From e1a840772d6d3008d8610c53c636e804d3ae0fda Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 19 Feb 2021 20:25:17 +0800 Subject: [PATCH 001/102] RTC: Refine TWCC and RTCP timer to 100ms. --- trunk/src/app/srs_app_rtc_conn.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 981a59c33..de6ec39c2 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -874,7 +874,7 @@ srs_error_t SrsRtcPlayStream::do_request_keyframe(uint32_t ssrc, SrsContextId ci SrsRtcPublishStream::SrsRtcPublishStream(SrsRtcConnection* session, const SrsContextId& cid) { - timer_ = new SrsHourGlass("publish", this, 20 * SRS_UTIME_MILLISECONDS); + timer_ = new SrsHourGlass("publish", this, 100 * SRS_UTIME_MILLISECONDS); cid_ = cid; is_started = false; @@ -985,11 +985,11 @@ srs_error_t SrsRtcPublishStream::start() return err; } - if ((err = timer_->tick(SRS_TICKID_TWCC, 40 * SRS_UTIME_MILLISECONDS)) != srs_success) { + if ((err = timer_->tick(SRS_TICKID_TWCC, 100 * SRS_UTIME_MILLISECONDS)) != srs_success) { return srs_error_wrap(err, "twcc tick"); } - if ((err = timer_->tick(SRS_TICKID_RTCP, 200 * SRS_UTIME_MILLISECONDS)) != srs_success) { + if ((err = timer_->tick(SRS_TICKID_RTCP, 1000 * SRS_UTIME_MILLISECONDS)) != srs_success) { return srs_error_wrap(err, "rtcp tick"); } @@ -1282,7 +1282,7 @@ srs_error_t SrsRtcPublishStream::send_periodic_twcc() if (last_time_send_twcc_) { uint32_t nn = 0; srs_utime_t duration = srs_duration(last_time_send_twcc_, srs_get_system_time()); - if (duration > 100 * SRS_UTIME_MILLISECONDS && twcc_epp_->can_print(0, &nn)) { + if (duration > 130 * SRS_UTIME_MILLISECONDS && twcc_epp_->can_print(0, &nn)) { srs_warn2(TAG_LARGE_TIMER, "twcc delay %dms > 100ms, count=%u/%u", srsu2msi(duration), nn, twcc_epp_->nn_count); } From 33f4e0207244095e3451d18a49c860a0f912940b Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 23 Feb 2021 17:10:27 +0800 Subject: [PATCH 002/102] RTC: Send NACK one by one to avoid packet freed by context switching --- trunk/src/app/srs_app_rtc_source.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index 5988119b5..e7d52da2d 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -2042,14 +2042,12 @@ srs_error_t SrsRtcSendTrack::on_recv_nack(const vector& lost_seqs, Srs statistic->nacks++; - vector resend_pkts; for(int i = 0; i < (int)lost_seqs.size(); ++i) { uint16_t seq = lost_seqs.at(i); SrsRtpPacket2* pkt = fetch_rtp_packet(seq); if (pkt == NULL) { continue; } - resend_pkts.push_back(pkt); info.nn_bytes += pkt->nb_bytes(); uint32_t nn = 0; @@ -2057,11 +2055,14 @@ srs_error_t SrsRtcSendTrack::on_recv_nack(const vector& lost_seqs, Srs srs_trace("RTC NACK ARQ seq=%u, ssrc=%u, ts=%u, count=%u/%u, %d bytes", pkt->header.get_sequence(), pkt->header.get_ssrc(), pkt->header.get_timestamp(), nn, nack_epp->nn_count, pkt->nb_bytes()); } - } - // By default, we send packets by sendmmsg. - if ((err = session_->do_send_packets(resend_pkts, info)) != srs_success) { - return srs_error_wrap(err, "raw send"); + vector resend_pkts; + resend_pkts.push_back(pkt); + + // By default, we send packets by sendmmsg. + if ((err = session_->do_send_packets(resend_pkts, info)) != srs_success) { + return srs_error_wrap(err, "raw send"); + } } return err; From 2f1e8a69118d9ee713b5f99f894e9678b4a6f301 Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 24 Feb 2021 11:39:30 +0800 Subject: [PATCH 003/102] RTC: Refine logs --- trunk/src/app/srs_app_rtc_api.cpp | 2 +- trunk/src/app/srs_app_rtc_conn.cpp | 6 +++--- trunk/src/app/srs_app_rtc_source.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_api.cpp b/trunk/src/app/srs_app_rtc_api.cpp index e1fa754ac..b35340b0c 100644 --- a/trunk/src/app/srs_app_rtc_api.cpp +++ b/trunk/src/app/srs_app_rtc_api.cpp @@ -786,7 +786,7 @@ srs_error_t SrsGoApiRtcNACK::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessa res->set("code", SrsJsonAny::integer(ERROR_SUCCESS)); if ((err = do_serve_http(w, r, res)) != srs_success) { - srs_warn("RTC NACK err %s", srs_error_desc(err).c_str()); + srs_warn("RTC: NACK err %s", srs_error_desc(err).c_str()); res->set("code", SrsJsonAny::integer(srs_error_code(err))); srs_freep(err); } diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index de6ec39c2..cd28f9824 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -768,7 +768,7 @@ srs_error_t SrsRtcPlayStream::on_rtcp_nack(SrsRtcpNack* rtcp) // If NACK disabled, print a log. if (!nack_enabled_) { vector sns = rtcp->get_lost_sns(); - srs_trace("RTC NACK ssrc=%u, seq=%s, ignored", ssrc, srs_join_vector_string(sns, ",").c_str()); + srs_trace("RTC: NACK ssrc=%u, seq=%s, ignored", ssrc, srs_join_vector_string(sns, ",").c_str()); return err; } @@ -1475,7 +1475,7 @@ void SrsRtcPublishStream::simulate_nack_drop(int nn) void SrsRtcPublishStream::simulate_drop_packet(SrsRtpHeader* h, int nn_bytes) { - srs_warn("RTC NACK simulator #%d drop seq=%u, ssrc=%u/%s, ts=%u, %d bytes", nn_simulate_nack_drop, + srs_warn("RTC: NACK simulator #%d drop seq=%u, ssrc=%u/%s, ts=%u, %d bytes", nn_simulate_nack_drop, h->get_sequence(), h->get_ssrc(), (get_video_track(h->get_ssrc())? "Video":"Audio"), h->get_timestamp(), nn_bytes); @@ -2478,7 +2478,7 @@ void SrsRtcConnection::simulate_nack_drop(int nn) void SrsRtcConnection::simulate_player_drop_packet(SrsRtpHeader* h, int nn_bytes) { - srs_warn("RTC NACK simulator #%d player drop seq=%u, ssrc=%u, ts=%u, %d bytes", nn_simulate_player_nack_drop, + srs_warn("RTC: NACK simulator #%d player drop seq=%u, ssrc=%u, ts=%u, %d bytes", nn_simulate_player_nack_drop, h->get_sequence(), h->get_ssrc(), h->get_timestamp(), nn_bytes); diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index e7d52da2d..5adb0c905 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -2052,7 +2052,7 @@ srs_error_t SrsRtcSendTrack::on_recv_nack(const vector& lost_seqs, Srs info.nn_bytes += pkt->nb_bytes(); uint32_t nn = 0; if (nack_epp->can_print(pkt->header.get_ssrc(), &nn)) { - srs_trace("RTC NACK ARQ seq=%u, ssrc=%u, ts=%u, count=%u/%u, %d bytes", pkt->header.get_sequence(), + srs_trace("RTC: NACK ARQ seq=%u, ssrc=%u, ts=%u, count=%u/%u, %d bytes", pkt->header.get_sequence(), pkt->header.get_ssrc(), pkt->header.get_timestamp(), nn, nack_epp->nn_count, pkt->nb_bytes()); } From 6c24f2e353559f3bb5d6eddc169881533b69af31 Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 24 Feb 2021 17:22:49 +0800 Subject: [PATCH 004/102] Refine logs --- trunk/src/app/srs_app_rtc_server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index f5f4dfe73..c83c0677e 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -666,7 +666,7 @@ srs_error_t SrsRtcServer::notify(int type, srs_utime_t interval, srs_utime_t tic _srs_pps_rnack->update(); _srs_pps_rnack2->update(); // TODO: FIXME: Show more data for RTC server. - srs_trace("RTC: Server conns=%u, pkts=%d, addrs=%d,%d, fid=%d,%d,%d, rtcp=%d,%d,%d, snk=%d,%d,%d,%d, rnk=%d,%d", + srs_trace("RTC: Server conns=%u, pkts=%d,%d,%d, fid=%d,%d,%d, rtcp=%d,%d,%d, snk=%d,%d,%d,%d, rnk=%d,%d", nn_rtc_conns, _srs_pps_pkts->r10s(), _srs_pps_addrs->r10s(), _srs_pps_fast_addrs->r10s(), _srs_pps_ids->r10s(), _srs_pps_fids->r10s(), _srs_pps_fids_level0->r10s(), From d92ceaca39cdd6c3e93aea5591049e6851dd8f83 Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 24 Feb 2021 17:33:20 +0800 Subject: [PATCH 005/102] RTC: Stat the detail of received packets --- trunk/src/app/srs_app_listener.cpp | 4 ++-- trunk/src/app/srs_app_rtc_server.cpp | 18 ++++++++++++++---- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/trunk/src/app/srs_app_listener.cpp b/trunk/src/app/srs_app_listener.cpp index a2aaa7407..c6cb51d6e 100755 --- a/trunk/src/app/srs_app_listener.cpp +++ b/trunk/src/app/srs_app_listener.cpp @@ -45,7 +45,7 @@ using namespace std; #include -SrsPps* _srs_pps_pkts = new SrsPps(_srs_clock); +SrsPps* _srs_pps_rpkts = new SrsPps(_srs_clock); SrsPps* _srs_pps_addrs = new SrsPps(_srs_clock); SrsPps* _srs_pps_fast_addrs = new SrsPps(_srs_clock); @@ -343,7 +343,7 @@ int SrsUdpMuxSocket::recvfrom(srs_utime_t timeout) address_changed_ = true; // Update the stat. - ++_srs_pps_pkts->sugar; + ++_srs_pps_rpkts->sugar; return nread; } diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index c83c0677e..8a2c0a324 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -45,7 +45,10 @@ using namespace std; #include #include -extern SrsPps* _srs_pps_pkts; +extern SrsPps* _srs_pps_rpkts; +SrsPps* _srs_pps_rstuns = new SrsPps(_srs_clock); +SrsPps* _srs_pps_rrtps = new SrsPps(_srs_clock); +SrsPps* _srs_pps_rrtcps = new SrsPps(_srs_clock); extern SrsPps* _srs_pps_addrs; extern SrsPps* _srs_pps_fast_addrs; @@ -357,6 +360,7 @@ srs_error_t SrsRtcServer::on_udp_packet(SrsUdpMuxSocket* skt) // For STUN, the peer address may change. if (!is_rtp_or_rtcp && srs_is_stun((uint8_t*)data, size)) { + ++_srs_pps_rstuns->sugar; string peer_id = skt->peer_id(); SrsStunPacket ping; @@ -390,6 +394,8 @@ srs_error_t SrsRtcServer::on_udp_packet(SrsUdpMuxSocket* skt) // Note that we don't(except error) switch to the context of session, for performance issue. if (is_rtp_or_rtcp && !is_rtcp) { + ++_srs_pps_rrtps->sugar; + err = session->on_rtp(data, size); if (err != srs_success) { session->switch_to_context(); @@ -399,9 +405,13 @@ srs_error_t SrsRtcServer::on_udp_packet(SrsUdpMuxSocket* skt) session->switch_to_context(); if (is_rtp_or_rtcp && is_rtcp) { + ++_srs_pps_rrtcps->sugar; + return session->on_rtcp(data, size); } if (srs_is_dtls((uint8_t*)data, size)) { + ++_srs_pps_rstuns->sugar; + return session->on_dtls(data, size); } return srs_error_new(ERROR_RTC_UDP, "unknown packet"); @@ -659,16 +669,16 @@ srs_error_t SrsRtcServer::notify(int type, srs_utime_t interval, srs_utime_t tic } // Update the pps stat for UDP socket and adddresses. - _srs_pps_pkts->update(); _srs_pps_addrs->update(); _srs_pps_fast_addrs->update(); + _srs_pps_rpkts->update(); _srs_pps_rstuns->update(); _srs_pps_rrtps->update(); _srs_pps_rrtcps->update(); _srs_pps_addrs->update(); _srs_pps_fast_addrs->update(); _srs_pps_ids->update(); _srs_pps_fids->update(); _srs_pps_fids_level0->update(); _srs_pps_pli->update(); _srs_pps_twcc->update(); _srs_pps_rr->update(); _srs_pps_snack->update(); _srs_pps_snack2->update(); _srs_pps_sanack->update(); _srs_pps_svnack->update(); _srs_pps_rnack->update(); _srs_pps_rnack2->update(); // TODO: FIXME: Show more data for RTC server. - srs_trace("RTC: Server conns=%u, pkts=%d,%d,%d, fid=%d,%d,%d, rtcp=%d,%d,%d, snk=%d,%d,%d,%d, rnk=%d,%d", + srs_trace("RTC: Server conns=%u, rpkts=%d,%d,%d,%d,%d,%d, fid=%d,%d,%d, rtcp=%d,%d,%d, snk=%d,%d,%d,%d, rnk=%d,%d", nn_rtc_conns, - _srs_pps_pkts->r10s(), _srs_pps_addrs->r10s(), _srs_pps_fast_addrs->r10s(), + _srs_pps_rpkts->r10s(), _srs_pps_rstuns->r10s(), _srs_pps_rrtps->r10s(), _srs_pps_rrtcps->r10s(), _srs_pps_addrs->r10s(), _srs_pps_fast_addrs->r10s(), _srs_pps_ids->r10s(), _srs_pps_fids->r10s(), _srs_pps_fids_level0->r10s(), _srs_pps_pli->r10s(), _srs_pps_twcc->r10s(), _srs_pps_rr->r10s(), _srs_pps_snack->r10s(), _srs_pps_snack2->r10s(), _srs_pps_sanack->r10s(), _srs_pps_svnack->r10s(), From 09bd1b9faad4b5aad43d4e921fed20373e356e55 Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 24 Feb 2021 17:55:27 +0800 Subject: [PATCH 006/102] RTC Stat the detail of send packets --- trunk/src/app/srs_app_listener.cpp | 4 ++++ trunk/src/app/srs_app_rtc_conn.cpp | 22 ++++++++++++++++++++++ trunk/src/app/srs_app_rtc_server.cpp | 14 +++++++++++--- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/trunk/src/app/srs_app_listener.cpp b/trunk/src/app/srs_app_listener.cpp index c6cb51d6e..ce335ce6d 100755 --- a/trunk/src/app/srs_app_listener.cpp +++ b/trunk/src/app/srs_app_listener.cpp @@ -49,6 +49,8 @@ SrsPps* _srs_pps_rpkts = new SrsPps(_srs_clock); SrsPps* _srs_pps_addrs = new SrsPps(_srs_clock); SrsPps* _srs_pps_fast_addrs = new SrsPps(_srs_clock); +SrsPps* _srs_pps_spkts = new SrsPps(_srs_clock); + // set the max packet size. #define SRS_UDP_MAX_PACKET_SIZE 65535 @@ -352,6 +354,8 @@ srs_error_t SrsUdpMuxSocket::sendto(void* data, int size, srs_utime_t timeout) { srs_error_t err = srs_success; + ++_srs_pps_spkts->sugar; + int nb_write = srs_sendto(lfd, data, size, (sockaddr*)&from, fromlen, timeout); if (nb_write <= 0) { diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index cd28f9824..dffd10b6e 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -60,6 +60,11 @@ using namespace std; #include +SrsPps* _srs_pps_sstuns = new SrsPps(_srs_clock); +SrsPps* _srs_pps_stwcc = new SrsPps(_srs_clock); +SrsPps* _srs_pps_srtcps = new SrsPps(_srs_clock); +SrsPps* _srs_pps_srtps = new SrsPps(_srs_clock); + SrsPps* _srs_pps_pli = new SrsPps(_srs_clock); SrsPps* _srs_pps_twcc = new SrsPps(_srs_clock); SrsPps* _srs_pps_rr = new SrsPps(_srs_clock); @@ -118,6 +123,8 @@ srs_error_t SrsSecurityTransport::write_dtls_data(void* data, int size) return err; } + ++_srs_pps_sstuns->sugar; + if ((err = session_->sendonly_skt->sendto(data, size, 0)) != srs_success) { return srs_error_wrap(err, "send dtls packet"); } @@ -1293,6 +1300,8 @@ srs_error_t SrsRtcPublishStream::send_periodic_twcc() return err; } + ++_srs_pps_stwcc->sugar; + char pkt[kRtcpPacketSize]; SrsBuffer *buffer = new SrsBuffer(pkt, sizeof(pkt)); SrsAutoFree(SrsBuffer, buffer); @@ -2298,6 +2307,8 @@ srs_error_t SrsRtcConnection::send_rtcp(char *data, int nb_data) { srs_error_t err = srs_success; + ++_srs_pps_srtcps->sugar; + int nb_buf = nb_data; if ((err = transport_->protect_rtcp(data, &nb_buf)) != srs_success) { return srs_error_wrap(err, "protect rtcp"); @@ -2324,6 +2335,7 @@ void SrsRtcConnection::check_send_nacks(SrsRtpNackForReceiver* nack, uint32_t ss } ++_srs_pps_snack2->sugar; + ++_srs_pps_srtcps->sugar; char buf[kRtcpPacketSize]; SrsBuffer stream(buf, sizeof(buf)); @@ -2343,6 +2355,8 @@ srs_error_t SrsRtcConnection::send_rtcp_rr(uint32_t ssrc, SrsRtpRingBuffer* rtp_ { srs_error_t err = srs_success; + ++_srs_pps_srtcps->sugar; + // @see https://tools.ietf.org/html/rfc3550#section-6.4.2 char buf[kRtpPacketSize]; SrsBuffer stream(buf, sizeof(buf)); @@ -2388,6 +2402,8 @@ srs_error_t SrsRtcConnection::send_rtcp_xr_rrtr(uint32_t ssrc) { srs_error_t err = srs_success; + ++_srs_pps_srtcps->sugar; + /* @see: http://www.rfc-editor.org/rfc/rfc3611.html#section-2 @@ -2440,6 +2456,8 @@ srs_error_t SrsRtcConnection::send_rtcp_fb_pli(uint32_t ssrc, const SrsContextId { srs_error_t err = srs_success; + ++_srs_pps_srtcps->sugar; + char buf[kRtpPacketSize]; SrsBuffer stream(buf, sizeof(buf)); stream.write_1bytes(0x81); @@ -2532,6 +2550,8 @@ srs_error_t SrsRtcConnection::do_send_packets(const std::vector& continue; } + ++_srs_pps_srtps->sugar; + // TODO: FIXME: Handle error. sendonly_skt->sendto(iov->iov_base, iov->iov_len, 0); @@ -2578,6 +2598,8 @@ srs_error_t SrsRtcConnection::on_binding_request(SrsStunPacket* r) { srs_error_t err = srs_success; + ++_srs_pps_sstuns->sugar; + bool strict_check = _srs_config->get_rtc_stun_strict_check(req->vhost); if (strict_check && r->get_ice_controlled()) { // @see: https://tools.ietf.org/html/draft-ietf-ice-rfc5245bis-00#section-6.1.3.1 diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index 8a2c0a324..49782d401 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -52,6 +52,12 @@ SrsPps* _srs_pps_rrtcps = new SrsPps(_srs_clock); extern SrsPps* _srs_pps_addrs; extern SrsPps* _srs_pps_fast_addrs; +extern SrsPps* _srs_pps_spkts; +extern SrsPps* _srs_pps_sstuns; +extern SrsPps* _srs_pps_stwcc; +extern SrsPps* _srs_pps_srtcps; +extern SrsPps* _srs_pps_srtps; + extern SrsPps* _srs_pps_ids; extern SrsPps* _srs_pps_fids; extern SrsPps* _srs_pps_fids_level0; @@ -669,16 +675,18 @@ srs_error_t SrsRtcServer::notify(int type, srs_utime_t interval, srs_utime_t tic } // Update the pps stat for UDP socket and adddresses. - _srs_pps_rpkts->update(); _srs_pps_rstuns->update(); _srs_pps_rrtps->update(); _srs_pps_rrtcps->update(); _srs_pps_addrs->update(); _srs_pps_fast_addrs->update(); + _srs_pps_rpkts->update(); _srs_pps_rrtps->update(); _srs_pps_rstuns->update(); _srs_pps_rrtcps->update(); _srs_pps_addrs->update(); _srs_pps_fast_addrs->update(); + _srs_pps_spkts->update(); _srs_pps_srtps->update(); _srs_pps_sstuns->update(); _srs_pps_stwcc->update(); _srs_pps_srtcps->update(); _srs_pps_ids->update(); _srs_pps_fids->update(); _srs_pps_fids_level0->update(); _srs_pps_pli->update(); _srs_pps_twcc->update(); _srs_pps_rr->update(); _srs_pps_snack->update(); _srs_pps_snack2->update(); _srs_pps_sanack->update(); _srs_pps_svnack->update(); _srs_pps_rnack->update(); _srs_pps_rnack2->update(); // TODO: FIXME: Show more data for RTC server. - srs_trace("RTC: Server conns=%u, rpkts=%d,%d,%d,%d,%d,%d, fid=%d,%d,%d, rtcp=%d,%d,%d, snk=%d,%d,%d,%d, rnk=%d,%d", + srs_trace("RTC: Server conns=%u, rpkts=%d,%d,%d,%d,%d,%d, spkts=%d,%d,%d,%d,%d, fid=%d,%d,%d, rtcp=%d,%d,%d, snk=%d,%d,%d,%d, rnk=%d,%d", nn_rtc_conns, - _srs_pps_rpkts->r10s(), _srs_pps_rstuns->r10s(), _srs_pps_rrtps->r10s(), _srs_pps_rrtcps->r10s(), _srs_pps_addrs->r10s(), _srs_pps_fast_addrs->r10s(), + _srs_pps_rpkts->r10s(), _srs_pps_rrtps->r10s(), _srs_pps_rstuns->r10s(), _srs_pps_rrtcps->r10s(), _srs_pps_addrs->r10s(), _srs_pps_fast_addrs->r10s(), + _srs_pps_spkts->r10s(), _srs_pps_srtps->r10s(), _srs_pps_sstuns->r10s(), _srs_pps_stwcc->r10s(), _srs_pps_srtcps->r10s(), _srs_pps_ids->r10s(), _srs_pps_fids->r10s(), _srs_pps_fids_level0->r10s(), _srs_pps_pli->r10s(), _srs_pps_twcc->r10s(), _srs_pps_rr->r10s(), _srs_pps_snack->r10s(), _srs_pps_snack2->r10s(), _srs_pps_sanack->r10s(), _srs_pps_svnack->r10s(), From b9352eac0c3d16e6770ab97c6afa8cfb0b2bb018 Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 24 Feb 2021 18:39:07 +0800 Subject: [PATCH 007/102] RTC: Refine stat logs --- trunk/src/app/srs_app_rtc_conn.cpp | 3 +-- trunk/src/app/srs_app_rtc_server.cpp | 23 ++++++++++++----------- trunk/src/app/srs_app_rtc_source.cpp | 4 ++++ 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index dffd10b6e..1b3329fe7 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -61,7 +61,6 @@ using namespace std; #include SrsPps* _srs_pps_sstuns = new SrsPps(_srs_clock); -SrsPps* _srs_pps_stwcc = new SrsPps(_srs_clock); SrsPps* _srs_pps_srtcps = new SrsPps(_srs_clock); SrsPps* _srs_pps_srtps = new SrsPps(_srs_clock); @@ -1300,7 +1299,7 @@ srs_error_t SrsRtcPublishStream::send_periodic_twcc() return err; } - ++_srs_pps_stwcc->sugar; + ++_srs_pps_srtcps->sugar; char pkt[kRtcpPacketSize]; SrsBuffer *buffer = new SrsBuffer(pkt, sizeof(pkt)); diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index 49782d401..67698172f 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -54,7 +54,6 @@ extern SrsPps* _srs_pps_fast_addrs; extern SrsPps* _srs_pps_spkts; extern SrsPps* _srs_pps_sstuns; -extern SrsPps* _srs_pps_stwcc; extern SrsPps* _srs_pps_srtcps; extern SrsPps* _srs_pps_srtps; @@ -73,6 +72,8 @@ extern SrsPps* _srs_pps_svnack; extern SrsPps* _srs_pps_rnack; extern SrsPps* _srs_pps_rnack2; +extern SrsPps* _srs_pps_rhnack; +extern SrsPps* _srs_pps_rmnack; SrsRtcBlackhole::SrsRtcBlackhole() { @@ -675,22 +676,22 @@ srs_error_t SrsRtcServer::notify(int type, srs_utime_t interval, srs_utime_t tic } // Update the pps stat for UDP socket and adddresses. - _srs_pps_rpkts->update(); _srs_pps_rrtps->update(); _srs_pps_rstuns->update(); _srs_pps_rrtcps->update(); _srs_pps_addrs->update(); _srs_pps_fast_addrs->update(); - _srs_pps_spkts->update(); _srs_pps_srtps->update(); _srs_pps_sstuns->update(); _srs_pps_stwcc->update(); _srs_pps_srtcps->update(); - _srs_pps_ids->update(); _srs_pps_fids->update(); _srs_pps_fids_level0->update(); + _srs_pps_rpkts->update(); _srs_pps_rrtps->update(); _srs_pps_rstuns->update(); _srs_pps_rrtcps->update(); + _srs_pps_spkts->update(); _srs_pps_srtps->update(); _srs_pps_sstuns->update(); _srs_pps_srtcps->update(); _srs_pps_pli->update(); _srs_pps_twcc->update(); _srs_pps_rr->update(); _srs_pps_snack->update(); _srs_pps_snack2->update(); _srs_pps_sanack->update(); _srs_pps_svnack->update(); - _srs_pps_rnack->update(); _srs_pps_rnack2->update(); + _srs_pps_rnack->update(); _srs_pps_rnack2->update(); _srs_pps_rhnack->update(); _srs_pps_rmnack->update(); + _srs_pps_ids->update(); _srs_pps_fids->update(); _srs_pps_fids_level0->update(); _srs_pps_addrs->update(); _srs_pps_fast_addrs->update(); // TODO: FIXME: Show more data for RTC server. - srs_trace("RTC: Server conns=%u, rpkts=%d,%d,%d,%d,%d,%d, spkts=%d,%d,%d,%d,%d, fid=%d,%d,%d, rtcp=%d,%d,%d, snk=%d,%d,%d,%d, rnk=%d,%d", + srs_trace("RTC: Server conns=%u, rpkts=%d,%d,%d,%d, spkts=%d,%d,%d,%d, rtcp=%d,%d,%d, snk=%d,%d,%d,%d, rnk=%d,%d,%d,%d, fid=%d,%d,%d,%d,%d", nn_rtc_conns, - _srs_pps_rpkts->r10s(), _srs_pps_rrtps->r10s(), _srs_pps_rstuns->r10s(), _srs_pps_rrtcps->r10s(), _srs_pps_addrs->r10s(), _srs_pps_fast_addrs->r10s(), - _srs_pps_spkts->r10s(), _srs_pps_srtps->r10s(), _srs_pps_sstuns->r10s(), _srs_pps_stwcc->r10s(), _srs_pps_srtcps->r10s(), - _srs_pps_ids->r10s(), _srs_pps_fids->r10s(), _srs_pps_fids_level0->r10s(), + _srs_pps_rpkts->r10s(), _srs_pps_rrtps->r10s(), _srs_pps_rstuns->r10s(), _srs_pps_rrtcps->r10s(), + _srs_pps_spkts->r10s(), _srs_pps_srtps->r10s(), _srs_pps_sstuns->r10s(), _srs_pps_srtcps->r10s(), _srs_pps_pli->r10s(), _srs_pps_twcc->r10s(), _srs_pps_rr->r10s(), - _srs_pps_snack->r10s(), _srs_pps_snack2->r10s(), _srs_pps_sanack->r10s(), _srs_pps_svnack->r10s(), - _srs_pps_rnack->r10s(), _srs_pps_rnack2->r10s() + _srs_pps_snack->r10s(), _srs_pps_sanack->r10s(), _srs_pps_svnack->r10s(), _srs_pps_snack2->r10s(), + _srs_pps_rnack->r10s(), _srs_pps_rnack2->r10s(), _srs_pps_rhnack->r10s(), _srs_pps_rmnack->r10s(), + _srs_pps_ids->r10s(), _srs_pps_fids->r10s(), _srs_pps_fids_level0->r10s(), _srs_pps_addrs->r10s(), _srs_pps_fast_addrs->r10s() ); return err; diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index 5adb0c905..eb5d30f20 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -58,6 +58,8 @@ SrsPps* _srs_pps_svnack = new SrsPps(_srs_clock); SrsPps* _srs_pps_rnack = new SrsPps(_srs_clock); SrsPps* _srs_pps_rnack2 = new SrsPps(_srs_clock); +SrsPps* _srs_pps_rhnack = new SrsPps(_srs_clock); +SrsPps* _srs_pps_rmnack = new SrsPps(_srs_clock); // Firefox defaults as 109, Chrome is 111. const int kAudioPayloadType = 111; @@ -2002,8 +2004,10 @@ SrsRtpPacket2* SrsRtcSendTrack::fetch_rtp_packet(uint16_t seq) // For NACK, it sequence must match exactly, or it cause SRTP fail. // Return packet only when sequence is equal. if (pkt->header.get_sequence() == seq) { + ++_srs_pps_rhnack->sugar; return pkt; } + ++_srs_pps_rmnack->sugar; // Ignore if sequence not match. uint32_t nn = 0; From 9ab12f9f2f45966b0d699a5d18e4e44effff8430 Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 24 Feb 2021 18:53:49 +0800 Subject: [PATCH 008/102] RTC: Stat the drop of UDP packets. --- trunk/src/app/srs_app_rtc_server.cpp | 6 +- trunk/src/app/srs_app_server.cpp | 5 ++ trunk/src/app/srs_app_utility.cpp | 88 ++++++++++++++++++++++++++++ trunk/src/app/srs_app_utility.hpp | 42 +++++++++++++ 4 files changed, 140 insertions(+), 1 deletion(-) diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index 67698172f..1a8c9dbf7 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -675,6 +675,9 @@ srs_error_t SrsRtcServer::notify(int type, srs_utime_t interval, srs_utime_t tic return err; } + // Show udp snmp statistic for RTC server. + SrsSnmpUdpStat* s = srs_get_udp_snmp_stat(); + // Update the pps stat for UDP socket and adddresses. _srs_pps_rpkts->update(); _srs_pps_rrtps->update(); _srs_pps_rstuns->update(); _srs_pps_rrtcps->update(); _srs_pps_spkts->update(); _srs_pps_srtps->update(); _srs_pps_sstuns->update(); _srs_pps_srtcps->update(); @@ -684,13 +687,14 @@ srs_error_t SrsRtcServer::notify(int type, srs_utime_t interval, srs_utime_t tic _srs_pps_ids->update(); _srs_pps_fids->update(); _srs_pps_fids_level0->update(); _srs_pps_addrs->update(); _srs_pps_fast_addrs->update(); // TODO: FIXME: Show more data for RTC server. - srs_trace("RTC: Server conns=%u, rpkts=%d,%d,%d,%d, spkts=%d,%d,%d,%d, rtcp=%d,%d,%d, snk=%d,%d,%d,%d, rnk=%d,%d,%d,%d, fid=%d,%d,%d,%d,%d", + srs_trace("RTC: Server conns=%u, rpkts=%d,%d,%d,%d, spkts=%d,%d,%d,%d, rtcp=%d,%d,%d, snk=%d,%d,%d,%d, rnk=%d,%d,%d,%d, drop=%d,%d, fid=%d,%d,%d,%d,%d", nn_rtc_conns, _srs_pps_rpkts->r10s(), _srs_pps_rrtps->r10s(), _srs_pps_rstuns->r10s(), _srs_pps_rrtcps->r10s(), _srs_pps_spkts->r10s(), _srs_pps_srtps->r10s(), _srs_pps_sstuns->r10s(), _srs_pps_srtcps->r10s(), _srs_pps_pli->r10s(), _srs_pps_twcc->r10s(), _srs_pps_rr->r10s(), _srs_pps_snack->r10s(), _srs_pps_sanack->r10s(), _srs_pps_svnack->r10s(), _srs_pps_snack2->r10s(), _srs_pps_rnack->r10s(), _srs_pps_rnack2->r10s(), _srs_pps_rhnack->r10s(), _srs_pps_rmnack->r10s(), + s->rcv_buf_errors_delta, s->snd_buf_errors_delta, _srs_pps_ids->r10s(), _srs_pps_fids->r10s(), _srs_pps_fids_level0->r10s(), _srs_pps_addrs->r10s(), _srs_pps_fast_addrs->r10s() ); diff --git a/trunk/src/app/srs_app_server.cpp b/trunk/src/app/srs_app_server.cpp index 39141bf55..cf3f553d6 100644 --- a/trunk/src/app/srs_app_server.cpp +++ b/trunk/src/app/srs_app_server.cpp @@ -1280,6 +1280,10 @@ srs_error_t SrsServer::setup_ticks() if ((err = timer_->tick(8, 3 * SRS_UTIME_SECONDS)) != srs_success) { return srs_error_wrap(err, "tick"); } + + if ((err = timer_->tick(10, 9 * SRS_UTIME_SECONDS)) != srs_success) { + return srs_error_wrap(err, "tick"); + } } if (_srs_config->get_heartbeat_enabled()) { @@ -1308,6 +1312,7 @@ srs_error_t SrsServer::notify(int event, srs_utime_t interval, srs_utime_t tick) case 7: srs_update_network_devices(); break; case 8: resample_kbps(); break; case 9: http_heartbeat->heartbeat(); break; + case 10: srs_update_udp_snmp_statistic(); break; } return err; diff --git a/trunk/src/app/srs_app_utility.cpp b/trunk/src/app/srs_app_utility.cpp index bde16dc83..a7251cf22 100644 --- a/trunk/src/app/srs_app_utility.cpp +++ b/trunk/src/app/srs_app_utility.cpp @@ -851,6 +851,94 @@ void srs_update_platform_info() r.ok = true; } +SrsSnmpUdpStat::SrsSnmpUdpStat() +{ + ok = false; + + in_datagrams = 0; + no_ports = 0; + in_errors = 0; + out_datagrams = 0; + rcv_buf_errors = 0; + snd_buf_errors = 0; + in_csum_errors = 0; + + rcv_buf_errors_delta = 0; + snd_buf_errors_delta = 0; +} + +SrsSnmpUdpStat::~SrsSnmpUdpStat() +{ +} + +static SrsSnmpUdpStat _srs_snmp_udp_stat; + +bool get_udp_snmp_statistic(SrsSnmpUdpStat& r) +{ +#ifndef SRS_OSX + if (true) { + FILE* f = fopen("/proc/net/snmp", "r"); + if (f == NULL) { + srs_warn("open proc network snmp failed, ignore"); + return false; + } + + // ignore title. + static char buf[1024]; + fgets(buf, sizeof(buf), f); + + while (fgets(buf, sizeof(buf), f)) { + // udp stat title + if (strncmp(buf, "Udp: ", 5) == 0) { + // read tcp stat data + if (!fgets(buf, sizeof(buf), f)) { + break; + } + // parse tcp stat data + if (strncmp(buf, "Udp: ", 5) == 0) { + sscanf(buf + 5, "%llu %llu %llu %llu %llu %llu %llu\n", + &r.in_datagrams, + &r.no_ports, + &r.in_errors, + &r.out_datagrams, + &r.rcv_buf_errors, + &r.snd_buf_errors, + &r.in_csum_errors); + } + } + } + fclose(f); + } +#endif + r.ok = true; + + return true; +} + +SrsSnmpUdpStat* srs_get_udp_snmp_stat() +{ + return &_srs_snmp_udp_stat; +} + +void srs_update_udp_snmp_statistic() +{ + SrsSnmpUdpStat r; + if (!get_udp_snmp_statistic(r)) { + return; + } + + SrsSnmpUdpStat& o = _srs_snmp_udp_stat; + if (o.rcv_buf_errors > 0) { + r.rcv_buf_errors_delta = int(r.rcv_buf_errors - o.rcv_buf_errors); + } + + if (o.snd_buf_errors > 0) { + r.snd_buf_errors_delta = int(r.snd_buf_errors - o.snd_buf_errors); + } + + _srs_snmp_udp_stat = r; +} + SrsNetworkDevices::SrsNetworkDevices() { ok = false; diff --git a/trunk/src/app/srs_app_utility.hpp b/trunk/src/app/srs_app_utility.hpp index 63bfef577..117f7e67d 100644 --- a/trunk/src/app/srs_app_utility.hpp +++ b/trunk/src/app/srs_app_utility.hpp @@ -547,6 +547,48 @@ extern SrsPlatformInfo* srs_get_platform_info(); // The daemon st-thread will update it. extern void srs_update_platform_info(); +class SrsSnmpUdpStat +{ +public: + // Whether the data is ok. + bool ok; + // send and recv buffer error delta + int rcv_buf_errors_delta; + int snd_buf_errors_delta; + +public: + // @see: cat /proc/uptimecat /proc/net/snmp|grep 'Udp:' + // @see: https://blog.packagecloud.io/eng/2017/02/06/monitoring-tuning-linux-networking-stack-sending-data/#procnetsnmp + // InDatagrams: incremented when recvmsg was used by a userland program to read datagram. + // also incremented when a UDP packet is encapsulated and sent back for processing. + unsigned long long in_datagrams; + // NoPorts: incremented when UDP packets arrive destined for a port where no program is listening. + unsigned long long no_ports; + // InErrors: incremented in several cases: no memory in the receive queue, when a bad checksum is seen, + // and if sk_add_backlog fails to add the datagram. + unsigned long long in_errors; + // OutDatagrams: incremented when a UDP packet is handed down without error to the IP protocol layer to be sent. + unsigned long long out_datagrams; + // RcvbufErrors: incremented when sock_queue_rcv_skb reports that no memory is available; + // this happens if sk->sk_rmem_alloc is greater than or equal to sk->sk_rcvbuf. + unsigned long long rcv_buf_errors; + // SndbufErrors: incremented if the IP protocol layer reported an error when trying to send the packet + // and no error queue has been setup. also incremented if no send queue space or kernel memory are available. + unsigned long long snd_buf_errors; + // InCsumErrors: incremented when a UDP checksum failure is detected. + // Note that in all cases I could find, InCsumErrors is incremented at the same time as InErrors. + // Thus, InErrors - InCsumErros should yield the count of memory related errors on the receive side. + unsigned long long in_csum_errors; +public: + SrsSnmpUdpStat(); + ~SrsSnmpUdpStat(); +}; + +// Get SNMP udp statistic, use cache to avoid performance problem. +extern SrsSnmpUdpStat* srs_get_udp_snmp_stat(); +// The daemon st-thread will update it. +void srs_update_udp_snmp_statistic(); + // The network device summary for each network device, for example, eth0, eth1, ethN class SrsNetworkDevices { From 5ff9977572e7f82572432388324c2d62e3ad78b8 Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 24 Feb 2021 20:56:17 +0800 Subject: [PATCH 009/102] Perf: Improve fast find for pithy print --- trunk/src/app/srs_app_pithy_print.cpp | 11 +++++++++-- trunk/src/app/srs_app_pithy_print.hpp | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/trunk/src/app/srs_app_pithy_print.cpp b/trunk/src/app/srs_app_pithy_print.cpp index f408d08c5..ebf70def8 100644 --- a/trunk/src/app/srs_app_pithy_print.cpp +++ b/trunk/src/app/srs_app_pithy_print.cpp @@ -171,6 +171,7 @@ static SrsStageManager* _srs_stages = new SrsStageManager(); SrsPithyPrint::SrsPithyPrint(int _stage_id) { stage_id = _stage_id; + cache_ = NULL; client_id = enter_stage(); previous_tick = srs_get_system_time(); _age = 0; @@ -308,7 +309,10 @@ void SrsPithyPrint::leave_stage() void SrsPithyPrint::elapse() { - SrsStageInfo* stage = _srs_stages->fetch_or_create(stage_id); + SrsStageInfo* stage = cache_; + if (!stage) { + stage = cache_ = _srs_stages->fetch_or_create(stage_id); + } srs_assert(stage != NULL); srs_utime_t diff = srs_get_system_time() - previous_tick; @@ -321,7 +325,10 @@ void SrsPithyPrint::elapse() bool SrsPithyPrint::can_print() { - SrsStageInfo* stage = _srs_stages->fetch_or_create(stage_id); + SrsStageInfo* stage = cache_; + if (!stage) { + stage = cache_ = _srs_stages->fetch_or_create(stage_id); + } srs_assert(stage != NULL); return stage->can_print(); diff --git a/trunk/src/app/srs_app_pithy_print.hpp b/trunk/src/app/srs_app_pithy_print.hpp index 0fa3b6da2..bc966db98 100644 --- a/trunk/src/app/srs_app_pithy_print.hpp +++ b/trunk/src/app/srs_app_pithy_print.hpp @@ -111,6 +111,7 @@ class SrsPithyPrint { private: int client_id; + SrsStageInfo* cache_; int stage_id; srs_utime_t _age; srs_utime_t previous_tick; From df6e47ebfc6f12b43d8f9affde8e79b7031213df Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 25 Feb 2021 12:32:58 +0800 Subject: [PATCH 010/102] RTC: Refine stat for RTC server --- trunk/src/app/srs_app_rtc_server.cpp | 68 ++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 18 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index 1a8c9dbf7..455696cce 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -674,28 +674,60 @@ srs_error_t SrsRtcServer::notify(int type, srs_utime_t interval, srs_utime_t tic if (!nn_rtc_conns) { return err; } + static char buf[128]; - // Show udp snmp statistic for RTC server. - SrsSnmpUdpStat* s = srs_get_udp_snmp_stat(); - - // Update the pps stat for UDP socket and adddresses. + string rpkts_desc; _srs_pps_rpkts->update(); _srs_pps_rrtps->update(); _srs_pps_rstuns->update(); _srs_pps_rrtcps->update(); - _srs_pps_spkts->update(); _srs_pps_srtps->update(); _srs_pps_sstuns->update(); _srs_pps_srtcps->update(); - _srs_pps_pli->update(); _srs_pps_twcc->update(); _srs_pps_rr->update(); - _srs_pps_snack->update(); _srs_pps_snack2->update(); _srs_pps_sanack->update(); _srs_pps_svnack->update(); - _srs_pps_rnack->update(); _srs_pps_rnack2->update(); _srs_pps_rhnack->update(); _srs_pps_rmnack->update(); - _srs_pps_ids->update(); _srs_pps_fids->update(); _srs_pps_fids_level0->update(); _srs_pps_addrs->update(); _srs_pps_fast_addrs->update(); + if (_srs_pps_rpkts->r10s() || _srs_pps_rrtps->r10s() || _srs_pps_rstuns->r10s() || _srs_pps_rrtcps->r10s()) { + snprintf(buf, sizeof(buf), ", rpkts=%d,%d,%d,%d", _srs_pps_rpkts->r10s(), _srs_pps_rrtps->r10s(), _srs_pps_rstuns->r10s(), _srs_pps_rrtcps->r10s()); + rpkts_desc = buf; + } - // TODO: FIXME: Show more data for RTC server. - srs_trace("RTC: Server conns=%u, rpkts=%d,%d,%d,%d, spkts=%d,%d,%d,%d, rtcp=%d,%d,%d, snk=%d,%d,%d,%d, rnk=%d,%d,%d,%d, drop=%d,%d, fid=%d,%d,%d,%d,%d", + string spkts_desc; + _srs_pps_spkts->update(); _srs_pps_srtps->update(); _srs_pps_sstuns->update(); _srs_pps_srtcps->update(); + if (_srs_pps_spkts->r10s() || _srs_pps_srtps->r10s() || _srs_pps_sstuns->r10s() || _srs_pps_srtcps->r10s()) { + snprintf(buf, sizeof(buf), ", spkts=%d,%d,%d,%d", _srs_pps_spkts->r10s(), _srs_pps_srtps->r10s(), _srs_pps_sstuns->r10s(), _srs_pps_srtcps->r10s()); + spkts_desc = buf; + } + + string rtcp_desc; + _srs_pps_pli->update(); _srs_pps_twcc->update(); _srs_pps_rr->update(); + if (_srs_pps_pli->r10s() || _srs_pps_twcc->r10s() || _srs_pps_rr->r10s()) { + snprintf(buf, sizeof(buf), ", rtcp=%d,%d,%d", _srs_pps_pli->r10s(), _srs_pps_twcc->r10s(), _srs_pps_rr->r10s()); + rtcp_desc = buf; + } + + string snk_desc; + _srs_pps_snack->update(); _srs_pps_snack2->update(); _srs_pps_sanack->update(); _srs_pps_svnack->update(); + if (_srs_pps_snack->r10s() || _srs_pps_sanack->r10s() || _srs_pps_svnack->r10s() || _srs_pps_snack2->r10s()) { + snprintf(buf, sizeof(buf), ", snk=%d,%d,%d,%d", _srs_pps_snack->r10s(), _srs_pps_sanack->r10s(), _srs_pps_svnack->r10s(), _srs_pps_snack2->r10s()); + snk_desc = buf; + } + + string rnk_desc; + _srs_pps_rnack->update(); _srs_pps_rnack2->update(); _srs_pps_rhnack->update(); _srs_pps_rmnack->update(); + if (_srs_pps_rnack->r10s() || _srs_pps_rnack2->r10s() || _srs_pps_rhnack->r10s() || _srs_pps_rmnack->r10s()) { + snprintf(buf, sizeof(buf), ", rnk=%d,%d,%d,%d", _srs_pps_rnack->r10s(), _srs_pps_rnack2->r10s(), _srs_pps_rhnack->r10s(), _srs_pps_rmnack->r10s()); + rnk_desc = buf; + } + + string drop_desc; + SrsSnmpUdpStat* s = srs_get_udp_snmp_stat(); + if (s->rcv_buf_errors_delta || s->snd_buf_errors_delta) { + snprintf(buf, sizeof(buf), ", drop=%d,%d", s->rcv_buf_errors_delta, s->snd_buf_errors_delta); + drop_desc = buf; + } + + string fid_desc; + _srs_pps_ids->update(); _srs_pps_fids->update(); _srs_pps_fids_level0->update(); _srs_pps_addrs->update(); _srs_pps_fast_addrs->update(); + if (_srs_pps_ids->r10s(), _srs_pps_fids->r10s(), _srs_pps_fids_level0->r10s(), _srs_pps_addrs->r10s(), _srs_pps_fast_addrs->r10s()) { + snprintf(buf, sizeof(buf), ", fid=%d,%d,%d,%d,%d", _srs_pps_ids->r10s(), _srs_pps_fids->r10s(), _srs_pps_fids_level0->r10s(), _srs_pps_addrs->r10s(), _srs_pps_fast_addrs->r10s()); + fid_desc = buf; + } + + srs_trace("RTC: Server conns=%u%s%s%s%s%s%s%s", nn_rtc_conns, - _srs_pps_rpkts->r10s(), _srs_pps_rrtps->r10s(), _srs_pps_rstuns->r10s(), _srs_pps_rrtcps->r10s(), - _srs_pps_spkts->r10s(), _srs_pps_srtps->r10s(), _srs_pps_sstuns->r10s(), _srs_pps_srtcps->r10s(), - _srs_pps_pli->r10s(), _srs_pps_twcc->r10s(), _srs_pps_rr->r10s(), - _srs_pps_snack->r10s(), _srs_pps_sanack->r10s(), _srs_pps_svnack->r10s(), _srs_pps_snack2->r10s(), - _srs_pps_rnack->r10s(), _srs_pps_rnack2->r10s(), _srs_pps_rhnack->r10s(), _srs_pps_rmnack->r10s(), - s->rcv_buf_errors_delta, s->snd_buf_errors_delta, - _srs_pps_ids->r10s(), _srs_pps_fids->r10s(), _srs_pps_fids_level0->r10s(), _srs_pps_addrs->r10s(), _srs_pps_fast_addrs->r10s() + rpkts_desc.c_str(), spkts_desc.c_str(), rtcp_desc.c_str(), snk_desc.c_str(), rnk_desc.c_str(), drop_desc.c_str(), fid_desc.c_str() ); return err; From d8ba72fdc5484fb94e05ed431d6e21d6097bf8b6 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 25 Feb 2021 13:46:52 +0800 Subject: [PATCH 011/102] Kernel: Extract SrsPps to kernel --- trunk/configure | 3 +- trunk/src/app/srs_app_rtc_server.cpp | 13 ++- trunk/src/kernel/srs_kernel_kbps.cpp | 123 +++++++++++++++++++++++ trunk/src/kernel/srs_kernel_kbps.hpp | 93 +++++++++++++++++ trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 6 ++ trunk/src/protocol/srs_protocol_kbps.cpp | 96 ------------------ trunk/src/protocol/srs_protocol_kbps.hpp | 63 +----------- 7 files changed, 236 insertions(+), 161 deletions(-) create mode 100644 trunk/src/kernel/srs_kernel_kbps.cpp create mode 100644 trunk/src/kernel/srs_kernel_kbps.hpp diff --git a/trunk/configure b/trunk/configure index 2a715da88..02dc2a0cc 100755 --- a/trunk/configure +++ b/trunk/configure @@ -216,7 +216,8 @@ ModuleLibIncs=(${SRS_OBJS_DIR} ${LibSSLRoot}) MODULE_FILES=("srs_kernel_error" "srs_kernel_log" "srs_kernel_buffer" "srs_kernel_utility" "srs_kernel_flv" "srs_kernel_codec" "srs_kernel_io" "srs_kernel_consts" "srs_kernel_aac" "srs_kernel_mp3" "srs_kernel_ts" - "srs_kernel_stream" "srs_kernel_balance" "srs_kernel_mp4" "srs_kernel_file") + "srs_kernel_stream" "srs_kernel_balance" "srs_kernel_mp4" "srs_kernel_file" + "srs_kernel_kbps") if [[ $SRS_RTC == YES ]]; then MODULE_FILES+=("srs_kernel_rtc_rtp" "srs_kernel_rtc_rtcp") fi diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index 455696cce..5dc93c269 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -75,6 +75,8 @@ extern SrsPps* _srs_pps_rnack2; extern SrsPps* _srs_pps_rhnack; extern SrsPps* _srs_pps_rmnack; +extern SrsPps* _srs_pps_objs_rtps; + SrsRtcBlackhole::SrsRtcBlackhole() { blackhole = false; @@ -676,6 +678,13 @@ srs_error_t SrsRtcServer::notify(int type, srs_utime_t interval, srs_utime_t tic } static char buf[128]; + string objs_desc; + _srs_pps_objs_rtps->update(); + if (_srs_pps_objs_rtps->r10s()) { + snprintf(buf, sizeof(buf), ", objs=%d", _srs_pps_objs_rtps->r10s()); + objs_desc = buf; + } + string rpkts_desc; _srs_pps_rpkts->update(); _srs_pps_rrtps->update(); _srs_pps_rstuns->update(); _srs_pps_rrtcps->update(); if (_srs_pps_rpkts->r10s() || _srs_pps_rrtps->r10s() || _srs_pps_rstuns->r10s() || _srs_pps_rrtcps->r10s()) { @@ -725,9 +734,9 @@ srs_error_t SrsRtcServer::notify(int type, srs_utime_t interval, srs_utime_t tic fid_desc = buf; } - srs_trace("RTC: Server conns=%u%s%s%s%s%s%s%s", + srs_trace("RTC: Server conns=%u%s%s%s%s%s%s%s%s", nn_rtc_conns, - rpkts_desc.c_str(), spkts_desc.c_str(), rtcp_desc.c_str(), snk_desc.c_str(), rnk_desc.c_str(), drop_desc.c_str(), fid_desc.c_str() + rpkts_desc.c_str(), spkts_desc.c_str(), rtcp_desc.c_str(), snk_desc.c_str(), rnk_desc.c_str(), drop_desc.c_str(), fid_desc.c_str(), objs_desc.c_str() ); return err; diff --git a/trunk/src/kernel/srs_kernel_kbps.cpp b/trunk/src/kernel/srs_kernel_kbps.cpp new file mode 100644 index 000000000..c76f4c33e --- /dev/null +++ b/trunk/src/kernel/srs_kernel_kbps.cpp @@ -0,0 +1,123 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2013-2020 Winlin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include + +#include + +SrsRateSample::SrsRateSample() +{ + total = time = -1; + rate = 0; +} + +SrsRateSample::~SrsRateSample() +{ +} + +SrsRateSample* SrsRateSample::update(int64_t nn, srs_utime_t t, int k) +{ + total = nn; + time = t; + rate = k; + return this; +} + +void srs_pps_init(SrsRateSample& sample, int64_t nn, srs_utime_t now) +{ + if (sample.time < 0 || nn < sample.total) { + sample.update(nn, now, 0); + } +} + +void srs_pps_update(SrsRateSample& sample, int64_t nn, srs_utime_t now) +{ + int pps = (int)((nn - sample.total) * 1000 / srsu2ms(now - sample.time)); + if (pps == 0 && nn > sample.total) { + pps = 1; // For pps in (0, 1), we set to 1. + } + sample.update(nn, now, pps); +} + +SrsPps::SrsPps(SrsWallClock* c) +{ + clk_ = c; + sugar = 0; +} + +SrsPps::~SrsPps() +{ +} + +void SrsPps::update() +{ + update(sugar); +} + +void SrsPps::update(int64_t nn) +{ + srs_utime_t now = clk_->now(); + + srs_pps_init(sample_10s_, nn, now); + srs_pps_init(sample_30s_, nn, now); + srs_pps_init(sample_1m_, nn, now); + srs_pps_init(sample_5m_, nn, now); + srs_pps_init(sample_60m_, nn, now); + + if (now - sample_10s_.time >= 10 * SRS_UTIME_SECONDS) { + srs_pps_update(sample_10s_, nn, now); + } + if (now - sample_30s_.time >= 30 * SRS_UTIME_SECONDS) { + srs_pps_update(sample_30s_, nn, now); + } + if (now - sample_1m_.time >= 60 * SRS_UTIME_SECONDS) { + srs_pps_update(sample_1m_, nn, now); + } + if (now - sample_5m_.time >= 300 * SRS_UTIME_SECONDS) { + srs_pps_update(sample_5m_, nn, now); + } + if (now - sample_60m_.time >= 3600 * SRS_UTIME_SECONDS) { + srs_pps_update(sample_60m_, nn, now); + } +} + +int SrsPps::r10s() +{ + return sample_10s_.rate; +} + +SrsWallClock::SrsWallClock() +{ +} + +SrsWallClock::~SrsWallClock() +{ +} + +srs_utime_t SrsWallClock::now() +{ + return srs_get_system_time(); +} + +SrsWallClock* _srs_clock = new SrsWallClock(); + diff --git a/trunk/src/kernel/srs_kernel_kbps.hpp b/trunk/src/kernel/srs_kernel_kbps.hpp new file mode 100644 index 000000000..deddf8166 --- /dev/null +++ b/trunk/src/kernel/srs_kernel_kbps.hpp @@ -0,0 +1,93 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2013-2020 Winlin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef SRS_KERNEL_KBPS_HPP +#define SRS_KERNEL_KBPS_HPP + +#include + +#include + +class SrsWallClock; + +// A sample for rate-based stat, such as kbps or kps. +class SrsRateSample +{ +public: + int64_t total; + srs_utime_t time; + // kbps or kps + int rate; +public: + SrsRateSample(); + virtual ~SrsRateSample(); +public: + virtual SrsRateSample* update(int64_t nn, srs_utime_t t, int k); +}; + +// A pps manager every some duration. +class SrsPps +{ +private: + SrsWallClock* clk_; +private: + // samples + SrsRateSample sample_10s_; + SrsRateSample sample_30s_; + SrsRateSample sample_1m_; + SrsRateSample sample_5m_; + SrsRateSample sample_60m_; +public: + // Sugar for target to stat. + int64_t sugar; +public: + SrsPps(SrsWallClock* clk); + virtual ~SrsPps(); +public: + // Update with the nn which is target. + void update(); + // Update with the nn. + void update(int64_t nn); + // Get the 10s average stat. + int r10s(); +}; + +/** + * A time source to provide wall clock. + */ +class SrsWallClock +{ +public: + SrsWallClock(); + virtual ~SrsWallClock(); +public: + /** + * Current time in srs_utime_t. + */ + virtual srs_utime_t now(); +}; + +// The global clock. +extern SrsWallClock* _srs_clock; + +#endif diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index a542d59b4..806ba3e67 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -34,6 +34,10 @@ using namespace std; #include #include +#include + +SrsPps* _srs_pps_objs_rtps = new SrsPps(_srs_clock); + /* @see https://tools.ietf.org/html/rfc1889#section-5.1 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 @@ -764,6 +768,8 @@ SrsRtpPacket2::SrsRtpPacket2() shared_msg = NULL; frame_type = SrsFrameTypeReserved; cached_payload_size = 0; + + ++_srs_pps_objs_rtps->sugar; } SrsRtpPacket2::~SrsRtpPacket2() diff --git a/trunk/src/protocol/srs_protocol_kbps.cpp b/trunk/src/protocol/srs_protocol_kbps.cpp index b0d4bfa0f..f0af4b210 100644 --- a/trunk/src/protocol/srs_protocol_kbps.cpp +++ b/trunk/src/protocol/srs_protocol_kbps.cpp @@ -25,87 +25,6 @@ #include -SrsRateSample::SrsRateSample() -{ - total = time = -1; - rate = 0; -} - -SrsRateSample::~SrsRateSample() -{ -} - -SrsRateSample* SrsRateSample::update(int64_t nn, srs_utime_t t, int k) -{ - total = nn; - time = t; - rate = k; - return this; -} - -void srs_pps_init(SrsRateSample& sample, int64_t nn, srs_utime_t now) -{ - if (sample.time < 0 || nn < sample.total) { - sample.update(nn, now, 0); - } -} - -void srs_pps_update(SrsRateSample& sample, int64_t nn, srs_utime_t now) -{ - int pps = (int)((nn - sample.total) * 1000 / srsu2ms(now - sample.time)); - if (pps == 0 && nn > sample.total) { - pps = 1; // For pps in (0, 1), we set to 1. - } - sample.update(nn, now, pps); -} - -SrsPps::SrsPps(SrsWallClock* c) -{ - clk_ = c; - sugar = 0; -} - -SrsPps::~SrsPps() -{ -} - -void SrsPps::update() -{ - update(sugar); -} - -void SrsPps::update(int64_t nn) -{ - srs_utime_t now = clk_->now(); - - srs_pps_init(sample_10s_, nn, now); - srs_pps_init(sample_30s_, nn, now); - srs_pps_init(sample_1m_, nn, now); - srs_pps_init(sample_5m_, nn, now); - srs_pps_init(sample_60m_, nn, now); - - if (now - sample_10s_.time >= 10 * SRS_UTIME_SECONDS) { - srs_pps_update(sample_10s_, nn, now); - } - if (now - sample_30s_.time >= 30 * SRS_UTIME_SECONDS) { - srs_pps_update(sample_30s_, nn, now); - } - if (now - sample_1m_.time >= 60 * SRS_UTIME_SECONDS) { - srs_pps_update(sample_1m_, nn, now); - } - if (now - sample_5m_.time >= 300 * SRS_UTIME_SECONDS) { - srs_pps_update(sample_5m_, nn, now); - } - if (now - sample_60m_.time >= 3600 * SRS_UTIME_SECONDS) { - srs_pps_update(sample_60m_, nn, now); - } -} - -int SrsPps::r10s() -{ - return sample_10s_.rate; -} - SrsKbpsSlice::SrsKbpsSlice(SrsWallClock* c) { clk = c; @@ -166,19 +85,6 @@ ISrsKbpsDelta::~ISrsKbpsDelta() { } -SrsWallClock::SrsWallClock() -{ -} - -SrsWallClock::~SrsWallClock() -{ -} - -srs_utime_t SrsWallClock::now() -{ - return srs_get_system_time(); -} - SrsKbps::SrsKbps(SrsWallClock* c) : is(c), os(c) { clk = c; @@ -360,5 +266,3 @@ int SrsKbps::size_memory() return sizeof(SrsKbps); } -SrsWallClock* _srs_clock = new SrsWallClock(); - diff --git a/trunk/src/protocol/srs_protocol_kbps.hpp b/trunk/src/protocol/srs_protocol_kbps.hpp index 014038e85..429f7375b 100644 --- a/trunk/src/protocol/srs_protocol_kbps.hpp +++ b/trunk/src/protocol/srs_protocol_kbps.hpp @@ -27,50 +27,7 @@ #include #include - -class SrsWallClock; - -// A sample for rate-based stat, such as kbps or kps. -class SrsRateSample -{ -public: - int64_t total; - srs_utime_t time; - // kbps or kps - int rate; -public: - SrsRateSample(); - virtual ~SrsRateSample(); -public: - virtual SrsRateSample* update(int64_t nn, srs_utime_t t, int k); -}; - -// A pps manager every some duration. -class SrsPps -{ -private: - SrsWallClock* clk_; -private: - // samples - SrsRateSample sample_10s_; - SrsRateSample sample_30s_; - SrsRateSample sample_1m_; - SrsRateSample sample_5m_; - SrsRateSample sample_60m_; -public: - // Sugar for target to stat. - int64_t sugar; -public: - SrsPps(SrsWallClock* clk); - virtual ~SrsPps(); -public: - // Update with the nn which is target. - void update(); - // Update with the nn. - void update(int64_t nn); - // Get the 10s average stat. - int r10s(); -}; +#include /** * a slice of kbps statistic, for input or output. @@ -144,21 +101,6 @@ public: virtual void remark(int64_t* in, int64_t* out) = 0; }; -/** - * A time source to provide wall clock. - */ -class SrsWallClock -{ -public: - SrsWallClock(); - virtual ~SrsWallClock(); -public: - /** - * Current time in srs_utime_t. - */ - virtual srs_utime_t now(); -}; - /** * to statistic the kbps of io. * itself can be a statistic source, for example, used for SRS bytes stat. @@ -258,7 +200,4 @@ public: virtual int size_memory(); }; -// The global clock. -extern SrsWallClock* _srs_clock; - #endif From 6dac1806279b85e4a82da608ba0eb65d839eb3ce Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 25 Feb 2021 14:06:18 +0800 Subject: [PATCH 012/102] Kernel: Never depends on another globals for global variables --- trunk/src/app/srs_app_conn.cpp | 8 +-- trunk/src/app/srs_app_hourglass.cpp | 2 +- trunk/src/app/srs_app_hybrid.cpp | 84 ++++++++++++------------- trunk/src/app/srs_app_listener.cpp | 8 +-- trunk/src/app/srs_app_rtc_conn.cpp | 16 ++--- trunk/src/app/srs_app_rtc_server.cpp | 6 +- trunk/src/app/srs_app_rtc_source.cpp | 16 ++--- trunk/src/kernel/srs_kernel_kbps.cpp | 14 ++++- trunk/src/kernel/srs_kernel_kbps.hpp | 4 +- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 2 +- trunk/src/protocol/srs_service_log.cpp | 4 +- 11 files changed, 88 insertions(+), 76 deletions(-) diff --git a/trunk/src/app/srs_app_conn.cpp b/trunk/src/app/srs_app_conn.cpp index 17301c4c4..9851313ea 100644 --- a/trunk/src/app/srs_app_conn.cpp +++ b/trunk/src/app/srs_app_conn.cpp @@ -38,10 +38,10 @@ using namespace std; #include -SrsPps* _srs_pps_ids = new SrsPps(_srs_clock); -SrsPps* _srs_pps_fids = new SrsPps(_srs_clock); -SrsPps* _srs_pps_fids_level0 = new SrsPps(_srs_clock); -SrsPps* _srs_pps_dispose = new SrsPps(_srs_clock); +SrsPps* _srs_pps_ids = new SrsPps(); +SrsPps* _srs_pps_fids = new SrsPps(); +SrsPps* _srs_pps_fids_level0 = new SrsPps(); +SrsPps* _srs_pps_dispose = new SrsPps(); ISrsDisposingHandler::ISrsDisposingHandler() { diff --git a/trunk/src/app/srs_app_hourglass.cpp b/trunk/src/app/srs_app_hourglass.cpp index f899a8b6b..b5c84ed9a 100644 --- a/trunk/src/app/srs_app_hourglass.cpp +++ b/trunk/src/app/srs_app_hourglass.cpp @@ -30,7 +30,7 @@ using namespace std; #include -SrsPps* _srs_pps_timer = new SrsPps(_srs_clock); +SrsPps* _srs_pps_timer = new SrsPps(); ISrsHourGlass::ISrsHourGlass() { diff --git a/trunk/src/app/srs_app_hybrid.cpp b/trunk/src/app/srs_app_hybrid.cpp index b8645bb4f..9a310b2ae 100644 --- a/trunk/src/app/srs_app_hybrid.cpp +++ b/trunk/src/app/srs_app_hybrid.cpp @@ -44,10 +44,10 @@ extern unsigned long long _st_stat_recvfrom; extern unsigned long long _st_stat_recvfrom_eagain; extern unsigned long long _st_stat_sendto; extern unsigned long long _st_stat_sendto_eagain; -SrsPps* _srs_pps_recvfrom = new SrsPps(_srs_clock); -SrsPps* _srs_pps_recvfrom_eagain = new SrsPps(_srs_clock); -SrsPps* _srs_pps_sendto = new SrsPps(_srs_clock); -SrsPps* _srs_pps_sendto_eagain = new SrsPps(_srs_clock); +SrsPps* _srs_pps_recvfrom = new SrsPps(); +SrsPps* _srs_pps_recvfrom_eagain = new SrsPps(); +SrsPps* _srs_pps_sendto = new SrsPps(); +SrsPps* _srs_pps_sendto_eagain = new SrsPps(); extern unsigned long long _st_stat_read; extern unsigned long long _st_stat_read_eagain; @@ -55,12 +55,12 @@ extern unsigned long long _st_stat_readv; extern unsigned long long _st_stat_readv_eagain; extern unsigned long long _st_stat_writev; extern unsigned long long _st_stat_writev_eagain; -SrsPps* _srs_pps_read = new SrsPps(_srs_clock); -SrsPps* _srs_pps_read_eagain = new SrsPps(_srs_clock); -SrsPps* _srs_pps_readv = new SrsPps(_srs_clock); -SrsPps* _srs_pps_readv_eagain = new SrsPps(_srs_clock); -SrsPps* _srs_pps_writev = new SrsPps(_srs_clock); -SrsPps* _srs_pps_writev_eagain = new SrsPps(_srs_clock); +SrsPps* _srs_pps_read = new SrsPps(); +SrsPps* _srs_pps_read_eagain = new SrsPps(); +SrsPps* _srs_pps_readv = new SrsPps(); +SrsPps* _srs_pps_readv_eagain = new SrsPps(); +SrsPps* _srs_pps_writev = new SrsPps(); +SrsPps* _srs_pps_writev_eagain = new SrsPps(); extern unsigned long long _st_stat_recvmsg; extern unsigned long long _st_stat_recvmsg_eagain; @@ -68,21 +68,21 @@ extern unsigned long long _st_stat_sendmsg; extern unsigned long long _st_stat_sendmsg_eagain; extern unsigned long long _st_stat_sendmmsg; extern unsigned long long _st_stat_sendmmsg_eagain; -SrsPps* _srs_pps_recvmsg = new SrsPps(_srs_clock); -SrsPps* _srs_pps_recvmsg_eagain = new SrsPps(_srs_clock); -SrsPps* _srs_pps_sendmsg = new SrsPps(_srs_clock); -SrsPps* _srs_pps_sendmsg_eagain = new SrsPps(_srs_clock); -SrsPps* _srs_pps_sendmmsg = new SrsPps(_srs_clock); -SrsPps* _srs_pps_sendmmsg_eagain = new SrsPps(_srs_clock); +SrsPps* _srs_pps_recvmsg = new SrsPps(); +SrsPps* _srs_pps_recvmsg_eagain = new SrsPps(); +SrsPps* _srs_pps_sendmsg = new SrsPps(); +SrsPps* _srs_pps_sendmsg_eagain = new SrsPps(); +SrsPps* _srs_pps_sendmmsg = new SrsPps(); +SrsPps* _srs_pps_sendmmsg_eagain = new SrsPps(); extern unsigned long long _st_stat_epoll; extern unsigned long long _st_stat_epoll_zero; extern unsigned long long _st_stat_epoll_shake; extern unsigned long long _st_stat_epoll_spin; -SrsPps* _srs_pps_epoll = new SrsPps(_srs_clock); -SrsPps* _srs_pps_epoll_zero = new SrsPps(_srs_clock); -SrsPps* _srs_pps_epoll_shake = new SrsPps(_srs_clock); -SrsPps* _srs_pps_epoll_spin = new SrsPps(_srs_clock); +SrsPps* _srs_pps_epoll = new SrsPps(); +SrsPps* _srs_pps_epoll_zero = new SrsPps(); +SrsPps* _srs_pps_epoll_shake = new SrsPps(); +SrsPps* _srs_pps_epoll_spin = new SrsPps(); extern unsigned long long _st_stat_sched_15ms; extern unsigned long long _st_stat_sched_20ms; @@ -93,26 +93,26 @@ extern unsigned long long _st_stat_sched_40ms; extern unsigned long long _st_stat_sched_80ms; extern unsigned long long _st_stat_sched_160ms; extern unsigned long long _st_stat_sched_s; -SrsPps* _srs_pps_sched_15ms = new SrsPps(_srs_clock); -SrsPps* _srs_pps_sched_20ms = new SrsPps(_srs_clock); -SrsPps* _srs_pps_sched_25ms = new SrsPps(_srs_clock); -SrsPps* _srs_pps_sched_30ms = new SrsPps(_srs_clock); -SrsPps* _srs_pps_sched_35ms = new SrsPps(_srs_clock); -SrsPps* _srs_pps_sched_40ms = new SrsPps(_srs_clock); -SrsPps* _srs_pps_sched_80ms = new SrsPps(_srs_clock); -SrsPps* _srs_pps_sched_160ms = new SrsPps(_srs_clock); -SrsPps* _srs_pps_sched_s = new SrsPps(_srs_clock); +SrsPps* _srs_pps_sched_15ms = new SrsPps(); +SrsPps* _srs_pps_sched_20ms = new SrsPps(); +SrsPps* _srs_pps_sched_25ms = new SrsPps(); +SrsPps* _srs_pps_sched_30ms = new SrsPps(); +SrsPps* _srs_pps_sched_35ms = new SrsPps(); +SrsPps* _srs_pps_sched_40ms = new SrsPps(); +SrsPps* _srs_pps_sched_80ms = new SrsPps(); +SrsPps* _srs_pps_sched_160ms = new SrsPps(); +SrsPps* _srs_pps_sched_s = new SrsPps(); #endif -SrsPps* _srs_pps_clock_15ms = new SrsPps(_srs_clock); -SrsPps* _srs_pps_clock_20ms = new SrsPps(_srs_clock); -SrsPps* _srs_pps_clock_25ms = new SrsPps(_srs_clock); -SrsPps* _srs_pps_clock_30ms = new SrsPps(_srs_clock); -SrsPps* _srs_pps_clock_35ms = new SrsPps(_srs_clock); -SrsPps* _srs_pps_clock_40ms = new SrsPps(_srs_clock); -SrsPps* _srs_pps_clock_80ms = new SrsPps(_srs_clock); -SrsPps* _srs_pps_clock_160ms = new SrsPps(_srs_clock); -SrsPps* _srs_pps_timer_s = new SrsPps(_srs_clock); +SrsPps* _srs_pps_clock_15ms = new SrsPps(); +SrsPps* _srs_pps_clock_20ms = new SrsPps(); +SrsPps* _srs_pps_clock_25ms = new SrsPps(); +SrsPps* _srs_pps_clock_30ms = new SrsPps(); +SrsPps* _srs_pps_clock_35ms = new SrsPps(); +SrsPps* _srs_pps_clock_40ms = new SrsPps(); +SrsPps* _srs_pps_clock_80ms = new SrsPps(); +SrsPps* _srs_pps_clock_160ms = new SrsPps(); +SrsPps* _srs_pps_timer_s = new SrsPps(); #if defined(SRS_DEBUG) && defined(SRS_DEBUG_STATS) extern int _st_active_count; @@ -120,10 +120,10 @@ extern unsigned long long _st_stat_thread_run; extern unsigned long long _st_stat_thread_idle; extern unsigned long long _st_stat_thread_yield; extern unsigned long long _st_stat_thread_yield2; -SrsPps* _srs_pps_thread_run = new SrsPps(_srs_clock); -SrsPps* _srs_pps_thread_idle = new SrsPps(_srs_clock); -SrsPps* _srs_pps_thread_yield = new SrsPps(_srs_clock); -SrsPps* _srs_pps_thread_yield2 = new SrsPps(_srs_clock); +SrsPps* _srs_pps_thread_run = new SrsPps(); +SrsPps* _srs_pps_thread_idle = new SrsPps(); +SrsPps* _srs_pps_thread_yield = new SrsPps(); +SrsPps* _srs_pps_thread_yield2 = new SrsPps(); #endif ISrsHybridServer::ISrsHybridServer() diff --git a/trunk/src/app/srs_app_listener.cpp b/trunk/src/app/srs_app_listener.cpp index ce335ce6d..ec131230b 100755 --- a/trunk/src/app/srs_app_listener.cpp +++ b/trunk/src/app/srs_app_listener.cpp @@ -45,11 +45,11 @@ using namespace std; #include -SrsPps* _srs_pps_rpkts = new SrsPps(_srs_clock); -SrsPps* _srs_pps_addrs = new SrsPps(_srs_clock); -SrsPps* _srs_pps_fast_addrs = new SrsPps(_srs_clock); +SrsPps* _srs_pps_rpkts = new SrsPps(); +SrsPps* _srs_pps_addrs = new SrsPps(); +SrsPps* _srs_pps_fast_addrs = new SrsPps(); -SrsPps* _srs_pps_spkts = new SrsPps(_srs_clock); +SrsPps* _srs_pps_spkts = new SrsPps(); // set the max packet size. #define SRS_UDP_MAX_PACKET_SIZE 65535 diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 1b3329fe7..683247235 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -60,15 +60,15 @@ using namespace std; #include -SrsPps* _srs_pps_sstuns = new SrsPps(_srs_clock); -SrsPps* _srs_pps_srtcps = new SrsPps(_srs_clock); -SrsPps* _srs_pps_srtps = new SrsPps(_srs_clock); +SrsPps* _srs_pps_sstuns = new SrsPps(); +SrsPps* _srs_pps_srtcps = new SrsPps(); +SrsPps* _srs_pps_srtps = new SrsPps(); -SrsPps* _srs_pps_pli = new SrsPps(_srs_clock); -SrsPps* _srs_pps_twcc = new SrsPps(_srs_clock); -SrsPps* _srs_pps_rr = new SrsPps(_srs_clock); -SrsPps* _srs_pps_pub = new SrsPps(_srs_clock); -SrsPps* _srs_pps_conn = new SrsPps(_srs_clock); +SrsPps* _srs_pps_pli = new SrsPps(); +SrsPps* _srs_pps_twcc = new SrsPps(); +SrsPps* _srs_pps_rr = new SrsPps(); +SrsPps* _srs_pps_pub = new SrsPps(); +SrsPps* _srs_pps_conn = new SrsPps(); extern SrsPps* _srs_pps_snack; extern SrsPps* _srs_pps_snack2; diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index 5dc93c269..c4453a8d7 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -46,9 +46,9 @@ using namespace std; #include extern SrsPps* _srs_pps_rpkts; -SrsPps* _srs_pps_rstuns = new SrsPps(_srs_clock); -SrsPps* _srs_pps_rrtps = new SrsPps(_srs_clock); -SrsPps* _srs_pps_rrtcps = new SrsPps(_srs_clock); +SrsPps* _srs_pps_rstuns = new SrsPps(); +SrsPps* _srs_pps_rrtps = new SrsPps(); +SrsPps* _srs_pps_rrtcps = new SrsPps(); extern SrsPps* _srs_pps_addrs; extern SrsPps* _srs_pps_fast_addrs; diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index eb5d30f20..95e0cc17e 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -51,15 +51,15 @@ #include // The NACK sent by us(SFU). -SrsPps* _srs_pps_snack = new SrsPps(_srs_clock); -SrsPps* _srs_pps_snack2 = new SrsPps(_srs_clock); -SrsPps* _srs_pps_sanack = new SrsPps(_srs_clock); -SrsPps* _srs_pps_svnack = new SrsPps(_srs_clock); +SrsPps* _srs_pps_snack = new SrsPps(); +SrsPps* _srs_pps_snack2 = new SrsPps(); +SrsPps* _srs_pps_sanack = new SrsPps(); +SrsPps* _srs_pps_svnack = new SrsPps(); -SrsPps* _srs_pps_rnack = new SrsPps(_srs_clock); -SrsPps* _srs_pps_rnack2 = new SrsPps(_srs_clock); -SrsPps* _srs_pps_rhnack = new SrsPps(_srs_clock); -SrsPps* _srs_pps_rmnack = new SrsPps(_srs_clock); +SrsPps* _srs_pps_rnack = new SrsPps(); +SrsPps* _srs_pps_rnack2 = new SrsPps(); +SrsPps* _srs_pps_rhnack = new SrsPps(); +SrsPps* _srs_pps_rmnack = new SrsPps(); // Firefox defaults as 109, Chrome is 111. const int kAudioPayloadType = 111; diff --git a/trunk/src/kernel/srs_kernel_kbps.cpp b/trunk/src/kernel/srs_kernel_kbps.cpp index c76f4c33e..6c2e9cb2a 100644 --- a/trunk/src/kernel/srs_kernel_kbps.cpp +++ b/trunk/src/kernel/srs_kernel_kbps.cpp @@ -59,9 +59,9 @@ void srs_pps_update(SrsRateSample& sample, int64_t nn, srs_utime_t now) sample.update(nn, now, pps); } -SrsPps::SrsPps(SrsWallClock* c) +SrsPps::SrsPps() { - clk_ = c; + clk_ = NULL; sugar = 0; } @@ -69,6 +69,11 @@ SrsPps::~SrsPps() { } +void SrsPps::set_clock(SrsWallClock* clk) +{ + clk_ = clk; +} + void SrsPps::update() { update(sugar); @@ -76,6 +81,11 @@ void SrsPps::update() void SrsPps::update(int64_t nn) { + // Lazy setup the clock. + if (!clk_) { + clk_ = _srs_clock; + } + srs_utime_t now = clk_->now(); srs_pps_init(sample_10s_, nn, now); diff --git a/trunk/src/kernel/srs_kernel_kbps.hpp b/trunk/src/kernel/srs_kernel_kbps.hpp index deddf8166..99842a26e 100644 --- a/trunk/src/kernel/srs_kernel_kbps.hpp +++ b/trunk/src/kernel/srs_kernel_kbps.hpp @@ -61,9 +61,11 @@ public: // Sugar for target to stat. int64_t sugar; public: - SrsPps(SrsWallClock* clk); + SrsPps(); virtual ~SrsPps(); public: + // Setup the clock, use global clock if not set. + void set_clock(SrsWallClock* clk); // Update with the nn which is target. void update(); // Update with the nn. diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index 806ba3e67..979bdf3de 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -36,7 +36,7 @@ using namespace std; #include -SrsPps* _srs_pps_objs_rtps = new SrsPps(_srs_clock); +SrsPps* _srs_pps_objs_rtps = new SrsPps(); /* @see https://tools.ietf.org/html/rfc1889#section-5.1 0 1 2 3 diff --git a/trunk/src/protocol/srs_service_log.cpp b/trunk/src/protocol/srs_service_log.cpp index fbd1e4b9e..8c3be6eda 100644 --- a/trunk/src/protocol/srs_service_log.cpp +++ b/trunk/src/protocol/srs_service_log.cpp @@ -35,8 +35,8 @@ using namespace std; #include -SrsPps* _srs_pps_cids_get = new SrsPps(_srs_clock); -SrsPps* _srs_pps_cids_set = new SrsPps(_srs_clock); +SrsPps* _srs_pps_cids_get = new SrsPps(); +SrsPps* _srs_pps_cids_set = new SrsPps(); #define SRS_BASIC_LOG_SIZE 8192 From e7529ce9dc09f9cdeb36e70f4aecdc1e70075459 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 25 Feb 2021 14:25:54 +0800 Subject: [PATCH 013/102] RTC: Stat the RTP and payload objects --- trunk/src/app/srs_app_rtc_server.cpp | 8 +++++--- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 8 ++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index c4453a8d7..2315e3d10 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -76,6 +76,8 @@ extern SrsPps* _srs_pps_rhnack; extern SrsPps* _srs_pps_rmnack; extern SrsPps* _srs_pps_objs_rtps; +extern SrsPps* _srs_pps_objs_rraw; +extern SrsPps* _srs_pps_objs_rfua; SrsRtcBlackhole::SrsRtcBlackhole() { @@ -679,9 +681,9 @@ srs_error_t SrsRtcServer::notify(int type, srs_utime_t interval, srs_utime_t tic static char buf[128]; string objs_desc; - _srs_pps_objs_rtps->update(); - if (_srs_pps_objs_rtps->r10s()) { - snprintf(buf, sizeof(buf), ", objs=%d", _srs_pps_objs_rtps->r10s()); + _srs_pps_objs_rtps->update(); _srs_pps_objs_rraw->update(); _srs_pps_objs_rfua->update(); + if (_srs_pps_objs_rtps->r10s() || _srs_pps_objs_rraw->r10s() || _srs_pps_objs_rfua->r10s()) { + snprintf(buf, sizeof(buf), ", objs=%d,%d,%d", _srs_pps_objs_rtps->r10s(), _srs_pps_objs_rraw->r10s(), _srs_pps_objs_rfua->r10s()); objs_desc = buf; } diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index 979bdf3de..ab2d07a34 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -37,6 +37,8 @@ using namespace std; #include SrsPps* _srs_pps_objs_rtps = new SrsPps(); +SrsPps* _srs_pps_objs_rraw = new SrsPps(); +SrsPps* _srs_pps_objs_rfua = new SrsPps(); /* @see https://tools.ietf.org/html/rfc1889#section-5.1 0 1 2 3 @@ -900,6 +902,8 @@ SrsRtpRawPayload::SrsRtpRawPayload() { payload = NULL; nn_payload = 0; + + ++_srs_pps_objs_rraw->sugar; } SrsRtpRawPayload::~SrsRtpRawPayload() @@ -1237,6 +1241,8 @@ SrsRtpFUAPayload::SrsRtpFUAPayload() { start = end = false; nri = nalu_type = (SrsAvcNaluType)0; + + ++_srs_pps_objs_rfua->sugar; } SrsRtpFUAPayload::~SrsRtpFUAPayload() @@ -1352,6 +1358,8 @@ SrsRtpFUAPayload2::SrsRtpFUAPayload2() payload = NULL; size = 0; + + ++_srs_pps_objs_rfua->sugar; } SrsRtpFUAPayload2::~SrsRtpFUAPayload2() From edb8a0f497191aeb913d185fdd120814cf4b400c Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 25 Feb 2021 17:56:15 +0800 Subject: [PATCH 014/102] RTC: Cache the buffer for player --- trunk/src/app/srs_app_rtc_conn.cpp | 22 ++++++++++++---------- trunk/src/app/srs_app_rtc_conn.hpp | 3 +++ 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 683247235..14564fb86 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1605,6 +1605,11 @@ SrsRtcConnection::SrsRtcConnection(SrsRtcServer* s, const SrsContextId& cid) server_ = s; transport_ = new SrsSecurityTransport(this); + cache_iov_ = new iovec(); + cache_iov_->iov_base = new char[kRtpPacketSize]; + cache_iov_->iov_len = kRtpPacketSize; + cache_buffer_ = new SrsBuffer((char*)cache_iov_->iov_base, kRtpPacketSize); + state_ = INIT; last_stun_time = 0; session_timeout = 0; @@ -1648,6 +1653,9 @@ SrsRtcConnection::~SrsRtcConnection() srs_freep(addr); } + srs_freep(cache_iov_); + srs_freep(cache_buffer_); + srs_freep(transport_); srs_freep(req); srs_freep(stat_); @@ -2510,22 +2518,16 @@ srs_error_t SrsRtcConnection::do_send_packets(const std::vector& SrsRtpPacket2* pkt = pkts.at(i); // For this message, select the first iovec. - iovec* iov = new iovec(); - SrsAutoFree(iovec, iov); - - char* iov_base = new char[kRtpPacketSize]; - SrsAutoFreeA(char, iov_base); - - iov->iov_base = iov_base; + iovec* iov = cache_iov_; iov->iov_len = kRtpPacketSize; + cache_buffer_->skip(-1 * cache_buffer_->pos()); // Marshal packet to bytes in iovec. if (true) { - SrsBuffer stream((char*)iov->iov_base, iov->iov_len); - if ((err = pkt->encode(&stream)) != srs_success) { + if ((err = pkt->encode(cache_buffer_)) != srs_success) { return srs_error_wrap(err, "encode packet"); } - iov->iov_len = stream.pos(); + iov->iov_len = cache_buffer_->pos(); } // Cipher RTP to SRTP packet. diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 6b84e108a..93d43db0e 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -431,6 +431,9 @@ private: SrsRtcConnectionStateType state_; ISrsRtcTransport* transport_; SrsHourGlass* timer_; +private: + iovec* cache_iov_; + SrsBuffer* cache_buffer_; private: // key: stream id std::map players_; From 4aa82b2fbf91bb151f44c1503ff15519e80fab6e Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 25 Feb 2021 19:02:38 +0800 Subject: [PATCH 015/102] RTC: Refine memory copy, allocate it later --- trunk/src/app/srs_app_rtc_conn.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 14564fb86..3ed1ca932 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1152,8 +1152,9 @@ srs_error_t SrsRtcPublishStream::on_rtp(char* data, int nb_data) } // Decrypt the cipher to plaintext RTP data. - int nb_unprotected_buf = nb_data; - if ((err = session_->transport_->unprotect_rtp(data, &nb_unprotected_buf)) != srs_success) { + char* plaintext = data; + int nb_plaintext = nb_data; + if ((err = session_->transport_->unprotect_rtp(plaintext, &nb_plaintext)) != srs_success) { // We try to decode the RTP header for more detail error informations. SrsBuffer b(data, nb_data); SrsRtpHeader h; h.ignore_padding(true); srs_error_t r0 = h.decode(&b); srs_freep(r0); // Ignore any error for header decoding. @@ -1163,17 +1164,14 @@ srs_error_t SrsRtcPublishStream::on_rtp(char* data, int nb_data) return err; } - - srs_assert(nb_unprotected_buf > 0); - char* unprotected_buf = new char[nb_unprotected_buf]; - memcpy(unprotected_buf, data, nb_unprotected_buf); + srs_assert(nb_plaintext > 0); if (_srs_blackhole->blackhole) { - _srs_blackhole->sendto(unprotected_buf, nb_unprotected_buf); + _srs_blackhole->sendto(plaintext, nb_plaintext); } // Handle the plaintext RTP packet. - if ((err = do_on_rtp(unprotected_buf, nb_unprotected_buf)) != srs_success) { + if ((err = do_on_rtp(plaintext, nb_plaintext)) != srs_success) { // We try to decode the RTP header for more detail error informations. SrsBuffer b(data, nb_data); SrsRtpHeader h; h.ignore_padding(true); srs_error_t r0 = h.decode(&b); srs_freep(r0); // Ignore any error for header decoding. @@ -1181,7 +1179,7 @@ srs_error_t SrsRtcPublishStream::on_rtp(char* data, int nb_data) int nb_header = h.nb_bytes(); const char* body = data + nb_header; int nb_body = nb_data - nb_header; - return srs_error_wrap(err, "cipher=%u, plaintext=%u, body=[%s]", nb_data, nb_unprotected_buf, + return srs_error_wrap(err, "cipher=%u, plaintext=%u, body=[%s]", nb_data, nb_plaintext, srs_string_dumps_hex(body, nb_body, 8).c_str()); } @@ -1192,8 +1190,9 @@ srs_error_t SrsRtcPublishStream::do_on_rtp(char* plaintext, int nb_plaintext) { srs_error_t err = srs_success; - char* buf = plaintext; + char* buf = new char[nb_plaintext]; int nb_buf = nb_plaintext; + memcpy(buf, plaintext, nb_plaintext); // Decode the RTP packet from buffer. SrsRtpPacket2* pkt = new SrsRtpPacket2(); From 23fa3fb35036de2a507e6cb43cfdfbfe31d7b846 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 25 Feb 2021 19:15:34 +0800 Subject: [PATCH 016/102] RTC: Refine memory allocate for publisher --- trunk/src/app/srs_app_rtc_conn.cpp | 22 ++++++++++------------ trunk/src/app/srs_app_rtc_conn.hpp | 2 +- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 3ed1ca932..ffcf053d5 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1164,14 +1164,9 @@ srs_error_t SrsRtcPublishStream::on_rtp(char* data, int nb_data) return err; } - srs_assert(nb_plaintext > 0); - - if (_srs_blackhole->blackhole) { - _srs_blackhole->sendto(plaintext, nb_plaintext); - } // Handle the plaintext RTP packet. - if ((err = do_on_rtp(plaintext, nb_plaintext)) != srs_success) { + if ((err = on_rtp_plaintext(plaintext, nb_plaintext)) != srs_success) { // We try to decode the RTP header for more detail error informations. SrsBuffer b(data, nb_data); SrsRtpHeader h; h.ignore_padding(true); srs_error_t r0 = h.decode(&b); srs_freep(r0); // Ignore any error for header decoding. @@ -1186,13 +1181,13 @@ srs_error_t SrsRtcPublishStream::on_rtp(char* data, int nb_data) return err; } -srs_error_t SrsRtcPublishStream::do_on_rtp(char* plaintext, int nb_plaintext) +srs_error_t SrsRtcPublishStream::on_rtp_plaintext(char* plaintext, int nb_plaintext) { srs_error_t err = srs_success; - char* buf = new char[nb_plaintext]; - int nb_buf = nb_plaintext; - memcpy(buf, plaintext, nb_plaintext); + if (_srs_blackhole->blackhole) { + _srs_blackhole->sendto(plaintext, nb_plaintext); + } // Decode the RTP packet from buffer. SrsRtpPacket2* pkt = new SrsRtpPacket2(); @@ -1202,9 +1197,12 @@ srs_error_t SrsRtcPublishStream::do_on_rtp(char* plaintext, int nb_plaintext) pkt->set_decode_handler(this); pkt->set_extension_types(&extension_types_); pkt->shared_msg = new SrsSharedPtrMessage(); - pkt->shared_msg->wrap(buf, nb_buf); - SrsBuffer b(buf, nb_buf); + char* buf = new char[nb_plaintext]; + memcpy(buf, plaintext, nb_plaintext); + pkt->shared_msg->wrap(buf, nb_plaintext); + + SrsBuffer b(buf, nb_plaintext); if ((err = pkt->decode(&b)) != srs_success) { return srs_error_wrap(err, "decode rtp packet"); } diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 93d43db0e..33e4aea70 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -354,7 +354,7 @@ private: public: srs_error_t on_rtp(char* buf, int nb_buf); private: - srs_error_t do_on_rtp(char* plaintext, int nb_plaintext); + srs_error_t on_rtp_plaintext(char* plaintext, int nb_plaintext); public: srs_error_t check_send_nacks(); public: From 048a72ab6e32b0f6aaeb72663bfffa6d843b8ab8 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 25 Feb 2021 19:16:50 +0800 Subject: [PATCH 017/102] RTC: Refine memory allocate for publisher --- trunk/src/app/srs_app_rtc_conn.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 33e4aea70..538eca984 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -354,6 +354,7 @@ private: public: srs_error_t on_rtp(char* buf, int nb_buf); private: + // @remark We copy the plaintext, user should free it. srs_error_t on_rtp_plaintext(char* plaintext, int nb_plaintext); public: srs_error_t check_send_nacks(); From d7bc8b98fb191c1ee020331f5a8b7052286653c2 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 26 Feb 2021 07:05:20 +0800 Subject: [PATCH 018/102] Fix build warning --- trunk/src/app/srs_app_rtc_jitbuffer.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/trunk/src/app/srs_app_rtc_jitbuffer.cpp b/trunk/src/app/srs_app_rtc_jitbuffer.cpp index 69d6becbc..cf3c172e2 100644 --- a/trunk/src/app/srs_app_rtc_jitbuffer.cpp +++ b/trunk/src/app/srs_app_rtc_jitbuffer.cpp @@ -1800,6 +1800,9 @@ SrsRtpFrameBuffer* SrsRtpJitterBuffer::ExtractAndSetDecode(uint32_t timestamp) } } + // Fix build warnings: variable ‘continuous’ set but not used + (void)continuous; + // The state must be changed to decoding before cleaning up zero sized // frames to avoid empty frames being cleaned up and then given to the // decoder. Propagates the missing_frame bit. From cec588e08a66a6c782f04d1974349f26931d46bb Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 26 Feb 2021 09:13:21 +0800 Subject: [PATCH 019/102] For #2188: Remove sendmmsg from ST. --- trunk/3rdparty/st-srs/Makefile | 4 -- trunk/3rdparty/st-srs/README.md | 2 +- trunk/3rdparty/st-srs/io.c | 65 --------------------------- trunk/3rdparty/st-srs/public.h | 8 ---- trunk/auto/depends.sh | 8 ---- trunk/auto/options.sh | 10 ----- trunk/src/app/srs_app_hybrid.cpp | 9 +--- trunk/src/protocol/srs_service_st.cpp | 5 --- trunk/src/protocol/srs_service_st.hpp | 8 ---- 9 files changed, 3 insertions(+), 116 deletions(-) diff --git a/trunk/3rdparty/st-srs/Makefile b/trunk/3rdparty/st-srs/Makefile index 71f96ba4e..cf4d51946 100644 --- a/trunk/3rdparty/st-srs/Makefile +++ b/trunk/3rdparty/st-srs/Makefile @@ -282,10 +282,6 @@ endif # # make EXTRA_CFLAGS=-UMD_HAVE_EPOLL # -# or to enable sendmmsg(2) support: -# -# make EXTRA_CFLAGS="-DMD_HAVE_SENDMMSG -D_GNU_SOURCE" -# # or to enable stats for ST: # # make EXTRA_CFLAGS=-DDEBUG_STATS diff --git a/trunk/3rdparty/st-srs/README.md b/trunk/3rdparty/st-srs/README.md index aa8ad70bc..8a5eba94f 100644 --- a/trunk/3rdparty/st-srs/README.md +++ b/trunk/3rdparty/st-srs/README.md @@ -66,7 +66,7 @@ The branch [srs](https://github.com/ossrs/state-threads/tree/srs) will be patche - [x] Support macro `MD_ST_NO_ASM` to disable ASM, [#8](https://github.com/ossrs/state-threads/issues/8). - [x] Merge patch [srs#1282](https://github.com/ossrs/srs/issues/1282#issuecomment-445539513) to support aarch64, [#9](https://github.com/ossrs/state-threads/issues/9). - [x] Support OSX for Apple Darwin, macOS, [#11](https://github.com/ossrs/state-threads/issues/11). -- [x] Support sendmmsg for UDP, [#12](https://github.com/ossrs/state-threads/issues/12). +- [ ] Support sendmmsg for UDP, [#12](https://github.com/ossrs/state-threads/issues/12). - [x] Refine performance for sleep or epoll_wait(0), [#17](https://github.com/ossrs/state-threads/issues/17). - [ ] Improve the performance of timer. [9fe8cfe5b](https://github.com/ossrs/state-threads/commit/9fe8cfe5b1c9741a2e671a46215184f267fba400), [7879c2b](https://github.com/ossrs/state-threads/commit/7879c2b), [387cddb](https://github.com/ossrs/state-threads/commit/387cddb) diff --git a/trunk/3rdparty/st-srs/io.c b/trunk/3rdparty/st-srs/io.c index da9184091..788a1046f 100644 --- a/trunk/3rdparty/st-srs/io.c +++ b/trunk/3rdparty/st-srs/io.c @@ -68,8 +68,6 @@ unsigned long long _st_stat_recvmsg = 0; unsigned long long _st_stat_recvmsg_eagain = 0; unsigned long long _st_stat_sendmsg = 0; unsigned long long _st_stat_sendmsg_eagain = 0; -unsigned long long _st_stat_sendmmsg = 0; -unsigned long long _st_stat_sendmmsg_eagain = 0; #endif #if EAGAIN != EWOULDBLOCK @@ -833,69 +831,6 @@ int st_sendmsg(_st_netfd_t *fd, const struct msghdr *msg, int flags, st_utime_t return n; } -int st_sendmmsg(st_netfd_t fd, struct st_mmsghdr *msgvec, unsigned int vlen, int flags, st_utime_t timeout) -{ -#if defined(MD_HAVE_SENDMMSG) && defined(_GNU_SOURCE) - int n; - int left; - struct mmsghdr *p; - - #if defined(DEBUG) && defined(DEBUG_STATS) - ++_st_stat_sendmmsg; - #endif - - left = (int)vlen; - while (left > 0) { - p = (struct mmsghdr*)msgvec + (vlen - left); - - if ((n = sendmmsg(fd->osfd, p, left, flags)) < 0) { - if (errno == EINTR) - continue; - if (!_IO_NOT_READY_ERROR) - break; - - #if defined(DEBUG) && defined(DEBUG_STATS) - ++_st_stat_sendmmsg_eagain; - #endif - - /* Wait until the socket becomes writable */ - if (st_netfd_poll(fd, POLLOUT, timeout) < 0) - break; - } - - left -= n; - } - - // An error is returned only if no datagrams could be sent. - if (left == (int)vlen) { - return n; - } - return (int)vlen - left; -#else - struct st_mmsghdr *p; - int i, n; - - // @see http://man7.org/linux/man-pages/man2/sendmmsg.2.html - for (i = 0; i < (int)vlen; ++i) { - p = msgvec + i; - n = st_sendmsg(fd, &p->msg_hdr, flags, timeout); - if (n < 0) { - // An error is returned only if no datagrams could be sent. - if (i == 0) { - return n; - } - return i + 1; - } - - p->msg_len = n; - } - - // Returns the number of messages sent from msgvec; if this is less than vlen, the caller can retry with a - // further sendmmsg() call to send the remaining messages. - return vlen; -#endif -} - /* * To open FIFOs or other special files. diff --git a/trunk/3rdparty/st-srs/public.h b/trunk/3rdparty/st-srs/public.h index c911912b8..df7c5c967 100644 --- a/trunk/3rdparty/st-srs/public.h +++ b/trunk/3rdparty/st-srs/public.h @@ -153,14 +153,6 @@ extern int st_sendto(st_netfd_t fd, const void *msg, int len, const struct socka extern int st_recvmsg(st_netfd_t fd, struct msghdr *msg, int flags, st_utime_t timeout); extern int st_sendmsg(st_netfd_t fd, const struct msghdr *msg, int flags, st_utime_t timeout); -// @see http://man7.org/linux/man-pages/man2/sendmmsg.2.html -#include -struct st_mmsghdr { - struct msghdr msg_hdr; /* Message header */ - unsigned int msg_len; /* Number of bytes transmitted */ -}; -extern int st_sendmmsg(st_netfd_t fd, struct st_mmsghdr *msgvec, unsigned int vlen, int flags, st_utime_t timeout); - extern st_netfd_t st_open(const char *path, int oflags, mode_t mode); #ifdef DEBUG diff --git a/trunk/auto/depends.sh b/trunk/auto/depends.sh index cda4091ea..c58f81d53 100755 --- a/trunk/auto/depends.sh +++ b/trunk/auto/depends.sh @@ -348,14 +348,6 @@ fi if [[ $SRS_OSX == YES ]]; then _ST_MAKE=darwin-debug && _ST_EXTRA_CFLAGS="-DMD_HAVE_KQUEUE" && _ST_LD=${SRS_TOOL_CC} && _ST_OBJ="DARWIN_`uname -r`_DBG" fi -# For UDP sendmmsg, disable it if not suppported. -if [[ $SRS_SENDMMSG == YES ]]; then - echo "Build ST with UDP sendmmsg support." - _ST_EXTRA_CFLAGS="$_ST_EXTRA_CFLAGS -DMD_HAVE_SENDMMSG -D_GNU_SOURCE" -else - echo "Build ST without UDP sendmmsg support." - _ST_EXTRA_CFLAGS="$_ST_EXTRA_CFLAGS -UMD_HAVE_SENDMMSG -U_GNU_SOURCE" -fi # Whether enable debug stats. if [[ $SRS_DEBUG_STATS == YES ]]; then _ST_EXTRA_CFLAGS="$_ST_EXTRA_CFLAGS -DDEBUG_STATS" diff --git a/trunk/auto/options.sh b/trunk/auto/options.sh index eb4433ecb..284965715 100755 --- a/trunk/auto/options.sh +++ b/trunk/auto/options.sh @@ -128,7 +128,6 @@ SRS_EXTRA_FLAGS= # Performance optimize. SRS_NASM=YES SRS_SRTP_ASM=YES -SRS_SENDMMSG=NO SRS_DEBUG=NO SRS_DEBUG_STATS=NO @@ -177,7 +176,6 @@ Performance: @see https://blog.csdn.net/win_lin/article/details/5 --nasm=on|off Whether build FFMPEG for RTC with nasm. Default: $(value2switch $SRS_NASM) --srtp-nasm=on|off Whether build SRTP with ASM(openssl-asm), requires RTC and openssl-1.0.*. Default: $(value2switch $SRS_SRTP_ASM) - --sendmmsg=on|off Whether enable UDP sendmmsg. Default: $(value2switch $SRS_SENDMMSG). @see http://man7.org/linux/man-pages/man2/sendmmsg.2.html Toolchain options: @see https://github.com/ossrs/srs/issues/1547#issuecomment-576078411 --static=on|off Whether add '-static' to link options. Default: $(value2switch $SRS_STATIC) @@ -230,8 +228,6 @@ function parse_user_option() { --x86-64) SRS_X86_X64=YES ;; --osx) SRS_OSX=YES ;; - --sendmmsg) if [[ $value == off ]]; then SRS_SENDMMSG=NO; else SRS_SENDMMSG=YES; fi ;; - --without-srtp-nasm) SRS_SRTP_ASM=NO ;; --with-srtp-nasm) SRS_SRTP_ASM=YES ;; --srtp-nasm) if [[ $value == off ]]; then SRS_SRTP_ASM=NO; else SRS_SRTP_ASM=YES; fi ;; @@ -523,11 +519,6 @@ function apply_detail_options() { echo "Use openssl-1.0 for SRTP-ASM." SRS_SSL_1_0=YES fi - - if [[ $SRS_OSX == YES && $SRS_SENDMMSG == YES ]]; then - echo "Disable sendmmsg for OSX" - SRS_SENDMMSG=NO - fi } apply_detail_options @@ -562,7 +553,6 @@ function regenerate_options() { SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --ffmpeg-fit=$(value2switch $SRS_FFMPEG_FIT)" SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --nasm=$(value2switch $SRS_NASM)" SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --srtp-nasm=$(value2switch $SRS_SRTP_ASM)" - SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --sendmmsg=$(value2switch $SRS_SENDMMSG)" SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --clean=$(value2switch $SRS_CLEAN)" SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --gperf=$(value2switch $SRS_GPERF)" SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --gmc=$(value2switch $SRS_GPERF_MC)" diff --git a/trunk/src/app/srs_app_hybrid.cpp b/trunk/src/app/srs_app_hybrid.cpp index 9a310b2ae..446593ee5 100644 --- a/trunk/src/app/srs_app_hybrid.cpp +++ b/trunk/src/app/srs_app_hybrid.cpp @@ -66,14 +66,10 @@ extern unsigned long long _st_stat_recvmsg; extern unsigned long long _st_stat_recvmsg_eagain; extern unsigned long long _st_stat_sendmsg; extern unsigned long long _st_stat_sendmsg_eagain; -extern unsigned long long _st_stat_sendmmsg; -extern unsigned long long _st_stat_sendmmsg_eagain; SrsPps* _srs_pps_recvmsg = new SrsPps(); SrsPps* _srs_pps_recvmsg_eagain = new SrsPps(); SrsPps* _srs_pps_sendmsg = new SrsPps(); SrsPps* _srs_pps_sendmsg_eagain = new SrsPps(); -SrsPps* _srs_pps_sendmmsg = new SrsPps(); -SrsPps* _srs_pps_sendmmsg_eagain = new SrsPps(); extern unsigned long long _st_stat_epoll; extern unsigned long long _st_stat_epoll_zero; @@ -400,9 +396,8 @@ srs_error_t SrsHybridServer::notify(int event, srs_utime_t interval, srs_utime_t #if defined(SRS_DEBUG) && defined(SRS_DEBUG_STATS) _srs_pps_recvmsg->update(_st_stat_recvmsg); _srs_pps_recvmsg_eagain->update(_st_stat_recvmsg_eagain); _srs_pps_sendmsg->update(_st_stat_sendmsg); _srs_pps_sendmsg_eagain->update(_st_stat_sendmsg_eagain); - _srs_pps_sendmmsg->update(_st_stat_sendmmsg); _srs_pps_sendmmsg_eagain->update(_st_stat_sendmmsg_eagain); - if (_srs_pps_recvmsg->r10s() || _srs_pps_recvmsg_eagain->r10s() || _srs_pps_sendmsg->r10s() || _srs_pps_sendmsg_eagain->r10s() || _srs_pps_sendmmsg->r10s() || _srs_pps_sendmmsg_eagain->r10s()) { - snprintf(buf, sizeof(buf), ", msg=%d,%d,%d,%d,%d,%d", _srs_pps_recvmsg->r10s(), _srs_pps_recvmsg_eagain->r10s(), _srs_pps_sendmsg->r10s(), _srs_pps_sendmsg_eagain->r10s(), _srs_pps_sendmmsg->r10s(), _srs_pps_sendmmsg_eagain->r10s()); + if (_srs_pps_recvmsg->r10s() || _srs_pps_recvmsg_eagain->r10s() || _srs_pps_sendmsg->r10s() || _srs_pps_sendmsg_eagain->r10s()) { + snprintf(buf, sizeof(buf), ", msg=%d,%d,%d,%d", _srs_pps_recvmsg->r10s(), _srs_pps_recvmsg_eagain->r10s(), _srs_pps_sendmsg->r10s(), _srs_pps_sendmsg_eagain->r10s()); msg_desc = buf; } #endif diff --git a/trunk/src/protocol/srs_service_st.cpp b/trunk/src/protocol/srs_service_st.cpp index a4189dd8e..6c55c586b 100644 --- a/trunk/src/protocol/srs_service_st.cpp +++ b/trunk/src/protocol/srs_service_st.cpp @@ -431,11 +431,6 @@ int srs_sendmsg(srs_netfd_t stfd, const struct msghdr *msg, int flags, srs_utime return st_sendmsg((st_netfd_t)stfd, msg, flags, (st_utime_t)timeout); } -int srs_sendmmsg(srs_netfd_t stfd, struct srs_mmsghdr *msgvec, unsigned int vlen, int flags, srs_utime_t timeout) -{ - return st_sendmmsg((st_netfd_t)stfd, (struct st_mmsghdr*)msgvec, vlen, flags, (st_utime_t)timeout); -} - srs_netfd_t srs_accept(srs_netfd_t stfd, struct sockaddr *addr, int *addrlen, srs_utime_t timeout) { return (srs_netfd_t)st_accept((st_netfd_t)stfd, addr, addrlen, (st_utime_t)timeout); diff --git a/trunk/src/protocol/srs_service_st.hpp b/trunk/src/protocol/srs_service_st.hpp index bcad9c8b9..3d51675e8 100644 --- a/trunk/src/protocol/srs_service_st.hpp +++ b/trunk/src/protocol/srs_service_st.hpp @@ -95,14 +95,6 @@ extern int srs_sendto(srs_netfd_t stfd, void *buf, int len, const struct sockadd extern int srs_recvmsg(srs_netfd_t stfd, struct msghdr *msg, int flags, srs_utime_t timeout); extern int srs_sendmsg(srs_netfd_t stfd, const struct msghdr *msg, int flags, srs_utime_t timeout); -// @see http://man7.org/linux/man-pages/man2/sendmmsg.2.html -#include -struct srs_mmsghdr { - struct msghdr msg_hdr; /* Message header */ - unsigned int msg_len; /* Number of bytes transmitted */ -}; -extern int srs_sendmmsg(srs_netfd_t stfd, struct srs_mmsghdr *msgvec, unsigned int vlen, int flags, srs_utime_t timeout); - extern srs_netfd_t srs_accept(srs_netfd_t stfd, struct sockaddr *addr, int *addrlen, srs_utime_t timeout); extern ssize_t srs_read(srs_netfd_t stfd, void *buf, size_t nbyte, srs_utime_t timeout); From 81060a17e637d1fabb4cb1f43d14df95354e8751 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 26 Feb 2021 10:20:22 +0800 Subject: [PATCH 020/102] Build: Add gcc version in cache directory --- trunk/auto/setup_variables.sh | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/trunk/auto/setup_variables.sh b/trunk/auto/setup_variables.sh index 0fcc1a67a..cf26ea0c3 100755 --- a/trunk/auto/setup_variables.sh +++ b/trunk/auto/setup_variables.sh @@ -7,8 +7,13 @@ OS_PREFIX="Platform" # Build platform cache. SRS_PLATFORM="${OS_PREFIX}-${OS_KERNEL_NAME}-${OS_KERNRL_RELEASE}" -if [[ ${SRS_BUILD_TAG} != "" ]]; then - SRS_PLATFORM="${SRS_PLATFORM}-${SRS_BUILD_TAG}" +# Build platform cache with gcc version. +if [[ $OS_KERNEL_NAME == Darwin ]]; then + GCC_VERSION="Clang$(gcc --version 2>/dev/null|grep clang|awk '{print $4}')" + SRS_PLATFORM="${SRS_PLATFORM}-${GCC_VERSION}" +else + GCC_VERSION="GCC$(gcc --version 2>/dev/null|grep gcc|awk '{print $3}')" + SRS_PLATFORM="${SRS_PLATFORM}-${GCC_VERSION}" fi # Use isolate cache for different SRS version. SRS_PLATFORM="${SRS_PLATFORM}-SRS4" From 0cb125e53d5bfececf2685420dc24b58401dfc79 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 26 Feb 2021 11:18:15 +0800 Subject: [PATCH 021/102] RTC: Refine publisher memory allocate, by packet itself --- trunk/src/app/srs_app_rtc_conn.cpp | 18 +++++------------- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 20 ++++++++++++++++++++ trunk/src/kernel/srs_kernel_rtc_rtp.hpp | 5 +++++ 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index ffcf053d5..829a447f0 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1193,19 +1193,11 @@ srs_error_t SrsRtcPublishStream::on_rtp_plaintext(char* plaintext, int nb_plaint SrsRtpPacket2* pkt = new SrsRtpPacket2(); SrsAutoFree(SrsRtpPacket2, pkt); - if (true) { - pkt->set_decode_handler(this); - pkt->set_extension_types(&extension_types_); - pkt->shared_msg = new SrsSharedPtrMessage(); - - char* buf = new char[nb_plaintext]; - memcpy(buf, plaintext, nb_plaintext); - pkt->shared_msg->wrap(buf, nb_plaintext); - - SrsBuffer b(buf, nb_plaintext); - if ((err = pkt->decode(&b)) != srs_success) { - return srs_error_wrap(err, "decode rtp packet"); - } + pkt->set_decode_handler(this); + pkt->set_extension_types(&extension_types_); + pkt->wrap(plaintext, nb_plaintext); + if ((err = pkt->decode(pkt->cache_buffer())) != srs_success) { + return srs_error_wrap(err, "decode rtp packet"); } // For source to consume packet. diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index ab2d07a34..86ee1770c 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -768,6 +768,7 @@ SrsRtpPacket2::SrsRtpPacket2() nalu_type = SrsAvcNaluTypeReserved; shared_msg = NULL; + cache_buffer_ = NULL; frame_type = SrsFrameTypeReserved; cached_payload_size = 0; @@ -778,6 +779,25 @@ SrsRtpPacket2::~SrsRtpPacket2() { srs_freep(payload); srs_freep(shared_msg); + srs_freep(cache_buffer_); +} + +void SrsRtpPacket2::wrap(char* data, int size) +{ + srs_freep(shared_msg); + shared_msg = new SrsSharedPtrMessage(); + + char* buf = new char[size]; + memcpy(buf, data, size); + shared_msg->wrap(buf, size); + + srs_freep(cache_buffer_); + cache_buffer_ = new SrsBuffer(buf, size); +} + +SrsBuffer* SrsRtpPacket2::cache_buffer() +{ + return cache_buffer_; } void SrsRtpPacket2::set_padding(int size) diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index 741a4fafb..9f6d2bb83 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -268,6 +268,7 @@ class SrsRtpPacket2 public: SrsRtpHeader header; ISrsRtpPayloader* payload; + SrsBuffer* cache_buffer_; // Helper fields. public: // The first byte as nalu type, for video decoder only. @@ -285,6 +286,10 @@ private: public: SrsRtpPacket2(); virtual ~SrsRtpPacket2(); +public: + // Wrap buffer to shared_message, which is managed by us. + void wrap(char* data, int size); + SrsBuffer* cache_buffer(); public: // Set the padding of RTP packet. void set_padding(int size); From b2d546156e8f79edaa60089abf3b0b93e9817e1c Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 26 Feb 2021 12:25:35 +0800 Subject: [PATCH 022/102] RTC: Refine RTP packet api, keep shared message to private --- trunk/src/app/srs_app_rtc_jitbuffer.cpp | 220 ------------------------ trunk/src/app/srs_app_rtc_jitbuffer.hpp | 1 - trunk/src/app/srs_app_rtc_source.cpp | 20 +-- trunk/src/kernel/srs_kernel_buffer.cpp | 10 +- trunk/src/kernel/srs_kernel_buffer.hpp | 2 + trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 26 ++- trunk/src/kernel/srs_kernel_rtc_rtp.hpp | 14 +- 7 files changed, 50 insertions(+), 243 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_jitbuffer.cpp b/trunk/src/app/srs_app_rtc_jitbuffer.cpp index cf3c172e2..f030932d2 100644 --- a/trunk/src/app/srs_app_rtc_jitbuffer.cpp +++ b/trunk/src/app/srs_app_rtc_jitbuffer.cpp @@ -1273,226 +1273,6 @@ SrsRtpFrameBufferEnum SrsRtpJitterBuffer::InsertPacket(uint16_t seq, uint32_t ts return buffer_state; } - -SrsRtpFrameBufferEnum SrsRtpJitterBuffer::InsertPacket2(const SrsRtpPacket2 &pkt, - bool* retransmitted) -{ - bool singlenual = false; - H264PacketizationTypes packetyType = kH264SingleNalu; - - //char *buf = pkt.shared_msg->payload; //rtp packet data - //int size = pkt.shared_msg->size; //rtp size - - //rtp header: total size - rtp payload size - int rtp_header_size = pkt.shared_msg->size - pkt.payload->nb_bytes(); - - char *rtp_payload_buf = pkt.shared_msg->payload + rtp_header_size; //rtp payload data - int rtp_payload_size = pkt.shared_msg->size - rtp_header_size; //rtp payload size; - - bool is_first_packet_in_frame = false; - - if (rtp_payload_size == 0){ - //B0(1011):pad+ext, A0(1010):pad - if ((pkt.shared_msg->payload[0] & 0xFF) == 0xB0 || (pkt.shared_msg->payload[0] & 0xFF) == 0xA0){ - //uint8_t padding_length = (uint8_t)(pkt.shared_msg->payload[pkt.shared_msg->size-1] & 0xFF); - srs_info("RTP: jitbuffer padding packet ts:%u, seq:%u, payload size:%d, padding size:%d", - pkt.header.get_timestamp(),pkt.header.get_sequence(), - rtp_payload_size, padding_length); - } - return kNoError; - } - - SrsAvcNaluType nal_unit_type = SrsAvcNaluTypeReserved; - FrameType frameType = kVideoFrameDelta; - - int8_t v = (uint8_t)pkt.nalu_type; - if (v == kStapA) { - singlenual = false; - packetyType = kH264StapA; - - is_first_packet_in_frame = true; - - SrsRtpSTAPPayload *payload = (SrsRtpSTAPPayload*)pkt.payload; - if (payload->get_sps() != NULL){ - nal_unit_type = SrsAvcNaluTypeSPS; - frameType = kVideoFrameKey; - } - } else if (v == kFuA) { - SrsRtpFUAPayload2 *payload = (SrsRtpFUAPayload2*)pkt.payload; - int8_t nalu_byte0 = ((int8_t)payload->nri & 0xE0) | ((int8_t)payload->nalu_type & 0x1F); - nal_unit_type = (SrsAvcNaluType)(nalu_byte0 & 0x1f); - - if (nal_unit_type == SrsAvcNaluTypeIDR){ - frameType = kVideoFrameKey; - } - - if (payload->start){ - //xx xx .... - //xx nalu .... - rtp_payload_buf[1] = nalu_byte0; - - //nalu .... - rtp_payload_buf = rtp_payload_buf + 1; - rtp_payload_size = rtp_payload_size - 1; - - is_first_packet_in_frame = true; - }else { - //xx xx .... - //.... - rtp_payload_buf = rtp_payload_buf + 2; - rtp_payload_size = rtp_payload_size - 2; - } - - singlenual = false; - packetyType = kH264FuA; - - } else { - singlenual = true; - packetyType = kH264SingleNalu; - is_first_packet_in_frame = true; - } - - const VCMPacket packet((const uint8_t*)rtp_payload_buf, rtp_payload_size, - pkt.header.get_sequence(), pkt.header.get_timestamp(), pkt.header.get_marker(), - packetyType, kRtpVideoH264, singlenual, is_first_packet_in_frame, frameType); - - ++num_packets_; - - if (num_packets_ == 1) { - time_first_packet_ms_ = srs_update_system_time(); - } - - //Does this packet belong to an old frame? - // if (last_decoded_state_.IsOldPacket(&packet)) { - - // //return kOldPacket; - // } - - //num_consecutive_old_packets_ = 0; - - SrsRtpFrameBuffer* frame; - FrameList* frame_list; - - const SrsRtpFrameBufferEnum error = GetFrameByRtpPacket(packet, &frame, &frame_list); - - if (error != kNoError) { - return error; - } - - - //srs_utime_t now_ms = srs_update_system_time(); - - FrameData frame_data; - frame_data.rtt_ms = 0; //rtt_ms_; - frame_data.rolling_average_packets_per_frame = 25;//average_packets_per_frame_; - - SrsRtpFrameBufferEnum buffer_state = frame->InsertPacket(packet, frame_data); - - if (buffer_state > 0) { - incoming_bit_count_ += packet.sizeBytes << 3; - - if (first_packet_since_reset_) { - latest_received_sequence_number_ = packet.seqNum; - first_packet_since_reset_ = false; - } else { - // if (IsPacketRetransmitted(packet)) { - // frame->IncrementNackCount(); - // } - - UpdateNackList(packet.seqNum); - - latest_received_sequence_number_ = LatestSequenceNumber( - latest_received_sequence_number_, packet.seqNum); - } - } - - // Is the frame already in the decodable list? - bool continuous = IsContinuous(*frame); - - switch (buffer_state) { - case kGeneralError: - case kTimeStampError: - case kSizeError: { - free_frames_.push_back(frame); - break; - } - - case kCompleteSession: { - //CountFrame(*frame); - // if (previous_state != kStateDecodable && - // previous_state != kStateComplete) { - // /*CountFrame(*frame);*/ //????????????????????�?? by ylr - // if (continuous) { - // // Signal that we have a complete session. - // frame_event_->Set(); - // } - // } - } - - // Note: There is no break here - continuing to kDecodableSession. - case kDecodableSession: { - // *retransmitted = (frame->GetNackCount() > 0); - - if (true || continuous) { - decodable_frames_.InsertFrame(frame); - FindAndInsertContinuousFrames(*frame); - } else { - incomplete_frames_.InsertFrame(frame); - - // If NACKs are enabled, keyframes are triggered by |GetNackList|. - // if (nack_mode_ == kNoNack && NonContinuousOrIncompleteDuration() > - // 90 * kMaxDiscontinuousFramesTime) { - // return kFlushIndicator; - // } - } - - break; - } - - case kIncomplete: { - if (frame->GetState() == kStateEmpty && - last_decoded_state_.UpdateEmptyFrame(frame)) { - free_frames_.push_back(frame); - return kNoError; - } else { - incomplete_frames_.InsertFrame(frame); - - // If NACKs are enabled, keyframes are triggered by |GetNackList|. - // if (nack_mode_ == kNoNack && NonContinuousOrIncompleteDuration() > - // 90 * kMaxDiscontinuousFramesTime) { - // return kFlushIndicator; - // } - } - - break; - } - - case kNoError: - case kOutOfBoundsPacket: - case kDuplicatePacket: { - // Put back the frame where it came from. - if (frame_list != NULL) { - frame_list->InsertFrame(frame); - } else { - free_frames_.push_back(frame); - } - - ++num_duplicated_packets_; - break; - } - - case kFlushIndicator:{ - free_frames_.push_back(frame); - } - return kFlushIndicator; - - default: - assert(false); - } - - return buffer_state; -} - // Gets frame to use for this timestamp. If no match, get empty frame. SrsRtpFrameBufferEnum SrsRtpJitterBuffer::GetFrameByRtpPacket(const VCMPacket& packet, SrsRtpFrameBuffer** frame, diff --git a/trunk/src/app/srs_app_rtc_jitbuffer.hpp b/trunk/src/app/srs_app_rtc_jitbuffer.hpp index 8a03efa67..a7682a2b9 100644 --- a/trunk/src/app/srs_app_rtc_jitbuffer.hpp +++ b/trunk/src/app/srs_app_rtc_jitbuffer.hpp @@ -413,7 +413,6 @@ public: public: srs_error_t start(); void Reset(); - SrsRtpFrameBufferEnum InsertPacket2(const SrsRtpPacket2 &pkt, bool* retransmitted); SrsRtpFrameBufferEnum InsertPacket(uint16_t seq, uint32_t ts, bool maker, char *buf, int size, bool* retransmitted); void ReleaseFrame(SrsRtpFrameBuffer* frame); diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index 95e0cc17e..c6a66e8df 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -818,12 +818,8 @@ srs_error_t SrsRtcFromRtmpBridger::package_opus(char* data, int size, SrsRtpPack SrsRtpRawPayload* raw = new SrsRtpRawPayload(); pkt->payload = raw; - raw->payload = new char[size]; + raw->payload = pkt->wrap(data, size); raw->nn_payload = size; - memcpy(raw->payload, data, size); - - pkt->shared_msg = new SrsSharedPtrMessage(); - pkt->shared_msg->wrap(raw->payload, size); *ppkt = pkt; @@ -964,9 +960,7 @@ srs_error_t SrsRtcFromRtmpBridger::package_stap_a(SrsRtcStream* source, SrsShare // Copy the SPS/PPS bytes, because it may change. int size = (int)(sps.size() + pps.size()); - char* payload = new char[size]; - pkt->shared_msg = new SrsSharedPtrMessage(); - pkt->shared_msg->wrap(payload, size); + char* payload = pkt->wrap(size); if (true) { SrsSample* sample = new SrsSample(); @@ -1038,7 +1032,7 @@ srs_error_t SrsRtcFromRtmpBridger::package_nalus(SrsSharedPtrMessage* msg, const pkt->header.set_sequence(video_sequence++); pkt->header.set_timestamp(msg->timestamp * 90); pkt->payload = raw; - pkt->shared_msg = msg->copy(); + pkt->wrap(msg); pkts.push_back(pkt); } else { // We must free it, should never use RTP packets to free it, @@ -1077,7 +1071,7 @@ srs_error_t SrsRtcFromRtmpBridger::package_nalus(SrsSharedPtrMessage* msg, const fua->end = bool(i == num_of_packet - 1); pkt->payload = fua; - pkt->shared_msg = msg->copy(); + pkt->wrap(msg); pkts.push_back(pkt); nb_left -= packet_size; @@ -1105,7 +1099,8 @@ srs_error_t SrsRtcFromRtmpBridger::package_single_nalu(SrsSharedPtrMessage* msg, raw->payload = sample->bytes; raw->nn_payload = sample->size; - pkt->shared_msg = msg->copy(); + pkt->wrap(msg); + pkts.push_back(pkt); return err; @@ -1142,7 +1137,8 @@ srs_error_t SrsRtcFromRtmpBridger::package_fu_a(SrsSharedPtrMessage* msg, SrsSam fua->payload = p; fua->size = packet_size; - pkt->shared_msg = msg->copy(); + pkt->wrap(msg); + pkts.push_back(pkt); p += packet_size; diff --git a/trunk/src/kernel/srs_kernel_buffer.cpp b/trunk/src/kernel/srs_kernel_buffer.cpp index 255357878..ff5cdbeb8 100644 --- a/trunk/src/kernel/srs_kernel_buffer.cpp +++ b/trunk/src/kernel/srs_kernel_buffer.cpp @@ -49,15 +49,19 @@ SrsBuffer::SrsBuffer(char* b, int nn) { p = bytes = b; nb_bytes = nn; - - // TODO: support both little and big endian. - srs_assert(srs_is_little_endian()); } SrsBuffer::~SrsBuffer() { } +SrsBuffer* SrsBuffer::copy() +{ + SrsBuffer* cp = new SrsBuffer(bytes, nb_bytes); + cp->p = p; + return cp; +} + char* SrsBuffer::data() { return bytes; diff --git a/trunk/src/kernel/srs_kernel_buffer.hpp b/trunk/src/kernel/srs_kernel_buffer.hpp index 061ea8338..c406d0906 100644 --- a/trunk/src/kernel/srs_kernel_buffer.hpp +++ b/trunk/src/kernel/srs_kernel_buffer.hpp @@ -109,6 +109,8 @@ public: SrsBuffer(char* b, int nn); ~SrsBuffer(); public: + // Copy the object, keep position of buffer. + SrsBuffer* copy(); // Get the data and head of buffer. // current-bytes = head() = data() + pos() char* data(); diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index 86ee1770c..ec028bbfa 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -782,20 +782,39 @@ SrsRtpPacket2::~SrsRtpPacket2() srs_freep(cache_buffer_); } -void SrsRtpPacket2::wrap(char* data, int size) +char* SrsRtpPacket2::wrap(int size) { srs_freep(shared_msg); shared_msg = new SrsSharedPtrMessage(); char* buf = new char[size]; - memcpy(buf, data, size); shared_msg->wrap(buf, size); srs_freep(cache_buffer_); cache_buffer_ = new SrsBuffer(buf, size); + + return buf; } -SrsBuffer* SrsRtpPacket2::cache_buffer() +char* SrsRtpPacket2::wrap(char* data, int size) +{ + char* buf = wrap(size); + memcpy(buf, data, size); + return buf; +} + +char* SrsRtpPacket2::wrap(SrsSharedPtrMessage* msg) +{ + srs_freep(shared_msg); + shared_msg = msg->copy(); + + srs_freep(cache_buffer_); + cache_buffer_ = new SrsBuffer(msg->payload, msg->size); + + return msg->payload; +} + +SrsBuffer* SrsRtpPacket2::cache_buffer() const { return cache_buffer_; } @@ -835,6 +854,7 @@ SrsRtpPacket2* SrsRtpPacket2::copy() cp->nalu_type = nalu_type; cp->shared_msg = shared_msg? shared_msg->copy():NULL; + cp->cache_buffer_ = cache_buffer_? cache_buffer_->copy():NULL; cp->frame_type = frame_type; cp->cached_payload_size = cached_payload_size; diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index 9f6d2bb83..920e91588 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -268,13 +268,15 @@ class SrsRtpPacket2 public: SrsRtpHeader header; ISrsRtpPayloader* payload; +private: + // The buffer bind to the shared message. SrsBuffer* cache_buffer_; + // The original shared message, all RTP packets can refer to its data. + SrsSharedPtrMessage* shared_msg; // Helper fields. public: // The first byte as nalu type, for video decoder only. SrsAvcNaluType nalu_type; - // The original shared message, all RTP packets can refer to its data. - SrsSharedPtrMessage* shared_msg; // The frame type, for RTMP bridger or SFU source. SrsFrameType frame_type; // Fast cache for performance. @@ -288,8 +290,12 @@ public: virtual ~SrsRtpPacket2(); public: // Wrap buffer to shared_message, which is managed by us. - void wrap(char* data, int size); - SrsBuffer* cache_buffer(); + char* wrap(int size); + char* wrap(char* data, int size); + // Wrap the shared message, we copy it. + char* wrap(SrsSharedPtrMessage* msg); + // Get the cache buffer which binds to the shared message. + SrsBuffer* cache_buffer() const; public: // Set the padding of RTP packet. void set_padding(int size); From bde86a2b234b1ec3157ad6fd910ffca3cdd98941 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 26 Feb 2021 13:11:56 +0800 Subject: [PATCH 023/102] RTC: Refine RTP packet buffer allocate, align to about 1500 bytes --- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index ec028bbfa..0fa2dc689 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -784,11 +784,19 @@ SrsRtpPacket2::~SrsRtpPacket2() char* SrsRtpPacket2::wrap(int size) { + // If the buffer is large enough, reuse it. + if (shared_msg && shared_msg->size >= size) { + return shared_msg->payload; + } + + // Create buffer if empty or not large enough. srs_freep(shared_msg); shared_msg = new SrsSharedPtrMessage(); - char* buf = new char[size]; - shared_msg->wrap(buf, size); + // For RTC, we use larger under-layer buffer for each packet. + int nb_buffer = srs_max(size, kRtpPacketSize); + char* buf = new char[nb_buffer]; + shared_msg->wrap(buf, nb_buffer); srs_freep(cache_buffer_); cache_buffer_ = new SrsBuffer(buf, size); From 86f43d4f72f97539011f5fd22df4443fe040053f Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 26 Feb 2021 16:21:59 +0800 Subject: [PATCH 024/102] RTC: Support RTP packet cache manager --- trunk/conf/full.conf | 3 + trunk/src/app/srs_app_config.cpp | 19 ++- trunk/src/app/srs_app_config.hpp | 1 + trunk/src/app/srs_app_rtc_server.cpp | 5 +- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 172 +++++++++++++++++++++--- trunk/src/kernel/srs_kernel_rtc_rtp.hpp | 49 ++++++- 6 files changed, 229 insertions(+), 20 deletions(-) diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 4e0c76424..b850003e5 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -497,6 +497,9 @@ rtc_server { # then system queue is 2000*4 = 8k, user can incrase reuseport to incrase the queue. # default: 2000 queue_length 2000; + # Whether enable the RTP packet cache. + # default: off + rtp_cache off; # The black-hole to copy packet to, for debugging. # For example, when debugging Chrome publish stream, the received packets are encrypted cipher, # we can set the publisher black-hole, SRS will copy the plaintext packets to black-hole, and diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index efd7e236b..52fadae34 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -3651,7 +3651,7 @@ srs_error_t SrsConfig::check_normal_config() string n = conf->at(i)->name; if (n != "enabled" && n != "listen" && n != "dir" && n != "candidate" && n != "ecdsa" && n != "encrypt" && n != "reuseport" && n != "merge_nalus" && n != "perf_stat" && n != "black_hole" - && n != "ip_family") { + && n != "ip_family" && n != "rtp_cache") { return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal rtc_server.%s", n.c_str()); } } @@ -4902,6 +4902,23 @@ bool SrsConfig::get_rtc_server_perf_stat() return SRS_CONF_PERFER_TRUE(conf->arg0()); } +bool SrsConfig::get_rtc_server_rtp_cache() +{ + static bool DEFAULT = false; + + SrsConfDirective* conf = root->get("rtc_server"); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("rtp_cache"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + return SRS_CONF_PERFER_FALSE(conf->arg0()); +} + bool SrsConfig::get_rtc_server_black_hole() { static bool DEFAULT = false; diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 507467073..a6cebc7c3 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -534,6 +534,7 @@ public: virtual int get_rtc_server_reuseport(); virtual bool get_rtc_server_merge_nalus(); virtual bool get_rtc_server_perf_stat(); + virtual bool get_rtc_server_rtp_cache(); virtual bool get_rtc_server_black_hole(); virtual std::string get_rtc_server_black_hole_addr(); private: diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index 2315e3d10..d4996de4c 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -283,7 +283,10 @@ srs_error_t SrsRtcServer::initialize() return srs_error_wrap(err, "black hole"); } - srs_trace("RTC server init ok"); + bool rtp_cache = _srs_config->get_rtc_server_rtp_cache(); + _srs_rtp_cache->set_enabled(rtp_cache); + + srs_trace("RTC server init ok, rtp_cache=%d", rtp_cache); return err; } diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index 0fa2dc689..352fed02e 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -162,13 +162,18 @@ int32_t srs_seq_distance(uint16_t value, uint16_t pre_value) SrsRtpExtensionTypes::SrsRtpExtensionTypes() { - memset(ids_, kRtpExtensionNone, sizeof(ids_)); + reset(); } SrsRtpExtensionTypes::~SrsRtpExtensionTypes() { } +void SrsRtpExtensionTypes::reset() +{ + memset(ids_, kRtpExtensionNone, sizeof(ids_)); +} + bool SrsRtpExtensionTypes::register_by_uri(int id, std::string uri) { for (int i = 0; i < (int)(sizeof(kExtensions)/sizeof(kExtensions[0])); ++i) { @@ -201,14 +206,22 @@ SrsRtpExtensionType SrsRtpExtensionTypes::get_type(int id) const -SrsRtpExtensionTwcc::SrsRtpExtensionTwcc(): has_twcc_(false), id_(0), sn_(0) +SrsRtpExtensionTwcc::SrsRtpExtensionTwcc() { + reset(); } SrsRtpExtensionTwcc::~SrsRtpExtensionTwcc() { } +void SrsRtpExtensionTwcc::reset() +{ + has_twcc_ = false; + id_ = 0; + sn_ = 0; +} + bool SrsRtpExtensionTwcc::has_twcc_ext() { return has_twcc_; @@ -286,8 +299,20 @@ void SrsRtpExtensionTwcc::set_sn(uint16_t sn) has_twcc_ = true; } -SrsRtpExtensionOneByte::SrsRtpExtensionOneByte() : has_ext_(false), id_(0), value_(0) +SrsRtpExtensionOneByte::SrsRtpExtensionOneByte() { + reset(); +} + +SrsRtpExtensionOneByte::~SrsRtpExtensionOneByte() +{ +} + +void SrsRtpExtensionOneByte::reset() +{ + has_ext_ = false; + id_ = 0; + value_ = 0; } void SrsRtpExtensionOneByte::set_id(int id) @@ -338,14 +363,26 @@ srs_error_t SrsRtpExtensionOneByte::encode(SrsBuffer* buf) return err; } -SrsRtpExtensions::SrsRtpExtensions() : has_ext_(false) +SrsRtpExtensions::SrsRtpExtensions() { + reset(); } SrsRtpExtensions::~SrsRtpExtensions() { } +void SrsRtpExtensions::reset() +{ + if (has_ext_) { + types_.reset(); + twcc_.reset(); + audio_level_.reset(); + } + + has_ext_ = false; +} + srs_error_t SrsRtpExtensions::decode(SrsBuffer* buf) { srs_error_t err = srs_success; @@ -524,6 +561,15 @@ srs_error_t SrsRtpExtensions::set_audio_level(int id, uint8_t level) } SrsRtpHeader::SrsRtpHeader() +{ + reset(); +} + +SrsRtpHeader::~SrsRtpHeader() +{ +} + +void SrsRtpHeader::reset() { padding_length = 0; cc = 0; @@ -532,11 +578,10 @@ SrsRtpHeader::SrsRtpHeader() sequence = 0; timestamp = 0; ssrc = 0; + memset(csrc, 0, sizeof(csrc)); ignore_padding_ = false; -} -SrsRtpHeader::~SrsRtpHeader() -{ + extensions_.reset(); } srs_error_t SrsRtpHeader::decode(SrsBuffer* buf) @@ -764,13 +809,10 @@ ISrsRtpPacketDecodeHandler::~ISrsRtpPacketDecodeHandler() SrsRtpPacket2::SrsRtpPacket2() { payload = NULL; - decode_handler = NULL; - - nalu_type = SrsAvcNaluTypeReserved; shared_msg = NULL; cache_buffer_ = NULL; - frame_type = SrsFrameTypeReserved; - cached_payload_size = 0; + + reset(); ++_srs_pps_objs_rtps->sugar; } @@ -782,10 +824,33 @@ SrsRtpPacket2::~SrsRtpPacket2() srs_freep(cache_buffer_); } +void SrsRtpPacket2::reset() +{ + nalu_type = SrsAvcNaluTypeReserved; + frame_type = SrsFrameTypeReserved; + cached_payload_size = 0; + decode_handler = NULL; + + header.reset(); + + // We do not cache the payload, it will be created even + // we cache it, because it only stores pointers to the shared message, + // and it's different for each packet. + srs_freep(payload); + + // We should reset the cached buffer. + if (cache_buffer_) { + cache_buffer_->skip(-1 * cache_buffer_->pos()); + } +} + char* SrsRtpPacket2::wrap(int size) { // If the buffer is large enough, reuse it. if (shared_msg && shared_msg->size >= size) { + // The size maybe changed, so we MUST reset it. + cache_buffer_->set_size(size); + return shared_msg->payload; } @@ -798,6 +863,7 @@ char* SrsRtpPacket2::wrap(int size) char* buf = new char[nb_buffer]; shared_msg->wrap(buf, nb_buffer); + // The size of buffer must equal to the actual size. srs_freep(cache_buffer_); cache_buffer_ = new SrsBuffer(buf, size); @@ -827,6 +893,18 @@ SrsBuffer* SrsRtpPacket2::cache_buffer() const return cache_buffer_; } +bool SrsRtpPacket2::try_recycle() +{ + // When recycling, and there is references about he shared buffer, we must free + // the shared message(may not free the buffer) to stop reuse the shared message. + if (shared_msg && shared_msg->count() > 0) { + srs_freep(shared_msg); + } + + // OK, allow to recycle this object. + return true; +} + void SrsRtpPacket2::set_padding(int size) { header.set_padding(size); @@ -855,14 +933,13 @@ bool SrsRtpPacket2::is_audio() SrsRtpPacket2* SrsRtpPacket2::copy() { - SrsRtpPacket2* cp = new SrsRtpPacket2(); + SrsRtpPacket2* cp = _srs_rtp_cache->allocate(); cp->header = header; cp->payload = payload? payload->copy():NULL; cp->nalu_type = nalu_type; - cp->shared_msg = shared_msg? shared_msg->copy():NULL; - cp->cache_buffer_ = cache_buffer_? cache_buffer_->copy():NULL; + cp->wrap(shared_msg); // Wrap the shared message and buffer. cp->frame_type = frame_type; cp->cached_payload_size = cached_payload_size; @@ -946,6 +1023,71 @@ srs_error_t SrsRtpPacket2::decode(SrsBuffer* buf) return err; } +SrsRtpPacketCacheManager::SrsRtpPacketCacheManager() +{ + enabled_ = false; +} + +SrsRtpPacketCacheManager::~SrsRtpPacketCacheManager() +{ + list::iterator it; + for (it = cache_pkts_.begin(); it != cache_pkts_.end(); ++it) { + SrsRtpPacket2* pkt = *it; + srs_freep(pkt); + } +} + +void SrsRtpPacketCacheManager::set_enabled(bool v) +{ + enabled_ = v; +} + +bool SrsRtpPacketCacheManager::enabled() +{ + return enabled_; +} + +SrsRtpPacket2* SrsRtpPacketCacheManager::allocate() +{ + if (!enabled_ || cache_pkts_.empty()) { + return new SrsRtpPacket2(); + } + + SrsRtpPacket2* pkt = cache_pkts_.back(); + cache_pkts_.pop_back(); + + // We MUST reset it to reuse it. + pkt->reset(); + + return pkt; +} + +void SrsRtpPacketCacheManager::recycle(SrsRtpPacket2* p) +{ + // The p may be NULL, because srs_freep(NULL) is ok. + if (!p) { + return; + } + + // TODO: FIXME: Directly free to keep low memory? + if (!enabled_) { + srs_freep(p); + return; + } + + // If there is any reference about the message, we should free the + // shared message then recycle it(or free it). + if (!p->try_recycle()) { + srs_freep(p); + return; + } + + // Recycle it. + cache_pkts_.push_back(p); +} + +SrsRtpPacketCacheManager* _srs_rtp_cache = new SrsRtpPacketCacheManager(); + SrsRtpRawPayload::SrsRtpRawPayload() { payload = NULL; diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index 920e91588..4174f68bb 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -30,6 +30,7 @@ #include #include +#include class SrsRtpPacket2; @@ -120,6 +121,9 @@ public: public: SrsRtpExtensionTypes(); virtual ~SrsRtpExtensionTypes(); +public: + // Reset the object to reuse it. + void reset(); private: bool register_id(int id, SrsRtpExtensionType type, std::string uri); private: @@ -135,6 +139,9 @@ class SrsRtpExtensionTwcc// : public ISrsCodec public: SrsRtpExtensionTwcc(); virtual ~SrsRtpExtensionTwcc(); +public: + // Reset the object to reuse it. + void reset(); bool has_twcc_ext(); uint8_t get_id(); @@ -157,7 +164,10 @@ class SrsRtpExtensionOneByte// : public ISrsCodec uint8_t value_; public: SrsRtpExtensionOneByte(); - virtual ~SrsRtpExtensionOneByte() {} + virtual ~SrsRtpExtensionOneByte(); +public: + // Reset the object to reuse it. + void reset(); bool exists() { return has_ext_; } int get_id() { return id_; } @@ -182,14 +192,16 @@ private: public: SrsRtpExtensions(); virtual ~SrsRtpExtensions(); - +public: + // Reset the object to reuse it. + void reset(); +public: bool exists(); void set_types_(const SrsRtpExtensionTypes* types); srs_error_t get_twcc_sequence_number(uint16_t& twcc_sn); srs_error_t set_twcc_sequence_number(uint8_t id, uint16_t sn); srs_error_t get_audio_level(uint8_t& level); srs_error_t set_audio_level(int id, uint8_t level); - // ISrsCodec public: virtual srs_error_t decode(SrsBuffer* buf); @@ -217,6 +229,9 @@ private: public: SrsRtpHeader(); virtual ~SrsRtpHeader(); +public: + // Reset the object to reuse it. + void reset(); public: virtual srs_error_t decode(SrsBuffer* buf); private: @@ -262,6 +277,7 @@ public: virtual void on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload) = 0; }; +// The RTP packet with cached shared message. class SrsRtpPacket2 { // RTP packet fields. @@ -289,6 +305,8 @@ public: SrsRtpPacket2(); virtual ~SrsRtpPacket2(); public: + // Reset the object to reuse it. + void reset(); // Wrap buffer to shared_message, which is managed by us. char* wrap(int size); char* wrap(char* data, int size); @@ -296,6 +314,9 @@ public: char* wrap(SrsSharedPtrMessage* msg); // Get the cache buffer which binds to the shared message. SrsBuffer* cache_buffer() const; + // Try to start recycle, return whether it's reusable. + // @remark If not reusable, user should free it directly. + bool try_recycle(); public: // Set the padding of RTP packet. void set_padding(int size); @@ -316,6 +337,28 @@ public: virtual srs_error_t decode(SrsBuffer* buf); }; +// The RTP packet cache manager. +class SrsRtpPacketCacheManager +{ +private: + bool enabled_; + std::list cache_pkts_; +public: + SrsRtpPacketCacheManager(); + virtual ~SrsRtpPacketCacheManager(); +public: + // Enable or disable cache. + void set_enabled(bool v); + bool enabled(); + // Try to allocate from cache, create new packet if no cache. + SrsRtpPacket2* allocate(); + // Recycle the packet to cache. + // @remark User can directly free the packet. + void recycle(SrsRtpPacket2* p); +}; + +extern SrsRtpPacketCacheManager* _srs_rtp_cache; + // Single payload data. class SrsRtpRawPayload : public ISrsRtpPayloader { From 4cb3a18d1e7a9e4d2d8801c43d9987e6d43be3d7 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 26 Feb 2021 16:36:21 +0800 Subject: [PATCH 025/102] RTC: Apply RTP packet cache manager --- trunk/src/app/srs_app_rtc_conn.cpp | 26 ++++++-- trunk/src/app/srs_app_rtc_conn.hpp | 2 + trunk/src/app/srs_app_rtc_queue.cpp | 8 +-- trunk/src/app/srs_app_rtc_source.cpp | 99 ++++++++++++++++------------ trunk/src/app/srs_app_rtc_source.hpp | 23 +++++-- 5 files changed, 100 insertions(+), 58 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 829a447f0..290fbe40f 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -606,7 +606,7 @@ srs_error_t SrsRtcPlayStream::cycle() for (int i = 0; i < msg_count; i++) { SrsRtpPacket2* pkt = pkts[i]; - srs_freep(pkt); + _srs_rtp_cache->recycle(pkt); } pkts.clear(); } @@ -1189,13 +1189,29 @@ srs_error_t SrsRtcPublishStream::on_rtp_plaintext(char* plaintext, int nb_plaint _srs_blackhole->sendto(plaintext, nb_plaintext); } - // Decode the RTP packet from buffer. - SrsRtpPacket2* pkt = new SrsRtpPacket2(); - SrsAutoFree(SrsRtpPacket2, pkt); + // Allocate packet form cache. + SrsRtpPacket2* pkt = _srs_rtp_cache->allocate(); + + // Copy the packet body. + pkt->wrap(plaintext, nb_plaintext); + srs_assert(pkt->cache_buffer()->pos() == 0); + + // Handle the packet. + err = do_on_rtp_plaintext(pkt); + + // Release the packet to cache. + _srs_rtp_cache->recycle(pkt); + + return err; +} + +srs_error_t SrsRtcPublishStream::do_on_rtp_plaintext(SrsRtpPacket2* pkt) +{ + srs_error_t err = srs_success; pkt->set_decode_handler(this); pkt->set_extension_types(&extension_types_); - pkt->wrap(plaintext, nb_plaintext); + if ((err = pkt->decode(pkt->cache_buffer())) != srs_success) { return srs_error_wrap(err, "decode rtp packet"); } diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 538eca984..3483862cb 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -356,6 +356,8 @@ public: private: // @remark We copy the plaintext, user should free it. srs_error_t on_rtp_plaintext(char* plaintext, int nb_plaintext); +private: + srs_error_t do_on_rtp_plaintext(SrsRtpPacket2* pkt); public: srs_error_t check_send_nacks(); public: diff --git a/trunk/src/app/srs_app_rtc_queue.cpp b/trunk/src/app/srs_app_rtc_queue.cpp index 2bba97b57..ee166eacd 100644 --- a/trunk/src/app/srs_app_rtc_queue.cpp +++ b/trunk/src/app/srs_app_rtc_queue.cpp @@ -49,7 +49,7 @@ SrsRtpRingBuffer::~SrsRtpRingBuffer() { for (int i = 0; i < capacity_; ++i) { SrsRtpPacket2* pkt = queue_[i]; - srs_freep(pkt); + _srs_rtp_cache->recycle(pkt); } srs_freepa(queue_); } @@ -76,7 +76,7 @@ void SrsRtpRingBuffer::set(uint16_t at, SrsRtpPacket2* pkt) SrsRtpPacket2* p = queue_[at % capacity_]; if (p) { - srs_freep(p); + _srs_rtp_cache->recycle(p); } queue_[at % capacity_] = pkt; @@ -164,7 +164,7 @@ void SrsRtpRingBuffer::clear_histroy(uint16_t seq) for (uint16_t i = 0; i < capacity_; i++) { SrsRtpPacket2* p = queue_[i]; if (p && p->header.get_sequence() < seq) { - srs_freep(p); + _srs_rtp_cache->recycle(p); queue_[i] = NULL; } } @@ -175,7 +175,7 @@ void SrsRtpRingBuffer::clear_all_histroy() for (uint16_t i = 0; i < capacity_; i++) { SrsRtpPacket2* p = queue_[i]; if (p) { - srs_freep(p); + _srs_rtp_cache->recycle(p); queue_[i] = NULL; } } diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index c6a66e8df..8d9bd3cc6 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -169,7 +169,7 @@ SrsRtcConsumer::~SrsRtcConsumer() vector::iterator it; for (it = queue.begin(); it != queue.end(); ++it) { SrsRtpPacket2* pkt = *it; - srs_freep(pkt); + _srs_rtp_cache->recycle(pkt); } srs_cond_destroy(mw_wait); @@ -582,6 +582,16 @@ std::vector SrsRtcStream::get_track_desc(std::string ty return track_descs; } +SrsRtpPacketCacheHelper::SrsRtpPacketCacheHelper() +{ + pkt = _srs_rtp_cache->allocate(); +} + +SrsRtpPacketCacheHelper::~SrsRtpPacketCacheHelper() +{ + _srs_rtp_cache->recycle(pkt); +} + #ifdef SRS_FFMPEG_FIT SrsRtcFromRtmpBridger::SrsRtcFromRtmpBridger(SrsRtcStream* source) { @@ -785,14 +795,14 @@ srs_error_t SrsRtcFromRtmpBridger::transcode(char* adts_audio, int nn_adts_audio // TODO: FIXME: Use it to padding audios. nn_max_extra_payload = srs_max(nn_max_extra_payload, size); - SrsRtpPacket2* pkt = NULL; - SrsAutoFree(SrsRtpPacket2, pkt); + SrsRtpPacketCacheHelper* helper = new SrsRtpPacketCacheHelper(); + SrsAutoFree(SrsRtpPacketCacheHelper, helper); - if ((err = package_opus(data, size, &pkt)) != srs_success) { + if ((err = package_opus(data, size, helper)) != srs_success) { return srs_error_wrap(err, "package opus"); } - if ((err = source_->on_rtp(pkt)) != srs_success) { + if ((err = source_->on_rtp(helper->pkt)) != srs_success) { return srs_error_wrap(err, "consume opus"); } } @@ -800,11 +810,11 @@ srs_error_t SrsRtcFromRtmpBridger::transcode(char* adts_audio, int nn_adts_audio return err; } -srs_error_t SrsRtcFromRtmpBridger::package_opus(char* data, int size, SrsRtpPacket2** ppkt) +srs_error_t SrsRtcFromRtmpBridger::package_opus(char* data, int size, SrsRtpPacketCacheHelper* helper) { srs_error_t err = srs_success; - SrsRtpPacket2* pkt = new SrsRtpPacket2(); + SrsRtpPacket2* pkt = helper->pkt; pkt->header.set_payload_type(kAudioPayloadType); pkt->header.set_ssrc(audio_ssrc); pkt->frame_type = SrsFrameTypeAudio; @@ -821,8 +831,6 @@ srs_error_t SrsRtcFromRtmpBridger::package_opus(char* data, int size, SrsRtpPack raw->payload = pkt->wrap(data, size); raw->nn_payload = size; - *ppkt = pkt; - return err; } @@ -849,22 +857,22 @@ srs_error_t SrsRtcFromRtmpBridger::on_video(SrsSharedPtrMessage* msg) // Well, for each IDR, we append a SPS/PPS before it, which is packaged in STAP-A. if (has_idr) { - SrsRtpPacket2* pkt = NULL; - SrsAutoFree(SrsRtpPacket2, pkt); + SrsRtpPacketCacheHelper* helper = new SrsRtpPacketCacheHelper(); + SrsAutoFree(SrsRtpPacketCacheHelper, helper); - if ((err = package_stap_a(source_, msg, &pkt)) != srs_success) { + if ((err = package_stap_a(source_, msg, helper)) != srs_success) { return srs_error_wrap(err, "package stap-a"); } - if ((err = source_->on_rtp(pkt)) != srs_success) { + if ((err = source_->on_rtp(helper->pkt)) != srs_success) { return srs_error_wrap(err, "consume sps/pps"); } } // If merge Nalus, we pcakges all NALUs(samples) as one NALU, in a RTP or FUA packet. - vector pkts; + vector helpers; if (merge_nalus && nn_samples > 1) { - if ((err = package_nalus(msg, samples, pkts)) != srs_success) { + if ((err = package_nalus(msg, samples, helpers)) != srs_success) { return srs_error_wrap(err, "package nalus as one"); } } else { @@ -879,22 +887,22 @@ srs_error_t SrsRtcFromRtmpBridger::on_video(SrsSharedPtrMessage* msg) } if (sample->size <= kRtpMaxPayloadSize) { - if ((err = package_single_nalu(msg, sample, pkts)) != srs_success) { + if ((err = package_single_nalu(msg, sample, helpers)) != srs_success) { return srs_error_wrap(err, "package single nalu"); } } else { - if ((err = package_fu_a(msg, sample, kRtpMaxPayloadSize, pkts)) != srs_success) { + if ((err = package_fu_a(msg, sample, kRtpMaxPayloadSize, helpers)) != srs_success) { return srs_error_wrap(err, "package fu-a"); } } } } - if (pkts.size() > 0) { - pkts.back()->header.set_marker(true); + if (!helpers.empty()) { + helpers.back()->pkt->header.set_marker(true); } - return consume_packets(pkts); + return consume_packets(helpers); } srs_error_t SrsRtcFromRtmpBridger::filter(SrsSharedPtrMessage* msg, SrsFormat* format, bool& has_idr, vector& samples) @@ -927,7 +935,7 @@ srs_error_t SrsRtcFromRtmpBridger::filter(SrsSharedPtrMessage* msg, SrsFormat* f return err; } -srs_error_t SrsRtcFromRtmpBridger::package_stap_a(SrsRtcStream* source, SrsSharedPtrMessage* msg, SrsRtpPacket2** ppkt) +srs_error_t SrsRtcFromRtmpBridger::package_stap_a(SrsRtcStream* source, SrsSharedPtrMessage* msg, SrsRtpPacketCacheHelper* helper) { srs_error_t err = srs_success; @@ -943,7 +951,7 @@ srs_error_t SrsRtcFromRtmpBridger::package_stap_a(SrsRtcStream* source, SrsShare return srs_error_new(ERROR_RTC_RTP_MUXER, "sps/pps empty"); } - SrsRtpPacket2* pkt = new SrsRtpPacket2(); + SrsRtpPacket2* pkt = helper->pkt; pkt->header.set_payload_type(kVideoPayloadType); pkt->header.set_ssrc(video_ssrc); pkt->frame_type = SrsFrameTypeVideo; @@ -982,13 +990,12 @@ srs_error_t SrsRtcFromRtmpBridger::package_stap_a(SrsRtcStream* source, SrsShare payload += (int)pps.size(); } - *ppkt = pkt; srs_info("RTC STAP-A seq=%u, sps %d, pps %d bytes", pkt->header.get_sequence(), sps.size(), pps.size()); return err; } -srs_error_t SrsRtcFromRtmpBridger::package_nalus(SrsSharedPtrMessage* msg, const vector& samples, vector& pkts) +srs_error_t SrsRtcFromRtmpBridger::package_nalus(SrsSharedPtrMessage* msg, const vector& samples, vector& helpers) { srs_error_t err = srs_success; @@ -1024,7 +1031,10 @@ srs_error_t SrsRtcFromRtmpBridger::package_nalus(SrsSharedPtrMessage* msg, const if (nn_bytes < kRtpMaxPayloadSize) { // Package NALUs in a single RTP packet. - SrsRtpPacket2* pkt = new SrsRtpPacket2(); + SrsRtpPacketCacheHelper* helper = new SrsRtpPacketCacheHelper(); + helpers.push_back(helper); + + SrsRtpPacket2* pkt = helper->pkt; pkt->header.set_payload_type(kVideoPayloadType); pkt->header.set_ssrc(video_ssrc); pkt->frame_type = SrsFrameTypeVideo; @@ -1033,7 +1043,6 @@ srs_error_t SrsRtcFromRtmpBridger::package_nalus(SrsSharedPtrMessage* msg, const pkt->header.set_timestamp(msg->timestamp * 90); pkt->payload = raw; pkt->wrap(msg); - pkts.push_back(pkt); } else { // We must free it, should never use RTP packets to free it, // because more than one RTP packet will refer to it. @@ -1057,7 +1066,10 @@ srs_error_t SrsRtcFromRtmpBridger::package_nalus(SrsSharedPtrMessage* msg, const return srs_error_wrap(err, "read samples %d bytes, left %d, total %d", packet_size, nb_left, nn_bytes); } - SrsRtpPacket2* pkt = new SrsRtpPacket2(); + SrsRtpPacketCacheHelper* helper = new SrsRtpPacketCacheHelper(); + helpers.push_back(helper); + + SrsRtpPacket2* pkt = helper->pkt; pkt->header.set_payload_type(kVideoPayloadType); pkt->header.set_ssrc(video_ssrc); pkt->frame_type = SrsFrameTypeVideo; @@ -1072,7 +1084,6 @@ srs_error_t SrsRtcFromRtmpBridger::package_nalus(SrsSharedPtrMessage* msg, const pkt->payload = fua; pkt->wrap(msg); - pkts.push_back(pkt); nb_left -= packet_size; } @@ -1082,11 +1093,14 @@ srs_error_t SrsRtcFromRtmpBridger::package_nalus(SrsSharedPtrMessage* msg, const } // Single NAL Unit Packet @see https://tools.ietf.org/html/rfc6184#section-5.6 -srs_error_t SrsRtcFromRtmpBridger::package_single_nalu(SrsSharedPtrMessage* msg, SrsSample* sample, vector& pkts) +srs_error_t SrsRtcFromRtmpBridger::package_single_nalu(SrsSharedPtrMessage* msg, SrsSample* sample, vector& helpers) { srs_error_t err = srs_success; - SrsRtpPacket2* pkt = new SrsRtpPacket2(); + SrsRtpPacketCacheHelper* helper = new SrsRtpPacketCacheHelper(); + helpers.push_back(helper); + + SrsRtpPacket2* pkt = helper->pkt; pkt->header.set_payload_type(kVideoPayloadType); pkt->header.set_ssrc(video_ssrc); pkt->frame_type = SrsFrameTypeVideo; @@ -1101,12 +1115,10 @@ srs_error_t SrsRtcFromRtmpBridger::package_single_nalu(SrsSharedPtrMessage* msg, pkt->wrap(msg); - pkts.push_back(pkt); - return err; } -srs_error_t SrsRtcFromRtmpBridger::package_fu_a(SrsSharedPtrMessage* msg, SrsSample* sample, int fu_payload_size, vector& pkts) +srs_error_t SrsRtcFromRtmpBridger::package_fu_a(SrsSharedPtrMessage* msg, SrsSample* sample, int fu_payload_size, vector& helpers) { srs_error_t err = srs_success; @@ -1119,7 +1131,10 @@ srs_error_t SrsRtcFromRtmpBridger::package_fu_a(SrsSharedPtrMessage* msg, SrsSam for (int i = 0; i < num_of_packet; ++i) { int packet_size = srs_min(nb_left, fu_payload_size); - SrsRtpPacket2* pkt = new SrsRtpPacket2(); + SrsRtpPacketCacheHelper* helper = new SrsRtpPacketCacheHelper(); + helpers.push_back(helper); + + SrsRtpPacket2* pkt = helper->pkt; pkt->header.set_payload_type(kVideoPayloadType); pkt->header.set_ssrc(video_ssrc); pkt->frame_type = SrsFrameTypeVideo; @@ -1139,8 +1154,6 @@ srs_error_t SrsRtcFromRtmpBridger::package_fu_a(SrsSharedPtrMessage* msg, SrsSam pkt->wrap(msg); - pkts.push_back(pkt); - p += packet_size; nb_left -= packet_size; } @@ -1148,22 +1161,22 @@ srs_error_t SrsRtcFromRtmpBridger::package_fu_a(SrsSharedPtrMessage* msg, SrsSam return err; } -srs_error_t SrsRtcFromRtmpBridger::consume_packets(vector& pkts) +srs_error_t SrsRtcFromRtmpBridger::consume_packets(vector& helpers) { srs_error_t err = srs_success; // TODO: FIXME: Consume a range of packets. - for (int i = 0; i < (int)pkts.size(); i++) { - SrsRtpPacket2* pkt = pkts[i]; - if ((err = source_->on_rtp(pkt)) != srs_success) { + for (int i = 0; i < (int)helpers.size(); i++) { + SrsRtpPacketCacheHelper* helper = helpers[i]; + if ((err = source_->on_rtp(helper->pkt)) != srs_success) { err = srs_error_wrap(err, "consume sps/pps"); break; } } - for (int i = 0; i < (int)pkts.size(); i++) { - SrsRtpPacket2* pkt = pkts[i]; - srs_freep(pkt); + for (int i = 0; i < (int)helpers.size(); i++) { + SrsRtpPacketCacheHelper* helper = helpers[i]; + srs_freep(helper); } return err; diff --git a/trunk/src/app/srs_app_rtc_source.hpp b/trunk/src/app/srs_app_rtc_source.hpp index 6d2334083..5d8f03f99 100644 --- a/trunk/src/app/srs_app_rtc_source.hpp +++ b/trunk/src/app/srs_app_rtc_source.hpp @@ -47,6 +47,7 @@ class SrsRtcStream; class SrsRtcFromRtmpBridger; class SrsAudioRecode; class SrsRtpPacket2; +class SrsRtpPacketCacheHelper; class SrsSample; class SrsRtcStreamDescription; class SrsRtcTrackDescription; @@ -222,6 +223,16 @@ public: std::vector get_track_desc(std::string type, std::string media_type); }; +// A helper class, to release the packet to cache. +class SrsRtpPacketCacheHelper +{ +public: + SrsRtpPacket2* pkt; +public: + SrsRtpPacketCacheHelper(); + virtual ~SrsRtpPacketCacheHelper(); +}; + #ifdef SRS_FFMPEG_FIT class SrsRtcFromRtmpBridger : public ISrsSourceBridger { @@ -252,16 +263,16 @@ public: virtual srs_error_t on_audio(SrsSharedPtrMessage* msg); private: srs_error_t transcode(char* adts_audio, int nn_adts_audio); - srs_error_t package_opus(char* data, int size, SrsRtpPacket2** ppkt); + srs_error_t package_opus(char* data, int size, SrsRtpPacketCacheHelper* helper); public: virtual srs_error_t on_video(SrsSharedPtrMessage* msg); private: srs_error_t filter(SrsSharedPtrMessage* msg, SrsFormat* format, bool& has_idr, std::vector& samples); - srs_error_t package_stap_a(SrsRtcStream* source, SrsSharedPtrMessage* msg, SrsRtpPacket2** ppkt); - srs_error_t package_nalus(SrsSharedPtrMessage* msg, const std::vector& samples, std::vector& pkts); - srs_error_t package_single_nalu(SrsSharedPtrMessage* msg, SrsSample* sample, std::vector& pkts); - srs_error_t package_fu_a(SrsSharedPtrMessage* msg, SrsSample* sample, int fu_payload_size, std::vector& pkts); - srs_error_t consume_packets(std::vector& pkts); + srs_error_t package_stap_a(SrsRtcStream* source, SrsSharedPtrMessage* msg, SrsRtpPacketCacheHelper* helper); + srs_error_t package_nalus(SrsSharedPtrMessage* msg, const std::vector& samples, std::vector& helpers); + srs_error_t package_single_nalu(SrsSharedPtrMessage* msg, SrsSample* sample, std::vector& helpers); + srs_error_t package_fu_a(SrsSharedPtrMessage* msg, SrsSample* sample, int fu_payload_size, std::vector& helpers); + srs_error_t consume_packets(std::vector& helpers); }; #endif From 6e9cb059b32d6c480e826375f08f23b43ea8cbd6 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 26 Feb 2021 18:32:29 +0800 Subject: [PATCH 026/102] RTC: Stat the large buffer allocation --- trunk/src/app/srs_app_rtc_server.cpp | 7 ++++--- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 3 +++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index d4996de4c..40bc4dae9 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -78,6 +78,7 @@ extern SrsPps* _srs_pps_rmnack; extern SrsPps* _srs_pps_objs_rtps; extern SrsPps* _srs_pps_objs_rraw; extern SrsPps* _srs_pps_objs_rfua; +extern SrsPps* _srs_pps_objs_rbuf; SrsRtcBlackhole::SrsRtcBlackhole() { @@ -684,9 +685,9 @@ srs_error_t SrsRtcServer::notify(int type, srs_utime_t interval, srs_utime_t tic static char buf[128]; string objs_desc; - _srs_pps_objs_rtps->update(); _srs_pps_objs_rraw->update(); _srs_pps_objs_rfua->update(); - if (_srs_pps_objs_rtps->r10s() || _srs_pps_objs_rraw->r10s() || _srs_pps_objs_rfua->r10s()) { - snprintf(buf, sizeof(buf), ", objs=%d,%d,%d", _srs_pps_objs_rtps->r10s(), _srs_pps_objs_rraw->r10s(), _srs_pps_objs_rfua->r10s()); + _srs_pps_objs_rtps->update(); _srs_pps_objs_rraw->update(); _srs_pps_objs_rfua->update(); _srs_pps_objs_rbuf->update(); + if (_srs_pps_objs_rtps->r10s() || _srs_pps_objs_rraw->r10s() || _srs_pps_objs_rfua->r10s() || _srs_pps_objs_rbuf->r10s()) { + snprintf(buf, sizeof(buf), ", objs=%d,%d,%d,%d", _srs_pps_objs_rtps->r10s(), _srs_pps_objs_rraw->r10s(), _srs_pps_objs_rfua->r10s(), _srs_pps_objs_rbuf->r10s()); objs_desc = buf; } diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index 352fed02e..cbbe7741a 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -39,6 +39,7 @@ using namespace std; SrsPps* _srs_pps_objs_rtps = new SrsPps(); SrsPps* _srs_pps_objs_rraw = new SrsPps(); SrsPps* _srs_pps_objs_rfua = new SrsPps(); +SrsPps* _srs_pps_objs_rbuf = new SrsPps(); /* @see https://tools.ietf.org/html/rfc1889#section-5.1 0 1 2 3 @@ -867,6 +868,8 @@ char* SrsRtpPacket2::wrap(int size) srs_freep(cache_buffer_); cache_buffer_ = new SrsBuffer(buf, size); + ++_srs_pps_objs_rbuf->sugar; + return buf; } From 4d0863468af1ea580540aabc7f71fa746625b754 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 26 Feb 2021 19:46:52 +0800 Subject: [PATCH 027/102] RTC: Cache the large buffer allocation --- trunk/conf/full.conf | 3 + trunk/src/app/srs_app_config.cpp | 19 +++- trunk/src/app/srs_app_config.hpp | 1 + trunk/src/app/srs_app_rtc_conn.cpp | 10 +- trunk/src/app/srs_app_rtc_conn.hpp | 2 +- trunk/src/app/srs_app_rtc_server.cpp | 5 +- trunk/src/kernel/srs_kernel_flv.hpp | 2 + trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 145 +++++++----------------- trunk/src/kernel/srs_kernel_rtc_rtp.hpp | 81 +++++++++---- 9 files changed, 135 insertions(+), 133 deletions(-) diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index b850003e5..19bd6f7e1 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -500,6 +500,9 @@ rtc_server { # Whether enable the RTP packet cache. # default: off rtp_cache off; + #Whether enable the RTP message(a large buffer) cache. + # default: off + rtp_msg_cache off; # The black-hole to copy packet to, for debugging. # For example, when debugging Chrome publish stream, the received packets are encrypted cipher, # we can set the publisher black-hole, SRS will copy the plaintext packets to black-hole, and diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 52fadae34..49ff10fea 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -3651,7 +3651,7 @@ srs_error_t SrsConfig::check_normal_config() string n = conf->at(i)->name; if (n != "enabled" && n != "listen" && n != "dir" && n != "candidate" && n != "ecdsa" && n != "encrypt" && n != "reuseport" && n != "merge_nalus" && n != "perf_stat" && n != "black_hole" - && n != "ip_family" && n != "rtp_cache") { + && n != "ip_family" && n != "rtp_cache" && n != "rtp_msg_cache") { return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal rtc_server.%s", n.c_str()); } } @@ -4919,6 +4919,23 @@ bool SrsConfig::get_rtc_server_rtp_cache() return SRS_CONF_PERFER_FALSE(conf->arg0()); } +bool SrsConfig::get_rtc_server_rtp_msg_cache() +{ + static bool DEFAULT = false; + + SrsConfDirective* conf = root->get("rtc_server"); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("rtp_msg_cache"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + return SRS_CONF_PERFER_FALSE(conf->arg0()); +} + bool SrsConfig::get_rtc_server_black_hole() { static bool DEFAULT = false; diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index a6cebc7c3..5ba3e36f9 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -535,6 +535,7 @@ public: virtual bool get_rtc_server_merge_nalus(); virtual bool get_rtc_server_perf_stat(); virtual bool get_rtc_server_rtp_cache(); + virtual bool get_rtc_server_rtp_msg_cache(); virtual bool get_rtc_server_black_hole(); virtual std::string get_rtc_server_black_hole_addr(); private: diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 290fbe40f..2ac360d5d 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1193,11 +1193,11 @@ srs_error_t SrsRtcPublishStream::on_rtp_plaintext(char* plaintext, int nb_plaint SrsRtpPacket2* pkt = _srs_rtp_cache->allocate(); // Copy the packet body. - pkt->wrap(plaintext, nb_plaintext); - srs_assert(pkt->cache_buffer()->pos() == 0); + char* p = pkt->wrap(plaintext, nb_plaintext); // Handle the packet. - err = do_on_rtp_plaintext(pkt); + SrsBuffer buf(p, nb_plaintext); + err = do_on_rtp_plaintext(pkt, &buf); // Release the packet to cache. _srs_rtp_cache->recycle(pkt); @@ -1205,14 +1205,14 @@ srs_error_t SrsRtcPublishStream::on_rtp_plaintext(char* plaintext, int nb_plaint return err; } -srs_error_t SrsRtcPublishStream::do_on_rtp_plaintext(SrsRtpPacket2* pkt) +srs_error_t SrsRtcPublishStream::do_on_rtp_plaintext(SrsRtpPacket2* pkt, SrsBuffer* buf) { srs_error_t err = srs_success; pkt->set_decode_handler(this); pkt->set_extension_types(&extension_types_); - if ((err = pkt->decode(pkt->cache_buffer())) != srs_success) { + if ((err = pkt->decode(buf)) != srs_success) { return srs_error_wrap(err, "decode rtp packet"); } diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 3483862cb..644c718f9 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -357,7 +357,7 @@ private: // @remark We copy the plaintext, user should free it. srs_error_t on_rtp_plaintext(char* plaintext, int nb_plaintext); private: - srs_error_t do_on_rtp_plaintext(SrsRtpPacket2* pkt); + srs_error_t do_on_rtp_plaintext(SrsRtpPacket2* pkt, SrsBuffer* buf); public: srs_error_t check_send_nacks(); public: diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index 40bc4dae9..36b4b53ee 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -287,7 +287,10 @@ srs_error_t SrsRtcServer::initialize() bool rtp_cache = _srs_config->get_rtc_server_rtp_cache(); _srs_rtp_cache->set_enabled(rtp_cache); - srs_trace("RTC server init ok, rtp_cache=%d", rtp_cache); + bool rtp_msg_cache = _srs_config->get_rtc_server_rtp_msg_cache(); + _srs_rtp_msg_cache->set_enabled(rtp_msg_cache); + + srs_trace("RTC server init ok, rc=%d, rmc=%d", rtp_cache, rtp_msg_cache); return err; } diff --git a/trunk/src/kernel/srs_kernel_flv.hpp b/trunk/src/kernel/srs_kernel_flv.hpp index f3be5931b..ba53e92db 100644 --- a/trunk/src/kernel/srs_kernel_flv.hpp +++ b/trunk/src/kernel/srs_kernel_flv.hpp @@ -312,6 +312,8 @@ public: SrsSharedPtrMessage(); virtual ~SrsSharedPtrMessage(); public: + // For object cache to reset and reuse it. + bool reset() { return true; } // Create shared ptr message, // copy header, manage the payload of msg, // set the payload to NULL to prevent double free. diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index cbbe7741a..60c076a9d 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -811,7 +811,6 @@ SrsRtpPacket2::SrsRtpPacket2() { payload = NULL; shared_msg = NULL; - cache_buffer_ = NULL; reset(); @@ -821,11 +820,17 @@ SrsRtpPacket2::SrsRtpPacket2() SrsRtpPacket2::~SrsRtpPacket2() { srs_freep(payload); - srs_freep(shared_msg); - srs_freep(cache_buffer_); + + // Recyle the real owner of message, no other reference object. + if (shared_msg && shared_msg->count() == 0) { + _srs_rtp_msg_cache->recycle(shared_msg); + shared_msg = NULL; + } else { + srs_freep(shared_msg); + } } -void SrsRtpPacket2::reset() +bool SrsRtpPacket2::reset() { nalu_type = SrsAvcNaluTypeReserved; frame_type = SrsFrameTypeReserved; @@ -839,38 +844,49 @@ void SrsRtpPacket2::reset() // and it's different for each packet. srs_freep(payload); - // We should reset the cached buffer. - if (cache_buffer_) { - cache_buffer_->skip(-1 * cache_buffer_->pos()); + // Recyle the real owner of message, no other reference object. + if (shared_msg && shared_msg->count() == 0) { + _srs_rtp_msg_cache->recycle(shared_msg); + shared_msg = NULL; + } else { + srs_freep(shared_msg); } + + return true; } char* SrsRtpPacket2::wrap(int size) { // If the buffer is large enough, reuse it. if (shared_msg && shared_msg->size >= size) { - // The size maybe changed, so we MUST reset it. - cache_buffer_->set_size(size); - return shared_msg->payload; } - // Create buffer if empty or not large enough. - srs_freep(shared_msg); - shared_msg = new SrsSharedPtrMessage(); + // Create a large enough message, with under-layer buffer. + while (true) { + srs_freep(shared_msg); + shared_msg = _srs_rtp_msg_cache->allocate(); - // For RTC, we use larger under-layer buffer for each packet. - int nb_buffer = srs_max(size, kRtpPacketSize); - char* buf = new char[nb_buffer]; - shared_msg->wrap(buf, nb_buffer); + // If got a cached message(which has payload), but it's too small, + // we free it and allocate a larger one. + if (shared_msg->payload && shared_msg->size < size) { + continue; + } - // The size of buffer must equal to the actual size. - srs_freep(cache_buffer_); - cache_buffer_ = new SrsBuffer(buf, size); + // Create under-layer buffer for new message + if (!shared_msg->payload) { + // For RTC, we use larger under-layer buffer for each packet. + int nb_buffer = srs_max(size, kRtpPacketSize); + char* buf = new char[nb_buffer]; + shared_msg->wrap(buf, nb_buffer); - ++_srs_pps_objs_rbuf->sugar; + ++_srs_pps_objs_rbuf->sugar; + } - return buf; + break; + } + + return shared_msg->payload; } char* SrsRtpPacket2::wrap(char* data, int size) @@ -885,29 +901,9 @@ char* SrsRtpPacket2::wrap(SrsSharedPtrMessage* msg) srs_freep(shared_msg); shared_msg = msg->copy(); - srs_freep(cache_buffer_); - cache_buffer_ = new SrsBuffer(msg->payload, msg->size); - return msg->payload; } -SrsBuffer* SrsRtpPacket2::cache_buffer() const -{ - return cache_buffer_; -} - -bool SrsRtpPacket2::try_recycle() -{ - // When recycling, and there is references about he shared buffer, we must free - // the shared message(may not free the buffer) to stop reuse the shared message. - if (shared_msg && shared_msg->count() > 0) { - srs_freep(shared_msg); - } - - // OK, allow to recycle this object. - return true; -} - void SrsRtpPacket2::set_padding(int size) { header.set_padding(size); @@ -1026,70 +1022,9 @@ srs_error_t SrsRtpPacket2::decode(SrsBuffer* buf) return err; } -SrsRtpPacketCacheManager::SrsRtpPacketCacheManager() -{ - enabled_ = false; -} +SrsRtpObjectCacheManager* _srs_rtp_cache = new SrsRtpObjectCacheManager(); -SrsRtpPacketCacheManager::~SrsRtpPacketCacheManager() -{ - list::iterator it; - for (it = cache_pkts_.begin(); it != cache_pkts_.end(); ++it) { - SrsRtpPacket2* pkt = *it; - srs_freep(pkt); - } -} - -void SrsRtpPacketCacheManager::set_enabled(bool v) -{ - enabled_ = v; -} - -bool SrsRtpPacketCacheManager::enabled() -{ - return enabled_; -} - -SrsRtpPacket2* SrsRtpPacketCacheManager::allocate() -{ - if (!enabled_ || cache_pkts_.empty()) { - return new SrsRtpPacket2(); - } - - SrsRtpPacket2* pkt = cache_pkts_.back(); - cache_pkts_.pop_back(); - - // We MUST reset it to reuse it. - pkt->reset(); - - return pkt; -} - -void SrsRtpPacketCacheManager::recycle(SrsRtpPacket2* p) -{ - // The p may be NULL, because srs_freep(NULL) is ok. - if (!p) { - return; - } - - // TODO: FIXME: Directly free to keep low memory? - if (!enabled_) { - srs_freep(p); - return; - } - - // If there is any reference about the message, we should free the - // shared message then recycle it(or free it). - if (!p->try_recycle()) { - srs_freep(p); - return; - } - - // Recycle it. - cache_pkts_.push_back(p); -} - -SrsRtpPacketCacheManager* _srs_rtp_cache = new SrsRtpPacketCacheManager(); +SrsRtpObjectCacheManager* _srs_rtp_msg_cache = new SrsRtpObjectCacheManager(); SrsRtpRawPayload::SrsRtpRawPayload() { diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index 4174f68bb..d8995a39a 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -285,8 +285,6 @@ public: SrsRtpHeader header; ISrsRtpPayloader* payload; private: - // The buffer bind to the shared message. - SrsBuffer* cache_buffer_; // The original shared message, all RTP packets can refer to its data. SrsSharedPtrMessage* shared_msg; // Helper fields. @@ -306,17 +304,12 @@ public: virtual ~SrsRtpPacket2(); public: // Reset the object to reuse it. - void reset(); + virtual bool reset(); // Wrap buffer to shared_message, which is managed by us. char* wrap(int size); char* wrap(char* data, int size); // Wrap the shared message, we copy it. char* wrap(SrsSharedPtrMessage* msg); - // Get the cache buffer which binds to the shared message. - SrsBuffer* cache_buffer() const; - // Try to start recycle, return whether it's reusable. - // @remark If not reusable, user should free it directly. - bool try_recycle(); public: // Set the padding of RTP packet. void set_padding(int size); @@ -337,27 +330,75 @@ public: virtual srs_error_t decode(SrsBuffer* buf); }; -// The RTP packet cache manager. -class SrsRtpPacketCacheManager +// The RTP packet or message cache manager. +template +class SrsRtpObjectCacheManager { private: bool enabled_; - std::list cache_pkts_; + std::list cache_objs_; public: - SrsRtpPacketCacheManager(); - virtual ~SrsRtpPacketCacheManager(); + SrsRtpObjectCacheManager() { + enabled_ = false; + } + virtual ~SrsRtpObjectCacheManager() { + typedef typename std::list::iterator iterator; + for (iterator it = cache_objs_.begin(); it != cache_objs_.end(); ++it) { + T* obj = *it; + srs_freep(obj); + } + } public: // Enable or disable cache. - void set_enabled(bool v); - bool enabled(); - // Try to allocate from cache, create new packet if no cache. - SrsRtpPacket2* allocate(); - // Recycle the packet to cache. + void set_enabled(bool v) { + enabled_ = v; + } + bool enabled() { + return enabled_; + } + // Try to allocate from cache, create new object if no cache. + T* allocate() { + while (true) { + if (!enabled_ || cache_objs_.empty()) { + return new T(); + } + + T* obj = cache_objs_.back(); + cache_objs_.pop_back(); + + // If reset the object fail, drop the cached object. + if (!obj->reset()) { + srs_freep(obj); + continue; + } + + return obj; + } + } + // Recycle the object to cache. // @remark User can directly free the packet. - void recycle(SrsRtpPacket2* p); + void recycle(T* p) { + // The p may be NULL, because srs_freep(NULL) is ok. + if (!p) { + return; + } + + // TODO: FIXME: Directly free to keep low memory? + if (!enabled_) { + srs_freep(p); + return; + } + + // Recycle it. + cache_objs_.push_back(p); + } }; -extern SrsRtpPacketCacheManager* _srs_rtp_cache; +// For RTP packets cache. +extern SrsRtpObjectCacheManager* _srs_rtp_cache; + +// For RTP packet shared messages cache. +extern SrsRtpObjectCacheManager* _srs_rtp_msg_cache; // Single payload data. class SrsRtpRawPayload : public ISrsRtpPayloader From fc4d7080c69a9629997ce255cb97df62c414951a Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 26 Feb 2021 20:28:05 +0800 Subject: [PATCH 028/102] RTC: Cache the RTP payload objects --- trunk/src/app/srs_app_rtc_server.cpp | 2 ++ trunk/src/app/srs_app_rtc_source.cpp | 12 ++++++------ trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 25 ++++++++++++++++++------- trunk/src/kernel/srs_kernel_rtc_rtp.hpp | 18 ++++++++++++------ 4 files changed, 38 insertions(+), 19 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index 36b4b53ee..e1b601478 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -286,6 +286,8 @@ srs_error_t SrsRtcServer::initialize() bool rtp_cache = _srs_config->get_rtc_server_rtp_cache(); _srs_rtp_cache->set_enabled(rtp_cache); + _srs_rtp_raw_cache->set_enabled(rtp_cache); + _srs_rtp_fua_cache->set_enabled(rtp_cache); bool rtp_msg_cache = _srs_config->get_rtc_server_rtp_msg_cache(); _srs_rtp_msg_cache->set_enabled(rtp_msg_cache); diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index 8d9bd3cc6..87ef3fb24 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -825,7 +825,7 @@ srs_error_t SrsRtcFromRtmpBridger::package_opus(char* data, int size, SrsRtpPack // TODO: FIXME: Why 960? Need Refactoring? audio_timestamp += 960; - SrsRtpRawPayload* raw = new SrsRtpRawPayload(); + SrsRtpRawPayload* raw = _srs_rtp_raw_cache->allocate(); pkt->payload = raw; raw->payload = pkt->wrap(data, size); @@ -1107,7 +1107,7 @@ srs_error_t SrsRtcFromRtmpBridger::package_single_nalu(SrsSharedPtrMessage* msg, pkt->header.set_sequence(video_sequence++); pkt->header.set_timestamp(msg->timestamp * 90); - SrsRtpRawPayload* raw = new SrsRtpRawPayload(); + SrsRtpRawPayload* raw = _srs_rtp_raw_cache->allocate(); pkt->payload = raw; raw->payload = sample->bytes; @@ -1141,7 +1141,7 @@ srs_error_t SrsRtcFromRtmpBridger::package_fu_a(SrsSharedPtrMessage* msg, SrsSam pkt->header.set_sequence(video_sequence++); pkt->header.set_timestamp(msg->timestamp * 90); - SrsRtpFUAPayload2* fua = new SrsRtpFUAPayload2(); + SrsRtpFUAPayload2* fua = _srs_rtp_fua_cache->allocate(); pkt->payload = fua; fua->nri = (SrsAvcNaluType)header; @@ -1861,7 +1861,7 @@ void SrsRtcAudioRecvTrack::on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffe return; } - *ppayload = new SrsRtpRawPayload(); + *ppayload = _srs_rtp_raw_cache->allocate(); } srs_error_t SrsRtcAudioRecvTrack::on_rtp(SrsRtcStream* source, SrsRtpPacket2* pkt, bool nack_enabled) @@ -1921,9 +1921,9 @@ void SrsRtcVideoRecvTrack::on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffe if (v == kStapA) { *ppayload = new SrsRtpSTAPPayload(); } else if (v == kFuA) { - *ppayload = new SrsRtpFUAPayload2(); + *ppayload = _srs_rtp_fua_cache->allocate(); } else { - *ppayload = new SrsRtpRawPayload(); + *ppayload = _srs_rtp_raw_cache->allocate(); } } diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index 60c076a9d..ca248c196 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -839,10 +839,19 @@ bool SrsRtpPacket2::reset() header.reset(); - // We do not cache the payload, it will be created even - // we cache it, because it only stores pointers to the shared message, - // and it's different for each packet. - srs_freep(payload); + // Only recycle some common payloads. + SrsRtpRawPayload* raw_payload; + SrsRtpFUAPayload2* fua_payload; + + if ((raw_payload = dynamic_cast(payload)) != NULL) { + _srs_rtp_raw_cache->recycle(raw_payload); + payload = NULL; + } else if ((fua_payload = dynamic_cast(payload)) != NULL) { + _srs_rtp_fua_cache->recycle(fua_payload); + payload = NULL; + } else { + srs_freep(payload); + } // Recyle the real owner of message, no other reference object. if (shared_msg && shared_msg->count() == 0) { @@ -1012,7 +1021,7 @@ srs_error_t SrsRtpPacket2::decode(SrsBuffer* buf) // By default, we always use the RAW payload. if (!payload) { - payload = new SrsRtpRawPayload(); + payload = _srs_rtp_raw_cache->allocate(); } if ((err = payload->decode(buf)) != srs_success) { @@ -1023,6 +1032,8 @@ srs_error_t SrsRtpPacket2::decode(SrsBuffer* buf) } SrsRtpObjectCacheManager* _srs_rtp_cache = new SrsRtpObjectCacheManager(); +SrsRtpObjectCacheManager* _srs_rtp_raw_cache = new SrsRtpObjectCacheManager(); +SrsRtpObjectCacheManager* _srs_rtp_fua_cache = new SrsRtpObjectCacheManager(); SrsRtpObjectCacheManager* _srs_rtp_msg_cache = new SrsRtpObjectCacheManager(); @@ -1072,7 +1083,7 @@ srs_error_t SrsRtpRawPayload::decode(SrsBuffer* buf) ISrsRtpPayloader* SrsRtpRawPayload::copy() { - SrsRtpRawPayload* cp = new SrsRtpRawPayload(); + SrsRtpRawPayload* cp = _srs_rtp_raw_cache->allocate(); cp->payload = payload; cp->nn_payload = nn_payload; @@ -1561,7 +1572,7 @@ srs_error_t SrsRtpFUAPayload2::decode(SrsBuffer* buf) ISrsRtpPayloader* SrsRtpFUAPayload2::copy() { - SrsRtpFUAPayload2* cp = new SrsRtpFUAPayload2(); + SrsRtpFUAPayload2* cp = _srs_rtp_fua_cache->allocate(); cp->nri = nri; cp->start = start; diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index d8995a39a..be54e856f 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -394,12 +394,6 @@ public: } }; -// For RTP packets cache. -extern SrsRtpObjectCacheManager* _srs_rtp_cache; - -// For RTP packet shared messages cache. -extern SrsRtpObjectCacheManager* _srs_rtp_msg_cache; - // Single payload data. class SrsRtpRawPayload : public ISrsRtpPayloader { @@ -411,6 +405,8 @@ public: public: SrsRtpRawPayload(); virtual ~SrsRtpRawPayload(); +public: + bool reset() { return true; } // interface ISrsRtpPayloader public: virtual uint64_t nb_bytes(); @@ -509,6 +505,8 @@ public: public: SrsRtpFUAPayload2(); virtual ~SrsRtpFUAPayload2(); +public: + bool reset() { return true; } // interface ISrsRtpPayloader public: virtual uint64_t nb_bytes(); @@ -517,4 +515,12 @@ public: virtual ISrsRtpPayloader* copy(); }; +// For RTP packets cache. +extern SrsRtpObjectCacheManager* _srs_rtp_cache; +extern SrsRtpObjectCacheManager* _srs_rtp_raw_cache; +extern SrsRtpObjectCacheManager* _srs_rtp_fua_cache; + +// For RTP packet shared messages cache. +extern SrsRtpObjectCacheManager* _srs_rtp_msg_cache; + #endif From 919107c6745e9372217d77f12194f4c9c97a155f Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 26 Feb 2021 20:38:50 +0800 Subject: [PATCH 029/102] Perf: Stat the shared messages. --- trunk/src/app/srs_app_rtc_server.cpp | 7 ++++--- trunk/src/kernel/srs_kernel_flv.cpp | 6 ++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index e1b601478..45be1e6ba 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -79,6 +79,7 @@ extern SrsPps* _srs_pps_objs_rtps; extern SrsPps* _srs_pps_objs_rraw; extern SrsPps* _srs_pps_objs_rfua; extern SrsPps* _srs_pps_objs_rbuf; +extern SrsPps* _srs_pps_objs_msgs; SrsRtcBlackhole::SrsRtcBlackhole() { @@ -690,9 +691,9 @@ srs_error_t SrsRtcServer::notify(int type, srs_utime_t interval, srs_utime_t tic static char buf[128]; string objs_desc; - _srs_pps_objs_rtps->update(); _srs_pps_objs_rraw->update(); _srs_pps_objs_rfua->update(); _srs_pps_objs_rbuf->update(); - if (_srs_pps_objs_rtps->r10s() || _srs_pps_objs_rraw->r10s() || _srs_pps_objs_rfua->r10s() || _srs_pps_objs_rbuf->r10s()) { - snprintf(buf, sizeof(buf), ", objs=%d,%d,%d,%d", _srs_pps_objs_rtps->r10s(), _srs_pps_objs_rraw->r10s(), _srs_pps_objs_rfua->r10s(), _srs_pps_objs_rbuf->r10s()); + _srs_pps_objs_rtps->update(); _srs_pps_objs_rraw->update(); _srs_pps_objs_rfua->update(); _srs_pps_objs_rbuf->update(); _srs_pps_objs_msgs->update(); + if (_srs_pps_objs_rtps->r10s() || _srs_pps_objs_rraw->r10s() || _srs_pps_objs_rfua->r10s() || _srs_pps_objs_rbuf->r10s() || _srs_pps_objs_msgs->r10s()) { + snprintf(buf, sizeof(buf), ", objs=%d,%d,%d,%d,%d", _srs_pps_objs_rtps->r10s(), _srs_pps_objs_rraw->r10s(), _srs_pps_objs_rfua->r10s(), _srs_pps_objs_rbuf->r10s(), _srs_pps_objs_msgs->r10s()); objs_desc = buf; } diff --git a/trunk/src/kernel/srs_kernel_flv.cpp b/trunk/src/kernel/srs_kernel_flv.cpp index ff41f6f4c..e5c27b673 100644 --- a/trunk/src/kernel/srs_kernel_flv.cpp +++ b/trunk/src/kernel/srs_kernel_flv.cpp @@ -40,6 +40,10 @@ using namespace std; #include #include +#include + +SrsPps* _srs_pps_objs_msgs = new SrsPps(); + SrsMessageHeader::SrsMessageHeader() { message_type = 0; @@ -209,6 +213,8 @@ SrsSharedPtrMessage::SrsSharedPtrPayload::~SrsSharedPtrPayload() SrsSharedPtrMessage::SrsSharedPtrMessage() : timestamp(0), stream_id(0), size(0), payload(NULL) { ptr = NULL; + + ++ _srs_pps_objs_msgs->sugar; } SrsSharedPtrMessage::~SrsSharedPtrMessage() From c00d286344dfba54606bb042663647cc492d1a1d Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 26 Feb 2021 21:35:51 +0800 Subject: [PATCH 030/102] Perf: Refine the stat --- trunk/src/app/srs_app_hybrid.cpp | 25 +++++++++++-- trunk/src/app/srs_app_rtc_server.cpp | 17 ++------- trunk/src/kernel/srs_kernel_flv.cpp | 21 +++++++++-- trunk/src/kernel/srs_kernel_flv.hpp | 2 ++ trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 48 +++++++++++++------------ trunk/src/kernel/srs_kernel_rtc_rtp.hpp | 5 +++ 6 files changed, 75 insertions(+), 43 deletions(-) diff --git a/trunk/src/app/srs_app_hybrid.cpp b/trunk/src/app/srs_app_hybrid.cpp index 446593ee5..94a1a72a4 100644 --- a/trunk/src/app/srs_app_hybrid.cpp +++ b/trunk/src/app/srs_app_hybrid.cpp @@ -122,6 +122,13 @@ SrsPps* _srs_pps_thread_yield = new SrsPps(); SrsPps* _srs_pps_thread_yield2 = new SrsPps(); #endif +extern SrsPps* _srs_pps_objs_rtps; +extern SrsPps* _srs_pps_objs_rraw; +extern SrsPps* _srs_pps_objs_rfua; +extern SrsPps* _srs_pps_objs_rbuf; +extern SrsPps* _srs_pps_objs_msgs; +extern SrsPps* _srs_pps_objs_rothers; + ISrsHybridServer::ISrsHybridServer() { } @@ -446,13 +453,25 @@ srs_error_t SrsHybridServer::notify(int event, srs_utime_t interval, srs_utime_t } #endif - srs_trace("Hybrid cpu=%.2f%%,%dMB%s%s%s%s%s%s%s%s%s%s", + string objs_desc; + _srs_pps_objs_rtps->update(); _srs_pps_objs_rraw->update(); _srs_pps_objs_rfua->update(); _srs_pps_objs_rbuf->update(); _srs_pps_objs_msgs->update(); _srs_pps_objs_rothers->update(); + if (_srs_pps_objs_rtps->r10s() || _srs_pps_objs_rraw->r10s() || _srs_pps_objs_rfua->r10s() || _srs_pps_objs_rbuf->r10s() || _srs_pps_objs_msgs->r10s() || _srs_pps_objs_rothers->r10s()) { + snprintf(buf, sizeof(buf), ", objs=%d,%d,%d,%d,%d,%d", _srs_pps_objs_rtps->r10s(), _srs_pps_objs_rraw->r10s(), _srs_pps_objs_rfua->r10s(), _srs_pps_objs_msgs->r10s(), _srs_pps_objs_rothers->r10s(), _srs_pps_objs_rbuf->r10s()); + objs_desc = buf; + } + + string cache_desc; + if (true) { + snprintf(buf, sizeof(buf), ", cache=%d,%d,%d,%d", _srs_rtp_cache->size(), _srs_rtp_raw_cache->size(), _srs_rtp_fua_cache->size(), _srs_rtp_msg_cache->size()); + cache_desc = buf; + } + + srs_trace("Hybrid cpu=%.2f%%,%dMB%s%s%s%s%s%s%s%s%s%s%s%s", u->percent * 100, memory, cid_desc.c_str(), timer_desc.c_str(), recvfrom_desc.c_str(), io_desc.c_str(), msg_desc.c_str(), epoll_desc.c_str(), sched_desc.c_str(), clock_desc.c_str(), - thread_desc.c_str(), - free_desc.c_str() + thread_desc.c_str(), free_desc.c_str(), objs_desc.c_str(), cache_desc.c_str() ); return err; diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index 45be1e6ba..748b24aa9 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -75,12 +75,6 @@ extern SrsPps* _srs_pps_rnack2; extern SrsPps* _srs_pps_rhnack; extern SrsPps* _srs_pps_rmnack; -extern SrsPps* _srs_pps_objs_rtps; -extern SrsPps* _srs_pps_objs_rraw; -extern SrsPps* _srs_pps_objs_rfua; -extern SrsPps* _srs_pps_objs_rbuf; -extern SrsPps* _srs_pps_objs_msgs; - SrsRtcBlackhole::SrsRtcBlackhole() { blackhole = false; @@ -690,13 +684,6 @@ srs_error_t SrsRtcServer::notify(int type, srs_utime_t interval, srs_utime_t tic } static char buf[128]; - string objs_desc; - _srs_pps_objs_rtps->update(); _srs_pps_objs_rraw->update(); _srs_pps_objs_rfua->update(); _srs_pps_objs_rbuf->update(); _srs_pps_objs_msgs->update(); - if (_srs_pps_objs_rtps->r10s() || _srs_pps_objs_rraw->r10s() || _srs_pps_objs_rfua->r10s() || _srs_pps_objs_rbuf->r10s() || _srs_pps_objs_msgs->r10s()) { - snprintf(buf, sizeof(buf), ", objs=%d,%d,%d,%d,%d", _srs_pps_objs_rtps->r10s(), _srs_pps_objs_rraw->r10s(), _srs_pps_objs_rfua->r10s(), _srs_pps_objs_rbuf->r10s(), _srs_pps_objs_msgs->r10s()); - objs_desc = buf; - } - string rpkts_desc; _srs_pps_rpkts->update(); _srs_pps_rrtps->update(); _srs_pps_rstuns->update(); _srs_pps_rrtcps->update(); if (_srs_pps_rpkts->r10s() || _srs_pps_rrtps->r10s() || _srs_pps_rstuns->r10s() || _srs_pps_rrtcps->r10s()) { @@ -746,9 +733,9 @@ srs_error_t SrsRtcServer::notify(int type, srs_utime_t interval, srs_utime_t tic fid_desc = buf; } - srs_trace("RTC: Server conns=%u%s%s%s%s%s%s%s%s", + srs_trace("RTC: Server conns=%u%s%s%s%s%s%s%s", nn_rtc_conns, - rpkts_desc.c_str(), spkts_desc.c_str(), rtcp_desc.c_str(), snk_desc.c_str(), rnk_desc.c_str(), drop_desc.c_str(), fid_desc.c_str(), objs_desc.c_str() + rpkts_desc.c_str(), spkts_desc.c_str(), rtcp_desc.c_str(), snk_desc.c_str(), rnk_desc.c_str(), drop_desc.c_str(), fid_desc.c_str() ); return err; diff --git a/trunk/src/kernel/srs_kernel_flv.cpp b/trunk/src/kernel/srs_kernel_flv.cpp index e5c27b673..95422eefd 100644 --- a/trunk/src/kernel/srs_kernel_flv.cpp +++ b/trunk/src/kernel/srs_kernel_flv.cpp @@ -39,6 +39,7 @@ using namespace std; #include #include #include +#include #include @@ -286,10 +287,24 @@ void SrsSharedPtrMessage::wrap(char* payload, int size) this->size = ptr->size; } +void SrsSharedPtrMessage::unwrap() +{ + if (ptr) { + if (ptr->shared_count == 0) { + srs_freep(ptr); + } else { + ptr->shared_count--; + ptr = NULL; + } + } + + payload = NULL; + size = 0; +} + int SrsSharedPtrMessage::count() { - srs_assert(ptr); - return ptr->shared_count; + return ptr? ptr->shared_count : 0; } bool SrsSharedPtrMessage::check(int stream_id) @@ -346,7 +361,7 @@ SrsSharedPtrMessage* SrsSharedPtrMessage::copy() { srs_assert(ptr); - SrsSharedPtrMessage* copy = new SrsSharedPtrMessage(); + SrsSharedPtrMessage* copy = _srs_rtp_msg_cache->allocate(); copy->ptr = ptr; ptr->shared_count++; diff --git a/trunk/src/kernel/srs_kernel_flv.hpp b/trunk/src/kernel/srs_kernel_flv.hpp index ba53e92db..0fc501331 100644 --- a/trunk/src/kernel/srs_kernel_flv.hpp +++ b/trunk/src/kernel/srs_kernel_flv.hpp @@ -328,6 +328,8 @@ public: // Create shared ptr message from RAW payload. // @remark Note that the header is set to zero. virtual void wrap(char* payload, int size); + // Decrease the reference, if the last one, free it. + void unwrap(); // Get current reference count. // when this object created, count set to 0. // if copy() this object, count increase 1. diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index ca248c196..96077d60c 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -40,6 +40,7 @@ SrsPps* _srs_pps_objs_rtps = new SrsPps(); SrsPps* _srs_pps_objs_rraw = new SrsPps(); SrsPps* _srs_pps_objs_rfua = new SrsPps(); SrsPps* _srs_pps_objs_rbuf = new SrsPps(); +SrsPps* _srs_pps_objs_rothers = new SrsPps(); /* @see https://tools.ietf.org/html/rfc1889#section-5.1 0 1 2 3 @@ -819,26 +820,11 @@ SrsRtpPacket2::SrsRtpPacket2() SrsRtpPacket2::~SrsRtpPacket2() { - srs_freep(payload); - - // Recyle the real owner of message, no other reference object. - if (shared_msg && shared_msg->count() == 0) { - _srs_rtp_msg_cache->recycle(shared_msg); - shared_msg = NULL; - } else { - srs_freep(shared_msg); - } + reuse(); } -bool SrsRtpPacket2::reset() +void SrsRtpPacket2::reuse() { - nalu_type = SrsAvcNaluTypeReserved; - frame_type = SrsFrameTypeReserved; - cached_payload_size = 0; - decode_handler = NULL; - - header.reset(); - // Only recycle some common payloads. SrsRtpRawPayload* raw_payload; SrsRtpFUAPayload2* fua_payload; @@ -853,13 +839,27 @@ bool SrsRtpPacket2::reset() srs_freep(payload); } - // Recyle the real owner of message, no other reference object. - if (shared_msg && shared_msg->count() == 0) { + // Recycle the real owner of message, clear the reference. + if (shared_msg) { + if (shared_msg->count() > 0) { + shared_msg->unwrap(); + } _srs_rtp_msg_cache->recycle(shared_msg); shared_msg = NULL; - } else { - srs_freep(shared_msg); } +} + +bool SrsRtpPacket2::reset() +{ + nalu_type = SrsAvcNaluTypeReserved; + frame_type = SrsFrameTypeReserved; + cached_payload_size = 0; + decode_handler = NULL; + + header.reset(); + + // Reset and reuse the payload and shared message. + reuse(); return true; } @@ -1095,6 +1095,8 @@ SrsRtpRawNALUs::SrsRtpRawNALUs() { cursor = 0; nn_bytes = 0; + + ++_srs_pps_objs_rothers->sugar; } SrsRtpRawNALUs::~SrsRtpRawNALUs() @@ -1232,6 +1234,8 @@ ISrsRtpPayloader* SrsRtpRawNALUs::copy() SrsRtpSTAPPayload::SrsRtpSTAPPayload() { nri = (SrsAvcNaluType)0; + + ++_srs_pps_objs_rothers->sugar; } SrsRtpSTAPPayload::~SrsRtpSTAPPayload() @@ -1381,7 +1385,7 @@ SrsRtpFUAPayload::SrsRtpFUAPayload() start = end = false; nri = nalu_type = (SrsAvcNaluType)0; - ++_srs_pps_objs_rfua->sugar; + ++_srs_pps_objs_rothers->sugar; } SrsRtpFUAPayload::~SrsRtpFUAPayload() diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index be54e856f..fff24942d 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -302,6 +302,8 @@ private: public: SrsRtpPacket2(); virtual ~SrsRtpPacket2(); +private: + void reuse(); public: // Reset the object to reuse it. virtual bool reset(); @@ -356,6 +358,9 @@ public: bool enabled() { return enabled_; } + int size() { + return (int)cache_objs_.size(); + } // Try to allocate from cache, create new object if no cache. T* allocate() { while (true) { From 30d760f909d204f971d5b2fcb2d291ade7855b40 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 26 Feb 2021 22:55:27 +0800 Subject: [PATCH 031/102] RTC: Only cache the UDP packet message --- trunk/src/app/srs_app_hybrid.cpp | 2 +- trunk/src/app/srs_app_rtc_server.cpp | 1 + trunk/src/kernel/srs_kernel_flv.cpp | 8 +++++-- trunk/src/kernel/srs_kernel_flv.hpp | 2 +- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 30 +++++++++++++++++++------ trunk/src/kernel/srs_kernel_rtc_rtp.hpp | 2 ++ 6 files changed, 34 insertions(+), 11 deletions(-) diff --git a/trunk/src/app/srs_app_hybrid.cpp b/trunk/src/app/srs_app_hybrid.cpp index 94a1a72a4..5ce5aad32 100644 --- a/trunk/src/app/srs_app_hybrid.cpp +++ b/trunk/src/app/srs_app_hybrid.cpp @@ -462,7 +462,7 @@ srs_error_t SrsHybridServer::notify(int event, srs_utime_t interval, srs_utime_t string cache_desc; if (true) { - snprintf(buf, sizeof(buf), ", cache=%d,%d,%d,%d", _srs_rtp_cache->size(), _srs_rtp_raw_cache->size(), _srs_rtp_fua_cache->size(), _srs_rtp_msg_cache->size()); + snprintf(buf, sizeof(buf), ", cache=%d,%d,%d,%d,%d", _srs_rtp_cache->size(), _srs_rtp_raw_cache->size(), _srs_rtp_fua_cache->size(), _srs_rtp_msg_cache->size(), _srs_rtp_msg_cache2->size()); cache_desc = buf; } diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index 748b24aa9..b1b5a0982 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -286,6 +286,7 @@ srs_error_t SrsRtcServer::initialize() bool rtp_msg_cache = _srs_config->get_rtc_server_rtp_msg_cache(); _srs_rtp_msg_cache->set_enabled(rtp_msg_cache); + _srs_rtp_msg_cache2->set_enabled(rtp_msg_cache); srs_trace("RTC server init ok, rc=%d, rmc=%d", rtp_cache, rtp_msg_cache); diff --git a/trunk/src/kernel/srs_kernel_flv.cpp b/trunk/src/kernel/srs_kernel_flv.cpp index 95422eefd..f0184cf7d 100644 --- a/trunk/src/kernel/srs_kernel_flv.cpp +++ b/trunk/src/kernel/srs_kernel_flv.cpp @@ -361,8 +361,12 @@ SrsSharedPtrMessage* SrsSharedPtrMessage::copy() { srs_assert(ptr); - SrsSharedPtrMessage* copy = _srs_rtp_msg_cache->allocate(); - + SrsSharedPtrMessage* copy = _srs_rtp_msg_cache2->allocate(); + + // We got an object from cache, the ptr might exists, so unwrap it. + copy->unwrap(); + + // Reference to this message instead. copy->ptr = ptr; ptr->shared_count++; diff --git a/trunk/src/kernel/srs_kernel_flv.hpp b/trunk/src/kernel/srs_kernel_flv.hpp index 0fc501331..d5a2bd2c3 100644 --- a/trunk/src/kernel/srs_kernel_flv.hpp +++ b/trunk/src/kernel/srs_kernel_flv.hpp @@ -290,7 +290,7 @@ public: // video/audio packet use raw bytes, no video/audio packet. char* payload; -private: +public: class SrsSharedPtrPayload { public: diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index 96077d60c..9bcbf0efb 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -840,13 +840,24 @@ void SrsRtpPacket2::reuse() } // Recycle the real owner of message, clear the reference. - if (shared_msg) { - if (shared_msg->count() > 0) { - shared_msg->unwrap(); - } - _srs_rtp_msg_cache->recycle(shared_msg); - shared_msg = NULL; + reuse_shared_msg(); +} + +void SrsRtpPacket2::reuse_shared_msg() +{ + if (!shared_msg) { + return; } + + // We only recycle the RTC UDP packet messages. + if (shared_msg->payload && shared_msg->size == kRtpPacketSize && shared_msg->count() == 0) { + _srs_rtp_msg_cache->recycle(shared_msg); + } else { + shared_msg->unwrap(); + _srs_rtp_msg_cache2->recycle(shared_msg); + } + + shared_msg = NULL; } bool SrsRtpPacket2::reset() @@ -879,6 +890,7 @@ char* SrsRtpPacket2::wrap(int size) // If got a cached message(which has payload), but it's too small, // we free it and allocate a larger one. if (shared_msg->payload && shared_msg->size < size) { + ++_srs_pps_objs_rothers->sugar; continue; } @@ -907,7 +919,10 @@ char* SrsRtpPacket2::wrap(char* data, int size) char* SrsRtpPacket2::wrap(SrsSharedPtrMessage* msg) { - srs_freep(shared_msg); + // Recycle the shared message. + reuse_shared_msg(); + + // Copy from the new message. shared_msg = msg->copy(); return msg->payload; @@ -1036,6 +1051,7 @@ SrsRtpObjectCacheManager* _srs_rtp_raw_cache = new SrsRtpObjec SrsRtpObjectCacheManager* _srs_rtp_fua_cache = new SrsRtpObjectCacheManager(); SrsRtpObjectCacheManager* _srs_rtp_msg_cache = new SrsRtpObjectCacheManager(); +SrsRtpObjectCacheManager* _srs_rtp_msg_cache2 = new SrsRtpObjectCacheManager(); SrsRtpRawPayload::SrsRtpRawPayload() { diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index fff24942d..63183bb22 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -304,6 +304,7 @@ public: virtual ~SrsRtpPacket2(); private: void reuse(); + void reuse_shared_msg(); public: // Reset the object to reuse it. virtual bool reset(); @@ -527,5 +528,6 @@ extern SrsRtpObjectCacheManager* _srs_rtp_fua_cache; // For RTP packet shared messages cache. extern SrsRtpObjectCacheManager* _srs_rtp_msg_cache; +extern SrsRtpObjectCacheManager* _srs_rtp_msg_cache2; #endif From 3989f2d5536406b787b51c1123efc17219ea7ee8 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 27 Feb 2021 07:41:51 +0800 Subject: [PATCH 032/102] RTC: Refine the stat logs, limit the object cache pool --- trunk/conf/full.conf | 30 +++++-- trunk/src/app/srs_app_config.cpp | 110 ++++++++++++++++++++++-- trunk/src/app/srs_app_config.hpp | 15 +++- trunk/src/app/srs_app_hybrid.cpp | 14 +-- trunk/src/app/srs_app_rtc_server.cpp | 38 ++++---- trunk/src/kernel/srs_kernel_flv.cpp | 2 +- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 11 +-- trunk/src/kernel/srs_kernel_rtc_rtp.hpp | 26 +++++- 8 files changed, 202 insertions(+), 44 deletions(-) diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 19bd6f7e1..4bee21e02 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -497,12 +497,30 @@ rtc_server { # then system queue is 2000*4 = 8k, user can incrase reuseport to incrase the queue. # default: 2000 queue_length 2000; - # Whether enable the RTP packet cache. - # default: off - rtp_cache off; - #Whether enable the RTP message(a large buffer) cache. - # default: off - rtp_msg_cache off; + # For RTP packet and its payload cache. + rtp_cache { + # Whether enable the RTP packet cache. + # default: off + enabled off; + # The cache size for rtp packet in MB, each object is about 300B.. + # default: 128 + pkt_size 128.0; + # The cache size for rtp payload in MB, each object is about 40B. + # default: 32 + payload_size 32.0; + } + # For RTP shared message and the large buffer cache. + rtp_msg_cache { + #Whether enable the RTP message(a large buffer) cache. + # default: off + enabled off; + # The cache size for message object in MB, each object is about 40B. + # default: 32 + msg_size 32.0; + # The cache size for message large buffer in MB, each object is about 1500B. + # default: 1024 + buffer_size 1024.0; + } # The black-hole to copy packet to, for debugging. # For example, when debugging Chrome publish stream, the received packets are encrypted cipher, # we can set the publisher black-hole, SRS will copy the plaintext packets to black-hole, and diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 49ff10fea..ff295d45f 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -4902,16 +4902,31 @@ bool SrsConfig::get_rtc_server_perf_stat() return SRS_CONF_PERFER_TRUE(conf->arg0()); } -bool SrsConfig::get_rtc_server_rtp_cache() +SrsConfDirective* SrsConfig::get_rtc_server_rtp_cache() +{ + SrsConfDirective* conf = root->get("rtc_server"); + if (!conf) { + return NULL; + } + + conf = conf->get("rtp_cache"); + if (!conf) { + return NULL; + } + + return conf; +} + +bool SrsConfig::get_rtc_server_rtp_cache_enabled() { static bool DEFAULT = false; - SrsConfDirective* conf = root->get("rtc_server"); + SrsConfDirective* conf = get_rtc_server_rtp_cache(); if (!conf) { return DEFAULT; } - conf = conf->get("rtp_cache"); + conf = conf->get("enabled"); if (!conf || conf->arg0().empty()) { return DEFAULT; } @@ -4919,16 +4934,65 @@ bool SrsConfig::get_rtc_server_rtp_cache() return SRS_CONF_PERFER_FALSE(conf->arg0()); } -bool SrsConfig::get_rtc_server_rtp_msg_cache() +uint64_t SrsConfig::get_rtc_server_rtp_cache_pkt_size() { - static bool DEFAULT = false; + int DEFAULT = 128 * 1024 * 1024; - SrsConfDirective* conf = root->get("rtc_server"); + SrsConfDirective* conf = get_rtc_server_rtp_cache(); if (!conf) { return DEFAULT; } + conf = conf->get("pkt_size"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + return (uint64_t)(1024 * ::atof(conf->arg0().c_str())); +} + +uint64_t SrsConfig::get_rtc_server_rtp_cache_payload_size() +{ + int DEFAULT = 32 * 1024 * 1024; + + SrsConfDirective* conf = get_rtc_server_rtp_cache(); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("payload_size"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + return (uint64_t)(1024 * ::atof(conf->arg0().c_str())); +} + +SrsConfDirective* SrsConfig::get_rtc_server_rtp_msg_cache() +{ + SrsConfDirective* conf = root->get("rtc_server"); + if (!conf) { + return NULL; + } + conf = conf->get("rtp_msg_cache"); + if (!conf) { + return NULL; + } + + return conf; +} + +bool SrsConfig::get_rtc_server_rtp_msg_cache_enabled() +{ + static bool DEFAULT = false; + + SrsConfDirective* conf = get_rtc_server_rtp_msg_cache(); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("enabled"); if (!conf || conf->arg0().empty()) { return DEFAULT; } @@ -4936,6 +5000,40 @@ bool SrsConfig::get_rtc_server_rtp_msg_cache() return SRS_CONF_PERFER_FALSE(conf->arg0()); } +uint64_t SrsConfig::get_rtc_server_rtp_msg_cache_msg_size() +{ + int DEFAULT = 32 * 1024 * 1024; + + SrsConfDirective* conf = get_rtc_server_rtp_msg_cache(); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("msg_size"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + return (uint64_t)(1024 * ::atof(conf->arg0().c_str())); +} + +uint64_t SrsConfig::get_rtc_server_rtp_msg_cache_buffer_size() +{ + int DEFAULT = 1024 * 1024 * 1024; + + SrsConfDirective* conf = get_rtc_server_rtp_msg_cache(); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("buffer_size"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + return (uint64_t)(1024 * ::atof(conf->arg0().c_str())); +} + bool SrsConfig::get_rtc_server_black_hole() { static bool DEFAULT = false; diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 5ba3e36f9..a027e5f2f 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -534,8 +534,19 @@ public: virtual int get_rtc_server_reuseport(); virtual bool get_rtc_server_merge_nalus(); virtual bool get_rtc_server_perf_stat(); - virtual bool get_rtc_server_rtp_cache(); - virtual bool get_rtc_server_rtp_msg_cache(); +private: + SrsConfDirective* get_rtc_server_rtp_cache(); +public: + virtual bool get_rtc_server_rtp_cache_enabled(); + virtual uint64_t get_rtc_server_rtp_cache_pkt_size(); + virtual uint64_t get_rtc_server_rtp_cache_payload_size(); +private: + virtual SrsConfDirective* get_rtc_server_rtp_msg_cache(); +public: + virtual bool get_rtc_server_rtp_msg_cache_enabled(); + virtual uint64_t get_rtc_server_rtp_msg_cache_msg_size(); + virtual uint64_t get_rtc_server_rtp_msg_cache_buffer_size(); +public: virtual bool get_rtc_server_black_hole(); virtual std::string get_rtc_server_black_hole_addr(); private: diff --git a/trunk/src/app/srs_app_hybrid.cpp b/trunk/src/app/srs_app_hybrid.cpp index 5ce5aad32..f0ff56f35 100644 --- a/trunk/src/app/srs_app_hybrid.cpp +++ b/trunk/src/app/srs_app_hybrid.cpp @@ -454,15 +454,19 @@ srs_error_t SrsHybridServer::notify(int event, srs_utime_t interval, srs_utime_t #endif string objs_desc; - _srs_pps_objs_rtps->update(); _srs_pps_objs_rraw->update(); _srs_pps_objs_rfua->update(); _srs_pps_objs_rbuf->update(); _srs_pps_objs_msgs->update(); _srs_pps_objs_rothers->update(); - if (_srs_pps_objs_rtps->r10s() || _srs_pps_objs_rraw->r10s() || _srs_pps_objs_rfua->r10s() || _srs_pps_objs_rbuf->r10s() || _srs_pps_objs_msgs->r10s() || _srs_pps_objs_rothers->r10s()) { - snprintf(buf, sizeof(buf), ", objs=%d,%d,%d,%d,%d,%d", _srs_pps_objs_rtps->r10s(), _srs_pps_objs_rraw->r10s(), _srs_pps_objs_rfua->r10s(), _srs_pps_objs_msgs->r10s(), _srs_pps_objs_rothers->r10s(), _srs_pps_objs_rbuf->r10s()); + _srs_pps_objs_rtps->update(); _srs_pps_objs_rraw->update(); _srs_pps_objs_rfua->update(); _srs_pps_objs_rbuf->update(); _srs_pps_objs_msgs->update(); _srs_pps_objs_rothers->update(); _srs_pps_objs_drop->update(); + if (_srs_pps_objs_rtps->r10s() || _srs_pps_objs_rraw->r10s() || _srs_pps_objs_rfua->r10s() || _srs_pps_objs_rbuf->r10s() || _srs_pps_objs_msgs->r10s() || _srs_pps_objs_rothers->r10s() || _srs_pps_objs_drop->r10s()) { + snprintf(buf, sizeof(buf), ", objs=(pkt:%d,raw:%d,fua:%d,msg:%d,oth:%d,buf:%d,drop:%d)", + _srs_pps_objs_rtps->r10s(), _srs_pps_objs_rraw->r10s(), _srs_pps_objs_rfua->r10s(), + _srs_pps_objs_msgs->r10s(), _srs_pps_objs_rothers->r10s(), _srs_pps_objs_rbuf->r10s(), _srs_pps_objs_drop->r10s()); objs_desc = buf; } string cache_desc; - if (true) { - snprintf(buf, sizeof(buf), ", cache=%d,%d,%d,%d,%d", _srs_rtp_cache->size(), _srs_rtp_raw_cache->size(), _srs_rtp_fua_cache->size(), _srs_rtp_msg_cache->size(), _srs_rtp_msg_cache2->size()); + if (_srs_rtp_cache->size() || _srs_rtp_raw_cache->size() || _srs_rtp_fua_cache->size() || _srs_rtp_msg_cache_buffers->size() || _srs_rtp_msg_cache_objs->size()) { + snprintf(buf, sizeof(buf), ", cache=(pkt:%d-%dw,raw:%d-%dw,fua:%d-%dw,msg:%d-%dw,buf:%d-%dw)", + _srs_rtp_cache->size(), _srs_rtp_cache->capacity()/10000, _srs_rtp_raw_cache->size(), _srs_rtp_raw_cache->capacity()/10000, + _srs_rtp_fua_cache->size(), _srs_rtp_fua_cache->capacity()/10000, _srs_rtp_msg_cache_buffers->size(), _srs_rtp_msg_cache_buffers->capacity()/10000, _srs_rtp_msg_cache_objs->size(), _srs_rtp_msg_cache_objs->capacity()/10000); cache_desc = buf; } diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index b1b5a0982..b2bad7285 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -279,16 +279,24 @@ srs_error_t SrsRtcServer::initialize() return srs_error_wrap(err, "black hole"); } - bool rtp_cache = _srs_config->get_rtc_server_rtp_cache(); - _srs_rtp_cache->set_enabled(rtp_cache); - _srs_rtp_raw_cache->set_enabled(rtp_cache); - _srs_rtp_fua_cache->set_enabled(rtp_cache); + bool rtp_cache_enabled = _srs_config->get_rtc_server_rtp_cache_enabled(); + uint64_t rtp_cache_pkt_size = _srs_config->get_rtc_server_rtp_cache_pkt_size(); + uint64_t rtp_cache_payload_size = _srs_config->get_rtc_server_rtp_cache_payload_size(); + _srs_rtp_cache->set_enabled(rtp_cache_enabled, rtp_cache_pkt_size); + _srs_rtp_raw_cache->set_enabled(rtp_cache_enabled, rtp_cache_payload_size); + _srs_rtp_fua_cache->set_enabled(rtp_cache_enabled, rtp_cache_payload_size); - bool rtp_msg_cache = _srs_config->get_rtc_server_rtp_msg_cache(); - _srs_rtp_msg_cache->set_enabled(rtp_msg_cache); - _srs_rtp_msg_cache2->set_enabled(rtp_msg_cache); + bool rtp_msg_cache_enabled = _srs_config->get_rtc_server_rtp_msg_cache_enabled(); + uint64_t rtp_msg_cache_msg_size = _srs_config->get_rtc_server_rtp_msg_cache_msg_size(); + uint64_t rtp_msg_cache_buffer_size = _srs_config->get_rtc_server_rtp_msg_cache_buffer_size(); + _srs_rtp_msg_cache_buffers->set_enabled(rtp_msg_cache_enabled, rtp_msg_cache_msg_size); + _srs_rtp_msg_cache_objs->set_enabled(rtp_msg_cache_enabled, rtp_msg_cache_buffer_size); - srs_trace("RTC server init ok, rc=%d, rmc=%d", rtp_cache, rtp_msg_cache); + srs_trace("RTC server init ok, rtp-cache=(enabled:%d,pkt:%dm-%dw,payload:%dm-%dw-%dw), msg-cache=(enabled:%d,obj:%dm-%dw,buf:%dm-%dw)", + rtp_cache_enabled, (int)(rtp_cache_pkt_size/1024/1024), _srs_rtp_cache->capacity()/10000, + (int)(rtp_cache_payload_size/1024/1024), _srs_rtp_raw_cache->capacity()/10000, _srs_rtp_fua_cache->capacity()/10000, + rtp_msg_cache_enabled, (int)(rtp_msg_cache_msg_size/1024/1024), _srs_rtp_msg_cache_objs->capacity()/10000, + (int)(rtp_msg_cache_buffer_size/1024/1024), _srs_rtp_msg_cache_buffers->capacity()/10000); return err; } @@ -688,49 +696,49 @@ srs_error_t SrsRtcServer::notify(int type, srs_utime_t interval, srs_utime_t tic string rpkts_desc; _srs_pps_rpkts->update(); _srs_pps_rrtps->update(); _srs_pps_rstuns->update(); _srs_pps_rrtcps->update(); if (_srs_pps_rpkts->r10s() || _srs_pps_rrtps->r10s() || _srs_pps_rstuns->r10s() || _srs_pps_rrtcps->r10s()) { - snprintf(buf, sizeof(buf), ", rpkts=%d,%d,%d,%d", _srs_pps_rpkts->r10s(), _srs_pps_rrtps->r10s(), _srs_pps_rstuns->r10s(), _srs_pps_rrtcps->r10s()); + snprintf(buf, sizeof(buf), ", rpkts=(%d,rtp:%d,stun:%d,rtcp:%d)", _srs_pps_rpkts->r10s(), _srs_pps_rrtps->r10s(), _srs_pps_rstuns->r10s(), _srs_pps_rrtcps->r10s()); rpkts_desc = buf; } string spkts_desc; _srs_pps_spkts->update(); _srs_pps_srtps->update(); _srs_pps_sstuns->update(); _srs_pps_srtcps->update(); if (_srs_pps_spkts->r10s() || _srs_pps_srtps->r10s() || _srs_pps_sstuns->r10s() || _srs_pps_srtcps->r10s()) { - snprintf(buf, sizeof(buf), ", spkts=%d,%d,%d,%d", _srs_pps_spkts->r10s(), _srs_pps_srtps->r10s(), _srs_pps_sstuns->r10s(), _srs_pps_srtcps->r10s()); + snprintf(buf, sizeof(buf), ", spkts=(%d,rtp:%d,stun:%d,rtcp:%d)", _srs_pps_spkts->r10s(), _srs_pps_srtps->r10s(), _srs_pps_sstuns->r10s(), _srs_pps_srtcps->r10s()); spkts_desc = buf; } string rtcp_desc; _srs_pps_pli->update(); _srs_pps_twcc->update(); _srs_pps_rr->update(); if (_srs_pps_pli->r10s() || _srs_pps_twcc->r10s() || _srs_pps_rr->r10s()) { - snprintf(buf, sizeof(buf), ", rtcp=%d,%d,%d", _srs_pps_pli->r10s(), _srs_pps_twcc->r10s(), _srs_pps_rr->r10s()); + snprintf(buf, sizeof(buf), ", rtcp=(pli:%d,twcc:%d,rr:%d)", _srs_pps_pli->r10s(), _srs_pps_twcc->r10s(), _srs_pps_rr->r10s()); rtcp_desc = buf; } string snk_desc; _srs_pps_snack->update(); _srs_pps_snack2->update(); _srs_pps_sanack->update(); _srs_pps_svnack->update(); if (_srs_pps_snack->r10s() || _srs_pps_sanack->r10s() || _srs_pps_svnack->r10s() || _srs_pps_snack2->r10s()) { - snprintf(buf, sizeof(buf), ", snk=%d,%d,%d,%d", _srs_pps_snack->r10s(), _srs_pps_sanack->r10s(), _srs_pps_svnack->r10s(), _srs_pps_snack2->r10s()); + snprintf(buf, sizeof(buf), ", snk=(%d,a:%d,v:%d,h:%d)", _srs_pps_snack->r10s(), _srs_pps_sanack->r10s(), _srs_pps_svnack->r10s(), _srs_pps_snack2->r10s()); snk_desc = buf; } string rnk_desc; _srs_pps_rnack->update(); _srs_pps_rnack2->update(); _srs_pps_rhnack->update(); _srs_pps_rmnack->update(); if (_srs_pps_rnack->r10s() || _srs_pps_rnack2->r10s() || _srs_pps_rhnack->r10s() || _srs_pps_rmnack->r10s()) { - snprintf(buf, sizeof(buf), ", rnk=%d,%d,%d,%d", _srs_pps_rnack->r10s(), _srs_pps_rnack2->r10s(), _srs_pps_rhnack->r10s(), _srs_pps_rmnack->r10s()); + snprintf(buf, sizeof(buf), ", rnk=(%d,%d,h:%d,m:%d)", _srs_pps_rnack->r10s(), _srs_pps_rnack2->r10s(), _srs_pps_rhnack->r10s(), _srs_pps_rmnack->r10s()); rnk_desc = buf; } string drop_desc; SrsSnmpUdpStat* s = srs_get_udp_snmp_stat(); if (s->rcv_buf_errors_delta || s->snd_buf_errors_delta) { - snprintf(buf, sizeof(buf), ", drop=%d,%d", s->rcv_buf_errors_delta, s->snd_buf_errors_delta); + snprintf(buf, sizeof(buf), ", drop=(r:%d,s:%d)", s->rcv_buf_errors_delta, s->snd_buf_errors_delta); drop_desc = buf; } string fid_desc; _srs_pps_ids->update(); _srs_pps_fids->update(); _srs_pps_fids_level0->update(); _srs_pps_addrs->update(); _srs_pps_fast_addrs->update(); if (_srs_pps_ids->r10s(), _srs_pps_fids->r10s(), _srs_pps_fids_level0->r10s(), _srs_pps_addrs->r10s(), _srs_pps_fast_addrs->r10s()) { - snprintf(buf, sizeof(buf), ", fid=%d,%d,%d,%d,%d", _srs_pps_ids->r10s(), _srs_pps_fids->r10s(), _srs_pps_fids_level0->r10s(), _srs_pps_addrs->r10s(), _srs_pps_fast_addrs->r10s()); + snprintf(buf, sizeof(buf), ", fid=(id:%d,fid:%d,ffid:%d,addr:%d,faddr:%d)", _srs_pps_ids->r10s(), _srs_pps_fids->r10s(), _srs_pps_fids_level0->r10s(), _srs_pps_addrs->r10s(), _srs_pps_fast_addrs->r10s()); fid_desc = buf; } diff --git a/trunk/src/kernel/srs_kernel_flv.cpp b/trunk/src/kernel/srs_kernel_flv.cpp index f0184cf7d..5fd1f0929 100644 --- a/trunk/src/kernel/srs_kernel_flv.cpp +++ b/trunk/src/kernel/srs_kernel_flv.cpp @@ -361,7 +361,7 @@ SrsSharedPtrMessage* SrsSharedPtrMessage::copy() { srs_assert(ptr); - SrsSharedPtrMessage* copy = _srs_rtp_msg_cache2->allocate(); + SrsSharedPtrMessage* copy = _srs_rtp_msg_cache_objs->allocate(); // We got an object from cache, the ptr might exists, so unwrap it. copy->unwrap(); diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index 9bcbf0efb..4d3b7271a 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -41,6 +41,7 @@ SrsPps* _srs_pps_objs_rraw = new SrsPps(); SrsPps* _srs_pps_objs_rfua = new SrsPps(); SrsPps* _srs_pps_objs_rbuf = new SrsPps(); SrsPps* _srs_pps_objs_rothers = new SrsPps(); +SrsPps* _srs_pps_objs_drop = new SrsPps(); /* @see https://tools.ietf.org/html/rfc1889#section-5.1 0 1 2 3 @@ -851,10 +852,10 @@ void SrsRtpPacket2::reuse_shared_msg() // We only recycle the RTC UDP packet messages. if (shared_msg->payload && shared_msg->size == kRtpPacketSize && shared_msg->count() == 0) { - _srs_rtp_msg_cache->recycle(shared_msg); + _srs_rtp_msg_cache_buffers->recycle(shared_msg); } else { shared_msg->unwrap(); - _srs_rtp_msg_cache2->recycle(shared_msg); + _srs_rtp_msg_cache_objs->recycle(shared_msg); } shared_msg = NULL; @@ -885,7 +886,7 @@ char* SrsRtpPacket2::wrap(int size) // Create a large enough message, with under-layer buffer. while (true) { srs_freep(shared_msg); - shared_msg = _srs_rtp_msg_cache->allocate(); + shared_msg = _srs_rtp_msg_cache_buffers->allocate(); // If got a cached message(which has payload), but it's too small, // we free it and allocate a larger one. @@ -1050,8 +1051,8 @@ SrsRtpObjectCacheManager* _srs_rtp_cache = new SrsRtpObjectCacheM SrsRtpObjectCacheManager* _srs_rtp_raw_cache = new SrsRtpObjectCacheManager(); SrsRtpObjectCacheManager* _srs_rtp_fua_cache = new SrsRtpObjectCacheManager(); -SrsRtpObjectCacheManager* _srs_rtp_msg_cache = new SrsRtpObjectCacheManager(); -SrsRtpObjectCacheManager* _srs_rtp_msg_cache2 = new SrsRtpObjectCacheManager(); +SrsRtpObjectCacheManager* _srs_rtp_msg_cache_buffers = new SrsRtpObjectCacheManager(); +SrsRtpObjectCacheManager* _srs_rtp_msg_cache_objs = new SrsRtpObjectCacheManager(); SrsRtpRawPayload::SrsRtpRawPayload() { diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index 63183bb22..77366e714 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -333,6 +333,10 @@ public: virtual srs_error_t decode(SrsBuffer* buf); }; +// For object cache manager to stat the object dropped. +#include +extern SrsPps* _srs_pps_objs_drop; + // The RTP packet or message cache manager. template class SrsRtpObjectCacheManager @@ -340,9 +344,11 @@ class SrsRtpObjectCacheManager private: bool enabled_; std::list cache_objs_; + size_t capacity_; public: SrsRtpObjectCacheManager() { enabled_ = false; + capacity_ = 0; } virtual ~SrsRtpObjectCacheManager() { typedef typename std::list::iterator iterator; @@ -353,8 +359,9 @@ public: } public: // Enable or disable cache. - void set_enabled(bool v) { + void set_enabled(bool v, uint64_t memory) { enabled_ = v; + capacity_ = (size_t)(memory / sizeof(T)); } bool enabled() { return enabled_; @@ -362,6 +369,9 @@ public: int size() { return (int)cache_objs_.size(); } + int capacity() { + return (int)capacity_; + } // Try to allocate from cache, create new object if no cache. T* allocate() { while (true) { @@ -389,12 +399,20 @@ public: return; } - // TODO: FIXME: Directly free to keep low memory? + // If disabled, drop the object. if (!enabled_) { srs_freep(p); return; } + // If exceed the capacity, drop the object. + if (cache_objs_.size() > capacity_) { + ++_srs_pps_objs_drop->sugar; + + srs_freep(p); + return; + } + // Recycle it. cache_objs_.push_back(p); } @@ -527,7 +545,7 @@ extern SrsRtpObjectCacheManager* _srs_rtp_raw_cache; extern SrsRtpObjectCacheManager* _srs_rtp_fua_cache; // For RTP packet shared messages cache. -extern SrsRtpObjectCacheManager* _srs_rtp_msg_cache; -extern SrsRtpObjectCacheManager* _srs_rtp_msg_cache2; +extern SrsRtpObjectCacheManager* _srs_rtp_msg_cache_buffers; +extern SrsRtpObjectCacheManager* _srs_rtp_msg_cache_objs; #endif From 501104e728872dc3394282eb6241010a8e2563be Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 27 Feb 2021 08:18:08 +0800 Subject: [PATCH 033/102] Perf: Limit the size of object cache pool --- trunk/conf/full.conf | 16 ++++---- trunk/src/app/srs_app_config.cpp | 16 ++++---- trunk/src/app/srs_app_rtc_server.cpp | 12 +++--- trunk/src/app/srs_app_rtc_server.hpp | 1 + trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 52 ++++++++++++++----------- trunk/src/kernel/srs_kernel_rtc_rtp.hpp | 23 +++++++++-- 6 files changed, 72 insertions(+), 48 deletions(-) diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 4bee21e02..3f31d0750 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -503,11 +503,11 @@ rtc_server { # default: off enabled off; # The cache size for rtp packet in MB, each object is about 300B.. - # default: 128 - pkt_size 128.0; + # default: 64 + pkt_size 64.0; # The cache size for rtp payload in MB, each object is about 40B. - # default: 32 - payload_size 32.0; + # default: 16 + payload_size 16.0; } # For RTP shared message and the large buffer cache. rtp_msg_cache { @@ -515,11 +515,11 @@ rtc_server { # default: off enabled off; # The cache size for message object in MB, each object is about 40B. - # default: 32 - msg_size 32.0; + # default: 16 + msg_size 16.0; # The cache size for message large buffer in MB, each object is about 1500B. - # default: 1024 - buffer_size 1024.0; + # default: 512 + buffer_size 512.0; } # The black-hole to copy packet to, for debugging. # For example, when debugging Chrome publish stream, the received packets are encrypted cipher, diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index ff295d45f..5780cc489 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -4936,7 +4936,7 @@ bool SrsConfig::get_rtc_server_rtp_cache_enabled() uint64_t SrsConfig::get_rtc_server_rtp_cache_pkt_size() { - int DEFAULT = 128 * 1024 * 1024; + int DEFAULT = 64 * 1024 * 1024; SrsConfDirective* conf = get_rtc_server_rtp_cache(); if (!conf) { @@ -4948,12 +4948,12 @@ uint64_t SrsConfig::get_rtc_server_rtp_cache_pkt_size() return DEFAULT; } - return (uint64_t)(1024 * ::atof(conf->arg0().c_str())); + return 1024 * (uint64_t)(1024 * ::atof(conf->arg0().c_str())); } uint64_t SrsConfig::get_rtc_server_rtp_cache_payload_size() { - int DEFAULT = 32 * 1024 * 1024; + int DEFAULT = 16 * 1024 * 1024; SrsConfDirective* conf = get_rtc_server_rtp_cache(); if (!conf) { @@ -4965,7 +4965,7 @@ uint64_t SrsConfig::get_rtc_server_rtp_cache_payload_size() return DEFAULT; } - return (uint64_t)(1024 * ::atof(conf->arg0().c_str())); + return 1024 * (uint64_t)(1024 * ::atof(conf->arg0().c_str())); } SrsConfDirective* SrsConfig::get_rtc_server_rtp_msg_cache() @@ -5002,7 +5002,7 @@ bool SrsConfig::get_rtc_server_rtp_msg_cache_enabled() uint64_t SrsConfig::get_rtc_server_rtp_msg_cache_msg_size() { - int DEFAULT = 32 * 1024 * 1024; + int DEFAULT = 16 * 1024 * 1024; SrsConfDirective* conf = get_rtc_server_rtp_msg_cache(); if (!conf) { @@ -5014,12 +5014,12 @@ uint64_t SrsConfig::get_rtc_server_rtp_msg_cache_msg_size() return DEFAULT; } - return (uint64_t)(1024 * ::atof(conf->arg0().c_str())); + return 1024 * (uint64_t)(1024 * ::atof(conf->arg0().c_str())); } uint64_t SrsConfig::get_rtc_server_rtp_msg_cache_buffer_size() { - int DEFAULT = 1024 * 1024 * 1024; + int DEFAULT = 512 * 1024 * 1024; SrsConfDirective* conf = get_rtc_server_rtp_msg_cache(); if (!conf) { @@ -5031,7 +5031,7 @@ uint64_t SrsConfig::get_rtc_server_rtp_msg_cache_buffer_size() return DEFAULT; } - return (uint64_t)(1024 * ::atof(conf->arg0().c_str())); + return 1024 * (uint64_t)(1024 * ::atof(conf->arg0().c_str())); } bool SrsConfig::get_rtc_server_black_hole() diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index b2bad7285..9dbb9342b 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -282,17 +282,17 @@ srs_error_t SrsRtcServer::initialize() bool rtp_cache_enabled = _srs_config->get_rtc_server_rtp_cache_enabled(); uint64_t rtp_cache_pkt_size = _srs_config->get_rtc_server_rtp_cache_pkt_size(); uint64_t rtp_cache_payload_size = _srs_config->get_rtc_server_rtp_cache_payload_size(); - _srs_rtp_cache->set_enabled(rtp_cache_enabled, rtp_cache_pkt_size); - _srs_rtp_raw_cache->set_enabled(rtp_cache_enabled, rtp_cache_payload_size); - _srs_rtp_fua_cache->set_enabled(rtp_cache_enabled, rtp_cache_payload_size); + _srs_rtp_cache->setup(rtp_cache_enabled, rtp_cache_pkt_size); + _srs_rtp_raw_cache->setup(rtp_cache_enabled, rtp_cache_payload_size); + _srs_rtp_fua_cache->setup(rtp_cache_enabled, rtp_cache_payload_size); bool rtp_msg_cache_enabled = _srs_config->get_rtc_server_rtp_msg_cache_enabled(); uint64_t rtp_msg_cache_msg_size = _srs_config->get_rtc_server_rtp_msg_cache_msg_size(); uint64_t rtp_msg_cache_buffer_size = _srs_config->get_rtc_server_rtp_msg_cache_buffer_size(); - _srs_rtp_msg_cache_buffers->set_enabled(rtp_msg_cache_enabled, rtp_msg_cache_msg_size); - _srs_rtp_msg_cache_objs->set_enabled(rtp_msg_cache_enabled, rtp_msg_cache_buffer_size); + _srs_rtp_msg_cache_buffers->setup(rtp_msg_cache_enabled, rtp_msg_cache_buffer_size); + _srs_rtp_msg_cache_objs->setup(rtp_msg_cache_enabled, rtp_msg_cache_msg_size); - srs_trace("RTC server init ok, rtp-cache=(enabled:%d,pkt:%dm-%dw,payload:%dm-%dw-%dw), msg-cache=(enabled:%d,obj:%dm-%dw,buf:%dm-%dw)", + srs_trace("RTC: Object cache init, rtp-cache=(enabled:%d,pkt:%dm-%dw,payload:%dm-%dw-%dw), msg-cache=(enabled:%d,obj:%dm-%dw,buf:%dm-%dw)", rtp_cache_enabled, (int)(rtp_cache_pkt_size/1024/1024), _srs_rtp_cache->capacity()/10000, (int)(rtp_cache_payload_size/1024/1024), _srs_rtp_raw_cache->capacity()/10000, _srs_rtp_fua_cache->capacity()/10000, rtp_msg_cache_enabled, (int)(rtp_msg_cache_msg_size/1024/1024), _srs_rtp_msg_cache_objs->capacity()/10000, diff --git a/trunk/src/app/srs_app_rtc_server.hpp b/trunk/src/app/srs_app_rtc_server.hpp index 8dd4b5530..5ec4efbe5 100644 --- a/trunk/src/app/srs_app_rtc_server.hpp +++ b/trunk/src/app/srs_app_rtc_server.hpp @@ -97,6 +97,7 @@ public: virtual ~SrsRtcServer(); public: virtual srs_error_t initialize(); +public: // Set the handler for server events. void set_handler(ISrsRtcServerHandler* h); void set_hijacker(ISrsRtcServerHijacker* h); diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index 4d3b7271a..5b6bcab7f 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -826,16 +826,20 @@ SrsRtpPacket2::~SrsRtpPacket2() void SrsRtpPacket2::reuse() { - // Only recycle some common payloads. - SrsRtpRawPayload* raw_payload; - SrsRtpFUAPayload2* fua_payload; + if (_srs_rtp_raw_cache->enabled() || _srs_rtp_fua_cache->enabled()) { + // Only recycle some common payloads. + SrsRtpRawPayload* raw_payload; + SrsRtpFUAPayload2* fua_payload; - if ((raw_payload = dynamic_cast(payload)) != NULL) { - _srs_rtp_raw_cache->recycle(raw_payload); - payload = NULL; - } else if ((fua_payload = dynamic_cast(payload)) != NULL) { - _srs_rtp_fua_cache->recycle(fua_payload); - payload = NULL; + if ((raw_payload = dynamic_cast(payload)) != NULL) { + _srs_rtp_raw_cache->recycle(raw_payload); + payload = NULL; + } else if ((fua_payload = dynamic_cast(payload)) != NULL) { + _srs_rtp_fua_cache->recycle(fua_payload); + payload = NULL; + } else { + srs_freep(payload); + } } else { srs_freep(payload); } @@ -850,15 +854,19 @@ void SrsRtpPacket2::reuse_shared_msg() return; } - // We only recycle the RTC UDP packet messages. - if (shared_msg->payload && shared_msg->size == kRtpPacketSize && shared_msg->count() == 0) { - _srs_rtp_msg_cache_buffers->recycle(shared_msg); - } else { - shared_msg->unwrap(); - _srs_rtp_msg_cache_objs->recycle(shared_msg); - } + if (_srs_rtp_msg_cache_buffers->enabled() || _srs_rtp_msg_cache_objs->enabled()) { + // We only recycle the RTC UDP packet messages. + if (shared_msg->payload && shared_msg->size == kRtpPacketSize && shared_msg->count() == 0) { + _srs_rtp_msg_cache_buffers->recycle(shared_msg); + } else { + shared_msg->unwrap(); + _srs_rtp_msg_cache_objs->recycle(shared_msg); + } - shared_msg = NULL; + shared_msg = NULL; + } else { + srs_freep(shared_msg); + } } bool SrsRtpPacket2::reset() @@ -1047,12 +1055,12 @@ srs_error_t SrsRtpPacket2::decode(SrsBuffer* buf) return err; } -SrsRtpObjectCacheManager* _srs_rtp_cache = new SrsRtpObjectCacheManager(); -SrsRtpObjectCacheManager* _srs_rtp_raw_cache = new SrsRtpObjectCacheManager(); -SrsRtpObjectCacheManager* _srs_rtp_fua_cache = new SrsRtpObjectCacheManager(); +SrsRtpObjectCacheManager* _srs_rtp_cache = new SrsRtpObjectCacheManager(sizeof(SrsRtpPacket2)); +SrsRtpObjectCacheManager* _srs_rtp_raw_cache = new SrsRtpObjectCacheManager(sizeof(SrsRtpRawPayload)); +SrsRtpObjectCacheManager* _srs_rtp_fua_cache = new SrsRtpObjectCacheManager(sizeof(SrsRtpFUAPayload2)); -SrsRtpObjectCacheManager* _srs_rtp_msg_cache_buffers = new SrsRtpObjectCacheManager(); -SrsRtpObjectCacheManager* _srs_rtp_msg_cache_objs = new SrsRtpObjectCacheManager(); +SrsRtpObjectCacheManager* _srs_rtp_msg_cache_buffers = new SrsRtpObjectCacheManager(sizeof(SrsSharedPtrMessage) + kRtpPacketSize); +SrsRtpObjectCacheManager* _srs_rtp_msg_cache_objs = new SrsRtpObjectCacheManager(sizeof(SrsSharedPtrMessage)); SrsRtpRawPayload::SrsRtpRawPayload() { diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index 77366e714..652128c88 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -345,10 +345,12 @@ private: bool enabled_; std::list cache_objs_; size_t capacity_; + size_t object_size_; public: - SrsRtpObjectCacheManager() { + SrsRtpObjectCacheManager(size_t size_of_object) { enabled_ = false; capacity_ = 0; + object_size_ = size_of_object; } virtual ~SrsRtpObjectCacheManager() { typedef typename std::list::iterator iterator; @@ -358,11 +360,24 @@ public: } } public: - // Enable or disable cache. - void set_enabled(bool v, uint64_t memory) { + // Setup the object cache, shrink if capacity changed. + void setup(bool v, uint64_t memory) { enabled_ = v; - capacity_ = (size_t)(memory / sizeof(T)); + capacity_ = (size_t)(memory / object_size_); + + + if (!enabled_) { + capacity_ = 0; + } + + // Shrink the cache. + while (cache_objs_.size() > capacity_) { + T* obj = cache_objs_.back(); + cache_objs_.pop_back(); + srs_freep(obj); + } } + // Get the status of object cache. bool enabled() { return enabled_; } From 8e4f252686607100959923bc74ac0441357337a9 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 27 Feb 2021 08:21:04 +0800 Subject: [PATCH 034/102] Support reload the object cache pool --- trunk/src/app/srs_app_rtc_server.cpp | 40 ++++++++++++++++++++++++++++ trunk/src/app/srs_app_rtc_server.hpp | 5 +++- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index 9dbb9342b..45a4dc010 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -248,10 +248,14 @@ SrsRtcServer::SrsRtcServer() handler = NULL; hijacker = NULL; timer = new SrsHourGlass("server", this, 1 * SRS_UTIME_SECONDS); + + _srs_config->subscribe(this); } SrsRtcServer::~SrsRtcServer() { + _srs_config->unsubscribe(this); + srs_freep(timer); if (true) { @@ -301,6 +305,42 @@ srs_error_t SrsRtcServer::initialize() return err; } +srs_error_t SrsRtcServer::on_reload_rtc_server() +{ + bool changed = false; + + bool rtp_cache_enabled = _srs_config->get_rtc_server_rtp_cache_enabled(); + uint64_t rtp_cache_pkt_size = _srs_config->get_rtc_server_rtp_cache_pkt_size(); + uint64_t rtp_cache_payload_size = _srs_config->get_rtc_server_rtp_cache_payload_size(); + if (_srs_rtp_cache->enabled() != rtp_cache_enabled) { + _srs_rtp_cache->setup(rtp_cache_enabled, rtp_cache_pkt_size); + _srs_rtp_raw_cache->setup(rtp_cache_enabled, rtp_cache_payload_size); + _srs_rtp_fua_cache->setup(rtp_cache_enabled, rtp_cache_payload_size); + + changed = true; + } + + bool rtp_msg_cache_enabled = _srs_config->get_rtc_server_rtp_msg_cache_enabled(); + uint64_t rtp_msg_cache_msg_size = _srs_config->get_rtc_server_rtp_msg_cache_msg_size(); + uint64_t rtp_msg_cache_buffer_size = _srs_config->get_rtc_server_rtp_msg_cache_buffer_size(); + if (_srs_rtp_msg_cache_buffers->enabled() != rtp_msg_cache_enabled) { + _srs_rtp_msg_cache_buffers->setup(rtp_msg_cache_enabled, rtp_msg_cache_buffer_size); + _srs_rtp_msg_cache_objs->setup(rtp_msg_cache_enabled, rtp_msg_cache_msg_size); + + changed = true; + } + + if (changed) { + srs_trace("RTC: Object cache reload, rtp-cache=(enabled:%d,pkt:%dm-%dw,payload:%dm-%dw-%dw), msg-cache=(enabled:%d,obj:%dm-%dw,buf:%dm-%dw)", + rtp_cache_enabled, (int)(rtp_cache_pkt_size/1024/1024), _srs_rtp_cache->capacity()/10000, + (int)(rtp_cache_payload_size/1024/1024), _srs_rtp_raw_cache->capacity()/10000, _srs_rtp_fua_cache->capacity()/10000, + rtp_msg_cache_enabled, (int)(rtp_msg_cache_msg_size/1024/1024), _srs_rtp_msg_cache_objs->capacity()/10000, + (int)(rtp_msg_cache_buffer_size/1024/1024), _srs_rtp_msg_cache_buffers->capacity()/10000); + } + + return srs_success; +} + void SrsRtcServer::set_handler(ISrsRtcServerHandler* h) { handler = h; diff --git a/trunk/src/app/srs_app_rtc_server.hpp b/trunk/src/app/srs_app_rtc_server.hpp index 5ec4efbe5..0507666ea 100644 --- a/trunk/src/app/srs_app_rtc_server.hpp +++ b/trunk/src/app/srs_app_rtc_server.hpp @@ -85,7 +85,7 @@ public: }; // The RTC server instance, listen UDP port, handle UDP packet, manage RTC connections. -class SrsRtcServer : virtual public ISrsUdpMuxHandler, virtual public ISrsHourGlass +class SrsRtcServer : virtual public ISrsUdpMuxHandler, virtual public ISrsHourGlass, virtual public ISrsReloadHandler { private: SrsHourGlass* timer; @@ -97,6 +97,9 @@ public: virtual ~SrsRtcServer(); public: virtual srs_error_t initialize(); +// interface ISrsReloadHandler +public: + virtual srs_error_t on_reload_rtc_server(); public: // Set the handler for server events. void set_handler(ISrsRtcServerHandler* h); From 73e357a93f231a4f6202474ad27f152186910bd4 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 27 Feb 2021 09:18:02 +0800 Subject: [PATCH 035/102] RTC: Support object cache pool. 4.0.75 --- README.md | 1 + trunk/src/core/srs_core_version4.hpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 186a90f85..8ef8ca3d1 100755 --- a/README.md +++ b/README.md @@ -156,6 +156,7 @@ For previous versions, please read: ## V4 changes +* v4.0, 2021-02-27, RTC: Support object cache pool. 4.0.75 * v4.0, 2021-02-12, RTC: Support high performance timer about 25ms resolution. 4.0.72 * v4.0, 2021-02-10, RTC: Refine performance about 700+ streams. 4.0.71 * v4.0, 2021-02-08, RTC: Print stat for pli and timer every 5s. 4.0.70 diff --git a/trunk/src/core/srs_core_version4.hpp b/trunk/src/core/srs_core_version4.hpp index 3db4f439e..405bea09e 100644 --- a/trunk/src/core/srs_core_version4.hpp +++ b/trunk/src/core/srs_core_version4.hpp @@ -24,6 +24,6 @@ #ifndef SRS_CORE_VERSION4_HPP #define SRS_CORE_VERSION4_HPP -#define SRS_VERSION4_REVISION 74 +#define SRS_VERSION4_REVISION 75 #endif From 8d7a2017424beaa3a5f4afcea05f3b3fb57ee46b Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 27 Feb 2021 10:41:48 +0800 Subject: [PATCH 036/102] RTC: Remove unused config --- trunk/conf/full.conf | 7 ------- 1 file changed, 7 deletions(-) diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 3f31d0750..13bdc7638 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -490,13 +490,6 @@ rtc_server { # Whether enable the perf stat at http://localhost:1985/api/v1/perf # default: on perf_stat on; - # The queue length, in number of mmsghdr, in messages. - # For example, 30 means we will cache 30K messages at most. - # If exceed, we will drop messages. - # @remark Each reuseport use a dedicated queue, if queue is 2000, reuseport is 4, - # then system queue is 2000*4 = 8k, user can incrase reuseport to incrase the queue. - # default: 2000 - queue_length 2000; # For RTP packet and its payload cache. rtp_cache { # Whether enable the RTP packet cache. From f2d9eb345c712a145ac4bd847b71aea2bd29417c Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 27 Feb 2021 11:23:50 +0800 Subject: [PATCH 037/102] Perf: Refine object cache, avoid dynamic cast --- trunk/src/app/srs_app_rtc_conn.cpp | 6 +-- trunk/src/app/srs_app_rtc_conn.hpp | 2 +- trunk/src/app/srs_app_rtc_source.cpp | 20 ++++--- trunk/src/app/srs_app_rtc_source.hpp | 4 +- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 70 ++++++++++++++----------- trunk/src/kernel/srs_kernel_rtc_rtp.hpp | 23 ++++++-- 6 files changed, 76 insertions(+), 49 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 2ac360d5d..894d5c65f 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1268,7 +1268,7 @@ srs_error_t SrsRtcPublishStream::check_send_nacks() return err; } -void SrsRtcPublishStream::on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload) +void SrsRtcPublishStream::on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload, SrsRtpPacketPayloadType* ppt) { // No payload, ignore. if (buf->empty()) { @@ -1280,9 +1280,9 @@ void SrsRtcPublishStream::on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer SrsRtcVideoRecvTrack* video_track = get_video_track(ssrc); if (audio_track) { - audio_track->on_before_decode_payload(pkt, buf, ppayload); + audio_track->on_before_decode_payload(pkt, buf, ppayload, ppt); } else if (video_track) { - video_track->on_before_decode_payload(pkt, buf, ppayload); + video_track->on_before_decode_payload(pkt, buf, ppayload, ppt); } } diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 644c718f9..437857833 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -361,7 +361,7 @@ private: public: srs_error_t check_send_nacks(); public: - virtual void on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload); + virtual void on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload, SrsRtpPacketPayloadType* ppt); private: srs_error_t send_periodic_twcc(); public: diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index 87ef3fb24..54d7e2a1e 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -826,7 +826,7 @@ srs_error_t SrsRtcFromRtmpBridger::package_opus(char* data, int size, SrsRtpPack audio_timestamp += 960; SrsRtpRawPayload* raw = _srs_rtp_raw_cache->allocate(); - pkt->payload = raw; + pkt->set_payload(raw, SrsRtpPacketPayloadTypeRaw); raw->payload = pkt->wrap(data, size); raw->nn_payload = size; @@ -961,7 +961,7 @@ srs_error_t SrsRtcFromRtmpBridger::package_stap_a(SrsRtcStream* source, SrsShare pkt->header.set_timestamp(msg->timestamp * 90); SrsRtpSTAPPayload* stap = new SrsRtpSTAPPayload(); - pkt->payload = stap; + pkt->set_payload(stap, SrsRtpPacketPayloadTypeSTAP); uint8_t header = sps[0]; stap->nri = (SrsAvcNaluType)header; @@ -1041,7 +1041,7 @@ srs_error_t SrsRtcFromRtmpBridger::package_nalus(SrsSharedPtrMessage* msg, const pkt->nalu_type = (SrsAvcNaluType)first_nalu_type; pkt->header.set_sequence(video_sequence++); pkt->header.set_timestamp(msg->timestamp * 90); - pkt->payload = raw; + pkt->set_payload(raw, SrsRtpPacketPayloadTypeNALU); pkt->wrap(msg); } else { // We must free it, should never use RTP packets to free it, @@ -1082,7 +1082,7 @@ srs_error_t SrsRtcFromRtmpBridger::package_nalus(SrsSharedPtrMessage* msg, const fua->start = bool(i == 0); fua->end = bool(i == num_of_packet - 1); - pkt->payload = fua; + pkt->set_payload(fua, SrsRtpPacketPayloadTypeFUA); pkt->wrap(msg); nb_left -= packet_size; @@ -1108,7 +1108,7 @@ srs_error_t SrsRtcFromRtmpBridger::package_single_nalu(SrsSharedPtrMessage* msg, pkt->header.set_timestamp(msg->timestamp * 90); SrsRtpRawPayload* raw = _srs_rtp_raw_cache->allocate(); - pkt->payload = raw; + pkt->set_payload(raw, SrsRtpPacketPayloadTypeRaw); raw->payload = sample->bytes; raw->nn_payload = sample->size; @@ -1142,7 +1142,7 @@ srs_error_t SrsRtcFromRtmpBridger::package_fu_a(SrsSharedPtrMessage* msg, SrsSam pkt->header.set_timestamp(msg->timestamp * 90); SrsRtpFUAPayload2* fua = _srs_rtp_fua_cache->allocate(); - pkt->payload = fua; + pkt->set_payload(fua, SrsRtpPacketPayloadTypeFUA2); fua->nri = (SrsAvcNaluType)header; fua->nalu_type = (SrsAvcNaluType)nal_type; @@ -1854,7 +1854,7 @@ SrsRtcAudioRecvTrack::~SrsRtcAudioRecvTrack() { } -void SrsRtcAudioRecvTrack::on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload) +void SrsRtcAudioRecvTrack::on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload, SrsRtpPacketPayloadType* ppt) { // No payload, ignore. if (buf->empty()) { @@ -1862,6 +1862,7 @@ void SrsRtcAudioRecvTrack::on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffe } *ppayload = _srs_rtp_raw_cache->allocate(); + *ppt = SrsRtpPacketPayloadTypeRaw; } srs_error_t SrsRtcAudioRecvTrack::on_rtp(SrsRtcStream* source, SrsRtpPacket2* pkt, bool nack_enabled) @@ -1910,7 +1911,7 @@ SrsRtcVideoRecvTrack::~SrsRtcVideoRecvTrack() { } -void SrsRtcVideoRecvTrack::on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload) +void SrsRtcVideoRecvTrack::on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload, SrsRtpPacketPayloadType* ppt) { // No payload, ignore. if (buf->empty()) { @@ -1920,10 +1921,13 @@ void SrsRtcVideoRecvTrack::on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffe uint8_t v = (uint8_t)pkt->nalu_type; if (v == kStapA) { *ppayload = new SrsRtpSTAPPayload(); + *ppt = SrsRtpPacketPayloadTypeUnknown; } else if (v == kFuA) { *ppayload = _srs_rtp_fua_cache->allocate(); + *ppt = SrsRtpPacketPayloadTypeFUA2; } else { *ppayload = _srs_rtp_raw_cache->allocate(); + *ppt = SrsRtpPacketPayloadTypeRaw; } } diff --git a/trunk/src/app/srs_app_rtc_source.hpp b/trunk/src/app/srs_app_rtc_source.hpp index 5d8f03f99..d5155c263 100644 --- a/trunk/src/app/srs_app_rtc_source.hpp +++ b/trunk/src/app/srs_app_rtc_source.hpp @@ -549,7 +549,7 @@ public: SrsRtcAudioRecvTrack(SrsRtcConnection* session, SrsRtcTrackDescription* track_desc); virtual ~SrsRtcAudioRecvTrack(); public: - virtual void on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload); + virtual void on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload, SrsRtpPacketPayloadType* ppt); public: virtual srs_error_t on_rtp(SrsRtcStream* source, SrsRtpPacket2* pkt, bool nack_enabled); virtual srs_error_t check_send_nacks(); @@ -561,7 +561,7 @@ public: SrsRtcVideoRecvTrack(SrsRtcConnection* session, SrsRtcTrackDescription* stream_descs); virtual ~SrsRtcVideoRecvTrack(); public: - virtual void on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload); + virtual void on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload, SrsRtpPacketPayloadType* ppt); public: virtual srs_error_t on_rtp(SrsRtcStream* source, SrsRtpPacket2* pkt, bool nack_enabled); virtual srs_error_t check_send_nacks(); diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index 5b6bcab7f..e60be64d6 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -811,7 +811,7 @@ ISrsRtpPacketDecodeHandler::~ISrsRtpPacketDecodeHandler() SrsRtpPacket2::SrsRtpPacket2() { - payload = NULL; + payload_ = NULL; payload_type_ = SrsRtpPacketPayloadTypeUnknown; shared_msg = NULL; reset(); @@ -821,31 +821,31 @@ SrsRtpPacket2::SrsRtpPacket2() SrsRtpPacket2::~SrsRtpPacket2() { - reuse(); + reuse_payload(); + reuse_shared_msg(); } -void SrsRtpPacket2::reuse() +void SrsRtpPacket2::reuse_payload() { - if (_srs_rtp_raw_cache->enabled() || _srs_rtp_fua_cache->enabled()) { - // Only recycle some common payloads. - SrsRtpRawPayload* raw_payload; - SrsRtpFUAPayload2* fua_payload; - - if ((raw_payload = dynamic_cast(payload)) != NULL) { - _srs_rtp_raw_cache->recycle(raw_payload); - payload = NULL; - } else if ((fua_payload = dynamic_cast(payload)) != NULL) { - _srs_rtp_fua_cache->recycle(fua_payload); - payload = NULL; - } else { - srs_freep(payload); - } - } else { - srs_freep(payload); + if (!payload_) { + return; } - // Recycle the real owner of message, clear the reference. - reuse_shared_msg(); + if (_srs_rtp_raw_cache->enabled() || _srs_rtp_fua_cache->enabled()) { + // Only recycle some common payloads. + if (payload_type_ == SrsRtpPacketPayloadTypeRaw) { + _srs_rtp_raw_cache->recycle((SrsRtpRawPayload*)payload_); + } else if (payload_type_ == SrsRtpPacketPayloadTypeFUA2) { + _srs_rtp_fua_cache->recycle((SrsRtpFUAPayload2*)payload_); + } else { + srs_freep(payload_); + } + } else { + srs_freep(payload_); + } + + // Reset the payload and its type. + payload_ = NULL; payload_type_ = SrsRtpPacketPayloadTypeUnknown; } void SrsRtpPacket2::reuse_shared_msg() @@ -854,6 +854,7 @@ void SrsRtpPacket2::reuse_shared_msg() return; } + // Recycle the real owner of message, clear the reference. if (_srs_rtp_msg_cache_buffers->enabled() || _srs_rtp_msg_cache_objs->enabled()) { // We only recycle the RTC UDP packet messages. if (shared_msg->payload && shared_msg->size == kRtpPacketSize && shared_msg->count() == 0) { @@ -877,9 +878,8 @@ bool SrsRtpPacket2::reset() decode_handler = NULL; header.reset(); - - // Reset and reuse the payload and shared message. - reuse(); + reuse_payload(); + reuse_shared_msg(); return true; } @@ -967,11 +967,16 @@ SrsRtpPacket2* SrsRtpPacket2::copy() { SrsRtpPacket2* cp = _srs_rtp_cache->allocate(); + // We got packet from cache, so we must recycle it. + cp->reuse_payload(); + cp->reuse_shared_msg(); + cp->header = header; - cp->payload = payload? payload->copy():NULL; + cp->payload_ = payload_? payload_->copy():NULL; + cp->payload_type_ = payload_type_; cp->nalu_type = nalu_type; - cp->wrap(shared_msg); // Wrap the shared message and buffer. + cp->shared_msg = shared_msg->copy(); cp->frame_type = frame_type; cp->cached_payload_size = cached_payload_size; @@ -988,7 +993,7 @@ void SrsRtpPacket2::set_extension_types(const SrsRtpExtensionTypes* v) uint64_t SrsRtpPacket2::nb_bytes() { if (!cached_payload_size) { - int nn_payload = (payload? payload->nb_bytes():0); + int nn_payload = (payload_? payload_->nb_bytes():0); cached_payload_size = header.nb_bytes() + nn_payload + header.get_padding(); } return cached_payload_size; @@ -1002,7 +1007,7 @@ srs_error_t SrsRtpPacket2::encode(SrsBuffer* buf) return srs_error_wrap(err, "rtp header"); } - if (payload && (err = payload->encode(buf)) != srs_success) { + if (payload_ && (err = payload_->encode(buf)) != srs_success) { return srs_error_wrap(err, "rtp payload"); } @@ -1040,15 +1045,16 @@ srs_error_t SrsRtpPacket2::decode(SrsBuffer* buf) // If user set the decode handler, call it to set the payload. if (decode_handler) { - decode_handler->on_before_decode_payload(this, buf, &payload); + decode_handler->on_before_decode_payload(this, buf, &payload_, &payload_type_); } // By default, we always use the RAW payload. - if (!payload) { - payload = _srs_rtp_raw_cache->allocate(); + if (!payload_) { + payload_ = _srs_rtp_raw_cache->allocate(); + payload_type_ = SrsRtpPacketPayloadTypeRaw; } - if ((err = payload->decode(buf)) != srs_success) { + if ((err = payload_->decode(buf)) != srs_success) { return srs_error_wrap(err, "rtp payload"); } diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index 652128c88..7d3fd5f44 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -258,6 +258,7 @@ public: srs_error_t set_twcc_sequence_number(uint8_t id, uint16_t sn); }; +// The common payload interface for RTP packet. class ISrsRtpPayloader : public ISrsCodec { public: @@ -267,6 +268,17 @@ public: virtual ISrsRtpPayloader* copy() = 0; }; +// The payload type, for performance to avoid dynamic cast. +enum SrsRtpPacketPayloadType +{ + SrsRtpPacketPayloadTypeRaw, + SrsRtpPacketPayloadTypeFUA2, + SrsRtpPacketPayloadTypeFUA, + SrsRtpPacketPayloadTypeNALU, + SrsRtpPacketPayloadTypeSTAP, + SrsRtpPacketPayloadTypeUnknown, +}; + class ISrsRtpPacketDecodeHandler { public: @@ -274,7 +286,7 @@ public: virtual ~ISrsRtpPacketDecodeHandler(); public: // We don't know the actual payload, so we depends on external handler. - virtual void on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload) = 0; + virtual void on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload, SrsRtpPacketPayloadType* ppt) = 0; }; // The RTP packet with cached shared message. @@ -283,7 +295,9 @@ class SrsRtpPacket2 // RTP packet fields. public: SrsRtpHeader header; - ISrsRtpPayloader* payload; +private: + ISrsRtpPayloader* payload_; + SrsRtpPacketPayloadType payload_type_; private: // The original shared message, all RTP packets can refer to its data. SrsSharedPtrMessage* shared_msg; @@ -303,7 +317,7 @@ public: SrsRtpPacket2(); virtual ~SrsRtpPacket2(); private: - void reuse(); + void reuse_payload(); void reuse_shared_msg(); public: // Reset the object to reuse it. @@ -314,6 +328,9 @@ public: // Wrap the shared message, we copy it. char* wrap(SrsSharedPtrMessage* msg); public: + // Get and set the payload of packet. + void set_payload(ISrsRtpPayloader* p, SrsRtpPacketPayloadType pt) { payload_ = p; payload_type_ = pt; } + ISrsRtpPayloader* payload() { return payload_; } // Set the padding of RTP packet. void set_padding(int size); // Increase the padding of RTP packet. From 6656330d2aad6433452be793c56fef6f1ce8ea5b Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 27 Feb 2021 11:40:46 +0800 Subject: [PATCH 038/102] Perf: Use vector to replace list for object cache --- trunk/src/kernel/srs_kernel_rtc_rtp.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index 7d3fd5f44..005da46d3 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -31,6 +31,7 @@ #include #include +#include class SrsRtpPacket2; @@ -360,7 +361,7 @@ class SrsRtpObjectCacheManager { private: bool enabled_; - std::list cache_objs_; + std::vector cache_objs_; size_t capacity_; size_t object_size_; public: @@ -370,7 +371,7 @@ public: object_size_ = size_of_object; } virtual ~SrsRtpObjectCacheManager() { - typedef typename std::list::iterator iterator; + typedef typename std::vector::iterator iterator; for (iterator it = cache_objs_.begin(); it != cache_objs_.end(); ++it) { T* obj = *it; srs_freep(obj); From 1e2daf9ea389bc4428a81d10a420c7f806ea2d5f Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 27 Feb 2021 12:14:48 +0800 Subject: [PATCH 039/102] Refine comments for object cache --- trunk/src/kernel/srs_kernel_rtc_rtp.hpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index 005da46d3..70a128089 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -321,7 +321,7 @@ private: void reuse_payload(); void reuse_shared_msg(); public: - // Reset the object to reuse it. + // Recycle the object to reuse it. virtual bool reset(); // Wrap buffer to shared_message, which is managed by us. char* wrap(int size); @@ -365,11 +365,13 @@ private: size_t capacity_; size_t object_size_; public: + // SrsRtpObjectCacheManager::SrsRtpObjectCacheManager SrsRtpObjectCacheManager(size_t size_of_object) { enabled_ = false; capacity_ = 0; object_size_ = size_of_object; } + // SrsRtpObjectCacheManager::~SrsRtpObjectCacheManager virtual ~SrsRtpObjectCacheManager() { typedef typename std::vector::iterator iterator; for (iterator it = cache_objs_.begin(); it != cache_objs_.end(); ++it) { @@ -379,6 +381,7 @@ public: } public: // Setup the object cache, shrink if capacity changed. + // SrsRtpObjectCacheManager::setup void setup(bool v, uint64_t memory) { enabled_ = v; capacity_ = (size_t)(memory / object_size_); @@ -396,16 +399,20 @@ public: } } // Get the status of object cache. + // SrsRtpObjectCacheManager::enabled bool enabled() { return enabled_; } + // SrsRtpObjectCacheManager::size int size() { return (int)cache_objs_.size(); } + // SrsRtpObjectCacheManager::capacity int capacity() { return (int)capacity_; } // Try to allocate from cache, create new object if no cache. + // SrsRtpObjectCacheManager::allocate T* allocate() { while (true) { if (!enabled_ || cache_objs_.empty()) { @@ -426,6 +433,7 @@ public: } // Recycle the object to cache. // @remark User can directly free the packet. + // SrsRtpObjectCacheManager::recycle void recycle(T* p) { // The p may be NULL, because srs_freep(NULL) is ok. if (!p) { From aacdc21d1c72a9a55a5a8a797b0fc611fe63e44e Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 27 Feb 2021 12:32:46 +0800 Subject: [PATCH 040/102] Refine object cache. --- trunk/src/kernel/srs_kernel_flv.hpp | 2 +- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 29 +++++++++++-------- trunk/src/kernel/srs_kernel_rtc_rtp.hpp | 38 ++++++++++++------------- 3 files changed, 36 insertions(+), 33 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_flv.hpp b/trunk/src/kernel/srs_kernel_flv.hpp index d5a2bd2c3..c5e96394d 100644 --- a/trunk/src/kernel/srs_kernel_flv.hpp +++ b/trunk/src/kernel/srs_kernel_flv.hpp @@ -313,7 +313,7 @@ public: virtual ~SrsSharedPtrMessage(); public: // For object cache to reset and reuse it. - bool reset() { return true; } + bool recycle() { return true; } // Create shared ptr message, // copy header, manage the payload of msg, // set the payload to NULL to prevent double free. diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index e60be64d6..d292be75b 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -811,21 +811,25 @@ ISrsRtpPacketDecodeHandler::~ISrsRtpPacketDecodeHandler() SrsRtpPacket2::SrsRtpPacket2() { - payload_ = NULL; payload_type_ = SrsRtpPacketPayloadTypeUnknown; + payload_ = NULL; + payload_type_ = SrsRtpPacketPayloadTypeUnknown; shared_msg = NULL; - reset(); + nalu_type = SrsAvcNaluTypeReserved; + frame_type = SrsFrameTypeReserved; + cached_payload_size = 0; + decode_handler = NULL; ++_srs_pps_objs_rtps->sugar; } SrsRtpPacket2::~SrsRtpPacket2() { - reuse_payload(); - reuse_shared_msg(); + recycle_payload(); + recycle_shared_msg(); } -void SrsRtpPacket2::reuse_payload() +void SrsRtpPacket2::recycle_payload() { if (!payload_) { return; @@ -848,7 +852,7 @@ void SrsRtpPacket2::reuse_payload() payload_ = NULL; payload_type_ = SrsRtpPacketPayloadTypeUnknown; } -void SrsRtpPacket2::reuse_shared_msg() +void SrsRtpPacket2::recycle_shared_msg() { if (!shared_msg) { return; @@ -870,7 +874,7 @@ void SrsRtpPacket2::reuse_shared_msg() } } -bool SrsRtpPacket2::reset() +bool SrsRtpPacket2::recycle() { nalu_type = SrsAvcNaluTypeReserved; frame_type = SrsFrameTypeReserved; @@ -878,8 +882,9 @@ bool SrsRtpPacket2::reset() decode_handler = NULL; header.reset(); - reuse_payload(); - reuse_shared_msg(); + + recycle_payload(); + recycle_shared_msg(); return true; } @@ -929,7 +934,7 @@ char* SrsRtpPacket2::wrap(char* data, int size) char* SrsRtpPacket2::wrap(SrsSharedPtrMessage* msg) { // Recycle the shared message. - reuse_shared_msg(); + recycle_shared_msg(); // Copy from the new message. shared_msg = msg->copy(); @@ -968,8 +973,8 @@ SrsRtpPacket2* SrsRtpPacket2::copy() SrsRtpPacket2* cp = _srs_rtp_cache->allocate(); // We got packet from cache, so we must recycle it. - cp->reuse_payload(); - cp->reuse_shared_msg(); + cp->recycle_payload(); + cp->recycle_shared_msg(); cp->header = header; cp->payload_ = payload_? payload_->copy():NULL; diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index 70a128089..4a8e70938 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -318,11 +318,11 @@ public: SrsRtpPacket2(); virtual ~SrsRtpPacket2(); private: - void reuse_payload(); - void reuse_shared_msg(); + void recycle_payload(); + void recycle_shared_msg(); public: // Recycle the object to reuse it. - virtual bool reset(); + virtual bool recycle(); // Wrap buffer to shared_message, which is managed by us. char* wrap(int size); char* wrap(char* data, int size); @@ -414,22 +414,14 @@ public: // Try to allocate from cache, create new object if no cache. // SrsRtpObjectCacheManager::allocate T* allocate() { - while (true) { - if (!enabled_ || cache_objs_.empty()) { - return new T(); - } - - T* obj = cache_objs_.back(); - cache_objs_.pop_back(); - - // If reset the object fail, drop the cached object. - if (!obj->reset()) { - srs_freep(obj); - continue; - } - - return obj; + if (!enabled_ || cache_objs_.empty()) { + return new T(); } + + T* obj = cache_objs_.back(); + cache_objs_.pop_back(); + + return obj; } // Recycle the object to cache. // @remark User can directly free the packet. @@ -446,6 +438,12 @@ public: return; } + // If recycle the object fail, drop the cached object. + if (!p->recycle()) { + srs_freep(p); + return; + } + // If exceed the capacity, drop the object. if (cache_objs_.size() > capacity_) { ++_srs_pps_objs_drop->sugar; @@ -471,7 +469,7 @@ public: SrsRtpRawPayload(); virtual ~SrsRtpRawPayload(); public: - bool reset() { return true; } + bool recycle() { return true; } // interface ISrsRtpPayloader public: virtual uint64_t nb_bytes(); @@ -571,7 +569,7 @@ public: SrsRtpFUAPayload2(); virtual ~SrsRtpFUAPayload2(); public: - bool reset() { return true; } + bool recycle() { return true; } // interface ISrsRtpPayloader public: virtual uint64_t nb_bytes(); From db0090be05f3ec7986df079c0e140069b5053d4f Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 27 Feb 2021 12:33:33 +0800 Subject: [PATCH 041/102] Refine code --- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 44 ++++++++++++------------- trunk/src/kernel/srs_kernel_rtc_rtp.hpp | 4 +-- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index d292be75b..65cc16a40 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -942,6 +942,28 @@ char* SrsRtpPacket2::wrap(SrsSharedPtrMessage* msg) return msg->payload; } +SrsRtpPacket2* SrsRtpPacket2::copy() +{ + SrsRtpPacket2* cp = _srs_rtp_cache->allocate(); + + // We got packet from cache, so we must recycle it. + cp->recycle_payload(); + cp->recycle_shared_msg(); + + cp->header = header; + cp->payload_ = payload_? payload_->copy():NULL; + cp->payload_type_ = payload_type_; + + cp->nalu_type = nalu_type; + cp->shared_msg = shared_msg->copy(); + cp->frame_type = frame_type; + + cp->cached_payload_size = cached_payload_size; + cp->decode_handler = decode_handler; + + return cp; +} + void SrsRtpPacket2::set_padding(int size) { header.set_padding(size); @@ -968,28 +990,6 @@ bool SrsRtpPacket2::is_audio() return frame_type == SrsFrameTypeAudio; } -SrsRtpPacket2* SrsRtpPacket2::copy() -{ - SrsRtpPacket2* cp = _srs_rtp_cache->allocate(); - - // We got packet from cache, so we must recycle it. - cp->recycle_payload(); - cp->recycle_shared_msg(); - - cp->header = header; - cp->payload_ = payload_? payload_->copy():NULL; - cp->payload_type_ = payload_type_; - - cp->nalu_type = nalu_type; - cp->shared_msg = shared_msg->copy(); - cp->frame_type = frame_type; - - cp->cached_payload_size = cached_payload_size; - cp->decode_handler = decode_handler; - - return cp; -} - void SrsRtpPacket2::set_extension_types(const SrsRtpExtensionTypes* v) { return header.set_extensions(v); diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index 4a8e70938..15961894e 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -328,6 +328,8 @@ public: char* wrap(char* data, int size); // Wrap the shared message, we copy it. char* wrap(SrsSharedPtrMessage* msg); + // Copy the RTP packet. + virtual SrsRtpPacket2* copy(); public: // Get and set the payload of packet. void set_payload(ISrsRtpPayloader* p, SrsRtpPacketPayloadType pt) { payload_ = p; payload_type_ = pt; } @@ -340,8 +342,6 @@ public: void set_decode_handler(ISrsRtpPacketDecodeHandler* h); // Whether the packet is Audio packet. bool is_audio(); - // Copy the RTP packet. - virtual SrsRtpPacket2* copy(); // Set RTP header extensions for encoding or decoding header extension void set_extension_types(const SrsRtpExtensionTypes* v); // interface ISrsEncoder From 561acd26c5f7712a1a3595d6304285416b018174 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 27 Feb 2021 12:34:12 +0800 Subject: [PATCH 042/102] Refine code --- trunk/src/app/srs_app_rtc_source.cpp | 2 +- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index 54d7e2a1e..21c7f8c7b 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -1921,7 +1921,7 @@ void SrsRtcVideoRecvTrack::on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffe uint8_t v = (uint8_t)pkt->nalu_type; if (v == kStapA) { *ppayload = new SrsRtpSTAPPayload(); - *ppt = SrsRtpPacketPayloadTypeUnknown; + *ppt = SrsRtpPacketPayloadTypeSTAP; } else if (v == kFuA) { *ppayload = _srs_rtp_fua_cache->allocate(); *ppt = SrsRtpPacketPayloadTypeFUA2; diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index 65cc16a40..028677409 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -849,7 +849,8 @@ void SrsRtpPacket2::recycle_payload() } // Reset the payload and its type. - payload_ = NULL; payload_type_ = SrsRtpPacketPayloadTypeUnknown; + payload_ = NULL; + payload_type_ = SrsRtpPacketPayloadTypeUnknown; } void SrsRtpPacket2::recycle_shared_msg() From 29b33e6303b28289e4100de1029261b72742b787 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 27 Feb 2021 12:54:06 +0800 Subject: [PATCH 043/102] RTC: Disable player perf stat, because it should be refined. --- trunk/conf/full.conf | 5 +++-- trunk/src/app/srs_app_config.cpp | 4 ++-- trunk/src/app/srs_app_rtc_conn.cpp | 10 +++++----- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 13bdc7638..8cdbe363e 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -488,8 +488,9 @@ rtc_server { # default: off merge_nalus off; # Whether enable the perf stat at http://localhost:1985/api/v1/perf - # default: on - perf_stat on; + # TODO: FIXME: We should enable it when refined. + # default: off + perf_stat off; # For RTP packet and its payload cache. rtp_cache { # Whether enable the RTP packet cache. diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 5780cc489..164def7ef 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -4887,7 +4887,7 @@ bool SrsConfig::get_rtc_server_merge_nalus() bool SrsConfig::get_rtc_server_perf_stat() { - static bool DEFAULT = true; + static bool DEFAULT = false; SrsConfDirective* conf = root->get("rtc_server"); if (!conf) { @@ -4899,7 +4899,7 @@ bool SrsConfig::get_rtc_server_perf_stat() return DEFAULT; } - return SRS_CONF_PERFER_TRUE(conf->arg0()); + return SRS_CONF_PERFER_FALSE(conf->arg0()); } SrsConfDirective* SrsConfig::get_rtc_server_rtp_cache() diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 894d5c65f..23e7b6dc6 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -550,10 +550,13 @@ srs_error_t SrsRtcPlayStream::cycle() realtime = _srs_config->get_realtime_enabled(req_->vhost, true); mw_msgs = _srs_config->get_mw_msgs(req_->vhost, realtime, true); + bool stat_enabled = _srs_config->get_rtc_server_perf_stat(); + SrsStatistic* stat = SrsStatistic::instance(); + // TODO: FIXME: Add cost in ms. SrsContextId cid = source->source_id(); - srs_trace("RTC: start play url=%s, source_id=%s/%s, realtime=%d, mw_msgs=%d", req_->get_stream_url().c_str(), - cid.c_str(), source->pre_source_id().c_str(), realtime, mw_msgs); + srs_trace("RTC: start play url=%s, source_id=%s/%s, realtime=%d, mw_msgs=%d, stat=%d", req_->get_stream_url().c_str(), + cid.c_str(), source->pre_source_id().c_str(), realtime, mw_msgs, stat_enabled); SrsErrorPithyPrint* epp = new SrsErrorPithyPrint(); SrsAutoFree(SrsErrorPithyPrint, epp); @@ -561,9 +564,6 @@ srs_error_t SrsRtcPlayStream::cycle() SrsPithyPrint* pprint = SrsPithyPrint::create_rtc_play(); SrsAutoFree(SrsPithyPrint, pprint); - bool stat_enabled = _srs_config->get_rtc_server_perf_stat(); - SrsStatistic* stat = SrsStatistic::instance(); - // TODO: FIXME: Use cache for performance? vector pkts; uint64_t total_pkts = 0; From ecef3e7f0a9c994953f679736314a32ee0825045 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 27 Feb 2021 17:40:19 +0800 Subject: [PATCH 044/102] Perf: Refine player cycle, use fast coroutine --- trunk/src/app/srs_app_rtc_conn.cpp | 180 ++++++++++++++++----------- trunk/src/app/srs_app_rtc_conn.hpp | 6 +- trunk/src/app/srs_app_rtc_source.cpp | 44 +++---- trunk/src/app/srs_app_rtc_source.hpp | 12 +- trunk/src/app/srs_app_st.cpp | 72 ++++++++--- trunk/src/app/srs_app_st.hpp | 63 +++++++--- 6 files changed, 236 insertions(+), 141 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 23e7b6dc6..85b134f6a 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -382,7 +382,7 @@ SrsRtcPlayStreamStatistic::~SrsRtcPlayStreamStatistic() SrsRtcPlayStream::SrsRtcPlayStream(SrsRtcConnection* s, const SrsContextId& cid) { cid_ = cid; - trd = new SrsDummyCoroutine(); + trd_ = NULL; req_ = NULL; source_ = NULL; @@ -412,7 +412,7 @@ SrsRtcPlayStream::~SrsRtcPlayStream() srs_freep(nack_epp); srs_freep(pli_worker_); - srs_freep(trd); + srs_freep(trd_); srs_freep(timer_); srs_freep(req_); @@ -499,10 +499,10 @@ srs_error_t SrsRtcPlayStream::start() return err; } - srs_freep(trd); - trd = new SrsSTCoroutine("rtc_sender", this, cid_); + srs_freep(trd_); + trd_ = new SrsFastCoroutine("rtc_sender", this, cid_); - if ((err = trd->start()) != srs_success) { + if ((err = trd_->start()) != srs_success) { return srs_error_wrap(err, "rtc_sender"); } @@ -527,7 +527,9 @@ srs_error_t SrsRtcPlayStream::start() void SrsRtcPlayStream::stop() { - trd->stop(); + if (trd_) { + trd_->stop(); + } } srs_error_t SrsRtcPlayStream::cycle() @@ -550,24 +552,14 @@ srs_error_t SrsRtcPlayStream::cycle() realtime = _srs_config->get_realtime_enabled(req_->vhost, true); mw_msgs = _srs_config->get_mw_msgs(req_->vhost, realtime, true); - bool stat_enabled = _srs_config->get_rtc_server_perf_stat(); - SrsStatistic* stat = SrsStatistic::instance(); - // TODO: FIXME: Add cost in ms. SrsContextId cid = source->source_id(); - srs_trace("RTC: start play url=%s, source_id=%s/%s, realtime=%d, mw_msgs=%d, stat=%d", req_->get_stream_url().c_str(), - cid.c_str(), source->pre_source_id().c_str(), realtime, mw_msgs, stat_enabled); + srs_trace("RTC: start play url=%s, source_id=%s/%s, realtime=%d, mw_msgs=%d", req_->get_stream_url().c_str(), + cid.c_str(), source->pre_source_id().c_str(), realtime, mw_msgs); SrsErrorPithyPrint* epp = new SrsErrorPithyPrint(); SrsAutoFree(SrsErrorPithyPrint, epp); - SrsPithyPrint* pprint = SrsPithyPrint::create_rtc_play(); - SrsAutoFree(SrsPithyPrint, pprint); - - // TODO: FIXME: Use cache for performance? - vector pkts; - uint64_t total_pkts = 0; - if (_srs_rtc_hijacker) { if ((err = _srs_rtc_hijacker->on_start_consume(session_, this, req_, consumer)) != srs_success) { return srs_error_wrap(err, "on start consuming"); @@ -575,64 +567,30 @@ srs_error_t SrsRtcPlayStream::cycle() } while (true) { - if ((err = trd->pull()) != srs_success) { + if ((err = trd_->pull()) != srs_success) { return srs_error_wrap(err, "rtc sender thread"); } // Wait for amount of packets. - consumer->wait(mw_msgs); - - // TODO: FIXME: Handle error. - consumer->dump_packets(pkts); - - int msg_count = (int)pkts.size(); - if (!msg_count) { - continue; +try_dump_again: + SrsRtpPacket2* pkt = NULL; + consumer->dump_packet(&pkt); + if (!pkt) { + // TODO: FIXME: We should check the quit event. + consumer->wait(mw_msgs); + goto try_dump_again; } - // Update stats for session. - session_->stat_->nn_out_rtp += msg_count; - total_pkts += msg_count; - - // Send-out all RTP packets and do cleanup - if (true) { - if ((err = send_packets(source, pkts, info)) != srs_success) { - uint32_t nn = 0; - if (epp->can_print(err, &nn)) { - srs_warn("play send packets=%u, nn=%u/%u, err: %s", pkts.size(), epp->nn_count, nn, srs_error_desc(err).c_str()); - } - srs_freep(err); + // Send-out the RTP packet and do cleanup + if ((err = send_packet(pkt)) != srs_success) { + uint32_t nn = 0; + if (epp->can_print(err, &nn)) { + srs_warn("play send packets=%u, nn=%u/%u, err: %s", 1, epp->nn_count, nn, srs_error_desc(err).c_str()); } - - for (int i = 0; i < msg_count; i++) { - SrsRtpPacket2* pkt = pkts[i]; - _srs_rtp_cache->recycle(pkt); - } - pkts.clear(); + srs_freep(err); } - // Stat for performance analysis. - if (!stat_enabled) { - continue; - } - - // Stat the original RAW AV frame, maybe h264+aac. - stat->perf_on_msgs(msg_count); - // Stat the RTC packets, RAW AV frame, maybe h.264+opus. - int nn_rtc_packets = srs_max(info.nn_audios, info.nn_extras) + info.nn_videos; - stat->perf_on_rtc_packets(nn_rtc_packets); - // Stat the RAW RTP packets, which maybe group by GSO. - stat->perf_on_rtp_packets(msg_count); - // Stat the bytes and paddings. - stat->perf_on_rtc_bytes(info.nn_bytes, info.nn_rtp_bytes, info.nn_padding_bytes); - - pprint->elapse(); - if (pprint->can_print()) { - // TODO: FIXME: Print stat like frame/s, packet/s, loss_packets. - srs_trace("-> RTC PLAY %d msgs, %d/%d packets, %d audios, %d extras, %d videos, %d samples, %d/%d/%d bytes, %d pad, %d/%d cache", - total_pkts, msg_count, info.nn_rtp_pkts, info.nn_audios, info.nn_extras, info.nn_videos, info.nn_samples, info.nn_bytes, - info.nn_rtp_bytes, info.nn_padding_bytes, info.nn_paddings, msg_count, msg_count); - } + _srs_rtp_cache->recycle(pkt); } } @@ -640,7 +598,6 @@ srs_error_t SrsRtcPlayStream::send_packets(SrsRtcStream* source, const vector send_pkts; // Covert kernel messages to RTP packets. for (int i = 0; i < (int)pkts.size(); i++) { SrsRtpPacket2* pkt = pkts[i]; @@ -656,7 +613,7 @@ srs_error_t SrsRtcPlayStream::send_packets(SrsRtcStream* source, const vectorheader.get_ssrc()]; - if ((err = audio_track->on_rtp(pkt, info)) != srs_success) { + if ((err = audio_track->on_rtp(pkt)) != srs_success) { return srs_error_wrap(err, "audio track, SSRC=%u, SEQ=%u", pkt->header.get_ssrc(), pkt->header.get_sequence()); } @@ -665,7 +622,7 @@ srs_error_t SrsRtcPlayStream::send_packets(SrsRtcStream* source, const vectorheader.get_ssrc()]; - if ((err = video_track->on_rtp(pkt, info)) != srs_success) { + if ((err = video_track->on_rtp(pkt)) != srs_success) { return srs_error_wrap(err, "video track, SSRC=%u, SEQ=%u", pkt->header.get_ssrc(), pkt->header.get_sequence()); } } @@ -678,6 +635,42 @@ srs_error_t SrsRtcPlayStream::send_packets(SrsRtcStream* source, const vectorheader.get_ssrc()) && !video_tracks_.count(pkt->header.get_ssrc())) { + srs_warn("ssrc %u not found", pkt->header.get_ssrc()); + return err; + } + + // For audio, we transcoded AAC to opus in extra payloads. + if (pkt->is_audio()) { + // TODO: FIXME: Any simple solution? + SrsRtcAudioSendTrack* audio_track = audio_tracks_[pkt->header.get_ssrc()]; + + if ((err = audio_track->on_rtp(pkt)) != srs_success) { + return srs_error_wrap(err, "audio track, SSRC=%u, SEQ=%u", pkt->header.get_ssrc(), pkt->header.get_sequence()); + } + + // TODO: FIXME: Padding audio to the max payload in RTP packets. + } else { + // TODO: FIXME: Any simple solution? + SrsRtcVideoSendTrack* video_track = video_tracks_[pkt->header.get_ssrc()]; + + if ((err = video_track->on_rtp(pkt)) != srs_success) { + return srs_error_wrap(err, "video track, SSRC=%u, SEQ=%u", pkt->header.get_ssrc(), pkt->header.get_sequence()); + } + } + + // Detail log, should disable it in release version. + srs_info("RTC: Update PT=%u, SSRC=%#x, Time=%u, %u bytes", pkt->header.get_payload_type(), pkt->header.get_ssrc(), + pkt->header.get_timestamp(), pkt->nb_bytes()); + + return err; +} + void SrsRtcPlayStream::set_all_tracks_status(bool status) { std::ostringstream merged_log; @@ -805,7 +798,7 @@ srs_error_t SrsRtcPlayStream::on_rtcp_nack(SrsRtcpNack* rtcp) } vector seqs = rtcp->get_lost_sns(); - if((err = target->on_recv_nack(seqs, info)) != srs_success) { + if((err = target->on_recv_nack(seqs)) != srs_success) { return srs_error_wrap(err, "track response nack. id:%s, ssrc=%u", target->get_track_id().c_str(), ssrc); } @@ -2569,6 +2562,51 @@ srs_error_t SrsRtcConnection::do_send_packets(const std::vector& return err; } +srs_error_t SrsRtcConnection::do_send_packet(SrsRtpPacket2* pkt) +{ + srs_error_t err = srs_success; + + // For this message, select the first iovec. + iovec* iov = cache_iov_; + iov->iov_len = kRtpPacketSize; + cache_buffer_->skip(-1 * cache_buffer_->pos()); + + // Marshal packet to bytes in iovec. + if (true) { + if ((err = pkt->encode(cache_buffer_)) != srs_success) { + return srs_error_wrap(err, "encode packet"); + } + iov->iov_len = cache_buffer_->pos(); + } + + // Cipher RTP to SRTP packet. + if (true) { + int nn_encrypt = (int)iov->iov_len; + if ((err = transport_->protect_rtp(iov->iov_base, &nn_encrypt)) != srs_success) { + return srs_error_wrap(err, "srtp protect"); + } + iov->iov_len = (size_t)nn_encrypt; + } + + // For NACK simulator, drop packet. + if (nn_simulate_player_nack_drop) { + simulate_player_drop_packet(&pkt->header, (int)iov->iov_len); + iov->iov_len = 0; + return err; + } + + ++_srs_pps_srtps->sugar; + + // TODO: FIXME: Handle error. + sendonly_skt->sendto(iov->iov_base, iov->iov_len, 0); + + // Detail log, should disable it in release version. + srs_info("RTC: SEND PT=%u, SSRC=%#x, SEQ=%u, Time=%u, %u/%u bytes", pkt->header.get_payload_type(), pkt->header.get_ssrc(), + pkt->header.get_sequence(), pkt->header.get_timestamp(), pkt->nb_bytes(), iov->iov_len); + + return err; +} + void SrsRtcConnection::set_all_tracks_status(std::string stream_uri, bool is_publish, bool status) { // For publishers. diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 437857833..69c620b03 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -62,6 +62,8 @@ class SrsRtcConsumer; class SrsRtcAudioSendTrack; class SrsRtcVideoSendTrack; class SrsErrorPithyPrint; +class SrsPithyPrint; +class SrsStatistic; const uint8_t kSR = 200; const uint8_t kRR = 201; @@ -245,7 +247,7 @@ class SrsRtcPlayStream : virtual public ISrsCoroutineHandler, virtual public ISr { private: SrsContextId cid_; - SrsCoroutine* trd; + SrsFastCoroutine* trd_; SrsRtcConnection* session_; SrsRtcPLIWorker* pli_worker_; private: @@ -285,6 +287,7 @@ public: virtual srs_error_t cycle(); private: srs_error_t send_packets(SrsRtcStream* source, const std::vector& pkts, SrsRtcPlayStreamStatistic& info); + srs_error_t send_packet(SrsRtpPacket2* pkt); public: // Directly set the status of track, generally for init to set the default value. void set_all_tracks_status(bool status); @@ -549,6 +552,7 @@ public: void simulate_nack_drop(int nn); void simulate_player_drop_packet(SrsRtpHeader* h, int nn_bytes); srs_error_t do_send_packets(const std::vector& pkts, SrsRtcPlayStreamStatistic& info); + srs_error_t do_send_packet(SrsRtpPacket2* pkt); // Directly set the status of play track, generally for init to set the default value. void set_all_tracks_status(std::string stream_uri, bool is_publish, bool status); private: diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index 21c7f8c7b..7d2c149b7 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -197,7 +197,7 @@ srs_error_t SrsRtcConsumer::enqueue(SrsRtpPacket2* pkt) return err; } -srs_error_t SrsRtcConsumer::dump_packets(std::vector& pkts) +srs_error_t SrsRtcConsumer::dump_packet(SrsRtpPacket2** ppkt) { srs_error_t err = srs_success; @@ -206,7 +206,11 @@ srs_error_t SrsRtcConsumer::dump_packets(std::vector& pkts) should_update_source_id = false; } - queue.swap(pkts); + // TODO: FIXME: Refine performance by ring buffer. + if (!queue.empty()) { + *ppkt = queue.front(); + queue.erase(queue.begin()); + } return err; } @@ -2049,7 +2053,7 @@ std::string SrsRtcSendTrack::get_track_id() return track_desc_->id_; } -srs_error_t SrsRtcSendTrack::on_recv_nack(const vector& lost_seqs, SrsRtcPlayStreamStatistic& info) +srs_error_t SrsRtcSendTrack::on_recv_nack(const vector& lost_seqs) { srs_error_t err = srs_success; @@ -2066,18 +2070,14 @@ srs_error_t SrsRtcSendTrack::on_recv_nack(const vector& lost_seqs, Srs continue; } - info.nn_bytes += pkt->nb_bytes(); uint32_t nn = 0; if (nack_epp->can_print(pkt->header.get_ssrc(), &nn)) { srs_trace("RTC: NACK ARQ seq=%u, ssrc=%u, ts=%u, count=%u/%u, %d bytes", pkt->header.get_sequence(), pkt->header.get_ssrc(), pkt->header.get_timestamp(), nn, nack_epp->nn_count, pkt->nb_bytes()); } - vector resend_pkts; - resend_pkts.push_back(pkt); - // By default, we send packets by sendmmsg. - if ((err = session_->do_send_packets(resend_pkts, info)) != srs_success) { + if ((err = session_->do_send_packet(pkt)) != srs_success) { return srs_error_wrap(err, "raw send"); } } @@ -2094,7 +2094,7 @@ SrsRtcAudioSendTrack::~SrsRtcAudioSendTrack() { } -srs_error_t SrsRtcAudioSendTrack::on_rtp(SrsRtpPacket2* pkt, SrsRtcPlayStreamStatistic& info) +srs_error_t SrsRtcAudioSendTrack::on_rtp(SrsRtpPacket2* pkt) { srs_error_t err = srs_success; @@ -2122,8 +2122,6 @@ srs_error_t SrsRtcAudioSendTrack::on_rtp(SrsRtpPacket2* pkt, SrsRtcPlayStreamSta } // Update stats. - info.nn_bytes += pkt->nb_bytes(); - info.nn_audios++; session_->stat_->nn_out_audios++; // track level statistic @@ -2131,13 +2129,8 @@ srs_error_t SrsRtcAudioSendTrack::on_rtp(SrsRtpPacket2* pkt, SrsRtcPlayStreamSta statistic_->packets++; statistic_->bytes += pkt->nb_bytes(); - if (true) { - std::vector pkts; - pkts.push_back(pkt); - - if ((err = session_->do_send_packets(pkts, info)) != srs_success) { - return srs_error_wrap(err, "raw send"); - } + if ((err = session_->do_send_packet(pkt)) != srs_success) { + return srs_error_wrap(err, "raw send"); } return err; @@ -2159,7 +2152,7 @@ SrsRtcVideoSendTrack::~SrsRtcVideoSendTrack() { } -srs_error_t SrsRtcVideoSendTrack::on_rtp(SrsRtpPacket2* pkt, SrsRtcPlayStreamStatistic& info) +srs_error_t SrsRtcVideoSendTrack::on_rtp(SrsRtpPacket2* pkt) { srs_error_t err = srs_success; @@ -2189,8 +2182,6 @@ srs_error_t SrsRtcVideoSendTrack::on_rtp(SrsRtpPacket2* pkt, SrsRtcPlayStreamSta } // Update stats. - info.nn_bytes += pkt->nb_bytes(); - info.nn_videos++; session_->stat_->nn_out_videos++; // track level statistic @@ -2198,15 +2189,10 @@ srs_error_t SrsRtcVideoSendTrack::on_rtp(SrsRtpPacket2* pkt, SrsRtcPlayStreamSta statistic->packets++; statistic->bytes += pkt->nb_bytes(); - if (true) { - std::vector pkts; - pkts.push_back(pkt); - - if ((err = session_->do_send_packets(pkts, info)) != srs_success) { - return srs_error_wrap(err, "raw send"); - } + if ((err = session_->do_send_packet(pkt)) != srs_success) { + return srs_error_wrap(err, "raw send"); } - + return err; } diff --git a/trunk/src/app/srs_app_rtc_source.hpp b/trunk/src/app/srs_app_rtc_source.hpp index d5155c263..5bb7c42d9 100644 --- a/trunk/src/app/srs_app_rtc_source.hpp +++ b/trunk/src/app/srs_app_rtc_source.hpp @@ -97,8 +97,8 @@ public: // Put RTP packet into queue. // @note We do not drop packet here, but drop it in sender. srs_error_t enqueue(SrsRtpPacket2* pkt); - // Get all RTP packets from queue. - virtual srs_error_t dump_packets(std::vector& pkts); + // For RTC, we only got one packet, because there is not many packets in queue. + virtual srs_error_t dump_packet(SrsRtpPacket2** ppkt); // Wait for at-least some messages incoming in queue. virtual void wait(int nb_msgs); }; @@ -591,9 +591,9 @@ public: bool get_track_status(); std::string get_track_id(); public: - virtual srs_error_t on_rtp(SrsRtpPacket2* pkt, SrsRtcPlayStreamStatistic& info) = 0; + virtual srs_error_t on_rtp(SrsRtpPacket2* pkt) = 0; virtual srs_error_t on_rtcp(SrsRtpPacket2* pkt) = 0; - virtual srs_error_t on_recv_nack(const std::vector& lost_seqs, SrsRtcPlayStreamStatistic& info); + virtual srs_error_t on_recv_nack(const std::vector& lost_seqs); }; class SrsRtcAudioSendTrack : public SrsRtcSendTrack @@ -602,7 +602,7 @@ public: SrsRtcAudioSendTrack(SrsRtcConnection* session, SrsRtcTrackDescription* track_desc); virtual ~SrsRtcAudioSendTrack(); public: - virtual srs_error_t on_rtp(SrsRtpPacket2* pkt, SrsRtcPlayStreamStatistic& info); + virtual srs_error_t on_rtp(SrsRtpPacket2* pkt); virtual srs_error_t on_rtcp(SrsRtpPacket2* pkt); }; @@ -612,7 +612,7 @@ public: SrsRtcVideoSendTrack(SrsRtcConnection* session, SrsRtcTrackDescription* track_desc); virtual ~SrsRtcVideoSendTrack(); public: - virtual srs_error_t on_rtp(SrsRtpPacket2* pkt, SrsRtcPlayStreamStatistic& info); + virtual srs_error_t on_rtp(SrsRtpPacket2* pkt); virtual srs_error_t on_rtcp(SrsRtpPacket2* pkt); }; diff --git a/trunk/src/app/srs_app_st.cpp b/trunk/src/app/srs_app_st.cpp index b11c50fd1..5a1954a4b 100755 --- a/trunk/src/app/srs_app_st.cpp +++ b/trunk/src/app/srs_app_st.cpp @@ -87,9 +87,54 @@ const SrsContextId& SrsDummyCoroutine::cid() return _srs_context->get_id(); } +SrsSTCoroutine::SrsSTCoroutine(string n, ISrsCoroutineHandler* h) +{ + impl_ = new SrsFastCoroutine(n, h); +} + +SrsSTCoroutine::SrsSTCoroutine(string n, ISrsCoroutineHandler* h, SrsContextId cid) +{ + impl_ = new SrsFastCoroutine(n, h, cid); +} + +SrsSTCoroutine::~SrsSTCoroutine() +{ + srs_freep(impl_); +} + +void SrsSTCoroutine::set_stack_size(int v) +{ + impl_->set_stack_size(v); +} + +srs_error_t SrsSTCoroutine::start() +{ + return impl_->start(); +} + +void SrsSTCoroutine::stop() +{ + impl_->stop(); +} + +void SrsSTCoroutine::interrupt() +{ + impl_->interrupt(); +} + +srs_error_t SrsSTCoroutine::pull() +{ + return impl_->pull(); +} + +const SrsContextId& SrsSTCoroutine::cid() +{ + return impl_->cid(); +} + _ST_THREAD_CREATE_PFN _pfn_st_thread_create = (_ST_THREAD_CREATE_PFN)st_thread_create; -SrsSTCoroutine::SrsSTCoroutine(string n, ISrsCoroutineHandler* h) +SrsFastCoroutine::SrsFastCoroutine(string n, ISrsCoroutineHandler* h) { // TODO: FIXME: Reduce duplicated code. name = n; @@ -102,7 +147,7 @@ SrsSTCoroutine::SrsSTCoroutine(string n, ISrsCoroutineHandler* h) stack_size = 0; } -SrsSTCoroutine::SrsSTCoroutine(string n, ISrsCoroutineHandler* h, SrsContextId cid) +SrsFastCoroutine::SrsFastCoroutine(string n, ISrsCoroutineHandler* h, SrsContextId cid) { name = n; handler = h; @@ -115,19 +160,19 @@ SrsSTCoroutine::SrsSTCoroutine(string n, ISrsCoroutineHandler* h, SrsContextId c stack_size = 0; } -SrsSTCoroutine::~SrsSTCoroutine() +SrsFastCoroutine::~SrsFastCoroutine() { stop(); srs_freep(trd_err); } -void SrsSTCoroutine::set_stack_size(int v) +void SrsFastCoroutine::set_stack_size(int v) { stack_size = v; } -srs_error_t SrsSTCoroutine::start() +srs_error_t SrsFastCoroutine::start() { srs_error_t err = srs_success; @@ -159,7 +204,7 @@ srs_error_t SrsSTCoroutine::start() return err; } -void SrsSTCoroutine::stop() +void SrsFastCoroutine::stop() { if (disposed) { return; @@ -190,7 +235,7 @@ void SrsSTCoroutine::stop() return; } -void SrsSTCoroutine::interrupt() +void SrsFastCoroutine::interrupt() { if (!started || interrupted || cycle_done) { return; @@ -204,17 +249,12 @@ void SrsSTCoroutine::interrupt() st_thread_interrupt((st_thread_t)trd); } -srs_error_t SrsSTCoroutine::pull() -{ - return srs_error_copy(trd_err); -} - -const SrsContextId& SrsSTCoroutine::cid() +const SrsContextId& SrsFastCoroutine::cid() { return cid_; } -srs_error_t SrsSTCoroutine::cycle() +srs_error_t SrsFastCoroutine::cycle() { if (_srs_context) { if (cid_.empty()) { @@ -234,9 +274,9 @@ srs_error_t SrsSTCoroutine::cycle() return err; } -void* SrsSTCoroutine::pfn(void* arg) +void* SrsFastCoroutine::pfn(void* arg) { - SrsSTCoroutine* p = (SrsSTCoroutine*)arg; + SrsFastCoroutine* p = (SrsFastCoroutine*)arg; srs_error_t err = p->cycle(); diff --git a/trunk/src/app/srs_app_st.hpp b/trunk/src/app/srs_app_st.hpp index 42313ed7a..89d118ce9 100644 --- a/trunk/src/app/srs_app_st.hpp +++ b/trunk/src/app/srs_app_st.hpp @@ -29,9 +29,12 @@ #include #include +#include #include #include +class SrsFastCoroutine; + // Each ST-coroutine must implements this interface, // to do the cycle job and handle some events. // @@ -108,10 +111,6 @@ public: virtual const SrsContextId& cid(); }; -// For utest to mock the thread create. -typedef void* (*_ST_THREAD_CREATE_PFN)(void *(*start)(void *arg), void *arg, int joinable, int stack_size); -extern _ST_THREAD_CREATE_PFN _pfn_st_thread_create; - // A ST-coroutine is a lightweight thread, just like the goroutine. // But the goroutine maybe run on different thread, while ST-coroutine only // run in single thread, because it use setjmp and longjmp, so it may cause @@ -127,19 +126,7 @@ extern _ST_THREAD_CREATE_PFN _pfn_st_thread_create; class SrsSTCoroutine : public SrsCoroutine { private: - std::string name; - int stack_size; - ISrsCoroutineHandler* handler; -private: - srs_thread_t trd; - SrsContextId cid_; - srs_error_t trd_err; -private: - bool started; - bool interrupted; - bool disposed; - // Cycle done, no need to interrupt it. - bool cycle_done; + SrsFastCoroutine* impl_; public: // Create a thread with name n and handler h. // @remark User can specify a cid for thread to use, or we will allocate a new one. @@ -170,8 +157,48 @@ public: virtual srs_error_t pull(); // Get the context id of thread. virtual const SrsContextId& cid(); +}; + +// For utest to mock the thread create. +typedef void* (*_ST_THREAD_CREATE_PFN)(void *(*start)(void *arg), void *arg, int joinable, int stack_size); +extern _ST_THREAD_CREATE_PFN _pfn_st_thread_create; + +// High performance coroutine. +class SrsFastCoroutine +{ private: - virtual srs_error_t cycle(); + std::string name; + int stack_size; + ISrsCoroutineHandler* handler; +private: + srs_thread_t trd; + SrsContextId cid_; + srs_error_t trd_err; +private: + bool started; + bool interrupted; + bool disposed; + // Cycle done, no need to interrupt it. + bool cycle_done; +public: + SrsFastCoroutine(std::string n, ISrsCoroutineHandler* h); + SrsFastCoroutine(std::string n, ISrsCoroutineHandler* h, SrsContextId cid); + ~SrsFastCoroutine(); +public: + void set_stack_size(int v); +public: + srs_error_t start(); + void stop(); + void interrupt(); + inline srs_error_t pull() { + if (trd_err == srs_success) { + return srs_success; + } + return srs_error_copy(trd_err); + } + const SrsContextId& cid(); +private: + srs_error_t cycle(); static void* pfn(void* arg); }; From e2bf9f3623fc8e4aabe2fe9f2ef32cbaafd05bb9 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 27 Feb 2021 17:53:59 +0800 Subject: [PATCH 045/102] Refine code, remove goto --- trunk/src/app/srs_app_rtc_conn.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 85b134f6a..d14e3d8d7 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -572,13 +572,12 @@ srs_error_t SrsRtcPlayStream::cycle() } // Wait for amount of packets. -try_dump_again: SrsRtpPacket2* pkt = NULL; consumer->dump_packet(&pkt); if (!pkt) { // TODO: FIXME: We should check the quit event. consumer->wait(mw_msgs); - goto try_dump_again; + continue; } // Send-out the RTP packet and do cleanup From e44170224698c12a404c44a81ae90aced9ccf072 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 27 Feb 2021 18:39:09 +0800 Subject: [PATCH 046/102] Refine code --- trunk/src/kernel/srs_kernel_flv.cpp | 6 +-- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 67 +++++++++++++------------ trunk/src/kernel/srs_kernel_rtc_rtp.hpp | 7 ++- 3 files changed, 42 insertions(+), 38 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_flv.cpp b/trunk/src/kernel/srs_kernel_flv.cpp index 5fd1f0929..a06e387df 100644 --- a/trunk/src/kernel/srs_kernel_flv.cpp +++ b/trunk/src/kernel/srs_kernel_flv.cpp @@ -290,11 +290,11 @@ void SrsSharedPtrMessage::wrap(char* payload, int size) void SrsSharedPtrMessage::unwrap() { if (ptr) { - if (ptr->shared_count == 0) { - srs_freep(ptr); - } else { + if (ptr->shared_count > 0) { ptr->shared_count--; ptr = NULL; + } else { + srs_freep(ptr); } } diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index 028677409..072d9bfd4 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -778,11 +778,6 @@ void SrsRtpHeader::set_ssrc(uint32_t v) ssrc = v; } -uint32_t SrsRtpHeader::get_ssrc() const -{ - return ssrc; -} - void SrsRtpHeader::set_padding(uint8_t v) { padding_length = v; @@ -835,21 +830,21 @@ void SrsRtpPacket2::recycle_payload() return; } - if (_srs_rtp_raw_cache->enabled() || _srs_rtp_fua_cache->enabled()) { - // Only recycle some common payloads. - if (payload_type_ == SrsRtpPacketPayloadTypeRaw) { - _srs_rtp_raw_cache->recycle((SrsRtpRawPayload*)payload_); - } else if (payload_type_ == SrsRtpPacketPayloadTypeFUA2) { - _srs_rtp_fua_cache->recycle((SrsRtpFUAPayload2*)payload_); - } else { - srs_freep(payload_); - } - } else { - srs_freep(payload_); + if (payload_type_ == SrsRtpPacketPayloadTypeRaw && _srs_rtp_raw_cache->enabled()) { + _srs_rtp_raw_cache->recycle((SrsRtpRawPayload*)payload_); + payload_ = NULL; + goto cleanup; } - // Reset the payload and its type. - payload_ = NULL; + if (payload_type_ == SrsRtpPacketPayloadTypeFUA2 && _srs_rtp_fua_cache->enabled()) { + _srs_rtp_fua_cache->recycle((SrsRtpFUAPayload2*)payload_); + payload_ = NULL; + goto cleanup; + } + + srs_freep(payload_); + +cleanup: payload_type_ = SrsRtpPacketPayloadTypeUnknown; } @@ -859,20 +854,22 @@ void SrsRtpPacket2::recycle_shared_msg() return; } - // Recycle the real owner of message, clear the reference. - if (_srs_rtp_msg_cache_buffers->enabled() || _srs_rtp_msg_cache_objs->enabled()) { - // We only recycle the RTC UDP packet messages. - if (shared_msg->payload && shared_msg->size == kRtpPacketSize && shared_msg->count() == 0) { - _srs_rtp_msg_cache_buffers->recycle(shared_msg); - } else { - shared_msg->unwrap(); - _srs_rtp_msg_cache_objs->recycle(shared_msg); - } - - shared_msg = NULL; - } else { - srs_freep(shared_msg); + if (!shared_msg->payload || shared_msg->size != kRtpPacketSize || shared_msg->count() > 0) { + shared_msg->unwrap(); + _srs_rtp_msg_cache_objs->recycle(shared_msg); + goto cleanup; } + + if (_srs_rtp_msg_cache_buffers->enabled()) { + _srs_rtp_msg_cache_buffers->recycle(shared_msg); + goto cleanup; + } + + srs_freep(shared_msg); + return; + +cleanup: + shared_msg = NULL; } bool SrsRtpPacket2::recycle() @@ -948,8 +945,12 @@ SrsRtpPacket2* SrsRtpPacket2::copy() SrsRtpPacket2* cp = _srs_rtp_cache->allocate(); // We got packet from cache, so we must recycle it. - cp->recycle_payload(); - cp->recycle_shared_msg(); + if (cp->payload_) { + cp->recycle_payload(); + } + if (cp->shared_msg) { + cp->recycle_shared_msg(); + } cp->header = header; cp->payload_ = payload_? payload_->copy():NULL; diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index 15961894e..e3fb55eb6 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -250,7 +250,10 @@ public: void set_timestamp(uint32_t v); uint32_t get_timestamp() const; void set_ssrc(uint32_t v); - uint32_t get_ssrc() const; + // SrsRtpHeader::get_ssrc + inline uint32_t get_ssrc() const { + return ssrc; + } void set_padding(uint8_t v); uint8_t get_padding() const; void set_extensions(const SrsRtpExtensionTypes* extmap); @@ -400,7 +403,7 @@ public: } // Get the status of object cache. // SrsRtpObjectCacheManager::enabled - bool enabled() { + inline bool enabled() { return enabled_; } // SrsRtpObjectCacheManager::size From 0fa3646c4a11b73bec77857fa32a4e32560cd1f2 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 27 Feb 2021 19:41:16 +0800 Subject: [PATCH 047/102] Perf: Directly reference the extmap --- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 28 ++++++++----------------- trunk/src/kernel/srs_kernel_rtc_rtp.hpp | 15 ++++++------- 2 files changed, 17 insertions(+), 26 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index 072d9bfd4..17f2bf7b3 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -165,18 +165,13 @@ int32_t srs_seq_distance(uint16_t value, uint16_t pre_value) SrsRtpExtensionTypes::SrsRtpExtensionTypes() { - reset(); + memset(ids_, kRtpExtensionNone, sizeof(ids_)); } SrsRtpExtensionTypes::~SrsRtpExtensionTypes() { } -void SrsRtpExtensionTypes::reset() -{ - memset(ids_, kRtpExtensionNone, sizeof(ids_)); -} - bool SrsRtpExtensionTypes::register_by_uri(int id, std::string uri) { for (int i = 0; i < (int)(sizeof(kExtensions)/sizeof(kExtensions[0])); ++i) { @@ -377,13 +372,10 @@ SrsRtpExtensions::~SrsRtpExtensions() void SrsRtpExtensions::reset() { - if (has_ext_) { - types_.reset(); - twcc_.reset(); - audio_level_.reset(); - } - has_ext_ = false; + types_ = NULL; + twcc_.reset(); + audio_level_.reset(); } srs_error_t SrsRtpExtensions::decode(SrsBuffer* buf) @@ -445,7 +437,7 @@ srs_error_t SrsRtpExtensions::decode_0xbede(SrsBuffer* buf) uint8_t id = (v & 0xF0) >> 4; uint8_t len = (v & 0x0F); - SrsRtpExtensionType xtype = types_.get_type(id); + SrsRtpExtensionType xtype = types_? types_->get_type(id) : kRtpExtensionNone; if (xtype == kRtpExtensionTransportSequenceNumber) { if ((err = twcc_.decode(buf)) != srs_success) { return srs_error_wrap(err, "decode twcc extension"); @@ -522,11 +514,9 @@ bool SrsRtpExtensions::exists() return has_ext_; } -void SrsRtpExtensions::set_types_(const SrsRtpExtensionTypes* types) +void SrsRtpExtensions::set_types_(SrsRtpExtensionTypes* types) { - if(types) { - types_ = *types; - } + types_ = types; } srs_error_t SrsRtpExtensions::get_twcc_sequence_number(uint16_t& twcc_sn) @@ -703,7 +693,7 @@ srs_error_t SrsRtpHeader::encode(SrsBuffer* buf) return err; } -void SrsRtpHeader::set_extensions(const SrsRtpExtensionTypes* extmap) +void SrsRtpHeader::set_extensions(SrsRtpExtensionTypes* extmap) { if (extmap) { extensions_.set_types_(extmap); @@ -992,7 +982,7 @@ bool SrsRtpPacket2::is_audio() return frame_type == SrsFrameTypeAudio; } -void SrsRtpPacket2::set_extension_types(const SrsRtpExtensionTypes* v) +void SrsRtpPacket2::set_extension_types(SrsRtpExtensionTypes* v) { return header.set_extensions(v); } diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index e3fb55eb6..34baa77e2 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -122,9 +122,6 @@ public: public: SrsRtpExtensionTypes(); virtual ~SrsRtpExtensionTypes(); -public: - // Reset the object to reuse it. - void reset(); private: bool register_id(int id, SrsRtpExtensionType type, std::string uri); private: @@ -187,7 +184,11 @@ class SrsRtpExtensions// : public ISrsCodec { private: bool has_ext_; - SrsRtpExtensionTypes types_; +private: + // The extension types is used to decode the packet, which is reference to + // the types in publish stream. + SrsRtpExtensionTypes* types_; +private: SrsRtpExtensionTwcc twcc_; SrsRtpExtensionOneByte audio_level_; public: @@ -198,7 +199,7 @@ public: void reset(); public: bool exists(); - void set_types_(const SrsRtpExtensionTypes* types); + void set_types_(SrsRtpExtensionTypes* types); srs_error_t get_twcc_sequence_number(uint16_t& twcc_sn); srs_error_t set_twcc_sequence_number(uint8_t id, uint16_t sn); srs_error_t get_audio_level(uint8_t& level); @@ -256,7 +257,7 @@ public: } void set_padding(uint8_t v); uint8_t get_padding() const; - void set_extensions(const SrsRtpExtensionTypes* extmap); + void set_extensions(SrsRtpExtensionTypes* extmap); void ignore_padding(bool v); srs_error_t get_twcc_sequence_number(uint16_t& twcc_sn); srs_error_t set_twcc_sequence_number(uint8_t id, uint16_t sn); @@ -346,7 +347,7 @@ public: // Whether the packet is Audio packet. bool is_audio(); // Set RTP header extensions for encoding or decoding header extension - void set_extension_types(const SrsRtpExtensionTypes* v); + void set_extension_types(SrsRtpExtensionTypes* v); // interface ISrsEncoder public: virtual uint64_t nb_bytes(); From 6d64490d738ff6b8f51f80dce80bb1297bec9416 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 27 Feb 2021 19:49:44 +0800 Subject: [PATCH 048/102] Perf: Never reset the csrc --- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index 17f2bf7b3..76d651da9 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -202,8 +202,6 @@ SrsRtpExtensionType SrsRtpExtensionTypes::get_type(int id) const return kInvalidType; } - - SrsRtpExtensionTwcc::SrsRtpExtensionTwcc() { reset(); @@ -556,6 +554,8 @@ srs_error_t SrsRtpExtensions::set_audio_level(int id, uint8_t level) SrsRtpHeader::SrsRtpHeader() { reset(); + + memset(csrc, 0, sizeof(csrc)); } SrsRtpHeader::~SrsRtpHeader() @@ -564,17 +564,23 @@ SrsRtpHeader::~SrsRtpHeader() void SrsRtpHeader::reset() { - padding_length = 0; + // Reset the fields in protocol. cc = 0; marker = false; payload_type = 0; sequence = 0; timestamp = 0; ssrc = 0; - memset(csrc, 0, sizeof(csrc)); + + // Reset the parsed fields. + padding_length = 0; + extensions_.reset(); + + // Reset other fields. ignore_padding_ = false; - extensions_.reset(); + // The CSRC is not used yet, so we never reset it. + //memset(csrc, 0, sizeof(csrc)); } srs_error_t SrsRtpHeader::decode(SrsBuffer* buf) From cca5f8db826833dd180f208723ea320e01e362db Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 27 Feb 2021 19:55:57 +0800 Subject: [PATCH 049/102] Refine code --- trunk/src/app/srs_app_rtc_conn.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index d14e3d8d7..e3d228846 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1203,6 +1203,7 @@ srs_error_t SrsRtcPublishStream::do_on_rtp_plaintext(SrsRtpPacket2* pkt, SrsBuff pkt->set_decode_handler(this); pkt->set_extension_types(&extension_types_); + pkt->ignore_padding(false); if ((err = pkt->decode(buf)) != srs_success) { return srs_error_wrap(err, "decode rtp packet"); From 00b0e22402a50939755e36ec2f3c9dad6581fd50 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 27 Feb 2021 20:05:28 +0800 Subject: [PATCH 050/102] Refine code --- trunk/src/app/srs_app_rtc_conn.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index e3d228846..3b63af1cc 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1203,7 +1203,7 @@ srs_error_t SrsRtcPublishStream::do_on_rtp_plaintext(SrsRtpPacket2* pkt, SrsBuff pkt->set_decode_handler(this); pkt->set_extension_types(&extension_types_); - pkt->ignore_padding(false); + pkt->header.ignore_padding(false); if ((err = pkt->decode(buf)) != srs_success) { return srs_error_wrap(err, "decode rtp packet"); From 81dddcbd93891b13760d1b03ce7b0964f777b14b Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 27 Feb 2021 21:46:50 +0800 Subject: [PATCH 051/102] RTC: Remove dead code --- trunk/src/app/srs_app_rtc_conn.cpp | 108 --------------------------- trunk/src/app/srs_app_rtc_conn.hpp | 36 --------- trunk/src/app/srs_app_rtc_source.hpp | 1 - 3 files changed, 145 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 3b63af1cc..a8b205b84 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -366,19 +366,6 @@ srs_error_t SrsRtcPLIWorker::cycle() return err; } -SrsRtcPlayStreamStatistic::SrsRtcPlayStreamStatistic() -{ - nn_rtp_pkts = 0; - nn_audios = nn_extras = 0; - nn_videos = nn_samples = 0; - nn_bytes = nn_rtp_bytes = 0; - nn_padding_bytes = nn_paddings = 0; -} - -SrsRtcPlayStreamStatistic::~SrsRtcPlayStreamStatistic() -{ -} - SrsRtcPlayStream::SrsRtcPlayStream(SrsRtcConnection* s, const SrsContextId& cid) { cid_ = cid; @@ -593,47 +580,6 @@ srs_error_t SrsRtcPlayStream::cycle() } } -srs_error_t SrsRtcPlayStream::send_packets(SrsRtcStream* source, const vector& pkts, SrsRtcPlayStreamStatistic& info) -{ - srs_error_t err = srs_success; - - // Covert kernel messages to RTP packets. - for (int i = 0; i < (int)pkts.size(); i++) { - SrsRtpPacket2* pkt = pkts[i]; - - // TODO: FIXME: Maybe refine for performance issue. - if (!audio_tracks_.count(pkt->header.get_ssrc()) && !video_tracks_.count(pkt->header.get_ssrc())) { - srs_warn("ssrc %u not found", pkt->header.get_ssrc()); - continue; - } - - // For audio, we transcoded AAC to opus in extra payloads. - if (pkt->is_audio()) { - // TODO: FIXME: Any simple solution? - SrsRtcAudioSendTrack* audio_track = audio_tracks_[pkt->header.get_ssrc()]; - - if ((err = audio_track->on_rtp(pkt)) != srs_success) { - return srs_error_wrap(err, "audio track, SSRC=%u, SEQ=%u", pkt->header.get_ssrc(), pkt->header.get_sequence()); - } - - // TODO: FIXME: Padding audio to the max payload in RTP packets. - } else { - // TODO: FIXME: Any simple solution? - SrsRtcVideoSendTrack* video_track = video_tracks_[pkt->header.get_ssrc()]; - - if ((err = video_track->on_rtp(pkt)) != srs_success) { - return srs_error_wrap(err, "video track, SSRC=%u, SEQ=%u", pkt->header.get_ssrc(), pkt->header.get_sequence()); - } - } - - // Detail log, should disable it in release version. - srs_info("RTC: Update PT=%u, SSRC=%#x, Time=%u, %u bytes", pkt->header.get_payload_type(), pkt->header.get_ssrc(), - pkt->header.get_timestamp(), pkt->nb_bytes()); - } - - return err; -} - srs_error_t SrsRtcPlayStream::send_packet(SrsRtpPacket2* pkt) { srs_error_t err = srs_success; @@ -2508,60 +2454,6 @@ void SrsRtcConnection::simulate_player_drop_packet(SrsRtpHeader* h, int nn_bytes nn_simulate_player_nack_drop--; } -srs_error_t SrsRtcConnection::do_send_packets(const std::vector& pkts, SrsRtcPlayStreamStatistic& info) -{ - srs_error_t err = srs_success; - - for (int i = 0; i < (int)pkts.size(); i++) { - SrsRtpPacket2* pkt = pkts.at(i); - - // For this message, select the first iovec. - iovec* iov = cache_iov_; - iov->iov_len = kRtpPacketSize; - cache_buffer_->skip(-1 * cache_buffer_->pos()); - - // Marshal packet to bytes in iovec. - if (true) { - if ((err = pkt->encode(cache_buffer_)) != srs_success) { - return srs_error_wrap(err, "encode packet"); - } - iov->iov_len = cache_buffer_->pos(); - } - - // Cipher RTP to SRTP packet. - if (true) { - int nn_encrypt = (int)iov->iov_len; - if ((err = transport_->protect_rtp(iov->iov_base, &nn_encrypt)) != srs_success) { - return srs_error_wrap(err, "srtp protect"); - } - iov->iov_len = (size_t)nn_encrypt; - } - - info.nn_rtp_bytes += (int)iov->iov_len; - - // When we send out a packet, increase the stat counter. - info.nn_rtp_pkts++; - - // For NACK simulator, drop packet. - if (nn_simulate_player_nack_drop) { - simulate_player_drop_packet(&pkt->header, (int)iov->iov_len); - iov->iov_len = 0; - continue; - } - - ++_srs_pps_srtps->sugar; - - // TODO: FIXME: Handle error. - sendonly_skt->sendto(iov->iov_base, iov->iov_len, 0); - - // Detail log, should disable it in release version. - srs_info("RTC: SEND PT=%u, SSRC=%#x, SEQ=%u, Time=%u, %u/%u bytes", pkt->header.get_payload_type(), pkt->header.get_ssrc(), - pkt->header.get_sequence(), pkt->header.get_timestamp(), pkt->nb_bytes(), iov->iov_len); - } - - return err; -} - srs_error_t SrsRtcConnection::do_send_packet(SrsRtpPacket2* pkt) { srs_error_t err = srs_success; diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 69c620b03..f3aa8e2e4 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -209,38 +209,6 @@ public: virtual srs_error_t cycle(); }; -// A group of RTP packets for outgoing(send to players). -class SrsRtcPlayStreamStatistic -{ -public: - // The total bytes of AVFrame packets. - int nn_bytes; - // The total bytes of RTP packets. - int nn_rtp_bytes; - // The total padded bytes. - int nn_padding_bytes; -public: - // The RTP packets send out by sendmmsg or sendmsg. Note that if many packets group to - // one msghdr by GSO, it's only one RTP packet, because we only send once. - int nn_rtp_pkts; - // For video, the samples or NALUs. - // TODO: FIXME: Remove it because we may don't know. - int nn_samples; - // For audio, the generated extra audio packets. - // For example, when transcoding AAC to opus, may many extra payloads for a audio. - // TODO: FIXME: Remove it because we may don't know. - int nn_extras; - // The original audio messages. - int nn_audios; - // The original video messages. - int nn_videos; - // The number of padded packet. - int nn_paddings; -public: - SrsRtcPlayStreamStatistic(); - virtual ~SrsRtcPlayStreamStatistic(); -}; - // A RTC play stream, client pull and play stream from SRS. class SrsRtcPlayStream : virtual public ISrsCoroutineHandler, virtual public ISrsReloadHandler , virtual public ISrsHourGlass, virtual public ISrsRtcPLIWorkerHandler @@ -268,8 +236,6 @@ private: private: // Whether palyer started. bool is_started; - // The statistic for consumer to send packets to player. - SrsRtcPlayStreamStatistic info; public: SrsRtcPlayStream(SrsRtcConnection* s, const SrsContextId& cid); virtual ~SrsRtcPlayStream(); @@ -286,7 +252,6 @@ public: public: virtual srs_error_t cycle(); private: - srs_error_t send_packets(SrsRtcStream* source, const std::vector& pkts, SrsRtcPlayStreamStatistic& info); srs_error_t send_packet(SrsRtpPacket2* pkt); public: // Directly set the status of track, generally for init to set the default value. @@ -551,7 +516,6 @@ public: // Simulate the NACK to drop nn packets. void simulate_nack_drop(int nn); void simulate_player_drop_packet(SrsRtpHeader* h, int nn_bytes); - srs_error_t do_send_packets(const std::vector& pkts, SrsRtcPlayStreamStatistic& info); srs_error_t do_send_packet(SrsRtpPacket2* pkt); // Directly set the status of play track, generally for init to set the default value. void set_all_tracks_status(std::string stream_uri, bool is_publish, bool status); diff --git a/trunk/src/app/srs_app_rtc_source.hpp b/trunk/src/app/srs_app_rtc_source.hpp index 5bb7c42d9..a1fe0b4f7 100644 --- a/trunk/src/app/srs_app_rtc_source.hpp +++ b/trunk/src/app/srs_app_rtc_source.hpp @@ -55,7 +55,6 @@ class SrsRtcConnection; class SrsRtpRingBuffer; class SrsRtpNackForReceiver; class SrsJsonObject; -class SrsRtcPlayStreamStatistic; class SrsErrorPithyPrint; class SrsRtcDummyBridger; From b1457dfc16e83354e9e172852a7aea2558f0740b Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 27 Feb 2021 22:00:00 +0800 Subject: [PATCH 052/102] Perf: Refine copy RTP header. --- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 50 ++++++++++++++++++++++++- trunk/src/kernel/srs_kernel_rtc_rtp.hpp | 11 ++++-- 2 files changed, 55 insertions(+), 6 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index 76d651da9..488fccea7 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -218,6 +218,13 @@ void SrsRtpExtensionTwcc::reset() sn_ = 0; } +void SrsRtpExtensionTwcc::assign(const SrsRtpExtensionTwcc& h) +{ + has_twcc_ = h.has_twcc_; + id_ = h.id_; + sn_ = h.sn_; +} + bool SrsRtpExtensionTwcc::has_twcc_ext() { return has_twcc_; @@ -311,6 +318,13 @@ void SrsRtpExtensionOneByte::reset() value_ = 0; } +void SrsRtpExtensionOneByte::assign(const SrsRtpExtensionOneByte& h) +{ + has_ext_ = h.has_ext_; + id_ = h.id_; + value_ = h.value_; +} + void SrsRtpExtensionOneByte::set_id(int id) { id_ = id; @@ -370,10 +384,21 @@ SrsRtpExtensions::~SrsRtpExtensions() void SrsRtpExtensions::reset() { - has_ext_ = false; types_ = NULL; twcc_.reset(); audio_level_.reset(); + has_ext_ = false; +} + +void SrsRtpExtensions::assign(const SrsRtpExtensions& h) +{ + has_ext_ = h.has_ext_; + types_ = h.types_; + + if (has_ext_) { + twcc_.assign(h.twcc_); + audio_level_.assign(h.audio_level_); + } } srs_error_t SrsRtpExtensions::decode(SrsBuffer* buf) @@ -583,6 +608,27 @@ void SrsRtpHeader::reset() //memset(csrc, 0, sizeof(csrc)); } +void SrsRtpHeader::assign(const SrsRtpHeader& h) +{ + // Reset the fields in protocol. + cc = h.cc; + marker = h.marker; + payload_type = h.payload_type; + sequence = h.sequence; + timestamp = h.timestamp; + ssrc = h.ssrc; + + // Reset the parsed fields. + padding_length = h.padding_length; + extensions_.assign(h.extensions_); + + // Reset other fields. + ignore_padding_ = h.ignore_padding_; + + // The CSRC is not used yet, so we never reset it. + //memcpy(csrc, h.csrc, sizeof(csrc)); +} + srs_error_t SrsRtpHeader::decode(SrsBuffer* buf) { srs_error_t err = srs_success; @@ -948,7 +994,7 @@ SrsRtpPacket2* SrsRtpPacket2::copy() cp->recycle_shared_msg(); } - cp->header = header; + cp->header.assign(header); cp->payload_ = payload_? payload_->copy():NULL; cp->payload_type_ = payload_type_; diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index 34baa77e2..4503a73e6 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -140,14 +140,14 @@ public: public: // Reset the object to reuse it. void reset(); - + void assign(const SrsRtpExtensionTwcc& h); +public: bool has_twcc_ext(); uint8_t get_id(); void set_id(uint8_t id); uint16_t get_sn(); void set_sn(uint16_t sn); - -public: +public: // ISrsCodec virtual srs_error_t decode(SrsBuffer* buf); virtual srs_error_t encode(SrsBuffer* buf); @@ -166,7 +166,8 @@ public: public: // Reset the object to reuse it. void reset(); - + void assign(const SrsRtpExtensionOneByte& h); +public: bool exists() { return has_ext_; } int get_id() { return id_; } uint8_t get_value() { return value_; } @@ -197,6 +198,7 @@ public: public: // Reset the object to reuse it. void reset(); + void assign(const SrsRtpExtensions& h); public: bool exists(); void set_types_(SrsRtpExtensionTypes* types); @@ -234,6 +236,7 @@ public: public: // Reset the object to reuse it. void reset(); + void assign(const SrsRtpHeader& h); public: virtual srs_error_t decode(SrsBuffer* buf); private: From 033f341ce1023c0c9c95880a7734ec6fd0862359 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 27 Feb 2021 22:09:06 +0800 Subject: [PATCH 053/102] Perf: Refine the recycle RTP packet, user should reset it --- trunk/src/app/srs_app_rtc_conn.cpp | 3 +++ trunk/src/app/srs_app_rtc_source.cpp | 3 +++ trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 25 +++++++++++++++++-------- trunk/src/kernel/srs_kernel_rtc_rtp.hpp | 4 ++++ 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index a8b205b84..cdd528b0a 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1130,6 +1130,9 @@ srs_error_t SrsRtcPublishStream::on_rtp_plaintext(char* plaintext, int nb_plaint // Allocate packet form cache. SrsRtpPacket2* pkt = _srs_rtp_cache->allocate(); + // It's better to reset it before decode it. + pkt->reset(); + // Copy the packet body. char* p = pkt->wrap(plaintext, nb_plaintext); diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index 7d2c149b7..c2f96f918 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -589,6 +589,9 @@ std::vector SrsRtcStream::get_track_desc(std::string ty SrsRtpPacketCacheHelper::SrsRtpPacketCacheHelper() { pkt = _srs_rtp_cache->allocate(); + + // We MUST reset the packet, when got from cache. + pkt->reset(); } SrsRtpPacketCacheHelper::~SrsRtpPacketCacheHelper() diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index 488fccea7..1b387fde0 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -866,6 +866,21 @@ SrsRtpPacket2::~SrsRtpPacket2() recycle_shared_msg(); } +void SrsRtpPacket2::reset() +{ + nalu_type = SrsAvcNaluTypeReserved; + frame_type = SrsFrameTypeReserved; + cached_payload_size = 0; + decode_handler = NULL; + + // It's important to reset the header. + header.reset(); + + // Recyle the payload again, to ensure the packet is new one. + recycle_payload(); + recycle_shared_msg(); +} + void SrsRtpPacket2::recycle_payload() { if (!payload_) { @@ -916,16 +931,10 @@ cleanup: bool SrsRtpPacket2::recycle() { - nalu_type = SrsAvcNaluTypeReserved; - frame_type = SrsFrameTypeReserved; - cached_payload_size = 0; - decode_handler = NULL; - - header.reset(); - + // We only recycle the payload and shared messages, + // for header and fields, user will reset or copy it. recycle_payload(); recycle_shared_msg(); - return true; } diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index 4503a73e6..ec4b44a99 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -324,6 +324,10 @@ private: public: SrsRtpPacket2(); virtual ~SrsRtpPacket2(); +public: + // User MUST reset the packet if got from cache, + // except copy(we will assign the header and copy payload). + void reset(); private: void recycle_payload(); void recycle_shared_msg(); From 3728b07c49bf623c258812ddbf6ff513c5c5910b Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 27 Feb 2021 23:03:08 +0800 Subject: [PATCH 054/102] Perf: Refine RTP packet copy --- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index 1b387fde0..3e2d12677 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -931,10 +931,16 @@ cleanup: bool SrsRtpPacket2::recycle() { + // Clear the cache size, it may change when reuse it. + cached_payload_size = 0; + // Reset the handler, for decode only. + decode_handler = NULL; + // We only recycle the payload and shared messages, // for header and fields, user will reset or copy it. recycle_payload(); recycle_shared_msg(); + return true; } @@ -995,13 +1001,10 @@ SrsRtpPacket2* SrsRtpPacket2::copy() { SrsRtpPacket2* cp = _srs_rtp_cache->allocate(); - // We got packet from cache, so we must recycle it. - if (cp->payload_) { - cp->recycle_payload(); - } - if (cp->shared_msg) { - cp->recycle_shared_msg(); - } + // We got packet from cache, the payload and message MUST be NULL, + // because we had clear it in recycle. + //srs_assert(!cp->payload_); + //srs_assert(!cp->shared_msg); cp->header.assign(header); cp->payload_ = payload_? payload_->copy():NULL; @@ -1011,8 +1014,9 @@ SrsRtpPacket2* SrsRtpPacket2::copy() cp->shared_msg = shared_msg->copy(); cp->frame_type = frame_type; - cp->cached_payload_size = cached_payload_size; - cp->decode_handler = decode_handler; + // For performance issue, do not copy the unused field. + //cp->cached_payload_size = cached_payload_size; + //cp->decode_handler = decode_handler; return cp; } From 42223b3f2e4afbb267fe875b326778d5eff472e2 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 27 Feb 2021 23:10:46 +0800 Subject: [PATCH 055/102] RTC: No cache for RTP packet size. --- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 18 ++---------------- trunk/src/kernel/srs_kernel_rtc_rtp.hpp | 3 --- 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index 3e2d12677..eb770735c 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -854,7 +854,6 @@ SrsRtpPacket2::SrsRtpPacket2() nalu_type = SrsAvcNaluTypeReserved; frame_type = SrsFrameTypeReserved; - cached_payload_size = 0; decode_handler = NULL; ++_srs_pps_objs_rtps->sugar; @@ -870,7 +869,6 @@ void SrsRtpPacket2::reset() { nalu_type = SrsAvcNaluTypeReserved; frame_type = SrsFrameTypeReserved; - cached_payload_size = 0; decode_handler = NULL; // It's important to reset the header. @@ -931,8 +929,6 @@ cleanup: bool SrsRtpPacket2::recycle() { - // Clear the cache size, it may change when reuse it. - cached_payload_size = 0; // Reset the handler, for decode only. decode_handler = NULL; @@ -1015,7 +1011,6 @@ SrsRtpPacket2* SrsRtpPacket2::copy() cp->frame_type = frame_type; // For performance issue, do not copy the unused field. - //cp->cached_payload_size = cached_payload_size; //cp->decode_handler = decode_handler; return cp; @@ -1024,17 +1019,11 @@ SrsRtpPacket2* SrsRtpPacket2::copy() void SrsRtpPacket2::set_padding(int size) { header.set_padding(size); - if (cached_payload_size) { - cached_payload_size += size - header.get_padding(); - } } void SrsRtpPacket2::add_padding(int size) { header.set_padding(header.get_padding() + size); - if (cached_payload_size) { - cached_payload_size += size; - } } void SrsRtpPacket2::set_decode_handler(ISrsRtpPacketDecodeHandler* h) @@ -1054,11 +1043,8 @@ void SrsRtpPacket2::set_extension_types(SrsRtpExtensionTypes* v) uint64_t SrsRtpPacket2::nb_bytes() { - if (!cached_payload_size) { - int nn_payload = (payload_? payload_->nb_bytes():0); - cached_payload_size = header.nb_bytes() + nn_payload + header.get_padding(); - } - return cached_payload_size; + int nn_payload = (payload_? payload_->nb_bytes():0); + return header.nb_bytes() + nn_payload + header.get_padding(); } srs_error_t SrsRtpPacket2::encode(SrsBuffer* buf) diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index ec4b44a99..1c119e0bc 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -315,10 +315,7 @@ public: SrsAvcNaluType nalu_type; // The frame type, for RTMP bridger or SFU source. SrsFrameType frame_type; -// Fast cache for performance. private: - // The cached payload size for packet. - int cached_payload_size; // The helper handler for decoder, use RAW payload if NULL. ISrsRtpPacketDecodeHandler* decode_handler; public: From f831e9240ed0fc83810b8838d6817ff88b0bc319 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 27 Feb 2021 23:29:52 +0800 Subject: [PATCH 056/102] RTC: Fast copy shared message for RTP --- trunk/src/kernel/srs_kernel_flv.cpp | 23 +++++++++++++++-------- trunk/src/kernel/srs_kernel_flv.hpp | 2 ++ trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 4 +++- trunk/src/kernel/srs_kernel_rtc_rtp.hpp | 4 +++- 4 files changed, 23 insertions(+), 10 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_flv.cpp b/trunk/src/kernel/srs_kernel_flv.cpp index a06e387df..0706cd487 100644 --- a/trunk/src/kernel/srs_kernel_flv.cpp +++ b/trunk/src/kernel/srs_kernel_flv.cpp @@ -361,14 +361,7 @@ SrsSharedPtrMessage* SrsSharedPtrMessage::copy() { srs_assert(ptr); - SrsSharedPtrMessage* copy = _srs_rtp_msg_cache_objs->allocate(); - - // We got an object from cache, the ptr might exists, so unwrap it. - copy->unwrap(); - - // Reference to this message instead. - copy->ptr = ptr; - ptr->shared_count++; + SrsSharedPtrMessage* copy = copy2(); copy->timestamp = timestamp; copy->stream_id = stream_id; @@ -378,6 +371,20 @@ SrsSharedPtrMessage* SrsSharedPtrMessage::copy() return copy; } +SrsSharedPtrMessage* SrsSharedPtrMessage::copy2() +{ + SrsSharedPtrMessage* copy = _srs_rtp_msg_cache_objs->allocate(); + + // We got an object from cache, the ptr might exists, so unwrap it. + //srs_assert(!copy->ptr); + + // Reference to this message instead. + copy->ptr = ptr; + ptr->shared_count++; + + return copy; +} + SrsFlvTransmuxer::SrsFlvTransmuxer() { writer = NULL; diff --git a/trunk/src/kernel/srs_kernel_flv.hpp b/trunk/src/kernel/srs_kernel_flv.hpp index c5e96394d..0cc6102ac 100644 --- a/trunk/src/kernel/srs_kernel_flv.hpp +++ b/trunk/src/kernel/srs_kernel_flv.hpp @@ -351,6 +351,8 @@ public: // copy current shared ptr message, use ref-count. // @remark, assert object is created. virtual SrsSharedPtrMessage* copy(); + // Only copy the buffer, without header fields. + virtual SrsSharedPtrMessage* copy2(); }; // Transmux RTMP packets to FLV stream. diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index eb770735c..36822a43f 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -910,6 +910,8 @@ void SrsRtpPacket2::recycle_shared_msg() } if (!shared_msg->payload || shared_msg->size != kRtpPacketSize || shared_msg->count() > 0) { + // Note that we must unwrap the shared message, because this object pool only cache the + // shared message itself without payload. shared_msg->unwrap(); _srs_rtp_msg_cache_objs->recycle(shared_msg); goto cleanup; @@ -1007,7 +1009,7 @@ SrsRtpPacket2* SrsRtpPacket2::copy() cp->payload_type_ = payload_type_; cp->nalu_type = nalu_type; - cp->shared_msg = shared_msg->copy(); + cp->shared_msg = shared_msg->copy2(); cp->frame_type = frame_type; // For performance issue, do not copy the unused field. diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index 1c119e0bc..b7947fa8c 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -591,8 +591,10 @@ extern SrsRtpObjectCacheManager* _srs_rtp_cache; extern SrsRtpObjectCacheManager* _srs_rtp_raw_cache; extern SrsRtpObjectCacheManager* _srs_rtp_fua_cache; -// For RTP packet shared messages cache. +// For shared message cache, with payload. extern SrsRtpObjectCacheManager* _srs_rtp_msg_cache_buffers; +// For shared message cache, without payload. +// Note that user must unwrap the shared message, before recycle it. extern SrsRtpObjectCacheManager* _srs_rtp_msg_cache_objs; #endif From 0aeaf442f77c24c83a82b0f35e69c251a9f79f5d Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 28 Feb 2021 06:56:53 +0800 Subject: [PATCH 057/102] RTC: Ignore NACK when disable for player. --- trunk/src/app/srs_app_rtc_conn.cpp | 32 ++++++++++++++++++++++++---- trunk/src/app/srs_app_rtc_source.cpp | 24 +++++++++++++++------ trunk/src/app/srs_app_rtc_source.hpp | 13 ++++++++--- 3 files changed, 56 insertions(+), 13 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index cdd528b0a..57a428e7d 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -432,11 +432,13 @@ srs_error_t SrsRtcPlayStream::initialize(SrsRequest* req, std::map::iterator it = sub_relations.begin(); while (it != sub_relations.end()) { if (it->second->type_ == "audio") { - audio_tracks_.insert(make_pair(it->first, new SrsRtcAudioSendTrack(session_, it->second))); + SrsRtcAudioSendTrack* track = new SrsRtcAudioSendTrack(session_, it->second); + audio_tracks_.insert(make_pair(it->first, track)); } if (it->second->type_ == "video") { - video_tracks_.insert(make_pair(it->first, new SrsRtcVideoSendTrack(session_, it->second))); + SrsRtcVideoSendTrack* track = new SrsRtcVideoSendTrack(session_, it->second); + video_tracks_.insert(make_pair(it->first, track)); } ++it; } @@ -446,6 +448,18 @@ srs_error_t SrsRtcPlayStream::initialize(SrsRequest* req, std::mapget_rtc_nack_enabled(req->vhost); srs_trace("RTC player nack=%d", nack_enabled_); + // Apply configs for all tracks. + for (map::iterator it = audio_tracks_.begin(); it != audio_tracks_.end(); ++it) { + SrsRtcAudioSendTrack* track = it->second; + track->set_nack_enabled(nack_enabled_); + } + + for (map::iterator it = video_tracks_.begin(); it != video_tracks_.end(); ++it) { + SrsRtcVideoSendTrack* track = it->second; + track->set_nack_enabled(nack_enabled_); + } + + // Update stat for session. session_->stat_->nn_subscribers++; return err; @@ -910,6 +924,16 @@ srs_error_t SrsRtcPublishStream::initialize(SrsRequest* r, SrsRtcStreamDescripti srs_trace("RTC publisher nack=%d, pt-drop=%u, twcc=%u/%d", nack_enabled_, pt_to_drop_, twcc_enabled_, twcc_id); + for (vector::iterator it = audio_tracks_.begin(); it != audio_tracks_.end(); ++it) { + SrsRtcAudioRecvTrack* track = *it; + track->set_nack_enabled(nack_enabled_); + } + for (vector::iterator it = video_tracks_.begin(); it != video_tracks_.end(); ++it) { + SrsRtcVideoRecvTrack* track = *it; + track->set_nack_enabled(nack_enabled_); + } + + // Update stat for session. session_->stat_->nn_publishers++; // Setup the publish stream in source to enable PLI as such. @@ -1164,12 +1188,12 @@ srs_error_t SrsRtcPublishStream::do_on_rtp_plaintext(SrsRtpPacket2* pkt, SrsBuff SrsRtcVideoRecvTrack* video_track = get_video_track(ssrc); if (audio_track) { pkt->frame_type = SrsFrameTypeAudio; - if ((err = audio_track->on_rtp(source, pkt, nack_enabled_)) != srs_success) { + if ((err = audio_track->on_rtp(source, pkt)) != srs_success) { return srs_error_wrap(err, "on audio"); } } else if (video_track) { pkt->frame_type = SrsFrameTypeVideo; - if ((err = video_track->on_rtp(source, pkt, nack_enabled_)) != srs_success) { + if ((err = video_track->on_rtp(source, pkt)) != srs_success) { return srs_error_wrap(err, "on video"); } } else { diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index c2f96f918..84af630e2 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -1729,6 +1729,7 @@ SrsRtcRecvTrack::SrsRtcRecvTrack(SrsRtcConnection* session, SrsRtcTrackDescripti session_ = session; track_desc_ = track_desc->copy(); statistic_ = new SrsRtcTrackStatistic(); + nack_enabled_ = false; if (is_audio) { rtp_queue_ = new SrsRtpRingBuffer(100); @@ -1749,6 +1750,11 @@ SrsRtcRecvTrack::~SrsRtcRecvTrack() srs_freep(statistic_); } +void SrsRtcRecvTrack::set_nack_enabled(bool v) +{ + nack_enabled_ = v; +} + bool SrsRtcRecvTrack::has_ssrc(uint32_t ssrc) { return track_desc_->has_ssrc(ssrc); @@ -1872,7 +1878,7 @@ void SrsRtcAudioRecvTrack::on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffe *ppt = SrsRtpPacketPayloadTypeRaw; } -srs_error_t SrsRtcAudioRecvTrack::on_rtp(SrsRtcStream* source, SrsRtpPacket2* pkt, bool nack_enabled) +srs_error_t SrsRtcAudioRecvTrack::on_rtp(SrsRtcStream* source, SrsRtpPacket2* pkt) { srs_error_t err = srs_success; @@ -1888,7 +1894,7 @@ srs_error_t SrsRtcAudioRecvTrack::on_rtp(SrsRtcStream* source, SrsRtpPacket2* pk } // For NACK to handle packet. - if (nack_enabled && (err = on_nack(pkt)) != srs_success) { + if (nack_enabled_ && (err = on_nack(pkt)) != srs_success) { return srs_error_wrap(err, "on nack"); } @@ -1938,7 +1944,7 @@ void SrsRtcVideoRecvTrack::on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffe } } -srs_error_t SrsRtcVideoRecvTrack::on_rtp(SrsRtcStream* source, SrsRtpPacket2* pkt, bool nack_enabled) +srs_error_t SrsRtcVideoRecvTrack::on_rtp(SrsRtcStream* source, SrsRtpPacket2* pkt) { srs_error_t err = srs_success; @@ -1956,7 +1962,7 @@ srs_error_t SrsRtcVideoRecvTrack::on_rtp(SrsRtcStream* source, SrsRtpPacket2* pk } // For NACK to handle packet. - if (nack_enabled && (err = on_nack(pkt)) != srs_success) { + if ((err = on_nack(pkt)) != srs_success) { return srs_error_wrap(err, "on nack"); } @@ -1990,6 +1996,7 @@ SrsRtcSendTrack::SrsRtcSendTrack(SrsRtcConnection* session, SrsRtcTrackDescripti session_ = session; track_desc_ = track_desc->copy(); statistic_ = new SrsRtcTrackStatistic(); + nack_enabled_ = false; if (is_audio) { rtp_queue_ = new SrsRtpRingBuffer(100); @@ -2008,6 +2015,11 @@ SrsRtcSendTrack::~SrsRtcSendTrack() srs_freep(nack_epp); } +void SrsRtcSendTrack::set_nack_enabled(bool v) +{ + nack_enabled_ = v; +} + bool SrsRtcSendTrack::has_ssrc(uint32_t ssrc) { return track_desc_->has_ssrc(ssrc); @@ -2119,7 +2131,7 @@ srs_error_t SrsRtcAudioSendTrack::on_rtp(SrsRtpPacket2* pkt) } // Put rtp packet to NACK/ARQ queue - if (true) { + if (nack_enabled_) { SrsRtpPacket2* nack = pkt->copy(); rtp_queue_->set(nack->header.get_sequence(), nack); } @@ -2179,7 +2191,7 @@ srs_error_t SrsRtcVideoSendTrack::on_rtp(SrsRtpPacket2* pkt) } // Put rtp packet to NACK/ARQ queue - if (true) { + if (nack_enabled_) { SrsRtpPacket2* nack = pkt->copy(); rtp_queue_->set(nack->header.get_sequence(), nack); } diff --git a/trunk/src/app/srs_app_rtc_source.hpp b/trunk/src/app/srs_app_rtc_source.hpp index a1fe0b4f7..a267adf57 100644 --- a/trunk/src/app/srs_app_rtc_source.hpp +++ b/trunk/src/app/srs_app_rtc_source.hpp @@ -510,6 +510,9 @@ public: class SrsRtcRecvTrack { protected: + // Whether enabled nack. + bool nack_enabled_; + SrsRtcTrackDescription* track_desc_; SrsRtcTrackStatistic* statistic_; @@ -524,6 +527,7 @@ public: SrsRtcRecvTrack(SrsRtcConnection* session, SrsRtcTrackDescription* stream_descs, bool is_audio); virtual ~SrsRtcRecvTrack(); public: + void set_nack_enabled(bool v); bool has_ssrc(uint32_t ssrc); uint32_t get_ssrc(); void update_rtt(int rtt); @@ -536,7 +540,7 @@ public: protected: srs_error_t on_nack(SrsRtpPacket2* pkt); public: - virtual srs_error_t on_rtp(SrsRtcStream* source, SrsRtpPacket2* pkt, bool nack_enabled) = 0; + virtual srs_error_t on_rtp(SrsRtcStream* source, SrsRtpPacket2* pkt) = 0; virtual srs_error_t check_send_nacks() = 0; protected: virtual srs_error_t do_check_send_nacks(uint32_t& timeout_nacks); @@ -550,7 +554,7 @@ public: public: virtual void on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload, SrsRtpPacketPayloadType* ppt); public: - virtual srs_error_t on_rtp(SrsRtcStream* source, SrsRtpPacket2* pkt, bool nack_enabled); + virtual srs_error_t on_rtp(SrsRtcStream* source, SrsRtpPacket2* pkt); virtual srs_error_t check_send_nacks(); }; @@ -562,7 +566,7 @@ public: public: virtual void on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload, SrsRtpPacketPayloadType* ppt); public: - virtual srs_error_t on_rtp(SrsRtcStream* source, SrsRtpPacket2* pkt, bool nack_enabled); + virtual srs_error_t on_rtp(SrsRtcStream* source, SrsRtpPacket2* pkt); virtual srs_error_t check_send_nacks(); }; @@ -577,6 +581,8 @@ protected: SrsRtcConnection* session_; // NACK ARQ ring buffer. SrsRtpRingBuffer* rtp_queue_; + // Whether enabled nack. + bool nack_enabled_; private: // The pithy print for special stage. SrsErrorPithyPrint* nack_epp; @@ -584,6 +590,7 @@ public: SrsRtcSendTrack(SrsRtcConnection* session, SrsRtcTrackDescription* track_desc, bool is_audio); virtual ~SrsRtcSendTrack(); public: + void set_nack_enabled(bool v); bool has_ssrc(uint32_t ssrc); SrsRtpPacket2* fetch_rtp_packet(uint16_t seq); bool set_track_status(bool active); From 74f63d6b1480432c034ff94fc2fd8b9f870266c1 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 28 Feb 2021 07:09:27 +0800 Subject: [PATCH 058/102] RTC: Ignore NACK when disable for player. --- trunk/src/app/srs_app_rtc_source.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index 84af630e2..fb62a374c 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -1962,7 +1962,7 @@ srs_error_t SrsRtcVideoRecvTrack::on_rtp(SrsRtcStream* source, SrsRtpPacket2* pk } // For NACK to handle packet. - if ((err = on_nack(pkt)) != srs_success) { + if (nack_enabled_ && (err = on_nack(pkt)) != srs_success) { return srs_error_wrap(err, "on nack"); } From 51a5e283fc08f231bb95e8a645865e0ee3ff5c82 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 28 Feb 2021 07:27:14 +0800 Subject: [PATCH 059/102] Perf: Avoid RTP packet copy for publisher NACK. --- trunk/src/app/srs_app_rtc_conn.cpp | 27 +++++++++++++++++---------- trunk/src/app/srs_app_rtc_conn.hpp | 2 +- trunk/src/app/srs_app_rtc_source.cpp | 23 +++++------------------ trunk/src/app/srs_app_rtc_source.hpp | 10 ++++------ 4 files changed, 27 insertions(+), 35 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 57a428e7d..9ede8164c 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -924,15 +924,6 @@ srs_error_t SrsRtcPublishStream::initialize(SrsRequest* r, SrsRtcStreamDescripti srs_trace("RTC publisher nack=%d, pt-drop=%u, twcc=%u/%d", nack_enabled_, pt_to_drop_, twcc_enabled_, twcc_id); - for (vector::iterator it = audio_tracks_.begin(); it != audio_tracks_.end(); ++it) { - SrsRtcAudioRecvTrack* track = *it; - track->set_nack_enabled(nack_enabled_); - } - for (vector::iterator it = video_tracks_.begin(); it != video_tracks_.end(); ++it) { - SrsRtcVideoRecvTrack* track = *it; - track->set_nack_enabled(nack_enabled_); - } - // Update stat for session. session_->stat_->nn_publishers++; @@ -1162,6 +1153,8 @@ srs_error_t SrsRtcPublishStream::on_rtp_plaintext(char* plaintext, int nb_plaint // Handle the packet. SrsBuffer buf(p, nb_plaintext); + + // @remark Note that the pkt might be set to NULL. err = do_on_rtp_plaintext(pkt, &buf); // Release the packet to cache. @@ -1170,7 +1163,7 @@ srs_error_t SrsRtcPublishStream::on_rtp_plaintext(char* plaintext, int nb_plaint return err; } -srs_error_t SrsRtcPublishStream::do_on_rtp_plaintext(SrsRtpPacket2* pkt, SrsBuffer* buf) +srs_error_t SrsRtcPublishStream::do_on_rtp_plaintext(SrsRtpPacket2*& pkt, SrsBuffer* buf) { srs_error_t err = srs_success; @@ -1206,6 +1199,20 @@ srs_error_t SrsRtcPublishStream::do_on_rtp_plaintext(SrsRtpPacket2* pkt, SrsBuff } } + // For NACK to handle packet. + // @remark Note that the pkt might be set to NULL. + if (nack_enabled_) { + if (audio_track) { + if ((err = audio_track->on_nack(&pkt)) != srs_success) { + return srs_error_wrap(err, "on nack"); + } + } else if (video_track) { + if ((err = video_track->on_nack(&pkt)) != srs_success) { + return srs_error_wrap(err, "on nack"); + } + } + } + return err; } diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index f3aa8e2e4..eacc8e6e9 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -325,7 +325,7 @@ private: // @remark We copy the plaintext, user should free it. srs_error_t on_rtp_plaintext(char* plaintext, int nb_plaintext); private: - srs_error_t do_on_rtp_plaintext(SrsRtpPacket2* pkt, SrsBuffer* buf); + srs_error_t do_on_rtp_plaintext(SrsRtpPacket2*& pkt, SrsBuffer* buf); public: srs_error_t check_send_nacks(); public: diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index fb62a374c..c0c87785c 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -1729,7 +1729,6 @@ SrsRtcRecvTrack::SrsRtcRecvTrack(SrsRtcConnection* session, SrsRtcTrackDescripti session_ = session; track_desc_ = track_desc->copy(); statistic_ = new SrsRtcTrackStatistic(); - nack_enabled_ = false; if (is_audio) { rtp_queue_ = new SrsRtpRingBuffer(100); @@ -1750,11 +1749,6 @@ SrsRtcRecvTrack::~SrsRtcRecvTrack() srs_freep(statistic_); } -void SrsRtcRecvTrack::set_nack_enabled(bool v) -{ - nack_enabled_ = v; -} - bool SrsRtcRecvTrack::has_ssrc(uint32_t ssrc) { return track_desc_->has_ssrc(ssrc); @@ -1818,10 +1812,11 @@ std::string SrsRtcRecvTrack::get_track_id() return track_desc_->id_; } -srs_error_t SrsRtcRecvTrack::on_nack(SrsRtpPacket2* pkt) +srs_error_t SrsRtcRecvTrack::on_nack(SrsRtpPacket2** ppkt) { srs_error_t err = srs_success; + SrsRtpPacket2* pkt = *ppkt; uint16_t seq = pkt->header.get_sequence(); SrsRtpNackInfo* nack_info = nack_receiver_->find(seq); if (nack_info) { @@ -1842,7 +1837,9 @@ srs_error_t SrsRtcRecvTrack::on_nack(SrsRtpPacket2* pkt) } // insert into video_queue and audio_queue - rtp_queue_->set(seq, pkt->copy()); + // We directly use the pkt, never copy it, so we should set the pkt to NULL. + rtp_queue_->set(seq, pkt); + *ppkt = NULL; return err; } @@ -1893,11 +1890,6 @@ srs_error_t SrsRtcAudioRecvTrack::on_rtp(SrsRtcStream* source, SrsRtpPacket2* pk return srs_error_wrap(err, "source on rtp"); } - // For NACK to handle packet. - if (nack_enabled_ && (err = on_nack(pkt)) != srs_success) { - return srs_error_wrap(err, "on nack"); - } - return err; } @@ -1961,11 +1953,6 @@ srs_error_t SrsRtcVideoRecvTrack::on_rtp(SrsRtcStream* source, SrsRtpPacket2* pk return srs_error_wrap(err, "source on rtp"); } - // For NACK to handle packet. - if (nack_enabled_ && (err = on_nack(pkt)) != srs_success) { - return srs_error_wrap(err, "on nack"); - } - return err; } diff --git a/trunk/src/app/srs_app_rtc_source.hpp b/trunk/src/app/srs_app_rtc_source.hpp index a267adf57..aed39ec31 100644 --- a/trunk/src/app/srs_app_rtc_source.hpp +++ b/trunk/src/app/srs_app_rtc_source.hpp @@ -510,9 +510,6 @@ public: class SrsRtcRecvTrack { protected: - // Whether enabled nack. - bool nack_enabled_; - SrsRtcTrackDescription* track_desc_; SrsRtcTrackStatistic* statistic_; @@ -527,7 +524,6 @@ public: SrsRtcRecvTrack(SrsRtcConnection* session, SrsRtcTrackDescription* stream_descs, bool is_audio); virtual ~SrsRtcRecvTrack(); public: - void set_nack_enabled(bool v); bool has_ssrc(uint32_t ssrc); uint32_t get_ssrc(); void update_rtt(int rtt); @@ -537,8 +533,10 @@ public: bool set_track_status(bool active); bool get_track_status(); std::string get_track_id(); -protected: - srs_error_t on_nack(SrsRtpPacket2* pkt); +public: + // Note that we can set the pkt to NULL to avoid copy, for example, if the NACK cache the pkt and + // set to NULL, nack nerver copy it but set the pkt to NULL. + srs_error_t on_nack(SrsRtpPacket2** ppkt); public: virtual srs_error_t on_rtp(SrsRtcStream* source, SrsRtpPacket2* pkt) = 0; virtual srs_error_t check_send_nacks() = 0; From 11454b3ced7189feb466b8f14e259326160322cd Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 28 Feb 2021 08:07:06 +0800 Subject: [PATCH 060/102] Perf: Avoid RTP packet copy for player NACK. --- trunk/src/app/srs_app_rtc_conn.cpp | 39 ++++++++++++++++------------ trunk/src/app/srs_app_rtc_conn.hpp | 2 +- trunk/src/app/srs_app_rtc_source.cpp | 33 +++++++++++------------ trunk/src/app/srs_app_rtc_source.hpp | 7 ++--- 4 files changed, 42 insertions(+), 39 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 9ede8164c..68a581460 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -448,17 +448,6 @@ srs_error_t SrsRtcPlayStream::initialize(SrsRequest* req, std::mapget_rtc_nack_enabled(req->vhost); srs_trace("RTC player nack=%d", nack_enabled_); - // Apply configs for all tracks. - for (map::iterator it = audio_tracks_.begin(); it != audio_tracks_.end(); ++it) { - SrsRtcAudioSendTrack* track = it->second; - track->set_nack_enabled(nack_enabled_); - } - - for (map::iterator it = video_tracks_.begin(); it != video_tracks_.end(); ++it) { - SrsRtcVideoSendTrack* track = it->second; - track->set_nack_enabled(nack_enabled_); - } - // Update stat for session. session_->stat_->nn_subscribers++; @@ -582,6 +571,7 @@ srs_error_t SrsRtcPlayStream::cycle() } // Send-out the RTP packet and do cleanup + // @remark Note that the pkt might be set to NULL. if ((err = send_packet(pkt)) != srs_success) { uint32_t nn = 0; if (epp->can_print(err, &nn)) { @@ -590,11 +580,13 @@ srs_error_t SrsRtcPlayStream::cycle() srs_freep(err); } + // Release the packet to cache. + // @remark Note that the pkt might be set to NULL. _srs_rtp_cache->recycle(pkt); } } -srs_error_t SrsRtcPlayStream::send_packet(SrsRtpPacket2* pkt) +srs_error_t SrsRtcPlayStream::send_packet(SrsRtpPacket2*& pkt) { srs_error_t err = srs_success; @@ -605,9 +597,11 @@ srs_error_t SrsRtcPlayStream::send_packet(SrsRtpPacket2* pkt) } // For audio, we transcoded AAC to opus in extra payloads. + SrsRtcAudioSendTrack* audio_track = NULL; + SrsRtcVideoSendTrack* video_track = NULL; if (pkt->is_audio()) { // TODO: FIXME: Any simple solution? - SrsRtcAudioSendTrack* audio_track = audio_tracks_[pkt->header.get_ssrc()]; + audio_track = audio_tracks_[pkt->header.get_ssrc()]; if ((err = audio_track->on_rtp(pkt)) != srs_success) { return srs_error_wrap(err, "audio track, SSRC=%u, SEQ=%u", pkt->header.get_ssrc(), pkt->header.get_sequence()); @@ -616,16 +610,26 @@ srs_error_t SrsRtcPlayStream::send_packet(SrsRtpPacket2* pkt) // TODO: FIXME: Padding audio to the max payload in RTP packets. } else { // TODO: FIXME: Any simple solution? - SrsRtcVideoSendTrack* video_track = video_tracks_[pkt->header.get_ssrc()]; + video_track = video_tracks_[pkt->header.get_ssrc()]; if ((err = video_track->on_rtp(pkt)) != srs_success) { return srs_error_wrap(err, "video track, SSRC=%u, SEQ=%u", pkt->header.get_ssrc(), pkt->header.get_sequence()); } } - // Detail log, should disable it in release version. - srs_info("RTC: Update PT=%u, SSRC=%#x, Time=%u, %u bytes", pkt->header.get_payload_type(), pkt->header.get_ssrc(), - pkt->header.get_timestamp(), pkt->nb_bytes()); + // For NACK to handle packet. + // @remark Note that the pkt might be set to NULL. + if (nack_enabled_) { + if (audio_track) { + if ((err = audio_track->on_nack(&pkt)) != srs_success) { + return srs_error_wrap(err, "on nack"); + } + } else if (video_track) { + if ((err = video_track->on_nack(&pkt)) != srs_success) { + return srs_error_wrap(err, "on nack"); + } + } + } return err; } @@ -1158,6 +1162,7 @@ srs_error_t SrsRtcPublishStream::on_rtp_plaintext(char* plaintext, int nb_plaint err = do_on_rtp_plaintext(pkt, &buf); // Release the packet to cache. + // @remark Note that the pkt might be set to NULL. _srs_rtp_cache->recycle(pkt); return err; diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index eacc8e6e9..4d662320b 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -252,7 +252,7 @@ public: public: virtual srs_error_t cycle(); private: - srs_error_t send_packet(SrsRtpPacket2* pkt); + srs_error_t send_packet(SrsRtpPacket2*& pkt); public: // Directly set the status of track, generally for init to set the default value. void set_all_tracks_status(bool status); diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index c0c87785c..429b949c7 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -1983,7 +1983,6 @@ SrsRtcSendTrack::SrsRtcSendTrack(SrsRtcConnection* session, SrsRtcTrackDescripti session_ = session; track_desc_ = track_desc->copy(); statistic_ = new SrsRtcTrackStatistic(); - nack_enabled_ = false; if (is_audio) { rtp_queue_ = new SrsRtpRingBuffer(100); @@ -2002,11 +2001,6 @@ SrsRtcSendTrack::~SrsRtcSendTrack() srs_freep(nack_epp); } -void SrsRtcSendTrack::set_nack_enabled(bool v) -{ - nack_enabled_ = v; -} - bool SrsRtcSendTrack::has_ssrc(uint32_t ssrc) { return track_desc_->has_ssrc(ssrc); @@ -2055,6 +2049,21 @@ std::string SrsRtcSendTrack::get_track_id() return track_desc_->id_; } +srs_error_t SrsRtcSendTrack::on_nack(SrsRtpPacket2** ppkt) +{ + srs_error_t err = srs_success; + + SrsRtpPacket2* pkt = *ppkt; + uint16_t seq = pkt->header.get_sequence(); + + // insert into video_queue and audio_queue + // We directly use the pkt, never copy it, so we should set the pkt to NULL. + rtp_queue_->set(seq, pkt); + *ppkt = NULL; + + return err; +} + srs_error_t SrsRtcSendTrack::on_recv_nack(const vector& lost_seqs) { srs_error_t err = srs_success; @@ -2117,12 +2126,6 @@ srs_error_t SrsRtcAudioSendTrack::on_rtp(SrsRtpPacket2* pkt) // TODO: FIXME: Should update PT for RTX. } - // Put rtp packet to NACK/ARQ queue - if (nack_enabled_) { - SrsRtpPacket2* nack = pkt->copy(); - rtp_queue_->set(nack->header.get_sequence(), nack); - } - // Update stats. session_->stat_->nn_out_audios++; @@ -2177,12 +2180,6 @@ srs_error_t SrsRtcVideoSendTrack::on_rtp(SrsRtpPacket2* pkt) // TODO: FIXME: Should update PT for RTX. } - // Put rtp packet to NACK/ARQ queue - if (nack_enabled_) { - SrsRtpPacket2* nack = pkt->copy(); - rtp_queue_->set(nack->header.get_sequence(), nack); - } - // Update stats. session_->stat_->nn_out_videos++; diff --git a/trunk/src/app/srs_app_rtc_source.hpp b/trunk/src/app/srs_app_rtc_source.hpp index aed39ec31..db187faf6 100644 --- a/trunk/src/app/srs_app_rtc_source.hpp +++ b/trunk/src/app/srs_app_rtc_source.hpp @@ -579,8 +579,6 @@ protected: SrsRtcConnection* session_; // NACK ARQ ring buffer. SrsRtpRingBuffer* rtp_queue_; - // Whether enabled nack. - bool nack_enabled_; private: // The pithy print for special stage. SrsErrorPithyPrint* nack_epp; @@ -588,12 +586,15 @@ public: SrsRtcSendTrack(SrsRtcConnection* session, SrsRtcTrackDescription* track_desc, bool is_audio); virtual ~SrsRtcSendTrack(); public: - void set_nack_enabled(bool v); bool has_ssrc(uint32_t ssrc); SrsRtpPacket2* fetch_rtp_packet(uint16_t seq); bool set_track_status(bool active); bool get_track_status(); std::string get_track_id(); +public: + // Note that we can set the pkt to NULL to avoid copy, for example, if the NACK cache the pkt and + // set to NULL, nack nerver copy it but set the pkt to NULL. + srs_error_t on_nack(SrsRtpPacket2** ppkt); public: virtual srs_error_t on_rtp(SrsRtpPacket2* pkt) = 0; virtual srs_error_t on_rtcp(SrsRtpPacket2* pkt) = 0; From eb9a2634338c482b3f4fd18e8b523f53690a960d Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 28 Feb 2021 08:23:35 +0800 Subject: [PATCH 061/102] Cache RTP packet size, revert 9ee0ed919a --- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 18 ++++++++++++++++-- trunk/src/kernel/srs_kernel_rtc_rtp.hpp | 3 +++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index 36822a43f..b633653f0 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -854,6 +854,7 @@ SrsRtpPacket2::SrsRtpPacket2() nalu_type = SrsAvcNaluTypeReserved; frame_type = SrsFrameTypeReserved; + cached_payload_size = 0; decode_handler = NULL; ++_srs_pps_objs_rtps->sugar; @@ -869,6 +870,7 @@ void SrsRtpPacket2::reset() { nalu_type = SrsAvcNaluTypeReserved; frame_type = SrsFrameTypeReserved; + cached_payload_size = 0; decode_handler = NULL; // It's important to reset the header. @@ -931,6 +933,8 @@ cleanup: bool SrsRtpPacket2::recycle() { + // Clear the cache size, it may change when reuse it. + cached_payload_size = 0; // Reset the handler, for decode only. decode_handler = NULL; @@ -1012,6 +1016,7 @@ SrsRtpPacket2* SrsRtpPacket2::copy() cp->shared_msg = shared_msg->copy2(); cp->frame_type = frame_type; + cp->cached_payload_size = cached_payload_size; // For performance issue, do not copy the unused field. //cp->decode_handler = decode_handler; @@ -1021,11 +1026,17 @@ SrsRtpPacket2* SrsRtpPacket2::copy() void SrsRtpPacket2::set_padding(int size) { header.set_padding(size); + if (cached_payload_size) { + cached_payload_size += size - header.get_padding(); + } } void SrsRtpPacket2::add_padding(int size) { header.set_padding(header.get_padding() + size); + if (cached_payload_size) { + cached_payload_size += size; + } } void SrsRtpPacket2::set_decode_handler(ISrsRtpPacketDecodeHandler* h) @@ -1045,8 +1056,11 @@ void SrsRtpPacket2::set_extension_types(SrsRtpExtensionTypes* v) uint64_t SrsRtpPacket2::nb_bytes() { - int nn_payload = (payload_? payload_->nb_bytes():0); - return header.nb_bytes() + nn_payload + header.get_padding(); + if (!cached_payload_size) { + int nn_payload = (payload_? payload_->nb_bytes():0); + cached_payload_size = header.nb_bytes() + nn_payload + header.get_padding(); + } + return cached_payload_size; } srs_error_t SrsRtpPacket2::encode(SrsBuffer* buf) diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index b7947fa8c..7227fb004 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -315,7 +315,10 @@ public: SrsAvcNaluType nalu_type; // The frame type, for RTMP bridger or SFU source. SrsFrameType frame_type; +// Fast cache for performance. private: + // The cached payload size for packet. + int cached_payload_size; // The helper handler for decoder, use RAW payload if NULL. ISrsRtpPacketDecodeHandler* decode_handler; public: From 7c517988a6e36326fee115da5e3e7a10ef80042c Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 28 Feb 2021 09:51:28 +0800 Subject: [PATCH 062/102] Perf: Refine header extensions marshal --- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 30 ++++++++++--------------- trunk/src/kernel/srs_kernel_rtc_rtp.hpp | 11 ++++----- 2 files changed, 16 insertions(+), 25 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index b633653f0..64ec08bc8 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -225,11 +225,6 @@ void SrsRtpExtensionTwcc::assign(const SrsRtpExtensionTwcc& h) sn_ = h.sn_; } -bool SrsRtpExtensionTwcc::has_twcc_ext() -{ - return has_twcc_; -} - srs_error_t SrsRtpExtensionTwcc::decode(SrsBuffer* buf) { srs_error_t err = srs_success; @@ -481,7 +476,7 @@ srs_error_t SrsRtpExtensions::decode_0xbede(SrsBuffer* buf) uint64_t SrsRtpExtensions::nb_bytes() { - int size = 4 + (twcc_.has_twcc_ext() ? twcc_.nb_bytes() : 0); + int size = 4 + (twcc_.exists() ? twcc_.nb_bytes() : 0); size += (audio_level_.exists() ? audio_level_.nb_bytes() : 0); // add padding size += (size % 4 == 0) ? 0 : (4 - size % 4); @@ -497,7 +492,7 @@ srs_error_t SrsRtpExtensions::encode(SrsBuffer* buf) // Write length. int len = 0; - if (twcc_.has_twcc_ext()) { + if (twcc_.exists()) { len += twcc_.nb_bytes(); } @@ -508,10 +503,14 @@ srs_error_t SrsRtpExtensions::encode(SrsBuffer* buf) int padding_count = (len % 4 == 0) ? 0 : (4 - len % 4); len += padding_count; + if (!buf->require(len)) { + return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", len); + } + buf->write_2bytes(len / 4); // Write extensions. - if (twcc_.has_twcc_ext()) { + if (twcc_.exists()) { if ((err = twcc_.encode(buf)) != srs_success) { return srs_error_wrap(err, "encode twcc extension"); } @@ -524,19 +523,14 @@ srs_error_t SrsRtpExtensions::encode(SrsBuffer* buf) } // add padding - while(padding_count > 0) { - buf->write_1bytes(0); - padding_count--; + if (padding_count) { + memset(buf->head(), 0, padding_count); + buf->skip(padding_count); } return err; } -bool SrsRtpExtensions::exists() -{ - return has_ext_; -} - void SrsRtpExtensions::set_types_(SrsRtpExtensionTypes* types) { types_ = types; @@ -544,7 +538,7 @@ void SrsRtpExtensions::set_types_(SrsRtpExtensionTypes* types) srs_error_t SrsRtpExtensions::get_twcc_sequence_number(uint16_t& twcc_sn) { - if (twcc_.has_twcc_ext()) { + if (twcc_.exists()) { twcc_sn = twcc_.get_sn(); return srs_success; } @@ -1080,7 +1074,7 @@ srs_error_t SrsRtpPacket2::encode(SrsBuffer* buf) if (!buf->require(padding)) { return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", padding); } - memset(buf->data() + buf->pos(), padding, padding); + memset(buf->head(), padding, padding); buf->skip(padding); } diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index 7227fb004..4f3e28524 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -142,7 +142,7 @@ public: void reset(); void assign(const SrsRtpExtensionTwcc& h); public: - bool has_twcc_ext(); + inline bool exists() { return has_twcc_; } // SrsRtpExtensionTwcc::exists uint8_t get_id(); void set_id(uint8_t id); uint16_t get_sn(); @@ -168,7 +168,7 @@ public: void reset(); void assign(const SrsRtpExtensionOneByte& h); public: - bool exists() { return has_ext_; } + inline bool exists() { return has_ext_; } // SrsRtpExtensionOneByte::exists int get_id() { return id_; } uint8_t get_value() { return value_; } void set_id(int id); @@ -200,7 +200,7 @@ public: void reset(); void assign(const SrsRtpExtensions& h); public: - bool exists(); + inline bool exists() { return has_ext_; } // SrsRtpExtensions::exists void set_types_(SrsRtpExtensionTypes* types); srs_error_t get_twcc_sequence_number(uint16_t& twcc_sn); srs_error_t set_twcc_sequence_number(uint8_t id, uint16_t sn); @@ -254,10 +254,7 @@ public: void set_timestamp(uint32_t v); uint32_t get_timestamp() const; void set_ssrc(uint32_t v); - // SrsRtpHeader::get_ssrc - inline uint32_t get_ssrc() const { - return ssrc; - } + inline uint32_t get_ssrc() const { return ssrc; } // SrsRtpHeader::get_ssrc void set_padding(uint8_t v); uint8_t get_padding() const; void set_extensions(SrsRtpExtensionTypes* extmap); From 5d4baf4eca21bc6ab8d26953d17a29ae5749e6e0 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 28 Feb 2021 10:04:30 +0800 Subject: [PATCH 063/102] RTC: Refine code, remove the assign --- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 48 +------------------------ trunk/src/kernel/srs_kernel_rtc_rtp.hpp | 4 --- 2 files changed, 1 insertion(+), 51 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index 64ec08bc8..2098d44eb 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -218,13 +218,6 @@ void SrsRtpExtensionTwcc::reset() sn_ = 0; } -void SrsRtpExtensionTwcc::assign(const SrsRtpExtensionTwcc& h) -{ - has_twcc_ = h.has_twcc_; - id_ = h.id_; - sn_ = h.sn_; -} - srs_error_t SrsRtpExtensionTwcc::decode(SrsBuffer* buf) { srs_error_t err = srs_success; @@ -313,13 +306,6 @@ void SrsRtpExtensionOneByte::reset() value_ = 0; } -void SrsRtpExtensionOneByte::assign(const SrsRtpExtensionOneByte& h) -{ - has_ext_ = h.has_ext_; - id_ = h.id_; - value_ = h.value_; -} - void SrsRtpExtensionOneByte::set_id(int id) { id_ = id; @@ -385,17 +371,6 @@ void SrsRtpExtensions::reset() has_ext_ = false; } -void SrsRtpExtensions::assign(const SrsRtpExtensions& h) -{ - has_ext_ = h.has_ext_; - types_ = h.types_; - - if (has_ext_) { - twcc_.assign(h.twcc_); - audio_level_.assign(h.audio_level_); - } -} - srs_error_t SrsRtpExtensions::decode(SrsBuffer* buf) { srs_error_t err = srs_success; @@ -602,27 +577,6 @@ void SrsRtpHeader::reset() //memset(csrc, 0, sizeof(csrc)); } -void SrsRtpHeader::assign(const SrsRtpHeader& h) -{ - // Reset the fields in protocol. - cc = h.cc; - marker = h.marker; - payload_type = h.payload_type; - sequence = h.sequence; - timestamp = h.timestamp; - ssrc = h.ssrc; - - // Reset the parsed fields. - padding_length = h.padding_length; - extensions_.assign(h.extensions_); - - // Reset other fields. - ignore_padding_ = h.ignore_padding_; - - // The CSRC is not used yet, so we never reset it. - //memcpy(csrc, h.csrc, sizeof(csrc)); -} - srs_error_t SrsRtpHeader::decode(SrsBuffer* buf) { srs_error_t err = srs_success; @@ -1002,7 +956,7 @@ SrsRtpPacket2* SrsRtpPacket2::copy() //srs_assert(!cp->payload_); //srs_assert(!cp->shared_msg); - cp->header.assign(header); + cp->header = header; cp->payload_ = payload_? payload_->copy():NULL; cp->payload_type_ = payload_type_; diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index 4f3e28524..ae403bc65 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -140,7 +140,6 @@ public: public: // Reset the object to reuse it. void reset(); - void assign(const SrsRtpExtensionTwcc& h); public: inline bool exists() { return has_twcc_; } // SrsRtpExtensionTwcc::exists uint8_t get_id(); @@ -166,7 +165,6 @@ public: public: // Reset the object to reuse it. void reset(); - void assign(const SrsRtpExtensionOneByte& h); public: inline bool exists() { return has_ext_; } // SrsRtpExtensionOneByte::exists int get_id() { return id_; } @@ -198,7 +196,6 @@ public: public: // Reset the object to reuse it. void reset(); - void assign(const SrsRtpExtensions& h); public: inline bool exists() { return has_ext_; } // SrsRtpExtensions::exists void set_types_(SrsRtpExtensionTypes* types); @@ -236,7 +233,6 @@ public: public: // Reset the object to reuse it. void reset(); - void assign(const SrsRtpHeader& h); public: virtual srs_error_t decode(SrsBuffer* buf); private: From eed98dd85b95a32828d9d5be1f98e815e37364f0 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 28 Feb 2021 10:06:52 +0800 Subject: [PATCH 064/102] RTC: Refine code, remove the reset for header --- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 58 ++++++------------------- trunk/src/kernel/srs_kernel_rtc_rtp.hpp | 12 ----- 2 files changed, 13 insertions(+), 57 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index 2098d44eb..3d150d03f 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -204,20 +204,15 @@ SrsRtpExtensionType SrsRtpExtensionTypes::get_type(int id) const SrsRtpExtensionTwcc::SrsRtpExtensionTwcc() { - reset(); + has_twcc_ = false; + id_ = 0; + sn_ = 0; } SrsRtpExtensionTwcc::~SrsRtpExtensionTwcc() { } -void SrsRtpExtensionTwcc::reset() -{ - has_twcc_ = false; - id_ = 0; - sn_ = 0; -} - srs_error_t SrsRtpExtensionTwcc::decode(SrsBuffer* buf) { srs_error_t err = srs_success; @@ -292,20 +287,15 @@ void SrsRtpExtensionTwcc::set_sn(uint16_t sn) SrsRtpExtensionOneByte::SrsRtpExtensionOneByte() { - reset(); + has_ext_ = false; + id_ = 0; + value_ = 0; } SrsRtpExtensionOneByte::~SrsRtpExtensionOneByte() { } -void SrsRtpExtensionOneByte::reset() -{ - has_ext_ = false; - id_ = 0; - value_ = 0; -} - void SrsRtpExtensionOneByte::set_id(int id) { id_ = id; @@ -356,21 +346,14 @@ srs_error_t SrsRtpExtensionOneByte::encode(SrsBuffer* buf) SrsRtpExtensions::SrsRtpExtensions() { - reset(); + types_ = NULL; + has_ext_ = false; } SrsRtpExtensions::~SrsRtpExtensions() { } -void SrsRtpExtensions::reset() -{ - types_ = NULL; - twcc_.reset(); - audio_level_.reset(); - has_ext_ = false; -} - srs_error_t SrsRtpExtensions::decode(SrsBuffer* buf) { srs_error_t err = srs_success; @@ -547,34 +530,19 @@ srs_error_t SrsRtpExtensions::set_audio_level(int id, uint8_t level) SrsRtpHeader::SrsRtpHeader() { - reset(); - - memset(csrc, 0, sizeof(csrc)); -} - -SrsRtpHeader::~SrsRtpHeader() -{ -} - -void SrsRtpHeader::reset() -{ - // Reset the fields in protocol. cc = 0; marker = false; payload_type = 0; sequence = 0; timestamp = 0; ssrc = 0; - - // Reset the parsed fields. padding_length = 0; - extensions_.reset(); - - // Reset other fields. ignore_padding_ = false; + memset(csrc, 0, sizeof(csrc)); +} - // The CSRC is not used yet, so we never reset it. - //memset(csrc, 0, sizeof(csrc)); +SrsRtpHeader::~SrsRtpHeader() +{ } srs_error_t SrsRtpHeader::decode(SrsBuffer* buf) @@ -822,7 +790,7 @@ void SrsRtpPacket2::reset() decode_handler = NULL; // It's important to reset the header. - header.reset(); + header = SrsRtpHeader(); // Recyle the payload again, to ensure the packet is new one. recycle_payload(); diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index ae403bc65..967462903 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -137,9 +137,6 @@ class SrsRtpExtensionTwcc// : public ISrsCodec public: SrsRtpExtensionTwcc(); virtual ~SrsRtpExtensionTwcc(); -public: - // Reset the object to reuse it. - void reset(); public: inline bool exists() { return has_twcc_; } // SrsRtpExtensionTwcc::exists uint8_t get_id(); @@ -162,9 +159,6 @@ class SrsRtpExtensionOneByte// : public ISrsCodec public: SrsRtpExtensionOneByte(); virtual ~SrsRtpExtensionOneByte(); -public: - // Reset the object to reuse it. - void reset(); public: inline bool exists() { return has_ext_; } // SrsRtpExtensionOneByte::exists int get_id() { return id_; } @@ -193,9 +187,6 @@ private: public: SrsRtpExtensions(); virtual ~SrsRtpExtensions(); -public: - // Reset the object to reuse it. - void reset(); public: inline bool exists() { return has_ext_; } // SrsRtpExtensions::exists void set_types_(SrsRtpExtensionTypes* types); @@ -230,9 +221,6 @@ private: public: SrsRtpHeader(); virtual ~SrsRtpHeader(); -public: - // Reset the object to reuse it. - void reset(); public: virtual srs_error_t decode(SrsBuffer* buf); private: From 171ae5dd2dc6d717941a234c3fdf3a7b7601639d Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 28 Feb 2021 11:26:50 +0800 Subject: [PATCH 065/102] RTC: Fix shared msg cache bug --- trunk/src/app/srs_app_hybrid.cpp | 3 ++- trunk/src/kernel/srs_kernel_flv.cpp | 33 ++++++++++++------------- trunk/src/kernel/srs_kernel_flv.hpp | 4 +-- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 22 +++++++++-------- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/trunk/src/app/srs_app_hybrid.cpp b/trunk/src/app/srs_app_hybrid.cpp index f0ff56f35..f9365f60a 100644 --- a/trunk/src/app/srs_app_hybrid.cpp +++ b/trunk/src/app/srs_app_hybrid.cpp @@ -466,7 +466,8 @@ srs_error_t SrsHybridServer::notify(int event, srs_utime_t interval, srs_utime_t if (_srs_rtp_cache->size() || _srs_rtp_raw_cache->size() || _srs_rtp_fua_cache->size() || _srs_rtp_msg_cache_buffers->size() || _srs_rtp_msg_cache_objs->size()) { snprintf(buf, sizeof(buf), ", cache=(pkt:%d-%dw,raw:%d-%dw,fua:%d-%dw,msg:%d-%dw,buf:%d-%dw)", _srs_rtp_cache->size(), _srs_rtp_cache->capacity()/10000, _srs_rtp_raw_cache->size(), _srs_rtp_raw_cache->capacity()/10000, - _srs_rtp_fua_cache->size(), _srs_rtp_fua_cache->capacity()/10000, _srs_rtp_msg_cache_buffers->size(), _srs_rtp_msg_cache_buffers->capacity()/10000, _srs_rtp_msg_cache_objs->size(), _srs_rtp_msg_cache_objs->capacity()/10000); + _srs_rtp_fua_cache->size(), _srs_rtp_fua_cache->capacity()/10000, _srs_rtp_msg_cache_objs->size(), _srs_rtp_msg_cache_objs->capacity()/10000, + _srs_rtp_msg_cache_buffers->size(), _srs_rtp_msg_cache_buffers->capacity()/10000); cache_desc = buf; } diff --git a/trunk/src/kernel/srs_kernel_flv.cpp b/trunk/src/kernel/srs_kernel_flv.cpp index 0706cd487..102165ec3 100644 --- a/trunk/src/kernel/srs_kernel_flv.cpp +++ b/trunk/src/kernel/srs_kernel_flv.cpp @@ -229,6 +229,19 @@ SrsSharedPtrMessage::~SrsSharedPtrMessage() } } +bool SrsSharedPtrMessage::recycle() +{ + // When recycle, unwrap if not the last reference. + if (ptr && ptr->shared_count > 0) { + ptr->shared_count--; + ptr = NULL; + payload = NULL; + size = 0; + } + + return true; +} + srs_error_t SrsSharedPtrMessage::create(SrsCommonMessage* msg) { srs_error_t err = srs_success; @@ -287,21 +300,6 @@ void SrsSharedPtrMessage::wrap(char* payload, int size) this->size = ptr->size; } -void SrsSharedPtrMessage::unwrap() -{ - if (ptr) { - if (ptr->shared_count > 0) { - ptr->shared_count--; - ptr = NULL; - } else { - srs_freep(ptr); - } - } - - payload = NULL; - size = 0; -} - int SrsSharedPtrMessage::count() { return ptr? ptr->shared_count : 0; @@ -365,8 +363,6 @@ SrsSharedPtrMessage* SrsSharedPtrMessage::copy() copy->timestamp = timestamp; copy->stream_id = stream_id; - copy->payload = ptr->payload; - copy->size = ptr->size; return copy; } @@ -382,6 +378,9 @@ SrsSharedPtrMessage* SrsSharedPtrMessage::copy2() copy->ptr = ptr; ptr->shared_count++; + copy->payload = ptr->payload; + copy->size = ptr->size; + return copy; } diff --git a/trunk/src/kernel/srs_kernel_flv.hpp b/trunk/src/kernel/srs_kernel_flv.hpp index 0cc6102ac..5250c12b2 100644 --- a/trunk/src/kernel/srs_kernel_flv.hpp +++ b/trunk/src/kernel/srs_kernel_flv.hpp @@ -313,7 +313,7 @@ public: virtual ~SrsSharedPtrMessage(); public: // For object cache to reset and reuse it. - bool recycle() { return true; } + bool recycle(); // Create shared ptr message, // copy header, manage the payload of msg, // set the payload to NULL to prevent double free. @@ -328,8 +328,6 @@ public: // Create shared ptr message from RAW payload. // @remark Note that the header is set to zero. virtual void wrap(char* payload, int size); - // Decrease the reference, if the last one, free it. - void unwrap(); // Get current reference count. // when this object created, count set to 0. // if copy() this object, count increase 1. diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index 3d150d03f..2086040c3 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -827,17 +827,19 @@ void SrsRtpPacket2::recycle_shared_msg() return; } - if (!shared_msg->payload || shared_msg->size != kRtpPacketSize || shared_msg->count() > 0) { - // Note that we must unwrap the shared message, because this object pool only cache the - // shared message itself without payload. - shared_msg->unwrap(); - _srs_rtp_msg_cache_objs->recycle(shared_msg); - goto cleanup; - } + // Only recycle the message for UDP packets. + if (shared_msg->payload && shared_msg->size == kRtpPacketSize) { + if (_srs_rtp_msg_cache_objs->enabled() && shared_msg->count() > 0) { + // Recycle the small shared message objects. + _srs_rtp_msg_cache_objs->recycle(shared_msg); + goto cleanup; + } - if (_srs_rtp_msg_cache_buffers->enabled()) { - _srs_rtp_msg_cache_buffers->recycle(shared_msg); - goto cleanup; + if (_srs_rtp_msg_cache_buffers->enabled() && shared_msg->count() == 0) { + // Recycle the UDP large buffer. + _srs_rtp_msg_cache_buffers->recycle(shared_msg); + goto cleanup; + } } srs_freep(shared_msg); From b91d37b78aa21f1fae50826c9ee950df64e6d873 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 28 Feb 2021 17:26:08 +0800 Subject: [PATCH 066/102] RTC: Store the actual size of buffer for RTP packet. --- trunk/src/kernel/srs_kernel_flv.hpp | 2 +- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 67 ++++++++++++++----------- trunk/src/kernel/srs_kernel_rtc_rtp.hpp | 7 ++- 3 files changed, 43 insertions(+), 33 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_flv.hpp b/trunk/src/kernel/srs_kernel_flv.hpp index 5250c12b2..67a7241ae 100644 --- a/trunk/src/kernel/srs_kernel_flv.hpp +++ b/trunk/src/kernel/srs_kernel_flv.hpp @@ -290,7 +290,7 @@ public: // video/audio packet use raw bytes, no video/audio packet. char* payload; -public: +private: class SrsSharedPtrPayload { public: diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index 2086040c3..b3fe73479 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -766,7 +766,8 @@ SrsRtpPacket2::SrsRtpPacket2() { payload_ = NULL; payload_type_ = SrsRtpPacketPayloadTypeUnknown; - shared_msg = NULL; + shared_buffer = NULL; + actual_buffer_size_ = 0; nalu_type = SrsAvcNaluTypeReserved; frame_type = SrsFrameTypeReserved; @@ -779,7 +780,7 @@ SrsRtpPacket2::SrsRtpPacket2() SrsRtpPacket2::~SrsRtpPacket2() { recycle_payload(); - recycle_shared_msg(); + recycle_shared_buffer(); } void SrsRtpPacket2::reset() @@ -794,7 +795,7 @@ void SrsRtpPacket2::reset() // Recyle the payload again, to ensure the packet is new one. recycle_payload(); - recycle_shared_msg(); + recycle_shared_buffer(); } void SrsRtpPacket2::recycle_payload() @@ -805,48 +806,47 @@ void SrsRtpPacket2::recycle_payload() if (payload_type_ == SrsRtpPacketPayloadTypeRaw && _srs_rtp_raw_cache->enabled()) { _srs_rtp_raw_cache->recycle((SrsRtpRawPayload*)payload_); - payload_ = NULL; goto cleanup; } if (payload_type_ == SrsRtpPacketPayloadTypeFUA2 && _srs_rtp_fua_cache->enabled()) { _srs_rtp_fua_cache->recycle((SrsRtpFUAPayload2*)payload_); - payload_ = NULL; goto cleanup; } srs_freep(payload_); cleanup: + payload_ = NULL; payload_type_ = SrsRtpPacketPayloadTypeUnknown; } -void SrsRtpPacket2::recycle_shared_msg() +void SrsRtpPacket2::recycle_shared_buffer() { - if (!shared_msg) { + if (!shared_buffer) { return; } // Only recycle the message for UDP packets. - if (shared_msg->payload && shared_msg->size == kRtpPacketSize) { - if (_srs_rtp_msg_cache_objs->enabled() && shared_msg->count() > 0) { + if (shared_buffer->payload && shared_buffer->size == kRtpPacketSize) { + if (_srs_rtp_msg_cache_objs->enabled() && shared_buffer->count() > 0) { // Recycle the small shared message objects. - _srs_rtp_msg_cache_objs->recycle(shared_msg); + _srs_rtp_msg_cache_objs->recycle(shared_buffer); goto cleanup; } - if (_srs_rtp_msg_cache_buffers->enabled() && shared_msg->count() == 0) { + if (_srs_rtp_msg_cache_buffers->enabled() && shared_buffer->count() == 0) { // Recycle the UDP large buffer. - _srs_rtp_msg_cache_buffers->recycle(shared_msg); + _srs_rtp_msg_cache_buffers->recycle(shared_buffer); goto cleanup; } } - srs_freep(shared_msg); - return; + srs_freep(shared_buffer); cleanup: - shared_msg = NULL; + shared_buffer = NULL; + actual_buffer_size_ = 0; } bool SrsRtpPacket2::recycle() @@ -859,7 +859,7 @@ bool SrsRtpPacket2::recycle() // We only recycle the payload and shared messages, // for header and fields, user will reset or copy it. recycle_payload(); - recycle_shared_msg(); + recycle_shared_buffer(); return true; } @@ -867,28 +867,30 @@ bool SrsRtpPacket2::recycle() char* SrsRtpPacket2::wrap(int size) { // If the buffer is large enough, reuse it. - if (shared_msg && shared_msg->size >= size) { - return shared_msg->payload; + if (shared_buffer && shared_buffer->size >= size) { + return shared_buffer->payload; } // Create a large enough message, with under-layer buffer. while (true) { - srs_freep(shared_msg); - shared_msg = _srs_rtp_msg_cache_buffers->allocate(); + srs_freep(shared_buffer); + shared_buffer = _srs_rtp_msg_cache_buffers->allocate(); + // The buffer size is larger or equals to the size of packet. + actual_buffer_size_ = size; // If got a cached message(which has payload), but it's too small, // we free it and allocate a larger one. - if (shared_msg->payload && shared_msg->size < size) { + if (shared_buffer->payload && shared_buffer->size < size) { ++_srs_pps_objs_rothers->sugar; continue; } // Create under-layer buffer for new message - if (!shared_msg->payload) { + if (!shared_buffer->payload) { // For RTC, we use larger under-layer buffer for each packet. int nb_buffer = srs_max(size, kRtpPacketSize); char* buf = new char[nb_buffer]; - shared_msg->wrap(buf, nb_buffer); + shared_buffer->wrap(buf, nb_buffer); ++_srs_pps_objs_rbuf->sugar; } @@ -896,7 +898,7 @@ char* SrsRtpPacket2::wrap(int size) break; } - return shared_msg->payload; + return shared_buffer->payload; } char* SrsRtpPacket2::wrap(char* data, int size) @@ -908,11 +910,15 @@ char* SrsRtpPacket2::wrap(char* data, int size) char* SrsRtpPacket2::wrap(SrsSharedPtrMessage* msg) { - // Recycle the shared message. - recycle_shared_msg(); + // Generally, the wrap(msg) is used for RTMP to RTC, which is not generated by RTC, + // so we do not recycle the msg. It's ok to directly free the msg, event the msg is + // allocated by object cache manager. + srs_freep(shared_buffer); // Copy from the new message. - shared_msg = msg->copy(); + shared_buffer = msg->copy(); + // If we wrap a message, the size of packet equals to the message size. + actual_buffer_size_ = shared_buffer->size; return msg->payload; } @@ -924,19 +930,20 @@ SrsRtpPacket2* SrsRtpPacket2::copy() // We got packet from cache, the payload and message MUST be NULL, // because we had clear it in recycle. //srs_assert(!cp->payload_); - //srs_assert(!cp->shared_msg); + //srs_assert(!cp->shared_buffer); cp->header = header; cp->payload_ = payload_? payload_->copy():NULL; cp->payload_type_ = payload_type_; cp->nalu_type = nalu_type; - cp->shared_msg = shared_msg->copy2(); + cp->shared_buffer = shared_buffer->copy2(); + cp->actual_buffer_size_ = actual_buffer_size_; cp->frame_type = frame_type; cp->cached_payload_size = cached_payload_size; // For performance issue, do not copy the unused field. - //cp->decode_handler = decode_handler; + cp->decode_handler = decode_handler; return cp; } diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index 967462903..da885d4d5 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -289,7 +289,10 @@ private: SrsRtpPacketPayloadType payload_type_; private: // The original shared message, all RTP packets can refer to its data. - SrsSharedPtrMessage* shared_msg; + // Note that the size of shared msg, is not the packet size, it's a larger aligned buffer. + SrsSharedPtrMessage* shared_buffer; + // The size of original packet. + int actual_buffer_size_; // Helper fields. public: // The first byte as nalu type, for video decoder only. @@ -311,7 +314,7 @@ public: void reset(); private: void recycle_payload(); - void recycle_shared_msg(); + void recycle_shared_buffer(); public: // Recycle the object to reuse it. virtual bool recycle(); From ee9ef378f9aa04aea48e2117c4eb1bc1c4970bd7 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 28 Feb 2021 17:36:03 +0800 Subject: [PATCH 067/102] RTC: Fix bug for wrap exists buffer size --- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index b3fe73479..80d6b8ff5 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -866,6 +866,9 @@ bool SrsRtpPacket2::recycle() char* SrsRtpPacket2::wrap(int size) { + // The buffer size is larger or equals to the size of packet. + actual_buffer_size_ = size; + // If the buffer is large enough, reuse it. if (shared_buffer && shared_buffer->size >= size) { return shared_buffer->payload; @@ -875,8 +878,6 @@ char* SrsRtpPacket2::wrap(int size) while (true) { srs_freep(shared_buffer); shared_buffer = _srs_rtp_msg_cache_buffers->allocate(); - // The buffer size is larger or equals to the size of packet. - actual_buffer_size_ = size; // If got a cached message(which has payload), but it's too small, // we free it and allocate a larger one. From 2719e4c0be8a7202fb10f06a2cf0d64fe3f07fba Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 28 Feb 2021 17:47:35 +0800 Subject: [PATCH 068/102] Refine code --- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 44 ++++++++++++------------- trunk/src/kernel/srs_kernel_rtc_rtp.hpp | 2 +- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index 80d6b8ff5..cbfe372af 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -766,7 +766,7 @@ SrsRtpPacket2::SrsRtpPacket2() { payload_ = NULL; payload_type_ = SrsRtpPacketPayloadTypeUnknown; - shared_buffer = NULL; + shared_buffer_ = NULL; actual_buffer_size_ = 0; nalu_type = SrsAvcNaluTypeReserved; @@ -823,29 +823,29 @@ cleanup: void SrsRtpPacket2::recycle_shared_buffer() { - if (!shared_buffer) { + if (!shared_buffer_) { return; } // Only recycle the message for UDP packets. - if (shared_buffer->payload && shared_buffer->size == kRtpPacketSize) { - if (_srs_rtp_msg_cache_objs->enabled() && shared_buffer->count() > 0) { + if (shared_buffer_->payload && shared_buffer_->size == kRtpPacketSize) { + if (_srs_rtp_msg_cache_objs->enabled() && shared_buffer_->count() > 0) { // Recycle the small shared message objects. - _srs_rtp_msg_cache_objs->recycle(shared_buffer); + _srs_rtp_msg_cache_objs->recycle(shared_buffer_); goto cleanup; } - if (_srs_rtp_msg_cache_buffers->enabled() && shared_buffer->count() == 0) { + if (_srs_rtp_msg_cache_buffers->enabled() && shared_buffer_->count() == 0) { // Recycle the UDP large buffer. - _srs_rtp_msg_cache_buffers->recycle(shared_buffer); + _srs_rtp_msg_cache_buffers->recycle(shared_buffer_); goto cleanup; } } - srs_freep(shared_buffer); + srs_freep(shared_buffer_); cleanup: - shared_buffer = NULL; + shared_buffer_ = NULL; actual_buffer_size_ = 0; } @@ -870,28 +870,28 @@ char* SrsRtpPacket2::wrap(int size) actual_buffer_size_ = size; // If the buffer is large enough, reuse it. - if (shared_buffer && shared_buffer->size >= size) { - return shared_buffer->payload; + if (shared_buffer_ && shared_buffer_->size >= size) { + return shared_buffer_->payload; } // Create a large enough message, with under-layer buffer. while (true) { - srs_freep(shared_buffer); - shared_buffer = _srs_rtp_msg_cache_buffers->allocate(); + srs_freep(shared_buffer_); + shared_buffer_ = _srs_rtp_msg_cache_buffers->allocate(); // If got a cached message(which has payload), but it's too small, // we free it and allocate a larger one. - if (shared_buffer->payload && shared_buffer->size < size) { + if (shared_buffer_->payload && shared_buffer_->size < size) { ++_srs_pps_objs_rothers->sugar; continue; } // Create under-layer buffer for new message - if (!shared_buffer->payload) { + if (!shared_buffer_->payload) { // For RTC, we use larger under-layer buffer for each packet. int nb_buffer = srs_max(size, kRtpPacketSize); char* buf = new char[nb_buffer]; - shared_buffer->wrap(buf, nb_buffer); + shared_buffer_->wrap(buf, nb_buffer); ++_srs_pps_objs_rbuf->sugar; } @@ -899,7 +899,7 @@ char* SrsRtpPacket2::wrap(int size) break; } - return shared_buffer->payload; + return shared_buffer_->payload; } char* SrsRtpPacket2::wrap(char* data, int size) @@ -914,12 +914,12 @@ char* SrsRtpPacket2::wrap(SrsSharedPtrMessage* msg) // Generally, the wrap(msg) is used for RTMP to RTC, which is not generated by RTC, // so we do not recycle the msg. It's ok to directly free the msg, event the msg is // allocated by object cache manager. - srs_freep(shared_buffer); + srs_freep(shared_buffer_); // Copy from the new message. - shared_buffer = msg->copy(); + shared_buffer_ = msg->copy(); // If we wrap a message, the size of packet equals to the message size. - actual_buffer_size_ = shared_buffer->size; + actual_buffer_size_ = shared_buffer_->size; return msg->payload; } @@ -931,14 +931,14 @@ SrsRtpPacket2* SrsRtpPacket2::copy() // We got packet from cache, the payload and message MUST be NULL, // because we had clear it in recycle. //srs_assert(!cp->payload_); - //srs_assert(!cp->shared_buffer); + //srs_assert(!cp->shared_buffer_); cp->header = header; cp->payload_ = payload_? payload_->copy():NULL; cp->payload_type_ = payload_type_; cp->nalu_type = nalu_type; - cp->shared_buffer = shared_buffer->copy2(); + cp->shared_buffer_ = shared_buffer_->copy2(); cp->actual_buffer_size_ = actual_buffer_size_; cp->frame_type = frame_type; diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index da885d4d5..5c29d67b5 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -290,7 +290,7 @@ private: private: // The original shared message, all RTP packets can refer to its data. // Note that the size of shared msg, is not the packet size, it's a larger aligned buffer. - SrsSharedPtrMessage* shared_buffer; + SrsSharedPtrMessage* shared_buffer_; // The size of original packet. int actual_buffer_size_; // Helper fields. From 50860325dd230a0a3667e2132d7a6a31cc870d3d Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 28 Feb 2021 18:22:04 +0800 Subject: [PATCH 069/102] RTC: Fix copy RTP packet bug --- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index cbfe372af..30d42e017 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -938,7 +938,7 @@ SrsRtpPacket2* SrsRtpPacket2::copy() cp->payload_type_ = payload_type_; cp->nalu_type = nalu_type; - cp->shared_buffer_ = shared_buffer_->copy2(); + cp->shared_buffer_ = shared_buffer_? shared_buffer_->copy2() : NULL; cp->actual_buffer_size_ = actual_buffer_size_; cp->frame_type = frame_type; From f63441413d62f1914f554c48c4a5a316e3df4cc5 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 28 Feb 2021 18:51:27 +0800 Subject: [PATCH 070/102] RTC: Support disable the NACK no-copy, enable copy by default --- trunk/conf/full.conf | 3 +++ trunk/src/app/srs_app_config.cpp | 22 ++++++++++++++++++++ trunk/src/app/srs_app_config.hpp | 1 + trunk/src/app/srs_app_rtc_conn.cpp | 30 ++++++++++++++++++++++++++-- trunk/src/app/srs_app_rtc_conn.hpp | 2 ++ trunk/src/app/srs_app_rtc_source.cpp | 18 +++++++++++++---- trunk/src/app/srs_app_rtc_source.hpp | 13 ++++++++++-- 7 files changed, 81 insertions(+), 8 deletions(-) diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 8cdbe363e..fa30db474 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -578,6 +578,9 @@ vhost rtc.vhost.srs.com { # Whether support NACK. # default: on enabled on; + # Whether directly use the packet, avoid copy. + # default: off + no_copy off; } # For TWCC. twcc { diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 164def7ef..fa16cc1aa 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -5249,6 +5249,28 @@ bool SrsConfig::get_rtc_nack_enabled(string vhost) return SRS_CONF_PERFER_TRUE(conf->arg0()); } +bool SrsConfig::get_rtc_nack_no_copy(string vhost) +{ + static bool DEFAULT = false; + + SrsConfDirective* conf = get_vhost(vhost); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("nack"); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("no_copy"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + return SRS_CONF_PERFER_FALSE(conf->arg0()); +} + bool SrsConfig::get_rtc_twcc_enabled(string vhost) { static bool DEFAULT = true; diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index a027e5f2f..31e174dc2 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -563,6 +563,7 @@ public: std::string get_rtc_dtls_version(std::string vhost); int get_rtc_drop_for_pt(std::string vhost); bool get_rtc_nack_enabled(std::string vhost); + bool get_rtc_nack_no_copy(std::string vhost); bool get_rtc_twcc_enabled(std::string vhost); // vhost specified section diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 68a581460..f0c9d18e6 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -381,6 +381,7 @@ SrsRtcPlayStream::SrsRtcPlayStream(SrsRtcConnection* s, const SrsContextId& cid) realtime = true; nack_enabled_ = false; + nack_no_copy_ = false; _srs_config->subscribe(this); timer_ = new SrsHourGlass("play", this, 1000 * SRS_UTIME_MILLISECONDS); @@ -446,7 +447,19 @@ srs_error_t SrsRtcPlayStream::initialize(SrsRequest* req, std::mapget_rtc_nack_enabled(req->vhost); - srs_trace("RTC player nack=%d", nack_enabled_); + nack_no_copy_ = _srs_config->get_rtc_nack_no_copy(req->vhost); + srs_trace("RTC player nack=%d, nnc=%d", nack_enabled_, nack_no_copy_); + + // Setup tracks. + for (map::iterator it = audio_tracks_.begin(); it != audio_tracks_.end(); ++it) { + SrsRtcAudioSendTrack* track = it->second; + track->set_nack_no_copy(nack_no_copy_); + } + + for (map::iterator it = video_tracks_.begin(); it != video_tracks_.end(); ++it) { + SrsRtcVideoSendTrack* track = it->second; + track->set_nack_no_copy(nack_no_copy_); + } // Update stat for session. session_->stat_->nn_subscribers++; @@ -849,6 +862,7 @@ SrsRtcPublishStream::SrsRtcPublishStream(SrsRtcConnection* session, const SrsCon source = NULL; nn_simulate_nack_drop = 0; nack_enabled_ = false; + nack_no_copy_ = false; pt_to_drop_ = 0; nn_audio_frames = 0; @@ -923,10 +937,22 @@ srs_error_t SrsRtcPublishStream::initialize(SrsRequest* r, SrsRtcStreamDescripti } nack_enabled_ = _srs_config->get_rtc_nack_enabled(req->vhost); + nack_no_copy_ = _srs_config->get_rtc_nack_no_copy(req->vhost); pt_to_drop_ = (uint16_t)_srs_config->get_rtc_drop_for_pt(req->vhost); twcc_enabled_ = _srs_config->get_rtc_twcc_enabled(req->vhost); - srs_trace("RTC publisher nack=%d, pt-drop=%u, twcc=%u/%d", nack_enabled_, pt_to_drop_, twcc_enabled_, twcc_id); + srs_trace("RTC publisher nack=%d, nnc=%d, pt-drop=%u, twcc=%u/%d", nack_enabled_, nack_no_copy_, pt_to_drop_, twcc_enabled_, twcc_id); + + // Setup tracks. + for (int i = 0; i < (int)audio_tracks_.size(); i++) { + SrsRtcAudioRecvTrack* track = audio_tracks_.at(i); + track->set_nack_no_copy(nack_no_copy_); + } + + for (int i = 0; i < (int)video_tracks_.size(); i++) { + SrsRtcVideoRecvTrack* track = video_tracks_.at(i); + track->set_nack_no_copy(nack_no_copy_); + } // Update stat for session. session_->stat_->nn_publishers++; diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 4d662320b..4f0373a46 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -233,6 +233,7 @@ private: bool realtime; // Whether enabled nack. bool nack_enabled_; + bool nack_no_copy_; private: // Whether palyer started. bool is_started; @@ -287,6 +288,7 @@ private: uint16_t pt_to_drop_; // Whether enabled nack. bool nack_enabled_; + bool nack_no_copy_; bool twcc_enabled_; private: bool request_keyframe_; diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index 429b949c7..cc328b176 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -1729,6 +1729,7 @@ SrsRtcRecvTrack::SrsRtcRecvTrack(SrsRtcConnection* session, SrsRtcTrackDescripti session_ = session; track_desc_ = track_desc->copy(); statistic_ = new SrsRtcTrackStatistic(); + nack_no_copy_ = false; if (is_audio) { rtp_queue_ = new SrsRtpRingBuffer(100); @@ -1838,8 +1839,12 @@ srs_error_t SrsRtcRecvTrack::on_nack(SrsRtpPacket2** ppkt) // insert into video_queue and audio_queue // We directly use the pkt, never copy it, so we should set the pkt to NULL. - rtp_queue_->set(seq, pkt); - *ppkt = NULL; + if (nack_no_copy_) { + rtp_queue_->set(seq, pkt); + *ppkt = NULL; + } else { + rtp_queue_->set(seq, pkt->copy()); + } return err; } @@ -1983,6 +1988,7 @@ SrsRtcSendTrack::SrsRtcSendTrack(SrsRtcConnection* session, SrsRtcTrackDescripti session_ = session; track_desc_ = track_desc->copy(); statistic_ = new SrsRtcTrackStatistic(); + nack_no_copy_ = false; if (is_audio) { rtp_queue_ = new SrsRtpRingBuffer(100); @@ -2058,8 +2064,12 @@ srs_error_t SrsRtcSendTrack::on_nack(SrsRtpPacket2** ppkt) // insert into video_queue and audio_queue // We directly use the pkt, never copy it, so we should set the pkt to NULL. - rtp_queue_->set(seq, pkt); - *ppkt = NULL; + if (nack_no_copy_) { + rtp_queue_->set(seq, pkt); + *ppkt = NULL; + } else { + rtp_queue_->set(seq, pkt->copy()); + } return err; } diff --git a/trunk/src/app/srs_app_rtc_source.hpp b/trunk/src/app/srs_app_rtc_source.hpp index db187faf6..8f29946f3 100644 --- a/trunk/src/app/srs_app_rtc_source.hpp +++ b/trunk/src/app/srs_app_rtc_source.hpp @@ -512,11 +512,14 @@ class SrsRtcRecvTrack protected: SrsRtcTrackDescription* track_desc_; SrsRtcTrackStatistic* statistic_; - +protected: SrsRtcConnection* session_; SrsRtpRingBuffer* rtp_queue_; SrsRtpNackForReceiver* nack_receiver_; - +private: + // By config, whether no copy. + bool nack_no_copy_; +protected: // send report ntp and received time. SrsNtp last_sender_report_ntp; uint64_t last_sender_report_sys_time; @@ -524,6 +527,8 @@ public: SrsRtcRecvTrack(SrsRtcConnection* session, SrsRtcTrackDescription* stream_descs, bool is_audio); virtual ~SrsRtcRecvTrack(); public: + // SrsRtcSendTrack::set_nack_no_copy + void set_nack_no_copy(bool v) { nack_no_copy_ = v; } bool has_ssrc(uint32_t ssrc); uint32_t get_ssrc(); void update_rtt(int rtt); @@ -580,12 +585,16 @@ protected: // NACK ARQ ring buffer. SrsRtpRingBuffer* rtp_queue_; private: + // By config, whether no copy. + bool nack_no_copy_; // The pithy print for special stage. SrsErrorPithyPrint* nack_epp; public: SrsRtcSendTrack(SrsRtcConnection* session, SrsRtcTrackDescription* track_desc, bool is_audio); virtual ~SrsRtcSendTrack(); public: + // SrsRtcSendTrack::set_nack_no_copy + void set_nack_no_copy(bool v) { nack_no_copy_ = v; } bool has_ssrc(uint32_t ssrc); SrsRtpPacket2* fetch_rtp_packet(uint16_t seq); bool set_track_status(bool active); From 58924d41b1664eb717d8216193e3e90e59b6b8bf Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 28 Feb 2021 20:27:34 +0800 Subject: [PATCH 071/102] RTC: Support high performance NO-COPY-NACK. 4.0.76 --- README.md | 1 + trunk/src/core/srs_core_version4.hpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8ef8ca3d1..cfc264ee1 100755 --- a/README.md +++ b/README.md @@ -156,6 +156,7 @@ For previous versions, please read: ## V4 changes +* v4.0, 2021-02-28, RTC: Support high performance NO-COPY-NACK. 4.0.76 * v4.0, 2021-02-27, RTC: Support object cache pool. 4.0.75 * v4.0, 2021-02-12, RTC: Support high performance timer about 25ms resolution. 4.0.72 * v4.0, 2021-02-10, RTC: Refine performance about 700+ streams. 4.0.71 diff --git a/trunk/src/core/srs_core_version4.hpp b/trunk/src/core/srs_core_version4.hpp index 405bea09e..05bc29894 100644 --- a/trunk/src/core/srs_core_version4.hpp +++ b/trunk/src/core/srs_core_version4.hpp @@ -24,6 +24,6 @@ #ifndef SRS_CORE_VERSION4_HPP #define SRS_CORE_VERSION4_HPP -#define SRS_VERSION4_REVISION 75 +#define SRS_VERSION4_REVISION 76 #endif From 781cd8e9de48adcc3009434bacafc532ed5296dd Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 28 Feb 2021 21:58:39 +0800 Subject: [PATCH 072/102] Update README --- README.md | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index cfc264ee1..d1b09747e 100755 --- a/README.md +++ b/README.md @@ -156,14 +156,10 @@ For previous versions, please read: ## V4 changes -* v4.0, 2021-02-28, RTC: Support high performance NO-COPY-NACK. 4.0.76 -* v4.0, 2021-02-27, RTC: Support object cache pool. 4.0.75 -* v4.0, 2021-02-12, RTC: Support high performance timer about 25ms resolution. 4.0.72 -* v4.0, 2021-02-10, RTC: Refine performance about 700+ streams. 4.0.71 -* v4.0, 2021-02-08, RTC: Print stat for pli and timer every 5s. 4.0.70 -* v4.0, 2021-02-07, RTC: Parse PT fast and refine udp handler. 4.0.69 -* v4.0, 2021-02-05, RTC: Refine UDP packet peer fast id. 4.0.68 -* v4.0, 2021-02-04, RTC: Reuse UDP socket to receive packet. 4.0.67 +* v4.0, 2021-02-28, RTC: Support high performance [NO-COPY-NACK](https://github.com/ossrs/srs/commit/36ea67359e55c94ab044cee4b6a4ec901a83a287#commitcomment-47654868). 4.0.76 +* v4.0, 2021-02-27, RTC: Support [Object Cache Pool](https://github.com/ossrs/srs/commit/14bfc98122bba369572417c19ebb2a61b373fc45#commitcomment-47655008) for performance. 4.0.75 +* v4.0, 2021-02-12, RTC: Support [High Resolution(about 25ms) Timer](https://github.com/ossrs/srs/commit/c5d2027f9af77fc2d34a6b6ca941c0f0fbdd10c4#commitcomment-47655747). 4.0.72 +* v4.0, 2021-02-10, RTC: [Improve performance about 700+](https://github.com/ossrs/srs/commit/b431ad738c39f34a5a0a39e81beb7854223db761#commitcomment-47655935) streams. 4.0.71 * v4.0, 2021-02-04, At least wait 1ms when <1ms, to avoid epoll_wait spin loop. 4.0.66 * v4.0, 2021-01-31, Enable -std=c++11 by default. 4.0.65 * v4.0, 2021-01-25, Enable --nasm and --srtp-asm by default for performance. 4.0.64 From eaf9ec6de860adde30b27161fa260b08c96bfd56 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 28 Feb 2021 22:02:24 +0800 Subject: [PATCH 073/102] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d1b09747e..dd3c6629d 100755 --- a/README.md +++ b/README.md @@ -156,7 +156,7 @@ For previous versions, please read: ## V4 changes -* v4.0, 2021-02-28, RTC: Support high performance [NO-COPY-NACK](https://github.com/ossrs/srs/commit/36ea67359e55c94ab044cee4b6a4ec901a83a287#commitcomment-47654868). 4.0.76 +* v4.0, 2021-02-28, RTC: Support high performance [Zero Copy NACK](https://github.com/ossrs/srs/commit/36ea67359e55c94ab044cee4b6a4ec901a83a287#commitcomment-47654868). 4.0.76 * v4.0, 2021-02-27, RTC: Support [Object Cache Pool](https://github.com/ossrs/srs/commit/14bfc98122bba369572417c19ebb2a61b373fc45#commitcomment-47655008) for performance. 4.0.75 * v4.0, 2021-02-12, RTC: Support [High Resolution(about 25ms) Timer](https://github.com/ossrs/srs/commit/c5d2027f9af77fc2d34a6b6ca941c0f0fbdd10c4#commitcomment-47655747). 4.0.72 * v4.0, 2021-02-10, RTC: [Improve performance about 700+](https://github.com/ossrs/srs/commit/b431ad738c39f34a5a0a39e81beb7854223db761#commitcomment-47655935) streams. 4.0.71 From 969b94784926fa342fa9a6d5cd30c386da031f93 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 2 Mar 2021 20:51:31 +0800 Subject: [PATCH 074/102] Hotfix 4.0.76, fix build fail for FFmpeg-fit CentOS6 --- trunk/configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trunk/configure b/trunk/configure index 02dc2a0cc..e5bb595ba 100755 --- a/trunk/configure +++ b/trunk/configure @@ -193,7 +193,7 @@ if [[ $SRS_GCOV == YES ]]; then fi # For FFMPEG/RTC. -if [[ $SRS_RTC == YES && $SRS_NASM == NO && $SRS_OSX == NO ]]; then +if [[ $SRS_RTC == YES && $SRS_FFMPEG_FIT == YES ]]; then SrsLinkOptions="${SrsLinkOptions} -lrt"; fi From 57f16299f4fb34c2307e435008782f0212df90df Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 3 Mar 2021 21:15:26 +0800 Subject: [PATCH 075/102] Fix #2219, Ubuntu build fail. Add CI for ubuntu20 --- .circleci/config.yml | 14 ++++++++++++-- trunk/auto/setup_variables.sh | 1 + trunk/src/core/srs_core_version4.hpp | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d62fc838d..1bd67557b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,6 +1,6 @@ version: 2 jobs: - build: + build-centos7: docker: - image: ossrs/srs:dev steps: @@ -9,6 +9,15 @@ jobs: cd trunk && ./configure --gb28181=off --utest=off --srtp-nasm=off && make && ./configure --gb28181=on --utest=on --srtp-nasm=on && make clean && make + build-ubuntu20: + docker: + - image: ossrs/srs:ubuntu20 + steps: + - checkout + - run: | + cd trunk && + ./configure --gb28181=off --utest=off --srtp-nasm=off && make && + ./configure --gb28181=on --utest=on --srtp-nasm=on && make clean && make test: docker: - image: ossrs/srs:dev @@ -22,5 +31,6 @@ workflows: version: 2 build_and_test: jobs: - - build + - build-centos7 + - build-ubuntu20 - test diff --git a/trunk/auto/setup_variables.sh b/trunk/auto/setup_variables.sh index cf26ea0c3..1a1bcb4d1 100755 --- a/trunk/auto/setup_variables.sh +++ b/trunk/auto/setup_variables.sh @@ -13,6 +13,7 @@ if [[ $OS_KERNEL_NAME == Darwin ]]; then SRS_PLATFORM="${SRS_PLATFORM}-${GCC_VERSION}" else GCC_VERSION="GCC$(gcc --version 2>/dev/null|grep gcc|awk '{print $3}')" + echo $GCC_VERSION| grep '-' >/dev/null && GCC_VERSION=$(echo $GCC_VERSION| awk -F '-' '{print$1}') SRS_PLATFORM="${SRS_PLATFORM}-${GCC_VERSION}" fi # Use isolate cache for different SRS version. diff --git a/trunk/src/core/srs_core_version4.hpp b/trunk/src/core/srs_core_version4.hpp index 05bc29894..11c87cb3a 100644 --- a/trunk/src/core/srs_core_version4.hpp +++ b/trunk/src/core/srs_core_version4.hpp @@ -24,6 +24,6 @@ #ifndef SRS_CORE_VERSION4_HPP #define SRS_CORE_VERSION4_HPP -#define SRS_VERSION4_REVISION 76 +#define SRS_VERSION4_REVISION 77 #endif From 6b2eb43e5cfa6f689696e82adc497b34b7d5b28f Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 3 Mar 2021 21:37:15 +0800 Subject: [PATCH 076/102] Fix #2219, Refine CI for ubuntu20 --- .circleci/config.yml | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1bd67557b..b3fe5f8a1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,23 +1,29 @@ version: 2 jobs: - build-centos7: + build-centos7-default: docker: - image: ossrs/srs:dev steps: - checkout - - run: | - cd trunk && - ./configure --gb28181=off --utest=off --srtp-nasm=off && make && - ./configure --gb28181=on --utest=on --srtp-nasm=on && make clean && make + - run: cd trunk && ./configure && make + build-centos7-noasm: + docker: + - image: ossrs/srs:dev + steps: + - checkout + - run: cd trunk && ./configure --nasm=off --srtp-nasm=off && make && + build-centos7-gb28181: + docker: + - image: ossrs/srs:dev + steps: + - checkout + - run: cd trunk && ./configure --gb28181=on && make build-ubuntu20: docker: - image: ossrs/srs:ubuntu20 steps: - checkout - - run: | - cd trunk && - ./configure --gb28181=off --utest=off --srtp-nasm=off && make && - ./configure --gb28181=on --utest=on --srtp-nasm=on && make clean && make + - run: cd trunk && ./configure && make test: docker: - image: ossrs/srs:dev @@ -25,12 +31,14 @@ jobs: - checkout - run: | cd trunk && - ./configure --gb28181=on --srtp-nasm=on --utest=on --gcov=on && make && + ./configure --gb28181=on --utest=on --gcov=on && make && ./objs/srs_utest && bash auto/coverage.sh workflows: version: 2 build_and_test: jobs: - - build-centos7 + - build-centos7-default + - build-centos7-noasm + - build-centos7-gb28181 - build-ubuntu20 - test From feca8f25783fcf06542a2bddf218d3f57c6dc1ae Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 3 Mar 2021 21:39:17 +0800 Subject: [PATCH 077/102] Fix #2219, Refine CI for ubuntu20 --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b3fe5f8a1..b5aa81f9a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -11,7 +11,7 @@ jobs: - image: ossrs/srs:dev steps: - checkout - - run: cd trunk && ./configure --nasm=off --srtp-nasm=off && make && + - run: cd trunk && ./configure --nasm=off --srtp-nasm=off && make build-centos7-gb28181: docker: - image: ossrs/srs:dev From 71876361019ad2a7244a5b150b6f5d483b620ef0 Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 3 Mar 2021 21:59:06 +0800 Subject: [PATCH 078/102] Fix #2219, Refine CI for ubuntu20 --- .circleci/config.yml | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b5aa81f9a..e185dbbeb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,23 +1,14 @@ version: 2 jobs: - build-centos7-default: + build-centos7: docker: - image: ossrs/srs:dev steps: - checkout - - run: cd trunk && ./configure && make - build-centos7-noasm: - docker: - - image: ossrs/srs:dev - steps: - - checkout - - run: cd trunk && ./configure --nasm=off --srtp-nasm=off && make - build-centos7-gb28181: - docker: - - image: ossrs/srs:dev - steps: - - checkout - - run: cd trunk && ./configure --gb28181=on && make + - run: | + cd trunk && ./configure && make && + ./configure --nasm=off --srtp-nasm=off && make clean && make && + ./configure --gb28181=on && make clean && make build-ubuntu20: docker: - image: ossrs/srs:ubuntu20 @@ -37,8 +28,6 @@ workflows: version: 2 build_and_test: jobs: - - build-centos7-default - - build-centos7-noasm - - build-centos7-gb28181 + - build-centos7 - build-ubuntu20 - test From f4331be2ef572dcd90711cc3cd91d5e879adb02c Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 3 Mar 2021 22:09:24 +0800 Subject: [PATCH 079/102] For #2219, Remove ubuntu20 CI --- .circleci/config.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index e185dbbeb..3a5dbe4cc 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -9,12 +9,6 @@ jobs: cd trunk && ./configure && make && ./configure --nasm=off --srtp-nasm=off && make clean && make && ./configure --gb28181=on && make clean && make - build-ubuntu20: - docker: - - image: ossrs/srs:ubuntu20 - steps: - - checkout - - run: cd trunk && ./configure && make test: docker: - image: ossrs/srs:dev @@ -29,5 +23,4 @@ workflows: build_and_test: jobs: - build-centos7 - - build-ubuntu20 - test From d4b8a57cf7a5eb2e7f9c331df83c1f3487ba3058 Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 1 Mar 2021 13:14:21 +0800 Subject: [PATCH 080/102] Enable Object Cache and Zero Copy Nack by default. 4.0.77 --- README.md | 1 + trunk/conf/full.conf | 12 ++++++------ trunk/src/app/srs_app_config.cpp | 12 ++++++------ 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index dd3c6629d..a9bed81fd 100755 --- a/README.md +++ b/README.md @@ -156,6 +156,7 @@ For previous versions, please read: ## V4 changes +* v4.0, 2021-03-01, Enable Object Cache and Zero Copy Nack by default. 4.0.77 * v4.0, 2021-02-28, RTC: Support high performance [Zero Copy NACK](https://github.com/ossrs/srs/commit/36ea67359e55c94ab044cee4b6a4ec901a83a287#commitcomment-47654868). 4.0.76 * v4.0, 2021-02-27, RTC: Support [Object Cache Pool](https://github.com/ossrs/srs/commit/14bfc98122bba369572417c19ebb2a61b373fc45#commitcomment-47655008) for performance. 4.0.75 * v4.0, 2021-02-12, RTC: Support [High Resolution(about 25ms) Timer](https://github.com/ossrs/srs/commit/c5d2027f9af77fc2d34a6b6ca941c0f0fbdd10c4#commitcomment-47655747). 4.0.72 diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index fa30db474..62307d2b5 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -494,8 +494,8 @@ rtc_server { # For RTP packet and its payload cache. rtp_cache { # Whether enable the RTP packet cache. - # default: off - enabled off; + # default: on + enabled on; # The cache size for rtp packet in MB, each object is about 300B.. # default: 64 pkt_size 64.0; @@ -506,8 +506,8 @@ rtc_server { # For RTP shared message and the large buffer cache. rtp_msg_cache { #Whether enable the RTP message(a large buffer) cache. - # default: off - enabled off; + # default: on + enabled on; # The cache size for message object in MB, each object is about 40B. # default: 16 msg_size 16.0; @@ -579,8 +579,8 @@ vhost rtc.vhost.srs.com { # default: on enabled on; # Whether directly use the packet, avoid copy. - # default: off - no_copy off; + # default: on + no_copy on; } # For TWCC. twcc { diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index fa16cc1aa..a0e78dec6 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -4919,7 +4919,7 @@ SrsConfDirective* SrsConfig::get_rtc_server_rtp_cache() bool SrsConfig::get_rtc_server_rtp_cache_enabled() { - static bool DEFAULT = false; + static bool DEFAULT = true; SrsConfDirective* conf = get_rtc_server_rtp_cache(); if (!conf) { @@ -4931,7 +4931,7 @@ bool SrsConfig::get_rtc_server_rtp_cache_enabled() return DEFAULT; } - return SRS_CONF_PERFER_FALSE(conf->arg0()); + return SRS_CONF_PERFER_TRUE(conf->arg0()); } uint64_t SrsConfig::get_rtc_server_rtp_cache_pkt_size() @@ -4985,7 +4985,7 @@ SrsConfDirective* SrsConfig::get_rtc_server_rtp_msg_cache() bool SrsConfig::get_rtc_server_rtp_msg_cache_enabled() { - static bool DEFAULT = false; + static bool DEFAULT = true; SrsConfDirective* conf = get_rtc_server_rtp_msg_cache(); if (!conf) { @@ -4997,7 +4997,7 @@ bool SrsConfig::get_rtc_server_rtp_msg_cache_enabled() return DEFAULT; } - return SRS_CONF_PERFER_FALSE(conf->arg0()); + return SRS_CONF_PERFER_TRUE(conf->arg0()); } uint64_t SrsConfig::get_rtc_server_rtp_msg_cache_msg_size() @@ -5251,7 +5251,7 @@ bool SrsConfig::get_rtc_nack_enabled(string vhost) bool SrsConfig::get_rtc_nack_no_copy(string vhost) { - static bool DEFAULT = false; + static bool DEFAULT = true; SrsConfDirective* conf = get_vhost(vhost); if (!conf) { @@ -5268,7 +5268,7 @@ bool SrsConfig::get_rtc_nack_no_copy(string vhost) return DEFAULT; } - return SRS_CONF_PERFER_FALSE(conf->arg0()); + return SRS_CONF_PERFER_TRUE(conf->arg0()); } bool SrsConfig::get_rtc_twcc_enabled(string vhost) From 8f1c9923795143a2afc13d1def94a5500243b34e Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 1 Mar 2021 14:36:38 +0800 Subject: [PATCH 081/102] Refine code, rename drop to loss --- trunk/src/app/srs_app_rtc_server.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index 45a4dc010..617337889 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -768,11 +768,11 @@ srs_error_t SrsRtcServer::notify(int type, srs_utime_t interval, srs_utime_t tic rnk_desc = buf; } - string drop_desc; + string loss_desc; SrsSnmpUdpStat* s = srs_get_udp_snmp_stat(); if (s->rcv_buf_errors_delta || s->snd_buf_errors_delta) { - snprintf(buf, sizeof(buf), ", drop=(r:%d,s:%d)", s->rcv_buf_errors_delta, s->snd_buf_errors_delta); - drop_desc = buf; + snprintf(buf, sizeof(buf), ", loss=(r:%d,s:%d)", s->rcv_buf_errors_delta, s->snd_buf_errors_delta); + loss_desc = buf; } string fid_desc; @@ -784,7 +784,7 @@ srs_error_t SrsRtcServer::notify(int type, srs_utime_t interval, srs_utime_t tic srs_trace("RTC: Server conns=%u%s%s%s%s%s%s%s", nn_rtc_conns, - rpkts_desc.c_str(), spkts_desc.c_str(), rtcp_desc.c_str(), snk_desc.c_str(), rnk_desc.c_str(), drop_desc.c_str(), fid_desc.c_str() + rpkts_desc.c_str(), spkts_desc.c_str(), rtcp_desc.c_str(), snk_desc.c_str(), rnk_desc.c_str(), loss_desc.c_str(), fid_desc.c_str() ); return err; From 96dbd7bced868ec21e92c7c727819b991012bfd6 Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 1 Mar 2021 20:47:57 +0800 Subject: [PATCH 082/102] Upgrade openssl from 1.1.0e to 1.1.1b, with source code. 4.0.78 --- README.md | 1 + .../Configurations/00-base-templates.conf | 356 + .../Configurations/10-main.conf | 1802 ++++ .../Configurations/15-android.conf | 261 + .../Configurations/15-ios.conf | 62 + .../Configurations/50-djgpp.conf | 17 + .../Configurations/50-haiku.conf | 30 + .../Configurations/50-masm.conf | 23 + .../Configurations/50-win-onecore.conf | 64 + .../Configurations/INTERNALS.Configure | 136 + .../openssl-1.1-fit/Configurations/README | 763 ++ .../Configurations/README.design | 623 ++ .../Configurations/common.tmpl | 221 + .../Configurations/common0.tmpl | 31 + .../Configurations/descrip.mms.tmpl | 1125 ++ .../Configurations/shared-info.pl | 82 + .../Configurations/unix-Makefile.tmpl | 1253 +++ .../Configurations/unix-checker.pm | 22 + .../Configurations/windows-checker.pm | 22 + .../Configurations/windows-makefile.tmpl | 760 ++ trunk/3rdparty/openssl-1.1-fit/Configure | 3519 ++++++ trunk/3rdparty/openssl-1.1-fit/LICENSE | 125 + trunk/3rdparty/openssl-1.1-fit/README.md | 3 + trunk/3rdparty/openssl-1.1-fit/apps/CA.pl.in | 214 + .../3rdparty/openssl-1.1-fit/apps/app_rand.c | 93 + trunk/3rdparty/openssl-1.1-fit/apps/apps.c | 2752 +++++ trunk/3rdparty/openssl-1.1-fit/apps/apps.h | 634 ++ .../3rdparty/openssl-1.1-fit/apps/asn1pars.c | 357 + .../3rdparty/openssl-1.1-fit/apps/bf_prefix.c | 177 + .../3rdparty/openssl-1.1-fit/apps/build.info | 38 + .../3rdparty/openssl-1.1-fit/apps/ca-cert.srl | 1 + .../3rdparty/openssl-1.1-fit/apps/ca-key.pem | 16 + .../3rdparty/openssl-1.1-fit/apps/ca-req.pem | 11 + trunk/3rdparty/openssl-1.1-fit/apps/ca.c | 2606 +++++ trunk/3rdparty/openssl-1.1-fit/apps/cert.pem | 11 + trunk/3rdparty/openssl-1.1-fit/apps/ciphers.c | 266 + .../3rdparty/openssl-1.1-fit/apps/client.pem | 52 + trunk/3rdparty/openssl-1.1-fit/apps/cms.c | 1289 +++ trunk/3rdparty/openssl-1.1-fit/apps/crl.c | 342 + trunk/3rdparty/openssl-1.1-fit/apps/crl2p7.c | 217 + .../openssl-1.1-fit/apps/ct_log_list.cnf | 9 + .../apps/demoSRP/srp_verifier.txt | 6 + .../apps/demoSRP/srp_verifier.txt.attr | 1 + trunk/3rdparty/openssl-1.1-fit/apps/dgst.c | 492 + .../3rdparty/openssl-1.1-fit/apps/dh1024.pem | 10 + .../3rdparty/openssl-1.1-fit/apps/dh2048.pem | 14 + .../3rdparty/openssl-1.1-fit/apps/dh4096.pem | 19 + trunk/3rdparty/openssl-1.1-fit/apps/dhparam.c | 379 + .../3rdparty/openssl-1.1-fit/apps/dsa-ca.pem | 47 + .../3rdparty/openssl-1.1-fit/apps/dsa-pca.pem | 47 + trunk/3rdparty/openssl-1.1-fit/apps/dsa.c | 265 + .../3rdparty/openssl-1.1-fit/apps/dsa1024.pem | 9 + .../3rdparty/openssl-1.1-fit/apps/dsa512.pem | 6 + trunk/3rdparty/openssl-1.1-fit/apps/dsap.pem | 6 + .../3rdparty/openssl-1.1-fit/apps/dsaparam.c | 258 + trunk/3rdparty/openssl-1.1-fit/apps/ec.c | 283 + trunk/3rdparty/openssl-1.1-fit/apps/ecparam.c | 450 + trunk/3rdparty/openssl-1.1-fit/apps/enc.c | 675 ++ trunk/3rdparty/openssl-1.1-fit/apps/engine.c | 489 + trunk/3rdparty/openssl-1.1-fit/apps/errstr.c | 67 + trunk/3rdparty/openssl-1.1-fit/apps/gendsa.c | 146 + trunk/3rdparty/openssl-1.1-fit/apps/genpkey.c | 322 + trunk/3rdparty/openssl-1.1-fit/apps/genrsa.c | 201 + trunk/3rdparty/openssl-1.1-fit/apps/nseq.c | 114 + trunk/3rdparty/openssl-1.1-fit/apps/ocsp.c | 1621 +++ .../openssl-1.1-fit/apps/openssl-vms.cnf | 350 + trunk/3rdparty/openssl-1.1-fit/apps/openssl.c | 826 ++ .../3rdparty/openssl-1.1-fit/apps/openssl.cnf | 350 + trunk/3rdparty/openssl-1.1-fit/apps/opt.c | 898 ++ trunk/3rdparty/openssl-1.1-fit/apps/passwd.c | 853 ++ .../openssl-1.1-fit/apps/pca-cert.srl | 1 + .../3rdparty/openssl-1.1-fit/apps/pca-key.pem | 16 + .../3rdparty/openssl-1.1-fit/apps/pca-req.pem | 11 + trunk/3rdparty/openssl-1.1-fit/apps/pkcs12.c | 968 ++ trunk/3rdparty/openssl-1.1-fit/apps/pkcs7.c | 198 + trunk/3rdparty/openssl-1.1-fit/apps/pkcs8.c | 359 + trunk/3rdparty/openssl-1.1-fit/apps/pkey.c | 243 + .../3rdparty/openssl-1.1-fit/apps/pkeyparam.c | 142 + trunk/3rdparty/openssl-1.1-fit/apps/pkeyutl.c | 525 + trunk/3rdparty/openssl-1.1-fit/apps/prime.c | 133 + .../3rdparty/openssl-1.1-fit/apps/privkey.pem | 16 + trunk/3rdparty/openssl-1.1-fit/apps/progs.pl | 181 + trunk/3rdparty/openssl-1.1-fit/apps/rand.c | 133 + trunk/3rdparty/openssl-1.1-fit/apps/rehash.c | 532 + trunk/3rdparty/openssl-1.1-fit/apps/req.c | 1664 +++ trunk/3rdparty/openssl-1.1-fit/apps/req.pem | 11 + trunk/3rdparty/openssl-1.1-fit/apps/rsa.c | 316 + .../3rdparty/openssl-1.1-fit/apps/rsa8192.pem | 101 + trunk/3rdparty/openssl-1.1-fit/apps/rsautl.c | 282 + .../openssl-1.1-fit/apps/s1024key.pem | 15 + .../openssl-1.1-fit/apps/s1024req.pem | 11 + .../openssl-1.1-fit/apps/s512-key.pem | 9 + .../openssl-1.1-fit/apps/s512-req.pem | 8 + trunk/3rdparty/openssl-1.1-fit/apps/s_apps.h | 89 + trunk/3rdparty/openssl-1.1-fit/apps/s_cb.c | 1481 +++ .../3rdparty/openssl-1.1-fit/apps/s_client.c | 3544 ++++++ .../3rdparty/openssl-1.1-fit/apps/s_server.c | 3632 +++++++ .../3rdparty/openssl-1.1-fit/apps/s_socket.c | 395 + trunk/3rdparty/openssl-1.1-fit/apps/s_time.c | 405 + .../3rdparty/openssl-1.1-fit/apps/server.pem | 52 + .../3rdparty/openssl-1.1-fit/apps/server.srl | 1 + .../3rdparty/openssl-1.1-fit/apps/server2.pem | 52 + trunk/3rdparty/openssl-1.1-fit/apps/sess_id.c | 191 + trunk/3rdparty/openssl-1.1-fit/apps/smime.c | 647 ++ trunk/3rdparty/openssl-1.1-fit/apps/speed.c | 3691 +++++++ trunk/3rdparty/openssl-1.1-fit/apps/spkac.c | 202 + trunk/3rdparty/openssl-1.1-fit/apps/srp.c | 613 ++ .../3rdparty/openssl-1.1-fit/apps/storeutl.c | 473 + .../3rdparty/openssl-1.1-fit/apps/testCA.pem | 8 + trunk/3rdparty/openssl-1.1-fit/apps/testdsa.h | 260 + trunk/3rdparty/openssl-1.1-fit/apps/testrsa.h | 1960 ++++ .../3rdparty/openssl-1.1-fit/apps/timeouts.h | 17 + trunk/3rdparty/openssl-1.1-fit/apps/ts.c | 986 ++ trunk/3rdparty/openssl-1.1-fit/apps/tsget.in | 200 + trunk/3rdparty/openssl-1.1-fit/apps/verify.c | 322 + trunk/3rdparty/openssl-1.1-fit/apps/version.c | 194 + .../openssl-1.1-fit/apps/vms_decc_init.c | 214 + .../openssl-1.1-fit/apps/vms_term_sock.c | 591 + .../openssl-1.1-fit/apps/vms_term_sock.h | 31 + .../openssl-1.1-fit/apps/win32_init.c | 307 + trunk/3rdparty/openssl-1.1-fit/apps/x509.c | 1196 +++ trunk/3rdparty/openssl-1.1-fit/appveyor.yml | 66 + trunk/3rdparty/openssl-1.1-fit/build.info | 103 + trunk/3rdparty/openssl-1.1-fit/config | 946 ++ trunk/3rdparty/openssl-1.1-fit/config.com | 93 + .../openssl-1.1-fit/crypto/LPdir_nyi.c | 56 + .../openssl-1.1-fit/crypto/LPdir_unix.c | 169 + .../openssl-1.1-fit/crypto/LPdir_vms.c | 207 + .../openssl-1.1-fit/crypto/LPdir_win.c | 214 + .../openssl-1.1-fit/crypto/LPdir_win32.c | 41 + .../openssl-1.1-fit/crypto/LPdir_wince.c | 44 + .../openssl-1.1-fit/crypto/aes/aes_cbc.c | 24 + .../openssl-1.1-fit/crypto/aes/aes_cfb.c | 43 + .../openssl-1.1-fit/crypto/aes/aes_core.c | 1367 +++ .../openssl-1.1-fit/crypto/aes/aes_ecb.c | 26 + .../openssl-1.1-fit/crypto/aes/aes_ige.c | 284 + .../openssl-1.1-fit/crypto/aes/aes_locl.h | 42 + .../openssl-1.1-fit/crypto/aes/aes_misc.c | 21 + .../openssl-1.1-fit/crypto/aes/aes_ofb.c | 19 + .../openssl-1.1-fit/crypto/aes/aes_wrap.c | 27 + .../openssl-1.1-fit/crypto/aes/aes_x86core.c | 1074 ++ .../openssl-1.1-fit/crypto/aes/asm/aes-586.pl | 3000 ++++++ .../crypto/aes/asm/aes-armv4.pl | 1245 +++ .../crypto/aes/asm/aes-c64xplus.pl | 1382 +++ .../openssl-1.1-fit/crypto/aes/asm/aes-ia64.S | 1130 ++ .../crypto/aes/asm/aes-mips.pl | 2170 ++++ .../crypto/aes/asm/aes-parisc.pl | 1038 ++ .../openssl-1.1-fit/crypto/aes/asm/aes-ppc.pl | 1459 +++ .../crypto/aes/asm/aes-s390x.pl | 2282 ++++ .../crypto/aes/asm/aes-sparcv9.pl | 1192 ++ .../crypto/aes/asm/aes-x86_64.pl | 2916 +++++ .../crypto/aes/asm/aesfx-sparcv9.pl | 1270 +++ .../crypto/aes/asm/aesni-mb-x86_64.pl | 1474 +++ .../crypto/aes/asm/aesni-sha1-x86_64.pl | 2140 ++++ .../crypto/aes/asm/aesni-sha256-x86_64.pl | 1770 +++ .../crypto/aes/asm/aesni-x86.pl | 3415 ++++++ .../crypto/aes/asm/aesni-x86_64.pl | 5141 +++++++++ .../crypto/aes/asm/aesp8-ppc.pl | 3807 +++++++ .../crypto/aes/asm/aest4-sparcv9.pl | 929 ++ .../crypto/aes/asm/aesv8-armx.pl | 1011 ++ .../crypto/aes/asm/bsaes-armv7.pl | 2491 +++++ .../crypto/aes/asm/bsaes-x86_64.pl | 3239 ++++++ .../crypto/aes/asm/vpaes-armv8.pl | 1277 +++ .../crypto/aes/asm/vpaes-ppc.pl | 1594 +++ .../crypto/aes/asm/vpaes-x86.pl | 916 ++ .../crypto/aes/asm/vpaes-x86_64.pl | 1241 +++ .../openssl-1.1-fit/crypto/aes/build.info | 64 + .../openssl-1.1-fit/crypto/alphacpuid.pl | 257 + .../openssl-1.1-fit/crypto/aria/aria.c | 1212 +++ .../openssl-1.1-fit/crypto/aria/build.info | 4 + .../openssl-1.1-fit/crypto/arm64cpuid.pl | 147 + .../openssl-1.1-fit/crypto/arm_arch.h | 84 + .../3rdparty/openssl-1.1-fit/crypto/armcap.c | 214 + .../openssl-1.1-fit/crypto/armv4cpuid.pl | 296 + .../openssl-1.1-fit/crypto/asn1/a_bitstr.c | 216 + .../openssl-1.1-fit/crypto/asn1/a_d2i_fp.c | 234 + .../openssl-1.1-fit/crypto/asn1/a_digest.c | 67 + .../openssl-1.1-fit/crypto/asn1/a_dup.c | 68 + .../openssl-1.1-fit/crypto/asn1/a_gentm.c | 82 + .../openssl-1.1-fit/crypto/asn1/a_i2d_fp.c | 111 + .../openssl-1.1-fit/crypto/asn1/a_int.c | 630 ++ .../openssl-1.1-fit/crypto/asn1/a_mbstr.c | 343 + .../openssl-1.1-fit/crypto/asn1/a_object.c | 383 + .../openssl-1.1-fit/crypto/asn1/a_octet.c | 29 + .../openssl-1.1-fit/crypto/asn1/a_print.c | 95 + .../openssl-1.1-fit/crypto/asn1/a_sign.c | 241 + .../openssl-1.1-fit/crypto/asn1/a_strex.c | 626 ++ .../openssl-1.1-fit/crypto/asn1/a_strnid.c | 219 + .../openssl-1.1-fit/crypto/asn1/a_time.c | 553 + .../openssl-1.1-fit/crypto/asn1/a_type.c | 134 + .../openssl-1.1-fit/crypto/asn1/a_utctm.c | 98 + .../openssl-1.1-fit/crypto/asn1/a_utf8.c | 188 + .../openssl-1.1-fit/crypto/asn1/a_verify.c | 178 + .../openssl-1.1-fit/crypto/asn1/ameth_lib.c | 451 + .../openssl-1.1-fit/crypto/asn1/asn1_err.c | 350 + .../openssl-1.1-fit/crypto/asn1/asn1_gen.c | 789 ++ .../crypto/asn1/asn1_item_list.c | 42 + .../crypto/asn1/asn1_item_list.h | 178 + .../openssl-1.1-fit/crypto/asn1/asn1_lib.c | 391 + .../openssl-1.1-fit/crypto/asn1/asn1_locl.h | 83 + .../openssl-1.1-fit/crypto/asn1/asn1_par.c | 375 + .../openssl-1.1-fit/crypto/asn1/asn_mime.c | 963 ++ .../openssl-1.1-fit/crypto/asn1/asn_moid.c | 100 + .../openssl-1.1-fit/crypto/asn1/asn_mstbl.c | 113 + .../openssl-1.1-fit/crypto/asn1/asn_pack.c | 62 + .../openssl-1.1-fit/crypto/asn1/bio_asn1.c | 444 + .../openssl-1.1-fit/crypto/asn1/bio_ndef.c | 201 + .../openssl-1.1-fit/crypto/asn1/build.info | 16 + .../openssl-1.1-fit/crypto/asn1/charmap.h | 34 + .../openssl-1.1-fit/crypto/asn1/charmap.pl | 119 + .../openssl-1.1-fit/crypto/asn1/d2i_pr.c | 125 + .../openssl-1.1-fit/crypto/asn1/d2i_pu.c | 77 + .../openssl-1.1-fit/crypto/asn1/evp_asn1.c | 115 + .../openssl-1.1-fit/crypto/asn1/f_int.c | 156 + .../openssl-1.1-fit/crypto/asn1/f_string.c | 136 + .../openssl-1.1-fit/crypto/asn1/i2d_pr.c | 33 + .../openssl-1.1-fit/crypto/asn1/i2d_pu.c | 38 + .../openssl-1.1-fit/crypto/asn1/n_pkey.c | 62 + .../openssl-1.1-fit/crypto/asn1/nsseq.c | 34 + .../openssl-1.1-fit/crypto/asn1/p5_pbe.c | 96 + .../openssl-1.1-fit/crypto/asn1/p5_pbev2.c | 221 + .../openssl-1.1-fit/crypto/asn1/p5_scrypt.c | 274 + .../openssl-1.1-fit/crypto/asn1/p8_pkey.c | 80 + .../crypto/asn1/standard_methods.h | 61 + .../openssl-1.1-fit/crypto/asn1/t_bitst.c | 56 + .../openssl-1.1-fit/crypto/asn1/t_pkey.c | 93 + .../openssl-1.1-fit/crypto/asn1/t_spki.c | 56 + .../openssl-1.1-fit/crypto/asn1/tasn_dec.c | 1160 ++ .../openssl-1.1-fit/crypto/asn1/tasn_enc.c | 609 ++ .../openssl-1.1-fit/crypto/asn1/tasn_fre.c | 208 + .../openssl-1.1-fit/crypto/asn1/tasn_new.c | 349 + .../openssl-1.1-fit/crypto/asn1/tasn_prn.c | 539 + .../openssl-1.1-fit/crypto/asn1/tasn_scn.c | 65 + .../openssl-1.1-fit/crypto/asn1/tasn_typ.c | 84 + .../openssl-1.1-fit/crypto/asn1/tasn_utl.c | 253 + .../crypto/asn1/tbl_standard.h | 61 + .../openssl-1.1-fit/crypto/asn1/x_algor.c | 94 + .../openssl-1.1-fit/crypto/asn1/x_bignum.c | 146 + .../openssl-1.1-fit/crypto/asn1/x_info.c | 39 + .../openssl-1.1-fit/crypto/asn1/x_int64.c | 291 + .../openssl-1.1-fit/crypto/asn1/x_long.c | 201 + .../openssl-1.1-fit/crypto/asn1/x_pkey.c | 47 + .../openssl-1.1-fit/crypto/asn1/x_sig.c | 39 + .../openssl-1.1-fit/crypto/asn1/x_spki.c | 28 + .../openssl-1.1-fit/crypto/asn1/x_val.c | 20 + .../crypto/async/arch/async_null.c | 23 + .../crypto/async/arch/async_null.h | 30 + .../crypto/async/arch/async_posix.c | 58 + .../crypto/async/arch/async_posix.h | 58 + .../crypto/async/arch/async_win.c | 55 + .../crypto/async/arch/async_win.h | 36 + .../openssl-1.1-fit/crypto/async/async.c | 451 + .../openssl-1.1-fit/crypto/async/async_err.c | 51 + .../openssl-1.1-fit/crypto/async/async_locl.h | 77 + .../openssl-1.1-fit/crypto/async/async_wait.c | 213 + .../openssl-1.1-fit/crypto/async/build.info | 4 + .../openssl-1.1-fit/crypto/bf/asm/bf-586.pl | 149 + .../openssl-1.1-fit/crypto/bf/bf_cfb64.c | 74 + .../openssl-1.1-fit/crypto/bf/bf_ecb.c | 43 + .../openssl-1.1-fit/crypto/bf/bf_enc.c | 175 + .../openssl-1.1-fit/crypto/bf/bf_locl.h | 84 + .../openssl-1.1-fit/crypto/bf/bf_ofb64.c | 61 + .../openssl-1.1-fit/crypto/bf/bf_pi.h | 530 + .../openssl-1.1-fit/crypto/bf/bf_skey.c | 67 + .../openssl-1.1-fit/crypto/bf/build.info | 7 + .../openssl-1.1-fit/crypto/bio/b_addr.c | 902 ++ .../openssl-1.1-fit/crypto/bio/b_dump.c | 148 + .../openssl-1.1-fit/crypto/bio/b_print.c | 930 ++ .../openssl-1.1-fit/crypto/bio/b_sock.c | 369 + .../openssl-1.1-fit/crypto/bio/b_sock2.c | 317 + .../openssl-1.1-fit/crypto/bio/bf_buff.c | 475 + .../openssl-1.1-fit/crypto/bio/bf_lbuf.c | 326 + .../openssl-1.1-fit/crypto/bio/bf_nbio.c | 200 + .../openssl-1.1-fit/crypto/bio/bf_null.c | 122 + .../openssl-1.1-fit/crypto/bio/bio_cb.c | 98 + .../openssl-1.1-fit/crypto/bio/bio_err.c | 145 + .../openssl-1.1-fit/crypto/bio/bio_lcl.h | 190 + .../openssl-1.1-fit/crypto/bio/bio_lib.c | 786 ++ .../openssl-1.1-fit/crypto/bio/bio_meth.c | 220 + .../openssl-1.1-fit/crypto/bio/bss_acpt.c | 560 + .../openssl-1.1-fit/crypto/bio/bss_bio.c | 808 ++ .../openssl-1.1-fit/crypto/bio/bss_conn.c | 540 + .../openssl-1.1-fit/crypto/bio/bss_dgram.c | 1925 ++++ .../openssl-1.1-fit/crypto/bio/bss_fd.c | 280 + .../openssl-1.1-fit/crypto/bio/bss_file.c | 427 + .../openssl-1.1-fit/crypto/bio/bss_log.c | 416 + .../openssl-1.1-fit/crypto/bio/bss_mem.c | 357 + .../openssl-1.1-fit/crypto/bio/bss_null.c | 87 + .../openssl-1.1-fit/crypto/bio/bss_sock.c | 233 + .../openssl-1.1-fit/crypto/bio/build.info | 8 + .../crypto/blake2/blake2_impl.h | 129 + .../crypto/blake2/blake2_locl.h | 90 + .../openssl-1.1-fit/crypto/blake2/blake2b.c | 269 + .../openssl-1.1-fit/crypto/blake2/blake2s.c | 263 + .../openssl-1.1-fit/crypto/blake2/build.info | 3 + .../openssl-1.1-fit/crypto/blake2/m_blake2b.c | 59 + .../openssl-1.1-fit/crypto/blake2/m_blake2s.c | 59 + .../openssl-1.1-fit/crypto/bn/README.pod | 241 + .../crypto/bn/asm/alpha-mont.pl | 328 + .../crypto/bn/asm/armv4-gf2m.pl | 332 + .../crypto/bn/asm/armv4-mont.pl | 757 ++ .../crypto/bn/asm/armv8-mont.pl | 1514 +++ .../openssl-1.1-fit/crypto/bn/asm/bn-586.pl | 785 ++ .../crypto/bn/asm/bn-c64xplus.asm | 382 + .../crypto/bn/asm/c64xplus-gf2m.pl | 160 + .../openssl-1.1-fit/crypto/bn/asm/co-586.pl | 298 + .../crypto/bn/asm/ia64-mont.pl | 860 ++ .../openssl-1.1-fit/crypto/bn/asm/ia64.S | 1565 +++ .../crypto/bn/asm/mips-mont.pl | 433 + .../openssl-1.1-fit/crypto/bn/asm/mips.pl | 2263 ++++ .../crypto/bn/asm/parisc-mont.pl | 1006 ++ .../openssl-1.1-fit/crypto/bn/asm/ppc-mont.pl | 1990 ++++ .../openssl-1.1-fit/crypto/bn/asm/ppc.pl | 2011 ++++ .../crypto/bn/asm/ppc64-mont.pl | 1652 +++ .../crypto/bn/asm/rsaz-avx2.pl | 1982 ++++ .../crypto/bn/asm/rsaz-x86_64.pl | 2404 +++++ .../crypto/bn/asm/s390x-gf2m.pl | 228 + .../crypto/bn/asm/s390x-mont.pl | 284 + .../openssl-1.1-fit/crypto/bn/asm/s390x.S | 713 ++ .../crypto/bn/asm/sparct4-mont.pl | 1228 +++ .../openssl-1.1-fit/crypto/bn/asm/sparcv8.S | 1458 +++ .../crypto/bn/asm/sparcv8plus.S | 1558 +++ .../crypto/bn/asm/sparcv9-gf2m.pl | 200 + .../crypto/bn/asm/sparcv9-mont.pl | 620 ++ .../crypto/bn/asm/sparcv9a-mont.pl | 887 ++ .../openssl-1.1-fit/crypto/bn/asm/via-mont.pl | 251 + .../crypto/bn/asm/vis3-mont.pl | 384 + .../openssl-1.1-fit/crypto/bn/asm/x86-gf2m.pl | 325 + .../openssl-1.1-fit/crypto/bn/asm/x86-mont.pl | 631 ++ .../crypto/bn/asm/x86_64-gcc.c | 643 ++ .../crypto/bn/asm/x86_64-gf2m.pl | 424 + .../crypto/bn/asm/x86_64-mont.pl | 1592 +++ .../crypto/bn/asm/x86_64-mont5.pl | 3945 +++++++ .../openssl-1.1-fit/crypto/bn/bn_add.c | 171 + .../openssl-1.1-fit/crypto/bn/bn_asm.c | 1039 ++ .../openssl-1.1-fit/crypto/bn/bn_blind.c | 312 + .../openssl-1.1-fit/crypto/bn/bn_const.c | 553 + .../openssl-1.1-fit/crypto/bn/bn_ctx.c | 361 + .../openssl-1.1-fit/crypto/bn/bn_depr.c | 68 + .../openssl-1.1-fit/crypto/bn/bn_dh.c | 512 + .../openssl-1.1-fit/crypto/bn/bn_div.c | 457 + .../openssl-1.1-fit/crypto/bn/bn_err.c | 118 + .../openssl-1.1-fit/crypto/bn/bn_exp.c | 1395 +++ .../openssl-1.1-fit/crypto/bn/bn_exp2.c | 201 + .../openssl-1.1-fit/crypto/bn/bn_gcd.c | 623 ++ .../openssl-1.1-fit/crypto/bn/bn_gf2m.c | 1166 ++ .../openssl-1.1-fit/crypto/bn/bn_intern.c | 199 + .../openssl-1.1-fit/crypto/bn/bn_kron.c | 140 + .../openssl-1.1-fit/crypto/bn/bn_lcl.h | 671 ++ .../openssl-1.1-fit/crypto/bn/bn_lib.c | 964 ++ .../openssl-1.1-fit/crypto/bn/bn_mod.c | 321 + .../openssl-1.1-fit/crypto/bn/bn_mont.c | 464 + .../openssl-1.1-fit/crypto/bn/bn_mpi.c | 86 + .../openssl-1.1-fit/crypto/bn/bn_mul.c | 684 ++ .../openssl-1.1-fit/crypto/bn/bn_nist.c | 1239 +++ .../openssl-1.1-fit/crypto/bn/bn_prime.c | 469 + .../openssl-1.1-fit/crypto/bn/bn_prime.h | 273 + .../openssl-1.1-fit/crypto/bn/bn_prime.pl | 48 + .../openssl-1.1-fit/crypto/bn/bn_print.c | 345 + .../openssl-1.1-fit/crypto/bn/bn_rand.c | 268 + .../openssl-1.1-fit/crypto/bn/bn_recp.c | 194 + .../openssl-1.1-fit/crypto/bn/bn_shift.c | 257 + .../openssl-1.1-fit/crypto/bn/bn_sqr.c | 239 + .../openssl-1.1-fit/crypto/bn/bn_sqrt.c | 358 + .../openssl-1.1-fit/crypto/bn/bn_srp.c | 545 + .../openssl-1.1-fit/crypto/bn/bn_word.c | 201 + .../openssl-1.1-fit/crypto/bn/bn_x931p.c | 244 + .../openssl-1.1-fit/crypto/bn/build.info | 67 + .../openssl-1.1-fit/crypto/bn/rsaz_exp.c | 315 + .../openssl-1.1-fit/crypto/bn/rsaz_exp.h | 40 + .../openssl-1.1-fit/crypto/buffer/buf_err.c | 38 + .../openssl-1.1-fit/crypto/buffer/buffer.c | 165 + .../openssl-1.1-fit/crypto/buffer/build.info | 2 + .../openssl-1.1-fit/crypto/build.info | 39 + .../openssl-1.1-fit/crypto/c64xpluscpuid.pl | 287 + .../crypto/camellia/asm/cmll-x86.pl | 1150 ++ .../crypto/camellia/asm/cmll-x86_64.pl | 1145 ++ .../crypto/camellia/asm/cmllt4-sparcv9.pl | 939 ++ .../crypto/camellia/build.info | 13 + .../crypto/camellia/camellia.c | 501 + .../crypto/camellia/cmll_cbc.c | 24 + .../crypto/camellia/cmll_cfb.c | 43 + .../crypto/camellia/cmll_ctr.c | 22 + .../crypto/camellia/cmll_ecb.c | 20 + .../crypto/camellia/cmll_locl.h | 43 + .../crypto/camellia/cmll_misc.c | 35 + .../crypto/camellia/cmll_ofb.c | 24 + .../crypto/cast/asm/cast-586.pl | 192 + .../openssl-1.1-fit/crypto/cast/build.info | 7 + .../openssl-1.1-fit/crypto/cast/c_cfb64.c | 74 + .../openssl-1.1-fit/crypto/cast/c_ecb.c | 32 + .../openssl-1.1-fit/crypto/cast/c_enc.c | 151 + .../openssl-1.1-fit/crypto/cast/c_ofb64.c | 61 + .../openssl-1.1-fit/crypto/cast/c_skey.c | 118 + .../openssl-1.1-fit/crypto/cast/cast_lcl.h | 188 + .../openssl-1.1-fit/crypto/cast/cast_s.h | 544 + .../crypto/chacha/asm/chacha-armv4.pl | 1160 ++ .../crypto/chacha/asm/chacha-armv8.pl | 1144 ++ .../crypto/chacha/asm/chacha-c64xplus.pl | 926 ++ .../crypto/chacha/asm/chacha-ppc.pl | 1348 +++ .../crypto/chacha/asm/chacha-s390x.pl | 326 + .../crypto/chacha/asm/chacha-x86.pl | 1155 ++ .../crypto/chacha/asm/chacha-x86_64.pl | 4005 +++++++ .../openssl-1.1-fit/crypto/chacha/build.info | 18 + .../crypto/chacha/chacha_enc.c | 121 + .../openssl-1.1-fit/crypto/cmac/build.info | 2 + .../openssl-1.1-fit/crypto/cmac/cm_ameth.c | 51 + .../openssl-1.1-fit/crypto/cmac/cm_pmeth.c | 161 + .../openssl-1.1-fit/crypto/cmac/cmac.c | 226 + .../openssl-1.1-fit/crypto/cms/build.info | 5 + .../openssl-1.1-fit/crypto/cms/cms_asn1.c | 403 + .../openssl-1.1-fit/crypto/cms/cms_att.c | 152 + .../openssl-1.1-fit/crypto/cms/cms_cd.c | 82 + .../openssl-1.1-fit/crypto/cms/cms_dd.c | 99 + .../openssl-1.1-fit/crypto/cms/cms_enc.c | 213 + .../openssl-1.1-fit/crypto/cms/cms_env.c | 903 ++ .../openssl-1.1-fit/crypto/cms/cms_err.c | 294 + .../openssl-1.1-fit/crypto/cms/cms_ess.c | 337 + .../openssl-1.1-fit/crypto/cms/cms_io.c | 88 + .../openssl-1.1-fit/crypto/cms/cms_kari.c | 414 + .../openssl-1.1-fit/crypto/cms/cms_lcl.h | 437 + .../openssl-1.1-fit/crypto/cms/cms_lib.c | 587 + .../openssl-1.1-fit/crypto/cms/cms_pwri.c | 394 + .../openssl-1.1-fit/crypto/cms/cms_sd.c | 926 ++ .../openssl-1.1-fit/crypto/cms/cms_smime.c | 843 ++ .../openssl-1.1-fit/crypto/comp/build.info | 4 + .../openssl-1.1-fit/crypto/comp/c_zlib.c | 618 ++ .../openssl-1.1-fit/crypto/comp/comp_err.c | 46 + .../openssl-1.1-fit/crypto/comp/comp_lcl.h | 30 + .../openssl-1.1-fit/crypto/comp/comp_lib.c | 93 + .../openssl-1.1-fit/crypto/conf/build.info | 4 + .../openssl-1.1-fit/crypto/conf/conf_api.c | 218 + .../openssl-1.1-fit/crypto/conf/conf_def.c | 878 ++ .../openssl-1.1-fit/crypto/conf/conf_def.h | 76 + .../openssl-1.1-fit/crypto/conf/conf_err.c | 95 + .../openssl-1.1-fit/crypto/conf/conf_lcl.h | 11 + .../openssl-1.1-fit/crypto/conf/conf_lib.c | 414 + .../openssl-1.1-fit/crypto/conf/conf_mall.c | 31 + .../openssl-1.1-fit/crypto/conf/conf_mod.c | 551 + .../openssl-1.1-fit/crypto/conf/conf_sap.c | 77 + .../openssl-1.1-fit/crypto/conf/conf_ssl.c | 181 + .../openssl-1.1-fit/crypto/conf/keysets.pl | 116 + .../3rdparty/openssl-1.1-fit/crypto/cpt_err.c | 77 + .../openssl-1.1-fit/crypto/cryptlib.c | 473 + .../openssl-1.1-fit/crypto/ct/build.info | 3 + .../openssl-1.1-fit/crypto/ct/ct_b64.c | 168 + .../openssl-1.1-fit/crypto/ct/ct_err.c | 96 + .../openssl-1.1-fit/crypto/ct/ct_locl.h | 216 + .../openssl-1.1-fit/crypto/ct/ct_log.c | 306 + .../openssl-1.1-fit/crypto/ct/ct_oct.c | 407 + .../openssl-1.1-fit/crypto/ct/ct_policy.c | 98 + .../openssl-1.1-fit/crypto/ct/ct_prn.c | 127 + .../openssl-1.1-fit/crypto/ct/ct_sct.c | 396 + .../openssl-1.1-fit/crypto/ct/ct_sct_ctx.c | 263 + .../openssl-1.1-fit/crypto/ct/ct_vfy.c | 140 + .../openssl-1.1-fit/crypto/ct/ct_x509v3.c | 104 + trunk/3rdparty/openssl-1.1-fit/crypto/ctype.c | 274 + .../openssl-1.1-fit/crypto/cversion.c | 44 + .../crypto/des/asm/crypt586.pl | 217 + .../openssl-1.1-fit/crypto/des/asm/des-586.pl | 465 + .../openssl-1.1-fit/crypto/des/asm/des_enc.m4 | 1968 ++++ .../openssl-1.1-fit/crypto/des/asm/desboth.pl | 86 + .../crypto/des/asm/dest4-sparcv9.pl | 627 ++ .../openssl-1.1-fit/crypto/des/build.info | 19 + .../openssl-1.1-fit/crypto/des/cbc_cksm.c | 53 + .../openssl-1.1-fit/crypto/des/cbc_enc.c | 12 + .../openssl-1.1-fit/crypto/des/cfb64ede.c | 189 + .../openssl-1.1-fit/crypto/des/cfb64enc.c | 73 + .../openssl-1.1-fit/crypto/des/cfb_enc.c | 150 + .../openssl-1.1-fit/crypto/des/des_enc.c | 299 + .../openssl-1.1-fit/crypto/des/des_locl.h | 226 + .../openssl-1.1-fit/crypto/des/ecb3_enc.c | 33 + .../openssl-1.1-fit/crypto/des/ecb_enc.c | 48 + .../openssl-1.1-fit/crypto/des/fcrypt.c | 149 + .../openssl-1.1-fit/crypto/des/fcrypt_b.c | 72 + .../openssl-1.1-fit/crypto/des/ncbc_enc.c | 106 + .../openssl-1.1-fit/crypto/des/ofb64ede.c | 62 + .../openssl-1.1-fit/crypto/des/ofb64enc.c | 60 + .../openssl-1.1-fit/crypto/des/ofb_enc.c | 82 + .../openssl-1.1-fit/crypto/des/pcbc_enc.c | 66 + .../openssl-1.1-fit/crypto/des/qud_cksm.c | 76 + .../openssl-1.1-fit/crypto/des/rand_key.c | 21 + .../openssl-1.1-fit/crypto/des/set_key.c | 372 + .../3rdparty/openssl-1.1-fit/crypto/des/spr.h | 163 + .../openssl-1.1-fit/crypto/des/str2key.c | 77 + .../openssl-1.1-fit/crypto/des/xcbc_enc.c | 103 + .../openssl-1.1-fit/crypto/dh/build.info | 5 + .../openssl-1.1-fit/crypto/dh/dh1024.pem | 5 + .../openssl-1.1-fit/crypto/dh/dh192.pem | 3 + .../openssl-1.1-fit/crypto/dh/dh2048.pem | 16 + .../openssl-1.1-fit/crypto/dh/dh4096.pem | 14 + .../openssl-1.1-fit/crypto/dh/dh512.pem | 4 + .../openssl-1.1-fit/crypto/dh/dh_ameth.c | 907 ++ .../openssl-1.1-fit/crypto/dh/dh_asn1.c | 138 + .../openssl-1.1-fit/crypto/dh/dh_check.c | 233 + .../openssl-1.1-fit/crypto/dh/dh_depr.c | 46 + .../openssl-1.1-fit/crypto/dh/dh_err.c | 101 + .../openssl-1.1-fit/crypto/dh/dh_gen.c | 130 + .../openssl-1.1-fit/crypto/dh/dh_kdf.c | 150 + .../openssl-1.1-fit/crypto/dh/dh_key.c | 232 + .../openssl-1.1-fit/crypto/dh/dh_lib.c | 291 + .../openssl-1.1-fit/crypto/dh/dh_locl.h | 57 + .../openssl-1.1-fit/crypto/dh/dh_meth.c | 173 + .../openssl-1.1-fit/crypto/dh/dh_pmeth.c | 547 + .../openssl-1.1-fit/crypto/dh/dh_prn.c | 30 + .../openssl-1.1-fit/crypto/dh/dh_rfc5114.c | 41 + .../openssl-1.1-fit/crypto/dh/dh_rfc7919.c | 74 + .../3rdparty/openssl-1.1-fit/crypto/dllmain.c | 46 + .../openssl-1.1-fit/crypto/dsa/build.info | 5 + .../openssl-1.1-fit/crypto/dsa/dsa_ameth.c | 572 + .../openssl-1.1-fit/crypto/dsa/dsa_asn1.c | 155 + .../openssl-1.1-fit/crypto/dsa/dsa_depr.c | 62 + .../openssl-1.1-fit/crypto/dsa/dsa_err.c | 76 + .../openssl-1.1-fit/crypto/dsa/dsa_gen.c | 616 ++ .../openssl-1.1-fit/crypto/dsa/dsa_key.c | 77 + .../openssl-1.1-fit/crypto/dsa/dsa_lib.c | 358 + .../openssl-1.1-fit/crypto/dsa/dsa_locl.h | 77 + .../openssl-1.1-fit/crypto/dsa/dsa_meth.c | 224 + .../openssl-1.1-fit/crypto/dsa/dsa_ossl.c | 428 + .../openssl-1.1-fit/crypto/dsa/dsa_pmeth.c | 273 + .../openssl-1.1-fit/crypto/dsa/dsa_prn.c | 69 + .../openssl-1.1-fit/crypto/dsa/dsa_sign.c | 24 + .../openssl-1.1-fit/crypto/dsa/dsa_vrf.c | 17 + .../openssl-1.1-fit/crypto/dso/build.info | 4 + .../openssl-1.1-fit/crypto/dso/dso_dl.c | 279 + .../openssl-1.1-fit/crypto/dso/dso_dlfcn.c | 457 + .../openssl-1.1-fit/crypto/dso/dso_err.c | 100 + .../openssl-1.1-fit/crypto/dso/dso_lib.c | 350 + .../openssl-1.1-fit/crypto/dso/dso_locl.h | 107 + .../openssl-1.1-fit/crypto/dso/dso_openssl.c | 22 + .../openssl-1.1-fit/crypto/dso/dso_vms.c | 466 + .../openssl-1.1-fit/crypto/dso/dso_win32.c | 566 + .../3rdparty/openssl-1.1-fit/crypto/ebcdic.c | 361 + .../crypto/ec/asm/ecp_nistz256-armv4.pl | 1865 ++++ .../crypto/ec/asm/ecp_nistz256-armv8.pl | 1883 ++++ .../crypto/ec/asm/ecp_nistz256-avx2.pl | 2080 ++++ .../crypto/ec/asm/ecp_nistz256-ppc64.pl | 2382 ++++ .../crypto/ec/asm/ecp_nistz256-sparcv9.pl | 3061 ++++++ .../crypto/ec/asm/ecp_nistz256-x86.pl | 1866 ++++ .../crypto/ec/asm/ecp_nistz256-x86_64.pl | 4741 ++++++++ .../crypto/ec/asm/x25519-ppc64.pl | 824 ++ .../crypto/ec/asm/x25519-x86_64.pl | 1117 ++ .../openssl-1.1-fit/crypto/ec/build.info | 42 + .../openssl-1.1-fit/crypto/ec/curve25519.c | 5596 ++++++++++ .../ec/curve448/arch_32/arch_intrinsics.h | 27 + .../crypto/ec/curve448/arch_32/f_impl.c | 95 + .../crypto/ec/curve448/arch_32/f_impl.h | 60 + .../crypto/ec/curve448/curve448.c | 727 ++ .../crypto/ec/curve448/curve448_lcl.h | 38 + .../crypto/ec/curve448/curve448_tables.c | 475 + .../crypto/ec/curve448/curve448utils.h | 78 + .../crypto/ec/curve448/ed448.h | 195 + .../crypto/ec/curve448/eddsa.c | 372 + .../crypto/ec/curve448/f_generic.c | 204 + .../crypto/ec/curve448/field.h | 168 + .../crypto/ec/curve448/point_448.h | 301 + .../crypto/ec/curve448/scalar.c | 235 + .../openssl-1.1-fit/crypto/ec/curve448/word.h | 81 + .../openssl-1.1-fit/crypto/ec/ec2_oct.c | 337 + .../openssl-1.1-fit/crypto/ec/ec2_smpl.c | 970 ++ .../openssl-1.1-fit/crypto/ec/ec_ameth.c | 942 ++ .../openssl-1.1-fit/crypto/ec/ec_asn1.c | 1221 +++ .../openssl-1.1-fit/crypto/ec/ec_check.c | 72 + .../openssl-1.1-fit/crypto/ec/ec_curve.c | 3199 ++++++ .../openssl-1.1-fit/crypto/ec/ec_cvt.c | 82 + .../openssl-1.1-fit/crypto/ec/ec_err.c | 394 + .../openssl-1.1-fit/crypto/ec/ec_key.c | 618 ++ .../openssl-1.1-fit/crypto/ec/ec_kmeth.c | 317 + .../openssl-1.1-fit/crypto/ec/ec_lcl.h | 737 ++ .../openssl-1.1-fit/crypto/ec/ec_lib.c | 1121 ++ .../openssl-1.1-fit/crypto/ec/ec_mult.c | 970 ++ .../openssl-1.1-fit/crypto/ec/ec_oct.c | 150 + .../openssl-1.1-fit/crypto/ec/ec_pmeth.c | 472 + .../openssl-1.1-fit/crypto/ec/ec_print.c | 121 + .../openssl-1.1-fit/crypto/ec/ecdh_kdf.c | 81 + .../openssl-1.1-fit/crypto/ec/ecdh_ossl.c | 121 + .../openssl-1.1-fit/crypto/ec/ecdsa_ossl.c | 417 + .../openssl-1.1-fit/crypto/ec/ecdsa_sign.c | 52 + .../openssl-1.1-fit/crypto/ec/ecdsa_vrf.c | 43 + .../openssl-1.1-fit/crypto/ec/eck_prn.c | 259 + .../openssl-1.1-fit/crypto/ec/ecp_mont.c | 291 + .../openssl-1.1-fit/crypto/ec/ecp_nist.c | 168 + .../openssl-1.1-fit/crypto/ec/ecp_nistp224.c | 1716 +++ .../openssl-1.1-fit/crypto/ec/ecp_nistp256.c | 2355 ++++ .../openssl-1.1-fit/crypto/ec/ecp_nistp521.c | 2159 ++++ .../openssl-1.1-fit/crypto/ec/ecp_nistputil.c | 223 + .../openssl-1.1-fit/crypto/ec/ecp_nistz256.c | 1701 +++ .../crypto/ec/ecp_nistz256_table.c | 9542 +++++++++++++++++ .../openssl-1.1-fit/crypto/ec/ecp_oct.c | 366 + .../openssl-1.1-fit/crypto/ec/ecp_smpl.c | 1689 +++ .../openssl-1.1-fit/crypto/ec/ecx_meth.c | 841 ++ .../openssl-1.1-fit/crypto/engine/README | 211 + .../openssl-1.1-fit/crypto/engine/build.info | 11 + .../openssl-1.1-fit/crypto/engine/eng_all.c | 25 + .../openssl-1.1-fit/crypto/engine/eng_cnf.c | 192 + .../openssl-1.1-fit/crypto/engine/eng_ctrl.c | 330 + .../crypto/engine/eng_devcrypto.c | 836 ++ .../openssl-1.1-fit/crypto/engine/eng_dyn.c | 510 + .../openssl-1.1-fit/crypto/engine/eng_err.c | 154 + .../openssl-1.1-fit/crypto/engine/eng_fat.c | 123 + .../openssl-1.1-fit/crypto/engine/eng_init.c | 109 + .../openssl-1.1-fit/crypto/engine/eng_int.h | 171 + .../openssl-1.1-fit/crypto/engine/eng_lib.c | 299 + .../openssl-1.1-fit/crypto/engine/eng_list.c | 349 + .../crypto/engine/eng_openssl.c | 648 ++ .../openssl-1.1-fit/crypto/engine/eng_pkey.c | 140 + .../crypto/engine/eng_rdrand.c | 97 + .../openssl-1.1-fit/crypto/engine/eng_table.c | 308 + .../openssl-1.1-fit/crypto/engine/tb_asnmth.c | 209 + .../openssl-1.1-fit/crypto/engine/tb_cipher.c | 91 + .../openssl-1.1-fit/crypto/engine/tb_dh.c | 72 + .../openssl-1.1-fit/crypto/engine/tb_digest.c | 91 + .../openssl-1.1-fit/crypto/engine/tb_dsa.c | 72 + .../openssl-1.1-fit/crypto/engine/tb_eckey.c | 72 + .../openssl-1.1-fit/crypto/engine/tb_pkmeth.c | 114 + .../openssl-1.1-fit/crypto/engine/tb_rand.c | 72 + .../openssl-1.1-fit/crypto/engine/tb_rsa.c | 72 + .../openssl-1.1-fit/crypto/err/README | 44 + .../openssl-1.1-fit/crypto/err/build.info | 3 + .../3rdparty/openssl-1.1-fit/crypto/err/err.c | 953 ++ .../openssl-1.1-fit/crypto/err/err_all.c | 101 + .../openssl-1.1-fit/crypto/err/err_prn.c | 65 + .../openssl-1.1-fit/crypto/err/openssl.ec | 78 + .../openssl-1.1-fit/crypto/err/openssl.txt | 3033 ++++++ .../openssl-1.1-fit/crypto/evp/bio_b64.c | 553 + .../openssl-1.1-fit/crypto/evp/bio_enc.c | 429 + .../openssl-1.1-fit/crypto/evp/bio_md.c | 233 + .../openssl-1.1-fit/crypto/evp/bio_ok.c | 610 ++ .../openssl-1.1-fit/crypto/evp/build.info | 25 + .../openssl-1.1-fit/crypto/evp/c_allc.c | 266 + .../openssl-1.1-fit/crypto/evp/c_alld.c | 60 + .../openssl-1.1-fit/crypto/evp/cmeth_lib.c | 151 + .../openssl-1.1-fit/crypto/evp/digest.c | 298 + .../openssl-1.1-fit/crypto/evp/e_aes.c | 4210 ++++++++ .../crypto/evp/e_aes_cbc_hmac_sha1.c | 964 ++ .../crypto/evp/e_aes_cbc_hmac_sha256.c | 950 ++ .../openssl-1.1-fit/crypto/evp/e_aria.c | 756 ++ .../openssl-1.1-fit/crypto/evp/e_bf.c | 38 + .../openssl-1.1-fit/crypto/evp/e_camellia.c | 366 + .../openssl-1.1-fit/crypto/evp/e_cast.c | 40 + .../crypto/evp/e_chacha20_poly1305.c | 630 ++ .../openssl-1.1-fit/crypto/evp/e_des.c | 242 + .../openssl-1.1-fit/crypto/evp/e_des3.c | 424 + .../openssl-1.1-fit/crypto/evp/e_idea.c | 70 + .../openssl-1.1-fit/crypto/evp/e_null.c | 50 + .../openssl-1.1-fit/crypto/evp/e_old.c | 113 + .../openssl-1.1-fit/crypto/evp/e_rc2.c | 191 + .../openssl-1.1-fit/crypto/evp/e_rc4.c | 82 + .../crypto/evp/e_rc4_hmac_md5.c | 262 + .../openssl-1.1-fit/crypto/evp/e_rc5.c | 74 + .../openssl-1.1-fit/crypto/evp/e_seed.c | 39 + .../openssl-1.1-fit/crypto/evp/e_sm4.c | 100 + .../openssl-1.1-fit/crypto/evp/e_xcbc_d.c | 83 + .../openssl-1.1-fit/crypto/evp/encode.c | 478 + .../openssl-1.1-fit/crypto/evp/evp_cnf.c | 56 + .../openssl-1.1-fit/crypto/evp/evp_enc.c | 677 ++ .../openssl-1.1-fit/crypto/evp/evp_err.c | 283 + .../openssl-1.1-fit/crypto/evp/evp_key.c | 150 + .../openssl-1.1-fit/crypto/evp/evp_lib.c | 528 + .../openssl-1.1-fit/crypto/evp/evp_locl.h | 68 + .../openssl-1.1-fit/crypto/evp/evp_pbe.c | 262 + .../openssl-1.1-fit/crypto/evp/evp_pkey.c | 149 + .../openssl-1.1-fit/crypto/evp/m_md2.c | 56 + .../openssl-1.1-fit/crypto/evp/m_md4.c | 55 + .../openssl-1.1-fit/crypto/evp/m_md5.c | 55 + .../openssl-1.1-fit/crypto/evp/m_md5_sha1.c | 142 + .../openssl-1.1-fit/crypto/evp/m_mdc2.c | 55 + .../openssl-1.1-fit/crypto/evp/m_null.c | 49 + .../openssl-1.1-fit/crypto/evp/m_ripemd.c | 55 + .../openssl-1.1-fit/crypto/evp/m_sha1.c | 297 + .../openssl-1.1-fit/crypto/evp/m_sha3.c | 406 + .../openssl-1.1-fit/crypto/evp/m_sigver.c | 218 + .../openssl-1.1-fit/crypto/evp/m_wp.c | 54 + .../openssl-1.1-fit/crypto/evp/names.c | 180 + .../openssl-1.1-fit/crypto/evp/p5_crpt.c | 103 + .../openssl-1.1-fit/crypto/evp/p5_crpt2.c | 265 + .../openssl-1.1-fit/crypto/evp/p_dec.c | 36 + .../openssl-1.1-fit/crypto/evp/p_enc.c | 35 + .../openssl-1.1-fit/crypto/evp/p_lib.c | 686 ++ .../openssl-1.1-fit/crypto/evp/p_open.c | 73 + .../openssl-1.1-fit/crypto/evp/p_seal.c | 65 + .../openssl-1.1-fit/crypto/evp/p_sign.c | 61 + .../openssl-1.1-fit/crypto/evp/p_verify.c | 55 + .../openssl-1.1-fit/crypto/evp/pbe_scrypt.c | 266 + .../openssl-1.1-fit/crypto/evp/pmeth_fn.c | 297 + .../openssl-1.1-fit/crypto/evp/pmeth_gn.c | 239 + .../openssl-1.1-fit/crypto/evp/pmeth_lib.c | 864 ++ .../3rdparty/openssl-1.1-fit/crypto/ex_data.c | 399 + .../3rdparty/openssl-1.1-fit/crypto/getenv.c | 31 + .../openssl-1.1-fit/crypto/hmac/build.info | 3 + .../openssl-1.1-fit/crypto/hmac/hm_ameth.c | 127 + .../openssl-1.1-fit/crypto/hmac/hm_pmeth.c | 212 + .../openssl-1.1-fit/crypto/hmac/hmac.c | 247 + .../openssl-1.1-fit/crypto/hmac/hmac_lcl.h | 25 + .../openssl-1.1-fit/crypto/ia64cpuid.S | 297 + .../openssl-1.1-fit/crypto/idea/build.info | 3 + .../openssl-1.1-fit/crypto/idea/i_cbc.c | 122 + .../openssl-1.1-fit/crypto/idea/i_cfb64.c | 74 + .../openssl-1.1-fit/crypto/idea/i_ecb.c | 34 + .../openssl-1.1-fit/crypto/idea/i_ofb64.c | 61 + .../openssl-1.1-fit/crypto/idea/i_skey.c | 112 + .../openssl-1.1-fit/crypto/idea/idea_lcl.h | 102 + .../internal/__DECC_INCLUDE_EPILOGUE.H | 16 + .../internal/__DECC_INCLUDE_PROLOGUE.H | 20 + .../crypto/include/internal/aria.h | 50 + .../crypto/include/internal/asn1_int.h | 113 + .../crypto/include/internal/async.h | 15 + .../crypto/include/internal/bn_conf.h.in | 27 + .../crypto/include/internal/bn_dh.h | 24 + .../crypto/include/internal/bn_int.h | 90 + .../crypto/include/internal/bn_srp.h | 32 + .../crypto/include/internal/chacha.h | 42 + .../crypto/include/internal/cryptlib_int.h | 35 + .../crypto/include/internal/ctype.h | 80 + .../crypto/include/internal/dso_conf.h.in | 30 + .../crypto/include/internal/ec_int.h | 53 + .../crypto/include/internal/engine.h | 20 + .../crypto/include/internal/err_int.h | 19 + .../crypto/include/internal/evp_int.h | 442 + .../crypto/include/internal/lhash.h | 15 + .../crypto/include/internal/md32_common.h | 256 + .../crypto/include/internal/objects.h | 12 + .../crypto/include/internal/poly1305.h | 21 + .../crypto/include/internal/rand_int.h | 134 + .../crypto/include/internal/sha.h | 19 + .../crypto/include/internal/siphash.h | 25 + .../crypto/include/internal/sm2.h | 78 + .../crypto/include/internal/sm2err.h | 61 + .../crypto/include/internal/sm3.h | 39 + .../crypto/include/internal/sm4.h | 37 + .../crypto/include/internal/store.h | 10 + .../crypto/include/internal/store_int.h | 26 + .../crypto/include/internal/x509_int.h | 286 + trunk/3rdparty/openssl-1.1-fit/crypto/init.c | 854 ++ .../openssl-1.1-fit/crypto/kdf/build.info | 3 + .../openssl-1.1-fit/crypto/kdf/hkdf.c | 352 + .../openssl-1.1-fit/crypto/kdf/kdf_err.c | 67 + .../openssl-1.1-fit/crypto/kdf/scrypt.c | 266 + .../openssl-1.1-fit/crypto/kdf/tls1_prf.c | 278 + .../openssl-1.1-fit/crypto/lhash/build.info | 3 + .../openssl-1.1-fit/crypto/lhash/lh_stats.c | 117 + .../openssl-1.1-fit/crypto/lhash/lhash.c | 393 + .../openssl-1.1-fit/crypto/lhash/lhash_lcl.h | 44 + .../openssl-1.1-fit/crypto/md2/build.info | 3 + .../openssl-1.1-fit/crypto/md2/md2_dgst.c | 173 + .../openssl-1.1-fit/crypto/md2/md2_one.c | 47 + .../openssl-1.1-fit/crypto/md4/build.info | 3 + .../openssl-1.1-fit/crypto/md4/md4_dgst.c | 147 + .../openssl-1.1-fit/crypto/md4/md4_locl.h | 60 + .../openssl-1.1-fit/crypto/md4/md4_one.c | 47 + .../openssl-1.1-fit/crypto/md5/asm/md5-586.pl | 318 + .../crypto/md5/asm/md5-sparcv9.pl | 437 + .../crypto/md5/asm/md5-x86_64.pl | 393 + .../openssl-1.1-fit/crypto/md5/build.info | 11 + .../openssl-1.1-fit/crypto/md5/md5_dgst.c | 164 + .../openssl-1.1-fit/crypto/md5/md5_locl.h | 80 + .../openssl-1.1-fit/crypto/md5/md5_one.c | 47 + .../openssl-1.1-fit/crypto/mdc2/build.info | 3 + .../openssl-1.1-fit/crypto/mdc2/mdc2_one.c | 27 + .../openssl-1.1-fit/crypto/mdc2/mdc2dgst.c | 126 + trunk/3rdparty/openssl-1.1-fit/crypto/mem.c | 323 + .../3rdparty/openssl-1.1-fit/crypto/mem_clr.c | 25 + .../3rdparty/openssl-1.1-fit/crypto/mem_dbg.c | 670 ++ .../3rdparty/openssl-1.1-fit/crypto/mem_sec.c | 646 ++ .../openssl-1.1-fit/crypto/mips_arch.h | 40 + .../crypto/modes/asm/aesni-gcm-x86_64.pl | 1099 ++ .../crypto/modes/asm/ghash-alpha.pl | 467 + .../crypto/modes/asm/ghash-armv4.pl | 551 + .../crypto/modes/asm/ghash-c64xplus.pl | 247 + .../crypto/modes/asm/ghash-ia64.pl | 470 + .../crypto/modes/asm/ghash-parisc.pl | 748 ++ .../crypto/modes/asm/ghash-s390x.pl | 262 + .../crypto/modes/asm/ghash-sparcv9.pl | 581 + .../crypto/modes/asm/ghash-x86.pl | 1404 +++ .../crypto/modes/asm/ghash-x86_64.pl | 1816 ++++ .../crypto/modes/asm/ghashp8-ppc.pl | 671 ++ .../crypto/modes/asm/ghashv8-armx.pl | 781 ++ .../openssl-1.1-fit/crypto/modes/build.info | 30 + .../openssl-1.1-fit/crypto/modes/cbc128.c | 161 + .../openssl-1.1-fit/crypto/modes/ccm128.c | 432 + .../openssl-1.1-fit/crypto/modes/cfb128.c | 198 + .../openssl-1.1-fit/crypto/modes/ctr128.c | 209 + .../openssl-1.1-fit/crypto/modes/cts128.c | 330 + .../openssl-1.1-fit/crypto/modes/gcm128.c | 1888 ++++ .../openssl-1.1-fit/crypto/modes/modes_lcl.h | 190 + .../openssl-1.1-fit/crypto/modes/ocb128.c | 562 + .../openssl-1.1-fit/crypto/modes/ofb128.c | 74 + .../openssl-1.1-fit/crypto/modes/wrap128.c | 331 + .../openssl-1.1-fit/crypto/modes/xts128.c | 157 + trunk/3rdparty/openssl-1.1-fit/crypto/o_dir.c | 37 + .../3rdparty/openssl-1.1-fit/crypto/o_fips.c | 24 + .../3rdparty/openssl-1.1-fit/crypto/o_fopen.c | 126 + .../3rdparty/openssl-1.1-fit/crypto/o_init.c | 21 + trunk/3rdparty/openssl-1.1-fit/crypto/o_str.c | 248 + .../3rdparty/openssl-1.1-fit/crypto/o_time.c | 200 + .../openssl-1.1-fit/crypto/objects/README | 44 + .../openssl-1.1-fit/crypto/objects/build.info | 3 + .../openssl-1.1-fit/crypto/objects/o_names.c | 406 + .../openssl-1.1-fit/crypto/objects/obj_dat.c | 739 ++ .../openssl-1.1-fit/crypto/objects/obj_dat.h | 5733 ++++++++++ .../openssl-1.1-fit/crypto/objects/obj_dat.pl | 228 + .../openssl-1.1-fit/crypto/objects/obj_err.c | 46 + .../openssl-1.1-fit/crypto/objects/obj_lcl.h | 14 + .../openssl-1.1-fit/crypto/objects/obj_lib.c | 65 + .../crypto/objects/obj_mac.num | 1194 +++ .../openssl-1.1-fit/crypto/objects/obj_xref.c | 139 + .../openssl-1.1-fit/crypto/objects/obj_xref.h | 128 + .../crypto/objects/obj_xref.txt | 66 + .../openssl-1.1-fit/crypto/objects/objects.pl | 203 + .../crypto/objects/objects.txt | 1677 +++ .../openssl-1.1-fit/crypto/objects/objxref.pl | 142 + .../openssl-1.1-fit/crypto/ocsp/build.info | 4 + .../openssl-1.1-fit/crypto/ocsp/ocsp_asn.c | 135 + .../openssl-1.1-fit/crypto/ocsp/ocsp_cl.c | 396 + .../openssl-1.1-fit/crypto/ocsp/ocsp_err.c | 101 + .../openssl-1.1-fit/crypto/ocsp/ocsp_ext.c | 472 + .../openssl-1.1-fit/crypto/ocsp/ocsp_ht.c | 502 + .../openssl-1.1-fit/crypto/ocsp/ocsp_lcl.h | 236 + .../openssl-1.1-fit/crypto/ocsp/ocsp_lib.c | 222 + .../openssl-1.1-fit/crypto/ocsp/ocsp_prn.c | 246 + .../openssl-1.1-fit/crypto/ocsp/ocsp_srv.c | 310 + .../openssl-1.1-fit/crypto/ocsp/ocsp_vfy.c | 435 + .../openssl-1.1-fit/crypto/ocsp/v3_ocsp.c | 264 + .../openssl-1.1-fit/crypto/pariscid.pl | 276 + .../openssl-1.1-fit/crypto/pem/build.info | 4 + .../openssl-1.1-fit/crypto/pem/pem_all.c | 181 + .../openssl-1.1-fit/crypto/pem/pem_err.c | 126 + .../openssl-1.1-fit/crypto/pem/pem_info.c | 337 + .../openssl-1.1-fit/crypto/pem/pem_lib.c | 988 ++ .../openssl-1.1-fit/crypto/pem/pem_oth.c | 36 + .../openssl-1.1-fit/crypto/pem/pem_pk8.c | 214 + .../openssl-1.1-fit/crypto/pem/pem_pkey.c | 245 + .../openssl-1.1-fit/crypto/pem/pem_sign.c | 50 + .../openssl-1.1-fit/crypto/pem/pem_x509.c | 18 + .../openssl-1.1-fit/crypto/pem/pem_xaux.c | 18 + .../openssl-1.1-fit/crypto/pem/pvkfmt.c | 883 ++ .../openssl-1.1-fit/crypto/perlasm/README | 124 + .../crypto/perlasm/arm-xlate.pl | 177 + .../openssl-1.1-fit/crypto/perlasm/cbc.pl | 356 + .../crypto/perlasm/ppc-xlate.pl | 344 + .../crypto/perlasm/sparcv9_modes.pl | 1702 +++ .../crypto/perlasm/x86_64-xlate.pl | 1447 +++ .../openssl-1.1-fit/crypto/perlasm/x86asm.pl | 303 + .../openssl-1.1-fit/crypto/perlasm/x86gas.pl | 265 + .../openssl-1.1-fit/crypto/perlasm/x86masm.pl | 206 + .../openssl-1.1-fit/crypto/perlasm/x86nasm.pl | 186 + .../openssl-1.1-fit/crypto/pkcs12/build.info | 5 + .../openssl-1.1-fit/crypto/pkcs12/p12_add.c | 164 + .../openssl-1.1-fit/crypto/pkcs12/p12_asn.c | 76 + .../openssl-1.1-fit/crypto/pkcs12/p12_attr.c | 103 + .../openssl-1.1-fit/crypto/pkcs12/p12_crpt.c | 70 + .../openssl-1.1-fit/crypto/pkcs12/p12_crt.c | 291 + .../openssl-1.1-fit/crypto/pkcs12/p12_decr.c | 155 + .../openssl-1.1-fit/crypto/pkcs12/p12_init.c | 44 + .../openssl-1.1-fit/crypto/pkcs12/p12_key.c | 183 + .../openssl-1.1-fit/crypto/pkcs12/p12_kiss.c | 250 + .../openssl-1.1-fit/crypto/pkcs12/p12_lcl.h | 43 + .../openssl-1.1-fit/crypto/pkcs12/p12_mutl.c | 246 + .../openssl-1.1-fit/crypto/pkcs12/p12_npas.c | 184 + .../openssl-1.1-fit/crypto/pkcs12/p12_p8d.c | 23 + .../openssl-1.1-fit/crypto/pkcs12/p12_p8e.c | 69 + .../openssl-1.1-fit/crypto/pkcs12/p12_sbag.c | 162 + .../openssl-1.1-fit/crypto/pkcs12/p12_utl.c | 244 + .../openssl-1.1-fit/crypto/pkcs12/pk12err.c | 117 + .../openssl-1.1-fit/crypto/pkcs7/bio_pk7.c | 24 + .../openssl-1.1-fit/crypto/pkcs7/build.info | 4 + .../openssl-1.1-fit/crypto/pkcs7/pk7_asn1.c | 202 + .../openssl-1.1-fit/crypto/pkcs7/pk7_attr.c | 121 + .../openssl-1.1-fit/crypto/pkcs7/pk7_doit.c | 1180 ++ .../openssl-1.1-fit/crypto/pkcs7/pk7_lib.c | 588 + .../openssl-1.1-fit/crypto/pkcs7/pk7_mime.c | 48 + .../openssl-1.1-fit/crypto/pkcs7/pk7_smime.c | 549 + .../openssl-1.1-fit/crypto/pkcs7/pkcs7err.c | 156 + .../crypto/poly1305/asm/poly1305-armv4.pl | 1253 +++ .../crypto/poly1305/asm/poly1305-armv8.pl | 946 ++ .../crypto/poly1305/asm/poly1305-c64xplus.pl | 331 + .../crypto/poly1305/asm/poly1305-mips.pl | 437 + .../crypto/poly1305/asm/poly1305-ppc.pl | 645 ++ .../crypto/poly1305/asm/poly1305-ppcfp.pl | 739 ++ .../crypto/poly1305/asm/poly1305-s390x.pl | 227 + .../crypto/poly1305/asm/poly1305-sparcv9.pl | 1120 ++ .../crypto/poly1305/asm/poly1305-x86.pl | 1815 ++++ .../crypto/poly1305/asm/poly1305-x86_64.pl | 4159 +++++++ .../crypto/poly1305/build.info | 24 + .../crypto/poly1305/poly1305.c | 531 + .../crypto/poly1305/poly1305_ameth.c | 122 + .../crypto/poly1305/poly1305_base2_44.c | 171 + .../crypto/poly1305/poly1305_ieee754.c | 488 + .../crypto/poly1305/poly1305_local.h | 27 + .../crypto/poly1305/poly1305_pmeth.c | 194 + .../openssl-1.1-fit/crypto/ppc_arch.h | 28 + .../3rdparty/openssl-1.1-fit/crypto/ppccap.c | 408 + .../openssl-1.1-fit/crypto/ppccpuid.pl | 382 + .../openssl-1.1-fit/crypto/rand/build.info | 4 + .../openssl-1.1-fit/crypto/rand/drbg_ctr.c | 438 + .../openssl-1.1-fit/crypto/rand/drbg_lib.c | 1159 ++ .../openssl-1.1-fit/crypto/rand/rand_egd.c | 158 + .../openssl-1.1-fit/crypto/rand/rand_err.c | 135 + .../openssl-1.1-fit/crypto/rand/rand_lcl.h | 293 + .../openssl-1.1-fit/crypto/rand/rand_lib.c | 859 ++ .../openssl-1.1-fit/crypto/rand/rand_unix.c | 707 ++ .../openssl-1.1-fit/crypto/rand/rand_vms.c | 528 + .../openssl-1.1-fit/crypto/rand/rand_win.c | 185 + .../openssl-1.1-fit/crypto/rand/randfile.c | 314 + .../openssl-1.1-fit/crypto/rc2/build.info | 3 + .../openssl-1.1-fit/crypto/rc2/rc2_cbc.c | 179 + .../openssl-1.1-fit/crypto/rc2/rc2_ecb.c | 40 + .../openssl-1.1-fit/crypto/rc2/rc2_locl.h | 134 + .../openssl-1.1-fit/crypto/rc2/rc2_skey.c | 98 + .../openssl-1.1-fit/crypto/rc2/rc2cfb64.c | 74 + .../openssl-1.1-fit/crypto/rc2/rc2ofb64.c | 61 + .../openssl-1.1-fit/crypto/rc4/asm/rc4-586.pl | 426 + .../crypto/rc4/asm/rc4-c64xplus.pl | 192 + .../crypto/rc4/asm/rc4-md5-x86_64.pl | 661 ++ .../crypto/rc4/asm/rc4-parisc.pl | 333 + .../crypto/rc4/asm/rc4-s390x.pl | 241 + .../crypto/rc4/asm/rc4-x86_64.pl | 696 ++ .../openssl-1.1-fit/crypto/rc4/build.info | 18 + .../openssl-1.1-fit/crypto/rc4/rc4_enc.c | 85 + .../openssl-1.1-fit/crypto/rc4/rc4_locl.h | 16 + .../openssl-1.1-fit/crypto/rc4/rc4_skey.c | 57 + .../openssl-1.1-fit/crypto/rc5/asm/rc5-586.pl | 122 + .../openssl-1.1-fit/crypto/rc5/build.info | 7 + .../openssl-1.1-fit/crypto/rc5/rc5_ecb.c | 32 + .../openssl-1.1-fit/crypto/rc5/rc5_enc.c | 160 + .../openssl-1.1-fit/crypto/rc5/rc5_locl.h | 186 + .../openssl-1.1-fit/crypto/rc5/rc5_skey.c | 61 + .../openssl-1.1-fit/crypto/rc5/rc5cfb64.c | 74 + .../openssl-1.1-fit/crypto/rc5/rc5ofb64.c | 61 + .../crypto/ripemd/asm/rmd-586.pl | 602 ++ .../openssl-1.1-fit/crypto/ripemd/build.info | 7 + .../openssl-1.1-fit/crypto/ripemd/rmd_dgst.c | 282 + .../openssl-1.1-fit/crypto/ripemd/rmd_locl.h | 87 + .../openssl-1.1-fit/crypto/ripemd/rmd_one.c | 28 + .../openssl-1.1-fit/crypto/ripemd/rmdconst.h | 350 + .../openssl-1.1-fit/crypto/rsa/build.info | 6 + .../openssl-1.1-fit/crypto/rsa/rsa_ameth.c | 1105 ++ .../openssl-1.1-fit/crypto/rsa/rsa_asn1.c | 121 + .../openssl-1.1-fit/crypto/rsa/rsa_chk.c | 228 + .../openssl-1.1-fit/crypto/rsa/rsa_crpt.c | 169 + .../openssl-1.1-fit/crypto/rsa/rsa_depr.c | 61 + .../openssl-1.1-fit/crypto/rsa/rsa_err.c | 246 + .../openssl-1.1-fit/crypto/rsa/rsa_gen.c | 394 + .../openssl-1.1-fit/crypto/rsa/rsa_lib.c | 479 + .../openssl-1.1-fit/crypto/rsa/rsa_locl.h | 132 + .../openssl-1.1-fit/crypto/rsa/rsa_meth.c | 287 + .../openssl-1.1-fit/crypto/rsa/rsa_mp.c | 115 + .../openssl-1.1-fit/crypto/rsa/rsa_none.c | 43 + .../openssl-1.1-fit/crypto/rsa/rsa_oaep.c | 313 + .../openssl-1.1-fit/crypto/rsa/rsa_ossl.c | 970 ++ .../openssl-1.1-fit/crypto/rsa/rsa_pk1.c | 255 + .../openssl-1.1-fit/crypto/rsa/rsa_pmeth.c | 860 ++ .../openssl-1.1-fit/crypto/rsa/rsa_prn.c | 42 + .../openssl-1.1-fit/crypto/rsa/rsa_pss.c | 255 + .../openssl-1.1-fit/crypto/rsa/rsa_saos.c | 95 + .../openssl-1.1-fit/crypto/rsa/rsa_sign.c | 248 + .../openssl-1.1-fit/crypto/rsa/rsa_ssl.c | 167 + .../openssl-1.1-fit/crypto/rsa/rsa_x931.c | 117 + .../openssl-1.1-fit/crypto/rsa/rsa_x931g.c | 200 + .../openssl-1.1-fit/crypto/s390x_arch.h | 103 + .../openssl-1.1-fit/crypto/s390xcap.c | 67 + .../openssl-1.1-fit/crypto/s390xcpuid.pl | 421 + .../openssl-1.1-fit/crypto/seed/build.info | 2 + .../openssl-1.1-fit/crypto/seed/seed.c | 590 + .../openssl-1.1-fit/crypto/seed/seed_cbc.c | 23 + .../openssl-1.1-fit/crypto/seed/seed_cfb.c | 20 + .../openssl-1.1-fit/crypto/seed/seed_ecb.c | 19 + .../openssl-1.1-fit/crypto/seed/seed_locl.h | 112 + .../openssl-1.1-fit/crypto/seed/seed_ofb.c | 19 + .../crypto/sha/asm/keccak1600-armv4.pl | 1606 +++ .../crypto/sha/asm/keccak1600-armv8.pl | 880 ++ .../crypto/sha/asm/keccak1600-avx2.pl | 482 + .../crypto/sha/asm/keccak1600-avx512.pl | 551 + .../crypto/sha/asm/keccak1600-avx512vl.pl | 392 + .../crypto/sha/asm/keccak1600-c64x.pl | 885 ++ .../crypto/sha/asm/keccak1600-mmx.pl | 440 + .../crypto/sha/asm/keccak1600-ppc64.pl | 758 ++ .../crypto/sha/asm/keccak1600-s390x.pl | 560 + .../crypto/sha/asm/keccak1600-x86_64.pl | 607 ++ .../crypto/sha/asm/keccak1600p8-ppc.pl | 850 ++ .../crypto/sha/asm/sha1-586.pl | 1491 +++ .../crypto/sha/asm/sha1-alpha.pl | 329 + .../crypto/sha/asm/sha1-armv4-large.pl | 742 ++ .../crypto/sha/asm/sha1-armv8.pl | 364 + .../crypto/sha/asm/sha1-c64xplus.pl | 337 + .../crypto/sha/asm/sha1-ia64.pl | 314 + .../crypto/sha/asm/sha1-mb-x86_64.pl | 1628 +++ .../crypto/sha/asm/sha1-mips.pl | 461 + .../crypto/sha/asm/sha1-parisc.pl | 279 + .../crypto/sha/asm/sha1-ppc.pl | 351 + .../crypto/sha/asm/sha1-s390x.pl | 249 + .../crypto/sha/asm/sha1-sparcv9.pl | 434 + .../crypto/sha/asm/sha1-sparcv9a.pl | 608 ++ .../crypto/sha/asm/sha1-thumb.pl | 266 + .../crypto/sha/asm/sha1-x86_64.pl | 2132 ++++ .../crypto/sha/asm/sha256-586.pl | 1296 +++ .../crypto/sha/asm/sha256-armv4.pl | 732 ++ .../crypto/sha/asm/sha256-c64xplus.pl | 320 + .../crypto/sha/asm/sha256-mb-x86_64.pl | 1614 +++ .../crypto/sha/asm/sha512-586.pl | 925 ++ .../crypto/sha/asm/sha512-armv4.pl | 668 ++ .../crypto/sha/asm/sha512-armv8.pl | 905 ++ .../crypto/sha/asm/sha512-c64xplus.pl | 438 + .../crypto/sha/asm/sha512-ia64.pl | 692 ++ .../crypto/sha/asm/sha512-mips.pl | 521 + .../crypto/sha/asm/sha512-parisc.pl | 807 ++ .../crypto/sha/asm/sha512-ppc.pl | 799 ++ .../crypto/sha/asm/sha512-s390x.pl | 324 + .../crypto/sha/asm/sha512-sparcv9.pl | 857 ++ .../crypto/sha/asm/sha512-x86_64.pl | 2498 +++++ .../crypto/sha/asm/sha512p8-ppc.pl | 420 + .../openssl-1.1-fit/crypto/sha/build.info | 89 + .../openssl-1.1-fit/crypto/sha/keccak1600.c | 1246 +++ .../openssl-1.1-fit/crypto/sha/sha1_one.c | 28 + .../openssl-1.1-fit/crypto/sha/sha1dgst.c | 17 + .../openssl-1.1-fit/crypto/sha/sha256.c | 386 + .../openssl-1.1-fit/crypto/sha/sha512.c | 765 ++ .../openssl-1.1-fit/crypto/sha/sha_locl.h | 424 + .../openssl-1.1-fit/crypto/siphash/build.info | 5 + .../openssl-1.1-fit/crypto/siphash/siphash.c | 260 + .../crypto/siphash/siphash_ameth.c | 123 + .../crypto/siphash/siphash_local.h | 23 + .../crypto/siphash/siphash_pmeth.c | 205 + .../openssl-1.1-fit/crypto/sm2/build.info | 5 + .../openssl-1.1-fit/crypto/sm2/sm2_crypt.c | 393 + .../openssl-1.1-fit/crypto/sm2/sm2_err.c | 69 + .../openssl-1.1-fit/crypto/sm2/sm2_pmeth.c | 325 + .../openssl-1.1-fit/crypto/sm2/sm2_sign.c | 479 + .../openssl-1.1-fit/crypto/sm3/build.info | 2 + .../openssl-1.1-fit/crypto/sm3/m_sm3.c | 52 + .../3rdparty/openssl-1.1-fit/crypto/sm3/sm3.c | 196 + .../openssl-1.1-fit/crypto/sm3/sm3_locl.h | 79 + .../openssl-1.1-fit/crypto/sm4/build.info | 4 + .../3rdparty/openssl-1.1-fit/crypto/sm4/sm4.c | 233 + .../openssl-1.1-fit/crypto/sparc_arch.h | 118 + .../openssl-1.1-fit/crypto/sparccpuid.S | 578 + .../openssl-1.1-fit/crypto/sparcv9cap.c | 295 + .../openssl-1.1-fit/crypto/srp/build.info | 2 + .../openssl-1.1-fit/crypto/srp/srp_lib.c | 286 + .../openssl-1.1-fit/crypto/srp/srp_vfy.c | 730 ++ .../openssl-1.1-fit/crypto/stack/build.info | 2 + .../openssl-1.1-fit/crypto/stack/stack.c | 413 + .../openssl-1.1-fit/crypto/store/build.info | 4 + .../crypto/store/loader_file.c | 1440 +++ .../openssl-1.1-fit/crypto/store/store_err.c | 146 + .../openssl-1.1-fit/crypto/store/store_init.c | 33 + .../openssl-1.1-fit/crypto/store/store_lib.c | 681 ++ .../openssl-1.1-fit/crypto/store/store_locl.h | 132 + .../crypto/store/store_register.c | 297 + .../crypto/store/store_strings.c | 28 + .../openssl-1.1-fit/crypto/threads_none.c | 136 + .../openssl-1.1-fit/crypto/threads_pthread.c | 196 + .../openssl-1.1-fit/crypto/threads_win.c | 163 + .../openssl-1.1-fit/crypto/ts/build.info | 5 + .../openssl-1.1-fit/crypto/ts/ts_asn1.c | 276 + .../openssl-1.1-fit/crypto/ts/ts_conf.c | 493 + .../openssl-1.1-fit/crypto/ts/ts_err.c | 184 + .../openssl-1.1-fit/crypto/ts/ts_lcl.h | 211 + .../openssl-1.1-fit/crypto/ts/ts_lib.c | 92 + .../openssl-1.1-fit/crypto/ts/ts_req_print.c | 51 + .../openssl-1.1-fit/crypto/ts/ts_req_utils.c | 183 + .../openssl-1.1-fit/crypto/ts/ts_rsp_print.c | 195 + .../openssl-1.1-fit/crypto/ts/ts_rsp_sign.c | 1057 ++ .../openssl-1.1-fit/crypto/ts/ts_rsp_utils.c | 365 + .../openssl-1.1-fit/crypto/ts/ts_rsp_verify.c | 704 ++ .../openssl-1.1-fit/crypto/ts/ts_verify_ctx.c | 146 + .../openssl-1.1-fit/crypto/txt_db/build.info | 2 + .../openssl-1.1-fit/crypto/txt_db/txt_db.c | 317 + .../openssl-1.1-fit/crypto/ui/build.info | 3 + .../openssl-1.1-fit/crypto/ui/ui_err.c | 78 + .../openssl-1.1-fit/crypto/ui/ui_lib.c | 954 ++ .../openssl-1.1-fit/crypto/ui/ui_locl.h | 109 + .../openssl-1.1-fit/crypto/ui/ui_null.c | 26 + .../openssl-1.1-fit/crypto/ui/ui_openssl.c | 744 ++ .../openssl-1.1-fit/crypto/ui/ui_util.c | 162 + trunk/3rdparty/openssl-1.1-fit/crypto/uid.c | 49 + .../3rdparty/openssl-1.1-fit/crypto/vms_rms.h | 58 + .../crypto/whrlpool/asm/wp-mmx.pl | 507 + .../crypto/whrlpool/asm/wp-x86_64.pl | 617 ++ .../crypto/whrlpool/build.info | 8 + .../crypto/whrlpool/wp_block.c | 784 ++ .../openssl-1.1-fit/crypto/whrlpool/wp_dgst.c | 258 + .../openssl-1.1-fit/crypto/whrlpool/wp_locl.h | 12 + .../openssl-1.1-fit/crypto/x509/build.info | 10 + .../openssl-1.1-fit/crypto/x509/by_dir.c | 390 + .../openssl-1.1-fit/crypto/x509/by_file.c | 227 + .../openssl-1.1-fit/crypto/x509/t_crl.c | 94 + .../openssl-1.1-fit/crypto/x509/t_req.c | 210 + .../openssl-1.1-fit/crypto/x509/t_x509.c | 379 + .../openssl-1.1-fit/crypto/x509/x509_att.c | 329 + .../openssl-1.1-fit/crypto/x509/x509_cmp.c | 458 + .../openssl-1.1-fit/crypto/x509/x509_d2.c | 57 + .../openssl-1.1-fit/crypto/x509/x509_def.c | 43 + .../openssl-1.1-fit/crypto/x509/x509_err.c | 181 + .../openssl-1.1-fit/crypto/x509/x509_ext.c | 159 + .../openssl-1.1-fit/crypto/x509/x509_lcl.h | 147 + .../openssl-1.1-fit/crypto/x509/x509_lu.c | 898 ++ .../openssl-1.1-fit/crypto/x509/x509_meth.c | 166 + .../openssl-1.1-fit/crypto/x509/x509_obj.c | 181 + .../openssl-1.1-fit/crypto/x509/x509_r2x.c | 67 + .../openssl-1.1-fit/crypto/x509/x509_req.c | 298 + .../openssl-1.1-fit/crypto/x509/x509_set.c | 237 + .../openssl-1.1-fit/crypto/x509/x509_trs.c | 299 + .../openssl-1.1-fit/crypto/x509/x509_txt.c | 182 + .../openssl-1.1-fit/crypto/x509/x509_v3.c | 235 + .../openssl-1.1-fit/crypto/x509/x509_vfy.c | 3275 ++++++ .../openssl-1.1-fit/crypto/x509/x509_vpm.c | 602 ++ .../openssl-1.1-fit/crypto/x509/x509cset.c | 183 + .../openssl-1.1-fit/crypto/x509/x509name.c | 360 + .../openssl-1.1-fit/crypto/x509/x509rset.c | 40 + .../openssl-1.1-fit/crypto/x509/x509spki.c | 75 + .../openssl-1.1-fit/crypto/x509/x509type.c | 84 + .../openssl-1.1-fit/crypto/x509/x_all.c | 525 + .../openssl-1.1-fit/crypto/x509/x_attrib.c | 55 + .../openssl-1.1-fit/crypto/x509/x_crl.c | 478 + .../openssl-1.1-fit/crypto/x509/x_exten.c | 28 + .../openssl-1.1-fit/crypto/x509/x_name.c | 551 + .../openssl-1.1-fit/crypto/x509/x_pubkey.c | 375 + .../openssl-1.1-fit/crypto/x509/x_req.c | 68 + .../openssl-1.1-fit/crypto/x509/x_x509.c | 247 + .../openssl-1.1-fit/crypto/x509/x_x509a.c | 169 + .../openssl-1.1-fit/crypto/x509v3/build.info | 8 + .../openssl-1.1-fit/crypto/x509v3/ext_dat.h | 25 + .../openssl-1.1-fit/crypto/x509v3/pcy_cache.c | 224 + .../openssl-1.1-fit/crypto/x509v3/pcy_data.c | 81 + .../openssl-1.1-fit/crypto/x509v3/pcy_int.h | 167 + .../openssl-1.1-fit/crypto/x509v3/pcy_lib.c | 108 + .../openssl-1.1-fit/crypto/x509v3/pcy_map.c | 81 + .../openssl-1.1-fit/crypto/x509v3/pcy_node.c | 147 + .../openssl-1.1-fit/crypto/x509v3/pcy_tree.c | 703 ++ .../crypto/x509v3/standard_exts.h | 78 + .../openssl-1.1-fit/crypto/x509v3/v3_addr.c | 1315 +++ .../openssl-1.1-fit/crypto/x509v3/v3_admis.c | 356 + .../openssl-1.1-fit/crypto/x509v3/v3_admis.h | 38 + .../openssl-1.1-fit/crypto/x509v3/v3_akey.c | 160 + .../openssl-1.1-fit/crypto/x509v3/v3_akeya.c | 23 + .../openssl-1.1-fit/crypto/x509v3/v3_alt.c | 592 + .../openssl-1.1-fit/crypto/x509v3/v3_asid.c | 880 ++ .../openssl-1.1-fit/crypto/x509v3/v3_bcons.c | 84 + .../openssl-1.1-fit/crypto/x509v3/v3_bitst.c | 93 + .../openssl-1.1-fit/crypto/x509v3/v3_conf.c | 511 + .../openssl-1.1-fit/crypto/x509v3/v3_cpols.c | 491 + .../openssl-1.1-fit/crypto/x509v3/v3_crld.c | 506 + .../openssl-1.1-fit/crypto/x509v3/v3_enum.c | 53 + .../openssl-1.1-fit/crypto/x509v3/v3_extku.c | 103 + .../openssl-1.1-fit/crypto/x509v3/v3_genn.c | 201 + .../openssl-1.1-fit/crypto/x509v3/v3_ia5.c | 65 + .../openssl-1.1-fit/crypto/x509v3/v3_info.c | 162 + .../openssl-1.1-fit/crypto/x509v3/v3_int.c | 43 + .../openssl-1.1-fit/crypto/x509v3/v3_lib.c | 303 + .../openssl-1.1-fit/crypto/x509v3/v3_ncons.c | 675 ++ .../openssl-1.1-fit/crypto/x509v3/v3_pci.c | 325 + .../openssl-1.1-fit/crypto/x509v3/v3_pcia.c | 64 + .../openssl-1.1-fit/crypto/x509v3/v3_pcons.c | 91 + .../openssl-1.1-fit/crypto/x509v3/v3_pku.c | 52 + .../openssl-1.1-fit/crypto/x509v3/v3_pmaps.c | 112 + .../openssl-1.1-fit/crypto/x509v3/v3_prn.c | 210 + .../openssl-1.1-fit/crypto/x509v3/v3_purp.c | 890 ++ .../openssl-1.1-fit/crypto/x509v3/v3_skey.c | 106 + .../openssl-1.1-fit/crypto/x509v3/v3_sxnet.c | 226 + .../openssl-1.1-fit/crypto/x509v3/v3_tlsf.c | 137 + .../openssl-1.1-fit/crypto/x509v3/v3_utl.c | 1239 +++ .../openssl-1.1-fit/crypto/x509v3/v3err.c | 257 + .../openssl-1.1-fit/crypto/x86_64cpuid.pl | 495 + .../openssl-1.1-fit/crypto/x86cpuid.pl | 509 + trunk/3rdparty/openssl-1.1-fit/e_os.h | 334 + .../engines/asm/e_padlock-x86.pl | 627 ++ .../engines/asm/e_padlock-x86_64.pl | 583 + .../openssl-1.1-fit/engines/build.info | 43 + .../openssl-1.1-fit/engines/e_afalg.c | 870 ++ .../openssl-1.1-fit/engines/e_afalg.ec | 3 + .../openssl-1.1-fit/engines/e_afalg.h | 95 + .../openssl-1.1-fit/engines/e_afalg.txt | 30 + .../openssl-1.1-fit/engines/e_afalg_err.c | 83 + .../openssl-1.1-fit/engines/e_afalg_err.h | 43 + .../3rdparty/openssl-1.1-fit/engines/e_capi.c | 1904 ++++ .../openssl-1.1-fit/engines/e_capi.ec | 3 + .../openssl-1.1-fit/engines/e_capi.txt | 62 + .../openssl-1.1-fit/engines/e_capi_err.c | 119 + .../openssl-1.1-fit/engines/e_capi_err.h | 75 + .../openssl-1.1-fit/engines/e_dasync.c | 785 ++ .../openssl-1.1-fit/engines/e_dasync.ec | 3 + .../openssl-1.1-fit/engines/e_dasync.txt | 22 + .../openssl-1.1-fit/engines/e_dasync_err.c | 73 + .../openssl-1.1-fit/engines/e_dasync_err.h | 37 + .../openssl-1.1-fit/engines/e_ossltest.c | 696 ++ .../openssl-1.1-fit/engines/e_ossltest.ec | 3 + .../openssl-1.1-fit/engines/e_ossltest.txt | 13 + .../openssl-1.1-fit/engines/e_ossltest_err.c | 63 + .../openssl-1.1-fit/engines/e_ossltest_err.h | 28 + .../openssl-1.1-fit/engines/e_padlock.c | 747 ++ .../external/perl/Downloaded.txt | 13 + .../external/perl/Text-Template-1.46/Artistic | 131 + .../external/perl/Text-Template-1.46/COPYING | 340 + .../external/perl/Text-Template-1.46/INSTALL | 31 + .../external/perl/Text-Template-1.46/MANIFEST | 25 + .../perl/Text-Template-1.46/META.json | 39 + .../external/perl/Text-Template-1.46/META.yml | 21 + .../perl/Text-Template-1.46/Makefile.PL | 7 + .../external/perl/Text-Template-1.46/README | 339 + .../Text-Template-1.46/lib/Text/Template.pm | 1973 ++++ .../lib/Text/Template/Preprocess.pm | 144 + .../perl/Text-Template-1.46/t/00-version.t | 11 + .../perl/Text-Template-1.46/t/01-basic.t | 266 + .../perl/Text-Template-1.46/t/02-hash.t | 111 + .../perl/Text-Template-1.46/t/03-out.t | 56 + .../perl/Text-Template-1.46/t/04-safe.t | 161 + .../perl/Text-Template-1.46/t/05-safe2.t | 105 + .../perl/Text-Template-1.46/t/06-ofh.t | 39 + .../perl/Text-Template-1.46/t/07-safe3.t | 91 + .../perl/Text-Template-1.46/t/08-exported.t | 75 + .../perl/Text-Template-1.46/t/09-error.t | 63 + .../perl/Text-Template-1.46/t/10-delimiters.t | 99 + .../perl/Text-Template-1.46/t/11-prepend.t | 94 + .../perl/Text-Template-1.46/t/12-preprocess.t | 52 + .../perl/Text-Template-1.46/t/13-taint.t | 119 + .../perl/Text-Template-1.46/t/14-broken.t | 82 + .../external/perl/transfer/Text/Template.pm | 23 + trunk/3rdparty/openssl-1.1-fit/fuzz/README.md | 131 + trunk/3rdparty/openssl-1.1-fit/fuzz/asn1.c | 352 + .../3rdparty/openssl-1.1-fit/fuzz/asn1parse.c | 43 + trunk/3rdparty/openssl-1.1-fit/fuzz/bignum.c | 109 + trunk/3rdparty/openssl-1.1-fit/fuzz/bndiv.c | 131 + .../3rdparty/openssl-1.1-fit/fuzz/build.info | 121 + trunk/3rdparty/openssl-1.1-fit/fuzz/client.c | 102 + trunk/3rdparty/openssl-1.1-fit/fuzz/cms.c | 55 + trunk/3rdparty/openssl-1.1-fit/fuzz/conf.c | 48 + trunk/3rdparty/openssl-1.1-fit/fuzz/crl.c | 47 + trunk/3rdparty/openssl-1.1-fit/fuzz/ct.c | 51 + trunk/3rdparty/openssl-1.1-fit/fuzz/driver.c | 55 + trunk/3rdparty/openssl-1.1-fit/fuzz/fuzzer.h | 14 + trunk/3rdparty/openssl-1.1-fit/fuzz/helper.py | 52 + .../openssl-1.1-fit/fuzz/mkfuzzoids.pl | 32 + trunk/3rdparty/openssl-1.1-fit/fuzz/oids.txt | 1065 ++ trunk/3rdparty/openssl-1.1-fit/fuzz/rand.inc | 40 + trunk/3rdparty/openssl-1.1-fit/fuzz/server.c | 650 ++ .../openssl-1.1-fit/fuzz/test-corpus.c | 104 + trunk/3rdparty/openssl-1.1-fit/fuzz/x509.c | 51 + .../internal/__DECC_INCLUDE_EPILOGUE.H | 16 + .../internal/__DECC_INCLUDE_PROLOGUE.H | 20 + .../openssl-1.1-fit/include/internal/bio.h | 33 + .../openssl-1.1-fit/include/internal/comp.h | 12 + .../openssl-1.1-fit/include/internal/conf.h | 30 + .../include/internal/constant_time_locl.h | 333 + .../include/internal/cryptlib.h | 98 + .../openssl-1.1-fit/include/internal/dane.h | 103 + .../openssl-1.1-fit/include/internal/dso.h | 165 + .../openssl-1.1-fit/include/internal/dsoerr.h | 83 + .../openssl-1.1-fit/include/internal/err.h | 15 + .../openssl-1.1-fit/include/internal/nelem.h | 14 + .../include/internal/numbers.h | 68 + .../openssl-1.1-fit/include/internal/o_dir.h | 52 + .../openssl-1.1-fit/include/internal/o_str.h | 17 + .../include/internal/refcount.h | 140 + .../include/internal/sockets.h | 155 + .../include/internal/sslconf.h | 20 + .../include/internal/thread_once.h | 137 + .../include/internal/tsan_assist.h | 144 + .../include/openssl/__DECC_INCLUDE_EPILOGUE.H | 16 + .../include/openssl/__DECC_INCLUDE_PROLOGUE.H | 20 + .../openssl-1.1-fit/include/openssl/aes.h | 92 + .../openssl-1.1-fit/include/openssl/asn1.h | 886 ++ .../include/openssl/asn1_mac.h | 10 + .../openssl-1.1-fit/include/openssl/asn1err.h | 252 + .../openssl-1.1-fit/include/openssl/asn1t.h | 945 ++ .../openssl-1.1-fit/include/openssl/async.h | 76 + .../include/openssl/asyncerr.h | 38 + .../openssl-1.1-fit/include/openssl/bio.h | 804 ++ .../openssl-1.1-fit/include/openssl/bioerr.h | 120 + .../include/openssl/blowfish.h | 61 + .../openssl-1.1-fit/include/openssl/bn.h | 539 + .../openssl-1.1-fit/include/openssl/bnerr.h | 96 + .../openssl-1.1-fit/include/openssl/buffer.h | 58 + .../include/openssl/buffererr.h | 30 + .../include/openssl/camellia.h | 83 + .../openssl-1.1-fit/include/openssl/cast.h | 53 + .../openssl-1.1-fit/include/openssl/cmac.h | 41 + .../openssl-1.1-fit/include/openssl/cms.h | 342 + .../openssl-1.1-fit/include/openssl/cmserr.h | 196 + .../openssl-1.1-fit/include/openssl/comp.h | 53 + .../openssl-1.1-fit/include/openssl/comperr.h | 40 + .../openssl-1.1-fit/include/openssl/conf.h | 168 + .../include/openssl/conf_api.h | 40 + .../openssl-1.1-fit/include/openssl/conferr.h | 72 + .../openssl-1.1-fit/include/openssl/crypto.h | 445 + .../include/openssl/cryptoerr.h | 56 + .../openssl-1.1-fit/include/openssl/ct.h | 476 + .../openssl-1.1-fit/include/openssl/cterr.h | 76 + .../openssl-1.1-fit/include/openssl/des.h | 174 + .../openssl-1.1-fit/include/openssl/dh.h | 340 + .../openssl-1.1-fit/include/openssl/dherr.h | 84 + .../openssl-1.1-fit/include/openssl/dsa.h | 238 + .../openssl-1.1-fit/include/openssl/dsaerr.h | 67 + .../openssl-1.1-fit/include/openssl/dtls1.h | 55 + .../openssl-1.1-fit/include/openssl/e_os2.h | 300 + .../openssl-1.1-fit/include/openssl/ebcdic.h | 33 + .../openssl-1.1-fit/include/openssl/ec.h | 1478 +++ .../openssl-1.1-fit/include/openssl/ecdh.h | 10 + .../openssl-1.1-fit/include/openssl/ecdsa.h | 10 + .../openssl-1.1-fit/include/openssl/ecerr.h | 271 + .../openssl-1.1-fit/include/openssl/engine.h | 751 ++ .../include/openssl/engineerr.h | 107 + .../openssl-1.1-fit/include/openssl/err.h | 273 + .../openssl-1.1-fit/include/openssl/evp.h | 1633 +++ .../openssl-1.1-fit/include/openssl/evperr.h | 194 + .../openssl-1.1-fit/include/openssl/hmac.h | 51 + .../openssl-1.1-fit/include/openssl/idea.h | 64 + .../openssl-1.1-fit/include/openssl/kdf.h | 97 + .../openssl-1.1-fit/include/openssl/kdferr.h | 51 + .../openssl-1.1-fit/include/openssl/lhash.h | 242 + .../openssl-1.1-fit/include/openssl/md2.h | 44 + .../openssl-1.1-fit/include/openssl/md4.h | 51 + .../openssl-1.1-fit/include/openssl/md5.h | 50 + .../openssl-1.1-fit/include/openssl/mdc2.h | 42 + .../openssl-1.1-fit/include/openssl/modes.h | 208 + .../openssl-1.1-fit/include/openssl/obj_mac.h | 5198 +++++++++ .../openssl-1.1-fit/include/openssl/objects.h | 175 + .../include/openssl/objectserr.h | 38 + .../openssl-1.1-fit/include/openssl/ocsp.h | 352 + .../openssl-1.1-fit/include/openssl/ocsperr.h | 74 + .../include/openssl/opensslconf.h.in | 155 + .../include/openssl/opensslv.h | 101 + .../include/openssl/ossl_typ.h | 196 + .../openssl-1.1-fit/include/openssl/pem.h | 378 + .../openssl-1.1-fit/include/openssl/pem2.h | 13 + .../openssl-1.1-fit/include/openssl/pemerr.h | 99 + .../openssl-1.1-fit/include/openssl/pkcs12.h | 223 + .../include/openssl/pkcs12err.h | 77 + .../openssl-1.1-fit/include/openssl/pkcs7.h | 319 + .../include/openssl/pkcs7err.h | 99 + .../openssl-1.1-fit/include/openssl/rand.h | 77 + .../include/openssl/rand_drbg.h | 130 + .../openssl-1.1-fit/include/openssl/randerr.h | 89 + .../openssl-1.1-fit/include/openssl/rc2.h | 51 + .../openssl-1.1-fit/include/openssl/rc4.h | 36 + .../openssl-1.1-fit/include/openssl/rc5.h | 63 + .../openssl-1.1-fit/include/openssl/ripemd.h | 47 + .../openssl-1.1-fit/include/openssl/rsa.h | 512 + .../openssl-1.1-fit/include/openssl/rsaerr.h | 162 + .../include/openssl/safestack.h | 207 + .../openssl-1.1-fit/include/openssl/seed.h | 96 + .../openssl-1.1-fit/include/openssl/sha.h | 119 + .../openssl-1.1-fit/include/openssl/srp.h | 135 + .../openssl-1.1-fit/include/openssl/srtp.h | 50 + .../openssl-1.1-fit/include/openssl/ssl.h | 2438 +++++ .../openssl-1.1-fit/include/openssl/ssl2.h | 24 + .../openssl-1.1-fit/include/openssl/ssl3.h | 339 + .../openssl-1.1-fit/include/openssl/sslerr.h | 768 ++ .../openssl-1.1-fit/include/openssl/stack.h | 83 + .../openssl-1.1-fit/include/openssl/store.h | 266 + .../include/openssl/storeerr.h | 87 + .../include/openssl/symhacks.h | 37 + .../openssl-1.1-fit/include/openssl/tls1.h | 1237 +++ .../openssl-1.1-fit/include/openssl/ts.h | 559 + .../openssl-1.1-fit/include/openssl/tserr.h | 128 + .../openssl-1.1-fit/include/openssl/txt_db.h | 57 + .../openssl-1.1-fit/include/openssl/ui.h | 368 + .../openssl-1.1-fit/include/openssl/uierr.h | 61 + .../include/openssl/whrlpool.h | 48 + .../openssl-1.1-fit/include/openssl/x509.h | 1047 ++ .../include/openssl/x509_vfy.h | 628 ++ .../openssl-1.1-fit/include/openssl/x509err.h | 125 + .../openssl-1.1-fit/include/openssl/x509v3.h | 935 ++ .../include/openssl/x509v3err.h | 158 + trunk/3rdparty/openssl-1.1-fit/ms/applink.c | 138 + trunk/3rdparty/openssl-1.1-fit/ms/cmp.pl | 53 + .../openssl-1.1-fit/ms/uplink-common.pl | 28 + .../openssl-1.1-fit/ms/uplink-ia64.pl | 61 + .../3rdparty/openssl-1.1-fit/ms/uplink-x86.pl | 44 + .../openssl-1.1-fit/ms/uplink-x86_64.pl | 71 + trunk/3rdparty/openssl-1.1-fit/ms/uplink.c | 135 + trunk/3rdparty/openssl-1.1-fit/ms/uplink.h | 38 + trunk/3rdparty/openssl-1.1-fit/os-dep/haiku.h | 2 + trunk/3rdparty/openssl-1.1-fit/ssl/bio_ssl.c | 505 + trunk/3rdparty/openssl-1.1-fit/ssl/build.info | 15 + trunk/3rdparty/openssl-1.1-fit/ssl/d1_lib.c | 972 ++ trunk/3rdparty/openssl-1.1-fit/ssl/d1_msg.c | 73 + trunk/3rdparty/openssl-1.1-fit/ssl/d1_srtp.c | 139 + trunk/3rdparty/openssl-1.1-fit/ssl/methods.c | 278 + trunk/3rdparty/openssl-1.1-fit/ssl/packet.c | 424 + .../openssl-1.1-fit/ssl/packet_locl.h | 874 ++ trunk/3rdparty/openssl-1.1-fit/ssl/pqueue.c | 158 + .../openssl-1.1-fit/ssl/record/README | 74 + .../openssl-1.1-fit/ssl/record/dtls1_bitmap.c | 78 + .../openssl-1.1-fit/ssl/record/rec_layer_d1.c | 1059 ++ .../openssl-1.1-fit/ssl/record/rec_layer_s3.c | 1771 +++ .../openssl-1.1-fit/ssl/record/record.h | 236 + .../openssl-1.1-fit/ssl/record/record_locl.h | 116 + .../openssl-1.1-fit/ssl/record/ssl3_buffer.c | 179 + .../openssl-1.1-fit/ssl/record/ssl3_record.c | 2057 ++++ .../ssl/record/ssl3_record_tls13.c | 196 + trunk/3rdparty/openssl-1.1-fit/ssl/s3_cbc.c | 487 + trunk/3rdparty/openssl-1.1-fit/ssl/s3_enc.c | 595 + trunk/3rdparty/openssl-1.1-fit/ssl/s3_lib.c | 4864 +++++++++ trunk/3rdparty/openssl-1.1-fit/ssl/s3_msg.c | 104 + trunk/3rdparty/openssl-1.1-fit/ssl/ssl_asn1.c | 393 + trunk/3rdparty/openssl-1.1-fit/ssl/ssl_cert.c | 1040 ++ .../openssl-1.1-fit/ssl/ssl_cert_table.h | 23 + trunk/3rdparty/openssl-1.1-fit/ssl/ssl_ciph.c | 2163 ++++ trunk/3rdparty/openssl-1.1-fit/ssl/ssl_conf.c | 993 ++ trunk/3rdparty/openssl-1.1-fit/ssl/ssl_err.c | 1277 +++ trunk/3rdparty/openssl-1.1-fit/ssl/ssl_init.c | 221 + trunk/3rdparty/openssl-1.1-fit/ssl/ssl_lib.c | 5581 ++++++++++ trunk/3rdparty/openssl-1.1-fit/ssl/ssl_locl.h | 2666 +++++ trunk/3rdparty/openssl-1.1-fit/ssl/ssl_mcnf.c | 99 + trunk/3rdparty/openssl-1.1-fit/ssl/ssl_rsa.c | 1148 ++ trunk/3rdparty/openssl-1.1-fit/ssl/ssl_sess.c | 1317 +++ trunk/3rdparty/openssl-1.1-fit/ssl/ssl_stat.c | 388 + trunk/3rdparty/openssl-1.1-fit/ssl/ssl_txt.c | 203 + trunk/3rdparty/openssl-1.1-fit/ssl/ssl_utst.c | 24 + .../openssl-1.1-fit/ssl/statem/README | 63 + .../openssl-1.1-fit/ssl/statem/extensions.c | 1700 +++ .../ssl/statem/extensions_clnt.c | 1991 ++++ .../ssl/statem/extensions_cust.c | 533 + .../ssl/statem/extensions_srvr.c | 1959 ++++ .../openssl-1.1-fit/ssl/statem/statem.c | 972 ++ .../openssl-1.1-fit/ssl/statem/statem.h | 157 + .../openssl-1.1-fit/ssl/statem/statem_clnt.c | 3851 +++++++ .../openssl-1.1-fit/ssl/statem/statem_dtls.c | 1281 +++ .../openssl-1.1-fit/ssl/statem/statem_lib.c | 2403 +++++ .../openssl-1.1-fit/ssl/statem/statem_locl.h | 420 + .../openssl-1.1-fit/ssl/statem/statem_srvr.c | 4272 ++++++++ trunk/3rdparty/openssl-1.1-fit/ssl/t1_enc.c | 678 ++ trunk/3rdparty/openssl-1.1-fit/ssl/t1_lib.c | 2792 +++++ trunk/3rdparty/openssl-1.1-fit/ssl/t1_trce.c | 1566 +++ .../3rdparty/openssl-1.1-fit/ssl/tls13_enc.c | 833 ++ trunk/3rdparty/openssl-1.1-fit/ssl/tls_srp.c | 456 + .../3rdparty/openssl-1.1-fit/tools/build.info | 7 + .../openssl-1.1-fit/tools/c_rehash.in | 231 + .../openssl-1.1-fit/util/add-depends.pl | 288 + .../3rdparty/openssl-1.1-fit/util/build.info | 8 + .../openssl-1.1-fit/util/check-malloc-errs | 16 + .../3rdparty/openssl-1.1-fit/util/ck_errf.pl | 152 + trunk/3rdparty/openssl-1.1-fit/util/copy.pl | 84 + trunk/3rdparty/openssl-1.1-fit/util/dofile.pl | 210 + trunk/3rdparty/openssl-1.1-fit/util/echo.pl | 12 + .../openssl-1.1-fit/util/find-doc-nits | 545 + .../openssl-1.1-fit/util/find-unused-errs | 54 + .../3rdparty/openssl-1.1-fit/util/indent.pro | 643 ++ .../openssl-1.1-fit/util/libcrypto.num | 4581 ++++++++ .../3rdparty/openssl-1.1-fit/util/libssl.num | 500 + .../openssl-1.1-fit/util/local_shlib.com.in | 30 + .../openssl-1.1-fit/util/mkbuildinf.pl | 56 + trunk/3rdparty/openssl-1.1-fit/util/mkdef.pl | 1633 +++ .../3rdparty/openssl-1.1-fit/util/mkdir-p.pl | 44 + trunk/3rdparty/openssl-1.1-fit/util/mkerr.pl | 753 ++ trunk/3rdparty/openssl-1.1-fit/util/mkrc.pl | 93 + .../util/openssl-format-source | 175 + .../util/openssl-update-copyright | 63 + .../openssl-1.1-fit/util/opensslwrap.sh | 26 + .../openssl-1.1-fit/util/perl/OpenSSL/Glob.pm | 21 + .../openssl-1.1-fit/util/perl/OpenSSL/Test.pm | 1216 +++ .../util/perl/OpenSSL/Test/Simple.pm | 91 + .../util/perl/OpenSSL/Test/Utils.pm | 240 + .../util/perl/OpenSSL/Util/Pod.pm | 149 + .../util/perl/TLSProxy/Alert.pm | 51 + .../util/perl/TLSProxy/Certificate.pm | 214 + .../util/perl/TLSProxy/CertificateVerify.pm | 96 + .../util/perl/TLSProxy/ClientHello.pm | 258 + .../util/perl/TLSProxy/EncryptedExtensions.pm | 110 + .../util/perl/TLSProxy/Message.pm | 592 + .../util/perl/TLSProxy/NewSessionTicket.pm | 81 + .../util/perl/TLSProxy/Proxy.pm | 728 ++ .../util/perl/TLSProxy/Record.pm | 401 + .../util/perl/TLSProxy/ServerHello.pm | 236 + .../util/perl/TLSProxy/ServerKeyExchange.pm | 157 + .../util/perl/checkhandshake.pm | 228 + .../util/perl/with_fallback.pm | 27 + .../3rdparty/openssl-1.1-fit/util/private.num | 457 + .../openssl-1.1-fit/util/process_docs.pl | 271 + .../openssl-1.1-fit/util/shlib_wrap.sh.in | 138 + .../openssl-1.1-fit/util/su-filter.pl | 264 + .../openssl-1.1-fit/util/unlocal_shlib.com.in | 26 + trunk/3rdparty/openssl-1.1.0e.zip | Bin 6623784 -> 0 bytes trunk/auto/depends.sh | 17 +- trunk/src/core/srs_core_version4.hpp | 2 +- 1476 files changed, 616554 insertions(+), 4 deletions(-) create mode 100644 trunk/3rdparty/openssl-1.1-fit/Configurations/00-base-templates.conf create mode 100644 trunk/3rdparty/openssl-1.1-fit/Configurations/10-main.conf create mode 100644 trunk/3rdparty/openssl-1.1-fit/Configurations/15-android.conf create mode 100644 trunk/3rdparty/openssl-1.1-fit/Configurations/15-ios.conf create mode 100644 trunk/3rdparty/openssl-1.1-fit/Configurations/50-djgpp.conf create mode 100644 trunk/3rdparty/openssl-1.1-fit/Configurations/50-haiku.conf create mode 100644 trunk/3rdparty/openssl-1.1-fit/Configurations/50-masm.conf create mode 100644 trunk/3rdparty/openssl-1.1-fit/Configurations/50-win-onecore.conf create mode 100644 trunk/3rdparty/openssl-1.1-fit/Configurations/INTERNALS.Configure create mode 100644 trunk/3rdparty/openssl-1.1-fit/Configurations/README create mode 100644 trunk/3rdparty/openssl-1.1-fit/Configurations/README.design create mode 100644 trunk/3rdparty/openssl-1.1-fit/Configurations/common.tmpl create mode 100644 trunk/3rdparty/openssl-1.1-fit/Configurations/common0.tmpl create mode 100644 trunk/3rdparty/openssl-1.1-fit/Configurations/descrip.mms.tmpl create mode 100644 trunk/3rdparty/openssl-1.1-fit/Configurations/shared-info.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/Configurations/unix-Makefile.tmpl create mode 100644 trunk/3rdparty/openssl-1.1-fit/Configurations/unix-checker.pm create mode 100644 trunk/3rdparty/openssl-1.1-fit/Configurations/windows-checker.pm create mode 100644 trunk/3rdparty/openssl-1.1-fit/Configurations/windows-makefile.tmpl create mode 100755 trunk/3rdparty/openssl-1.1-fit/Configure create mode 100644 trunk/3rdparty/openssl-1.1-fit/LICENSE create mode 100644 trunk/3rdparty/openssl-1.1-fit/README.md create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/CA.pl.in create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/app_rand.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/apps.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/apps.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/asn1pars.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/bf_prefix.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/ca-cert.srl create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/ca-key.pem create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/ca-req.pem create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/ca.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/cert.pem create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/ciphers.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/client.pem create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/cms.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/crl.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/crl2p7.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/ct_log_list.cnf create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/demoSRP/srp_verifier.txt create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/demoSRP/srp_verifier.txt.attr create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/dgst.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/dh1024.pem create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/dh2048.pem create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/dh4096.pem create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/dhparam.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/dsa-ca.pem create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/dsa-pca.pem create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/dsa.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/dsa1024.pem create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/dsa512.pem create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/dsap.pem create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/dsaparam.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/ec.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/ecparam.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/enc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/engine.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/errstr.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/gendsa.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/genpkey.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/genrsa.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/nseq.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/ocsp.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/openssl-vms.cnf create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/openssl.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/openssl.cnf create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/opt.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/passwd.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/pca-cert.srl create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/pca-key.pem create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/pca-req.pem create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/pkcs12.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/pkcs7.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/pkcs8.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/pkey.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/pkeyparam.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/pkeyutl.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/prime.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/privkey.pem create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/progs.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/rand.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/rehash.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/req.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/req.pem create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/rsa.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/rsa8192.pem create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/rsautl.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/s1024key.pem create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/s1024req.pem create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/s512-key.pem create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/s512-req.pem create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/s_apps.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/s_cb.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/s_client.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/s_server.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/s_socket.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/s_time.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/server.pem create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/server.srl create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/server2.pem create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/sess_id.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/smime.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/speed.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/spkac.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/srp.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/storeutl.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/testCA.pem create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/testdsa.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/testrsa.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/timeouts.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/ts.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/tsget.in create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/verify.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/version.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/vms_decc_init.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/vms_term_sock.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/vms_term_sock.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/win32_init.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/apps/x509.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/appveyor.yml create mode 100644 trunk/3rdparty/openssl-1.1-fit/build.info create mode 100755 trunk/3rdparty/openssl-1.1-fit/config create mode 100644 trunk/3rdparty/openssl-1.1-fit/config.com create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/LPdir_nyi.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/LPdir_unix.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/LPdir_vms.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/LPdir_win.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/LPdir_win32.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/LPdir_wince.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_cbc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_cfb.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_core.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_ecb.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_ige.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_misc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_ofb.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_wrap.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_x86core.c create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-586.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-armv4.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-c64xplus.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-ia64.S create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-mips.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-parisc.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-ppc.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-s390x.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-sparcv9.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-x86_64.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesfx-sparcv9.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesni-mb-x86_64.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesni-sha1-x86_64.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesni-sha256-x86_64.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesni-x86.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesni-x86_64.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesp8-ppc.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aest4-sparcv9.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesv8-armx.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/bsaes-armv7.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/bsaes-x86_64.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/vpaes-armv8.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/vpaes-ppc.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/vpaes-x86.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/vpaes-x86_64.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aes/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/alphacpuid.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aria/aria.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/aria/build.info create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/arm64cpuid.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/arm_arch.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/armcap.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/armv4cpuid.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_bitstr.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_d2i_fp.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_digest.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_dup.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_gentm.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_i2d_fp.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_int.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_mbstr.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_object.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_octet.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_print.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_sign.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_strex.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_strnid.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_time.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_type.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_utctm.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_utf8.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_verify.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/ameth_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn1_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn1_gen.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn1_item_list.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn1_item_list.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn1_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn1_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn1_par.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn_mime.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn_moid.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn_mstbl.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn_pack.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/bio_asn1.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/bio_ndef.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/charmap.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/charmap.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/d2i_pr.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/d2i_pu.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/evp_asn1.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/f_int.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/f_string.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/i2d_pr.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/i2d_pu.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/n_pkey.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/nsseq.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/p5_pbe.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/p5_pbev2.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/p5_scrypt.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/p8_pkey.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/standard_methods.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/t_bitst.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/t_pkey.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/t_spki.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_dec.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_enc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_fre.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_new.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_prn.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_scn.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_typ.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_utl.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tbl_standard.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_algor.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_bignum.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_info.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_int64.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_long.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_pkey.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_sig.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_spki.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_val.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/async/arch/async_null.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/async/arch/async_null.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/async/arch/async_posix.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/async/arch/async_posix.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/async/arch/async_win.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/async/arch/async_win.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/async/async.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/async/async_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/async/async_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/async/async_wait.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/async/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bf/asm/bf-586.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bf/bf_cfb64.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bf/bf_ecb.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bf/bf_enc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bf/bf_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bf/bf_ofb64.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bf/bf_pi.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bf/bf_skey.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bf/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_addr.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_dump.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_print.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_sock.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_sock2.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bio/bf_buff.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bio/bf_lbuf.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bio/bf_nbio.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bio/bf_null.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_cb.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_lcl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_meth.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_acpt.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_bio.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_conn.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_dgram.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_fd.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_file.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_log.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_mem.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_null.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_sock.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bio/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/blake2/blake2_impl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/blake2/blake2_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/blake2/blake2b.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/blake2/blake2s.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/blake2/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/blake2/m_blake2b.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/blake2/m_blake2s.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/README.pod create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/alpha-mont.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/armv4-gf2m.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/armv4-mont.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/armv8-mont.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/bn-586.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/bn-c64xplus.asm create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/c64xplus-gf2m.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/co-586.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/ia64-mont.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/ia64.S create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/mips-mont.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/mips.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/parisc-mont.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/ppc-mont.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/ppc.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/ppc64-mont.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/rsaz-avx2.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/rsaz-x86_64.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/s390x-gf2m.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/s390x-mont.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/s390x.S create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/sparct4-mont.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/sparcv8.S create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/sparcv8plus.S create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/sparcv9-gf2m.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/sparcv9-mont.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/sparcv9a-mont.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/via-mont.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/vis3-mont.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/x86-gf2m.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/x86-mont.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/x86_64-gcc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/x86_64-gf2m.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/x86_64-mont.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/x86_64-mont5.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_add.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_asm.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_blind.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_const.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_ctx.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_depr.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_dh.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_div.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_exp.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_exp2.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_gcd.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_gf2m.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_intern.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_kron.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_lcl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_mod.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_mont.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_mpi.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_mul.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_nist.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_prime.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_prime.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_prime.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_print.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_rand.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_recp.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_shift.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_sqr.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_sqrt.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_srp.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_word.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_x931p.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/rsaz_exp.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/bn/rsaz_exp.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/buffer/buf_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/buffer/buffer.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/buffer/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/c64xpluscpuid.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/camellia/asm/cmll-x86.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/camellia/asm/cmll-x86_64.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/camellia/asm/cmllt4-sparcv9.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/camellia/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/camellia/camellia.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/camellia/cmll_cbc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/camellia/cmll_cfb.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/camellia/cmll_ctr.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/camellia/cmll_ecb.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/camellia/cmll_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/camellia/cmll_misc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/camellia/cmll_ofb.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cast/asm/cast-586.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cast/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cast/c_cfb64.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cast/c_ecb.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cast/c_enc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cast/c_ofb64.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cast/c_skey.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cast/cast_lcl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cast/cast_s.h create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/chacha/asm/chacha-armv4.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/chacha/asm/chacha-armv8.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/chacha/asm/chacha-c64xplus.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/chacha/asm/chacha-ppc.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/chacha/asm/chacha-s390x.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/chacha/asm/chacha-x86.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/chacha/asm/chacha-x86_64.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/chacha/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/chacha/chacha_enc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cmac/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cmac/cm_ameth.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cmac/cm_pmeth.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cmac/cmac.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cms/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_asn1.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_att.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_cd.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_dd.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_enc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_env.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_ess.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_io.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_kari.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_lcl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_pwri.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_sd.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_smime.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/comp/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/comp/c_zlib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/comp/comp_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/comp/comp_lcl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/comp/comp_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/conf/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_api.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_def.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_def.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_lcl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_mall.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_mod.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_sap.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_ssl.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/conf/keysets.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cpt_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cryptlib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ct/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_b64.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_log.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_oct.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_policy.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_prn.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_sct.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_sct_ctx.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_vfy.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_x509v3.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ctype.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/cversion.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/des/asm/crypt586.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/des/asm/des-586.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/des/asm/des_enc.m4 create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/des/asm/desboth.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/des/asm/dest4-sparcv9.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/des/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/des/cbc_cksm.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/des/cbc_enc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/des/cfb64ede.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/des/cfb64enc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/des/cfb_enc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/des/des_enc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/des/des_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/des/ecb3_enc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/des/ecb_enc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/des/fcrypt.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/des/fcrypt_b.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/des/ncbc_enc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/des/ofb64ede.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/des/ofb64enc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/des/ofb_enc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/des/pcbc_enc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/des/qud_cksm.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/des/rand_key.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/des/set_key.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/des/spr.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/des/str2key.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/des/xcbc_enc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dh/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh1024.pem create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh192.pem create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh2048.pem create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh4096.pem create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh512.pem create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_ameth.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_asn1.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_check.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_depr.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_gen.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_kdf.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_key.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_meth.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_pmeth.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_prn.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_rfc5114.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_rfc7919.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dllmain.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dsa/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_ameth.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_asn1.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_depr.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_gen.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_key.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_meth.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_ossl.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_pmeth.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_prn.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_sign.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_vrf.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dso/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_dl.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_dlfcn.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_openssl.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_vms.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_win32.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ebcdic.c create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/ecp_nistz256-armv4.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/ecp_nistz256-armv8.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/ecp_nistz256-avx2.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/ecp_nistz256-ppc64.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/ecp_nistz256-sparcv9.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/ecp_nistz256-x86.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/ecp_nistz256-x86_64.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/x25519-ppc64.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/x25519-x86_64.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve25519.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/arch_32/arch_intrinsics.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/arch_32/f_impl.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/arch_32/f_impl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/curve448.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/curve448_lcl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/curve448_tables.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/curve448utils.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/ed448.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/eddsa.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/f_generic.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/field.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/point_448.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/scalar.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/word.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec2_oct.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec2_smpl.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_ameth.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_asn1.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_check.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_curve.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_cvt.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_key.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_kmeth.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_lcl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_mult.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_oct.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_pmeth.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_print.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecdh_kdf.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecdh_ossl.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecdsa_ossl.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecdsa_sign.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecdsa_vrf.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/eck_prn.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_mont.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_nist.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_nistp224.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_nistp256.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_nistp521.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_nistputil.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_nistz256.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_nistz256_table.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_oct.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_smpl.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecx_meth.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/engine/README create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/engine/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_all.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_cnf.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_ctrl.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_devcrypto.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_dyn.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_fat.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_init.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_int.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_list.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_openssl.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_pkey.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_rdrand.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_table.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_asnmth.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_cipher.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_dh.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_digest.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_dsa.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_eckey.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_pkmeth.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_rand.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_rsa.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/err/README create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/err/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/err/err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/err/err_all.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/err/err_prn.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/err/openssl.ec create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/err/openssl.txt create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/bio_b64.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/bio_enc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/bio_md.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/bio_ok.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/c_allc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/c_alld.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/cmeth_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/digest.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_aes.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_aes_cbc_hmac_sha1.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_aes_cbc_hmac_sha256.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_aria.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_bf.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_camellia.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_cast.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_chacha20_poly1305.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_des.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_des3.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_idea.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_null.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_old.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_rc2.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_rc4.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_rc4_hmac_md5.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_rc5.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_seed.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_sm4.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_xcbc_d.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/encode.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_cnf.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_enc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_key.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_pbe.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_pkey.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_md2.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_md4.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_md5.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_md5_sha1.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_mdc2.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_null.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_ripemd.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_sha1.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_sha3.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_sigver.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_wp.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/names.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/p5_crpt.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/p5_crpt2.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/p_dec.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/p_enc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/p_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/p_open.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/p_seal.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/p_sign.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/p_verify.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/pbe_scrypt.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/pmeth_fn.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/pmeth_gn.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/evp/pmeth_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ex_data.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/getenv.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/hmac/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/hmac/hm_ameth.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/hmac/hm_pmeth.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/hmac/hmac.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/hmac/hmac_lcl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ia64cpuid.S create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/idea/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/idea/i_cbc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/idea/i_cfb64.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/idea/i_ecb.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/idea/i_ofb64.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/idea/i_skey.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/idea/idea_lcl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/__DECC_INCLUDE_EPILOGUE.H create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/__DECC_INCLUDE_PROLOGUE.H create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/aria.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/asn1_int.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/async.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/bn_conf.h.in create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/bn_dh.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/bn_int.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/bn_srp.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/chacha.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/cryptlib_int.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/ctype.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/dso_conf.h.in create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/ec_int.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/engine.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/err_int.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/evp_int.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/lhash.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/md32_common.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/objects.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/poly1305.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/rand_int.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/sha.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/siphash.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/sm2.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/sm2err.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/sm3.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/sm4.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/store.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/store_int.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/x509_int.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/init.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/kdf/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/kdf/hkdf.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/kdf/kdf_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/kdf/scrypt.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/kdf/tls1_prf.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/lhash/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/lhash/lh_stats.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/lhash/lhash.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/lhash/lhash_lcl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/md2/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/md2/md2_dgst.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/md2/md2_one.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/md4/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/md4/md4_dgst.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/md4/md4_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/md4/md4_one.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/md5/asm/md5-586.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/md5/asm/md5-sparcv9.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/md5/asm/md5-x86_64.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/md5/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/md5/md5_dgst.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/md5/md5_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/md5/md5_one.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/mdc2/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/mdc2/mdc2_one.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/mdc2/mdc2dgst.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/mem.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/mem_clr.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/mem_dbg.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/mem_sec.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/mips_arch.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/aesni-gcm-x86_64.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-alpha.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-armv4.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-c64xplus.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-ia64.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-parisc.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-s390x.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-sparcv9.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-x86.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-x86_64.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghashp8-ppc.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghashv8-armx.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/modes/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/modes/cbc128.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/modes/ccm128.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/modes/cfb128.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/modes/ctr128.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/modes/cts128.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/modes/gcm128.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/modes/modes_lcl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/modes/ocb128.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/modes/ofb128.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/modes/wrap128.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/modes/xts128.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/o_dir.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/o_fips.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/o_fopen.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/o_init.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/o_str.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/o_time.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/objects/README create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/objects/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/objects/o_names.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_dat.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_dat.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_dat.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_lcl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_mac.num create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_xref.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_xref.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_xref.txt create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/objects/objects.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/objects/objects.txt create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/objects/objxref.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_asn.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_cl.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_ext.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_ht.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_lcl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_prn.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_srv.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_vfy.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/v3_ocsp.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pariscid.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pem/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_all.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_info.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_oth.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_pk8.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_pkey.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_sign.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_x509.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_xaux.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pem/pvkfmt.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/README create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/arm-xlate.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/cbc.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/ppc-xlate.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/sparcv9_modes.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/x86_64-xlate.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/x86asm.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/x86gas.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/x86masm.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/x86nasm.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_add.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_asn.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_attr.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_crpt.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_crt.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_decr.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_init.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_key.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_kiss.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_lcl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_mutl.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_npas.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_p8d.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_p8e.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_sbag.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_utl.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/pk12err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/bio_pk7.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/pk7_asn1.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/pk7_attr.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/pk7_doit.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/pk7_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/pk7_mime.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/pk7_smime.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/pkcs7err.c create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-armv4.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-armv8.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-c64xplus.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-mips.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-ppc.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-ppcfp.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-s390x.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-sparcv9.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-x86.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-x86_64.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/poly1305.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/poly1305_ameth.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/poly1305_base2_44.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/poly1305_ieee754.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/poly1305_local.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/poly1305_pmeth.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ppc_arch.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ppccap.c create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/ppccpuid.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rand/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rand/drbg_ctr.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rand/drbg_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rand/rand_egd.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rand/rand_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rand/rand_lcl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rand/rand_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rand/rand_unix.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rand/rand_vms.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rand/rand_win.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rand/randfile.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rc2/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rc2/rc2_cbc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rc2/rc2_ecb.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rc2/rc2_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rc2/rc2_skey.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rc2/rc2cfb64.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rc2/rc2ofb64.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rc4/asm/rc4-586.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rc4/asm/rc4-c64xplus.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rc4/asm/rc4-md5-x86_64.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rc4/asm/rc4-parisc.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rc4/asm/rc4-s390x.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/rc4/asm/rc4-x86_64.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rc4/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rc4/rc4_enc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rc4/rc4_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rc4/rc4_skey.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rc5/asm/rc5-586.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rc5/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rc5/rc5_ecb.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rc5/rc5_enc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rc5/rc5_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rc5/rc5_skey.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rc5/rc5cfb64.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rc5/rc5ofb64.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ripemd/asm/rmd-586.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ripemd/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ripemd/rmd_dgst.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ripemd/rmd_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ripemd/rmd_one.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ripemd/rmdconst.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rsa/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_ameth.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_asn1.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_chk.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_crpt.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_depr.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_gen.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_meth.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_mp.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_none.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_oaep.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_ossl.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_pk1.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_pmeth.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_prn.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_pss.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_saos.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_sign.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_ssl.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_x931.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_x931g.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/s390x_arch.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/s390xcap.c create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/s390xcpuid.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/seed/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/seed/seed.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/seed/seed_cbc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/seed/seed_cfb.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/seed/seed_ecb.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/seed/seed_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/seed/seed_ofb.c create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-armv4.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-armv8.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-avx2.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-avx512.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-avx512vl.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-c64x.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-mmx.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-ppc64.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-s390x.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-x86_64.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600p8-ppc.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-586.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-alpha.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-armv4-large.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-armv8.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-c64xplus.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-ia64.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-mb-x86_64.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-mips.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-parisc.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-ppc.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-s390x.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-sparcv9.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-sparcv9a.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-thumb.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-x86_64.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha256-586.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha256-armv4.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha256-c64xplus.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha256-mb-x86_64.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-586.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-armv4.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-armv8.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-c64xplus.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-ia64.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-mips.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-parisc.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-ppc.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-s390x.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-sparcv9.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-x86_64.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512p8-ppc.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/keccak1600.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/sha1_one.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/sha1dgst.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/sha256.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/sha512.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sha/sha_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/siphash/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/siphash/siphash.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/siphash/siphash_ameth.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/siphash/siphash_local.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/siphash/siphash_pmeth.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sm2/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sm2/sm2_crypt.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sm2/sm2_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sm2/sm2_pmeth.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sm2/sm2_sign.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sm3/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sm3/m_sm3.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sm3/sm3.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sm3/sm3_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sm4/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sm4/sm4.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sparc_arch.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sparccpuid.S create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/sparcv9cap.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/srp/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/srp/srp_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/srp/srp_vfy.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/stack/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/stack/stack.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/store/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/store/loader_file.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/store/store_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/store/store_init.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/store/store_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/store/store_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/store/store_register.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/store/store_strings.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/threads_none.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/threads_pthread.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/threads_win.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ts/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_asn1.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_conf.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_lcl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_req_print.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_req_utils.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_rsp_print.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_rsp_sign.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_rsp_utils.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_rsp_verify.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_verify_ctx.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/txt_db/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/txt_db/txt_db.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ui/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ui/ui_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ui/ui_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ui/ui_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ui/ui_null.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ui/ui_openssl.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/ui/ui_util.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/uid.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/vms_rms.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/whrlpool/asm/wp-mmx.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/whrlpool/asm/wp-x86_64.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/whrlpool/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/whrlpool/wp_block.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/whrlpool/wp_dgst.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/whrlpool/wp_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/by_dir.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/by_file.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/t_crl.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/t_req.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/t_x509.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_att.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_cmp.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_d2.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_def.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_ext.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_lcl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_lu.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_meth.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_obj.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_r2x.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_req.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_set.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_trs.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_txt.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_v3.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_vfy.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_vpm.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509cset.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509name.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509rset.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509spki.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509type.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_all.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_attrib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_crl.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_exten.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_name.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_pubkey.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_req.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_x509.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_x509a.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/ext_dat.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/pcy_cache.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/pcy_data.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/pcy_int.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/pcy_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/pcy_map.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/pcy_node.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/pcy_tree.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/standard_exts.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_addr.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_admis.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_admis.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_akey.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_akeya.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_alt.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_asid.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_bcons.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_bitst.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_conf.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_cpols.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_crld.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_enum.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_extku.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_genn.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_ia5.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_info.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_int.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_ncons.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_pci.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_pcia.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_pcons.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_pku.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_pmaps.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_prn.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_purp.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_skey.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_sxnet.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_tlsf.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_utl.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x86_64cpuid.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/crypto/x86cpuid.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/e_os.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/engines/asm/e_padlock-x86.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/engines/asm/e_padlock-x86_64.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/engines/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/engines/e_afalg.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/engines/e_afalg.ec create mode 100644 trunk/3rdparty/openssl-1.1-fit/engines/e_afalg.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/engines/e_afalg.txt create mode 100644 trunk/3rdparty/openssl-1.1-fit/engines/e_afalg_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/engines/e_afalg_err.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/engines/e_capi.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/engines/e_capi.ec create mode 100644 trunk/3rdparty/openssl-1.1-fit/engines/e_capi.txt create mode 100644 trunk/3rdparty/openssl-1.1-fit/engines/e_capi_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/engines/e_capi_err.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/engines/e_dasync.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/engines/e_dasync.ec create mode 100644 trunk/3rdparty/openssl-1.1-fit/engines/e_dasync.txt create mode 100644 trunk/3rdparty/openssl-1.1-fit/engines/e_dasync_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/engines/e_dasync_err.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/engines/e_ossltest.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/engines/e_ossltest.ec create mode 100644 trunk/3rdparty/openssl-1.1-fit/engines/e_ossltest.txt create mode 100644 trunk/3rdparty/openssl-1.1-fit/engines/e_ossltest_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/engines/e_ossltest_err.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/engines/e_padlock.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/external/perl/Downloaded.txt create mode 100644 trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/Artistic create mode 100644 trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/COPYING create mode 100644 trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/INSTALL create mode 100644 trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/MANIFEST create mode 100644 trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/META.json create mode 100644 trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/META.yml create mode 100644 trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/Makefile.PL create mode 100644 trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/README create mode 100644 trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/lib/Text/Template.pm create mode 100644 trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/lib/Text/Template/Preprocess.pm create mode 100644 trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/00-version.t create mode 100644 trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/01-basic.t create mode 100644 trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/02-hash.t create mode 100644 trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/03-out.t create mode 100644 trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/04-safe.t create mode 100644 trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/05-safe2.t create mode 100644 trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/06-ofh.t create mode 100644 trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/07-safe3.t create mode 100644 trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/08-exported.t create mode 100644 trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/09-error.t create mode 100644 trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/10-delimiters.t create mode 100644 trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/11-prepend.t create mode 100644 trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/12-preprocess.t create mode 100644 trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/13-taint.t create mode 100644 trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/14-broken.t create mode 100644 trunk/3rdparty/openssl-1.1-fit/external/perl/transfer/Text/Template.pm create mode 100644 trunk/3rdparty/openssl-1.1-fit/fuzz/README.md create mode 100644 trunk/3rdparty/openssl-1.1-fit/fuzz/asn1.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/fuzz/asn1parse.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/fuzz/bignum.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/fuzz/bndiv.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/fuzz/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/fuzz/client.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/fuzz/cms.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/fuzz/conf.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/fuzz/crl.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/fuzz/ct.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/fuzz/driver.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/fuzz/fuzzer.h create mode 100755 trunk/3rdparty/openssl-1.1-fit/fuzz/helper.py create mode 100755 trunk/3rdparty/openssl-1.1-fit/fuzz/mkfuzzoids.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/fuzz/oids.txt create mode 100644 trunk/3rdparty/openssl-1.1-fit/fuzz/rand.inc create mode 100644 trunk/3rdparty/openssl-1.1-fit/fuzz/server.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/fuzz/test-corpus.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/fuzz/x509.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/internal/__DECC_INCLUDE_EPILOGUE.H create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/internal/__DECC_INCLUDE_PROLOGUE.H create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/internal/bio.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/internal/comp.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/internal/conf.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/internal/constant_time_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/internal/cryptlib.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/internal/dane.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/internal/dso.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/internal/dsoerr.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/internal/err.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/internal/nelem.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/internal/numbers.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/internal/o_dir.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/internal/o_str.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/internal/refcount.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/internal/sockets.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/internal/sslconf.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/internal/thread_once.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/internal/tsan_assist.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/__DECC_INCLUDE_EPILOGUE.H create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/__DECC_INCLUDE_PROLOGUE.H create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/aes.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/asn1.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/asn1_mac.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/asn1err.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/asn1t.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/async.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/asyncerr.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/bio.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/bioerr.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/blowfish.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/bn.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/bnerr.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/buffer.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/buffererr.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/camellia.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/cast.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/cmac.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/cms.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/cmserr.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/comp.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/comperr.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/conf.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/conf_api.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/conferr.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/crypto.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/cryptoerr.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/ct.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/cterr.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/des.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/dh.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/dherr.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/dsa.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/dsaerr.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/dtls1.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/e_os2.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/ebcdic.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/ec.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/ecdh.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/ecdsa.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/ecerr.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/engine.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/engineerr.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/err.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/evp.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/evperr.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/hmac.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/idea.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/kdf.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/kdferr.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/lhash.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/md2.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/md4.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/md5.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/mdc2.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/modes.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/obj_mac.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/objects.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/objectserr.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/ocsp.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/ocsperr.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/opensslconf.h.in create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/opensslv.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/ossl_typ.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/pem.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/pem2.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/pemerr.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/pkcs12.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/pkcs12err.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/pkcs7.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/pkcs7err.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/rand.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/rand_drbg.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/randerr.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/rc2.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/rc4.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/rc5.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/ripemd.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/rsa.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/rsaerr.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/safestack.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/seed.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/sha.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/srp.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/srtp.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/ssl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/ssl2.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/ssl3.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/sslerr.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/stack.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/store.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/storeerr.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/symhacks.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/tls1.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/ts.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/tserr.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/txt_db.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/ui.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/uierr.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/whrlpool.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/x509.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/x509_vfy.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/x509err.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/x509v3.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/include/openssl/x509v3err.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/ms/applink.c create mode 100755 trunk/3rdparty/openssl-1.1-fit/ms/cmp.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/ms/uplink-common.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/ms/uplink-ia64.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/ms/uplink-x86.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/ms/uplink-x86_64.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/ms/uplink.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ms/uplink.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/os-dep/haiku.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/bio_ssl.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/d1_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/d1_msg.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/d1_srtp.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/methods.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/packet.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/packet_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/pqueue.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/record/README create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/record/dtls1_bitmap.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/record/rec_layer_d1.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/record/rec_layer_s3.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/record/record.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/record/record_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/record/ssl3_buffer.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/record/ssl3_record.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/record/ssl3_record_tls13.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/s3_cbc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/s3_enc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/s3_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/s3_msg.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/ssl_asn1.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/ssl_cert.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/ssl_cert_table.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/ssl_ciph.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/ssl_conf.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/ssl_err.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/ssl_init.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/ssl_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/ssl_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/ssl_mcnf.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/ssl_rsa.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/ssl_sess.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/ssl_stat.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/ssl_txt.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/ssl_utst.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/statem/README create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/statem/extensions.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/statem/extensions_clnt.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/statem/extensions_cust.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/statem/extensions_srvr.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_clnt.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_dtls.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_locl.h create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_srvr.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/t1_enc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/t1_lib.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/t1_trce.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/tls13_enc.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/ssl/tls_srp.c create mode 100644 trunk/3rdparty/openssl-1.1-fit/tools/build.info create mode 100644 trunk/3rdparty/openssl-1.1-fit/tools/c_rehash.in create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/add-depends.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/build.info create mode 100755 trunk/3rdparty/openssl-1.1-fit/util/check-malloc-errs create mode 100755 trunk/3rdparty/openssl-1.1-fit/util/ck_errf.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/copy.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/dofile.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/echo.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/util/find-doc-nits create mode 100755 trunk/3rdparty/openssl-1.1-fit/util/find-unused-errs create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/indent.pro create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/libcrypto.num create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/libssl.num create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/local_shlib.com.in create mode 100755 trunk/3rdparty/openssl-1.1-fit/util/mkbuildinf.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/util/mkdef.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/util/mkdir-p.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/util/mkerr.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/util/mkrc.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/util/openssl-format-source create mode 100755 trunk/3rdparty/openssl-1.1-fit/util/openssl-update-copyright create mode 100755 trunk/3rdparty/openssl-1.1-fit/util/opensslwrap.sh create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/perl/OpenSSL/Glob.pm create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/perl/OpenSSL/Test.pm create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/perl/OpenSSL/Test/Simple.pm create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/perl/OpenSSL/Test/Utils.pm create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/perl/OpenSSL/Util/Pod.pm create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/Alert.pm create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/Certificate.pm create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/CertificateVerify.pm create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/ClientHello.pm create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/EncryptedExtensions.pm create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/Message.pm create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/NewSessionTicket.pm create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/Proxy.pm create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/Record.pm create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/ServerHello.pm create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/ServerKeyExchange.pm create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/perl/checkhandshake.pm create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/perl/with_fallback.pm create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/private.num create mode 100755 trunk/3rdparty/openssl-1.1-fit/util/process_docs.pl create mode 100755 trunk/3rdparty/openssl-1.1-fit/util/shlib_wrap.sh.in create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/su-filter.pl create mode 100644 trunk/3rdparty/openssl-1.1-fit/util/unlocal_shlib.com.in delete mode 100644 trunk/3rdparty/openssl-1.1.0e.zip diff --git a/README.md b/README.md index a9bed81fd..5dbb1013a 100755 --- a/README.md +++ b/README.md @@ -156,6 +156,7 @@ For previous versions, please read: ## V4 changes +* v4.0, 2021-03-01, Upgrade openssl from 1.1.0e to 1.1.1b, with source code. 4.0.78 * v4.0, 2021-03-01, Enable Object Cache and Zero Copy Nack by default. 4.0.77 * v4.0, 2021-02-28, RTC: Support high performance [Zero Copy NACK](https://github.com/ossrs/srs/commit/36ea67359e55c94ab044cee4b6a4ec901a83a287#commitcomment-47654868). 4.0.76 * v4.0, 2021-02-27, RTC: Support [Object Cache Pool](https://github.com/ossrs/srs/commit/14bfc98122bba369572417c19ebb2a61b373fc45#commitcomment-47655008) for performance. 4.0.75 diff --git a/trunk/3rdparty/openssl-1.1-fit/Configurations/00-base-templates.conf b/trunk/3rdparty/openssl-1.1-fit/Configurations/00-base-templates.conf new file mode 100644 index 000000000..5fd995cb3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/Configurations/00-base-templates.conf @@ -0,0 +1,356 @@ +# -*- Mode: perl -*- +my %targets=( + DEFAULTS => { + template => 1, + + cflags => "", + cppflags => "", + lflags => "", + defines => [], + includes => [], + lib_cflags => "", + lib_cppflags => "", + lib_defines => [], + thread_scheme => "(unknown)", # Assume we don't know + thread_defines => [], + + apps_aux_src => "", + apps_init_src => "", + cpuid_asm_src => "mem_clr.c", + uplink_aux_src => "", + bn_asm_src => "bn_asm.c", + ec_asm_src => "", + des_asm_src => "des_enc.c fcrypt_b.c", + aes_asm_src => "aes_core.c aes_cbc.c", + bf_asm_src => "bf_enc.c", + md5_asm_src => "", + cast_asm_src => "c_enc.c", + rc4_asm_src => "rc4_enc.c rc4_skey.c", + rmd160_asm_src => "", + rc5_asm_src => "rc5_enc.c", + wp_asm_src => "wp_block.c", + cmll_asm_src => "camellia.c cmll_misc.c cmll_cbc.c", + modes_asm_src => "", + padlock_asm_src => "", + chacha_asm_src => "chacha_enc.c", + poly1305_asm_src => "", + keccak1600_asm_src => "keccak1600.c", + + unistd => "", + shared_target => "", + shared_cflag => "", + shared_defines => [], + shared_ldflag => "", + shared_rcflag => "", + shared_extension => "", + + #### Defaults for the benefit of the config targets who don't inherit + #### a BASE and assume Unix defaults + #### THESE WILL DISAPPEAR IN OpenSSL 1.2 + build_scheme => [ "unified", "unix" ], + build_file => "Makefile", + + AR => "ar", + ARFLAGS => "r", + CC => "cc", + HASHBANGPERL => "/usr/bin/env perl", + RANLIB => sub { which("$config{cross_compile_prefix}ranlib") + ? "ranlib" : "" }, + RC => "windres", + + #### THESE WILL BE ENABLED IN OpenSSL 1.2 + #HASHBANGPERL => "PERL", # Only Unix actually cares + }, + + BASE_common => { + template => 1, + + enable => [], + disable => [], + + defines => + sub { + my @defs = (); + push @defs, "ZLIB" unless $disabled{zlib}; + push @defs, "ZLIB_SHARED" unless $disabled{"zlib-dynamic"}; + return [ @defs ]; + }, + includes => + sub { + my @incs = (); + push @incs, $withargs{zlib_include} + if !$disabled{zlib} && $withargs{zlib_include}; + return [ @incs ]; + }, + }, + + BASE_unix => { + inherit_from => [ "BASE_common" ], + template => 1, + + AR => "ar", + ARFLAGS => "r", + CC => "cc", + lflags => + sub { $withargs{zlib_lib} ? "-L".$withargs{zlib_lib} : () }, + ex_libs => + sub { !defined($disabled{zlib}) + && defined($disabled{"zlib-dynamic"}) + ? "-lz" : () }, + HASHBANGPERL => "/usr/bin/env perl", # Only Unix actually cares + RANLIB => sub { which("$config{cross_compile_prefix}ranlib") + ? "ranlib" : "" }, + RC => "windres", + + shared_extension => ".so", + + build_scheme => [ "unified", "unix" ], + build_file => "Makefile", + }, + + BASE_Windows => { + inherit_from => [ "BASE_common" ], + template => 1, + + lib_defines => + sub { + my @defs = (); + unless ($disabled{"zlib-dynamic"}) { + my $zlib = $withargs{zlib_lib} // "ZLIB1"; + push @defs, 'LIBZ=' . (quotify("perl", $zlib))[0]; + } + return [ @defs ]; + }, + ex_libs => + sub { + unless ($disabled{zlib}) { + if (defined($disabled{"zlib-dynamic"})) { + return $withargs{zlib_lib} // "ZLIB1"; + } + } + return (); + }, + + LD => "link", + LDFLAGS => "/nologo", + ldoutflag => "/out:", + AR => "lib", + ARFLAGS => "/nologo", + aroutflag => "/out:", + RC => "rc", + rcoutflag => "/fo", + MT => "mt", + MTFLAGS => "-nologo", + mtinflag => "-manifest ", + mtoutflag => "-outputresource:", + + shared_extension => ".dll", + + build_file => "makefile", + build_scheme => [ "unified", "windows" ], + }, + + BASE_VMS => { + inherit_from => [ "BASE_common" ], + template => 1, + + includes => + add(sub { + my @incs = (); + # GNV$ZLIB_INCLUDE is the standard logical name for later + # zlib incarnations. + push @incs, 'GNV$ZLIB_INCLUDE:' + if !$disabled{zlib} && !$withargs{zlib_include}; + return [ @incs ]; + }), + + shared_extension => ".exe", + + build_file => "descrip.mms", + build_scheme => [ "unified", "VMS" ], + }, + + uplink_common => { + template => 1, + apps_init_src => add("../ms/applink.c"), + uplink_aux_src => add("../ms/uplink.c"), + defines => add("OPENSSL_USE_APPLINK"), + }, + x86_uplink => { + inherit_from => [ "uplink_common" ], + template => 1, + uplink_aux_src => add("uplink-x86.s"), + }, + x86_64_uplink => { + inherit_from => [ "uplink_common" ], + template => 1, + uplink_aux_src => add("uplink-x86_64.s"), + }, + ia64_uplink => { + inherit_from => [ "uplink_common" ], + template => 1, + uplink_aux_src => add("uplink-ia64.s"), + }, + + x86_asm => { + template => 1, + cpuid_asm_src => "x86cpuid.s", + bn_asm_src => "bn-586.s co-586.s x86-mont.s x86-gf2m.s", + ec_asm_src => "ecp_nistz256.c ecp_nistz256-x86.s", + des_asm_src => "des-586.s crypt586.s", + aes_asm_src => "aes-586.s vpaes-x86.s aesni-x86.s", + bf_asm_src => "bf-586.s", + md5_asm_src => "md5-586.s", + cast_asm_src => "cast-586.s", + sha1_asm_src => "sha1-586.s sha256-586.s sha512-586.s", + rc4_asm_src => "rc4-586.s", + rmd160_asm_src => "rmd-586.s", + rc5_asm_src => "rc5-586.s", + wp_asm_src => "wp_block.c wp-mmx.s", + cmll_asm_src => "cmll-x86.s", + modes_asm_src => "ghash-x86.s", + padlock_asm_src => "e_padlock-x86.s", + chacha_asm_src => "chacha-x86.s", + poly1305_asm_src=> "poly1305-x86.s", + }, + x86_elf_asm => { + template => 1, + inherit_from => [ "x86_asm" ], + perlasm_scheme => "elf" + }, + x86_64_asm => { + template => 1, + cpuid_asm_src => "x86_64cpuid.s", + bn_asm_src => "asm/x86_64-gcc.c x86_64-mont.s x86_64-mont5.s x86_64-gf2m.s rsaz_exp.c rsaz-x86_64.s rsaz-avx2.s", + ec_asm_src => "ecp_nistz256.c ecp_nistz256-x86_64.s x25519-x86_64.s", + aes_asm_src => "aes-x86_64.s vpaes-x86_64.s bsaes-x86_64.s aesni-x86_64.s aesni-sha1-x86_64.s aesni-sha256-x86_64.s aesni-mb-x86_64.s", + md5_asm_src => "md5-x86_64.s", + sha1_asm_src => "sha1-x86_64.s sha256-x86_64.s sha512-x86_64.s sha1-mb-x86_64.s sha256-mb-x86_64.s", + rc4_asm_src => "rc4-x86_64.s rc4-md5-x86_64.s", + wp_asm_src => "wp-x86_64.s", + cmll_asm_src => "cmll-x86_64.s cmll_misc.c", + modes_asm_src => "ghash-x86_64.s aesni-gcm-x86_64.s", + padlock_asm_src => "e_padlock-x86_64.s", + chacha_asm_src => "chacha-x86_64.s", + poly1305_asm_src=> "poly1305-x86_64.s", + keccak1600_asm_src => "keccak1600-x86_64.s", + }, + ia64_asm => { + template => 1, + cpuid_asm_src => "ia64cpuid.s", + bn_asm_src => "bn-ia64.s ia64-mont.s", + aes_asm_src => "aes_core.c aes_cbc.c aes-ia64.s", + sha1_asm_src => "sha1-ia64.s sha256-ia64.s sha512-ia64.s", + modes_asm_src => "ghash-ia64.s", + perlasm_scheme => "void" + }, + sparcv9_asm => { + template => 1, + cpuid_asm_src => "sparcv9cap.c sparccpuid.S", + bn_asm_src => "asm/sparcv8plus.S sparcv9-mont.S sparcv9a-mont.S vis3-mont.S sparct4-mont.S sparcv9-gf2m.S", + ec_asm_src => "ecp_nistz256.c ecp_nistz256-sparcv9.S", + des_asm_src => "des_enc-sparc.S fcrypt_b.c dest4-sparcv9.S", + aes_asm_src => "aes_core.c aes_cbc.c aes-sparcv9.S aest4-sparcv9.S aesfx-sparcv9.S", + md5_asm_src => "md5-sparcv9.S", + sha1_asm_src => "sha1-sparcv9.S sha256-sparcv9.S sha512-sparcv9.S", + cmll_asm_src => "camellia.c cmll_misc.c cmll_cbc.c cmllt4-sparcv9.S", + modes_asm_src => "ghash-sparcv9.S", + poly1305_asm_src=> "poly1305-sparcv9.S", + perlasm_scheme => "void" + }, + sparcv8_asm => { + template => 1, + cpuid_asm_src => "", + bn_asm_src => "asm/sparcv8.S", + des_asm_src => "des_enc-sparc.S fcrypt_b.c", + perlasm_scheme => "void" + }, + alpha_asm => { + template => 1, + cpuid_asm_src => "alphacpuid.s", + bn_asm_src => "bn_asm.c alpha-mont.S", + sha1_asm_src => "sha1-alpha.S", + modes_asm_src => "ghash-alpha.S", + perlasm_scheme => "void" + }, + mips32_asm => { + template => 1, + bn_asm_src => "bn-mips.S mips-mont.S", + aes_asm_src => "aes_cbc.c aes-mips.S", + sha1_asm_src => "sha1-mips.S sha256-mips.S", + }, + mips64_asm => { + inherit_from => [ "mips32_asm" ], + template => 1, + sha1_asm_src => add("sha512-mips.S"), + poly1305_asm_src=> "poly1305-mips.S", + }, + s390x_asm => { + template => 1, + cpuid_asm_src => "s390xcap.c s390xcpuid.S", + bn_asm_src => "asm/s390x.S s390x-mont.S s390x-gf2m.s", + aes_asm_src => "aes-s390x.S aes-ctr.fake aes-xts.fake", + sha1_asm_src => "sha1-s390x.S sha256-s390x.S sha512-s390x.S", + rc4_asm_src => "rc4-s390x.s", + modes_asm_src => "ghash-s390x.S", + chacha_asm_src => "chacha-s390x.S", + poly1305_asm_src=> "poly1305-s390x.S", + keccak1600_asm_src => "keccak1600-s390x.S", + }, + armv4_asm => { + template => 1, + cpuid_asm_src => "armcap.c armv4cpuid.S", + bn_asm_src => "bn_asm.c armv4-mont.S armv4-gf2m.S", + ec_asm_src => "ecp_nistz256.c ecp_nistz256-armv4.S", + aes_asm_src => "aes_cbc.c aes-armv4.S bsaes-armv7.S aesv8-armx.S", + sha1_asm_src => "sha1-armv4-large.S sha256-armv4.S sha512-armv4.S", + modes_asm_src => "ghash-armv4.S ghashv8-armx.S", + chacha_asm_src => "chacha-armv4.S", + poly1305_asm_src=> "poly1305-armv4.S", + keccak1600_asm_src => "keccak1600-armv4.S", + perlasm_scheme => "void" + }, + aarch64_asm => { + template => 1, + cpuid_asm_src => "armcap.c arm64cpuid.S", + ec_asm_src => "ecp_nistz256.c ecp_nistz256-armv8.S", + bn_asm_src => "bn_asm.c armv8-mont.S", + aes_asm_src => "aes_core.c aes_cbc.c aesv8-armx.S vpaes-armv8.S", + sha1_asm_src => "sha1-armv8.S sha256-armv8.S sha512-armv8.S", + modes_asm_src => "ghashv8-armx.S", + chacha_asm_src => "chacha-armv8.S", + poly1305_asm_src=> "poly1305-armv8.S", + keccak1600_asm_src => "keccak1600-armv8.S", + }, + parisc11_asm => { + template => 1, + cpuid_asm_src => "pariscid.s", + bn_asm_src => "bn_asm.c parisc-mont.s", + aes_asm_src => "aes_core.c aes_cbc.c aes-parisc.s", + sha1_asm_src => "sha1-parisc.s sha256-parisc.s sha512-parisc.s", + rc4_asm_src => "rc4-parisc.s", + modes_asm_src => "ghash-parisc.s", + perlasm_scheme => "32" + }, + parisc20_64_asm => { + template => 1, + inherit_from => [ "parisc11_asm" ], + perlasm_scheme => "64", + }, + ppc32_asm => { + template => 1, + cpuid_asm_src => "ppccpuid.s ppccap.c", + bn_asm_src => "bn-ppc.s ppc-mont.s", + aes_asm_src => "aes_core.c aes_cbc.c aes-ppc.s vpaes-ppc.s aesp8-ppc.s", + sha1_asm_src => "sha1-ppc.s sha256-ppc.s sha512-ppc.s sha256p8-ppc.s sha512p8-ppc.s", + modes_asm_src => "ghashp8-ppc.s", + chacha_asm_src => "chacha-ppc.s", + poly1305_asm_src=> "poly1305-ppc.s poly1305-ppcfp.s", + }, + ppc64_asm => { + inherit_from => [ "ppc32_asm" ], + template => 1, + ec_asm_src => "ecp_nistz256.c ecp_nistz256-ppc64.s x25519-ppc64.s", + keccak1600_asm_src => "keccak1600-ppc64.s", + }, +); diff --git a/trunk/3rdparty/openssl-1.1-fit/Configurations/10-main.conf b/trunk/3rdparty/openssl-1.1-fit/Configurations/10-main.conf new file mode 100644 index 000000000..930f2d3c9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/Configurations/10-main.conf @@ -0,0 +1,1802 @@ +## -*- mode: perl; -*- +## Standard openssl configuration targets. + +# Helper functions for the Windows configs +my $vc_win64a_info = {}; +sub vc_win64a_info { + unless (%$vc_win64a_info) { + if (`nasm -v 2>NUL` =~ /NASM version ([0-9]+\.[0-9]+)/ && $1 >= 2.0) { + $vc_win64a_info = { AS => "nasm", + ASFLAGS => "-g", + asflags => "-Ox -f win64 -DNEAR", + asoutflag => "-o " }; + } elsif ($disabled{asm}) { + # assembler is still used to compile uplink shim + $vc_win64a_info = { AS => "ml64", + ASFLAGS => "/nologo /Zi", + asflags => "/c /Cp /Cx", + asoutflag => "/Fo" }; + } else { + $die->("NASM not found - make sure it's installed and available on %PATH%\n"); + $vc_win64a_info = { AS => "{unknown}", + ASFLAGS => "", + asflags => "", + asoutflag => "" }; + } + } + return $vc_win64a_info; +} + +my $vc_win32_info = {}; +sub vc_win32_info { + unless (%$vc_win32_info) { + my $ver=`nasm -v 2>NUL`; + my $vew=`nasmw -v 2>NUL`; + if ($ver ne "" || $vew ne "") { + $vc_win32_info = { AS => $ver ge $vew ? "nasm" : "nasmw", + ASFLAGS => "", + asflags => "-f win32", + asoutflag => "-o ", + perlasm_scheme => "win32n" }; + } elsif ($disabled{asm}) { + # not actually used, uplink shim is inlined into C code + $vc_win32_info = { AS => "ml", + ASFLAGS => "/nologo /Zi", + asflags => "/Cp /coff /c /Cx", + asoutflag => "/Fo", + perlasm_scheme => "win32" }; + } else { + $die->("NASM not found - make sure it's installed and available on %PATH%\n"); + $vc_win32_info = { AS => "{unknown}", + ASFLAGS => "", + asflags => "", + asoutflag => "", + perlasm_scheme => "win32" }; + } + } + return $vc_win32_info; +} + +my $vc_wince_info = {}; +sub vc_wince_info { + unless (%$vc_wince_info) { + # sanity check + $die->('%OSVERSION% is not defined') if (!defined(env('OSVERSION'))); + $die->('%PLATFORM% is not defined') if (!defined(env('PLATFORM'))); + $die->('%TARGETCPU% is not defined') if (!defined(env('TARGETCPU'))); + + # + # Idea behind this is to mimic flags set by eVC++ IDE... + # + my $wcevers = env('OSVERSION'); # WCENNN + my $wcevernum; + my $wceverdotnum; + if ($wcevers =~ /^WCE([1-9])([0-9]{2})$/) { + $wcevernum = "$1$2"; + $wceverdotnum = "$1.$2"; + } else { + $die->('%OSVERSION% value is insane'); + $wcevernum = "{unknown}"; + $wceverdotnum = "{unknown}"; + } + my $wcecdefs = "-D_WIN32_WCE=$wcevernum -DUNDER_CE=$wcevernum"; # -D_WIN32_WCE=NNN + my $wcelflag = "/subsystem:windowsce,$wceverdotnum"; # ...,N.NN + + my $wceplatf = env('PLATFORM'); + + $wceplatf =~ tr/a-z0-9 /A-Z0-9_/; + $wcecdefs .= " -DWCE_PLATFORM_$wceplatf"; + + my $wcetgt = env('TARGETCPU'); # just shorter name... + SWITCH: for($wcetgt) { + /^X86/ && do { $wcecdefs.=" -Dx86 -D_X86_ -D_i386_ -Di_386_"; + $wcelflag.=" /machine:X86"; last; }; + /^ARMV4[IT]/ && do { $wcecdefs.=" -DARM -D_ARM_ -D$wcetgt"; + $wcecdefs.=" -DTHUMB -D_THUMB_" if($wcetgt=~/T$/); + $wcecdefs.=" -QRarch4T -QRinterwork-return"; + $wcelflag.=" /machine:THUMB"; last; }; + /^ARM/ && do { $wcecdefs.=" -DARM -D_ARM_ -D$wcetgt"; + $wcelflag.=" /machine:ARM"; last; }; + /^MIPSIV/ && do { $wcecdefs.=" -DMIPS -D_MIPS_ -DR4000 -D$wcetgt"; + $wcecdefs.=" -D_MIPS64 -QMmips4 -QMn32"; + $wcelflag.=" /machine:MIPSFPU"; last; }; + /^MIPS16/ && do { $wcecdefs.=" -DMIPS -D_MIPS_ -DR4000 -D$wcetgt"; + $wcecdefs.=" -DMIPSII -QMmips16"; + $wcelflag.=" /machine:MIPS16"; last; }; + /^MIPSII/ && do { $wcecdefs.=" -DMIPS -D_MIPS_ -DR4000 -D$wcetgt"; + $wcecdefs.=" -QMmips2"; + $wcelflag.=" /machine:MIPS"; last; }; + /^R4[0-9]{3}/ && do { $wcecdefs.=" -DMIPS -D_MIPS_ -DR4000"; + $wcelflag.=" /machine:MIPS"; last; }; + /^SH[0-9]/ && do { $wcecdefs.=" -D$wcetgt -D_${wcetgt}_ -DSHx"; + $wcecdefs.=" -Qsh4" if ($wcetgt =~ /^SH4/); + $wcelflag.=" /machine:$wcetgt"; last; }; + { $wcecdefs.=" -D$wcetgt -D_${wcetgt}_"; + $wcelflag.=" /machine:$wcetgt"; last; }; + } + + $vc_wince_info = { cppflags => $wcecdefs, + lflags => $wcelflag }; + } + return $vc_wince_info; +} + +# Helper functions for the VMS configs +my $vms_info = {}; +sub vms_info { + my $pointer_size_str = $config{target} =~ m|-p(\d+)$| ? $1 : ""; + + # For the case where Configure iterate through all config targets, such + # as when listing them and their details, we reset info if the pointer + # size changes. + if (%$vms_info && $vms_info->{pointer_size} ne $pointer_size_str) { + $vms_info = {}; + } + + unless (%$vms_info) { + $vms_info->{disable_warns} = [ ]; + $vms_info->{pointer_size} = $pointer_size_str; + if ($pointer_size_str eq "64") { + `PIPE CC /NOCROSS_REFERENCE /NOLIST /NOOBJECT /WARNINGS = DISABLE = ( MAYLOSEDATA3, EMPTYFILE ) NL: 2> NL:`; + if ($? == 0) { + push @{$vms_info->{disable_warns}}, "MAYLOSEDATA3"; + } + } + + unless ($disabled{zlib}) { + my $default_zlib = 'GNV$LIBZSHR' . $pointer_size_str; + if (defined($disabled{"zlib-dynamic"})) { + $vms_info->{zlib} = $withargs{zlib_lib} || "$default_zlib/SHARE"; + } else { + $vms_info->{def_zlib} = $withargs{zlib_lib} || $default_zlib; + # In case the --with-zlib-lib value contains something like + # /SHARE or /LIB or so at the end, remove it. + $vms_info->{def_zlib} =~ s|/.*$||g; + } + } + + if ($config{target} =~ /-ia64/) { + `PIPE ias -H 2> NL:`; + if ($? == 0) { + $vms_info->{AS} = "ias"; + $vms_info->{ASFLAGS} = '-d debug'; + $vms_info->{asflags} = '"-N" vms_upcase'; + $vms_info->{asoutflag} = "-o "; + $vms_info->{perlasm_scheme} = "ias"; + } + } + } + return $vms_info; +} + +my %targets = ( + +#### Basic configs that should work on any 32-bit box + "gcc" => { + inherit_from => [ "BASE_unix" ], + CC => "gcc", + CFLAGS => picker(debug => "-O0 -g", + release => "-O3"), + thread_scheme => "(unknown)", + bn_ops => "BN_LLONG", + }, + "cc" => { + inherit_from => [ "BASE_unix" ], + CC => "cc", + CFLAGS => "-O", + thread_scheme => "(unknown)", + }, + +#### VOS Configurations + "vos-gcc" => { + inherit_from => [ "BASE_unix" ], + CC => "gcc", + CFLAGS => picker(default => "-Wall", + debug => "-O0 -g", + release => "-O3"), + cppflags => "-D_POSIX_C_SOURCE=200112L -D_BSD -D_VOS_EXTENDED_NAMES", + lib_cppflags => "-DB_ENDIAN", + thread_scheme => "(unknown)", + sys_id => "VOS", + lflags => add("-Wl,-map"), + bn_ops => "BN_LLONG", + shared_extension => ".so", + }, + +#### Solaris configurations + "solaris-common" => { + inherit_from => [ "BASE_unix" ], + template => 1, + lib_cppflags => "-DFILIO_H", + ex_libs => add("-lsocket -lnsl -ldl"), + dso_scheme => "dlfcn", + thread_scheme => "pthreads", + shared_target => "self", + shared_extension => ".so.\$(SHLIB_VERSION_NUMBER)", + shared_ldflag => "-Wl,-Bsymbolic", + shared_defflag => "-Wl,-M,", + shared_sonameflag=> "-Wl,-h,", + }, +#### Solaris x86 with GNU C setups + "solaris-x86-gcc" => { + # NB. GNU C has to be configured to use GNU assembler, and not + # /usr/ccs/bin/as. Failure to comply will result in compile + # failures [at least] in 32-bit build. + inherit_from => [ "solaris-common", asm("x86_elf_asm") ], + CC => "gcc", + CFLAGS => add_before(picker(default => "-Wall", + debug => "-O0 -g", + release => "-O3 -fomit-frame-pointer")), + cflags => add(threads("-pthread")), + lib_cppflags => add("-DL_ENDIAN"), + ex_libs => add(threads("-pthread")), + bn_ops => "BN_LLONG", + shared_cflag => "-fPIC", + shared_ldflag => add_before("-shared -static-libgcc"), + }, + "solaris64-x86_64-gcc" => { + # -shared -static-libgcc might appear controversial, but modules + # taken from static libgcc do not have relocations and linking + # them into our shared objects doesn't have any negative side + # effects. On the contrary, doing so makes it possible to use + # gcc shared build with Sun C. Given that gcc generates faster + # code [thanks to inline assembler], I would actually recommend + # to consider using gcc shared build even with vendor compiler:-) + # -- + inherit_from => [ "solaris-common", asm("x86_64_asm") ], + CC => "gcc", + CFLAGS => add_before(picker(default => "-Wall", + debug => "-O0 -g", + release => "-O3")), + cflags => add_before("-m64", threads("-pthread")), + lib_cppflags => add("-DL_ENDIAN"), + ex_libs => add(threads("-pthread")), + bn_ops => "SIXTY_FOUR_BIT_LONG", + perlasm_scheme => "elf", + shared_cflag => "-fPIC", + shared_ldflag => add_before("-shared -static-libgcc"), + multilib => "/64", + }, + +#### Solaris x86 with Sun C setups + # There used to be solaris-x86-cc target, but it was removed, + # primarily because vendor assembler can't assemble our modules + # with -KPIC flag. As result it, assembly support, was not even + # available as option. But its lack means lack of side-channel + # resistant code, which is incompatible with security by todays + # standards. Fortunately gcc is readily available prepackaged + # option, which we can firmly point at... + # + # On related note, solaris64-x86_64-cc target won't compile code + # paths utilizing AVX and post-Haswell instruction extensions. + # Consider switching to solaris64-x86_64-gcc even here... + # + "solaris64-x86_64-cc" => { + inherit_from => [ "solaris-common", asm("x86_64_asm") ], + CC => "cc", + CFLAGS => add_before(picker(debug => "-g", + release => "-xO5 -xdepend -xbuiltin")), + cflags => add_before("-xarch=generic64 -xstrconst -Xa"), + cppflags => add(threads("-D_REENTRANT")), + lib_cppflags => add("-DL_ENDIAN"), + thread_scheme => "pthreads", + lflags => add(threads("-mt")), + ex_libs => add(threads("-lpthread")), + bn_ops => "SIXTY_FOUR_BIT_LONG", + perlasm_scheme => "elf", + shared_cflag => "-KPIC", + shared_ldflag => add_before("-G -dy -z text"), + multilib => "/64", + }, + +#### SPARC Solaris with GNU C setups + "solaris-sparcv7-gcc" => { + inherit_from => [ "solaris-common" ], + CC => "gcc", + CFLAGS => add_before(picker(default => "-Wall", + debug => "-O0 -g", + release => "-O3")), + cflags => add(threads("-pthread")), + lib_cppflags => add("-DB_ENDIAN -DBN_DIV2W"), + ex_libs => add(threads("-pthread")), + bn_ops => "BN_LLONG RC4_CHAR", + shared_cflag => "-fPIC", + shared_ldflag => add_before("-shared"), + }, + "solaris-sparcv8-gcc" => { + inherit_from => [ "solaris-sparcv7-gcc", asm("sparcv8_asm") ], + cflags => add_before("-mcpu=v8"), + }, + "solaris-sparcv9-gcc" => { + # -m32 should be safe to add as long as driver recognizes + # -mcpu=ultrasparc + inherit_from => [ "solaris-sparcv7-gcc", asm("sparcv9_asm") ], + cflags => add_before("-m32 -mcpu=ultrasparc"), + }, + "solaris64-sparcv9-gcc" => { + inherit_from => [ "solaris-sparcv9-gcc" ], + cflags => sub { my $f=join(" ",@_); $f =~ s/\-m32/-m64/; $f; }, + bn_ops => "BN_LLONG RC4_CHAR", + multilib => "/64", + }, + +#### SPARC Solaris with Sun C setups +# SC4.0 doesn't pass 'make test', upgrade to SC5.0 or SC4.2. +# SC4.2 is ok, better than gcc even on bn as long as you tell it -xarch=v8 +# SC5.0 note: Compiler common patch 107357-01 or later is required! + "solaris-sparcv7-cc" => { + inherit_from => [ "solaris-common" ], + CC => "cc", + CFLAGS => add_before(picker(debug => "-g", + release => "-xO5 -xdepend")), + cflags => add_before("-xstrconst -Xa"), + cppflags => add(threads("-D_REENTRANT")), + lib_cppflags => add("-DB_ENDIAN -DBN_DIV2W"), + lflags => add(threads("-mt")), + ex_libs => add(threads("-lpthread")), + bn_ops => "BN_LLONG RC4_CHAR", + shared_cflag => "-KPIC", + shared_ldflag => add_before("-G -dy -z text"), + }, +#### + "solaris-sparcv8-cc" => { + inherit_from => [ "solaris-sparcv7-cc", asm("sparcv8_asm") ], + cflags => add_before("-xarch=v8"), + }, + "solaris-sparcv9-cc" => { + inherit_from => [ "solaris-sparcv7-cc", asm("sparcv9_asm") ], + cflags => add_before("-xarch=v8plus"), + }, + "solaris64-sparcv9-cc" => { + inherit_from => [ "solaris-sparcv7-cc", asm("sparcv9_asm") ], + cflags => add_before("-xarch=v9"), + bn_ops => "BN_LLONG RC4_CHAR", + multilib => "/64", + }, + +#### IRIX 6.x configs +# Only N32 and N64 ABIs are supported. + "irix-common" => { + inherit_from => [ "BASE_unix" ], + template => 1, + cppflags => threads("-D_SGI_MP_SOURCE"), + lib_cppflags => "-DB_ENDIAN", + ex_libs => add(threads("-lpthread")), + thread_scheme => "pthreads", + dso_scheme => "dlfcn", + shared_target => "self", + shared_extension => ".so.\$(SHLIB_VERSION_NUMBER)", + shared_ldflag => "-shared -Wl,-Bsymbolic", + shared_sonameflag=> "-Wl,-soname,", + }, + "irix-mips3-gcc" => { + inherit_from => [ "irix-common", asm("mips64_asm") ], + CC => "gcc", + CFLAGS => picker(debug => "-g -O0", + release => "-O3"), + LDFLAGS => "-static-libgcc", + cflags => "-mabi=n32", + bn_ops => "RC4_CHAR SIXTY_FOUR_BIT", + perlasm_scheme => "n32", + multilib => "32", + }, + "irix-mips3-cc" => { + inherit_from => [ "irix-common", asm("mips64_asm") ], + CC => "cc", + CFLAGS => picker(debug => "-g -O0", + release => "-O2"), + cflags => "-n32 -mips3 -use_readonly_const -G0 -rdata_shared", + bn_ops => "RC4_CHAR SIXTY_FOUR_BIT", + perlasm_scheme => "n32", + multilib => "32", + }, + # N64 ABI builds. + "irix64-mips4-gcc" => { + inherit_from => [ "irix-common", asm("mips64_asm") ], + CC => "gcc", + CFLAGS => picker(debug => "-g -O0", + release => "-O3"), + LDFLAGS => "-static-libgcc", + cflags => "-mabi=64 -mips4", + bn_ops => "RC4_CHAR SIXTY_FOUR_BIT_LONG", + perlasm_scheme => "64", + multilib => "64", + }, + "irix64-mips4-cc" => { + inherit_from => [ "irix-common", asm("mips64_asm") ], + CC => "cc", + CFLAGS => picker(debug => "-g -O0", + release => "-O2"), + cflags => "-64 -mips4 -use_readonly_const -G0 -rdata_shared", + bn_ops => "RC4_CHAR SIXTY_FOUR_BIT_LONG", + perlasm_scheme => "64", + multilib => "64", + }, + +#### Unified HP-UX ANSI C configs. +# Special notes: +# - Originally we were optimizing at +O4 level. It should be noted +# that the only difference between +O3 and +O4 is global inter- +# procedural analysis. As it has to be performed during the link +# stage the compiler leaves behind certain pseudo-code in lib*.a +# which might be release or even patch level specific. Generating +# the machine code for and analyzing the *whole* program appears +# to be *extremely* memory demanding while the performance gain is +# actually questionable. The situation is intensified by the default +# HP-UX data set size limit (infamous 'maxdsiz' tunable) of 64MB +# which is way too low for +O4. In other words, doesn't +O3 make +# more sense? +# - Keep in mind that the HP compiler by default generates code +# suitable for execution on the host you're currently compiling at. +# If the toolkit is meant to be used on various PA-RISC processors +# consider './Configure hpux-parisc-[g]cc +DAportable'. +# - -DMD32_XARRAY triggers workaround for compiler bug we ran into in +# 32-bit message digests. (For the moment of this writing) HP C +# doesn't seem to "digest" too many local variables (they make "him" +# chew forever:-). For more details look-up MD32_XARRAY comment in +# crypto/sha/sha_lcl.h. +# - originally there were 32-bit hpux-parisc2-* targets. They were +# scrapped, because a) they were not interchangeable with other 32-bit +# targets; b) performance-critical 32-bit assembly modules implement +# even PA-RISC 2.0-specific code paths, which are chosen at run-time, +# thus adequate performance is provided even with PA-RISC 1.1 build. + "hpux-common" => { + inherit_from => [ "BASE_unix" ], + template => 1, + defines => add("_XOPEN_SOURCE", "_XOPEN_SOURCE_EXTENDED", + "_HPUX_ALT_XOPEN_SOCKET_API"), + lib_cppflags => "-DB_ENDIAN", + thread_scheme => "pthreads", + dso_scheme => "dlfcn", # overridden in 32-bit PA-RISC builds + shared_target => "self", + bin_lflags => "-Wl,+s,+cdp,../:,+cdp,./:", + shared_ldflag => "-Wl,-B,symbolic,+vnocompatwarnings,-z,+s,+cdp,../:,+cdp,./:", + shared_sonameflag=> "-Wl,+h,", + }, + "hpux-parisc-gcc" => { + inherit_from => [ "hpux-common" ], + CC => "gcc", + CFLAGS => picker(debug => "-O0 -g", + release => "-O3"), + cflags => add(threads("-pthread")), + lib_cppflags => add("-DBN_DIV2W"), + ex_libs => add("-ldld", threads("-pthread")), + bn_ops => "BN_LLONG RC4_CHAR", + dso_scheme => "dl", + shared_cflag => "-fPIC", + shared_ldflag => add_before("-shared"), + shared_extension => ".sl.\$(SHLIB_VERSION_NUMBER)", + }, + "hpux-parisc1_1-gcc" => { + inherit_from => [ "hpux-parisc-gcc", asm("parisc11_asm") ], + multilib => "/pa1.1", + }, + "hpux64-parisc2-gcc" => { + inherit_from => [ "hpux-common", asm("parisc20_64_asm") ], + CC => "gcc", + CFLAGS => combine(picker(debug => "-O0 -g", + release => "-O3")), + cflags => add(threads("-pthread")), + ex_libs => add("-ldl", threads("-pthread")), + bn_ops => "SIXTY_FOUR_BIT_LONG RC4_CHAR", + shared_cflag => "-fpic", + shared_ldflag => add_before("-shared"), + shared_extension => ".sl.\$(SHLIB_VERSION_NUMBER)", + multilib => "/pa20_64", + }, + + # More attempts at unified 10.X and 11.X targets for HP C compiler. + "hpux-parisc-cc" => { + inherit_from => [ "hpux-common" ], + CC => "cc", + CFLAGS => picker(debug => "+O0 +d -g", + release => "+O3"), + cflags => "+Optrs_strongly_typed -Ae +ESlit", + cppflags => threads("-D_REENTRANT"), + lib_cppflags => add("-DBN_DIV2W -DMD32_XARRAY"), + ex_libs => add("-ldld", threads("-lpthread")), + bn_ops => "RC4_CHAR", + dso_scheme => "dl", + shared_cflag => "+Z", + shared_ldflag => add_before("-b"), + shared_extension => ".sl.\$(SHLIB_VERSION_NUMBER)", + }, + "hpux-parisc1_1-cc" => { + inherit_from => [ "hpux-parisc-cc", asm("parisc11_asm") ], + cflags => add_before("+DA1.1"), + multilib => "/pa1.1", + }, + "hpux64-parisc2-cc" => { + inherit_from => [ "hpux-common", asm("parisc20_64_asm") ], + CC => "cc", + CFLAGS => picker(debug => "+O0 +d -g", + release => "+O3") , + cflags => "+DD64 +Optrs_strongly_typed -Ae +ESlit", + cppflags => threads("-D_REENTRANT") , + lib_cppflags => add("-DMD32_XARRAY"), + ex_libs => add("-ldl", threads("-lpthread")), + bn_ops => "SIXTY_FOUR_BIT_LONG RC4_CHAR", + shared_cflag => "+Z", + shared_ldflag => add_before("-b"), + shared_extension => ".sl.\$(SHLIB_VERSION_NUMBER)", + multilib => "/pa20_64", + }, + + # HP/UX IA-64 targets + "hpux-ia64-cc" => { + inherit_from => [ "hpux-common", asm("ia64_asm") ], + CC => "cc", + CFLAGS => picker(debug => "+O0 +d -g", + release => "+O2"), + cflags => "-Ae +DD32 +Olit=all -z", + cppflags => add(threads("-D_REENTRANT")), + ex_libs => add("-ldl", threads("-lpthread")), + bn_ops => "SIXTY_FOUR_BIT", + shared_cflag => "+Z", + shared_ldflag => add_before("-b"), + shared_extension => ".so.\$(SHLIB_VERSION_NUMBER)", + multilib => "/hpux32", + }, + "hpux64-ia64-cc" => { + inherit_from => [ "hpux-common", asm("ia64_asm") ], + CC => "cc", + CFLAGS => picker(debug => "+O0 +d -g", + release => "+O3"), + cflags => "-Ae +DD64 +Olit=all -z", + cppflags => threads("-D_REENTRANT"), + ex_libs => add("-ldl", threads("-lpthread")), + bn_ops => "SIXTY_FOUR_BIT_LONG", + shared_cflag => "+Z", + shared_ldflag => add_before("-b"), + shared_extension => ".so.\$(SHLIB_VERSION_NUMBER)", + multilib => "/hpux64", + }, + # GCC builds... + "hpux-ia64-gcc" => { + inherit_from => [ "hpux-common", asm("ia64_asm") ], + CC => "gcc", + CFLAGS => picker(debug => "-O0 -g", + release => "-O3"), + cflags => add(threads("-pthread")), + ex_libs => add("-ldl", threads("-pthread")), + bn_ops => "SIXTY_FOUR_BIT", + shared_cflag => "-fpic", + shared_ldflag => add_before("-shared"), + shared_extension => ".so.\$(SHLIB_VERSION_NUMBER)", + multilib => "/hpux32", + }, + "hpux64-ia64-gcc" => { + inherit_from => [ "hpux-common", asm("ia64_asm") ], + CC => "gcc", + CFLAGS => picker(debug => "-O0 -g", + release => "-O3"), + cflags => combine("-mlp64", threads("-pthread")), + ex_libs => add("-ldl", threads("-pthread")), + bn_ops => "SIXTY_FOUR_BIT_LONG", + shared_cflag => "-fpic", + shared_ldflag => add_before("-shared"), + shared_extension => ".so.\$(SHLIB_VERSION_NUMBER)", + multilib => "/hpux64", + }, + +#### HP MPE/iX http://jazz.external.hp.com/src/openssl/ + "MPE/iX-gcc" => { + inherit_from => [ "BASE_unix" ], + CC => "gcc", + CFLAGS => "-O3", + cppflags => "-D_POSIX_SOURCE -D_SOCKET_SOURCE", + includes => [ "/SYSLOG/PUB" ], + lib_cppflags => "-DBN_DIV2W", + sys_id => "MPE", + lflags => add("-L/SYSLOG/PUB"), + ex_libs => add("-lsyslog -lsocket -lcurses"), + thread_scheme => "(unknown)", + bn_ops => "BN_LLONG", + }, + +#### DEC Alpha Tru64 targets. Tru64 is marketing name for OSF/1 version 4 +#### and forward. In reality 'uname -s' still returns "OSF1". Originally +#### there were even osf1-* configs targeting prior versions provided, +#### but not anymore... + "tru64-alpha-gcc" => { + inherit_from => [ "BASE_unix", asm("alpha_asm") ], + CC => "gcc", + CFLAGS => "-O3", + cflags => add("-std=c9x", threads("-pthread")), + cppflags => "-D_XOPEN_SOURCE=500 -D_OSF_SOURCE", + ex_libs => add("-lrt", threads("-pthread")), # for mlock(2) + bn_ops => "SIXTY_FOUR_BIT_LONG", + thread_scheme => "pthreads", + dso_scheme => "dlfcn", + shared_target => "alpha-osf1-shared", + shared_extension => ".so", + }, + "tru64-alpha-cc" => { + inherit_from => [ "BASE_unix", asm("alpha_asm") ], + CC => "cc", + CFLAGS => "-tune host -fast", + cflags => add("-std1 -readonly_strings", + threads("-pthread")), + cppflags => "-D_XOPEN_SOURCE=500 -D_OSF_SOURCE", + ex_libs => add("-lrt", threads("-pthread")), # for mlock(2) + bn_ops => "SIXTY_FOUR_BIT_LONG", + thread_scheme => "pthreads", + dso_scheme => "dlfcn", + shared_target => "alpha-osf1-shared", + shared_ldflag => "-msym", + shared_extension => ".so", + }, + +#### +#### Variety of LINUX:-) +#### +# *-generic* is endian-neutral target, but ./config is free to +# throw in -D[BL]_ENDIAN, whichever appropriate... + "linux-generic32" => { + inherit_from => [ "BASE_unix" ], + CC => "gcc", + CXX => "g++", + CFLAGS => picker(default => "-Wall", + debug => "-O0 -g", + release => "-O3"), + CXXFLAGS => picker(default => "-Wall", + debug => "-O0 -g", + release => "-O3"), + cflags => threads("-pthread"), + cxxflags => combine("-std=c++11", threads("-pthread")), + lib_cppflags => "-DOPENSSL_USE_NODELETE", + ex_libs => add("-ldl", threads("-pthread")), + bn_ops => "BN_LLONG RC4_CHAR", + thread_scheme => "pthreads", + dso_scheme => "dlfcn", + shared_target => "linux-shared", + shared_cflag => "-fPIC", + shared_ldflag => sub { $disabled{pinshared} ? () : "-Wl,-znodelete" }, + shared_extension => ".so.\$(SHLIB_VERSION_NUMBER)", + enable => [ "afalgeng" ], + }, + "linux-generic64" => { + inherit_from => [ "linux-generic32" ], + bn_ops => "SIXTY_FOUR_BIT_LONG RC4_CHAR", + }, + + "linux-ppc" => { + inherit_from => [ "linux-generic32", asm("ppc32_asm") ], + perlasm_scheme => "linux32", + }, + "linux-ppc64" => { + inherit_from => [ "linux-generic64", asm("ppc64_asm") ], + cflags => add("-m64"), + cxxflags => add("-m64"), + lib_cppflags => add("-DB_ENDIAN"), + perlasm_scheme => "linux64", + multilib => "64", + }, + "linux-ppc64le" => { + inherit_from => [ "linux-generic64", asm("ppc64_asm") ], + cflags => add("-m64"), + cxxflags => add("-m64"), + lib_cppflags => add("-DL_ENDIAN"), + perlasm_scheme => "linux64le", + }, + + "linux-armv4" => { + ################################################################ + # Note that -march is not among compiler options in linux-armv4 + # target description. Not specifying one is intentional to give + # you choice to: + # + # a) rely on your compiler default by not specifying one; + # b) specify your target platform explicitly for optimal + # performance, e.g. -march=armv6 or -march=armv7-a; + # c) build "universal" binary that targets *range* of platforms + # by specifying minimum and maximum supported architecture; + # + # As for c) option. It actually makes no sense to specify + # maximum to be less than ARMv7, because it's the least + # requirement for run-time switch between platform-specific + # code paths. And without run-time switch performance would be + # equivalent to one for minimum. Secondly, there are some + # natural limitations that you'd have to accept and respect. + # Most notably you can *not* build "universal" binary for + # big-endian platform. This is because ARMv7 processor always + # picks instructions in little-endian order. Another similar + # limitation is that -mthumb can't "cross" -march=armv6t2 + # boundary, because that's where it became Thumb-2. Well, this + # limitation is a bit artificial, because it's not really + # impossible, but it's deemed too tricky to support. And of + # course you have to be sure that your binutils are actually + # up to the task of handling maximum target platform. With all + # this in mind here is an example of how to configure + # "universal" build: + # + # ./Configure linux-armv4 -march=armv6 -D__ARM_MAX_ARCH__=8 + # + inherit_from => [ "linux-generic32", asm("armv4_asm") ], + perlasm_scheme => "linux32", + }, + "linux-aarch64" => { + inherit_from => [ "linux-generic64", asm("aarch64_asm") ], + perlasm_scheme => "linux64", + }, + "linux-arm64ilp32" => { # https://wiki.linaro.org/Platform/arm64-ilp32 + inherit_from => [ "linux-generic32", asm("aarch64_asm") ], + cflags => add("-mabi=ilp32"), + cxxflags => add("-mabi=ilp32"), + bn_ops => "SIXTY_FOUR_BIT RC4_CHAR", + perlasm_scheme => "linux64", + }, + + "linux-mips32" => { + # Configure script adds minimally required -march for assembly + # support, if no -march was specified at command line. + inherit_from => [ "linux-generic32", asm("mips32_asm") ], + cflags => add("-mabi=32"), + cxxflags => add("-mabi=32"), + perlasm_scheme => "o32", + }, + # mips32 and mips64 below refer to contemporary MIPS Architecture + # specifications, MIPS32 and MIPS64, rather than to kernel bitness. + "linux-mips64" => { + inherit_from => [ "linux-generic32", asm("mips64_asm") ], + cflags => add("-mabi=n32"), + cxxflags => add("-mabi=n32"), + bn_ops => "SIXTY_FOUR_BIT RC4_CHAR", + perlasm_scheme => "n32", + multilib => "32", + }, + "linux64-mips64" => { + inherit_from => [ "linux-generic64", asm("mips64_asm") ], + cflags => add("-mabi=64"), + cxxflags => add("-mabi=64"), + perlasm_scheme => "64", + multilib => "64", + }, + + #### IA-32 targets... + #### These two targets are a bit aged and are to be used on older Linux + #### machines where gcc doesn't understand -m32 and -m64 + "linux-elf" => { + inherit_from => [ "linux-generic32", asm("x86_elf_asm") ], + CFLAGS => add(picker(release => "-fomit-frame-pointer")), + lib_cppflags => add("-DL_ENDIAN"), + bn_ops => "BN_LLONG", + }, + "linux-aout" => { + inherit_from => [ "BASE_unix", asm("x86_asm") ], + CC => "gcc", + CFLAGS => add(picker(default => "-Wall", + debug => "-O0 -g", + release => "-O3 -fomit-frame-pointer")), + lib_cppflags => add("-DL_ENDIAN"), + bn_ops => "BN_LLONG", + thread_scheme => "(unknown)", + perlasm_scheme => "a.out", + }, + + #### X86 / X86_64 targets + "linux-x86" => { + inherit_from => [ "linux-generic32", asm("x86_asm") ], + CFLAGS => add(picker(release => "-fomit-frame-pointer")), + cflags => add("-m32"), + cxxflags => add("-m32"), + lib_cppflags => add("-DL_ENDIAN"), + bn_ops => "BN_LLONG", + perlasm_scheme => "elf", + }, + "linux-x86-clang" => { + inherit_from => [ "linux-x86" ], + CC => "clang", + CXX => "clang++", + }, + "linux-x86_64" => { + inherit_from => [ "linux-generic64", asm("x86_64_asm") ], + cflags => add("-m64"), + cxxflags => add("-m64"), + lib_cppflags => add("-DL_ENDIAN"), + bn_ops => "SIXTY_FOUR_BIT_LONG", + perlasm_scheme => "elf", + multilib => "64", + }, + "linux-x86_64-clang" => { + inherit_from => [ "linux-x86_64" ], + CC => "clang", + CXX => "clang++", + }, + "linux-x32" => { + inherit_from => [ "linux-generic32", asm("x86_64_asm") ], + cflags => add("-mx32"), + cxxflags => add("-mx32"), + lib_cppflags => add("-DL_ENDIAN"), + bn_ops => "SIXTY_FOUR_BIT", + perlasm_scheme => "elf32", + multilib => "x32", + }, + + "linux-ia64" => { + inherit_from => [ "linux-generic64", asm("ia64_asm") ], + bn_ops => "SIXTY_FOUR_BIT_LONG", + }, + + "linux64-s390x" => { + inherit_from => [ "linux-generic64", asm("s390x_asm") ], + cflags => add("-m64"), + cxxflags => add("-m64"), + lib_cppflags => add("-DB_ENDIAN"), + perlasm_scheme => "64", + multilib => "64", + }, + "linux32-s390x" => { + #### So called "highgprs" target for z/Architecture CPUs + # "Highgprs" is kernel feature first implemented in Linux + # 2.6.32, see /proc/cpuinfo. The idea is to preserve most + # significant bits of general purpose registers not only + # upon 32-bit process context switch, but even on + # asynchronous signal delivery to such process. This makes + # it possible to deploy 64-bit instructions even in legacy + # application context and achieve better [or should we say + # adequate] performance. The build is binary compatible with + # linux-generic32, and the idea is to be able to install the + # resulting libcrypto.so alongside generic one, e.g. as + # /lib/highgprs/libcrypto.so.x.y, for ldconfig and run-time + # linker to autodiscover. Unfortunately it doesn't work just + # yet, because of couple of bugs in glibc + # sysdeps/s390/dl-procinfo.c affecting ldconfig and ld.so.1... + # + inherit_from => [ "linux-generic32", asm("s390x_asm") ], + cflags => add("-m31 -Wa,-mzarch"), + cxxflags => add("-m31 -Wa,-mzarch"), + lib_cppflags => add("-DB_ENDIAN"), + bn_asm_src => sub { my $r=join(" ",@_); $r=~s|asm/s390x\.S|bn_asm.c|; $r; }, + perlasm_scheme => "31", + multilib => "/highgprs", + }, + + #### SPARC Linux setups + "linux-sparcv8" => { + inherit_from => [ "linux-generic32", asm("sparcv8_asm") ], + cflags => add("-mcpu=v8"), + cxxflags => add("-mcpu=v8"), + lib_cppflags => add("-DB_ENDIAN -DBN_DIV2W"), + }, + "linux-sparcv9" => { + # it's a real mess with -mcpu=ultrasparc option under Linux, + # but -Wa,-Av8plus should do the trick no matter what. + inherit_from => [ "linux-generic32", asm("sparcv9_asm") ], + cflags => add("-m32 -mcpu=ultrasparc -Wa,-Av8plus"), + cxxflags => add("-m32 -mcpu=ultrasparc -Wa,-Av8plus"), + lib_cppflags => add("-DB_ENDIAN -DBN_DIV2W"), + }, + "linux64-sparcv9" => { + # GCC 3.1 is a requirement + inherit_from => [ "linux-generic64", asm("sparcv9_asm") ], + cflags => add("-m64 -mcpu=ultrasparc"), + cxxflags => add("-m64 -mcpu=ultrasparc"), + lib_cppflags => add("-DB_ENDIAN"), + bn_ops => "BN_LLONG RC4_CHAR", + multilib => "64", + }, + + "linux-alpha-gcc" => { + inherit_from => [ "linux-generic64", asm("alpha_asm") ], + lib_cppflags => add("-DL_ENDIAN"), + bn_ops => "SIXTY_FOUR_BIT_LONG", + }, + "linux-c64xplus" => { + inherit_from => [ "BASE_unix" ], + # TI_CGT_C6000_7.3.x is a requirement + CC => "cl6x", + CFLAGS => "-o2 -ox -ms", + cflags => "--linux -ea=.s -eo=.o -mv6400+ -pden", + cxxflags => "--linux -ea=.s -eo=.o -mv6400+ -pden", + cppflags => combine("-DOPENSSL_SMALL_FOOTPRINT", + threads("-D_REENTRANT")), + bn_ops => "BN_LLONG", + cpuid_asm_src => "c64xpluscpuid.s", + bn_asm_src => "asm/bn-c64xplus.asm c64xplus-gf2m.s", + aes_asm_src => "aes-c64xplus.s aes_cbc.c aes-ctr.fake", + sha1_asm_src => "sha1-c64xplus.s sha256-c64xplus.s sha512-c64xplus.s", + rc4_asm_src => "rc4-c64xplus.s", + modes_asm_src => "ghash-c64xplus.s", + chacha_asm_src => "chacha-c64xplus.s", + poly1305_asm_src => "poly1305-c64xplus.s", + thread_scheme => "pthreads", + perlasm_scheme => "void", + dso_scheme => "dlfcn", + shared_target => "linux-shared", + shared_cflag => "--pic", + shared_ldflag => add("-z --sysv --shared"), + shared_extension => ".so.\$(SHLIB_VERSION_NUMBER)", + ranlib => "true", + }, + +#### *BSD + "BSD-generic32" => { + # As for thread cflag. Idea is to maintain "collective" set of + # flags, which would cover all BSD flavors. -pthread applies + # to them all, but is treated differently. OpenBSD expands is + # as -D_POSIX_THREAD -lc_r, which is sufficient. FreeBSD 4.x + # expands it as -lc_r, which has to be accompanied by explicit + # -D_THREAD_SAFE and sometimes -D_REENTRANT. FreeBSD 5.x + # expands it as -lc_r, which seems to be sufficient? + inherit_from => [ "BASE_unix" ], + CC => "cc", + CFLAGS => picker(default => "-Wall", + debug => "-O0 -g", + release => "-O3"), + cflags => threads("-pthread"), + cppflags => threads("-D_THREAD_SAFE -D_REENTRANT"), + ex_libs => add(threads("-pthread")), + enable => add("devcryptoeng"), + bn_ops => "BN_LLONG", + thread_scheme => "pthreads", + dso_scheme => "dlfcn", + shared_target => "bsd-gcc-shared", + shared_cflag => "-fPIC", + shared_extension => ".so.\$(SHLIB_VERSION_NUMBER)", + }, + "BSD-generic64" => { + inherit_from => [ "BSD-generic32" ], + bn_ops => "SIXTY_FOUR_BIT_LONG", + }, + + "BSD-x86" => { + inherit_from => [ "BSD-generic32", asm("x86_asm") ], + CFLAGS => add(picker(release => "-fomit-frame-pointer")), + lib_cppflags => add("-DL_ENDIAN"), + bn_ops => "BN_LLONG", + shared_target => "bsd-shared", + perlasm_scheme => "a.out", + }, + "BSD-x86-elf" => { + inherit_from => [ "BSD-x86" ], + perlasm_scheme => "elf", + }, + + "BSD-sparcv8" => { + inherit_from => [ "BSD-generic32", asm("sparcv8_asm") ], + cflags => add("-mcpu=v8"), + lib_cppflags => add("-DB_ENDIAN"), + }, + "BSD-sparc64" => { + # -DMD32_REG_T=int doesn't actually belong in sparc64 target, it + # simply *happens* to work around a compiler bug in gcc 3.3.3, + # triggered by RIPEMD160 code. + inherit_from => [ "BSD-generic64", asm("sparcv9_asm") ], + lib_cppflags => add("-DB_ENDIAN -DMD32_REG_T=int"), + bn_ops => "BN_LLONG", + }, + + "BSD-ia64" => { + inherit_from => [ "BSD-generic64", asm("ia64_asm") ], + lib_cppflags => add("-DL_ENDIAN"), + bn_ops => "SIXTY_FOUR_BIT_LONG", + }, + + "BSD-x86_64" => { + inherit_from => [ "BSD-generic64", asm("x86_64_asm") ], + lib_cppflags => add("-DL_ENDIAN"), + bn_ops => "SIXTY_FOUR_BIT_LONG", + perlasm_scheme => "elf", + }, + + "bsdi-elf-gcc" => { + inherit_from => [ "BASE_unix", asm("x86_elf_asm") ], + CC => "gcc", + CFLAGS => "-fomit-frame-pointer -O3 -Wall", + lib_cppflags => "-DPERL5 -DL_ENDIAN", + ex_libs => add("-ldl"), + bn_ops => "BN_LLONG", + thread_scheme => "(unknown)", + dso_scheme => "dlfcn", + shared_target => "bsd-gcc-shared", + shared_cflag => "-fPIC", + shared_extension => ".so.\$(SHLIB_VERSION_NUMBER)", + }, + + "nextstep" => { + inherit_from => [ "BASE_unix" ], + CC => "cc", + CFLAGS => "-O -Wall", + unistd => "", + bn_ops => "BN_LLONG", + thread_scheme => "(unknown)", + }, + "nextstep3.3" => { + inherit_from => [ "BASE_unix" ], + CC => "cc", + CFLAGS => "-O3 -Wall", + unistd => "", + bn_ops => "BN_LLONG", + thread_scheme => "(unknown)", + }, + +#### SCO/Caldera targets. +# +# Originally we had like unixware-*, unixware-*-pentium, unixware-*-p6, etc. +# Now we only have blended unixware-* as it's the only one used by ./config. +# If you want to optimize for particular microarchitecture, bypass ./config +# and './Configure unixware-7 -Kpentium_pro' or whatever appropriate. +# Note that not all targets include assembler support. Mostly because of +# lack of motivation to support out-of-date platforms with out-of-date +# compiler drivers and assemblers. +# +# UnixWare 2.0x fails destest with -O. + "unixware-2.0" => { + inherit_from => [ "BASE_unix" ], + CC => "cc", + cflags => threads("-Kthread"), + lib_cppflags => "-DFILIO_H -DNO_STRINGS_H", + ex_libs => add("-lsocket -lnsl -lresolv -lx"), + thread_scheme => "uithreads", + }, + "unixware-2.1" => { + inherit_from => [ "BASE_unix" ], + CC => "cc", + CFLAGS => "-O", + cflags => threads("-Kthread"), + lib_cppflags => "-DFILIO_H", + ex_libs => add("-lsocket -lnsl -lresolv -lx"), + thread_scheme => "uithreads", + }, + "unixware-7" => { + inherit_from => [ "BASE_unix", asm("x86_elf_asm") ], + CC => "cc", + CFLAGS => "-O", + cflags => combine("-Kalloca", threads("-Kthread")), + lib_cppflags => "-DFILIO_H", + ex_libs => add("-lsocket -lnsl"), + thread_scheme => "uithreads", + bn_ops => "BN_LLONG", + perlasm_scheme => "elf-1", + dso_scheme => "dlfcn", + shared_target => "svr5-shared", + shared_cflag => "-Kpic", + shared_extension => ".so.\$(SHLIB_VERSION_NUMBER)", + }, + "unixware-7-gcc" => { + inherit_from => [ "BASE_unix", asm("x86_elf_asm") ], + CC => "gcc", + CFLAGS => "-O3 -fomit-frame-pointer -Wall", + cppflags => add(threads("-D_REENTRANT")), + lib_cppflags => add("-DL_ENDIAN -DFILIO_H"), + ex_libs => add("-lsocket -lnsl"), + bn_ops => "BN_LLONG", + thread_scheme => "pthreads", + perlasm_scheme => "elf-1", + dso_scheme => "dlfcn", + shared_target => "gnu-shared", + shared_cflag => "-fPIC", + shared_extension => ".so.\$(SHLIB_VERSION_NUMBER)", + }, +# SCO 5 - Ben Laurie says the -O breaks the SCO cc. + "sco5-cc" => { + inherit_from => [ "BASE_unix", asm("x86_elf_asm") ], + cc => "cc", + cflags => "-belf", + ex_libs => add("-lsocket -lnsl"), + thread_scheme => "(unknown)", + perlasm_scheme => "elf-1", + dso_scheme => "dlfcn", + shared_target => "svr3-shared", + shared_cflag => "-Kpic", + shared_extension => ".so.\$(SHLIB_VERSION_NUMBER)", + }, + "sco5-gcc" => { + inherit_from => [ "BASE_unix", asm("x86_elf_asm") ], + cc => "gcc", + cflags => "-O3 -fomit-frame-pointer", + ex_libs => add("-lsocket -lnsl"), + bn_ops => "BN_LLONG", + thread_scheme => "(unknown)", + perlasm_scheme => "elf-1", + dso_scheme => "dlfcn", + shared_target => "svr3-shared", + shared_cflag => "-fPIC", + shared_extension => ".so.\$(SHLIB_VERSION_NUMBER)", + }, + +#### IBM's AIX. + # Below targets assume AIX >=5. Caveat lector. If you are accustomed + # to control compilation "bitness" by setting $OBJECT_MODE environment + # variable, then you should know that in OpenSSL case it's considered + # only in ./config. Once configured, build procedure remains "deaf" to + # current value of $OBJECT_MODE. + "aix-common" => { + inherit_from => [ "BASE_unix" ], + template => 1, + sys_id => "AIX", + lib_cppflags => "-DB_ENDIAN", + lflags => "-Wl,-bsvr4", + thread_scheme => "pthreads", + dso_scheme => "dlfcn", + shared_target => "self", + module_ldflags => "-Wl,-G,-bsymbolic,-bexpall", + shared_ldflag => "-Wl,-G,-bsymbolic,-bnoentry", + shared_defflag => "-Wl,-bE:", + shared_extension => ".so.\$(SHLIB_VERSION_NUMBER)", + dso_extension => ".so", + lib_extension => shared("_a.a"), + shared_extension_simple => shared(".a"), + }, + "aix-gcc" => { + inherit_from => [ "aix-common", asm("ppc32_asm") ], + CC => "gcc", + CFLAGS => picker(debug => "-O0 -g", + release => "-O"), + cflags => add(threads("-pthread")), + ex_libs => threads("-pthread"), + bn_ops => "BN_LLONG RC4_CHAR", + perlasm_scheme => "aix32", + shared_ldflag => add_before("-shared -static-libgcc"), + AR => add("-X32"), + RANLIB => add("-X32"), + }, + "aix64-gcc" => { + inherit_from => [ "aix-common", asm("ppc64_asm") ], + CC => "gcc", + CFLAGS => picker(debug => "-O0 -g", + release => "-O"), + cflags => combine("-maix64", threads("-pthread")), + ex_libs => threads("-pthread"), + bn_ops => "SIXTY_FOUR_BIT_LONG RC4_CHAR", + perlasm_scheme => "aix64", + shared_ldflag => add_before("-shared -static-libgcc"), + shared_extension => "64.so.\$(SHLIB_VERSION_NUMBER)", + AR => add("-X64"), + RANLIB => add("-X64"), + }, + "aix-cc" => { + inherit_from => [ "aix-common", asm("ppc32_asm") ], + CC => "cc", + CFLAGS => picker(debug => "-O0 -g", + release => "-O"), + cflags => combine("-q32 -qmaxmem=16384 -qro -qroconst", + threads("-qthreaded")), + cppflags => threads("-D_THREAD_SAFE"), + ex_libs => threads("-lpthreads"), + bn_ops => "BN_LLONG RC4_CHAR", + perlasm_scheme => "aix32", + shared_cflag => "-qpic", + AR => add("-X32"), + RANLIB => add("-X32"), + }, + "aix64-cc" => { + inherit_from => [ "aix-common", asm("ppc64_asm") ], + CC => "cc", + CFLAGS => picker(debug => "-O0 -g", + release => "-O"), + cflags => combine("-q64 -qmaxmem=16384 -qro -qroconst", + threads("-qthreaded")), + cppflags => threads("-D_THREAD_SAFE"), + ex_libs => threads("-lpthreads"), + bn_ops => "SIXTY_FOUR_BIT_LONG RC4_CHAR", + perlasm_scheme => "aix64", + dso_scheme => "dlfcn", + shared_cflag => "-qpic", + shared_extension => "64.so.\$(SHLIB_VERSION_NUMBER)", + AR => add("-X64"), + RANLIB => add("-X64"), + }, + +# SIEMENS BS2000/OSD: an EBCDIC-based mainframe + "BS2000-OSD" => { + inherit_from => [ "BASE_unix" ], + CC => "c89", + CFLAGS => "-O", + cflags => "-XLLML -XLLMK -XL", + cppflags => "-DCHARSET_EBCDIC", + lib_cppflags => "-DB_ENDIAN", + ex_libs => add("-lsocket -lnsl"), + bn_ops => "THIRTY_TWO_BIT RC4_CHAR", + thread_scheme => "(unknown)", + }, + +#### Visual C targets +# +# Win64 targets, WIN64I denotes IA-64/Itanium and WIN64A - AMD64 +# +# Note about /wd4090, disable warning C4090. This warning returns false +# positives in some situations. Disabling it altogether masks both +# legitimate and false cases, but as we compile on multiple platforms, +# we rely on other compilers to catch legitimate cases. +# +# Also note that we force threads no matter what. Configuring "no-threads" +# is ignored. +# +# UNICODE is defined in VC-common and applies to all targets. It used to +# be an opt-in option for VC-WIN32, but not anymore. The original reason +# was because ANSI API was *native* system interface for no longer +# supported Windows 9x. Keep in mind that UNICODE only affects how +# OpenSSL libraries interact with underlying OS, it doesn't affect API +# that OpenSSL presents to application. + + "VC-common" => { + inherit_from => [ "BASE_Windows" ], + template => 1, + CC => "cl", + CPP => '$(CC) /EP /C', + CFLAGS => "/W3 /wd4090 /nologo", + LDFLAGS => add("/debug"), + coutflag => "/Fo", + defines => add("OPENSSL_SYS_WIN32", "WIN32_LEAN_AND_MEAN", + "UNICODE", "_UNICODE", + "_CRT_SECURE_NO_DEPRECATE", + "_WINSOCK_DEPRECATED_NO_WARNINGS"), + lib_cflags => add("/Zi /Fdossl_static.pdb"), + lib_defines => add("L_ENDIAN"), + dso_cflags => "/Zi /Fddso.pdb", + bin_cflags => "/Zi /Fdapp.pdb", + shared_ldflag => "/dll", + shared_target => "win-shared", # meaningless except it gives Configure a hint + thread_scheme => "winthreads", + dso_scheme => "win32", + apps_aux_src => add("win32_init.c"), + bn_ops => "EXPORT_VAR_AS_FN", + # additional parameter to build_scheme denotes install-path "flavour" + build_scheme => add("VC-common", { separator => undef }), + }, + "VC-noCE-common" => { + inherit_from => [ "VC-common" ], + template => 1, + CFLAGS => add(picker(debug => '/Od', + release => '/O2')), + cflags => add(picker(default => '/Gs0 /GF /Gy', + debug => + sub { + ($disabled{shared} ? "" : "/MDd"); + }, + release => + sub { + ($disabled{shared} ? "" : "/MD"); + })), + defines => add(picker(default => [], # works as type cast + debug => [ "DEBUG", "_DEBUG" ])), + lib_cflags => add(sub { $disabled{shared} ? "/MT /Zl" : () }), + # Following might/should appears controversial, i.e. defining + # /MDd without evaluating $disabled{shared}. It works in + # non-shared build because static library is compiled with /Zl + # and bares no reference to specific RTL. And it works in + # shared build because multiple /MDd options are not prohibited. + # But why /MDd in static build? Well, basically this is just a + # reference point, which allows to catch eventual errors that + # would prevent those who want to wrap OpenSSL into own .DLL. + # Why not /MD in release build then? Well, some are likely to + # prefer [non-debug] openssl.exe to be free from Micorosoft RTL + # redistributable. + bin_cflags => add(picker(debug => "/MDd", + release => sub { $disabled{shared} ? "/MT" : () }, + )), + bin_lflags => add("/subsystem:console /opt:ref"), + ex_libs => add(sub { + my @ex_libs = (); + push @ex_libs, 'ws2_32.lib' unless $disabled{sock}; + push @ex_libs, 'gdi32.lib advapi32.lib crypt32.lib user32.lib'; + return join(" ", @ex_libs); + }), + }, + "VC-WIN64-common" => { + inherit_from => [ "VC-noCE-common" ], + template => 1, + ex_libs => add(sub { + my @ex_libs = (); + push @ex_libs, 'bufferoverflowu.lib' if (`cl 2>&1` =~ /14\.00\.4[0-9]{4}\./); + return join(" ", @_, @ex_libs); + }), + bn_ops => add("SIXTY_FOUR_BIT"), + }, + "VC-WIN64I" => { + inherit_from => [ "VC-WIN64-common", asm("ia64_asm"), + sub { $disabled{shared} ? () : "ia64_uplink" } ], + AS => "ias", + ASFLAGS => "-d debug", + asoutflag => "-o ", + sys_id => "WIN64I", + bn_asm_src => sub { return undef unless @_; + my $r=join(" ",@_); $r=~s|bn-ia64.s|bn_asm.c|; $r; }, + perlasm_scheme => "ias", + multilib => "-ia64", + }, + "VC-WIN64A" => { + inherit_from => [ "VC-WIN64-common", asm("x86_64_asm"), + sub { $disabled{shared} ? () : "x86_64_uplink" } ], + AS => sub { vc_win64a_info()->{AS} }, + ASFLAGS => sub { vc_win64a_info()->{ASFLAGS} }, + asoutflag => sub { vc_win64a_info()->{asoutflag} }, + asflags => sub { vc_win64a_info()->{asflags} }, + sys_id => "WIN64A", + bn_asm_src => sub { return undef unless @_; + my $r=join(" ",@_); $r=~s|asm/x86_64-gcc|bn_asm|; $r; }, + perlasm_scheme => "auto", + multilib => "-x64", + }, + "VC-WIN32" => { + inherit_from => [ "VC-noCE-common", asm("x86_asm"), + sub { $disabled{shared} ? () : "uplink_common" } ], + CFLAGS => add("/WX"), + AS => sub { vc_win32_info()->{AS} }, + ASFLAGS => sub { vc_win32_info()->{ASFLAGS} }, + asoutflag => sub { vc_win32_info()->{asoutflag} }, + asflags => sub { vc_win32_info()->{asflags} }, + sys_id => "WIN32", + bn_ops => add("BN_LLONG"), + perlasm_scheme => sub { vc_win32_info()->{perlasm_scheme} }, + # "WOW" stands for "Windows on Windows", and "VC-WOW" engages + # some installation path heuristics in windows-makefile.tmpl... + build_scheme => add("VC-WOW", { separator => undef }), + }, + "VC-CE" => { + inherit_from => [ "VC-common" ], + CFLAGS => add(picker(debug => "/Od", + release => "/O1i")), + CPPDEFINES => picker(debug => [ "DEBUG", "_DEBUG" ]), + LDFLAGS => add("/nologo /opt:ref"), + cflags => + combine('/GF /Gy', + sub { vc_wince_info()->{cflags}; }, + sub { `cl 2>&1` =~ /Version ([0-9]+)\./ && $1>=14 + ? ($disabled{shared} ? " /MT" : " /MD") + : " /MC"; }), + cppflags => sub { vc_wince_info()->{cppflags}; }, + lib_defines => add("NO_CHMOD", "OPENSSL_SMALL_FOOTPRINT"), + lib_cppflags => sub { vc_wince_info()->{cppflags}; }, + includes => + add(combine(sub { defined(env('WCECOMPAT')) + ? '$(WCECOMPAT)/include' : (); }, + sub { defined(env('PORTSDK_LIBPATH')) + ? '$(PORTSDK_LIBPATH)/../../include' + : (); })), + lflags => add(combine(sub { vc_wince_info()->{lflags}; }, + sub { defined(env('PORTSDK_LIBPATH')) + ? "/entry:mainCRTstartup" : (); })), + sys_id => "WINCE", + bn_ops => add("BN_LLONG"), + ex_libs => add(sub { + my @ex_libs = (); + push @ex_libs, 'ws2.lib' unless $disabled{sock}; + push @ex_libs, 'crypt32.lib'; + if (defined(env('WCECOMPAT'))) { + my $x = '$(WCECOMPAT)/lib'; + if (-f "$x/env('TARGETCPU')/wcecompatex.lib") { + $x .= '/$(TARGETCPU)/wcecompatex.lib'; + } else { + $x .= '/wcecompatex.lib'; + } + push @ex_libs, $x; + } + push @ex_libs, '$(PORTSDK_LIBPATH)/portlib.lib' + if (defined(env('PORTSDK_LIBPATH'))); + push @ex_libs, ' /nodefaultlib coredll.lib corelibc.lib' + if (env('TARGETCPU') eq "X86"); + return @ex_libs; + }), + }, + +#### MinGW + "mingw" => { + inherit_from => [ "BASE_unix", asm("x86_asm"), + sub { $disabled{shared} ? () : "x86_uplink" } ], + CC => "gcc", + CFLAGS => picker(default => "-Wall", + debug => "-g -O0", + release => "-O3 -fomit-frame-pointer"), + cflags => "-m32", + cppflags => combine("-DUNICODE -D_UNICODE -DWIN32_LEAN_AND_MEAN", + threads("-D_MT")), + lib_cppflags => "-DL_ENDIAN", + sys_id => "MINGW32", + ex_libs => add("-lws2_32 -lgdi32 -lcrypt32"), + bn_ops => "BN_LLONG EXPORT_VAR_AS_FN", + thread_scheme => "winthreads", + perlasm_scheme => "coff", + dso_scheme => "win32", + shared_target => "mingw-shared", + shared_cppflags => add("_WINDLL"), + shared_ldflag => "-static-libgcc", + shared_rcflag => "--target=pe-i386", + shared_extension => ".dll", + multilib => "", + apps_aux_src => add("win32_init.c"), + }, + "mingw64" => { + # As for OPENSSL_USE_APPLINK. Applink makes it possible to use + # .dll compiled with one compiler with application compiled with + # another compiler. It's possible to engage Applink support in + # mingw64 build, but it's not done, because till mingw64 + # supports structured exception handling, one can't seriously + # consider its binaries for using with non-mingw64 run-time + # environment. And as mingw64 is always consistent with itself, + # Applink is never engaged and can as well be omitted. + inherit_from => [ "BASE_unix", asm("x86_64_asm") ], + CC => "gcc", + CFLAGS => picker(default => "-Wall", + debug => "-g -O0", + release => "-O3"), + cflags => "-m64", + cppflags => combine("-DUNICODE -D_UNICODE -DWIN32_LEAN_AND_MEAN", + threads("-D_MT")), + lib_cppflags => "-DL_ENDIAN", + sys_id => "MINGW64", + ex_libs => add("-lws2_32 -lgdi32 -lcrypt32"), + bn_ops => "SIXTY_FOUR_BIT EXPORT_VAR_AS_FN", + thread_scheme => "winthreads", + perlasm_scheme => "mingw64", + dso_scheme => "win32", + shared_target => "mingw-shared", + shared_cppflags => add("_WINDLL"), + shared_ldflag => "-static-libgcc", + shared_rcflag => "--target=pe-x86-64", + shared_extension => ".dll", + multilib => "64", + apps_aux_src => add("win32_init.c"), + }, + +#### UEFI + "UEFI" => { + inherit_from => [ "BASE_unix" ], + CC => "cc", + CFLAGS => "-O", + lib_cppflags => "-DL_ENDIAN", + sys_id => "UEFI", + }, + +#### UWIN + "UWIN" => { + inherit_from => [ "BASE_unix" ], + CC => "cc", + CFLAGS => "-O -Wall", + lib_cppflags => "-DTERMIOS -DL_ENDIAN", + sys_id => "UWIN", + bn_ops => "BN_LLONG", + dso_scheme => "win32", + }, + +#### Cygwin + "Cygwin-x86" => { + inherit_from => [ "BASE_unix", asm("x86_asm") ], + CC => "gcc", + CFLAGS => picker(default => "-Wall", + debug => "-g -O0", + release => "-O3 -fomit-frame-pointer"), + lib_cppflags => "-DTERMIOS -DL_ENDIAN", + sys_id => "CYGWIN", + bn_ops => "BN_LLONG", + thread_scheme => "pthread", + perlasm_scheme => "coff", + dso_scheme => "dlfcn", + shared_target => "cygwin-shared", + shared_cppflags => "-D_WINDLL", + shared_extension => ".dll", + }, + "Cygwin-x86_64" => { + inherit_from => [ "BASE_unix", asm("x86_64_asm") ], + CC => "gcc", + CFLAGS => picker(default => "-Wall", + debug => "-g -O0", + release => "-O3"), + lib_cppflags => "-DTERMIOS -DL_ENDIAN", + sys_id => "CYGWIN", + bn_ops => "SIXTY_FOUR_BIT_LONG", + thread_scheme => "pthread", + perlasm_scheme => "mingw64", + dso_scheme => "dlfcn", + shared_target => "cygwin-shared", + shared_cppflags => "-D_WINDLL", + shared_extension => ".dll", + }, + # Backward compatibility for those using this target + "Cygwin" => { + inherit_from => [ "Cygwin-x86" ] + }, + # In case someone constructs the Cygwin target name themself + "Cygwin-i386" => { + inherit_from => [ "Cygwin-x86" ] + }, + "Cygwin-i486" => { + inherit_from => [ "Cygwin-x86" ] + }, + "Cygwin-i586" => { + inherit_from => [ "Cygwin-x86" ] + }, + "Cygwin-i686" => { + inherit_from => [ "Cygwin-x86" ] + }, + +##### MacOS X (a.k.a. Darwin) setup + "darwin-common" => { + inherit_from => [ "BASE_unix" ], + template => 1, + CC => "cc", + CFLAGS => picker(debug => "-g -O0", + release => "-O3"), + cppflags => threads("-D_REENTRANT"), + lflags => "-Wl,-search_paths_first", + sys_id => "MACOSX", + bn_ops => "BN_LLONG RC4_CHAR", + thread_scheme => "pthreads", + perlasm_scheme => "osx32", + dso_scheme => "dlfcn", + ranlib => "ranlib -c", + shared_target => "darwin-shared", + shared_cflag => "-fPIC", + shared_extension => ".\$(SHLIB_VERSION_NUMBER).dylib", + }, + # Option "freeze" such as -std=gnu9x can't negatively interfere + # with future defaults for below two targets, because MacOS X + # for PPC has no future, it was discontinued by vendor in 2009. + "darwin-ppc-cc" => { + inherit_from => [ "darwin-common", asm("ppc32_asm") ], + cflags => add("-arch ppc -std=gnu9x -Wa,-force_cpusubtype_ALL"), + lib_cppflags => add("-DB_ENDIAN"), + shared_cflag => add("-fno-common"), + perlasm_scheme => "osx32", + }, + "darwin64-ppc-cc" => { + inherit_from => [ "darwin-common", asm("ppc64_asm") ], + cflags => add("-arch ppc64 -std=gnu9x"), + lib_cppflags => add("-DB_ENDIAN"), + bn_ops => "SIXTY_FOUR_BIT_LONG RC4_CHAR", + perlasm_scheme => "osx64", + }, + "darwin-i386-cc" => { + inherit_from => [ "darwin-common", asm("x86_asm") ], + CFLAGS => add(picker(release => "-fomit-frame-pointer")), + cflags => add("-arch i386"), + lib_cppflags => add("-DL_ENDIAN"), + bn_ops => "BN_LLONG RC4_INT", + perlasm_scheme => "macosx", + }, + "darwin64-x86_64-cc" => { + inherit_from => [ "darwin-common", asm("x86_64_asm") ], + CFLAGS => add("-Wall"), + cflags => add("-arch x86_64"), + lib_cppflags => add("-DL_ENDIAN"), + bn_ops => "SIXTY_FOUR_BIT_LONG", + perlasm_scheme => "macosx", + }, + +##### GNU Hurd + "hurd-x86" => { + inherit_from => [ "BASE_unix" ], + inherit_from => [ asm("x86_elf_asm") ], + CC => "gcc", + CFLAGS => "-O3 -fomit-frame-pointer -Wall", + cflags => threads("-pthread"), + lib_cppflags => "-DL_ENDIAN", + ex_libs => add("-ldl", threads("-pthread")), + bn_ops => "BN_LLONG", + thread_scheme => "pthreads", + dso_scheme => "dlfcn", + shared_target => "linux-shared", + shared_cflag => "-fPIC", + shared_extension => ".so.\$(SHLIB_VERSION_NUMBER)", + }, + +##### VxWorks for various targets + "vxworks-ppc60x" => { + inherit_from => [ "BASE_unix" ], + CC => "ccppc", + CFLAGS => "-O2 -Wall -fstrength-reduce", + cflags => "-mrtp -mhard-float -mstrict-align -fno-implicit-fp -fno-builtin -fno-strict-aliasing", + cppflags => combine("-D_REENTRANT -DPPC32_fp60x -DCPU=PPC32", + "_DTOOL_FAMILY=gnu -DTOOL=gnu", + "-I\$(WIND_BASE)/target/usr/h", + "-I\$(WIND_BASE)/target/usr/h/wrn/coreip"), + sys_id => "VXWORKS", + lflags => add("-L \$(WIND_BASE)/target/usr/lib/ppc/PPC32/common"), + ex_libs => add("-Wl,--defsym,__wrs_rtp_base=0xe0000000"), + }, + "vxworks-ppcgen" => { + inherit_from => [ "BASE_unix" ], + CC => "ccppc", + CFLAGS => "-O1 -Wall", + cflags => "-mrtp -msoft-float -mstrict-align -fno-builtin -fno-strict-aliasing", + cppflags => combine("-D_REENTRANT -DPPC32 -DCPU=PPC32", + "-DTOOL_FAMILY=gnu -DTOOL=gnu", + "-I\$(WIND_BASE)/target/usr/h", + "-I\$(WIND_BASE)/target/usr/h/wrn/coreip"), + sys_id => "VXWORKS", + lflags => add("-L \$(WIND_BASE)/target/usr/lib/ppc/PPC32/sfcommon"), + ex_libs => add("-Wl,--defsym,__wrs_rtp_base=0xe0000000"), + }, + "vxworks-ppc405" => { + inherit_from => [ "BASE_unix" ], + CC => "ccppc", + CFLAGS => "-g", + cflags => "-msoft-float -mlongcall", + cppflags => combine("-D_REENTRANT -DPPC32 -DCPU=PPC405", + "-DTOOL_FAMILY=gnu -DTOOL=gnu", + "-I\$(WIND_BASE)/target/h"), + sys_id => "VXWORKS", + lflags => add("-r"), + }, + "vxworks-ppc750" => { + inherit_from => [ "BASE_unix" ], + CC => "ccppc", + CFLAGS => "-ansi -fvolatile -Wall \$(DEBUG_FLAG)", + cflags => "-nostdinc -fno-builtin -fno-for-scope -fsigned-char -msoft-float -mlongcall", + cppflags => combine("-DPPC750 -D_REENTRANT -DCPU=PPC604", + "-I\$(WIND_BASE)/target/h"), + sys_id => "VXWORKS", + lflags => add("-r"), + }, + "vxworks-ppc750-debug" => { + inherit_from => [ "BASE_unix" ], + CC => "ccppc", + CFLAGS => "-ansi -fvolatile -Wall -g", + cflags => "-nostdinc -fno-builtin -fno-for-scope -fsigned-char -msoft-float -mlongcall", + cppflags => combine("-DPPC750 -D_REENTRANT -DCPU=PPC604", + "-DPEDANTIC -DDEBUG", + "-I\$(WIND_BASE)/target/h"), + sys_id => "VXWORKS", + lflags => add("-r"), + }, + "vxworks-ppc860" => { + inherit_from => [ "BASE_unix" ], + CC => "ccppc", + cflags => "-nostdinc -msoft-float", + cppflags => combine("-DCPU=PPC860 -DNO_STRINGS_H", + "-I\$(WIND_BASE)/target/h"), + sys_id => "VXWORKS", + lflags => add("-r"), + }, + "vxworks-simlinux" => { + inherit_from => [ "BASE_unix" ], + CC => "ccpentium", + cflags => "-B\$(WIND_BASE)/host/\$(WIND_HOST_TYPE)/lib/gcc-lib/ -fno-builtin -fno-defer-pop", + cppflags => combine("-D_VSB_CONFIG_FILE=\"\$(WIND_BASE)/target/lib/h/config/vsbConfig.h\"", + "-DL_ENDIAN -DCPU=SIMLINUX -DNO_STRINGS_H", + "-DTOOL_FAMILY=gnu -DTOOL=gnu", + "-DOPENSSL_NO_HW_PADLOCK", + "-I\$(WIND_BASE)/target/h", + "-I\$(WIND_BASE)/target/h/wrn/coreip"), + sys_id => "VXWORKS", + lflags => add("-r"), + ranlib => "ranlibpentium", + }, + "vxworks-mips" => { + inherit_from => [ "BASE_unix", asm("mips32_asm") ], + CC => "ccmips", + CFLAGS => "-O -G 0", + cflags => "-mrtp -mips2 -B\$(WIND_BASE)/host/\$(WIND_HOST_TYPE)/lib/gcc-lib/ -msoft-float -mno-branch-likely -fno-builtin -fno-defer-pop", + cppflags => combine("-D_VSB_CONFIG_FILE=\"\$(WIND_BASE)/target/lib/h/config/vsbConfig.h\"", + "-DCPU=MIPS32 -DNO_STRINGS_H", + "-DTOOL_FAMILY=gnu -DTOOL=gnu", + "-DOPENSSL_NO_HW_PADLOCK", + threads("-D_REENTRANT"), + "-I\$(WIND_BASE)/target/h", + "-I\$(WIND_BASE)/target/h/wrn/coreip"), + sys_id => "VXWORKS", + lflags => add("-L \$(WIND_BASE)/target/usr/lib/mips/MIPSI32/sfcommon"), + ex_libs => add("-Wl,--defsym,__wrs_rtp_base=0xe0000000"), + thread_scheme => "pthreads", + perlasm_scheme => "o32", + ranlib => "ranlibmips", + }, + +#### uClinux + "uClinux-dist" => { + inherit_from => [ "BASE_unix" ], + CC => sub { env('CC') }, + cppflags => threads("-D_REENTRANT"), + ex_libs => add("\$(LDLIBS)"), + bn_ops => "BN_LLONG", + thread_scheme => "pthreads", + dso_scheme => sub { env('LIBSSL_dlfcn') }, + shared_target => "linux-shared", + shared_cflag => "-fPIC", + shared_extension => ".so.\$(SHLIB_VERSION_NUMBER)", + ranlib => sub { env('RANLIB') }, + }, + "uClinux-dist64" => { + inherit_from => [ "BASE_unix" ], + CC => sub { env('CC') }, + cppflags => threads("-D_REENTRANT"), + ex_libs => add("\$(LDLIBS)"), + bn_ops => "SIXTY_FOUR_BIT_LONG", + thread_scheme => "pthreads", + dso_scheme => sub { env('LIBSSL_dlfcn') }, + shared_target => "linux-shared", + shared_cflag => "-fPIC", + shared_extension => ".so.\$(SHLIB_VERSION_NUMBER)", + ranlib => sub { env('RANLIB') }, + }, + + ##### VMS + # Most things happen in vms-generic. + # Note that vms_info extracts the pointer size from the end of + # the target name, and will assume that anything matching /-p\d+$/ + # indicates the pointer size setting for the desired target. + "vms-generic" => { + inherit_from => [ "BASE_VMS" ], + template => 1, + CC => "CC/DECC", + CPP => '$(CC)/PREPROCESS_ONLY=SYS$OUTPUT:', + CFLAGS => + combine(picker(default => "/STANDARD=(ISOC94,RELAXED)/NOLIST/PREFIX=ALL", + debug => "/NOOPTIMIZE/DEBUG", + release => "/OPTIMIZE/NODEBUG"), + sub { my @warnings = + @{vms_info()->{disable_warns}}; + @warnings + ? "/WARNINGS=DISABLE=(".join(",",@warnings).")" : (); }), + lib_defines => + add("OPENSSL_USE_NODELETE", + sub { + return vms_info()->{def_zlib} + ? "LIBZ=\"\"\"".vms_info()->{def_zlib}."\"\"\"" : (); + }), + lflags => picker(default => "/MAP='F\$PARSE(\".MAP\",\"\$\@\")'", + debug => "/DEBUG/TRACEBACK", + release => "/NODEBUG/NOTRACEBACK"), + lib_cflags => add("/NAMES=(AS_IS,SHORTENED)/EXTERN_MODEL=STRICT_REFDEF"), + # no_inst_lib_cflags is used instead of lib_cflags by descrip.mms.tmpl + # for object files belonging to selected internal libraries + no_inst_lib_cflags => "", + ex_libs => add(sub { return vms_info()->{zlib} || (); }), + shared_target => "vms-shared", + dso_scheme => "vms", + thread_scheme => "pthreads", + + AS => sub { vms_info()->{AS} }, + ASFLAGS => sub { vms_info()->{ASFLAGS} }, + asoutflag => sub { vms_info()->{asoutflag} }, + asflags => sub { vms_info()->{asflags} }, + perlasm_scheme => sub { vms_info()->{perlasm_scheme} }, + + disable => add('pinshared'), + + apps_aux_src => "vms_term_sock.c", + apps_init_src => "vms_decc_init.c", + }, + + # From HELP CC/POINTER_SIZE: + # + # ---------- + # LONG[=ARGV] The compiler assumes 64-bit pointers. If the ARGV option to + # LONG or 64 is present, the main argument argv will be an + # array of long pointers instead of an array of short pointers. + # + # 64[=ARGV] Same as LONG. + # ---------- + # + # We don't want the hassle of dealing with 32-bit pointers with argv, so + # we force it to have 64-bit pointers, see the added cflags in the -p64 + # config targets below. + + "vms-alpha" => { + inherit_from => [ "vms-generic" ], + bn_ops => "SIXTY_FOUR_BIT RC4_INT", + pointer_size => "", + }, + "vms-alpha-p32" => { + inherit_from => [ "vms-alpha" ], + cflags => add("/POINTER_SIZE=32"), + pointer_size => "32", + }, + "vms-alpha-p64" => { + inherit_from => [ "vms-alpha" ], + cflags => add("/POINTER_SIZE=64=ARGV"), + pointer_size => "64", + }, + "vms-ia64" => { + inherit_from => [ "vms-generic", + sub { vms_info()->{AS} + ? asm("ia64_asm")->() : () } ], + bn_ops => "SIXTY_FOUR_BIT RC4_INT", + pointer_size => "", + + modes_asm_src => "", # Because ghash-ia64.s doesn't work on VMS + }, + "vms-ia64-p32" => { + inherit_from => [ "vms-ia64" ], + cflags => add("/POINTER_SIZE=32"), + pointer_size => "32", + }, + "vms-ia64-p64" => { + inherit_from => [ "vms-ia64" ], + cflags => add("/POINTER_SIZE=64=ARGV"), + pointer_size => "64", + }, + +); diff --git a/trunk/3rdparty/openssl-1.1-fit/Configurations/15-android.conf b/trunk/3rdparty/openssl-1.1-fit/Configurations/15-android.conf new file mode 100644 index 000000000..7b496a452 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/Configurations/15-android.conf @@ -0,0 +1,261 @@ +#### Android... +# +# See NOTES.ANDROID for details, and don't miss platform-specific +# comments below... + +{ + use File::Spec::Functions; + + my $android_ndk = {}; + my %triplet = ( + arm => "arm-linux-androideabi", + arm64 => "aarch64-linux-android", + mips => "mipsel-linux-android", + mips64 => "mips64el-linux-android", + x86 => "i686-linux-android", + x86_64 => "x86_64-linux-android", + ); + + sub android_ndk { + unless (%$android_ndk) { + if ($now_printing =~ m|^android|) { + return $android_ndk = { bn_ops => "BN_AUTO" }; + } + + my $ndk_var; + my $ndk; + foreach (qw(ANDROID_NDK_HOME ANDROID_NDK)) { + $ndk_var = $_; + $ndk = $ENV{$ndk_var}; + last if defined $ndk; + } + die "\$ANDROID_NDK_HOME is not defined" if (!$ndk); + if (!-d "$ndk/platforms" && !-f "$ndk/AndroidVersion.txt") { + # $ndk/platforms is traditional "all-inclusive" NDK, while + # $ndk/AndroidVersion.txt is so-called standalone toolchain + # tailored for specific target down to API level. + die "\$ANDROID_NDK_HOME=$ndk is invalid"; + } + $ndk = canonpath($ndk); + + my $ndkver = undef; + + if (open my $fh, "<$ndk/source.properties") { + local $_; + while(<$fh>) { + if (m|Pkg\.Revision\s*=\s*([0-9]+)|) { + $ndkver = $1; + last; + } + } + close $fh; + } + + my ($sysroot, $api, $arch); + + $config{target} =~ m|[^-]+-([^-]+)$|; # split on dash + $arch = $1; + + if ($sysroot = $ENV{CROSS_SYSROOT}) { + $sysroot =~ m|/android-([0-9]+)/arch-(\w+)/?$|; + ($api, $arch) = ($1, $2); + } elsif (-f "$ndk/AndroidVersion.txt") { + $sysroot = "$ndk/sysroot"; + } else { + $api = "*"; + + # see if user passed -D__ANDROID_API__=N + foreach (@{$useradd{CPPDEFINES}}, @{$user{CPPFLAGS}}) { + if (m|__ANDROID_API__=([0-9]+)|) { + $api = $1; + last; + } + } + + # list available platforms (numerically) + my @platforms = sort { $a =~ m/-([0-9]+)$/; my $aa = $1; + $b =~ m/-([0-9]+)$/; $aa <=> $1; + } glob("$ndk/platforms/android-$api"); + die "no $ndk/platforms/android-$api" if ($#platforms < 0); + + $sysroot = "@platforms[$#platforms]/arch-$arch"; + $sysroot =~ m|/android-([0-9]+)/arch-$arch|; + $api = $1; + } + die "no sysroot=$sysroot" if (!-d $sysroot); + + my $triarch = $triplet{$arch}; + my $cflags; + my $cppflags; + + # see if there is NDK clang on $PATH, "universal" or "standalone" + if (which("clang") =~ m|^$ndk/.*/prebuilt/([^/]+)/|) { + my $host=$1; + # harmonize with gcc default + my $arm = $ndkver > 16 ? "armv7a" : "armv5te"; + (my $tridefault = $triarch) =~ s/^arm-/$arm-/; + (my $tritools = $triarch) =~ s/(?:x|i6)86(_64)?-.*/x86$1/; + $cflags .= " -target $tridefault " + . "-gcc-toolchain \$($ndk_var)/toolchains" + . "/$tritools-4.9/prebuilt/$host"; + $user{CC} = "clang" if ($user{CC} !~ m|clang|); + $user{CROSS_COMPILE} = undef; + if (which("llvm-ar") =~ m|^$ndk/.*/prebuilt/([^/]+)/|) { + $user{AR} = "llvm-ar"; + $user{ARFLAGS} = [ "rs" ]; + $user{RANLIB} = ":"; + } + } elsif (-f "$ndk/AndroidVersion.txt") { #"standalone toolchain" + my $cc = $user{CC} // "clang"; + # One can probably argue that both clang and gcc should be + # probed, but support for "standalone toolchain" was added + # *after* announcement that gcc is being phased out, so + # favouring clang is considered adequate. Those who insist + # have option to enforce test for gcc with CC=gcc. + if (which("$triarch-$cc") !~ m|^$ndk|) { + die "no NDK $triarch-$cc on \$PATH"; + } + $user{CC} = $cc; + $user{CROSS_COMPILE} = "$triarch-"; + } elsif ($user{CC} eq "clang") { + die "no NDK clang on \$PATH"; + } else { + if (which("$triarch-gcc") !~ m|^$ndk/.*/prebuilt/([^/]+)/|) { + die "no NDK $triarch-gcc on \$PATH"; + } + $cflags .= " -mandroid"; + $user{CROSS_COMPILE} = "$triarch-"; + } + + if (!-d "$sysroot/usr/include") { + my $incroot = "$ndk/sysroot/usr/include"; + die "no $incroot" if (!-d $incroot); + die "no $incroot/$triarch" if (!-d "$incroot/$triarch"); + $incroot =~ s|^$ndk/||; + $cppflags = "-D__ANDROID_API__=$api"; + $cppflags .= " -isystem \$($ndk_var)/$incroot/$triarch"; + $cppflags .= " -isystem \$($ndk_var)/$incroot"; + } + + $sysroot =~ s|^$ndk/||; + $android_ndk = { + cflags => "$cflags --sysroot=\$($ndk_var)/$sysroot", + cppflags => $cppflags, + bn_ops => $arch =~ m/64$/ ? "SIXTY_FOUR_BIT_LONG" + : "BN_LLONG", + }; + } + + return $android_ndk; + } +} + +my %targets = ( + "android" => { + inherit_from => [ "linux-generic32" ], + template => 1, + ################################################################ + # Special note about -pie. The underlying reason is that + # Lollipop refuses to run non-PIE. But what about older systems + # and NDKs? -fPIC was never problem, so the only concern is -pie. + # Older toolchains, e.g. r4, appear to handle it and binaries + # turn out mostly functional. "Mostly" means that oldest + # Androids, such as Froyo, fail to handle executable, but newer + # systems are perfectly capable of executing binaries targeting + # Froyo. Keep in mind that in the nutshell Android builds are + # about JNI, i.e. shared libraries, not applications. + cflags => add(sub { android_ndk()->{cflags} }), + cppflags => add(sub { android_ndk()->{cppflags} }), + cxxflags => add(sub { android_ndk()->{cflags} }), + bn_ops => sub { android_ndk()->{bn_ops} }, + bin_cflags => "-pie", + enable => [ ], + }, + "android-arm" => { + ################################################################ + # Contemporary Android applications can provide multiple JNI + # providers in .apk, targeting multiple architectures. Among + # them there is "place" for two ARM flavours: generic eabi and + # armv7-a/hard-float. However, it should be noted that OpenSSL's + # ability to engage NEON is not constrained by ABI choice, nor + # is your ability to call OpenSSL from your application code + # compiled with floating-point ABI other than default 'soft'. + # (Latter thanks to __attribute__((pcs("aapcs"))) declaration.) + # This means that choice of ARM libraries you provide in .apk + # is driven by application needs. For example if application + # itself benefits from NEON or is floating-point intensive, then + # it might be appropriate to provide both libraries. Otherwise + # just generic eabi would do. But in latter case it would be + # appropriate to + # + # ./Configure android-arm -D__ARM_MAX_ARCH__=8 + # + # in order to build "universal" binary and allow OpenSSL take + # advantage of NEON when it's available. + # + # Keep in mind that (just like with linux-armv4) we rely on + # compiler defaults, which is not necessarily what you had + # in mind, in which case you would have to pass additional + # -march and/or -mfloat-abi flags. NDK defaults to armv5te. + # Newer NDK versions reportedly require additional -latomic. + # + inherit_from => [ "android", asm("armv4_asm") ], + bn_ops => add("RC4_CHAR"), + }, + "android-arm64" => { + inherit_from => [ "android", asm("aarch64_asm") ], + bn_ops => add("RC4_CHAR"), + perlasm_scheme => "linux64", + }, + + "android-mips" => { + inherit_from => [ "android", asm("mips32_asm") ], + bn_ops => add("RC4_CHAR"), + perlasm_scheme => "o32", + }, + "android-mips64" => { + ################################################################ + # You are more than likely have to specify target processor + # on ./Configure command line. Trouble is that toolchain's + # default is MIPS64r6 (at least in r10d), but there are no + # such processors around (or they are too rare to spot one). + # Actual problem is that MIPS64r6 is binary incompatible + # with previous MIPS ISA versions, in sense that unlike + # prior versions original MIPS binary code will fail. + # + inherit_from => [ "android", asm("mips64_asm") ], + bn_ops => add("RC4_CHAR"), + perlasm_scheme => "64", + }, + + "android-x86" => { + inherit_from => [ "android", asm("x86_asm") ], + CFLAGS => add(picker(release => "-fomit-frame-pointer")), + bn_ops => add("RC4_INT"), + perlasm_scheme => "android", + }, + "android-x86_64" => { + inherit_from => [ "android", asm("x86_64_asm") ], + bn_ops => add("RC4_INT"), + perlasm_scheme => "elf", + }, + + #################################################################### + # Backward compatible targets, (might) requre $CROSS_SYSROOT + # + "android-armeabi" => { + inherit_from => [ "android-arm" ], + }, + "android64" => { + inherit_from => [ "android" ], + }, + "android64-aarch64" => { + inherit_from => [ "android-arm64" ], + }, + "android64-x86_64" => { + inherit_from => [ "android-x86_64" ], + }, + "android64-mips64" => { + inherit_from => [ "android-mips64" ], + }, +); diff --git a/trunk/3rdparty/openssl-1.1-fit/Configurations/15-ios.conf b/trunk/3rdparty/openssl-1.1-fit/Configurations/15-ios.conf new file mode 100644 index 000000000..1bb9f48d0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/Configurations/15-ios.conf @@ -0,0 +1,62 @@ +#### iPhoneOS/iOS +# +# It takes recent enough XCode to use following two targets. It shouldn't +# be a problem by now, but if they don't work, original targets below +# that depend on manual definition of environment variables should still +# work... +# +my %targets = ( + "ios-common" => { + template => 1, + inherit_from => [ "darwin-common" ], + sys_id => "iOS", + disable => [ "engine", "async" ], + }, + "ios-xcrun" => { + inherit_from => [ "ios-common", asm("armv4_asm") ], + # It should be possible to go below iOS 6 and even add -arch armv6, + # thus targeting iPhone pre-3GS, but it's assumed to be irrelevant + # at this point. + CC => "xcrun -sdk iphoneos cc", + cflags => add("-arch armv7 -mios-version-min=6.0.0 -fno-common"), + perlasm_scheme => "ios32", + }, + "ios64-xcrun" => { + inherit_from => [ "ios-common", asm("aarch64_asm") ], + CC => "xcrun -sdk iphoneos cc", + cflags => add("-arch arm64 -mios-version-min=7.0.0 -fno-common"), + bn_ops => "SIXTY_FOUR_BIT_LONG RC4_CHAR", + perlasm_scheme => "ios64", + }, + "iossimulator-xcrun" => { + inherit_from => [ "ios-common" ], + CC => "xcrun -sdk iphonesimulator cc", + }, +# It takes three prior-set environment variables to make it work: +# +# CROSS_COMPILE=/where/toolchain/is/usr/bin/ [note ending slash] +# CROSS_TOP=/where/SDKs/are +# CROSS_SDK=iPhoneOSx.y.sdk +# +# Exact paths vary with Xcode releases, but for couple of last ones +# they would look like this: +# +# CROSS_COMPILE=`xcode-select --print-path`/Toolchains/XcodeDefault.xctoolchain/usr/bin/ +# CROSS_TOP=`xcode-select --print-path`/Platforms/iPhoneOS.platform/Developer +# CROSS_SDK=iPhoneOS.sdk +# + "iphoneos-cross" => { + inherit_from => [ "ios-common" ], + cflags => add("-isysroot \$(CROSS_TOP)/SDKs/\$(CROSS_SDK) -fno-common"), + }, + "ios-cross" => { + inherit_from => [ "ios-xcrun" ], + CC => "cc", + cflags => add("-isysroot \$(CROSS_TOP)/SDKs/\$(CROSS_SDK)"), + }, + "ios64-cross" => { + inherit_from => [ "ios64-xcrun" ], + CC => "cc", + cflags => add("-isysroot \$(CROSS_TOP)/SDKs/\$(CROSS_SDK)"), + }, +); diff --git a/trunk/3rdparty/openssl-1.1-fit/Configurations/50-djgpp.conf b/trunk/3rdparty/openssl-1.1-fit/Configurations/50-djgpp.conf new file mode 100644 index 000000000..a8853a81a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/Configurations/50-djgpp.conf @@ -0,0 +1,17 @@ +# We can't make any commitment to support the DJGPP platform, +# and rely entirely on the OpenSSL community to help is fine +# tune and test. + +my %targets = ( + "DJGPP" => { + inherit_from => [ asm("x86_asm") ], + CC => "gcc", + CFLAGS => "-fomit-frame-pointer -O2 -Wall", + cflags => "-I/dev/env/WATT_ROOT/inc -DTERMIOS -DL_ENDIAN", + sys_id => "MSDOS", + lflags => add("-L/dev/env/WATT_ROOT/lib"), + ex_libs => add("-lwatt"), + bn_ops => "BN_LLONG", + perlasm_scheme => "a.out", + }, +); diff --git a/trunk/3rdparty/openssl-1.1-fit/Configurations/50-haiku.conf b/trunk/3rdparty/openssl-1.1-fit/Configurations/50-haiku.conf new file mode 100644 index 000000000..cd6d10e5f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/Configurations/50-haiku.conf @@ -0,0 +1,30 @@ +my %targets = ( + "haiku-common" => { + template => 1, + CC => "cc", + CFLAGS => add_before(picker(default => "-Wall", + debug => "-g -O0", + release => "-O2")), + cflags => add_before("-DL_ENDIAN -include \$(SRCDIR)/os-dep/haiku.h", + threads("-D_REENTRANT")), + sys_id => "HAIKU", + ex_libs => "-lnetwork", + perlasm_scheme => "elf", + thread_scheme => "pthreads", + dso_scheme => "dlfcn", + shared_target => "gnu-shared", + shared_cflag => "-fPIC", + shared_ldflag => "-shared", + shared_extension => ".so.\$(SHLIB_VERSION_NUMBER)", + }, + "haiku-x86" => { + inherit_from => [ "haiku-common", asm("x86_elf_asm") ], + CFLAGS => add(picker(release => "-fomit-frame-pointer")), + bn_ops => "BN_LLONG", + }, + "haiku-x86_64" => { + inherit_from => [ "haiku-common" ], + cflags => add("-m64"), + bn_ops => "SIXTY_FOUR_BIT_LONG", + }, +); diff --git a/trunk/3rdparty/openssl-1.1-fit/Configurations/50-masm.conf b/trunk/3rdparty/openssl-1.1-fit/Configurations/50-masm.conf new file mode 100644 index 000000000..2c55dddc2 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/Configurations/50-masm.conf @@ -0,0 +1,23 @@ +# We can't make commitment to supporting Microsoft assembler, +# because it would mean supporting all masm versions. This in +# in turn is because masm is not really an interchangeable option, +# while users tend to have reasons to stick with specific Visual +# Studio versions. It's usually lesser hassle to make it work +# with latest assembler, but tweaking for older versions had +# proven to be daunting task. This is experimental target, for +# production builds stick with [up-to-date version of] nasm. + +my %targets = ( + "VC-WIN64A-masm" => { + inherit_from => [ "VC-WIN64-common", asm("x86_64_asm"), + sub { $disabled{shared} ? () : "x86_64_uplink" } ], + AS => "ml64", + ASFLAGS => "/nologo /Zi", + asoutflag => "/Fo", + asflags => "/c /Cp /Cx", + sys_id => "WIN64A", + bn_asm_src => sub { return undef unless @_; + my $r=join(" ",@_); $r=~s|asm/x86_64-gcc|bn_asm|; $r; }, + perlasm_scheme => "masm", + }, +); diff --git a/trunk/3rdparty/openssl-1.1-fit/Configurations/50-win-onecore.conf b/trunk/3rdparty/openssl-1.1-fit/Configurations/50-win-onecore.conf new file mode 100644 index 000000000..51cb3819c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/Configurations/50-win-onecore.conf @@ -0,0 +1,64 @@ +# Windows OneCore targets. +# +# OneCore is new API stability "contract" that transends Desktop, IoT and +# Mobile[?] Windows editions. It's a set up "umbrella" libraries that +# export subset of Win32 API that are common to all Windows 10 devices. +# +# OneCore Configuration temporarly dedicated for console applications +# due to disabled event logging, which is incompatible with one core. +# Error messages are provided via standard error only. +# TODO: extend error handling to use ETW based eventing +# (Or rework whole error messaging) + +my %targets = ( + "VC-WIN32-ONECORE" => { + inherit_from => [ "VC-WIN32" ], + # /NODEFAULTLIB:kernel32.lib is needed, because MSVCRT.LIB has + # hidden reference to kernel32.lib, but we don't actually want + # it in "onecore" build. + lflags => add("/NODEFAULTLIB:kernel32.lib"), + defines => add("OPENSSL_SYS_WIN_CORE"), + ex_libs => "onecore.lib", + }, + "VC-WIN64A-ONECORE" => { + inherit_from => [ "VC-WIN64A" ], + lflags => add("/NODEFAULTLIB:kernel32.lib"), + defines => add("OPENSSL_SYS_WIN_CORE"), + ex_libs => "onecore.lib", + }, + + # Windows on ARM targets. ARM compilers are additional components in + # VS2017, i.e. they are not installed by default. And when installed, + # there are no "ARM Tool Command Prompt"s on Start menu, you have + # to locate vcvarsall.bat and act accordingly. VC-WIN32-ARM has + # received limited testing with evp_test.exe on Windows 10 IoT Core, + # but not VC-WIN64-ARM, no hardware... In other words they are not + # actually supported... + # + # Another thing to keep in mind [in cross-compilation scenario such + # as this one] is that target's file system has nothing to do with + # compilation system's one. This means that you're are likely to use + # --prefix and --openssldir with target-specific values. 'nmake install' + # step is effectively meaningless in cross-compilation case, though + # it might be useful to 'nmake install DESTDIR=S:\ome\where' where you + # can point Visual Studio to when compiling custom application code. + + "VC-WIN32-ARM" => { + inherit_from => [ "VC-noCE-common" ], + defines => add("_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE", + "OPENSSL_SYS_WIN_CORE"), + bn_ops => "BN_LLONG RC4_CHAR EXPORT_VAR_AS_FN", + lflags => add("/NODEFAULTLIB:kernel32.lib"), + ex_libs => "onecore.lib", + multilib => "-arm", + }, + "VC-WIN64-ARM" => { + inherit_from => [ "VC-noCE-common" ], + defines => add("_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE", + "OPENSSL_SYS_WIN_CORE"), + bn_ops => "SIXTY_FOUR_BIT RC4_CHAR EXPORT_VAR_AS_FN", + lflags => add("/NODEFAULTLIB:kernel32.lib"), + ex_libs => "onecore.lib", + multilib => "-arm64", + }, +); diff --git a/trunk/3rdparty/openssl-1.1-fit/Configurations/INTERNALS.Configure b/trunk/3rdparty/openssl-1.1-fit/Configurations/INTERNALS.Configure new file mode 100644 index 000000000..b28305dec --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/Configurations/INTERNALS.Configure @@ -0,0 +1,136 @@ +Configure Internals +=================== + +[ note: this file uses markdown for formatting ] + +Intro +----- + +This is a collection of notes that are hopefully of interest to those +who decide to dive into Configure and what it does. This is a living +document and anyone is encouraged to add to it and submit changes. +There's no claim for this document to be complete at any time, but it +will hopefully reach such a point in time. + + +---------------------------------------------------------------------- + +Parsing build.info files, processing conditions +----------------------------------------------- + +Processing conditions in build.info files is done with the help of a +condition stack that tell if a build.info should be processed or if it +should just be skipped over. The possible states of the stack top are +expressed in the following comment from Configure: + + # The top item of this stack has the following values + # -2 positive already run and we found ELSE (following ELSIF should fail) + # -1 positive already run (skip until ENDIF) + # 0 negatives so far (if we're at a condition, check it) + # 1 last was positive (don't skip lines until next ELSE, ELSIF or ENDIF) + # 2 positive ELSE (following ELSIF should fail) + +Ground rule is that non-condition lines are skipped over if the +stack top is > 0. Condition lines (IF, ELSIF, ELSE and ENDIF +statements) need to be processed either way to keep track of the skip +stack states, so they are a little more intricate. + +Instead of trying to describe in words, here are some example of what +the skip stack should look like after each line is processed: + +Example 1: + +| IF[1] | 1 | | +| ... whatever ... | | this line is processed | +| IF[1] | 1 1 | | +| ... whatever ... | | this line is processed | +| ELSIF[1] | 1 -1 | | +| ... whatever ... | | this line is skipped over | +| ELSE | 1 -2 | | +| ... whatever ... | | this line is skipped over | +| ENDIF | 1 | | +| ... whatever ... | | this line is processed | +| ELSIF[1] | -1 | | +| ... whatever ... | | this line is skipped over | +| IF[1] | -1 -1 | | +| ... whatever ... | | this line is skipped over | +| ELSIF[1] | -1 -1 | | +| ... whatever ... | | this line is skipped over | +| ELSE | -1 -2 | | +| ... whatever ... | | this line is skipped over | +| ENDIF | -1 | | +| ... whatever ... | | this line is skipped over | +| ENDIF | | | + +Example 2: + +| IF[0] | 0 | | +| ... whatever ... | | this line is skipped over | +| IF[1] | 0 -1 | | +| ... whatever ... | | this line is skipped over | +| ELSIF[1] | 0 -1 | | +| ... whatever ... | | this line is skipped over | +| ELSE | 0 -2 | | +| ... whatever ... | | this line is skipped over | +| ENDIF | 0 | | +| ... whatever ... | | this line is skipped over | +| ELSIF[1] | 1 | | +| ... whatever ... | | this line is processed | +| IF[1] | 1 1 | | +| ... whatever ... | | this line is processed | +| ELSIF[1] | 1 -1 | | +| ... whatever ... | | this line is skipped over | +| ELSE | 1 -2 | | +| ... whatever ... | | this line is skipped over | +| ENDIF | 1 | | +| ... whatever ... | | this line is processed | +| ENDIF | | | + +Example 3: + +| IF[0] | 0 | | +| ... whatever ... | | this line is skipped over | +| IF[0] | 0 -1 | | +| ... whatever ... | | this line is skipped over | +| ELSIF[1] | 0 -1 | | +| ... whatever ... | | this line is skipped over | +| ELSE | 0 -2 | | +| ... whatever ... | | this line is skipped over | +| ENDIF | 0 | | +| ... whatever ... | | this line is skipped over | +| ELSIF[1] | 1 | | +| ... whatever ... | | this line is processed | +| IF[0] | 1 0 | | +| ... whatever ... | | this line is skipped over | +| ELSIF[1] | 1 1 | | +| ... whatever ... | | this line is processed | +| ELSE | 1 -2 | | +| ... whatever ... | | this line is skipped over | +| ENDIF | 1 | | +| ... whatever ... | | this line is processed | +| ENDIF | | | + +Example 4: + +| IF[0] | 0 | | +| ... whatever ... | | this line is skipped over | +| IF[0] | 0 -1 | | +| ... whatever ... | | this line is skipped over | +| ELSIF[0] | 0 -1 | | +| ... whatever ... | | this line is skipped over | +| ELSE | 0 -2 | | +| ... whatever ... | | this line is skipped over | +| ENDIF | 0 | | +| ... whatever ... | | this line is skipped over | +| ELSIF[1] | 1 | | +| ... whatever ... | | this line is processed | +| IF[0] | 1 0 | | +| ... whatever ... | | this line is skipped over | +| ELSIF[0] | 1 0 | | +| ... whatever ... | | this line is skipped over | +| ELSE | 1 2 | | +| ... whatever ... | | this line is processed | +| ENDIF | 1 | | +| ... whatever ... | | this line is processed | +| ENDIF | | | + diff --git a/trunk/3rdparty/openssl-1.1-fit/Configurations/README b/trunk/3rdparty/openssl-1.1-fit/Configurations/README new file mode 100644 index 000000000..0b856284d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/Configurations/README @@ -0,0 +1,763 @@ +Intro +===== + +This directory contains a few sets of files that are used for +configuration in diverse ways: + + *.conf Target platform configurations, please read + 'Configurations of OpenSSL target platforms' for more + information. + *.tmpl Build file templates, please read 'Build-file + programming with the "unified" build system' as well + as 'Build info files' for more information. + *.pm Helper scripts / modules for the main `Configure` + script. See 'Configure helper scripts for more + information. + + +Configurations of OpenSSL target platforms +========================================== + +Configuration targets are a collection of facts that we know about +different platforms and their capabilities. We organise them in a +hash table, where each entry represent a specific target. + +Note that configuration target names must be unique across all config +files. The Configure script does check that a config file doesn't +have config targets that shadow config targets from other files. + +In each table entry, the following keys are significant: + + inherit_from => Other targets to inherit values from. + Explained further below. [1] + template => Set to 1 if this isn't really a platform + target. Instead, this target is a template + upon which other targets can be built. + Explained further below. [1] + + sys_id => System identity for systems where that + is difficult to determine automatically. + + enable => Enable specific configuration features. + This MUST be an array of words. + disable => Disable specific configuration features. + This MUST be an array of words. + Note: if the same feature is both enabled + and disabled, disable wins. + + as => The assembler command. This is not always + used (for example on Unix, where the C + compiler is used instead). + asflags => Default assembler command flags [4]. + cpp => The C preprocessor command, normally not + given, as the build file defaults are + usually good enough. + cppflags => Default C preprocessor flags [4]. + defines => As an alternative, macro definitions may be + given here instead of in `cppflags' [4]. + If given here, they MUST be as an array of + the string such as "MACRO=value", or just + "MACRO" for definitions without value. + includes => As an alternative, inclusion directories + may be given here instead of in `cppflags' + [4]. If given here, the MUST be an array + of strings, one directory specification + each. + cc => The C compiler command, usually one of "cc", + "gcc" or "clang". This command is normally + also used to link object files and + libraries into the final program. + cxx => The C++ compiler command, usually one of + "c++", "g++" or "clang++". This command is + also used when linking a program where at + least one of the object file is made from + C++ source. + cflags => Defaults C compiler flags [4]. + cxxflags => Default C++ compiler flags [4]. If unset, + it gets the same value as cflags. + + (linking is a complex thing, see [3] below) + ld => Linker command, usually not defined + (meaning the compiler command is used + instead). + (NOTE: this is here for future use, it's + not implemented yet) + lflags => Default flags used when linking apps, + shared libraries or DSOs [4]. + ex_libs => Extra libraries that are needed when + linking shared libraries, DSOs or programs. + The value is also assigned to Libs.private + in $(libdir)/pkgconfig/libcrypto.pc. + + shared_cppflags => Extra C preprocessor flags used when + processing C files for shared libraries. + shared_cflag => Extra C compiler flags used when compiling + for shared libraries, typically something + like "-fPIC". + shared_ldflag => Extra linking flags used when linking + shared libraries. + module_cppflags + module_cflags + module_ldflags => Has the same function as the corresponding + `shared_' attributes, but for building DSOs. + When unset, they get the same values as the + corresponding `shared_' attributes. + + ar => The library archive command, the default is + "ar". + (NOTE: this is here for future use, it's + not implemented yet) + arflags => Flags to be used with the library archive + command. On Unix, this includes the + command letter, 'r' by default. + + ranlib => The library archive indexing command, the + default is 'ranlib' it it exists. + + unistd => An alternative header to the typical + ''. This is very rarely needed. + + shared_extension => File name extension used for shared + libraries. + obj_extension => File name extension used for object files. + On unix, this defaults to ".o" (NOTE: this + is here for future use, it's not + implemented yet) + exe_extension => File name extension used for executable + files. On unix, this defaults to "" (NOTE: + this is here for future use, it's not + implemented yet) + shlib_variant => A "variant" identifier inserted between the base + shared library name and the extension. On "unixy" + platforms (BSD, Linux, Solaris, MacOS/X, ...) this + supports installation of custom OpenSSL libraries + that don't conflict with other builds of OpenSSL + installed on the system. The variant identifier + becomes part of the SONAME of the library and also + any symbol versions (symbol versions are not used or + needed with MacOS/X). For example, on a system + where a default build would normally create the SSL + shared library as 'libssl.so -> libssl.so.1.1' with + the value of the symlink as the SONAME, a target + definition that sets 'shlib_variant => "-abc"' will + create 'libssl.so -> libssl-abc.so.1.1', again with + an SONAME equal to the value of the symlink. The + symbol versions associated with the variant library + would then be 'OPENSSL_ABC_' rather than + the default 'OPENSSL_'. The string inserted + into symbol versions is obtained by mapping all + letters in the "variant" identifier to upper case + and all non-alphanumeric characters to '_'. + + thread_scheme => The type of threads is used on the + configured platform. Currently known + values are "(unknown)", "pthreads", + "uithreads" (a.k.a solaris threads) and + "winthreads". Except for "(unknown)", the + actual value is currently ignored but may + be used in the future. See further notes + below [2]. + dso_scheme => The type of dynamic shared objects to build + for. This mostly comes into play with + engines, but can be used for other purposes + as well. Valid values are "DLFCN" + (dlopen() et al), "DLFCN_NO_H" (for systems + that use dlopen() et al but do not have + fcntl.h), "DL" (shl_load() et al), "WIN32" + and "VMS". + perlasm_scheme => The perlasm method used to create the + assembler files used when compiling with + assembler implementations. + shared_target => The shared library building method used. + This is a target found in Makefile.shared. + build_scheme => The scheme used to build up a Makefile. + In its simplest form, the value is a string + with the name of the build scheme. + The value may also take the form of a list + of strings, if the build_scheme is to have + some options. In this case, the first + string in the list is the name of the build + scheme. + Currently recognised build scheme is "unified". + For the "unified" build scheme, this item + *must* be an array with the first being the + word "unified" and the second being a word + to identify the platform family. + + multilib => On systems that support having multiple + implementations of a library (typically a + 32-bit and a 64-bit variant), this is used + to have the different variants in different + directories. + + bn_ops => Building options (was just bignum options in + the earlier history of this option, hence the + name). This is a string of words that describe + algorithms' implementation parameters that + are optimal for the designated target platform, + such as the type of integers used to build up + the bignum, different ways to implement certain + ciphers and so on. To fully comprehend the + meaning, the best is to read the affected + source. + The valid words are: + + THIRTY_TWO_BIT bignum limbs are 32 bits, + this is default if no + option is specified, it + works on any supported + system [unless "wider" + limb size is implied in + assembly code]; + BN_LLONG bignum limbs are 32 bits, + but 64-bit 'unsigned long + long' is used internally + in calculations; + SIXTY_FOUR_BIT_LONG bignum limbs are 64 bits + and sizeof(long) is 8; + SIXTY_FOUR_BIT bignums limbs are 64 bits, + but execution environment + is ILP32; + RC4_CHAR RC4 key schedule is made + up of 'unsigned char's; + RC4_INT RC4 key schedule is made + up of 'unsigned int's; + EXPORT_VAR_AS_FN for shared libraries, + export vars as + accessor functions. + + apps_aux_src => Extra source to build apps/openssl and other + apps, as needed by the target and that can be + collected in a library. + apps_init_src => Init source to build apps/openssl and other + apps, as needed by the target. This code + cannot be placed in a library, as the rest + of the code isn't expected to link to it + explicitly. + cpuid_asm_src => assembler implementation of cpuid code as + well as OPENSSL_cleanse(). + Default to mem_clr.c + bn_asm_src => Assembler implementation of core bignum + functions. + Defaults to bn_asm.c + ec_asm_src => Assembler implementation of core EC + functions. + des_asm_src => Assembler implementation of core DES + encryption functions. + Defaults to 'des_enc.c fcrypt_b.c' + aes_asm_src => Assembler implementation of core AES + functions. + Defaults to 'aes_core.c aes_cbc.c' + bf_asm_src => Assembler implementation of core BlowFish + functions. + Defaults to 'bf_enc.c' + md5_asm_src => Assembler implementation of core MD5 + functions. + sha1_asm_src => Assembler implementation of core SHA1, + functions, and also possibly SHA256 and + SHA512 ones. + cast_asm_src => Assembler implementation of core CAST + functions. + Defaults to 'c_enc.c' + rc4_asm_src => Assembler implementation of core RC4 + functions. + Defaults to 'rc4_enc.c rc4_skey.c' + rmd160_asm_src => Assembler implementation of core RMD160 + functions. + rc5_asm_src => Assembler implementation of core RC5 + functions. + Defaults to 'rc5_enc.c' + wp_asm_src => Assembler implementation of core WHIRLPOOL + functions. + cmll_asm_src => Assembler implementation of core CAMELLIA + functions. + Defaults to 'camellia.c cmll_misc.c cmll_cbc.c' + modes_asm_src => Assembler implementation of cipher modes, + currently the functions gcm_gmult_4bit and + gcm_ghash_4bit. + padlock_asm_src => Assembler implementation of core parts of + the padlock engine. This is mandatory on + any platform where the padlock engine might + actually be built. + + +[1] as part of the target configuration, one can have a key called + 'inherit_from' that indicate what other configurations to inherit + data from. These are resolved recursively. + + Inheritance works as a set of default values that can be overridden + by corresponding key values in the inheriting configuration. + + Note 1: any configuration table can be used as a template. + Note 2: pure templates have the attribute 'template => 1' and + cannot be used as build targets. + + If several configurations are given in the 'inherit_from' array, + the values of same attribute are concatenated with space + separation. With this, it's possible to have several smaller + templates for different configuration aspects that can be combined + into a complete configuration. + + instead of a scalar value or an array, a value can be a code block + of the form 'sub { /* your code here */ }'. This code block will + be called with the list of inherited values for that key as + arguments. In fact, the concatenation of strings is really done + by using 'sub { join(" ",@_) }' on the list of inherited values. + + An example: + + "foo" => { + template => 1, + haha => "ha ha", + hoho => "ho", + ignored => "This should not appear in the end result", + }, + "bar" => { + template => 1, + haha => "ah", + hoho => "haho", + hehe => "hehe" + }, + "laughter" => { + inherit_from => [ "foo", "bar" ], + hehe => sub { join(" ",(@_,"!!!")) }, + ignored => "", + } + + The entry for "laughter" will become as follows after processing: + + "laughter" => { + haha => "ha ha ah", + hoho => "ho haho", + hehe => "hehe !!!", + ignored => "" + } + +[2] OpenSSL is built with threading capabilities unless the user + specifies 'no-threads'. The value of the key 'thread_scheme' may + be "(unknown)", in which case the user MUST give some compilation + flags to Configure. + +[3] OpenSSL has three types of things to link from object files or + static libraries: + + - shared libraries; that would be libcrypto and libssl. + - shared objects (sometimes called dynamic libraries); that would + be the engines. + - applications; those are apps/openssl and all the test apps. + + Very roughly speaking, linking is done like this (words in braces + represent the configuration settings documented at the beginning + of this file): + + shared libraries: + {ld} $(CFLAGS) {lflags} {shared_ldflag} -o libfoo.so \ + foo/something.o foo/somethingelse.o {ex_libs} + + shared objects: + {ld} $(CFLAGS) {lflags} {module_ldflags} -o libeng.so \ + blah1.o blah2.o -lcrypto {ex_libs} + + applications: + {ld} $(CFLAGS) {lflags} -o app \ + app1.o utils.o -lssl -lcrypto {ex_libs} + +[4] There are variants of these attribute, prefixed with `lib_', + `dso_' or `bin_'. Those variants replace the unprefixed attribute + when building library, DSO or program modules specifically. + +Historically, the target configurations came in form of a string with +values separated by colons. This use is deprecated. The string form +looked like this: + + "target" => "{cc}:{cflags}:{unistd}:{thread_cflag}:{sys_id}:{lflags}:{bn_ops}:{cpuid_obj}:{bn_obj}:{ec_obj}:{des_obj}:{aes_obj}:{bf_obj}:{md5_obj}:{sha1_obj}:{cast_obj}:{rc4_obj}:{rmd160_obj}:{rc5_obj}:{wp_obj}:{cmll_obj}:{modes_obj}:{padlock_obj}:{perlasm_scheme}:{dso_scheme}:{shared_target}:{shared_cflag}:{shared_ldflag}:{shared_extension}:{ranlib}:{arflags}:{multilib}" + + +Build info files +================ + +The build.info files that are spread over the source tree contain the +minimum information needed to build and distribute OpenSSL. It uses a +simple and yet fairly powerful language to determine what needs to be +built, from what sources, and other relationships between files. + +For every build.info file, all file references are relative to the +directory of the build.info file for source files, and the +corresponding build directory for built files if the build tree +differs from the source tree. + +When processed, every line is processed with the perl module +Text::Template, using the delimiters "{-" and "-}". The hashes +%config and %target are passed to the perl fragments, along with +$sourcedir and $builddir, which are the locations of the source +directory for the current build.info file and the corresponding build +directory, all relative to the top of the build tree. + +To begin with, things to be built are declared by setting specific +variables: + + PROGRAMS=foo bar + LIBS=libsomething + ENGINES=libeng + SCRIPTS=myhack + EXTRA=file1 file2 + +Note that the files mentioned for PROGRAMS, LIBS and ENGINES *must* be +without extensions. The build file templates will figure them out. + +For each thing to be built, it is then possible to say what sources +they are built from: + + PROGRAMS=foo bar + SOURCE[foo]=foo.c common.c + SOURCE[bar]=bar.c extra.c common.c + +It's also possible to tell some other dependencies: + + DEPEND[foo]=libsomething + DEPEND[libbar]=libsomethingelse + +(it could be argued that 'libsomething' and 'libsomethingelse' are +source as well. However, the files given through SOURCE are expected +to be located in the source tree while files given through DEPEND are +expected to be located in the build tree) + +It's also possible to depend on static libraries explicitly: + + DEPEND[foo]=libsomething.a + DEPEND[libbar]=libsomethingelse.a + +This should be rarely used, and care should be taken to make sure it's +only used when supported. For example, native Windows build doesn't +support building static libraries and DLLs at the same time, so using +static libraries on Windows can only be done when configured +'no-shared'. + +One some platforms, shared libraries come with a name that's different +from their static counterpart. That's declared as follows: + + SHARED_NAME[libfoo]=cygfoo-{- $config{shlibver} -} + +The example is from Cygwin, which has a required naming convention. + +Sometimes, it makes sense to rename an output file, for example a +library: + + RENAME[libfoo]=libbar + +That line has "libfoo" renamed to "libbar". While it makes no +sense at all to just have a rename like that (why not just use +"libbar" everywhere?), it does make sense when it can be used +conditionally. See a little further below for an example. + +In some cases, it's desirable to include some source files in the +shared form of a library only: + + SHARED_SOURCE[libfoo]=dllmain.c + +For any file to be built, it's also possible to tell what extra +include paths the build of their source files should use: + + INCLUDE[foo]=include + +In some cases, one might want to generate some source files from +others, that's done as follows: + + GENERATE[foo.s]=asm/something.pl $(CFLAGS) + GENERATE[bar.s]=asm/bar.S + +The value of each GENERATE line is a command line or part of it. +Configure places no rules on the command line, except that the first +item must be the generator file. It is, however, entirely up to the +build file template to define exactly how those command lines should +be handled, how the output is captured and so on. + +Sometimes, the generator file itself depends on other files, for +example if it is a perl script that depends on other perl modules. +This can be expressed using DEPEND like this: + + DEPEND[asm/something.pl]=../perlasm/Foo.pm + +There may also be cases where the exact file isn't easily specified, +but an inclusion directory still needs to be specified. INCLUDE can +be used in that case: + + INCLUDE[asm/something.pl]=../perlasm + +NOTE: GENERATE lines are limited to one command only per GENERATE. + +As a last resort, it's possible to have raw build file lines, between +BEGINRAW and ENDRAW lines as follows: + + BEGINRAW[Makefile(unix)] + haha.h: {- $builddir -}/Makefile + echo "/* haha */" > haha.h + ENDRAW[Makefile(unix)] + +The word within square brackets is the build_file configuration item +or the build_file configuration item followed by the second word in the +build_scheme configuration item for the configured target within +parenthesis as shown above. For example, with the following relevant +configuration items: + + build_file => "build.ninja" + build_scheme => [ "unified", "unix" ] + +... these lines will be considered: + + BEGINRAW[build.ninja] + build haha.h: echo "/* haha */" > haha.h + ENDRAW[build.ninja] + + BEGINRAW[build.ninja(unix)] + build hoho.h: echo "/* hoho */" > hoho.h + ENDRAW[build.ninja(unix)] + +Should it be needed because the recipes within a RAW section might +clash with those generated by Configure, it's possible to tell it +not to generate them with the use of OVERRIDES, for example: + + SOURCE[libfoo]=foo.c bar.c + + OVERRIDES=bar.o + BEGINRAW[Makefile(unix)] + bar.o: bar.c + $(CC) $(CFLAGS) -DSPECIAL -c -o $@ $< + ENDRAW[Makefile(unix)] + +See the documentation further up for more information on configuration +items. + +Finally, you can have some simple conditional use of the build.info +information, looking like this: + + IF[1] + something + ELSIF[2] + something other + ELSE + something else + ENDIF + +The expression in square brackets is interpreted as a string in perl, +and will be seen as true if perl thinks it is, otherwise false. For +example, the above would have "something" used, since 1 is true. + +Together with the use of Text::Template, this can be used as +conditions based on something in the passed variables, for example: + + IF[{- $disabled{shared} -}] + LIBS=libcrypto + SOURCE[libcrypto]=... + ELSE + LIBS=libfoo + SOURCE[libfoo]=... + ENDIF + +or: + + # VMS has a cultural standard where all libraries are prefixed. + # For OpenSSL, the choice is 'ossl_' + IF[{- $config{target} =~ /^vms/ -}] + RENAME[libcrypto]=ossl_libcrypto + RENAME[libssl]=ossl_libssl + ENDIF + + +Build-file programming with the "unified" build system +====================================================== + +"Build files" are called "Makefile" on Unix-like operating systems, +"descrip.mms" for MMS on VMS, "makefile" for nmake on Windows, etc. + +To use the "unified" build system, the target configuration needs to +set the three items 'build_scheme', 'build_file' and 'build_command'. +In the rest of this section, we will assume that 'build_scheme' is set +to "unified" (see the configurations documentation above for the +details). + +For any name given by 'build_file', the "unified" system expects a +template file in Configurations/ named like the build file, with +".tmpl" appended, or in case of possible ambiguity, a combination of +the second 'build_scheme' list item and the 'build_file' name. For +example, if 'build_file' is set to "Makefile", the template could be +Configurations/Makefile.tmpl or Configurations/unix-Makefile.tmpl. +In case both Configurations/unix-Makefile.tmpl and +Configurations/Makefile.tmpl are present, the former takes +precedence. + +The build-file template is processed with the perl module +Text::Template, using "{-" and "-}" as delimiters that enclose the +perl code fragments that generate configuration-dependent content. +Those perl fragments have access to all the hash variables from +configdata.pem. + +The build-file template is expected to define at least the following +perl functions in a perl code fragment enclosed with "{-" and "-}". +They are all expected to return a string with the lines they produce. + + generatesrc - function that produces build file lines to generate + a source file from some input. + + It's called like this: + + generatesrc(src => "PATH/TO/tobegenerated", + generator => [ "generatingfile", ... ] + generator_incs => [ "INCL/PATH", ... ] + generator_deps => [ "dep1", ... ] + generator => [ "generatingfile", ... ] + incs => [ "INCL/PATH", ... ], + deps => [ "dep1", ... ], + intent => one of "libs", "dso", "bin" ); + + 'src' has the name of the file to be generated. + 'generator' is the command or part of command to + generate the file, of which the first item is + expected to be the file to generate from. + generatesrc() is expected to analyse and figure out + exactly how to apply that file and how to capture + the result. 'generator_incs' and 'generator_deps' + are include directories and files that the generator + file itself depends on. 'incs' and 'deps' are + include directories and files that are used if $(CC) + is used as an intermediary step when generating the + end product (the file indicated by 'src'). 'intent' + indicates what the generated file is going to be + used for. + + src2obj - function that produces build file lines to build an + object file from source files and associated data. + + It's called like this: + + src2obj(obj => "PATH/TO/objectfile", + srcs => [ "PATH/TO/sourcefile", ... ], + deps => [ "dep1", ... ], + incs => [ "INCL/PATH", ... ] + intent => one of "lib", "dso", "bin" ); + + 'obj' has the intended object file *without* + extension, src2obj() is expected to add that. + 'srcs' has the list of source files to build the + object file, with the first item being the source + file that directly corresponds to the object file. + 'deps' is a list of explicit dependencies. 'incs' + is a list of include file directories. Finally, + 'intent' indicates what this object file is going + to be used for. + + obj2lib - function that produces build file lines to build a + static library file ("libfoo.a" in Unix terms) from + object files. + + called like this: + + obj2lib(lib => "PATH/TO/libfile", + objs => [ "PATH/TO/objectfile", ... ]); + + 'lib' has the intended library file name *without* + extension, obj2lib is expected to add that. 'objs' + has the list of object files (also *without* + extension) to build this library. + + libobj2shlib - function that produces build file lines to build a + shareable object library file ("libfoo.so" in Unix + terms) from the corresponding static library file + or object files. + + called like this: + + libobj2shlib(shlib => "PATH/TO/shlibfile", + lib => "PATH/TO/libfile", + objs => [ "PATH/TO/objectfile", ... ], + deps => [ "PATH/TO/otherlibfile", ... ]); + + 'lib' has the intended library file name *without* + extension, libobj2shlib is expected to add that. + 'shlib' has the corresponding shared library name + *without* extension. 'deps' has the list of other + libraries (also *without* extension) this library + needs to be linked with. 'objs' has the list of + object files (also *without* extension) to build + this library. + + This function has a choice; it can use the + corresponding static library as input to make the + shared library, or the list of object files. + + obj2dso - function that produces build file lines to build a + dynamic shared object file from object files. + + called like this: + + obj2dso(lib => "PATH/TO/libfile", + objs => [ "PATH/TO/objectfile", ... ], + deps => [ "PATH/TO/otherlibfile", + ... ]); + + This is almost the same as libobj2shlib, but the + intent is to build a shareable library that can be + loaded in runtime (a "plugin"...). The differences + are subtle, one of the most visible ones is that the + resulting shareable library is produced from object + files only. + + obj2bin - function that produces build file lines to build an + executable file from object files. + + called like this: + + obj2bin(bin => "PATH/TO/binfile", + objs => [ "PATH/TO/objectfile", ... ], + deps => [ "PATH/TO/libfile", ... ]); + + 'bin' has the intended executable file name + *without* extension, obj2bin is expected to add + that. 'objs' has the list of object files (also + *without* extension) to build this library. 'deps' + has the list of library files (also *without* + extension) that the programs needs to be linked + with. + + in2script - function that produces build file lines to build a + script file from some input. + + called like this: + + in2script(script => "PATH/TO/scriptfile", + sources => [ "PATH/TO/infile", ... ]); + + 'script' has the intended script file name. + 'sources' has the list of source files to build the + resulting script from. + +In all cases, file file paths are relative to the build tree top, and +the build file actions run with the build tree top as current working +directory. + +Make sure to end the section with these functions with a string that +you thing is appropriate for the resulting build file. If nothing +else, end it like this: + + ""; # Make sure no lingering values end up in the Makefile + -} + + +Configure helper scripts +======================== + +Configure uses helper scripts in this directory: + +Checker scripts +--------------- + +These scripts are per platform family, to check the integrity of the +tools used for configuration and building. The checker script used is +either {build_platform}-{build_file}-checker.pm or +{build_platform}-checker.pm, where {build_platform} is the second +'build_scheme' list element from the configuration target data, and +{build_file} is 'build_file' from the same target data. + +If the check succeeds, the script is expected to end with a non-zero +expression. If the check fails, the script can end with a zero, or +with a `die`. diff --git a/trunk/3rdparty/openssl-1.1-fit/Configurations/README.design b/trunk/3rdparty/openssl-1.1-fit/Configurations/README.design new file mode 100644 index 000000000..5fb2737c2 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/Configurations/README.design @@ -0,0 +1,623 @@ +Design document for the unified scheme data +=========================================== + +How are things connected? +------------------------- + +The unified scheme takes all its data from the build.info files seen +throughout the source tree. These files hold the minimum information +needed to build end product files from diverse sources. See the +section on build.info files below. + +From the information in build.info files, Configure builds up an +information database as a hash table called %unified_info, which is +stored in configdata.pm, found at the top of the build tree (which may +or may not be the same as the source tree). + +Configurations/common.tmpl uses the data from %unified_info to +generate the rules for building end product files as well as +intermediary files with the help of a few functions found in the +build-file templates. See the section on build-file templates further +down for more information. + +build.info files +---------------- + +As mentioned earlier, build.info files are meant to hold the minimum +information needed to build output files, and therefore only (with a +few possible exceptions [1]) have information about end products (such +as scripts, library files and programs) and source files (such as C +files, C header files, assembler files, etc). Intermediate files such +as object files are rarely directly referred to in build.info files (and +when they are, it's always with the file name extension .o), they are +inferred by Configure. By the same rule of minimalism, end product +file name extensions (such as .so, .a, .exe, etc) are never mentioned +in build.info. Their file name extensions will be inferred by the +build-file templates, adapted for the platform they are meant for (see +sections on %unified_info and build-file templates further down). + +The variables PROGRAMS, LIBS, ENGINES and SCRIPTS are used to declare +end products. There are variants for them with '_NO_INST' as suffix +(PROGRAM_NO_INST etc) to specify end products that shouldn't get +installed. + +The variables SOURCE, DEPEND and INCLUDE are indexed by a produced +file, and their values are the source used to produce that particular +produced file, extra dependencies, and include directories needed. + +All their values in all the build.info throughout the source tree are +collected together and form a set of programs, libraries, engines and +scripts to be produced, source files, dependencies, etc etc etc. + +Let's have a pretend example, a very limited contraption of OpenSSL, +composed of the program 'apps/openssl', the libraries 'libssl' and +'libcrypto', an engine 'engines/ossltest' and their sources and +dependencies. + + # build.info + LIBS=libcrypto libssl + INCLUDE[libcrypto]=include + INCLUDE[libssl]=include + DEPEND[libssl]=libcrypto + +This is the top directory build.info file, and it tells us that two +libraries are to be built, the include directory 'include/' shall be +used throughout when building anything that will end up in each +library, and that the library 'libssl' depend on the library +'libcrypto' to function properly. + + # apps/build.info + PROGRAMS=openssl + SOURCE[openssl]=openssl.c + INCLUDE[openssl]=.. ../include + DEPEND[openssl]=../libssl + +This is the build.info file in 'apps/', one may notice that all file +paths mentioned are relative to the directory the build.info file is +located in. This one tells us that there's a program to be built +called 'apps/openssl' (the file name extension will depend on the +platform and is therefore not mentioned in the build.info file). It's +built from one source file, 'apps/openssl.c', and building it requires +the use of '.' and 'include' include directories (both are declared +from the point of view of the 'apps/' directory), and that the program +depends on the library 'libssl' to function properly. + + # crypto/build.info + LIBS=../libcrypto + SOURCE[../libcrypto]=aes.c evp.c cversion.c + DEPEND[cversion.o]=buildinf.h + + GENERATE[buildinf.h]=../util/mkbuildinf.pl "$(CC) $(CFLAGS)" "$(PLATFORM)" + DEPEND[buildinf.h]=../Makefile + DEPEND[../util/mkbuildinf.pl]=../util/Foo.pm + +This is the build.info file in 'crypto', and it tells us a little more +about what's needed to produce 'libcrypto'. LIBS is used again to +declare that 'libcrypto' is to be produced. This declaration is +really unnecessary as it's already mentioned in the top build.info +file, but can make the info file easier to understand. This is to +show that duplicate information isn't an issue. + +This build.info file informs us that 'libcrypto' is built from a few +source files, 'crypto/aes.c', 'crypto/evp.c' and 'crypto/cversion.c'. +It also shows us that building the object file inferred from +'crypto/cversion.c' depends on 'crypto/buildinf.h'. Finally, it +also shows the possibility to declare how some files are generated +using some script, in this case a perl script, and how such scripts +can be declared to depend on other files, in this case a perl module. + +Two things are worth an extra note: + +'DEPEND[cversion.o]' mentions an object file. DEPEND indexes is the +only location where it's valid to mention them + +Lines in 'BEGINRAW'..'ENDRAW' sections must always mention files as +seen from the top directory, no exception. + + # ssl/build.info + LIBS=../libssl + SOURCE[../libssl]=tls.c + +This is the build.info file in 'ssl/', and it tells us that the +library 'libssl' is built from the source file 'ssl/tls.c'. + + # engines/build.info + ENGINES=dasync + SOURCE[dasync]=e_dasync.c + DEPEND[dasync]=../libcrypto + INCLUDE[dasync]=../include + + ENGINES_NO_INST=ossltest + SOURCE[ossltest]=e_ossltest.c + DEPEND[ossltest]=../libcrypto.a + INCLUDE[ossltest]=../include + +This is the build.info file in 'engines/', telling us that two engines +called 'engines/dasync' and 'engines/ossltest' shall be built, that +dasync's source is 'engines/e_dasync.c' and ossltest's source is +'engines/e_ossltest.c' and that the include directory 'include/' may +be used when building anything that will be part of these engines. +Also, both engines depend on the library 'libcrypto' to function +properly. ossltest is explicitly linked with the static variant of +the library 'libcrypto'. Finally, only dasync is being installed, as +ossltest is only for internal testing. + +When Configure digests these build.info files, the accumulated +information comes down to this: + + LIBS=libcrypto libssl + SOURCE[libcrypto]=crypto/aes.c crypto/evp.c crypto/cversion.c + DEPEND[crypto/cversion.o]=crypto/buildinf.h + INCLUDE[libcrypto]=include + SOURCE[libssl]=ssl/tls.c + INCLUDE[libssl]=include + DEPEND[libssl]=libcrypto + + PROGRAMS=apps/openssl + SOURCE[apps/openssl]=apps/openssl.c + INCLUDE[apps/openssl]=. include + DEPEND[apps/openssl]=libssl + + ENGINES=engines/dasync + SOURCE[engines/dasync]=engines/e_dasync.c + DEPEND[engines/dasync]=libcrypto + INCLUDE[engines/dasync]=include + + ENGINES_NO_INST=engines/ossltest + SOURCE[engines/ossltest]=engines/e_ossltest.c + DEPEND[engines/ossltest]=libcrypto.a + INCLUDE[engines/ossltest]=include + + GENERATE[crypto/buildinf.h]=util/mkbuildinf.pl "$(CC) $(CFLAGS)" "$(PLATFORM)" + DEPEND[crypto/buildinf.h]=Makefile + DEPEND[util/mkbuildinf.pl]=util/Foo.pm + + +A few notes worth mentioning: + +LIBS may be used to declare routine libraries only. + +PROGRAMS may be used to declare programs only. + +ENGINES may be used to declare engines only. + +The indexes for SOURCE must only be end product files, such as +libraries, programs or engines. The values of SOURCE variables must +only be source files (possibly generated). + +INCLUDE and DEPEND shows a relationship between different files +(usually produced files) or between files and directories, such as a +program depending on a library, or between an object file and some +extra source file. + +When Configure processes the build.info files, it will take it as +truth without question, and will therefore perform very few checks. +If the build tree is separate from the source tree, it will assume +that all built files and up in the build directory and that all source +files are to be found in the source tree, if they can be found there. +Configure will assume that source files that can't be found in the +source tree (such as 'crypto/bildinf.h' in the example above) are +generated and will be found in the build tree. + + +The %unified_info database +-------------------------- + +The information in all the build.info get digested by Configure and +collected into the %unified_info database, divided into the following +indexes: + + depends => a hash table containing 'file' => [ 'dependency' ... ] + pairs. These are directly inferred from the DEPEND + variables in build.info files. + + engines => a list of engines. These are directly inferred from + the ENGINES variable in build.info files. + + generate => a hash table containing 'file' => [ 'generator' ... ] + pairs. These are directly inferred from the GENERATE + variables in build.info files. + + includes => a hash table containing 'file' => [ 'include' ... ] + pairs. These are directly inferred from the INCLUDE + variables in build.info files. + + install => a hash table containing 'type' => [ 'file' ... ] pairs. + The types are 'programs', 'libraries', 'engines' and + 'scripts', and the array of files list the files of + that type that should be installed. + + libraries => a list of libraries. These are directly inferred from + the LIBS variable in build.info files. + + programs => a list of programs. These are directly inferred from + the PROGRAMS variable in build.info files. + + rawlines => a list of build-file lines. These are a direct copy of + the BEGINRAW..ENDRAW lines in build.info files. Note: + only the BEGINRAW..ENDRAW section for the current + platform are copied, the rest are ignored. + + scripts => a list of scripts. There are directly inferred from + the SCRIPTS variable in build.info files. + + sources => a hash table containing 'file' => [ 'sourcefile' ... ] + pairs. These are indirectly inferred from the SOURCE + variables in build.info files. Object files are + mentioned in this hash table, with source files from + SOURCE variables, and AS source files for programs and + libraries. + + shared_sources => + a hash table just like 'sources', but only as source + files (object files) for building shared libraries. + +As an example, here is how the build.info files example from the +section above would be digested into a %unified_info table: + + our %unified_info = ( + "depends" => + { + "apps/openssl" => + [ + "libssl", + ], + "crypto/buildinf.h" => + [ + "Makefile", + ], + "crypto/cversion.o" => + [ + "crypto/buildinf.h", + ], + "engines/dasync" => + [ + "libcrypto", + ], + "engines/ossltest" => + [ + "libcrypto.a", + ], + "libssl" => + [ + "libcrypto", + ], + "util/mkbuildinf.pl" => + [ + "util/Foo.pm", + ], + }, + "engines" => + [ + "engines/dasync", + "engines/ossltest", + ], + "generate" => + { + "crypto/buildinf.h" => + [ + "util/mkbuildinf.pl", + "\"\$(CC)", + "\$(CFLAGS)\"", + "\"$(PLATFORM)\"", + ], + }, + "includes" => + { + "apps/openssl" => + [ + ".", + "include", + ], + "engines/ossltest" => + [ + "include" + ], + "libcrypto" => + [ + "include", + ], + "libssl" => + [ + "include", + ], + "util/mkbuildinf.pl" => + [ + "util", + ], + } + "install" => + { + "engines" => + [ + "engines/dasync", + ], + "libraries" => + [ + "libcrypto", + "libssl", + ], + "programs" => + [ + "apps/openssl", + ], + }, + "libraries" => + [ + "libcrypto", + "libssl", + ], + "programs" => + [ + "apps/openssl", + ], + "rawlines" => + [ + ], + "sources" => + { + "apps/openssl" => + [ + "apps/openssl.o", + ], + "apps/openssl.o" => + [ + "apps/openssl.c", + ], + "crypto/aes.o" => + [ + "crypto/aes.c", + ], + "crypto/cversion.o" => + [ + "crypto/cversion.c", + ], + "crypto/evp.o" => + [ + "crypto/evp.c", + ], + "engines/e_dasync.o" => + [ + "engines/e_dasync.c", + ], + "engines/dasync" => + [ + "engines/e_dasync.o", + ], + "engines/e_ossltest.o" => + [ + "engines/e_ossltest.c", + ], + "engines/ossltest" => + [ + "engines/e_ossltest.o", + ], + "libcrypto" => + [ + "crypto/aes.c", + "crypto/cversion.c", + "crypto/evp.c", + ], + "libssl" => + [ + "ssl/tls.c", + ], + "ssl/tls.o" => + [ + "ssl/tls.c", + ], + }, + ); + +As can be seen, everything in %unified_info is fairly simple suggest +of information. Still, it tells us that to build all programs, we +must build 'apps/openssl', and to build the latter, we will need to +build all its sources ('apps/openssl.o' in this case) and all the +other things it depends on (such as 'libssl'). All those dependencies +need to be built as well, using the same logic, so to build 'libssl', +we need to build 'ssl/tls.o' as well as 'libcrypto', and to build the +latter... + + +Build-file templates +-------------------- + +Build-file templates are essentially build-files (such as Makefile on +Unix) with perl code fragments mixed in. Those perl code fragment +will generate all the configuration dependent data, including all the +rules needed to build end product files and intermediary files alike. +At a minimum, there must be a perl code fragment that defines a set of +functions that are used to generates specific build-file rules, to +build static libraries from object files, to build shared libraries +from static libraries, to programs from object files and libraries, +etc. + + generatesrc - function that produces build file lines to generate + a source file from some input. + + It's called like this: + + generatesrc(src => "PATH/TO/tobegenerated", + generator => [ "generatingfile", ... ] + generator_incs => [ "INCL/PATH", ... ] + generator_deps => [ "dep1", ... ] + incs => [ "INCL/PATH", ... ], + deps => [ "dep1", ... ], + intent => one of "libs", "dso", "bin" ); + + 'src' has the name of the file to be generated. + 'generator' is the command or part of command to + generate the file, of which the first item is + expected to be the file to generate from. + generatesrc() is expected to analyse and figure out + exactly how to apply that file and how to capture + the result. 'generator_incs' and 'generator_deps' + are include directories and files that the generator + file itself depends on. 'incs' and 'deps' are + include directories and files that are used if $(CC) + is used as an intermediary step when generating the + end product (the file indicated by 'src'). 'intent' + indicates what the generated file is going to be + used for. + + src2obj - function that produces build file lines to build an + object file from source files and associated data. + + It's called like this: + + src2obj(obj => "PATH/TO/objectfile", + srcs => [ "PATH/TO/sourcefile", ... ], + deps => [ "dep1", ... ], + incs => [ "INCL/PATH", ... ] + intent => one of "lib", "dso", "bin" ); + + 'obj' has the intended object file *without* + extension, src2obj() is expected to add that. + 'srcs' has the list of source files to build the + object file, with the first item being the source + file that directly corresponds to the object file. + 'deps' is a list of explicit dependencies. 'incs' + is a list of include file directories. Finally, + 'intent' indicates what this object file is going + to be used for. + + obj2lib - function that produces build file lines to build a + static library file ("libfoo.a" in Unix terms) from + object files. + + called like this: + + obj2lib(lib => "PATH/TO/libfile", + objs => [ "PATH/TO/objectfile", ... ]); + + 'lib' has the intended library file name *without* + extension, obj2lib is expected to add that. 'objs' + has the list of object files (also *without* + extension) to build this library. + + libobj2shlib - function that produces build file lines to build a + shareable object library file ("libfoo.so" in Unix + terms) from the corresponding static library file + or object files. + + called like this: + + libobj2shlib(shlib => "PATH/TO/shlibfile", + lib => "PATH/TO/libfile", + objs => [ "PATH/TO/objectfile", ... ], + deps => [ "PATH/TO/otherlibfile", ... ]); + + 'lib' has the intended library file name *without* + extension, libobj2shlib is expected to add that. + 'shlib' has the corresponding shared library name + *without* extension. 'deps' has the list of other + libraries (also *without* extension) this library + needs to be linked with. 'objs' has the list of + object files (also *without* extension) to build + this library. + + This function has a choice; it can use the + corresponding static library as input to make the + shared library, or the list of object files. + + obj2dynlib - function that produces build file lines to build a + dynamically loadable library file ("libfoo.so" on + Unix) from object files. + + called like this: + + obj2dynlib(lib => "PATH/TO/libfile", + objs => [ "PATH/TO/objectfile", ... ], + deps => [ "PATH/TO/otherlibfile", + ... ]); + + This is almost the same as libobj2shlib, but the + intent is to build a shareable library that can be + loaded in runtime (a "plugin"...). The differences + are subtle, one of the most visible ones is that the + resulting shareable library is produced from object + files only. + + obj2bin - function that produces build file lines to build an + executable file from object files. + + called like this: + + obj2bin(bin => "PATH/TO/binfile", + objs => [ "PATH/TO/objectfile", ... ], + deps => [ "PATH/TO/libfile", ... ]); + + 'bin' has the intended executable file name + *without* extension, obj2bin is expected to add + that. 'objs' has the list of object files (also + *without* extension) to build this library. 'deps' + has the list of library files (also *without* + extension) that the programs needs to be linked + with. + + in2script - function that produces build file lines to build a + script file from some input. + + called like this: + + in2script(script => "PATH/TO/scriptfile", + sources => [ "PATH/TO/infile", ... ]); + + 'script' has the intended script file name. + 'sources' has the list of source files to build the + resulting script from. + +Along with the build-file templates is the driving engine +Configurations/common.tmpl, which looks through all the information in +%unified_info and generates all the rulesets to build libraries, +programs and all intermediate files, using the rule generating +functions defined in the build-file template. + +As an example with the smaller build.info set we've seen as an +example, producing the rules to build 'libcrypto' would result in the +following calls: + + # Note: libobj2shlib will only be called if shared libraries are + # to be produced. + # Note 2: libobj2shlib gets both the name of the static library + # and the names of all the object files that go into it. It's up + # to the implementation to decide which to use as input. + # Note 3: common.tmpl peals off the ".o" extension from all object + # files, as the platform at hand may have a different one. + libobj2shlib(shlib => "libcrypto", + lib => "libcrypto", + objs => [ "crypto/aes", "crypto/evp", "crypto/cversion" ], + deps => [ ]); + + obj2lib(lib => "libcrypto" + objs => [ "crypto/aes", "crypto/evp", "crypto/cversion" ]); + + src2obj(obj => "crypto/aes" + srcs => [ "crypto/aes.c" ], + deps => [ ], + incs => [ "include" ], + intent => "lib"); + + src2obj(obj => "crypto/evp" + srcs => [ "crypto/evp.c" ], + deps => [ ], + incs => [ "include" ], + intent => "lib"); + + src2obj(obj => "crypto/cversion" + srcs => [ "crypto/cversion.c" ], + deps => [ "crypto/buildinf.h" ], + incs => [ "include" ], + intent => "lib"); + + generatesrc(src => "crypto/buildinf.h", + generator => [ "util/mkbuildinf.pl", "\"$(CC)", + "$(CFLAGS)\"", "\"$(PLATFORM)\"" ], + generator_incs => [ "util" ], + generator_deps => [ "util/Foo.pm" ], + incs => [ ], + deps => [ ], + intent => "lib"); + +The returned strings from all those calls are then concatenated +together and written to the resulting build-file. diff --git a/trunk/3rdparty/openssl-1.1-fit/Configurations/common.tmpl b/trunk/3rdparty/openssl-1.1-fit/Configurations/common.tmpl new file mode 100644 index 000000000..3a466eeb6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/Configurations/common.tmpl @@ -0,0 +1,221 @@ +{- # -*- Mode: perl -*- + + use File::Basename; + + # A cache of objects for which a recipe has already been generated + my %cache; + + # resolvedepends and reducedepends work in tandem to make sure + # there are no duplicate dependencies and that they are in the + # right order. This is especially used to sort the list of + # libraries that a build depends on. + sub extensionlesslib { + my @result = map { $_ =~ /(\.a)?$/; $` } @_; + return @result if wantarray; + return $result[0]; + } + sub resolvedepends { + my $thing = shift; + my $extensionlessthing = extensionlesslib($thing); + my @listsofar = @_; # to check if we're looping + my @list = @{$unified_info{depends}->{$thing} // + $unified_info{depends}->{$extensionlessthing}}; + my @newlist = (); + if (scalar @list) { + foreach my $item (@list) { + my $extensionlessitem = extensionlesslib($item); + # It's time to break off when the dependency list starts looping + next if grep { extensionlesslib($_) eq $extensionlessitem } @listsofar; + push @newlist, $item, resolvedepends($item, @listsofar, $item); + } + } + @newlist; + } + sub reducedepends { + my @list = @_; + my @newlist = (); + my %replace = (); + while (@list) { + my $item = shift @list; + my $extensionlessitem = extensionlesslib($item); + if (grep { $extensionlessitem eq extensionlesslib($_) } @list) { + if ($item ne $extensionlessitem) { + # If this instance of the library is explicitly static, we + # prefer that to any shared library name, since it must have + # been done on purpose. + $replace{$extensionlessitem} = $item; + } + } else { + push @newlist, $item; + } + } + map { $replace{$_} // $_; } @newlist; + } + + # is_installed checks if a given file will be installed (i.e. they are + # not defined _NO_INST in build.info) + sub is_installed { + my $product = shift; + if (grep { $product eq $_ } + map { (@{$unified_info{install}->{$_}}) } + keys %{$unified_info{install}}) { + return 1; + } + return 0; + } + + # dogenerate is responsible for producing all the recipes that build + # generated source files. It recurses in case a dependency is also a + # generated source file. + sub dogenerate { + my $src = shift; + return "" if $cache{$src}; + my $obj = shift; + my $bin = shift; + my %opts = @_; + if ($unified_info{generate}->{$src}) { + die "$src is generated by Configure, should not appear in build file\n" + if ref $unified_info{generate}->{$src} eq ""; + my $script = $unified_info{generate}->{$src}->[0]; + $OUT .= generatesrc(src => $src, + generator => $unified_info{generate}->{$src}, + generator_incs => $unified_info{includes}->{$script}, + generator_deps => $unified_info{depends}->{$script}, + deps => $unified_info{depends}->{$src}, + incs => $unified_info{includes}->{$obj}, + %opts); + foreach (@{$unified_info{depends}->{$src}}) { + dogenerate($_, $obj, $bin, %opts); + } + } + $cache{$src} = 1; + } + + # doobj is responsible for producing all the recipes that build + # object files as well as dependency files. + sub doobj { + my $obj = shift; + return "" if $cache{$obj}; + my $bin = shift; + my %opts = @_; + if (@{$unified_info{sources}->{$obj}}) { + $OUT .= src2obj(obj => $obj, + product => $bin, + srcs => $unified_info{sources}->{$obj}, + deps => $unified_info{depends}->{$obj}, + incs => $unified_info{includes}->{$obj}, + %opts); + foreach ((@{$unified_info{sources}->{$obj}}, + @{$unified_info{depends}->{$obj}})) { + dogenerate($_, $obj, $bin, %opts); + } + } + $cache{$obj} = 1; + } + + # dolib is responsible for building libraries. It will call + # libobj2shlib is shared libraries are produced, and obj2lib in all + # cases. It also makes sure all object files for the library are + # built. + sub dolib { + my $lib = shift; + return "" if $cache{$lib}; + unless ($disabled{shared} || $lib =~ /\.a$/) { + $OUT .= libobj2shlib(shlib => $unified_info{sharednames}->{$lib}, + lib => $lib, + objs => [ @{$unified_info{shared_sources}->{$lib}}, + @{$unified_info{sources}->{$lib}} ], + deps => [ reducedepends(resolvedepends($lib)) ], + installed => is_installed($lib)); + foreach ((@{$unified_info{shared_sources}->{$lib}}, + @{$unified_info{sources}->{$lib}})) { + # If this is somehow a compiled object, take care of it that way + # Otherwise, it might simply be generated + if (defined $unified_info{sources}->{$_}) { + doobj($_, $lib, intent => "lib", installed => is_installed($lib)); + } else { + dogenerate($_, undef, undef, intent => "lib"); + } + } + } + $OUT .= obj2lib(lib => $lib, + objs => [ @{$unified_info{sources}->{$lib}} ]); + foreach (@{$unified_info{sources}->{$lib}}) { + doobj($_, $lib, intent => "lib", installed => is_installed($lib)); + } + $cache{$lib} = 1; + } + + # doengine is responsible for building engines. It will call + # obj2dso, and also makes sure all object files for the library + # are built. + sub doengine { + my $lib = shift; + return "" if $cache{$lib}; + $OUT .= obj2dso(lib => $lib, + objs => [ @{$unified_info{sources}->{$lib}}, + @{$unified_info{shared_sources}->{$lib}} ], + deps => [ resolvedepends($lib) ], + installed => is_installed($lib)); + foreach ((@{$unified_info{sources}->{$lib}}, + @{$unified_info{shared_sources}->{$lib}})) { + doobj($_, $lib, intent => "dso", installed => is_installed($lib)); + } + $cache{$lib} = 1; + } + + # dobin is responsible for building programs. It will call obj2bin, + # and also makes sure all object files for the library are built. + sub dobin { + my $bin = shift; + return "" if $cache{$bin}; + my $deps = [ reducedepends(resolvedepends($bin)) ]; + $OUT .= obj2bin(bin => $bin, + objs => [ @{$unified_info{sources}->{$bin}} ], + deps => $deps, + installed => is_installed($bin)); + foreach (@{$unified_info{sources}->{$bin}}) { + doobj($_, $bin, intent => "bin", installed => is_installed($bin)); + } + $cache{$bin} = 1; + } + + # dobin is responsible for building scripts from templates. It will + # call in2script. + sub doscript { + my $script = shift; + return "" if $cache{$script}; + $OUT .= in2script(script => $script, + sources => $unified_info{sources}->{$script}, + installed => is_installed($script)); + $cache{$script} = 1; + } + + sub dodir { + my $dir = shift; + return "" if !exists(&generatedir) or $cache{$dir}; + $OUT .= generatedir(dir => $dir, + deps => $unified_info{dirinfo}->{$dir}->{deps}, + %{$unified_info{dirinfo}->{$_}->{products}}); + $cache{$dir} = 1; + } + + # Start with populating the cache with all the overrides + %cache = map { $_ => 1 } @{$unified_info{overrides}}; + + # Build mandatory generated headers + foreach (@{$unified_info{depends}->{""}}) { dogenerate($_); } + + # Build all known libraries, engines, programs and scripts. + # Everything else will be handled as a consequence. + foreach (@{$unified_info{libraries}}) { dolib($_); } + foreach (@{$unified_info{engines}}) { doengine($_); } + foreach (@{$unified_info{programs}}) { dobin($_); } + foreach (@{$unified_info{scripts}}) { doscript($_); } + + foreach (sort keys %{$unified_info{dirinfo}}) { dodir($_); } + + # Finally, should there be any applicable BEGINRAW/ENDRAW sections, + # they are added here. + $OUT .= $_."\n" foreach @{$unified_info{rawlines}}; +-} diff --git a/trunk/3rdparty/openssl-1.1-fit/Configurations/common0.tmpl b/trunk/3rdparty/openssl-1.1-fit/Configurations/common0.tmpl new file mode 100644 index 000000000..03acb3e0b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/Configurations/common0.tmpl @@ -0,0 +1,31 @@ +{- # -*- Mode: perl -*- + + # Commonly used list of generated files + # The reason for the complexity is that the build.info files provide + # GENERATE rules for *all* platforms without discrimination, while the + # build files only want those for a particular build. Therefore, we + # need to extrapolate exactly what we need to generate. The way to do + # that is to extract all possible source files from diverse tables and + # filter out all that are not generated + my %generatables = + map { $_ => 1 } + ( # The sources of stuff may be generated + ( map { @{$unified_info{sources}->{$_}} } + keys %{$unified_info{sources}} ), + $disabled{shared} + ? () + : ( map { @{$unified_info{shared_sources}->{$_}} } + keys %{$unified_info{shared_sources}} ), + # Things we explicitly depend on are usually generated + ( map { $_ eq "" ? () : @{$unified_info{depends}->{$_}} } + keys %{$unified_info{depends}} )); + our @generated = + sort ( ( grep { defined $unified_info{generate}->{$_} } + sort keys %generatables ), + # Scripts are assumed to be generated, so add thhem too + ( grep { defined $unified_info{sources}->{$_} } + @{$unified_info{scripts}} ) ); + + # Avoid strange output + ""; +-} diff --git a/trunk/3rdparty/openssl-1.1-fit/Configurations/descrip.mms.tmpl b/trunk/3rdparty/openssl-1.1-fit/Configurations/descrip.mms.tmpl new file mode 100644 index 000000000..0ccd5f075 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/Configurations/descrip.mms.tmpl @@ -0,0 +1,1125 @@ +## descrip.mms to build OpenSSL on OpenVMS +## +## {- join("\n## ", @autowarntext) -} +{- + use File::Spec::Functions qw/:DEFAULT abs2rel rel2abs/; + use File::Basename; + + # Our prefix, claimed when speaking with the VSI folks Tuesday + # January 26th 2016 + our $osslprefix = 'OSSL$'; + (our $osslprefix_q = $osslprefix) =~ s/\$/\\\$/; + + our $sover_dirname = sprintf "%02d%02d", split(/\./, $config{shlib_version_number}); + our $osslver = sprintf "%02d%02d", split(/\./, $config{version}); + + our $sourcedir = $config{sourcedir}; + our $builddir = $config{builddir}; + sub sourcefile { + catfile($sourcedir, @_); + } + sub buildfile { + catfile($builddir, @_); + } + sub sourcedir { + catdir($sourcedir, @_); + } + sub builddir { + catdir($builddir, @_); + } + sub tree { + (my $x = shift) =~ s|\]$|...]|; + $x + } + sub move { + my $f = catdir(@_); + my $b = abs2rel(rel2abs("."),rel2abs($f)); + $sourcedir = catdir($b,$sourcedir) + if !file_name_is_absolute($sourcedir); + $builddir = catdir($b,$builddir) + if !file_name_is_absolute($builddir); + ""; + } + + # Because we need to make two computations of these data, + # we store them in arrays for reuse + our @libs = + map { (my $x = $_) =~ s/\.a$//; $x } + @{$unified_info{libraries}}; + our @shlibs = + map { $unified_info{sharednames}->{$_} || () } + grep(!/\.a$/, @{$unified_info{libraries}}); + our @install_libs = + map { (my $x = $_) =~ s/\.a$//; $x } + @{$unified_info{install}->{libraries}}; + our @install_shlibs = + map { $unified_info{sharednames}->{$_} || () } + grep(!/\.a$/, @{$unified_info{install}->{libraries}}); + + # This is a horrible hack, but is needed because recursive inclusion of files + # in different directories does not work well with HP C. + my $sd = sourcedir("crypto", "async", "arch"); + foreach (grep /\[\.crypto\.async\.arch\].*\.o$/, keys %{$unified_info{sources}}) { + (my $x = $_) =~ s|\.o$|.OBJ|; + $unified_info{before}->{$x} + = qq(arch_include = F\$PARSE("$sd","A.;",,,"SYNTAX_ONLY") - "A.;" + define arch 'arch_include'); + $unified_info{after}->{$x} + = qq(deassign arch); + } + my $sd1 = sourcedir("ssl","record"); + my $sd2 = sourcedir("ssl","statem"); + my @ssl_locl_users = grep(/^\[\.(?:ssl\.(?:record|statem)|test)\].*\.o$/, + keys %{$unified_info{sources}}); + foreach (@ssl_locl_users) { + (my $x = $_) =~ s|\.o$|.OBJ|; + $unified_info{before}->{$x} + = qq(record_include = F\$PARSE("$sd1","A.;",,,"SYNTAX_ONLY") - "A.;" + define record 'record_include' + statem_include = F\$PARSE("$sd2","A.;",,,"SYNTAX_ONLY") - "A.;" + define statem 'statem_include'); + $unified_info{after}->{$x} + = qq(deassign statem + deassign record); + } + # This makes sure things get built in the order they need + # to. You're welcome. + sub dependmagic { + my $target = shift; + + return "$target : build_generated\n\t\pipe \$(MMS) \$(MMSQUALIFIERS) depend && \$(MMS) \$(MMSQUALIFIERS) _$target\n_$target"; + } + #use Data::Dumper; + #print STDERR "DEBUG: before:\n", Dumper($unified_info{before}); + #print STDERR "DEBUG: after:\n", Dumper($unified_info{after}); + ""; +-} +PLATFORM={- $config{target} -} +OPTIONS={- $config{options} -} +CONFIGURE_ARGS=({- join(", ",quotify_l(@{$config{perlargv}})) -}) +SRCDIR={- $config{sourcedir} -} +BLDDIR={- $config{builddir} -} + +# Allow both V and VERBOSE to indicate verbosity. This only applies +# to testing. +VERBOSE=$(V) + +VERSION={- $config{version} -} +MAJOR={- $config{major} -} +MINOR={- $config{minor} -} +SHLIB_VERSION_NUMBER={- $config{shlib_version_number} -} +SHLIB_VERSION_HISTORY={- $config{shlib_version_history} -} +SHLIB_MAJOR={- $config{shlib_major} -} +SHLIB_MINOR={- $config{shlib_minor} -} +SHLIB_TARGET={- $target{shared_target} -} + +EXE_EXT=.EXE +LIB_EXT=.OLB +SHLIB_EXT=.EXE +OBJ_EXT=.OBJ +DEP_EXT=.D + +LIBS={- join(", ", map { "-\n\t".$_.".OLB" } @libs) -} +SHLIBS={- join(", ", map { "-\n\t".$_.".EXE" } @shlibs) -} +ENGINES={- join(", ", map { "-\n\t".$_.".EXE" } @{$unified_info{engines}}) -} +PROGRAMS={- join(", ", map { "-\n\t".$_.".EXE" } @{$unified_info{programs}}) -} +SCRIPTS={- join(", ", map { "-\n\t".$_ } @{$unified_info{scripts}}) -} +{- output_off() if $disabled{makedepend}; "" -} +DEPS={- our @deps = map { (my $x = $_) =~ s|\.o$|\$(DEP_EXT)|; $x; } + grep { $unified_info{sources}->{$_}->[0] =~ /\.c$/ } + keys %{$unified_info{sources}}; + join(", ", map { "-\n\t".$_ } @deps); -} +{- output_on() if $disabled{makedepend}; "" -} +GENERATED_MANDATORY={- join(", ", map { "-\n\t".$_ } @{$unified_info{depends}->{""}} ) -} +GENERATED={- # common0.tmpl provides @generated + join(", ", map { (my $x = $_) =~ s|\.[sS]$|.asm|; "-\n\t".$x } + @generated) -} + +INSTALL_LIBS={- join(", ", map { "-\n\t".$_.".OLB" } @install_libs) -} +INSTALL_SHLIBS={- join(", ", map { "-\n\t".$_.".EXE" } @install_shlibs) -} +INSTALL_ENGINES={- join(", ", map { "-\n\t".$_.".EXE" } @{$unified_info{install}->{engines}}) -} +INSTALL_PROGRAMS={- join(", ", map { "-\n\t".$_.".EXE" } @{$unified_info{install}->{programs}}) -} +{- output_off() if $disabled{apps}; "" -} +BIN_SCRIPTS=[.tools]c_rehash.pl +MISC_SCRIPTS=[.apps]CA.pl, [.apps]tsget.pl +{- output_on() if $disabled{apps}; "" -} + +APPS_OPENSSL={- use File::Spec::Functions; + catfile("apps","openssl") -} + +# DESTDIR is for package builders so that they can configure for, say, +# SYS$COMMON:[OPENSSL] and yet have everything installed in STAGING:[USER]. +# In that case, configure with --prefix=SYS$COMMON:[OPENSSL] and then run +# MMS with /MACROS=(DESTDIR=STAGING:[USER]). The result will end up in +# STAGING:[USER.OPENSSL]. +# Normally it is left empty. +DESTDIR= + +# Do not edit this manually. Use Configure --prefix=DIR to change this! +INSTALLTOP={- our $installtop = + catdir($config{prefix}) || "SYS\$COMMON:[OPENSSL]"; + $installtop -} +SYSTARTUP={- catdir($installtop, '[.SYS$STARTUP]'); -} +# This is the standard central area to store certificates, private keys... +OPENSSLDIR={- catdir($config{openssldir}) or + $config{prefix} ? catdir($config{prefix},"COMMON") + : "SYS\$COMMON:[OPENSSL-COMMON]" -} +# The same, but for C +OPENSSLDIR_C={- $osslprefix -}DATAROOT:[000000] +# Where installed engines reside, for C +ENGINESDIR_C={- $osslprefix -}ENGINES{- $sover_dirname.$target{pointer_size} -}: + +##### User defined commands and flags ################################ + +CC={- $config{CC} -} +CPP={- $config{CPP} -} +DEFINES={- our $defines1 = join('', map { ",$_" } @{$config{CPPDEFINES}}) -} +INCLUDES={- our $includes1 = join(',', @{$config{CPPINCLUDES}}) -} +CPPFLAGS={- our $cppflags1 = join('', @{$config{CPPFLAGS}}) -} +CFLAGS={- join('', @{$config{CFLAGS}}) -} +LDFLAGS={- join('', @{$config{LFLAGS}}) -} +EX_LIBS={- join('', map { ",$_" } @{$config{LDLIBS}}) -} + +PERL={- $config{PERL} -} + +AS={- $config{AS} -} +ASFLAGS={- join(' ', @{$config{ASFLAGS}}) -} + +##### Special command flags ########################################## + +ASOUTFLAG={- $target{asoutflag} -}$(OSSL_EMPTY) + +##### Project flags ################################################## + +# Variables starting with CNF_ are common variables for all product types + +CNF_ASFLAGS={- join('', $target{asflags} || (), + @{$config{asflags}}) -} +CNF_DEFINES={- our $defines2 = join('', map { ",$_" } @{$target{defines}}, + @{$config{defines}}) -} +CNF_INCLUDES={- our $includes2 = join(',', @{$target{includes}}, + @{$config{includes}}) -} +CNF_CPPFLAGS={- our $cppflags2 = join('', $target{cppflags} || (), + @{$config{cppflags}}) -} +CNF_CFLAGS={- join('', $target{cflags} || (), + @{$config{cflags}}) -} +CNF_CXXFLAGS={- join('', $target{cxxflags} || (), + @{$config{cxxflags}}) -} +CNF_LDFLAGS={- join('', $target{lflags} || (), + @{$config{lflags}}) -} +CNF_EX_LIBS={- join('', map{ ",$_" } @{$target{ex_libs}}, + @{$config{ex_libs}}) -} + +# Variables starting with LIB_ are used to build library object files +# and shared libraries. +# Variables starting with DSO_ are used to build DSOs and their object files. +# Variables starting with BIN_ are used to build programs and their object +# files. + +LIB_ASFLAGS={- join(' ', $target{lib_asflags} || (), + @{$config{lib_asflags}}, + '$(CNF_ASFLAGS)', '$(ASFLAGS)') -} +LIB_DEFINES={- our $lib_defines = + join('', (map { ",$_" } @{$target{lib_defines}}, + @{$target{shared_defines}}, + @{$config{lib_defines}}, + @{$config{shared_defines}})); + join('', $lib_defines, + (map { ",$_" } 'OPENSSLDIR="""$(OPENSSLDIR_C)"""', + 'ENGINESDIR="""$(ENGINESDIR_C)"""'), + '$(CNF_DEFINES)', '$(DEFINES)') -} +LIB_INCLUDES={- our $lib_includes = + join(',', @{$target{lib_includes}}, + @{$target{shared_includes}}, + @{$config{lib_includes}}, + @{$config{shared_includes}}) -} +LIB_CPPFLAGS={- our $lib_cppflags = + join('', $target{lib_cppflags} || (), + $target{shared_cppflags} || (), + @{$config{lib_cppflags}}, + @{$config{shared_cppflag}}); + join('', "'qual_includes'", + '/DEFINE=(__dummy$(LIB_DEFINES))', + $lib_cppflags, + '$(CNF_CPPFLAGS)', '$(CPPFLAGS)') -} +LIB_CFLAGS={- join('', $target{lib_cflags} || (), + $target{shared_cflag} || (), + @{$config{lib_cflags}}, + @{$config{shared_cflag}}, + '$(CNF_CFLAGS)', '$(CFLAGS)') -} +LIB_LDFLAGS={- join('', $target{lib_lflags} || (), + $target{shared_ldflag} || (), + @{$config{lib_lflags}}, + @{$config{shared_ldflag}}, + '$(CNF_LDFLAGS)', '$(LDFLAGS)') -} +LIB_EX_LIBS=$(CNF_EX_LIBS)$(EX_LIBS) +DSO_ASFLAGS={- join(' ', $target{dso_asflags} || (), + $target{module_asflags} || (), + @{$config{dso_asflags}}, + @{$config{module_asflags}}, + '$(CNF_ASFLAGS)', '$(ASFLAGS)') -} +DSO_DEFINES={- join('', (map { ",$_" } @{$target{dso_defines}}, + @{$target{module_defines}}, + @{$config{dso_defines}}, + @{$config{module_defines}}), + '$(CNF_DEFINES)', '$(DEFINES)') -} +DSO_INCLUDES={- join(',', @{$target{dso_includes}}, + @{$target{module_includes}}, + @{$config{dso_includes}}, + @{$config{module_includes}}) -} +DSO_CPPFLAGS={- join('', "'qual_includes'", + '/DEFINE=(__dummy$(DSO_DEFINES))', + $target{dso_cppflags} || (), + $target{module_cppflags} || (), + @{$config{dso_cppflags}}, + @{$config{module_cppflags}}, + '$(CNF_CPPFLAGS)', '$(CPPFLAGS)') -} +DSO_CFLAGS={- join('', $target{dso_cflags} || (), + $target{module_cflags} || (), + @{$config{dso_cflags}}, + @{$config{module_cflags}}, + '$(CNF_CFLAGS)', '$(CFLAGS)') -} +DSO_LDFLAGS={- join('', $target{dso_lflags} || (), + $target{module_ldflags} || (), + @{$config{dso_lflags}}, + @{$config{module_ldflags}}, + '$(CNF_LDFLAGS)', '$(LDFLAGS)') -} +DSO_EX_LIBS=$(CNF_EX_LIBS) $(EX_LIBS) +BIN_ASFLAGS={- join(' ', $target{bin_asflags} || (), + @{$config{bin_asflags}}, + '$(CNF_ASFLAGS)', '$(ASFLAGS)') -} +BIN_DEFINES={- join('', (map { ",$_" } @{$target{bin_defines}}, + @{$config{bin_defines}}), + '$(CNF_DEFINES)', '$(DEFINES)') -} +BIN_INCLUDES={- join(',', @{$target{bin_includes}}, + @{$config{bin_includes}}) -} +BIN_CPPFLAGS={- join('', "'qual_includes'", + '/DEFINE=(__dummy$(DSO_DEFINES))', + $target{bin_cppflags} || (), + @{$config{bin_cppflag}}, + '$(CNF_CPPFLAGS)', '$(CPPFLAGS)') -} +BIN_CFLAGS={- join('', $target{bin_cflag} || (), + @{$config{bin_cflag}}, + '$(CNF_CFLAGS)', '$(CFLAGS)') -} +BIN_LDFLAGS={- join('', $target{bin_lflags} || (), + @{$config{bin_lflags}} || (), + '$(CNF_LDFLAGS)', '$(LDFLAGS)') -} +BIN_EX_LIBS=$(CNF_EX_LIBS) $(EX_LIBS) +NO_INST_LIB_CFLAGS={- join('', $target{no_inst_lib_cflags} + // $target{lib_cflags} + // (), + $target{shared_cflag} || (), + @{$config{lib_cflags}}, + @{$config{shared_cflag}}, + '$(CNF_CFLAGS)', '$(CFLAGS)') -} +NO_INST_DSO_CFLAGS={- join('', $target{no_inst_lib_cflags} + // $target{lib_cflags} + // (), + $target{dso_cflags} || (), + @{$config{lib_cflags}}, + @{$config{dso_cflags}}, + '$(CNF_CFLAGS)', '$(CFLAGS)') -} +NO_INST_BIN_CFLAGS={- join('', $target{no_inst_bin_cflags} + // $target{bin_cflags} + // (), + @{$config{bin_cflags}}, + '$(CNF_CFLAGS)', '$(CFLAGS)') -} + +PERLASM_SCHEME={- $target{perlasm_scheme} -} + +# CPPFLAGS_Q is used for one thing only: to build up buildinf.h +CPPFLAGS_Q={- (my $c = $lib_cppflags.$cppflags2.$cppflags1) =~ s|"|""|g; + (my $d = $lib_defines.$defines2.$defines1) =~ s|"|""|g; + my $i = join(',', $lib_includes || (), $includes2 || (), + $includes1 || ()); + my $x = $c; + $x .= "/INCLUDE=($i)" if $i; + $x .= "/DEFINE=($d)" if $d; + $x; -} + +# .FIRST and .LAST are special targets with MMS and MMK. +# The defines in there are for C. includes that look like +# this: +# +# #include +# #include "internal/bar.h" +# +# will use the logical names to find the files. Expecting +# DECompHP C to find files in subdirectories of whatever was +# given with /INCLUDE is a fantasy, unfortunately. +NODEBUG=@ +.FIRST : + $(NODEBUG) openssl_inc1 = F$PARSE("[.include.openssl]","A.;",,,"syntax_only") - "A.;" + $(NODEBUG) openssl_inc2 = F$PARSE("{- catdir($config{sourcedir},"[.include.openssl]") -}","A.;",,,"SYNTAX_ONLY") - "A.;" + $(NODEBUG) internal_inc1 = F$PARSE("[.crypto.include.internal]","A.;",,,"SYNTAX_ONLY") - "A.;" + $(NODEBUG) internal_inc2 = F$PARSE("{- catdir($config{sourcedir},"[.include.internal]") -}","A.;",,,"SYNTAX_ONLY") - "A.;" + $(NODEBUG) internal_inc3 = F$PARSE("{- catdir($config{sourcedir},"[.crypto.include.internal]") -}","A.;",,,"SYNTAX_ONLY") - "A.;" + $(NODEBUG) DEFINE openssl 'openssl_inc1','openssl_inc2' + $(NODEBUG) DEFINE internal 'internal_inc1','internal_inc2','internal_inc3' + $(NODEBUG) staging_dir = "$(DESTDIR)" + $(NODEBUG) staging_instdir = "" + $(NODEBUG) staging_datadir = "" + $(NODEBUG) IF staging_dir .NES. "" THEN - + staging_instdir = F$PARSE("A.;",staging_dir,"[]",,"SYNTAX_ONLY") + $(NODEBUG) IF staging_instdir - "]A.;" .NES. staging_instdir THEN - + staging_instdir = staging_instdir - "]A.;" + ".OPENSSL-INSTALL]" + $(NODEBUG) IF staging_instdir - "A.;" .NES. staging_instdir THEN - + staging_instdir = staging_instdir - "A.;" + "[OPENSSL-INSTALL]" + $(NODEBUG) IF staging_dir .NES. "" THEN - + staging_datadir = F$PARSE("A.;",staging_dir,"[]",,"SYNTAX_ONLY") + $(NODEBUG) IF staging_datadir - "]A.;" .NES. staging_datadir THEN - + staging_datadir = staging_datadir - "]A.;" + ".OPENSSL-COMMON]" + $(NODEBUG) IF staging_datadir - "A.;" .NES. staging_datadir THEN - + staging_datadir = staging_datadir - "A.;" + "[OPENSSL-COMMON]" + $(NODEBUG) ! + $(NODEBUG) ! Installation logical names + $(NODEBUG) ! + $(NODEBUG) installtop = F$PARSE(staging_instdir,"$(INSTALLTOP)","[]A.;",,"SYNTAX_ONLY,NO_CONCEAL") - ".][000000" - "[000000." - "][" - "]A.;" + ".]" + $(NODEBUG) datatop = F$PARSE(staging_datadir,"$(OPENSSLDIR)","[]A.;",,"SYNTAX_ONLY,NO_CONCEAL") - ".][000000" - "[000000." - "][" - "]A.;" + ".]" + $(NODEBUG) DEFINE ossl_installroot 'installtop' + $(NODEBUG) DEFINE ossl_dataroot 'datatop' + $(NODEBUG) ! + $(NODEBUG) ! Figure out the architecture + $(NODEBUG) ! + $(NODEBUG) arch = f$edit( f$getsyi( "arch_name"), "upcase") + $(NODEBUG) ! + $(NODEBUG) ! Set up logical names for the libraries, so LINK and + $(NODEBUG) ! running programs can use them. + $(NODEBUG) ! + $(NODEBUG) {- join("\n\t\$(NODEBUG) ", map { "DEFINE ".uc($_)." 'F\$ENV(\"DEFAULT\")'".uc($_)."\$(SHLIB_EXT)" } @shlibs) || "!" -} + +.LAST : + $(NODEBUG) {- join("\n\t\$(NODEBUG) ", map { "DEASSIGN ".uc($_) } @shlibs) || "!" -} + $(NODEBUG) DEASSIGN ossl_dataroot + $(NODEBUG) DEASSIGN ossl_installroot + $(NODEBUG) DEASSIGN internal + $(NODEBUG) DEASSIGN openssl +.DEFAULT : + @ ! MMS cannot handle no actions... + +# The main targets ################################################### + +{- dependmagic('all'); -} : build_libs_nodep, build_engines_nodep, build_programs_nodep +{- dependmagic('build_libs'); -} : build_libs_nodep +{- dependmagic('build_engines'); -} : build_engines_nodep +{- dependmagic('build_programs'); -} : build_programs_nodep + +build_generated : $(GENERATED_MANDATORY) +build_libs_nodep : $(LIBS), $(SHLIBS) +build_engines_nodep : $(ENGINES) +build_programs_nodep : $(PROGRAMS), $(SCRIPTS) + +# Kept around for backward compatibility +build_apps build_tests : build_programs + +# Convenience target to prebuild all generated files, not just the mandatory +# ones +build_all_generated : $(GENERATED_MANDATORY) $(GENERATED) + @ ! {- output_off() if $disabled{makedepend}; "" -} + @ WRITE SYS$OUTPUT "Warning: consider configuring with no-makedepend, because if" + @ WRITE SYS$OUTPUT " target system doesn't have $(PERL)," + @ WRITE SYS$OUTPUT " then make will fail..." + @ ! {- output_on() if $disabled{makedepend}; "" -} + +test : tests +{- dependmagic('tests'); -} : build_programs_nodep, build_engines_nodep + @ ! {- output_off() if $disabled{tests}; "" -} + SET DEFAULT [.test]{- move("test") -} + CREATE/DIR [.test-runs] + DEFINE SRCTOP {- sourcedir() -} + DEFINE BLDTOP {- builddir() -} + DEFINE RESULT_D {- builddir(qw(test test-runs)) -} + DEFINE OPENSSL_ENGINES {- builddir("engines") -} + DEFINE OPENSSL_DEBUG_MEMORY "on" + IF "$(VERBOSE)" .NES. "" THEN DEFINE VERBOSE "$(VERBOSE)" + $(PERL) {- sourcefile("test", "run_tests.pl") -} $(TESTS) + DEASSIGN OPENSSL_DEBUG_MEMORY + DEASSIGN OPENSSL_ENGINES + DEASSIGN BLDTOP + DEASSIGN SRCTOP + SET DEFAULT [-]{- move("..") -} + @ ! {- if ($disabled{tests}) { output_on(); } else { output_off(); } "" -} + @ WRITE SYS$OUTPUT "Tests are not supported with your chosen Configure options" + @ ! {- output_on() if !$disabled{tests}; "" -} + +list-tests : + @ ! {- output_off() if $disabled{tests}; "" -} + @ DEFINE SRCTOP {- sourcedir() -} + @ $(PERL) {- sourcefile("test", "run_tests.pl") -} list + @ DEASSIGN SRCTOP + @ ! {- if ($disabled{tests}) { output_on(); } else { output_off(); } "" -} + @ WRITE SYS$OUTPUT "Tests are not supported with your chosen Configure options" + @ ! {- output_on() if !$disabled{tests}; "" -} + +install : install_sw install_ssldirs install_docs + @ WRITE SYS$OUTPUT "" + @ WRITE SYS$OUTPUT "######################################################################" + @ WRITE SYS$OUTPUT "" + @ IF "$(DESTDIR)" .EQS. "" THEN - + PIPE ( WRITE SYS$OUTPUT "Installation complete" ; - + WRITE SYS$OUTPUT "" ; - + WRITE SYS$OUTPUT "Run @$(SYSTARTUP)openssl_startup{- $osslver -} to set up logical names" ; - + WRITE SYS$OUTPUT "then run @$(SYSTARTUP)openssl_utils{- $osslver -} to define commands" ; - + WRITE SYS$OUTPUT "" ) + @ IF "$(DESTDIR)" .NES. "" THEN - + PIPE ( WRITE SYS$OUTPUT "Staging installation complete" ; - + WRITE SYS$OUTPUT "" ; - + WRITE SYS$OUTPUT "Finish or package in such a way that the contents of the directory tree" ; - + WRITE SYS$OUTPUT staging_instdir ; - + WRITE SYS$OUTPUT "ends up in $(INSTALLTOP)," ; - + WRITE SYS$OUTPUT "and that the contents of the contents of the directory tree" ; - + WRITE SYS$OUTPUT staging_datadir ; - + WRITE SYS$OUTPUT "ends up in $(OPENSSLDIR)" ; - + WRITE SYS$OUTPUT "" ; - + WRITE SYS$OUTPUT "When in its final destination," ; - + WRITE SYS$OUTPUT "Run @$(SYSTARTUP)openssl_startup{- $osslver -} to set up logical names" ; - + WRITE SYS$OUTPUT "then run @$(SYSTARTUP)openssl_utils{- $osslver -} to define commands" ; - + WRITE SYS$OUTPUT "" ) + +check_install : + spawn/nolog @ossl_installroot:[SYSTEST]openssl_ivp{- $osslver -}.com + +uninstall : uninstall_docs uninstall_sw + +# Because VMS wants the generation number (or *) to delete files, we can't +# use $(LIBS), $(PROGRAMS), $(GENERATED) and $(ENGINES)directly. +libclean : + {- join("\n\t", map { "- DELETE $_.OLB;*" } @libs) || "@ !" -} + {- join("\n\t", map { "- DELETE $_.EXE;*,$_.MAP;*" } @shlibs) || "@ !" -} + +clean : libclean + {- join("\n\t", map { "- DELETE $_.EXE;*,$_.OPT;*" } @{$unified_info{programs}}) || "@ !" -} + {- join("\n\t", map { "- DELETE $_.EXE;*,$_.OPT;*" } @{$unified_info{engines}}) || "@ !" -} + {- join("\n\t", map { "- DELETE $_;*" } @{$unified_info{scripts}}) || "@ !" -} + {- join("\n\t", map { "- DELETE $_;*" } @{$unified_info{depends}->{""}}) || "@ !" -} + {- join("\n\t", map { "- DELETE $_;*" } @generated) || "@ !" -} + - DELETE [...]*.MAP;* + - DELETE [...]*.D;* + - DELETE [...]*.OBJ;*,*.LIS;* + - DELETE []CXX$DEMANGLER_DB.;* + - DELETE [.VMS]openssl_startup.com;* + - DELETE [.VMS]openssl_shutdown.com;* + - DELETE []vmsconfig.pm;* + +distclean : clean + - DELETE configdata.pm;* + - DELETE descrip.mms;* + +depend : descrip.mms +descrip.mms : FORCE + @ ! {- output_off() if $disabled{makedepend}; "" -} + @ $(PERL) {- sourcefile("util", "add-depends.pl") -} "VMS C" + @ ! {- output_on() if $disabled{makedepend}; "" -} + +# Install helper targets ############################################# + +install_sw : install_dev install_engines install_runtime - + install_startup install_ivp + +uninstall_sw : uninstall_dev uninstall_engines uninstall_runtime - + uninstall_startup uninstall_ivp + +install_docs : install_html_docs + +uninstall_docs : uninstall_html_docs + +install_ssldirs : check_INSTALLTOP + - CREATE/DIR/PROT=(S:RWED,O:RWE,G:RE,W:RE) OSSL_DATAROOT:[000000] + IF F$SEARCH("OSSL_DATAROOT:[000000]CERTS.DIR;1") .EQS. "" THEN - + CREATE/DIR/PROT=(S:RWED,O:RWE,G:RE,W:RE) OSSL_DATAROOT:[CERTS] + IF F$SEARCH("OSSL_DATAROOT:[000000]PRIVATE.DIR;1") .EQS. "" THEN - + CREATE/DIR/PROT=(S:RWED,O:RWE,G,W) OSSL_DATAROOT:[PRIVATE] + IF F$SEARCH("OSSL_DATAROOT:[000000]MISC.DIR;1") .EQS. "" THEN - + CREATE/DIR/PROT=(S:RWED,O:RWE,G,W) OSSL_DATAROOT:[MISC] + COPY/PROT=W:RE $(MISC_SCRIPTS) OSSL_DATAROOT:[MISC] + @ ! Install configuration file + COPY/PROT=W:R {- sourcefile("apps", "openssl-vms.cnf") -} - + ossl_dataroot:[000000]openssl.cnf-dist + IF F$SEARCH("OSSL_DATAROOT:[000000]openssl.cnf") .EQS. "" THEN - + COPY/PROT=W:R {- sourcefile("apps", "openssl-vms.cnf") -} - + ossl_dataroot:[000000]openssl.cnf + @ ! Install CTLOG configuration file + COPY/PROT=W:R {- sourcefile("apps", "ct_log_list.cnf") -} - + ossl_dataroot:[000000]ct_log_list.cnf-dist + IF F$SEARCH("OSSL_DATAROOT:[000000]ct_log_list.cnf") .EQS. "" THEN - + COPY/PROT=W:R {- sourcefile("apps", "ct_log_list.cnf") -} - + ossl_dataroot:[000000]ct_log_list.cnf + +install_dev : check_INSTALLTOP install_runtime_libs + @ WRITE SYS$OUTPUT "*** Installing development files" + @ ! Install header files + - CREATE/DIR ossl_installroot:[include.openssl] + COPY/PROT=W:R openssl:*.h ossl_installroot:[include.openssl] + @ ! Install static (development) libraries + - CREATE/DIR ossl_installroot:[LIB.'arch'] + {- join("\n ", + map { "COPY/PROT=W:R $_.OLB ossl_installroot:[LIB.'arch']" } + @install_libs) -} + +install_engines : check_INSTALLTOP install_runtime_libs build_engines + @ {- output_off() unless scalar @{$unified_info{engines}}; "" -} ! + @ WRITE SYS$OUTPUT "*** Installing engines" + - CREATE/DIR ossl_installroot:[ENGINES{- $sover_dirname.$target{pointer_size} -}.'arch'] + {- join("\n ", + map { "COPY/PROT=W:RE $_.EXE ossl_installroot:[ENGINES$sover_dirname$target{pointer_size}.'arch']" } + @{$unified_info{install}->{engines}}) -} + @ {- output_on() unless scalar @{$unified_info{engines}}; "" -} ! + +install_runtime : install_programs + +install_runtime_libs : check_INSTALLTOP build_libs + @ {- output_off() if $disabled{shared}; "" -} ! + @ WRITE SYS$OUTPUT "*** Installing shareable images" + @ ! Install shared (runtime) libraries + - CREATE/DIR ossl_installroot:[LIB.'arch'] + {- join("\n ", + map { "COPY/PROT=W:R $_.EXE ossl_installroot:[LIB.'arch']" } + @install_shlibs) -} + @ {- output_on() if $disabled{shared}; "" -} ! + +install_programs : check_INSTALLTOP install_runtime_libs build_programs + @ {- output_off() if $disabled{apps}; "" -} ! + @ ! Install the main program + - CREATE/DIR ossl_installroot:[EXE.'arch'] + COPY/PROT=W:RE [.APPS]openssl.EXE - + ossl_installroot:[EXE.'arch']openssl{- $osslver -}.EXE + @ ! Install scripts + COPY/PROT=W:RE $(BIN_SCRIPTS) ossl_installroot:[EXE] + @ ! {- output_on() if $disabled{apps}; "" -} + +install_startup : [.VMS]openssl_startup.com [.VMS]openssl_shutdown.com - + [.VMS]openssl_utils.com, check_INSTALLTOP + - CREATE/DIR ossl_installroot:[SYS$STARTUP] + COPY/PROT=W:RE [.VMS]openssl_startup.com - + ossl_installroot:[SYS$STARTUP]openssl_startup{- $osslver -}.com + COPY/PROT=W:RE [.VMS]openssl_shutdown.com - + ossl_installroot:[SYS$STARTUP]openssl_shutdown{- $osslver -}.com + COPY/PROT=W:RE [.VMS]openssl_utils.com - + ossl_installroot:[SYS$STARTUP]openssl_utils{- $osslver -}.com + +install_ivp : [.VMS]openssl_ivp.com check_INSTALLTOP + - CREATE/DIR ossl_installroot:[SYSTEST] + COPY/PROT=W:RE [.VMS]openssl_ivp.com - + ossl_installroot:[SYSTEST]openssl_ivp{- $osslver -}.com + +[.VMS]openssl_startup.com : vmsconfig.pm {- sourcefile("VMS", "openssl_startup.com.in") -} + - CREATE/DIR [.VMS] + $(PERL) "-I." "-Mvmsconfig" {- sourcefile("util", "dofile.pl") -} - + {- sourcefile("VMS", "openssl_startup.com.in") -} - + > [.VMS]openssl_startup.com + +[.VMS]openssl_utils.com : vmsconfig.pm {- sourcefile("VMS", "openssl_utils.com.in") -} + - CREATE/DIR [.VMS] + $(PERL) "-I." "-Mvmsconfig" {- sourcefile("util", "dofile.pl") -} - + {- sourcefile("VMS", "openssl_utils.com.in") -} - + > [.VMS]openssl_utils.com + +[.VMS]openssl_shutdown.com : vmsconfig.pm {- sourcefile("VMS", "openssl_shutdown.com.in") -} + - CREATE/DIR [.VMS] + $(PERL) "-I." "-Mvmsconfig" {- sourcefile("util", "dofile.pl") -} - + {- sourcefile("VMS", "openssl_shutdown.com.in") -} - + > [.VMS]openssl_shutdown.com + +[.VMS]openssl_ivp.com : vmsconfig.pm {- sourcefile("VMS", "openssl_ivp.com.in") -} + - CREATE/DIR [.VMS] + $(PERL) "-I." "-Mvmsconfig" {- sourcefile("util", "dofile.pl") -} - + {- sourcefile("VMS", "openssl_ivp.com.in") -} - + > [.VMS]openssl_ivp.com + +vmsconfig.pm : configdata.pm + OPEN/WRITE/SHARE=READ CONFIG []vmsconfig.pm + WRITE CONFIG "package vmsconfig;" + WRITE CONFIG "use strict; use warnings;" + WRITE CONFIG "use Exporter;" + WRITE CONFIG "our @ISA = qw(Exporter);" + WRITE CONFIG "our @EXPORT = qw(%config %target %withargs %unified_info %disabled);" + WRITE CONFIG "our %config = (" + WRITE CONFIG " target => '","{- $config{target} -}","'," + WRITE CONFIG " version => '","{- $config{version} -}","'," + WRITE CONFIG " shlib_version_number => '","{- $config{shlib_version_number} -}","'," + WRITE CONFIG " shlib_major => '","{- $config{shlib_major} -}","'," + WRITE CONFIG " shlib_minor => '","{- $config{shlib_minor} -}","'," + WRITE CONFIG " no_shared => '","{- $disabled{shared} -}","'," + WRITE CONFIG " INSTALLTOP => '$(INSTALLTOP)'," + WRITE CONFIG " OPENSSLDIR => '$(OPENSSLDIR)'," + WRITE CONFIG " pointer_size => '","{- $target{pointer_size} -}","'," + WRITE CONFIG ");" + WRITE CONFIG "our %target = ();" + WRITE CONFIG "our %disabled = ();" + WRITE CONFIG "our %withargs = ();" + WRITE CONFIG "our %unified_info = ();" + WRITE CONFIG "1;" + CLOSE CONFIG + +install_html_docs : check_INSTALLTOP + sourcedir = F$PARSE("{- $sourcedir -}A.;","[]") - "]A.;" + ".DOC]" + $(PERL) {- sourcefile("util", "process_docs.pl") -} - + --sourcedir='sourcedir' --destdir=ossl_installroot:[HTML] - + --type=html + +check_INSTALLTOP : + @ IF "$(INSTALLTOP)" .EQS. "" THEN - + WRITE SYS$ERROR "INSTALLTOP should not be empty" + @ IF "$(INSTALLTOP)" .EQS. "" THEN - + EXIT %x10000002 + +# Helper targets ##################################################### + +# Developer targets ################################################## + +debug_logicals : + SH LOGICAL/PROC openssl,internal,ossl_installroot,ossl_dataroot + +# Building targets ################################################### + +configdata.pm : $(SRCDIR)Configure $(SRCDIR)config.com {- join(" ", @{$config{build_file_templates}}, @{$config{build_infos}}, @{$config{conf_files}}) -} + perl configdata.pm -r + @ WRITE SYS$OUTPUT "*************************************************" + @ WRITE SYS$OUTPUT "*** ***" + @ WRITE SYS$OUTPUT "*** Please run the same mms command again ***" + @ WRITE SYS$OUTPUT "*** ***" + @ WRITE SYS$OUTPUT "*************************************************" + @ PIPE ( EXIT %X10000000 ) + +reconfigure reconf : + perl configdata.pm -r + +{- + use File::Basename; + use File::Spec::Functions qw/abs2rel rel2abs catfile catdir/; + + # Helper function to figure out dependencies on libraries + # It takes a list of library names and outputs a list of dependencies + sub compute_lib_depends { + if ($disabled{shared}) { + return map { $_ =~ /\.a$/ ? $`.".OLB" : $_.".OLB" } @_; + } + return map { $_ =~ /\.a$/ + ? $`.".OLB" + : $unified_info{sharednames}->{$_}.".EXE" } @_; + } + + # Helper function to deal with inclusion directory specs. + # We have to deal with two things: + # 1. comma separation and no possibility of trailing comma + # 2. no inclusion directories given at all + # 3. long compiler command lines + # To resolve 1, we need to iterate through the sources of inclusion + # directories, and only add a comma when needed. + # To resolve 2, we need to have a variable that will hold the whole + # inclusion qualifier, or be the empty string if there are no inclusion + # directories. That's the symbol 'qual_includes' that's used in CPPFLAGS + # To resolve 3, we creata a logical name TMP_INCLUDES: to hold the list + # of inclusion directories. + # + # This function returns a list of two lists, one being the collection of + # commands to execute before the compiler is called, and the other being + # the collection of commands to execute after. It takes as arguments the + # collection of strings to include as directory specs. + sub includes { + my @stuff = ( @_ ); + my @before = ( + 'qual_includes :=', + ); + my @after = ( + 'DELETE/SYMBOL/LOCAL qual_includes', + ); + + if (scalar @stuff > 0) { + push @before, 'tmp_includes := '.shift(@stuff); + while (@stuff) { + push @before, 'tmp_add := '.shift(@stuff); + push @before, 'IF tmp_includes .NES. "" .AND. tmp_add .NES. "" THEN tmp_includes = tmp_includes + ","'; + push @before, 'tmp_includes = tmp_includes + tmp_add'; + } + push @before, "IF tmp_includes .NES. \"\" THEN DEFINE tmp_includes 'tmp_includes'"; + push @before, 'IF tmp_includes .NES. "" THEN qual_includes := /INCLUDE=(tmp_includes:)'; + push @before, 'DELETE/SYMBOL/LOCAL tmp_includes'; + push @before, 'DELETE/SYMBOL/LOCAL tmp_add'; + push @after, 'DEASSIGN tmp_includes:' + } + return ([ @before ], [ @after ]); + } + + sub generatesrc { + my %args = @_; + (my $target = $args{src}) =~ s/\.[sS]$/.asm/; + my $generator = join(" ", @{$args{generator}}); + my $generator_incs = join("", map { ' "-I'.$_.'"' } @{$args{generator_incs}}); + my $deps = join(", -\n\t\t", @{$args{generator_deps}}, @{$args{deps}}); + + if ($target !~ /\.asm$/) { + if ($args{generator}->[0] =~ m|^.*\.in$|) { + my $dofile = abs2rel(rel2abs(catfile($config{sourcedir}, + "util", "dofile.pl")), + rel2abs($config{builddir})); + return <<"EOF"; +$target : $args{generator}->[0] $deps + \$(PERL) "-I\$(BLDDIR)" "-Mconfigdata" $dofile \\ + "-o$target{build_file}" $generator > \$\@ +EOF + } else { + return <<"EOF"; +$target : $args{generator}->[0] $deps + \$(PERL)$generator_incs $generator > \$\@ +EOF + } + } else { + if ($args{generator}->[0] =~ /\.pl$/) { + $generator = '$(PERL)'.$generator_incs.' '.$generator; + } elsif ($args{generator}->[0] =~ /\.S$/) { + $generator = undef; + } else { + die "Generator type for $src unknown: $generator\n"; + } + + my $cppflags = { + lib => '$(LIB_CFLAGS) $(LIB_CPPFLAGS)', + dso => '$(DSO_CFLAGS) $(DSO_CPPFLAGS)', + bin => '$(BIN_CFLAGS) $(BIN_CPPFLAGS)' + } -> {$args{intent}}; + my @incs_cmds = includes({ lib => '$(LIB_INCLUDES)', + dso => '$(DSO_INCLUDES)', + bin => '$(BIN_INCLUDES)' } -> {$args{intent}}, + '$(CNF_INCLUDES)', + '$(INCLUDES)', + @{$args{incs}}); + my $incs_on = join("\n\t\@ ", @{$incs_cmds[0]}) || '!'; + my $incs_off = join("\n\t\@ ", @{$incs_cmds[1]}) || '!'; + if (defined($generator)) { + # If the target is named foo.S in build.info, we want to + # end up generating foo.s in two steps. + if ($args{src} =~ /\.S$/) { + return <<"EOF"; +$target : $args{generator}->[0] $deps + $generator \$\@-S + \@ $incs_on + PIPE \$(CPP) $cppflags \$\@-S | - + \$(PERL) -ne "/^#(\\s*line)?\\s*[0-9]+\\s+""/ or print" > \$\@-i + \@ $incs_off + RENAME \$\@-i \$\@ + DELETE \$\@-S; +EOF + } + # Otherwise.... + return <<"EOF"; +$target : $args{generator}->[0] $deps + $generator \$\@ +EOF + } + return <<"EOF"; +$target : $args{generator}->[0] $deps + \@ $incs_on + SHOW SYMBOL qual_includes + PIPE \$(CPP) $cppflags $args{generator}->[0] | - + \$(PERL) "-ne" "/^#(\\s*line)?\\s*[0-9]+\\s+""/ or print" > \$\@ + \@ $incs_off +EOF + } + } + + sub src2obj { + my %args = @_; + my @srcs = map { (my $x = $_) =~ s/\.s$/.asm/; $x + } ( @{$args{srcs}} ); + (my $obj = $args{obj}) =~ s|\.o$||; + my $deps = join(", -\n\t\t", @srcs, @{$args{deps}}); + + # Because VMS C isn't very good at combining a /INCLUDE path with + # #includes having a relative directory (like '#include "../foo.h"), + # the best choice is to move to the first source file's intended + # directory before compiling, and make sure to write the object file + # in the correct position (important when the object tree is other + # than the source tree). + my $forward = dirname($args{srcs}->[0]); + my $backward = abs2rel(rel2abs("."), rel2abs($forward)); + my $objd = abs2rel(rel2abs(dirname($obj)), rel2abs($forward)); + my $objn = basename($obj); + my $srcs = + join(", ", map { abs2rel(rel2abs($_), rel2abs($forward)) } @srcs); + my $before = $unified_info{before}->{$obj.".OBJ"} || "\@ !"; + my $after = $unified_info{after}->{$obj.".OBJ"} || "\@ !"; + + my $cflags; + if ($args{installed}) { + $cflags = { lib => '$(LIB_CFLAGS)', + dso => '$(DSO_CFLAGS)', + bin => '$(BIN_CFLAGS)' } -> {$args{intent}}; + } else { + $cflags = { lib => '$(NO_INST_LIB_CFLAGS)', + dso => '$(NO_INST_DSO_CFLAGS)', + bin => '$(NO_INST_BIN_CFLAGS)' } -> {$args{intent}}; + } + $cflags .= { lib => '$(LIB_CPPFLAGS)', + dso => '$(DSO_CPPFLAGS)', + bin => '$(BIN_CPPFLAGS)' } -> {$args{intent}}; + my $asflags = { lib => ' $(LIB_ASFLAGS)', + dso => ' $(DSO_ASFLAGS)', + bin => ' $(BIN_ASFLAGS)' } -> {$args{intent}}; + + my @incs_cmds = includes({ lib => '$(LIB_INCLUDES)', + dso => '$(DSO_INCLUDES)', + bin => '$(BIN_INCLUDES)' } -> {$args{intent}}, + '$(INCLUDES)', + map { + file_name_is_absolute($_) + ? $_ : catdir($backward,$_) + } @{$args{incs}}); + my $incs_on = join("\n\t\@ ", @{$incs_cmds[0]}) || '!'; + my $incs_off = join("\n\t\@ ", @{$incs_cmds[1]}) || '!'; + + if ($srcs[0] =~ /\.asm$/) { + return <<"EOF"; +$obj.OBJ : $deps + ${before} + SET DEFAULT $forward + \$(AS) $asflags \$(ASOUTFLAG)${objd}${objn}.OBJ $srcs + SET DEFAULT $backward + ${after} + - PURGE $obj.OBJ +EOF + } elsif ($srcs[0] =~ /.S$/) { + return <<"EOF"; +$obj.OBJ : $deps + ${before} + SET DEFAULT $forward + \@ $incs_on + PIPE \$(CPP) ${cflags} $srcs | - + \$(PERL) -ne "/^#(\\s*line)?\\s*[0-9]+\\s+""/ or print" - + > ${objd}${objn}.asm + \@ $incs_off + SET DEFAULT $backward + ${after} + \$(AS) $asflags \$(ASOUTFLAG)$obj.OBJ $obj.asm + - PURGE $obj.OBJ +EOF + } + + my $depbuild = $disabled{makedepend} ? "" + : " /MMS=(FILE=${objd}${objn}.D,TARGET=$obj.OBJ)"; + + return <<"EOF"; +$obj.OBJ : $deps + ${before} + SET DEFAULT $forward + \@ $incs_on + \$(CC) ${cflags}${depbuild} /OBJECT=${objd}${objn}.OBJ /REPOSITORY=$backward $srcs + \@ $incs_off + SET DEFAULT $backward + ${after} + - PURGE $obj.OBJ +EOF + } + sub libobj2shlib { + my %args = @_; + my $lib = $args{lib}; + my $shlib = $args{shlib}; + my $libd = dirname($lib); + my $libn = basename($lib); + my @objs = map { (my $x = $_) =~ s|\.o$|.OBJ|; $x } + grep { $_ =~ m|\.o$| } + @{$args{objs}}; + my @defs = grep { $_ =~ /\.opt$/ } @{$args{objs}}; + my @deps = compute_lib_depends(@{$args{deps}}); + die "More than one symbol vector" if scalar @defs > 1; + my $deps = join(", -\n\t\t", @defs, @deps); + my $shlib_target = $disabled{shared} ? "" : $target{shared_target}; + my $translatesyms_pl = abs2rel(rel2abs(catfile($config{sourcedir}, + "VMS", "translatesyms.pl")), + rel2abs($config{builddir})); + # The "[]" hack is because in .OPT files, each line inherits the + # previous line's file spec as default, so if no directory spec + # is present in the current line and the previous line has one that + # doesn't apply, you're in for a surprise. + my $write_opt1 = + join(",-\"\n\t", map { my $x = $_ =~ /\[/ ? $_ : "[]".$_; + "WRITE OPT_FILE \"$x" } @objs). + "\""; + my $write_opt2 = + join("\n\t", map { my $x = $_ =~ /\[/ ? $_ : "[]".$_; + $x =~ s|(\.EXE)|$1/SHARE|; + $x =~ s|(\.OLB)|$1/LIB|; + "WRITE OPT_FILE \"$x\"" } @deps) + || "\@ !"; + return <<"EOF" +$shlib.EXE : $lib.OLB $deps + \$(PERL) $translatesyms_pl \$(BLDDIR)CXX\$DEMANGLER_DB. < $defs[0] > $defs[0]-translated + OPEN/WRITE/SHARE=READ OPT_FILE $lib-components.OPT + $write_opt1 + $write_opt2 + CLOSE OPT_FILE + LINK \$(LIB_LDFLAGS)/SHARE=\$\@ $defs[0]-translated/OPT,- + $lib-components.OPT/OPT \$(LIB_EX_LIBS) + DELETE $defs[0]-translated;*,$lib-components.OPT;* + PURGE $shlib.EXE,$shlib.MAP +EOF + . ($config{target} =~ m|alpha| ? "" : <<"EOF" + SET IMAGE/FLAGS=(NOCALL_DEBUG) \$\@ +EOF + ); + } + sub obj2dso { + my %args = @_; + my $lib = $args{lib}; + my $libd = dirname($lib); + my $libn = basename($lib); + (my $libn_nolib = $libn) =~ s/^lib//; + my @objs = map { (my $x = $_) =~ s|\.o$|.OBJ|; $x } @{$args{objs}}; + my @deps = compute_lib_depends(@{$args{deps}}); + my $deps = join(", -\n\t\t", @objs, @deps); + my $shlib_target = $disabled{shared} ? "" : $target{shared_target}; + my $engine_opt = abs2rel(rel2abs(catfile($config{sourcedir}, + "VMS", "engine.opt")), + rel2abs($config{builddir})); + # The "[]" hack is because in .OPT files, each line inherits the + # previous line's file spec as default, so if no directory spec + # is present in the current line and the previous line has one that + # doesn't apply, you're in for a surprise. + my $write_opt1 = + join(",-\"\n\t", map { my $x = $_ =~ /\[/ ? $_ : "[]".$_; + "WRITE OPT_FILE \"$x" } @objs). + "\""; + my $write_opt2 = + join("\n\t", map { my $x = $_ =~ /\[/ ? $_ : "[]".$_; + $x =~ s|(\.EXE)|$1/SHARE|; + $x =~ s|(\.OLB)|$1/LIB|; + "WRITE OPT_FILE \"$x\"" } @deps) + || "\@ !"; + return <<"EOF" +$lib.EXE : $deps + OPEN/WRITE/SHARE=READ OPT_FILE $lib.OPT + TYPE $engine_opt /OUTPUT=OPT_FILE: + $write_opt1 + $write_opt2 + CLOSE OPT_FILE + LINK \$(DSO_LDFLAGS)/SHARE=\$\@ $lib.OPT/OPT \$(DSO_EX_LIBS) + - PURGE $lib.EXE,$lib.OPT,$lib.MAP +EOF + . ($config{target} =~ m|alpha| ? "" : <<"EOF" + SET IMAGE/FLAGS=(NOCALL_DEBUG) \$\@ +EOF + ); + } + sub obj2lib { + my %args = @_; + (my $lib = $args{lib}) =~ s/\.a$//; + my @objs = map { (my $x = $_) =~ s|\.o$|.OBJ|; $x } @{$args{objs}}; + my $objs = join(", -\n\t\t", @objs); + my $fill_lib = join("\n\t", (map { "LIBRARY/REPLACE $lib.OLB $_" } + @objs)); + return <<"EOF"; +$lib.OLB : $objs + LIBRARY/CREATE/OBJECT $lib.OLB + $fill_lib + - PURGE $lib.OLB +EOF + } + sub obj2bin { + my %args = @_; + my $bin = $args{bin}; + my $bind = dirname($bin); + my $binn = basename($bin); + my @objs = map { (my $x = $_) =~ s|\.o$|.OBJ|; $x } @{$args{objs}}; + my $objs = join(",", @objs); + my @deps = compute_lib_depends(@{$args{deps}}); + my $deps = join(", -\n\t\t", @objs, @deps); + + my $olb_count = scalar grep(m|\.OLB$|, @deps); + my $analyse_objs = "@ !"; + if ($olb_count > 0) { + my $analyse_quals = + $config{target} =~ m|alpha| ? "/GSD" : "/SECTIONS=SYMTAB"; + $analyse_objs = "- pipe ANALYSE/OBJECT$analyse_quals $objs | SEARCH SYS\$INPUT \"\"\"main\"\"\" ; nomain = \$severity .NE. 1" + } + # The "[]" hack is because in .OPT files, each line inherits the + # previous line's file spec as default, so if no directory spec + # is present in the current line and the previous line has one that + # doesn't apply, you're in for a surprise. + my $write_opt1 = + join(",-\"\n\t", map { my $x = $_ =~ /\[/ ? $_ : "[]".$_; + "\@ WRITE OPT_FILE \"$x" } @objs). + "\""; + my $write_opt2 = + join("\n\t", map { my @lines = (); + my $x = $_ =~ /\[/ ? $_ : "[]".$_; + if ($x =~ m|\.EXE$|) { + push @lines, "\@ WRITE OPT_FILE \"$x/SHARE\""; + } elsif ($x =~ m|\.OLB$|) { + (my $l = $x) =~ s/\W/_/g; + push @lines, + "\@ IF nomain THEN WRITE OPT_FILE \"$x/LIB\$(INCLUDE_MAIN_$l)\"", + "\@ IF .NOT. nomain THEN WRITE OPT_FILE \"$x/LIB\"" + } + @lines + } @deps) + || "\@ !"; + # The linking commands looks a bit complex, but it's for good reason. + # When you link, say, foo.obj, bar.obj and libsomething.exe/share, and + # bar.obj happens to have a symbol that also exists in libsomething.exe, + # the linker will warn about it, loudly, and will then choose to pick + # the first copy encountered (the one in bar.obj in this example). + # On Unix and on Windows, the corresponding maneuvre goes through + # silently with the same effect. + # With some test programs, made for checking the internals of OpenSSL, + # we do this kind of linking deliberately, picking a few specific object + # files from within [.crypto] or [.ssl] so we can reach symbols that are + # otherwise unreachable (since the shareable images only exports the + # symbols listed in [.util]*.num), and then with the shared libraries + # themselves. So we need to silence the warning about multiply defined + # symbols, to mimic the way linking work on Unix and Windows, and so + # the build isn't interrupted (MMS stops when warnings are signaled, + # by default), and so someone building doesn't have to worry where it + # isn't necessary. If there are other warnings, however, we show them + # and let it break the build. + return <<"EOF" +$bin.EXE : $deps + $analyse_objs + @ OPEN/WRITE/SHARE=READ OPT_FILE $bin.OPT + $write_opt1 + $write_opt2 + @ CLOSE OPT_FILE + TYPE $bin.opt ! For debugging + - pipe SPAWN/WAIT/NOLOG/OUT=$bin.LINKLOG - + LINK \$(BIN_LDFLAGS)/EXEC=\$\@ $bin.OPT/OPT \$(BIN_EX_LIBS) ; - + link_status = \$status ; link_severity = link_status .AND. 7 + @ search_severity = 1 + -@ IF link_severity .EQ. 0 THEN - + pipe SEARCH $bin.LINKLOG "%","-"/MATCH=AND | - + SPAWN/WAIT/NOLOG/OUT=NLA0: - + SEARCH SYS\$INPUT: "-W-MULDEF,"/MATCH=NOR ; - + search_severity = \$severity + @ ! search_severity is 3 when the last search didn't find any matching + @ ! string: %SEARCH-I-NOMATCHES, no strings matched + @ ! If that was the result, we pretend linking got through without + @ ! fault or warning. + @ IF search_severity .EQ. 3 THEN link_severity = 1 + @ ! At this point, if link_severity shows that there was a fault + @ ! or warning, make sure to restore the linking status. + -@ IF .NOT. link_severity THEN TYPE $bin.LINKLOG + -@ DELETE $bin.LINKLOG;* + @ IF .NOT. link_severity THEN SPAWN/WAIT/NOLOG EXIT 'link_status' + - PURGE $bin.EXE,$bin.OPT +EOF + . ($config{target} =~ m|alpha| ? "" : <<"EOF" + SET IMAGE/FLAGS=(NOCALL_DEBUG) \$\@ +EOF + ); + } + sub in2script { + my %args = @_; + my $script = $args{script}; + return "" if grep { $_ eq $script } @{$args{sources}}; # No overwrite! + my $sources = join(" ", @{$args{sources}}); + my $dofile = abs2rel(rel2abs(catfile($config{sourcedir}, + "util", "dofile.pl")), + rel2abs($config{builddir})); + return <<"EOF"; +$script : $sources + \$(PERL) "-I\$(BLDDIR)" "-Mconfigdata" $dofile - + "-o$target{build_file}" $sources > $script + SET FILE/PROT=(S:RWED,O:RWED,G:RE,W:RE) $script + PURGE $script +EOF + } + "" # Important! This becomes part of the template result. +-} diff --git a/trunk/3rdparty/openssl-1.1-fit/Configurations/shared-info.pl b/trunk/3rdparty/openssl-1.1-fit/Configurations/shared-info.pl new file mode 100644 index 000000000..47eddd683 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/Configurations/shared-info.pl @@ -0,0 +1,82 @@ +#! /usr/bin/env perl +# -*- mode: perl; -*- +# Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# This is a collection of extra attributes to be used as input for creating +# shared libraries, currently on any Unix variant, including Unix like +# environments on Windows. + +sub detect_gnu_ld { + my @lines = + `$config{CROSS_COMPILE}$config{CC} -Wl,-V /dev/null 2>&1`; + return grep /^GNU ld/, @lines; +} +sub detect_gnu_cc { + my @lines = + `$config{CROSS_COMPILE}$config{CC} -v 2>&1`; + return grep /gcc/, @lines; +} + +my %shared_info; +%shared_info = ( + 'gnu-shared' => { + shared_ldflag => '-shared -Wl,-Bsymbolic', + shared_sonameflag => '-Wl,-soname=', + }, + 'linux-shared' => sub { + return { + %{$shared_info{'gnu-shared'}}, + shared_defflag => '-Wl,--version-script=', + }; + }, + 'bsd-gcc-shared' => sub { return $shared_info{'linux-shared'}; }, + 'bsd-shared' => sub { + return $shared_info{'gnu-shared'} if detect_gnu_ld(); + return { + shared_ldflag => '-shared -nostdlib', + }; + }, + 'darwin-shared' => { + module_ldflags => '-bundle', + shared_ldflag => '-dynamiclib -current_version $(SHLIB_VERSION_NUMBER) -compatibility_version $(SHLIB_VERSION_NUMBER)', + shared_sonameflag => '-install_name $(INSTALLTOP)/$(LIBDIR)/', + }, + 'cygwin-shared' => { + shared_ldflag => '-shared -Wl,--enable-auto-image-base', + shared_impflag => '-Wl,--out-implib=', + }, + 'mingw-shared' => sub { + return { + %{$shared_info{'cygwin-shared'}}, + # def_flag made to empty string so it still generates + # something + shared_defflag => '', + }; + }, + 'alpha-osf1-shared' => sub { + return $shared_info{'gnu-shared'} if detect_gnu_ld(); + return { + module_ldflags => '-shared -Wl,-Bsymbolic', + shared_ldflag => '-shared -Wl,-Bsymbolic -set_version $(SHLIB_VERSION_NUMBER)', + }; + }, + 'svr3-shared' => sub { + return $shared_info{'gnu-shared'} if detect_gnu_ld(); + return { + shared_ldflag => '-G', + shared_sonameflag => '-h ', + }; + }, + 'svr5-shared' => sub { + return $shared_info{'gnu-shared'} if detect_gnu_ld(); + return { + shared_ldflag => detect_gnu_cc() ? '-shared' : '-G', + shared_sonameflag => '-h ', + }; + }, +); diff --git a/trunk/3rdparty/openssl-1.1-fit/Configurations/unix-Makefile.tmpl b/trunk/3rdparty/openssl-1.1-fit/Configurations/unix-Makefile.tmpl new file mode 100644 index 000000000..288b79202 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/Configurations/unix-Makefile.tmpl @@ -0,0 +1,1253 @@ +## +## Makefile for OpenSSL +## +## {- join("\n## ", @autowarntext) -} +{- + our $objext = $target{obj_extension} || ".o"; + our $depext = $target{dep_extension} || ".d"; + our $exeext = $target{exe_extension} || ""; + our $libext = $target{lib_extension} || ".a"; + our $shlibext = $target{shared_extension} || ".so"; + our $shlibvariant = $target{shlib_variant} || ""; + our $shlibextsimple = $target{shared_extension_simple} || ".so"; + our $shlibextimport = $target{shared_import_extension} || ""; + our $dsoext = $target{dso_extension} || ".so"; + our $makedepprog = $disabled{makedepend} ? undef : $config{makedepprog}; + + sub windowsdll { $config{target} =~ /^(?:Cygwin|mingw)/ } + + # Shared AIX support is special. We put libcrypto[64].so.ver into + # libcrypto.a and use libcrypto_a.a as static one. + sub sharedaix { !$disabled{shared} && $config{target} =~ /^aix/ } + + our $sover_dirname = $config{shlib_version_number}; + $sover_dirname =~ s|\.|_|g + if $config{target} =~ /^mingw/; + + # shlib and shlib_simple both take a static library name and figure + # out what the shlib name should be. + # + # When OpenSSL is configured "no-shared", these functions will just + # return empty lists, making them suitable to join(). + # + # With Windows DLL producers, shlib($libname) will return the shared + # library name (which usually is different from the static library + # name) with the default shared extension appended to it, while + # shlib_simple($libname) will return the static library name with + # the shared extension followed by ".a" appended to it. The former + # result is used as the runtime shared library while the latter is + # used as the DLL import library. + # + # On all Unix systems, shlib($libname) will return the library name + # with the default shared extension, while shlib_simple($libname) + # will return the name from shlib($libname) with any SO version number + # removed. On some systems, they may therefore return the exact same + # string. + sub shlib { + my $lib = shift; + return () if $disabled{shared} || $lib =~ /\.a$/; + return $unified_info{sharednames}->{$lib}. $shlibvariant. '$(SHLIB_EXT)'; + } + sub shlib_simple { + my $lib = shift; + return () if $disabled{shared} || $lib =~ /\.a$/; + + if (windowsdll()) { + return $lib . '$(SHLIB_EXT_IMPORT)'; + } + return $lib . '$(SHLIB_EXT_SIMPLE)'; + } + + # Easy fixing of static library names + sub lib { + (my $lib = shift) =~ s/\.a$//; + return $lib . $libext; + } + + # dso is a complement to shlib / shlib_simple that returns the + # given libname with the simple shared extension (possible SO version + # removed). This differs from shlib_simple() by being unconditional. + sub dso { + my $engine = shift; + + return $engine . $dsoext; + } + # This makes sure things get built in the order they need + # to. You're welcome. + sub dependmagic { + my $target = shift; + + return "$target: build_generated\n\t\$(MAKE) depend && \$(MAKE) _$target\n_$target"; + } + ''; +-} +PLATFORM={- $config{target} -} +OPTIONS={- $config{options} -} +CONFIGURE_ARGS=({- join(", ",quotify_l(@{$config{perlargv}})) -}) +SRCDIR={- $config{sourcedir} -} +BLDDIR={- $config{builddir} -} + +VERSION={- $config{version} -} +MAJOR={- $config{major} -} +MINOR={- $config{minor} -} +SHLIB_VERSION_NUMBER={- $config{shlib_version_number} -} +SHLIB_VERSION_HISTORY={- $config{shlib_version_history} -} +SHLIB_MAJOR={- $config{shlib_major} -} +SHLIB_MINOR={- $config{shlib_minor} -} +SHLIB_TARGET={- $target{shared_target} -} +SHLIB_EXT={- $shlibext -} +SHLIB_EXT_SIMPLE={- $shlibextsimple -} +SHLIB_EXT_IMPORT={- $shlibextimport -} + +LIBS={- join(" ", map { lib($_) } @{$unified_info{libraries}}) -} +SHLIBS={- join(" ", map { shlib($_) } @{$unified_info{libraries}}) -} +SHLIB_INFO={- join(" ", map { "\"".shlib($_).";".shlib_simple($_)."\"" } @{$unified_info{libraries}}) -} +ENGINES={- join(" ", map { dso($_) } @{$unified_info{engines}}) -} +PROGRAMS={- join(" ", map { $_.$exeext } @{$unified_info{programs}}) -} +SCRIPTS={- join(" ", @{$unified_info{scripts}}) -} +{- output_off() if $disabled{makedepend}; "" -} +DEPS={- join(" ", map { (my $x = $_) =~ s|\.o$|$depext|; $x; } + grep { $unified_info{sources}->{$_}->[0] =~ /\.c$/ } + keys %{$unified_info{sources}}); -} +{- output_on() if $disabled{makedepend}; "" -} +GENERATED_MANDATORY={- join(" ", @{$unified_info{depends}->{""}}) -} +GENERATED={- # common0.tmpl provides @generated + join(" ", @generated ) -} + +INSTALL_LIBS={- join(" ", map { lib($_) } @{$unified_info{install}->{libraries}}) -} +INSTALL_SHLIBS={- join(" ", map { shlib($_) } @{$unified_info{install}->{libraries}}) -} +INSTALL_SHLIB_INFO={- join(" ", map { "\"".shlib($_).";".shlib_simple($_)."\"" } @{$unified_info{install}->{libraries}}) -} +INSTALL_ENGINES={- join(" ", map { dso($_) } @{$unified_info{install}->{engines}}) -} +INSTALL_PROGRAMS={- join(" ", map { $_.$exeext } @{$unified_info{install}->{programs}}) -} +{- output_off() if $disabled{apps}; "" -} +BIN_SCRIPTS=$(BLDDIR)/tools/c_rehash +MISC_SCRIPTS=$(BLDDIR)/apps/CA.pl $(BLDDIR)/apps/tsget.pl:tsget +{- output_on() if $disabled{apps}; "" -} + +APPS_OPENSSL={- use File::Spec::Functions; + catfile("apps","openssl") -} + +# DESTDIR is for package builders so that they can configure for, say, +# /usr/ and yet have everything installed to /tmp/somedir/usr/. +# Normally it is left empty. +DESTDIR= + +# Do not edit these manually. Use Configure with --prefix or --openssldir +# to change this! Short explanation in the top comment in Configure +INSTALLTOP={- # $prefix is used in the OPENSSLDIR perl snippet + # + our $prefix = $config{prefix} || "/usr/local"; + $prefix -} +OPENSSLDIR={- # + # The logic here is that if no --openssldir was given, + # OPENSSLDIR will get the value from $prefix plus "/ssl". + # If --openssldir was given and the value is an absolute + # path, OPENSSLDIR will get its value without change. + # If the value from --openssldir is a relative path, + # OPENSSLDIR will get $prefix with the --openssldir + # value appended as a subdirectory. + # + use File::Spec::Functions; + our $openssldir = + $config{openssldir} ? + (file_name_is_absolute($config{openssldir}) ? + $config{openssldir} + : catdir($prefix, $config{openssldir})) + : catdir($prefix, "ssl"); + $openssldir -} +LIBDIR={- our $libdir = $config{libdir}; + unless ($libdir) { + # + # if $prefix/lib$target{multilib} is not an existing + # directory, then assume that it's not searched by linker + # automatically, in which case adding $target{multilib} suffix + # causes more grief than we're ready to tolerate, so don't... + our $multilib = + -d "$prefix/lib$target{multilib}" ? $target{multilib} : ""; + $libdir = "lib$multilib"; + } + file_name_is_absolute($libdir) ? "" : $libdir -} +# $(libdir) is chosen to be compatible with the GNU coding standards +libdir={- file_name_is_absolute($libdir) + ? $libdir : '$(INSTALLTOP)/$(LIBDIR)' -} +ENGINESDIR=$(libdir)/engines-{- $sover_dirname -} + +# Convenience variable for those who want to set the rpath in shared +# libraries and applications +LIBRPATH=$(libdir) + +MANDIR=$(INSTALLTOP)/share/man +DOCDIR=$(INSTALLTOP)/share/doc/$(BASENAME) +HTMLDIR=$(DOCDIR)/html + +# MANSUFFIX is for the benefit of anyone who may want to have a suffix +# appended after the manpage file section number. "ssl" is popular, +# resulting in files such as config.5ssl rather than config.5. +MANSUFFIX= +HTMLSUFFIX=html + +# For "optional" echo messages, to get "real" silence +ECHO = echo + +##### User defined commands and flags ################################ + +# We let the C compiler driver to take care of .s files. This is done in +# order to be excused from maintaining a separate set of architecture +# dependent assembler flags. E.g. if you throw -mcpu=ultrasparc at SPARC +# gcc, then the driver will automatically translate it to -xarch=v8plus +# and pass it down to assembler. In any case, we do not define AS or +# ASFLAGS for this reason. + +CROSS_COMPILE={- $config{CROSS_COMPILE} -} +CC=$(CROSS_COMPILE){- $config{CC} -} +CXX={- $config{CXX} ? "\$(CROSS_COMPILE)$config{CXX}" : '' -} +CPPFLAGS={- our $cppflags1 = join(" ", + (map { "-D".$_} @{$config{CPPDEFINES}}), + (map { "-I".$_} @{$config{CPPINCLUDES}}), + @{$config{CPPFLAGS}}) -} +CFLAGS={- join(' ', @{$config{CFLAGS}}) -} +CXXFLAGS={- join(' ', @{$config{CXXFLAGS}}) -} +LDFLAGS= {- join(' ', @{$config{LDFLAGS}}) -} +EX_LIBS= {- join(' ', @{$config{LDLIBS}}) -} + +MAKEDEPEND={- $config{makedepprog} -} + +PERL={- $config{PERL} -} + +AR=$(CROSS_COMPILE){- $config{AR} -} +ARFLAGS= {- join(' ', @{$config{ARFLAGS}}) -} +RANLIB={- $config{RANLIB} ? "\$(CROSS_COMPILE)$config{RANLIB}" : "true"; -} +RC= $(CROSS_COMPILE){- $config{RC} -} +RCFLAGS={- join(' ', @{$config{RCFLAGS}}) -} {- $target{shared_rcflag} -} + +RM= rm -f +RMDIR= rmdir +TAR= {- $target{TAR} || "tar" -} +TARFLAGS= {- $target{TARFLAGS} -} + +BASENAME= openssl +NAME= $(BASENAME)-$(VERSION) +# Relative to $(SRCDIR) +TARFILE= ../$(NAME).tar + +##### Project flags ################################################## + +# Variables starting with CNF_ are common variables for all product types + +CNF_CPPFLAGS={- our $cppflags2 = + join(' ', $target{cppflags} || (), + (map { "-D".$_} @{$target{defines}}, + @{$config{defines}}), + (map { "-I".$_} @{$target{includes}}, + @{$config{includes}}), + @{$config{cppflags}}) -} +CNF_CFLAGS={- join(' ', $target{cflags} || (), + @{$config{cflags}}) -} +CNF_CXXFLAGS={- join(' ', $target{cxxflags} || (), + @{$config{cxxflags}}) -} +CNF_LDFLAGS={- join(' ', $target{lflags} || (), + @{$config{lflags}}) -} +CNF_EX_LIBS={- join(' ', $target{ex_libs} || (), + @{$config{ex_libs}}) -} + +# Variables starting with LIB_ are used to build library object files +# and shared libraries. +# Variables starting with DSO_ are used to build DSOs and their object files. +# Variables starting with BIN_ are used to build programs and their object +# files. + +LIB_CPPFLAGS={- our $lib_cppflags = + join(' ', $target{lib_cppflags} || (), + $target{shared_cppflag} || (), + (map { '-D'.$_ } + @{$config{lib_defines}}, + @{$config{shared_defines}}), + @{$config{lib_cppflags}}, + @{$config{shared_cppflag}}); + join(' ', $lib_cppflags, + (map { '-D'.$_ } + 'OPENSSLDIR="\"$(OPENSSLDIR)\""', + 'ENGINESDIR="\"$(ENGINESDIR)\""'), + '$(CNF_CPPFLAGS)', '$(CPPFLAGS)') -} +LIB_CFLAGS={- join(' ', $target{lib_cflags} || (), + $target{shared_cflag} || (), + @{$config{lib_cflags}}, + @{$config{shared_cflag}}, + '$(CNF_CFLAGS)', '$(CFLAGS)') -} +LIB_CXXFLAGS={- join(' ', $target{lib_cxxflags} || (), + $target{shared_cxxflag} || (), + @{$config{lib_cxxflags}}, + @{$config{shared_cxxflag}}, + '$(CNF_CXXFLAGS)', '$(CXXFLAGS)') -} +LIB_LDFLAGS={- join(' ', $target{shared_ldflag} || (), + $config{shared_ldflag} || (), + '$(CNF_LDFLAGS)', '$(LDFLAGS)') -} +LIB_EX_LIBS=$(CNF_EX_LIBS) $(EX_LIBS) +DSO_CPPFLAGS={- join(' ', $target{dso_cppflags} || (), + $target{module_cppflags} || (), + @{$config{dso_cppflags}}, + @{$config{module_cppflags}}, + '$(CNF_CPPFLAGS)', '$(CPPFLAGS)') -} +DSO_CFLAGS={- join(' ', $target{dso_cflags} || (), + $target{module_cflags} || (), + @{$config{dso_cflags}}, + @{$config{module_cflags}}, + '$(CNF_CFLAGS)', '$(CFLAGS)') -} +DSO_CXXFLAGS={- join(' ', $target{dso_cxxflags} || (), + $target{module_cxxflags} || (), + @{$config{dso_cxxflags}}, + @{$config{module_cxxflag}}, + '$(CNF_CXXFLAGS)', '$(CXXFLAGS)') -} +DSO_LDFLAGS={- join(' ', $target{dso_ldflags} || (), + $target{module_ldflags} || (), + @{$config{dso_ldflags}}, + @{$config{module_ldflags}}, + '$(CNF_LDFLAGS)', '$(LDFLAGS)') -} +DSO_EX_LIBS=$(CNF_EX_LIBS) $(EX_LIBS) +BIN_CPPFLAGS={- join(' ', $target{bin_cppflags} || (), + @{$config{bin_cppflags}}, + '$(CNF_CPPFLAGS)', '$(CPPFLAGS)') -} +BIN_CFLAGS={- join(' ', $target{bin_cflags} || (), + @{$config{bin_cflags}}, + '$(CNF_CFLAGS)', '$(CFLAGS)') -} +BIN_CXXFLAGS={- join(' ', $target{bin_cxxflags} || (), + @{$config{bin_cxxflags}}, + '$(CNF_CXXFLAGS)', '$(CXXFLAGS)') -} +BIN_LDFLAGS={- join(' ', $target{bin_lflags} || (), + @{$config{bin_lflags}}, + '$(CNF_LDFLAGS)', '$(LDFLAGS)') -} +BIN_EX_LIBS=$(CNF_EX_LIBS) $(EX_LIBS) + +# CPPFLAGS_Q is used for one thing only: to build up buildinf.h +CPPFLAGS_Q={- $cppflags1 =~ s|([\\"])|\\$1|g; + $cppflags2 =~ s|([\\"])|\\$1|g; + $lib_cppflags =~ s|([\\"])|\\$1|g; + join(' ', $lib_cppflags || (), $cppflags2 || (), + $cppflags1 || ()) -} + +PERLASM_SCHEME= {- $target{perlasm_scheme} -} + +# For x86 assembler: Set PROCESSOR to 386 if you want to support +# the 80386. +PROCESSOR= {- $config{processor} -} + +# We want error [and other] messages in English. Trouble is that make(1) +# doesn't pass macros down as environment variables unless there already +# was corresponding variable originally set. In other words we can only +# reassign environment variables, but not set new ones, not in portable +# manner that is. That's why we reassign several, just to be sure... +LC_ALL=C +LC_MESSAGES=C +LANG=C + +# The main targets ################################################### + +{- dependmagic('all'); -}: build_libs_nodep build_engines_nodep build_programs_nodep link-utils +{- dependmagic('build_libs'); -}: build_libs_nodep +{- dependmagic('build_engines'); -}: build_engines_nodep +{- dependmagic('build_programs'); -}: build_programs_nodep + +build_generated: $(GENERATED_MANDATORY) +build_libs_nodep: libcrypto.pc libssl.pc openssl.pc +build_engines_nodep: $(ENGINES) +build_programs_nodep: $(PROGRAMS) $(SCRIPTS) + +# Kept around for backward compatibility +build_apps build_tests: build_programs + +# Convenience target to prebuild all generated files, not just the mandatory +# ones +build_all_generated: $(GENERATED_MANDATORY) $(GENERATED) + @ : {- output_off() if $disabled{makedepend}; "" -} + @echo "Warning: consider configuring with no-makedepend, because if" + @echo " target system doesn't have $(PERL)," + @echo " then make will fail..." + @ : {- output_on() if $disabled{makedepend}; "" -} + +test: tests +{- dependmagic('tests'); -}: build_programs_nodep build_engines_nodep link-utils + @ : {- output_off() if $disabled{tests}; "" -} + ( cd test; \ + mkdir -p test-runs; \ + SRCTOP=../$(SRCDIR) \ + BLDTOP=../$(BLDDIR) \ + RESULT_D=test-runs \ + PERL="$(PERL)" \ + EXE_EXT={- $exeext -} \ + OPENSSL_ENGINES=`cd ../$(BLDDIR)/engines 2>/dev/null && pwd` \ + OPENSSL_DEBUG_MEMORY=on \ + $(PERL) ../$(SRCDIR)/test/run_tests.pl $(TESTS) ) + @ : {- if ($disabled{tests}) { output_on(); } else { output_off(); } "" -} + @echo "Tests are not supported with your chosen Configure options" + @ : {- output_on() if !$disabled{tests}; "" -} + +list-tests: + @ : {- output_off() if $disabled{tests}; "" -} + @SRCTOP="$(SRCDIR)" \ + $(PERL) $(SRCDIR)/test/run_tests.pl list + @ : {- if ($disabled{tests}) { output_on(); } else { output_off(); } "" -} + @echo "Tests are not supported with your chosen Configure options" + @ : {- output_on() if !$disabled{tests}; "" -} + +install: install_sw install_ssldirs install_docs + +uninstall: uninstall_docs uninstall_sw + +libclean: + @set -e; for s in $(SHLIB_INFO); do \ + if [ "$$s" = ";" ]; then continue; fi; \ + s1=`echo "$$s" | cut -f1 -d";"`; \ + s2=`echo "$$s" | cut -f2 -d";"`; \ + $(ECHO) $(RM) $$s1; {- output_off() unless windowsdll(); "" -}\ + $(RM) apps/$$s1; \ + $(RM) test/$$s1; \ + $(RM) fuzz/$$s1; {- output_on() unless windowsdll(); "" -}\ + $(RM) $$s1; \ + if [ "$$s1" != "$$s2" ]; then \ + $(ECHO) $(RM) $$s2; \ + $(RM) $$s2; \ + fi; \ + done + $(RM) $(LIBS) + $(RM) *.map + +clean: libclean + $(RM) $(PROGRAMS) $(TESTPROGS) $(ENGINES) $(SCRIPTS) + $(RM) $(GENERATED_MANDATORY) $(GENERATED) + -$(RM) `find . -name .git -prune -o -name '*{- $depext -}' -print` + -$(RM) `find . -name .git -prune -o -name '*{- $objext -}' -print` + $(RM) core + $(RM) tags TAGS doc-nits + $(RM) -r test/test-runs + $(RM) openssl.pc libcrypto.pc libssl.pc + -$(RM) `find . -name .git -prune -o -type l -print` + $(RM) $(TARFILE) + +distclean: clean + $(RM) configdata.pm + $(RM) Makefile + +# We check if any depfile is newer than Makefile and decide to +# concatenate only if that is true. +depend: + @: {- output_off() if $disabled{makedepend}; "" -} + @$(PERL) $(SRCDIR)/util/add-depends.pl {- + defined $makedepprog && $makedepprog =~ /\/makedepend/ + ? 'makedepend' : 'gcc' -} + @: {- output_on() if $disabled{makedepend}; "" -} + +# Install helper targets ############################################# + +install_sw: install_dev install_engines install_runtime + +uninstall_sw: uninstall_runtime uninstall_engines uninstall_dev + +install_docs: install_man_docs install_html_docs + +uninstall_docs: uninstall_man_docs uninstall_html_docs + $(RM) -r -v $(DESTDIR)$(DOCDIR) + +install_ssldirs: + @$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(OPENSSLDIR)/certs + @$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(OPENSSLDIR)/private + @$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(OPENSSLDIR)/misc + @set -e; for x in dummy $(MISC_SCRIPTS); do \ + if [ "$$x" = "dummy" ]; then continue; fi; \ + x1=`echo "$$x" | cut -f1 -d:`; \ + x2=`echo "$$x" | cut -f2 -d:`; \ + fn=`basename $$x1`; \ + $(ECHO) "install $$x1 -> $(DESTDIR)$(OPENSSLDIR)/misc/$$fn"; \ + cp $$x1 $(DESTDIR)$(OPENSSLDIR)/misc/$$fn.new; \ + chmod 755 $(DESTDIR)$(OPENSSLDIR)/misc/$$fn.new; \ + mv -f $(DESTDIR)$(OPENSSLDIR)/misc/$$fn.new \ + $(DESTDIR)$(OPENSSLDIR)/misc/$$fn; \ + if [ "$$x1" != "$$x2" ]; then \ + ln=`basename "$$x2"`; \ + : {- output_off() unless windowsdll(); "" -}; \ + $(ECHO) "copy $(DESTDIR)$(OPENSSLDIR)/misc/$$ln -> $(DESTDIR)$(OPENSSLDIR)/misc/$$fn"; \ + cp $(DESTDIR)$(OPENSSLDIR)/misc/$$fn $(DESTDIR)$(OPENSSLDIR)/misc/$$ln; \ + : {- output_on() unless windowsdll(); + output_off() if windowsdll(); "" -}; \ + $(ECHO) "link $(DESTDIR)$(OPENSSLDIR)/misc/$$ln -> $(DESTDIR)$(OPENSSLDIR)/misc/$$fn"; \ + ln -sf $$fn $(DESTDIR)$(OPENSSLDIR)/misc/$$ln; \ + : {- output_on() if windowsdll(); "" -}; \ + fi; \ + done + @$(ECHO) "install $(SRCDIR)/apps/openssl.cnf -> $(DESTDIR)$(OPENSSLDIR)/openssl.cnf.dist" + @cp $(SRCDIR)/apps/openssl.cnf $(DESTDIR)$(OPENSSLDIR)/openssl.cnf.new + @chmod 644 $(DESTDIR)$(OPENSSLDIR)/openssl.cnf.new + @mv -f $(DESTDIR)$(OPENSSLDIR)/openssl.cnf.new $(DESTDIR)$(OPENSSLDIR)/openssl.cnf.dist + @if [ ! -f "$(DESTDIR)$(OPENSSLDIR)/openssl.cnf" ]; then \ + $(ECHO) "install $(SRCDIR)/apps/openssl.cnf -> $(DESTDIR)$(OPENSSLDIR)/openssl.cnf"; \ + cp $(SRCDIR)/apps/openssl.cnf $(DESTDIR)$(OPENSSLDIR)/openssl.cnf; \ + chmod 644 $(DESTDIR)$(OPENSSLDIR)/openssl.cnf; \ + fi + @$(ECHO) "install $(SRCDIR)/apps/ct_log_list.cnf -> $(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf.dist" + @cp $(SRCDIR)/apps/ct_log_list.cnf $(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf.new + @chmod 644 $(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf.new + @mv -f $(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf.new $(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf.dist + @if [ ! -f "$(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf" ]; then \ + $(ECHO) "install $(SRCDIR)/apps/ct_log_list.cnf -> $(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf"; \ + cp $(SRCDIR)/apps/ct_log_list.cnf $(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf; \ + chmod 644 $(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf; \ + fi + +install_dev: install_runtime_libs + @[ -n "$(INSTALLTOP)" ] || (echo INSTALLTOP should not be empty; exit 1) + @$(ECHO) "*** Installing development files" + @$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(INSTALLTOP)/include/openssl + @ : {- output_off() unless grep { $_ eq "OPENSSL_USE_APPLINK" } (@{$target{defines}}, @{$config{defines}}); "" -} + @$(ECHO) "install $(SRCDIR)/ms/applink.c -> $(DESTDIR)$(INSTALLTOP)/include/openssl/applink.c" + @cp $(SRCDIR)/ms/applink.c $(DESTDIR)$(INSTALLTOP)/include/openssl/applink.c + @chmod 644 $(DESTDIR)$(INSTALLTOP)/include/openssl/applink.c + @ : {- output_on() unless grep { $_ eq "OPENSSL_USE_APPLINK" } (@{$target{defines}}, @{$config{defines}}); "" -} + @set -e; for i in $(SRCDIR)/include/openssl/*.h \ + $(BLDDIR)/include/openssl/*.h; do \ + fn=`basename $$i`; \ + $(ECHO) "install $$i -> $(DESTDIR)$(INSTALLTOP)/include/openssl/$$fn"; \ + cp $$i $(DESTDIR)$(INSTALLTOP)/include/openssl/$$fn; \ + chmod 644 $(DESTDIR)$(INSTALLTOP)/include/openssl/$$fn; \ + done + @$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(libdir) + @set -e; for l in $(INSTALL_LIBS); do \ + fn=`basename $$l`; \ + $(ECHO) "install $$l -> $(DESTDIR)$(libdir)/$$fn"; \ + cp $$l $(DESTDIR)$(libdir)/$$fn.new; \ + $(RANLIB) $(DESTDIR)$(libdir)/$$fn.new; \ + chmod 644 $(DESTDIR)$(libdir)/$$fn.new; \ + mv -f $(DESTDIR)$(libdir)/$$fn.new \ + $(DESTDIR)$(libdir)/$$fn; \ + done + @ : {- output_off() if $disabled{shared}; "" -} + @set -e; for s in $(INSTALL_SHLIB_INFO); do \ + s1=`echo "$$s" | cut -f1 -d";"`; \ + s2=`echo "$$s" | cut -f2 -d";"`; \ + fn1=`basename $$s1`; \ + fn2=`basename $$s2`; \ + : {- output_off(); output_on() unless windowsdll() or sharedaix(); "" -}; \ + if [ "$$fn1" != "$$fn2" ]; then \ + $(ECHO) "link $(DESTDIR)$(libdir)/$$fn2 -> $(DESTDIR)$(libdir)/$$fn1"; \ + ln -sf $$fn1 $(DESTDIR)$(libdir)/$$fn2; \ + fi; \ + : {- output_off() unless windowsdll() or sharedaix(); output_on() if windowsdll(); "" -}; \ + $(ECHO) "install $$s2 -> $(DESTDIR)$(libdir)/$$fn2"; \ + cp $$s2 $(DESTDIR)$(libdir)/$$fn2.new; \ + chmod 755 $(DESTDIR)$(libdir)/$$fn2.new; \ + mv -f $(DESTDIR)$(libdir)/$$fn2.new \ + $(DESTDIR)$(libdir)/$$fn2; \ + : {- output_off() if windowsdll(); output_on() if sharedaix(); "" -}; \ + a=$(DESTDIR)$(libdir)/$$fn2; \ + $(ECHO) "install $$s1 -> $$a"; \ + if [ -f $$a ]; then ( trap "rm -rf /tmp/ar.$$$$" INT 0; \ + mkdir /tmp/ar.$$$$; ( cd /tmp/ar.$$$$; \ + cp -f $$a $$a.new; \ + for so in `$(AR) t $$a`; do \ + $(AR) x $$a $$so; \ + chmod u+w $$so; \ + strip -X32_64 -e $$so; \ + $(AR) r $$a.new $$so; \ + done; \ + )); fi; \ + $(AR) r $$a.new $$s1; \ + mv -f $$a.new $$a; \ + : {- output_off() if sharedaix(); output_on(); "" -}; \ + done + @ : {- output_on() if $disabled{shared}; "" -} + @$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(libdir)/pkgconfig + @$(ECHO) "install libcrypto.pc -> $(DESTDIR)$(libdir)/pkgconfig/libcrypto.pc" + @cp libcrypto.pc $(DESTDIR)$(libdir)/pkgconfig + @chmod 644 $(DESTDIR)$(libdir)/pkgconfig/libcrypto.pc + @$(ECHO) "install libssl.pc -> $(DESTDIR)$(libdir)/pkgconfig/libssl.pc" + @cp libssl.pc $(DESTDIR)$(libdir)/pkgconfig + @chmod 644 $(DESTDIR)$(libdir)/pkgconfig/libssl.pc + @$(ECHO) "install openssl.pc -> $(DESTDIR)$(libdir)/pkgconfig/openssl.pc" + @cp openssl.pc $(DESTDIR)$(libdir)/pkgconfig + @chmod 644 $(DESTDIR)$(libdir)/pkgconfig/openssl.pc + +uninstall_dev: uninstall_runtime_libs + @$(ECHO) "*** Uninstalling development files" + @ : {- output_off() unless grep { $_ eq "OPENSSL_USE_APPLINK" } (@{$target{defines}}, @{$config{defines}}); "" -} + @$(ECHO) "$(RM) $(DESTDIR)$(INSTALLTOP)/include/openssl/applink.c" + @$(RM) $(DESTDIR)$(INSTALLTOP)/include/openssl/applink.c + @ : {- output_on() unless grep { $_ eq "OPENSSL_USE_APPLINK" } (@{$target{defines}}, @{$config{defines}}); "" -} + @set -e; for i in $(SRCDIR)/include/openssl/*.h \ + $(BLDDIR)/include/openssl/*.h; do \ + fn=`basename $$i`; \ + $(ECHO) "$(RM) $(DESTDIR)$(INSTALLTOP)/include/openssl/$$fn"; \ + $(RM) $(DESTDIR)$(INSTALLTOP)/include/openssl/$$fn; \ + done + -$(RMDIR) $(DESTDIR)$(INSTALLTOP)/include/openssl + -$(RMDIR) $(DESTDIR)$(INSTALLTOP)/include + @set -e; for l in $(INSTALL_LIBS); do \ + fn=`basename $$l`; \ + $(ECHO) "$(RM) $(DESTDIR)$(libdir)/$$fn"; \ + $(RM) $(DESTDIR)$(libdir)/$$fn; \ + done + @ : {- output_off() if $disabled{shared}; "" -} + @set -e; for s in $(INSTALL_SHLIB_INFO); do \ + s1=`echo "$$s" | cut -f1 -d";"`; \ + s2=`echo "$$s" | cut -f2 -d";"`; \ + fn1=`basename $$s1`; \ + fn2=`basename $$s2`; \ + : {- output_off() if windowsdll(); "" -}; \ + $(ECHO) "$(RM) $(DESTDIR)$(libdir)/$$fn2"; \ + $(RM) $(DESTDIR)$(libdir)/$$fn2; \ + if [ "$$fn1" != "$$fn2" -a -f "$(DESTDIR)$(libdir)/$$fn1" ]; then \ + $(ECHO) "$(RM) $(DESTDIR)$(libdir)/$$fn1"; \ + $(RM) $(DESTDIR)$(libdir)/$$fn1; \ + fi; \ + : {- output_on() if windowsdll(); "" -}{- output_off() unless windowsdll(); "" -}; \ + $(ECHO) "$(RM) $(DESTDIR)$(libdir)/$$fn2"; \ + $(RM) $(DESTDIR)$(libdir)/$$fn2; \ + : {- output_on() unless windowsdll(); "" -}; \ + done + @ : {- output_on() if $disabled{shared}; "" -} + $(RM) $(DESTDIR)$(libdir)/pkgconfig/libcrypto.pc + $(RM) $(DESTDIR)$(libdir)/pkgconfig/libssl.pc + $(RM) $(DESTDIR)$(libdir)/pkgconfig/openssl.pc + -$(RMDIR) $(DESTDIR)$(libdir)/pkgconfig + -$(RMDIR) $(DESTDIR)$(libdir) + +install_engines: install_runtime_libs build_engines + @[ -n "$(INSTALLTOP)" ] || (echo INSTALLTOP should not be empty; exit 1) + @$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(ENGINESDIR)/ + @$(ECHO) "*** Installing engines" + @set -e; for e in dummy $(INSTALL_ENGINES); do \ + if [ "$$e" = "dummy" ]; then continue; fi; \ + fn=`basename $$e`; \ + $(ECHO) "install $$e -> $(DESTDIR)$(ENGINESDIR)/$$fn"; \ + cp $$e $(DESTDIR)$(ENGINESDIR)/$$fn.new; \ + chmod 755 $(DESTDIR)$(ENGINESDIR)/$$fn.new; \ + mv -f $(DESTDIR)$(ENGINESDIR)/$$fn.new \ + $(DESTDIR)$(ENGINESDIR)/$$fn; \ + done + +uninstall_engines: + @$(ECHO) "*** Uninstalling engines" + @set -e; for e in dummy $(INSTALL_ENGINES); do \ + if [ "$$e" = "dummy" ]; then continue; fi; \ + fn=`basename $$e`; \ + if [ "$$fn" = '{- dso("ossltest") -}' ]; then \ + continue; \ + fi; \ + $(ECHO) "$(RM) $(DESTDIR)$(ENGINESDIR)/$$fn"; \ + $(RM) $(DESTDIR)$(ENGINESDIR)/$$fn; \ + done + -$(RMDIR) $(DESTDIR)$(ENGINESDIR) + +install_runtime: install_programs + +install_runtime_libs: build_libs + @[ -n "$(INSTALLTOP)" ] || (echo INSTALLTOP should not be empty; exit 1) + @ : {- output_off() if windowsdll(); "" -} + @$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(libdir) + @ : {- output_on() if windowsdll(); output_off() unless windowsdll(); "" -} + @$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(INSTALLTOP)/bin + @ : {- output_on() unless windowsdll(); "" -} + @$(ECHO) "*** Installing runtime libraries" + @set -e; for s in dummy $(INSTALL_SHLIBS); do \ + if [ "$$s" = "dummy" ]; then continue; fi; \ + fn=`basename $$s`; \ + : {- output_off() unless windowsdll(); "" -}; \ + $(ECHO) "install $$s -> $(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \ + cp $$s $(DESTDIR)$(INSTALLTOP)/bin/$$fn.new; \ + chmod 755 $(DESTDIR)$(INSTALLTOP)/bin/$$fn.new; \ + mv -f $(DESTDIR)$(INSTALLTOP)/bin/$$fn.new \ + $(DESTDIR)$(INSTALLTOP)/bin/$$fn; \ + : {- output_on() unless windowsdll(); "" -}{- output_off() if windowsdll(); "" -}; \ + $(ECHO) "install $$s -> $(DESTDIR)$(libdir)/$$fn"; \ + cp $$s $(DESTDIR)$(libdir)/$$fn.new; \ + chmod 755 $(DESTDIR)$(libdir)/$$fn.new; \ + mv -f $(DESTDIR)$(libdir)/$$fn.new \ + $(DESTDIR)$(libdir)/$$fn; \ + : {- output_on() if windowsdll(); "" -}; \ + done + +install_programs: install_runtime_libs build_programs + @[ -n "$(INSTALLTOP)" ] || (echo INSTALLTOP should not be empty; exit 1) + @$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(INSTALLTOP)/bin + @$(ECHO) "*** Installing runtime programs" + @set -e; for x in dummy $(INSTALL_PROGRAMS); do \ + if [ "$$x" = "dummy" ]; then continue; fi; \ + fn=`basename $$x`; \ + $(ECHO) "install $$x -> $(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \ + cp $$x $(DESTDIR)$(INSTALLTOP)/bin/$$fn.new; \ + chmod 755 $(DESTDIR)$(INSTALLTOP)/bin/$$fn.new; \ + mv -f $(DESTDIR)$(INSTALLTOP)/bin/$$fn.new \ + $(DESTDIR)$(INSTALLTOP)/bin/$$fn; \ + done + @set -e; for x in dummy $(BIN_SCRIPTS); do \ + if [ "$$x" = "dummy" ]; then continue; fi; \ + fn=`basename $$x`; \ + $(ECHO) "install $$x -> $(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \ + cp $$x $(DESTDIR)$(INSTALLTOP)/bin/$$fn.new; \ + chmod 755 $(DESTDIR)$(INSTALLTOP)/bin/$$fn.new; \ + mv -f $(DESTDIR)$(INSTALLTOP)/bin/$$fn.new \ + $(DESTDIR)$(INSTALLTOP)/bin/$$fn; \ + done + +uninstall_runtime: uninstall_programs uninstall_runtime_libs + +uninstall_programs: + @$(ECHO) "*** Uninstalling runtime programs" + @set -e; for x in dummy $(INSTALL_PROGRAMS); \ + do \ + if [ "$$x" = "dummy" ]; then continue; fi; \ + fn=`basename $$x`; \ + $(ECHO) "$(RM) $(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \ + $(RM) $(DESTDIR)$(INSTALLTOP)/bin/$$fn; \ + done; + @set -e; for x in dummy $(BIN_SCRIPTS); \ + do \ + if [ "$$x" = "dummy" ]; then continue; fi; \ + fn=`basename $$x`; \ + $(ECHO) "$(RM) $(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \ + $(RM) $(DESTDIR)$(INSTALLTOP)/bin/$$fn; \ + done + -$(RMDIR) $(DESTDIR)$(INSTALLTOP)/bin + +uninstall_runtime_libs: + @$(ECHO) "*** Uninstalling runtime libraries" + @ : {- output_off() unless windowsdll(); "" -} + @set -e; for s in dummy $(INSTALL_SHLIBS); do \ + if [ "$$s" = "dummy" ]; then continue; fi; \ + fn=`basename $$s`; \ + $(ECHO) "$(RM) $(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \ + $(RM) $(DESTDIR)$(INSTALLTOP)/bin/$$fn; \ + done + @ : {- output_on() unless windowsdll(); "" -} + + +install_man_docs: + @[ -n "$(INSTALLTOP)" ] || (echo INSTALLTOP should not be empty; exit 1) + @$(ECHO) "*** Installing manpages" + $(PERL) $(SRCDIR)/util/process_docs.pl \ + --destdir=$(DESTDIR)$(MANDIR) --type=man --suffix=$(MANSUFFIX) + +uninstall_man_docs: + @$(ECHO) "*** Uninstalling manpages" + $(PERL) $(SRCDIR)/util/process_docs.pl \ + --destdir=$(DESTDIR)$(MANDIR) --type=man --suffix=$(MANSUFFIX) \ + --remove + +install_html_docs: + @[ -n "$(INSTALLTOP)" ] || (echo INSTALLTOP should not be empty; exit 1) + @$(ECHO) "*** Installing HTML manpages" + $(PERL) $(SRCDIR)/util/process_docs.pl \ + --destdir=$(DESTDIR)$(HTMLDIR) --type=html + +uninstall_html_docs: + @$(ECHO) "*** Uninstalling manpages" + $(PERL) $(SRCDIR)/util/process_docs.pl \ + --destdir=$(DESTDIR)$(HTMLDIR) --type=html --remove + + +# Developer targets (note: these are only available on Unix) ######### + +update: generate errors ordinals + +generate: generate_apps generate_crypto_bn generate_crypto_objects \ + generate_crypto_conf generate_crypto_asn1 generate_fuzz_oids + +.PHONY: doc-nits +doc-nits: + (cd $(SRCDIR); $(PERL) util/find-doc-nits -n -p ) >doc-nits + @if [ -s doc-nits ] ; then cat doc-nits ; exit 1; \ + else echo 'doc-nits: no errors.'; rm doc-nits ; fi + +# Test coverage is a good idea for the future +#coverage: $(PROGRAMS) $(TESTPROGRAMS) +# ... + +lint: + lint -DLINT $(INCLUDES) $(SRCS) + +generate_apps: + ( cd $(SRCDIR); $(PERL) VMS/VMSify-conf.pl \ + < apps/openssl.cnf > apps/openssl-vms.cnf ) + +generate_crypto_bn: + ( cd $(SRCDIR); $(PERL) crypto/bn/bn_prime.pl > crypto/bn/bn_prime.h ) + +generate_crypto_objects: + ( cd $(SRCDIR); $(PERL) crypto/objects/objects.pl -n \ + crypto/objects/objects.txt \ + crypto/objects/obj_mac.num \ + > crypto/objects/obj_mac.new && \ + mv crypto/objects/obj_mac.new crypto/objects/obj_mac.num ) + ( cd $(SRCDIR); $(PERL) crypto/objects/objects.pl \ + crypto/objects/objects.txt \ + crypto/objects/obj_mac.num \ + > include/openssl/obj_mac.h ) + ( cd $(SRCDIR); $(PERL) crypto/objects/obj_dat.pl \ + include/openssl/obj_mac.h \ + > crypto/objects/obj_dat.h ) + ( cd $(SRCDIR); $(PERL) crypto/objects/objxref.pl \ + crypto/objects/obj_mac.num \ + crypto/objects/obj_xref.txt \ + > crypto/objects/obj_xref.h ) + +generate_crypto_conf: + ( cd $(SRCDIR); $(PERL) crypto/conf/keysets.pl \ + > crypto/conf/conf_def.h ) + +generate_crypto_asn1: + ( cd $(SRCDIR); $(PERL) crypto/asn1/charmap.pl \ + > crypto/asn1/charmap.h ) + +generate_fuzz_oids: + ( cd $(SRCDIR); $(PERL) fuzz/mkfuzzoids.pl \ + crypto/objects/obj_dat.h \ + > fuzz/oids.txt ) + +# Set to -force to force a rebuild +ERROR_REBUILD= +errors: + ( b=`pwd`; set -e; cd $(SRCDIR); \ + $(PERL) util/ck_errf.pl -strict -internal; \ + $(PERL) -I$$b util/mkerr.pl $(ERROR_REBUILD) -internal ) + ( b=`pwd`; set -e; cd $(SRCDIR)/engines; \ + for E in *.ec ; do \ + $(PERL) ../util/ck_errf.pl -strict \ + -conf $$E `basename $$E .ec`.c; \ + $(PERL) -I$$b ../util/mkerr.pl $(ERROR_REBUILD) -static \ + -conf $$E `basename $$E .ec`.c ; \ + done ) + +ordinals: + ( b=`pwd`; cd $(SRCDIR); $(PERL) -I$$b util/mkdef.pl crypto update ) + ( b=`pwd`; cd $(SRCDIR); $(PERL) -I$$b util/mkdef.pl ssl update ) + +test_ordinals: + ( cd test; \ + SRCTOP=../$(SRCDIR) \ + BLDTOP=../$(BLDDIR) \ + $(PERL) ../$(SRCDIR)/test/run_tests.pl test_ordinals ) + +tags TAGS: FORCE + rm -f TAGS tags + -ctags -R . + -etags `find . -name '*.[ch]' -o -name '*.pm'` + +# Release targets (note: only available on Unix) ##################### + +tar: + (cd $(SRCDIR); ./util/mktar.sh --name='$(NAME)' --tarfile='$(TARFILE)') + +# Helper targets ##################################################### + +link-utils: $(BLDDIR)/util/opensslwrap.sh + +$(BLDDIR)/util/opensslwrap.sh: configdata.pm + @if [ "$(SRCDIR)" != "$(BLDDIR)" ]; then \ + mkdir -p "$(BLDDIR)/util"; \ + ln -sf "../$(SRCDIR)/util/opensslwrap.sh" "$(BLDDIR)/util"; \ + fi + +FORCE: + +# Building targets ################################################### + +libcrypto.pc libssl.pc openssl.pc: configdata.pm $(LIBS) {- join(" ",map { shlib_simple($_) } @{$unified_info{libraries}}) -} +libcrypto.pc: + @ ( echo 'prefix=$(INSTALLTOP)'; \ + echo 'exec_prefix=$${prefix}'; \ + if [ -n "$(LIBDIR)" ]; then \ + echo 'libdir=$${exec_prefix}/$(LIBDIR)'; \ + else \ + echo 'libdir=$(libdir)'; \ + fi; \ + echo 'includedir=$${prefix}/include'; \ + echo 'enginesdir=$${libdir}/engines-{- $sover_dirname -}'; \ + echo ''; \ + echo 'Name: OpenSSL-libcrypto'; \ + echo 'Description: OpenSSL cryptography library'; \ + echo 'Version: '$(VERSION); \ + echo 'Libs: -L$${libdir} -lcrypto'; \ + echo 'Libs.private: $(LIB_EX_LIBS)'; \ + echo 'Cflags: -I$${includedir}' ) > libcrypto.pc + +libssl.pc: + @ ( echo 'prefix=$(INSTALLTOP)'; \ + echo 'exec_prefix=$${prefix}'; \ + if [ -n "$(LIBDIR)" ]; then \ + echo 'libdir=$${exec_prefix}/$(LIBDIR)'; \ + else \ + echo 'libdir=$(libdir)'; \ + fi; \ + echo 'includedir=$${prefix}/include'; \ + echo ''; \ + echo 'Name: OpenSSL-libssl'; \ + echo 'Description: Secure Sockets Layer and cryptography libraries'; \ + echo 'Version: '$(VERSION); \ + echo 'Requires.private: libcrypto'; \ + echo 'Libs: -L$${libdir} -lssl'; \ + echo 'Cflags: -I$${includedir}' ) > libssl.pc + +openssl.pc: + @ ( echo 'prefix=$(INSTALLTOP)'; \ + echo 'exec_prefix=$${prefix}'; \ + if [ -n "$(LIBDIR)" ]; then \ + echo 'libdir=$${exec_prefix}/$(LIBDIR)'; \ + else \ + echo 'libdir=$(libdir)'; \ + fi; \ + echo 'includedir=$${prefix}/include'; \ + echo ''; \ + echo 'Name: OpenSSL'; \ + echo 'Description: Secure Sockets Layer and cryptography libraries and tools'; \ + echo 'Version: '$(VERSION); \ + echo 'Requires: libssl libcrypto' ) > openssl.pc + +configdata.pm: $(SRCDIR)/Configure $(SRCDIR)/config {- join(" ", @{$config{build_file_templates}}, @{$config{build_infos}}, @{$config{conf_files}}) -} + @echo "Detected changed: $?" + $(PERL) configdata.pm -r + @echo "**************************************************" + @echo "*** ***" + @echo "*** Please run the same make command again ***" + @echo "*** ***" + @echo "**************************************************" + @false + +reconfigure reconf: + $(PERL) configdata.pm -r + +{- + use File::Basename; + use File::Spec::Functions qw/:DEFAULT abs2rel rel2abs/; + + # Helper function to figure out dependencies on libraries + # It takes a list of library names and outputs a list of dependencies + sub compute_lib_depends { + if ($disabled{shared}) { + return map { lib($_) } @_; + } + + # Depending on shared libraries: + # On Windows POSIX layers, we depend on {libname}.dll.a + # On Unix platforms, we depend on {shlibname}.so + return map { $_ =~ /\.a$/ ? $`.$libext : shlib_simple($_) } @_; + } + + sub generatesrc { + my %args = @_; + my $generator = join(" ", @{$args{generator}}); + my $generator_incs = join("", map { " -I".$_ } @{$args{generator_incs}}); + my $incs = join("", map { " -I".$_ } @{$args{incs}}); + my $deps = join(" ", @{$args{generator_deps}}, @{$args{deps}}); + + if ($args{src} !~ /\.[sS]$/) { + if ($args{generator}->[0] =~ m|^.*\.in$|) { + my $dofile = abs2rel(rel2abs(catfile($config{sourcedir}, + "util", "dofile.pl")), + rel2abs($config{builddir})); + return <<"EOF"; +$args{src}: $args{generator}->[0] $deps + \$(PERL) "-I\$(BLDDIR)" -Mconfigdata "$dofile" \\ + "-o$target{build_file}" $generator > \$@ +EOF + } else { + return <<"EOF"; +$args{src}: $args{generator}->[0] $deps + \$(PERL)$generator_incs $generator > \$@ +EOF + } + } else { + if ($args{generator}->[0] =~ /\.pl$/) { + $generator = 'CC="$(CC)" $(PERL)'.$generator_incs.' '.$generator; + } elsif ($args{generator}->[0] =~ /\.m4$/) { + $generator = 'm4 -B 8192'.$generator_incs.' '.$generator.' >' + } elsif ($args{generator}->[0] =~ /\.S$/) { + $generator = undef; + } else { + die "Generator type for $args{src} unknown: $generator\n"; + } + + my $cppflags = { + lib => '$(LIB_CFLAGS) $(LIB_CPPFLAGS)', + dso => '$(DSO_CFLAGS) $(DSO_CPPFLAGS)', + bin => '$(BIN_CFLAGS) $(BIN_CPPFLAGS)' + } -> {$args{intent}}; + if (defined($generator)) { + return <<"EOF"; +$args{src}: $args{generator}->[0] $deps + $generator \$@ +EOF + } + return <<"EOF"; +$args{src}: $args{generator}->[0] $deps + \$(CC) $incs $cppflags -E $args{generator}->[0] | \\ + \$(PERL) -ne '/^#(line)?\\s*[0-9]+/ or print' > \$@ +EOF + } + } + + # Should one wonder about the end of the Perl snippet, it's because this + # second regexp eats up line endings as well, if the removed path is the + # last in the line. We may therefore need to put back a line ending. + sub src2obj { + my %args = @_; + (my $obj = $args{obj}) =~ s|\.o$||; + my @srcs = @{$args{srcs}}; + my $srcs = join(" ", @srcs); + my $deps = join(" ", @srcs, @{$args{deps}}); + my $incs = join("", map { " -I".$_ } @{$args{incs}}); + my $cmd; + my $cmdflags; + my $cmdcompile; + if (grep /\.rc$/, @srcs) { + $cmd = '$(RC)'; + $cmdflags = '$(RCFLAGS)'; + $cmdcompile = ''; + } elsif (grep /\.(cc|cpp)$/, @srcs) { + $cmd = '$(CXX)'; + $cmdcompile = ' -c'; + $cmdflags = { + lib => '$(LIB_CXXFLAGS) $(LIB_CPPFLAGS)', + dso => '$(DSO_CXXFLAGS) $(DSO_CPPFLAGS)', + bin => '$(BIN_CXXFLAGS) $(BIN_CPPFLAGS)' + } -> {$args{intent}}; + } else { + $cmd = '$(CC)'; + $cmdcompile = ' -c'; + $cmdflags = { + lib => '$(LIB_CFLAGS) $(LIB_CPPFLAGS)', + dso => '$(DSO_CFLAGS) $(DSO_CPPFLAGS)', + bin => '$(BIN_CFLAGS) $(BIN_CPPFLAGS)' + } -> {$args{intent}}; + } + my $recipe; + # extension-specific rules + if (grep /\.s$/, @srcs) { + $recipe .= <<"EOF"; +$obj$objext: $deps + $cmd $cmdflags -c -o \$\@ $srcs +EOF + } elsif (grep /\.S$/, @srcs) { + # Originally there was mutli-step rule with $(CC) -E file.S + # followed by $(CC) -c file.s. It compensated for one of + # legacy platform compiler's inability to handle .S files. + # The platform is long discontinued by vendor so there is + # hardly a point to drag it along... + $recipe .= <<"EOF"; +$obj$objext: $deps + $cmd $incs $cmdflags -c -o \$\@ $srcs +EOF + } elsif (defined $makedepprog && $makedepprog !~ /\/makedepend/ + && !grep /\.rc$/, @srcs) { + $recipe .= <<"EOF"; +$obj$objext: $deps + $cmd $incs $cmdflags -MMD -MF $obj$depext.tmp -MT \$\@ -c -o \$\@ $srcs + \@touch $obj$depext.tmp + \@if cmp $obj$depext.tmp $obj$depext > /dev/null 2> /dev/null; then \\ + rm -f $obj$depext.tmp; \\ + else \\ + mv $obj$depext.tmp $obj$depext; \\ + fi +EOF + } else { + $recipe .= <<"EOF"; +$obj$objext: $deps + $cmd $incs $cmdflags $cmdcompile -o \$\@ $srcs +EOF + if (defined $makedepprog && $makedepprog =~ /\/makedepend/) { + $recipe .= <<"EOF"; + \$(MAKEDEPEND) -f- -Y -- $incs $cmdflags -- $srcs 2>/dev/null \\ + > $obj$depext +EOF + } + } + return $recipe; + } + # We *know* this routine is only called when we've configure 'shared'. + sub libobj2shlib { + my %args = @_; + my $lib = $args{lib}; + my $shlib = $args{shlib}; + my $libd = dirname($lib); + my $libn = basename($lib); + (my $libname = $libn) =~ s/^lib//; + my @linkdirs = (); + foreach (@{args{deps}}) { + my $d = dirname($_); + push @linkdirs, $d unless grep { $d eq $_ } @linkdirs; + } + my $linkflags = join("", map { "-L$_ " } @linkdirs); + my $linklibs = join("", map { my $f = basename($_); + (my $l = $f) =~ s/^lib//; + " -l$l" } @{$args{deps}}); + my @objs = map { (my $x = $_) =~ s|\.o$||; "$x$objext" } + grep { $_ !~ m/\.(?:def|map)$/ } + @{$args{objs}}; + my @defs = grep { $_ =~ /\.(?:def|map)$/ } @{$args{objs}}; + my @deps = compute_lib_depends(@{$args{deps}}); + die "More than one exported symbol map" if scalar @defs > 1; + my $objs = join(" ", @objs); + my $deps = join(" ", @objs, @defs, @deps); + my $simple = shlib_simple($lib); + my $full = shlib($lib); + my $target = "$simple $full"; + my $shared_soname = ""; + $shared_soname .= ' '.$target{shared_sonameflag}.basename($full) + if defined $target{shared_sonameflag}; + my $shared_imp = ""; + $shared_imp .= ' '.$target{shared_impflag}.basename($simple) + if defined $target{shared_impflag}; + my $shared_def = join("", map { ' '.$target{shared_defflag}.$_ } @defs); + my $recipe = <<"EOF"; +$target: $deps + \$(CC) \$(LIB_CFLAGS) $linkflags\$(LIB_LDFLAGS)$shared_soname$shared_imp \\ + -o $full$shared_def $objs \\ + $linklibs \$(LIB_EX_LIBS) +EOF + if (windowsdll()) { + $recipe .= <<"EOF"; + rm -f apps/$shlib'\$(SHLIB_EXT)' + rm -f test/$shlib'\$(SHLIB_EXT)' + rm -f fuzz/$shlib'\$(SHLIB_EXT)' + cp -p $shlib'\$(SHLIB_EXT)' apps/ + cp -p $shlib'\$(SHLIB_EXT)' test/ + cp -p $shlib'\$(SHLIB_EXT)' fuzz/ +EOF + } elsif (sharedaix()) { + $recipe .= <<"EOF"; + rm -f $simple && \\ + \$(AR) r $simple $full +EOF + } else { + $recipe .= <<"EOF"; + if [ '$simple' != '$full' ]; then \\ + rm -f $simple; \\ + ln -s $full $simple; \\ + fi +EOF + } + } + sub obj2dso { + my %args = @_; + my $dso = $args{lib}; + my $dsod = dirname($dso); + my $dson = basename($dso); + my @linkdirs = (); + foreach (@{args{deps}}) { + my $d = dirname($_); + push @linkdirs, $d unless grep { $d eq $_ } @linkdirs; + } + my $linkflags = join("", map { "-L$_ " } @linkdirs); + my $linklibs = join("", map { my $f = basename($_); + (my $l = $f) =~ s/^lib//; + " -l$l" } @{$args{deps}}); + my @objs = map { (my $x = $_) =~ s|\.o$||; "$x$objext" } + grep { $_ !~ m/\.(?:def|map)$/ } + @{$args{objs}}; + my @deps = compute_lib_depends(@{$args{deps}}); + my $objs = join(" ", @objs); + my $deps = join(" ", @deps); + my $target = dso($dso); + return <<"EOF"; +$target: $objs $deps + \$(CC) \$(DSO_CFLAGS) $linkflags\$(DSO_LDFLAGS) \\ + -o $target $objs \\ + $linklibs \$(DSO_EX_LIBS) +EOF + } + sub obj2lib { + my %args = @_; + (my $lib = $args{lib}) =~ s/\.a$//; + my @objs = map { (my $x = $_) =~ s|\.o$|$objext|; $x } @{$args{objs}}; + my $objs = join(" ", @objs); + return <<"EOF"; +$lib$libext: $objs + \$(AR) \$(ARFLAGS) \$\@ \$\? + \$(RANLIB) \$\@ || echo Never mind. +EOF + } + sub obj2bin { + my %args = @_; + my $bin = $args{bin}; + my $bind = dirname($bin); + my $binn = basename($bin); + my $objs = join(" ", map { (my $x = $_) =~ s|\.o$||; "$x$objext" } + @{$args{objs}}); + my $deps = join(" ",compute_lib_depends(@{$args{deps}})); + my @linkdirs = (); + foreach (@{args{deps}}) { + next if $_ =~ /\.a$/; + my $d = dirname($_); + push @linkdirs, $d unless grep { $d eq $_ } @linkdirs; + } + my $linkflags = join("", map { "-L$_ " } @linkdirs); + my $linklibs = join("", map { if ($_ =~ s/\.a$//) { + " $_$libext"; + } else { + my $f = basename($_); + (my $l = $f) =~ s/^lib//; + " -l$l" + } + } @{$args{deps}}); + my $cmd = '$(CC)'; + my $cmdflags = '$(BIN_CFLAGS)'; + if (grep /_cc\.o$/, @{$args{objs}}) { + $cmd = '$(CXX)'; + $cmdflags = '$(BIN_CXXFLAGS)'; + } + return <<"EOF"; +$bin$exeext: $objs $deps + rm -f $bin$exeext + \$\${LDCMD:-$cmd} $cmdflags $linkflags\$(BIN_LDFLAGS) \\ + -o $bin$exeext $objs \\ + $linklibs \$(BIN_EX_LIBS) +EOF + } + sub in2script { + my %args = @_; + my $script = $args{script}; + my $sources = join(" ", @{$args{sources}}); + my $dofile = abs2rel(rel2abs(catfile($config{sourcedir}, + "util", "dofile.pl")), + rel2abs($config{builddir})); + return <<"EOF"; +$script: $sources + \$(PERL) "-I\$(BLDDIR)" -Mconfigdata "$dofile" \\ + "-o$target{build_file}" $sources > "$script" + chmod a+x $script +EOF + } + sub generatedir { + my %args = @_; + my $dir = $args{dir}; + my @deps = map { s|\.o$|$objext|; $_ } @{$args{deps}}; + my @actions = (); + my %extinfo = ( dso => $dsoext, + lib => $libext, + bin => $exeext ); + + # We already have a 'test' target, and the top directory is just plain + # silly + return if $dir eq "test" || $dir eq "."; + + foreach my $type (("dso", "lib", "bin", "script")) { + next unless defined($unified_info{dirinfo}->{$dir}->{products}->{$type}); + # For lib object files, we could update the library. However, it + # was decided that it's enough to build the directory local object + # files, so we don't need to add any actions, and the dependencies + # are already taken care of. + if ($type ne "lib") { + foreach my $prod (@{$unified_info{dirinfo}->{$dir}->{products}->{$type}}) { + if (dirname($prod) eq $dir) { + push @deps, $prod.$extinfo{$type}; + } else { + push @actions, "\t@ : No support to produce $type ".join(", ", @{$unified_info{dirinfo}->{$dir}->{products}->{$type}}); + } + } + } + } + + my $deps = join(" ", @deps); + my $actions = join("\n", "", @actions); + return <<"EOF"; +$dir $dir/: $deps$actions +EOF + } + "" # Important! This becomes part of the template result. +-} diff --git a/trunk/3rdparty/openssl-1.1-fit/Configurations/unix-checker.pm b/trunk/3rdparty/openssl-1.1-fit/Configurations/unix-checker.pm new file mode 100644 index 000000000..b39b0eb7c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/Configurations/unix-checker.pm @@ -0,0 +1,22 @@ +#! /usr/bin/perl + +use Config; + +# Check that the perl implementation file modules generate paths that +# we expect for the platform +use File::Spec::Functions qw(:DEFAULT rel2abs); + +if (rel2abs('.') !~ m|/|) { + die <[$#$build_scheme]; # last element + my $win_installenv = + $install_flavour eq "VC-WOW" ? "ProgramFiles(x86)" + : "ProgramW6432"; + my $win_commonenv = + $install_flavour eq "VC-WOW" ? "CommonProgramFiles(x86)" + : "CommonProgramW6432"; + our $win_installroot = + defined($ENV{$win_installenv}) ? $win_installenv : 'ProgramFiles'; + our $win_commonroot = + defined($ENV{$win_commonenv}) ? $win_commonenv : 'CommonProgramFiles'; + + # expand variables early + $win_installroot = $ENV{$win_installroot}; + $win_commonroot = $ENV{$win_commonroot}; + + sub shlib { + my $lib = shift; + return () if $disabled{shared} || $lib =~ /\.a$/; + return () unless defined $unified_info{sharednames}->{$lib}; + return $unified_info{sharednames}->{$lib} . $shlibext; + } + + sub lib { + (my $lib = shift) =~ s/\.a$//; + $lib .= '_static' + if (defined $unified_info{sharednames}->{$lib}); + return $lib . $libext; + } + + sub shlib_import { + my $lib = shift; + return () if $disabled{shared} || $lib =~ /\.a$/; + return $lib . $shlibextimport; + } + + sub dso { + my $dso = shift; + + return $dso . $dsoext; + } + # This makes sure things get built in the order they need + # to. You're welcome. + sub dependmagic { + my $target = shift; + + return "$target: build_generated\n\t\$(MAKE) /\$(MAKEFLAGS) depend && \$(MAKE) /\$(MAKEFLAGS) _$target\n_$target"; + } + ''; +-} + +PLATFORM={- $config{target} -} +SRCDIR={- $config{sourcedir} -} +BLDDIR={- $config{builddir} -} + +VERSION={- $config{version} -} +MAJOR={- $config{major} -} +MINOR={- $config{minor} -} + +SHLIB_VERSION_NUMBER={- $config{shlib_version_number} -} + +LIBS={- join(" ", map { ( shlib_import($_), lib($_) ) } @{$unified_info{libraries}}) -} +SHLIBS={- join(" ", map { shlib($_) } @{$unified_info{libraries}}) -} +SHLIBPDBS={- join(" ", map { local $shlibext = ".pdb"; shlib($_) } @{$unified_info{libraries}}) -} +ENGINES={- join(" ", map { dso($_) } @{$unified_info{engines}}) -} +ENGINEPDBS={- join(" ", map { local $dsoext = ".pdb"; dso($_) } @{$unified_info{engines}}) -} +PROGRAMS={- our @PROGRAMS = map { $_.$exeext } @{$unified_info{programs}}; join(" ", @PROGRAMS) -} +PROGRAMPDBS={- join(" ", map { $_.".pdb" } @{$unified_info{programs}}) -} +SCRIPTS={- join(" ", @{$unified_info{scripts}}) -} +{- output_off() if $disabled{makedepend}; "" -} +DEPS={- join(" ", map { (my $x = $_) =~ s|\.o$|$depext|; $x; } + grep { $unified_info{sources}->{$_}->[0] =~ /\.c$/ } + keys %{$unified_info{sources}}); -} +{- output_on() if $disabled{makedepend}; "" -} +GENERATED_MANDATORY={- join(" ", @{$unified_info{depends}->{""}} ) -} +GENERATED={- # common0.tmpl provides @generated + join(" ", map { (my $x = $_) =~ s|\.[sS]$|.asm|; $x } + @generated) -} + +INSTALL_LIBS={- join(" ", map { quotify1(shlib_import($_) or lib($_)) } @{$unified_info{install}->{libraries}}) -} +INSTALL_SHLIBS={- join(" ", map { quotify_l(shlib($_)) } @{$unified_info{install}->{libraries}}) -} +INSTALL_SHLIBPDBS={- join(" ", map { local $shlibext = ".pdb"; quotify_l(shlib($_)) } @{$unified_info{install}->{libraries}}) -} +INSTALL_ENGINES={- join(" ", map { quotify1(dso($_)) } @{$unified_info{install}->{engines}}) -} +INSTALL_ENGINEPDBS={- join(" ", map { local $dsoext = ".pdb"; quotify1(dso($_)) } @{$unified_info{install}->{engines}}) -} +INSTALL_PROGRAMS={- join(" ", map { quotify1($_.$exeext) } grep { !m|^test\\| } @{$unified_info{install}->{programs}}) -} +INSTALL_PROGRAMPDBS={- join(" ", map { quotify1($_.".pdb") } grep { !m|^test\\| } @{$unified_info{install}->{programs}}) -} +{- output_off() if $disabled{apps}; "" -} +BIN_SCRIPTS="$(BLDDIR)\tools\c_rehash.pl" +MISC_SCRIPTS="$(BLDDIR)\apps\CA.pl" "$(BLDDIR)\apps\tsget.pl" +{- output_on() if $disabled{apps}; "" -} + +APPS_OPENSSL={- use File::Spec::Functions; + "\"".catfile("apps","openssl")."\"" -} + +# Do not edit these manually. Use Configure with --prefix or --openssldir +# to change this! Short explanation in the top comment in Configure +INSTALLTOP_dev={- # $prefix is used in the OPENSSLDIR perl snippet + # + use File::Spec::Functions qw(:DEFAULT splitpath); + our $prefix = canonpath($config{prefix} + || "$win_installroot\\OpenSSL"); + our ($prefix_dev, $prefix_dir, $prefix_file) = + splitpath($prefix, 1); + $prefix_dev -} +INSTALLTOP_dir={- canonpath($prefix_dir) -} +OPENSSLDIR_dev={- # + # The logic here is that if no --openssldir was given, + # OPENSSLDIR will get the value "$win_commonroot\\SSL". + # If --openssldir was given and the value is an absolute + # path, OPENSSLDIR will get its value without change. + # If the value from --openssldir is a relative path, + # OPENSSLDIR will get $prefix with the --openssldir + # value appended as a subdirectory. + # + use File::Spec::Functions qw(:DEFAULT splitpath); + our $openssldir = + $config{openssldir} ? + (file_name_is_absolute($config{openssldir}) ? + canonpath($config{openssldir}) + : catdir($prefix, $config{openssldir})) + : canonpath("$win_commonroot\\SSL"); + our ($openssldir_dev, $openssldir_dir, $openssldir_file) = + splitpath($openssldir, 1); + $openssldir_dev -} +OPENSSLDIR_dir={- canonpath($openssldir_dir) -} +LIBDIR={- our $libdir = $config{libdir} || "lib"; + file_name_is_absolute($libdir) ? "" : $libdir -} +ENGINESDIR_dev={- use File::Spec::Functions qw(:DEFAULT splitpath); + our $enginesdir = catdir($prefix,$libdir,"engines-$sover_dirname"); + our ($enginesdir_dev, $enginesdir_dir, $enginesdir_file) = + splitpath($enginesdir, 1); + $enginesdir_dev -} +ENGINESDIR_dir={- canonpath($enginesdir_dir) -} +!IF "$(DESTDIR)" != "" +INSTALLTOP=$(DESTDIR)$(INSTALLTOP_dir) +OPENSSLDIR=$(DESTDIR)$(OPENSSLDIR_dir) +ENGINESDIR=$(DESTDIR)$(ENGINESDIR_dir) +!ELSE +INSTALLTOP=$(INSTALLTOP_dev)$(INSTALLTOP_dir) +OPENSSLDIR=$(OPENSSLDIR_dev)$(OPENSSLDIR_dir) +ENGINESDIR=$(ENGINESDIR_dev)$(ENGINESDIR_dir) +!ENDIF + +# $(libdir) is chosen to be compatible with the GNU coding standards +libdir={- file_name_is_absolute($libdir) + ? $libdir : '$(INSTALLTOP)\$(LIBDIR)' -} + +##### User defined commands and flags ################################ + +CC={- $config{CC} -} +CPP={- $config{CPP} -} +CPPFLAGS={- our $cppflags1 = join(" ", + (map { "-D".$_} @{$config{CPPDEFINES}}), + (map { " /I ".$_} @{$config{CPPINCLUDES}}), + @{$config{CPPFLAGS}}) -} +CFLAGS={- join(' ', @{$config{CFLAGS}}) -} +LD={- $config{LD} -} +LDFLAGS={- join(' ', @{$config{LDFLAGS}}) -} +EX_LIBS={- join(' ', @{$config{LDLIBS}}) -} + +PERL={- $config{PERL} -} + +AR={- $config{AR} -} +ARFLAGS= {- join(' ', @{$config{ARFLAGS}}) -} + +MT={- $config{MT} -} +MTFLAGS= {- join(' ', @{$config{MTFLAGS}}) -} + +AS={- $config{AS} -} +ASFLAGS={- join(' ', @{$config{ASFLAGS}}) -} + +RC={- $config{RC} -} + +ECHO="$(PERL)" "$(SRCDIR)\util\echo.pl" + +##### Special command flags ########################################## + +COUTFLAG={- $target{coutflag} -}$(OSSL_EMPTY) +LDOUTFLAG={- $target{ldoutflag} -}$(OSSL_EMPTY) +AROUTFLAG={- $target{aroutflag} -}$(OSSL_EMPTY) +MTINFLAG={- $target{mtinflag} -}$(OSSL_EMPTY) +MTOUTFLAG={- $target{mtoutflag} -}$(OSSL_EMPTY) +ASOUTFLAG={- $target{asoutflag} -}$(OSSL_EMPTY) +RCOUTFLAG={- $target{rcoutflag} -}$(OSSL_EMPTY) + +##### Project flags ################################################## + +# Variables starting with CNF_ are common variables for all product types + +CNF_ASFLAGS={- join(' ', $target{asflags} || (), + @{$config{asflags}}) -} +CNF_CPPFLAGS={- our $cppfags2 = + join(' ', $target{cppflags} || (), + (map { '-D'.quotify1($_) } @{$target{defines}}, + @{$config{defines}}), + (map { '-I'.quotify1($_) } @{$target{includes}}, + @{$config{includes}}), + @{$config{cppflags}}) -} +CNF_CFLAGS={- join(' ', $target{cflags} || (), + @{$config{cflags}}) -} +CNF_CXXFLAGS={- join(' ', $target{cxxflags} || (), + @{$config{cxxflags}}) -} +CNF_LDFLAGS={- join(' ', $target{lflags} || (), + @{$config{lflags}}) -} +CNF_EX_LIBS={- join(' ', $target{ex_libs} || (), + @{$config{ex_libs}}) -} + +# Variables starting with LIB_ are used to build library object files +# and shared libraries. +# Variables starting with DSO_ are used to build DSOs and their object files. +# Variables starting with BIN_ are used to build programs and their object +# files. + +LIB_ASFLAGS={- join(' ', $target{lib_asflags} || (), + @{$config{lib_asflags}}, + '$(CNF_ASFLAGS)', '$(ASFLAGS)') -} +LIB_CPPFLAGS={- our $lib_cppflags = + join(' ', $target{lib_cppflags} || (), + $target{shared_cppflag} || (), + (map { '-D'.quotify1($_) } + @{$target{lib_defines}}, + @{$target{shared_defines}}, + @{$config{lib_defines}}, + @{$config{shared_defines}}), + (map { '-I'.quotify1($_) } + @{$target{lib_includes}}, + @{$target{shared_includes}}, + @{$config{lib_includes}}, + @{$config{shared_includes}}), + @{$config{lib_cppflags}}, + @{$config{shared_cppflag}}); + join(' ', $lib_cppflags, + (map { '-D'.quotify1($_) } + "OPENSSLDIR=\"$openssldir\"", + "ENGINESDIR=\"$enginesdir\""), + '$(CNF_CPPFLAGS)', '$(CPPFLAGS)') -} +LIB_CFLAGS={- join(' ', $target{lib_cflags} || (), + $target{shared_cflag} || (), + @{$config{lib_cflags}}, + @{$config{shared_cflag}}, + '$(CNF_CFLAGS)', '$(CFLAGS)') -} +LIB_LDFLAGS={- join(' ', $target{shared_ldflag} || (), + $config{shared_ldflag} || (), + '$(CNF_LDFLAGS)', '$(LDFLAGS)') -} +LIB_EX_LIBS=$(CNF_EX_LIBS) $(EX_LIBS) +DSO_ASFLAGS={- join(' ', $target{dso_asflags} || (), + $target{module_asflags} || (), + @{$config{dso_asflags}}, + @{$config{module_asflags}}, + '$(CNF_ASFLAGS)', '$(ASFLAGS)') -} +DSO_CPPFLAGS={- join(' ', $target{dso_cppflags} || (), + $target{module_cppflags} || (), + @{$config{dso_cppflags}}, + @{$config{module_cppflags}}, + '$(CNF_CPPFLAGS)', '$(CPPFLAGS)') -} +DSO_CFLAGS={- join(' ', $target{dso_cflags} || (), + $target{module_cflags} || (), + @{$config{dso_cflags}}, + @{$config{module_cflags}}, + '$(CNF_CFLAGS)', '$(CFLAGS)') -} +DSO_LDFLAGS={- join(' ', $target{dso_lflags} || (), + $target{module_ldflags} || (), + @{$config{dso_lflags}}, + @{$config{module_ldflags}}, + '$(CNF_LDFLAGS)', '$(LDFLAGS)') -} +DSO_EX_LIBS=$(CNF_EX_LIBS) $(EX_LIBS) +BIN_ASFLAGS={- join(' ', $target{bin_asflags} || (), + @{$config{bin_asflags}}, + '$(CNF_ASFLAGS)', '$(ASFLAGS)') -} +BIN_CPPFLAGS={- join(' ', $target{bin_cppflags} || (), + @{$config{bin_cppflags}}, + '$(CNF_CPPFLAGS)', '$(CPPFLAGS)') -} +BIN_CFLAGS={- join(' ', $target{bin_cflags} || (), + @{$config{bin_cflags}}, + '$(CNF_CFLAGS)', '$(CFLAGS)') -} +BIN_LDFLAGS={- join(' ', $target{bin_lflags} || (), + @{$config{bin_lflags}}, + '$(CNF_LDFLAGS)', '$(LDFLAGS)') -} +BIN_EX_LIBS=$(CNF_EX_LIBS) $(EX_LIBS) + +# CPPFLAGS_Q is used for one thing only: to build up buildinf.h +CPPFLAGS_Q={- $cppflags1 =~ s|([\\"])|\\$1|g; + $cppflags2 =~ s|([\\"])|\\$1|g; + join(' ', $lib_cppflags || (), $cppflags2 || (), + $cppflags1 || ()) -} + +PERLASM_SCHEME= {- $target{perlasm_scheme} -} + +PROCESSOR= {- $config{processor} -} + +# The main targets ################################################### + +{- dependmagic('all'); -}: build_libs_nodep build_engines_nodep build_programs_nodep +{- dependmagic('build_libs'); -}: build_libs_nodep +{- dependmagic('build_engines'); -}: build_engines_nodep +{- dependmagic('build_programs'); -}: build_programs_nodep + +build_generated: $(GENERATED_MANDATORY) +build_libs_nodep: $(LIBS) {- join(" ",map { shlib_import($_) } @{$unified_info{libraries}}) -} +build_engines_nodep: $(ENGINES) +build_programs_nodep: $(PROGRAMS) $(SCRIPTS) + +# Kept around for backward compatibility +build_apps build_tests: build_programs + +# Convenience target to prebuild all generated files, not just the mandatory +# ones +build_all_generated: $(GENERATED_MANDATORY) $(GENERATED) + @{- output_off() if $disabled{makedepend}; "" -} + @$(ECHO) "Warning: consider configuring with no-makedepend, because if" + @$(ECHO) " target system doesn't have $(PERL)," + @$(ECHO) " then make will fail..." + @{- output_on() if $disabled{makedepend}; "" -} + +test: tests +{- dependmagic('tests'); -}: build_programs_nodep build_engines_nodep + @{- output_off() if $disabled{tests}; "" -} + -mkdir $(BLDDIR)\test\test-runs + set SRCTOP=$(SRCDIR) + set BLDTOP=$(BLDDIR) + set RESULT_D=$(BLDDIR)\test\test-runs + set PERL=$(PERL) + set OPENSSL_ENGINES=$(MAKEDIR)\engines + set OPENSSL_DEBUG_MEMORY=on + "$(PERL)" "$(SRCDIR)\test\run_tests.pl" $(TESTS) + @{- if ($disabled{tests}) { output_on(); } else { output_off(); } "" -} + @$(ECHO) "Tests are not supported with your chosen Configure options" + @{- output_on() if !$disabled{tests}; "" -} + +list-tests: + @{- output_off() if $disabled{tests}; "" -} + @set SRCTOP=$(SRCDIR) + @"$(PERL)" "$(SRCDIR)\test\run_tests.pl" list + @{- if ($disabled{tests}) { output_on(); } else { output_off(); } "" -} + @$(ECHO) "Tests are not supported with your chosen Configure options" + @{- output_on() if !$disabled{tests}; "" -} + +install: install_sw install_ssldirs install_docs + +uninstall: uninstall_docs uninstall_sw + +libclean: + "$(PERL)" -e "map { m/(.*)\.dll$$/; unlink glob """{.,apps,test,fuzz}/$$1.*"""; } @ARGV" $(SHLIBS) + -del /Q /F $(LIBS) libcrypto.* libssl.* ossl_static.pdb + +clean: libclean + {- join("\n\t", map { "-del /Q /F $_" } @PROGRAMS) -} + -del /Q /F $(ENGINES) + -del /Q /F $(SCRIPTS) + -del /Q /F $(GENERATED_MANDATORY) + -del /Q /F $(GENERATED) + -del /Q /S /F *.d *.obj *.pdb *.ilk *.manifest + -del /Q /S /F engines\*.lib engines\*.exp + -del /Q /S /F apps\*.lib apps\*.rc apps\*.res apps\*.exp + -del /Q /S /F test\*.exp + -rmdir /Q /S test\test-runs + +distclean: clean + -del /Q /F configdata.pm + -del /Q /F makefile + +depend: + @ {- output_off() if $disabled{makedepend}; "" -} + @ "$(PERL)" "$(SRCDIR)\util\add-depends.pl" "VC" + @ {- output_on() if $disabled{makedepend}; "" -} + +# Install helper targets ############################################# + +install_sw: install_dev install_engines install_runtime + +uninstall_sw: uninstall_runtime uninstall_engines uninstall_dev + +install_docs: install_html_docs + +uninstall_docs: uninstall_html_docs + +install_ssldirs: + @"$(PERL)" "$(SRCDIR)\util\mkdir-p.pl" "$(OPENSSLDIR)\certs" + @"$(PERL)" "$(SRCDIR)\util\mkdir-p.pl" "$(OPENSSLDIR)\private" + @"$(PERL)" "$(SRCDIR)\util\mkdir-p.pl" "$(OPENSSLDIR)\misc" + @"$(PERL)" "$(SRCDIR)\util\copy.pl" "$(SRCDIR)\apps\openssl.cnf" \ + "$(OPENSSLDIR)\openssl.cnf.dist" + @IF NOT EXIST "$(OPENSSLDIR)\openssl.cnf" \ + "$(PERL)" "$(SRCDIR)\util\copy.pl" "$(SRCDIR)\apps\openssl.cnf" \ + "$(OPENSSLDIR)\openssl.cnf" + @"$(PERL)" "$(SRCDIR)\util\copy.pl" $(MISC_SCRIPTS) \ + "$(OPENSSLDIR)\misc" + @"$(PERL)" "$(SRCDIR)\util\copy.pl" "$(SRCDIR)\apps\ct_log_list.cnf" \ + "$(OPENSSLDIR)\ct_log_list.cnf.dist" + @IF NOT EXIST "$(OPENSSLDIR)\ct_log_list.cnf" \ + "$(PERL)" "$(SRCDIR)\util\copy.pl" "$(SRCDIR)\apps\ct_log_list.cnf" \ + "$(OPENSSLDIR)\ct_log_list.cnf" + +install_dev: install_runtime_libs + @if "$(INSTALLTOP)"=="" ( $(ECHO) "INSTALLTOP should not be empty" & exit 1 ) + @$(ECHO) "*** Installing development files" + @"$(PERL)" "$(SRCDIR)\util\mkdir-p.pl" "$(INSTALLTOP)\include\openssl" + @{- output_off() unless grep { $_ eq "OPENSSL_USE_APPLINK" } (@{$target{defines}}, @{$config{defines}}); "" -} + @"$(PERL)" "$(SRCDIR)\util\copy.pl" "$(SRCDIR)\ms\applink.c" \ + "$(INSTALLTOP)\include\openssl" + @{- output_on() unless grep { $_ eq "OPENSSL_USE_APPLINK" } (@{$target{defines}}, @{$config{defines}}); "" -} + @"$(PERL)" "$(SRCDIR)\util\copy.pl" "-exclude_re=/__DECC_" \ + "$(SRCDIR)\include\openssl\*.h" \ + "$(INSTALLTOP)\include\openssl" + @"$(PERL)" "$(SRCDIR)\util\copy.pl" "$(BLDDIR)\include\openssl\*.h" \ + "$(INSTALLTOP)\include\openssl" + @"$(PERL)" "$(SRCDIR)\util\mkdir-p.pl" "$(libdir)" + @"$(PERL)" "$(SRCDIR)\util\copy.pl" $(INSTALL_LIBS) "$(libdir)" + @if "$(SHLIBS)"=="" \ + "$(PERL)" "$(SRCDIR)\util\copy.pl" ossl_static.pdb "$(libdir)" + +uninstall_dev: + +install_engines: install_runtime_libs build_engines + @if "$(INSTALLTOP)"=="" ( $(ECHO) "INSTALLTOP should not be empty" & exit 1 ) + @$(ECHO) "*** Installing engines" + @"$(PERL)" "$(SRCDIR)\util\mkdir-p.pl" "$(ENGINESDIR)" + @if not "$(ENGINES)"=="" \ + "$(PERL)" "$(SRCDIR)\util\copy.pl" $(INSTALL_ENGINES) "$(ENGINESDIR)" + @if not "$(ENGINES)"=="" \ + "$(PERL)" "$(SRCDIR)\util\copy.pl" $(INSTALL_ENGINEPDBS) "$(ENGINESDIR)" + +uninstall_engines: + +install_runtime: install_programs + +install_runtime_libs: build_libs + @if "$(INSTALLTOP)"=="" ( $(ECHO) "INSTALLTOP should not be empty" & exit 1 ) + @$(ECHO) "*** Installing runtime libraries" + @"$(PERL)" "$(SRCDIR)\util\mkdir-p.pl" "$(INSTALLTOP)\bin" + @if not "$(SHLIBS)"=="" \ + "$(PERL)" "$(SRCDIR)\util\copy.pl" $(INSTALL_SHLIBS) "$(INSTALLTOP)\bin" + @if not "$(SHLIBS)"=="" \ + "$(PERL)" "$(SRCDIR)\util\copy.pl" $(INSTALL_SHLIBPDBS) \ + "$(INSTALLTOP)\bin" + +install_programs: install_runtime_libs build_programs + @if "$(INSTALLTOP)"=="" ( $(ECHO) "INSTALLTOP should not be empty" & exit 1 ) + @$(ECHO) "*** Installing runtime programs" + @"$(PERL)" "$(SRCDIR)\util\mkdir-p.pl" "$(INSTALLTOP)\bin" + @"$(PERL)" "$(SRCDIR)\util\copy.pl" $(INSTALL_PROGRAMS) \ + "$(INSTALLTOP)\bin" + @"$(PERL)" "$(SRCDIR)\util\copy.pl" $(INSTALL_PROGRAMPDBS) \ + "$(INSTALLTOP)\bin" + @"$(PERL)" "$(SRCDIR)\util\copy.pl" $(BIN_SCRIPTS) \ + "$(INSTALLTOP)\bin" + +uninstall_runtime: + +install_html_docs: + "$(PERL)" "$(SRCDIR)\util\process_docs.pl" \ + "--destdir=$(INSTALLTOP)\html" --type=html + +uninstall_html_docs: + +# Building targets ################################################### + +configdata.pm: "$(SRCDIR)\Configure" {- join(" ", map { '"'.$_.'"' } @{$config{build_file_templates}}, @{$config{build_infos}}, @{$config{conf_files}}) -} + @$(ECHO) "Detected changed: $?" + "$(PERL)" configdata.pm -r + @$(ECHO) "**************************************************" + @$(ECHO) "*** ***" + @$(ECHO) "*** Please run the same make command again ***" + @$(ECHO) "*** ***" + @$(ECHO) "**************************************************" + @exit 1 + +reconfigure reconf: + "$(PERL)" configdata.pm -r + +{- + use File::Basename; + use File::Spec::Functions qw/:DEFAULT abs2rel rel2abs/; + + # Helper function to figure out dependencies on libraries + # It takes a list of library names and outputs a list of dependencies + sub compute_lib_depends { + if ($disabled{shared}) { + return map { lib($_) } @_; + } + return map { shlib_import($_) or lib($_) } @_; + } + + sub generatesrc { + my %args = @_; + (my $target = $args{src}) =~ s/\.[sS]$/.asm/; + my ($gen0, @gens) = @{$args{generator}}; + my $generator = '"'.$gen0.'"'.join('', map { " $_" } @gens); + my $generator_incs = join("", map { " -I \"$_\"" } @{$args{generator_incs}}); + my $incs = join("", map { " /I \"$_\"" } @{$args{incs}}); + my $deps = @{$args{deps}} ? + '"'.join('" "', @{$args{generator_deps}}, @{$args{deps}}).'"' : ''; + + if ($target !~ /\.asm$/) { + if ($args{generator}->[0] =~ m|^.*\.in$|) { + my $dofile = abs2rel(rel2abs(catfile($config{sourcedir}, + "util", "dofile.pl")), + rel2abs($config{builddir})); + return <<"EOF"; +$target: "$args{generator}->[0]" $deps + "\$(PERL)" "-I\$(BLDDIR)" -Mconfigdata "$dofile" \\ + "-o$target{build_file}" $generator > \$@ +EOF + } else { + return <<"EOF"; +$target: "$args{generator}->[0]" $deps + "\$(PERL)"$generator_incs $generator > \$@ +EOF + } + } else { + if ($args{generator}->[0] =~ /\.pl$/) { + $generator = '"$(PERL)"'.$generator_incs.' '.$generator; + } elsif ($args{generator}->[0] =~ /\.S$/) { + $generator = undef; + } else { + die "Generator type for $src unknown: $generator\n"; + } + + my $cppflags = $incs; + $cppflags .= { + lib => ' $(LIB_CFLAGS) $(LIB_CPPFLAGS)', + dso => ' $(DSO_CFLAGS) $(DSO_CPPFLAGS)', + bin => ' $(BIN_CFLAGS) $(BIN_CPPFLAGS)' + } -> {$args{intent}}; + if (defined($generator)) { + # If the target is named foo.S in build.info, we want to + # end up generating foo.s in two steps. + if ($args{src} =~ /\.S$/) { + return <<"EOF"; +$target: "$args{generator}->[0]" $deps + set ASM=\$(AS) + $generator \$@.S + \$(CPP) $cppflags \$@.S > \$@.i && move /Y \$@.i \$@ + del /Q \$@.S +EOF + } + # Otherwise.... + return <<"EOF"; +$target: "$args{generator}->[0]" $deps + set ASM=\$(AS) + $generator \$@ +EOF + } + return <<"EOF"; +$target: "$args{generator}->[0]" $deps + \$(CPP) $incs $cppflags "$args{generator}->[0]" > \$@.i && move /Y \$@.i \$@ +EOF + } + } + + sub src2obj { + my %args = @_; + my @srcs = map { (my $x = $_) =~ s/\.s$/.asm/; $x + } ( @{$args{srcs}} ); + my $srcs = '"'.join('" "', @srcs).'"'; + my $deps = '"'.join('" "', @srcs, @{$args{deps}}).'"'; + my $incs = join("", map { ' /I "'.$_.'"' } @{$args{incs}}); + my $cflags = { lib => ' $(LIB_CFLAGS)', + dso => ' $(DSO_CFLAGS)', + bin => ' $(BIN_CFLAGS)' } -> {$args{intent}}; + $cflags .= $incs; + $cflags .= { lib => ' $(LIB_CPPFLAGS)', + dso => ' $(DSO_CPPFLAGS)', + bin => ' $(BIN_CPPFLAGS)' } -> {$args{intent}}; + my $asflags = { lib => ' $(LIB_ASFLAGS)', + dso => ' $(DSO_ASFLAGS)', + bin => ' $(BIN_ASFLAGS)' } -> {$args{intent}}; + my $makedepprog = $config{makedepprog}; + if ($srcs[0] =~ /\.rc$/) { + return <<"EOF"; +$args{obj}: $deps + \$(RC) \$(RCOUTFLAG)\$\@ $srcs +EOF + } + (my $obj = $args{obj}) =~ s|\.o$||; + if ($srcs[0] =~ /\.asm$/) { + return <<"EOF"; +$obj$objext: $deps + \$(AS) $asflags \$(ASOUTFLAG)\$\@ $srcs +EOF + } elsif ($srcs[0] =~ /.S$/) { + return <<"EOF"; +$obj$objext: $deps + \$(CC) /EP /D__ASSEMBLER__ $cflags $srcs > \$@.asm && \$(AS) $asflags \$(ASOUTFLAG)\$\@ \$@.asm +EOF + } + my $recipe = <<"EOF"; +$obj$objext: $deps + \$(CC) $cflags -c \$(COUTFLAG)\$\@ $srcs +EOF + $recipe .= <<"EOF" unless $disabled{makedepend}; + \$(CC) $cflags /Zs /showIncludes $srcs 2>&1 > $obj$depext +EOF + return $recipe; + } + + # We *know* this routine is only called when we've configure 'shared'. + # Also, note that even though the import library built here looks like + # a static library, it really isn't. + sub libobj2shlib { + my %args = @_; + my $lib = $args{lib}; + my @objs = map { (my $x = $_) =~ s|\.o$|$objext|; $x } + grep { $_ =~ m/\.(?:o|res)$/ } + @{$args{objs}}; + my @defs = grep { $_ =~ /\.def$/ } @{$args{objs}}; + my @deps = compute_lib_depends(@{$args{deps}}); + die "More than one exported symbols list" if scalar @defs > 1; + my $linklibs = join("", map { "$_\n" } @deps); + my $objs = join("\n", @objs); + my $deps = join(" ", @objs, @defs, @deps); + my $import = shlib_import($lib); + my $dll = shlib($lib); + my $shared_def = join("", map { " /def:$_" } @defs); + return <<"EOF" +# The import library may look like a static library, but it is not. +# We MUST make the import library depend on the DLL, in case someone +# mistakenly removes the latter. +$import: $dll +$dll: $deps + IF EXIST $full.manifest DEL /F /Q $full.manifest + IF EXIST \$@ DEL /F /Q \$@ + \$(LD) \$(LDFLAGS) \$(LIB_LDFLAGS) \\ + /implib:$import \$(LDOUTFLAG)$dll$shared_def @<< || (DEL /Q \$(\@B).* $import && EXIT 1) +$objs +$linklibs\$(LIB_EX_LIBS) +<< + IF EXIST $dll.manifest \\ + \$(MT) \$(MTFLAGS) \$(MTINFLAG)$dll.manifest \$(MTOUTFLAG)$dll + IF EXIST apps\\$dll DEL /Q /F apps\\$dll + IF EXIST test\\$dll DEL /Q /F test\\$dll + IF EXIST fuzz\\$dll DEL /Q /F fuzz\\$dll + COPY $dll apps + COPY $dll test + COPY $dll fuzz +EOF + } + sub obj2dso { + my %args = @_; + my $dso = $args{lib}; + my $dso_n = basename($dso); + my @objs = map { (my $x = $_) =~ s|\.o$|$objext|; $x } @{$args{objs}}; + my @deps = compute_lib_depends(@{$args{deps}}); + my $objs = join("\n", @objs); + my $linklibs = join("", map { "$_\n" } @deps); + my $deps = join(" ", @objs, @deps); + return <<"EOF"; +$dso$dsoext: $deps + IF EXIST $dso$dsoext.manifest DEL /F /Q $dso$dsoext.manifest + \$(LD) \$(LDFLAGS) \$(DSO_LDFLAGS) \$(LDOUTFLAG)$dso$dsoext /def:<< @<< +LIBRARY $dso_n +EXPORTS + bind_engine @1 + v_check @2 +<< +$objs +$linklibs \$(DSO_EX_LIBS) +<< + IF EXIST $dso$dsoext.manifest \\ + \$(MT) \$(MTFLAGS) \$(MTINFLAG)$dso$dsoext.manifest \$(MTOUTFLAG)$dso$dsoext +EOF + } + sub obj2lib { + my %args = @_; + my $lib = lib($args{lib}); + my @objs = map { (my $x = $_) =~ s|\.o$|$objext|; $x } @{$args{objs}}; + my $objs = join("\n", @objs); + my $deps = join(" ", @objs); + return <<"EOF"; +$lib: $deps + \$(AR) \$(ARFLAGS) \$(AROUTFLAG)$lib @<< +$objs +<< +EOF + } + sub obj2bin { + my %args = @_; + my $bin = $args{bin}; + my @objs = map { (my $x = $_) =~ s|\.o$|$objext|; $x } @{$args{objs}}; + my @deps = compute_lib_depends(@{$args{deps}}); + my $objs = join("\n", @objs); + my $linklibs = join("", map { "$_\n" } @deps); + my $deps = join(" ", @objs, @deps); + return <<"EOF"; +$bin$exeext: $deps + IF EXIST $bin$exeext.manifest DEL /F /Q $bin$exeext.manifest + \$(LD) \$(LDFLAGS) \$(BIN_LDFLAGS) \$(LDOUTFLAG)$bin$exeext @<< +$objs +setargv.obj +$linklibs\$(BIN_EX_LIBS) +<< + IF EXIST $bin$exeext.manifest \\ + \$(MT) \$(MTFLAGS) \$(MTINFLAG)$bin$exeext.manifest \$(MTOUTFLAG)$bin$exeext +EOF + } + sub in2script { + my %args = @_; + my $script = $args{script}; + my $sources = '"'.join('" "', @{$args{sources}}).'"'; + my $dofile = abs2rel(rel2abs(catfile($config{sourcedir}, + "util", "dofile.pl")), + rel2abs($config{builddir})); + return <<"EOF"; +$script: $sources + "\$(PERL)" "-I\$(BLDDIR)" -Mconfigdata "$dofile" \\ + "-o$target{build_file}" $sources > "$script" +EOF + } + sub generatedir { + my %args = @_; + my $dir = $args{dir}; + my @deps = map { s|\.o$|$objext|; $_ } @{$args{deps}}; + my @actions = (); + my %extinfo = ( dso => $dsoext, + lib => $libext, + bin => $exeext ); + + # We already have a 'test' target, and the top directory is just plain + # silly + return if $dir eq "test" || $dir eq "."; + + foreach my $type (("dso", "lib", "bin", "script")) { + next unless defined($unified_info{dirinfo}->{$dir}->{products}->{$type}); + # For lib object files, we could update the library. However, + # LIB on Windows doesn't work that way, so we won't create any + # actions for it, and the dependencies are already taken care of. + if ($type ne "lib") { + foreach my $prod (@{$unified_info{dirinfo}->{$dir}->{products}->{$type}}) { + if (dirname($prod) eq $dir) { + push @deps, $prod.$extinfo{$type}; + } + } + } + } + + my $deps = join(" ", @deps); + my $actions = join("\n", "", @actions); + return <<"EOF"; +$dir $dir\\ : $deps$actions +EOF + } + "" # Important! This becomes part of the template result. +-} diff --git a/trunk/3rdparty/openssl-1.1-fit/Configure b/trunk/3rdparty/openssl-1.1-fit/Configure new file mode 100755 index 000000000..608012225 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/Configure @@ -0,0 +1,3519 @@ +#! /usr/bin/env perl +# -*- mode: perl; -*- +# Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +## Configure -- OpenSSL source tree configuration script + +use 5.10.0; +use strict; +use Config; +use FindBin; +use lib "$FindBin::Bin/util/perl"; +use File::Basename; +use File::Spec::Functions qw/:DEFAULT abs2rel rel2abs/; +use File::Path qw/mkpath/; +use OpenSSL::Glob; + +# see INSTALL for instructions. + +my $orig_death_handler = $SIG{__DIE__}; +$SIG{__DIE__} = \&death_handler; + +my $usage="Usage: Configure [no- ...] [enable- ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-egd] [sctp] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--config=FILE] os/compiler[:flags]\n"; + +# Options: +# +# --config add the given configuration file, which will be read after +# any "Configurations*" files that are found in the same +# directory as this script. +# --prefix prefix for the OpenSSL installation, which includes the +# directories bin, lib, include, share/man, share/doc/openssl +# This becomes the value of INSTALLTOP in Makefile +# (Default: /usr/local) +# --openssldir OpenSSL data area, such as openssl.cnf, certificates and keys. +# If it's a relative directory, it will be added on the directory +# given with --prefix. +# This becomes the value of OPENSSLDIR in Makefile and in C. +# (Default: PREFIX/ssl) +# +# --cross-compile-prefix Add specified prefix to binutils components. +# +# --api One of 0.9.8, 1.0.0 or 1.1.0. Do not compile support for +# interfaces deprecated as of the specified OpenSSL version. +# +# no-hw-xxx do not compile support for specific crypto hardware. +# Generic OpenSSL-style methods relating to this support +# are always compiled but return NULL if the hardware +# support isn't compiled. +# no-hw do not compile support for any crypto hardware. +# [no-]threads [don't] try to create a library that is suitable for +# multithreaded applications (default is "threads" if we +# know how to do it) +# [no-]shared [don't] try to create shared libraries when supported. +# [no-]pic [don't] try to build position independent code when supported. +# If disabled, it also disables shared and dynamic-engine. +# no-asm do not use assembler +# no-dso do not compile in any native shared-library methods. This +# will ensure that all methods just return NULL. +# no-egd do not compile support for the entropy-gathering daemon APIs +# [no-]zlib [don't] compile support for zlib compression. +# zlib-dynamic Like "zlib", but the zlib library is expected to be a shared +# library and will be loaded in run-time by the OpenSSL library. +# sctp include SCTP support +# enable-weak-ssl-ciphers +# Enable weak ciphers that are disabled by default. +# 386 generate 80386 code in assembly modules +# no-sse2 disables IA-32 SSE2 code in assembly modules, the above +# mentioned '386' option implies this one +# no- build without specified algorithm (rsa, idea, rc5, ...) +# - + compiler options are passed through +# -static while -static is also a pass-through compiler option (and +# as such is limited to environments where it's actually +# meaningful), it triggers a number configuration options, +# namely no-dso, no-pic, no-shared and no-threads. It is +# argued that the only reason to produce statically linked +# binaries (and in context it means executables linked with +# -static flag, and not just executables linked with static +# libcrypto.a) is to eliminate dependency on specific run-time, +# a.k.a. libc version. The mentioned config options are meant +# to achieve just that. Unfortunately on Linux it's impossible +# to eliminate the dependency completely for openssl executable +# because of getaddrinfo and gethostbyname calls, which can +# invoke dynamically loadable library facility anyway to meet +# the lookup requests. For this reason on Linux statically +# linked openssl executable has rather debugging value than +# production quality. +# +# DEBUG_SAFESTACK use type-safe stacks to enforce type-safety on stack items +# provided to stack calls. Generates unique stack functions for +# each possible stack type. +# BN_LLONG use the type 'long long' in crypto/bn/bn.h +# RC4_CHAR use 'char' instead of 'int' for RC4_INT in crypto/rc4/rc4.h +# Following are set automatically by this script +# +# MD5_ASM use some extra md5 assembler, +# SHA1_ASM use some extra sha1 assembler, must define L_ENDIAN for x86 +# RMD160_ASM use some extra ripemd160 assembler, +# SHA256_ASM sha256_block is implemented in assembler +# SHA512_ASM sha512_block is implemented in assembler +# AES_ASM AES_[en|de]crypt is implemented in assembler + +# Minimum warning options... any contributions to OpenSSL should at least get +# past these. + +# DEBUG_UNUSED enables __owur (warn unused result) checks. +# -DPEDANTIC complements -pedantic and is meant to mask code that +# is not strictly standard-compliant and/or implementation-specific, +# e.g. inline assembly, disregards to alignment requirements, such +# that -pedantic would complain about. Incidentally -DPEDANTIC has +# to be used even in sanitized builds, because sanitizer too is +# supposed to and does take notice of non-standard behaviour. Then +# -pedantic with pre-C9x compiler would also complain about 'long +# long' not being supported. As 64-bit algorithms are common now, +# it grew impossible to resolve this without sizeable additional +# code, so we just tell compiler to be pedantic about everything +# but 'long long' type. + +my $gcc_devteam_warn = "-DDEBUG_UNUSED" + . " -DPEDANTIC -pedantic -Wno-long-long" + . " -Wall" + . " -Wextra" + . " -Wno-unused-parameter" + . " -Wno-missing-field-initializers" + . " -Wswitch" + . " -Wsign-compare" + . " -Wmissing-prototypes" + . " -Wstrict-prototypes" + . " -Wshadow" + . " -Wformat" + . " -Wtype-limits" + . " -Wundef" + . " -Werror" + ; + +# These are used in addition to $gcc_devteam_warn when the compiler is clang. +# TODO(openssl-team): fix problems and investigate if (at least) the +# following warnings can also be enabled: +# -Wcast-align +# -Wunreachable-code -- no, too ugly/compiler-specific +# -Wlanguage-extension-token -- no, we use asm() +# -Wunused-macros -- no, too tricky for BN and _XOPEN_SOURCE etc +# -Wextended-offsetof -- no, needed in CMS ASN1 code +# -Wunused-function -- no, it forces header use of safestack et al +# DEFINE macros +my $clang_devteam_warn = "" + . " -Wswitch-default" + . " -Wno-parentheses-equality" + . " -Wno-language-extension-token" + . " -Wno-extended-offsetof" + . " -Wconditional-uninitialized" + . " -Wincompatible-pointer-types-discards-qualifiers" + . " -Wmissing-variable-declarations" + . " -Wno-unknown-warning-option" + . " -Wno-unused-function" + ; + +# This adds backtrace information to the memory leak info. Is only used +# when crypto-mdebug-backtrace is enabled. +my $memleak_devteam_backtrace = "-rdynamic"; + +my $strict_warnings = 0; + +# As for $BSDthreads. Idea is to maintain "collective" set of flags, +# which would cover all BSD flavors. -pthread applies to them all, +# but is treated differently. OpenBSD expands is as -D_POSIX_THREAD +# -lc_r, which is sufficient. FreeBSD 4.x expands it as -lc_r, +# which has to be accompanied by explicit -D_THREAD_SAFE and +# sometimes -D_REENTRANT. FreeBSD 5.x expands it as -lc_r, which +# seems to be sufficient? +our $BSDthreads="-pthread -D_THREAD_SAFE -D_REENTRANT"; + +# +# API compatibility name to version number mapping. +# +my $maxapi = "1.1.0"; # API for "no-deprecated" builds +my $apitable = { + "1.1.0" => "0x10100000L", + "1.0.0" => "0x10000000L", + "0.9.8" => "0x00908000L", +}; + +our %table = (); +our %config = (); +our %withargs = (); +our $now_printing; # set to current entry's name in print_table_entry + # (todo: right thing would be to encapsulate name + # into %target [class] and make print_table_entry + # a method) + +# Forward declarations ############################################### + +# read_config(filename) +# +# Reads a configuration file and populates %table with the contents +# (which the configuration file places in %targets). +sub read_config; + +# resolve_config(target) +# +# Resolves all the late evaluations, inheritances and so on for the +# chosen target and any target it inherits from. +sub resolve_config; + + +# Information collection ############################################# + +# Unified build supports separate build dir +my $srcdir = catdir(absolutedir(dirname($0))); # catdir ensures local syntax +my $blddir = catdir(absolutedir(".")); # catdir ensures local syntax +my $dofile = abs2rel(catfile($srcdir, "util/dofile.pl")); + +my $local_config_envname = 'OPENSSL_LOCAL_CONFIG_DIR'; + +$config{sourcedir} = abs2rel($srcdir); +$config{builddir} = abs2rel($blddir); + +# Collect reconfiguration information if needed +my @argvcopy=@ARGV; + +if (grep /^reconf(igure)?$/, @argvcopy) { + die "reconfiguring with other arguments present isn't supported" + if scalar @argvcopy > 1; + if (-f "./configdata.pm") { + my $file = "./configdata.pm"; + unless (my $return = do $file) { + die "couldn't parse $file: $@" if $@; + die "couldn't do $file: $!" unless defined $return; + die "couldn't run $file" unless $return; + } + + @argvcopy = defined($configdata::config{perlargv}) ? + @{$configdata::config{perlargv}} : (); + die "Incorrect data to reconfigure, please do a normal configuration\n" + if (grep(/^reconf/,@argvcopy)); + $config{perlenv} = $configdata::config{perlenv} // {}; + } else { + die "Insufficient data to reconfigure, please do a normal configuration\n"; + } +} + +$config{perlargv} = [ @argvcopy ]; + +# Collect version numbers +$config{version} = "unknown"; +$config{version_num} = "unknown"; +$config{shlib_version_number} = "unknown"; +$config{shlib_version_history} = "unknown"; + +collect_information( + collect_from_file(catfile($srcdir,'include/openssl/opensslv.h')), + qr/OPENSSL.VERSION.TEXT.*OpenSSL (\S+) / => sub { $config{version} = $1; }, + qr/OPENSSL.VERSION.NUMBER.*(0x\S+)/ => sub { $config{version_num}=$1 }, + qr/SHLIB_VERSION_NUMBER *"([^"]+)"/ => sub { $config{shlib_version_number}=$1 }, + qr/SHLIB_VERSION_HISTORY *"([^"]*)"/ => sub { $config{shlib_version_history}=$1 } + ); +if ($config{shlib_version_history} ne "") { $config{shlib_version_history} .= ":"; } + +($config{major}, $config{minor}) + = ($config{version} =~ /^([0-9]+)\.([0-9\.]+)/); +($config{shlib_major}, $config{shlib_minor}) + = ($config{shlib_version_number} =~ /^([0-9]+)\.([0-9\.]+)/); +die "erroneous version information in opensslv.h: ", + "$config{major}, $config{minor}, $config{shlib_major}, $config{shlib_minor}\n" + if ($config{major} eq "" || $config{minor} eq "" + || $config{shlib_major} eq "" || $config{shlib_minor} eq ""); + +# Collect target configurations + +my $pattern = catfile(dirname($0), "Configurations", "*.conf"); +foreach (sort glob($pattern)) { + &read_config($_); +} + +if (defined env($local_config_envname)) { + if ($^O eq 'VMS') { + # VMS environment variables are logical names, + # which can be used as is + $pattern = $local_config_envname . ':' . '*.conf'; + } else { + $pattern = catfile(env($local_config_envname), '*.conf'); + } + + foreach (sort glob($pattern)) { + &read_config($_); + } +} + +# Save away perl command information +$config{perl_cmd} = $^X; +$config{perl_version} = $Config{version}; +$config{perl_archname} = $Config{archname}; + +$config{prefix}=""; +$config{openssldir}=""; +$config{processor}=""; +$config{libdir}=""; +my $auto_threads=1; # enable threads automatically? true by default +my $default_ranlib; + +# Top level directories to build +$config{dirs} = [ "crypto", "ssl", "engines", "apps", "test", "util", "tools", "fuzz" ]; +# crypto/ subdirectories to build +$config{sdirs} = [ + "objects", + "md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash", "sm3", + "des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "sm4", "chacha", "modes", + "bn", "ec", "rsa", "dsa", "dh", "sm2", "dso", "engine", + "buffer", "bio", "stack", "lhash", "rand", "err", + "evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui", + "cms", "ts", "srp", "cmac", "ct", "async", "kdf", "store" + ]; +# test/ subdirectories to build +$config{tdirs} = [ "ossl_shim" ]; + +# Known TLS and DTLS protocols +my @tls = qw(ssl3 tls1 tls1_1 tls1_2 tls1_3); +my @dtls = qw(dtls1 dtls1_2); + +# Explicitly known options that are possible to disable. They can +# be regexps, and will be used like this: /^no-${option}$/ +# For developers: keep it sorted alphabetically + +my @disablables = ( + "afalgeng", + "aria", + "asan", + "asm", + "async", + "autoalginit", + "autoerrinit", + "autoload-config", + "bf", + "blake2", + "camellia", + "capieng", + "cast", + "chacha", + "cmac", + "cms", + "comp", + "crypto-mdebug", + "crypto-mdebug-backtrace", + "ct", + "deprecated", + "des", + "devcryptoeng", + "dgram", + "dh", + "dsa", + "dso", + "dtls", + "dynamic-engine", + "ec", + "ec2m", + "ecdh", + "ecdsa", + "ec_nistp_64_gcc_128", + "egd", + "engine", + "err", + "external-tests", + "filenames", + "fuzz-libfuzzer", + "fuzz-afl", + "gost", + "heartbeats", + "hw(-.+)?", + "idea", + "makedepend", + "md2", + "md4", + "mdc2", + "msan", + "multiblock", + "nextprotoneg", + "pinshared", + "ocb", + "ocsp", + "pic", + "poly1305", + "posix-io", + "psk", + "rc2", + "rc4", + "rc5", + "rdrand", + "rfc3779", + "rmd160", + "scrypt", + "sctp", + "seed", + "shared", + "siphash", + "sm2", + "sm3", + "sm4", + "sock", + "srp", + "srtp", + "sse2", + "ssl", + "ssl-trace", + "static-engine", + "stdio", + "tests", + "threads", + "tls", + "ts", + "ubsan", + "ui-console", + "unit-test", + "whirlpool", + "weak-ssl-ciphers", + "zlib", + "zlib-dynamic", + ); +foreach my $proto ((@tls, @dtls)) + { + push(@disablables, $proto); + push(@disablables, "$proto-method") unless $proto eq "tls1_3"; + } + +my %deprecated_disablables = ( + "ssl2" => undef, + "buf-freelists" => undef, + "ripemd" => "rmd160", + "ui" => "ui-console", + ); + +# All of the following are disabled by default: + +our %disabled = ( # "what" => "comment" + "asan" => "default", + "crypto-mdebug" => "default", + "crypto-mdebug-backtrace" => "default", + "devcryptoeng" => "default", + "ec_nistp_64_gcc_128" => "default", + "egd" => "default", + "external-tests" => "default", + "fuzz-libfuzzer" => "default", + "fuzz-afl" => "default", + "heartbeats" => "default", + "md2" => "default", + "msan" => "default", + "rc5" => "default", + "sctp" => "default", + "ssl-trace" => "default", + "ssl3" => "default", + "ssl3-method" => "default", + "ubsan" => "default", + "unit-test" => "default", + "weak-ssl-ciphers" => "default", + "zlib" => "default", + "zlib-dynamic" => "default", + ); + +# Note: => pair form used for aesthetics, not to truly make a hash table +my @disable_cascades = ( + # "what" => [ "cascade", ... ] + sub { $config{processor} eq "386" } + => [ "sse2" ], + "ssl" => [ "ssl3" ], + "ssl3-method" => [ "ssl3" ], + "zlib" => [ "zlib-dynamic" ], + "des" => [ "mdc2" ], + "ec" => [ "ecdsa", "ecdh" ], + + "dgram" => [ "dtls", "sctp" ], + "sock" => [ "dgram" ], + "dtls" => [ @dtls ], + sub { 0 == scalar grep { !$disabled{$_} } @dtls } + => [ "dtls" ], + + "tls" => [ @tls ], + sub { 0 == scalar grep { !$disabled{$_} } @tls } + => [ "tls" ], + + "crypto-mdebug" => [ "crypto-mdebug-backtrace" ], + + # Without DSO, we can't load dynamic engines, so don't build them dynamic + "dso" => [ "dynamic-engine" ], + + # Without position independent code, there can be no shared libraries or DSOs + "pic" => [ "shared" ], + "shared" => [ "dynamic-engine" ], + "engine" => [ "afalgeng", "devcryptoeng" ], + + # no-autoalginit is only useful when building non-shared + "autoalginit" => [ "shared", "apps" ], + + "stdio" => [ "apps", "capieng", "egd" ], + "apps" => [ "tests" ], + "tests" => [ "external-tests" ], + "comp" => [ "zlib" ], + "ec" => [ "tls1_3", "sm2" ], + "sm3" => [ "sm2" ], + sub { !$disabled{"unit-test"} } => [ "heartbeats" ], + + sub { !$disabled{"msan"} } => [ "asm" ], + ); + +# Avoid protocol support holes. Also disable all versions below N, if version +# N is disabled while N+1 is enabled. +# +my @list = (reverse @tls); +while ((my $first, my $second) = (shift @list, shift @list)) { + last unless @list; + push @disable_cascades, ( sub { !$disabled{$first} && $disabled{$second} } + => [ @list ] ); + unshift @list, $second; +} +my @list = (reverse @dtls); +while ((my $first, my $second) = (shift @list, shift @list)) { + last unless @list; + push @disable_cascades, ( sub { !$disabled{$first} && $disabled{$second} } + => [ @list ] ); + unshift @list, $second; +} + +# Explicit "no-..." options will be collected in %disabled along with the defaults. +# To remove something from %disabled, use "enable-foo". +# For symmetry, "disable-foo" is a synonym for "no-foo". + +&usage if ($#ARGV < 0); + +# For the "make variables" CINCLUDES and CDEFINES, we support lists with +# platform specific list separators. Users from those platforms should +# recognise those separators from how you set up the PATH to find executables. +# The default is the Unix like separator, :, but as an exception, we also +# support the space as separator. +my $list_separator_re = + { VMS => qr/(? qr/(? {$^O} // qr/(? env('AR'), + ARFLAGS => [], + AS => undef, + ASFLAGS => [], + CC => env('CC'), + CFLAGS => [], + CXX => env('CXX'), + CXXFLAGS => [], + CPP => undef, + CPPFLAGS => [], # -D, -I, -Wp, + CPPDEFINES => [], # Alternative for -D + CPPINCLUDES => [], # Alternative for -I + CROSS_COMPILE => env('CROSS_COMPILE'), + HASHBANGPERL=> env('HASHBANGPERL') || env('PERL'), + LD => undef, + LDFLAGS => [], # -L, -Wl, + LDLIBS => [], # -l + MT => undef, + MTFLAGS => [], + PERL => env('PERL') || ($^O ne "VMS" ? $^X : "perl"), + RANLIB => env('RANLIB'), + RC => env('RC') || env('WINDRES'), + RCFLAGS => [], + RM => undef, + ); +# Info about what "make variables" may be prefixed with the cross compiler +# prefix. This should NEVER mention any such variable with a list for value. +my @user_crossable = qw ( AR AS CC CXX CPP LD MT RANLIB RC ); +# The same but for flags given as Configure options. These are *additional* +# input, as opposed to the VAR=string option that override the corresponding +# config target attributes +my %useradd = ( + CPPDEFINES => [], + CPPINCLUDES => [], + CPPFLAGS => [], + CFLAGS => [], + CXXFLAGS => [], + LDFLAGS => [], + LDLIBS => [], + ); + +my %user_synonyms = ( + HASHBANGPERL=> 'PERL', + RC => 'WINDRES', + ); + +# Some target attributes have been renamed, this is the translation table +my %target_attr_translate =( + ar => 'AR', + as => 'AS', + cc => 'CC', + cxx => 'CXX', + cpp => 'CPP', + hashbangperl => 'HASHBANGPERL', + ld => 'LD', + mt => 'MT', + ranlib => 'RANLIB', + rc => 'RC', + rm => 'RM', + ); + +# Initialisers coming from 'config' scripts +$config{defines} = [ split(/$list_separator_re/, env('__CNF_CPPDEFINES')) ]; +$config{includes} = [ split(/$list_separator_re/, env('__CNF_CPPINCLUDES')) ]; +$config{cppflags} = [ env('__CNF_CPPFLAGS') || () ]; +$config{cflags} = [ env('__CNF_CFLAGS') || () ]; +$config{cxxflags} = [ env('__CNF_CXXFLAGS') || () ]; +$config{lflags} = [ env('__CNF_LDFLAGS') || () ]; +$config{ex_libs} = [ env('__CNF_LDLIBS') || () ]; + +$config{openssl_api_defines}=[]; +$config{openssl_algorithm_defines}=[]; +$config{openssl_thread_defines}=[]; +$config{openssl_sys_defines}=[]; +$config{openssl_other_defines}=[]; +$config{options}=""; +$config{build_type} = "release"; +my $target=""; + +my %cmdvars = (); # Stores FOO='blah' type arguments +my %unsupported_options = (); +my %deprecated_options = (); +# If you change this, update apps/version.c +my @known_seed_sources = qw(getrandom devrandom os egd none rdcpu librandom); +my @seed_sources = (); +while (@argvcopy) + { + $_ = shift @argvcopy; + + # Support env variable assignments among the options + if (m|^(\w+)=(.+)?$|) + { + $cmdvars{$1} = $2; + # Every time a variable is given as a configuration argument, + # it acts as a reset if the variable. + if (exists $user{$1}) + { + $user{$1} = ref $user{$1} eq "ARRAY" ? [] : undef; + } + #if (exists $useradd{$1}) + # { + # $useradd{$1} = []; + # } + next; + } + + # VMS is a case insensitive environment, and depending on settings + # out of our control, we may receive options uppercased. Let's + # downcase at least the part before any equal sign. + if ($^O eq "VMS") + { + s/^([^=]*)/lc($1)/e; + } + + # some people just can't read the instructions, clang people have to... + s/^-no-(?!integrated-as)/no-/; + + # rewrite some options in "enable-..." form + s /^-?-?shared$/enable-shared/; + s /^sctp$/enable-sctp/; + s /^threads$/enable-threads/; + s /^zlib$/enable-zlib/; + s /^zlib-dynamic$/enable-zlib-dynamic/; + + if (/^(no|disable|enable)-(.+)$/) + { + my $word = $2; + if (!exists $deprecated_disablables{$word} + && !grep { $word =~ /^${_}$/ } @disablables) + { + $unsupported_options{$_} = 1; + next; + } + } + if (/^no-(.+)$/ || /^disable-(.+)$/) + { + foreach my $proto ((@tls, @dtls)) + { + if ($1 eq "$proto-method") + { + $disabled{"$proto"} = "option($proto-method)"; + last; + } + } + if ($1 eq "dtls") + { + foreach my $proto (@dtls) + { + $disabled{$proto} = "option(dtls)"; + } + $disabled{"dtls"} = "option(dtls)"; + } + elsif ($1 eq "ssl") + { + # Last one of its kind + $disabled{"ssl3"} = "option(ssl)"; + } + elsif ($1 eq "tls") + { + # XXX: Tests will fail if all SSL/TLS + # protocols are disabled. + foreach my $proto (@tls) + { + $disabled{$proto} = "option(tls)"; + } + } + elsif ($1 eq "static-engine") + { + delete $disabled{"dynamic-engine"}; + } + elsif ($1 eq "dynamic-engine") + { + $disabled{"dynamic-engine"} = "option"; + } + elsif (exists $deprecated_disablables{$1}) + { + $deprecated_options{$_} = 1; + if (defined $deprecated_disablables{$1}) + { + $disabled{$deprecated_disablables{$1}} = "option"; + } + } + else + { + $disabled{$1} = "option"; + } + # No longer an automatic choice + $auto_threads = 0 if ($1 eq "threads"); + } + elsif (/^enable-(.+)$/) + { + if ($1 eq "static-engine") + { + $disabled{"dynamic-engine"} = "option"; + } + elsif ($1 eq "dynamic-engine") + { + delete $disabled{"dynamic-engine"}; + } + elsif ($1 eq "zlib-dynamic") + { + delete $disabled{"zlib"}; + } + my $algo = $1; + delete $disabled{$algo}; + + # No longer an automatic choice + $auto_threads = 0 if ($1 eq "threads"); + } + elsif (/^--strict-warnings$/) + { + $strict_warnings = 1; + } + elsif (/^--debug$/) + { + $config{build_type} = "debug"; + } + elsif (/^--release$/) + { + $config{build_type} = "release"; + } + elsif (/^386$/) + { $config{processor}=386; } + elsif (/^fips$/) + { + die "FIPS mode not supported\n"; + } + elsif (/^rsaref$/) + { + # No RSAref support any more since it's not needed. + # The check for the option is there so scripts aren't + # broken + } + elsif (/^nofipscanistercheck$/) + { + die "FIPS mode not supported\n"; + } + elsif (/^[-+]/) + { + if (/^--prefix=(.*)$/) + { + $config{prefix}=$1; + die "Directory given with --prefix MUST be absolute\n" + unless file_name_is_absolute($config{prefix}); + } + elsif (/^--api=(.*)$/) + { + $config{api}=$1; + } + elsif (/^--libdir=(.*)$/) + { + $config{libdir}=$1; + } + elsif (/^--openssldir=(.*)$/) + { + $config{openssldir}=$1; + } + elsif (/^--with-zlib-lib=(.*)$/) + { + $withargs{zlib_lib}=$1; + } + elsif (/^--with-zlib-include=(.*)$/) + { + $withargs{zlib_include}=$1; + } + elsif (/^--with-fuzzer-lib=(.*)$/) + { + $withargs{fuzzer_lib}=$1; + } + elsif (/^--with-fuzzer-include=(.*)$/) + { + $withargs{fuzzer_include}=$1; + } + elsif (/^--with-rand-seed=(.*)$/) + { + foreach my $x (split(m|,|, $1)) + { + die "Unknown --with-rand-seed choice $x\n" + if ! grep { $x eq $_ } @known_seed_sources; + push @seed_sources, $x; + } + } + elsif (/^--cross-compile-prefix=(.*)$/) + { + $user{CROSS_COMPILE}=$1; + } + elsif (/^--config=(.*)$/) + { + read_config $1; + } + elsif (/^-l(.*)$/) + { + push @{$useradd{LDLIBS}}, $_; + } + elsif (/^-framework$/) + { + push @{$useradd{LDLIBS}}, $_, shift(@argvcopy); + } + elsif (/^-L(.*)$/ or /^-Wl,/) + { + push @{$useradd{LDFLAGS}}, $_; + } + elsif (/^-rpath$/ or /^-R$/) + # -rpath is the OSF1 rpath flag + # -R is the old Solaris rpath flag + { + my $rpath = shift(@argvcopy) || ""; + $rpath .= " " if $rpath ne ""; + push @{$useradd{LDFLAGS}}, $_, $rpath; + } + elsif (/^-static$/) + { + push @{$useradd{LDFLAGS}}, $_; + $disabled{"dso"} = "forced"; + $disabled{"pic"} = "forced"; + $disabled{"shared"} = "forced"; + $disabled{"threads"} = "forced"; + } + elsif (/^-D(.*)$/) + { + push @{$useradd{CPPDEFINES}}, $1; + } + elsif (/^-I(.*)$/) + { + push @{$useradd{CPPINCLUDES}}, $1; + } + elsif (/^-Wp,$/) + { + push @{$useradd{CPPFLAGS}}, $1; + } + else # common if (/^[-+]/), just pass down... + { + $_ =~ s/%([0-9a-f]{1,2})/chr(hex($1))/gei; + push @{$useradd{CFLAGS}}, $_; + push @{$useradd{CXXFLAGS}}, $_; + } + } + else + { + die "target already defined - $target (offending arg: $_)\n" if ($target ne ""); + $target=$_; + } + unless ($_ eq $target || /^no-/ || /^disable-/) + { + # "no-..." follows later after implied deactivations + # have been derived. (Don't take this too seriously, + # we really only write OPTIONS to the Makefile out of + # nostalgia.) + + if ($config{options} eq "") + { $config{options} = $_; } + else + { $config{options} .= " ".$_; } + } + } + +if (defined($config{api}) && !exists $apitable->{$config{api}}) { + die "***** Unsupported api compatibility level: $config{api}\n", +} + +if (keys %deprecated_options) + { + warn "***** Deprecated options: ", + join(", ", keys %deprecated_options), "\n"; + } +if (keys %unsupported_options) + { + die "***** Unsupported options: ", + join(", ", keys %unsupported_options), "\n"; + } + +# If any %useradd entry has been set, we must check that the "make +# variables" haven't been set. We start by checking of any %useradd entry +# is set. +if (grep { scalar @$_ > 0 } values %useradd) { + # Hash of env / make variables names. The possible values are: + # 1 - "make vars" + # 2 - %useradd entry set + # 3 - both set + my %detected_vars = + map { my $v = 0; + $v += 1 if $cmdvars{$_}; + $v += 2 if @{$useradd{$_}}; + $_ => $v } + keys %useradd; + + # If any of the corresponding "make variables" is set, we error + if (grep { $_ & 1 } values %detected_vars) { + my $names = join(', ', grep { $detected_vars{$_} > 0 } + sort keys %detected_vars); + die <<"_____"; +***** Mixing make variables and additional compiler/linker flags as +***** configure command line option is not permitted. +***** Affected make variables: $names +_____ + } +} + +# Check through all supported command line variables to see if any of them +# were set, and canonicalise the values we got. If no compiler or linker +# flag or anything else that affects %useradd was set, we also check the +# environment for values. +my $anyuseradd = + grep { defined $_ && (ref $_ ne 'ARRAY' || @$_) } values %useradd; +foreach (keys %user) { + my $value = $cmdvars{$_}; + $value //= env($_) unless $anyuseradd; + $value //= + defined $user_synonyms{$_} ? $cmdvars{$user_synonyms{$_}} : undef; + $value //= defined $user_synonyms{$_} ? env($user_synonyms{$_}) : undef + unless $anyuseradd; + + if (defined $value) { + if (ref $user{$_} eq 'ARRAY') { + $user{$_} = [ split /$list_separator_re/, $value ]; + } elsif (!defined $user{$_}) { + $user{$_} = $value; + } + } +} + +if (grep { /-rpath\b/ } ($user{LDFLAGS} ? @{$user{LDFLAGS}} : ()) + && !$disabled{shared} + && !($disabled{asan} && $disabled{msan} && $disabled{ubsan})) { + die "***** Cannot simultaneously use -rpath, shared libraries, and\n", + "***** any of asan, msan or ubsan\n"; +} + +my @tocheckfor = (keys %disabled); +while (@tocheckfor) { + my %new_tocheckfor = (); + my @cascade_copy = (@disable_cascades); + while (@cascade_copy) { + my ($test, $descendents) = (shift @cascade_copy, shift @cascade_copy); + if (ref($test) eq "CODE" ? $test->() : defined($disabled{$test})) { + foreach(grep { !defined($disabled{$_}) } @$descendents) { + $new_tocheckfor{$_} = 1; $disabled{$_} = "forced"; + } + } + } + @tocheckfor = (keys %new_tocheckfor); +} + +our $die = sub { die @_; }; +if ($target eq "TABLE") { + local $die = sub { warn @_; }; + foreach (sort keys %table) { + print_table_entry($_, "TABLE"); + } + exit 0; +} + +if ($target eq "LIST") { + foreach (sort keys %table) { + print $_,"\n" unless $table{$_}->{template}; + } + exit 0; +} + +if ($target eq "HASH") { + local $die = sub { warn @_; }; + print "%table = (\n"; + foreach (sort keys %table) { + print_table_entry($_, "HASH"); + } + exit 0; +} + +print "Configuring OpenSSL version $config{version} ($config{version_num}) "; +print "for $target\n"; + +if (scalar(@seed_sources) == 0) { + print "Using os-specific seed configuration\n"; + push @seed_sources, 'os'; +} +if (scalar(grep { $_ eq 'none' } @seed_sources) > 0) { + die "Cannot seed with none and anything else" if scalar(@seed_sources) > 1; + warn <<_____ if scalar(@seed_sources) == 1; + +============================== WARNING =============================== +You have selected the --with-rand-seed=none option, which effectively +disables automatic reseeding of the OpenSSL random generator. +All operations depending on the random generator such as creating keys +will not work unless the random generator is seeded manually by the +application. + +Please read the 'Note on random number generation' section in the +INSTALL instructions and the RAND_DRBG(7) manual page for more details. +============================== WARNING =============================== + +_____ +} +push @{$config{openssl_other_defines}}, + map { (my $x = $_) =~ tr|[\-a-z]|[_A-Z]|; "OPENSSL_RAND_SEED_$x" } + @seed_sources; + +# Backward compatibility? +if ($target =~ m/^CygWin32(-.*)$/) { + $target = "Cygwin".$1; +} + +# Support for legacy targets having a name starting with 'debug-' +my ($d, $t) = $target =~ m/^(debug-)?(.*)$/; +if ($d) { + $config{build_type} = "debug"; + + # If we do not find debug-foo in the table, the target is set to foo. + if (!$table{$target}) { + $target = $t; + } +} + +&usage if !$table{$target} || $table{$target}->{template}; + +$config{target} = $target; +my %target = resolve_config($target); + +foreach (keys %target_attr_translate) { + $target{$target_attr_translate{$_}} = $target{$_} + if $target{$_}; + delete $target{$_}; +} + +%target = ( %{$table{DEFAULTS}}, %target ); + +# Make the flags to build DSOs the same as for shared libraries unless they +# are already defined +$target{module_cflags} = $target{shared_cflag} unless defined $target{module_cflags}; +$target{module_cxxflags} = $target{shared_cxxflag} unless defined $target{module_cxxflags}; +$target{module_ldflags} = $target{shared_ldflag} unless defined $target{module_ldflags}; +{ + my $shared_info_pl = + catfile(dirname($0), "Configurations", "shared-info.pl"); + my %shared_info = read_eval_file($shared_info_pl); + push @{$target{_conf_fname_int}}, $shared_info_pl; + my $si = $target{shared_target}; + while (ref $si ne "HASH") { + last if ! defined $si; + if (ref $si eq "CODE") { + $si = $si->(); + } else { + $si = $shared_info{$si}; + } + } + + # Some of the 'shared_target' values don't have any entried in + # %shared_info. That's perfectly fine, AS LONG AS the build file + # template knows how to handle this. That is currently the case for + # Windows and VMS. + if (defined $si) { + # Just as above, copy certain shared_* attributes to the corresponding + # module_ attribute unless the latter is already defined + $si->{module_cflags} = $si->{shared_cflag} unless defined $si->{module_cflags}; + $si->{module_cxxflags} = $si->{shared_cxxflag} unless defined $si->{module_cxxflags}; + $si->{module_ldflags} = $si->{shared_ldflag} unless defined $si->{module_ldflags}; + foreach (sort keys %$si) { + $target{$_} = defined $target{$_} + ? add($si->{$_})->($target{$_}) + : $si->{$_}; + } + } +} + +my %conf_files = map { $_ => 1 } (@{$target{_conf_fname_int}}); +$config{conf_files} = [ sort keys %conf_files ]; + +foreach my $feature (@{$target{disable}}) { + if (exists $deprecated_disablables{$feature}) { + warn "***** config $target disables deprecated feature $feature\n"; + } elsif (!grep { $feature eq $_ } @disablables) { + die "***** config $target disables unknown feature $feature\n"; + } + $disabled{$feature} = 'config'; +} +foreach my $feature (@{$target{enable}}) { + if ("default" eq ($disabled{$feature} // "")) { + if (exists $deprecated_disablables{$feature}) { + warn "***** config $target enables deprecated feature $feature\n"; + } elsif (!grep { $feature eq $_ } @disablables) { + die "***** config $target enables unknown feature $feature\n"; + } + delete $disabled{$feature}; + } +} + +$target{CXXFLAGS}//=$target{CFLAGS} if $target{CXX}; +$target{cxxflags}//=$target{cflags} if $target{CXX}; +$target{exe_extension}=""; +$target{exe_extension}=".exe" if ($config{target} eq "DJGPP" + || $config{target} =~ /^(?:Cygwin|mingw)/); +$target{exe_extension}=".pm" if ($config{target} =~ /vos/); + +($target{shared_extension_simple}=$target{shared_extension}) + =~ s|\.\$\(SHLIB_VERSION_NUMBER\)|| + unless defined($target{shared_extension_simple}); +$target{dso_extension}//=$target{shared_extension_simple}; +($target{shared_import_extension}=$target{shared_extension_simple}.".a") + if ($config{target} =~ /^(?:Cygwin|mingw)/); + +# Fill %config with values from %user, and in case those are undefined or +# empty, use values from %target (acting as a default). +foreach (keys %user) { + my $ref_type = ref $user{$_}; + + # Temporary function. Takes an intended ref type (empty string or "ARRAY") + # and a value that's to be coerced into that type. + my $mkvalue = sub { + my $type = shift; + my $value = shift; + my $undef_p = shift; + + die "Too many arguments for \$mkvalue" if @_; + + while (ref $value eq 'CODE') { + $value = $value->(); + } + + if ($type eq 'ARRAY') { + return undef unless defined $value; + return undef if ref $value ne 'ARRAY' && !$value; + return undef if ref $value eq 'ARRAY' && !@$value; + return [ $value ] unless ref $value eq 'ARRAY'; + } + return undef unless $value; + return $value; + }; + + $config{$_} = + $mkvalue->($ref_type, $user{$_}) + || $mkvalue->($ref_type, $target{$_}); + delete $config{$_} unless defined $config{$_}; +} + +# Allow overriding the build file name +$config{build_file} = env('BUILDFILE') || $target{build_file} || "Makefile"; + +my %disabled_info = (); # For configdata.pm +foreach my $what (sort keys %disabled) { + $config{options} .= " no-$what"; + + if (!grep { $what eq $_ } ( 'dso', 'threads', 'shared', 'pic', + 'dynamic-engine', 'makedepend', + 'zlib-dynamic', 'zlib', 'sse2' )) { + (my $WHAT = uc $what) =~ s|-|_|g; + + # Fix up C macro end names + $WHAT = "RMD160" if $what eq "ripemd"; + + # fix-up crypto/directory name(s) + $what = "ripemd" if $what eq "rmd160"; + $what = "whrlpool" if $what eq "whirlpool"; + + my $macro = $disabled_info{$what}->{macro} = "OPENSSL_NO_$WHAT"; + + if ((grep { $what eq $_ } @{$config{sdirs}}) + && $what ne 'async' && $what ne 'err') { + @{$config{sdirs}} = grep { $what ne $_} @{$config{sdirs}}; + $disabled_info{$what}->{skipped} = [ catdir('crypto', $what) ]; + + if ($what ne 'engine') { + push @{$config{openssl_algorithm_defines}}, $macro; + } else { + @{$config{dirs}} = grep !/^engines$/, @{$config{dirs}}; + push @{$disabled_info{engine}->{skipped}}, catdir('engines'); + push @{$config{openssl_other_defines}}, $macro; + } + } else { + push @{$config{openssl_other_defines}}, $macro; + } + + } +} + +# Make sure build_scheme is consistent. +$target{build_scheme} = [ $target{build_scheme} ] + if ref($target{build_scheme}) ne "ARRAY"; + +my ($builder, $builder_platform, @builder_opts) = + @{$target{build_scheme}}; + +foreach my $checker (($builder_platform."-".$target{build_file}."-checker.pm", + $builder_platform."-checker.pm")) { + my $checker_path = catfile($srcdir, "Configurations", $checker); + if (-f $checker_path) { + my $fn = $ENV{CONFIGURE_CHECKER_WARN} + ? sub { warn $@; } : sub { die $@; }; + if (! do $checker_path) { + if ($@) { + $fn->($@); + } elsif ($!) { + $fn->($!); + } else { + $fn->("The detected tools didn't match the platform\n"); + } + } + last; + } +} + +push @{$config{defines}}, "NDEBUG" if $config{build_type} eq "release"; + +if ($target =~ /^mingw/ && `$config{CC} --target-help 2>&1` =~ m/-mno-cygwin/m) + { + push @{$config{cflags}}, "-mno-cygwin"; + push @{$config{cxxflags}}, "-mno-cygwin" if $config{CXX}; + push @{$config{shared_ldflag}}, "-mno-cygwin"; + } + +if ($target =~ /linux.*-mips/ && !$disabled{asm} + && !grep { $_ !~ /-m(ips|arch=)/ } (@{$user{CFLAGS}}, + @{$useradd{CFLAGS}})) { + # minimally required architecture flags for assembly modules + my $value; + $value = '-mips2' if ($target =~ /mips32/); + $value = '-mips3' if ($target =~ /mips64/); + unshift @{$config{cflags}}, $value; + unshift @{$config{cxxflags}}, $value if $config{CXX}; +} + +# If threads aren't disabled, check how possible they are +unless ($disabled{threads}) { + if ($auto_threads) { + # Enabled by default, disable it forcibly if unavailable + if ($target{thread_scheme} eq "(unknown)") { + $disabled{threads} = "unavailable"; + } + } else { + # The user chose to enable threads explicitly, let's see + # if there's a chance that's possible + if ($target{thread_scheme} eq "(unknown)") { + # If the user asked for "threads" and we don't have internal + # knowledge how to do it, [s]he is expected to provide any + # system-dependent compiler options that are necessary. We + # can't truly check that the given options are correct, but + # we expect the user to know what [s]He is doing. + if (!@{$user{CFLAGS}} && !@{$useradd{CFLAGS}} + && !@{$user{CPPDEFINES}} && !@{$useradd{CPPDEFINES}}) { + die "You asked for multi-threading support, but didn't\n" + ,"provide any system-specific compiler options\n"; + } + } + } +} + +# If threads still aren't disabled, add a C macro to ensure the source +# code knows about it. Any other flag is taken care of by the configs. +unless($disabled{threads}) { + push @{$config{openssl_thread_defines}}, "OPENSSL_THREADS"; +} + +# With "deprecated" disable all deprecated features. +if (defined($disabled{"deprecated"})) { + $config{api} = $maxapi; +} + +my $no_shared_warn=0; +if ($target{shared_target} eq "") + { + $no_shared_warn = 1 + if (!$disabled{shared} || !$disabled{"dynamic-engine"}); + $disabled{shared} = "no-shared-target"; + $disabled{pic} = $disabled{shared} = $disabled{"dynamic-engine"} = + "no-shared-target"; + } + +if ($disabled{"dynamic-engine"}) { + push @{$config{openssl_other_defines}}, "OPENSSL_NO_DYNAMIC_ENGINE"; + $config{dynamic_engines} = 0; +} else { + push @{$config{openssl_other_defines}}, "OPENSSL_NO_STATIC_ENGINE"; + $config{dynamic_engines} = 1; +} + +unless ($disabled{asan}) { + push @{$config{cflags}}, "-fsanitize=address"; + push @{$config{cxxflags}}, "-fsanitize=address" if $config{CXX}; +} + +unless ($disabled{ubsan}) { + # -DPEDANTIC or -fnosanitize=alignment may also be required on some + # platforms. + push @{$config{cflags}}, "-fsanitize=undefined", "-fno-sanitize-recover=all"; + push @{$config{cxxflags}}, "-fsanitize=undefined", "-fno-sanitize-recover=all" + if $config{CXX}; +} + +unless ($disabled{msan}) { + push @{$config{cflags}}, "-fsanitize=memory"; + push @{$config{cxxflags}}, "-fsanitize=memory" if $config{CXX}; +} + +unless ($disabled{"fuzz-libfuzzer"} && $disabled{"fuzz-afl"} + && $disabled{asan} && $disabled{ubsan} && $disabled{msan}) { + push @{$config{cflags}}, "-fno-omit-frame-pointer", "-g"; + push @{$config{cxxflags}}, "-fno-omit-frame-pointer", "-g" if $config{CXX}; +} +# +# Platform fix-ups +# + +# This saves the build files from having to check +if ($disabled{pic}) + { + foreach (qw(shared_cflag shared_cxxflag shared_cppflag + shared_defines shared_includes shared_ldflag + module_cflags module_cxxflags module_cppflags + module_defines module_includes module_lflags)) + { + delete $config{$_}; + $target{$_} = ""; + } + } +else + { + push @{$config{lib_defines}}, "OPENSSL_PIC"; + } + +if ($target{sys_id} ne "") + { + push @{$config{openssl_sys_defines}}, "OPENSSL_SYS_$target{sys_id}"; + } + +unless ($disabled{asm}) { + $target{cpuid_asm_src}=$table{DEFAULTS}->{cpuid_asm_src} if ($config{processor} eq "386"); + push @{$config{lib_defines}}, "OPENSSL_CPUID_OBJ" if ($target{cpuid_asm_src} ne "mem_clr.c"); + + $target{bn_asm_src} =~ s/\w+-gf2m.c// if (defined($disabled{ec2m})); + + # bn-586 is the only one implementing bn_*_part_words + push @{$config{lib_defines}}, "OPENSSL_BN_ASM_PART_WORDS" if ($target{bn_asm_src} =~ /bn-586/); + push @{$config{lib_defines}}, "OPENSSL_IA32_SSE2" if (!$disabled{sse2} && $target{bn_asm_src} =~ /86/); + + push @{$config{lib_defines}}, "OPENSSL_BN_ASM_MONT" if ($target{bn_asm_src} =~ /-mont/); + push @{$config{lib_defines}}, "OPENSSL_BN_ASM_MONT5" if ($target{bn_asm_src} =~ /-mont5/); + push @{$config{lib_defines}}, "OPENSSL_BN_ASM_GF2m" if ($target{bn_asm_src} =~ /-gf2m/); + push @{$config{lib_defines}}, "BN_DIV3W" if ($target{bn_asm_src} =~ /-div3w/); + + if ($target{sha1_asm_src}) { + push @{$config{lib_defines}}, "SHA1_ASM" if ($target{sha1_asm_src} =~ /sx86/ || $target{sha1_asm_src} =~ /sha1/); + push @{$config{lib_defines}}, "SHA256_ASM" if ($target{sha1_asm_src} =~ /sha256/); + push @{$config{lib_defines}}, "SHA512_ASM" if ($target{sha1_asm_src} =~ /sha512/); + } + if ($target{keccak1600_asm_src} ne $table{DEFAULTS}->{keccak1600_asm_src}) { + push @{$config{lib_defines}}, "KECCAK1600_ASM"; + } + if ($target{rc4_asm_src} ne $table{DEFAULTS}->{rc4_asm_src}) { + push @{$config{lib_defines}}, "RC4_ASM"; + } + if ($target{md5_asm_src}) { + push @{$config{lib_defines}}, "MD5_ASM"; + } + $target{cast_asm_src}=$table{DEFAULTS}->{cast_asm_src} unless $disabled{pic}; # CAST assembler is not PIC + if ($target{rmd160_asm_src}) { + push @{$config{lib_defines}}, "RMD160_ASM"; + } + if ($target{aes_asm_src}) { + push @{$config{lib_defines}}, "AES_ASM" if ($target{aes_asm_src} =~ m/\baes-/);; + # aes-ctr.fake is not a real file, only indication that assembler + # module implements AES_ctr32_encrypt... + push @{$config{lib_defines}}, "AES_CTR_ASM" if ($target{aes_asm_src} =~ s/\s*aes-ctr\.fake//); + # aes-xts.fake indicates presence of AES_xts_[en|de]crypt... + push @{$config{lib_defines}}, "AES_XTS_ASM" if ($target{aes_asm_src} =~ s/\s*aes-xts\.fake//); + $target{aes_asm_src} =~ s/\s*(vpaes|aesni)-x86\.s//g if ($disabled{sse2}); + push @{$config{lib_defines}}, "VPAES_ASM" if ($target{aes_asm_src} =~ m/vpaes/); + push @{$config{lib_defines}}, "BSAES_ASM" if ($target{aes_asm_src} =~ m/bsaes/); + } + if ($target{wp_asm_src} =~ /mmx/) { + if ($config{processor} eq "386") { + $target{wp_asm_src}=$table{DEFAULTS}->{wp_asm_src}; + } elsif (!$disabled{"whirlpool"}) { + push @{$config{lib_defines}}, "WHIRLPOOL_ASM"; + } + } + if ($target{modes_asm_src} =~ /ghash-/) { + push @{$config{lib_defines}}, "GHASH_ASM"; + } + if ($target{ec_asm_src} =~ /ecp_nistz256/) { + push @{$config{lib_defines}}, "ECP_NISTZ256_ASM"; + } + if ($target{ec_asm_src} =~ /x25519/) { + push @{$config{lib_defines}}, "X25519_ASM"; + } + if ($target{padlock_asm_src} ne $table{DEFAULTS}->{padlock_asm_src}) { + push @{$config{lib_defines}}, "PADLOCK_ASM"; + } + if ($target{poly1305_asm_src} ne "") { + push @{$config{lib_defines}}, "POLY1305_ASM"; + } +} + +my %predefined = compiler_predefined($config{CROSS_COMPILE}.$config{CC}); + +# Check for makedepend capabilities. +if (!$disabled{makedepend}) { + if ($config{target} =~ /^(VC|vms)-/) { + # For VC- and vms- targets, there's nothing more to do here. The + # functionality is hard coded in the corresponding build files for + # cl (Windows) and CC/DECC (VMS). + } elsif (($predefined{__GNUC__} // -1) >= 3 + && !($predefined{__APPLE_CC__} && !$predefined{__clang__})) { + # We know that GNU C version 3 and up as well as all clang + # versions support dependency generation, but Xcode did not + # handle $cc -M before clang support (but claims __GNUC__ = 3) + $config{makedepprog} = "\$(CROSS_COMPILE)$config{CC}"; + } else { + # In all other cases, we look for 'makedepend', and disable the + # capability if not found. + $config{makedepprog} = which('makedepend'); + $disabled{makedepend} = "unavailable" unless $config{makedepprog}; + } +} + +if (!$disabled{asm} && !$predefined{__MACH__} && $^O ne 'VMS') { + # probe for -Wa,--noexecstack option... + if ($predefined{__clang__}) { + # clang has builtin assembler, which doesn't recognize --help, + # but it apparently recognizes the option in question on all + # supported platforms even when it's meaningless. In other words + # probe would fail, but probed option always accepted... + push @{$config{cflags}}, "-Wa,--noexecstack", "-Qunused-arguments"; + } else { + my $cc = $config{CROSS_COMPILE}.$config{CC}; + open(PIPE, "$cc -Wa,--help -c -o null.$$.o -x assembler /dev/null 2>&1 |"); + while() { + if (m/--noexecstack/) { + push @{$config{cflags}}, "-Wa,--noexecstack"; + last; + } + } + close(PIPE); + unlink("null.$$.o"); + } +} + +# Deal with bn_ops ################################################### + +$config{bn_ll} =0; +$config{export_var_as_fn} =0; +my $def_int="unsigned int"; +$config{rc4_int} =$def_int; +($config{b64l},$config{b64},$config{b32})=(0,0,1); + +my $count = 0; +foreach (sort split(/\s+/,$target{bn_ops})) { + $count++ if /SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT/; + $config{export_var_as_fn}=1 if $_ eq 'EXPORT_VAR_AS_FN'; + $config{bn_ll}=1 if $_ eq 'BN_LLONG'; + $config{rc4_int}="unsigned char" if $_ eq 'RC4_CHAR'; + ($config{b64l},$config{b64},$config{b32}) + =(0,1,0) if $_ eq 'SIXTY_FOUR_BIT'; + ($config{b64l},$config{b64},$config{b32}) + =(1,0,0) if $_ eq 'SIXTY_FOUR_BIT_LONG'; + ($config{b64l},$config{b64},$config{b32}) + =(0,0,1) if $_ eq 'THIRTY_TWO_BIT'; +} +die "Exactly one of SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT can be set in bn_ops\n" + if $count > 1; + + +# Hack cflags for better warnings (dev option) ####################### + +# "Stringify" the C and C++ flags string. This permits it to be made part of +# a string and works as well on command lines. +$config{cflags} = [ map { (my $x = $_) =~ s/([\\\"])/\\$1/g; $x } + @{$config{cflags}} ]; +$config{cxxflags} = [ map { (my $x = $_) =~ s/([\\\"])/\\$1/g; $x } + @{$config{cxxflags}} ] if $config{CXX}; + +if (defined($config{api})) { + $config{openssl_api_defines} = [ "OPENSSL_MIN_API=".$apitable->{$config{api}} ]; + my $apiflag = sprintf("OPENSSL_API_COMPAT=%s", $apitable->{$config{api}}); + push @{$config{defines}}, $apiflag; +} + +if ($strict_warnings) + { + my $wopt; + my $gccver = $predefined{__GNUC__} // -1; + + die "ERROR --strict-warnings requires gcc[>=4] or gcc-alike" + unless $gccver >= 4; + foreach $wopt (split /\s+/, $gcc_devteam_warn) + { + push @{$config{cflags}}, $wopt + unless grep { $_ eq $wopt } @{$config{cflags}}; + push @{$config{cxxflags}}, $wopt + if ($config{CXX} + && !grep { $_ eq $wopt } @{$config{cxxflags}}); + } + if (defined($predefined{__clang__})) + { + foreach $wopt (split /\s+/, $clang_devteam_warn) + { + push @{$config{cflags}}, $wopt + unless grep { $_ eq $wopt } @{$config{cflags}}; + push @{$config{cxxflags}}, $wopt + if ($config{CXX} + && !grep { $_ eq $wopt } @{$config{cxxflags}}); + } + } + } + +unless ($disabled{"crypto-mdebug-backtrace"}) + { + foreach my $wopt (split /\s+/, $memleak_devteam_backtrace) + { + push @{$config{cflags}}, $wopt + unless grep { $_ eq $wopt } @{$config{cflags}}; + push @{$config{cxxflags}}, $wopt + if ($config{CXX} + && !grep { $_ eq $wopt } @{$config{cxxflags}}); + } + if ($target =~ /^BSD-/) + { + push @{$config{ex_libs}}, "-lexecinfo"; + } + } + +unless ($disabled{afalgeng}) { + $config{afalgeng}=""; + if (grep { $_ eq 'afalgeng' } @{$target{enable}}) { + my $minver = 4*10000 + 1*100 + 0; + if ($config{CROSS_COMPILE} eq "") { + my $verstr = `uname -r`; + my ($ma, $mi1, $mi2) = split("\\.", $verstr); + ($mi2) = $mi2 =~ /(\d+)/; + my $ver = $ma*10000 + $mi1*100 + $mi2; + if ($ver < $minver) { + $disabled{afalgeng} = "too-old-kernel"; + } else { + push @{$config{engdirs}}, "afalg"; + } + } else { + $disabled{afalgeng} = "cross-compiling"; + } + } else { + $disabled{afalgeng} = "not-linux"; + } +} + +push @{$config{openssl_other_defines}}, "OPENSSL_NO_AFALGENG" if ($disabled{afalgeng}); + +# Finish up %config by appending things the user gave us on the command line +# apart from "make variables" +foreach (keys %useradd) { + # The must all be lists, so we assert that here + die "internal error: \$useradd{$_} isn't an ARRAY\n" + unless ref $useradd{$_} eq 'ARRAY'; + + if (defined $config{$_}) { + push @{$config{$_}}, @{$useradd{$_}}; + } else { + $config{$_} = [ @{$useradd{$_}} ]; + } +} + +# ALL MODIFICATIONS TO %config and %target MUST BE DONE FROM HERE ON + +# If we use the unified build, collect information from build.info files +my %unified_info = (); + +my $buildinfo_debug = defined($ENV{CONFIGURE_DEBUG_BUILDINFO}); +if ($builder eq "unified") { + use with_fallback qw(Text::Template); + + sub cleandir { + my $base = shift; + my $dir = shift; + my $relativeto = shift || "."; + + $dir = catdir($base,$dir) unless isabsolute($dir); + + # Make sure the directories we're building in exists + mkpath($dir); + + my $res = abs2rel(absolutedir($dir), rel2abs($relativeto)); + #print STDERR "DEBUG[cleandir]: $dir , $base => $res\n"; + return $res; + } + + sub cleanfile { + my $base = shift; + my $file = shift; + my $relativeto = shift || "."; + + $file = catfile($base,$file) unless isabsolute($file); + + my $d = dirname($file); + my $f = basename($file); + + # Make sure the directories we're building in exists + mkpath($d); + + my $res = abs2rel(catfile(absolutedir($d), $f), rel2abs($relativeto)); + #print STDERR "DEBUG[cleanfile]: $d , $f => $res\n"; + return $res; + } + + # Store the name of the template file we will build the build file from + # in %config. This may be useful for the build file itself. + my @build_file_template_names = + ( $builder_platform."-".$target{build_file}.".tmpl", + $target{build_file}.".tmpl" ); + my @build_file_templates = (); + + # First, look in the user provided directory, if given + if (defined env($local_config_envname)) { + @build_file_templates = + map { + if ($^O eq 'VMS') { + # VMS environment variables are logical names, + # which can be used as is + $local_config_envname . ':' . $_; + } else { + catfile(env($local_config_envname), $_); + } + } + @build_file_template_names; + } + # Then, look in our standard directory + push @build_file_templates, + ( map { cleanfile($srcdir, catfile("Configurations", $_), $blddir) } + @build_file_template_names ); + + my $build_file_template; + for $_ (@build_file_templates) { + $build_file_template = $_; + last if -f $build_file_template; + + $build_file_template = undef; + } + if (!defined $build_file_template) { + die "*** Couldn't find any of:\n", join("\n", @build_file_templates), "\n"; + } + $config{build_file_templates} + = [ cleanfile($srcdir, catfile("Configurations", "common0.tmpl"), + $blddir), + $build_file_template, + cleanfile($srcdir, catfile("Configurations", "common.tmpl"), + $blddir) ]; + + my @build_infos = ( [ ".", "build.info" ] ); + foreach (@{$config{dirs}}) { + push @build_infos, [ $_, "build.info" ] + if (-f catfile($srcdir, $_, "build.info")); + } + foreach (@{$config{sdirs}}) { + push @build_infos, [ catdir("crypto", $_), "build.info" ] + if (-f catfile($srcdir, "crypto", $_, "build.info")); + } + foreach (@{$config{engdirs}}) { + push @build_infos, [ catdir("engines", $_), "build.info" ] + if (-f catfile($srcdir, "engines", $_, "build.info")); + } + foreach (@{$config{tdirs}}) { + push @build_infos, [ catdir("test", $_), "build.info" ] + if (-f catfile($srcdir, "test", $_, "build.info")); + } + + $config{build_infos} = [ ]; + + my %ordinals = (); + foreach (@build_infos) { + my $sourced = catdir($srcdir, $_->[0]); + my $buildd = catdir($blddir, $_->[0]); + + mkpath($buildd); + + my $f = $_->[1]; + # The basic things we're trying to build + my @programs = (); + my @programs_install = (); + my @libraries = (); + my @libraries_install = (); + my @engines = (); + my @engines_install = (); + my @scripts = (); + my @scripts_install = (); + my @extra = (); + my @overrides = (); + my @intermediates = (); + my @rawlines = (); + + my %sources = (); + my %shared_sources = (); + my %includes = (); + my %depends = (); + my %renames = (); + my %sharednames = (); + my %generate = (); + + # We want to detect configdata.pm in the source tree, so we + # don't use it if the build tree is different. + my $src_configdata = cleanfile($srcdir, "configdata.pm", $blddir); + + push @{$config{build_infos}}, catfile(abs2rel($sourced, $blddir), $f); + my $template = + Text::Template->new(TYPE => 'FILE', + SOURCE => catfile($sourced, $f), + PREPEND => qq{use lib "$FindBin::Bin/util/perl";}); + die "Something went wrong with $sourced/$f: $!\n" unless $template; + my @text = + split /^/m, + $template->fill_in(HASH => { config => \%config, + target => \%target, + disabled => \%disabled, + withargs => \%withargs, + builddir => abs2rel($buildd, $blddir), + sourcedir => abs2rel($sourced, $blddir), + buildtop => abs2rel($blddir, $blddir), + sourcetop => abs2rel($srcdir, $blddir) }, + DELIMITERS => [ "{-", "-}" ]); + + # The top item of this stack has the following values + # -2 positive already run and we found ELSE (following ELSIF should fail) + # -1 positive already run (skip until ENDIF) + # 0 negatives so far (if we're at a condition, check it) + # 1 last was positive (don't skip lines until next ELSE, ELSIF or ENDIF) + # 2 positive ELSE (following ELSIF should fail) + my @skip = (); + collect_information( + collect_from_array([ @text ], + qr/\\$/ => sub { my $l1 = shift; my $l2 = shift; + $l1 =~ s/\\$//; $l1.$l2 }), + # Info we're looking for + qr/^\s*IF\[((?:\\.|[^\\\]])*)\]\s*$/ + => sub { + if (! @skip || $skip[$#skip] > 0) { + push @skip, !! $1; + } else { + push @skip, -1; + } + }, + qr/^\s*ELSIF\[((?:\\.|[^\\\]])*)\]\s*$/ + => sub { die "ELSIF out of scope" if ! @skip; + die "ELSIF following ELSE" if abs($skip[$#skip]) == 2; + $skip[$#skip] = -1 if $skip[$#skip] != 0; + $skip[$#skip] = !! $1 + if $skip[$#skip] == 0; }, + qr/^\s*ELSE\s*$/ + => sub { die "ELSE out of scope" if ! @skip; + $skip[$#skip] = -2 if $skip[$#skip] != 0; + $skip[$#skip] = 2 if $skip[$#skip] == 0; }, + qr/^\s*ENDIF\s*$/ + => sub { die "ENDIF out of scope" if ! @skip; + pop @skip; }, + qr/^\s*PROGRAMS(_NO_INST)?\s*=\s*(.*)\s*$/ + => sub { + if (!@skip || $skip[$#skip] > 0) { + my $install = $1; + my @x = tokenize($2); + push @programs, @x; + push @programs_install, @x unless $install; + } + }, + qr/^\s*LIBS(_NO_INST)?\s*=\s*(.*)\s*$/ + => sub { + if (!@skip || $skip[$#skip] > 0) { + my $install = $1; + my @x = tokenize($2); + push @libraries, @x; + push @libraries_install, @x unless $install; + } + }, + qr/^\s*ENGINES(_NO_INST)?\s*=\s*(.*)\s*$/ + => sub { + if (!@skip || $skip[$#skip] > 0) { + my $install = $1; + my @x = tokenize($2); + push @engines, @x; + push @engines_install, @x unless $install; + } + }, + qr/^\s*SCRIPTS(_NO_INST)?\s*=\s*(.*)\s*$/ + => sub { + if (!@skip || $skip[$#skip] > 0) { + my $install = $1; + my @x = tokenize($2); + push @scripts, @x; + push @scripts_install, @x unless $install; + } + }, + qr/^\s*EXTRA\s*=\s*(.*)\s*$/ + => sub { push @extra, tokenize($1) + if !@skip || $skip[$#skip] > 0 }, + qr/^\s*OVERRIDES\s*=\s*(.*)\s*$/ + => sub { push @overrides, tokenize($1) + if !@skip || $skip[$#skip] > 0 }, + + qr/^\s*ORDINALS\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/, + => sub { push @{$ordinals{$1}}, tokenize($2) + if !@skip || $skip[$#skip] > 0 }, + qr/^\s*SOURCE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ + => sub { push @{$sources{$1}}, tokenize($2) + if !@skip || $skip[$#skip] > 0 }, + qr/^\s*SHARED_SOURCE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ + => sub { push @{$shared_sources{$1}}, tokenize($2) + if !@skip || $skip[$#skip] > 0 }, + qr/^\s*INCLUDE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ + => sub { push @{$includes{$1}}, tokenize($2) + if !@skip || $skip[$#skip] > 0 }, + qr/^\s*DEPEND\[((?:\\.|[^\\\]])*)\]\s*=\s*(.*)\s*$/ + => sub { push @{$depends{$1}}, tokenize($2) + if !@skip || $skip[$#skip] > 0 }, + qr/^\s*GENERATE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ + => sub { push @{$generate{$1}}, $2 + if !@skip || $skip[$#skip] > 0 }, + qr/^\s*RENAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ + => sub { push @{$renames{$1}}, tokenize($2) + if !@skip || $skip[$#skip] > 0 }, + qr/^\s*SHARED_NAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ + => sub { push @{$sharednames{$1}}, tokenize($2) + if !@skip || $skip[$#skip] > 0 }, + qr/^\s*BEGINRAW\[((?:\\.|[^\\\]])+)\]\s*$/ + => sub { + my $lineiterator = shift; + my $target_kind = $1; + while (defined $lineiterator->()) { + s|\R$||; + if (/^\s*ENDRAW\[((?:\\.|[^\\\]])+)\]\s*$/) { + die "ENDRAW doesn't match BEGINRAW" + if $1 ne $target_kind; + last; + } + next if @skip && $skip[$#skip] <= 0; + push @rawlines, $_ + if ($target_kind eq $target{build_file} + || $target_kind eq $target{build_file}."(".$builder_platform.")"); + } + }, + qr/^\s*(?:#.*)?$/ => sub { }, + "OTHERWISE" => sub { die "Something wrong with this line:\n$_\nat $sourced/$f" }, + "BEFORE" => sub { + if ($buildinfo_debug) { + print STDERR "DEBUG: Parsing ",join(" ", @_),"\n"; + print STDERR "DEBUG: ... before parsing, skip stack is ",join(" ", map { int($_) } @skip),"\n"; + } + }, + "AFTER" => sub { + if ($buildinfo_debug) { + print STDERR "DEBUG: .... after parsing, skip stack is ",join(" ", map { int($_) } @skip),"\n"; + } + }, + ); + die "runaway IF?" if (@skip); + + foreach (keys %renames) { + die "$_ renamed to more than one thing: " + ,join(" ", @{$renames{$_}}),"\n" + if scalar @{$renames{$_}} > 1; + my $dest = cleanfile($buildd, $_, $blddir); + my $to = cleanfile($buildd, $renames{$_}->[0], $blddir); + die "$dest renamed to more than one thing: " + ,$unified_info{rename}->{$dest}, $to + unless !defined($unified_info{rename}->{$dest}) + or $unified_info{rename}->{$dest} eq $to; + $unified_info{rename}->{$dest} = $to; + } + + foreach (@programs) { + my $program = cleanfile($buildd, $_, $blddir); + if ($unified_info{rename}->{$program}) { + $program = $unified_info{rename}->{$program}; + } + $unified_info{programs}->{$program} = 1; + } + + foreach (@programs_install) { + my $program = cleanfile($buildd, $_, $blddir); + if ($unified_info{rename}->{$program}) { + $program = $unified_info{rename}->{$program}; + } + $unified_info{install}->{programs}->{$program} = 1; + } + + foreach (@libraries) { + my $library = cleanfile($buildd, $_, $blddir); + if ($unified_info{rename}->{$library}) { + $library = $unified_info{rename}->{$library}; + } + $unified_info{libraries}->{$library} = 1; + } + + foreach (@libraries_install) { + my $library = cleanfile($buildd, $_, $blddir); + if ($unified_info{rename}->{$library}) { + $library = $unified_info{rename}->{$library}; + } + $unified_info{install}->{libraries}->{$library} = 1; + } + + die <<"EOF" if scalar @engines and !$config{dynamic_engines}; +ENGINES can only be used if configured with 'dynamic-engine'. +This is usually a fault in a build.info file. +EOF + foreach (@engines) { + my $library = cleanfile($buildd, $_, $blddir); + if ($unified_info{rename}->{$library}) { + $library = $unified_info{rename}->{$library}; + } + $unified_info{engines}->{$library} = 1; + } + + foreach (@engines_install) { + my $library = cleanfile($buildd, $_, $blddir); + if ($unified_info{rename}->{$library}) { + $library = $unified_info{rename}->{$library}; + } + $unified_info{install}->{engines}->{$library} = 1; + } + + foreach (@scripts) { + my $script = cleanfile($buildd, $_, $blddir); + if ($unified_info{rename}->{$script}) { + $script = $unified_info{rename}->{$script}; + } + $unified_info{scripts}->{$script} = 1; + } + + foreach (@scripts_install) { + my $script = cleanfile($buildd, $_, $blddir); + if ($unified_info{rename}->{$script}) { + $script = $unified_info{rename}->{$script}; + } + $unified_info{install}->{scripts}->{$script} = 1; + } + + foreach (@extra) { + my $extra = cleanfile($buildd, $_, $blddir); + $unified_info{extra}->{$extra} = 1; + } + + foreach (@overrides) { + my $override = cleanfile($buildd, $_, $blddir); + $unified_info{overrides}->{$override} = 1; + } + + push @{$unified_info{rawlines}}, @rawlines; + + unless ($disabled{shared}) { + # Check sharednames. + foreach (keys %sharednames) { + my $dest = cleanfile($buildd, $_, $blddir); + if ($unified_info{rename}->{$dest}) { + $dest = $unified_info{rename}->{$dest}; + } + die "shared_name for $dest with multiple values: " + ,join(" ", @{$sharednames{$_}}),"\n" + if scalar @{$sharednames{$_}} > 1; + my $to = cleanfile($buildd, $sharednames{$_}->[0], $blddir); + die "shared_name found for a library $dest that isn't defined\n" + unless $unified_info{libraries}->{$dest}; + die "shared_name for $dest with multiple values: " + ,$unified_info{sharednames}->{$dest}, ", ", $to + unless !defined($unified_info{sharednames}->{$dest}) + or $unified_info{sharednames}->{$dest} eq $to; + $unified_info{sharednames}->{$dest} = $to; + } + + # Additionally, we set up sharednames for libraries that don't + # have any, as themselves. Only for libraries that aren't + # explicitly static. + foreach (grep !/\.a$/, keys %{$unified_info{libraries}}) { + if (!defined $unified_info{sharednames}->{$_}) { + $unified_info{sharednames}->{$_} = $_ + } + } + + # Check that we haven't defined any library as both shared and + # explicitly static. That is forbidden. + my @doubles = (); + foreach (grep /\.a$/, keys %{$unified_info{libraries}}) { + (my $l = $_) =~ s/\.a$//; + push @doubles, $l if defined $unified_info{sharednames}->{$l}; + } + die "these libraries are both explicitly static and shared:\n ", + join(" ", @doubles), "\n" + if @doubles; + } + + foreach (keys %sources) { + my $dest = $_; + my $ddest = cleanfile($buildd, $_, $blddir); + if ($unified_info{rename}->{$ddest}) { + $ddest = $unified_info{rename}->{$ddest}; + } + foreach (@{$sources{$dest}}) { + my $s = cleanfile($sourced, $_, $blddir); + + # If it isn't in the source tree, we assume it's generated + # in the build tree + if ($s eq $src_configdata || ! -f $s || $generate{$_}) { + $s = cleanfile($buildd, $_, $blddir); + } + # We recognise C++, C and asm files + if ($s =~ /\.(cc|cpp|c|s|S)$/) { + my $o = $_; + $o =~ s/\.[csS]$/.o/; # C and assembler + $o =~ s/\.(cc|cpp)$/_cc.o/; # C++ + $o = cleanfile($buildd, $o, $blddir); + $unified_info{sources}->{$ddest}->{$o} = 1; + $unified_info{sources}->{$o}->{$s} = 1; + } elsif ($s =~ /\.rc$/) { + # We also recognise resource files + my $o = $_; + $o =~ s/\.rc$/.res/; # Resource configuration + my $o = cleanfile($buildd, $o, $blddir); + $unified_info{sources}->{$ddest}->{$o} = 1; + $unified_info{sources}->{$o}->{$s} = 1; + } else { + $unified_info{sources}->{$ddest}->{$s} = 1; + } + } + } + + foreach (keys %shared_sources) { + my $dest = $_; + my $ddest = cleanfile($buildd, $_, $blddir); + if ($unified_info{rename}->{$ddest}) { + $ddest = $unified_info{rename}->{$ddest}; + } + foreach (@{$shared_sources{$dest}}) { + my $s = cleanfile($sourced, $_, $blddir); + + # If it isn't in the source tree, we assume it's generated + # in the build tree + if ($s eq $src_configdata || ! -f $s || $generate{$_}) { + $s = cleanfile($buildd, $_, $blddir); + } + + if ($s =~ /\.(cc|cpp|c|s|S)$/) { + # We recognise C++, C and asm files + my $o = $_; + $o =~ s/\.[csS]$/.o/; # C and assembler + $o =~ s/\.(cc|cpp)$/_cc.o/; # C++ + $o = cleanfile($buildd, $o, $blddir); + $unified_info{shared_sources}->{$ddest}->{$o} = 1; + $unified_info{sources}->{$o}->{$s} = 1; + } elsif ($s =~ /\.rc$/) { + # We also recognise resource files + my $o = $_; + $o =~ s/\.rc$/.res/; # Resource configuration + my $o = cleanfile($buildd, $o, $blddir); + $unified_info{shared_sources}->{$ddest}->{$o} = 1; + $unified_info{sources}->{$o}->{$s} = 1; + } elsif ($s =~ /\.(def|map|opt)$/) { + # We also recognise .def / .map / .opt files + # We know they are generated files + my $def = cleanfile($buildd, $s, $blddir); + $unified_info{shared_sources}->{$ddest}->{$def} = 1; + } else { + die "unrecognised source file type for shared library: $s\n"; + } + } + } + + foreach (keys %generate) { + my $dest = $_; + my $ddest = cleanfile($buildd, $_, $blddir); + if ($unified_info{rename}->{$ddest}) { + $ddest = $unified_info{rename}->{$ddest}; + } + die "more than one generator for $dest: " + ,join(" ", @{$generate{$_}}),"\n" + if scalar @{$generate{$_}} > 1; + my @generator = split /\s+/, $generate{$dest}->[0]; + $generator[0] = cleanfile($sourced, $generator[0], $blddir), + $unified_info{generate}->{$ddest} = [ @generator ]; + } + + foreach (keys %depends) { + my $dest = $_; + my $ddest = $dest eq "" ? "" : cleanfile($sourced, $_, $blddir); + + # If the destination doesn't exist in source, it can only be + # a generated file in the build tree. + if ($ddest ne "" && ($ddest eq $src_configdata || ! -f $ddest)) { + $ddest = cleanfile($buildd, $_, $blddir); + if ($unified_info{rename}->{$ddest}) { + $ddest = $unified_info{rename}->{$ddest}; + } + } + foreach (@{$depends{$dest}}) { + my $d = cleanfile($sourced, $_, $blddir); + + # If we know it's generated, or assume it is because we can't + # find it in the source tree, we set file we depend on to be + # in the build tree rather than the source tree, and assume + # and that there are lines to build it in a BEGINRAW..ENDRAW + # section or in the Makefile template. + if ($d eq $src_configdata + || ! -f $d + || (grep { $d eq $_ } + map { cleanfile($srcdir, $_, $blddir) } + grep { /\.h$/ } keys %{$unified_info{generate}})) { + $d = cleanfile($buildd, $_, $blddir); + } + # Take note if the file to depend on is being renamed + # Take extra care with files ending with .a, they should + # be treated without that extension, and the extension + # should be added back after treatment. + $d =~ /(\.a)?$/; + my $e = $1 // ""; + $d = $`; + if ($unified_info{rename}->{$d}) { + $d = $unified_info{rename}->{$d}; + } + $d .= $e; + $unified_info{depends}->{$ddest}->{$d} = 1; + } + } + + foreach (keys %includes) { + my $dest = $_; + my $ddest = cleanfile($sourced, $_, $blddir); + + # If the destination doesn't exist in source, it can only be + # a generated file in the build tree. + if ($ddest eq $src_configdata || ! -f $ddest) { + $ddest = cleanfile($buildd, $_, $blddir); + if ($unified_info{rename}->{$ddest}) { + $ddest = $unified_info{rename}->{$ddest}; + } + } + foreach (@{$includes{$dest}}) { + my $is = cleandir($sourced, $_, $blddir); + my $ib = cleandir($buildd, $_, $blddir); + push @{$unified_info{includes}->{$ddest}->{source}}, $is + unless grep { $_ eq $is } @{$unified_info{includes}->{$ddest}->{source}}; + push @{$unified_info{includes}->{$ddest}->{build}}, $ib + unless grep { $_ eq $ib } @{$unified_info{includes}->{$ddest}->{build}}; + } + } + } + + my $ordinals_text = join(', ', sort keys %ordinals); + warn <<"EOF" if $ordinals_text; + +WARNING: ORDINALS were specified for $ordinals_text +They are ignored and should be replaced with a combination of GENERATE, +DEPEND and SHARED_SOURCE. +EOF + + # Massage the result + + # If the user configured no-shared, we allow no shared sources + if ($disabled{shared}) { + foreach (keys %{$unified_info{shared_sources}}) { + foreach (keys %{$unified_info{shared_sources}->{$_}}) { + delete $unified_info{sources}->{$_}; + } + } + $unified_info{shared_sources} = {}; + } + + # If we depend on a header file or a perl module, add an inclusion of + # its directory to allow smoothe inclusion + foreach my $dest (keys %{$unified_info{depends}}) { + next if $dest eq ""; + foreach my $d (keys %{$unified_info{depends}->{$dest}}) { + next unless $d =~ /\.(h|pm)$/; + my $i = dirname($d); + my $spot = + $d eq "configdata.pm" || defined($unified_info{generate}->{$d}) + ? 'build' : 'source'; + push @{$unified_info{includes}->{$dest}->{$spot}}, $i + unless grep { $_ eq $i } @{$unified_info{includes}->{$dest}->{$spot}}; + } + } + + # Trickle down includes placed on libraries, engines and programs to + # their sources (i.e. object files) + foreach my $dest (keys %{$unified_info{engines}}, + keys %{$unified_info{libraries}}, + keys %{$unified_info{programs}}) { + foreach my $k (("source", "build")) { + next unless defined($unified_info{includes}->{$dest}->{$k}); + my @incs = reverse @{$unified_info{includes}->{$dest}->{$k}}; + foreach my $obj (grep /\.o$/, + (keys %{$unified_info{sources}->{$dest} // {}}, + keys %{$unified_info{shared_sources}->{$dest} // {}})) { + foreach my $inc (@incs) { + unshift @{$unified_info{includes}->{$obj}->{$k}}, $inc + unless grep { $_ eq $inc } @{$unified_info{includes}->{$obj}->{$k}}; + } + } + } + delete $unified_info{includes}->{$dest}; + } + + ### Make unified_info a bit more efficient + # One level structures + foreach (("programs", "libraries", "engines", "scripts", "extra", "overrides")) { + $unified_info{$_} = [ sort keys %{$unified_info{$_}} ]; + } + # Two level structures + foreach my $l1 (("install", "sources", "shared_sources", "ldadd", "depends")) { + foreach my $l2 (sort keys %{$unified_info{$l1}}) { + $unified_info{$l1}->{$l2} = + [ sort keys %{$unified_info{$l1}->{$l2}} ]; + } + } + # Includes + foreach my $dest (sort keys %{$unified_info{includes}}) { + if (defined($unified_info{includes}->{$dest}->{build})) { + my @source_includes = (); + @source_includes = ( @{$unified_info{includes}->{$dest}->{source}} ) + if defined($unified_info{includes}->{$dest}->{source}); + $unified_info{includes}->{$dest} = + [ @{$unified_info{includes}->{$dest}->{build}} ]; + foreach my $inc (@source_includes) { + push @{$unified_info{includes}->{$dest}}, $inc + unless grep { $_ eq $inc } @{$unified_info{includes}->{$dest}}; + } + } else { + $unified_info{includes}->{$dest} = + [ @{$unified_info{includes}->{$dest}->{source}} ]; + } + } + + # For convenience collect information regarding directories where + # files are generated, those generated files and the end product + # they end up in where applicable. Then, add build rules for those + # directories + my %loopinfo = ( "lib" => [ @{$unified_info{libraries}} ], + "dso" => [ @{$unified_info{engines}} ], + "bin" => [ @{$unified_info{programs}} ], + "script" => [ @{$unified_info{scripts}} ] ); + foreach my $type (keys %loopinfo) { + foreach my $product (@{$loopinfo{$type}}) { + my %dirs = (); + my $pd = dirname($product); + + foreach (@{$unified_info{sources}->{$product} // []}, + @{$unified_info{shared_sources}->{$product} // []}) { + my $d = dirname($_); + + # We don't want to create targets for source directories + # when building out of source + next if ($config{sourcedir} ne $config{builddir} + && $d =~ m|^\Q$config{sourcedir}\E|); + # We already have a "test" target, and the current directory + # is just silly to make a target for + next if $d eq "test" || $d eq "."; + + $dirs{$d} = 1; + push @{$unified_info{dirinfo}->{$d}->{deps}}, $_ + if $d ne $pd; + } + foreach (keys %dirs) { + push @{$unified_info{dirinfo}->{$_}->{products}->{$type}}, + $product; + } + } + } +} + +# For the schemes that need it, we provide the old *_obj configs +# from the *_asm_obj ones +foreach (grep /_(asm|aux)_src$/, keys %target) { + my $src = $_; + (my $obj = $_) =~ s/_(asm|aux)_src$/_obj/; + $target{$obj} = $target{$src}; + $target{$obj} =~ s/\.[csS]\b/.o/g; # C and assembler + $target{$obj} =~ s/\.(cc|cpp)\b/_cc.o/g; # C++ +} + +# Write down our configuration where it fits ######################### + +print "Creating configdata.pm\n"; +open(OUT,">configdata.pm") || die "unable to create configdata.pm: $!\n"; +print OUT <<"EOF"; +#! $config{HASHBANGPERL} + +package configdata; + +use strict; +use warnings; + +use Exporter; +#use vars qw(\@ISA \@EXPORT); +our \@ISA = qw(Exporter); +our \@EXPORT = qw(\%config \%target \%disabled \%withargs \%unified_info \@disablables); + +EOF +print OUT "our %config = (\n"; +foreach (sort keys %config) { + if (ref($config{$_}) eq "ARRAY") { + print OUT " ", $_, " => [ ", join(", ", + map { quotify("perl", $_) } + @{$config{$_}}), " ],\n"; + } elsif (ref($config{$_}) eq "HASH") { + print OUT " ", $_, " => {"; + if (scalar keys %{$config{$_}} > 0) { + print OUT "\n"; + foreach my $key (sort keys %{$config{$_}}) { + print OUT " ", + join(" => ", + quotify("perl", $key), + defined $config{$_}->{$key} + ? quotify("perl", $config{$_}->{$key}) + : "undef"); + print OUT ",\n"; + } + print OUT " "; + } + print OUT "},\n"; + } else { + print OUT " ", $_, " => ", quotify("perl", $config{$_}), ",\n" + } +} +print OUT <<"EOF"; +); + +EOF +print OUT "our %target = (\n"; +foreach (sort keys %target) { + if (ref($target{$_}) eq "ARRAY") { + print OUT " ", $_, " => [ ", join(", ", + map { quotify("perl", $_) } + @{$target{$_}}), " ],\n"; + } else { + print OUT " ", $_, " => ", quotify("perl", $target{$_}), ",\n" + } +} +print OUT <<"EOF"; +); + +EOF +print OUT "our \%available_protocols = (\n"; +print OUT " tls => [ ", join(", ", map { quotify("perl", $_) } @tls), " ],\n"; +print OUT " dtls => [ ", join(", ", map { quotify("perl", $_) } @dtls), " ],\n"; +print OUT <<"EOF"; +); + +EOF +print OUT "our \@disablables = (\n"; +foreach (@disablables) { + print OUT " ", quotify("perl", $_), ",\n"; +} +print OUT <<"EOF"; +); + +EOF +print OUT "our \%disabled = (\n"; +foreach (sort keys %disabled) { + print OUT " ", quotify("perl", $_), " => ", quotify("perl", $disabled{$_}), ",\n"; +} +print OUT <<"EOF"; +); + +EOF +print OUT "our %withargs = (\n"; +foreach (sort keys %withargs) { + if (ref($withargs{$_}) eq "ARRAY") { + print OUT " ", $_, " => [ ", join(", ", + map { quotify("perl", $_) } + @{$withargs{$_}}), " ],\n"; + } else { + print OUT " ", $_, " => ", quotify("perl", $withargs{$_}), ",\n" + } +} +print OUT <<"EOF"; +); + +EOF +if ($builder eq "unified") { + my $recurse; + $recurse = sub { + my $indent = shift; + foreach (@_) { + if (ref $_ eq "ARRAY") { + print OUT " "x$indent, "[\n"; + foreach (@$_) { + $recurse->($indent + 4, $_); + } + print OUT " "x$indent, "],\n"; + } elsif (ref $_ eq "HASH") { + my %h = %$_; + print OUT " "x$indent, "{\n"; + foreach (sort keys %h) { + if (ref $h{$_} eq "") { + print OUT " "x($indent + 4), quotify("perl", $_), " => ", quotify("perl", $h{$_}), ",\n"; + } else { + print OUT " "x($indent + 4), quotify("perl", $_), " =>\n"; + $recurse->($indent + 8, $h{$_}); + } + } + print OUT " "x$indent, "},\n"; + } else { + print OUT " "x$indent, quotify("perl", $_), ",\n"; + } + } + }; + print OUT "our %unified_info = (\n"; + foreach (sort keys %unified_info) { + if (ref $unified_info{$_} eq "") { + print OUT " "x4, quotify("perl", $_), " => ", quotify("perl", $unified_info{$_}), ",\n"; + } else { + print OUT " "x4, quotify("perl", $_), " =>\n"; + $recurse->(8, $unified_info{$_}); + } + } + print OUT <<"EOF"; +); + +EOF +} +print OUT + "# The following data is only used when this files is use as a script\n"; +print OUT "my \@makevars = (\n"; +foreach (sort keys %user) { + print OUT " '",$_,"',\n"; +} +print OUT ");\n"; +print OUT "my \%disabled_info = (\n"; +foreach my $what (sort keys %disabled_info) { + print OUT " '$what' => {\n"; + foreach my $info (sort keys %{$disabled_info{$what}}) { + if (ref $disabled_info{$what}->{$info} eq 'ARRAY') { + print OUT " $info => [ ", + join(', ', map { "'$_'" } @{$disabled_info{$what}->{$info}}), + " ],\n"; + } else { + print OUT " $info => '", $disabled_info{$what}->{$info}, + "',\n"; + } + } + print OUT " },\n"; +} +print OUT ");\n"; +print OUT 'my @user_crossable = qw( ', join (' ', @user_crossable), " );\n"; +print OUT << 'EOF'; +# If run directly, we can give some answers, and even reconfigure +unless (caller) { + use Getopt::Long; + use File::Spec::Functions; + use File::Basename; + use Pod::Usage; + + my $here = dirname($0); + + my $dump = undef; + my $cmdline = undef; + my $options = undef; + my $target = undef; + my $envvars = undef; + my $makevars = undef; + my $buildparams = undef; + my $reconf = undef; + my $verbose = undef; + my $help = undef; + my $man = undef; + GetOptions('dump|d' => \$dump, + 'command-line|c' => \$cmdline, + 'options|o' => \$options, + 'target|t' => \$target, + 'environment|e' => \$envvars, + 'make-variables|m' => \$makevars, + 'build-parameters|b' => \$buildparams, + 'reconfigure|reconf|r' => \$reconf, + 'verbose|v' => \$verbose, + 'help' => \$help, + 'man' => \$man) + or die "Errors in command line arguments\n"; + + unless ($dump || $cmdline || $options || $target || $envvars || $makevars + || $buildparams || $reconf || $verbose || $help || $man) { + print STDERR <<"_____"; +You must give at least one option. +For more information, do '$0 --help' +_____ + exit(2); + } + + if ($help) { + pod2usage(-exitval => 0, + -verbose => 1); + } + if ($man) { + pod2usage(-exitval => 0, + -verbose => 2); + } + if ($dump || $cmdline) { + print "\nCommand line (with current working directory = $here):\n\n"; + print ' ',join(' ', + $config{PERL}, + catfile($config{sourcedir}, 'Configure'), + @{$config{perlargv}}), "\n"; + print "\nPerl information:\n\n"; + print ' ',$config{perl_cmd},"\n"; + print ' ',$config{perl_version},' for ',$config{perl_archname},"\n"; + } + if ($dump || $options) { + my $longest = 0; + my $longest2 = 0; + foreach my $what (@disablables) { + $longest = length($what) if $longest < length($what); + $longest2 = length($disabled{$what}) + if $disabled{$what} && $longest2 < length($disabled{$what}); + } + print "\nEnabled features:\n\n"; + foreach my $what (@disablables) { + print " $what\n" unless $disabled{$what}; + } + print "\nDisabled features:\n\n"; + foreach my $what (@disablables) { + if ($disabled{$what}) { + print " $what", ' ' x ($longest - length($what) + 1), + "[$disabled{$what}]", ' ' x ($longest2 - length($disabled{$what}) + 1); + print $disabled_info{$what}->{macro} + if $disabled_info{$what}->{macro}; + print ' (skip ', + join(', ', @{$disabled_info{$what}->{skipped}}), + ')' + if $disabled_info{$what}->{skipped}; + print "\n"; + } + } + } + if ($dump || $target) { + print "\nConfig target attributes:\n\n"; + foreach (sort keys %target) { + next if $_ =~ m|^_| || $_ eq 'template'; + my $quotify = sub { + map { (my $x = $_) =~ s|([\\\$\@"])|\\$1|g; "\"$x\""} @_; + }; + print ' ', $_, ' => '; + if (ref($target{$_}) eq "ARRAY") { + print '[ ', join(', ', $quotify->(@{$target{$_}})), " ],\n"; + } else { + print $quotify->($target{$_}), ",\n" + } + } + } + if ($dump || $envvars) { + print "\nRecorded environment:\n\n"; + foreach (sort keys %{$config{perlenv}}) { + print ' ',$_,' = ',($config{perlenv}->{$_} || ''),"\n"; + } + } + if ($dump || $makevars) { + print "\nMakevars:\n\n"; + foreach my $var (@makevars) { + my $prefix = ''; + $prefix = $config{CROSS_COMPILE} + if grep { $var eq $_ } @user_crossable; + $prefix //= ''; + print ' ',$var,' ' x (16 - length $var),'= ', + (ref $config{$var} eq 'ARRAY' + ? join(' ', @{$config{$var}}) + : $prefix.$config{$var}), + "\n" + if defined $config{$var}; + } + + my @buildfile = ($config{builddir}, $config{build_file}); + unshift @buildfile, $here + unless file_name_is_absolute($config{builddir}); + my $buildfile = canonpath(catdir(@buildfile)); + print <<"_____"; + +NOTE: These variables only represent the configuration view. The build file +template may have processed these variables further, please have a look at the +build file for more exact data: + $buildfile +_____ + } + if ($dump || $buildparams) { + my @buildfile = ($config{builddir}, $config{build_file}); + unshift @buildfile, $here + unless file_name_is_absolute($config{builddir}); + print "\nbuild file:\n\n"; + print " ", canonpath(catfile(@buildfile)),"\n"; + + print "\nbuild file templates:\n\n"; + foreach (@{$config{build_file_templates}}) { + my @tmpl = ($_); + unshift @tmpl, $here + unless file_name_is_absolute($config{sourcedir}); + print ' ',canonpath(catfile(@tmpl)),"\n"; + } + } + if ($reconf) { + if ($verbose) { + print 'Reconfiguring with: ', join(' ',@{$config{perlargv}}), "\n"; + foreach (sort keys %{$config{perlenv}}) { + print ' ',$_,' = ',($config{perlenv}->{$_} || ""),"\n"; + } + } + + chdir $here; + exec $^X,catfile($config{sourcedir}, 'Configure'),'reconf'; + } +} + +1; + +__END__ + +=head1 NAME + +configdata.pm - configuration data for OpenSSL builds + +=head1 SYNOPSIS + +Interactive: + + perl configdata.pm [options] + +As data bank module: + + use configdata; + +=head1 DESCRIPTION + +This module can be used in two modes, interactively and as a module containing +all the data recorded by OpenSSL's Configure script. + +When used interactively, simply run it as any perl script, with at least one +option, and you will get the information you ask for. See L below. + +When loaded as a module, you get a few databanks with useful information to +perform build related tasks. The databanks are: + + %config Configured things. + %target The OpenSSL config target with all inheritances + resolved. + %disabled The features that are disabled. + @disablables The list of features that can be disabled. + %withargs All data given through --with-THING options. + %unified_info All information that was computed from the build.info + files. + +=head1 OPTIONS + +=over 4 + +=item B<--help> + +Print a brief help message and exit. + +=item B<--man> + +Print the manual page and exit. + +=item B<--dump> | B<-d> + +Print all relevant configuration data. This is equivalent to B<--command-line> +B<--options> B<--target> B<--environment> B<--make-variables> +B<--build-parameters>. + +=item B<--command-line> | B<-c> + +Print the current configuration command line. + +=item B<--options> | B<-o> + +Print the features, both enabled and disabled, and display defined macro and +skipped directories where applicable. + +=item B<--target> | B<-t> + +Print the config attributes for this config target. + +=item B<--environment> | B<-e> + +Print the environment variables and their values at the time of configuration. + +=item B<--make-variables> | B<-m> + +Print the main make variables generated in the current configuration + +=item B<--build-parameters> | B<-b> + +Print the build parameters, i.e. build file and build file templates. + +=item B<--reconfigure> | B<--reconf> | B<-r> + +Redo the configuration. + +=item B<--verbose> | B<-v> + +Verbose output. + +=back + +=cut + +EOF +close(OUT); +if ($builder_platform eq 'unix') { + my $mode = (0755 & ~umask); + chmod $mode, 'configdata.pm' + or warn sprintf("WARNING: Couldn't change mode for 'configdata.pm' to 0%03o: %s\n",$mode,$!); +} + +my %builders = ( + unified => sub { + print 'Creating ',$target{build_file},"\n"; + run_dofile(catfile($blddir, $target{build_file}), + @{$config{build_file_templates}}); + }, + ); + +$builders{$builder}->($builder_platform, @builder_opts); + +$SIG{__DIE__} = $orig_death_handler; + +print <<"EOF" if ($disabled{threads} eq "unavailable"); + +The library could not be configured for supporting multi-threaded +applications as the compiler options required on this system are not known. +See file INSTALL for details if you need multi-threading. +EOF + +print <<"EOF" if ($no_shared_warn); + +The options 'shared', 'pic' and 'dynamic-engine' aren't supported on this +platform, so we will pretend you gave the option 'no-pic', which also disables +'shared' and 'dynamic-engine'. If you know how to implement shared libraries +or position independent code, please let us know (but please first make sure +you have tried with a current version of OpenSSL). +EOF + +print <<"EOF"; + +********************************************************************** +*** *** +*** OpenSSL has been successfully configured *** +*** *** +*** If you encounter a problem while building, please open an *** +*** issue on GitHub *** +*** and include the output from the following command: *** +*** *** +*** perl configdata.pm --dump *** +*** *** +*** (If you are new to OpenSSL, you might want to consult the *** +*** 'Troubleshooting' section in the INSTALL file first) *** +*** *** +********************************************************************** +EOF + +exit(0); + +###################################################################### +# +# Helpers and utility functions +# + +# Death handler, to print a helpful message in case of failure ####### +# +sub death_handler { + die @_ if $^S; # To prevent the added message in eval blocks + my $build_file = $target{build_file} // "build file"; + my @message = ( <<"_____", @_ ); + +Failure! $build_file wasn't produced. +Please read INSTALL and associated NOTES files. You may also have to look over +your available compiler tool chain or change your configuration. + +_____ + + # Dying is terminal, so it's ok to reset the signal handler here. + $SIG{__DIE__} = $orig_death_handler; + die @message; +} + +# Configuration file reading ######################################### + +# Note: All of the helper functions are for lazy evaluation. They all +# return a CODE ref, which will return the intended value when evaluated. +# Thus, whenever there's mention of a returned value, it's about that +# intended value. + +# Helper function to implement conditional inheritance depending on the +# value of $disabled{asm}. Used in inherit_from values as follows: +# +# inherit_from => [ "template", asm("asm_tmpl") ] +# +sub asm { + my @x = @_; + sub { + $disabled{asm} ? () : @x; + } +} + +# Helper function to implement conditional value variants, with a default +# plus additional values based on the value of $config{build_type}. +# Arguments are given in hash table form: +# +# picker(default => "Basic string: ", +# debug => "debug", +# release => "release") +# +# When configuring with --debug, the resulting string will be +# "Basic string: debug", and when not, it will be "Basic string: release" +# +# This can be used to create variants of sets of flags according to the +# build type: +# +# cflags => picker(default => "-Wall", +# debug => "-g -O0", +# release => "-O3") +# +sub picker { + my %opts = @_; + return sub { add($opts{default} || (), + $opts{$config{build_type}} || ())->(); } +} + +# Helper function to combine several values of different types into one. +# This is useful if you want to combine a string with the result of a +# lazy function, such as: +# +# cflags => combine("-Wall", sub { $disabled{zlib} ? () : "-DZLIB" }) +# +sub combine { + my @stuff = @_; + return sub { add(@stuff)->(); } +} + +# Helper function to implement conditional values depending on the value +# of $disabled{threads}. Can be used as follows: +# +# cflags => combine("-Wall", threads("-pthread")) +# +sub threads { + my @flags = @_; + return sub { add($disabled{threads} ? () : @flags)->(); } +} + +sub shared { + my @flags = @_; + return sub { add($disabled{shared} ? () : @flags)->(); } +} + +our $add_called = 0; +# Helper function to implement adding values to already existing configuration +# values. It handles elements that are ARRAYs, CODEs and scalars +sub _add { + my $separator = shift; + + # If there's any ARRAY in the collection of values OR the separator + # is undef, we will return an ARRAY of combined values, otherwise a + # string of joined values with $separator as the separator. + my $found_array = !defined($separator); + + my @values = + map { + my $res = $_; + while (ref($res) eq "CODE") { + $res = $res->(); + } + if (defined($res)) { + if (ref($res) eq "ARRAY") { + $found_array = 1; + @$res; + } else { + $res; + } + } else { + (); + } + } (@_); + + $add_called = 1; + + if ($found_array) { + [ @values ]; + } else { + join($separator, grep { defined($_) && $_ ne "" } @values); + } +} +sub add_before { + my $separator = " "; + if (ref($_[$#_]) eq "HASH") { + my $opts = pop; + $separator = $opts->{separator}; + } + my @x = @_; + sub { _add($separator, @x, @_) }; +} +sub add { + my $separator = " "; + if (ref($_[$#_]) eq "HASH") { + my $opts = pop; + $separator = $opts->{separator}; + } + my @x = @_; + sub { _add($separator, @_, @x) }; +} + +sub read_eval_file { + my $fname = shift; + my $content; + my @result; + + open F, "< $fname" or die "Can't open '$fname': $!\n"; + { + undef local $/; + $content = ; + } + close F; + { + local $@; + + @result = ( eval $content ); + warn $@ if $@; + } + return wantarray ? @result : $result[0]; +} + +# configuration reader, evaluates the input file as a perl script and expects +# it to fill %targets with target configurations. Those are then added to +# %table. +sub read_config { + my $fname = shift; + my %targets; + + { + # Protect certain tables from tampering + local %table = (); + + %targets = read_eval_file($fname); + } + my %preexisting = (); + foreach (sort keys %targets) { + $preexisting{$_} = 1 if $table{$_}; + } + die <<"EOF", +The following config targets from $fname +shadow pre-existing config targets with the same name: +EOF + map { " $_\n" } sort keys %preexisting + if %preexisting; + + + # For each target, check that it's configured with a hash table. + foreach (keys %targets) { + if (ref($targets{$_}) ne "HASH") { + if (ref($targets{$_}) eq "") { + warn "Deprecated target configuration for $_, ignoring...\n"; + } else { + warn "Misconfigured target configuration for $_ (should be a hash table), ignoring...\n"; + } + delete $targets{$_}; + } else { + $targets{$_}->{_conf_fname_int} = add([ $fname ]); + } + } + + %table = (%table, %targets); + +} + +# configuration resolver. Will only resolve all the lazy evaluation +# codeblocks for the chosen target and all those it inherits from, +# recursively +sub resolve_config { + my $target = shift; + my @breadcrumbs = @_; + +# my $extra_checks = defined($ENV{CONFIGURE_EXTRA_CHECKS}); + + if (grep { $_ eq $target } @breadcrumbs) { + die "inherit_from loop! target backtrace:\n " + ,$target,"\n ",join("\n ", @breadcrumbs),"\n"; + } + + if (!defined($table{$target})) { + warn "Warning! target $target doesn't exist!\n"; + return (); + } + # Recurse through all inheritances. They will be resolved on the + # fly, so when this operation is done, they will all just be a + # bunch of attributes with string values. + # What we get here, though, are keys with references to lists of + # the combined values of them all. We will deal with lists after + # this stage is done. + my %combined_inheritance = (); + if ($table{$target}->{inherit_from}) { + my @inherit_from = + map { ref($_) eq "CODE" ? $_->() : $_ } @{$table{$target}->{inherit_from}}; + foreach (@inherit_from) { + my %inherited_config = resolve_config($_, $target, @breadcrumbs); + + # 'template' is a marker that's considered private to + # the config that had it. + delete $inherited_config{template}; + + foreach (keys %inherited_config) { + if (!$combined_inheritance{$_}) { + $combined_inheritance{$_} = []; + } + push @{$combined_inheritance{$_}}, $inherited_config{$_}; + } + } + } + + # We won't need inherit_from in this target any more, since we've + # resolved all the inheritances that lead to this + delete $table{$target}->{inherit_from}; + + # Now is the time to deal with those lists. Here's the place to + # decide what shall be done with those lists, all based on the + # values of the target we're currently dealing with. + # - If a value is a coderef, it will be executed with the list of + # inherited values as arguments. + # - If the corresponding key doesn't have a value at all or is the + # empty string, the inherited value list will be run through the + # default combiner (below), and the result becomes this target's + # value. + # - Otherwise, this target's value is assumed to be a string that + # will simply override the inherited list of values. + my $default_combiner = add(); + + my %all_keys = + map { $_ => 1 } (keys %combined_inheritance, + keys %{$table{$target}}); + + sub process_values { + my $object = shift; + my $inherited = shift; # Always a [ list ] + my $target = shift; + my $entry = shift; + + $add_called = 0; + + while(ref($object) eq "CODE") { + $object = $object->(@$inherited); + } + if (!defined($object)) { + return (); + } + elsif (ref($object) eq "ARRAY") { + local $add_called; # To make sure recursive calls don't affect it + return [ map { process_values($_, $inherited, $target, $entry) } + @$object ]; + } elsif (ref($object) eq "") { + return $object; + } else { + die "cannot handle reference type ",ref($object) + ," found in target ",$target," -> ",$entry,"\n"; + } + } + + foreach (sort keys %all_keys) { + my $previous = $combined_inheritance{$_}; + + # Current target doesn't have a value for the current key? + # Assign it the default combiner, the rest of this loop body + # will handle it just like any other coderef. + if (!exists $table{$target}->{$_}) { + $table{$target}->{$_} = $default_combiner; + } + + $table{$target}->{$_} = process_values($table{$target}->{$_}, + $combined_inheritance{$_}, + $target, $_); + unless(defined($table{$target}->{$_})) { + delete $table{$target}->{$_}; + } +# if ($extra_checks && +# $previous && !($add_called || $previous ~~ $table{$target}->{$_})) { +# warn "$_ got replaced in $target\n"; +# } + } + + # Finally done, return the result. + return %{$table{$target}}; +} + +sub usage + { + print STDERR $usage; + print STDERR "\npick os/compiler from:\n"; + my $j=0; + my $i; + my $k=0; + foreach $i (sort keys %table) + { + next if $table{$i}->{template}; + next if $i =~ /^debug/; + $k += length($i) + 1; + if ($k > 78) + { + print STDERR "\n"; + $k=length($i); + } + print STDERR $i . " "; + } + foreach $i (sort keys %table) + { + next if $table{$i}->{template}; + next if $i !~ /^debug/; + $k += length($i) + 1; + if ($k > 78) + { + print STDERR "\n"; + $k=length($i); + } + print STDERR $i . " "; + } + print STDERR "\n\nNOTE: If in doubt, on Unix-ish systems use './config'.\n"; + exit(1); + } + +sub run_dofile +{ + my $out = shift; + my @templates = @_; + + unlink $out || warn "Can't remove $out, $!" + if -f $out; + foreach (@templates) { + die "Can't open $_, $!" unless -f $_; + } + my $perlcmd = (quotify("maybeshell", $config{PERL}))[0]; + my $cmd = "$perlcmd \"-I.\" \"-Mconfigdata\" \"$dofile\" -o\"Configure\" \"".join("\" \"",@templates)."\" > \"$out.new\""; + #print STDERR "DEBUG[run_dofile]: \$cmd = $cmd\n"; + system($cmd); + exit 1 if $? != 0; + rename("$out.new", $out) || die "Can't rename $out.new, $!"; +} + +sub compiler_predefined { + state %predefined; + my $cc = shift; + + return () if $^O eq 'VMS'; + + die 'compiler_predefined called without a compiler command' + unless $cc; + + if (! $predefined{$cc}) { + + $predefined{$cc} = {}; + + # collect compiler pre-defines from gcc or gcc-alike... + open(PIPE, "$cc -dM -E -x c /dev/null 2>&1 |"); + while (my $l = ) { + $l =~ m/^#define\s+(\w+(?:\(\w+\))?)(?:\s+(.+))?/ or last; + $predefined{$cc}->{$1} = $2 // ''; + } + close(PIPE); + } + + return %{$predefined{$cc}}; +} + +sub which +{ + my ($name)=@_; + + if (eval { require IPC::Cmd; 1; }) { + IPC::Cmd->import(); + return scalar IPC::Cmd::can_run($name); + } else { + # if there is $directories component in splitpath, + # then it's not something to test with $PATH... + return $name if (File::Spec->splitpath($name))[1]; + + foreach (File::Spec->path()) { + my $fullpath = catfile($_, "$name$target{exe_extension}"); + if (-f $fullpath and -x $fullpath) { + return $fullpath; + } + } + } +} + +sub env +{ + my $name = shift; + my %opts = @_; + + unless ($opts{cacheonly}) { + # Note that if $ENV{$name} doesn't exist or is undefined, + # $config{perlenv}->{$name} will be created with the value + # undef. This is intentional. + + $config{perlenv}->{$name} = $ENV{$name} + if ! exists $config{perlenv}->{$name}; + } + return $config{perlenv}->{$name}; +} + +# Configuration printer ############################################## + +sub print_table_entry +{ + local $now_printing = shift; + my %target = resolve_config($now_printing); + my $type = shift; + + # Don't print the templates + return if $target{template}; + + my @sequence = ( + "sys_id", + "cpp", + "cppflags", + "defines", + "includes", + "cc", + "cflags", + "unistd", + "ld", + "lflags", + "loutflag", + "ex_libs", + "bn_ops", + "apps_aux_src", + "cpuid_asm_src", + "uplink_aux_src", + "bn_asm_src", + "ec_asm_src", + "des_asm_src", + "aes_asm_src", + "bf_asm_src", + "md5_asm_src", + "cast_asm_src", + "sha1_asm_src", + "rc4_asm_src", + "rmd160_asm_src", + "rc5_asm_src", + "wp_asm_src", + "cmll_asm_src", + "modes_asm_src", + "padlock_asm_src", + "chacha_asm_src", + "poly1035_asm_src", + "thread_scheme", + "perlasm_scheme", + "dso_scheme", + "shared_target", + "shared_cflag", + "shared_defines", + "shared_ldflag", + "shared_rcflag", + "shared_extension", + "dso_extension", + "obj_extension", + "exe_extension", + "ranlib", + "ar", + "arflags", + "aroutflag", + "rc", + "rcflags", + "rcoutflag", + "mt", + "mtflags", + "mtinflag", + "mtoutflag", + "multilib", + "build_scheme", + ); + + if ($type eq "TABLE") { + print "\n"; + print "*** $now_printing\n"; + foreach (@sequence) { + if (ref($target{$_}) eq "ARRAY") { + printf "\$%-12s = %s\n", $_, join(" ", @{$target{$_}}); + } else { + printf "\$%-12s = %s\n", $_, $target{$_}; + } + } + } elsif ($type eq "HASH") { + my $largest = + length((sort { length($a) <=> length($b) } @sequence)[-1]); + print " '$now_printing' => {\n"; + foreach (@sequence) { + if ($target{$_}) { + if (ref($target{$_}) eq "ARRAY") { + print " '",$_,"'"," " x ($largest - length($_))," => [ ",join(", ", map { "'$_'" } @{$target{$_}})," ],\n"; + } else { + print " '",$_,"'"," " x ($largest - length($_))," => '",$target{$_},"',\n"; + } + } + } + print " },\n"; + } +} + +# Utility routines ################################################### + +# On VMS, if the given file is a logical name, File::Spec::Functions +# will consider it an absolute path. There are cases when we want a +# purely syntactic check without checking the environment. +sub isabsolute { + my $file = shift; + + # On non-platforms, we just use file_name_is_absolute(). + return file_name_is_absolute($file) unless $^O eq "VMS"; + + # If the file spec includes a device or a directory spec, + # file_name_is_absolute() is perfectly safe. + return file_name_is_absolute($file) if $file =~ m|[:\[]|; + + # Here, we know the given file spec isn't absolute + return 0; +} + +# Makes a directory absolute and cleans out /../ in paths like foo/../bar +# On some platforms, this uses rel2abs(), while on others, realpath() is used. +# realpath() requires that at least all path components except the last is an +# existing directory. On VMS, the last component of the directory spec must +# exist. +sub absolutedir { + my $dir = shift; + + # realpath() is quite buggy on VMS. It uses LIB$FID_TO_NAME, which + # will return the volume name for the device, no matter what. Also, + # it will return an incorrect directory spec if the argument is a + # directory that doesn't exist. + if ($^O eq "VMS") { + return rel2abs($dir); + } + + # We use realpath() on Unix, since no other will properly clean out + # a directory spec. + use Cwd qw/realpath/; + + return realpath($dir); +} + +sub quotify { + my %processors = ( + perl => sub { my $x = shift; + $x =~ s/([\\\$\@"])/\\$1/g; + return '"'.$x.'"'; }, + maybeshell => sub { my $x = shift; + (my $y = $x) =~ s/([\\\"])/\\$1/g; + if ($x ne $y || $x =~ m|\s|) { + return '"'.$y.'"'; + } else { + return $x; + } + }, + ); + my $for = shift; + my $processor = + defined($processors{$for}) ? $processors{$for} : sub { shift; }; + + return map { $processor->($_); } @_; +} + +# collect_from_file($filename, $line_concat_cond_re, $line_concat) +# $filename is a file name to read from +# $line_concat_cond_re is a regexp detecting a line continuation ending +# $line_concat is a CODEref that takes care of concatenating two lines +sub collect_from_file { + my $filename = shift; + my $line_concat_cond_re = shift; + my $line_concat = shift; + + open my $fh, $filename || die "unable to read $filename: $!\n"; + return sub { + my $saved_line = ""; + $_ = ""; + while (<$fh>) { + s|\R$||; + if (defined $line_concat) { + $_ = $line_concat->($saved_line, $_); + $saved_line = ""; + } + if (defined $line_concat_cond_re && /$line_concat_cond_re/) { + $saved_line = $_; + next; + } + return $_; + } + die "$filename ending with continuation line\n" if $_; + close $fh; + return undef; + } +} + +# collect_from_array($array, $line_concat_cond_re, $line_concat) +# $array is an ARRAYref of lines +# $line_concat_cond_re is a regexp detecting a line continuation ending +# $line_concat is a CODEref that takes care of concatenating two lines +sub collect_from_array { + my $array = shift; + my $line_concat_cond_re = shift; + my $line_concat = shift; + my @array = (@$array); + + return sub { + my $saved_line = ""; + $_ = ""; + while (defined($_ = shift @array)) { + s|\R$||; + if (defined $line_concat) { + $_ = $line_concat->($saved_line, $_); + $saved_line = ""; + } + if (defined $line_concat_cond_re && /$line_concat_cond_re/) { + $saved_line = $_; + next; + } + return $_; + } + die "input text ending with continuation line\n" if $_; + return undef; + } +} + +# collect_information($lineiterator, $line_continue, $regexp => $CODEref, ...) +# $lineiterator is a CODEref that delivers one line at a time. +# All following arguments are regex/CODEref pairs, where the regexp detects a +# line and the CODEref does something with the result of the regexp. +sub collect_information { + my $lineiterator = shift; + my %collectors = @_; + + while(defined($_ = $lineiterator->())) { + s|\R$||; + my $found = 0; + if ($collectors{"BEFORE"}) { + $collectors{"BEFORE"}->($_); + } + foreach my $re (keys %collectors) { + if ($re !~ /^OTHERWISE|BEFORE|AFTER$/ && /$re/) { + $collectors{$re}->($lineiterator); + $found = 1; + }; + } + if ($collectors{"OTHERWISE"}) { + $collectors{"OTHERWISE"}->($lineiterator, $_) + unless $found || !defined $collectors{"OTHERWISE"}; + } + if ($collectors{"AFTER"}) { + $collectors{"AFTER"}->($_); + } + } +} + +# tokenize($line) +# $line is a line of text to split up into tokens +# returns a list of tokens +# +# Tokens are divided by spaces. If the tokens include spaces, they +# have to be quoted with single or double quotes. Double quotes +# inside a double quoted token must be escaped. Escaping is done +# with backslash. +# Basically, the same quoting rules apply for " and ' as in any +# Unix shell. +sub tokenize { + my $line = my $debug_line = shift; + my @result = (); + + while ($line =~ s|^\s+||, $line ne "") { + my $token = ""; + while ($line ne "" && $line !~ m|^\s|) { + if ($line =~ m/^"((?:[^"\\]+|\\.)*)"/) { + $token .= $1; + $line = $'; + } elsif ($line =~ m/^'([^']*)'/) { + $token .= $1; + $line = $'; + } elsif ($line =~ m/^(\S+)/) { + $token .= $1; + $line = $'; + } + } + push @result, $token; + } + + if ($ENV{CONFIGURE_DEBUG_TOKENIZE}) { + print STDERR "DEBUG[tokenize]: Parsed '$debug_line' into:\n"; + print STDERR "DEBUG[tokenize]: ('", join("', '", @result), "')\n"; + } + return @result; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/LICENSE b/trunk/3rdparty/openssl-1.1-fit/LICENSE new file mode 100644 index 000000000..9601ab435 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/LICENSE @@ -0,0 +1,125 @@ + + LICENSE ISSUES + ============== + + The OpenSSL toolkit stays under a double license, i.e. both the conditions of + the OpenSSL License and the original SSLeay license apply to the toolkit. + See below for the actual license texts. + + OpenSSL License + --------------- + +/* ==================================================================== + * Copyright (c) 1998-2019 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + + Original SSLeay License + ----------------------- + +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + diff --git a/trunk/3rdparty/openssl-1.1-fit/README.md b/trunk/3rdparty/openssl-1.1-fit/README.md new file mode 100644 index 000000000..d7c5dbc2f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/README.md @@ -0,0 +1,3 @@ + +For openssl-1.1.1b.tar.gz + diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/CA.pl.in b/trunk/3rdparty/openssl-1.1-fit/apps/CA.pl.in new file mode 100644 index 000000000..db3cc3831 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/CA.pl.in @@ -0,0 +1,214 @@ +#!{- $config{HASHBANGPERL} -} +# Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# Wrapper around the ca to make it easier to use +# +# {- join("\n# ", @autowarntext) -} + +use strict; +use warnings; + +my $openssl = "openssl"; +if(defined $ENV{'OPENSSL'}) { + $openssl = $ENV{'OPENSSL'}; +} else { + $ENV{'OPENSSL'} = $openssl; +} + +my $verbose = 1; + +my $OPENSSL_CONFIG = $ENV{"OPENSSL_CONFIG"} || ""; +my $DAYS = "-days 365"; +my $CADAYS = "-days 1095"; # 3 years +my $REQ = "$openssl req $OPENSSL_CONFIG"; +my $CA = "$openssl ca $OPENSSL_CONFIG"; +my $VERIFY = "$openssl verify"; +my $X509 = "$openssl x509"; +my $PKCS12 = "$openssl pkcs12"; + +# default openssl.cnf file has setup as per the following +my $CATOP = "./demoCA"; +my $CAKEY = "cakey.pem"; +my $CAREQ = "careq.pem"; +my $CACERT = "cacert.pem"; +my $CACRL = "crl.pem"; +my $DIRMODE = 0777; + +my $NEWKEY = "newkey.pem"; +my $NEWREQ = "newreq.pem"; +my $NEWCERT = "newcert.pem"; +my $NEWP12 = "newcert.p12"; +my $RET = 0; +my $WHAT = shift @ARGV || ""; +my @OPENSSL_CMDS = ("req", "ca", "pkcs12", "x509", "verify"); +my %EXTRA = extra_args(\@ARGV, "-extra-"); +my $FILE; + +sub extra_args { + my ($args_ref, $arg_prefix) = @_; + my %eargs = map { + if ($_ < $#$args_ref) { + my ($arg, $value) = splice(@$args_ref, $_, 2); + $arg =~ s/$arg_prefix//; + ($arg, $value); + } else { + (); + } + } reverse grep($$args_ref[$_] =~ /$arg_prefix/, 0..$#$args_ref); + my %empty = map { ($_, "") } @OPENSSL_CMDS; + return (%empty, %eargs); +} + +# See if reason for a CRL entry is valid; exit if not. +sub crl_reason_ok +{ + my $r = shift; + + if ($r eq 'unspecified' || $r eq 'keyCompromise' + || $r eq 'CACompromise' || $r eq 'affiliationChanged' + || $r eq 'superseded' || $r eq 'cessationOfOperation' + || $r eq 'certificateHold' || $r eq 'removeFromCRL') { + return 1; + } + print STDERR "Invalid CRL reason; must be one of:\n"; + print STDERR " unspecified, keyCompromise, CACompromise,\n"; + print STDERR " affiliationChanged, superseded, cessationOfOperation\n"; + print STDERR " certificateHold, removeFromCRL"; + exit 1; +} + +# Copy a PEM-format file; return like exit status (zero means ok) +sub copy_pemfile +{ + my ($infile, $outfile, $bound) = @_; + my $found = 0; + + open IN, $infile || die "Cannot open $infile, $!"; + open OUT, ">$outfile" || die "Cannot write to $outfile, $!"; + while () { + $found = 1 if /^-----BEGIN.*$bound/; + print OUT $_ if $found; + $found = 2, last if /^-----END.*$bound/; + } + close IN; + close OUT; + return $found == 2 ? 0 : 1; +} + +# Wrapper around system; useful for debugging. Returns just the exit status +sub run +{ + my $cmd = shift; + print "====\n$cmd\n" if $verbose; + my $status = system($cmd); + print "==> $status\n====\n" if $verbose; + return $status >> 8; +} + + +if ( $WHAT =~ /^(-\?|-h|-help)$/ ) { + print STDERR "usage: CA.pl -newcert | -newreq | -newreq-nodes | -xsign | -sign | -signCA | -signcert | -crl | -newca [-extra-cmd extra-params]\n"; + print STDERR " CA.pl -pkcs12 [-extra-pkcs12 extra-params] [certname]\n"; + print STDERR " CA.pl -verify [-extra-verify extra-params] certfile ...\n"; + print STDERR " CA.pl -revoke [-extra-ca extra-params] certfile [reason]\n"; + exit 0; +} +if ($WHAT eq '-newcert' ) { + # create a certificate + $RET = run("$REQ -new -x509 -keyout $NEWKEY -out $NEWCERT $DAYS $EXTRA{req}"); + print "Cert is in $NEWCERT, private key is in $NEWKEY\n" if $RET == 0; +} elsif ($WHAT eq '-precert' ) { + # create a pre-certificate + $RET = run("$REQ -x509 -precert -keyout $NEWKEY -out $NEWCERT $DAYS"); + print "Pre-cert is in $NEWCERT, private key is in $NEWKEY\n" if $RET == 0; +} elsif ($WHAT =~ /^\-newreq(\-nodes)?$/ ) { + # create a certificate request + $RET = run("$REQ -new $1 -keyout $NEWKEY -out $NEWREQ $DAYS $EXTRA{req}"); + print "Request is in $NEWREQ, private key is in $NEWKEY\n" if $RET == 0; +} elsif ($WHAT eq '-newca' ) { + # create the directory hierarchy + mkdir ${CATOP}, $DIRMODE; + mkdir "${CATOP}/certs", $DIRMODE; + mkdir "${CATOP}/crl", $DIRMODE ; + mkdir "${CATOP}/newcerts", $DIRMODE; + mkdir "${CATOP}/private", $DIRMODE; + open OUT, ">${CATOP}/index.txt"; + close OUT; + open OUT, ">${CATOP}/crlnumber"; + print OUT "01\n"; + close OUT; + # ask user for existing CA certificate + print "CA certificate filename (or enter to create)\n"; + $FILE = "" unless defined($FILE = ); + $FILE =~ s{\R$}{}; + if ($FILE ne "") { + copy_pemfile($FILE,"${CATOP}/private/$CAKEY", "PRIVATE"); + copy_pemfile($FILE,"${CATOP}/$CACERT", "CERTIFICATE"); + } else { + print "Making CA certificate ...\n"; + $RET = run("$REQ -new -keyout" + . " ${CATOP}/private/$CAKEY" + . " -out ${CATOP}/$CAREQ $EXTRA{req}"); + $RET = run("$CA -create_serial" + . " -out ${CATOP}/$CACERT $CADAYS -batch" + . " -keyfile ${CATOP}/private/$CAKEY -selfsign" + . " -extensions v3_ca $EXTRA{ca}" + . " -infiles ${CATOP}/$CAREQ") if $RET == 0; + print "CA certificate is in ${CATOP}/$CACERT\n" if $RET == 0; + } +} elsif ($WHAT eq '-pkcs12' ) { + my $cname = $ARGV[0]; + $cname = "My Certificate" unless defined $cname; + $RET = run("$PKCS12 -in $NEWCERT -inkey $NEWKEY" + . " -certfile ${CATOP}/$CACERT" + . " -out $NEWP12" + . " -export -name \"$cname\" $EXTRA{pkcs12}"); + print "PKCS #12 file is in $NEWP12\n" if $RET == 0; +} elsif ($WHAT eq '-xsign' ) { + $RET = run("$CA -policy policy_anything $EXTRA{ca} -infiles $NEWREQ"); +} elsif ($WHAT eq '-sign' ) { + $RET = run("$CA -policy policy_anything -out $NEWCERT $EXTRA{ca} -infiles $NEWREQ"); + print "Signed certificate is in $NEWCERT\n" if $RET == 0; +} elsif ($WHAT eq '-signCA' ) { + $RET = run("$CA -policy policy_anything -out $NEWCERT" + . " -extensions v3_ca $EXTRA{ca} -infiles $NEWREQ"); + print "Signed CA certificate is in $NEWCERT\n" if $RET == 0; +} elsif ($WHAT eq '-signcert' ) { + $RET = run("$X509 -x509toreq -in $NEWREQ -signkey $NEWREQ" + . " -out tmp.pem $EXTRA{x509}"); + $RET = run("$CA -policy policy_anything -out $NEWCERT" + . "$EXTRA{ca} -infiles tmp.pem") if $RET == 0; + print "Signed certificate is in $NEWCERT\n" if $RET == 0; +} elsif ($WHAT eq '-verify' ) { + my @files = @ARGV ? @ARGV : ( $NEWCERT ); + my $file; + foreach $file (@files) { + my $status = run("$VERIFY \"-CAfile\" ${CATOP}/$CACERT $file $EXTRA{verify}"); + $RET = $status if $status != 0; + } +} elsif ($WHAT eq '-crl' ) { + $RET = run("$CA -gencrl -out ${CATOP}/crl/$CACRL $EXTRA{ca}"); + print "Generated CRL is in ${CATOP}/crl/$CACRL\n" if $RET == 0; +} elsif ($WHAT eq '-revoke' ) { + my $cname = $ARGV[0]; + if (!defined $cname) { + print "Certificate filename is required; reason optional.\n"; + exit 1; + } + my $reason = $ARGV[1]; + $reason = " -crl_reason $reason" + if defined $reason && crl_reason_ok($reason); + $RET = run("$CA -revoke \"$cname\"" . $reason . $EXTRA{ca}); +} else { + print STDERR "Unknown arg \"$WHAT\"\n"; + print STDERR "Use -help for help.\n"; + exit 1; +} + +exit $RET; diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/app_rand.c b/trunk/3rdparty/openssl-1.1-fit/apps/app_rand.c new file mode 100644 index 000000000..2b0bbde03 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/app_rand.c @@ -0,0 +1,93 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "apps.h" +#include +#include +#include +#include + +static char *save_rand_file; + +void app_RAND_load_conf(CONF *c, const char *section) +{ + const char *randfile = NCONF_get_string(c, section, "RANDFILE"); + + if (randfile == NULL) { + ERR_clear_error(); + return; + } + if (RAND_load_file(randfile, -1) < 0) { + BIO_printf(bio_err, "Can't load %s into RNG\n", randfile); + ERR_print_errors(bio_err); + } + if (save_rand_file == NULL) + save_rand_file = OPENSSL_strdup(randfile); +} + +static int loadfiles(char *name) +{ + char *p; + int last, ret = 1; + + for ( ; ; ) { + last = 0; + for (p = name; *p != '\0' && *p != LIST_SEPARATOR_CHAR; p++) + continue; + if (*p == '\0') + last = 1; + *p = '\0'; + if (RAND_load_file(name, -1) < 0) { + BIO_printf(bio_err, "Can't load %s into RNG\n", name); + ERR_print_errors(bio_err); + ret = 0; + } + if (last) + break; + name = p + 1; + if (*name == '\0') + break; + } + return ret; +} + +void app_RAND_write(void) +{ + if (save_rand_file == NULL) + return; + if (RAND_write_file(save_rand_file) == -1) { + BIO_printf(bio_err, "Cannot write random bytes:\n"); + ERR_print_errors(bio_err); + } + OPENSSL_free(save_rand_file); + save_rand_file = NULL; +} + + +/* + * See comments in opt_verify for explanation of this. + */ +enum r_range { OPT_R_ENUM }; + +int opt_rand(int opt) +{ + switch ((enum r_range)opt) { + case OPT_R__FIRST: + case OPT_R__LAST: + break; + case OPT_R_RAND: + return loadfiles(opt_arg()); + break; + case OPT_R_WRITERAND: + OPENSSL_free(save_rand_file); + save_rand_file = OPENSSL_strdup(opt_arg()); + break; + } + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/apps.c b/trunk/3rdparty/openssl-1.1-fit/apps/apps.c new file mode 100644 index 000000000..36cb0b278 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/apps.c @@ -0,0 +1,2752 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS) +/* + * On VMS, you need to define this to get the declaration of fileno(). The + * value 2 is to make sure no function defined in POSIX-2 is left undefined. + */ +# define _POSIX_C_SOURCE 2 +#endif + +#include +#include +#include +#include +#ifndef OPENSSL_NO_POSIX_IO +# include +# include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef OPENSSL_NO_ENGINE +# include +#endif +#ifndef OPENSSL_NO_RSA +# include +#endif +#include +#include +#include "s_apps.h" +#include "apps.h" + +#ifdef _WIN32 +static int WIN32_rename(const char *from, const char *to); +# define rename(from,to) WIN32_rename((from),(to)) +#endif + +typedef struct { + const char *name; + unsigned long flag; + unsigned long mask; +} NAME_EX_TBL; + +static UI_METHOD *ui_method = NULL; +static const UI_METHOD *ui_fallback_method = NULL; + +static int set_table_opts(unsigned long *flags, const char *arg, + const NAME_EX_TBL * in_tbl); +static int set_multi_opts(unsigned long *flags, const char *arg, + const NAME_EX_TBL * in_tbl); + +int app_init(long mesgwin); + +int chopup_args(ARGS *arg, char *buf) +{ + int quoted; + char c = '\0', *p = NULL; + + arg->argc = 0; + if (arg->size == 0) { + arg->size = 20; + arg->argv = app_malloc(sizeof(*arg->argv) * arg->size, "argv space"); + } + + for (p = buf;;) { + /* Skip whitespace. */ + while (*p && isspace(_UC(*p))) + p++; + if (!*p) + break; + + /* The start of something good :-) */ + if (arg->argc >= arg->size) { + char **tmp; + arg->size += 20; + tmp = OPENSSL_realloc(arg->argv, sizeof(*arg->argv) * arg->size); + if (tmp == NULL) + return 0; + arg->argv = tmp; + } + quoted = *p == '\'' || *p == '"'; + if (quoted) + c = *p++; + arg->argv[arg->argc++] = p; + + /* now look for the end of this */ + if (quoted) { + while (*p && *p != c) + p++; + *p++ = '\0'; + } else { + while (*p && !isspace(_UC(*p))) + p++; + if (*p) + *p++ = '\0'; + } + } + arg->argv[arg->argc] = NULL; + return 1; +} + +#ifndef APP_INIT +int app_init(long mesgwin) +{ + return 1; +} +#endif + +int ctx_set_verify_locations(SSL_CTX *ctx, const char *CAfile, + const char *CApath, int noCAfile, int noCApath) +{ + if (CAfile == NULL && CApath == NULL) { + if (!noCAfile && SSL_CTX_set_default_verify_file(ctx) <= 0) + return 0; + if (!noCApath && SSL_CTX_set_default_verify_dir(ctx) <= 0) + return 0; + + return 1; + } + return SSL_CTX_load_verify_locations(ctx, CAfile, CApath); +} + +#ifndef OPENSSL_NO_CT + +int ctx_set_ctlog_list_file(SSL_CTX *ctx, const char *path) +{ + if (path == NULL) + return SSL_CTX_set_default_ctlog_list_file(ctx); + + return SSL_CTX_set_ctlog_list_file(ctx, path); +} + +#endif + +static unsigned long nmflag = 0; +static char nmflag_set = 0; + +int set_nameopt(const char *arg) +{ + int ret = set_name_ex(&nmflag, arg); + + if (ret) + nmflag_set = 1; + + return ret; +} + +unsigned long get_nameopt(void) +{ + return (nmflag_set) ? nmflag : XN_FLAG_ONELINE; +} + +int dump_cert_text(BIO *out, X509 *x) +{ + print_name(out, "subject=", X509_get_subject_name(x), get_nameopt()); + BIO_puts(out, "\n"); + print_name(out, "issuer=", X509_get_issuer_name(x), get_nameopt()); + BIO_puts(out, "\n"); + + return 0; +} + +static int ui_open(UI *ui) +{ + int (*opener)(UI *ui) = UI_method_get_opener(ui_fallback_method); + + if (opener) + return opener(ui); + return 1; +} + +static int ui_read(UI *ui, UI_STRING *uis) +{ + int (*reader)(UI *ui, UI_STRING *uis) = NULL; + + if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD + && UI_get0_user_data(ui)) { + switch (UI_get_string_type(uis)) { + case UIT_PROMPT: + case UIT_VERIFY: + { + const char *password = + ((PW_CB_DATA *)UI_get0_user_data(ui))->password; + if (password && password[0] != '\0') { + UI_set_result(ui, uis, password); + return 1; + } + } + break; + case UIT_NONE: + case UIT_BOOLEAN: + case UIT_INFO: + case UIT_ERROR: + break; + } + } + + reader = UI_method_get_reader(ui_fallback_method); + if (reader) + return reader(ui, uis); + return 1; +} + +static int ui_write(UI *ui, UI_STRING *uis) +{ + int (*writer)(UI *ui, UI_STRING *uis) = NULL; + + if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD + && UI_get0_user_data(ui)) { + switch (UI_get_string_type(uis)) { + case UIT_PROMPT: + case UIT_VERIFY: + { + const char *password = + ((PW_CB_DATA *)UI_get0_user_data(ui))->password; + if (password && password[0] != '\0') + return 1; + } + break; + case UIT_NONE: + case UIT_BOOLEAN: + case UIT_INFO: + case UIT_ERROR: + break; + } + } + + writer = UI_method_get_writer(ui_fallback_method); + if (writer) + return writer(ui, uis); + return 1; +} + +static int ui_close(UI *ui) +{ + int (*closer)(UI *ui) = UI_method_get_closer(ui_fallback_method); + + if (closer) + return closer(ui); + return 1; +} + +int setup_ui_method(void) +{ + ui_fallback_method = UI_null(); +#ifndef OPENSSL_NO_UI_CONSOLE + ui_fallback_method = UI_OpenSSL(); +#endif + ui_method = UI_create_method("OpenSSL application user interface"); + UI_method_set_opener(ui_method, ui_open); + UI_method_set_reader(ui_method, ui_read); + UI_method_set_writer(ui_method, ui_write); + UI_method_set_closer(ui_method, ui_close); + return 0; +} + +void destroy_ui_method(void) +{ + if (ui_method) { + UI_destroy_method(ui_method); + ui_method = NULL; + } +} + +const UI_METHOD *get_ui_method(void) +{ + return ui_method; +} + +int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_tmp) +{ + int res = 0; + UI *ui = NULL; + PW_CB_DATA *cb_data = (PW_CB_DATA *)cb_tmp; + + ui = UI_new_method(ui_method); + if (ui) { + int ok = 0; + char *buff = NULL; + int ui_flags = 0; + const char *prompt_info = NULL; + char *prompt; + + if (cb_data != NULL && cb_data->prompt_info != NULL) + prompt_info = cb_data->prompt_info; + prompt = UI_construct_prompt(ui, "pass phrase", prompt_info); + if (!prompt) { + BIO_printf(bio_err, "Out of memory\n"); + UI_free(ui); + return 0; + } + + ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD; + UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0); + + /* We know that there is no previous user data to return to us */ + (void)UI_add_user_data(ui, cb_data); + + ok = UI_add_input_string(ui, prompt, ui_flags, buf, + PW_MIN_LENGTH, bufsiz - 1); + + if (ok >= 0 && verify) { + buff = app_malloc(bufsiz, "password buffer"); + ok = UI_add_verify_string(ui, prompt, ui_flags, buff, + PW_MIN_LENGTH, bufsiz - 1, buf); + } + if (ok >= 0) + do { + ok = UI_process(ui); + } while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0)); + + OPENSSL_clear_free(buff, (unsigned int)bufsiz); + + if (ok >= 0) + res = strlen(buf); + if (ok == -1) { + BIO_printf(bio_err, "User interface error\n"); + ERR_print_errors(bio_err); + OPENSSL_cleanse(buf, (unsigned int)bufsiz); + res = 0; + } + if (ok == -2) { + BIO_printf(bio_err, "aborted!\n"); + OPENSSL_cleanse(buf, (unsigned int)bufsiz); + res = 0; + } + UI_free(ui); + OPENSSL_free(prompt); + } + return res; +} + +static char *app_get_pass(const char *arg, int keepbio); + +int app_passwd(const char *arg1, const char *arg2, char **pass1, char **pass2) +{ + int same; + if (arg2 == NULL || arg1 == NULL || strcmp(arg1, arg2)) + same = 0; + else + same = 1; + if (arg1 != NULL) { + *pass1 = app_get_pass(arg1, same); + if (*pass1 == NULL) + return 0; + } else if (pass1 != NULL) { + *pass1 = NULL; + } + if (arg2 != NULL) { + *pass2 = app_get_pass(arg2, same ? 2 : 0); + if (*pass2 == NULL) + return 0; + } else if (pass2 != NULL) { + *pass2 = NULL; + } + return 1; +} + +static char *app_get_pass(const char *arg, int keepbio) +{ + char *tmp, tpass[APP_PASS_LEN]; + static BIO *pwdbio = NULL; + int i; + + if (strncmp(arg, "pass:", 5) == 0) + return OPENSSL_strdup(arg + 5); + if (strncmp(arg, "env:", 4) == 0) { + tmp = getenv(arg + 4); + if (tmp == NULL) { + BIO_printf(bio_err, "Can't read environment variable %s\n", arg + 4); + return NULL; + } + return OPENSSL_strdup(tmp); + } + if (!keepbio || pwdbio == NULL) { + if (strncmp(arg, "file:", 5) == 0) { + pwdbio = BIO_new_file(arg + 5, "r"); + if (pwdbio == NULL) { + BIO_printf(bio_err, "Can't open file %s\n", arg + 5); + return NULL; + } +#if !defined(_WIN32) + /* + * Under _WIN32, which covers even Win64 and CE, file + * descriptors referenced by BIO_s_fd are not inherited + * by child process and therefore below is not an option. + * It could have been an option if bss_fd.c was operating + * on real Windows descriptors, such as those obtained + * with CreateFile. + */ + } else if (strncmp(arg, "fd:", 3) == 0) { + BIO *btmp; + i = atoi(arg + 3); + if (i >= 0) + pwdbio = BIO_new_fd(i, BIO_NOCLOSE); + if ((i < 0) || !pwdbio) { + BIO_printf(bio_err, "Can't access file descriptor %s\n", arg + 3); + return NULL; + } + /* + * Can't do BIO_gets on an fd BIO so add a buffering BIO + */ + btmp = BIO_new(BIO_f_buffer()); + pwdbio = BIO_push(btmp, pwdbio); +#endif + } else if (strcmp(arg, "stdin") == 0) { + pwdbio = dup_bio_in(FORMAT_TEXT); + if (!pwdbio) { + BIO_printf(bio_err, "Can't open BIO for stdin\n"); + return NULL; + } + } else { + BIO_printf(bio_err, "Invalid password argument \"%s\"\n", arg); + return NULL; + } + } + i = BIO_gets(pwdbio, tpass, APP_PASS_LEN); + if (keepbio != 1) { + BIO_free_all(pwdbio); + pwdbio = NULL; + } + if (i <= 0) { + BIO_printf(bio_err, "Error reading password from BIO\n"); + return NULL; + } + tmp = strchr(tpass, '\n'); + if (tmp != NULL) + *tmp = 0; + return OPENSSL_strdup(tpass); +} + +CONF *app_load_config_bio(BIO *in, const char *filename) +{ + long errorline = -1; + CONF *conf; + int i; + + conf = NCONF_new(NULL); + i = NCONF_load_bio(conf, in, &errorline); + if (i > 0) + return conf; + + if (errorline <= 0) { + BIO_printf(bio_err, "%s: Can't load ", opt_getprog()); + } else { + BIO_printf(bio_err, "%s: Error on line %ld of ", opt_getprog(), + errorline); + } + if (filename != NULL) + BIO_printf(bio_err, "config file \"%s\"\n", filename); + else + BIO_printf(bio_err, "config input"); + + NCONF_free(conf); + return NULL; +} + +CONF *app_load_config(const char *filename) +{ + BIO *in; + CONF *conf; + + in = bio_open_default(filename, 'r', FORMAT_TEXT); + if (in == NULL) + return NULL; + + conf = app_load_config_bio(in, filename); + BIO_free(in); + return conf; +} + +CONF *app_load_config_quiet(const char *filename) +{ + BIO *in; + CONF *conf; + + in = bio_open_default_quiet(filename, 'r', FORMAT_TEXT); + if (in == NULL) + return NULL; + + conf = app_load_config_bio(in, filename); + BIO_free(in); + return conf; +} + +int app_load_modules(const CONF *config) +{ + CONF *to_free = NULL; + + if (config == NULL) + config = to_free = app_load_config_quiet(default_config_file); + if (config == NULL) + return 1; + + if (CONF_modules_load(config, NULL, 0) <= 0) { + BIO_printf(bio_err, "Error configuring OpenSSL modules\n"); + ERR_print_errors(bio_err); + NCONF_free(to_free); + return 0; + } + NCONF_free(to_free); + return 1; +} + +int add_oid_section(CONF *conf) +{ + char *p; + STACK_OF(CONF_VALUE) *sktmp; + CONF_VALUE *cnf; + int i; + + if ((p = NCONF_get_string(conf, NULL, "oid_section")) == NULL) { + ERR_clear_error(); + return 1; + } + if ((sktmp = NCONF_get_section(conf, p)) == NULL) { + BIO_printf(bio_err, "problem loading oid section %s\n", p); + return 0; + } + for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) { + cnf = sk_CONF_VALUE_value(sktmp, i); + if (OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) { + BIO_printf(bio_err, "problem creating object %s=%s\n", + cnf->name, cnf->value); + return 0; + } + } + return 1; +} + +static int load_pkcs12(BIO *in, const char *desc, + pem_password_cb *pem_cb, void *cb_data, + EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca) +{ + const char *pass; + char tpass[PEM_BUFSIZE]; + int len, ret = 0; + PKCS12 *p12; + p12 = d2i_PKCS12_bio(in, NULL); + if (p12 == NULL) { + BIO_printf(bio_err, "Error loading PKCS12 file for %s\n", desc); + goto die; + } + /* See if an empty password will do */ + if (PKCS12_verify_mac(p12, "", 0) || PKCS12_verify_mac(p12, NULL, 0)) { + pass = ""; + } else { + if (!pem_cb) + pem_cb = (pem_password_cb *)password_callback; + len = pem_cb(tpass, PEM_BUFSIZE, 0, cb_data); + if (len < 0) { + BIO_printf(bio_err, "Passphrase callback error for %s\n", desc); + goto die; + } + if (len < PEM_BUFSIZE) + tpass[len] = 0; + if (!PKCS12_verify_mac(p12, tpass, len)) { + BIO_printf(bio_err, + "Mac verify error (wrong password?) in PKCS12 file for %s\n", + desc); + goto die; + } + pass = tpass; + } + ret = PKCS12_parse(p12, pass, pkey, cert, ca); + die: + PKCS12_free(p12); + return ret; +} + +#if !defined(OPENSSL_NO_OCSP) && !defined(OPENSSL_NO_SOCK) +static int load_cert_crl_http(const char *url, X509 **pcert, X509_CRL **pcrl) +{ + char *host = NULL, *port = NULL, *path = NULL; + BIO *bio = NULL; + OCSP_REQ_CTX *rctx = NULL; + int use_ssl, rv = 0; + if (!OCSP_parse_url(url, &host, &port, &path, &use_ssl)) + goto err; + if (use_ssl) { + BIO_puts(bio_err, "https not supported\n"); + goto err; + } + bio = BIO_new_connect(host); + if (!bio || !BIO_set_conn_port(bio, port)) + goto err; + rctx = OCSP_REQ_CTX_new(bio, 1024); + if (rctx == NULL) + goto err; + if (!OCSP_REQ_CTX_http(rctx, "GET", path)) + goto err; + if (!OCSP_REQ_CTX_add1_header(rctx, "Host", host)) + goto err; + if (pcert) { + do { + rv = X509_http_nbio(rctx, pcert); + } while (rv == -1); + } else { + do { + rv = X509_CRL_http_nbio(rctx, pcrl); + } while (rv == -1); + } + + err: + OPENSSL_free(host); + OPENSSL_free(path); + OPENSSL_free(port); + BIO_free_all(bio); + OCSP_REQ_CTX_free(rctx); + if (rv != 1) { + BIO_printf(bio_err, "Error loading %s from %s\n", + pcert ? "certificate" : "CRL", url); + ERR_print_errors(bio_err); + } + return rv; +} +#endif + +X509 *load_cert(const char *file, int format, const char *cert_descrip) +{ + X509 *x = NULL; + BIO *cert; + + if (format == FORMAT_HTTP) { +#if !defined(OPENSSL_NO_OCSP) && !defined(OPENSSL_NO_SOCK) + load_cert_crl_http(file, &x, NULL); +#endif + return x; + } + + if (file == NULL) { + unbuffer(stdin); + cert = dup_bio_in(format); + } else { + cert = bio_open_default(file, 'r', format); + } + if (cert == NULL) + goto end; + + if (format == FORMAT_ASN1) { + x = d2i_X509_bio(cert, NULL); + } else if (format == FORMAT_PEM) { + x = PEM_read_bio_X509_AUX(cert, NULL, + (pem_password_cb *)password_callback, NULL); + } else if (format == FORMAT_PKCS12) { + if (!load_pkcs12(cert, cert_descrip, NULL, NULL, NULL, &x, NULL)) + goto end; + } else { + BIO_printf(bio_err, "bad input format specified for %s\n", cert_descrip); + goto end; + } + end: + if (x == NULL) { + BIO_printf(bio_err, "unable to load certificate\n"); + ERR_print_errors(bio_err); + } + BIO_free(cert); + return x; +} + +X509_CRL *load_crl(const char *infile, int format) +{ + X509_CRL *x = NULL; + BIO *in = NULL; + + if (format == FORMAT_HTTP) { +#if !defined(OPENSSL_NO_OCSP) && !defined(OPENSSL_NO_SOCK) + load_cert_crl_http(infile, NULL, &x); +#endif + return x; + } + + in = bio_open_default(infile, 'r', format); + if (in == NULL) + goto end; + if (format == FORMAT_ASN1) { + x = d2i_X509_CRL_bio(in, NULL); + } else if (format == FORMAT_PEM) { + x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); + } else { + BIO_printf(bio_err, "bad input format specified for input crl\n"); + goto end; + } + if (x == NULL) { + BIO_printf(bio_err, "unable to load CRL\n"); + ERR_print_errors(bio_err); + goto end; + } + + end: + BIO_free(in); + return x; +} + +EVP_PKEY *load_key(const char *file, int format, int maybe_stdin, + const char *pass, ENGINE *e, const char *key_descrip) +{ + BIO *key = NULL; + EVP_PKEY *pkey = NULL; + PW_CB_DATA cb_data; + + cb_data.password = pass; + cb_data.prompt_info = file; + + if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE)) { + BIO_printf(bio_err, "no keyfile specified\n"); + goto end; + } + if (format == FORMAT_ENGINE) { + if (e == NULL) { + BIO_printf(bio_err, "no engine specified\n"); + } else { +#ifndef OPENSSL_NO_ENGINE + if (ENGINE_init(e)) { + pkey = ENGINE_load_private_key(e, file, ui_method, &cb_data); + ENGINE_finish(e); + } + if (pkey == NULL) { + BIO_printf(bio_err, "cannot load %s from engine\n", key_descrip); + ERR_print_errors(bio_err); + } +#else + BIO_printf(bio_err, "engines not supported\n"); +#endif + } + goto end; + } + if (file == NULL && maybe_stdin) { + unbuffer(stdin); + key = dup_bio_in(format); + } else { + key = bio_open_default(file, 'r', format); + } + if (key == NULL) + goto end; + if (format == FORMAT_ASN1) { + pkey = d2i_PrivateKey_bio(key, NULL); + } else if (format == FORMAT_PEM) { + pkey = PEM_read_bio_PrivateKey(key, NULL, + (pem_password_cb *)password_callback, + &cb_data); + } else if (format == FORMAT_PKCS12) { + if (!load_pkcs12(key, key_descrip, + (pem_password_cb *)password_callback, &cb_data, + &pkey, NULL, NULL)) + goto end; +#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) && !defined (OPENSSL_NO_RC4) + } else if (format == FORMAT_MSBLOB) { + pkey = b2i_PrivateKey_bio(key); + } else if (format == FORMAT_PVK) { + pkey = b2i_PVK_bio(key, (pem_password_cb *)password_callback, + &cb_data); +#endif + } else { + BIO_printf(bio_err, "bad input format specified for key file\n"); + goto end; + } + end: + BIO_free(key); + if (pkey == NULL) { + BIO_printf(bio_err, "unable to load %s\n", key_descrip); + ERR_print_errors(bio_err); + } + return pkey; +} + +EVP_PKEY *load_pubkey(const char *file, int format, int maybe_stdin, + const char *pass, ENGINE *e, const char *key_descrip) +{ + BIO *key = NULL; + EVP_PKEY *pkey = NULL; + PW_CB_DATA cb_data; + + cb_data.password = pass; + cb_data.prompt_info = file; + + if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE)) { + BIO_printf(bio_err, "no keyfile specified\n"); + goto end; + } + if (format == FORMAT_ENGINE) { + if (e == NULL) { + BIO_printf(bio_err, "no engine specified\n"); + } else { +#ifndef OPENSSL_NO_ENGINE + pkey = ENGINE_load_public_key(e, file, ui_method, &cb_data); + if (pkey == NULL) { + BIO_printf(bio_err, "cannot load %s from engine\n", key_descrip); + ERR_print_errors(bio_err); + } +#else + BIO_printf(bio_err, "engines not supported\n"); +#endif + } + goto end; + } + if (file == NULL && maybe_stdin) { + unbuffer(stdin); + key = dup_bio_in(format); + } else { + key = bio_open_default(file, 'r', format); + } + if (key == NULL) + goto end; + if (format == FORMAT_ASN1) { + pkey = d2i_PUBKEY_bio(key, NULL); + } else if (format == FORMAT_ASN1RSA) { +#ifndef OPENSSL_NO_RSA + RSA *rsa; + rsa = d2i_RSAPublicKey_bio(key, NULL); + if (rsa) { + pkey = EVP_PKEY_new(); + if (pkey != NULL) + EVP_PKEY_set1_RSA(pkey, rsa); + RSA_free(rsa); + } else +#else + BIO_printf(bio_err, "RSA keys not supported\n"); +#endif + pkey = NULL; + } else if (format == FORMAT_PEMRSA) { +#ifndef OPENSSL_NO_RSA + RSA *rsa; + rsa = PEM_read_bio_RSAPublicKey(key, NULL, + (pem_password_cb *)password_callback, + &cb_data); + if (rsa != NULL) { + pkey = EVP_PKEY_new(); + if (pkey != NULL) + EVP_PKEY_set1_RSA(pkey, rsa); + RSA_free(rsa); + } else +#else + BIO_printf(bio_err, "RSA keys not supported\n"); +#endif + pkey = NULL; + } else if (format == FORMAT_PEM) { + pkey = PEM_read_bio_PUBKEY(key, NULL, + (pem_password_cb *)password_callback, + &cb_data); +#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) + } else if (format == FORMAT_MSBLOB) { + pkey = b2i_PublicKey_bio(key); +#endif + } + end: + BIO_free(key); + if (pkey == NULL) + BIO_printf(bio_err, "unable to load %s\n", key_descrip); + return pkey; +} + +static int load_certs_crls(const char *file, int format, + const char *pass, const char *desc, + STACK_OF(X509) **pcerts, + STACK_OF(X509_CRL) **pcrls) +{ + int i; + BIO *bio; + STACK_OF(X509_INFO) *xis = NULL; + X509_INFO *xi; + PW_CB_DATA cb_data; + int rv = 0; + + cb_data.password = pass; + cb_data.prompt_info = file; + + if (format != FORMAT_PEM) { + BIO_printf(bio_err, "bad input format specified for %s\n", desc); + return 0; + } + + bio = bio_open_default(file, 'r', FORMAT_PEM); + if (bio == NULL) + return 0; + + xis = PEM_X509_INFO_read_bio(bio, NULL, + (pem_password_cb *)password_callback, + &cb_data); + + BIO_free(bio); + + if (pcerts != NULL && *pcerts == NULL) { + *pcerts = sk_X509_new_null(); + if (*pcerts == NULL) + goto end; + } + + if (pcrls != NULL && *pcrls == NULL) { + *pcrls = sk_X509_CRL_new_null(); + if (*pcrls == NULL) + goto end; + } + + for (i = 0; i < sk_X509_INFO_num(xis); i++) { + xi = sk_X509_INFO_value(xis, i); + if (xi->x509 != NULL && pcerts != NULL) { + if (!sk_X509_push(*pcerts, xi->x509)) + goto end; + xi->x509 = NULL; + } + if (xi->crl != NULL && pcrls != NULL) { + if (!sk_X509_CRL_push(*pcrls, xi->crl)) + goto end; + xi->crl = NULL; + } + } + + if (pcerts != NULL && sk_X509_num(*pcerts) > 0) + rv = 1; + + if (pcrls != NULL && sk_X509_CRL_num(*pcrls) > 0) + rv = 1; + + end: + + sk_X509_INFO_pop_free(xis, X509_INFO_free); + + if (rv == 0) { + if (pcerts != NULL) { + sk_X509_pop_free(*pcerts, X509_free); + *pcerts = NULL; + } + if (pcrls != NULL) { + sk_X509_CRL_pop_free(*pcrls, X509_CRL_free); + *pcrls = NULL; + } + BIO_printf(bio_err, "unable to load %s\n", + pcerts ? "certificates" : "CRLs"); + ERR_print_errors(bio_err); + } + return rv; +} + +void* app_malloc(int sz, const char *what) +{ + void *vp = OPENSSL_malloc(sz); + + if (vp == NULL) { + BIO_printf(bio_err, "%s: Could not allocate %d bytes for %s\n", + opt_getprog(), sz, what); + ERR_print_errors(bio_err); + exit(1); + } + return vp; +} + +/* + * Initialize or extend, if *certs != NULL, a certificate stack. + */ +int load_certs(const char *file, STACK_OF(X509) **certs, int format, + const char *pass, const char *desc) +{ + return load_certs_crls(file, format, pass, desc, certs, NULL); +} + +/* + * Initialize or extend, if *crls != NULL, a certificate stack. + */ +int load_crls(const char *file, STACK_OF(X509_CRL) **crls, int format, + const char *pass, const char *desc) +{ + return load_certs_crls(file, format, pass, desc, NULL, crls); +} + +#define X509V3_EXT_UNKNOWN_MASK (0xfL << 16) +/* Return error for unknown extensions */ +#define X509V3_EXT_DEFAULT 0 +/* Print error for unknown extensions */ +#define X509V3_EXT_ERROR_UNKNOWN (1L << 16) +/* ASN1 parse unknown extensions */ +#define X509V3_EXT_PARSE_UNKNOWN (2L << 16) +/* BIO_dump unknown extensions */ +#define X509V3_EXT_DUMP_UNKNOWN (3L << 16) + +#define X509_FLAG_CA (X509_FLAG_NO_ISSUER | X509_FLAG_NO_PUBKEY | \ + X509_FLAG_NO_HEADER | X509_FLAG_NO_VERSION) + +int set_cert_ex(unsigned long *flags, const char *arg) +{ + static const NAME_EX_TBL cert_tbl[] = { + {"compatible", X509_FLAG_COMPAT, 0xffffffffl}, + {"ca_default", X509_FLAG_CA, 0xffffffffl}, + {"no_header", X509_FLAG_NO_HEADER, 0}, + {"no_version", X509_FLAG_NO_VERSION, 0}, + {"no_serial", X509_FLAG_NO_SERIAL, 0}, + {"no_signame", X509_FLAG_NO_SIGNAME, 0}, + {"no_validity", X509_FLAG_NO_VALIDITY, 0}, + {"no_subject", X509_FLAG_NO_SUBJECT, 0}, + {"no_issuer", X509_FLAG_NO_ISSUER, 0}, + {"no_pubkey", X509_FLAG_NO_PUBKEY, 0}, + {"no_extensions", X509_FLAG_NO_EXTENSIONS, 0}, + {"no_sigdump", X509_FLAG_NO_SIGDUMP, 0}, + {"no_aux", X509_FLAG_NO_AUX, 0}, + {"no_attributes", X509_FLAG_NO_ATTRIBUTES, 0}, + {"ext_default", X509V3_EXT_DEFAULT, X509V3_EXT_UNKNOWN_MASK}, + {"ext_error", X509V3_EXT_ERROR_UNKNOWN, X509V3_EXT_UNKNOWN_MASK}, + {"ext_parse", X509V3_EXT_PARSE_UNKNOWN, X509V3_EXT_UNKNOWN_MASK}, + {"ext_dump", X509V3_EXT_DUMP_UNKNOWN, X509V3_EXT_UNKNOWN_MASK}, + {NULL, 0, 0} + }; + return set_multi_opts(flags, arg, cert_tbl); +} + +int set_name_ex(unsigned long *flags, const char *arg) +{ + static const NAME_EX_TBL ex_tbl[] = { + {"esc_2253", ASN1_STRFLGS_ESC_2253, 0}, + {"esc_2254", ASN1_STRFLGS_ESC_2254, 0}, + {"esc_ctrl", ASN1_STRFLGS_ESC_CTRL, 0}, + {"esc_msb", ASN1_STRFLGS_ESC_MSB, 0}, + {"use_quote", ASN1_STRFLGS_ESC_QUOTE, 0}, + {"utf8", ASN1_STRFLGS_UTF8_CONVERT, 0}, + {"ignore_type", ASN1_STRFLGS_IGNORE_TYPE, 0}, + {"show_type", ASN1_STRFLGS_SHOW_TYPE, 0}, + {"dump_all", ASN1_STRFLGS_DUMP_ALL, 0}, + {"dump_nostr", ASN1_STRFLGS_DUMP_UNKNOWN, 0}, + {"dump_der", ASN1_STRFLGS_DUMP_DER, 0}, + {"compat", XN_FLAG_COMPAT, 0xffffffffL}, + {"sep_comma_plus", XN_FLAG_SEP_COMMA_PLUS, XN_FLAG_SEP_MASK}, + {"sep_comma_plus_space", XN_FLAG_SEP_CPLUS_SPC, XN_FLAG_SEP_MASK}, + {"sep_semi_plus_space", XN_FLAG_SEP_SPLUS_SPC, XN_FLAG_SEP_MASK}, + {"sep_multiline", XN_FLAG_SEP_MULTILINE, XN_FLAG_SEP_MASK}, + {"dn_rev", XN_FLAG_DN_REV, 0}, + {"nofname", XN_FLAG_FN_NONE, XN_FLAG_FN_MASK}, + {"sname", XN_FLAG_FN_SN, XN_FLAG_FN_MASK}, + {"lname", XN_FLAG_FN_LN, XN_FLAG_FN_MASK}, + {"align", XN_FLAG_FN_ALIGN, 0}, + {"oid", XN_FLAG_FN_OID, XN_FLAG_FN_MASK}, + {"space_eq", XN_FLAG_SPC_EQ, 0}, + {"dump_unknown", XN_FLAG_DUMP_UNKNOWN_FIELDS, 0}, + {"RFC2253", XN_FLAG_RFC2253, 0xffffffffL}, + {"oneline", XN_FLAG_ONELINE, 0xffffffffL}, + {"multiline", XN_FLAG_MULTILINE, 0xffffffffL}, + {"ca_default", XN_FLAG_MULTILINE, 0xffffffffL}, + {NULL, 0, 0} + }; + if (set_multi_opts(flags, arg, ex_tbl) == 0) + return 0; + if (*flags != XN_FLAG_COMPAT + && (*flags & XN_FLAG_SEP_MASK) == 0) + *flags |= XN_FLAG_SEP_CPLUS_SPC; + return 1; +} + +int set_ext_copy(int *copy_type, const char *arg) +{ + if (strcasecmp(arg, "none") == 0) + *copy_type = EXT_COPY_NONE; + else if (strcasecmp(arg, "copy") == 0) + *copy_type = EXT_COPY_ADD; + else if (strcasecmp(arg, "copyall") == 0) + *copy_type = EXT_COPY_ALL; + else + return 0; + return 1; +} + +int copy_extensions(X509 *x, X509_REQ *req, int copy_type) +{ + STACK_OF(X509_EXTENSION) *exts = NULL; + X509_EXTENSION *ext, *tmpext; + ASN1_OBJECT *obj; + int i, idx, ret = 0; + if (!x || !req || (copy_type == EXT_COPY_NONE)) + return 1; + exts = X509_REQ_get_extensions(req); + + for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { + ext = sk_X509_EXTENSION_value(exts, i); + obj = X509_EXTENSION_get_object(ext); + idx = X509_get_ext_by_OBJ(x, obj, -1); + /* Does extension exist? */ + if (idx != -1) { + /* If normal copy don't override existing extension */ + if (copy_type == EXT_COPY_ADD) + continue; + /* Delete all extensions of same type */ + do { + tmpext = X509_get_ext(x, idx); + X509_delete_ext(x, idx); + X509_EXTENSION_free(tmpext); + idx = X509_get_ext_by_OBJ(x, obj, -1); + } while (idx != -1); + } + if (!X509_add_ext(x, ext, -1)) + goto end; + } + + ret = 1; + + end: + + sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); + + return ret; +} + +static int set_multi_opts(unsigned long *flags, const char *arg, + const NAME_EX_TBL * in_tbl) +{ + STACK_OF(CONF_VALUE) *vals; + CONF_VALUE *val; + int i, ret = 1; + if (!arg) + return 0; + vals = X509V3_parse_list(arg); + for (i = 0; i < sk_CONF_VALUE_num(vals); i++) { + val = sk_CONF_VALUE_value(vals, i); + if (!set_table_opts(flags, val->name, in_tbl)) + ret = 0; + } + sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); + return ret; +} + +static int set_table_opts(unsigned long *flags, const char *arg, + const NAME_EX_TBL * in_tbl) +{ + char c; + const NAME_EX_TBL *ptbl; + c = arg[0]; + + if (c == '-') { + c = 0; + arg++; + } else if (c == '+') { + c = 1; + arg++; + } else { + c = 1; + } + + for (ptbl = in_tbl; ptbl->name; ptbl++) { + if (strcasecmp(arg, ptbl->name) == 0) { + *flags &= ~ptbl->mask; + if (c) + *flags |= ptbl->flag; + else + *flags &= ~ptbl->flag; + return 1; + } + } + return 0; +} + +void print_name(BIO *out, const char *title, X509_NAME *nm, + unsigned long lflags) +{ + char *buf; + char mline = 0; + int indent = 0; + + if (title) + BIO_puts(out, title); + if ((lflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) { + mline = 1; + indent = 4; + } + if (lflags == XN_FLAG_COMPAT) { + buf = X509_NAME_oneline(nm, 0, 0); + BIO_puts(out, buf); + BIO_puts(out, "\n"); + OPENSSL_free(buf); + } else { + if (mline) + BIO_puts(out, "\n"); + X509_NAME_print_ex(out, nm, indent, lflags); + BIO_puts(out, "\n"); + } +} + +void print_bignum_var(BIO *out, const BIGNUM *in, const char *var, + int len, unsigned char *buffer) +{ + BIO_printf(out, " static unsigned char %s_%d[] = {", var, len); + if (BN_is_zero(in)) { + BIO_printf(out, "\n 0x00"); + } else { + int i, l; + + l = BN_bn2bin(in, buffer); + for (i = 0; i < l; i++) { + BIO_printf(out, (i % 10) == 0 ? "\n " : " "); + if (i < l - 1) + BIO_printf(out, "0x%02X,", buffer[i]); + else + BIO_printf(out, "0x%02X", buffer[i]); + } + } + BIO_printf(out, "\n };\n"); +} + +void print_array(BIO *out, const char* title, int len, const unsigned char* d) +{ + int i; + + BIO_printf(out, "unsigned char %s[%d] = {", title, len); + for (i = 0; i < len; i++) { + if ((i % 10) == 0) + BIO_printf(out, "\n "); + if (i < len - 1) + BIO_printf(out, "0x%02X, ", d[i]); + else + BIO_printf(out, "0x%02X", d[i]); + } + BIO_printf(out, "\n};\n"); +} + +X509_STORE *setup_verify(const char *CAfile, const char *CApath, int noCAfile, int noCApath) +{ + X509_STORE *store = X509_STORE_new(); + X509_LOOKUP *lookup; + + if (store == NULL) + goto end; + + if (CAfile != NULL || !noCAfile) { + lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); + if (lookup == NULL) + goto end; + if (CAfile) { + if (!X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM)) { + BIO_printf(bio_err, "Error loading file %s\n", CAfile); + goto end; + } + } else { + X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); + } + } + + if (CApath != NULL || !noCApath) { + lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); + if (lookup == NULL) + goto end; + if (CApath) { + if (!X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM)) { + BIO_printf(bio_err, "Error loading directory %s\n", CApath); + goto end; + } + } else { + X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); + } + } + + ERR_clear_error(); + return store; + end: + X509_STORE_free(store); + return NULL; +} + +#ifndef OPENSSL_NO_ENGINE +/* Try to load an engine in a shareable library */ +static ENGINE *try_load_engine(const char *engine) +{ + ENGINE *e = ENGINE_by_id("dynamic"); + if (e) { + if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", engine, 0) + || !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) { + ENGINE_free(e); + e = NULL; + } + } + return e; +} +#endif + +ENGINE *setup_engine(const char *engine, int debug) +{ + ENGINE *e = NULL; + +#ifndef OPENSSL_NO_ENGINE + if (engine != NULL) { + if (strcmp(engine, "auto") == 0) { + BIO_printf(bio_err, "enabling auto ENGINE support\n"); + ENGINE_register_all_complete(); + return NULL; + } + if ((e = ENGINE_by_id(engine)) == NULL + && (e = try_load_engine(engine)) == NULL) { + BIO_printf(bio_err, "invalid engine \"%s\"\n", engine); + ERR_print_errors(bio_err); + return NULL; + } + if (debug) { + ENGINE_ctrl(e, ENGINE_CTRL_SET_LOGSTREAM, 0, bio_err, 0); + } + ENGINE_ctrl_cmd(e, "SET_USER_INTERFACE", 0, ui_method, 0, 1); + if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) { + BIO_printf(bio_err, "can't use that engine\n"); + ERR_print_errors(bio_err); + ENGINE_free(e); + return NULL; + } + + BIO_printf(bio_err, "engine \"%s\" set.\n", ENGINE_get_id(e)); + } +#endif + return e; +} + +void release_engine(ENGINE *e) +{ +#ifndef OPENSSL_NO_ENGINE + if (e != NULL) + /* Free our "structural" reference. */ + ENGINE_free(e); +#endif +} + +static unsigned long index_serial_hash(const OPENSSL_CSTRING *a) +{ + const char *n; + + n = a[DB_serial]; + while (*n == '0') + n++; + return OPENSSL_LH_strhash(n); +} + +static int index_serial_cmp(const OPENSSL_CSTRING *a, + const OPENSSL_CSTRING *b) +{ + const char *aa, *bb; + + for (aa = a[DB_serial]; *aa == '0'; aa++) ; + for (bb = b[DB_serial]; *bb == '0'; bb++) ; + return strcmp(aa, bb); +} + +static int index_name_qual(char **a) +{ + return (a[0][0] == 'V'); +} + +static unsigned long index_name_hash(const OPENSSL_CSTRING *a) +{ + return OPENSSL_LH_strhash(a[DB_name]); +} + +int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b) +{ + return strcmp(a[DB_name], b[DB_name]); +} + +static IMPLEMENT_LHASH_HASH_FN(index_serial, OPENSSL_CSTRING) +static IMPLEMENT_LHASH_COMP_FN(index_serial, OPENSSL_CSTRING) +static IMPLEMENT_LHASH_HASH_FN(index_name, OPENSSL_CSTRING) +static IMPLEMENT_LHASH_COMP_FN(index_name, OPENSSL_CSTRING) +#undef BSIZE +#define BSIZE 256 +BIGNUM *load_serial(const char *serialfile, int create, ASN1_INTEGER **retai) +{ + BIO *in = NULL; + BIGNUM *ret = NULL; + char buf[1024]; + ASN1_INTEGER *ai = NULL; + + ai = ASN1_INTEGER_new(); + if (ai == NULL) + goto err; + + in = BIO_new_file(serialfile, "r"); + if (in == NULL) { + if (!create) { + perror(serialfile); + goto err; + } + ERR_clear_error(); + ret = BN_new(); + if (ret == NULL || !rand_serial(ret, ai)) + BIO_printf(bio_err, "Out of memory\n"); + } else { + if (!a2i_ASN1_INTEGER(in, ai, buf, 1024)) { + BIO_printf(bio_err, "unable to load number from %s\n", + serialfile); + goto err; + } + ret = ASN1_INTEGER_to_BN(ai, NULL); + if (ret == NULL) { + BIO_printf(bio_err, + "error converting number from bin to BIGNUM\n"); + goto err; + } + } + + if (ret && retai) { + *retai = ai; + ai = NULL; + } + err: + BIO_free(in); + ASN1_INTEGER_free(ai); + return ret; +} + +int save_serial(const char *serialfile, const char *suffix, const BIGNUM *serial, + ASN1_INTEGER **retai) +{ + char buf[1][BSIZE]; + BIO *out = NULL; + int ret = 0; + ASN1_INTEGER *ai = NULL; + int j; + + if (suffix == NULL) + j = strlen(serialfile); + else + j = strlen(serialfile) + strlen(suffix) + 1; + if (j >= BSIZE) { + BIO_printf(bio_err, "file name too long\n"); + goto err; + } + + if (suffix == NULL) + OPENSSL_strlcpy(buf[0], serialfile, BSIZE); + else { +#ifndef OPENSSL_SYS_VMS + j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", serialfile, suffix); +#else + j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", serialfile, suffix); +#endif + } + out = BIO_new_file(buf[0], "w"); + if (out == NULL) { + ERR_print_errors(bio_err); + goto err; + } + + if ((ai = BN_to_ASN1_INTEGER(serial, NULL)) == NULL) { + BIO_printf(bio_err, "error converting serial to ASN.1 format\n"); + goto err; + } + i2a_ASN1_INTEGER(out, ai); + BIO_puts(out, "\n"); + ret = 1; + if (retai) { + *retai = ai; + ai = NULL; + } + err: + BIO_free_all(out); + ASN1_INTEGER_free(ai); + return ret; +} + +int rotate_serial(const char *serialfile, const char *new_suffix, + const char *old_suffix) +{ + char buf[2][BSIZE]; + int i, j; + + i = strlen(serialfile) + strlen(old_suffix); + j = strlen(serialfile) + strlen(new_suffix); + if (i > j) + j = i; + if (j + 1 >= BSIZE) { + BIO_printf(bio_err, "file name too long\n"); + goto err; + } +#ifndef OPENSSL_SYS_VMS + j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", serialfile, new_suffix); + j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.%s", serialfile, old_suffix); +#else + j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", serialfile, new_suffix); + j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-%s", serialfile, old_suffix); +#endif + if (rename(serialfile, buf[1]) < 0 && errno != ENOENT +#ifdef ENOTDIR + && errno != ENOTDIR +#endif + ) { + BIO_printf(bio_err, + "unable to rename %s to %s\n", serialfile, buf[1]); + perror("reason"); + goto err; + } + if (rename(buf[0], serialfile) < 0) { + BIO_printf(bio_err, + "unable to rename %s to %s\n", buf[0], serialfile); + perror("reason"); + rename(buf[1], serialfile); + goto err; + } + return 1; + err: + return 0; +} + +int rand_serial(BIGNUM *b, ASN1_INTEGER *ai) +{ + BIGNUM *btmp; + int ret = 0; + + btmp = b == NULL ? BN_new() : b; + if (btmp == NULL) + return 0; + + if (!BN_rand(btmp, SERIAL_RAND_BITS, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) + goto error; + if (ai && !BN_to_ASN1_INTEGER(btmp, ai)) + goto error; + + ret = 1; + + error: + + if (btmp != b) + BN_free(btmp); + + return ret; +} + +CA_DB *load_index(const char *dbfile, DB_ATTR *db_attr) +{ + CA_DB *retdb = NULL; + TXT_DB *tmpdb = NULL; + BIO *in; + CONF *dbattr_conf = NULL; + char buf[BSIZE]; +#ifndef OPENSSL_NO_POSIX_IO + FILE *dbfp; + struct stat dbst; +#endif + + in = BIO_new_file(dbfile, "r"); + if (in == NULL) { + ERR_print_errors(bio_err); + goto err; + } + +#ifndef OPENSSL_NO_POSIX_IO + BIO_get_fp(in, &dbfp); + if (fstat(fileno(dbfp), &dbst) == -1) { + SYSerr(SYS_F_FSTAT, errno); + ERR_add_error_data(3, "fstat('", dbfile, "')"); + ERR_print_errors(bio_err); + goto err; + } +#endif + + if ((tmpdb = TXT_DB_read(in, DB_NUMBER)) == NULL) + goto err; + +#ifndef OPENSSL_SYS_VMS + BIO_snprintf(buf, sizeof(buf), "%s.attr", dbfile); +#else + BIO_snprintf(buf, sizeof(buf), "%s-attr", dbfile); +#endif + dbattr_conf = app_load_config_quiet(buf); + + retdb = app_malloc(sizeof(*retdb), "new DB"); + retdb->db = tmpdb; + tmpdb = NULL; + if (db_attr) + retdb->attributes = *db_attr; + else { + retdb->attributes.unique_subject = 1; + } + + if (dbattr_conf) { + char *p = NCONF_get_string(dbattr_conf, NULL, "unique_subject"); + if (p) { + retdb->attributes.unique_subject = parse_yesno(p, 1); + } + } + + retdb->dbfname = OPENSSL_strdup(dbfile); +#ifndef OPENSSL_NO_POSIX_IO + retdb->dbst = dbst; +#endif + + err: + NCONF_free(dbattr_conf); + TXT_DB_free(tmpdb); + BIO_free_all(in); + return retdb; +} + +/* + * Returns > 0 on success, <= 0 on error + */ +int index_index(CA_DB *db) +{ + if (!TXT_DB_create_index(db->db, DB_serial, NULL, + LHASH_HASH_FN(index_serial), + LHASH_COMP_FN(index_serial))) { + BIO_printf(bio_err, + "error creating serial number index:(%ld,%ld,%ld)\n", + db->db->error, db->db->arg1, db->db->arg2); + return 0; + } + + if (db->attributes.unique_subject + && !TXT_DB_create_index(db->db, DB_name, index_name_qual, + LHASH_HASH_FN(index_name), + LHASH_COMP_FN(index_name))) { + BIO_printf(bio_err, "error creating name index:(%ld,%ld,%ld)\n", + db->db->error, db->db->arg1, db->db->arg2); + return 0; + } + return 1; +} + +int save_index(const char *dbfile, const char *suffix, CA_DB *db) +{ + char buf[3][BSIZE]; + BIO *out; + int j; + + j = strlen(dbfile) + strlen(suffix); + if (j + 6 >= BSIZE) { + BIO_printf(bio_err, "file name too long\n"); + goto err; + } +#ifndef OPENSSL_SYS_VMS + j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s.attr", dbfile); + j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.attr.%s", dbfile, suffix); + j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", dbfile, suffix); +#else + j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s-attr", dbfile); + j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-attr-%s", dbfile, suffix); + j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", dbfile, suffix); +#endif + out = BIO_new_file(buf[0], "w"); + if (out == NULL) { + perror(dbfile); + BIO_printf(bio_err, "unable to open '%s'\n", dbfile); + goto err; + } + j = TXT_DB_write(out, db->db); + BIO_free(out); + if (j <= 0) + goto err; + + out = BIO_new_file(buf[1], "w"); + if (out == NULL) { + perror(buf[2]); + BIO_printf(bio_err, "unable to open '%s'\n", buf[2]); + goto err; + } + BIO_printf(out, "unique_subject = %s\n", + db->attributes.unique_subject ? "yes" : "no"); + BIO_free(out); + + return 1; + err: + return 0; +} + +int rotate_index(const char *dbfile, const char *new_suffix, + const char *old_suffix) +{ + char buf[5][BSIZE]; + int i, j; + + i = strlen(dbfile) + strlen(old_suffix); + j = strlen(dbfile) + strlen(new_suffix); + if (i > j) + j = i; + if (j + 6 >= BSIZE) { + BIO_printf(bio_err, "file name too long\n"); + goto err; + } +#ifndef OPENSSL_SYS_VMS + j = BIO_snprintf(buf[4], sizeof(buf[4]), "%s.attr", dbfile); + j = BIO_snprintf(buf[3], sizeof(buf[3]), "%s.attr.%s", dbfile, old_suffix); + j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s.attr.%s", dbfile, new_suffix); + j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.%s", dbfile, old_suffix); + j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", dbfile, new_suffix); +#else + j = BIO_snprintf(buf[4], sizeof(buf[4]), "%s-attr", dbfile); + j = BIO_snprintf(buf[3], sizeof(buf[3]), "%s-attr-%s", dbfile, old_suffix); + j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s-attr-%s", dbfile, new_suffix); + j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-%s", dbfile, old_suffix); + j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", dbfile, new_suffix); +#endif + if (rename(dbfile, buf[1]) < 0 && errno != ENOENT +#ifdef ENOTDIR + && errno != ENOTDIR +#endif + ) { + BIO_printf(bio_err, "unable to rename %s to %s\n", dbfile, buf[1]); + perror("reason"); + goto err; + } + if (rename(buf[0], dbfile) < 0) { + BIO_printf(bio_err, "unable to rename %s to %s\n", buf[0], dbfile); + perror("reason"); + rename(buf[1], dbfile); + goto err; + } + if (rename(buf[4], buf[3]) < 0 && errno != ENOENT +#ifdef ENOTDIR + && errno != ENOTDIR +#endif + ) { + BIO_printf(bio_err, "unable to rename %s to %s\n", buf[4], buf[3]); + perror("reason"); + rename(dbfile, buf[0]); + rename(buf[1], dbfile); + goto err; + } + if (rename(buf[2], buf[4]) < 0) { + BIO_printf(bio_err, "unable to rename %s to %s\n", buf[2], buf[4]); + perror("reason"); + rename(buf[3], buf[4]); + rename(dbfile, buf[0]); + rename(buf[1], dbfile); + goto err; + } + return 1; + err: + return 0; +} + +void free_index(CA_DB *db) +{ + if (db) { + TXT_DB_free(db->db); + OPENSSL_free(db->dbfname); + OPENSSL_free(db); + } +} + +int parse_yesno(const char *str, int def) +{ + if (str) { + switch (*str) { + case 'f': /* false */ + case 'F': /* FALSE */ + case 'n': /* no */ + case 'N': /* NO */ + case '0': /* 0 */ + return 0; + case 't': /* true */ + case 'T': /* TRUE */ + case 'y': /* yes */ + case 'Y': /* YES */ + case '1': /* 1 */ + return 1; + } + } + return def; +} + +/* + * name is expected to be in the format /type0=value0/type1=value1/type2=... + * where characters may be escaped by \ + */ +X509_NAME *parse_name(const char *cp, long chtype, int canmulti) +{ + int nextismulti = 0; + char *work; + X509_NAME *n; + + if (*cp++ != '/') { + BIO_printf(bio_err, + "name is expected to be in the format " + "/type0=value0/type1=value1/type2=... where characters may " + "be escaped by \\. This name is not in that format: '%s'\n", + --cp); + return NULL; + } + + n = X509_NAME_new(); + if (n == NULL) + return NULL; + work = OPENSSL_strdup(cp); + if (work == NULL) + goto err; + + while (*cp) { + char *bp = work; + char *typestr = bp; + unsigned char *valstr; + int nid; + int ismulti = nextismulti; + nextismulti = 0; + + /* Collect the type */ + while (*cp && *cp != '=') + *bp++ = *cp++; + if (*cp == '\0') { + BIO_printf(bio_err, + "%s: Hit end of string before finding the equals.\n", + opt_getprog()); + goto err; + } + *bp++ = '\0'; + ++cp; + + /* Collect the value. */ + valstr = (unsigned char *)bp; + for (; *cp && *cp != '/'; *bp++ = *cp++) { + if (canmulti && *cp == '+') { + nextismulti = 1; + break; + } + if (*cp == '\\' && *++cp == '\0') { + BIO_printf(bio_err, + "%s: escape character at end of string\n", + opt_getprog()); + goto err; + } + } + *bp++ = '\0'; + + /* If not at EOS (must be + or /), move forward. */ + if (*cp) + ++cp; + + /* Parse */ + nid = OBJ_txt2nid(typestr); + if (nid == NID_undef) { + BIO_printf(bio_err, "%s: Skipping unknown attribute \"%s\"\n", + opt_getprog(), typestr); + continue; + } + if (*valstr == '\0') { + BIO_printf(bio_err, + "%s: No value provided for Subject Attribute %s, skipped\n", + opt_getprog(), typestr); + continue; + } + if (!X509_NAME_add_entry_by_NID(n, nid, chtype, + valstr, strlen((char *)valstr), + -1, ismulti ? -1 : 0)) + goto err; + } + + OPENSSL_free(work); + return n; + + err: + X509_NAME_free(n); + OPENSSL_free(work); + return NULL; +} + +/* + * Read whole contents of a BIO into an allocated memory buffer and return + * it. + */ + +int bio_to_mem(unsigned char **out, int maxlen, BIO *in) +{ + BIO *mem; + int len, ret; + unsigned char tbuf[1024]; + + mem = BIO_new(BIO_s_mem()); + if (mem == NULL) + return -1; + for (;;) { + if ((maxlen != -1) && maxlen < 1024) + len = maxlen; + else + len = 1024; + len = BIO_read(in, tbuf, len); + if (len < 0) { + BIO_free(mem); + return -1; + } + if (len == 0) + break; + if (BIO_write(mem, tbuf, len) != len) { + BIO_free(mem); + return -1; + } + maxlen -= len; + + if (maxlen == 0) + break; + } + ret = BIO_get_mem_data(mem, (char **)out); + BIO_set_flags(mem, BIO_FLAGS_MEM_RDONLY); + BIO_free(mem); + return ret; +} + +int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value) +{ + int rv; + char *stmp, *vtmp = NULL; + stmp = OPENSSL_strdup(value); + if (!stmp) + return -1; + vtmp = strchr(stmp, ':'); + if (vtmp) { + *vtmp = 0; + vtmp++; + } + rv = EVP_PKEY_CTX_ctrl_str(ctx, stmp, vtmp); + OPENSSL_free(stmp); + return rv; +} + +static void nodes_print(const char *name, STACK_OF(X509_POLICY_NODE) *nodes) +{ + X509_POLICY_NODE *node; + int i; + + BIO_printf(bio_err, "%s Policies:", name); + if (nodes) { + BIO_puts(bio_err, "\n"); + for (i = 0; i < sk_X509_POLICY_NODE_num(nodes); i++) { + node = sk_X509_POLICY_NODE_value(nodes, i); + X509_POLICY_NODE_print(bio_err, node, 2); + } + } else { + BIO_puts(bio_err, " \n"); + } +} + +void policies_print(X509_STORE_CTX *ctx) +{ + X509_POLICY_TREE *tree; + int explicit_policy; + tree = X509_STORE_CTX_get0_policy_tree(ctx); + explicit_policy = X509_STORE_CTX_get_explicit_policy(ctx); + + BIO_printf(bio_err, "Require explicit Policy: %s\n", + explicit_policy ? "True" : "False"); + + nodes_print("Authority", X509_policy_tree_get0_policies(tree)); + nodes_print("User", X509_policy_tree_get0_user_policies(tree)); +} + +/*- + * next_protos_parse parses a comma separated list of strings into a string + * in a format suitable for passing to SSL_CTX_set_next_protos_advertised. + * outlen: (output) set to the length of the resulting buffer on success. + * err: (maybe NULL) on failure, an error message line is written to this BIO. + * in: a NUL terminated string like "abc,def,ghi" + * + * returns: a malloc'd buffer or NULL on failure. + */ +unsigned char *next_protos_parse(size_t *outlen, const char *in) +{ + size_t len; + unsigned char *out; + size_t i, start = 0; + + len = strlen(in); + if (len >= 65535) + return NULL; + + out = app_malloc(strlen(in) + 1, "NPN buffer"); + for (i = 0; i <= len; ++i) { + if (i == len || in[i] == ',') { + if (i - start > 255) { + OPENSSL_free(out); + return NULL; + } + out[start] = (unsigned char)(i - start); + start = i + 1; + } else { + out[i + 1] = in[i]; + } + } + + *outlen = len + 1; + return out; +} + +void print_cert_checks(BIO *bio, X509 *x, + const char *checkhost, + const char *checkemail, const char *checkip) +{ + if (x == NULL) + return; + if (checkhost) { + BIO_printf(bio, "Hostname %s does%s match certificate\n", + checkhost, + X509_check_host(x, checkhost, 0, 0, NULL) == 1 + ? "" : " NOT"); + } + + if (checkemail) { + BIO_printf(bio, "Email %s does%s match certificate\n", + checkemail, X509_check_email(x, checkemail, 0, 0) + ? "" : " NOT"); + } + + if (checkip) { + BIO_printf(bio, "IP %s does%s match certificate\n", + checkip, X509_check_ip_asc(x, checkip, 0) ? "" : " NOT"); + } +} + +/* Get first http URL from a DIST_POINT structure */ + +static const char *get_dp_url(DIST_POINT *dp) +{ + GENERAL_NAMES *gens; + GENERAL_NAME *gen; + int i, gtype; + ASN1_STRING *uri; + if (!dp->distpoint || dp->distpoint->type != 0) + return NULL; + gens = dp->distpoint->name.fullname; + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { + gen = sk_GENERAL_NAME_value(gens, i); + uri = GENERAL_NAME_get0_value(gen, >ype); + if (gtype == GEN_URI && ASN1_STRING_length(uri) > 6) { + const char *uptr = (const char *)ASN1_STRING_get0_data(uri); + if (strncmp(uptr, "http://", 7) == 0) + return uptr; + } + } + return NULL; +} + +/* + * Look through a CRLDP structure and attempt to find an http URL to + * downloads a CRL from. + */ + +static X509_CRL *load_crl_crldp(STACK_OF(DIST_POINT) *crldp) +{ + int i; + const char *urlptr = NULL; + for (i = 0; i < sk_DIST_POINT_num(crldp); i++) { + DIST_POINT *dp = sk_DIST_POINT_value(crldp, i); + urlptr = get_dp_url(dp); + if (urlptr) + return load_crl(urlptr, FORMAT_HTTP); + } + return NULL; +} + +/* + * Example of downloading CRLs from CRLDP: not usable for real world as it + * always downloads, doesn't support non-blocking I/O and doesn't cache + * anything. + */ + +static STACK_OF(X509_CRL) *crls_http_cb(X509_STORE_CTX *ctx, X509_NAME *nm) +{ + X509 *x; + STACK_OF(X509_CRL) *crls = NULL; + X509_CRL *crl; + STACK_OF(DIST_POINT) *crldp; + + crls = sk_X509_CRL_new_null(); + if (!crls) + return NULL; + x = X509_STORE_CTX_get_current_cert(ctx); + crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL); + crl = load_crl_crldp(crldp); + sk_DIST_POINT_pop_free(crldp, DIST_POINT_free); + if (!crl) { + sk_X509_CRL_free(crls); + return NULL; + } + sk_X509_CRL_push(crls, crl); + /* Try to download delta CRL */ + crldp = X509_get_ext_d2i(x, NID_freshest_crl, NULL, NULL); + crl = load_crl_crldp(crldp); + sk_DIST_POINT_pop_free(crldp, DIST_POINT_free); + if (crl) + sk_X509_CRL_push(crls, crl); + return crls; +} + +void store_setup_crl_download(X509_STORE *st) +{ + X509_STORE_set_lookup_crls_cb(st, crls_http_cb); +} + +/* + * Platform-specific sections + */ +#if defined(_WIN32) +# ifdef fileno +# undef fileno +# define fileno(a) (int)_fileno(a) +# endif + +# include +# include + +static int WIN32_rename(const char *from, const char *to) +{ + TCHAR *tfrom = NULL, *tto; + DWORD err; + int ret = 0; + + if (sizeof(TCHAR) == 1) { + tfrom = (TCHAR *)from; + tto = (TCHAR *)to; + } else { /* UNICODE path */ + + size_t i, flen = strlen(from) + 1, tlen = strlen(to) + 1; + tfrom = malloc(sizeof(*tfrom) * (flen + tlen)); + if (tfrom == NULL) + goto err; + tto = tfrom + flen; +# if !defined(_WIN32_WCE) || _WIN32_WCE>=101 + if (!MultiByteToWideChar(CP_ACP, 0, from, flen, (WCHAR *)tfrom, flen)) +# endif + for (i = 0; i < flen; i++) + tfrom[i] = (TCHAR)from[i]; +# if !defined(_WIN32_WCE) || _WIN32_WCE>=101 + if (!MultiByteToWideChar(CP_ACP, 0, to, tlen, (WCHAR *)tto, tlen)) +# endif + for (i = 0; i < tlen; i++) + tto[i] = (TCHAR)to[i]; + } + + if (MoveFile(tfrom, tto)) + goto ok; + err = GetLastError(); + if (err == ERROR_ALREADY_EXISTS || err == ERROR_FILE_EXISTS) { + if (DeleteFile(tto) && MoveFile(tfrom, tto)) + goto ok; + err = GetLastError(); + } + if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) + errno = ENOENT; + else if (err == ERROR_ACCESS_DENIED) + errno = EACCES; + else + errno = EINVAL; /* we could map more codes... */ + err: + ret = -1; + ok: + if (tfrom != NULL && tfrom != (TCHAR *)from) + free(tfrom); + return ret; +} +#endif + +/* app_tminterval section */ +#if defined(_WIN32) +double app_tminterval(int stop, int usertime) +{ + FILETIME now; + double ret = 0; + static ULARGE_INTEGER tmstart; + static int warning = 1; +# ifdef _WIN32_WINNT + static HANDLE proc = NULL; + + if (proc == NULL) { + if (check_winnt()) + proc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, + GetCurrentProcessId()); + if (proc == NULL) + proc = (HANDLE) - 1; + } + + if (usertime && proc != (HANDLE) - 1) { + FILETIME junk; + GetProcessTimes(proc, &junk, &junk, &junk, &now); + } else +# endif + { + SYSTEMTIME systime; + + if (usertime && warning) { + BIO_printf(bio_err, "To get meaningful results, run " + "this program on idle system.\n"); + warning = 0; + } + GetSystemTime(&systime); + SystemTimeToFileTime(&systime, &now); + } + + if (stop == TM_START) { + tmstart.u.LowPart = now.dwLowDateTime; + tmstart.u.HighPart = now.dwHighDateTime; + } else { + ULARGE_INTEGER tmstop; + + tmstop.u.LowPart = now.dwLowDateTime; + tmstop.u.HighPart = now.dwHighDateTime; + + ret = (__int64)(tmstop.QuadPart - tmstart.QuadPart) * 1e-7; + } + + return ret; +} +#elif defined(OPENSSL_SYS_VXWORKS) +# include + +double app_tminterval(int stop, int usertime) +{ + double ret = 0; +# ifdef CLOCK_REALTIME + static struct timespec tmstart; + struct timespec now; +# else + static unsigned long tmstart; + unsigned long now; +# endif + static int warning = 1; + + if (usertime && warning) { + BIO_printf(bio_err, "To get meaningful results, run " + "this program on idle system.\n"); + warning = 0; + } +# ifdef CLOCK_REALTIME + clock_gettime(CLOCK_REALTIME, &now); + if (stop == TM_START) + tmstart = now; + else + ret = ((now.tv_sec + now.tv_nsec * 1e-9) + - (tmstart.tv_sec + tmstart.tv_nsec * 1e-9)); +# else + now = tickGet(); + if (stop == TM_START) + tmstart = now; + else + ret = (now - tmstart) / (double)sysClkRateGet(); +# endif + return ret; +} + +#elif defined(OPENSSL_SYSTEM_VMS) +# include +# include + +double app_tminterval(int stop, int usertime) +{ + static clock_t tmstart; + double ret = 0; + clock_t now; +# ifdef __TMS + struct tms rus; + + now = times(&rus); + if (usertime) + now = rus.tms_utime; +# else + if (usertime) + now = clock(); /* sum of user and kernel times */ + else { + struct timeval tv; + gettimeofday(&tv, NULL); + now = (clock_t)((unsigned long long)tv.tv_sec * CLK_TCK + + (unsigned long long)tv.tv_usec * (1000000 / CLK_TCK) + ); + } +# endif + if (stop == TM_START) + tmstart = now; + else + ret = (now - tmstart) / (double)(CLK_TCK); + + return ret; +} + +#elif defined(_SC_CLK_TCK) /* by means of unistd.h */ +# include + +double app_tminterval(int stop, int usertime) +{ + double ret = 0; + struct tms rus; + clock_t now = times(&rus); + static clock_t tmstart; + + if (usertime) + now = rus.tms_utime; + + if (stop == TM_START) { + tmstart = now; + } else { + long int tck = sysconf(_SC_CLK_TCK); + ret = (now - tmstart) / (double)tck; + } + + return ret; +} + +#else +# include +# include + +double app_tminterval(int stop, int usertime) +{ + double ret = 0; + struct rusage rus; + struct timeval now; + static struct timeval tmstart; + + if (usertime) + getrusage(RUSAGE_SELF, &rus), now = rus.ru_utime; + else + gettimeofday(&now, NULL); + + if (stop == TM_START) + tmstart = now; + else + ret = ((now.tv_sec + now.tv_usec * 1e-6) + - (tmstart.tv_sec + tmstart.tv_usec * 1e-6)); + + return ret; +} +#endif + +int app_access(const char* name, int flag) +{ +#ifdef _WIN32 + return _access(name, flag); +#else + return access(name, flag); +#endif +} + +/* app_isdir section */ +#ifdef _WIN32 +int app_isdir(const char *name) +{ + DWORD attr; +# if defined(UNICODE) || defined(_UNICODE) + size_t i, len_0 = strlen(name) + 1; + WCHAR tempname[MAX_PATH]; + + if (len_0 > MAX_PATH) + return -1; + +# if !defined(_WIN32_WCE) || _WIN32_WCE>=101 + if (!MultiByteToWideChar(CP_ACP, 0, name, len_0, tempname, MAX_PATH)) +# endif + for (i = 0; i < len_0; i++) + tempname[i] = (WCHAR)name[i]; + + attr = GetFileAttributes(tempname); +# else + attr = GetFileAttributes(name); +# endif + if (attr == INVALID_FILE_ATTRIBUTES) + return -1; + return ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0); +} +#else +# include +# ifndef S_ISDIR +# if defined(_S_IFMT) && defined(_S_IFDIR) +# define S_ISDIR(a) (((a) & _S_IFMT) == _S_IFDIR) +# else +# define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR) +# endif +# endif + +int app_isdir(const char *name) +{ +# if defined(S_ISDIR) + struct stat st; + + if (stat(name, &st) == 0) + return S_ISDIR(st.st_mode); + else + return -1; +# else + return -1; +# endif +} +#endif + +/* raw_read|write section */ +#if defined(__VMS) +# include "vms_term_sock.h" +static int stdin_sock = -1; + +static void close_stdin_sock(void) +{ + TerminalSocket (TERM_SOCK_DELETE, &stdin_sock); +} + +int fileno_stdin(void) +{ + if (stdin_sock == -1) { + TerminalSocket(TERM_SOCK_CREATE, &stdin_sock); + atexit(close_stdin_sock); + } + + return stdin_sock; +} +#else +int fileno_stdin(void) +{ + return fileno(stdin); +} +#endif + +int fileno_stdout(void) +{ + return fileno(stdout); +} + +#if defined(_WIN32) && defined(STD_INPUT_HANDLE) +int raw_read_stdin(void *buf, int siz) +{ + DWORD n; + if (ReadFile(GetStdHandle(STD_INPUT_HANDLE), buf, siz, &n, NULL)) + return n; + else + return -1; +} +#elif defined(__VMS) +# include + +int raw_read_stdin(void *buf, int siz) +{ + return recv(fileno_stdin(), buf, siz, 0); +} +#else +int raw_read_stdin(void *buf, int siz) +{ + return read(fileno_stdin(), buf, siz); +} +#endif + +#if defined(_WIN32) && defined(STD_OUTPUT_HANDLE) +int raw_write_stdout(const void *buf, int siz) +{ + DWORD n; + if (WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, siz, &n, NULL)) + return n; + else + return -1; +} +#else +int raw_write_stdout(const void *buf, int siz) +{ + return write(fileno_stdout(), buf, siz); +} +#endif + +/* + * Centralized handling if input and output files with format specification + * The format is meant to show what the input and output is supposed to be, + * and is therefore a show of intent more than anything else. However, it + * does impact behavior on some platform, such as differentiating between + * text and binary input/output on non-Unix platforms + */ +static int istext(int format) +{ + return (format & B_FORMAT_TEXT) == B_FORMAT_TEXT; +} + +BIO *dup_bio_in(int format) +{ + return BIO_new_fp(stdin, + BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0)); +} + +static BIO_METHOD *prefix_method = NULL; + +BIO *dup_bio_out(int format) +{ + BIO *b = BIO_new_fp(stdout, + BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0)); + void *prefix = NULL; + +#ifdef OPENSSL_SYS_VMS + if (istext(format)) + b = BIO_push(BIO_new(BIO_f_linebuffer()), b); +#endif + + if (istext(format) && (prefix = getenv("HARNESS_OSSL_PREFIX")) != NULL) { + if (prefix_method == NULL) + prefix_method = apps_bf_prefix(); + b = BIO_push(BIO_new(prefix_method), b); + BIO_ctrl(b, PREFIX_CTRL_SET_PREFIX, 0, prefix); + } + + return b; +} + +BIO *dup_bio_err(int format) +{ + BIO *b = BIO_new_fp(stderr, + BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0)); +#ifdef OPENSSL_SYS_VMS + if (istext(format)) + b = BIO_push(BIO_new(BIO_f_linebuffer()), b); +#endif + return b; +} + +void destroy_prefix_method(void) +{ + BIO_meth_free(prefix_method); + prefix_method = NULL; +} + +void unbuffer(FILE *fp) +{ +/* + * On VMS, setbuf() will only take 32-bit pointers, and a compilation + * with /POINTER_SIZE=64 will give off a MAYLOSEDATA2 warning here. + * However, we trust that the C RTL will never give us a FILE pointer + * above the first 4 GB of memory, so we simply turn off the warning + * temporarily. + */ +#if defined(OPENSSL_SYS_VMS) && defined(__DECC) +# pragma environment save +# pragma message disable maylosedata2 +#endif + setbuf(fp, NULL); +#if defined(OPENSSL_SYS_VMS) && defined(__DECC) +# pragma environment restore +#endif +} + +static const char *modestr(char mode, int format) +{ + OPENSSL_assert(mode == 'a' || mode == 'r' || mode == 'w'); + + switch (mode) { + case 'a': + return istext(format) ? "a" : "ab"; + case 'r': + return istext(format) ? "r" : "rb"; + case 'w': + return istext(format) ? "w" : "wb"; + } + /* The assert above should make sure we never reach this point */ + return NULL; +} + +static const char *modeverb(char mode) +{ + switch (mode) { + case 'a': + return "appending"; + case 'r': + return "reading"; + case 'w': + return "writing"; + } + return "(doing something)"; +} + +/* + * Open a file for writing, owner-read-only. + */ +BIO *bio_open_owner(const char *filename, int format, int private) +{ + FILE *fp = NULL; + BIO *b = NULL; + int fd = -1, bflags, mode, textmode; + + if (!private || filename == NULL || strcmp(filename, "-") == 0) + return bio_open_default(filename, 'w', format); + + mode = O_WRONLY; +#ifdef O_CREAT + mode |= O_CREAT; +#endif +#ifdef O_TRUNC + mode |= O_TRUNC; +#endif + textmode = istext(format); + if (!textmode) { +#ifdef O_BINARY + mode |= O_BINARY; +#elif defined(_O_BINARY) + mode |= _O_BINARY; +#endif + } + +#ifdef OPENSSL_SYS_VMS + /* VMS doesn't have O_BINARY, it just doesn't make sense. But, + * it still needs to know that we're going binary, or fdopen() + * will fail with "invalid argument"... so we tell VMS what the + * context is. + */ + if (!textmode) + fd = open(filename, mode, 0600, "ctx=bin"); + else +#endif + fd = open(filename, mode, 0600); + if (fd < 0) + goto err; + fp = fdopen(fd, modestr('w', format)); + if (fp == NULL) + goto err; + bflags = BIO_CLOSE; + if (textmode) + bflags |= BIO_FP_TEXT; + b = BIO_new_fp(fp, bflags); + if (b) + return b; + + err: + BIO_printf(bio_err, "%s: Can't open \"%s\" for writing, %s\n", + opt_getprog(), filename, strerror(errno)); + ERR_print_errors(bio_err); + /* If we have fp, then fdopen took over fd, so don't close both. */ + if (fp) + fclose(fp); + else if (fd >= 0) + close(fd); + return NULL; +} + +static BIO *bio_open_default_(const char *filename, char mode, int format, + int quiet) +{ + BIO *ret; + + if (filename == NULL || strcmp(filename, "-") == 0) { + ret = mode == 'r' ? dup_bio_in(format) : dup_bio_out(format); + if (quiet) { + ERR_clear_error(); + return ret; + } + if (ret != NULL) + return ret; + BIO_printf(bio_err, + "Can't open %s, %s\n", + mode == 'r' ? "stdin" : "stdout", strerror(errno)); + } else { + ret = BIO_new_file(filename, modestr(mode, format)); + if (quiet) { + ERR_clear_error(); + return ret; + } + if (ret != NULL) + return ret; + BIO_printf(bio_err, + "Can't open %s for %s, %s\n", + filename, modeverb(mode), strerror(errno)); + } + ERR_print_errors(bio_err); + return NULL; +} + +BIO *bio_open_default(const char *filename, char mode, int format) +{ + return bio_open_default_(filename, mode, format, 0); +} + +BIO *bio_open_default_quiet(const char *filename, char mode, int format) +{ + return bio_open_default_(filename, mode, format, 1); +} + +void wait_for_async(SSL *s) +{ + /* On Windows select only works for sockets, so we simply don't wait */ +#ifndef OPENSSL_SYS_WINDOWS + int width = 0; + fd_set asyncfds; + OSSL_ASYNC_FD *fds; + size_t numfds; + size_t i; + + if (!SSL_get_all_async_fds(s, NULL, &numfds)) + return; + if (numfds == 0) + return; + fds = app_malloc(sizeof(OSSL_ASYNC_FD) * numfds, "allocate async fds"); + if (!SSL_get_all_async_fds(s, fds, &numfds)) { + OPENSSL_free(fds); + return; + } + + FD_ZERO(&asyncfds); + for (i = 0; i < numfds; i++) { + if (width <= (int)fds[i]) + width = (int)fds[i] + 1; + openssl_fdset((int)fds[i], &asyncfds); + } + select(width, (void *)&asyncfds, NULL, NULL, NULL); + OPENSSL_free(fds); +#endif +} + +/* if OPENSSL_SYS_WINDOWS is defined then so is OPENSSL_SYS_MSDOS */ +#if defined(OPENSSL_SYS_MSDOS) +int has_stdin_waiting(void) +{ +# if defined(OPENSSL_SYS_WINDOWS) + HANDLE inhand = GetStdHandle(STD_INPUT_HANDLE); + DWORD events = 0; + INPUT_RECORD inputrec; + DWORD insize = 1; + BOOL peeked; + + if (inhand == INVALID_HANDLE_VALUE) { + return 0; + } + + peeked = PeekConsoleInput(inhand, &inputrec, insize, &events); + if (!peeked) { + /* Probably redirected input? _kbhit() does not work in this case */ + if (!feof(stdin)) { + return 1; + } + return 0; + } +# endif + return _kbhit(); +} +#endif + +/* Corrupt a signature by modifying final byte */ +void corrupt_signature(const ASN1_STRING *signature) +{ + unsigned char *s = signature->data; + s[signature->length - 1] ^= 0x1; +} + +int set_cert_times(X509 *x, const char *startdate, const char *enddate, + int days) +{ + if (startdate == NULL || strcmp(startdate, "today") == 0) { + if (X509_gmtime_adj(X509_getm_notBefore(x), 0) == NULL) + return 0; + } else { + if (!ASN1_TIME_set_string_X509(X509_getm_notBefore(x), startdate)) + return 0; + } + if (enddate == NULL) { + if (X509_time_adj_ex(X509_getm_notAfter(x), days, 0, NULL) + == NULL) + return 0; + } else if (!ASN1_TIME_set_string_X509(X509_getm_notAfter(x), enddate)) { + return 0; + } + return 1; +} + +void make_uppercase(char *string) +{ + int i; + + for (i = 0; string[i] != '\0'; i++) + string[i] = toupper((unsigned char)string[i]); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/apps.h b/trunk/3rdparty/openssl-1.1-fit/apps/apps.h new file mode 100644 index 000000000..d9eb650eb --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/apps.h @@ -0,0 +1,634 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_APPS_H +# define HEADER_APPS_H + +# include "e_os.h" /* struct timeval for DTLS */ +# include "internal/nelem.h" +# include + +# include +# ifndef OPENSSL_NO_POSIX_IO +# include +# include +# endif + +# include +# include +# include +# include +# include +# include +# include +# include +# include + +# if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WINCE) +# define openssl_fdset(a,b) FD_SET((unsigned int)a, b) +# else +# define openssl_fdset(a,b) FD_SET(a, b) +# endif + +/* + * quick macro when you need to pass an unsigned char instead of a char. + * this is true for some implementations of the is*() functions, for + * example. + */ +#define _UC(c) ((unsigned char)(c)) + +void app_RAND_load_conf(CONF *c, const char *section); +void app_RAND_write(void); + +extern char *default_config_file; +extern BIO *bio_in; +extern BIO *bio_out; +extern BIO *bio_err; +extern const unsigned char tls13_aes128gcmsha256_id[]; +extern const unsigned char tls13_aes256gcmsha384_id[]; +extern BIO_ADDR *ourpeer; + +BIO_METHOD *apps_bf_prefix(void); +/* + * The control used to set the prefix with BIO_ctrl() + * We make it high enough so the chance of ever clashing with the BIO library + * remains unlikely for the foreseeable future and beyond. + */ +#define PREFIX_CTRL_SET_PREFIX (1 << 15) +/* + * apps_bf_prefix() returns a dynamically created BIO_METHOD, which we + * need to destroy at some point. When created internally, it's stored + * in an internal pointer which can be freed with the following function + */ +void destroy_prefix_method(void); + +BIO *dup_bio_in(int format); +BIO *dup_bio_out(int format); +BIO *dup_bio_err(int format); +BIO *bio_open_owner(const char *filename, int format, int private); +BIO *bio_open_default(const char *filename, char mode, int format); +BIO *bio_open_default_quiet(const char *filename, char mode, int format); +CONF *app_load_config_bio(BIO *in, const char *filename); +CONF *app_load_config(const char *filename); +CONF *app_load_config_quiet(const char *filename); +int app_load_modules(const CONF *config); +void unbuffer(FILE *fp); +void wait_for_async(SSL *s); +# if defined(OPENSSL_SYS_MSDOS) +int has_stdin_waiting(void); +# endif + +void corrupt_signature(const ASN1_STRING *signature); +int set_cert_times(X509 *x, const char *startdate, const char *enddate, + int days); + +/* + * Common verification options. + */ +# define OPT_V_ENUM \ + OPT_V__FIRST=2000, \ + OPT_V_POLICY, OPT_V_PURPOSE, OPT_V_VERIFY_NAME, OPT_V_VERIFY_DEPTH, \ + OPT_V_ATTIME, OPT_V_VERIFY_HOSTNAME, OPT_V_VERIFY_EMAIL, \ + OPT_V_VERIFY_IP, OPT_V_IGNORE_CRITICAL, OPT_V_ISSUER_CHECKS, \ + OPT_V_CRL_CHECK, OPT_V_CRL_CHECK_ALL, OPT_V_POLICY_CHECK, \ + OPT_V_EXPLICIT_POLICY, OPT_V_INHIBIT_ANY, OPT_V_INHIBIT_MAP, \ + OPT_V_X509_STRICT, OPT_V_EXTENDED_CRL, OPT_V_USE_DELTAS, \ + OPT_V_POLICY_PRINT, OPT_V_CHECK_SS_SIG, OPT_V_TRUSTED_FIRST, \ + OPT_V_SUITEB_128_ONLY, OPT_V_SUITEB_128, OPT_V_SUITEB_192, \ + OPT_V_PARTIAL_CHAIN, OPT_V_NO_ALT_CHAINS, OPT_V_NO_CHECK_TIME, \ + OPT_V_VERIFY_AUTH_LEVEL, OPT_V_ALLOW_PROXY_CERTS, \ + OPT_V__LAST + +# define OPT_V_OPTIONS \ + { "policy", OPT_V_POLICY, 's', "adds policy to the acceptable policy set"}, \ + { "purpose", OPT_V_PURPOSE, 's', \ + "certificate chain purpose"}, \ + { "verify_name", OPT_V_VERIFY_NAME, 's', "verification policy name"}, \ + { "verify_depth", OPT_V_VERIFY_DEPTH, 'n', \ + "chain depth limit" }, \ + { "auth_level", OPT_V_VERIFY_AUTH_LEVEL, 'n', \ + "chain authentication security level" }, \ + { "attime", OPT_V_ATTIME, 'M', "verification epoch time" }, \ + { "verify_hostname", OPT_V_VERIFY_HOSTNAME, 's', \ + "expected peer hostname" }, \ + { "verify_email", OPT_V_VERIFY_EMAIL, 's', \ + "expected peer email" }, \ + { "verify_ip", OPT_V_VERIFY_IP, 's', \ + "expected peer IP address" }, \ + { "ignore_critical", OPT_V_IGNORE_CRITICAL, '-', \ + "permit unhandled critical extensions"}, \ + { "issuer_checks", OPT_V_ISSUER_CHECKS, '-', "(deprecated)"}, \ + { "crl_check", OPT_V_CRL_CHECK, '-', "check leaf certificate revocation" }, \ + { "crl_check_all", OPT_V_CRL_CHECK_ALL, '-', "check full chain revocation" }, \ + { "policy_check", OPT_V_POLICY_CHECK, '-', "perform rfc5280 policy checks"}, \ + { "explicit_policy", OPT_V_EXPLICIT_POLICY, '-', \ + "set policy variable require-explicit-policy"}, \ + { "inhibit_any", OPT_V_INHIBIT_ANY, '-', \ + "set policy variable inhibit-any-policy"}, \ + { "inhibit_map", OPT_V_INHIBIT_MAP, '-', \ + "set policy variable inhibit-policy-mapping"}, \ + { "x509_strict", OPT_V_X509_STRICT, '-', \ + "disable certificate compatibility work-arounds"}, \ + { "extended_crl", OPT_V_EXTENDED_CRL, '-', \ + "enable extended CRL features"}, \ + { "use_deltas", OPT_V_USE_DELTAS, '-', \ + "use delta CRLs"}, \ + { "policy_print", OPT_V_POLICY_PRINT, '-', \ + "print policy processing diagnostics"}, \ + { "check_ss_sig", OPT_V_CHECK_SS_SIG, '-', \ + "check root CA self-signatures"}, \ + { "trusted_first", OPT_V_TRUSTED_FIRST, '-', \ + "search trust store first (default)" }, \ + { "suiteB_128_only", OPT_V_SUITEB_128_ONLY, '-', "Suite B 128-bit-only mode"}, \ + { "suiteB_128", OPT_V_SUITEB_128, '-', \ + "Suite B 128-bit mode allowing 192-bit algorithms"}, \ + { "suiteB_192", OPT_V_SUITEB_192, '-', "Suite B 192-bit-only mode" }, \ + { "partial_chain", OPT_V_PARTIAL_CHAIN, '-', \ + "accept chains anchored by intermediate trust-store CAs"}, \ + { "no_alt_chains", OPT_V_NO_ALT_CHAINS, '-', "(deprecated)" }, \ + { "no_check_time", OPT_V_NO_CHECK_TIME, '-', "ignore certificate validity time" }, \ + { "allow_proxy_certs", OPT_V_ALLOW_PROXY_CERTS, '-', "allow the use of proxy certificates" } + +# define OPT_V_CASES \ + OPT_V__FIRST: case OPT_V__LAST: break; \ + case OPT_V_POLICY: \ + case OPT_V_PURPOSE: \ + case OPT_V_VERIFY_NAME: \ + case OPT_V_VERIFY_DEPTH: \ + case OPT_V_VERIFY_AUTH_LEVEL: \ + case OPT_V_ATTIME: \ + case OPT_V_VERIFY_HOSTNAME: \ + case OPT_V_VERIFY_EMAIL: \ + case OPT_V_VERIFY_IP: \ + case OPT_V_IGNORE_CRITICAL: \ + case OPT_V_ISSUER_CHECKS: \ + case OPT_V_CRL_CHECK: \ + case OPT_V_CRL_CHECK_ALL: \ + case OPT_V_POLICY_CHECK: \ + case OPT_V_EXPLICIT_POLICY: \ + case OPT_V_INHIBIT_ANY: \ + case OPT_V_INHIBIT_MAP: \ + case OPT_V_X509_STRICT: \ + case OPT_V_EXTENDED_CRL: \ + case OPT_V_USE_DELTAS: \ + case OPT_V_POLICY_PRINT: \ + case OPT_V_CHECK_SS_SIG: \ + case OPT_V_TRUSTED_FIRST: \ + case OPT_V_SUITEB_128_ONLY: \ + case OPT_V_SUITEB_128: \ + case OPT_V_SUITEB_192: \ + case OPT_V_PARTIAL_CHAIN: \ + case OPT_V_NO_ALT_CHAINS: \ + case OPT_V_NO_CHECK_TIME: \ + case OPT_V_ALLOW_PROXY_CERTS + +/* + * Common "extended validation" options. + */ +# define OPT_X_ENUM \ + OPT_X__FIRST=1000, \ + OPT_X_KEY, OPT_X_CERT, OPT_X_CHAIN, OPT_X_CHAIN_BUILD, \ + OPT_X_CERTFORM, OPT_X_KEYFORM, \ + OPT_X__LAST + +# define OPT_X_OPTIONS \ + { "xkey", OPT_X_KEY, '<', "key for Extended certificates"}, \ + { "xcert", OPT_X_CERT, '<', "cert for Extended certificates"}, \ + { "xchain", OPT_X_CHAIN, '<', "chain for Extended certificates"}, \ + { "xchain_build", OPT_X_CHAIN_BUILD, '-', \ + "build certificate chain for the extended certificates"}, \ + { "xcertform", OPT_X_CERTFORM, 'F', \ + "format of Extended certificate (PEM or DER) PEM default " }, \ + { "xkeyform", OPT_X_KEYFORM, 'F', \ + "format of Extended certificate's key (PEM or DER) PEM default"} + +# define OPT_X_CASES \ + OPT_X__FIRST: case OPT_X__LAST: break; \ + case OPT_X_KEY: \ + case OPT_X_CERT: \ + case OPT_X_CHAIN: \ + case OPT_X_CHAIN_BUILD: \ + case OPT_X_CERTFORM: \ + case OPT_X_KEYFORM + +/* + * Common SSL options. + * Any changes here must be coordinated with ../ssl/ssl_conf.c + */ +# define OPT_S_ENUM \ + OPT_S__FIRST=3000, \ + OPT_S_NOSSL3, OPT_S_NOTLS1, OPT_S_NOTLS1_1, OPT_S_NOTLS1_2, \ + OPT_S_NOTLS1_3, OPT_S_BUGS, OPT_S_NO_COMP, OPT_S_NOTICKET, \ + OPT_S_SERVERPREF, OPT_S_LEGACYRENEG, OPT_S_LEGACYCONN, \ + OPT_S_ONRESUMP, OPT_S_NOLEGACYCONN, OPT_S_ALLOW_NO_DHE_KEX, \ + OPT_S_PRIORITIZE_CHACHA, \ + OPT_S_STRICT, OPT_S_SIGALGS, OPT_S_CLIENTSIGALGS, OPT_S_GROUPS, \ + OPT_S_CURVES, OPT_S_NAMEDCURVE, OPT_S_CIPHER, OPT_S_CIPHERSUITES, \ + OPT_S_RECORD_PADDING, OPT_S_DEBUGBROKE, OPT_S_COMP, \ + OPT_S_MINPROTO, OPT_S_MAXPROTO, \ + OPT_S_NO_RENEGOTIATION, OPT_S_NO_MIDDLEBOX, OPT_S__LAST + +# define OPT_S_OPTIONS \ + {"no_ssl3", OPT_S_NOSSL3, '-',"Just disable SSLv3" }, \ + {"no_tls1", OPT_S_NOTLS1, '-', "Just disable TLSv1"}, \ + {"no_tls1_1", OPT_S_NOTLS1_1, '-', "Just disable TLSv1.1" }, \ + {"no_tls1_2", OPT_S_NOTLS1_2, '-', "Just disable TLSv1.2"}, \ + {"no_tls1_3", OPT_S_NOTLS1_3, '-', "Just disable TLSv1.3"}, \ + {"bugs", OPT_S_BUGS, '-', "Turn on SSL bug compatibility"}, \ + {"no_comp", OPT_S_NO_COMP, '-', "Disable SSL/TLS compression (default)" }, \ + {"comp", OPT_S_COMP, '-', "Use SSL/TLS-level compression" }, \ + {"no_ticket", OPT_S_NOTICKET, '-', \ + "Disable use of TLS session tickets"}, \ + {"serverpref", OPT_S_SERVERPREF, '-', "Use server's cipher preferences"}, \ + {"legacy_renegotiation", OPT_S_LEGACYRENEG, '-', \ + "Enable use of legacy renegotiation (dangerous)"}, \ + {"no_renegotiation", OPT_S_NO_RENEGOTIATION, '-', \ + "Disable all renegotiation."}, \ + {"legacy_server_connect", OPT_S_LEGACYCONN, '-', \ + "Allow initial connection to servers that don't support RI"}, \ + {"no_resumption_on_reneg", OPT_S_ONRESUMP, '-', \ + "Disallow session resumption on renegotiation"}, \ + {"no_legacy_server_connect", OPT_S_NOLEGACYCONN, '-', \ + "Disallow initial connection to servers that don't support RI"}, \ + {"allow_no_dhe_kex", OPT_S_ALLOW_NO_DHE_KEX, '-', \ + "In TLSv1.3 allow non-(ec)dhe based key exchange on resumption"}, \ + {"prioritize_chacha", OPT_S_PRIORITIZE_CHACHA, '-', \ + "Prioritize ChaCha ciphers when preferred by clients"}, \ + {"strict", OPT_S_STRICT, '-', \ + "Enforce strict certificate checks as per TLS standard"}, \ + {"sigalgs", OPT_S_SIGALGS, 's', \ + "Signature algorithms to support (colon-separated list)" }, \ + {"client_sigalgs", OPT_S_CLIENTSIGALGS, 's', \ + "Signature algorithms to support for client certificate" \ + " authentication (colon-separated list)" }, \ + {"groups", OPT_S_GROUPS, 's', \ + "Groups to advertise (colon-separated list)" }, \ + {"curves", OPT_S_CURVES, 's', \ + "Groups to advertise (colon-separated list)" }, \ + {"named_curve", OPT_S_NAMEDCURVE, 's', \ + "Elliptic curve used for ECDHE (server-side only)" }, \ + {"cipher", OPT_S_CIPHER, 's', "Specify TLSv1.2 and below cipher list to be used"}, \ + {"ciphersuites", OPT_S_CIPHERSUITES, 's', "Specify TLSv1.3 ciphersuites to be used"}, \ + {"min_protocol", OPT_S_MINPROTO, 's', "Specify the minimum protocol version to be used"}, \ + {"max_protocol", OPT_S_MAXPROTO, 's', "Specify the maximum protocol version to be used"}, \ + {"record_padding", OPT_S_RECORD_PADDING, 's', \ + "Block size to pad TLS 1.3 records to."}, \ + {"debug_broken_protocol", OPT_S_DEBUGBROKE, '-', \ + "Perform all sorts of protocol violations for testing purposes"}, \ + {"no_middlebox", OPT_S_NO_MIDDLEBOX, '-', \ + "Disable TLSv1.3 middlebox compat mode" } + +# define OPT_S_CASES \ + OPT_S__FIRST: case OPT_S__LAST: break; \ + case OPT_S_NOSSL3: \ + case OPT_S_NOTLS1: \ + case OPT_S_NOTLS1_1: \ + case OPT_S_NOTLS1_2: \ + case OPT_S_NOTLS1_3: \ + case OPT_S_BUGS: \ + case OPT_S_NO_COMP: \ + case OPT_S_COMP: \ + case OPT_S_NOTICKET: \ + case OPT_S_SERVERPREF: \ + case OPT_S_LEGACYRENEG: \ + case OPT_S_LEGACYCONN: \ + case OPT_S_ONRESUMP: \ + case OPT_S_NOLEGACYCONN: \ + case OPT_S_ALLOW_NO_DHE_KEX: \ + case OPT_S_PRIORITIZE_CHACHA: \ + case OPT_S_STRICT: \ + case OPT_S_SIGALGS: \ + case OPT_S_CLIENTSIGALGS: \ + case OPT_S_GROUPS: \ + case OPT_S_CURVES: \ + case OPT_S_NAMEDCURVE: \ + case OPT_S_CIPHER: \ + case OPT_S_CIPHERSUITES: \ + case OPT_S_RECORD_PADDING: \ + case OPT_S_NO_RENEGOTIATION: \ + case OPT_S_MINPROTO: \ + case OPT_S_MAXPROTO: \ + case OPT_S_DEBUGBROKE: \ + case OPT_S_NO_MIDDLEBOX + +#define IS_NO_PROT_FLAG(o) \ + (o == OPT_S_NOSSL3 || o == OPT_S_NOTLS1 || o == OPT_S_NOTLS1_1 \ + || o == OPT_S_NOTLS1_2 || o == OPT_S_NOTLS1_3) + +/* + * Random state options. + */ +# define OPT_R_ENUM \ + OPT_R__FIRST=1500, OPT_R_RAND, OPT_R_WRITERAND, OPT_R__LAST + +# define OPT_R_OPTIONS \ + {"rand", OPT_R_RAND, 's', "Load the file(s) into the random number generator"}, \ + {"writerand", OPT_R_WRITERAND, '>', "Write random data to the specified file"} + +# define OPT_R_CASES \ + OPT_R__FIRST: case OPT_R__LAST: break; \ + case OPT_R_RAND: case OPT_R_WRITERAND + +/* + * Option parsing. + */ +extern const char OPT_HELP_STR[]; +extern const char OPT_MORE_STR[]; +typedef struct options_st { + const char *name; + int retval; + /* + * value type: - no value (also the value zero), n number, p positive + * number, u unsigned, l long, s string, < input file, > output file, + * f any format, F der/pem format, E der/pem/engine format identifier. + * l, n and u include zero; p does not. + */ + int valtype; + const char *helpstr; +} OPTIONS; + +/* + * A string/int pairing; widely use for option value lookup, hence the + * name OPT_PAIR. But that name is misleading in s_cb.c, so we also use + * the "generic" name STRINT_PAIR. + */ +typedef struct string_int_pair_st { + const char *name; + int retval; +} OPT_PAIR, STRINT_PAIR; + +/* Flags to pass into opt_format; see FORMAT_xxx, below. */ +# define OPT_FMT_PEMDER (1L << 1) +# define OPT_FMT_PKCS12 (1L << 2) +# define OPT_FMT_SMIME (1L << 3) +# define OPT_FMT_ENGINE (1L << 4) +# define OPT_FMT_MSBLOB (1L << 5) +/* (1L << 6) was OPT_FMT_NETSCAPE, but wasn't used */ +# define OPT_FMT_NSS (1L << 7) +# define OPT_FMT_TEXT (1L << 8) +# define OPT_FMT_HTTP (1L << 9) +# define OPT_FMT_PVK (1L << 10) +# define OPT_FMT_PDE (OPT_FMT_PEMDER | OPT_FMT_ENGINE) +# define OPT_FMT_PDS (OPT_FMT_PEMDER | OPT_FMT_SMIME) +# define OPT_FMT_ANY ( \ + OPT_FMT_PEMDER | OPT_FMT_PKCS12 | OPT_FMT_SMIME | \ + OPT_FMT_ENGINE | OPT_FMT_MSBLOB | OPT_FMT_NSS | \ + OPT_FMT_TEXT | OPT_FMT_HTTP | OPT_FMT_PVK) + +char *opt_progname(const char *argv0); +char *opt_getprog(void); +char *opt_init(int ac, char **av, const OPTIONS * o); +int opt_next(void); +int opt_format(const char *s, unsigned long flags, int *result); +int opt_int(const char *arg, int *result); +int opt_ulong(const char *arg, unsigned long *result); +int opt_long(const char *arg, long *result); +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \ + defined(INTMAX_MAX) && defined(UINTMAX_MAX) +int opt_imax(const char *arg, intmax_t *result); +int opt_umax(const char *arg, uintmax_t *result); +#else +# define opt_imax opt_long +# define opt_umax opt_ulong +# define intmax_t long +# define uintmax_t unsigned long +#endif +int opt_pair(const char *arg, const OPT_PAIR * pairs, int *result); +int opt_cipher(const char *name, const EVP_CIPHER **cipherp); +int opt_md(const char *name, const EVP_MD **mdp); +char *opt_arg(void); +char *opt_flag(void); +char *opt_unknown(void); +char **opt_rest(void); +int opt_num_rest(void); +int opt_verify(int i, X509_VERIFY_PARAM *vpm); +int opt_rand(int i); +void opt_help(const OPTIONS * list); +int opt_format_error(const char *s, unsigned long flags); + +typedef struct args_st { + int size; + int argc; + char **argv; +} ARGS; + +/* + * VMS C only for now, implemented in vms_decc_init.c + * If other C compilers forget to terminate argv with NULL, this function + * can be re-used. + */ +char **copy_argv(int *argc, char *argv[]); +/* + * Win32-specific argv initialization that splits OS-supplied UNICODE + * command line string to array of UTF8-encoded strings. + */ +void win32_utf8argv(int *argc, char **argv[]); + + +# define PW_MIN_LENGTH 4 +typedef struct pw_cb_data { + const void *password; + const char *prompt_info; +} PW_CB_DATA; + +int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_data); + +int setup_ui_method(void); +void destroy_ui_method(void); +const UI_METHOD *get_ui_method(void); + +int chopup_args(ARGS *arg, char *buf); +# ifdef HEADER_X509_H +int dump_cert_text(BIO *out, X509 *x); +void print_name(BIO *out, const char *title, X509_NAME *nm, + unsigned long lflags); +# endif +void print_bignum_var(BIO *, const BIGNUM *, const char*, + int, unsigned char *); +void print_array(BIO *, const char *, int, const unsigned char *); +int set_nameopt(const char *arg); +unsigned long get_nameopt(void); +int set_cert_ex(unsigned long *flags, const char *arg); +int set_name_ex(unsigned long *flags, const char *arg); +int set_ext_copy(int *copy_type, const char *arg); +int copy_extensions(X509 *x, X509_REQ *req, int copy_type); +int app_passwd(const char *arg1, const char *arg2, char **pass1, char **pass2); +int add_oid_section(CONF *conf); +X509 *load_cert(const char *file, int format, const char *cert_descrip); +X509_CRL *load_crl(const char *infile, int format); +EVP_PKEY *load_key(const char *file, int format, int maybe_stdin, + const char *pass, ENGINE *e, const char *key_descrip); +EVP_PKEY *load_pubkey(const char *file, int format, int maybe_stdin, + const char *pass, ENGINE *e, const char *key_descrip); +int load_certs(const char *file, STACK_OF(X509) **certs, int format, + const char *pass, const char *cert_descrip); +int load_crls(const char *file, STACK_OF(X509_CRL) **crls, int format, + const char *pass, const char *cert_descrip); +X509_STORE *setup_verify(const char *CAfile, const char *CApath, + int noCAfile, int noCApath); +__owur int ctx_set_verify_locations(SSL_CTX *ctx, const char *CAfile, + const char *CApath, int noCAfile, + int noCApath); + +#ifndef OPENSSL_NO_CT + +/* + * Sets the file to load the Certificate Transparency log list from. + * If path is NULL, loads from the default file path. + * Returns 1 on success, 0 otherwise. + */ +__owur int ctx_set_ctlog_list_file(SSL_CTX *ctx, const char *path); + +#endif + +ENGINE *setup_engine(const char *engine, int debug); +void release_engine(ENGINE *e); + +# ifndef OPENSSL_NO_OCSP +OCSP_RESPONSE *process_responder(OCSP_REQUEST *req, + const char *host, const char *path, + const char *port, int use_ssl, + STACK_OF(CONF_VALUE) *headers, + int req_timeout); +# endif + +/* Functions defined in ca.c and also used in ocsp.c */ +int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, + ASN1_GENERALIZEDTIME **pinvtm, const char *str); + +# define DB_type 0 +# define DB_exp_date 1 +# define DB_rev_date 2 +# define DB_serial 3 /* index - unique */ +# define DB_file 4 +# define DB_name 5 /* index - unique when active and not + * disabled */ +# define DB_NUMBER 6 + +# define DB_TYPE_REV 'R' /* Revoked */ +# define DB_TYPE_EXP 'E' /* Expired */ +# define DB_TYPE_VAL 'V' /* Valid ; inserted with: ca ... -valid */ +# define DB_TYPE_SUSP 'S' /* Suspended */ + +typedef struct db_attr_st { + int unique_subject; +} DB_ATTR; +typedef struct ca_db_st { + DB_ATTR attributes; + TXT_DB *db; + char *dbfname; +# ifndef OPENSSL_NO_POSIX_IO + struct stat dbst; +# endif +} CA_DB; + +void* app_malloc(int sz, const char *what); +BIGNUM *load_serial(const char *serialfile, int create, ASN1_INTEGER **retai); +int save_serial(const char *serialfile, const char *suffix, const BIGNUM *serial, + ASN1_INTEGER **retai); +int rotate_serial(const char *serialfile, const char *new_suffix, + const char *old_suffix); +int rand_serial(BIGNUM *b, ASN1_INTEGER *ai); +CA_DB *load_index(const char *dbfile, DB_ATTR *dbattr); +int index_index(CA_DB *db); +int save_index(const char *dbfile, const char *suffix, CA_DB *db); +int rotate_index(const char *dbfile, const char *new_suffix, + const char *old_suffix); +void free_index(CA_DB *db); +# define index_name_cmp_noconst(a, b) \ + index_name_cmp((const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, a), \ + (const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, b)) +int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b); +int parse_yesno(const char *str, int def); + +X509_NAME *parse_name(const char *str, long chtype, int multirdn); +void policies_print(X509_STORE_CTX *ctx); +int bio_to_mem(unsigned char **out, int maxlen, BIO *in); +int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value); +int init_gen_str(EVP_PKEY_CTX **pctx, + const char *algname, ENGINE *e, int do_param); +int do_X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md, + STACK_OF(OPENSSL_STRING) *sigopts); +int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md, + STACK_OF(OPENSSL_STRING) *sigopts); +int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md, + STACK_OF(OPENSSL_STRING) *sigopts); + +extern char *psk_key; + + +unsigned char *next_protos_parse(size_t *outlen, const char *in); + +void print_cert_checks(BIO *bio, X509 *x, + const char *checkhost, + const char *checkemail, const char *checkip); + +void store_setup_crl_download(X509_STORE *st); + +/* See OPT_FMT_xxx, above. */ +/* On some platforms, it's important to distinguish between text and binary + * files. On some, there might even be specific file formats for different + * contents. The FORMAT_xxx macros are meant to express an intent with the + * file being read or created. + */ +# define B_FORMAT_TEXT 0x8000 +# define FORMAT_UNDEF 0 +# define FORMAT_TEXT (1 | B_FORMAT_TEXT) /* Generic text */ +# define FORMAT_BINARY 2 /* Generic binary */ +# define FORMAT_BASE64 (3 | B_FORMAT_TEXT) /* Base64 */ +# define FORMAT_ASN1 4 /* ASN.1/DER */ +# define FORMAT_PEM (5 | B_FORMAT_TEXT) +# define FORMAT_PKCS12 6 +# define FORMAT_SMIME (7 | B_FORMAT_TEXT) +# define FORMAT_ENGINE 8 /* Not really a file format */ +# define FORMAT_PEMRSA (9 | B_FORMAT_TEXT) /* PEM RSAPubicKey format */ +# define FORMAT_ASN1RSA 10 /* DER RSAPubicKey format */ +# define FORMAT_MSBLOB 11 /* MS Key blob format */ +# define FORMAT_PVK 12 /* MS PVK file format */ +# define FORMAT_HTTP 13 /* Download using HTTP */ +# define FORMAT_NSS 14 /* NSS keylog format */ + +# define EXT_COPY_NONE 0 +# define EXT_COPY_ADD 1 +# define EXT_COPY_ALL 2 + +# define NETSCAPE_CERT_HDR "certificate" + +# define APP_PASS_LEN 1024 + +/* + * IETF RFC 5280 says serial number must be <= 20 bytes. Use 159 bits + * so that the first bit will never be one, so that the DER encoding + * rules won't force a leading octet. + */ +# define SERIAL_RAND_BITS 159 + +int app_isdir(const char *); +int app_access(const char *, int flag); +int fileno_stdin(void); +int fileno_stdout(void); +int raw_read_stdin(void *, int); +int raw_write_stdout(const void *, int); + +# define TM_START 0 +# define TM_STOP 1 +double app_tminterval(int stop, int usertime); + +void make_uppercase(char *string); + +typedef struct verify_options_st { + int depth; + int quiet; + int error; + int return_error; +} VERIFY_CB_ARGS; + +extern VERIFY_CB_ARGS verify_args; + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/asn1pars.c b/trunk/3rdparty/openssl-1.1-fit/apps/asn1pars.c new file mode 100644 index 000000000..62c70b9cc --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/asn1pars.c @@ -0,0 +1,357 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include +#include + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_IN, OPT_OUT, OPT_INDENT, OPT_NOOUT, + OPT_OID, OPT_OFFSET, OPT_LENGTH, OPT_DUMP, OPT_DLIMIT, + OPT_STRPARSE, OPT_GENSTR, OPT_GENCONF, OPT_STRICTPEM, + OPT_ITEM +} OPTION_CHOICE; + +const OPTIONS asn1parse_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"inform", OPT_INFORM, 'F', "input format - one of DER PEM"}, + {"in", OPT_IN, '<', "input file"}, + {"out", OPT_OUT, '>', "output file (output format is always DER)"}, + {"i", OPT_INDENT, 0, "indents the output"}, + {"noout", OPT_NOOUT, 0, "do not produce any output"}, + {"offset", OPT_OFFSET, 'p', "offset into file"}, + {"length", OPT_LENGTH, 'p', "length of section in file"}, + {"oid", OPT_OID, '<', "file of extra oid definitions"}, + {"dump", OPT_DUMP, 0, "unknown data in hex form"}, + {"dlimit", OPT_DLIMIT, 'p', + "dump the first arg bytes of unknown data in hex form"}, + {"strparse", OPT_STRPARSE, 'p', + "offset; a series of these can be used to 'dig'"}, + {OPT_MORE_STR, 0, 0, "into multiple ASN1 blob wrappings"}, + {"genstr", OPT_GENSTR, 's', "string to generate ASN1 structure from"}, + {"genconf", OPT_GENCONF, 's', "file to generate ASN1 structure from"}, + {OPT_MORE_STR, 0, 0, "(-inform will be ignored)"}, + {"strictpem", OPT_STRICTPEM, 0, + "do not attempt base64 decode outside PEM markers"}, + {"item", OPT_ITEM, 's', "item to parse and print"}, + {NULL} +}; + +static int do_generate(char *genstr, const char *genconf, BUF_MEM *buf); + +int asn1parse_main(int argc, char **argv) +{ + ASN1_TYPE *at = NULL; + BIO *in = NULL, *b64 = NULL, *derout = NULL; + BUF_MEM *buf = NULL; + STACK_OF(OPENSSL_STRING) *osk = NULL; + char *genstr = NULL, *genconf = NULL; + char *infile = NULL, *oidfile = NULL, *derfile = NULL; + unsigned char *str = NULL; + char *name = NULL, *header = NULL, *prog; + const unsigned char *ctmpbuf; + int indent = 0, noout = 0, dump = 0, strictpem = 0, informat = FORMAT_PEM; + int offset = 0, ret = 1, i, j; + long num, tmplen; + unsigned char *tmpbuf; + unsigned int length = 0; + OPTION_CHOICE o; + const ASN1_ITEM *it = NULL; + + prog = opt_init(argc, argv, asn1parse_options); + + if ((osk = sk_OPENSSL_STRING_new_null()) == NULL) { + BIO_printf(bio_err, "%s: Memory allocation failure\n", prog); + goto end; + } + + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(asn1parse_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + derfile = opt_arg(); + break; + case OPT_INDENT: + indent = 1; + break; + case OPT_NOOUT: + noout = 1; + break; + case OPT_OID: + oidfile = opt_arg(); + break; + case OPT_OFFSET: + offset = strtol(opt_arg(), NULL, 0); + break; + case OPT_LENGTH: + length = strtol(opt_arg(), NULL, 0); + break; + case OPT_DUMP: + dump = -1; + break; + case OPT_DLIMIT: + dump = strtol(opt_arg(), NULL, 0); + break; + case OPT_STRPARSE: + sk_OPENSSL_STRING_push(osk, opt_arg()); + break; + case OPT_GENSTR: + genstr = opt_arg(); + break; + case OPT_GENCONF: + genconf = opt_arg(); + break; + case OPT_STRICTPEM: + strictpem = 1; + informat = FORMAT_PEM; + break; + case OPT_ITEM: + it = ASN1_ITEM_lookup(opt_arg()); + if (it == NULL) { + size_t tmp; + + BIO_printf(bio_err, "Unknown item name %s\n", opt_arg()); + BIO_puts(bio_err, "Supported types:\n"); + for (tmp = 0;; tmp++) { + it = ASN1_ITEM_get(tmp); + if (it == NULL) + break; + BIO_printf(bio_err, " %s\n", it->sname); + } + goto end; + } + break; + } + } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + + if (oidfile != NULL) { + in = bio_open_default(oidfile, 'r', FORMAT_TEXT); + if (in == NULL) + goto end; + OBJ_create_objects(in); + BIO_free(in); + } + + if ((in = bio_open_default(infile, 'r', informat)) == NULL) + goto end; + + if (derfile && (derout = bio_open_default(derfile, 'w', FORMAT_ASN1)) == NULL) + goto end; + + if (strictpem) { + if (PEM_read_bio(in, &name, &header, &str, &num) != + 1) { + BIO_printf(bio_err, "Error reading PEM file\n"); + ERR_print_errors(bio_err); + goto end; + } + } else { + + if ((buf = BUF_MEM_new()) == NULL) + goto end; + if (!BUF_MEM_grow(buf, BUFSIZ * 8)) + goto end; /* Pre-allocate :-) */ + + if (genstr || genconf) { + num = do_generate(genstr, genconf, buf); + if (num < 0) { + ERR_print_errors(bio_err); + goto end; + } + } else { + + if (informat == FORMAT_PEM) { + BIO *tmp; + + if ((b64 = BIO_new(BIO_f_base64())) == NULL) + goto end; + BIO_push(b64, in); + tmp = in; + in = b64; + b64 = tmp; + } + + num = 0; + for (;;) { + if (!BUF_MEM_grow(buf, num + BUFSIZ)) + goto end; + i = BIO_read(in, &(buf->data[num]), BUFSIZ); + if (i <= 0) + break; + num += i; + } + } + str = (unsigned char *)buf->data; + + } + + /* If any structs to parse go through in sequence */ + + if (sk_OPENSSL_STRING_num(osk)) { + tmpbuf = str; + tmplen = num; + for (i = 0; i < sk_OPENSSL_STRING_num(osk); i++) { + ASN1_TYPE *atmp; + int typ; + j = strtol(sk_OPENSSL_STRING_value(osk, i), NULL, 0); + if (j <= 0 || j >= tmplen) { + BIO_printf(bio_err, "'%s' is out of range\n", + sk_OPENSSL_STRING_value(osk, i)); + continue; + } + tmpbuf += j; + tmplen -= j; + atmp = at; + ctmpbuf = tmpbuf; + at = d2i_ASN1_TYPE(NULL, &ctmpbuf, tmplen); + ASN1_TYPE_free(atmp); + if (!at) { + BIO_printf(bio_err, "Error parsing structure\n"); + ERR_print_errors(bio_err); + goto end; + } + typ = ASN1_TYPE_get(at); + if ((typ == V_ASN1_OBJECT) + || (typ == V_ASN1_BOOLEAN) + || (typ == V_ASN1_NULL)) { + BIO_printf(bio_err, "Can't parse %s type\n", ASN1_tag2str(typ)); + ERR_print_errors(bio_err); + goto end; + } + /* hmm... this is a little evil but it works */ + tmpbuf = at->value.asn1_string->data; + tmplen = at->value.asn1_string->length; + } + str = tmpbuf; + num = tmplen; + } + + if (offset < 0 || offset >= num) { + BIO_printf(bio_err, "Error: offset out of range\n"); + goto end; + } + + num -= offset; + + if (length == 0 || length > (unsigned int)num) + length = (unsigned int)num; + if (derout != NULL) { + if (BIO_write(derout, str + offset, length) != (int)length) { + BIO_printf(bio_err, "Error writing output\n"); + ERR_print_errors(bio_err); + goto end; + } + } + if (!noout) { + const unsigned char *p = str + offset; + + if (it != NULL) { + ASN1_VALUE *value = ASN1_item_d2i(NULL, &p, length, it); + if (value == NULL) { + BIO_printf(bio_err, "Error parsing item %s\n", it->sname); + ERR_print_errors(bio_err); + goto end; + } + ASN1_item_print(bio_out, value, 0, it, NULL); + ASN1_item_free(value, it); + } else { + if (!ASN1_parse_dump(bio_out, p, length, indent, dump)) { + ERR_print_errors(bio_err); + goto end; + } + } + } + ret = 0; + end: + BIO_free(derout); + BIO_free(in); + BIO_free(b64); + if (ret != 0) + ERR_print_errors(bio_err); + BUF_MEM_free(buf); + OPENSSL_free(name); + OPENSSL_free(header); + if (strictpem) + OPENSSL_free(str); + ASN1_TYPE_free(at); + sk_OPENSSL_STRING_free(osk); + return ret; +} + +static int do_generate(char *genstr, const char *genconf, BUF_MEM *buf) +{ + CONF *cnf = NULL; + int len; + unsigned char *p; + ASN1_TYPE *atyp = NULL; + + if (genconf != NULL) { + if ((cnf = app_load_config(genconf)) == NULL) + goto err; + if (genstr == NULL) + genstr = NCONF_get_string(cnf, "default", "asn1"); + if (genstr == NULL) { + BIO_printf(bio_err, "Can't find 'asn1' in '%s'\n", genconf); + goto err; + } + } + + atyp = ASN1_generate_nconf(genstr, cnf); + NCONF_free(cnf); + cnf = NULL; + + if (atyp == NULL) + return -1; + + len = i2d_ASN1_TYPE(atyp, NULL); + + if (len <= 0) + goto err; + + if (!BUF_MEM_grow(buf, len)) + goto err; + + p = (unsigned char *)buf->data; + + i2d_ASN1_TYPE(atyp, &p); + + ASN1_TYPE_free(atyp); + return len; + + err: + NCONF_free(cnf); + ASN1_TYPE_free(atyp); + return -1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/bf_prefix.c b/trunk/3rdparty/openssl-1.1-fit/apps/bf_prefix.c new file mode 100644 index 000000000..bae3c91bf --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/bf_prefix.c @@ -0,0 +1,177 @@ +/* + * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include "apps.h" + +static int prefix_write(BIO *b, const char *out, size_t outl, + size_t *numwritten); +static int prefix_read(BIO *b, char *buf, size_t size, size_t *numread); +static int prefix_puts(BIO *b, const char *str); +static int prefix_gets(BIO *b, char *str, int size); +static long prefix_ctrl(BIO *b, int cmd, long arg1, void *arg2); +static int prefix_create(BIO *b); +static int prefix_destroy(BIO *b); +static long prefix_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp); + +static BIO_METHOD *prefix_meth = NULL; + +BIO_METHOD *apps_bf_prefix(void) +{ + if (prefix_meth == NULL) { + if ((prefix_meth = + BIO_meth_new(BIO_TYPE_FILTER, "Prefix filter")) == NULL + || !BIO_meth_set_create(prefix_meth, prefix_create) + || !BIO_meth_set_destroy(prefix_meth, prefix_destroy) + || !BIO_meth_set_write_ex(prefix_meth, prefix_write) + || !BIO_meth_set_read_ex(prefix_meth, prefix_read) + || !BIO_meth_set_puts(prefix_meth, prefix_puts) + || !BIO_meth_set_gets(prefix_meth, prefix_gets) + || !BIO_meth_set_ctrl(prefix_meth, prefix_ctrl) + || !BIO_meth_set_callback_ctrl(prefix_meth, prefix_callback_ctrl)) { + BIO_meth_free(prefix_meth); + prefix_meth = NULL; + } + } + return prefix_meth; +} + +typedef struct prefix_ctx_st { + char *prefix; + int linestart; /* flag to indicate we're at the line start */ +} PREFIX_CTX; + +static int prefix_create(BIO *b) +{ + PREFIX_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); + + if (ctx == NULL) + return 0; + + ctx->prefix = NULL; + ctx->linestart = 1; + BIO_set_data(b, ctx); + BIO_set_init(b, 1); + return 1; +} + +static int prefix_destroy(BIO *b) +{ + PREFIX_CTX *ctx = BIO_get_data(b); + + OPENSSL_free(ctx->prefix); + OPENSSL_free(ctx); + return 1; +} + +static int prefix_read(BIO *b, char *in, size_t size, size_t *numread) +{ + return BIO_read_ex(BIO_next(b), in, size, numread); +} + +static int prefix_write(BIO *b, const char *out, size_t outl, + size_t *numwritten) +{ + PREFIX_CTX *ctx = BIO_get_data(b); + + if (ctx == NULL) + return 0; + + /* If no prefix is set or if it's empty, we've got nothing to do here */ + if (ctx->prefix == NULL || *ctx->prefix == '\0') { + /* We do note if what comes next will be a new line, though */ + if (outl > 0) + ctx->linestart = (out[outl-1] == '\n'); + return BIO_write_ex(BIO_next(b), out, outl, numwritten); + } + + *numwritten = 0; + + while (outl > 0) { + size_t i; + char c; + + /* If we know that we're at the start of the line, output the prefix */ + if (ctx->linestart) { + size_t dontcare; + + if (!BIO_write_ex(BIO_next(b), ctx->prefix, strlen(ctx->prefix), + &dontcare)) + return 0; + ctx->linestart = 0; + } + + /* Now, go look for the next LF, or the end of the string */ + for (i = 0, c = '\0'; i < outl && (c = out[i]) != '\n'; i++) + continue; + if (c == '\n') + i++; + + /* Output what we found so far */ + while (i > 0) { + size_t num = 0; + + if (!BIO_write_ex(BIO_next(b), out, i, &num)) + return 0; + out += num; + outl -= num; + *numwritten += num; + i -= num; + } + + /* If we found a LF, what follows is a new line, so take note */ + if (c == '\n') + ctx->linestart = 1; + } + + return 1; +} + +static long prefix_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + long ret = 0; + + switch (cmd) { + case PREFIX_CTRL_SET_PREFIX: + { + PREFIX_CTX *ctx = BIO_get_data(b); + + if (ctx == NULL) + break; + + OPENSSL_free(ctx->prefix); + ctx->prefix = OPENSSL_strdup((const char *)ptr); + ret = ctx->prefix != NULL; + } + break; + default: + if (BIO_next(b) != NULL) + ret = BIO_ctrl(BIO_next(b), cmd, num, ptr); + break; + } + return ret; +} + +static long prefix_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) +{ + return BIO_callback_ctrl(BIO_next(b), cmd, fp); +} + +static int prefix_gets(BIO *b, char *buf, int size) +{ + return BIO_gets(BIO_next(b), buf, size); +} + +static int prefix_puts(BIO *b, const char *str) +{ + return BIO_write(b, str, strlen(str)); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/build.info b/trunk/3rdparty/openssl-1.1-fit/apps/build.info new file mode 100644 index 000000000..751d8da82 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/build.info @@ -0,0 +1,38 @@ +{- our @apps_openssl_src = + qw(openssl.c + asn1pars.c ca.c ciphers.c cms.c crl.c crl2p7.c dgst.c dhparam.c + dsa.c dsaparam.c ec.c ecparam.c enc.c engine.c errstr.c gendsa.c + genpkey.c genrsa.c nseq.c ocsp.c passwd.c pkcs12.c pkcs7.c pkcs8.c + pkey.c pkeyparam.c pkeyutl.c prime.c rand.c req.c rsa.c rsautl.c + s_client.c s_server.c s_time.c sess_id.c smime.c speed.c spkac.c + srp.c ts.c verify.c version.c x509.c rehash.c storeutl.c); + our @apps_lib_src = + ( qw(apps.c opt.c s_cb.c s_socket.c app_rand.c bf_prefix.c), + split(/\s+/, $target{apps_aux_src}) ); + our @apps_init_src = split(/\s+/, $target{apps_init_src}); + "" -} +IF[{- !$disabled{apps} -}] + LIBS_NO_INST=libapps.a + SOURCE[libapps.a]={- join(" ", @apps_lib_src) -} + INCLUDE[libapps.a]=.. ../include + + PROGRAMS=openssl + SOURCE[openssl]={- join(" ", @apps_init_src) -} + SOURCE[openssl]={- join(" ", @apps_openssl_src) -} + INCLUDE[openssl]=.. ../include + DEPEND[openssl]=libapps.a ../libssl + +IF[{- $config{target} =~ /^(?:Cygwin|mingw|VC-)/ -}] + GENERATE[openssl.rc]=../util/mkrc.pl openssl + SOURCE[openssl]=openssl.rc +ENDIF + + {- join("\n ", map { (my $x = $_) =~ s|\.c$|.o|; "DEPEND[$x]=progs.h" } + @apps_openssl_src) -} + GENERATE[progs.h]=progs.pl $(APPS_OPENSSL) + DEPEND[progs.h]=../configdata.pm + + SCRIPTS=CA.pl tsget.pl + SOURCE[CA.pl]=CA.pl.in + SOURCE[tsget.pl]=tsget.in +ENDIF diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/ca-cert.srl b/trunk/3rdparty/openssl-1.1-fit/apps/ca-cert.srl new file mode 100644 index 000000000..2c7456e3e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/ca-cert.srl @@ -0,0 +1 @@ +07 diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/ca-key.pem b/trunk/3rdparty/openssl-1.1-fit/apps/ca-key.pem new file mode 100644 index 000000000..4e7424906 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/ca-key.pem @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAL4tQNyKy4U2zX6l +IZvORB1edmwMwIgSB4cgoFECrG5pixzYxKauZkAwKG9/+L4DB8qXRjfXWcvafcOU +DlYpRROykJ7wGkiqmqbZyrxY8DWjk5ZZQXiSuhYOAJB+Fyfb11JZV6+CvBQX/1g+ +vhJr39Gmp6oAesoYrj90ecozClmnAgMBAAECgYA3j6sSg+5f9hnldUMzbPjTh8Sb +XsJlPrc6UFrmMBzGiUleXSpe9Dbla+x0XvQCN4pwMvAN4nnWp/f0Su5BV/9Y93nb +im5ijGNrfN9i6QrnqGCr+MMute+4E8HR2pCScX0mBLDDf40SmDvMzCaxtd21keyr +9DqHgInQZNEi6NKlkQJBAPCbUTFg6iQ6VTCQ8CsEf5q2xHhuTK23fJ999lvWVxN7 +QsvWb9RP9Ng34HVtvB7Pl6P7FyHLQYiDJhhvYR0L0+kCQQDKV/09Kt6Wjf5Omp1I +wd3A+tFnipdqnPw+qNHGjevv0hYiEIWQOYbx00zXgaX+WN/pzV9eeNN2XAxlNJ++ +dxcPAkBrzeuPKFFAcjKBVC+H1rgl5gYZv7Hzk+buv02G0H6rZ+sB0c7BXiHiTwbv +Fn/XfkP/YR14Ms3mEH0dLaphjU8hAkEAh3Ar/rRiN04mCcEuRFQXtaNtZSv8PA2G +Pf7MI2Y9pdHupLCAZlBLRjTUO2/5hu1AO4QPMPIZQSFN3rRBtMCL+wJAMp/m2hvI +TmtbMp/IrKGfma09e3yFiCmoNn7cHLJ7jLvXcacV2XNzpr9YHfBxiZo0g9FqZKvv +PZoQ5B2XJ7bhTQ== +-----END PRIVATE KEY----- diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/ca-req.pem b/trunk/3rdparty/openssl-1.1-fit/apps/ca-req.pem new file mode 100644 index 000000000..84c6dbb68 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/ca-req.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBmzCCAQQCAQAwWzELMAkGA1UEBhMCQVUxEzARBgNVBAgMClF1ZWVuc2xhbmQx +GjAYBgNVBAoMEUNyeXB0U29mdCBQdHkgTHRkMRswGQYDVQQDDBJUZXN0IENBICgx +MDI0IGJpdCkwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAL4tQNyKy4U2zX6l +IZvORB1edmwMwIgSB4cgoFECrG5pixzYxKauZkAwKG9/+L4DB8qXRjfXWcvafcOU +DlYpRROykJ7wGkiqmqbZyrxY8DWjk5ZZQXiSuhYOAJB+Fyfb11JZV6+CvBQX/1g+ +vhJr39Gmp6oAesoYrj90ecozClmnAgMBAAGgADANBgkqhkiG9w0BAQsFAAOBgQCo +2jE7J1SNV7kyRm9m8CoPw8xYsuVcVFxPheBymYp8BlO0/rSdYygRjobpYnLVRUPZ +pV792wzT1Rp4sXfZWO10lkFY4yi0pH2cdK2RX7qedibV1Xu9vt/yYANFBKVpA4dy +PRyTQwi3In1N8hdfddpYR8f5MIUYRe5poFMIJcf8JA== +-----END CERTIFICATE REQUEST----- diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/ca.c b/trunk/3rdparty/openssl-1.1-fit/apps/ca.c new file mode 100644 index 000000000..69207c066 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/ca.c @@ -0,0 +1,2606 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef W_OK +# ifdef OPENSSL_SYS_VMS +# include +# elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS) +# include +# endif +#endif + +#include "apps.h" +#include "progs.h" + +#ifndef W_OK +# define F_OK 0 +# define W_OK 2 +# define R_OK 4 +#endif + +#ifndef PATH_MAX +# define PATH_MAX 4096 +#endif + +#define BASE_SECTION "ca" + +#define ENV_DEFAULT_CA "default_ca" + +#define STRING_MASK "string_mask" +#define UTF8_IN "utf8" + +#define ENV_NEW_CERTS_DIR "new_certs_dir" +#define ENV_CERTIFICATE "certificate" +#define ENV_SERIAL "serial" +#define ENV_RAND_SERIAL "rand_serial" +#define ENV_CRLNUMBER "crlnumber" +#define ENV_PRIVATE_KEY "private_key" +#define ENV_DEFAULT_DAYS "default_days" +#define ENV_DEFAULT_STARTDATE "default_startdate" +#define ENV_DEFAULT_ENDDATE "default_enddate" +#define ENV_DEFAULT_CRL_DAYS "default_crl_days" +#define ENV_DEFAULT_CRL_HOURS "default_crl_hours" +#define ENV_DEFAULT_MD "default_md" +#define ENV_DEFAULT_EMAIL_DN "email_in_dn" +#define ENV_PRESERVE "preserve" +#define ENV_POLICY "policy" +#define ENV_EXTENSIONS "x509_extensions" +#define ENV_CRLEXT "crl_extensions" +#define ENV_MSIE_HACK "msie_hack" +#define ENV_NAMEOPT "name_opt" +#define ENV_CERTOPT "cert_opt" +#define ENV_EXTCOPY "copy_extensions" +#define ENV_UNIQUE_SUBJECT "unique_subject" + +#define ENV_DATABASE "database" + +/* Additional revocation information types */ +typedef enum { + REV_VALID = -1, /* Valid (not-revoked) status */ + REV_NONE = 0, /* No additional information */ + REV_CRL_REASON = 1, /* Value is CRL reason code */ + REV_HOLD = 2, /* Value is hold instruction */ + REV_KEY_COMPROMISE = 3, /* Value is cert key compromise time */ + REV_CA_COMPROMISE = 4 /* Value is CA key compromise time */ +} REVINFO_TYPE; + +static char *lookup_conf(const CONF *conf, const char *group, const char *tag); + +static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, + const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(CONF_VALUE) *policy, CA_DB *db, + BIGNUM *serial, const char *subj, unsigned long chtype, + int multirdn, int email_dn, const char *startdate, + const char *enddate, + long days, int batch, const char *ext_sect, CONF *conf, + int verbose, unsigned long certopt, unsigned long nameopt, + int default_op, int ext_copy, int selfsign); +static int certify_cert(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, + const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(CONF_VALUE) *policy, CA_DB *db, + BIGNUM *serial, const char *subj, unsigned long chtype, + int multirdn, int email_dn, const char *startdate, + const char *enddate, long days, int batch, const char *ext_sect, + CONF *conf, int verbose, unsigned long certopt, + unsigned long nameopt, int default_op, int ext_copy); +static int certify_spkac(X509 **xret, const char *infile, EVP_PKEY *pkey, + X509 *x509, const EVP_MD *dgst, + STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(CONF_VALUE) *policy, CA_DB *db, + BIGNUM *serial, const char *subj, unsigned long chtype, + int multirdn, int email_dn, const char *startdate, + const char *enddate, long days, const char *ext_sect, CONF *conf, + int verbose, unsigned long certopt, + unsigned long nameopt, int default_op, int ext_copy); +static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, + const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, + const char *subj, unsigned long chtype, int multirdn, + int email_dn, const char *startdate, const char *enddate, long days, + int batch, int verbose, X509_REQ *req, const char *ext_sect, + CONF *conf, unsigned long certopt, unsigned long nameopt, + int default_op, int ext_copy, int selfsign); +static int get_certificate_status(const char *ser_status, CA_DB *db); +static int do_updatedb(CA_DB *db); +static int check_time_format(const char *str); +static int do_revoke(X509 *x509, CA_DB *db, REVINFO_TYPE rev_type, + const char *extval); +static char *make_revocation_str(REVINFO_TYPE rev_type, const char *rev_arg); +static int make_revoked(X509_REVOKED *rev, const char *str); +static int old_entry_print(const ASN1_OBJECT *obj, const ASN1_STRING *str); +static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext); + +static CONF *extconf = NULL; +static int preserve = 0; +static int msie_hack = 0; + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_ENGINE, OPT_VERBOSE, OPT_CONFIG, OPT_NAME, OPT_SUBJ, OPT_UTF8, + OPT_CREATE_SERIAL, OPT_MULTIVALUE_RDN, OPT_STARTDATE, OPT_ENDDATE, + OPT_DAYS, OPT_MD, OPT_POLICY, OPT_KEYFILE, OPT_KEYFORM, OPT_PASSIN, + OPT_KEY, OPT_CERT, OPT_SELFSIGN, OPT_IN, OPT_OUT, OPT_OUTDIR, + OPT_SIGOPT, OPT_NOTEXT, OPT_BATCH, OPT_PRESERVEDN, OPT_NOEMAILDN, + OPT_GENCRL, OPT_MSIE_HACK, OPT_CRLDAYS, OPT_CRLHOURS, OPT_CRLSEC, + OPT_INFILES, OPT_SS_CERT, OPT_SPKAC, OPT_REVOKE, OPT_VALID, + OPT_EXTENSIONS, OPT_EXTFILE, OPT_STATUS, OPT_UPDATEDB, OPT_CRLEXTS, + OPT_RAND_SERIAL, + OPT_R_ENUM, + /* Do not change the order here; see related case statements below */ + OPT_CRL_REASON, OPT_CRL_HOLD, OPT_CRL_COMPROMISE, OPT_CRL_CA_COMPROMISE +} OPTION_CHOICE; + +const OPTIONS ca_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"verbose", OPT_VERBOSE, '-', "Verbose output during processing"}, + {"config", OPT_CONFIG, 's', "A config file"}, + {"name", OPT_NAME, 's', "The particular CA definition to use"}, + {"subj", OPT_SUBJ, 's', "Use arg instead of request's subject"}, + {"utf8", OPT_UTF8, '-', "Input characters are UTF8 (default ASCII)"}, + {"create_serial", OPT_CREATE_SERIAL, '-', + "If reading serial fails, create a new random serial"}, + {"rand_serial", OPT_RAND_SERIAL, '-', + "Always create a random serial; do not store it"}, + {"multivalue-rdn", OPT_MULTIVALUE_RDN, '-', + "Enable support for multivalued RDNs"}, + {"startdate", OPT_STARTDATE, 's', "Cert notBefore, YYMMDDHHMMSSZ"}, + {"enddate", OPT_ENDDATE, 's', + "YYMMDDHHMMSSZ cert notAfter (overrides -days)"}, + {"days", OPT_DAYS, 'p', "Number of days to certify the cert for"}, + {"md", OPT_MD, 's', "md to use; one of md2, md5, sha or sha1"}, + {"policy", OPT_POLICY, 's', "The CA 'policy' to support"}, + {"keyfile", OPT_KEYFILE, 's', "Private key"}, + {"keyform", OPT_KEYFORM, 'f', "Private key file format (PEM or ENGINE)"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"key", OPT_KEY, 's', "Key to decode the private key if it is encrypted"}, + {"cert", OPT_CERT, '<', "The CA cert"}, + {"selfsign", OPT_SELFSIGN, '-', + "Sign a cert with the key associated with it"}, + {"in", OPT_IN, '<', "The input PEM encoded cert request(s)"}, + {"out", OPT_OUT, '>', "Where to put the output file(s)"}, + {"outdir", OPT_OUTDIR, '/', "Where to put output cert"}, + {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"}, + {"notext", OPT_NOTEXT, '-', "Do not print the generated certificate"}, + {"batch", OPT_BATCH, '-', "Don't ask questions"}, + {"preserveDN", OPT_PRESERVEDN, '-', "Don't re-order the DN"}, + {"noemailDN", OPT_NOEMAILDN, '-', "Don't add the EMAIL field to the DN"}, + {"gencrl", OPT_GENCRL, '-', "Generate a new CRL"}, + {"msie_hack", OPT_MSIE_HACK, '-', + "msie modifications to handle all those universal strings"}, + {"crldays", OPT_CRLDAYS, 'p', "Days until the next CRL is due"}, + {"crlhours", OPT_CRLHOURS, 'p', "Hours until the next CRL is due"}, + {"crlsec", OPT_CRLSEC, 'p', "Seconds until the next CRL is due"}, + {"infiles", OPT_INFILES, '-', "The last argument, requests to process"}, + {"ss_cert", OPT_SS_CERT, '<', "File contains a self signed cert to sign"}, + {"spkac", OPT_SPKAC, '<', + "File contains DN and signed public key and challenge"}, + {"revoke", OPT_REVOKE, '<', "Revoke a cert (given in file)"}, + {"valid", OPT_VALID, 's', + "Add a Valid(not-revoked) DB entry about a cert (given in file)"}, + {"extensions", OPT_EXTENSIONS, 's', + "Extension section (override value in config file)"}, + {"extfile", OPT_EXTFILE, '<', + "Configuration file with X509v3 extensions to add"}, + {"status", OPT_STATUS, 's', "Shows cert status given the serial number"}, + {"updatedb", OPT_UPDATEDB, '-', "Updates db for expired cert"}, + {"crlexts", OPT_CRLEXTS, 's', + "CRL extension section (override value in config file)"}, + {"crl_reason", OPT_CRL_REASON, 's', "revocation reason"}, + {"crl_hold", OPT_CRL_HOLD, 's', + "the hold instruction, an OID. Sets revocation reason to certificateHold"}, + {"crl_compromise", OPT_CRL_COMPROMISE, 's', + "sets compromise time to val and the revocation reason to keyCompromise"}, + {"crl_CA_compromise", OPT_CRL_CA_COMPROMISE, 's', + "sets compromise time to val and the revocation reason to CACompromise"}, + OPT_R_OPTIONS, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + {NULL} +}; + +int ca_main(int argc, char **argv) +{ + CONF *conf = NULL; + ENGINE *e = NULL; + BIGNUM *crlnumber = NULL, *serial = NULL; + EVP_PKEY *pkey = NULL; + BIO *in = NULL, *out = NULL, *Sout = NULL; + ASN1_INTEGER *tmpser; + ASN1_TIME *tmptm; + CA_DB *db = NULL; + DB_ATTR db_attr; + STACK_OF(CONF_VALUE) *attribs = NULL; + STACK_OF(OPENSSL_STRING) *sigopts = NULL; + STACK_OF(X509) *cert_sk = NULL; + X509_CRL *crl = NULL; + const EVP_MD *dgst = NULL; + char *configfile = default_config_file, *section = NULL; + char *md = NULL, *policy = NULL, *keyfile = NULL; + char *certfile = NULL, *crl_ext = NULL, *crlnumberfile = NULL, *key = NULL; + const char *infile = NULL, *spkac_file = NULL, *ss_cert_file = NULL; + const char *extensions = NULL, *extfile = NULL, *passinarg = NULL; + char *outdir = NULL, *outfile = NULL, *rev_arg = NULL, *ser_status = NULL; + const char *serialfile = NULL, *subj = NULL; + char *prog, *startdate = NULL, *enddate = NULL; + char *dbfile = NULL, *f; + char new_cert[PATH_MAX]; + char tmp[10 + 1] = "\0"; + char *const *pp; + const char *p; + size_t outdirlen = 0; + int create_ser = 0, free_key = 0, total = 0, total_done = 0; + int batch = 0, default_op = 1, doupdatedb = 0, ext_copy = EXT_COPY_NONE; + int keyformat = FORMAT_PEM, multirdn = 0, notext = 0, output_der = 0; + int ret = 1, email_dn = 1, req = 0, verbose = 0, gencrl = 0, dorevoke = 0; + int rand_ser = 0, i, j, selfsign = 0, def_nid, def_ret; + long crldays = 0, crlhours = 0, crlsec = 0, days = 0; + unsigned long chtype = MBSTRING_ASC, certopt = 0; + X509 *x509 = NULL, *x509p = NULL, *x = NULL; + REVINFO_TYPE rev_type = REV_NONE; + X509_REVOKED *r = NULL; + OPTION_CHOICE o; + + prog = opt_init(argc, argv, ca_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: +opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(ca_options); + ret = 0; + goto end; + case OPT_IN: + req = 1; + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_VERBOSE: + verbose = 1; + break; + case OPT_CONFIG: + configfile = opt_arg(); + break; + case OPT_NAME: + section = opt_arg(); + break; + case OPT_SUBJ: + subj = opt_arg(); + /* preserve=1; */ + break; + case OPT_UTF8: + chtype = MBSTRING_UTF8; + break; + case OPT_RAND_SERIAL: + rand_ser = 1; + break; + case OPT_CREATE_SERIAL: + create_ser = 1; + break; + case OPT_MULTIVALUE_RDN: + multirdn = 1; + break; + case OPT_STARTDATE: + startdate = opt_arg(); + break; + case OPT_ENDDATE: + enddate = opt_arg(); + break; + case OPT_DAYS: + days = atoi(opt_arg()); + break; + case OPT_MD: + md = opt_arg(); + break; + case OPT_POLICY: + policy = opt_arg(); + break; + case OPT_KEYFILE: + keyfile = opt_arg(); + break; + case OPT_KEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyformat)) + goto opthelp; + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_KEY: + key = opt_arg(); + break; + case OPT_CERT: + certfile = opt_arg(); + break; + case OPT_SELFSIGN: + selfsign = 1; + break; + case OPT_OUTDIR: + outdir = opt_arg(); + break; + case OPT_SIGOPT: + if (sigopts == NULL) + sigopts = sk_OPENSSL_STRING_new_null(); + if (sigopts == NULL || !sk_OPENSSL_STRING_push(sigopts, opt_arg())) + goto end; + break; + case OPT_NOTEXT: + notext = 1; + break; + case OPT_BATCH: + batch = 1; + break; + case OPT_PRESERVEDN: + preserve = 1; + break; + case OPT_NOEMAILDN: + email_dn = 0; + break; + case OPT_GENCRL: + gencrl = 1; + break; + case OPT_MSIE_HACK: + msie_hack = 1; + break; + case OPT_CRLDAYS: + crldays = atol(opt_arg()); + break; + case OPT_CRLHOURS: + crlhours = atol(opt_arg()); + break; + case OPT_CRLSEC: + crlsec = atol(opt_arg()); + break; + case OPT_INFILES: + req = 1; + goto end_of_options; + case OPT_SS_CERT: + ss_cert_file = opt_arg(); + req = 1; + break; + case OPT_SPKAC: + spkac_file = opt_arg(); + req = 1; + break; + case OPT_REVOKE: + infile = opt_arg(); + dorevoke = 1; + break; + case OPT_VALID: + infile = opt_arg(); + dorevoke = 2; + break; + case OPT_EXTENSIONS: + extensions = opt_arg(); + break; + case OPT_EXTFILE: + extfile = opt_arg(); + break; + case OPT_STATUS: + ser_status = opt_arg(); + break; + case OPT_UPDATEDB: + doupdatedb = 1; + break; + case OPT_CRLEXTS: + crl_ext = opt_arg(); + break; + case OPT_CRL_REASON: /* := REV_CRL_REASON */ + case OPT_CRL_HOLD: + case OPT_CRL_COMPROMISE: + case OPT_CRL_CA_COMPROMISE: + rev_arg = opt_arg(); + rev_type = (o - OPT_CRL_REASON) + REV_CRL_REASON; + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + } + } +end_of_options: + argc = opt_num_rest(); + argv = opt_rest(); + + BIO_printf(bio_err, "Using configuration from %s\n", configfile); + + if ((conf = app_load_config(configfile)) == NULL) + goto end; + if (configfile != default_config_file && !app_load_modules(conf)) + goto end; + + /* Lets get the config section we are using */ + if (section == NULL + && (section = lookup_conf(conf, BASE_SECTION, ENV_DEFAULT_CA)) == NULL) + goto end; + + p = NCONF_get_string(conf, NULL, "oid_file"); + if (p == NULL) + ERR_clear_error(); + if (p != NULL) { + BIO *oid_bio = BIO_new_file(p, "r"); + + if (oid_bio == NULL) { + ERR_clear_error(); + } else { + OBJ_create_objects(oid_bio); + BIO_free(oid_bio); + } + } + if (!add_oid_section(conf)) { + ERR_print_errors(bio_err); + goto end; + } + + app_RAND_load_conf(conf, BASE_SECTION); + + f = NCONF_get_string(conf, section, STRING_MASK); + if (f == NULL) + ERR_clear_error(); + + if (f != NULL && !ASN1_STRING_set_default_mask_asc(f)) { + BIO_printf(bio_err, "Invalid global string mask setting %s\n", f); + goto end; + } + + if (chtype != MBSTRING_UTF8) { + f = NCONF_get_string(conf, section, UTF8_IN); + if (f == NULL) + ERR_clear_error(); + else if (strcmp(f, "yes") == 0) + chtype = MBSTRING_UTF8; + } + + db_attr.unique_subject = 1; + p = NCONF_get_string(conf, section, ENV_UNIQUE_SUBJECT); + if (p != NULL) + db_attr.unique_subject = parse_yesno(p, 1); + else + ERR_clear_error(); + + /*****************************************************************/ + /* report status of cert with serial number given on command line */ + if (ser_status) { + dbfile = lookup_conf(conf, section, ENV_DATABASE); + if (dbfile == NULL) + goto end; + + db = load_index(dbfile, &db_attr); + if (db == NULL) + goto end; + + if (index_index(db) <= 0) + goto end; + + if (get_certificate_status(ser_status, db) != 1) + BIO_printf(bio_err, "Error verifying serial %s!\n", ser_status); + goto end; + } + + /*****************************************************************/ + /* we definitely need a private key, so let's get it */ + + if (keyfile == NULL + && (keyfile = lookup_conf(conf, section, ENV_PRIVATE_KEY)) == NULL) + goto end; + + if (key == NULL) { + free_key = 1; + if (!app_passwd(passinarg, NULL, &key, NULL)) { + BIO_printf(bio_err, "Error getting password\n"); + goto end; + } + } + pkey = load_key(keyfile, keyformat, 0, key, e, "CA private key"); + if (key != NULL) + OPENSSL_cleanse(key, strlen(key)); + if (pkey == NULL) + /* load_key() has already printed an appropriate message */ + goto end; + + /*****************************************************************/ + /* we need a certificate */ + if (!selfsign || spkac_file || ss_cert_file || gencrl) { + if (certfile == NULL + && (certfile = lookup_conf(conf, section, ENV_CERTIFICATE)) == NULL) + goto end; + + x509 = load_cert(certfile, FORMAT_PEM, "CA certificate"); + if (x509 == NULL) + goto end; + + if (!X509_check_private_key(x509, pkey)) { + BIO_printf(bio_err, + "CA certificate and CA private key do not match\n"); + goto end; + } + } + if (!selfsign) + x509p = x509; + + f = NCONF_get_string(conf, BASE_SECTION, ENV_PRESERVE); + if (f == NULL) + ERR_clear_error(); + if ((f != NULL) && ((*f == 'y') || (*f == 'Y'))) + preserve = 1; + f = NCONF_get_string(conf, BASE_SECTION, ENV_MSIE_HACK); + if (f == NULL) + ERR_clear_error(); + if ((f != NULL) && ((*f == 'y') || (*f == 'Y'))) + msie_hack = 1; + + f = NCONF_get_string(conf, section, ENV_NAMEOPT); + + if (f != NULL) { + if (!set_nameopt(f)) { + BIO_printf(bio_err, "Invalid name options: \"%s\"\n", f); + goto end; + } + default_op = 0; + } + + f = NCONF_get_string(conf, section, ENV_CERTOPT); + + if (f != NULL) { + if (!set_cert_ex(&certopt, f)) { + BIO_printf(bio_err, "Invalid certificate options: \"%s\"\n", f); + goto end; + } + default_op = 0; + } else { + ERR_clear_error(); + } + + f = NCONF_get_string(conf, section, ENV_EXTCOPY); + + if (f != NULL) { + if (!set_ext_copy(&ext_copy, f)) { + BIO_printf(bio_err, "Invalid extension copy option: \"%s\"\n", f); + goto end; + } + } else { + ERR_clear_error(); + } + + /*****************************************************************/ + /* lookup where to write new certificates */ + if ((outdir == NULL) && (req)) { + + outdir = NCONF_get_string(conf, section, ENV_NEW_CERTS_DIR); + if (outdir == NULL) { + BIO_printf(bio_err, + "there needs to be defined a directory for new certificate to be placed in\n"); + goto end; + } +#ifndef OPENSSL_SYS_VMS + /* + * outdir is a directory spec, but access() for VMS demands a + * filename. We could use the DEC C routine to convert the + * directory syntax to Unix, and give that to app_isdir, + * but for now the fopen will catch the error if it's not a + * directory + */ + if (app_isdir(outdir) <= 0) { + BIO_printf(bio_err, "%s: %s is not a directory\n", prog, outdir); + perror(outdir); + goto end; + } +#endif + } + + /*****************************************************************/ + /* we need to load the database file */ + dbfile = lookup_conf(conf, section, ENV_DATABASE); + if (dbfile == NULL) + goto end; + + db = load_index(dbfile, &db_attr); + if (db == NULL) + goto end; + + /* Lets check some fields */ + for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { + pp = sk_OPENSSL_PSTRING_value(db->db->data, i); + if ((pp[DB_type][0] != DB_TYPE_REV) && (pp[DB_rev_date][0] != '\0')) { + BIO_printf(bio_err, + "entry %d: not revoked yet, but has a revocation date\n", + i + 1); + goto end; + } + if ((pp[DB_type][0] == DB_TYPE_REV) && + !make_revoked(NULL, pp[DB_rev_date])) { + BIO_printf(bio_err, " in entry %d\n", i + 1); + goto end; + } + if (!check_time_format((char *)pp[DB_exp_date])) { + BIO_printf(bio_err, "entry %d: invalid expiry date\n", i + 1); + goto end; + } + p = pp[DB_serial]; + j = strlen(p); + if (*p == '-') { + p++; + j--; + } + if ((j & 1) || (j < 2)) { + BIO_printf(bio_err, "entry %d: bad serial number length (%d)\n", + i + 1, j); + goto end; + } + for ( ; *p; p++) { + if (!isxdigit(_UC(*p))) { + BIO_printf(bio_err, + "entry %d: bad char 0%o '%c' in serial number\n", + i + 1, *p, *p); + goto end; + } + } + } + if (verbose) { + TXT_DB_write(bio_out, db->db); + BIO_printf(bio_err, "%d entries loaded from the database\n", + sk_OPENSSL_PSTRING_num(db->db->data)); + BIO_printf(bio_err, "generating index\n"); + } + + if (index_index(db) <= 0) + goto end; + + /*****************************************************************/ + /* Update the db file for expired certificates */ + if (doupdatedb) { + if (verbose) + BIO_printf(bio_err, "Updating %s ...\n", dbfile); + + i = do_updatedb(db); + if (i == -1) { + BIO_printf(bio_err, "Malloc failure\n"); + goto end; + } else if (i == 0) { + if (verbose) + BIO_printf(bio_err, "No entries found to mark expired\n"); + } else { + if (!save_index(dbfile, "new", db)) + goto end; + + if (!rotate_index(dbfile, "new", "old")) + goto end; + + if (verbose) + BIO_printf(bio_err, "Done. %d entries marked as expired\n", i); + } + } + + /*****************************************************************/ + /* Read extensions config file */ + if (extfile) { + if ((extconf = app_load_config(extfile)) == NULL) { + ret = 1; + goto end; + } + + if (verbose) + BIO_printf(bio_err, "Successfully loaded extensions file %s\n", + extfile); + + /* We can have sections in the ext file */ + if (extensions == NULL) { + extensions = NCONF_get_string(extconf, "default", "extensions"); + if (extensions == NULL) + extensions = "default"; + } + } + + /*****************************************************************/ + if (req || gencrl) { + if (spkac_file != NULL) { + output_der = 1; + batch = 1; + } + } + + def_ret = EVP_PKEY_get_default_digest_nid(pkey, &def_nid); + /* + * EVP_PKEY_get_default_digest_nid() returns 2 if the digest is + * mandatory for this algorithm. + */ + if (def_ret == 2 && def_nid == NID_undef) { + /* The signing algorithm requires there to be no digest */ + dgst = EVP_md_null(); + } else if (md == NULL + && (md = lookup_conf(conf, section, ENV_DEFAULT_MD)) == NULL) { + goto end; + } else { + if (strcmp(md, "default") == 0) { + if (def_ret <= 0) { + BIO_puts(bio_err, "no default digest\n"); + goto end; + } + md = (char *)OBJ_nid2sn(def_nid); + } + + if (!opt_md(md, &dgst)) + goto end; + } + + if (req) { + if (email_dn == 1) { + char *tmp_email_dn = NULL; + + tmp_email_dn = NCONF_get_string(conf, section, ENV_DEFAULT_EMAIL_DN); + if (tmp_email_dn != NULL && strcmp(tmp_email_dn, "no") == 0) + email_dn = 0; + } + if (verbose) + BIO_printf(bio_err, "message digest is %s\n", + OBJ_nid2ln(EVP_MD_type(dgst))); + if (policy == NULL + && (policy = lookup_conf(conf, section, ENV_POLICY)) == NULL) + goto end; + + if (verbose) + BIO_printf(bio_err, "policy is %s\n", policy); + + if (NCONF_get_string(conf, section, ENV_RAND_SERIAL) != NULL) { + rand_ser = 1; + } else { + serialfile = lookup_conf(conf, section, ENV_SERIAL); + if (serialfile == NULL) + goto end; + } + + if (extconf == NULL) { + /* + * no '-extfile' option, so we look for extensions in the main + * configuration file + */ + if (extensions == NULL) { + extensions = NCONF_get_string(conf, section, ENV_EXTENSIONS); + if (extensions == NULL) + ERR_clear_error(); + } + if (extensions != NULL) { + /* Check syntax of file */ + X509V3_CTX ctx; + X509V3_set_ctx_test(&ctx); + X509V3_set_nconf(&ctx, conf); + if (!X509V3_EXT_add_nconf(conf, &ctx, extensions, NULL)) { + BIO_printf(bio_err, + "Error Loading extension section %s\n", + extensions); + ret = 1; + goto end; + } + } + } + + if (startdate == NULL) { + startdate = NCONF_get_string(conf, section, ENV_DEFAULT_STARTDATE); + if (startdate == NULL) + ERR_clear_error(); + } + if (startdate != NULL && !ASN1_TIME_set_string_X509(NULL, startdate)) { + BIO_printf(bio_err, + "start date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n"); + goto end; + } + if (startdate == NULL) + startdate = "today"; + + if (enddate == NULL) { + enddate = NCONF_get_string(conf, section, ENV_DEFAULT_ENDDATE); + if (enddate == NULL) + ERR_clear_error(); + } + if (enddate != NULL && !ASN1_TIME_set_string_X509(NULL, enddate)) { + BIO_printf(bio_err, + "end date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n"); + goto end; + } + + if (days == 0) { + if (!NCONF_get_number(conf, section, ENV_DEFAULT_DAYS, &days)) + days = 0; + } + if (enddate == NULL && days == 0) { + BIO_printf(bio_err, "cannot lookup how many days to certify for\n"); + goto end; + } + + if (rand_ser) { + if ((serial = BN_new()) == NULL || !rand_serial(serial, NULL)) { + BIO_printf(bio_err, "error generating serial number\n"); + goto end; + } + } else { + if ((serial = load_serial(serialfile, create_ser, NULL)) == NULL) { + BIO_printf(bio_err, "error while loading serial number\n"); + goto end; + } + if (verbose) { + if (BN_is_zero(serial)) { + BIO_printf(bio_err, "next serial number is 00\n"); + } else { + if ((f = BN_bn2hex(serial)) == NULL) + goto end; + BIO_printf(bio_err, "next serial number is %s\n", f); + OPENSSL_free(f); + } + } + } + + if ((attribs = NCONF_get_section(conf, policy)) == NULL) { + BIO_printf(bio_err, "unable to find 'section' for %s\n", policy); + goto end; + } + + if ((cert_sk = sk_X509_new_null()) == NULL) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto end; + } + if (spkac_file != NULL) { + total++; + j = certify_spkac(&x, spkac_file, pkey, x509, dgst, sigopts, + attribs, db, serial, subj, chtype, multirdn, + email_dn, startdate, enddate, days, extensions, + conf, verbose, certopt, get_nameopt(), default_op, + ext_copy); + if (j < 0) + goto end; + if (j > 0) { + total_done++; + BIO_printf(bio_err, "\n"); + if (!BN_add_word(serial, 1)) + goto end; + if (!sk_X509_push(cert_sk, x)) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto end; + } + } + } + if (ss_cert_file != NULL) { + total++; + j = certify_cert(&x, ss_cert_file, pkey, x509, dgst, sigopts, + attribs, + db, serial, subj, chtype, multirdn, email_dn, + startdate, enddate, days, batch, extensions, + conf, verbose, certopt, get_nameopt(), default_op, + ext_copy); + if (j < 0) + goto end; + if (j > 0) { + total_done++; + BIO_printf(bio_err, "\n"); + if (!BN_add_word(serial, 1)) + goto end; + if (!sk_X509_push(cert_sk, x)) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto end; + } + } + } + if (infile != NULL) { + total++; + j = certify(&x, infile, pkey, x509p, dgst, sigopts, attribs, db, + serial, subj, chtype, multirdn, email_dn, startdate, + enddate, days, batch, extensions, conf, verbose, + certopt, get_nameopt(), default_op, ext_copy, selfsign); + if (j < 0) + goto end; + if (j > 0) { + total_done++; + BIO_printf(bio_err, "\n"); + if (!BN_add_word(serial, 1)) + goto end; + if (!sk_X509_push(cert_sk, x)) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto end; + } + } + } + for (i = 0; i < argc; i++) { + total++; + j = certify(&x, argv[i], pkey, x509p, dgst, sigopts, attribs, db, + serial, subj, chtype, multirdn, email_dn, startdate, + enddate, days, batch, extensions, conf, verbose, + certopt, get_nameopt(), default_op, ext_copy, selfsign); + if (j < 0) + goto end; + if (j > 0) { + total_done++; + BIO_printf(bio_err, "\n"); + if (!BN_add_word(serial, 1)) { + X509_free(x); + goto end; + } + if (!sk_X509_push(cert_sk, x)) { + BIO_printf(bio_err, "Memory allocation failure\n"); + X509_free(x); + goto end; + } + } + } + /* + * we have a stack of newly certified certificates and a data base + * and serial number that need updating + */ + + if (sk_X509_num(cert_sk) > 0) { + if (!batch) { + BIO_printf(bio_err, + "\n%d out of %d certificate requests certified, commit? [y/n]", + total_done, total); + (void)BIO_flush(bio_err); + tmp[0] = '\0'; + if (fgets(tmp, sizeof(tmp), stdin) == NULL) { + BIO_printf(bio_err, "CERTIFICATION CANCELED: I/O error\n"); + ret = 0; + goto end; + } + if (tmp[0] != 'y' && tmp[0] != 'Y') { + BIO_printf(bio_err, "CERTIFICATION CANCELED\n"); + ret = 0; + goto end; + } + } + + BIO_printf(bio_err, "Write out database with %d new entries\n", + sk_X509_num(cert_sk)); + + if (serialfile != NULL + && !save_serial(serialfile, "new", serial, NULL)) + goto end; + + if (!save_index(dbfile, "new", db)) + goto end; + } + + outdirlen = OPENSSL_strlcpy(new_cert, outdir, sizeof(new_cert)); +#ifndef OPENSSL_SYS_VMS + outdirlen = OPENSSL_strlcat(new_cert, "/", sizeof(new_cert)); +#endif + + if (verbose) + BIO_printf(bio_err, "writing new certificates\n"); + + for (i = 0; i < sk_X509_num(cert_sk); i++) { + BIO *Cout = NULL; + X509 *xi = sk_X509_value(cert_sk, i); + ASN1_INTEGER *serialNumber = X509_get_serialNumber(xi); + const unsigned char *psn = ASN1_STRING_get0_data(serialNumber); + const int snl = ASN1_STRING_length(serialNumber); + const int filen_len = 2 * (snl > 0 ? snl : 1) + sizeof(".pem"); + char *n = new_cert + outdirlen; + + if (outdirlen + filen_len > PATH_MAX) { + BIO_printf(bio_err, "certificate file name too long\n"); + goto end; + } + + if (snl > 0) { + static const char HEX_DIGITS[] = "0123456789ABCDEF"; + + for (j = 0; j < snl; j++, psn++) { + *n++ = HEX_DIGITS[*psn >> 4]; + *n++ = HEX_DIGITS[*psn & 0x0F]; + } + } else { + *(n++) = '0'; + *(n++) = '0'; + } + *(n++) = '.'; + *(n++) = 'p'; + *(n++) = 'e'; + *(n++) = 'm'; + *n = '\0'; /* closing new_cert */ + if (verbose) + BIO_printf(bio_err, "writing %s\n", new_cert); + + Sout = bio_open_default(outfile, 'w', + output_der ? FORMAT_ASN1 : FORMAT_TEXT); + if (Sout == NULL) + goto end; + + Cout = BIO_new_file(new_cert, "w"); + if (Cout == NULL) { + perror(new_cert); + goto end; + } + write_new_certificate(Cout, xi, 0, notext); + write_new_certificate(Sout, xi, output_der, notext); + BIO_free_all(Cout); + BIO_free_all(Sout); + Sout = NULL; + } + + if (sk_X509_num(cert_sk)) { + /* Rename the database and the serial file */ + if (serialfile != NULL + && !rotate_serial(serialfile, "new", "old")) + goto end; + + if (!rotate_index(dbfile, "new", "old")) + goto end; + + BIO_printf(bio_err, "Data Base Updated\n"); + } + } + + /*****************************************************************/ + if (gencrl) { + int crl_v2 = 0; + if (crl_ext == NULL) { + crl_ext = NCONF_get_string(conf, section, ENV_CRLEXT); + if (crl_ext == NULL) + ERR_clear_error(); + } + if (crl_ext != NULL) { + /* Check syntax of file */ + X509V3_CTX ctx; + X509V3_set_ctx_test(&ctx); + X509V3_set_nconf(&ctx, conf); + if (!X509V3_EXT_add_nconf(conf, &ctx, crl_ext, NULL)) { + BIO_printf(bio_err, + "Error Loading CRL extension section %s\n", crl_ext); + ret = 1; + goto end; + } + } + + if ((crlnumberfile = NCONF_get_string(conf, section, ENV_CRLNUMBER)) + != NULL) + if ((crlnumber = load_serial(crlnumberfile, 0, NULL)) == NULL) { + BIO_printf(bio_err, "error while loading CRL number\n"); + goto end; + } + + if (!crldays && !crlhours && !crlsec) { + if (!NCONF_get_number(conf, section, + ENV_DEFAULT_CRL_DAYS, &crldays)) + crldays = 0; + if (!NCONF_get_number(conf, section, + ENV_DEFAULT_CRL_HOURS, &crlhours)) + crlhours = 0; + ERR_clear_error(); + } + if ((crldays == 0) && (crlhours == 0) && (crlsec == 0)) { + BIO_printf(bio_err, + "cannot lookup how long until the next CRL is issued\n"); + goto end; + } + + if (verbose) + BIO_printf(bio_err, "making CRL\n"); + if ((crl = X509_CRL_new()) == NULL) + goto end; + if (!X509_CRL_set_issuer_name(crl, X509_get_subject_name(x509))) + goto end; + + tmptm = ASN1_TIME_new(); + if (tmptm == NULL + || X509_gmtime_adj(tmptm, 0) == NULL + || !X509_CRL_set1_lastUpdate(crl, tmptm) + || X509_time_adj_ex(tmptm, crldays, crlhours * 60 * 60 + crlsec, + NULL) == NULL) { + BIO_puts(bio_err, "error setting CRL nextUpdate\n"); + ASN1_TIME_free(tmptm); + goto end; + } + X509_CRL_set1_nextUpdate(crl, tmptm); + + ASN1_TIME_free(tmptm); + + for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { + pp = sk_OPENSSL_PSTRING_value(db->db->data, i); + if (pp[DB_type][0] == DB_TYPE_REV) { + if ((r = X509_REVOKED_new()) == NULL) + goto end; + j = make_revoked(r, pp[DB_rev_date]); + if (!j) + goto end; + if (j == 2) + crl_v2 = 1; + if (!BN_hex2bn(&serial, pp[DB_serial])) + goto end; + tmpser = BN_to_ASN1_INTEGER(serial, NULL); + BN_free(serial); + serial = NULL; + if (!tmpser) + goto end; + X509_REVOKED_set_serialNumber(r, tmpser); + ASN1_INTEGER_free(tmpser); + X509_CRL_add0_revoked(crl, r); + } + } + + /* + * sort the data so it will be written in serial number order + */ + X509_CRL_sort(crl); + + /* we now have a CRL */ + if (verbose) + BIO_printf(bio_err, "signing CRL\n"); + + /* Add any extensions asked for */ + + if (crl_ext != NULL || crlnumberfile != NULL) { + X509V3_CTX crlctx; + X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0); + X509V3_set_nconf(&crlctx, conf); + + if (crl_ext != NULL) + if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx, crl_ext, crl)) + goto end; + if (crlnumberfile != NULL) { + tmpser = BN_to_ASN1_INTEGER(crlnumber, NULL); + if (!tmpser) + goto end; + X509_CRL_add1_ext_i2d(crl, NID_crl_number, tmpser, 0, 0); + ASN1_INTEGER_free(tmpser); + crl_v2 = 1; + if (!BN_add_word(crlnumber, 1)) + goto end; + } + } + if (crl_ext != NULL || crl_v2) { + if (!X509_CRL_set_version(crl, 1)) + goto end; /* version 2 CRL */ + } + + /* we have a CRL number that need updating */ + if (crlnumberfile != NULL + && !save_serial(crlnumberfile, "new", crlnumber, NULL)) + goto end; + + BN_free(crlnumber); + crlnumber = NULL; + + if (!do_X509_CRL_sign(crl, pkey, dgst, sigopts)) + goto end; + + Sout = bio_open_default(outfile, 'w', + output_der ? FORMAT_ASN1 : FORMAT_TEXT); + if (Sout == NULL) + goto end; + + PEM_write_bio_X509_CRL(Sout, crl); + + /* Rename the crlnumber file */ + if (crlnumberfile != NULL + && !rotate_serial(crlnumberfile, "new", "old")) + goto end; + + } + /*****************************************************************/ + if (dorevoke) { + if (infile == NULL) { + BIO_printf(bio_err, "no input files\n"); + goto end; + } else { + X509 *revcert; + revcert = load_cert(infile, FORMAT_PEM, infile); + if (revcert == NULL) + goto end; + if (dorevoke == 2) + rev_type = REV_VALID; + j = do_revoke(revcert, db, rev_type, rev_arg); + if (j <= 0) + goto end; + X509_free(revcert); + + if (!save_index(dbfile, "new", db)) + goto end; + + if (!rotate_index(dbfile, "new", "old")) + goto end; + + BIO_printf(bio_err, "Data Base Updated\n"); + } + } + ret = 0; + + end: + if (ret) + ERR_print_errors(bio_err); + BIO_free_all(Sout); + BIO_free_all(out); + BIO_free_all(in); + sk_X509_pop_free(cert_sk, X509_free); + + if (free_key) + OPENSSL_free(key); + BN_free(serial); + BN_free(crlnumber); + free_index(db); + sk_OPENSSL_STRING_free(sigopts); + EVP_PKEY_free(pkey); + X509_free(x509); + X509_CRL_free(crl); + NCONF_free(conf); + NCONF_free(extconf); + release_engine(e); + return ret; +} + +static char *lookup_conf(const CONF *conf, const char *section, const char *tag) +{ + char *entry = NCONF_get_string(conf, section, tag); + if (entry == NULL) + BIO_printf(bio_err, "variable lookup failed for %s::%s\n", section, tag); + return entry; +} + +static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, + const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(CONF_VALUE) *policy, CA_DB *db, + BIGNUM *serial, const char *subj, unsigned long chtype, + int multirdn, int email_dn, const char *startdate, + const char *enddate, + long days, int batch, const char *ext_sect, CONF *lconf, + int verbose, unsigned long certopt, unsigned long nameopt, + int default_op, int ext_copy, int selfsign) +{ + X509_REQ *req = NULL; + BIO *in = NULL; + EVP_PKEY *pktmp = NULL; + int ok = -1, i; + + in = BIO_new_file(infile, "r"); + if (in == NULL) { + ERR_print_errors(bio_err); + goto end; + } + if ((req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL)) == NULL) { + BIO_printf(bio_err, "Error reading certificate request in %s\n", + infile); + goto end; + } + if (verbose) + X509_REQ_print_ex(bio_err, req, nameopt, X509_FLAG_COMPAT); + + BIO_printf(bio_err, "Check that the request matches the signature\n"); + + if (selfsign && !X509_REQ_check_private_key(req, pkey)) { + BIO_printf(bio_err, + "Certificate request and CA private key do not match\n"); + ok = 0; + goto end; + } + if ((pktmp = X509_REQ_get0_pubkey(req)) == NULL) { + BIO_printf(bio_err, "error unpacking public key\n"); + goto end; + } + i = X509_REQ_verify(req, pktmp); + pktmp = NULL; + if (i < 0) { + ok = 0; + BIO_printf(bio_err, "Signature verification problems....\n"); + ERR_print_errors(bio_err); + goto end; + } + if (i == 0) { + ok = 0; + BIO_printf(bio_err, + "Signature did not match the certificate request\n"); + ERR_print_errors(bio_err); + goto end; + } else { + BIO_printf(bio_err, "Signature ok\n"); + } + + ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj, + chtype, multirdn, email_dn, startdate, enddate, days, batch, + verbose, req, ext_sect, lconf, certopt, nameopt, default_op, + ext_copy, selfsign); + + end: + X509_REQ_free(req); + BIO_free(in); + return ok; +} + +static int certify_cert(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, + const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(CONF_VALUE) *policy, CA_DB *db, + BIGNUM *serial, const char *subj, unsigned long chtype, + int multirdn, int email_dn, const char *startdate, + const char *enddate, long days, int batch, const char *ext_sect, + CONF *lconf, int verbose, unsigned long certopt, + unsigned long nameopt, int default_op, int ext_copy) +{ + X509 *req = NULL; + X509_REQ *rreq = NULL; + EVP_PKEY *pktmp = NULL; + int ok = -1, i; + + if ((req = load_cert(infile, FORMAT_PEM, infile)) == NULL) + goto end; + if (verbose) + X509_print(bio_err, req); + + BIO_printf(bio_err, "Check that the request matches the signature\n"); + + if ((pktmp = X509_get0_pubkey(req)) == NULL) { + BIO_printf(bio_err, "error unpacking public key\n"); + goto end; + } + i = X509_verify(req, pktmp); + if (i < 0) { + ok = 0; + BIO_printf(bio_err, "Signature verification problems....\n"); + goto end; + } + if (i == 0) { + ok = 0; + BIO_printf(bio_err, "Signature did not match the certificate\n"); + goto end; + } else { + BIO_printf(bio_err, "Signature ok\n"); + } + + if ((rreq = X509_to_X509_REQ(req, NULL, NULL)) == NULL) + goto end; + + ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj, + chtype, multirdn, email_dn, startdate, enddate, days, batch, + verbose, rreq, ext_sect, lconf, certopt, nameopt, default_op, + ext_copy, 0); + + end: + X509_REQ_free(rreq); + X509_free(req); + return ok; +} + +static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, + const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, + const char *subj, unsigned long chtype, int multirdn, + int email_dn, const char *startdate, const char *enddate, long days, + int batch, int verbose, X509_REQ *req, const char *ext_sect, + CONF *lconf, unsigned long certopt, unsigned long nameopt, + int default_op, int ext_copy, int selfsign) +{ + X509_NAME *name = NULL, *CAname = NULL, *subject = NULL; + const ASN1_TIME *tm; + ASN1_STRING *str, *str2; + ASN1_OBJECT *obj; + X509 *ret = NULL; + X509_NAME_ENTRY *ne, *tne; + EVP_PKEY *pktmp; + int ok = -1, i, j, last, nid; + const char *p; + CONF_VALUE *cv; + OPENSSL_STRING row[DB_NUMBER]; + OPENSSL_STRING *irow = NULL; + OPENSSL_STRING *rrow = NULL; + char buf[25]; + + for (i = 0; i < DB_NUMBER; i++) + row[i] = NULL; + + if (subj) { + X509_NAME *n = parse_name(subj, chtype, multirdn); + + if (!n) { + ERR_print_errors(bio_err); + goto end; + } + X509_REQ_set_subject_name(req, n); + X509_NAME_free(n); + } + + if (default_op) + BIO_printf(bio_err, "The Subject's Distinguished Name is as follows\n"); + + name = X509_REQ_get_subject_name(req); + for (i = 0; i < X509_NAME_entry_count(name); i++) { + ne = X509_NAME_get_entry(name, i); + str = X509_NAME_ENTRY_get_data(ne); + obj = X509_NAME_ENTRY_get_object(ne); + nid = OBJ_obj2nid(obj); + + if (msie_hack) { + /* assume all type should be strings */ + + if (str->type == V_ASN1_UNIVERSALSTRING) + ASN1_UNIVERSALSTRING_to_string(str); + + if (str->type == V_ASN1_IA5STRING && nid != NID_pkcs9_emailAddress) + str->type = V_ASN1_T61STRING; + + if (nid == NID_pkcs9_emailAddress + && str->type == V_ASN1_PRINTABLESTRING) + str->type = V_ASN1_IA5STRING; + } + + /* If no EMAIL is wanted in the subject */ + if (nid == NID_pkcs9_emailAddress && !email_dn) + continue; + + /* check some things */ + if (nid == NID_pkcs9_emailAddress && str->type != V_ASN1_IA5STRING) { + BIO_printf(bio_err, + "\nemailAddress type needs to be of type IA5STRING\n"); + goto end; + } + if (str->type != V_ASN1_BMPSTRING && str->type != V_ASN1_UTF8STRING) { + j = ASN1_PRINTABLE_type(str->data, str->length); + if ((j == V_ASN1_T61STRING && str->type != V_ASN1_T61STRING) || + (j == V_ASN1_IA5STRING && str->type == V_ASN1_PRINTABLESTRING)) + { + BIO_printf(bio_err, + "\nThe string contains characters that are illegal for the ASN.1 type\n"); + goto end; + } + } + + if (default_op) + old_entry_print(obj, str); + } + + /* Ok, now we check the 'policy' stuff. */ + if ((subject = X509_NAME_new()) == NULL) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto end; + } + + /* take a copy of the issuer name before we mess with it. */ + if (selfsign) + CAname = X509_NAME_dup(name); + else + CAname = X509_NAME_dup(X509_get_subject_name(x509)); + if (CAname == NULL) + goto end; + str = str2 = NULL; + + for (i = 0; i < sk_CONF_VALUE_num(policy); i++) { + cv = sk_CONF_VALUE_value(policy, i); /* get the object id */ + if ((j = OBJ_txt2nid(cv->name)) == NID_undef) { + BIO_printf(bio_err, + "%s:unknown object type in 'policy' configuration\n", + cv->name); + goto end; + } + obj = OBJ_nid2obj(j); + + last = -1; + for (;;) { + X509_NAME_ENTRY *push = NULL; + + /* lookup the object in the supplied name list */ + j = X509_NAME_get_index_by_OBJ(name, obj, last); + if (j < 0) { + if (last != -1) + break; + tne = NULL; + } else { + tne = X509_NAME_get_entry(name, j); + } + last = j; + + /* depending on the 'policy', decide what to do. */ + if (strcmp(cv->value, "optional") == 0) { + if (tne != NULL) + push = tne; + } else if (strcmp(cv->value, "supplied") == 0) { + if (tne == NULL) { + BIO_printf(bio_err, + "The %s field needed to be supplied and was missing\n", + cv->name); + goto end; + } else { + push = tne; + } + } else if (strcmp(cv->value, "match") == 0) { + int last2; + + if (tne == NULL) { + BIO_printf(bio_err, + "The mandatory %s field was missing\n", + cv->name); + goto end; + } + + last2 = -1; + + again2: + j = X509_NAME_get_index_by_OBJ(CAname, obj, last2); + if ((j < 0) && (last2 == -1)) { + BIO_printf(bio_err, + "The %s field does not exist in the CA certificate,\n" + "the 'policy' is misconfigured\n", cv->name); + goto end; + } + if (j >= 0) { + push = X509_NAME_get_entry(CAname, j); + str = X509_NAME_ENTRY_get_data(tne); + str2 = X509_NAME_ENTRY_get_data(push); + last2 = j; + if (ASN1_STRING_cmp(str, str2) != 0) + goto again2; + } + if (j < 0) { + BIO_printf(bio_err, + "The %s field is different between\n" + "CA certificate (%s) and the request (%s)\n", + cv->name, + ((str2 == NULL) ? "NULL" : (char *)str2->data), + ((str == NULL) ? "NULL" : (char *)str->data)); + goto end; + } + } else { + BIO_printf(bio_err, + "%s:invalid type in 'policy' configuration\n", + cv->value); + goto end; + } + + if (push != NULL) { + if (!X509_NAME_add_entry(subject, push, -1, 0)) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto end; + } + } + if (j < 0) + break; + } + } + + if (preserve) { + X509_NAME_free(subject); + /* subject=X509_NAME_dup(X509_REQ_get_subject_name(req)); */ + subject = X509_NAME_dup(name); + if (subject == NULL) + goto end; + } + + /* We are now totally happy, lets make and sign the certificate */ + if (verbose) + BIO_printf(bio_err, + "Everything appears to be ok, creating and signing the certificate\n"); + + if ((ret = X509_new()) == NULL) + goto end; + +#ifdef X509_V3 + /* Make it an X509 v3 certificate. */ + if (!X509_set_version(ret, 2)) + goto end; +#endif + + if (BN_to_ASN1_INTEGER(serial, X509_get_serialNumber(ret)) == NULL) + goto end; + if (selfsign) { + if (!X509_set_issuer_name(ret, subject)) + goto end; + } else { + if (!X509_set_issuer_name(ret, X509_get_subject_name(x509))) + goto end; + } + + if (!set_cert_times(ret, startdate, enddate, days)) + goto end; + + if (enddate != NULL) { + int tdays; + + if (!ASN1_TIME_diff(&tdays, NULL, NULL, X509_get0_notAfter(ret))) + goto end; + days = tdays; + } + + if (!X509_set_subject_name(ret, subject)) + goto end; + + pktmp = X509_REQ_get0_pubkey(req); + i = X509_set_pubkey(ret, pktmp); + if (!i) + goto end; + + /* Lets add the extensions, if there are any */ + if (ext_sect) { + X509V3_CTX ctx; + + /* Initialize the context structure */ + if (selfsign) + X509V3_set_ctx(&ctx, ret, ret, req, NULL, 0); + else + X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0); + + if (extconf != NULL) { + if (verbose) + BIO_printf(bio_err, "Extra configuration file found\n"); + + /* Use the extconf configuration db LHASH */ + X509V3_set_nconf(&ctx, extconf); + + /* Test the structure (needed?) */ + /* X509V3_set_ctx_test(&ctx); */ + + /* Adds exts contained in the configuration file */ + if (!X509V3_EXT_add_nconf(extconf, &ctx, ext_sect, ret)) { + BIO_printf(bio_err, + "ERROR: adding extensions in section %s\n", + ext_sect); + ERR_print_errors(bio_err); + goto end; + } + if (verbose) + BIO_printf(bio_err, + "Successfully added extensions from file.\n"); + } else if (ext_sect) { + /* We found extensions to be set from config file */ + X509V3_set_nconf(&ctx, lconf); + + if (!X509V3_EXT_add_nconf(lconf, &ctx, ext_sect, ret)) { + BIO_printf(bio_err, + "ERROR: adding extensions in section %s\n", + ext_sect); + ERR_print_errors(bio_err); + goto end; + } + + if (verbose) + BIO_printf(bio_err, + "Successfully added extensions from config\n"); + } + } + + /* Copy extensions from request (if any) */ + + if (!copy_extensions(ret, req, ext_copy)) { + BIO_printf(bio_err, "ERROR: adding extensions from request\n"); + ERR_print_errors(bio_err); + goto end; + } + + { + const STACK_OF(X509_EXTENSION) *exts = X509_get0_extensions(ret); + + if (exts != NULL && sk_X509_EXTENSION_num(exts) > 0) + /* Make it an X509 v3 certificate. */ + if (!X509_set_version(ret, 2)) + goto end; + } + + if (verbose) + BIO_printf(bio_err, + "The subject name appears to be ok, checking data base for clashes\n"); + + /* Build the correct Subject if no e-mail is wanted in the subject. */ + if (!email_dn) { + X509_NAME_ENTRY *tmpne; + X509_NAME *dn_subject; + + /* + * Its best to dup the subject DN and then delete any email addresses + * because this retains its structure. + */ + if ((dn_subject = X509_NAME_dup(subject)) == NULL) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto end; + } + i = -1; + while ((i = X509_NAME_get_index_by_NID(dn_subject, + NID_pkcs9_emailAddress, + i)) >= 0) { + tmpne = X509_NAME_delete_entry(dn_subject, i--); + X509_NAME_ENTRY_free(tmpne); + } + + if (!X509_set_subject_name(ret, dn_subject)) { + X509_NAME_free(dn_subject); + goto end; + } + X509_NAME_free(dn_subject); + } + + row[DB_name] = X509_NAME_oneline(X509_get_subject_name(ret), NULL, 0); + if (row[DB_name] == NULL) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto end; + } + + if (BN_is_zero(serial)) + row[DB_serial] = OPENSSL_strdup("00"); + else + row[DB_serial] = BN_bn2hex(serial); + if (row[DB_serial] == NULL) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto end; + } + + if (row[DB_name][0] == '\0') { + /* + * An empty subject! We'll use the serial number instead. If + * unique_subject is in use then we don't want different entries with + * empty subjects matching each other. + */ + OPENSSL_free(row[DB_name]); + row[DB_name] = OPENSSL_strdup(row[DB_serial]); + if (row[DB_name] == NULL) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto end; + } + } + + if (db->attributes.unique_subject) { + OPENSSL_STRING *crow = row; + + rrow = TXT_DB_get_by_index(db->db, DB_name, crow); + if (rrow != NULL) { + BIO_printf(bio_err, + "ERROR:There is already a certificate for %s\n", + row[DB_name]); + } + } + if (rrow == NULL) { + rrow = TXT_DB_get_by_index(db->db, DB_serial, row); + if (rrow != NULL) { + BIO_printf(bio_err, + "ERROR:Serial number %s has already been issued,\n", + row[DB_serial]); + BIO_printf(bio_err, + " check the database/serial_file for corruption\n"); + } + } + + if (rrow != NULL) { + BIO_printf(bio_err, "The matching entry has the following details\n"); + if (rrow[DB_type][0] == DB_TYPE_EXP) + p = "Expired"; + else if (rrow[DB_type][0] == DB_TYPE_REV) + p = "Revoked"; + else if (rrow[DB_type][0] == DB_TYPE_VAL) + p = "Valid"; + else + p = "\ninvalid type, Data base error\n"; + BIO_printf(bio_err, "Type :%s\n", p);; + if (rrow[DB_type][0] == DB_TYPE_REV) { + p = rrow[DB_exp_date]; + if (p == NULL) + p = "undef"; + BIO_printf(bio_err, "Was revoked on:%s\n", p); + } + p = rrow[DB_exp_date]; + if (p == NULL) + p = "undef"; + BIO_printf(bio_err, "Expires on :%s\n", p); + p = rrow[DB_serial]; + if (p == NULL) + p = "undef"; + BIO_printf(bio_err, "Serial Number :%s\n", p); + p = rrow[DB_file]; + if (p == NULL) + p = "undef"; + BIO_printf(bio_err, "File name :%s\n", p); + p = rrow[DB_name]; + if (p == NULL) + p = "undef"; + BIO_printf(bio_err, "Subject Name :%s\n", p); + ok = -1; /* This is now a 'bad' error. */ + goto end; + } + + if (!default_op) { + BIO_printf(bio_err, "Certificate Details:\n"); + /* + * Never print signature details because signature not present + */ + certopt |= X509_FLAG_NO_SIGDUMP | X509_FLAG_NO_SIGNAME; + X509_print_ex(bio_err, ret, nameopt, certopt); + } + + BIO_printf(bio_err, "Certificate is to be certified until "); + ASN1_TIME_print(bio_err, X509_get0_notAfter(ret)); + if (days) + BIO_printf(bio_err, " (%ld days)", days); + BIO_printf(bio_err, "\n"); + + if (!batch) { + + BIO_printf(bio_err, "Sign the certificate? [y/n]:"); + (void)BIO_flush(bio_err); + buf[0] = '\0'; + if (fgets(buf, sizeof(buf), stdin) == NULL) { + BIO_printf(bio_err, + "CERTIFICATE WILL NOT BE CERTIFIED: I/O error\n"); + ok = 0; + goto end; + } + if (!(buf[0] == 'y' || buf[0] == 'Y')) { + BIO_printf(bio_err, "CERTIFICATE WILL NOT BE CERTIFIED\n"); + ok = 0; + goto end; + } + } + + pktmp = X509_get0_pubkey(ret); + if (EVP_PKEY_missing_parameters(pktmp) && + !EVP_PKEY_missing_parameters(pkey)) + EVP_PKEY_copy_parameters(pktmp, pkey); + + if (!do_X509_sign(ret, pkey, dgst, sigopts)) + goto end; + + /* We now just add it to the database as DB_TYPE_VAL('V') */ + row[DB_type] = OPENSSL_strdup("V"); + tm = X509_get0_notAfter(ret); + row[DB_exp_date] = app_malloc(tm->length + 1, "row expdate"); + memcpy(row[DB_exp_date], tm->data, tm->length); + row[DB_exp_date][tm->length] = '\0'; + row[DB_rev_date] = NULL; + row[DB_file] = OPENSSL_strdup("unknown"); + if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) || + (row[DB_file] == NULL) || (row[DB_name] == NULL)) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto end; + } + + irow = app_malloc(sizeof(*irow) * (DB_NUMBER + 1), "row space"); + for (i = 0; i < DB_NUMBER; i++) + irow[i] = row[i]; + irow[DB_NUMBER] = NULL; + + if (!TXT_DB_insert(db->db, irow)) { + BIO_printf(bio_err, "failed to update database\n"); + BIO_printf(bio_err, "TXT_DB error number %ld\n", db->db->error); + goto end; + } + irow = NULL; + ok = 1; + end: + if (ok != 1) { + for (i = 0; i < DB_NUMBER; i++) + OPENSSL_free(row[i]); + } + OPENSSL_free(irow); + + X509_NAME_free(CAname); + X509_NAME_free(subject); + if (ok <= 0) + X509_free(ret); + else + *xret = ret; + return ok; +} + +static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext) +{ + + if (output_der) { + (void)i2d_X509_bio(bp, x); + return; + } + if (!notext) + X509_print(bp, x); + PEM_write_bio_X509(bp, x); +} + +static int certify_spkac(X509 **xret, const char *infile, EVP_PKEY *pkey, + X509 *x509, const EVP_MD *dgst, + STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(CONF_VALUE) *policy, CA_DB *db, + BIGNUM *serial, const char *subj, unsigned long chtype, + int multirdn, int email_dn, const char *startdate, + const char *enddate, long days, const char *ext_sect, + CONF *lconf, int verbose, unsigned long certopt, + unsigned long nameopt, int default_op, int ext_copy) +{ + STACK_OF(CONF_VALUE) *sk = NULL; + LHASH_OF(CONF_VALUE) *parms = NULL; + X509_REQ *req = NULL; + CONF_VALUE *cv = NULL; + NETSCAPE_SPKI *spki = NULL; + char *type, *buf; + EVP_PKEY *pktmp = NULL; + X509_NAME *n = NULL; + X509_NAME_ENTRY *ne = NULL; + int ok = -1, i, j; + long errline; + int nid; + + /* + * Load input file into a hash table. (This is just an easy + * way to read and parse the file, then put it into a convenient + * STACK format). + */ + parms = CONF_load(NULL, infile, &errline); + if (parms == NULL) { + BIO_printf(bio_err, "error on line %ld of %s\n", errline, infile); + ERR_print_errors(bio_err); + goto end; + } + + sk = CONF_get_section(parms, "default"); + if (sk_CONF_VALUE_num(sk) == 0) { + BIO_printf(bio_err, "no name/value pairs found in %s\n", infile); + goto end; + } + + /* + * Now create a dummy X509 request structure. We don't actually + * have an X509 request, but we have many of the components + * (a public key, various DN components). The idea is that we + * put these components into the right X509 request structure + * and we can use the same code as if you had a real X509 request. + */ + req = X509_REQ_new(); + if (req == NULL) { + ERR_print_errors(bio_err); + goto end; + } + + /* + * Build up the subject name set. + */ + n = X509_REQ_get_subject_name(req); + + for (i = 0;; i++) { + if (sk_CONF_VALUE_num(sk) <= i) + break; + + cv = sk_CONF_VALUE_value(sk, i); + type = cv->name; + /* + * Skip past any leading X. X: X, etc to allow for multiple instances + */ + for (buf = cv->name; *buf; buf++) + if ((*buf == ':') || (*buf == ',') || (*buf == '.')) { + buf++; + if (*buf) + type = buf; + break; + } + + buf = cv->value; + if ((nid = OBJ_txt2nid(type)) == NID_undef) { + if (strcmp(type, "SPKAC") == 0) { + spki = NETSCAPE_SPKI_b64_decode(cv->value, -1); + if (spki == NULL) { + BIO_printf(bio_err, + "unable to load Netscape SPKAC structure\n"); + ERR_print_errors(bio_err); + goto end; + } + } + continue; + } + + if (!X509_NAME_add_entry_by_NID(n, nid, chtype, + (unsigned char *)buf, -1, -1, 0)) + goto end; + } + if (spki == NULL) { + BIO_printf(bio_err, "Netscape SPKAC structure not found in %s\n", + infile); + goto end; + } + + /* + * Now extract the key from the SPKI structure. + */ + + BIO_printf(bio_err, "Check that the SPKAC request matches the signature\n"); + + if ((pktmp = NETSCAPE_SPKI_get_pubkey(spki)) == NULL) { + BIO_printf(bio_err, "error unpacking SPKAC public key\n"); + goto end; + } + + j = NETSCAPE_SPKI_verify(spki, pktmp); + if (j <= 0) { + EVP_PKEY_free(pktmp); + BIO_printf(bio_err, + "signature verification failed on SPKAC public key\n"); + goto end; + } + BIO_printf(bio_err, "Signature ok\n"); + + X509_REQ_set_pubkey(req, pktmp); + EVP_PKEY_free(pktmp); + ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj, + chtype, multirdn, email_dn, startdate, enddate, days, 1, + verbose, req, ext_sect, lconf, certopt, nameopt, default_op, + ext_copy, 0); + end: + X509_REQ_free(req); + CONF_free(parms); + NETSCAPE_SPKI_free(spki); + X509_NAME_ENTRY_free(ne); + + return ok; +} + +static int check_time_format(const char *str) +{ + return ASN1_TIME_set_string(NULL, str); +} + +static int do_revoke(X509 *x509, CA_DB *db, REVINFO_TYPE rev_type, + const char *value) +{ + const ASN1_TIME *tm = NULL; + char *row[DB_NUMBER], **rrow, **irow; + char *rev_str = NULL; + BIGNUM *bn = NULL; + int ok = -1, i; + + for (i = 0; i < DB_NUMBER; i++) + row[i] = NULL; + row[DB_name] = X509_NAME_oneline(X509_get_subject_name(x509), NULL, 0); + bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509), NULL); + if (!bn) + goto end; + if (BN_is_zero(bn)) + row[DB_serial] = OPENSSL_strdup("00"); + else + row[DB_serial] = BN_bn2hex(bn); + BN_free(bn); + if (row[DB_name] != NULL && row[DB_name][0] == '\0') { + /* Entries with empty Subjects actually use the serial number instead */ + OPENSSL_free(row[DB_name]); + row[DB_name] = OPENSSL_strdup(row[DB_serial]); + } + if ((row[DB_name] == NULL) || (row[DB_serial] == NULL)) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto end; + } + /* + * We have to lookup by serial number because name lookup skips revoked + * certs + */ + rrow = TXT_DB_get_by_index(db->db, DB_serial, row); + if (rrow == NULL) { + BIO_printf(bio_err, + "Adding Entry with serial number %s to DB for %s\n", + row[DB_serial], row[DB_name]); + + /* We now just add it to the database as DB_TYPE_REV('V') */ + row[DB_type] = OPENSSL_strdup("V"); + tm = X509_get0_notAfter(x509); + row[DB_exp_date] = app_malloc(tm->length + 1, "row exp_data"); + memcpy(row[DB_exp_date], tm->data, tm->length); + row[DB_exp_date][tm->length] = '\0'; + row[DB_rev_date] = NULL; + row[DB_file] = OPENSSL_strdup("unknown"); + + if (row[DB_type] == NULL || row[DB_file] == NULL) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto end; + } + + irow = app_malloc(sizeof(*irow) * (DB_NUMBER + 1), "row ptr"); + for (i = 0; i < DB_NUMBER; i++) + irow[i] = row[i]; + irow[DB_NUMBER] = NULL; + + if (!TXT_DB_insert(db->db, irow)) { + BIO_printf(bio_err, "failed to update database\n"); + BIO_printf(bio_err, "TXT_DB error number %ld\n", db->db->error); + OPENSSL_free(irow); + goto end; + } + + for (i = 0; i < DB_NUMBER; i++) + row[i] = NULL; + + /* Revoke Certificate */ + if (rev_type == REV_VALID) + ok = 1; + else + /* Retry revocation after DB insertion */ + ok = do_revoke(x509, db, rev_type, value); + + goto end; + + } else if (index_name_cmp_noconst(row, rrow)) { + BIO_printf(bio_err, "ERROR:name does not match %s\n", row[DB_name]); + goto end; + } else if (rev_type == REV_VALID) { + BIO_printf(bio_err, "ERROR:Already present, serial number %s\n", + row[DB_serial]); + goto end; + } else if (rrow[DB_type][0] == DB_TYPE_REV) { + BIO_printf(bio_err, "ERROR:Already revoked, serial number %s\n", + row[DB_serial]); + goto end; + } else { + BIO_printf(bio_err, "Revoking Certificate %s.\n", rrow[DB_serial]); + rev_str = make_revocation_str(rev_type, value); + if (!rev_str) { + BIO_printf(bio_err, "Error in revocation arguments\n"); + goto end; + } + rrow[DB_type][0] = DB_TYPE_REV; + rrow[DB_type][1] = '\0'; + rrow[DB_rev_date] = rev_str; + } + ok = 1; + end: + for (i = 0; i < DB_NUMBER; i++) + OPENSSL_free(row[i]); + return ok; +} + +static int get_certificate_status(const char *serial, CA_DB *db) +{ + char *row[DB_NUMBER], **rrow; + int ok = -1, i; + size_t serial_len = strlen(serial); + + /* Free Resources */ + for (i = 0; i < DB_NUMBER; i++) + row[i] = NULL; + + /* Malloc needed char spaces */ + row[DB_serial] = app_malloc(serial_len + 2, "row serial#"); + + if (serial_len % 2) { + /* + * Set the first char to 0 + */ + row[DB_serial][0] = '0'; + + /* Copy String from serial to row[DB_serial] */ + memcpy(row[DB_serial] + 1, serial, serial_len); + row[DB_serial][serial_len + 1] = '\0'; + } else { + /* Copy String from serial to row[DB_serial] */ + memcpy(row[DB_serial], serial, serial_len); + row[DB_serial][serial_len] = '\0'; + } + + /* Make it Upper Case */ + make_uppercase(row[DB_serial]); + + ok = 1; + + /* Search for the certificate */ + rrow = TXT_DB_get_by_index(db->db, DB_serial, row); + if (rrow == NULL) { + BIO_printf(bio_err, "Serial %s not present in db.\n", row[DB_serial]); + ok = -1; + goto end; + } else if (rrow[DB_type][0] == DB_TYPE_VAL) { + BIO_printf(bio_err, "%s=Valid (%c)\n", + row[DB_serial], rrow[DB_type][0]); + goto end; + } else if (rrow[DB_type][0] == DB_TYPE_REV) { + BIO_printf(bio_err, "%s=Revoked (%c)\n", + row[DB_serial], rrow[DB_type][0]); + goto end; + } else if (rrow[DB_type][0] == DB_TYPE_EXP) { + BIO_printf(bio_err, "%s=Expired (%c)\n", + row[DB_serial], rrow[DB_type][0]); + goto end; + } else if (rrow[DB_type][0] == DB_TYPE_SUSP) { + BIO_printf(bio_err, "%s=Suspended (%c)\n", + row[DB_serial], rrow[DB_type][0]); + goto end; + } else { + BIO_printf(bio_err, "%s=Unknown (%c).\n", + row[DB_serial], rrow[DB_type][0]); + ok = -1; + } + end: + for (i = 0; i < DB_NUMBER; i++) { + OPENSSL_free(row[i]); + } + return ok; +} + +static int do_updatedb(CA_DB *db) +{ + ASN1_UTCTIME *a_tm = NULL; + int i, cnt = 0; + int db_y2k, a_y2k; /* flags = 1 if y >= 2000 */ + char **rrow, *a_tm_s; + + a_tm = ASN1_UTCTIME_new(); + if (a_tm == NULL) + return -1; + + /* get actual time and make a string */ + if (X509_gmtime_adj(a_tm, 0) == NULL) { + ASN1_UTCTIME_free(a_tm); + return -1; + } + a_tm_s = app_malloc(a_tm->length + 1, "time string"); + + memcpy(a_tm_s, a_tm->data, a_tm->length); + a_tm_s[a_tm->length] = '\0'; + + if (strncmp(a_tm_s, "49", 2) <= 0) + a_y2k = 1; + else + a_y2k = 0; + + for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { + rrow = sk_OPENSSL_PSTRING_value(db->db->data, i); + + if (rrow[DB_type][0] == DB_TYPE_VAL) { + /* ignore entries that are not valid */ + if (strncmp(rrow[DB_exp_date], "49", 2) <= 0) + db_y2k = 1; + else + db_y2k = 0; + + if (db_y2k == a_y2k) { + /* all on the same y2k side */ + if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0) { + rrow[DB_type][0] = DB_TYPE_EXP; + rrow[DB_type][1] = '\0'; + cnt++; + + BIO_printf(bio_err, "%s=Expired\n", rrow[DB_serial]); + } + } else if (db_y2k < a_y2k) { + rrow[DB_type][0] = DB_TYPE_EXP; + rrow[DB_type][1] = '\0'; + cnt++; + + BIO_printf(bio_err, "%s=Expired\n", rrow[DB_serial]); + } + + } + } + + ASN1_UTCTIME_free(a_tm); + OPENSSL_free(a_tm_s); + return cnt; +} + +static const char *crl_reasons[] = { + /* CRL reason strings */ + "unspecified", + "keyCompromise", + "CACompromise", + "affiliationChanged", + "superseded", + "cessationOfOperation", + "certificateHold", + "removeFromCRL", + /* Additional pseudo reasons */ + "holdInstruction", + "keyTime", + "CAkeyTime" +}; + +#define NUM_REASONS OSSL_NELEM(crl_reasons) + +/* + * Given revocation information convert to a DB string. The format of the + * string is: revtime[,reason,extra]. Where 'revtime' is the revocation time + * (the current time). 'reason' is the optional CRL reason and 'extra' is any + * additional argument + */ + +static char *make_revocation_str(REVINFO_TYPE rev_type, const char *rev_arg) +{ + char *str; + const char *reason = NULL, *other = NULL; + ASN1_OBJECT *otmp; + ASN1_UTCTIME *revtm = NULL; + int i; + + switch (rev_type) { + case REV_NONE: + case REV_VALID: + break; + + case REV_CRL_REASON: + for (i = 0; i < 8; i++) { + if (strcasecmp(rev_arg, crl_reasons[i]) == 0) { + reason = crl_reasons[i]; + break; + } + } + if (reason == NULL) { + BIO_printf(bio_err, "Unknown CRL reason %s\n", rev_arg); + return NULL; + } + break; + + case REV_HOLD: + /* Argument is an OID */ + otmp = OBJ_txt2obj(rev_arg, 0); + ASN1_OBJECT_free(otmp); + + if (otmp == NULL) { + BIO_printf(bio_err, "Invalid object identifier %s\n", rev_arg); + return NULL; + } + + reason = "holdInstruction"; + other = rev_arg; + break; + + case REV_KEY_COMPROMISE: + case REV_CA_COMPROMISE: + /* Argument is the key compromise time */ + if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg)) { + BIO_printf(bio_err, + "Invalid time format %s. Need YYYYMMDDHHMMSSZ\n", + rev_arg); + return NULL; + } + other = rev_arg; + if (rev_type == REV_KEY_COMPROMISE) + reason = "keyTime"; + else + reason = "CAkeyTime"; + + break; + } + + revtm = X509_gmtime_adj(NULL, 0); + + if (!revtm) + return NULL; + + i = revtm->length + 1; + + if (reason) + i += strlen(reason) + 1; + if (other) + i += strlen(other) + 1; + + str = app_malloc(i, "revocation reason"); + OPENSSL_strlcpy(str, (char *)revtm->data, i); + if (reason) { + OPENSSL_strlcat(str, ",", i); + OPENSSL_strlcat(str, reason, i); + } + if (other) { + OPENSSL_strlcat(str, ",", i); + OPENSSL_strlcat(str, other, i); + } + ASN1_UTCTIME_free(revtm); + return str; +} + +/*- + * Convert revocation field to X509_REVOKED entry + * return code: + * 0 error + * 1 OK + * 2 OK and some extensions added (i.e. V2 CRL) + */ + +static int make_revoked(X509_REVOKED *rev, const char *str) +{ + char *tmp = NULL; + int reason_code = -1; + int i, ret = 0; + ASN1_OBJECT *hold = NULL; + ASN1_GENERALIZEDTIME *comp_time = NULL; + ASN1_ENUMERATED *rtmp = NULL; + + ASN1_TIME *revDate = NULL; + + i = unpack_revinfo(&revDate, &reason_code, &hold, &comp_time, str); + + if (i == 0) + goto end; + + if (rev && !X509_REVOKED_set_revocationDate(rev, revDate)) + goto end; + + if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)) { + rtmp = ASN1_ENUMERATED_new(); + if (rtmp == NULL || !ASN1_ENUMERATED_set(rtmp, reason_code)) + goto end; + if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0)) + goto end; + } + + if (rev && comp_time) { + if (!X509_REVOKED_add1_ext_i2d + (rev, NID_invalidity_date, comp_time, 0, 0)) + goto end; + } + if (rev && hold) { + if (!X509_REVOKED_add1_ext_i2d + (rev, NID_hold_instruction_code, hold, 0, 0)) + goto end; + } + + if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS) + ret = 2; + else + ret = 1; + + end: + + OPENSSL_free(tmp); + ASN1_OBJECT_free(hold); + ASN1_GENERALIZEDTIME_free(comp_time); + ASN1_ENUMERATED_free(rtmp); + ASN1_TIME_free(revDate); + + return ret; +} + +static int old_entry_print(const ASN1_OBJECT *obj, const ASN1_STRING *str) +{ + char buf[25], *pbuf; + const char *p; + int j; + + j = i2a_ASN1_OBJECT(bio_err, obj); + pbuf = buf; + for (j = 22 - j; j > 0; j--) + *(pbuf++) = ' '; + *(pbuf++) = ':'; + *(pbuf++) = '\0'; + BIO_puts(bio_err, buf); + + if (str->type == V_ASN1_PRINTABLESTRING) + BIO_printf(bio_err, "PRINTABLE:'"); + else if (str->type == V_ASN1_T61STRING) + BIO_printf(bio_err, "T61STRING:'"); + else if (str->type == V_ASN1_IA5STRING) + BIO_printf(bio_err, "IA5STRING:'"); + else if (str->type == V_ASN1_UNIVERSALSTRING) + BIO_printf(bio_err, "UNIVERSALSTRING:'"); + else + BIO_printf(bio_err, "ASN.1 %2d:'", str->type); + + p = (const char *)str->data; + for (j = str->length; j > 0; j--) { + if ((*p >= ' ') && (*p <= '~')) + BIO_printf(bio_err, "%c", *p); + else if (*p & 0x80) + BIO_printf(bio_err, "\\0x%02X", *p); + else if ((unsigned char)*p == 0xf7) + BIO_printf(bio_err, "^?"); + else + BIO_printf(bio_err, "^%c", *p + '@'); + p++; + } + BIO_printf(bio_err, "'\n"); + return 1; +} + +int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, + ASN1_GENERALIZEDTIME **pinvtm, const char *str) +{ + char *tmp; + char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p; + int reason_code = -1; + int ret = 0; + unsigned int i; + ASN1_OBJECT *hold = NULL; + ASN1_GENERALIZEDTIME *comp_time = NULL; + + tmp = OPENSSL_strdup(str); + if (!tmp) { + BIO_printf(bio_err, "memory allocation failure\n"); + goto end; + } + + p = strchr(tmp, ','); + + rtime_str = tmp; + + if (p) { + *p = '\0'; + p++; + reason_str = p; + p = strchr(p, ','); + if (p) { + *p = '\0'; + arg_str = p + 1; + } + } + + if (prevtm) { + *prevtm = ASN1_UTCTIME_new(); + if (*prevtm == NULL) { + BIO_printf(bio_err, "memory allocation failure\n"); + goto end; + } + if (!ASN1_UTCTIME_set_string(*prevtm, rtime_str)) { + BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str); + goto end; + } + } + if (reason_str) { + for (i = 0; i < NUM_REASONS; i++) { + if (strcasecmp(reason_str, crl_reasons[i]) == 0) { + reason_code = i; + break; + } + } + if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS) { + BIO_printf(bio_err, "invalid reason code %s\n", reason_str); + goto end; + } + + if (reason_code == 7) { + reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL; + } else if (reason_code == 8) { /* Hold instruction */ + if (!arg_str) { + BIO_printf(bio_err, "missing hold instruction\n"); + goto end; + } + reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD; + hold = OBJ_txt2obj(arg_str, 0); + + if (!hold) { + BIO_printf(bio_err, "invalid object identifier %s\n", arg_str); + goto end; + } + if (phold) + *phold = hold; + else + ASN1_OBJECT_free(hold); + } else if ((reason_code == 9) || (reason_code == 10)) { + if (!arg_str) { + BIO_printf(bio_err, "missing compromised time\n"); + goto end; + } + comp_time = ASN1_GENERALIZEDTIME_new(); + if (comp_time == NULL) { + BIO_printf(bio_err, "memory allocation failure\n"); + goto end; + } + if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str)) { + BIO_printf(bio_err, "invalid compromised time %s\n", arg_str); + goto end; + } + if (reason_code == 9) + reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE; + else + reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE; + } + } + + if (preason) + *preason = reason_code; + if (pinvtm) { + *pinvtm = comp_time; + comp_time = NULL; + } + + ret = 1; + + end: + + OPENSSL_free(tmp); + ASN1_GENERALIZEDTIME_free(comp_time); + + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/cert.pem b/trunk/3rdparty/openssl-1.1-fit/apps/cert.pem new file mode 100644 index 000000000..de4a77ac6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/cert.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBoDCCAUoCAQAwDQYJKoZIhvcNAQEEBQAwYzELMAkGA1UEBhMCQVUxEzARBgNV +BAgTClF1ZWVuc2xhbmQxGjAYBgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMSMwIQYD +VQQDExpTZXJ2ZXIgdGVzdCBjZXJ0ICg1MTIgYml0KTAeFw05NzA5MDkwMzQxMjZa +Fw05NzEwMDkwMzQxMjZaMF4xCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0 +YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxFzAVBgNVBAMT +DkVyaWMgdGhlIFlvdW5nMFEwCQYFKw4DAgwFAANEAAJBALVEqPODnpI4rShlY8S7 +tB713JNvabvn6Gned7zylwLLiXQAo/PAT6mfdWPTyCX9RlId/Aroh1ou893BA32Q +sggwDQYJKoZIhvcNAQEEBQADQQCU5SSgapJSdRXJoX+CpCvFy+JVh9HpSjCpSNKO +19raHv98hKAUJuP9HyM+SUsffO6mAIgitUaqW8/wDMePhEC3 +-----END CERTIFICATE----- diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/ciphers.c b/trunk/3rdparty/openssl-1.1-fit/apps/ciphers.c new file mode 100644 index 000000000..0bb33a4ac --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/ciphers.c @@ -0,0 +1,266 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_STDNAME, + OPT_CONVERT, + OPT_SSL3, + OPT_TLS1, + OPT_TLS1_1, + OPT_TLS1_2, + OPT_TLS1_3, + OPT_PSK, + OPT_SRP, + OPT_CIPHERSUITES, + OPT_V, OPT_UPPER_V, OPT_S +} OPTION_CHOICE; + +const OPTIONS ciphers_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"v", OPT_V, '-', "Verbose listing of the SSL/TLS ciphers"}, + {"V", OPT_UPPER_V, '-', "Even more verbose"}, + {"s", OPT_S, '-', "Only supported ciphers"}, +#ifndef OPENSSL_NO_SSL3 + {"ssl3", OPT_SSL3, '-', "SSL3 mode"}, +#endif +#ifndef OPENSSL_NO_TLS1 + {"tls1", OPT_TLS1, '-', "TLS1 mode"}, +#endif +#ifndef OPENSSL_NO_TLS1_1 + {"tls1_1", OPT_TLS1_1, '-', "TLS1.1 mode"}, +#endif +#ifndef OPENSSL_NO_TLS1_2 + {"tls1_2", OPT_TLS1_2, '-', "TLS1.2 mode"}, +#endif +#ifndef OPENSSL_NO_TLS1_3 + {"tls1_3", OPT_TLS1_3, '-', "TLS1.3 mode"}, +#endif + {"stdname", OPT_STDNAME, '-', "Show standard cipher names"}, +#ifndef OPENSSL_NO_PSK + {"psk", OPT_PSK, '-', "include ciphersuites requiring PSK"}, +#endif +#ifndef OPENSSL_NO_SRP + {"srp", OPT_SRP, '-', "include ciphersuites requiring SRP"}, +#endif + {"convert", OPT_CONVERT, 's', "Convert standard name into OpenSSL name"}, + {"ciphersuites", OPT_CIPHERSUITES, 's', + "Configure the TLSv1.3 ciphersuites to use"}, + {NULL} +}; + +#ifndef OPENSSL_NO_PSK +static unsigned int dummy_psk(SSL *ssl, const char *hint, char *identity, + unsigned int max_identity_len, + unsigned char *psk, + unsigned int max_psk_len) +{ + return 0; +} +#endif +#ifndef OPENSSL_NO_SRP +static char *dummy_srp(SSL *ssl, void *arg) +{ + return ""; +} +#endif + +int ciphers_main(int argc, char **argv) +{ + SSL_CTX *ctx = NULL; + SSL *ssl = NULL; + STACK_OF(SSL_CIPHER) *sk = NULL; + const SSL_METHOD *meth = TLS_server_method(); + int ret = 1, i, verbose = 0, Verbose = 0, use_supported = 0; + int stdname = 0; +#ifndef OPENSSL_NO_PSK + int psk = 0; +#endif +#ifndef OPENSSL_NO_SRP + int srp = 0; +#endif + const char *p; + char *ciphers = NULL, *prog, *convert = NULL, *ciphersuites = NULL; + char buf[512]; + OPTION_CHOICE o; + int min_version = 0, max_version = 0; + + prog = opt_init(argc, argv, ciphers_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(ciphers_options); + ret = 0; + goto end; + case OPT_V: + verbose = 1; + break; + case OPT_UPPER_V: + verbose = Verbose = 1; + break; + case OPT_S: + use_supported = 1; + break; + case OPT_STDNAME: + stdname = verbose = 1; + break; + case OPT_CONVERT: + convert = opt_arg(); + break; + case OPT_SSL3: + min_version = SSL3_VERSION; + max_version = SSL3_VERSION; + break; + case OPT_TLS1: + min_version = TLS1_VERSION; + max_version = TLS1_VERSION; + break; + case OPT_TLS1_1: + min_version = TLS1_1_VERSION; + max_version = TLS1_1_VERSION; + break; + case OPT_TLS1_2: + min_version = TLS1_2_VERSION; + max_version = TLS1_2_VERSION; + break; + case OPT_TLS1_3: + min_version = TLS1_3_VERSION; + max_version = TLS1_3_VERSION; + break; + case OPT_PSK: +#ifndef OPENSSL_NO_PSK + psk = 1; +#endif + break; + case OPT_SRP: +#ifndef OPENSSL_NO_SRP + srp = 1; +#endif + break; + case OPT_CIPHERSUITES: + ciphersuites = opt_arg(); + break; + } + } + argv = opt_rest(); + argc = opt_num_rest(); + + if (argc == 1) + ciphers = *argv; + else if (argc != 0) + goto opthelp; + + if (convert != NULL) { + BIO_printf(bio_out, "OpenSSL cipher name: %s\n", + OPENSSL_cipher_name(convert)); + goto end; + } + + ctx = SSL_CTX_new(meth); + if (ctx == NULL) + goto err; + if (SSL_CTX_set_min_proto_version(ctx, min_version) == 0) + goto err; + if (SSL_CTX_set_max_proto_version(ctx, max_version) == 0) + goto err; + +#ifndef OPENSSL_NO_PSK + if (psk) + SSL_CTX_set_psk_client_callback(ctx, dummy_psk); +#endif +#ifndef OPENSSL_NO_SRP + if (srp) + SSL_CTX_set_srp_client_pwd_callback(ctx, dummy_srp); +#endif + + if (ciphersuites != NULL && !SSL_CTX_set_ciphersuites(ctx, ciphersuites)) { + BIO_printf(bio_err, "Error setting TLSv1.3 ciphersuites\n"); + goto err; + } + + if (ciphers != NULL) { + if (!SSL_CTX_set_cipher_list(ctx, ciphers)) { + BIO_printf(bio_err, "Error in cipher list\n"); + goto err; + } + } + ssl = SSL_new(ctx); + if (ssl == NULL) + goto err; + + if (use_supported) + sk = SSL_get1_supported_ciphers(ssl); + else + sk = SSL_get_ciphers(ssl); + + if (!verbose) { + for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) { + const SSL_CIPHER *c = sk_SSL_CIPHER_value(sk, i); + p = SSL_CIPHER_get_name(c); + if (p == NULL) + break; + if (i != 0) + BIO_printf(bio_out, ":"); + BIO_printf(bio_out, "%s", p); + } + BIO_printf(bio_out, "\n"); + } else { + + for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) { + const SSL_CIPHER *c; + + c = sk_SSL_CIPHER_value(sk, i); + + if (Verbose) { + unsigned long id = SSL_CIPHER_get_id(c); + int id0 = (int)(id >> 24); + int id1 = (int)((id >> 16) & 0xffL); + int id2 = (int)((id >> 8) & 0xffL); + int id3 = (int)(id & 0xffL); + + if ((id & 0xff000000L) == 0x03000000L) + BIO_printf(bio_out, " 0x%02X,0x%02X - ", id2, id3); /* SSL3 + * cipher */ + else + BIO_printf(bio_out, "0x%02X,0x%02X,0x%02X,0x%02X - ", id0, id1, id2, id3); /* whatever */ + } + if (stdname) { + const char *nm = SSL_CIPHER_standard_name(c); + if (nm == NULL) + nm = "UNKNOWN"; + BIO_printf(bio_out, "%s - ", nm); + } + BIO_puts(bio_out, SSL_CIPHER_description(c, buf, sizeof(buf))); + } + } + + ret = 0; + goto end; + err: + ERR_print_errors(bio_err); + end: + if (use_supported) + sk_SSL_CIPHER_free(sk); + SSL_CTX_free(ctx); + SSL_free(ssl); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/client.pem b/trunk/3rdparty/openssl-1.1-fit/apps/client.pem new file mode 100644 index 000000000..e7a47a73f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/client.pem @@ -0,0 +1,52 @@ +subject= C = UK, O = OpenSSL Group, OU = FOR TESTING PURPOSES ONLY, CN = Test Client Cert +issuer= C = UK, O = OpenSSL Group, OU = FOR TESTING PURPOSES ONLY, CN = OpenSSL Test Intermediate CA +-----BEGIN CERTIFICATE----- +MIID5zCCAs+gAwIBAgIJALnu1NlVpZ6yMA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNV +BAYTAlVLMRYwFAYDVQQKDA1PcGVuU1NMIEdyb3VwMSIwIAYDVQQLDBlGT1IgVEVT +VElORyBQVVJQT1NFUyBPTkxZMSUwIwYDVQQDDBxPcGVuU1NMIFRlc3QgSW50ZXJt +ZWRpYXRlIENBMB4XDTExMTIwODE0MDE0OFoXDTIxMTAxNjE0MDE0OFowZDELMAkG +A1UEBhMCVUsxFjAUBgNVBAoMDU9wZW5TU0wgR3JvdXAxIjAgBgNVBAsMGUZPUiBU +RVNUSU5HIFBVUlBPU0VTIE9OTFkxGTAXBgNVBAMMEFRlc3QgQ2xpZW50IENlcnQw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0ranbHRLcLVqN+0BzcZpY ++yOLqxzDWT1LD9eW1stC4NzXX9/DCtSIVyN7YIHdGLrIPr64IDdXXaMRzgZ2rOKs +lmHCAiFpO/ja99gGCJRxH0xwQatqAULfJVHeUhs7OEGOZc2nWifjqKvGfNTilP7D +nwi69ipQFq9oS19FmhwVHk2wg7KZGHI1qDyG04UrfCZMRitvS9+UVhPpIPjuiBi2 +x3/FZIpL5gXJvvFK6xHY63oq2asyzBATntBgnP4qJFWWcvRx24wF1PnZabxuVoL2 +bPnQ/KvONDrw3IdqkKhYNTul7jEcu3OlcZIMw+7DiaKJLAzKb/bBF5gm/pwW6As9 +AgMBAAGjgY8wgYwwDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCBeAwLAYJYIZI +AYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQW +BBSZHKyLoTh7Mb409Zn/mK1ceSDAjDAfBgNVHSMEGDAWgBQ2w2yI55X+sL3szj49 +hqshgYfa2jANBgkqhkiG9w0BAQUFAAOCAQEAD0mL7PtPYgCEuDyOQSbLpeND5hVS +curxQdGnrJ6Acrhodb7E9ccATokeb0PLx6HBLQUicxhTZIQ9FbO43YkQcOU6C3BB +IlwskqmtN6+VmrQzNolHCDzvxNZs9lYL2VbGPGqVRyjZeHpoAlf9cQr8PgDb4d4b +vUx2KAhHQvV2nkmYvKyXcgnRuHggumF87mkxidriGAEFwH4qfOqetUg64WyxP7P2 +QLipm04SyQa7ONtIApfVXgHcE42Py4/f4arzCzMjKe3VyhGkS7nsT55X/fWgTaRm +CQPkO+H94P958WTvQDt77bQ+D3IvYaVvfil8n6HJMOJfFT0LJuSUbpSXJg== +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAtK2p2x0S3C1ajftAc3GaWPsji6scw1k9Sw/XltbLQuDc11/f +wwrUiFcje2CB3Ri6yD6+uCA3V12jEc4GdqzirJZhwgIhaTv42vfYBgiUcR9McEGr +agFC3yVR3lIbOzhBjmXNp1on46irxnzU4pT+w58IuvYqUBavaEtfRZocFR5NsIOy +mRhyNag8htOFK3wmTEYrb0vflFYT6SD47ogYtsd/xWSKS+YFyb7xSusR2Ot6Ktmr +MswQE57QYJz+KiRVlnL0cduMBdT52Wm8blaC9mz50PyrzjQ68NyHapCoWDU7pe4x +HLtzpXGSDMPuw4miiSwMym/2wReYJv6cFugLPQIDAQABAoIBAAZOyc9MhIwLSU4L +p4RgQvM4UVVe8/Id+3XTZ8NsXExJbWxXfIhiqGjaIfL8u4vsgRjcl+v1s/jo2/iT +KMab4o4D8gXD7UavQVDjtjb/ta79WL3SjRl2Uc9YjjMkyq6WmDNQeo2NKDdafCTB +1uzSJtLNipB8Z53ELPuHJhxX9QMHrMnuha49riQgXZ7buP9iQrHJFhImBjSzbxJx +L+TI6rkyLSf9Wi0Pd3L27Ob3QWNfNRYNSeTE+08eSRChkur5W0RuXAcuAICdQlCl +LBvWO/LmmvbzCqiDcgy/TliSb6CGGwgiNG7LJZmlkYNj8laGwalNlYZs3UrVv6NO +Br2loAECgYEA2kvCvPGj0Dg/6g7WhXDvAkEbcaL1tSeCxBbNH+6HS2UWMWvyTtCn +/bbD519QIdkvayy1QjEf32GV/UjUVmlULMLBcDy0DGjtL3+XpIhLKWDNxN1v1/ai +1oz23ZJCOgnk6K4qtFtlRS1XtynjA+rBetvYvLP9SKeFrnpzCgaA2r0CgYEA0+KX +1ACXDTNH5ySX3kMjSS9xdINf+OOw4CvPHFwbtc9aqk2HePlEsBTz5I/W3rKwXva3 +NqZ/bRqVVeZB/hHKFywgdUQk2Uc5z/S7Lw70/w1HubNTXGU06Ngb6zOFAo/o/TwZ +zTP1BMIKSOB6PAZPS3l+aLO4FRIRotfFhgRHOoECgYEAmiZbqt8cJaJDB/5YYDzC +mp3tSk6gIb936Q6M5VqkMYp9pIKsxhk0N8aDCnTU+kIK6SzWBpr3/d9Ecmqmfyq7 +5SvWO3KyVf0WWK9KH0abhOm2BKm2HBQvI0DB5u8sUx2/hsvOnjPYDISbZ11t0MtK +u35Zy89yMYcSsIYJjG/ROCUCgYEAgI2P9G5PNxEP5OtMwOsW84Y3Xat/hPAQFlI+ +HES+AzbFGWJkeT8zL2nm95tVkFP1sggZ7Kxjz3w7cpx7GX0NkbWSE9O+T51pNASV +tN1sQ3p5M+/a+cnlqgfEGJVvc7iAcXQPa3LEi5h2yPR49QYXAgG6cifn3dDSpmwn +SUI7PQECgYEApGCIIpSRPLAEHTGmP87RBL1smurhwmy2s/pghkvUkWehtxg0sGHh +kuaqDWcskogv+QC0sVdytiLSz8G0DwcEcsHK1Fkyb8A+ayiw6jWJDo2m9+IF4Fww +1Te6jFPYDESnbhq7+TLGgHGhtwcu5cnb4vSuYXGXKupZGzoLOBbv1Zw= +-----END RSA PRIVATE KEY----- diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/cms.c b/trunk/3rdparty/openssl-1.1-fit/apps/cms.c new file mode 100644 index 000000000..e9d760c99 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/cms.c @@ -0,0 +1,1289 @@ +/* + * Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* CMS utility function */ + +#include +#include +#include "apps.h" +#include "progs.h" + +#ifndef OPENSSL_NO_CMS + +# include +# include +# include +# include +# include +# include + +static int save_certs(char *signerfile, STACK_OF(X509) *signers); +static int cms_cb(int ok, X509_STORE_CTX *ctx); +static void receipt_request_print(CMS_ContentInfo *cms); +static CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING) + *rr_to, int rr_allorfirst, STACK_OF(OPENSSL_STRING) + *rr_from); +static int cms_set_pkey_param(EVP_PKEY_CTX *pctx, + STACK_OF(OPENSSL_STRING) *param); + +# define SMIME_OP 0x10 +# define SMIME_IP 0x20 +# define SMIME_SIGNERS 0x40 +# define SMIME_ENCRYPT (1 | SMIME_OP) +# define SMIME_DECRYPT (2 | SMIME_IP) +# define SMIME_SIGN (3 | SMIME_OP | SMIME_SIGNERS) +# define SMIME_VERIFY (4 | SMIME_IP) +# define SMIME_CMSOUT (5 | SMIME_IP | SMIME_OP) +# define SMIME_RESIGN (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS) +# define SMIME_DATAOUT (7 | SMIME_IP) +# define SMIME_DATA_CREATE (8 | SMIME_OP) +# define SMIME_DIGEST_VERIFY (9 | SMIME_IP) +# define SMIME_DIGEST_CREATE (10 | SMIME_OP) +# define SMIME_UNCOMPRESS (11 | SMIME_IP) +# define SMIME_COMPRESS (12 | SMIME_OP) +# define SMIME_ENCRYPTED_DECRYPT (13 | SMIME_IP) +# define SMIME_ENCRYPTED_ENCRYPT (14 | SMIME_OP) +# define SMIME_SIGN_RECEIPT (15 | SMIME_IP | SMIME_OP) +# define SMIME_VERIFY_RECEIPT (16 | SMIME_IP) + +static int verify_err = 0; + +typedef struct cms_key_param_st cms_key_param; + +struct cms_key_param_st { + int idx; + STACK_OF(OPENSSL_STRING) *param; + cms_key_param *next; +}; + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_ENCRYPT, + OPT_DECRYPT, OPT_SIGN, OPT_SIGN_RECEIPT, OPT_RESIGN, + OPT_VERIFY, OPT_VERIFY_RETCODE, OPT_VERIFY_RECEIPT, + OPT_CMSOUT, OPT_DATA_OUT, OPT_DATA_CREATE, OPT_DIGEST_VERIFY, + OPT_DIGEST_CREATE, OPT_COMPRESS, OPT_UNCOMPRESS, + OPT_ED_DECRYPT, OPT_ED_ENCRYPT, OPT_DEBUG_DECRYPT, OPT_TEXT, + OPT_ASCIICRLF, OPT_NOINTERN, OPT_NOVERIFY, OPT_NOCERTS, + OPT_NOATTR, OPT_NODETACH, OPT_NOSMIMECAP, OPT_BINARY, OPT_KEYID, + OPT_NOSIGS, OPT_NO_CONTENT_VERIFY, OPT_NO_ATTR_VERIFY, OPT_INDEF, + OPT_NOINDEF, OPT_CRLFEOL, OPT_NOOUT, OPT_RR_PRINT, + OPT_RR_ALL, OPT_RR_FIRST, OPT_RCTFORM, OPT_CERTFILE, OPT_CAFILE, + OPT_CAPATH, OPT_NOCAPATH, OPT_NOCAFILE,OPT_CONTENT, OPT_PRINT, + OPT_SECRETKEY, OPT_SECRETKEYID, OPT_PWRI_PASSWORD, OPT_ECONTENT_TYPE, + OPT_PASSIN, OPT_TO, OPT_FROM, OPT_SUBJECT, OPT_SIGNER, OPT_RECIP, + OPT_CERTSOUT, OPT_MD, OPT_INKEY, OPT_KEYFORM, OPT_KEYOPT, OPT_RR_FROM, + OPT_RR_TO, OPT_AES128_WRAP, OPT_AES192_WRAP, OPT_AES256_WRAP, + OPT_3DES_WRAP, OPT_ENGINE, + OPT_R_ENUM, + OPT_V_ENUM, + OPT_CIPHER +} OPTION_CHOICE; + +const OPTIONS cms_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] cert.pem...\n"}, + {OPT_HELP_STR, 1, '-', + " cert.pem... recipient certs for encryption\n"}, + {OPT_HELP_STR, 1, '-', "Valid options are:\n"}, + {"help", OPT_HELP, '-', "Display this summary"}, + {"inform", OPT_INFORM, 'c', "Input format SMIME (default), PEM or DER"}, + {"outform", OPT_OUTFORM, 'c', + "Output format SMIME (default), PEM or DER"}, + {"in", OPT_IN, '<', "Input file"}, + {"out", OPT_OUT, '>', "Output file"}, + {"encrypt", OPT_ENCRYPT, '-', "Encrypt message"}, + {"decrypt", OPT_DECRYPT, '-', "Decrypt encrypted message"}, + {"sign", OPT_SIGN, '-', "Sign message"}, + {"sign_receipt", OPT_SIGN_RECEIPT, '-', "Generate a signed receipt for the message"}, + {"resign", OPT_RESIGN, '-', "Resign a signed message"}, + {"verify", OPT_VERIFY, '-', "Verify signed message"}, + {"verify_retcode", OPT_VERIFY_RETCODE, '-'}, + {"verify_receipt", OPT_VERIFY_RECEIPT, '<'}, + {"cmsout", OPT_CMSOUT, '-', "Output CMS structure"}, + {"data_out", OPT_DATA_OUT, '-'}, + {"data_create", OPT_DATA_CREATE, '-'}, + {"digest_verify", OPT_DIGEST_VERIFY, '-'}, + {"digest_create", OPT_DIGEST_CREATE, '-'}, + {"compress", OPT_COMPRESS, '-'}, + {"uncompress", OPT_UNCOMPRESS, '-'}, + {"EncryptedData_decrypt", OPT_ED_DECRYPT, '-'}, + {"EncryptedData_encrypt", OPT_ED_ENCRYPT, '-'}, + {"debug_decrypt", OPT_DEBUG_DECRYPT, '-'}, + {"text", OPT_TEXT, '-', "Include or delete text MIME headers"}, + {"asciicrlf", OPT_ASCIICRLF, '-'}, + {"nointern", OPT_NOINTERN, '-', + "Don't search certificates in message for signer"}, + {"noverify", OPT_NOVERIFY, '-', "Don't verify signers certificate"}, + {"nocerts", OPT_NOCERTS, '-', + "Don't include signers certificate when signing"}, + {"noattr", OPT_NOATTR, '-', "Don't include any signed attributes"}, + {"nodetach", OPT_NODETACH, '-', "Use opaque signing"}, + {"nosmimecap", OPT_NOSMIMECAP, '-', "Omit the SMIMECapabilities attribute"}, + {"binary", OPT_BINARY, '-', "Don't translate message to text"}, + {"keyid", OPT_KEYID, '-', "Use subject key identifier"}, + {"nosigs", OPT_NOSIGS, '-', "Don't verify message signature"}, + {"no_content_verify", OPT_NO_CONTENT_VERIFY, '-'}, + {"no_attr_verify", OPT_NO_ATTR_VERIFY, '-'}, + {"stream", OPT_INDEF, '-', "Enable CMS streaming"}, + {"indef", OPT_INDEF, '-', "Same as -stream"}, + {"noindef", OPT_NOINDEF, '-', "Disable CMS streaming"}, + {"crlfeol", OPT_CRLFEOL, '-', "Use CRLF as EOL termination instead of CR only" }, + {"noout", OPT_NOOUT, '-', "For the -cmsout operation do not output the parsed CMS structure"}, + {"receipt_request_print", OPT_RR_PRINT, '-', "Print CMS Receipt Request" }, + {"receipt_request_all", OPT_RR_ALL, '-'}, + {"receipt_request_first", OPT_RR_FIRST, '-'}, + {"rctform", OPT_RCTFORM, 'F', "Receipt file format"}, + {"certfile", OPT_CERTFILE, '<', "Other certificates file"}, + {"CAfile", OPT_CAFILE, '<', "Trusted certificates file"}, + {"CApath", OPT_CAPATH, '/', "trusted certificates directory"}, + {"no-CAfile", OPT_NOCAFILE, '-', + "Do not load the default certificates file"}, + {"no-CApath", OPT_NOCAPATH, '-', + "Do not load certificates from the default certificates directory"}, + {"content", OPT_CONTENT, '<', + "Supply or override content for detached signature"}, + {"print", OPT_PRINT, '-', + "For the -cmsout operation print out all fields of the CMS structure"}, + {"secretkey", OPT_SECRETKEY, 's'}, + {"secretkeyid", OPT_SECRETKEYID, 's'}, + {"pwri_password", OPT_PWRI_PASSWORD, 's'}, + {"econtent_type", OPT_ECONTENT_TYPE, 's'}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"to", OPT_TO, 's', "To address"}, + {"from", OPT_FROM, 's', "From address"}, + {"subject", OPT_SUBJECT, 's', "Subject"}, + {"signer", OPT_SIGNER, 's', "Signer certificate file"}, + {"recip", OPT_RECIP, '<', "Recipient cert file for decryption"}, + {"certsout", OPT_CERTSOUT, '>', "Certificate output file"}, + {"md", OPT_MD, 's', "Digest algorithm to use when signing or resigning"}, + {"inkey", OPT_INKEY, 's', + "Input private key (if not signer or recipient)"}, + {"keyform", OPT_KEYFORM, 'f', "Input private key format (PEM or ENGINE)"}, + {"keyopt", OPT_KEYOPT, 's', "Set public key parameters as n:v pairs"}, + {"receipt_request_from", OPT_RR_FROM, 's'}, + {"receipt_request_to", OPT_RR_TO, 's'}, + {"", OPT_CIPHER, '-', "Any supported cipher"}, + OPT_R_OPTIONS, + OPT_V_OPTIONS, + {"aes128-wrap", OPT_AES128_WRAP, '-', "Use AES128 to wrap key"}, + {"aes192-wrap", OPT_AES192_WRAP, '-', "Use AES192 to wrap key"}, + {"aes256-wrap", OPT_AES256_WRAP, '-', "Use AES256 to wrap key"}, +# ifndef OPENSSL_NO_DES + {"des3-wrap", OPT_3DES_WRAP, '-', "Use 3DES-EDE to wrap key"}, +# endif +# ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"}, +# endif + {NULL} +}; + +int cms_main(int argc, char **argv) +{ + ASN1_OBJECT *econtent_type = NULL; + BIO *in = NULL, *out = NULL, *indata = NULL, *rctin = NULL; + CMS_ContentInfo *cms = NULL, *rcms = NULL; + CMS_ReceiptRequest *rr = NULL; + ENGINE *e = NULL; + EVP_PKEY *key = NULL; + const EVP_CIPHER *cipher = NULL, *wrap_cipher = NULL; + const EVP_MD *sign_md = NULL; + STACK_OF(OPENSSL_STRING) *rr_to = NULL, *rr_from = NULL; + STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL; + STACK_OF(X509) *encerts = NULL, *other = NULL; + X509 *cert = NULL, *recip = NULL, *signer = NULL; + X509_STORE *store = NULL; + X509_VERIFY_PARAM *vpm = NULL; + char *certfile = NULL, *keyfile = NULL, *contfile = NULL; + const char *CAfile = NULL, *CApath = NULL; + char *certsoutfile = NULL; + int noCAfile = 0, noCApath = 0; + char *infile = NULL, *outfile = NULL, *rctfile = NULL; + char *passinarg = NULL, *passin = NULL, *signerfile = NULL, *recipfile = NULL; + char *to = NULL, *from = NULL, *subject = NULL, *prog; + cms_key_param *key_first = NULL, *key_param = NULL; + int flags = CMS_DETACHED, noout = 0, print = 0, keyidx = -1, vpmtouched = 0; + int informat = FORMAT_SMIME, outformat = FORMAT_SMIME; + int operation = 0, ret = 1, rr_print = 0, rr_allorfirst = -1; + int verify_retcode = 0, rctformat = FORMAT_SMIME, keyform = FORMAT_PEM; + size_t secret_keylen = 0, secret_keyidlen = 0; + unsigned char *pwri_pass = NULL, *pwri_tmp = NULL; + unsigned char *secret_key = NULL, *secret_keyid = NULL; + long ltmp; + const char *mime_eol = "\n"; + OPTION_CHOICE o; + + if ((vpm = X509_VERIFY_PARAM_new()) == NULL) + return 1; + + prog = opt_init(argc, argv, cms_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(cms_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_PDS, &informat)) + goto opthelp; + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PDS, &outformat)) + goto opthelp; + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_ENCRYPT: + operation = SMIME_ENCRYPT; + break; + case OPT_DECRYPT: + operation = SMIME_DECRYPT; + break; + case OPT_SIGN: + operation = SMIME_SIGN; + break; + case OPT_SIGN_RECEIPT: + operation = SMIME_SIGN_RECEIPT; + break; + case OPT_RESIGN: + operation = SMIME_RESIGN; + break; + case OPT_VERIFY: + operation = SMIME_VERIFY; + break; + case OPT_VERIFY_RETCODE: + verify_retcode = 1; + break; + case OPT_VERIFY_RECEIPT: + operation = SMIME_VERIFY_RECEIPT; + rctfile = opt_arg(); + break; + case OPT_CMSOUT: + operation = SMIME_CMSOUT; + break; + case OPT_DATA_OUT: + operation = SMIME_DATAOUT; + break; + case OPT_DATA_CREATE: + operation = SMIME_DATA_CREATE; + break; + case OPT_DIGEST_VERIFY: + operation = SMIME_DIGEST_VERIFY; + break; + case OPT_DIGEST_CREATE: + operation = SMIME_DIGEST_CREATE; + break; + case OPT_COMPRESS: + operation = SMIME_COMPRESS; + break; + case OPT_UNCOMPRESS: + operation = SMIME_UNCOMPRESS; + break; + case OPT_ED_DECRYPT: + operation = SMIME_ENCRYPTED_DECRYPT; + break; + case OPT_ED_ENCRYPT: + operation = SMIME_ENCRYPTED_ENCRYPT; + break; + case OPT_DEBUG_DECRYPT: + flags |= CMS_DEBUG_DECRYPT; + break; + case OPT_TEXT: + flags |= CMS_TEXT; + break; + case OPT_ASCIICRLF: + flags |= CMS_ASCIICRLF; + break; + case OPT_NOINTERN: + flags |= CMS_NOINTERN; + break; + case OPT_NOVERIFY: + flags |= CMS_NO_SIGNER_CERT_VERIFY; + break; + case OPT_NOCERTS: + flags |= CMS_NOCERTS; + break; + case OPT_NOATTR: + flags |= CMS_NOATTR; + break; + case OPT_NODETACH: + flags &= ~CMS_DETACHED; + break; + case OPT_NOSMIMECAP: + flags |= CMS_NOSMIMECAP; + break; + case OPT_BINARY: + flags |= CMS_BINARY; + break; + case OPT_KEYID: + flags |= CMS_USE_KEYID; + break; + case OPT_NOSIGS: + flags |= CMS_NOSIGS; + break; + case OPT_NO_CONTENT_VERIFY: + flags |= CMS_NO_CONTENT_VERIFY; + break; + case OPT_NO_ATTR_VERIFY: + flags |= CMS_NO_ATTR_VERIFY; + break; + case OPT_INDEF: + flags |= CMS_STREAM; + break; + case OPT_NOINDEF: + flags &= ~CMS_STREAM; + break; + case OPT_CRLFEOL: + mime_eol = "\r\n"; + flags |= CMS_CRLFEOL; + break; + case OPT_NOOUT: + noout = 1; + break; + case OPT_RR_PRINT: + rr_print = 1; + break; + case OPT_RR_ALL: + rr_allorfirst = 0; + break; + case OPT_RR_FIRST: + rr_allorfirst = 1; + break; + case OPT_RCTFORM: + if (rctformat == FORMAT_SMIME) + rcms = SMIME_read_CMS(rctin, NULL); + else if (rctformat == FORMAT_PEM) + rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL); + else if (rctformat == FORMAT_ASN1) + if (!opt_format(opt_arg(), + OPT_FMT_PEMDER | OPT_FMT_SMIME, &rctformat)) + goto opthelp; + break; + case OPT_CERTFILE: + certfile = opt_arg(); + break; + case OPT_CAFILE: + CAfile = opt_arg(); + break; + case OPT_CAPATH: + CApath = opt_arg(); + break; + case OPT_NOCAFILE: + noCAfile = 1; + break; + case OPT_NOCAPATH: + noCApath = 1; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_CONTENT: + contfile = opt_arg(); + break; + case OPT_RR_FROM: + if (rr_from == NULL + && (rr_from = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; + sk_OPENSSL_STRING_push(rr_from, opt_arg()); + break; + case OPT_RR_TO: + if (rr_to == NULL + && (rr_to = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; + sk_OPENSSL_STRING_push(rr_to, opt_arg()); + break; + case OPT_PRINT: + noout = print = 1; + break; + case OPT_SECRETKEY: + if (secret_key != NULL) { + BIO_printf(bio_err, "Invalid key (supplied twice) %s\n", + opt_arg()); + goto opthelp; + } + secret_key = OPENSSL_hexstr2buf(opt_arg(), <mp); + if (secret_key == NULL) { + BIO_printf(bio_err, "Invalid key %s\n", opt_arg()); + goto end; + } + secret_keylen = (size_t)ltmp; + break; + case OPT_SECRETKEYID: + if (secret_keyid != NULL) { + BIO_printf(bio_err, "Invalid id (supplied twice) %s\n", + opt_arg()); + goto opthelp; + } + secret_keyid = OPENSSL_hexstr2buf(opt_arg(), <mp); + if (secret_keyid == NULL) { + BIO_printf(bio_err, "Invalid id %s\n", opt_arg()); + goto opthelp; + } + secret_keyidlen = (size_t)ltmp; + break; + case OPT_PWRI_PASSWORD: + pwri_pass = (unsigned char *)opt_arg(); + break; + case OPT_ECONTENT_TYPE: + if (econtent_type != NULL) { + BIO_printf(bio_err, "Invalid OID (supplied twice) %s\n", + opt_arg()); + goto opthelp; + } + econtent_type = OBJ_txt2obj(opt_arg(), 0); + if (econtent_type == NULL) { + BIO_printf(bio_err, "Invalid OID %s\n", opt_arg()); + goto opthelp; + } + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_TO: + to = opt_arg(); + break; + case OPT_FROM: + from = opt_arg(); + break; + case OPT_SUBJECT: + subject = opt_arg(); + break; + case OPT_CERTSOUT: + certsoutfile = opt_arg(); + break; + case OPT_MD: + if (!opt_md(opt_arg(), &sign_md)) + goto end; + break; + case OPT_SIGNER: + /* If previous -signer argument add signer to list */ + if (signerfile != NULL) { + if (sksigners == NULL + && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; + sk_OPENSSL_STRING_push(sksigners, signerfile); + if (keyfile == NULL) + keyfile = signerfile; + if (skkeys == NULL + && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; + sk_OPENSSL_STRING_push(skkeys, keyfile); + keyfile = NULL; + } + signerfile = opt_arg(); + break; + case OPT_INKEY: + /* If previous -inkey argument add signer to list */ + if (keyfile != NULL) { + if (signerfile == NULL) { + BIO_puts(bio_err, "Illegal -inkey without -signer\n"); + goto end; + } + if (sksigners == NULL + && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; + sk_OPENSSL_STRING_push(sksigners, signerfile); + signerfile = NULL; + if (skkeys == NULL + && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; + sk_OPENSSL_STRING_push(skkeys, keyfile); + } + keyfile = opt_arg(); + break; + case OPT_KEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform)) + goto opthelp; + break; + case OPT_RECIP: + if (operation == SMIME_ENCRYPT) { + if (encerts == NULL && (encerts = sk_X509_new_null()) == NULL) + goto end; + cert = load_cert(opt_arg(), FORMAT_PEM, + "recipient certificate file"); + if (cert == NULL) + goto end; + sk_X509_push(encerts, cert); + cert = NULL; + } else { + recipfile = opt_arg(); + } + break; + case OPT_CIPHER: + if (!opt_cipher(opt_unknown(), &cipher)) + goto end; + break; + case OPT_KEYOPT: + keyidx = -1; + if (operation == SMIME_ENCRYPT) { + if (encerts != NULL) + keyidx += sk_X509_num(encerts); + } else { + if (keyfile != NULL || signerfile != NULL) + keyidx++; + if (skkeys != NULL) + keyidx += sk_OPENSSL_STRING_num(skkeys); + } + if (keyidx < 0) { + BIO_printf(bio_err, "No key specified\n"); + goto opthelp; + } + if (key_param == NULL || key_param->idx != keyidx) { + cms_key_param *nparam; + nparam = app_malloc(sizeof(*nparam), "key param buffer"); + nparam->idx = keyidx; + if ((nparam->param = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; + nparam->next = NULL; + if (key_first == NULL) + key_first = nparam; + else + key_param->next = nparam; + key_param = nparam; + } + sk_OPENSSL_STRING_push(key_param->param, opt_arg()); + break; + case OPT_V_CASES: + if (!opt_verify(o, vpm)) + goto end; + vpmtouched++; + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_3DES_WRAP: +# ifndef OPENSSL_NO_DES + wrap_cipher = EVP_des_ede3_wrap(); +# endif + break; + case OPT_AES128_WRAP: + wrap_cipher = EVP_aes_128_wrap(); + break; + case OPT_AES192_WRAP: + wrap_cipher = EVP_aes_192_wrap(); + break; + case OPT_AES256_WRAP: + wrap_cipher = EVP_aes_256_wrap(); + break; + } + } + argc = opt_num_rest(); + argv = opt_rest(); + + if ((rr_allorfirst != -1 || rr_from != NULL) && rr_to == NULL) { + BIO_puts(bio_err, "No Signed Receipts Recipients\n"); + goto opthelp; + } + + if (!(operation & SMIME_SIGNERS) && (rr_to != NULL || rr_from != NULL)) { + BIO_puts(bio_err, "Signed receipts only allowed with -sign\n"); + goto opthelp; + } + if (!(operation & SMIME_SIGNERS) && (skkeys != NULL || sksigners != NULL)) { + BIO_puts(bio_err, "Multiple signers or keys not allowed\n"); + goto opthelp; + } + + if (operation & SMIME_SIGNERS) { + if (keyfile != NULL && signerfile == NULL) { + BIO_puts(bio_err, "Illegal -inkey without -signer\n"); + goto opthelp; + } + /* Check to see if any final signer needs to be appended */ + if (signerfile != NULL) { + if (sksigners == NULL + && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; + sk_OPENSSL_STRING_push(sksigners, signerfile); + if (skkeys == NULL && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; + if (keyfile == NULL) + keyfile = signerfile; + sk_OPENSSL_STRING_push(skkeys, keyfile); + } + if (sksigners == NULL) { + BIO_printf(bio_err, "No signer certificate specified\n"); + goto opthelp; + } + signerfile = NULL; + keyfile = NULL; + } else if (operation == SMIME_DECRYPT) { + if (recipfile == NULL && keyfile == NULL + && secret_key == NULL && pwri_pass == NULL) { + BIO_printf(bio_err, + "No recipient certificate or key specified\n"); + goto opthelp; + } + } else if (operation == SMIME_ENCRYPT) { + if (*argv == NULL && secret_key == NULL + && pwri_pass == NULL && encerts == NULL) { + BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n"); + goto opthelp; + } + } else if (!operation) { + goto opthelp; + } + + if (!app_passwd(passinarg, NULL, &passin, NULL)) { + BIO_printf(bio_err, "Error getting password\n"); + goto end; + } + + ret = 2; + + if (!(operation & SMIME_SIGNERS)) + flags &= ~CMS_DETACHED; + + if (!(operation & SMIME_OP)) + if (flags & CMS_BINARY) + outformat = FORMAT_BINARY; + + if (!(operation & SMIME_IP)) + if (flags & CMS_BINARY) + informat = FORMAT_BINARY; + + if (operation == SMIME_ENCRYPT) { + if (!cipher) { +# ifndef OPENSSL_NO_DES + cipher = EVP_des_ede3_cbc(); +# else + BIO_printf(bio_err, "No cipher selected\n"); + goto end; +# endif + } + + if (secret_key && !secret_keyid) { + BIO_printf(bio_err, "No secret key id\n"); + goto end; + } + + if (*argv && encerts == NULL) + if ((encerts = sk_X509_new_null()) == NULL) + goto end; + while (*argv) { + if ((cert = load_cert(*argv, FORMAT_PEM, + "recipient certificate file")) == NULL) + goto end; + sk_X509_push(encerts, cert); + cert = NULL; + argv++; + } + } + + if (certfile != NULL) { + if (!load_certs(certfile, &other, FORMAT_PEM, NULL, + "certificate file")) { + ERR_print_errors(bio_err); + goto end; + } + } + + if (recipfile != NULL && (operation == SMIME_DECRYPT)) { + if ((recip = load_cert(recipfile, FORMAT_PEM, + "recipient certificate file")) == NULL) { + ERR_print_errors(bio_err); + goto end; + } + } + + if (operation == SMIME_SIGN_RECEIPT) { + if ((signer = load_cert(signerfile, FORMAT_PEM, + "receipt signer certificate file")) == NULL) { + ERR_print_errors(bio_err); + goto end; + } + } + + if (operation == SMIME_DECRYPT) { + if (keyfile == NULL) + keyfile = recipfile; + } else if ((operation == SMIME_SIGN) || (operation == SMIME_SIGN_RECEIPT)) { + if (keyfile == NULL) + keyfile = signerfile; + } else { + keyfile = NULL; + } + + if (keyfile != NULL) { + key = load_key(keyfile, keyform, 0, passin, e, "signing key file"); + if (key == NULL) + goto end; + } + + in = bio_open_default(infile, 'r', informat); + if (in == NULL) + goto end; + + if (operation & SMIME_IP) { + if (informat == FORMAT_SMIME) { + cms = SMIME_read_CMS(in, &indata); + } else if (informat == FORMAT_PEM) { + cms = PEM_read_bio_CMS(in, NULL, NULL, NULL); + } else if (informat == FORMAT_ASN1) { + cms = d2i_CMS_bio(in, NULL); + } else { + BIO_printf(bio_err, "Bad input format for CMS file\n"); + goto end; + } + + if (cms == NULL) { + BIO_printf(bio_err, "Error reading S/MIME message\n"); + goto end; + } + if (contfile != NULL) { + BIO_free(indata); + if ((indata = BIO_new_file(contfile, "rb")) == NULL) { + BIO_printf(bio_err, "Can't read content file %s\n", contfile); + goto end; + } + } + if (certsoutfile != NULL) { + STACK_OF(X509) *allcerts; + allcerts = CMS_get1_certs(cms); + if (!save_certs(certsoutfile, allcerts)) { + BIO_printf(bio_err, + "Error writing certs to %s\n", certsoutfile); + ret = 5; + goto end; + } + sk_X509_pop_free(allcerts, X509_free); + } + } + + if (rctfile != NULL) { + char *rctmode = (rctformat == FORMAT_ASN1) ? "rb" : "r"; + if ((rctin = BIO_new_file(rctfile, rctmode)) == NULL) { + BIO_printf(bio_err, "Can't open receipt file %s\n", rctfile); + goto end; + } + + if (rctformat == FORMAT_SMIME) { + rcms = SMIME_read_CMS(rctin, NULL); + } else if (rctformat == FORMAT_PEM) { + rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL); + } else if (rctformat == FORMAT_ASN1) { + rcms = d2i_CMS_bio(rctin, NULL); + } else { + BIO_printf(bio_err, "Bad input format for receipt\n"); + goto end; + } + + if (rcms == NULL) { + BIO_printf(bio_err, "Error reading receipt\n"); + goto end; + } + } + + out = bio_open_default(outfile, 'w', outformat); + if (out == NULL) + goto end; + + if ((operation == SMIME_VERIFY) || (operation == SMIME_VERIFY_RECEIPT)) { + if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL) + goto end; + X509_STORE_set_verify_cb(store, cms_cb); + if (vpmtouched) + X509_STORE_set1_param(store, vpm); + } + + ret = 3; + + if (operation == SMIME_DATA_CREATE) { + cms = CMS_data_create(in, flags); + } else if (operation == SMIME_DIGEST_CREATE) { + cms = CMS_digest_create(in, sign_md, flags); + } else if (operation == SMIME_COMPRESS) { + cms = CMS_compress(in, -1, flags); + } else if (operation == SMIME_ENCRYPT) { + int i; + flags |= CMS_PARTIAL; + cms = CMS_encrypt(NULL, in, cipher, flags); + if (cms == NULL) + goto end; + for (i = 0; i < sk_X509_num(encerts); i++) { + CMS_RecipientInfo *ri; + cms_key_param *kparam; + int tflags = flags; + X509 *x = sk_X509_value(encerts, i); + for (kparam = key_first; kparam; kparam = kparam->next) { + if (kparam->idx == i) { + tflags |= CMS_KEY_PARAM; + break; + } + } + ri = CMS_add1_recipient_cert(cms, x, tflags); + if (ri == NULL) + goto end; + if (kparam != NULL) { + EVP_PKEY_CTX *pctx; + pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); + if (!cms_set_pkey_param(pctx, kparam->param)) + goto end; + } + if (CMS_RecipientInfo_type(ri) == CMS_RECIPINFO_AGREE + && wrap_cipher) { + EVP_CIPHER_CTX *wctx; + wctx = CMS_RecipientInfo_kari_get0_ctx(ri); + EVP_EncryptInit_ex(wctx, wrap_cipher, NULL, NULL, NULL); + } + } + + if (secret_key != NULL) { + if (!CMS_add0_recipient_key(cms, NID_undef, + secret_key, secret_keylen, + secret_keyid, secret_keyidlen, + NULL, NULL, NULL)) + goto end; + /* NULL these because call absorbs them */ + secret_key = NULL; + secret_keyid = NULL; + } + if (pwri_pass != NULL) { + pwri_tmp = (unsigned char *)OPENSSL_strdup((char *)pwri_pass); + if (pwri_tmp == NULL) + goto end; + if (CMS_add0_recipient_password(cms, + -1, NID_undef, NID_undef, + pwri_tmp, -1, NULL) == NULL) + goto end; + pwri_tmp = NULL; + } + if (!(flags & CMS_STREAM)) { + if (!CMS_final(cms, in, NULL, flags)) + goto end; + } + } else if (operation == SMIME_ENCRYPTED_ENCRYPT) { + cms = CMS_EncryptedData_encrypt(in, cipher, + secret_key, secret_keylen, flags); + + } else if (operation == SMIME_SIGN_RECEIPT) { + CMS_ContentInfo *srcms = NULL; + STACK_OF(CMS_SignerInfo) *sis; + CMS_SignerInfo *si; + sis = CMS_get0_SignerInfos(cms); + if (sis == NULL) + goto end; + si = sk_CMS_SignerInfo_value(sis, 0); + srcms = CMS_sign_receipt(si, signer, key, other, flags); + if (srcms == NULL) + goto end; + CMS_ContentInfo_free(cms); + cms = srcms; + } else if (operation & SMIME_SIGNERS) { + int i; + /* + * If detached data content we enable streaming if S/MIME output + * format. + */ + if (operation == SMIME_SIGN) { + + if (flags & CMS_DETACHED) { + if (outformat == FORMAT_SMIME) + flags |= CMS_STREAM; + } + flags |= CMS_PARTIAL; + cms = CMS_sign(NULL, NULL, other, in, flags); + if (cms == NULL) + goto end; + if (econtent_type != NULL) + CMS_set1_eContentType(cms, econtent_type); + + if (rr_to != NULL) { + rr = make_receipt_request(rr_to, rr_allorfirst, rr_from); + if (rr == NULL) { + BIO_puts(bio_err, + "Signed Receipt Request Creation Error\n"); + goto end; + } + } + } else { + flags |= CMS_REUSE_DIGEST; + } + for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) { + CMS_SignerInfo *si; + cms_key_param *kparam; + int tflags = flags; + signerfile = sk_OPENSSL_STRING_value(sksigners, i); + keyfile = sk_OPENSSL_STRING_value(skkeys, i); + + signer = load_cert(signerfile, FORMAT_PEM, "signer certificate"); + if (signer == NULL) { + ret = 2; + goto end; + } + key = load_key(keyfile, keyform, 0, passin, e, "signing key file"); + if (key == NULL) { + ret = 2; + goto end; + } + for (kparam = key_first; kparam; kparam = kparam->next) { + if (kparam->idx == i) { + tflags |= CMS_KEY_PARAM; + break; + } + } + si = CMS_add1_signer(cms, signer, key, sign_md, tflags); + if (si == NULL) + goto end; + if (kparam != NULL) { + EVP_PKEY_CTX *pctx; + pctx = CMS_SignerInfo_get0_pkey_ctx(si); + if (!cms_set_pkey_param(pctx, kparam->param)) + goto end; + } + if (rr != NULL && !CMS_add1_ReceiptRequest(si, rr)) + goto end; + X509_free(signer); + signer = NULL; + EVP_PKEY_free(key); + key = NULL; + } + /* If not streaming or resigning finalize structure */ + if ((operation == SMIME_SIGN) && !(flags & CMS_STREAM)) { + if (!CMS_final(cms, in, NULL, flags)) + goto end; + } + } + + if (cms == NULL) { + BIO_printf(bio_err, "Error creating CMS structure\n"); + goto end; + } + + ret = 4; + if (operation == SMIME_DECRYPT) { + if (flags & CMS_DEBUG_DECRYPT) + CMS_decrypt(cms, NULL, NULL, NULL, NULL, flags); + + if (secret_key != NULL) { + if (!CMS_decrypt_set1_key(cms, + secret_key, secret_keylen, + secret_keyid, secret_keyidlen)) { + BIO_puts(bio_err, "Error decrypting CMS using secret key\n"); + goto end; + } + } + + if (key != NULL) { + if (!CMS_decrypt_set1_pkey(cms, key, recip)) { + BIO_puts(bio_err, "Error decrypting CMS using private key\n"); + goto end; + } + } + + if (pwri_pass != NULL) { + if (!CMS_decrypt_set1_password(cms, pwri_pass, -1)) { + BIO_puts(bio_err, "Error decrypting CMS using password\n"); + goto end; + } + } + + if (!CMS_decrypt(cms, NULL, NULL, indata, out, flags)) { + BIO_printf(bio_err, "Error decrypting CMS structure\n"); + goto end; + } + } else if (operation == SMIME_DATAOUT) { + if (!CMS_data(cms, out, flags)) + goto end; + } else if (operation == SMIME_UNCOMPRESS) { + if (!CMS_uncompress(cms, indata, out, flags)) + goto end; + } else if (operation == SMIME_DIGEST_VERIFY) { + if (CMS_digest_verify(cms, indata, out, flags) > 0) { + BIO_printf(bio_err, "Verification successful\n"); + } else { + BIO_printf(bio_err, "Verification failure\n"); + goto end; + } + } else if (operation == SMIME_ENCRYPTED_DECRYPT) { + if (!CMS_EncryptedData_decrypt(cms, secret_key, secret_keylen, + indata, out, flags)) + goto end; + } else if (operation == SMIME_VERIFY) { + if (CMS_verify(cms, other, store, indata, out, flags) > 0) { + BIO_printf(bio_err, "Verification successful\n"); + } else { + BIO_printf(bio_err, "Verification failure\n"); + if (verify_retcode) + ret = verify_err + 32; + goto end; + } + if (signerfile != NULL) { + STACK_OF(X509) *signers; + signers = CMS_get0_signers(cms); + if (!save_certs(signerfile, signers)) { + BIO_printf(bio_err, + "Error writing signers to %s\n", signerfile); + ret = 5; + goto end; + } + sk_X509_free(signers); + } + if (rr_print) + receipt_request_print(cms); + + } else if (operation == SMIME_VERIFY_RECEIPT) { + if (CMS_verify_receipt(rcms, cms, other, store, flags) > 0) { + BIO_printf(bio_err, "Verification successful\n"); + } else { + BIO_printf(bio_err, "Verification failure\n"); + goto end; + } + } else { + if (noout) { + if (print) + CMS_ContentInfo_print_ctx(out, cms, 0, NULL); + } else if (outformat == FORMAT_SMIME) { + if (to) + BIO_printf(out, "To: %s%s", to, mime_eol); + if (from) + BIO_printf(out, "From: %s%s", from, mime_eol); + if (subject) + BIO_printf(out, "Subject: %s%s", subject, mime_eol); + if (operation == SMIME_RESIGN) + ret = SMIME_write_CMS(out, cms, indata, flags); + else + ret = SMIME_write_CMS(out, cms, in, flags); + } else if (outformat == FORMAT_PEM) { + ret = PEM_write_bio_CMS_stream(out, cms, in, flags); + } else if (outformat == FORMAT_ASN1) { + ret = i2d_CMS_bio_stream(out, cms, in, flags); + } else { + BIO_printf(bio_err, "Bad output format for CMS file\n"); + goto end; + } + if (ret <= 0) { + ret = 6; + goto end; + } + } + ret = 0; + end: + if (ret) + ERR_print_errors(bio_err); + sk_X509_pop_free(encerts, X509_free); + sk_X509_pop_free(other, X509_free); + X509_VERIFY_PARAM_free(vpm); + sk_OPENSSL_STRING_free(sksigners); + sk_OPENSSL_STRING_free(skkeys); + OPENSSL_free(secret_key); + OPENSSL_free(secret_keyid); + OPENSSL_free(pwri_tmp); + ASN1_OBJECT_free(econtent_type); + CMS_ReceiptRequest_free(rr); + sk_OPENSSL_STRING_free(rr_to); + sk_OPENSSL_STRING_free(rr_from); + for (key_param = key_first; key_param;) { + cms_key_param *tparam; + sk_OPENSSL_STRING_free(key_param->param); + tparam = key_param->next; + OPENSSL_free(key_param); + key_param = tparam; + } + X509_STORE_free(store); + X509_free(cert); + X509_free(recip); + X509_free(signer); + EVP_PKEY_free(key); + CMS_ContentInfo_free(cms); + CMS_ContentInfo_free(rcms); + release_engine(e); + BIO_free(rctin); + BIO_free(in); + BIO_free(indata); + BIO_free_all(out); + OPENSSL_free(passin); + return ret; +} + +static int save_certs(char *signerfile, STACK_OF(X509) *signers) +{ + int i; + BIO *tmp; + if (signerfile == NULL) + return 1; + tmp = BIO_new_file(signerfile, "w"); + if (tmp == NULL) + return 0; + for (i = 0; i < sk_X509_num(signers); i++) + PEM_write_bio_X509(tmp, sk_X509_value(signers, i)); + BIO_free(tmp); + return 1; +} + +/* Minimal callback just to output policy info (if any) */ + +static int cms_cb(int ok, X509_STORE_CTX *ctx) +{ + int error; + + error = X509_STORE_CTX_get_error(ctx); + + verify_err = error; + + if ((error != X509_V_ERR_NO_EXPLICIT_POLICY) + && ((error != X509_V_OK) || (ok != 2))) + return ok; + + policies_print(ctx); + + return ok; + +} + +static void gnames_stack_print(STACK_OF(GENERAL_NAMES) *gns) +{ + STACK_OF(GENERAL_NAME) *gens; + GENERAL_NAME *gen; + int i, j; + + for (i = 0; i < sk_GENERAL_NAMES_num(gns); i++) { + gens = sk_GENERAL_NAMES_value(gns, i); + for (j = 0; j < sk_GENERAL_NAME_num(gens); j++) { + gen = sk_GENERAL_NAME_value(gens, j); + BIO_puts(bio_err, " "); + GENERAL_NAME_print(bio_err, gen); + BIO_puts(bio_err, "\n"); + } + } + return; +} + +static void receipt_request_print(CMS_ContentInfo *cms) +{ + STACK_OF(CMS_SignerInfo) *sis; + CMS_SignerInfo *si; + CMS_ReceiptRequest *rr; + int allorfirst; + STACK_OF(GENERAL_NAMES) *rto, *rlist; + ASN1_STRING *scid; + int i, rv; + sis = CMS_get0_SignerInfos(cms); + for (i = 0; i < sk_CMS_SignerInfo_num(sis); i++) { + si = sk_CMS_SignerInfo_value(sis, i); + rv = CMS_get1_ReceiptRequest(si, &rr); + BIO_printf(bio_err, "Signer %d:\n", i + 1); + if (rv == 0) { + BIO_puts(bio_err, " No Receipt Request\n"); + } else if (rv < 0) { + BIO_puts(bio_err, " Receipt Request Parse Error\n"); + ERR_print_errors(bio_err); + } else { + const char *id; + int idlen; + CMS_ReceiptRequest_get0_values(rr, &scid, &allorfirst, + &rlist, &rto); + BIO_puts(bio_err, " Signed Content ID:\n"); + idlen = ASN1_STRING_length(scid); + id = (const char *)ASN1_STRING_get0_data(scid); + BIO_dump_indent(bio_err, id, idlen, 4); + BIO_puts(bio_err, " Receipts From"); + if (rlist != NULL) { + BIO_puts(bio_err, " List:\n"); + gnames_stack_print(rlist); + } else if (allorfirst == 1) { + BIO_puts(bio_err, ": First Tier\n"); + } else if (allorfirst == 0) { + BIO_puts(bio_err, ": All\n"); + } else { + BIO_printf(bio_err, " Unknown (%d)\n", allorfirst); + } + BIO_puts(bio_err, " Receipts To:\n"); + gnames_stack_print(rto); + } + CMS_ReceiptRequest_free(rr); + } +} + +static STACK_OF(GENERAL_NAMES) *make_names_stack(STACK_OF(OPENSSL_STRING) *ns) +{ + int i; + STACK_OF(GENERAL_NAMES) *ret; + GENERAL_NAMES *gens = NULL; + GENERAL_NAME *gen = NULL; + ret = sk_GENERAL_NAMES_new_null(); + if (ret == NULL) + goto err; + for (i = 0; i < sk_OPENSSL_STRING_num(ns); i++) { + char *str = sk_OPENSSL_STRING_value(ns, i); + gen = a2i_GENERAL_NAME(NULL, NULL, NULL, GEN_EMAIL, str, 0); + if (gen == NULL) + goto err; + gens = GENERAL_NAMES_new(); + if (gens == NULL) + goto err; + if (!sk_GENERAL_NAME_push(gens, gen)) + goto err; + gen = NULL; + if (!sk_GENERAL_NAMES_push(ret, gens)) + goto err; + gens = NULL; + } + + return ret; + + err: + sk_GENERAL_NAMES_pop_free(ret, GENERAL_NAMES_free); + GENERAL_NAMES_free(gens); + GENERAL_NAME_free(gen); + return NULL; +} + +static CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING) + *rr_to, int rr_allorfirst, STACK_OF(OPENSSL_STRING) + *rr_from) +{ + STACK_OF(GENERAL_NAMES) *rct_to = NULL, *rct_from = NULL; + CMS_ReceiptRequest *rr; + rct_to = make_names_stack(rr_to); + if (rct_to == NULL) + goto err; + if (rr_from != NULL) { + rct_from = make_names_stack(rr_from); + if (rct_from == NULL) + goto err; + } else { + rct_from = NULL; + } + rr = CMS_ReceiptRequest_create0(NULL, -1, rr_allorfirst, rct_from, + rct_to); + return rr; + err: + sk_GENERAL_NAMES_pop_free(rct_to, GENERAL_NAMES_free); + return NULL; +} + +static int cms_set_pkey_param(EVP_PKEY_CTX *pctx, + STACK_OF(OPENSSL_STRING) *param) +{ + char *keyopt; + int i; + if (sk_OPENSSL_STRING_num(param) <= 0) + return 1; + for (i = 0; i < sk_OPENSSL_STRING_num(param); i++) { + keyopt = sk_OPENSSL_STRING_value(param, i); + if (pkey_ctrl_string(pctx, keyopt) <= 0) { + BIO_printf(bio_err, "parameter error \"%s\"\n", keyopt); + ERR_print_errors(bio_err); + return 0; + } + } + return 1; +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/crl.c b/trunk/3rdparty/openssl-1.1-fit/apps/crl.c new file mode 100644 index 000000000..031fada14 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/crl.c @@ -0,0 +1,342 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include +#include + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_IN, OPT_OUTFORM, OPT_OUT, OPT_KEYFORM, OPT_KEY, + OPT_ISSUER, OPT_LASTUPDATE, OPT_NEXTUPDATE, OPT_FINGERPRINT, + OPT_CRLNUMBER, OPT_BADSIG, OPT_GENDELTA, OPT_CAPATH, OPT_CAFILE, + OPT_NOCAPATH, OPT_NOCAFILE, OPT_VERIFY, OPT_TEXT, OPT_HASH, OPT_HASH_OLD, + OPT_NOOUT, OPT_NAMEOPT, OPT_MD +} OPTION_CHOICE; + +const OPTIONS crl_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"inform", OPT_INFORM, 'F', "Input format; default PEM"}, + {"in", OPT_IN, '<', "Input file - default stdin"}, + {"outform", OPT_OUTFORM, 'F', "Output format - default PEM"}, + {"out", OPT_OUT, '>', "output file - default stdout"}, + {"keyform", OPT_KEYFORM, 'F', "Private key file format (PEM or ENGINE)"}, + {"key", OPT_KEY, '<', "CRL signing Private key to use"}, + {"issuer", OPT_ISSUER, '-', "Print issuer DN"}, + {"lastupdate", OPT_LASTUPDATE, '-', "Set lastUpdate field"}, + {"nextupdate", OPT_NEXTUPDATE, '-', "Set nextUpdate field"}, + {"noout", OPT_NOOUT, '-', "No CRL output"}, + {"fingerprint", OPT_FINGERPRINT, '-', "Print the crl fingerprint"}, + {"crlnumber", OPT_CRLNUMBER, '-', "Print CRL number"}, + {"badsig", OPT_BADSIG, '-', "Corrupt last byte of loaded CRL signature (for test)" }, + {"gendelta", OPT_GENDELTA, '<', "Other CRL to compare/diff to the Input one"}, + {"CApath", OPT_CAPATH, '/', "Verify CRL using certificates in dir"}, + {"CAfile", OPT_CAFILE, '<', "Verify CRL using certificates in file name"}, + {"no-CAfile", OPT_NOCAFILE, '-', + "Do not load the default certificates file"}, + {"no-CApath", OPT_NOCAPATH, '-', + "Do not load certificates from the default certificates directory"}, + {"verify", OPT_VERIFY, '-', "Verify CRL signature"}, + {"text", OPT_TEXT, '-', "Print out a text format version"}, + {"hash", OPT_HASH, '-', "Print hash value"}, + {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"}, + {"", OPT_MD, '-', "Any supported digest"}, +#ifndef OPENSSL_NO_MD5 + {"hash_old", OPT_HASH_OLD, '-', "Print old-style (MD5) hash value"}, +#endif + {NULL} +}; + +int crl_main(int argc, char **argv) +{ + X509_CRL *x = NULL; + BIO *out = NULL; + X509_STORE *store = NULL; + X509_STORE_CTX *ctx = NULL; + X509_LOOKUP *lookup = NULL; + X509_OBJECT *xobj = NULL; + EVP_PKEY *pkey; + const EVP_MD *digest = EVP_sha1(); + char *infile = NULL, *outfile = NULL, *crldiff = NULL, *keyfile = NULL; + const char *CAfile = NULL, *CApath = NULL, *prog; + OPTION_CHOICE o; + int hash = 0, issuer = 0, lastupdate = 0, nextupdate = 0, noout = 0; + int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM; + int ret = 1, num = 0, badsig = 0, fingerprint = 0, crlnumber = 0; + int text = 0, do_ver = 0, noCAfile = 0, noCApath = 0; + int i; +#ifndef OPENSSL_NO_MD5 + int hash_old = 0; +#endif + + prog = opt_init(argc, argv, crl_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(crl_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) + goto opthelp; + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_KEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &keyformat)) + goto opthelp; + break; + case OPT_KEY: + keyfile = opt_arg(); + break; + case OPT_GENDELTA: + crldiff = opt_arg(); + break; + case OPT_CAPATH: + CApath = opt_arg(); + do_ver = 1; + break; + case OPT_CAFILE: + CAfile = opt_arg(); + do_ver = 1; + break; + case OPT_NOCAPATH: + noCApath = 1; + break; + case OPT_NOCAFILE: + noCAfile = 1; + break; + case OPT_HASH_OLD: +#ifndef OPENSSL_NO_MD5 + hash_old = ++num; +#endif + break; + case OPT_VERIFY: + do_ver = 1; + break; + case OPT_TEXT: + text = 1; + break; + case OPT_HASH: + hash = ++num; + break; + case OPT_ISSUER: + issuer = ++num; + break; + case OPT_LASTUPDATE: + lastupdate = ++num; + break; + case OPT_NEXTUPDATE: + nextupdate = ++num; + break; + case OPT_NOOUT: + noout = ++num; + break; + case OPT_FINGERPRINT: + fingerprint = ++num; + break; + case OPT_CRLNUMBER: + crlnumber = ++num; + break; + case OPT_BADSIG: + badsig = 1; + break; + case OPT_NAMEOPT: + if (!set_nameopt(opt_arg())) + goto opthelp; + break; + case OPT_MD: + if (!opt_md(opt_unknown(), &digest)) + goto opthelp; + } + } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + + x = load_crl(infile, informat); + if (x == NULL) + goto end; + + if (do_ver) { + if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL) + goto end; + lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); + if (lookup == NULL) + goto end; + ctx = X509_STORE_CTX_new(); + if (ctx == NULL || !X509_STORE_CTX_init(ctx, store, NULL, NULL)) { + BIO_printf(bio_err, "Error initialising X509 store\n"); + goto end; + } + + xobj = X509_STORE_CTX_get_obj_by_subject(ctx, X509_LU_X509, + X509_CRL_get_issuer(x)); + if (xobj == NULL) { + BIO_printf(bio_err, "Error getting CRL issuer certificate\n"); + goto end; + } + pkey = X509_get_pubkey(X509_OBJECT_get0_X509(xobj)); + X509_OBJECT_free(xobj); + if (!pkey) { + BIO_printf(bio_err, "Error getting CRL issuer public key\n"); + goto end; + } + i = X509_CRL_verify(x, pkey); + EVP_PKEY_free(pkey); + if (i < 0) + goto end; + if (i == 0) + BIO_printf(bio_err, "verify failure\n"); + else + BIO_printf(bio_err, "verify OK\n"); + } + + if (crldiff) { + X509_CRL *newcrl, *delta; + if (!keyfile) { + BIO_puts(bio_err, "Missing CRL signing key\n"); + goto end; + } + newcrl = load_crl(crldiff, informat); + if (!newcrl) + goto end; + pkey = load_key(keyfile, keyformat, 0, NULL, NULL, "CRL signing key"); + if (!pkey) { + X509_CRL_free(newcrl); + goto end; + } + delta = X509_CRL_diff(x, newcrl, pkey, digest, 0); + X509_CRL_free(newcrl); + EVP_PKEY_free(pkey); + if (delta) { + X509_CRL_free(x); + x = delta; + } else { + BIO_puts(bio_err, "Error creating delta CRL\n"); + goto end; + } + } + + if (badsig) { + const ASN1_BIT_STRING *sig; + + X509_CRL_get0_signature(x, &sig, NULL); + corrupt_signature(sig); + } + + if (num) { + for (i = 1; i <= num; i++) { + if (issuer == i) { + print_name(bio_out, "issuer=", X509_CRL_get_issuer(x), + get_nameopt()); + } + if (crlnumber == i) { + ASN1_INTEGER *crlnum; + crlnum = X509_CRL_get_ext_d2i(x, NID_crl_number, NULL, NULL); + BIO_printf(bio_out, "crlNumber="); + if (crlnum) { + i2a_ASN1_INTEGER(bio_out, crlnum); + ASN1_INTEGER_free(crlnum); + } else + BIO_puts(bio_out, ""); + BIO_printf(bio_out, "\n"); + } + if (hash == i) { + BIO_printf(bio_out, "%08lx\n", + X509_NAME_hash(X509_CRL_get_issuer(x))); + } +#ifndef OPENSSL_NO_MD5 + if (hash_old == i) { + BIO_printf(bio_out, "%08lx\n", + X509_NAME_hash_old(X509_CRL_get_issuer(x))); + } +#endif + if (lastupdate == i) { + BIO_printf(bio_out, "lastUpdate="); + ASN1_TIME_print(bio_out, X509_CRL_get0_lastUpdate(x)); + BIO_printf(bio_out, "\n"); + } + if (nextupdate == i) { + BIO_printf(bio_out, "nextUpdate="); + if (X509_CRL_get0_nextUpdate(x)) + ASN1_TIME_print(bio_out, X509_CRL_get0_nextUpdate(x)); + else + BIO_printf(bio_out, "NONE"); + BIO_printf(bio_out, "\n"); + } + if (fingerprint == i) { + int j; + unsigned int n; + unsigned char md[EVP_MAX_MD_SIZE]; + + if (!X509_CRL_digest(x, digest, md, &n)) { + BIO_printf(bio_err, "out of memory\n"); + goto end; + } + BIO_printf(bio_out, "%s Fingerprint=", + OBJ_nid2sn(EVP_MD_type(digest))); + for (j = 0; j < (int)n; j++) { + BIO_printf(bio_out, "%02X%c", md[j], (j + 1 == (int)n) + ? '\n' : ':'); + } + } + } + } + out = bio_open_default(outfile, 'w', outformat); + if (out == NULL) + goto end; + + if (text) + X509_CRL_print_ex(out, x, get_nameopt()); + + if (noout) { + ret = 0; + goto end; + } + + if (outformat == FORMAT_ASN1) + i = (int)i2d_X509_CRL_bio(out, x); + else + i = PEM_write_bio_X509_CRL(out, x); + if (!i) { + BIO_printf(bio_err, "unable to write CRL\n"); + goto end; + } + ret = 0; + + end: + if (ret != 0) + ERR_print_errors(bio_err); + BIO_free_all(out); + X509_CRL_free(x); + X509_STORE_CTX_free(ctx); + X509_STORE_free(store); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/crl2p7.c b/trunk/3rdparty/openssl-1.1-fit/apps/crl2p7.c new file mode 100644 index 000000000..88fabcb22 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/crl2p7.c @@ -0,0 +1,217 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include +#include +#include + +static int add_certs_from_file(STACK_OF(X509) *stack, char *certfile); + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_NOCRL, OPT_CERTFILE +} OPTION_CHOICE; + +const OPTIONS crl2pkcs7_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"}, + {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"}, + {"in", OPT_IN, '<', "Input file"}, + {"out", OPT_OUT, '>', "Output file"}, + {"nocrl", OPT_NOCRL, '-', "No crl to load, just certs from '-certfile'"}, + {"certfile", OPT_CERTFILE, '<', + "File of chain of certs to a trusted CA; can be repeated"}, + {NULL} +}; + +int crl2pkcs7_main(int argc, char **argv) +{ + BIO *in = NULL, *out = NULL; + PKCS7 *p7 = NULL; + PKCS7_SIGNED *p7s = NULL; + STACK_OF(OPENSSL_STRING) *certflst = NULL; + STACK_OF(X509) *cert_stack = NULL; + STACK_OF(X509_CRL) *crl_stack = NULL; + X509_CRL *crl = NULL; + char *infile = NULL, *outfile = NULL, *prog, *certfile; + int i = 0, informat = FORMAT_PEM, outformat = FORMAT_PEM, ret = 1, nocrl = + 0; + OPTION_CHOICE o; + + prog = opt_init(argc, argv, crl2pkcs7_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(crl2pkcs7_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) + goto opthelp; + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_NOCRL: + nocrl = 1; + break; + case OPT_CERTFILE: + if ((certflst == NULL) + && (certflst = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; + if (!sk_OPENSSL_STRING_push(certflst, opt_arg())) + goto end; + break; + } + } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + + if (!nocrl) { + in = bio_open_default(infile, 'r', informat); + if (in == NULL) + goto end; + + if (informat == FORMAT_ASN1) + crl = d2i_X509_CRL_bio(in, NULL); + else if (informat == FORMAT_PEM) + crl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); + if (crl == NULL) { + BIO_printf(bio_err, "unable to load CRL\n"); + ERR_print_errors(bio_err); + goto end; + } + } + + if ((p7 = PKCS7_new()) == NULL) + goto end; + if ((p7s = PKCS7_SIGNED_new()) == NULL) + goto end; + p7->type = OBJ_nid2obj(NID_pkcs7_signed); + p7->d.sign = p7s; + p7s->contents->type = OBJ_nid2obj(NID_pkcs7_data); + + if (!ASN1_INTEGER_set(p7s->version, 1)) + goto end; + if ((crl_stack = sk_X509_CRL_new_null()) == NULL) + goto end; + p7s->crl = crl_stack; + if (crl != NULL) { + sk_X509_CRL_push(crl_stack, crl); + crl = NULL; /* now part of p7 for OPENSSL_freeing */ + } + + if ((cert_stack = sk_X509_new_null()) == NULL) + goto end; + p7s->cert = cert_stack; + + if (certflst != NULL) + for (i = 0; i < sk_OPENSSL_STRING_num(certflst); i++) { + certfile = sk_OPENSSL_STRING_value(certflst, i); + if (add_certs_from_file(cert_stack, certfile) < 0) { + BIO_printf(bio_err, "error loading certificates\n"); + ERR_print_errors(bio_err); + goto end; + } + } + + out = bio_open_default(outfile, 'w', outformat); + if (out == NULL) + goto end; + + if (outformat == FORMAT_ASN1) + i = i2d_PKCS7_bio(out, p7); + else if (outformat == FORMAT_PEM) + i = PEM_write_bio_PKCS7(out, p7); + if (!i) { + BIO_printf(bio_err, "unable to write pkcs7 object\n"); + ERR_print_errors(bio_err); + goto end; + } + ret = 0; + end: + sk_OPENSSL_STRING_free(certflst); + BIO_free(in); + BIO_free_all(out); + PKCS7_free(p7); + X509_CRL_free(crl); + + return ret; +} + +/*- + *---------------------------------------------------------------------- + * int add_certs_from_file + * + * Read a list of certificates to be checked from a file. + * + * Results: + * number of certs added if successful, -1 if not. + *---------------------------------------------------------------------- + */ +static int add_certs_from_file(STACK_OF(X509) *stack, char *certfile) +{ + BIO *in = NULL; + int count = 0; + int ret = -1; + STACK_OF(X509_INFO) *sk = NULL; + X509_INFO *xi; + + in = BIO_new_file(certfile, "r"); + if (in == NULL) { + BIO_printf(bio_err, "error opening the file, %s\n", certfile); + goto end; + } + + /* This loads from a file, a stack of x509/crl/pkey sets */ + sk = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL); + if (sk == NULL) { + BIO_printf(bio_err, "error reading the file, %s\n", certfile); + goto end; + } + + /* scan over it and pull out the CRL's */ + while (sk_X509_INFO_num(sk)) { + xi = sk_X509_INFO_shift(sk); + if (xi->x509 != NULL) { + sk_X509_push(stack, xi->x509); + xi->x509 = NULL; + count++; + } + X509_INFO_free(xi); + } + + ret = count; + end: + /* never need to OPENSSL_free x */ + BIO_free(in); + sk_X509_INFO_free(sk); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/ct_log_list.cnf b/trunk/3rdparty/openssl-1.1-fit/apps/ct_log_list.cnf new file mode 100644 index 000000000..e643cfdbd --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/ct_log_list.cnf @@ -0,0 +1,9 @@ +# This file specifies the Certificate Transparency logs +# that are to be trusted. + +# Google's list of logs can be found here: +# www.certificate-transparency.org/known-logs +# A Python program to convert the log list to OpenSSL's format can be +# found here: +# https://github.com/google/certificate-transparency/blob/master/python/utilities/log_list/print_log_list.py +# Use the "--openssl_output" flag. diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/demoSRP/srp_verifier.txt b/trunk/3rdparty/openssl-1.1-fit/apps/demoSRP/srp_verifier.txt new file mode 100644 index 000000000..c2d5c6033 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/demoSRP/srp_verifier.txt @@ -0,0 +1,6 @@ +# This is a file that will be filled by the openssl srp routine. +# You can initialize the file with additional groups, these are +# records starting with a I followed by the g and N values and the id. +# The exact values ... you have to dig this out from the source of srp.c +# or srp_vfy.c +# The last value of an I is used as the default group for new users. diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/demoSRP/srp_verifier.txt.attr b/trunk/3rdparty/openssl-1.1-fit/apps/demoSRP/srp_verifier.txt.attr new file mode 100644 index 000000000..8f7e63a34 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/demoSRP/srp_verifier.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/dgst.c b/trunk/3rdparty/openssl-1.1-fit/apps/dgst.c new file mode 100644 index 000000000..d158a0ccb --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/dgst.c @@ -0,0 +1,492 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include +#include +#include +#include + +#undef BUFSIZE +#define BUFSIZE 1024*8 + +int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, + EVP_PKEY *key, unsigned char *sigin, int siglen, + const char *sig_name, const char *md_name, + const char *file); + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_C, OPT_R, OPT_OUT, OPT_SIGN, OPT_PASSIN, OPT_VERIFY, + OPT_PRVERIFY, OPT_SIGNATURE, OPT_KEYFORM, OPT_ENGINE, OPT_ENGINE_IMPL, + OPT_HEX, OPT_BINARY, OPT_DEBUG, OPT_FIPS_FINGERPRINT, + OPT_HMAC, OPT_MAC, OPT_SIGOPT, OPT_MACOPT, + OPT_DIGEST, + OPT_R_ENUM +} OPTION_CHOICE; + +const OPTIONS dgst_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] [file...]\n"}, + {OPT_HELP_STR, 1, '-', + " file... files to digest (default is stdin)\n"}, + {"help", OPT_HELP, '-', "Display this summary"}, + {"c", OPT_C, '-', "Print the digest with separating colons"}, + {"r", OPT_R, '-', "Print the digest in coreutils format"}, + {"out", OPT_OUT, '>', "Output to filename rather than stdout"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"sign", OPT_SIGN, 's', "Sign digest using private key"}, + {"verify", OPT_VERIFY, 's', + "Verify a signature using public key"}, + {"prverify", OPT_PRVERIFY, 's', + "Verify a signature using private key"}, + {"signature", OPT_SIGNATURE, '<', "File with signature to verify"}, + {"keyform", OPT_KEYFORM, 'f', "Key file format (PEM or ENGINE)"}, + {"hex", OPT_HEX, '-', "Print as hex dump"}, + {"binary", OPT_BINARY, '-', "Print in binary form"}, + {"d", OPT_DEBUG, '-', "Print debug info"}, + {"debug", OPT_DEBUG, '-', "Print debug info"}, + {"fips-fingerprint", OPT_FIPS_FINGERPRINT, '-', + "Compute HMAC with the key used in OpenSSL-FIPS fingerprint"}, + {"hmac", OPT_HMAC, 's', "Create hashed MAC with key"}, + {"mac", OPT_MAC, 's', "Create MAC (not necessarily HMAC)"}, + {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"}, + {"macopt", OPT_MACOPT, 's', "MAC algorithm parameters in n:v form or key"}, + {"", OPT_DIGEST, '-', "Any supported digest"}, + OPT_R_OPTIONS, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"}, + {"engine_impl", OPT_ENGINE_IMPL, '-', + "Also use engine given by -engine for digest operations"}, +#endif + {NULL} +}; + +int dgst_main(int argc, char **argv) +{ + BIO *in = NULL, *inp, *bmd = NULL, *out = NULL; + ENGINE *e = NULL, *impl = NULL; + EVP_PKEY *sigkey = NULL; + STACK_OF(OPENSSL_STRING) *sigopts = NULL, *macopts = NULL; + char *hmac_key = NULL; + char *mac_name = NULL; + char *passinarg = NULL, *passin = NULL; + const EVP_MD *md = NULL, *m; + const char *outfile = NULL, *keyfile = NULL, *prog = NULL; + const char *sigfile = NULL; + OPTION_CHOICE o; + int separator = 0, debug = 0, keyform = FORMAT_PEM, siglen = 0; + int i, ret = 1, out_bin = -1, want_pub = 0, do_verify = 0; + unsigned char *buf = NULL, *sigbuf = NULL; + int engine_impl = 0; + + prog = opt_progname(argv[0]); + buf = app_malloc(BUFSIZE, "I/O buffer"); + md = EVP_get_digestbyname(prog); + + prog = opt_init(argc, argv, dgst_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(dgst_options); + ret = 0; + goto end; + case OPT_C: + separator = 1; + break; + case OPT_R: + separator = 2; + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_SIGN: + keyfile = opt_arg(); + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_VERIFY: + keyfile = opt_arg(); + want_pub = do_verify = 1; + break; + case OPT_PRVERIFY: + keyfile = opt_arg(); + do_verify = 1; + break; + case OPT_SIGNATURE: + sigfile = opt_arg(); + break; + case OPT_KEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform)) + goto opthelp; + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_ENGINE_IMPL: + engine_impl = 1; + break; + case OPT_HEX: + out_bin = 0; + break; + case OPT_BINARY: + out_bin = 1; + break; + case OPT_DEBUG: + debug = 1; + break; + case OPT_FIPS_FINGERPRINT: + hmac_key = "etaonrishdlcupfm"; + break; + case OPT_HMAC: + hmac_key = opt_arg(); + break; + case OPT_MAC: + mac_name = opt_arg(); + break; + case OPT_SIGOPT: + if (!sigopts) + sigopts = sk_OPENSSL_STRING_new_null(); + if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg())) + goto opthelp; + break; + case OPT_MACOPT: + if (!macopts) + macopts = sk_OPENSSL_STRING_new_null(); + if (!macopts || !sk_OPENSSL_STRING_push(macopts, opt_arg())) + goto opthelp; + break; + case OPT_DIGEST: + if (!opt_md(opt_unknown(), &m)) + goto opthelp; + md = m; + break; + } + } + argc = opt_num_rest(); + argv = opt_rest(); + if (keyfile != NULL && argc > 1) { + BIO_printf(bio_err, "%s: Can only sign or verify one file.\n", prog); + goto end; + } + + if (do_verify && sigfile == NULL) { + BIO_printf(bio_err, + "No signature to verify: use the -signature option\n"); + goto end; + } + if (engine_impl) + impl = e; + + in = BIO_new(BIO_s_file()); + bmd = BIO_new(BIO_f_md()); + if ((in == NULL) || (bmd == NULL)) { + ERR_print_errors(bio_err); + goto end; + } + + if (debug) { + BIO_set_callback(in, BIO_debug_callback); + /* needed for windows 3.1 */ + BIO_set_callback_arg(in, (char *)bio_err); + } + + if (!app_passwd(passinarg, NULL, &passin, NULL)) { + BIO_printf(bio_err, "Error getting password\n"); + goto end; + } + + if (out_bin == -1) { + if (keyfile != NULL) + out_bin = 1; + else + out_bin = 0; + } + + out = bio_open_default(outfile, 'w', out_bin ? FORMAT_BINARY : FORMAT_TEXT); + if (out == NULL) + goto end; + + if ((!(mac_name == NULL) + !(keyfile == NULL) + !(hmac_key == NULL)) > 1) { + BIO_printf(bio_err, "MAC and Signing key cannot both be specified\n"); + goto end; + } + + if (keyfile != NULL) { + int type; + + if (want_pub) + sigkey = load_pubkey(keyfile, keyform, 0, NULL, e, "key file"); + else + sigkey = load_key(keyfile, keyform, 0, passin, e, "key file"); + if (sigkey == NULL) { + /* + * load_[pub]key() has already printed an appropriate message + */ + goto end; + } + type = EVP_PKEY_id(sigkey); + if (type == EVP_PKEY_ED25519 || type == EVP_PKEY_ED448) { + /* + * We implement PureEdDSA for these which doesn't have a separate + * digest, and only supports one shot. + */ + BIO_printf(bio_err, "Key type not supported for this operation\n"); + goto end; + } + } + + if (mac_name != NULL) { + EVP_PKEY_CTX *mac_ctx = NULL; + int r = 0; + if (!init_gen_str(&mac_ctx, mac_name, impl, 0)) + goto mac_end; + if (macopts != NULL) { + char *macopt; + for (i = 0; i < sk_OPENSSL_STRING_num(macopts); i++) { + macopt = sk_OPENSSL_STRING_value(macopts, i); + if (pkey_ctrl_string(mac_ctx, macopt) <= 0) { + BIO_printf(bio_err, + "MAC parameter error \"%s\"\n", macopt); + ERR_print_errors(bio_err); + goto mac_end; + } + } + } + if (EVP_PKEY_keygen(mac_ctx, &sigkey) <= 0) { + BIO_puts(bio_err, "Error generating key\n"); + ERR_print_errors(bio_err); + goto mac_end; + } + r = 1; + mac_end: + EVP_PKEY_CTX_free(mac_ctx); + if (r == 0) + goto end; + } + + if (hmac_key != NULL) { + sigkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, impl, + (unsigned char *)hmac_key, -1); + if (sigkey == NULL) + goto end; + } + + if (sigkey != NULL) { + EVP_MD_CTX *mctx = NULL; + EVP_PKEY_CTX *pctx = NULL; + int r; + if (!BIO_get_md_ctx(bmd, &mctx)) { + BIO_printf(bio_err, "Error getting context\n"); + ERR_print_errors(bio_err); + goto end; + } + if (do_verify) + r = EVP_DigestVerifyInit(mctx, &pctx, md, impl, sigkey); + else + r = EVP_DigestSignInit(mctx, &pctx, md, impl, sigkey); + if (!r) { + BIO_printf(bio_err, "Error setting context\n"); + ERR_print_errors(bio_err); + goto end; + } + if (sigopts != NULL) { + char *sigopt; + for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) { + sigopt = sk_OPENSSL_STRING_value(sigopts, i); + if (pkey_ctrl_string(pctx, sigopt) <= 0) { + BIO_printf(bio_err, "parameter error \"%s\"\n", sigopt); + ERR_print_errors(bio_err); + goto end; + } + } + } + } + /* we use md as a filter, reading from 'in' */ + else { + EVP_MD_CTX *mctx = NULL; + if (!BIO_get_md_ctx(bmd, &mctx)) { + BIO_printf(bio_err, "Error getting context\n"); + ERR_print_errors(bio_err); + goto end; + } + if (md == NULL) + md = EVP_sha256(); + if (!EVP_DigestInit_ex(mctx, md, impl)) { + BIO_printf(bio_err, "Error setting digest\n"); + ERR_print_errors(bio_err); + goto end; + } + } + + if (sigfile != NULL && sigkey != NULL) { + BIO *sigbio = BIO_new_file(sigfile, "rb"); + if (sigbio == NULL) { + BIO_printf(bio_err, "Error opening signature file %s\n", sigfile); + ERR_print_errors(bio_err); + goto end; + } + siglen = EVP_PKEY_size(sigkey); + sigbuf = app_malloc(siglen, "signature buffer"); + siglen = BIO_read(sigbio, sigbuf, siglen); + BIO_free(sigbio); + if (siglen <= 0) { + BIO_printf(bio_err, "Error reading signature file %s\n", sigfile); + ERR_print_errors(bio_err); + goto end; + } + } + inp = BIO_push(bmd, in); + + if (md == NULL) { + EVP_MD_CTX *tctx; + BIO_get_md_ctx(bmd, &tctx); + md = EVP_MD_CTX_md(tctx); + } + + if (argc == 0) { + BIO_set_fp(in, stdin, BIO_NOCLOSE); + ret = do_fp(out, buf, inp, separator, out_bin, sigkey, sigbuf, + siglen, NULL, NULL, "stdin"); + } else { + const char *md_name = NULL, *sig_name = NULL; + if (!out_bin) { + if (sigkey != NULL) { + const EVP_PKEY_ASN1_METHOD *ameth; + ameth = EVP_PKEY_get0_asn1(sigkey); + if (ameth) + EVP_PKEY_asn1_get0_info(NULL, NULL, + NULL, NULL, &sig_name, ameth); + } + if (md != NULL) + md_name = EVP_MD_name(md); + } + ret = 0; + for (i = 0; i < argc; i++) { + int r; + if (BIO_read_filename(in, argv[i]) <= 0) { + perror(argv[i]); + ret++; + continue; + } else { + r = do_fp(out, buf, inp, separator, out_bin, sigkey, sigbuf, + siglen, sig_name, md_name, argv[i]); + } + if (r) + ret = r; + (void)BIO_reset(bmd); + } + } + end: + OPENSSL_clear_free(buf, BUFSIZE); + BIO_free(in); + OPENSSL_free(passin); + BIO_free_all(out); + EVP_PKEY_free(sigkey); + sk_OPENSSL_STRING_free(sigopts); + sk_OPENSSL_STRING_free(macopts); + OPENSSL_free(sigbuf); + BIO_free(bmd); + release_engine(e); + return ret; +} + +int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, + EVP_PKEY *key, unsigned char *sigin, int siglen, + const char *sig_name, const char *md_name, + const char *file) +{ + size_t len; + int i; + + for (;;) { + i = BIO_read(bp, (char *)buf, BUFSIZE); + if (i < 0) { + BIO_printf(bio_err, "Read Error in %s\n", file); + ERR_print_errors(bio_err); + return 1; + } + if (i == 0) + break; + } + if (sigin != NULL) { + EVP_MD_CTX *ctx; + BIO_get_md_ctx(bp, &ctx); + i = EVP_DigestVerifyFinal(ctx, sigin, (unsigned int)siglen); + if (i > 0) { + BIO_printf(out, "Verified OK\n"); + } else if (i == 0) { + BIO_printf(out, "Verification Failure\n"); + return 1; + } else { + BIO_printf(bio_err, "Error Verifying Data\n"); + ERR_print_errors(bio_err); + return 1; + } + return 0; + } + if (key != NULL) { + EVP_MD_CTX *ctx; + BIO_get_md_ctx(bp, &ctx); + len = BUFSIZE; + if (!EVP_DigestSignFinal(ctx, buf, &len)) { + BIO_printf(bio_err, "Error Signing Data\n"); + ERR_print_errors(bio_err); + return 1; + } + } else { + len = BIO_gets(bp, (char *)buf, BUFSIZE); + if ((int)len < 0) { + ERR_print_errors(bio_err); + return 1; + } + } + + if (binout) { + BIO_write(out, buf, len); + } else if (sep == 2) { + for (i = 0; i < (int)len; i++) + BIO_printf(out, "%02x", buf[i]); + BIO_printf(out, " *%s\n", file); + } else { + if (sig_name != NULL) { + BIO_puts(out, sig_name); + if (md_name != NULL) + BIO_printf(out, "-%s", md_name); + BIO_printf(out, "(%s)= ", file); + } else if (md_name != NULL) { + BIO_printf(out, "%s(%s)= ", md_name, file); + } else { + BIO_printf(out, "(%s)= ", file); + } + for (i = 0; i < (int)len; i++) { + if (sep && (i != 0)) + BIO_printf(out, ":"); + BIO_printf(out, "%02x", buf[i]); + } + BIO_printf(out, "\n"); + } + return 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/dh1024.pem b/trunk/3rdparty/openssl-1.1-fit/apps/dh1024.pem new file mode 100644 index 000000000..813e8a4a4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/dh1024.pem @@ -0,0 +1,10 @@ +-----BEGIN DH PARAMETERS----- +MIGHAoGBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR +Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL +/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7OZTgf//////////AgEC +-----END DH PARAMETERS----- + +These are the 1024-bit DH parameters from "Internet Key Exchange +Protocol Version 2 (IKEv2)": https://tools.ietf.org/html/rfc5996 + +See https://tools.ietf.org/html/rfc2412 for how they were generated. diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/dh2048.pem b/trunk/3rdparty/openssl-1.1-fit/apps/dh2048.pem new file mode 100644 index 000000000..288a20997 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/dh2048.pem @@ -0,0 +1,14 @@ +-----BEGIN DH PARAMETERS----- +MIIBCAKCAQEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb +IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft +awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT +mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh +fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq +5RXSJhiY+gUQFXKOWoqsqmj//////////wIBAg== +-----END DH PARAMETERS----- + +These are the 2048-bit DH parameters from "More Modular Exponential +(MODP) Diffie-Hellman groups for Internet Key Exchange (IKE)": +https://tools.ietf.org/html/rfc3526 + +See https://tools.ietf.org/html/rfc2412 for how they were generated. diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/dh4096.pem b/trunk/3rdparty/openssl-1.1-fit/apps/dh4096.pem new file mode 100644 index 000000000..08560e128 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/dh4096.pem @@ -0,0 +1,19 @@ +-----BEGIN DH PARAMETERS----- +MIICCAKCAgEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb +IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft +awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT +mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh +fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq +5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM +fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq +ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI +ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O ++S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI +HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0BjGZ//////////8CAQI= +-----END DH PARAMETERS----- + +These are the 4096-bit DH parameters from "More Modular Exponential +(MODP) Diffie-Hellman groups for Internet Key Exchange (IKE)": +https://tools.ietf.org/html/rfc3526 + +See https://tools.ietf.org/html/rfc2412 for how they were generated. diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/dhparam.c b/trunk/3rdparty/openssl-1.1-fit/apps/dhparam.c new file mode 100644 index 000000000..13f76754d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/dhparam.c @@ -0,0 +1,379 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#ifdef OPENSSL_NO_DH +NON_EMPTY_TRANSLATION_UNIT +#else + +# include +# include +# include +# include +# include "apps.h" +# include "progs.h" +# include +# include +# include +# include +# include +# include + +# ifndef OPENSSL_NO_DSA +# include +# endif + +# define DEFBITS 2048 + +static int dh_cb(int p, int n, BN_GENCB *cb); + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, + OPT_ENGINE, OPT_CHECK, OPT_TEXT, OPT_NOOUT, + OPT_DSAPARAM, OPT_C, OPT_2, OPT_5, + OPT_R_ENUM +} OPTION_CHOICE; + +const OPTIONS dhparam_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [flags] [numbits]\n"}, + {OPT_HELP_STR, 1, '-', "Valid options are:\n"}, + {"help", OPT_HELP, '-', "Display this summary"}, + {"in", OPT_IN, '<', "Input file"}, + {"inform", OPT_INFORM, 'F', "Input format, DER or PEM"}, + {"outform", OPT_OUTFORM, 'F', "Output format, DER or PEM"}, + {"out", OPT_OUT, '>', "Output file"}, + {"check", OPT_CHECK, '-', "Check the DH parameters"}, + {"text", OPT_TEXT, '-', "Print a text form of the DH parameters"}, + {"noout", OPT_NOOUT, '-', "Don't output any DH parameters"}, + OPT_R_OPTIONS, + {"C", OPT_C, '-', "Print C code"}, + {"2", OPT_2, '-', "Generate parameters using 2 as the generator value"}, + {"5", OPT_5, '-', "Generate parameters using 5 as the generator value"}, +# ifndef OPENSSL_NO_DSA + {"dsaparam", OPT_DSAPARAM, '-', + "Read or generate DSA parameters, convert to DH"}, +# endif +# ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"}, +# endif + {NULL} +}; + +int dhparam_main(int argc, char **argv) +{ + BIO *in = NULL, *out = NULL; + DH *dh = NULL; + char *infile = NULL, *outfile = NULL, *prog; + ENGINE *e = NULL; +#ifndef OPENSSL_NO_DSA + int dsaparam = 0; +#endif + int i, text = 0, C = 0, ret = 1, num = 0, g = 0; + int informat = FORMAT_PEM, outformat = FORMAT_PEM, check = 0, noout = 0; + OPTION_CHOICE o; + + prog = opt_init(argc, argv, dhparam_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(dhparam_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) + goto opthelp; + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_CHECK: + check = 1; + break; + case OPT_TEXT: + text = 1; + break; + case OPT_DSAPARAM: +#ifndef OPENSSL_NO_DSA + dsaparam = 1; +#endif + break; + case OPT_C: + C = 1; + break; + case OPT_2: + g = 2; + break; + case OPT_5: + g = 5; + break; + case OPT_NOOUT: + noout = 1; + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + } + } + argc = opt_num_rest(); + argv = opt_rest(); + + if (argv[0] != NULL && (!opt_int(argv[0], &num) || num <= 0)) + goto end; + + if (g && !num) + num = DEFBITS; + +# ifndef OPENSSL_NO_DSA + if (dsaparam && g) { + BIO_printf(bio_err, + "generator may not be chosen for DSA parameters\n"); + goto end; + } +# endif + + out = bio_open_default(outfile, 'w', outformat); + if (out == NULL) + goto end; + + /* DH parameters */ + if (num && !g) + g = 2; + + if (num) { + + BN_GENCB *cb; + cb = BN_GENCB_new(); + if (cb == NULL) { + ERR_print_errors(bio_err); + goto end; + } + + BN_GENCB_set(cb, dh_cb, bio_err); + +# ifndef OPENSSL_NO_DSA + if (dsaparam) { + DSA *dsa = DSA_new(); + + BIO_printf(bio_err, + "Generating DSA parameters, %d bit long prime\n", num); + if (dsa == NULL + || !DSA_generate_parameters_ex(dsa, num, NULL, 0, NULL, NULL, + cb)) { + DSA_free(dsa); + BN_GENCB_free(cb); + ERR_print_errors(bio_err); + goto end; + } + + dh = DSA_dup_DH(dsa); + DSA_free(dsa); + if (dh == NULL) { + BN_GENCB_free(cb); + ERR_print_errors(bio_err); + goto end; + } + } else +# endif + { + dh = DH_new(); + BIO_printf(bio_err, + "Generating DH parameters, %d bit long safe prime, generator %d\n", + num, g); + BIO_printf(bio_err, "This is going to take a long time\n"); + if (dh == NULL || !DH_generate_parameters_ex(dh, num, g, cb)) { + BN_GENCB_free(cb); + ERR_print_errors(bio_err); + goto end; + } + } + + BN_GENCB_free(cb); + } else { + + in = bio_open_default(infile, 'r', informat); + if (in == NULL) + goto end; + +# ifndef OPENSSL_NO_DSA + if (dsaparam) { + DSA *dsa; + + if (informat == FORMAT_ASN1) + dsa = d2i_DSAparams_bio(in, NULL); + else /* informat == FORMAT_PEM */ + dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL); + + if (dsa == NULL) { + BIO_printf(bio_err, "unable to load DSA parameters\n"); + ERR_print_errors(bio_err); + goto end; + } + + dh = DSA_dup_DH(dsa); + DSA_free(dsa); + if (dh == NULL) { + ERR_print_errors(bio_err); + goto end; + } + } else +# endif + { + if (informat == FORMAT_ASN1) { + /* + * We have no PEM header to determine what type of DH params it + * is. We'll just try both. + */ + dh = d2i_DHparams_bio(in, NULL); + /* BIO_reset() returns 0 for success for file BIOs only!!! */ + if (dh == NULL && BIO_reset(in) == 0) + dh = d2i_DHxparams_bio(in, NULL); + } else { + /* informat == FORMAT_PEM */ + dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL); + } + + if (dh == NULL) { + BIO_printf(bio_err, "unable to load DH parameters\n"); + ERR_print_errors(bio_err); + goto end; + } + } + + /* dh != NULL */ + } + + if (text) { + DHparams_print(out, dh); + } + + if (check) { + if (!DH_check(dh, &i)) { + ERR_print_errors(bio_err); + goto end; + } + if (i & DH_CHECK_P_NOT_PRIME) + BIO_printf(bio_err, "WARNING: p value is not prime\n"); + if (i & DH_CHECK_P_NOT_SAFE_PRIME) + BIO_printf(bio_err, "WARNING: p value is not a safe prime\n"); + if (i & DH_CHECK_Q_NOT_PRIME) + BIO_printf(bio_err, "WARNING: q value is not a prime\n"); + if (i & DH_CHECK_INVALID_Q_VALUE) + BIO_printf(bio_err, "WARNING: q value is invalid\n"); + if (i & DH_CHECK_INVALID_J_VALUE) + BIO_printf(bio_err, "WARNING: j value is invalid\n"); + if (i & DH_UNABLE_TO_CHECK_GENERATOR) + BIO_printf(bio_err, + "WARNING: unable to check the generator value\n"); + if (i & DH_NOT_SUITABLE_GENERATOR) + BIO_printf(bio_err, "WARNING: the g value is not a generator\n"); + if (i == 0) + BIO_printf(bio_err, "DH parameters appear to be ok.\n"); + if (num != 0 && i != 0) { + /* + * We have generated parameters but DH_check() indicates they are + * invalid! This should never happen! + */ + BIO_printf(bio_err, "ERROR: Invalid parameters generated\n"); + goto end; + } + } + if (C) { + unsigned char *data; + int len, bits; + const BIGNUM *pbn, *gbn; + + len = DH_size(dh); + bits = DH_bits(dh); + DH_get0_pqg(dh, &pbn, NULL, &gbn); + data = app_malloc(len, "print a BN"); + + BIO_printf(out, "static DH *get_dh%d(void)\n{\n", bits); + print_bignum_var(out, pbn, "dhp", bits, data); + print_bignum_var(out, gbn, "dhg", bits, data); + BIO_printf(out, " DH *dh = DH_new();\n" + " BIGNUM *p, *g;\n" + "\n" + " if (dh == NULL)\n" + " return NULL;\n"); + BIO_printf(out, " p = BN_bin2bn(dhp_%d, sizeof(dhp_%d), NULL);\n", + bits, bits); + BIO_printf(out, " g = BN_bin2bn(dhg_%d, sizeof(dhg_%d), NULL);\n", + bits, bits); + BIO_printf(out, " if (p == NULL || g == NULL\n" + " || !DH_set0_pqg(dh, p, NULL, g)) {\n" + " DH_free(dh);\n" + " BN_free(p);\n" + " BN_free(g);\n" + " return NULL;\n" + " }\n"); + if (DH_get_length(dh) > 0) + BIO_printf(out, + " if (!DH_set_length(dh, %ld)) {\n" + " DH_free(dh);\n" + " return NULL;\n" + " }\n", DH_get_length(dh)); + BIO_printf(out, " return dh;\n}\n"); + OPENSSL_free(data); + } + + if (!noout) { + const BIGNUM *q; + DH_get0_pqg(dh, NULL, &q, NULL); + if (outformat == FORMAT_ASN1) { + if (q != NULL) + i = i2d_DHxparams_bio(out, dh); + else + i = i2d_DHparams_bio(out, dh); + } else if (q != NULL) { + i = PEM_write_bio_DHxparams(out, dh); + } else { + i = PEM_write_bio_DHparams(out, dh); + } + if (!i) { + BIO_printf(bio_err, "unable to write DH parameters\n"); + ERR_print_errors(bio_err); + goto end; + } + } + ret = 0; + end: + BIO_free(in); + BIO_free_all(out); + DH_free(dh); + release_engine(e); + return ret; +} + +static int dh_cb(int p, int n, BN_GENCB *cb) +{ + static const char symbols[] = ".+*\n"; + char c = (p >= 0 && (size_t)p < sizeof(symbols) - 1) ? symbols[p] : '?'; + + BIO_write(BN_GENCB_get_arg(cb), &c, 1); + (void)BIO_flush(BN_GENCB_get_arg(cb)); + return 1; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/dsa-ca.pem b/trunk/3rdparty/openssl-1.1-fit/apps/dsa-ca.pem new file mode 100644 index 000000000..3ce8dc605 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/dsa-ca.pem @@ -0,0 +1,47 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBugIBAAKBgQCnP26Fv0FqKX3wn0cZMJCaCR3aajMexT2GlrMV4FMuj+BZgnOQ +PnUxmUd6UvuF5NmmezibaIqEm4fGHrV+hktTW1nPcWUZiG7OZq5riDb77Cjcwtel +u+UsOSZL2ppwGJU3lRBWI/YV7boEXt45T/23Qx+1pGVvzYAR5HCVW1DNSQIVAPcH +Me36bAYD1YWKHKycZedQZmVvAoGATd9MA6aRivUZb1BGJZnlaG8w42nh5bNdmLso +hkj83pkEP1+IDJxzJA0gXbkqmj8YlifkYofBe3RiU/xhJ6h6kQmdtvFNnFQPWAbu +SXQHzlV+I84W9srcWmEBfslxtU323DQph2j2XiCTs9v15AlsQReVkusBtXOlan7Y +Mu0OArgCgYAapll6iqz9XrZFlk2GCVcB+KihxWnH7IuHvSLw9YUrJahcBHmbpvt4 +94lF4gC5w3WPM+vXJofbusk4GoQEEsQNMDaah4m49uUqAylOVFJJJXuirVJ+o+0T +tOFDITEAl+YZZariXOD7tdOSOl9RLMPC6+daHKS9e68u3enxhqnDGQIUB78dhW77 +J6zsFbSEHaQGUmfSeoM= +-----END DSA PRIVATE KEY----- +-----BEGIN CERTIFICATE REQUEST----- +MIICVjCCAhMCAQAwUjELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx +ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDELMAkGA1UEAwwCQ0Ew +ggG2MIIBKwYHKoZIzjgEATCCAR4CgYEApz9uhb9Bail98J9HGTCQmgkd2mozHsU9 +hpazFeBTLo/gWYJzkD51MZlHelL7heTZpns4m2iKhJuHxh61foZLU1tZz3FlGYhu +zmaua4g2++wo3MLXpbvlLDkmS9qacBiVN5UQViP2Fe26BF7eOU/9t0MftaRlb82A +EeRwlVtQzUkCFQD3BzHt+mwGA9WFihysnGXnUGZlbwKBgE3fTAOmkYr1GW9QRiWZ +5WhvMONp4eWzXZi7KIZI/N6ZBD9fiAyccyQNIF25Kpo/GJYn5GKHwXt0YlP8YSeo +epEJnbbxTZxUD1gG7kl0B85VfiPOFvbK3FphAX7JcbVN9tw0KYdo9l4gk7Pb9eQJ +bEEXlZLrAbVzpWp+2DLtDgK4A4GEAAKBgBqmWXqKrP1etkWWTYYJVwH4qKHFacfs +i4e9IvD1hSslqFwEeZum+3j3iUXiALnDdY8z69cmh9u6yTgahAQSxA0wNpqHibj2 +5SoDKU5UUkkle6KtUn6j7RO04UMhMQCX5hllquJc4Pu105I6X1Esw8Lr51ocpL17 +ry7d6fGGqcMZoAAwCwYJYIZIAWUDBAMCAzAAMC0CFCp7rUwGJNtxK6Aqo6k6US+S +KP8sAhUAyfSi8Zs3QAvkJoFG0IMRaq8M03I= +-----END CERTIFICATE REQUEST----- +-----BEGIN CERTIFICATE----- +MIIDMDCCAuygAwIBAgIBAjALBglghkgBZQMEAwIwUzELMAkGA1UEBhMCQVUxEzAR +BgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5 +IEx0ZDEMMAoGA1UEAwwDUENBMCAXDTE2MDExMzIxNDE0OVoYDzMwMTUwNTE2MjE0 +MTQ5WjBSMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UE +CgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQswCQYDVQQDDAJDQTCCAbYwggEr +BgcqhkjOOAQBMIIBHgKBgQCnP26Fv0FqKX3wn0cZMJCaCR3aajMexT2GlrMV4FMu +j+BZgnOQPnUxmUd6UvuF5NmmezibaIqEm4fGHrV+hktTW1nPcWUZiG7OZq5riDb7 +7Cjcwtelu+UsOSZL2ppwGJU3lRBWI/YV7boEXt45T/23Qx+1pGVvzYAR5HCVW1DN +SQIVAPcHMe36bAYD1YWKHKycZedQZmVvAoGATd9MA6aRivUZb1BGJZnlaG8w42nh +5bNdmLsohkj83pkEP1+IDJxzJA0gXbkqmj8YlifkYofBe3RiU/xhJ6h6kQmdtvFN +nFQPWAbuSXQHzlV+I84W9srcWmEBfslxtU323DQph2j2XiCTs9v15AlsQReVkusB +tXOlan7YMu0OArgDgYQAAoGAGqZZeoqs/V62RZZNhglXAfioocVpx+yLh70i8PWF +KyWoXAR5m6b7ePeJReIAucN1jzPr1yaH27rJOBqEBBLEDTA2moeJuPblKgMpTlRS +SSV7oq1SfqPtE7ThQyExAJfmGWWq4lzg+7XTkjpfUSzDwuvnWhykvXuvLt3p8Yap +wxmjUDBOMB0GA1UdDgQWBBTMZcORcBEVlqO/CD4pf4V6N1NM1zAfBgNVHSMEGDAW +gBTGjwJ33uvjSa20RNrMKWoGptOLdDAMBgNVHRMEBTADAQH/MAsGCWCGSAFlAwQD +AgMxADAuAhUA4V6MrHufG8R79E+AtVO02olPxK8CFQDkZyo/TWpavsUBRDJbCeD9 +jgjIkA== +-----END CERTIFICATE----- diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/dsa-pca.pem b/trunk/3rdparty/openssl-1.1-fit/apps/dsa-pca.pem new file mode 100644 index 000000000..a51a06ed1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/dsa-pca.pem @@ -0,0 +1,47 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBvAIBAAKBgQCnP26Fv0FqKX3wn0cZMJCaCR3aajMexT2GlrMV4FMuj+BZgnOQ +PnUxmUd6UvuF5NmmezibaIqEm4fGHrV+hktTW1nPcWUZiG7OZq5riDb77Cjcwtel +u+UsOSZL2ppwGJU3lRBWI/YV7boEXt45T/23Qx+1pGVvzYAR5HCVW1DNSQIVAPcH +Me36bAYD1YWKHKycZedQZmVvAoGATd9MA6aRivUZb1BGJZnlaG8w42nh5bNdmLso +hkj83pkEP1+IDJxzJA0gXbkqmj8YlifkYofBe3RiU/xhJ6h6kQmdtvFNnFQPWAbu +SXQHzlV+I84W9srcWmEBfslxtU323DQph2j2XiCTs9v15AlsQReVkusBtXOlan7Y +Mu0OArgCgYEApu25HkB1b4gKMIV7aLGNSIknMzYgrB7o1kQxeDf34dDVRM9OZ8tk +umz6tl+iUcNe5EoxdsYV1IXSddjOi08LOLsZq7AQlNnKvbtlmMDULpqkZJD0bO7A +29nisJfKy1URqABLw5DgfcPh1ZLXtmDfUgJvmjgTmvTPT2j9TPjq7RUCFQDNvrBz +6TicfImU7UFRn9h00j0lJQ== +-----END DSA PRIVATE KEY----- +-----BEGIN CERTIFICATE REQUEST----- +MIICWDCCAhUCAQAwUzELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx +ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEMMAoGA1UEAwwDUENB +MIIBtzCCASsGByqGSM44BAEwggEeAoGBAKc/boW/QWopffCfRxkwkJoJHdpqMx7F +PYaWsxXgUy6P4FmCc5A+dTGZR3pS+4Xk2aZ7OJtoioSbh8YetX6GS1NbWc9xZRmI +bs5mrmuINvvsKNzC16W75Sw5JkvamnAYlTeVEFYj9hXtugRe3jlP/bdDH7WkZW/N +gBHkcJVbUM1JAhUA9wcx7fpsBgPVhYocrJxl51BmZW8CgYBN30wDppGK9RlvUEYl +meVobzDjaeHls12YuyiGSPzemQQ/X4gMnHMkDSBduSqaPxiWJ+Rih8F7dGJT/GEn +qHqRCZ228U2cVA9YBu5JdAfOVX4jzhb2ytxaYQF+yXG1TfbcNCmHaPZeIJOz2/Xk +CWxBF5WS6wG1c6Vqftgy7Q4CuAOBhQACgYEApu25HkB1b4gKMIV7aLGNSIknMzYg +rB7o1kQxeDf34dDVRM9OZ8tkumz6tl+iUcNe5EoxdsYV1IXSddjOi08LOLsZq7AQ +lNnKvbtlmMDULpqkZJD0bO7A29nisJfKy1URqABLw5DgfcPh1ZLXtmDfUgJvmjgT +mvTPT2j9TPjq7RWgADALBglghkgBZQMEAwIDMAAwLQIVAPA6/jxCT1D2HgzE4iZR +AEup/C7YAhRPLTQvQnAiS5FRrA+8SwBLvDAsaw== +-----END CERTIFICATE REQUEST----- +-----BEGIN CERTIFICATE----- +MIIDMDCCAu6gAwIBAgIBATALBglghkgBZQMEAwIwUzELMAkGA1UEBhMCQVUxEzAR +BgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5 +IEx0ZDEMMAoGA1UEAwwDUENBMCAXDTE2MDExMzIxNDE0OVoYDzMwMTUwNTE2MjE0 +MTQ5WjBTMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UE +CgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQwwCgYDVQQDDANQQ0EwggG3MIIB +KwYHKoZIzjgEATCCAR4CgYEApz9uhb9Bail98J9HGTCQmgkd2mozHsU9hpazFeBT +Lo/gWYJzkD51MZlHelL7heTZpns4m2iKhJuHxh61foZLU1tZz3FlGYhuzmaua4g2 +++wo3MLXpbvlLDkmS9qacBiVN5UQViP2Fe26BF7eOU/9t0MftaRlb82AEeRwlVtQ +zUkCFQD3BzHt+mwGA9WFihysnGXnUGZlbwKBgE3fTAOmkYr1GW9QRiWZ5WhvMONp +4eWzXZi7KIZI/N6ZBD9fiAyccyQNIF25Kpo/GJYn5GKHwXt0YlP8YSeoepEJnbbx +TZxUD1gG7kl0B85VfiPOFvbK3FphAX7JcbVN9tw0KYdo9l4gk7Pb9eQJbEEXlZLr +AbVzpWp+2DLtDgK4A4GFAAKBgQCm7bkeQHVviAowhXtosY1IiSczNiCsHujWRDF4 +N/fh0NVEz05ny2S6bPq2X6JRw17kSjF2xhXUhdJ12M6LTws4uxmrsBCU2cq9u2WY +wNQumqRkkPRs7sDb2eKwl8rLVRGoAEvDkOB9w+HVkte2YN9SAm+aOBOa9M9PaP1M ++OrtFaNQME4wHQYDVR0OBBYEFMaPAnfe6+NJrbRE2swpagam04t0MB8GA1UdIwQY +MBaAFMaPAnfe6+NJrbRE2swpagam04t0MAwGA1UdEwQFMAMBAf8wCwYJYIZIAWUD +BAMCAy8AMCwCFFhdz4fzQo9BBF20U1CHldYTi/D7AhQydDnDMj21y+U1UhDZJrvh +lnt88g== +-----END CERTIFICATE----- diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/dsa.c b/trunk/3rdparty/openssl-1.1-fit/apps/dsa.c new file mode 100644 index 000000000..6022e64cd --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/dsa.c @@ -0,0 +1,265 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#ifdef OPENSSL_NO_DSA +NON_EMPTY_TRANSLATION_UNIT +#else + +# include +# include +# include +# include +# include "apps.h" +# include "progs.h" +# include +# include +# include +# include +# include +# include +# include + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_ENGINE, + /* Do not change the order here; see case statements below */ + OPT_PVK_NONE, OPT_PVK_WEAK, OPT_PVK_STRONG, + OPT_NOOUT, OPT_TEXT, OPT_MODULUS, OPT_PUBIN, + OPT_PUBOUT, OPT_CIPHER, OPT_PASSIN, OPT_PASSOUT +} OPTION_CHOICE; + +const OPTIONS dsa_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"inform", OPT_INFORM, 'f', "Input format, DER PEM PVK"}, + {"outform", OPT_OUTFORM, 'f', "Output format, DER PEM PVK"}, + {"in", OPT_IN, 's', "Input key"}, + {"out", OPT_OUT, '>', "Output file"}, + {"noout", OPT_NOOUT, '-', "Don't print key out"}, + {"text", OPT_TEXT, '-', "Print the key in text"}, + {"modulus", OPT_MODULUS, '-', "Print the DSA public value"}, + {"pubin", OPT_PUBIN, '-', "Expect a public key in input file"}, + {"pubout", OPT_PUBOUT, '-', "Output public key, not private"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, + {"", OPT_CIPHER, '-', "Any supported cipher"}, +# ifndef OPENSSL_NO_RC4 + {"pvk-strong", OPT_PVK_STRONG, '-', "Enable 'Strong' PVK encoding level (default)"}, + {"pvk-weak", OPT_PVK_WEAK, '-', "Enable 'Weak' PVK encoding level"}, + {"pvk-none", OPT_PVK_NONE, '-', "Don't enforce PVK encoding"}, +# endif +# ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"}, +# endif + {NULL} +}; + +int dsa_main(int argc, char **argv) +{ + BIO *out = NULL; + DSA *dsa = NULL; + ENGINE *e = NULL; + const EVP_CIPHER *enc = NULL; + char *infile = NULL, *outfile = NULL, *prog; + char *passin = NULL, *passout = NULL, *passinarg = NULL, *passoutarg = NULL; + OPTION_CHOICE o; + int informat = FORMAT_PEM, outformat = FORMAT_PEM, text = 0, noout = 0; + int i, modulus = 0, pubin = 0, pubout = 0, ret = 1; +# ifndef OPENSSL_NO_RC4 + int pvk_encr = 2; +# endif + int private = 0; + + prog = opt_init(argc, argv, dsa_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + ret = 0; + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(dsa_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &outformat)) + goto opthelp; + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_PASSOUT: + passoutarg = opt_arg(); + break; + case OPT_PVK_STRONG: /* pvk_encr:= 2 */ + case OPT_PVK_WEAK: /* pvk_encr:= 1 */ + case OPT_PVK_NONE: /* pvk_encr:= 0 */ +#ifndef OPENSSL_NO_RC4 + pvk_encr = (o - OPT_PVK_NONE); +#endif + break; + case OPT_NOOUT: + noout = 1; + break; + case OPT_TEXT: + text = 1; + break; + case OPT_MODULUS: + modulus = 1; + break; + case OPT_PUBIN: + pubin = 1; + break; + case OPT_PUBOUT: + pubout = 1; + break; + case OPT_CIPHER: + if (!opt_cipher(opt_unknown(), &enc)) + goto end; + break; + } + } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + + private = pubin || pubout ? 0 : 1; + if (text && !pubin) + private = 1; + + if (!app_passwd(passinarg, passoutarg, &passin, &passout)) { + BIO_printf(bio_err, "Error getting passwords\n"); + goto end; + } + + BIO_printf(bio_err, "read DSA key\n"); + { + EVP_PKEY *pkey; + + if (pubin) + pkey = load_pubkey(infile, informat, 1, passin, e, "Public Key"); + else + pkey = load_key(infile, informat, 1, passin, e, "Private Key"); + + if (pkey != NULL) { + dsa = EVP_PKEY_get1_DSA(pkey); + EVP_PKEY_free(pkey); + } + } + if (dsa == NULL) { + BIO_printf(bio_err, "unable to load Key\n"); + ERR_print_errors(bio_err); + goto end; + } + + out = bio_open_owner(outfile, outformat, private); + if (out == NULL) + goto end; + + if (text) { + assert(pubin || private); + if (!DSA_print(out, dsa, 0)) { + perror(outfile); + ERR_print_errors(bio_err); + goto end; + } + } + + if (modulus) { + const BIGNUM *pub_key = NULL; + DSA_get0_key(dsa, &pub_key, NULL); + BIO_printf(out, "Public Key="); + BN_print(out, pub_key); + BIO_printf(out, "\n"); + } + + if (noout) { + ret = 0; + goto end; + } + BIO_printf(bio_err, "writing DSA key\n"); + if (outformat == FORMAT_ASN1) { + if (pubin || pubout) { + i = i2d_DSA_PUBKEY_bio(out, dsa); + } else { + assert(private); + i = i2d_DSAPrivateKey_bio(out, dsa); + } + } else if (outformat == FORMAT_PEM) { + if (pubin || pubout) { + i = PEM_write_bio_DSA_PUBKEY(out, dsa); + } else { + assert(private); + i = PEM_write_bio_DSAPrivateKey(out, dsa, enc, + NULL, 0, NULL, passout); + } +# ifndef OPENSSL_NO_RSA + } else if (outformat == FORMAT_MSBLOB || outformat == FORMAT_PVK) { + EVP_PKEY *pk; + pk = EVP_PKEY_new(); + if (pk == NULL) + goto end; + + EVP_PKEY_set1_DSA(pk, dsa); + if (outformat == FORMAT_PVK) { + if (pubin) { + BIO_printf(bio_err, "PVK form impossible with public key input\n"); + EVP_PKEY_free(pk); + goto end; + } + assert(private); +# ifdef OPENSSL_NO_RC4 + BIO_printf(bio_err, "PVK format not supported\n"); + EVP_PKEY_free(pk); + goto end; +# else + i = i2b_PVK_bio(out, pk, pvk_encr, 0, passout); +# endif + } else if (pubin || pubout) { + i = i2b_PublicKey_bio(out, pk); + } else { + assert(private); + i = i2b_PrivateKey_bio(out, pk); + } + EVP_PKEY_free(pk); +# endif + } else { + BIO_printf(bio_err, "bad output format specified for outfile\n"); + goto end; + } + if (i <= 0) { + BIO_printf(bio_err, "unable to write private key\n"); + ERR_print_errors(bio_err); + goto end; + } + ret = 0; + end: + BIO_free_all(out); + DSA_free(dsa); + release_engine(e); + OPENSSL_free(passin); + OPENSSL_free(passout); + return ret; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/dsa1024.pem b/trunk/3rdparty/openssl-1.1-fit/apps/dsa1024.pem new file mode 100644 index 000000000..082dec389 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/dsa1024.pem @@ -0,0 +1,9 @@ +-----BEGIN DSA PARAMETERS----- +MIIBHgKBgQCnP26Fv0FqKX3wn0cZMJCaCR3aajMexT2GlrMV4FMuj+BZgnOQPnUx +mUd6UvuF5NmmezibaIqEm4fGHrV+hktTW1nPcWUZiG7OZq5riDb77Cjcwtelu+Us +OSZL2ppwGJU3lRBWI/YV7boEXt45T/23Qx+1pGVvzYAR5HCVW1DNSQIVAPcHMe36 +bAYD1YWKHKycZedQZmVvAoGATd9MA6aRivUZb1BGJZnlaG8w42nh5bNdmLsohkj8 +3pkEP1+IDJxzJA0gXbkqmj8YlifkYofBe3RiU/xhJ6h6kQmdtvFNnFQPWAbuSXQH +zlV+I84W9srcWmEBfslxtU323DQph2j2XiCTs9v15AlsQReVkusBtXOlan7YMu0O +Arg= +-----END DSA PARAMETERS----- diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/dsa512.pem b/trunk/3rdparty/openssl-1.1-fit/apps/dsa512.pem new file mode 100644 index 000000000..5f86d1a6e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/dsa512.pem @@ -0,0 +1,6 @@ +-----BEGIN DSA PARAMETERS----- +MIGdAkEAnRtpjibb8isRcBmG9hnI+BnyGFOURgbQYlAzSwI8UjADizv5X9EkBk97 +TLqqQJv9luQ3M7stWtdaEUBmonZ9MQIVAPtT71C0QJIxVoZTeuiLIppJ+3GPAkEA +gz6I5cWJc847bAFJv7PHnwrqRJHlMKrZvltftxDXibeOdPvPKR7rqCxUUbgQ3qDO +L8wka5B33qJoplISogOdIA== +-----END DSA PARAMETERS----- diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/dsap.pem b/trunk/3rdparty/openssl-1.1-fit/apps/dsap.pem new file mode 100644 index 000000000..d4dfdb305 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/dsap.pem @@ -0,0 +1,6 @@ +-----BEGIN DSA PARAMETERS----- +MIGcAkEA+ZiKEvZmc9MtnaFZh4NiZ3oZS4J1PHvPrm9MXj5ntVheDPkdmBDTncya +GAJcMjwsyB/GvLDGd6yGCw/8eF+09wIVAK3VagOxGd/Q4Af5NbxR5FB7CXEjAkA2 +t/q7HgVLi0KeKvcDG8BRl3wuy7bCvpjgtWiJc/tpvcuzeuAayH89UofjAGueKjXD +ADiRffvSdhrNw5dkqdql +-----END DSA PARAMETERS----- diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/dsaparam.c b/trunk/3rdparty/openssl-1.1-fit/apps/dsaparam.c new file mode 100644 index 000000000..b227b76a3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/dsaparam.c @@ -0,0 +1,258 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#ifdef OPENSSL_NO_DSA +NON_EMPTY_TRANSLATION_UNIT +#else + +# include +# include +# include +# include +# include "apps.h" +# include "progs.h" +# include +# include +# include +# include +# include +# include + +static int dsa_cb(int p, int n, BN_GENCB *cb); + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_TEXT, OPT_C, + OPT_NOOUT, OPT_GENKEY, OPT_ENGINE, OPT_R_ENUM +} OPTION_CHOICE; + +const OPTIONS dsaparam_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"}, + {"in", OPT_IN, '<', "Input file"}, + {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"}, + {"out", OPT_OUT, '>', "Output file"}, + {"text", OPT_TEXT, '-', "Print as text"}, + {"C", OPT_C, '-', "Output C code"}, + {"noout", OPT_NOOUT, '-', "No output"}, + {"genkey", OPT_GENKEY, '-', "Generate a DSA key"}, + OPT_R_OPTIONS, +# ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"}, +# endif + {NULL} +}; + +int dsaparam_main(int argc, char **argv) +{ + ENGINE *e = NULL; + DSA *dsa = NULL; + BIO *in = NULL, *out = NULL; + BN_GENCB *cb = NULL; + int numbits = -1, num = 0, genkey = 0; + int informat = FORMAT_PEM, outformat = FORMAT_PEM, noout = 0, C = 0; + int ret = 1, i, text = 0, private = 0; + char *infile = NULL, *outfile = NULL, *prog; + OPTION_CHOICE o; + + prog = opt_init(argc, argv, dsaparam_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(dsaparam_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) + goto opthelp; + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_TEXT: + text = 1; + break; + case OPT_C: + C = 1; + break; + case OPT_GENKEY: + genkey = 1; + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_NOOUT: + noout = 1; + break; + } + } + argc = opt_num_rest(); + argv = opt_rest(); + + if (argc == 1) { + if (!opt_int(argv[0], &num) || num < 0) + goto end; + /* generate a key */ + numbits = num; + } + private = genkey ? 1 : 0; + + in = bio_open_default(infile, 'r', informat); + if (in == NULL) + goto end; + out = bio_open_owner(outfile, outformat, private); + if (out == NULL) + goto end; + + if (numbits > 0) { + if (numbits > OPENSSL_DSA_MAX_MODULUS_BITS) + BIO_printf(bio_err, + "Warning: It is not recommended to use more than %d bit for DSA keys.\n" + " Your key size is %d! Larger key size may behave not as expected.\n", + OPENSSL_DSA_MAX_MODULUS_BITS, numbits); + + cb = BN_GENCB_new(); + if (cb == NULL) { + BIO_printf(bio_err, "Error allocating BN_GENCB object\n"); + goto end; + } + BN_GENCB_set(cb, dsa_cb, bio_err); + dsa = DSA_new(); + if (dsa == NULL) { + BIO_printf(bio_err, "Error allocating DSA object\n"); + goto end; + } + BIO_printf(bio_err, "Generating DSA parameters, %d bit long prime\n", + num); + BIO_printf(bio_err, "This could take some time\n"); + if (!DSA_generate_parameters_ex(dsa, num, NULL, 0, NULL, NULL, cb)) { + ERR_print_errors(bio_err); + BIO_printf(bio_err, "Error, DSA key generation failed\n"); + goto end; + } + } else if (informat == FORMAT_ASN1) { + dsa = d2i_DSAparams_bio(in, NULL); + } else { + dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL); + } + if (dsa == NULL) { + BIO_printf(bio_err, "unable to load DSA parameters\n"); + ERR_print_errors(bio_err); + goto end; + } + + if (text) { + DSAparams_print(out, dsa); + } + + if (C) { + const BIGNUM *p = NULL, *q = NULL, *g = NULL; + unsigned char *data; + int len, bits_p; + + DSA_get0_pqg(dsa, &p, &q, &g); + len = BN_num_bytes(p); + bits_p = BN_num_bits(p); + + data = app_malloc(len + 20, "BN space"); + + BIO_printf(bio_out, "static DSA *get_dsa%d(void)\n{\n", bits_p); + print_bignum_var(bio_out, p, "dsap", bits_p, data); + print_bignum_var(bio_out, q, "dsaq", bits_p, data); + print_bignum_var(bio_out, g, "dsag", bits_p, data); + BIO_printf(bio_out, " DSA *dsa = DSA_new();\n" + " BIGNUM *p, *q, *g;\n" + "\n"); + BIO_printf(bio_out, " if (dsa == NULL)\n" + " return NULL;\n"); + BIO_printf(bio_out, " if (!DSA_set0_pqg(dsa, p = BN_bin2bn(dsap_%d, sizeof(dsap_%d), NULL),\n", + bits_p, bits_p); + BIO_printf(bio_out, " q = BN_bin2bn(dsaq_%d, sizeof(dsaq_%d), NULL),\n", + bits_p, bits_p); + BIO_printf(bio_out, " g = BN_bin2bn(dsag_%d, sizeof(dsag_%d), NULL))) {\n", + bits_p, bits_p); + BIO_printf(bio_out, " DSA_free(dsa);\n" + " BN_free(p);\n" + " BN_free(q);\n" + " BN_free(g);\n" + " return NULL;\n" + " }\n" + " return dsa;\n}\n"); + OPENSSL_free(data); + } + + if (outformat == FORMAT_ASN1 && genkey) + noout = 1; + + if (!noout) { + if (outformat == FORMAT_ASN1) + i = i2d_DSAparams_bio(out, dsa); + else + i = PEM_write_bio_DSAparams(out, dsa); + if (!i) { + BIO_printf(bio_err, "unable to write DSA parameters\n"); + ERR_print_errors(bio_err); + goto end; + } + } + if (genkey) { + DSA *dsakey; + + if ((dsakey = DSAparams_dup(dsa)) == NULL) + goto end; + if (!DSA_generate_key(dsakey)) { + ERR_print_errors(bio_err); + DSA_free(dsakey); + goto end; + } + assert(private); + if (outformat == FORMAT_ASN1) + i = i2d_DSAPrivateKey_bio(out, dsakey); + else + i = PEM_write_bio_DSAPrivateKey(out, dsakey, NULL, NULL, 0, NULL, + NULL); + DSA_free(dsakey); + } + ret = 0; + end: + BN_GENCB_free(cb); + BIO_free(in); + BIO_free_all(out); + DSA_free(dsa); + release_engine(e); + return ret; +} + +static int dsa_cb(int p, int n, BN_GENCB *cb) +{ + static const char symbols[] = ".+*\n"; + char c = (p >= 0 && (size_t)p < sizeof(symbols) - 1) ? symbols[p] : '?'; + + BIO_write(BN_GENCB_get_arg(cb), &c, 1); + (void)BIO_flush(BN_GENCB_get_arg(cb)); + return 1; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/ec.c b/trunk/3rdparty/openssl-1.1-fit/apps/ec.c new file mode 100644 index 000000000..03abb0068 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/ec.c @@ -0,0 +1,283 @@ +/* + * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#ifdef OPENSSL_NO_EC +NON_EMPTY_TRANSLATION_UNIT +#else + +# include +# include +# include +# include "apps.h" +# include "progs.h" +# include +# include +# include +# include + +static OPT_PAIR conv_forms[] = { + {"compressed", POINT_CONVERSION_COMPRESSED}, + {"uncompressed", POINT_CONVERSION_UNCOMPRESSED}, + {"hybrid", POINT_CONVERSION_HYBRID}, + {NULL} +}; + +static OPT_PAIR param_enc[] = { + {"named_curve", OPENSSL_EC_NAMED_CURVE}, + {"explicit", 0}, + {NULL} +}; + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_IN, OPT_OUT, + OPT_NOOUT, OPT_TEXT, OPT_PARAM_OUT, OPT_PUBIN, OPT_PUBOUT, + OPT_PASSIN, OPT_PASSOUT, OPT_PARAM_ENC, OPT_CONV_FORM, OPT_CIPHER, + OPT_NO_PUBLIC, OPT_CHECK +} OPTION_CHOICE; + +const OPTIONS ec_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"in", OPT_IN, 's', "Input file"}, + {"inform", OPT_INFORM, 'f', "Input format - DER or PEM"}, + {"out", OPT_OUT, '>', "Output file"}, + {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"}, + {"noout", OPT_NOOUT, '-', "Don't print key out"}, + {"text", OPT_TEXT, '-', "Print the key"}, + {"param_out", OPT_PARAM_OUT, '-', "Print the elliptic curve parameters"}, + {"pubin", OPT_PUBIN, '-', "Expect a public key in input file"}, + {"pubout", OPT_PUBOUT, '-', "Output public key, not private"}, + {"no_public", OPT_NO_PUBLIC, '-', "exclude public key from private key"}, + {"check", OPT_CHECK, '-', "check key consistency"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, + {"param_enc", OPT_PARAM_ENC, 's', + "Specifies the way the ec parameters are encoded"}, + {"conv_form", OPT_CONV_FORM, 's', "Specifies the point conversion form "}, + {"", OPT_CIPHER, '-', "Any supported cipher"}, +# ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +# endif + {NULL} +}; + +int ec_main(int argc, char **argv) +{ + BIO *in = NULL, *out = NULL; + ENGINE *e = NULL; + EC_KEY *eckey = NULL; + const EC_GROUP *group; + const EVP_CIPHER *enc = NULL; + point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED; + char *infile = NULL, *outfile = NULL, *prog; + char *passin = NULL, *passout = NULL, *passinarg = NULL, *passoutarg = NULL; + OPTION_CHOICE o; + int asn1_flag = OPENSSL_EC_NAMED_CURVE, new_form = 0, new_asn1_flag = 0; + int informat = FORMAT_PEM, outformat = FORMAT_PEM, text = 0, noout = 0; + int pubin = 0, pubout = 0, param_out = 0, i, ret = 1, private = 0; + int no_public = 0, check = 0; + + prog = opt_init(argc, argv, ec_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(ec_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) + goto opthelp; + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_NOOUT: + noout = 1; + break; + case OPT_TEXT: + text = 1; + break; + case OPT_PARAM_OUT: + param_out = 1; + break; + case OPT_PUBIN: + pubin = 1; + break; + case OPT_PUBOUT: + pubout = 1; + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_PASSOUT: + passoutarg = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_CIPHER: + if (!opt_cipher(opt_unknown(), &enc)) + goto opthelp; + break; + case OPT_CONV_FORM: + if (!opt_pair(opt_arg(), conv_forms, &i)) + goto opthelp; + new_form = 1; + form = i; + break; + case OPT_PARAM_ENC: + if (!opt_pair(opt_arg(), param_enc, &i)) + goto opthelp; + new_asn1_flag = 1; + asn1_flag = i; + break; + case OPT_NO_PUBLIC: + no_public = 1; + break; + case OPT_CHECK: + check = 1; + break; + } + } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + + private = param_out || pubin || pubout ? 0 : 1; + if (text && !pubin) + private = 1; + + if (!app_passwd(passinarg, passoutarg, &passin, &passout)) { + BIO_printf(bio_err, "Error getting passwords\n"); + goto end; + } + + if (informat != FORMAT_ENGINE) { + in = bio_open_default(infile, 'r', informat); + if (in == NULL) + goto end; + } + + BIO_printf(bio_err, "read EC key\n"); + if (informat == FORMAT_ASN1) { + if (pubin) + eckey = d2i_EC_PUBKEY_bio(in, NULL); + else + eckey = d2i_ECPrivateKey_bio(in, NULL); + } else if (informat == FORMAT_ENGINE) { + EVP_PKEY *pkey; + if (pubin) + pkey = load_pubkey(infile, informat, 1, passin, e, "Public Key"); + else + pkey = load_key(infile, informat, 1, passin, e, "Private Key"); + if (pkey != NULL) { + eckey = EVP_PKEY_get1_EC_KEY(pkey); + EVP_PKEY_free(pkey); + } + } else { + if (pubin) + eckey = PEM_read_bio_EC_PUBKEY(in, NULL, NULL, NULL); + else + eckey = PEM_read_bio_ECPrivateKey(in, NULL, NULL, passin); + } + if (eckey == NULL) { + BIO_printf(bio_err, "unable to load Key\n"); + ERR_print_errors(bio_err); + goto end; + } + + out = bio_open_owner(outfile, outformat, private); + if (out == NULL) + goto end; + + group = EC_KEY_get0_group(eckey); + + if (new_form) + EC_KEY_set_conv_form(eckey, form); + + if (new_asn1_flag) + EC_KEY_set_asn1_flag(eckey, asn1_flag); + + if (no_public) + EC_KEY_set_enc_flags(eckey, EC_PKEY_NO_PUBKEY); + + if (text) { + assert(pubin || private); + if (!EC_KEY_print(out, eckey, 0)) { + perror(outfile); + ERR_print_errors(bio_err); + goto end; + } + } + + if (check) { + if (EC_KEY_check_key(eckey) == 1) { + BIO_printf(bio_err, "EC Key valid.\n"); + } else { + BIO_printf(bio_err, "EC Key Invalid!\n"); + ERR_print_errors(bio_err); + } + } + + if (noout) { + ret = 0; + goto end; + } + + BIO_printf(bio_err, "writing EC key\n"); + if (outformat == FORMAT_ASN1) { + if (param_out) { + i = i2d_ECPKParameters_bio(out, group); + } else if (pubin || pubout) { + i = i2d_EC_PUBKEY_bio(out, eckey); + } else { + assert(private); + i = i2d_ECPrivateKey_bio(out, eckey); + } + } else { + if (param_out) { + i = PEM_write_bio_ECPKParameters(out, group); + } else if (pubin || pubout) { + i = PEM_write_bio_EC_PUBKEY(out, eckey); + } else { + assert(private); + i = PEM_write_bio_ECPrivateKey(out, eckey, enc, + NULL, 0, NULL, passout); + } + } + + if (!i) { + BIO_printf(bio_err, "unable to write private key\n"); + ERR_print_errors(bio_err); + } else { + ret = 0; + } + end: + BIO_free(in); + BIO_free_all(out); + EC_KEY_free(eckey); + release_engine(e); + OPENSSL_free(passin); + OPENSSL_free(passout); + return ret; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/ecparam.c b/trunk/3rdparty/openssl-1.1-fit/apps/ecparam.c new file mode 100644 index 000000000..917f1a86b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/ecparam.c @@ -0,0 +1,450 @@ +/* + * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#ifdef OPENSSL_NO_EC +NON_EMPTY_TRANSLATION_UNIT +#else + +# include +# include +# include +# include +# include "apps.h" +# include "progs.h" +# include +# include +# include +# include +# include +# include + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_TEXT, OPT_C, + OPT_CHECK, OPT_LIST_CURVES, OPT_NO_SEED, OPT_NOOUT, OPT_NAME, + OPT_CONV_FORM, OPT_PARAM_ENC, OPT_GENKEY, OPT_ENGINE, + OPT_R_ENUM +} OPTION_CHOICE; + +const OPTIONS ecparam_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"inform", OPT_INFORM, 'F', "Input format - default PEM (DER or PEM)"}, + {"outform", OPT_OUTFORM, 'F', "Output format - default PEM"}, + {"in", OPT_IN, '<', "Input file - default stdin"}, + {"out", OPT_OUT, '>', "Output file - default stdout"}, + {"text", OPT_TEXT, '-', "Print the ec parameters in text form"}, + {"C", OPT_C, '-', "Print a 'C' function creating the parameters"}, + {"check", OPT_CHECK, '-', "Validate the ec parameters"}, + {"list_curves", OPT_LIST_CURVES, '-', + "Prints a list of all curve 'short names'"}, + {"no_seed", OPT_NO_SEED, '-', + "If 'explicit' parameters are chosen do not use the seed"}, + {"noout", OPT_NOOUT, '-', "Do not print the ec parameter"}, + {"name", OPT_NAME, 's', + "Use the ec parameters with specified 'short name'"}, + {"conv_form", OPT_CONV_FORM, 's', "Specifies the point conversion form "}, + {"param_enc", OPT_PARAM_ENC, 's', + "Specifies the way the ec parameters are encoded"}, + {"genkey", OPT_GENKEY, '-', "Generate ec key"}, + OPT_R_OPTIONS, +# ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +# endif + {NULL} +}; + +static OPT_PAIR forms[] = { + {"compressed", POINT_CONVERSION_COMPRESSED}, + {"uncompressed", POINT_CONVERSION_UNCOMPRESSED}, + {"hybrid", POINT_CONVERSION_HYBRID}, + {NULL} +}; + +static OPT_PAIR encodings[] = { + {"named_curve", OPENSSL_EC_NAMED_CURVE}, + {"explicit", 0}, + {NULL} +}; + +int ecparam_main(int argc, char **argv) +{ + ENGINE *e = NULL; + BIGNUM *ec_gen = NULL, *ec_order = NULL, *ec_cofactor = NULL; + BIGNUM *ec_p = NULL, *ec_a = NULL, *ec_b = NULL; + BIO *in = NULL, *out = NULL; + EC_GROUP *group = NULL; + point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED; + char *curve_name = NULL; + char *infile = NULL, *outfile = NULL, *prog; + unsigned char *buffer = NULL; + OPTION_CHOICE o; + int asn1_flag = OPENSSL_EC_NAMED_CURVE, new_asn1_flag = 0; + int informat = FORMAT_PEM, outformat = FORMAT_PEM, noout = 0, C = 0; + int ret = 1, private = 0; + int list_curves = 0, no_seed = 0, check = 0, new_form = 0; + int text = 0, i, genkey = 0; + + prog = opt_init(argc, argv, ecparam_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(ecparam_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) + goto opthelp; + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_TEXT: + text = 1; + break; + case OPT_C: + C = 1; + break; + case OPT_CHECK: + check = 1; + break; + case OPT_LIST_CURVES: + list_curves = 1; + break; + case OPT_NO_SEED: + no_seed = 1; + break; + case OPT_NOOUT: + noout = 1; + break; + case OPT_NAME: + curve_name = opt_arg(); + break; + case OPT_CONV_FORM: + if (!opt_pair(opt_arg(), forms, &new_form)) + goto opthelp; + form = new_form; + new_form = 1; + break; + case OPT_PARAM_ENC: + if (!opt_pair(opt_arg(), encodings, &asn1_flag)) + goto opthelp; + new_asn1_flag = 1; + break; + case OPT_GENKEY: + genkey = 1; + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + } + } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + + private = genkey ? 1 : 0; + + in = bio_open_default(infile, 'r', informat); + if (in == NULL) + goto end; + out = bio_open_owner(outfile, outformat, private); + if (out == NULL) + goto end; + + if (list_curves) { + EC_builtin_curve *curves = NULL; + size_t crv_len = EC_get_builtin_curves(NULL, 0); + size_t n; + + curves = app_malloc((int)sizeof(*curves) * crv_len, "list curves"); + if (!EC_get_builtin_curves(curves, crv_len)) { + OPENSSL_free(curves); + goto end; + } + + for (n = 0; n < crv_len; n++) { + const char *comment; + const char *sname; + comment = curves[n].comment; + sname = OBJ_nid2sn(curves[n].nid); + if (comment == NULL) + comment = "CURVE DESCRIPTION NOT AVAILABLE"; + if (sname == NULL) + sname = ""; + + BIO_printf(out, " %-10s: ", sname); + BIO_printf(out, "%s\n", comment); + } + + OPENSSL_free(curves); + ret = 0; + goto end; + } + + if (curve_name != NULL) { + int nid; + + /* + * workaround for the SECG curve names secp192r1 and secp256r1 (which + * are the same as the curves prime192v1 and prime256v1 defined in + * X9.62) + */ + if (strcmp(curve_name, "secp192r1") == 0) { + BIO_printf(bio_err, "using curve name prime192v1 " + "instead of secp192r1\n"); + nid = NID_X9_62_prime192v1; + } else if (strcmp(curve_name, "secp256r1") == 0) { + BIO_printf(bio_err, "using curve name prime256v1 " + "instead of secp256r1\n"); + nid = NID_X9_62_prime256v1; + } else { + nid = OBJ_sn2nid(curve_name); + } + + if (nid == 0) + nid = EC_curve_nist2nid(curve_name); + + if (nid == 0) { + BIO_printf(bio_err, "unknown curve name (%s)\n", curve_name); + goto end; + } + + group = EC_GROUP_new_by_curve_name(nid); + if (group == NULL) { + BIO_printf(bio_err, "unable to create curve (%s)\n", curve_name); + goto end; + } + EC_GROUP_set_asn1_flag(group, asn1_flag); + EC_GROUP_set_point_conversion_form(group, form); + } else if (informat == FORMAT_ASN1) { + group = d2i_ECPKParameters_bio(in, NULL); + } else { + group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL); + } + if (group == NULL) { + BIO_printf(bio_err, "unable to load elliptic curve parameters\n"); + ERR_print_errors(bio_err); + goto end; + } + + if (new_form) + EC_GROUP_set_point_conversion_form(group, form); + + if (new_asn1_flag) + EC_GROUP_set_asn1_flag(group, asn1_flag); + + if (no_seed) { + EC_GROUP_set_seed(group, NULL, 0); + } + + if (text) { + if (!ECPKParameters_print(out, group, 0)) + goto end; + } + + if (check) { + BIO_printf(bio_err, "checking elliptic curve parameters: "); + if (!EC_GROUP_check(group, NULL)) { + BIO_printf(bio_err, "failed\n"); + ERR_print_errors(bio_err); + goto end; + } + BIO_printf(bio_err, "ok\n"); + + } + + if (C) { + size_t buf_len = 0, tmp_len = 0; + const EC_POINT *point; + int is_prime, len = 0; + const EC_METHOD *meth = EC_GROUP_method_of(group); + + if ((ec_p = BN_new()) == NULL + || (ec_a = BN_new()) == NULL + || (ec_b = BN_new()) == NULL + || (ec_gen = BN_new()) == NULL + || (ec_order = BN_new()) == NULL + || (ec_cofactor = BN_new()) == NULL) { + perror("Can't allocate BN"); + goto end; + } + + is_prime = (EC_METHOD_get_field_type(meth) == NID_X9_62_prime_field); + if (!is_prime) { + BIO_printf(bio_err, "Can only handle X9.62 prime fields\n"); + goto end; + } + + if (!EC_GROUP_get_curve(group, ec_p, ec_a, ec_b, NULL)) + goto end; + + if ((point = EC_GROUP_get0_generator(group)) == NULL) + goto end; + if (!EC_POINT_point2bn(group, point, + EC_GROUP_get_point_conversion_form(group), + ec_gen, NULL)) + goto end; + if (!EC_GROUP_get_order(group, ec_order, NULL)) + goto end; + if (!EC_GROUP_get_cofactor(group, ec_cofactor, NULL)) + goto end; + + if (!ec_p || !ec_a || !ec_b || !ec_gen || !ec_order || !ec_cofactor) + goto end; + + len = BN_num_bits(ec_order); + + if ((tmp_len = (size_t)BN_num_bytes(ec_p)) > buf_len) + buf_len = tmp_len; + if ((tmp_len = (size_t)BN_num_bytes(ec_a)) > buf_len) + buf_len = tmp_len; + if ((tmp_len = (size_t)BN_num_bytes(ec_b)) > buf_len) + buf_len = tmp_len; + if ((tmp_len = (size_t)BN_num_bytes(ec_gen)) > buf_len) + buf_len = tmp_len; + if ((tmp_len = (size_t)BN_num_bytes(ec_order)) > buf_len) + buf_len = tmp_len; + if ((tmp_len = (size_t)BN_num_bytes(ec_cofactor)) > buf_len) + buf_len = tmp_len; + + buffer = app_malloc(buf_len, "BN buffer"); + + BIO_printf(out, "EC_GROUP *get_ec_group_%d(void)\n{\n", len); + print_bignum_var(out, ec_p, "ec_p", len, buffer); + print_bignum_var(out, ec_a, "ec_a", len, buffer); + print_bignum_var(out, ec_b, "ec_b", len, buffer); + print_bignum_var(out, ec_gen, "ec_gen", len, buffer); + print_bignum_var(out, ec_order, "ec_order", len, buffer); + print_bignum_var(out, ec_cofactor, "ec_cofactor", len, buffer); + BIO_printf(out, " int ok = 0;\n" + " EC_GROUP *group = NULL;\n" + " EC_POINT *point = NULL;\n" + " BIGNUM *tmp_1 = NULL;\n" + " BIGNUM *tmp_2 = NULL;\n" + " BIGNUM *tmp_3 = NULL;\n" + "\n"); + + BIO_printf(out, " if ((tmp_1 = BN_bin2bn(ec_p_%d, sizeof(ec_p_%d), NULL)) == NULL)\n" + " goto err;\n", len, len); + BIO_printf(out, " if ((tmp_2 = BN_bin2bn(ec_a_%d, sizeof(ec_a_%d), NULL)) == NULL)\n" + " goto err;\n", len, len); + BIO_printf(out, " if ((tmp_3 = BN_bin2bn(ec_b_%d, sizeof(ec_b_%d), NULL)) == NULL)\n" + " goto err;\n", len, len); + BIO_printf(out, " if ((group = EC_GROUP_new_curve_GFp(tmp_1, tmp_2, tmp_3, NULL)) == NULL)\n" + " goto err;\n" + "\n"); + BIO_printf(out, " /* build generator */\n"); + BIO_printf(out, " if ((tmp_1 = BN_bin2bn(ec_gen_%d, sizeof(ec_gen_%d), tmp_1)) == NULL)\n" + " goto err;\n", len, len); + BIO_printf(out, " point = EC_POINT_bn2point(group, tmp_1, NULL, NULL);\n"); + BIO_printf(out, " if (point == NULL)\n" + " goto err;\n"); + BIO_printf(out, " if ((tmp_2 = BN_bin2bn(ec_order_%d, sizeof(ec_order_%d), tmp_2)) == NULL)\n" + " goto err;\n", len, len); + BIO_printf(out, " if ((tmp_3 = BN_bin2bn(ec_cofactor_%d, sizeof(ec_cofactor_%d), tmp_3)) == NULL)\n" + " goto err;\n", len, len); + BIO_printf(out, " if (!EC_GROUP_set_generator(group, point, tmp_2, tmp_3))\n" + " goto err;\n" + "ok = 1;" + "\n"); + BIO_printf(out, "err:\n" + " BN_free(tmp_1);\n" + " BN_free(tmp_2);\n" + " BN_free(tmp_3);\n" + " EC_POINT_free(point);\n" + " if (!ok) {\n" + " EC_GROUP_free(group);\n" + " return NULL;\n" + " }\n" + " return (group);\n" + "}\n"); + } + + if (outformat == FORMAT_ASN1 && genkey) + noout = 1; + + if (!noout) { + if (outformat == FORMAT_ASN1) + i = i2d_ECPKParameters_bio(out, group); + else + i = PEM_write_bio_ECPKParameters(out, group); + if (!i) { + BIO_printf(bio_err, "unable to write elliptic " + "curve parameters\n"); + ERR_print_errors(bio_err); + goto end; + } + } + + if (genkey) { + EC_KEY *eckey = EC_KEY_new(); + + if (eckey == NULL) + goto end; + + if (EC_KEY_set_group(eckey, group) == 0) { + BIO_printf(bio_err, "unable to set group when generating key\n"); + EC_KEY_free(eckey); + ERR_print_errors(bio_err); + goto end; + } + + if (new_form) + EC_KEY_set_conv_form(eckey, form); + + if (!EC_KEY_generate_key(eckey)) { + BIO_printf(bio_err, "unable to generate key\n"); + EC_KEY_free(eckey); + ERR_print_errors(bio_err); + goto end; + } + assert(private); + if (outformat == FORMAT_ASN1) + i = i2d_ECPrivateKey_bio(out, eckey); + else + i = PEM_write_bio_ECPrivateKey(out, eckey, NULL, + NULL, 0, NULL, NULL); + EC_KEY_free(eckey); + } + + ret = 0; + end: + BN_free(ec_p); + BN_free(ec_a); + BN_free(ec_b); + BN_free(ec_gen); + BN_free(ec_order); + BN_free(ec_cofactor); + OPENSSL_free(buffer); + EC_GROUP_free(group); + release_engine(e); + BIO_free(in); + BIO_free_all(out); + return ret; +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/enc.c b/trunk/3rdparty/openssl-1.1-fit/apps/enc.c new file mode 100644 index 000000000..8e5a57d3e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/enc.c @@ -0,0 +1,675 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include +#include +#include +#include +#ifndef OPENSSL_NO_COMP +# include +#endif +#include + +#undef SIZE +#undef BSIZE +#define SIZE (512) +#define BSIZE (8*1024) + +static int set_hex(const char *in, unsigned char *out, int size); +static void show_ciphers(const OBJ_NAME *name, void *bio_); + +struct doall_enc_ciphers { + BIO *bio; + int n; +}; + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_LIST, + OPT_E, OPT_IN, OPT_OUT, OPT_PASS, OPT_ENGINE, OPT_D, OPT_P, OPT_V, + OPT_NOPAD, OPT_SALT, OPT_NOSALT, OPT_DEBUG, OPT_UPPER_P, OPT_UPPER_A, + OPT_A, OPT_Z, OPT_BUFSIZE, OPT_K, OPT_KFILE, OPT_UPPER_K, OPT_NONE, + OPT_UPPER_S, OPT_IV, OPT_MD, OPT_ITER, OPT_PBKDF2, OPT_CIPHER, + OPT_R_ENUM +} OPTION_CHOICE; + +const OPTIONS enc_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"ciphers", OPT_LIST, '-', "List ciphers"}, + {"in", OPT_IN, '<', "Input file"}, + {"out", OPT_OUT, '>', "Output file"}, + {"pass", OPT_PASS, 's', "Passphrase source"}, + {"e", OPT_E, '-', "Encrypt"}, + {"d", OPT_D, '-', "Decrypt"}, + {"p", OPT_P, '-', "Print the iv/key"}, + {"P", OPT_UPPER_P, '-', "Print the iv/key and exit"}, + {"v", OPT_V, '-', "Verbose output"}, + {"nopad", OPT_NOPAD, '-', "Disable standard block padding"}, + {"salt", OPT_SALT, '-', "Use salt in the KDF (default)"}, + {"nosalt", OPT_NOSALT, '-', "Do not use salt in the KDF"}, + {"debug", OPT_DEBUG, '-', "Print debug info"}, + {"a", OPT_A, '-', "Base64 encode/decode, depending on encryption flag"}, + {"base64", OPT_A, '-', "Same as option -a"}, + {"A", OPT_UPPER_A, '-', + "Used with -[base64|a] to specify base64 buffer as a single line"}, + {"bufsize", OPT_BUFSIZE, 's', "Buffer size"}, + {"k", OPT_K, 's', "Passphrase"}, + {"kfile", OPT_KFILE, '<', "Read passphrase from file"}, + {"K", OPT_UPPER_K, 's', "Raw key, in hex"}, + {"S", OPT_UPPER_S, 's', "Salt, in hex"}, + {"iv", OPT_IV, 's', "IV in hex"}, + {"md", OPT_MD, 's', "Use specified digest to create a key from the passphrase"}, + {"iter", OPT_ITER, 'p', "Specify the iteration count and force use of PBKDF2"}, + {"pbkdf2", OPT_PBKDF2, '-', "Use password-based key derivation function 2"}, + {"none", OPT_NONE, '-', "Don't encrypt"}, + {"", OPT_CIPHER, '-', "Any supported cipher"}, + OPT_R_OPTIONS, +#ifdef ZLIB + {"z", OPT_Z, '-', "Use zlib as the 'encryption'"}, +#endif +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + {NULL} +}; + +int enc_main(int argc, char **argv) +{ + static char buf[128]; + static const char magic[] = "Salted__"; + ENGINE *e = NULL; + BIO *in = NULL, *out = NULL, *b64 = NULL, *benc = NULL, *rbio = + NULL, *wbio = NULL; + EVP_CIPHER_CTX *ctx = NULL; + const EVP_CIPHER *cipher = NULL, *c; + const EVP_MD *dgst = NULL; + char *hkey = NULL, *hiv = NULL, *hsalt = NULL, *p; + char *infile = NULL, *outfile = NULL, *prog; + char *str = NULL, *passarg = NULL, *pass = NULL, *strbuf = NULL; + char mbuf[sizeof(magic) - 1]; + OPTION_CHOICE o; + int bsize = BSIZE, verbose = 0, debug = 0, olb64 = 0, nosalt = 0; + int enc = 1, printkey = 0, i, k; + int base64 = 0, informat = FORMAT_BINARY, outformat = FORMAT_BINARY; + int ret = 1, inl, nopad = 0; + unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH]; + unsigned char *buff = NULL, salt[PKCS5_SALT_LEN]; + int pbkdf2 = 0; + int iter = 0; + long n; + struct doall_enc_ciphers dec; +#ifdef ZLIB + int do_zlib = 0; + BIO *bzl = NULL; +#endif + + /* first check the program name */ + prog = opt_progname(argv[0]); + if (strcmp(prog, "base64") == 0) { + base64 = 1; +#ifdef ZLIB + } else if (strcmp(prog, "zlib") == 0) { + do_zlib = 1; +#endif + } else { + cipher = EVP_get_cipherbyname(prog); + if (cipher == NULL && strcmp(prog, "enc") != 0) { + BIO_printf(bio_err, "%s is not a known cipher\n", prog); + goto end; + } + } + + prog = opt_init(argc, argv, enc_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(enc_options); + ret = 0; + goto end; + case OPT_LIST: + BIO_printf(bio_out, "Supported ciphers:\n"); + dec.bio = bio_out; + dec.n = 0; + OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, + show_ciphers, &dec); + BIO_printf(bio_out, "\n"); + ret = 0; + goto end; + case OPT_E: + enc = 1; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_PASS: + passarg = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_D: + enc = 0; + break; + case OPT_P: + printkey = 1; + break; + case OPT_V: + verbose = 1; + break; + case OPT_NOPAD: + nopad = 1; + break; + case OPT_SALT: + nosalt = 0; + break; + case OPT_NOSALT: + nosalt = 1; + break; + case OPT_DEBUG: + debug = 1; + break; + case OPT_UPPER_P: + printkey = 2; + break; + case OPT_UPPER_A: + olb64 = 1; + break; + case OPT_A: + base64 = 1; + break; + case OPT_Z: +#ifdef ZLIB + do_zlib = 1; +#endif + break; + case OPT_BUFSIZE: + p = opt_arg(); + i = (int)strlen(p) - 1; + k = i >= 1 && p[i] == 'k'; + if (k) + p[i] = '\0'; + if (!opt_long(opt_arg(), &n) + || n < 0 || (k && n >= LONG_MAX / 1024)) + goto opthelp; + if (k) + n *= 1024; + bsize = (int)n; + break; + case OPT_K: + str = opt_arg(); + break; + case OPT_KFILE: + in = bio_open_default(opt_arg(), 'r', FORMAT_TEXT); + if (in == NULL) + goto opthelp; + i = BIO_gets(in, buf, sizeof(buf)); + BIO_free(in); + in = NULL; + if (i <= 0) { + BIO_printf(bio_err, + "%s Can't read key from %s\n", prog, opt_arg()); + goto opthelp; + } + while (--i > 0 && (buf[i] == '\r' || buf[i] == '\n')) + buf[i] = '\0'; + if (i <= 0) { + BIO_printf(bio_err, "%s: zero length password\n", prog); + goto opthelp; + } + str = buf; + break; + case OPT_UPPER_K: + hkey = opt_arg(); + break; + case OPT_UPPER_S: + hsalt = opt_arg(); + break; + case OPT_IV: + hiv = opt_arg(); + break; + case OPT_MD: + if (!opt_md(opt_arg(), &dgst)) + goto opthelp; + break; + case OPT_CIPHER: + if (!opt_cipher(opt_unknown(), &c)) + goto opthelp; + cipher = c; + break; + case OPT_ITER: + if (!opt_int(opt_arg(), &iter)) + goto opthelp; + pbkdf2 = 1; + break; + case OPT_PBKDF2: + pbkdf2 = 1; + if (iter == 0) /* do not overwrite a chosen value */ + iter = 10000; + break; + case OPT_NONE: + cipher = NULL; + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + } + } + if (opt_num_rest() != 0) { + BIO_printf(bio_err, "Extra arguments given.\n"); + goto opthelp; + } + + if (cipher && EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) { + BIO_printf(bio_err, "%s: AEAD ciphers not supported\n", prog); + goto end; + } + + if (cipher && (EVP_CIPHER_mode(cipher) == EVP_CIPH_XTS_MODE)) { + BIO_printf(bio_err, "%s XTS ciphers not supported\n", prog); + goto end; + } + + if (dgst == NULL) + dgst = EVP_sha256(); + + if (iter == 0) + iter = 1; + + /* It must be large enough for a base64 encoded line */ + if (base64 && bsize < 80) + bsize = 80; + if (verbose) + BIO_printf(bio_err, "bufsize=%d\n", bsize); + +#ifdef ZLIB + if (!do_zlib) +#endif + if (base64) { + if (enc) + outformat = FORMAT_BASE64; + else + informat = FORMAT_BASE64; + } + + strbuf = app_malloc(SIZE, "strbuf"); + buff = app_malloc(EVP_ENCODE_LENGTH(bsize), "evp buffer"); + + if (infile == NULL) { + in = dup_bio_in(informat); + } else { + in = bio_open_default(infile, 'r', informat); + } + if (in == NULL) + goto end; + + if (str == NULL && passarg != NULL) { + if (!app_passwd(passarg, NULL, &pass, NULL)) { + BIO_printf(bio_err, "Error getting password\n"); + goto end; + } + str = pass; + } + + if ((str == NULL) && (cipher != NULL) && (hkey == NULL)) { + if (1) { +#ifndef OPENSSL_NO_UI_CONSOLE + for (;;) { + char prompt[200]; + + BIO_snprintf(prompt, sizeof(prompt), "enter %s %s password:", + OBJ_nid2ln(EVP_CIPHER_nid(cipher)), + (enc) ? "encryption" : "decryption"); + strbuf[0] = '\0'; + i = EVP_read_pw_string((char *)strbuf, SIZE, prompt, enc); + if (i == 0) { + if (strbuf[0] == '\0') { + ret = 1; + goto end; + } + str = strbuf; + break; + } + if (i < 0) { + BIO_printf(bio_err, "bad password read\n"); + goto end; + } + } + } else { +#endif + BIO_printf(bio_err, "password required\n"); + goto end; + } + } + + out = bio_open_default(outfile, 'w', outformat); + if (out == NULL) + goto end; + + if (debug) { + BIO_set_callback(in, BIO_debug_callback); + BIO_set_callback(out, BIO_debug_callback); + BIO_set_callback_arg(in, (char *)bio_err); + BIO_set_callback_arg(out, (char *)bio_err); + } + + rbio = in; + wbio = out; + +#ifdef ZLIB + if (do_zlib) { + if ((bzl = BIO_new(BIO_f_zlib())) == NULL) + goto end; + if (debug) { + BIO_set_callback(bzl, BIO_debug_callback); + BIO_set_callback_arg(bzl, (char *)bio_err); + } + if (enc) + wbio = BIO_push(bzl, wbio); + else + rbio = BIO_push(bzl, rbio); + } +#endif + + if (base64) { + if ((b64 = BIO_new(BIO_f_base64())) == NULL) + goto end; + if (debug) { + BIO_set_callback(b64, BIO_debug_callback); + BIO_set_callback_arg(b64, (char *)bio_err); + } + if (olb64) + BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); + if (enc) + wbio = BIO_push(b64, wbio); + else + rbio = BIO_push(b64, rbio); + } + + if (cipher != NULL) { + /* + * Note that str is NULL if a key was passed on the command line, so + * we get no salt in that case. Is this a bug? + */ + if (str != NULL) { + /* + * Salt handling: if encrypting generate a salt and write to + * output BIO. If decrypting read salt from input BIO. + */ + unsigned char *sptr; + size_t str_len = strlen(str); + + if (nosalt) { + sptr = NULL; + } else { + if (enc) { + if (hsalt) { + if (!set_hex(hsalt, salt, sizeof(salt))) { + BIO_printf(bio_err, "invalid hex salt value\n"); + goto end; + } + } else if (RAND_bytes(salt, sizeof(salt)) <= 0) { + goto end; + } + /* + * If -P option then don't bother writing + */ + if ((printkey != 2) + && (BIO_write(wbio, magic, + sizeof(magic) - 1) != sizeof(magic) - 1 + || BIO_write(wbio, + (char *)salt, + sizeof(salt)) != sizeof(salt))) { + BIO_printf(bio_err, "error writing output file\n"); + goto end; + } + } else if (BIO_read(rbio, mbuf, sizeof(mbuf)) != sizeof(mbuf) + || BIO_read(rbio, + (unsigned char *)salt, + sizeof(salt)) != sizeof(salt)) { + BIO_printf(bio_err, "error reading input file\n"); + goto end; + } else if (memcmp(mbuf, magic, sizeof(magic) - 1)) { + BIO_printf(bio_err, "bad magic number\n"); + goto end; + } + sptr = salt; + } + + if (pbkdf2 == 1) { + /* + * derive key and default iv + * concatenated into a temporary buffer + */ + unsigned char tmpkeyiv[EVP_MAX_KEY_LENGTH + EVP_MAX_IV_LENGTH]; + int iklen = EVP_CIPHER_key_length(cipher); + int ivlen = EVP_CIPHER_iv_length(cipher); + /* not needed if HASH_UPDATE() is fixed : */ + int islen = (sptr != NULL ? sizeof(salt) : 0); + if (!PKCS5_PBKDF2_HMAC(str, str_len, sptr, islen, + iter, dgst, iklen+ivlen, tmpkeyiv)) { + BIO_printf(bio_err, "PKCS5_PBKDF2_HMAC failed\n"); + goto end; + } + /* split and move data back to global buffer */ + memcpy(key, tmpkeyiv, iklen); + memcpy(iv, tmpkeyiv+iklen, ivlen); + } else { + BIO_printf(bio_err, "*** WARNING : " + "deprecated key derivation used.\n" + "Using -iter or -pbkdf2 would be better.\n"); + if (!EVP_BytesToKey(cipher, dgst, sptr, + (unsigned char *)str, str_len, + 1, key, iv)) { + BIO_printf(bio_err, "EVP_BytesToKey failed\n"); + goto end; + } + } + /* + * zero the complete buffer or the string passed from the command + * line. + */ + if (str == strbuf) + OPENSSL_cleanse(str, SIZE); + else + OPENSSL_cleanse(str, str_len); + } + if (hiv != NULL) { + int siz = EVP_CIPHER_iv_length(cipher); + if (siz == 0) { + BIO_printf(bio_err, "warning: iv not use by this cipher\n"); + } else if (!set_hex(hiv, iv, siz)) { + BIO_printf(bio_err, "invalid hex iv value\n"); + goto end; + } + } + if ((hiv == NULL) && (str == NULL) + && EVP_CIPHER_iv_length(cipher) != 0) { + /* + * No IV was explicitly set and no IV was generated. + * Hence the IV is undefined, making correct decryption impossible. + */ + BIO_printf(bio_err, "iv undefined\n"); + goto end; + } + if (hkey != NULL) { + if (!set_hex(hkey, key, EVP_CIPHER_key_length(cipher))) { + BIO_printf(bio_err, "invalid hex key value\n"); + goto end; + } + /* wiping secret data as we no longer need it */ + OPENSSL_cleanse(hkey, strlen(hkey)); + } + + if ((benc = BIO_new(BIO_f_cipher())) == NULL) + goto end; + + /* + * Since we may be changing parameters work on the encryption context + * rather than calling BIO_set_cipher(). + */ + + BIO_get_cipher_ctx(benc, &ctx); + + if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, enc)) { + BIO_printf(bio_err, "Error setting cipher %s\n", + EVP_CIPHER_name(cipher)); + ERR_print_errors(bio_err); + goto end; + } + + if (nopad) + EVP_CIPHER_CTX_set_padding(ctx, 0); + + if (!EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, enc)) { + BIO_printf(bio_err, "Error setting cipher %s\n", + EVP_CIPHER_name(cipher)); + ERR_print_errors(bio_err); + goto end; + } + + if (debug) { + BIO_set_callback(benc, BIO_debug_callback); + BIO_set_callback_arg(benc, (char *)bio_err); + } + + if (printkey) { + if (!nosalt) { + printf("salt="); + for (i = 0; i < (int)sizeof(salt); i++) + printf("%02X", salt[i]); + printf("\n"); + } + if (EVP_CIPHER_key_length(cipher) > 0) { + printf("key="); + for (i = 0; i < EVP_CIPHER_key_length(cipher); i++) + printf("%02X", key[i]); + printf("\n"); + } + if (EVP_CIPHER_iv_length(cipher) > 0) { + printf("iv ="); + for (i = 0; i < EVP_CIPHER_iv_length(cipher); i++) + printf("%02X", iv[i]); + printf("\n"); + } + if (printkey == 2) { + ret = 0; + goto end; + } + } + } + + /* Only encrypt/decrypt as we write the file */ + if (benc != NULL) + wbio = BIO_push(benc, wbio); + + for (;;) { + inl = BIO_read(rbio, (char *)buff, bsize); + if (inl <= 0) + break; + if (BIO_write(wbio, (char *)buff, inl) != inl) { + BIO_printf(bio_err, "error writing output file\n"); + goto end; + } + } + if (!BIO_flush(wbio)) { + BIO_printf(bio_err, "bad decrypt\n"); + goto end; + } + + ret = 0; + if (verbose) { + BIO_printf(bio_err, "bytes read : %8ju\n", BIO_number_read(in)); + BIO_printf(bio_err, "bytes written: %8ju\n", BIO_number_written(out)); + } + end: + ERR_print_errors(bio_err); + OPENSSL_free(strbuf); + OPENSSL_free(buff); + BIO_free(in); + BIO_free_all(out); + BIO_free(benc); + BIO_free(b64); +#ifdef ZLIB + BIO_free(bzl); +#endif + release_engine(e); + OPENSSL_free(pass); + return ret; +} + +static void show_ciphers(const OBJ_NAME *name, void *arg) +{ + struct doall_enc_ciphers *dec = (struct doall_enc_ciphers *)arg; + const EVP_CIPHER *cipher; + + if (!islower((unsigned char)*name->name)) + return; + + /* Filter out ciphers that we cannot use */ + cipher = EVP_get_cipherbyname(name->name); + if (cipher == NULL || + (EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) != 0 || + EVP_CIPHER_mode(cipher) == EVP_CIPH_XTS_MODE) + return; + + BIO_printf(dec->bio, "-%-25s", name->name); + if (++dec->n == 3) { + BIO_printf(dec->bio, "\n"); + dec->n = 0; + } else + BIO_printf(dec->bio, " "); +} + +static int set_hex(const char *in, unsigned char *out, int size) +{ + int i, n; + unsigned char j; + + i = size * 2; + n = strlen(in); + if (n > i) { + BIO_printf(bio_err, "hex string is too long, ignoring excess\n"); + n = i; /* ignore exceeding part */ + } else if (n < i) { + BIO_printf(bio_err, "hex string is too short, padding with zero bytes to length\n"); + } + + memset(out, 0, size); + for (i = 0; i < n; i++) { + j = (unsigned char)*in++; + if (!isxdigit(j)) { + BIO_printf(bio_err, "non-hex digit\n"); + return 0; + } + j = (unsigned char)OPENSSL_hexchar2int(j); + if (i & 1) + out[i / 2] |= j; + else + out[i / 2] = (j << 4); + } + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/engine.c b/trunk/3rdparty/openssl-1.1-fit/apps/engine.c new file mode 100644 index 000000000..83f9588a0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/engine.c @@ -0,0 +1,489 @@ +/* + * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#ifdef OPENSSL_NO_ENGINE +NON_EMPTY_TRANSLATION_UNIT +#else + +# include "apps.h" +# include "progs.h" +# include +# include +# include +# include +# include +# include +# include + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_C, OPT_T, OPT_TT, OPT_PRE, OPT_POST, + OPT_V = 100, OPT_VV, OPT_VVV, OPT_VVVV +} OPTION_CHOICE; + +const OPTIONS engine_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] engine...\n"}, + {OPT_HELP_STR, 1, '-', + " engine... Engines to load\n"}, + {"help", OPT_HELP, '-', "Display this summary"}, + {"v", OPT_V, '-', "List 'control commands' For each specified engine"}, + {"vv", OPT_VV, '-', "Also display each command's description"}, + {"vvv", OPT_VVV, '-', "Also add the input flags for each command"}, + {"vvvv", OPT_VVVV, '-', "Also show internal input flags"}, + {"c", OPT_C, '-', "List the capabilities of specified engine"}, + {"t", OPT_T, '-', "Check that specified engine is available"}, + {"tt", OPT_TT, '-', "Display error trace for unavailable engines"}, + {"pre", OPT_PRE, 's', "Run command against the ENGINE before loading it"}, + {"post", OPT_POST, 's', "Run command against the ENGINE after loading it"}, + {OPT_MORE_STR, OPT_EOF, 1, + "Commands are like \"SO_PATH:/lib/libdriver.so\""}, + {NULL} +}; + +static int append_buf(char **buf, int *size, const char *s) +{ + const int expand = 256; + int len = strlen(s) + 1; + char *p = *buf; + + if (p == NULL) { + *size = ((len + expand - 1) / expand) * expand; + p = *buf = app_malloc(*size, "engine buffer"); + } else { + const int blen = strlen(p); + + if (blen > 0) + len += 2 + blen; + + if (len > *size) { + *size = ((len + expand - 1) / expand) * expand; + p = OPENSSL_realloc(p, *size); + if (p == NULL) { + OPENSSL_free(*buf); + *buf = NULL; + return 0; + } + *buf = p; + } + + if (blen > 0) { + p += blen; + *p++ = ','; + *p++ = ' '; + } + } + + strcpy(p, s); + return 1; +} + +static int util_flags(BIO *out, unsigned int flags, const char *indent) +{ + int started = 0, err = 0; + /* Indent before displaying input flags */ + BIO_printf(out, "%s%s(input flags): ", indent, indent); + if (flags == 0) { + BIO_printf(out, "\n"); + return 1; + } + /* + * If the object is internal, mark it in a way that shows instead of + * having it part of all the other flags, even if it really is. + */ + if (flags & ENGINE_CMD_FLAG_INTERNAL) { + BIO_printf(out, "[Internal] "); + } + + if (flags & ENGINE_CMD_FLAG_NUMERIC) { + BIO_printf(out, "NUMERIC"); + started = 1; + } + /* + * Now we check that no combinations of the mutually exclusive NUMERIC, + * STRING, and NO_INPUT flags have been used. Future flags that can be + * OR'd together with these would need to added after these to preserve + * the testing logic. + */ + if (flags & ENGINE_CMD_FLAG_STRING) { + if (started) { + BIO_printf(out, "|"); + err = 1; + } + BIO_printf(out, "STRING"); + started = 1; + } + if (flags & ENGINE_CMD_FLAG_NO_INPUT) { + if (started) { + BIO_printf(out, "|"); + err = 1; + } + BIO_printf(out, "NO_INPUT"); + started = 1; + } + /* Check for unknown flags */ + flags = flags & ~ENGINE_CMD_FLAG_NUMERIC & + ~ENGINE_CMD_FLAG_STRING & + ~ENGINE_CMD_FLAG_NO_INPUT & ~ENGINE_CMD_FLAG_INTERNAL; + if (flags) { + if (started) + BIO_printf(out, "|"); + BIO_printf(out, "<0x%04X>", flags); + } + if (err) + BIO_printf(out, " "); + BIO_printf(out, "\n"); + return 1; +} + +static int util_verbose(ENGINE *e, int verbose, BIO *out, const char *indent) +{ + static const int line_wrap = 78; + int num; + int ret = 0; + char *name = NULL; + char *desc = NULL; + int flags; + int xpos = 0; + STACK_OF(OPENSSL_STRING) *cmds = NULL; + if (!ENGINE_ctrl(e, ENGINE_CTRL_HAS_CTRL_FUNCTION, 0, NULL, NULL) || + ((num = ENGINE_ctrl(e, ENGINE_CTRL_GET_FIRST_CMD_TYPE, + 0, NULL, NULL)) <= 0)) { + return 1; + } + + cmds = sk_OPENSSL_STRING_new_null(); + if (cmds == NULL) + goto err; + + do { + int len; + /* Get the command input flags */ + if ((flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, num, + NULL, NULL)) < 0) + goto err; + if (!(flags & ENGINE_CMD_FLAG_INTERNAL) || verbose >= 4) { + /* Get the command name */ + if ((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_LEN_FROM_CMD, num, + NULL, NULL)) <= 0) + goto err; + name = app_malloc(len + 1, "name buffer"); + if (ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_FROM_CMD, num, name, + NULL) <= 0) + goto err; + /* Get the command description */ + if ((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_LEN_FROM_CMD, num, + NULL, NULL)) < 0) + goto err; + if (len > 0) { + desc = app_malloc(len + 1, "description buffer"); + if (ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_FROM_CMD, num, desc, + NULL) <= 0) + goto err; + } + /* Now decide on the output */ + if (xpos == 0) + /* Do an indent */ + xpos = BIO_puts(out, indent); + else + /* Otherwise prepend a ", " */ + xpos += BIO_printf(out, ", "); + if (verbose == 1) { + /* + * We're just listing names, comma-delimited + */ + if ((xpos > (int)strlen(indent)) && + (xpos + (int)strlen(name) > line_wrap)) { + BIO_printf(out, "\n"); + xpos = BIO_puts(out, indent); + } + xpos += BIO_printf(out, "%s", name); + } else { + /* We're listing names plus descriptions */ + BIO_printf(out, "%s: %s\n", name, + (desc == NULL) ? "" : desc); + /* ... and sometimes input flags */ + if ((verbose >= 3) && !util_flags(out, flags, indent)) + goto err; + xpos = 0; + } + } + OPENSSL_free(name); + name = NULL; + OPENSSL_free(desc); + desc = NULL; + /* Move to the next command */ + num = ENGINE_ctrl(e, ENGINE_CTRL_GET_NEXT_CMD_TYPE, num, NULL, NULL); + } while (num > 0); + if (xpos > 0) + BIO_printf(out, "\n"); + ret = 1; + err: + sk_OPENSSL_STRING_free(cmds); + OPENSSL_free(name); + OPENSSL_free(desc); + return ret; +} + +static void util_do_cmds(ENGINE *e, STACK_OF(OPENSSL_STRING) *cmds, + BIO *out, const char *indent) +{ + int loop, res, num = sk_OPENSSL_STRING_num(cmds); + + if (num < 0) { + BIO_printf(out, "[Error]: internal stack error\n"); + return; + } + for (loop = 0; loop < num; loop++) { + char buf[256]; + const char *cmd, *arg; + cmd = sk_OPENSSL_STRING_value(cmds, loop); + res = 1; /* assume success */ + /* Check if this command has no ":arg" */ + if ((arg = strstr(cmd, ":")) == NULL) { + if (!ENGINE_ctrl_cmd_string(e, cmd, NULL, 0)) + res = 0; + } else { + if ((int)(arg - cmd) > 254) { + BIO_printf(out, "[Error]: command name too long\n"); + return; + } + memcpy(buf, cmd, (int)(arg - cmd)); + buf[arg - cmd] = '\0'; + arg++; /* Move past the ":" */ + /* Call the command with the argument */ + if (!ENGINE_ctrl_cmd_string(e, buf, arg, 0)) + res = 0; + } + if (res) { + BIO_printf(out, "[Success]: %s\n", cmd); + } else { + BIO_printf(out, "[Failure]: %s\n", cmd); + ERR_print_errors(out); + } + } +} + +struct util_store_cap_data { + ENGINE *engine; + char **cap_buf; + int *cap_size; + int ok; +}; +static void util_store_cap(const OSSL_STORE_LOADER *loader, void *arg) +{ + struct util_store_cap_data *ctx = arg; + + if (OSSL_STORE_LOADER_get0_engine(loader) == ctx->engine) { + char buf[256]; + BIO_snprintf(buf, sizeof(buf), "STORE(%s)", + OSSL_STORE_LOADER_get0_scheme(loader)); + if (!append_buf(ctx->cap_buf, ctx->cap_size, buf)) + ctx->ok = 0; + } +} + +int engine_main(int argc, char **argv) +{ + int ret = 1, i; + int verbose = 0, list_cap = 0, test_avail = 0, test_avail_noise = 0; + ENGINE *e; + STACK_OF(OPENSSL_CSTRING) *engines = sk_OPENSSL_CSTRING_new_null(); + STACK_OF(OPENSSL_STRING) *pre_cmds = sk_OPENSSL_STRING_new_null(); + STACK_OF(OPENSSL_STRING) *post_cmds = sk_OPENSSL_STRING_new_null(); + BIO *out; + const char *indent = " "; + OPTION_CHOICE o; + char *prog; + char *argv1; + + out = dup_bio_out(FORMAT_TEXT); + if (engines == NULL || pre_cmds == NULL || post_cmds == NULL) + goto end; + + /* Remember the original command name, parse/skip any leading engine + * names, and then setup to parse the rest of the line as flags. */ + prog = argv[0]; + while ((argv1 = argv[1]) != NULL && *argv1 != '-') { + sk_OPENSSL_CSTRING_push(engines, argv1); + argc--; + argv++; + } + argv[0] = prog; + opt_init(argc, argv, engine_options); + + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(engine_options); + ret = 0; + goto end; + case OPT_VVVV: + case OPT_VVV: + case OPT_VV: + case OPT_V: + /* Convert to an integer from one to four. */ + i = (int)(o - OPT_V) + 1; + if (verbose < i) + verbose = i; + break; + case OPT_C: + list_cap = 1; + break; + case OPT_TT: + test_avail_noise++; + /* fall thru */ + case OPT_T: + test_avail++; + break; + case OPT_PRE: + sk_OPENSSL_STRING_push(pre_cmds, opt_arg()); + break; + case OPT_POST: + sk_OPENSSL_STRING_push(post_cmds, opt_arg()); + break; + } + } + + /* Allow any trailing parameters as engine names. */ + argc = opt_num_rest(); + argv = opt_rest(); + for ( ; *argv; argv++) { + if (**argv == '-') { + BIO_printf(bio_err, "%s: Cannot mix flags and engine names.\n", + prog); + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + } + sk_OPENSSL_CSTRING_push(engines, *argv); + } + + if (sk_OPENSSL_CSTRING_num(engines) == 0) { + for (e = ENGINE_get_first(); e != NULL; e = ENGINE_get_next(e)) { + sk_OPENSSL_CSTRING_push(engines, ENGINE_get_id(e)); + } + } + + ret = 0; + for (i = 0; i < sk_OPENSSL_CSTRING_num(engines); i++) { + const char *id = sk_OPENSSL_CSTRING_value(engines, i); + if ((e = ENGINE_by_id(id)) != NULL) { + const char *name = ENGINE_get_name(e); + /* + * Do "id" first, then "name". Easier to auto-parse. + */ + BIO_printf(out, "(%s) %s\n", id, name); + util_do_cmds(e, pre_cmds, out, indent); + if (strcmp(ENGINE_get_id(e), id) != 0) { + BIO_printf(out, "Loaded: (%s) %s\n", + ENGINE_get_id(e), ENGINE_get_name(e)); + } + if (list_cap) { + int cap_size = 256; + char *cap_buf = NULL; + int k, n; + const int *nids; + ENGINE_CIPHERS_PTR fn_c; + ENGINE_DIGESTS_PTR fn_d; + ENGINE_PKEY_METHS_PTR fn_pk; + + if (ENGINE_get_RSA(e) != NULL + && !append_buf(&cap_buf, &cap_size, "RSA")) + goto end; + if (ENGINE_get_DSA(e) != NULL + && !append_buf(&cap_buf, &cap_size, "DSA")) + goto end; + if (ENGINE_get_DH(e) != NULL + && !append_buf(&cap_buf, &cap_size, "DH")) + goto end; + if (ENGINE_get_RAND(e) != NULL + && !append_buf(&cap_buf, &cap_size, "RAND")) + goto end; + + fn_c = ENGINE_get_ciphers(e); + if (fn_c == NULL) + goto skip_ciphers; + n = fn_c(e, NULL, &nids, 0); + for (k = 0; k < n; ++k) + if (!append_buf(&cap_buf, &cap_size, OBJ_nid2sn(nids[k]))) + goto end; + + skip_ciphers: + fn_d = ENGINE_get_digests(e); + if (fn_d == NULL) + goto skip_digests; + n = fn_d(e, NULL, &nids, 0); + for (k = 0; k < n; ++k) + if (!append_buf(&cap_buf, &cap_size, OBJ_nid2sn(nids[k]))) + goto end; + + skip_digests: + fn_pk = ENGINE_get_pkey_meths(e); + if (fn_pk == NULL) + goto skip_pmeths; + n = fn_pk(e, NULL, &nids, 0); + for (k = 0; k < n; ++k) + if (!append_buf(&cap_buf, &cap_size, OBJ_nid2sn(nids[k]))) + goto end; + skip_pmeths: + { + struct util_store_cap_data store_ctx; + + store_ctx.engine = e; + store_ctx.cap_buf = &cap_buf; + store_ctx.cap_size = &cap_size; + store_ctx.ok = 1; + + OSSL_STORE_do_all_loaders(util_store_cap, &store_ctx); + if (!store_ctx.ok) + goto end; + } + if (cap_buf != NULL && (*cap_buf != '\0')) + BIO_printf(out, " [%s]\n", cap_buf); + + OPENSSL_free(cap_buf); + } + if (test_avail) { + BIO_printf(out, "%s", indent); + if (ENGINE_init(e)) { + BIO_printf(out, "[ available ]\n"); + util_do_cmds(e, post_cmds, out, indent); + ENGINE_finish(e); + } else { + BIO_printf(out, "[ unavailable ]\n"); + if (test_avail_noise) + ERR_print_errors_fp(stdout); + ERR_clear_error(); + } + } + if ((verbose > 0) && !util_verbose(e, verbose, out, indent)) + goto end; + ENGINE_free(e); + } else { + ERR_print_errors(bio_err); + /* because exit codes above 127 have special meaning on Unix */ + if (++ret > 127) + ret = 127; + } + } + + end: + + ERR_print_errors(bio_err); + sk_OPENSSL_CSTRING_free(engines); + sk_OPENSSL_STRING_free(pre_cmds); + sk_OPENSSL_STRING_free(post_cmds); + BIO_free_all(out); + return ret; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/errstr.c b/trunk/3rdparty/openssl-1.1-fit/apps/errstr.c new file mode 100644 index 000000000..3ef01f076 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/errstr.c @@ -0,0 +1,67 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP +} OPTION_CHOICE; + +const OPTIONS errstr_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] errnum...\n"}, + {OPT_HELP_STR, 1, '-', " errnum Error number\n"}, + {"help", OPT_HELP, '-', "Display this summary"}, + {NULL} +}; + +int errstr_main(int argc, char **argv) +{ + OPTION_CHOICE o; + char buf[256], *prog; + int ret = 1; + unsigned long l; + + prog = opt_init(argc, argv, errstr_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(errstr_options); + ret = 0; + goto end; + } + } + + ret = 0; + for (argv = opt_rest(); *argv; argv++) { + if (sscanf(*argv, "%lx", &l) == 0) { + ret++; + } else { + /* We're not really an SSL application so this won't auto-init, but + * we're still interested in SSL error strings + */ + OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS + | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); + ERR_error_string_n(l, buf, sizeof(buf)); + BIO_printf(bio_out, "%s\n", buf); + } + } + end: + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/gendsa.c b/trunk/3rdparty/openssl-1.1-fit/apps/gendsa.c new file mode 100644 index 000000000..401375420 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/gendsa.c @@ -0,0 +1,146 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#ifdef OPENSSL_NO_DSA +NON_EMPTY_TRANSLATION_UNIT +#else + +# include +# include +# include +# include +# include "apps.h" +# include "progs.h" +# include +# include +# include +# include +# include +# include + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_OUT, OPT_PASSOUT, OPT_ENGINE, OPT_CIPHER, + OPT_R_ENUM +} OPTION_CHOICE; + +const OPTIONS gendsa_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [args] dsaparam-file\n"}, + {OPT_HELP_STR, 1, '-', "Valid options are:\n"}, + {"help", OPT_HELP, '-', "Display this summary"}, + {"out", OPT_OUT, '>', "Output the key to the specified file"}, + {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, + OPT_R_OPTIONS, + {"", OPT_CIPHER, '-', "Encrypt the output with any supported cipher"}, +# ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +# endif + {NULL} +}; + +int gendsa_main(int argc, char **argv) +{ + ENGINE *e = NULL; + BIO *out = NULL, *in = NULL; + DSA *dsa = NULL; + const EVP_CIPHER *enc = NULL; + char *dsaparams = NULL; + char *outfile = NULL, *passoutarg = NULL, *passout = NULL, *prog; + OPTION_CHOICE o; + int ret = 1, private = 0; + const BIGNUM *p = NULL; + + prog = opt_init(argc, argv, gendsa_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + ret = 0; + opt_help(gendsa_options); + goto end; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_PASSOUT: + passoutarg = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_CIPHER: + if (!opt_cipher(opt_unknown(), &enc)) + goto end; + break; + } + } + argc = opt_num_rest(); + argv = opt_rest(); + private = 1; + + if (argc != 1) + goto opthelp; + dsaparams = *argv; + + if (!app_passwd(NULL, passoutarg, NULL, &passout)) { + BIO_printf(bio_err, "Error getting password\n"); + goto end; + } + + in = bio_open_default(dsaparams, 'r', FORMAT_PEM); + if (in == NULL) + goto end2; + + if ((dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL)) == NULL) { + BIO_printf(bio_err, "unable to load DSA parameter file\n"); + goto end; + } + BIO_free(in); + in = NULL; + + out = bio_open_owner(outfile, FORMAT_PEM, private); + if (out == NULL) + goto end2; + + DSA_get0_pqg(dsa, &p, NULL, NULL); + + if (BN_num_bits(p) > OPENSSL_DSA_MAX_MODULUS_BITS) + BIO_printf(bio_err, + "Warning: It is not recommended to use more than %d bit for DSA keys.\n" + " Your key size is %d! Larger key size may behave not as expected.\n", + OPENSSL_DSA_MAX_MODULUS_BITS, BN_num_bits(p)); + + BIO_printf(bio_err, "Generating DSA key, %d bits\n", BN_num_bits(p)); + if (!DSA_generate_key(dsa)) + goto end; + + assert(private); + if (!PEM_write_bio_DSAPrivateKey(out, dsa, enc, NULL, 0, NULL, passout)) + goto end; + ret = 0; + end: + if (ret != 0) + ERR_print_errors(bio_err); + end2: + BIO_free(in); + BIO_free_all(out); + DSA_free(dsa); + release_engine(e); + OPENSSL_free(passout); + return ret; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/genpkey.c b/trunk/3rdparty/openssl-1.1-fit/apps/genpkey.c new file mode 100644 index 000000000..39fa73c91 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/genpkey.c @@ -0,0 +1,322 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#ifndef OPENSSL_NO_ENGINE +# include +#endif + +static int init_keygen_file(EVP_PKEY_CTX **pctx, const char *file, ENGINE *e); +static int genpkey_cb(EVP_PKEY_CTX *ctx); + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_ENGINE, OPT_OUTFORM, OPT_OUT, OPT_PASS, OPT_PARAMFILE, + OPT_ALGORITHM, OPT_PKEYOPT, OPT_GENPARAM, OPT_TEXT, OPT_CIPHER +} OPTION_CHOICE; + +const OPTIONS genpkey_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"out", OPT_OUT, '>', "Output file"}, + {"outform", OPT_OUTFORM, 'F', "output format (DER or PEM)"}, + {"pass", OPT_PASS, 's', "Output file pass phrase source"}, + {"paramfile", OPT_PARAMFILE, '<', "Parameters file"}, + {"algorithm", OPT_ALGORITHM, 's', "The public key algorithm"}, + {"pkeyopt", OPT_PKEYOPT, 's', + "Set the public key algorithm option as opt:value"}, + {"genparam", OPT_GENPARAM, '-', "Generate parameters, not key"}, + {"text", OPT_TEXT, '-', "Print the in text"}, + {"", OPT_CIPHER, '-', "Cipher to use to encrypt the key"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + /* This is deliberately last. */ + {OPT_HELP_STR, 1, 1, + "Order of options may be important! See the documentation.\n"}, + {NULL} +}; + +int genpkey_main(int argc, char **argv) +{ + BIO *in = NULL, *out = NULL; + ENGINE *e = NULL; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *ctx = NULL; + char *outfile = NULL, *passarg = NULL, *pass = NULL, *prog; + const EVP_CIPHER *cipher = NULL; + OPTION_CHOICE o; + int outformat = FORMAT_PEM, text = 0, ret = 1, rv, do_param = 0; + int private = 0; + + prog = opt_init(argc, argv, genpkey_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + ret = 0; + opt_help(genpkey_options); + goto end; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) + goto opthelp; + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_PASS: + passarg = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_PARAMFILE: + if (do_param == 1) + goto opthelp; + if (!init_keygen_file(&ctx, opt_arg(), e)) + goto end; + break; + case OPT_ALGORITHM: + if (!init_gen_str(&ctx, opt_arg(), e, do_param)) + goto end; + break; + case OPT_PKEYOPT: + if (ctx == NULL) { + BIO_printf(bio_err, "%s: No keytype specified.\n", prog); + goto opthelp; + } + if (pkey_ctrl_string(ctx, opt_arg()) <= 0) { + BIO_printf(bio_err, + "%s: Error setting %s parameter:\n", + prog, opt_arg()); + ERR_print_errors(bio_err); + goto end; + } + break; + case OPT_GENPARAM: + if (ctx != NULL) + goto opthelp; + do_param = 1; + break; + case OPT_TEXT: + text = 1; + break; + case OPT_CIPHER: + if (!opt_cipher(opt_unknown(), &cipher) + || do_param == 1) + goto opthelp; + if (EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE || + EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE || + EVP_CIPHER_mode(cipher) == EVP_CIPH_XTS_MODE || + EVP_CIPHER_mode(cipher) == EVP_CIPH_OCB_MODE) { + BIO_printf(bio_err, "%s: cipher mode not supported\n", prog); + goto end; + } + } + } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + + private = do_param ? 0 : 1; + + if (ctx == NULL) + goto opthelp; + + if (!app_passwd(passarg, NULL, &pass, NULL)) { + BIO_puts(bio_err, "Error getting password\n"); + goto end; + } + + out = bio_open_owner(outfile, outformat, private); + if (out == NULL) + goto end; + + EVP_PKEY_CTX_set_cb(ctx, genpkey_cb); + EVP_PKEY_CTX_set_app_data(ctx, bio_err); + + if (do_param) { + if (EVP_PKEY_paramgen(ctx, &pkey) <= 0) { + BIO_puts(bio_err, "Error generating parameters\n"); + ERR_print_errors(bio_err); + goto end; + } + } else { + if (EVP_PKEY_keygen(ctx, &pkey) <= 0) { + BIO_puts(bio_err, "Error generating key\n"); + ERR_print_errors(bio_err); + goto end; + } + } + + if (do_param) { + rv = PEM_write_bio_Parameters(out, pkey); + } else if (outformat == FORMAT_PEM) { + assert(private); + rv = PEM_write_bio_PrivateKey(out, pkey, cipher, NULL, 0, NULL, pass); + } else if (outformat == FORMAT_ASN1) { + assert(private); + rv = i2d_PrivateKey_bio(out, pkey); + } else { + BIO_printf(bio_err, "Bad format specified for key\n"); + goto end; + } + + if (rv <= 0) { + BIO_puts(bio_err, "Error writing key\n"); + ERR_print_errors(bio_err); + } + + if (text) { + if (do_param) + rv = EVP_PKEY_print_params(out, pkey, 0, NULL); + else + rv = EVP_PKEY_print_private(out, pkey, 0, NULL); + + if (rv <= 0) { + BIO_puts(bio_err, "Error printing key\n"); + ERR_print_errors(bio_err); + } + } + + ret = 0; + + end: + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(ctx); + BIO_free_all(out); + BIO_free(in); + release_engine(e); + OPENSSL_free(pass); + return ret; +} + +static int init_keygen_file(EVP_PKEY_CTX **pctx, const char *file, ENGINE *e) +{ + BIO *pbio; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *ctx = NULL; + if (*pctx) { + BIO_puts(bio_err, "Parameters already set!\n"); + return 0; + } + + pbio = BIO_new_file(file, "r"); + if (!pbio) { + BIO_printf(bio_err, "Can't open parameter file %s\n", file); + return 0; + } + + pkey = PEM_read_bio_Parameters(pbio, NULL); + BIO_free(pbio); + + if (!pkey) { + BIO_printf(bio_err, "Error reading parameter file %s\n", file); + return 0; + } + + ctx = EVP_PKEY_CTX_new(pkey, e); + if (ctx == NULL) + goto err; + if (EVP_PKEY_keygen_init(ctx) <= 0) + goto err; + EVP_PKEY_free(pkey); + *pctx = ctx; + return 1; + + err: + BIO_puts(bio_err, "Error initializing context\n"); + ERR_print_errors(bio_err); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + return 0; + +} + +int init_gen_str(EVP_PKEY_CTX **pctx, + const char *algname, ENGINE *e, int do_param) +{ + EVP_PKEY_CTX *ctx = NULL; + const EVP_PKEY_ASN1_METHOD *ameth; + ENGINE *tmpeng = NULL; + int pkey_id; + + if (*pctx) { + BIO_puts(bio_err, "Algorithm already set!\n"); + return 0; + } + + ameth = EVP_PKEY_asn1_find_str(&tmpeng, algname, -1); + +#ifndef OPENSSL_NO_ENGINE + if (!ameth && e) + ameth = ENGINE_get_pkey_asn1_meth_str(e, algname, -1); +#endif + + if (!ameth) { + BIO_printf(bio_err, "Algorithm %s not found\n", algname); + return 0; + } + + ERR_clear_error(); + + EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth); +#ifndef OPENSSL_NO_ENGINE + ENGINE_finish(tmpeng); +#endif + ctx = EVP_PKEY_CTX_new_id(pkey_id, e); + + if (!ctx) + goto err; + if (do_param) { + if (EVP_PKEY_paramgen_init(ctx) <= 0) + goto err; + } else { + if (EVP_PKEY_keygen_init(ctx) <= 0) + goto err; + } + + *pctx = ctx; + return 1; + + err: + BIO_printf(bio_err, "Error initializing %s context\n", algname); + ERR_print_errors(bio_err); + EVP_PKEY_CTX_free(ctx); + return 0; + +} + +static int genpkey_cb(EVP_PKEY_CTX *ctx) +{ + char c = '*'; + BIO *b = EVP_PKEY_CTX_get_app_data(ctx); + int p; + p = EVP_PKEY_CTX_get_keygen_info(ctx, 0); + if (p == 0) + c = '.'; + if (p == 1) + c = '+'; + if (p == 2) + c = '*'; + if (p == 3) + c = '\n'; + BIO_write(b, &c, 1); + (void)BIO_flush(b); + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/genrsa.c b/trunk/3rdparty/openssl-1.1-fit/apps/genrsa.c new file mode 100644 index 000000000..c17cd1471 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/genrsa.c @@ -0,0 +1,201 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#ifdef OPENSSL_NO_RSA +NON_EMPTY_TRANSLATION_UNIT +#else + +# include +# include +# include +# include +# include "apps.h" +# include "progs.h" +# include +# include +# include +# include +# include +# include +# include +# include + +# define DEFBITS 2048 +# define DEFPRIMES 2 + +static int genrsa_cb(int p, int n, BN_GENCB *cb); + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_3, OPT_F4, OPT_ENGINE, + OPT_OUT, OPT_PASSOUT, OPT_CIPHER, OPT_PRIMES, + OPT_R_ENUM +} OPTION_CHOICE; + +const OPTIONS genrsa_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"3", OPT_3, '-', "Use 3 for the E value"}, + {"F4", OPT_F4, '-', "Use F4 (0x10001) for the E value"}, + {"f4", OPT_F4, '-', "Use F4 (0x10001) for the E value"}, + {"out", OPT_OUT, '>', "Output the key to specified file"}, + OPT_R_OPTIONS, + {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, + {"", OPT_CIPHER, '-', "Encrypt the output with any supported cipher"}, +# ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +# endif + {"primes", OPT_PRIMES, 'p', "Specify number of primes"}, + {NULL} +}; + +int genrsa_main(int argc, char **argv) +{ + BN_GENCB *cb = BN_GENCB_new(); + PW_CB_DATA cb_data; + ENGINE *eng = NULL; + BIGNUM *bn = BN_new(); + BIO *out = NULL; + const BIGNUM *e; + RSA *rsa = NULL; + const EVP_CIPHER *enc = NULL; + int ret = 1, num = DEFBITS, private = 0, primes = DEFPRIMES; + unsigned long f4 = RSA_F4; + char *outfile = NULL, *passoutarg = NULL, *passout = NULL; + char *prog, *hexe, *dece; + OPTION_CHOICE o; + + if (bn == NULL || cb == NULL) + goto end; + + BN_GENCB_set(cb, genrsa_cb, bio_err); + + prog = opt_init(argc, argv, genrsa_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: +opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + ret = 0; + opt_help(genrsa_options); + goto end; + case OPT_3: + f4 = 3; + break; + case OPT_F4: + f4 = RSA_F4; + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_ENGINE: + eng = setup_engine(opt_arg(), 0); + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_PASSOUT: + passoutarg = opt_arg(); + break; + case OPT_CIPHER: + if (!opt_cipher(opt_unknown(), &enc)) + goto end; + break; + case OPT_PRIMES: + if (!opt_int(opt_arg(), &primes)) + goto end; + break; + } + } + argc = opt_num_rest(); + argv = opt_rest(); + + if (argc == 1) { + if (!opt_int(argv[0], &num) || num <= 0) + goto end; + if (num > OPENSSL_RSA_MAX_MODULUS_BITS) + BIO_printf(bio_err, + "Warning: It is not recommended to use more than %d bit for RSA keys.\n" + " Your key size is %d! Larger key size may behave not as expected.\n", + OPENSSL_RSA_MAX_MODULUS_BITS, num); + } else if (argc > 0) { + BIO_printf(bio_err, "Extra arguments given.\n"); + goto opthelp; + } + + private = 1; + if (!app_passwd(NULL, passoutarg, NULL, &passout)) { + BIO_printf(bio_err, "Error getting password\n"); + goto end; + } + + out = bio_open_owner(outfile, FORMAT_PEM, private); + if (out == NULL) + goto end; + + BIO_printf(bio_err, "Generating RSA private key, %d bit long modulus (%d primes)\n", + num, primes); + rsa = eng ? RSA_new_method(eng) : RSA_new(); + if (rsa == NULL) + goto end; + + if (!BN_set_word(bn, f4) + || !RSA_generate_multi_prime_key(rsa, num, primes, bn, cb)) + goto end; + + RSA_get0_key(rsa, NULL, &e, NULL); + hexe = BN_bn2hex(e); + dece = BN_bn2dec(e); + if (hexe && dece) { + BIO_printf(bio_err, "e is %s (0x%s)\n", dece, hexe); + } + OPENSSL_free(hexe); + OPENSSL_free(dece); + cb_data.password = passout; + cb_data.prompt_info = outfile; + assert(private); + if (!PEM_write_bio_RSAPrivateKey(out, rsa, enc, NULL, 0, + (pem_password_cb *)password_callback, + &cb_data)) + goto end; + + ret = 0; + end: + BN_free(bn); + BN_GENCB_free(cb); + RSA_free(rsa); + BIO_free_all(out); + release_engine(eng); + OPENSSL_free(passout); + if (ret != 0) + ERR_print_errors(bio_err); + return ret; +} + +static int genrsa_cb(int p, int n, BN_GENCB *cb) +{ + char c = '*'; + + if (p == 0) + c = '.'; + if (p == 1) + c = '+'; + if (p == 2) + c = '*'; + if (p == 3) + c = '\n'; + BIO_write(BN_GENCB_get_arg(cb), &c, 1); + (void)BIO_flush(BN_GENCB_get_arg(cb)); + return 1; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/nseq.c b/trunk/3rdparty/openssl-1.1-fit/apps/nseq.c new file mode 100644 index 000000000..a067c9159 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/nseq.c @@ -0,0 +1,114 @@ +/* + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_TOSEQ, OPT_IN, OPT_OUT +} OPTION_CHOICE; + +const OPTIONS nseq_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"toseq", OPT_TOSEQ, '-', "Output NS Sequence file"}, + {"in", OPT_IN, '<', "Input file"}, + {"out", OPT_OUT, '>', "Output file"}, + {NULL} +}; + +int nseq_main(int argc, char **argv) +{ + BIO *in = NULL, *out = NULL; + X509 *x509 = NULL; + NETSCAPE_CERT_SEQUENCE *seq = NULL; + OPTION_CHOICE o; + int toseq = 0, ret = 1, i; + char *infile = NULL, *outfile = NULL, *prog; + + prog = opt_init(argc, argv, nseq_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + ret = 0; + opt_help(nseq_options); + goto end; + case OPT_TOSEQ: + toseq = 1; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + } + } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + + in = bio_open_default(infile, 'r', FORMAT_PEM); + if (in == NULL) + goto end; + out = bio_open_default(outfile, 'w', FORMAT_PEM); + if (out == NULL) + goto end; + + if (toseq) { + seq = NETSCAPE_CERT_SEQUENCE_new(); + if (seq == NULL) + goto end; + seq->certs = sk_X509_new_null(); + if (seq->certs == NULL) + goto end; + while ((x509 = PEM_read_bio_X509(in, NULL, NULL, NULL))) + sk_X509_push(seq->certs, x509); + + if (!sk_X509_num(seq->certs)) { + BIO_printf(bio_err, "%s: Error reading certs file %s\n", + prog, infile); + ERR_print_errors(bio_err); + goto end; + } + PEM_write_bio_NETSCAPE_CERT_SEQUENCE(out, seq); + ret = 0; + goto end; + } + + seq = PEM_read_bio_NETSCAPE_CERT_SEQUENCE(in, NULL, NULL, NULL); + if (seq == NULL) { + BIO_printf(bio_err, "%s: Error reading sequence file %s\n", + prog, infile); + ERR_print_errors(bio_err); + goto end; + } + + for (i = 0; i < sk_X509_num(seq->certs); i++) { + x509 = sk_X509_value(seq->certs, i); + dump_cert_text(out, x509); + PEM_write_bio_X509(out, x509); + } + ret = 0; + end: + BIO_free(in); + BIO_free_all(out); + NETSCAPE_CERT_SEQUENCE_free(seq); + + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/ocsp.c b/trunk/3rdparty/openssl-1.1-fit/apps/ocsp.c new file mode 100644 index 000000000..e8aeb11cc --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/ocsp.c @@ -0,0 +1,1621 @@ +/* + * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#ifdef OPENSSL_NO_OCSP +NON_EMPTY_TRANSLATION_UNIT +#else +# ifdef OPENSSL_SYS_VMS +# define _XOPEN_SOURCE_EXTENDED/* So fd_set and friends get properly defined + * on OpenVMS */ +# endif + +# include +# include +# include +# include +# include + +/* Needs to be included before the openssl headers */ +# include "apps.h" +# include "progs.h" +# include "internal/sockets.h" +# include +# include +# include +# include +# include +# include +# include +# include + +#ifndef HAVE_FORK +# if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_WINDOWS) +# define HAVE_FORK 0 +# else +# define HAVE_FORK 1 +# endif +#endif + +#if HAVE_FORK +# undef NO_FORK +#else +# define NO_FORK +#endif + +# if !defined(NO_FORK) && !defined(OPENSSL_NO_SOCK) \ + && !defined(OPENSSL_NO_POSIX_IO) +# define OCSP_DAEMON +# include +# include +# include +# include +# define MAXERRLEN 1000 /* limit error text sent to syslog to 1000 bytes */ +# else +# undef LOG_INFO +# undef LOG_WARNING +# undef LOG_ERR +# define LOG_INFO 0 +# define LOG_WARNING 1 +# define LOG_ERR 2 +# endif + +# if defined(OPENSSL_SYS_VXWORKS) +/* not supported */ +int setpgid(pid_t pid, pid_t pgid) +{ + errno = ENOSYS; + return 0; +} +/* not supported */ +pid_t fork(void) +{ + errno = ENOSYS; + return (pid_t) -1; +} +# endif +/* Maximum leeway in validity period: default 5 minutes */ +# define MAX_VALIDITY_PERIOD (5 * 60) + +static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, + const EVP_MD *cert_id_md, X509 *issuer, + STACK_OF(OCSP_CERTID) *ids); +static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, + const EVP_MD *cert_id_md, X509 *issuer, + STACK_OF(OCSP_CERTID) *ids); +static void print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req, + STACK_OF(OPENSSL_STRING) *names, + STACK_OF(OCSP_CERTID) *ids, long nsec, + long maxage); +static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req, + CA_DB *db, STACK_OF(X509) *ca, X509 *rcert, + EVP_PKEY *rkey, const EVP_MD *md, + STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(X509) *rother, unsigned long flags, + int nmin, int ndays, int badsig); + +static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser); +static BIO *init_responder(const char *port); +static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, int timeout); +static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp); +static void log_message(int level, const char *fmt, ...); +static char *prog; +static int multi = 0; + +# ifdef OCSP_DAEMON +static int acfd = (int) INVALID_SOCKET; +static int index_changed(CA_DB *); +static void spawn_loop(void); +static int print_syslog(const char *str, size_t len, void *levPtr); +static void sock_timeout(int signum); +# endif + +# ifndef OPENSSL_NO_SOCK +static OCSP_RESPONSE *query_responder(BIO *cbio, const char *host, + const char *path, + const STACK_OF(CONF_VALUE) *headers, + OCSP_REQUEST *req, int req_timeout); +# endif + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_OUTFILE, OPT_TIMEOUT, OPT_URL, OPT_HOST, OPT_PORT, + OPT_IGNORE_ERR, OPT_NOVERIFY, OPT_NONCE, OPT_NO_NONCE, + OPT_RESP_NO_CERTS, OPT_RESP_KEY_ID, OPT_NO_CERTS, + OPT_NO_SIGNATURE_VERIFY, OPT_NO_CERT_VERIFY, OPT_NO_CHAIN, + OPT_NO_CERT_CHECKS, OPT_NO_EXPLICIT, OPT_TRUST_OTHER, + OPT_NO_INTERN, OPT_BADSIG, OPT_TEXT, OPT_REQ_TEXT, OPT_RESP_TEXT, + OPT_REQIN, OPT_RESPIN, OPT_SIGNER, OPT_VAFILE, OPT_SIGN_OTHER, + OPT_VERIFY_OTHER, OPT_CAFILE, OPT_CAPATH, OPT_NOCAFILE, OPT_NOCAPATH, + OPT_VALIDITY_PERIOD, OPT_STATUS_AGE, OPT_SIGNKEY, OPT_REQOUT, + OPT_RESPOUT, OPT_PATH, OPT_ISSUER, OPT_CERT, OPT_SERIAL, + OPT_INDEX, OPT_CA, OPT_NMIN, OPT_REQUEST, OPT_NDAYS, OPT_RSIGNER, + OPT_RKEY, OPT_ROTHER, OPT_RMD, OPT_RSIGOPT, OPT_HEADER, + OPT_V_ENUM, + OPT_MD, + OPT_MULTI +} OPTION_CHOICE; + +const OPTIONS ocsp_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"out", OPT_OUTFILE, '>', "Output filename"}, + {"timeout", OPT_TIMEOUT, 'p', + "Connection timeout (in seconds) to the OCSP responder"}, + {"url", OPT_URL, 's', "Responder URL"}, + {"host", OPT_HOST, 's', "TCP/IP hostname:port to connect to"}, + {"port", OPT_PORT, 'p', "Port to run responder on"}, + {"ignore_err", OPT_IGNORE_ERR, '-', + "Ignore error on OCSP request or response and continue running"}, + {"noverify", OPT_NOVERIFY, '-', "Don't verify response at all"}, + {"nonce", OPT_NONCE, '-', "Add OCSP nonce to request"}, + {"no_nonce", OPT_NO_NONCE, '-', "Don't add OCSP nonce to request"}, + {"resp_no_certs", OPT_RESP_NO_CERTS, '-', + "Don't include any certificates in response"}, + {"resp_key_id", OPT_RESP_KEY_ID, '-', + "Identify response by signing certificate key ID"}, +# ifdef OCSP_DAEMON + {"multi", OPT_MULTI, 'p', "run multiple responder processes"}, +# endif + {"no_certs", OPT_NO_CERTS, '-', + "Don't include any certificates in signed request"}, + {"no_signature_verify", OPT_NO_SIGNATURE_VERIFY, '-', + "Don't check signature on response"}, + {"no_cert_verify", OPT_NO_CERT_VERIFY, '-', + "Don't check signing certificate"}, + {"no_chain", OPT_NO_CHAIN, '-', "Don't chain verify response"}, + {"no_cert_checks", OPT_NO_CERT_CHECKS, '-', + "Don't do additional checks on signing certificate"}, + {"no_explicit", OPT_NO_EXPLICIT, '-', + "Do not explicitly check the chain, just verify the root"}, + {"trust_other", OPT_TRUST_OTHER, '-', + "Don't verify additional certificates"}, + {"no_intern", OPT_NO_INTERN, '-', + "Don't search certificates contained in response for signer"}, + {"badsig", OPT_BADSIG, '-', + "Corrupt last byte of loaded OSCP response signature (for test)"}, + {"text", OPT_TEXT, '-', "Print text form of request and response"}, + {"req_text", OPT_REQ_TEXT, '-', "Print text form of request"}, + {"resp_text", OPT_RESP_TEXT, '-', "Print text form of response"}, + {"reqin", OPT_REQIN, 's', "File with the DER-encoded request"}, + {"respin", OPT_RESPIN, 's', "File with the DER-encoded response"}, + {"signer", OPT_SIGNER, '<', "Certificate to sign OCSP request with"}, + {"VAfile", OPT_VAFILE, '<', "Validator certificates file"}, + {"sign_other", OPT_SIGN_OTHER, '<', + "Additional certificates to include in signed request"}, + {"verify_other", OPT_VERIFY_OTHER, '<', + "Additional certificates to search for signer"}, + {"CAfile", OPT_CAFILE, '<', "Trusted certificates file"}, + {"CApath", OPT_CAPATH, '<', "Trusted certificates directory"}, + {"no-CAfile", OPT_NOCAFILE, '-', + "Do not load the default certificates file"}, + {"no-CApath", OPT_NOCAPATH, '-', + "Do not load certificates from the default certificates directory"}, + {"validity_period", OPT_VALIDITY_PERIOD, 'u', + "Maximum validity discrepancy in seconds"}, + {"status_age", OPT_STATUS_AGE, 'p', "Maximum status age in seconds"}, + {"signkey", OPT_SIGNKEY, 's', "Private key to sign OCSP request with"}, + {"reqout", OPT_REQOUT, 's', "Output file for the DER-encoded request"}, + {"respout", OPT_RESPOUT, 's', "Output file for the DER-encoded response"}, + {"path", OPT_PATH, 's', "Path to use in OCSP request"}, + {"issuer", OPT_ISSUER, '<', "Issuer certificate"}, + {"cert", OPT_CERT, '<', "Certificate to check"}, + {"serial", OPT_SERIAL, 's', "Serial number to check"}, + {"index", OPT_INDEX, '<', "Certificate status index file"}, + {"CA", OPT_CA, '<', "CA certificate"}, + {"nmin", OPT_NMIN, 'p', "Number of minutes before next update"}, + {"nrequest", OPT_REQUEST, 'p', + "Number of requests to accept (default unlimited)"}, + {"ndays", OPT_NDAYS, 'p', "Number of days before next update"}, + {"rsigner", OPT_RSIGNER, '<', + "Responder certificate to sign responses with"}, + {"rkey", OPT_RKEY, '<', "Responder key to sign responses with"}, + {"rother", OPT_ROTHER, '<', "Other certificates to include in response"}, + {"rmd", OPT_RMD, 's', "Digest Algorithm to use in signature of OCSP response"}, + {"rsigopt", OPT_RSIGOPT, 's', "OCSP response signature parameter in n:v form"}, + {"header", OPT_HEADER, 's', "key=value header to add"}, + {"", OPT_MD, '-', "Any supported digest algorithm (sha1,sha256, ... )"}, + OPT_V_OPTIONS, + {NULL} +}; + +int ocsp_main(int argc, char **argv) +{ + BIO *acbio = NULL, *cbio = NULL, *derbio = NULL, *out = NULL; + const EVP_MD *cert_id_md = NULL, *rsign_md = NULL; + STACK_OF(OPENSSL_STRING) *rsign_sigopts = NULL; + int trailing_md = 0; + CA_DB *rdb = NULL; + EVP_PKEY *key = NULL, *rkey = NULL; + OCSP_BASICRESP *bs = NULL; + OCSP_REQUEST *req = NULL; + OCSP_RESPONSE *resp = NULL; + STACK_OF(CONF_VALUE) *headers = NULL; + STACK_OF(OCSP_CERTID) *ids = NULL; + STACK_OF(OPENSSL_STRING) *reqnames = NULL; + STACK_OF(X509) *sign_other = NULL, *verify_other = NULL, *rother = NULL; + STACK_OF(X509) *issuers = NULL; + X509 *issuer = NULL, *cert = NULL; + STACK_OF(X509) *rca_cert = NULL; + X509 *signer = NULL, *rsigner = NULL; + X509_STORE *store = NULL; + X509_VERIFY_PARAM *vpm = NULL; + const char *CAfile = NULL, *CApath = NULL; + char *header, *value; + char *host = NULL, *port = NULL, *path = "/", *outfile = NULL; + char *rca_filename = NULL, *reqin = NULL, *respin = NULL; + char *reqout = NULL, *respout = NULL, *ridx_filename = NULL; + char *rsignfile = NULL, *rkeyfile = NULL; + char *sign_certfile = NULL, *verify_certfile = NULL, *rcertfile = NULL; + char *signfile = NULL, *keyfile = NULL; + char *thost = NULL, *tport = NULL, *tpath = NULL; + int noCAfile = 0, noCApath = 0; + int accept_count = -1, add_nonce = 1, noverify = 0, use_ssl = -1; + int vpmtouched = 0, badsig = 0, i, ignore_err = 0, nmin = 0, ndays = -1; + int req_text = 0, resp_text = 0, ret = 1; + int req_timeout = -1; + long nsec = MAX_VALIDITY_PERIOD, maxage = -1; + unsigned long sign_flags = 0, verify_flags = 0, rflags = 0; + OPTION_CHOICE o; + + reqnames = sk_OPENSSL_STRING_new_null(); + if (reqnames == NULL) + goto end; + ids = sk_OCSP_CERTID_new_null(); + if (ids == NULL) + goto end; + if ((vpm = X509_VERIFY_PARAM_new()) == NULL) + return 1; + + prog = opt_init(argc, argv, ocsp_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + ret = 0; + opt_help(ocsp_options); + goto end; + case OPT_OUTFILE: + outfile = opt_arg(); + break; + case OPT_TIMEOUT: +#ifndef OPENSSL_NO_SOCK + req_timeout = atoi(opt_arg()); +#endif + break; + case OPT_URL: + OPENSSL_free(thost); + OPENSSL_free(tport); + OPENSSL_free(tpath); + thost = tport = tpath = NULL; + if (!OCSP_parse_url(opt_arg(), &host, &port, &path, &use_ssl)) { + BIO_printf(bio_err, "%s Error parsing URL\n", prog); + goto end; + } + thost = host; + tport = port; + tpath = path; + break; + case OPT_HOST: + host = opt_arg(); + break; + case OPT_PORT: + port = opt_arg(); + break; + case OPT_IGNORE_ERR: + ignore_err = 1; + break; + case OPT_NOVERIFY: + noverify = 1; + break; + case OPT_NONCE: + add_nonce = 2; + break; + case OPT_NO_NONCE: + add_nonce = 0; + break; + case OPT_RESP_NO_CERTS: + rflags |= OCSP_NOCERTS; + break; + case OPT_RESP_KEY_ID: + rflags |= OCSP_RESPID_KEY; + break; + case OPT_NO_CERTS: + sign_flags |= OCSP_NOCERTS; + break; + case OPT_NO_SIGNATURE_VERIFY: + verify_flags |= OCSP_NOSIGS; + break; + case OPT_NO_CERT_VERIFY: + verify_flags |= OCSP_NOVERIFY; + break; + case OPT_NO_CHAIN: + verify_flags |= OCSP_NOCHAIN; + break; + case OPT_NO_CERT_CHECKS: + verify_flags |= OCSP_NOCHECKS; + break; + case OPT_NO_EXPLICIT: + verify_flags |= OCSP_NOEXPLICIT; + break; + case OPT_TRUST_OTHER: + verify_flags |= OCSP_TRUSTOTHER; + break; + case OPT_NO_INTERN: + verify_flags |= OCSP_NOINTERN; + break; + case OPT_BADSIG: + badsig = 1; + break; + case OPT_TEXT: + req_text = resp_text = 1; + break; + case OPT_REQ_TEXT: + req_text = 1; + break; + case OPT_RESP_TEXT: + resp_text = 1; + break; + case OPT_REQIN: + reqin = opt_arg(); + break; + case OPT_RESPIN: + respin = opt_arg(); + break; + case OPT_SIGNER: + signfile = opt_arg(); + break; + case OPT_VAFILE: + verify_certfile = opt_arg(); + verify_flags |= OCSP_TRUSTOTHER; + break; + case OPT_SIGN_OTHER: + sign_certfile = opt_arg(); + break; + case OPT_VERIFY_OTHER: + verify_certfile = opt_arg(); + break; + case OPT_CAFILE: + CAfile = opt_arg(); + break; + case OPT_CAPATH: + CApath = opt_arg(); + break; + case OPT_NOCAFILE: + noCAfile = 1; + break; + case OPT_NOCAPATH: + noCApath = 1; + break; + case OPT_V_CASES: + if (!opt_verify(o, vpm)) + goto end; + vpmtouched++; + break; + case OPT_VALIDITY_PERIOD: + opt_long(opt_arg(), &nsec); + break; + case OPT_STATUS_AGE: + opt_long(opt_arg(), &maxage); + break; + case OPT_SIGNKEY: + keyfile = opt_arg(); + break; + case OPT_REQOUT: + reqout = opt_arg(); + break; + case OPT_RESPOUT: + respout = opt_arg(); + break; + case OPT_PATH: + path = opt_arg(); + break; + case OPT_ISSUER: + issuer = load_cert(opt_arg(), FORMAT_PEM, "issuer certificate"); + if (issuer == NULL) + goto end; + if (issuers == NULL) { + if ((issuers = sk_X509_new_null()) == NULL) + goto end; + } + sk_X509_push(issuers, issuer); + break; + case OPT_CERT: + X509_free(cert); + cert = load_cert(opt_arg(), FORMAT_PEM, "certificate"); + if (cert == NULL) + goto end; + if (cert_id_md == NULL) + cert_id_md = EVP_sha1(); + if (!add_ocsp_cert(&req, cert, cert_id_md, issuer, ids)) + goto end; + if (!sk_OPENSSL_STRING_push(reqnames, opt_arg())) + goto end; + trailing_md = 0; + break; + case OPT_SERIAL: + if (cert_id_md == NULL) + cert_id_md = EVP_sha1(); + if (!add_ocsp_serial(&req, opt_arg(), cert_id_md, issuer, ids)) + goto end; + if (!sk_OPENSSL_STRING_push(reqnames, opt_arg())) + goto end; + trailing_md = 0; + break; + case OPT_INDEX: + ridx_filename = opt_arg(); + break; + case OPT_CA: + rca_filename = opt_arg(); + break; + case OPT_NMIN: + opt_int(opt_arg(), &nmin); + if (ndays == -1) + ndays = 0; + break; + case OPT_REQUEST: + opt_int(opt_arg(), &accept_count); + break; + case OPT_NDAYS: + ndays = atoi(opt_arg()); + break; + case OPT_RSIGNER: + rsignfile = opt_arg(); + break; + case OPT_RKEY: + rkeyfile = opt_arg(); + break; + case OPT_ROTHER: + rcertfile = opt_arg(); + break; + case OPT_RMD: /* Response MessageDigest */ + if (!opt_md(opt_arg(), &rsign_md)) + goto end; + break; + case OPT_RSIGOPT: + if (rsign_sigopts == NULL) + rsign_sigopts = sk_OPENSSL_STRING_new_null(); + if (rsign_sigopts == NULL || !sk_OPENSSL_STRING_push(rsign_sigopts, opt_arg())) + goto end; + break; + case OPT_HEADER: + header = opt_arg(); + value = strchr(header, '='); + if (value == NULL) { + BIO_printf(bio_err, "Missing = in header key=value\n"); + goto opthelp; + } + *value++ = '\0'; + if (!X509V3_add_value(header, value, &headers)) + goto end; + break; + case OPT_MD: + if (trailing_md) { + BIO_printf(bio_err, + "%s: Digest must be before -cert or -serial\n", + prog); + goto opthelp; + } + if (!opt_md(opt_unknown(), &cert_id_md)) + goto opthelp; + trailing_md = 1; + break; + case OPT_MULTI: +# ifdef OCSP_DAEMON + multi = atoi(opt_arg()); +# endif + break; + } + } + if (trailing_md) { + BIO_printf(bio_err, "%s: Digest must be before -cert or -serial\n", + prog); + goto opthelp; + } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + + /* Have we anything to do? */ + if (req == NULL && reqin == NULL + && respin == NULL && !(port != NULL && ridx_filename != NULL)) + goto opthelp; + + out = bio_open_default(outfile, 'w', FORMAT_TEXT); + if (out == NULL) + goto end; + + if (req == NULL && (add_nonce != 2)) + add_nonce = 0; + + if (req == NULL && reqin != NULL) { + derbio = bio_open_default(reqin, 'r', FORMAT_ASN1); + if (derbio == NULL) + goto end; + req = d2i_OCSP_REQUEST_bio(derbio, NULL); + BIO_free(derbio); + if (req == NULL) { + BIO_printf(bio_err, "Error reading OCSP request\n"); + goto end; + } + } + + if (req == NULL && port != NULL) { + acbio = init_responder(port); + if (acbio == NULL) + goto end; + } + + if (rsignfile != NULL) { + if (rkeyfile == NULL) + rkeyfile = rsignfile; + rsigner = load_cert(rsignfile, FORMAT_PEM, "responder certificate"); + if (rsigner == NULL) { + BIO_printf(bio_err, "Error loading responder certificate\n"); + goto end; + } + if (!load_certs(rca_filename, &rca_cert, FORMAT_PEM, + NULL, "CA certificate")) + goto end; + if (rcertfile != NULL) { + if (!load_certs(rcertfile, &rother, FORMAT_PEM, NULL, + "responder other certificates")) + goto end; + } + rkey = load_key(rkeyfile, FORMAT_PEM, 0, NULL, NULL, + "responder private key"); + if (rkey == NULL) + goto end; + } + + if (ridx_filename != NULL + && (rkey == NULL || rsigner == NULL || rca_cert == NULL)) { + BIO_printf(bio_err, + "Responder mode requires certificate, key, and CA.\n"); + goto end; + } + + if (ridx_filename != NULL) { + rdb = load_index(ridx_filename, NULL); + if (rdb == NULL || index_index(rdb) <= 0) { + ret = 1; + goto end; + } + } + +# ifdef OCSP_DAEMON + if (multi && acbio != NULL) + spawn_loop(); + if (acbio != NULL && req_timeout > 0) + signal(SIGALRM, sock_timeout); +#endif + + if (acbio != NULL) + log_message(LOG_INFO, "waiting for OCSP client connections..."); + +redo_accept: + + if (acbio != NULL) { +# ifdef OCSP_DAEMON + if (index_changed(rdb)) { + CA_DB *newrdb = load_index(ridx_filename, NULL); + + if (newrdb != NULL && index_index(newrdb) > 0) { + free_index(rdb); + rdb = newrdb; + } else { + free_index(newrdb); + log_message(LOG_ERR, "error reloading updated index: %s", + ridx_filename); + } + } +# endif + + req = NULL; + if (!do_responder(&req, &cbio, acbio, req_timeout)) + goto redo_accept; + + if (req == NULL) { + resp = + OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, + NULL); + send_ocsp_response(cbio, resp); + goto done_resp; + } + } + + if (req == NULL + && (signfile != NULL || reqout != NULL + || host != NULL || add_nonce || ridx_filename != NULL)) { + BIO_printf(bio_err, "Need an OCSP request for this operation!\n"); + goto end; + } + + if (req != NULL && add_nonce) + OCSP_request_add1_nonce(req, NULL, -1); + + if (signfile != NULL) { + if (keyfile == NULL) + keyfile = signfile; + signer = load_cert(signfile, FORMAT_PEM, "signer certificate"); + if (signer == NULL) { + BIO_printf(bio_err, "Error loading signer certificate\n"); + goto end; + } + if (sign_certfile != NULL) { + if (!load_certs(sign_certfile, &sign_other, FORMAT_PEM, NULL, + "signer certificates")) + goto end; + } + key = load_key(keyfile, FORMAT_PEM, 0, NULL, NULL, + "signer private key"); + if (key == NULL) + goto end; + + if (!OCSP_request_sign + (req, signer, key, NULL, sign_other, sign_flags)) { + BIO_printf(bio_err, "Error signing OCSP request\n"); + goto end; + } + } + + if (req_text && req != NULL) + OCSP_REQUEST_print(out, req, 0); + + if (reqout != NULL) { + derbio = bio_open_default(reqout, 'w', FORMAT_ASN1); + if (derbio == NULL) + goto end; + i2d_OCSP_REQUEST_bio(derbio, req); + BIO_free(derbio); + } + + if (rdb != NULL) { + make_ocsp_response(bio_err, &resp, req, rdb, rca_cert, rsigner, rkey, + rsign_md, rsign_sigopts, rother, rflags, nmin, ndays, badsig); + if (cbio != NULL) + send_ocsp_response(cbio, resp); + } else if (host != NULL) { +# ifndef OPENSSL_NO_SOCK + resp = process_responder(req, host, path, + port, use_ssl, headers, req_timeout); + if (resp == NULL) + goto end; +# else + BIO_printf(bio_err, + "Error creating connect BIO - sockets not supported.\n"); + goto end; +# endif + } else if (respin != NULL) { + derbio = bio_open_default(respin, 'r', FORMAT_ASN1); + if (derbio == NULL) + goto end; + resp = d2i_OCSP_RESPONSE_bio(derbio, NULL); + BIO_free(derbio); + if (resp == NULL) { + BIO_printf(bio_err, "Error reading OCSP response\n"); + goto end; + } + } else { + ret = 0; + goto end; + } + + done_resp: + + if (respout != NULL) { + derbio = bio_open_default(respout, 'w', FORMAT_ASN1); + if (derbio == NULL) + goto end; + i2d_OCSP_RESPONSE_bio(derbio, resp); + BIO_free(derbio); + } + + i = OCSP_response_status(resp); + if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL) { + BIO_printf(out, "Responder Error: %s (%d)\n", + OCSP_response_status_str(i), i); + if (!ignore_err) + goto end; + } + + if (resp_text) + OCSP_RESPONSE_print(out, resp, 0); + + /* If running as responder don't verify our own response */ + if (cbio != NULL) { + /* If not unlimited, see if we took all we should. */ + if (accept_count != -1 && --accept_count <= 0) { + ret = 0; + goto end; + } + BIO_free_all(cbio); + cbio = NULL; + OCSP_REQUEST_free(req); + req = NULL; + OCSP_RESPONSE_free(resp); + resp = NULL; + goto redo_accept; + } + if (ridx_filename != NULL) { + ret = 0; + goto end; + } + + if (store == NULL) { + store = setup_verify(CAfile, CApath, noCAfile, noCApath); + if (!store) + goto end; + } + if (vpmtouched) + X509_STORE_set1_param(store, vpm); + if (verify_certfile != NULL) { + if (!load_certs(verify_certfile, &verify_other, FORMAT_PEM, NULL, + "validator certificate")) + goto end; + } + + bs = OCSP_response_get1_basic(resp); + if (bs == NULL) { + BIO_printf(bio_err, "Error parsing response\n"); + goto end; + } + + ret = 0; + + if (!noverify) { + if (req != NULL && ((i = OCSP_check_nonce(req, bs)) <= 0)) { + if (i == -1) + BIO_printf(bio_err, "WARNING: no nonce in response\n"); + else { + BIO_printf(bio_err, "Nonce Verify error\n"); + ret = 1; + goto end; + } + } + + i = OCSP_basic_verify(bs, verify_other, store, verify_flags); + if (i <= 0 && issuers) { + i = OCSP_basic_verify(bs, issuers, store, OCSP_TRUSTOTHER); + if (i > 0) + ERR_clear_error(); + } + if (i <= 0) { + BIO_printf(bio_err, "Response Verify Failure\n"); + ERR_print_errors(bio_err); + ret = 1; + } else { + BIO_printf(bio_err, "Response verify OK\n"); + } + } + + print_ocsp_summary(out, bs, req, reqnames, ids, nsec, maxage); + + end: + ERR_print_errors(bio_err); + X509_free(signer); + X509_STORE_free(store); + X509_VERIFY_PARAM_free(vpm); + sk_OPENSSL_STRING_free(rsign_sigopts); + EVP_PKEY_free(key); + EVP_PKEY_free(rkey); + X509_free(cert); + sk_X509_pop_free(issuers, X509_free); + X509_free(rsigner); + sk_X509_pop_free(rca_cert, X509_free); + free_index(rdb); + BIO_free_all(cbio); + BIO_free_all(acbio); + BIO_free_all(out); + OCSP_REQUEST_free(req); + OCSP_RESPONSE_free(resp); + OCSP_BASICRESP_free(bs); + sk_OPENSSL_STRING_free(reqnames); + sk_OCSP_CERTID_free(ids); + sk_X509_pop_free(sign_other, X509_free); + sk_X509_pop_free(verify_other, X509_free); + sk_CONF_VALUE_pop_free(headers, X509V3_conf_free); + OPENSSL_free(thost); + OPENSSL_free(tport); + OPENSSL_free(tpath); + + return ret; +} + +static void +log_message(int level, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); +# ifdef OCSP_DAEMON + if (multi) { + char buf[1024]; + if (vsnprintf(buf, sizeof(buf), fmt, ap) > 0) { + syslog(level, "%s", buf); + } + if (level >= LOG_ERR) + ERR_print_errors_cb(print_syslog, &level); + } +# endif + if (!multi) { + BIO_printf(bio_err, "%s: ", prog); + BIO_vprintf(bio_err, fmt, ap); + BIO_printf(bio_err, "\n"); + } + va_end(ap); +} + +# ifdef OCSP_DAEMON + +static int print_syslog(const char *str, size_t len, void *levPtr) +{ + int level = *(int *)levPtr; + int ilen = (len > MAXERRLEN) ? MAXERRLEN : len; + + syslog(level, "%.*s", ilen, str); + + return ilen; +} + +static int index_changed(CA_DB *rdb) +{ + struct stat sb; + + if (rdb != NULL && stat(rdb->dbfname, &sb) != -1) { + if (rdb->dbst.st_mtime != sb.st_mtime + || rdb->dbst.st_ctime != sb.st_ctime + || rdb->dbst.st_ino != sb.st_ino + || rdb->dbst.st_dev != sb.st_dev) { + syslog(LOG_INFO, "index file changed, reloading"); + return 1; + } + } + return 0; +} + +static void killall(int ret, pid_t *kidpids) +{ + int i; + + for (i = 0; i < multi; ++i) + if (kidpids[i] != 0) + (void)kill(kidpids[i], SIGTERM); + OPENSSL_free(kidpids); + sleep(1); + exit(ret); +} + +static int termsig = 0; + +static void noteterm (int sig) +{ + termsig = sig; +} + +/* + * Loop spawning up to `multi` child processes, only child processes return + * from this function. The parent process loops until receiving a termination + * signal, kills extant children and exits without returning. + */ +static void spawn_loop(void) +{ + pid_t *kidpids = NULL; + int status; + int procs = 0; + int i; + + openlog(prog, LOG_PID, LOG_DAEMON); + + if (setpgid(0, 0)) { + syslog(LOG_ERR, "fatal: error detaching from parent process group: %s", + strerror(errno)); + exit(1); + } + kidpids = app_malloc(multi * sizeof(*kidpids), "child PID array"); + for (i = 0; i < multi; ++i) + kidpids[i] = 0; + + signal(SIGINT, noteterm); + signal(SIGTERM, noteterm); + + while (termsig == 0) { + pid_t fpid; + + /* + * Wait for a child to replace when we're at the limit. + * Slow down if a child exited abnormally or waitpid() < 0 + */ + while (termsig == 0 && procs >= multi) { + if ((fpid = waitpid(-1, &status, 0)) > 0) { + for (i = 0; i < procs; ++i) { + if (kidpids[i] == fpid) { + kidpids[i] = 0; + --procs; + break; + } + } + if (i >= multi) { + syslog(LOG_ERR, "fatal: internal error: " + "no matching child slot for pid: %ld", + (long) fpid); + killall(1, kidpids); + } + if (status != 0) { + if (WIFEXITED(status)) + syslog(LOG_WARNING, "child process: %ld, exit status: %d", + (long)fpid, WEXITSTATUS(status)); + else if (WIFSIGNALED(status)) + syslog(LOG_WARNING, "child process: %ld, term signal %d%s", + (long)fpid, WTERMSIG(status), +#ifdef WCOREDUMP + WCOREDUMP(status) ? " (core dumped)" : +#endif + ""); + sleep(1); + } + break; + } else if (errno != EINTR) { + syslog(LOG_ERR, "fatal: waitpid(): %s", strerror(errno)); + killall(1, kidpids); + } + } + if (termsig) + break; + + switch(fpid = fork()) { + case -1: /* error */ + /* System critically low on memory, pause and try again later */ + sleep(30); + break; + case 0: /* child */ + OPENSSL_free(kidpids); + signal(SIGINT, SIG_DFL); + signal(SIGTERM, SIG_DFL); + if (termsig) + _exit(0); + if (RAND_poll() <= 0) { + syslog(LOG_ERR, "fatal: RAND_poll() failed"); + _exit(1); + } + return; + default: /* parent */ + for (i = 0; i < multi; ++i) { + if (kidpids[i] == 0) { + kidpids[i] = fpid; + procs++; + break; + } + } + if (i >= multi) { + syslog(LOG_ERR, "fatal: internal error: no free child slots"); + killall(1, kidpids); + } + break; + } + } + + /* The loop above can only break on termsig */ + syslog(LOG_INFO, "terminating on signal: %d", termsig); + killall(0, kidpids); +} +# endif + +static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, + const EVP_MD *cert_id_md, X509 *issuer, + STACK_OF(OCSP_CERTID) *ids) +{ + OCSP_CERTID *id; + + if (issuer == NULL) { + BIO_printf(bio_err, "No issuer certificate specified\n"); + return 0; + } + if (*req == NULL) + *req = OCSP_REQUEST_new(); + if (*req == NULL) + goto err; + id = OCSP_cert_to_id(cert_id_md, cert, issuer); + if (id == NULL || !sk_OCSP_CERTID_push(ids, id)) + goto err; + if (!OCSP_request_add0_id(*req, id)) + goto err; + return 1; + + err: + BIO_printf(bio_err, "Error Creating OCSP request\n"); + return 0; +} + +static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, + const EVP_MD *cert_id_md, X509 *issuer, + STACK_OF(OCSP_CERTID) *ids) +{ + OCSP_CERTID *id; + X509_NAME *iname; + ASN1_BIT_STRING *ikey; + ASN1_INTEGER *sno; + + if (issuer == NULL) { + BIO_printf(bio_err, "No issuer certificate specified\n"); + return 0; + } + if (*req == NULL) + *req = OCSP_REQUEST_new(); + if (*req == NULL) + goto err; + iname = X509_get_subject_name(issuer); + ikey = X509_get0_pubkey_bitstr(issuer); + sno = s2i_ASN1_INTEGER(NULL, serial); + if (sno == NULL) { + BIO_printf(bio_err, "Error converting serial number %s\n", serial); + return 0; + } + id = OCSP_cert_id_new(cert_id_md, iname, ikey, sno); + ASN1_INTEGER_free(sno); + if (id == NULL || !sk_OCSP_CERTID_push(ids, id)) + goto err; + if (!OCSP_request_add0_id(*req, id)) + goto err; + return 1; + + err: + BIO_printf(bio_err, "Error Creating OCSP request\n"); + return 0; +} + +static void print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req, + STACK_OF(OPENSSL_STRING) *names, + STACK_OF(OCSP_CERTID) *ids, long nsec, + long maxage) +{ + OCSP_CERTID *id; + const char *name; + int i, status, reason; + ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; + + if (bs == NULL || req == NULL || !sk_OPENSSL_STRING_num(names) + || !sk_OCSP_CERTID_num(ids)) + return; + + for (i = 0; i < sk_OCSP_CERTID_num(ids); i++) { + id = sk_OCSP_CERTID_value(ids, i); + name = sk_OPENSSL_STRING_value(names, i); + BIO_printf(out, "%s: ", name); + + if (!OCSP_resp_find_status(bs, id, &status, &reason, + &rev, &thisupd, &nextupd)) { + BIO_puts(out, "ERROR: No Status found.\n"); + continue; + } + + /* + * Check validity: if invalid write to output BIO so we know which + * response this refers to. + */ + if (!OCSP_check_validity(thisupd, nextupd, nsec, maxage)) { + BIO_puts(out, "WARNING: Status times invalid.\n"); + ERR_print_errors(out); + } + BIO_printf(out, "%s\n", OCSP_cert_status_str(status)); + + BIO_puts(out, "\tThis Update: "); + ASN1_GENERALIZEDTIME_print(out, thisupd); + BIO_puts(out, "\n"); + + if (nextupd) { + BIO_puts(out, "\tNext Update: "); + ASN1_GENERALIZEDTIME_print(out, nextupd); + BIO_puts(out, "\n"); + } + + if (status != V_OCSP_CERTSTATUS_REVOKED) + continue; + + if (reason != -1) + BIO_printf(out, "\tReason: %s\n", OCSP_crl_reason_str(reason)); + + BIO_puts(out, "\tRevocation Time: "); + ASN1_GENERALIZEDTIME_print(out, rev); + BIO_puts(out, "\n"); + } +} + +static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req, + CA_DB *db, STACK_OF(X509) *ca, X509 *rcert, + EVP_PKEY *rkey, const EVP_MD *rmd, + STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(X509) *rother, unsigned long flags, + int nmin, int ndays, int badsig) +{ + ASN1_TIME *thisupd = NULL, *nextupd = NULL; + OCSP_CERTID *cid; + OCSP_BASICRESP *bs = NULL; + int i, id_count; + EVP_MD_CTX *mctx = NULL; + EVP_PKEY_CTX *pkctx = NULL; + + id_count = OCSP_request_onereq_count(req); + + if (id_count <= 0) { + *resp = + OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, NULL); + goto end; + } + + bs = OCSP_BASICRESP_new(); + thisupd = X509_gmtime_adj(NULL, 0); + if (ndays != -1) + nextupd = X509_time_adj_ex(NULL, ndays, nmin * 60, NULL); + + /* Examine each certificate id in the request */ + for (i = 0; i < id_count; i++) { + OCSP_ONEREQ *one; + ASN1_INTEGER *serial; + char **inf; + int jj; + int found = 0; + ASN1_OBJECT *cert_id_md_oid; + const EVP_MD *cert_id_md; + one = OCSP_request_onereq_get0(req, i); + cid = OCSP_onereq_get0_id(one); + + OCSP_id_get0_info(NULL, &cert_id_md_oid, NULL, NULL, cid); + + cert_id_md = EVP_get_digestbyobj(cert_id_md_oid); + if (cert_id_md == NULL) { + *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR, + NULL); + goto end; + } + for (jj = 0; jj < sk_X509_num(ca) && !found; jj++) { + X509 *ca_cert = sk_X509_value(ca, jj); + OCSP_CERTID *ca_id = OCSP_cert_to_id(cert_id_md, NULL, ca_cert); + + if (OCSP_id_issuer_cmp(ca_id, cid) == 0) + found = 1; + + OCSP_CERTID_free(ca_id); + } + + if (!found) { + OCSP_basic_add1_status(bs, cid, + V_OCSP_CERTSTATUS_UNKNOWN, + 0, NULL, thisupd, nextupd); + continue; + } + OCSP_id_get0_info(NULL, NULL, NULL, &serial, cid); + inf = lookup_serial(db, serial); + if (inf == NULL) { + OCSP_basic_add1_status(bs, cid, + V_OCSP_CERTSTATUS_UNKNOWN, + 0, NULL, thisupd, nextupd); + } else if (inf[DB_type][0] == DB_TYPE_VAL) { + OCSP_basic_add1_status(bs, cid, + V_OCSP_CERTSTATUS_GOOD, + 0, NULL, thisupd, nextupd); + } else if (inf[DB_type][0] == DB_TYPE_REV) { + ASN1_OBJECT *inst = NULL; + ASN1_TIME *revtm = NULL; + ASN1_GENERALIZEDTIME *invtm = NULL; + OCSP_SINGLERESP *single; + int reason = -1; + unpack_revinfo(&revtm, &reason, &inst, &invtm, inf[DB_rev_date]); + single = OCSP_basic_add1_status(bs, cid, + V_OCSP_CERTSTATUS_REVOKED, + reason, revtm, thisupd, nextupd); + if (invtm != NULL) + OCSP_SINGLERESP_add1_ext_i2d(single, NID_invalidity_date, + invtm, 0, 0); + else if (inst != NULL) + OCSP_SINGLERESP_add1_ext_i2d(single, + NID_hold_instruction_code, inst, + 0, 0); + ASN1_OBJECT_free(inst); + ASN1_TIME_free(revtm); + ASN1_GENERALIZEDTIME_free(invtm); + } + } + + OCSP_copy_nonce(bs, req); + + mctx = EVP_MD_CTX_new(); + if ( mctx == NULL || !EVP_DigestSignInit(mctx, &pkctx, rmd, NULL, rkey)) { + *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR, NULL); + goto end; + } + for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) { + char *sigopt = sk_OPENSSL_STRING_value(sigopts, i); + + if (pkey_ctrl_string(pkctx, sigopt) <= 0) { + BIO_printf(err, "parameter error \"%s\"\n", sigopt); + ERR_print_errors(bio_err); + *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR, + NULL); + goto end; + } + } + OCSP_basic_sign_ctx(bs, rcert, mctx, rother, flags); + + if (badsig) { + const ASN1_OCTET_STRING *sig = OCSP_resp_get0_signature(bs); + corrupt_signature(sig); + } + + *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_SUCCESSFUL, bs); + + end: + EVP_MD_CTX_free(mctx); + ASN1_TIME_free(thisupd); + ASN1_TIME_free(nextupd); + OCSP_BASICRESP_free(bs); +} + +static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser) +{ + int i; + BIGNUM *bn = NULL; + char *itmp, *row[DB_NUMBER], **rrow; + for (i = 0; i < DB_NUMBER; i++) + row[i] = NULL; + bn = ASN1_INTEGER_to_BN(ser, NULL); + OPENSSL_assert(bn); /* FIXME: should report an error at this + * point and abort */ + if (BN_is_zero(bn)) + itmp = OPENSSL_strdup("00"); + else + itmp = BN_bn2hex(bn); + row[DB_serial] = itmp; + BN_free(bn); + rrow = TXT_DB_get_by_index(db->db, DB_serial, row); + OPENSSL_free(itmp); + return rrow; +} + +/* Quick and dirty OCSP server: read in and parse input request */ + +static BIO *init_responder(const char *port) +{ +# ifdef OPENSSL_NO_SOCK + BIO_printf(bio_err, + "Error setting up accept BIO - sockets not supported.\n"); + return NULL; +# else + BIO *acbio = NULL, *bufbio = NULL; + + bufbio = BIO_new(BIO_f_buffer()); + if (bufbio == NULL) + goto err; + acbio = BIO_new(BIO_s_accept()); + if (acbio == NULL + || BIO_set_bind_mode(acbio, BIO_BIND_REUSEADDR) < 0 + || BIO_set_accept_port(acbio, port) < 0) { + log_message(LOG_ERR, "Error setting up accept BIO"); + goto err; + } + + BIO_set_accept_bios(acbio, bufbio); + bufbio = NULL; + if (BIO_do_accept(acbio) <= 0) { + log_message(LOG_ERR, "Error starting accept"); + goto err; + } + + return acbio; + + err: + BIO_free_all(acbio); + BIO_free(bufbio); + return NULL; +# endif +} + +# ifndef OPENSSL_NO_SOCK +/* + * Decode %xx URL-decoding in-place. Ignores mal-formed sequences. + */ +static int urldecode(char *p) +{ + unsigned char *out = (unsigned char *)p; + unsigned char *save = out; + + for (; *p; p++) { + if (*p != '%') + *out++ = *p; + else if (isxdigit(_UC(p[1])) && isxdigit(_UC(p[2]))) { + /* Don't check, can't fail because of ixdigit() call. */ + *out++ = (OPENSSL_hexchar2int(p[1]) << 4) + | OPENSSL_hexchar2int(p[2]); + p += 2; + } + else + return -1; + } + *out = '\0'; + return (int)(out - save); +} +# endif + +# ifdef OCSP_DAEMON +static void sock_timeout(int signum) +{ + if (acfd != (int)INVALID_SOCKET) + (void)shutdown(acfd, SHUT_RD); +} +# endif + +static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, + int timeout) +{ +# ifdef OPENSSL_NO_SOCK + return 0; +# else + int len; + OCSP_REQUEST *req = NULL; + char inbuf[2048], reqbuf[2048]; + char *p, *q; + BIO *cbio = NULL, *getbio = NULL, *b64 = NULL; + const char *client; + + *preq = NULL; + + /* Connection loss before accept() is routine, ignore silently */ + if (BIO_do_accept(acbio) <= 0) + return 0; + + cbio = BIO_pop(acbio); + *pcbio = cbio; + client = BIO_get_peer_name(cbio); + +# ifdef OCSP_DAEMON + if (timeout > 0) { + (void) BIO_get_fd(cbio, &acfd); + alarm(timeout); + } +# endif + + /* Read the request line. */ + len = BIO_gets(cbio, reqbuf, sizeof(reqbuf)); + if (len <= 0) + goto out; + + if (strncmp(reqbuf, "GET ", 4) == 0) { + /* Expecting GET {sp} /URL {sp} HTTP/1.x */ + for (p = reqbuf + 4; *p == ' '; ++p) + continue; + if (*p != '/') { + log_message(LOG_INFO, "Invalid request -- bad URL: %s", client); + goto out; + } + p++; + + /* Splice off the HTTP version identifier. */ + for (q = p; *q; q++) + if (*q == ' ') + break; + if (strncmp(q, " HTTP/1.", 8) != 0) { + log_message(LOG_INFO, + "Invalid request -- bad HTTP version: %s", client); + goto out; + } + *q = '\0'; + + /* + * Skip "GET / HTTP..." requests often used by load-balancers + */ + if (p[1] == '\0') + goto out; + + len = urldecode(p); + if (len <= 0) { + log_message(LOG_INFO, + "Invalid request -- bad URL encoding: %s", client); + goto out; + } + if ((getbio = BIO_new_mem_buf(p, len)) == NULL + || (b64 = BIO_new(BIO_f_base64())) == NULL) { + log_message(LOG_ERR, "Could not allocate base64 bio: %s", client); + goto out; + } + BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); + getbio = BIO_push(b64, getbio); + } else if (strncmp(reqbuf, "POST ", 5) != 0) { + log_message(LOG_INFO, "Invalid request -- bad HTTP verb: %s", client); + goto out; + } + + /* Read and skip past the headers. */ + for (;;) { + len = BIO_gets(cbio, inbuf, sizeof(inbuf)); + if (len <= 0) + goto out; + if ((inbuf[0] == '\r') || (inbuf[0] == '\n')) + break; + } + +# ifdef OCSP_DAEMON + /* Clear alarm before we close the client socket */ + alarm(0); + timeout = 0; +# endif + + /* Try to read OCSP request */ + if (getbio != NULL) { + req = d2i_OCSP_REQUEST_bio(getbio, NULL); + BIO_free_all(getbio); + } else { + req = d2i_OCSP_REQUEST_bio(cbio, NULL); + } + + if (req == NULL) + log_message(LOG_ERR, "Error parsing OCSP request"); + + *preq = req; + +out: +# ifdef OCSP_DAEMON + if (timeout > 0) + alarm(0); + acfd = (int)INVALID_SOCKET; +# endif + return 1; +# endif +} + +static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp) +{ + char http_resp[] = + "HTTP/1.0 200 OK\r\nContent-type: application/ocsp-response\r\n" + "Content-Length: %d\r\n\r\n"; + if (cbio == NULL) + return 0; + BIO_printf(cbio, http_resp, i2d_OCSP_RESPONSE(resp, NULL)); + i2d_OCSP_RESPONSE_bio(cbio, resp); + (void)BIO_flush(cbio); + return 1; +} + +# ifndef OPENSSL_NO_SOCK +static OCSP_RESPONSE *query_responder(BIO *cbio, const char *host, + const char *path, + const STACK_OF(CONF_VALUE) *headers, + OCSP_REQUEST *req, int req_timeout) +{ + int fd; + int rv; + int i; + int add_host = 1; + OCSP_REQ_CTX *ctx = NULL; + OCSP_RESPONSE *rsp = NULL; + fd_set confds; + struct timeval tv; + + if (req_timeout != -1) + BIO_set_nbio(cbio, 1); + + rv = BIO_do_connect(cbio); + + if ((rv <= 0) && ((req_timeout == -1) || !BIO_should_retry(cbio))) { + BIO_puts(bio_err, "Error connecting BIO\n"); + return NULL; + } + + if (BIO_get_fd(cbio, &fd) < 0) { + BIO_puts(bio_err, "Can't get connection fd\n"); + goto err; + } + + if (req_timeout != -1 && rv <= 0) { + FD_ZERO(&confds); + openssl_fdset(fd, &confds); + tv.tv_usec = 0; + tv.tv_sec = req_timeout; + rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv); + if (rv == 0) { + BIO_puts(bio_err, "Timeout on connect\n"); + return NULL; + } + } + + ctx = OCSP_sendreq_new(cbio, path, NULL, -1); + if (ctx == NULL) + return NULL; + + for (i = 0; i < sk_CONF_VALUE_num(headers); i++) { + CONF_VALUE *hdr = sk_CONF_VALUE_value(headers, i); + if (add_host == 1 && strcasecmp("host", hdr->name) == 0) + add_host = 0; + if (!OCSP_REQ_CTX_add1_header(ctx, hdr->name, hdr->value)) + goto err; + } + + if (add_host == 1 && OCSP_REQ_CTX_add1_header(ctx, "Host", host) == 0) + goto err; + + if (!OCSP_REQ_CTX_set1_req(ctx, req)) + goto err; + + for (;;) { + rv = OCSP_sendreq_nbio(&rsp, ctx); + if (rv != -1) + break; + if (req_timeout == -1) + continue; + FD_ZERO(&confds); + openssl_fdset(fd, &confds); + tv.tv_usec = 0; + tv.tv_sec = req_timeout; + if (BIO_should_read(cbio)) { + rv = select(fd + 1, (void *)&confds, NULL, NULL, &tv); + } else if (BIO_should_write(cbio)) { + rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv); + } else { + BIO_puts(bio_err, "Unexpected retry condition\n"); + goto err; + } + if (rv == 0) { + BIO_puts(bio_err, "Timeout on request\n"); + break; + } + if (rv == -1) { + BIO_puts(bio_err, "Select error\n"); + break; + } + + } + err: + OCSP_REQ_CTX_free(ctx); + + return rsp; +} + +OCSP_RESPONSE *process_responder(OCSP_REQUEST *req, + const char *host, const char *path, + const char *port, int use_ssl, + STACK_OF(CONF_VALUE) *headers, + int req_timeout) +{ + BIO *cbio = NULL; + SSL_CTX *ctx = NULL; + OCSP_RESPONSE *resp = NULL; + + cbio = BIO_new_connect(host); + if (cbio == NULL) { + BIO_printf(bio_err, "Error creating connect BIO\n"); + goto end; + } + if (port != NULL) + BIO_set_conn_port(cbio, port); + if (use_ssl == 1) { + BIO *sbio; + ctx = SSL_CTX_new(TLS_client_method()); + if (ctx == NULL) { + BIO_printf(bio_err, "Error creating SSL context.\n"); + goto end; + } + SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); + sbio = BIO_new_ssl(ctx, 1); + cbio = BIO_push(sbio, cbio); + } + + resp = query_responder(cbio, host, path, headers, req, req_timeout); + if (resp == NULL) + BIO_printf(bio_err, "Error querying OCSP responder\n"); + end: + BIO_free_all(cbio); + SSL_CTX_free(ctx); + return resp; +} +# endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/openssl-vms.cnf b/trunk/3rdparty/openssl-1.1-fit/apps/openssl-vms.cnf new file mode 100644 index 000000000..e64cc9f3a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/openssl-vms.cnf @@ -0,0 +1,350 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# Note that you can include other files from the main configuration +# file using the .include directive. +#.include filename + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca', 'req' and 'ts'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +# Policies used by the TSA examples. +tsa_policy1 = 1.2.3.4.1 +tsa_policy2 = 1.2.3.4.5.6 +tsa_policy3 = 1.2.3.4.5.7 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = sys\$disk:[.demoCA # Where everything is kept +certs = $dir.certs] # Where the issued certs are kept +crl_dir = $dir.crl] # Where the issued crl are kept +database = $dir]index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certs with same subject. +new_certs_dir = $dir.newcerts] # default place for new certs. + +certificate = $dir]cacert.pem # The CA certificate +serial = $dir]serial. # The current serial number +crlnumber = $dir]crlnumber. # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir]crl.pem # The current CRL +private_key = $dir.private]cakey.pem# The private key + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = default # use public key default MD +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 2048 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString (PKIX recommendation before 2004) +# utf8only: only UTF8Strings (PKIX recommendation after 2004). +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings. +string_mask = utf8only + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = AU +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Some-State + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = Internet Widgits Pty Ltd + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +#organizationalUnitName_default = + +commonName = Common Name (e.g. server FQDN or YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This is required for TSA certificates. +# extendedKeyUsage = critical,timeStamping + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer + +basicConstraints = critical,CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as an test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo + +#################################################################### +[ tsa ] + +default_tsa = tsa_config1 # the default TSA section + +[ tsa_config1 ] + +# These are used by the TSA reply generation only. +dir = sys\$disk:[.demoCA # TSA root directory +serial = $dir]tsaserial. # The current serial number (mandatory) +crypto_device = builtin # OpenSSL engine to use for signing +signer_cert = $dir/tsacert.pem # The TSA signing certificate + # (optional) +certs = $dir.cacert.pem] # Certificate chain to include in reply + # (optional) +signer_key = $dir/private/tsakey.pem # The TSA private key (optional) +signer_digest = sha256 # Signing digest to use. (Optional) +default_policy = tsa_policy1 # Policy if request did not specify it + # (optional) +other_policies = tsa_policy2, tsa_policy3 # acceptable policies (optional) +digests = sha1, sha256, sha384, sha512 # Acceptable message digests (mandatory) +accuracy = secs:1, millisecs:500, microsecs:100 # (optional) +clock_precision_digits = 0 # number of digits after dot. (optional) +ordering = yes # Is ordering defined for timestamps? + # (optional, default: no) +tsa_name = yes # Must the TSA name be included in the reply? + # (optional, default: no) +ess_cert_id_chain = no # Must the ESS cert id chain be included? + # (optional, default: no) +ess_cert_id_alg = sha1 # algorithm to compute certificate + # identifier (optional, default: sha1) diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/openssl.c b/trunk/3rdparty/openssl-1.1-fit/apps/openssl.c new file mode 100644 index 000000000..a872e2c5e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/openssl.c @@ -0,0 +1,826 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef OPENSSL_NO_ENGINE +# include +#endif +#include +#include "s_apps.h" +/* Needed to get the other O_xxx flags. */ +#ifdef OPENSSL_SYS_VMS +# include +#endif +#include "apps.h" +#define INCLUDE_FUNCTION_TABLE +#include "progs.h" + +/* Structure to hold the number of columns to be displayed and the + * field width used to display them. + */ +typedef struct { + int columns; + int width; +} DISPLAY_COLUMNS; + +/* Special sentinel to exit the program. */ +#define EXIT_THE_PROGRAM (-1) + +/* + * The LHASH callbacks ("hash" & "cmp") have been replaced by functions with + * the base prototypes (we cast each variable inside the function to the + * required type of "FUNCTION*"). This removes the necessity for + * macro-generated wrapper functions. + */ +static LHASH_OF(FUNCTION) *prog_init(void); +static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[]); +static void list_pkey(void); +static void list_pkey_meth(void); +static void list_type(FUNC_TYPE ft, int one); +static void list_disabled(void); +char *default_config_file = NULL; + +BIO *bio_in = NULL; +BIO *bio_out = NULL; +BIO *bio_err = NULL; + +static void calculate_columns(DISPLAY_COLUMNS *dc) +{ + FUNCTION *f; + int len, maxlen = 0; + + for (f = functions; f->name != NULL; ++f) + if (f->type == FT_general || f->type == FT_md || f->type == FT_cipher) + if ((len = strlen(f->name)) > maxlen) + maxlen = len; + + dc->width = maxlen + 2; + dc->columns = (80 - 1) / dc->width; +} + +static int apps_startup(void) +{ +#ifdef SIGPIPE + signal(SIGPIPE, SIG_IGN); +#endif + + /* Set non-default library initialisation settings */ + if (!OPENSSL_init_ssl(OPENSSL_INIT_ENGINE_ALL_BUILTIN + | OPENSSL_INIT_LOAD_CONFIG, NULL)) + return 0; + + setup_ui_method(); + + return 1; +} + +static void apps_shutdown(void) +{ + destroy_ui_method(); + destroy_prefix_method(); +} + +static char *make_config_name(void) +{ + const char *t; + size_t len; + char *p; + + if ((t = getenv("OPENSSL_CONF")) != NULL) + return OPENSSL_strdup(t); + + t = X509_get_default_cert_area(); + len = strlen(t) + 1 + strlen(OPENSSL_CONF) + 1; + p = app_malloc(len, "config filename buffer"); + strcpy(p, t); +#ifndef OPENSSL_SYS_VMS + strcat(p, "/"); +#endif + strcat(p, OPENSSL_CONF); + + return p; +} + +int main(int argc, char *argv[]) +{ + FUNCTION f, *fp; + LHASH_OF(FUNCTION) *prog = NULL; + char **copied_argv = NULL; + char *p, *pname; + char buf[1024]; + const char *prompt; + ARGS arg; + int first, n, i, ret = 0; + + arg.argv = NULL; + arg.size = 0; + + /* Set up some of the environment. */ + default_config_file = make_config_name(); + bio_in = dup_bio_in(FORMAT_TEXT); + bio_out = dup_bio_out(FORMAT_TEXT); + bio_err = dup_bio_err(FORMAT_TEXT); + +#if defined(OPENSSL_SYS_VMS) && defined(__DECC) + copied_argv = argv = copy_argv(&argc, argv); +#elif defined(_WIN32) + /* + * Replace argv[] with UTF-8 encoded strings. + */ + win32_utf8argv(&argc, &argv); +#endif + + p = getenv("OPENSSL_DEBUG_MEMORY"); + if (p != NULL && strcmp(p, "on") == 0) + CRYPTO_set_mem_debug(1); + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); + + if (getenv("OPENSSL_FIPS")) { + BIO_printf(bio_err, "FIPS mode not supported.\n"); + return 1; + } + + if (!apps_startup()) { + BIO_printf(bio_err, + "FATAL: Startup failure (dev note: apps_startup() failed)\n"); + ERR_print_errors(bio_err); + ret = 1; + goto end; + } + + prog = prog_init(); + pname = opt_progname(argv[0]); + + /* first check the program name */ + f.name = pname; + fp = lh_FUNCTION_retrieve(prog, &f); + if (fp != NULL) { + argv[0] = pname; + ret = fp->func(argc, argv); + goto end; + } + + /* If there is stuff on the command line, run with that. */ + if (argc != 1) { + argc--; + argv++; + ret = do_cmd(prog, argc, argv); + if (ret < 0) + ret = 0; + goto end; + } + + /* ok, lets enter interactive mode */ + for (;;) { + ret = 0; + /* Read a line, continue reading if line ends with \ */ + for (p = buf, n = sizeof(buf), i = 0, first = 1; n > 0; first = 0) { + prompt = first ? "OpenSSL> " : "> "; + p[0] = '\0'; +#ifndef READLINE + fputs(prompt, stdout); + fflush(stdout); + if (!fgets(p, n, stdin)) + goto end; + if (p[0] == '\0') + goto end; + i = strlen(p); + if (i <= 1) + break; + if (p[i - 2] != '\\') + break; + i -= 2; + p += i; + n -= i; +#else + { + extern char *readline(const char *); + extern void add_history(const char *cp); + char *text; + + text = readline(prompt); + if (text == NULL) + goto end; + i = strlen(text); + if (i == 0 || i > n) + break; + if (text[i - 1] != '\\') { + p += strlen(strcpy(p, text)); + free(text); + add_history(buf); + break; + } + + text[i - 1] = '\0'; + p += strlen(strcpy(p, text)); + free(text); + n -= i; + } +#endif + } + + if (!chopup_args(&arg, buf)) { + BIO_printf(bio_err, "Can't parse (no memory?)\n"); + break; + } + + ret = do_cmd(prog, arg.argc, arg.argv); + if (ret == EXIT_THE_PROGRAM) { + ret = 0; + goto end; + } + if (ret != 0) + BIO_printf(bio_err, "error in %s\n", arg.argv[0]); + (void)BIO_flush(bio_out); + (void)BIO_flush(bio_err); + } + ret = 1; + end: + OPENSSL_free(copied_argv); + OPENSSL_free(default_config_file); + lh_FUNCTION_free(prog); + OPENSSL_free(arg.argv); + app_RAND_write(); + + BIO_free(bio_in); + BIO_free_all(bio_out); + apps_shutdown(); +#ifndef OPENSSL_NO_CRYPTO_MDEBUG + if (CRYPTO_mem_leaks(bio_err) <= 0) + ret = 1; +#endif + BIO_free(bio_err); + EXIT(ret); +} + +static void list_cipher_fn(const EVP_CIPHER *c, + const char *from, const char *to, void *arg) +{ + if (c != NULL) { + BIO_printf(arg, "%s\n", EVP_CIPHER_name(c)); + } else { + if (from == NULL) + from = ""; + if (to == NULL) + to = ""; + BIO_printf(arg, "%s => %s\n", from, to); + } +} + +static void list_md_fn(const EVP_MD *m, + const char *from, const char *to, void *arg) +{ + if (m != NULL) { + BIO_printf(arg, "%s\n", EVP_MD_name(m)); + } else { + if (from == NULL) + from = ""; + if (to == NULL) + to = ""; + BIO_printf((BIO *)arg, "%s => %s\n", from, to); + } +} + +static void list_missing_help(void) +{ + const FUNCTION *fp; + const OPTIONS *o; + + for (fp = functions; fp->name != NULL; fp++) { + if ((o = fp->help) != NULL) { + /* If there is help, list what flags are not documented. */ + for ( ; o->name != NULL; o++) { + if (o->helpstr == NULL) + BIO_printf(bio_out, "%s %s\n", fp->name, o->name); + } + } else if (fp->func != dgst_main) { + /* If not aliased to the dgst command, */ + BIO_printf(bio_out, "%s *\n", fp->name); + } + } +} + +static void list_options_for_command(const char *command) +{ + const FUNCTION *fp; + const OPTIONS *o; + + for (fp = functions; fp->name != NULL; fp++) + if (strcmp(fp->name, command) == 0) + break; + if (fp->name == NULL) { + BIO_printf(bio_err, "Invalid command '%s'; type \"help\" for a list.\n", + command); + return; + } + + if ((o = fp->help) == NULL) + return; + + for ( ; o->name != NULL; o++) { + if (o->name == OPT_HELP_STR + || o->name == OPT_MORE_STR + || o->name[0] == '\0') + continue; + BIO_printf(bio_out, "%s %c\n", o->name, o->valtype); + } +} + + +/* Unified enum for help and list commands. */ +typedef enum HELPLIST_CHOICE { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ONE, + OPT_COMMANDS, OPT_DIGEST_COMMANDS, OPT_OPTIONS, + OPT_DIGEST_ALGORITHMS, OPT_CIPHER_COMMANDS, OPT_CIPHER_ALGORITHMS, + OPT_PK_ALGORITHMS, OPT_PK_METHOD, OPT_DISABLED, OPT_MISSING_HELP +} HELPLIST_CHOICE; + +const OPTIONS list_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"1", OPT_ONE, '-', "List in one column"}, + {"commands", OPT_COMMANDS, '-', "List of standard commands"}, + {"digest-commands", OPT_DIGEST_COMMANDS, '-', + "List of message digest commands"}, + {"digest-algorithms", OPT_DIGEST_ALGORITHMS, '-', + "List of message digest algorithms"}, + {"cipher-commands", OPT_CIPHER_COMMANDS, '-', "List of cipher commands"}, + {"cipher-algorithms", OPT_CIPHER_ALGORITHMS, '-', + "List of cipher algorithms"}, + {"public-key-algorithms", OPT_PK_ALGORITHMS, '-', + "List of public key algorithms"}, + {"public-key-methods", OPT_PK_METHOD, '-', + "List of public key methods"}, + {"disabled", OPT_DISABLED, '-', + "List of disabled features"}, + {"missing-help", OPT_MISSING_HELP, '-', + "List missing detailed help strings"}, + {"options", OPT_OPTIONS, 's', + "List options for specified command"}, + {NULL} +}; + +int list_main(int argc, char **argv) +{ + char *prog; + HELPLIST_CHOICE o; + int one = 0, done = 0; + + prog = opt_init(argc, argv, list_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: /* Never hit, but suppresses warning */ + case OPT_ERR: +opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + return 1; + case OPT_HELP: + opt_help(list_options); + break; + case OPT_ONE: + one = 1; + break; + case OPT_COMMANDS: + list_type(FT_general, one); + break; + case OPT_DIGEST_COMMANDS: + list_type(FT_md, one); + break; + case OPT_DIGEST_ALGORITHMS: + EVP_MD_do_all_sorted(list_md_fn, bio_out); + break; + case OPT_CIPHER_COMMANDS: + list_type(FT_cipher, one); + break; + case OPT_CIPHER_ALGORITHMS: + EVP_CIPHER_do_all_sorted(list_cipher_fn, bio_out); + break; + case OPT_PK_ALGORITHMS: + list_pkey(); + break; + case OPT_PK_METHOD: + list_pkey_meth(); + break; + case OPT_DISABLED: + list_disabled(); + break; + case OPT_MISSING_HELP: + list_missing_help(); + break; + case OPT_OPTIONS: + list_options_for_command(opt_arg()); + break; + } + done = 1; + } + if (opt_num_rest() != 0) { + BIO_printf(bio_err, "Extra arguments given.\n"); + goto opthelp; + } + + if (!done) + goto opthelp; + + return 0; +} + +typedef enum HELP_CHOICE { + OPT_hERR = -1, OPT_hEOF = 0, OPT_hHELP +} HELP_CHOICE; + +const OPTIONS help_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: help [options]\n"}, + {OPT_HELP_STR, 1, '-', " help [command]\n"}, + {"help", OPT_hHELP, '-', "Display this summary"}, + {NULL} +}; + + +int help_main(int argc, char **argv) +{ + FUNCTION *fp; + int i, nl; + FUNC_TYPE tp; + char *prog; + HELP_CHOICE o; + DISPLAY_COLUMNS dc; + + prog = opt_init(argc, argv, help_options); + while ((o = opt_next()) != OPT_hEOF) { + switch (o) { + case OPT_hERR: + case OPT_hEOF: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + return 1; + case OPT_hHELP: + opt_help(help_options); + return 0; + } + } + + if (opt_num_rest() == 1) { + char *new_argv[3]; + + new_argv[0] = opt_rest()[0]; + new_argv[1] = "--help"; + new_argv[2] = NULL; + return do_cmd(prog_init(), 2, new_argv); + } + if (opt_num_rest() != 0) { + BIO_printf(bio_err, "Usage: %s\n", prog); + return 1; + } + + calculate_columns(&dc); + BIO_printf(bio_err, "Standard commands"); + i = 0; + tp = FT_none; + for (fp = functions; fp->name != NULL; fp++) { + nl = 0; + if (i++ % dc.columns == 0) { + BIO_printf(bio_err, "\n"); + nl = 1; + } + if (fp->type != tp) { + tp = fp->type; + if (!nl) + BIO_printf(bio_err, "\n"); + if (tp == FT_md) { + i = 1; + BIO_printf(bio_err, + "\nMessage Digest commands (see the `dgst' command for more details)\n"); + } else if (tp == FT_cipher) { + i = 1; + BIO_printf(bio_err, + "\nCipher commands (see the `enc' command for more details)\n"); + } + } + BIO_printf(bio_err, "%-*s", dc.width, fp->name); + } + BIO_printf(bio_err, "\n\n"); + return 0; +} + +static void list_type(FUNC_TYPE ft, int one) +{ + FUNCTION *fp; + int i = 0; + DISPLAY_COLUMNS dc = {0}; + + if (!one) + calculate_columns(&dc); + + for (fp = functions; fp->name != NULL; fp++) { + if (fp->type != ft) + continue; + if (one) { + BIO_printf(bio_out, "%s\n", fp->name); + } else { + if (i % dc.columns == 0 && i > 0) + BIO_printf(bio_out, "\n"); + BIO_printf(bio_out, "%-*s", dc.width, fp->name); + i++; + } + } + if (!one) + BIO_printf(bio_out, "\n\n"); +} + +static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[]) +{ + FUNCTION f, *fp; + + if (argc <= 0 || argv[0] == NULL) + return 0; + f.name = argv[0]; + fp = lh_FUNCTION_retrieve(prog, &f); + if (fp == NULL) { + if (EVP_get_digestbyname(argv[0])) { + f.type = FT_md; + f.func = dgst_main; + fp = &f; + } else if (EVP_get_cipherbyname(argv[0])) { + f.type = FT_cipher; + f.func = enc_main; + fp = &f; + } + } + if (fp != NULL) { + return fp->func(argc, argv); + } + if ((strncmp(argv[0], "no-", 3)) == 0) { + /* + * User is asking if foo is unsupported, by trying to "run" the + * no-foo command. Strange. + */ + f.name = argv[0] + 3; + if (lh_FUNCTION_retrieve(prog, &f) == NULL) { + BIO_printf(bio_out, "%s\n", argv[0]); + return 0; + } + BIO_printf(bio_out, "%s\n", argv[0] + 3); + return 1; + } + if (strcmp(argv[0], "quit") == 0 || strcmp(argv[0], "q") == 0 || + strcmp(argv[0], "exit") == 0 || strcmp(argv[0], "bye") == 0) + /* Special value to mean "exit the program. */ + return EXIT_THE_PROGRAM; + + BIO_printf(bio_err, "Invalid command '%s'; type \"help\" for a list.\n", + argv[0]); + return 1; +} + +static void list_pkey(void) +{ + int i; + + for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) { + const EVP_PKEY_ASN1_METHOD *ameth; + int pkey_id, pkey_base_id, pkey_flags; + const char *pinfo, *pem_str; + ameth = EVP_PKEY_asn1_get0(i); + EVP_PKEY_asn1_get0_info(&pkey_id, &pkey_base_id, &pkey_flags, + &pinfo, &pem_str, ameth); + if (pkey_flags & ASN1_PKEY_ALIAS) { + BIO_printf(bio_out, "Name: %s\n", OBJ_nid2ln(pkey_id)); + BIO_printf(bio_out, "\tAlias for: %s\n", + OBJ_nid2ln(pkey_base_id)); + } else { + BIO_printf(bio_out, "Name: %s\n", pinfo); + BIO_printf(bio_out, "\tType: %s Algorithm\n", + pkey_flags & ASN1_PKEY_DYNAMIC ? + "External" : "Builtin"); + BIO_printf(bio_out, "\tOID: %s\n", OBJ_nid2ln(pkey_id)); + if (pem_str == NULL) + pem_str = "(none)"; + BIO_printf(bio_out, "\tPEM string: %s\n", pem_str); + } + + } +} + +static void list_pkey_meth(void) +{ + size_t i; + size_t meth_count = EVP_PKEY_meth_get_count(); + + for (i = 0; i < meth_count; i++) { + const EVP_PKEY_METHOD *pmeth = EVP_PKEY_meth_get0(i); + int pkey_id, pkey_flags; + + EVP_PKEY_meth_get0_info(&pkey_id, &pkey_flags, pmeth); + BIO_printf(bio_out, "%s\n", OBJ_nid2ln(pkey_id)); + BIO_printf(bio_out, "\tType: %s Algorithm\n", + pkey_flags & ASN1_PKEY_DYNAMIC ? "External" : "Builtin"); + } +} + +static int function_cmp(const FUNCTION * a, const FUNCTION * b) +{ + return strncmp(a->name, b->name, 8); +} + +static unsigned long function_hash(const FUNCTION * a) +{ + return OPENSSL_LH_strhash(a->name); +} + +static int SortFnByName(const void *_f1, const void *_f2) +{ + const FUNCTION *f1 = _f1; + const FUNCTION *f2 = _f2; + + if (f1->type != f2->type) + return f1->type - f2->type; + return strcmp(f1->name, f2->name); +} + +static void list_disabled(void) +{ + BIO_puts(bio_out, "Disabled algorithms:\n"); +#ifdef OPENSSL_NO_ARIA + BIO_puts(bio_out, "ARIA\n"); +#endif +#ifdef OPENSSL_NO_BF + BIO_puts(bio_out, "BF\n"); +#endif +#ifdef OPENSSL_NO_BLAKE2 + BIO_puts(bio_out, "BLAKE2\n"); +#endif +#ifdef OPENSSL_NO_CAMELLIA + BIO_puts(bio_out, "CAMELLIA\n"); +#endif +#ifdef OPENSSL_NO_CAST + BIO_puts(bio_out, "CAST\n"); +#endif +#ifdef OPENSSL_NO_CMAC + BIO_puts(bio_out, "CMAC\n"); +#endif +#ifdef OPENSSL_NO_CMS + BIO_puts(bio_out, "CMS\n"); +#endif +#ifdef OPENSSL_NO_COMP + BIO_puts(bio_out, "COMP\n"); +#endif +#ifdef OPENSSL_NO_DES + BIO_puts(bio_out, "DES\n"); +#endif +#ifdef OPENSSL_NO_DGRAM + BIO_puts(bio_out, "DGRAM\n"); +#endif +#ifdef OPENSSL_NO_DH + BIO_puts(bio_out, "DH\n"); +#endif +#ifdef OPENSSL_NO_DSA + BIO_puts(bio_out, "DSA\n"); +#endif +#if defined(OPENSSL_NO_DTLS) + BIO_puts(bio_out, "DTLS\n"); +#endif +#if defined(OPENSSL_NO_DTLS1) + BIO_puts(bio_out, "DTLS1\n"); +#endif +#if defined(OPENSSL_NO_DTLS1_2) + BIO_puts(bio_out, "DTLS1_2\n"); +#endif +#ifdef OPENSSL_NO_EC + BIO_puts(bio_out, "EC\n"); +#endif +#ifdef OPENSSL_NO_EC2M + BIO_puts(bio_out, "EC2M\n"); +#endif +#ifdef OPENSSL_NO_ENGINE + BIO_puts(bio_out, "ENGINE\n"); +#endif +#ifdef OPENSSL_NO_GOST + BIO_puts(bio_out, "GOST\n"); +#endif +#ifdef OPENSSL_NO_HEARTBEATS + BIO_puts(bio_out, "HEARTBEATS\n"); +#endif +#ifdef OPENSSL_NO_IDEA + BIO_puts(bio_out, "IDEA\n"); +#endif +#ifdef OPENSSL_NO_MD2 + BIO_puts(bio_out, "MD2\n"); +#endif +#ifdef OPENSSL_NO_MD4 + BIO_puts(bio_out, "MD4\n"); +#endif +#ifdef OPENSSL_NO_MD5 + BIO_puts(bio_out, "MD5\n"); +#endif +#ifdef OPENSSL_NO_MDC2 + BIO_puts(bio_out, "MDC2\n"); +#endif +#ifdef OPENSSL_NO_OCB + BIO_puts(bio_out, "OCB\n"); +#endif +#ifdef OPENSSL_NO_OCSP + BIO_puts(bio_out, "OCSP\n"); +#endif +#ifdef OPENSSL_NO_PSK + BIO_puts(bio_out, "PSK\n"); +#endif +#ifdef OPENSSL_NO_RC2 + BIO_puts(bio_out, "RC2\n"); +#endif +#ifdef OPENSSL_NO_RC4 + BIO_puts(bio_out, "RC4\n"); +#endif +#ifdef OPENSSL_NO_RC5 + BIO_puts(bio_out, "RC5\n"); +#endif +#ifdef OPENSSL_NO_RMD160 + BIO_puts(bio_out, "RMD160\n"); +#endif +#ifdef OPENSSL_NO_RSA + BIO_puts(bio_out, "RSA\n"); +#endif +#ifdef OPENSSL_NO_SCRYPT + BIO_puts(bio_out, "SCRYPT\n"); +#endif +#ifdef OPENSSL_NO_SCTP + BIO_puts(bio_out, "SCTP\n"); +#endif +#ifdef OPENSSL_NO_SEED + BIO_puts(bio_out, "SEED\n"); +#endif +#ifdef OPENSSL_NO_SM2 + BIO_puts(bio_out, "SM2\n"); +#endif +#ifdef OPENSSL_NO_SM3 + BIO_puts(bio_out, "SM3\n"); +#endif +#ifdef OPENSSL_NO_SM4 + BIO_puts(bio_out, "SM4\n"); +#endif +#ifdef OPENSSL_NO_SOCK + BIO_puts(bio_out, "SOCK\n"); +#endif +#ifdef OPENSSL_NO_SRP + BIO_puts(bio_out, "SRP\n"); +#endif +#ifdef OPENSSL_NO_SRTP + BIO_puts(bio_out, "SRTP\n"); +#endif +#ifdef OPENSSL_NO_SSL3 + BIO_puts(bio_out, "SSL3\n"); +#endif +#ifdef OPENSSL_NO_TLS1 + BIO_puts(bio_out, "TLS1\n"); +#endif +#ifdef OPENSSL_NO_TLS1_1 + BIO_puts(bio_out, "TLS1_1\n"); +#endif +#ifdef OPENSSL_NO_TLS1_2 + BIO_puts(bio_out, "TLS1_2\n"); +#endif +#ifdef OPENSSL_NO_WHIRLPOOL + BIO_puts(bio_out, "WHIRLPOOL\n"); +#endif +#ifndef ZLIB + BIO_puts(bio_out, "ZLIB\n"); +#endif +} + +static LHASH_OF(FUNCTION) *prog_init(void) +{ + static LHASH_OF(FUNCTION) *ret = NULL; + static int prog_inited = 0; + FUNCTION *f; + size_t i; + + if (prog_inited) + return ret; + + prog_inited = 1; + + /* Sort alphabetically within category. For nicer help displays. */ + for (i = 0, f = functions; f->name != NULL; ++f, ++i) + ; + qsort(functions, i, sizeof(*functions), SortFnByName); + + if ((ret = lh_FUNCTION_new(function_hash, function_cmp)) == NULL) + return NULL; + + for (f = functions; f->name != NULL; f++) + (void)lh_FUNCTION_insert(ret, f); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/openssl.cnf b/trunk/3rdparty/openssl-1.1-fit/apps/openssl.cnf new file mode 100644 index 000000000..4acca4b04 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/openssl.cnf @@ -0,0 +1,350 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# Note that you can include other files from the main configuration +# file using the .include directive. +#.include filename + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca', 'req' and 'ts'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +# Policies used by the TSA examples. +tsa_policy1 = 1.2.3.4.1 +tsa_policy2 = 1.2.3.4.5.6 +tsa_policy3 = 1.2.3.4.5.7 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certs with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem# The private key + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = default # use public key default MD +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 2048 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString (PKIX recommendation before 2004) +# utf8only: only UTF8Strings (PKIX recommendation after 2004). +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings. +string_mask = utf8only + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = AU +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Some-State + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = Internet Widgits Pty Ltd + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +#organizationalUnitName_default = + +commonName = Common Name (e.g. server FQDN or YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This is required for TSA certificates. +# extendedKeyUsage = critical,timeStamping + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer + +basicConstraints = critical,CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as an test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo + +#################################################################### +[ tsa ] + +default_tsa = tsa_config1 # the default TSA section + +[ tsa_config1 ] + +# These are used by the TSA reply generation only. +dir = ./demoCA # TSA root directory +serial = $dir/tsaserial # The current serial number (mandatory) +crypto_device = builtin # OpenSSL engine to use for signing +signer_cert = $dir/tsacert.pem # The TSA signing certificate + # (optional) +certs = $dir/cacert.pem # Certificate chain to include in reply + # (optional) +signer_key = $dir/private/tsakey.pem # The TSA private key (optional) +signer_digest = sha256 # Signing digest to use. (Optional) +default_policy = tsa_policy1 # Policy if request did not specify it + # (optional) +other_policies = tsa_policy2, tsa_policy3 # acceptable policies (optional) +digests = sha1, sha256, sha384, sha512 # Acceptable message digests (mandatory) +accuracy = secs:1, millisecs:500, microsecs:100 # (optional) +clock_precision_digits = 0 # number of digits after dot. (optional) +ordering = yes # Is ordering defined for timestamps? + # (optional, default: no) +tsa_name = yes # Must the TSA name be included in the reply? + # (optional, default: no) +ess_cert_id_chain = no # Must the ESS cert id chain be included? + # (optional, default: no) +ess_cert_id_alg = sha1 # algorithm to compute certificate + # identifier (optional, default: sha1) diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/opt.c b/trunk/3rdparty/openssl-1.1-fit/apps/opt.c new file mode 100644 index 000000000..666856535 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/opt.c @@ -0,0 +1,898 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ +#include "apps.h" +#include +#if !defined(OPENSSL_SYS_MSDOS) +# include OPENSSL_UNISTD +#endif + +#include +#include +#include +#include +#include +#include + +#define MAX_OPT_HELP_WIDTH 30 +const char OPT_HELP_STR[] = "--"; +const char OPT_MORE_STR[] = "---"; + +/* Our state */ +static char **argv; +static int argc; +static int opt_index; +static char *arg; +static char *flag; +static char *dunno; +static const OPTIONS *unknown; +static const OPTIONS *opts; +static char prog[40]; + +/* + * Return the simple name of the program; removing various platform gunk. + */ +#if defined(OPENSSL_SYS_WIN32) +char *opt_progname(const char *argv0) +{ + size_t i, n; + const char *p; + char *q; + + /* find the last '/', '\' or ':' */ + for (p = argv0 + strlen(argv0); --p > argv0;) + if (*p == '/' || *p == '\\' || *p == ':') { + p++; + break; + } + + /* Strip off trailing nonsense. */ + n = strlen(p); + if (n > 4 && + (strcmp(&p[n - 4], ".exe") == 0 || strcmp(&p[n - 4], ".EXE") == 0)) + n -= 4; + + /* Copy over the name, in lowercase. */ + if (n > sizeof(prog) - 1) + n = sizeof(prog) - 1; + for (q = prog, i = 0; i < n; i++, p++) + *q++ = tolower((unsigned char)*p); + *q = '\0'; + return prog; +} + +#elif defined(OPENSSL_SYS_VMS) + +char *opt_progname(const char *argv0) +{ + const char *p, *q; + + /* Find last special character sys:[foo.bar]openssl */ + for (p = argv0 + strlen(argv0); --p > argv0;) + if (*p == ':' || *p == ']' || *p == '>') { + p++; + break; + } + + q = strrchr(p, '.'); + strncpy(prog, p, sizeof(prog) - 1); + prog[sizeof(prog) - 1] = '\0'; + if (q != NULL && q - p < sizeof(prog)) + prog[q - p] = '\0'; + return prog; +} + +#else + +char *opt_progname(const char *argv0) +{ + const char *p; + + /* Could use strchr, but this is like the ones above. */ + for (p = argv0 + strlen(argv0); --p > argv0;) + if (*p == '/') { + p++; + break; + } + strncpy(prog, p, sizeof(prog) - 1); + prog[sizeof(prog) - 1] = '\0'; + return prog; +} +#endif + +char *opt_getprog(void) +{ + return prog; +} + +/* Set up the arg parsing. */ +char *opt_init(int ac, char **av, const OPTIONS *o) +{ + /* Store state. */ + argc = ac; + argv = av; + opt_index = 1; + opts = o; + opt_progname(av[0]); + unknown = NULL; + + for (; o->name; ++o) { +#ifndef NDEBUG + const OPTIONS *next; + int duplicated, i; +#endif + + if (o->name == OPT_HELP_STR || o->name == OPT_MORE_STR) + continue; +#ifndef NDEBUG + i = o->valtype; + + /* Make sure options are legit. */ + assert(o->name[0] != '-'); + assert(o->retval > 0); + switch (i) { + case 0: case '-': case '/': case '<': case '>': case 'E': case 'F': + case 'M': case 'U': case 'f': case 'l': case 'n': case 'p': case 's': + case 'u': case 'c': + break; + default: + assert(0); + } + + /* Make sure there are no duplicates. */ + for (next = o + 1; next->name; ++next) { + /* + * Some compilers inline strcmp and the assert string is too long. + */ + duplicated = strcmp(o->name, next->name) == 0; + assert(!duplicated); + } +#endif + if (o->name[0] == '\0') { + assert(unknown == NULL); + unknown = o; + assert(unknown->valtype == 0 || unknown->valtype == '-'); + } + } + return prog; +} + +static OPT_PAIR formats[] = { + {"PEM/DER", OPT_FMT_PEMDER}, + {"pkcs12", OPT_FMT_PKCS12}, + {"smime", OPT_FMT_SMIME}, + {"engine", OPT_FMT_ENGINE}, + {"msblob", OPT_FMT_MSBLOB}, + {"nss", OPT_FMT_NSS}, + {"text", OPT_FMT_TEXT}, + {"http", OPT_FMT_HTTP}, + {"pvk", OPT_FMT_PVK}, + {NULL} +}; + +/* Print an error message about a failed format parse. */ +int opt_format_error(const char *s, unsigned long flags) +{ + OPT_PAIR *ap; + + if (flags == OPT_FMT_PEMDER) { + BIO_printf(bio_err, "%s: Bad format \"%s\"; must be pem or der\n", + prog, s); + } else { + BIO_printf(bio_err, "%s: Bad format \"%s\"; must be one of:\n", + prog, s); + for (ap = formats; ap->name; ap++) + if (flags & ap->retval) + BIO_printf(bio_err, " %s\n", ap->name); + } + return 0; +} + +/* Parse a format string, put it into *result; return 0 on failure, else 1. */ +int opt_format(const char *s, unsigned long flags, int *result) +{ + switch (*s) { + default: + return 0; + case 'D': + case 'd': + if ((flags & OPT_FMT_PEMDER) == 0) + return opt_format_error(s, flags); + *result = FORMAT_ASN1; + break; + case 'T': + case 't': + if ((flags & OPT_FMT_TEXT) == 0) + return opt_format_error(s, flags); + *result = FORMAT_TEXT; + break; + case 'N': + case 'n': + if ((flags & OPT_FMT_NSS) == 0) + return opt_format_error(s, flags); + if (strcmp(s, "NSS") != 0 && strcmp(s, "nss") != 0) + return opt_format_error(s, flags); + *result = FORMAT_NSS; + break; + case 'S': + case 's': + if ((flags & OPT_FMT_SMIME) == 0) + return opt_format_error(s, flags); + *result = FORMAT_SMIME; + break; + case 'M': + case 'm': + if ((flags & OPT_FMT_MSBLOB) == 0) + return opt_format_error(s, flags); + *result = FORMAT_MSBLOB; + break; + case 'E': + case 'e': + if ((flags & OPT_FMT_ENGINE) == 0) + return opt_format_error(s, flags); + *result = FORMAT_ENGINE; + break; + case 'H': + case 'h': + if ((flags & OPT_FMT_HTTP) == 0) + return opt_format_error(s, flags); + *result = FORMAT_HTTP; + break; + case '1': + if ((flags & OPT_FMT_PKCS12) == 0) + return opt_format_error(s, flags); + *result = FORMAT_PKCS12; + break; + case 'P': + case 'p': + if (s[1] == '\0' || strcmp(s, "PEM") == 0 || strcmp(s, "pem") == 0) { + if ((flags & OPT_FMT_PEMDER) == 0) + return opt_format_error(s, flags); + *result = FORMAT_PEM; + } else if (strcmp(s, "PVK") == 0 || strcmp(s, "pvk") == 0) { + if ((flags & OPT_FMT_PVK) == 0) + return opt_format_error(s, flags); + *result = FORMAT_PVK; + } else if (strcmp(s, "P12") == 0 || strcmp(s, "p12") == 0 + || strcmp(s, "PKCS12") == 0 || strcmp(s, "pkcs12") == 0) { + if ((flags & OPT_FMT_PKCS12) == 0) + return opt_format_error(s, flags); + *result = FORMAT_PKCS12; + } else { + return 0; + } + break; + } + return 1; +} + +/* Parse a cipher name, put it in *EVP_CIPHER; return 0 on failure, else 1. */ +int opt_cipher(const char *name, const EVP_CIPHER **cipherp) +{ + *cipherp = EVP_get_cipherbyname(name); + if (*cipherp != NULL) + return 1; + BIO_printf(bio_err, "%s: Unrecognized flag %s\n", prog, name); + return 0; +} + +/* + * Parse message digest name, put it in *EVP_MD; return 0 on failure, else 1. + */ +int opt_md(const char *name, const EVP_MD **mdp) +{ + *mdp = EVP_get_digestbyname(name); + if (*mdp != NULL) + return 1; + BIO_printf(bio_err, "%s: Unrecognized flag %s\n", prog, name); + return 0; +} + +/* Look through a list of name/value pairs. */ +int opt_pair(const char *name, const OPT_PAIR* pairs, int *result) +{ + const OPT_PAIR *pp; + + for (pp = pairs; pp->name; pp++) + if (strcmp(pp->name, name) == 0) { + *result = pp->retval; + return 1; + } + BIO_printf(bio_err, "%s: Value must be one of:\n", prog); + for (pp = pairs; pp->name; pp++) + BIO_printf(bio_err, "\t%s\n", pp->name); + return 0; +} + +/* Parse an int, put it into *result; return 0 on failure, else 1. */ +int opt_int(const char *value, int *result) +{ + long l; + + if (!opt_long(value, &l)) + return 0; + *result = (int)l; + if (*result != l) { + BIO_printf(bio_err, "%s: Value \"%s\" outside integer range\n", + prog, value); + return 0; + } + return 1; +} + +static void opt_number_error(const char *v) +{ + size_t i = 0; + struct strstr_pair_st { + char *prefix; + char *name; + } b[] = { + {"0x", "a hexadecimal"}, + {"0X", "a hexadecimal"}, + {"0", "an octal"} + }; + + for (i = 0; i < OSSL_NELEM(b); i++) { + if (strncmp(v, b[i].prefix, strlen(b[i].prefix)) == 0) { + BIO_printf(bio_err, + "%s: Can't parse \"%s\" as %s number\n", + prog, v, b[i].name); + return; + } + } + BIO_printf(bio_err, "%s: Can't parse \"%s\" as a number\n", prog, v); + return; +} + +/* Parse a long, put it into *result; return 0 on failure, else 1. */ +int opt_long(const char *value, long *result) +{ + int oerrno = errno; + long l; + char *endp; + + errno = 0; + l = strtol(value, &endp, 0); + if (*endp + || endp == value + || ((l == LONG_MAX || l == LONG_MIN) && errno == ERANGE) + || (l == 0 && errno != 0)) { + opt_number_error(value); + errno = oerrno; + return 0; + } + *result = l; + errno = oerrno; + return 1; +} + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \ + defined(INTMAX_MAX) && defined(UINTMAX_MAX) + +/* Parse an intmax_t, put it into *result; return 0 on failure, else 1. */ +int opt_imax(const char *value, intmax_t *result) +{ + int oerrno = errno; + intmax_t m; + char *endp; + + errno = 0; + m = strtoimax(value, &endp, 0); + if (*endp + || endp == value + || ((m == INTMAX_MAX || m == INTMAX_MIN) && errno == ERANGE) + || (m == 0 && errno != 0)) { + opt_number_error(value); + errno = oerrno; + return 0; + } + *result = m; + errno = oerrno; + return 1; +} + +/* Parse a uintmax_t, put it into *result; return 0 on failure, else 1. */ +int opt_umax(const char *value, uintmax_t *result) +{ + int oerrno = errno; + uintmax_t m; + char *endp; + + errno = 0; + m = strtoumax(value, &endp, 0); + if (*endp + || endp == value + || (m == UINTMAX_MAX && errno == ERANGE) + || (m == 0 && errno != 0)) { + opt_number_error(value); + errno = oerrno; + return 0; + } + *result = m; + errno = oerrno; + return 1; +} +#endif + +/* + * Parse an unsigned long, put it into *result; return 0 on failure, else 1. + */ +int opt_ulong(const char *value, unsigned long *result) +{ + int oerrno = errno; + char *endptr; + unsigned long l; + + errno = 0; + l = strtoul(value, &endptr, 0); + if (*endptr + || endptr == value + || ((l == ULONG_MAX) && errno == ERANGE) + || (l == 0 && errno != 0)) { + opt_number_error(value); + errno = oerrno; + return 0; + } + *result = l; + errno = oerrno; + return 1; +} + +/* + * We pass opt as an int but cast it to "enum range" so that all the + * items in the OPT_V_ENUM enumeration are caught; this makes -Wswitch + * in gcc do the right thing. + */ +enum range { OPT_V_ENUM }; + +int opt_verify(int opt, X509_VERIFY_PARAM *vpm) +{ + int i; + ossl_intmax_t t = 0; + ASN1_OBJECT *otmp; + X509_PURPOSE *xptmp; + const X509_VERIFY_PARAM *vtmp; + + assert(vpm != NULL); + assert(opt > OPT_V__FIRST); + assert(opt < OPT_V__LAST); + + switch ((enum range)opt) { + case OPT_V__FIRST: + case OPT_V__LAST: + return 0; + case OPT_V_POLICY: + otmp = OBJ_txt2obj(opt_arg(), 0); + if (otmp == NULL) { + BIO_printf(bio_err, "%s: Invalid Policy %s\n", prog, opt_arg()); + return 0; + } + X509_VERIFY_PARAM_add0_policy(vpm, otmp); + break; + case OPT_V_PURPOSE: + /* purpose name -> purpose index */ + i = X509_PURPOSE_get_by_sname(opt_arg()); + if (i < 0) { + BIO_printf(bio_err, "%s: Invalid purpose %s\n", prog, opt_arg()); + return 0; + } + + /* purpose index -> purpose object */ + xptmp = X509_PURPOSE_get0(i); + + /* purpose object -> purpose value */ + i = X509_PURPOSE_get_id(xptmp); + + if (!X509_VERIFY_PARAM_set_purpose(vpm, i)) { + BIO_printf(bio_err, + "%s: Internal error setting purpose %s\n", + prog, opt_arg()); + return 0; + } + break; + case OPT_V_VERIFY_NAME: + vtmp = X509_VERIFY_PARAM_lookup(opt_arg()); + if (vtmp == NULL) { + BIO_printf(bio_err, "%s: Invalid verify name %s\n", + prog, opt_arg()); + return 0; + } + X509_VERIFY_PARAM_set1(vpm, vtmp); + break; + case OPT_V_VERIFY_DEPTH: + i = atoi(opt_arg()); + if (i >= 0) + X509_VERIFY_PARAM_set_depth(vpm, i); + break; + case OPT_V_VERIFY_AUTH_LEVEL: + i = atoi(opt_arg()); + if (i >= 0) + X509_VERIFY_PARAM_set_auth_level(vpm, i); + break; + case OPT_V_ATTIME: + if (!opt_imax(opt_arg(), &t)) + return 0; + if (t != (time_t)t) { + BIO_printf(bio_err, "%s: epoch time out of range %s\n", + prog, opt_arg()); + return 0; + } + X509_VERIFY_PARAM_set_time(vpm, (time_t)t); + break; + case OPT_V_VERIFY_HOSTNAME: + if (!X509_VERIFY_PARAM_set1_host(vpm, opt_arg(), 0)) + return 0; + break; + case OPT_V_VERIFY_EMAIL: + if (!X509_VERIFY_PARAM_set1_email(vpm, opt_arg(), 0)) + return 0; + break; + case OPT_V_VERIFY_IP: + if (!X509_VERIFY_PARAM_set1_ip_asc(vpm, opt_arg())) + return 0; + break; + case OPT_V_IGNORE_CRITICAL: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_IGNORE_CRITICAL); + break; + case OPT_V_ISSUER_CHECKS: + /* NOP, deprecated */ + break; + case OPT_V_CRL_CHECK: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CRL_CHECK); + break; + case OPT_V_CRL_CHECK_ALL: + X509_VERIFY_PARAM_set_flags(vpm, + X509_V_FLAG_CRL_CHECK | + X509_V_FLAG_CRL_CHECK_ALL); + break; + case OPT_V_POLICY_CHECK: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_POLICY_CHECK); + break; + case OPT_V_EXPLICIT_POLICY: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXPLICIT_POLICY); + break; + case OPT_V_INHIBIT_ANY: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_ANY); + break; + case OPT_V_INHIBIT_MAP: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_MAP); + break; + case OPT_V_X509_STRICT: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_X509_STRICT); + break; + case OPT_V_EXTENDED_CRL: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXTENDED_CRL_SUPPORT); + break; + case OPT_V_USE_DELTAS: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_USE_DELTAS); + break; + case OPT_V_POLICY_PRINT: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NOTIFY_POLICY); + break; + case OPT_V_CHECK_SS_SIG: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CHECK_SS_SIGNATURE); + break; + case OPT_V_TRUSTED_FIRST: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_TRUSTED_FIRST); + break; + case OPT_V_SUITEB_128_ONLY: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS_ONLY); + break; + case OPT_V_SUITEB_128: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS); + break; + case OPT_V_SUITEB_192: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_192_LOS); + break; + case OPT_V_PARTIAL_CHAIN: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_PARTIAL_CHAIN); + break; + case OPT_V_NO_ALT_CHAINS: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_ALT_CHAINS); + break; + case OPT_V_NO_CHECK_TIME: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_CHECK_TIME); + break; + case OPT_V_ALLOW_PROXY_CERTS: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_ALLOW_PROXY_CERTS); + break; + } + return 1; + +} + +/* + * Parse the next flag (and value if specified), return 0 if done, -1 on + * error, otherwise the flag's retval. + */ +int opt_next(void) +{ + char *p; + const OPTIONS *o; + int ival; + long lval; + unsigned long ulval; + ossl_intmax_t imval; + ossl_uintmax_t umval; + + /* Look at current arg; at end of the list? */ + arg = NULL; + p = argv[opt_index]; + if (p == NULL) + return 0; + + /* If word doesn't start with a -, we're done. */ + if (*p != '-') + return 0; + + /* Hit "--" ? We're done. */ + opt_index++; + if (strcmp(p, "--") == 0) + return 0; + + /* Allow -nnn and --nnn */ + if (*++p == '-') + p++; + flag = p - 1; + + /* If we have --flag=foo, snip it off */ + if ((arg = strchr(p, '=')) != NULL) + *arg++ = '\0'; + for (o = opts; o->name; ++o) { + /* If not this option, move on to the next one. */ + if (strcmp(p, o->name) != 0) + continue; + + /* If it doesn't take a value, make sure none was given. */ + if (o->valtype == 0 || o->valtype == '-') { + if (arg) { + BIO_printf(bio_err, + "%s: Option -%s does not take a value\n", prog, p); + return -1; + } + return o->retval; + } + + /* Want a value; get the next param if =foo not used. */ + if (arg == NULL) { + if (argv[opt_index] == NULL) { + BIO_printf(bio_err, + "%s: Option -%s needs a value\n", prog, o->name); + return -1; + } + arg = argv[opt_index++]; + } + + /* Syntax-check value. */ + switch (o->valtype) { + default: + case 's': + /* Just a string. */ + break; + case '/': + if (app_isdir(arg) > 0) + break; + BIO_printf(bio_err, "%s: Not a directory: %s\n", prog, arg); + return -1; + case '<': + /* Input file. */ + break; + case '>': + /* Output file. */ + break; + case 'p': + case 'n': + if (!opt_int(arg, &ival) + || (o->valtype == 'p' && ival <= 0)) { + BIO_printf(bio_err, + "%s: Non-positive number \"%s\" for -%s\n", + prog, arg, o->name); + return -1; + } + break; + case 'M': + if (!opt_imax(arg, &imval)) { + BIO_printf(bio_err, + "%s: Invalid number \"%s\" for -%s\n", + prog, arg, o->name); + return -1; + } + break; + case 'U': + if (!opt_umax(arg, &umval)) { + BIO_printf(bio_err, + "%s: Invalid number \"%s\" for -%s\n", + prog, arg, o->name); + return -1; + } + break; + case 'l': + if (!opt_long(arg, &lval)) { + BIO_printf(bio_err, + "%s: Invalid number \"%s\" for -%s\n", + prog, arg, o->name); + return -1; + } + break; + case 'u': + if (!opt_ulong(arg, &ulval)) { + BIO_printf(bio_err, + "%s: Invalid number \"%s\" for -%s\n", + prog, arg, o->name); + return -1; + } + break; + case 'c': + case 'E': + case 'F': + case 'f': + if (opt_format(arg, + o->valtype == 'c' ? OPT_FMT_PDS : + o->valtype == 'E' ? OPT_FMT_PDE : + o->valtype == 'F' ? OPT_FMT_PEMDER + : OPT_FMT_ANY, &ival)) + break; + BIO_printf(bio_err, + "%s: Invalid format \"%s\" for -%s\n", + prog, arg, o->name); + return -1; + } + + /* Return the flag value. */ + return o->retval; + } + if (unknown != NULL) { + dunno = p; + return unknown->retval; + } + BIO_printf(bio_err, "%s: Option unknown option -%s\n", prog, p); + return -1; +} + +/* Return the most recent flag parameter. */ +char *opt_arg(void) +{ + return arg; +} + +/* Return the most recent flag. */ +char *opt_flag(void) +{ + return flag; +} + +/* Return the unknown option. */ +char *opt_unknown(void) +{ + return dunno; +} + +/* Return the rest of the arguments after parsing flags. */ +char **opt_rest(void) +{ + return &argv[opt_index]; +} + +/* How many items in remaining args? */ +int opt_num_rest(void) +{ + int i = 0; + char **pp; + + for (pp = opt_rest(); *pp; pp++, i++) + continue; + return i; +} + +/* Return a string describing the parameter type. */ +static const char *valtype2param(const OPTIONS *o) +{ + switch (o->valtype) { + case 0: + case '-': + return ""; + case 's': + return "val"; + case '/': + return "dir"; + case '<': + return "infile"; + case '>': + return "outfile"; + case 'p': + return "+int"; + case 'n': + return "int"; + case 'l': + return "long"; + case 'u': + return "ulong"; + case 'E': + return "PEM|DER|ENGINE"; + case 'F': + return "PEM|DER"; + case 'f': + return "format"; + case 'M': + return "intmax"; + case 'U': + return "uintmax"; + } + return "parm"; +} + +void opt_help(const OPTIONS *list) +{ + const OPTIONS *o; + int i; + int standard_prolog; + int width = 5; + char start[80 + 1]; + char *p; + const char *help; + + /* Starts with its own help message? */ + standard_prolog = list[0].name != OPT_HELP_STR; + + /* Find the widest help. */ + for (o = list; o->name; o++) { + if (o->name == OPT_MORE_STR) + continue; + i = 2 + (int)strlen(o->name); + if (o->valtype != '-') + i += 1 + strlen(valtype2param(o)); + if (i < MAX_OPT_HELP_WIDTH && i > width) + width = i; + assert(i < (int)sizeof(start)); + } + + if (standard_prolog) + BIO_printf(bio_err, "Usage: %s [options]\nValid options are:\n", + prog); + + /* Now let's print. */ + for (o = list; o->name; o++) { + help = o->helpstr ? o->helpstr : "(No additional info)"; + if (o->name == OPT_HELP_STR) { + BIO_printf(bio_err, help, prog); + continue; + } + + /* Pad out prefix */ + memset(start, ' ', sizeof(start) - 1); + start[sizeof(start) - 1] = '\0'; + + if (o->name == OPT_MORE_STR) { + /* Continuation of previous line; pad and print. */ + start[width] = '\0'; + BIO_printf(bio_err, "%s %s\n", start, help); + continue; + } + + /* Build up the "-flag [param]" part. */ + p = start; + *p++ = ' '; + *p++ = '-'; + if (o->name[0]) + p += strlen(strcpy(p, o->name)); + else + *p++ = '*'; + if (o->valtype != '-') { + *p++ = ' '; + p += strlen(strcpy(p, valtype2param(o))); + } + *p = ' '; + if ((int)(p - start) >= MAX_OPT_HELP_WIDTH) { + *p = '\0'; + BIO_printf(bio_err, "%s\n", start); + memset(start, ' ', sizeof(start)); + } + start[width] = '\0'; + BIO_printf(bio_err, "%s %s\n", start, help); + } +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/passwd.c b/trunk/3rdparty/openssl-1.1-fit/apps/passwd.c new file mode 100644 index 000000000..aa516c874 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/passwd.c @@ -0,0 +1,853 @@ +/* + * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#include "apps.h" +#include "progs.h" + +#include +#include +#include +#include +#ifndef OPENSSL_NO_DES +# include +#endif +#include +#include + +static unsigned const char cov_2char[64] = { + /* from crypto/des/fcrypt.c */ + 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, + 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, + 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, + 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62, + 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, + 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, + 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A +}; + +static const char ascii_dollar[] = { 0x24, 0x00 }; + +typedef enum { + passwd_unset = 0, + passwd_crypt, + passwd_md5, + passwd_apr1, + passwd_sha256, + passwd_sha512, + passwd_aixmd5 +} passwd_modes; + +static int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p, + char *passwd, BIO *out, int quiet, int table, + int reverse, size_t pw_maxlen, passwd_modes mode); + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_IN, + OPT_NOVERIFY, OPT_QUIET, OPT_TABLE, OPT_REVERSE, OPT_APR1, + OPT_1, OPT_5, OPT_6, OPT_CRYPT, OPT_AIXMD5, OPT_SALT, OPT_STDIN, + OPT_R_ENUM +} OPTION_CHOICE; + +const OPTIONS passwd_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"in", OPT_IN, '<', "Read passwords from file"}, + {"noverify", OPT_NOVERIFY, '-', + "Never verify when reading password from terminal"}, + {"quiet", OPT_QUIET, '-', "No warnings"}, + {"table", OPT_TABLE, '-', "Format output as table"}, + {"reverse", OPT_REVERSE, '-', "Switch table columns"}, + {"salt", OPT_SALT, 's', "Use provided salt"}, + {"stdin", OPT_STDIN, '-', "Read passwords from stdin"}, + {"6", OPT_6, '-', "SHA512-based password algorithm"}, + {"5", OPT_5, '-', "SHA256-based password algorithm"}, + {"apr1", OPT_APR1, '-', "MD5-based password algorithm, Apache variant"}, + {"1", OPT_1, '-', "MD5-based password algorithm"}, + {"aixmd5", OPT_AIXMD5, '-', "AIX MD5-based password algorithm"}, +#ifndef OPENSSL_NO_DES + {"crypt", OPT_CRYPT, '-', "Standard Unix password algorithm (default)"}, +#endif + OPT_R_OPTIONS, + {NULL} +}; + +int passwd_main(int argc, char **argv) +{ + BIO *in = NULL; + char *infile = NULL, *salt = NULL, *passwd = NULL, **passwds = NULL; + char *salt_malloc = NULL, *passwd_malloc = NULL, *prog; + OPTION_CHOICE o; + int in_stdin = 0, pw_source_defined = 0; +#ifndef OPENSSL_NO_UI_CONSOLE + int in_noverify = 0; +#endif + int passed_salt = 0, quiet = 0, table = 0, reverse = 0; + int ret = 1; + passwd_modes mode = passwd_unset; + size_t passwd_malloc_size = 0; + size_t pw_maxlen = 256; /* arbitrary limit, should be enough for most + * passwords */ + + prog = opt_init(argc, argv, passwd_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(passwd_options); + ret = 0; + goto end; + case OPT_IN: + if (pw_source_defined) + goto opthelp; + infile = opt_arg(); + pw_source_defined = 1; + break; + case OPT_NOVERIFY: +#ifndef OPENSSL_NO_UI_CONSOLE + in_noverify = 1; +#endif + break; + case OPT_QUIET: + quiet = 1; + break; + case OPT_TABLE: + table = 1; + break; + case OPT_REVERSE: + reverse = 1; + break; + case OPT_1: + if (mode != passwd_unset) + goto opthelp; + mode = passwd_md5; + break; + case OPT_5: + if (mode != passwd_unset) + goto opthelp; + mode = passwd_sha256; + break; + case OPT_6: + if (mode != passwd_unset) + goto opthelp; + mode = passwd_sha512; + break; + case OPT_APR1: + if (mode != passwd_unset) + goto opthelp; + mode = passwd_apr1; + break; + case OPT_AIXMD5: + if (mode != passwd_unset) + goto opthelp; + mode = passwd_aixmd5; + break; + case OPT_CRYPT: +#ifndef OPENSSL_NO_DES + if (mode != passwd_unset) + goto opthelp; + mode = passwd_crypt; +#endif + break; + case OPT_SALT: + passed_salt = 1; + salt = opt_arg(); + break; + case OPT_STDIN: + if (pw_source_defined) + goto opthelp; + in_stdin = 1; + pw_source_defined = 1; + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + } + } + argc = opt_num_rest(); + argv = opt_rest(); + + if (*argv != NULL) { + if (pw_source_defined) + goto opthelp; + pw_source_defined = 1; + passwds = argv; + } + + if (mode == passwd_unset) { + /* use default */ + mode = passwd_crypt; + } + +#ifdef OPENSSL_NO_DES + if (mode == passwd_crypt) + goto opthelp; +#endif + + if (infile != NULL && in_stdin) { + BIO_printf(bio_err, "%s: Can't combine -in and -stdin\n", prog); + goto end; + } + + if (infile != NULL || in_stdin) { + /* + * If in_stdin is true, we know that infile is NULL, and that + * bio_open_default() will give us back an alias for stdin. + */ + in = bio_open_default(infile, 'r', FORMAT_TEXT); + if (in == NULL) + goto end; + } + + if (mode == passwd_crypt) + pw_maxlen = 8; + + if (passwds == NULL) { + /* no passwords on the command line */ + + passwd_malloc_size = pw_maxlen + 2; + /* longer than necessary so that we can warn about truncation */ + passwd = passwd_malloc = + app_malloc(passwd_malloc_size, "password buffer"); + } + + if ((in == NULL) && (passwds == NULL)) { + /* + * we use the following method to make sure what + * in the 'else' section is always compiled, to + * avoid rot of not-frequently-used code. + */ + if (1) { +#ifndef OPENSSL_NO_UI_CONSOLE + /* build a null-terminated list */ + static char *passwds_static[2] = { NULL, NULL }; + + passwds = passwds_static; + if (in == NULL) { + if (EVP_read_pw_string + (passwd_malloc, passwd_malloc_size, "Password: ", + !(passed_salt || in_noverify)) != 0) + goto end; + } + passwds[0] = passwd_malloc; + } else { +#endif + BIO_printf(bio_err, "password required\n"); + goto end; + } + } + + if (in == NULL) { + assert(passwds != NULL); + assert(*passwds != NULL); + + do { /* loop over list of passwords */ + passwd = *passwds++; + if (!do_passwd(passed_salt, &salt, &salt_malloc, passwd, bio_out, + quiet, table, reverse, pw_maxlen, mode)) + goto end; + } while (*passwds != NULL); + } else { + /* in != NULL */ + int done; + + assert(passwd != NULL); + do { + int r = BIO_gets(in, passwd, pw_maxlen + 1); + if (r > 0) { + char *c = (strchr(passwd, '\n')); + if (c != NULL) { + *c = 0; /* truncate at newline */ + } else { + /* ignore rest of line */ + char trash[BUFSIZ]; + do + r = BIO_gets(in, trash, sizeof(trash)); + while ((r > 0) && (!strchr(trash, '\n'))); + } + + if (!do_passwd + (passed_salt, &salt, &salt_malloc, passwd, bio_out, quiet, + table, reverse, pw_maxlen, mode)) + goto end; + } + done = (r <= 0); + } while (!done); + } + ret = 0; + + end: +#if 0 + ERR_print_errors(bio_err); +#endif + OPENSSL_free(salt_malloc); + OPENSSL_free(passwd_malloc); + BIO_free(in); + return ret; +} + +/* + * MD5-based password algorithm (should probably be available as a library + * function; then the static buffer would not be acceptable). For magic + * string "1", this should be compatible to the MD5-based BSD password + * algorithm. For 'magic' string "apr1", this is compatible to the MD5-based + * Apache password algorithm. (Apparently, the Apache password algorithm is + * identical except that the 'magic' string was changed -- the laziest + * application of the NIH principle I've ever encountered.) + */ +static char *md5crypt(const char *passwd, const char *magic, const char *salt) +{ + /* "$apr1$..salt..$.......md5hash..........\0" */ + static char out_buf[6 + 9 + 24 + 2]; + unsigned char buf[MD5_DIGEST_LENGTH]; + char ascii_magic[5]; /* "apr1" plus '\0' */ + char ascii_salt[9]; /* Max 8 chars plus '\0' */ + char *ascii_passwd = NULL; + char *salt_out; + int n; + unsigned int i; + EVP_MD_CTX *md = NULL, *md2 = NULL; + size_t passwd_len, salt_len, magic_len; + + passwd_len = strlen(passwd); + + out_buf[0] = 0; + magic_len = strlen(magic); + OPENSSL_strlcpy(ascii_magic, magic, sizeof(ascii_magic)); +#ifdef CHARSET_EBCDIC + if ((magic[0] & 0x80) != 0) /* High bit is 1 in EBCDIC alnums */ + ebcdic2ascii(ascii_magic, ascii_magic, magic_len); +#endif + + /* The salt gets truncated to 8 chars */ + OPENSSL_strlcpy(ascii_salt, salt, sizeof(ascii_salt)); + salt_len = strlen(ascii_salt); +#ifdef CHARSET_EBCDIC + ebcdic2ascii(ascii_salt, ascii_salt, salt_len); +#endif + +#ifdef CHARSET_EBCDIC + ascii_passwd = OPENSSL_strdup(passwd); + if (ascii_passwd == NULL) + return NULL; + ebcdic2ascii(ascii_passwd, ascii_passwd, passwd_len); + passwd = ascii_passwd; +#endif + + if (magic_len > 0) { + OPENSSL_strlcat(out_buf, ascii_dollar, sizeof(out_buf)); + + if (magic_len > 4) /* assert it's "1" or "apr1" */ + goto err; + + OPENSSL_strlcat(out_buf, ascii_magic, sizeof(out_buf)); + OPENSSL_strlcat(out_buf, ascii_dollar, sizeof(out_buf)); + } + + OPENSSL_strlcat(out_buf, ascii_salt, sizeof(out_buf)); + + if (strlen(out_buf) > 6 + 8) /* assert "$apr1$..salt.." */ + goto err; + + salt_out = out_buf; + if (magic_len > 0) + salt_out += 2 + magic_len; + + if (salt_len > 8) + goto err; + + md = EVP_MD_CTX_new(); + if (md == NULL + || !EVP_DigestInit_ex(md, EVP_md5(), NULL) + || !EVP_DigestUpdate(md, passwd, passwd_len)) + goto err; + + if (magic_len > 0) + if (!EVP_DigestUpdate(md, ascii_dollar, 1) + || !EVP_DigestUpdate(md, ascii_magic, magic_len) + || !EVP_DigestUpdate(md, ascii_dollar, 1)) + goto err; + + if (!EVP_DigestUpdate(md, ascii_salt, salt_len)) + goto err; + + md2 = EVP_MD_CTX_new(); + if (md2 == NULL + || !EVP_DigestInit_ex(md2, EVP_md5(), NULL) + || !EVP_DigestUpdate(md2, passwd, passwd_len) + || !EVP_DigestUpdate(md2, ascii_salt, salt_len) + || !EVP_DigestUpdate(md2, passwd, passwd_len) + || !EVP_DigestFinal_ex(md2, buf, NULL)) + goto err; + + for (i = passwd_len; i > sizeof(buf); i -= sizeof(buf)) { + if (!EVP_DigestUpdate(md, buf, sizeof(buf))) + goto err; + } + if (!EVP_DigestUpdate(md, buf, i)) + goto err; + + n = passwd_len; + while (n) { + if (!EVP_DigestUpdate(md, (n & 1) ? "\0" : passwd, 1)) + goto err; + n >>= 1; + } + if (!EVP_DigestFinal_ex(md, buf, NULL)) + return NULL; + + for (i = 0; i < 1000; i++) { + if (!EVP_DigestInit_ex(md2, EVP_md5(), NULL)) + goto err; + if (!EVP_DigestUpdate(md2, + (i & 1) ? (unsigned const char *)passwd : buf, + (i & 1) ? passwd_len : sizeof(buf))) + goto err; + if (i % 3) { + if (!EVP_DigestUpdate(md2, ascii_salt, salt_len)) + goto err; + } + if (i % 7) { + if (!EVP_DigestUpdate(md2, passwd, passwd_len)) + goto err; + } + if (!EVP_DigestUpdate(md2, + (i & 1) ? buf : (unsigned const char *)passwd, + (i & 1) ? sizeof(buf) : passwd_len)) + goto err; + if (!EVP_DigestFinal_ex(md2, buf, NULL)) + goto err; + } + EVP_MD_CTX_free(md2); + EVP_MD_CTX_free(md); + md2 = NULL; + md = NULL; + + { + /* transform buf into output string */ + unsigned char buf_perm[sizeof(buf)]; + int dest, source; + char *output; + + /* silly output permutation */ + for (dest = 0, source = 0; dest < 14; + dest++, source = (source + 6) % 17) + buf_perm[dest] = buf[source]; + buf_perm[14] = buf[5]; + buf_perm[15] = buf[11]; +# ifndef PEDANTIC /* Unfortunately, this generates a "no + * effect" warning */ + assert(16 == sizeof(buf_perm)); +# endif + + output = salt_out + salt_len; + assert(output == out_buf + strlen(out_buf)); + + *output++ = ascii_dollar[0]; + + for (i = 0; i < 15; i += 3) { + *output++ = cov_2char[buf_perm[i + 2] & 0x3f]; + *output++ = cov_2char[((buf_perm[i + 1] & 0xf) << 2) | + (buf_perm[i + 2] >> 6)]; + *output++ = cov_2char[((buf_perm[i] & 3) << 4) | + (buf_perm[i + 1] >> 4)]; + *output++ = cov_2char[buf_perm[i] >> 2]; + } + assert(i == 15); + *output++ = cov_2char[buf_perm[i] & 0x3f]; + *output++ = cov_2char[buf_perm[i] >> 6]; + *output = 0; + assert(strlen(out_buf) < sizeof(out_buf)); +#ifdef CHARSET_EBCDIC + ascii2ebcdic(out_buf, out_buf, strlen(out_buf)); +#endif + } + + return out_buf; + + err: + OPENSSL_free(ascii_passwd); + EVP_MD_CTX_free(md2); + EVP_MD_CTX_free(md); + return NULL; +} + +/* + * SHA based password algorithm, describe by Ulrich Drepper here: + * https://www.akkadia.org/drepper/SHA-crypt.txt + * (note that it's in the public domain) + */ +static char *shacrypt(const char *passwd, const char *magic, const char *salt) +{ + /* Prefix for optional rounds specification. */ + static const char rounds_prefix[] = "rounds="; + /* Maximum salt string length. */ +# define SALT_LEN_MAX 16 + /* Default number of rounds if not explicitly specified. */ +# define ROUNDS_DEFAULT 5000 + /* Minimum number of rounds. */ +# define ROUNDS_MIN 1000 + /* Maximum number of rounds. */ +# define ROUNDS_MAX 999999999 + + /* "$6$rounds=$......salt......$...shahash(up to 86 chars)...\0" */ + static char out_buf[3 + 17 + 17 + 86 + 1]; + unsigned char buf[SHA512_DIGEST_LENGTH]; + unsigned char temp_buf[SHA512_DIGEST_LENGTH]; + size_t buf_size = 0; + char ascii_magic[2]; + char ascii_salt[17]; /* Max 16 chars plus '\0' */ + char *ascii_passwd = NULL; + size_t n; + EVP_MD_CTX *md = NULL, *md2 = NULL; + const EVP_MD *sha = NULL; + size_t passwd_len, salt_len, magic_len; + unsigned int rounds = 5000; /* Default */ + char rounds_custom = 0; + char *p_bytes = NULL; + char *s_bytes = NULL; + char *cp = NULL; + + passwd_len = strlen(passwd); + magic_len = strlen(magic); + + /* assert it's "5" or "6" */ + if (magic_len != 1) + return NULL; + + switch (magic[0]) { + case '5': + sha = EVP_sha256(); + buf_size = 32; + break; + case '6': + sha = EVP_sha512(); + buf_size = 64; + break; + default: + return NULL; + } + + if (strncmp(salt, rounds_prefix, sizeof(rounds_prefix) - 1) == 0) { + const char *num = salt + sizeof(rounds_prefix) - 1; + char *endp; + unsigned long int srounds = strtoul (num, &endp, 10); + if (*endp == '$') { + salt = endp + 1; + if (srounds > ROUNDS_MAX) + rounds = ROUNDS_MAX; + else if (srounds < ROUNDS_MIN) + rounds = ROUNDS_MIN; + else + rounds = (unsigned int)srounds; + rounds_custom = 1; + } else { + return NULL; + } + } + + OPENSSL_strlcpy(ascii_magic, magic, sizeof(ascii_magic)); +#ifdef CHARSET_EBCDIC + if ((magic[0] & 0x80) != 0) /* High bit is 1 in EBCDIC alnums */ + ebcdic2ascii(ascii_magic, ascii_magic, magic_len); +#endif + + /* The salt gets truncated to 16 chars */ + OPENSSL_strlcpy(ascii_salt, salt, sizeof(ascii_salt)); + salt_len = strlen(ascii_salt); +#ifdef CHARSET_EBCDIC + ebcdic2ascii(ascii_salt, ascii_salt, salt_len); +#endif + +#ifdef CHARSET_EBCDIC + ascii_passwd = OPENSSL_strdup(passwd); + if (ascii_passwd == NULL) + return NULL; + ebcdic2ascii(ascii_passwd, ascii_passwd, passwd_len); + passwd = ascii_passwd; +#endif + + out_buf[0] = 0; + OPENSSL_strlcat(out_buf, ascii_dollar, sizeof(out_buf)); + OPENSSL_strlcat(out_buf, ascii_magic, sizeof(out_buf)); + OPENSSL_strlcat(out_buf, ascii_dollar, sizeof(out_buf)); + if (rounds_custom) { + char tmp_buf[80]; /* "rounds=999999999" */ + sprintf(tmp_buf, "rounds=%u", rounds); +#ifdef CHARSET_EBCDIC + /* In case we're really on a ASCII based platform and just pretend */ + if (tmp_buf[0] != 0x72) /* ASCII 'r' */ + ebcdic2ascii(tmp_buf, tmp_buf, strlen(tmp_buf)); +#endif + OPENSSL_strlcat(out_buf, tmp_buf, sizeof(out_buf)); + OPENSSL_strlcat(out_buf, ascii_dollar, sizeof(out_buf)); + } + OPENSSL_strlcat(out_buf, ascii_salt, sizeof(out_buf)); + + /* assert "$5$rounds=999999999$......salt......" */ + if (strlen(out_buf) > 3 + 17 * rounds_custom + salt_len ) + goto err; + + md = EVP_MD_CTX_new(); + if (md == NULL + || !EVP_DigestInit_ex(md, sha, NULL) + || !EVP_DigestUpdate(md, passwd, passwd_len) + || !EVP_DigestUpdate(md, ascii_salt, salt_len)) + goto err; + + md2 = EVP_MD_CTX_new(); + if (md2 == NULL + || !EVP_DigestInit_ex(md2, sha, NULL) + || !EVP_DigestUpdate(md2, passwd, passwd_len) + || !EVP_DigestUpdate(md2, ascii_salt, salt_len) + || !EVP_DigestUpdate(md2, passwd, passwd_len) + || !EVP_DigestFinal_ex(md2, buf, NULL)) + goto err; + + for (n = passwd_len; n > buf_size; n -= buf_size) { + if (!EVP_DigestUpdate(md, buf, buf_size)) + goto err; + } + if (!EVP_DigestUpdate(md, buf, n)) + goto err; + + n = passwd_len; + while (n) { + if (!EVP_DigestUpdate(md, + (n & 1) ? buf : (unsigned const char *)passwd, + (n & 1) ? buf_size : passwd_len)) + goto err; + n >>= 1; + } + if (!EVP_DigestFinal_ex(md, buf, NULL)) + return NULL; + + /* P sequence */ + if (!EVP_DigestInit_ex(md2, sha, NULL)) + goto err; + + for (n = passwd_len; n > 0; n--) + if (!EVP_DigestUpdate(md2, passwd, passwd_len)) + goto err; + + if (!EVP_DigestFinal_ex(md2, temp_buf, NULL)) + return NULL; + + if ((p_bytes = OPENSSL_zalloc(passwd_len)) == NULL) + goto err; + for (cp = p_bytes, n = passwd_len; n > buf_size; n -= buf_size, cp += buf_size) + memcpy(cp, temp_buf, buf_size); + memcpy(cp, temp_buf, n); + + /* S sequence */ + if (!EVP_DigestInit_ex(md2, sha, NULL)) + goto err; + + for (n = 16 + buf[0]; n > 0; n--) + if (!EVP_DigestUpdate(md2, ascii_salt, salt_len)) + goto err; + + if (!EVP_DigestFinal_ex(md2, temp_buf, NULL)) + return NULL; + + if ((s_bytes = OPENSSL_zalloc(salt_len)) == NULL) + goto err; + for (cp = s_bytes, n = salt_len; n > buf_size; n -= buf_size, cp += buf_size) + memcpy(cp, temp_buf, buf_size); + memcpy(cp, temp_buf, n); + + for (n = 0; n < rounds; n++) { + if (!EVP_DigestInit_ex(md2, sha, NULL)) + goto err; + if (!EVP_DigestUpdate(md2, + (n & 1) ? (unsigned const char *)p_bytes : buf, + (n & 1) ? passwd_len : buf_size)) + goto err; + if (n % 3) { + if (!EVP_DigestUpdate(md2, s_bytes, salt_len)) + goto err; + } + if (n % 7) { + if (!EVP_DigestUpdate(md2, p_bytes, passwd_len)) + goto err; + } + if (!EVP_DigestUpdate(md2, + (n & 1) ? buf : (unsigned const char *)p_bytes, + (n & 1) ? buf_size : passwd_len)) + goto err; + if (!EVP_DigestFinal_ex(md2, buf, NULL)) + goto err; + } + EVP_MD_CTX_free(md2); + EVP_MD_CTX_free(md); + md2 = NULL; + md = NULL; + OPENSSL_free(p_bytes); + OPENSSL_free(s_bytes); + p_bytes = NULL; + s_bytes = NULL; + + cp = out_buf + strlen(out_buf); + *cp++ = ascii_dollar[0]; + +# define b64_from_24bit(B2, B1, B0, N) \ + do { \ + unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0); \ + int i = (N); \ + while (i-- > 0) \ + { \ + *cp++ = cov_2char[w & 0x3f]; \ + w >>= 6; \ + } \ + } while (0) + + switch (magic[0]) { + case '5': + b64_from_24bit (buf[0], buf[10], buf[20], 4); + b64_from_24bit (buf[21], buf[1], buf[11], 4); + b64_from_24bit (buf[12], buf[22], buf[2], 4); + b64_from_24bit (buf[3], buf[13], buf[23], 4); + b64_from_24bit (buf[24], buf[4], buf[14], 4); + b64_from_24bit (buf[15], buf[25], buf[5], 4); + b64_from_24bit (buf[6], buf[16], buf[26], 4); + b64_from_24bit (buf[27], buf[7], buf[17], 4); + b64_from_24bit (buf[18], buf[28], buf[8], 4); + b64_from_24bit (buf[9], buf[19], buf[29], 4); + b64_from_24bit (0, buf[31], buf[30], 3); + break; + case '6': + b64_from_24bit (buf[0], buf[21], buf[42], 4); + b64_from_24bit (buf[22], buf[43], buf[1], 4); + b64_from_24bit (buf[44], buf[2], buf[23], 4); + b64_from_24bit (buf[3], buf[24], buf[45], 4); + b64_from_24bit (buf[25], buf[46], buf[4], 4); + b64_from_24bit (buf[47], buf[5], buf[26], 4); + b64_from_24bit (buf[6], buf[27], buf[48], 4); + b64_from_24bit (buf[28], buf[49], buf[7], 4); + b64_from_24bit (buf[50], buf[8], buf[29], 4); + b64_from_24bit (buf[9], buf[30], buf[51], 4); + b64_from_24bit (buf[31], buf[52], buf[10], 4); + b64_from_24bit (buf[53], buf[11], buf[32], 4); + b64_from_24bit (buf[12], buf[33], buf[54], 4); + b64_from_24bit (buf[34], buf[55], buf[13], 4); + b64_from_24bit (buf[56], buf[14], buf[35], 4); + b64_from_24bit (buf[15], buf[36], buf[57], 4); + b64_from_24bit (buf[37], buf[58], buf[16], 4); + b64_from_24bit (buf[59], buf[17], buf[38], 4); + b64_from_24bit (buf[18], buf[39], buf[60], 4); + b64_from_24bit (buf[40], buf[61], buf[19], 4); + b64_from_24bit (buf[62], buf[20], buf[41], 4); + b64_from_24bit (0, 0, buf[63], 2); + break; + default: + goto err; + } + *cp = '\0'; +#ifdef CHARSET_EBCDIC + ascii2ebcdic(out_buf, out_buf, strlen(out_buf)); +#endif + + return out_buf; + + err: + EVP_MD_CTX_free(md2); + EVP_MD_CTX_free(md); + OPENSSL_free(p_bytes); + OPENSSL_free(s_bytes); + OPENSSL_free(ascii_passwd); + return NULL; +} + +static int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p, + char *passwd, BIO *out, int quiet, int table, + int reverse, size_t pw_maxlen, passwd_modes mode) +{ + char *hash = NULL; + + assert(salt_p != NULL); + assert(salt_malloc_p != NULL); + + /* first make sure we have a salt */ + if (!passed_salt) { + size_t saltlen = 0; + size_t i; + +#ifndef OPENSSL_NO_DES + if (mode == passwd_crypt) + saltlen = 2; +#endif /* !OPENSSL_NO_DES */ + + if (mode == passwd_md5 || mode == passwd_apr1 || mode == passwd_aixmd5) + saltlen = 8; + + if (mode == passwd_sha256 || mode == passwd_sha512) + saltlen = 16; + + assert(saltlen != 0); + + if (*salt_malloc_p == NULL) + *salt_p = *salt_malloc_p = app_malloc(saltlen + 1, "salt buffer"); + if (RAND_bytes((unsigned char *)*salt_p, saltlen) <= 0) + goto end; + + for (i = 0; i < saltlen; i++) + (*salt_p)[i] = cov_2char[(*salt_p)[i] & 0x3f]; /* 6 bits */ + (*salt_p)[i] = 0; +# ifdef CHARSET_EBCDIC + /* The password encryption funtion will convert back to ASCII */ + ascii2ebcdic(*salt_p, *salt_p, saltlen); +# endif + } + + assert(*salt_p != NULL); + + /* truncate password if necessary */ + if ((strlen(passwd) > pw_maxlen)) { + if (!quiet) + /* + * XXX: really we should know how to print a size_t, not cast it + */ + BIO_printf(bio_err, + "Warning: truncating password to %u characters\n", + (unsigned)pw_maxlen); + passwd[pw_maxlen] = 0; + } + assert(strlen(passwd) <= pw_maxlen); + + /* now compute password hash */ +#ifndef OPENSSL_NO_DES + if (mode == passwd_crypt) + hash = DES_crypt(passwd, *salt_p); +#endif + if (mode == passwd_md5 || mode == passwd_apr1) + hash = md5crypt(passwd, (mode == passwd_md5 ? "1" : "apr1"), *salt_p); + if (mode == passwd_aixmd5) + hash = md5crypt(passwd, "", *salt_p); + if (mode == passwd_sha256 || mode == passwd_sha512) + hash = shacrypt(passwd, (mode == passwd_sha256 ? "5" : "6"), *salt_p); + assert(hash != NULL); + + if (table && !reverse) + BIO_printf(out, "%s\t%s\n", passwd, hash); + else if (table && reverse) + BIO_printf(out, "%s\t%s\n", hash, passwd); + else + BIO_printf(out, "%s\n", hash); + return 1; + + end: + return 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/pca-cert.srl b/trunk/3rdparty/openssl-1.1-fit/apps/pca-cert.srl new file mode 100644 index 000000000..2c7456e3e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/pca-cert.srl @@ -0,0 +1 @@ +07 diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/pca-key.pem b/trunk/3rdparty/openssl-1.1-fit/apps/pca-key.pem new file mode 100644 index 000000000..c6ad0e92d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/pca-key.pem @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALYYjjtpLs/lfkPF +xAFZ4V3He5mZFbsEakK9bA2fQaryreRwyfhbXbDJHyBV+c4xI5fbmmVd2t/us4k4 +rMhGsBtL89SqCEHhPJpLFywiQVmJTAjANYrWkZK5uR/++YmZyzuLfPHLButuK6cF +GKXw3NNToxjYooMf0mad2rPX3cKTAgMBAAECgYBvrJ+Nz/Pli9jjt2V9bqHH4Y7r +o/avuwVv6Ltbn0+mhy4d6w3yQhYzVSTBr/iDe59YglUt1WFl8/4nKZrNOIzHJlav +Sw4hd3fYBHxbT+DgZMQ9ikjHECWRdDffrnlTLsSJAcxnpMJBPe3dKCRDMUrqWUvB +IIKaxyqmXJms5Y/wAQJBAPFL9NMKJcWBftMKXCasxsV0ZGjgqHGZODYjtGFN9jJO +6AbZrxfCcapTWG4RCC2o/EDEMN8aArEhfdrYY3lhXGsCQQDBMRzFevkD7SYXTw5G +NA/gJOAsFMYbt7tebcCRsHT7t3ymVfO2QwK7ZF0f/SYvi7cMAPraHvO7s3kFdGTB +kDx5AkAHBICASsFCdzurA5gef9PgFjx9WFtNwnkCChPK6KuKVwUkfdw7wqnvnDDs +Mo6cVVfQwmPxeR4u7JxuavCprQ01AkEAp5ZGAh1J9Jj9CQ1AMbAp8WOrvzGKJTM9 +641Dll4/LLif/d7j2kDJFuvaSMyeGnKVqGkVMq/U+QeYPR4Z5TuM6QJAWK05qFed +wYgTZyVN0MY53ZOMAIWwjz0cr24TvDfmsZqIvguGL616GKQZKdKDZQyQHg+dCzqJ +HgIoacuFDKz5CA== +-----END PRIVATE KEY----- diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/pca-req.pem b/trunk/3rdparty/openssl-1.1-fit/apps/pca-req.pem new file mode 100644 index 000000000..5a8c5cbf1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/pca-req.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBnDCCAQUCAQAwXDELMAkGA1UEBhMCQVUxEzARBgNVBAgMClF1ZWVuc2xhbmQx +GjAYBgNVBAoMEUNyeXB0U29mdCBQdHkgTHRkMRwwGgYDVQQDDBNUZXN0IFBDQSAo +MTAyNCBiaXQpMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2GI47aS7P5X5D +xcQBWeFdx3uZmRW7BGpCvWwNn0Gq8q3kcMn4W12wyR8gVfnOMSOX25plXdrf7rOJ +OKzIRrAbS/PUqghB4TyaSxcsIkFZiUwIwDWK1pGSubkf/vmJmcs7i3zxywbrbiun +BRil8NzTU6MY2KKDH9Jmndqz193CkwIDAQABoAAwDQYJKoZIhvcNAQELBQADgYEA +eJdCB0nHnFK0hek4biAxX0GuJXkknuUy46NKEhv3GBwt4gtO29bfkbQTGOsBBKNs +KptlnkItscOXY+0lSva9K3XlwD9do7k2IZFtXJVayZVw1GcKybIY0l7B6kcSxG7T +f3CsO+ifdrsJKtyoZNs96lBMrtXyGybt3mgQNdZauQU= +-----END CERTIFICATE REQUEST----- diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/pkcs12.c b/trunk/3rdparty/openssl-1.1-fit/apps/pkcs12.c new file mode 100644 index 000000000..719a309a8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/pkcs12.c @@ -0,0 +1,968 @@ +/* + * Copyright 1999-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#if defined(OPENSSL_NO_DES) +NON_EMPTY_TRANSLATION_UNIT +#else + +# include +# include +# include +# include "apps.h" +# include "progs.h" +# include +# include +# include +# include + +# define NOKEYS 0x1 +# define NOCERTS 0x2 +# define INFO 0x4 +# define CLCERTS 0x8 +# define CACERTS 0x10 + +#define PASSWD_BUF_SIZE 2048 + +static int get_cert_chain(X509 *cert, X509_STORE *store, + STACK_OF(X509) **chain); +int dump_certs_keys_p12(BIO *out, const PKCS12 *p12, + const char *pass, int passlen, int options, + char *pempass, const EVP_CIPHER *enc); +int dump_certs_pkeys_bags(BIO *out, const STACK_OF(PKCS12_SAFEBAG) *bags, + const char *pass, int passlen, int options, + char *pempass, const EVP_CIPHER *enc); +int dump_certs_pkeys_bag(BIO *out, const PKCS12_SAFEBAG *bags, + const char *pass, int passlen, + int options, char *pempass, const EVP_CIPHER *enc); +int print_attribs(BIO *out, const STACK_OF(X509_ATTRIBUTE) *attrlst, + const char *name); +void hex_prin(BIO *out, unsigned char *buf, int len); +static int alg_print(const X509_ALGOR *alg); +int cert_load(BIO *in, STACK_OF(X509) *sk); +static int set_pbe(int *ppbe, const char *str); + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_CIPHER, OPT_NOKEYS, OPT_KEYEX, OPT_KEYSIG, OPT_NOCERTS, OPT_CLCERTS, + OPT_CACERTS, OPT_NOOUT, OPT_INFO, OPT_CHAIN, OPT_TWOPASS, OPT_NOMACVER, + OPT_DESCERT, OPT_EXPORT, OPT_NOITER, OPT_MACITER, OPT_NOMACITER, + OPT_NOMAC, OPT_LMK, OPT_NODES, OPT_MACALG, OPT_CERTPBE, OPT_KEYPBE, + OPT_INKEY, OPT_CERTFILE, OPT_NAME, OPT_CSP, OPT_CANAME, + OPT_IN, OPT_OUT, OPT_PASSIN, OPT_PASSOUT, OPT_PASSWORD, OPT_CAPATH, + OPT_CAFILE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_ENGINE, + OPT_R_ENUM +} OPTION_CHOICE; + +const OPTIONS pkcs12_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"nokeys", OPT_NOKEYS, '-', "Don't output private keys"}, + {"keyex", OPT_KEYEX, '-', "Set MS key exchange type"}, + {"keysig", OPT_KEYSIG, '-', "Set MS key signature type"}, + {"nocerts", OPT_NOCERTS, '-', "Don't output certificates"}, + {"clcerts", OPT_CLCERTS, '-', "Only output client certificates"}, + {"cacerts", OPT_CACERTS, '-', "Only output CA certificates"}, + {"noout", OPT_NOOUT, '-', "Don't output anything, just verify"}, + {"info", OPT_INFO, '-', "Print info about PKCS#12 structure"}, + {"chain", OPT_CHAIN, '-', "Add certificate chain"}, + {"twopass", OPT_TWOPASS, '-', "Separate MAC, encryption passwords"}, + {"nomacver", OPT_NOMACVER, '-', "Don't verify MAC"}, +# ifndef OPENSSL_NO_RC2 + {"descert", OPT_DESCERT, '-', + "Encrypt output with 3DES (default RC2-40)"}, + {"certpbe", OPT_CERTPBE, 's', + "Certificate PBE algorithm (default RC2-40)"}, +# else + {"descert", OPT_DESCERT, '-', "Encrypt output with 3DES (the default)"}, + {"certpbe", OPT_CERTPBE, 's', "Certificate PBE algorithm (default 3DES)"}, +# endif + {"export", OPT_EXPORT, '-', "Output PKCS12 file"}, + {"noiter", OPT_NOITER, '-', "Don't use encryption iteration"}, + {"maciter", OPT_MACITER, '-', "Use MAC iteration"}, + {"nomaciter", OPT_NOMACITER, '-', "Don't use MAC iteration"}, + {"nomac", OPT_NOMAC, '-', "Don't generate MAC"}, + {"LMK", OPT_LMK, '-', + "Add local machine keyset attribute to private key"}, + {"nodes", OPT_NODES, '-', "Don't encrypt private keys"}, + {"macalg", OPT_MACALG, 's', + "Digest algorithm used in MAC (default SHA1)"}, + {"keypbe", OPT_KEYPBE, 's', "Private key PBE algorithm (default 3DES)"}, + OPT_R_OPTIONS, + {"inkey", OPT_INKEY, 's', "Private key if not infile"}, + {"certfile", OPT_CERTFILE, '<', "Load certs from file"}, + {"name", OPT_NAME, 's', "Use name as friendly name"}, + {"CSP", OPT_CSP, 's', "Microsoft CSP name"}, + {"caname", OPT_CANAME, 's', + "Use name as CA friendly name (can be repeated)"}, + {"in", OPT_IN, '<', "Input filename"}, + {"out", OPT_OUT, '>', "Output filename"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, + {"password", OPT_PASSWORD, 's', "Set import/export password source"}, + {"CApath", OPT_CAPATH, '/', "PEM-format directory of CA's"}, + {"CAfile", OPT_CAFILE, '<', "PEM-format file of CA's"}, + {"no-CAfile", OPT_NOCAFILE, '-', + "Do not load the default certificates file"}, + {"no-CApath", OPT_NOCAPATH, '-', + "Do not load certificates from the default certificates directory"}, + {"", OPT_CIPHER, '-', "Any supported cipher"}, +# ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +# endif + {NULL} +}; + +int pkcs12_main(int argc, char **argv) +{ + char *infile = NULL, *outfile = NULL, *keyname = NULL, *certfile = NULL; + char *name = NULL, *csp_name = NULL; + char pass[PASSWD_BUF_SIZE] = "", macpass[PASSWD_BUF_SIZE] = ""; + int export_cert = 0, options = 0, chain = 0, twopass = 0, keytype = 0; + int iter = PKCS12_DEFAULT_ITER, maciter = PKCS12_DEFAULT_ITER; +# ifndef OPENSSL_NO_RC2 + int cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC; +# else + int cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; +# endif + int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; + int ret = 1, macver = 1, add_lmk = 0, private = 0; + int noprompt = 0; + char *passinarg = NULL, *passoutarg = NULL, *passarg = NULL; + char *passin = NULL, *passout = NULL, *macalg = NULL; + char *cpass = NULL, *mpass = NULL, *badpass = NULL; + const char *CApath = NULL, *CAfile = NULL, *prog; + int noCApath = 0, noCAfile = 0; + ENGINE *e = NULL; + BIO *in = NULL, *out = NULL; + PKCS12 *p12 = NULL; + STACK_OF(OPENSSL_STRING) *canames = NULL; + const EVP_CIPHER *enc = EVP_des_ede3_cbc(); + OPTION_CHOICE o; + + prog = opt_init(argc, argv, pkcs12_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(pkcs12_options); + ret = 0; + goto end; + case OPT_NOKEYS: + options |= NOKEYS; + break; + case OPT_KEYEX: + keytype = KEY_EX; + break; + case OPT_KEYSIG: + keytype = KEY_SIG; + break; + case OPT_NOCERTS: + options |= NOCERTS; + break; + case OPT_CLCERTS: + options |= CLCERTS; + break; + case OPT_CACERTS: + options |= CACERTS; + break; + case OPT_NOOUT: + options |= (NOKEYS | NOCERTS); + break; + case OPT_INFO: + options |= INFO; + break; + case OPT_CHAIN: + chain = 1; + break; + case OPT_TWOPASS: + twopass = 1; + break; + case OPT_NOMACVER: + macver = 0; + break; + case OPT_DESCERT: + cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; + break; + case OPT_EXPORT: + export_cert = 1; + break; + case OPT_CIPHER: + if (!opt_cipher(opt_unknown(), &enc)) + goto opthelp; + break; + case OPT_NOITER: + iter = 1; + break; + case OPT_MACITER: + maciter = PKCS12_DEFAULT_ITER; + break; + case OPT_NOMACITER: + maciter = 1; + break; + case OPT_NOMAC: + maciter = -1; + break; + case OPT_MACALG: + macalg = opt_arg(); + break; + case OPT_NODES: + enc = NULL; + break; + case OPT_CERTPBE: + if (!set_pbe(&cert_pbe, opt_arg())) + goto opthelp; + break; + case OPT_KEYPBE: + if (!set_pbe(&key_pbe, opt_arg())) + goto opthelp; + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_INKEY: + keyname = opt_arg(); + break; + case OPT_CERTFILE: + certfile = opt_arg(); + break; + case OPT_NAME: + name = opt_arg(); + break; + case OPT_LMK: + add_lmk = 1; + break; + case OPT_CSP: + csp_name = opt_arg(); + break; + case OPT_CANAME: + if (canames == NULL + && (canames = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; + sk_OPENSSL_STRING_push(canames, opt_arg()); + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_PASSOUT: + passoutarg = opt_arg(); + break; + case OPT_PASSWORD: + passarg = opt_arg(); + break; + case OPT_CAPATH: + CApath = opt_arg(); + break; + case OPT_CAFILE: + CAfile = opt_arg(); + break; + case OPT_NOCAPATH: + noCApath = 1; + break; + case OPT_NOCAFILE: + noCAfile = 1; + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + } + } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + + private = 1; + + if (passarg != NULL) { + if (export_cert) + passoutarg = passarg; + else + passinarg = passarg; + } + + if (!app_passwd(passinarg, passoutarg, &passin, &passout)) { + BIO_printf(bio_err, "Error getting passwords\n"); + goto end; + } + + if (cpass == NULL) { + if (export_cert) + cpass = passout; + else + cpass = passin; + } + + if (cpass != NULL) { + mpass = cpass; + noprompt = 1; + if (twopass) { + if (export_cert) + BIO_printf(bio_err, "Option -twopass cannot be used with -passout or -password\n"); + else + BIO_printf(bio_err, "Option -twopass cannot be used with -passin or -password\n"); + goto end; + } + } else { + cpass = pass; + mpass = macpass; + } + + if (twopass) { + /* To avoid bit rot */ + if (1) { +#ifndef OPENSSL_NO_UI_CONSOLE + if (EVP_read_pw_string( + macpass, sizeof(macpass), "Enter MAC Password:", export_cert)) { + BIO_printf(bio_err, "Can't read Password\n"); + goto end; + } + } else { +#endif + BIO_printf(bio_err, "Unsupported option -twopass\n"); + goto end; + } + } + + if (export_cert) { + EVP_PKEY *key = NULL; + X509 *ucert = NULL, *x = NULL; + STACK_OF(X509) *certs = NULL; + const EVP_MD *macmd = NULL; + unsigned char *catmp = NULL; + int i; + + if ((options & (NOCERTS | NOKEYS)) == (NOCERTS | NOKEYS)) { + BIO_printf(bio_err, "Nothing to do!\n"); + goto export_end; + } + + if (options & NOCERTS) + chain = 0; + + if (!(options & NOKEYS)) { + key = load_key(keyname ? keyname : infile, + FORMAT_PEM, 1, passin, e, "private key"); + if (key == NULL) + goto export_end; + } + + /* Load in all certs in input file */ + if (!(options & NOCERTS)) { + if (!load_certs(infile, &certs, FORMAT_PEM, NULL, + "certificates")) + goto export_end; + + if (key != NULL) { + /* Look for matching private key */ + for (i = 0; i < sk_X509_num(certs); i++) { + x = sk_X509_value(certs, i); + if (X509_check_private_key(x, key)) { + ucert = x; + /* Zero keyid and alias */ + X509_keyid_set1(ucert, NULL, 0); + X509_alias_set1(ucert, NULL, 0); + /* Remove from list */ + (void)sk_X509_delete(certs, i); + break; + } + } + if (ucert == NULL) { + BIO_printf(bio_err, + "No certificate matches private key\n"); + goto export_end; + } + } + + } + + /* Add any more certificates asked for */ + if (certfile != NULL) { + if (!load_certs(certfile, &certs, FORMAT_PEM, NULL, + "certificates from certfile")) + goto export_end; + } + + /* If chaining get chain from user cert */ + if (chain) { + int vret; + STACK_OF(X509) *chain2; + X509_STORE *store; + if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) + == NULL) + goto export_end; + + vret = get_cert_chain(ucert, store, &chain2); + X509_STORE_free(store); + + if (vret == X509_V_OK) { + /* Exclude verified certificate */ + for (i = 1; i < sk_X509_num(chain2); i++) + sk_X509_push(certs, sk_X509_value(chain2, i)); + /* Free first certificate */ + X509_free(sk_X509_value(chain2, 0)); + sk_X509_free(chain2); + } else { + if (vret != X509_V_ERR_UNSPECIFIED) + BIO_printf(bio_err, "Error %s getting chain.\n", + X509_verify_cert_error_string(vret)); + else + ERR_print_errors(bio_err); + goto export_end; + } + } + + /* Add any CA names */ + + for (i = 0; i < sk_OPENSSL_STRING_num(canames); i++) { + catmp = (unsigned char *)sk_OPENSSL_STRING_value(canames, i); + X509_alias_set1(sk_X509_value(certs, i), catmp, -1); + } + + if (csp_name != NULL && key != NULL) + EVP_PKEY_add1_attr_by_NID(key, NID_ms_csp_name, + MBSTRING_ASC, (unsigned char *)csp_name, + -1); + + if (add_lmk && key != NULL) + EVP_PKEY_add1_attr_by_NID(key, NID_LocalKeySet, 0, NULL, -1); + + if (!noprompt) { + /* To avoid bit rot */ + if (1) { +#ifndef OPENSSL_NO_UI_CONSOLE + if (EVP_read_pw_string(pass, sizeof(pass), + "Enter Export Password:", 1)) { + BIO_printf(bio_err, "Can't read Password\n"); + goto export_end; + } + } else { +#endif + BIO_printf(bio_err, "Password required\n"); + goto export_end; + } + } + + if (!twopass) + OPENSSL_strlcpy(macpass, pass, sizeof(macpass)); + + p12 = PKCS12_create(cpass, name, key, ucert, certs, + key_pbe, cert_pbe, iter, -1, keytype); + + if (!p12) { + ERR_print_errors(bio_err); + goto export_end; + } + + if (macalg) { + if (!opt_md(macalg, &macmd)) + goto opthelp; + } + + if (maciter != -1) + PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, macmd); + + assert(private); + + out = bio_open_owner(outfile, FORMAT_PKCS12, private); + if (out == NULL) + goto end; + + i2d_PKCS12_bio(out, p12); + + ret = 0; + + export_end: + + EVP_PKEY_free(key); + sk_X509_pop_free(certs, X509_free); + X509_free(ucert); + + goto end; + + } + + in = bio_open_default(infile, 'r', FORMAT_PKCS12); + if (in == NULL) + goto end; + out = bio_open_owner(outfile, FORMAT_PEM, private); + if (out == NULL) + goto end; + + if ((p12 = d2i_PKCS12_bio(in, NULL)) == NULL) { + ERR_print_errors(bio_err); + goto end; + } + + if (!noprompt) { + if (1) { +#ifndef OPENSSL_NO_UI_CONSOLE + if (EVP_read_pw_string(pass, sizeof(pass), "Enter Import Password:", + 0)) { + BIO_printf(bio_err, "Can't read Password\n"); + goto end; + } + } else { +#endif + BIO_printf(bio_err, "Password required\n"); + goto end; + } + } + + if (!twopass) + OPENSSL_strlcpy(macpass, pass, sizeof(macpass)); + + if ((options & INFO) && PKCS12_mac_present(p12)) { + const ASN1_INTEGER *tmaciter; + const X509_ALGOR *macalgid; + const ASN1_OBJECT *macobj; + const ASN1_OCTET_STRING *tmac; + const ASN1_OCTET_STRING *tsalt; + + PKCS12_get0_mac(&tmac, &macalgid, &tsalt, &tmaciter, p12); + /* current hash algorithms do not use parameters so extract just name, + in future alg_print() may be needed */ + X509_ALGOR_get0(&macobj, NULL, NULL, macalgid); + BIO_puts(bio_err, "MAC: "); + i2a_ASN1_OBJECT(bio_err, macobj); + BIO_printf(bio_err, ", Iteration %ld\n", + tmaciter != NULL ? ASN1_INTEGER_get(tmaciter) : 1L); + BIO_printf(bio_err, "MAC length: %ld, salt length: %ld\n", + tmac != NULL ? ASN1_STRING_length(tmac) : 0L, + tsalt != NULL ? ASN1_STRING_length(tsalt) : 0L); + } + if (macver) { + /* If we enter empty password try no password first */ + if (!mpass[0] && PKCS12_verify_mac(p12, NULL, 0)) { + /* If mac and crypto pass the same set it to NULL too */ + if (!twopass) + cpass = NULL; + } else if (!PKCS12_verify_mac(p12, mpass, -1)) { + /* + * May be UTF8 from previous version of OpenSSL: + * convert to a UTF8 form which will translate + * to the same Unicode password. + */ + unsigned char *utmp; + int utmplen; + utmp = OPENSSL_asc2uni(mpass, -1, NULL, &utmplen); + if (utmp == NULL) + goto end; + badpass = OPENSSL_uni2utf8(utmp, utmplen); + OPENSSL_free(utmp); + if (!PKCS12_verify_mac(p12, badpass, -1)) { + BIO_printf(bio_err, "Mac verify error: invalid password?\n"); + ERR_print_errors(bio_err); + goto end; + } else { + BIO_printf(bio_err, "Warning: using broken algorithm\n"); + if (!twopass) + cpass = badpass; + } + } + } + + assert(private); + if (!dump_certs_keys_p12(out, p12, cpass, -1, options, passout, enc)) { + BIO_printf(bio_err, "Error outputting keys and certificates\n"); + ERR_print_errors(bio_err); + goto end; + } + ret = 0; + end: + PKCS12_free(p12); + release_engine(e); + BIO_free(in); + BIO_free_all(out); + sk_OPENSSL_STRING_free(canames); + OPENSSL_free(badpass); + OPENSSL_free(passin); + OPENSSL_free(passout); + return ret; +} + +int dump_certs_keys_p12(BIO *out, const PKCS12 *p12, const char *pass, + int passlen, int options, char *pempass, + const EVP_CIPHER *enc) +{ + STACK_OF(PKCS7) *asafes = NULL; + STACK_OF(PKCS12_SAFEBAG) *bags; + int i, bagnid; + int ret = 0; + PKCS7 *p7; + + if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL) + return 0; + for (i = 0; i < sk_PKCS7_num(asafes); i++) { + p7 = sk_PKCS7_value(asafes, i); + bagnid = OBJ_obj2nid(p7->type); + if (bagnid == NID_pkcs7_data) { + bags = PKCS12_unpack_p7data(p7); + if (options & INFO) + BIO_printf(bio_err, "PKCS7 Data\n"); + } else if (bagnid == NID_pkcs7_encrypted) { + if (options & INFO) { + BIO_printf(bio_err, "PKCS7 Encrypted data: "); + alg_print(p7->d.encrypted->enc_data->algorithm); + } + bags = PKCS12_unpack_p7encdata(p7, pass, passlen); + } else { + continue; + } + if (!bags) + goto err; + if (!dump_certs_pkeys_bags(out, bags, pass, passlen, + options, pempass, enc)) { + sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); + goto err; + } + sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); + bags = NULL; + } + ret = 1; + + err: + sk_PKCS7_pop_free(asafes, PKCS7_free); + return ret; +} + +int dump_certs_pkeys_bags(BIO *out, const STACK_OF(PKCS12_SAFEBAG) *bags, + const char *pass, int passlen, int options, + char *pempass, const EVP_CIPHER *enc) +{ + int i; + for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) { + if (!dump_certs_pkeys_bag(out, + sk_PKCS12_SAFEBAG_value(bags, i), + pass, passlen, options, pempass, enc)) + return 0; + } + return 1; +} + +int dump_certs_pkeys_bag(BIO *out, const PKCS12_SAFEBAG *bag, + const char *pass, int passlen, int options, + char *pempass, const EVP_CIPHER *enc) +{ + EVP_PKEY *pkey; + PKCS8_PRIV_KEY_INFO *p8; + const PKCS8_PRIV_KEY_INFO *p8c; + X509 *x509; + const STACK_OF(X509_ATTRIBUTE) *attrs; + int ret = 0; + + attrs = PKCS12_SAFEBAG_get0_attrs(bag); + + switch (PKCS12_SAFEBAG_get_nid(bag)) { + case NID_keyBag: + if (options & INFO) + BIO_printf(bio_err, "Key bag\n"); + if (options & NOKEYS) + return 1; + print_attribs(out, attrs, "Bag Attributes"); + p8c = PKCS12_SAFEBAG_get0_p8inf(bag); + if ((pkey = EVP_PKCS82PKEY(p8c)) == NULL) + return 0; + print_attribs(out, PKCS8_pkey_get0_attrs(p8c), "Key Attributes"); + ret = PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, pempass); + EVP_PKEY_free(pkey); + break; + + case NID_pkcs8ShroudedKeyBag: + if (options & INFO) { + const X509_SIG *tp8; + const X509_ALGOR *tp8alg; + + BIO_printf(bio_err, "Shrouded Keybag: "); + tp8 = PKCS12_SAFEBAG_get0_pkcs8(bag); + X509_SIG_get0(tp8, &tp8alg, NULL); + alg_print(tp8alg); + } + if (options & NOKEYS) + return 1; + print_attribs(out, attrs, "Bag Attributes"); + if ((p8 = PKCS12_decrypt_skey(bag, pass, passlen)) == NULL) + return 0; + if ((pkey = EVP_PKCS82PKEY(p8)) == NULL) { + PKCS8_PRIV_KEY_INFO_free(p8); + return 0; + } + print_attribs(out, PKCS8_pkey_get0_attrs(p8), "Key Attributes"); + PKCS8_PRIV_KEY_INFO_free(p8); + ret = PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, pempass); + EVP_PKEY_free(pkey); + break; + + case NID_certBag: + if (options & INFO) + BIO_printf(bio_err, "Certificate bag\n"); + if (options & NOCERTS) + return 1; + if (PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID)) { + if (options & CACERTS) + return 1; + } else if (options & CLCERTS) + return 1; + print_attribs(out, attrs, "Bag Attributes"); + if (PKCS12_SAFEBAG_get_bag_nid(bag) != NID_x509Certificate) + return 1; + if ((x509 = PKCS12_SAFEBAG_get1_cert(bag)) == NULL) + return 0; + dump_cert_text(out, x509); + ret = PEM_write_bio_X509(out, x509); + X509_free(x509); + break; + + case NID_safeContentsBag: + if (options & INFO) + BIO_printf(bio_err, "Safe Contents bag\n"); + print_attribs(out, attrs, "Bag Attributes"); + return dump_certs_pkeys_bags(out, PKCS12_SAFEBAG_get0_safes(bag), + pass, passlen, options, pempass, enc); + + default: + BIO_printf(bio_err, "Warning unsupported bag type: "); + i2a_ASN1_OBJECT(bio_err, PKCS12_SAFEBAG_get0_type(bag)); + BIO_printf(bio_err, "\n"); + return 1; + } + return ret; +} + +/* Given a single certificate return a verified chain or NULL if error */ + +static int get_cert_chain(X509 *cert, X509_STORE *store, + STACK_OF(X509) **chain) +{ + X509_STORE_CTX *store_ctx = NULL; + STACK_OF(X509) *chn = NULL; + int i = 0; + + store_ctx = X509_STORE_CTX_new(); + if (store_ctx == NULL) { + i = X509_V_ERR_UNSPECIFIED; + goto end; + } + if (!X509_STORE_CTX_init(store_ctx, store, cert, NULL)) { + i = X509_V_ERR_UNSPECIFIED; + goto end; + } + + + if (X509_verify_cert(store_ctx) > 0) + chn = X509_STORE_CTX_get1_chain(store_ctx); + else if ((i = X509_STORE_CTX_get_error(store_ctx)) == 0) + i = X509_V_ERR_UNSPECIFIED; + +end: + X509_STORE_CTX_free(store_ctx); + *chain = chn; + return i; +} + +static int alg_print(const X509_ALGOR *alg) +{ + int pbenid, aparamtype; + const ASN1_OBJECT *aoid; + const void *aparam; + PBEPARAM *pbe = NULL; + + X509_ALGOR_get0(&aoid, &aparamtype, &aparam, alg); + + pbenid = OBJ_obj2nid(aoid); + + BIO_printf(bio_err, "%s", OBJ_nid2ln(pbenid)); + + /* + * If PBE algorithm is PBES2 decode algorithm parameters + * for additional details. + */ + if (pbenid == NID_pbes2) { + PBE2PARAM *pbe2 = NULL; + int encnid; + if (aparamtype == V_ASN1_SEQUENCE) + pbe2 = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBE2PARAM)); + if (pbe2 == NULL) { + BIO_puts(bio_err, ", "); + goto done; + } + X509_ALGOR_get0(&aoid, &aparamtype, &aparam, pbe2->keyfunc); + pbenid = OBJ_obj2nid(aoid); + X509_ALGOR_get0(&aoid, NULL, NULL, pbe2->encryption); + encnid = OBJ_obj2nid(aoid); + BIO_printf(bio_err, ", %s, %s", OBJ_nid2ln(pbenid), + OBJ_nid2sn(encnid)); + /* If KDF is PBKDF2 decode parameters */ + if (pbenid == NID_id_pbkdf2) { + PBKDF2PARAM *kdf = NULL; + int prfnid; + if (aparamtype == V_ASN1_SEQUENCE) + kdf = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBKDF2PARAM)); + if (kdf == NULL) { + BIO_puts(bio_err, ", "); + goto done; + } + + if (kdf->prf == NULL) { + prfnid = NID_hmacWithSHA1; + } else { + X509_ALGOR_get0(&aoid, NULL, NULL, kdf->prf); + prfnid = OBJ_obj2nid(aoid); + } + BIO_printf(bio_err, ", Iteration %ld, PRF %s", + ASN1_INTEGER_get(kdf->iter), OBJ_nid2sn(prfnid)); + PBKDF2PARAM_free(kdf); +#ifndef OPENSSL_NO_SCRYPT + } else if (pbenid == NID_id_scrypt) { + SCRYPT_PARAMS *kdf = NULL; + + if (aparamtype == V_ASN1_SEQUENCE) + kdf = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(SCRYPT_PARAMS)); + if (kdf == NULL) { + BIO_puts(bio_err, ", "); + goto done; + } + BIO_printf(bio_err, ", Salt length: %d, Cost(N): %ld, " + "Block size(r): %ld, Paralelizm(p): %ld", + ASN1_STRING_length(kdf->salt), + ASN1_INTEGER_get(kdf->costParameter), + ASN1_INTEGER_get(kdf->blockSize), + ASN1_INTEGER_get(kdf->parallelizationParameter)); + SCRYPT_PARAMS_free(kdf); +#endif + } + PBE2PARAM_free(pbe2); + } else { + if (aparamtype == V_ASN1_SEQUENCE) + pbe = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBEPARAM)); + if (pbe == NULL) { + BIO_puts(bio_err, ", "); + goto done; + } + BIO_printf(bio_err, ", Iteration %ld", ASN1_INTEGER_get(pbe->iter)); + PBEPARAM_free(pbe); + } + done: + BIO_puts(bio_err, "\n"); + return 1; +} + +/* Load all certificates from a given file */ + +int cert_load(BIO *in, STACK_OF(X509) *sk) +{ + int ret; + X509 *cert; + ret = 0; + while ((cert = PEM_read_bio_X509(in, NULL, NULL, NULL))) { + ret = 1; + sk_X509_push(sk, cert); + } + if (ret) + ERR_clear_error(); + return ret; +} + +/* Generalised attribute print: handle PKCS#8 and bag attributes */ + +int print_attribs(BIO *out, const STACK_OF(X509_ATTRIBUTE) *attrlst, + const char *name) +{ + X509_ATTRIBUTE *attr; + ASN1_TYPE *av; + char *value; + int i, attr_nid; + if (!attrlst) { + BIO_printf(out, "%s: \n", name); + return 1; + } + if (!sk_X509_ATTRIBUTE_num(attrlst)) { + BIO_printf(out, "%s: \n", name); + return 1; + } + BIO_printf(out, "%s\n", name); + for (i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) { + ASN1_OBJECT *attr_obj; + attr = sk_X509_ATTRIBUTE_value(attrlst, i); + attr_obj = X509_ATTRIBUTE_get0_object(attr); + attr_nid = OBJ_obj2nid(attr_obj); + BIO_printf(out, " "); + if (attr_nid == NID_undef) { + i2a_ASN1_OBJECT(out, attr_obj); + BIO_printf(out, ": "); + } else { + BIO_printf(out, "%s: ", OBJ_nid2ln(attr_nid)); + } + + if (X509_ATTRIBUTE_count(attr)) { + av = X509_ATTRIBUTE_get0_type(attr, 0); + switch (av->type) { + case V_ASN1_BMPSTRING: + value = OPENSSL_uni2asc(av->value.bmpstring->data, + av->value.bmpstring->length); + BIO_printf(out, "%s\n", value); + OPENSSL_free(value); + break; + + case V_ASN1_OCTET_STRING: + hex_prin(out, av->value.octet_string->data, + av->value.octet_string->length); + BIO_printf(out, "\n"); + break; + + case V_ASN1_BIT_STRING: + hex_prin(out, av->value.bit_string->data, + av->value.bit_string->length); + BIO_printf(out, "\n"); + break; + + default: + BIO_printf(out, "\n", av->type); + break; + } + } else { + BIO_printf(out, "\n"); + } + } + return 1; +} + +void hex_prin(BIO *out, unsigned char *buf, int len) +{ + int i; + for (i = 0; i < len; i++) + BIO_printf(out, "%02X ", buf[i]); +} + +static int set_pbe(int *ppbe, const char *str) +{ + if (!str) + return 0; + if (strcmp(str, "NONE") == 0) { + *ppbe = -1; + return 1; + } + *ppbe = OBJ_txt2nid(str); + if (*ppbe == NID_undef) { + BIO_printf(bio_err, "Unknown PBE algorithm %s\n", str); + return 0; + } + return 1; +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/pkcs7.c b/trunk/3rdparty/openssl-1.1-fit/apps/pkcs7.c new file mode 100644 index 000000000..c3e9f5c69 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/pkcs7.c @@ -0,0 +1,198 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include +#include +#include + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_NOOUT, + OPT_TEXT, OPT_PRINT, OPT_PRINT_CERTS, OPT_ENGINE +} OPTION_CHOICE; + +const OPTIONS pkcs7_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"}, + {"in", OPT_IN, '<', "Input file"}, + {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"}, + {"out", OPT_OUT, '>', "Output file"}, + {"noout", OPT_NOOUT, '-', "Don't output encoded data"}, + {"text", OPT_TEXT, '-', "Print full details of certificates"}, + {"print", OPT_PRINT, '-', "Print out all fields of the PKCS7 structure"}, + {"print_certs", OPT_PRINT_CERTS, '-', + "Print_certs print any certs or crl in the input"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + {NULL} +}; + +int pkcs7_main(int argc, char **argv) +{ + ENGINE *e = NULL; + PKCS7 *p7 = NULL; + BIO *in = NULL, *out = NULL; + int informat = FORMAT_PEM, outformat = FORMAT_PEM; + char *infile = NULL, *outfile = NULL, *prog; + int i, print_certs = 0, text = 0, noout = 0, p7_print = 0, ret = 1; + OPTION_CHOICE o; + + prog = opt_init(argc, argv, pkcs7_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(pkcs7_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) + goto opthelp; + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_NOOUT: + noout = 1; + break; + case OPT_TEXT: + text = 1; + break; + case OPT_PRINT: + p7_print = 1; + break; + case OPT_PRINT_CERTS: + print_certs = 1; + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + } + } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + + in = bio_open_default(infile, 'r', informat); + if (in == NULL) + goto end; + + if (informat == FORMAT_ASN1) + p7 = d2i_PKCS7_bio(in, NULL); + else + p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL); + if (p7 == NULL) { + BIO_printf(bio_err, "unable to load PKCS7 object\n"); + ERR_print_errors(bio_err); + goto end; + } + + out = bio_open_default(outfile, 'w', outformat); + if (out == NULL) + goto end; + + if (p7_print) + PKCS7_print_ctx(out, p7, 0, NULL); + + if (print_certs) { + STACK_OF(X509) *certs = NULL; + STACK_OF(X509_CRL) *crls = NULL; + + i = OBJ_obj2nid(p7->type); + switch (i) { + case NID_pkcs7_signed: + if (p7->d.sign != NULL) { + certs = p7->d.sign->cert; + crls = p7->d.sign->crl; + } + break; + case NID_pkcs7_signedAndEnveloped: + if (p7->d.signed_and_enveloped != NULL) { + certs = p7->d.signed_and_enveloped->cert; + crls = p7->d.signed_and_enveloped->crl; + } + break; + default: + break; + } + + if (certs != NULL) { + X509 *x; + + for (i = 0; i < sk_X509_num(certs); i++) { + x = sk_X509_value(certs, i); + if (text) + X509_print(out, x); + else + dump_cert_text(out, x); + + if (!noout) + PEM_write_bio_X509(out, x); + BIO_puts(out, "\n"); + } + } + if (crls != NULL) { + X509_CRL *crl; + + for (i = 0; i < sk_X509_CRL_num(crls); i++) { + crl = sk_X509_CRL_value(crls, i); + + X509_CRL_print_ex(out, crl, get_nameopt()); + + if (!noout) + PEM_write_bio_X509_CRL(out, crl); + BIO_puts(out, "\n"); + } + } + + ret = 0; + goto end; + } + + if (!noout) { + if (outformat == FORMAT_ASN1) + i = i2d_PKCS7_bio(out, p7); + else + i = PEM_write_bio_PKCS7(out, p7); + + if (!i) { + BIO_printf(bio_err, "unable to write pkcs7 object\n"); + ERR_print_errors(bio_err); + goto end; + } + } + ret = 0; + end: + PKCS7_free(p7); + release_engine(e); + BIO_free(in); + BIO_free_all(out); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/pkcs8.c b/trunk/3rdparty/openssl-1.1-fit/apps/pkcs8.c new file mode 100644 index 000000000..205536560 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/pkcs8.c @@ -0,0 +1,359 @@ +/* + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_IN, OPT_OUT, + OPT_TOPK8, OPT_NOITER, OPT_NOCRYPT, +#ifndef OPENSSL_NO_SCRYPT + OPT_SCRYPT, OPT_SCRYPT_N, OPT_SCRYPT_R, OPT_SCRYPT_P, +#endif + OPT_V2, OPT_V1, OPT_V2PRF, OPT_ITER, OPT_PASSIN, OPT_PASSOUT, + OPT_TRADITIONAL, + OPT_R_ENUM +} OPTION_CHOICE; + +const OPTIONS pkcs8_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"inform", OPT_INFORM, 'F', "Input format (DER or PEM)"}, + {"outform", OPT_OUTFORM, 'F', "Output format (DER or PEM)"}, + {"in", OPT_IN, '<', "Input file"}, + {"out", OPT_OUT, '>', "Output file"}, + {"topk8", OPT_TOPK8, '-', "Output PKCS8 file"}, + {"noiter", OPT_NOITER, '-', "Use 1 as iteration count"}, + {"nocrypt", OPT_NOCRYPT, '-', "Use or expect unencrypted private key"}, + OPT_R_OPTIONS, + {"v2", OPT_V2, 's', "Use PKCS#5 v2.0 and cipher"}, + {"v1", OPT_V1, 's', "Use PKCS#5 v1.5 and cipher"}, + {"v2prf", OPT_V2PRF, 's', "Set the PRF algorithm to use with PKCS#5 v2.0"}, + {"iter", OPT_ITER, 'p', "Specify the iteration count"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, + {"traditional", OPT_TRADITIONAL, '-', "use traditional format private key"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif +#ifndef OPENSSL_NO_SCRYPT + {"scrypt", OPT_SCRYPT, '-', "Use scrypt algorithm"}, + {"scrypt_N", OPT_SCRYPT_N, 's', "Set scrypt N parameter"}, + {"scrypt_r", OPT_SCRYPT_R, 's', "Set scrypt r parameter"}, + {"scrypt_p", OPT_SCRYPT_P, 's', "Set scrypt p parameter"}, +#endif + {NULL} +}; + +int pkcs8_main(int argc, char **argv) +{ + BIO *in = NULL, *out = NULL; + ENGINE *e = NULL; + EVP_PKEY *pkey = NULL; + PKCS8_PRIV_KEY_INFO *p8inf = NULL; + X509_SIG *p8 = NULL; + const EVP_CIPHER *cipher = NULL; + char *infile = NULL, *outfile = NULL; + char *passinarg = NULL, *passoutarg = NULL, *prog; +#ifndef OPENSSL_NO_UI_CONSOLE + char pass[APP_PASS_LEN]; +#endif + char *passin = NULL, *passout = NULL, *p8pass = NULL; + OPTION_CHOICE o; + int nocrypt = 0, ret = 1, iter = PKCS12_DEFAULT_ITER; + int informat = FORMAT_PEM, outformat = FORMAT_PEM, topk8 = 0, pbe_nid = -1; + int private = 0, traditional = 0; +#ifndef OPENSSL_NO_SCRYPT + long scrypt_N = 0, scrypt_r = 0, scrypt_p = 0; +#endif + + prog = opt_init(argc, argv, pkcs8_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(pkcs8_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) + goto opthelp; + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_TOPK8: + topk8 = 1; + break; + case OPT_NOITER: + iter = 1; + break; + case OPT_NOCRYPT: + nocrypt = 1; + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_TRADITIONAL: + traditional = 1; + break; + case OPT_V2: + if (!opt_cipher(opt_arg(), &cipher)) + goto opthelp; + break; + case OPT_V1: + pbe_nid = OBJ_txt2nid(opt_arg()); + if (pbe_nid == NID_undef) { + BIO_printf(bio_err, + "%s: Unknown PBE algorithm %s\n", prog, opt_arg()); + goto opthelp; + } + break; + case OPT_V2PRF: + pbe_nid = OBJ_txt2nid(opt_arg()); + if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, pbe_nid, NULL, NULL, 0)) { + BIO_printf(bio_err, + "%s: Unknown PRF algorithm %s\n", prog, opt_arg()); + goto opthelp; + } + if (cipher == NULL) + cipher = EVP_aes_256_cbc(); + break; + case OPT_ITER: + if (!opt_int(opt_arg(), &iter)) + goto opthelp; + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_PASSOUT: + passoutarg = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; +#ifndef OPENSSL_NO_SCRYPT + case OPT_SCRYPT: + scrypt_N = 16384; + scrypt_r = 8; + scrypt_p = 1; + if (cipher == NULL) + cipher = EVP_aes_256_cbc(); + break; + case OPT_SCRYPT_N: + if (!opt_long(opt_arg(), &scrypt_N) || scrypt_N <= 0) + goto opthelp; + break; + case OPT_SCRYPT_R: + if (!opt_long(opt_arg(), &scrypt_r) || scrypt_r <= 0) + goto opthelp; + break; + case OPT_SCRYPT_P: + if (!opt_long(opt_arg(), &scrypt_p) || scrypt_p <= 0) + goto opthelp; + break; +#endif + } + } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + + private = 1; + + if (!app_passwd(passinarg, passoutarg, &passin, &passout)) { + BIO_printf(bio_err, "Error getting passwords\n"); + goto end; + } + + if ((pbe_nid == -1) && cipher == NULL) + cipher = EVP_aes_256_cbc(); + + in = bio_open_default(infile, 'r', informat); + if (in == NULL) + goto end; + out = bio_open_owner(outfile, outformat, private); + if (out == NULL) + goto end; + + if (topk8) { + pkey = load_key(infile, informat, 1, passin, e, "key"); + if (pkey == NULL) + goto end; + if ((p8inf = EVP_PKEY2PKCS8(pkey)) == NULL) { + BIO_printf(bio_err, "Error converting key\n"); + ERR_print_errors(bio_err); + goto end; + } + if (nocrypt) { + assert(private); + if (outformat == FORMAT_PEM) { + PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8inf); + } else if (outformat == FORMAT_ASN1) { + i2d_PKCS8_PRIV_KEY_INFO_bio(out, p8inf); + } else { + BIO_printf(bio_err, "Bad format specified for key\n"); + goto end; + } + } else { + X509_ALGOR *pbe; + if (cipher) { +#ifndef OPENSSL_NO_SCRYPT + if (scrypt_N && scrypt_r && scrypt_p) + pbe = PKCS5_pbe2_set_scrypt(cipher, NULL, 0, NULL, + scrypt_N, scrypt_r, scrypt_p); + else +#endif + pbe = PKCS5_pbe2_set_iv(cipher, iter, NULL, 0, NULL, + pbe_nid); + } else { + pbe = PKCS5_pbe_set(pbe_nid, iter, NULL, 0); + } + if (pbe == NULL) { + BIO_printf(bio_err, "Error setting PBE algorithm\n"); + ERR_print_errors(bio_err); + goto end; + } + if (passout != NULL) { + p8pass = passout; + } else if (1) { + /* To avoid bit rot */ +#ifndef OPENSSL_NO_UI_CONSOLE + p8pass = pass; + if (EVP_read_pw_string + (pass, sizeof(pass), "Enter Encryption Password:", 1)) { + X509_ALGOR_free(pbe); + goto end; + } + } else { +#endif + BIO_printf(bio_err, "Password required\n"); + goto end; + } + p8 = PKCS8_set0_pbe(p8pass, strlen(p8pass), p8inf, pbe); + if (p8 == NULL) { + X509_ALGOR_free(pbe); + BIO_printf(bio_err, "Error encrypting key\n"); + ERR_print_errors(bio_err); + goto end; + } + assert(private); + if (outformat == FORMAT_PEM) + PEM_write_bio_PKCS8(out, p8); + else if (outformat == FORMAT_ASN1) + i2d_PKCS8_bio(out, p8); + else { + BIO_printf(bio_err, "Bad format specified for key\n"); + goto end; + } + } + + ret = 0; + goto end; + } + + if (nocrypt) { + if (informat == FORMAT_PEM) { + p8inf = PEM_read_bio_PKCS8_PRIV_KEY_INFO(in, NULL, NULL, NULL); + } else if (informat == FORMAT_ASN1) { + p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(in, NULL); + } else { + BIO_printf(bio_err, "Bad format specified for key\n"); + goto end; + } + } else { + if (informat == FORMAT_PEM) { + p8 = PEM_read_bio_PKCS8(in, NULL, NULL, NULL); + } else if (informat == FORMAT_ASN1) { + p8 = d2i_PKCS8_bio(in, NULL); + } else { + BIO_printf(bio_err, "Bad format specified for key\n"); + goto end; + } + + if (p8 == NULL) { + BIO_printf(bio_err, "Error reading key\n"); + ERR_print_errors(bio_err); + goto end; + } + if (passin != NULL) { + p8pass = passin; + } else if (1) { +#ifndef OPENSSL_NO_UI_CONSOLE + p8pass = pass; + if (EVP_read_pw_string(pass, sizeof(pass), "Enter Password:", 0)) { + BIO_printf(bio_err, "Can't read Password\n"); + goto end; + } + } else { +#endif + BIO_printf(bio_err, "Password required\n"); + goto end; + } + p8inf = PKCS8_decrypt(p8, p8pass, strlen(p8pass)); + } + + if (p8inf == NULL) { + BIO_printf(bio_err, "Error decrypting key\n"); + ERR_print_errors(bio_err); + goto end; + } + + if ((pkey = EVP_PKCS82PKEY(p8inf)) == NULL) { + BIO_printf(bio_err, "Error converting key\n"); + ERR_print_errors(bio_err); + goto end; + } + + assert(private); + if (outformat == FORMAT_PEM) { + if (traditional) + PEM_write_bio_PrivateKey_traditional(out, pkey, NULL, NULL, 0, + NULL, passout); + else + PEM_write_bio_PrivateKey(out, pkey, NULL, NULL, 0, NULL, passout); + } else if (outformat == FORMAT_ASN1) { + i2d_PrivateKey_bio(out, pkey); + } else { + BIO_printf(bio_err, "Bad format specified for key\n"); + goto end; + } + ret = 0; + + end: + X509_SIG_free(p8); + PKCS8_PRIV_KEY_INFO_free(p8inf); + EVP_PKEY_free(pkey); + release_engine(e); + BIO_free_all(out); + BIO_free(in); + OPENSSL_free(passin); + OPENSSL_free(passout); + + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/pkey.c b/trunk/3rdparty/openssl-1.1-fit/apps/pkey.c new file mode 100644 index 000000000..0dd5590bd --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/pkey.c @@ -0,0 +1,243 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_OUTFORM, OPT_PASSIN, OPT_PASSOUT, OPT_ENGINE, + OPT_IN, OPT_OUT, OPT_PUBIN, OPT_PUBOUT, OPT_TEXT_PUB, + OPT_TEXT, OPT_NOOUT, OPT_MD, OPT_TRADITIONAL, OPT_CHECK, OPT_PUB_CHECK +} OPTION_CHOICE; + +const OPTIONS pkey_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"inform", OPT_INFORM, 'f', "Input format (DER or PEM)"}, + {"outform", OPT_OUTFORM, 'F', "Output format (DER or PEM)"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, + {"in", OPT_IN, 's', "Input key"}, + {"out", OPT_OUT, '>', "Output file"}, + {"pubin", OPT_PUBIN, '-', + "Read public key from input (default is private key)"}, + {"pubout", OPT_PUBOUT, '-', "Output public key, not private"}, + {"text_pub", OPT_TEXT_PUB, '-', "Only output public key components"}, + {"text", OPT_TEXT, '-', "Output in plaintext as well"}, + {"noout", OPT_NOOUT, '-', "Don't output the key"}, + {"", OPT_MD, '-', "Any supported cipher"}, + {"traditional", OPT_TRADITIONAL, '-', + "Use traditional format for private keys"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + {"check", OPT_CHECK, '-', "Check key consistency"}, + {"pubcheck", OPT_PUB_CHECK, '-', "Check public key consistency"}, + {NULL} +}; + +int pkey_main(int argc, char **argv) +{ + BIO *in = NULL, *out = NULL; + ENGINE *e = NULL; + EVP_PKEY *pkey = NULL; + const EVP_CIPHER *cipher = NULL; + char *infile = NULL, *outfile = NULL, *passin = NULL, *passout = NULL; + char *passinarg = NULL, *passoutarg = NULL, *prog; + OPTION_CHOICE o; + int informat = FORMAT_PEM, outformat = FORMAT_PEM; + int pubin = 0, pubout = 0, pubtext = 0, text = 0, noout = 0, ret = 1; + int private = 0, traditional = 0, check = 0, pub_check = 0; + + prog = opt_init(argc, argv, pkey_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(pkey_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat)) + goto opthelp; + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) + goto opthelp; + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_PASSOUT: + passoutarg = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_PUBIN: + pubin = pubout = pubtext = 1; + break; + case OPT_PUBOUT: + pubout = 1; + break; + case OPT_TEXT_PUB: + pubtext = text = 1; + break; + case OPT_TEXT: + text = 1; + break; + case OPT_NOOUT: + noout = 1; + break; + case OPT_TRADITIONAL: + traditional = 1; + break; + case OPT_CHECK: + check = 1; + break; + case OPT_PUB_CHECK: + pub_check = 1; + break; + case OPT_MD: + if (!opt_cipher(opt_unknown(), &cipher)) + goto opthelp; + } + } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + + private = !noout && !pubout ? 1 : 0; + if (text && !pubtext) + private = 1; + + if (!app_passwd(passinarg, passoutarg, &passin, &passout)) { + BIO_printf(bio_err, "Error getting passwords\n"); + goto end; + } + + out = bio_open_owner(outfile, outformat, private); + if (out == NULL) + goto end; + + if (pubin) + pkey = load_pubkey(infile, informat, 1, passin, e, "Public Key"); + else + pkey = load_key(infile, informat, 1, passin, e, "key"); + if (pkey == NULL) + goto end; + + if (check || pub_check) { + int r; + EVP_PKEY_CTX *ctx; + + ctx = EVP_PKEY_CTX_new(pkey, e); + if (ctx == NULL) { + ERR_print_errors(bio_err); + goto end; + } + + if (check) + r = EVP_PKEY_check(ctx); + else + r = EVP_PKEY_public_check(ctx); + + if (r == 1) { + BIO_printf(out, "Key is valid\n"); + } else { + /* + * Note: at least for RSA keys if this function returns + * -1, there will be no error reasons. + */ + unsigned long err; + + BIO_printf(out, "Key is invalid\n"); + + while ((err = ERR_peek_error()) != 0) { + BIO_printf(out, "Detailed error: %s\n", + ERR_reason_error_string(err)); + ERR_get_error(); /* remove err from error stack */ + } + } + EVP_PKEY_CTX_free(ctx); + } + + if (!noout) { + if (outformat == FORMAT_PEM) { + if (pubout) { + if (!PEM_write_bio_PUBKEY(out, pkey)) + goto end; + } else { + assert(private); + if (traditional) { + if (!PEM_write_bio_PrivateKey_traditional(out, pkey, cipher, + NULL, 0, NULL, + passout)) + goto end; + } else { + if (!PEM_write_bio_PrivateKey(out, pkey, cipher, + NULL, 0, NULL, passout)) + goto end; + } + } + } else if (outformat == FORMAT_ASN1) { + if (pubout) { + if (!i2d_PUBKEY_bio(out, pkey)) + goto end; + } else { + assert(private); + if (!i2d_PrivateKey_bio(out, pkey)) + goto end; + } + } else { + BIO_printf(bio_err, "Bad format specified for key\n"); + goto end; + } + } + + if (text) { + if (pubtext) { + if (EVP_PKEY_print_public(out, pkey, 0, NULL) <= 0) + goto end; + } else { + assert(private); + if (EVP_PKEY_print_private(out, pkey, 0, NULL) <= 0) + goto end; + } + } + + ret = 0; + + end: + if (ret != 0) + ERR_print_errors(bio_err); + EVP_PKEY_free(pkey); + release_engine(e); + BIO_free_all(out); + BIO_free(in); + OPENSSL_free(passin); + OPENSSL_free(passout); + + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/pkeyparam.c b/trunk/3rdparty/openssl-1.1-fit/apps/pkeyparam.c new file mode 100644 index 000000000..41c3f532b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/pkeyparam.c @@ -0,0 +1,142 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_IN, OPT_OUT, OPT_TEXT, OPT_NOOUT, + OPT_ENGINE, OPT_CHECK +} OPTION_CHOICE; + +const OPTIONS pkeyparam_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"in", OPT_IN, '<', "Input file"}, + {"out", OPT_OUT, '>', "Output file"}, + {"text", OPT_TEXT, '-', "Print parameters as text"}, + {"noout", OPT_NOOUT, '-', "Don't output encoded parameters"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + {"check", OPT_CHECK, '-', "Check key param consistency"}, + {NULL} +}; + +int pkeyparam_main(int argc, char **argv) +{ + ENGINE *e = NULL; + BIO *in = NULL, *out = NULL; + EVP_PKEY *pkey = NULL; + int text = 0, noout = 0, ret = 1, check = 0; + OPTION_CHOICE o; + char *infile = NULL, *outfile = NULL, *prog; + + prog = opt_init(argc, argv, pkeyparam_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(pkeyparam_options); + ret = 0; + goto end; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_TEXT: + text = 1; + break; + case OPT_NOOUT: + noout = 1; + break; + case OPT_CHECK: + check = 1; + break; + } + } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + + in = bio_open_default(infile, 'r', FORMAT_PEM); + if (in == NULL) + goto end; + out = bio_open_default(outfile, 'w', FORMAT_PEM); + if (out == NULL) + goto end; + pkey = PEM_read_bio_Parameters(in, NULL); + if (pkey == NULL) { + BIO_printf(bio_err, "Error reading parameters\n"); + ERR_print_errors(bio_err); + goto end; + } + + if (check) { + int r; + EVP_PKEY_CTX *ctx; + + ctx = EVP_PKEY_CTX_new(pkey, e); + if (ctx == NULL) { + ERR_print_errors(bio_err); + goto end; + } + + r = EVP_PKEY_param_check(ctx); + + if (r == 1) { + BIO_printf(out, "Parameters are valid\n"); + } else { + /* + * Note: at least for RSA keys if this function returns + * -1, there will be no error reasons. + */ + unsigned long err; + + BIO_printf(out, "Parameters are invalid\n"); + + while ((err = ERR_peek_error()) != 0) { + BIO_printf(out, "Detailed error: %s\n", + ERR_reason_error_string(err)); + ERR_get_error(); /* remove err from error stack */ + } + } + EVP_PKEY_CTX_free(ctx); + } + + if (!noout) + PEM_write_bio_Parameters(out, pkey); + + if (text) + EVP_PKEY_print_params(out, pkey, 0, NULL); + + ret = 0; + + end: + EVP_PKEY_free(pkey); + release_engine(e); + BIO_free_all(out); + BIO_free(in); + + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/pkeyutl.c b/trunk/3rdparty/openssl-1.1-fit/apps/pkeyutl.c new file mode 100644 index 000000000..2c4e524b6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/pkeyutl.c @@ -0,0 +1,525 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include + +#define KEY_NONE 0 +#define KEY_PRIVKEY 1 +#define KEY_PUBKEY 2 +#define KEY_CERT 3 + +static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize, + const char *keyfile, int keyform, int key_type, + char *passinarg, int pkey_op, ENGINE *e, + const int impl); + +static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file, + ENGINE *e); + +static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op, + unsigned char *out, size_t *poutlen, + const unsigned char *in, size_t inlen); + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_ENGINE, OPT_ENGINE_IMPL, OPT_IN, OPT_OUT, + OPT_PUBIN, OPT_CERTIN, OPT_ASN1PARSE, OPT_HEXDUMP, OPT_SIGN, + OPT_VERIFY, OPT_VERIFYRECOVER, OPT_REV, OPT_ENCRYPT, OPT_DECRYPT, + OPT_DERIVE, OPT_SIGFILE, OPT_INKEY, OPT_PEERKEY, OPT_PASSIN, + OPT_PEERFORM, OPT_KEYFORM, OPT_PKEYOPT, OPT_KDF, OPT_KDFLEN, + OPT_R_ENUM +} OPTION_CHOICE; + +const OPTIONS pkeyutl_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"in", OPT_IN, '<', "Input file - default stdin"}, + {"out", OPT_OUT, '>', "Output file - default stdout"}, + {"pubin", OPT_PUBIN, '-', "Input is a public key"}, + {"certin", OPT_CERTIN, '-', "Input is a cert with a public key"}, + {"asn1parse", OPT_ASN1PARSE, '-', "asn1parse the output data"}, + {"hexdump", OPT_HEXDUMP, '-', "Hex dump output"}, + {"sign", OPT_SIGN, '-', "Sign input data with private key"}, + {"verify", OPT_VERIFY, '-', "Verify with public key"}, + {"verifyrecover", OPT_VERIFYRECOVER, '-', + "Verify with public key, recover original data"}, + {"rev", OPT_REV, '-', "Reverse the order of the input buffer"}, + {"encrypt", OPT_ENCRYPT, '-', "Encrypt input data with public key"}, + {"decrypt", OPT_DECRYPT, '-', "Decrypt input data with private key"}, + {"derive", OPT_DERIVE, '-', "Derive shared secret"}, + {"kdf", OPT_KDF, 's', "Use KDF algorithm"}, + {"kdflen", OPT_KDFLEN, 'p', "KDF algorithm output length"}, + {"sigfile", OPT_SIGFILE, '<', "Signature file (verify operation only)"}, + {"inkey", OPT_INKEY, 's', "Input private key file"}, + {"peerkey", OPT_PEERKEY, 's', "Peer key file used in key derivation"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"peerform", OPT_PEERFORM, 'E', "Peer key format - default PEM"}, + {"keyform", OPT_KEYFORM, 'E', "Private key format - default PEM"}, + {"pkeyopt", OPT_PKEYOPT, 's', "Public key options as opt:value"}, + OPT_R_OPTIONS, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, + {"engine_impl", OPT_ENGINE_IMPL, '-', + "Also use engine given by -engine for crypto operations"}, +#endif + {NULL} +}; + +int pkeyutl_main(int argc, char **argv) +{ + BIO *in = NULL, *out = NULL; + ENGINE *e = NULL; + EVP_PKEY_CTX *ctx = NULL; + char *infile = NULL, *outfile = NULL, *sigfile = NULL, *passinarg = NULL; + char hexdump = 0, asn1parse = 0, rev = 0, *prog; + unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL; + OPTION_CHOICE o; + int buf_inlen = 0, siglen = -1, keyform = FORMAT_PEM, peerform = FORMAT_PEM; + int keysize = -1, pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY; + int engine_impl = 0; + int ret = 1, rv = -1; + size_t buf_outlen; + const char *inkey = NULL; + const char *peerkey = NULL; + const char *kdfalg = NULL; + int kdflen = 0; + STACK_OF(OPENSSL_STRING) *pkeyopts = NULL; + + prog = opt_init(argc, argv, pkeyutl_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(pkeyutl_options); + ret = 0; + goto end; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_SIGFILE: + sigfile = opt_arg(); + break; + case OPT_ENGINE_IMPL: + engine_impl = 1; + break; + case OPT_INKEY: + inkey = opt_arg(); + break; + case OPT_PEERKEY: + peerkey = opt_arg(); + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_PEERFORM: + if (!opt_format(opt_arg(), OPT_FMT_PDE, &peerform)) + goto opthelp; + break; + case OPT_KEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_PDE, &keyform)) + goto opthelp; + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_PUBIN: + key_type = KEY_PUBKEY; + break; + case OPT_CERTIN: + key_type = KEY_CERT; + break; + case OPT_ASN1PARSE: + asn1parse = 1; + break; + case OPT_HEXDUMP: + hexdump = 1; + break; + case OPT_SIGN: + pkey_op = EVP_PKEY_OP_SIGN; + break; + case OPT_VERIFY: + pkey_op = EVP_PKEY_OP_VERIFY; + break; + case OPT_VERIFYRECOVER: + pkey_op = EVP_PKEY_OP_VERIFYRECOVER; + break; + case OPT_ENCRYPT: + pkey_op = EVP_PKEY_OP_ENCRYPT; + break; + case OPT_DECRYPT: + pkey_op = EVP_PKEY_OP_DECRYPT; + break; + case OPT_DERIVE: + pkey_op = EVP_PKEY_OP_DERIVE; + break; + case OPT_KDF: + pkey_op = EVP_PKEY_OP_DERIVE; + key_type = KEY_NONE; + kdfalg = opt_arg(); + break; + case OPT_KDFLEN: + kdflen = atoi(opt_arg()); + break; + case OPT_REV: + rev = 1; + break; + case OPT_PKEYOPT: + if ((pkeyopts == NULL && + (pkeyopts = sk_OPENSSL_STRING_new_null()) == NULL) || + sk_OPENSSL_STRING_push(pkeyopts, opt_arg()) == 0) { + BIO_puts(bio_err, "out of memory\n"); + goto end; + } + break; + } + } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + + if (kdfalg != NULL) { + if (kdflen == 0) { + BIO_printf(bio_err, + "%s: no KDF length given (-kdflen parameter).\n", prog); + goto opthelp; + } + } else if (inkey == NULL) { + BIO_printf(bio_err, + "%s: no private key given (-inkey parameter).\n", prog); + goto opthelp; + } else if (peerkey != NULL && pkey_op != EVP_PKEY_OP_DERIVE) { + BIO_printf(bio_err, + "%s: no peer key given (-peerkey parameter).\n", prog); + goto opthelp; + } + ctx = init_ctx(kdfalg, &keysize, inkey, keyform, key_type, + passinarg, pkey_op, e, engine_impl); + if (ctx == NULL) { + BIO_printf(bio_err, "%s: Error initializing context\n", prog); + ERR_print_errors(bio_err); + goto end; + } + if (peerkey != NULL && !setup_peer(ctx, peerform, peerkey, e)) { + BIO_printf(bio_err, "%s: Error setting up peer key\n", prog); + ERR_print_errors(bio_err); + goto end; + } + if (pkeyopts != NULL) { + int num = sk_OPENSSL_STRING_num(pkeyopts); + int i; + + for (i = 0; i < num; ++i) { + const char *opt = sk_OPENSSL_STRING_value(pkeyopts, i); + + if (pkey_ctrl_string(ctx, opt) <= 0) { + BIO_printf(bio_err, "%s: Can't set parameter \"%s\":\n", + prog, opt); + ERR_print_errors(bio_err); + goto end; + } + } + } + + if (sigfile != NULL && (pkey_op != EVP_PKEY_OP_VERIFY)) { + BIO_printf(bio_err, + "%s: Signature file specified for non verify\n", prog); + goto end; + } + + if (sigfile == NULL && (pkey_op == EVP_PKEY_OP_VERIFY)) { + BIO_printf(bio_err, + "%s: No signature file specified for verify\n", prog); + goto end; + } + + if (pkey_op != EVP_PKEY_OP_DERIVE) { + in = bio_open_default(infile, 'r', FORMAT_BINARY); + if (in == NULL) + goto end; + } + out = bio_open_default(outfile, 'w', FORMAT_BINARY); + if (out == NULL) + goto end; + + if (sigfile != NULL) { + BIO *sigbio = BIO_new_file(sigfile, "rb"); + + if (sigbio == NULL) { + BIO_printf(bio_err, "Can't open signature file %s\n", sigfile); + goto end; + } + siglen = bio_to_mem(&sig, keysize * 10, sigbio); + BIO_free(sigbio); + if (siglen < 0) { + BIO_printf(bio_err, "Error reading signature data\n"); + goto end; + } + } + + if (in != NULL) { + /* Read the input data */ + buf_inlen = bio_to_mem(&buf_in, keysize * 10, in); + if (buf_inlen < 0) { + BIO_printf(bio_err, "Error reading input Data\n"); + goto end; + } + if (rev) { + size_t i; + unsigned char ctmp; + size_t l = (size_t)buf_inlen; + for (i = 0; i < l / 2; i++) { + ctmp = buf_in[i]; + buf_in[i] = buf_in[l - 1 - i]; + buf_in[l - 1 - i] = ctmp; + } + } + } + + /* Sanity check the input */ + if (buf_inlen > EVP_MAX_MD_SIZE + && (pkey_op == EVP_PKEY_OP_SIGN + || pkey_op == EVP_PKEY_OP_VERIFY + || pkey_op == EVP_PKEY_OP_VERIFYRECOVER)) { + BIO_printf(bio_err, + "Error: The input data looks too long to be a hash\n"); + goto end; + } + + if (pkey_op == EVP_PKEY_OP_VERIFY) { + rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen, + buf_in, (size_t)buf_inlen); + if (rv == 1) { + BIO_puts(out, "Signature Verified Successfully\n"); + ret = 0; + } else { + BIO_puts(out, "Signature Verification Failure\n"); + } + goto end; + } + if (kdflen != 0) { + buf_outlen = kdflen; + rv = 1; + } else { + rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen, + buf_in, (size_t)buf_inlen); + } + if (rv > 0 && buf_outlen != 0) { + buf_out = app_malloc(buf_outlen, "buffer output"); + rv = do_keyop(ctx, pkey_op, + buf_out, (size_t *)&buf_outlen, + buf_in, (size_t)buf_inlen); + } + if (rv <= 0) { + if (pkey_op != EVP_PKEY_OP_DERIVE) { + BIO_puts(bio_err, "Public Key operation error\n"); + } else { + BIO_puts(bio_err, "Key derivation failed\n"); + } + ERR_print_errors(bio_err); + goto end; + } + ret = 0; + + if (asn1parse) { + if (!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1)) + ERR_print_errors(bio_err); + } else if (hexdump) { + BIO_dump(out, (char *)buf_out, buf_outlen); + } else { + BIO_write(out, buf_out, buf_outlen); + } + + end: + EVP_PKEY_CTX_free(ctx); + release_engine(e); + BIO_free(in); + BIO_free_all(out); + OPENSSL_free(buf_in); + OPENSSL_free(buf_out); + OPENSSL_free(sig); + sk_OPENSSL_STRING_free(pkeyopts); + return ret; +} + +static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize, + const char *keyfile, int keyform, int key_type, + char *passinarg, int pkey_op, ENGINE *e, + const int engine_impl) +{ + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *ctx = NULL; + ENGINE *impl = NULL; + char *passin = NULL; + int rv = -1; + X509 *x; + if (((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT) + || (pkey_op == EVP_PKEY_OP_DERIVE)) + && (key_type != KEY_PRIVKEY && kdfalg == NULL)) { + BIO_printf(bio_err, "A private key is needed for this operation\n"); + goto end; + } + if (!app_passwd(passinarg, NULL, &passin, NULL)) { + BIO_printf(bio_err, "Error getting password\n"); + goto end; + } + switch (key_type) { + case KEY_PRIVKEY: + pkey = load_key(keyfile, keyform, 0, passin, e, "Private Key"); + break; + + case KEY_PUBKEY: + pkey = load_pubkey(keyfile, keyform, 0, NULL, e, "Public Key"); + break; + + case KEY_CERT: + x = load_cert(keyfile, keyform, "Certificate"); + if (x) { + pkey = X509_get_pubkey(x); + X509_free(x); + } + break; + + case KEY_NONE: + break; + + } + +#ifndef OPENSSL_NO_ENGINE + if (engine_impl) + impl = e; +#endif + + if (kdfalg != NULL) { + int kdfnid = OBJ_sn2nid(kdfalg); + + if (kdfnid == NID_undef) { + kdfnid = OBJ_ln2nid(kdfalg); + if (kdfnid == NID_undef) { + BIO_printf(bio_err, "The given KDF \"%s\" is unknown.\n", + kdfalg); + goto end; + } + } + ctx = EVP_PKEY_CTX_new_id(kdfnid, impl); + } else { + if (pkey == NULL) + goto end; + *pkeysize = EVP_PKEY_size(pkey); + ctx = EVP_PKEY_CTX_new(pkey, impl); + EVP_PKEY_free(pkey); + } + + if (ctx == NULL) + goto end; + + switch (pkey_op) { + case EVP_PKEY_OP_SIGN: + rv = EVP_PKEY_sign_init(ctx); + break; + + case EVP_PKEY_OP_VERIFY: + rv = EVP_PKEY_verify_init(ctx); + break; + + case EVP_PKEY_OP_VERIFYRECOVER: + rv = EVP_PKEY_verify_recover_init(ctx); + break; + + case EVP_PKEY_OP_ENCRYPT: + rv = EVP_PKEY_encrypt_init(ctx); + break; + + case EVP_PKEY_OP_DECRYPT: + rv = EVP_PKEY_decrypt_init(ctx); + break; + + case EVP_PKEY_OP_DERIVE: + rv = EVP_PKEY_derive_init(ctx); + break; + } + + if (rv <= 0) { + EVP_PKEY_CTX_free(ctx); + ctx = NULL; + } + + end: + OPENSSL_free(passin); + return ctx; + +} + +static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file, + ENGINE *e) +{ + EVP_PKEY *peer = NULL; + ENGINE *engine = NULL; + int ret; + + if (peerform == FORMAT_ENGINE) + engine = e; + peer = load_pubkey(file, peerform, 0, NULL, engine, "Peer Key"); + if (peer == NULL) { + BIO_printf(bio_err, "Error reading peer key %s\n", file); + ERR_print_errors(bio_err); + return 0; + } + + ret = EVP_PKEY_derive_set_peer(ctx, peer); + + EVP_PKEY_free(peer); + if (ret <= 0) + ERR_print_errors(bio_err); + return ret; +} + +static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op, + unsigned char *out, size_t *poutlen, + const unsigned char *in, size_t inlen) +{ + int rv = 0; + switch (pkey_op) { + case EVP_PKEY_OP_VERIFYRECOVER: + rv = EVP_PKEY_verify_recover(ctx, out, poutlen, in, inlen); + break; + + case EVP_PKEY_OP_SIGN: + rv = EVP_PKEY_sign(ctx, out, poutlen, in, inlen); + break; + + case EVP_PKEY_OP_ENCRYPT: + rv = EVP_PKEY_encrypt(ctx, out, poutlen, in, inlen); + break; + + case EVP_PKEY_OP_DECRYPT: + rv = EVP_PKEY_decrypt(ctx, out, poutlen, in, inlen); + break; + + case EVP_PKEY_OP_DERIVE: + rv = EVP_PKEY_derive(ctx, out, poutlen); + break; + + } + return rv; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/prime.c b/trunk/3rdparty/openssl-1.1-fit/apps/prime.c new file mode 100644 index 000000000..694479764 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/prime.c @@ -0,0 +1,133 @@ +/* + * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#include "apps.h" +#include "progs.h" +#include + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_HEX, OPT_GENERATE, OPT_BITS, OPT_SAFE, OPT_CHECKS +} OPTION_CHOICE; + +const OPTIONS prime_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] [number...]\n"}, + {OPT_HELP_STR, 1, '-', + " number Number to check for primality\n"}, + {"help", OPT_HELP, '-', "Display this summary"}, + {"hex", OPT_HEX, '-', "Hex output"}, + {"generate", OPT_GENERATE, '-', "Generate a prime"}, + {"bits", OPT_BITS, 'p', "Size of number in bits"}, + {"safe", OPT_SAFE, '-', + "When used with -generate, generate a safe prime"}, + {"checks", OPT_CHECKS, 'p', "Number of checks"}, + {NULL} +}; + +int prime_main(int argc, char **argv) +{ + BIGNUM *bn = NULL; + int hex = 0, checks = 20, generate = 0, bits = 0, safe = 0, ret = 1; + char *prog; + OPTION_CHOICE o; + + prog = opt_init(argc, argv, prime_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: +opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(prime_options); + ret = 0; + goto end; + case OPT_HEX: + hex = 1; + break; + case OPT_GENERATE: + generate = 1; + break; + case OPT_BITS: + bits = atoi(opt_arg()); + break; + case OPT_SAFE: + safe = 1; + break; + case OPT_CHECKS: + checks = atoi(opt_arg()); + break; + } + } + argc = opt_num_rest(); + argv = opt_rest(); + + if (generate) { + if (argc != 0) { + BIO_printf(bio_err, "Extra arguments given.\n"); + goto opthelp; + } + } else if (argc == 0) { + BIO_printf(bio_err, "%s: No prime specified\n", prog); + goto opthelp; + } + + if (generate) { + char *s; + + if (!bits) { + BIO_printf(bio_err, "Specify the number of bits.\n"); + goto end; + } + bn = BN_new(); + if (bn == NULL) { + BIO_printf(bio_err, "Out of memory.\n"); + goto end; + } + if (!BN_generate_prime_ex(bn, bits, safe, NULL, NULL, NULL)) { + BIO_printf(bio_err, "Failed to generate prime.\n"); + goto end; + } + s = hex ? BN_bn2hex(bn) : BN_bn2dec(bn); + if (s == NULL) { + BIO_printf(bio_err, "Out of memory.\n"); + goto end; + } + BIO_printf(bio_out, "%s\n", s); + OPENSSL_free(s); + } else { + for ( ; *argv; argv++) { + int r; + + if (hex) + r = BN_hex2bn(&bn, argv[0]); + else + r = BN_dec2bn(&bn, argv[0]); + + if (!r) { + BIO_printf(bio_err, "Failed to process value (%s)\n", argv[0]); + goto end; + } + + BN_print(bio_out, bn); + BIO_printf(bio_out, " (%s) %s prime\n", + argv[0], + BN_is_prime_ex(bn, checks, NULL, NULL) + ? "is" : "is not"); + } + } + + ret = 0; + end: + BN_free(bn); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/privkey.pem b/trunk/3rdparty/openssl-1.1-fit/apps/privkey.pem new file mode 100644 index 000000000..02f34981e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/privkey.pem @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMo7DFNMqywUA1O/ +qvWqCOm6rGrUAcR+dKsSXw6y2qiKO7APDDyotc0b4Mxwqjga98npex2RBIwUoCGJ +iEmMXo/a8RbXVUZ+ZwcAX7PC+XeXVC5qoajaBBkd2MvYmib/2PqnNrgvhHsUL5dO +xhC7cRqxLM/g45k3Yyw+nGa+WkTdAgMBAAECgYBMBT5w4dVG0I8foGFnz+9hzWab +Ee9IKjE5TcKmB93ilXQyjrWO5+zPmbc7ou6aAKk9IaPCTY1kCyzW7pho7Xdt+RFq +TgVXGZZfqtixO7f2/5oqZAkd00eOn9ZrhBpVMu4yXbbDvhDyFe4/oy0HGDjRUhxa +Lf6ZlBuTherxm4eFkQJBAPBQwRs9UtqaMAQlagA9pV5UsQjV1WT4IxDURMPfXgCd +ETNkB6pP0SmxQm5xhv9N2HY1UtoWpug9s0OU5IJB15sCQQDXbfbjiujNbuOxCFNw +68JZaCFVdNovyOWORkpenQLNEjVkmTCS9OayK09ADEYtsdpUGKeF+2EYBNkFr5px +CajnAkBMYI4PNz1HBuwt1SpMa0tMoMQnV7bbwVV7usskKbC5pzHZUHhzM6z5gEHp +0iEisT4Ty7zKXZqsgzefSgoaMAzzAkEAoCIaUhtwXzwdPfvNYnOs3J6doJMimECB ++lbfcyLM8TimvadtRt+KGEg/OYGmLNM2UiqdY+duzdbUpvhYGcwvYwJAQvaoi9z2 +CkiwSs/PFrLaNlfLJmXRsUBzmiWYoh6+IQJJorEXz7ewI72ee9RBO4s746cgUFwH +Ri+qO+HhZFUBqQ== +-----END PRIVATE KEY----- diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/progs.pl b/trunk/3rdparty/openssl-1.1-fit/apps/progs.pl new file mode 100644 index 000000000..57671405d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/progs.pl @@ -0,0 +1,181 @@ +#! /usr/bin/env perl +# Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# Generate progs.h file by looking for command mains in list of C files +# passed on the command line. + +use strict; +use warnings; +use lib '.'; +use configdata qw/@disablables %unified_info/; + +my %commands = (); +my $cmdre = qr/^\s*int\s+([a-z_][a-z0-9_]*)_main\(\s*int\s+argc\s*,/; +my $apps_openssl = shift @ARGV; +my $YEAR = [localtime()]->[5] + 1900; + +# because the program apps/openssl has object files as sources, and +# they then have the corresponding C files as source, we need to chain +# the lookups in %unified_info +my @openssl_source = + map { @{$unified_info{sources}->{$_}} } + grep { /\.o$/ } + @{$unified_info{sources}->{$apps_openssl}}; + +foreach my $filename (@openssl_source) { + open F, $filename or die "Couldn't open $filename: $!\n"; + foreach ( grep /$cmdre/, ) { + my @foo = /$cmdre/; + $commands{$1} = 1; + } + close F; +} + +@ARGV = sort keys %commands; + +print <<"EOF"; +/* + * WARNING: do not edit! + * Generated by apps/progs.pl + * + * Copyright 1995-$YEAR The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +typedef enum FUNC_TYPE { + FT_none, FT_general, FT_md, FT_cipher, FT_pkey, + FT_md_alg, FT_cipher_alg +} FUNC_TYPE; + +typedef struct function_st { + FUNC_TYPE type; + const char *name; + int (*func)(int argc, char *argv[]); + const OPTIONS *help; +} FUNCTION; + +DEFINE_LHASH_OF(FUNCTION); + +EOF + +foreach (@ARGV) { + printf "extern int %s_main(int argc, char *argv[]);\n", $_; +} +print "\n"; + +foreach (@ARGV) { + printf "extern const OPTIONS %s_options[];\n", $_; +} +print "\n"; + +my %cmd_disabler = ( + ciphers => "sock", + genrsa => "rsa", + rsautl => "rsa", + gendsa => "dsa", + dsaparam => "dsa", + gendh => "dh", + dhparam => "dh", + ecparam => "ec", + pkcs12 => "des", +); + +print "#ifdef INCLUDE_FUNCTION_TABLE\n"; +print "static FUNCTION functions[] = {\n"; +foreach my $cmd ( @ARGV ) { + my $str = " {FT_general, \"$cmd\", ${cmd}_main, ${cmd}_options},\n"; + if ($cmd =~ /^s_/) { + print "#ifndef OPENSSL_NO_SOCK\n${str}#endif\n"; + } elsif (grep { $cmd eq $_ } @disablables) { + print "#ifndef OPENSSL_NO_" . uc($cmd) . "\n${str}#endif\n"; + } elsif (my $disabler = $cmd_disabler{$cmd}) { + print "#ifndef OPENSSL_NO_" . uc($disabler) . "\n${str}#endif\n"; + } else { + print $str; + } +} + +my %md_disabler = ( + blake2b512 => "blake2", + blake2s256 => "blake2", +); +foreach my $cmd ( + "md2", "md4", "md5", + "gost", + "sha1", "sha224", "sha256", "sha384", + "sha512", "sha512-224", "sha512-256", + "sha3-224", "sha3-256", "sha3-384", "sha3-512", + "shake128", "shake256", + "mdc2", "rmd160", "blake2b512", "blake2s256", + "sm3" +) { + my $str = " {FT_md, \"$cmd\", dgst_main},\n"; + if (grep { $cmd eq $_ } @disablables) { + print "#ifndef OPENSSL_NO_" . uc($cmd) . "\n${str}#endif\n"; + } elsif (my $disabler = $md_disabler{$cmd}) { + print "#ifndef OPENSSL_NO_" . uc($disabler) . "\n${str}#endif\n"; + } else { + print $str; + } +} + +my %cipher_disabler = ( + des3 => "des", + desx => "des", + cast5 => "cast", +); +foreach my $cmd ( + "aes-128-cbc", "aes-128-ecb", + "aes-192-cbc", "aes-192-ecb", + "aes-256-cbc", "aes-256-ecb", + "aria-128-cbc", "aria-128-cfb", + "aria-128-ctr", "aria-128-ecb", "aria-128-ofb", + "aria-128-cfb1", "aria-128-cfb8", + "aria-192-cbc", "aria-192-cfb", + "aria-192-ctr", "aria-192-ecb", "aria-192-ofb", + "aria-192-cfb1", "aria-192-cfb8", + "aria-256-cbc", "aria-256-cfb", + "aria-256-ctr", "aria-256-ecb", "aria-256-ofb", + "aria-256-cfb1", "aria-256-cfb8", + "camellia-128-cbc", "camellia-128-ecb", + "camellia-192-cbc", "camellia-192-ecb", + "camellia-256-cbc", "camellia-256-ecb", + "base64", "zlib", + "des", "des3", "desx", "idea", "seed", "rc4", "rc4-40", + "rc2", "bf", "cast", "rc5", + "des-ecb", "des-ede", "des-ede3", + "des-cbc", "des-ede-cbc","des-ede3-cbc", + "des-cfb", "des-ede-cfb","des-ede3-cfb", + "des-ofb", "des-ede-ofb","des-ede3-ofb", + "idea-cbc","idea-ecb", "idea-cfb", "idea-ofb", + "seed-cbc","seed-ecb", "seed-cfb", "seed-ofb", + "rc2-cbc", "rc2-ecb", "rc2-cfb","rc2-ofb", "rc2-64-cbc", "rc2-40-cbc", + "bf-cbc", "bf-ecb", "bf-cfb", "bf-ofb", + "cast5-cbc","cast5-ecb", "cast5-cfb","cast5-ofb", + "cast-cbc", "rc5-cbc", "rc5-ecb", "rc5-cfb", "rc5-ofb", + "sm4-cbc", "sm4-ecb", "sm4-cfb", "sm4-ofb", "sm4-ctr" +) { + my $str = " {FT_cipher, \"$cmd\", enc_main, enc_options},\n"; + (my $algo = $cmd) =~ s/-.*//g; + if ($cmd eq "zlib") { + print "#ifdef ZLIB\n${str}#endif\n"; + } elsif (grep { $algo eq $_ } @disablables) { + print "#ifndef OPENSSL_NO_" . uc($algo) . "\n${str}#endif\n"; + } elsif (my $disabler = $cipher_disabler{$algo}) { + print "#ifndef OPENSSL_NO_" . uc($disabler) . "\n${str}#endif\n"; + } else { + print $str; + } +} + +print " {0, NULL, NULL}\n};\n"; +print "#endif\n"; diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/rand.c b/trunk/3rdparty/openssl-1.1-fit/apps/rand.c new file mode 100644 index 000000000..4c6181507 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/rand.c @@ -0,0 +1,133 @@ +/* + * Copyright 1998-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "apps.h" +#include "progs.h" + +#include +#include +#include + +#include +#include +#include + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_OUT, OPT_ENGINE, OPT_BASE64, OPT_HEX, + OPT_R_ENUM +} OPTION_CHOICE; + +const OPTIONS rand_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [flags] num\n"}, + {OPT_HELP_STR, 1, '-', "Valid options are:\n"}, + {"help", OPT_HELP, '-', "Display this summary"}, + {"out", OPT_OUT, '>', "Output file"}, + OPT_R_OPTIONS, + {"base64", OPT_BASE64, '-', "Base64 encode output"}, + {"hex", OPT_HEX, '-', "Hex encode output"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + {NULL} +}; + +int rand_main(int argc, char **argv) +{ + ENGINE *e = NULL; + BIO *out = NULL; + char *outfile = NULL, *prog; + OPTION_CHOICE o; + int format = FORMAT_BINARY, i, num = -1, r, ret = 1; + + prog = opt_init(argc, argv, rand_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(rand_options); + ret = 0; + goto end; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_BASE64: + format = FORMAT_BASE64; + break; + case OPT_HEX: + format = FORMAT_TEXT; + break; + } + } + argc = opt_num_rest(); + argv = opt_rest(); + if (argc == 1) { + if (!opt_int(argv[0], &num) || num <= 0) + goto end; + } else if (argc > 0) { + BIO_printf(bio_err, "Extra arguments given.\n"); + goto opthelp; + } + + out = bio_open_default(outfile, 'w', format); + if (out == NULL) + goto end; + + if (format == FORMAT_BASE64) { + BIO *b64 = BIO_new(BIO_f_base64()); + if (b64 == NULL) + goto end; + out = BIO_push(b64, out); + } + + while (num > 0) { + unsigned char buf[4096]; + int chunk; + + chunk = num; + if (chunk > (int)sizeof(buf)) + chunk = sizeof(buf); + r = RAND_bytes(buf, chunk); + if (r <= 0) + goto end; + if (format != FORMAT_TEXT) { + if (BIO_write(out, buf, chunk) != chunk) + goto end; + } else { + for (i = 0; i < chunk; i++) + if (BIO_printf(out, "%02x", buf[i]) != 2) + goto end; + } + num -= chunk; + } + if (format == FORMAT_TEXT) + BIO_puts(out, "\n"); + if (BIO_flush(out) <= 0) + goto end; + + ret = 0; + + end: + if (ret != 0) + ERR_print_errors(bio_err); + release_engine(e); + BIO_free_all(out); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/rehash.c b/trunk/3rdparty/openssl-1.1-fit/apps/rehash.c new file mode 100644 index 000000000..2b769fbce --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/rehash.c @@ -0,0 +1,532 @@ +/* + * Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2013-2014 Timo Teräs + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "apps.h" +#include "progs.h" + +#if defined(OPENSSL_SYS_UNIX) || defined(__APPLE__) || \ + (defined(__VMS) && defined(__DECC) && __CRTL_VER >= 80300000) +# include +# include +# include +# include +# include +# include +# include + +/* + * Make sure that the processing of symbol names is treated the same as when + * libcrypto is built. This is done automatically for public headers (see + * include/openssl/__DECC_INCLUDE_PROLOGUE.H and __DECC_INCLUDE_EPILOGUE.H), + * but not for internal headers. + */ +# ifdef __VMS +# pragma names save +# pragma names as_is,shortened +# endif + +# include "internal/o_dir.h" + +# ifdef __VMS +# pragma names restore +# endif + +# include +# include +# include + + +# ifndef PATH_MAX +# define PATH_MAX 4096 +# endif +# ifndef NAME_MAX +# define NAME_MAX 255 +# endif +# define MAX_COLLISIONS 256 + +# if defined(OPENSSL_SYS_VXWORKS) +/* + * VxWorks has no symbolic links + */ + +# define lstat(path, buf) stat(path, buf) + +int symlink(const char *target, const char *linkpath) +{ + errno = ENOSYS; + return -1; +} + +ssize_t readlink(const char *pathname, char *buf, size_t bufsiz) +{ + errno = ENOSYS; + return -1; +} +# endif + +typedef struct hentry_st { + struct hentry_st *next; + char *filename; + unsigned short old_id; + unsigned char need_symlink; + unsigned char digest[EVP_MAX_MD_SIZE]; +} HENTRY; + +typedef struct bucket_st { + struct bucket_st *next; + HENTRY *first_entry, *last_entry; + unsigned int hash; + unsigned short type; + unsigned short num_needed; +} BUCKET; + +enum Type { + /* Keep in sync with |suffixes|, below. */ + TYPE_CERT=0, TYPE_CRL=1 +}; + +enum Hash { + HASH_OLD, HASH_NEW, HASH_BOTH +}; + + +static int evpmdsize; +static const EVP_MD *evpmd; +static int remove_links = 1; +static int verbose = 0; +static BUCKET *hash_table[257]; + +static const char *suffixes[] = { "", "r" }; +static const char *extensions[] = { "pem", "crt", "cer", "crl" }; + + +static void bit_set(unsigned char *set, unsigned int bit) +{ + set[bit >> 3] |= 1 << (bit & 0x7); +} + +static int bit_isset(unsigned char *set, unsigned int bit) +{ + return set[bit >> 3] & (1 << (bit & 0x7)); +} + + +/* + * Process an entry; return number of errors. + */ +static int add_entry(enum Type type, unsigned int hash, const char *filename, + const unsigned char *digest, int need_symlink, + unsigned short old_id) +{ + static BUCKET nilbucket; + static HENTRY nilhentry; + BUCKET *bp; + HENTRY *ep, *found = NULL; + unsigned int ndx = (type + hash) % OSSL_NELEM(hash_table); + + for (bp = hash_table[ndx]; bp; bp = bp->next) + if (bp->type == type && bp->hash == hash) + break; + if (bp == NULL) { + bp = app_malloc(sizeof(*bp), "hash bucket"); + *bp = nilbucket; + bp->next = hash_table[ndx]; + bp->type = type; + bp->hash = hash; + hash_table[ndx] = bp; + } + + for (ep = bp->first_entry; ep; ep = ep->next) { + if (digest && memcmp(digest, ep->digest, evpmdsize) == 0) { + BIO_printf(bio_err, + "%s: warning: skipping duplicate %s in %s\n", + opt_getprog(), + type == TYPE_CERT ? "certificate" : "CRL", filename); + return 0; + } + if (strcmp(filename, ep->filename) == 0) { + found = ep; + if (digest == NULL) + break; + } + } + ep = found; + if (ep == NULL) { + if (bp->num_needed >= MAX_COLLISIONS) { + BIO_printf(bio_err, + "%s: error: hash table overflow for %s\n", + opt_getprog(), filename); + return 1; + } + ep = app_malloc(sizeof(*ep), "collision bucket"); + *ep = nilhentry; + ep->old_id = ~0; + ep->filename = OPENSSL_strdup(filename); + if (bp->last_entry) + bp->last_entry->next = ep; + if (bp->first_entry == NULL) + bp->first_entry = ep; + bp->last_entry = ep; + } + + if (old_id < ep->old_id) + ep->old_id = old_id; + if (need_symlink && !ep->need_symlink) { + ep->need_symlink = 1; + bp->num_needed++; + memcpy(ep->digest, digest, evpmdsize); + } + return 0; +} + +/* + * Check if a symlink goes to the right spot; return 0 if okay. + * This can be -1 if bad filename, or an error count. + */ +static int handle_symlink(const char *filename, const char *fullpath) +{ + unsigned int hash = 0; + int i, type, id; + unsigned char ch; + char linktarget[PATH_MAX], *endptr; + ossl_ssize_t n; + + for (i = 0; i < 8; i++) { + ch = filename[i]; + if (!isxdigit(ch)) + return -1; + hash <<= 4; + hash += OPENSSL_hexchar2int(ch); + } + if (filename[i++] != '.') + return -1; + for (type = OSSL_NELEM(suffixes) - 1; type > 0; type--) { + const char *suffix = suffixes[type]; + if (strncasecmp(suffix, &filename[i], strlen(suffix)) == 0) + break; + } + i += strlen(suffixes[type]); + + id = strtoul(&filename[i], &endptr, 10); + if (*endptr != '\0') + return -1; + + n = readlink(fullpath, linktarget, sizeof(linktarget)); + if (n < 0 || n >= (int)sizeof(linktarget)) + return -1; + linktarget[n] = 0; + + return add_entry(type, hash, linktarget, NULL, 0, id); +} + +/* + * process a file, return number of errors. + */ +static int do_file(const char *filename, const char *fullpath, enum Hash h) +{ + STACK_OF (X509_INFO) *inf = NULL; + X509_INFO *x; + X509_NAME *name = NULL; + BIO *b; + const char *ext; + unsigned char digest[EVP_MAX_MD_SIZE]; + int type, errs = 0; + size_t i; + + /* Does it end with a recognized extension? */ + if ((ext = strrchr(filename, '.')) == NULL) + goto end; + for (i = 0; i < OSSL_NELEM(extensions); i++) { + if (strcasecmp(extensions[i], ext + 1) == 0) + break; + } + if (i >= OSSL_NELEM(extensions)) + goto end; + + /* Does it have X.509 data in it? */ + if ((b = BIO_new_file(fullpath, "r")) == NULL) { + BIO_printf(bio_err, "%s: error: skipping %s, cannot open file\n", + opt_getprog(), filename); + errs++; + goto end; + } + inf = PEM_X509_INFO_read_bio(b, NULL, NULL, NULL); + BIO_free(b); + if (inf == NULL) + goto end; + + if (sk_X509_INFO_num(inf) != 1) { + BIO_printf(bio_err, + "%s: warning: skipping %s," + "it does not contain exactly one certificate or CRL\n", + opt_getprog(), filename); + /* This is not an error. */ + goto end; + } + x = sk_X509_INFO_value(inf, 0); + if (x->x509 != NULL) { + type = TYPE_CERT; + name = X509_get_subject_name(x->x509); + X509_digest(x->x509, evpmd, digest, NULL); + } else if (x->crl != NULL) { + type = TYPE_CRL; + name = X509_CRL_get_issuer(x->crl); + X509_CRL_digest(x->crl, evpmd, digest, NULL); + } else { + ++errs; + goto end; + } + if (name != NULL) { + if ((h == HASH_NEW) || (h == HASH_BOTH)) + errs += add_entry(type, X509_NAME_hash(name), filename, digest, 1, ~0); + if ((h == HASH_OLD) || (h == HASH_BOTH)) + errs += add_entry(type, X509_NAME_hash_old(name), filename, digest, 1, ~0); + } + +end: + sk_X509_INFO_pop_free(inf, X509_INFO_free); + return errs; +} + +static void str_free(char *s) +{ + OPENSSL_free(s); +} + +static int ends_with_dirsep(const char *path) +{ + if (*path != '\0') + path += strlen(path) - 1; +# if defined __VMS + if (*path == ']' || *path == '>' || *path == ':') + return 1; +# elif defined _WIN32 + if (*path == '\\') + return 1; +# endif + return *path == '/'; +} + +/* + * Process a directory; return number of errors found. + */ +static int do_dir(const char *dirname, enum Hash h) +{ + BUCKET *bp, *nextbp; + HENTRY *ep, *nextep; + OPENSSL_DIR_CTX *d = NULL; + struct stat st; + unsigned char idmask[MAX_COLLISIONS / 8]; + int n, numfiles, nextid, buflen, errs = 0; + size_t i; + const char *pathsep; + const char *filename; + char *buf, *copy = NULL; + STACK_OF(OPENSSL_STRING) *files = NULL; + + if (app_access(dirname, W_OK) < 0) { + BIO_printf(bio_err, "Skipping %s, can't write\n", dirname); + return 1; + } + buflen = strlen(dirname); + pathsep = (buflen && !ends_with_dirsep(dirname)) ? "/": ""; + buflen += NAME_MAX + 1 + 1; + buf = app_malloc(buflen, "filename buffer"); + + if (verbose) + BIO_printf(bio_out, "Doing %s\n", dirname); + + if ((files = sk_OPENSSL_STRING_new_null()) == NULL) { + BIO_printf(bio_err, "Skipping %s, out of memory\n", dirname); + errs = 1; + goto err; + } + while ((filename = OPENSSL_DIR_read(&d, dirname)) != NULL) { + if ((copy = OPENSSL_strdup(filename)) == NULL + || sk_OPENSSL_STRING_push(files, copy) == 0) { + OPENSSL_free(copy); + BIO_puts(bio_err, "out of memory\n"); + errs = 1; + goto err; + } + } + OPENSSL_DIR_end(&d); + sk_OPENSSL_STRING_sort(files); + + numfiles = sk_OPENSSL_STRING_num(files); + for (n = 0; n < numfiles; ++n) { + filename = sk_OPENSSL_STRING_value(files, n); + if (BIO_snprintf(buf, buflen, "%s%s%s", + dirname, pathsep, filename) >= buflen) + continue; + if (lstat(buf, &st) < 0) + continue; + if (S_ISLNK(st.st_mode) && handle_symlink(filename, buf) == 0) + continue; + errs += do_file(filename, buf, h); + } + + for (i = 0; i < OSSL_NELEM(hash_table); i++) { + for (bp = hash_table[i]; bp; bp = nextbp) { + nextbp = bp->next; + nextid = 0; + memset(idmask, 0, (bp->num_needed + 7) / 8); + for (ep = bp->first_entry; ep; ep = ep->next) + if (ep->old_id < bp->num_needed) + bit_set(idmask, ep->old_id); + + for (ep = bp->first_entry; ep; ep = nextep) { + nextep = ep->next; + if (ep->old_id < bp->num_needed) { + /* Link exists, and is used as-is */ + BIO_snprintf(buf, buflen, "%08x.%s%d", bp->hash, + suffixes[bp->type], ep->old_id); + if (verbose) + BIO_printf(bio_out, "link %s -> %s\n", + ep->filename, buf); + } else if (ep->need_symlink) { + /* New link needed (it may replace something) */ + while (bit_isset(idmask, nextid)) + nextid++; + + BIO_snprintf(buf, buflen, "%s%s%n%08x.%s%d", + dirname, pathsep, &n, bp->hash, + suffixes[bp->type], nextid); + if (verbose) + BIO_printf(bio_out, "link %s -> %s\n", + ep->filename, &buf[n]); + if (unlink(buf) < 0 && errno != ENOENT) { + BIO_printf(bio_err, + "%s: Can't unlink %s, %s\n", + opt_getprog(), buf, strerror(errno)); + errs++; + } + if (symlink(ep->filename, buf) < 0) { + BIO_printf(bio_err, + "%s: Can't symlink %s, %s\n", + opt_getprog(), ep->filename, + strerror(errno)); + errs++; + } + bit_set(idmask, nextid); + } else if (remove_links) { + /* Link to be deleted */ + BIO_snprintf(buf, buflen, "%s%s%n%08x.%s%d", + dirname, pathsep, &n, bp->hash, + suffixes[bp->type], ep->old_id); + if (verbose) + BIO_printf(bio_out, "unlink %s\n", + &buf[n]); + if (unlink(buf) < 0 && errno != ENOENT) { + BIO_printf(bio_err, + "%s: Can't unlink %s, %s\n", + opt_getprog(), buf, strerror(errno)); + errs++; + } + } + OPENSSL_free(ep->filename); + OPENSSL_free(ep); + } + OPENSSL_free(bp); + } + hash_table[i] = NULL; + } + + err: + sk_OPENSSL_STRING_pop_free(files, str_free); + OPENSSL_free(buf); + return errs; +} + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMPAT, OPT_OLD, OPT_N, OPT_VERBOSE +} OPTION_CHOICE; + +const OPTIONS rehash_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] [cert-directory...]\n"}, + {OPT_HELP_STR, 1, '-', "Valid options are:\n"}, + {"help", OPT_HELP, '-', "Display this summary"}, + {"h", OPT_HELP, '-', "Display this summary"}, + {"compat", OPT_COMPAT, '-', "Create both new- and old-style hash links"}, + {"old", OPT_OLD, '-', "Use old-style hash to generate links"}, + {"n", OPT_N, '-', "Do not remove existing links"}, + {"v", OPT_VERBOSE, '-', "Verbose output"}, + {NULL} +}; + + +int rehash_main(int argc, char **argv) +{ + const char *env, *prog; + char *e, *m; + int errs = 0; + OPTION_CHOICE o; + enum Hash h = HASH_NEW; + + prog = opt_init(argc, argv, rehash_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(rehash_options); + goto end; + case OPT_COMPAT: + h = HASH_BOTH; + break; + case OPT_OLD: + h = HASH_OLD; + break; + case OPT_N: + remove_links = 0; + break; + case OPT_VERBOSE: + verbose = 1; + break; + } + } + argc = opt_num_rest(); + argv = opt_rest(); + + evpmd = EVP_sha1(); + evpmdsize = EVP_MD_size(evpmd); + + if (*argv != NULL) { + while (*argv != NULL) + errs += do_dir(*argv++, h); + } else if ((env = getenv(X509_get_default_cert_dir_env())) != NULL) { + char lsc[2] = { LIST_SEPARATOR_CHAR, '\0' }; + m = OPENSSL_strdup(env); + for (e = strtok(m, lsc); e != NULL; e = strtok(NULL, lsc)) + errs += do_dir(e, h); + OPENSSL_free(m); + } else { + errs += do_dir(X509_get_default_cert_dir(), h); + } + + end: + return errs; +} + +#else +const OPTIONS rehash_options[] = { + {NULL} +}; + +int rehash_main(int argc, char **argv) +{ + BIO_printf(bio_err, "Not available; use c_rehash script\n"); + return 1; +} + +#endif /* defined(OPENSSL_SYS_UNIX) || defined(__APPLE__) */ diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/req.c b/trunk/3rdparty/openssl-1.1-fit/apps/req.c new file mode 100644 index 000000000..6fd28a2ab --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/req.c @@ -0,0 +1,1664 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef OPENSSL_NO_RSA +# include +#endif +#ifndef OPENSSL_NO_DSA +# include +#endif + +#define SECTION "req" + +#define BITS "default_bits" +#define KEYFILE "default_keyfile" +#define PROMPT "prompt" +#define DISTINGUISHED_NAME "distinguished_name" +#define ATTRIBUTES "attributes" +#define V3_EXTENSIONS "x509_extensions" +#define REQ_EXTENSIONS "req_extensions" +#define STRING_MASK "string_mask" +#define UTF8_IN "utf8" + +#define DEFAULT_KEY_LENGTH 2048 +#define MIN_KEY_LENGTH 512 + +static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *dn, int mutlirdn, + int attribs, unsigned long chtype); +static int build_subject(X509_REQ *req, const char *subj, unsigned long chtype, + int multirdn); +static int prompt_info(X509_REQ *req, + STACK_OF(CONF_VALUE) *dn_sk, const char *dn_sect, + STACK_OF(CONF_VALUE) *attr_sk, const char *attr_sect, + int attribs, unsigned long chtype); +static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *sk, + STACK_OF(CONF_VALUE) *attr, int attribs, + unsigned long chtype); +static int add_attribute_object(X509_REQ *req, char *text, const char *def, + char *value, int nid, int n_min, int n_max, + unsigned long chtype); +static int add_DN_object(X509_NAME *n, char *text, const char *def, + char *value, int nid, int n_min, int n_max, + unsigned long chtype, int mval); +static int genpkey_cb(EVP_PKEY_CTX *ctx); +static int build_data(char *text, const char *def, + char *value, int n_min, int n_max, + char *buf, const int buf_size, + const char *desc1, const char *desc2 + ); +static int req_check_len(int len, int n_min, int n_max); +static int check_end(const char *str, const char *end); +static int join(char buf[], size_t buf_size, const char *name, + const char *tail, const char *desc); +static EVP_PKEY_CTX *set_keygen_ctx(const char *gstr, + int *pkey_type, long *pkeylen, + char **palgnam, ENGINE *keygen_engine); +static CONF *req_conf = NULL; +static CONF *addext_conf = NULL; +static int batch = 0; + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_KEYGEN_ENGINE, OPT_KEY, + OPT_PUBKEY, OPT_NEW, OPT_CONFIG, OPT_KEYFORM, OPT_IN, OPT_OUT, + OPT_KEYOUT, OPT_PASSIN, OPT_PASSOUT, OPT_NEWKEY, + OPT_PKEYOPT, OPT_SIGOPT, OPT_BATCH, OPT_NEWHDR, OPT_MODULUS, + OPT_VERIFY, OPT_NODES, OPT_NOOUT, OPT_VERBOSE, OPT_UTF8, + OPT_NAMEOPT, OPT_REQOPT, OPT_SUBJ, OPT_SUBJECT, OPT_TEXT, OPT_X509, + OPT_MULTIVALUE_RDN, OPT_DAYS, OPT_SET_SERIAL, OPT_ADDEXT, OPT_EXTENSIONS, + OPT_REQEXTS, OPT_PRECERT, OPT_MD, + OPT_R_ENUM +} OPTION_CHOICE; + +const OPTIONS req_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"}, + {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"}, + {"in", OPT_IN, '<', "Input file"}, + {"out", OPT_OUT, '>', "Output file"}, + {"key", OPT_KEY, 's', "Private key to use"}, + {"keyform", OPT_KEYFORM, 'f', "Key file format"}, + {"pubkey", OPT_PUBKEY, '-', "Output public key"}, + {"new", OPT_NEW, '-', "New request"}, + {"config", OPT_CONFIG, '<', "Request template file"}, + {"keyout", OPT_KEYOUT, '>', "File to send the key to"}, + {"passin", OPT_PASSIN, 's', "Private key password source"}, + {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, + OPT_R_OPTIONS, + {"newkey", OPT_NEWKEY, 's', "Specify as type:bits"}, + {"pkeyopt", OPT_PKEYOPT, 's', "Public key options as opt:value"}, + {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"}, + {"batch", OPT_BATCH, '-', + "Do not ask anything during request generation"}, + {"newhdr", OPT_NEWHDR, '-', "Output \"NEW\" in the header lines"}, + {"modulus", OPT_MODULUS, '-', "RSA modulus"}, + {"verify", OPT_VERIFY, '-', "Verify signature on REQ"}, + {"nodes", OPT_NODES, '-', "Don't encrypt the output key"}, + {"noout", OPT_NOOUT, '-', "Do not output REQ"}, + {"verbose", OPT_VERBOSE, '-', "Verbose output"}, + {"utf8", OPT_UTF8, '-', "Input characters are UTF8 (default ASCII)"}, + {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"}, + {"reqopt", OPT_REQOPT, 's', "Various request text options"}, + {"text", OPT_TEXT, '-', "Text form of request"}, + {"x509", OPT_X509, '-', + "Output a x509 structure instead of a cert request"}, + {OPT_MORE_STR, 1, 1, "(Required by some CA's)"}, + {"subj", OPT_SUBJ, 's', "Set or modify request subject"}, + {"subject", OPT_SUBJECT, '-', "Output the request's subject"}, + {"multivalue-rdn", OPT_MULTIVALUE_RDN, '-', + "Enable support for multivalued RDNs"}, + {"days", OPT_DAYS, 'p', "Number of days cert is valid for"}, + {"set_serial", OPT_SET_SERIAL, 's', "Serial number to use"}, + {"addext", OPT_ADDEXT, 's', + "Additional cert extension key=value pair (may be given more than once)"}, + {"extensions", OPT_EXTENSIONS, 's', + "Cert extension section (override value in config file)"}, + {"reqexts", OPT_REQEXTS, 's', + "Request extension section (override value in config file)"}, + {"precert", OPT_PRECERT, '-', "Add a poison extension (implies -new)"}, + {"", OPT_MD, '-', "Any supported digest"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, + {"keygen_engine", OPT_KEYGEN_ENGINE, 's', + "Specify engine to be used for key generation operations"}, +#endif + {NULL} +}; + + +/* + * An LHASH of strings, where each string is an extension name. + */ +static unsigned long ext_name_hash(const OPENSSL_STRING *a) +{ + return OPENSSL_LH_strhash((const char *)a); +} + +static int ext_name_cmp(const OPENSSL_STRING *a, const OPENSSL_STRING *b) +{ + return strcmp((const char *)a, (const char *)b); +} + +static void exts_cleanup(OPENSSL_STRING *x) +{ + OPENSSL_free((char *)x); +} + +/* + * Is the |kv| key already duplicated? This is remarkably tricky to get + * right. Return 0 if unique, -1 on runtime error; 1 if found or a syntax + * error. + */ +static int duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv) +{ + char *p; + size_t off; + + /* Check syntax. */ + /* Skip leading whitespace, make a copy. */ + while (*kv && isspace(*kv)) + if (*++kv == '\0') + return 1; + if ((p = strchr(kv, '=')) == NULL) + return 1; + off = p - kv; + if ((kv = OPENSSL_strdup(kv)) == NULL) + return -1; + + /* Skip trailing space before the equal sign. */ + for (p = kv + off; p > kv; --p) + if (!isspace(p[-1])) + break; + if (p == kv) { + OPENSSL_free(kv); + return 1; + } + *p = '\0'; + + /* Finally have a clean "key"; see if it's there [by attempt to add it]. */ + if ((p = (char *)lh_OPENSSL_STRING_insert(addexts, (OPENSSL_STRING*)kv)) + != NULL || lh_OPENSSL_STRING_error(addexts)) { + OPENSSL_free(p != NULL ? p : kv); + return -1; + } + + return 0; +} + +int req_main(int argc, char **argv) +{ + ASN1_INTEGER *serial = NULL; + BIO *in = NULL, *out = NULL; + ENGINE *e = NULL, *gen_eng = NULL; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *genctx = NULL; + STACK_OF(OPENSSL_STRING) *pkeyopts = NULL, *sigopts = NULL; + LHASH_OF(OPENSSL_STRING) *addexts = NULL; + X509 *x509ss = NULL; + X509_REQ *req = NULL; + const EVP_CIPHER *cipher = NULL; + const EVP_MD *md_alg = NULL, *digest = NULL; + BIO *addext_bio = NULL; + char *extensions = NULL, *infile = NULL; + char *outfile = NULL, *keyfile = NULL; + char *keyalgstr = NULL, *p, *prog, *passargin = NULL, *passargout = NULL; + char *passin = NULL, *passout = NULL; + char *nofree_passin = NULL, *nofree_passout = NULL; + char *req_exts = NULL, *subj = NULL; + char *template = default_config_file, *keyout = NULL; + const char *keyalg = NULL; + OPTION_CHOICE o; + int ret = 1, x509 = 0, days = 0, i = 0, newreq = 0, verbose = 0; + int pkey_type = -1, private = 0; + int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyform = FORMAT_PEM; + int modulus = 0, multirdn = 0, verify = 0, noout = 0, text = 0; + int nodes = 0, newhdr = 0, subject = 0, pubkey = 0, precert = 0; + long newkey = -1; + unsigned long chtype = MBSTRING_ASC, reqflag = 0; + +#ifndef OPENSSL_NO_DES + cipher = EVP_des_ede3_cbc(); +#endif + + prog = opt_init(argc, argv, req_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(req_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) + goto opthelp; + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) + goto opthelp; + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_KEYGEN_ENGINE: +#ifndef OPENSSL_NO_ENGINE + gen_eng = ENGINE_by_id(opt_arg()); + if (gen_eng == NULL) { + BIO_printf(bio_err, "Can't find keygen engine %s\n", *argv); + goto opthelp; + } +#endif + break; + case OPT_KEY: + keyfile = opt_arg(); + break; + case OPT_PUBKEY: + pubkey = 1; + break; + case OPT_NEW: + newreq = 1; + break; + case OPT_CONFIG: + template = opt_arg(); + break; + case OPT_KEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_KEYOUT: + keyout = opt_arg(); + break; + case OPT_PASSIN: + passargin = opt_arg(); + break; + case OPT_PASSOUT: + passargout = opt_arg(); + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_NEWKEY: + keyalg = opt_arg(); + newreq = 1; + break; + case OPT_PKEYOPT: + if (!pkeyopts) + pkeyopts = sk_OPENSSL_STRING_new_null(); + if (!pkeyopts || !sk_OPENSSL_STRING_push(pkeyopts, opt_arg())) + goto opthelp; + break; + case OPT_SIGOPT: + if (!sigopts) + sigopts = sk_OPENSSL_STRING_new_null(); + if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg())) + goto opthelp; + break; + case OPT_BATCH: + batch = 1; + break; + case OPT_NEWHDR: + newhdr = 1; + break; + case OPT_MODULUS: + modulus = 1; + break; + case OPT_VERIFY: + verify = 1; + break; + case OPT_NODES: + nodes = 1; + break; + case OPT_NOOUT: + noout = 1; + break; + case OPT_VERBOSE: + verbose = 1; + break; + case OPT_UTF8: + chtype = MBSTRING_UTF8; + break; + case OPT_NAMEOPT: + if (!set_nameopt(opt_arg())) + goto opthelp; + break; + case OPT_REQOPT: + if (!set_cert_ex(&reqflag, opt_arg())) + goto opthelp; + break; + case OPT_TEXT: + text = 1; + break; + case OPT_X509: + x509 = 1; + break; + case OPT_DAYS: + days = atoi(opt_arg()); + break; + case OPT_SET_SERIAL: + if (serial != NULL) { + BIO_printf(bio_err, "Serial number supplied twice\n"); + goto opthelp; + } + serial = s2i_ASN1_INTEGER(NULL, opt_arg()); + if (serial == NULL) + goto opthelp; + break; + case OPT_SUBJECT: + subject = 1; + break; + case OPT_SUBJ: + subj = opt_arg(); + break; + case OPT_MULTIVALUE_RDN: + multirdn = 1; + break; + case OPT_ADDEXT: + p = opt_arg(); + if (addexts == NULL) { + addexts = lh_OPENSSL_STRING_new(ext_name_hash, ext_name_cmp); + addext_bio = BIO_new(BIO_s_mem()); + if (addexts == NULL || addext_bio == NULL) + goto end; + } + i = duplicated(addexts, p); + if (i == 1) + goto opthelp; + if (i < 0 || BIO_printf(addext_bio, "%s\n", opt_arg()) < 0) + goto end; + break; + case OPT_EXTENSIONS: + extensions = opt_arg(); + break; + case OPT_REQEXTS: + req_exts = opt_arg(); + break; + case OPT_PRECERT: + newreq = precert = 1; + break; + case OPT_MD: + if (!opt_md(opt_unknown(), &md_alg)) + goto opthelp; + digest = md_alg; + break; + } + } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + + if (days && !x509) + BIO_printf(bio_err, "Ignoring -days; not generating a certificate\n"); + if (x509 && infile == NULL) + newreq = 1; + + /* TODO: simplify this as pkey is still always NULL here */ + private = newreq && (pkey == NULL) ? 1 : 0; + + if (!app_passwd(passargin, passargout, &passin, &passout)) { + BIO_printf(bio_err, "Error getting passwords\n"); + goto end; + } + + if (verbose) + BIO_printf(bio_err, "Using configuration from %s\n", template); + req_conf = app_load_config(template); + if (addext_bio) { + if (verbose) + BIO_printf(bio_err, + "Using additional configuration from command line\n"); + addext_conf = app_load_config_bio(addext_bio, NULL); + } + if (template != default_config_file && !app_load_modules(req_conf)) + goto end; + + if (req_conf != NULL) { + p = NCONF_get_string(req_conf, NULL, "oid_file"); + if (p == NULL) + ERR_clear_error(); + if (p != NULL) { + BIO *oid_bio; + + oid_bio = BIO_new_file(p, "r"); + if (oid_bio == NULL) { + /*- + BIO_printf(bio_err,"problems opening %s for extra oid's\n",p); + ERR_print_errors(bio_err); + */ + } else { + OBJ_create_objects(oid_bio); + BIO_free(oid_bio); + } + } + } + if (!add_oid_section(req_conf)) + goto end; + + if (md_alg == NULL) { + p = NCONF_get_string(req_conf, SECTION, "default_md"); + if (p == NULL) { + ERR_clear_error(); + } else { + if (!opt_md(p, &md_alg)) + goto opthelp; + digest = md_alg; + } + } + + if (extensions == NULL) { + extensions = NCONF_get_string(req_conf, SECTION, V3_EXTENSIONS); + if (extensions == NULL) + ERR_clear_error(); + } + if (extensions != NULL) { + /* Check syntax of file */ + X509V3_CTX ctx; + X509V3_set_ctx_test(&ctx); + X509V3_set_nconf(&ctx, req_conf); + if (!X509V3_EXT_add_nconf(req_conf, &ctx, extensions, NULL)) { + BIO_printf(bio_err, + "Error Loading extension section %s\n", extensions); + goto end; + } + } + if (addext_conf != NULL) { + /* Check syntax of command line extensions */ + X509V3_CTX ctx; + X509V3_set_ctx_test(&ctx); + X509V3_set_nconf(&ctx, addext_conf); + if (!X509V3_EXT_add_nconf(addext_conf, &ctx, "default", NULL)) { + BIO_printf(bio_err, "Error Loading command line extensions\n"); + goto end; + } + } + + if (passin == NULL) { + passin = nofree_passin = + NCONF_get_string(req_conf, SECTION, "input_password"); + if (passin == NULL) + ERR_clear_error(); + } + + if (passout == NULL) { + passout = nofree_passout = + NCONF_get_string(req_conf, SECTION, "output_password"); + if (passout == NULL) + ERR_clear_error(); + } + + p = NCONF_get_string(req_conf, SECTION, STRING_MASK); + if (p == NULL) + ERR_clear_error(); + + if (p != NULL && !ASN1_STRING_set_default_mask_asc(p)) { + BIO_printf(bio_err, "Invalid global string mask setting %s\n", p); + goto end; + } + + if (chtype != MBSTRING_UTF8) { + p = NCONF_get_string(req_conf, SECTION, UTF8_IN); + if (p == NULL) + ERR_clear_error(); + else if (strcmp(p, "yes") == 0) + chtype = MBSTRING_UTF8; + } + + if (req_exts == NULL) { + req_exts = NCONF_get_string(req_conf, SECTION, REQ_EXTENSIONS); + if (req_exts == NULL) + ERR_clear_error(); + } + if (req_exts != NULL) { + /* Check syntax of file */ + X509V3_CTX ctx; + X509V3_set_ctx_test(&ctx); + X509V3_set_nconf(&ctx, req_conf); + if (!X509V3_EXT_add_nconf(req_conf, &ctx, req_exts, NULL)) { + BIO_printf(bio_err, + "Error Loading request extension section %s\n", + req_exts); + goto end; + } + } + + if (keyfile != NULL) { + pkey = load_key(keyfile, keyform, 0, passin, e, "Private Key"); + if (pkey == NULL) { + /* load_key() has already printed an appropriate message */ + goto end; + } else { + app_RAND_load_conf(req_conf, SECTION); + } + } + + if (newreq && (pkey == NULL)) { + app_RAND_load_conf(req_conf, SECTION); + + if (!NCONF_get_number(req_conf, SECTION, BITS, &newkey)) { + newkey = DEFAULT_KEY_LENGTH; + } + + if (keyalg != NULL) { + genctx = set_keygen_ctx(keyalg, &pkey_type, &newkey, + &keyalgstr, gen_eng); + if (genctx == NULL) + goto end; + } + + if (newkey < MIN_KEY_LENGTH + && (pkey_type == EVP_PKEY_RSA || pkey_type == EVP_PKEY_DSA)) { + BIO_printf(bio_err, "private key length is too short,\n"); + BIO_printf(bio_err, "it needs to be at least %d bits, not %ld\n", + MIN_KEY_LENGTH, newkey); + goto end; + } + + if (pkey_type == EVP_PKEY_RSA && newkey > OPENSSL_RSA_MAX_MODULUS_BITS) + BIO_printf(bio_err, + "Warning: It is not recommended to use more than %d bit for RSA keys.\n" + " Your key size is %ld! Larger key size may behave not as expected.\n", + OPENSSL_RSA_MAX_MODULUS_BITS, newkey); + +#ifndef OPENSSL_NO_DSA + if (pkey_type == EVP_PKEY_DSA && newkey > OPENSSL_DSA_MAX_MODULUS_BITS) + BIO_printf(bio_err, + "Warning: It is not recommended to use more than %d bit for DSA keys.\n" + " Your key size is %ld! Larger key size may behave not as expected.\n", + OPENSSL_DSA_MAX_MODULUS_BITS, newkey); +#endif + + if (genctx == NULL) { + genctx = set_keygen_ctx(NULL, &pkey_type, &newkey, + &keyalgstr, gen_eng); + if (!genctx) + goto end; + } + + if (pkeyopts != NULL) { + char *genopt; + for (i = 0; i < sk_OPENSSL_STRING_num(pkeyopts); i++) { + genopt = sk_OPENSSL_STRING_value(pkeyopts, i); + if (pkey_ctrl_string(genctx, genopt) <= 0) { + BIO_printf(bio_err, "parameter error \"%s\"\n", genopt); + ERR_print_errors(bio_err); + goto end; + } + } + } + + if (pkey_type == EVP_PKEY_EC) { + BIO_printf(bio_err, "Generating an EC private key\n"); + } else { + BIO_printf(bio_err, "Generating a %s private key\n", keyalgstr); + } + + EVP_PKEY_CTX_set_cb(genctx, genpkey_cb); + EVP_PKEY_CTX_set_app_data(genctx, bio_err); + + if (EVP_PKEY_keygen(genctx, &pkey) <= 0) { + BIO_puts(bio_err, "Error Generating Key\n"); + goto end; + } + + EVP_PKEY_CTX_free(genctx); + genctx = NULL; + + if (keyout == NULL) { + keyout = NCONF_get_string(req_conf, SECTION, KEYFILE); + if (keyout == NULL) + ERR_clear_error(); + } + + if (keyout == NULL) + BIO_printf(bio_err, "writing new private key to stdout\n"); + else + BIO_printf(bio_err, "writing new private key to '%s'\n", keyout); + out = bio_open_owner(keyout, outformat, private); + if (out == NULL) + goto end; + + p = NCONF_get_string(req_conf, SECTION, "encrypt_rsa_key"); + if (p == NULL) { + ERR_clear_error(); + p = NCONF_get_string(req_conf, SECTION, "encrypt_key"); + if (p == NULL) + ERR_clear_error(); + } + if ((p != NULL) && (strcmp(p, "no") == 0)) + cipher = NULL; + if (nodes) + cipher = NULL; + + i = 0; + loop: + assert(private); + if (!PEM_write_bio_PrivateKey(out, pkey, cipher, + NULL, 0, NULL, passout)) { + if ((ERR_GET_REASON(ERR_peek_error()) == + PEM_R_PROBLEMS_GETTING_PASSWORD) && (i < 3)) { + ERR_clear_error(); + i++; + goto loop; + } + goto end; + } + BIO_free(out); + out = NULL; + BIO_printf(bio_err, "-----\n"); + } + + if (!newreq) { + in = bio_open_default(infile, 'r', informat); + if (in == NULL) + goto end; + + if (informat == FORMAT_ASN1) + req = d2i_X509_REQ_bio(in, NULL); + else + req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL); + if (req == NULL) { + BIO_printf(bio_err, "unable to load X509 request\n"); + goto end; + } + } + + if (newreq || x509) { + if (pkey == NULL) { + BIO_printf(bio_err, "you need to specify a private key\n"); + goto end; + } + + if (req == NULL) { + req = X509_REQ_new(); + if (req == NULL) { + goto end; + } + + i = make_REQ(req, pkey, subj, multirdn, !x509, chtype); + subj = NULL; /* done processing '-subj' option */ + if (!i) { + BIO_printf(bio_err, "problems making Certificate Request\n"); + goto end; + } + } + if (x509) { + EVP_PKEY *tmppkey; + X509V3_CTX ext_ctx; + if ((x509ss = X509_new()) == NULL) + goto end; + + /* Set version to V3 */ + if ((extensions != NULL || addext_conf != NULL) + && !X509_set_version(x509ss, 2)) + goto end; + if (serial != NULL) { + if (!X509_set_serialNumber(x509ss, serial)) + goto end; + } else { + if (!rand_serial(NULL, X509_get_serialNumber(x509ss))) + goto end; + } + + if (!X509_set_issuer_name(x509ss, X509_REQ_get_subject_name(req))) + goto end; + if (days == 0) { + /* set default days if it's not specified */ + days = 30; + } + if (!set_cert_times(x509ss, NULL, NULL, days)) + goto end; + if (!X509_set_subject_name + (x509ss, X509_REQ_get_subject_name(req))) + goto end; + tmppkey = X509_REQ_get0_pubkey(req); + if (!tmppkey || !X509_set_pubkey(x509ss, tmppkey)) + goto end; + + /* Set up V3 context struct */ + + X509V3_set_ctx(&ext_ctx, x509ss, x509ss, NULL, NULL, 0); + X509V3_set_nconf(&ext_ctx, req_conf); + + /* Add extensions */ + if (extensions != NULL && !X509V3_EXT_add_nconf(req_conf, + &ext_ctx, extensions, + x509ss)) { + BIO_printf(bio_err, "Error Loading extension section %s\n", + extensions); + goto end; + } + if (addext_conf != NULL + && !X509V3_EXT_add_nconf(addext_conf, &ext_ctx, "default", + x509ss)) { + BIO_printf(bio_err, "Error Loading command line extensions\n"); + goto end; + } + + /* If a pre-cert was requested, we need to add a poison extension */ + if (precert) { + if (X509_add1_ext_i2d(x509ss, NID_ct_precert_poison, NULL, 1, 0) + != 1) { + BIO_printf(bio_err, "Error adding poison extension\n"); + goto end; + } + } + + i = do_X509_sign(x509ss, pkey, digest, sigopts); + if (!i) { + ERR_print_errors(bio_err); + goto end; + } + } else { + X509V3_CTX ext_ctx; + + /* Set up V3 context struct */ + + X509V3_set_ctx(&ext_ctx, NULL, NULL, req, NULL, 0); + X509V3_set_nconf(&ext_ctx, req_conf); + + /* Add extensions */ + if (req_exts != NULL + && !X509V3_EXT_REQ_add_nconf(req_conf, &ext_ctx, + req_exts, req)) { + BIO_printf(bio_err, "Error Loading extension section %s\n", + req_exts); + goto end; + } + if (addext_conf != NULL + && !X509V3_EXT_REQ_add_nconf(addext_conf, &ext_ctx, "default", + req)) { + BIO_printf(bio_err, "Error Loading command line extensions\n"); + goto end; + } + i = do_X509_REQ_sign(req, pkey, digest, sigopts); + if (!i) { + ERR_print_errors(bio_err); + goto end; + } + } + } + + if (subj && x509) { + BIO_printf(bio_err, "Cannot modify certificate subject\n"); + goto end; + } + + if (subj && !x509) { + if (verbose) { + BIO_printf(bio_err, "Modifying Request's Subject\n"); + print_name(bio_err, "old subject=", + X509_REQ_get_subject_name(req), get_nameopt()); + } + + if (build_subject(req, subj, chtype, multirdn) == 0) { + BIO_printf(bio_err, "ERROR: cannot modify subject\n"); + ret = 1; + goto end; + } + + if (verbose) { + print_name(bio_err, "new subject=", + X509_REQ_get_subject_name(req), get_nameopt()); + } + } + + if (verify && !x509) { + EVP_PKEY *tpubkey = pkey; + + if (tpubkey == NULL) { + tpubkey = X509_REQ_get0_pubkey(req); + if (tpubkey == NULL) + goto end; + } + + i = X509_REQ_verify(req, tpubkey); + + if (i < 0) { + goto end; + } else if (i == 0) { + BIO_printf(bio_err, "verify failure\n"); + ERR_print_errors(bio_err); + } else { /* if (i > 0) */ + BIO_printf(bio_err, "verify OK\n"); + } + } + + if (noout && !text && !modulus && !subject && !pubkey) { + ret = 0; + goto end; + } + + out = bio_open_default(outfile, + keyout != NULL && outfile != NULL && + strcmp(keyout, outfile) == 0 ? 'a' : 'w', + outformat); + if (out == NULL) + goto end; + + if (pubkey) { + EVP_PKEY *tpubkey = X509_REQ_get0_pubkey(req); + + if (tpubkey == NULL) { + BIO_printf(bio_err, "Error getting public key\n"); + ERR_print_errors(bio_err); + goto end; + } + PEM_write_bio_PUBKEY(out, tpubkey); + } + + if (text) { + if (x509) + X509_print_ex(out, x509ss, get_nameopt(), reqflag); + else + X509_REQ_print_ex(out, req, get_nameopt(), reqflag); + } + + if (subject) { + if (x509) + print_name(out, "subject=", X509_get_subject_name(x509ss), + get_nameopt()); + else + print_name(out, "subject=", X509_REQ_get_subject_name(req), + get_nameopt()); + } + + if (modulus) { + EVP_PKEY *tpubkey; + + if (x509) + tpubkey = X509_get0_pubkey(x509ss); + else + tpubkey = X509_REQ_get0_pubkey(req); + if (tpubkey == NULL) { + fprintf(stdout, "Modulus=unavailable\n"); + goto end; + } + fprintf(stdout, "Modulus="); +#ifndef OPENSSL_NO_RSA + if (EVP_PKEY_base_id(tpubkey) == EVP_PKEY_RSA) { + const BIGNUM *n; + RSA_get0_key(EVP_PKEY_get0_RSA(tpubkey), &n, NULL, NULL); + BN_print(out, n); + } else +#endif + fprintf(stdout, "Wrong Algorithm type"); + fprintf(stdout, "\n"); + } + + if (!noout && !x509) { + if (outformat == FORMAT_ASN1) + i = i2d_X509_REQ_bio(out, req); + else if (newhdr) + i = PEM_write_bio_X509_REQ_NEW(out, req); + else + i = PEM_write_bio_X509_REQ(out, req); + if (!i) { + BIO_printf(bio_err, "unable to write X509 request\n"); + goto end; + } + } + if (!noout && x509 && (x509ss != NULL)) { + if (outformat == FORMAT_ASN1) + i = i2d_X509_bio(out, x509ss); + else + i = PEM_write_bio_X509(out, x509ss); + if (!i) { + BIO_printf(bio_err, "unable to write X509 certificate\n"); + goto end; + } + } + ret = 0; + end: + if (ret) { + ERR_print_errors(bio_err); + } + NCONF_free(req_conf); + NCONF_free(addext_conf); + BIO_free(addext_bio); + BIO_free(in); + BIO_free_all(out); + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(genctx); + sk_OPENSSL_STRING_free(pkeyopts); + sk_OPENSSL_STRING_free(sigopts); + lh_OPENSSL_STRING_doall(addexts, exts_cleanup); + lh_OPENSSL_STRING_free(addexts); +#ifndef OPENSSL_NO_ENGINE + ENGINE_free(gen_eng); +#endif + OPENSSL_free(keyalgstr); + X509_REQ_free(req); + X509_free(x509ss); + ASN1_INTEGER_free(serial); + release_engine(e); + if (passin != nofree_passin) + OPENSSL_free(passin); + if (passout != nofree_passout) + OPENSSL_free(passout); + return ret; +} + +static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int multirdn, + int attribs, unsigned long chtype) +{ + int ret = 0, i; + char no_prompt = 0; + STACK_OF(CONF_VALUE) *dn_sk, *attr_sk = NULL; + char *tmp, *dn_sect, *attr_sect; + + tmp = NCONF_get_string(req_conf, SECTION, PROMPT); + if (tmp == NULL) + ERR_clear_error(); + if ((tmp != NULL) && strcmp(tmp, "no") == 0) + no_prompt = 1; + + dn_sect = NCONF_get_string(req_conf, SECTION, DISTINGUISHED_NAME); + if (dn_sect == NULL) { + BIO_printf(bio_err, "unable to find '%s' in config\n", + DISTINGUISHED_NAME); + goto err; + } + dn_sk = NCONF_get_section(req_conf, dn_sect); + if (dn_sk == NULL) { + BIO_printf(bio_err, "unable to get '%s' section\n", dn_sect); + goto err; + } + + attr_sect = NCONF_get_string(req_conf, SECTION, ATTRIBUTES); + if (attr_sect == NULL) { + ERR_clear_error(); + attr_sk = NULL; + } else { + attr_sk = NCONF_get_section(req_conf, attr_sect); + if (attr_sk == NULL) { + BIO_printf(bio_err, "unable to get '%s' section\n", attr_sect); + goto err; + } + } + + /* setup version number */ + if (!X509_REQ_set_version(req, 0L)) + goto err; /* version 1 */ + + if (subj) + i = build_subject(req, subj, chtype, multirdn); + else if (no_prompt) + i = auto_info(req, dn_sk, attr_sk, attribs, chtype); + else + i = prompt_info(req, dn_sk, dn_sect, attr_sk, attr_sect, attribs, + chtype); + if (!i) + goto err; + + if (!X509_REQ_set_pubkey(req, pkey)) + goto err; + + ret = 1; + err: + return ret; +} + +/* + * subject is expected to be in the format /type0=value0/type1=value1/type2=... + * where characters may be escaped by \ + */ +static int build_subject(X509_REQ *req, const char *subject, unsigned long chtype, + int multirdn) +{ + X509_NAME *n; + + if ((n = parse_name(subject, chtype, multirdn)) == NULL) + return 0; + + if (!X509_REQ_set_subject_name(req, n)) { + X509_NAME_free(n); + return 0; + } + X509_NAME_free(n); + return 1; +} + +static int prompt_info(X509_REQ *req, + STACK_OF(CONF_VALUE) *dn_sk, const char *dn_sect, + STACK_OF(CONF_VALUE) *attr_sk, const char *attr_sect, + int attribs, unsigned long chtype) +{ + int i; + char *p, *q; + char buf[100]; + int nid, mval; + long n_min, n_max; + char *type, *value; + const char *def; + CONF_VALUE *v; + X509_NAME *subj; + subj = X509_REQ_get_subject_name(req); + + if (!batch) { + BIO_printf(bio_err, + "You are about to be asked to enter information that will be incorporated\n"); + BIO_printf(bio_err, "into your certificate request.\n"); + BIO_printf(bio_err, + "What you are about to enter is what is called a Distinguished Name or a DN.\n"); + BIO_printf(bio_err, + "There are quite a few fields but you can leave some blank\n"); + BIO_printf(bio_err, + "For some fields there will be a default value,\n"); + BIO_printf(bio_err, + "If you enter '.', the field will be left blank.\n"); + BIO_printf(bio_err, "-----\n"); + } + + if (sk_CONF_VALUE_num(dn_sk)) { + i = -1; + start: + for ( ; ; ) { + i++; + if (sk_CONF_VALUE_num(dn_sk) <= i) + break; + + v = sk_CONF_VALUE_value(dn_sk, i); + p = q = NULL; + type = v->name; + if (!check_end(type, "_min") || !check_end(type, "_max") || + !check_end(type, "_default") || !check_end(type, "_value")) + continue; + /* + * Skip past any leading X. X: X, etc to allow for multiple + * instances + */ + for (p = v->name; *p; p++) + if ((*p == ':') || (*p == ',') || (*p == '.')) { + p++; + if (*p) + type = p; + break; + } + if (*type == '+') { + mval = -1; + type++; + } else { + mval = 0; + } + /* If OBJ not recognised ignore it */ + if ((nid = OBJ_txt2nid(type)) == NID_undef) + goto start; + if (!join(buf, sizeof(buf), v->name, "_default", "Name")) + return 0; + if ((def = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) { + ERR_clear_error(); + def = ""; + } + + if (!join(buf, sizeof(buf), v->name, "_value", "Name")) + return 0; + if ((value = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) { + ERR_clear_error(); + value = NULL; + } + + if (!join(buf, sizeof(buf), v->name, "_min", "Name")) + return 0; + if (!NCONF_get_number(req_conf, dn_sect, buf, &n_min)) { + ERR_clear_error(); + n_min = -1; + } + + + if (!join(buf, sizeof(buf), v->name, "_max", "Name")) + return 0; + if (!NCONF_get_number(req_conf, dn_sect, buf, &n_max)) { + ERR_clear_error(); + n_max = -1; + } + + if (!add_DN_object(subj, v->value, def, value, nid, + n_min, n_max, chtype, mval)) + return 0; + } + if (X509_NAME_entry_count(subj) == 0) { + BIO_printf(bio_err, + "error, no objects specified in config file\n"); + return 0; + } + + if (attribs) { + if ((attr_sk != NULL) && (sk_CONF_VALUE_num(attr_sk) > 0) + && (!batch)) { + BIO_printf(bio_err, + "\nPlease enter the following 'extra' attributes\n"); + BIO_printf(bio_err, + "to be sent with your certificate request\n"); + } + + i = -1; + start2: + for ( ; ; ) { + i++; + if ((attr_sk == NULL) || (sk_CONF_VALUE_num(attr_sk) <= i)) + break; + + v = sk_CONF_VALUE_value(attr_sk, i); + type = v->name; + if ((nid = OBJ_txt2nid(type)) == NID_undef) + goto start2; + + if (!join(buf, sizeof(buf), type, "_default", "Name")) + return 0; + if ((def = NCONF_get_string(req_conf, attr_sect, buf)) + == NULL) { + ERR_clear_error(); + def = ""; + } + + if (!join(buf, sizeof(buf), type, "_value", "Name")) + return 0; + if ((value = NCONF_get_string(req_conf, attr_sect, buf)) + == NULL) { + ERR_clear_error(); + value = NULL; + } + + if (!join(buf, sizeof(buf), type,"_min", "Name")) + return 0; + if (!NCONF_get_number(req_conf, attr_sect, buf, &n_min)) { + ERR_clear_error(); + n_min = -1; + } + + if (!join(buf, sizeof(buf), type, "_max", "Name")) + return 0; + if (!NCONF_get_number(req_conf, attr_sect, buf, &n_max)) { + ERR_clear_error(); + n_max = -1; + } + + if (!add_attribute_object(req, + v->value, def, value, nid, n_min, + n_max, chtype)) + return 0; + } + } + } else { + BIO_printf(bio_err, "No template, please set one up.\n"); + return 0; + } + + return 1; + +} + +static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk, + STACK_OF(CONF_VALUE) *attr_sk, int attribs, + unsigned long chtype) +{ + int i, spec_char, plus_char; + char *p, *q; + char *type; + CONF_VALUE *v; + X509_NAME *subj; + + subj = X509_REQ_get_subject_name(req); + + for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) { + int mval; + v = sk_CONF_VALUE_value(dn_sk, i); + p = q = NULL; + type = v->name; + /* + * Skip past any leading X. X: X, etc to allow for multiple instances + */ + for (p = v->name; *p; p++) { +#ifndef CHARSET_EBCDIC + spec_char = ((*p == ':') || (*p == ',') || (*p == '.')); +#else + spec_char = ((*p == os_toascii[':']) || (*p == os_toascii[',']) + || (*p == os_toascii['.'])); +#endif + if (spec_char) { + p++; + if (*p) + type = p; + break; + } + } +#ifndef CHARSET_EBCDIC + plus_char = (*type == '+'); +#else + plus_char = (*type == os_toascii['+']); +#endif + if (plus_char) { + type++; + mval = -1; + } else { + mval = 0; + } + if (!X509_NAME_add_entry_by_txt(subj, type, chtype, + (unsigned char *)v->value, -1, -1, + mval)) + return 0; + + } + + if (!X509_NAME_entry_count(subj)) { + BIO_printf(bio_err, "error, no objects specified in config file\n"); + return 0; + } + if (attribs) { + for (i = 0; i < sk_CONF_VALUE_num(attr_sk); i++) { + v = sk_CONF_VALUE_value(attr_sk, i); + if (!X509_REQ_add1_attr_by_txt(req, v->name, chtype, + (unsigned char *)v->value, -1)) + return 0; + } + } + return 1; +} + +static int add_DN_object(X509_NAME *n, char *text, const char *def, + char *value, int nid, int n_min, int n_max, + unsigned long chtype, int mval) +{ + int ret = 0; + char buf[1024]; + + ret = build_data(text, def, value, n_min, n_max, buf, sizeof(buf), + "DN value", "DN default"); + if ((ret == 0) || (ret == 1)) + return ret; + ret = 1; + + if (!X509_NAME_add_entry_by_NID(n, nid, chtype, + (unsigned char *)buf, -1, -1, mval)) + ret = 0; + + return ret; +} + +static int add_attribute_object(X509_REQ *req, char *text, const char *def, + char *value, int nid, int n_min, + int n_max, unsigned long chtype) +{ + int ret = 0; + char buf[1024]; + + ret = build_data(text, def, value, n_min, n_max, buf, sizeof(buf), + "Attribute value", "Attribute default"); + if ((ret == 0) || (ret == 1)) + return ret; + ret = 1; + + if (!X509_REQ_add1_attr_by_NID(req, nid, chtype, + (unsigned char *)buf, -1)) { + BIO_printf(bio_err, "Error adding attribute\n"); + ERR_print_errors(bio_err); + ret = 0; + } + + return ret; +} + + +static int build_data(char *text, const char *def, + char *value, int n_min, int n_max, + char *buf, const int buf_size, + const char *desc1, const char *desc2 + ) +{ + int i; + start: + if (!batch) + BIO_printf(bio_err, "%s [%s]:", text, def); + (void)BIO_flush(bio_err); + if (value != NULL) { + if (!join(buf, buf_size, value, "\n", desc1)) + return 0; + BIO_printf(bio_err, "%s\n", value); + } else { + buf[0] = '\0'; + if (!batch) { + if (!fgets(buf, buf_size, stdin)) + return 0; + } else { + buf[0] = '\n'; + buf[1] = '\0'; + } + } + + if (buf[0] == '\0') + return 0; + if (buf[0] == '\n') { + if ((def == NULL) || (def[0] == '\0')) + return 1; + if (!join(buf, buf_size, def, "\n", desc2)) + return 0; + } else if ((buf[0] == '.') && (buf[1] == '\n')) { + return 1; + } + + i = strlen(buf); + if (buf[i - 1] != '\n') { + BIO_printf(bio_err, "weird input :-(\n"); + return 0; + } + buf[--i] = '\0'; +#ifdef CHARSET_EBCDIC + ebcdic2ascii(buf, buf, i); +#endif + if (!req_check_len(i, n_min, n_max)) { + if (batch || value) + return 0; + goto start; + } + return 2; +} + +static int req_check_len(int len, int n_min, int n_max) +{ + if ((n_min > 0) && (len < n_min)) { + BIO_printf(bio_err, + "string is too short, it needs to be at least %d bytes long\n", + n_min); + return 0; + } + if ((n_max >= 0) && (len > n_max)) { + BIO_printf(bio_err, + "string is too long, it needs to be no more than %d bytes long\n", + n_max); + return 0; + } + return 1; +} + +/* Check if the end of a string matches 'end' */ +static int check_end(const char *str, const char *end) +{ + size_t elen, slen; + const char *tmp; + + elen = strlen(end); + slen = strlen(str); + if (elen > slen) + return 1; + tmp = str + slen - elen; + return strcmp(tmp, end); +} + +/* + * Merge the two strings together into the result buffer checking for + * overflow and producing an error message if there is. + */ +static int join(char buf[], size_t buf_size, const char *name, + const char *tail, const char *desc) +{ + const size_t name_len = strlen(name), tail_len = strlen(tail); + + if (name_len + tail_len + 1 > buf_size) { + BIO_printf(bio_err, "%s '%s' too long\n", desc, name); + return 0; + } + memcpy(buf, name, name_len); + memcpy(buf + name_len, tail, tail_len + 1); + return 1; +} + +static EVP_PKEY_CTX *set_keygen_ctx(const char *gstr, + int *pkey_type, long *pkeylen, + char **palgnam, ENGINE *keygen_engine) +{ + EVP_PKEY_CTX *gctx = NULL; + EVP_PKEY *param = NULL; + long keylen = -1; + BIO *pbio = NULL; + const char *paramfile = NULL; + + if (gstr == NULL) { + *pkey_type = EVP_PKEY_RSA; + keylen = *pkeylen; + } else if (gstr[0] >= '0' && gstr[0] <= '9') { + *pkey_type = EVP_PKEY_RSA; + keylen = atol(gstr); + *pkeylen = keylen; + } else if (strncmp(gstr, "param:", 6) == 0) { + paramfile = gstr + 6; + } else { + const char *p = strchr(gstr, ':'); + int len; + ENGINE *tmpeng; + const EVP_PKEY_ASN1_METHOD *ameth; + + if (p != NULL) + len = p - gstr; + else + len = strlen(gstr); + /* + * The lookup of a the string will cover all engines so keep a note + * of the implementation. + */ + + ameth = EVP_PKEY_asn1_find_str(&tmpeng, gstr, len); + + if (ameth == NULL) { + BIO_printf(bio_err, "Unknown algorithm %.*s\n", len, gstr); + return NULL; + } + + EVP_PKEY_asn1_get0_info(NULL, pkey_type, NULL, NULL, NULL, ameth); +#ifndef OPENSSL_NO_ENGINE + ENGINE_finish(tmpeng); +#endif + if (*pkey_type == EVP_PKEY_RSA) { + if (p != NULL) { + keylen = atol(p + 1); + *pkeylen = keylen; + } else { + keylen = *pkeylen; + } + } else if (p != NULL) { + paramfile = p + 1; + } + } + + if (paramfile != NULL) { + pbio = BIO_new_file(paramfile, "r"); + if (pbio == NULL) { + BIO_printf(bio_err, "Can't open parameter file %s\n", paramfile); + return NULL; + } + param = PEM_read_bio_Parameters(pbio, NULL); + + if (param == NULL) { + X509 *x; + + (void)BIO_reset(pbio); + x = PEM_read_bio_X509(pbio, NULL, NULL, NULL); + if (x != NULL) { + param = X509_get_pubkey(x); + X509_free(x); + } + } + + BIO_free(pbio); + + if (param == NULL) { + BIO_printf(bio_err, "Error reading parameter file %s\n", paramfile); + return NULL; + } + if (*pkey_type == -1) { + *pkey_type = EVP_PKEY_id(param); + } else if (*pkey_type != EVP_PKEY_base_id(param)) { + BIO_printf(bio_err, "Key Type does not match parameters\n"); + EVP_PKEY_free(param); + return NULL; + } + } + + if (palgnam != NULL) { + const EVP_PKEY_ASN1_METHOD *ameth; + ENGINE *tmpeng; + const char *anam; + + ameth = EVP_PKEY_asn1_find(&tmpeng, *pkey_type); + if (ameth == NULL) { + BIO_puts(bio_err, "Internal error: can't find key algorithm\n"); + return NULL; + } + EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL, &anam, ameth); + *palgnam = OPENSSL_strdup(anam); +#ifndef OPENSSL_NO_ENGINE + ENGINE_finish(tmpeng); +#endif + } + + if (param != NULL) { + gctx = EVP_PKEY_CTX_new(param, keygen_engine); + *pkeylen = EVP_PKEY_bits(param); + EVP_PKEY_free(param); + } else { + gctx = EVP_PKEY_CTX_new_id(*pkey_type, keygen_engine); + } + + if (gctx == NULL) { + BIO_puts(bio_err, "Error allocating keygen context\n"); + ERR_print_errors(bio_err); + return NULL; + } + + if (EVP_PKEY_keygen_init(gctx) <= 0) { + BIO_puts(bio_err, "Error initializing keygen context\n"); + ERR_print_errors(bio_err); + EVP_PKEY_CTX_free(gctx); + return NULL; + } +#ifndef OPENSSL_NO_RSA + if ((*pkey_type == EVP_PKEY_RSA) && (keylen != -1)) { + if (EVP_PKEY_CTX_set_rsa_keygen_bits(gctx, keylen) <= 0) { + BIO_puts(bio_err, "Error setting RSA keysize\n"); + ERR_print_errors(bio_err); + EVP_PKEY_CTX_free(gctx); + return NULL; + } + } +#endif + + return gctx; +} + +static int genpkey_cb(EVP_PKEY_CTX *ctx) +{ + char c = '*'; + BIO *b = EVP_PKEY_CTX_get_app_data(ctx); + int p; + p = EVP_PKEY_CTX_get_keygen_info(ctx, 0); + if (p == 0) + c = '.'; + if (p == 1) + c = '+'; + if (p == 2) + c = '*'; + if (p == 3) + c = '\n'; + BIO_write(b, &c, 1); + (void)BIO_flush(b); + return 1; +} + +static int do_sign_init(EVP_MD_CTX *ctx, EVP_PKEY *pkey, + const EVP_MD *md, STACK_OF(OPENSSL_STRING) *sigopts) +{ + EVP_PKEY_CTX *pkctx = NULL; + int i, def_nid; + + if (ctx == NULL) + return 0; + /* + * EVP_PKEY_get_default_digest_nid() returns 2 if the digest is mandatory + * for this algorithm. + */ + if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) == 2 + && def_nid == NID_undef) { + /* The signing algorithm requires there to be no digest */ + md = NULL; + } + if (!EVP_DigestSignInit(ctx, &pkctx, md, NULL, pkey)) + return 0; + for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) { + char *sigopt = sk_OPENSSL_STRING_value(sigopts, i); + if (pkey_ctrl_string(pkctx, sigopt) <= 0) { + BIO_printf(bio_err, "parameter error \"%s\"\n", sigopt); + ERR_print_errors(bio_err); + return 0; + } + } + return 1; +} + +int do_X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md, + STACK_OF(OPENSSL_STRING) *sigopts) +{ + int rv; + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); + + rv = do_sign_init(mctx, pkey, md, sigopts); + if (rv > 0) + rv = X509_sign_ctx(x, mctx); + EVP_MD_CTX_free(mctx); + return rv > 0 ? 1 : 0; +} + +int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md, + STACK_OF(OPENSSL_STRING) *sigopts) +{ + int rv; + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); + rv = do_sign_init(mctx, pkey, md, sigopts); + if (rv > 0) + rv = X509_REQ_sign_ctx(x, mctx); + EVP_MD_CTX_free(mctx); + return rv > 0 ? 1 : 0; +} + +int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md, + STACK_OF(OPENSSL_STRING) *sigopts) +{ + int rv; + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); + rv = do_sign_init(mctx, pkey, md, sigopts); + if (rv > 0) + rv = X509_CRL_sign_ctx(x, mctx); + EVP_MD_CTX_free(mctx); + return rv > 0 ? 1 : 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/req.pem b/trunk/3rdparty/openssl-1.1-fit/apps/req.pem new file mode 100644 index 000000000..5537df601 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/req.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBlzCCAVcCAQAwXjELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUx +ITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEXMBUGA1UEAxMORXJp +YyB0aGUgWW91bmcwge8wgaYGBSsOAwIMMIGcAkEA+ZiKEvZmc9MtnaFZh4NiZ3oZ +S4J1PHvPrm9MXj5ntVheDPkdmBDTncyaGAJcMjwsyB/GvLDGd6yGCw/8eF+09wIV +AK3VagOxGd/Q4Af5NbxR5FB7CXEjAkA2t/q7HgVLi0KeKvcDG8BRl3wuy7bCvpjg +tWiJc/tpvcuzeuAayH89UofjAGueKjXDADiRffvSdhrNw5dkqdqlA0QAAkEAtUSo +84OekjitKGVjxLu0HvXck29pu+foad53vPKXAsuJdACj88BPqZ91Y9PIJf1GUh38 +CuiHWi7z3cEDfZCyCKAAMAkGBSsOAwIbBQADLwAwLAIUTg8amKVBE9oqC5B75dDQ +Chy3LdQCFHKodGEj3LjuTzdm/RTe2KZL9Uzf +-----END CERTIFICATE REQUEST----- diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/rsa.c b/trunk/3rdparty/openssl-1.1-fit/apps/rsa.c new file mode 100644 index 000000000..fdd02dce3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/rsa.c @@ -0,0 +1,316 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#ifdef OPENSSL_NO_RSA +NON_EMPTY_TRANSLATION_UNIT +#else + +# include +# include +# include +# include +# include "apps.h" +# include "progs.h" +# include +# include +# include +# include +# include +# include +# include + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_IN, OPT_OUT, + OPT_PUBIN, OPT_PUBOUT, OPT_PASSOUT, OPT_PASSIN, + OPT_RSAPUBKEY_IN, OPT_RSAPUBKEY_OUT, + /* Do not change the order here; see case statements below */ + OPT_PVK_NONE, OPT_PVK_WEAK, OPT_PVK_STRONG, + OPT_NOOUT, OPT_TEXT, OPT_MODULUS, OPT_CHECK, OPT_CIPHER +} OPTION_CHOICE; + +const OPTIONS rsa_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"inform", OPT_INFORM, 'f', "Input format, one of DER PEM"}, + {"outform", OPT_OUTFORM, 'f', "Output format, one of DER PEM PVK"}, + {"in", OPT_IN, 's', "Input file"}, + {"out", OPT_OUT, '>', "Output file"}, + {"pubin", OPT_PUBIN, '-', "Expect a public key in input file"}, + {"pubout", OPT_PUBOUT, '-', "Output a public key"}, + {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"RSAPublicKey_in", OPT_RSAPUBKEY_IN, '-', "Input is an RSAPublicKey"}, + {"RSAPublicKey_out", OPT_RSAPUBKEY_OUT, '-', "Output is an RSAPublicKey"}, + {"noout", OPT_NOOUT, '-', "Don't print key out"}, + {"text", OPT_TEXT, '-', "Print the key in text"}, + {"modulus", OPT_MODULUS, '-', "Print the RSA key modulus"}, + {"check", OPT_CHECK, '-', "Verify key consistency"}, + {"", OPT_CIPHER, '-', "Any supported cipher"}, +# if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4) + {"pvk-strong", OPT_PVK_STRONG, '-', "Enable 'Strong' PVK encoding level (default)"}, + {"pvk-weak", OPT_PVK_WEAK, '-', "Enable 'Weak' PVK encoding level"}, + {"pvk-none", OPT_PVK_NONE, '-', "Don't enforce PVK encoding"}, +# endif +# ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +# endif + {NULL} +}; + +int rsa_main(int argc, char **argv) +{ + ENGINE *e = NULL; + BIO *out = NULL; + RSA *rsa = NULL; + const EVP_CIPHER *enc = NULL; + char *infile = NULL, *outfile = NULL, *prog; + char *passin = NULL, *passout = NULL, *passinarg = NULL, *passoutarg = NULL; + int i, private = 0; + int informat = FORMAT_PEM, outformat = FORMAT_PEM, text = 0, check = 0; + int noout = 0, modulus = 0, pubin = 0, pubout = 0, ret = 1; +# if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4) + int pvk_encr = 2; +# endif + OPTION_CHOICE o; + + prog = opt_init(argc, argv, rsa_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(rsa_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &outformat)) + goto opthelp; + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_PASSOUT: + passoutarg = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_PUBIN: + pubin = 1; + break; + case OPT_PUBOUT: + pubout = 1; + break; + case OPT_RSAPUBKEY_IN: + pubin = 2; + break; + case OPT_RSAPUBKEY_OUT: + pubout = 2; + break; + case OPT_PVK_STRONG: /* pvk_encr:= 2 */ + case OPT_PVK_WEAK: /* pvk_encr:= 1 */ + case OPT_PVK_NONE: /* pvk_encr:= 0 */ +# if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4) + pvk_encr = (o - OPT_PVK_NONE); +# endif + break; + case OPT_NOOUT: + noout = 1; + break; + case OPT_TEXT: + text = 1; + break; + case OPT_MODULUS: + modulus = 1; + break; + case OPT_CHECK: + check = 1; + break; + case OPT_CIPHER: + if (!opt_cipher(opt_unknown(), &enc)) + goto opthelp; + break; + } + } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + + private = (text && !pubin) || (!pubout && !noout) ? 1 : 0; + + if (!app_passwd(passinarg, passoutarg, &passin, &passout)) { + BIO_printf(bio_err, "Error getting passwords\n"); + goto end; + } + if (check && pubin) { + BIO_printf(bio_err, "Only private keys can be checked\n"); + goto end; + } + + { + EVP_PKEY *pkey; + + if (pubin) { + int tmpformat = -1; + if (pubin == 2) { + if (informat == FORMAT_PEM) + tmpformat = FORMAT_PEMRSA; + else if (informat == FORMAT_ASN1) + tmpformat = FORMAT_ASN1RSA; + } else { + tmpformat = informat; + } + + pkey = load_pubkey(infile, tmpformat, 1, passin, e, "Public Key"); + } else { + pkey = load_key(infile, informat, 1, passin, e, "Private Key"); + } + + if (pkey != NULL) + rsa = EVP_PKEY_get1_RSA(pkey); + EVP_PKEY_free(pkey); + } + + if (rsa == NULL) { + ERR_print_errors(bio_err); + goto end; + } + + out = bio_open_owner(outfile, outformat, private); + if (out == NULL) + goto end; + + if (text) { + assert(pubin || private); + if (!RSA_print(out, rsa, 0)) { + perror(outfile); + ERR_print_errors(bio_err); + goto end; + } + } + + if (modulus) { + const BIGNUM *n; + RSA_get0_key(rsa, &n, NULL, NULL); + BIO_printf(out, "Modulus="); + BN_print(out, n); + BIO_printf(out, "\n"); + } + + if (check) { + int r = RSA_check_key_ex(rsa, NULL); + + if (r == 1) { + BIO_printf(out, "RSA key ok\n"); + } else if (r == 0) { + unsigned long err; + + while ((err = ERR_peek_error()) != 0 && + ERR_GET_LIB(err) == ERR_LIB_RSA && + ERR_GET_FUNC(err) == RSA_F_RSA_CHECK_KEY_EX && + ERR_GET_REASON(err) != ERR_R_MALLOC_FAILURE) { + BIO_printf(out, "RSA key error: %s\n", + ERR_reason_error_string(err)); + ERR_get_error(); /* remove err from error stack */ + } + } else if (r == -1) { + ERR_print_errors(bio_err); + goto end; + } + } + + if (noout) { + ret = 0; + goto end; + } + BIO_printf(bio_err, "writing RSA key\n"); + if (outformat == FORMAT_ASN1) { + if (pubout || pubin) { + if (pubout == 2) + i = i2d_RSAPublicKey_bio(out, rsa); + else + i = i2d_RSA_PUBKEY_bio(out, rsa); + } else { + assert(private); + i = i2d_RSAPrivateKey_bio(out, rsa); + } + } else if (outformat == FORMAT_PEM) { + if (pubout || pubin) { + if (pubout == 2) + i = PEM_write_bio_RSAPublicKey(out, rsa); + else + i = PEM_write_bio_RSA_PUBKEY(out, rsa); + } else { + assert(private); + i = PEM_write_bio_RSAPrivateKey(out, rsa, + enc, NULL, 0, NULL, passout); + } +# ifndef OPENSSL_NO_DSA + } else if (outformat == FORMAT_MSBLOB || outformat == FORMAT_PVK) { + EVP_PKEY *pk; + pk = EVP_PKEY_new(); + if (pk == NULL) + goto end; + + EVP_PKEY_set1_RSA(pk, rsa); + if (outformat == FORMAT_PVK) { + if (pubin) { + BIO_printf(bio_err, "PVK form impossible with public key input\n"); + EVP_PKEY_free(pk); + goto end; + } + assert(private); +# ifdef OPENSSL_NO_RC4 + BIO_printf(bio_err, "PVK format not supported\n"); + EVP_PKEY_free(pk); + goto end; +# else + i = i2b_PVK_bio(out, pk, pvk_encr, 0, passout); +# endif + } else if (pubin || pubout) { + i = i2b_PublicKey_bio(out, pk); + } else { + assert(private); + i = i2b_PrivateKey_bio(out, pk); + } + EVP_PKEY_free(pk); +# endif + } else { + BIO_printf(bio_err, "bad output format specified for outfile\n"); + goto end; + } + if (i <= 0) { + BIO_printf(bio_err, "unable to write key\n"); + ERR_print_errors(bio_err); + } else { + ret = 0; + } + end: + release_engine(e); + BIO_free_all(out); + RSA_free(rsa); + OPENSSL_free(passin); + OPENSSL_free(passout); + return ret; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/rsa8192.pem b/trunk/3rdparty/openssl-1.1-fit/apps/rsa8192.pem new file mode 100644 index 000000000..946a6e543 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/rsa8192.pem @@ -0,0 +1,101 @@ +-----BEGIN RSA PRIVATE KEY----- + +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 +-----END RSA PRIVATE KEY----- + diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/rsautl.c b/trunk/3rdparty/openssl-1.1-fit/apps/rsautl.c new file mode 100644 index 000000000..5da8504d3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/rsautl.c @@ -0,0 +1,282 @@ +/* + * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#ifdef OPENSSL_NO_RSA +NON_EMPTY_TRANSLATION_UNIT +#else + +# include "apps.h" +# include "progs.h" +# include +# include +# include +# include + +# define RSA_SIGN 1 +# define RSA_VERIFY 2 +# define RSA_ENCRYPT 3 +# define RSA_DECRYPT 4 + +# define KEY_PRIVKEY 1 +# define KEY_PUBKEY 2 +# define KEY_CERT 3 + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_ENGINE, OPT_IN, OPT_OUT, OPT_ASN1PARSE, OPT_HEXDUMP, + OPT_RAW, OPT_OAEP, OPT_SSL, OPT_PKCS, OPT_X931, + OPT_SIGN, OPT_VERIFY, OPT_REV, OPT_ENCRYPT, OPT_DECRYPT, + OPT_PUBIN, OPT_CERTIN, OPT_INKEY, OPT_PASSIN, OPT_KEYFORM, + OPT_R_ENUM +} OPTION_CHOICE; + +const OPTIONS rsautl_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"in", OPT_IN, '<', "Input file"}, + {"out", OPT_OUT, '>', "Output file"}, + {"inkey", OPT_INKEY, 's', "Input key"}, + {"keyform", OPT_KEYFORM, 'E', "Private key format - default PEM"}, + {"pubin", OPT_PUBIN, '-', "Input is an RSA public"}, + {"certin", OPT_CERTIN, '-', "Input is a cert carrying an RSA public key"}, + {"ssl", OPT_SSL, '-', "Use SSL v2 padding"}, + {"raw", OPT_RAW, '-', "Use no padding"}, + {"pkcs", OPT_PKCS, '-', "Use PKCS#1 v1.5 padding (default)"}, + {"oaep", OPT_OAEP, '-', "Use PKCS#1 OAEP"}, + {"sign", OPT_SIGN, '-', "Sign with private key"}, + {"verify", OPT_VERIFY, '-', "Verify with public key"}, + {"asn1parse", OPT_ASN1PARSE, '-', + "Run output through asn1parse; useful with -verify"}, + {"hexdump", OPT_HEXDUMP, '-', "Hex dump output"}, + {"x931", OPT_X931, '-', "Use ANSI X9.31 padding"}, + {"rev", OPT_REV, '-', "Reverse the order of the input buffer"}, + {"encrypt", OPT_ENCRYPT, '-', "Encrypt with public key"}, + {"decrypt", OPT_DECRYPT, '-', "Decrypt with private key"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + OPT_R_OPTIONS, +# ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +# endif + {NULL} +}; + +int rsautl_main(int argc, char **argv) +{ + BIO *in = NULL, *out = NULL; + ENGINE *e = NULL; + EVP_PKEY *pkey = NULL; + RSA *rsa = NULL; + X509 *x; + char *infile = NULL, *outfile = NULL, *keyfile = NULL; + char *passinarg = NULL, *passin = NULL, *prog; + char rsa_mode = RSA_VERIFY, key_type = KEY_PRIVKEY; + unsigned char *rsa_in = NULL, *rsa_out = NULL, pad = RSA_PKCS1_PADDING; + int rsa_inlen, keyformat = FORMAT_PEM, keysize, ret = 1; + int rsa_outlen = 0, hexdump = 0, asn1parse = 0, need_priv = 0, rev = 0; + OPTION_CHOICE o; + + prog = opt_init(argc, argv, rsautl_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(rsautl_options); + ret = 0; + goto end; + case OPT_KEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_PDE, &keyformat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_ASN1PARSE: + asn1parse = 1; + break; + case OPT_HEXDUMP: + hexdump = 1; + break; + case OPT_RAW: + pad = RSA_NO_PADDING; + break; + case OPT_OAEP: + pad = RSA_PKCS1_OAEP_PADDING; + break; + case OPT_SSL: + pad = RSA_SSLV23_PADDING; + break; + case OPT_PKCS: + pad = RSA_PKCS1_PADDING; + break; + case OPT_X931: + pad = RSA_X931_PADDING; + break; + case OPT_SIGN: + rsa_mode = RSA_SIGN; + need_priv = 1; + break; + case OPT_VERIFY: + rsa_mode = RSA_VERIFY; + break; + case OPT_REV: + rev = 1; + break; + case OPT_ENCRYPT: + rsa_mode = RSA_ENCRYPT; + break; + case OPT_DECRYPT: + rsa_mode = RSA_DECRYPT; + need_priv = 1; + break; + case OPT_PUBIN: + key_type = KEY_PUBKEY; + break; + case OPT_CERTIN: + key_type = KEY_CERT; + break; + case OPT_INKEY: + keyfile = opt_arg(); + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + } + } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + + if (need_priv && (key_type != KEY_PRIVKEY)) { + BIO_printf(bio_err, "A private key is needed for this operation\n"); + goto end; + } + + if (!app_passwd(passinarg, NULL, &passin, NULL)) { + BIO_printf(bio_err, "Error getting password\n"); + goto end; + } + + switch (key_type) { + case KEY_PRIVKEY: + pkey = load_key(keyfile, keyformat, 0, passin, e, "Private Key"); + break; + + case KEY_PUBKEY: + pkey = load_pubkey(keyfile, keyformat, 0, NULL, e, "Public Key"); + break; + + case KEY_CERT: + x = load_cert(keyfile, keyformat, "Certificate"); + if (x) { + pkey = X509_get_pubkey(x); + X509_free(x); + } + break; + } + + if (pkey == NULL) + return 1; + + rsa = EVP_PKEY_get1_RSA(pkey); + EVP_PKEY_free(pkey); + + if (rsa == NULL) { + BIO_printf(bio_err, "Error getting RSA key\n"); + ERR_print_errors(bio_err); + goto end; + } + + in = bio_open_default(infile, 'r', FORMAT_BINARY); + if (in == NULL) + goto end; + out = bio_open_default(outfile, 'w', FORMAT_BINARY); + if (out == NULL) + goto end; + + keysize = RSA_size(rsa); + + rsa_in = app_malloc(keysize * 2, "hold rsa key"); + rsa_out = app_malloc(keysize, "output rsa key"); + + /* Read the input data */ + rsa_inlen = BIO_read(in, rsa_in, keysize * 2); + if (rsa_inlen < 0) { + BIO_printf(bio_err, "Error reading input Data\n"); + goto end; + } + if (rev) { + int i; + unsigned char ctmp; + for (i = 0; i < rsa_inlen / 2; i++) { + ctmp = rsa_in[i]; + rsa_in[i] = rsa_in[rsa_inlen - 1 - i]; + rsa_in[rsa_inlen - 1 - i] = ctmp; + } + } + switch (rsa_mode) { + + case RSA_VERIFY: + rsa_outlen = RSA_public_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad); + break; + + case RSA_SIGN: + rsa_outlen = + RSA_private_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad); + break; + + case RSA_ENCRYPT: + rsa_outlen = RSA_public_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad); + break; + + case RSA_DECRYPT: + rsa_outlen = + RSA_private_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad); + break; + } + + if (rsa_outlen < 0) { + BIO_printf(bio_err, "RSA operation error\n"); + ERR_print_errors(bio_err); + goto end; + } + ret = 0; + if (asn1parse) { + if (!ASN1_parse_dump(out, rsa_out, rsa_outlen, 1, -1)) { + ERR_print_errors(bio_err); + } + } else if (hexdump) { + BIO_dump(out, (char *)rsa_out, rsa_outlen); + } else { + BIO_write(out, rsa_out, rsa_outlen); + } + end: + RSA_free(rsa); + release_engine(e); + BIO_free(in); + BIO_free_all(out); + OPENSSL_free(rsa_in); + OPENSSL_free(rsa_out); + OPENSSL_free(passin); + return ret; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/s1024key.pem b/trunk/3rdparty/openssl-1.1-fit/apps/s1024key.pem new file mode 100644 index 000000000..19e040357 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/s1024key.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQCzEfU8E+ZGTGtHXV5XhvM2Lg32fXUIjydXb34BGVPX6oN7+aNV +S9eWayvW/+9/vUb0aCqilJrpFesgItV2T8VhhjOE++XUz46uNpcMU7wHMEAXUufP +pztpFm8ZEk2tFKvadkSSoN8lb11juvZVkSkPlB65pFhSe4QKSp6J4HrkYwIDAQAB +AoGBAKy8jvb0Lzby8q11yNLf7+78wCVdYi7ugMHcYA1JVFK8+zb1WfSm44FLQo/0 +dSChAjgz36TTexeLODPYxleJndjVcOMVzsLJjSM8dLpXsTS4FCeMbhw2s2u+xqKY +bbPWfk+HOTyJjfnkcC5Nbg44eOmruq0gSmBeUXVM5UntlTnxAkEA7TGCA3h7kx5E +Bl4zl2pc3gPAGt+dyfk5Po9mGJUUXhF5p2zueGmYWW74TmOWB1kzt4QRdYMzFePq +zfDNXEa1CwJBAMFErdY0xp0UJ13WwBbUTk8rujqQdHtjw0klhpbuKkjxu2hN0wwM +6p0D9qxF7JHaghqVRI0fAW/EE0OzdHMR9QkCQQDNR26dMFXKsoPu+vItljj/UEGf +QG7gERiQ4yxaFBPHgdpGo0kT31eh9x9hQGDkxTe0GNG/YSgCRvm8+C3TMcKXAkBD +dhGn36wkUFCddMSAM4NSJ1VN8/Z0y5HzCmI8dM3VwGtGMUQlxKxwOl30LEQzdS5M +0SWojNYXiT2gOBfBwtbhAkEAhafl5QEOIgUz+XazS/IlZ8goNKdDVfYgK3mHHjvv +nY5G+AuGebdNkXJr4KSWxDcN+C2i47zuj4QXA16MAOandA== +-----END RSA PRIVATE KEY----- diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/s1024req.pem b/trunk/3rdparty/openssl-1.1-fit/apps/s1024req.pem new file mode 100644 index 000000000..bb75e7eeb --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/s1024req.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBojCCAQsCAQAwZDELMAkGA1UEBhMCQVUxEzARBgNVBAgTClF1ZWVuc2xhbmQx +GjAYBgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMSQwIgYDVQQDExtTZXJ2ZXIgdGVz +dCBjZXJ0ICgxMDI0IGJpdCkwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALMR +9TwT5kZMa0ddXleG8zYuDfZ9dQiPJ1dvfgEZU9fqg3v5o1VL15ZrK9b/73+9RvRo +KqKUmukV6yAi1XZPxWGGM4T75dTPjq42lwxTvAcwQBdS58+nO2kWbxkSTa0Uq9p2 +RJKg3yVvXWO69lWRKQ+UHrmkWFJ7hApKnongeuRjAgMBAAEwDQYJKoZIhvcNAQEE +BQADgYEAStHlk4pBbwiNeQ2/PKTPPXzITYC8Gn0XMbrU94e/6JIKiO7aArq9Espq +nrBSvC14dHcNl6NNvnkEKdQ7hAkcACfBbnOXA/oQvMBd4GD78cH3k0jVDoVUEjil +frLfWlckW6WzpTktt0ZPDdAjJCmKVh0ABHimi7Bo9FC3wIGIe5M= +-----END CERTIFICATE REQUEST----- diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/s512-key.pem b/trunk/3rdparty/openssl-1.1-fit/apps/s512-key.pem new file mode 100644 index 000000000..0e3ff2d37 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/s512-key.pem @@ -0,0 +1,9 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIBPAIBAAJBAJ+zw4Qnlf8SMVIPFe9GEcStgOY2Ww/dgNdhjeD8ckUJNP5VZkVD +TGiXav6ooKXfX3j/7tdkuD8Ey2//Kv7+ue0CAwEAAQJAN6W31vDEP2DjdqhzCDDu +OA4NACqoiFqyblo7yc2tM4h4xMbC3Yx5UKMN9ZkCtX0gzrz6DyF47bdKcWBzNWCj +gQIhANEoojVt7hq+SQ6MCN6FTAysGgQf56Q3TYoJMoWvdiXVAiEAw3e3rc+VJpOz +rHuDo6bgpjUAAXM+v3fcpsfZSNO6V7kCIQCtbVjanpUwvZkMI9by02oUk9taki3b +PzPfAfNPYAbCJQIhAJXNQDWyqwn/lGmR11cqY2y9nZ1+5w3yHGatLrcDnQHxAiEA +vnlEGo8K85u+KwIOimM48ZG8oTk7iFdkqLJR1utT3aU= +-----END RSA PRIVATE KEY----- diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/s512-req.pem b/trunk/3rdparty/openssl-1.1-fit/apps/s512-req.pem new file mode 100644 index 000000000..ea314be55 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/s512-req.pem @@ -0,0 +1,8 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBGzCBxgIBADBjMQswCQYDVQQGEwJBVTETMBEGA1UECBMKUXVlZW5zbGFuZDEa +MBgGA1UEChMRQ3J5cHRTb2Z0IFB0eSBMdGQxIzAhBgNVBAMTGlNlcnZlciB0ZXN0 +IGNlcnQgKDUxMiBiaXQpMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJ+zw4Qnlf8S +MVIPFe9GEcStgOY2Ww/dgNdhjeD8ckUJNP5VZkVDTGiXav6ooKXfX3j/7tdkuD8E +y2//Kv7+ue0CAwEAATANBgkqhkiG9w0BAQQFAANBAAB+uQi+qwn6qRSHB8EUTvsm +5TNTHzYDeN39nyIbZNX2s0se3Srn2Bxft5YCwD3moFZ9QoyDHxE0h6qLX5yjD+8= +-----END CERTIFICATE REQUEST----- diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/s_apps.h b/trunk/3rdparty/openssl-1.1-fit/apps/s_apps.h new file mode 100644 index 000000000..0a3bc9628 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/s_apps.h @@ -0,0 +1,89 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) +# include +#endif + +#if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32) +# define _kbhit kbhit +#endif + +#define PORT "4433" +#define PROTOCOL "tcp" + +typedef int (*do_server_cb)(int s, int stype, int prot, unsigned char *context); +int do_server(int *accept_sock, const char *host, const char *port, + int family, int type, int protocol, do_server_cb cb, + unsigned char *context, int naccept, BIO *bio_s_out); +#ifdef HEADER_X509_H +int verify_callback(int ok, X509_STORE_CTX *ctx); +#endif +#ifdef HEADER_SSL_H +int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file); +int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key, + STACK_OF(X509) *chain, int build_chain); +int ssl_print_sigalgs(BIO *out, SSL *s); +int ssl_print_point_formats(BIO *out, SSL *s); +int ssl_print_groups(BIO *out, SSL *s, int noshared); +#endif +int ssl_print_tmp_key(BIO *out, SSL *s); +int init_client(int *sock, const char *host, const char *port, + const char *bindhost, const char *bindport, + int family, int type, int protocol); +int should_retry(int i); + +long bio_dump_callback(BIO *bio, int cmd, const char *argp, + int argi, long argl, long ret); + +#ifdef HEADER_SSL_H +void apps_ssl_info_callback(const SSL *s, int where, int ret); +void msg_cb(int write_p, int version, int content_type, const void *buf, + size_t len, SSL *ssl, void *arg); +void tlsext_cb(SSL *s, int client_server, int type, const unsigned char *data, + int len, void *arg); +#endif + +int generate_cookie_callback(SSL *ssl, unsigned char *cookie, + unsigned int *cookie_len); +int verify_cookie_callback(SSL *ssl, const unsigned char *cookie, + unsigned int cookie_len); + +#ifdef __VMS /* 31 char symbol name limit */ +# define generate_stateless_cookie_callback generate_stateless_cookie_cb +# define verify_stateless_cookie_callback verify_stateless_cookie_cb +#endif + +int generate_stateless_cookie_callback(SSL *ssl, unsigned char *cookie, + size_t *cookie_len); +int verify_stateless_cookie_callback(SSL *ssl, const unsigned char *cookie, + size_t cookie_len); + +typedef struct ssl_excert_st SSL_EXCERT; + +void ssl_ctx_set_excert(SSL_CTX *ctx, SSL_EXCERT *exc); +void ssl_excert_free(SSL_EXCERT *exc); +int args_excert(int option, SSL_EXCERT **pexc); +int load_excert(SSL_EXCERT **pexc); +void print_verify_detail(SSL *s, BIO *bio); +void print_ssl_summary(SSL *s); +#ifdef HEADER_SSL_H +int config_ctx(SSL_CONF_CTX *cctx, STACK_OF(OPENSSL_STRING) *str, SSL_CTX *ctx); +int ssl_ctx_add_crls(SSL_CTX *ctx, STACK_OF(X509_CRL) *crls, + int crl_download); +int ssl_load_stores(SSL_CTX *ctx, const char *vfyCApath, + const char *vfyCAfile, const char *chCApath, + const char *chCAfile, STACK_OF(X509_CRL) *crls, + int crl_download); +void ssl_ctx_security_debug(SSL_CTX *ctx, int verbose); +int set_keylog_file(SSL_CTX *ctx, const char *keylog_file); +void print_ca_names(BIO *bio, SSL *s); +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/s_cb.c b/trunk/3rdparty/openssl-1.1-fit/apps/s_cb.c new file mode 100644 index 000000000..d0e332a70 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/s_cb.c @@ -0,0 +1,1481 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* callback functions used by s_client, s_server, and s_time */ +#include +#include +#include /* for memcpy() and strcmp() */ +#include "apps.h" +#include +#include +#include +#include +#include +#ifndef OPENSSL_NO_DH +# include +#endif +#include "s_apps.h" + +#define COOKIE_SECRET_LENGTH 16 + +VERIFY_CB_ARGS verify_args = { -1, 0, X509_V_OK, 0 }; + +#ifndef OPENSSL_NO_SOCK +static unsigned char cookie_secret[COOKIE_SECRET_LENGTH]; +static int cookie_initialized = 0; +#endif +static BIO *bio_keylog = NULL; + +static const char *lookup(int val, const STRINT_PAIR* list, const char* def) +{ + for ( ; list->name; ++list) + if (list->retval == val) + return list->name; + return def; +} + +int verify_callback(int ok, X509_STORE_CTX *ctx) +{ + X509 *err_cert; + int err, depth; + + err_cert = X509_STORE_CTX_get_current_cert(ctx); + err = X509_STORE_CTX_get_error(ctx); + depth = X509_STORE_CTX_get_error_depth(ctx); + + if (!verify_args.quiet || !ok) { + BIO_printf(bio_err, "depth=%d ", depth); + if (err_cert != NULL) { + X509_NAME_print_ex(bio_err, + X509_get_subject_name(err_cert), + 0, get_nameopt()); + BIO_puts(bio_err, "\n"); + } else { + BIO_puts(bio_err, "\n"); + } + } + if (!ok) { + BIO_printf(bio_err, "verify error:num=%d:%s\n", err, + X509_verify_cert_error_string(err)); + if (verify_args.depth < 0 || verify_args.depth >= depth) { + if (!verify_args.return_error) + ok = 1; + verify_args.error = err; + } else { + ok = 0; + verify_args.error = X509_V_ERR_CERT_CHAIN_TOO_LONG; + } + } + switch (err) { + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: + BIO_puts(bio_err, "issuer= "); + X509_NAME_print_ex(bio_err, X509_get_issuer_name(err_cert), + 0, get_nameopt()); + BIO_puts(bio_err, "\n"); + break; + case X509_V_ERR_CERT_NOT_YET_VALID: + case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: + BIO_printf(bio_err, "notBefore="); + ASN1_TIME_print(bio_err, X509_get0_notBefore(err_cert)); + BIO_printf(bio_err, "\n"); + break; + case X509_V_ERR_CERT_HAS_EXPIRED: + case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: + BIO_printf(bio_err, "notAfter="); + ASN1_TIME_print(bio_err, X509_get0_notAfter(err_cert)); + BIO_printf(bio_err, "\n"); + break; + case X509_V_ERR_NO_EXPLICIT_POLICY: + if (!verify_args.quiet) + policies_print(ctx); + break; + } + if (err == X509_V_OK && ok == 2 && !verify_args.quiet) + policies_print(ctx); + if (ok && !verify_args.quiet) + BIO_printf(bio_err, "verify return:%d\n", ok); + return ok; +} + +int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file) +{ + if (cert_file != NULL) { + if (SSL_CTX_use_certificate_file(ctx, cert_file, + SSL_FILETYPE_PEM) <= 0) { + BIO_printf(bio_err, "unable to get certificate from '%s'\n", + cert_file); + ERR_print_errors(bio_err); + return 0; + } + if (key_file == NULL) + key_file = cert_file; + if (SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) <= 0) { + BIO_printf(bio_err, "unable to get private key from '%s'\n", + key_file); + ERR_print_errors(bio_err); + return 0; + } + + /* + * If we are using DSA, we can copy the parameters from the private + * key + */ + + /* + * Now we know that a key and cert have been set against the SSL + * context + */ + if (!SSL_CTX_check_private_key(ctx)) { + BIO_printf(bio_err, + "Private key does not match the certificate public key\n"); + return 0; + } + } + return 1; +} + +int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key, + STACK_OF(X509) *chain, int build_chain) +{ + int chflags = chain ? SSL_BUILD_CHAIN_FLAG_CHECK : 0; + if (cert == NULL) + return 1; + if (SSL_CTX_use_certificate(ctx, cert) <= 0) { + BIO_printf(bio_err, "error setting certificate\n"); + ERR_print_errors(bio_err); + return 0; + } + + if (SSL_CTX_use_PrivateKey(ctx, key) <= 0) { + BIO_printf(bio_err, "error setting private key\n"); + ERR_print_errors(bio_err); + return 0; + } + + /* + * Now we know that a key and cert have been set against the SSL context + */ + if (!SSL_CTX_check_private_key(ctx)) { + BIO_printf(bio_err, + "Private key does not match the certificate public key\n"); + return 0; + } + if (chain && !SSL_CTX_set1_chain(ctx, chain)) { + BIO_printf(bio_err, "error setting certificate chain\n"); + ERR_print_errors(bio_err); + return 0; + } + if (build_chain && !SSL_CTX_build_cert_chain(ctx, chflags)) { + BIO_printf(bio_err, "error building certificate chain\n"); + ERR_print_errors(bio_err); + return 0; + } + return 1; +} + +static STRINT_PAIR cert_type_list[] = { + {"RSA sign", TLS_CT_RSA_SIGN}, + {"DSA sign", TLS_CT_DSS_SIGN}, + {"RSA fixed DH", TLS_CT_RSA_FIXED_DH}, + {"DSS fixed DH", TLS_CT_DSS_FIXED_DH}, + {"ECDSA sign", TLS_CT_ECDSA_SIGN}, + {"RSA fixed ECDH", TLS_CT_RSA_FIXED_ECDH}, + {"ECDSA fixed ECDH", TLS_CT_ECDSA_FIXED_ECDH}, + {"GOST01 Sign", TLS_CT_GOST01_SIGN}, + {NULL} +}; + +static void ssl_print_client_cert_types(BIO *bio, SSL *s) +{ + const unsigned char *p; + int i; + int cert_type_num = SSL_get0_certificate_types(s, &p); + if (!cert_type_num) + return; + BIO_puts(bio, "Client Certificate Types: "); + for (i = 0; i < cert_type_num; i++) { + unsigned char cert_type = p[i]; + const char *cname = lookup((int)cert_type, cert_type_list, NULL); + + if (i) + BIO_puts(bio, ", "); + if (cname != NULL) + BIO_puts(bio, cname); + else + BIO_printf(bio, "UNKNOWN (%d),", cert_type); + } + BIO_puts(bio, "\n"); +} + +static const char *get_sigtype(int nid) +{ + switch (nid) { + case EVP_PKEY_RSA: + return "RSA"; + + case EVP_PKEY_RSA_PSS: + return "RSA-PSS"; + + case EVP_PKEY_DSA: + return "DSA"; + + case EVP_PKEY_EC: + return "ECDSA"; + + case NID_ED25519: + return "Ed25519"; + + case NID_ED448: + return "Ed448"; + + case NID_id_GostR3410_2001: + return "gost2001"; + + case NID_id_GostR3410_2012_256: + return "gost2012_256"; + + case NID_id_GostR3410_2012_512: + return "gost2012_512"; + + default: + return NULL; + } +} + +static int do_print_sigalgs(BIO *out, SSL *s, int shared) +{ + int i, nsig, client; + client = SSL_is_server(s) ? 0 : 1; + if (shared) + nsig = SSL_get_shared_sigalgs(s, 0, NULL, NULL, NULL, NULL, NULL); + else + nsig = SSL_get_sigalgs(s, -1, NULL, NULL, NULL, NULL, NULL); + if (nsig == 0) + return 1; + + if (shared) + BIO_puts(out, "Shared "); + + if (client) + BIO_puts(out, "Requested "); + BIO_puts(out, "Signature Algorithms: "); + for (i = 0; i < nsig; i++) { + int hash_nid, sign_nid; + unsigned char rhash, rsign; + const char *sstr = NULL; + if (shared) + SSL_get_shared_sigalgs(s, i, &sign_nid, &hash_nid, NULL, + &rsign, &rhash); + else + SSL_get_sigalgs(s, i, &sign_nid, &hash_nid, NULL, &rsign, &rhash); + if (i) + BIO_puts(out, ":"); + sstr = get_sigtype(sign_nid); + if (sstr) + BIO_printf(out, "%s", sstr); + else + BIO_printf(out, "0x%02X", (int)rsign); + if (hash_nid != NID_undef) + BIO_printf(out, "+%s", OBJ_nid2sn(hash_nid)); + else if (sstr == NULL) + BIO_printf(out, "+0x%02X", (int)rhash); + } + BIO_puts(out, "\n"); + return 1; +} + +int ssl_print_sigalgs(BIO *out, SSL *s) +{ + int nid; + if (!SSL_is_server(s)) + ssl_print_client_cert_types(out, s); + do_print_sigalgs(out, s, 0); + do_print_sigalgs(out, s, 1); + if (SSL_get_peer_signature_nid(s, &nid) && nid != NID_undef) + BIO_printf(out, "Peer signing digest: %s\n", OBJ_nid2sn(nid)); + if (SSL_get_peer_signature_type_nid(s, &nid)) + BIO_printf(out, "Peer signature type: %s\n", get_sigtype(nid)); + return 1; +} + +#ifndef OPENSSL_NO_EC +int ssl_print_point_formats(BIO *out, SSL *s) +{ + int i, nformats; + const char *pformats; + nformats = SSL_get0_ec_point_formats(s, &pformats); + if (nformats <= 0) + return 1; + BIO_puts(out, "Supported Elliptic Curve Point Formats: "); + for (i = 0; i < nformats; i++, pformats++) { + if (i) + BIO_puts(out, ":"); + switch (*pformats) { + case TLSEXT_ECPOINTFORMAT_uncompressed: + BIO_puts(out, "uncompressed"); + break; + + case TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime: + BIO_puts(out, "ansiX962_compressed_prime"); + break; + + case TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2: + BIO_puts(out, "ansiX962_compressed_char2"); + break; + + default: + BIO_printf(out, "unknown(%d)", (int)*pformats); + break; + + } + } + BIO_puts(out, "\n"); + return 1; +} + +int ssl_print_groups(BIO *out, SSL *s, int noshared) +{ + int i, ngroups, *groups, nid; + const char *gname; + + ngroups = SSL_get1_groups(s, NULL); + if (ngroups <= 0) + return 1; + groups = app_malloc(ngroups * sizeof(int), "groups to print"); + SSL_get1_groups(s, groups); + + BIO_puts(out, "Supported Elliptic Groups: "); + for (i = 0; i < ngroups; i++) { + if (i) + BIO_puts(out, ":"); + nid = groups[i]; + /* If unrecognised print out hex version */ + if (nid & TLSEXT_nid_unknown) { + BIO_printf(out, "0x%04X", nid & 0xFFFF); + } else { + /* TODO(TLS1.3): Get group name here */ + /* Use NIST name for curve if it exists */ + gname = EC_curve_nid2nist(nid); + if (gname == NULL) + gname = OBJ_nid2sn(nid); + BIO_printf(out, "%s", gname); + } + } + OPENSSL_free(groups); + if (noshared) { + BIO_puts(out, "\n"); + return 1; + } + BIO_puts(out, "\nShared Elliptic groups: "); + ngroups = SSL_get_shared_group(s, -1); + for (i = 0; i < ngroups; i++) { + if (i) + BIO_puts(out, ":"); + nid = SSL_get_shared_group(s, i); + /* TODO(TLS1.3): Convert for DH groups */ + gname = EC_curve_nid2nist(nid); + if (gname == NULL) + gname = OBJ_nid2sn(nid); + BIO_printf(out, "%s", gname); + } + if (ngroups == 0) + BIO_puts(out, "NONE"); + BIO_puts(out, "\n"); + return 1; +} +#endif + +int ssl_print_tmp_key(BIO *out, SSL *s) +{ + EVP_PKEY *key; + + if (!SSL_get_peer_tmp_key(s, &key)) + return 1; + BIO_puts(out, "Server Temp Key: "); + switch (EVP_PKEY_id(key)) { + case EVP_PKEY_RSA: + BIO_printf(out, "RSA, %d bits\n", EVP_PKEY_bits(key)); + break; + + case EVP_PKEY_DH: + BIO_printf(out, "DH, %d bits\n", EVP_PKEY_bits(key)); + break; +#ifndef OPENSSL_NO_EC + case EVP_PKEY_EC: + { + EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key); + int nid; + const char *cname; + nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); + EC_KEY_free(ec); + cname = EC_curve_nid2nist(nid); + if (cname == NULL) + cname = OBJ_nid2sn(nid); + BIO_printf(out, "ECDH, %s, %d bits\n", cname, EVP_PKEY_bits(key)); + } + break; +#endif + default: + BIO_printf(out, "%s, %d bits\n", OBJ_nid2sn(EVP_PKEY_id(key)), + EVP_PKEY_bits(key)); + } + EVP_PKEY_free(key); + return 1; +} + +long bio_dump_callback(BIO *bio, int cmd, const char *argp, + int argi, long argl, long ret) +{ + BIO *out; + + out = (BIO *)BIO_get_callback_arg(bio); + if (out == NULL) + return ret; + + if (cmd == (BIO_CB_READ | BIO_CB_RETURN)) { + BIO_printf(out, "read from %p [%p] (%lu bytes => %ld (0x%lX))\n", + (void *)bio, (void *)argp, (unsigned long)argi, ret, ret); + BIO_dump(out, argp, (int)ret); + return ret; + } else if (cmd == (BIO_CB_WRITE | BIO_CB_RETURN)) { + BIO_printf(out, "write to %p [%p] (%lu bytes => %ld (0x%lX))\n", + (void *)bio, (void *)argp, (unsigned long)argi, ret, ret); + BIO_dump(out, argp, (int)ret); + } + return ret; +} + +void apps_ssl_info_callback(const SSL *s, int where, int ret) +{ + const char *str; + int w; + + w = where & ~SSL_ST_MASK; + + if (w & SSL_ST_CONNECT) + str = "SSL_connect"; + else if (w & SSL_ST_ACCEPT) + str = "SSL_accept"; + else + str = "undefined"; + + if (where & SSL_CB_LOOP) { + BIO_printf(bio_err, "%s:%s\n", str, SSL_state_string_long(s)); + } else if (where & SSL_CB_ALERT) { + str = (where & SSL_CB_READ) ? "read" : "write"; + BIO_printf(bio_err, "SSL3 alert %s:%s:%s\n", + str, + SSL_alert_type_string_long(ret), + SSL_alert_desc_string_long(ret)); + } else if (where & SSL_CB_EXIT) { + if (ret == 0) + BIO_printf(bio_err, "%s:failed in %s\n", + str, SSL_state_string_long(s)); + else if (ret < 0) + BIO_printf(bio_err, "%s:error in %s\n", + str, SSL_state_string_long(s)); + } +} + +static STRINT_PAIR ssl_versions[] = { + {"SSL 3.0", SSL3_VERSION}, + {"TLS 1.0", TLS1_VERSION}, + {"TLS 1.1", TLS1_1_VERSION}, + {"TLS 1.2", TLS1_2_VERSION}, + {"TLS 1.3", TLS1_3_VERSION}, + {"DTLS 1.0", DTLS1_VERSION}, + {"DTLS 1.0 (bad)", DTLS1_BAD_VER}, + {NULL} +}; + +static STRINT_PAIR alert_types[] = { + {" close_notify", 0}, + {" end_of_early_data", 1}, + {" unexpected_message", 10}, + {" bad_record_mac", 20}, + {" decryption_failed", 21}, + {" record_overflow", 22}, + {" decompression_failure", 30}, + {" handshake_failure", 40}, + {" bad_certificate", 42}, + {" unsupported_certificate", 43}, + {" certificate_revoked", 44}, + {" certificate_expired", 45}, + {" certificate_unknown", 46}, + {" illegal_parameter", 47}, + {" unknown_ca", 48}, + {" access_denied", 49}, + {" decode_error", 50}, + {" decrypt_error", 51}, + {" export_restriction", 60}, + {" protocol_version", 70}, + {" insufficient_security", 71}, + {" internal_error", 80}, + {" inappropriate_fallback", 86}, + {" user_canceled", 90}, + {" no_renegotiation", 100}, + {" missing_extension", 109}, + {" unsupported_extension", 110}, + {" certificate_unobtainable", 111}, + {" unrecognized_name", 112}, + {" bad_certificate_status_response", 113}, + {" bad_certificate_hash_value", 114}, + {" unknown_psk_identity", 115}, + {" certificate_required", 116}, + {NULL} +}; + +static STRINT_PAIR handshakes[] = { + {", HelloRequest", SSL3_MT_HELLO_REQUEST}, + {", ClientHello", SSL3_MT_CLIENT_HELLO}, + {", ServerHello", SSL3_MT_SERVER_HELLO}, + {", HelloVerifyRequest", DTLS1_MT_HELLO_VERIFY_REQUEST}, + {", NewSessionTicket", SSL3_MT_NEWSESSION_TICKET}, + {", EndOfEarlyData", SSL3_MT_END_OF_EARLY_DATA}, + {", EncryptedExtensions", SSL3_MT_ENCRYPTED_EXTENSIONS}, + {", Certificate", SSL3_MT_CERTIFICATE}, + {", ServerKeyExchange", SSL3_MT_SERVER_KEY_EXCHANGE}, + {", CertificateRequest", SSL3_MT_CERTIFICATE_REQUEST}, + {", ServerHelloDone", SSL3_MT_SERVER_DONE}, + {", CertificateVerify", SSL3_MT_CERTIFICATE_VERIFY}, + {", ClientKeyExchange", SSL3_MT_CLIENT_KEY_EXCHANGE}, + {", Finished", SSL3_MT_FINISHED}, + {", CertificateUrl", SSL3_MT_CERTIFICATE_URL}, + {", CertificateStatus", SSL3_MT_CERTIFICATE_STATUS}, + {", SupplementalData", SSL3_MT_SUPPLEMENTAL_DATA}, + {", KeyUpdate", SSL3_MT_KEY_UPDATE}, +#ifndef OPENSSL_NO_NEXTPROTONEG + {", NextProto", SSL3_MT_NEXT_PROTO}, +#endif + {", MessageHash", SSL3_MT_MESSAGE_HASH}, + {NULL} +}; + +void msg_cb(int write_p, int version, int content_type, const void *buf, + size_t len, SSL *ssl, void *arg) +{ + BIO *bio = arg; + const char *str_write_p = write_p ? ">>>" : "<<<"; + const char *str_version = lookup(version, ssl_versions, "???"); + const char *str_content_type = "", *str_details1 = "", *str_details2 = ""; + const unsigned char* bp = buf; + + if (version == SSL3_VERSION || + version == TLS1_VERSION || + version == TLS1_1_VERSION || + version == TLS1_2_VERSION || + version == TLS1_3_VERSION || + version == DTLS1_VERSION || version == DTLS1_BAD_VER) { + switch (content_type) { + case 20: + str_content_type = ", ChangeCipherSpec"; + break; + case 21: + str_content_type = ", Alert"; + str_details1 = ", ???"; + if (len == 2) { + switch (bp[0]) { + case 1: + str_details1 = ", warning"; + break; + case 2: + str_details1 = ", fatal"; + break; + } + str_details2 = lookup((int)bp[1], alert_types, " ???"); + } + break; + case 22: + str_content_type = ", Handshake"; + str_details1 = "???"; + if (len > 0) + str_details1 = lookup((int)bp[0], handshakes, "???"); + break; + case 23: + str_content_type = ", ApplicationData"; + break; +#ifndef OPENSSL_NO_HEARTBEATS + case 24: + str_details1 = ", Heartbeat"; + + if (len > 0) { + switch (bp[0]) { + case 1: + str_details1 = ", HeartbeatRequest"; + break; + case 2: + str_details1 = ", HeartbeatResponse"; + break; + } + } + break; +#endif + } + } + + BIO_printf(bio, "%s %s%s [length %04lx]%s%s\n", str_write_p, str_version, + str_content_type, (unsigned long)len, str_details1, + str_details2); + + if (len > 0) { + size_t num, i; + + BIO_printf(bio, " "); + num = len; + for (i = 0; i < num; i++) { + if (i % 16 == 0 && i > 0) + BIO_printf(bio, "\n "); + BIO_printf(bio, " %02x", ((const unsigned char *)buf)[i]); + } + if (i < len) + BIO_printf(bio, " ..."); + BIO_printf(bio, "\n"); + } + (void)BIO_flush(bio); +} + +static STRINT_PAIR tlsext_types[] = { + {"server name", TLSEXT_TYPE_server_name}, + {"max fragment length", TLSEXT_TYPE_max_fragment_length}, + {"client certificate URL", TLSEXT_TYPE_client_certificate_url}, + {"trusted CA keys", TLSEXT_TYPE_trusted_ca_keys}, + {"truncated HMAC", TLSEXT_TYPE_truncated_hmac}, + {"status request", TLSEXT_TYPE_status_request}, + {"user mapping", TLSEXT_TYPE_user_mapping}, + {"client authz", TLSEXT_TYPE_client_authz}, + {"server authz", TLSEXT_TYPE_server_authz}, + {"cert type", TLSEXT_TYPE_cert_type}, + {"supported_groups", TLSEXT_TYPE_supported_groups}, + {"EC point formats", TLSEXT_TYPE_ec_point_formats}, + {"SRP", TLSEXT_TYPE_srp}, + {"signature algorithms", TLSEXT_TYPE_signature_algorithms}, + {"use SRTP", TLSEXT_TYPE_use_srtp}, + {"heartbeat", TLSEXT_TYPE_heartbeat}, + {"session ticket", TLSEXT_TYPE_session_ticket}, + {"renegotiation info", TLSEXT_TYPE_renegotiate}, + {"signed certificate timestamps", TLSEXT_TYPE_signed_certificate_timestamp}, + {"TLS padding", TLSEXT_TYPE_padding}, +#ifdef TLSEXT_TYPE_next_proto_neg + {"next protocol", TLSEXT_TYPE_next_proto_neg}, +#endif +#ifdef TLSEXT_TYPE_encrypt_then_mac + {"encrypt-then-mac", TLSEXT_TYPE_encrypt_then_mac}, +#endif +#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation + {"application layer protocol negotiation", + TLSEXT_TYPE_application_layer_protocol_negotiation}, +#endif +#ifdef TLSEXT_TYPE_extended_master_secret + {"extended master secret", TLSEXT_TYPE_extended_master_secret}, +#endif + {"key share", TLSEXT_TYPE_key_share}, + {"supported versions", TLSEXT_TYPE_supported_versions}, + {"psk", TLSEXT_TYPE_psk}, + {"psk kex modes", TLSEXT_TYPE_psk_kex_modes}, + {"certificate authorities", TLSEXT_TYPE_certificate_authorities}, + {"post handshake auth", TLSEXT_TYPE_post_handshake_auth}, + {NULL} +}; + +void tlsext_cb(SSL *s, int client_server, int type, + const unsigned char *data, int len, void *arg) +{ + BIO *bio = arg; + const char *extname = lookup(type, tlsext_types, "unknown"); + + BIO_printf(bio, "TLS %s extension \"%s\" (id=%d), len=%d\n", + client_server ? "server" : "client", extname, type, len); + BIO_dump(bio, (const char *)data, len); + (void)BIO_flush(bio); +} + +#ifndef OPENSSL_NO_SOCK +int generate_cookie_callback(SSL *ssl, unsigned char *cookie, + unsigned int *cookie_len) +{ + unsigned char *buffer; + size_t length = 0; + unsigned short port; + BIO_ADDR *lpeer = NULL, *peer = NULL; + + /* Initialize a random secret */ + if (!cookie_initialized) { + if (RAND_bytes(cookie_secret, COOKIE_SECRET_LENGTH) <= 0) { + BIO_printf(bio_err, "error setting random cookie secret\n"); + return 0; + } + cookie_initialized = 1; + } + + if (SSL_is_dtls(ssl)) { + lpeer = peer = BIO_ADDR_new(); + if (peer == NULL) { + BIO_printf(bio_err, "memory full\n"); + return 0; + } + + /* Read peer information */ + (void)BIO_dgram_get_peer(SSL_get_rbio(ssl), peer); + } else { + peer = ourpeer; + } + + /* Create buffer with peer's address and port */ + if (!BIO_ADDR_rawaddress(peer, NULL, &length)) { + BIO_printf(bio_err, "Failed getting peer address\n"); + return 0; + } + OPENSSL_assert(length != 0); + port = BIO_ADDR_rawport(peer); + length += sizeof(port); + buffer = app_malloc(length, "cookie generate buffer"); + + memcpy(buffer, &port, sizeof(port)); + BIO_ADDR_rawaddress(peer, buffer + sizeof(port), NULL); + + /* Calculate HMAC of buffer using the secret */ + HMAC(EVP_sha1(), cookie_secret, COOKIE_SECRET_LENGTH, + buffer, length, cookie, cookie_len); + + OPENSSL_free(buffer); + BIO_ADDR_free(lpeer); + + return 1; +} + +int verify_cookie_callback(SSL *ssl, const unsigned char *cookie, + unsigned int cookie_len) +{ + unsigned char result[EVP_MAX_MD_SIZE]; + unsigned int resultlength; + + /* Note: we check cookie_initialized because if it's not, + * it cannot be valid */ + if (cookie_initialized + && generate_cookie_callback(ssl, result, &resultlength) + && cookie_len == resultlength + && memcmp(result, cookie, resultlength) == 0) + return 1; + + return 0; +} + +int generate_stateless_cookie_callback(SSL *ssl, unsigned char *cookie, + size_t *cookie_len) +{ + unsigned int temp; + int res = generate_cookie_callback(ssl, cookie, &temp); + *cookie_len = temp; + return res; +} + +int verify_stateless_cookie_callback(SSL *ssl, const unsigned char *cookie, + size_t cookie_len) +{ + return verify_cookie_callback(ssl, cookie, cookie_len); +} + +#endif + +/* + * Example of extended certificate handling. Where the standard support of + * one certificate per algorithm is not sufficient an application can decide + * which certificate(s) to use at runtime based on whatever criteria it deems + * appropriate. + */ + +/* Linked list of certificates, keys and chains */ +struct ssl_excert_st { + int certform; + const char *certfile; + int keyform; + const char *keyfile; + const char *chainfile; + X509 *cert; + EVP_PKEY *key; + STACK_OF(X509) *chain; + int build_chain; + struct ssl_excert_st *next, *prev; +}; + +static STRINT_PAIR chain_flags[] = { + {"Overall Validity", CERT_PKEY_VALID}, + {"Sign with EE key", CERT_PKEY_SIGN}, + {"EE signature", CERT_PKEY_EE_SIGNATURE}, + {"CA signature", CERT_PKEY_CA_SIGNATURE}, + {"EE key parameters", CERT_PKEY_EE_PARAM}, + {"CA key parameters", CERT_PKEY_CA_PARAM}, + {"Explicitly sign with EE key", CERT_PKEY_EXPLICIT_SIGN}, + {"Issuer Name", CERT_PKEY_ISSUER_NAME}, + {"Certificate Type", CERT_PKEY_CERT_TYPE}, + {NULL} +}; + +static void print_chain_flags(SSL *s, int flags) +{ + STRINT_PAIR *pp; + + for (pp = chain_flags; pp->name; ++pp) + BIO_printf(bio_err, "\t%s: %s\n", + pp->name, + (flags & pp->retval) ? "OK" : "NOT OK"); + BIO_printf(bio_err, "\tSuite B: "); + if (SSL_set_cert_flags(s, 0) & SSL_CERT_FLAG_SUITEB_128_LOS) + BIO_puts(bio_err, flags & CERT_PKEY_SUITEB ? "OK\n" : "NOT OK\n"); + else + BIO_printf(bio_err, "not tested\n"); +} + +/* + * Very basic selection callback: just use any certificate chain reported as + * valid. More sophisticated could prioritise according to local policy. + */ +static int set_cert_cb(SSL *ssl, void *arg) +{ + int i, rv; + SSL_EXCERT *exc = arg; +#ifdef CERT_CB_TEST_RETRY + static int retry_cnt; + if (retry_cnt < 5) { + retry_cnt++; + BIO_printf(bio_err, + "Certificate callback retry test: count %d\n", + retry_cnt); + return -1; + } +#endif + SSL_certs_clear(ssl); + + if (exc == NULL) + return 1; + + /* + * Go to end of list and traverse backwards since we prepend newer + * entries this retains the original order. + */ + while (exc->next != NULL) + exc = exc->next; + + i = 0; + + while (exc != NULL) { + i++; + rv = SSL_check_chain(ssl, exc->cert, exc->key, exc->chain); + BIO_printf(bio_err, "Checking cert chain %d:\nSubject: ", i); + X509_NAME_print_ex(bio_err, X509_get_subject_name(exc->cert), 0, + get_nameopt()); + BIO_puts(bio_err, "\n"); + print_chain_flags(ssl, rv); + if (rv & CERT_PKEY_VALID) { + if (!SSL_use_certificate(ssl, exc->cert) + || !SSL_use_PrivateKey(ssl, exc->key)) { + return 0; + } + /* + * NB: we wouldn't normally do this as it is not efficient + * building chains on each connection better to cache the chain + * in advance. + */ + if (exc->build_chain) { + if (!SSL_build_cert_chain(ssl, 0)) + return 0; + } else if (exc->chain != NULL) { + SSL_set1_chain(ssl, exc->chain); + } + } + exc = exc->prev; + } + return 1; +} + +void ssl_ctx_set_excert(SSL_CTX *ctx, SSL_EXCERT *exc) +{ + SSL_CTX_set_cert_cb(ctx, set_cert_cb, exc); +} + +static int ssl_excert_prepend(SSL_EXCERT **pexc) +{ + SSL_EXCERT *exc = app_malloc(sizeof(*exc), "prepend cert"); + + memset(exc, 0, sizeof(*exc)); + + exc->next = *pexc; + *pexc = exc; + + if (exc->next) { + exc->certform = exc->next->certform; + exc->keyform = exc->next->keyform; + exc->next->prev = exc; + } else { + exc->certform = FORMAT_PEM; + exc->keyform = FORMAT_PEM; + } + return 1; + +} + +void ssl_excert_free(SSL_EXCERT *exc) +{ + SSL_EXCERT *curr; + + if (exc == NULL) + return; + while (exc) { + X509_free(exc->cert); + EVP_PKEY_free(exc->key); + sk_X509_pop_free(exc->chain, X509_free); + curr = exc; + exc = exc->next; + OPENSSL_free(curr); + } +} + +int load_excert(SSL_EXCERT **pexc) +{ + SSL_EXCERT *exc = *pexc; + if (exc == NULL) + return 1; + /* If nothing in list, free and set to NULL */ + if (exc->certfile == NULL && exc->next == NULL) { + ssl_excert_free(exc); + *pexc = NULL; + return 1; + } + for (; exc; exc = exc->next) { + if (exc->certfile == NULL) { + BIO_printf(bio_err, "Missing filename\n"); + return 0; + } + exc->cert = load_cert(exc->certfile, exc->certform, + "Server Certificate"); + if (exc->cert == NULL) + return 0; + if (exc->keyfile != NULL) { + exc->key = load_key(exc->keyfile, exc->keyform, + 0, NULL, NULL, "Server Key"); + } else { + exc->key = load_key(exc->certfile, exc->certform, + 0, NULL, NULL, "Server Key"); + } + if (exc->key == NULL) + return 0; + if (exc->chainfile != NULL) { + if (!load_certs(exc->chainfile, &exc->chain, FORMAT_PEM, NULL, + "Server Chain")) + return 0; + } + } + return 1; +} + +enum range { OPT_X_ENUM }; + +int args_excert(int opt, SSL_EXCERT **pexc) +{ + SSL_EXCERT *exc = *pexc; + + assert(opt > OPT_X__FIRST); + assert(opt < OPT_X__LAST); + + if (exc == NULL) { + if (!ssl_excert_prepend(&exc)) { + BIO_printf(bio_err, " %s: Error initialising xcert\n", + opt_getprog()); + goto err; + } + *pexc = exc; + } + + switch ((enum range)opt) { + case OPT_X__FIRST: + case OPT_X__LAST: + return 0; + case OPT_X_CERT: + if (exc->certfile != NULL && !ssl_excert_prepend(&exc)) { + BIO_printf(bio_err, "%s: Error adding xcert\n", opt_getprog()); + goto err; + } + *pexc = exc; + exc->certfile = opt_arg(); + break; + case OPT_X_KEY: + if (exc->keyfile != NULL) { + BIO_printf(bio_err, "%s: Key already specified\n", opt_getprog()); + goto err; + } + exc->keyfile = opt_arg(); + break; + case OPT_X_CHAIN: + if (exc->chainfile != NULL) { + BIO_printf(bio_err, "%s: Chain already specified\n", + opt_getprog()); + goto err; + } + exc->chainfile = opt_arg(); + break; + case OPT_X_CHAIN_BUILD: + exc->build_chain = 1; + break; + case OPT_X_CERTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &exc->certform)) + return 0; + break; + case OPT_X_KEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &exc->keyform)) + return 0; + break; + } + return 1; + + err: + ERR_print_errors(bio_err); + ssl_excert_free(exc); + *pexc = NULL; + return 0; +} + +static void print_raw_cipherlist(SSL *s) +{ + const unsigned char *rlist; + static const unsigned char scsv_id[] = { 0, 0xFF }; + size_t i, rlistlen, num; + if (!SSL_is_server(s)) + return; + num = SSL_get0_raw_cipherlist(s, NULL); + OPENSSL_assert(num == 2); + rlistlen = SSL_get0_raw_cipherlist(s, &rlist); + BIO_puts(bio_err, "Client cipher list: "); + for (i = 0; i < rlistlen; i += num, rlist += num) { + const SSL_CIPHER *c = SSL_CIPHER_find(s, rlist); + if (i) + BIO_puts(bio_err, ":"); + if (c != NULL) { + BIO_puts(bio_err, SSL_CIPHER_get_name(c)); + } else if (memcmp(rlist, scsv_id, num) == 0) { + BIO_puts(bio_err, "SCSV"); + } else { + size_t j; + BIO_puts(bio_err, "0x"); + for (j = 0; j < num; j++) + BIO_printf(bio_err, "%02X", rlist[j]); + } + } + BIO_puts(bio_err, "\n"); +} + +/* + * Hex encoder for TLSA RRdata, not ':' delimited. + */ +static char *hexencode(const unsigned char *data, size_t len) +{ + static const char *hex = "0123456789abcdef"; + char *out; + char *cp; + size_t outlen = 2 * len + 1; + int ilen = (int) outlen; + + if (outlen < len || ilen < 0 || outlen != (size_t)ilen) { + BIO_printf(bio_err, "%s: %zu-byte buffer too large to hexencode\n", + opt_getprog(), len); + exit(1); + } + cp = out = app_malloc(ilen, "TLSA hex data buffer"); + + while (len-- > 0) { + *cp++ = hex[(*data >> 4) & 0x0f]; + *cp++ = hex[*data++ & 0x0f]; + } + *cp = '\0'; + return out; +} + +void print_verify_detail(SSL *s, BIO *bio) +{ + int mdpth; + EVP_PKEY *mspki; + long verify_err = SSL_get_verify_result(s); + + if (verify_err == X509_V_OK) { + const char *peername = SSL_get0_peername(s); + + BIO_printf(bio, "Verification: OK\n"); + if (peername != NULL) + BIO_printf(bio, "Verified peername: %s\n", peername); + } else { + const char *reason = X509_verify_cert_error_string(verify_err); + + BIO_printf(bio, "Verification error: %s\n", reason); + } + + if ((mdpth = SSL_get0_dane_authority(s, NULL, &mspki)) >= 0) { + uint8_t usage, selector, mtype; + const unsigned char *data = NULL; + size_t dlen = 0; + char *hexdata; + + mdpth = SSL_get0_dane_tlsa(s, &usage, &selector, &mtype, &data, &dlen); + + /* + * The TLSA data field can be quite long when it is a certificate, + * public key or even a SHA2-512 digest. Because the initial octets of + * ASN.1 certificates and public keys contain mostly boilerplate OIDs + * and lengths, we show the last 12 bytes of the data instead, as these + * are more likely to distinguish distinct TLSA records. + */ +#define TLSA_TAIL_SIZE 12 + if (dlen > TLSA_TAIL_SIZE) + hexdata = hexencode(data + dlen - TLSA_TAIL_SIZE, TLSA_TAIL_SIZE); + else + hexdata = hexencode(data, dlen); + BIO_printf(bio, "DANE TLSA %d %d %d %s%s %s at depth %d\n", + usage, selector, mtype, + (dlen > TLSA_TAIL_SIZE) ? "..." : "", hexdata, + (mspki != NULL) ? "signed the certificate" : + mdpth ? "matched TA certificate" : "matched EE certificate", + mdpth); + OPENSSL_free(hexdata); + } +} + +void print_ssl_summary(SSL *s) +{ + const SSL_CIPHER *c; + X509 *peer; + + BIO_printf(bio_err, "Protocol version: %s\n", SSL_get_version(s)); + print_raw_cipherlist(s); + c = SSL_get_current_cipher(s); + BIO_printf(bio_err, "Ciphersuite: %s\n", SSL_CIPHER_get_name(c)); + do_print_sigalgs(bio_err, s, 0); + peer = SSL_get_peer_certificate(s); + if (peer != NULL) { + int nid; + + BIO_puts(bio_err, "Peer certificate: "); + X509_NAME_print_ex(bio_err, X509_get_subject_name(peer), + 0, get_nameopt()); + BIO_puts(bio_err, "\n"); + if (SSL_get_peer_signature_nid(s, &nid)) + BIO_printf(bio_err, "Hash used: %s\n", OBJ_nid2sn(nid)); + if (SSL_get_peer_signature_type_nid(s, &nid)) + BIO_printf(bio_err, "Signature type: %s\n", get_sigtype(nid)); + print_verify_detail(s, bio_err); + } else { + BIO_puts(bio_err, "No peer certificate\n"); + } + X509_free(peer); +#ifndef OPENSSL_NO_EC + ssl_print_point_formats(bio_err, s); + if (SSL_is_server(s)) + ssl_print_groups(bio_err, s, 1); + else + ssl_print_tmp_key(bio_err, s); +#else + if (!SSL_is_server(s)) + ssl_print_tmp_key(bio_err, s); +#endif +} + +int config_ctx(SSL_CONF_CTX *cctx, STACK_OF(OPENSSL_STRING) *str, + SSL_CTX *ctx) +{ + int i; + + SSL_CONF_CTX_set_ssl_ctx(cctx, ctx); + for (i = 0; i < sk_OPENSSL_STRING_num(str); i += 2) { + const char *flag = sk_OPENSSL_STRING_value(str, i); + const char *arg = sk_OPENSSL_STRING_value(str, i + 1); + if (SSL_CONF_cmd(cctx, flag, arg) <= 0) { + if (arg != NULL) + BIO_printf(bio_err, "Error with command: \"%s %s\"\n", + flag, arg); + else + BIO_printf(bio_err, "Error with command: \"%s\"\n", flag); + ERR_print_errors(bio_err); + return 0; + } + } + if (!SSL_CONF_CTX_finish(cctx)) { + BIO_puts(bio_err, "Error finishing context\n"); + ERR_print_errors(bio_err); + return 0; + } + return 1; +} + +static int add_crls_store(X509_STORE *st, STACK_OF(X509_CRL) *crls) +{ + X509_CRL *crl; + int i; + for (i = 0; i < sk_X509_CRL_num(crls); i++) { + crl = sk_X509_CRL_value(crls, i); + X509_STORE_add_crl(st, crl); + } + return 1; +} + +int ssl_ctx_add_crls(SSL_CTX *ctx, STACK_OF(X509_CRL) *crls, int crl_download) +{ + X509_STORE *st; + st = SSL_CTX_get_cert_store(ctx); + add_crls_store(st, crls); + if (crl_download) + store_setup_crl_download(st); + return 1; +} + +int ssl_load_stores(SSL_CTX *ctx, + const char *vfyCApath, const char *vfyCAfile, + const char *chCApath, const char *chCAfile, + STACK_OF(X509_CRL) *crls, int crl_download) +{ + X509_STORE *vfy = NULL, *ch = NULL; + int rv = 0; + if (vfyCApath != NULL || vfyCAfile != NULL) { + vfy = X509_STORE_new(); + if (vfy == NULL) + goto err; + if (!X509_STORE_load_locations(vfy, vfyCAfile, vfyCApath)) + goto err; + add_crls_store(vfy, crls); + SSL_CTX_set1_verify_cert_store(ctx, vfy); + if (crl_download) + store_setup_crl_download(vfy); + } + if (chCApath != NULL || chCAfile != NULL) { + ch = X509_STORE_new(); + if (ch == NULL) + goto err; + if (!X509_STORE_load_locations(ch, chCAfile, chCApath)) + goto err; + SSL_CTX_set1_chain_cert_store(ctx, ch); + } + rv = 1; + err: + X509_STORE_free(vfy); + X509_STORE_free(ch); + return rv; +} + +/* Verbose print out of security callback */ + +typedef struct { + BIO *out; + int verbose; + int (*old_cb) (const SSL *s, const SSL_CTX *ctx, int op, int bits, int nid, + void *other, void *ex); +} security_debug_ex; + +static STRINT_PAIR callback_types[] = { + {"Supported Ciphersuite", SSL_SECOP_CIPHER_SUPPORTED}, + {"Shared Ciphersuite", SSL_SECOP_CIPHER_SHARED}, + {"Check Ciphersuite", SSL_SECOP_CIPHER_CHECK}, +#ifndef OPENSSL_NO_DH + {"Temp DH key bits", SSL_SECOP_TMP_DH}, +#endif + {"Supported Curve", SSL_SECOP_CURVE_SUPPORTED}, + {"Shared Curve", SSL_SECOP_CURVE_SHARED}, + {"Check Curve", SSL_SECOP_CURVE_CHECK}, + {"Supported Signature Algorithm digest", SSL_SECOP_SIGALG_SUPPORTED}, + {"Shared Signature Algorithm digest", SSL_SECOP_SIGALG_SHARED}, + {"Check Signature Algorithm digest", SSL_SECOP_SIGALG_CHECK}, + {"Signature Algorithm mask", SSL_SECOP_SIGALG_MASK}, + {"Certificate chain EE key", SSL_SECOP_EE_KEY}, + {"Certificate chain CA key", SSL_SECOP_CA_KEY}, + {"Peer Chain EE key", SSL_SECOP_PEER_EE_KEY}, + {"Peer Chain CA key", SSL_SECOP_PEER_CA_KEY}, + {"Certificate chain CA digest", SSL_SECOP_CA_MD}, + {"Peer chain CA digest", SSL_SECOP_PEER_CA_MD}, + {"SSL compression", SSL_SECOP_COMPRESSION}, + {"Session ticket", SSL_SECOP_TICKET}, + {NULL} +}; + +static int security_callback_debug(const SSL *s, const SSL_CTX *ctx, + int op, int bits, int nid, + void *other, void *ex) +{ + security_debug_ex *sdb = ex; + int rv, show_bits = 1, cert_md = 0; + const char *nm; + rv = sdb->old_cb(s, ctx, op, bits, nid, other, ex); + if (rv == 1 && sdb->verbose < 2) + return 1; + BIO_puts(sdb->out, "Security callback: "); + + nm = lookup(op, callback_types, NULL); + switch (op) { + case SSL_SECOP_TICKET: + case SSL_SECOP_COMPRESSION: + show_bits = 0; + nm = NULL; + break; + case SSL_SECOP_VERSION: + BIO_printf(sdb->out, "Version=%s", lookup(nid, ssl_versions, "???")); + show_bits = 0; + nm = NULL; + break; + case SSL_SECOP_CA_MD: + case SSL_SECOP_PEER_CA_MD: + cert_md = 1; + break; + } + if (nm != NULL) + BIO_printf(sdb->out, "%s=", nm); + + switch (op & SSL_SECOP_OTHER_TYPE) { + + case SSL_SECOP_OTHER_CIPHER: + BIO_puts(sdb->out, SSL_CIPHER_get_name(other)); + break; + +#ifndef OPENSSL_NO_EC + case SSL_SECOP_OTHER_CURVE: + { + const char *cname; + cname = EC_curve_nid2nist(nid); + if (cname == NULL) + cname = OBJ_nid2sn(nid); + BIO_puts(sdb->out, cname); + } + break; +#endif +#ifndef OPENSSL_NO_DH + case SSL_SECOP_OTHER_DH: + { + DH *dh = other; + BIO_printf(sdb->out, "%d", DH_bits(dh)); + break; + } +#endif + case SSL_SECOP_OTHER_CERT: + { + if (cert_md) { + int sig_nid = X509_get_signature_nid(other); + BIO_puts(sdb->out, OBJ_nid2sn(sig_nid)); + } else { + EVP_PKEY *pkey = X509_get0_pubkey(other); + const char *algname = ""; + EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL, + &algname, EVP_PKEY_get0_asn1(pkey)); + BIO_printf(sdb->out, "%s, bits=%d", + algname, EVP_PKEY_bits(pkey)); + } + break; + } + case SSL_SECOP_OTHER_SIGALG: + { + const unsigned char *salg = other; + const char *sname = NULL; + switch (salg[1]) { + case TLSEXT_signature_anonymous: + sname = "anonymous"; + break; + case TLSEXT_signature_rsa: + sname = "RSA"; + break; + case TLSEXT_signature_dsa: + sname = "DSA"; + break; + case TLSEXT_signature_ecdsa: + sname = "ECDSA"; + break; + } + + BIO_puts(sdb->out, OBJ_nid2sn(nid)); + if (sname) + BIO_printf(sdb->out, ", algorithm=%s", sname); + else + BIO_printf(sdb->out, ", algid=%d", salg[1]); + break; + } + + } + + if (show_bits) + BIO_printf(sdb->out, ", security bits=%d", bits); + BIO_printf(sdb->out, ": %s\n", rv ? "yes" : "no"); + return rv; +} + +void ssl_ctx_security_debug(SSL_CTX *ctx, int verbose) +{ + static security_debug_ex sdb; + + sdb.out = bio_err; + sdb.verbose = verbose; + sdb.old_cb = SSL_CTX_get_security_callback(ctx); + SSL_CTX_set_security_callback(ctx, security_callback_debug); + SSL_CTX_set0_security_ex_data(ctx, &sdb); +} + +static void keylog_callback(const SSL *ssl, const char *line) +{ + if (bio_keylog == NULL) { + BIO_printf(bio_err, "Keylog callback is invoked without valid file!\n"); + return; + } + + /* + * There might be concurrent writers to the keylog file, so we must ensure + * that the given line is written at once. + */ + BIO_printf(bio_keylog, "%s\n", line); + (void)BIO_flush(bio_keylog); +} + +int set_keylog_file(SSL_CTX *ctx, const char *keylog_file) +{ + /* Close any open files */ + BIO_free_all(bio_keylog); + bio_keylog = NULL; + + if (ctx == NULL || keylog_file == NULL) { + /* Keylogging is disabled, OK. */ + return 0; + } + + /* + * Append rather than write in order to allow concurrent modification. + * Furthermore, this preserves existing keylog files which is useful when + * the tool is run multiple times. + */ + bio_keylog = BIO_new_file(keylog_file, "a"); + if (bio_keylog == NULL) { + BIO_printf(bio_err, "Error writing keylog file %s\n", keylog_file); + return 1; + } + + /* Write a header for seekable, empty files (this excludes pipes). */ + if (BIO_tell(bio_keylog) == 0) { + BIO_puts(bio_keylog, + "# SSL/TLS secrets log file, generated by OpenSSL\n"); + (void)BIO_flush(bio_keylog); + } + SSL_CTX_set_keylog_callback(ctx, keylog_callback); + return 0; +} + +void print_ca_names(BIO *bio, SSL *s) +{ + const char *cs = SSL_is_server(s) ? "server" : "client"; + const STACK_OF(X509_NAME) *sk = SSL_get0_peer_CA_list(s); + int i; + + if (sk == NULL || sk_X509_NAME_num(sk) == 0) { + BIO_printf(bio, "---\nNo %s certificate CA names sent\n", cs); + return; + } + + BIO_printf(bio, "---\nAcceptable %s certificate CA names\n",cs); + for (i = 0; i < sk_X509_NAME_num(sk); i++) { + X509_NAME_print_ex(bio, sk_X509_NAME_value(sk, i), 0, get_nameopt()); + BIO_write(bio, "\n", 1); + } +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/s_client.c b/trunk/3rdparty/openssl-1.1-fit/apps/s_client.c new file mode 100644 index 000000000..4dd6e2fef --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/s_client.c @@ -0,0 +1,3544 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2005 Nokia. All rights reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "e_os.h" +#include +#include +#include +#include +#include +#include + +#ifndef OPENSSL_NO_SOCK + +/* + * With IPv6, it looks like Digital has mixed up the proper order of + * recursive header file inclusion, resulting in the compiler complaining + * that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which is + * needed to have fileno() declared correctly... So let's define u_int + */ +#if defined(OPENSSL_SYS_VMS_DECC) && !defined(__U_INT) +# define __U_INT +typedef unsigned int u_int; +#endif + +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef OPENSSL_NO_SRP +# include +#endif +#ifndef OPENSSL_NO_CT +# include +#endif +#include "s_apps.h" +#include "timeouts.h" +#include "internal/sockets.h" + +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) +# include +# endif +#endif + +#undef BUFSIZZ +#define BUFSIZZ 1024*8 +#define S_CLIENT_IRC_READ_TIMEOUT 8 + +static char *prog; +static int c_debug = 0; +static int c_showcerts = 0; +static char *keymatexportlabel = NULL; +static int keymatexportlen = 20; +static BIO *bio_c_out = NULL; +static int c_quiet = 0; +static char *sess_out = NULL; +static SSL_SESSION *psksess = NULL; + +static void print_stuff(BIO *berr, SSL *con, int full); +#ifndef OPENSSL_NO_OCSP +static int ocsp_resp_cb(SSL *s, void *arg); +#endif +static int ldap_ExtendedResponse_parse(const char *buf, long rem); +static int is_dNS_name(const char *host); + +static int saved_errno; + +static void save_errno(void) +{ + saved_errno = errno; + errno = 0; +} + +static int restore_errno(void) +{ + int ret = errno; + errno = saved_errno; + return ret; +} + +static void do_ssl_shutdown(SSL *ssl) +{ + int ret; + + do { + /* We only do unidirectional shutdown */ + ret = SSL_shutdown(ssl); + if (ret < 0) { + switch (SSL_get_error(ssl, ret)) { + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_ASYNC: + case SSL_ERROR_WANT_ASYNC_JOB: + /* We just do busy waiting. Nothing clever */ + continue; + } + ret = 0; + } + } while (ret < 0); +} + +/* Default PSK identity and key */ +static char *psk_identity = "Client_identity"; + +#ifndef OPENSSL_NO_PSK +static unsigned int psk_client_cb(SSL *ssl, const char *hint, char *identity, + unsigned int max_identity_len, + unsigned char *psk, + unsigned int max_psk_len) +{ + int ret; + long key_len; + unsigned char *key; + + if (c_debug) + BIO_printf(bio_c_out, "psk_client_cb\n"); + if (!hint) { + /* no ServerKeyExchange message */ + if (c_debug) + BIO_printf(bio_c_out, + "NULL received PSK identity hint, continuing anyway\n"); + } else if (c_debug) { + BIO_printf(bio_c_out, "Received PSK identity hint '%s'\n", hint); + } + + /* + * lookup PSK identity and PSK key based on the given identity hint here + */ + ret = BIO_snprintf(identity, max_identity_len, "%s", psk_identity); + if (ret < 0 || (unsigned int)ret > max_identity_len) + goto out_err; + if (c_debug) + BIO_printf(bio_c_out, "created identity '%s' len=%d\n", identity, + ret); + + /* convert the PSK key to binary */ + key = OPENSSL_hexstr2buf(psk_key, &key_len); + if (key == NULL) { + BIO_printf(bio_err, "Could not convert PSK key '%s' to buffer\n", + psk_key); + return 0; + } + if (max_psk_len > INT_MAX || key_len > (long)max_psk_len) { + BIO_printf(bio_err, + "psk buffer of callback is too small (%d) for key (%ld)\n", + max_psk_len, key_len); + OPENSSL_free(key); + return 0; + } + + memcpy(psk, key, key_len); + OPENSSL_free(key); + + if (c_debug) + BIO_printf(bio_c_out, "created PSK len=%ld\n", key_len); + + return key_len; + out_err: + if (c_debug) + BIO_printf(bio_err, "Error in PSK client callback\n"); + return 0; +} +#endif + +const unsigned char tls13_aes128gcmsha256_id[] = { 0x13, 0x01 }; +const unsigned char tls13_aes256gcmsha384_id[] = { 0x13, 0x02 }; + +static int psk_use_session_cb(SSL *s, const EVP_MD *md, + const unsigned char **id, size_t *idlen, + SSL_SESSION **sess) +{ + SSL_SESSION *usesess = NULL; + const SSL_CIPHER *cipher = NULL; + + if (psksess != NULL) { + SSL_SESSION_up_ref(psksess); + usesess = psksess; + } else { + long key_len; + unsigned char *key = OPENSSL_hexstr2buf(psk_key, &key_len); + + if (key == NULL) { + BIO_printf(bio_err, "Could not convert PSK key '%s' to buffer\n", + psk_key); + return 0; + } + + /* We default to SHA-256 */ + cipher = SSL_CIPHER_find(s, tls13_aes128gcmsha256_id); + if (cipher == NULL) { + BIO_printf(bio_err, "Error finding suitable ciphersuite\n"); + OPENSSL_free(key); + return 0; + } + + usesess = SSL_SESSION_new(); + if (usesess == NULL + || !SSL_SESSION_set1_master_key(usesess, key, key_len) + || !SSL_SESSION_set_cipher(usesess, cipher) + || !SSL_SESSION_set_protocol_version(usesess, TLS1_3_VERSION)) { + OPENSSL_free(key); + goto err; + } + OPENSSL_free(key); + } + + cipher = SSL_SESSION_get0_cipher(usesess); + if (cipher == NULL) + goto err; + + if (md != NULL && SSL_CIPHER_get_handshake_digest(cipher) != md) { + /* PSK not usable, ignore it */ + *id = NULL; + *idlen = 0; + *sess = NULL; + SSL_SESSION_free(usesess); + } else { + *sess = usesess; + *id = (unsigned char *)psk_identity; + *idlen = strlen(psk_identity); + } + + return 1; + + err: + SSL_SESSION_free(usesess); + return 0; +} + +/* This is a context that we pass to callbacks */ +typedef struct tlsextctx_st { + BIO *biodebug; + int ack; +} tlsextctx; + +static int ssl_servername_cb(SSL *s, int *ad, void *arg) +{ + tlsextctx *p = (tlsextctx *) arg; + const char *hn = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); + if (SSL_get_servername_type(s) != -1) + p->ack = !SSL_session_reused(s) && hn != NULL; + else + BIO_printf(bio_err, "Can't use SSL_get_servername\n"); + + return SSL_TLSEXT_ERR_OK; +} + +#ifndef OPENSSL_NO_SRP + +/* This is a context that we pass to all callbacks */ +typedef struct srp_arg_st { + char *srppassin; + char *srplogin; + int msg; /* copy from c_msg */ + int debug; /* copy from c_debug */ + int amp; /* allow more groups */ + int strength; /* minimal size for N */ +} SRP_ARG; + +# define SRP_NUMBER_ITERATIONS_FOR_PRIME 64 + +static int srp_Verify_N_and_g(const BIGNUM *N, const BIGNUM *g) +{ + BN_CTX *bn_ctx = BN_CTX_new(); + BIGNUM *p = BN_new(); + BIGNUM *r = BN_new(); + int ret = + g != NULL && N != NULL && bn_ctx != NULL && BN_is_odd(N) && + BN_is_prime_ex(N, SRP_NUMBER_ITERATIONS_FOR_PRIME, bn_ctx, NULL) == 1 && + p != NULL && BN_rshift1(p, N) && + /* p = (N-1)/2 */ + BN_is_prime_ex(p, SRP_NUMBER_ITERATIONS_FOR_PRIME, bn_ctx, NULL) == 1 && + r != NULL && + /* verify g^((N-1)/2) == -1 (mod N) */ + BN_mod_exp(r, g, p, N, bn_ctx) && + BN_add_word(r, 1) && BN_cmp(r, N) == 0; + + BN_free(r); + BN_free(p); + BN_CTX_free(bn_ctx); + return ret; +} + +/*- + * This callback is used here for two purposes: + * - extended debugging + * - making some primality tests for unknown groups + * The callback is only called for a non default group. + * + * An application does not need the call back at all if + * only the standard groups are used. In real life situations, + * client and server already share well known groups, + * thus there is no need to verify them. + * Furthermore, in case that a server actually proposes a group that + * is not one of those defined in RFC 5054, it is more appropriate + * to add the group to a static list and then compare since + * primality tests are rather cpu consuming. + */ + +static int ssl_srp_verify_param_cb(SSL *s, void *arg) +{ + SRP_ARG *srp_arg = (SRP_ARG *)arg; + BIGNUM *N = NULL, *g = NULL; + + if (((N = SSL_get_srp_N(s)) == NULL) || ((g = SSL_get_srp_g(s)) == NULL)) + return 0; + if (srp_arg->debug || srp_arg->msg || srp_arg->amp == 1) { + BIO_printf(bio_err, "SRP parameters:\n"); + BIO_printf(bio_err, "\tN="); + BN_print(bio_err, N); + BIO_printf(bio_err, "\n\tg="); + BN_print(bio_err, g); + BIO_printf(bio_err, "\n"); + } + + if (SRP_check_known_gN_param(g, N)) + return 1; + + if (srp_arg->amp == 1) { + if (srp_arg->debug) + BIO_printf(bio_err, + "SRP param N and g are not known params, going to check deeper.\n"); + + /* + * The srp_moregroups is a real debugging feature. Implementors + * should rather add the value to the known ones. The minimal size + * has already been tested. + */ + if (BN_num_bits(g) <= BN_BITS && srp_Verify_N_and_g(N, g)) + return 1; + } + BIO_printf(bio_err, "SRP param N and g rejected.\n"); + return 0; +} + +# define PWD_STRLEN 1024 + +static char *ssl_give_srp_client_pwd_cb(SSL *s, void *arg) +{ + SRP_ARG *srp_arg = (SRP_ARG *)arg; + char *pass = app_malloc(PWD_STRLEN + 1, "SRP password buffer"); + PW_CB_DATA cb_tmp; + int l; + + cb_tmp.password = (char *)srp_arg->srppassin; + cb_tmp.prompt_info = "SRP user"; + if ((l = password_callback(pass, PWD_STRLEN, 0, &cb_tmp)) < 0) { + BIO_printf(bio_err, "Can't read Password\n"); + OPENSSL_free(pass); + return NULL; + } + *(pass + l) = '\0'; + + return pass; +} + +#endif + +#ifndef OPENSSL_NO_NEXTPROTONEG +/* This the context that we pass to next_proto_cb */ +typedef struct tlsextnextprotoctx_st { + unsigned char *data; + size_t len; + int status; +} tlsextnextprotoctx; + +static tlsextnextprotoctx next_proto; + +static int next_proto_cb(SSL *s, unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen, + void *arg) +{ + tlsextnextprotoctx *ctx = arg; + + if (!c_quiet) { + /* We can assume that |in| is syntactically valid. */ + unsigned i; + BIO_printf(bio_c_out, "Protocols advertised by server: "); + for (i = 0; i < inlen;) { + if (i) + BIO_write(bio_c_out, ", ", 2); + BIO_write(bio_c_out, &in[i + 1], in[i]); + i += in[i] + 1; + } + BIO_write(bio_c_out, "\n", 1); + } + + ctx->status = + SSL_select_next_proto(out, outlen, in, inlen, ctx->data, ctx->len); + return SSL_TLSEXT_ERR_OK; +} +#endif /* ndef OPENSSL_NO_NEXTPROTONEG */ + +static int serverinfo_cli_parse_cb(SSL *s, unsigned int ext_type, + const unsigned char *in, size_t inlen, + int *al, void *arg) +{ + char pem_name[100]; + unsigned char ext_buf[4 + 65536]; + + /* Reconstruct the type/len fields prior to extension data */ + inlen &= 0xffff; /* for formal memcmpy correctness */ + ext_buf[0] = (unsigned char)(ext_type >> 8); + ext_buf[1] = (unsigned char)(ext_type); + ext_buf[2] = (unsigned char)(inlen >> 8); + ext_buf[3] = (unsigned char)(inlen); + memcpy(ext_buf + 4, in, inlen); + + BIO_snprintf(pem_name, sizeof(pem_name), "SERVERINFO FOR EXTENSION %d", + ext_type); + PEM_write_bio(bio_c_out, pem_name, "", ext_buf, 4 + inlen); + return 1; +} + +/* + * Hex decoder that tolerates optional whitespace. Returns number of bytes + * produced, advances inptr to end of input string. + */ +static ossl_ssize_t hexdecode(const char **inptr, void *result) +{ + unsigned char **out = (unsigned char **)result; + const char *in = *inptr; + unsigned char *ret = app_malloc(strlen(in) / 2, "hexdecode"); + unsigned char *cp = ret; + uint8_t byte; + int nibble = 0; + + if (ret == NULL) + return -1; + + for (byte = 0; *in; ++in) { + int x; + + if (isspace(_UC(*in))) + continue; + x = OPENSSL_hexchar2int(*in); + if (x < 0) { + OPENSSL_free(ret); + return 0; + } + byte |= (char)x; + if ((nibble ^= 1) == 0) { + *cp++ = byte; + byte = 0; + } else { + byte <<= 4; + } + } + if (nibble != 0) { + OPENSSL_free(ret); + return 0; + } + *inptr = in; + + return cp - (*out = ret); +} + +/* + * Decode unsigned 0..255, returns 1 on success, <= 0 on failure. Advances + * inptr to next field skipping leading whitespace. + */ +static ossl_ssize_t checked_uint8(const char **inptr, void *out) +{ + uint8_t *result = (uint8_t *)out; + const char *in = *inptr; + char *endp; + long v; + int e; + + save_errno(); + v = strtol(in, &endp, 10); + e = restore_errno(); + + if (((v == LONG_MIN || v == LONG_MAX) && e == ERANGE) || + endp == in || !isspace(_UC(*endp)) || + v != (*result = (uint8_t) v)) { + return -1; + } + for (in = endp; isspace(_UC(*in)); ++in) + continue; + + *inptr = in; + return 1; +} + +struct tlsa_field { + void *var; + const char *name; + ossl_ssize_t (*parser)(const char **, void *); +}; + +static int tlsa_import_rr(SSL *con, const char *rrdata) +{ + /* Not necessary to re-init these values; the "parsers" do that. */ + static uint8_t usage; + static uint8_t selector; + static uint8_t mtype; + static unsigned char *data; + static struct tlsa_field tlsa_fields[] = { + { &usage, "usage", checked_uint8 }, + { &selector, "selector", checked_uint8 }, + { &mtype, "mtype", checked_uint8 }, + { &data, "data", hexdecode }, + { NULL, } + }; + struct tlsa_field *f; + int ret; + const char *cp = rrdata; + ossl_ssize_t len = 0; + + for (f = tlsa_fields; f->var; ++f) { + /* Returns number of bytes produced, advances cp to next field */ + if ((len = f->parser(&cp, f->var)) <= 0) { + BIO_printf(bio_err, "%s: warning: bad TLSA %s field in: %s\n", + prog, f->name, rrdata); + return 0; + } + } + /* The data field is last, so len is its length */ + ret = SSL_dane_tlsa_add(con, usage, selector, mtype, data, len); + OPENSSL_free(data); + + if (ret == 0) { + ERR_print_errors(bio_err); + BIO_printf(bio_err, "%s: warning: unusable TLSA rrdata: %s\n", + prog, rrdata); + return 0; + } + if (ret < 0) { + ERR_print_errors(bio_err); + BIO_printf(bio_err, "%s: warning: error loading TLSA rrdata: %s\n", + prog, rrdata); + return 0; + } + return ret; +} + +static int tlsa_import_rrset(SSL *con, STACK_OF(OPENSSL_STRING) *rrset) +{ + int num = sk_OPENSSL_STRING_num(rrset); + int count = 0; + int i; + + for (i = 0; i < num; ++i) { + char *rrdata = sk_OPENSSL_STRING_value(rrset, i); + if (tlsa_import_rr(con, rrdata) > 0) + ++count; + } + return count > 0; +} + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_4, OPT_6, OPT_HOST, OPT_PORT, OPT_CONNECT, OPT_BIND, OPT_UNIX, + OPT_XMPPHOST, OPT_VERIFY, OPT_NAMEOPT, + OPT_CERT, OPT_CRL, OPT_CRL_DOWNLOAD, OPT_SESS_OUT, OPT_SESS_IN, + OPT_CERTFORM, OPT_CRLFORM, OPT_VERIFY_RET_ERROR, OPT_VERIFY_QUIET, + OPT_BRIEF, OPT_PREXIT, OPT_CRLF, OPT_QUIET, OPT_NBIO, + OPT_SSL_CLIENT_ENGINE, OPT_IGN_EOF, OPT_NO_IGN_EOF, + OPT_DEBUG, OPT_TLSEXTDEBUG, OPT_STATUS, OPT_WDEBUG, + OPT_MSG, OPT_MSGFILE, OPT_ENGINE, OPT_TRACE, OPT_SECURITY_DEBUG, + OPT_SECURITY_DEBUG_VERBOSE, OPT_SHOWCERTS, OPT_NBIO_TEST, OPT_STATE, + OPT_PSK_IDENTITY, OPT_PSK, OPT_PSK_SESS, +#ifndef OPENSSL_NO_SRP + OPT_SRPUSER, OPT_SRPPASS, OPT_SRP_STRENGTH, OPT_SRP_LATEUSER, + OPT_SRP_MOREGROUPS, +#endif + OPT_SSL3, OPT_SSL_CONFIG, + OPT_TLS1_3, OPT_TLS1_2, OPT_TLS1_1, OPT_TLS1, OPT_DTLS, OPT_DTLS1, + OPT_DTLS1_2, OPT_SCTP, OPT_TIMEOUT, OPT_MTU, OPT_KEYFORM, OPT_PASS, + OPT_CERT_CHAIN, OPT_CAPATH, OPT_NOCAPATH, OPT_CHAINCAPATH, OPT_VERIFYCAPATH, + OPT_KEY, OPT_RECONNECT, OPT_BUILD_CHAIN, OPT_CAFILE, OPT_NOCAFILE, + OPT_CHAINCAFILE, OPT_VERIFYCAFILE, OPT_NEXTPROTONEG, OPT_ALPN, + OPT_SERVERINFO, OPT_STARTTLS, OPT_SERVERNAME, OPT_NOSERVERNAME, OPT_ASYNC, + OPT_USE_SRTP, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN, OPT_PROTOHOST, + OPT_MAXFRAGLEN, OPT_MAX_SEND_FRAG, OPT_SPLIT_SEND_FRAG, OPT_MAX_PIPELINES, + OPT_READ_BUF, OPT_KEYLOG_FILE, OPT_EARLY_DATA, OPT_REQCAFILE, + OPT_V_ENUM, + OPT_X_ENUM, + OPT_S_ENUM, + OPT_FALLBACKSCSV, OPT_NOCMDS, OPT_PROXY, OPT_DANE_TLSA_DOMAIN, +#ifndef OPENSSL_NO_CT + OPT_CT, OPT_NOCT, OPT_CTLOG_FILE, +#endif + OPT_DANE_TLSA_RRDATA, OPT_DANE_EE_NO_NAME, + OPT_ENABLE_PHA, + OPT_SCTP_LABEL_BUG, + OPT_R_ENUM +} OPTION_CHOICE; + +const OPTIONS s_client_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"host", OPT_HOST, 's', "Use -connect instead"}, + {"port", OPT_PORT, 'p', "Use -connect instead"}, + {"connect", OPT_CONNECT, 's', + "TCP/IP where to connect (default is :" PORT ")"}, + {"bind", OPT_BIND, 's', "bind local address for connection"}, + {"proxy", OPT_PROXY, 's', + "Connect to via specified proxy to the real server"}, +#ifdef AF_UNIX + {"unix", OPT_UNIX, 's', "Connect over the specified Unix-domain socket"}, +#endif + {"4", OPT_4, '-', "Use IPv4 only"}, +#ifdef AF_INET6 + {"6", OPT_6, '-', "Use IPv6 only"}, +#endif + {"verify", OPT_VERIFY, 'p', "Turn on peer certificate verification"}, + {"cert", OPT_CERT, '<', "Certificate file to use, PEM format assumed"}, + {"certform", OPT_CERTFORM, 'F', + "Certificate format (PEM or DER) PEM default"}, + {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"}, + {"key", OPT_KEY, 's', "Private key file to use, if not in -cert file"}, + {"keyform", OPT_KEYFORM, 'E', "Key format (PEM, DER or engine) PEM default"}, + {"pass", OPT_PASS, 's', "Private key file pass phrase source"}, + {"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"}, + {"CAfile", OPT_CAFILE, '<', "PEM format file of CA's"}, + {"no-CAfile", OPT_NOCAFILE, '-', + "Do not load the default certificates file"}, + {"no-CApath", OPT_NOCAPATH, '-', + "Do not load certificates from the default certificates directory"}, + {"requestCAfile", OPT_REQCAFILE, '<', + "PEM format file of CA names to send to the server"}, + {"dane_tlsa_domain", OPT_DANE_TLSA_DOMAIN, 's', "DANE TLSA base domain"}, + {"dane_tlsa_rrdata", OPT_DANE_TLSA_RRDATA, 's', + "DANE TLSA rrdata presentation form"}, + {"dane_ee_no_namechecks", OPT_DANE_EE_NO_NAME, '-', + "Disable name checks when matching DANE-EE(3) TLSA records"}, + {"reconnect", OPT_RECONNECT, '-', + "Drop and re-make the connection with the same Session-ID"}, + {"showcerts", OPT_SHOWCERTS, '-', + "Show all certificates sent by the server"}, + {"debug", OPT_DEBUG, '-', "Extra output"}, + {"msg", OPT_MSG, '-', "Show protocol messages"}, + {"msgfile", OPT_MSGFILE, '>', + "File to send output of -msg or -trace, instead of stdout"}, + {"nbio_test", OPT_NBIO_TEST, '-', "More ssl protocol testing"}, + {"state", OPT_STATE, '-', "Print the ssl states"}, + {"crlf", OPT_CRLF, '-', "Convert LF from terminal into CRLF"}, + {"quiet", OPT_QUIET, '-', "No s_client output"}, + {"ign_eof", OPT_IGN_EOF, '-', "Ignore input eof (default when -quiet)"}, + {"no_ign_eof", OPT_NO_IGN_EOF, '-', "Don't ignore input eof"}, + {"starttls", OPT_STARTTLS, 's', + "Use the appropriate STARTTLS command before starting TLS"}, + {"xmpphost", OPT_XMPPHOST, 's', + "Alias of -name option for \"-starttls xmpp[-server]\""}, + OPT_R_OPTIONS, + {"sess_out", OPT_SESS_OUT, '>', "File to write SSL session to"}, + {"sess_in", OPT_SESS_IN, '<', "File to read SSL session from"}, +#ifndef OPENSSL_NO_SRTP + {"use_srtp", OPT_USE_SRTP, 's', + "Offer SRTP key management with a colon-separated profile list"}, +#endif + {"keymatexport", OPT_KEYMATEXPORT, 's', + "Export keying material using label"}, + {"keymatexportlen", OPT_KEYMATEXPORTLEN, 'p', + "Export len bytes of keying material (default 20)"}, + {"maxfraglen", OPT_MAXFRAGLEN, 'p', + "Enable Maximum Fragment Length Negotiation (len values: 512, 1024, 2048 and 4096)"}, + {"fallback_scsv", OPT_FALLBACKSCSV, '-', "Send the fallback SCSV"}, + {"name", OPT_PROTOHOST, 's', + "Hostname to use for \"-starttls lmtp\", \"-starttls smtp\" or \"-starttls xmpp[-server]\""}, + {"CRL", OPT_CRL, '<', "CRL file to use"}, + {"crl_download", OPT_CRL_DOWNLOAD, '-', "Download CRL from distribution points"}, + {"CRLform", OPT_CRLFORM, 'F', "CRL format (PEM or DER) PEM is default"}, + {"verify_return_error", OPT_VERIFY_RET_ERROR, '-', + "Close connection on verification error"}, + {"verify_quiet", OPT_VERIFY_QUIET, '-', "Restrict verify output to errors"}, + {"brief", OPT_BRIEF, '-', + "Restrict output to brief summary of connection parameters"}, + {"prexit", OPT_PREXIT, '-', + "Print session information when the program exits"}, + {"security_debug", OPT_SECURITY_DEBUG, '-', + "Enable security debug messages"}, + {"security_debug_verbose", OPT_SECURITY_DEBUG_VERBOSE, '-', + "Output more security debug output"}, + {"cert_chain", OPT_CERT_CHAIN, '<', + "Certificate chain file (in PEM format)"}, + {"chainCApath", OPT_CHAINCAPATH, '/', + "Use dir as certificate store path to build CA certificate chain"}, + {"verifyCApath", OPT_VERIFYCAPATH, '/', + "Use dir as certificate store path to verify CA certificate"}, + {"build_chain", OPT_BUILD_CHAIN, '-', "Build certificate chain"}, + {"chainCAfile", OPT_CHAINCAFILE, '<', + "CA file for certificate chain (PEM format)"}, + {"verifyCAfile", OPT_VERIFYCAFILE, '<', + "CA file for certificate verification (PEM format)"}, + {"nocommands", OPT_NOCMDS, '-', "Do not use interactive command letters"}, + {"servername", OPT_SERVERNAME, 's', + "Set TLS extension servername (SNI) in ClientHello (default)"}, + {"noservername", OPT_NOSERVERNAME, '-', + "Do not send the server name (SNI) extension in the ClientHello"}, + {"tlsextdebug", OPT_TLSEXTDEBUG, '-', + "Hex dump of all TLS extensions received"}, +#ifndef OPENSSL_NO_OCSP + {"status", OPT_STATUS, '-', "Request certificate status from server"}, +#endif + {"serverinfo", OPT_SERVERINFO, 's', + "types Send empty ClientHello extensions (comma-separated numbers)"}, + {"alpn", OPT_ALPN, 's', + "Enable ALPN extension, considering named protocols supported (comma-separated list)"}, + {"async", OPT_ASYNC, '-', "Support asynchronous operation"}, + {"ssl_config", OPT_SSL_CONFIG, 's', "Use specified configuration file"}, + {"max_send_frag", OPT_MAX_SEND_FRAG, 'p', "Maximum Size of send frames "}, + {"split_send_frag", OPT_SPLIT_SEND_FRAG, 'p', + "Size used to split data for encrypt pipelines"}, + {"max_pipelines", OPT_MAX_PIPELINES, 'p', + "Maximum number of encrypt/decrypt pipelines to be used"}, + {"read_buf", OPT_READ_BUF, 'p', + "Default read buffer size to be used for connections"}, + OPT_S_OPTIONS, + OPT_V_OPTIONS, + OPT_X_OPTIONS, +#ifndef OPENSSL_NO_SSL3 + {"ssl3", OPT_SSL3, '-', "Just use SSLv3"}, +#endif +#ifndef OPENSSL_NO_TLS1 + {"tls1", OPT_TLS1, '-', "Just use TLSv1"}, +#endif +#ifndef OPENSSL_NO_TLS1_1 + {"tls1_1", OPT_TLS1_1, '-', "Just use TLSv1.1"}, +#endif +#ifndef OPENSSL_NO_TLS1_2 + {"tls1_2", OPT_TLS1_2, '-', "Just use TLSv1.2"}, +#endif +#ifndef OPENSSL_NO_TLS1_3 + {"tls1_3", OPT_TLS1_3, '-', "Just use TLSv1.3"}, +#endif +#ifndef OPENSSL_NO_DTLS + {"dtls", OPT_DTLS, '-', "Use any version of DTLS"}, + {"timeout", OPT_TIMEOUT, '-', + "Enable send/receive timeout on DTLS connections"}, + {"mtu", OPT_MTU, 'p', "Set the link layer MTU"}, +#endif +#ifndef OPENSSL_NO_DTLS1 + {"dtls1", OPT_DTLS1, '-', "Just use DTLSv1"}, +#endif +#ifndef OPENSSL_NO_DTLS1_2 + {"dtls1_2", OPT_DTLS1_2, '-', "Just use DTLSv1.2"}, +#endif +#ifndef OPENSSL_NO_SCTP + {"sctp", OPT_SCTP, '-', "Use SCTP"}, + {"sctp_label_bug", OPT_SCTP_LABEL_BUG, '-', "Enable SCTP label length bug"}, +#endif +#ifndef OPENSSL_NO_SSL_TRACE + {"trace", OPT_TRACE, '-', "Show trace output of protocol messages"}, +#endif +#ifdef WATT32 + {"wdebug", OPT_WDEBUG, '-', "WATT-32 tcp debugging"}, +#endif + {"nbio", OPT_NBIO, '-', "Use non-blocking IO"}, + {"psk_identity", OPT_PSK_IDENTITY, 's', "PSK identity"}, + {"psk", OPT_PSK, 's', "PSK in hex (without 0x)"}, + {"psk_session", OPT_PSK_SESS, '<', "File to read PSK SSL session from"}, +#ifndef OPENSSL_NO_SRP + {"srpuser", OPT_SRPUSER, 's', "SRP authentication for 'user'"}, + {"srppass", OPT_SRPPASS, 's', "Password for 'user'"}, + {"srp_lateuser", OPT_SRP_LATEUSER, '-', + "SRP username into second ClientHello message"}, + {"srp_moregroups", OPT_SRP_MOREGROUPS, '-', + "Tolerate other than the known g N values."}, + {"srp_strength", OPT_SRP_STRENGTH, 'p', "Minimal length in bits for N"}, +#endif +#ifndef OPENSSL_NO_NEXTPROTONEG + {"nextprotoneg", OPT_NEXTPROTONEG, 's', + "Enable NPN extension, considering named protocols supported (comma-separated list)"}, +#endif +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, + {"ssl_client_engine", OPT_SSL_CLIENT_ENGINE, 's', + "Specify engine to be used for client certificate operations"}, +#endif +#ifndef OPENSSL_NO_CT + {"ct", OPT_CT, '-', "Request and parse SCTs (also enables OCSP stapling)"}, + {"noct", OPT_NOCT, '-', "Do not request or parse SCTs (default)"}, + {"ctlogfile", OPT_CTLOG_FILE, '<', "CT log list CONF file"}, +#endif + {"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"}, + {"early_data", OPT_EARLY_DATA, '<', "File to send as early data"}, + {"enable_pha", OPT_ENABLE_PHA, '-', "Enable post-handshake-authentication"}, + {NULL, OPT_EOF, 0x00, NULL} +}; + +typedef enum PROTOCOL_choice { + PROTO_OFF, + PROTO_SMTP, + PROTO_POP3, + PROTO_IMAP, + PROTO_FTP, + PROTO_TELNET, + PROTO_XMPP, + PROTO_XMPP_SERVER, + PROTO_CONNECT, + PROTO_IRC, + PROTO_MYSQL, + PROTO_POSTGRES, + PROTO_LMTP, + PROTO_NNTP, + PROTO_SIEVE, + PROTO_LDAP +} PROTOCOL_CHOICE; + +static const OPT_PAIR services[] = { + {"smtp", PROTO_SMTP}, + {"pop3", PROTO_POP3}, + {"imap", PROTO_IMAP}, + {"ftp", PROTO_FTP}, + {"xmpp", PROTO_XMPP}, + {"xmpp-server", PROTO_XMPP_SERVER}, + {"telnet", PROTO_TELNET}, + {"irc", PROTO_IRC}, + {"mysql", PROTO_MYSQL}, + {"postgres", PROTO_POSTGRES}, + {"lmtp", PROTO_LMTP}, + {"nntp", PROTO_NNTP}, + {"sieve", PROTO_SIEVE}, + {"ldap", PROTO_LDAP}, + {NULL, 0} +}; + +#define IS_INET_FLAG(o) \ + (o == OPT_4 || o == OPT_6 || o == OPT_HOST || o == OPT_PORT || o == OPT_CONNECT) +#define IS_UNIX_FLAG(o) (o == OPT_UNIX) + +#define IS_PROT_FLAG(o) \ + (o == OPT_SSL3 || o == OPT_TLS1 || o == OPT_TLS1_1 || o == OPT_TLS1_2 \ + || o == OPT_TLS1_3 || o == OPT_DTLS || o == OPT_DTLS1 || o == OPT_DTLS1_2) + +/* Free |*dest| and optionally set it to a copy of |source|. */ +static void freeandcopy(char **dest, const char *source) +{ + OPENSSL_free(*dest); + *dest = NULL; + if (source != NULL) + *dest = OPENSSL_strdup(source); +} + +static int new_session_cb(SSL *s, SSL_SESSION *sess) +{ + + if (sess_out != NULL) { + BIO *stmp = BIO_new_file(sess_out, "w"); + + if (stmp == NULL) { + BIO_printf(bio_err, "Error writing session file %s\n", sess_out); + } else { + PEM_write_bio_SSL_SESSION(stmp, sess); + BIO_free(stmp); + } + } + + /* + * Session data gets dumped on connection for TLSv1.2 and below, and on + * arrival of the NewSessionTicket for TLSv1.3. + */ + if (SSL_version(s) == TLS1_3_VERSION) { + BIO_printf(bio_c_out, + "---\nPost-Handshake New Session Ticket arrived:\n"); + SSL_SESSION_print(bio_c_out, sess); + BIO_printf(bio_c_out, "---\n"); + } + + /* + * We always return a "fail" response so that the session gets freed again + * because we haven't used the reference. + */ + return 0; +} + +int s_client_main(int argc, char **argv) +{ + BIO *sbio; + EVP_PKEY *key = NULL; + SSL *con = NULL; + SSL_CTX *ctx = NULL; + STACK_OF(X509) *chain = NULL; + X509 *cert = NULL; + X509_VERIFY_PARAM *vpm = NULL; + SSL_EXCERT *exc = NULL; + SSL_CONF_CTX *cctx = NULL; + STACK_OF(OPENSSL_STRING) *ssl_args = NULL; + char *dane_tlsa_domain = NULL; + STACK_OF(OPENSSL_STRING) *dane_tlsa_rrset = NULL; + int dane_ee_no_name = 0; + STACK_OF(X509_CRL) *crls = NULL; + const SSL_METHOD *meth = TLS_client_method(); + const char *CApath = NULL, *CAfile = NULL; + char *cbuf = NULL, *sbuf = NULL; + char *mbuf = NULL, *proxystr = NULL, *connectstr = NULL, *bindstr = NULL; + char *cert_file = NULL, *key_file = NULL, *chain_file = NULL; + char *chCApath = NULL, *chCAfile = NULL, *host = NULL; + char *port = OPENSSL_strdup(PORT); + char *bindhost = NULL, *bindport = NULL; + char *passarg = NULL, *pass = NULL, *vfyCApath = NULL, *vfyCAfile = NULL; + char *ReqCAfile = NULL; + char *sess_in = NULL, *crl_file = NULL, *p; + const char *protohost = NULL; + struct timeval timeout, *timeoutp; + fd_set readfds, writefds; + int noCApath = 0, noCAfile = 0; + int build_chain = 0, cbuf_len, cbuf_off, cert_format = FORMAT_PEM; + int key_format = FORMAT_PEM, crlf = 0, full_log = 1, mbuf_len = 0; + int prexit = 0; + int sdebug = 0; + int reconnect = 0, verify = SSL_VERIFY_NONE, vpmtouched = 0; + int ret = 1, in_init = 1, i, nbio_test = 0, s = -1, k, width, state = 0; + int sbuf_len, sbuf_off, cmdletters = 1; + int socket_family = AF_UNSPEC, socket_type = SOCK_STREAM, protocol = 0; + int starttls_proto = PROTO_OFF, crl_format = FORMAT_PEM, crl_download = 0; + int write_tty, read_tty, write_ssl, read_ssl, tty_on, ssl_pending; +#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) + int at_eof = 0; +#endif + int read_buf_len = 0; + int fallback_scsv = 0; + OPTION_CHOICE o; +#ifndef OPENSSL_NO_DTLS + int enable_timeouts = 0; + long socket_mtu = 0; +#endif +#ifndef OPENSSL_NO_ENGINE + ENGINE *ssl_client_engine = NULL; +#endif + ENGINE *e = NULL; +#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) + struct timeval tv; +#endif + const char *servername = NULL; + int noservername = 0; + const char *alpn_in = NULL; + tlsextctx tlsextcbp = { NULL, 0 }; + const char *ssl_config = NULL; +#define MAX_SI_TYPES 100 + unsigned short serverinfo_types[MAX_SI_TYPES]; + int serverinfo_count = 0, start = 0, len; +#ifndef OPENSSL_NO_NEXTPROTONEG + const char *next_proto_neg_in = NULL; +#endif +#ifndef OPENSSL_NO_SRP + char *srppass = NULL; + int srp_lateuser = 0; + SRP_ARG srp_arg = { NULL, NULL, 0, 0, 0, 1024 }; +#endif +#ifndef OPENSSL_NO_SRTP + char *srtp_profiles = NULL; +#endif +#ifndef OPENSSL_NO_CT + char *ctlog_file = NULL; + int ct_validation = 0; +#endif + int min_version = 0, max_version = 0, prot_opt = 0, no_prot_opt = 0; + int async = 0; + unsigned int max_send_fragment = 0; + unsigned int split_send_fragment = 0, max_pipelines = 0; + enum { use_inet, use_unix, use_unknown } connect_type = use_unknown; + int count4or6 = 0; + uint8_t maxfraglen = 0; + int c_nbio = 0, c_msg = 0, c_ign_eof = 0, c_brief = 0; + int c_tlsextdebug = 0; +#ifndef OPENSSL_NO_OCSP + int c_status_req = 0; +#endif + BIO *bio_c_msg = NULL; + const char *keylog_file = NULL, *early_data_file = NULL; +#ifndef OPENSSL_NO_DTLS + int isdtls = 0; +#endif + char *psksessf = NULL; + int enable_pha = 0; +#ifndef OPENSSL_NO_SCTP + int sctp_label_bug = 0; +#endif + + FD_ZERO(&readfds); + FD_ZERO(&writefds); +/* Known false-positive of MemorySanitizer. */ +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) + __msan_unpoison(&readfds, sizeof(readfds)); + __msan_unpoison(&writefds, sizeof(writefds)); +# endif +#endif + + prog = opt_progname(argv[0]); + c_quiet = 0; + c_debug = 0; + c_showcerts = 0; + c_nbio = 0; + vpm = X509_VERIFY_PARAM_new(); + cctx = SSL_CONF_CTX_new(); + + if (vpm == NULL || cctx == NULL) { + BIO_printf(bio_err, "%s: out of memory\n", prog); + goto end; + } + + cbuf = app_malloc(BUFSIZZ, "cbuf"); + sbuf = app_malloc(BUFSIZZ, "sbuf"); + mbuf = app_malloc(BUFSIZZ, "mbuf"); + + SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CLIENT | SSL_CONF_FLAG_CMDLINE); + + prog = opt_init(argc, argv, s_client_options); + while ((o = opt_next()) != OPT_EOF) { + /* Check for intermixing flags. */ + if (connect_type == use_unix && IS_INET_FLAG(o)) { + BIO_printf(bio_err, + "%s: Intermixed protocol flags (unix and internet domains)\n", + prog); + goto end; + } + if (connect_type == use_inet && IS_UNIX_FLAG(o)) { + BIO_printf(bio_err, + "%s: Intermixed protocol flags (internet and unix domains)\n", + prog); + goto end; + } + + if (IS_PROT_FLAG(o) && ++prot_opt > 1) { + BIO_printf(bio_err, "Cannot supply multiple protocol flags\n"); + goto end; + } + if (IS_NO_PROT_FLAG(o)) + no_prot_opt++; + if (prot_opt == 1 && no_prot_opt) { + BIO_printf(bio_err, + "Cannot supply both a protocol flag and '-no_'\n"); + goto end; + } + + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(s_client_options); + ret = 0; + goto end; + case OPT_4: + connect_type = use_inet; + socket_family = AF_INET; + count4or6++; + break; +#ifdef AF_INET6 + case OPT_6: + connect_type = use_inet; + socket_family = AF_INET6; + count4or6++; + break; +#endif + case OPT_HOST: + connect_type = use_inet; + freeandcopy(&host, opt_arg()); + break; + case OPT_PORT: + connect_type = use_inet; + freeandcopy(&port, opt_arg()); + break; + case OPT_CONNECT: + connect_type = use_inet; + freeandcopy(&connectstr, opt_arg()); + break; + case OPT_BIND: + freeandcopy(&bindstr, opt_arg()); + break; + case OPT_PROXY: + proxystr = opt_arg(); + starttls_proto = PROTO_CONNECT; + break; +#ifdef AF_UNIX + case OPT_UNIX: + connect_type = use_unix; + socket_family = AF_UNIX; + freeandcopy(&host, opt_arg()); + break; +#endif + case OPT_XMPPHOST: + /* fall through, since this is an alias */ + case OPT_PROTOHOST: + protohost = opt_arg(); + break; + case OPT_VERIFY: + verify = SSL_VERIFY_PEER; + verify_args.depth = atoi(opt_arg()); + if (!c_quiet) + BIO_printf(bio_err, "verify depth is %d\n", verify_args.depth); + break; + case OPT_CERT: + cert_file = opt_arg(); + break; + case OPT_NAMEOPT: + if (!set_nameopt(opt_arg())) + goto end; + break; + case OPT_CRL: + crl_file = opt_arg(); + break; + case OPT_CRL_DOWNLOAD: + crl_download = 1; + break; + case OPT_SESS_OUT: + sess_out = opt_arg(); + break; + case OPT_SESS_IN: + sess_in = opt_arg(); + break; + case OPT_CERTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &cert_format)) + goto opthelp; + break; + case OPT_CRLFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &crl_format)) + goto opthelp; + break; + case OPT_VERIFY_RET_ERROR: + verify = SSL_VERIFY_PEER; + verify_args.return_error = 1; + break; + case OPT_VERIFY_QUIET: + verify_args.quiet = 1; + break; + case OPT_BRIEF: + c_brief = verify_args.quiet = c_quiet = 1; + break; + case OPT_S_CASES: + if (ssl_args == NULL) + ssl_args = sk_OPENSSL_STRING_new_null(); + if (ssl_args == NULL + || !sk_OPENSSL_STRING_push(ssl_args, opt_flag()) + || !sk_OPENSSL_STRING_push(ssl_args, opt_arg())) { + BIO_printf(bio_err, "%s: Memory allocation failure\n", prog); + goto end; + } + break; + case OPT_V_CASES: + if (!opt_verify(o, vpm)) + goto end; + vpmtouched++; + break; + case OPT_X_CASES: + if (!args_excert(o, &exc)) + goto end; + break; + case OPT_PREXIT: + prexit = 1; + break; + case OPT_CRLF: + crlf = 1; + break; + case OPT_QUIET: + c_quiet = c_ign_eof = 1; + break; + case OPT_NBIO: + c_nbio = 1; + break; + case OPT_NOCMDS: + cmdletters = 0; + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 1); + break; + case OPT_SSL_CLIENT_ENGINE: +#ifndef OPENSSL_NO_ENGINE + ssl_client_engine = ENGINE_by_id(opt_arg()); + if (ssl_client_engine == NULL) { + BIO_printf(bio_err, "Error getting client auth engine\n"); + goto opthelp; + } +#endif + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_IGN_EOF: + c_ign_eof = 1; + break; + case OPT_NO_IGN_EOF: + c_ign_eof = 0; + break; + case OPT_DEBUG: + c_debug = 1; + break; + case OPT_TLSEXTDEBUG: + c_tlsextdebug = 1; + break; + case OPT_STATUS: +#ifndef OPENSSL_NO_OCSP + c_status_req = 1; +#endif + break; + case OPT_WDEBUG: +#ifdef WATT32 + dbug_init(); +#endif + break; + case OPT_MSG: + c_msg = 1; + break; + case OPT_MSGFILE: + bio_c_msg = BIO_new_file(opt_arg(), "w"); + break; + case OPT_TRACE: +#ifndef OPENSSL_NO_SSL_TRACE + c_msg = 2; +#endif + break; + case OPT_SECURITY_DEBUG: + sdebug = 1; + break; + case OPT_SECURITY_DEBUG_VERBOSE: + sdebug = 2; + break; + case OPT_SHOWCERTS: + c_showcerts = 1; + break; + case OPT_NBIO_TEST: + nbio_test = 1; + break; + case OPT_STATE: + state = 1; + break; + case OPT_PSK_IDENTITY: + psk_identity = opt_arg(); + break; + case OPT_PSK: + for (p = psk_key = opt_arg(); *p; p++) { + if (isxdigit(_UC(*p))) + continue; + BIO_printf(bio_err, "Not a hex number '%s'\n", psk_key); + goto end; + } + break; + case OPT_PSK_SESS: + psksessf = opt_arg(); + break; +#ifndef OPENSSL_NO_SRP + case OPT_SRPUSER: + srp_arg.srplogin = opt_arg(); + if (min_version < TLS1_VERSION) + min_version = TLS1_VERSION; + break; + case OPT_SRPPASS: + srppass = opt_arg(); + if (min_version < TLS1_VERSION) + min_version = TLS1_VERSION; + break; + case OPT_SRP_STRENGTH: + srp_arg.strength = atoi(opt_arg()); + BIO_printf(bio_err, "SRP minimal length for N is %d\n", + srp_arg.strength); + if (min_version < TLS1_VERSION) + min_version = TLS1_VERSION; + break; + case OPT_SRP_LATEUSER: + srp_lateuser = 1; + if (min_version < TLS1_VERSION) + min_version = TLS1_VERSION; + break; + case OPT_SRP_MOREGROUPS: + srp_arg.amp = 1; + if (min_version < TLS1_VERSION) + min_version = TLS1_VERSION; + break; +#endif + case OPT_SSL_CONFIG: + ssl_config = opt_arg(); + break; + case OPT_SSL3: + min_version = SSL3_VERSION; + max_version = SSL3_VERSION; + break; + case OPT_TLS1_3: + min_version = TLS1_3_VERSION; + max_version = TLS1_3_VERSION; + break; + case OPT_TLS1_2: + min_version = TLS1_2_VERSION; + max_version = TLS1_2_VERSION; + break; + case OPT_TLS1_1: + min_version = TLS1_1_VERSION; + max_version = TLS1_1_VERSION; + break; + case OPT_TLS1: + min_version = TLS1_VERSION; + max_version = TLS1_VERSION; + break; + case OPT_DTLS: +#ifndef OPENSSL_NO_DTLS + meth = DTLS_client_method(); + socket_type = SOCK_DGRAM; + isdtls = 1; +#endif + break; + case OPT_DTLS1: +#ifndef OPENSSL_NO_DTLS1 + meth = DTLS_client_method(); + min_version = DTLS1_VERSION; + max_version = DTLS1_VERSION; + socket_type = SOCK_DGRAM; + isdtls = 1; +#endif + break; + case OPT_DTLS1_2: +#ifndef OPENSSL_NO_DTLS1_2 + meth = DTLS_client_method(); + min_version = DTLS1_2_VERSION; + max_version = DTLS1_2_VERSION; + socket_type = SOCK_DGRAM; + isdtls = 1; +#endif + break; + case OPT_SCTP: +#ifndef OPENSSL_NO_SCTP + protocol = IPPROTO_SCTP; +#endif + break; + case OPT_SCTP_LABEL_BUG: +#ifndef OPENSSL_NO_SCTP + sctp_label_bug = 1; +#endif + break; + case OPT_TIMEOUT: +#ifndef OPENSSL_NO_DTLS + enable_timeouts = 1; +#endif + break; + case OPT_MTU: +#ifndef OPENSSL_NO_DTLS + socket_mtu = atol(opt_arg()); +#endif + break; + case OPT_FALLBACKSCSV: + fallback_scsv = 1; + break; + case OPT_KEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_PDE, &key_format)) + goto opthelp; + break; + case OPT_PASS: + passarg = opt_arg(); + break; + case OPT_CERT_CHAIN: + chain_file = opt_arg(); + break; + case OPT_KEY: + key_file = opt_arg(); + break; + case OPT_RECONNECT: + reconnect = 5; + break; + case OPT_CAPATH: + CApath = opt_arg(); + break; + case OPT_NOCAPATH: + noCApath = 1; + break; + case OPT_CHAINCAPATH: + chCApath = opt_arg(); + break; + case OPT_VERIFYCAPATH: + vfyCApath = opt_arg(); + break; + case OPT_BUILD_CHAIN: + build_chain = 1; + break; + case OPT_REQCAFILE: + ReqCAfile = opt_arg(); + break; + case OPT_CAFILE: + CAfile = opt_arg(); + break; + case OPT_NOCAFILE: + noCAfile = 1; + break; +#ifndef OPENSSL_NO_CT + case OPT_NOCT: + ct_validation = 0; + break; + case OPT_CT: + ct_validation = 1; + break; + case OPT_CTLOG_FILE: + ctlog_file = opt_arg(); + break; +#endif + case OPT_CHAINCAFILE: + chCAfile = opt_arg(); + break; + case OPT_VERIFYCAFILE: + vfyCAfile = opt_arg(); + break; + case OPT_DANE_TLSA_DOMAIN: + dane_tlsa_domain = opt_arg(); + break; + case OPT_DANE_TLSA_RRDATA: + if (dane_tlsa_rrset == NULL) + dane_tlsa_rrset = sk_OPENSSL_STRING_new_null(); + if (dane_tlsa_rrset == NULL || + !sk_OPENSSL_STRING_push(dane_tlsa_rrset, opt_arg())) { + BIO_printf(bio_err, "%s: Memory allocation failure\n", prog); + goto end; + } + break; + case OPT_DANE_EE_NO_NAME: + dane_ee_no_name = 1; + break; + case OPT_NEXTPROTONEG: +#ifndef OPENSSL_NO_NEXTPROTONEG + next_proto_neg_in = opt_arg(); +#endif + break; + case OPT_ALPN: + alpn_in = opt_arg(); + break; + case OPT_SERVERINFO: + p = opt_arg(); + len = strlen(p); + for (start = 0, i = 0; i <= len; ++i) { + if (i == len || p[i] == ',') { + serverinfo_types[serverinfo_count] = atoi(p + start); + if (++serverinfo_count == MAX_SI_TYPES) + break; + start = i + 1; + } + } + break; + case OPT_STARTTLS: + if (!opt_pair(opt_arg(), services, &starttls_proto)) + goto end; + break; + case OPT_SERVERNAME: + servername = opt_arg(); + break; + case OPT_NOSERVERNAME: + noservername = 1; + break; + case OPT_USE_SRTP: +#ifndef OPENSSL_NO_SRTP + srtp_profiles = opt_arg(); +#endif + break; + case OPT_KEYMATEXPORT: + keymatexportlabel = opt_arg(); + break; + case OPT_KEYMATEXPORTLEN: + keymatexportlen = atoi(opt_arg()); + break; + case OPT_ASYNC: + async = 1; + break; + case OPT_MAXFRAGLEN: + len = atoi(opt_arg()); + switch (len) { + case 512: + maxfraglen = TLSEXT_max_fragment_length_512; + break; + case 1024: + maxfraglen = TLSEXT_max_fragment_length_1024; + break; + case 2048: + maxfraglen = TLSEXT_max_fragment_length_2048; + break; + case 4096: + maxfraglen = TLSEXT_max_fragment_length_4096; + break; + default: + BIO_printf(bio_err, + "%s: Max Fragment Len %u is out of permitted values", + prog, len); + goto opthelp; + } + break; + case OPT_MAX_SEND_FRAG: + max_send_fragment = atoi(opt_arg()); + break; + case OPT_SPLIT_SEND_FRAG: + split_send_fragment = atoi(opt_arg()); + break; + case OPT_MAX_PIPELINES: + max_pipelines = atoi(opt_arg()); + break; + case OPT_READ_BUF: + read_buf_len = atoi(opt_arg()); + break; + case OPT_KEYLOG_FILE: + keylog_file = opt_arg(); + break; + case OPT_EARLY_DATA: + early_data_file = opt_arg(); + break; + case OPT_ENABLE_PHA: + enable_pha = 1; + break; + } + } + if (count4or6 >= 2) { + BIO_printf(bio_err, "%s: Can't use both -4 and -6\n", prog); + goto opthelp; + } + if (noservername) { + if (servername != NULL) { + BIO_printf(bio_err, + "%s: Can't use -servername and -noservername together\n", + prog); + goto opthelp; + } + if (dane_tlsa_domain != NULL) { + BIO_printf(bio_err, + "%s: Can't use -dane_tlsa_domain and -noservername together\n", + prog); + goto opthelp; + } + } + argc = opt_num_rest(); + if (argc == 1) { + /* If there's a positional argument, it's the equivalent of + * OPT_CONNECT. + * Don't allow -connect and a separate argument. + */ + if (connectstr != NULL) { + BIO_printf(bio_err, + "%s: must not provide both -connect option and target parameter\n", + prog); + goto opthelp; + } + connect_type = use_inet; + freeandcopy(&connectstr, *opt_rest()); + } else if (argc != 0) { + goto opthelp; + } + +#ifndef OPENSSL_NO_NEXTPROTONEG + if (min_version == TLS1_3_VERSION && next_proto_neg_in != NULL) { + BIO_printf(bio_err, "Cannot supply -nextprotoneg with TLSv1.3\n"); + goto opthelp; + } +#endif + if (proxystr != NULL) { + int res; + char *tmp_host = host, *tmp_port = port; + if (connectstr == NULL) { + BIO_printf(bio_err, "%s: -proxy requires use of -connect or target parameter\n", prog); + goto opthelp; + } + res = BIO_parse_hostserv(proxystr, &host, &port, BIO_PARSE_PRIO_HOST); + if (tmp_host != host) + OPENSSL_free(tmp_host); + if (tmp_port != port) + OPENSSL_free(tmp_port); + if (!res) { + BIO_printf(bio_err, + "%s: -proxy argument malformed or ambiguous\n", prog); + goto end; + } + } else { + int res = 1; + char *tmp_host = host, *tmp_port = port; + if (connectstr != NULL) + res = BIO_parse_hostserv(connectstr, &host, &port, + BIO_PARSE_PRIO_HOST); + if (tmp_host != host) + OPENSSL_free(tmp_host); + if (tmp_port != port) + OPENSSL_free(tmp_port); + if (!res) { + BIO_printf(bio_err, + "%s: -connect argument or target parameter malformed or ambiguous\n", + prog); + goto end; + } + } + + if (bindstr != NULL) { + int res; + res = BIO_parse_hostserv(bindstr, &bindhost, &bindport, + BIO_PARSE_PRIO_HOST); + if (!res) { + BIO_printf(bio_err, + "%s: -bind argument parameter malformed or ambiguous\n", + prog); + goto end; + } + } + +#ifdef AF_UNIX + if (socket_family == AF_UNIX && socket_type != SOCK_STREAM) { + BIO_printf(bio_err, + "Can't use unix sockets and datagrams together\n"); + goto end; + } +#endif + +#ifndef OPENSSL_NO_SCTP + if (protocol == IPPROTO_SCTP) { + if (socket_type != SOCK_DGRAM) { + BIO_printf(bio_err, "Can't use -sctp without DTLS\n"); + goto end; + } + /* SCTP is unusual. It uses DTLS over a SOCK_STREAM protocol */ + socket_type = SOCK_STREAM; + } +#endif + +#if !defined(OPENSSL_NO_NEXTPROTONEG) + next_proto.status = -1; + if (next_proto_neg_in) { + next_proto.data = + next_protos_parse(&next_proto.len, next_proto_neg_in); + if (next_proto.data == NULL) { + BIO_printf(bio_err, "Error parsing -nextprotoneg argument\n"); + goto end; + } + } else + next_proto.data = NULL; +#endif + + if (!app_passwd(passarg, NULL, &pass, NULL)) { + BIO_printf(bio_err, "Error getting password\n"); + goto end; + } + + if (key_file == NULL) + key_file = cert_file; + + if (key_file != NULL) { + key = load_key(key_file, key_format, 0, pass, e, + "client certificate private key file"); + if (key == NULL) { + ERR_print_errors(bio_err); + goto end; + } + } + + if (cert_file != NULL) { + cert = load_cert(cert_file, cert_format, "client certificate file"); + if (cert == NULL) { + ERR_print_errors(bio_err); + goto end; + } + } + + if (chain_file != NULL) { + if (!load_certs(chain_file, &chain, FORMAT_PEM, NULL, + "client certificate chain")) + goto end; + } + + if (crl_file != NULL) { + X509_CRL *crl; + crl = load_crl(crl_file, crl_format); + if (crl == NULL) { + BIO_puts(bio_err, "Error loading CRL\n"); + ERR_print_errors(bio_err); + goto end; + } + crls = sk_X509_CRL_new_null(); + if (crls == NULL || !sk_X509_CRL_push(crls, crl)) { + BIO_puts(bio_err, "Error adding CRL\n"); + ERR_print_errors(bio_err); + X509_CRL_free(crl); + goto end; + } + } + + if (!load_excert(&exc)) + goto end; + + if (bio_c_out == NULL) { + if (c_quiet && !c_debug) { + bio_c_out = BIO_new(BIO_s_null()); + if (c_msg && bio_c_msg == NULL) + bio_c_msg = dup_bio_out(FORMAT_TEXT); + } else if (bio_c_out == NULL) + bio_c_out = dup_bio_out(FORMAT_TEXT); + } +#ifndef OPENSSL_NO_SRP + if (!app_passwd(srppass, NULL, &srp_arg.srppassin, NULL)) { + BIO_printf(bio_err, "Error getting password\n"); + goto end; + } +#endif + + ctx = SSL_CTX_new(meth); + if (ctx == NULL) { + ERR_print_errors(bio_err); + goto end; + } + + SSL_CTX_clear_mode(ctx, SSL_MODE_AUTO_RETRY); + + if (sdebug) + ssl_ctx_security_debug(ctx, sdebug); + + if (!config_ctx(cctx, ssl_args, ctx)) + goto end; + + if (ssl_config != NULL) { + if (SSL_CTX_config(ctx, ssl_config) == 0) { + BIO_printf(bio_err, "Error using configuration \"%s\"\n", + ssl_config); + ERR_print_errors(bio_err); + goto end; + } + } + +#ifndef OPENSSL_NO_SCTP + if (protocol == IPPROTO_SCTP && sctp_label_bug == 1) + SSL_CTX_set_mode(ctx, SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG); +#endif + + if (min_version != 0 + && SSL_CTX_set_min_proto_version(ctx, min_version) == 0) + goto end; + if (max_version != 0 + && SSL_CTX_set_max_proto_version(ctx, max_version) == 0) + goto end; + + if (vpmtouched && !SSL_CTX_set1_param(ctx, vpm)) { + BIO_printf(bio_err, "Error setting verify params\n"); + ERR_print_errors(bio_err); + goto end; + } + + if (async) { + SSL_CTX_set_mode(ctx, SSL_MODE_ASYNC); + } + + if (max_send_fragment > 0 + && !SSL_CTX_set_max_send_fragment(ctx, max_send_fragment)) { + BIO_printf(bio_err, "%s: Max send fragment size %u is out of permitted range\n", + prog, max_send_fragment); + goto end; + } + + if (split_send_fragment > 0 + && !SSL_CTX_set_split_send_fragment(ctx, split_send_fragment)) { + BIO_printf(bio_err, "%s: Split send fragment size %u is out of permitted range\n", + prog, split_send_fragment); + goto end; + } + + if (max_pipelines > 0 + && !SSL_CTX_set_max_pipelines(ctx, max_pipelines)) { + BIO_printf(bio_err, "%s: Max pipelines %u is out of permitted range\n", + prog, max_pipelines); + goto end; + } + + if (read_buf_len > 0) { + SSL_CTX_set_default_read_buffer_len(ctx, read_buf_len); + } + + if (maxfraglen > 0 + && !SSL_CTX_set_tlsext_max_fragment_length(ctx, maxfraglen)) { + BIO_printf(bio_err, + "%s: Max Fragment Length code %u is out of permitted values" + "\n", prog, maxfraglen); + goto end; + } + + if (!ssl_load_stores(ctx, vfyCApath, vfyCAfile, chCApath, chCAfile, + crls, crl_download)) { + BIO_printf(bio_err, "Error loading store locations\n"); + ERR_print_errors(bio_err); + goto end; + } + if (ReqCAfile != NULL) { + STACK_OF(X509_NAME) *nm = sk_X509_NAME_new_null(); + + if (nm == NULL || !SSL_add_file_cert_subjects_to_stack(nm, ReqCAfile)) { + sk_X509_NAME_pop_free(nm, X509_NAME_free); + BIO_printf(bio_err, "Error loading CA names\n"); + ERR_print_errors(bio_err); + goto end; + } + SSL_CTX_set0_CA_list(ctx, nm); + } +#ifndef OPENSSL_NO_ENGINE + if (ssl_client_engine) { + if (!SSL_CTX_set_client_cert_engine(ctx, ssl_client_engine)) { + BIO_puts(bio_err, "Error setting client auth engine\n"); + ERR_print_errors(bio_err); + ENGINE_free(ssl_client_engine); + goto end; + } + ENGINE_free(ssl_client_engine); + } +#endif + +#ifndef OPENSSL_NO_PSK + if (psk_key != NULL) { + if (c_debug) + BIO_printf(bio_c_out, "PSK key given, setting client callback\n"); + SSL_CTX_set_psk_client_callback(ctx, psk_client_cb); + } +#endif + if (psksessf != NULL) { + BIO *stmp = BIO_new_file(psksessf, "r"); + + if (stmp == NULL) { + BIO_printf(bio_err, "Can't open PSK session file %s\n", psksessf); + ERR_print_errors(bio_err); + goto end; + } + psksess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL); + BIO_free(stmp); + if (psksess == NULL) { + BIO_printf(bio_err, "Can't read PSK session file %s\n", psksessf); + ERR_print_errors(bio_err); + goto end; + } + } + if (psk_key != NULL || psksess != NULL) + SSL_CTX_set_psk_use_session_callback(ctx, psk_use_session_cb); + +#ifndef OPENSSL_NO_SRTP + if (srtp_profiles != NULL) { + /* Returns 0 on success! */ + if (SSL_CTX_set_tlsext_use_srtp(ctx, srtp_profiles) != 0) { + BIO_printf(bio_err, "Error setting SRTP profile\n"); + ERR_print_errors(bio_err); + goto end; + } + } +#endif + + if (exc != NULL) + ssl_ctx_set_excert(ctx, exc); + +#if !defined(OPENSSL_NO_NEXTPROTONEG) + if (next_proto.data != NULL) + SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &next_proto); +#endif + if (alpn_in) { + size_t alpn_len; + unsigned char *alpn = next_protos_parse(&alpn_len, alpn_in); + + if (alpn == NULL) { + BIO_printf(bio_err, "Error parsing -alpn argument\n"); + goto end; + } + /* Returns 0 on success! */ + if (SSL_CTX_set_alpn_protos(ctx, alpn, alpn_len) != 0) { + BIO_printf(bio_err, "Error setting ALPN\n"); + goto end; + } + OPENSSL_free(alpn); + } + + for (i = 0; i < serverinfo_count; i++) { + if (!SSL_CTX_add_client_custom_ext(ctx, + serverinfo_types[i], + NULL, NULL, NULL, + serverinfo_cli_parse_cb, NULL)) { + BIO_printf(bio_err, + "Warning: Unable to add custom extension %u, skipping\n", + serverinfo_types[i]); + } + } + + if (state) + SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback); + +#ifndef OPENSSL_NO_CT + /* Enable SCT processing, without early connection termination */ + if (ct_validation && + !SSL_CTX_enable_ct(ctx, SSL_CT_VALIDATION_PERMISSIVE)) { + ERR_print_errors(bio_err); + goto end; + } + + if (!ctx_set_ctlog_list_file(ctx, ctlog_file)) { + if (ct_validation) { + ERR_print_errors(bio_err); + goto end; + } + + /* + * If CT validation is not enabled, the log list isn't needed so don't + * show errors or abort. We try to load it regardless because then we + * can show the names of the logs any SCTs came from (SCTs may be seen + * even with validation disabled). + */ + ERR_clear_error(); + } +#endif + + SSL_CTX_set_verify(ctx, verify, verify_callback); + + if (!ctx_set_verify_locations(ctx, CAfile, CApath, noCAfile, noCApath)) { + ERR_print_errors(bio_err); + goto end; + } + + ssl_ctx_add_crls(ctx, crls, crl_download); + + if (!set_cert_key_stuff(ctx, cert, key, chain, build_chain)) + goto end; + + if (!noservername) { + tlsextcbp.biodebug = bio_err; + SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb); + SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp); + } +# ifndef OPENSSL_NO_SRP + if (srp_arg.srplogin) { + if (!srp_lateuser && !SSL_CTX_set_srp_username(ctx, srp_arg.srplogin)) { + BIO_printf(bio_err, "Unable to set SRP username\n"); + goto end; + } + srp_arg.msg = c_msg; + srp_arg.debug = c_debug; + SSL_CTX_set_srp_cb_arg(ctx, &srp_arg); + SSL_CTX_set_srp_client_pwd_callback(ctx, ssl_give_srp_client_pwd_cb); + SSL_CTX_set_srp_strength(ctx, srp_arg.strength); + if (c_msg || c_debug || srp_arg.amp == 0) + SSL_CTX_set_srp_verify_param_callback(ctx, + ssl_srp_verify_param_cb); + } +# endif + + if (dane_tlsa_domain != NULL) { + if (SSL_CTX_dane_enable(ctx) <= 0) { + BIO_printf(bio_err, + "%s: Error enabling DANE TLSA authentication.\n", + prog); + ERR_print_errors(bio_err); + goto end; + } + } + + /* + * In TLSv1.3 NewSessionTicket messages arrive after the handshake and can + * come at any time. Therefore we use a callback to write out the session + * when we know about it. This approach works for < TLSv1.3 as well. + */ + SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_CLIENT + | SSL_SESS_CACHE_NO_INTERNAL_STORE); + SSL_CTX_sess_set_new_cb(ctx, new_session_cb); + + if (set_keylog_file(ctx, keylog_file)) + goto end; + + con = SSL_new(ctx); + if (con == NULL) + goto end; + + if (enable_pha) + SSL_set_post_handshake_auth(con, 1); + + if (sess_in != NULL) { + SSL_SESSION *sess; + BIO *stmp = BIO_new_file(sess_in, "r"); + if (stmp == NULL) { + BIO_printf(bio_err, "Can't open session file %s\n", sess_in); + ERR_print_errors(bio_err); + goto end; + } + sess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL); + BIO_free(stmp); + if (sess == NULL) { + BIO_printf(bio_err, "Can't open session file %s\n", sess_in); + ERR_print_errors(bio_err); + goto end; + } + if (!SSL_set_session(con, sess)) { + BIO_printf(bio_err, "Can't set session\n"); + ERR_print_errors(bio_err); + goto end; + } + + SSL_SESSION_free(sess); + } + + if (fallback_scsv) + SSL_set_mode(con, SSL_MODE_SEND_FALLBACK_SCSV); + + if (!noservername && (servername != NULL || dane_tlsa_domain == NULL)) { + if (servername == NULL) { + if(host == NULL || is_dNS_name(host)) + servername = (host == NULL) ? "localhost" : host; + } + if (servername != NULL && !SSL_set_tlsext_host_name(con, servername)) { + BIO_printf(bio_err, "Unable to set TLS servername extension.\n"); + ERR_print_errors(bio_err); + goto end; + } + } + + if (dane_tlsa_domain != NULL) { + if (SSL_dane_enable(con, dane_tlsa_domain) <= 0) { + BIO_printf(bio_err, "%s: Error enabling DANE TLSA " + "authentication.\n", prog); + ERR_print_errors(bio_err); + goto end; + } + if (dane_tlsa_rrset == NULL) { + BIO_printf(bio_err, "%s: DANE TLSA authentication requires at " + "least one -dane_tlsa_rrdata option.\n", prog); + goto end; + } + if (tlsa_import_rrset(con, dane_tlsa_rrset) <= 0) { + BIO_printf(bio_err, "%s: Failed to import any TLSA " + "records.\n", prog); + goto end; + } + if (dane_ee_no_name) + SSL_dane_set_flags(con, DANE_FLAG_NO_DANE_EE_NAMECHECKS); + } else if (dane_tlsa_rrset != NULL) { + BIO_printf(bio_err, "%s: DANE TLSA authentication requires the " + "-dane_tlsa_domain option.\n", prog); + goto end; + } + + re_start: + if (init_client(&s, host, port, bindhost, bindport, socket_family, + socket_type, protocol) == 0) { + BIO_printf(bio_err, "connect:errno=%d\n", get_last_socket_error()); + BIO_closesocket(s); + goto end; + } + BIO_printf(bio_c_out, "CONNECTED(%08X)\n", s); + + if (c_nbio) { + if (!BIO_socket_nbio(s, 1)) { + ERR_print_errors(bio_err); + goto end; + } + BIO_printf(bio_c_out, "Turned on non blocking io\n"); + } +#ifndef OPENSSL_NO_DTLS + if (isdtls) { + union BIO_sock_info_u peer_info; + +#ifndef OPENSSL_NO_SCTP + if (protocol == IPPROTO_SCTP) + sbio = BIO_new_dgram_sctp(s, BIO_NOCLOSE); + else +#endif + sbio = BIO_new_dgram(s, BIO_NOCLOSE); + + if ((peer_info.addr = BIO_ADDR_new()) == NULL) { + BIO_printf(bio_err, "memory allocation failure\n"); + BIO_closesocket(s); + goto end; + } + if (!BIO_sock_info(s, BIO_SOCK_INFO_ADDRESS, &peer_info)) { + BIO_printf(bio_err, "getsockname:errno=%d\n", + get_last_socket_error()); + BIO_ADDR_free(peer_info.addr); + BIO_closesocket(s); + goto end; + } + + (void)BIO_ctrl_set_connected(sbio, peer_info.addr); + BIO_ADDR_free(peer_info.addr); + peer_info.addr = NULL; + + if (enable_timeouts) { + timeout.tv_sec = 0; + timeout.tv_usec = DGRAM_RCV_TIMEOUT; + BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); + + timeout.tv_sec = 0; + timeout.tv_usec = DGRAM_SND_TIMEOUT; + BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout); + } + + if (socket_mtu) { + if (socket_mtu < DTLS_get_link_min_mtu(con)) { + BIO_printf(bio_err, "MTU too small. Must be at least %ld\n", + DTLS_get_link_min_mtu(con)); + BIO_free(sbio); + goto shut; + } + SSL_set_options(con, SSL_OP_NO_QUERY_MTU); + if (!DTLS_set_link_mtu(con, socket_mtu)) { + BIO_printf(bio_err, "Failed to set MTU\n"); + BIO_free(sbio); + goto shut; + } + } else { + /* want to do MTU discovery */ + BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL); + } + } else +#endif /* OPENSSL_NO_DTLS */ + sbio = BIO_new_socket(s, BIO_NOCLOSE); + + if (nbio_test) { + BIO *test; + + test = BIO_new(BIO_f_nbio_test()); + sbio = BIO_push(test, sbio); + } + + if (c_debug) { + BIO_set_callback(sbio, bio_dump_callback); + BIO_set_callback_arg(sbio, (char *)bio_c_out); + } + if (c_msg) { +#ifndef OPENSSL_NO_SSL_TRACE + if (c_msg == 2) + SSL_set_msg_callback(con, SSL_trace); + else +#endif + SSL_set_msg_callback(con, msg_cb); + SSL_set_msg_callback_arg(con, bio_c_msg ? bio_c_msg : bio_c_out); + } + + if (c_tlsextdebug) { + SSL_set_tlsext_debug_callback(con, tlsext_cb); + SSL_set_tlsext_debug_arg(con, bio_c_out); + } +#ifndef OPENSSL_NO_OCSP + if (c_status_req) { + SSL_set_tlsext_status_type(con, TLSEXT_STATUSTYPE_ocsp); + SSL_CTX_set_tlsext_status_cb(ctx, ocsp_resp_cb); + SSL_CTX_set_tlsext_status_arg(ctx, bio_c_out); + } +#endif + + SSL_set_bio(con, sbio, sbio); + SSL_set_connect_state(con); + + /* ok, lets connect */ + if (fileno_stdin() > SSL_get_fd(con)) + width = fileno_stdin() + 1; + else + width = SSL_get_fd(con) + 1; + + read_tty = 1; + write_tty = 0; + tty_on = 0; + read_ssl = 1; + write_ssl = 1; + + cbuf_len = 0; + cbuf_off = 0; + sbuf_len = 0; + sbuf_off = 0; + + switch ((PROTOCOL_CHOICE) starttls_proto) { + case PROTO_OFF: + break; + case PROTO_LMTP: + case PROTO_SMTP: + { + /* + * This is an ugly hack that does a lot of assumptions. We do + * have to handle multi-line responses which may come in a single + * packet or not. We therefore have to use BIO_gets() which does + * need a buffering BIO. So during the initial chitchat we do + * push a buffering BIO into the chain that is removed again + * later on to not disturb the rest of the s_client operation. + */ + int foundit = 0; + BIO *fbio = BIO_new(BIO_f_buffer()); + + BIO_push(fbio, sbio); + /* Wait for multi-line response to end from LMTP or SMTP */ + do { + mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); + } while (mbuf_len > 3 && mbuf[3] == '-'); + if (protohost == NULL) + protohost = "mail.example.com"; + if (starttls_proto == (int)PROTO_LMTP) + BIO_printf(fbio, "LHLO %s\r\n", protohost); + else + BIO_printf(fbio, "EHLO %s\r\n", protohost); + (void)BIO_flush(fbio); + /* + * Wait for multi-line response to end LHLO LMTP or EHLO SMTP + * response. + */ + do { + mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); + if (strstr(mbuf, "STARTTLS")) + foundit = 1; + } while (mbuf_len > 3 && mbuf[3] == '-'); + (void)BIO_flush(fbio); + BIO_pop(fbio); + BIO_free(fbio); + if (!foundit) + BIO_printf(bio_err, + "Didn't find STARTTLS in server response," + " trying anyway...\n"); + BIO_printf(sbio, "STARTTLS\r\n"); + BIO_read(sbio, sbuf, BUFSIZZ); + } + break; + case PROTO_POP3: + { + BIO_read(sbio, mbuf, BUFSIZZ); + BIO_printf(sbio, "STLS\r\n"); + mbuf_len = BIO_read(sbio, sbuf, BUFSIZZ); + if (mbuf_len < 0) { + BIO_printf(bio_err, "BIO_read failed\n"); + goto end; + } + } + break; + case PROTO_IMAP: + { + int foundit = 0; + BIO *fbio = BIO_new(BIO_f_buffer()); + + BIO_push(fbio, sbio); + BIO_gets(fbio, mbuf, BUFSIZZ); + /* STARTTLS command requires CAPABILITY... */ + BIO_printf(fbio, ". CAPABILITY\r\n"); + (void)BIO_flush(fbio); + /* wait for multi-line CAPABILITY response */ + do { + mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); + if (strstr(mbuf, "STARTTLS")) + foundit = 1; + } + while (mbuf_len > 3 && mbuf[0] != '.'); + (void)BIO_flush(fbio); + BIO_pop(fbio); + BIO_free(fbio); + if (!foundit) + BIO_printf(bio_err, + "Didn't find STARTTLS in server response," + " trying anyway...\n"); + BIO_printf(sbio, ". STARTTLS\r\n"); + BIO_read(sbio, sbuf, BUFSIZZ); + } + break; + case PROTO_FTP: + { + BIO *fbio = BIO_new(BIO_f_buffer()); + + BIO_push(fbio, sbio); + /* wait for multi-line response to end from FTP */ + do { + mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); + } + while (mbuf_len > 3 && mbuf[3] == '-'); + (void)BIO_flush(fbio); + BIO_pop(fbio); + BIO_free(fbio); + BIO_printf(sbio, "AUTH TLS\r\n"); + BIO_read(sbio, sbuf, BUFSIZZ); + } + break; + case PROTO_XMPP: + case PROTO_XMPP_SERVER: + { + int seen = 0; + BIO_printf(sbio, "", + starttls_proto == PROTO_XMPP ? "client" : "server", + protohost ? protohost : host); + seen = BIO_read(sbio, mbuf, BUFSIZZ); + if (seen < 0) { + BIO_printf(bio_err, "BIO_read failed\n"); + goto end; + } + mbuf[seen] = '\0'; + while (!strstr + (mbuf, ""); + seen = BIO_read(sbio, sbuf, BUFSIZZ); + if (seen < 0) { + BIO_printf(bio_err, "BIO_read failed\n"); + goto shut; + } + sbuf[seen] = '\0'; + if (!strstr(sbuf, " 2); + } + (void)BIO_flush(fbio); + BIO_pop(fbio); + BIO_free(fbio); + if (foundit != success) { + goto shut; + } + } + break; + case PROTO_IRC: + { + int numeric; + BIO *fbio = BIO_new(BIO_f_buffer()); + + BIO_push(fbio, sbio); + BIO_printf(fbio, "STARTTLS\r\n"); + (void)BIO_flush(fbio); + width = SSL_get_fd(con) + 1; + + do { + numeric = 0; + + FD_ZERO(&readfds); + openssl_fdset(SSL_get_fd(con), &readfds); + timeout.tv_sec = S_CLIENT_IRC_READ_TIMEOUT; + timeout.tv_usec = 0; + /* + * If the IRCd doesn't respond within + * S_CLIENT_IRC_READ_TIMEOUT seconds, assume + * it doesn't support STARTTLS. Many IRCds + * will not give _any_ sort of response to a + * STARTTLS command when it's not supported. + */ + if (!BIO_get_buffer_num_lines(fbio) + && !BIO_pending(fbio) + && !BIO_pending(sbio) + && select(width, (void *)&readfds, NULL, NULL, + &timeout) < 1) { + BIO_printf(bio_err, + "Timeout waiting for response (%d seconds).\n", + S_CLIENT_IRC_READ_TIMEOUT); + break; + } + + mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); + if (mbuf_len < 1 || sscanf(mbuf, "%*s %d", &numeric) != 1) + break; + /* :example.net 451 STARTTLS :You have not registered */ + /* :example.net 421 STARTTLS :Unknown command */ + if ((numeric == 451 || numeric == 421) + && strstr(mbuf, "STARTTLS") != NULL) { + BIO_printf(bio_err, "STARTTLS not supported: %s", mbuf); + break; + } + if (numeric == 691) { + BIO_printf(bio_err, "STARTTLS negotiation failed: "); + ERR_print_errors(bio_err); + break; + } + } while (numeric != 670); + + (void)BIO_flush(fbio); + BIO_pop(fbio); + BIO_free(fbio); + if (numeric != 670) { + BIO_printf(bio_err, "Server does not support STARTTLS.\n"); + ret = 1; + goto shut; + } + } + break; + case PROTO_MYSQL: + { + /* SSL request packet */ + static const unsigned char ssl_req[] = { + /* payload_length, sequence_id */ + 0x20, 0x00, 0x00, 0x01, + /* payload */ + /* capability flags, CLIENT_SSL always set */ + 0x85, 0xae, 0x7f, 0x00, + /* max-packet size */ + 0x00, 0x00, 0x00, 0x01, + /* character set */ + 0x21, + /* string[23] reserved (all [0]) */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + int bytes = 0; + int ssl_flg = 0x800; + int pos; + const unsigned char *packet = (const unsigned char *)sbuf; + + /* Receiving Initial Handshake packet. */ + bytes = BIO_read(sbio, (void *)packet, BUFSIZZ); + if (bytes < 0) { + BIO_printf(bio_err, "BIO_read failed\n"); + goto shut; + /* Packet length[3], Packet number[1] + minimum payload[17] */ + } else if (bytes < 21) { + BIO_printf(bio_err, "MySQL packet too short.\n"); + goto shut; + } else if (bytes != (4 + packet[0] + + (packet[1] << 8) + + (packet[2] << 16))) { + BIO_printf(bio_err, "MySQL packet length does not match.\n"); + goto shut; + /* protocol version[1] */ + } else if (packet[4] != 0xA) { + BIO_printf(bio_err, + "Only MySQL protocol version 10 is supported.\n"); + goto shut; + } + + pos = 5; + /* server version[string+NULL] */ + for (;;) { + if (pos >= bytes) { + BIO_printf(bio_err, "Cannot confirm server version. "); + goto shut; + } else if (packet[pos++] == '\0') { + break; + } + } + + /* make sure we have at least 15 bytes left in the packet */ + if (pos + 15 > bytes) { + BIO_printf(bio_err, + "MySQL server handshake packet is broken.\n"); + goto shut; + } + + pos += 12; /* skip over conn id[4] + SALT[8] */ + if (packet[pos++] != '\0') { /* verify filler */ + BIO_printf(bio_err, + "MySQL packet is broken.\n"); + goto shut; + } + + /* capability flags[2] */ + if (!((packet[pos] + (packet[pos + 1] << 8)) & ssl_flg)) { + BIO_printf(bio_err, "MySQL server does not support SSL.\n"); + goto shut; + } + + /* Sending SSL Handshake packet. */ + BIO_write(sbio, ssl_req, sizeof(ssl_req)); + (void)BIO_flush(sbio); + } + break; + case PROTO_POSTGRES: + { + static const unsigned char ssl_request[] = { + /* Length SSLRequest */ + 0, 0, 0, 8, 4, 210, 22, 47 + }; + int bytes; + + /* Send SSLRequest packet */ + BIO_write(sbio, ssl_request, 8); + (void)BIO_flush(sbio); + + /* Reply will be a single S if SSL is enabled */ + bytes = BIO_read(sbio, sbuf, BUFSIZZ); + if (bytes != 1 || sbuf[0] != 'S') + goto shut; + } + break; + case PROTO_NNTP: + { + int foundit = 0; + BIO *fbio = BIO_new(BIO_f_buffer()); + + BIO_push(fbio, sbio); + BIO_gets(fbio, mbuf, BUFSIZZ); + /* STARTTLS command requires CAPABILITIES... */ + BIO_printf(fbio, "CAPABILITIES\r\n"); + (void)BIO_flush(fbio); + /* wait for multi-line CAPABILITIES response */ + do { + mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); + if (strstr(mbuf, "STARTTLS")) + foundit = 1; + } while (mbuf_len > 1 && mbuf[0] != '.'); + (void)BIO_flush(fbio); + BIO_pop(fbio); + BIO_free(fbio); + if (!foundit) + BIO_printf(bio_err, + "Didn't find STARTTLS in server response," + " trying anyway...\n"); + BIO_printf(sbio, "STARTTLS\r\n"); + mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ); + if (mbuf_len < 0) { + BIO_printf(bio_err, "BIO_read failed\n"); + goto end; + } + mbuf[mbuf_len] = '\0'; + if (strstr(mbuf, "382") == NULL) { + BIO_printf(bio_err, "STARTTLS failed: %s", mbuf); + goto shut; + } + } + break; + case PROTO_SIEVE: + { + int foundit = 0; + BIO *fbio = BIO_new(BIO_f_buffer()); + + BIO_push(fbio, sbio); + /* wait for multi-line response to end from Sieve */ + do { + mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); + /* + * According to RFC 5804 § 1.7, capability + * is case-insensitive, make it uppercase + */ + if (mbuf_len > 1 && mbuf[0] == '"') { + make_uppercase(mbuf); + if (strncmp(mbuf, "\"STARTTLS\"", 10) == 0) + foundit = 1; + } + } while (mbuf_len > 1 && mbuf[0] == '"'); + (void)BIO_flush(fbio); + BIO_pop(fbio); + BIO_free(fbio); + if (!foundit) + BIO_printf(bio_err, + "Didn't find STARTTLS in server response," + " trying anyway...\n"); + BIO_printf(sbio, "STARTTLS\r\n"); + mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ); + if (mbuf_len < 0) { + BIO_printf(bio_err, "BIO_read failed\n"); + goto end; + } + mbuf[mbuf_len] = '\0'; + if (mbuf_len < 2) { + BIO_printf(bio_err, "STARTTLS failed: %s", mbuf); + goto shut; + } + /* + * According to RFC 5804 § 2.2, response codes are case- + * insensitive, make it uppercase but preserve the response. + */ + strncpy(sbuf, mbuf, 2); + make_uppercase(sbuf); + if (strncmp(sbuf, "OK", 2) != 0) { + BIO_printf(bio_err, "STARTTLS not supported: %s", mbuf); + goto shut; + } + } + break; + case PROTO_LDAP: + { + /* StartTLS Operation according to RFC 4511 */ + static char ldap_tls_genconf[] = "asn1=SEQUENCE:LDAPMessage\n" + "[LDAPMessage]\n" + "messageID=INTEGER:1\n" + "extendedReq=EXPLICIT:23A,IMPLICIT:0C," + "FORMAT:ASCII,OCT:1.3.6.1.4.1.1466.20037\n"; + long errline = -1; + char *genstr = NULL; + int result = -1; + ASN1_TYPE *atyp = NULL; + BIO *ldapbio = BIO_new(BIO_s_mem()); + CONF *cnf = NCONF_new(NULL); + + if (cnf == NULL) { + BIO_free(ldapbio); + goto end; + } + BIO_puts(ldapbio, ldap_tls_genconf); + if (NCONF_load_bio(cnf, ldapbio, &errline) <= 0) { + BIO_free(ldapbio); + NCONF_free(cnf); + if (errline <= 0) { + BIO_printf(bio_err, "NCONF_load_bio failed\n"); + goto end; + } else { + BIO_printf(bio_err, "Error on line %ld\n", errline); + goto end; + } + } + BIO_free(ldapbio); + genstr = NCONF_get_string(cnf, "default", "asn1"); + if (genstr == NULL) { + NCONF_free(cnf); + BIO_printf(bio_err, "NCONF_get_string failed\n"); + goto end; + } + atyp = ASN1_generate_nconf(genstr, cnf); + if (atyp == NULL) { + NCONF_free(cnf); + BIO_printf(bio_err, "ASN1_generate_nconf failed\n"); + goto end; + } + NCONF_free(cnf); + + /* Send SSLRequest packet */ + BIO_write(sbio, atyp->value.sequence->data, + atyp->value.sequence->length); + (void)BIO_flush(sbio); + ASN1_TYPE_free(atyp); + + mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ); + if (mbuf_len < 0) { + BIO_printf(bio_err, "BIO_read failed\n"); + goto end; + } + result = ldap_ExtendedResponse_parse(mbuf, mbuf_len); + if (result < 0) { + BIO_printf(bio_err, "ldap_ExtendedResponse_parse failed\n"); + goto shut; + } else if (result > 0) { + BIO_printf(bio_err, "STARTTLS failed, LDAP Result Code: %i\n", + result); + goto shut; + } + mbuf_len = 0; + } + break; + } + + if (early_data_file != NULL + && ((SSL_get0_session(con) != NULL + && SSL_SESSION_get_max_early_data(SSL_get0_session(con)) > 0) + || (psksess != NULL + && SSL_SESSION_get_max_early_data(psksess) > 0))) { + BIO *edfile = BIO_new_file(early_data_file, "r"); + size_t readbytes, writtenbytes; + int finish = 0; + + if (edfile == NULL) { + BIO_printf(bio_err, "Cannot open early data file\n"); + goto shut; + } + + while (!finish) { + if (!BIO_read_ex(edfile, cbuf, BUFSIZZ, &readbytes)) + finish = 1; + + while (!SSL_write_early_data(con, cbuf, readbytes, &writtenbytes)) { + switch (SSL_get_error(con, 0)) { + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_ASYNC: + case SSL_ERROR_WANT_READ: + /* Just keep trying - busy waiting */ + continue; + default: + BIO_printf(bio_err, "Error writing early data\n"); + BIO_free(edfile); + ERR_print_errors(bio_err); + goto shut; + } + } + } + + BIO_free(edfile); + } + + for (;;) { + FD_ZERO(&readfds); + FD_ZERO(&writefds); + + if (SSL_is_dtls(con) && DTLSv1_get_timeout(con, &timeout)) + timeoutp = &timeout; + else + timeoutp = NULL; + + if (!SSL_is_init_finished(con) && SSL_total_renegotiations(con) == 0 + && SSL_get_key_update_type(con) == SSL_KEY_UPDATE_NONE) { + in_init = 1; + tty_on = 0; + } else { + tty_on = 1; + if (in_init) { + in_init = 0; + + if (c_brief) { + BIO_puts(bio_err, "CONNECTION ESTABLISHED\n"); + print_ssl_summary(con); + } + + print_stuff(bio_c_out, con, full_log); + if (full_log > 0) + full_log--; + + if (starttls_proto) { + BIO_write(bio_err, mbuf, mbuf_len); + /* We don't need to know any more */ + if (!reconnect) + starttls_proto = PROTO_OFF; + } + + if (reconnect) { + reconnect--; + BIO_printf(bio_c_out, + "drop connection and then reconnect\n"); + do_ssl_shutdown(con); + SSL_set_connect_state(con); + BIO_closesocket(SSL_get_fd(con)); + goto re_start; + } + } + } + + ssl_pending = read_ssl && SSL_has_pending(con); + + if (!ssl_pending) { +#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) + if (tty_on) { + /* + * Note that select() returns when read _would not block_, + * and EOF satisfies that. To avoid a CPU-hogging loop, + * set the flag so we exit. + */ + if (read_tty && !at_eof) + openssl_fdset(fileno_stdin(), &readfds); +#if !defined(OPENSSL_SYS_VMS) + if (write_tty) + openssl_fdset(fileno_stdout(), &writefds); +#endif + } + if (read_ssl) + openssl_fdset(SSL_get_fd(con), &readfds); + if (write_ssl) + openssl_fdset(SSL_get_fd(con), &writefds); +#else + if (!tty_on || !write_tty) { + if (read_ssl) + openssl_fdset(SSL_get_fd(con), &readfds); + if (write_ssl) + openssl_fdset(SSL_get_fd(con), &writefds); + } +#endif + + /* + * Note: under VMS with SOCKETSHR the second parameter is + * currently of type (int *) whereas under other systems it is + * (void *) if you don't have a cast it will choke the compiler: + * if you do have a cast then you can either go for (int *) or + * (void *). + */ +#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) + /* + * Under Windows/DOS we make the assumption that we can always + * write to the tty: therefore if we need to write to the tty we + * just fall through. Otherwise we timeout the select every + * second and see if there are any keypresses. Note: this is a + * hack, in a proper Windows application we wouldn't do this. + */ + i = 0; + if (!write_tty) { + if (read_tty) { + tv.tv_sec = 1; + tv.tv_usec = 0; + i = select(width, (void *)&readfds, (void *)&writefds, + NULL, &tv); + if (!i && (!has_stdin_waiting() || !read_tty)) + continue; + } else + i = select(width, (void *)&readfds, (void *)&writefds, + NULL, timeoutp); + } +#else + i = select(width, (void *)&readfds, (void *)&writefds, + NULL, timeoutp); +#endif + if (i < 0) { + BIO_printf(bio_err, "bad select %d\n", + get_last_socket_error()); + goto shut; + } + } + + if (SSL_is_dtls(con) && DTLSv1_handle_timeout(con) > 0) + BIO_printf(bio_err, "TIMEOUT occurred\n"); + + if (!ssl_pending && FD_ISSET(SSL_get_fd(con), &writefds)) { + k = SSL_write(con, &(cbuf[cbuf_off]), (unsigned int)cbuf_len); + switch (SSL_get_error(con, k)) { + case SSL_ERROR_NONE: + cbuf_off += k; + cbuf_len -= k; + if (k <= 0) + goto end; + /* we have done a write(con,NULL,0); */ + if (cbuf_len <= 0) { + read_tty = 1; + write_ssl = 0; + } else { /* if (cbuf_len > 0) */ + + read_tty = 0; + write_ssl = 1; + } + break; + case SSL_ERROR_WANT_WRITE: + BIO_printf(bio_c_out, "write W BLOCK\n"); + write_ssl = 1; + read_tty = 0; + break; + case SSL_ERROR_WANT_ASYNC: + BIO_printf(bio_c_out, "write A BLOCK\n"); + wait_for_async(con); + write_ssl = 1; + read_tty = 0; + break; + case SSL_ERROR_WANT_READ: + BIO_printf(bio_c_out, "write R BLOCK\n"); + write_tty = 0; + read_ssl = 1; + write_ssl = 0; + break; + case SSL_ERROR_WANT_X509_LOOKUP: + BIO_printf(bio_c_out, "write X BLOCK\n"); + break; + case SSL_ERROR_ZERO_RETURN: + if (cbuf_len != 0) { + BIO_printf(bio_c_out, "shutdown\n"); + ret = 0; + goto shut; + } else { + read_tty = 1; + write_ssl = 0; + break; + } + + case SSL_ERROR_SYSCALL: + if ((k != 0) || (cbuf_len != 0)) { + BIO_printf(bio_err, "write:errno=%d\n", + get_last_socket_error()); + goto shut; + } else { + read_tty = 1; + write_ssl = 0; + } + break; + case SSL_ERROR_WANT_ASYNC_JOB: + /* This shouldn't ever happen in s_client - treat as an error */ + case SSL_ERROR_SSL: + ERR_print_errors(bio_err); + goto shut; + } + } +#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_VMS) + /* Assume Windows/DOS/BeOS can always write */ + else if (!ssl_pending && write_tty) +#else + else if (!ssl_pending && FD_ISSET(fileno_stdout(), &writefds)) +#endif + { +#ifdef CHARSET_EBCDIC + ascii2ebcdic(&(sbuf[sbuf_off]), &(sbuf[sbuf_off]), sbuf_len); +#endif + i = raw_write_stdout(&(sbuf[sbuf_off]), sbuf_len); + + if (i <= 0) { + BIO_printf(bio_c_out, "DONE\n"); + ret = 0; + goto shut; + } + + sbuf_len -= i; + sbuf_off += i; + if (sbuf_len <= 0) { + read_ssl = 1; + write_tty = 0; + } + } else if (ssl_pending || FD_ISSET(SSL_get_fd(con), &readfds)) { +#ifdef RENEG + { + static int iiii; + if (++iiii == 52) { + SSL_renegotiate(con); + iiii = 0; + } + } +#endif + k = SSL_read(con, sbuf, 1024 /* BUFSIZZ */ ); + + switch (SSL_get_error(con, k)) { + case SSL_ERROR_NONE: + if (k <= 0) + goto end; + sbuf_off = 0; + sbuf_len = k; + + read_ssl = 0; + write_tty = 1; + break; + case SSL_ERROR_WANT_ASYNC: + BIO_printf(bio_c_out, "read A BLOCK\n"); + wait_for_async(con); + write_tty = 0; + read_ssl = 1; + if ((read_tty == 0) && (write_ssl == 0)) + write_ssl = 1; + break; + case SSL_ERROR_WANT_WRITE: + BIO_printf(bio_c_out, "read W BLOCK\n"); + write_ssl = 1; + read_tty = 0; + break; + case SSL_ERROR_WANT_READ: + BIO_printf(bio_c_out, "read R BLOCK\n"); + write_tty = 0; + read_ssl = 1; + if ((read_tty == 0) && (write_ssl == 0)) + write_ssl = 1; + break; + case SSL_ERROR_WANT_X509_LOOKUP: + BIO_printf(bio_c_out, "read X BLOCK\n"); + break; + case SSL_ERROR_SYSCALL: + ret = get_last_socket_error(); + if (c_brief) + BIO_puts(bio_err, "CONNECTION CLOSED BY SERVER\n"); + else + BIO_printf(bio_err, "read:errno=%d\n", ret); + goto shut; + case SSL_ERROR_ZERO_RETURN: + BIO_printf(bio_c_out, "closed\n"); + ret = 0; + goto shut; + case SSL_ERROR_WANT_ASYNC_JOB: + /* This shouldn't ever happen in s_client. Treat as an error */ + case SSL_ERROR_SSL: + ERR_print_errors(bio_err); + goto shut; + } + } +/* OPENSSL_SYS_MSDOS includes OPENSSL_SYS_WINDOWS */ +#if defined(OPENSSL_SYS_MSDOS) + else if (has_stdin_waiting()) +#else + else if (FD_ISSET(fileno_stdin(), &readfds)) +#endif + { + if (crlf) { + int j, lf_num; + + i = raw_read_stdin(cbuf, BUFSIZZ / 2); + lf_num = 0; + /* both loops are skipped when i <= 0 */ + for (j = 0; j < i; j++) + if (cbuf[j] == '\n') + lf_num++; + for (j = i - 1; j >= 0; j--) { + cbuf[j + lf_num] = cbuf[j]; + if (cbuf[j] == '\n') { + lf_num--; + i++; + cbuf[j + lf_num] = '\r'; + } + } + assert(lf_num == 0); + } else + i = raw_read_stdin(cbuf, BUFSIZZ); +#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) + if (i == 0) + at_eof = 1; +#endif + + if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q' && cmdletters))) { + BIO_printf(bio_err, "DONE\n"); + ret = 0; + goto shut; + } + + if ((!c_ign_eof) && (cbuf[0] == 'R' && cmdletters)) { + BIO_printf(bio_err, "RENEGOTIATING\n"); + SSL_renegotiate(con); + cbuf_len = 0; + } else if (!c_ign_eof && (cbuf[0] == 'K' || cbuf[0] == 'k' ) + && cmdletters) { + BIO_printf(bio_err, "KEYUPDATE\n"); + SSL_key_update(con, + cbuf[0] == 'K' ? SSL_KEY_UPDATE_REQUESTED + : SSL_KEY_UPDATE_NOT_REQUESTED); + cbuf_len = 0; + } +#ifndef OPENSSL_NO_HEARTBEATS + else if ((!c_ign_eof) && (cbuf[0] == 'B' && cmdletters)) { + BIO_printf(bio_err, "HEARTBEATING\n"); + SSL_heartbeat(con); + cbuf_len = 0; + } +#endif + else { + cbuf_len = i; + cbuf_off = 0; +#ifdef CHARSET_EBCDIC + ebcdic2ascii(cbuf, cbuf, i); +#endif + } + + write_ssl = 1; + read_tty = 0; + } + } + + ret = 0; + shut: + if (in_init) + print_stuff(bio_c_out, con, full_log); + do_ssl_shutdown(con); + + /* + * If we ended with an alert being sent, but still with data in the + * network buffer to be read, then calling BIO_closesocket() will + * result in a TCP-RST being sent. On some platforms (notably + * Windows) then this will result in the peer immediately abandoning + * the connection including any buffered alert data before it has + * had a chance to be read. Shutting down the sending side first, + * and then closing the socket sends TCP-FIN first followed by + * TCP-RST. This seems to allow the peer to read the alert data. + */ + shutdown(SSL_get_fd(con), 1); /* SHUT_WR */ + /* + * We just said we have nothing else to say, but it doesn't mean that + * the other side has nothing. It's even recommended to consume incoming + * data. [In testing context this ensures that alerts are passed on...] + */ + timeout.tv_sec = 0; + timeout.tv_usec = 500000; /* some extreme round-trip */ + do { + FD_ZERO(&readfds); + openssl_fdset(s, &readfds); + } while (select(s + 1, &readfds, NULL, NULL, &timeout) > 0 + && BIO_read(sbio, sbuf, BUFSIZZ) > 0); + + BIO_closesocket(SSL_get_fd(con)); + end: + if (con != NULL) { + if (prexit != 0) + print_stuff(bio_c_out, con, 1); + SSL_free(con); + } + SSL_SESSION_free(psksess); +#if !defined(OPENSSL_NO_NEXTPROTONEG) + OPENSSL_free(next_proto.data); +#endif + SSL_CTX_free(ctx); + set_keylog_file(NULL, NULL); + X509_free(cert); + sk_X509_CRL_pop_free(crls, X509_CRL_free); + EVP_PKEY_free(key); + sk_X509_pop_free(chain, X509_free); + OPENSSL_free(pass); +#ifndef OPENSSL_NO_SRP + OPENSSL_free(srp_arg.srppassin); +#endif + OPENSSL_free(connectstr); + OPENSSL_free(bindstr); + OPENSSL_free(host); + OPENSSL_free(port); + X509_VERIFY_PARAM_free(vpm); + ssl_excert_free(exc); + sk_OPENSSL_STRING_free(ssl_args); + sk_OPENSSL_STRING_free(dane_tlsa_rrset); + SSL_CONF_CTX_free(cctx); + OPENSSL_clear_free(cbuf, BUFSIZZ); + OPENSSL_clear_free(sbuf, BUFSIZZ); + OPENSSL_clear_free(mbuf, BUFSIZZ); + release_engine(e); + BIO_free(bio_c_out); + bio_c_out = NULL; + BIO_free(bio_c_msg); + bio_c_msg = NULL; + return ret; +} + +static void print_stuff(BIO *bio, SSL *s, int full) +{ + X509 *peer = NULL; + STACK_OF(X509) *sk; + const SSL_CIPHER *c; + int i, istls13 = (SSL_version(s) == TLS1_3_VERSION); + long verify_result; +#ifndef OPENSSL_NO_COMP + const COMP_METHOD *comp, *expansion; +#endif + unsigned char *exportedkeymat; +#ifndef OPENSSL_NO_CT + const SSL_CTX *ctx = SSL_get_SSL_CTX(s); +#endif + + if (full) { + int got_a_chain = 0; + + sk = SSL_get_peer_cert_chain(s); + if (sk != NULL) { + got_a_chain = 1; + + BIO_printf(bio, "---\nCertificate chain\n"); + for (i = 0; i < sk_X509_num(sk); i++) { + BIO_printf(bio, "%2d s:", i); + X509_NAME_print_ex(bio, X509_get_subject_name(sk_X509_value(sk, i)), 0, get_nameopt()); + BIO_puts(bio, "\n"); + BIO_printf(bio, " i:"); + X509_NAME_print_ex(bio, X509_get_issuer_name(sk_X509_value(sk, i)), 0, get_nameopt()); + BIO_puts(bio, "\n"); + if (c_showcerts) + PEM_write_bio_X509(bio, sk_X509_value(sk, i)); + } + } + + BIO_printf(bio, "---\n"); + peer = SSL_get_peer_certificate(s); + if (peer != NULL) { + BIO_printf(bio, "Server certificate\n"); + + /* Redundant if we showed the whole chain */ + if (!(c_showcerts && got_a_chain)) + PEM_write_bio_X509(bio, peer); + dump_cert_text(bio, peer); + } else { + BIO_printf(bio, "no peer certificate available\n"); + } + print_ca_names(bio, s); + + ssl_print_sigalgs(bio, s); + ssl_print_tmp_key(bio, s); + +#ifndef OPENSSL_NO_CT + /* + * When the SSL session is anonymous, or resumed via an abbreviated + * handshake, no SCTs are provided as part of the handshake. While in + * a resumed session SCTs may be present in the session's certificate, + * no callbacks are invoked to revalidate these, and in any case that + * set of SCTs may be incomplete. Thus it makes little sense to + * attempt to display SCTs from a resumed session's certificate, and of + * course none are associated with an anonymous peer. + */ + if (peer != NULL && !SSL_session_reused(s) && SSL_ct_is_enabled(s)) { + const STACK_OF(SCT) *scts = SSL_get0_peer_scts(s); + int sct_count = scts != NULL ? sk_SCT_num(scts) : 0; + + BIO_printf(bio, "---\nSCTs present (%i)\n", sct_count); + if (sct_count > 0) { + const CTLOG_STORE *log_store = SSL_CTX_get0_ctlog_store(ctx); + + BIO_printf(bio, "---\n"); + for (i = 0; i < sct_count; ++i) { + SCT *sct = sk_SCT_value(scts, i); + + BIO_printf(bio, "SCT validation status: %s\n", + SCT_validation_status_string(sct)); + SCT_print(sct, bio, 0, log_store); + if (i < sct_count - 1) + BIO_printf(bio, "\n---\n"); + } + BIO_printf(bio, "\n"); + } + } +#endif + + BIO_printf(bio, + "---\nSSL handshake has read %ju bytes " + "and written %ju bytes\n", + BIO_number_read(SSL_get_rbio(s)), + BIO_number_written(SSL_get_wbio(s))); + } + print_verify_detail(s, bio); + BIO_printf(bio, (SSL_session_reused(s) ? "---\nReused, " : "---\nNew, ")); + c = SSL_get_current_cipher(s); + BIO_printf(bio, "%s, Cipher is %s\n", + SSL_CIPHER_get_version(c), SSL_CIPHER_get_name(c)); + if (peer != NULL) { + EVP_PKEY *pktmp; + + pktmp = X509_get0_pubkey(peer); + BIO_printf(bio, "Server public key is %d bit\n", + EVP_PKEY_bits(pktmp)); + } + BIO_printf(bio, "Secure Renegotiation IS%s supported\n", + SSL_get_secure_renegotiation_support(s) ? "" : " NOT"); +#ifndef OPENSSL_NO_COMP + comp = SSL_get_current_compression(s); + expansion = SSL_get_current_expansion(s); + BIO_printf(bio, "Compression: %s\n", + comp ? SSL_COMP_get_name(comp) : "NONE"); + BIO_printf(bio, "Expansion: %s\n", + expansion ? SSL_COMP_get_name(expansion) : "NONE"); +#endif + +#ifdef SSL_DEBUG + { + /* Print out local port of connection: useful for debugging */ + int sock; + union BIO_sock_info_u info; + + sock = SSL_get_fd(s); + if ((info.addr = BIO_ADDR_new()) != NULL + && BIO_sock_info(sock, BIO_SOCK_INFO_ADDRESS, &info)) { + BIO_printf(bio_c_out, "LOCAL PORT is %u\n", + ntohs(BIO_ADDR_rawport(info.addr))); + } + BIO_ADDR_free(info.addr); + } +#endif + +#if !defined(OPENSSL_NO_NEXTPROTONEG) + if (next_proto.status != -1) { + const unsigned char *proto; + unsigned int proto_len; + SSL_get0_next_proto_negotiated(s, &proto, &proto_len); + BIO_printf(bio, "Next protocol: (%d) ", next_proto.status); + BIO_write(bio, proto, proto_len); + BIO_write(bio, "\n", 1); + } +#endif + { + const unsigned char *proto; + unsigned int proto_len; + SSL_get0_alpn_selected(s, &proto, &proto_len); + if (proto_len > 0) { + BIO_printf(bio, "ALPN protocol: "); + BIO_write(bio, proto, proto_len); + BIO_write(bio, "\n", 1); + } else + BIO_printf(bio, "No ALPN negotiated\n"); + } + +#ifndef OPENSSL_NO_SRTP + { + SRTP_PROTECTION_PROFILE *srtp_profile = + SSL_get_selected_srtp_profile(s); + + if (srtp_profile) + BIO_printf(bio, "SRTP Extension negotiated, profile=%s\n", + srtp_profile->name); + } +#endif + + if (istls13) { + switch (SSL_get_early_data_status(s)) { + case SSL_EARLY_DATA_NOT_SENT: + BIO_printf(bio, "Early data was not sent\n"); + break; + + case SSL_EARLY_DATA_REJECTED: + BIO_printf(bio, "Early data was rejected\n"); + break; + + case SSL_EARLY_DATA_ACCEPTED: + BIO_printf(bio, "Early data was accepted\n"); + break; + + } + + /* + * We also print the verify results when we dump session information, + * but in TLSv1.3 we may not get that right away (or at all) depending + * on when we get a NewSessionTicket. Therefore we print it now as well. + */ + verify_result = SSL_get_verify_result(s); + BIO_printf(bio, "Verify return code: %ld (%s)\n", verify_result, + X509_verify_cert_error_string(verify_result)); + } else { + /* In TLSv1.3 we do this on arrival of a NewSessionTicket */ + SSL_SESSION_print(bio, SSL_get_session(s)); + } + + if (SSL_get_session(s) != NULL && keymatexportlabel != NULL) { + BIO_printf(bio, "Keying material exporter:\n"); + BIO_printf(bio, " Label: '%s'\n", keymatexportlabel); + BIO_printf(bio, " Length: %i bytes\n", keymatexportlen); + exportedkeymat = app_malloc(keymatexportlen, "export key"); + if (!SSL_export_keying_material(s, exportedkeymat, + keymatexportlen, + keymatexportlabel, + strlen(keymatexportlabel), + NULL, 0, 0)) { + BIO_printf(bio, " Error\n"); + } else { + BIO_printf(bio, " Keying material: "); + for (i = 0; i < keymatexportlen; i++) + BIO_printf(bio, "%02X", exportedkeymat[i]); + BIO_printf(bio, "\n"); + } + OPENSSL_free(exportedkeymat); + } + BIO_printf(bio, "---\n"); + X509_free(peer); + /* flush, or debugging output gets mixed with http response */ + (void)BIO_flush(bio); +} + +# ifndef OPENSSL_NO_OCSP +static int ocsp_resp_cb(SSL *s, void *arg) +{ + const unsigned char *p; + int len; + OCSP_RESPONSE *rsp; + len = SSL_get_tlsext_status_ocsp_resp(s, &p); + BIO_puts(arg, "OCSP response: "); + if (p == NULL) { + BIO_puts(arg, "no response sent\n"); + return 1; + } + rsp = d2i_OCSP_RESPONSE(NULL, &p, len); + if (rsp == NULL) { + BIO_puts(arg, "response parse error\n"); + BIO_dump_indent(arg, (char *)p, len, 4); + return 0; + } + BIO_puts(arg, "\n======================================\n"); + OCSP_RESPONSE_print(arg, rsp, 0); + BIO_puts(arg, "======================================\n"); + OCSP_RESPONSE_free(rsp); + return 1; +} +# endif + +static int ldap_ExtendedResponse_parse(const char *buf, long rem) +{ + const unsigned char *cur, *end; + long len; + int tag, xclass, inf, ret = -1; + + cur = (const unsigned char *)buf; + end = cur + rem; + + /* + * From RFC 4511: + * + * LDAPMessage ::= SEQUENCE { + * messageID MessageID, + * protocolOp CHOICE { + * ... + * extendedResp ExtendedResponse, + * ... }, + * controls [0] Controls OPTIONAL } + * + * ExtendedResponse ::= [APPLICATION 24] SEQUENCE { + * COMPONENTS OF LDAPResult, + * responseName [10] LDAPOID OPTIONAL, + * responseValue [11] OCTET STRING OPTIONAL } + * + * LDAPResult ::= SEQUENCE { + * resultCode ENUMERATED { + * success (0), + * ... + * other (80), + * ... }, + * matchedDN LDAPDN, + * diagnosticMessage LDAPString, + * referral [3] Referral OPTIONAL } + */ + + /* pull SEQUENCE */ + inf = ASN1_get_object(&cur, &len, &tag, &xclass, rem); + if (inf != V_ASN1_CONSTRUCTED || tag != V_ASN1_SEQUENCE || + (rem = end - cur, len > rem)) { + BIO_printf(bio_err, "Unexpected LDAP response\n"); + goto end; + } + + rem = len; /* ensure that we don't overstep the SEQUENCE */ + + /* pull MessageID */ + inf = ASN1_get_object(&cur, &len, &tag, &xclass, rem); + if (inf != V_ASN1_UNIVERSAL || tag != V_ASN1_INTEGER || + (rem = end - cur, len > rem)) { + BIO_printf(bio_err, "No MessageID\n"); + goto end; + } + + cur += len; /* shall we check for MessageId match or just skip? */ + + /* pull [APPLICATION 24] */ + rem = end - cur; + inf = ASN1_get_object(&cur, &len, &tag, &xclass, rem); + if (inf != V_ASN1_CONSTRUCTED || xclass != V_ASN1_APPLICATION || + tag != 24) { + BIO_printf(bio_err, "Not ExtendedResponse\n"); + goto end; + } + + /* pull resultCode */ + rem = end - cur; + inf = ASN1_get_object(&cur, &len, &tag, &xclass, rem); + if (inf != V_ASN1_UNIVERSAL || tag != V_ASN1_ENUMERATED || len == 0 || + (rem = end - cur, len > rem)) { + BIO_printf(bio_err, "Not LDAPResult\n"); + goto end; + } + + /* len should always be one, but just in case... */ + for (ret = 0, inf = 0; inf < len; inf++) { + ret <<= 8; + ret |= cur[inf]; + } + /* There is more data, but we don't care... */ + end: + return ret; +} + +/* + * Host dNS Name verifier: used for checking that the hostname is in dNS format + * before setting it as SNI + */ +static int is_dNS_name(const char *host) +{ + const size_t MAX_LABEL_LENGTH = 63; + size_t i; + int isdnsname = 0; + size_t length = strlen(host); + size_t label_length = 0; + int all_numeric = 1; + + /* + * Deviation from strict DNS name syntax, also check names with '_' + * Check DNS name syntax, any '-' or '.' must be internal, + * and on either side of each '.' we can't have a '-' or '.'. + * + * If the name has just one label, we don't consider it a DNS name. + */ + for (i = 0; i < length && label_length < MAX_LABEL_LENGTH; ++i) { + char c = host[i]; + + if ((c >= 'a' && c <= 'z') + || (c >= 'A' && c <= 'Z') + || c == '_') { + label_length += 1; + all_numeric = 0; + continue; + } + + if (c >= '0' && c <= '9') { + label_length += 1; + continue; + } + + /* Dot and hyphen cannot be first or last. */ + if (i > 0 && i < length - 1) { + if (c == '-') { + label_length += 1; + continue; + } + /* + * Next to a dot the preceding and following characters must not be + * another dot or a hyphen. Otherwise, record that the name is + * plausible, since it has two or more labels. + */ + if (c == '.' + && host[i + 1] != '.' + && host[i - 1] != '-' + && host[i + 1] != '-') { + label_length = 0; + isdnsname = 1; + continue; + } + } + isdnsname = 0; + break; + } + + /* dNS name must not be all numeric and labels must be shorter than 64 characters. */ + isdnsname &= !all_numeric && !(label_length == MAX_LABEL_LENGTH); + + return isdnsname; +} +#endif /* OPENSSL_NO_SOCK */ diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/s_server.c b/trunk/3rdparty/openssl-1.1-fit/apps/s_server.c new file mode 100644 index 000000000..929a08bd8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/s_server.c @@ -0,0 +1,3632 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * Copyright 2005 Nokia. All rights reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#if defined(_WIN32) +/* Included before async.h to avoid some warnings */ +# include +#endif + +#include +#include +#include + +#ifndef OPENSSL_NO_SOCK + +/* + * With IPv6, it looks like Digital has mixed up the proper order of + * recursive header file inclusion, resulting in the compiler complaining + * that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which is + * needed to have fileno() declared correctly... So let's define u_int + */ +#if defined(OPENSSL_SYS_VMS_DECC) && !defined(__U_INT) +# define __U_INT +typedef unsigned int u_int; +#endif + +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include +#include +#include +#ifndef OPENSSL_NO_DH +# include +#endif +#ifndef OPENSSL_NO_RSA +# include +#endif +#ifndef OPENSSL_NO_SRP +# include +#endif +#include "s_apps.h" +#include "timeouts.h" +#ifdef CHARSET_EBCDIC +#include +#endif +#include "internal/sockets.h" + +static int not_resumable_sess_cb(SSL *s, int is_forward_secure); +static int sv_body(int s, int stype, int prot, unsigned char *context); +static int www_body(int s, int stype, int prot, unsigned char *context); +static int rev_body(int s, int stype, int prot, unsigned char *context); +static void close_accept_socket(void); +static int init_ssl_connection(SSL *s); +static void print_stats(BIO *bp, SSL_CTX *ctx); +static int generate_session_id(SSL *ssl, unsigned char *id, + unsigned int *id_len); +static void init_session_cache_ctx(SSL_CTX *sctx); +static void free_sessions(void); +#ifndef OPENSSL_NO_DH +static DH *load_dh_param(const char *dhfile); +#endif +static void print_connection_info(SSL *con); + +static const int bufsize = 16 * 1024; +static int accept_socket = -1; + +#define TEST_CERT "server.pem" +#define TEST_CERT2 "server2.pem" + +static int s_nbio = 0; +static int s_nbio_test = 0; +static int s_crlf = 0; +static SSL_CTX *ctx = NULL; +static SSL_CTX *ctx2 = NULL; +static int www = 0; + +static BIO *bio_s_out = NULL; +static BIO *bio_s_msg = NULL; +static int s_debug = 0; +static int s_tlsextdebug = 0; +static int s_msg = 0; +static int s_quiet = 0; +static int s_ign_eof = 0; +static int s_brief = 0; + +static char *keymatexportlabel = NULL; +static int keymatexportlen = 20; + +static int async = 0; + +static const char *session_id_prefix = NULL; + +#ifndef OPENSSL_NO_DTLS +static int enable_timeouts = 0; +static long socket_mtu; +#endif + +/* + * We define this but make it always be 0 in no-dtls builds to simplify the + * code. + */ +static int dtlslisten = 0; +static int stateless = 0; + +static int early_data = 0; +static SSL_SESSION *psksess = NULL; + +static char *psk_identity = "Client_identity"; +char *psk_key = NULL; /* by default PSK is not used */ + +#ifndef OPENSSL_NO_PSK +static unsigned int psk_server_cb(SSL *ssl, const char *identity, + unsigned char *psk, + unsigned int max_psk_len) +{ + long key_len = 0; + unsigned char *key; + + if (s_debug) + BIO_printf(bio_s_out, "psk_server_cb\n"); + if (identity == NULL) { + BIO_printf(bio_err, "Error: client did not send PSK identity\n"); + goto out_err; + } + if (s_debug) + BIO_printf(bio_s_out, "identity_len=%d identity=%s\n", + (int)strlen(identity), identity); + + /* here we could lookup the given identity e.g. from a database */ + if (strcmp(identity, psk_identity) != 0) { + BIO_printf(bio_s_out, "PSK warning: client identity not what we expected" + " (got '%s' expected '%s')\n", identity, psk_identity); + } else { + if (s_debug) + BIO_printf(bio_s_out, "PSK client identity found\n"); + } + + /* convert the PSK key to binary */ + key = OPENSSL_hexstr2buf(psk_key, &key_len); + if (key == NULL) { + BIO_printf(bio_err, "Could not convert PSK key '%s' to buffer\n", + psk_key); + return 0; + } + if (key_len > (int)max_psk_len) { + BIO_printf(bio_err, + "psk buffer of callback is too small (%d) for key (%ld)\n", + max_psk_len, key_len); + OPENSSL_free(key); + return 0; + } + + memcpy(psk, key, key_len); + OPENSSL_free(key); + + if (s_debug) + BIO_printf(bio_s_out, "fetched PSK len=%ld\n", key_len); + return key_len; + out_err: + if (s_debug) + BIO_printf(bio_err, "Error in PSK server callback\n"); + (void)BIO_flush(bio_err); + (void)BIO_flush(bio_s_out); + return 0; +} +#endif + +#define TLS13_AES_128_GCM_SHA256_BYTES ((const unsigned char *)"\x13\x01") +#define TLS13_AES_256_GCM_SHA384_BYTES ((const unsigned char *)"\x13\x02") + +static int psk_find_session_cb(SSL *ssl, const unsigned char *identity, + size_t identity_len, SSL_SESSION **sess) +{ + SSL_SESSION *tmpsess = NULL; + unsigned char *key; + long key_len; + const SSL_CIPHER *cipher = NULL; + + if (strlen(psk_identity) != identity_len + || memcmp(psk_identity, identity, identity_len) != 0) { + *sess = NULL; + return 1; + } + + if (psksess != NULL) { + SSL_SESSION_up_ref(psksess); + *sess = psksess; + return 1; + } + + key = OPENSSL_hexstr2buf(psk_key, &key_len); + if (key == NULL) { + BIO_printf(bio_err, "Could not convert PSK key '%s' to buffer\n", + psk_key); + return 0; + } + + /* We default to SHA256 */ + cipher = SSL_CIPHER_find(ssl, tls13_aes128gcmsha256_id); + if (cipher == NULL) { + BIO_printf(bio_err, "Error finding suitable ciphersuite\n"); + OPENSSL_free(key); + return 0; + } + + tmpsess = SSL_SESSION_new(); + if (tmpsess == NULL + || !SSL_SESSION_set1_master_key(tmpsess, key, key_len) + || !SSL_SESSION_set_cipher(tmpsess, cipher) + || !SSL_SESSION_set_protocol_version(tmpsess, SSL_version(ssl))) { + OPENSSL_free(key); + return 0; + } + OPENSSL_free(key); + *sess = tmpsess; + + return 1; +} + +#ifndef OPENSSL_NO_SRP +/* This is a context that we pass to callbacks */ +typedef struct srpsrvparm_st { + char *login; + SRP_VBASE *vb; + SRP_user_pwd *user; +} srpsrvparm; +static srpsrvparm srp_callback_parm; + +/* + * This callback pretends to require some asynchronous logic in order to + * obtain a verifier. When the callback is called for a new connection we + * return with a negative value. This will provoke the accept etc to return + * with an LOOKUP_X509. The main logic of the reinvokes the suspended call + * (which would normally occur after a worker has finished) and we set the + * user parameters. + */ +static int ssl_srp_server_param_cb(SSL *s, int *ad, void *arg) +{ + srpsrvparm *p = (srpsrvparm *) arg; + int ret = SSL3_AL_FATAL; + + if (p->login == NULL && p->user == NULL) { + p->login = SSL_get_srp_username(s); + BIO_printf(bio_err, "SRP username = \"%s\"\n", p->login); + return -1; + } + + if (p->user == NULL) { + BIO_printf(bio_err, "User %s doesn't exist\n", p->login); + goto err; + } + + if (SSL_set_srp_server_param + (s, p->user->N, p->user->g, p->user->s, p->user->v, + p->user->info) < 0) { + *ad = SSL_AD_INTERNAL_ERROR; + goto err; + } + BIO_printf(bio_err, + "SRP parameters set: username = \"%s\" info=\"%s\" \n", + p->login, p->user->info); + ret = SSL_ERROR_NONE; + + err: + SRP_user_pwd_free(p->user); + p->user = NULL; + p->login = NULL; + return ret; +} + +#endif + +static int local_argc = 0; +static char **local_argv; + +#ifdef CHARSET_EBCDIC +static int ebcdic_new(BIO *bi); +static int ebcdic_free(BIO *a); +static int ebcdic_read(BIO *b, char *out, int outl); +static int ebcdic_write(BIO *b, const char *in, int inl); +static long ebcdic_ctrl(BIO *b, int cmd, long num, void *ptr); +static int ebcdic_gets(BIO *bp, char *buf, int size); +static int ebcdic_puts(BIO *bp, const char *str); + +# define BIO_TYPE_EBCDIC_FILTER (18|0x0200) +static BIO_METHOD *methods_ebcdic = NULL; + +/* This struct is "unwarranted chumminess with the compiler." */ +typedef struct { + size_t alloced; + char buff[1]; +} EBCDIC_OUTBUFF; + +static const BIO_METHOD *BIO_f_ebcdic_filter() +{ + if (methods_ebcdic == NULL) { + methods_ebcdic = BIO_meth_new(BIO_TYPE_EBCDIC_FILTER, + "EBCDIC/ASCII filter"); + if (methods_ebcdic == NULL + || !BIO_meth_set_write(methods_ebcdic, ebcdic_write) + || !BIO_meth_set_read(methods_ebcdic, ebcdic_read) + || !BIO_meth_set_puts(methods_ebcdic, ebcdic_puts) + || !BIO_meth_set_gets(methods_ebcdic, ebcdic_gets) + || !BIO_meth_set_ctrl(methods_ebcdic, ebcdic_ctrl) + || !BIO_meth_set_create(methods_ebcdic, ebcdic_new) + || !BIO_meth_set_destroy(methods_ebcdic, ebcdic_free)) + return NULL; + } + return methods_ebcdic; +} + +static int ebcdic_new(BIO *bi) +{ + EBCDIC_OUTBUFF *wbuf; + + wbuf = app_malloc(sizeof(*wbuf) + 1024, "ebcdic wbuf"); + wbuf->alloced = 1024; + wbuf->buff[0] = '\0'; + + BIO_set_data(bi, wbuf); + BIO_set_init(bi, 1); + return 1; +} + +static int ebcdic_free(BIO *a) +{ + EBCDIC_OUTBUFF *wbuf; + + if (a == NULL) + return 0; + wbuf = BIO_get_data(a); + OPENSSL_free(wbuf); + BIO_set_data(a, NULL); + BIO_set_init(a, 0); + + return 1; +} + +static int ebcdic_read(BIO *b, char *out, int outl) +{ + int ret = 0; + BIO *next = BIO_next(b); + + if (out == NULL || outl == 0) + return 0; + if (next == NULL) + return 0; + + ret = BIO_read(next, out, outl); + if (ret > 0) + ascii2ebcdic(out, out, ret); + return ret; +} + +static int ebcdic_write(BIO *b, const char *in, int inl) +{ + EBCDIC_OUTBUFF *wbuf; + BIO *next = BIO_next(b); + int ret = 0; + int num; + + if ((in == NULL) || (inl <= 0)) + return 0; + if (next == NULL) + return 0; + + wbuf = (EBCDIC_OUTBUFF *) BIO_get_data(b); + + if (inl > (num = wbuf->alloced)) { + num = num + num; /* double the size */ + if (num < inl) + num = inl; + OPENSSL_free(wbuf); + wbuf = app_malloc(sizeof(*wbuf) + num, "grow ebcdic wbuf"); + + wbuf->alloced = num; + wbuf->buff[0] = '\0'; + + BIO_set_data(b, wbuf); + } + + ebcdic2ascii(wbuf->buff, in, inl); + + ret = BIO_write(next, wbuf->buff, inl); + + return ret; +} + +static long ebcdic_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + long ret; + BIO *next = BIO_next(b); + + if (next == NULL) + return 0; + switch (cmd) { + case BIO_CTRL_DUP: + ret = 0L; + break; + default: + ret = BIO_ctrl(next, cmd, num, ptr); + break; + } + return ret; +} + +static int ebcdic_gets(BIO *bp, char *buf, int size) +{ + int i, ret = 0; + BIO *next = BIO_next(bp); + + if (next == NULL) + return 0; +/* return(BIO_gets(bp->next_bio,buf,size));*/ + for (i = 0; i < size - 1; ++i) { + ret = ebcdic_read(bp, &buf[i], 1); + if (ret <= 0) + break; + else if (buf[i] == '\n') { + ++i; + break; + } + } + if (i < size) + buf[i] = '\0'; + return (ret < 0 && i == 0) ? ret : i; +} + +static int ebcdic_puts(BIO *bp, const char *str) +{ + if (BIO_next(bp) == NULL) + return 0; + return ebcdic_write(bp, str, strlen(str)); +} +#endif + +/* This is a context that we pass to callbacks */ +typedef struct tlsextctx_st { + char *servername; + BIO *biodebug; + int extension_error; +} tlsextctx; + +static int ssl_servername_cb(SSL *s, int *ad, void *arg) +{ + tlsextctx *p = (tlsextctx *) arg; + const char *servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); + + if (servername != NULL && p->biodebug != NULL) { + const char *cp = servername; + unsigned char uc; + + BIO_printf(p->biodebug, "Hostname in TLS extension: \""); + while ((uc = *cp++) != 0) + BIO_printf(p->biodebug, + isascii(uc) && isprint(uc) ? "%c" : "\\x%02x", uc); + BIO_printf(p->biodebug, "\"\n"); + } + + if (p->servername == NULL) + return SSL_TLSEXT_ERR_NOACK; + + if (servername != NULL) { + if (strcasecmp(servername, p->servername)) + return p->extension_error; + if (ctx2 != NULL) { + BIO_printf(p->biodebug, "Switching server context.\n"); + SSL_set_SSL_CTX(s, ctx2); + } + } + return SSL_TLSEXT_ERR_OK; +} + +/* Structure passed to cert status callback */ +typedef struct tlsextstatusctx_st { + int timeout; + /* File to load OCSP Response from (or NULL if no file) */ + char *respin; + /* Default responder to use */ + char *host, *path, *port; + int use_ssl; + int verbose; +} tlsextstatusctx; + +static tlsextstatusctx tlscstatp = { -1 }; + +#ifndef OPENSSL_NO_OCSP + +/* + * Helper function to get an OCSP_RESPONSE from a responder. This is a + * simplified version. It examines certificates each time and makes one OCSP + * responder query for each request. A full version would store details such as + * the OCSP certificate IDs and minimise the number of OCSP responses by caching + * them until they were considered "expired". + */ +static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx, + OCSP_RESPONSE **resp) +{ + char *host = NULL, *port = NULL, *path = NULL; + int use_ssl; + STACK_OF(OPENSSL_STRING) *aia = NULL; + X509 *x = NULL; + X509_STORE_CTX *inctx = NULL; + X509_OBJECT *obj; + OCSP_REQUEST *req = NULL; + OCSP_CERTID *id = NULL; + STACK_OF(X509_EXTENSION) *exts; + int ret = SSL_TLSEXT_ERR_NOACK; + int i; + + /* Build up OCSP query from server certificate */ + x = SSL_get_certificate(s); + aia = X509_get1_ocsp(x); + if (aia != NULL) { + if (!OCSP_parse_url(sk_OPENSSL_STRING_value(aia, 0), + &host, &port, &path, &use_ssl)) { + BIO_puts(bio_err, "cert_status: can't parse AIA URL\n"); + goto err; + } + if (srctx->verbose) + BIO_printf(bio_err, "cert_status: AIA URL: %s\n", + sk_OPENSSL_STRING_value(aia, 0)); + } else { + if (srctx->host == NULL) { + BIO_puts(bio_err, + "cert_status: no AIA and no default responder URL\n"); + goto done; + } + host = srctx->host; + path = srctx->path; + port = srctx->port; + use_ssl = srctx->use_ssl; + } + + inctx = X509_STORE_CTX_new(); + if (inctx == NULL) + goto err; + if (!X509_STORE_CTX_init(inctx, + SSL_CTX_get_cert_store(SSL_get_SSL_CTX(s)), + NULL, NULL)) + goto err; + obj = X509_STORE_CTX_get_obj_by_subject(inctx, X509_LU_X509, + X509_get_issuer_name(x)); + if (obj == NULL) { + BIO_puts(bio_err, "cert_status: Can't retrieve issuer certificate.\n"); + goto done; + } + id = OCSP_cert_to_id(NULL, x, X509_OBJECT_get0_X509(obj)); + X509_OBJECT_free(obj); + if (id == NULL) + goto err; + req = OCSP_REQUEST_new(); + if (req == NULL) + goto err; + if (!OCSP_request_add0_id(req, id)) + goto err; + id = NULL; + /* Add any extensions to the request */ + SSL_get_tlsext_status_exts(s, &exts); + for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { + X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i); + if (!OCSP_REQUEST_add_ext(req, ext, -1)) + goto err; + } + *resp = process_responder(req, host, path, port, use_ssl, NULL, + srctx->timeout); + if (*resp == NULL) { + BIO_puts(bio_err, "cert_status: error querying responder\n"); + goto done; + } + + ret = SSL_TLSEXT_ERR_OK; + goto done; + + err: + ret = SSL_TLSEXT_ERR_ALERT_FATAL; + done: + /* + * If we parsed aia we need to free; otherwise they were copied and we + * don't + */ + if (aia != NULL) { + OPENSSL_free(host); + OPENSSL_free(path); + OPENSSL_free(port); + X509_email_free(aia); + } + OCSP_CERTID_free(id); + OCSP_REQUEST_free(req); + X509_STORE_CTX_free(inctx); + return ret; +} + +/* + * Certificate Status callback. This is called when a client includes a + * certificate status request extension. The response is either obtained from a + * file, or from an OCSP responder. + */ +static int cert_status_cb(SSL *s, void *arg) +{ + tlsextstatusctx *srctx = arg; + OCSP_RESPONSE *resp = NULL; + unsigned char *rspder = NULL; + int rspderlen; + int ret = SSL_TLSEXT_ERR_ALERT_FATAL; + + if (srctx->verbose) + BIO_puts(bio_err, "cert_status: callback called\n"); + + if (srctx->respin != NULL) { + BIO *derbio = bio_open_default(srctx->respin, 'r', FORMAT_ASN1); + if (derbio == NULL) { + BIO_puts(bio_err, "cert_status: Cannot open OCSP response file\n"); + goto err; + } + resp = d2i_OCSP_RESPONSE_bio(derbio, NULL); + BIO_free(derbio); + if (resp == NULL) { + BIO_puts(bio_err, "cert_status: Error reading OCSP response\n"); + goto err; + } + } else { + ret = get_ocsp_resp_from_responder(s, srctx, &resp); + if (ret != SSL_TLSEXT_ERR_OK) + goto err; + } + + rspderlen = i2d_OCSP_RESPONSE(resp, &rspder); + if (rspderlen <= 0) + goto err; + + SSL_set_tlsext_status_ocsp_resp(s, rspder, rspderlen); + if (srctx->verbose) { + BIO_puts(bio_err, "cert_status: ocsp response sent:\n"); + OCSP_RESPONSE_print(bio_err, resp, 2); + } + + ret = SSL_TLSEXT_ERR_OK; + + err: + if (ret != SSL_TLSEXT_ERR_OK) + ERR_print_errors(bio_err); + + OCSP_RESPONSE_free(resp); + + return ret; +} +#endif + +#ifndef OPENSSL_NO_NEXTPROTONEG +/* This is the context that we pass to next_proto_cb */ +typedef struct tlsextnextprotoctx_st { + unsigned char *data; + size_t len; +} tlsextnextprotoctx; + +static int next_proto_cb(SSL *s, const unsigned char **data, + unsigned int *len, void *arg) +{ + tlsextnextprotoctx *next_proto = arg; + + *data = next_proto->data; + *len = next_proto->len; + + return SSL_TLSEXT_ERR_OK; +} +#endif /* ndef OPENSSL_NO_NEXTPROTONEG */ + +/* This the context that we pass to alpn_cb */ +typedef struct tlsextalpnctx_st { + unsigned char *data; + size_t len; +} tlsextalpnctx; + +static int alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen, void *arg) +{ + tlsextalpnctx *alpn_ctx = arg; + + if (!s_quiet) { + /* We can assume that |in| is syntactically valid. */ + unsigned int i; + BIO_printf(bio_s_out, "ALPN protocols advertised by the client: "); + for (i = 0; i < inlen;) { + if (i) + BIO_write(bio_s_out, ", ", 2); + BIO_write(bio_s_out, &in[i + 1], in[i]); + i += in[i] + 1; + } + BIO_write(bio_s_out, "\n", 1); + } + + if (SSL_select_next_proto + ((unsigned char **)out, outlen, alpn_ctx->data, alpn_ctx->len, in, + inlen) != OPENSSL_NPN_NEGOTIATED) { + return SSL_TLSEXT_ERR_NOACK; + } + + if (!s_quiet) { + BIO_printf(bio_s_out, "ALPN protocols selected: "); + BIO_write(bio_s_out, *out, *outlen); + BIO_write(bio_s_out, "\n", 1); + } + + return SSL_TLSEXT_ERR_OK; +} + +static int not_resumable_sess_cb(SSL *s, int is_forward_secure) +{ + /* disable resumption for sessions with forward secure ciphers */ + return is_forward_secure; +} + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ENGINE, + OPT_4, OPT_6, OPT_ACCEPT, OPT_PORT, OPT_UNIX, OPT_UNLINK, OPT_NACCEPT, + OPT_VERIFY, OPT_NAMEOPT, OPT_UPPER_V_VERIFY, OPT_CONTEXT, OPT_CERT, OPT_CRL, + OPT_CRL_DOWNLOAD, OPT_SERVERINFO, OPT_CERTFORM, OPT_KEY, OPT_KEYFORM, + OPT_PASS, OPT_CERT_CHAIN, OPT_DHPARAM, OPT_DCERTFORM, OPT_DCERT, + OPT_DKEYFORM, OPT_DPASS, OPT_DKEY, OPT_DCERT_CHAIN, OPT_NOCERT, + OPT_CAPATH, OPT_NOCAPATH, OPT_CHAINCAPATH, OPT_VERIFYCAPATH, OPT_NO_CACHE, + OPT_EXT_CACHE, OPT_CRLFORM, OPT_VERIFY_RET_ERROR, OPT_VERIFY_QUIET, + OPT_BUILD_CHAIN, OPT_CAFILE, OPT_NOCAFILE, OPT_CHAINCAFILE, + OPT_VERIFYCAFILE, OPT_NBIO, OPT_NBIO_TEST, OPT_IGN_EOF, OPT_NO_IGN_EOF, + OPT_DEBUG, OPT_TLSEXTDEBUG, OPT_STATUS, OPT_STATUS_VERBOSE, + OPT_STATUS_TIMEOUT, OPT_STATUS_URL, OPT_STATUS_FILE, OPT_MSG, OPT_MSGFILE, + OPT_TRACE, OPT_SECURITY_DEBUG, OPT_SECURITY_DEBUG_VERBOSE, OPT_STATE, + OPT_CRLF, OPT_QUIET, OPT_BRIEF, OPT_NO_DHE, + OPT_NO_RESUME_EPHEMERAL, OPT_PSK_IDENTITY, OPT_PSK_HINT, OPT_PSK, + OPT_PSK_SESS, OPT_SRPVFILE, OPT_SRPUSERSEED, OPT_REV, OPT_WWW, + OPT_UPPER_WWW, OPT_HTTP, OPT_ASYNC, OPT_SSL_CONFIG, + OPT_MAX_SEND_FRAG, OPT_SPLIT_SEND_FRAG, OPT_MAX_PIPELINES, OPT_READ_BUF, + OPT_SSL3, OPT_TLS1_3, OPT_TLS1_2, OPT_TLS1_1, OPT_TLS1, OPT_DTLS, OPT_DTLS1, + OPT_DTLS1_2, OPT_SCTP, OPT_TIMEOUT, OPT_MTU, OPT_LISTEN, OPT_STATELESS, + OPT_ID_PREFIX, OPT_SERVERNAME, OPT_SERVERNAME_FATAL, + OPT_CERT2, OPT_KEY2, OPT_NEXTPROTONEG, OPT_ALPN, + OPT_SRTP_PROFILES, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN, + OPT_KEYLOG_FILE, OPT_MAX_EARLY, OPT_RECV_MAX_EARLY, OPT_EARLY_DATA, + OPT_S_NUM_TICKETS, OPT_ANTI_REPLAY, OPT_NO_ANTI_REPLAY, OPT_SCTP_LABEL_BUG, + OPT_R_ENUM, + OPT_S_ENUM, + OPT_V_ENUM, + OPT_X_ENUM +} OPTION_CHOICE; + +const OPTIONS s_server_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"port", OPT_PORT, 'p', + "TCP/IP port to listen on for connections (default is " PORT ")"}, + {"accept", OPT_ACCEPT, 's', + "TCP/IP optional host and port to listen on for connections (default is *:" PORT ")"}, +#ifdef AF_UNIX + {"unix", OPT_UNIX, 's', "Unix domain socket to accept on"}, +#endif + {"4", OPT_4, '-', "Use IPv4 only"}, + {"6", OPT_6, '-', "Use IPv6 only"}, +#ifdef AF_UNIX + {"unlink", OPT_UNLINK, '-', "For -unix, unlink existing socket first"}, +#endif + {"context", OPT_CONTEXT, 's', "Set session ID context"}, + {"verify", OPT_VERIFY, 'n', "Turn on peer certificate verification"}, + {"Verify", OPT_UPPER_V_VERIFY, 'n', + "Turn on peer certificate verification, must have a cert"}, + {"cert", OPT_CERT, '<', "Certificate file to use; default is " TEST_CERT}, + {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"}, + {"naccept", OPT_NACCEPT, 'p', "Terminate after #num connections"}, + {"serverinfo", OPT_SERVERINFO, 's', + "PEM serverinfo file for certificate"}, + {"certform", OPT_CERTFORM, 'F', + "Certificate format (PEM or DER) PEM default"}, + {"key", OPT_KEY, 's', + "Private Key if not in -cert; default is " TEST_CERT}, + {"keyform", OPT_KEYFORM, 'f', + "Key format (PEM, DER or ENGINE) PEM default"}, + {"pass", OPT_PASS, 's', "Private key file pass phrase source"}, + {"dcert", OPT_DCERT, '<', + "Second certificate file to use (usually for DSA)"}, + {"dhparam", OPT_DHPARAM, '<', "DH parameters file to use"}, + {"dcertform", OPT_DCERTFORM, 'F', + "Second certificate format (PEM or DER) PEM default"}, + {"dkey", OPT_DKEY, '<', + "Second private key file to use (usually for DSA)"}, + {"dkeyform", OPT_DKEYFORM, 'F', + "Second key format (PEM, DER or ENGINE) PEM default"}, + {"dpass", OPT_DPASS, 's', "Second private key file pass phrase source"}, + {"nbio_test", OPT_NBIO_TEST, '-', "Test with the non-blocking test bio"}, + {"crlf", OPT_CRLF, '-', "Convert LF from terminal into CRLF"}, + {"debug", OPT_DEBUG, '-', "Print more output"}, + {"msg", OPT_MSG, '-', "Show protocol messages"}, + {"msgfile", OPT_MSGFILE, '>', + "File to send output of -msg or -trace, instead of stdout"}, + {"state", OPT_STATE, '-', "Print the SSL states"}, + {"CAfile", OPT_CAFILE, '<', "PEM format file of CA's"}, + {"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"}, + {"no-CAfile", OPT_NOCAFILE, '-', + "Do not load the default certificates file"}, + {"no-CApath", OPT_NOCAPATH, '-', + "Do not load certificates from the default certificates directory"}, + {"nocert", OPT_NOCERT, '-', "Don't use any certificates (Anon-DH)"}, + {"quiet", OPT_QUIET, '-', "No server output"}, + {"no_resume_ephemeral", OPT_NO_RESUME_EPHEMERAL, '-', + "Disable caching and tickets if ephemeral (EC)DH is used"}, + {"www", OPT_WWW, '-', "Respond to a 'GET /' with a status page"}, + {"WWW", OPT_UPPER_WWW, '-', "Respond to a 'GET with the file ./path"}, + {"servername", OPT_SERVERNAME, 's', + "Servername for HostName TLS extension"}, + {"servername_fatal", OPT_SERVERNAME_FATAL, '-', + "mismatch send fatal alert (default warning alert)"}, + {"cert2", OPT_CERT2, '<', + "Certificate file to use for servername; default is" TEST_CERT2}, + {"key2", OPT_KEY2, '<', + "-Private Key file to use for servername if not in -cert2"}, + {"tlsextdebug", OPT_TLSEXTDEBUG, '-', + "Hex dump of all TLS extensions received"}, + {"HTTP", OPT_HTTP, '-', "Like -WWW but ./path includes HTTP headers"}, + {"id_prefix", OPT_ID_PREFIX, 's', + "Generate SSL/TLS session IDs prefixed by arg"}, + OPT_R_OPTIONS, + {"keymatexport", OPT_KEYMATEXPORT, 's', + "Export keying material using label"}, + {"keymatexportlen", OPT_KEYMATEXPORTLEN, 'p', + "Export len bytes of keying material (default 20)"}, + {"CRL", OPT_CRL, '<', "CRL file to use"}, + {"crl_download", OPT_CRL_DOWNLOAD, '-', + "Download CRL from distribution points"}, + {"cert_chain", OPT_CERT_CHAIN, '<', + "certificate chain file in PEM format"}, + {"dcert_chain", OPT_DCERT_CHAIN, '<', + "second certificate chain file in PEM format"}, + {"chainCApath", OPT_CHAINCAPATH, '/', + "use dir as certificate store path to build CA certificate chain"}, + {"verifyCApath", OPT_VERIFYCAPATH, '/', + "use dir as certificate store path to verify CA certificate"}, + {"no_cache", OPT_NO_CACHE, '-', "Disable session cache"}, + {"ext_cache", OPT_EXT_CACHE, '-', + "Disable internal cache, setup and use external cache"}, + {"CRLform", OPT_CRLFORM, 'F', "CRL format (PEM or DER) PEM is default"}, + {"verify_return_error", OPT_VERIFY_RET_ERROR, '-', + "Close connection on verification error"}, + {"verify_quiet", OPT_VERIFY_QUIET, '-', + "No verify output except verify errors"}, + {"build_chain", OPT_BUILD_CHAIN, '-', "Build certificate chain"}, + {"chainCAfile", OPT_CHAINCAFILE, '<', + "CA file for certificate chain (PEM format)"}, + {"verifyCAfile", OPT_VERIFYCAFILE, '<', + "CA file for certificate verification (PEM format)"}, + {"ign_eof", OPT_IGN_EOF, '-', "ignore input eof (default when -quiet)"}, + {"no_ign_eof", OPT_NO_IGN_EOF, '-', "Do not ignore input eof"}, +#ifndef OPENSSL_NO_OCSP + {"status", OPT_STATUS, '-', "Request certificate status from server"}, + {"status_verbose", OPT_STATUS_VERBOSE, '-', + "Print more output in certificate status callback"}, + {"status_timeout", OPT_STATUS_TIMEOUT, 'n', + "Status request responder timeout"}, + {"status_url", OPT_STATUS_URL, 's', "Status request fallback URL"}, + {"status_file", OPT_STATUS_FILE, '<', + "File containing DER encoded OCSP Response"}, +#endif +#ifndef OPENSSL_NO_SSL_TRACE + {"trace", OPT_TRACE, '-', "trace protocol messages"}, +#endif + {"security_debug", OPT_SECURITY_DEBUG, '-', + "Print output from SSL/TLS security framework"}, + {"security_debug_verbose", OPT_SECURITY_DEBUG_VERBOSE, '-', + "Print more output from SSL/TLS security framework"}, + {"brief", OPT_BRIEF, '-', + "Restrict output to brief summary of connection parameters"}, + {"rev", OPT_REV, '-', + "act as a simple test server which just sends back with the received text reversed"}, + {"async", OPT_ASYNC, '-', "Operate in asynchronous mode"}, + {"ssl_config", OPT_SSL_CONFIG, 's', + "Configure SSL_CTX using the configuration 'val'"}, + {"max_send_frag", OPT_MAX_SEND_FRAG, 'p', "Maximum Size of send frames "}, + {"split_send_frag", OPT_SPLIT_SEND_FRAG, 'p', + "Size used to split data for encrypt pipelines"}, + {"max_pipelines", OPT_MAX_PIPELINES, 'p', + "Maximum number of encrypt/decrypt pipelines to be used"}, + {"read_buf", OPT_READ_BUF, 'p', + "Default read buffer size to be used for connections"}, + OPT_S_OPTIONS, + OPT_V_OPTIONS, + OPT_X_OPTIONS, + {"nbio", OPT_NBIO, '-', "Use non-blocking IO"}, + {"psk_identity", OPT_PSK_IDENTITY, 's', "PSK identity to expect"}, +#ifndef OPENSSL_NO_PSK + {"psk_hint", OPT_PSK_HINT, 's', "PSK identity hint to use"}, +#endif + {"psk", OPT_PSK, 's', "PSK in hex (without 0x)"}, + {"psk_session", OPT_PSK_SESS, '<', "File to read PSK SSL session from"}, +#ifndef OPENSSL_NO_SRP + {"srpvfile", OPT_SRPVFILE, '<', "The verifier file for SRP"}, + {"srpuserseed", OPT_SRPUSERSEED, 's', + "A seed string for a default user salt"}, +#endif +#ifndef OPENSSL_NO_SSL3 + {"ssl3", OPT_SSL3, '-', "Just talk SSLv3"}, +#endif +#ifndef OPENSSL_NO_TLS1 + {"tls1", OPT_TLS1, '-', "Just talk TLSv1"}, +#endif +#ifndef OPENSSL_NO_TLS1_1 + {"tls1_1", OPT_TLS1_1, '-', "Just talk TLSv1.1"}, +#endif +#ifndef OPENSSL_NO_TLS1_2 + {"tls1_2", OPT_TLS1_2, '-', "just talk TLSv1.2"}, +#endif +#ifndef OPENSSL_NO_TLS1_3 + {"tls1_3", OPT_TLS1_3, '-', "just talk TLSv1.3"}, +#endif +#ifndef OPENSSL_NO_DTLS + {"dtls", OPT_DTLS, '-', "Use any DTLS version"}, + {"timeout", OPT_TIMEOUT, '-', "Enable timeouts"}, + {"mtu", OPT_MTU, 'p', "Set link layer MTU"}, + {"listen", OPT_LISTEN, '-', + "Listen for a DTLS ClientHello with a cookie and then connect"}, +#endif + {"stateless", OPT_STATELESS, '-', "Require TLSv1.3 cookies"}, +#ifndef OPENSSL_NO_DTLS1 + {"dtls1", OPT_DTLS1, '-', "Just talk DTLSv1"}, +#endif +#ifndef OPENSSL_NO_DTLS1_2 + {"dtls1_2", OPT_DTLS1_2, '-', "Just talk DTLSv1.2"}, +#endif +#ifndef OPENSSL_NO_SCTP + {"sctp", OPT_SCTP, '-', "Use SCTP"}, + {"sctp_label_bug", OPT_SCTP_LABEL_BUG, '-', "Enable SCTP label length bug"}, +#endif +#ifndef OPENSSL_NO_DH + {"no_dhe", OPT_NO_DHE, '-', "Disable ephemeral DH"}, +#endif +#ifndef OPENSSL_NO_NEXTPROTONEG + {"nextprotoneg", OPT_NEXTPROTONEG, 's', + "Set the advertised protocols for the NPN extension (comma-separated list)"}, +#endif +#ifndef OPENSSL_NO_SRTP + {"use_srtp", OPT_SRTP_PROFILES, 's', + "Offer SRTP key management with a colon-separated profile list"}, +#endif + {"alpn", OPT_ALPN, 's', + "Set the advertised protocols for the ALPN extension (comma-separated list)"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + {"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"}, + {"max_early_data", OPT_MAX_EARLY, 'n', + "The maximum number of bytes of early data as advertised in tickets"}, + {"recv_max_early_data", OPT_RECV_MAX_EARLY, 'n', + "The maximum number of bytes of early data (hard limit)"}, + {"early_data", OPT_EARLY_DATA, '-', "Attempt to read early data"}, + {"num_tickets", OPT_S_NUM_TICKETS, 'n', + "The number of TLSv1.3 session tickets that a server will automatically issue" }, + {"anti_replay", OPT_ANTI_REPLAY, '-', "Switch on anti-replay protection (default)"}, + {"no_anti_replay", OPT_NO_ANTI_REPLAY, '-', "Switch off anti-replay protection"}, + {NULL, OPT_EOF, 0, NULL} +}; + +#define IS_PROT_FLAG(o) \ + (o == OPT_SSL3 || o == OPT_TLS1 || o == OPT_TLS1_1 || o == OPT_TLS1_2 \ + || o == OPT_TLS1_3 || o == OPT_DTLS || o == OPT_DTLS1 || o == OPT_DTLS1_2) + +int s_server_main(int argc, char *argv[]) +{ + ENGINE *engine = NULL; + EVP_PKEY *s_key = NULL, *s_dkey = NULL; + SSL_CONF_CTX *cctx = NULL; + const SSL_METHOD *meth = TLS_server_method(); + SSL_EXCERT *exc = NULL; + STACK_OF(OPENSSL_STRING) *ssl_args = NULL; + STACK_OF(X509) *s_chain = NULL, *s_dchain = NULL; + STACK_OF(X509_CRL) *crls = NULL; + X509 *s_cert = NULL, *s_dcert = NULL; + X509_VERIFY_PARAM *vpm = NULL; + const char *CApath = NULL, *CAfile = NULL, *chCApath = NULL, *chCAfile = NULL; + char *dpassarg = NULL, *dpass = NULL; + char *passarg = NULL, *pass = NULL, *vfyCApath = NULL, *vfyCAfile = NULL; + char *crl_file = NULL, *prog; +#ifdef AF_UNIX + int unlink_unix_path = 0; +#endif + do_server_cb server_cb; + int vpmtouched = 0, build_chain = 0, no_cache = 0, ext_cache = 0; +#ifndef OPENSSL_NO_DH + char *dhfile = NULL; + int no_dhe = 0; +#endif + int nocert = 0, ret = 1; + int noCApath = 0, noCAfile = 0; + int s_cert_format = FORMAT_PEM, s_key_format = FORMAT_PEM; + int s_dcert_format = FORMAT_PEM, s_dkey_format = FORMAT_PEM; + int rev = 0, naccept = -1, sdebug = 0; + int socket_family = AF_UNSPEC, socket_type = SOCK_STREAM, protocol = 0; + int state = 0, crl_format = FORMAT_PEM, crl_download = 0; + char *host = NULL; + char *port = BUF_strdup(PORT); + unsigned char *context = NULL; + OPTION_CHOICE o; + EVP_PKEY *s_key2 = NULL; + X509 *s_cert2 = NULL; + tlsextctx tlsextcbp = { NULL, NULL, SSL_TLSEXT_ERR_ALERT_WARNING }; + const char *ssl_config = NULL; + int read_buf_len = 0; +#ifndef OPENSSL_NO_NEXTPROTONEG + const char *next_proto_neg_in = NULL; + tlsextnextprotoctx next_proto = { NULL, 0 }; +#endif + const char *alpn_in = NULL; + tlsextalpnctx alpn_ctx = { NULL, 0 }; +#ifndef OPENSSL_NO_PSK + /* by default do not send a PSK identity hint */ + char *psk_identity_hint = NULL; +#endif + char *p; +#ifndef OPENSSL_NO_SRP + char *srpuserseed = NULL; + char *srp_verifier_file = NULL; +#endif +#ifndef OPENSSL_NO_SRTP + char *srtp_profiles = NULL; +#endif + int min_version = 0, max_version = 0, prot_opt = 0, no_prot_opt = 0; + int s_server_verify = SSL_VERIFY_NONE; + int s_server_session_id_context = 1; /* anything will do */ + const char *s_cert_file = TEST_CERT, *s_key_file = NULL, *s_chain_file = NULL; + const char *s_cert_file2 = TEST_CERT2, *s_key_file2 = NULL; + char *s_dcert_file = NULL, *s_dkey_file = NULL, *s_dchain_file = NULL; +#ifndef OPENSSL_NO_OCSP + int s_tlsextstatus = 0; +#endif + int no_resume_ephemeral = 0; + unsigned int max_send_fragment = 0; + unsigned int split_send_fragment = 0, max_pipelines = 0; + const char *s_serverinfo_file = NULL; + const char *keylog_file = NULL; + int max_early_data = -1, recv_max_early_data = -1; + char *psksessf = NULL; +#ifndef OPENSSL_NO_SCTP + int sctp_label_bug = 0; +#endif + + /* Init of few remaining global variables */ + local_argc = argc; + local_argv = argv; + + ctx = ctx2 = NULL; + s_nbio = s_nbio_test = 0; + www = 0; + bio_s_out = NULL; + s_debug = 0; + s_msg = 0; + s_quiet = 0; + s_brief = 0; + async = 0; + + cctx = SSL_CONF_CTX_new(); + vpm = X509_VERIFY_PARAM_new(); + if (cctx == NULL || vpm == NULL) + goto end; + SSL_CONF_CTX_set_flags(cctx, + SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CMDLINE); + + prog = opt_init(argc, argv, s_server_options); + while ((o = opt_next()) != OPT_EOF) { + if (IS_PROT_FLAG(o) && ++prot_opt > 1) { + BIO_printf(bio_err, "Cannot supply multiple protocol flags\n"); + goto end; + } + if (IS_NO_PROT_FLAG(o)) + no_prot_opt++; + if (prot_opt == 1 && no_prot_opt) { + BIO_printf(bio_err, + "Cannot supply both a protocol flag and '-no_'\n"); + goto end; + } + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(s_server_options); + ret = 0; + goto end; + + case OPT_4: +#ifdef AF_UNIX + if (socket_family == AF_UNIX) { + OPENSSL_free(host); host = NULL; + OPENSSL_free(port); port = NULL; + } +#endif + socket_family = AF_INET; + break; + case OPT_6: + if (1) { +#ifdef AF_INET6 +#ifdef AF_UNIX + if (socket_family == AF_UNIX) { + OPENSSL_free(host); host = NULL; + OPENSSL_free(port); port = NULL; + } +#endif + socket_family = AF_INET6; + } else { +#endif + BIO_printf(bio_err, "%s: IPv6 domain sockets unsupported\n", prog); + goto end; + } + break; + case OPT_PORT: +#ifdef AF_UNIX + if (socket_family == AF_UNIX) { + socket_family = AF_UNSPEC; + } +#endif + OPENSSL_free(port); port = NULL; + OPENSSL_free(host); host = NULL; + if (BIO_parse_hostserv(opt_arg(), NULL, &port, BIO_PARSE_PRIO_SERV) < 1) { + BIO_printf(bio_err, + "%s: -port argument malformed or ambiguous\n", + port); + goto end; + } + break; + case OPT_ACCEPT: +#ifdef AF_UNIX + if (socket_family == AF_UNIX) { + socket_family = AF_UNSPEC; + } +#endif + OPENSSL_free(port); port = NULL; + OPENSSL_free(host); host = NULL; + if (BIO_parse_hostserv(opt_arg(), &host, &port, BIO_PARSE_PRIO_SERV) < 1) { + BIO_printf(bio_err, + "%s: -accept argument malformed or ambiguous\n", + port); + goto end; + } + break; +#ifdef AF_UNIX + case OPT_UNIX: + socket_family = AF_UNIX; + OPENSSL_free(host); host = BUF_strdup(opt_arg()); + OPENSSL_free(port); port = NULL; + break; + case OPT_UNLINK: + unlink_unix_path = 1; + break; +#endif + case OPT_NACCEPT: + naccept = atol(opt_arg()); + break; + case OPT_VERIFY: + s_server_verify = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE; + verify_args.depth = atoi(opt_arg()); + if (!s_quiet) + BIO_printf(bio_err, "verify depth is %d\n", verify_args.depth); + break; + case OPT_UPPER_V_VERIFY: + s_server_verify = + SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | + SSL_VERIFY_CLIENT_ONCE; + verify_args.depth = atoi(opt_arg()); + if (!s_quiet) + BIO_printf(bio_err, + "verify depth is %d, must return a certificate\n", + verify_args.depth); + break; + case OPT_CONTEXT: + context = (unsigned char *)opt_arg(); + break; + case OPT_CERT: + s_cert_file = opt_arg(); + break; + case OPT_NAMEOPT: + if (!set_nameopt(opt_arg())) + goto end; + break; + case OPT_CRL: + crl_file = opt_arg(); + break; + case OPT_CRL_DOWNLOAD: + crl_download = 1; + break; + case OPT_SERVERINFO: + s_serverinfo_file = opt_arg(); + break; + case OPT_CERTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &s_cert_format)) + goto opthelp; + break; + case OPT_KEY: + s_key_file = opt_arg(); + break; + case OPT_KEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &s_key_format)) + goto opthelp; + break; + case OPT_PASS: + passarg = opt_arg(); + break; + case OPT_CERT_CHAIN: + s_chain_file = opt_arg(); + break; + case OPT_DHPARAM: +#ifndef OPENSSL_NO_DH + dhfile = opt_arg(); +#endif + break; + case OPT_DCERTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &s_dcert_format)) + goto opthelp; + break; + case OPT_DCERT: + s_dcert_file = opt_arg(); + break; + case OPT_DKEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &s_dkey_format)) + goto opthelp; + break; + case OPT_DPASS: + dpassarg = opt_arg(); + break; + case OPT_DKEY: + s_dkey_file = opt_arg(); + break; + case OPT_DCERT_CHAIN: + s_dchain_file = opt_arg(); + break; + case OPT_NOCERT: + nocert = 1; + break; + case OPT_CAPATH: + CApath = opt_arg(); + break; + case OPT_NOCAPATH: + noCApath = 1; + break; + case OPT_CHAINCAPATH: + chCApath = opt_arg(); + break; + case OPT_VERIFYCAPATH: + vfyCApath = opt_arg(); + break; + case OPT_NO_CACHE: + no_cache = 1; + break; + case OPT_EXT_CACHE: + ext_cache = 1; + break; + case OPT_CRLFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &crl_format)) + goto opthelp; + break; + case OPT_S_CASES: + case OPT_S_NUM_TICKETS: + case OPT_ANTI_REPLAY: + case OPT_NO_ANTI_REPLAY: + if (ssl_args == NULL) + ssl_args = sk_OPENSSL_STRING_new_null(); + if (ssl_args == NULL + || !sk_OPENSSL_STRING_push(ssl_args, opt_flag()) + || !sk_OPENSSL_STRING_push(ssl_args, opt_arg())) { + BIO_printf(bio_err, "%s: Memory allocation failure\n", prog); + goto end; + } + break; + case OPT_V_CASES: + if (!opt_verify(o, vpm)) + goto end; + vpmtouched++; + break; + case OPT_X_CASES: + if (!args_excert(o, &exc)) + goto end; + break; + case OPT_VERIFY_RET_ERROR: + verify_args.return_error = 1; + break; + case OPT_VERIFY_QUIET: + verify_args.quiet = 1; + break; + case OPT_BUILD_CHAIN: + build_chain = 1; + break; + case OPT_CAFILE: + CAfile = opt_arg(); + break; + case OPT_NOCAFILE: + noCAfile = 1; + break; + case OPT_CHAINCAFILE: + chCAfile = opt_arg(); + break; + case OPT_VERIFYCAFILE: + vfyCAfile = opt_arg(); + break; + case OPT_NBIO: + s_nbio = 1; + break; + case OPT_NBIO_TEST: + s_nbio = s_nbio_test = 1; + break; + case OPT_IGN_EOF: + s_ign_eof = 1; + break; + case OPT_NO_IGN_EOF: + s_ign_eof = 0; + break; + case OPT_DEBUG: + s_debug = 1; + break; + case OPT_TLSEXTDEBUG: + s_tlsextdebug = 1; + break; + case OPT_STATUS: +#ifndef OPENSSL_NO_OCSP + s_tlsextstatus = 1; +#endif + break; + case OPT_STATUS_VERBOSE: +#ifndef OPENSSL_NO_OCSP + s_tlsextstatus = tlscstatp.verbose = 1; +#endif + break; + case OPT_STATUS_TIMEOUT: +#ifndef OPENSSL_NO_OCSP + s_tlsextstatus = 1; + tlscstatp.timeout = atoi(opt_arg()); +#endif + break; + case OPT_STATUS_URL: +#ifndef OPENSSL_NO_OCSP + s_tlsextstatus = 1; + if (!OCSP_parse_url(opt_arg(), + &tlscstatp.host, + &tlscstatp.port, + &tlscstatp.path, &tlscstatp.use_ssl)) { + BIO_printf(bio_err, "Error parsing URL\n"); + goto end; + } +#endif + break; + case OPT_STATUS_FILE: +#ifndef OPENSSL_NO_OCSP + s_tlsextstatus = 1; + tlscstatp.respin = opt_arg(); +#endif + break; + case OPT_MSG: + s_msg = 1; + break; + case OPT_MSGFILE: + bio_s_msg = BIO_new_file(opt_arg(), "w"); + break; + case OPT_TRACE: +#ifndef OPENSSL_NO_SSL_TRACE + s_msg = 2; +#endif + break; + case OPT_SECURITY_DEBUG: + sdebug = 1; + break; + case OPT_SECURITY_DEBUG_VERBOSE: + sdebug = 2; + break; + case OPT_STATE: + state = 1; + break; + case OPT_CRLF: + s_crlf = 1; + break; + case OPT_QUIET: + s_quiet = 1; + break; + case OPT_BRIEF: + s_quiet = s_brief = verify_args.quiet = 1; + break; + case OPT_NO_DHE: +#ifndef OPENSSL_NO_DH + no_dhe = 1; +#endif + break; + case OPT_NO_RESUME_EPHEMERAL: + no_resume_ephemeral = 1; + break; + case OPT_PSK_IDENTITY: + psk_identity = opt_arg(); + break; + case OPT_PSK_HINT: +#ifndef OPENSSL_NO_PSK + psk_identity_hint = opt_arg(); +#endif + break; + case OPT_PSK: + for (p = psk_key = opt_arg(); *p; p++) { + if (isxdigit(_UC(*p))) + continue; + BIO_printf(bio_err, "Not a hex number '%s'\n", psk_key); + goto end; + } + break; + case OPT_PSK_SESS: + psksessf = opt_arg(); + break; + case OPT_SRPVFILE: +#ifndef OPENSSL_NO_SRP + srp_verifier_file = opt_arg(); + if (min_version < TLS1_VERSION) + min_version = TLS1_VERSION; +#endif + break; + case OPT_SRPUSERSEED: +#ifndef OPENSSL_NO_SRP + srpuserseed = opt_arg(); + if (min_version < TLS1_VERSION) + min_version = TLS1_VERSION; +#endif + break; + case OPT_REV: + rev = 1; + break; + case OPT_WWW: + www = 1; + break; + case OPT_UPPER_WWW: + www = 2; + break; + case OPT_HTTP: + www = 3; + break; + case OPT_SSL_CONFIG: + ssl_config = opt_arg(); + break; + case OPT_SSL3: + min_version = SSL3_VERSION; + max_version = SSL3_VERSION; + break; + case OPT_TLS1_3: + min_version = TLS1_3_VERSION; + max_version = TLS1_3_VERSION; + break; + case OPT_TLS1_2: + min_version = TLS1_2_VERSION; + max_version = TLS1_2_VERSION; + break; + case OPT_TLS1_1: + min_version = TLS1_1_VERSION; + max_version = TLS1_1_VERSION; + break; + case OPT_TLS1: + min_version = TLS1_VERSION; + max_version = TLS1_VERSION; + break; + case OPT_DTLS: +#ifndef OPENSSL_NO_DTLS + meth = DTLS_server_method(); + socket_type = SOCK_DGRAM; +#endif + break; + case OPT_DTLS1: +#ifndef OPENSSL_NO_DTLS + meth = DTLS_server_method(); + min_version = DTLS1_VERSION; + max_version = DTLS1_VERSION; + socket_type = SOCK_DGRAM; +#endif + break; + case OPT_DTLS1_2: +#ifndef OPENSSL_NO_DTLS + meth = DTLS_server_method(); + min_version = DTLS1_2_VERSION; + max_version = DTLS1_2_VERSION; + socket_type = SOCK_DGRAM; +#endif + break; + case OPT_SCTP: +#ifndef OPENSSL_NO_SCTP + protocol = IPPROTO_SCTP; +#endif + break; + case OPT_SCTP_LABEL_BUG: +#ifndef OPENSSL_NO_SCTP + sctp_label_bug = 1; +#endif + break; + case OPT_TIMEOUT: +#ifndef OPENSSL_NO_DTLS + enable_timeouts = 1; +#endif + break; + case OPT_MTU: +#ifndef OPENSSL_NO_DTLS + socket_mtu = atol(opt_arg()); +#endif + break; + case OPT_LISTEN: +#ifndef OPENSSL_NO_DTLS + dtlslisten = 1; +#endif + break; + case OPT_STATELESS: + stateless = 1; + break; + case OPT_ID_PREFIX: + session_id_prefix = opt_arg(); + break; + case OPT_ENGINE: + engine = setup_engine(opt_arg(), 1); + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_SERVERNAME: + tlsextcbp.servername = opt_arg(); + break; + case OPT_SERVERNAME_FATAL: + tlsextcbp.extension_error = SSL_TLSEXT_ERR_ALERT_FATAL; + break; + case OPT_CERT2: + s_cert_file2 = opt_arg(); + break; + case OPT_KEY2: + s_key_file2 = opt_arg(); + break; + case OPT_NEXTPROTONEG: +# ifndef OPENSSL_NO_NEXTPROTONEG + next_proto_neg_in = opt_arg(); +#endif + break; + case OPT_ALPN: + alpn_in = opt_arg(); + break; + case OPT_SRTP_PROFILES: +#ifndef OPENSSL_NO_SRTP + srtp_profiles = opt_arg(); +#endif + break; + case OPT_KEYMATEXPORT: + keymatexportlabel = opt_arg(); + break; + case OPT_KEYMATEXPORTLEN: + keymatexportlen = atoi(opt_arg()); + break; + case OPT_ASYNC: + async = 1; + break; + case OPT_MAX_SEND_FRAG: + max_send_fragment = atoi(opt_arg()); + break; + case OPT_SPLIT_SEND_FRAG: + split_send_fragment = atoi(opt_arg()); + break; + case OPT_MAX_PIPELINES: + max_pipelines = atoi(opt_arg()); + break; + case OPT_READ_BUF: + read_buf_len = atoi(opt_arg()); + break; + case OPT_KEYLOG_FILE: + keylog_file = opt_arg(); + break; + case OPT_MAX_EARLY: + max_early_data = atoi(opt_arg()); + if (max_early_data < 0) { + BIO_printf(bio_err, "Invalid value for max_early_data\n"); + goto end; + } + break; + case OPT_RECV_MAX_EARLY: + recv_max_early_data = atoi(opt_arg()); + if (recv_max_early_data < 0) { + BIO_printf(bio_err, "Invalid value for recv_max_early_data\n"); + goto end; + } + break; + case OPT_EARLY_DATA: + early_data = 1; + if (max_early_data == -1) + max_early_data = SSL3_RT_MAX_PLAIN_LENGTH; + break; + } + } + argc = opt_num_rest(); + argv = opt_rest(); + +#ifndef OPENSSL_NO_NEXTPROTONEG + if (min_version == TLS1_3_VERSION && next_proto_neg_in != NULL) { + BIO_printf(bio_err, "Cannot supply -nextprotoneg with TLSv1.3\n"); + goto opthelp; + } +#endif +#ifndef OPENSSL_NO_DTLS + if (www && socket_type == SOCK_DGRAM) { + BIO_printf(bio_err, "Can't use -HTTP, -www or -WWW with DTLS\n"); + goto end; + } + + if (dtlslisten && socket_type != SOCK_DGRAM) { + BIO_printf(bio_err, "Can only use -listen with DTLS\n"); + goto end; + } +#endif + + if (stateless && socket_type != SOCK_STREAM) { + BIO_printf(bio_err, "Can only use --stateless with TLS\n"); + goto end; + } + +#ifdef AF_UNIX + if (socket_family == AF_UNIX && socket_type != SOCK_STREAM) { + BIO_printf(bio_err, + "Can't use unix sockets and datagrams together\n"); + goto end; + } +#endif + if (early_data && (www > 0 || rev)) { + BIO_printf(bio_err, + "Can't use -early_data in combination with -www, -WWW, -HTTP, or -rev\n"); + goto end; + } + +#ifndef OPENSSL_NO_SCTP + if (protocol == IPPROTO_SCTP) { + if (socket_type != SOCK_DGRAM) { + BIO_printf(bio_err, "Can't use -sctp without DTLS\n"); + goto end; + } + /* SCTP is unusual. It uses DTLS over a SOCK_STREAM protocol */ + socket_type = SOCK_STREAM; + } +#endif + + if (!app_passwd(passarg, dpassarg, &pass, &dpass)) { + BIO_printf(bio_err, "Error getting password\n"); + goto end; + } + + if (s_key_file == NULL) + s_key_file = s_cert_file; + + if (s_key_file2 == NULL) + s_key_file2 = s_cert_file2; + + if (!load_excert(&exc)) + goto end; + + if (nocert == 0) { + s_key = load_key(s_key_file, s_key_format, 0, pass, engine, + "server certificate private key file"); + if (s_key == NULL) { + ERR_print_errors(bio_err); + goto end; + } + + s_cert = load_cert(s_cert_file, s_cert_format, + "server certificate file"); + + if (s_cert == NULL) { + ERR_print_errors(bio_err); + goto end; + } + if (s_chain_file != NULL) { + if (!load_certs(s_chain_file, &s_chain, FORMAT_PEM, NULL, + "server certificate chain")) + goto end; + } + + if (tlsextcbp.servername != NULL) { + s_key2 = load_key(s_key_file2, s_key_format, 0, pass, engine, + "second server certificate private key file"); + if (s_key2 == NULL) { + ERR_print_errors(bio_err); + goto end; + } + + s_cert2 = load_cert(s_cert_file2, s_cert_format, + "second server certificate file"); + + if (s_cert2 == NULL) { + ERR_print_errors(bio_err); + goto end; + } + } + } +#if !defined(OPENSSL_NO_NEXTPROTONEG) + if (next_proto_neg_in) { + next_proto.data = next_protos_parse(&next_proto.len, next_proto_neg_in); + if (next_proto.data == NULL) + goto end; + } +#endif + alpn_ctx.data = NULL; + if (alpn_in) { + alpn_ctx.data = next_protos_parse(&alpn_ctx.len, alpn_in); + if (alpn_ctx.data == NULL) + goto end; + } + + if (crl_file != NULL) { + X509_CRL *crl; + crl = load_crl(crl_file, crl_format); + if (crl == NULL) { + BIO_puts(bio_err, "Error loading CRL\n"); + ERR_print_errors(bio_err); + goto end; + } + crls = sk_X509_CRL_new_null(); + if (crls == NULL || !sk_X509_CRL_push(crls, crl)) { + BIO_puts(bio_err, "Error adding CRL\n"); + ERR_print_errors(bio_err); + X509_CRL_free(crl); + goto end; + } + } + + if (s_dcert_file != NULL) { + + if (s_dkey_file == NULL) + s_dkey_file = s_dcert_file; + + s_dkey = load_key(s_dkey_file, s_dkey_format, + 0, dpass, engine, "second certificate private key file"); + if (s_dkey == NULL) { + ERR_print_errors(bio_err); + goto end; + } + + s_dcert = load_cert(s_dcert_file, s_dcert_format, + "second server certificate file"); + + if (s_dcert == NULL) { + ERR_print_errors(bio_err); + goto end; + } + if (s_dchain_file != NULL) { + if (!load_certs(s_dchain_file, &s_dchain, FORMAT_PEM, NULL, + "second server certificate chain")) + goto end; + } + + } + + if (bio_s_out == NULL) { + if (s_quiet && !s_debug) { + bio_s_out = BIO_new(BIO_s_null()); + if (s_msg && bio_s_msg == NULL) + bio_s_msg = dup_bio_out(FORMAT_TEXT); + } else { + if (bio_s_out == NULL) + bio_s_out = dup_bio_out(FORMAT_TEXT); + } + } +#if !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_EC) + if (nocert) +#endif + { + s_cert_file = NULL; + s_key_file = NULL; + s_dcert_file = NULL; + s_dkey_file = NULL; + s_cert_file2 = NULL; + s_key_file2 = NULL; + } + + ctx = SSL_CTX_new(meth); + if (ctx == NULL) { + ERR_print_errors(bio_err); + goto end; + } + + SSL_CTX_clear_mode(ctx, SSL_MODE_AUTO_RETRY); + + if (sdebug) + ssl_ctx_security_debug(ctx, sdebug); + + if (!config_ctx(cctx, ssl_args, ctx)) + goto end; + + if (ssl_config) { + if (SSL_CTX_config(ctx, ssl_config) == 0) { + BIO_printf(bio_err, "Error using configuration \"%s\"\n", + ssl_config); + ERR_print_errors(bio_err); + goto end; + } + } + +#ifndef OPENSSL_NO_SCTP + if (protocol == IPPROTO_SCTP && sctp_label_bug == 1) + SSL_CTX_set_mode(ctx, SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG); +#endif + + if (min_version != 0 + && SSL_CTX_set_min_proto_version(ctx, min_version) == 0) + goto end; + if (max_version != 0 + && SSL_CTX_set_max_proto_version(ctx, max_version) == 0) + goto end; + + if (session_id_prefix) { + if (strlen(session_id_prefix) >= 32) + BIO_printf(bio_err, + "warning: id_prefix is too long, only one new session will be possible\n"); + if (!SSL_CTX_set_generate_session_id(ctx, generate_session_id)) { + BIO_printf(bio_err, "error setting 'id_prefix'\n"); + ERR_print_errors(bio_err); + goto end; + } + BIO_printf(bio_err, "id_prefix '%s' set.\n", session_id_prefix); + } + SSL_CTX_set_quiet_shutdown(ctx, 1); + if (exc != NULL) + ssl_ctx_set_excert(ctx, exc); + + if (state) + SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback); + if (no_cache) + SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); + else if (ext_cache) + init_session_cache_ctx(ctx); + else + SSL_CTX_sess_set_cache_size(ctx, 128); + + if (async) { + SSL_CTX_set_mode(ctx, SSL_MODE_ASYNC); + } + + if (max_send_fragment > 0 + && !SSL_CTX_set_max_send_fragment(ctx, max_send_fragment)) { + BIO_printf(bio_err, "%s: Max send fragment size %u is out of permitted range\n", + prog, max_send_fragment); + goto end; + } + + if (split_send_fragment > 0 + && !SSL_CTX_set_split_send_fragment(ctx, split_send_fragment)) { + BIO_printf(bio_err, "%s: Split send fragment size %u is out of permitted range\n", + prog, split_send_fragment); + goto end; + } + if (max_pipelines > 0 + && !SSL_CTX_set_max_pipelines(ctx, max_pipelines)) { + BIO_printf(bio_err, "%s: Max pipelines %u is out of permitted range\n", + prog, max_pipelines); + goto end; + } + + if (read_buf_len > 0) { + SSL_CTX_set_default_read_buffer_len(ctx, read_buf_len); + } +#ifndef OPENSSL_NO_SRTP + if (srtp_profiles != NULL) { + /* Returns 0 on success! */ + if (SSL_CTX_set_tlsext_use_srtp(ctx, srtp_profiles) != 0) { + BIO_printf(bio_err, "Error setting SRTP profile\n"); + ERR_print_errors(bio_err); + goto end; + } + } +#endif + + if (!ctx_set_verify_locations(ctx, CAfile, CApath, noCAfile, noCApath)) { + ERR_print_errors(bio_err); + goto end; + } + if (vpmtouched && !SSL_CTX_set1_param(ctx, vpm)) { + BIO_printf(bio_err, "Error setting verify params\n"); + ERR_print_errors(bio_err); + goto end; + } + + ssl_ctx_add_crls(ctx, crls, 0); + + if (!ssl_load_stores(ctx, vfyCApath, vfyCAfile, chCApath, chCAfile, + crls, crl_download)) { + BIO_printf(bio_err, "Error loading store locations\n"); + ERR_print_errors(bio_err); + goto end; + } + + if (s_cert2) { + ctx2 = SSL_CTX_new(meth); + if (ctx2 == NULL) { + ERR_print_errors(bio_err); + goto end; + } + } + + if (ctx2 != NULL) { + BIO_printf(bio_s_out, "Setting secondary ctx parameters\n"); + + if (sdebug) + ssl_ctx_security_debug(ctx, sdebug); + + if (session_id_prefix) { + if (strlen(session_id_prefix) >= 32) + BIO_printf(bio_err, + "warning: id_prefix is too long, only one new session will be possible\n"); + if (!SSL_CTX_set_generate_session_id(ctx2, generate_session_id)) { + BIO_printf(bio_err, "error setting 'id_prefix'\n"); + ERR_print_errors(bio_err); + goto end; + } + BIO_printf(bio_err, "id_prefix '%s' set.\n", session_id_prefix); + } + SSL_CTX_set_quiet_shutdown(ctx2, 1); + if (exc != NULL) + ssl_ctx_set_excert(ctx2, exc); + + if (state) + SSL_CTX_set_info_callback(ctx2, apps_ssl_info_callback); + + if (no_cache) + SSL_CTX_set_session_cache_mode(ctx2, SSL_SESS_CACHE_OFF); + else if (ext_cache) + init_session_cache_ctx(ctx2); + else + SSL_CTX_sess_set_cache_size(ctx2, 128); + + if (async) + SSL_CTX_set_mode(ctx2, SSL_MODE_ASYNC); + + if (!ctx_set_verify_locations(ctx2, CAfile, CApath, noCAfile, + noCApath)) { + ERR_print_errors(bio_err); + goto end; + } + if (vpmtouched && !SSL_CTX_set1_param(ctx2, vpm)) { + BIO_printf(bio_err, "Error setting verify params\n"); + ERR_print_errors(bio_err); + goto end; + } + + ssl_ctx_add_crls(ctx2, crls, 0); + if (!config_ctx(cctx, ssl_args, ctx2)) + goto end; + } +#ifndef OPENSSL_NO_NEXTPROTONEG + if (next_proto.data) + SSL_CTX_set_next_protos_advertised_cb(ctx, next_proto_cb, + &next_proto); +#endif + if (alpn_ctx.data) + SSL_CTX_set_alpn_select_cb(ctx, alpn_cb, &alpn_ctx); + +#ifndef OPENSSL_NO_DH + if (!no_dhe) { + DH *dh = NULL; + + if (dhfile != NULL) + dh = load_dh_param(dhfile); + else if (s_cert_file != NULL) + dh = load_dh_param(s_cert_file); + + if (dh != NULL) { + BIO_printf(bio_s_out, "Setting temp DH parameters\n"); + } else { + BIO_printf(bio_s_out, "Using default temp DH parameters\n"); + } + (void)BIO_flush(bio_s_out); + + if (dh == NULL) { + SSL_CTX_set_dh_auto(ctx, 1); + } else if (!SSL_CTX_set_tmp_dh(ctx, dh)) { + BIO_puts(bio_err, "Error setting temp DH parameters\n"); + ERR_print_errors(bio_err); + DH_free(dh); + goto end; + } + + if (ctx2 != NULL) { + if (!dhfile) { + DH *dh2 = load_dh_param(s_cert_file2); + if (dh2 != NULL) { + BIO_printf(bio_s_out, "Setting temp DH parameters\n"); + (void)BIO_flush(bio_s_out); + + DH_free(dh); + dh = dh2; + } + } + if (dh == NULL) { + SSL_CTX_set_dh_auto(ctx2, 1); + } else if (!SSL_CTX_set_tmp_dh(ctx2, dh)) { + BIO_puts(bio_err, "Error setting temp DH parameters\n"); + ERR_print_errors(bio_err); + DH_free(dh); + goto end; + } + } + DH_free(dh); + } +#endif + + if (!set_cert_key_stuff(ctx, s_cert, s_key, s_chain, build_chain)) + goto end; + + if (s_serverinfo_file != NULL + && !SSL_CTX_use_serverinfo_file(ctx, s_serverinfo_file)) { + ERR_print_errors(bio_err); + goto end; + } + + if (ctx2 != NULL + && !set_cert_key_stuff(ctx2, s_cert2, s_key2, NULL, build_chain)) + goto end; + + if (s_dcert != NULL) { + if (!set_cert_key_stuff(ctx, s_dcert, s_dkey, s_dchain, build_chain)) + goto end; + } + + if (no_resume_ephemeral) { + SSL_CTX_set_not_resumable_session_callback(ctx, + not_resumable_sess_cb); + + if (ctx2 != NULL) + SSL_CTX_set_not_resumable_session_callback(ctx2, + not_resumable_sess_cb); + } +#ifndef OPENSSL_NO_PSK + if (psk_key != NULL) { + if (s_debug) + BIO_printf(bio_s_out, "PSK key given, setting server callback\n"); + SSL_CTX_set_psk_server_callback(ctx, psk_server_cb); + } + + if (!SSL_CTX_use_psk_identity_hint(ctx, psk_identity_hint)) { + BIO_printf(bio_err, "error setting PSK identity hint to context\n"); + ERR_print_errors(bio_err); + goto end; + } +#endif + if (psksessf != NULL) { + BIO *stmp = BIO_new_file(psksessf, "r"); + + if (stmp == NULL) { + BIO_printf(bio_err, "Can't open PSK session file %s\n", psksessf); + ERR_print_errors(bio_err); + goto end; + } + psksess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL); + BIO_free(stmp); + if (psksess == NULL) { + BIO_printf(bio_err, "Can't read PSK session file %s\n", psksessf); + ERR_print_errors(bio_err); + goto end; + } + + } + + if (psk_key != NULL || psksess != NULL) + SSL_CTX_set_psk_find_session_callback(ctx, psk_find_session_cb); + + SSL_CTX_set_verify(ctx, s_server_verify, verify_callback); + if (!SSL_CTX_set_session_id_context(ctx, + (void *)&s_server_session_id_context, + sizeof(s_server_session_id_context))) { + BIO_printf(bio_err, "error setting session id context\n"); + ERR_print_errors(bio_err); + goto end; + } + + /* Set DTLS cookie generation and verification callbacks */ + SSL_CTX_set_cookie_generate_cb(ctx, generate_cookie_callback); + SSL_CTX_set_cookie_verify_cb(ctx, verify_cookie_callback); + + /* Set TLS1.3 cookie generation and verification callbacks */ + SSL_CTX_set_stateless_cookie_generate_cb(ctx, generate_stateless_cookie_callback); + SSL_CTX_set_stateless_cookie_verify_cb(ctx, verify_stateless_cookie_callback); + + if (ctx2 != NULL) { + SSL_CTX_set_verify(ctx2, s_server_verify, verify_callback); + if (!SSL_CTX_set_session_id_context(ctx2, + (void *)&s_server_session_id_context, + sizeof(s_server_session_id_context))) { + BIO_printf(bio_err, "error setting session id context\n"); + ERR_print_errors(bio_err); + goto end; + } + tlsextcbp.biodebug = bio_s_out; + SSL_CTX_set_tlsext_servername_callback(ctx2, ssl_servername_cb); + SSL_CTX_set_tlsext_servername_arg(ctx2, &tlsextcbp); + SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb); + SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp); + } + +#ifndef OPENSSL_NO_SRP + if (srp_verifier_file != NULL) { + srp_callback_parm.vb = SRP_VBASE_new(srpuserseed); + srp_callback_parm.user = NULL; + srp_callback_parm.login = NULL; + if ((ret = + SRP_VBASE_init(srp_callback_parm.vb, + srp_verifier_file)) != SRP_NO_ERROR) { + BIO_printf(bio_err, + "Cannot initialize SRP verifier file \"%s\":ret=%d\n", + srp_verifier_file, ret); + goto end; + } + SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, verify_callback); + SSL_CTX_set_srp_cb_arg(ctx, &srp_callback_parm); + SSL_CTX_set_srp_username_callback(ctx, ssl_srp_server_param_cb); + } else +#endif + if (CAfile != NULL) { + SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(CAfile)); + + if (ctx2) + SSL_CTX_set_client_CA_list(ctx2, SSL_load_client_CA_file(CAfile)); + } +#ifndef OPENSSL_NO_OCSP + if (s_tlsextstatus) { + SSL_CTX_set_tlsext_status_cb(ctx, cert_status_cb); + SSL_CTX_set_tlsext_status_arg(ctx, &tlscstatp); + if (ctx2) { + SSL_CTX_set_tlsext_status_cb(ctx2, cert_status_cb); + SSL_CTX_set_tlsext_status_arg(ctx2, &tlscstatp); + } + } +#endif + if (set_keylog_file(ctx, keylog_file)) + goto end; + + if (max_early_data >= 0) + SSL_CTX_set_max_early_data(ctx, max_early_data); + if (recv_max_early_data >= 0) + SSL_CTX_set_recv_max_early_data(ctx, recv_max_early_data); + + if (rev) + server_cb = rev_body; + else if (www) + server_cb = www_body; + else + server_cb = sv_body; +#ifdef AF_UNIX + if (socket_family == AF_UNIX + && unlink_unix_path) + unlink(host); +#endif + do_server(&accept_socket, host, port, socket_family, socket_type, protocol, + server_cb, context, naccept, bio_s_out); + print_stats(bio_s_out, ctx); + ret = 0; + end: + SSL_CTX_free(ctx); + SSL_SESSION_free(psksess); + set_keylog_file(NULL, NULL); + X509_free(s_cert); + sk_X509_CRL_pop_free(crls, X509_CRL_free); + X509_free(s_dcert); + EVP_PKEY_free(s_key); + EVP_PKEY_free(s_dkey); + sk_X509_pop_free(s_chain, X509_free); + sk_X509_pop_free(s_dchain, X509_free); + OPENSSL_free(pass); + OPENSSL_free(dpass); + OPENSSL_free(host); + OPENSSL_free(port); + X509_VERIFY_PARAM_free(vpm); + free_sessions(); + OPENSSL_free(tlscstatp.host); + OPENSSL_free(tlscstatp.port); + OPENSSL_free(tlscstatp.path); + SSL_CTX_free(ctx2); + X509_free(s_cert2); + EVP_PKEY_free(s_key2); +#ifndef OPENSSL_NO_NEXTPROTONEG + OPENSSL_free(next_proto.data); +#endif + OPENSSL_free(alpn_ctx.data); + ssl_excert_free(exc); + sk_OPENSSL_STRING_free(ssl_args); + SSL_CONF_CTX_free(cctx); + release_engine(engine); + BIO_free(bio_s_out); + bio_s_out = NULL; + BIO_free(bio_s_msg); + bio_s_msg = NULL; +#ifdef CHARSET_EBCDIC + BIO_meth_free(methods_ebcdic); +#endif + return ret; +} + +static void print_stats(BIO *bio, SSL_CTX *ssl_ctx) +{ + BIO_printf(bio, "%4ld items in the session cache\n", + SSL_CTX_sess_number(ssl_ctx)); + BIO_printf(bio, "%4ld client connects (SSL_connect())\n", + SSL_CTX_sess_connect(ssl_ctx)); + BIO_printf(bio, "%4ld client renegotiates (SSL_connect())\n", + SSL_CTX_sess_connect_renegotiate(ssl_ctx)); + BIO_printf(bio, "%4ld client connects that finished\n", + SSL_CTX_sess_connect_good(ssl_ctx)); + BIO_printf(bio, "%4ld server accepts (SSL_accept())\n", + SSL_CTX_sess_accept(ssl_ctx)); + BIO_printf(bio, "%4ld server renegotiates (SSL_accept())\n", + SSL_CTX_sess_accept_renegotiate(ssl_ctx)); + BIO_printf(bio, "%4ld server accepts that finished\n", + SSL_CTX_sess_accept_good(ssl_ctx)); + BIO_printf(bio, "%4ld session cache hits\n", SSL_CTX_sess_hits(ssl_ctx)); + BIO_printf(bio, "%4ld session cache misses\n", + SSL_CTX_sess_misses(ssl_ctx)); + BIO_printf(bio, "%4ld session cache timeouts\n", + SSL_CTX_sess_timeouts(ssl_ctx)); + BIO_printf(bio, "%4ld callback cache hits\n", + SSL_CTX_sess_cb_hits(ssl_ctx)); + BIO_printf(bio, "%4ld cache full overflows (%ld allowed)\n", + SSL_CTX_sess_cache_full(ssl_ctx), + SSL_CTX_sess_get_cache_size(ssl_ctx)); +} + +static int sv_body(int s, int stype, int prot, unsigned char *context) +{ + char *buf = NULL; + fd_set readfds; + int ret = 1, width; + int k, i; + unsigned long l; + SSL *con = NULL; + BIO *sbio; + struct timeval timeout; +#if !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)) + struct timeval *timeoutp; +#endif +#ifndef OPENSSL_NO_DTLS +# ifndef OPENSSL_NO_SCTP + int isdtls = (stype == SOCK_DGRAM || prot == IPPROTO_SCTP); +# else + int isdtls = (stype == SOCK_DGRAM); +# endif +#endif + + buf = app_malloc(bufsize, "server buffer"); + if (s_nbio) { + if (!BIO_socket_nbio(s, 1)) + ERR_print_errors(bio_err); + else if (!s_quiet) + BIO_printf(bio_err, "Turned on non blocking io\n"); + } + + con = SSL_new(ctx); + if (con == NULL) { + ret = -1; + goto err; + } + + if (s_tlsextdebug) { + SSL_set_tlsext_debug_callback(con, tlsext_cb); + SSL_set_tlsext_debug_arg(con, bio_s_out); + } + + if (context != NULL + && !SSL_set_session_id_context(con, context, + strlen((char *)context))) { + BIO_printf(bio_err, "Error setting session id context\n"); + ret = -1; + goto err; + } + + if (!SSL_clear(con)) { + BIO_printf(bio_err, "Error clearing SSL connection\n"); + ret = -1; + goto err; + } +#ifndef OPENSSL_NO_DTLS + if (isdtls) { +# ifndef OPENSSL_NO_SCTP + if (prot == IPPROTO_SCTP) + sbio = BIO_new_dgram_sctp(s, BIO_NOCLOSE); + else +# endif + sbio = BIO_new_dgram(s, BIO_NOCLOSE); + + if (enable_timeouts) { + timeout.tv_sec = 0; + timeout.tv_usec = DGRAM_RCV_TIMEOUT; + BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); + + timeout.tv_sec = 0; + timeout.tv_usec = DGRAM_SND_TIMEOUT; + BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout); + } + + if (socket_mtu) { + if (socket_mtu < DTLS_get_link_min_mtu(con)) { + BIO_printf(bio_err, "MTU too small. Must be at least %ld\n", + DTLS_get_link_min_mtu(con)); + ret = -1; + BIO_free(sbio); + goto err; + } + SSL_set_options(con, SSL_OP_NO_QUERY_MTU); + if (!DTLS_set_link_mtu(con, socket_mtu)) { + BIO_printf(bio_err, "Failed to set MTU\n"); + ret = -1; + BIO_free(sbio); + goto err; + } + } else + /* want to do MTU discovery */ + BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL); + +# ifndef OPENSSL_NO_SCTP + if (prot != IPPROTO_SCTP) +# endif + /* Turn on cookie exchange. Not necessary for SCTP */ + SSL_set_options(con, SSL_OP_COOKIE_EXCHANGE); + } else +#endif + sbio = BIO_new_socket(s, BIO_NOCLOSE); + + if (sbio == NULL) { + BIO_printf(bio_err, "Unable to create BIO\n"); + ERR_print_errors(bio_err); + goto err; + } + + if (s_nbio_test) { + BIO *test; + + test = BIO_new(BIO_f_nbio_test()); + sbio = BIO_push(test, sbio); + } + + SSL_set_bio(con, sbio, sbio); + SSL_set_accept_state(con); + /* SSL_set_fd(con,s); */ + + if (s_debug) { + BIO_set_callback(SSL_get_rbio(con), bio_dump_callback); + BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out); + } + if (s_msg) { +#ifndef OPENSSL_NO_SSL_TRACE + if (s_msg == 2) + SSL_set_msg_callback(con, SSL_trace); + else +#endif + SSL_set_msg_callback(con, msg_cb); + SSL_set_msg_callback_arg(con, bio_s_msg ? bio_s_msg : bio_s_out); + } + + if (s_tlsextdebug) { + SSL_set_tlsext_debug_callback(con, tlsext_cb); + SSL_set_tlsext_debug_arg(con, bio_s_out); + } + + if (early_data) { + int write_header = 1, edret = SSL_READ_EARLY_DATA_ERROR; + size_t readbytes; + + while (edret != SSL_READ_EARLY_DATA_FINISH) { + for (;;) { + edret = SSL_read_early_data(con, buf, bufsize, &readbytes); + if (edret != SSL_READ_EARLY_DATA_ERROR) + break; + + switch (SSL_get_error(con, 0)) { + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_ASYNC: + case SSL_ERROR_WANT_READ: + /* Just keep trying - busy waiting */ + continue; + default: + BIO_printf(bio_err, "Error reading early data\n"); + ERR_print_errors(bio_err); + goto err; + } + } + if (readbytes > 0) { + if (write_header) { + BIO_printf(bio_s_out, "Early data received:\n"); + write_header = 0; + } + raw_write_stdout(buf, (unsigned int)readbytes); + (void)BIO_flush(bio_s_out); + } + } + if (write_header) { + if (SSL_get_early_data_status(con) == SSL_EARLY_DATA_NOT_SENT) + BIO_printf(bio_s_out, "No early data received\n"); + else + BIO_printf(bio_s_out, "Early data was rejected\n"); + } else { + BIO_printf(bio_s_out, "\nEnd of early data\n"); + } + if (SSL_is_init_finished(con)) + print_connection_info(con); + } + + if (fileno_stdin() > s) + width = fileno_stdin() + 1; + else + width = s + 1; + for (;;) { + int read_from_terminal; + int read_from_sslcon; + + read_from_terminal = 0; + read_from_sslcon = SSL_has_pending(con) + || (async && SSL_waiting_for_async(con)); + + if (!read_from_sslcon) { + FD_ZERO(&readfds); +#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) + openssl_fdset(fileno_stdin(), &readfds); +#endif + openssl_fdset(s, &readfds); + /* + * Note: under VMS with SOCKETSHR the second parameter is + * currently of type (int *) whereas under other systems it is + * (void *) if you don't have a cast it will choke the compiler: + * if you do have a cast then you can either go for (int *) or + * (void *). + */ +#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) + /* + * Under DOS (non-djgpp) and Windows we can't select on stdin: + * only on sockets. As a workaround we timeout the select every + * second and check for any keypress. In a proper Windows + * application we wouldn't do this because it is inefficient. + */ + timeout.tv_sec = 1; + timeout.tv_usec = 0; + i = select(width, (void *)&readfds, NULL, NULL, &timeout); + if (has_stdin_waiting()) + read_from_terminal = 1; + if ((i < 0) || (!i && !read_from_terminal)) + continue; +#else + if (SSL_is_dtls(con) && DTLSv1_get_timeout(con, &timeout)) + timeoutp = &timeout; + else + timeoutp = NULL; + + i = select(width, (void *)&readfds, NULL, NULL, timeoutp); + + if ((SSL_is_dtls(con)) && DTLSv1_handle_timeout(con) > 0) + BIO_printf(bio_err, "TIMEOUT occurred\n"); + + if (i <= 0) + continue; + if (FD_ISSET(fileno_stdin(), &readfds)) + read_from_terminal = 1; +#endif + if (FD_ISSET(s, &readfds)) + read_from_sslcon = 1; + } + if (read_from_terminal) { + if (s_crlf) { + int j, lf_num; + + i = raw_read_stdin(buf, bufsize / 2); + lf_num = 0; + /* both loops are skipped when i <= 0 */ + for (j = 0; j < i; j++) + if (buf[j] == '\n') + lf_num++; + for (j = i - 1; j >= 0; j--) { + buf[j + lf_num] = buf[j]; + if (buf[j] == '\n') { + lf_num--; + i++; + buf[j + lf_num] = '\r'; + } + } + assert(lf_num == 0); + } else { + i = raw_read_stdin(buf, bufsize); + } + + if (!s_quiet && !s_brief) { + if ((i <= 0) || (buf[0] == 'Q')) { + BIO_printf(bio_s_out, "DONE\n"); + (void)BIO_flush(bio_s_out); + BIO_closesocket(s); + close_accept_socket(); + ret = -11; + goto err; + } + if ((i <= 0) || (buf[0] == 'q')) { + BIO_printf(bio_s_out, "DONE\n"); + (void)BIO_flush(bio_s_out); + if (SSL_version(con) != DTLS1_VERSION) + BIO_closesocket(s); + /* + * close_accept_socket(); ret= -11; + */ + goto err; + } +#ifndef OPENSSL_NO_HEARTBEATS + if ((buf[0] == 'B') && ((buf[1] == '\n') || (buf[1] == '\r'))) { + BIO_printf(bio_err, "HEARTBEATING\n"); + SSL_heartbeat(con); + i = 0; + continue; + } +#endif + if ((buf[0] == 'r') && ((buf[1] == '\n') || (buf[1] == '\r'))) { + SSL_renegotiate(con); + i = SSL_do_handshake(con); + printf("SSL_do_handshake -> %d\n", i); + i = 0; /* 13; */ + continue; + } + if ((buf[0] == 'R') && ((buf[1] == '\n') || (buf[1] == '\r'))) { + SSL_set_verify(con, + SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, + NULL); + SSL_renegotiate(con); + i = SSL_do_handshake(con); + printf("SSL_do_handshake -> %d\n", i); + i = 0; /* 13; */ + continue; + } + if ((buf[0] == 'K' || buf[0] == 'k') + && ((buf[1] == '\n') || (buf[1] == '\r'))) { + SSL_key_update(con, buf[0] == 'K' ? + SSL_KEY_UPDATE_REQUESTED + : SSL_KEY_UPDATE_NOT_REQUESTED); + i = SSL_do_handshake(con); + printf("SSL_do_handshake -> %d\n", i); + i = 0; + continue; + } + if (buf[0] == 'c' && ((buf[1] == '\n') || (buf[1] == '\r'))) { + SSL_set_verify(con, SSL_VERIFY_PEER, NULL); + i = SSL_verify_client_post_handshake(con); + if (i == 0) { + printf("Failed to initiate request\n"); + ERR_print_errors(bio_err); + } else { + i = SSL_do_handshake(con); + printf("SSL_do_handshake -> %d\n", i); + i = 0; + } + continue; + } + if (buf[0] == 'P') { + static const char *str = "Lets print some clear text\n"; + BIO_write(SSL_get_wbio(con), str, strlen(str)); + } + if (buf[0] == 'S') { + print_stats(bio_s_out, SSL_get_SSL_CTX(con)); + } + } +#ifdef CHARSET_EBCDIC + ebcdic2ascii(buf, buf, i); +#endif + l = k = 0; + for (;;) { + /* should do a select for the write */ +#ifdef RENEG + static count = 0; + if (++count == 100) { + count = 0; + SSL_renegotiate(con); + } +#endif + k = SSL_write(con, &(buf[l]), (unsigned int)i); +#ifndef OPENSSL_NO_SRP + while (SSL_get_error(con, k) == SSL_ERROR_WANT_X509_LOOKUP) { + BIO_printf(bio_s_out, "LOOKUP renego during write\n"); + SRP_user_pwd_free(srp_callback_parm.user); + srp_callback_parm.user = + SRP_VBASE_get1_by_user(srp_callback_parm.vb, + srp_callback_parm.login); + if (srp_callback_parm.user) + BIO_printf(bio_s_out, "LOOKUP done %s\n", + srp_callback_parm.user->info); + else + BIO_printf(bio_s_out, "LOOKUP not successful\n"); + k = SSL_write(con, &(buf[l]), (unsigned int)i); + } +#endif + switch (SSL_get_error(con, k)) { + case SSL_ERROR_NONE: + break; + case SSL_ERROR_WANT_ASYNC: + BIO_printf(bio_s_out, "Write BLOCK (Async)\n"); + (void)BIO_flush(bio_s_out); + wait_for_async(con); + break; + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_X509_LOOKUP: + BIO_printf(bio_s_out, "Write BLOCK\n"); + (void)BIO_flush(bio_s_out); + break; + case SSL_ERROR_WANT_ASYNC_JOB: + /* + * This shouldn't ever happen in s_server. Treat as an error + */ + case SSL_ERROR_SYSCALL: + case SSL_ERROR_SSL: + BIO_printf(bio_s_out, "ERROR\n"); + (void)BIO_flush(bio_s_out); + ERR_print_errors(bio_err); + ret = 1; + goto err; + /* break; */ + case SSL_ERROR_ZERO_RETURN: + BIO_printf(bio_s_out, "DONE\n"); + (void)BIO_flush(bio_s_out); + ret = 1; + goto err; + } + if (k > 0) { + l += k; + i -= k; + } + if (i <= 0) + break; + } + } + if (read_from_sslcon) { + /* + * init_ssl_connection handles all async events itself so if we're + * waiting for async then we shouldn't go back into + * init_ssl_connection + */ + if ((!async || !SSL_waiting_for_async(con)) + && !SSL_is_init_finished(con)) { + i = init_ssl_connection(con); + + if (i < 0) { + ret = 0; + goto err; + } else if (i == 0) { + ret = 1; + goto err; + } + } else { + again: + i = SSL_read(con, (char *)buf, bufsize); +#ifndef OPENSSL_NO_SRP + while (SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP) { + BIO_printf(bio_s_out, "LOOKUP renego during read\n"); + SRP_user_pwd_free(srp_callback_parm.user); + srp_callback_parm.user = + SRP_VBASE_get1_by_user(srp_callback_parm.vb, + srp_callback_parm.login); + if (srp_callback_parm.user) + BIO_printf(bio_s_out, "LOOKUP done %s\n", + srp_callback_parm.user->info); + else + BIO_printf(bio_s_out, "LOOKUP not successful\n"); + i = SSL_read(con, (char *)buf, bufsize); + } +#endif + switch (SSL_get_error(con, i)) { + case SSL_ERROR_NONE: +#ifdef CHARSET_EBCDIC + ascii2ebcdic(buf, buf, i); +#endif + raw_write_stdout(buf, (unsigned int)i); + (void)BIO_flush(bio_s_out); + if (SSL_has_pending(con)) + goto again; + break; + case SSL_ERROR_WANT_ASYNC: + BIO_printf(bio_s_out, "Read BLOCK (Async)\n"); + (void)BIO_flush(bio_s_out); + wait_for_async(con); + break; + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_READ: + BIO_printf(bio_s_out, "Read BLOCK\n"); + (void)BIO_flush(bio_s_out); + break; + case SSL_ERROR_WANT_ASYNC_JOB: + /* + * This shouldn't ever happen in s_server. Treat as an error + */ + case SSL_ERROR_SYSCALL: + case SSL_ERROR_SSL: + BIO_printf(bio_s_out, "ERROR\n"); + (void)BIO_flush(bio_s_out); + ERR_print_errors(bio_err); + ret = 1; + goto err; + case SSL_ERROR_ZERO_RETURN: + BIO_printf(bio_s_out, "DONE\n"); + (void)BIO_flush(bio_s_out); + ret = 1; + goto err; + } + } + } + } + err: + if (con != NULL) { + BIO_printf(bio_s_out, "shutting down SSL\n"); + SSL_set_shutdown(con, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); + SSL_free(con); + } + BIO_printf(bio_s_out, "CONNECTION CLOSED\n"); + OPENSSL_clear_free(buf, bufsize); + return ret; +} + +static void close_accept_socket(void) +{ + BIO_printf(bio_err, "shutdown accept socket\n"); + if (accept_socket >= 0) { + BIO_closesocket(accept_socket); + } +} + +static int is_retryable(SSL *con, int i) +{ + int err = SSL_get_error(con, i); + + /* If it's not a fatal error, it must be retryable */ + return (err != SSL_ERROR_SSL) + && (err != SSL_ERROR_SYSCALL) + && (err != SSL_ERROR_ZERO_RETURN); +} + +static int init_ssl_connection(SSL *con) +{ + int i; + long verify_err; + int retry = 0; + + if (dtlslisten || stateless) { + BIO_ADDR *client = NULL; + + if (dtlslisten) { + if ((client = BIO_ADDR_new()) == NULL) { + BIO_printf(bio_err, "ERROR - memory\n"); + return 0; + } + i = DTLSv1_listen(con, client); + } else { + i = SSL_stateless(con); + } + if (i > 0) { + BIO *wbio; + int fd = -1; + + if (dtlslisten) { + wbio = SSL_get_wbio(con); + if (wbio) { + BIO_get_fd(wbio, &fd); + } + + if (!wbio || BIO_connect(fd, client, 0) == 0) { + BIO_printf(bio_err, "ERROR - unable to connect\n"); + BIO_ADDR_free(client); + return 0; + } + + (void)BIO_ctrl_set_connected(wbio, client); + BIO_ADDR_free(client); + dtlslisten = 0; + } else { + stateless = 0; + } + i = SSL_accept(con); + } else { + BIO_ADDR_free(client); + } + } else { + do { + i = SSL_accept(con); + + if (i <= 0) + retry = is_retryable(con, i); +#ifdef CERT_CB_TEST_RETRY + { + while (i <= 0 + && SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP + && SSL_get_state(con) == TLS_ST_SR_CLNT_HELLO) { + BIO_printf(bio_err, + "LOOKUP from certificate callback during accept\n"); + i = SSL_accept(con); + if (i <= 0) + retry = is_retryable(con, i); + } + } +#endif + +#ifndef OPENSSL_NO_SRP + while (i <= 0 + && SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP) { + BIO_printf(bio_s_out, "LOOKUP during accept %s\n", + srp_callback_parm.login); + SRP_user_pwd_free(srp_callback_parm.user); + srp_callback_parm.user = + SRP_VBASE_get1_by_user(srp_callback_parm.vb, + srp_callback_parm.login); + if (srp_callback_parm.user) + BIO_printf(bio_s_out, "LOOKUP done %s\n", + srp_callback_parm.user->info); + else + BIO_printf(bio_s_out, "LOOKUP not successful\n"); + i = SSL_accept(con); + if (i <= 0) + retry = is_retryable(con, i); + } +#endif + } while (i < 0 && SSL_waiting_for_async(con)); + } + + if (i <= 0) { + if (((dtlslisten || stateless) && i == 0) + || (!dtlslisten && !stateless && retry)) { + BIO_printf(bio_s_out, "DELAY\n"); + return 1; + } + + BIO_printf(bio_err, "ERROR\n"); + + verify_err = SSL_get_verify_result(con); + if (verify_err != X509_V_OK) { + BIO_printf(bio_err, "verify error:%s\n", + X509_verify_cert_error_string(verify_err)); + } + /* Always print any error messages */ + ERR_print_errors(bio_err); + return 0; + } + + print_connection_info(con); + return 1; +} + +static void print_connection_info(SSL *con) +{ + const char *str; + X509 *peer; + char buf[BUFSIZ]; +#if !defined(OPENSSL_NO_NEXTPROTONEG) + const unsigned char *next_proto_neg; + unsigned next_proto_neg_len; +#endif + unsigned char *exportedkeymat; + int i; + + if (s_brief) + print_ssl_summary(con); + + PEM_write_bio_SSL_SESSION(bio_s_out, SSL_get_session(con)); + + peer = SSL_get_peer_certificate(con); + if (peer != NULL) { + BIO_printf(bio_s_out, "Client certificate\n"); + PEM_write_bio_X509(bio_s_out, peer); + dump_cert_text(bio_s_out, peer); + X509_free(peer); + peer = NULL; + } + + if (SSL_get_shared_ciphers(con, buf, sizeof(buf)) != NULL) + BIO_printf(bio_s_out, "Shared ciphers:%s\n", buf); + str = SSL_CIPHER_get_name(SSL_get_current_cipher(con)); + ssl_print_sigalgs(bio_s_out, con); +#ifndef OPENSSL_NO_EC + ssl_print_point_formats(bio_s_out, con); + ssl_print_groups(bio_s_out, con, 0); +#endif + print_ca_names(bio_s_out, con); + BIO_printf(bio_s_out, "CIPHER is %s\n", (str != NULL) ? str : "(NONE)"); + +#if !defined(OPENSSL_NO_NEXTPROTONEG) + SSL_get0_next_proto_negotiated(con, &next_proto_neg, &next_proto_neg_len); + if (next_proto_neg) { + BIO_printf(bio_s_out, "NEXTPROTO is "); + BIO_write(bio_s_out, next_proto_neg, next_proto_neg_len); + BIO_printf(bio_s_out, "\n"); + } +#endif +#ifndef OPENSSL_NO_SRTP + { + SRTP_PROTECTION_PROFILE *srtp_profile + = SSL_get_selected_srtp_profile(con); + + if (srtp_profile) + BIO_printf(bio_s_out, "SRTP Extension negotiated, profile=%s\n", + srtp_profile->name); + } +#endif + if (SSL_session_reused(con)) + BIO_printf(bio_s_out, "Reused session-id\n"); + BIO_printf(bio_s_out, "Secure Renegotiation IS%s supported\n", + SSL_get_secure_renegotiation_support(con) ? "" : " NOT"); + if ((SSL_get_options(con) & SSL_OP_NO_RENEGOTIATION)) + BIO_printf(bio_s_out, "Renegotiation is DISABLED\n"); + + if (keymatexportlabel != NULL) { + BIO_printf(bio_s_out, "Keying material exporter:\n"); + BIO_printf(bio_s_out, " Label: '%s'\n", keymatexportlabel); + BIO_printf(bio_s_out, " Length: %i bytes\n", keymatexportlen); + exportedkeymat = app_malloc(keymatexportlen, "export key"); + if (!SSL_export_keying_material(con, exportedkeymat, + keymatexportlen, + keymatexportlabel, + strlen(keymatexportlabel), + NULL, 0, 0)) { + BIO_printf(bio_s_out, " Error\n"); + } else { + BIO_printf(bio_s_out, " Keying material: "); + for (i = 0; i < keymatexportlen; i++) + BIO_printf(bio_s_out, "%02X", exportedkeymat[i]); + BIO_printf(bio_s_out, "\n"); + } + OPENSSL_free(exportedkeymat); + } + + (void)BIO_flush(bio_s_out); +} + +#ifndef OPENSSL_NO_DH +static DH *load_dh_param(const char *dhfile) +{ + DH *ret = NULL; + BIO *bio; + + if ((bio = BIO_new_file(dhfile, "r")) == NULL) + goto err; + ret = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + err: + BIO_free(bio); + return ret; +} +#endif + +static int www_body(int s, int stype, int prot, unsigned char *context) +{ + char *buf = NULL; + int ret = 1; + int i, j, k, dot; + SSL *con; + const SSL_CIPHER *c; + BIO *io, *ssl_bio, *sbio; +#ifdef RENEG + int total_bytes = 0; +#endif + int width; + fd_set readfds; + + /* Set width for a select call if needed */ + width = s + 1; + + buf = app_malloc(bufsize, "server www buffer"); + io = BIO_new(BIO_f_buffer()); + ssl_bio = BIO_new(BIO_f_ssl()); + if ((io == NULL) || (ssl_bio == NULL)) + goto err; + + if (s_nbio) { + if (!BIO_socket_nbio(s, 1)) + ERR_print_errors(bio_err); + else if (!s_quiet) + BIO_printf(bio_err, "Turned on non blocking io\n"); + } + + /* lets make the output buffer a reasonable size */ + if (!BIO_set_write_buffer_size(io, bufsize)) + goto err; + + if ((con = SSL_new(ctx)) == NULL) + goto err; + + if (s_tlsextdebug) { + SSL_set_tlsext_debug_callback(con, tlsext_cb); + SSL_set_tlsext_debug_arg(con, bio_s_out); + } + + if (context != NULL + && !SSL_set_session_id_context(con, context, + strlen((char *)context))) { + SSL_free(con); + goto err; + } + + sbio = BIO_new_socket(s, BIO_NOCLOSE); + if (s_nbio_test) { + BIO *test; + + test = BIO_new(BIO_f_nbio_test()); + sbio = BIO_push(test, sbio); + } + SSL_set_bio(con, sbio, sbio); + SSL_set_accept_state(con); + + /* No need to free |con| after this. Done by BIO_free(ssl_bio) */ + BIO_set_ssl(ssl_bio, con, BIO_CLOSE); + BIO_push(io, ssl_bio); +#ifdef CHARSET_EBCDIC + io = BIO_push(BIO_new(BIO_f_ebcdic_filter()), io); +#endif + + if (s_debug) { + BIO_set_callback(SSL_get_rbio(con), bio_dump_callback); + BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out); + } + if (s_msg) { +#ifndef OPENSSL_NO_SSL_TRACE + if (s_msg == 2) + SSL_set_msg_callback(con, SSL_trace); + else +#endif + SSL_set_msg_callback(con, msg_cb); + SSL_set_msg_callback_arg(con, bio_s_msg ? bio_s_msg : bio_s_out); + } + + for (;;) { + i = BIO_gets(io, buf, bufsize - 1); + if (i < 0) { /* error */ + if (!BIO_should_retry(io) && !SSL_waiting_for_async(con)) { + if (!s_quiet) + ERR_print_errors(bio_err); + goto err; + } else { + BIO_printf(bio_s_out, "read R BLOCK\n"); +#ifndef OPENSSL_NO_SRP + if (BIO_should_io_special(io) + && BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) { + BIO_printf(bio_s_out, "LOOKUP renego during read\n"); + SRP_user_pwd_free(srp_callback_parm.user); + srp_callback_parm.user = + SRP_VBASE_get1_by_user(srp_callback_parm.vb, + srp_callback_parm.login); + if (srp_callback_parm.user) + BIO_printf(bio_s_out, "LOOKUP done %s\n", + srp_callback_parm.user->info); + else + BIO_printf(bio_s_out, "LOOKUP not successful\n"); + continue; + } +#endif +#if !defined(OPENSSL_SYS_MSDOS) + sleep(1); +#endif + continue; + } + } else if (i == 0) { /* end of input */ + ret = 1; + goto end; + } + + /* else we have data */ + if (((www == 1) && (strncmp("GET ", buf, 4) == 0)) || + ((www == 2) && (strncmp("GET /stats ", buf, 11) == 0))) { + char *p; + X509 *peer = NULL; + STACK_OF(SSL_CIPHER) *sk; + static const char *space = " "; + + if (www == 1 && strncmp("GET /reneg", buf, 10) == 0) { + if (strncmp("GET /renegcert", buf, 14) == 0) + SSL_set_verify(con, + SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, + NULL); + i = SSL_renegotiate(con); + BIO_printf(bio_s_out, "SSL_renegotiate -> %d\n", i); + /* Send the HelloRequest */ + i = SSL_do_handshake(con); + if (i <= 0) { + BIO_printf(bio_s_out, "SSL_do_handshake() Retval %d\n", + SSL_get_error(con, i)); + ERR_print_errors(bio_err); + goto err; + } + /* Wait for a ClientHello to come back */ + FD_ZERO(&readfds); + openssl_fdset(s, &readfds); + i = select(width, (void *)&readfds, NULL, NULL, NULL); + if (i <= 0 || !FD_ISSET(s, &readfds)) { + BIO_printf(bio_s_out, + "Error waiting for client response\n"); + ERR_print_errors(bio_err); + goto err; + } + /* + * We're not actually expecting any data here and we ignore + * any that is sent. This is just to force the handshake that + * we're expecting to come from the client. If they haven't + * sent one there's not much we can do. + */ + BIO_gets(io, buf, bufsize - 1); + } + + BIO_puts(io, + "HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n"); + BIO_puts(io, "\n"); + BIO_puts(io, "
\n");
+            /* BIO_puts(io, OpenSSL_version(OPENSSL_VERSION)); */
+            BIO_puts(io, "\n");
+            for (i = 0; i < local_argc; i++) {
+                const char *myp;
+                for (myp = local_argv[i]; *myp; myp++)
+                    switch (*myp) {
+                    case '<':
+                        BIO_puts(io, "<");
+                        break;
+                    case '>':
+                        BIO_puts(io, ">");
+                        break;
+                    case '&':
+                        BIO_puts(io, "&");
+                        break;
+                    default:
+                        BIO_write(io, myp, 1);
+                        break;
+                    }
+                BIO_write(io, " ", 1);
+            }
+            BIO_puts(io, "\n");
+
+            BIO_printf(io,
+                       "Secure Renegotiation IS%s supported\n",
+                       SSL_get_secure_renegotiation_support(con) ?
+                       "" : " NOT");
+
+            /*
+             * The following is evil and should not really be done
+             */
+            BIO_printf(io, "Ciphers supported in s_server binary\n");
+            sk = SSL_get_ciphers(con);
+            j = sk_SSL_CIPHER_num(sk);
+            for (i = 0; i < j; i++) {
+                c = sk_SSL_CIPHER_value(sk, i);
+                BIO_printf(io, "%-11s:%-25s ",
+                           SSL_CIPHER_get_version(c), SSL_CIPHER_get_name(c));
+                if ((((i + 1) % 2) == 0) && (i + 1 != j))
+                    BIO_puts(io, "\n");
+            }
+            BIO_puts(io, "\n");
+            p = SSL_get_shared_ciphers(con, buf, bufsize);
+            if (p != NULL) {
+                BIO_printf(io,
+                           "---\nCiphers common between both SSL end points:\n");
+                j = i = 0;
+                while (*p) {
+                    if (*p == ':') {
+                        BIO_write(io, space, 26 - j);
+                        i++;
+                        j = 0;
+                        BIO_write(io, ((i % 3) ? " " : "\n"), 1);
+                    } else {
+                        BIO_write(io, p, 1);
+                        j++;
+                    }
+                    p++;
+                }
+                BIO_puts(io, "\n");
+            }
+            ssl_print_sigalgs(io, con);
+#ifndef OPENSSL_NO_EC
+            ssl_print_groups(io, con, 0);
+#endif
+            print_ca_names(io, con);
+            BIO_printf(io, (SSL_session_reused(con)
+                            ? "---\nReused, " : "---\nNew, "));
+            c = SSL_get_current_cipher(con);
+            BIO_printf(io, "%s, Cipher is %s\n",
+                       SSL_CIPHER_get_version(c), SSL_CIPHER_get_name(c));
+            SSL_SESSION_print(io, SSL_get_session(con));
+            BIO_printf(io, "---\n");
+            print_stats(io, SSL_get_SSL_CTX(con));
+            BIO_printf(io, "---\n");
+            peer = SSL_get_peer_certificate(con);
+            if (peer != NULL) {
+                BIO_printf(io, "Client certificate\n");
+                X509_print(io, peer);
+                PEM_write_bio_X509(io, peer);
+                X509_free(peer);
+                peer = NULL;
+            } else {
+                BIO_puts(io, "no client certificate available\n");
+            }
+            BIO_puts(io, "
\r\n\r\n"); + break; + } else if ((www == 2 || www == 3) + && (strncmp("GET /", buf, 5) == 0)) { + BIO *file; + char *p, *e; + static const char *text = + "HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n"; + + /* skip the '/' */ + p = &(buf[5]); + + dot = 1; + for (e = p; *e != '\0'; e++) { + if (e[0] == ' ') + break; + + switch (dot) { + case 1: + dot = (e[0] == '.') ? 2 : 0; + break; + case 2: + dot = (e[0] == '.') ? 3 : 0; + break; + case 3: + dot = (e[0] == '/') ? -1 : 0; + break; + } + if (dot == 0) + dot = (e[0] == '/') ? 1 : 0; + } + dot = (dot == 3) || (dot == -1); /* filename contains ".." + * component */ + + if (*e == '\0') { + BIO_puts(io, text); + BIO_printf(io, "'%s' is an invalid file name\r\n", p); + break; + } + *e = '\0'; + + if (dot) { + BIO_puts(io, text); + BIO_printf(io, "'%s' contains '..' reference\r\n", p); + break; + } + + if (*p == '/') { + BIO_puts(io, text); + BIO_printf(io, "'%s' is an invalid path\r\n", p); + break; + } + + /* if a directory, do the index thang */ + if (app_isdir(p) > 0) { + BIO_puts(io, text); + BIO_printf(io, "'%s' is a directory\r\n", p); + break; + } + + if ((file = BIO_new_file(p, "r")) == NULL) { + BIO_puts(io, text); + BIO_printf(io, "Error opening '%s'\r\n", p); + ERR_print_errors(io); + break; + } + + if (!s_quiet) + BIO_printf(bio_err, "FILE:%s\n", p); + + if (www == 2) { + i = strlen(p); + if (((i > 5) && (strcmp(&(p[i - 5]), ".html") == 0)) || + ((i > 4) && (strcmp(&(p[i - 4]), ".php") == 0)) || + ((i > 4) && (strcmp(&(p[i - 4]), ".htm") == 0))) + BIO_puts(io, + "HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n"); + else + BIO_puts(io, + "HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n"); + } + /* send the file */ + for (;;) { + i = BIO_read(file, buf, bufsize); + if (i <= 0) + break; + +#ifdef RENEG + total_bytes += i; + BIO_printf(bio_err, "%d\n", i); + if (total_bytes > 3 * 1024) { + total_bytes = 0; + BIO_printf(bio_err, "RENEGOTIATE\n"); + SSL_renegotiate(con); + } +#endif + + for (j = 0; j < i;) { +#ifdef RENEG + static count = 0; + if (++count == 13) { + SSL_renegotiate(con); + } +#endif + k = BIO_write(io, &(buf[j]), i - j); + if (k <= 0) { + if (!BIO_should_retry(io) + && !SSL_waiting_for_async(con)) + goto write_error; + else { + BIO_printf(bio_s_out, "rwrite W BLOCK\n"); + } + } else { + j += k; + } + } + } + write_error: + BIO_free(file); + break; + } + } + + for (;;) { + i = (int)BIO_flush(io); + if (i <= 0) { + if (!BIO_should_retry(io)) + break; + } else + break; + } + end: + /* make sure we re-use sessions */ + SSL_set_shutdown(con, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); + + err: + OPENSSL_free(buf); + BIO_free_all(io); + return ret; +} + +static int rev_body(int s, int stype, int prot, unsigned char *context) +{ + char *buf = NULL; + int i; + int ret = 1; + SSL *con; + BIO *io, *ssl_bio, *sbio; + + buf = app_malloc(bufsize, "server rev buffer"); + io = BIO_new(BIO_f_buffer()); + ssl_bio = BIO_new(BIO_f_ssl()); + if ((io == NULL) || (ssl_bio == NULL)) + goto err; + + /* lets make the output buffer a reasonable size */ + if (!BIO_set_write_buffer_size(io, bufsize)) + goto err; + + if ((con = SSL_new(ctx)) == NULL) + goto err; + + if (s_tlsextdebug) { + SSL_set_tlsext_debug_callback(con, tlsext_cb); + SSL_set_tlsext_debug_arg(con, bio_s_out); + } + if (context != NULL + && !SSL_set_session_id_context(con, context, + strlen((char *)context))) { + SSL_free(con); + ERR_print_errors(bio_err); + goto err; + } + + sbio = BIO_new_socket(s, BIO_NOCLOSE); + SSL_set_bio(con, sbio, sbio); + SSL_set_accept_state(con); + + /* No need to free |con| after this. Done by BIO_free(ssl_bio) */ + BIO_set_ssl(ssl_bio, con, BIO_CLOSE); + BIO_push(io, ssl_bio); +#ifdef CHARSET_EBCDIC + io = BIO_push(BIO_new(BIO_f_ebcdic_filter()), io); +#endif + + if (s_debug) { + BIO_set_callback(SSL_get_rbio(con), bio_dump_callback); + BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out); + } + if (s_msg) { +#ifndef OPENSSL_NO_SSL_TRACE + if (s_msg == 2) + SSL_set_msg_callback(con, SSL_trace); + else +#endif + SSL_set_msg_callback(con, msg_cb); + SSL_set_msg_callback_arg(con, bio_s_msg ? bio_s_msg : bio_s_out); + } + + for (;;) { + i = BIO_do_handshake(io); + if (i > 0) + break; + if (!BIO_should_retry(io)) { + BIO_puts(bio_err, "CONNECTION FAILURE\n"); + ERR_print_errors(bio_err); + goto end; + } +#ifndef OPENSSL_NO_SRP + if (BIO_should_io_special(io) + && BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) { + BIO_printf(bio_s_out, "LOOKUP renego during accept\n"); + SRP_user_pwd_free(srp_callback_parm.user); + srp_callback_parm.user = + SRP_VBASE_get1_by_user(srp_callback_parm.vb, + srp_callback_parm.login); + if (srp_callback_parm.user) + BIO_printf(bio_s_out, "LOOKUP done %s\n", + srp_callback_parm.user->info); + else + BIO_printf(bio_s_out, "LOOKUP not successful\n"); + continue; + } +#endif + } + BIO_printf(bio_err, "CONNECTION ESTABLISHED\n"); + print_ssl_summary(con); + + for (;;) { + i = BIO_gets(io, buf, bufsize - 1); + if (i < 0) { /* error */ + if (!BIO_should_retry(io)) { + if (!s_quiet) + ERR_print_errors(bio_err); + goto err; + } else { + BIO_printf(bio_s_out, "read R BLOCK\n"); +#ifndef OPENSSL_NO_SRP + if (BIO_should_io_special(io) + && BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) { + BIO_printf(bio_s_out, "LOOKUP renego during read\n"); + SRP_user_pwd_free(srp_callback_parm.user); + srp_callback_parm.user = + SRP_VBASE_get1_by_user(srp_callback_parm.vb, + srp_callback_parm.login); + if (srp_callback_parm.user) + BIO_printf(bio_s_out, "LOOKUP done %s\n", + srp_callback_parm.user->info); + else + BIO_printf(bio_s_out, "LOOKUP not successful\n"); + continue; + } +#endif +#if !defined(OPENSSL_SYS_MSDOS) + sleep(1); +#endif + continue; + } + } else if (i == 0) { /* end of input */ + ret = 1; + BIO_printf(bio_err, "CONNECTION CLOSED\n"); + goto end; + } else { + char *p = buf + i - 1; + while (i && (*p == '\n' || *p == '\r')) { + p--; + i--; + } + if (!s_ign_eof && (i == 5) && (strncmp(buf, "CLOSE", 5) == 0)) { + ret = 1; + BIO_printf(bio_err, "CONNECTION CLOSED\n"); + goto end; + } + BUF_reverse((unsigned char *)buf, NULL, i); + buf[i] = '\n'; + BIO_write(io, buf, i + 1); + for (;;) { + i = BIO_flush(io); + if (i > 0) + break; + if (!BIO_should_retry(io)) + goto end; + } + } + } + end: + /* make sure we re-use sessions */ + SSL_set_shutdown(con, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); + + err: + + OPENSSL_free(buf); + BIO_free_all(io); + return ret; +} + +#define MAX_SESSION_ID_ATTEMPTS 10 +static int generate_session_id(SSL *ssl, unsigned char *id, + unsigned int *id_len) +{ + unsigned int count = 0; + do { + if (RAND_bytes(id, *id_len) <= 0) + return 0; + /* + * Prefix the session_id with the required prefix. NB: If our prefix + * is too long, clip it - but there will be worse effects anyway, eg. + * the server could only possibly create 1 session ID (ie. the + * prefix!) so all future session negotiations will fail due to + * conflicts. + */ + memcpy(id, session_id_prefix, + (strlen(session_id_prefix) < *id_len) ? + strlen(session_id_prefix) : *id_len); + } + while (SSL_has_matching_session_id(ssl, id, *id_len) && + (++count < MAX_SESSION_ID_ATTEMPTS)); + if (count >= MAX_SESSION_ID_ATTEMPTS) + return 0; + return 1; +} + +/* + * By default s_server uses an in-memory cache which caches SSL_SESSION + * structures without any serialisation. This hides some bugs which only + * become apparent in deployed servers. By implementing a basic external + * session cache some issues can be debugged using s_server. + */ + +typedef struct simple_ssl_session_st { + unsigned char *id; + unsigned int idlen; + unsigned char *der; + int derlen; + struct simple_ssl_session_st *next; +} simple_ssl_session; + +static simple_ssl_session *first = NULL; + +static int add_session(SSL *ssl, SSL_SESSION *session) +{ + simple_ssl_session *sess = app_malloc(sizeof(*sess), "get session"); + unsigned char *p; + + SSL_SESSION_get_id(session, &sess->idlen); + sess->derlen = i2d_SSL_SESSION(session, NULL); + if (sess->derlen < 0) { + BIO_printf(bio_err, "Error encoding session\n"); + OPENSSL_free(sess); + return 0; + } + + sess->id = OPENSSL_memdup(SSL_SESSION_get_id(session, NULL), sess->idlen); + sess->der = app_malloc(sess->derlen, "get session buffer"); + if (!sess->id) { + BIO_printf(bio_err, "Out of memory adding to external cache\n"); + OPENSSL_free(sess->id); + OPENSSL_free(sess->der); + OPENSSL_free(sess); + return 0; + } + p = sess->der; + + /* Assume it still works. */ + if (i2d_SSL_SESSION(session, &p) != sess->derlen) { + BIO_printf(bio_err, "Unexpected session encoding length\n"); + OPENSSL_free(sess->id); + OPENSSL_free(sess->der); + OPENSSL_free(sess); + return 0; + } + + sess->next = first; + first = sess; + BIO_printf(bio_err, "New session added to external cache\n"); + return 0; +} + +static SSL_SESSION *get_session(SSL *ssl, const unsigned char *id, int idlen, + int *do_copy) +{ + simple_ssl_session *sess; + *do_copy = 0; + for (sess = first; sess; sess = sess->next) { + if (idlen == (int)sess->idlen && !memcmp(sess->id, id, idlen)) { + const unsigned char *p = sess->der; + BIO_printf(bio_err, "Lookup session: cache hit\n"); + return d2i_SSL_SESSION(NULL, &p, sess->derlen); + } + } + BIO_printf(bio_err, "Lookup session: cache miss\n"); + return NULL; +} + +static void del_session(SSL_CTX *sctx, SSL_SESSION *session) +{ + simple_ssl_session *sess, *prev = NULL; + const unsigned char *id; + unsigned int idlen; + id = SSL_SESSION_get_id(session, &idlen); + for (sess = first; sess; sess = sess->next) { + if (idlen == sess->idlen && !memcmp(sess->id, id, idlen)) { + if (prev) + prev->next = sess->next; + else + first = sess->next; + OPENSSL_free(sess->id); + OPENSSL_free(sess->der); + OPENSSL_free(sess); + return; + } + prev = sess; + } +} + +static void init_session_cache_ctx(SSL_CTX *sctx) +{ + SSL_CTX_set_session_cache_mode(sctx, + SSL_SESS_CACHE_NO_INTERNAL | + SSL_SESS_CACHE_SERVER); + SSL_CTX_sess_set_new_cb(sctx, add_session); + SSL_CTX_sess_set_get_cb(sctx, get_session); + SSL_CTX_sess_set_remove_cb(sctx, del_session); +} + +static void free_sessions(void) +{ + simple_ssl_session *sess, *tsess; + for (sess = first; sess;) { + OPENSSL_free(sess->id); + OPENSSL_free(sess->der); + tsess = sess; + sess = sess->next; + OPENSSL_free(tsess); + } + first = NULL; +} + +#endif /* OPENSSL_NO_SOCK */ diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/s_socket.c b/trunk/3rdparty/openssl-1.1-fit/apps/s_socket.c new file mode 100644 index 000000000..76f928900 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/s_socket.c @@ -0,0 +1,395 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* socket-related functions used by s_client and s_server */ +#include +#include +#include +#include +#include +#include + +/* + * With IPv6, it looks like Digital has mixed up the proper order of + * recursive header file inclusion, resulting in the compiler complaining + * that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which is + * needed to have fileno() declared correctly... So let's define u_int + */ +#if defined(OPENSSL_SYS_VMS_DECC) && !defined(__U_INT) +# define __U_INT +typedef unsigned int u_int; +#endif + +#ifndef OPENSSL_NO_SOCK + +# include "apps.h" +# include "s_apps.h" +# include "internal/sockets.h" + +# include +# include + +/* Keep track of our peer's address for the cookie callback */ +BIO_ADDR *ourpeer = NULL; + +/* + * init_client - helper routine to set up socket communication + * @sock: pointer to storage of resulting socket. + * @host: the host name or path (for AF_UNIX) to connect to. + * @port: the port to connect to (ignored for AF_UNIX). + * @bindhost: source host or path (for AF_UNIX). + * @bindport: source port (ignored for AF_UNIX). + * @family: desired socket family, may be AF_INET, AF_INET6, AF_UNIX or + * AF_UNSPEC + * @type: socket type, must be SOCK_STREAM or SOCK_DGRAM + * @protocol: socket protocol, e.g. IPPROTO_TCP or IPPROTO_UDP (or 0 for any) + * + * This will create a socket and use it to connect to a host:port, or if + * family == AF_UNIX, to the path found in host. + * + * If the host has more than one address, it will try them one by one until + * a successful connection is established. The resulting socket will be + * found in *sock on success, it will be given INVALID_SOCKET otherwise. + * + * Returns 1 on success, 0 on failure. + */ +int init_client(int *sock, const char *host, const char *port, + const char *bindhost, const char *bindport, + int family, int type, int protocol) +{ + BIO_ADDRINFO *res = NULL; + BIO_ADDRINFO *bindaddr = NULL; + const BIO_ADDRINFO *ai = NULL; + const BIO_ADDRINFO *bi = NULL; + int found = 0; + int ret; + + if (BIO_sock_init() != 1) + return 0; + + ret = BIO_lookup_ex(host, port, BIO_LOOKUP_CLIENT, family, type, protocol, + &res); + if (ret == 0) { + ERR_print_errors(bio_err); + return 0; + } + + if (bindhost != NULL || bindport != NULL) { + ret = BIO_lookup_ex(bindhost, bindport, BIO_LOOKUP_CLIENT, + family, type, protocol, &bindaddr); + if (ret == 0) { + ERR_print_errors (bio_err); + goto out; + } + } + + ret = 0; + for (ai = res; ai != NULL; ai = BIO_ADDRINFO_next(ai)) { + /* Admittedly, these checks are quite paranoid, we should not get + * anything in the BIO_ADDRINFO chain that we haven't + * asked for. */ + OPENSSL_assert((family == AF_UNSPEC + || family == BIO_ADDRINFO_family(ai)) + && (type == 0 || type == BIO_ADDRINFO_socktype(ai)) + && (protocol == 0 + || protocol == BIO_ADDRINFO_protocol(ai))); + + if (bindaddr != NULL) { + for (bi = bindaddr; bi != NULL; bi = BIO_ADDRINFO_next(bi)) { + if (BIO_ADDRINFO_family(bi) == BIO_ADDRINFO_family(ai)) + break; + } + if (bi == NULL) + continue; + ++found; + } + + *sock = BIO_socket(BIO_ADDRINFO_family(ai), BIO_ADDRINFO_socktype(ai), + BIO_ADDRINFO_protocol(ai), 0); + if (*sock == INVALID_SOCKET) { + /* Maybe the kernel doesn't support the socket family, even if + * BIO_lookup() added it in the returned result... + */ + continue; + } + + if (bi != NULL) { + if (!BIO_bind(*sock, BIO_ADDRINFO_address(bi), + BIO_SOCK_REUSEADDR)) { + BIO_closesocket(*sock); + *sock = INVALID_SOCKET; + break; + } + } + +#ifndef OPENSSL_NO_SCTP + if (protocol == IPPROTO_SCTP) { + /* + * For SCTP we have to set various options on the socket prior to + * connecting. This is done automatically by BIO_new_dgram_sctp(). + * We don't actually need the created BIO though so we free it again + * immediately. + */ + BIO *tmpbio = BIO_new_dgram_sctp(*sock, BIO_NOCLOSE); + + if (tmpbio == NULL) { + ERR_print_errors(bio_err); + return 0; + } + BIO_free(tmpbio); + } +#endif + + if (!BIO_connect(*sock, BIO_ADDRINFO_address(ai), + protocol == IPPROTO_TCP ? BIO_SOCK_NODELAY : 0)) { + BIO_closesocket(*sock); + *sock = INVALID_SOCKET; + continue; + } + + /* Success, don't try any more addresses */ + break; + } + + if (*sock == INVALID_SOCKET) { + if (bindaddr != NULL && !found) { + BIO_printf(bio_err, "Can't bind %saddress for %s%s%s\n", + BIO_ADDRINFO_family(res) == AF_INET6 ? "IPv6 " : + BIO_ADDRINFO_family(res) == AF_INET ? "IPv4 " : + BIO_ADDRINFO_family(res) == AF_UNIX ? "unix " : "", + bindhost != NULL ? bindhost : "", + bindport != NULL ? ":" : "", + bindport != NULL ? bindport : ""); + ERR_clear_error(); + ret = 0; + } + ERR_print_errors(bio_err); + } else { + /* Remove any stale errors from previous connection attempts */ + ERR_clear_error(); + ret = 1; + } +out: + if (bindaddr != NULL) { + BIO_ADDRINFO_free (bindaddr); + } + BIO_ADDRINFO_free(res); + return ret; +} + +/* + * do_server - helper routine to perform a server operation + * @accept_sock: pointer to storage of resulting socket. + * @host: the host name or path (for AF_UNIX) to connect to. + * @port: the port to connect to (ignored for AF_UNIX). + * @family: desired socket family, may be AF_INET, AF_INET6, AF_UNIX or + * AF_UNSPEC + * @type: socket type, must be SOCK_STREAM or SOCK_DGRAM + * @cb: pointer to a function that receives the accepted socket and + * should perform the communication with the connecting client. + * @context: pointer to memory that's passed verbatim to the cb function. + * @naccept: number of times an incoming connect should be accepted. If -1, + * unlimited number. + * + * This will create a socket and use it to listen to a host:port, or if + * family == AF_UNIX, to the path found in host, then start accepting + * incoming connections and run cb on the resulting socket. + * + * 0 on failure, something other on success. + */ +int do_server(int *accept_sock, const char *host, const char *port, + int family, int type, int protocol, do_server_cb cb, + unsigned char *context, int naccept, BIO *bio_s_out) +{ + int asock = 0; + int sock; + int i; + BIO_ADDRINFO *res = NULL; + const BIO_ADDRINFO *next; + int sock_family, sock_type, sock_protocol, sock_port; + const BIO_ADDR *sock_address; + int sock_options = BIO_SOCK_REUSEADDR; + int ret = 0; + + if (BIO_sock_init() != 1) + return 0; + + if (!BIO_lookup_ex(host, port, BIO_LOOKUP_SERVER, family, type, protocol, + &res)) { + ERR_print_errors(bio_err); + return 0; + } + + /* Admittedly, these checks are quite paranoid, we should not get + * anything in the BIO_ADDRINFO chain that we haven't asked for */ + OPENSSL_assert((family == AF_UNSPEC || family == BIO_ADDRINFO_family(res)) + && (type == 0 || type == BIO_ADDRINFO_socktype(res)) + && (protocol == 0 || protocol == BIO_ADDRINFO_protocol(res))); + + sock_family = BIO_ADDRINFO_family(res); + sock_type = BIO_ADDRINFO_socktype(res); + sock_protocol = BIO_ADDRINFO_protocol(res); + sock_address = BIO_ADDRINFO_address(res); + next = BIO_ADDRINFO_next(res); + if (sock_family == AF_INET6) + sock_options |= BIO_SOCK_V6_ONLY; + if (next != NULL + && BIO_ADDRINFO_socktype(next) == sock_type + && BIO_ADDRINFO_protocol(next) == sock_protocol) { + if (sock_family == AF_INET + && BIO_ADDRINFO_family(next) == AF_INET6) { + sock_family = AF_INET6; + sock_address = BIO_ADDRINFO_address(next); + } else if (sock_family == AF_INET6 + && BIO_ADDRINFO_family(next) == AF_INET) { + sock_options &= ~BIO_SOCK_V6_ONLY; + } + } + + asock = BIO_socket(sock_family, sock_type, sock_protocol, 0); + if (asock == INVALID_SOCKET + || !BIO_listen(asock, sock_address, sock_options)) { + BIO_ADDRINFO_free(res); + ERR_print_errors(bio_err); + if (asock != INVALID_SOCKET) + BIO_closesocket(asock); + goto end; + } + +#ifndef OPENSSL_NO_SCTP + if (protocol == IPPROTO_SCTP) { + /* + * For SCTP we have to set various options on the socket prior to + * accepting. This is done automatically by BIO_new_dgram_sctp(). + * We don't actually need the created BIO though so we free it again + * immediately. + */ + BIO *tmpbio = BIO_new_dgram_sctp(asock, BIO_NOCLOSE); + + if (tmpbio == NULL) { + BIO_closesocket(asock); + ERR_print_errors(bio_err); + goto end; + } + BIO_free(tmpbio); + } +#endif + + sock_port = BIO_ADDR_rawport(sock_address); + + BIO_ADDRINFO_free(res); + res = NULL; + + if (sock_port == 0) { + /* dynamically allocated port, report which one */ + union BIO_sock_info_u info; + char *hostname = NULL; + char *service = NULL; + int success = 0; + + if ((info.addr = BIO_ADDR_new()) != NULL + && BIO_sock_info(asock, BIO_SOCK_INFO_ADDRESS, &info) + && (hostname = BIO_ADDR_hostname_string(info.addr, 1)) != NULL + && (service = BIO_ADDR_service_string(info.addr, 1)) != NULL + && BIO_printf(bio_s_out, + strchr(hostname, ':') == NULL + ? /* IPv4 */ "ACCEPT %s:%s\n" + : /* IPv6 */ "ACCEPT [%s]:%s\n", + hostname, service) > 0) + success = 1; + + (void)BIO_flush(bio_s_out); + OPENSSL_free(hostname); + OPENSSL_free(service); + BIO_ADDR_free(info.addr); + if (!success) { + BIO_closesocket(asock); + ERR_print_errors(bio_err); + goto end; + } + } else { + (void)BIO_printf(bio_s_out, "ACCEPT\n"); + (void)BIO_flush(bio_s_out); + } + + if (accept_sock != NULL) + *accept_sock = asock; + for (;;) { + char sink[64]; + struct timeval timeout; + fd_set readfds; + + if (type == SOCK_STREAM) { + BIO_ADDR_free(ourpeer); + ourpeer = BIO_ADDR_new(); + if (ourpeer == NULL) { + BIO_closesocket(asock); + ERR_print_errors(bio_err); + goto end; + } + do { + sock = BIO_accept_ex(asock, ourpeer, 0); + } while (sock < 0 && BIO_sock_should_retry(sock)); + if (sock < 0) { + ERR_print_errors(bio_err); + BIO_closesocket(asock); + break; + } + BIO_set_tcp_ndelay(sock, 1); + i = (*cb)(sock, type, protocol, context); + + /* + * If we ended with an alert being sent, but still with data in the + * network buffer to be read, then calling BIO_closesocket() will + * result in a TCP-RST being sent. On some platforms (notably + * Windows) then this will result in the peer immediately abandoning + * the connection including any buffered alert data before it has + * had a chance to be read. Shutting down the sending side first, + * and then closing the socket sends TCP-FIN first followed by + * TCP-RST. This seems to allow the peer to read the alert data. + */ + shutdown(sock, 1); /* SHUT_WR */ + /* + * We just said we have nothing else to say, but it doesn't mean + * that the other side has nothing. It's even recommended to + * consume incoming data. [In testing context this ensures that + * alerts are passed on...] + */ + timeout.tv_sec = 0; + timeout.tv_usec = 500000; /* some extreme round-trip */ + do { + FD_ZERO(&readfds); + openssl_fdset(sock, &readfds); + } while (select(sock + 1, &readfds, NULL, NULL, &timeout) > 0 + && readsocket(sock, sink, sizeof(sink)) > 0); + + BIO_closesocket(sock); + } else { + i = (*cb)(asock, type, protocol, context); + } + + if (naccept != -1) + naccept--; + if (i < 0 || naccept == 0) { + BIO_closesocket(asock); + ret = i; + break; + } + } + end: +# ifdef AF_UNIX + if (family == AF_UNIX) + unlink(host); +# endif + BIO_ADDR_free(ourpeer); + ourpeer = NULL; + return ret; +} + +#endif /* OPENSSL_NO_SOCK */ diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/s_time.c b/trunk/3rdparty/openssl-1.1-fit/apps/s_time.c new file mode 100644 index 000000000..82d40a5a5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/s_time.c @@ -0,0 +1,405 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include + +#include + +#ifndef OPENSSL_NO_SOCK + +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include "s_apps.h" +#include +#include +#if !defined(OPENSSL_SYS_MSDOS) +# include OPENSSL_UNISTD +#endif + +#define SSL_CONNECT_NAME "localhost:4433" + +#define SECONDS 30 +#define SECONDSSTR "30" + +static SSL *doConnection(SSL *scon, const char *host, SSL_CTX *ctx); + +/* + * Define a HTTP get command globally. + * Also define the size of the command, this is two bytes less than + * the size of the string because the %s is replaced by the URL. + */ +static const char fmt_http_get_cmd[] = "GET %s HTTP/1.0\r\n\r\n"; +static const size_t fmt_http_get_cmd_size = sizeof(fmt_http_get_cmd) - 2; + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_CONNECT, OPT_CIPHER, OPT_CIPHERSUITES, OPT_CERT, OPT_NAMEOPT, OPT_KEY, + OPT_CAPATH, OPT_CAFILE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_NEW, OPT_REUSE, + OPT_BUGS, OPT_VERIFY, OPT_TIME, OPT_SSL3, + OPT_WWW +} OPTION_CHOICE; + +const OPTIONS s_time_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"connect", OPT_CONNECT, 's', + "Where to connect as post:port (default is " SSL_CONNECT_NAME ")"}, + {"cipher", OPT_CIPHER, 's', "TLSv1.2 and below cipher list to be used"}, + {"ciphersuites", OPT_CIPHERSUITES, 's', + "Specify TLSv1.3 ciphersuites to be used"}, + {"cert", OPT_CERT, '<', "Cert file to use, PEM format assumed"}, + {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"}, + {"key", OPT_KEY, '<', "File with key, PEM; default is -cert file"}, + {"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"}, + {"cafile", OPT_CAFILE, '<', "PEM format file of CA's"}, + {"no-CAfile", OPT_NOCAFILE, '-', + "Do not load the default certificates file"}, + {"no-CApath", OPT_NOCAPATH, '-', + "Do not load certificates from the default certificates directory"}, + {"new", OPT_NEW, '-', "Just time new connections"}, + {"reuse", OPT_REUSE, '-', "Just time connection reuse"}, + {"bugs", OPT_BUGS, '-', "Turn on SSL bug compatibility"}, + {"verify", OPT_VERIFY, 'p', + "Turn on peer certificate verification, set depth"}, + {"time", OPT_TIME, 'p', "Seconds to collect data, default " SECONDSSTR}, + {"www", OPT_WWW, 's', "Fetch specified page from the site"}, +#ifndef OPENSSL_NO_SSL3 + {"ssl3", OPT_SSL3, '-', "Just use SSLv3"}, +#endif + {NULL} +}; + +#define START 0 +#define STOP 1 + +static double tm_Time_F(int s) +{ + return app_tminterval(s, 1); +} + +int s_time_main(int argc, char **argv) +{ + char buf[1024 * 8]; + SSL *scon = NULL; + SSL_CTX *ctx = NULL; + const SSL_METHOD *meth = NULL; + char *CApath = NULL, *CAfile = NULL, *cipher = NULL, *ciphersuites = NULL; + char *www_path = NULL; + char *host = SSL_CONNECT_NAME, *certfile = NULL, *keyfile = NULL, *prog; + double totalTime = 0.0; + int noCApath = 0, noCAfile = 0; + int maxtime = SECONDS, nConn = 0, perform = 3, ret = 1, i, st_bugs = 0; + long bytes_read = 0, finishtime = 0; + OPTION_CHOICE o; + int max_version = 0, ver, buf_len; + size_t buf_size; + + meth = TLS_client_method(); + + prog = opt_init(argc, argv, s_time_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(s_time_options); + ret = 0; + goto end; + case OPT_CONNECT: + host = opt_arg(); + break; + case OPT_REUSE: + perform = 2; + break; + case OPT_NEW: + perform = 1; + break; + case OPT_VERIFY: + if (!opt_int(opt_arg(), &verify_args.depth)) + goto opthelp; + BIO_printf(bio_err, "%s: verify depth is %d\n", + prog, verify_args.depth); + break; + case OPT_CERT: + certfile = opt_arg(); + break; + case OPT_NAMEOPT: + if (!set_nameopt(opt_arg())) + goto end; + break; + case OPT_KEY: + keyfile = opt_arg(); + break; + case OPT_CAPATH: + CApath = opt_arg(); + break; + case OPT_CAFILE: + CAfile = opt_arg(); + break; + case OPT_NOCAPATH: + noCApath = 1; + break; + case OPT_NOCAFILE: + noCAfile = 1; + break; + case OPT_CIPHER: + cipher = opt_arg(); + break; + case OPT_CIPHERSUITES: + ciphersuites = opt_arg(); + break; + case OPT_BUGS: + st_bugs = 1; + break; + case OPT_TIME: + if (!opt_int(opt_arg(), &maxtime)) + goto opthelp; + break; + case OPT_WWW: + www_path = opt_arg(); + buf_size = strlen(www_path) + fmt_http_get_cmd_size; + if (buf_size > sizeof(buf)) { + BIO_printf(bio_err, "%s: -www option is too long\n", prog); + goto end; + } + break; + case OPT_SSL3: + max_version = SSL3_VERSION; + break; + } + } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + + if (cipher == NULL) + cipher = getenv("SSL_CIPHER"); + + if ((ctx = SSL_CTX_new(meth)) == NULL) + goto end; + + SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); + SSL_CTX_set_quiet_shutdown(ctx, 1); + if (SSL_CTX_set_max_proto_version(ctx, max_version) == 0) + goto end; + + if (st_bugs) + SSL_CTX_set_options(ctx, SSL_OP_ALL); + if (cipher != NULL && !SSL_CTX_set_cipher_list(ctx, cipher)) + goto end; + if (ciphersuites != NULL && !SSL_CTX_set_ciphersuites(ctx, ciphersuites)) + goto end; + if (!set_cert_stuff(ctx, certfile, keyfile)) + goto end; + + if (!ctx_set_verify_locations(ctx, CAfile, CApath, noCAfile, noCApath)) { + ERR_print_errors(bio_err); + goto end; + } + if (!(perform & 1)) + goto next; + printf("Collecting connection statistics for %d seconds\n", maxtime); + + /* Loop and time how long it takes to make connections */ + + bytes_read = 0; + finishtime = (long)time(NULL) + maxtime; + tm_Time_F(START); + for (;;) { + if (finishtime < (long)time(NULL)) + break; + + if ((scon = doConnection(NULL, host, ctx)) == NULL) + goto end; + + if (www_path != NULL) { + buf_len = BIO_snprintf(buf, sizeof(buf), fmt_http_get_cmd, + www_path); + if (buf_len <= 0 || SSL_write(scon, buf, buf_len) <= 0) + goto end; + while ((i = SSL_read(scon, buf, sizeof(buf))) > 0) + bytes_read += i; + } + SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); + BIO_closesocket(SSL_get_fd(scon)); + + nConn += 1; + if (SSL_session_reused(scon)) { + ver = 'r'; + } else { + ver = SSL_version(scon); + if (ver == TLS1_VERSION) + ver = 't'; + else if (ver == SSL3_VERSION) + ver = '3'; + else + ver = '*'; + } + fputc(ver, stdout); + fflush(stdout); + + SSL_free(scon); + scon = NULL; + } + totalTime += tm_Time_F(STOP); /* Add the time for this iteration */ + + i = (int)((long)time(NULL) - finishtime + maxtime); + printf + ("\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n", + nConn, totalTime, ((double)nConn / totalTime), bytes_read); + printf + ("%d connections in %ld real seconds, %ld bytes read per connection\n", + nConn, (long)time(NULL) - finishtime + maxtime, bytes_read / nConn); + + /* + * Now loop and time connections using the same session id over and over + */ + + next: + if (!(perform & 2)) + goto end; + printf("\n\nNow timing with session id reuse.\n"); + + /* Get an SSL object so we can reuse the session id */ + if ((scon = doConnection(NULL, host, ctx)) == NULL) { + BIO_printf(bio_err, "Unable to get connection\n"); + goto end; + } + + if (www_path != NULL) { + buf_len = BIO_snprintf(buf, sizeof(buf), fmt_http_get_cmd, www_path); + if (buf_len <= 0 || SSL_write(scon, buf, buf_len) <= 0) + goto end; + while ((i = SSL_read(scon, buf, sizeof(buf))) > 0) + continue; + } + SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); + BIO_closesocket(SSL_get_fd(scon)); + + nConn = 0; + totalTime = 0.0; + + finishtime = (long)time(NULL) + maxtime; + + printf("starting\n"); + bytes_read = 0; + tm_Time_F(START); + + for (;;) { + if (finishtime < (long)time(NULL)) + break; + + if ((doConnection(scon, host, ctx)) == NULL) + goto end; + + if (www_path != NULL) { + buf_len = BIO_snprintf(buf, sizeof(buf), fmt_http_get_cmd, + www_path); + if (buf_len <= 0 || SSL_write(scon, buf, buf_len) <= 0) + goto end; + while ((i = SSL_read(scon, buf, sizeof(buf))) > 0) + bytes_read += i; + } + SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); + BIO_closesocket(SSL_get_fd(scon)); + + nConn += 1; + if (SSL_session_reused(scon)) { + ver = 'r'; + } else { + ver = SSL_version(scon); + if (ver == TLS1_VERSION) + ver = 't'; + else if (ver == SSL3_VERSION) + ver = '3'; + else + ver = '*'; + } + fputc(ver, stdout); + fflush(stdout); + } + totalTime += tm_Time_F(STOP); /* Add the time for this iteration */ + + printf + ("\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n", + nConn, totalTime, ((double)nConn / totalTime), bytes_read); + printf + ("%d connections in %ld real seconds, %ld bytes read per connection\n", + nConn, (long)time(NULL) - finishtime + maxtime, bytes_read / nConn); + + ret = 0; + + end: + SSL_free(scon); + SSL_CTX_free(ctx); + return ret; +} + +/*- + * doConnection - make a connection + */ +static SSL *doConnection(SSL *scon, const char *host, SSL_CTX *ctx) +{ + BIO *conn; + SSL *serverCon; + int i; + + if ((conn = BIO_new(BIO_s_connect())) == NULL) + return NULL; + + BIO_set_conn_hostname(conn, host); + BIO_set_conn_mode(conn, BIO_SOCK_NODELAY); + + if (scon == NULL) + serverCon = SSL_new(ctx); + else { + serverCon = scon; + SSL_set_connect_state(serverCon); + } + + SSL_set_bio(serverCon, conn, conn); + + /* ok, lets connect */ + i = SSL_connect(serverCon); + if (i <= 0) { + BIO_printf(bio_err, "ERROR\n"); + if (verify_args.error != X509_V_OK) + BIO_printf(bio_err, "verify error:%s\n", + X509_verify_cert_error_string(verify_args.error)); + else + ERR_print_errors(bio_err); + if (scon == NULL) + SSL_free(serverCon); + return NULL; + } + +#if defined(SOL_SOCKET) && defined(SO_LINGER) + { + struct linger no_linger; + int fd; + + no_linger.l_onoff = 1; + no_linger.l_linger = 0; + fd = SSL_get_fd(serverCon); + if (fd >= 0) + (void)setsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&no_linger, + sizeof(no_linger)); + } +#endif + + return serverCon; +} +#endif /* OPENSSL_NO_SOCK */ diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/server.pem b/trunk/3rdparty/openssl-1.1-fit/apps/server.pem new file mode 100644 index 000000000..d0fc265f0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/server.pem @@ -0,0 +1,52 @@ +subject= C = UK, O = OpenSSL Group, OU = FOR TESTING PURPOSES ONLY, CN = Test Server Cert +issuer= C = UK, O = OpenSSL Group, OU = FOR TESTING PURPOSES ONLY, CN = OpenSSL Test Intermediate CA +-----BEGIN CERTIFICATE----- +MIID5zCCAs+gAwIBAgIJALnu1NlVpZ6zMA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNV +BAYTAlVLMRYwFAYDVQQKDA1PcGVuU1NMIEdyb3VwMSIwIAYDVQQLDBlGT1IgVEVT +VElORyBQVVJQT1NFUyBPTkxZMSUwIwYDVQQDDBxPcGVuU1NMIFRlc3QgSW50ZXJt +ZWRpYXRlIENBMB4XDTExMTIwODE0MDE0OFoXDTIxMTAxNjE0MDE0OFowZDELMAkG +A1UEBhMCVUsxFjAUBgNVBAoMDU9wZW5TU0wgR3JvdXAxIjAgBgNVBAsMGUZPUiBU +RVNUSU5HIFBVUlBPU0VTIE9OTFkxGTAXBgNVBAMMEFRlc3QgU2VydmVyIENlcnQw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDzhPOSNtyyRspmeuUpxfNJ +KCLTuf7g3uQ4zu4iHOmRO5TQci+HhVlLZrHF9XqFXcIP0y4pWDbMSGuiorUmzmfi +R7bfSdI/+qIQt8KXRH6HNG1t8ou0VSvWId5TS5Dq/er5ODUr9OaaDva7EquHIcMv +vPQGuI+OEAcnleVCy9HVEIySrO4P3CNIicnGkwwiAud05yUAq/gPXBC1hTtmlPD7 +TVcGVSEiJdvzqqlgv02qedGrkki6GY4S7GjZxrrf7Foc2EP+51LJzwLQx3/JfrCU +41NEWAsu/Sl0tQabXESN+zJ1pDqoZ3uHMgpQjeGiE0olr+YcsSW/tJmiU9OiAr8R +AgMBAAGjgY8wgYwwDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCBeAwLAYJYIZI +AYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQW +BBSCvM8AABPR9zklmifnr9LvIBturDAfBgNVHSMEGDAWgBQ2w2yI55X+sL3szj49 +hqshgYfa2jANBgkqhkiG9w0BAQUFAAOCAQEAqb1NV0B0/pbpK9Z4/bNjzPQLTRLK +WnSNm/Jh5v0GEUOE/Beg7GNjNrmeNmqxAlpqWz9qoeoFZax+QBpIZYjROU3TS3fp +yLsrnlr0CDQ5R7kCCDGa8dkXxemmpZZLbUCpW2Uoy8sAA4JjN9OtsZY7dvUXFgJ7 +vVNTRnI01ghknbtD+2SxSQd3CWF6QhcRMAzZJ1z1cbbwGDDzfvGFPzJ+Sq+zEPds +xoVLLSetCiBc+40ZcDS5dV98h9XD7JMTQfxzA7mNGv73JoZJA6nFgj+ADSlJsY/t +JBv+z1iQRueoh9Qeee+ZbRifPouCB8FDx+AltvHTANdAq0t/K3o+pplMVA== +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA84TzkjbcskbKZnrlKcXzSSgi07n+4N7kOM7uIhzpkTuU0HIv +h4VZS2axxfV6hV3CD9MuKVg2zEhroqK1Js5n4ke230nSP/qiELfCl0R+hzRtbfKL +tFUr1iHeU0uQ6v3q+Tg1K/Tmmg72uxKrhyHDL7z0BriPjhAHJ5XlQsvR1RCMkqzu +D9wjSInJxpMMIgLndOclAKv4D1wQtYU7ZpTw+01XBlUhIiXb86qpYL9NqnnRq5JI +uhmOEuxo2ca63+xaHNhD/udSyc8C0Md/yX6wlONTRFgLLv0pdLUGm1xEjfsydaQ6 +qGd7hzIKUI3hohNKJa/mHLElv7SZolPTogK/EQIDAQABAoIBAADq9FwNtuE5IRQn +zGtO4q7Y5uCzZ8GDNYr9RKp+P2cbuWDbvVAecYq2NV9QoIiWJOAYZKklOvekIju3 +r0UZLA0PRiIrTg6NrESx3JrjWDK8QNlUO7CPTZ39/K+FrmMkV9lem9yxjJjyC34D +AQB+YRTx+l14HppjdxNwHjAVQpIx/uO2F5xAMuk32+3K+pq9CZUtrofe1q4Agj9R +5s8mSy9pbRo9kW9wl5xdEotz1LivFOEiqPUJTUq5J5PeMKao3vdK726XI4Z455Nm +W2/MA0YV0ug2FYinHcZdvKM6dimH8GLfa3X8xKRfzjGjTiMSwsdjgMa4awY3tEHH +674jhAECgYEA/zqMrc0zsbNk83sjgaYIug5kzEpN4ic020rSZsmQxSCerJTgNhmg +utKSCt0Re09Jt3LqG48msahX8ycqDsHNvlEGPQSbMu9IYeO3Wr3fAm75GEtFWePY +BhM73I7gkRt4s8bUiUepMG/wY45c5tRF23xi8foReHFFe9MDzh8fJFECgYEA9EFX +4qAik1pOJGNei9BMwmx0I0gfVEIgu0tzeVqT45vcxbxr7RkTEaDoAG6PlbWP6D9a +WQNLp4gsgRM90ZXOJ4up5DsAWDluvaF4/omabMA+MJJ5kGZ0gCj5rbZbKqUws7x8 +bp+6iBfUPJUbcqNqFmi/08Yt7vrDnMnyMw2A/sECgYEAiiuRMxnuzVm34hQcsbhH +6ymVqf7j0PW2qK0F4H1ocT9qhzWFd+RB3kHWrCjnqODQoI6GbGr/4JepHUpre1ex +4UEN5oSS3G0ru0rC3U4C59dZ5KwDHFm7ffZ1pr52ljfQDUsrjjIMRtuiwNK2OoRa +WSsqiaL+SDzSB+nBmpnAizECgYBdt/y6rerWUx4MhDwwtTnel7JwHyo2MDFS6/5g +n8qC2Lj6/fMDRE22w+CA2esp7EJNQJGv+b27iFpbJEDh+/Lf5YzIT4MwVskQ5bYB +JFcmRxUVmf4e09D7o705U/DjCgMH09iCsbLmqQ38ONIRSHZaJtMDtNTHD1yi+jF+ +OT43gQKBgQC/2OHZoko6iRlNOAQ/tMVFNq7fL81GivoQ9F1U0Qr+DH3ZfaH8eIkX +xT0ToMPJUzWAn8pZv0snA0um6SIgvkCuxO84OkANCVbttzXImIsL7pFzfcwV/ERK +UM6j0ZuSMFOCr/lGPAoOQU0fskidGEHi1/kW+suSr28TqsyYZpwBDQ== +-----END RSA PRIVATE KEY----- diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/server.srl b/trunk/3rdparty/openssl-1.1-fit/apps/server.srl new file mode 100644 index 000000000..8a0f05e16 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/server.srl @@ -0,0 +1 @@ +01 diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/server2.pem b/trunk/3rdparty/openssl-1.1-fit/apps/server2.pem new file mode 100644 index 000000000..a3927cf78 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/server2.pem @@ -0,0 +1,52 @@ +subject= C = UK, O = OpenSSL Group, OU = FOR TESTING PURPOSES ONLY, CN = Test Server Cert #2 +issuer= C = UK, O = OpenSSL Group, OU = FOR TESTING PURPOSES ONLY, CN = OpenSSL Test Intermediate CA +-----BEGIN CERTIFICATE----- +MIID6jCCAtKgAwIBAgIJALnu1NlVpZ60MA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNV +BAYTAlVLMRYwFAYDVQQKDA1PcGVuU1NMIEdyb3VwMSIwIAYDVQQLDBlGT1IgVEVT +VElORyBQVVJQT1NFUyBPTkxZMSUwIwYDVQQDDBxPcGVuU1NMIFRlc3QgSW50ZXJt +ZWRpYXRlIENBMB4XDTExMTIwODE0MDE0OFoXDTIxMTAxNjE0MDE0OFowZzELMAkG +A1UEBhMCVUsxFjAUBgNVBAoMDU9wZW5TU0wgR3JvdXAxIjAgBgNVBAsMGUZPUiBU +RVNUSU5HIFBVUlBPU0VTIE9OTFkxHDAaBgNVBAMME1Rlc3QgU2VydmVyIENlcnQg +IzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDrdi7j9yctG+L4EjBy +gjPmEqZzOJEQba26MoQGzglU7e5Xf59Rb/hgVQuKAoiZe7/R8rK4zJ4W7iXdXw0L +qBpyG8B5aGKeI32w+A9TcBApoXXL2CrYQEQjZwUIpLlYBIi2NkJj3nVkq5dgl1gO +ALiQ+W8jg3kzg5Ec9rimp9r93N8wsSL3awsafurmYCvOf7leHaMP1WJ/zDRGUNHG +/WtDjXc8ZUG1+6EXU9Jc2Fs+2Omf7fcN0l00AK/wPg8OaNS0rKyGq9JdIT9FRGV1 +bXe/rx58FaE5CItdwCSYhJvF/O95LWQoxJXye5bCFLmvDTEyVq9FMSCptfsmbXjE +ZGsXAgMBAAGjgY8wgYwwDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCBeAwLAYJ +YIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1Ud +DgQWBBR52UaWWTKzZGDH/X4mWNcuqeQVazAfBgNVHSMEGDAWgBQ2w2yI55X+sL3s +zj49hqshgYfa2jANBgkqhkiG9w0BAQUFAAOCAQEANBW+XYLlHBqVY/31ie+3gRlS +LPfy4SIqn0t3RJjagT29MXprblBO2cbMO8VGjkQdKGpmMXjxbht2arOOUXRHX4n/ +XTyn/QHEf0bcwIITMReO3DZUPAEw8hSjn9xEOM0IRVOCP+mH5fi74QzzQaZVCyYg +5VtLKdww/+sc0nCbKl2KWgDluriH0nfVx95qgW3mg9dhXRr0zmf1w2zkBHYpARYL +Dew6Z8EE4tS3HJu8/qM6meWzNtrfonQ3eiiMxjZBxzV46jchBwa2z9XYhP6AmpPb +oeTSzcQNbWsxaGYzWo46oLDUZmJOwSBawbS31bZNMCoPIY6ukoesCzFSsUKZww== +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEA63Yu4/cnLRvi+BIwcoIz5hKmcziREG2tujKEBs4JVO3uV3+f +UW/4YFULigKImXu/0fKyuMyeFu4l3V8NC6gachvAeWhiniN9sPgPU3AQKaF1y9gq +2EBEI2cFCKS5WASItjZCY951ZKuXYJdYDgC4kPlvI4N5M4ORHPa4pqfa/dzfMLEi +92sLGn7q5mArzn+5Xh2jD9Vif8w0RlDRxv1rQ413PGVBtfuhF1PSXNhbPtjpn+33 +DdJdNACv8D4PDmjUtKyshqvSXSE/RURldW13v68efBWhOQiLXcAkmISbxfzveS1k +KMSV8nuWwhS5rw0xMlavRTEgqbX7Jm14xGRrFwIDAQABAoIBAHLsTPihIfLnYIE5 +x4GsQQ5zXeBw5ITDM37ktwHnQDC+rIzyUl1aLD1AZRBoKinXd4lOTqLZ4/NHKx4A +DYr58mZtWyUmqLOMmQVuHXTZBlp7XtYuXMMNovQwjQlp9LicBeoBU6gQ5PVMtubD +F4xGF89Sn0cTHW3iMkqTtQ5KcR1j57OcJO0FEb1vPvk2MXI5ZyAatUYE7YacbEzd +rg02uIwx3FqNSkuSI79uz4hMdV5TPtuhxx9nTwj9aLUhXFeZ0mn2PVgVzEnnMoJb ++znlsZDgzDlJqdaD744YGWh8Z3OEssB35KfzFcdOeO6yH8lmv2Zfznk7pNPT7LTb +Lae9VgkCgYEA92p1qnAB3NtJtNcaW53i0S5WJgS1hxWKvUDx3lTB9s8X9fHpqL1a +E94fDfWzp/hax6FefUKIvBOukPLQ6bYjTMiFoOHzVirghAIuIUoMI5VtLhwD1hKs +Lr7l/dptMgKb1nZHyXoKHRBthsy3K4+udsPi8TzMvYElgEqyQIe/Rk0CgYEA86GL +8HC6zLszzKERDPBxrboRmoFvVUCTQDhsfj1M8aR3nQ8V5LkdIJc7Wqm/Ggfk9QRf +rJ8M2WUMlU5CNnCn/KCrKzCNZIReze3fV+HnKdbcXGLvgbHPrhnz8yYehUFG+RGq +bVyDWRU94T38izy2s5qMYrMJWZEYyXncSPbfcPMCgYAtaXfxcZ+V5xYPQFARMtiX +5nZfggvDoJuXgx0h3tK/N2HBfcaSdzbaYLG4gTmZggc/jwnl2dl5E++9oSPhUdIG +3ONSFUbxsOsGr9PBvnKd8WZZyUCXAVRjPBzAzF+whzQNWCZy/5htnz9LN7YDI9s0 +5113Q96cheDZPFydZY0hHQKBgQDVbEhNukM5xCiNcu+f2SaMnLp9EjQ4h5g3IvaP +5B16daw/Dw8LzcohWboqIxeAsze0GD/D1ZUJAEd0qBjC3g+a9BjefervCjKOzXng +38mEUm+6EwVjJSQcjSmycEs+Sr/kwr/8i5WYvU32+jk4tFgMoC+o6tQe/Uesf68k +z/dPVwKBgGbF7Vv1/3SmhlOy+zYyvJ0CrWtKxH9QP6tLIEgEpd8x7YTSuCH94yok +kToMXYA3sWNPt22GbRDZ+rcp4c7HkDx6I6vpdP9aQEwJTp0EPy0sgWr2XwYmreIQ +NFmkk8Itn9EY2R9VBaP7GLv5kvwxDdLAnmwGmzVtbmaVdxCaBwUk +-----END RSA PRIVATE KEY----- diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/sess_id.c b/trunk/3rdparty/openssl-1.1-fit/apps/sess_id.c new file mode 100644 index 000000000..8fd584f3b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/sess_id.c @@ -0,0 +1,191 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include +#include + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, + OPT_TEXT, OPT_CERT, OPT_NOOUT, OPT_CONTEXT +} OPTION_CHOICE; + +const OPTIONS sess_id_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"inform", OPT_INFORM, 'F', "Input format - default PEM (DER or PEM)"}, + {"outform", OPT_OUTFORM, 'f', + "Output format - default PEM (PEM, DER or NSS)"}, + {"in", OPT_IN, 's', "Input file - default stdin"}, + {"out", OPT_OUT, '>', "Output file - default stdout"}, + {"text", OPT_TEXT, '-', "Print ssl session id details"}, + {"cert", OPT_CERT, '-', "Output certificate "}, + {"noout", OPT_NOOUT, '-', "Don't output the encoded session info"}, + {"context", OPT_CONTEXT, 's', "Set the session ID context"}, + {NULL} +}; + +static SSL_SESSION *load_sess_id(char *file, int format); + +int sess_id_main(int argc, char **argv) +{ + SSL_SESSION *x = NULL; + X509 *peer = NULL; + BIO *out = NULL; + char *infile = NULL, *outfile = NULL, *context = NULL, *prog; + int informat = FORMAT_PEM, outformat = FORMAT_PEM; + int cert = 0, noout = 0, text = 0, ret = 1, i, num = 0; + OPTION_CHOICE o; + + prog = opt_init(argc, argv, sess_id_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(sess_id_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) + goto opthelp; + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER | OPT_FMT_NSS, + &outformat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_TEXT: + text = ++num; + break; + case OPT_CERT: + cert = ++num; + break; + case OPT_NOOUT: + noout = ++num; + break; + case OPT_CONTEXT: + context = opt_arg(); + break; + } + } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + + x = load_sess_id(infile, informat); + if (x == NULL) { + goto end; + } + peer = SSL_SESSION_get0_peer(x); + + if (context != NULL) { + size_t ctx_len = strlen(context); + if (ctx_len > SSL_MAX_SID_CTX_LENGTH) { + BIO_printf(bio_err, "Context too long\n"); + goto end; + } + if (!SSL_SESSION_set1_id_context(x, (unsigned char *)context, + ctx_len)) { + BIO_printf(bio_err, "Error setting id context\n"); + goto end; + } + } + + if (!noout || text) { + out = bio_open_default(outfile, 'w', outformat); + if (out == NULL) + goto end; + } + + if (text) { + SSL_SESSION_print(out, x); + + if (cert) { + if (peer == NULL) + BIO_puts(out, "No certificate present\n"); + else + X509_print(out, peer); + } + } + + if (!noout && !cert) { + if (outformat == FORMAT_ASN1) { + i = i2d_SSL_SESSION_bio(out, x); + } else if (outformat == FORMAT_PEM) { + i = PEM_write_bio_SSL_SESSION(out, x); + } else if (outformat == FORMAT_NSS) { + i = SSL_SESSION_print_keylog(out, x); + } else { + BIO_printf(bio_err, "bad output format specified for outfile\n"); + goto end; + } + if (!i) { + BIO_printf(bio_err, "unable to write SSL_SESSION\n"); + goto end; + } + } else if (!noout && (peer != NULL)) { /* just print the certificate */ + if (outformat == FORMAT_ASN1) { + i = (int)i2d_X509_bio(out, peer); + } else if (outformat == FORMAT_PEM) { + i = PEM_write_bio_X509(out, peer); + } else { + BIO_printf(bio_err, "bad output format specified for outfile\n"); + goto end; + } + if (!i) { + BIO_printf(bio_err, "unable to write X509\n"); + goto end; + } + } + ret = 0; + end: + BIO_free_all(out); + SSL_SESSION_free(x); + return ret; +} + +static SSL_SESSION *load_sess_id(char *infile, int format) +{ + SSL_SESSION *x = NULL; + BIO *in = NULL; + + in = bio_open_default(infile, 'r', format); + if (in == NULL) + goto end; + if (format == FORMAT_ASN1) + x = d2i_SSL_SESSION_bio(in, NULL); + else + x = PEM_read_bio_SSL_SESSION(in, NULL, NULL, NULL); + if (x == NULL) { + BIO_printf(bio_err, "unable to load SSL_SESSION\n"); + ERR_print_errors(bio_err); + goto end; + } + + end: + BIO_free(in); + return x; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/smime.c b/trunk/3rdparty/openssl-1.1-fit/apps/smime.c new file mode 100644 index 000000000..6fd473775 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/smime.c @@ -0,0 +1,647 @@ +/* + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* S/MIME utility function */ + +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include +#include + +static int save_certs(char *signerfile, STACK_OF(X509) *signers); +static int smime_cb(int ok, X509_STORE_CTX *ctx); + +#define SMIME_OP 0x10 +#define SMIME_IP 0x20 +#define SMIME_SIGNERS 0x40 +#define SMIME_ENCRYPT (1 | SMIME_OP) +#define SMIME_DECRYPT (2 | SMIME_IP) +#define SMIME_SIGN (3 | SMIME_OP | SMIME_SIGNERS) +#define SMIME_VERIFY (4 | SMIME_IP) +#define SMIME_PK7OUT (5 | SMIME_IP | SMIME_OP) +#define SMIME_RESIGN (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS) + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_ENCRYPT, OPT_DECRYPT, OPT_SIGN, OPT_RESIGN, OPT_VERIFY, + OPT_PK7OUT, OPT_TEXT, OPT_NOINTERN, OPT_NOVERIFY, OPT_NOCHAIN, + OPT_NOCERTS, OPT_NOATTR, OPT_NODETACH, OPT_NOSMIMECAP, + OPT_BINARY, OPT_NOSIGS, OPT_STREAM, OPT_INDEF, OPT_NOINDEF, + OPT_CRLFEOL, OPT_ENGINE, OPT_PASSIN, + OPT_TO, OPT_FROM, OPT_SUBJECT, OPT_SIGNER, OPT_RECIP, OPT_MD, + OPT_CIPHER, OPT_INKEY, OPT_KEYFORM, OPT_CERTFILE, OPT_CAFILE, + OPT_R_ENUM, + OPT_V_ENUM, + OPT_CAPATH, OPT_NOCAFILE, OPT_NOCAPATH, OPT_IN, OPT_INFORM, OPT_OUT, + OPT_OUTFORM, OPT_CONTENT +} OPTION_CHOICE; + +const OPTIONS smime_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] cert.pem...\n"}, + {OPT_HELP_STR, 1, '-', + " cert.pem... recipient certs for encryption\n"}, + {OPT_HELP_STR, 1, '-', "Valid options are:\n"}, + {"help", OPT_HELP, '-', "Display this summary"}, + {"encrypt", OPT_ENCRYPT, '-', "Encrypt message"}, + {"decrypt", OPT_DECRYPT, '-', "Decrypt encrypted message"}, + {"sign", OPT_SIGN, '-', "Sign message"}, + {"verify", OPT_VERIFY, '-', "Verify signed message"}, + {"pk7out", OPT_PK7OUT, '-', "Output PKCS#7 structure"}, + {"nointern", OPT_NOINTERN, '-', + "Don't search certificates in message for signer"}, + {"nosigs", OPT_NOSIGS, '-', "Don't verify message signature"}, + {"noverify", OPT_NOVERIFY, '-', "Don't verify signers certificate"}, + {"nocerts", OPT_NOCERTS, '-', + "Don't include signers certificate when signing"}, + {"nodetach", OPT_NODETACH, '-', "Use opaque signing"}, + {"noattr", OPT_NOATTR, '-', "Don't include any signed attributes"}, + {"binary", OPT_BINARY, '-', "Don't translate message to text"}, + {"certfile", OPT_CERTFILE, '<', "Other certificates file"}, + {"signer", OPT_SIGNER, 's', "Signer certificate file"}, + {"recip", OPT_RECIP, '<', "Recipient certificate file for decryption"}, + {"in", OPT_IN, '<', "Input file"}, + {"inform", OPT_INFORM, 'c', "Input format SMIME (default), PEM or DER"}, + {"inkey", OPT_INKEY, 's', + "Input private key (if not signer or recipient)"}, + {"keyform", OPT_KEYFORM, 'f', "Input private key format (PEM or ENGINE)"}, + {"out", OPT_OUT, '>', "Output file"}, + {"outform", OPT_OUTFORM, 'c', + "Output format SMIME (default), PEM or DER"}, + {"content", OPT_CONTENT, '<', + "Supply or override content for detached signature"}, + {"to", OPT_TO, 's', "To address"}, + {"from", OPT_FROM, 's', "From address"}, + {"subject", OPT_SUBJECT, 's', "Subject"}, + {"text", OPT_TEXT, '-', "Include or delete text MIME headers"}, + {"CApath", OPT_CAPATH, '/', "Trusted certificates directory"}, + {"CAfile", OPT_CAFILE, '<', "Trusted certificates file"}, + {"no-CAfile", OPT_NOCAFILE, '-', + "Do not load the default certificates file"}, + {"no-CApath", OPT_NOCAPATH, '-', + "Do not load certificates from the default certificates directory"}, + {"resign", OPT_RESIGN, '-', "Resign a signed message"}, + {"nochain", OPT_NOCHAIN, '-', + "set PKCS7_NOCHAIN so certificates contained in the message are not used as untrusted CAs" }, + {"nosmimecap", OPT_NOSMIMECAP, '-', "Omit the SMIMECapabilities attribute"}, + {"stream", OPT_STREAM, '-', "Enable CMS streaming" }, + {"indef", OPT_INDEF, '-', "Same as -stream" }, + {"noindef", OPT_NOINDEF, '-', "Disable CMS streaming"}, + {"crlfeol", OPT_CRLFEOL, '-', "Use CRLF as EOL termination instead of CR only"}, + OPT_R_OPTIONS, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"md", OPT_MD, 's', "Digest algorithm to use when signing or resigning"}, + {"", OPT_CIPHER, '-', "Any supported cipher"}, + OPT_V_OPTIONS, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + {NULL} +}; + +int smime_main(int argc, char **argv) +{ + BIO *in = NULL, *out = NULL, *indata = NULL; + EVP_PKEY *key = NULL; + PKCS7 *p7 = NULL; + STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL; + STACK_OF(X509) *encerts = NULL, *other = NULL; + X509 *cert = NULL, *recip = NULL, *signer = NULL; + X509_STORE *store = NULL; + X509_VERIFY_PARAM *vpm = NULL; + const EVP_CIPHER *cipher = NULL; + const EVP_MD *sign_md = NULL; + const char *CAfile = NULL, *CApath = NULL, *prog = NULL; + char *certfile = NULL, *keyfile = NULL, *contfile = NULL; + char *infile = NULL, *outfile = NULL, *signerfile = NULL, *recipfile = NULL; + char *passinarg = NULL, *passin = NULL, *to = NULL, *from = NULL, *subject = NULL; + OPTION_CHOICE o; + int noCApath = 0, noCAfile = 0; + int flags = PKCS7_DETACHED, operation = 0, ret = 0, indef = 0; + int informat = FORMAT_SMIME, outformat = FORMAT_SMIME, keyform = + FORMAT_PEM; + int vpmtouched = 0, rv = 0; + ENGINE *e = NULL; + const char *mime_eol = "\n"; + + if ((vpm = X509_VERIFY_PARAM_new()) == NULL) + return 1; + + prog = opt_init(argc, argv, smime_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(smime_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_PDS, &informat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PDS, &outformat)) + goto opthelp; + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_ENCRYPT: + operation = SMIME_ENCRYPT; + break; + case OPT_DECRYPT: + operation = SMIME_DECRYPT; + break; + case OPT_SIGN: + operation = SMIME_SIGN; + break; + case OPT_RESIGN: + operation = SMIME_RESIGN; + break; + case OPT_VERIFY: + operation = SMIME_VERIFY; + break; + case OPT_PK7OUT: + operation = SMIME_PK7OUT; + break; + case OPT_TEXT: + flags |= PKCS7_TEXT; + break; + case OPT_NOINTERN: + flags |= PKCS7_NOINTERN; + break; + case OPT_NOVERIFY: + flags |= PKCS7_NOVERIFY; + break; + case OPT_NOCHAIN: + flags |= PKCS7_NOCHAIN; + break; + case OPT_NOCERTS: + flags |= PKCS7_NOCERTS; + break; + case OPT_NOATTR: + flags |= PKCS7_NOATTR; + break; + case OPT_NODETACH: + flags &= ~PKCS7_DETACHED; + break; + case OPT_NOSMIMECAP: + flags |= PKCS7_NOSMIMECAP; + break; + case OPT_BINARY: + flags |= PKCS7_BINARY; + break; + case OPT_NOSIGS: + flags |= PKCS7_NOSIGS; + break; + case OPT_STREAM: + case OPT_INDEF: + indef = 1; + break; + case OPT_NOINDEF: + indef = 0; + break; + case OPT_CRLFEOL: + flags |= PKCS7_CRLFEOL; + mime_eol = "\r\n"; + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_TO: + to = opt_arg(); + break; + case OPT_FROM: + from = opt_arg(); + break; + case OPT_SUBJECT: + subject = opt_arg(); + break; + case OPT_SIGNER: + /* If previous -signer argument add signer to list */ + if (signerfile != NULL) { + if (sksigners == NULL + && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; + sk_OPENSSL_STRING_push(sksigners, signerfile); + if (keyfile == NULL) + keyfile = signerfile; + if (skkeys == NULL + && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; + sk_OPENSSL_STRING_push(skkeys, keyfile); + keyfile = NULL; + } + signerfile = opt_arg(); + break; + case OPT_RECIP: + recipfile = opt_arg(); + break; + case OPT_MD: + if (!opt_md(opt_arg(), &sign_md)) + goto opthelp; + break; + case OPT_CIPHER: + if (!opt_cipher(opt_unknown(), &cipher)) + goto opthelp; + break; + case OPT_INKEY: + /* If previous -inkey argument add signer to list */ + if (keyfile != NULL) { + if (signerfile == NULL) { + BIO_printf(bio_err, + "%s: Must have -signer before -inkey\n", prog); + goto opthelp; + } + if (sksigners == NULL + && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; + sk_OPENSSL_STRING_push(sksigners, signerfile); + signerfile = NULL; + if (skkeys == NULL + && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; + sk_OPENSSL_STRING_push(skkeys, keyfile); + } + keyfile = opt_arg(); + break; + case OPT_KEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform)) + goto opthelp; + break; + case OPT_CERTFILE: + certfile = opt_arg(); + break; + case OPT_CAFILE: + CAfile = opt_arg(); + break; + case OPT_CAPATH: + CApath = opt_arg(); + break; + case OPT_NOCAFILE: + noCAfile = 1; + break; + case OPT_NOCAPATH: + noCApath = 1; + break; + case OPT_CONTENT: + contfile = opt_arg(); + break; + case OPT_V_CASES: + if (!opt_verify(o, vpm)) + goto opthelp; + vpmtouched++; + break; + } + } + argc = opt_num_rest(); + argv = opt_rest(); + + if (!(operation & SMIME_SIGNERS) && (skkeys != NULL || sksigners != NULL)) { + BIO_puts(bio_err, "Multiple signers or keys not allowed\n"); + goto opthelp; + } + + if (operation & SMIME_SIGNERS) { + /* Check to see if any final signer needs to be appended */ + if (keyfile && !signerfile) { + BIO_puts(bio_err, "Illegal -inkey without -signer\n"); + goto opthelp; + } + if (signerfile != NULL) { + if (sksigners == NULL + && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; + sk_OPENSSL_STRING_push(sksigners, signerfile); + if (!skkeys && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; + if (!keyfile) + keyfile = signerfile; + sk_OPENSSL_STRING_push(skkeys, keyfile); + } + if (sksigners == NULL) { + BIO_printf(bio_err, "No signer certificate specified\n"); + goto opthelp; + } + signerfile = NULL; + keyfile = NULL; + } else if (operation == SMIME_DECRYPT) { + if (recipfile == NULL && keyfile == NULL) { + BIO_printf(bio_err, + "No recipient certificate or key specified\n"); + goto opthelp; + } + } else if (operation == SMIME_ENCRYPT) { + if (argc == 0) { + BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n"); + goto opthelp; + } + } else if (!operation) { + goto opthelp; + } + + if (!app_passwd(passinarg, NULL, &passin, NULL)) { + BIO_printf(bio_err, "Error getting password\n"); + goto end; + } + + ret = 2; + + if (!(operation & SMIME_SIGNERS)) + flags &= ~PKCS7_DETACHED; + + if (!(operation & SMIME_OP)) { + if (flags & PKCS7_BINARY) + outformat = FORMAT_BINARY; + } + + if (!(operation & SMIME_IP)) { + if (flags & PKCS7_BINARY) + informat = FORMAT_BINARY; + } + + if (operation == SMIME_ENCRYPT) { + if (cipher == NULL) { +#ifndef OPENSSL_NO_DES + cipher = EVP_des_ede3_cbc(); +#else + BIO_printf(bio_err, "No cipher selected\n"); + goto end; +#endif + } + encerts = sk_X509_new_null(); + if (encerts == NULL) + goto end; + while (*argv != NULL) { + cert = load_cert(*argv, FORMAT_PEM, + "recipient certificate file"); + if (cert == NULL) + goto end; + sk_X509_push(encerts, cert); + cert = NULL; + argv++; + } + } + + if (certfile != NULL) { + if (!load_certs(certfile, &other, FORMAT_PEM, NULL, + "certificate file")) { + ERR_print_errors(bio_err); + goto end; + } + } + + if (recipfile != NULL && (operation == SMIME_DECRYPT)) { + if ((recip = load_cert(recipfile, FORMAT_PEM, + "recipient certificate file")) == NULL) { + ERR_print_errors(bio_err); + goto end; + } + } + + if (operation == SMIME_DECRYPT) { + if (keyfile == NULL) + keyfile = recipfile; + } else if (operation == SMIME_SIGN) { + if (keyfile == NULL) + keyfile = signerfile; + } else { + keyfile = NULL; + } + + if (keyfile != NULL) { + key = load_key(keyfile, keyform, 0, passin, e, "signing key file"); + if (key == NULL) + goto end; + } + + in = bio_open_default(infile, 'r', informat); + if (in == NULL) + goto end; + + if (operation & SMIME_IP) { + if (informat == FORMAT_SMIME) { + p7 = SMIME_read_PKCS7(in, &indata); + } else if (informat == FORMAT_PEM) { + p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL); + } else if (informat == FORMAT_ASN1) { + p7 = d2i_PKCS7_bio(in, NULL); + } else { + BIO_printf(bio_err, "Bad input format for PKCS#7 file\n"); + goto end; + } + + if (p7 == NULL) { + BIO_printf(bio_err, "Error reading S/MIME message\n"); + goto end; + } + if (contfile != NULL) { + BIO_free(indata); + if ((indata = BIO_new_file(contfile, "rb")) == NULL) { + BIO_printf(bio_err, "Can't read content file %s\n", contfile); + goto end; + } + } + } + + out = bio_open_default(outfile, 'w', outformat); + if (out == NULL) + goto end; + + if (operation == SMIME_VERIFY) { + if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL) + goto end; + X509_STORE_set_verify_cb(store, smime_cb); + if (vpmtouched) + X509_STORE_set1_param(store, vpm); + } + + ret = 3; + + if (operation == SMIME_ENCRYPT) { + if (indef) + flags |= PKCS7_STREAM; + p7 = PKCS7_encrypt(encerts, in, cipher, flags); + } else if (operation & SMIME_SIGNERS) { + int i; + /* + * If detached data content we only enable streaming if S/MIME output + * format. + */ + if (operation == SMIME_SIGN) { + if (flags & PKCS7_DETACHED) { + if (outformat == FORMAT_SMIME) + flags |= PKCS7_STREAM; + } else if (indef) { + flags |= PKCS7_STREAM; + } + flags |= PKCS7_PARTIAL; + p7 = PKCS7_sign(NULL, NULL, other, in, flags); + if (p7 == NULL) + goto end; + if (flags & PKCS7_NOCERTS) { + for (i = 0; i < sk_X509_num(other); i++) { + X509 *x = sk_X509_value(other, i); + PKCS7_add_certificate(p7, x); + } + } + } else { + flags |= PKCS7_REUSE_DIGEST; + } + for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) { + signerfile = sk_OPENSSL_STRING_value(sksigners, i); + keyfile = sk_OPENSSL_STRING_value(skkeys, i); + signer = load_cert(signerfile, FORMAT_PEM, + "signer certificate"); + if (signer == NULL) + goto end; + key = load_key(keyfile, keyform, 0, passin, e, "signing key file"); + if (key == NULL) + goto end; + if (!PKCS7_sign_add_signer(p7, signer, key, sign_md, flags)) + goto end; + X509_free(signer); + signer = NULL; + EVP_PKEY_free(key); + key = NULL; + } + /* If not streaming or resigning finalize structure */ + if ((operation == SMIME_SIGN) && !(flags & PKCS7_STREAM)) { + if (!PKCS7_final(p7, in, flags)) + goto end; + } + } + + if (p7 == NULL) { + BIO_printf(bio_err, "Error creating PKCS#7 structure\n"); + goto end; + } + + ret = 4; + if (operation == SMIME_DECRYPT) { + if (!PKCS7_decrypt(p7, key, recip, out, flags)) { + BIO_printf(bio_err, "Error decrypting PKCS#7 structure\n"); + goto end; + } + } else if (operation == SMIME_VERIFY) { + STACK_OF(X509) *signers; + if (PKCS7_verify(p7, other, store, indata, out, flags)) + BIO_printf(bio_err, "Verification successful\n"); + else { + BIO_printf(bio_err, "Verification failure\n"); + goto end; + } + signers = PKCS7_get0_signers(p7, other, flags); + if (!save_certs(signerfile, signers)) { + BIO_printf(bio_err, "Error writing signers to %s\n", signerfile); + ret = 5; + goto end; + } + sk_X509_free(signers); + } else if (operation == SMIME_PK7OUT) { + PEM_write_bio_PKCS7(out, p7); + } else { + if (to) + BIO_printf(out, "To: %s%s", to, mime_eol); + if (from) + BIO_printf(out, "From: %s%s", from, mime_eol); + if (subject) + BIO_printf(out, "Subject: %s%s", subject, mime_eol); + if (outformat == FORMAT_SMIME) { + if (operation == SMIME_RESIGN) + rv = SMIME_write_PKCS7(out, p7, indata, flags); + else + rv = SMIME_write_PKCS7(out, p7, in, flags); + } else if (outformat == FORMAT_PEM) { + rv = PEM_write_bio_PKCS7_stream(out, p7, in, flags); + } else if (outformat == FORMAT_ASN1) { + rv = i2d_PKCS7_bio_stream(out, p7, in, flags); + } else { + BIO_printf(bio_err, "Bad output format for PKCS#7 file\n"); + goto end; + } + if (rv == 0) { + BIO_printf(bio_err, "Error writing output\n"); + ret = 3; + goto end; + } + } + ret = 0; + end: + if (ret) + ERR_print_errors(bio_err); + sk_X509_pop_free(encerts, X509_free); + sk_X509_pop_free(other, X509_free); + X509_VERIFY_PARAM_free(vpm); + sk_OPENSSL_STRING_free(sksigners); + sk_OPENSSL_STRING_free(skkeys); + X509_STORE_free(store); + X509_free(cert); + X509_free(recip); + X509_free(signer); + EVP_PKEY_free(key); + PKCS7_free(p7); + release_engine(e); + BIO_free(in); + BIO_free(indata); + BIO_free_all(out); + OPENSSL_free(passin); + return ret; +} + +static int save_certs(char *signerfile, STACK_OF(X509) *signers) +{ + int i; + BIO *tmp; + + if (signerfile == NULL) + return 1; + tmp = BIO_new_file(signerfile, "w"); + if (tmp == NULL) + return 0; + for (i = 0; i < sk_X509_num(signers); i++) + PEM_write_bio_X509(tmp, sk_X509_value(signers, i)); + BIO_free(tmp); + return 1; +} + +/* Minimal callback just to output policy info (if any) */ + +static int smime_cb(int ok, X509_STORE_CTX *ctx) +{ + int error; + + error = X509_STORE_CTX_get_error(ctx); + + if ((error != X509_V_ERR_NO_EXPLICIT_POLICY) + && ((error != X509_V_OK) || (ok != 2))) + return ok; + + policies_print(ctx); + + return ok; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/speed.c b/trunk/3rdparty/openssl-1.1-fit/apps/speed.c new file mode 100644 index 000000000..506737d05 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/speed.c @@ -0,0 +1,3691 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#undef SECONDS +#define SECONDS 3 +#define RSA_SECONDS 10 +#define DSA_SECONDS 10 +#define ECDSA_SECONDS 10 +#define ECDH_SECONDS 10 +#define EdDSA_SECONDS 10 + +#include +#include +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include +#include +#include +#if !defined(OPENSSL_SYS_MSDOS) +# include OPENSSL_UNISTD +#endif + +#if defined(_WIN32) +# include +#endif + +#include +#ifndef OPENSSL_NO_DES +# include +#endif +#include +#ifndef OPENSSL_NO_CAMELLIA +# include +#endif +#ifndef OPENSSL_NO_MD2 +# include +#endif +#ifndef OPENSSL_NO_MDC2 +# include +#endif +#ifndef OPENSSL_NO_MD4 +# include +#endif +#ifndef OPENSSL_NO_MD5 +# include +#endif +#include +#include +#ifndef OPENSSL_NO_RMD160 +# include +#endif +#ifndef OPENSSL_NO_WHIRLPOOL +# include +#endif +#ifndef OPENSSL_NO_RC4 +# include +#endif +#ifndef OPENSSL_NO_RC5 +# include +#endif +#ifndef OPENSSL_NO_RC2 +# include +#endif +#ifndef OPENSSL_NO_IDEA +# include +#endif +#ifndef OPENSSL_NO_SEED +# include +#endif +#ifndef OPENSSL_NO_BF +# include +#endif +#ifndef OPENSSL_NO_CAST +# include +#endif +#ifndef OPENSSL_NO_RSA +# include +# include "./testrsa.h" +#endif +#include +#ifndef OPENSSL_NO_DSA +# include +# include "./testdsa.h" +#endif +#ifndef OPENSSL_NO_EC +# include +#endif +#include + +#ifndef HAVE_FORK +# if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_VXWORKS) +# define HAVE_FORK 0 +# else +# define HAVE_FORK 1 +# endif +#endif + +#if HAVE_FORK +# undef NO_FORK +#else +# define NO_FORK +#endif + +#define MAX_MISALIGNMENT 63 +#define MAX_ECDH_SIZE 256 +#define MISALIGN 64 + +typedef struct openssl_speed_sec_st { + int sym; + int rsa; + int dsa; + int ecdsa; + int ecdh; + int eddsa; +} openssl_speed_sec_t; + +static volatile int run = 0; + +static int mr = 0; +static int usertime = 1; + +#ifndef OPENSSL_NO_MD2 +static int EVP_Digest_MD2_loop(void *args); +#endif + +#ifndef OPENSSL_NO_MDC2 +static int EVP_Digest_MDC2_loop(void *args); +#endif +#ifndef OPENSSL_NO_MD4 +static int EVP_Digest_MD4_loop(void *args); +#endif +#ifndef OPENSSL_NO_MD5 +static int MD5_loop(void *args); +static int HMAC_loop(void *args); +#endif +static int SHA1_loop(void *args); +static int SHA256_loop(void *args); +static int SHA512_loop(void *args); +#ifndef OPENSSL_NO_WHIRLPOOL +static int WHIRLPOOL_loop(void *args); +#endif +#ifndef OPENSSL_NO_RMD160 +static int EVP_Digest_RMD160_loop(void *args); +#endif +#ifndef OPENSSL_NO_RC4 +static int RC4_loop(void *args); +#endif +#ifndef OPENSSL_NO_DES +static int DES_ncbc_encrypt_loop(void *args); +static int DES_ede3_cbc_encrypt_loop(void *args); +#endif +static int AES_cbc_128_encrypt_loop(void *args); +static int AES_cbc_192_encrypt_loop(void *args); +static int AES_ige_128_encrypt_loop(void *args); +static int AES_cbc_256_encrypt_loop(void *args); +static int AES_ige_192_encrypt_loop(void *args); +static int AES_ige_256_encrypt_loop(void *args); +static int CRYPTO_gcm128_aad_loop(void *args); +static int RAND_bytes_loop(void *args); +static int EVP_Update_loop(void *args); +static int EVP_Update_loop_ccm(void *args); +static int EVP_Update_loop_aead(void *args); +static int EVP_Digest_loop(void *args); +#ifndef OPENSSL_NO_RSA +static int RSA_sign_loop(void *args); +static int RSA_verify_loop(void *args); +#endif +#ifndef OPENSSL_NO_DSA +static int DSA_sign_loop(void *args); +static int DSA_verify_loop(void *args); +#endif +#ifndef OPENSSL_NO_EC +static int ECDSA_sign_loop(void *args); +static int ECDSA_verify_loop(void *args); +static int EdDSA_sign_loop(void *args); +static int EdDSA_verify_loop(void *args); +#endif + +static double Time_F(int s); +static void print_message(const char *s, long num, int length, int tm); +static void pkey_print_message(const char *str, const char *str2, + long num, unsigned int bits, int sec); +static void print_result(int alg, int run_no, int count, double time_used); +#ifndef NO_FORK +static int do_multi(int multi, int size_num); +#endif + +static const int lengths_list[] = { + 16, 64, 256, 1024, 8 * 1024, 16 * 1024 +}; +static const int *lengths = lengths_list; + +static const int aead_lengths_list[] = { + 2, 31, 136, 1024, 8 * 1024, 16 * 1024 +}; + +#define START 0 +#define STOP 1 + +#ifdef SIGALRM + +static void alarmed(int sig) +{ + signal(SIGALRM, alarmed); + run = 0; +} + +static double Time_F(int s) +{ + double ret = app_tminterval(s, usertime); + if (s == STOP) + alarm(0); + return ret; +} + +#elif defined(_WIN32) + +# define SIGALRM -1 + +static unsigned int lapse; +static volatile unsigned int schlock; +static void alarm_win32(unsigned int secs) +{ + lapse = secs * 1000; +} + +# define alarm alarm_win32 + +static DWORD WINAPI sleepy(VOID * arg) +{ + schlock = 1; + Sleep(lapse); + run = 0; + return 0; +} + +static double Time_F(int s) +{ + double ret; + static HANDLE thr; + + if (s == START) { + schlock = 0; + thr = CreateThread(NULL, 4096, sleepy, NULL, 0, NULL); + if (thr == NULL) { + DWORD err = GetLastError(); + BIO_printf(bio_err, "unable to CreateThread (%lu)", err); + ExitProcess(err); + } + while (!schlock) + Sleep(0); /* scheduler spinlock */ + ret = app_tminterval(s, usertime); + } else { + ret = app_tminterval(s, usertime); + if (run) + TerminateThread(thr, 0); + CloseHandle(thr); + } + + return ret; +} +#else +static double Time_F(int s) +{ + return app_tminterval(s, usertime); +} +#endif + +static void multiblock_speed(const EVP_CIPHER *evp_cipher, int lengths_single, + const openssl_speed_sec_t *seconds); + +#define found(value, pairs, result)\ + opt_found(value, result, pairs, OSSL_NELEM(pairs)) +static int opt_found(const char *name, unsigned int *result, + const OPT_PAIR pairs[], unsigned int nbelem) +{ + unsigned int idx; + + for (idx = 0; idx < nbelem; ++idx, pairs++) + if (strcmp(name, pairs->name) == 0) { + *result = pairs->retval; + return 1; + } + return 0; +} + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_ELAPSED, OPT_EVP, OPT_DECRYPT, OPT_ENGINE, OPT_MULTI, + OPT_MR, OPT_MB, OPT_MISALIGN, OPT_ASYNCJOBS, OPT_R_ENUM, + OPT_PRIMES, OPT_SECONDS, OPT_BYTES, OPT_AEAD +} OPTION_CHOICE; + +const OPTIONS speed_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] ciphers...\n"}, + {OPT_HELP_STR, 1, '-', "Valid options are:\n"}, + {"help", OPT_HELP, '-', "Display this summary"}, + {"evp", OPT_EVP, 's', "Use EVP-named cipher or digest"}, + {"decrypt", OPT_DECRYPT, '-', + "Time decryption instead of encryption (only EVP)"}, + {"aead", OPT_AEAD, '-', + "Benchmark EVP-named AEAD cipher in TLS-like sequence"}, + {"mb", OPT_MB, '-', + "Enable (tls1>=1) multi-block mode on EVP-named cipher"}, + {"mr", OPT_MR, '-', "Produce machine readable output"}, +#ifndef NO_FORK + {"multi", OPT_MULTI, 'p', "Run benchmarks in parallel"}, +#endif +#ifndef OPENSSL_NO_ASYNC + {"async_jobs", OPT_ASYNCJOBS, 'p', + "Enable async mode and start specified number of jobs"}, +#endif + OPT_R_OPTIONS, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + {"elapsed", OPT_ELAPSED, '-', + "Use wall-clock time instead of CPU user time as divisor"}, + {"primes", OPT_PRIMES, 'p', "Specify number of primes (for RSA only)"}, + {"seconds", OPT_SECONDS, 'p', + "Run benchmarks for specified amount of seconds"}, + {"bytes", OPT_BYTES, 'p', + "Run [non-PKI] benchmarks on custom-sized buffer"}, + {"misalign", OPT_MISALIGN, 'p', + "Use specified offset to mis-align buffers"}, + {NULL} +}; + +#define D_MD2 0 +#define D_MDC2 1 +#define D_MD4 2 +#define D_MD5 3 +#define D_HMAC 4 +#define D_SHA1 5 +#define D_RMD160 6 +#define D_RC4 7 +#define D_CBC_DES 8 +#define D_EDE3_DES 9 +#define D_CBC_IDEA 10 +#define D_CBC_SEED 11 +#define D_CBC_RC2 12 +#define D_CBC_RC5 13 +#define D_CBC_BF 14 +#define D_CBC_CAST 15 +#define D_CBC_128_AES 16 +#define D_CBC_192_AES 17 +#define D_CBC_256_AES 18 +#define D_CBC_128_CML 19 +#define D_CBC_192_CML 20 +#define D_CBC_256_CML 21 +#define D_EVP 22 +#define D_SHA256 23 +#define D_SHA512 24 +#define D_WHIRLPOOL 25 +#define D_IGE_128_AES 26 +#define D_IGE_192_AES 27 +#define D_IGE_256_AES 28 +#define D_GHASH 29 +#define D_RAND 30 +/* name of algorithms to test */ +static const char *names[] = { + "md2", "mdc2", "md4", "md5", "hmac(md5)", "sha1", "rmd160", "rc4", + "des cbc", "des ede3", "idea cbc", "seed cbc", + "rc2 cbc", "rc5-32/12 cbc", "blowfish cbc", "cast cbc", + "aes-128 cbc", "aes-192 cbc", "aes-256 cbc", + "camellia-128 cbc", "camellia-192 cbc", "camellia-256 cbc", + "evp", "sha256", "sha512", "whirlpool", + "aes-128 ige", "aes-192 ige", "aes-256 ige", "ghash", + "rand" +}; +#define ALGOR_NUM OSSL_NELEM(names) + +/* list of configured algorithm (remaining) */ +static const OPT_PAIR doit_choices[] = { +#ifndef OPENSSL_NO_MD2 + {"md2", D_MD2}, +#endif +#ifndef OPENSSL_NO_MDC2 + {"mdc2", D_MDC2}, +#endif +#ifndef OPENSSL_NO_MD4 + {"md4", D_MD4}, +#endif +#ifndef OPENSSL_NO_MD5 + {"md5", D_MD5}, + {"hmac", D_HMAC}, +#endif + {"sha1", D_SHA1}, + {"sha256", D_SHA256}, + {"sha512", D_SHA512}, +#ifndef OPENSSL_NO_WHIRLPOOL + {"whirlpool", D_WHIRLPOOL}, +#endif +#ifndef OPENSSL_NO_RMD160 + {"ripemd", D_RMD160}, + {"rmd160", D_RMD160}, + {"ripemd160", D_RMD160}, +#endif +#ifndef OPENSSL_NO_RC4 + {"rc4", D_RC4}, +#endif +#ifndef OPENSSL_NO_DES + {"des-cbc", D_CBC_DES}, + {"des-ede3", D_EDE3_DES}, +#endif + {"aes-128-cbc", D_CBC_128_AES}, + {"aes-192-cbc", D_CBC_192_AES}, + {"aes-256-cbc", D_CBC_256_AES}, + {"aes-128-ige", D_IGE_128_AES}, + {"aes-192-ige", D_IGE_192_AES}, + {"aes-256-ige", D_IGE_256_AES}, +#ifndef OPENSSL_NO_RC2 + {"rc2-cbc", D_CBC_RC2}, + {"rc2", D_CBC_RC2}, +#endif +#ifndef OPENSSL_NO_RC5 + {"rc5-cbc", D_CBC_RC5}, + {"rc5", D_CBC_RC5}, +#endif +#ifndef OPENSSL_NO_IDEA + {"idea-cbc", D_CBC_IDEA}, + {"idea", D_CBC_IDEA}, +#endif +#ifndef OPENSSL_NO_SEED + {"seed-cbc", D_CBC_SEED}, + {"seed", D_CBC_SEED}, +#endif +#ifndef OPENSSL_NO_BF + {"bf-cbc", D_CBC_BF}, + {"blowfish", D_CBC_BF}, + {"bf", D_CBC_BF}, +#endif +#ifndef OPENSSL_NO_CAST + {"cast-cbc", D_CBC_CAST}, + {"cast", D_CBC_CAST}, + {"cast5", D_CBC_CAST}, +#endif + {"ghash", D_GHASH}, + {"rand", D_RAND} +}; + +static double results[ALGOR_NUM][OSSL_NELEM(lengths_list)]; + +#ifndef OPENSSL_NO_DSA +# define R_DSA_512 0 +# define R_DSA_1024 1 +# define R_DSA_2048 2 +static const OPT_PAIR dsa_choices[] = { + {"dsa512", R_DSA_512}, + {"dsa1024", R_DSA_1024}, + {"dsa2048", R_DSA_2048} +}; +# define DSA_NUM OSSL_NELEM(dsa_choices) + +static double dsa_results[DSA_NUM][2]; /* 2 ops: sign then verify */ +#endif /* OPENSSL_NO_DSA */ + +#define R_RSA_512 0 +#define R_RSA_1024 1 +#define R_RSA_2048 2 +#define R_RSA_3072 3 +#define R_RSA_4096 4 +#define R_RSA_7680 5 +#define R_RSA_15360 6 +#ifndef OPENSSL_NO_RSA +static const OPT_PAIR rsa_choices[] = { + {"rsa512", R_RSA_512}, + {"rsa1024", R_RSA_1024}, + {"rsa2048", R_RSA_2048}, + {"rsa3072", R_RSA_3072}, + {"rsa4096", R_RSA_4096}, + {"rsa7680", R_RSA_7680}, + {"rsa15360", R_RSA_15360} +}; +# define RSA_NUM OSSL_NELEM(rsa_choices) + +static double rsa_results[RSA_NUM][2]; /* 2 ops: sign then verify */ +#endif /* OPENSSL_NO_RSA */ + +#define R_EC_P160 0 +#define R_EC_P192 1 +#define R_EC_P224 2 +#define R_EC_P256 3 +#define R_EC_P384 4 +#define R_EC_P521 5 +#define R_EC_K163 6 +#define R_EC_K233 7 +#define R_EC_K283 8 +#define R_EC_K409 9 +#define R_EC_K571 10 +#define R_EC_B163 11 +#define R_EC_B233 12 +#define R_EC_B283 13 +#define R_EC_B409 14 +#define R_EC_B571 15 +#define R_EC_BRP256R1 16 +#define R_EC_BRP256T1 17 +#define R_EC_BRP384R1 18 +#define R_EC_BRP384T1 19 +#define R_EC_BRP512R1 20 +#define R_EC_BRP512T1 21 +#define R_EC_X25519 22 +#define R_EC_X448 23 +#ifndef OPENSSL_NO_EC +static OPT_PAIR ecdsa_choices[] = { + {"ecdsap160", R_EC_P160}, + {"ecdsap192", R_EC_P192}, + {"ecdsap224", R_EC_P224}, + {"ecdsap256", R_EC_P256}, + {"ecdsap384", R_EC_P384}, + {"ecdsap521", R_EC_P521}, + {"ecdsak163", R_EC_K163}, + {"ecdsak233", R_EC_K233}, + {"ecdsak283", R_EC_K283}, + {"ecdsak409", R_EC_K409}, + {"ecdsak571", R_EC_K571}, + {"ecdsab163", R_EC_B163}, + {"ecdsab233", R_EC_B233}, + {"ecdsab283", R_EC_B283}, + {"ecdsab409", R_EC_B409}, + {"ecdsab571", R_EC_B571}, + {"ecdsabrp256r1", R_EC_BRP256R1}, + {"ecdsabrp256t1", R_EC_BRP256T1}, + {"ecdsabrp384r1", R_EC_BRP384R1}, + {"ecdsabrp384t1", R_EC_BRP384T1}, + {"ecdsabrp512r1", R_EC_BRP512R1}, + {"ecdsabrp512t1", R_EC_BRP512T1} +}; +# define ECDSA_NUM OSSL_NELEM(ecdsa_choices) + +static double ecdsa_results[ECDSA_NUM][2]; /* 2 ops: sign then verify */ + +static const OPT_PAIR ecdh_choices[] = { + {"ecdhp160", R_EC_P160}, + {"ecdhp192", R_EC_P192}, + {"ecdhp224", R_EC_P224}, + {"ecdhp256", R_EC_P256}, + {"ecdhp384", R_EC_P384}, + {"ecdhp521", R_EC_P521}, + {"ecdhk163", R_EC_K163}, + {"ecdhk233", R_EC_K233}, + {"ecdhk283", R_EC_K283}, + {"ecdhk409", R_EC_K409}, + {"ecdhk571", R_EC_K571}, + {"ecdhb163", R_EC_B163}, + {"ecdhb233", R_EC_B233}, + {"ecdhb283", R_EC_B283}, + {"ecdhb409", R_EC_B409}, + {"ecdhb571", R_EC_B571}, + {"ecdhbrp256r1", R_EC_BRP256R1}, + {"ecdhbrp256t1", R_EC_BRP256T1}, + {"ecdhbrp384r1", R_EC_BRP384R1}, + {"ecdhbrp384t1", R_EC_BRP384T1}, + {"ecdhbrp512r1", R_EC_BRP512R1}, + {"ecdhbrp512t1", R_EC_BRP512T1}, + {"ecdhx25519", R_EC_X25519}, + {"ecdhx448", R_EC_X448} +}; +# define EC_NUM OSSL_NELEM(ecdh_choices) + +static double ecdh_results[EC_NUM][1]; /* 1 op: derivation */ + +#define R_EC_Ed25519 0 +#define R_EC_Ed448 1 +static OPT_PAIR eddsa_choices[] = { + {"ed25519", R_EC_Ed25519}, + {"ed448", R_EC_Ed448} +}; +# define EdDSA_NUM OSSL_NELEM(eddsa_choices) + +static double eddsa_results[EdDSA_NUM][2]; /* 2 ops: sign then verify */ +#endif /* OPENSSL_NO_EC */ + +#ifndef SIGALRM +# define COND(d) (count < (d)) +# define COUNT(d) (d) +#else +# define COND(unused_cond) (run && count<0x7fffffff) +# define COUNT(d) (count) +#endif /* SIGALRM */ + +typedef struct loopargs_st { + ASYNC_JOB *inprogress_job; + ASYNC_WAIT_CTX *wait_ctx; + unsigned char *buf; + unsigned char *buf2; + unsigned char *buf_malloc; + unsigned char *buf2_malloc; + unsigned char *key; + unsigned int siglen; + size_t sigsize; +#ifndef OPENSSL_NO_RSA + RSA *rsa_key[RSA_NUM]; +#endif +#ifndef OPENSSL_NO_DSA + DSA *dsa_key[DSA_NUM]; +#endif +#ifndef OPENSSL_NO_EC + EC_KEY *ecdsa[ECDSA_NUM]; + EVP_PKEY_CTX *ecdh_ctx[EC_NUM]; + EVP_MD_CTX *eddsa_ctx[EdDSA_NUM]; + unsigned char *secret_a; + unsigned char *secret_b; + size_t outlen[EC_NUM]; +#endif + EVP_CIPHER_CTX *ctx; + HMAC_CTX *hctx; + GCM128_CONTEXT *gcm_ctx; +} loopargs_t; +static int run_benchmark(int async_jobs, int (*loop_function) (void *), + loopargs_t * loopargs); + +static unsigned int testnum; + +/* Nb of iterations to do per algorithm and key-size */ +static long c[ALGOR_NUM][OSSL_NELEM(lengths_list)]; + +#ifndef OPENSSL_NO_MD2 +static int EVP_Digest_MD2_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + unsigned char md2[MD2_DIGEST_LENGTH]; + int count; + + for (count = 0; COND(c[D_MD2][testnum]); count++) { + if (!EVP_Digest(buf, (size_t)lengths[testnum], md2, NULL, EVP_md2(), + NULL)) + return -1; + } + return count; +} +#endif + +#ifndef OPENSSL_NO_MDC2 +static int EVP_Digest_MDC2_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + unsigned char mdc2[MDC2_DIGEST_LENGTH]; + int count; + + for (count = 0; COND(c[D_MDC2][testnum]); count++) { + if (!EVP_Digest(buf, (size_t)lengths[testnum], mdc2, NULL, EVP_mdc2(), + NULL)) + return -1; + } + return count; +} +#endif + +#ifndef OPENSSL_NO_MD4 +static int EVP_Digest_MD4_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + unsigned char md4[MD4_DIGEST_LENGTH]; + int count; + + for (count = 0; COND(c[D_MD4][testnum]); count++) { + if (!EVP_Digest(buf, (size_t)lengths[testnum], md4, NULL, EVP_md4(), + NULL)) + return -1; + } + return count; +} +#endif + +#ifndef OPENSSL_NO_MD5 +static int MD5_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + unsigned char md5[MD5_DIGEST_LENGTH]; + int count; + for (count = 0; COND(c[D_MD5][testnum]); count++) + MD5(buf, lengths[testnum], md5); + return count; +} + +static int HMAC_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + HMAC_CTX *hctx = tempargs->hctx; + unsigned char hmac[MD5_DIGEST_LENGTH]; + int count; + + for (count = 0; COND(c[D_HMAC][testnum]); count++) { + HMAC_Init_ex(hctx, NULL, 0, NULL, NULL); + HMAC_Update(hctx, buf, lengths[testnum]); + HMAC_Final(hctx, hmac, NULL); + } + return count; +} +#endif + +static int SHA1_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + unsigned char sha[SHA_DIGEST_LENGTH]; + int count; + for (count = 0; COND(c[D_SHA1][testnum]); count++) + SHA1(buf, lengths[testnum], sha); + return count; +} + +static int SHA256_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + unsigned char sha256[SHA256_DIGEST_LENGTH]; + int count; + for (count = 0; COND(c[D_SHA256][testnum]); count++) + SHA256(buf, lengths[testnum], sha256); + return count; +} + +static int SHA512_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + unsigned char sha512[SHA512_DIGEST_LENGTH]; + int count; + for (count = 0; COND(c[D_SHA512][testnum]); count++) + SHA512(buf, lengths[testnum], sha512); + return count; +} + +#ifndef OPENSSL_NO_WHIRLPOOL +static int WHIRLPOOL_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + unsigned char whirlpool[WHIRLPOOL_DIGEST_LENGTH]; + int count; + for (count = 0; COND(c[D_WHIRLPOOL][testnum]); count++) + WHIRLPOOL(buf, lengths[testnum], whirlpool); + return count; +} +#endif + +#ifndef OPENSSL_NO_RMD160 +static int EVP_Digest_RMD160_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + unsigned char rmd160[RIPEMD160_DIGEST_LENGTH]; + int count; + for (count = 0; COND(c[D_RMD160][testnum]); count++) { + if (!EVP_Digest(buf, (size_t)lengths[testnum], &(rmd160[0]), + NULL, EVP_ripemd160(), NULL)) + return -1; + } + return count; +} +#endif + +#ifndef OPENSSL_NO_RC4 +static RC4_KEY rc4_ks; +static int RC4_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + int count; + for (count = 0; COND(c[D_RC4][testnum]); count++) + RC4(&rc4_ks, (size_t)lengths[testnum], buf, buf); + return count; +} +#endif + +#ifndef OPENSSL_NO_DES +static unsigned char DES_iv[8]; +static DES_key_schedule sch; +static DES_key_schedule sch2; +static DES_key_schedule sch3; +static int DES_ncbc_encrypt_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + int count; + for (count = 0; COND(c[D_CBC_DES][testnum]); count++) + DES_ncbc_encrypt(buf, buf, lengths[testnum], &sch, + &DES_iv, DES_ENCRYPT); + return count; +} + +static int DES_ede3_cbc_encrypt_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + int count; + for (count = 0; COND(c[D_EDE3_DES][testnum]); count++) + DES_ede3_cbc_encrypt(buf, buf, lengths[testnum], + &sch, &sch2, &sch3, &DES_iv, DES_ENCRYPT); + return count; +} +#endif + +#define MAX_BLOCK_SIZE 128 + +static unsigned char iv[2 * MAX_BLOCK_SIZE / 8]; +static AES_KEY aes_ks1, aes_ks2, aes_ks3; +static int AES_cbc_128_encrypt_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + int count; + for (count = 0; COND(c[D_CBC_128_AES][testnum]); count++) + AES_cbc_encrypt(buf, buf, + (size_t)lengths[testnum], &aes_ks1, iv, AES_ENCRYPT); + return count; +} + +static int AES_cbc_192_encrypt_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + int count; + for (count = 0; COND(c[D_CBC_192_AES][testnum]); count++) + AES_cbc_encrypt(buf, buf, + (size_t)lengths[testnum], &aes_ks2, iv, AES_ENCRYPT); + return count; +} + +static int AES_cbc_256_encrypt_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + int count; + for (count = 0; COND(c[D_CBC_256_AES][testnum]); count++) + AES_cbc_encrypt(buf, buf, + (size_t)lengths[testnum], &aes_ks3, iv, AES_ENCRYPT); + return count; +} + +static int AES_ige_128_encrypt_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + unsigned char *buf2 = tempargs->buf2; + int count; + for (count = 0; COND(c[D_IGE_128_AES][testnum]); count++) + AES_ige_encrypt(buf, buf2, + (size_t)lengths[testnum], &aes_ks1, iv, AES_ENCRYPT); + return count; +} + +static int AES_ige_192_encrypt_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + unsigned char *buf2 = tempargs->buf2; + int count; + for (count = 0; COND(c[D_IGE_192_AES][testnum]); count++) + AES_ige_encrypt(buf, buf2, + (size_t)lengths[testnum], &aes_ks2, iv, AES_ENCRYPT); + return count; +} + +static int AES_ige_256_encrypt_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + unsigned char *buf2 = tempargs->buf2; + int count; + for (count = 0; COND(c[D_IGE_256_AES][testnum]); count++) + AES_ige_encrypt(buf, buf2, + (size_t)lengths[testnum], &aes_ks3, iv, AES_ENCRYPT); + return count; +} + +static int CRYPTO_gcm128_aad_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + GCM128_CONTEXT *gcm_ctx = tempargs->gcm_ctx; + int count; + for (count = 0; COND(c[D_GHASH][testnum]); count++) + CRYPTO_gcm128_aad(gcm_ctx, buf, lengths[testnum]); + return count; +} + +static int RAND_bytes_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + int count; + + for (count = 0; COND(c[D_RAND][testnum]); count++) + RAND_bytes(buf, lengths[testnum]); + return count; +} + +static long save_count = 0; +static int decrypt = 0; +static int EVP_Update_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + EVP_CIPHER_CTX *ctx = tempargs->ctx; + int outl, count, rc; +#ifndef SIGALRM + int nb_iter = save_count * 4 * lengths[0] / lengths[testnum]; +#endif + if (decrypt) { + for (count = 0; COND(nb_iter); count++) { + rc = EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]); + if (rc != 1) { + /* reset iv in case of counter overflow */ + EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, -1); + } + } + } else { + for (count = 0; COND(nb_iter); count++) { + rc = EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]); + if (rc != 1) { + /* reset iv in case of counter overflow */ + EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, -1); + } + } + } + if (decrypt) + EVP_DecryptFinal_ex(ctx, buf, &outl); + else + EVP_EncryptFinal_ex(ctx, buf, &outl); + return count; +} + +/* + * CCM does not support streaming. For the purpose of performance measurement, + * each message is encrypted using the same (key,iv)-pair. Do not use this + * code in your application. + */ +static int EVP_Update_loop_ccm(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + EVP_CIPHER_CTX *ctx = tempargs->ctx; + int outl, count; + unsigned char tag[12]; +#ifndef SIGALRM + int nb_iter = save_count * 4 * lengths[0] / lengths[testnum]; +#endif + if (decrypt) { + for (count = 0; COND(nb_iter); count++) { + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, sizeof(tag), tag); + /* reset iv */ + EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv); + /* counter is reset on every update */ + EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]); + } + } else { + for (count = 0; COND(nb_iter); count++) { + /* restore iv length field */ + EVP_EncryptUpdate(ctx, NULL, &outl, NULL, lengths[testnum]); + /* counter is reset on every update */ + EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]); + } + } + if (decrypt) + EVP_DecryptFinal_ex(ctx, buf, &outl); + else + EVP_EncryptFinal_ex(ctx, buf, &outl); + return count; +} + +/* + * To make AEAD benchmarking more relevant perform TLS-like operations, + * 13-byte AAD followed by payload. But don't use TLS-formatted AAD, as + * payload length is not actually limited by 16KB... + */ +static int EVP_Update_loop_aead(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + EVP_CIPHER_CTX *ctx = tempargs->ctx; + int outl, count; + unsigned char aad[13] = { 0xcc }; + unsigned char faketag[16] = { 0xcc }; +#ifndef SIGALRM + int nb_iter = save_count * 4 * lengths[0] / lengths[testnum]; +#endif + if (decrypt) { + for (count = 0; COND(nb_iter); count++) { + EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv); + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, + sizeof(faketag), faketag); + EVP_DecryptUpdate(ctx, NULL, &outl, aad, sizeof(aad)); + EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]); + EVP_DecryptFinal_ex(ctx, buf + outl, &outl); + } + } else { + for (count = 0; COND(nb_iter); count++) { + EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv); + EVP_EncryptUpdate(ctx, NULL, &outl, aad, sizeof(aad)); + EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]); + EVP_EncryptFinal_ex(ctx, buf + outl, &outl); + } + } + return count; +} + +static const EVP_MD *evp_md = NULL; +static int EVP_Digest_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + unsigned char md[EVP_MAX_MD_SIZE]; + int count; +#ifndef SIGALRM + int nb_iter = save_count * 4 * lengths[0] / lengths[testnum]; +#endif + + for (count = 0; COND(nb_iter); count++) { + if (!EVP_Digest(buf, lengths[testnum], md, NULL, evp_md, NULL)) + return -1; + } + return count; +} + +#ifndef OPENSSL_NO_RSA +static long rsa_c[RSA_NUM][2]; /* # RSA iteration test */ + +static int RSA_sign_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + unsigned char *buf2 = tempargs->buf2; + unsigned int *rsa_num = &tempargs->siglen; + RSA **rsa_key = tempargs->rsa_key; + int ret, count; + for (count = 0; COND(rsa_c[testnum][0]); count++) { + ret = RSA_sign(NID_md5_sha1, buf, 36, buf2, rsa_num, rsa_key[testnum]); + if (ret == 0) { + BIO_printf(bio_err, "RSA sign failure\n"); + ERR_print_errors(bio_err); + count = -1; + break; + } + } + return count; +} + +static int RSA_verify_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + unsigned char *buf2 = tempargs->buf2; + unsigned int rsa_num = tempargs->siglen; + RSA **rsa_key = tempargs->rsa_key; + int ret, count; + for (count = 0; COND(rsa_c[testnum][1]); count++) { + ret = + RSA_verify(NID_md5_sha1, buf, 36, buf2, rsa_num, rsa_key[testnum]); + if (ret <= 0) { + BIO_printf(bio_err, "RSA verify failure\n"); + ERR_print_errors(bio_err); + count = -1; + break; + } + } + return count; +} +#endif + +#ifndef OPENSSL_NO_DSA +static long dsa_c[DSA_NUM][2]; +static int DSA_sign_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + unsigned char *buf2 = tempargs->buf2; + DSA **dsa_key = tempargs->dsa_key; + unsigned int *siglen = &tempargs->siglen; + int ret, count; + for (count = 0; COND(dsa_c[testnum][0]); count++) { + ret = DSA_sign(0, buf, 20, buf2, siglen, dsa_key[testnum]); + if (ret == 0) { + BIO_printf(bio_err, "DSA sign failure\n"); + ERR_print_errors(bio_err); + count = -1; + break; + } + } + return count; +} + +static int DSA_verify_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + unsigned char *buf2 = tempargs->buf2; + DSA **dsa_key = tempargs->dsa_key; + unsigned int siglen = tempargs->siglen; + int ret, count; + for (count = 0; COND(dsa_c[testnum][1]); count++) { + ret = DSA_verify(0, buf, 20, buf2, siglen, dsa_key[testnum]); + if (ret <= 0) { + BIO_printf(bio_err, "DSA verify failure\n"); + ERR_print_errors(bio_err); + count = -1; + break; + } + } + return count; +} +#endif + +#ifndef OPENSSL_NO_EC +static long ecdsa_c[ECDSA_NUM][2]; +static int ECDSA_sign_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + EC_KEY **ecdsa = tempargs->ecdsa; + unsigned char *ecdsasig = tempargs->buf2; + unsigned int *ecdsasiglen = &tempargs->siglen; + int ret, count; + for (count = 0; COND(ecdsa_c[testnum][0]); count++) { + ret = ECDSA_sign(0, buf, 20, ecdsasig, ecdsasiglen, ecdsa[testnum]); + if (ret == 0) { + BIO_printf(bio_err, "ECDSA sign failure\n"); + ERR_print_errors(bio_err); + count = -1; + break; + } + } + return count; +} + +static int ECDSA_verify_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + EC_KEY **ecdsa = tempargs->ecdsa; + unsigned char *ecdsasig = tempargs->buf2; + unsigned int ecdsasiglen = tempargs->siglen; + int ret, count; + for (count = 0; COND(ecdsa_c[testnum][1]); count++) { + ret = ECDSA_verify(0, buf, 20, ecdsasig, ecdsasiglen, ecdsa[testnum]); + if (ret != 1) { + BIO_printf(bio_err, "ECDSA verify failure\n"); + ERR_print_errors(bio_err); + count = -1; + break; + } + } + return count; +} + +/* ******************************************************************** */ +static long ecdh_c[EC_NUM][1]; + +static int ECDH_EVP_derive_key_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + EVP_PKEY_CTX *ctx = tempargs->ecdh_ctx[testnum]; + unsigned char *derived_secret = tempargs->secret_a; + int count; + size_t *outlen = &(tempargs->outlen[testnum]); + + for (count = 0; COND(ecdh_c[testnum][0]); count++) + EVP_PKEY_derive(ctx, derived_secret, outlen); + + return count; +} + +static long eddsa_c[EdDSA_NUM][2]; +static int EdDSA_sign_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + EVP_MD_CTX **edctx = tempargs->eddsa_ctx; + unsigned char *eddsasig = tempargs->buf2; + size_t *eddsasigsize = &tempargs->sigsize; + int ret, count; + + for (count = 0; COND(eddsa_c[testnum][0]); count++) { + ret = EVP_DigestSign(edctx[testnum], eddsasig, eddsasigsize, buf, 20); + if (ret == 0) { + BIO_printf(bio_err, "EdDSA sign failure\n"); + ERR_print_errors(bio_err); + count = -1; + break; + } + } + return count; +} + +static int EdDSA_verify_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + EVP_MD_CTX **edctx = tempargs->eddsa_ctx; + unsigned char *eddsasig = tempargs->buf2; + size_t eddsasigsize = tempargs->sigsize; + int ret, count; + + for (count = 0; COND(eddsa_c[testnum][1]); count++) { + ret = EVP_DigestVerify(edctx[testnum], eddsasig, eddsasigsize, buf, 20); + if (ret != 1) { + BIO_printf(bio_err, "EdDSA verify failure\n"); + ERR_print_errors(bio_err); + count = -1; + break; + } + } + return count; +} +#endif /* OPENSSL_NO_EC */ + +static int run_benchmark(int async_jobs, + int (*loop_function) (void *), loopargs_t * loopargs) +{ + int job_op_count = 0; + int total_op_count = 0; + int num_inprogress = 0; + int error = 0, i = 0, ret = 0; + OSSL_ASYNC_FD job_fd = 0; + size_t num_job_fds = 0; + + run = 1; + + if (async_jobs == 0) { + return loop_function((void *)&loopargs); + } + + for (i = 0; i < async_jobs && !error; i++) { + loopargs_t *looparg_item = loopargs + i; + + /* Copy pointer content (looparg_t item address) into async context */ + ret = ASYNC_start_job(&loopargs[i].inprogress_job, loopargs[i].wait_ctx, + &job_op_count, loop_function, + (void *)&looparg_item, sizeof(looparg_item)); + switch (ret) { + case ASYNC_PAUSE: + ++num_inprogress; + break; + case ASYNC_FINISH: + if (job_op_count == -1) { + error = 1; + } else { + total_op_count += job_op_count; + } + break; + case ASYNC_NO_JOBS: + case ASYNC_ERR: + BIO_printf(bio_err, "Failure in the job\n"); + ERR_print_errors(bio_err); + error = 1; + break; + } + } + + while (num_inprogress > 0) { +#if defined(OPENSSL_SYS_WINDOWS) + DWORD avail = 0; +#elif defined(OPENSSL_SYS_UNIX) + int select_result = 0; + OSSL_ASYNC_FD max_fd = 0; + fd_set waitfdset; + + FD_ZERO(&waitfdset); + + for (i = 0; i < async_jobs && num_inprogress > 0; i++) { + if (loopargs[i].inprogress_job == NULL) + continue; + + if (!ASYNC_WAIT_CTX_get_all_fds + (loopargs[i].wait_ctx, NULL, &num_job_fds) + || num_job_fds > 1) { + BIO_printf(bio_err, "Too many fds in ASYNC_WAIT_CTX\n"); + ERR_print_errors(bio_err); + error = 1; + break; + } + ASYNC_WAIT_CTX_get_all_fds(loopargs[i].wait_ctx, &job_fd, + &num_job_fds); + FD_SET(job_fd, &waitfdset); + if (job_fd > max_fd) + max_fd = job_fd; + } + + if (max_fd >= (OSSL_ASYNC_FD)FD_SETSIZE) { + BIO_printf(bio_err, + "Error: max_fd (%d) must be smaller than FD_SETSIZE (%d). " + "Decrease the value of async_jobs\n", + max_fd, FD_SETSIZE); + ERR_print_errors(bio_err); + error = 1; + break; + } + + select_result = select(max_fd + 1, &waitfdset, NULL, NULL, NULL); + if (select_result == -1 && errno == EINTR) + continue; + + if (select_result == -1) { + BIO_printf(bio_err, "Failure in the select\n"); + ERR_print_errors(bio_err); + error = 1; + break; + } + + if (select_result == 0) + continue; +#endif + + for (i = 0; i < async_jobs; i++) { + if (loopargs[i].inprogress_job == NULL) + continue; + + if (!ASYNC_WAIT_CTX_get_all_fds + (loopargs[i].wait_ctx, NULL, &num_job_fds) + || num_job_fds > 1) { + BIO_printf(bio_err, "Too many fds in ASYNC_WAIT_CTX\n"); + ERR_print_errors(bio_err); + error = 1; + break; + } + ASYNC_WAIT_CTX_get_all_fds(loopargs[i].wait_ctx, &job_fd, + &num_job_fds); + +#if defined(OPENSSL_SYS_UNIX) + if (num_job_fds == 1 && !FD_ISSET(job_fd, &waitfdset)) + continue; +#elif defined(OPENSSL_SYS_WINDOWS) + if (num_job_fds == 1 + && !PeekNamedPipe(job_fd, NULL, 0, NULL, &avail, NULL) + && avail > 0) + continue; +#endif + + ret = ASYNC_start_job(&loopargs[i].inprogress_job, + loopargs[i].wait_ctx, &job_op_count, + loop_function, (void *)(loopargs + i), + sizeof(loopargs_t)); + switch (ret) { + case ASYNC_PAUSE: + break; + case ASYNC_FINISH: + if (job_op_count == -1) { + error = 1; + } else { + total_op_count += job_op_count; + } + --num_inprogress; + loopargs[i].inprogress_job = NULL; + break; + case ASYNC_NO_JOBS: + case ASYNC_ERR: + --num_inprogress; + loopargs[i].inprogress_job = NULL; + BIO_printf(bio_err, "Failure in the job\n"); + ERR_print_errors(bio_err); + error = 1; + break; + } + } + } + + return error ? -1 : total_op_count; +} + +int speed_main(int argc, char **argv) +{ + ENGINE *e = NULL; + loopargs_t *loopargs = NULL; + const char *prog; + const char *engine_id = NULL; + const EVP_CIPHER *evp_cipher = NULL; + double d = 0.0; + OPTION_CHOICE o; + int async_init = 0, multiblock = 0, pr_header = 0; + int doit[ALGOR_NUM] = { 0 }; + int ret = 1, misalign = 0, lengths_single = 0, aead = 0; + long count = 0; + unsigned int size_num = OSSL_NELEM(lengths_list); + unsigned int i, k, loop, loopargs_len = 0, async_jobs = 0; + int keylen; + int buflen; +#ifndef NO_FORK + int multi = 0; +#endif +#if !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_DSA) \ + || !defined(OPENSSL_NO_EC) + long rsa_count = 1; +#endif + openssl_speed_sec_t seconds = { SECONDS, RSA_SECONDS, DSA_SECONDS, + ECDSA_SECONDS, ECDH_SECONDS, + EdDSA_SECONDS }; + + /* What follows are the buffers and key material. */ +#ifndef OPENSSL_NO_RC5 + RC5_32_KEY rc5_ks; +#endif +#ifndef OPENSSL_NO_RC2 + RC2_KEY rc2_ks; +#endif +#ifndef OPENSSL_NO_IDEA + IDEA_KEY_SCHEDULE idea_ks; +#endif +#ifndef OPENSSL_NO_SEED + SEED_KEY_SCHEDULE seed_ks; +#endif +#ifndef OPENSSL_NO_BF + BF_KEY bf_ks; +#endif +#ifndef OPENSSL_NO_CAST + CAST_KEY cast_ks; +#endif + static const unsigned char key16[16] = { + 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, + 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12 + }; + static const unsigned char key24[24] = { + 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, + 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, + 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34 + }; + static const unsigned char key32[32] = { + 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, + 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, + 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, + 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56 + }; +#ifndef OPENSSL_NO_CAMELLIA + static const unsigned char ckey24[24] = { + 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, + 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, + 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34 + }; + static const unsigned char ckey32[32] = { + 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, + 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, + 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, + 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56 + }; + CAMELLIA_KEY camellia_ks1, camellia_ks2, camellia_ks3; +#endif +#ifndef OPENSSL_NO_DES + static DES_cblock key = { + 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 + }; + static DES_cblock key2 = { + 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12 + }; + static DES_cblock key3 = { + 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34 + }; +#endif +#ifndef OPENSSL_NO_RSA + static const unsigned int rsa_bits[RSA_NUM] = { + 512, 1024, 2048, 3072, 4096, 7680, 15360 + }; + static const unsigned char *rsa_data[RSA_NUM] = { + test512, test1024, test2048, test3072, test4096, test7680, test15360 + }; + static const int rsa_data_length[RSA_NUM] = { + sizeof(test512), sizeof(test1024), + sizeof(test2048), sizeof(test3072), + sizeof(test4096), sizeof(test7680), + sizeof(test15360) + }; + int rsa_doit[RSA_NUM] = { 0 }; + int primes = RSA_DEFAULT_PRIME_NUM; +#endif +#ifndef OPENSSL_NO_DSA + static const unsigned int dsa_bits[DSA_NUM] = { 512, 1024, 2048 }; + int dsa_doit[DSA_NUM] = { 0 }; +#endif +#ifndef OPENSSL_NO_EC + /* + * We only test over the following curves as they are representative, To + * add tests over more curves, simply add the curve NID and curve name to + * the following arrays and increase the |ecdh_choices| list accordingly. + */ + static const struct { + const char *name; + unsigned int nid; + unsigned int bits; + } test_curves[] = { + /* Prime Curves */ + {"secp160r1", NID_secp160r1, 160}, + {"nistp192", NID_X9_62_prime192v1, 192}, + {"nistp224", NID_secp224r1, 224}, + {"nistp256", NID_X9_62_prime256v1, 256}, + {"nistp384", NID_secp384r1, 384}, + {"nistp521", NID_secp521r1, 521}, + /* Binary Curves */ + {"nistk163", NID_sect163k1, 163}, + {"nistk233", NID_sect233k1, 233}, + {"nistk283", NID_sect283k1, 283}, + {"nistk409", NID_sect409k1, 409}, + {"nistk571", NID_sect571k1, 571}, + {"nistb163", NID_sect163r2, 163}, + {"nistb233", NID_sect233r1, 233}, + {"nistb283", NID_sect283r1, 283}, + {"nistb409", NID_sect409r1, 409}, + {"nistb571", NID_sect571r1, 571}, + {"brainpoolP256r1", NID_brainpoolP256r1, 256}, + {"brainpoolP256t1", NID_brainpoolP256t1, 256}, + {"brainpoolP384r1", NID_brainpoolP384r1, 384}, + {"brainpoolP384t1", NID_brainpoolP384t1, 384}, + {"brainpoolP512r1", NID_brainpoolP512r1, 512}, + {"brainpoolP512t1", NID_brainpoolP512t1, 512}, + /* Other and ECDH only ones */ + {"X25519", NID_X25519, 253}, + {"X448", NID_X448, 448} + }; + static const struct { + const char *name; + unsigned int nid; + unsigned int bits; + size_t sigsize; + } test_ed_curves[] = { + /* EdDSA */ + {"Ed25519", NID_ED25519, 253, 64}, + {"Ed448", NID_ED448, 456, 114} + }; + int ecdsa_doit[ECDSA_NUM] = { 0 }; + int ecdh_doit[EC_NUM] = { 0 }; + int eddsa_doit[EdDSA_NUM] = { 0 }; + OPENSSL_assert(OSSL_NELEM(test_curves) >= EC_NUM); + OPENSSL_assert(OSSL_NELEM(test_ed_curves) >= EdDSA_NUM); +#endif /* ndef OPENSSL_NO_EC */ + + prog = opt_init(argc, argv, speed_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opterr: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(speed_options); + ret = 0; + goto end; + case OPT_ELAPSED: + usertime = 0; + break; + case OPT_EVP: + evp_md = NULL; + evp_cipher = EVP_get_cipherbyname(opt_arg()); + if (evp_cipher == NULL) + evp_md = EVP_get_digestbyname(opt_arg()); + if (evp_cipher == NULL && evp_md == NULL) { + BIO_printf(bio_err, + "%s: %s is an unknown cipher or digest\n", + prog, opt_arg()); + goto end; + } + doit[D_EVP] = 1; + break; + case OPT_DECRYPT: + decrypt = 1; + break; + case OPT_ENGINE: + /* + * In a forked execution, an engine might need to be + * initialised by each child process, not by the parent. + * So store the name here and run setup_engine() later on. + */ + engine_id = opt_arg(); + break; + case OPT_MULTI: +#ifndef NO_FORK + multi = atoi(opt_arg()); +#endif + break; + case OPT_ASYNCJOBS: +#ifndef OPENSSL_NO_ASYNC + async_jobs = atoi(opt_arg()); + if (!ASYNC_is_capable()) { + BIO_printf(bio_err, + "%s: async_jobs specified but async not supported\n", + prog); + goto opterr; + } + if (async_jobs > 99999) { + BIO_printf(bio_err, "%s: too many async_jobs\n", prog); + goto opterr; + } +#endif + break; + case OPT_MISALIGN: + if (!opt_int(opt_arg(), &misalign)) + goto end; + if (misalign > MISALIGN) { + BIO_printf(bio_err, + "%s: Maximum offset is %d\n", prog, MISALIGN); + goto opterr; + } + break; + case OPT_MR: + mr = 1; + break; + case OPT_MB: + multiblock = 1; +#ifdef OPENSSL_NO_MULTIBLOCK + BIO_printf(bio_err, + "%s: -mb specified but multi-block support is disabled\n", + prog); + goto end; +#endif + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_PRIMES: + if (!opt_int(opt_arg(), &primes)) + goto end; + break; + case OPT_SECONDS: + seconds.sym = seconds.rsa = seconds.dsa = seconds.ecdsa + = seconds.ecdh = seconds.eddsa = atoi(opt_arg()); + break; + case OPT_BYTES: + lengths_single = atoi(opt_arg()); + lengths = &lengths_single; + size_num = 1; + break; + case OPT_AEAD: + aead = 1; + break; + } + } + argc = opt_num_rest(); + argv = opt_rest(); + + /* Remaining arguments are algorithms. */ + for (; *argv; argv++) { + if (found(*argv, doit_choices, &i)) { + doit[i] = 1; + continue; + } +#ifndef OPENSSL_NO_DES + if (strcmp(*argv, "des") == 0) { + doit[D_CBC_DES] = doit[D_EDE3_DES] = 1; + continue; + } +#endif + if (strcmp(*argv, "sha") == 0) { + doit[D_SHA1] = doit[D_SHA256] = doit[D_SHA512] = 1; + continue; + } +#ifndef OPENSSL_NO_RSA + if (strcmp(*argv, "openssl") == 0) + continue; + if (strcmp(*argv, "rsa") == 0) { + for (loop = 0; loop < OSSL_NELEM(rsa_doit); loop++) + rsa_doit[loop] = 1; + continue; + } + if (found(*argv, rsa_choices, &i)) { + rsa_doit[i] = 1; + continue; + } +#endif +#ifndef OPENSSL_NO_DSA + if (strcmp(*argv, "dsa") == 0) { + dsa_doit[R_DSA_512] = dsa_doit[R_DSA_1024] = + dsa_doit[R_DSA_2048] = 1; + continue; + } + if (found(*argv, dsa_choices, &i)) { + dsa_doit[i] = 2; + continue; + } +#endif + if (strcmp(*argv, "aes") == 0) { + doit[D_CBC_128_AES] = doit[D_CBC_192_AES] = doit[D_CBC_256_AES] = 1; + continue; + } +#ifndef OPENSSL_NO_CAMELLIA + if (strcmp(*argv, "camellia") == 0) { + doit[D_CBC_128_CML] = doit[D_CBC_192_CML] = doit[D_CBC_256_CML] = 1; + continue; + } +#endif +#ifndef OPENSSL_NO_EC + if (strcmp(*argv, "ecdsa") == 0) { + for (loop = 0; loop < OSSL_NELEM(ecdsa_doit); loop++) + ecdsa_doit[loop] = 1; + continue; + } + if (found(*argv, ecdsa_choices, &i)) { + ecdsa_doit[i] = 2; + continue; + } + if (strcmp(*argv, "ecdh") == 0) { + for (loop = 0; loop < OSSL_NELEM(ecdh_doit); loop++) + ecdh_doit[loop] = 1; + continue; + } + if (found(*argv, ecdh_choices, &i)) { + ecdh_doit[i] = 2; + continue; + } + if (strcmp(*argv, "eddsa") == 0) { + for (loop = 0; loop < OSSL_NELEM(eddsa_doit); loop++) + eddsa_doit[loop] = 1; + continue; + } + if (found(*argv, eddsa_choices, &i)) { + eddsa_doit[i] = 2; + continue; + } +#endif + BIO_printf(bio_err, "%s: Unknown algorithm %s\n", prog, *argv); + goto end; + } + + /* Sanity checks */ + if (aead) { + if (evp_cipher == NULL) { + BIO_printf(bio_err, "-aead can be used only with an AEAD cipher\n"); + goto end; + } else if (!(EVP_CIPHER_flags(evp_cipher) & + EVP_CIPH_FLAG_AEAD_CIPHER)) { + BIO_printf(bio_err, "%s is not an AEAD cipher\n", + OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher))); + goto end; + } + } + if (multiblock) { + if (evp_cipher == NULL) { + BIO_printf(bio_err,"-mb can be used only with a multi-block" + " capable cipher\n"); + goto end; + } else if (!(EVP_CIPHER_flags(evp_cipher) & + EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK)) { + BIO_printf(bio_err, "%s is not a multi-block capable\n", + OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher))); + goto end; + } else if (async_jobs > 0) { + BIO_printf(bio_err, "Async mode is not supported with -mb"); + goto end; + } + } + + /* Initialize the job pool if async mode is enabled */ + if (async_jobs > 0) { + async_init = ASYNC_init_thread(async_jobs, async_jobs); + if (!async_init) { + BIO_printf(bio_err, "Error creating the ASYNC job pool\n"); + goto end; + } + } + + loopargs_len = (async_jobs == 0 ? 1 : async_jobs); + loopargs = + app_malloc(loopargs_len * sizeof(loopargs_t), "array of loopargs"); + memset(loopargs, 0, loopargs_len * sizeof(loopargs_t)); + + for (i = 0; i < loopargs_len; i++) { + if (async_jobs > 0) { + loopargs[i].wait_ctx = ASYNC_WAIT_CTX_new(); + if (loopargs[i].wait_ctx == NULL) { + BIO_printf(bio_err, "Error creating the ASYNC_WAIT_CTX\n"); + goto end; + } + } + + buflen = lengths[size_num - 1]; + if (buflen < 36) /* size of random vector in RSA bencmark */ + buflen = 36; + buflen += MAX_MISALIGNMENT + 1; + loopargs[i].buf_malloc = app_malloc(buflen, "input buffer"); + loopargs[i].buf2_malloc = app_malloc(buflen, "input buffer"); + memset(loopargs[i].buf_malloc, 0, buflen); + memset(loopargs[i].buf2_malloc, 0, buflen); + + /* Align the start of buffers on a 64 byte boundary */ + loopargs[i].buf = loopargs[i].buf_malloc + misalign; + loopargs[i].buf2 = loopargs[i].buf2_malloc + misalign; +#ifndef OPENSSL_NO_EC + loopargs[i].secret_a = app_malloc(MAX_ECDH_SIZE, "ECDH secret a"); + loopargs[i].secret_b = app_malloc(MAX_ECDH_SIZE, "ECDH secret b"); +#endif + } + +#ifndef NO_FORK + if (multi && do_multi(multi, size_num)) + goto show_res; +#endif + + /* Initialize the engine after the fork */ + e = setup_engine(engine_id, 0); + + /* No parameters; turn on everything. */ + if ((argc == 0) && !doit[D_EVP]) { + for (i = 0; i < ALGOR_NUM; i++) + if (i != D_EVP) + doit[i] = 1; +#ifndef OPENSSL_NO_RSA + for (i = 0; i < RSA_NUM; i++) + rsa_doit[i] = 1; +#endif +#ifndef OPENSSL_NO_DSA + for (i = 0; i < DSA_NUM; i++) + dsa_doit[i] = 1; +#endif +#ifndef OPENSSL_NO_EC + for (loop = 0; loop < OSSL_NELEM(ecdsa_doit); loop++) + ecdsa_doit[loop] = 1; + for (loop = 0; loop < OSSL_NELEM(ecdh_doit); loop++) + ecdh_doit[loop] = 1; + for (loop = 0; loop < OSSL_NELEM(eddsa_doit); loop++) + eddsa_doit[loop] = 1; +#endif + } + for (i = 0; i < ALGOR_NUM; i++) + if (doit[i]) + pr_header++; + + if (usertime == 0 && !mr) + BIO_printf(bio_err, + "You have chosen to measure elapsed time " + "instead of user CPU time.\n"); + +#ifndef OPENSSL_NO_RSA + for (i = 0; i < loopargs_len; i++) { + if (primes > RSA_DEFAULT_PRIME_NUM) { + /* for multi-prime RSA, skip this */ + break; + } + for (k = 0; k < RSA_NUM; k++) { + const unsigned char *p; + + p = rsa_data[k]; + loopargs[i].rsa_key[k] = + d2i_RSAPrivateKey(NULL, &p, rsa_data_length[k]); + if (loopargs[i].rsa_key[k] == NULL) { + BIO_printf(bio_err, + "internal error loading RSA key number %d\n", k); + goto end; + } + } + } +#endif +#ifndef OPENSSL_NO_DSA + for (i = 0; i < loopargs_len; i++) { + loopargs[i].dsa_key[0] = get_dsa(512); + loopargs[i].dsa_key[1] = get_dsa(1024); + loopargs[i].dsa_key[2] = get_dsa(2048); + } +#endif +#ifndef OPENSSL_NO_DES + DES_set_key_unchecked(&key, &sch); + DES_set_key_unchecked(&key2, &sch2); + DES_set_key_unchecked(&key3, &sch3); +#endif + AES_set_encrypt_key(key16, 128, &aes_ks1); + AES_set_encrypt_key(key24, 192, &aes_ks2); + AES_set_encrypt_key(key32, 256, &aes_ks3); +#ifndef OPENSSL_NO_CAMELLIA + Camellia_set_key(key16, 128, &camellia_ks1); + Camellia_set_key(ckey24, 192, &camellia_ks2); + Camellia_set_key(ckey32, 256, &camellia_ks3); +#endif +#ifndef OPENSSL_NO_IDEA + IDEA_set_encrypt_key(key16, &idea_ks); +#endif +#ifndef OPENSSL_NO_SEED + SEED_set_key(key16, &seed_ks); +#endif +#ifndef OPENSSL_NO_RC4 + RC4_set_key(&rc4_ks, 16, key16); +#endif +#ifndef OPENSSL_NO_RC2 + RC2_set_key(&rc2_ks, 16, key16, 128); +#endif +#ifndef OPENSSL_NO_RC5 + RC5_32_set_key(&rc5_ks, 16, key16, 12); +#endif +#ifndef OPENSSL_NO_BF + BF_set_key(&bf_ks, 16, key16); +#endif +#ifndef OPENSSL_NO_CAST + CAST_set_key(&cast_ks, 16, key16); +#endif +#ifndef SIGALRM +# ifndef OPENSSL_NO_DES + BIO_printf(bio_err, "First we calculate the approximate speed ...\n"); + count = 10; + do { + long it; + count *= 2; + Time_F(START); + for (it = count; it; it--) + DES_ecb_encrypt((DES_cblock *)loopargs[0].buf, + (DES_cblock *)loopargs[0].buf, &sch, DES_ENCRYPT); + d = Time_F(STOP); + } while (d < 3); + save_count = count; + c[D_MD2][0] = count / 10; + c[D_MDC2][0] = count / 10; + c[D_MD4][0] = count; + c[D_MD5][0] = count; + c[D_HMAC][0] = count; + c[D_SHA1][0] = count; + c[D_RMD160][0] = count; + c[D_RC4][0] = count * 5; + c[D_CBC_DES][0] = count; + c[D_EDE3_DES][0] = count / 3; + c[D_CBC_IDEA][0] = count; + c[D_CBC_SEED][0] = count; + c[D_CBC_RC2][0] = count; + c[D_CBC_RC5][0] = count; + c[D_CBC_BF][0] = count; + c[D_CBC_CAST][0] = count; + c[D_CBC_128_AES][0] = count; + c[D_CBC_192_AES][0] = count; + c[D_CBC_256_AES][0] = count; + c[D_CBC_128_CML][0] = count; + c[D_CBC_192_CML][0] = count; + c[D_CBC_256_CML][0] = count; + c[D_SHA256][0] = count; + c[D_SHA512][0] = count; + c[D_WHIRLPOOL][0] = count; + c[D_IGE_128_AES][0] = count; + c[D_IGE_192_AES][0] = count; + c[D_IGE_256_AES][0] = count; + c[D_GHASH][0] = count; + c[D_RAND][0] = count; + + for (i = 1; i < size_num; i++) { + long l0, l1; + + l0 = (long)lengths[0]; + l1 = (long)lengths[i]; + + c[D_MD2][i] = c[D_MD2][0] * 4 * l0 / l1; + c[D_MDC2][i] = c[D_MDC2][0] * 4 * l0 / l1; + c[D_MD4][i] = c[D_MD4][0] * 4 * l0 / l1; + c[D_MD5][i] = c[D_MD5][0] * 4 * l0 / l1; + c[D_HMAC][i] = c[D_HMAC][0] * 4 * l0 / l1; + c[D_SHA1][i] = c[D_SHA1][0] * 4 * l0 / l1; + c[D_RMD160][i] = c[D_RMD160][0] * 4 * l0 / l1; + c[D_SHA256][i] = c[D_SHA256][0] * 4 * l0 / l1; + c[D_SHA512][i] = c[D_SHA512][0] * 4 * l0 / l1; + c[D_WHIRLPOOL][i] = c[D_WHIRLPOOL][0] * 4 * l0 / l1; + c[D_GHASH][i] = c[D_GHASH][0] * 4 * l0 / l1; + c[D_RAND][i] = c[D_RAND][0] * 4 * l0 / l1; + + l0 = (long)lengths[i - 1]; + + c[D_RC4][i] = c[D_RC4][i - 1] * l0 / l1; + c[D_CBC_DES][i] = c[D_CBC_DES][i - 1] * l0 / l1; + c[D_EDE3_DES][i] = c[D_EDE3_DES][i - 1] * l0 / l1; + c[D_CBC_IDEA][i] = c[D_CBC_IDEA][i - 1] * l0 / l1; + c[D_CBC_SEED][i] = c[D_CBC_SEED][i - 1] * l0 / l1; + c[D_CBC_RC2][i] = c[D_CBC_RC2][i - 1] * l0 / l1; + c[D_CBC_RC5][i] = c[D_CBC_RC5][i - 1] * l0 / l1; + c[D_CBC_BF][i] = c[D_CBC_BF][i - 1] * l0 / l1; + c[D_CBC_CAST][i] = c[D_CBC_CAST][i - 1] * l0 / l1; + c[D_CBC_128_AES][i] = c[D_CBC_128_AES][i - 1] * l0 / l1; + c[D_CBC_192_AES][i] = c[D_CBC_192_AES][i - 1] * l0 / l1; + c[D_CBC_256_AES][i] = c[D_CBC_256_AES][i - 1] * l0 / l1; + c[D_CBC_128_CML][i] = c[D_CBC_128_CML][i - 1] * l0 / l1; + c[D_CBC_192_CML][i] = c[D_CBC_192_CML][i - 1] * l0 / l1; + c[D_CBC_256_CML][i] = c[D_CBC_256_CML][i - 1] * l0 / l1; + c[D_IGE_128_AES][i] = c[D_IGE_128_AES][i - 1] * l0 / l1; + c[D_IGE_192_AES][i] = c[D_IGE_192_AES][i - 1] * l0 / l1; + c[D_IGE_256_AES][i] = c[D_IGE_256_AES][i - 1] * l0 / l1; + } + +# ifndef OPENSSL_NO_RSA + rsa_c[R_RSA_512][0] = count / 2000; + rsa_c[R_RSA_512][1] = count / 400; + for (i = 1; i < RSA_NUM; i++) { + rsa_c[i][0] = rsa_c[i - 1][0] / 8; + rsa_c[i][1] = rsa_c[i - 1][1] / 4; + if (rsa_doit[i] <= 1 && rsa_c[i][0] == 0) + rsa_doit[i] = 0; + else { + if (rsa_c[i][0] == 0) { + rsa_c[i][0] = 1; /* Set minimum iteration Nb to 1. */ + rsa_c[i][1] = 20; + } + } + } +# endif + +# ifndef OPENSSL_NO_DSA + dsa_c[R_DSA_512][0] = count / 1000; + dsa_c[R_DSA_512][1] = count / 1000 / 2; + for (i = 1; i < DSA_NUM; i++) { + dsa_c[i][0] = dsa_c[i - 1][0] / 4; + dsa_c[i][1] = dsa_c[i - 1][1] / 4; + if (dsa_doit[i] <= 1 && dsa_c[i][0] == 0) + dsa_doit[i] = 0; + else { + if (dsa_c[i][0] == 0) { + dsa_c[i][0] = 1; /* Set minimum iteration Nb to 1. */ + dsa_c[i][1] = 1; + } + } + } +# endif + +# ifndef OPENSSL_NO_EC + ecdsa_c[R_EC_P160][0] = count / 1000; + ecdsa_c[R_EC_P160][1] = count / 1000 / 2; + for (i = R_EC_P192; i <= R_EC_P521; i++) { + ecdsa_c[i][0] = ecdsa_c[i - 1][0] / 2; + ecdsa_c[i][1] = ecdsa_c[i - 1][1] / 2; + if (ecdsa_doit[i] <= 1 && ecdsa_c[i][0] == 0) + ecdsa_doit[i] = 0; + else { + if (ecdsa_c[i][0] == 0) { + ecdsa_c[i][0] = 1; + ecdsa_c[i][1] = 1; + } + } + } + ecdsa_c[R_EC_K163][0] = count / 1000; + ecdsa_c[R_EC_K163][1] = count / 1000 / 2; + for (i = R_EC_K233; i <= R_EC_K571; i++) { + ecdsa_c[i][0] = ecdsa_c[i - 1][0] / 2; + ecdsa_c[i][1] = ecdsa_c[i - 1][1] / 2; + if (ecdsa_doit[i] <= 1 && ecdsa_c[i][0] == 0) + ecdsa_doit[i] = 0; + else { + if (ecdsa_c[i][0] == 0) { + ecdsa_c[i][0] = 1; + ecdsa_c[i][1] = 1; + } + } + } + ecdsa_c[R_EC_B163][0] = count / 1000; + ecdsa_c[R_EC_B163][1] = count / 1000 / 2; + for (i = R_EC_B233; i <= R_EC_B571; i++) { + ecdsa_c[i][0] = ecdsa_c[i - 1][0] / 2; + ecdsa_c[i][1] = ecdsa_c[i - 1][1] / 2; + if (ecdsa_doit[i] <= 1 && ecdsa_c[i][0] == 0) + ecdsa_doit[i] = 0; + else { + if (ecdsa_c[i][0] == 0) { + ecdsa_c[i][0] = 1; + ecdsa_c[i][1] = 1; + } + } + } + + ecdh_c[R_EC_P160][0] = count / 1000; + for (i = R_EC_P192; i <= R_EC_P521; i++) { + ecdh_c[i][0] = ecdh_c[i - 1][0] / 2; + if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0) + ecdh_doit[i] = 0; + else { + if (ecdh_c[i][0] == 0) { + ecdh_c[i][0] = 1; + } + } + } + ecdh_c[R_EC_K163][0] = count / 1000; + for (i = R_EC_K233; i <= R_EC_K571; i++) { + ecdh_c[i][0] = ecdh_c[i - 1][0] / 2; + if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0) + ecdh_doit[i] = 0; + else { + if (ecdh_c[i][0] == 0) { + ecdh_c[i][0] = 1; + } + } + } + ecdh_c[R_EC_B163][0] = count / 1000; + for (i = R_EC_B233; i <= R_EC_B571; i++) { + ecdh_c[i][0] = ecdh_c[i - 1][0] / 2; + if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0) + ecdh_doit[i] = 0; + else { + if (ecdh_c[i][0] == 0) { + ecdh_c[i][0] = 1; + } + } + } + /* repeated code good to factorize */ + ecdh_c[R_EC_BRP256R1][0] = count / 1000; + for (i = R_EC_BRP384R1; i <= R_EC_BRP512R1; i += 2) { + ecdh_c[i][0] = ecdh_c[i - 2][0] / 2; + if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0) + ecdh_doit[i] = 0; + else { + if (ecdh_c[i][0] == 0) { + ecdh_c[i][0] = 1; + } + } + } + ecdh_c[R_EC_BRP256T1][0] = count / 1000; + for (i = R_EC_BRP384T1; i <= R_EC_BRP512T1; i += 2) { + ecdh_c[i][0] = ecdh_c[i - 2][0] / 2; + if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0) + ecdh_doit[i] = 0; + else { + if (ecdh_c[i][0] == 0) { + ecdh_c[i][0] = 1; + } + } + } + /* default iteration count for the last two EC Curves */ + ecdh_c[R_EC_X25519][0] = count / 1800; + ecdh_c[R_EC_X448][0] = count / 7200; + + eddsa_c[R_EC_Ed25519][0] = count / 1800; + eddsa_c[R_EC_Ed448][0] = count / 7200; +# endif + +# else +/* not worth fixing */ +# error "You cannot disable DES on systems without SIGALRM." +# endif /* OPENSSL_NO_DES */ +#elif SIGALRM > 0 + signal(SIGALRM, alarmed); +#endif /* SIGALRM */ + +#ifndef OPENSSL_NO_MD2 + if (doit[D_MD2]) { + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_MD2], c[D_MD2][testnum], lengths[testnum], + seconds.sym); + Time_F(START); + count = run_benchmark(async_jobs, EVP_Digest_MD2_loop, loopargs); + d = Time_F(STOP); + print_result(D_MD2, testnum, count, d); + } + } +#endif +#ifndef OPENSSL_NO_MDC2 + if (doit[D_MDC2]) { + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_MDC2], c[D_MDC2][testnum], lengths[testnum], + seconds.sym); + Time_F(START); + count = run_benchmark(async_jobs, EVP_Digest_MDC2_loop, loopargs); + d = Time_F(STOP); + print_result(D_MDC2, testnum, count, d); + } + } +#endif + +#ifndef OPENSSL_NO_MD4 + if (doit[D_MD4]) { + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_MD4], c[D_MD4][testnum], lengths[testnum], + seconds.sym); + Time_F(START); + count = run_benchmark(async_jobs, EVP_Digest_MD4_loop, loopargs); + d = Time_F(STOP); + print_result(D_MD4, testnum, count, d); + } + } +#endif + +#ifndef OPENSSL_NO_MD5 + if (doit[D_MD5]) { + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_MD5], c[D_MD5][testnum], lengths[testnum], + seconds.sym); + Time_F(START); + count = run_benchmark(async_jobs, MD5_loop, loopargs); + d = Time_F(STOP); + print_result(D_MD5, testnum, count, d); + } + } + + if (doit[D_HMAC]) { + static const char hmac_key[] = "This is a key..."; + int len = strlen(hmac_key); + + for (i = 0; i < loopargs_len; i++) { + loopargs[i].hctx = HMAC_CTX_new(); + if (loopargs[i].hctx == NULL) { + BIO_printf(bio_err, "HMAC malloc failure, exiting..."); + exit(1); + } + + HMAC_Init_ex(loopargs[i].hctx, hmac_key, len, EVP_md5(), NULL); + } + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_HMAC], c[D_HMAC][testnum], lengths[testnum], + seconds.sym); + Time_F(START); + count = run_benchmark(async_jobs, HMAC_loop, loopargs); + d = Time_F(STOP); + print_result(D_HMAC, testnum, count, d); + } + for (i = 0; i < loopargs_len; i++) { + HMAC_CTX_free(loopargs[i].hctx); + } + } +#endif + if (doit[D_SHA1]) { + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_SHA1], c[D_SHA1][testnum], lengths[testnum], + seconds.sym); + Time_F(START); + count = run_benchmark(async_jobs, SHA1_loop, loopargs); + d = Time_F(STOP); + print_result(D_SHA1, testnum, count, d); + } + } + if (doit[D_SHA256]) { + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_SHA256], c[D_SHA256][testnum], + lengths[testnum], seconds.sym); + Time_F(START); + count = run_benchmark(async_jobs, SHA256_loop, loopargs); + d = Time_F(STOP); + print_result(D_SHA256, testnum, count, d); + } + } + if (doit[D_SHA512]) { + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_SHA512], c[D_SHA512][testnum], + lengths[testnum], seconds.sym); + Time_F(START); + count = run_benchmark(async_jobs, SHA512_loop, loopargs); + d = Time_F(STOP); + print_result(D_SHA512, testnum, count, d); + } + } +#ifndef OPENSSL_NO_WHIRLPOOL + if (doit[D_WHIRLPOOL]) { + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_WHIRLPOOL], c[D_WHIRLPOOL][testnum], + lengths[testnum], seconds.sym); + Time_F(START); + count = run_benchmark(async_jobs, WHIRLPOOL_loop, loopargs); + d = Time_F(STOP); + print_result(D_WHIRLPOOL, testnum, count, d); + } + } +#endif + +#ifndef OPENSSL_NO_RMD160 + if (doit[D_RMD160]) { + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_RMD160], c[D_RMD160][testnum], + lengths[testnum], seconds.sym); + Time_F(START); + count = run_benchmark(async_jobs, EVP_Digest_RMD160_loop, loopargs); + d = Time_F(STOP); + print_result(D_RMD160, testnum, count, d); + } + } +#endif +#ifndef OPENSSL_NO_RC4 + if (doit[D_RC4]) { + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_RC4], c[D_RC4][testnum], lengths[testnum], + seconds.sym); + Time_F(START); + count = run_benchmark(async_jobs, RC4_loop, loopargs); + d = Time_F(STOP); + print_result(D_RC4, testnum, count, d); + } + } +#endif +#ifndef OPENSSL_NO_DES + if (doit[D_CBC_DES]) { + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_CBC_DES], c[D_CBC_DES][testnum], + lengths[testnum], seconds.sym); + Time_F(START); + count = run_benchmark(async_jobs, DES_ncbc_encrypt_loop, loopargs); + d = Time_F(STOP); + print_result(D_CBC_DES, testnum, count, d); + } + } + + if (doit[D_EDE3_DES]) { + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_EDE3_DES], c[D_EDE3_DES][testnum], + lengths[testnum], seconds.sym); + Time_F(START); + count = + run_benchmark(async_jobs, DES_ede3_cbc_encrypt_loop, loopargs); + d = Time_F(STOP); + print_result(D_EDE3_DES, testnum, count, d); + } + } +#endif + + if (doit[D_CBC_128_AES]) { + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_CBC_128_AES], c[D_CBC_128_AES][testnum], + lengths[testnum], seconds.sym); + Time_F(START); + count = + run_benchmark(async_jobs, AES_cbc_128_encrypt_loop, loopargs); + d = Time_F(STOP); + print_result(D_CBC_128_AES, testnum, count, d); + } + } + if (doit[D_CBC_192_AES]) { + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_CBC_192_AES], c[D_CBC_192_AES][testnum], + lengths[testnum], seconds.sym); + Time_F(START); + count = + run_benchmark(async_jobs, AES_cbc_192_encrypt_loop, loopargs); + d = Time_F(STOP); + print_result(D_CBC_192_AES, testnum, count, d); + } + } + if (doit[D_CBC_256_AES]) { + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_CBC_256_AES], c[D_CBC_256_AES][testnum], + lengths[testnum], seconds.sym); + Time_F(START); + count = + run_benchmark(async_jobs, AES_cbc_256_encrypt_loop, loopargs); + d = Time_F(STOP); + print_result(D_CBC_256_AES, testnum, count, d); + } + } + + if (doit[D_IGE_128_AES]) { + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_IGE_128_AES], c[D_IGE_128_AES][testnum], + lengths[testnum], seconds.sym); + Time_F(START); + count = + run_benchmark(async_jobs, AES_ige_128_encrypt_loop, loopargs); + d = Time_F(STOP); + print_result(D_IGE_128_AES, testnum, count, d); + } + } + if (doit[D_IGE_192_AES]) { + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_IGE_192_AES], c[D_IGE_192_AES][testnum], + lengths[testnum], seconds.sym); + Time_F(START); + count = + run_benchmark(async_jobs, AES_ige_192_encrypt_loop, loopargs); + d = Time_F(STOP); + print_result(D_IGE_192_AES, testnum, count, d); + } + } + if (doit[D_IGE_256_AES]) { + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_IGE_256_AES], c[D_IGE_256_AES][testnum], + lengths[testnum], seconds.sym); + Time_F(START); + count = + run_benchmark(async_jobs, AES_ige_256_encrypt_loop, loopargs); + d = Time_F(STOP); + print_result(D_IGE_256_AES, testnum, count, d); + } + } + if (doit[D_GHASH]) { + for (i = 0; i < loopargs_len; i++) { + loopargs[i].gcm_ctx = + CRYPTO_gcm128_new(&aes_ks1, (block128_f) AES_encrypt); + CRYPTO_gcm128_setiv(loopargs[i].gcm_ctx, + (unsigned char *)"0123456789ab", 12); + } + + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_GHASH], c[D_GHASH][testnum], + lengths[testnum], seconds.sym); + Time_F(START); + count = run_benchmark(async_jobs, CRYPTO_gcm128_aad_loop, loopargs); + d = Time_F(STOP); + print_result(D_GHASH, testnum, count, d); + } + for (i = 0; i < loopargs_len; i++) + CRYPTO_gcm128_release(loopargs[i].gcm_ctx); + } +#ifndef OPENSSL_NO_CAMELLIA + if (doit[D_CBC_128_CML]) { + if (async_jobs > 0) { + BIO_printf(bio_err, "Async mode is not supported with %s\n", + names[D_CBC_128_CML]); + doit[D_CBC_128_CML] = 0; + } + for (testnum = 0; testnum < size_num && async_init == 0; testnum++) { + print_message(names[D_CBC_128_CML], c[D_CBC_128_CML][testnum], + lengths[testnum], seconds.sym); + Time_F(START); + for (count = 0, run = 1; COND(c[D_CBC_128_CML][testnum]); count++) + Camellia_cbc_encrypt(loopargs[0].buf, loopargs[0].buf, + (size_t)lengths[testnum], &camellia_ks1, + iv, CAMELLIA_ENCRYPT); + d = Time_F(STOP); + print_result(D_CBC_128_CML, testnum, count, d); + } + } + if (doit[D_CBC_192_CML]) { + if (async_jobs > 0) { + BIO_printf(bio_err, "Async mode is not supported with %s\n", + names[D_CBC_192_CML]); + doit[D_CBC_192_CML] = 0; + } + for (testnum = 0; testnum < size_num && async_init == 0; testnum++) { + print_message(names[D_CBC_192_CML], c[D_CBC_192_CML][testnum], + lengths[testnum], seconds.sym); + if (async_jobs > 0) { + BIO_printf(bio_err, "Async mode is not supported, exiting..."); + exit(1); + } + Time_F(START); + for (count = 0, run = 1; COND(c[D_CBC_192_CML][testnum]); count++) + Camellia_cbc_encrypt(loopargs[0].buf, loopargs[0].buf, + (size_t)lengths[testnum], &camellia_ks2, + iv, CAMELLIA_ENCRYPT); + d = Time_F(STOP); + print_result(D_CBC_192_CML, testnum, count, d); + } + } + if (doit[D_CBC_256_CML]) { + if (async_jobs > 0) { + BIO_printf(bio_err, "Async mode is not supported with %s\n", + names[D_CBC_256_CML]); + doit[D_CBC_256_CML] = 0; + } + for (testnum = 0; testnum < size_num && async_init == 0; testnum++) { + print_message(names[D_CBC_256_CML], c[D_CBC_256_CML][testnum], + lengths[testnum], seconds.sym); + Time_F(START); + for (count = 0, run = 1; COND(c[D_CBC_256_CML][testnum]); count++) + Camellia_cbc_encrypt(loopargs[0].buf, loopargs[0].buf, + (size_t)lengths[testnum], &camellia_ks3, + iv, CAMELLIA_ENCRYPT); + d = Time_F(STOP); + print_result(D_CBC_256_CML, testnum, count, d); + } + } +#endif +#ifndef OPENSSL_NO_IDEA + if (doit[D_CBC_IDEA]) { + if (async_jobs > 0) { + BIO_printf(bio_err, "Async mode is not supported with %s\n", + names[D_CBC_IDEA]); + doit[D_CBC_IDEA] = 0; + } + for (testnum = 0; testnum < size_num && async_init == 0; testnum++) { + print_message(names[D_CBC_IDEA], c[D_CBC_IDEA][testnum], + lengths[testnum], seconds.sym); + Time_F(START); + for (count = 0, run = 1; COND(c[D_CBC_IDEA][testnum]); count++) + IDEA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf, + (size_t)lengths[testnum], &idea_ks, + iv, IDEA_ENCRYPT); + d = Time_F(STOP); + print_result(D_CBC_IDEA, testnum, count, d); + } + } +#endif +#ifndef OPENSSL_NO_SEED + if (doit[D_CBC_SEED]) { + if (async_jobs > 0) { + BIO_printf(bio_err, "Async mode is not supported with %s\n", + names[D_CBC_SEED]); + doit[D_CBC_SEED] = 0; + } + for (testnum = 0; testnum < size_num && async_init == 0; testnum++) { + print_message(names[D_CBC_SEED], c[D_CBC_SEED][testnum], + lengths[testnum], seconds.sym); + Time_F(START); + for (count = 0, run = 1; COND(c[D_CBC_SEED][testnum]); count++) + SEED_cbc_encrypt(loopargs[0].buf, loopargs[0].buf, + (size_t)lengths[testnum], &seed_ks, iv, 1); + d = Time_F(STOP); + print_result(D_CBC_SEED, testnum, count, d); + } + } +#endif +#ifndef OPENSSL_NO_RC2 + if (doit[D_CBC_RC2]) { + if (async_jobs > 0) { + BIO_printf(bio_err, "Async mode is not supported with %s\n", + names[D_CBC_RC2]); + doit[D_CBC_RC2] = 0; + } + for (testnum = 0; testnum < size_num && async_init == 0; testnum++) { + print_message(names[D_CBC_RC2], c[D_CBC_RC2][testnum], + lengths[testnum], seconds.sym); + if (async_jobs > 0) { + BIO_printf(bio_err, "Async mode is not supported, exiting..."); + exit(1); + } + Time_F(START); + for (count = 0, run = 1; COND(c[D_CBC_RC2][testnum]); count++) + RC2_cbc_encrypt(loopargs[0].buf, loopargs[0].buf, + (size_t)lengths[testnum], &rc2_ks, + iv, RC2_ENCRYPT); + d = Time_F(STOP); + print_result(D_CBC_RC2, testnum, count, d); + } + } +#endif +#ifndef OPENSSL_NO_RC5 + if (doit[D_CBC_RC5]) { + if (async_jobs > 0) { + BIO_printf(bio_err, "Async mode is not supported with %s\n", + names[D_CBC_RC5]); + doit[D_CBC_RC5] = 0; + } + for (testnum = 0; testnum < size_num && async_init == 0; testnum++) { + print_message(names[D_CBC_RC5], c[D_CBC_RC5][testnum], + lengths[testnum], seconds.sym); + if (async_jobs > 0) { + BIO_printf(bio_err, "Async mode is not supported, exiting..."); + exit(1); + } + Time_F(START); + for (count = 0, run = 1; COND(c[D_CBC_RC5][testnum]); count++) + RC5_32_cbc_encrypt(loopargs[0].buf, loopargs[0].buf, + (size_t)lengths[testnum], &rc5_ks, + iv, RC5_ENCRYPT); + d = Time_F(STOP); + print_result(D_CBC_RC5, testnum, count, d); + } + } +#endif +#ifndef OPENSSL_NO_BF + if (doit[D_CBC_BF]) { + if (async_jobs > 0) { + BIO_printf(bio_err, "Async mode is not supported with %s\n", + names[D_CBC_BF]); + doit[D_CBC_BF] = 0; + } + for (testnum = 0; testnum < size_num && async_init == 0; testnum++) { + print_message(names[D_CBC_BF], c[D_CBC_BF][testnum], + lengths[testnum], seconds.sym); + Time_F(START); + for (count = 0, run = 1; COND(c[D_CBC_BF][testnum]); count++) + BF_cbc_encrypt(loopargs[0].buf, loopargs[0].buf, + (size_t)lengths[testnum], &bf_ks, + iv, BF_ENCRYPT); + d = Time_F(STOP); + print_result(D_CBC_BF, testnum, count, d); + } + } +#endif +#ifndef OPENSSL_NO_CAST + if (doit[D_CBC_CAST]) { + if (async_jobs > 0) { + BIO_printf(bio_err, "Async mode is not supported with %s\n", + names[D_CBC_CAST]); + doit[D_CBC_CAST] = 0; + } + for (testnum = 0; testnum < size_num && async_init == 0; testnum++) { + print_message(names[D_CBC_CAST], c[D_CBC_CAST][testnum], + lengths[testnum], seconds.sym); + Time_F(START); + for (count = 0, run = 1; COND(c[D_CBC_CAST][testnum]); count++) + CAST_cbc_encrypt(loopargs[0].buf, loopargs[0].buf, + (size_t)lengths[testnum], &cast_ks, + iv, CAST_ENCRYPT); + d = Time_F(STOP); + print_result(D_CBC_CAST, testnum, count, d); + } + } +#endif + if (doit[D_RAND]) { + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_RAND], c[D_RAND][testnum], lengths[testnum], + seconds.sym); + Time_F(START); + count = run_benchmark(async_jobs, RAND_bytes_loop, loopargs); + d = Time_F(STOP); + print_result(D_RAND, testnum, count, d); + } + } + + if (doit[D_EVP]) { + if (evp_cipher != NULL) { + int (*loopfunc)(void *args) = EVP_Update_loop; + + if (multiblock && (EVP_CIPHER_flags(evp_cipher) & + EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK)) { + multiblock_speed(evp_cipher, lengths_single, &seconds); + ret = 0; + goto end; + } + + names[D_EVP] = OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher)); + + if (EVP_CIPHER_mode(evp_cipher) == EVP_CIPH_CCM_MODE) { + loopfunc = EVP_Update_loop_ccm; + } else if (aead && (EVP_CIPHER_flags(evp_cipher) & + EVP_CIPH_FLAG_AEAD_CIPHER)) { + loopfunc = EVP_Update_loop_aead; + if (lengths == lengths_list) { + lengths = aead_lengths_list; + size_num = OSSL_NELEM(aead_lengths_list); + } + } + + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_EVP], save_count, lengths[testnum], + seconds.sym); + + for (k = 0; k < loopargs_len; k++) { + loopargs[k].ctx = EVP_CIPHER_CTX_new(); + EVP_CipherInit_ex(loopargs[k].ctx, evp_cipher, NULL, NULL, + iv, decrypt ? 0 : 1); + + EVP_CIPHER_CTX_set_padding(loopargs[k].ctx, 0); + + keylen = EVP_CIPHER_CTX_key_length(loopargs[k].ctx); + loopargs[k].key = app_malloc(keylen, "evp_cipher key"); + EVP_CIPHER_CTX_rand_key(loopargs[k].ctx, loopargs[k].key); + EVP_CipherInit_ex(loopargs[k].ctx, NULL, NULL, + loopargs[k].key, NULL, -1); + OPENSSL_clear_free(loopargs[k].key, keylen); + } + + Time_F(START); + count = run_benchmark(async_jobs, loopfunc, loopargs); + d = Time_F(STOP); + for (k = 0; k < loopargs_len; k++) { + EVP_CIPHER_CTX_free(loopargs[k].ctx); + } + print_result(D_EVP, testnum, count, d); + } + } else if (evp_md != NULL) { + names[D_EVP] = OBJ_nid2ln(EVP_MD_type(evp_md)); + + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_EVP], save_count, lengths[testnum], + seconds.sym); + Time_F(START); + count = run_benchmark(async_jobs, EVP_Digest_loop, loopargs); + d = Time_F(STOP); + print_result(D_EVP, testnum, count, d); + } + } + } + + for (i = 0; i < loopargs_len; i++) + if (RAND_bytes(loopargs[i].buf, 36) <= 0) + goto end; + +#ifndef OPENSSL_NO_RSA + for (testnum = 0; testnum < RSA_NUM; testnum++) { + int st = 0; + if (!rsa_doit[testnum]) + continue; + for (i = 0; i < loopargs_len; i++) { + if (primes > 2) { + /* we haven't set keys yet, generate multi-prime RSA keys */ + BIGNUM *bn = BN_new(); + + if (bn == NULL) + goto end; + if (!BN_set_word(bn, RSA_F4)) { + BN_free(bn); + goto end; + } + + BIO_printf(bio_err, "Generate multi-prime RSA key for %s\n", + rsa_choices[testnum].name); + + loopargs[i].rsa_key[testnum] = RSA_new(); + if (loopargs[i].rsa_key[testnum] == NULL) { + BN_free(bn); + goto end; + } + + if (!RSA_generate_multi_prime_key(loopargs[i].rsa_key[testnum], + rsa_bits[testnum], + primes, bn, NULL)) { + BN_free(bn); + goto end; + } + BN_free(bn); + } + st = RSA_sign(NID_md5_sha1, loopargs[i].buf, 36, loopargs[i].buf2, + &loopargs[i].siglen, loopargs[i].rsa_key[testnum]); + if (st == 0) + break; + } + if (st == 0) { + BIO_printf(bio_err, + "RSA sign failure. No RSA sign will be done.\n"); + ERR_print_errors(bio_err); + rsa_count = 1; + } else { + pkey_print_message("private", "rsa", + rsa_c[testnum][0], rsa_bits[testnum], + seconds.rsa); + /* RSA_blinding_on(rsa_key[testnum],NULL); */ + Time_F(START); + count = run_benchmark(async_jobs, RSA_sign_loop, loopargs); + d = Time_F(STOP); + BIO_printf(bio_err, + mr ? "+R1:%ld:%d:%.2f\n" + : "%ld %u bits private RSA's in %.2fs\n", + count, rsa_bits[testnum], d); + rsa_results[testnum][0] = (double)count / d; + rsa_count = count; + } + + for (i = 0; i < loopargs_len; i++) { + st = RSA_verify(NID_md5_sha1, loopargs[i].buf, 36, loopargs[i].buf2, + loopargs[i].siglen, loopargs[i].rsa_key[testnum]); + if (st <= 0) + break; + } + if (st <= 0) { + BIO_printf(bio_err, + "RSA verify failure. No RSA verify will be done.\n"); + ERR_print_errors(bio_err); + rsa_doit[testnum] = 0; + } else { + pkey_print_message("public", "rsa", + rsa_c[testnum][1], rsa_bits[testnum], + seconds.rsa); + Time_F(START); + count = run_benchmark(async_jobs, RSA_verify_loop, loopargs); + d = Time_F(STOP); + BIO_printf(bio_err, + mr ? "+R2:%ld:%d:%.2f\n" + : "%ld %u bits public RSA's in %.2fs\n", + count, rsa_bits[testnum], d); + rsa_results[testnum][1] = (double)count / d; + } + + if (rsa_count <= 1) { + /* if longer than 10s, don't do any more */ + for (testnum++; testnum < RSA_NUM; testnum++) + rsa_doit[testnum] = 0; + } + } +#endif /* OPENSSL_NO_RSA */ + + for (i = 0; i < loopargs_len; i++) + if (RAND_bytes(loopargs[i].buf, 36) <= 0) + goto end; + +#ifndef OPENSSL_NO_DSA + for (testnum = 0; testnum < DSA_NUM; testnum++) { + int st = 0; + if (!dsa_doit[testnum]) + continue; + + /* DSA_generate_key(dsa_key[testnum]); */ + /* DSA_sign_setup(dsa_key[testnum],NULL); */ + for (i = 0; i < loopargs_len; i++) { + st = DSA_sign(0, loopargs[i].buf, 20, loopargs[i].buf2, + &loopargs[i].siglen, loopargs[i].dsa_key[testnum]); + if (st == 0) + break; + } + if (st == 0) { + BIO_printf(bio_err, + "DSA sign failure. No DSA sign will be done.\n"); + ERR_print_errors(bio_err); + rsa_count = 1; + } else { + pkey_print_message("sign", "dsa", + dsa_c[testnum][0], dsa_bits[testnum], + seconds.dsa); + Time_F(START); + count = run_benchmark(async_jobs, DSA_sign_loop, loopargs); + d = Time_F(STOP); + BIO_printf(bio_err, + mr ? "+R3:%ld:%u:%.2f\n" + : "%ld %u bits DSA signs in %.2fs\n", + count, dsa_bits[testnum], d); + dsa_results[testnum][0] = (double)count / d; + rsa_count = count; + } + + for (i = 0; i < loopargs_len; i++) { + st = DSA_verify(0, loopargs[i].buf, 20, loopargs[i].buf2, + loopargs[i].siglen, loopargs[i].dsa_key[testnum]); + if (st <= 0) + break; + } + if (st <= 0) { + BIO_printf(bio_err, + "DSA verify failure. No DSA verify will be done.\n"); + ERR_print_errors(bio_err); + dsa_doit[testnum] = 0; + } else { + pkey_print_message("verify", "dsa", + dsa_c[testnum][1], dsa_bits[testnum], + seconds.dsa); + Time_F(START); + count = run_benchmark(async_jobs, DSA_verify_loop, loopargs); + d = Time_F(STOP); + BIO_printf(bio_err, + mr ? "+R4:%ld:%u:%.2f\n" + : "%ld %u bits DSA verify in %.2fs\n", + count, dsa_bits[testnum], d); + dsa_results[testnum][1] = (double)count / d; + } + + if (rsa_count <= 1) { + /* if longer than 10s, don't do any more */ + for (testnum++; testnum < DSA_NUM; testnum++) + dsa_doit[testnum] = 0; + } + } +#endif /* OPENSSL_NO_DSA */ + +#ifndef OPENSSL_NO_EC + for (testnum = 0; testnum < ECDSA_NUM; testnum++) { + int st = 1; + + if (!ecdsa_doit[testnum]) + continue; /* Ignore Curve */ + for (i = 0; i < loopargs_len; i++) { + loopargs[i].ecdsa[testnum] = + EC_KEY_new_by_curve_name(test_curves[testnum].nid); + if (loopargs[i].ecdsa[testnum] == NULL) { + st = 0; + break; + } + } + if (st == 0) { + BIO_printf(bio_err, "ECDSA failure.\n"); + ERR_print_errors(bio_err); + rsa_count = 1; + } else { + for (i = 0; i < loopargs_len; i++) { + EC_KEY_precompute_mult(loopargs[i].ecdsa[testnum], NULL); + /* Perform ECDSA signature test */ + EC_KEY_generate_key(loopargs[i].ecdsa[testnum]); + st = ECDSA_sign(0, loopargs[i].buf, 20, loopargs[i].buf2, + &loopargs[i].siglen, + loopargs[i].ecdsa[testnum]); + if (st == 0) + break; + } + if (st == 0) { + BIO_printf(bio_err, + "ECDSA sign failure. No ECDSA sign will be done.\n"); + ERR_print_errors(bio_err); + rsa_count = 1; + } else { + pkey_print_message("sign", "ecdsa", + ecdsa_c[testnum][0], + test_curves[testnum].bits, seconds.ecdsa); + Time_F(START); + count = run_benchmark(async_jobs, ECDSA_sign_loop, loopargs); + d = Time_F(STOP); + + BIO_printf(bio_err, + mr ? "+R5:%ld:%u:%.2f\n" : + "%ld %u bits ECDSA signs in %.2fs \n", + count, test_curves[testnum].bits, d); + ecdsa_results[testnum][0] = (double)count / d; + rsa_count = count; + } + + /* Perform ECDSA verification test */ + for (i = 0; i < loopargs_len; i++) { + st = ECDSA_verify(0, loopargs[i].buf, 20, loopargs[i].buf2, + loopargs[i].siglen, + loopargs[i].ecdsa[testnum]); + if (st != 1) + break; + } + if (st != 1) { + BIO_printf(bio_err, + "ECDSA verify failure. No ECDSA verify will be done.\n"); + ERR_print_errors(bio_err); + ecdsa_doit[testnum] = 0; + } else { + pkey_print_message("verify", "ecdsa", + ecdsa_c[testnum][1], + test_curves[testnum].bits, seconds.ecdsa); + Time_F(START); + count = run_benchmark(async_jobs, ECDSA_verify_loop, loopargs); + d = Time_F(STOP); + BIO_printf(bio_err, + mr ? "+R6:%ld:%u:%.2f\n" + : "%ld %u bits ECDSA verify in %.2fs\n", + count, test_curves[testnum].bits, d); + ecdsa_results[testnum][1] = (double)count / d; + } + + if (rsa_count <= 1) { + /* if longer than 10s, don't do any more */ + for (testnum++; testnum < ECDSA_NUM; testnum++) + ecdsa_doit[testnum] = 0; + } + } + } + + for (testnum = 0; testnum < EC_NUM; testnum++) { + int ecdh_checks = 1; + + if (!ecdh_doit[testnum]) + continue; + + for (i = 0; i < loopargs_len; i++) { + EVP_PKEY_CTX *kctx = NULL; + EVP_PKEY_CTX *test_ctx = NULL; + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *key_A = NULL; + EVP_PKEY *key_B = NULL; + size_t outlen; + size_t test_outlen; + + /* Ensure that the error queue is empty */ + if (ERR_peek_error()) { + BIO_printf(bio_err, + "WARNING: the error queue contains previous unhandled errors.\n"); + ERR_print_errors(bio_err); + } + + /* Let's try to create a ctx directly from the NID: this works for + * curves like Curve25519 that are not implemented through the low + * level EC interface. + * If this fails we try creating a EVP_PKEY_EC generic param ctx, + * then we set the curve by NID before deriving the actual keygen + * ctx for that specific curve. */ + kctx = EVP_PKEY_CTX_new_id(test_curves[testnum].nid, NULL); /* keygen ctx from NID */ + if (!kctx) { + EVP_PKEY_CTX *pctx = NULL; + EVP_PKEY *params = NULL; + + /* If we reach this code EVP_PKEY_CTX_new_id() failed and a + * "int_ctx_new:unsupported algorithm" error was added to the + * error queue. + * We remove it from the error queue as we are handling it. */ + unsigned long error = ERR_peek_error(); /* peek the latest error in the queue */ + if (error == ERR_peek_last_error() && /* oldest and latest errors match */ + /* check that the error origin matches */ + ERR_GET_LIB(error) == ERR_LIB_EVP && + ERR_GET_FUNC(error) == EVP_F_INT_CTX_NEW && + ERR_GET_REASON(error) == EVP_R_UNSUPPORTED_ALGORITHM) + ERR_get_error(); /* pop error from queue */ + if (ERR_peek_error()) { + BIO_printf(bio_err, + "Unhandled error in the error queue during ECDH init.\n"); + ERR_print_errors(bio_err); + rsa_count = 1; + break; + } + + if ( /* Create the context for parameter generation */ + !(pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) || + /* Initialise the parameter generation */ + !EVP_PKEY_paramgen_init(pctx) || + /* Set the curve by NID */ + !EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, + test_curves + [testnum].nid) || + /* Create the parameter object params */ + !EVP_PKEY_paramgen(pctx, ¶ms)) { + ecdh_checks = 0; + BIO_printf(bio_err, "ECDH EC params init failure.\n"); + ERR_print_errors(bio_err); + rsa_count = 1; + break; + } + /* Create the context for the key generation */ + kctx = EVP_PKEY_CTX_new(params, NULL); + + EVP_PKEY_free(params); + params = NULL; + EVP_PKEY_CTX_free(pctx); + pctx = NULL; + } + if (kctx == NULL || /* keygen ctx is not null */ + !EVP_PKEY_keygen_init(kctx) /* init keygen ctx */ ) { + ecdh_checks = 0; + BIO_printf(bio_err, "ECDH keygen failure.\n"); + ERR_print_errors(bio_err); + rsa_count = 1; + break; + } + + if (!EVP_PKEY_keygen(kctx, &key_A) || /* generate secret key A */ + !EVP_PKEY_keygen(kctx, &key_B) || /* generate secret key B */ + !(ctx = EVP_PKEY_CTX_new(key_A, NULL)) || /* derivation ctx from skeyA */ + !EVP_PKEY_derive_init(ctx) || /* init derivation ctx */ + !EVP_PKEY_derive_set_peer(ctx, key_B) || /* set peer pubkey in ctx */ + !EVP_PKEY_derive(ctx, NULL, &outlen) || /* determine max length */ + outlen == 0 || /* ensure outlen is a valid size */ + outlen > MAX_ECDH_SIZE /* avoid buffer overflow */ ) { + ecdh_checks = 0; + BIO_printf(bio_err, "ECDH key generation failure.\n"); + ERR_print_errors(bio_err); + rsa_count = 1; + break; + } + + /* Here we perform a test run, comparing the output of a*B and b*A; + * we try this here and assume that further EVP_PKEY_derive calls + * never fail, so we can skip checks in the actually benchmarked + * code, for maximum performance. */ + if (!(test_ctx = EVP_PKEY_CTX_new(key_B, NULL)) || /* test ctx from skeyB */ + !EVP_PKEY_derive_init(test_ctx) || /* init derivation test_ctx */ + !EVP_PKEY_derive_set_peer(test_ctx, key_A) || /* set peer pubkey in test_ctx */ + !EVP_PKEY_derive(test_ctx, NULL, &test_outlen) || /* determine max length */ + !EVP_PKEY_derive(ctx, loopargs[i].secret_a, &outlen) || /* compute a*B */ + !EVP_PKEY_derive(test_ctx, loopargs[i].secret_b, &test_outlen) || /* compute b*A */ + test_outlen != outlen /* compare output length */ ) { + ecdh_checks = 0; + BIO_printf(bio_err, "ECDH computation failure.\n"); + ERR_print_errors(bio_err); + rsa_count = 1; + break; + } + + /* Compare the computation results: CRYPTO_memcmp() returns 0 if equal */ + if (CRYPTO_memcmp(loopargs[i].secret_a, + loopargs[i].secret_b, outlen)) { + ecdh_checks = 0; + BIO_printf(bio_err, "ECDH computations don't match.\n"); + ERR_print_errors(bio_err); + rsa_count = 1; + break; + } + + loopargs[i].ecdh_ctx[testnum] = ctx; + loopargs[i].outlen[testnum] = outlen; + + EVP_PKEY_free(key_A); + EVP_PKEY_free(key_B); + EVP_PKEY_CTX_free(kctx); + kctx = NULL; + EVP_PKEY_CTX_free(test_ctx); + test_ctx = NULL; + } + if (ecdh_checks != 0) { + pkey_print_message("", "ecdh", + ecdh_c[testnum][0], + test_curves[testnum].bits, seconds.ecdh); + Time_F(START); + count = + run_benchmark(async_jobs, ECDH_EVP_derive_key_loop, loopargs); + d = Time_F(STOP); + BIO_printf(bio_err, + mr ? "+R7:%ld:%d:%.2f\n" : + "%ld %u-bits ECDH ops in %.2fs\n", count, + test_curves[testnum].bits, d); + ecdh_results[testnum][0] = (double)count / d; + rsa_count = count; + } + + if (rsa_count <= 1) { + /* if longer than 10s, don't do any more */ + for (testnum++; testnum < OSSL_NELEM(ecdh_doit); testnum++) + ecdh_doit[testnum] = 0; + } + } + + for (testnum = 0; testnum < EdDSA_NUM; testnum++) { + int st = 1; + EVP_PKEY *ed_pkey = NULL; + EVP_PKEY_CTX *ed_pctx = NULL; + + if (!eddsa_doit[testnum]) + continue; /* Ignore Curve */ + for (i = 0; i < loopargs_len; i++) { + loopargs[i].eddsa_ctx[testnum] = EVP_MD_CTX_new(); + if (loopargs[i].eddsa_ctx[testnum] == NULL) { + st = 0; + break; + } + + if ((ed_pctx = EVP_PKEY_CTX_new_id(test_ed_curves[testnum].nid, NULL)) + == NULL + || !EVP_PKEY_keygen_init(ed_pctx) + || !EVP_PKEY_keygen(ed_pctx, &ed_pkey)) { + st = 0; + EVP_PKEY_CTX_free(ed_pctx); + break; + } + EVP_PKEY_CTX_free(ed_pctx); + + if (!EVP_DigestSignInit(loopargs[i].eddsa_ctx[testnum], NULL, NULL, + NULL, ed_pkey)) { + st = 0; + EVP_PKEY_free(ed_pkey); + break; + } + EVP_PKEY_free(ed_pkey); + } + if (st == 0) { + BIO_printf(bio_err, "EdDSA failure.\n"); + ERR_print_errors(bio_err); + rsa_count = 1; + } else { + for (i = 0; i < loopargs_len; i++) { + /* Perform EdDSA signature test */ + loopargs[i].sigsize = test_ed_curves[testnum].sigsize; + st = EVP_DigestSign(loopargs[i].eddsa_ctx[testnum], + loopargs[i].buf2, &loopargs[i].sigsize, + loopargs[i].buf, 20); + if (st == 0) + break; + } + if (st == 0) { + BIO_printf(bio_err, + "EdDSA sign failure. No EdDSA sign will be done.\n"); + ERR_print_errors(bio_err); + rsa_count = 1; + } else { + pkey_print_message("sign", test_ed_curves[testnum].name, + eddsa_c[testnum][0], + test_ed_curves[testnum].bits, seconds.eddsa); + Time_F(START); + count = run_benchmark(async_jobs, EdDSA_sign_loop, loopargs); + d = Time_F(STOP); + + BIO_printf(bio_err, + mr ? "+R8:%ld:%u:%s:%.2f\n" : + "%ld %u bits %s signs in %.2fs \n", + count, test_ed_curves[testnum].bits, + test_ed_curves[testnum].name, d); + eddsa_results[testnum][0] = (double)count / d; + rsa_count = count; + } + + /* Perform EdDSA verification test */ + for (i = 0; i < loopargs_len; i++) { + st = EVP_DigestVerify(loopargs[i].eddsa_ctx[testnum], + loopargs[i].buf2, loopargs[i].sigsize, + loopargs[i].buf, 20); + if (st != 1) + break; + } + if (st != 1) { + BIO_printf(bio_err, + "EdDSA verify failure. No EdDSA verify will be done.\n"); + ERR_print_errors(bio_err); + eddsa_doit[testnum] = 0; + } else { + pkey_print_message("verify", test_ed_curves[testnum].name, + eddsa_c[testnum][1], + test_ed_curves[testnum].bits, seconds.eddsa); + Time_F(START); + count = run_benchmark(async_jobs, EdDSA_verify_loop, loopargs); + d = Time_F(STOP); + BIO_printf(bio_err, + mr ? "+R9:%ld:%u:%s:%.2f\n" + : "%ld %u bits %s verify in %.2fs\n", + count, test_ed_curves[testnum].bits, + test_ed_curves[testnum].name, d); + eddsa_results[testnum][1] = (double)count / d; + } + + if (rsa_count <= 1) { + /* if longer than 10s, don't do any more */ + for (testnum++; testnum < EdDSA_NUM; testnum++) + eddsa_doit[testnum] = 0; + } + } + } + +#endif /* OPENSSL_NO_EC */ +#ifndef NO_FORK + show_res: +#endif + if (!mr) { + printf("%s\n", OpenSSL_version(OPENSSL_VERSION)); + printf("%s\n", OpenSSL_version(OPENSSL_BUILT_ON)); + printf("options:"); + printf("%s ", BN_options()); +#ifndef OPENSSL_NO_MD2 + printf("%s ", MD2_options()); +#endif +#ifndef OPENSSL_NO_RC4 + printf("%s ", RC4_options()); +#endif +#ifndef OPENSSL_NO_DES + printf("%s ", DES_options()); +#endif + printf("%s ", AES_options()); +#ifndef OPENSSL_NO_IDEA + printf("%s ", IDEA_options()); +#endif +#ifndef OPENSSL_NO_BF + printf("%s ", BF_options()); +#endif + printf("\n%s\n", OpenSSL_version(OPENSSL_CFLAGS)); + } + + if (pr_header) { + if (mr) + printf("+H"); + else { + printf + ("The 'numbers' are in 1000s of bytes per second processed.\n"); + printf("type "); + } + for (testnum = 0; testnum < size_num; testnum++) + printf(mr ? ":%d" : "%7d bytes", lengths[testnum]); + printf("\n"); + } + + for (k = 0; k < ALGOR_NUM; k++) { + if (!doit[k]) + continue; + if (mr) + printf("+F:%u:%s", k, names[k]); + else + printf("%-13s", names[k]); + for (testnum = 0; testnum < size_num; testnum++) { + if (results[k][testnum] > 10000 && !mr) + printf(" %11.2fk", results[k][testnum] / 1e3); + else + printf(mr ? ":%.2f" : " %11.2f ", results[k][testnum]); + } + printf("\n"); + } +#ifndef OPENSSL_NO_RSA + testnum = 1; + for (k = 0; k < RSA_NUM; k++) { + if (!rsa_doit[k]) + continue; + if (testnum && !mr) { + printf("%18ssign verify sign/s verify/s\n", " "); + testnum = 0; + } + if (mr) + printf("+F2:%u:%u:%f:%f\n", + k, rsa_bits[k], rsa_results[k][0], rsa_results[k][1]); + else + printf("rsa %4u bits %8.6fs %8.6fs %8.1f %8.1f\n", + rsa_bits[k], 1.0 / rsa_results[k][0], 1.0 / rsa_results[k][1], + rsa_results[k][0], rsa_results[k][1]); + } +#endif +#ifndef OPENSSL_NO_DSA + testnum = 1; + for (k = 0; k < DSA_NUM; k++) { + if (!dsa_doit[k]) + continue; + if (testnum && !mr) { + printf("%18ssign verify sign/s verify/s\n", " "); + testnum = 0; + } + if (mr) + printf("+F3:%u:%u:%f:%f\n", + k, dsa_bits[k], dsa_results[k][0], dsa_results[k][1]); + else + printf("dsa %4u bits %8.6fs %8.6fs %8.1f %8.1f\n", + dsa_bits[k], 1.0 / dsa_results[k][0], 1.0 / dsa_results[k][1], + dsa_results[k][0], dsa_results[k][1]); + } +#endif +#ifndef OPENSSL_NO_EC + testnum = 1; + for (k = 0; k < OSSL_NELEM(ecdsa_doit); k++) { + if (!ecdsa_doit[k]) + continue; + if (testnum && !mr) { + printf("%30ssign verify sign/s verify/s\n", " "); + testnum = 0; + } + + if (mr) + printf("+F4:%u:%u:%f:%f\n", + k, test_curves[k].bits, + ecdsa_results[k][0], ecdsa_results[k][1]); + else + printf("%4u bits ecdsa (%s) %8.4fs %8.4fs %8.1f %8.1f\n", + test_curves[k].bits, test_curves[k].name, + 1.0 / ecdsa_results[k][0], 1.0 / ecdsa_results[k][1], + ecdsa_results[k][0], ecdsa_results[k][1]); + } + + testnum = 1; + for (k = 0; k < EC_NUM; k++) { + if (!ecdh_doit[k]) + continue; + if (testnum && !mr) { + printf("%30sop op/s\n", " "); + testnum = 0; + } + if (mr) + printf("+F5:%u:%u:%f:%f\n", + k, test_curves[k].bits, + ecdh_results[k][0], 1.0 / ecdh_results[k][0]); + + else + printf("%4u bits ecdh (%s) %8.4fs %8.1f\n", + test_curves[k].bits, test_curves[k].name, + 1.0 / ecdh_results[k][0], ecdh_results[k][0]); + } + + testnum = 1; + for (k = 0; k < OSSL_NELEM(eddsa_doit); k++) { + if (!eddsa_doit[k]) + continue; + if (testnum && !mr) { + printf("%30ssign verify sign/s verify/s\n", " "); + testnum = 0; + } + + if (mr) + printf("+F6:%u:%u:%s:%f:%f\n", + k, test_ed_curves[k].bits, test_ed_curves[k].name, + eddsa_results[k][0], eddsa_results[k][1]); + else + printf("%4u bits EdDSA (%s) %8.4fs %8.4fs %8.1f %8.1f\n", + test_ed_curves[k].bits, test_ed_curves[k].name, + 1.0 / eddsa_results[k][0], 1.0 / eddsa_results[k][1], + eddsa_results[k][0], eddsa_results[k][1]); + } +#endif + + ret = 0; + + end: + ERR_print_errors(bio_err); + for (i = 0; i < loopargs_len; i++) { + OPENSSL_free(loopargs[i].buf_malloc); + OPENSSL_free(loopargs[i].buf2_malloc); + +#ifndef OPENSSL_NO_RSA + for (k = 0; k < RSA_NUM; k++) + RSA_free(loopargs[i].rsa_key[k]); +#endif +#ifndef OPENSSL_NO_DSA + for (k = 0; k < DSA_NUM; k++) + DSA_free(loopargs[i].dsa_key[k]); +#endif +#ifndef OPENSSL_NO_EC + for (k = 0; k < ECDSA_NUM; k++) + EC_KEY_free(loopargs[i].ecdsa[k]); + for (k = 0; k < EC_NUM; k++) + EVP_PKEY_CTX_free(loopargs[i].ecdh_ctx[k]); + for (k = 0; k < EdDSA_NUM; k++) + EVP_MD_CTX_free(loopargs[i].eddsa_ctx[k]); + OPENSSL_free(loopargs[i].secret_a); + OPENSSL_free(loopargs[i].secret_b); +#endif + } + + if (async_jobs > 0) { + for (i = 0; i < loopargs_len; i++) + ASYNC_WAIT_CTX_free(loopargs[i].wait_ctx); + } + + if (async_init) { + ASYNC_cleanup_thread(); + } + OPENSSL_free(loopargs); + release_engine(e); + return ret; +} + +static void print_message(const char *s, long num, int length, int tm) +{ +#ifdef SIGALRM + BIO_printf(bio_err, + mr ? "+DT:%s:%d:%d\n" + : "Doing %s for %ds on %d size blocks: ", s, tm, length); + (void)BIO_flush(bio_err); + alarm(tm); +#else + BIO_printf(bio_err, + mr ? "+DN:%s:%ld:%d\n" + : "Doing %s %ld times on %d size blocks: ", s, num, length); + (void)BIO_flush(bio_err); +#endif +} + +static void pkey_print_message(const char *str, const char *str2, long num, + unsigned int bits, int tm) +{ +#ifdef SIGALRM + BIO_printf(bio_err, + mr ? "+DTP:%d:%s:%s:%d\n" + : "Doing %u bits %s %s's for %ds: ", bits, str, str2, tm); + (void)BIO_flush(bio_err); + alarm(tm); +#else + BIO_printf(bio_err, + mr ? "+DNP:%ld:%d:%s:%s\n" + : "Doing %ld %u bits %s %s's: ", num, bits, str, str2); + (void)BIO_flush(bio_err); +#endif +} + +static void print_result(int alg, int run_no, int count, double time_used) +{ + if (count == -1) { + BIO_puts(bio_err, "EVP error!\n"); + exit(1); + } + BIO_printf(bio_err, + mr ? "+R:%d:%s:%f\n" + : "%d %s's in %.2fs\n", count, names[alg], time_used); + results[alg][run_no] = ((double)count) / time_used * lengths[run_no]; +} + +#ifndef NO_FORK +static char *sstrsep(char **string, const char *delim) +{ + char isdelim[256]; + char *token = *string; + + if (**string == 0) + return NULL; + + memset(isdelim, 0, sizeof(isdelim)); + isdelim[0] = 1; + + while (*delim) { + isdelim[(unsigned char)(*delim)] = 1; + delim++; + } + + while (!isdelim[(unsigned char)(**string)]) { + (*string)++; + } + + if (**string) { + **string = 0; + (*string)++; + } + + return token; +} + +static int do_multi(int multi, int size_num) +{ + int n; + int fd[2]; + int *fds; + static char sep[] = ":"; + + fds = app_malloc(sizeof(*fds) * multi, "fd buffer for do_multi"); + for (n = 0; n < multi; ++n) { + if (pipe(fd) == -1) { + BIO_printf(bio_err, "pipe failure\n"); + exit(1); + } + fflush(stdout); + (void)BIO_flush(bio_err); + if (fork()) { + close(fd[1]); + fds[n] = fd[0]; + } else { + close(fd[0]); + close(1); + if (dup(fd[1]) == -1) { + BIO_printf(bio_err, "dup failed\n"); + exit(1); + } + close(fd[1]); + mr = 1; + usertime = 0; + free(fds); + return 0; + } + printf("Forked child %d\n", n); + } + + /* for now, assume the pipe is long enough to take all the output */ + for (n = 0; n < multi; ++n) { + FILE *f; + char buf[1024]; + char *p; + + f = fdopen(fds[n], "r"); + while (fgets(buf, sizeof(buf), f)) { + p = strchr(buf, '\n'); + if (p) + *p = '\0'; + if (buf[0] != '+') { + BIO_printf(bio_err, + "Don't understand line '%s' from child %d\n", buf, + n); + continue; + } + printf("Got: %s from %d\n", buf, n); + if (strncmp(buf, "+F:", 3) == 0) { + int alg; + int j; + + p = buf + 3; + alg = atoi(sstrsep(&p, sep)); + sstrsep(&p, sep); + for (j = 0; j < size_num; ++j) + results[alg][j] += atof(sstrsep(&p, sep)); + } else if (strncmp(buf, "+F2:", 4) == 0) { + int k; + double d; + + p = buf + 4; + k = atoi(sstrsep(&p, sep)); + sstrsep(&p, sep); + + d = atof(sstrsep(&p, sep)); + rsa_results[k][0] += d; + + d = atof(sstrsep(&p, sep)); + rsa_results[k][1] += d; + } +# ifndef OPENSSL_NO_DSA + else if (strncmp(buf, "+F3:", 4) == 0) { + int k; + double d; + + p = buf + 4; + k = atoi(sstrsep(&p, sep)); + sstrsep(&p, sep); + + d = atof(sstrsep(&p, sep)); + dsa_results[k][0] += d; + + d = atof(sstrsep(&p, sep)); + dsa_results[k][1] += d; + } +# endif +# ifndef OPENSSL_NO_EC + else if (strncmp(buf, "+F4:", 4) == 0) { + int k; + double d; + + p = buf + 4; + k = atoi(sstrsep(&p, sep)); + sstrsep(&p, sep); + + d = atof(sstrsep(&p, sep)); + ecdsa_results[k][0] += d; + + d = atof(sstrsep(&p, sep)); + ecdsa_results[k][1] += d; + } else if (strncmp(buf, "+F5:", 4) == 0) { + int k; + double d; + + p = buf + 4; + k = atoi(sstrsep(&p, sep)); + sstrsep(&p, sep); + + d = atof(sstrsep(&p, sep)); + ecdh_results[k][0] += d; + } else if (strncmp(buf, "+F6:", 4) == 0) { + int k; + double d; + + p = buf + 4; + k = atoi(sstrsep(&p, sep)); + sstrsep(&p, sep); + + d = atof(sstrsep(&p, sep)); + eddsa_results[k][0] += d; + + d = atof(sstrsep(&p, sep)); + eddsa_results[k][1] += d; + } +# endif + + else if (strncmp(buf, "+H:", 3) == 0) { + ; + } else + BIO_printf(bio_err, "Unknown type '%s' from child %d\n", buf, + n); + } + + fclose(f); + } + free(fds); + return 1; +} +#endif + +static void multiblock_speed(const EVP_CIPHER *evp_cipher, int lengths_single, + const openssl_speed_sec_t *seconds) +{ + static const int mblengths_list[] = + { 8 * 1024, 2 * 8 * 1024, 4 * 8 * 1024, 8 * 8 * 1024, 8 * 16 * 1024 }; + const int *mblengths = mblengths_list; + int j, count, keylen, num = OSSL_NELEM(mblengths_list); + const char *alg_name; + unsigned char *inp, *out, *key, no_key[32], no_iv[16]; + EVP_CIPHER_CTX *ctx; + double d = 0.0; + + if (lengths_single) { + mblengths = &lengths_single; + num = 1; + } + + inp = app_malloc(mblengths[num - 1], "multiblock input buffer"); + out = app_malloc(mblengths[num - 1] + 1024, "multiblock output buffer"); + ctx = EVP_CIPHER_CTX_new(); + EVP_EncryptInit_ex(ctx, evp_cipher, NULL, NULL, no_iv); + + keylen = EVP_CIPHER_CTX_key_length(ctx); + key = app_malloc(keylen, "evp_cipher key"); + EVP_CIPHER_CTX_rand_key(ctx, key); + EVP_EncryptInit_ex(ctx, NULL, NULL, key, NULL); + OPENSSL_clear_free(key, keylen); + + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_MAC_KEY, sizeof(no_key), no_key); + alg_name = OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher)); + + for (j = 0; j < num; j++) { + print_message(alg_name, 0, mblengths[j], seconds->sym); + Time_F(START); + for (count = 0, run = 1; run && count < 0x7fffffff; count++) { + unsigned char aad[EVP_AEAD_TLS1_AAD_LEN]; + EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM mb_param; + size_t len = mblengths[j]; + int packlen; + + memset(aad, 0, 8); /* avoid uninitialized values */ + aad[8] = 23; /* SSL3_RT_APPLICATION_DATA */ + aad[9] = 3; /* version */ + aad[10] = 2; + aad[11] = 0; /* length */ + aad[12] = 0; + mb_param.out = NULL; + mb_param.inp = aad; + mb_param.len = len; + mb_param.interleave = 8; + + packlen = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_TLS1_1_MULTIBLOCK_AAD, + sizeof(mb_param), &mb_param); + + if (packlen > 0) { + mb_param.out = out; + mb_param.inp = inp; + mb_param.len = len; + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT, + sizeof(mb_param), &mb_param); + } else { + int pad; + + RAND_bytes(out, 16); + len += 16; + aad[11] = (unsigned char)(len >> 8); + aad[12] = (unsigned char)(len); + pad = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_TLS1_AAD, + EVP_AEAD_TLS1_AAD_LEN, aad); + EVP_Cipher(ctx, out, inp, len + pad); + } + } + d = Time_F(STOP); + BIO_printf(bio_err, mr ? "+R:%d:%s:%f\n" + : "%d %s's in %.2fs\n", count, "evp", d); + results[D_EVP][j] = ((double)count) / d * mblengths[j]; + } + + if (mr) { + fprintf(stdout, "+H"); + for (j = 0; j < num; j++) + fprintf(stdout, ":%d", mblengths[j]); + fprintf(stdout, "\n"); + fprintf(stdout, "+F:%d:%s", D_EVP, alg_name); + for (j = 0; j < num; j++) + fprintf(stdout, ":%.2f", results[D_EVP][j]); + fprintf(stdout, "\n"); + } else { + fprintf(stdout, + "The 'numbers' are in 1000s of bytes per second processed.\n"); + fprintf(stdout, "type "); + for (j = 0; j < num; j++) + fprintf(stdout, "%7d bytes", mblengths[j]); + fprintf(stdout, "\n"); + fprintf(stdout, "%-24s", alg_name); + + for (j = 0; j < num; j++) { + if (results[D_EVP][j] > 10000) + fprintf(stdout, " %11.2fk", results[D_EVP][j] / 1e3); + else + fprintf(stdout, " %11.2f ", results[D_EVP][j]); + } + fprintf(stdout, "\n"); + } + + OPENSSL_free(inp); + OPENSSL_free(out); + EVP_CIPHER_CTX_free(ctx); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/spkac.c b/trunk/3rdparty/openssl-1.1-fit/apps/spkac.c new file mode 100644 index 000000000..f384af6eb --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/spkac.c @@ -0,0 +1,202 @@ +/* + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include +#include +#include + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_NOOUT, OPT_PUBKEY, OPT_VERIFY, OPT_IN, OPT_OUT, + OPT_ENGINE, OPT_KEY, OPT_CHALLENGE, OPT_PASSIN, OPT_SPKAC, + OPT_SPKSECT, OPT_KEYFORM +} OPTION_CHOICE; + +const OPTIONS spkac_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"in", OPT_IN, '<', "Input file"}, + {"out", OPT_OUT, '>', "Output file"}, + {"key", OPT_KEY, '<', "Create SPKAC using private key"}, + {"keyform", OPT_KEYFORM, 'f', "Private key file format - default PEM (PEM, DER, or ENGINE)"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"challenge", OPT_CHALLENGE, 's', "Challenge string"}, + {"spkac", OPT_SPKAC, 's', "Alternative SPKAC name"}, + {"noout", OPT_NOOUT, '-', "Don't print SPKAC"}, + {"pubkey", OPT_PUBKEY, '-', "Output public key"}, + {"verify", OPT_VERIFY, '-', "Verify SPKAC signature"}, + {"spksect", OPT_SPKSECT, 's', + "Specify the name of an SPKAC-dedicated section of configuration"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + {NULL} +}; + +int spkac_main(int argc, char **argv) +{ + BIO *out = NULL; + CONF *conf = NULL; + ENGINE *e = NULL; + EVP_PKEY *pkey = NULL; + NETSCAPE_SPKI *spki = NULL; + char *challenge = NULL, *keyfile = NULL; + char *infile = NULL, *outfile = NULL, *passinarg = NULL, *passin = NULL; + char *spkstr = NULL, *prog; + const char *spkac = "SPKAC", *spksect = "default"; + int i, ret = 1, verify = 0, noout = 0, pubkey = 0; + int keyformat = FORMAT_PEM; + OPTION_CHOICE o; + + prog = opt_init(argc, argv, spkac_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(spkac_options); + ret = 0; + goto end; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_NOOUT: + noout = 1; + break; + case OPT_PUBKEY: + pubkey = 1; + break; + case OPT_VERIFY: + verify = 1; + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_KEY: + keyfile = opt_arg(); + break; + case OPT_KEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyformat)) + goto opthelp; + break; + case OPT_CHALLENGE: + challenge = opt_arg(); + break; + case OPT_SPKAC: + spkac = opt_arg(); + break; + case OPT_SPKSECT: + spksect = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + } + } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + + if (!app_passwd(passinarg, NULL, &passin, NULL)) { + BIO_printf(bio_err, "Error getting password\n"); + goto end; + } + + if (keyfile != NULL) { + pkey = load_key(strcmp(keyfile, "-") ? keyfile : NULL, + keyformat, 1, passin, e, "private key"); + if (pkey == NULL) + goto end; + spki = NETSCAPE_SPKI_new(); + if (spki == NULL) + goto end; + if (challenge != NULL) + ASN1_STRING_set(spki->spkac->challenge, + challenge, (int)strlen(challenge)); + NETSCAPE_SPKI_set_pubkey(spki, pkey); + NETSCAPE_SPKI_sign(spki, pkey, EVP_md5()); + spkstr = NETSCAPE_SPKI_b64_encode(spki); + if (spkstr == NULL) + goto end; + + out = bio_open_default(outfile, 'w', FORMAT_TEXT); + if (out == NULL) { + OPENSSL_free(spkstr); + goto end; + } + BIO_printf(out, "SPKAC=%s\n", spkstr); + OPENSSL_free(spkstr); + ret = 0; + goto end; + } + + if ((conf = app_load_config(infile)) == NULL) + goto end; + + spkstr = NCONF_get_string(conf, spksect, spkac); + + if (spkstr == NULL) { + BIO_printf(bio_err, "Can't find SPKAC called \"%s\"\n", spkac); + ERR_print_errors(bio_err); + goto end; + } + + spki = NETSCAPE_SPKI_b64_decode(spkstr, -1); + + if (spki == NULL) { + BIO_printf(bio_err, "Error loading SPKAC\n"); + ERR_print_errors(bio_err); + goto end; + } + + out = bio_open_default(outfile, 'w', FORMAT_TEXT); + if (out == NULL) + goto end; + + if (!noout) + NETSCAPE_SPKI_print(out, spki); + pkey = NETSCAPE_SPKI_get_pubkey(spki); + if (verify) { + i = NETSCAPE_SPKI_verify(spki, pkey); + if (i > 0) { + BIO_printf(bio_err, "Signature OK\n"); + } else { + BIO_printf(bio_err, "Signature Failure\n"); + ERR_print_errors(bio_err); + goto end; + } + } + if (pubkey) + PEM_write_bio_PUBKEY(out, pkey); + + ret = 0; + + end: + NCONF_free(conf); + NETSCAPE_SPKI_free(spki); + BIO_free_all(out); + EVP_PKEY_free(pkey); + release_engine(e); + OPENSSL_free(passin); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/srp.c b/trunk/3rdparty/openssl-1.1-fit/apps/srp.c new file mode 100644 index 000000000..689574a48 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/srp.c @@ -0,0 +1,613 @@ +/* + * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2004, EdelKey Project. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + * + * Originally written by Christophe Renou and Peter Sylvester, + * for the EdelKey project. + */ + +#include +#ifdef OPENSSL_NO_SRP +NON_EMPTY_TRANSLATION_UNIT +#else + +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include "apps.h" +# include "progs.h" + +# define BASE_SECTION "srp" +# define CONFIG_FILE "openssl.cnf" + + +# define ENV_DATABASE "srpvfile" +# define ENV_DEFAULT_SRP "default_srp" + +static int get_index(CA_DB *db, char *id, char type) +{ + char **pp; + int i; + if (id == NULL) + return -1; + if (type == DB_SRP_INDEX) { + for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { + pp = sk_OPENSSL_PSTRING_value(db->db->data, i); + if (pp[DB_srptype][0] == DB_SRP_INDEX + && strcmp(id, pp[DB_srpid]) == 0) + return i; + } + } else { + for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { + pp = sk_OPENSSL_PSTRING_value(db->db->data, i); + + if (pp[DB_srptype][0] != DB_SRP_INDEX + && strcmp(id, pp[DB_srpid]) == 0) + return i; + } + } + + return -1; +} + +static void print_entry(CA_DB *db, int indx, int verbose, char *s) +{ + if (indx >= 0 && verbose) { + int j; + char **pp = sk_OPENSSL_PSTRING_value(db->db->data, indx); + BIO_printf(bio_err, "%s \"%s\"\n", s, pp[DB_srpid]); + for (j = 0; j < DB_NUMBER; j++) { + BIO_printf(bio_err, " %d = \"%s\"\n", j, pp[j]); + } + } +} + +static void print_index(CA_DB *db, int indexindex, int verbose) +{ + print_entry(db, indexindex, verbose, "g N entry"); +} + +static void print_user(CA_DB *db, int userindex, int verbose) +{ + if (verbose > 0) { + char **pp = sk_OPENSSL_PSTRING_value(db->db->data, userindex); + + if (pp[DB_srptype][0] != 'I') { + print_entry(db, userindex, verbose, "User entry"); + print_entry(db, get_index(db, pp[DB_srpgN], 'I'), verbose, + "g N entry"); + } + + } +} + +static int update_index(CA_DB *db, char **row) +{ + char **irow; + int i; + + irow = app_malloc(sizeof(*irow) * (DB_NUMBER + 1), "row pointers"); + for (i = 0; i < DB_NUMBER; i++) + irow[i] = row[i]; + irow[DB_NUMBER] = NULL; + + if (!TXT_DB_insert(db->db, irow)) { + BIO_printf(bio_err, "failed to update srpvfile\n"); + BIO_printf(bio_err, "TXT_DB error number %ld\n", db->db->error); + OPENSSL_free(irow); + return 0; + } + return 1; +} + +static char *lookup_conf(const CONF *conf, const char *section, const char *tag) +{ + char *entry = NCONF_get_string(conf, section, tag); + if (entry == NULL) + BIO_printf(bio_err, "variable lookup failed for %s::%s\n", section, tag); + return entry; +} + +static char *srp_verify_user(const char *user, const char *srp_verifier, + char *srp_usersalt, const char *g, const char *N, + const char *passin, int verbose) +{ + char password[1025]; + PW_CB_DATA cb_tmp; + char *verifier = NULL; + char *gNid = NULL; + int len; + + cb_tmp.prompt_info = user; + cb_tmp.password = passin; + + len = password_callback(password, sizeof(password)-1, 0, &cb_tmp); + if (len > 0) { + password[len] = 0; + if (verbose) + BIO_printf(bio_err, + "Validating\n user=\"%s\"\n srp_verifier=\"%s\"\n srp_usersalt=\"%s\"\n g=\"%s\"\n N=\"%s\"\n", + user, srp_verifier, srp_usersalt, g, N); + if (verbose > 1) + BIO_printf(bio_err, "Pass %s\n", password); + + OPENSSL_assert(srp_usersalt != NULL); + if ((gNid = SRP_create_verifier(user, password, &srp_usersalt, + &verifier, N, g)) == NULL) { + BIO_printf(bio_err, "Internal error validating SRP verifier\n"); + } else { + if (strcmp(verifier, srp_verifier)) + gNid = NULL; + OPENSSL_free(verifier); + } + OPENSSL_cleanse(password, len); + } + return gNid; +} + +static char *srp_create_user(char *user, char **srp_verifier, + char **srp_usersalt, char *g, char *N, + char *passout, int verbose) +{ + char password[1025]; + PW_CB_DATA cb_tmp; + char *gNid = NULL; + char *salt = NULL; + int len; + cb_tmp.prompt_info = user; + cb_tmp.password = passout; + + len = password_callback(password, sizeof(password)-1, 1, &cb_tmp); + if (len > 0) { + password[len] = 0; + if (verbose) + BIO_printf(bio_err, "Creating\n user=\"%s\"\n g=\"%s\"\n N=\"%s\"\n", + user, g, N); + if ((gNid = SRP_create_verifier(user, password, &salt, + srp_verifier, N, g)) == NULL) { + BIO_printf(bio_err, "Internal error creating SRP verifier\n"); + } else { + *srp_usersalt = salt; + } + OPENSSL_cleanse(password, len); + if (verbose > 1) + BIO_printf(bio_err, "gNid=%s salt =\"%s\"\n verifier =\"%s\"\n", + gNid, salt, *srp_verifier); + + } + return gNid; +} + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_VERBOSE, OPT_CONFIG, OPT_NAME, OPT_SRPVFILE, OPT_ADD, + OPT_DELETE, OPT_MODIFY, OPT_LIST, OPT_GN, OPT_USERINFO, + OPT_PASSIN, OPT_PASSOUT, OPT_ENGINE, OPT_R_ENUM +} OPTION_CHOICE; + +const OPTIONS srp_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"verbose", OPT_VERBOSE, '-', "Talk a lot while doing things"}, + {"config", OPT_CONFIG, '<', "A config file"}, + {"name", OPT_NAME, 's', "The particular srp definition to use"}, + {"srpvfile", OPT_SRPVFILE, '<', "The srp verifier file name"}, + {"add", OPT_ADD, '-', "Add a user and srp verifier"}, + {"modify", OPT_MODIFY, '-', + "Modify the srp verifier of an existing user"}, + {"delete", OPT_DELETE, '-', "Delete user from verifier file"}, + {"list", OPT_LIST, '-', "List users"}, + {"gn", OPT_GN, 's', "Set g and N values to be used for new verifier"}, + {"userinfo", OPT_USERINFO, 's', "Additional info to be set for user"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, + OPT_R_OPTIONS, +# ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +# endif + {NULL} +}; + +int srp_main(int argc, char **argv) +{ + ENGINE *e = NULL; + CA_DB *db = NULL; + CONF *conf = NULL; + int gNindex = -1, maxgN = -1, ret = 1, errors = 0, verbose = 0, i; + int doupdatedb = 0, mode = OPT_ERR; + char *user = NULL, *passinarg = NULL, *passoutarg = NULL; + char *passin = NULL, *passout = NULL, *gN = NULL, *userinfo = NULL; + char *section = NULL; + char **gNrow = NULL, *configfile = NULL; + char *srpvfile = NULL, **pp, *prog; + OPTION_CHOICE o; + + prog = opt_init(argc, argv, srp_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(srp_options); + ret = 0; + goto end; + case OPT_VERBOSE: + verbose++; + break; + case OPT_CONFIG: + configfile = opt_arg(); + break; + case OPT_NAME: + section = opt_arg(); + break; + case OPT_SRPVFILE: + srpvfile = opt_arg(); + break; + case OPT_ADD: + case OPT_DELETE: + case OPT_MODIFY: + case OPT_LIST: + if (mode != OPT_ERR) { + BIO_printf(bio_err, + "%s: Only one of -add/-delete/-modify/-list\n", + prog); + goto opthelp; + } + mode = o; + break; + case OPT_GN: + gN = opt_arg(); + break; + case OPT_USERINFO: + userinfo = opt_arg(); + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_PASSOUT: + passoutarg = opt_arg(); + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + } + } + argc = opt_num_rest(); + argv = opt_rest(); + + if (srpvfile != NULL && configfile != NULL) { + BIO_printf(bio_err, + "-srpvfile and -configfile cannot be specified together.\n"); + goto end; + } + if (mode == OPT_ERR) { + BIO_printf(bio_err, + "Exactly one of the options -add, -delete, -modify -list must be specified.\n"); + goto opthelp; + } + if (mode == OPT_DELETE || mode == OPT_MODIFY || mode == OPT_ADD) { + if (argc == 0) { + BIO_printf(bio_err, "Need at least one user.\n"); + goto opthelp; + } + user = *argv++; + } + if ((passinarg != NULL || passoutarg != NULL) && argc != 1) { + BIO_printf(bio_err, + "-passin, -passout arguments only valid with one user.\n"); + goto opthelp; + } + + if (!app_passwd(passinarg, passoutarg, &passin, &passout)) { + BIO_printf(bio_err, "Error getting passwords\n"); + goto end; + } + + if (srpvfile == NULL) { + if (configfile == NULL) + configfile = default_config_file; + + if (verbose) + BIO_printf(bio_err, "Using configuration from %s\n", + configfile); + conf = app_load_config(configfile); + if (conf == NULL) + goto end; + if (configfile != default_config_file && !app_load_modules(conf)) + goto end; + + /* Lets get the config section we are using */ + if (section == NULL) { + if (verbose) + BIO_printf(bio_err, + "trying to read " ENV_DEFAULT_SRP + " in " BASE_SECTION "\n"); + + section = lookup_conf(conf, BASE_SECTION, ENV_DEFAULT_SRP); + if (section == NULL) + goto end; + } + + app_RAND_load_conf(conf, BASE_SECTION); + + if (verbose) + BIO_printf(bio_err, + "trying to read " ENV_DATABASE " in section \"%s\"\n", + section); + + srpvfile = lookup_conf(conf, section, ENV_DATABASE); + if (srpvfile == NULL) + goto end; + } + + if (verbose) + BIO_printf(bio_err, "Trying to read SRP verifier file \"%s\"\n", + srpvfile); + + db = load_index(srpvfile, NULL); + if (db == NULL) + goto end; + + /* Lets check some fields */ + for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { + pp = sk_OPENSSL_PSTRING_value(db->db->data, i); + + if (pp[DB_srptype][0] == DB_SRP_INDEX) { + maxgN = i; + if ((gNindex < 0) && (gN != NULL) && strcmp(gN, pp[DB_srpid]) == 0) + gNindex = i; + + print_index(db, i, verbose > 1); + } + } + + if (verbose) + BIO_printf(bio_err, "Database initialised\n"); + + if (gNindex >= 0) { + gNrow = sk_OPENSSL_PSTRING_value(db->db->data, gNindex); + print_entry(db, gNindex, verbose > 1, "Default g and N"); + } else if (maxgN > 0 && !SRP_get_default_gN(gN)) { + BIO_printf(bio_err, "No g and N value for index \"%s\"\n", gN); + goto end; + } else { + if (verbose) + BIO_printf(bio_err, "Database has no g N information.\n"); + gNrow = NULL; + } + + if (verbose > 1) + BIO_printf(bio_err, "Starting user processing\n"); + + while (mode == OPT_LIST || user != NULL) { + int userindex = -1; + + if (user != NULL && verbose > 1) + BIO_printf(bio_err, "Processing user \"%s\"\n", user); + if ((userindex = get_index(db, user, 'U')) >= 0) + print_user(db, userindex, (verbose > 0) || mode == OPT_LIST); + + if (mode == OPT_LIST) { + if (user == NULL) { + BIO_printf(bio_err, "List all users\n"); + + for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) + print_user(db, i, 1); + } else if (userindex < 0) { + BIO_printf(bio_err, + "user \"%s\" does not exist, ignored. t\n", user); + errors++; + } + } else if (mode == OPT_ADD) { + if (userindex >= 0) { + /* reactivation of a new user */ + char **row = + sk_OPENSSL_PSTRING_value(db->db->data, userindex); + BIO_printf(bio_err, "user \"%s\" reactivated.\n", user); + row[DB_srptype][0] = 'V'; + + doupdatedb = 1; + } else { + char *row[DB_NUMBER]; + char *gNid; + row[DB_srpverifier] = NULL; + row[DB_srpsalt] = NULL; + row[DB_srpinfo] = NULL; + if (! + (gNid = + srp_create_user(user, &(row[DB_srpverifier]), + &(row[DB_srpsalt]), + gNrow ? gNrow[DB_srpsalt] : gN, + gNrow ? gNrow[DB_srpverifier] : NULL, + passout, verbose))) { + BIO_printf(bio_err, + "Cannot create srp verifier for user \"%s\", operation abandoned .\n", + user); + errors++; + goto end; + } + row[DB_srpid] = OPENSSL_strdup(user); + row[DB_srptype] = OPENSSL_strdup("v"); + row[DB_srpgN] = OPENSSL_strdup(gNid); + + if ((row[DB_srpid] == NULL) + || (row[DB_srpgN] == NULL) + || (row[DB_srptype] == NULL) + || (row[DB_srpverifier] == NULL) + || (row[DB_srpsalt] == NULL) + || (userinfo + && ((row[DB_srpinfo] = OPENSSL_strdup(userinfo)) == NULL)) + || !update_index(db, row)) { + OPENSSL_free(row[DB_srpid]); + OPENSSL_free(row[DB_srpgN]); + OPENSSL_free(row[DB_srpinfo]); + OPENSSL_free(row[DB_srptype]); + OPENSSL_free(row[DB_srpverifier]); + OPENSSL_free(row[DB_srpsalt]); + goto end; + } + doupdatedb = 1; + } + } else if (mode == OPT_MODIFY) { + if (userindex < 0) { + BIO_printf(bio_err, + "user \"%s\" does not exist, operation ignored.\n", + user); + errors++; + } else { + + char **row = + sk_OPENSSL_PSTRING_value(db->db->data, userindex); + char type = row[DB_srptype][0]; + if (type == 'v') { + BIO_printf(bio_err, + "user \"%s\" already updated, operation ignored.\n", + user); + errors++; + } else { + char *gNid; + + if (row[DB_srptype][0] == 'V') { + int user_gN; + char **irow = NULL; + if (verbose) + BIO_printf(bio_err, + "Verifying password for user \"%s\"\n", + user); + if ((user_gN = + get_index(db, row[DB_srpgN], DB_SRP_INDEX)) >= 0) + irow = + sk_OPENSSL_PSTRING_value(db->db->data, + userindex); + + if (!srp_verify_user + (user, row[DB_srpverifier], row[DB_srpsalt], + irow ? irow[DB_srpsalt] : row[DB_srpgN], + irow ? irow[DB_srpverifier] : NULL, passin, + verbose)) { + BIO_printf(bio_err, + "Invalid password for user \"%s\", operation abandoned.\n", + user); + errors++; + goto end; + } + } + if (verbose) + BIO_printf(bio_err, "Password for user \"%s\" ok.\n", + user); + + if (! + (gNid = + srp_create_user(user, &(row[DB_srpverifier]), + &(row[DB_srpsalt]), + gNrow ? gNrow[DB_srpsalt] : NULL, + gNrow ? gNrow[DB_srpverifier] : NULL, + passout, verbose))) { + BIO_printf(bio_err, + "Cannot create srp verifier for user \"%s\", operation abandoned.\n", + user); + errors++; + goto end; + } + + row[DB_srptype][0] = 'v'; + row[DB_srpgN] = OPENSSL_strdup(gNid); + + if (row[DB_srpid] == NULL + || row[DB_srpgN] == NULL + || row[DB_srptype] == NULL + || row[DB_srpverifier] == NULL + || row[DB_srpsalt] == NULL + || (userinfo + && ((row[DB_srpinfo] = OPENSSL_strdup(userinfo)) + == NULL))) + goto end; + + doupdatedb = 1; + } + } + } else if (mode == OPT_DELETE) { + if (userindex < 0) { + BIO_printf(bio_err, + "user \"%s\" does not exist, operation ignored. t\n", + user); + errors++; + } else { + char **xpp = sk_OPENSSL_PSTRING_value(db->db->data, userindex); + + BIO_printf(bio_err, "user \"%s\" revoked. t\n", user); + xpp[DB_srptype][0] = 'R'; + doupdatedb = 1; + } + } + user = *argv++; + if (user == NULL) { + /* no more processing in any mode if no users left */ + break; + } + } + + if (verbose) + BIO_printf(bio_err, "User procession done.\n"); + + if (doupdatedb) { + /* Lets check some fields */ + for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { + pp = sk_OPENSSL_PSTRING_value(db->db->data, i); + + if (pp[DB_srptype][0] == 'v') { + pp[DB_srptype][0] = 'V'; + print_user(db, i, verbose); + } + } + + if (verbose) + BIO_printf(bio_err, "Trying to update srpvfile.\n"); + if (!save_index(srpvfile, "new", db)) + goto end; + + if (verbose) + BIO_printf(bio_err, "Temporary srpvfile created.\n"); + if (!rotate_index(srpvfile, "new", "old")) + goto end; + + if (verbose) + BIO_printf(bio_err, "srpvfile updated.\n"); + } + + ret = (errors != 0); + end: + if (errors != 0) + if (verbose) + BIO_printf(bio_err, "User errors %d.\n", errors); + + if (verbose) + BIO_printf(bio_err, "SRP terminating with code %d.\n", ret); + + OPENSSL_free(passin); + OPENSSL_free(passout); + if (ret) + ERR_print_errors(bio_err); + NCONF_free(conf); + free_index(db); + release_engine(e); + return ret; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/storeutl.c b/trunk/3rdparty/openssl-1.1-fit/apps/storeutl.c new file mode 100644 index 000000000..50007f6e8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/storeutl.c @@ -0,0 +1,473 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include /* s2i_ASN1_INTEGER */ + +static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata, + int expected, int criterion, OSSL_STORE_SEARCH *search, + int text, int noout, int recursive, int indent, BIO *out, + const char *prog); + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ENGINE, OPT_OUT, OPT_PASSIN, + OPT_NOOUT, OPT_TEXT, OPT_RECURSIVE, + OPT_SEARCHFOR_CERTS, OPT_SEARCHFOR_KEYS, OPT_SEARCHFOR_CRLS, + OPT_CRITERION_SUBJECT, OPT_CRITERION_ISSUER, OPT_CRITERION_SERIAL, + OPT_CRITERION_FINGERPRINT, OPT_CRITERION_ALIAS, + OPT_MD +} OPTION_CHOICE; + +const OPTIONS storeutl_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] uri\nValid options are:\n"}, + {"help", OPT_HELP, '-', "Display this summary"}, + {"out", OPT_OUT, '>', "Output file - default stdout"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"text", OPT_TEXT, '-', "Print a text form of the objects"}, + {"noout", OPT_NOOUT, '-', "No PEM output, just status"}, + {"certs", OPT_SEARCHFOR_CERTS, '-', "Search for certificates only"}, + {"keys", OPT_SEARCHFOR_KEYS, '-', "Search for keys only"}, + {"crls", OPT_SEARCHFOR_CRLS, '-', "Search for CRLs only"}, + {"subject", OPT_CRITERION_SUBJECT, 's', "Search by subject"}, + {"issuer", OPT_CRITERION_ISSUER, 's', "Search by issuer and serial, issuer name"}, + {"serial", OPT_CRITERION_SERIAL, 's', "Search by issuer and serial, serial number"}, + {"fingerprint", OPT_CRITERION_FINGERPRINT, 's', "Search by public key fingerprint, given in hex"}, + {"alias", OPT_CRITERION_ALIAS, 's', "Search by alias"}, + {"", OPT_MD, '-', "Any supported digest"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + {"r", OPT_RECURSIVE, '-', "Recurse through names"}, + {NULL} +}; + +int storeutl_main(int argc, char *argv[]) +{ + int ret = 1, noout = 0, text = 0, recursive = 0; + char *outfile = NULL, *passin = NULL, *passinarg = NULL; + BIO *out = NULL; + ENGINE *e = NULL; + OPTION_CHOICE o; + char *prog = opt_init(argc, argv, storeutl_options); + PW_CB_DATA pw_cb_data; + int expected = 0; + int criterion = 0; + X509_NAME *subject = NULL, *issuer = NULL; + ASN1_INTEGER *serial = NULL; + unsigned char *fingerprint = NULL; + size_t fingerprintlen = 0; + char *alias = NULL; + OSSL_STORE_SEARCH *search = NULL; + const EVP_MD *digest = NULL; + + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(storeutl_options); + ret = 0; + goto end; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_NOOUT: + noout = 1; + break; + case OPT_TEXT: + text = 1; + break; + case OPT_RECURSIVE: + recursive = 1; + break; + case OPT_SEARCHFOR_CERTS: + case OPT_SEARCHFOR_KEYS: + case OPT_SEARCHFOR_CRLS: + if (expected != 0) { + BIO_printf(bio_err, "%s: only one search type can be given.\n", + prog); + goto end; + } + { + static const struct { + enum OPTION_choice choice; + int type; + } map[] = { + {OPT_SEARCHFOR_CERTS, OSSL_STORE_INFO_CERT}, + {OPT_SEARCHFOR_KEYS, OSSL_STORE_INFO_PKEY}, + {OPT_SEARCHFOR_CRLS, OSSL_STORE_INFO_CRL}, + }; + size_t i; + + for (i = 0; i < OSSL_NELEM(map); i++) { + if (o == map[i].choice) { + expected = map[i].type; + break; + } + } + /* + * If expected wasn't set at this point, it means the map + * isn't syncronised with the possible options leading here. + */ + OPENSSL_assert(expected != 0); + } + break; + case OPT_CRITERION_SUBJECT: + if (criterion != 0) { + BIO_printf(bio_err, "%s: criterion already given.\n", + prog); + goto end; + } + criterion = OSSL_STORE_SEARCH_BY_NAME; + if (subject != NULL) { + BIO_printf(bio_err, "%s: subject already given.\n", + prog); + goto end; + } + if ((subject = parse_name(opt_arg(), MBSTRING_UTF8, 1)) == NULL) { + BIO_printf(bio_err, "%s: can't parse subject argument.\n", + prog); + goto end; + } + break; + case OPT_CRITERION_ISSUER: + if (criterion != 0 + || (criterion == OSSL_STORE_SEARCH_BY_ISSUER_SERIAL + && issuer != NULL)) { + BIO_printf(bio_err, "%s: criterion already given.\n", + prog); + goto end; + } + criterion = OSSL_STORE_SEARCH_BY_ISSUER_SERIAL; + if (issuer != NULL) { + BIO_printf(bio_err, "%s: issuer already given.\n", + prog); + goto end; + } + if ((issuer = parse_name(opt_arg(), MBSTRING_UTF8, 1)) == NULL) { + BIO_printf(bio_err, "%s: can't parse issuer argument.\n", + prog); + goto end; + } + break; + case OPT_CRITERION_SERIAL: + if (criterion != 0 + || (criterion == OSSL_STORE_SEARCH_BY_ISSUER_SERIAL + && serial != NULL)) { + BIO_printf(bio_err, "%s: criterion already given.\n", + prog); + goto end; + } + criterion = OSSL_STORE_SEARCH_BY_ISSUER_SERIAL; + if (serial != NULL) { + BIO_printf(bio_err, "%s: serial number already given.\n", + prog); + goto end; + } + if ((serial = s2i_ASN1_INTEGER(NULL, opt_arg())) == NULL) { + BIO_printf(bio_err, "%s: can't parse serial number argument.\n", + prog); + goto end; + } + break; + case OPT_CRITERION_FINGERPRINT: + if (criterion != 0 + || (criterion == OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT + && fingerprint != NULL)) { + BIO_printf(bio_err, "%s: criterion already given.\n", + prog); + goto end; + } + criterion = OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT; + if (fingerprint != NULL) { + BIO_printf(bio_err, "%s: fingerprint already given.\n", + prog); + goto end; + } + { + long tmplen = 0; + + if ((fingerprint = OPENSSL_hexstr2buf(opt_arg(), &tmplen)) + == NULL) { + BIO_printf(bio_err, + "%s: can't parse fingerprint argument.\n", + prog); + goto end; + } + fingerprintlen = (size_t)tmplen; + } + break; + case OPT_CRITERION_ALIAS: + if (criterion != 0) { + BIO_printf(bio_err, "%s: criterion already given.\n", + prog); + goto end; + } + criterion = OSSL_STORE_SEARCH_BY_ALIAS; + if (alias != NULL) { + BIO_printf(bio_err, "%s: alias already given.\n", + prog); + goto end; + } + if ((alias = OPENSSL_strdup(opt_arg())) == NULL) { + BIO_printf(bio_err, "%s: can't parse alias argument.\n", + prog); + goto end; + } + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_MD: + if (!opt_md(opt_unknown(), &digest)) + goto opthelp; + } + } + argc = opt_num_rest(); + argv = opt_rest(); + + if (argc == 0) { + BIO_printf(bio_err, "%s: No URI given, nothing to do...\n", prog); + goto opthelp; + } + if (argc > 1) { + BIO_printf(bio_err, "%s: Unknown extra parameters after URI\n", prog); + goto opthelp; + } + + if (criterion != 0) { + switch (criterion) { + case OSSL_STORE_SEARCH_BY_NAME: + if ((search = OSSL_STORE_SEARCH_by_name(subject)) == NULL) { + ERR_print_errors(bio_err); + goto end; + } + break; + case OSSL_STORE_SEARCH_BY_ISSUER_SERIAL: + if (issuer == NULL || serial == NULL) { + BIO_printf(bio_err, + "%s: both -issuer and -serial must be given.\n", + prog); + goto end; + } + if ((search = OSSL_STORE_SEARCH_by_issuer_serial(issuer, serial)) + == NULL) { + ERR_print_errors(bio_err); + goto end; + } + break; + case OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT: + if ((search = OSSL_STORE_SEARCH_by_key_fingerprint(digest, + fingerprint, + fingerprintlen)) + == NULL) { + ERR_print_errors(bio_err); + goto end; + } + break; + case OSSL_STORE_SEARCH_BY_ALIAS: + if ((search = OSSL_STORE_SEARCH_by_alias(alias)) == NULL) { + ERR_print_errors(bio_err); + goto end; + } + break; + } + } + + if (!app_passwd(passinarg, NULL, &passin, NULL)) { + BIO_printf(bio_err, "Error getting passwords\n"); + goto end; + } + pw_cb_data.password = passin; + pw_cb_data.prompt_info = argv[0]; + + out = bio_open_default(outfile, 'w', FORMAT_TEXT); + if (out == NULL) + goto end; + + ret = process(argv[0], get_ui_method(), &pw_cb_data, + expected, criterion, search, + text, noout, recursive, 0, out, prog); + + end: + OPENSSL_free(fingerprint); + OPENSSL_free(alias); + ASN1_INTEGER_free(serial); + X509_NAME_free(subject); + X509_NAME_free(issuer); + OSSL_STORE_SEARCH_free(search); + BIO_free_all(out); + OPENSSL_free(passin); + release_engine(e); + return ret; +} + +static int indent_printf(int indent, BIO *bio, const char *format, ...) +{ + va_list args; + int ret; + + va_start(args, format); + + ret = BIO_printf(bio, "%*s", indent, "") + BIO_vprintf(bio, format, args); + + va_end(args); + return ret; +} + +static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata, + int expected, int criterion, OSSL_STORE_SEARCH *search, + int text, int noout, int recursive, int indent, BIO *out, + const char *prog) +{ + OSSL_STORE_CTX *store_ctx = NULL; + int ret = 1, items = 0; + + if ((store_ctx = OSSL_STORE_open(uri, uimeth, uidata, NULL, NULL)) + == NULL) { + BIO_printf(bio_err, "Couldn't open file or uri %s\n", uri); + ERR_print_errors(bio_err); + return ret; + } + + if (expected != 0) { + if (!OSSL_STORE_expect(store_ctx, expected)) { + ERR_print_errors(bio_err); + goto end2; + } + } + + if (criterion != 0) { + if (!OSSL_STORE_supports_search(store_ctx, criterion)) { + BIO_printf(bio_err, + "%s: the store scheme doesn't support the given search criteria.\n", + prog); + goto end2; + } + + if (!OSSL_STORE_find(store_ctx, search)) { + ERR_print_errors(bio_err); + goto end2; + } + } + + /* From here on, we count errors, and we'll return the count at the end */ + ret = 0; + + for (;;) { + OSSL_STORE_INFO *info = OSSL_STORE_load(store_ctx); + int type = info == NULL ? 0 : OSSL_STORE_INFO_get_type(info); + const char *infostr = + info == NULL ? NULL : OSSL_STORE_INFO_type_string(type); + + if (info == NULL) { + if (OSSL_STORE_eof(store_ctx)) + break; + + if (OSSL_STORE_error(store_ctx)) { + if (recursive) + ERR_clear_error(); + else + ERR_print_errors(bio_err); + ret++; + continue; + } + + BIO_printf(bio_err, + "ERROR: OSSL_STORE_load() returned NULL without " + "eof or error indications\n"); + BIO_printf(bio_err, " This is an error in the loader\n"); + ERR_print_errors(bio_err); + ret++; + break; + } + + if (type == OSSL_STORE_INFO_NAME) { + const char *name = OSSL_STORE_INFO_get0_NAME(info); + const char *desc = OSSL_STORE_INFO_get0_NAME_description(info); + indent_printf(indent, bio_out, "%d: %s: %s\n", items, infostr, + name); + if (desc != NULL) + indent_printf(indent, bio_out, "%s\n", desc); + } else { + indent_printf(indent, bio_out, "%d: %s\n", items, infostr); + } + + /* + * Unfortunately, PEM_X509_INFO_write_bio() is sorely lacking in + * functionality, so we must figure out how exactly to write things + * ourselves... + */ + switch (type) { + case OSSL_STORE_INFO_NAME: + if (recursive) { + const char *suburi = OSSL_STORE_INFO_get0_NAME(info); + ret += process(suburi, uimeth, uidata, + expected, criterion, search, + text, noout, recursive, indent + 2, out, prog); + } + break; + case OSSL_STORE_INFO_PARAMS: + if (text) + EVP_PKEY_print_params(out, OSSL_STORE_INFO_get0_PARAMS(info), + 0, NULL); + if (!noout) + PEM_write_bio_Parameters(out, + OSSL_STORE_INFO_get0_PARAMS(info)); + break; + case OSSL_STORE_INFO_PKEY: + if (text) + EVP_PKEY_print_private(out, OSSL_STORE_INFO_get0_PKEY(info), + 0, NULL); + if (!noout) + PEM_write_bio_PrivateKey(out, OSSL_STORE_INFO_get0_PKEY(info), + NULL, NULL, 0, NULL, NULL); + break; + case OSSL_STORE_INFO_CERT: + if (text) + X509_print(out, OSSL_STORE_INFO_get0_CERT(info)); + if (!noout) + PEM_write_bio_X509(out, OSSL_STORE_INFO_get0_CERT(info)); + break; + case OSSL_STORE_INFO_CRL: + if (text) + X509_CRL_print(out, OSSL_STORE_INFO_get0_CRL(info)); + if (!noout) + PEM_write_bio_X509_CRL(out, OSSL_STORE_INFO_get0_CRL(info)); + break; + default: + BIO_printf(bio_err, "!!! Unknown code\n"); + ret++; + break; + } + items++; + OSSL_STORE_INFO_free(info); + } + indent_printf(indent, out, "Total found: %d\n", items); + + end2: + if (!OSSL_STORE_close(store_ctx)) { + ERR_print_errors(bio_err); + ret++; + } + + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/testCA.pem b/trunk/3rdparty/openssl-1.1-fit/apps/testCA.pem new file mode 100644 index 000000000..dcb710aa9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/testCA.pem @@ -0,0 +1,8 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBBzCBsgIBADBNMQswCQYDVQQGEwJBVTETMBEGA1UECBMKUXVlZW5zbGFuZDEX +MBUGA1UEChMOTWluY29tIFB0eSBMdGQxEDAOBgNVBAMTB1RFU1QgQ0EwXDANBgkq +hkiG9w0BAQEFAANLADBIAkEAzW9brgA8efT2ODB+NrsflJZj3KKqKsm4OrXTRqfL +VETj1ws/zCXl42XJAxdWQMCP0liKfc9Ut4xi1qCVI7N07wIDAQABoAAwDQYJKoZI +hvcNAQEEBQADQQBjZZ42Det9Uw0AFwJy4ufUEy5Cv74pxBp5SZnljgHY+Az0Hs2S +uNkIegr2ITX5azKi9nOkg9ZmsmGG13FIjiC/ +-----END CERTIFICATE REQUEST----- diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/testdsa.h b/trunk/3rdparty/openssl-1.1-fit/apps/testdsa.h new file mode 100644 index 000000000..3c4b459db --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/testdsa.h @@ -0,0 +1,260 @@ +/* + * Copyright 1998-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* used by speed.c */ +DSA *get_dsa(int); + +static unsigned char dsa512_priv[] = { + 0x65, 0xe5, 0xc7, 0x38, 0x60, 0x24, 0xb5, 0x89, 0xd4, 0x9c, 0xeb, 0x4c, + 0x9c, 0x1d, 0x7a, 0x22, 0xbd, 0xd1, 0xc2, 0xd2, +}; + +static unsigned char dsa512_pub[] = { + 0x00, 0x95, 0xa7, 0x0d, 0xec, 0x93, 0x68, 0xba, 0x5f, 0xf7, 0x5f, 0x07, + 0xf2, 0x3b, 0xad, 0x6b, 0x01, 0xdc, 0xbe, 0xec, 0xde, 0x04, 0x7a, 0x3a, + 0x27, 0xb3, 0xec, 0x49, 0xfd, 0x08, 0x43, 0x3d, 0x7e, 0xa8, 0x2c, 0x5e, + 0x7b, 0xbb, 0xfc, 0xf4, 0x6e, 0xeb, 0x6c, 0xb0, 0x6e, 0xf8, 0x02, 0x12, + 0x8c, 0x38, 0x5d, 0x83, 0x56, 0x7d, 0xee, 0x53, 0x05, 0x3e, 0x24, 0x84, + 0xbe, 0xba, 0x0a, 0x6b, 0xc8, +}; + +static unsigned char dsa512_p[] = { + 0x9D, 0x1B, 0x69, 0x8E, 0x26, 0xDB, 0xF2, 0x2B, 0x11, 0x70, 0x19, 0x86, + 0xF6, 0x19, 0xC8, 0xF8, 0x19, 0xF2, 0x18, 0x53, 0x94, 0x46, 0x06, 0xD0, + 0x62, 0x50, 0x33, 0x4B, 0x02, 0x3C, 0x52, 0x30, 0x03, 0x8B, 0x3B, 0xF9, + 0x5F, 0xD1, 0x24, 0x06, 0x4F, 0x7B, 0x4C, 0xBA, 0xAA, 0x40, 0x9B, 0xFD, + 0x96, 0xE4, 0x37, 0x33, 0xBB, 0x2D, 0x5A, 0xD7, 0x5A, 0x11, 0x40, 0x66, + 0xA2, 0x76, 0x7D, 0x31, +}; + +static unsigned char dsa512_q[] = { + 0xFB, 0x53, 0xEF, 0x50, 0xB4, 0x40, 0x92, 0x31, 0x56, 0x86, 0x53, 0x7A, + 0xE8, 0x8B, 0x22, 0x9A, 0x49, 0xFB, 0x71, 0x8F, +}; + +static unsigned char dsa512_g[] = { + 0x83, 0x3E, 0x88, 0xE5, 0xC5, 0x89, 0x73, 0xCE, 0x3B, 0x6C, 0x01, 0x49, + 0xBF, 0xB3, 0xC7, 0x9F, 0x0A, 0xEA, 0x44, 0x91, 0xE5, 0x30, 0xAA, 0xD9, + 0xBE, 0x5B, 0x5F, 0xB7, 0x10, 0xD7, 0x89, 0xB7, 0x8E, 0x74, 0xFB, 0xCF, + 0x29, 0x1E, 0xEB, 0xA8, 0x2C, 0x54, 0x51, 0xB8, 0x10, 0xDE, 0xA0, 0xCE, + 0x2F, 0xCC, 0x24, 0x6B, 0x90, 0x77, 0xDE, 0xA2, 0x68, 0xA6, 0x52, 0x12, + 0xA2, 0x03, 0x9D, 0x20, +}; + +static unsigned char dsa1024_priv[] = { + 0x7d, 0x21, 0xda, 0xbb, 0x62, 0x15, 0x47, 0x36, 0x07, 0x67, 0x12, 0xe8, + 0x8c, 0xaa, 0x1c, 0xcd, 0x38, 0x12, 0x61, 0x18, +}; + +static unsigned char dsa1024_pub[] = { + 0x3c, 0x4e, 0x9c, 0x2a, 0x7f, 0x16, 0xc1, 0x25, 0xeb, 0xac, 0x78, 0x63, + 0x90, 0x14, 0x8c, 0x8b, 0xf4, 0x68, 0x43, 0x3c, 0x2d, 0xee, 0x65, 0x50, + 0x7d, 0x9c, 0x8f, 0x8c, 0x8a, 0x51, 0xd6, 0x11, 0x2b, 0x99, 0xaf, 0x1e, + 0x90, 0x97, 0xb5, 0xd3, 0xa6, 0x20, 0x25, 0xd6, 0xfe, 0x43, 0x02, 0xd5, + 0x91, 0x7d, 0xa7, 0x8c, 0xdb, 0xc9, 0x85, 0xa3, 0x36, 0x48, 0xf7, 0x68, + 0xaa, 0x60, 0xb1, 0xf7, 0x05, 0x68, 0x3a, 0xa3, 0x3f, 0xd3, 0x19, 0x82, + 0xd8, 0x82, 0x7a, 0x77, 0xfb, 0xef, 0xf4, 0x15, 0x0a, 0xeb, 0x06, 0x04, + 0x7f, 0x53, 0x07, 0x0c, 0xbc, 0xcb, 0x2d, 0x83, 0xdb, 0x3e, 0xd1, 0x28, + 0xa5, 0xa1, 0x31, 0xe0, 0x67, 0xfa, 0x50, 0xde, 0x9b, 0x07, 0x83, 0x7e, + 0x2c, 0x0b, 0xc3, 0x13, 0x50, 0x61, 0xe5, 0xad, 0xbd, 0x36, 0xb8, 0x97, + 0x4e, 0x40, 0x7d, 0xe8, 0x83, 0x0d, 0xbc, 0x4b +}; + +static unsigned char dsa1024_p[] = { + 0xA7, 0x3F, 0x6E, 0x85, 0xBF, 0x41, 0x6A, 0x29, 0x7D, 0xF0, 0x9F, 0x47, + 0x19, 0x30, 0x90, 0x9A, 0x09, 0x1D, 0xDA, 0x6A, 0x33, 0x1E, 0xC5, 0x3D, + 0x86, 0x96, 0xB3, 0x15, 0xE0, 0x53, 0x2E, 0x8F, 0xE0, 0x59, 0x82, 0x73, + 0x90, 0x3E, 0x75, 0x31, 0x99, 0x47, 0x7A, 0x52, 0xFB, 0x85, 0xE4, 0xD9, + 0xA6, 0x7B, 0x38, 0x9B, 0x68, 0x8A, 0x84, 0x9B, 0x87, 0xC6, 0x1E, 0xB5, + 0x7E, 0x86, 0x4B, 0x53, 0x5B, 0x59, 0xCF, 0x71, 0x65, 0x19, 0x88, 0x6E, + 0xCE, 0x66, 0xAE, 0x6B, 0x88, 0x36, 0xFB, 0xEC, 0x28, 0xDC, 0xC2, 0xD7, + 0xA5, 0xBB, 0xE5, 0x2C, 0x39, 0x26, 0x4B, 0xDA, 0x9A, 0x70, 0x18, 0x95, + 0x37, 0x95, 0x10, 0x56, 0x23, 0xF6, 0x15, 0xED, 0xBA, 0x04, 0x5E, 0xDE, + 0x39, 0x4F, 0xFD, 0xB7, 0x43, 0x1F, 0xB5, 0xA4, 0x65, 0x6F, 0xCD, 0x80, + 0x11, 0xE4, 0x70, 0x95, 0x5B, 0x50, 0xCD, 0x49, +}; + +static unsigned char dsa1024_q[] = { + 0xF7, 0x07, 0x31, 0xED, 0xFA, 0x6C, 0x06, 0x03, 0xD5, 0x85, 0x8A, 0x1C, + 0xAC, 0x9C, 0x65, 0xE7, 0x50, 0x66, 0x65, 0x6F, +}; + +static unsigned char dsa1024_g[] = { + 0x4D, 0xDF, 0x4C, 0x03, 0xA6, 0x91, 0x8A, 0xF5, 0x19, 0x6F, 0x50, 0x46, + 0x25, 0x99, 0xE5, 0x68, 0x6F, 0x30, 0xE3, 0x69, 0xE1, 0xE5, 0xB3, 0x5D, + 0x98, 0xBB, 0x28, 0x86, 0x48, 0xFC, 0xDE, 0x99, 0x04, 0x3F, 0x5F, 0x88, + 0x0C, 0x9C, 0x73, 0x24, 0x0D, 0x20, 0x5D, 0xB9, 0x2A, 0x9A, 0x3F, 0x18, + 0x96, 0x27, 0xE4, 0x62, 0x87, 0xC1, 0x7B, 0x74, 0x62, 0x53, 0xFC, 0x61, + 0x27, 0xA8, 0x7A, 0x91, 0x09, 0x9D, 0xB6, 0xF1, 0x4D, 0x9C, 0x54, 0x0F, + 0x58, 0x06, 0xEE, 0x49, 0x74, 0x07, 0xCE, 0x55, 0x7E, 0x23, 0xCE, 0x16, + 0xF6, 0xCA, 0xDC, 0x5A, 0x61, 0x01, 0x7E, 0xC9, 0x71, 0xB5, 0x4D, 0xF6, + 0xDC, 0x34, 0x29, 0x87, 0x68, 0xF6, 0x5E, 0x20, 0x93, 0xB3, 0xDB, 0xF5, + 0xE4, 0x09, 0x6C, 0x41, 0x17, 0x95, 0x92, 0xEB, 0x01, 0xB5, 0x73, 0xA5, + 0x6A, 0x7E, 0xD8, 0x32, 0xED, 0x0E, 0x02, 0xB8, +}; + +static unsigned char dsa2048_priv[] = { + 0x32, 0x67, 0x92, 0xf6, 0xc4, 0xe2, 0xe2, 0xe8, 0xa0, 0x8b, 0x6b, 0x45, + 0x0c, 0x8a, 0x76, 0xb0, 0xee, 0xcf, 0x91, 0xa7, +}; + +static unsigned char dsa2048_pub[] = { + 0x17, 0x8f, 0xa8, 0x11, 0x84, 0x92, 0xec, 0x83, 0x47, 0xc7, 0x6a, 0xb0, + 0x92, 0xaf, 0x5a, 0x20, 0x37, 0xa3, 0x64, 0x79, 0xd2, 0xd0, 0x3d, 0xcd, + 0xe0, 0x61, 0x88, 0x88, 0x21, 0xcc, 0x74, 0x5d, 0xce, 0x4c, 0x51, 0x47, + 0xf0, 0xc5, 0x5c, 0x4c, 0x82, 0x7a, 0xaf, 0x72, 0xad, 0xb9, 0xe0, 0x53, + 0xf2, 0x78, 0xb7, 0xf0, 0xb5, 0x48, 0x7f, 0x8a, 0x3a, 0x18, 0xd1, 0x9f, + 0x8b, 0x7d, 0xa5, 0x47, 0xb7, 0x95, 0xab, 0x98, 0xf8, 0x7b, 0x74, 0x50, + 0x56, 0x8e, 0x57, 0xf0, 0xee, 0xf5, 0xb7, 0xba, 0xab, 0x85, 0x86, 0xf9, + 0x2b, 0xef, 0x41, 0x56, 0xa0, 0xa4, 0x9f, 0xb7, 0x38, 0x00, 0x46, 0x0a, + 0xa6, 0xf1, 0xfc, 0x1f, 0xd8, 0x4e, 0x85, 0x44, 0x92, 0x43, 0x21, 0x5d, + 0x6e, 0xcc, 0xc2, 0xcb, 0x26, 0x31, 0x0d, 0x21, 0xc4, 0xbd, 0x8d, 0x24, + 0xbc, 0xd9, 0x18, 0x19, 0xd7, 0xdc, 0xf1, 0xe7, 0x93, 0x50, 0x48, 0x03, + 0x2c, 0xae, 0x2e, 0xe7, 0x49, 0x88, 0x5f, 0x93, 0x57, 0x27, 0x99, 0x36, + 0xb4, 0x20, 0xab, 0xfc, 0xa7, 0x2b, 0xf2, 0xd9, 0x98, 0xd7, 0xd4, 0x34, + 0x9d, 0x96, 0x50, 0x58, 0x9a, 0xea, 0x54, 0xf3, 0xee, 0xf5, 0x63, 0x14, + 0xee, 0x85, 0x83, 0x74, 0x76, 0xe1, 0x52, 0x95, 0xc3, 0xf7, 0xeb, 0x04, + 0x04, 0x7b, 0xa7, 0x28, 0x1b, 0xcc, 0xea, 0x4a, 0x4e, 0x84, 0xda, 0xd8, + 0x9c, 0x79, 0xd8, 0x9b, 0x66, 0x89, 0x2f, 0xcf, 0xac, 0xd7, 0x79, 0xf9, + 0xa9, 0xd8, 0x45, 0x13, 0x78, 0xb9, 0x00, 0x14, 0xc9, 0x7e, 0x22, 0x51, + 0x86, 0x67, 0xb0, 0x9f, 0x26, 0x11, 0x23, 0xc8, 0x38, 0xd7, 0x70, 0x1d, + 0x15, 0x8e, 0x4d, 0x4f, 0x95, 0x97, 0x40, 0xa1, 0xc2, 0x7e, 0x01, 0x18, + 0x72, 0xf4, 0x10, 0xe6, 0x8d, 0x52, 0x16, 0x7f, 0xf2, 0xc9, 0xf8, 0x33, + 0x8b, 0x33, 0xb7, 0xce, +}; + +static unsigned char dsa2048_p[] = { + 0xA0, 0x25, 0xFA, 0xAD, 0xF4, 0x8E, 0xB9, 0xE5, 0x99, 0xF3, 0x5D, 0x6F, + 0x4F, 0x83, 0x34, 0xE2, 0x7E, 0xCF, 0x6F, 0xBF, 0x30, 0xAF, 0x6F, 0x81, + 0xEB, 0xF8, 0xC4, 0x13, 0xD9, 0xA0, 0x5D, 0x8B, 0x5C, 0x8E, 0xDC, 0xC2, + 0x1D, 0x0B, 0x41, 0x32, 0xB0, 0x1F, 0xFE, 0xEF, 0x0C, 0xC2, 0xA2, 0x7E, + 0x68, 0x5C, 0x28, 0x21, 0xE9, 0xF5, 0xB1, 0x58, 0x12, 0x63, 0x4C, 0x19, + 0x4E, 0xFF, 0x02, 0x4B, 0x92, 0xED, 0xD2, 0x07, 0x11, 0x4D, 0x8C, 0x58, + 0x16, 0x5C, 0x55, 0x8E, 0xAD, 0xA3, 0x67, 0x7D, 0xB9, 0x86, 0x6E, 0x0B, + 0xE6, 0x54, 0x6F, 0x40, 0xAE, 0x0E, 0x67, 0x4C, 0xF9, 0x12, 0x5B, 0x3C, + 0x08, 0x7A, 0xF7, 0xFC, 0x67, 0x86, 0x69, 0xE7, 0x0A, 0x94, 0x40, 0xBF, + 0x8B, 0x76, 0xFE, 0x26, 0xD1, 0xF2, 0xA1, 0x1A, 0x84, 0xA1, 0x43, 0x56, + 0x28, 0xBC, 0x9A, 0x5F, 0xD7, 0x3B, 0x69, 0x89, 0x8A, 0x36, 0x2C, 0x51, + 0xDF, 0x12, 0x77, 0x2F, 0x57, 0x7B, 0xA0, 0xAA, 0xDD, 0x7F, 0xA1, 0x62, + 0x3B, 0x40, 0x7B, 0x68, 0x1A, 0x8F, 0x0D, 0x38, 0xBB, 0x21, 0x5D, 0x18, + 0xFC, 0x0F, 0x46, 0xF7, 0xA3, 0xB0, 0x1D, 0x23, 0xC3, 0xD2, 0xC7, 0x72, + 0x51, 0x18, 0xDF, 0x46, 0x95, 0x79, 0xD9, 0xBD, 0xB5, 0x19, 0x02, 0x2C, + 0x87, 0xDC, 0xE7, 0x57, 0x82, 0x7E, 0xF1, 0x8B, 0x06, 0x3D, 0x00, 0xA5, + 0x7B, 0x6B, 0x26, 0x27, 0x91, 0x0F, 0x6A, 0x77, 0xE4, 0xD5, 0x04, 0xE4, + 0x12, 0x2C, 0x42, 0xFF, 0xD2, 0x88, 0xBB, 0xD3, 0x92, 0xA0, 0xF9, 0xC8, + 0x51, 0x64, 0x14, 0x5C, 0xD8, 0xF9, 0x6C, 0x47, 0x82, 0xB4, 0x1C, 0x7F, + 0x09, 0xB8, 0xF0, 0x25, 0x83, 0x1D, 0x3F, 0x3F, 0x05, 0xB3, 0x21, 0x0A, + 0x5D, 0xA7, 0xD8, 0x54, 0xC3, 0x65, 0x7D, 0xC3, 0xB0, 0x1D, 0xBF, 0xAE, + 0xF8, 0x68, 0xCF, 0x9B, +}; + +static unsigned char dsa2048_q[] = { + 0x97, 0xE7, 0x33, 0x4D, 0xD3, 0x94, 0x3E, 0x0B, 0xDB, 0x62, 0x74, 0xC6, + 0xA1, 0x08, 0xDD, 0x19, 0xA3, 0x75, 0x17, 0x1B, +}; + +static unsigned char dsa2048_g[] = { + 0x2C, 0x78, 0x16, 0x59, 0x34, 0x63, 0xF4, 0xF3, 0x92, 0xFC, 0xB5, 0xA5, + 0x4F, 0x13, 0xDE, 0x2F, 0x1C, 0xA4, 0x3C, 0xAE, 0xAD, 0x38, 0x3F, 0x7E, + 0x90, 0xBF, 0x96, 0xA6, 0xAE, 0x25, 0x90, 0x72, 0xF5, 0x8E, 0x80, 0x0C, + 0x39, 0x1C, 0xD9, 0xEC, 0xBA, 0x90, 0x5B, 0x3A, 0xE8, 0x58, 0x6C, 0x9E, + 0x30, 0x42, 0x37, 0x02, 0x31, 0x82, 0xBC, 0x6A, 0xDF, 0x6A, 0x09, 0x29, + 0xE3, 0xC0, 0x46, 0xD1, 0xCB, 0x85, 0xEC, 0x0C, 0x30, 0x5E, 0xEA, 0xC8, + 0x39, 0x8E, 0x22, 0x9F, 0x22, 0x10, 0xD2, 0x34, 0x61, 0x68, 0x37, 0x3D, + 0x2E, 0x4A, 0x5B, 0x9A, 0xF5, 0xC1, 0x48, 0xC6, 0xF6, 0xDC, 0x63, 0x1A, + 0xD3, 0x96, 0x64, 0xBA, 0x34, 0xC9, 0xD1, 0xA0, 0xD1, 0xAE, 0x6C, 0x2F, + 0x48, 0x17, 0x93, 0x14, 0x43, 0xED, 0xF0, 0x21, 0x30, 0x19, 0xC3, 0x1B, + 0x5F, 0xDE, 0xA3, 0xF0, 0x70, 0x78, 0x18, 0xE1, 0xA8, 0xE4, 0xEE, 0x2E, + 0x00, 0xA5, 0xE4, 0xB3, 0x17, 0xC8, 0x0C, 0x7D, 0x6E, 0x42, 0xDC, 0xB7, + 0x46, 0x00, 0x36, 0x4D, 0xD4, 0x46, 0xAA, 0x3D, 0x3C, 0x46, 0x89, 0x40, + 0xBF, 0x1D, 0x84, 0x77, 0x0A, 0x75, 0xF3, 0x87, 0x1D, 0x08, 0x4C, 0xA6, + 0xD1, 0xA9, 0x1C, 0x1E, 0x12, 0x1E, 0xE1, 0xC7, 0x30, 0x28, 0x76, 0xA5, + 0x7F, 0x6C, 0x85, 0x96, 0x2B, 0x6F, 0xDB, 0x80, 0x66, 0x26, 0xAE, 0xF5, + 0x93, 0xC7, 0x8E, 0xAE, 0x9A, 0xED, 0xE4, 0xCA, 0x04, 0xEA, 0x3B, 0x72, + 0xEF, 0xDC, 0x87, 0xED, 0x0D, 0xA5, 0x4C, 0x4A, 0xDD, 0x71, 0x22, 0x64, + 0x59, 0x69, 0x4E, 0x8E, 0xBF, 0x43, 0xDC, 0xAB, 0x8E, 0x66, 0xBB, 0x01, + 0xB6, 0xF4, 0xE7, 0xFD, 0xD2, 0xAD, 0x9F, 0x36, 0xC1, 0xA0, 0x29, 0x99, + 0xD1, 0x96, 0x70, 0x59, 0x06, 0x78, 0x35, 0xBD, 0x65, 0x55, 0x52, 0x9E, + 0xF8, 0xB2, 0xE5, 0x38, +}; + +typedef struct testdsa_st { + unsigned char *priv; + unsigned char *pub; + unsigned char *p; + unsigned char *g; + unsigned char *q; + int priv_l; + int pub_l; + int p_l; + int g_l; + int q_l; +} testdsa; + +#define set_dsa_ptr(st, bits) \ + do { \ + st.priv = dsa##bits##_priv; \ + st.pub = dsa##bits##_pub; \ + st.p = dsa##bits##_p; \ + st.g = dsa##bits##_g; \ + st.q = dsa##bits##_q; \ + st.priv_l = sizeof(dsa##bits##_priv); \ + st.pub_l = sizeof(dsa##bits##_pub); \ + st.p_l = sizeof(dsa##bits##_p); \ + st.g_l = sizeof(dsa##bits##_g); \ + st.q_l = sizeof(dsa##bits##_q); \ + } while (0) + +DSA *get_dsa(int dsa_bits) +{ + DSA *dsa; + BIGNUM *priv_key, *pub_key, *p, *q, *g; + testdsa dsa_t; + + switch (dsa_bits) { + case 512: + set_dsa_ptr(dsa_t, 512); + break; + case 1024: + set_dsa_ptr(dsa_t, 1024); + break; + case 2048: + set_dsa_ptr(dsa_t, 2048); + break; + default: + return NULL; + } + + if ((dsa = DSA_new()) == NULL) + return NULL; + priv_key = BN_bin2bn(dsa_t.priv, dsa_t.priv_l, NULL); + pub_key = BN_bin2bn(dsa_t.pub, dsa_t.pub_l, NULL); + p = BN_bin2bn(dsa_t.p, dsa_t.p_l, NULL); + q = BN_bin2bn(dsa_t.q, dsa_t.q_l, NULL); + g = BN_bin2bn(dsa_t.g, dsa_t.g_l, NULL); + if ((priv_key == NULL) || (pub_key == NULL) || (p == NULL) || (q == NULL) + || (g == NULL)) { + goto err; + } + if (!DSA_set0_pqg(dsa, p, q, g)) + goto err; + + if (!DSA_set0_key(dsa, pub_key, priv_key)) + goto err; + + return dsa; + err: + DSA_free(dsa); + BN_free(priv_key); + BN_free(pub_key); + BN_free(p); + BN_free(q); + BN_free(g); + return NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/testrsa.h b/trunk/3rdparty/openssl-1.1-fit/apps/testrsa.h new file mode 100644 index 000000000..1350ce54e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/testrsa.h @@ -0,0 +1,1960 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +static unsigned char test512[] = { + 0x30, 0x82, 0x01, 0x3a, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00, + 0xd6, 0x33, 0xb9, 0xc8, 0xfb, 0x4f, 0x3c, 0x7d, 0xc0, 0x01, + 0x86, 0xd0, 0xe7, 0xa0, 0x55, 0xf2, 0x95, 0x93, 0xcc, 0x4f, + 0xb7, 0x5b, 0x67, 0x5b, 0x94, 0x68, 0xc9, 0x34, 0x15, 0xde, + 0xa5, 0x2e, 0x1c, 0x33, 0xc2, 0x6e, 0xfc, 0x34, 0x5e, 0x71, + 0x13, 0xb7, 0xd6, 0xee, 0xd8, 0xa5, 0x65, 0x05, 0x72, 0x87, + 0xa8, 0xb0, 0x77, 0xfe, 0x57, 0xf5, 0xfc, 0x5f, 0x55, 0x83, + 0x87, 0xdd, 0x57, 0x49, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, + 0x41, 0x00, 0xa7, 0xf7, 0x91, 0xc5, 0x0f, 0x84, 0x57, 0xdc, + 0x07, 0xf7, 0x6a, 0x7f, 0x60, 0x52, 0xb3, 0x72, 0xf1, 0x66, + 0x1f, 0x7d, 0x97, 0x3b, 0x9e, 0xb6, 0x0a, 0x8f, 0x8c, 0xcf, + 0x42, 0x23, 0x00, 0x04, 0xd4, 0x28, 0x0e, 0x1c, 0x90, 0xc4, + 0x11, 0x25, 0x25, 0xa5, 0x93, 0xa5, 0x2f, 0x70, 0x02, 0xdf, + 0x81, 0x9c, 0x49, 0x03, 0xa0, 0xf8, 0x6d, 0x54, 0x2e, 0x26, + 0xde, 0xaa, 0x85, 0x59, 0xa8, 0x31, 0x02, 0x21, 0x00, 0xeb, + 0x47, 0xd7, 0x3b, 0xf6, 0xc3, 0xdd, 0x5a, 0x46, 0xc5, 0xb9, + 0x2b, 0x9a, 0xa0, 0x09, 0x8f, 0xa6, 0xfb, 0xf3, 0x78, 0x7a, + 0x33, 0x70, 0x9d, 0x0f, 0x42, 0x6b, 0x13, 0x68, 0x24, 0xd3, + 0x15, 0x02, 0x21, 0x00, 0xe9, 0x10, 0xb0, 0xb3, 0x0d, 0xe2, + 0x82, 0x68, 0x77, 0x8a, 0x6e, 0x7c, 0xda, 0xbc, 0x3e, 0x53, + 0x83, 0xfb, 0xd6, 0x22, 0xe7, 0xb5, 0xae, 0x6e, 0x80, 0xda, + 0x00, 0x55, 0x97, 0xc1, 0xd0, 0x65, 0x02, 0x20, 0x4c, 0xf8, + 0x73, 0xb1, 0x6a, 0x49, 0x29, 0x61, 0x1f, 0x46, 0x10, 0x0d, + 0xf3, 0xc7, 0xe7, 0x58, 0xd7, 0x88, 0x15, 0x5e, 0x94, 0x9b, + 0xbf, 0x7b, 0xa2, 0x42, 0x58, 0x45, 0x41, 0x0c, 0xcb, 0x01, + 0x02, 0x20, 0x12, 0x11, 0xba, 0x31, 0x57, 0x9d, 0x3d, 0x11, + 0x0e, 0x5b, 0x8c, 0x2f, 0x5f, 0xe2, 0x02, 0x4f, 0x05, 0x47, + 0x8c, 0x15, 0x8e, 0xb3, 0x56, 0x3f, 0xb8, 0xfb, 0xad, 0xd4, + 0xf4, 0xfc, 0x10, 0xc5, 0x02, 0x20, 0x18, 0xa1, 0x29, 0x99, + 0x5b, 0xd9, 0xc8, 0xd4, 0xfc, 0x49, 0x7a, 0x2a, 0x21, 0x2c, + 0x49, 0xe4, 0x4f, 0xeb, 0xef, 0x51, 0xf1, 0xab, 0x6d, 0xfb, + 0x4b, 0x14, 0xe9, 0x4b, 0x52, 0xb5, 0x82, 0x2c, +}; + +static unsigned char test1024[] = { + 0x30, 0x82, 0x02, 0x5c, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, + 0x00, 0xdc, 0x98, 0x43, 0xe8, 0x3d, 0x43, 0x5b, 0xe4, 0x05, + 0xcd, 0xd0, 0xa9, 0x3e, 0xcb, 0x83, 0x75, 0xf6, 0xb5, 0xa5, + 0x9f, 0x6b, 0xe9, 0x34, 0x41, 0x29, 0x18, 0xfa, 0x6a, 0x55, + 0x4d, 0x70, 0xfc, 0xec, 0xae, 0x87, 0x38, 0x0a, 0x20, 0xa9, + 0xc0, 0x45, 0x77, 0x6e, 0x57, 0x60, 0x57, 0xf4, 0xed, 0x96, + 0x22, 0xcb, 0x8f, 0xe1, 0x33, 0x3a, 0x17, 0x1f, 0xed, 0x37, + 0xa5, 0x6f, 0xeb, 0xa6, 0xbc, 0x12, 0x80, 0x1d, 0x53, 0xbd, + 0x70, 0xeb, 0x21, 0x76, 0x3e, 0xc9, 0x2f, 0x1a, 0x45, 0x24, + 0x82, 0xff, 0xcd, 0x59, 0x32, 0x06, 0x2e, 0x12, 0x3b, 0x23, + 0x78, 0xed, 0x12, 0x3d, 0xe0, 0x8d, 0xf9, 0x67, 0x4f, 0x37, + 0x4e, 0x47, 0x02, 0x4c, 0x2d, 0xc0, 0x4f, 0x1f, 0xb3, 0x94, + 0xe1, 0x41, 0x2e, 0x2d, 0x90, 0x10, 0xfc, 0x82, 0x91, 0x8b, + 0x0f, 0x22, 0xd4, 0xf2, 0xfc, 0x2c, 0xab, 0x53, 0x55, 0x02, + 0x03, 0x01, 0x00, 0x01, 0x02, 0x81, 0x80, 0x2b, 0xcc, 0x3f, + 0x8f, 0x58, 0xba, 0x8b, 0x00, 0x16, 0xf6, 0xea, 0x3a, 0xf0, + 0x30, 0xd0, 0x05, 0x17, 0xda, 0xb0, 0xeb, 0x9a, 0x2d, 0x4f, + 0x26, 0xb0, 0xd6, 0x38, 0xc1, 0xeb, 0xf5, 0xd8, 0x3d, 0x1f, + 0x70, 0xf7, 0x7f, 0xf4, 0xe2, 0xcf, 0x51, 0x51, 0x79, 0x88, + 0xfa, 0xe8, 0x32, 0x0e, 0x7b, 0x2d, 0x97, 0xf2, 0xfa, 0xba, + 0x27, 0xc5, 0x9c, 0xd9, 0xc5, 0xeb, 0x8a, 0x79, 0x52, 0x3c, + 0x64, 0x34, 0x7d, 0xc2, 0xcf, 0x28, 0xc7, 0x4e, 0xd5, 0x43, + 0x0b, 0xd1, 0xa6, 0xca, 0x6d, 0x03, 0x2d, 0x72, 0x23, 0xbc, + 0x6d, 0x05, 0xfa, 0x16, 0x09, 0x2f, 0x2e, 0x5c, 0xb6, 0xee, + 0x74, 0xdd, 0xd2, 0x48, 0x8e, 0x36, 0x0c, 0x06, 0x3d, 0x4d, + 0xe5, 0x10, 0x82, 0xeb, 0x6a, 0xf3, 0x4b, 0x9f, 0xd6, 0xed, + 0x11, 0xb1, 0x6e, 0xec, 0xf4, 0xfe, 0x8e, 0x75, 0x94, 0x20, + 0x2f, 0xcb, 0xac, 0x46, 0xf1, 0x02, 0x41, 0x00, 0xf9, 0x8c, + 0xa3, 0x85, 0xb1, 0xdd, 0x29, 0xaf, 0x65, 0xc1, 0x33, 0xf3, + 0x95, 0xc5, 0x52, 0x68, 0x0b, 0xd4, 0xf1, 0xe5, 0x0e, 0x02, + 0x9f, 0x4f, 0xfa, 0x77, 0xdc, 0x46, 0x9e, 0xc7, 0xa6, 0xe4, + 0x16, 0x29, 0xda, 0xb0, 0x07, 0xcf, 0x5b, 0xa9, 0x12, 0x8a, + 0xdd, 0x63, 0x0a, 0xde, 0x2e, 0x8c, 0x66, 0x8b, 0x8c, 0xdc, + 0x19, 0xa3, 0x7e, 0xf4, 0x3b, 0xd0, 0x1a, 0x8c, 0xa4, 0xc2, + 0xe1, 0xd3, 0x02, 0x41, 0x00, 0xe2, 0x4c, 0x05, 0xf2, 0x04, + 0x86, 0x4e, 0x61, 0x43, 0xdb, 0xb0, 0xb9, 0x96, 0x86, 0x52, + 0x2c, 0xca, 0x8d, 0x7b, 0xab, 0x0b, 0x13, 0x0d, 0x7e, 0x38, + 0x5b, 0xe2, 0x2e, 0x7b, 0x0e, 0xe7, 0x19, 0x99, 0x38, 0xe7, + 0xf2, 0x21, 0xbd, 0x85, 0x85, 0xe3, 0xfd, 0x28, 0x77, 0x20, + 0x31, 0x71, 0x2c, 0xd0, 0xff, 0xfb, 0x2e, 0xaf, 0x85, 0xb4, + 0x86, 0xca, 0xf3, 0xbb, 0xca, 0xaa, 0x0f, 0x95, 0x37, 0x02, + 0x40, 0x0e, 0x41, 0x9a, 0x95, 0xe8, 0xb3, 0x59, 0xce, 0x4b, + 0x61, 0xde, 0x35, 0xec, 0x38, 0x79, 0x9c, 0xb8, 0x10, 0x52, + 0x41, 0x63, 0xab, 0x82, 0xae, 0x6f, 0x00, 0xa9, 0xf4, 0xde, + 0xdd, 0x49, 0x0b, 0x7e, 0xb8, 0xa5, 0x65, 0xa9, 0x0c, 0x8f, + 0x8f, 0xf9, 0x1f, 0x35, 0xc6, 0x92, 0xb8, 0x5e, 0xb0, 0x66, + 0xab, 0x52, 0x40, 0xc0, 0xb6, 0x36, 0x6a, 0x7d, 0x80, 0x46, + 0x04, 0x02, 0xe5, 0x9f, 0x41, 0x02, 0x41, 0x00, 0xc0, 0xad, + 0xcc, 0x4e, 0x21, 0xee, 0x1d, 0x24, 0x91, 0xfb, 0xa7, 0x80, + 0x8d, 0x9a, 0xb6, 0xb3, 0x2e, 0x8f, 0xc2, 0xe1, 0x82, 0xdf, + 0x69, 0x18, 0xb4, 0x71, 0xff, 0xa6, 0x65, 0xde, 0xed, 0x84, + 0x8d, 0x42, 0xb7, 0xb3, 0x21, 0x69, 0x56, 0x1c, 0x07, 0x60, + 0x51, 0x29, 0x04, 0xff, 0x34, 0x06, 0xdd, 0xb9, 0x67, 0x2c, + 0x7c, 0x04, 0x93, 0x0e, 0x46, 0x15, 0xbb, 0x2a, 0xb7, 0x1b, + 0xe7, 0x87, 0x02, 0x40, 0x78, 0xda, 0x5d, 0x07, 0x51, 0x0c, + 0x16, 0x7a, 0x9f, 0x29, 0x20, 0x84, 0x0d, 0x42, 0xfa, 0xd7, + 0x00, 0xd8, 0x77, 0x7e, 0xb0, 0xb0, 0x6b, 0xd6, 0x5b, 0x53, + 0xb8, 0x9b, 0x7a, 0xcd, 0xc7, 0x2b, 0xb8, 0x6a, 0x63, 0xa9, + 0xfb, 0x6f, 0xa4, 0x72, 0xbf, 0x4c, 0x5d, 0x00, 0x14, 0xba, + 0xfa, 0x59, 0x88, 0xed, 0xe4, 0xe0, 0x8c, 0xa2, 0xec, 0x14, + 0x7e, 0x2d, 0xe2, 0xf0, 0x46, 0x49, 0x95, 0x45, +}; + +static unsigned char test2048[] = { + 0x30, 0x82, 0x04, 0xa3, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, + 0x01, 0x00, 0xc0, 0xc0, 0xce, 0x3e, 0x3c, 0x53, 0x67, 0x3f, + 0x4f, 0xc5, 0x2f, 0xa4, 0xc2, 0x5a, 0x2f, 0x58, 0xfd, 0x27, + 0x52, 0x6a, 0xe8, 0xcf, 0x4a, 0x73, 0x47, 0x8d, 0x25, 0x0f, + 0x5f, 0x03, 0x26, 0x78, 0xef, 0xf0, 0x22, 0x12, 0xd3, 0xde, + 0x47, 0xb2, 0x1c, 0x0b, 0x38, 0x63, 0x1a, 0x6c, 0x85, 0x7a, + 0x80, 0xc6, 0x8f, 0xa0, 0x41, 0xaf, 0x62, 0xc4, 0x67, 0x32, + 0x88, 0xf8, 0xa6, 0x9c, 0xf5, 0x23, 0x1d, 0xe4, 0xac, 0x3f, + 0x29, 0xf9, 0xec, 0xe1, 0x8b, 0x26, 0x03, 0x2c, 0xb2, 0xab, + 0xf3, 0x7d, 0xb5, 0xca, 0x49, 0xc0, 0x8f, 0x1c, 0xdf, 0x33, + 0x3a, 0x60, 0xda, 0x3c, 0xb0, 0x16, 0xf8, 0xa9, 0x12, 0x8f, + 0x64, 0xac, 0x23, 0x0c, 0x69, 0x64, 0x97, 0x5d, 0x99, 0xd4, + 0x09, 0x83, 0x9b, 0x61, 0xd3, 0xac, 0xf0, 0xde, 0xdd, 0x5e, + 0x9f, 0x44, 0x94, 0xdb, 0x3a, 0x4d, 0x97, 0xe8, 0x52, 0x29, + 0xf7, 0xdb, 0x94, 0x07, 0x45, 0x90, 0x78, 0x1e, 0x31, 0x0b, + 0x80, 0xf7, 0x57, 0xad, 0x1c, 0x79, 0xc5, 0xcb, 0x32, 0xb0, + 0xce, 0xcd, 0x74, 0xb3, 0xe2, 0x94, 0xc5, 0x78, 0x2f, 0x34, + 0x1a, 0x45, 0xf7, 0x8c, 0x52, 0xa5, 0xbc, 0x8d, 0xec, 0xd1, + 0x2f, 0x31, 0x3b, 0xf0, 0x49, 0x59, 0x5e, 0x88, 0x9d, 0x15, + 0x92, 0x35, 0x32, 0xc1, 0xe7, 0x61, 0xec, 0x50, 0x48, 0x7c, + 0xba, 0x05, 0xf9, 0xf8, 0xf8, 0xa7, 0x8c, 0x83, 0xe8, 0x66, + 0x5b, 0xeb, 0xfe, 0xd8, 0x4f, 0xdd, 0x6d, 0x36, 0xc0, 0xb2, + 0x90, 0x0f, 0xb8, 0x52, 0xf9, 0x04, 0x9b, 0x40, 0x2c, 0x27, + 0xd6, 0x36, 0x8e, 0xc2, 0x1b, 0x44, 0xf3, 0x92, 0xd5, 0x15, + 0x9e, 0x9a, 0xbc, 0xf3, 0x7d, 0x03, 0xd7, 0x02, 0x14, 0x20, + 0xe9, 0x10, 0x92, 0xfd, 0xf9, 0xfc, 0x8f, 0xe5, 0x18, 0xe1, + 0x95, 0xcc, 0x9e, 0x60, 0xa6, 0xfa, 0x38, 0x4d, 0x02, 0x03, + 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x00, 0x00, 0xc3, 0xc3, + 0x0d, 0xb4, 0x27, 0x90, 0x8d, 0x4b, 0xbf, 0xb8, 0x84, 0xaa, + 0xd0, 0xb8, 0xc7, 0x5d, 0x99, 0xbe, 0x55, 0xf6, 0x3e, 0x7c, + 0x49, 0x20, 0xcb, 0x8a, 0x8e, 0x19, 0x0e, 0x66, 0x24, 0xac, + 0xaf, 0x03, 0x33, 0x97, 0xeb, 0x95, 0xd5, 0x3b, 0x0f, 0x40, + 0x56, 0x04, 0x50, 0xd1, 0xe6, 0xbe, 0x84, 0x0b, 0x25, 0xd3, + 0x9c, 0xe2, 0x83, 0x6c, 0xf5, 0x62, 0x5d, 0xba, 0x2b, 0x7d, + 0x3d, 0x7a, 0x6c, 0xe1, 0xd2, 0x0e, 0x54, 0x93, 0x80, 0x01, + 0x91, 0x51, 0x09, 0xe8, 0x5b, 0x8e, 0x47, 0xbd, 0x64, 0xe4, + 0x0e, 0x03, 0x83, 0x55, 0xcf, 0x5a, 0x37, 0xf0, 0x25, 0xb5, + 0x7d, 0x21, 0xd7, 0x69, 0xdf, 0x6f, 0xc2, 0xcf, 0x10, 0xc9, + 0x8a, 0x40, 0x9f, 0x7a, 0x70, 0xc0, 0xe8, 0xe8, 0xc0, 0xe6, + 0x9a, 0x15, 0x0a, 0x8d, 0x4e, 0x46, 0xcb, 0x7a, 0xdb, 0xb3, + 0xcb, 0x83, 0x02, 0xc4, 0xf0, 0xab, 0xeb, 0x02, 0x01, 0x0e, + 0x23, 0xfc, 0x1d, 0xc4, 0xbd, 0xd4, 0xaa, 0x5d, 0x31, 0x46, + 0x99, 0xce, 0x9e, 0xf8, 0x04, 0x75, 0x10, 0x67, 0xc4, 0x53, + 0x47, 0x44, 0xfa, 0xc2, 0x25, 0x73, 0x7e, 0xd0, 0x8e, 0x59, + 0xd1, 0xb2, 0x5a, 0xf4, 0xc7, 0x18, 0x92, 0x2f, 0x39, 0xab, + 0xcd, 0xa3, 0xb5, 0xc2, 0xb9, 0xc7, 0xb9, 0x1b, 0x9f, 0x48, + 0xfa, 0x13, 0xc6, 0x98, 0x4d, 0xca, 0x84, 0x9c, 0x06, 0xca, + 0xe7, 0x89, 0x01, 0x04, 0xc4, 0x6c, 0xfd, 0x29, 0x59, 0x35, + 0xe7, 0xf3, 0xdd, 0xce, 0x64, 0x59, 0xbf, 0x21, 0x13, 0xa9, + 0x9f, 0x0e, 0xc5, 0xff, 0xbd, 0x33, 0x00, 0xec, 0xac, 0x6b, + 0x11, 0xef, 0x51, 0x5e, 0xad, 0x07, 0x15, 0xde, 0xb8, 0x5f, + 0xc6, 0xb9, 0xa3, 0x22, 0x65, 0x46, 0x83, 0x14, 0xdf, 0xd0, + 0xf1, 0x44, 0x8a, 0xe1, 0x9c, 0x23, 0x33, 0xb4, 0x97, 0x33, + 0xe6, 0x6b, 0x81, 0x02, 0x81, 0x81, 0x00, 0xec, 0x12, 0xa7, + 0x59, 0x74, 0x6a, 0xde, 0x3e, 0xad, 0xd8, 0x36, 0x80, 0x50, + 0xa2, 0xd5, 0x21, 0x81, 0x07, 0xf1, 0xd0, 0x91, 0xf2, 0x6c, + 0x12, 0x2f, 0x9d, 0x1a, 0x26, 0xf8, 0x30, 0x65, 0xdf, 0xe8, + 0xc0, 0x9b, 0x6a, 0x30, 0x98, 0x82, 0x87, 0xec, 0xa2, 0x56, + 0x87, 0x62, 0x6f, 0xe7, 0x9f, 0xf6, 0x56, 0xe6, 0x71, 0x8f, + 0x49, 0x86, 0x93, 0x5a, 0x4d, 0x34, 0x58, 0xfe, 0xd9, 0x04, + 0x13, 0xaf, 0x79, 0xb7, 0xad, 0x11, 0xd1, 0x30, 0x9a, 0x14, + 0x06, 0xa0, 0xfa, 0xb7, 0x55, 0xdc, 0x6c, 0x5a, 0x4c, 0x2c, + 0x59, 0x56, 0xf6, 0xe8, 0x9d, 0xaf, 0x0a, 0x78, 0x99, 0x06, + 0x06, 0x9e, 0xe7, 0x9c, 0x51, 0x55, 0x43, 0xfc, 0x3b, 0x6c, + 0x0b, 0xbf, 0x2d, 0x41, 0xa7, 0xaf, 0xb7, 0xe0, 0xe8, 0x28, + 0x18, 0xb4, 0x13, 0xd1, 0xe6, 0x97, 0xd0, 0x9f, 0x6a, 0x80, + 0xca, 0xdd, 0x1a, 0x7e, 0x15, 0x02, 0x81, 0x81, 0x00, 0xd1, + 0x06, 0x0c, 0x1f, 0xe3, 0xd0, 0xab, 0xd6, 0xca, 0x7c, 0xbc, + 0x7d, 0x13, 0x35, 0xce, 0x27, 0xcd, 0xd8, 0x49, 0x51, 0x63, + 0x64, 0x0f, 0xca, 0x06, 0x12, 0xfc, 0x07, 0x3e, 0xaf, 0x61, + 0x6d, 0xe2, 0x53, 0x39, 0x27, 0xae, 0xc3, 0x11, 0x9e, 0x94, + 0x01, 0x4f, 0xe3, 0xf3, 0x67, 0xf9, 0x77, 0xf9, 0xe7, 0x95, + 0x3a, 0x6f, 0xe2, 0x20, 0x73, 0x3e, 0xa4, 0x7a, 0x28, 0xd4, + 0x61, 0x97, 0xf6, 0x17, 0xa0, 0x23, 0x10, 0x2b, 0xce, 0x84, + 0x57, 0x7e, 0x25, 0x1f, 0xf4, 0xa8, 0x54, 0xd2, 0x65, 0x94, + 0xcc, 0x95, 0x0a, 0xab, 0x30, 0xc1, 0x59, 0x1f, 0x61, 0x8e, + 0xb9, 0x6b, 0xd7, 0x4e, 0xb9, 0x83, 0x43, 0x79, 0x85, 0x11, + 0xbc, 0x0f, 0xae, 0x25, 0x20, 0x05, 0xbc, 0xd2, 0x48, 0xa1, + 0x68, 0x09, 0x84, 0xf6, 0x12, 0x9a, 0x66, 0xb9, 0x2b, 0xbb, + 0x76, 0x03, 0x17, 0x46, 0x4e, 0x97, 0x59, 0x02, 0x81, 0x80, + 0x09, 0x4c, 0xfa, 0xd6, 0xe5, 0x65, 0x48, 0x78, 0x43, 0xb5, + 0x1f, 0x00, 0x93, 0x2c, 0xb7, 0x24, 0xe8, 0xc6, 0x7d, 0x5a, + 0x70, 0x45, 0x92, 0xc8, 0x6c, 0xa3, 0xcd, 0xe1, 0xf7, 0x29, + 0x40, 0xfa, 0x3f, 0x5b, 0x47, 0x44, 0x39, 0xc1, 0xe8, 0x72, + 0x9e, 0x7a, 0x0e, 0xda, 0xaa, 0xa0, 0x2a, 0x09, 0xfd, 0x54, + 0x93, 0x23, 0xaa, 0x37, 0x85, 0x5b, 0xcc, 0xd4, 0xf9, 0xd8, + 0xff, 0xc1, 0x61, 0x0d, 0xbd, 0x7e, 0x18, 0x24, 0x73, 0x6d, + 0x40, 0x72, 0xf1, 0x93, 0x09, 0x48, 0x97, 0x6c, 0x84, 0x90, + 0xa8, 0x46, 0x14, 0x01, 0x39, 0x11, 0xe5, 0x3c, 0x41, 0x27, + 0x32, 0x75, 0x24, 0xed, 0xa1, 0xd9, 0x12, 0x29, 0x8a, 0x28, + 0x71, 0x89, 0x8d, 0xca, 0x30, 0xb0, 0x01, 0xc4, 0x2f, 0x82, + 0x19, 0x14, 0x4c, 0x70, 0x1c, 0xb8, 0x23, 0x2e, 0xe8, 0x90, + 0x49, 0x97, 0x92, 0x97, 0x6b, 0x7a, 0x9d, 0xb9, 0x02, 0x81, + 0x80, 0x0f, 0x0e, 0xa1, 0x76, 0xf6, 0xa1, 0x44, 0x8f, 0xaf, + 0x7c, 0x76, 0xd3, 0x87, 0xbb, 0xbb, 0x83, 0x10, 0x88, 0x01, + 0x18, 0x14, 0xd1, 0xd3, 0x75, 0x59, 0x24, 0xaa, 0xf5, 0x16, + 0xa5, 0xe9, 0x9d, 0xd1, 0xcc, 0xee, 0xf4, 0x15, 0xd9, 0xc5, + 0x7e, 0x27, 0xe9, 0x44, 0x49, 0x06, 0x72, 0xb9, 0xfc, 0xd3, + 0x8a, 0xc4, 0x2c, 0x36, 0x7d, 0x12, 0x9b, 0x5a, 0xaa, 0xdc, + 0x85, 0xee, 0x6e, 0xad, 0x54, 0xb3, 0xf4, 0xfc, 0x31, 0xa1, + 0x06, 0x3a, 0x70, 0x57, 0x0c, 0xf3, 0x95, 0x5b, 0x3e, 0xe8, + 0xfd, 0x1a, 0x4f, 0xf6, 0x78, 0x93, 0x46, 0x6a, 0xd7, 0x31, + 0xb4, 0x84, 0x64, 0x85, 0x09, 0x38, 0x89, 0x92, 0x94, 0x1c, + 0xbf, 0xe2, 0x3c, 0x2a, 0xe0, 0xff, 0x99, 0xa3, 0xf0, 0x2b, + 0x31, 0xc2, 0x36, 0xcd, 0x60, 0xbf, 0x9d, 0x2d, 0x74, 0x32, + 0xe8, 0x9c, 0x93, 0x6e, 0xbb, 0x91, 0x7b, 0xfd, 0xd9, 0x02, + 0x81, 0x81, 0x00, 0xa2, 0x71, 0x25, 0x38, 0xeb, 0x2a, 0xe9, + 0x37, 0xcd, 0xfe, 0x44, 0xce, 0x90, 0x3f, 0x52, 0x87, 0x84, + 0x52, 0x1b, 0xae, 0x8d, 0x22, 0x94, 0xce, 0x38, 0xe6, 0x04, + 0x88, 0x76, 0x85, 0x9a, 0xd3, 0x14, 0x09, 0xe5, 0x69, 0x9a, + 0xff, 0x58, 0x92, 0x02, 0x6a, 0x7d, 0x7c, 0x1e, 0x2c, 0xfd, + 0xa8, 0xca, 0x32, 0x14, 0x4f, 0x0d, 0x84, 0x0d, 0x37, 0x43, + 0xbf, 0xe4, 0x5d, 0x12, 0xc8, 0x24, 0x91, 0x27, 0x8d, 0x46, + 0xd9, 0x54, 0x53, 0xe7, 0x62, 0x71, 0xa8, 0x2b, 0x71, 0x41, + 0x8d, 0x75, 0xf8, 0x3a, 0xa0, 0x61, 0x29, 0x46, 0xa6, 0xe5, + 0x82, 0xfa, 0x3a, 0xd9, 0x08, 0xfa, 0xfc, 0x63, 0xfd, 0x6b, + 0x30, 0xbc, 0xf4, 0x4e, 0x9e, 0x8c, 0x25, 0x0c, 0xb6, 0x55, + 0xe7, 0x3c, 0xd4, 0x4e, 0x0b, 0xfd, 0x8b, 0xc3, 0x0e, 0x1d, + 0x9c, 0x44, 0x57, 0x8f, 0x1f, 0x86, 0xf7, 0xd5, 0x1b, 0xe4, + 0x95, +}; + +static unsigned char test3072[] = { + 0x30, 0x82, 0x06, 0xe3, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, + 0x81, 0x00, 0xbc, 0x3b, 0x23, 0xc0, 0x33, 0xa7, 0x8b, 0xaa, + 0xca, 0xa3, 0x8c, 0x94, 0xf2, 0x4c, 0x52, 0x08, 0x85, 0x80, + 0xfc, 0x36, 0x15, 0xfa, 0x03, 0x06, 0xb6, 0xd6, 0x3f, 0x60, + 0x8a, 0x89, 0x0d, 0xba, 0x1a, 0x51, 0x0b, 0x12, 0xea, 0x71, + 0x77, 0xf6, 0x3a, 0x30, 0x21, 0x3d, 0x24, 0xf8, 0x2e, 0xd0, + 0x17, 0x3a, 0x85, 0x94, 0x25, 0x42, 0x89, 0xff, 0x6a, 0x68, + 0xdf, 0x1f, 0x86, 0xae, 0xa5, 0xbb, 0x9a, 0x79, 0xf6, 0x69, + 0x94, 0xfe, 0xde, 0xfe, 0xce, 0x1b, 0x2e, 0xae, 0x1d, 0x91, + 0xcb, 0xb9, 0xf1, 0x2d, 0xd8, 0x00, 0x82, 0x51, 0x8e, 0xf9, + 0xfd, 0xac, 0xf1, 0x0e, 0x7f, 0xb7, 0x95, 0x85, 0x35, 0xf9, + 0xcb, 0xbe, 0x5f, 0xd3, 0x58, 0xe3, 0xa1, 0x54, 0x9e, 0x30, + 0xb1, 0x8d, 0x01, 0x97, 0x82, 0x06, 0x8e, 0x77, 0xfb, 0xce, + 0x50, 0x2f, 0xbf, 0xf1, 0xff, 0x57, 0x0a, 0x42, 0x03, 0xfd, + 0x0e, 0xba, 0x1e, 0xca, 0x85, 0xc1, 0x9b, 0xa5, 0x9d, 0x09, + 0x0e, 0xe9, 0xbb, 0xc5, 0x73, 0x47, 0x0d, 0x39, 0x3c, 0x64, + 0x06, 0x9a, 0x79, 0x3f, 0x50, 0x87, 0x9c, 0x18, 0x2d, 0x62, + 0x01, 0xfc, 0xed, 0xc1, 0x58, 0x28, 0x21, 0x94, 0x1e, 0xf9, + 0x2d, 0x96, 0x4f, 0xd0, 0xbc, 0xf1, 0xe0, 0x8a, 0xfa, 0x4d, + 0xb6, 0x78, 0x4a, 0xde, 0x17, 0x59, 0xb0, 0x22, 0xa0, 0x9a, + 0xd3, 0x70, 0xb6, 0xc2, 0xbe, 0xbc, 0x96, 0xca, 0x41, 0x5f, + 0x58, 0x4e, 0xce, 0xef, 0x64, 0x45, 0xdd, 0x3f, 0x81, 0x92, + 0xcc, 0x40, 0x79, 0xfc, 0x19, 0xe2, 0xbc, 0x77, 0x2f, 0x43, + 0xfb, 0x8e, 0xad, 0x82, 0x4a, 0x0b, 0xb1, 0xbc, 0x09, 0x8a, + 0x80, 0xc3, 0x0f, 0xef, 0xd2, 0x06, 0xd3, 0x4b, 0x0c, 0x7f, + 0xae, 0x60, 0x3f, 0x2e, 0x52, 0xb4, 0xe4, 0xc2, 0x5c, 0xa6, + 0x71, 0xc0, 0x13, 0x9c, 0xca, 0xa6, 0x0d, 0x13, 0xd7, 0xb7, + 0x14, 0x94, 0x3f, 0x0d, 0x8b, 0x06, 0x70, 0x2f, 0x15, 0x82, + 0x8d, 0x47, 0x45, 0xa6, 0x00, 0x8a, 0x14, 0x91, 0xde, 0x2f, + 0x50, 0x17, 0xe3, 0x1d, 0x34, 0x29, 0x8c, 0xe4, 0x57, 0x74, + 0x2a, 0x3a, 0x82, 0x65, 0x26, 0xf7, 0x8d, 0xcc, 0x1b, 0x8f, + 0xaf, 0xe5, 0x85, 0xe5, 0xbe, 0x85, 0xd6, 0xb7, 0x04, 0xe8, + 0xf5, 0xd4, 0x74, 0xe2, 0x54, 0x14, 0xdd, 0x58, 0xcf, 0x1f, + 0x11, 0x8a, 0x9f, 0x82, 0xa2, 0x01, 0xf9, 0xc2, 0xdf, 0x7b, + 0x84, 0xb1, 0xd8, 0x5b, 0x70, 0xbb, 0x24, 0xe7, 0xd0, 0x2a, + 0x75, 0x3d, 0x55, 0xac, 0x45, 0xe9, 0xab, 0xc6, 0x84, 0x8a, + 0xe7, 0x6d, 0x26, 0x12, 0x89, 0xb5, 0x67, 0xe8, 0x46, 0x9d, + 0x46, 0x1a, 0xfa, 0x2d, 0xc0, 0x5b, 0x60, 0x46, 0x8b, 0xb7, + 0x32, 0x03, 0xff, 0x75, 0xee, 0x9f, 0x3c, 0xdd, 0xb6, 0x35, + 0x4e, 0x82, 0xbd, 0x99, 0x73, 0x51, 0x02, 0x03, 0x01, 0x00, + 0x01, 0x02, 0x82, 0x01, 0x80, 0x42, 0xee, 0xa4, 0x9f, 0xcb, + 0xbe, 0x60, 0x23, 0xb3, 0x3a, 0xc4, 0xda, 0x91, 0xee, 0x21, + 0x9d, 0x76, 0x1b, 0x8f, 0x93, 0x8b, 0xed, 0x02, 0xf6, 0x78, + 0x3d, 0x66, 0xfb, 0xe5, 0x47, 0x26, 0xe2, 0x6e, 0x49, 0x33, + 0x2e, 0xde, 0xbe, 0xca, 0x71, 0x7b, 0xef, 0x71, 0x62, 0x54, + 0xab, 0x0b, 0xba, 0x63, 0x08, 0x24, 0x47, 0xb1, 0x98, 0x1f, + 0x89, 0xfb, 0x44, 0x9f, 0x52, 0x8e, 0x89, 0xbb, 0xd5, 0x21, + 0xf1, 0x0c, 0x76, 0x2e, 0xcd, 0x12, 0x6e, 0x78, 0xcb, 0xa1, + 0xa5, 0xb8, 0x4e, 0x07, 0xab, 0x6e, 0xdf, 0x66, 0x57, 0x87, + 0xff, 0x88, 0x5f, 0xcc, 0x9c, 0x9a, 0x7b, 0x15, 0x5f, 0x2a, + 0x83, 0xdb, 0xd5, 0x9f, 0x65, 0x6a, 0x9d, 0xb4, 0x95, 0xfc, + 0xe0, 0x22, 0x00, 0x1e, 0xa2, 0x8d, 0x56, 0x5a, 0x9e, 0x0a, + 0x3b, 0x10, 0x07, 0x24, 0xec, 0x55, 0xcc, 0xaf, 0x87, 0x3b, + 0xd6, 0x8d, 0xa4, 0x86, 0x80, 0x18, 0x42, 0xdb, 0x9d, 0x24, + 0xc3, 0x97, 0x3b, 0x89, 0x5a, 0x03, 0xb3, 0x0a, 0x72, 0xd1, + 0x78, 0xf0, 0xc8, 0x80, 0xb0, 0x9d, 0x3c, 0xae, 0x5e, 0x0a, + 0x5b, 0x6e, 0x87, 0xd3, 0x3d, 0x25, 0x2e, 0x03, 0x33, 0x01, + 0xfd, 0xb1, 0xa5, 0xd9, 0x58, 0x01, 0xb9, 0xaf, 0xf6, 0x32, + 0x6a, 0x38, 0xe7, 0x39, 0x63, 0x3c, 0xfc, 0x0c, 0x41, 0x90, + 0x28, 0x40, 0x03, 0xcd, 0xfb, 0xde, 0x80, 0x74, 0x21, 0xaa, + 0xae, 0x58, 0xe9, 0x97, 0x18, 0x85, 0x58, 0x3d, 0x2b, 0xd6, + 0x61, 0xf6, 0xe8, 0xbc, 0x6d, 0x2a, 0xf3, 0xb8, 0xea, 0x8c, + 0x64, 0x44, 0xc6, 0xd3, 0x9f, 0x00, 0x7b, 0xb2, 0x52, 0x18, + 0x11, 0x04, 0x96, 0xb7, 0x05, 0xbb, 0xc2, 0x38, 0x5b, 0xa7, + 0x0a, 0x84, 0xb6, 0x4f, 0x02, 0x63, 0xa4, 0x57, 0x00, 0xe3, + 0xde, 0xe4, 0xf2, 0xb3, 0x55, 0xd9, 0x00, 0xa9, 0xd2, 0x5c, + 0x69, 0x9f, 0xe5, 0x80, 0x4f, 0x23, 0x7c, 0xd9, 0xa7, 0x77, + 0x4a, 0xbb, 0x09, 0x6d, 0x45, 0x02, 0xcf, 0x32, 0x90, 0xfd, + 0x10, 0xb6, 0xb3, 0x93, 0xd9, 0x3b, 0x1d, 0x57, 0x66, 0xb5, + 0xb3, 0xb1, 0x6e, 0x53, 0x5f, 0x04, 0x60, 0x29, 0xcd, 0xe8, + 0xb8, 0xab, 0x62, 0x82, 0x33, 0x40, 0xc7, 0xf8, 0x64, 0x60, + 0x0e, 0xab, 0x06, 0x3e, 0xa0, 0xa3, 0x62, 0x11, 0x3f, 0x67, + 0x5d, 0x24, 0x9e, 0x60, 0x29, 0xdc, 0x4c, 0xd5, 0x13, 0xee, + 0x3d, 0xb7, 0x84, 0x93, 0x27, 0xb5, 0x6a, 0xf9, 0xf0, 0xdd, + 0x50, 0xac, 0x46, 0x3c, 0xe6, 0xd5, 0xec, 0xf7, 0xb7, 0x9f, + 0x23, 0x39, 0x9c, 0x88, 0x8c, 0x5a, 0x62, 0x3f, 0x8d, 0x4a, + 0xd7, 0xeb, 0x5e, 0x1e, 0x49, 0xf8, 0xa9, 0x53, 0x11, 0x75, + 0xd0, 0x43, 0x1e, 0xc7, 0x29, 0x22, 0x80, 0x1f, 0xc5, 0x83, + 0x8d, 0x20, 0x04, 0x87, 0x7f, 0x57, 0x8c, 0xf5, 0xa1, 0x02, + 0x81, 0xc1, 0x00, 0xf7, 0xaa, 0xf5, 0xa5, 0x00, 0xdb, 0xd6, + 0x11, 0xfc, 0x07, 0x6d, 0x22, 0x24, 0x2b, 0x4b, 0xc5, 0x67, + 0x0f, 0x37, 0xa5, 0xdb, 0x8f, 0x38, 0xe2, 0x05, 0x43, 0x9a, + 0x44, 0x05, 0x3f, 0xa9, 0xac, 0x4c, 0x98, 0x3c, 0x72, 0x38, + 0xc3, 0x89, 0x33, 0x58, 0x73, 0x51, 0xcc, 0x5d, 0x2f, 0x8f, + 0x6d, 0x3f, 0xa1, 0x22, 0x9e, 0xfb, 0x9a, 0xb4, 0xb8, 0x79, + 0x95, 0xaf, 0x83, 0xcf, 0x5a, 0xb7, 0x14, 0x14, 0x0c, 0x51, + 0x8a, 0x11, 0xe6, 0xd6, 0x21, 0x1e, 0x17, 0x13, 0xd3, 0x69, + 0x7a, 0x3a, 0xd5, 0xaf, 0x3f, 0xb8, 0x25, 0x01, 0xcb, 0x2b, + 0xe6, 0xfc, 0x03, 0xd8, 0xd4, 0xf7, 0x20, 0xe0, 0x21, 0xef, + 0x1a, 0xca, 0x61, 0xeb, 0x8e, 0x96, 0x45, 0x8e, 0x5c, 0xe6, + 0x81, 0x0b, 0x2d, 0x05, 0x32, 0xf9, 0x41, 0x62, 0xb4, 0x33, + 0x98, 0x10, 0x3a, 0xcd, 0xf0, 0x7a, 0x8b, 0x1a, 0x48, 0xd7, + 0x3b, 0x01, 0xf5, 0x18, 0x65, 0x8f, 0x3c, 0xc2, 0x31, 0x3b, + 0xd3, 0xa7, 0x17, 0x5f, 0x7c, 0x0c, 0xe7, 0x25, 0x18, 0x5a, + 0x08, 0xe1, 0x09, 0x89, 0x13, 0xa7, 0xc5, 0x12, 0xab, 0x88, + 0x30, 0xcd, 0x06, 0xf9, 0xba, 0x6f, 0xca, 0x9c, 0x8a, 0xda, + 0x3e, 0x53, 0x90, 0xd7, 0x16, 0x2e, 0xfc, 0xbc, 0xad, 0xd6, + 0x3d, 0xc0, 0x66, 0x4c, 0x02, 0x3d, 0x31, 0xfd, 0x6c, 0xdb, + 0x1c, 0xdf, 0x96, 0x33, 0x23, 0x02, 0x81, 0xc1, 0x00, 0xc2, + 0x90, 0x47, 0xc4, 0xfb, 0x59, 0xf0, 0xc5, 0x14, 0x75, 0x29, + 0xfa, 0x77, 0xa1, 0x8d, 0xd4, 0x90, 0xa1, 0x0d, 0x3f, 0x16, + 0x88, 0xe3, 0x4c, 0x8f, 0x8f, 0x18, 0x8c, 0x9c, 0x8a, 0xd5, + 0xa7, 0x41, 0x99, 0xf3, 0x80, 0x8e, 0xb1, 0xb8, 0x63, 0xd8, + 0x3f, 0x95, 0xd0, 0xd0, 0x2b, 0xf5, 0xe6, 0x93, 0xe8, 0xfe, + 0xd0, 0x73, 0xd5, 0xbd, 0xb4, 0xee, 0x51, 0x19, 0x6a, 0x10, + 0xca, 0xc8, 0xba, 0xa4, 0x4d, 0x84, 0x54, 0x38, 0x17, 0xb5, + 0xd0, 0xa8, 0x75, 0x22, 0xc5, 0x1b, 0x61, 0xa6, 0x51, 0x88, + 0x63, 0xf0, 0x4f, 0xd1, 0x88, 0xd9, 0x16, 0x49, 0x30, 0xe1, + 0xa8, 0x47, 0xc9, 0x30, 0x1d, 0x5c, 0x75, 0xd8, 0x89, 0xb6, + 0x1d, 0x45, 0xd8, 0x0f, 0x94, 0x89, 0xb3, 0xe4, 0x51, 0xfa, + 0x21, 0xff, 0x6f, 0xb6, 0x30, 0x6f, 0x33, 0x24, 0xbc, 0x09, + 0x98, 0xe9, 0x20, 0x02, 0x0b, 0xde, 0xff, 0xc5, 0x06, 0xb6, + 0x28, 0xa3, 0xa1, 0x07, 0xe8, 0xe1, 0xd2, 0xc2, 0xf1, 0xd1, + 0x23, 0x6b, 0x4c, 0x3a, 0xae, 0x85, 0xec, 0xf9, 0xff, 0xa7, + 0x9b, 0x25, 0xb8, 0x95, 0x1d, 0xa8, 0x14, 0x81, 0x4f, 0x79, + 0x4f, 0xd6, 0x39, 0x5d, 0xe6, 0x5f, 0xd2, 0x34, 0x54, 0x8b, + 0x1e, 0x40, 0x4c, 0x15, 0x5a, 0x45, 0xce, 0x0c, 0xb0, 0xdf, + 0xa1, 0x17, 0xb8, 0xb0, 0x6a, 0x82, 0xa5, 0x97, 0x92, 0x70, + 0xfb, 0x02, 0x81, 0xc0, 0x77, 0x46, 0x44, 0x2b, 0x04, 0xf0, + 0xda, 0x75, 0xaa, 0xd4, 0xc0, 0xc0, 0x32, 0x7f, 0x0f, 0x6c, + 0xb0, 0x27, 0x69, 0xfb, 0x5c, 0x73, 0xeb, 0x47, 0x1e, 0x95, + 0xe2, 0x13, 0x64, 0x1b, 0xb6, 0xd1, 0x1d, 0xca, 0x2b, 0x42, + 0x2f, 0x08, 0x2c, 0x69, 0x27, 0xed, 0xd1, 0xb5, 0x04, 0x23, + 0xc5, 0x85, 0x2d, 0xa1, 0xa2, 0x94, 0xc2, 0x43, 0x4d, 0x49, + 0x92, 0x74, 0x7e, 0x24, 0x92, 0x95, 0xf3, 0x99, 0x9d, 0xd6, + 0x18, 0xe6, 0xcf, 0x9c, 0x45, 0xff, 0x89, 0x08, 0x40, 0x2a, + 0x0e, 0xa0, 0x28, 0xf9, 0x83, 0xfe, 0xc1, 0xe6, 0x40, 0xa8, + 0xe2, 0x29, 0xc9, 0xb0, 0xe8, 0x9a, 0x17, 0xb2, 0x23, 0x7e, + 0xf4, 0x32, 0x08, 0xc9, 0x83, 0xb2, 0x15, 0xb8, 0xc5, 0xc9, + 0x03, 0xd1, 0x9d, 0xda, 0x3e, 0xa8, 0xbf, 0xd5, 0xb7, 0x7d, + 0x65, 0x63, 0x94, 0x5d, 0x5d, 0x94, 0xb4, 0xcf, 0x8d, 0x07, + 0x0b, 0x70, 0x85, 0x8e, 0xce, 0x03, 0x0b, 0x2a, 0x8d, 0xb3, + 0x3c, 0x46, 0xc0, 0x2f, 0xc7, 0x72, 0x6c, 0x9c, 0x5d, 0x07, + 0x0f, 0x45, 0x3b, 0x6b, 0x66, 0x32, 0xab, 0x17, 0x83, 0xd8, + 0x4c, 0x2c, 0x84, 0x71, 0x19, 0x8f, 0xaa, 0x0a, 0xff, 0xbc, + 0xf7, 0x42, 0x10, 0xe8, 0xae, 0x4d, 0x26, 0xaf, 0xdd, 0x06, + 0x33, 0x29, 0x66, 0x21, 0x5d, 0xf5, 0xae, 0x17, 0x07, 0x1f, + 0x87, 0x9e, 0xae, 0x27, 0x1d, 0xd5, 0x02, 0x81, 0xc0, 0x56, + 0x17, 0x4f, 0x9a, 0x8a, 0xf9, 0xde, 0x3e, 0xe6, 0x71, 0x7d, + 0x94, 0xb5, 0xb0, 0xc7, 0xb8, 0x62, 0x12, 0xd1, 0x70, 0xb4, + 0x00, 0xf8, 0x4a, 0xdd, 0x4f, 0x1d, 0x36, 0xc2, 0xe1, 0xef, + 0xee, 0x25, 0x6a, 0x00, 0xc4, 0x46, 0xdf, 0xbe, 0xce, 0x77, + 0x56, 0x93, 0x6d, 0x25, 0x5f, 0xfe, 0x5b, 0xfb, 0xe0, 0xe2, + 0x37, 0xcc, 0xb9, 0xac, 0x4a, 0xce, 0x15, 0x16, 0xa0, 0xc7, + 0x33, 0x63, 0xa4, 0xaa, 0xa5, 0x1e, 0x43, 0xc1, 0xda, 0x43, + 0xfa, 0x43, 0x40, 0x29, 0x95, 0x7c, 0x2b, 0x36, 0x53, 0xe7, + 0x7d, 0x09, 0x4d, 0xd8, 0x52, 0xac, 0x74, 0x5f, 0x08, 0x81, + 0x21, 0x5c, 0x3a, 0x5a, 0xce, 0xf3, 0x25, 0xb6, 0x1e, 0x21, + 0x76, 0x4c, 0x7c, 0x71, 0x50, 0x71, 0xaa, 0x27, 0x02, 0x5b, + 0x23, 0x06, 0x0b, 0x21, 0x5b, 0xc7, 0x28, 0xa3, 0x3d, 0x8d, + 0x25, 0x9b, 0x2a, 0x2d, 0x9d, 0xa1, 0x1c, 0x1d, 0xcb, 0x7d, + 0x78, 0xf8, 0x06, 0x7e, 0x20, 0x7f, 0x24, 0x2a, 0x5c, 0xa4, + 0x04, 0xff, 0x2a, 0x68, 0xe0, 0xe6, 0xa3, 0xd8, 0x6f, 0x56, + 0x73, 0xa1, 0x3a, 0x4e, 0xc9, 0x23, 0xa1, 0x87, 0x22, 0x6a, + 0x74, 0x78, 0x3f, 0x44, 0x1c, 0x77, 0x13, 0xe5, 0x51, 0xef, + 0x89, 0x00, 0x3c, 0x6a, 0x4a, 0x5a, 0x8e, 0xf5, 0x30, 0xa2, + 0x93, 0x7e, 0x92, 0x9b, 0x85, 0x55, 0xaf, 0xfe, 0x24, 0xaf, + 0x57, 0x02, 0x81, 0xc1, 0x00, 0xa4, 0xc2, 0x6a, 0x59, 0x45, + 0xea, 0x71, 0x7d, 0x4c, 0xaf, 0xaf, 0xd6, 0x55, 0x97, 0x73, + 0xc5, 0xa1, 0x3c, 0xf6, 0x59, 0x23, 0xb6, 0x1f, 0x5e, 0x9c, + 0x96, 0x0f, 0x97, 0x66, 0x82, 0x91, 0x48, 0x36, 0x70, 0x02, + 0x67, 0xde, 0x34, 0xa6, 0x95, 0x7b, 0x51, 0x43, 0x66, 0xa4, + 0x16, 0x45, 0x59, 0x12, 0xdb, 0x35, 0x19, 0x4b, 0xbf, 0x1d, + 0xab, 0xf3, 0x3f, 0xb4, 0xb4, 0x6f, 0x66, 0xb0, 0x67, 0xc6, + 0x77, 0x2c, 0x46, 0xa8, 0x03, 0x64, 0x9a, 0x13, 0x9d, 0x40, + 0x22, 0x56, 0x76, 0x1a, 0x7c, 0x1e, 0xe2, 0xda, 0x7f, 0x09, + 0xcf, 0x10, 0xe3, 0xf2, 0xf4, 0x2a, 0x3b, 0x46, 0xc7, 0x61, + 0x9b, 0xef, 0x4a, 0x18, 0x60, 0x8c, 0x32, 0x71, 0xb9, 0xdd, + 0xac, 0xa0, 0xc6, 0x8d, 0x3f, 0xab, 0xc3, 0x21, 0x2c, 0xeb, + 0x91, 0x8f, 0xc7, 0x43, 0x0d, 0x0c, 0x67, 0x9e, 0xab, 0xe6, + 0x8d, 0xb6, 0x2d, 0x41, 0xca, 0x43, 0xd8, 0xcb, 0x30, 0xfb, + 0x3b, 0x40, 0x0d, 0x10, 0x9b, 0xb1, 0x55, 0x93, 0x73, 0x8b, + 0x60, 0xef, 0xc0, 0xee, 0xc0, 0xa6, 0x7a, 0x79, 0x90, 0xfd, + 0x4c, 0x25, 0xd4, 0x4f, 0x67, 0xbe, 0xf7, 0x86, 0x3c, 0x5d, + 0x2b, 0x7d, 0x97, 0x3d, 0xa2, 0x91, 0xa5, 0x06, 0x69, 0xf6, + 0x7a, 0xb8, 0x77, 0xe6, 0x70, 0xa9, 0xd8, 0x86, 0x4b, 0xa6, + 0xcf, 0x67, 0x1d, 0x33, 0xcf, 0xfe, 0x3e +}; + +static unsigned char test4096[] = { + 0x30, 0x82, 0x09, 0x29, 0x02, 0x01, 0x00, 0x02, 0x82, 0x02, + 0x01, 0x00, 0xc0, 0x71, 0xac, 0x1a, 0x13, 0x88, 0x82, 0x43, + 0x3b, 0x51, 0x57, 0x71, 0x8d, 0xb6, 0x2b, 0x82, 0x65, 0x21, + 0x53, 0x5f, 0x28, 0x29, 0x4f, 0x8d, 0x7c, 0x8a, 0xb9, 0x44, + 0xb3, 0x28, 0x41, 0x4f, 0xd3, 0xfa, 0x6a, 0xf8, 0xb9, 0x28, + 0x50, 0x39, 0x67, 0x53, 0x2c, 0x3c, 0xd7, 0xcb, 0x96, 0x41, + 0x40, 0x32, 0xbb, 0xeb, 0x70, 0xae, 0x1f, 0xb0, 0x65, 0xf7, + 0x3a, 0xd9, 0x22, 0xfd, 0x10, 0xae, 0xbd, 0x02, 0xe2, 0xdd, + 0xf3, 0xc2, 0x79, 0x3c, 0xc6, 0xfc, 0x75, 0xbb, 0xaf, 0x4e, + 0x3a, 0x36, 0xc2, 0x4f, 0xea, 0x25, 0xdf, 0x13, 0x16, 0x4b, + 0x20, 0xfe, 0x4b, 0x69, 0x16, 0xc4, 0x7f, 0x1a, 0x43, 0xa6, + 0x17, 0x1b, 0xb9, 0x0a, 0xf3, 0x09, 0x86, 0x28, 0x89, 0xcf, + 0x2c, 0xd0, 0xd4, 0x81, 0xaf, 0xc6, 0x6d, 0xe6, 0x21, 0x8d, + 0xee, 0xef, 0xea, 0xdc, 0xb7, 0xc6, 0x3b, 0x63, 0x9f, 0x0e, + 0xad, 0x89, 0x78, 0x23, 0x18, 0xbf, 0x70, 0x7e, 0x84, 0xe0, + 0x37, 0xec, 0xdb, 0x8e, 0x9c, 0x3e, 0x6a, 0x19, 0xcc, 0x99, + 0x72, 0xe6, 0xb5, 0x7d, 0x6d, 0xfa, 0xe5, 0xd3, 0xe4, 0x90, + 0xb5, 0xb2, 0xb2, 0x12, 0x70, 0x4e, 0xca, 0xf8, 0x10, 0xf8, + 0xa3, 0x14, 0xc2, 0x48, 0x19, 0xeb, 0x60, 0x99, 0xbb, 0x2a, + 0x1f, 0xb1, 0x7a, 0xb1, 0x3d, 0x24, 0xfb, 0xa0, 0x29, 0xda, + 0xbd, 0x1b, 0xd7, 0xa4, 0xbf, 0xef, 0x60, 0x2d, 0x22, 0xca, + 0x65, 0x98, 0xf1, 0xc4, 0xe1, 0xc9, 0x02, 0x6b, 0x16, 0x28, + 0x2f, 0xa1, 0xaa, 0x79, 0x00, 0xda, 0xdc, 0x7c, 0x43, 0xf7, + 0x42, 0x3c, 0xa0, 0xef, 0x68, 0xf7, 0xdf, 0xb9, 0x69, 0xfb, + 0x8e, 0x01, 0xed, 0x01, 0x42, 0xb5, 0x4e, 0x57, 0xa6, 0x26, + 0xb8, 0xd0, 0x7b, 0x56, 0x6d, 0x03, 0xc6, 0x40, 0x8c, 0x8c, + 0x2a, 0x55, 0xd7, 0x9c, 0x35, 0x00, 0x94, 0x93, 0xec, 0x03, + 0xeb, 0x22, 0xef, 0x77, 0xbb, 0x79, 0x13, 0x3f, 0x15, 0xa1, + 0x8f, 0xca, 0xdf, 0xfd, 0xd3, 0xb8, 0xe1, 0xd4, 0xcc, 0x09, + 0x3f, 0x3c, 0x2c, 0xdb, 0xd1, 0x49, 0x7f, 0x38, 0x07, 0x83, + 0x6d, 0xeb, 0x08, 0x66, 0xe9, 0x06, 0x44, 0x12, 0xac, 0x95, + 0x22, 0x90, 0x23, 0x67, 0xd4, 0x08, 0xcc, 0xf4, 0xb7, 0xdc, + 0xcc, 0x87, 0xd4, 0xac, 0x69, 0x35, 0x4c, 0xb5, 0x39, 0x36, + 0xcd, 0xa4, 0xd2, 0x95, 0xca, 0x0d, 0xc5, 0xda, 0xc2, 0xc5, + 0x22, 0x32, 0x28, 0x08, 0xe3, 0xd2, 0x8b, 0x38, 0x30, 0xdc, + 0x8c, 0x75, 0x4f, 0x6a, 0xec, 0x7a, 0xac, 0x16, 0x3e, 0xa8, + 0xd4, 0x6a, 0x45, 0xe1, 0xa8, 0x4f, 0x2e, 0x80, 0x34, 0xaa, + 0x54, 0x1b, 0x02, 0x95, 0x7d, 0x8a, 0x6d, 0xcc, 0x79, 0xca, + 0xf2, 0xa4, 0x2e, 0x8d, 0xfb, 0xfe, 0x15, 0x51, 0x10, 0x0e, + 0x4d, 0x88, 0xb1, 0xc7, 0xf4, 0x79, 0xdb, 0xf0, 0xb4, 0x56, + 0x44, 0x37, 0xca, 0x5a, 0xc1, 0x8c, 0x48, 0xac, 0xae, 0x48, + 0x80, 0x83, 0x01, 0x3f, 0xde, 0xd9, 0xd3, 0x2c, 0x51, 0x46, + 0xb1, 0x41, 0xb6, 0xc6, 0x91, 0x72, 0xf9, 0x83, 0x55, 0x1b, + 0x8c, 0xba, 0xf3, 0x73, 0xe5, 0x2c, 0x74, 0x50, 0x3a, 0xbe, + 0xc5, 0x2f, 0xa7, 0xb2, 0x6d, 0x8c, 0x9e, 0x13, 0x77, 0xa3, + 0x13, 0xcd, 0x6d, 0x8c, 0x45, 0xe1, 0xfc, 0x0b, 0xb7, 0x69, + 0xe9, 0x27, 0xbc, 0x65, 0xc3, 0xfa, 0x9b, 0xd0, 0xef, 0xfe, + 0xe8, 0x1f, 0xb3, 0x5e, 0x34, 0xf4, 0x8c, 0xea, 0xfc, 0xd3, + 0x81, 0xbf, 0x3d, 0x30, 0xb2, 0xb4, 0x01, 0xe8, 0x43, 0x0f, + 0xba, 0x02, 0x23, 0x42, 0x76, 0x82, 0x31, 0x73, 0x91, 0xed, + 0x07, 0x46, 0x61, 0x0d, 0x39, 0x83, 0x40, 0xce, 0x7a, 0xd4, + 0xdb, 0x80, 0x2c, 0x1f, 0x0d, 0xd1, 0x34, 0xd4, 0x92, 0xe3, + 0xd4, 0xf1, 0xc2, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, + 0x82, 0x02, 0x01, 0x00, 0x97, 0x6c, 0xda, 0x6e, 0xea, 0x4f, + 0xcf, 0xaf, 0xf7, 0x4c, 0xd9, 0xf1, 0x90, 0x00, 0x77, 0xdb, + 0xf2, 0x97, 0x76, 0x72, 0xb9, 0xb7, 0x47, 0xd1, 0x9c, 0xdd, + 0xcb, 0x4a, 0x33, 0x6e, 0xc9, 0x75, 0x76, 0xe6, 0xe4, 0xa5, + 0x31, 0x8c, 0x77, 0x13, 0xb4, 0x29, 0xcd, 0xf5, 0x52, 0x17, + 0xef, 0xf3, 0x08, 0x00, 0xe3, 0xbd, 0x2e, 0xbc, 0xd4, 0x52, + 0x88, 0xe9, 0x30, 0x75, 0x0b, 0x02, 0xf5, 0xcd, 0x89, 0x0c, + 0x6c, 0x57, 0x19, 0x27, 0x3d, 0x1e, 0x85, 0xb4, 0xc1, 0x2f, + 0x1d, 0x92, 0x00, 0x5c, 0x76, 0x29, 0x4b, 0xa4, 0xe1, 0x12, + 0xb3, 0xc8, 0x09, 0xfe, 0x0e, 0x78, 0x72, 0x61, 0xcb, 0x61, + 0x6f, 0x39, 0x91, 0x95, 0x4e, 0xd5, 0x3e, 0xc7, 0x8f, 0xb8, + 0xf6, 0x36, 0xfe, 0x9c, 0x93, 0x9a, 0x38, 0x25, 0x7a, 0xf4, + 0x4a, 0x12, 0xd4, 0xa0, 0x13, 0xbd, 0xf9, 0x1d, 0x12, 0x3e, + 0x21, 0x39, 0xfb, 0x72, 0xe0, 0x05, 0x3d, 0xc3, 0xe5, 0x50, + 0xa8, 0x5d, 0x85, 0xa3, 0xea, 0x5f, 0x1c, 0xb2, 0x3f, 0xea, + 0x6d, 0x03, 0x91, 0x55, 0xd8, 0x19, 0x0a, 0x21, 0x12, 0x16, + 0xd9, 0x12, 0xc4, 0xe6, 0x07, 0x18, 0x5b, 0x26, 0xa4, 0xae, + 0xed, 0x2b, 0xb7, 0xa6, 0xed, 0xf8, 0xad, 0xec, 0x77, 0xe6, + 0x7f, 0x4f, 0x76, 0x00, 0xc0, 0xfa, 0x15, 0x92, 0xb4, 0x2c, + 0x22, 0xc2, 0xeb, 0x6a, 0xad, 0x14, 0x05, 0xb2, 0xe5, 0x8a, + 0x9e, 0x85, 0x83, 0xcc, 0x04, 0xf1, 0x56, 0x78, 0x44, 0x5e, + 0xde, 0xe0, 0x60, 0x1a, 0x65, 0x79, 0x31, 0x23, 0x05, 0xbb, + 0x01, 0xff, 0xdd, 0x2e, 0xb7, 0xb3, 0xaa, 0x74, 0xe0, 0xa5, + 0x94, 0xaf, 0x4b, 0xde, 0x58, 0x0f, 0x55, 0xde, 0x33, 0xf6, + 0xe3, 0xd6, 0x34, 0x36, 0x57, 0xd6, 0x79, 0x91, 0x2e, 0xbe, + 0x3b, 0xd9, 0x4e, 0xb6, 0x9d, 0x21, 0x5c, 0xd3, 0x48, 0x14, + 0x7f, 0x4a, 0xc4, 0x60, 0xa9, 0x29, 0xf8, 0x53, 0x7f, 0x88, + 0x11, 0x2d, 0xb5, 0xc5, 0x2d, 0x6f, 0xee, 0x85, 0x0b, 0xf7, + 0x8d, 0x9a, 0xbe, 0xb0, 0x42, 0xf2, 0x2e, 0x71, 0xaf, 0x19, + 0x31, 0x6d, 0xec, 0xcd, 0x6f, 0x2b, 0x23, 0xdf, 0xb4, 0x40, + 0xaf, 0x2c, 0x0a, 0xc3, 0x1b, 0x7d, 0x7d, 0x03, 0x1d, 0x4b, + 0xf3, 0xb5, 0xe0, 0x85, 0xd8, 0xdf, 0x91, 0x6b, 0x0a, 0x69, + 0xf7, 0xf2, 0x69, 0x66, 0x5b, 0xf1, 0xcf, 0x46, 0x7d, 0xe9, + 0x70, 0xfa, 0x6d, 0x7e, 0x75, 0x4e, 0xa9, 0x77, 0xe6, 0x8c, + 0x02, 0xf7, 0x14, 0x4d, 0xa5, 0x41, 0x8f, 0x3f, 0xc1, 0x62, + 0x1e, 0x71, 0x5e, 0x38, 0xb4, 0xd6, 0xe6, 0xe1, 0x4b, 0xc2, + 0x2c, 0x30, 0x83, 0x81, 0x6f, 0x49, 0x2e, 0x96, 0xe6, 0xc9, + 0x9a, 0xf7, 0x5d, 0x09, 0xa0, 0x55, 0x02, 0xa5, 0x3a, 0x25, + 0x23, 0xd0, 0x92, 0xc3, 0xa3, 0xe3, 0x0e, 0x12, 0x2f, 0x4d, + 0xef, 0xf3, 0x55, 0x5a, 0xbe, 0xe6, 0x19, 0x86, 0x31, 0xab, + 0x75, 0x9a, 0xd3, 0xf0, 0x2c, 0xc5, 0x41, 0x92, 0xd9, 0x1f, + 0x5f, 0x11, 0x8c, 0x75, 0x1c, 0x63, 0xd0, 0x02, 0x80, 0x2c, + 0x68, 0xcb, 0x93, 0xfb, 0x51, 0x73, 0x49, 0xb4, 0x60, 0xda, + 0xe2, 0x26, 0xaf, 0xa9, 0x46, 0x12, 0xb8, 0xec, 0x50, 0xdd, + 0x12, 0x06, 0x5f, 0xce, 0x59, 0xe6, 0xf6, 0x1c, 0xe0, 0x54, + 0x10, 0xad, 0xf6, 0xcd, 0x98, 0xcc, 0x0f, 0xfb, 0xcb, 0x41, + 0x14, 0x9d, 0xed, 0xe4, 0xb4, 0x74, 0x5f, 0x09, 0x60, 0xc7, + 0x12, 0xf6, 0x7b, 0x3c, 0x8f, 0xa7, 0x20, 0xbc, 0xe4, 0xb1, + 0xef, 0xeb, 0xa4, 0x93, 0xc5, 0x06, 0xca, 0x9a, 0x27, 0x9d, + 0x87, 0xf3, 0xde, 0xca, 0xe5, 0xe7, 0xf6, 0x1c, 0x01, 0x65, + 0x5b, 0xfb, 0x19, 0x79, 0x6e, 0x08, 0x26, 0xc5, 0xc8, 0x28, + 0x0e, 0xb6, 0x3b, 0x07, 0x08, 0xc1, 0x02, 0x82, 0x01, 0x01, + 0x00, 0xe8, 0x1c, 0x73, 0xa6, 0xb8, 0xe0, 0x0e, 0x6d, 0x8d, + 0x1b, 0xb9, 0x53, 0xed, 0x58, 0x94, 0xe6, 0x1d, 0x60, 0x14, + 0x5c, 0x76, 0x43, 0xc4, 0x58, 0x19, 0xc4, 0x24, 0xe8, 0xbc, + 0x1b, 0x3b, 0x0b, 0x13, 0x24, 0x45, 0x54, 0x0e, 0xcc, 0x37, + 0xf0, 0xe0, 0x63, 0x7d, 0xc3, 0xf7, 0xfb, 0x81, 0x74, 0x81, + 0xc4, 0x0f, 0x1a, 0x21, 0x48, 0xaf, 0xce, 0xc1, 0xc4, 0x94, + 0x18, 0x06, 0x44, 0x8d, 0xd3, 0xd2, 0x22, 0x2d, 0x2d, 0x3e, + 0x5a, 0x31, 0xdc, 0x95, 0x8e, 0xf4, 0x41, 0xfc, 0x58, 0xc9, + 0x40, 0x92, 0x17, 0x5f, 0xe3, 0xda, 0xac, 0x9e, 0x3f, 0x1c, + 0x2a, 0x6b, 0x58, 0x5f, 0x48, 0x78, 0x20, 0xb1, 0xaf, 0x24, + 0x9b, 0x3c, 0x20, 0x8b, 0x93, 0x25, 0x9e, 0xe6, 0x6b, 0xbc, + 0x13, 0x42, 0x14, 0x6c, 0x36, 0x31, 0xff, 0x7a, 0xd1, 0xc1, + 0x1a, 0x26, 0x14, 0x7f, 0xa9, 0x76, 0xa7, 0x0c, 0xf8, 0xcc, + 0xed, 0x07, 0x6a, 0xd2, 0xdf, 0x62, 0xee, 0x0a, 0x7c, 0x84, + 0xcb, 0x49, 0x90, 0xb2, 0x03, 0x0d, 0xa2, 0x82, 0x06, 0x77, + 0xf1, 0xcd, 0x67, 0xf2, 0x47, 0x21, 0x02, 0x3f, 0x43, 0x21, + 0xf0, 0x46, 0x30, 0x62, 0x51, 0x72, 0xb1, 0xe7, 0x48, 0xc6, + 0x67, 0x12, 0xcd, 0x9e, 0xd6, 0x15, 0xe5, 0x21, 0xed, 0xfa, + 0x8f, 0x30, 0xa6, 0x41, 0xfe, 0xb6, 0xfa, 0x8f, 0x34, 0x14, + 0x19, 0xe8, 0x11, 0xf7, 0xa5, 0x77, 0x3e, 0xb7, 0xf9, 0x39, + 0x07, 0x8c, 0x67, 0x2a, 0xab, 0x7b, 0x08, 0xf8, 0xb0, 0x06, + 0xa8, 0xea, 0x2f, 0x8f, 0xfa, 0xcc, 0xcc, 0x40, 0xce, 0xf3, + 0x70, 0x4f, 0x3f, 0x7f, 0xe2, 0x0c, 0xea, 0x76, 0x4a, 0x35, + 0x4e, 0x47, 0xad, 0x2b, 0xa7, 0x97, 0x5d, 0x74, 0x43, 0x97, + 0x90, 0xd2, 0xfb, 0xd9, 0xf9, 0x96, 0x01, 0x33, 0x05, 0xed, + 0x7b, 0x03, 0x05, 0xad, 0xf8, 0x49, 0x03, 0x02, 0x82, 0x01, + 0x01, 0x00, 0xd4, 0x40, 0x17, 0x66, 0x10, 0x92, 0x95, 0xc8, + 0xec, 0x62, 0xa9, 0x7a, 0xcb, 0x93, 0x8e, 0xe6, 0x53, 0xd4, + 0x80, 0x48, 0x27, 0x4b, 0x41, 0xce, 0x61, 0xdf, 0xbf, 0x94, + 0xa4, 0x3d, 0x71, 0x03, 0x0b, 0xed, 0x25, 0x71, 0x98, 0xa4, + 0xd6, 0xd5, 0x4a, 0x57, 0xf5, 0x6c, 0x1b, 0xda, 0x21, 0x7d, + 0x35, 0x45, 0xb3, 0xf3, 0x6a, 0xd9, 0xd3, 0x43, 0xe8, 0x5c, + 0x54, 0x1c, 0x83, 0x1b, 0xb4, 0x5f, 0xf2, 0x97, 0x24, 0x2e, + 0xdc, 0x40, 0xde, 0x92, 0x23, 0x59, 0x8e, 0xbc, 0xd2, 0xa1, + 0xf2, 0xe0, 0x4c, 0xdd, 0x0b, 0xd1, 0xe7, 0xae, 0x65, 0xbc, + 0xb5, 0xf5, 0x5b, 0x98, 0xe9, 0xd7, 0xc2, 0xb7, 0x0e, 0x55, + 0x71, 0x0e, 0x3c, 0x0a, 0x24, 0x6b, 0xa6, 0xe6, 0x14, 0x61, + 0x11, 0xfd, 0x33, 0x42, 0x99, 0x2b, 0x84, 0x77, 0x74, 0x92, + 0x91, 0xf5, 0x79, 0x79, 0xcf, 0xad, 0x8e, 0x04, 0xef, 0x80, + 0x1e, 0x57, 0xf4, 0x14, 0xf5, 0x35, 0x09, 0x74, 0xb2, 0x13, + 0x71, 0x58, 0x6b, 0xea, 0x32, 0x5d, 0xf3, 0xd3, 0x76, 0x48, + 0x39, 0x10, 0x23, 0x84, 0x9d, 0xbe, 0x92, 0x77, 0x4a, 0xed, + 0x70, 0x3e, 0x1a, 0xa2, 0x6c, 0xb3, 0x81, 0x00, 0xc3, 0xc9, + 0xe4, 0x52, 0xc8, 0x24, 0x88, 0x0c, 0x41, 0xad, 0x87, 0x5a, + 0xea, 0xa3, 0x7a, 0x85, 0x1c, 0x5e, 0x31, 0x7f, 0xc3, 0x35, + 0xc6, 0xfa, 0x10, 0xc8, 0x75, 0x10, 0xc4, 0x96, 0x99, 0xe7, + 0xfe, 0x01, 0xb4, 0x74, 0xdb, 0xb4, 0x11, 0xc3, 0xc8, 0x8c, + 0xf6, 0xf7, 0x3b, 0x66, 0x50, 0xfc, 0xdb, 0xeb, 0xca, 0x47, + 0x85, 0x89, 0xe1, 0x65, 0xd9, 0x62, 0x34, 0x3c, 0x70, 0xd8, + 0x2e, 0xb4, 0x2f, 0x65, 0x3c, 0x4a, 0xa6, 0x2a, 0xe7, 0xc7, + 0xd8, 0x41, 0x8f, 0x8a, 0x43, 0xbf, 0x42, 0xf2, 0x4d, 0xbc, + 0xfc, 0x9e, 0x27, 0x95, 0xfb, 0x75, 0xff, 0xab, 0x02, 0x82, + 0x01, 0x00, 0x41, 0x2f, 0x44, 0x57, 0x6d, 0x12, 0x17, 0x5b, + 0x32, 0xc6, 0xb7, 0x6c, 0x57, 0x7a, 0x8a, 0x0e, 0x79, 0xef, + 0x72, 0xa8, 0x68, 0xda, 0x2d, 0x38, 0xe4, 0xbb, 0x8d, 0xf6, + 0x02, 0x65, 0xcf, 0x56, 0x13, 0xe1, 0x1a, 0xcb, 0x39, 0x80, + 0xa6, 0xb1, 0x32, 0x03, 0x1e, 0xdd, 0xbb, 0x35, 0xd9, 0xac, + 0x43, 0x89, 0x31, 0x08, 0x90, 0x92, 0x5e, 0x35, 0x3d, 0x7b, + 0x9c, 0x6f, 0x86, 0xcb, 0x17, 0xdd, 0x85, 0xe4, 0xed, 0x35, + 0x08, 0x8e, 0xc1, 0xf4, 0x05, 0xd8, 0x68, 0xc6, 0x63, 0x3c, + 0xf7, 0xff, 0xf7, 0x47, 0x33, 0x39, 0xc5, 0x3e, 0xb7, 0x0e, + 0x58, 0x35, 0x9d, 0x81, 0xea, 0xf8, 0x6a, 0x2c, 0x1c, 0x5a, + 0x68, 0x78, 0x64, 0x11, 0x6b, 0xc1, 0x3e, 0x4e, 0x7a, 0xbd, + 0x84, 0xcb, 0x0f, 0xc2, 0xb6, 0x85, 0x1d, 0xd3, 0x76, 0xc5, + 0x93, 0x6a, 0x69, 0x89, 0x56, 0x34, 0xdc, 0x4a, 0x9b, 0xbc, + 0xff, 0xa8, 0x0d, 0x6e, 0x35, 0x9c, 0x60, 0xa7, 0x23, 0x30, + 0xc7, 0x06, 0x64, 0x39, 0x8b, 0x94, 0x89, 0xee, 0xba, 0x7f, + 0x60, 0x8d, 0xfa, 0xb6, 0x97, 0x76, 0xdc, 0x51, 0x4a, 0x3c, + 0xeb, 0x3a, 0x14, 0x2c, 0x20, 0x60, 0x69, 0x4a, 0x86, 0xfe, + 0x8c, 0x21, 0x84, 0x49, 0x54, 0xb3, 0x20, 0xe1, 0x01, 0x7f, + 0x58, 0xdf, 0x7f, 0xb5, 0x21, 0x51, 0x8c, 0x47, 0x9f, 0x91, + 0xeb, 0x97, 0x3e, 0xf2, 0x54, 0xcf, 0x16, 0x46, 0xf9, 0xd9, + 0xb6, 0xe7, 0x64, 0xc9, 0xd0, 0x54, 0xea, 0x2f, 0xa1, 0xcf, + 0xa5, 0x7f, 0x28, 0x8d, 0x84, 0xec, 0xd5, 0x39, 0x03, 0x76, + 0x5b, 0x2d, 0x8e, 0x43, 0xf2, 0x01, 0x24, 0xc9, 0x6f, 0xc0, + 0xf5, 0x69, 0x6f, 0x7d, 0xb5, 0x85, 0xd2, 0x5f, 0x7f, 0x78, + 0x40, 0x07, 0x7f, 0x09, 0x15, 0xb5, 0x1f, 0x28, 0x65, 0x10, + 0xe4, 0x19, 0xa8, 0xc6, 0x9e, 0x8d, 0xdc, 0xcb, 0x02, 0x82, + 0x01, 0x00, 0x13, 0x01, 0xee, 0x56, 0x80, 0x93, 0x70, 0x00, + 0x7f, 0x52, 0xd2, 0x94, 0xa1, 0x98, 0x84, 0x4a, 0x92, 0x25, + 0x4c, 0x9b, 0xa9, 0x91, 0x2e, 0xc2, 0x79, 0xb7, 0x5c, 0xe3, + 0xc5, 0xd5, 0x8e, 0xc2, 0x54, 0x16, 0x17, 0xad, 0x55, 0x9b, + 0x25, 0x76, 0x12, 0x63, 0x50, 0x22, 0x2f, 0x58, 0x58, 0x79, + 0x6b, 0x04, 0xe3, 0xf9, 0x9f, 0x8f, 0x04, 0x41, 0x67, 0x94, + 0xa5, 0x1f, 0xac, 0x8a, 0x15, 0x9c, 0x26, 0x10, 0x6c, 0xf8, + 0x19, 0x57, 0x61, 0xd7, 0x3a, 0x7d, 0x31, 0xb0, 0x2d, 0x38, + 0xbd, 0x94, 0x62, 0xad, 0xc4, 0xfa, 0x36, 0x42, 0x42, 0xf0, + 0x24, 0x67, 0x65, 0x9d, 0x8b, 0x0b, 0x7c, 0x6f, 0x82, 0x44, + 0x1a, 0x8c, 0xc8, 0xc9, 0xab, 0xbb, 0x4c, 0x45, 0xfc, 0x7b, + 0x38, 0xee, 0x30, 0xe1, 0xfc, 0xef, 0x8d, 0xbc, 0x58, 0xdf, + 0x2b, 0x5d, 0x0d, 0x54, 0xe0, 0x49, 0x4d, 0x97, 0x99, 0x8f, + 0x22, 0xa8, 0x83, 0xbe, 0x40, 0xbb, 0x50, 0x2e, 0x78, 0x28, + 0x0f, 0x95, 0x78, 0x8c, 0x8f, 0x98, 0x24, 0x56, 0xc2, 0x97, + 0xf3, 0x2c, 0x43, 0xd2, 0x03, 0x82, 0x66, 0x81, 0x72, 0x5f, + 0x53, 0x16, 0xec, 0xb1, 0xb1, 0x04, 0x5e, 0x40, 0x20, 0x48, + 0x7b, 0x3f, 0x02, 0x97, 0x6a, 0xeb, 0x96, 0x12, 0x21, 0x35, + 0xfe, 0x1f, 0x47, 0xc0, 0x95, 0xea, 0xc5, 0x8a, 0x08, 0x84, + 0x4f, 0x5e, 0x63, 0x94, 0x60, 0x0f, 0x71, 0x5b, 0x7f, 0x4a, + 0xec, 0x4f, 0x60, 0xc6, 0xba, 0x4a, 0x24, 0xf1, 0x20, 0x8b, + 0xa7, 0x2e, 0x3a, 0xce, 0x8d, 0xe0, 0x27, 0x1d, 0xb5, 0x8e, + 0xb4, 0x21, 0xc5, 0xe2, 0xa6, 0x16, 0x0a, 0x51, 0x83, 0x55, + 0x88, 0xd1, 0x30, 0x11, 0x63, 0xd5, 0xd7, 0x8d, 0xae, 0x16, + 0x12, 0x82, 0xc4, 0x85, 0x00, 0x4e, 0x27, 0x83, 0xa5, 0x7c, + 0x90, 0x2e, 0xe5, 0xa2, 0xa3, 0xd3, 0x4c, 0x63, 0x02, 0x82, + 0x01, 0x01, 0x00, 0x86, 0x08, 0x98, 0x98, 0xa5, 0x00, 0x05, + 0x39, 0x77, 0xd9, 0x66, 0xb3, 0xcf, 0xca, 0xa0, 0x71, 0xb3, + 0x50, 0xce, 0x3d, 0xb1, 0x93, 0x95, 0x35, 0xc4, 0xd4, 0x2e, + 0x90, 0xdf, 0x0f, 0xfc, 0x60, 0xc1, 0x94, 0x68, 0x61, 0x43, + 0xca, 0x9a, 0x23, 0x4a, 0x1e, 0x45, 0x72, 0x99, 0xb5, 0x1e, + 0x61, 0x8d, 0x77, 0x0f, 0xa0, 0xbb, 0xd7, 0x77, 0xb4, 0x2a, + 0x15, 0x11, 0x88, 0x2d, 0xb3, 0x56, 0x61, 0x5e, 0x6a, 0xed, + 0xa4, 0x46, 0x4a, 0x3f, 0x50, 0x11, 0xd6, 0xba, 0xb6, 0xd7, + 0x95, 0x65, 0x53, 0xc3, 0xa1, 0x8f, 0xe0, 0xa3, 0xf5, 0x1c, + 0xfd, 0xaf, 0x6e, 0x43, 0xd7, 0x17, 0xa7, 0xd3, 0x81, 0x1b, + 0xa4, 0xdf, 0xe0, 0x97, 0x8a, 0x46, 0x03, 0xd3, 0x46, 0x0e, + 0x83, 0x48, 0x4e, 0xd2, 0x02, 0xcb, 0xc0, 0xad, 0x79, 0x95, + 0x8c, 0x96, 0xba, 0x40, 0x34, 0x11, 0x71, 0x5e, 0xe9, 0x11, + 0xf9, 0xc5, 0x4a, 0x5e, 0x91, 0x9d, 0xf5, 0x92, 0x4f, 0xeb, + 0xc6, 0x70, 0x02, 0x2d, 0x3d, 0x04, 0xaa, 0xe9, 0x3a, 0x8e, + 0xd5, 0xa8, 0xad, 0xf7, 0xce, 0x0d, 0x16, 0xb2, 0xec, 0x0a, + 0x9c, 0xf5, 0x94, 0x39, 0xb9, 0x8a, 0xfc, 0x1e, 0xf9, 0xcc, + 0xf2, 0x5f, 0x21, 0x31, 0x74, 0x72, 0x6b, 0x64, 0xae, 0x35, + 0x61, 0x8d, 0x0d, 0xcb, 0xe7, 0xda, 0x39, 0xca, 0xf3, 0x21, + 0x66, 0x0b, 0x95, 0xd7, 0x0a, 0x7c, 0xca, 0xa1, 0xa9, 0x5a, + 0xe8, 0xac, 0xe0, 0x71, 0x54, 0xaf, 0x28, 0xcf, 0xd5, 0x70, + 0x89, 0xe0, 0xf3, 0x9e, 0x43, 0x6c, 0x8d, 0x7b, 0x99, 0x01, + 0x68, 0x4d, 0xa1, 0x45, 0x46, 0x0c, 0x43, 0xbc, 0xcc, 0x2c, + 0xdd, 0xc5, 0x46, 0xc8, 0x4e, 0x0e, 0xbe, 0xed, 0xb9, 0x26, + 0xab, 0x2e, 0xdb, 0xeb, 0x8f, 0xff, 0xdb, 0xb0, 0xc6, 0x55, + 0xaf, 0xf8, 0x2a, 0x91, 0x9d, 0x50, 0x44, 0x21, 0x17, +}; + +static unsigned char test7680[] = { + 0x30, 0x82, 0x11, 0x09, 0x02, 0x01, 0x00, 0x02, 0x82, 0x03, + 0xc1, 0x00, 0xe3, 0x27, 0x46, 0x99, 0xb5, 0x17, 0xab, 0xfa, + 0x65, 0x05, 0x7a, 0x06, 0x81, 0x14, 0xce, 0x43, 0x21, 0x49, + 0x0f, 0x08, 0xf1, 0x70, 0xb4, 0xc1, 0x10, 0xd1, 0x87, 0xf8, + 0x29, 0x91, 0x36, 0x66, 0x2d, 0xbe, 0x7b, 0x1d, 0xa2, 0x0b, + 0x20, 0x38, 0xd9, 0x8e, 0x78, 0x27, 0xcf, 0xb5, 0x45, 0x58, + 0x3d, 0xf4, 0xda, 0xf0, 0xdc, 0x21, 0x17, 0x52, 0xcd, 0x68, + 0xe2, 0x81, 0xac, 0x88, 0x61, 0x10, 0xbc, 0xb0, 0x7f, 0xe4, + 0xf3, 0x78, 0xb7, 0x28, 0x6c, 0x5f, 0x5c, 0xc2, 0x8d, 0x3d, + 0xb0, 0x87, 0x41, 0x15, 0x2e, 0x09, 0x5f, 0xea, 0x06, 0x7f, + 0xe9, 0x35, 0x18, 0x90, 0x50, 0xad, 0xf6, 0xb9, 0xfd, 0x33, + 0x02, 0x1a, 0x99, 0x9e, 0xa5, 0x7d, 0x2c, 0x3b, 0x24, 0xe7, + 0x31, 0x35, 0x73, 0x9a, 0xb0, 0xfe, 0x03, 0xfc, 0xc6, 0x98, + 0x78, 0xd9, 0x66, 0x95, 0xa5, 0x12, 0xbc, 0x1e, 0x82, 0xbc, + 0xf1, 0xc5, 0x31, 0xcd, 0xa6, 0xb1, 0x0c, 0x02, 0xbf, 0x7f, + 0xb7, 0xaf, 0x5f, 0xd6, 0xed, 0xf7, 0xc1, 0x59, 0x86, 0x3a, + 0x35, 0x95, 0x54, 0x21, 0x8d, 0x6a, 0xb3, 0xd1, 0x2b, 0x71, + 0xf5, 0xf1, 0x66, 0x00, 0xb1, 0x88, 0xee, 0x3b, 0xa4, 0x41, + 0x52, 0x1a, 0xf5, 0x0e, 0x32, 0xb6, 0xbf, 0x52, 0xab, 0x51, + 0x55, 0x91, 0x32, 0x4f, 0xaf, 0x91, 0xac, 0xf7, 0xff, 0x8e, + 0x3b, 0x2b, 0x61, 0xe9, 0x6d, 0x1d, 0x68, 0x80, 0x90, 0x79, + 0x34, 0x96, 0xca, 0x49, 0x43, 0x7c, 0x89, 0x4e, 0x5e, 0x31, + 0xb5, 0xce, 0x01, 0x9b, 0x09, 0xaf, 0x92, 0x06, 0x24, 0xe7, + 0x22, 0x35, 0xcc, 0xa2, 0x0b, 0xfb, 0x5b, 0x87, 0x65, 0x71, + 0xff, 0x64, 0x3e, 0xf9, 0xe8, 0x33, 0xa0, 0xc3, 0x4e, 0xb2, + 0x41, 0x98, 0x54, 0xeb, 0x13, 0x99, 0xfb, 0x32, 0x78, 0x7e, + 0xda, 0x4f, 0xd3, 0x46, 0x6a, 0xb5, 0x78, 0x81, 0x3f, 0x04, + 0x13, 0x5f, 0x67, 0xaf, 0x88, 0xa5, 0x9e, 0x0d, 0xc5, 0xf3, + 0xe7, 0x4c, 0x51, 0xf5, 0x51, 0x4a, 0xa4, 0x58, 0x64, 0xd9, + 0xa2, 0x32, 0x54, 0x36, 0xce, 0x38, 0xd8, 0xc2, 0x0e, 0x0d, + 0x60, 0x8e, 0x32, 0x7f, 0x90, 0x8a, 0xbc, 0x88, 0xbe, 0x6a, + 0xc0, 0x47, 0x0f, 0x02, 0x41, 0xff, 0x3b, 0x7e, 0xc5, 0xa6, + 0x33, 0x1d, 0x19, 0xd1, 0xd5, 0x67, 0x6c, 0xbf, 0x16, 0xb0, + 0x7e, 0x80, 0x10, 0xbf, 0x7f, 0xdd, 0xd0, 0xf4, 0xc3, 0x94, + 0x2c, 0x9a, 0x2c, 0xda, 0x69, 0x4e, 0xd6, 0x7b, 0x40, 0x4d, + 0x2a, 0x27, 0xcb, 0x5a, 0xe5, 0x2d, 0x3f, 0x7d, 0x51, 0x9d, + 0x9f, 0x70, 0xde, 0x50, 0xb1, 0xd3, 0xd2, 0x38, 0x4d, 0x1c, + 0xca, 0xc2, 0x1e, 0x80, 0xd0, 0x36, 0x82, 0x04, 0xe6, 0x17, + 0x79, 0x9f, 0x2e, 0xc9, 0xed, 0x2b, 0xd5, 0x1b, 0xfa, 0x7d, + 0x1a, 0x80, 0xb5, 0x0e, 0x2f, 0x05, 0xbe, 0x4a, 0x1b, 0xfe, + 0x0a, 0xad, 0x01, 0xde, 0x91, 0xc8, 0xf9, 0x81, 0xbe, 0xc7, + 0xaf, 0xe7, 0x87, 0xed, 0x9d, 0xb8, 0x6c, 0xad, 0x65, 0xed, + 0x5e, 0xd3, 0x67, 0x8c, 0x62, 0x3a, 0xe7, 0xfd, 0x67, 0xe0, + 0xbb, 0x57, 0xaf, 0x56, 0xeb, 0x4a, 0x58, 0x6e, 0xad, 0xf2, + 0xbe, 0xc3, 0x70, 0x29, 0xf8, 0xeb, 0x68, 0x45, 0xa0, 0xbd, + 0xcd, 0xa5, 0xb4, 0xd9, 0x01, 0xb7, 0x44, 0xeb, 0x97, 0xf3, + 0x0c, 0x56, 0xe4, 0x26, 0xd0, 0xa5, 0xb1, 0xa3, 0x49, 0x6e, + 0x88, 0xf2, 0x22, 0xe2, 0x7b, 0x58, 0x3a, 0xd9, 0x52, 0xa4, + 0xb1, 0x4c, 0x5c, 0x7c, 0xf0, 0x88, 0x7b, 0x9f, 0x06, 0xe9, + 0x32, 0x4e, 0xf2, 0x64, 0x83, 0x8b, 0xa2, 0xea, 0x1d, 0x25, + 0xf1, 0x8d, 0x16, 0x8b, 0xe0, 0xab, 0xd2, 0xe9, 0xe4, 0x6b, + 0x7d, 0x76, 0x98, 0x22, 0x53, 0x31, 0x6b, 0xcc, 0xf1, 0xe5, + 0x1d, 0xd7, 0xa5, 0xb0, 0xea, 0x6b, 0x38, 0x14, 0x0c, 0x06, + 0x10, 0x27, 0xd8, 0x33, 0xf3, 0x9a, 0xae, 0x94, 0xdd, 0x0b, + 0xb4, 0x6d, 0xe5, 0x91, 0xdd, 0xf1, 0x0f, 0x27, 0xa4, 0x94, + 0x55, 0xf0, 0xde, 0x07, 0x29, 0xe6, 0x3f, 0x26, 0x19, 0xa1, + 0xdd, 0xd1, 0x06, 0x99, 0xda, 0x54, 0x23, 0x3c, 0xf5, 0x5c, + 0x2e, 0x96, 0xa9, 0x21, 0x23, 0x25, 0x2e, 0x6f, 0xf1, 0xf9, + 0x11, 0x54, 0xe5, 0x7b, 0xb9, 0x1f, 0x11, 0xe2, 0x9e, 0x6b, + 0x61, 0x8b, 0xa3, 0x8b, 0xc1, 0x20, 0x9b, 0xfb, 0x51, 0xef, + 0xbb, 0xb9, 0xf6, 0xaf, 0x66, 0xb3, 0x2c, 0x25, 0xef, 0x76, + 0xcb, 0xbf, 0x7a, 0x93, 0x2f, 0xe1, 0x17, 0x56, 0xc1, 0x00, + 0x33, 0xb5, 0xd9, 0x91, 0x05, 0x31, 0xcc, 0x72, 0xcd, 0x4a, + 0x93, 0x9a, 0xe3, 0x21, 0x42, 0x9e, 0xb8, 0x4e, 0x6c, 0x27, + 0x93, 0xf0, 0x7f, 0x22, 0xdb, 0xe5, 0xb3, 0xa3, 0xf7, 0xe7, + 0x80, 0xbb, 0x91, 0xca, 0xf7, 0xe8, 0x52, 0xb8, 0x11, 0x64, + 0x66, 0x25, 0x94, 0xf8, 0x6f, 0x0b, 0x3b, 0xb7, 0xff, 0x80, + 0x9e, 0x36, 0xe9, 0x88, 0x2e, 0xab, 0x05, 0xbf, 0x99, 0x9f, + 0x2b, 0x4f, 0xc6, 0xb1, 0x13, 0x5b, 0x06, 0xff, 0x0a, 0x7b, + 0xbc, 0x7f, 0x07, 0xa0, 0x35, 0xc2, 0x2d, 0x44, 0x3e, 0xad, + 0x44, 0xcb, 0x47, 0x18, 0x26, 0x71, 0x7b, 0x17, 0xc9, 0x6d, + 0xb5, 0x4b, 0xcf, 0xdf, 0x14, 0x2c, 0x6c, 0xdf, 0x21, 0xce, + 0x93, 0x49, 0x34, 0x69, 0x49, 0xfd, 0x3e, 0x71, 0x5b, 0xfa, + 0x07, 0xc5, 0x7e, 0x5e, 0x54, 0x1a, 0x3c, 0xa6, 0x29, 0xb5, + 0xbf, 0x0d, 0xf1, 0xc6, 0xa4, 0x61, 0xd6, 0x17, 0x1d, 0xf0, + 0xa2, 0x78, 0x8f, 0xbc, 0x7e, 0x0c, 0xb4, 0xf0, 0x1e, 0x05, + 0xea, 0xb5, 0xad, 0x68, 0x95, 0x0b, 0x27, 0xb4, 0x29, 0x7c, + 0x70, 0x2a, 0x9a, 0x0a, 0x39, 0xd4, 0x76, 0xb7, 0x72, 0x30, + 0x5e, 0xae, 0x9c, 0x4a, 0x55, 0xc7, 0x46, 0xd7, 0x5f, 0xbe, + 0x10, 0x61, 0x25, 0x18, 0x7a, 0x9f, 0xd3, 0x05, 0x3d, 0x6f, + 0x9a, 0x1e, 0xec, 0x2b, 0x03, 0xe0, 0x49, 0x6a, 0x9c, 0xd6, + 0xdb, 0xc2, 0xa1, 0xe1, 0x0a, 0xbb, 0x31, 0x42, 0xc8, 0x43, + 0x4e, 0x7c, 0xa9, 0x7c, 0x60, 0xea, 0xbe, 0xf1, 0x8b, 0xe8, + 0xb2, 0x90, 0x83, 0x14, 0x21, 0xe4, 0xb3, 0x0d, 0x7c, 0x63, + 0x3c, 0x98, 0x55, 0xc6, 0x44, 0xa6, 0xa8, 0x1e, 0x42, 0xb7, + 0x89, 0xa8, 0xbd, 0xb8, 0x34, 0x3d, 0x09, 0x80, 0x99, 0x73, + 0x9f, 0xaf, 0x17, 0x56, 0xf2, 0x73, 0x3e, 0x1e, 0x6e, 0xe9, + 0x18, 0xa0, 0x5b, 0x69, 0xce, 0xfd, 0x3d, 0x77, 0x81, 0x95, + 0x3b, 0xf1, 0xde, 0x26, 0xe9, 0x27, 0xef, 0x92, 0x2a, 0x97, + 0xdc, 0x95, 0xa5, 0xa3, 0xb0, 0xfb, 0x96, 0x89, 0x4f, 0xe6, + 0xc1, 0x42, 0x0b, 0xfd, 0xb4, 0x6d, 0x0a, 0x9f, 0x9b, 0x31, + 0xd8, 0x21, 0x38, 0x8a, 0xee, 0xb6, 0x5c, 0x12, 0xa8, 0xb4, + 0x07, 0x79, 0x41, 0xa7, 0x7f, 0x13, 0x74, 0xad, 0x0b, 0xee, + 0x28, 0x52, 0xac, 0x2f, 0x4d, 0x30, 0x1c, 0xc5, 0xa6, 0xa5, + 0x61, 0x42, 0xbd, 0xe1, 0x4f, 0xd3, 0xec, 0x66, 0xf2, 0x63, + 0xf4, 0x93, 0xdb, 0x35, 0x2d, 0x3b, 0x71, 0x25, 0x09, 0xde, + 0xda, 0x46, 0xda, 0xe2, 0xa7, 0xa3, 0xdf, 0xcd, 0xbf, 0x58, + 0x05, 0x25, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x03, + 0xc0, 0x5f, 0xd5, 0x15, 0x1b, 0x09, 0xe4, 0xa7, 0xc0, 0xa6, + 0xd8, 0x0d, 0xa8, 0x2a, 0xd3, 0x1d, 0x46, 0x03, 0x07, 0xf0, + 0x98, 0xe4, 0x4b, 0x99, 0x66, 0x8e, 0x72, 0xe7, 0xbb, 0x51, + 0xc6, 0x1a, 0xbe, 0x36, 0xf4, 0x52, 0xba, 0xa8, 0xbf, 0xaa, + 0xe3, 0x71, 0x1d, 0x83, 0x21, 0xc0, 0xa6, 0x88, 0x4f, 0xf7, + 0x2b, 0x93, 0x26, 0xe4, 0xa7, 0xed, 0x50, 0x18, 0xaa, 0xf4, + 0x4c, 0xa2, 0xfe, 0x92, 0x7c, 0xde, 0x2e, 0x54, 0x76, 0xc2, + 0x25, 0x1e, 0x98, 0xa6, 0x48, 0x01, 0x39, 0x6f, 0x1f, 0x24, + 0x97, 0x9b, 0x64, 0x95, 0x1c, 0x8d, 0x63, 0x8d, 0x44, 0x6f, + 0x9d, 0xdf, 0xf4, 0x1a, 0xa5, 0x9a, 0x1e, 0xd3, 0x6c, 0xae, + 0xa9, 0x8c, 0x3f, 0xfb, 0x2f, 0x78, 0xf6, 0xa6, 0xd6, 0x06, + 0xd3, 0xb7, 0x26, 0xff, 0x1e, 0xdb, 0x8d, 0xcc, 0x37, 0x4d, + 0x5c, 0xe2, 0xc3, 0xa5, 0x75, 0xe6, 0xf9, 0xb4, 0x4c, 0x84, + 0x6f, 0x9e, 0x58, 0x55, 0xc8, 0x01, 0xfa, 0x32, 0xd2, 0x6e, + 0x2b, 0x45, 0xf2, 0xc6, 0x48, 0xad, 0x40, 0xd8, 0xb9, 0x3c, + 0x1b, 0xf8, 0xf7, 0x82, 0xd3, 0x0e, 0x73, 0xe3, 0xb1, 0x5b, + 0x82, 0x71, 0x77, 0x3f, 0x6f, 0x36, 0x9a, 0xe0, 0xec, 0x51, + 0xf8, 0x5f, 0x84, 0x92, 0xee, 0xb8, 0x7e, 0xe7, 0x1a, 0x14, + 0x50, 0x82, 0x7a, 0x4d, 0xe6, 0xd6, 0xa3, 0x76, 0x24, 0x8a, + 0x5f, 0xfe, 0x19, 0xdd, 0xd7, 0xf7, 0x5b, 0xae, 0x18, 0x04, + 0x90, 0xcd, 0x5c, 0xe5, 0x64, 0xe8, 0x04, 0xb1, 0x06, 0xa5, + 0xdd, 0xf8, 0x9d, 0x71, 0x13, 0xaa, 0x36, 0x7f, 0x61, 0x27, + 0xf4, 0xac, 0x95, 0x7d, 0x1a, 0x99, 0x7d, 0xe0, 0xd5, 0x9c, + 0x5a, 0xad, 0x9a, 0xff, 0x54, 0xb0, 0xb1, 0x55, 0x45, 0x2d, + 0x19, 0x58, 0x52, 0x28, 0xdd, 0xe0, 0xb5, 0x65, 0x52, 0x97, + 0x45, 0xf0, 0x2b, 0x98, 0x1f, 0x61, 0x6c, 0x9d, 0xaa, 0x59, + 0x85, 0xf9, 0x97, 0x7b, 0xbd, 0xeb, 0x95, 0x81, 0xfb, 0x29, + 0x8c, 0xf0, 0x52, 0xdf, 0xed, 0xee, 0xb2, 0x00, 0x32, 0x35, + 0x14, 0xa8, 0xa4, 0xca, 0x91, 0xff, 0x18, 0xb7, 0x96, 0xfb, + 0x32, 0x62, 0xa9, 0xa0, 0xd0, 0x77, 0x43, 0xf5, 0x99, 0xd1, + 0xee, 0xe8, 0xad, 0x1a, 0x2c, 0xd4, 0xeb, 0xe1, 0xf5, 0x01, + 0x41, 0x78, 0xc0, 0x27, 0x19, 0x50, 0x2e, 0xba, 0x22, 0xd1, + 0xeb, 0xb3, 0xa5, 0x27, 0x0b, 0xec, 0xf9, 0x26, 0x7e, 0x1f, + 0xe7, 0x17, 0x9f, 0x39, 0xa8, 0x72, 0x22, 0x63, 0x79, 0x6a, + 0x9c, 0x89, 0x55, 0x9a, 0xb4, 0x61, 0x41, 0xbc, 0xaa, 0x14, + 0x37, 0x29, 0x03, 0xc0, 0x52, 0x4e, 0x31, 0x44, 0x8f, 0x2e, + 0x17, 0x81, 0x88, 0xf4, 0xce, 0xda, 0x41, 0xb8, 0xd5, 0x14, + 0x91, 0x8c, 0xca, 0xd2, 0x0d, 0x99, 0x06, 0x09, 0xc2, 0xb7, + 0xe8, 0xae, 0xfa, 0x01, 0xea, 0x99, 0x62, 0x68, 0xb6, 0xdf, + 0xc8, 0x27, 0xae, 0xbf, 0xb0, 0x9b, 0x5b, 0x1a, 0xa2, 0xe2, + 0x5a, 0x7a, 0xe5, 0x4b, 0x92, 0x1f, 0xff, 0x73, 0xae, 0x16, + 0x40, 0x78, 0x42, 0x28, 0xbb, 0x13, 0x5e, 0xbc, 0x71, 0x7a, + 0x78, 0x3e, 0xd8, 0x1b, 0xc2, 0x2c, 0xd6, 0xdc, 0xfa, 0x39, + 0x72, 0xf8, 0xa2, 0x2c, 0x8b, 0x1c, 0x5d, 0xab, 0xb8, 0x07, + 0xc7, 0xae, 0x29, 0x93, 0x68, 0xbf, 0x61, 0xe9, 0xa4, 0x37, + 0x83, 0x7d, 0x13, 0xc7, 0x18, 0xf0, 0x7d, 0xa4, 0x20, 0x47, + 0x14, 0x68, 0x95, 0x46, 0x56, 0x6d, 0xd5, 0x7b, 0xe1, 0x51, + 0x8f, 0x96, 0xc1, 0x7b, 0x35, 0x09, 0x7a, 0x89, 0x0e, 0xdf, + 0x12, 0xd5, 0xe1, 0x9c, 0x2a, 0x94, 0x95, 0x43, 0x93, 0x48, + 0xa6, 0x23, 0xe6, 0xd8, 0xf2, 0xb8, 0x0e, 0xba, 0x6d, 0x61, + 0x03, 0xaf, 0x40, 0x63, 0x2b, 0x2f, 0xee, 0x61, 0x4c, 0xc4, + 0x70, 0x3d, 0x78, 0xc1, 0x4f, 0x8e, 0x0b, 0x9b, 0x06, 0x35, + 0x6d, 0x6d, 0x83, 0x37, 0xbb, 0x39, 0x7d, 0x7f, 0x33, 0x93, + 0xc4, 0xeb, 0x8e, 0xfc, 0xda, 0xf0, 0x54, 0xfe, 0x1d, 0xc4, + 0xd3, 0x83, 0x99, 0xdf, 0x65, 0xee, 0x00, 0x7d, 0x86, 0x27, + 0xd4, 0x3a, 0x6b, 0xe6, 0x82, 0x8e, 0x58, 0x2d, 0x03, 0x38, + 0xef, 0x6c, 0x82, 0x87, 0x18, 0x3b, 0x47, 0xe7, 0xbc, 0xe1, + 0x58, 0x70, 0x4d, 0x46, 0x96, 0x34, 0x60, 0x96, 0x15, 0x09, + 0x3c, 0x84, 0x40, 0xaf, 0x80, 0x32, 0x75, 0xc7, 0x23, 0x6c, + 0xfb, 0x1d, 0x57, 0x73, 0x19, 0x09, 0xe8, 0x1a, 0x4c, 0x02, + 0x5c, 0x7e, 0x4e, 0xbe, 0x75, 0xf8, 0x73, 0xff, 0x2d, 0x54, + 0x19, 0x55, 0xf5, 0xf4, 0x1b, 0xc9, 0xbc, 0xc2, 0x19, 0xcb, + 0xb7, 0x4e, 0x6a, 0x0d, 0xff, 0xca, 0x7d, 0xd0, 0x88, 0x91, + 0x8b, 0x9b, 0x21, 0xa4, 0xa2, 0x43, 0x0d, 0xbc, 0x9e, 0x73, + 0x7d, 0x54, 0x7d, 0x95, 0xcc, 0x63, 0x5e, 0xc1, 0xb8, 0xe6, + 0x27, 0xff, 0x20, 0x07, 0xe8, 0x6e, 0x7e, 0xf2, 0x0f, 0x5a, + 0x09, 0xef, 0xe5, 0x4d, 0x80, 0x39, 0x95, 0xd5, 0xf4, 0xee, + 0x3b, 0xca, 0x7c, 0x73, 0xf8, 0x39, 0x5a, 0xc1, 0x1d, 0x7d, + 0x94, 0x72, 0x32, 0xad, 0x58, 0xe2, 0xfc, 0x71, 0x6e, 0x66, + 0xaa, 0xa1, 0x59, 0xd6, 0xac, 0xab, 0xbe, 0x8c, 0x53, 0x99, + 0xcd, 0xe8, 0x2d, 0xb5, 0xb3, 0x46, 0x58, 0x2e, 0x16, 0xd7, + 0x4d, 0x8b, 0x7d, 0x4a, 0xb1, 0x4c, 0x85, 0x91, 0x1b, 0x57, + 0x54, 0xf8, 0x14, 0x59, 0xdb, 0xc4, 0x2c, 0x9c, 0x08, 0x6d, + 0x3d, 0xd7, 0xf6, 0xa6, 0xe6, 0xb3, 0x2a, 0xe7, 0x29, 0x1c, + 0xab, 0xb4, 0xed, 0x13, 0x19, 0xf8, 0xb6, 0x60, 0x92, 0x44, + 0x53, 0xd4, 0xa9, 0x7e, 0xba, 0x21, 0xa2, 0xdc, 0x6e, 0xa5, + 0x5e, 0x53, 0x59, 0x3c, 0x52, 0x61, 0x7b, 0x5f, 0x19, 0xad, + 0xc8, 0x6d, 0x68, 0x8d, 0x7a, 0xc9, 0xd6, 0xef, 0xeb, 0x67, + 0x4f, 0xca, 0xe7, 0xf6, 0x29, 0x36, 0x97, 0xfb, 0x3e, 0x37, + 0x95, 0x85, 0x71, 0x70, 0xf6, 0x63, 0x86, 0x2a, 0x29, 0xd7, + 0x9a, 0x96, 0x76, 0xa7, 0x47, 0x98, 0x4e, 0x06, 0x31, 0xaf, + 0xf3, 0x4f, 0x2a, 0x65, 0x90, 0x6a, 0x4b, 0x8e, 0x43, 0x79, + 0xe2, 0xdd, 0xce, 0x08, 0x1c, 0x01, 0xec, 0x38, 0x41, 0xdd, + 0x19, 0xd8, 0xf3, 0x36, 0x03, 0x35, 0x03, 0xaf, 0x1c, 0x45, + 0x3c, 0xac, 0x13, 0xaa, 0x36, 0x16, 0x48, 0x77, 0xb3, 0xbe, + 0xa3, 0xb3, 0x9d, 0x7f, 0x20, 0xca, 0x74, 0x65, 0xac, 0x93, + 0xa7, 0x54, 0xad, 0xc8, 0x68, 0x0e, 0xf8, 0x44, 0x1f, 0xad, + 0x2c, 0xb7, 0x9a, 0x9a, 0x07, 0xe5, 0xcd, 0x87, 0xe0, 0x14, + 0xb5, 0xaf, 0xd3, 0xd7, 0xcf, 0x13, 0x9f, 0x3b, 0xbd, 0xfe, + 0x29, 0x0b, 0x72, 0xf5, 0x4c, 0x54, 0x94, 0xc7, 0x66, 0xec, + 0xa8, 0x41, 0x96, 0x3d, 0x17, 0xed, 0x19, 0xc0, 0x82, 0x3e, + 0x5f, 0x9a, 0x91, 0xfe, 0xd1, 0x2f, 0xb8, 0x94, 0xaa, 0x58, + 0x68, 0x95, 0x31, 0x87, 0x57, 0x9a, 0x75, 0x94, 0x4d, 0x38, + 0x7d, 0x56, 0x82, 0x81, 0x9c, 0xb9, 0x34, 0x2b, 0xe7, 0x40, + 0xd9, 0x3c, 0x77, 0x5b, 0x95, 0x51, 0x06, 0x11, 0x41, 0xe3, + 0x8b, 0xb7, 0x32, 0xeb, 0xe1, 0x05, 0x1b, 0x10, 0xa8, 0x0e, + 0xa1, 0x02, 0x82, 0x01, 0xe1, 0x00, 0xfa, 0x38, 0x34, 0xfe, + 0x55, 0x87, 0x71, 0x62, 0x47, 0x00, 0x33, 0x64, 0x67, 0x70, + 0x79, 0x76, 0xdf, 0xfe, 0xc3, 0x28, 0x38, 0xdf, 0x90, 0xd4, + 0xc0, 0xee, 0x98, 0xbf, 0x9d, 0x9b, 0x85, 0xd8, 0x61, 0x65, + 0xa5, 0x70, 0xf5, 0xd2, 0x2c, 0xbf, 0x2f, 0xb5, 0x55, 0x79, + 0x92, 0x13, 0xba, 0x4d, 0x3c, 0x39, 0xbf, 0xd5, 0x31, 0x13, + 0x7a, 0x31, 0xf4, 0x8b, 0xce, 0xf8, 0xd0, 0xd3, 0x9b, 0xe2, + 0xee, 0x31, 0xdb, 0xba, 0xcc, 0x1a, 0xba, 0x1c, 0x8d, 0xee, + 0xea, 0xcb, 0xd3, 0x5a, 0xad, 0x87, 0xd6, 0xf9, 0x15, 0x2f, + 0x6e, 0x00, 0x06, 0x74, 0x25, 0x8d, 0xff, 0xc8, 0xa6, 0x11, + 0x1c, 0xe8, 0x16, 0x1a, 0xde, 0x53, 0x05, 0xb9, 0x53, 0x55, + 0x28, 0x83, 0x3d, 0xbe, 0x61, 0x0c, 0xc4, 0x98, 0x7d, 0xf6, + 0xec, 0x36, 0xc3, 0xe5, 0xe7, 0x1d, 0x14, 0x64, 0xcb, 0x0d, + 0x62, 0x5d, 0x7a, 0xcd, 0x88, 0xfc, 0x66, 0x4e, 0xf9, 0x36, + 0x47, 0x95, 0x18, 0x3a, 0x48, 0x2a, 0xff, 0x62, 0x8f, 0x6c, + 0xe2, 0xc2, 0xe9, 0xd3, 0x6a, 0x45, 0x5c, 0xf5, 0x89, 0x53, + 0x5c, 0xbe, 0xcf, 0xad, 0x87, 0x22, 0x9c, 0x31, 0x48, 0xdb, + 0xd8, 0xe4, 0xe5, 0x38, 0xae, 0xc2, 0xb0, 0xd2, 0xba, 0xb7, + 0x30, 0x53, 0x2d, 0xb1, 0x35, 0xf1, 0x58, 0x0f, 0x8a, 0x06, + 0x51, 0x76, 0xb9, 0x2c, 0x32, 0xe0, 0xd1, 0xaa, 0x82, 0x34, + 0x69, 0x71, 0x1c, 0x5f, 0x35, 0xa8, 0x9d, 0x11, 0xac, 0x13, + 0xdb, 0x7b, 0xf6, 0x93, 0xe3, 0xb9, 0xbd, 0xd9, 0xb2, 0x86, + 0xff, 0x61, 0x88, 0x2b, 0x72, 0x5c, 0x84, 0xe1, 0x0c, 0x72, + 0xab, 0x44, 0xff, 0x23, 0x13, 0xaf, 0xd1, 0x5a, 0xd3, 0xea, + 0x73, 0xfe, 0xd5, 0xa4, 0x7d, 0x9e, 0x4e, 0xac, 0x03, 0x93, + 0x72, 0x14, 0x2d, 0x96, 0x6f, 0xee, 0xb4, 0xcd, 0x4e, 0xab, + 0xea, 0x71, 0x93, 0x81, 0xe0, 0x3d, 0xcd, 0x61, 0x96, 0x25, + 0x76, 0xbd, 0xc4, 0xb5, 0xdd, 0x7c, 0xf1, 0xb9, 0xe1, 0x2c, + 0x58, 0x1b, 0xa4, 0x46, 0x4b, 0x12, 0x57, 0x58, 0xaa, 0x3a, + 0xae, 0x89, 0xa3, 0xb3, 0xcf, 0x1f, 0x8d, 0x67, 0xdf, 0x6d, + 0x7e, 0x8e, 0xfa, 0xc5, 0x09, 0x73, 0x46, 0x56, 0x55, 0x90, + 0xeb, 0x77, 0x4e, 0x16, 0x4f, 0x68, 0x7b, 0x1f, 0x61, 0x23, + 0xec, 0xa9, 0x71, 0x30, 0x33, 0x25, 0xc7, 0x4e, 0x26, 0x2e, + 0x4e, 0x2b, 0xc2, 0x64, 0x5f, 0xf5, 0x8f, 0x7a, 0x4b, 0x1c, + 0x06, 0xb3, 0x91, 0xf6, 0x9b, 0x51, 0xb7, 0xb0, 0x64, 0x72, + 0x04, 0xe5, 0xfa, 0x14, 0x2f, 0xed, 0x61, 0x29, 0x03, 0x73, + 0x19, 0x15, 0x6e, 0x2c, 0x8b, 0x0e, 0xec, 0x4d, 0xf1, 0xe3, + 0x6f, 0x58, 0x7c, 0xc9, 0x48, 0x67, 0x3f, 0x51, 0xb5, 0xb7, + 0x26, 0x46, 0xa7, 0x25, 0x79, 0x55, 0xfe, 0x3a, 0x44, 0xb4, + 0x44, 0xfc, 0xb8, 0x14, 0x34, 0x47, 0xd7, 0xa3, 0x0e, 0x76, + 0xe7, 0x83, 0x9a, 0x02, 0xc3, 0xcf, 0x2b, 0xd9, 0x83, 0x93, + 0xd5, 0xee, 0x99, 0x74, 0x45, 0x62, 0x23, 0xa6, 0x02, 0xc9, + 0xc0, 0x10, 0x70, 0x0a, 0x99, 0x29, 0x0c, 0x79, 0x04, 0x4c, + 0x77, 0x21, 0x96, 0xf0, 0xa5, 0x17, 0x22, 0xbe, 0xab, 0x9b, + 0xd7, 0x42, 0xd3, 0xe9, 0xc0, 0x42, 0x44, 0x7d, 0x9d, 0xc9, + 0x3d, 0xf9, 0x36, 0x97, 0x1b, 0x75, 0x52, 0x8f, 0xe9, 0xb9, + 0x8c, 0xa7, 0x64, 0x19, 0x5b, 0x5d, 0x60, 0xb4, 0x42, 0x95, + 0xc9, 0xdb, 0x82, 0x03, 0xc6, 0xb0, 0x28, 0x72, 0x64, 0x03, + 0x41, 0x4d, 0x8f, 0xc6, 0xd0, 0xcd, 0x02, 0x82, 0x01, 0xe1, + 0x00, 0xe8, 0x66, 0xa7, 0xf9, 0x0f, 0x5a, 0x21, 0xfc, 0x88, + 0x4e, 0x91, 0xd5, 0x4a, 0xf0, 0xf4, 0x32, 0xe5, 0x0d, 0xf3, + 0x06, 0x95, 0xd0, 0x4e, 0x47, 0x0c, 0x04, 0x66, 0x77, 0xfd, + 0xb8, 0x93, 0x0d, 0xff, 0x8f, 0x97, 0xa0, 0x4a, 0x36, 0x37, + 0xa6, 0x5e, 0x95, 0x79, 0xc8, 0xb2, 0x21, 0x98, 0x81, 0xf1, + 0xb8, 0xf4, 0x52, 0xaf, 0x3c, 0x8c, 0x86, 0x85, 0x55, 0x56, + 0xfc, 0x90, 0xe3, 0x32, 0x50, 0x7c, 0x54, 0x07, 0x9e, 0xed, + 0xfc, 0xd4, 0xb9, 0x5c, 0x98, 0x22, 0xfb, 0x72, 0xd7, 0x83, + 0xf0, 0xd1, 0x61, 0x10, 0xbd, 0x68, 0x5d, 0x72, 0xc1, 0xce, + 0x92, 0x43, 0x77, 0x9f, 0xb8, 0x8d, 0x8e, 0xf2, 0xe3, 0x62, + 0x4a, 0x93, 0x03, 0xd3, 0xd9, 0x01, 0xa8, 0x99, 0x6f, 0xa3, + 0x4c, 0x6d, 0x7a, 0xf2, 0x9e, 0x8e, 0x6b, 0xbc, 0xe4, 0x9d, + 0x8e, 0xe7, 0x25, 0x86, 0xa4, 0xa9, 0xc2, 0xef, 0xdf, 0xbb, + 0x6e, 0x3d, 0x4b, 0x57, 0x95, 0x81, 0x6f, 0x68, 0x3f, 0x19, + 0xa8, 0xff, 0x5a, 0x08, 0x7a, 0xe4, 0x4c, 0x4e, 0xb4, 0xea, + 0xf4, 0xc8, 0x2f, 0xef, 0x8c, 0x5e, 0xcd, 0x62, 0x1c, 0x8c, + 0x93, 0x60, 0x5d, 0xa3, 0x11, 0x64, 0x0b, 0xeb, 0x6d, 0x21, + 0xbc, 0x3a, 0x5b, 0x5c, 0x0c, 0xa7, 0x8a, 0xc6, 0xa8, 0xe1, + 0x48, 0x81, 0x01, 0xb5, 0x65, 0xab, 0x2e, 0xbe, 0x38, 0x94, + 0xf7, 0xa6, 0x33, 0xc1, 0x6e, 0x0b, 0x88, 0x38, 0xe7, 0x1b, + 0x04, 0x9a, 0x10, 0x2d, 0x1d, 0x3f, 0x5f, 0x5f, 0xc8, 0xef, + 0xcd, 0xc5, 0x16, 0xdc, 0x84, 0xc0, 0x66, 0xe0, 0xa3, 0xfc, + 0xfa, 0x96, 0xc7, 0xb7, 0xec, 0x4f, 0x40, 0x0a, 0xc5, 0xbe, + 0x6d, 0x39, 0x4a, 0x7e, 0x91, 0x4f, 0xe1, 0x03, 0xd2, 0x39, + 0xbc, 0x87, 0x69, 0xa1, 0xf0, 0x6d, 0x11, 0xf5, 0xb4, 0x9d, + 0xae, 0x76, 0x6b, 0xc6, 0xbf, 0xe4, 0x47, 0xbc, 0x4d, 0x13, + 0x88, 0xa8, 0x83, 0xf5, 0xae, 0x1d, 0xfb, 0x4d, 0x4c, 0x44, + 0x03, 0xd8, 0xa4, 0x2e, 0x4d, 0xf8, 0x5f, 0x45, 0x94, 0x58, + 0xd7, 0xd9, 0x4b, 0x47, 0xd8, 0xfc, 0x35, 0x05, 0xed, 0xb4, + 0xb6, 0xc2, 0x36, 0x2e, 0xba, 0xd2, 0x7a, 0xba, 0x69, 0x34, + 0xbf, 0xf1, 0xa1, 0x5e, 0x17, 0x71, 0x89, 0xd3, 0x54, 0x57, + 0x05, 0x2b, 0x82, 0xe3, 0x0a, 0x64, 0x5c, 0x3b, 0x8c, 0x6b, + 0xc7, 0x10, 0x8a, 0xb5, 0xd3, 0xd7, 0x90, 0xeb, 0xdb, 0x1d, + 0xa0, 0xbf, 0x6b, 0xea, 0xcd, 0x31, 0x7a, 0x8d, 0x64, 0xcc, + 0x58, 0xc0, 0x07, 0xa4, 0x6e, 0x14, 0x0b, 0xf3, 0xea, 0x3e, + 0x87, 0x9f, 0x7c, 0xb8, 0x1c, 0x22, 0x26, 0x8a, 0x7d, 0x90, + 0xdd, 0x57, 0x28, 0x38, 0xcc, 0x0e, 0x71, 0x92, 0x89, 0xee, + 0x79, 0x88, 0xbc, 0x05, 0x21, 0xda, 0x42, 0x92, 0x52, 0x66, + 0xac, 0x4a, 0xe5, 0xf5, 0x6e, 0x47, 0xd5, 0xba, 0x37, 0xd3, + 0x7c, 0x89, 0xd4, 0xd8, 0x6f, 0xde, 0x63, 0x44, 0xb5, 0x88, + 0xdd, 0xb1, 0x30, 0xb4, 0x6d, 0xcd, 0xbf, 0xc8, 0x34, 0x27, + 0x59, 0x7d, 0x79, 0xdc, 0x96, 0x5b, 0x8e, 0xc0, 0x87, 0xc0, + 0x4e, 0x40, 0x07, 0x13, 0x91, 0x6b, 0x3a, 0x12, 0x03, 0x64, + 0x70, 0xaf, 0x80, 0x24, 0x1c, 0x5c, 0xfb, 0xf5, 0xc0, 0x74, + 0x5e, 0xaf, 0x06, 0x18, 0x04, 0x67, 0x4a, 0xbd, 0xac, 0xd7, + 0xca, 0xbe, 0x4e, 0xa1, 0x19, 0x48, 0x7d, 0xa6, 0x59, 0xf6, + 0x1a, 0x62, 0x50, 0x53, 0x46, 0xa4, 0x5b, 0x9c, 0x5a, 0xfd, + 0x89, 0x9d, 0xd4, 0xde, 0xf4, 0xa7, 0x3d, 0x88, 0x73, 0xa5, + 0xb9, 0x02, 0x82, 0x01, 0xe1, 0x00, 0xe7, 0x70, 0x59, 0xc3, + 0xed, 0xc4, 0x6b, 0xa1, 0xa5, 0x5e, 0x90, 0x2a, 0x8c, 0x6a, + 0xc2, 0x4e, 0xab, 0xfc, 0xee, 0xf2, 0x23, 0x38, 0xd6, 0xb3, + 0x93, 0x08, 0x9e, 0x0c, 0x8e, 0x71, 0x2d, 0xa9, 0xe8, 0xdc, + 0xa5, 0xdc, 0x07, 0xe3, 0xb1, 0x33, 0xdd, 0xa2, 0xf2, 0x3e, + 0x92, 0x58, 0xe0, 0xf7, 0x53, 0x7f, 0x6e, 0xea, 0x78, 0x8c, + 0x35, 0x78, 0x43, 0x63, 0x95, 0xbb, 0x1b, 0x1c, 0xbf, 0x91, + 0x75, 0x14, 0x74, 0xd3, 0x20, 0xba, 0x8f, 0xee, 0x9d, 0x71, + 0xa1, 0x87, 0x8a, 0x24, 0xd3, 0x61, 0x53, 0xfb, 0xec, 0x16, + 0x84, 0xbe, 0x4d, 0x39, 0xdd, 0x0a, 0xac, 0xce, 0x20, 0x9c, + 0xaf, 0x8a, 0x13, 0xf8, 0x22, 0x2f, 0xd4, 0x99, 0x88, 0x74, + 0xba, 0x16, 0x3a, 0x63, 0xff, 0x4c, 0x5a, 0x03, 0x5a, 0x6f, + 0xac, 0x29, 0x33, 0xa5, 0x50, 0xd1, 0xda, 0xed, 0x27, 0xcb, + 0x67, 0x72, 0x63, 0x85, 0xfc, 0xf0, 0xc8, 0x88, 0xbf, 0x85, + 0xef, 0x4b, 0xfe, 0xae, 0xd9, 0xd5, 0xbb, 0x86, 0xa4, 0x76, + 0xe8, 0x7f, 0xb4, 0xdb, 0xb1, 0xee, 0x1a, 0x7f, 0x99, 0xd7, + 0x9b, 0x6f, 0x7a, 0x94, 0x5c, 0xec, 0x2c, 0x60, 0x81, 0xad, + 0xa7, 0xbe, 0x80, 0x2e, 0x9f, 0xa6, 0xc0, 0xfb, 0x09, 0x6d, + 0x2b, 0xab, 0xa4, 0x15, 0xc7, 0x79, 0x46, 0x24, 0x89, 0x5c, + 0x32, 0xb9, 0x87, 0xa9, 0x54, 0x1e, 0x12, 0x90, 0x8e, 0x02, + 0x80, 0x8c, 0xf8, 0xdb, 0x2f, 0xbc, 0x98, 0x1b, 0xa2, 0x78, + 0x73, 0x89, 0x03, 0x97, 0xe3, 0x09, 0x08, 0x8b, 0x75, 0xcf, + 0xdc, 0x23, 0x90, 0x59, 0xef, 0x5b, 0x98, 0x24, 0xb8, 0xe8, + 0xcf, 0x75, 0xf0, 0x2f, 0xb7, 0xa3, 0xe6, 0x17, 0x06, 0xf0, + 0x52, 0xfe, 0x21, 0x0a, 0x16, 0x8e, 0xf8, 0xe1, 0xae, 0x25, + 0x11, 0x5d, 0x8c, 0x95, 0x1b, 0x4f, 0x45, 0xb8, 0xa8, 0xcd, + 0xe6, 0xf9, 0xca, 0xa0, 0x54, 0x93, 0x95, 0x86, 0x6f, 0xe4, + 0x93, 0x22, 0x0f, 0xf2, 0xcf, 0xbd, 0x23, 0xb0, 0xf4, 0x8f, + 0x99, 0xa7, 0x67, 0x99, 0x05, 0x13, 0x1f, 0xeb, 0x88, 0xf8, + 0xe2, 0x3b, 0xb9, 0x49, 0x35, 0x89, 0x4f, 0xb8, 0x06, 0x37, + 0x36, 0xda, 0x75, 0x25, 0x0f, 0x0a, 0xaa, 0xc2, 0x6c, 0x3e, + 0xb1, 0x2d, 0x16, 0xf3, 0x17, 0xdb, 0xe2, 0x16, 0x32, 0x39, + 0x92, 0x4b, 0x5f, 0xc0, 0x5f, 0x6e, 0xd0, 0x1c, 0x7e, 0xc0, + 0x51, 0xd9, 0xb3, 0xe2, 0x37, 0xc7, 0xe0, 0x40, 0x13, 0x7d, + 0x06, 0xcd, 0xcd, 0x72, 0xb6, 0x53, 0x2d, 0x7e, 0x60, 0x49, + 0xfe, 0x31, 0xe1, 0xd0, 0x0e, 0x4c, 0x98, 0x93, 0xe0, 0xf6, + 0xf2, 0xfa, 0x99, 0x7f, 0x65, 0xd8, 0x15, 0xc6, 0x3a, 0xb8, + 0x4d, 0x63, 0x21, 0x78, 0xe4, 0x19, 0x6b, 0xbd, 0xde, 0x40, + 0x5b, 0x8c, 0xfa, 0x49, 0x75, 0x23, 0x8f, 0x14, 0xc2, 0x3b, + 0xa3, 0x9b, 0xc5, 0x80, 0x1a, 0xa3, 0x60, 0xd7, 0x17, 0x27, + 0xf0, 0x18, 0x0f, 0xba, 0x02, 0xf7, 0x7a, 0xed, 0xa4, 0x00, + 0x77, 0xde, 0x4b, 0xdd, 0xf9, 0xd7, 0x3e, 0x75, 0xed, 0x1a, + 0x43, 0x26, 0x71, 0x1b, 0xbc, 0x72, 0xf5, 0x70, 0x72, 0x03, + 0x70, 0x25, 0x87, 0x81, 0x6a, 0x92, 0x2d, 0xb7, 0x02, 0xf0, + 0x10, 0x79, 0x65, 0x9d, 0x4e, 0x11, 0x7d, 0x5c, 0x5b, 0x37, + 0xaa, 0xb4, 0xfa, 0x43, 0x66, 0x48, 0x6c, 0x67, 0x64, 0x9e, + 0x15, 0x75, 0x36, 0xe7, 0x25, 0x55, 0x07, 0x7f, 0x74, 0x1f, + 0x2c, 0x28, 0x76, 0xe7, 0x9b, 0x3d, 0x91, 0x0b, 0xcd, 0x6a, + 0x1d, 0x5a, 0xea, 0x63, 0xd0, 0xf9, 0x02, 0x82, 0x01, 0xe0, + 0x3e, 0x31, 0xf2, 0xf4, 0x29, 0x92, 0xa2, 0x93, 0xd5, 0xda, + 0xc9, 0x16, 0x7e, 0xf6, 0xdb, 0x33, 0x9f, 0xaf, 0x4b, 0x01, + 0xd1, 0x28, 0x2d, 0x3a, 0xc0, 0x51, 0x91, 0x26, 0xbd, 0xa5, + 0x1e, 0xdd, 0xd9, 0x2e, 0x11, 0x93, 0x19, 0x29, 0x47, 0x5d, + 0x63, 0xe4, 0xb6, 0xf1, 0xea, 0x12, 0x29, 0xa1, 0x65, 0x12, + 0x6d, 0x78, 0x8f, 0x63, 0x31, 0xec, 0x72, 0x54, 0x73, 0x72, + 0x26, 0x48, 0x57, 0x57, 0xc8, 0xde, 0x28, 0x27, 0xf5, 0x62, + 0xfb, 0x7f, 0x1b, 0xf3, 0xaf, 0x31, 0x01, 0xfc, 0x01, 0x58, + 0x7a, 0x80, 0x72, 0x9d, 0x6e, 0x07, 0xcc, 0x45, 0x67, 0xc6, + 0x26, 0xfe, 0x25, 0xa5, 0x9b, 0x64, 0xcd, 0x45, 0xe3, 0x31, + 0x38, 0x05, 0x07, 0x36, 0x05, 0x46, 0x9c, 0xc1, 0x8e, 0xbf, + 0x4e, 0x71, 0x5f, 0xea, 0xe5, 0x0c, 0x9a, 0x41, 0xc8, 0x94, + 0xcc, 0xf1, 0x73, 0x06, 0x30, 0x54, 0x76, 0x23, 0xb7, 0x22, + 0x7a, 0x8e, 0xe6, 0x42, 0xa1, 0xa0, 0x32, 0x12, 0xe9, 0x08, + 0x1c, 0x46, 0x79, 0x0c, 0x82, 0x7a, 0x95, 0x79, 0xbf, 0x83, + 0x80, 0xeb, 0xab, 0x3d, 0x32, 0xc5, 0xde, 0x62, 0xeb, 0x90, + 0x29, 0x73, 0x05, 0xc8, 0x0a, 0xb1, 0x51, 0xf1, 0x23, 0xdd, + 0x1e, 0xf5, 0x02, 0x3e, 0x74, 0xbc, 0x24, 0x0c, 0x60, 0x36, + 0x2a, 0x28, 0x4d, 0xe6, 0x86, 0x98, 0x7c, 0xd9, 0xe1, 0xac, + 0x21, 0x33, 0xaa, 0xa9, 0x8b, 0xb6, 0x8a, 0x1b, 0xf7, 0x54, + 0x14, 0xf3, 0x0d, 0x4f, 0xcd, 0x7c, 0xf5, 0xc2, 0x6d, 0xc2, + 0xf0, 0xe2, 0xfc, 0x63, 0x1e, 0xa6, 0xa9, 0xa9, 0xd9, 0x73, + 0x2a, 0xd5, 0x0a, 0x38, 0xd8, 0xc0, 0xb7, 0xe1, 0x51, 0xe4, + 0x23, 0x37, 0xf7, 0x85, 0x66, 0x0e, 0x3f, 0x1a, 0x8c, 0xcf, + 0x12, 0xa2, 0x47, 0x6f, 0x73, 0x91, 0x21, 0xe3, 0x93, 0x6b, + 0x74, 0x4f, 0xc5, 0xa1, 0xe7, 0x32, 0xf7, 0x86, 0xdd, 0x1a, + 0x6e, 0x96, 0xda, 0x32, 0x1d, 0xdd, 0xfa, 0x42, 0xd5, 0xd4, + 0xfd, 0xae, 0x7a, 0xa1, 0xed, 0x3d, 0x79, 0xfe, 0x88, 0x84, + 0x43, 0xa7, 0xec, 0xf3, 0x7a, 0x13, 0xaa, 0xa1, 0x82, 0x02, + 0x83, 0x19, 0x43, 0x0a, 0x46, 0x78, 0x07, 0xd9, 0x4d, 0xff, + 0xac, 0x67, 0xd6, 0x29, 0x89, 0xfe, 0x2b, 0xab, 0x5f, 0x9a, + 0x87, 0x99, 0x80, 0xaf, 0x70, 0x4a, 0x6a, 0xb9, 0x5a, 0xc2, + 0xac, 0x7f, 0xa2, 0xc7, 0xad, 0xe2, 0x1f, 0xec, 0xc5, 0x12, + 0x17, 0x08, 0x87, 0x8f, 0x20, 0x95, 0xbe, 0xaf, 0x62, 0x2c, + 0xc2, 0x3f, 0x89, 0x56, 0xd8, 0x50, 0x96, 0x97, 0x72, 0xe2, + 0x92, 0xe1, 0x2a, 0xd8, 0x84, 0x9f, 0x31, 0xe3, 0x06, 0xd8, + 0xe5, 0x91, 0x63, 0x19, 0xe1, 0x27, 0xad, 0xe2, 0xf2, 0x0a, + 0x5e, 0x78, 0x8b, 0x1b, 0x13, 0x31, 0x4b, 0xbd, 0x77, 0xb2, + 0xd6, 0x5c, 0x92, 0x81, 0x50, 0x02, 0x37, 0xd2, 0xe6, 0xeb, + 0x66, 0x6b, 0xaa, 0xfc, 0xcd, 0x54, 0x5d, 0xb8, 0x03, 0x87, + 0xe8, 0xfa, 0xb2, 0xde, 0xcb, 0xf8, 0x6e, 0x58, 0xde, 0xcb, + 0x09, 0x54, 0x8a, 0x9f, 0x46, 0xa3, 0x7e, 0x8d, 0x15, 0xff, + 0x1b, 0x0d, 0x89, 0xc4, 0x1a, 0x21, 0x31, 0x5e, 0xed, 0x0b, + 0x67, 0x3c, 0x70, 0xed, 0x92, 0x48, 0xef, 0xec, 0xf0, 0x77, + 0xc2, 0x79, 0x6c, 0x06, 0x09, 0xaa, 0xab, 0xf6, 0x4c, 0xcd, + 0xfa, 0x7e, 0x4a, 0x88, 0xdc, 0xa8, 0x9b, 0xd3, 0x69, 0x94, + 0x88, 0x09, 0x1d, 0x30, 0x43, 0x9e, 0x2c, 0xcb, 0x01, 0x1d, + 0x4a, 0x3b, 0x04, 0xec, 0x0e, 0xb1, 0xde, 0x09, 0xad, 0x29, + 0x02, 0x82, 0x01, 0xe1, 0x00, 0x9f, 0x02, 0x13, 0x7a, 0xd0, + 0xa9, 0x8a, 0x7a, 0xa0, 0x05, 0xbb, 0x44, 0x6f, 0xaf, 0xf7, + 0xe3, 0xd4, 0x35, 0xef, 0x73, 0x39, 0xd5, 0xe0, 0xa2, 0x0f, + 0x1a, 0x25, 0xa8, 0xf7, 0xc2, 0xa5, 0xec, 0x57, 0xf8, 0x0d, + 0x2a, 0xb6, 0x64, 0x03, 0x8c, 0x22, 0x0f, 0xe7, 0x98, 0xa1, + 0x12, 0xfe, 0x24, 0xef, 0x61, 0x28, 0x9f, 0xa7, 0x22, 0x6b, + 0x6d, 0xab, 0x8d, 0x7d, 0x2a, 0x8b, 0xae, 0x8b, 0xfd, 0xcb, + 0xd5, 0x0b, 0x79, 0x1b, 0x89, 0xcb, 0x5b, 0x7a, 0x8c, 0xdc, + 0xe8, 0x8d, 0xdd, 0x35, 0x9f, 0x06, 0x69, 0x64, 0x12, 0xeb, + 0x46, 0x79, 0xdf, 0x82, 0x2c, 0x89, 0x75, 0x9e, 0x7a, 0xec, + 0xad, 0xe5, 0x88, 0x31, 0xfa, 0x86, 0x93, 0xca, 0xf1, 0x2d, + 0x9b, 0x62, 0x5a, 0xe9, 0x43, 0x09, 0xf3, 0x8c, 0xe5, 0xc7, + 0xc0, 0xce, 0x86, 0xe7, 0xdb, 0xc7, 0x4d, 0x27, 0xd5, 0xee, + 0x76, 0xce, 0x35, 0x30, 0x47, 0xef, 0x00, 0x1b, 0x69, 0x9a, + 0x3f, 0xa5, 0x2a, 0xc9, 0x07, 0xab, 0x99, 0xba, 0x2a, 0xe7, + 0xfb, 0xa9, 0x4e, 0xb9, 0xae, 0x2c, 0x50, 0xfc, 0x35, 0x49, + 0xe6, 0x97, 0x78, 0x3c, 0xb1, 0x59, 0xd7, 0x1d, 0x4e, 0x4e, + 0xea, 0xde, 0xa0, 0xd0, 0xc4, 0x1d, 0xb1, 0xd3, 0x53, 0x1e, + 0xf9, 0xbf, 0xb3, 0x6a, 0x17, 0xb4, 0xda, 0xcc, 0x27, 0x19, + 0xc6, 0x35, 0xe8, 0x28, 0xd3, 0xe3, 0x76, 0x3a, 0xdc, 0xd0, + 0x75, 0xc8, 0xb4, 0x6c, 0xbe, 0x84, 0x2a, 0x45, 0xd1, 0x43, + 0x22, 0x54, 0xd7, 0xc5, 0xd0, 0xd7, 0x73, 0x35, 0x6b, 0xa8, + 0xfa, 0xad, 0x60, 0xc0, 0x64, 0xc1, 0x58, 0x89, 0x09, 0x81, + 0x0a, 0x0b, 0xea, 0x33, 0x91, 0xb0, 0xef, 0x53, 0x50, 0x41, + 0xae, 0xd9, 0xee, 0xbe, 0x9e, 0xf0, 0x0b, 0xa0, 0x7c, 0xbf, + 0x3f, 0xc9, 0x4b, 0xe0, 0x48, 0xd8, 0x10, 0xd5, 0x2e, 0xce, + 0xf0, 0x7c, 0xd8, 0x05, 0xde, 0x09, 0x7e, 0x8c, 0x63, 0x4c, + 0xdb, 0x8b, 0x91, 0xcd, 0x7f, 0xb6, 0x6b, 0xad, 0xce, 0xb1, + 0x17, 0x6c, 0xf7, 0x08, 0x0d, 0x7c, 0xda, 0x4f, 0x0a, 0x07, + 0xd0, 0xae, 0x72, 0x3c, 0x67, 0x4a, 0x44, 0x54, 0x47, 0xce, + 0xe1, 0x17, 0x07, 0x12, 0xde, 0x52, 0xef, 0xef, 0x4c, 0x2b, + 0x42, 0x7d, 0x09, 0x80, 0x36, 0x34, 0xdc, 0x45, 0x6f, 0xb0, + 0x2d, 0xab, 0xa0, 0x0c, 0x58, 0xae, 0x35, 0xd3, 0x9b, 0x37, + 0xc1, 0x1d, 0xeb, 0xfe, 0xc3, 0x04, 0xc9, 0x1d, 0xe7, 0x3d, + 0x16, 0x64, 0xed, 0xf5, 0xe8, 0xdf, 0x99, 0xa4, 0xfb, 0xad, + 0x79, 0x88, 0xd5, 0x8c, 0x62, 0x33, 0x9e, 0x35, 0xa6, 0x7f, + 0x9d, 0xb6, 0x1a, 0x40, 0x6d, 0xc3, 0x89, 0x5d, 0x7b, 0xe2, + 0xc8, 0xd3, 0x16, 0x13, 0x07, 0x9a, 0x38, 0x22, 0x33, 0x03, + 0xac, 0x70, 0x3e, 0xce, 0x32, 0x56, 0x0b, 0x58, 0x56, 0xb8, + 0xe9, 0xd8, 0x42, 0x35, 0x6c, 0xb9, 0x02, 0xb3, 0x64, 0xeb, + 0xaa, 0x09, 0x3f, 0xac, 0x66, 0x08, 0xb4, 0x5f, 0x3e, 0xb4, + 0xec, 0x39, 0xb1, 0x99, 0xe4, 0x5d, 0x1d, 0x32, 0x14, 0xc1, + 0x48, 0x8f, 0x6c, 0x65, 0x87, 0x34, 0x50, 0xa4, 0xf4, 0x9b, + 0x5b, 0x2e, 0xb5, 0x79, 0x0d, 0x11, 0x62, 0xa4, 0x35, 0x9c, + 0x6f, 0x92, 0xd0, 0x68, 0x07, 0xdd, 0x69, 0x85, 0x48, 0xe3, + 0x5d, 0x10, 0x34, 0xaf, 0xea, 0x41, 0x72, 0x5a, 0x71, 0x00, + 0xf8, 0xe6, 0x47, 0x7f, 0xa0, 0x6f, 0x91, 0x96, 0x40, 0x00, + 0x40, 0x70, 0xfb, 0x63, 0xcf, 0xc9, 0x36, 0x04, 0x1c, 0x3b, + 0x11, 0x08, 0x29, 0x81, 0x9f +}; + +static unsigned char test15360[] = { + 0x30, 0x82, 0x21, 0xe8, 0x02, 0x01, 0x00, 0x02, 0x82, 0x07, + 0x81, 0x00, 0xad, 0x3f, 0xaa, 0xdc, 0x8c, 0x85, 0xcb, 0x60, + 0xd2, 0xf5, 0x30, 0xa1, 0x0f, 0x26, 0xec, 0xdf, 0xfc, 0x91, + 0x39, 0xbd, 0x3e, 0x8f, 0x99, 0x64, 0x1e, 0x51, 0xd2, 0x27, + 0x5e, 0x76, 0xcd, 0x86, 0x33, 0x07, 0xf9, 0xbd, 0x3b, 0x06, + 0xc3, 0x3c, 0x85, 0xcb, 0x7e, 0x91, 0x14, 0xb0, 0x0b, 0x77, + 0x22, 0x30, 0x71, 0xb8, 0xbb, 0x74, 0x30, 0x33, 0x35, 0x56, + 0x34, 0x47, 0x10, 0x8f, 0x88, 0xe2, 0x6f, 0xdc, 0x3b, 0xe9, + 0x58, 0x9d, 0x0c, 0xdc, 0x8f, 0x70, 0x41, 0x7a, 0x12, 0xd2, + 0x9a, 0x35, 0xbe, 0x0a, 0x57, 0x13, 0x0c, 0xe9, 0xbf, 0x77, + 0x54, 0x00, 0x74, 0xb7, 0x1a, 0x3e, 0xa7, 0xe9, 0xb6, 0xe7, + 0x4f, 0x1e, 0xa4, 0xc0, 0x7c, 0x4c, 0x66, 0xc5, 0xce, 0xad, + 0x96, 0x1b, 0xe2, 0x1a, 0xf1, 0x3d, 0x8b, 0x50, 0xcf, 0xe2, + 0x15, 0x21, 0x6d, 0x83, 0x95, 0x00, 0xee, 0x97, 0xc4, 0xae, + 0xc9, 0x38, 0x62, 0x6c, 0xb2, 0xe7, 0x7f, 0x15, 0x0a, 0xab, + 0x86, 0xb9, 0xd9, 0x8a, 0xf8, 0xeb, 0x88, 0x5d, 0xdc, 0x0c, + 0x1e, 0xc5, 0xe6, 0xa1, 0x7b, 0xbf, 0xf1, 0x02, 0xe3, 0xad, + 0xf8, 0xed, 0x17, 0x9f, 0x83, 0x11, 0x31, 0x3b, 0xad, 0xb4, + 0xf9, 0x8d, 0x1d, 0x56, 0x9b, 0xac, 0x68, 0x55, 0x0a, 0x74, + 0x20, 0xee, 0x57, 0xe7, 0x1c, 0x6d, 0x05, 0xa1, 0x4e, 0xa5, + 0x11, 0x99, 0xb4, 0x86, 0xdb, 0x58, 0xe7, 0xf6, 0xb6, 0x4f, + 0x92, 0x58, 0x57, 0x9b, 0x74, 0x04, 0xe5, 0xd1, 0x1d, 0x7c, + 0x4b, 0xb8, 0x1f, 0x5d, 0x0e, 0x93, 0xee, 0x44, 0x18, 0xb6, + 0x58, 0x0e, 0xa1, 0x0b, 0x8e, 0x2e, 0x99, 0x4c, 0x72, 0x91, + 0xfa, 0xfa, 0xe2, 0x22, 0x05, 0x5d, 0x2b, 0x2d, 0xd8, 0x60, + 0xd5, 0x1b, 0x08, 0x56, 0x2b, 0xb5, 0x21, 0xdb, 0x1a, 0xe6, + 0xa8, 0x39, 0xa2, 0xf4, 0x58, 0xcb, 0xd2, 0xf9, 0xce, 0xc0, + 0x1e, 0x1b, 0xf9, 0xa7, 0x37, 0xca, 0xa3, 0x77, 0x6e, 0xb1, + 0xaf, 0x33, 0xb5, 0x6d, 0x5f, 0x33, 0x2e, 0x1a, 0x34, 0xdb, + 0x42, 0xbe, 0x5f, 0xf9, 0x09, 0xb7, 0x9f, 0xd4, 0x09, 0xfb, + 0x87, 0x13, 0x3c, 0xe2, 0x27, 0xb8, 0xf3, 0x1d, 0x7e, 0x92, + 0xdd, 0x87, 0x86, 0x55, 0x69, 0x9b, 0x55, 0xcd, 0xef, 0x7a, + 0x71, 0x5d, 0x81, 0x3a, 0xd9, 0xf7, 0x7f, 0xde, 0xe0, 0x92, + 0xd9, 0x78, 0x0f, 0x1d, 0x43, 0xb1, 0x1e, 0x29, 0xc1, 0x49, + 0xb6, 0x5e, 0x85, 0x83, 0xd9, 0x04, 0xfd, 0x79, 0xd8, 0x47, + 0x03, 0x2e, 0x85, 0x19, 0xfd, 0x63, 0xe7, 0xa4, 0x8b, 0xc0, + 0x94, 0x0e, 0xb7, 0x54, 0x97, 0xd6, 0x44, 0x5d, 0x63, 0x12, + 0xff, 0xdd, 0xde, 0x2c, 0x00, 0x0e, 0xc9, 0xca, 0x7e, 0xa2, + 0x65, 0x25, 0xb0, 0x1d, 0xa9, 0x20, 0x4f, 0xdd, 0xea, 0x3a, + 0xb5, 0xe8, 0x0f, 0xf3, 0xb2, 0xb7, 0x00, 0x4a, 0xe8, 0xa4, + 0x83, 0x49, 0xbd, 0x78, 0xdf, 0xac, 0x2c, 0x37, 0x81, 0xb3, + 0xf3, 0xb7, 0x13, 0x93, 0x3e, 0xb2, 0x79, 0x55, 0xf2, 0xd8, + 0x9c, 0xf7, 0xf2, 0xf1, 0xd5, 0x6c, 0x9c, 0xff, 0xec, 0xf4, + 0xea, 0x08, 0x3c, 0x65, 0x35, 0xb7, 0x09, 0x03, 0x6d, 0x99, + 0x1d, 0x5b, 0x73, 0x06, 0x61, 0xb4, 0xf0, 0xc5, 0xdb, 0x3e, + 0xe0, 0x1d, 0xa8, 0x5b, 0x7a, 0x5b, 0x5b, 0x9c, 0x11, 0x75, + 0x83, 0x1d, 0xf4, 0x73, 0x27, 0xf3, 0x79, 0xf2, 0x82, 0xd6, + 0x28, 0x45, 0x58, 0x23, 0x6c, 0x29, 0xd3, 0x50, 0x51, 0x1b, + 0x38, 0xef, 0x89, 0x90, 0x84, 0xa2, 0x4c, 0x35, 0x7b, 0x30, + 0x5e, 0xbd, 0x1a, 0xd5, 0xdf, 0xcd, 0xcd, 0x74, 0x3f, 0x2e, + 0x01, 0xea, 0x33, 0x07, 0x74, 0xfb, 0x86, 0x75, 0x20, 0x0e, + 0x4f, 0xbf, 0x65, 0xd4, 0x15, 0x19, 0x6f, 0x8d, 0x37, 0xcd, + 0xb6, 0x6f, 0x50, 0x9d, 0x5e, 0x04, 0x81, 0x7d, 0xec, 0xd6, + 0xbb, 0x40, 0x1b, 0xe0, 0xf5, 0xd5, 0x86, 0x26, 0xc5, 0x41, + 0x84, 0x0e, 0x3e, 0x73, 0xb7, 0xa4, 0xbe, 0x2a, 0xfe, 0xd7, + 0xe4, 0x4d, 0x5c, 0x2d, 0x6a, 0x04, 0xe6, 0xdd, 0x28, 0xa0, + 0x75, 0x4c, 0xe0, 0x23, 0x2c, 0xad, 0xec, 0xaa, 0x72, 0xfd, + 0x03, 0xc0, 0x65, 0xfa, 0xc4, 0x3c, 0x25, 0x10, 0xae, 0x3f, + 0x09, 0x96, 0x4e, 0xff, 0xfe, 0xc7, 0xe4, 0x9e, 0xec, 0xb5, + 0x6e, 0xec, 0xf3, 0x7a, 0x83, 0x7a, 0x8b, 0xbb, 0x91, 0x8d, + 0xab, 0x3c, 0x4d, 0x7f, 0x34, 0x77, 0xbe, 0x0c, 0x87, 0xf2, + 0xc3, 0xd6, 0xcb, 0xcc, 0xfa, 0x1e, 0xaf, 0x21, 0x24, 0xe9, + 0xaa, 0x89, 0x61, 0x0c, 0x7a, 0x1c, 0x7d, 0x00, 0x87, 0x69, + 0x30, 0xa0, 0xb4, 0x3b, 0x96, 0x1c, 0x00, 0x14, 0x07, 0xb8, + 0x3f, 0x59, 0x62, 0x3a, 0x3f, 0xfb, 0x68, 0xb8, 0x81, 0x7d, + 0x4a, 0x9d, 0x1c, 0xa2, 0x07, 0xa3, 0xb1, 0x42, 0x7b, 0xfa, + 0x9b, 0xbc, 0x94, 0x30, 0x7e, 0xea, 0xe7, 0x40, 0x7e, 0xd4, + 0x0f, 0x33, 0x3b, 0x57, 0xda, 0x8b, 0x6d, 0x64, 0xd5, 0xe4, + 0x91, 0x83, 0xf0, 0x3d, 0xae, 0x8b, 0x91, 0xf0, 0xcd, 0xb1, + 0xa0, 0xe0, 0x0d, 0xe1, 0xbb, 0x22, 0x78, 0x1f, 0x3a, 0xe5, + 0x53, 0x28, 0xf0, 0x35, 0xae, 0x71, 0xe6, 0xfd, 0x63, 0xb2, + 0x9c, 0x3f, 0xdd, 0x95, 0x7b, 0xc4, 0xe9, 0x2f, 0xd9, 0x93, + 0x3a, 0x10, 0x42, 0x1c, 0x90, 0xab, 0xfb, 0xd3, 0x02, 0xe9, + 0x59, 0xbc, 0x53, 0x7e, 0xf3, 0xe1, 0x52, 0x15, 0xa6, 0x58, + 0x9e, 0xc1, 0xa6, 0x0e, 0x2e, 0x35, 0x07, 0x3a, 0xc3, 0x1f, + 0xaa, 0x58, 0xe7, 0xc6, 0x33, 0x6a, 0x39, 0x4b, 0x21, 0x15, + 0x3d, 0x92, 0x4e, 0x5e, 0xf9, 0x01, 0xd6, 0x0f, 0x28, 0x61, + 0x15, 0xdf, 0xed, 0x6f, 0x75, 0xc4, 0x8f, 0xcb, 0x16, 0x55, + 0x09, 0xc7, 0x24, 0xb2, 0x0c, 0x49, 0x25, 0x8d, 0x5e, 0xf1, + 0x0e, 0xe0, 0xe2, 0xc4, 0xcc, 0x1f, 0x4e, 0x60, 0x5c, 0x5e, + 0xc6, 0x7f, 0x68, 0x7f, 0xdb, 0x1a, 0x01, 0x67, 0x07, 0xb1, + 0x56, 0x93, 0xf2, 0x26, 0x81, 0xc0, 0x33, 0xb8, 0x48, 0xf9, + 0x2c, 0x5c, 0x18, 0x29, 0xed, 0xe0, 0x6c, 0xa0, 0xac, 0xd2, + 0x90, 0x4b, 0x52, 0x87, 0xbb, 0xb5, 0x05, 0xd8, 0x56, 0xc5, + 0xb8, 0x8f, 0x3f, 0x49, 0x52, 0x9a, 0xa2, 0xd0, 0x40, 0x80, + 0x5b, 0x16, 0x15, 0xbc, 0x74, 0x8e, 0x00, 0x10, 0xaf, 0xfb, + 0x6d, 0xba, 0xcb, 0xbc, 0xe6, 0x13, 0x75, 0xce, 0x27, 0xae, + 0x85, 0x57, 0x6c, 0xc0, 0x8a, 0x84, 0x6f, 0x34, 0x16, 0xd4, + 0x35, 0xd2, 0xcc, 0x55, 0x00, 0xc1, 0xd8, 0x28, 0x2c, 0x9c, + 0x84, 0x78, 0xbf, 0xf0, 0x3b, 0x0d, 0x9f, 0x81, 0xd4, 0xef, + 0x99, 0x77, 0x53, 0xd2, 0x8e, 0x43, 0x52, 0xf0, 0x32, 0x7e, + 0xba, 0xbf, 0xb6, 0x0e, 0x9d, 0x9b, 0x00, 0xd0, 0x50, 0x55, + 0x67, 0x5a, 0x2c, 0x8b, 0x9b, 0x29, 0xfb, 0x41, 0x74, 0x4c, + 0xb7, 0xd8, 0x98, 0xa2, 0xfb, 0x73, 0x07, 0x96, 0xef, 0xcd, + 0x47, 0x13, 0x1d, 0xe2, 0xb1, 0xac, 0xf3, 0xcf, 0x47, 0x98, + 0x7b, 0x6f, 0xf6, 0x32, 0x44, 0x41, 0x78, 0x09, 0x8e, 0x64, + 0x0c, 0xbf, 0xe2, 0x0f, 0x8c, 0x44, 0x2f, 0x4e, 0x55, 0xe0, + 0xc6, 0xfd, 0x05, 0x74, 0x18, 0x1a, 0xb9, 0xfa, 0xcb, 0xd3, + 0xfa, 0x69, 0x50, 0x63, 0xce, 0x2b, 0xef, 0x92, 0x0f, 0x11, + 0xd4, 0x9b, 0x53, 0x6c, 0xed, 0xc5, 0x0b, 0x7c, 0xbd, 0xa1, + 0x5d, 0xdf, 0xab, 0xcf, 0xaa, 0x83, 0x5e, 0xa8, 0xc5, 0xfe, + 0x91, 0x2b, 0x23, 0x1f, 0x39, 0x3d, 0x71, 0x74, 0xbf, 0xa2, + 0xf1, 0xda, 0x2f, 0x29, 0x02, 0x9b, 0xea, 0x48, 0x2c, 0xaf, + 0xe7, 0xa9, 0xf5, 0x68, 0xab, 0x8f, 0x18, 0xb9, 0x7b, 0x28, + 0xf0, 0x92, 0xfb, 0x07, 0xd7, 0xbd, 0x43, 0xcd, 0x7f, 0xfc, + 0xb9, 0x5f, 0x24, 0xf8, 0x48, 0x2e, 0xbe, 0x42, 0x87, 0x80, + 0x38, 0x78, 0x9e, 0x8c, 0x52, 0x6d, 0xfa, 0x2e, 0x46, 0x35, + 0x7a, 0x59, 0x88, 0xb9, 0x3e, 0xcb, 0x79, 0xb4, 0x8a, 0x9e, + 0xd5, 0xd0, 0x30, 0x8c, 0xb2, 0x0c, 0x9d, 0x8d, 0x2d, 0x64, + 0x0b, 0xf6, 0xeb, 0xf1, 0xde, 0xea, 0x74, 0xfc, 0xbc, 0x01, + 0x18, 0x48, 0x4e, 0x35, 0x02, 0x83, 0x01, 0xb2, 0x50, 0xa0, + 0x44, 0x19, 0x30, 0x00, 0x12, 0x4a, 0xa0, 0x6d, 0x6b, 0x8b, + 0xf1, 0xce, 0xda, 0x2e, 0x16, 0x35, 0x52, 0x26, 0xf9, 0xbe, + 0xb1, 0x37, 0xfc, 0x0a, 0x8b, 0x6f, 0x06, 0x11, 0x7b, 0xf7, + 0xa8, 0x40, 0xbd, 0x8d, 0x94, 0xa4, 0xa2, 0xe0, 0xb6, 0xdf, + 0x62, 0xc0, 0x6f, 0xb3, 0x5d, 0x84, 0xb9, 0xaa, 0x2f, 0xc1, + 0x3b, 0xcb, 0x20, 0xc6, 0x68, 0x69, 0x15, 0x74, 0xbc, 0xdb, + 0x43, 0x9c, 0x4a, 0xfc, 0x72, 0xc1, 0xf5, 0x87, 0x80, 0xe8, + 0x6c, 0xd5, 0xc1, 0x2e, 0x34, 0x5e, 0x96, 0x76, 0x08, 0x3e, + 0x45, 0xe4, 0xa0, 0x4a, 0x7a, 0xc1, 0x67, 0x38, 0xf2, 0x31, + 0x1f, 0x7b, 0x0f, 0x54, 0xbd, 0x0d, 0x1f, 0x9e, 0x8e, 0x99, + 0x8b, 0x58, 0xd9, 0x94, 0x87, 0xaa, 0x8b, 0x82, 0x5d, 0x5e, + 0xe8, 0x50, 0xf4, 0xf2, 0xc7, 0xe9, 0x85, 0x6b, 0xd2, 0xef, + 0x13, 0xc1, 0xed, 0x57, 0x2a, 0xc5, 0xd6, 0x5d, 0xa4, 0x3b, + 0x29, 0xba, 0xab, 0x1b, 0xaa, 0x21, 0x41, 0xe9, 0xdc, 0x47, + 0x88, 0xef, 0x0c, 0xfc, 0xb2, 0xdc, 0xf7, 0xdb, 0x55, 0x4d, + 0x70, 0xc7, 0xe2, 0x8a, 0x8a, 0xe1, 0xde, 0xcf, 0xe5, 0xca, + 0x23, 0x36, 0x29, 0xe5, 0xfc, 0x54, 0x66, 0xda, 0xe9, 0xab, + 0x58, 0x20, 0xb2, 0x8e, 0xb2, 0x7d, 0x5d, 0xb8, 0xc7, 0x6c, + 0x48, 0x53, 0x2b, 0x47, 0xe0, 0x12, 0x00, 0x0e, 0xfe, 0xa5, + 0x93, 0x34, 0xf9, 0x3e, 0xa6, 0x3f, 0x56, 0xaa, 0x43, 0x65, + 0xbb, 0x5a, 0x70, 0x3e, 0x62, 0xac, 0x3f, 0x5b, 0x90, 0x02, + 0x50, 0x5d, 0x05, 0xa8, 0xd5, 0x67, 0x1a, 0x62, 0xec, 0xd4, + 0xde, 0x29, 0x04, 0xac, 0x6d, 0x15, 0x5d, 0xa0, 0xec, 0xf2, + 0x57, 0x13, 0x0e, 0x17, 0x96, 0x0c, 0x32, 0x6a, 0xc5, 0xe0, + 0xa8, 0xff, 0x85, 0xa4, 0xa3, 0xe3, 0x0e, 0x35, 0x5d, 0xd1, + 0x28, 0x84, 0xaa, 0xc4, 0x84, 0xcd, 0x25, 0x63, 0x85, 0x82, + 0x3e, 0x12, 0x30, 0x17, 0x57, 0x45, 0xb8, 0xb4, 0x34, 0x01, + 0x3a, 0xa2, 0x77, 0x61, 0xc8, 0x3d, 0x1f, 0xc5, 0x0e, 0x4a, + 0xbb, 0xf6, 0xa0, 0x5d, 0x79, 0x4b, 0xc8, 0xf3, 0x9c, 0x87, + 0x05, 0x2f, 0xea, 0x25, 0x28, 0x91, 0x69, 0x77, 0x7c, 0xba, + 0xea, 0x4a, 0x75, 0x2e, 0x2b, 0x17, 0x83, 0x50, 0x32, 0x43, + 0x4f, 0xcd, 0xf1, 0x77, 0xb1, 0x22, 0x0a, 0x8b, 0x69, 0x58, + 0x09, 0x35, 0x07, 0x6d, 0x61, 0x4a, 0x8d, 0x18, 0x65, 0x6e, + 0x9b, 0x62, 0x07, 0xd0, 0x6a, 0x92, 0x39, 0x05, 0x80, 0x14, + 0xfa, 0x1c, 0x93, 0x84, 0x0c, 0xb5, 0x8c, 0x41, 0x91, 0x4e, + 0x48, 0xf0, 0xf2, 0xba, 0x1d, 0x73, 0x2f, 0x1e, 0xa1, 0x55, + 0xc3, 0x02, 0x8c, 0xb1, 0xf2, 0x37, 0xa6, 0x9a, 0x6b, 0xcd, + 0x45, 0x2e, 0x08, 0x90, 0x26, 0x63, 0x91, 0xff, 0x22, 0x5e, + 0xcd, 0xae, 0x9b, 0x19, 0x1e, 0x10, 0x62, 0x4e, 0x1f, 0x2d, + 0x81, 0x69, 0x4f, 0x41, 0xe5, 0x94, 0xff, 0x7e, 0xcc, 0x15, + 0x36, 0x1e, 0x29, 0x59, 0x37, 0xe7, 0x64, 0x40, 0x17, 0x1a, + 0x32, 0xba, 0x01, 0x26, 0x30, 0x80, 0x60, 0x07, 0x86, 0x6e, + 0xd4, 0xb3, 0xe2, 0x44, 0x16, 0x33, 0xf2, 0x4c, 0x84, 0x0e, + 0xb1, 0x4a, 0xc7, 0x92, 0xa6, 0xa3, 0x42, 0x36, 0x05, 0x3e, + 0x74, 0xa8, 0xb1, 0xc5, 0x63, 0x59, 0x0d, 0x1e, 0x36, 0x45, + 0x2b, 0x36, 0x5e, 0xca, 0xab, 0x97, 0x49, 0xd3, 0xab, 0xae, + 0x63, 0x0a, 0xd1, 0x03, 0x57, 0x88, 0xa4, 0xa4, 0x3c, 0xda, + 0x15, 0x49, 0x1a, 0x5d, 0xe6, 0x5e, 0xb9, 0x82, 0x23, 0xc0, + 0x83, 0x96, 0xfe, 0x38, 0x0b, 0x80, 0x0e, 0xde, 0x22, 0xeb, + 0x5d, 0xe4, 0x56, 0x32, 0xbe, 0xe0, 0xc0, 0x6e, 0x69, 0x63, + 0x27, 0x4e, 0x00, 0x58, 0x80, 0x70, 0xd9, 0xcc, 0x4e, 0xae, + 0x6c, 0x5e, 0x6a, 0x43, 0x81, 0xfd, 0x45, 0xb2, 0xa4, 0x6c, + 0xf0, 0x9c, 0x66, 0x5c, 0x7d, 0x5c, 0x78, 0x55, 0x33, 0x4b, + 0x3c, 0x3b, 0x1d, 0x18, 0x58, 0x79, 0x6a, 0x02, 0xec, 0xce, + 0x53, 0x69, 0xc0, 0x17, 0xed, 0x57, 0xaf, 0x71, 0x5b, 0x42, + 0x1b, 0x49, 0xd8, 0xe8, 0x96, 0x80, 0xb6, 0x48, 0x1b, 0x7c, + 0xf8, 0x74, 0x1c, 0xb1, 0xc4, 0x10, 0xb7, 0xf4, 0x97, 0x7e, + 0x6b, 0x8f, 0x54, 0xba, 0x37, 0xb9, 0x35, 0x9e, 0x7b, 0x17, + 0x16, 0x9b, 0x89, 0x39, 0xae, 0x4f, 0x2e, 0x18, 0x65, 0xb4, + 0x76, 0x20, 0x9a, 0x58, 0xe2, 0x57, 0x6e, 0x1c, 0x3f, 0x8e, + 0x9a, 0xbb, 0xd8, 0xfc, 0x4c, 0xd6, 0x2d, 0xc1, 0xa6, 0x46, + 0xac, 0x13, 0x1e, 0xa7, 0xf7, 0x1d, 0x28, 0x3a, 0xf4, 0xd6, + 0x48, 0xfb, 0xe5, 0xb3, 0x84, 0x94, 0x47, 0x92, 0xae, 0x9a, + 0x58, 0xc5, 0xac, 0x23, 0x1b, 0xb5, 0xcd, 0x96, 0xd2, 0x5e, + 0xb2, 0x41, 0xfc, 0x9a, 0xae, 0x19, 0xf1, 0x7b, 0x4b, 0x53, + 0x1b, 0xfa, 0xa5, 0x0c, 0x49, 0x6d, 0xff, 0xf4, 0x51, 0x88, + 0x19, 0x04, 0xd9, 0x85, 0x8e, 0xe2, 0x3a, 0x62, 0x31, 0x5c, + 0x6e, 0xe8, 0x4d, 0x04, 0x1d, 0xd8, 0xc2, 0x7b, 0x51, 0xe7, + 0x59, 0xbc, 0x85, 0x5c, 0xc4, 0xcc, 0xad, 0xcb, 0x93, 0x69, + 0x18, 0xe4, 0x71, 0x9e, 0x63, 0x33, 0x99, 0xb6, 0x3b, 0x23, + 0x11, 0x17, 0x7a, 0x3d, 0x6f, 0xb9, 0x6b, 0xf1, 0xf2, 0xa7, + 0x03, 0xfd, 0xf0, 0xcd, 0x5b, 0xb5, 0xda, 0x9a, 0xd9, 0x95, + 0x02, 0x76, 0xd8, 0x38, 0xd3, 0xbd, 0xa0, 0x4a, 0x9a, 0xab, + 0x70, 0xde, 0xc6, 0xf9, 0xa5, 0x19, 0x9c, 0xc4, 0xf9, 0x07, + 0x4d, 0xea, 0x15, 0xc2, 0x91, 0x4d, 0x54, 0xa9, 0x2c, 0xca, + 0xdf, 0xaa, 0xd1, 0xc4, 0xc0, 0x18, 0x77, 0x28, 0x2a, 0x2c, + 0xc3, 0x7c, 0x26, 0xbd, 0xd8, 0x0d, 0x51, 0xa1, 0x4d, 0xad, + 0x76, 0x76, 0xaa, 0xa9, 0x45, 0x82, 0x4f, 0x76, 0xfb, 0x1a, + 0xd3, 0x71, 0x3c, 0x55, 0xa2, 0x5c, 0xe0, 0xd6, 0xda, 0x35, + 0xbe, 0x25, 0x23, 0x26, 0x51, 0xc6, 0xb4, 0xf3, 0x3e, 0x2c, + 0x54, 0x09, 0xc7, 0x6f, 0xa5, 0x08, 0x81, 0xba, 0x75, 0xda, + 0xcb, 0x4d, 0x05, 0xdd, 0xca, 0x93, 0x48, 0x30, 0xe8, 0x4a, + 0x1f, 0xfd, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x07, + 0x80, 0x25, 0x2f, 0xbc, 0x49, 0xf8, 0xb3, 0xa3, 0x32, 0xd6, + 0x35, 0x20, 0xca, 0x01, 0x49, 0x96, 0xa0, 0x81, 0x42, 0xde, + 0xc4, 0xdb, 0x0f, 0xd1, 0x99, 0xe6, 0xd4, 0x23, 0x2a, 0xa6, + 0x21, 0x13, 0xfe, 0x51, 0x27, 0xce, 0x18, 0x2a, 0xfa, 0x49, + 0x9f, 0xcd, 0x0c, 0x1f, 0xcf, 0x9e, 0x44, 0x27, 0x41, 0xdc, + 0x09, 0xcf, 0xef, 0x19, 0xf5, 0x57, 0x7f, 0x36, 0x5c, 0x99, + 0x7e, 0x03, 0x74, 0xfb, 0xa9, 0xb6, 0xde, 0xeb, 0xd1, 0x2b, + 0x5f, 0x12, 0x6a, 0xa9, 0x33, 0x2c, 0x2a, 0xba, 0xad, 0x8f, + 0xc2, 0x27, 0x57, 0x6a, 0xd7, 0x40, 0xf7, 0x4f, 0x4c, 0x9a, + 0xb0, 0x3a, 0x5d, 0x2e, 0xf9, 0xf1, 0xea, 0xbd, 0x82, 0xaa, + 0xbd, 0xe6, 0x19, 0x16, 0xd5, 0x03, 0x5e, 0x43, 0xfd, 0x88, + 0x71, 0xd5, 0xb7, 0x78, 0xbe, 0x80, 0x0f, 0xc9, 0x7f, 0x3a, + 0x8f, 0xe1, 0x44, 0xd4, 0x0f, 0xce, 0x26, 0xaf, 0x65, 0xe0, + 0xf5, 0x04, 0x53, 0x56, 0x97, 0x4f, 0xf4, 0xc1, 0x44, 0x8d, + 0xf7, 0x88, 0x55, 0x47, 0x16, 0xaf, 0x3f, 0x8e, 0x42, 0xdf, + 0xbc, 0x14, 0xc3, 0xe6, 0x9f, 0x0d, 0x69, 0x54, 0x5b, 0x7c, + 0x49, 0xcf, 0xbf, 0x42, 0x4f, 0xc7, 0x64, 0x8a, 0xe5, 0x84, + 0x87, 0x20, 0x9b, 0xfd, 0x70, 0x25, 0x38, 0xd3, 0xb4, 0x97, + 0x78, 0xf1, 0x4f, 0x3f, 0x0f, 0xbb, 0x9c, 0xa3, 0x17, 0xd5, + 0x4e, 0x4b, 0xac, 0x82, 0x9a, 0x73, 0xb7, 0xc5, 0xec, 0x10, + 0x7a, 0x7b, 0xdb, 0x77, 0x2c, 0xb1, 0xf3, 0x8f, 0xc3, 0xa5, + 0x31, 0x11, 0x32, 0x55, 0x35, 0xb5, 0x77, 0xd2, 0x62, 0x19, + 0x46, 0x92, 0x94, 0xbb, 0x61, 0x0f, 0x30, 0x94, 0x8a, 0xf6, + 0xf7, 0x30, 0xe0, 0xa2, 0x8c, 0x1b, 0xff, 0x8c, 0x29, 0x44, + 0xb4, 0xb7, 0xb6, 0x5f, 0x4d, 0x52, 0xc6, 0x07, 0xe1, 0x28, + 0x8c, 0xae, 0x88, 0x8a, 0x22, 0xbd, 0xd7, 0x36, 0xe4, 0x8f, + 0xd1, 0xeb, 0x65, 0x54, 0x19, 0x5f, 0xba, 0xfb, 0xfc, 0x91, + 0xa1, 0xa4, 0xb8, 0xa4, 0x2d, 0x85, 0x20, 0xc4, 0xe5, 0xa7, + 0x4e, 0xdb, 0xa4, 0xc5, 0xcc, 0x2f, 0x37, 0x41, 0x29, 0x47, + 0x15, 0xff, 0x04, 0x80, 0x08, 0x37, 0xce, 0xc5, 0xe3, 0x5a, + 0x3f, 0x83, 0xbb, 0x03, 0x9e, 0xfe, 0xec, 0xe4, 0x11, 0x41, + 0x12, 0x13, 0xf2, 0x00, 0xe5, 0x1a, 0x02, 0x49, 0xeb, 0xdb, + 0x57, 0xe4, 0xce, 0xa0, 0x3f, 0xfd, 0x3c, 0x73, 0x2b, 0x92, + 0x44, 0x79, 0x9e, 0x12, 0x4f, 0xfa, 0xe4, 0x53, 0x62, 0xf2, + 0xb0, 0xe2, 0x8a, 0xf0, 0x93, 0xa8, 0x1d, 0xee, 0x8d, 0x58, + 0x7a, 0x4c, 0x29, 0x91, 0x29, 0xc1, 0xa4, 0xd5, 0xe6, 0x37, + 0x1b, 0x75, 0x5b, 0xb6, 0x6b, 0x76, 0x2e, 0xcb, 0xbd, 0xa9, + 0xbe, 0x4c, 0x2e, 0x21, 0xa6, 0x38, 0xde, 0x66, 0x2f, 0x51, + 0xea, 0x4c, 0xba, 0x3f, 0x4a, 0xfe, 0x7a, 0x15, 0xb3, 0x72, + 0x26, 0xba, 0xcf, 0x9e, 0x1b, 0x03, 0xa6, 0xaa, 0x65, 0x68, + 0xd3, 0x8c, 0x15, 0x17, 0xe9, 0x11, 0x18, 0x3c, 0xb6, 0xf8, + 0x02, 0x54, 0x98, 0x49, 0xfa, 0x35, 0x3c, 0xcd, 0xac, 0xc8, + 0x2b, 0x1a, 0x63, 0x93, 0x03, 0x05, 0xa1, 0x41, 0xbe, 0x12, + 0xca, 0x15, 0x47, 0x72, 0x63, 0x77, 0x26, 0xd0, 0xe7, 0x8f, + 0x0d, 0x6e, 0x9c, 0xac, 0x07, 0xbe, 0x03, 0x22, 0xd0, 0x39, + 0x63, 0x8d, 0x9b, 0xc6, 0x20, 0x81, 0xb5, 0x67, 0x15, 0xf6, + 0xb0, 0xe3, 0xb9, 0x3e, 0xb7, 0x3f, 0x8f, 0x46, 0xc9, 0x74, + 0x10, 0x1e, 0x53, 0xf1, 0xd4, 0x30, 0x4d, 0x6e, 0x72, 0xb4, + 0x73, 0x1c, 0xb6, 0x79, 0x82, 0x60, 0x2e, 0x2a, 0x7d, 0x82, + 0x95, 0xb5, 0x7c, 0x4d, 0x44, 0xcb, 0xd8, 0x8a, 0x17, 0xe8, + 0x50, 0x29, 0xd8, 0x3a, 0xeb, 0x29, 0xc1, 0x83, 0x0f, 0xd9, + 0xaf, 0xcc, 0xfa, 0xea, 0x3a, 0x47, 0x5d, 0x33, 0x1f, 0xe8, + 0x33, 0x5b, 0x88, 0x8e, 0xdb, 0xd5, 0x1e, 0xaf, 0x4a, 0x5f, + 0xc0, 0xfa, 0xf0, 0xb5, 0xa3, 0x5b, 0xda, 0x38, 0xb7, 0x38, + 0x5e, 0xce, 0x81, 0x44, 0xf7, 0x66, 0x62, 0x64, 0x1d, 0x04, + 0xf0, 0x8a, 0x4f, 0xa2, 0x80, 0x76, 0x83, 0x23, 0x89, 0x61, + 0x6b, 0xc3, 0xb7, 0xee, 0xb5, 0x06, 0x33, 0xad, 0x63, 0x04, + 0x78, 0xc9, 0xde, 0x32, 0xde, 0xcf, 0x18, 0xb9, 0xb0, 0x3b, + 0xee, 0x0a, 0x58, 0xea, 0xad, 0xbc, 0x1e, 0x77, 0xa0, 0x93, + 0xf7, 0xae, 0x9e, 0xb6, 0x31, 0x59, 0x8e, 0xb1, 0x03, 0x8f, + 0xbb, 0xa4, 0x25, 0x0c, 0x2e, 0xd7, 0xe2, 0x62, 0x5c, 0xf1, + 0x68, 0xe9, 0x76, 0xd7, 0x23, 0x14, 0x45, 0xaf, 0xcb, 0x09, + 0x50, 0x05, 0x3f, 0xa0, 0xf9, 0xc3, 0x9e, 0x89, 0x05, 0xa8, + 0x3b, 0x54, 0x55, 0x32, 0x74, 0x91, 0x46, 0xc1, 0x2c, 0x96, + 0x7e, 0x60, 0xad, 0xfa, 0xbb, 0xcd, 0x09, 0x7b, 0x39, 0x10, + 0x82, 0x8a, 0xc0, 0x5a, 0x0d, 0xab, 0xb3, 0x71, 0x45, 0xad, + 0x39, 0x8e, 0xec, 0x4d, 0x91, 0x8d, 0xda, 0x8d, 0xfa, 0xb0, + 0xad, 0x44, 0x3c, 0xc9, 0x21, 0x56, 0x22, 0xfc, 0xd3, 0xba, + 0xb7, 0x3c, 0xe3, 0x8d, 0xda, 0x59, 0x34, 0x42, 0xdd, 0x04, + 0x5b, 0x8e, 0x2b, 0xc7, 0x94, 0xd5, 0x42, 0xe0, 0x4a, 0x6f, + 0x35, 0x5a, 0x27, 0x82, 0xd8, 0x82, 0x40, 0xee, 0x0f, 0xa6, + 0xef, 0xe4, 0x70, 0xe3, 0x30, 0xb7, 0x2d, 0xd4, 0xbb, 0x27, + 0xb2, 0xbf, 0xad, 0x49, 0x45, 0xbc, 0xeb, 0xbe, 0xb7, 0xd8, + 0xe3, 0xb1, 0xf3, 0xeb, 0x41, 0x20, 0x9b, 0x21, 0x54, 0xc3, + 0xa8, 0xaf, 0x9f, 0x20, 0x5c, 0x15, 0x8e, 0x25, 0xbc, 0xbc, + 0x69, 0x91, 0xfe, 0xda, 0xad, 0xe5, 0x37, 0x7d, 0xb0, 0x51, + 0x14, 0xae, 0x8f, 0x35, 0x15, 0x0a, 0xd4, 0x49, 0xa7, 0xd9, + 0x20, 0x70, 0xa4, 0xf2, 0xf4, 0x24, 0x66, 0x52, 0xd1, 0xa5, + 0x22, 0xea, 0x29, 0xd9, 0xb2, 0x82, 0x8d, 0x36, 0x66, 0x75, + 0x6e, 0xd5, 0x8c, 0x54, 0x08, 0x21, 0xf2, 0xee, 0x78, 0xc7, + 0x1f, 0x9c, 0x63, 0x5d, 0x88, 0x56, 0xd1, 0xa0, 0x80, 0x33, + 0x60, 0x55, 0x23, 0x72, 0xd6, 0xb0, 0x1a, 0x50, 0xde, 0x25, + 0x70, 0xb5, 0x77, 0x42, 0xf8, 0x19, 0x18, 0x15, 0x8f, 0xfd, + 0x0c, 0x6a, 0x46, 0x1f, 0xbf, 0xe7, 0x60, 0x91, 0xe7, 0xbb, + 0x25, 0x63, 0x66, 0xff, 0x11, 0x97, 0xbb, 0xfd, 0x3a, 0x17, + 0x94, 0x77, 0xb4, 0xc5, 0x21, 0xba, 0x30, 0x94, 0xdd, 0xe5, + 0xeb, 0x1d, 0x01, 0xba, 0xf9, 0xb0, 0x30, 0xdb, 0x11, 0x93, + 0xb7, 0xfa, 0x79, 0xe8, 0x5e, 0xb3, 0x39, 0xf4, 0x51, 0x68, + 0x31, 0xce, 0xe9, 0x0e, 0x93, 0xde, 0xff, 0xec, 0x27, 0xbd, + 0xa6, 0x1a, 0x4c, 0xe0, 0x92, 0x5c, 0xd4, 0x07, 0xd2, 0xa1, + 0xdd, 0x12, 0x83, 0xd2, 0x9a, 0x79, 0xb3, 0x3c, 0xfb, 0x07, + 0xe3, 0x18, 0x1a, 0xa3, 0x24, 0x80, 0xb4, 0xcc, 0xf4, 0xc6, + 0xa5, 0x6c, 0x25, 0xd7, 0x99, 0x1a, 0x30, 0xf0, 0xa9, 0xfc, + 0x2e, 0x83, 0x44, 0xac, 0x64, 0x76, 0x34, 0xb0, 0xa6, 0x6f, + 0x20, 0x5a, 0x14, 0xf2, 0x07, 0xa7, 0x6f, 0x4d, 0xab, 0xf5, + 0xfc, 0x9d, 0xd6, 0x3e, 0x82, 0x48, 0x31, 0x25, 0x47, 0xc9, + 0x0e, 0x1d, 0xdb, 0x98, 0x91, 0x56, 0xf5, 0xfe, 0x66, 0x8d, + 0x48, 0xf0, 0x4c, 0x6c, 0x2c, 0x96, 0x54, 0x43, 0xec, 0x76, + 0xf2, 0xe1, 0x76, 0x68, 0xc8, 0xe1, 0xde, 0x0d, 0x8e, 0x6f, + 0xfc, 0x15, 0xd5, 0x93, 0x92, 0xfe, 0xca, 0x9b, 0x30, 0x61, + 0x03, 0x0b, 0xca, 0x99, 0x2f, 0xd3, 0x15, 0xe9, 0x66, 0x81, + 0xbd, 0x56, 0x17, 0x14, 0x4a, 0x2e, 0xf1, 0x34, 0x84, 0x55, + 0x9d, 0xc0, 0x2b, 0xa7, 0x4a, 0xee, 0xf1, 0x7c, 0x67, 0xc7, + 0xf3, 0x08, 0x1e, 0x6d, 0x6b, 0x5b, 0xcc, 0x81, 0x91, 0x5c, + 0x94, 0x1a, 0x80, 0xda, 0x3a, 0xce, 0x36, 0x05, 0xb0, 0x7a, + 0xe8, 0xd0, 0xb4, 0x57, 0x9c, 0xf9, 0xea, 0xf3, 0x26, 0x1d, + 0xcb, 0xf8, 0xdd, 0x65, 0xaf, 0xf7, 0xcd, 0xf7, 0xa1, 0x3d, + 0xfc, 0x9a, 0x3b, 0x08, 0xb9, 0xfa, 0x3c, 0x16, 0x49, 0x4a, + 0xf1, 0xba, 0x4d, 0x31, 0xdd, 0x5e, 0x4f, 0x3d, 0x66, 0x22, + 0x1b, 0x08, 0x91, 0x7d, 0xc6, 0xaf, 0x15, 0x07, 0x3c, 0xa1, + 0xf7, 0x07, 0xfd, 0x3e, 0x90, 0xbb, 0x6f, 0x7a, 0xe9, 0xe1, + 0x2f, 0xb9, 0xee, 0x91, 0x8e, 0x18, 0xcc, 0x8d, 0x1d, 0x22, + 0xa0, 0xa0, 0x28, 0x25, 0xfc, 0xd4, 0x94, 0xd3, 0xaa, 0xcf, + 0xce, 0xd0, 0x85, 0x82, 0x6f, 0x20, 0x9f, 0x55, 0x0e, 0xe5, + 0x72, 0x0d, 0x17, 0x3e, 0x34, 0xc7, 0x2c, 0x0a, 0x14, 0x45, + 0x27, 0xe2, 0xc7, 0x2f, 0x86, 0xa1, 0x55, 0x3e, 0x78, 0x03, + 0xe9, 0x78, 0x2e, 0xd3, 0x99, 0xee, 0xa0, 0x14, 0xf8, 0xe3, + 0x6c, 0xeb, 0x3f, 0x9a, 0xf3, 0x15, 0xce, 0xd5, 0x76, 0xf6, + 0x3a, 0x86, 0x30, 0x76, 0xf9, 0x88, 0x30, 0xf5, 0x4a, 0x50, + 0x58, 0x80, 0xe9, 0xd9, 0xd4, 0xb9, 0x34, 0x42, 0xa6, 0x4e, + 0x9c, 0x1a, 0x07, 0x16, 0x9e, 0xee, 0xe4, 0x88, 0x04, 0x8e, + 0xa8, 0xe7, 0xcd, 0xe8, 0x47, 0x1e, 0x54, 0x45, 0xd2, 0x65, + 0xd8, 0xee, 0x4b, 0xbd, 0xd0, 0x85, 0xaa, 0xfb, 0x06, 0x53, + 0x91, 0x7e, 0xe0, 0x59, 0x20, 0x57, 0x6a, 0xee, 0xd8, 0x9f, + 0x77, 0x7f, 0xd7, 0x40, 0x63, 0xbb, 0x21, 0x75, 0x76, 0x11, + 0x27, 0xcf, 0x05, 0xbb, 0x41, 0x30, 0x98, 0xbf, 0xdc, 0x5f, + 0xc6, 0xa4, 0x1e, 0x30, 0xa1, 0x53, 0xd4, 0x36, 0x7f, 0x2e, + 0x86, 0xd7, 0xd9, 0x95, 0x29, 0xd5, 0x46, 0x18, 0x60, 0x27, + 0xe4, 0x6f, 0xcb, 0xf4, 0xe2, 0xfe, 0xff, 0x3e, 0xff, 0x15, + 0xc6, 0xf2, 0x31, 0xf9, 0x2a, 0xc8, 0x05, 0x4e, 0x7c, 0x2e, + 0x92, 0xc8, 0x41, 0x4f, 0x9e, 0x23, 0x21, 0x4d, 0x74, 0xf8, + 0xc3, 0x44, 0x39, 0xc2, 0x69, 0x4b, 0x2e, 0x76, 0x5e, 0x44, + 0x12, 0x65, 0x31, 0x98, 0xbe, 0x0a, 0x10, 0x11, 0x12, 0x2c, + 0x67, 0x3d, 0x85, 0x2e, 0xd3, 0x97, 0x54, 0x1e, 0xb6, 0xad, + 0xd9, 0x45, 0x11, 0x53, 0x04, 0x7c, 0x3f, 0xf4, 0xc9, 0xac, + 0x82, 0x1b, 0x84, 0xf4, 0x20, 0x6b, 0xf1, 0xf5, 0x72, 0x04, + 0x24, 0xc1, 0xd3, 0x42, 0x43, 0x52, 0x9d, 0x2d, 0xd3, 0x89, + 0x8e, 0xd8, 0x28, 0xb9, 0xa2, 0xb4, 0xed, 0xbc, 0x76, 0x87, + 0x55, 0x67, 0x39, 0xd9, 0xb7, 0x20, 0x6a, 0xec, 0xec, 0xb8, + 0x14, 0x51, 0x91, 0xb9, 0x96, 0x0f, 0x7a, 0x3a, 0x12, 0xde, + 0x14, 0x3b, 0x83, 0xcf, 0x41, 0x5b, 0x5d, 0xff, 0x33, 0x68, + 0xdb, 0x53, 0x64, 0x93, 0xb1, 0xc3, 0x8a, 0x46, 0xa8, 0x44, + 0x9c, 0x14, 0x12, 0x6c, 0x92, 0x6f, 0xae, 0xc3, 0x45, 0xb2, + 0xa1, 0x67, 0x81, 0x3c, 0x22, 0x47, 0xfd, 0xa4, 0x7a, 0x79, + 0xa8, 0x0a, 0xfb, 0x7a, 0x91, 0x6e, 0xe9, 0x53, 0xec, 0x98, + 0x82, 0x57, 0xad, 0x05, 0x38, 0x55, 0xc1, 0xce, 0x3a, 0x04, + 0x4d, 0x12, 0x72, 0x37, 0x4a, 0x36, 0x54, 0x3f, 0x67, 0x8a, + 0xee, 0xd9, 0xf3, 0x80, 0xd5, 0xd7, 0xb8, 0xfc, 0x6e, 0x4f, + 0x60, 0x2b, 0x5a, 0xa4, 0xc5, 0x05, 0xdb, 0xe5, 0x09, 0xe3, + 0xeb, 0xa2, 0x51, 0x33, 0x30, 0x96, 0x46, 0x01, 0x26, 0x8f, + 0x38, 0xc9, 0x97, 0x32, 0x2d, 0xb4, 0x59, 0x15, 0x15, 0x38, + 0x66, 0x66, 0xfe, 0xcb, 0xee, 0xc1, 0xf6, 0x4e, 0xb7, 0xdf, + 0x7b, 0x63, 0xe6, 0x3f, 0xe0, 0x1c, 0x97, 0xed, 0x86, 0xf3, + 0xd2, 0xad, 0x42, 0x29, 0x20, 0x28, 0xa6, 0x59, 0x58, 0x7d, + 0x8f, 0x5c, 0x43, 0x07, 0xd1, 0x7e, 0x83, 0xba, 0x9c, 0x1b, + 0xfe, 0x17, 0x9e, 0xc8, 0x09, 0x63, 0x9a, 0x2d, 0x61, 0x33, + 0x51, 0x46, 0x01, 0xa8, 0xe9, 0x43, 0x1e, 0x4e, 0xfe, 0x61, + 0x1a, 0x28, 0x11, 0x65, 0x70, 0x43, 0x9f, 0xfc, 0x21, 0x1d, + 0x76, 0x7b, 0x40, 0x08, 0x18, 0xd3, 0xe8, 0xc2, 0xe3, 0x8c, + 0xe7, 0x27, 0xc2, 0xec, 0xb0, 0x08, 0x3e, 0x6b, 0x8f, 0x77, + 0x6d, 0x9e, 0xa6, 0xab, 0xce, 0x9a, 0xf8, 0x8f, 0x77, 0xb3, + 0xf4, 0xe8, 0x8b, 0xe7, 0xd9, 0xa1, 0x95, 0x40, 0x6b, 0xca, + 0x21, 0x98, 0xff, 0xdc, 0xdc, 0x96, 0xc3, 0x08, 0x81, 0x72, + 0x9a, 0xdd, 0xe2, 0xcf, 0x95, 0x99, 0xa6, 0xa3, 0x5e, 0x9e, + 0x25, 0x60, 0xa3, 0xc3, 0x39, 0xf7, 0x54, 0x6c, 0xf2, 0x75, + 0xa9, 0x38, 0x12, 0x38, 0x4d, 0x42, 0xe8, 0xec, 0x13, 0x25, + 0xa0, 0xf8, 0x04, 0xb8, 0xf6, 0x66, 0x0b, 0x56, 0xe1, 0xfb, + 0x26, 0x03, 0xe6, 0xa5, 0xf1, 0x4d, 0x7f, 0xa5, 0x9d, 0x58, + 0x71, 0xd8, 0xc7, 0x6a, 0xbe, 0xdc, 0x90, 0x89, 0xb1, 0x36, + 0xb4, 0xb6, 0xb4, 0xbb, 0xaf, 0x6e, 0x43, 0x10, 0xa6, 0xea, + 0xee, 0x12, 0xcb, 0x08, 0x2c, 0x4e, 0x66, 0xf0, 0x1f, 0xf4, + 0xbf, 0xd3, 0xeb, 0x63, 0x48, 0xd0, 0xbe, 0x8a, 0xed, 0x24, + 0xdb, 0x0f, 0x23, 0x1d, 0x2e, 0x30, 0x97, 0x0f, 0xd8, 0xc6, + 0x3b, 0x04, 0x2f, 0x33, 0x78, 0x20, 0x6e, 0xb1, 0x33, 0x03, + 0x27, 0xac, 0x0a, 0x37, 0x15, 0x31, 0xef, 0x4d, 0x43, 0xcc, + 0xa0, 0x49, 0x80, 0xe3, 0x8c, 0xc0, 0xf3, 0xf7, 0x2d, 0x37, + 0x1d, 0xd3, 0x90, 0x5f, 0xad, 0x31, 0xb5, 0x95, 0x17, 0x69, + 0x4b, 0xec, 0x84, 0x9d, 0x2b, 0x8d, 0xdd, 0x9b, 0x58, 0x04, + 0xba, 0x28, 0x0e, 0x28, 0xc1, 0x54, 0x6c, 0xb0, 0x25, 0x0c, + 0x4f, 0x98, 0x47, 0xf7, 0x93, 0xc2, 0xae, 0x2f, 0x6d, 0x29, + 0x9c, 0x3d, 0xe3, 0xb5, 0xe3, 0x28, 0x43, 0x14, 0xe6, 0x92, + 0x4c, 0x79, 0x90, 0x59, 0x75, 0x77, 0x56, 0x43, 0xda, 0xac, + 0xa9, 0x42, 0xd7, 0xca, 0x95, 0x73, 0x26, 0x54, 0x1f, 0x3a, + 0x8a, 0x37, 0x64, 0xd7, 0xcf, 0xe1, 0x31, 0xf7, 0x40, 0x59, + 0xfd, 0xff, 0xea, 0x72, 0xfd, 0xc4, 0xde, 0xe3, 0x4d, 0x8a, + 0xf5, 0x80, 0xc0, 0x61, 0x21, 0xbd, 0xbd, 0x8e, 0x42, 0xd5, + 0x4c, 0xe4, 0xf4, 0x78, 0x31, 0xca, 0xf1, 0xec, 0x7c, 0x7b, + 0x85, 0x6a, 0x05, 0x54, 0xbe, 0x38, 0x54, 0x2f, 0x1f, 0xda, + 0x9f, 0x98, 0xe2, 0x79, 0xd7, 0x42, 0xca, 0xba, 0x85, 0x21, + 0xe2, 0xcb, 0x2b, 0xae, 0x4a, 0x4e, 0x35, 0xfb, 0xcf, 0x3d, + 0xc5, 0xae, 0x27, 0x30, 0xa9, 0x45, 0xe6, 0x3b, 0x43, 0x3e, + 0x35, 0xe3, 0xf2, 0x0d, 0x53, 0x32, 0x2b, 0xf6, 0xe6, 0xc7, + 0xd5, 0x02, 0x82, 0x03, 0xc1, 0x00, 0xd4, 0x04, 0x9b, 0xef, + 0x5d, 0x58, 0xb0, 0xa3, 0xaa, 0xd2, 0xab, 0x53, 0x65, 0x99, + 0x03, 0x49, 0x48, 0x4d, 0xf5, 0xdf, 0x5d, 0x16, 0x14, 0x11, + 0x60, 0x45, 0x1b, 0xff, 0x4a, 0x60, 0x2b, 0x37, 0x63, 0xf6, + 0xa7, 0x8a, 0xa8, 0xff, 0x08, 0x97, 0x08, 0xfc, 0xbb, 0xb3, + 0x20, 0xa3, 0xcd, 0xd9, 0x58, 0xdb, 0x16, 0x1b, 0x88, 0x02, + 0x1e, 0x0f, 0x43, 0x9b, 0x16, 0x7e, 0xbe, 0xb1, 0x9c, 0x13, + 0x10, 0xdc, 0xa1, 0x56, 0xff, 0xa3, 0xff, 0x5e, 0x69, 0x30, + 0xee, 0x7e, 0x76, 0x5f, 0x84, 0x94, 0xeb, 0x8f, 0x58, 0xf8, + 0xcf, 0xbb, 0x99, 0x6e, 0xf0, 0xd8, 0x32, 0xf6, 0xce, 0x48, + 0x6f, 0x7c, 0xc8, 0x8f, 0xd3, 0x86, 0x22, 0x49, 0x9f, 0xde, + 0x11, 0x05, 0xa4, 0xdc, 0x92, 0xfb, 0x0f, 0xfa, 0x09, 0x4d, + 0x17, 0x1a, 0xe2, 0x76, 0x67, 0x40, 0xa9, 0x5b, 0x1b, 0x54, + 0x66, 0x48, 0xf7, 0xc3, 0x59, 0xd4, 0xcf, 0x55, 0xd0, 0x7f, + 0x3b, 0xb0, 0xa2, 0xd8, 0xec, 0xb7, 0x88, 0xe7, 0xb0, 0x30, + 0x72, 0x42, 0x65, 0xe2, 0x91, 0xa7, 0x9b, 0xf6, 0x07, 0x45, + 0x52, 0x51, 0xaa, 0xbe, 0x32, 0x35, 0xe4, 0x88, 0x23, 0xe7, + 0xcb, 0x3c, 0x1c, 0xfb, 0x0b, 0x96, 0xd5, 0xb3, 0x92, 0x86, + 0x79, 0x5b, 0x47, 0x93, 0xd6, 0xbd, 0xc7, 0x21, 0x17, 0xd0, + 0xc9, 0xc7, 0x69, 0x84, 0x80, 0x98, 0xaf, 0x2c, 0x63, 0xd1, + 0xef, 0x6e, 0xca, 0x84, 0x30, 0x32, 0x83, 0x2d, 0x49, 0xbb, + 0x1f, 0x2a, 0xfe, 0x40, 0x7c, 0x03, 0xd4, 0x45, 0xdc, 0xfe, + 0x94, 0xf9, 0xe4, 0x36, 0x47, 0xfa, 0x7e, 0x2e, 0x93, 0x03, + 0xf8, 0x15, 0xf9, 0xce, 0xc3, 0x5b, 0x76, 0x10, 0xec, 0x89, + 0x8c, 0xce, 0x25, 0xa5, 0x77, 0x9a, 0xc5, 0x1e, 0xdd, 0x07, + 0x1b, 0x5b, 0xac, 0x6f, 0xdb, 0x94, 0x85, 0xdf, 0x02, 0x22, + 0xd1, 0xa9, 0x01, 0x8e, 0x63, 0xa1, 0xee, 0x94, 0x9c, 0xdb, + 0xb4, 0x1a, 0x43, 0xe1, 0x1f, 0x4e, 0x2f, 0x68, 0x50, 0x0c, + 0x2f, 0x5b, 0xc5, 0x1b, 0xe1, 0x8d, 0x4b, 0xe0, 0x63, 0x8d, + 0x7a, 0x30, 0xbe, 0xb7, 0x2e, 0x02, 0xc6, 0x02, 0xac, 0xa8, + 0xb8, 0x65, 0xc6, 0x28, 0xee, 0xe4, 0xec, 0x99, 0xa1, 0x9a, + 0xfd, 0x1f, 0xb5, 0x85, 0x7a, 0x94, 0x16, 0xe2, 0xe7, 0x74, + 0x06, 0x54, 0x1b, 0xd0, 0xaf, 0x58, 0x4e, 0x50, 0x7e, 0xd6, + 0xe4, 0x31, 0xd2, 0x0c, 0xd7, 0x9d, 0xe2, 0x00, 0x30, 0xbe, + 0x26, 0x30, 0x48, 0x99, 0x98, 0x58, 0x54, 0x5a, 0xc4, 0x0a, + 0x6c, 0xa1, 0x06, 0xe9, 0x38, 0xe6, 0x79, 0x39, 0x00, 0x9e, + 0xb6, 0xe3, 0xf7, 0x01, 0xcf, 0x2f, 0x82, 0x5e, 0xc3, 0x21, + 0x1b, 0x79, 0x93, 0xb5, 0xe4, 0x39, 0x9d, 0x32, 0x9d, 0x72, + 0xa4, 0xa8, 0xc9, 0x90, 0xce, 0xaf, 0xc0, 0x00, 0xad, 0x20, + 0x87, 0x26, 0xc7, 0xd3, 0x5f, 0x2e, 0xf0, 0x5e, 0xf8, 0x8b, + 0x85, 0xa3, 0xc6, 0x66, 0xd8, 0x2f, 0x86, 0xfe, 0x7d, 0x8d, + 0x22, 0xa5, 0x6d, 0x68, 0x3e, 0x87, 0x6e, 0xf7, 0xf1, 0xf0, + 0x07, 0xc4, 0xe3, 0xf1, 0x84, 0xc4, 0x93, 0x42, 0x06, 0x20, + 0x80, 0x64, 0xb3, 0x52, 0x5c, 0xa5, 0xcf, 0xee, 0xfe, 0xa4, + 0x09, 0x41, 0xbe, 0xaa, 0x78, 0x52, 0x76, 0x3f, 0xf7, 0xe8, + 0xa1, 0x6b, 0x0a, 0xbc, 0x22, 0xbe, 0xdf, 0x72, 0x7b, 0xea, + 0x90, 0x43, 0xee, 0xc2, 0x0b, 0x26, 0xdc, 0x02, 0x26, 0xa7, + 0x50, 0x04, 0x7a, 0x06, 0x91, 0xae, 0x93, 0xd5, 0xd2, 0xc9, + 0xa1, 0xe1, 0xfc, 0xb9, 0x8c, 0x94, 0xca, 0xa8, 0x1c, 0x2c, + 0x57, 0x97, 0x3e, 0x50, 0xed, 0x93, 0x45, 0x7a, 0x2c, 0x59, + 0x7b, 0x34, 0x8f, 0xcd, 0xd6, 0x17, 0x93, 0xd8, 0xde, 0xe8, + 0xb0, 0x9e, 0x27, 0x15, 0xc5, 0xbb, 0xa5, 0xbb, 0xc2, 0x30, + 0x9b, 0xc7, 0x27, 0x02, 0x18, 0xd8, 0xdb, 0xa4, 0x84, 0x37, + 0x64, 0xf7, 0xf7, 0xf1, 0xc8, 0x86, 0x4c, 0x64, 0x97, 0x08, + 0xe9, 0x4e, 0x0e, 0xb6, 0x92, 0xe9, 0x4c, 0x7b, 0x7f, 0xe1, + 0xcc, 0xa0, 0x71, 0xa7, 0x34, 0x48, 0x46, 0xbb, 0x37, 0xce, + 0xb0, 0x4d, 0x39, 0xa8, 0x0e, 0xab, 0xf6, 0x2f, 0x7c, 0x88, + 0xae, 0xcf, 0x90, 0xc6, 0x01, 0xd3, 0x5b, 0x37, 0xe9, 0xb1, + 0x28, 0x42, 0x14, 0xbf, 0x59, 0x35, 0x04, 0xab, 0x46, 0x6e, + 0xa8, 0x29, 0xe2, 0x7a, 0x77, 0x0e, 0x07, 0x67, 0xe4, 0x2b, + 0x03, 0xd2, 0x02, 0x36, 0x16, 0xd7, 0x81, 0x5d, 0x38, 0x9c, + 0x68, 0x9c, 0xf5, 0x9e, 0x49, 0x7d, 0x99, 0xfd, 0xcd, 0x1d, + 0xd2, 0xdf, 0x3c, 0x36, 0x19, 0x85, 0xaa, 0xb1, 0x30, 0x7a, + 0x21, 0xb1, 0x83, 0x16, 0xcf, 0xd1, 0x75, 0xa5, 0x9d, 0xd7, + 0xc1, 0x60, 0xa8, 0xdb, 0x1e, 0xb9, 0x3e, 0x9c, 0x12, 0x42, + 0xe8, 0x47, 0x49, 0x18, 0x9f, 0x5c, 0x12, 0xd1, 0x69, 0xd5, + 0x7d, 0xa8, 0x3c, 0xda, 0x35, 0x8a, 0x6c, 0x63, 0xb8, 0x62, + 0x8a, 0x61, 0xfa, 0xf2, 0x61, 0x11, 0x1e, 0xb6, 0xf3, 0x5c, + 0x62, 0x9d, 0xa7, 0x62, 0x0c, 0x87, 0x93, 0xe2, 0x23, 0x6c, + 0x3d, 0xa9, 0x2c, 0x4b, 0xd5, 0x7f, 0xfe, 0x72, 0x27, 0x36, + 0x06, 0xcb, 0x65, 0x38, 0xef, 0x13, 0x57, 0x6a, 0xc9, 0xc6, + 0x4f, 0x51, 0xd0, 0x90, 0x06, 0xa0, 0x23, 0x65, 0x95, 0xce, + 0x16, 0x8f, 0x8d, 0xb2, 0xf9, 0x7f, 0x3c, 0x2c, 0x30, 0x5a, + 0x38, 0xf1, 0x62, 0x79, 0x4b, 0xe5, 0xd7, 0x0a, 0x3f, 0x83, + 0x5f, 0x46, 0x26, 0x97, 0xb7, 0x08, 0x8c, 0x5b, 0xb8, 0x02, + 0x28, 0xf2, 0x4d, 0xdf, 0x93, 0x97, 0xc5, 0x94, 0x4b, 0x0e, + 0x42, 0xc3, 0x35, 0x91, 0x6b, 0x69, 0x61, 0x76, 0x7f, 0x94, + 0xcf, 0x0b, 0x81, 0x33, 0xff, 0xf3, 0x0c, 0xc7, 0x01, 0x94, + 0x94, 0xa9, 0xed, 0xcd, 0x4b, 0xc8, 0xcb, 0x91, 0xf9, 0x7a, + 0x47, 0xcd, 0x79, 0x3c, 0xa6, 0xde, 0x52, 0xd2, 0x47, 0x5c, + 0x10, 0x62, 0xbb, 0xe5, 0x32, 0xde, 0x83, 0xcf, 0xa8, 0x52, + 0xb3, 0xe7, 0xf9, 0xec, 0x17, 0x34, 0xbf, 0x33, 0x5d, 0xb2, + 0x4e, 0x56, 0xf7, 0x29, 0xd9, 0x5c, 0x1b, 0x83, 0x01, 0xbb, + 0xb9, 0x2b, 0x95, 0x52, 0x08, 0xab, 0xa4, 0x51, 0x03, 0xa1, + 0xfb, 0x6a, 0x50, 0xcd, 0xa8, 0x9d, 0x95, 0x6f, 0x7e, 0xb1, + 0x80, 0x1e, 0x9d, 0x81, 0x01, 0x26, 0x41, 0x78, 0x36, 0x3c, + 0x8a, 0x44, 0xf4, 0x98, 0x88, 0x1c, 0x5d, 0x06, 0xd3, 0xd2, + 0xb2, 0x58, 0x7d, 0xa1, 0x45, 0x1b, 0xbf, 0x8c, 0xf6, 0x6a, + 0xfa, 0xfd, 0x08, 0x29, 0x3e, 0x91, 0x57, 0xf1, 0x3d, 0x20, + 0xed, 0x49, 0x6e, 0x9c, 0x46, 0xd5, 0x08, 0x8d, 0x9b, 0xf8, + 0xef, 0xa3, 0x3a, 0x98, 0xcb, 0xb4, 0xcb, 0x5b, 0x30, 0x25, + 0x20, 0xcc, 0x04, 0xa1, 0xeb, 0xeb, 0xee, 0x1b, 0x36, 0x85, + 0xc1, 0x93, 0x16, 0x5a, 0x31, 0xdf, 0xd6, 0x0e, 0x73, 0x9e, + 0x63, 0x6e, 0x96, 0x90, 0x54, 0xd2, 0xc2, 0x53, 0x69, 0x93, + 0xd5, 0x54, 0xca, 0xd8, 0x84, 0xf7, 0x8f, 0x9a, 0xd1, 0x80, + 0x0d, 0x57, 0xa8, 0x26, 0xbe, 0x45, 0x64, 0xd5, 0x2b, 0xbb, + 0x45, 0xb5, 0x08, 0xb9, 0x37, 0x57, 0x02, 0x82, 0x03, 0xc1, + 0x00, 0xd1, 0x30, 0x2e, 0xb7, 0x9b, 0xe7, 0x5d, 0x13, 0x74, + 0x1f, 0x52, 0xf2, 0x02, 0x18, 0xe9, 0x07, 0x87, 0x9e, 0xed, + 0xde, 0x83, 0x92, 0xcf, 0x73, 0x61, 0x21, 0xc4, 0x62, 0x30, + 0x6c, 0xa2, 0x36, 0xbd, 0xe2, 0xc5, 0x19, 0xf6, 0xdf, 0x51, + 0x7b, 0xca, 0xd4, 0xe4, 0x51, 0x83, 0x49, 0x27, 0xdd, 0xbd, + 0xb0, 0x10, 0x79, 0x39, 0xdd, 0x0e, 0x3d, 0x65, 0xad, 0x6d, + 0xa3, 0x95, 0x52, 0x85, 0xdb, 0x18, 0x94, 0x60, 0xaa, 0xc0, + 0xc8, 0x8b, 0xdb, 0xfe, 0xf9, 0xf0, 0x86, 0xf9, 0x33, 0x8a, + 0xd7, 0xbe, 0x8d, 0x43, 0x83, 0x4d, 0xe4, 0x17, 0x2b, 0x46, + 0x54, 0x44, 0x1b, 0xbe, 0x52, 0x64, 0x47, 0x02, 0x6c, 0x4a, + 0x64, 0xb4, 0x3f, 0x21, 0x2f, 0xbb, 0xe3, 0x72, 0x7c, 0x26, + 0x14, 0xdf, 0x80, 0x50, 0xd4, 0x94, 0xe9, 0xc6, 0x7d, 0x71, + 0xd8, 0xaf, 0xfb, 0x74, 0x36, 0x33, 0xbe, 0x58, 0x63, 0xad, + 0xcb, 0xdf, 0xc0, 0x73, 0x9e, 0x19, 0xb0, 0x65, 0xe1, 0xd1, + 0x10, 0x44, 0xf1, 0xf0, 0x08, 0xa3, 0x09, 0x25, 0xeb, 0xd5, + 0xcb, 0xdd, 0x98, 0xdd, 0xbc, 0x09, 0x2c, 0xef, 0xc1, 0x8d, + 0x43, 0x15, 0x41, 0xc2, 0xa1, 0x84, 0x37, 0x70, 0x5a, 0xd5, + 0xf5, 0xb2, 0x6a, 0x1f, 0xbb, 0xcc, 0x30, 0xb9, 0xd9, 0xc7, + 0x36, 0x21, 0xf3, 0x69, 0x3e, 0x91, 0x38, 0x4d, 0xa5, 0xc4, + 0xf7, 0x84, 0x90, 0x34, 0x0e, 0x47, 0x7e, 0x26, 0xf2, 0x98, + 0x25, 0x26, 0xda, 0xf0, 0x4e, 0x55, 0xea, 0x4d, 0x9b, 0x8a, + 0x4a, 0xe1, 0x1f, 0xa0, 0x07, 0x90, 0x9e, 0x59, 0x64, 0xae, + 0xd9, 0xd6, 0x7e, 0x72, 0xa1, 0xc4, 0xea, 0x7d, 0xbd, 0x1f, + 0x7d, 0x2b, 0xd9, 0x2c, 0xdc, 0x8b, 0xc0, 0xda, 0x52, 0x0c, + 0xd1, 0xd0, 0x56, 0xb7, 0x93, 0xc7, 0x26, 0x79, 0x71, 0xd0, + 0x0d, 0xae, 0xaa, 0xa7, 0xe4, 0xc1, 0x59, 0x27, 0x68, 0x97, + 0x9a, 0xff, 0x3d, 0x36, 0x07, 0x55, 0x77, 0x07, 0x97, 0x69, + 0xf3, 0x99, 0x91, 0x3f, 0x63, 0xfd, 0x70, 0x8c, 0xa1, 0xeb, + 0xc5, 0x21, 0xa3, 0xfe, 0x99, 0x96, 0x11, 0x37, 0xb9, 0xe6, + 0x93, 0xf8, 0xd0, 0xb1, 0xa3, 0x57, 0x7a, 0xa8, 0x63, 0xdd, + 0x09, 0x56, 0xb0, 0x3b, 0xa6, 0x59, 0xc7, 0x89, 0x54, 0x16, + 0xe9, 0x2d, 0x78, 0x7d, 0xaf, 0x4e, 0x0a, 0x5b, 0x62, 0x3b, + 0x0b, 0xcb, 0x24, 0x89, 0x4e, 0x1c, 0x3d, 0xe1, 0xbd, 0x5a, + 0x3e, 0xc5, 0xfd, 0x15, 0x3d, 0x08, 0x38, 0x33, 0x5e, 0x37, + 0x4c, 0xe3, 0xe3, 0xe9, 0xc4, 0x1d, 0x2b, 0xd4, 0x58, 0x25, + 0x58, 0x23, 0x8e, 0xc6, 0x83, 0x9a, 0xf3, 0x9a, 0x78, 0xe9, + 0xa7, 0xca, 0xd7, 0xdd, 0x89, 0x20, 0x6e, 0x02, 0xea, 0x6b, + 0x37, 0x74, 0xda, 0xa0, 0xc2, 0x5a, 0x2b, 0x80, 0x1c, 0x28, + 0x91, 0x0d, 0x50, 0x64, 0xf0, 0x12, 0xe7, 0xc4, 0x7e, 0xdd, + 0x28, 0x3b, 0x26, 0x9a, 0xf4, 0x39, 0x56, 0xa4, 0x72, 0x4d, + 0xcb, 0x67, 0x3c, 0x68, 0xb2, 0x6f, 0xf0, 0xd0, 0x15, 0x90, + 0xc8, 0x08, 0xbb, 0x0b, 0x08, 0x6b, 0x8a, 0xde, 0x41, 0x57, + 0xbc, 0x63, 0x0e, 0x00, 0x8d, 0xf8, 0xdd, 0x93, 0xce, 0x58, + 0x7b, 0xa8, 0xb9, 0x64, 0x26, 0x06, 0xe7, 0x71, 0x23, 0x0f, + 0x41, 0xf1, 0xb7, 0xae, 0x59, 0x2e, 0xd0, 0x73, 0xc5, 0xd9, + 0xdc, 0x0e, 0x1c, 0x02, 0x58, 0x69, 0xb3, 0x15, 0x6d, 0x96, + 0x2b, 0xdb, 0x7b, 0x3b, 0x6c, 0x38, 0x32, 0x6b, 0xd8, 0x08, + 0xb2, 0xbd, 0xa7, 0x49, 0x43, 0xeb, 0x90, 0x42, 0x70, 0xc5, + 0xba, 0xcd, 0x4a, 0x44, 0x8f, 0x83, 0x0d, 0x17, 0x51, 0x5a, + 0x95, 0xa2, 0x57, 0x9a, 0x16, 0x19, 0x91, 0xbb, 0x90, 0x5c, + 0x2a, 0x16, 0xe8, 0x26, 0x10, 0x3c, 0xb7, 0x10, 0x5c, 0xf8, + 0xc5, 0x15, 0x2b, 0x70, 0x75, 0x69, 0xba, 0x7b, 0x3d, 0x0b, + 0x57, 0xac, 0x39, 0x12, 0x2e, 0xd6, 0xd9, 0x13, 0x74, 0x8e, + 0xa8, 0x0b, 0x17, 0xe1, 0x03, 0x7a, 0xba, 0x1d, 0x07, 0x91, + 0x8c, 0x2a, 0x3a, 0x8d, 0xe0, 0x2a, 0x94, 0xd4, 0x16, 0x35, + 0x64, 0x8b, 0x92, 0x2c, 0x2f, 0xa4, 0x18, 0xfe, 0x3f, 0x02, + 0x19, 0x8c, 0xb9, 0xeb, 0xaf, 0x01, 0x06, 0xa8, 0x37, 0x7f, + 0xe2, 0x44, 0x10, 0xce, 0xeb, 0x8d, 0xd0, 0x73, 0xc4, 0x1e, + 0x3d, 0x2c, 0xaf, 0x77, 0xb2, 0xef, 0xe5, 0x95, 0x8b, 0xdf, + 0x02, 0xfc, 0x93, 0xb8, 0xa9, 0x27, 0x88, 0x1d, 0x1d, 0x82, + 0x9f, 0xb6, 0xe4, 0x12, 0x05, 0x79, 0xb6, 0x1c, 0x41, 0x0d, + 0xc1, 0x53, 0x49, 0x8f, 0x3d, 0xc9, 0xad, 0x84, 0xcb, 0x0b, + 0x88, 0x7e, 0xfe, 0x73, 0x59, 0x21, 0x64, 0xc5, 0x50, 0x53, + 0xdc, 0x98, 0xc6, 0x43, 0xb8, 0xf5, 0xc3, 0xa1, 0xf5, 0xb2, + 0xd8, 0x86, 0xe9, 0xae, 0x98, 0xf9, 0x3b, 0x99, 0xc0, 0xe7, + 0xd7, 0x4a, 0xed, 0xac, 0x89, 0x84, 0xb0, 0x8e, 0xd3, 0xab, + 0xec, 0x03, 0x02, 0x12, 0x4b, 0x44, 0x17, 0x4d, 0x98, 0x26, + 0x1e, 0x51, 0xc5, 0xbb, 0xcd, 0xdc, 0x50, 0xab, 0x83, 0x37, + 0x49, 0x90, 0x1e, 0x34, 0xad, 0x81, 0x22, 0x6c, 0xe4, 0xdd, + 0x19, 0x01, 0x09, 0x25, 0x2d, 0x9e, 0x52, 0x90, 0x72, 0xa1, + 0x68, 0x3d, 0x0c, 0x49, 0x99, 0x19, 0x75, 0x5a, 0xca, 0x08, + 0x69, 0xa1, 0xd2, 0x88, 0x8c, 0xea, 0xcf, 0x9c, 0xbc, 0x23, + 0xad, 0x3f, 0xb9, 0xfc, 0xb9, 0x30, 0x0d, 0xd6, 0xd9, 0x65, + 0x0c, 0x7e, 0x99, 0x68, 0x35, 0x26, 0x07, 0xd1, 0x55, 0xbf, + 0x8e, 0xde, 0xe7, 0xe7, 0x01, 0xcb, 0xca, 0x0a, 0x39, 0x2e, + 0xcc, 0x19, 0xec, 0x77, 0xf3, 0xab, 0xb2, 0xe6, 0x0e, 0x54, + 0x06, 0x01, 0x50, 0x77, 0xd3, 0x61, 0x36, 0x05, 0x90, 0xe4, + 0xd8, 0xc4, 0x1d, 0xf5, 0xc7, 0xfa, 0x65, 0xf0, 0x46, 0x6a, + 0x5f, 0xa7, 0xc3, 0x8c, 0x6f, 0x04, 0x7f, 0xcf, 0x97, 0xb9, + 0x68, 0x92, 0x31, 0x09, 0x02, 0x9f, 0x22, 0xc9, 0xf8, 0xe6, + 0x7e, 0xa8, 0x95, 0x5b, 0x6b, 0xfe, 0x9c, 0x4e, 0x63, 0x2d, + 0x8c, 0x1a, 0x4c, 0x8b, 0x14, 0x79, 0x08, 0xd5, 0x96, 0x76, + 0xd1, 0xb4, 0x2f, 0xae, 0x5d, 0x91, 0x88, 0x7c, 0xdd, 0xd2, + 0x06, 0x86, 0xcf, 0x0a, 0x83, 0x6f, 0xda, 0xca, 0x71, 0x7c, + 0xe7, 0xe5, 0x34, 0xa8, 0x9a, 0x53, 0x8d, 0xa5, 0xaa, 0x5d, + 0xb5, 0x17, 0x81, 0x34, 0x6f, 0xbe, 0xbb, 0xb6, 0x58, 0x22, + 0x90, 0x80, 0xf6, 0x9c, 0x1c, 0xb0, 0x79, 0x8f, 0x92, 0x5b, + 0x7d, 0x1c, 0x71, 0x5f, 0xb4, 0x87, 0x36, 0xbe, 0x81, 0x8d, + 0x4a, 0xfc, 0x28, 0x72, 0x81, 0xaf, 0x5f, 0xbd, 0x5f, 0x99, + 0xe3, 0xc9, 0x37, 0xb0, 0x6e, 0xad, 0x70, 0x96, 0xfa, 0xe3, + 0x99, 0xf7, 0x08, 0x14, 0x21, 0x21, 0xb7, 0x1a, 0xaa, 0xe8, + 0x07, 0xb6, 0xfd, 0xa3, 0x7a, 0x2d, 0x93, 0x64, 0x8f, 0x89, + 0x2c, 0x71, 0x49, 0x71, 0xb8, 0x45, 0xca, 0xe0, 0x7c, 0x00, + 0x8d, 0xbd, 0xb8, 0x1c, 0x3a, 0x94, 0xa2, 0xa7, 0x6d, 0x0a, + 0x2e, 0x84, 0xaf, 0xbd, 0xab, 0x05, 0x95, 0x64, 0x8b, 0x05, + 0xc8, 0xc9, 0x4e, 0xea, 0xb5, 0x96, 0x4a, 0x47, 0xdd, 0xf2, + 0xcb, 0x02, 0x82, 0x03, 0xc0, 0x59, 0xb3, 0xd9, 0x85, 0xdc, + 0xa8, 0xb9, 0x93, 0x85, 0xa2, 0xbc, 0x79, 0xfc, 0x72, 0x50, + 0xc1, 0xa0, 0xa5, 0xdb, 0x71, 0x35, 0xa1, 0x31, 0xbc, 0x68, + 0x4e, 0xd5, 0x19, 0x9e, 0x0e, 0x32, 0x3a, 0xad, 0x40, 0x9e, + 0x82, 0x3c, 0x1e, 0x2b, 0x34, 0x3b, 0xc9, 0x32, 0x61, 0x07, + 0x5e, 0x46, 0xa9, 0xbe, 0xbe, 0x73, 0x0c, 0x12, 0xef, 0x52, + 0x68, 0x82, 0xe2, 0x0b, 0x12, 0x74, 0xfc, 0x10, 0x5c, 0xc0, + 0xb5, 0x98, 0x4d, 0x86, 0xbb, 0x8c, 0x40, 0x15, 0xa1, 0x6e, + 0x46, 0x73, 0x2e, 0xd6, 0x99, 0x6b, 0x50, 0xab, 0x04, 0x1a, + 0x5f, 0xf4, 0xfa, 0xcb, 0x4b, 0xad, 0xc4, 0x5e, 0x62, 0xa7, + 0x48, 0xd4, 0x52, 0x85, 0xdc, 0x2a, 0x85, 0x9b, 0xee, 0x08, + 0xa5, 0xaa, 0xaa, 0xe8, 0x44, 0xf0, 0xed, 0x89, 0x21, 0xe4, + 0xb4, 0xab, 0x3c, 0x0d, 0x53, 0x7e, 0x53, 0xdd, 0xac, 0x47, + 0xda, 0x77, 0x79, 0x5f, 0x78, 0x7a, 0x80, 0x84, 0x46, 0x50, + 0xaa, 0xdb, 0x3b, 0x8c, 0x6b, 0xda, 0xb0, 0xac, 0x0a, 0xd3, + 0x4c, 0xe4, 0x6e, 0x87, 0xd1, 0xb2, 0x5a, 0xd5, 0x98, 0xae, + 0xcb, 0x7e, 0xc2, 0x19, 0xdc, 0x53, 0x64, 0x86, 0x4c, 0x7b, + 0xe0, 0x63, 0x22, 0x94, 0x34, 0xad, 0x15, 0xdc, 0xd8, 0xa8, + 0x5f, 0xc6, 0x58, 0xf6, 0x72, 0x34, 0xdd, 0xfb, 0x85, 0x8a, + 0xd9, 0xa3, 0xfb, 0x3b, 0xad, 0x5d, 0xf0, 0x1a, 0x0b, 0xa8, + 0x91, 0xe7, 0x7d, 0x26, 0x27, 0x38, 0xf8, 0xe0, 0x49, 0x1b, + 0x56, 0xc5, 0x5b, 0xe3, 0x1c, 0x7b, 0xa3, 0x53, 0x6d, 0x22, + 0xfa, 0xd7, 0x63, 0x5f, 0xf0, 0xcb, 0x92, 0x49, 0x01, 0x54, + 0xe5, 0x77, 0x5b, 0xd3, 0xab, 0xce, 0xb8, 0x3a, 0x5b, 0xb8, + 0x07, 0x40, 0x46, 0x51, 0xe4, 0x59, 0xa2, 0x45, 0x41, 0xcc, + 0x81, 0x6c, 0xe3, 0xa6, 0xb3, 0xa0, 0x30, 0x4a, 0x67, 0x10, + 0xed, 0xc0, 0x8a, 0xcd, 0xfc, 0xa5, 0x44, 0x9b, 0x59, 0x19, + 0x4a, 0x43, 0x8d, 0xec, 0x00, 0xd8, 0x6d, 0xf9, 0xf0, 0x2d, + 0xd9, 0x55, 0xfc, 0x05, 0xe2, 0x12, 0x48, 0x4d, 0xd6, 0x7d, + 0xec, 0x41, 0xc4, 0x9e, 0xe2, 0xed, 0x84, 0x14, 0x29, 0x0e, + 0x5b, 0x81, 0x0b, 0xb0, 0x87, 0x8a, 0xd3, 0x35, 0x5c, 0xad, + 0xdb, 0xcc, 0xa1, 0x3c, 0xcb, 0x8b, 0x23, 0x55, 0x69, 0xf1, + 0x83, 0x84, 0x81, 0x36, 0xae, 0xd5, 0xf3, 0x98, 0xb6, 0xb2, + 0xb5, 0xa1, 0x79, 0x6d, 0x80, 0x8f, 0x2e, 0x25, 0x71, 0x4e, + 0x16, 0xff, 0xa0, 0x7c, 0xa4, 0x62, 0x8c, 0x44, 0x85, 0x64, + 0x90, 0x7c, 0xac, 0x10, 0x36, 0xf2, 0xf2, 0xfb, 0x20, 0x2b, + 0xa1, 0x27, 0xd0, 0xcc, 0x27, 0xfd, 0xb0, 0xba, 0x3e, 0x37, + 0xb1, 0xa8, 0x9d, 0x3c, 0x82, 0x63, 0xd0, 0x16, 0x6d, 0x7a, + 0xdd, 0x2e, 0xea, 0xe5, 0x87, 0xd6, 0x64, 0x72, 0xdb, 0x60, + 0x53, 0x38, 0x18, 0x66, 0x1d, 0x25, 0xf6, 0x08, 0x92, 0x7f, + 0x68, 0x5b, 0x79, 0x07, 0xde, 0x93, 0xee, 0xf8, 0x8f, 0xce, + 0x28, 0xcf, 0xb1, 0x5b, 0x43, 0x51, 0xdf, 0xf5, 0xac, 0xe8, + 0x9c, 0x95, 0x14, 0x8a, 0x67, 0xe1, 0x25, 0xfe, 0x11, 0xa2, + 0x40, 0xf8, 0xdd, 0xcf, 0xf5, 0x17, 0x94, 0xb6, 0x88, 0x10, + 0xa2, 0x90, 0x58, 0xef, 0xaf, 0x73, 0xf8, 0x7c, 0x9b, 0x20, + 0x30, 0x79, 0xca, 0x3f, 0xa9, 0x22, 0x40, 0xfd, 0xcc, 0xb0, + 0x5d, 0x0d, 0x97, 0x6b, 0xc0, 0x75, 0x35, 0x33, 0xc5, 0x76, + 0x45, 0x6e, 0x9b, 0x78, 0xe7, 0xb4, 0x04, 0xb3, 0xba, 0x3b, + 0x93, 0xb1, 0xa9, 0x8f, 0xa1, 0x24, 0x5d, 0x1c, 0x0e, 0x66, + 0xc0, 0xc6, 0xcc, 0xd6, 0xb7, 0x88, 0x9d, 0xb8, 0x45, 0xe3, + 0xaa, 0xc9, 0x6c, 0xfd, 0x37, 0xdc, 0x85, 0xd5, 0x49, 0xfd, + 0xef, 0xeb, 0xf9, 0x7a, 0x3f, 0x7a, 0x4f, 0x86, 0x49, 0xaa, + 0x9f, 0x08, 0x12, 0x0b, 0x11, 0x35, 0x5c, 0xd5, 0xd3, 0xda, + 0x14, 0x50, 0x03, 0x2c, 0x24, 0x26, 0x0e, 0x29, 0x18, 0xcc, + 0x1d, 0x0a, 0x7c, 0x94, 0x8b, 0xc0, 0xa0, 0x3f, 0xea, 0xf8, + 0xf8, 0xa9, 0x1d, 0x65, 0x31, 0x6f, 0x3b, 0xa6, 0xd0, 0xfc, + 0x26, 0xb0, 0x4e, 0x3a, 0x66, 0xe7, 0x32, 0x10, 0x2e, 0x84, + 0x47, 0xad, 0xa9, 0x18, 0xfc, 0xa3, 0x8b, 0x74, 0x84, 0x4f, + 0xd4, 0x25, 0x93, 0x0f, 0xdb, 0x2e, 0xae, 0x88, 0x8e, 0x28, + 0xf8, 0x0f, 0xaa, 0x60, 0xd4, 0xbe, 0xad, 0x66, 0x0c, 0x0d, + 0x01, 0xbd, 0x8d, 0xc4, 0xfc, 0x48, 0xef, 0x78, 0x14, 0x34, + 0xee, 0xb3, 0xbc, 0xd4, 0xbb, 0x1f, 0x7c, 0x12, 0x5c, 0x9b, + 0xeb, 0x77, 0x3e, 0x2c, 0x6e, 0x31, 0x59, 0xe6, 0x78, 0xc5, + 0xe8, 0xa4, 0xdd, 0xf1, 0xef, 0x5d, 0x27, 0x45, 0x31, 0x13, + 0xd0, 0x21, 0xa1, 0x13, 0xce, 0xac, 0x7e, 0xbb, 0xfb, 0x32, + 0xeb, 0x76, 0x31, 0xc4, 0xba, 0xdf, 0xfb, 0x5a, 0x1b, 0xc9, + 0x9e, 0x74, 0xa0, 0x9e, 0x26, 0x82, 0xd5, 0x6e, 0x1d, 0xc3, + 0x0e, 0xd1, 0x6d, 0xdb, 0x43, 0xb3, 0x0b, 0x14, 0xcb, 0xf1, + 0xad, 0x62, 0x34, 0x49, 0xb8, 0xd3, 0x08, 0xca, 0x93, 0xf1, + 0x42, 0xb2, 0x4b, 0x23, 0x79, 0x93, 0xde, 0x18, 0x58, 0xf3, + 0x66, 0xfa, 0xdc, 0xab, 0xca, 0x33, 0x22, 0x2b, 0x5c, 0x8c, + 0x12, 0xc1, 0x7b, 0x2e, 0x52, 0x72, 0xa7, 0x78, 0x4a, 0x49, + 0xa1, 0x53, 0x02, 0x76, 0x2d, 0x2e, 0xf8, 0x43, 0x3c, 0xe8, + 0xfa, 0xb7, 0xff, 0x39, 0xed, 0x74, 0x9e, 0x11, 0x61, 0x33, + 0xde, 0x2a, 0x55, 0xe6, 0x4a, 0xe7, 0x97, 0xa6, 0xb2, 0xc3, + 0x40, 0x41, 0x52, 0x66, 0xcf, 0xbf, 0xf8, 0x8e, 0x08, 0xea, + 0x96, 0x4d, 0x03, 0xc9, 0xbe, 0x3c, 0x4e, 0x36, 0x8c, 0x6f, + 0x4d, 0x1e, 0xcd, 0x31, 0x6d, 0x53, 0xea, 0x9e, 0xf0, 0x8e, + 0x35, 0x97, 0x37, 0x54, 0xe9, 0x0f, 0xb8, 0x23, 0x25, 0x69, + 0x5b, 0xb5, 0xff, 0xc3, 0x5a, 0x2d, 0x10, 0x6a, 0xc0, 0xb8, + 0xee, 0x0d, 0x31, 0x5b, 0xe4, 0x69, 0x40, 0x62, 0xa7, 0x1b, + 0x16, 0xfa, 0xd6, 0xb8, 0xba, 0xc8, 0x6a, 0xa3, 0x29, 0xdd, + 0x9b, 0x4d, 0xd7, 0x96, 0xef, 0x31, 0x74, 0xac, 0x37, 0x10, + 0x91, 0x30, 0x0c, 0x15, 0x3f, 0x09, 0xb6, 0x7d, 0x22, 0xfb, + 0x8c, 0x6f, 0xc3, 0x93, 0xa3, 0x98, 0xa6, 0x23, 0xa4, 0x55, + 0xe0, 0x9e, 0x23, 0x06, 0xa9, 0x78, 0xe9, 0xb3, 0x88, 0xc9, + 0xb7, 0x83, 0x05, 0x46, 0x11, 0x3a, 0x0a, 0xb9, 0x74, 0x5b, + 0xa0, 0xb5, 0x06, 0x96, 0x86, 0xb6, 0xf4, 0x9d, 0x0d, 0x86, + 0x43, 0xa8, 0x40, 0x4b, 0x08, 0x93, 0x7c, 0xad, 0xb0, 0x50, + 0xb4, 0xd0, 0xe7, 0xad, 0xd0, 0x54, 0x5e, 0x15, 0xaf, 0xad, + 0x34, 0x12, 0x86, 0xb3, 0x29, 0x3b, 0x20, 0xc9, 0xad, 0xeb, + 0xc2, 0x65, 0xf3, 0x5c, 0x2d, 0xe5, 0xff, 0xfd, 0x81, 0x79, + 0xf5, 0x11, 0x6f, 0xf7, 0xca, 0x0c, 0x76, 0xf0, 0xd4, 0x02, + 0x9d, 0xb7, 0x76, 0x39, 0x6d, 0x32, 0x6a, 0xb8, 0x30, 0xa4, + 0x01, 0xcc, 0x10, 0xef, 0xb1, 0x0e, 0x41, 0x22, 0x82, 0x5b, + 0x22, 0xcb, 0x32, 0x19, 0x2e, 0xa3, 0x0a, 0xce, 0x05, 0xdd, + 0xe8, 0x4a, 0x58, 0x92, 0xe1, 0x02, 0x82, 0x03, 0xc0, 0x22, + 0x0f, 0x95, 0x5b, 0xc2, 0x1f, 0xde, 0xf0, 0xde, 0xf4, 0x86, + 0xbd, 0xef, 0x07, 0x7d, 0x52, 0x03, 0x8c, 0x26, 0x31, 0x17, + 0xfd, 0x5c, 0x97, 0xed, 0xd5, 0xe0, 0xb3, 0x18, 0x2d, 0x68, + 0x10, 0x3f, 0xc4, 0xdf, 0xd1, 0x05, 0x78, 0x81, 0x3d, 0x05, + 0xde, 0xba, 0x3a, 0x67, 0x85, 0x0e, 0xdf, 0xb5, 0x16, 0x28, + 0xe8, 0x84, 0x3a, 0x71, 0x2a, 0x20, 0x17, 0x28, 0x05, 0xfd, + 0xb7, 0x4d, 0x22, 0x4a, 0x93, 0x46, 0x56, 0x27, 0x43, 0xc0, + 0x3a, 0x16, 0xff, 0x3d, 0x61, 0xcc, 0xcb, 0xce, 0xac, 0xa8, + 0x53, 0x3a, 0x0d, 0xf4, 0x2d, 0xd2, 0x73, 0xf2, 0x64, 0xa0, + 0x1e, 0x60, 0x53, 0xec, 0x0d, 0xff, 0xe0, 0x00, 0x10, 0xfb, + 0xa4, 0x57, 0xd3, 0xfc, 0xe4, 0xe0, 0xec, 0x44, 0x0b, 0x1c, + 0x05, 0x39, 0xa4, 0x13, 0x87, 0x29, 0x11, 0x9d, 0xea, 0xe9, + 0x64, 0xa9, 0x1c, 0x76, 0x3a, 0x65, 0x0b, 0xfd, 0xed, 0x77, + 0x46, 0x4f, 0xcd, 0x0b, 0x63, 0xc4, 0x83, 0x0b, 0x56, 0x79, + 0xd3, 0x67, 0x01, 0x11, 0x02, 0xd9, 0x50, 0xd8, 0x23, 0xf4, + 0xb6, 0x02, 0x4c, 0xae, 0xb5, 0xc9, 0x68, 0x1b, 0x87, 0x33, + 0xbb, 0xdc, 0x64, 0x0e, 0x32, 0x34, 0xb2, 0x25, 0xaa, 0x76, + 0xdd, 0x7e, 0xc3, 0x46, 0x51, 0x1c, 0xc1, 0xd0, 0x05, 0x09, + 0x6c, 0x27, 0xd3, 0xcf, 0x33, 0x7a, 0xb9, 0x26, 0x24, 0x23, + 0x4a, 0x93, 0x9f, 0x4b, 0x96, 0xc7, 0xe2, 0xb2, 0x51, 0x42, + 0x4d, 0x5d, 0xd9, 0x73, 0x75, 0xce, 0x23, 0x28, 0x56, 0x5e, + 0xe7, 0x96, 0x58, 0x04, 0xfd, 0x33, 0x93, 0x08, 0x41, 0x62, + 0x02, 0x7e, 0xc9, 0xc6, 0x55, 0x64, 0x19, 0xda, 0x39, 0xb8, + 0x5d, 0x09, 0x47, 0xf3, 0xdd, 0x77, 0xee, 0xea, 0x35, 0x73, + 0x95, 0xdb, 0x18, 0x4d, 0xd1, 0xfe, 0xee, 0x40, 0x31, 0x2a, + 0x22, 0x91, 0x69, 0xd6, 0xed, 0x9c, 0x54, 0x14, 0x73, 0x61, + 0x61, 0xe7, 0x1d, 0x34, 0x96, 0x47, 0xff, 0x28, 0x7a, 0x48, + 0xa3, 0xf4, 0xcd, 0x64, 0x23, 0xe2, 0x52, 0x2f, 0x20, 0x8f, + 0x04, 0xb3, 0xdc, 0xf0, 0x29, 0x67, 0x88, 0x76, 0x79, 0xdb, + 0x86, 0xa7, 0x95, 0xf0, 0x15, 0x81, 0xbb, 0x98, 0xee, 0xff, + 0x55, 0x7c, 0xb0, 0xee, 0x67, 0x65, 0xfd, 0xf2, 0x29, 0x0f, + 0x85, 0x51, 0xf9, 0xac, 0x5c, 0x55, 0x5a, 0xde, 0x40, 0x62, + 0x58, 0x55, 0x9f, 0x09, 0x4c, 0x2e, 0x28, 0x75, 0xbc, 0x48, + 0xe2, 0x97, 0x85, 0xb3, 0x83, 0xeb, 0x21, 0x49, 0x21, 0xd4, + 0xed, 0x74, 0x4f, 0xc1, 0x6c, 0x34, 0x8c, 0x11, 0xb0, 0x93, + 0x41, 0x99, 0x23, 0x2e, 0xa4, 0xc1, 0x9f, 0x34, 0x74, 0x64, + 0xbb, 0xd7, 0x4f, 0x8f, 0x9f, 0x3a, 0x0c, 0x4f, 0x5e, 0xdd, + 0x41, 0x07, 0xf1, 0xfd, 0x5a, 0x9d, 0xe6, 0x77, 0xd8, 0x7e, + 0x71, 0x7b, 0xad, 0xf7, 0x76, 0x13, 0x71, 0x90, 0xb3, 0x0f, + 0x46, 0x8e, 0xee, 0x7b, 0x33, 0x97, 0x5d, 0x21, 0x3b, 0xa0, + 0x58, 0x9e, 0xb7, 0x87, 0x30, 0x8f, 0xc1, 0x23, 0x2c, 0xde, + 0xf7, 0x0d, 0xa9, 0xd6, 0x50, 0xeb, 0x35, 0x7a, 0x82, 0xab, + 0x22, 0x49, 0x86, 0xd4, 0x61, 0xc7, 0xc2, 0x4e, 0x77, 0xfc, + 0x16, 0x0b, 0xaf, 0x81, 0x6a, 0x47, 0xea, 0xac, 0x7e, 0x51, + 0x4c, 0x56, 0x30, 0x21, 0x46, 0x41, 0xc3, 0x92, 0x60, 0x99, + 0x4f, 0x88, 0x36, 0x3b, 0x27, 0xb4, 0xb2, 0x7e, 0x44, 0x2f, + 0xdd, 0x95, 0xe4, 0x5e, 0x16, 0x1f, 0xa7, 0x32, 0x6b, 0x60, + 0x24, 0x0f, 0xf2, 0xe6, 0x35, 0x3c, 0x0c, 0x3e, 0xb5, 0xd6, + 0xdd, 0x63, 0xe2, 0x76, 0x35, 0x38, 0x79, 0xbf, 0xa5, 0x23, + 0xa4, 0xdd, 0xeb, 0x01, 0x48, 0xd0, 0x60, 0x86, 0x11, 0x38, + 0x5f, 0x9e, 0x6b, 0x00, 0x67, 0xd2, 0x5b, 0x41, 0x0a, 0x5e, + 0x13, 0x0f, 0xa1, 0x9e, 0x90, 0x85, 0xa6, 0x7f, 0xe5, 0x4b, + 0x9e, 0x93, 0x4e, 0x5b, 0x1f, 0x47, 0x62, 0xb0, 0x23, 0xbe, + 0x82, 0xa9, 0xd9, 0xb6, 0x2e, 0xfd, 0xb1, 0x10, 0xca, 0xe0, + 0xc9, 0x5d, 0xf6, 0x85, 0x18, 0x6c, 0x9c, 0x1d, 0x1f, 0x7c, + 0xf6, 0x55, 0x09, 0x80, 0xcf, 0xac, 0xfe, 0x37, 0x6a, 0x4f, + 0x96, 0xaa, 0x40, 0x79, 0x8b, 0x4a, 0xf2, 0x96, 0x79, 0x12, + 0x1a, 0x26, 0x87, 0x06, 0x35, 0x4d, 0xd4, 0x3e, 0x14, 0x39, + 0xe5, 0x6c, 0x39, 0x0f, 0x84, 0xb3, 0x5f, 0xed, 0xf4, 0xff, + 0x89, 0x52, 0x05, 0x00, 0xf1, 0xd1, 0xc3, 0xcf, 0x54, 0x10, + 0x24, 0x7c, 0xa6, 0xb5, 0x95, 0xa8, 0x6e, 0x13, 0x3e, 0x4a, + 0x40, 0x6c, 0xf9, 0x63, 0x90, 0x44, 0x52, 0x07, 0x53, 0xb7, + 0x51, 0xd9, 0x18, 0x47, 0x2e, 0xb0, 0x4e, 0x0f, 0x09, 0x99, + 0x3a, 0x97, 0x26, 0x53, 0xa6, 0x02, 0x06, 0x0e, 0x93, 0xe1, + 0x0b, 0xc5, 0xa9, 0x14, 0xd3, 0xd6, 0x8a, 0x29, 0x75, 0xcd, + 0xb6, 0x7b, 0x64, 0x7c, 0xdd, 0x7e, 0xb4, 0x0a, 0x87, 0x48, + 0x4a, 0x1b, 0x0e, 0x74, 0x4c, 0xd3, 0x0e, 0x96, 0x0e, 0x53, + 0xc4, 0x3d, 0x7b, 0x1c, 0x87, 0x6a, 0x15, 0xd8, 0x77, 0xba, + 0xe6, 0xa0, 0x2f, 0x2c, 0x1a, 0x9d, 0xde, 0x79, 0xfd, 0xab, + 0x44, 0x80, 0xf0, 0x37, 0x9a, 0x3b, 0xf8, 0xde, 0x3d, 0x29, + 0xcb, 0x89, 0x64, 0x4b, 0x57, 0xe7, 0x6b, 0x84, 0x09, 0x27, + 0x17, 0x2f, 0xb2, 0xba, 0x3d, 0x09, 0xc9, 0x3c, 0x89, 0xe6, + 0x19, 0x73, 0x83, 0xf7, 0xc6, 0x19, 0x18, 0x96, 0xb2, 0x7d, + 0x1e, 0x9f, 0x70, 0x1f, 0xfc, 0x1f, 0xe2, 0xb5, 0x69, 0x1e, + 0xf4, 0x65, 0x91, 0xce, 0x4b, 0xdc, 0x74, 0x49, 0x21, 0x64, + 0x8b, 0x33, 0x50, 0xd2, 0xc1, 0x33, 0x62, 0x5b, 0xde, 0x0a, + 0x72, 0xbe, 0xc0, 0x05, 0x51, 0x15, 0x80, 0xed, 0x32, 0x3a, + 0x64, 0xa2, 0x73, 0x68, 0x5b, 0x16, 0xcf, 0x70, 0x5c, 0x98, + 0xe5, 0x67, 0x45, 0x60, 0x57, 0x2b, 0x47, 0x0a, 0x22, 0x73, + 0xc3, 0x56, 0x33, 0x3e, 0x14, 0x1d, 0x0c, 0xd1, 0x03, 0x08, + 0x92, 0x21, 0x2b, 0xa9, 0x6e, 0x6b, 0xf9, 0x0c, 0x1e, 0x86, + 0xdd, 0xb5, 0xbb, 0xa4, 0xa5, 0x82, 0x99, 0x98, 0x49, 0x36, + 0xec, 0x98, 0x98, 0x95, 0xac, 0xc2, 0xa0, 0x1f, 0xa5, 0x7e, + 0x67, 0xd1, 0xcf, 0x6a, 0xf4, 0x16, 0x08, 0x7a, 0x8d, 0x0b, + 0xae, 0x12, 0x51, 0xe6, 0x8e, 0xe6, 0xcd, 0xa1, 0xaa, 0x6d, + 0xe4, 0x54, 0xd4, 0x69, 0x1b, 0x09, 0x6a, 0xba, 0x5e, 0x0b, + 0x11, 0x9c, 0x83, 0xb3, 0x5c, 0x67, 0xbb, 0x2d, 0xf8, 0x66, + 0x1c, 0x33, 0xb8, 0x22, 0x58, 0x10, 0x96, 0xe9, 0x99, 0xaf, + 0x0b, 0x2a, 0xf1, 0xe0, 0xcb, 0x56, 0xfb, 0x6d, 0x04, 0x40, + 0xec, 0x37, 0x67, 0x1e, 0x08, 0x7a, 0x1c, 0xe9, 0xd8, 0x54, + 0xf7, 0xd4, 0xc7, 0x3c, 0x45, 0x23, 0x2b, 0x76, 0xd2, 0x62, + 0xc2, 0x53, 0xce, 0xfe, 0x02, 0xc4, 0xd9, 0xf6, 0x3c, 0xed, + 0x49, 0x47, 0x21, 0xf9, 0x03, 0x3a, 0xa0, 0x16, 0x3a, 0xfe, + 0x0c, 0x2f, 0x54, 0x7e, 0x85, 0x29, 0x7b, 0xc0, 0xaf, 0xa8, + 0x5d, 0x31, 0x25, 0xda, 0xa7, 0xe3, 0x92, 0x1b, 0x64, 0x01, + 0x1b, 0x3f, 0x6e, 0x47, 0xc5, 0x5a, 0x84, 0x52, 0x17, 0x02, + 0x82, 0x03, 0xc1, 0x00, 0x81, 0x99, 0x2e, 0x72, 0x41, 0x6e, + 0x86, 0xeb, 0x6f, 0x42, 0xd1, 0x38, 0x6e, 0xaa, 0x1a, 0xd5, + 0x0a, 0xad, 0x51, 0xb1, 0xce, 0xd6, 0x35, 0xbe, 0x34, 0xd8, + 0xc1, 0xe4, 0x5f, 0xdf, 0x2e, 0xe4, 0x90, 0xf2, 0x61, 0x21, + 0x46, 0xc6, 0xfe, 0xab, 0x0f, 0x6c, 0x97, 0x78, 0xcd, 0x55, + 0x86, 0x83, 0x61, 0x99, 0x49, 0x14, 0x86, 0xc6, 0x86, 0xf1, + 0x41, 0x66, 0xc9, 0x39, 0x52, 0x99, 0x49, 0x07, 0xd6, 0x9d, + 0xb7, 0x40, 0x34, 0x5f, 0xe7, 0x3a, 0xfa, 0x95, 0xeb, 0xa1, + 0x03, 0xb7, 0x52, 0x71, 0x93, 0x30, 0x0b, 0x51, 0x58, 0x82, + 0x07, 0x2f, 0x44, 0xa9, 0x4f, 0x9b, 0x1b, 0xf3, 0xd6, 0x21, + 0x3d, 0x68, 0xef, 0x3f, 0xaf, 0xc2, 0x6f, 0xa0, 0xd5, 0x2b, + 0xb8, 0x73, 0x84, 0x67, 0x36, 0x8b, 0xa4, 0x25, 0xe0, 0x86, + 0xd9, 0x14, 0x5c, 0x6c, 0xd8, 0x61, 0xe1, 0x0a, 0x6c, 0xaf, + 0xbb, 0x9c, 0xf6, 0x74, 0xca, 0x5a, 0x04, 0xac, 0x85, 0xc1, + 0x1b, 0x4d, 0xf2, 0x07, 0xb6, 0x1e, 0x97, 0x7b, 0x75, 0xdf, + 0x9b, 0x8a, 0x31, 0xc6, 0x90, 0xd5, 0x8d, 0x39, 0xc2, 0x54, + 0xf4, 0xe2, 0x83, 0x57, 0x12, 0x19, 0xf5, 0xb2, 0xd2, 0x53, + 0x81, 0x6d, 0xf0, 0x09, 0xc9, 0x80, 0x8b, 0x07, 0x7c, 0x59, + 0xcd, 0x78, 0x00, 0xd6, 0x44, 0x7f, 0xe4, 0xdb, 0x77, 0x02, + 0x00, 0x25, 0x79, 0x91, 0xc9, 0xde, 0xd0, 0xed, 0x3f, 0xfc, + 0x37, 0x36, 0xea, 0xf0, 0x56, 0x50, 0xe7, 0x38, 0xca, 0xe1, + 0x67, 0x12, 0x96, 0x55, 0x3e, 0xff, 0x97, 0xe5, 0xa7, 0x03, + 0x5b, 0x72, 0x80, 0xd6, 0xa5, 0x23, 0x39, 0x78, 0x07, 0xc8, + 0x83, 0x19, 0x74, 0xfb, 0x79, 0xc2, 0x9e, 0xbd, 0xf9, 0xaf, + 0x09, 0x0f, 0xbd, 0x3d, 0x34, 0xe8, 0x44, 0x89, 0xb1, 0xf1, + 0x2b, 0xa5, 0xff, 0x22, 0xc9, 0x47, 0xe2, 0x31, 0xb5, 0x6b, + 0x8a, 0x65, 0x5f, 0x81, 0x5f, 0x89, 0xb0, 0x03, 0x5d, 0x53, + 0x0e, 0xdd, 0xfb, 0xe5, 0x70, 0xaa, 0xd2, 0x37, 0x4d, 0xa1, + 0x7c, 0xf2, 0xe4, 0x7f, 0xf1, 0x4a, 0xaf, 0x12, 0xd1, 0x83, + 0xdc, 0xb2, 0x9e, 0xc1, 0x95, 0x3d, 0x04, 0x9f, 0xa3, 0xad, + 0xcc, 0x78, 0x14, 0x9a, 0xf9, 0x58, 0x39, 0x08, 0x15, 0xda, + 0x1b, 0x94, 0x50, 0x2d, 0x44, 0xc0, 0x23, 0x1c, 0x36, 0x5f, + 0x16, 0x08, 0xa3, 0xdf, 0x9e, 0x4f, 0xbb, 0x07, 0xcd, 0xe3, + 0x8c, 0xbf, 0xf1, 0xc3, 0x3e, 0x98, 0xf8, 0x49, 0x79, 0x58, + 0xc9, 0x0f, 0x47, 0xc0, 0xab, 0x2f, 0x21, 0x63, 0xf6, 0xe6, + 0xfe, 0x8a, 0xea, 0xbc, 0x32, 0x63, 0xca, 0x75, 0xf8, 0xa4, + 0x1b, 0x6c, 0xfe, 0x9a, 0x6e, 0x68, 0x1f, 0x48, 0x59, 0xfb, + 0x34, 0x43, 0x10, 0xd5, 0x0d, 0x80, 0x54, 0xcb, 0x67, 0x21, + 0xc7, 0x13, 0x85, 0x38, 0x0c, 0xf9, 0x40, 0x2e, 0x2e, 0x4a, + 0x05, 0x9e, 0x51, 0xae, 0xdd, 0xba, 0x23, 0x83, 0x66, 0x2a, + 0xbf, 0x7f, 0xca, 0x9c, 0x6c, 0x2d, 0x6b, 0x7d, 0x68, 0x52, + 0x81, 0x56, 0x2f, 0xea, 0xf9, 0xe7, 0xf1, 0x55, 0x16, 0xfc, + 0x29, 0xe2, 0xa5, 0x1e, 0x0a, 0x06, 0xe0, 0x85, 0x4e, 0xa6, + 0x5d, 0x20, 0x9d, 0x2b, 0xa2, 0xad, 0xaa, 0xd6, 0x9b, 0xd2, + 0x98, 0x29, 0x45, 0x5c, 0x55, 0xc0, 0x91, 0xa2, 0x65, 0xcd, + 0xac, 0xc6, 0x1a, 0x53, 0xa1, 0x46, 0x13, 0xf9, 0xfe, 0x1a, + 0xf6, 0xdf, 0xa5, 0x1a, 0x58, 0x7c, 0x81, 0x2e, 0x46, 0x46, + 0xf7, 0x2f, 0xd6, 0xaa, 0x21, 0xb0, 0x0e, 0x7e, 0xac, 0xb8, + 0xc6, 0x76, 0x62, 0x82, 0x3b, 0x0a, 0x36, 0xbe, 0x97, 0x16, + 0xd5, 0x79, 0x55, 0x15, 0x64, 0x2a, 0xbe, 0x19, 0x4e, 0x93, + 0x3b, 0x44, 0x7c, 0xe2, 0xfc, 0x18, 0x4e, 0x83, 0x37, 0xfb, + 0x26, 0x78, 0x6d, 0x24, 0x6b, 0x48, 0x21, 0x67, 0xde, 0xf5, + 0x00, 0x22, 0x9a, 0xec, 0x40, 0x16, 0x96, 0x8a, 0x3f, 0xd5, + 0xa6, 0x5e, 0x03, 0x84, 0xbb, 0x15, 0x4d, 0x55, 0x71, 0x00, + 0x90, 0xc2, 0x96, 0x25, 0x01, 0xab, 0xe6, 0x47, 0x44, 0x6f, + 0xf9, 0x53, 0x80, 0x2b, 0xa8, 0x83, 0xc8, 0x14, 0x77, 0x13, + 0x00, 0x66, 0xee, 0x7e, 0x7a, 0xa0, 0x28, 0x65, 0xf3, 0x31, + 0xb6, 0xac, 0xd7, 0x87, 0x84, 0x29, 0xed, 0x5b, 0xcd, 0x74, + 0xc0, 0x89, 0x51, 0x11, 0x9a, 0xd5, 0x7b, 0xe0, 0x9c, 0xd0, + 0x8d, 0x72, 0xe3, 0x77, 0xda, 0x0a, 0xc2, 0xdc, 0x6f, 0xad, + 0x49, 0x03, 0xfa, 0xe6, 0x7e, 0xa6, 0x24, 0x32, 0xe6, 0x8f, + 0xd9, 0x70, 0xfa, 0x59, 0x70, 0xa9, 0xa3, 0x08, 0x7d, 0x89, + 0xc4, 0x96, 0x61, 0xc2, 0xf5, 0xe5, 0xb5, 0x3b, 0x0d, 0xec, + 0xb8, 0x9c, 0xee, 0x09, 0x77, 0x27, 0xbd, 0x35, 0x66, 0x90, + 0x9e, 0x46, 0xf7, 0xbd, 0xa6, 0xc5, 0x31, 0xd4, 0x6a, 0x52, + 0x17, 0x5d, 0x0a, 0x0e, 0x2c, 0x34, 0x7a, 0x6a, 0x21, 0xac, + 0x42, 0xf0, 0x31, 0xde, 0x48, 0xe0, 0x27, 0xd0, 0x79, 0xc9, + 0x06, 0x94, 0x7b, 0x51, 0x4b, 0x5b, 0x02, 0x6a, 0x19, 0xba, + 0x71, 0x45, 0x9c, 0xdf, 0xe6, 0x30, 0x9e, 0xaa, 0xad, 0xa1, + 0x87, 0xf6, 0x37, 0xde, 0xa2, 0x97, 0x68, 0x20, 0x2d, 0x5a, + 0xdc, 0xdd, 0x91, 0x63, 0x5f, 0x79, 0xda, 0x99, 0x20, 0x3a, + 0x4b, 0xe5, 0x43, 0x0e, 0x12, 0x70, 0x57, 0x91, 0xfa, 0xee, + 0xc4, 0xb6, 0xb6, 0xb1, 0xf1, 0x06, 0xbd, 0xcf, 0x8d, 0x2a, + 0x05, 0xc0, 0x07, 0x23, 0x84, 0x85, 0xef, 0x9c, 0xbb, 0x6f, + 0x5f, 0x4a, 0x9a, 0x27, 0x9f, 0x9f, 0x32, 0x97, 0xe8, 0x24, + 0xb9, 0x64, 0x2c, 0x39, 0xff, 0x2f, 0x4b, 0xc4, 0x7e, 0x65, + 0xfe, 0xbb, 0x5c, 0xa0, 0xb2, 0x6e, 0xc4, 0xb6, 0x93, 0x2b, + 0x51, 0x9e, 0x2e, 0x1f, 0xd8, 0xcf, 0x60, 0xe0, 0x75, 0x15, + 0xf9, 0xa0, 0x67, 0x99, 0x88, 0x2b, 0x76, 0xce, 0x41, 0x42, + 0x10, 0x29, 0x89, 0xbf, 0xca, 0xb7, 0x61, 0x08, 0x94, 0xee, + 0xa0, 0xb3, 0x3a, 0x09, 0xc5, 0x6f, 0x04, 0xf9, 0x1b, 0xb5, + 0x64, 0x99, 0x08, 0xe4, 0xcc, 0xce, 0xdf, 0x71, 0x65, 0x8a, + 0x6d, 0x62, 0xde, 0x76, 0x1d, 0x6d, 0x6b, 0x78, 0x22, 0x32, + 0x63, 0xdd, 0x53, 0x7d, 0xec, 0xed, 0x9d, 0x82, 0xa9, 0x2c, + 0x5c, 0x8a, 0x17, 0xdd, 0x85, 0xf9, 0xd2, 0xac, 0x6e, 0x98, + 0x60, 0x2e, 0x08, 0xd4, 0x06, 0x76, 0xf4, 0x97, 0xca, 0xb1, + 0x72, 0x50, 0x5b, 0x83, 0xea, 0xbb, 0x39, 0x0f, 0x18, 0xb3, + 0xb8, 0x03, 0xee, 0x7c, 0x84, 0xa9, 0x69, 0xcd, 0x1d, 0xbd, + 0xe2, 0xb7, 0xce, 0xe2, 0x6f, 0x03, 0x49, 0x52, 0x67, 0xa0, + 0x1b, 0x23, 0x43, 0x92, 0x2c, 0x7c, 0x3b, 0x65, 0xe8, 0x61, + 0x99, 0xde, 0xb5, 0xf1, 0x63, 0x73, 0x92, 0x6c, 0x70, 0x8b, + 0x83, 0x10, 0xb4, 0x06, 0x2c, 0x99, 0x12, 0x73, 0xec, 0x87, + 0x92, 0x09, 0x67, 0x96, 0xd6, 0x9c, 0x9f, 0x35, 0x48, 0x48, + 0x3b, 0x44, 0x00, 0x73, 0x1c, 0x59, 0xeb, 0x81, 0x7b, 0xd1, + 0xda, 0x76, 0xcf, 0xc2, 0x4d, 0xf1, 0xa2, 0x5b, 0x2f, 0x5f, + 0x91, 0x29, 0x6e, 0x08, 0x37, 0xd6, 0xaa, 0xd2, 0xf8, 0x4f, + 0x5e, 0x00, 0x16, 0x52 +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/timeouts.h b/trunk/3rdparty/openssl-1.1-fit/apps/timeouts.h new file mode 100644 index 000000000..e023b0aa4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/timeouts.h @@ -0,0 +1,17 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef INCLUDED_TIMEOUTS_H +# define INCLUDED_TIMEOUTS_H + +/* numbers in us */ +# define DGRAM_RCV_TIMEOUT 250000 +# define DGRAM_SND_TIMEOUT 250000 + +#endif /* ! INCLUDED_TIMEOUTS_H */ diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/ts.c b/trunk/3rdparty/openssl-1.1-fit/apps/ts.c new file mode 100644 index 000000000..930c1daaa --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/ts.c @@ -0,0 +1,986 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#ifdef OPENSSL_NO_TS +NON_EMPTY_TRANSLATION_UNIT +#else +# include +# include +# include +# include "apps.h" +# include "progs.h" +# include +# include +# include +# include +# include +# include + +/* Request nonce length, in bits (must be a multiple of 8). */ +# define NONCE_LENGTH 64 + +/* Name of config entry that defines the OID file. */ +# define ENV_OID_FILE "oid_file" + +/* Is |EXACTLY_ONE| of three pointers set? */ +# define EXACTLY_ONE(a, b, c) \ + (( a && !b && !c) || \ + ( b && !a && !c) || \ + ( c && !a && !b)) + +static ASN1_OBJECT *txt2obj(const char *oid); +static CONF *load_config_file(const char *configfile); + +/* Query related functions. */ +static int query_command(const char *data, const char *digest, + const EVP_MD *md, const char *policy, int no_nonce, + int cert, const char *in, const char *out, int text); +static TS_REQ *create_query(BIO *data_bio, const char *digest, const EVP_MD *md, + const char *policy, int no_nonce, int cert); +static int create_digest(BIO *input, const char *digest, + const EVP_MD *md, unsigned char **md_value); +static ASN1_INTEGER *create_nonce(int bits); + +/* Reply related functions. */ +static int reply_command(CONF *conf, const char *section, const char *engine, + const char *queryfile, const char *passin, const char *inkey, + const EVP_MD *md, const char *signer, const char *chain, + const char *policy, const char *in, int token_in, + const char *out, int token_out, int text); +static TS_RESP *read_PKCS7(BIO *in_bio); +static TS_RESP *create_response(CONF *conf, const char *section, const char *engine, + const char *queryfile, const char *passin, + const char *inkey, const EVP_MD *md, const char *signer, + const char *chain, const char *policy); +static ASN1_INTEGER *serial_cb(TS_RESP_CTX *ctx, void *data); +static ASN1_INTEGER *next_serial(const char *serialfile); +static int save_ts_serial(const char *serialfile, ASN1_INTEGER *serial); + +/* Verify related functions. */ +static int verify_command(const char *data, const char *digest, const char *queryfile, + const char *in, int token_in, + const char *CApath, const char *CAfile, const char *untrusted, + X509_VERIFY_PARAM *vpm); +static TS_VERIFY_CTX *create_verify_ctx(const char *data, const char *digest, + const char *queryfile, + const char *CApath, const char *CAfile, + const char *untrusted, + X509_VERIFY_PARAM *vpm); +static X509_STORE *create_cert_store(const char *CApath, const char *CAfile, + X509_VERIFY_PARAM *vpm); +static int verify_cb(int ok, X509_STORE_CTX *ctx); + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_ENGINE, OPT_CONFIG, OPT_SECTION, OPT_QUERY, OPT_DATA, + OPT_DIGEST, OPT_TSPOLICY, OPT_NO_NONCE, OPT_CERT, + OPT_IN, OPT_TOKEN_IN, OPT_OUT, OPT_TOKEN_OUT, OPT_TEXT, + OPT_REPLY, OPT_QUERYFILE, OPT_PASSIN, OPT_INKEY, OPT_SIGNER, + OPT_CHAIN, OPT_VERIFY, OPT_CAPATH, OPT_CAFILE, OPT_UNTRUSTED, + OPT_MD, OPT_V_ENUM, OPT_R_ENUM +} OPTION_CHOICE; + +const OPTIONS ts_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"config", OPT_CONFIG, '<', "Configuration file"}, + {"section", OPT_SECTION, 's', "Section to use within config file"}, + {"query", OPT_QUERY, '-', "Generate a TS query"}, + {"data", OPT_DATA, '<', "File to hash"}, + {"digest", OPT_DIGEST, 's', "Digest (as a hex string)"}, + OPT_R_OPTIONS, + {"tspolicy", OPT_TSPOLICY, 's', "Policy OID to use"}, + {"no_nonce", OPT_NO_NONCE, '-', "Do not include a nonce"}, + {"cert", OPT_CERT, '-', "Put cert request into query"}, + {"in", OPT_IN, '<', "Input file"}, + {"token_in", OPT_TOKEN_IN, '-', "Input is a PKCS#7 file"}, + {"out", OPT_OUT, '>', "Output file"}, + {"token_out", OPT_TOKEN_OUT, '-', "Output is a PKCS#7 file"}, + {"text", OPT_TEXT, '-', "Output text (not DER)"}, + {"reply", OPT_REPLY, '-', "Generate a TS reply"}, + {"queryfile", OPT_QUERYFILE, '<', "File containing a TS query"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"inkey", OPT_INKEY, 's', "File with private key for reply"}, + {"signer", OPT_SIGNER, 's', "Signer certificate file"}, + {"chain", OPT_CHAIN, '<', "File with signer CA chain"}, + {"verify", OPT_VERIFY, '-', "Verify a TS response"}, + {"CApath", OPT_CAPATH, '/', "Path to trusted CA files"}, + {"CAfile", OPT_CAFILE, '<', "File with trusted CA certs"}, + {"untrusted", OPT_UNTRUSTED, '<', "File with untrusted certs"}, + {"", OPT_MD, '-', "Any supported digest"}, +# ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +# endif + {OPT_HELP_STR, 1, '-', "\nOptions specific to 'ts -verify': \n"}, + OPT_V_OPTIONS, + {OPT_HELP_STR, 1, '-', "\n"}, + {NULL} +}; + +/* + * This command is so complex, special help is needed. + */ +static char* opt_helplist[] = { + "Typical uses:", + "ts -query [-rand file...] [-config file] [-data file]", + " [-digest hexstring] [-tspolicy oid] [-no_nonce] [-cert]", + " [-in file] [-out file] [-text]", + " or", + "ts -reply [-config file] [-section tsa_section]", + " [-queryfile file] [-passin password]", + " [-signer tsa_cert.pem] [-inkey private_key.pem]", + " [-chain certs_file.pem] [-tspolicy oid]", + " [-in file] [-token_in] [-out file] [-token_out]", +# ifndef OPENSSL_NO_ENGINE + " [-text] [-engine id]", +# else + " [-text]", +# endif + " or", + "ts -verify -CApath dir -CAfile file.pem -untrusted file.pem", + " [-data file] [-digest hexstring]", + " [-queryfile file] -in file [-token_in]", + " [[options specific to 'ts -verify']]", + NULL, +}; + +int ts_main(int argc, char **argv) +{ + CONF *conf = NULL; + const char *CAfile = NULL, *untrusted = NULL, *prog; + const char *configfile = default_config_file, *engine = NULL; + const char *section = NULL; + char **helpp; + char *password = NULL; + char *data = NULL, *digest = NULL, *policy = NULL; + char *in = NULL, *out = NULL, *queryfile = NULL, *passin = NULL; + char *inkey = NULL, *signer = NULL, *chain = NULL, *CApath = NULL; + const EVP_MD *md = NULL; + OPTION_CHOICE o, mode = OPT_ERR; + int ret = 1, no_nonce = 0, cert = 0, text = 0; + int vpmtouched = 0; + X509_VERIFY_PARAM *vpm = NULL; + /* Input is ContentInfo instead of TimeStampResp. */ + int token_in = 0; + /* Output is ContentInfo instead of TimeStampResp. */ + int token_out = 0; + + if ((vpm = X509_VERIFY_PARAM_new()) == NULL) + goto end; + + prog = opt_init(argc, argv, ts_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(ts_options); + for (helpp = opt_helplist; *helpp; ++helpp) + BIO_printf(bio_err, "%s\n", *helpp); + ret = 0; + goto end; + case OPT_CONFIG: + configfile = opt_arg(); + break; + case OPT_SECTION: + section = opt_arg(); + break; + case OPT_QUERY: + case OPT_REPLY: + case OPT_VERIFY: + if (mode != OPT_ERR) + goto opthelp; + mode = o; + break; + case OPT_DATA: + data = opt_arg(); + break; + case OPT_DIGEST: + digest = opt_arg(); + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_TSPOLICY: + policy = opt_arg(); + break; + case OPT_NO_NONCE: + no_nonce = 1; + break; + case OPT_CERT: + cert = 1; + break; + case OPT_IN: + in = opt_arg(); + break; + case OPT_TOKEN_IN: + token_in = 1; + break; + case OPT_OUT: + out = opt_arg(); + break; + case OPT_TOKEN_OUT: + token_out = 1; + break; + case OPT_TEXT: + text = 1; + break; + case OPT_QUERYFILE: + queryfile = opt_arg(); + break; + case OPT_PASSIN: + passin = opt_arg(); + break; + case OPT_INKEY: + inkey = opt_arg(); + break; + case OPT_SIGNER: + signer = opt_arg(); + break; + case OPT_CHAIN: + chain = opt_arg(); + break; + case OPT_CAPATH: + CApath = opt_arg(); + break; + case OPT_CAFILE: + CAfile = opt_arg(); + break; + case OPT_UNTRUSTED: + untrusted = opt_arg(); + break; + case OPT_ENGINE: + engine = opt_arg(); + break; + case OPT_MD: + if (!opt_md(opt_unknown(), &md)) + goto opthelp; + break; + case OPT_V_CASES: + if (!opt_verify(o, vpm)) + goto end; + vpmtouched++; + break; + } + } + if (mode == OPT_ERR || opt_num_rest() != 0) + goto opthelp; + + if (mode == OPT_REPLY && passin && + !app_passwd(passin, NULL, &password, NULL)) { + BIO_printf(bio_err, "Error getting password.\n"); + goto end; + } + + conf = load_config_file(configfile); + if (configfile != default_config_file && !app_load_modules(conf)) + goto end; + + /* Check parameter consistency and execute the appropriate function. */ + if (mode == OPT_QUERY) { + if (vpmtouched) + goto opthelp; + if ((data != NULL) && (digest != NULL)) + goto opthelp; + ret = !query_command(data, digest, md, policy, no_nonce, cert, + in, out, text); + } else if (mode == OPT_REPLY) { + if (vpmtouched) + goto opthelp; + if ((in != NULL) && (queryfile != NULL)) + goto opthelp; + if (in == NULL) { + if ((conf == NULL) || (token_in != 0)) + goto opthelp; + } + ret = !reply_command(conf, section, engine, queryfile, + password, inkey, md, signer, chain, policy, + in, token_in, out, token_out, text); + + } else if (mode == OPT_VERIFY) { + if ((in == NULL) || !EXACTLY_ONE(queryfile, data, digest)) + goto opthelp; + ret = !verify_command(data, digest, queryfile, in, token_in, + CApath, CAfile, untrusted, + vpmtouched ? vpm : NULL); + } else { + goto opthelp; + } + + end: + X509_VERIFY_PARAM_free(vpm); + NCONF_free(conf); + OPENSSL_free(password); + return ret; +} + +/* + * Configuration file-related function definitions. + */ + +static ASN1_OBJECT *txt2obj(const char *oid) +{ + ASN1_OBJECT *oid_obj = NULL; + + if ((oid_obj = OBJ_txt2obj(oid, 0)) == NULL) + BIO_printf(bio_err, "cannot convert %s to OID\n", oid); + + return oid_obj; +} + +static CONF *load_config_file(const char *configfile) +{ + CONF *conf = app_load_config(configfile); + + if (conf != NULL) { + const char *p; + + BIO_printf(bio_err, "Using configuration from %s\n", configfile); + p = NCONF_get_string(conf, NULL, ENV_OID_FILE); + if (p != NULL) { + BIO *oid_bio = BIO_new_file(p, "r"); + if (!oid_bio) + ERR_print_errors(bio_err); + else { + OBJ_create_objects(oid_bio); + BIO_free_all(oid_bio); + } + } else + ERR_clear_error(); + if (!add_oid_section(conf)) + ERR_print_errors(bio_err); + } + return conf; +} + +/* + * Query-related method definitions. + */ +static int query_command(const char *data, const char *digest, const EVP_MD *md, + const char *policy, int no_nonce, + int cert, const char *in, const char *out, int text) +{ + int ret = 0; + TS_REQ *query = NULL; + BIO *in_bio = NULL; + BIO *data_bio = NULL; + BIO *out_bio = NULL; + + /* Build query object. */ + if (in != NULL) { + if ((in_bio = bio_open_default(in, 'r', FORMAT_ASN1)) == NULL) + goto end; + query = d2i_TS_REQ_bio(in_bio, NULL); + } else { + if (digest == NULL + && (data_bio = bio_open_default(data, 'r', FORMAT_ASN1)) == NULL) + goto end; + query = create_query(data_bio, digest, md, policy, no_nonce, cert); + } + if (query == NULL) + goto end; + + if (text) { + if ((out_bio = bio_open_default(out, 'w', FORMAT_TEXT)) == NULL) + goto end; + if (!TS_REQ_print_bio(out_bio, query)) + goto end; + } else { + if ((out_bio = bio_open_default(out, 'w', FORMAT_ASN1)) == NULL) + goto end; + if (!i2d_TS_REQ_bio(out_bio, query)) + goto end; + } + + ret = 1; + + end: + ERR_print_errors(bio_err); + BIO_free_all(in_bio); + BIO_free_all(data_bio); + BIO_free_all(out_bio); + TS_REQ_free(query); + return ret; +} + +static TS_REQ *create_query(BIO *data_bio, const char *digest, const EVP_MD *md, + const char *policy, int no_nonce, int cert) +{ + int ret = 0; + TS_REQ *ts_req = NULL; + int len; + TS_MSG_IMPRINT *msg_imprint = NULL; + X509_ALGOR *algo = NULL; + unsigned char *data = NULL; + ASN1_OBJECT *policy_obj = NULL; + ASN1_INTEGER *nonce_asn1 = NULL; + + if (md == NULL && (md = EVP_get_digestbyname("sha1")) == NULL) + goto err; + if ((ts_req = TS_REQ_new()) == NULL) + goto err; + if (!TS_REQ_set_version(ts_req, 1)) + goto err; + if ((msg_imprint = TS_MSG_IMPRINT_new()) == NULL) + goto err; + if ((algo = X509_ALGOR_new()) == NULL) + goto err; + if ((algo->algorithm = OBJ_nid2obj(EVP_MD_type(md))) == NULL) + goto err; + if ((algo->parameter = ASN1_TYPE_new()) == NULL) + goto err; + algo->parameter->type = V_ASN1_NULL; + if (!TS_MSG_IMPRINT_set_algo(msg_imprint, algo)) + goto err; + if ((len = create_digest(data_bio, digest, md, &data)) == 0) + goto err; + if (!TS_MSG_IMPRINT_set_msg(msg_imprint, data, len)) + goto err; + if (!TS_REQ_set_msg_imprint(ts_req, msg_imprint)) + goto err; + if (policy && (policy_obj = txt2obj(policy)) == NULL) + goto err; + if (policy_obj && !TS_REQ_set_policy_id(ts_req, policy_obj)) + goto err; + + /* Setting nonce if requested. */ + if (!no_nonce && (nonce_asn1 = create_nonce(NONCE_LENGTH)) == NULL) + goto err; + if (nonce_asn1 && !TS_REQ_set_nonce(ts_req, nonce_asn1)) + goto err; + if (!TS_REQ_set_cert_req(ts_req, cert)) + goto err; + + ret = 1; + err: + if (!ret) { + TS_REQ_free(ts_req); + ts_req = NULL; + BIO_printf(bio_err, "could not create query\n"); + ERR_print_errors(bio_err); + } + TS_MSG_IMPRINT_free(msg_imprint); + X509_ALGOR_free(algo); + OPENSSL_free(data); + ASN1_OBJECT_free(policy_obj); + ASN1_INTEGER_free(nonce_asn1); + return ts_req; +} + +static int create_digest(BIO *input, const char *digest, const EVP_MD *md, + unsigned char **md_value) +{ + int md_value_len; + int rv = 0; + EVP_MD_CTX *md_ctx = NULL; + + md_value_len = EVP_MD_size(md); + if (md_value_len < 0) + return 0; + + if (input != NULL) { + unsigned char buffer[4096]; + int length; + + md_ctx = EVP_MD_CTX_new(); + if (md_ctx == NULL) + return 0; + *md_value = app_malloc(md_value_len, "digest buffer"); + if (!EVP_DigestInit(md_ctx, md)) + goto err; + while ((length = BIO_read(input, buffer, sizeof(buffer))) > 0) { + if (!EVP_DigestUpdate(md_ctx, buffer, length)) + goto err; + } + if (!EVP_DigestFinal(md_ctx, *md_value, NULL)) + goto err; + md_value_len = EVP_MD_size(md); + } else { + long digest_len; + *md_value = OPENSSL_hexstr2buf(digest, &digest_len); + if (!*md_value || md_value_len != digest_len) { + OPENSSL_free(*md_value); + *md_value = NULL; + BIO_printf(bio_err, "bad digest, %d bytes " + "must be specified\n", md_value_len); + return 0; + } + } + rv = md_value_len; + err: + EVP_MD_CTX_free(md_ctx); + return rv; +} + +static ASN1_INTEGER *create_nonce(int bits) +{ + unsigned char buf[20]; + ASN1_INTEGER *nonce = NULL; + int len = (bits - 1) / 8 + 1; + int i; + + if (len > (int)sizeof(buf)) + goto err; + if (RAND_bytes(buf, len) <= 0) + goto err; + + /* Find the first non-zero byte and creating ASN1_INTEGER object. */ + for (i = 0; i < len && !buf[i]; ++i) + continue; + if ((nonce = ASN1_INTEGER_new()) == NULL) + goto err; + OPENSSL_free(nonce->data); + nonce->length = len - i; + nonce->data = app_malloc(nonce->length + 1, "nonce buffer"); + memcpy(nonce->data, buf + i, nonce->length); + return nonce; + + err: + BIO_printf(bio_err, "could not create nonce\n"); + ASN1_INTEGER_free(nonce); + return NULL; +} + +/* + * Reply-related method definitions. + */ + +static int reply_command(CONF *conf, const char *section, const char *engine, + const char *queryfile, const char *passin, const char *inkey, + const EVP_MD *md, const char *signer, const char *chain, + const char *policy, const char *in, int token_in, + const char *out, int token_out, int text) +{ + int ret = 0; + TS_RESP *response = NULL; + BIO *in_bio = NULL; + BIO *query_bio = NULL; + BIO *inkey_bio = NULL; + BIO *signer_bio = NULL; + BIO *out_bio = NULL; + + if (in != NULL) { + if ((in_bio = BIO_new_file(in, "rb")) == NULL) + goto end; + if (token_in) { + response = read_PKCS7(in_bio); + } else { + response = d2i_TS_RESP_bio(in_bio, NULL); + } + } else { + response = create_response(conf, section, engine, queryfile, + passin, inkey, md, signer, chain, policy); + if (response != NULL) + BIO_printf(bio_err, "Response has been generated.\n"); + else + BIO_printf(bio_err, "Response is not generated.\n"); + } + if (response == NULL) + goto end; + + /* Write response. */ + if (text) { + if ((out_bio = bio_open_default(out, 'w', FORMAT_TEXT)) == NULL) + goto end; + if (token_out) { + TS_TST_INFO *tst_info = TS_RESP_get_tst_info(response); + if (!TS_TST_INFO_print_bio(out_bio, tst_info)) + goto end; + } else { + if (!TS_RESP_print_bio(out_bio, response)) + goto end; + } + } else { + if ((out_bio = bio_open_default(out, 'w', FORMAT_ASN1)) == NULL) + goto end; + if (token_out) { + PKCS7 *token = TS_RESP_get_token(response); + if (!i2d_PKCS7_bio(out_bio, token)) + goto end; + } else { + if (!i2d_TS_RESP_bio(out_bio, response)) + goto end; + } + } + + ret = 1; + + end: + ERR_print_errors(bio_err); + BIO_free_all(in_bio); + BIO_free_all(query_bio); + BIO_free_all(inkey_bio); + BIO_free_all(signer_bio); + BIO_free_all(out_bio); + TS_RESP_free(response); + return ret; +} + +/* Reads a PKCS7 token and adds default 'granted' status info to it. */ +static TS_RESP *read_PKCS7(BIO *in_bio) +{ + int ret = 0; + PKCS7 *token = NULL; + TS_TST_INFO *tst_info = NULL; + TS_RESP *resp = NULL; + TS_STATUS_INFO *si = NULL; + + if ((token = d2i_PKCS7_bio(in_bio, NULL)) == NULL) + goto end; + if ((tst_info = PKCS7_to_TS_TST_INFO(token)) == NULL) + goto end; + if ((resp = TS_RESP_new()) == NULL) + goto end; + if ((si = TS_STATUS_INFO_new()) == NULL) + goto end; + if (!TS_STATUS_INFO_set_status(si, TS_STATUS_GRANTED)) + goto end; + if (!TS_RESP_set_status_info(resp, si)) + goto end; + TS_RESP_set_tst_info(resp, token, tst_info); + token = NULL; /* Ownership is lost. */ + tst_info = NULL; /* Ownership is lost. */ + ret = 1; + + end: + PKCS7_free(token); + TS_TST_INFO_free(tst_info); + if (!ret) { + TS_RESP_free(resp); + resp = NULL; + } + TS_STATUS_INFO_free(si); + return resp; +} + +static TS_RESP *create_response(CONF *conf, const char *section, const char *engine, + const char *queryfile, const char *passin, + const char *inkey, const EVP_MD *md, const char *signer, + const char *chain, const char *policy) +{ + int ret = 0; + TS_RESP *response = NULL; + BIO *query_bio = NULL; + TS_RESP_CTX *resp_ctx = NULL; + + if ((query_bio = BIO_new_file(queryfile, "rb")) == NULL) + goto end; + if ((section = TS_CONF_get_tsa_section(conf, section)) == NULL) + goto end; + if ((resp_ctx = TS_RESP_CTX_new()) == NULL) + goto end; + if (!TS_CONF_set_serial(conf, section, serial_cb, resp_ctx)) + goto end; +# ifndef OPENSSL_NO_ENGINE + if (!TS_CONF_set_crypto_device(conf, section, engine)) + goto end; +# endif + if (!TS_CONF_set_signer_cert(conf, section, signer, resp_ctx)) + goto end; + if (!TS_CONF_set_certs(conf, section, chain, resp_ctx)) + goto end; + if (!TS_CONF_set_signer_key(conf, section, inkey, passin, resp_ctx)) + goto end; + + if (md) { + if (!TS_RESP_CTX_set_signer_digest(resp_ctx, md)) + goto end; + } else if (!TS_CONF_set_signer_digest(conf, section, NULL, resp_ctx)) { + goto end; + } + + if (!TS_CONF_set_ess_cert_id_digest(conf, section, resp_ctx)) + goto end; + if (!TS_CONF_set_def_policy(conf, section, policy, resp_ctx)) + goto end; + if (!TS_CONF_set_policies(conf, section, resp_ctx)) + goto end; + if (!TS_CONF_set_digests(conf, section, resp_ctx)) + goto end; + if (!TS_CONF_set_accuracy(conf, section, resp_ctx)) + goto end; + if (!TS_CONF_set_clock_precision_digits(conf, section, resp_ctx)) + goto end; + if (!TS_CONF_set_ordering(conf, section, resp_ctx)) + goto end; + if (!TS_CONF_set_tsa_name(conf, section, resp_ctx)) + goto end; + if (!TS_CONF_set_ess_cert_id_chain(conf, section, resp_ctx)) + goto end; + if ((response = TS_RESP_create_response(resp_ctx, query_bio)) == NULL) + goto end; + ret = 1; + + end: + if (!ret) { + TS_RESP_free(response); + response = NULL; + } + TS_RESP_CTX_free(resp_ctx); + BIO_free_all(query_bio); + return response; +} + +static ASN1_INTEGER *serial_cb(TS_RESP_CTX *ctx, void *data) +{ + const char *serial_file = (const char *)data; + ASN1_INTEGER *serial = next_serial(serial_file); + + if (serial == NULL) { + TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION, + "Error during serial number " + "generation."); + TS_RESP_CTX_add_failure_info(ctx, TS_INFO_ADD_INFO_NOT_AVAILABLE); + } else { + save_ts_serial(serial_file, serial); + } + + return serial; +} + +static ASN1_INTEGER *next_serial(const char *serialfile) +{ + int ret = 0; + BIO *in = NULL; + ASN1_INTEGER *serial = NULL; + BIGNUM *bn = NULL; + + if ((serial = ASN1_INTEGER_new()) == NULL) + goto err; + + if ((in = BIO_new_file(serialfile, "r")) == NULL) { + ERR_clear_error(); + BIO_printf(bio_err, "Warning: could not open file %s for " + "reading, using serial number: 1\n", serialfile); + if (!ASN1_INTEGER_set(serial, 1)) + goto err; + } else { + char buf[1024]; + if (!a2i_ASN1_INTEGER(in, serial, buf, sizeof(buf))) { + BIO_printf(bio_err, "unable to load number from %s\n", + serialfile); + goto err; + } + if ((bn = ASN1_INTEGER_to_BN(serial, NULL)) == NULL) + goto err; + ASN1_INTEGER_free(serial); + serial = NULL; + if (!BN_add_word(bn, 1)) + goto err; + if ((serial = BN_to_ASN1_INTEGER(bn, NULL)) == NULL) + goto err; + } + ret = 1; + + err: + if (!ret) { + ASN1_INTEGER_free(serial); + serial = NULL; + } + BIO_free_all(in); + BN_free(bn); + return serial; +} + +static int save_ts_serial(const char *serialfile, ASN1_INTEGER *serial) +{ + int ret = 0; + BIO *out = NULL; + + if ((out = BIO_new_file(serialfile, "w")) == NULL) + goto err; + if (i2a_ASN1_INTEGER(out, serial) <= 0) + goto err; + if (BIO_puts(out, "\n") <= 0) + goto err; + ret = 1; + err: + if (!ret) + BIO_printf(bio_err, "could not save serial number to %s\n", + serialfile); + BIO_free_all(out); + return ret; +} + + +/* + * Verify-related method definitions. + */ + +static int verify_command(const char *data, const char *digest, const char *queryfile, + const char *in, int token_in, + const char *CApath, const char *CAfile, const char *untrusted, + X509_VERIFY_PARAM *vpm) +{ + BIO *in_bio = NULL; + PKCS7 *token = NULL; + TS_RESP *response = NULL; + TS_VERIFY_CTX *verify_ctx = NULL; + int ret = 0; + + if ((in_bio = BIO_new_file(in, "rb")) == NULL) + goto end; + if (token_in) { + if ((token = d2i_PKCS7_bio(in_bio, NULL)) == NULL) + goto end; + } else { + if ((response = d2i_TS_RESP_bio(in_bio, NULL)) == NULL) + goto end; + } + + if ((verify_ctx = create_verify_ctx(data, digest, queryfile, + CApath, CAfile, untrusted, + vpm)) == NULL) + goto end; + + ret = token_in + ? TS_RESP_verify_token(verify_ctx, token) + : TS_RESP_verify_response(verify_ctx, response); + + end: + printf("Verification: "); + if (ret) + printf("OK\n"); + else { + printf("FAILED\n"); + ERR_print_errors(bio_err); + } + + BIO_free_all(in_bio); + PKCS7_free(token); + TS_RESP_free(response); + TS_VERIFY_CTX_free(verify_ctx); + return ret; +} + +static TS_VERIFY_CTX *create_verify_ctx(const char *data, const char *digest, + const char *queryfile, + const char *CApath, const char *CAfile, + const char *untrusted, + X509_VERIFY_PARAM *vpm) +{ + TS_VERIFY_CTX *ctx = NULL; + BIO *input = NULL; + TS_REQ *request = NULL; + int ret = 0; + int f = 0; + + if (data != NULL || digest != NULL) { + if ((ctx = TS_VERIFY_CTX_new()) == NULL) + goto err; + f = TS_VFY_VERSION | TS_VFY_SIGNER; + if (data != NULL) { + BIO *out = NULL; + + f |= TS_VFY_DATA; + if ((out = BIO_new_file(data, "rb")) == NULL) + goto err; + if (TS_VERIFY_CTX_set_data(ctx, out) == NULL) { + BIO_free_all(out); + goto err; + } + } else if (digest != NULL) { + long imprint_len; + unsigned char *hexstr = OPENSSL_hexstr2buf(digest, &imprint_len); + f |= TS_VFY_IMPRINT; + if (TS_VERIFY_CTX_set_imprint(ctx, hexstr, imprint_len) == NULL) { + BIO_printf(bio_err, "invalid digest string\n"); + goto err; + } + } + + } else if (queryfile != NULL) { + if ((input = BIO_new_file(queryfile, "rb")) == NULL) + goto err; + if ((request = d2i_TS_REQ_bio(input, NULL)) == NULL) + goto err; + if ((ctx = TS_REQ_to_TS_VERIFY_CTX(request, NULL)) == NULL) + goto err; + } else { + return NULL; + } + + /* Add the signature verification flag and arguments. */ + TS_VERIFY_CTX_add_flags(ctx, f | TS_VFY_SIGNATURE); + + /* Initialising the X509_STORE object. */ + if (TS_VERIFY_CTX_set_store(ctx, create_cert_store(CApath, CAfile, vpm)) + == NULL) + goto err; + + /* Loading untrusted certificates. */ + if (untrusted + && TS_VERIFY_CTS_set_certs(ctx, TS_CONF_load_certs(untrusted)) == NULL) + goto err; + ret = 1; + + err: + if (!ret) { + TS_VERIFY_CTX_free(ctx); + ctx = NULL; + } + BIO_free_all(input); + TS_REQ_free(request); + return ctx; +} + +static X509_STORE *create_cert_store(const char *CApath, const char *CAfile, + X509_VERIFY_PARAM *vpm) +{ + X509_STORE *cert_ctx = NULL; + X509_LOOKUP *lookup = NULL; + int i; + + cert_ctx = X509_STORE_new(); + X509_STORE_set_verify_cb(cert_ctx, verify_cb); + if (CApath != NULL) { + lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_hash_dir()); + if (lookup == NULL) { + BIO_printf(bio_err, "memory allocation failure\n"); + goto err; + } + i = X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM); + if (!i) { + BIO_printf(bio_err, "Error loading directory %s\n", CApath); + goto err; + } + } + + if (CAfile != NULL) { + lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_file()); + if (lookup == NULL) { + BIO_printf(bio_err, "memory allocation failure\n"); + goto err; + } + i = X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM); + if (!i) { + BIO_printf(bio_err, "Error loading file %s\n", CAfile); + goto err; + } + } + + if (vpm != NULL) + X509_STORE_set1_param(cert_ctx, vpm); + + return cert_ctx; + + err: + X509_STORE_free(cert_ctx); + return NULL; +} + +static int verify_cb(int ok, X509_STORE_CTX *ctx) +{ + return ok; +} +#endif /* ndef OPENSSL_NO_TS */ diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/tsget.in b/trunk/3rdparty/openssl-1.1-fit/apps/tsget.in new file mode 100644 index 000000000..bec365e28 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/tsget.in @@ -0,0 +1,200 @@ +#!{- $config{HASHBANGPERL} -} +# Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. +# Copyright (c) 2002 The OpenTSA Project. All rights reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use strict; +use IO::Handle; +use Getopt::Std; +use File::Basename; +use WWW::Curl::Easy; + +use vars qw(%options); + +# Callback for reading the body. +sub read_body { + my ($maxlength, $state) = @_; + my $return_data = ""; + my $data_len = length ${$state->{data}}; + if ($state->{bytes} < $data_len) { + $data_len = $data_len - $state->{bytes}; + $data_len = $maxlength if $data_len > $maxlength; + $return_data = substr ${$state->{data}}, $state->{bytes}, $data_len; + $state->{bytes} += $data_len; + } + return $return_data; +} + +# Callback for writing the body into a variable. +sub write_body { + my ($data, $pointer) = @_; + ${$pointer} .= $data; + return length($data); +} + +# Initialise a new Curl object. +sub create_curl { + my $url = shift; + + # Create Curl object. + my $curl = WWW::Curl::Easy::new(); + + # Error-handling related options. + $curl->setopt(CURLOPT_VERBOSE, 1) if $options{d}; + $curl->setopt(CURLOPT_FAILONERROR, 1); + $curl->setopt(CURLOPT_USERAGENT, + "OpenTSA tsget.pl/openssl-{- $config{version} -}"); + + # Options for POST method. + $curl->setopt(CURLOPT_UPLOAD, 1); + $curl->setopt(CURLOPT_CUSTOMREQUEST, "POST"); + $curl->setopt(CURLOPT_HTTPHEADER, + ["Content-Type: application/timestamp-query", + "Accept: application/timestamp-reply,application/timestamp-response"]); + $curl->setopt(CURLOPT_READFUNCTION, \&read_body); + $curl->setopt(CURLOPT_HEADERFUNCTION, sub { return length($_[0]); }); + + # Options for getting the result. + $curl->setopt(CURLOPT_WRITEFUNCTION, \&write_body); + + # SSL related options. + $curl->setopt(CURLOPT_SSLKEYTYPE, "PEM"); + $curl->setopt(CURLOPT_SSL_VERIFYPEER, 1); # Verify server's certificate. + $curl->setopt(CURLOPT_SSL_VERIFYHOST, 2); # Check server's CN. + $curl->setopt(CURLOPT_SSLKEY, $options{k}) if defined($options{k}); + $curl->setopt(CURLOPT_SSLKEYPASSWD, $options{p}) if defined($options{p}); + $curl->setopt(CURLOPT_SSLCERT, $options{c}) if defined($options{c}); + $curl->setopt(CURLOPT_CAINFO, $options{C}) if defined($options{C}); + $curl->setopt(CURLOPT_CAPATH, $options{P}) if defined($options{P}); + $curl->setopt(CURLOPT_RANDOM_FILE, $options{r}) if defined($options{r}); + $curl->setopt(CURLOPT_EGDSOCKET, $options{g}) if defined($options{g}); + + # Setting destination. + $curl->setopt(CURLOPT_URL, $url); + + return $curl; +} + +# Send a request and returns the body back. +sub get_timestamp { + my $curl = shift; + my $body = shift; + my $ts_body; + local $::error_buf; + + # Error-handling related options. + $curl->setopt(CURLOPT_ERRORBUFFER, "::error_buf"); + + # Options for POST method. + $curl->setopt(CURLOPT_INFILE, {data => $body, bytes => 0}); + $curl->setopt(CURLOPT_INFILESIZE, length(${$body})); + + # Options for getting the result. + $curl->setopt(CURLOPT_FILE, \$ts_body); + + # Send the request... + my $error_code = $curl->perform(); + my $error_string; + if ($error_code != 0) { + my $http_code = $curl->getinfo(CURLINFO_HTTP_CODE); + $error_string = "could not get timestamp"; + $error_string .= ", http code: $http_code" unless $http_code == 0; + $error_string .= ", curl code: $error_code"; + $error_string .= " ($::error_buf)" if defined($::error_buf); + } else { + my $ct = $curl->getinfo(CURLINFO_CONTENT_TYPE); + if (lc($ct) ne "application/timestamp-reply" + && lc($ct) ne "application/timestamp-response") { + $error_string = "unexpected content type returned: $ct"; + } + } + return ($ts_body, $error_string); + +} + +# Print usage information and exists. +sub usage { + + print STDERR "usage: $0 -h [-e ] [-o ] "; + print STDERR "[-v] [-d] [-k ] [-p ] "; + print STDERR "[-c ] [-C ] [-P ] "; + print STDERR "[-r ] [-g ] []...\n"; + exit 1; +} + +# ---------------------------------------------------------------------- +# Main program +# ---------------------------------------------------------------------- + +# Getting command-line options (default comes from TSGET environment variable). +my $getopt_arg = "h:e:o:vdk:p:c:C:P:r:g:"; +if (exists $ENV{TSGET}) { + my @old_argv = @ARGV; + @ARGV = split /\s+/, $ENV{TSGET}; + getopts($getopt_arg, \%options) or usage; + @ARGV = @old_argv; +} +getopts($getopt_arg, \%options) or usage; + +# Checking argument consistency. +if (!exists($options{h}) || (@ARGV == 0 && !exists($options{o})) + || (@ARGV > 1 && exists($options{o}))) { + print STDERR "Inconsistent command line options.\n"; + usage; +} +# Setting defaults. +@ARGV = ("-") unless @ARGV != 0; +$options{e} = ".tsr" unless defined($options{e}); + +# Processing requests. +my $curl = create_curl $options{h}; +undef $/; # For reading whole files. +REQUEST: foreach (@ARGV) { + my $input = $_; + my ($base, $path) = fileparse($input, '\.[^.]*'); + my $output_base = $base . $options{e}; + my $output = defined($options{o}) ? $options{o} : $path . $output_base; + + STDERR->printflush("$input: ") if $options{v}; + # Read request. + my $body; + if ($input eq "-") { + # Read the request from STDIN; + $body = ; + } else { + # Read the request from file. + open INPUT, "<" . $input + or warn("$input: could not open input file: $!\n"), next REQUEST; + $body = ; + close INPUT + or warn("$input: could not close input file: $!\n"), next REQUEST; + } + + # Send request. + STDERR->printflush("sending request") if $options{v}; + + my ($ts_body, $error) = get_timestamp $curl, \$body; + if (defined($error)) { + die "$input: fatal error: $error\n"; + } + STDERR->printflush(", reply received") if $options{v}; + + # Write response. + if ($output eq "-") { + # Write to STDOUT. + print $ts_body; + } else { + # Write to file. + open OUTPUT, ">", $output + or warn("$output: could not open output file: $!\n"), next REQUEST; + print OUTPUT $ts_body; + close OUTPUT + or warn("$output: could not close output file: $!\n"), next REQUEST; + } + STDERR->printflush(", $output written.\n") if $options{v}; +} +$curl->cleanup(); diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/verify.c b/trunk/3rdparty/openssl-1.1-fit/apps/verify.c new file mode 100644 index 000000000..1f9385606 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/verify.c @@ -0,0 +1,322 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include +#include + +static int cb(int ok, X509_STORE_CTX *ctx); +static int check(X509_STORE *ctx, const char *file, + STACK_OF(X509) *uchain, STACK_OF(X509) *tchain, + STACK_OF(X509_CRL) *crls, int show_chain); +static int v_verbose = 0, vflags = 0; + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_ENGINE, OPT_CAPATH, OPT_CAFILE, OPT_NOCAPATH, OPT_NOCAFILE, + OPT_UNTRUSTED, OPT_TRUSTED, OPT_CRLFILE, OPT_CRL_DOWNLOAD, OPT_SHOW_CHAIN, + OPT_V_ENUM, OPT_NAMEOPT, + OPT_VERBOSE +} OPTION_CHOICE; + +const OPTIONS verify_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] cert.pem...\n"}, + {OPT_HELP_STR, 1, '-', "Valid options are:\n"}, + {"help", OPT_HELP, '-', "Display this summary"}, + {"verbose", OPT_VERBOSE, '-', + "Print extra information about the operations being performed."}, + {"CApath", OPT_CAPATH, '/', "A directory of trusted certificates"}, + {"CAfile", OPT_CAFILE, '<', "A file of trusted certificates"}, + {"no-CAfile", OPT_NOCAFILE, '-', + "Do not load the default certificates file"}, + {"no-CApath", OPT_NOCAPATH, '-', + "Do not load certificates from the default certificates directory"}, + {"untrusted", OPT_UNTRUSTED, '<', "A file of untrusted certificates"}, + {"trusted", OPT_TRUSTED, '<', "A file of trusted certificates"}, + {"CRLfile", OPT_CRLFILE, '<', + "File containing one or more CRL's (in PEM format) to load"}, + {"crl_download", OPT_CRL_DOWNLOAD, '-', + "Attempt to download CRL information for this certificate"}, + {"show_chain", OPT_SHOW_CHAIN, '-', + "Display information about the certificate chain"}, + {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"}, + OPT_V_OPTIONS, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + {NULL} +}; + +int verify_main(int argc, char **argv) +{ + ENGINE *e = NULL; + STACK_OF(X509) *untrusted = NULL, *trusted = NULL; + STACK_OF(X509_CRL) *crls = NULL; + X509_STORE *store = NULL; + X509_VERIFY_PARAM *vpm = NULL; + const char *prog, *CApath = NULL, *CAfile = NULL; + int noCApath = 0, noCAfile = 0; + int vpmtouched = 0, crl_download = 0, show_chain = 0, i = 0, ret = 1; + OPTION_CHOICE o; + + if ((vpm = X509_VERIFY_PARAM_new()) == NULL) + goto end; + + prog = opt_init(argc, argv, verify_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(verify_options); + BIO_printf(bio_err, "Recognized usages:\n"); + for (i = 0; i < X509_PURPOSE_get_count(); i++) { + X509_PURPOSE *ptmp; + ptmp = X509_PURPOSE_get0(i); + BIO_printf(bio_err, "\t%-10s\t%s\n", + X509_PURPOSE_get0_sname(ptmp), + X509_PURPOSE_get0_name(ptmp)); + } + + BIO_printf(bio_err, "Recognized verify names:\n"); + for (i = 0; i < X509_VERIFY_PARAM_get_count(); i++) { + const X509_VERIFY_PARAM *vptmp; + vptmp = X509_VERIFY_PARAM_get0(i); + BIO_printf(bio_err, "\t%-10s\n", + X509_VERIFY_PARAM_get0_name(vptmp)); + } + ret = 0; + goto end; + case OPT_V_CASES: + if (!opt_verify(o, vpm)) + goto end; + vpmtouched++; + break; + case OPT_CAPATH: + CApath = opt_arg(); + break; + case OPT_CAFILE: + CAfile = opt_arg(); + break; + case OPT_NOCAPATH: + noCApath = 1; + break; + case OPT_NOCAFILE: + noCAfile = 1; + break; + case OPT_UNTRUSTED: + /* Zero or more times */ + if (!load_certs(opt_arg(), &untrusted, FORMAT_PEM, NULL, + "untrusted certificates")) + goto end; + break; + case OPT_TRUSTED: + /* Zero or more times */ + noCAfile = 1; + noCApath = 1; + if (!load_certs(opt_arg(), &trusted, FORMAT_PEM, NULL, + "trusted certificates")) + goto end; + break; + case OPT_CRLFILE: + /* Zero or more times */ + if (!load_crls(opt_arg(), &crls, FORMAT_PEM, NULL, + "other CRLs")) + goto end; + break; + case OPT_CRL_DOWNLOAD: + crl_download = 1; + break; + case OPT_ENGINE: + if ((e = setup_engine(opt_arg(), 0)) == NULL) { + /* Failure message already displayed */ + goto end; + } + break; + case OPT_SHOW_CHAIN: + show_chain = 1; + break; + case OPT_NAMEOPT: + if (!set_nameopt(opt_arg())) + goto end; + break; + case OPT_VERBOSE: + v_verbose = 1; + break; + } + } + argc = opt_num_rest(); + argv = opt_rest(); + if (trusted != NULL && (CAfile || CApath)) { + BIO_printf(bio_err, + "%s: Cannot use -trusted with -CAfile or -CApath\n", + prog); + goto end; + } + + if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL) + goto end; + X509_STORE_set_verify_cb(store, cb); + + if (vpmtouched) + X509_STORE_set1_param(store, vpm); + + ERR_clear_error(); + + if (crl_download) + store_setup_crl_download(store); + + ret = 0; + if (argc < 1) { + if (check(store, NULL, untrusted, trusted, crls, show_chain) != 1) + ret = -1; + } else { + for (i = 0; i < argc; i++) + if (check(store, argv[i], untrusted, trusted, crls, + show_chain) != 1) + ret = -1; + } + + end: + X509_VERIFY_PARAM_free(vpm); + X509_STORE_free(store); + sk_X509_pop_free(untrusted, X509_free); + sk_X509_pop_free(trusted, X509_free); + sk_X509_CRL_pop_free(crls, X509_CRL_free); + release_engine(e); + return (ret < 0 ? 2 : ret); +} + +static int check(X509_STORE *ctx, const char *file, + STACK_OF(X509) *uchain, STACK_OF(X509) *tchain, + STACK_OF(X509_CRL) *crls, int show_chain) +{ + X509 *x = NULL; + int i = 0, ret = 0; + X509_STORE_CTX *csc; + STACK_OF(X509) *chain = NULL; + int num_untrusted; + + x = load_cert(file, FORMAT_PEM, "certificate file"); + if (x == NULL) + goto end; + + csc = X509_STORE_CTX_new(); + if (csc == NULL) { + printf("error %s: X.509 store context allocation failed\n", + (file == NULL) ? "stdin" : file); + goto end; + } + + X509_STORE_set_flags(ctx, vflags); + if (!X509_STORE_CTX_init(csc, ctx, x, uchain)) { + X509_STORE_CTX_free(csc); + printf("error %s: X.509 store context initialization failed\n", + (file == NULL) ? "stdin" : file); + goto end; + } + if (tchain != NULL) + X509_STORE_CTX_set0_trusted_stack(csc, tchain); + if (crls != NULL) + X509_STORE_CTX_set0_crls(csc, crls); + i = X509_verify_cert(csc); + if (i > 0 && X509_STORE_CTX_get_error(csc) == X509_V_OK) { + printf("%s: OK\n", (file == NULL) ? "stdin" : file); + ret = 1; + if (show_chain) { + int j; + + chain = X509_STORE_CTX_get1_chain(csc); + num_untrusted = X509_STORE_CTX_get_num_untrusted(csc); + printf("Chain:\n"); + for (j = 0; j < sk_X509_num(chain); j++) { + X509 *cert = sk_X509_value(chain, j); + printf("depth=%d: ", j); + X509_NAME_print_ex_fp(stdout, + X509_get_subject_name(cert), + 0, get_nameopt()); + if (j < num_untrusted) + printf(" (untrusted)"); + printf("\n"); + } + sk_X509_pop_free(chain, X509_free); + } + } else { + printf("error %s: verification failed\n", (file == NULL) ? "stdin" : file); + } + X509_STORE_CTX_free(csc); + + end: + if (i <= 0) + ERR_print_errors(bio_err); + X509_free(x); + + return ret; +} + +static int cb(int ok, X509_STORE_CTX *ctx) +{ + int cert_error = X509_STORE_CTX_get_error(ctx); + X509 *current_cert = X509_STORE_CTX_get_current_cert(ctx); + + if (!ok) { + if (current_cert != NULL) { + X509_NAME_print_ex(bio_err, + X509_get_subject_name(current_cert), + 0, get_nameopt()); + BIO_printf(bio_err, "\n"); + } + BIO_printf(bio_err, "%serror %d at %d depth lookup: %s\n", + X509_STORE_CTX_get0_parent_ctx(ctx) ? "[CRL path] " : "", + cert_error, + X509_STORE_CTX_get_error_depth(ctx), + X509_verify_cert_error_string(cert_error)); + + /* + * Pretend that some errors are ok, so they don't stop further + * processing of the certificate chain. Setting ok = 1 does this. + * After X509_verify_cert() is done, we verify that there were + * no actual errors, even if the returned value was positive. + */ + switch (cert_error) { + case X509_V_ERR_NO_EXPLICIT_POLICY: + policies_print(ctx); + /* fall thru */ + case X509_V_ERR_CERT_HAS_EXPIRED: + /* Continue even if the leaf is a self signed cert */ + case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: + /* Continue after extension errors too */ + case X509_V_ERR_INVALID_CA: + case X509_V_ERR_INVALID_NON_CA: + case X509_V_ERR_PATH_LENGTH_EXCEEDED: + case X509_V_ERR_INVALID_PURPOSE: + case X509_V_ERR_CRL_HAS_EXPIRED: + case X509_V_ERR_CRL_NOT_YET_VALID: + case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION: + ok = 1; + } + + return ok; + + } + if (cert_error == X509_V_OK && ok == 2) + policies_print(ctx); + if (!v_verbose) + ERR_clear_error(); + return ok; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/version.c b/trunk/3rdparty/openssl-1.1-fit/apps/version.c new file mode 100644 index 000000000..2aca16361 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/version.c @@ -0,0 +1,194 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#ifndef OPENSSL_NO_MD2 +# include +#endif +#ifndef OPENSSL_NO_RC4 +# include +#endif +#ifndef OPENSSL_NO_DES +# include +#endif +#ifndef OPENSSL_NO_IDEA +# include +#endif +#ifndef OPENSSL_NO_BF +# include +#endif + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_B, OPT_D, OPT_E, OPT_F, OPT_O, OPT_P, OPT_V, OPT_A, OPT_R +} OPTION_CHOICE; + +const OPTIONS version_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"a", OPT_A, '-', "Show all data"}, + {"b", OPT_B, '-', "Show build date"}, + {"d", OPT_D, '-', "Show configuration directory"}, + {"e", OPT_E, '-', "Show engines directory"}, + {"f", OPT_F, '-', "Show compiler flags used"}, + {"o", OPT_O, '-', "Show some internal datatype options"}, + {"p", OPT_P, '-', "Show target build platform"}, + {"r", OPT_R, '-', "Show random seeding options"}, + {"v", OPT_V, '-', "Show library version"}, + {NULL} +}; + +#if defined(OPENSSL_RAND_SEED_DEVRANDOM) || defined(OPENSSL_RAND_SEED_EGD) +static void printlist(const char *prefix, const char **dev) +{ + printf("%s (", prefix); + for ( ; *dev != NULL; dev++) + printf(" \"%s\"", *dev); + printf(" )"); +} +#endif + +int version_main(int argc, char **argv) +{ + int ret = 1, dirty = 0, seed = 0; + int cflags = 0, version = 0, date = 0, options = 0, platform = 0, dir = 0; + int engdir = 0; + char *prog; + OPTION_CHOICE o; + + prog = opt_init(argc, argv, version_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: +opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(version_options); + ret = 0; + goto end; + case OPT_B: + dirty = date = 1; + break; + case OPT_D: + dirty = dir = 1; + break; + case OPT_E: + dirty = engdir = 1; + break; + case OPT_F: + dirty = cflags = 1; + break; + case OPT_O: + dirty = options = 1; + break; + case OPT_P: + dirty = platform = 1; + break; + case OPT_R: + dirty = seed = 1; + break; + case OPT_V: + dirty = version = 1; + break; + case OPT_A: + seed = options = cflags = version = date = platform = dir = engdir + = 1; + break; + } + } + if (opt_num_rest() != 0) { + BIO_printf(bio_err, "Extra parameters given.\n"); + goto opthelp; + } + if (!dirty) + version = 1; + + if (version) { + if (OpenSSL_version_num() == OPENSSL_VERSION_NUMBER) + printf("%s\n", OpenSSL_version(OPENSSL_VERSION)); + else + printf("%s (Library: %s)\n", + OPENSSL_VERSION_TEXT, OpenSSL_version(OPENSSL_VERSION)); + } + if (date) + printf("%s\n", OpenSSL_version(OPENSSL_BUILT_ON)); + if (platform) + printf("%s\n", OpenSSL_version(OPENSSL_PLATFORM)); + if (options) { + printf("options: "); + printf("%s ", BN_options()); +#ifndef OPENSSL_NO_MD2 + printf("%s ", MD2_options()); +#endif +#ifndef OPENSSL_NO_RC4 + printf("%s ", RC4_options()); +#endif +#ifndef OPENSSL_NO_DES + printf("%s ", DES_options()); +#endif +#ifndef OPENSSL_NO_IDEA + printf("%s ", IDEA_options()); +#endif +#ifndef OPENSSL_NO_BF + printf("%s ", BF_options()); +#endif + printf("\n"); + } + if (cflags) + printf("%s\n", OpenSSL_version(OPENSSL_CFLAGS)); + if (dir) + printf("%s\n", OpenSSL_version(OPENSSL_DIR)); + if (engdir) + printf("%s\n", OpenSSL_version(OPENSSL_ENGINES_DIR)); + if (seed) { + printf("Seeding source:"); +#ifdef OPENSSL_RAND_SEED_RTDSC + printf(" rtdsc"); +#endif +#ifdef OPENSSL_RAND_SEED_RDCPU + printf(" rdrand ( rdseed rdrand )"); +#endif +#ifdef OPENSSL_RAND_SEED_LIBRANDOM + printf(" C-library-random"); +#endif +#ifdef OPENSSL_RAND_SEED_GETRANDOM + printf(" getrandom-syscall"); +#endif +#ifdef OPENSSL_RAND_SEED_DEVRANDOM + { + static const char *dev[] = { DEVRANDOM, NULL }; + printlist(" random-device", dev); + } +#endif +#ifdef OPENSSL_RAND_SEED_EGD + { + static const char *dev[] = { DEVRANDOM_EGD, NULL }; + printlist(" EGD", dev); + } +#endif +#ifdef OPENSSL_RAND_SEED_NONE + printf(" none"); +#endif +#ifdef OPENSSL_RAND_SEED_OS + printf(" os-specific"); +#endif + printf("\n"); + } + ret = 0; + end: + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/vms_decc_init.c b/trunk/3rdparty/openssl-1.1-fit/apps/vms_decc_init.c new file mode 100644 index 000000000..f83f7168e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/vms_decc_init.c @@ -0,0 +1,214 @@ +/* + * Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#if defined( __VMS) && !defined( OPENSSL_NO_DECC_INIT) && \ + defined( __DECC) && !defined( __VAX) && (__CRTL_VER >= 70301000) +# define USE_DECC_INIT 1 +#endif + +#ifdef USE_DECC_INIT + +/* + * ---------------------------------------------------------------------- + * decc_init() On non-VAX systems, uses LIB$INITIALIZE to set a collection + * of C RTL features without using the DECC$* logical name method. + * ---------------------------------------------------------------------- + */ + +# include +# include +# include + +# include "apps.h" + +/* Global storage. */ + +/* Flag to sense if decc_init() was called. */ + +int decc_init_done = -1; + +/* Structure to hold a DECC$* feature name and its desired value. */ + +typedef struct { + char *name; + int value; +} decc_feat_t; + +/* + * Array of DECC$* feature names and their desired values. Note: + * DECC$ARGV_PARSE_STYLE is the urgent one. + */ + +decc_feat_t decc_feat_array[] = { + /* Preserve command-line case with SET PROCESS/PARSE_STYLE=EXTENDED */ + {"DECC$ARGV_PARSE_STYLE", 1}, + + /* Preserve case for file names on ODS5 disks. */ + {"DECC$EFS_CASE_PRESERVE", 1}, + + /* + * Enable multiple dots (and most characters) in ODS5 file names, while + * preserving VMS-ness of ";version". + */ + {"DECC$EFS_CHARSET", 1}, + + /* List terminator. */ + {(char *)NULL, 0} +}; + + +char **copy_argv(int *argc, char *argv[]) +{ + /*- + * The note below is for historical purpose. On VMS now we always + * copy argv "safely." + * + * 2011-03-22 SMS. + * If we have 32-bit pointers everywhere, then we're safe, and + * we bypass this mess, as on non-VMS systems. + * Problem 1: Compaq/HP C before V7.3 always used 32-bit + * pointers for argv[]. + * Fix 1: For a 32-bit argv[], when we're using 64-bit pointers + * everywhere else, we always allocate and use a 64-bit + * duplicate of argv[]. + * Problem 2: Compaq/HP C V7.3 (Alpha, IA64) before ECO1 failed + * to NULL-terminate a 64-bit argv[]. (As this was written, the + * compiler ECO was available only on IA64.) + * Fix 2: Unless advised not to (VMS_TRUST_ARGV), we test a + * 64-bit argv[argc] for NULL, and, if necessary, use a + * (properly) NULL-terminated (64-bit) duplicate of argv[]. + * The same code is used in either case to duplicate argv[]. + * Some of these decisions could be handled in preprocessing, + * but the code tends to get even uglier, and the penalty for + * deciding at compile- or run-time is tiny. + */ + + int i, count = *argc; + char **newargv = app_malloc(sizeof(*newargv) * (count + 1), "argv copy"); + + for (i = 0; i < count; i++) + newargv[i] = argv[i]; + newargv[i] = NULL; + *argc = i; + return newargv; +} + +/* LIB$INITIALIZE initialization function. */ + +static void decc_init(void) +{ + char *openssl_debug_decc_init; + int verbose = 0; + int feat_index; + int feat_value; + int feat_value_max; + int feat_value_min; + int i; + int sts; + + /* Get debug option. */ + openssl_debug_decc_init = getenv("OPENSSL_DEBUG_DECC_INIT"); + if (openssl_debug_decc_init != NULL) { + verbose = strtol(openssl_debug_decc_init, NULL, 10); + if (verbose <= 0) { + verbose = 1; + } + } + + /* Set the global flag to indicate that LIB$INITIALIZE worked. */ + decc_init_done = 1; + + /* Loop through all items in the decc_feat_array[]. */ + + for (i = 0; decc_feat_array[i].name != NULL; i++) { + /* Get the feature index. */ + feat_index = decc$feature_get_index(decc_feat_array[i].name); + if (feat_index >= 0) { + /* Valid item. Collect its properties. */ + feat_value = decc$feature_get_value(feat_index, 1); + feat_value_min = decc$feature_get_value(feat_index, 2); + feat_value_max = decc$feature_get_value(feat_index, 3); + + /* Check the validity of our desired value. */ + if ((decc_feat_array[i].value >= feat_value_min) && + (decc_feat_array[i].value <= feat_value_max)) { + /* Valid value. Set it if necessary. */ + if (feat_value != decc_feat_array[i].value) { + sts = decc$feature_set_value(feat_index, + 1, decc_feat_array[i].value); + + if (verbose > 1) { + fprintf(stderr, " %s = %d, sts = %d.\n", + decc_feat_array[i].name, + decc_feat_array[i].value, sts); + } + } + } else { + /* Invalid DECC feature value. */ + fprintf(stderr, + " INVALID DECC$FEATURE VALUE, %d: %d <= %s <= %d.\n", + feat_value, + feat_value_min, decc_feat_array[i].name, + feat_value_max); + } + } else { + /* Invalid DECC feature name. */ + fprintf(stderr, + " UNKNOWN DECC$FEATURE: %s.\n", decc_feat_array[i].name); + } + } + + if (verbose > 0) { + fprintf(stderr, " DECC_INIT complete.\n"); + } +} + +/* Get "decc_init()" into a valid, loaded LIB$INITIALIZE PSECT. */ + +# pragma nostandard + +/* + * Establish the LIB$INITIALIZE PSECTs, with proper alignment and other + * attributes. Note that "nopic" is significant only on VAX. + */ +# pragma extern_model save + +# if __INITIAL_POINTER_SIZE == 64 +# define PSECT_ALIGN 3 +# else +# define PSECT_ALIGN 2 +# endif + +# pragma extern_model strict_refdef "LIB$INITIALIZ" PSECT_ALIGN, nopic, nowrt +const int spare[8] = { 0 }; + +# pragma extern_model strict_refdef "LIB$INITIALIZE" PSECT_ALIGN, nopic, nowrt +void (*const x_decc_init) () = decc_init; + +# pragma extern_model restore + +/* Fake reference to ensure loading the LIB$INITIALIZE PSECT. */ + +# pragma extern_model save + +int LIB$INITIALIZE(void); + +# pragma extern_model strict_refdef +int dmy_lib$initialize = (int)LIB$INITIALIZE; + +# pragma extern_model restore + +# pragma standard + +#else /* def USE_DECC_INIT */ + +/* Dummy code to avoid a %CC-W-EMPTYFILE complaint. */ +int decc_init_dummy(void); + +#endif /* def USE_DECC_INIT */ diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/vms_term_sock.c b/trunk/3rdparty/openssl-1.1-fit/apps/vms_term_sock.c new file mode 100644 index 000000000..9a90a1e79 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/vms_term_sock.c @@ -0,0 +1,591 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016 VMS Software, Inc. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifdef __VMS +# define OPENSSL_SYS_VMS +# pragma message disable DOLLARID + + +# include + +# if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS) +/* + * On VMS, you need to define this to get the declaration of fileno(). The + * value 2 is to make sure no function defined in POSIX-2 is left undefined. + */ +# define _POSIX_C_SOURCE 2 +# endif + +# include + +# undef _POSIX_C_SOURCE + +# include +# include +# include +# include +# include +# include +# include +# include +# include +# ifdef __alpha +# include +# else +typedef struct _iosb { /* Copied from IOSBDEF.H for Alpha */ +# pragma __nomember_alignment + __union { + __struct { + unsigned short int iosb$w_status; /* Final I/O status */ + __union { + __struct { /* 16-bit byte count variant */ + unsigned short int iosb$w_bcnt; /* 16-bit byte count */ + __union { + unsigned int iosb$l_dev_depend; /* 32-bit device dependent info */ + unsigned int iosb$l_pid; /* 32-bit pid */ + } iosb$r_l; + } iosb$r_bcnt_16; + __struct { /* 32-bit byte count variant */ + unsigned int iosb$l_bcnt; /* 32-bit byte count (unaligned) */ + unsigned short int iosb$w_dev_depend_high; /* 16-bit device dependent info */ + } iosb$r_bcnt_32; + } iosb$r_devdepend; + } iosb$r_io_64; + __struct { + __union { + unsigned int iosb$l_getxxi_status; /* Final GETxxI status */ + unsigned int iosb$l_reg_status; /* Final $Registry status */ + } iosb$r_l_status; + unsigned int iosb$l_reserved; /* Reserved field */ + } iosb$r_get_64; + } iosb$r_io_get; +} IOSB; + +# if !defined(__VAXC) +# define iosb$w_status iosb$r_io_get.iosb$r_io_64.iosb$w_status +# define iosb$w_bcnt iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_16.iosb$w_bcnt +# define iosb$r_l iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_16.iosb$r_l +# define iosb$l_dev_depend iosb$r_l.iosb$l_dev_depend +# define iosb$l_pid iosb$r_l.iosb$l_pid +# define iosb$l_bcnt iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_32.iosb$l_bcnt +# define iosb$w_dev_depend_high iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_32.iosb$w_dev_depend_high +# define iosb$l_getxxi_status iosb$r_io_get.iosb$r_get_64.iosb$r_l_status.iosb$l_getxxi_status +# define iosb$l_reg_status iosb$r_io_get.iosb$r_get_64.iosb$r_l_status.iosb$l_reg_status +# endif /* #if !defined(__VAXC) */ + +# endif /* End of IOSBDEF */ + +# include +# include +# include +# include +# include +# include + +# include "vms_term_sock.h" + +# ifdef __alpha +static struct _iosb TerminalDeviceIosb; +# else +IOSB TerminalDeviceIosb; +# endif + +static char TerminalDeviceBuff[255 + 2]; +static int TerminalSocketPair[2] = {0, 0}; +static unsigned short TerminalDeviceChan = 0; + +static int CreateSocketPair (int, int, int, int *); +static void SocketPairTimeoutAst (int); +static int TerminalDeviceAst (int); +static void LogMessage (char *, ...); + +/* +** Socket Pair Timeout Value (must be 0-59 seconds) +*/ +# define SOCKET_PAIR_TIMEOUT_VALUE 20 + +/* +** Socket Pair Timeout Block which is passed to timeout AST +*/ +typedef struct _SocketPairTimeoutBlock { + unsigned short SockChan1; + unsigned short SockChan2; +} SPTB; + +# ifdef TERM_SOCK_TEST + +/*----------------------------------------------------------------------------*/ +/* */ +/*----------------------------------------------------------------------------*/ +int main (int argc, char *argv[], char *envp[]) +{ + char TermBuff[80]; + int TermSock, + status, + len; + + LogMessage ("Enter 'q' or 'Q' to quit ..."); + while (strcasecmp (TermBuff, "Q")) { + /* + ** Create the terminal socket + */ + status = TerminalSocket (TERM_SOCK_CREATE, &TermSock); + if (status != TERM_SOCK_SUCCESS) + exit (1); + + /* + ** Process the terminal input + */ + LogMessage ("Waiting on terminal I/O ...\n"); + len = recv (TermSock, TermBuff, sizeof(TermBuff), 0) ; + TermBuff[len] = '\0'; + LogMessage ("Received terminal I/O [%s]", TermBuff); + + /* + ** Delete the terminal socket + */ + status = TerminalSocket (TERM_SOCK_DELETE, &TermSock); + if (status != TERM_SOCK_SUCCESS) + exit (1); + } + + return 1; + +} +# endif + +/*----------------------------------------------------------------------------*/ +/* */ +/*----------------------------------------------------------------------------*/ +int TerminalSocket (int FunctionCode, int *ReturnSocket) +{ + int status; + $DESCRIPTOR (TerminalDeviceDesc, "SYS$COMMAND"); + + /* + ** Process the requested function code + */ + switch (FunctionCode) { + case TERM_SOCK_CREATE: + /* + ** Create a socket pair + */ + status = CreateSocketPair (AF_INET, SOCK_STREAM, 0, TerminalSocketPair); + if (status == -1) { + LogMessage ("TerminalSocket: CreateSocketPair () - %08X", status); + if (TerminalSocketPair[0]) + close (TerminalSocketPair[0]); + if (TerminalSocketPair[1]) + close (TerminalSocketPair[1]); + return TERM_SOCK_FAILURE; + } + + /* + ** Assign a channel to the terminal device + */ + status = sys$assign (&TerminalDeviceDesc, + &TerminalDeviceChan, + 0, 0, 0); + if (! (status & 1)) { + LogMessage ("TerminalSocket: SYS$ASSIGN () - %08X", status); + close (TerminalSocketPair[0]); + close (TerminalSocketPair[1]); + return TERM_SOCK_FAILURE; + } + + /* + ** Queue an async IO to the terminal device + */ + status = sys$qio (EFN$C_ENF, + TerminalDeviceChan, + IO$_READVBLK, + &TerminalDeviceIosb, + TerminalDeviceAst, + 0, + TerminalDeviceBuff, + sizeof(TerminalDeviceBuff) - 2, + 0, 0, 0, 0); + if (! (status & 1)) { + LogMessage ("TerminalSocket: SYS$QIO () - %08X", status); + close (TerminalSocketPair[0]); + close (TerminalSocketPair[1]); + return TERM_SOCK_FAILURE; + } + + /* + ** Return the input side of the socket pair + */ + *ReturnSocket = TerminalSocketPair[1]; + break; + + case TERM_SOCK_DELETE: + /* + ** Cancel any pending IO on the terminal channel + */ + status = sys$cancel (TerminalDeviceChan); + if (! (status & 1)) { + LogMessage ("TerminalSocket: SYS$CANCEL () - %08X", status); + close (TerminalSocketPair[0]); + close (TerminalSocketPair[1]); + return TERM_SOCK_FAILURE; + } + + /* + ** Deassign the terminal channel + */ + status = sys$dassgn (TerminalDeviceChan); + if (! (status & 1)) { + LogMessage ("TerminalSocket: SYS$DASSGN () - %08X", status); + close (TerminalSocketPair[0]); + close (TerminalSocketPair[1]); + return TERM_SOCK_FAILURE; + } + + /* + ** Close the terminal socket pair + */ + close (TerminalSocketPair[0]); + close (TerminalSocketPair[1]); + + /* + ** Return the initialized socket + */ + *ReturnSocket = 0; + break; + + default: + /* + ** Invalid function code + */ + LogMessage ("TerminalSocket: Invalid Function Code - %d", FunctionCode); + return TERM_SOCK_FAILURE; + break; + } + + /* + ** Return success + */ + return TERM_SOCK_SUCCESS; + +} + +/*----------------------------------------------------------------------------*/ +/* */ +/*----------------------------------------------------------------------------*/ +static int CreateSocketPair (int SocketFamily, + int SocketType, + int SocketProtocol, + int *SocketPair) +{ + struct dsc$descriptor AscTimeDesc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL}; + static const char* LocalHostAddr = {"127.0.0.1"}; + unsigned short TcpAcceptChan = 0, + TcpDeviceChan = 0; + unsigned long BinTimeBuff[2]; + struct sockaddr_in sin; + char AscTimeBuff[32]; + short LocalHostPort; + int status; + unsigned int slen; + +# ifdef __alpha + struct _iosb iosb; +# else + IOSB iosb; +# endif + + int SockDesc1 = 0, + SockDesc2 = 0; + SPTB sptb; + $DESCRIPTOR (TcpDeviceDesc, "TCPIP$DEVICE"); + + /* + ** Create a socket + */ + SockDesc1 = socket (SocketFamily, SocketType, 0); + if (SockDesc1 < 0) { + LogMessage ("CreateSocketPair: socket () - %d", errno); + return -1; + } + + /* + ** Initialize the socket information + */ + slen = sizeof(sin); + memset ((char *) &sin, 0, slen); + sin.sin_family = SocketFamily; + sin.sin_addr.s_addr = inet_addr (LocalHostAddr); + sin.sin_port = 0; + + /* + ** Bind the socket to the local IP + */ + status = bind (SockDesc1, (struct sockaddr *) &sin, slen); + if (status < 0) { + LogMessage ("CreateSocketPair: bind () - %d", errno); + close (SockDesc1); + return -1; + } + + /* + ** Get the socket name so we can save the port number + */ + status = getsockname (SockDesc1, (struct sockaddr *) &sin, &slen); + if (status < 0) { + LogMessage ("CreateSocketPair: getsockname () - %d", errno); + close (SockDesc1); + return -1; + } else + LocalHostPort = sin.sin_port; + + /* + ** Setup a listen for the socket + */ + listen (SockDesc1, 5); + + /* + ** Get the binary (64-bit) time of the specified timeout value + */ + sprintf (AscTimeBuff, "0 0:0:%02d.00", SOCKET_PAIR_TIMEOUT_VALUE); + AscTimeDesc.dsc$w_length = strlen (AscTimeBuff); + AscTimeDesc.dsc$a_pointer = AscTimeBuff; + status = sys$bintim (&AscTimeDesc, BinTimeBuff); + if (! (status & 1)) { + LogMessage ("CreateSocketPair: SYS$BINTIM () - %08X", status); + close (SockDesc1); + return -1; + } + + /* + ** Assign another channel to the TCP/IP device for the accept. + ** This is the channel that ends up being connected to. + */ + status = sys$assign (&TcpDeviceDesc, &TcpDeviceChan, 0, 0, 0); + if (! (status & 1)) { + LogMessage ("CreateSocketPair: SYS$ASSIGN () - %08X", status); + close (SockDesc1); + return -1; + } + + /* + ** Get the channel of the first socket for the accept + */ + TcpAcceptChan = decc$get_sdc (SockDesc1); + + /* + ** Perform the accept using $QIO so we can do this asynchronously + */ + status = sys$qio (EFN$C_ENF, + TcpAcceptChan, + IO$_ACCESS | IO$M_ACCEPT, + &iosb, + 0, 0, 0, 0, 0, + &TcpDeviceChan, + 0, 0); + if (! (status & 1)) { + LogMessage ("CreateSocketPair: SYS$QIO () - %08X", status); + close (SockDesc1); + sys$dassgn (TcpDeviceChan); + return -1; + } + + /* + ** Create the second socket to do the connect + */ + SockDesc2 = socket (SocketFamily, SocketType, 0); + if (SockDesc2 < 0) { + LogMessage ("CreateSocketPair: socket () - %d", errno); + sys$cancel (TcpAcceptChan); + close (SockDesc1); + sys$dassgn (TcpDeviceChan); + return (-1) ; + } + + /* + ** Setup the Socket Pair Timeout Block + */ + sptb.SockChan1 = TcpAcceptChan; + sptb.SockChan2 = decc$get_sdc (SockDesc2); + + /* + ** Before we block on the connect, set a timer that can cancel I/O on our + ** two sockets if it never connects. + */ + status = sys$setimr (EFN$C_ENF, + BinTimeBuff, + SocketPairTimeoutAst, + &sptb, + 0); + if (! (status & 1)) { + LogMessage ("CreateSocketPair: SYS$SETIMR () - %08X", status); + sys$cancel (TcpAcceptChan); + close (SockDesc1); + close (SockDesc2); + sys$dassgn (TcpDeviceChan); + return -1; + } + + /* + ** Now issue the connect + */ + memset ((char *) &sin, 0, sizeof(sin)) ; + sin.sin_family = SocketFamily; + sin.sin_addr.s_addr = inet_addr (LocalHostAddr) ; + sin.sin_port = LocalHostPort ; + + status = connect (SockDesc2, (struct sockaddr *) &sin, sizeof(sin)); + if (status < 0 ) { + LogMessage ("CreateSocketPair: connect () - %d", errno); + sys$cantim (&sptb, 0); + sys$cancel (TcpAcceptChan); + close (SockDesc1); + close (SockDesc2); + sys$dassgn (TcpDeviceChan); + return -1; + } + + /* + ** Wait for the asynch $QIO to finish. Note that if the I/O was aborted + ** (SS$_ABORT), then we probably canceled it from the AST routine - so log + ** a timeout. + */ + status = sys$synch (EFN$C_ENF, &iosb); + if (! (iosb.iosb$w_status & 1)) { + if (iosb.iosb$w_status == SS$_ABORT) + LogMessage ("CreateSocketPair: SYS$QIO(iosb) timeout"); + else { + LogMessage ("CreateSocketPair: SYS$QIO(iosb) - %d", + iosb.iosb$w_status); + sys$cantim (&sptb, 0); + } + close (SockDesc1); + close (SockDesc2); + sys$dassgn (TcpDeviceChan); + return -1; + } + + /* + ** Here we're successfully connected, so cancel the timer, convert the + ** I/O channel to a socket fd, close the listener socket and return the + ** connected pair. + */ + sys$cantim (&sptb, 0); + + close (SockDesc1) ; + SocketPair[0] = SockDesc2 ; + SocketPair[1] = socket_fd (TcpDeviceChan); + + return (0) ; + +} + +/*----------------------------------------------------------------------------*/ +/* */ +/*----------------------------------------------------------------------------*/ +static void SocketPairTimeoutAst (int astparm) +{ + SPTB *sptb = (SPTB *) astparm; + + sys$cancel (sptb->SockChan2); /* Cancel the connect() */ + sys$cancel (sptb->SockChan1); /* Cancel the accept() */ + + return; + +} + +/*----------------------------------------------------------------------------*/ +/* */ +/*----------------------------------------------------------------------------*/ +static int TerminalDeviceAst (int astparm) +{ + int status; + + /* + ** Terminate the terminal buffer + */ + TerminalDeviceBuff[TerminalDeviceIosb.iosb$w_bcnt] = '\0'; + strcat (TerminalDeviceBuff, "\n"); + + /* + ** Send the data read from the terminal device through the socket pair + */ + send (TerminalSocketPair[0], TerminalDeviceBuff, + TerminalDeviceIosb.iosb$w_bcnt + 1, 0); + + /* + ** Queue another async IO to the terminal device + */ + status = sys$qio (EFN$C_ENF, + TerminalDeviceChan, + IO$_READVBLK, + &TerminalDeviceIosb, + TerminalDeviceAst, + 0, + TerminalDeviceBuff, + sizeof(TerminalDeviceBuff) - 1, + 0, 0, 0, 0); + + /* + ** Return status + */ + return status; + +} + +/*----------------------------------------------------------------------------*/ +/* */ +/*----------------------------------------------------------------------------*/ +static void LogMessage (char *msg, ...) +{ + char *Month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + static unsigned int pid = 0; + va_list args; + time_t CurTime; + struct tm *LocTime; + char MsgBuff[256]; + + /* + ** Get the process pid + */ + if (pid == 0) + pid = getpid (); + + /* + ** Convert the current time into local time + */ + CurTime = time (NULL); + LocTime = localtime (&CurTime); + + /* + ** Format the message buffer + */ + sprintf (MsgBuff, "%02d-%s-%04d %02d:%02d:%02d [%08X] %s\n", + LocTime->tm_mday, Month[LocTime->tm_mon], + (LocTime->tm_year + 1900), LocTime->tm_hour, LocTime->tm_min, + LocTime->tm_sec, pid, msg); + + /* + ** Get any variable arguments and add them to the print of the message + ** buffer + */ + va_start (args, msg); + vfprintf (stderr, MsgBuff, args); + va_end (args); + + /* + ** Flush standard error output + */ + fsync (fileno (stderr)); + + return; + +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/vms_term_sock.h b/trunk/3rdparty/openssl-1.1-fit/apps/vms_term_sock.h new file mode 100644 index 000000000..c4d1702d7 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/vms_term_sock.h @@ -0,0 +1,31 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016 VMS Software, Inc. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef TERM_SOCK_H +# define TERM_SOCK_H + +/* +** Terminal Socket Function Codes +*/ +# define TERM_SOCK_CREATE 1 +# define TERM_SOCK_DELETE 2 + +/* +** Terminal Socket Status Codes +*/ +# define TERM_SOCK_FAILURE 0 +# define TERM_SOCK_SUCCESS 1 + +/* +** Terminal Socket Prototype +*/ +int TerminalSocket (int FunctionCode, int *ReturnSocket); + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/win32_init.c b/trunk/3rdparty/openssl-1.1-fit/apps/win32_init.c new file mode 100644 index 000000000..df4bff41a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/win32_init.c @@ -0,0 +1,307 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include + +#if defined(CP_UTF8) + +static UINT saved_cp; +static int newargc; +static char **newargv; + +static void cleanup(void) +{ + int i; + + SetConsoleOutputCP(saved_cp); + + for (i = 0; i < newargc; i++) + free(newargv[i]); + + free(newargv); +} + +/* + * Incrementally [re]allocate newargv and keep it NULL-terminated. + */ +static int validate_argv(int argc) +{ + static int size = 0; + + if (argc >= size) { + char **ptr; + + while (argc >= size) + size += 64; + + ptr = realloc(newargv, size * sizeof(newargv[0])); + if (ptr == NULL) + return 0; + + (newargv = ptr)[argc] = NULL; + } else { + newargv[argc] = NULL; + } + + return 1; +} + +static int process_glob(WCHAR *wstr, int wlen) +{ + int i, slash, udlen; + WCHAR saved_char; + WIN32_FIND_DATAW data; + HANDLE h; + + /* + * Note that we support wildcard characters only in filename part + * of the path, and not in directories. Windows users are used to + * this, that's why recursive glob processing is not implemented. + */ + /* + * Start by looking for last slash or backslash, ... + */ + for (slash = 0, i = 0; i < wlen; i++) + if (wstr[i] == L'/' || wstr[i] == L'\\') + slash = i + 1; + /* + * ... then look for asterisk or question mark in the file name. + */ + for (i = slash; i < wlen; i++) + if (wstr[i] == L'*' || wstr[i] == L'?') + break; + + if (i == wlen) + return 0; /* definitely not a glob */ + + saved_char = wstr[wlen]; + wstr[wlen] = L'\0'; + h = FindFirstFileW(wstr, &data); + wstr[wlen] = saved_char; + if (h == INVALID_HANDLE_VALUE) + return 0; /* not a valid glob, just pass... */ + + if (slash) + udlen = WideCharToMultiByte(CP_UTF8, 0, wstr, slash, + NULL, 0, NULL, NULL); + else + udlen = 0; + + do { + int uflen; + char *arg; + + /* + * skip over . and .. + */ + if (data.cFileName[0] == L'.') { + if ((data.cFileName[1] == L'\0') || + (data.cFileName[1] == L'.' && data.cFileName[2] == L'\0')) + continue; + } + + if (!validate_argv(newargc + 1)) + break; + + /* + * -1 below means "scan for trailing '\0' *and* count it", + * so that |uflen| covers even trailing '\0'. + */ + uflen = WideCharToMultiByte(CP_UTF8, 0, data.cFileName, -1, + NULL, 0, NULL, NULL); + + arg = malloc(udlen + uflen); + if (arg == NULL) + break; + + if (udlen) + WideCharToMultiByte(CP_UTF8, 0, wstr, slash, + arg, udlen, NULL, NULL); + + WideCharToMultiByte(CP_UTF8, 0, data.cFileName, -1, + arg + udlen, uflen, NULL, NULL); + + newargv[newargc++] = arg; + } while (FindNextFileW(h, &data)); + + CloseHandle(h); + + return 1; +} + +void win32_utf8argv(int *argc, char **argv[]) +{ + const WCHAR *wcmdline; + WCHAR *warg, *wend, *p; + int wlen, ulen, valid = 1; + char *arg; + + if (GetEnvironmentVariableW(L"OPENSSL_WIN32_UTF8", NULL, 0) == 0) + return; + + newargc = 0; + newargv = NULL; + if (!validate_argv(newargc)) + return; + + wcmdline = GetCommandLineW(); + if (wcmdline == NULL) return; + + /* + * make a copy of the command line, since we might have to modify it... + */ + wlen = wcslen(wcmdline); + p = _alloca((wlen + 1) * sizeof(WCHAR)); + wcscpy(p, wcmdline); + + while (*p != L'\0') { + int in_quote = 0; + + if (*p == L' ' || *p == L'\t') { + p++; /* skip over white spaces */ + continue; + } + + /* + * Note: because we may need to fiddle with the number of backslashes, + * the argument string is copied into itself. This is safe because + * the number of characters will never expand. + */ + warg = wend = p; + while (*p != L'\0' + && (in_quote || (*p != L' ' && *p != L'\t'))) { + switch (*p) { + case L'\\': + /* + * Microsoft documentation on how backslashes are treated + * is: + * + * + Backslashes are interpreted literally, unless they + * immediately precede a double quotation mark. + * + If an even number of backslashes is followed by a double + * quotation mark, one backslash is placed in the argv array + * for every pair of backslashes, and the double quotation + * mark is interpreted as a string delimiter. + * + If an odd number of backslashes is followed by a double + * quotation mark, one backslash is placed in the argv array + * for every pair of backslashes, and the double quotation + * mark is "escaped" by the remaining backslash, causing a + * literal double quotation mark (") to be placed in argv. + * + * Ref: https://msdn.microsoft.com/en-us/library/17w5ykft.aspx + * + * Though referred page doesn't mention it, multiple qouble + * quotes are also special. Pair of double quotes in quoted + * string is counted as single double quote. + */ + { + const WCHAR *q = p; + int i; + + while (*p == L'\\') + p++; + + if (*p == L'"') { + int i; + + for (i = (p - q) / 2; i > 0; i--) + *wend++ = L'\\'; + + /* + * if odd amount of backslashes before the quote, + * said quote is part of the argument, not a delimiter + */ + if ((p - q) % 2 == 1) + *wend++ = *p++; + } else { + for (i = p - q; i > 0; i--) + *wend++ = L'\\'; + } + } + break; + case L'"': + /* + * Without the preceding backslash (or when preceded with an + * even number of backslashes), the double quote is a simple + * string delimiter and just slightly change the parsing state + */ + if (in_quote && p[1] == L'"') + *wend++ = *p++; + else + in_quote = !in_quote; + p++; + break; + default: + /* + * Any other non-delimiter character is just taken verbatim + */ + *wend++ = *p++; + } + } + + wlen = wend - warg; + + if (wlen == 0 || !process_glob(warg, wlen)) { + if (!validate_argv(newargc + 1)) { + valid = 0; + break; + } + + ulen = 0; + if (wlen > 0) { + ulen = WideCharToMultiByte(CP_UTF8, 0, warg, wlen, + NULL, 0, NULL, NULL); + if (ulen <= 0) + continue; + } + + arg = malloc(ulen + 1); + if (arg == NULL) { + valid = 0; + break; + } + + if (wlen > 0) + WideCharToMultiByte(CP_UTF8, 0, warg, wlen, + arg, ulen, NULL, NULL); + arg[ulen] = '\0'; + + newargv[newargc++] = arg; + } + } + + if (valid) { + saved_cp = GetConsoleOutputCP(); + SetConsoleOutputCP(CP_UTF8); + + *argc = newargc; + *argv = newargv; + + atexit(cleanup); + } else if (newargv != NULL) { + int i; + + for (i = 0; i < newargc; i++) + free(newargv[i]); + + free(newargv); + + newargc = 0; + newargv = NULL; + } + + return; +} +#else +void win32_utf8argv(int *argc, char **argv[]) +{ return; } +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/apps/x509.c b/trunk/3rdparty/openssl-1.1-fit/apps/x509.c new file mode 100644 index 000000000..81291a9a4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/apps/x509.c @@ -0,0 +1,1196 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef OPENSSL_NO_RSA +# include +#endif +#ifndef OPENSSL_NO_DSA +# include +#endif + +#undef POSTFIX +#define POSTFIX ".srl" +#define DEF_DAYS 30 + +static int callb(int ok, X509_STORE_CTX *ctx); +static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, + const EVP_MD *digest, CONF *conf, const char *section, + int preserve_dates); +static int x509_certify(X509_STORE *ctx, const char *CAfile, const EVP_MD *digest, + X509 *x, X509 *xca, EVP_PKEY *pkey, + STACK_OF(OPENSSL_STRING) *sigopts, const char *serialfile, + int create, int days, int clrext, CONF *conf, + const char *section, ASN1_INTEGER *sno, int reqfile, + int preserve_dates); +static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt); +static int print_x509v3_exts(BIO *bio, X509 *x, const char *exts); + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_INFORM, OPT_OUTFORM, OPT_KEYFORM, OPT_REQ, OPT_CAFORM, + OPT_CAKEYFORM, OPT_SIGOPT, OPT_DAYS, OPT_PASSIN, OPT_EXTFILE, + OPT_EXTENSIONS, OPT_IN, OPT_OUT, OPT_SIGNKEY, OPT_CA, + OPT_CAKEY, OPT_CASERIAL, OPT_SET_SERIAL, OPT_FORCE_PUBKEY, + OPT_ADDTRUST, OPT_ADDREJECT, OPT_SETALIAS, OPT_CERTOPT, OPT_NAMEOPT, + OPT_C, OPT_EMAIL, OPT_OCSP_URI, OPT_SERIAL, OPT_NEXT_SERIAL, + OPT_MODULUS, OPT_PUBKEY, OPT_X509TOREQ, OPT_TEXT, OPT_HASH, + OPT_ISSUER_HASH, OPT_SUBJECT, OPT_ISSUER, OPT_FINGERPRINT, OPT_DATES, + OPT_PURPOSE, OPT_STARTDATE, OPT_ENDDATE, OPT_CHECKEND, OPT_CHECKHOST, + OPT_CHECKEMAIL, OPT_CHECKIP, OPT_NOOUT, OPT_TRUSTOUT, OPT_CLRTRUST, + OPT_CLRREJECT, OPT_ALIAS, OPT_CACREATESERIAL, OPT_CLREXT, OPT_OCSPID, + OPT_SUBJECT_HASH_OLD, + OPT_ISSUER_HASH_OLD, + OPT_BADSIG, OPT_MD, OPT_ENGINE, OPT_NOCERT, OPT_PRESERVE_DATES, + OPT_R_ENUM, OPT_EXT +} OPTION_CHOICE; + +const OPTIONS x509_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"inform", OPT_INFORM, 'f', + "Input format - default PEM (one of DER or PEM)"}, + {"in", OPT_IN, '<', "Input file - default stdin"}, + {"outform", OPT_OUTFORM, 'f', + "Output format - default PEM (one of DER or PEM)"}, + {"out", OPT_OUT, '>', "Output file - default stdout"}, + {"keyform", OPT_KEYFORM, 'F', "Private key format - default PEM"}, + {"passin", OPT_PASSIN, 's', "Private key password/pass-phrase source"}, + {"serial", OPT_SERIAL, '-', "Print serial number value"}, + {"subject_hash", OPT_HASH, '-', "Print subject hash value"}, + {"issuer_hash", OPT_ISSUER_HASH, '-', "Print issuer hash value"}, + {"hash", OPT_HASH, '-', "Synonym for -subject_hash"}, + {"subject", OPT_SUBJECT, '-', "Print subject DN"}, + {"issuer", OPT_ISSUER, '-', "Print issuer DN"}, + {"email", OPT_EMAIL, '-', "Print email address(es)"}, + {"startdate", OPT_STARTDATE, '-', "Set notBefore field"}, + {"enddate", OPT_ENDDATE, '-', "Set notAfter field"}, + {"purpose", OPT_PURPOSE, '-', "Print out certificate purposes"}, + {"dates", OPT_DATES, '-', "Both Before and After dates"}, + {"modulus", OPT_MODULUS, '-', "Print the RSA key modulus"}, + {"pubkey", OPT_PUBKEY, '-', "Output the public key"}, + {"fingerprint", OPT_FINGERPRINT, '-', + "Print the certificate fingerprint"}, + {"alias", OPT_ALIAS, '-', "Output certificate alias"}, + {"noout", OPT_NOOUT, '-', "No output, just status"}, + {"nocert", OPT_NOCERT, '-', "No certificate output"}, + {"ocspid", OPT_OCSPID, '-', + "Print OCSP hash values for the subject name and public key"}, + {"ocsp_uri", OPT_OCSP_URI, '-', "Print OCSP Responder URL(s)"}, + {"trustout", OPT_TRUSTOUT, '-', "Output a trusted certificate"}, + {"clrtrust", OPT_CLRTRUST, '-', "Clear all trusted purposes"}, + {"clrext", OPT_CLREXT, '-', "Clear all certificate extensions"}, + {"addtrust", OPT_ADDTRUST, 's', "Trust certificate for a given purpose"}, + {"addreject", OPT_ADDREJECT, 's', + "Reject certificate for a given purpose"}, + {"setalias", OPT_SETALIAS, 's', "Set certificate alias"}, + {"days", OPT_DAYS, 'n', + "How long till expiry of a signed certificate - def 30 days"}, + {"checkend", OPT_CHECKEND, 'M', + "Check whether the cert expires in the next arg seconds"}, + {OPT_MORE_STR, 1, 1, "Exit 1 if so, 0 if not"}, + {"signkey", OPT_SIGNKEY, '<', "Self sign cert with arg"}, + {"x509toreq", OPT_X509TOREQ, '-', + "Output a certification request object"}, + {"req", OPT_REQ, '-', "Input is a certificate request, sign and output"}, + {"CA", OPT_CA, '<', "Set the CA certificate, must be PEM format"}, + {"CAkey", OPT_CAKEY, 's', + "The CA key, must be PEM format; if not in CAfile"}, + {"CAcreateserial", OPT_CACREATESERIAL, '-', + "Create serial number file if it does not exist"}, + {"CAserial", OPT_CASERIAL, 's', "Serial file"}, + {"set_serial", OPT_SET_SERIAL, 's', "Serial number to use"}, + {"text", OPT_TEXT, '-', "Print the certificate in text form"}, + {"ext", OPT_EXT, 's', "Print various X509V3 extensions"}, + {"C", OPT_C, '-', "Print out C code forms"}, + {"extfile", OPT_EXTFILE, '<', "File with X509V3 extensions to add"}, + OPT_R_OPTIONS, + {"extensions", OPT_EXTENSIONS, 's', "Section from config file to use"}, + {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"}, + {"certopt", OPT_CERTOPT, 's', "Various certificate text options"}, + {"checkhost", OPT_CHECKHOST, 's', "Check certificate matches host"}, + {"checkemail", OPT_CHECKEMAIL, 's', "Check certificate matches email"}, + {"checkip", OPT_CHECKIP, 's', "Check certificate matches ipaddr"}, + {"CAform", OPT_CAFORM, 'F', "CA format - default PEM"}, + {"CAkeyform", OPT_CAKEYFORM, 'f', "CA key format - default PEM"}, + {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"}, + {"force_pubkey", OPT_FORCE_PUBKEY, '<', "Force the Key to put inside certificate"}, + {"next_serial", OPT_NEXT_SERIAL, '-', "Increment current certificate serial number"}, + {"clrreject", OPT_CLRREJECT, '-', + "Clears all the prohibited or rejected uses of the certificate"}, + {"badsig", OPT_BADSIG, '-', "Corrupt last byte of certificate signature (for test)"}, + {"", OPT_MD, '-', "Any supported digest"}, +#ifndef OPENSSL_NO_MD5 + {"subject_hash_old", OPT_SUBJECT_HASH_OLD, '-', + "Print old-style (MD5) issuer hash value"}, + {"issuer_hash_old", OPT_ISSUER_HASH_OLD, '-', + "Print old-style (MD5) subject hash value"}, +#endif +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + {"preserve_dates", OPT_PRESERVE_DATES, '-', "preserve existing dates when signing"}, + {NULL} +}; + +int x509_main(int argc, char **argv) +{ + ASN1_INTEGER *sno = NULL; + ASN1_OBJECT *objtmp = NULL; + BIO *out = NULL; + CONF *extconf = NULL; + EVP_PKEY *Upkey = NULL, *CApkey = NULL, *fkey = NULL; + STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL; + STACK_OF(OPENSSL_STRING) *sigopts = NULL; + X509 *x = NULL, *xca = NULL; + X509_REQ *req = NULL, *rq = NULL; + X509_STORE *ctx = NULL; + const EVP_MD *digest = NULL; + char *CAkeyfile = NULL, *CAserial = NULL, *fkeyfile = NULL, *alias = NULL; + char *checkhost = NULL, *checkemail = NULL, *checkip = NULL, *exts = NULL; + char *extsect = NULL, *extfile = NULL, *passin = NULL, *passinarg = NULL; + char *infile = NULL, *outfile = NULL, *keyfile = NULL, *CAfile = NULL; + char *prog; + int x509req = 0, days = DEF_DAYS, modulus = 0, pubkey = 0, pprint = 0; + int C = 0, CAformat = FORMAT_PEM, CAkeyformat = FORMAT_PEM; + int fingerprint = 0, reqfile = 0, checkend = 0; + int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM; + int next_serial = 0, subject_hash = 0, issuer_hash = 0, ocspid = 0; + int noout = 0, sign_flag = 0, CA_flag = 0, CA_createserial = 0, email = 0; + int ocsp_uri = 0, trustout = 0, clrtrust = 0, clrreject = 0, aliasout = 0; + int ret = 1, i, num = 0, badsig = 0, clrext = 0, nocert = 0; + int text = 0, serial = 0, subject = 0, issuer = 0, startdate = 0, ext = 0; + int enddate = 0; + time_t checkoffset = 0; + unsigned long certflag = 0; + int preserve_dates = 0; + OPTION_CHOICE o; + ENGINE *e = NULL; +#ifndef OPENSSL_NO_MD5 + int subject_hash_old = 0, issuer_hash_old = 0; +#endif + + ctx = X509_STORE_new(); + if (ctx == NULL) + goto end; + X509_STORE_set_verify_cb(ctx, callb); + + prog = opt_init(argc, argv, x509_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(x509_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &outformat)) + goto opthelp; + break; + case OPT_KEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &keyformat)) + goto opthelp; + break; + case OPT_CAFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &CAformat)) + goto opthelp; + break; + case OPT_CAKEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &CAkeyformat)) + goto opthelp; + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_REQ: + reqfile = 1; + break; + + case OPT_SIGOPT: + if (!sigopts) + sigopts = sk_OPENSSL_STRING_new_null(); + if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg())) + goto opthelp; + break; + case OPT_DAYS: + if (preserve_dates) + goto opthelp; + days = atoi(opt_arg()); + break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; + case OPT_EXTFILE: + extfile = opt_arg(); + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; + case OPT_EXTENSIONS: + extsect = opt_arg(); + break; + case OPT_SIGNKEY: + keyfile = opt_arg(); + sign_flag = ++num; + break; + case OPT_CA: + CAfile = opt_arg(); + CA_flag = ++num; + break; + case OPT_CAKEY: + CAkeyfile = opt_arg(); + break; + case OPT_CASERIAL: + CAserial = opt_arg(); + break; + case OPT_SET_SERIAL: + if (sno != NULL) { + BIO_printf(bio_err, "Serial number supplied twice\n"); + goto opthelp; + } + if ((sno = s2i_ASN1_INTEGER(NULL, opt_arg())) == NULL) + goto opthelp; + break; + case OPT_FORCE_PUBKEY: + fkeyfile = opt_arg(); + break; + case OPT_ADDTRUST: + if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) { + BIO_printf(bio_err, + "%s: Invalid trust object value %s\n", + prog, opt_arg()); + goto opthelp; + } + if (trust == NULL && (trust = sk_ASN1_OBJECT_new_null()) == NULL) + goto end; + sk_ASN1_OBJECT_push(trust, objtmp); + objtmp = NULL; + trustout = 1; + break; + case OPT_ADDREJECT: + if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) { + BIO_printf(bio_err, + "%s: Invalid reject object value %s\n", + prog, opt_arg()); + goto opthelp; + } + if (reject == NULL + && (reject = sk_ASN1_OBJECT_new_null()) == NULL) + goto end; + sk_ASN1_OBJECT_push(reject, objtmp); + objtmp = NULL; + trustout = 1; + break; + case OPT_SETALIAS: + alias = opt_arg(); + trustout = 1; + break; + case OPT_CERTOPT: + if (!set_cert_ex(&certflag, opt_arg())) + goto opthelp; + break; + case OPT_NAMEOPT: + if (!set_nameopt(opt_arg())) + goto opthelp; + break; + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; + case OPT_C: + C = ++num; + break; + case OPT_EMAIL: + email = ++num; + break; + case OPT_OCSP_URI: + ocsp_uri = ++num; + break; + case OPT_SERIAL: + serial = ++num; + break; + case OPT_NEXT_SERIAL: + next_serial = ++num; + break; + case OPT_MODULUS: + modulus = ++num; + break; + case OPT_PUBKEY: + pubkey = ++num; + break; + case OPT_X509TOREQ: + x509req = ++num; + break; + case OPT_TEXT: + text = ++num; + break; + case OPT_SUBJECT: + subject = ++num; + break; + case OPT_ISSUER: + issuer = ++num; + break; + case OPT_FINGERPRINT: + fingerprint = ++num; + break; + case OPT_HASH: + subject_hash = ++num; + break; + case OPT_ISSUER_HASH: + issuer_hash = ++num; + break; + case OPT_PURPOSE: + pprint = ++num; + break; + case OPT_STARTDATE: + startdate = ++num; + break; + case OPT_ENDDATE: + enddate = ++num; + break; + case OPT_NOOUT: + noout = ++num; + break; + case OPT_EXT: + ext = ++num; + exts = opt_arg(); + break; + case OPT_NOCERT: + nocert = 1; + break; + case OPT_TRUSTOUT: + trustout = 1; + break; + case OPT_CLRTRUST: + clrtrust = ++num; + break; + case OPT_CLRREJECT: + clrreject = ++num; + break; + case OPT_ALIAS: + aliasout = ++num; + break; + case OPT_CACREATESERIAL: + CA_createserial = ++num; + break; + case OPT_CLREXT: + clrext = 1; + break; + case OPT_OCSPID: + ocspid = ++num; + break; + case OPT_BADSIG: + badsig = 1; + break; +#ifndef OPENSSL_NO_MD5 + case OPT_SUBJECT_HASH_OLD: + subject_hash_old = ++num; + break; + case OPT_ISSUER_HASH_OLD: + issuer_hash_old = ++num; + break; +#else + case OPT_SUBJECT_HASH_OLD: + case OPT_ISSUER_HASH_OLD: + break; +#endif + case OPT_DATES: + startdate = ++num; + enddate = ++num; + break; + case OPT_CHECKEND: + checkend = 1; + { + intmax_t temp = 0; + if (!opt_imax(opt_arg(), &temp)) + goto opthelp; + checkoffset = (time_t)temp; + if ((intmax_t)checkoffset != temp) { + BIO_printf(bio_err, "%s: checkend time out of range %s\n", + prog, opt_arg()); + goto opthelp; + } + } + break; + case OPT_CHECKHOST: + checkhost = opt_arg(); + break; + case OPT_CHECKEMAIL: + checkemail = opt_arg(); + break; + case OPT_CHECKIP: + checkip = opt_arg(); + break; + case OPT_PRESERVE_DATES: + if (days != DEF_DAYS) + goto opthelp; + preserve_dates = 1; + break; + case OPT_MD: + if (!opt_md(opt_unknown(), &digest)) + goto opthelp; + } + } + argc = opt_num_rest(); + argv = opt_rest(); + if (argc != 0) { + BIO_printf(bio_err, "%s: Unknown parameter %s\n", prog, argv[0]); + goto opthelp; + } + + if (!app_passwd(passinarg, NULL, &passin, NULL)) { + BIO_printf(bio_err, "Error getting password\n"); + goto end; + } + + if (!X509_STORE_set_default_paths(ctx)) { + ERR_print_errors(bio_err); + goto end; + } + + if (fkeyfile != NULL) { + fkey = load_pubkey(fkeyfile, keyformat, 0, NULL, e, "Forced key"); + if (fkey == NULL) + goto end; + } + + if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM)) { + CAkeyfile = CAfile; + } else if ((CA_flag) && (CAkeyfile == NULL)) { + BIO_printf(bio_err, + "need to specify a CAkey if using the CA command\n"); + goto end; + } + + if (extfile != NULL) { + X509V3_CTX ctx2; + if ((extconf = app_load_config(extfile)) == NULL) + goto end; + if (extsect == NULL) { + extsect = NCONF_get_string(extconf, "default", "extensions"); + if (extsect == NULL) { + ERR_clear_error(); + extsect = "default"; + } + } + X509V3_set_ctx_test(&ctx2); + X509V3_set_nconf(&ctx2, extconf); + if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL)) { + BIO_printf(bio_err, + "Error Loading extension section %s\n", extsect); + ERR_print_errors(bio_err); + goto end; + } + } + + if (reqfile) { + EVP_PKEY *pkey; + BIO *in; + + if (!sign_flag && !CA_flag) { + BIO_printf(bio_err, "We need a private key to sign with\n"); + goto end; + } + in = bio_open_default(infile, 'r', informat); + if (in == NULL) + goto end; + req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL); + BIO_free(in); + + if (req == NULL) { + ERR_print_errors(bio_err); + goto end; + } + + if ((pkey = X509_REQ_get0_pubkey(req)) == NULL) { + BIO_printf(bio_err, "error unpacking public key\n"); + goto end; + } + i = X509_REQ_verify(req, pkey); + if (i < 0) { + BIO_printf(bio_err, "Signature verification error\n"); + ERR_print_errors(bio_err); + goto end; + } + if (i == 0) { + BIO_printf(bio_err, + "Signature did not match the certificate request\n"); + goto end; + } else { + BIO_printf(bio_err, "Signature ok\n"); + } + + print_name(bio_err, "subject=", X509_REQ_get_subject_name(req), + get_nameopt()); + + if ((x = X509_new()) == NULL) + goto end; + + if (sno == NULL) { + sno = ASN1_INTEGER_new(); + if (sno == NULL || !rand_serial(NULL, sno)) + goto end; + if (!X509_set_serialNumber(x, sno)) + goto end; + ASN1_INTEGER_free(sno); + sno = NULL; + } else if (!X509_set_serialNumber(x, sno)) { + goto end; + } + + if (!X509_set_issuer_name(x, X509_REQ_get_subject_name(req))) + goto end; + if (!X509_set_subject_name(x, X509_REQ_get_subject_name(req))) + goto end; + if (!set_cert_times(x, NULL, NULL, days)) + goto end; + + if (fkey != NULL) { + X509_set_pubkey(x, fkey); + } else { + pkey = X509_REQ_get0_pubkey(req); + X509_set_pubkey(x, pkey); + } + } else { + x = load_cert(infile, informat, "Certificate"); + } + + if (x == NULL) + goto end; + if (CA_flag) { + xca = load_cert(CAfile, CAformat, "CA Certificate"); + if (xca == NULL) + goto end; + } + + out = bio_open_default(outfile, 'w', outformat); + if (out == NULL) + goto end; + + if (!noout || text || next_serial) + OBJ_create("2.99999.3", "SET.ex3", "SET x509v3 extension 3"); + + if (alias) + X509_alias_set1(x, (unsigned char *)alias, -1); + + if (clrtrust) + X509_trust_clear(x); + if (clrreject) + X509_reject_clear(x); + + if (trust != NULL) { + for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) { + objtmp = sk_ASN1_OBJECT_value(trust, i); + X509_add1_trust_object(x, objtmp); + } + objtmp = NULL; + } + + if (reject != NULL) { + for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) { + objtmp = sk_ASN1_OBJECT_value(reject, i); + X509_add1_reject_object(x, objtmp); + } + objtmp = NULL; + } + + if (badsig) { + const ASN1_BIT_STRING *signature; + + X509_get0_signature(&signature, NULL, x); + corrupt_signature(signature); + } + + if (num) { + for (i = 1; i <= num; i++) { + if (issuer == i) { + print_name(out, "issuer=", X509_get_issuer_name(x), get_nameopt()); + } else if (subject == i) { + print_name(out, "subject=", + X509_get_subject_name(x), get_nameopt()); + } else if (serial == i) { + BIO_printf(out, "serial="); + i2a_ASN1_INTEGER(out, X509_get_serialNumber(x)); + BIO_printf(out, "\n"); + } else if (next_serial == i) { + ASN1_INTEGER *ser = X509_get_serialNumber(x); + BIGNUM *bnser = ASN1_INTEGER_to_BN(ser, NULL); + + if (!bnser) + goto end; + if (!BN_add_word(bnser, 1)) + goto end; + ser = BN_to_ASN1_INTEGER(bnser, NULL); + if (!ser) + goto end; + BN_free(bnser); + i2a_ASN1_INTEGER(out, ser); + ASN1_INTEGER_free(ser); + BIO_puts(out, "\n"); + } else if ((email == i) || (ocsp_uri == i)) { + int j; + STACK_OF(OPENSSL_STRING) *emlst; + if (email == i) + emlst = X509_get1_email(x); + else + emlst = X509_get1_ocsp(x); + for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++) + BIO_printf(out, "%s\n", + sk_OPENSSL_STRING_value(emlst, j)); + X509_email_free(emlst); + } else if (aliasout == i) { + unsigned char *alstr; + alstr = X509_alias_get0(x, NULL); + if (alstr) + BIO_printf(out, "%s\n", alstr); + else + BIO_puts(out, "\n"); + } else if (subject_hash == i) { + BIO_printf(out, "%08lx\n", X509_subject_name_hash(x)); + } +#ifndef OPENSSL_NO_MD5 + else if (subject_hash_old == i) { + BIO_printf(out, "%08lx\n", X509_subject_name_hash_old(x)); + } +#endif + else if (issuer_hash == i) { + BIO_printf(out, "%08lx\n", X509_issuer_name_hash(x)); + } +#ifndef OPENSSL_NO_MD5 + else if (issuer_hash_old == i) { + BIO_printf(out, "%08lx\n", X509_issuer_name_hash_old(x)); + } +#endif + else if (pprint == i) { + X509_PURPOSE *ptmp; + int j; + BIO_printf(out, "Certificate purposes:\n"); + for (j = 0; j < X509_PURPOSE_get_count(); j++) { + ptmp = X509_PURPOSE_get0(j); + purpose_print(out, x, ptmp); + } + } else if (modulus == i) { + EVP_PKEY *pkey; + + pkey = X509_get0_pubkey(x); + if (pkey == NULL) { + BIO_printf(bio_err, "Modulus=unavailable\n"); + ERR_print_errors(bio_err); + goto end; + } + BIO_printf(out, "Modulus="); +#ifndef OPENSSL_NO_RSA + if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) { + const BIGNUM *n; + RSA_get0_key(EVP_PKEY_get0_RSA(pkey), &n, NULL, NULL); + BN_print(out, n); + } else +#endif +#ifndef OPENSSL_NO_DSA + if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA) { + const BIGNUM *dsapub = NULL; + DSA_get0_key(EVP_PKEY_get0_DSA(pkey), &dsapub, NULL); + BN_print(out, dsapub); + } else +#endif + { + BIO_printf(out, "Wrong Algorithm type"); + } + BIO_printf(out, "\n"); + } else if (pubkey == i) { + EVP_PKEY *pkey; + + pkey = X509_get0_pubkey(x); + if (pkey == NULL) { + BIO_printf(bio_err, "Error getting public key\n"); + ERR_print_errors(bio_err); + goto end; + } + PEM_write_bio_PUBKEY(out, pkey); + } else if (C == i) { + unsigned char *d; + char *m; + int len; + + print_name(out, "/*\n" + " * Subject: ", X509_get_subject_name(x), get_nameopt()); + print_name(out, " * Issuer: ", X509_get_issuer_name(x), get_nameopt()); + BIO_puts(out, " */\n"); + + len = i2d_X509(x, NULL); + m = app_malloc(len, "x509 name buffer"); + d = (unsigned char *)m; + len = i2d_X509_NAME(X509_get_subject_name(x), &d); + print_array(out, "the_subject_name", len, (unsigned char *)m); + d = (unsigned char *)m; + len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d); + print_array(out, "the_public_key", len, (unsigned char *)m); + d = (unsigned char *)m; + len = i2d_X509(x, &d); + print_array(out, "the_certificate", len, (unsigned char *)m); + OPENSSL_free(m); + } else if (text == i) { + X509_print_ex(out, x, get_nameopt(), certflag); + } else if (startdate == i) { + BIO_puts(out, "notBefore="); + ASN1_TIME_print(out, X509_get0_notBefore(x)); + BIO_puts(out, "\n"); + } else if (enddate == i) { + BIO_puts(out, "notAfter="); + ASN1_TIME_print(out, X509_get0_notAfter(x)); + BIO_puts(out, "\n"); + } else if (fingerprint == i) { + int j; + unsigned int n; + unsigned char md[EVP_MAX_MD_SIZE]; + const EVP_MD *fdig = digest; + + if (fdig == NULL) + fdig = EVP_sha1(); + + if (!X509_digest(x, fdig, md, &n)) { + BIO_printf(bio_err, "out of memory\n"); + goto end; + } + BIO_printf(out, "%s Fingerprint=", + OBJ_nid2sn(EVP_MD_type(fdig))); + for (j = 0; j < (int)n; j++) { + BIO_printf(out, "%02X%c", md[j], (j + 1 == (int)n) + ? '\n' : ':'); + } + } + + /* should be in the library */ + else if ((sign_flag == i) && (x509req == 0)) { + BIO_printf(bio_err, "Getting Private key\n"); + if (Upkey == NULL) { + Upkey = load_key(keyfile, keyformat, 0, + passin, e, "Private key"); + if (Upkey == NULL) + goto end; + } + + if (!sign(x, Upkey, days, clrext, digest, extconf, extsect, preserve_dates)) + goto end; + } else if (CA_flag == i) { + BIO_printf(bio_err, "Getting CA Private Key\n"); + if (CAkeyfile != NULL) { + CApkey = load_key(CAkeyfile, CAkeyformat, + 0, passin, e, "CA Private Key"); + if (CApkey == NULL) + goto end; + } + + if (!x509_certify(ctx, CAfile, digest, x, xca, + CApkey, sigopts, + CAserial, CA_createserial, days, clrext, + extconf, extsect, sno, reqfile, preserve_dates)) + goto end; + } else if (x509req == i) { + EVP_PKEY *pk; + + BIO_printf(bio_err, "Getting request Private Key\n"); + if (keyfile == NULL) { + BIO_printf(bio_err, "no request key file specified\n"); + goto end; + } else { + pk = load_key(keyfile, keyformat, 0, + passin, e, "request key"); + if (pk == NULL) + goto end; + } + + BIO_printf(bio_err, "Generating certificate request\n"); + + rq = X509_to_X509_REQ(x, pk, digest); + EVP_PKEY_free(pk); + if (rq == NULL) { + ERR_print_errors(bio_err); + goto end; + } + if (!noout) { + X509_REQ_print_ex(out, rq, get_nameopt(), X509_FLAG_COMPAT); + PEM_write_bio_X509_REQ(out, rq); + } + noout = 1; + } else if (ocspid == i) { + X509_ocspid_print(out, x); + } else if (ext == i) { + print_x509v3_exts(out, x, exts); + } + } + } + + if (checkend) { + time_t tcheck = time(NULL) + checkoffset; + + if (X509_cmp_time(X509_get0_notAfter(x), &tcheck) < 0) { + BIO_printf(out, "Certificate will expire\n"); + ret = 1; + } else { + BIO_printf(out, "Certificate will not expire\n"); + ret = 0; + } + goto end; + } + + print_cert_checks(out, x, checkhost, checkemail, checkip); + + if (noout || nocert) { + ret = 0; + goto end; + } + + if (outformat == FORMAT_ASN1) { + i = i2d_X509_bio(out, x); + } else if (outformat == FORMAT_PEM) { + if (trustout) + i = PEM_write_bio_X509_AUX(out, x); + else + i = PEM_write_bio_X509(out, x); + } else { + BIO_printf(bio_err, "bad output format specified for outfile\n"); + goto end; + } + if (!i) { + BIO_printf(bio_err, "unable to write certificate\n"); + ERR_print_errors(bio_err); + goto end; + } + ret = 0; + end: + NCONF_free(extconf); + BIO_free_all(out); + X509_STORE_free(ctx); + X509_REQ_free(req); + X509_free(x); + X509_free(xca); + EVP_PKEY_free(Upkey); + EVP_PKEY_free(CApkey); + EVP_PKEY_free(fkey); + sk_OPENSSL_STRING_free(sigopts); + X509_REQ_free(rq); + ASN1_INTEGER_free(sno); + sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free); + sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free); + ASN1_OBJECT_free(objtmp); + release_engine(e); + OPENSSL_free(passin); + return ret; +} + +static ASN1_INTEGER *x509_load_serial(const char *CAfile, + const char *serialfile, int create) +{ + char *buf = NULL; + ASN1_INTEGER *bs = NULL; + BIGNUM *serial = NULL; + + if (serialfile == NULL) { + const char *p = strrchr(CAfile, '.'); + size_t len = p != NULL ? (size_t)(p - CAfile) : strlen(CAfile); + + buf = app_malloc(len + sizeof(POSTFIX), "serial# buffer"); + memcpy(buf, CAfile, len); + memcpy(buf + len, POSTFIX, sizeof(POSTFIX)); + serialfile = buf; + } + + serial = load_serial(serialfile, create, NULL); + if (serial == NULL) + goto end; + + if (!BN_add_word(serial, 1)) { + BIO_printf(bio_err, "add_word failure\n"); + goto end; + } + + if (!save_serial(serialfile, NULL, serial, &bs)) + goto end; + + end: + OPENSSL_free(buf); + BN_free(serial); + return bs; +} + +static int x509_certify(X509_STORE *ctx, const char *CAfile, const EVP_MD *digest, + X509 *x, X509 *xca, EVP_PKEY *pkey, + STACK_OF(OPENSSL_STRING) *sigopts, + const char *serialfile, int create, + int days, int clrext, CONF *conf, const char *section, + ASN1_INTEGER *sno, int reqfile, int preserve_dates) +{ + int ret = 0; + ASN1_INTEGER *bs = NULL; + X509_STORE_CTX *xsc = NULL; + EVP_PKEY *upkey; + + upkey = X509_get0_pubkey(xca); + if (upkey == NULL) { + BIO_printf(bio_err, "Error obtaining CA X509 public key\n"); + goto end; + } + EVP_PKEY_copy_parameters(upkey, pkey); + + xsc = X509_STORE_CTX_new(); + if (xsc == NULL || !X509_STORE_CTX_init(xsc, ctx, x, NULL)) { + BIO_printf(bio_err, "Error initialising X509 store\n"); + goto end; + } + if (sno) + bs = sno; + else if ((bs = x509_load_serial(CAfile, serialfile, create)) == NULL) + goto end; + + /* + * NOTE: this certificate can/should be self signed, unless it was a + * certificate request in which case it is not. + */ + X509_STORE_CTX_set_cert(xsc, x); + X509_STORE_CTX_set_flags(xsc, X509_V_FLAG_CHECK_SS_SIGNATURE); + if (!reqfile && X509_verify_cert(xsc) <= 0) + goto end; + + if (!X509_check_private_key(xca, pkey)) { + BIO_printf(bio_err, + "CA certificate and CA private key do not match\n"); + goto end; + } + + if (!X509_set_issuer_name(x, X509_get_subject_name(xca))) + goto end; + if (!X509_set_serialNumber(x, bs)) + goto end; + + if (!preserve_dates && !set_cert_times(x, NULL, NULL, days)) + goto end; + + if (clrext) { + while (X509_get_ext_count(x) > 0) + X509_delete_ext(x, 0); + } + + if (conf != NULL) { + X509V3_CTX ctx2; + X509_set_version(x, 2); /* version 3 certificate */ + X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0); + X509V3_set_nconf(&ctx2, conf); + if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x)) + goto end; + } + + if (!do_X509_sign(x, pkey, digest, sigopts)) + goto end; + ret = 1; + end: + X509_STORE_CTX_free(xsc); + if (!ret) + ERR_print_errors(bio_err); + if (!sno) + ASN1_INTEGER_free(bs); + return ret; +} + +static int callb(int ok, X509_STORE_CTX *ctx) +{ + int err; + X509 *err_cert; + + /* + * it is ok to use a self signed certificate This case will catch both + * the initial ok == 0 and the final ok == 1 calls to this function + */ + err = X509_STORE_CTX_get_error(ctx); + if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) + return 1; + + /* + * BAD we should have gotten an error. Normally if everything worked + * X509_STORE_CTX_get_error(ctx) will still be set to + * DEPTH_ZERO_SELF_.... + */ + if (ok) { + BIO_printf(bio_err, + "error with certificate to be certified - should be self signed\n"); + return 0; + } else { + err_cert = X509_STORE_CTX_get_current_cert(ctx); + print_name(bio_err, NULL, X509_get_subject_name(err_cert), 0); + BIO_printf(bio_err, + "error with certificate - error %d at depth %d\n%s\n", err, + X509_STORE_CTX_get_error_depth(ctx), + X509_verify_cert_error_string(err)); + return 1; + } +} + +/* self sign */ +static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, + const EVP_MD *digest, CONF *conf, const char *section, + int preserve_dates) +{ + + if (!X509_set_issuer_name(x, X509_get_subject_name(x))) + goto err; + if (!preserve_dates && !set_cert_times(x, NULL, NULL, days)) + goto err; + if (!X509_set_pubkey(x, pkey)) + goto err; + if (clrext) { + while (X509_get_ext_count(x) > 0) + X509_delete_ext(x, 0); + } + if (conf != NULL) { + X509V3_CTX ctx; + X509_set_version(x, 2); /* version 3 certificate */ + X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0); + X509V3_set_nconf(&ctx, conf); + if (!X509V3_EXT_add_nconf(conf, &ctx, section, x)) + goto err; + } + if (!X509_sign(x, pkey, digest)) + goto err; + return 1; + err: + ERR_print_errors(bio_err); + return 0; +} + +static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt) +{ + int id, i, idret; + const char *pname; + id = X509_PURPOSE_get_id(pt); + pname = X509_PURPOSE_get0_name(pt); + for (i = 0; i < 2; i++) { + idret = X509_check_purpose(cert, id, i); + BIO_printf(bio, "%s%s : ", pname, i ? " CA" : ""); + if (idret == 1) + BIO_printf(bio, "Yes\n"); + else if (idret == 0) + BIO_printf(bio, "No\n"); + else + BIO_printf(bio, "Yes (WARNING code=%d)\n", idret); + } + return 1; +} + +static int parse_ext_names(char *names, const char **result) +{ + char *p, *q; + int cnt = 0, len = 0; + + p = q = names; + len = strlen(names); + + while (q - names <= len) { + if (*q != ',' && *q != '\0') { + q++; + continue; + } + if (p != q) { + /* found */ + if (result != NULL) { + result[cnt] = p; + *q = '\0'; + } + cnt++; + } + p = ++q; + } + + return cnt; +} + +static int print_x509v3_exts(BIO *bio, X509 *x, const char *ext_names) +{ + const STACK_OF(X509_EXTENSION) *exts = NULL; + STACK_OF(X509_EXTENSION) *exts2 = NULL; + X509_EXTENSION *ext = NULL; + ASN1_OBJECT *obj; + int i, j, ret = 0, num, nn = 0; + const char *sn, **names = NULL; + char *tmp_ext_names = NULL; + + exts = X509_get0_extensions(x); + if ((num = sk_X509_EXTENSION_num(exts)) <= 0) { + BIO_printf(bio, "No extensions in certificate\n"); + ret = 1; + goto end; + } + + /* parse comma separated ext name string */ + if ((tmp_ext_names = OPENSSL_strdup(ext_names)) == NULL) + goto end; + if ((nn = parse_ext_names(tmp_ext_names, NULL)) == 0) { + BIO_printf(bio, "Invalid extension names: %s\n", ext_names); + goto end; + } + if ((names = OPENSSL_malloc(sizeof(char *) * nn)) == NULL) + goto end; + parse_ext_names(tmp_ext_names, names); + + for (i = 0; i < num; i++) { + ext = sk_X509_EXTENSION_value(exts, i); + + /* check if this ext is what we want */ + obj = X509_EXTENSION_get_object(ext); + sn = OBJ_nid2sn(OBJ_obj2nid(obj)); + if (sn == NULL || strcmp(sn, "UNDEF") == 0) + continue; + + for (j = 0; j < nn; j++) { + if (strcmp(sn, names[j]) == 0) { + /* push the extension into a new stack */ + if (exts2 == NULL + && (exts2 = sk_X509_EXTENSION_new_null()) == NULL) + goto end; + if (!sk_X509_EXTENSION_push(exts2, ext)) + goto end; + } + } + } + + if (!sk_X509_EXTENSION_num(exts2)) { + BIO_printf(bio, "No extensions matched with %s\n", ext_names); + ret = 1; + goto end; + } + + ret = X509V3_extensions_print(bio, NULL, exts2, 0, 0); + end: + sk_X509_EXTENSION_free(exts2); + OPENSSL_free(names); + OPENSSL_free(tmp_ext_names); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/appveyor.yml b/trunk/3rdparty/openssl-1.1-fit/appveyor.yml new file mode 100644 index 000000000..24966c0fa --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/appveyor.yml @@ -0,0 +1,66 @@ +platform: + - x64 + - x86 + +environment: + fast_finish: true + matrix: + - VSVER: 14 + +configuration: + - shared + - plain + +before_build: + - ps: >- + If ($env:Platform -Match "x86") { + $env:VCVARS_PLATFORM="x86" + $env:TARGET="VC-WIN32 no-asm" + } Else { + $env:VCVARS_PLATFORM="amd64" + $env:TARGET="VC-WIN64A-masm" + } + - ps: >- + If ($env:Configuration -Match "shared") { + $env:SHARED="no-makedepend" + } Else { + $env:SHARED="no-shared no-makedepend" + } + - ps: $env:VSCOMNTOOLS=(Get-Content ("env:VS" + "$env:VSVER" + "0COMNTOOLS")) + - call "%VSCOMNTOOLS%\..\..\VC\vcvarsall.bat" %VCVARS_PLATFORM% + - mkdir _build + - cd _build + - perl ..\Configure %TARGET% %SHARED% + - perl configdata.pm --dump + - cd .. + - ps: >- + if (-not $env:APPVEYOR_PULL_REQUEST_NUMBER` + -or (&git log -2 | Select-String "\[extended tests\]") ) { + $env:EXTENDED_TESTS="yes" + } + +build_script: + - cd _build + - ps: >- + If ($env:Configuration -Match "shared" -or $env:EXTENDED_TESTS) { + cmd /c "nmake build_all_generated 2>&1" + cmd /c "nmake PERL=no-perl 2>&1" + } + - cd .. + +test_script: + - cd _build + - ps: >- + If ($env:Configuration -Match "shared" -or $env:EXTENDED_TESTS) { + if ($env:EXTENDED_TESTS) { + cmd /c "nmake test V=1 2>&1" + } Else { + cmd /c "nmake test V=1 TESTS=-test_fuzz 2>&1" + } + } + - ps: >- + if ($env:EXTENDED_TESTS) { + mkdir ..\_install + cmd /c "nmake install DESTDIR=..\_install 2>&1" + } + - cd .. diff --git a/trunk/3rdparty/openssl-1.1-fit/build.info b/trunk/3rdparty/openssl-1.1-fit/build.info new file mode 100644 index 000000000..3dda4e89b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/build.info @@ -0,0 +1,103 @@ +{- + our $sover = $config{shlib_version_number}; + our $sover_filename = $sover; + $sover_filename =~ s|\.|_|g + if $config{target} =~ /^mingw/ || $config{target} =~ /^VC-/; + $sover_filename = + sprintf "%02d%02d", split m|\.|, $config{shlib_version_number} + if $config{target} =~ /^vms/; + ""; +-} +LIBS=libcrypto libssl +INCLUDE[libcrypto]=. crypto/include include +INCLUDE[libssl]=. include +DEPEND[libssl]=libcrypto + +# Empty DEPEND "indices" means the dependencies are expected to be built +# unconditionally before anything else. +DEPEND[]=include/openssl/opensslconf.h crypto/include/internal/bn_conf.h \ + crypto/include/internal/dso_conf.h +DEPEND[include/openssl/opensslconf.h]=configdata.pm +GENERATE[include/openssl/opensslconf.h]=include/openssl/opensslconf.h.in +DEPEND[crypto/include/internal/bn_conf.h]=configdata.pm +GENERATE[crypto/include/internal/bn_conf.h]=crypto/include/internal/bn_conf.h.in +DEPEND[crypto/include/internal/dso_conf.h]=configdata.pm +GENERATE[crypto/include/internal/dso_conf.h]=crypto/include/internal/dso_conf.h.in + +IF[{- defined $target{shared_defflag} -}] + IF[{- $config{target} =~ /^mingw/ -}] + GENERATE[libcrypto.def]=util/mkdef.pl crypto 32 + DEPEND[libcrypto.def]=util/libcrypto.num + GENERATE[libssl.def]=util/mkdef.pl ssl 32 + DEPEND[libssl.def]=util/libssl.num + + SHARED_SOURCE[libcrypto]=libcrypto.def + SHARED_SOURCE[libssl]=libssl.def + ELSIF[{- $config{target} =~ /^aix/ -}] + GENERATE[libcrypto.map]=util/mkdef.pl crypto aix + DEPEND[libcrypto.map]=util/libcrypto.num + GENERATE[libssl.map]=util/mkdef.pl ssl aix + DEPEND[libssl.map]=util/libssl.num + + SHARED_SOURCE[libcrypto]=libcrypto.map + SHARED_SOURCE[libssl]=libssl.map + ELSE + GENERATE[libcrypto.map]=util/mkdef.pl crypto linux + DEPEND[libcrypto.map]=util/libcrypto.num + GENERATE[libssl.map]=util/mkdef.pl ssl linux + DEPEND[libssl.map]=util/libssl.num + + SHARED_SOURCE[libcrypto]=libcrypto.map + SHARED_SOURCE[libssl]=libssl.map + ENDIF +ENDIF +# VMS and VC don't have parametrised .def / .symvec generation, so they get +# special treatment, since we know they do use these files +IF[{- $config{target} =~ /^VC-/ -}] + GENERATE[libcrypto.def]=util/mkdef.pl crypto 32 + DEPEND[libcrypto.def]=util/libcrypto.num + GENERATE[libssl.def]=util/mkdef.pl ssl 32 + DEPEND[libssl.def]=util/libssl.num + + SHARED_SOURCE[libcrypto]=libcrypto.def + SHARED_SOURCE[libssl]=libssl.def +ELSIF[{- $config{target} =~ /^vms/ -}] + GENERATE[libcrypto.opt]=util/mkdef.pl crypto "VMS" + DEPEND[libcrypto.opt]=util/libcrypto.num + GENERATE[libssl.opt]=util/mkdef.pl ssl "VMS" + DEPEND[libssl.opt]=util/libssl.num + + SHARED_SOURCE[libcrypto]=libcrypto.opt + SHARED_SOURCE[libssl]=libssl.opt +ENDIF + +IF[{- $config{target} =~ /^(?:Cygwin|mingw|VC-)/ -}] + GENERATE[libcrypto.rc]=util/mkrc.pl libcrypto + GENERATE[libssl.rc]=util/mkrc.pl libssl + + SHARED_SOURCE[libcrypto]=libcrypto.rc + SHARED_SOURCE[libssl]=libssl.rc +ENDIF + +IF[{- $config{target} =~ /^Cygwin/ -}] + SHARED_NAME[libcrypto]=cygcrypto-{- $sover_filename -} + SHARED_NAME[libssl]=cygssl-{- $sover_filename -} +ELSIF[{- $config{target} =~ /^mingw/ -}] + SHARED_NAME[libcrypto]=libcrypto-{- $sover_filename -}{- $config{target} eq "mingw64" ? "-x64" : "" -} + SHARED_NAME[libssl]=libssl-{- $sover_filename -}{- $config{target} eq "mingw64" ? "-x64" : "" -} +ELSIF[{- $config{target} =~ /^VC-/ -}] + SHARED_NAME[libcrypto]=libcrypto-{- $sover_filename -}{- $target{multilib} -} + SHARED_NAME[libssl]=libssl-{- $sover_filename -}{- $target{multilib} -} +ENDIF + +# VMS has a cultural standard where all libraries are prefixed. +# For OpenSSL, the choice is 'ossl$' (this prefix was claimed in a +# conversation with VSI, Tuesday January 26 2016) +# Also, it seems it's usual to have the pointer size the libraries +# were built for as part of the name. +IF[{- $config{target} =~ /^vms/ -}] + RENAME[libcrypto]=ossl$libcrypto{- $target{pointer_size} -} + RENAME[libssl]=ossl$libssl{- $target{pointer_size} -} + SHARED_NAME[libcrypto]=ossl$libcrypto{- $sover_filename -}_shr{- $target{pointer_size} -} + SHARED_NAME[libssl]=ossl$libssl{- $sover_filename -}_shr{- $target{pointer_size} -} +ENDIF diff --git a/trunk/3rdparty/openssl-1.1-fit/config b/trunk/3rdparty/openssl-1.1-fit/config new file mode 100755 index 000000000..d0e31b651 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/config @@ -0,0 +1,946 @@ +#!/bin/sh +# Copyright 1998-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# OpenSSL config: determine the operating system and run ./Configure +# Derived from minarch and GuessOS from Apache. +# +# Do "config -h" for usage information. +SUFFIX="" +DRYRUN="false" +VERBOSE="false" +EXE="" +THERE=`dirname $0` + +# pick up any command line args to config +for i +do +case "$i" in +-d*) options=$options" --debug";; +-t*) DRYRUN="true" VERBOSE="true";; +-v*) VERBOSE="true";; +-h*) DRYRUN="true"; cat </dev/null` || MACHINE="unknown" +[ "$RELEASE" ] || RELEASE=`(uname -r) 2>/dev/null` || RELEASE="unknown" +[ "$SYSTEM" ] || SYSTEM=`(uname -s) 2>/dev/null` || SYSTEM="unknown" +[ "$BUILD" ] || VERSION=`(uname -v) 2>/dev/null` || VERSION="unknown" + + +# Now test for ISC and SCO, since it is has a braindamaged uname. +# +# We need to work around FreeBSD 1.1.5.1 +( +XREL=`uname -X 2>/dev/null | grep "^Release" | awk '{print $3}'` +if [ "x$XREL" != "x" ]; then + if [ -f /etc/kconfig ]; then + case "$XREL" in + 4.0|4.1) + echo "${MACHINE}-whatever-isc4"; exit 0 + ;; + esac + else + case "$XREL" in + 3.2v4.2) + echo "whatever-whatever-sco3"; exit 0 + ;; + 3.2v5.0*) + echo "whatever-whatever-sco5"; exit 0 + ;; + 4.2MP) + case "x${VERSION}" in + x2.0*) echo "whatever-whatever-unixware20"; exit 0 ;; + x2.1*) echo "whatever-whatever-unixware21"; exit 0 ;; + x2*) echo "whatever-whatever-unixware2"; exit 0 ;; + esac + ;; + 4.2) + echo "whatever-whatever-unixware1"; exit 0 + ;; + 5*) + case "x${VERSION}" in + # We hardcode i586 in place of ${MACHINE} for the + # following reason. The catch is that even though Pentium + # is minimum requirement for platforms in question, + # ${MACHINE} gets always assigned to i386. Now, problem + # with i386 is that it makes ./config pass 386 to + # ./Configure, which in turn makes make generate + # inefficient SHA-1 (for this moment) code. + x[678]*) echo "i586-sco-unixware7"; exit 0 ;; + esac + ;; + esac + fi +fi +# Now we simply scan though... In most cases, the SYSTEM info is enough +# +case "${SYSTEM}:${RELEASE}:${VERSION}:${MACHINE}" in + A/UX:*) + echo "m68k-apple-aux3"; exit 0 + ;; + + AIX:[3-9]:4:*) + echo "${MACHINE}-ibm-aix"; exit 0 + ;; + + AIX:*:[5-9]:*) + echo "${MACHINE}-ibm-aix"; exit 0 + ;; + + AIX:*) + echo "${MACHINE}-ibm-aix3"; exit 0 + ;; + + HI-UX:*) + echo "${MACHINE}-hi-hiux"; exit 0 + ;; + + HP-UX:*) + HPUXVER=`echo ${RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "$HPUXVER" in + 1[0-9].*) # HPUX 10 and 11 targets are unified + echo "${MACHINE}-hp-hpux1x"; exit 0 + ;; + *) + echo "${MACHINE}-hp-hpux"; exit 0 + ;; + esac + ;; + + IRIX:6.*) + echo "mips3-sgi-irix"; exit 0 + ;; + + IRIX64:*) + echo "mips4-sgi-irix64"; exit 0 + ;; + + Linux:[2-9].*) + echo "${MACHINE}-whatever-linux2"; exit 0 + ;; + + Linux:1.*) + echo "${MACHINE}-whatever-linux1"; exit 0 + ;; + + GNU*) + echo "hurd-x86"; exit 0; + ;; + + LynxOS:*) + echo "${MACHINE}-lynx-lynxos"; exit 0 + ;; + + BSD/OS:4.*) # BSD/OS always says 386 + echo "i486-whatever-bsdi4"; exit 0 + ;; + + BSD/386:*:*:*486*|BSD/OS:*:*:*:*486*) + case `/sbin/sysctl -n hw.model` in + Pentium*) + echo "i586-whatever-bsdi"; exit 0 + ;; + *) + echo "i386-whatever-bsdi"; exit 0 + ;; + esac; + ;; + + BSD/386:*|BSD/OS:*) + echo "${MACHINE}-whatever-bsdi"; exit 0 + ;; + + FreeBSD:*:*:*386*) + VERS=`echo ${RELEASE} | sed -e 's/[-(].*//'` + MACH=`sysctl -n hw.model` + ARCH='whatever' + case ${MACH} in + *386* ) MACH="i386" ;; + *486* ) MACH="i486" ;; + Pentium\ II*) MACH="i686" ;; + Pentium* ) MACH="i586" ;; + * ) MACH="$MACHINE" ;; + esac + case ${MACH} in + i[0-9]86 ) ARCH="pc" ;; + esac + echo "${MACH}-${ARCH}-freebsd${VERS}"; exit 0 + ;; + + DragonFly:*) + echo "${MACHINE}-whatever-dragonfly"; exit 0 + ;; + + FreeBSD:*) + echo "${MACHINE}-whatever-freebsd"; exit 0 + ;; + + Haiku:*) + echo "${MACHINE}-whatever-haiku"; exit 0 + ;; + + NetBSD:*:*:*386*) + echo "`(/usr/sbin/sysctl -n hw.model || /sbin/sysctl -n hw.model) | sed 's,.*\(.\)86-class.*,i\186,'`-whatever-netbsd"; exit 0 + ;; + + NetBSD:*) + echo "${MACHINE}-whatever-netbsd"; exit 0 + ;; + + OpenBSD:*) + echo "${MACHINE}-whatever-openbsd"; exit 0 + ;; + + OpenUNIX:*) + echo "${MACHINE}-unknown-OpenUNIX${VERSION}"; exit 0 + ;; + + OSF1:*:*:*alpha*) + OSFMAJOR=`echo ${RELEASE}| sed -e 's/^V\([0-9]*\)\..*$/\1/'` + case "$OSFMAJOR" in + 4|5) + echo "${MACHINE}-dec-tru64"; exit 0 + ;; + 1|2|3) + echo "${MACHINE}-dec-osf"; exit 0 + ;; + *) + echo "${MACHINE}-dec-osf"; exit 0 + ;; + esac + ;; + + Paragon*:*:*:*) + echo "i860-intel-osf1"; exit 0 + ;; + + Rhapsody:*) + echo "ppc-apple-rhapsody"; exit 0 + ;; + + Darwin:*) + case "$MACHINE" in + Power*) + echo "ppc-apple-darwin${VERSION}" + ;; + x86_64) + echo "x86_64-apple-darwin${VERSION}" + ;; + *) + echo "i686-apple-darwin${VERSION}" + ;; + esac + exit 0 + ;; + + SunOS:5.*) + echo "${MACHINE}-whatever-solaris2"; exit 0 + ;; + + SunOS:*) + echo "${MACHINE}-sun-sunos4"; exit 0 + ;; + + UNIX_System_V:4.*:*) + echo "${MACHINE}-whatever-sysv4"; exit 0 + ;; + + VOS:*:*:i786) + echo "i386-stratus-vos"; exit 0 + ;; + + VOS:*:*:*) + echo "hppa1.1-stratus-vos"; exit 0 + ;; + + *:4*:R4*:m88k) + echo "${MACHINE}-whatever-sysv4"; exit 0 + ;; + + DYNIX/ptx:4*:*) + echo "${MACHINE}-whatever-sysv4"; exit 0 + ;; + + *:4.0:3.0:3[34]?? | *:4.0:3.0:3[34]??,*) + echo "i486-ncr-sysv4"; exit 0 + ;; + + ULTRIX:*) + echo "${MACHINE}-unknown-ultrix"; exit 0 + ;; + + POSIX-BC*) + echo "${MACHINE}-siemens-sysv4"; exit 0 # Here, $MACHINE == "BS2000" + ;; + + machten:*) + echo "${MACHINE}-tenon-${SYSTEM}"; exit 0; + ;; + + library:*) + echo "${MACHINE}-ncr-sysv4"; exit 0 + ;; + + ConvexOS:*:11.0:*) + echo "${MACHINE}-v11-${SYSTEM}"; exit 0; + ;; + + # The following combinations are supported + # MINGW64* on x86_64 => mingw64 + # MINGW32* on x86_64 => mingw + # MINGW32* on i?86 => mingw + # + # MINGW64* on i?86 isn't expected to work... + MINGW64*:*:*:x86_64) + echo "${MACHINE}-whatever-mingw64"; exit 0; + ;; + MINGW*) + echo "${MACHINE}-whatever-mingw"; exit 0; + ;; + CYGWIN*) + echo "${MACHINE}-pc-cygwin"; exit 0 + ;; + + vxworks*) + echo "${MACHINE}-whatever-vxworks"; exit 0; + ;; +esac + +# +# Ugg. These are all we can determine by what we know about +# the output of uname. Be more creative: +# + +# Do the Apollo stuff first. Here, we just simply assume +# that the existence of the /usr/apollo directory is proof +# enough +if [ -d /usr/apollo ]; then + echo "whatever-apollo-whatever" + exit 0 +fi + +# Now NeXT +ISNEXT=`hostinfo 2>/dev/null` +case "$ISNEXT" in + *'NeXT Mach 3.3'*) + echo "whatever-next-nextstep3.3"; exit 0 + ;; + *NeXT*) + echo "whatever-next-nextstep"; exit 0 + ;; +esac + +# At this point we gone through all the one's +# we know of: Punt + +echo "${MACHINE}-whatever-${SYSTEM}" +exit 0 +) 2>/dev/null | ( + +# --------------------------------------------------------------------------- +# this is where the translation occurs into SSLeay terms +# --------------------------------------------------------------------------- + +# Only set CC if not supplied already +if [ -z "$CROSS_COMPILE$CC" ]; then + GCCVER=`sh -c "gcc -dumpversion" 2>/dev/null` + if [ "$GCCVER" != "" ]; then + # then strip off whatever prefix egcs prepends the number with... + # Hopefully, this will work for any future prefixes as well. + GCCVER=`echo $GCCVER | LC_ALL=C sed 's/^[a-zA-Z]*\-//'` + # Since gcc 3.1 gcc --version behaviour has changed. gcc -dumpversion + # does give us what we want though, so we use that. We just just the + # major and minor version numbers. + # peak single digit before and after first dot, e.g. 2.95.1 gives 29 + GCCVER=`echo $GCCVER | sed 's/\([0-9]\)\.\([0-9]\).*/\1\2/'` + CC=gcc + else + CC=cc + fi +fi +GCCVER=${GCCVER:-0} +if [ "$SYSTEM" = "HP-UX" ];then + # By default gcc is a ILP32 compiler (with long long == 64). + GCC_BITS="32" + if [ $GCCVER -ge 30 ]; then + # PA64 support only came in with gcc 3.0.x. + # We check if the preprocessor symbol __LP64__ is defined... + if echo "__LP64__" | gcc -v -E -x c - 2>/dev/null | grep "^__LP64__" 2>&1 > /dev/null; then + : # __LP64__ has slipped through, it therefore is not defined + else + GCC_BITS="64" + fi + fi +fi +if [ "$SYSTEM" = "SunOS" ]; then + if [ $GCCVER -ge 30 ]; then + # 64-bit ABI isn't officially supported in gcc 3.0, but it appears + # to be working, at the very least 'make test' passes... + if gcc -v -E -x c /dev/null 2>&1 | grep __arch64__ > /dev/null; then + GCC_ARCH="-m64" + else + GCC_ARCH="-m32" + fi + fi + # check for WorkShop C, expected output is "cc: blah-blah C x.x" + CCVER=`(cc -V 2>&1) 2>/dev/null | \ + egrep -e '^cc: .* C [0-9]\.[0-9]' | \ + sed 's/.* C \([0-9]\)\.\([0-9]\).*/\1\2/'` + CCVER=${CCVER:-0} + if [ $MACHINE != i86pc -a $CCVER -gt 40 ]; then + CC=cc # overrides gcc!!! + if [ $CCVER -eq 50 ]; then + echo "WARNING! Detected WorkShop C 5.0. Do make sure you have" + echo " patch #107357-01 or later applied." + sleep 5 + fi + fi +fi + +if [ "${SYSTEM}" = "AIX" ]; then # favor vendor cc over gcc + (cc) 2>&1 | grep -iv "not found" > /dev/null && CC=cc +fi + +CCVER=${CCVER:-0} + +# read the output of the embedded GuessOS +read GUESSOS + +echo Operating system: $GUESSOS + +# now map the output into SSLeay terms ... really should hack into the +# script above so we end up with values in vars but that would take +# more time that I want to waste at the moment +case "$GUESSOS" in + uClinux*64*) + OUT=uClinux-dist64 + ;; + uClinux*) + OUT=uClinux-dist + ;; + mips3-sgi-irix) + OUT="irix-mips3-$CC" + ;; + mips4-sgi-irix64) + echo "WARNING! If you wish to build 64-bit library, then you have to" + echo " invoke '$THERE/Configure irix64-mips4-$CC' *manually*." + if [ "$DRYRUN" = "false" -a -t 1 ]; then + echo " You have about 5 seconds to press Ctrl-C to abort." + (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1 + fi + OUT="irix-mips3-$CC" + ;; + ppc-apple-rhapsody) OUT="rhapsody-ppc-cc" ;; + ppc-apple-darwin*) + ISA64=`(sysctl -n hw.optional.64bitops) 2>/dev/null` + if [ "$ISA64" = "1" -a -z "$KERNEL_BITS" ]; then + echo "WARNING! If you wish to build 64-bit library, then you have to" + echo " invoke '$THERE/Configure darwin64-ppc-cc' *manually*." + if [ "$DRYRUN" = "false" -a -t 1 ]; then + echo " You have about 5 seconds to press Ctrl-C to abort." + (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1 + fi + fi + if [ "$ISA64" = "1" -a "$KERNEL_BITS" = "64" ]; then + OUT="darwin64-ppc-cc" + else + OUT="darwin-ppc-cc" + fi ;; + i?86-apple-darwin*) + ISA64=`(sysctl -n hw.optional.x86_64) 2>/dev/null` + if [ "$ISA64" = "1" -a -z "$KERNEL_BITS" ]; then + echo "WARNING! If you wish to build 64-bit library, then you have to" + echo " invoke 'KERNEL_BITS=64 $THERE/config $options'." + if [ "$DRYRUN" = "false" -a -t 1 ]; then + echo " You have about 5 seconds to press Ctrl-C to abort." + (trap "stty `stty -g`; exit 1" 2; stty -icanon min 0 time 50; read waste; exit 0) <&1 || exit + fi + fi + if [ "$ISA64" = "1" -a "$KERNEL_BITS" = "64" ]; then + OUT="darwin64-x86_64-cc" + else + OUT="darwin-i386-cc" + fi ;; + x86_64-apple-darwin*) + if [ "$KERNEL_BITS" = "32" ]; then + OUT="darwin-i386-cc" + else + OUT="darwin64-x86_64-cc" + fi ;; + armv6+7-*-iphoneos) + __CNF_CFLAGS="$__CNF_CFLAGS -arch%20armv6 -arch%20armv7" + __CNF_CXXFLAGS="$__CNF_CXXFLAGS -arch%20armv6 -arch%20armv7" + OUT="iphoneos-cross" ;; + *-*-iphoneos) + __CNF_CFLAGS="$__CNF_CFLAGS -arch%20${MACHINE}" + __CNF_CXXFLAGS="$__CNF_CXXFLAGS -arch%20${MACHINE}" + OUT="iphoneos-cross" ;; + arm64-*-iphoneos|*-*-ios64) + OUT="ios64-cross" ;; + alpha-*-linux2) + ISA=`awk '/cpu model/{print$4;exit(0);}' /proc/cpuinfo` + case ${ISA:-generic} in + *[678]) OUT="linux-alpha+bwx-$CC" ;; + *) OUT="linux-alpha-$CC" ;; + esac + if [ "$CC" = "gcc" ]; then + case ${ISA:-generic} in + EV5|EV45) __CNF_CFLAGS="$__CNF_CFLAGS -mcpu=ev5" + __CNF_CXXFLAGS="$__CNF_CFLAGS -mcpu=ev5";; + EV56|PCA56) __CNF_CFLAGS="$__CNF_CFLAGS -mcpu=ev56" + __CNF_CXXFLAGS="$__CNF_CXXFLAGS -mcpu=ev56";; + *) __CNF_CFLAGS="$__CNF_CFLAGS -mcpu=ev6" + __CNF_CXXFLAGS="$__CNF_CXXFLAGS -mcpu=ev6";; + esac + fi + ;; + ppc64-*-linux2) + if [ -z "$KERNEL_BITS" ]; then + echo "WARNING! If you wish to build 64-bit library, then you have to" + echo " invoke '$THERE/Configure linux-ppc64' *manually*." + if [ "$DRYRUN" = "false" -a -t 1 ]; then + echo " You have about 5 seconds to press Ctrl-C to abort." + (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1 + fi + fi + if [ "$KERNEL_BITS" = "64" ]; then + OUT="linux-ppc64" + else + OUT="linux-ppc" + if (echo "__LP64__" | gcc -E -x c - 2>/dev/null | grep "^__LP64__" 2>&1 > /dev/null); then + :; + else + __CNF_CFLAGS="$__CNF_CFLAGS -m32" + __CNF_CXXFLAGS="$__CNF_CXXFLAGS -m32" + fi + fi + ;; + ppc64le-*-linux2) OUT="linux-ppc64le" ;; + ppc-*-linux2) OUT="linux-ppc" ;; + mips64*-*-linux2) + echo "WARNING! If you wish to build 64-bit library, then you have to" + echo " invoke '$THERE/Configure linux64-mips64' *manually*." + if [ "$DRYRUN" = "false" -a -t 1 ]; then + echo " You have about 5 seconds to press Ctrl-C to abort." + (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1 + fi + OUT="linux-mips64" + ;; + mips*-*-linux2) OUT="linux-mips32" ;; + ppc60x-*-vxworks*) OUT="vxworks-ppc60x" ;; + ppcgen-*-vxworks*) OUT="vxworks-ppcgen" ;; + pentium-*-vxworks*) OUT="vxworks-pentium" ;; + simlinux-*-vxworks*) OUT="vxworks-simlinux" ;; + mips-*-vxworks*) OUT="vxworks-mips";; + ia64-*-linux?) OUT="linux-ia64" ;; + sparc64-*-linux2) + echo "WARNING! If you *know* that your GNU C supports 64-bit/V9 ABI" + echo " and wish to build 64-bit library, then you have to" + echo " invoke '$THERE/Configure linux64-sparcv9' *manually*." + if [ "$DRYRUN" = "false" -a -t 1 ]; then + echo " You have about 5 seconds to press Ctrl-C to abort." + (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1 + fi + OUT="linux-sparcv9" ;; + sparc-*-linux2) + KARCH=`awk '/^type/{print$3;exit(0);}' /proc/cpuinfo` + case ${KARCH:-sun4} in + sun4u*) OUT="linux-sparcv9" ;; + sun4m) OUT="linux-sparcv8" ;; + sun4d) OUT="linux-sparcv8" ;; + *) OUT="linux-generic32"; + __CNF_CPPFLAGS="$__CNF_CPPFLAGS -DB_ENDIAN" ;; + esac ;; + parisc*-*-linux2) + # 64-bit builds under parisc64 linux are not supported and + # compiler is expected to generate 32-bit objects... + CPUARCH=`awk '/cpu family/{print substr($5,1,3); exit(0);}' /proc/cpuinfo` + CPUSCHEDULE=`awk '/^cpu.[ ]*: PA/{print substr($3,3); exit(0);}' /proc/cpuinfo` + + # ??TODO ?? Model transformations + # 0. CPU Architecture for the 1.1 processor has letter suffixes. We strip that off + # assuming no further arch. identification will ever be used by GCC. + # 1. I'm most concerned about whether is a 7300LC is closer to a 7100 versus a 7100LC. + # 2. The variant 64-bit processors cause concern should GCC support explicit schedulers + # for these chips in the future. + # PA7300LC -> 7100LC (1.1) + # PA8200 -> 8000 (2.0) + # PA8500 -> 8000 (2.0) + # PA8600 -> 8000 (2.0) + + CPUSCHEDULE=`echo $CPUSCHEDULE|sed -e 's/7300LC/7100LC/' -e 's/8.00/8000/'` + # Finish Model transformations + + __CNF_CPPFLAGS="$__CNF_CPPFLAGS -DB_ENDIAN" + __CNF_CFLAGS="$__CNF_CFLAGS -mschedule=$CPUSCHEDULE -march=$CPUARCH" + __CNF_CXXFLAGS="$__CNF_CXXFLAGS -mschedule=$CPUSCHEDULE -march=$CPUARCH" + OUT="linux-generic32" ;; + armv[1-3]*-*-linux2) OUT="linux-generic32" ;; + armv[7-9]*-*-linux2) OUT="linux-armv4" + __CNF_CFLAGS="$__CNF_CFLAGS -march=armv7-a" + __CNF_CXXFLAGS="$__CNF_CXXFLAGS -march=armv7-a" + ;; + arm*-*-linux2) OUT="linux-armv4" ;; + aarch64-*-linux2) OUT="linux-aarch64" ;; + sh*b-*-linux2) OUT="linux-generic32"; + __CNF_CPPFLAGS="$__CNF_CPPFLAGS -DB_ENDIAN" ;; + sh*-*-linux2) OUT="linux-generic32"; + __CNF_CPPFLAGS="$__CNF_CPPFLAGS -DL_ENDIAN" ;; + m68k*-*-linux2) OUT="linux-generic32"; + __CNF_CPPFLAGS="$__CNF_CPPFLAGS -DB_ENDIAN" ;; + s390-*-linux2) OUT="linux-generic32"; + __CNF_CPPFLAGS="$__CNF_CPPFLAGS -DB_ENDIAN" ;; + s390x-*-linux2) + # To be uncommented when glibc bug is fixed, see Configure... + #if egrep -e '^features.* highgprs' /proc/cpuinfo >/dev/null ; then + # echo "WARNING! If you wish to build \"highgprs\" 32-bit library, then you" + # echo " have to invoke './Configure linux32-s390x' *manually*." + # if [ "$DRYRUN" = "false" -a -t -1 ]; then + # echo " You have about 5 seconds to press Ctrl-C to abort." + # (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1 + # fi + #fi + OUT="linux64-s390x" + ;; + x86_64-*-linux?) + if $CC -dM -E -x c /dev/null 2>&1 | grep -q ILP32 > /dev/null; then + OUT="linux-x32" + else + OUT="linux-x86_64" + fi ;; + *86-*-linux2) + # On machines where the compiler understands -m32, prefer a + # config target that uses it + if $CC -m32 -E -x c /dev/null > /dev/null 2>&1; then + OUT="linux-x86" + else + OUT="linux-elf" + fi ;; + *86-*-linux1) OUT="linux-aout" ;; + *-*-linux?) OUT="linux-generic32" ;; + sun4[uv]*-*-solaris2) + OUT="solaris-sparcv9-$CC" + ISA64=`(isainfo) 2>/dev/null | grep sparcv9` + if [ "$ISA64" != "" -a "$KERNEL_BITS" = "" ]; then + if [ "$CC" = "cc" -a $CCVER -ge 50 ]; then + echo "WARNING! If you wish to build 64-bit library, then you have to" + echo " invoke '$THERE/Configure solaris64-sparcv9-cc' *manually*." + if [ "$DRYRUN" = "false" -a -t 1 ]; then + echo " You have about 5 seconds to press Ctrl-C to abort." + (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1 + fi + elif [ "$CC" = "gcc" -a "$GCC_ARCH" = "-m64" ]; then + # $GCC_ARCH denotes default ABI chosen by compiler driver + # (first one found on the $PATH). I assume that user + # expects certain consistency with the rest of his builds + # and therefore switch over to 64-bit. + OUT="solaris64-sparcv9-gcc" + echo "WARNING! If you wish to build 32-bit library, then you have to" + echo " invoke '$THERE/Configure solaris-sparcv9-gcc' *manually*." + if [ "$DRYRUN" = "false" -a -t 1 ]; then + echo " You have about 5 seconds to press Ctrl-C to abort." + (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1 + fi + elif [ "$GCC_ARCH" = "-m32" ]; then + echo "NOTICE! If you *know* that your GNU C supports 64-bit/V9 ABI" + echo " and wish to build 64-bit library, then you have to" + echo " invoke '$THERE/Configure solaris64-sparcv9-gcc' *manually*." + if [ "$DRYRUN" = "false" -a -t 1 ]; then + echo " You have about 5 seconds to press Ctrl-C to abort." + (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1 + fi + fi + fi + if [ "$ISA64" != "" -a "$KERNEL_BITS" = "64" ]; then + OUT="solaris64-sparcv9-$CC" + fi + ;; + sun4m-*-solaris2) OUT="solaris-sparcv8-$CC" ;; + sun4d-*-solaris2) OUT="solaris-sparcv8-$CC" ;; + sun4*-*-solaris2) OUT="solaris-sparcv7-$CC" ;; + *86*-*-solaris2) + ISA64=`(isainfo) 2>/dev/null | grep amd64` + if [ "$ISA64" != "" -a ${KERNEL_BITS:-64} -eq 64 ]; then + OUT="solaris64-x86_64-$CC" + else + OUT="solaris-x86-$CC" + if [ `uname -r | sed -e 's/5\.//'` -lt 10 ]; then + options="$options no-sse2" + fi + fi + ;; + *-*-sunos4) OUT="sunos-$CC" ;; + + *86*-*-bsdi4) OUT="BSD-x86-elf"; options="$options no-sse2"; + __CNF_LDFLAGS="$__CNF_LDFLAGS -ldl" ;; + alpha*-*-*bsd*) OUT="BSD-generic64"; + __CNF_CPPFLAGS="$__CNF_CPPFLAGS -DL_ENDIAN" ;; + powerpc64-*-*bsd*) OUT="BSD-generic64"; + __CNF_CPPFLAGS="$__CNF_CPPFLAGS -DB_ENDIAN" ;; + sparc64-*-*bsd*) OUT="BSD-sparc64" ;; + ia64-*-*bsd*) OUT="BSD-ia64" ;; + x86_64-*-dragonfly*) OUT="BSD-x86_64" ;; + amd64-*-*bsd*) OUT="BSD-x86_64" ;; + *86*-*-*bsd*) # mimic ld behaviour when it's looking for libc... + if [ -L /usr/lib/libc.so ]; then # [Free|Net]BSD + libc=/usr/lib/libc.so + else # OpenBSD + # ld searches for highest libc.so.* and so do we + libc=`(ls /usr/lib/libc.so.* /lib/libc.so.* | tail -1) 2>/dev/null` + fi + case "`(file -L $libc) 2>/dev/null`" in + *ELF*) OUT="BSD-x86-elf" ;; + *) OUT="BSD-x86"; options="$options no-sse2" ;; + esac ;; + *-*-*bsd*) OUT="BSD-generic32" ;; + + x86_64-*-haiku) OUT="haiku-x86_64" ;; + *-*-haiku) OUT="haiku-x86" ;; + + *-*-osf) OUT="osf1-alpha-cc" ;; + *-*-tru64) OUT="tru64-alpha-cc" ;; + *-*-[Uu]nix[Ww]are7) + if [ "$CC" = "gcc" ]; then + OUT="unixware-7-gcc" ; options="$options no-sse2" + else + OUT="unixware-7" ; options="$options no-sse2" + __CNF_CPPFLAGS="$__CNF_CPPFLAGS -D__i386__" + fi + ;; + *-*-[Uu]nix[Ww]are20*) OUT="unixware-2.0"; options="$options no-sse2 no-sha512" ;; + *-*-[Uu]nix[Ww]are21*) OUT="unixware-2.1"; options="$options no-sse2 no-sha512" ;; + *-*-vos) + options="$options no-threads no-shared no-asm no-dso" + EXE=".pm" + OUT="vos-$CC" ;; + BS2000-siemens-sysv4) OUT="BS2000-OSD" ;; + *-hpux1*) + if [ $CC = "gcc" -a $GCC_BITS = "64" ]; then + OUT="hpux64-parisc2-gcc" + fi + [ "$KERNEL_BITS" ] || KERNEL_BITS=`(getconf KERNEL_BITS) 2>/dev/null` + KERNEL_BITS=${KERNEL_BITS:-32} + CPU_VERSION=`(getconf CPU_VERSION) 2>/dev/null` + CPU_VERSION=${CPU_VERSION:-0} + # See for further info on CPU_VERSION. + if [ $CPU_VERSION -ge 768 ]; then # IA-64 CPU + if [ $KERNEL_BITS -eq 64 -a "$CC" = "cc" ]; then + OUT="hpux64-ia64-cc" + else + OUT="hpux-ia64-cc" + fi + elif [ $CPU_VERSION -ge 532 ]; then # PA-RISC 2.x CPU + # PA-RISC 2.0 is no longer supported as separate 32-bit + # target. This is compensated for by run-time detection + # in most critical assembly modules and taking advantage + # of 2.0 architecture in PA-RISC 1.1 build. + OUT=${OUT:-"hpux-parisc1_1-${CC}"} + if [ $KERNEL_BITS -eq 64 -a "$CC" = "cc" ]; then + echo "WARNING! If you wish to build 64-bit library then you have to" + echo " invoke '$THERE/Configure hpux64-parisc2-cc' *manually*." + if [ "$DRYRUN" = "false" -a -t 1 ]; then + echo " You have about 5 seconds to press Ctrl-C to abort." + (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1 + fi + fi + elif [ $CPU_VERSION -ge 528 ]; then # PA-RISC 1.1+ CPU + OUT="hpux-parisc1_1-${CC}" + elif [ $CPU_VERSION -ge 523 ]; then # PA-RISC 1.0 CPU + OUT="hpux-parisc-${CC}" + else # Motorola(?) CPU + OUT="hpux-$CC" + fi + __CNF_CPPFLAGS="$__CNF_CPPFLAGS -D_REENTRANT" ;; + *-hpux) OUT="hpux-parisc-$CC" ;; + *-aix) + [ "$KERNEL_BITS" ] || KERNEL_BITS=`(getconf KERNEL_BITMODE) 2>/dev/null` + KERNEL_BITS=${KERNEL_BITS:-32} + OBJECT_MODE=${OBJECT_MODE:-32} + if [ "$CC" = "gcc" ]; then + OUT="aix-gcc" + if [ $OBJECT_MODE -eq 64 ]; then + echo 'Your $OBJECT_MODE was found to be set to 64' + OUT="aix64-gcc" + fi + elif [ $OBJECT_MODE -eq 64 ]; then + echo 'Your $OBJECT_MODE was found to be set to 64' + OUT="aix64-cc" + else + OUT="aix-cc" + if [ $KERNEL_BITS -eq 64 ]; then + echo "WARNING! If you wish to build 64-bit kit, then you have to" + echo " invoke '$THERE/Configure aix64-cc' *manually*." + if [ "$DRYRUN" = "false" -a -t 1 ]; then + echo " You have ~5 seconds to press Ctrl-C to abort." + (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1 + fi + fi + fi + if (lsattr -E -O -l `lsdev -c processor|awk '{print$1;exit}'` | grep -i powerpc) >/dev/null 2>&1; then + : # this applies even to Power3 and later, as they return PowerPC_POWER[345] + else + options="$options no-asm" + fi + ;; + # these are all covered by the catchall below + i[3456]86-*-cygwin) OUT="Cygwin-x86" ;; + *-*-cygwin) OUT="Cygwin-${MACHINE}" ;; + x86-*-android|i?86-*-android) OUT="android-x86" ;; + armv[7-9]*-*-android) + OUT="android-armeabi" + __CNF_CFLAGS="$__CNF_CFLAGS -march=armv7-a" + __CNF_CXXFLAGS="$__CNF_CXXFLAGS -march=armv7-a";; + arm*-*-android) OUT="android-armeabi" ;; + *) OUT=`echo $GUESSOS | awk -F- '{print $3}'`;; +esac + +# NB: This atalla support has been superseded by the ENGINE support +# That contains its own header and definitions anyway. Support can +# be enabled or disabled on any supported platform without external +# headers, eg. by adding the "hw-atalla" switch to ./config or +# perl Configure +# +# See whether we can compile Atalla support +#if [ -f /usr/include/atasi.h ] +#then +# __CNF_CPPFLAGS="$__CNF_CPPFLAGS -DATALLA" +#fi + +if [ -n "$CONFIG_OPTIONS" ]; then + options="$options $CONFIG_OPTIONS" +fi + +# gcc < 2.8 does not support -march=ultrasparc +if [ "$OUT" = solaris-sparcv9-gcc -a $GCCVER -lt 28 ] +then + echo "WARNING! Falling down to 'solaris-sparcv8-gcc'." + echo " Upgrade to gcc-2.8 or later." + sleep 5 + OUT=solaris-sparcv8-gcc +fi +if [ "$OUT" = "linux-sparcv9" -a $GCCVER -lt 28 ] +then + echo "WARNING! Falling down to 'linux-sparcv8'." + echo " Upgrade to gcc-2.8 or later." + sleep 5 + OUT=linux-sparcv8 +fi + +case "$GUESSOS" in + i386-*) options="$options 386" ;; +esac + +for i in aes aria bf camellia cast des dh dsa ec hmac idea md2 md5 mdc2 rc2 rc4 rc5 ripemd rsa seed sha sm2 sm3 sm4 +do + if [ ! -d $THERE/crypto/$i ] + then + options="$options no-$i" + fi +done + +if [ -z "$OUT" ]; then + OUT="$CC" +fi + +if [ ".$PERL" = . ] ; then + for i in . `echo $PATH | sed 's/:/ /g'`; do + if [ -f "$i/perl5$EXE" ] ; then + PERL="$i/perl5$EXE" + break; + fi; + done +fi + +if [ ".$PERL" = . ] ; then + for i in . `echo $PATH | sed 's/:/ /g'`; do + if [ -f "$i/perl$EXE" ] ; then + if "$i/perl$EXE" -e 'exit($]<5.0)'; then + PERL="$i/perl$EXE" + break; + fi; + fi; + done +fi + +if [ ".$PERL" = . ] ; then + echo "You need Perl 5." + exit 1 +fi + +# run Configure to check to see if we need to specify the +# compiler for the platform ... in which case we add it on +# the end ... otherwise we leave it off + +$PERL $THERE/Configure LIST | grep "$OUT-$CC" > /dev/null +if [ $? = "0" ]; then + OUT="$OUT-$CC" +fi + +OUT="$OUT" + +$PERL $THERE/Configure LIST | grep "$OUT" > /dev/null +if [ $? = "0" ]; then + if [ "$VERBOSE" = "true" ]; then + echo /usr/bin/env \ + __CNF_CPPDEFINES="'$__CNF_CPPDEFINES'" \ + __CNF_CPPINCLUDES="'$__CNF_CPPINCLUDES'" \ + __CNF_CPPFLAGS="'$__CNF_CPPFLAGS'" \ + __CNF_CFLAGS="'$__CNF_CFLAGS'" \ + __CNF_CXXFLAGS="'$__CNF_CXXFLAGS'" \ + __CNF_LDFLAGS="'$__CNF_LDFLAGS'" \ + __CNF_LDLIBS="'$__CNF_LDLIBS'" \ + $PERL $THERE/Configure $OUT $options + fi + if [ "$DRYRUN" = "false" ]; then + # eval to make sure quoted options, possibly with spaces inside, + # are treated right + eval /usr/bin/env \ + __CNF_CPPDEFINES="'$__CNF_CPPDEFINES'" \ + __CNF_CPPINCLUDES="'$__CNF_CPPINCLUDES'" \ + __CNF_CPPFLAGS="'$__CNF_CPPFLAGS'" \ + __CNF_CFLAGS="'$__CNF_CFLAGS'" \ + __CNF_CXXFLAGS="'$__CNF_CXXFLAGS'" \ + __CNF_LDFLAGS="'$__CNF_LDFLAGS'" \ + __CNF_LDLIBS="'$__CNF_LDLIBS'" \ + $PERL $THERE/Configure $OUT $options + fi +else + echo "This system ($OUT) is not supported. See file INSTALL for details." + exit 1 +fi + +if [ "$OUT" = "darwin64-x86_64-cc" ]; then + echo "WARNING! If you wish to build 32-bit libraries, then you have to" + echo " invoke 'KERNEL_BITS=32 $THERE/config $options'." +fi +) diff --git a/trunk/3rdparty/openssl-1.1-fit/config.com b/trunk/3rdparty/openssl-1.1-fit/config.com new file mode 100644 index 000000000..46ccaa20d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/config.com @@ -0,0 +1,93 @@ +$ ! OpenSSL config: determine the architecture and run Configure +$ ! Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. +$ ! +$ ! Licensed under the OpenSSL license (the "License"). You may not use +$ ! this file except in compliance with the License. You can obtain a +$ ! copy in the file LICENSE in the source distribution or at +$ ! https://www.openssl.org/source/license.html +$ ! +$ ! Very simple for the moment, it will take the following arguments: +$ ! +$ ! -32 or 32 sets /POINTER_SIZE=32 +$ ! -64 or 64 sets /POINTER_SIZE=64 +$ ! -d sets debugging +$ ! -h prints a usage and exits +$ ! -t test mode, doesn't run Configure +$ +$ arch = f$edit( f$getsyi( "arch_name"), "lowercase") +$ pointer_size = "" +$ dryrun = 0 +$ verbose = 0 +$ here = F$PARSE("A.;",F$ENVIRONMENT("PROCEDURE"),,,"SYNTAX_ONLY") - "A.;" +$ +$ collected_args = "" +$ P_index = 0 +$ LOOP1: +$ P_index = P_index + 1 +$ IF P_index .GT. 8 THEN GOTO ENDLOOP1 +$ P = F$EDIT(P1,"TRIM,LOWERCASE") +$ IF P .EQS. "-h" +$ THEN +$ dryrun = 1 +$ P = "" +$ TYPE SYS$INPUT +$ DECK +Usage: @config [options] + + -32 or 32 Build with 32-bit pointer size. + -64 or 64 Build with 64-bit pointer size. + -d Build with debugging. + -t Test mode, do not run the Configure perl script. + -v Verbose mode, show the exact Configure call that is being made. + -h This help. + +Any other text will be passed to the Configure perl script. +See INSTALL for instructions. + +$ EOD +$ ENDIF +$ IF P .EQS. "-t" +$ THEN +$ dryrun = 1 +$ verbose = 1 +$ P = "" +$ ENDIF +$ IF P .EQS. "-v" +$ THEN +$ verbose = 1 +$ P = "" +$ ENDIF +$ IF P .EQS. "-32" .OR. P .EQS. "32" +$ THEN +$ pointer_size = "-P32" +$ P = "" +$ ENDIF +$ IF P .EQS. "-64" .OR. P .EQS. "64" +$ THEN +$ pointer_size = "-P64" +$ P = "" +$ ENDIF +$ IF P .EQS. "-d" +$ THEN +$ collected_args = collected_args + " --debug" +$ P = "" +$ ENDIF +$ IF P .NES. "" THEN - + collected_args = collected_args + " """ + P1 + """" +$ P1 = P2 +$ P2 = P3 +$ P3 = P4 +$ P4 = P5 +$ P5 = P6 +$ P6 = P7 +$ P7 = P8 +$ P8 = "" +$ GOTO LOOP1 +$ ENDLOOP1: +$ +$ target = "vms-''arch'''pointer_size'" +$ IF verbose THEN - + WRITE SYS$OUTPUT "PERL ''here'Configure ""''target'""",collected_args +$ IF .not. dryrun THEN - + PERL 'here'Configure "''target'"'collected_args' +$ EXIT $STATUS diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/LPdir_nyi.c b/trunk/3rdparty/openssl-1.1-fit/crypto/LPdir_nyi.c new file mode 100644 index 000000000..b02449f7c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/LPdir_nyi.c @@ -0,0 +1,56 @@ +/* + * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This file is dual-licensed and is also available under the following + * terms: + * + * Copyright (c) 2004, Richard Levitte + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef LPDIR_H +# include "LPdir.h" +#endif + +struct LP_dir_context_st { + void *dummy; +}; +const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory) +{ + errno = EINVAL; + return 0; +} + +int LP_find_file_end(LP_DIR_CTX **ctx) +{ + errno = EINVAL; + return 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/LPdir_unix.c b/trunk/3rdparty/openssl-1.1-fit/crypto/LPdir_unix.c new file mode 100644 index 000000000..b1022895c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/LPdir_unix.c @@ -0,0 +1,169 @@ +/* + * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This file is dual-licensed and is also available under the following + * terms: + * + * Copyright (c) 2004, 2018, Richard Levitte + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#ifndef LPDIR_H +# include "LPdir.h" +#endif +#ifdef __VMS +# include +#endif + +/* + * The POSIX macro for the maximum number of characters in a file path is + * NAME_MAX. However, some operating systems use PATH_MAX instead. + * Therefore, it seems natural to first check for PATH_MAX and use that, and + * if it doesn't exist, use NAME_MAX. + */ +#if defined(PATH_MAX) +# define LP_ENTRY_SIZE PATH_MAX +#elif defined(NAME_MAX) +# define LP_ENTRY_SIZE NAME_MAX +#endif + +/* + * Of course, there's the possibility that neither PATH_MAX nor NAME_MAX + * exist. It's also possible that NAME_MAX exists but is define to a very + * small value (HP-UX offers 14), so we need to check if we got a result, and + * if it meets a minimum standard, and create or change it if not. + */ +#if !defined(LP_ENTRY_SIZE) || LP_ENTRY_SIZE<255 +# undef LP_ENTRY_SIZE +# define LP_ENTRY_SIZE 255 +#endif + +struct LP_dir_context_st { + DIR *dir; + char entry_name[LP_ENTRY_SIZE + 1]; +#ifdef __VMS + int expect_file_generations; + char previous_entry_name[LP_ENTRY_SIZE + 1]; +#endif +}; + +const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory) +{ + struct dirent *direntry = NULL; + + if (ctx == NULL || directory == NULL) { + errno = EINVAL; + return 0; + } + + errno = 0; + if (*ctx == NULL) { + *ctx = malloc(sizeof(**ctx)); + if (*ctx == NULL) { + errno = ENOMEM; + return 0; + } + memset(*ctx, 0, sizeof(**ctx)); + +#ifdef __VMS + { + char c = directory[strlen(directory) - 1]; + + if (c == ']' || c == '>' || c == ':') + (*ctx)->expect_file_generations = 1; + } +#endif + + (*ctx)->dir = opendir(directory); + if ((*ctx)->dir == NULL) { + int save_errno = errno; /* Probably not needed, but I'm paranoid */ + free(*ctx); + *ctx = NULL; + errno = save_errno; + return 0; + } + } + +#ifdef __VMS + strncpy((*ctx)->previous_entry_name, (*ctx)->entry_name, + sizeof((*ctx)->previous_entry_name)); + + again: +#endif + + direntry = readdir((*ctx)->dir); + if (direntry == NULL) { + return 0; + } + + strncpy((*ctx)->entry_name, direntry->d_name, + sizeof((*ctx)->entry_name) - 1); + (*ctx)->entry_name[sizeof((*ctx)->entry_name) - 1] = '\0'; +#ifdef __VMS + if ((*ctx)->expect_file_generations) { + char *p = (*ctx)->entry_name + strlen((*ctx)->entry_name); + + while(p > (*ctx)->entry_name && isdigit(p[-1])) + p--; + if (p > (*ctx)->entry_name && p[-1] == ';') + p[-1] = '\0'; + if (strcasecmp((*ctx)->entry_name, (*ctx)->previous_entry_name) == 0) + goto again; + } +#endif + return (*ctx)->entry_name; +} + +int LP_find_file_end(LP_DIR_CTX **ctx) +{ + if (ctx != NULL && *ctx != NULL) { + int ret = closedir((*ctx)->dir); + + free(*ctx); + switch (ret) { + case 0: + return 1; + case -1: + return 0; + default: + break; + } + } + errno = EINVAL; + return 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/LPdir_vms.c b/trunk/3rdparty/openssl-1.1-fit/crypto/LPdir_vms.c new file mode 100644 index 000000000..e35363fd6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/LPdir_vms.c @@ -0,0 +1,207 @@ +/* + * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This file is dual-licensed and is also available under the following + * terms: + * + * Copyright (c) 2004, Richard Levitte + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef LPDIR_H +# include "LPdir.h" +#endif +#include "vms_rms.h" + +/* Some compiler options hide EVMSERR. */ +#ifndef EVMSERR +# define EVMSERR 65535 /* error for non-translatable VMS errors */ +#endif + +struct LP_dir_context_st { + unsigned long VMS_context; + char filespec[NAMX_MAXRSS + 1]; + char result[NAMX_MAXRSS + 1]; + struct dsc$descriptor_d filespec_dsc; + struct dsc$descriptor_d result_dsc; +}; + +const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory) +{ + int status; + char *p, *r; + size_t l; + unsigned long flags = 0; + +/* Arrange 32-bit pointer to (copied) string storage, if needed. */ +#if __INITIAL_POINTER_SIZE == 64 +# pragma pointer_size save +# pragma pointer_size 32 + char *ctx_filespec_32p; +# pragma pointer_size restore + char ctx_filespec_32[NAMX_MAXRSS + 1]; +#endif /* __INITIAL_POINTER_SIZE == 64 */ + +#ifdef NAML$C_MAXRSS + flags |= LIB$M_FIL_LONG_NAMES; +#endif + + if (ctx == NULL || directory == NULL) { + errno = EINVAL; + return 0; + } + + errno = 0; + if (*ctx == NULL) { + size_t filespeclen = strlen(directory); + char *filespec = NULL; + + if (filespeclen == 0) { + errno = ENOENT; + return 0; + } + + /* MUST be a VMS directory specification! Let's estimate if it is. */ + if (directory[filespeclen - 1] != ']' + && directory[filespeclen - 1] != '>' + && directory[filespeclen - 1] != ':') { + errno = EINVAL; + return 0; + } + + filespeclen += 4; /* "*.*;" */ + + if (filespeclen > NAMX_MAXRSS) { + errno = ENAMETOOLONG; + return 0; + } + + *ctx = malloc(sizeof(**ctx)); + if (*ctx == NULL) { + errno = ENOMEM; + return 0; + } + memset(*ctx, 0, sizeof(**ctx)); + + strcpy((*ctx)->filespec, directory); + strcat((*ctx)->filespec, "*.*;"); + +/* Arrange 32-bit pointer to (copied) string storage, if needed. */ +#if __INITIAL_POINTER_SIZE == 64 +# define CTX_FILESPEC ctx_filespec_32p + /* Copy the file name to storage with a 32-bit pointer. */ + ctx_filespec_32p = ctx_filespec_32; + strcpy(ctx_filespec_32p, (*ctx)->filespec); +#else /* __INITIAL_POINTER_SIZE == 64 */ +# define CTX_FILESPEC (*ctx)->filespec +#endif /* __INITIAL_POINTER_SIZE == 64 [else] */ + + (*ctx)->filespec_dsc.dsc$w_length = filespeclen; + (*ctx)->filespec_dsc.dsc$b_dtype = DSC$K_DTYPE_T; + (*ctx)->filespec_dsc.dsc$b_class = DSC$K_CLASS_S; + (*ctx)->filespec_dsc.dsc$a_pointer = CTX_FILESPEC; + } + + (*ctx)->result_dsc.dsc$w_length = 0; + (*ctx)->result_dsc.dsc$b_dtype = DSC$K_DTYPE_T; + (*ctx)->result_dsc.dsc$b_class = DSC$K_CLASS_D; + (*ctx)->result_dsc.dsc$a_pointer = 0; + + status = lib$find_file(&(*ctx)->filespec_dsc, &(*ctx)->result_dsc, + &(*ctx)->VMS_context, 0, 0, 0, &flags); + + if (status == RMS$_NMF) { + errno = 0; + vaxc$errno = status; + return NULL; + } + + if (!$VMS_STATUS_SUCCESS(status)) { + errno = EVMSERR; + vaxc$errno = status; + return NULL; + } + + /* + * Quick, cheap and dirty way to discard any device and directory, since + * we only want file names + */ + l = (*ctx)->result_dsc.dsc$w_length; + p = (*ctx)->result_dsc.dsc$a_pointer; + r = p; + for (; *p; p++) { + if (*p == '^' && p[1] != '\0') { /* Take care of ODS-5 escapes */ + p++; + } else if (*p == ':' || *p == '>' || *p == ']') { + l -= p + 1 - r; + r = p + 1; + } else if (*p == ';') { + l = p - r; + break; + } + } + + strncpy((*ctx)->result, r, l); + (*ctx)->result[l] = '\0'; + str$free1_dx(&(*ctx)->result_dsc); + + return (*ctx)->result; +} + +int LP_find_file_end(LP_DIR_CTX **ctx) +{ + if (ctx != NULL && *ctx != NULL) { + int status = lib$find_file_end(&(*ctx)->VMS_context); + + free(*ctx); + + if (!$VMS_STATUS_SUCCESS(status)) { + errno = EVMSERR; + vaxc$errno = status; + return 0; + } + return 1; + } + errno = EINVAL; + return 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/LPdir_win.c b/trunk/3rdparty/openssl-1.1-fit/crypto/LPdir_win.c new file mode 100644 index 000000000..1dc1ef122 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/LPdir_win.c @@ -0,0 +1,214 @@ +/* + * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This file is dual-licensed and is also available under the following + * terms: + * + * Copyright (c) 2004, Richard Levitte + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "internal/numbers.h" +#ifndef LPDIR_H +# include "LPdir.h" +#endif + +/* + * We're most likely overcautious here, but let's reserve for broken WinCE + * headers and explicitly opt for UNICODE call. Keep in mind that our WinCE + * builds are compiled with -DUNICODE [as well as -D_UNICODE]. + */ +#if defined(LP_SYS_WINCE) && !defined(FindFirstFile) +# define FindFirstFile FindFirstFileW +#endif +#if defined(LP_SYS_WINCE) && !defined(FindNextFile) +# define FindNextFile FindNextFileW +#endif + +#ifndef NAME_MAX +# define NAME_MAX 255 +#endif + +#ifdef CP_UTF8 +# define CP_DEFAULT CP_UTF8 +#else +# define CP_DEFAULT CP_ACP +#endif + +struct LP_dir_context_st { + WIN32_FIND_DATA ctx; + HANDLE handle; + char entry_name[NAME_MAX + 1]; +}; + +const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory) +{ + if (ctx == NULL || directory == NULL) { + errno = EINVAL; + return 0; + } + + errno = 0; + if (*ctx == NULL) { + size_t dirlen = strlen(directory); + + if (dirlen == 0 || dirlen > INT_MAX - 3) { + errno = ENOENT; + return 0; + } + + *ctx = malloc(sizeof(**ctx)); + if (*ctx == NULL) { + errno = ENOMEM; + return 0; + } + memset(*ctx, 0, sizeof(**ctx)); + + if (sizeof(TCHAR) != sizeof(char)) { + TCHAR *wdir = NULL; + /* len_0 denotes string length *with* trailing 0 */ + size_t index = 0, len_0 = dirlen + 1; +#ifdef LP_MULTIBYTE_AVAILABLE + int sz = 0; + UINT cp; + + do { +# ifdef CP_UTF8 + if ((sz = MultiByteToWideChar((cp = CP_UTF8), 0, + directory, len_0, + NULL, 0)) > 0 || + GetLastError() != ERROR_NO_UNICODE_TRANSLATION) + break; +# endif + sz = MultiByteToWideChar((cp = CP_ACP), 0, + directory, len_0, + NULL, 0); + } while (0); + + if (sz > 0) { + /* + * allocate two additional characters in case we need to + * concatenate asterisk, |sz| covers trailing '\0'! + */ + wdir = _alloca((sz + 2) * sizeof(TCHAR)); + if (!MultiByteToWideChar(cp, 0, directory, len_0, + (WCHAR *)wdir, sz)) { + free(*ctx); + *ctx = NULL; + errno = EINVAL; + return 0; + } + } else +#endif + { + sz = len_0; + /* + * allocate two additional characters in case we need to + * concatenate asterisk, |sz| covers trailing '\0'! + */ + wdir = _alloca((sz + 2) * sizeof(TCHAR)); + for (index = 0; index < len_0; index++) + wdir[index] = (TCHAR)directory[index]; + } + + sz--; /* wdir[sz] is trailing '\0' now */ + if (wdir[sz - 1] != TEXT('*')) { + if (wdir[sz - 1] != TEXT('/') && wdir[sz - 1] != TEXT('\\')) + _tcscpy(wdir + sz, TEXT("/*")); + else + _tcscpy(wdir + sz, TEXT("*")); + } + + (*ctx)->handle = FindFirstFile(wdir, &(*ctx)->ctx); + } else { + if (directory[dirlen - 1] != '*') { + char *buf = _alloca(dirlen + 3); + + strcpy(buf, directory); + if (buf[dirlen - 1] != '/' && buf[dirlen - 1] != '\\') + strcpy(buf + dirlen, "/*"); + else + strcpy(buf + dirlen, "*"); + + directory = buf; + } + + (*ctx)->handle = FindFirstFile((TCHAR *)directory, &(*ctx)->ctx); + } + + if ((*ctx)->handle == INVALID_HANDLE_VALUE) { + free(*ctx); + *ctx = NULL; + errno = EINVAL; + return 0; + } + } else { + if (FindNextFile((*ctx)->handle, &(*ctx)->ctx) == FALSE) { + return 0; + } + } + if (sizeof(TCHAR) != sizeof(char)) { + TCHAR *wdir = (*ctx)->ctx.cFileName; + size_t index, len_0 = 0; + + while (wdir[len_0] && len_0 < (sizeof((*ctx)->entry_name) - 1)) + len_0++; + len_0++; + +#ifdef LP_MULTIBYTE_AVAILABLE + if (!WideCharToMultiByte(CP_DEFAULT, 0, (WCHAR *)wdir, len_0, + (*ctx)->entry_name, + sizeof((*ctx)->entry_name), NULL, 0)) +#endif + for (index = 0; index < len_0; index++) + (*ctx)->entry_name[index] = (char)wdir[index]; + } else + strncpy((*ctx)->entry_name, (const char *)(*ctx)->ctx.cFileName, + sizeof((*ctx)->entry_name) - 1); + + (*ctx)->entry_name[sizeof((*ctx)->entry_name) - 1] = '\0'; + + return (*ctx)->entry_name; +} + +int LP_find_file_end(LP_DIR_CTX **ctx) +{ + if (ctx != NULL && *ctx != NULL) { + FindClose((*ctx)->handle); + free(*ctx); + *ctx = NULL; + return 1; + } + errno = EINVAL; + return 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/LPdir_win32.c b/trunk/3rdparty/openssl-1.1-fit/crypto/LPdir_win32.c new file mode 100644 index 000000000..edceb98d6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/LPdir_win32.c @@ -0,0 +1,41 @@ +/* + * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This file is dual-licensed and is also available under the following + * terms: + * + * Copyright (c) 2004, Richard Levitte + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LP_SYS_WIN32 +#define LP_MULTIBYTE_AVAILABLE +#include "LPdir_win.c" diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/LPdir_wince.c b/trunk/3rdparty/openssl-1.1-fit/crypto/LPdir_wince.c new file mode 100644 index 000000000..a24e73829 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/LPdir_wince.c @@ -0,0 +1,44 @@ +/* + * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This file is dual-licensed and is also available under the following + * terms: + * + * Copyright (c) 2004, Richard Levitte + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LP_SYS_WINCE +/* + * We might want to define LP_MULTIBYTE_AVAILABLE here. It's currently under + * investigation what the exact conditions would be + */ +#include "LPdir_win.c" diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_cbc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_cbc.c new file mode 100644 index 000000000..342841fc4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_cbc.c @@ -0,0 +1,24 @@ +/* + * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const AES_KEY *key, + unsigned char *ivec, const int enc) +{ + + if (enc) + CRYPTO_cbc128_encrypt(in, out, len, key, ivec, + (block128_f) AES_encrypt); + else + CRYPTO_cbc128_decrypt(in, out, len, key, ivec, + (block128_f) AES_decrypt); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_cfb.c b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_cfb.c new file mode 100644 index 000000000..f010e3c4e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_cfb.c @@ -0,0 +1,43 @@ +/* + * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +/* + * The input and output encrypted as though 128bit cfb mode is being used. + * The extra state information to record how much of the 128bit block we have + * used is contained in *num; + */ + +void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, int *num, const int enc) +{ + + CRYPTO_cfb128_encrypt(in, out, length, key, ivec, num, enc, + (block128_f) AES_encrypt); +} + +/* N.B. This expects the input to be packed, MS bit first */ +void AES_cfb1_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, int *num, const int enc) +{ + CRYPTO_cfb128_1_encrypt(in, out, length, key, ivec, num, enc, + (block128_f) AES_encrypt); +} + +void AES_cfb8_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, int *num, const int enc) +{ + CRYPTO_cfb128_8_encrypt(in, out, length, key, ivec, num, enc, + (block128_f) AES_encrypt); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_core.c b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_core.c new file mode 100644 index 000000000..f1f11fd8d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_core.c @@ -0,0 +1,1367 @@ +/* + * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/** + * rijndael-alg-fst.c + * + * @version 3.0 (December 2000) + * + * Optimised ANSI C code for the Rijndael cipher (now AES) + * + * @author Vincent Rijmen + * @author Antoon Bosselaers + * @author Paulo Barreto + * + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Note: rewritten a little bit to provide error control and an OpenSSL- + compatible API */ + +#include + +#include +#include +#include +#include "aes_locl.h" + +#ifndef AES_ASM +/*- +Te0[x] = S [x].[02, 01, 01, 03]; +Te1[x] = S [x].[03, 02, 01, 01]; +Te2[x] = S [x].[01, 03, 02, 01]; +Te3[x] = S [x].[01, 01, 03, 02]; + +Td0[x] = Si[x].[0e, 09, 0d, 0b]; +Td1[x] = Si[x].[0b, 0e, 09, 0d]; +Td2[x] = Si[x].[0d, 0b, 0e, 09]; +Td3[x] = Si[x].[09, 0d, 0b, 0e]; +Td4[x] = Si[x].[01]; +*/ + +static const u32 Te0[256] = { + 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, + 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, + 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, + 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, + 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, + 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, + 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, + 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, + 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, + 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, + 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, + 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, + 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, + 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, + 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, + 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, + 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, + 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, + 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, + 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, + 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, + 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, + 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, + 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, + 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, + 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, + 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, + 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, + 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, + 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, + 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, + 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, + 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, + 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, + 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, + 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, + 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, + 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, + 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, + 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, + 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, + 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, + 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, + 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, + 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, + 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, + 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, + 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, + 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, + 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, + 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, + 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, + 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, + 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, + 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, + 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, + 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, + 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, + 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, + 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, + 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, + 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, + 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, + 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, +}; +static const u32 Te1[256] = { + 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, + 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, + 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, + 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, + 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, + 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, + 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, + 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, + 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, + 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, + 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, + 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, + 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, + 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, + 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, + 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, + 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, + 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, + 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, + 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, + 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, + 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, + 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, + 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, + 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, + 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, + 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, + 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, + 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, + 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, + 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, + 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, + 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, + 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, + 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, + 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, + 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, + 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, + 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, + 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, + 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, + 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, + 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, + 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, + 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, + 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, + 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, + 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, + 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, + 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, + 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, + 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, + 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, + 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, + 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, + 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, + 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, + 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, + 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, + 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, + 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, + 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, + 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, + 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, +}; +static const u32 Te2[256] = { + 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, + 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, + 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, + 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, + 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, + 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, + 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, + 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, + 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, + 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, + 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, + 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, + 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, + 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, + 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, + 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, + 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, + 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, + 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, + 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, + 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, + 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, + 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, + 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, + 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, + 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, + 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, + 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, + 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, + 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, + 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, + 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, + 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, + 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, + 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, + 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, + 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, + 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, + 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, + 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, + 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, + 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, + 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, + 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, + 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, + 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, + 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, + 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, + 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, + 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, + 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, + 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, + 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, + 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, + 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, + 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, + 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, + 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, + 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, + 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, + 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, + 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, + 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, + 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, +}; +static const u32 Te3[256] = { + 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, + 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, + 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, + 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, + 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, + 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, + 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, + 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, + 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, + 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, + 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, + 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, + 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, + 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, + 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, + 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, + 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, + 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, + 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, + 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, + 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, + 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, + 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, + 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, + 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, + 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, + 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, + 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, + 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, + 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, + 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, + 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, + 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, + 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, + 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, + 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, + 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, + 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, + 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, + 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, + 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, + 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, + 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, + 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, + 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, + 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, + 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, + 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, + 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, + 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, + 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, + 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, + 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, + 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, + 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, + 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, + 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, + 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, + 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, + 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, + 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, + 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, + 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, + 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, +}; + +static const u32 Td0[256] = { + 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, + 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, + 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, + 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, + 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, + 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, + 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, + 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, + 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, + 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, + 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, + 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, + 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, + 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, + 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, + 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, + 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, + 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, + 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, + 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, + 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, + 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, + 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, + 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, + 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, + 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, + 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, + 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, + 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, + 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, + 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, + 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, + 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, + 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, + 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, + 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, + 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, + 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, + 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, + 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, + 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, + 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, + 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, + 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, + 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, + 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, + 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, + 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, + 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, + 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, + 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, + 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, + 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, + 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, + 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, + 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, + 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, + 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, + 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, + 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, + 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, + 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, + 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, + 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, +}; +static const u32 Td1[256] = { + 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, + 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, + 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, + 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, + 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, + 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, + 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, + 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, + 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, + 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, + 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, + 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, + 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, + 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, + 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, + 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, + 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, + 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, + 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, + 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, + 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, + 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, + 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, + 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, + 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, + 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, + 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, + 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, + 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, + 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, + 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, + 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, + 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, + 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, + 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, + 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, + 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, + 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, + 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, + 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, + 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, + 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, + 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, + 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, + 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, + 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, + 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, + 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, + 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, + 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, + 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, + 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, + 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, + 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, + 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, + 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, + 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, + 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, + 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, + 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, + 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, + 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, + 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, + 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, +}; +static const u32 Td2[256] = { + 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, + 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, + 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, + 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, + 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, + 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, + 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, + 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, + 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, + 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, + 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, + 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, + 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, + 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, + 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, + 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, + 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, + 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, + 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, + 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, + 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, + 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, + 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, + 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, + 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, + 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, + 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, + 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, + 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, + 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, + 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, + 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, + 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, + 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, + 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, + 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, + 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, + 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, + 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, + 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, + 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, + 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, + 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, + 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, + 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, + 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, + 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, + 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, + 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, + 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, + 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, + 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, + 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, + 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, + 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, + 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, + 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, + 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, + 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, + 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, + 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, + 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, + 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, + 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, +}; +static const u32 Td3[256] = { + 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, + 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, + 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, + 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, + 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, + 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, + 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, + 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, + 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, + 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, + 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, + 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, + 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, + 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, + 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, + 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, + 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, + 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, + 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, + 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, + 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, + 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, + 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, + 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, + 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, + 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, + 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, + 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, + 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, + 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, + 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, + 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, + 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, + 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, + 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, + 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, + 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, + 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, + 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, + 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, + 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, + 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, + 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, + 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, + 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, + 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, + 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, + 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, + 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, + 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, + 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, + 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, + 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, + 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, + 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, + 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, + 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, + 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, + 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, + 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, + 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, + 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, + 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, + 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, +}; +static const u8 Td4[256] = { + 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U, + 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU, + 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U, + 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU, + 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU, + 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU, + 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U, + 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U, + 0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U, + 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U, + 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU, + 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U, + 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU, + 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U, + 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U, + 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU, + 0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU, + 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U, + 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U, + 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU, + 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U, + 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU, + 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U, + 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U, + 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U, + 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU, + 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU, + 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU, + 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U, + 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U, + 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, + 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU, +}; +static const u32 rcon[] = { + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, + 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +}; + +/** + * Expand the cipher key into the encryption key schedule. + */ +int AES_set_encrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key) +{ + + u32 *rk; + int i = 0; + u32 temp; + + if (!userKey || !key) + return -1; + if (bits != 128 && bits != 192 && bits != 256) + return -2; + + rk = key->rd_key; + + if (bits == 128) + key->rounds = 10; + else if (bits == 192) + key->rounds = 12; + else + key->rounds = 14; + + rk[0] = GETU32(userKey ); + rk[1] = GETU32(userKey + 4); + rk[2] = GETU32(userKey + 8); + rk[3] = GETU32(userKey + 12); + if (bits == 128) { + while (1) { + temp = rk[3]; + rk[4] = rk[0] ^ + (Te2[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te0[(temp ) & 0xff] & 0x0000ff00) ^ + (Te1[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + if (++i == 10) { + return 0; + } + rk += 4; + } + } + rk[4] = GETU32(userKey + 16); + rk[5] = GETU32(userKey + 20); + if (bits == 192) { + while (1) { + temp = rk[ 5]; + rk[ 6] = rk[ 0] ^ + (Te2[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te0[(temp ) & 0xff] & 0x0000ff00) ^ + (Te1[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[ 7] = rk[ 1] ^ rk[ 6]; + rk[ 8] = rk[ 2] ^ rk[ 7]; + rk[ 9] = rk[ 3] ^ rk[ 8]; + if (++i == 8) { + return 0; + } + rk[10] = rk[ 4] ^ rk[ 9]; + rk[11] = rk[ 5] ^ rk[10]; + rk += 6; + } + } + rk[6] = GETU32(userKey + 24); + rk[7] = GETU32(userKey + 28); + if (bits == 256) { + while (1) { + temp = rk[ 7]; + rk[ 8] = rk[ 0] ^ + (Te2[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te0[(temp ) & 0xff] & 0x0000ff00) ^ + (Te1[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[ 9] = rk[ 1] ^ rk[ 8]; + rk[10] = rk[ 2] ^ rk[ 9]; + rk[11] = rk[ 3] ^ rk[10]; + if (++i == 7) { + return 0; + } + temp = rk[11]; + rk[12] = rk[ 4] ^ + (Te2[(temp >> 24) ] & 0xff000000) ^ + (Te3[(temp >> 16) & 0xff] & 0x00ff0000) ^ + (Te0[(temp >> 8) & 0xff] & 0x0000ff00) ^ + (Te1[(temp ) & 0xff] & 0x000000ff); + rk[13] = rk[ 5] ^ rk[12]; + rk[14] = rk[ 6] ^ rk[13]; + rk[15] = rk[ 7] ^ rk[14]; + + rk += 8; + } + } + return 0; +} + +/** + * Expand the cipher key into the decryption key schedule. + */ +int AES_set_decrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key) +{ + + u32 *rk; + int i, j, status; + u32 temp; + + /* first, start with an encryption schedule */ + status = AES_set_encrypt_key(userKey, bits, key); + if (status < 0) + return status; + + rk = key->rd_key; + + /* invert the order of the round keys: */ + for (i = 0, j = 4*(key->rounds); i < j; i += 4, j -= 4) { + temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; + temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; + temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; + temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; + } + /* apply the inverse MixColumn transform to all round keys but the first and the last: */ + for (i = 1; i < (key->rounds); i++) { + rk += 4; + rk[0] = + Td0[Te1[(rk[0] >> 24) ] & 0xff] ^ + Td1[Te1[(rk[0] >> 16) & 0xff] & 0xff] ^ + Td2[Te1[(rk[0] >> 8) & 0xff] & 0xff] ^ + Td3[Te1[(rk[0] ) & 0xff] & 0xff]; + rk[1] = + Td0[Te1[(rk[1] >> 24) ] & 0xff] ^ + Td1[Te1[(rk[1] >> 16) & 0xff] & 0xff] ^ + Td2[Te1[(rk[1] >> 8) & 0xff] & 0xff] ^ + Td3[Te1[(rk[1] ) & 0xff] & 0xff]; + rk[2] = + Td0[Te1[(rk[2] >> 24) ] & 0xff] ^ + Td1[Te1[(rk[2] >> 16) & 0xff] & 0xff] ^ + Td2[Te1[(rk[2] >> 8) & 0xff] & 0xff] ^ + Td3[Te1[(rk[2] ) & 0xff] & 0xff]; + rk[3] = + Td0[Te1[(rk[3] >> 24) ] & 0xff] ^ + Td1[Te1[(rk[3] >> 16) & 0xff] & 0xff] ^ + Td2[Te1[(rk[3] >> 8) & 0xff] & 0xff] ^ + Td3[Te1[(rk[3] ) & 0xff] & 0xff]; + } + return 0; +} + +/* + * Encrypt a single block + * in and out can overlap + */ +void AES_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key) { + + const u32 *rk; + u32 s0, s1, s2, s3, t0, t1, t2, t3; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + assert(in && out && key); + rk = key->rd_key; + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(in ) ^ rk[0]; + s1 = GETU32(in + 4) ^ rk[1]; + s2 = GETU32(in + 8) ^ rk[2]; + s3 = GETU32(in + 12) ^ rk[3]; +#ifdef FULL_UNROLL + /* round 1: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7]; + /* round 2: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; + if (key->rounds > 10) { + /* round 10: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43]; + /* round 11: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47]; + if (key->rounds > 12) { + /* round 12: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51]; + /* round 13: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55]; + } + } + rk += key->rounds << 2; +#else /* !FULL_UNROLL */ + /* + * Nr - 1 full rounds: + */ + r = key->rounds >> 1; + for (;;) { + t0 = + Te0[(s0 >> 24) ] ^ + Te1[(s1 >> 16) & 0xff] ^ + Te2[(s2 >> 8) & 0xff] ^ + Te3[(s3 ) & 0xff] ^ + rk[4]; + t1 = + Te0[(s1 >> 24) ] ^ + Te1[(s2 >> 16) & 0xff] ^ + Te2[(s3 >> 8) & 0xff] ^ + Te3[(s0 ) & 0xff] ^ + rk[5]; + t2 = + Te0[(s2 >> 24) ] ^ + Te1[(s3 >> 16) & 0xff] ^ + Te2[(s0 >> 8) & 0xff] ^ + Te3[(s1 ) & 0xff] ^ + rk[6]; + t3 = + Te0[(s3 >> 24) ] ^ + Te1[(s0 >> 16) & 0xff] ^ + Te2[(s1 >> 8) & 0xff] ^ + Te3[(s2 ) & 0xff] ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Te0[(t0 >> 24) ] ^ + Te1[(t1 >> 16) & 0xff] ^ + Te2[(t2 >> 8) & 0xff] ^ + Te3[(t3 ) & 0xff] ^ + rk[0]; + s1 = + Te0[(t1 >> 24) ] ^ + Te1[(t2 >> 16) & 0xff] ^ + Te2[(t3 >> 8) & 0xff] ^ + Te3[(t0 ) & 0xff] ^ + rk[1]; + s2 = + Te0[(t2 >> 24) ] ^ + Te1[(t3 >> 16) & 0xff] ^ + Te2[(t0 >> 8) & 0xff] ^ + Te3[(t1 ) & 0xff] ^ + rk[2]; + s3 = + Te0[(t3 >> 24) ] ^ + Te1[(t0 >> 16) & 0xff] ^ + Te2[(t1 >> 8) & 0xff] ^ + Te3[(t2 ) & 0xff] ^ + rk[3]; + } +#endif /* ?FULL_UNROLL */ + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Te2[(t0 >> 24) ] & 0xff000000) ^ + (Te3[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (Te0[(t2 >> 8) & 0xff] & 0x0000ff00) ^ + (Te1[(t3 ) & 0xff] & 0x000000ff) ^ + rk[0]; + PUTU32(out , s0); + s1 = + (Te2[(t1 >> 24) ] & 0xff000000) ^ + (Te3[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (Te0[(t3 >> 8) & 0xff] & 0x0000ff00) ^ + (Te1[(t0 ) & 0xff] & 0x000000ff) ^ + rk[1]; + PUTU32(out + 4, s1); + s2 = + (Te2[(t2 >> 24) ] & 0xff000000) ^ + (Te3[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (Te0[(t0 >> 8) & 0xff] & 0x0000ff00) ^ + (Te1[(t1 ) & 0xff] & 0x000000ff) ^ + rk[2]; + PUTU32(out + 8, s2); + s3 = + (Te2[(t3 >> 24) ] & 0xff000000) ^ + (Te3[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (Te0[(t1 >> 8) & 0xff] & 0x0000ff00) ^ + (Te1[(t2 ) & 0xff] & 0x000000ff) ^ + rk[3]; + PUTU32(out + 12, s3); +} + +/* + * Decrypt a single block + * in and out can overlap + */ +void AES_decrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key) +{ + + const u32 *rk; + u32 s0, s1, s2, s3, t0, t1, t2, t3; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + assert(in && out && key); + rk = key->rd_key; + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(in ) ^ rk[0]; + s1 = GETU32(in + 4) ^ rk[1]; + s2 = GETU32(in + 8) ^ rk[2]; + s3 = GETU32(in + 12) ^ rk[3]; +#ifdef FULL_UNROLL + /* round 1: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7]; + /* round 2: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39]; + if (key->rounds > 10) { + /* round 10: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43]; + /* round 11: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47]; + if (key->rounds > 12) { + /* round 12: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51]; + /* round 13: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55]; + } + } + rk += key->rounds << 2; +#else /* !FULL_UNROLL */ + /* + * Nr - 1 full rounds: + */ + r = key->rounds >> 1; + for (;;) { + t0 = + Td0[(s0 >> 24) ] ^ + Td1[(s3 >> 16) & 0xff] ^ + Td2[(s2 >> 8) & 0xff] ^ + Td3[(s1 ) & 0xff] ^ + rk[4]; + t1 = + Td0[(s1 >> 24) ] ^ + Td1[(s0 >> 16) & 0xff] ^ + Td2[(s3 >> 8) & 0xff] ^ + Td3[(s2 ) & 0xff] ^ + rk[5]; + t2 = + Td0[(s2 >> 24) ] ^ + Td1[(s1 >> 16) & 0xff] ^ + Td2[(s0 >> 8) & 0xff] ^ + Td3[(s3 ) & 0xff] ^ + rk[6]; + t3 = + Td0[(s3 >> 24) ] ^ + Td1[(s2 >> 16) & 0xff] ^ + Td2[(s1 >> 8) & 0xff] ^ + Td3[(s0 ) & 0xff] ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Td0[(t0 >> 24) ] ^ + Td1[(t3 >> 16) & 0xff] ^ + Td2[(t2 >> 8) & 0xff] ^ + Td3[(t1 ) & 0xff] ^ + rk[0]; + s1 = + Td0[(t1 >> 24) ] ^ + Td1[(t0 >> 16) & 0xff] ^ + Td2[(t3 >> 8) & 0xff] ^ + Td3[(t2 ) & 0xff] ^ + rk[1]; + s2 = + Td0[(t2 >> 24) ] ^ + Td1[(t1 >> 16) & 0xff] ^ + Td2[(t0 >> 8) & 0xff] ^ + Td3[(t3 ) & 0xff] ^ + rk[2]; + s3 = + Td0[(t3 >> 24) ] ^ + Td1[(t2 >> 16) & 0xff] ^ + Td2[(t1 >> 8) & 0xff] ^ + Td3[(t0 ) & 0xff] ^ + rk[3]; + } +#endif /* ?FULL_UNROLL */ + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + ((u32)Td4[(t0 >> 24) ] << 24) ^ + ((u32)Td4[(t3 >> 16) & 0xff] << 16) ^ + ((u32)Td4[(t2 >> 8) & 0xff] << 8) ^ + ((u32)Td4[(t1 ) & 0xff]) ^ + rk[0]; + PUTU32(out , s0); + s1 = + ((u32)Td4[(t1 >> 24) ] << 24) ^ + ((u32)Td4[(t0 >> 16) & 0xff] << 16) ^ + ((u32)Td4[(t3 >> 8) & 0xff] << 8) ^ + ((u32)Td4[(t2 ) & 0xff]) ^ + rk[1]; + PUTU32(out + 4, s1); + s2 = + ((u32)Td4[(t2 >> 24) ] << 24) ^ + ((u32)Td4[(t1 >> 16) & 0xff] << 16) ^ + ((u32)Td4[(t0 >> 8) & 0xff] << 8) ^ + ((u32)Td4[(t3 ) & 0xff]) ^ + rk[2]; + PUTU32(out + 8, s2); + s3 = + ((u32)Td4[(t3 >> 24) ] << 24) ^ + ((u32)Td4[(t2 >> 16) & 0xff] << 16) ^ + ((u32)Td4[(t1 >> 8) & 0xff] << 8) ^ + ((u32)Td4[(t0 ) & 0xff]) ^ + rk[3]; + PUTU32(out + 12, s3); +} + +#else /* AES_ASM */ + +static const u8 Te4[256] = { + 0x63U, 0x7cU, 0x77U, 0x7bU, 0xf2U, 0x6bU, 0x6fU, 0xc5U, + 0x30U, 0x01U, 0x67U, 0x2bU, 0xfeU, 0xd7U, 0xabU, 0x76U, + 0xcaU, 0x82U, 0xc9U, 0x7dU, 0xfaU, 0x59U, 0x47U, 0xf0U, + 0xadU, 0xd4U, 0xa2U, 0xafU, 0x9cU, 0xa4U, 0x72U, 0xc0U, + 0xb7U, 0xfdU, 0x93U, 0x26U, 0x36U, 0x3fU, 0xf7U, 0xccU, + 0x34U, 0xa5U, 0xe5U, 0xf1U, 0x71U, 0xd8U, 0x31U, 0x15U, + 0x04U, 0xc7U, 0x23U, 0xc3U, 0x18U, 0x96U, 0x05U, 0x9aU, + 0x07U, 0x12U, 0x80U, 0xe2U, 0xebU, 0x27U, 0xb2U, 0x75U, + 0x09U, 0x83U, 0x2cU, 0x1aU, 0x1bU, 0x6eU, 0x5aU, 0xa0U, + 0x52U, 0x3bU, 0xd6U, 0xb3U, 0x29U, 0xe3U, 0x2fU, 0x84U, + 0x53U, 0xd1U, 0x00U, 0xedU, 0x20U, 0xfcU, 0xb1U, 0x5bU, + 0x6aU, 0xcbU, 0xbeU, 0x39U, 0x4aU, 0x4cU, 0x58U, 0xcfU, + 0xd0U, 0xefU, 0xaaU, 0xfbU, 0x43U, 0x4dU, 0x33U, 0x85U, + 0x45U, 0xf9U, 0x02U, 0x7fU, 0x50U, 0x3cU, 0x9fU, 0xa8U, + 0x51U, 0xa3U, 0x40U, 0x8fU, 0x92U, 0x9dU, 0x38U, 0xf5U, + 0xbcU, 0xb6U, 0xdaU, 0x21U, 0x10U, 0xffU, 0xf3U, 0xd2U, + 0xcdU, 0x0cU, 0x13U, 0xecU, 0x5fU, 0x97U, 0x44U, 0x17U, + 0xc4U, 0xa7U, 0x7eU, 0x3dU, 0x64U, 0x5dU, 0x19U, 0x73U, + 0x60U, 0x81U, 0x4fU, 0xdcU, 0x22U, 0x2aU, 0x90U, 0x88U, + 0x46U, 0xeeU, 0xb8U, 0x14U, 0xdeU, 0x5eU, 0x0bU, 0xdbU, + 0xe0U, 0x32U, 0x3aU, 0x0aU, 0x49U, 0x06U, 0x24U, 0x5cU, + 0xc2U, 0xd3U, 0xacU, 0x62U, 0x91U, 0x95U, 0xe4U, 0x79U, + 0xe7U, 0xc8U, 0x37U, 0x6dU, 0x8dU, 0xd5U, 0x4eU, 0xa9U, + 0x6cU, 0x56U, 0xf4U, 0xeaU, 0x65U, 0x7aU, 0xaeU, 0x08U, + 0xbaU, 0x78U, 0x25U, 0x2eU, 0x1cU, 0xa6U, 0xb4U, 0xc6U, + 0xe8U, 0xddU, 0x74U, 0x1fU, 0x4bU, 0xbdU, 0x8bU, 0x8aU, + 0x70U, 0x3eU, 0xb5U, 0x66U, 0x48U, 0x03U, 0xf6U, 0x0eU, + 0x61U, 0x35U, 0x57U, 0xb9U, 0x86U, 0xc1U, 0x1dU, 0x9eU, + 0xe1U, 0xf8U, 0x98U, 0x11U, 0x69U, 0xd9U, 0x8eU, 0x94U, + 0x9bU, 0x1eU, 0x87U, 0xe9U, 0xceU, 0x55U, 0x28U, 0xdfU, + 0x8cU, 0xa1U, 0x89U, 0x0dU, 0xbfU, 0xe6U, 0x42U, 0x68U, + 0x41U, 0x99U, 0x2dU, 0x0fU, 0xb0U, 0x54U, 0xbbU, 0x16U +}; +static const u32 rcon[] = { + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, + 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +}; + +/** + * Expand the cipher key into the encryption key schedule. + */ +int AES_set_encrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key) +{ + u32 *rk; + int i = 0; + u32 temp; + + if (!userKey || !key) + return -1; + if (bits != 128 && bits != 192 && bits != 256) + return -2; + + rk = key->rd_key; + + if (bits == 128) + key->rounds = 10; + else if (bits == 192) + key->rounds = 12; + else + key->rounds = 14; + + rk[0] = GETU32(userKey ); + rk[1] = GETU32(userKey + 4); + rk[2] = GETU32(userKey + 8); + rk[3] = GETU32(userKey + 12); + if (bits == 128) { + while (1) { + temp = rk[3]; + rk[4] = rk[0] ^ + ((u32)Te4[(temp >> 16) & 0xff] << 24) ^ + ((u32)Te4[(temp >> 8) & 0xff] << 16) ^ + ((u32)Te4[(temp ) & 0xff] << 8) ^ + ((u32)Te4[(temp >> 24) ]) ^ + rcon[i]; + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + if (++i == 10) { + return 0; + } + rk += 4; + } + } + rk[4] = GETU32(userKey + 16); + rk[5] = GETU32(userKey + 20); + if (bits == 192) { + while (1) { + temp = rk[ 5]; + rk[ 6] = rk[ 0] ^ + ((u32)Te4[(temp >> 16) & 0xff] << 24) ^ + ((u32)Te4[(temp >> 8) & 0xff] << 16) ^ + ((u32)Te4[(temp ) & 0xff] << 8) ^ + ((u32)Te4[(temp >> 24) ]) ^ + rcon[i]; + rk[ 7] = rk[ 1] ^ rk[ 6]; + rk[ 8] = rk[ 2] ^ rk[ 7]; + rk[ 9] = rk[ 3] ^ rk[ 8]; + if (++i == 8) { + return 0; + } + rk[10] = rk[ 4] ^ rk[ 9]; + rk[11] = rk[ 5] ^ rk[10]; + rk += 6; + } + } + rk[6] = GETU32(userKey + 24); + rk[7] = GETU32(userKey + 28); + if (bits == 256) { + while (1) { + temp = rk[ 7]; + rk[ 8] = rk[ 0] ^ + ((u32)Te4[(temp >> 16) & 0xff] << 24) ^ + ((u32)Te4[(temp >> 8) & 0xff] << 16) ^ + ((u32)Te4[(temp ) & 0xff] << 8) ^ + ((u32)Te4[(temp >> 24) ]) ^ + rcon[i]; + rk[ 9] = rk[ 1] ^ rk[ 8]; + rk[10] = rk[ 2] ^ rk[ 9]; + rk[11] = rk[ 3] ^ rk[10]; + if (++i == 7) { + return 0; + } + temp = rk[11]; + rk[12] = rk[ 4] ^ + ((u32)Te4[(temp >> 24) ] << 24) ^ + ((u32)Te4[(temp >> 16) & 0xff] << 16) ^ + ((u32)Te4[(temp >> 8) & 0xff] << 8) ^ + ((u32)Te4[(temp ) & 0xff]); + rk[13] = rk[ 5] ^ rk[12]; + rk[14] = rk[ 6] ^ rk[13]; + rk[15] = rk[ 7] ^ rk[14]; + + rk += 8; + } + } + return 0; +} + +/** + * Expand the cipher key into the decryption key schedule. + */ +int AES_set_decrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key) +{ + + u32 *rk; + int i, j, status; + u32 temp; + + /* first, start with an encryption schedule */ + status = AES_set_encrypt_key(userKey, bits, key); + if (status < 0) + return status; + + rk = key->rd_key; + + /* invert the order of the round keys: */ + for (i = 0, j = 4*(key->rounds); i < j; i += 4, j -= 4) { + temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; + temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; + temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; + temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; + } + /* apply the inverse MixColumn transform to all round keys but the first and the last: */ + for (i = 1; i < (key->rounds); i++) { + rk += 4; + for (j = 0; j < 4; j++) { + u32 tp1, tp2, tp4, tp8, tp9, tpb, tpd, tpe, m; + + tp1 = rk[j]; + m = tp1 & 0x80808080; + tp2 = ((tp1 & 0x7f7f7f7f) << 1) ^ + ((m - (m >> 7)) & 0x1b1b1b1b); + m = tp2 & 0x80808080; + tp4 = ((tp2 & 0x7f7f7f7f) << 1) ^ + ((m - (m >> 7)) & 0x1b1b1b1b); + m = tp4 & 0x80808080; + tp8 = ((tp4 & 0x7f7f7f7f) << 1) ^ + ((m - (m >> 7)) & 0x1b1b1b1b); + tp9 = tp8 ^ tp1; + tpb = tp9 ^ tp2; + tpd = tp9 ^ tp4; + tpe = tp8 ^ tp4 ^ tp2; +#if defined(ROTATE) + rk[j] = tpe ^ ROTATE(tpd,16) ^ + ROTATE(tp9,24) ^ ROTATE(tpb,8); +#else + rk[j] = tpe ^ (tpd >> 16) ^ (tpd << 16) ^ + (tp9 >> 8) ^ (tp9 << 24) ^ + (tpb >> 24) ^ (tpb << 8); +#endif + } + } + return 0; +} + +#endif /* AES_ASM */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_ecb.c b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_ecb.c new file mode 100644 index 000000000..29bfc1ad6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_ecb.c @@ -0,0 +1,26 @@ +/* + * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#include +#include "aes_locl.h" + +void AES_ecb_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key, const int enc) +{ + + assert(in && out && key); + assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc)); + + if (AES_ENCRYPT == enc) + AES_encrypt(in, out, key); + else + AES_decrypt(in, out, key); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_ige.c b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_ige.c new file mode 100644 index 000000000..75f796cf3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_ige.c @@ -0,0 +1,284 @@ +/* + * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" + +#include +#include "aes_locl.h" + +#define N_WORDS (AES_BLOCK_SIZE / sizeof(unsigned long)) +typedef struct { + unsigned long data[N_WORDS]; +} aes_block_t; + +/* XXX: probably some better way to do this */ +#if defined(__i386__) || defined(__x86_64__) +# define UNALIGNED_MEMOPS_ARE_FAST 1 +#else +# define UNALIGNED_MEMOPS_ARE_FAST 0 +#endif + +#if UNALIGNED_MEMOPS_ARE_FAST +# define load_block(d, s) (d) = *(const aes_block_t *)(s) +# define store_block(d, s) *(aes_block_t *)(d) = (s) +#else +# define load_block(d, s) memcpy((d).data, (s), AES_BLOCK_SIZE) +# define store_block(d, s) memcpy((d), (s).data, AES_BLOCK_SIZE) +#endif + +/* N.B. The IV for this mode is _twice_ the block size */ + +void AES_ige_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, const int enc) +{ + size_t n; + size_t len = length; + + if (length == 0) + return; + + OPENSSL_assert(in && out && key && ivec); + OPENSSL_assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc)); + OPENSSL_assert((length % AES_BLOCK_SIZE) == 0); + + len = length / AES_BLOCK_SIZE; + + if (AES_ENCRYPT == enc) { + if (in != out && + (UNALIGNED_MEMOPS_ARE_FAST + || ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(long) == + 0)) { + aes_block_t *ivp = (aes_block_t *) ivec; + aes_block_t *iv2p = (aes_block_t *) (ivec + AES_BLOCK_SIZE); + + while (len) { + aes_block_t *inp = (aes_block_t *) in; + aes_block_t *outp = (aes_block_t *) out; + + for (n = 0; n < N_WORDS; ++n) + outp->data[n] = inp->data[n] ^ ivp->data[n]; + AES_encrypt((unsigned char *)outp->data, + (unsigned char *)outp->data, key); + for (n = 0; n < N_WORDS; ++n) + outp->data[n] ^= iv2p->data[n]; + ivp = outp; + iv2p = inp; + --len; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + memcpy(ivec, ivp->data, AES_BLOCK_SIZE); + memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE); + } else { + aes_block_t tmp, tmp2; + aes_block_t iv; + aes_block_t iv2; + + load_block(iv, ivec); + load_block(iv2, ivec + AES_BLOCK_SIZE); + + while (len) { + load_block(tmp, in); + for (n = 0; n < N_WORDS; ++n) + tmp2.data[n] = tmp.data[n] ^ iv.data[n]; + AES_encrypt((unsigned char *)tmp2.data, + (unsigned char *)tmp2.data, key); + for (n = 0; n < N_WORDS; ++n) + tmp2.data[n] ^= iv2.data[n]; + store_block(out, tmp2); + iv = tmp2; + iv2 = tmp; + --len; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + memcpy(ivec, iv.data, AES_BLOCK_SIZE); + memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE); + } + } else { + if (in != out && + (UNALIGNED_MEMOPS_ARE_FAST + || ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(long) == + 0)) { + aes_block_t *ivp = (aes_block_t *) ivec; + aes_block_t *iv2p = (aes_block_t *) (ivec + AES_BLOCK_SIZE); + + while (len) { + aes_block_t tmp; + aes_block_t *inp = (aes_block_t *) in; + aes_block_t *outp = (aes_block_t *) out; + + for (n = 0; n < N_WORDS; ++n) + tmp.data[n] = inp->data[n] ^ iv2p->data[n]; + AES_decrypt((unsigned char *)tmp.data, + (unsigned char *)outp->data, key); + for (n = 0; n < N_WORDS; ++n) + outp->data[n] ^= ivp->data[n]; + ivp = inp; + iv2p = outp; + --len; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + memcpy(ivec, ivp->data, AES_BLOCK_SIZE); + memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE); + } else { + aes_block_t tmp, tmp2; + aes_block_t iv; + aes_block_t iv2; + + load_block(iv, ivec); + load_block(iv2, ivec + AES_BLOCK_SIZE); + + while (len) { + load_block(tmp, in); + tmp2 = tmp; + for (n = 0; n < N_WORDS; ++n) + tmp.data[n] ^= iv2.data[n]; + AES_decrypt((unsigned char *)tmp.data, + (unsigned char *)tmp.data, key); + for (n = 0; n < N_WORDS; ++n) + tmp.data[n] ^= iv.data[n]; + store_block(out, tmp); + iv = tmp2; + iv2 = tmp; + --len; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + memcpy(ivec, iv.data, AES_BLOCK_SIZE); + memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE); + } + } +} + +/* + * Note that its effectively impossible to do biIGE in anything other + * than a single pass, so no provision is made for chaining. + */ + +/* N.B. The IV for this mode is _four times_ the block size */ + +void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + const AES_KEY *key2, const unsigned char *ivec, + const int enc) +{ + size_t n; + size_t len = length; + unsigned char tmp[AES_BLOCK_SIZE]; + unsigned char tmp2[AES_BLOCK_SIZE]; + unsigned char tmp3[AES_BLOCK_SIZE]; + unsigned char prev[AES_BLOCK_SIZE]; + const unsigned char *iv; + const unsigned char *iv2; + + OPENSSL_assert(in && out && key && ivec); + OPENSSL_assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc)); + OPENSSL_assert((length % AES_BLOCK_SIZE) == 0); + + if (AES_ENCRYPT == enc) { + /* + * XXX: Do a separate case for when in != out (strictly should check + * for overlap, too) + */ + + /* First the forward pass */ + iv = ivec; + iv2 = ivec + AES_BLOCK_SIZE; + while (len >= AES_BLOCK_SIZE) { + for (n = 0; n < AES_BLOCK_SIZE; ++n) + out[n] = in[n] ^ iv[n]; + AES_encrypt(out, out, key); + for (n = 0; n < AES_BLOCK_SIZE; ++n) + out[n] ^= iv2[n]; + iv = out; + memcpy(prev, in, AES_BLOCK_SIZE); + iv2 = prev; + len -= AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + + /* And now backwards */ + iv = ivec + AES_BLOCK_SIZE * 2; + iv2 = ivec + AES_BLOCK_SIZE * 3; + len = length; + while (len >= AES_BLOCK_SIZE) { + out -= AES_BLOCK_SIZE; + /* + * XXX: reduce copies by alternating between buffers + */ + memcpy(tmp, out, AES_BLOCK_SIZE); + for (n = 0; n < AES_BLOCK_SIZE; ++n) + out[n] ^= iv[n]; + /* + * hexdump(stdout, "out ^ iv", out, AES_BLOCK_SIZE); + */ + AES_encrypt(out, out, key); + /* + * hexdump(stdout,"enc", out, AES_BLOCK_SIZE); + */ + /* + * hexdump(stdout,"iv2", iv2, AES_BLOCK_SIZE); + */ + for (n = 0; n < AES_BLOCK_SIZE; ++n) + out[n] ^= iv2[n]; + /* + * hexdump(stdout,"out", out, AES_BLOCK_SIZE); + */ + iv = out; + memcpy(prev, tmp, AES_BLOCK_SIZE); + iv2 = prev; + len -= AES_BLOCK_SIZE; + } + } else { + /* First backwards */ + iv = ivec + AES_BLOCK_SIZE * 2; + iv2 = ivec + AES_BLOCK_SIZE * 3; + in += length; + out += length; + while (len >= AES_BLOCK_SIZE) { + in -= AES_BLOCK_SIZE; + out -= AES_BLOCK_SIZE; + memcpy(tmp, in, AES_BLOCK_SIZE); + memcpy(tmp2, in, AES_BLOCK_SIZE); + for (n = 0; n < AES_BLOCK_SIZE; ++n) + tmp[n] ^= iv2[n]; + AES_decrypt(tmp, out, key); + for (n = 0; n < AES_BLOCK_SIZE; ++n) + out[n] ^= iv[n]; + memcpy(tmp3, tmp2, AES_BLOCK_SIZE); + iv = tmp3; + iv2 = out; + len -= AES_BLOCK_SIZE; + } + + /* And now forwards */ + iv = ivec; + iv2 = ivec + AES_BLOCK_SIZE; + len = length; + while (len >= AES_BLOCK_SIZE) { + memcpy(tmp, out, AES_BLOCK_SIZE); + memcpy(tmp2, out, AES_BLOCK_SIZE); + for (n = 0; n < AES_BLOCK_SIZE; ++n) + tmp[n] ^= iv2[n]; + AES_decrypt(tmp, out, key); + for (n = 0; n < AES_BLOCK_SIZE; ++n) + out[n] ^= iv[n]; + memcpy(tmp3, tmp2, AES_BLOCK_SIZE); + iv = tmp3; + iv2 = out; + len -= AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + } +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_locl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_locl.h new file mode 100644 index 000000000..adee29df8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_locl.h @@ -0,0 +1,42 @@ +/* + * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_AES_LOCL_H +# define HEADER_AES_LOCL_H + +# include +# include +# include +# include + +# if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64)) +# define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) +# define GETU32(p) SWAP(*((u32 *)(p))) +# define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); } +# else +# define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) +# define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } +# endif + +# ifdef AES_LONG +typedef unsigned long u32; +# else +typedef unsigned int u32; +# endif +typedef unsigned short u16; +typedef unsigned char u8; + +# define MAXKC (256/32) +# define MAXKB (256/8) +# define MAXNR 14 + +/* This controls loop-unrolling in aes_core.c */ +# undef FULL_UNROLL + +#endif /* !HEADER_AES_LOCL_H */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_misc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_misc.c new file mode 100644 index 000000000..7403c84f8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_misc.c @@ -0,0 +1,21 @@ +/* + * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "aes_locl.h" + +const char *AES_options(void) +{ +#ifdef FULL_UNROLL + return "aes(full)"; +#else + return "aes(partial)"; +#endif +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_ofb.c b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_ofb.c new file mode 100644 index 000000000..215b53858 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_ofb.c @@ -0,0 +1,19 @@ +/* + * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, int *num) +{ + CRYPTO_ofb128_encrypt(in, out, length, key, ivec, num, + (block128_f) AES_encrypt); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_wrap.c b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_wrap.c new file mode 100644 index 000000000..cae0b2122 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_wrap.c @@ -0,0 +1,27 @@ +/* + * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include +#include + +int AES_wrap_key(AES_KEY *key, const unsigned char *iv, + unsigned char *out, + const unsigned char *in, unsigned int inlen) +{ + return CRYPTO_128_wrap(key, iv, out, in, inlen, (block128_f) AES_encrypt); +} + +int AES_unwrap_key(AES_KEY *key, const unsigned char *iv, + unsigned char *out, + const unsigned char *in, unsigned int inlen) +{ + return CRYPTO_128_unwrap(key, iv, out, in, inlen, + (block128_f) AES_decrypt); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_x86core.c b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_x86core.c new file mode 100644 index 000000000..1b660d716 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/aes_x86core.c @@ -0,0 +1,1074 @@ +/* + * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This is experimental x86[_64] derivative. It assumes little-endian + * byte order and expects CPU to sustain unaligned memory references. + * It is used as playground for cache-time attack mitigations and + * serves as reference C implementation for x86[_64] as well as some + * other assembly modules. + */ + +/** + * rijndael-alg-fst.c + * + * @version 3.0 (December 2000) + * + * Optimised ANSI C code for the Rijndael cipher (now AES) + * + * @author Vincent Rijmen + * @author Antoon Bosselaers + * @author Paulo Barreto + * + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include + +#include +#include +#include "aes_locl.h" + +/* + * These two parameters control which table, 256-byte or 2KB, is + * referenced in outer and respectively inner rounds. + */ +#define AES_COMPACT_IN_OUTER_ROUNDS +#ifdef AES_COMPACT_IN_OUTER_ROUNDS +/* AES_COMPACT_IN_OUTER_ROUNDS costs ~30% in performance, while + * adding AES_COMPACT_IN_INNER_ROUNDS reduces benchmark *further* + * by factor of ~2. */ +# undef AES_COMPACT_IN_INNER_ROUNDS +#endif + +#if 1 +static void prefetch256(const void *table) +{ + volatile unsigned long *t=(void *)table,ret; + unsigned long sum; + int i; + + /* 32 is common least cache-line size */ + for (sum=0,i=0;i<256/sizeof(t[0]);i+=32/sizeof(t[0])) sum ^= t[i]; + + ret = sum; +} +#else +# define prefetch256(t) +#endif + +#undef GETU32 +#define GETU32(p) (*((u32*)(p))) + +#if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__) +typedef unsigned __int64 u64; +#define U64(C) C##UI64 +#elif defined(__arch64__) +typedef unsigned long u64; +#define U64(C) C##UL +#else +typedef unsigned long long u64; +#define U64(C) C##ULL +#endif + +#undef ROTATE +#if defined(_MSC_VER) +# define ROTATE(a,n) _lrotl(a,n) +#elif defined(__ICC) +# define ROTATE(a,n) _rotl(a,n) +#elif defined(__GNUC__) && __GNUC__>=2 +# if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__) +# define ROTATE(a,n) ({ register unsigned int ret; \ + asm ( \ + "roll %1,%0" \ + : "=r"(ret) \ + : "I"(n), "0"(a) \ + : "cc"); \ + ret; \ + }) +# endif +#endif +/*- +Te [x] = S [x].[02, 01, 01, 03, 02, 01, 01, 03]; +Te0[x] = S [x].[02, 01, 01, 03]; +Te1[x] = S [x].[03, 02, 01, 01]; +Te2[x] = S [x].[01, 03, 02, 01]; +Te3[x] = S [x].[01, 01, 03, 02]; +*/ +#define Te0 (u32)((u64*)((u8*)Te+0)) +#define Te1 (u32)((u64*)((u8*)Te+3)) +#define Te2 (u32)((u64*)((u8*)Te+2)) +#define Te3 (u32)((u64*)((u8*)Te+1)) +/*- +Td [x] = Si[x].[0e, 09, 0d, 0b, 0e, 09, 0d, 0b]; +Td0[x] = Si[x].[0e, 09, 0d, 0b]; +Td1[x] = Si[x].[0b, 0e, 09, 0d]; +Td2[x] = Si[x].[0d, 0b, 0e, 09]; +Td3[x] = Si[x].[09, 0d, 0b, 0e]; +Td4[x] = Si[x].[01]; +*/ +#define Td0 (u32)((u64*)((u8*)Td+0)) +#define Td1 (u32)((u64*)((u8*)Td+3)) +#define Td2 (u32)((u64*)((u8*)Td+2)) +#define Td3 (u32)((u64*)((u8*)Td+1)) + +static const u64 Te[256] = { + U64(0xa56363c6a56363c6), U64(0x847c7cf8847c7cf8), + U64(0x997777ee997777ee), U64(0x8d7b7bf68d7b7bf6), + U64(0x0df2f2ff0df2f2ff), U64(0xbd6b6bd6bd6b6bd6), + U64(0xb16f6fdeb16f6fde), U64(0x54c5c59154c5c591), + U64(0x5030306050303060), U64(0x0301010203010102), + U64(0xa96767cea96767ce), U64(0x7d2b2b567d2b2b56), + U64(0x19fefee719fefee7), U64(0x62d7d7b562d7d7b5), + U64(0xe6abab4de6abab4d), U64(0x9a7676ec9a7676ec), + U64(0x45caca8f45caca8f), U64(0x9d82821f9d82821f), + U64(0x40c9c98940c9c989), U64(0x877d7dfa877d7dfa), + U64(0x15fafaef15fafaef), U64(0xeb5959b2eb5959b2), + U64(0xc947478ec947478e), U64(0x0bf0f0fb0bf0f0fb), + U64(0xecadad41ecadad41), U64(0x67d4d4b367d4d4b3), + U64(0xfda2a25ffda2a25f), U64(0xeaafaf45eaafaf45), + U64(0xbf9c9c23bf9c9c23), U64(0xf7a4a453f7a4a453), + U64(0x967272e4967272e4), U64(0x5bc0c09b5bc0c09b), + U64(0xc2b7b775c2b7b775), U64(0x1cfdfde11cfdfde1), + U64(0xae93933dae93933d), U64(0x6a26264c6a26264c), + U64(0x5a36366c5a36366c), U64(0x413f3f7e413f3f7e), + U64(0x02f7f7f502f7f7f5), U64(0x4fcccc834fcccc83), + U64(0x5c3434685c343468), U64(0xf4a5a551f4a5a551), + U64(0x34e5e5d134e5e5d1), U64(0x08f1f1f908f1f1f9), + U64(0x937171e2937171e2), U64(0x73d8d8ab73d8d8ab), + U64(0x5331316253313162), U64(0x3f15152a3f15152a), + U64(0x0c0404080c040408), U64(0x52c7c79552c7c795), + U64(0x6523234665232346), U64(0x5ec3c39d5ec3c39d), + U64(0x2818183028181830), U64(0xa1969637a1969637), + U64(0x0f05050a0f05050a), U64(0xb59a9a2fb59a9a2f), + U64(0x0907070e0907070e), U64(0x3612122436121224), + U64(0x9b80801b9b80801b), U64(0x3de2e2df3de2e2df), + U64(0x26ebebcd26ebebcd), U64(0x6927274e6927274e), + U64(0xcdb2b27fcdb2b27f), U64(0x9f7575ea9f7575ea), + U64(0x1b0909121b090912), U64(0x9e83831d9e83831d), + U64(0x742c2c58742c2c58), U64(0x2e1a1a342e1a1a34), + U64(0x2d1b1b362d1b1b36), U64(0xb26e6edcb26e6edc), + U64(0xee5a5ab4ee5a5ab4), U64(0xfba0a05bfba0a05b), + U64(0xf65252a4f65252a4), U64(0x4d3b3b764d3b3b76), + U64(0x61d6d6b761d6d6b7), U64(0xceb3b37dceb3b37d), + U64(0x7b2929527b292952), U64(0x3ee3e3dd3ee3e3dd), + U64(0x712f2f5e712f2f5e), U64(0x9784841397848413), + U64(0xf55353a6f55353a6), U64(0x68d1d1b968d1d1b9), + U64(0x0000000000000000), U64(0x2cededc12cededc1), + U64(0x6020204060202040), U64(0x1ffcfce31ffcfce3), + U64(0xc8b1b179c8b1b179), U64(0xed5b5bb6ed5b5bb6), + U64(0xbe6a6ad4be6a6ad4), U64(0x46cbcb8d46cbcb8d), + U64(0xd9bebe67d9bebe67), U64(0x4b3939724b393972), + U64(0xde4a4a94de4a4a94), U64(0xd44c4c98d44c4c98), + U64(0xe85858b0e85858b0), U64(0x4acfcf854acfcf85), + U64(0x6bd0d0bb6bd0d0bb), U64(0x2aefefc52aefefc5), + U64(0xe5aaaa4fe5aaaa4f), U64(0x16fbfbed16fbfbed), + U64(0xc5434386c5434386), U64(0xd74d4d9ad74d4d9a), + U64(0x5533336655333366), U64(0x9485851194858511), + U64(0xcf45458acf45458a), U64(0x10f9f9e910f9f9e9), + U64(0x0602020406020204), U64(0x817f7ffe817f7ffe), + U64(0xf05050a0f05050a0), U64(0x443c3c78443c3c78), + U64(0xba9f9f25ba9f9f25), U64(0xe3a8a84be3a8a84b), + U64(0xf35151a2f35151a2), U64(0xfea3a35dfea3a35d), + U64(0xc0404080c0404080), U64(0x8a8f8f058a8f8f05), + U64(0xad92923fad92923f), U64(0xbc9d9d21bc9d9d21), + U64(0x4838387048383870), U64(0x04f5f5f104f5f5f1), + U64(0xdfbcbc63dfbcbc63), U64(0xc1b6b677c1b6b677), + U64(0x75dadaaf75dadaaf), U64(0x6321214263212142), + U64(0x3010102030101020), U64(0x1affffe51affffe5), + U64(0x0ef3f3fd0ef3f3fd), U64(0x6dd2d2bf6dd2d2bf), + U64(0x4ccdcd814ccdcd81), U64(0x140c0c18140c0c18), + U64(0x3513132635131326), U64(0x2fececc32fececc3), + U64(0xe15f5fbee15f5fbe), U64(0xa2979735a2979735), + U64(0xcc444488cc444488), U64(0x3917172e3917172e), + U64(0x57c4c49357c4c493), U64(0xf2a7a755f2a7a755), + U64(0x827e7efc827e7efc), U64(0x473d3d7a473d3d7a), + U64(0xac6464c8ac6464c8), U64(0xe75d5dbae75d5dba), + U64(0x2b1919322b191932), U64(0x957373e6957373e6), + U64(0xa06060c0a06060c0), U64(0x9881811998818119), + U64(0xd14f4f9ed14f4f9e), U64(0x7fdcdca37fdcdca3), + U64(0x6622224466222244), U64(0x7e2a2a547e2a2a54), + U64(0xab90903bab90903b), U64(0x8388880b8388880b), + U64(0xca46468cca46468c), U64(0x29eeeec729eeeec7), + U64(0xd3b8b86bd3b8b86b), U64(0x3c1414283c141428), + U64(0x79dedea779dedea7), U64(0xe25e5ebce25e5ebc), + U64(0x1d0b0b161d0b0b16), U64(0x76dbdbad76dbdbad), + U64(0x3be0e0db3be0e0db), U64(0x5632326456323264), + U64(0x4e3a3a744e3a3a74), U64(0x1e0a0a141e0a0a14), + U64(0xdb494992db494992), U64(0x0a06060c0a06060c), + U64(0x6c2424486c242448), U64(0xe45c5cb8e45c5cb8), + U64(0x5dc2c29f5dc2c29f), U64(0x6ed3d3bd6ed3d3bd), + U64(0xefacac43efacac43), U64(0xa66262c4a66262c4), + U64(0xa8919139a8919139), U64(0xa4959531a4959531), + U64(0x37e4e4d337e4e4d3), U64(0x8b7979f28b7979f2), + U64(0x32e7e7d532e7e7d5), U64(0x43c8c88b43c8c88b), + U64(0x5937376e5937376e), U64(0xb76d6ddab76d6dda), + U64(0x8c8d8d018c8d8d01), U64(0x64d5d5b164d5d5b1), + U64(0xd24e4e9cd24e4e9c), U64(0xe0a9a949e0a9a949), + U64(0xb46c6cd8b46c6cd8), U64(0xfa5656acfa5656ac), + U64(0x07f4f4f307f4f4f3), U64(0x25eaeacf25eaeacf), + U64(0xaf6565caaf6565ca), U64(0x8e7a7af48e7a7af4), + U64(0xe9aeae47e9aeae47), U64(0x1808081018080810), + U64(0xd5baba6fd5baba6f), U64(0x887878f0887878f0), + U64(0x6f25254a6f25254a), U64(0x722e2e5c722e2e5c), + U64(0x241c1c38241c1c38), U64(0xf1a6a657f1a6a657), + U64(0xc7b4b473c7b4b473), U64(0x51c6c69751c6c697), + U64(0x23e8e8cb23e8e8cb), U64(0x7cdddda17cdddda1), + U64(0x9c7474e89c7474e8), U64(0x211f1f3e211f1f3e), + U64(0xdd4b4b96dd4b4b96), U64(0xdcbdbd61dcbdbd61), + U64(0x868b8b0d868b8b0d), U64(0x858a8a0f858a8a0f), + U64(0x907070e0907070e0), U64(0x423e3e7c423e3e7c), + U64(0xc4b5b571c4b5b571), U64(0xaa6666ccaa6666cc), + U64(0xd8484890d8484890), U64(0x0503030605030306), + U64(0x01f6f6f701f6f6f7), U64(0x120e0e1c120e0e1c), + U64(0xa36161c2a36161c2), U64(0x5f35356a5f35356a), + U64(0xf95757aef95757ae), U64(0xd0b9b969d0b9b969), + U64(0x9186861791868617), U64(0x58c1c19958c1c199), + U64(0x271d1d3a271d1d3a), U64(0xb99e9e27b99e9e27), + U64(0x38e1e1d938e1e1d9), U64(0x13f8f8eb13f8f8eb), + U64(0xb398982bb398982b), U64(0x3311112233111122), + U64(0xbb6969d2bb6969d2), U64(0x70d9d9a970d9d9a9), + U64(0x898e8e07898e8e07), U64(0xa7949433a7949433), + U64(0xb69b9b2db69b9b2d), U64(0x221e1e3c221e1e3c), + U64(0x9287871592878715), U64(0x20e9e9c920e9e9c9), + U64(0x49cece8749cece87), U64(0xff5555aaff5555aa), + U64(0x7828285078282850), U64(0x7adfdfa57adfdfa5), + U64(0x8f8c8c038f8c8c03), U64(0xf8a1a159f8a1a159), + U64(0x8089890980898909), U64(0x170d0d1a170d0d1a), + U64(0xdabfbf65dabfbf65), U64(0x31e6e6d731e6e6d7), + U64(0xc6424284c6424284), U64(0xb86868d0b86868d0), + U64(0xc3414182c3414182), U64(0xb0999929b0999929), + U64(0x772d2d5a772d2d5a), U64(0x110f0f1e110f0f1e), + U64(0xcbb0b07bcbb0b07b), U64(0xfc5454a8fc5454a8), + U64(0xd6bbbb6dd6bbbb6d), U64(0x3a16162c3a16162c) +}; + +static const u8 Te4[256] = { + 0x63U, 0x7cU, 0x77U, 0x7bU, 0xf2U, 0x6bU, 0x6fU, 0xc5U, + 0x30U, 0x01U, 0x67U, 0x2bU, 0xfeU, 0xd7U, 0xabU, 0x76U, + 0xcaU, 0x82U, 0xc9U, 0x7dU, 0xfaU, 0x59U, 0x47U, 0xf0U, + 0xadU, 0xd4U, 0xa2U, 0xafU, 0x9cU, 0xa4U, 0x72U, 0xc0U, + 0xb7U, 0xfdU, 0x93U, 0x26U, 0x36U, 0x3fU, 0xf7U, 0xccU, + 0x34U, 0xa5U, 0xe5U, 0xf1U, 0x71U, 0xd8U, 0x31U, 0x15U, + 0x04U, 0xc7U, 0x23U, 0xc3U, 0x18U, 0x96U, 0x05U, 0x9aU, + 0x07U, 0x12U, 0x80U, 0xe2U, 0xebU, 0x27U, 0xb2U, 0x75U, + 0x09U, 0x83U, 0x2cU, 0x1aU, 0x1bU, 0x6eU, 0x5aU, 0xa0U, + 0x52U, 0x3bU, 0xd6U, 0xb3U, 0x29U, 0xe3U, 0x2fU, 0x84U, + 0x53U, 0xd1U, 0x00U, 0xedU, 0x20U, 0xfcU, 0xb1U, 0x5bU, + 0x6aU, 0xcbU, 0xbeU, 0x39U, 0x4aU, 0x4cU, 0x58U, 0xcfU, + 0xd0U, 0xefU, 0xaaU, 0xfbU, 0x43U, 0x4dU, 0x33U, 0x85U, + 0x45U, 0xf9U, 0x02U, 0x7fU, 0x50U, 0x3cU, 0x9fU, 0xa8U, + 0x51U, 0xa3U, 0x40U, 0x8fU, 0x92U, 0x9dU, 0x38U, 0xf5U, + 0xbcU, 0xb6U, 0xdaU, 0x21U, 0x10U, 0xffU, 0xf3U, 0xd2U, + 0xcdU, 0x0cU, 0x13U, 0xecU, 0x5fU, 0x97U, 0x44U, 0x17U, + 0xc4U, 0xa7U, 0x7eU, 0x3dU, 0x64U, 0x5dU, 0x19U, 0x73U, + 0x60U, 0x81U, 0x4fU, 0xdcU, 0x22U, 0x2aU, 0x90U, 0x88U, + 0x46U, 0xeeU, 0xb8U, 0x14U, 0xdeU, 0x5eU, 0x0bU, 0xdbU, + 0xe0U, 0x32U, 0x3aU, 0x0aU, 0x49U, 0x06U, 0x24U, 0x5cU, + 0xc2U, 0xd3U, 0xacU, 0x62U, 0x91U, 0x95U, 0xe4U, 0x79U, + 0xe7U, 0xc8U, 0x37U, 0x6dU, 0x8dU, 0xd5U, 0x4eU, 0xa9U, + 0x6cU, 0x56U, 0xf4U, 0xeaU, 0x65U, 0x7aU, 0xaeU, 0x08U, + 0xbaU, 0x78U, 0x25U, 0x2eU, 0x1cU, 0xa6U, 0xb4U, 0xc6U, + 0xe8U, 0xddU, 0x74U, 0x1fU, 0x4bU, 0xbdU, 0x8bU, 0x8aU, + 0x70U, 0x3eU, 0xb5U, 0x66U, 0x48U, 0x03U, 0xf6U, 0x0eU, + 0x61U, 0x35U, 0x57U, 0xb9U, 0x86U, 0xc1U, 0x1dU, 0x9eU, + 0xe1U, 0xf8U, 0x98U, 0x11U, 0x69U, 0xd9U, 0x8eU, 0x94U, + 0x9bU, 0x1eU, 0x87U, 0xe9U, 0xceU, 0x55U, 0x28U, 0xdfU, + 0x8cU, 0xa1U, 0x89U, 0x0dU, 0xbfU, 0xe6U, 0x42U, 0x68U, + 0x41U, 0x99U, 0x2dU, 0x0fU, 0xb0U, 0x54U, 0xbbU, 0x16U +}; + +static const u64 Td[256] = { + U64(0x50a7f45150a7f451), U64(0x5365417e5365417e), + U64(0xc3a4171ac3a4171a), U64(0x965e273a965e273a), + U64(0xcb6bab3bcb6bab3b), U64(0xf1459d1ff1459d1f), + U64(0xab58faacab58faac), U64(0x9303e34b9303e34b), + U64(0x55fa302055fa3020), U64(0xf66d76adf66d76ad), + U64(0x9176cc889176cc88), U64(0x254c02f5254c02f5), + U64(0xfcd7e54ffcd7e54f), U64(0xd7cb2ac5d7cb2ac5), + U64(0x8044352680443526), U64(0x8fa362b58fa362b5), + U64(0x495ab1de495ab1de), U64(0x671bba25671bba25), + U64(0x980eea45980eea45), U64(0xe1c0fe5de1c0fe5d), + U64(0x02752fc302752fc3), U64(0x12f04c8112f04c81), + U64(0xa397468da397468d), U64(0xc6f9d36bc6f9d36b), + U64(0xe75f8f03e75f8f03), U64(0x959c9215959c9215), + U64(0xeb7a6dbfeb7a6dbf), U64(0xda595295da595295), + U64(0x2d83bed42d83bed4), U64(0xd3217458d3217458), + U64(0x2969e0492969e049), U64(0x44c8c98e44c8c98e), + U64(0x6a89c2756a89c275), U64(0x78798ef478798ef4), + U64(0x6b3e58996b3e5899), U64(0xdd71b927dd71b927), + U64(0xb64fe1beb64fe1be), U64(0x17ad88f017ad88f0), + U64(0x66ac20c966ac20c9), U64(0xb43ace7db43ace7d), + U64(0x184adf63184adf63), U64(0x82311ae582311ae5), + U64(0x6033519760335197), U64(0x457f5362457f5362), + U64(0xe07764b1e07764b1), U64(0x84ae6bbb84ae6bbb), + U64(0x1ca081fe1ca081fe), U64(0x942b08f9942b08f9), + U64(0x5868487058684870), U64(0x19fd458f19fd458f), + U64(0x876cde94876cde94), U64(0xb7f87b52b7f87b52), + U64(0x23d373ab23d373ab), U64(0xe2024b72e2024b72), + U64(0x578f1fe3578f1fe3), U64(0x2aab55662aab5566), + U64(0x0728ebb20728ebb2), U64(0x03c2b52f03c2b52f), + U64(0x9a7bc5869a7bc586), U64(0xa50837d3a50837d3), + U64(0xf2872830f2872830), U64(0xb2a5bf23b2a5bf23), + U64(0xba6a0302ba6a0302), U64(0x5c8216ed5c8216ed), + U64(0x2b1ccf8a2b1ccf8a), U64(0x92b479a792b479a7), + U64(0xf0f207f3f0f207f3), U64(0xa1e2694ea1e2694e), + U64(0xcdf4da65cdf4da65), U64(0xd5be0506d5be0506), + U64(0x1f6234d11f6234d1), U64(0x8afea6c48afea6c4), + U64(0x9d532e349d532e34), U64(0xa055f3a2a055f3a2), + U64(0x32e18a0532e18a05), U64(0x75ebf6a475ebf6a4), + U64(0x39ec830b39ec830b), U64(0xaaef6040aaef6040), + U64(0x069f715e069f715e), U64(0x51106ebd51106ebd), + U64(0xf98a213ef98a213e), U64(0x3d06dd963d06dd96), + U64(0xae053eddae053edd), U64(0x46bde64d46bde64d), + U64(0xb58d5491b58d5491), U64(0x055dc471055dc471), + U64(0x6fd406046fd40604), U64(0xff155060ff155060), + U64(0x24fb981924fb9819), U64(0x97e9bdd697e9bdd6), + U64(0xcc434089cc434089), U64(0x779ed967779ed967), + U64(0xbd42e8b0bd42e8b0), U64(0x888b8907888b8907), + U64(0x385b19e7385b19e7), U64(0xdbeec879dbeec879), + U64(0x470a7ca1470a7ca1), U64(0xe90f427ce90f427c), + U64(0xc91e84f8c91e84f8), U64(0x0000000000000000), + U64(0x8386800983868009), U64(0x48ed2b3248ed2b32), + U64(0xac70111eac70111e), U64(0x4e725a6c4e725a6c), + U64(0xfbff0efdfbff0efd), U64(0x5638850f5638850f), + U64(0x1ed5ae3d1ed5ae3d), U64(0x27392d3627392d36), + U64(0x64d90f0a64d90f0a), U64(0x21a65c6821a65c68), + U64(0xd1545b9bd1545b9b), U64(0x3a2e36243a2e3624), + U64(0xb1670a0cb1670a0c), U64(0x0fe757930fe75793), + U64(0xd296eeb4d296eeb4), U64(0x9e919b1b9e919b1b), + U64(0x4fc5c0804fc5c080), U64(0xa220dc61a220dc61), + U64(0x694b775a694b775a), U64(0x161a121c161a121c), + U64(0x0aba93e20aba93e2), U64(0xe52aa0c0e52aa0c0), + U64(0x43e0223c43e0223c), U64(0x1d171b121d171b12), + U64(0x0b0d090e0b0d090e), U64(0xadc78bf2adc78bf2), + U64(0xb9a8b62db9a8b62d), U64(0xc8a91e14c8a91e14), + U64(0x8519f1578519f157), U64(0x4c0775af4c0775af), + U64(0xbbdd99eebbdd99ee), U64(0xfd607fa3fd607fa3), + U64(0x9f2601f79f2601f7), U64(0xbcf5725cbcf5725c), + U64(0xc53b6644c53b6644), U64(0x347efb5b347efb5b), + U64(0x7629438b7629438b), U64(0xdcc623cbdcc623cb), + U64(0x68fcedb668fcedb6), U64(0x63f1e4b863f1e4b8), + U64(0xcadc31d7cadc31d7), U64(0x1085634210856342), + U64(0x4022971340229713), U64(0x2011c6842011c684), + U64(0x7d244a857d244a85), U64(0xf83dbbd2f83dbbd2), + U64(0x1132f9ae1132f9ae), U64(0x6da129c76da129c7), + U64(0x4b2f9e1d4b2f9e1d), U64(0xf330b2dcf330b2dc), + U64(0xec52860dec52860d), U64(0xd0e3c177d0e3c177), + U64(0x6c16b32b6c16b32b), U64(0x99b970a999b970a9), + U64(0xfa489411fa489411), U64(0x2264e9472264e947), + U64(0xc48cfca8c48cfca8), U64(0x1a3ff0a01a3ff0a0), + U64(0xd82c7d56d82c7d56), U64(0xef903322ef903322), + U64(0xc74e4987c74e4987), U64(0xc1d138d9c1d138d9), + U64(0xfea2ca8cfea2ca8c), U64(0x360bd498360bd498), + U64(0xcf81f5a6cf81f5a6), U64(0x28de7aa528de7aa5), + U64(0x268eb7da268eb7da), U64(0xa4bfad3fa4bfad3f), + U64(0xe49d3a2ce49d3a2c), U64(0x0d9278500d927850), + U64(0x9bcc5f6a9bcc5f6a), U64(0x62467e5462467e54), + U64(0xc2138df6c2138df6), U64(0xe8b8d890e8b8d890), + U64(0x5ef7392e5ef7392e), U64(0xf5afc382f5afc382), + U64(0xbe805d9fbe805d9f), U64(0x7c93d0697c93d069), + U64(0xa92dd56fa92dd56f), U64(0xb31225cfb31225cf), + U64(0x3b99acc83b99acc8), U64(0xa77d1810a77d1810), + U64(0x6e639ce86e639ce8), U64(0x7bbb3bdb7bbb3bdb), + U64(0x097826cd097826cd), U64(0xf418596ef418596e), + U64(0x01b79aec01b79aec), U64(0xa89a4f83a89a4f83), + U64(0x656e95e6656e95e6), U64(0x7ee6ffaa7ee6ffaa), + U64(0x08cfbc2108cfbc21), U64(0xe6e815efe6e815ef), + U64(0xd99be7bad99be7ba), U64(0xce366f4ace366f4a), + U64(0xd4099fead4099fea), U64(0xd67cb029d67cb029), + U64(0xafb2a431afb2a431), U64(0x31233f2a31233f2a), + U64(0x3094a5c63094a5c6), U64(0xc066a235c066a235), + U64(0x37bc4e7437bc4e74), U64(0xa6ca82fca6ca82fc), + U64(0xb0d090e0b0d090e0), U64(0x15d8a73315d8a733), + U64(0x4a9804f14a9804f1), U64(0xf7daec41f7daec41), + U64(0x0e50cd7f0e50cd7f), U64(0x2ff691172ff69117), + U64(0x8dd64d768dd64d76), U64(0x4db0ef434db0ef43), + U64(0x544daacc544daacc), U64(0xdf0496e4df0496e4), + U64(0xe3b5d19ee3b5d19e), U64(0x1b886a4c1b886a4c), + U64(0xb81f2cc1b81f2cc1), U64(0x7f5165467f516546), + U64(0x04ea5e9d04ea5e9d), U64(0x5d358c015d358c01), + U64(0x737487fa737487fa), U64(0x2e410bfb2e410bfb), + U64(0x5a1d67b35a1d67b3), U64(0x52d2db9252d2db92), + U64(0x335610e9335610e9), U64(0x1347d66d1347d66d), + U64(0x8c61d79a8c61d79a), U64(0x7a0ca1377a0ca137), + U64(0x8e14f8598e14f859), U64(0x893c13eb893c13eb), + U64(0xee27a9ceee27a9ce), U64(0x35c961b735c961b7), + U64(0xede51ce1ede51ce1), U64(0x3cb1477a3cb1477a), + U64(0x59dfd29c59dfd29c), U64(0x3f73f2553f73f255), + U64(0x79ce141879ce1418), U64(0xbf37c773bf37c773), + U64(0xeacdf753eacdf753), U64(0x5baafd5f5baafd5f), + U64(0x146f3ddf146f3ddf), U64(0x86db447886db4478), + U64(0x81f3afca81f3afca), U64(0x3ec468b93ec468b9), + U64(0x2c3424382c342438), U64(0x5f40a3c25f40a3c2), + U64(0x72c31d1672c31d16), U64(0x0c25e2bc0c25e2bc), + U64(0x8b493c288b493c28), U64(0x41950dff41950dff), + U64(0x7101a8397101a839), U64(0xdeb30c08deb30c08), + U64(0x9ce4b4d89ce4b4d8), U64(0x90c1566490c15664), + U64(0x6184cb7b6184cb7b), U64(0x70b632d570b632d5), + U64(0x745c6c48745c6c48), U64(0x4257b8d04257b8d0) +}; +static const u8 Td4[256] = { + 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U, + 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU, + 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U, + 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU, + 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU, + 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU, + 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U, + 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U, + 0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U, + 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U, + 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU, + 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U, + 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU, + 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U, + 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U, + 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU, + 0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU, + 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U, + 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U, + 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU, + 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U, + 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU, + 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U, + 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U, + 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U, + 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU, + 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU, + 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU, + 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U, + 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U, + 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, + 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU +}; + +static const u32 rcon[] = { + 0x00000001U, 0x00000002U, 0x00000004U, 0x00000008U, + 0x00000010U, 0x00000020U, 0x00000040U, 0x00000080U, + 0x0000001bU, 0x00000036U, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +}; + +/** + * Expand the cipher key into the encryption key schedule. + */ +int AES_set_encrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key) +{ + + u32 *rk; + int i = 0; + u32 temp; + + if (!userKey || !key) + return -1; + if (bits != 128 && bits != 192 && bits != 256) + return -2; + + rk = key->rd_key; + + if (bits==128) + key->rounds = 10; + else if (bits==192) + key->rounds = 12; + else + key->rounds = 14; + + rk[0] = GETU32(userKey ); + rk[1] = GETU32(userKey + 4); + rk[2] = GETU32(userKey + 8); + rk[3] = GETU32(userKey + 12); + if (bits == 128) { + while (1) { + temp = rk[3]; + rk[4] = rk[0] ^ + ((u32)Te4[(temp >> 8) & 0xff] ) ^ + ((u32)Te4[(temp >> 16) & 0xff] << 8) ^ + ((u32)Te4[(temp >> 24) ] << 16) ^ + ((u32)Te4[(temp ) & 0xff] << 24) ^ + rcon[i]; + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + if (++i == 10) { + return 0; + } + rk += 4; + } + } + rk[4] = GETU32(userKey + 16); + rk[5] = GETU32(userKey + 20); + if (bits == 192) { + while (1) { + temp = rk[ 5]; + rk[ 6] = rk[ 0] ^ + ((u32)Te4[(temp >> 8) & 0xff] ) ^ + ((u32)Te4[(temp >> 16) & 0xff] << 8) ^ + ((u32)Te4[(temp >> 24) ] << 16) ^ + ((u32)Te4[(temp ) & 0xff] << 24) ^ + rcon[i]; + rk[ 7] = rk[ 1] ^ rk[ 6]; + rk[ 8] = rk[ 2] ^ rk[ 7]; + rk[ 9] = rk[ 3] ^ rk[ 8]; + if (++i == 8) { + return 0; + } + rk[10] = rk[ 4] ^ rk[ 9]; + rk[11] = rk[ 5] ^ rk[10]; + rk += 6; + } + } + rk[6] = GETU32(userKey + 24); + rk[7] = GETU32(userKey + 28); + if (bits == 256) { + while (1) { + temp = rk[ 7]; + rk[ 8] = rk[ 0] ^ + ((u32)Te4[(temp >> 8) & 0xff] ) ^ + ((u32)Te4[(temp >> 16) & 0xff] << 8) ^ + ((u32)Te4[(temp >> 24) ] << 16) ^ + ((u32)Te4[(temp ) & 0xff] << 24) ^ + rcon[i]; + rk[ 9] = rk[ 1] ^ rk[ 8]; + rk[10] = rk[ 2] ^ rk[ 9]; + rk[11] = rk[ 3] ^ rk[10]; + if (++i == 7) { + return 0; + } + temp = rk[11]; + rk[12] = rk[ 4] ^ + ((u32)Te4[(temp ) & 0xff] ) ^ + ((u32)Te4[(temp >> 8) & 0xff] << 8) ^ + ((u32)Te4[(temp >> 16) & 0xff] << 16) ^ + ((u32)Te4[(temp >> 24) ] << 24); + rk[13] = rk[ 5] ^ rk[12]; + rk[14] = rk[ 6] ^ rk[13]; + rk[15] = rk[ 7] ^ rk[14]; + + rk += 8; + } + } + return 0; +} + +/** + * Expand the cipher key into the decryption key schedule. + */ +int AES_set_decrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key) +{ + + u32 *rk; + int i, j, status; + u32 temp; + + /* first, start with an encryption schedule */ + status = AES_set_encrypt_key(userKey, bits, key); + if (status < 0) + return status; + + rk = key->rd_key; + + /* invert the order of the round keys: */ + for (i = 0, j = 4*(key->rounds); i < j; i += 4, j -= 4) { + temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; + temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; + temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; + temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; + } + /* apply the inverse MixColumn transform to all round keys but the first and the last: */ + for (i = 1; i < (key->rounds); i++) { + rk += 4; +#if 1 + for (j = 0; j < 4; j++) { + u32 tp1, tp2, tp4, tp8, tp9, tpb, tpd, tpe, m; + + tp1 = rk[j]; + m = tp1 & 0x80808080; + tp2 = ((tp1 & 0x7f7f7f7f) << 1) ^ + ((m - (m >> 7)) & 0x1b1b1b1b); + m = tp2 & 0x80808080; + tp4 = ((tp2 & 0x7f7f7f7f) << 1) ^ + ((m - (m >> 7)) & 0x1b1b1b1b); + m = tp4 & 0x80808080; + tp8 = ((tp4 & 0x7f7f7f7f) << 1) ^ + ((m - (m >> 7)) & 0x1b1b1b1b); + tp9 = tp8 ^ tp1; + tpb = tp9 ^ tp2; + tpd = tp9 ^ tp4; + tpe = tp8 ^ tp4 ^ tp2; +#if defined(ROTATE) + rk[j] = tpe ^ ROTATE(tpd,16) ^ + ROTATE(tp9,8) ^ ROTATE(tpb,24); +#else + rk[j] = tpe ^ (tpd >> 16) ^ (tpd << 16) ^ + (tp9 >> 24) ^ (tp9 << 8) ^ + (tpb >> 8) ^ (tpb << 24); +#endif + } +#else + rk[0] = + Td0[Te2[(rk[0] ) & 0xff] & 0xff] ^ + Td1[Te2[(rk[0] >> 8) & 0xff] & 0xff] ^ + Td2[Te2[(rk[0] >> 16) & 0xff] & 0xff] ^ + Td3[Te2[(rk[0] >> 24) ] & 0xff]; + rk[1] = + Td0[Te2[(rk[1] ) & 0xff] & 0xff] ^ + Td1[Te2[(rk[1] >> 8) & 0xff] & 0xff] ^ + Td2[Te2[(rk[1] >> 16) & 0xff] & 0xff] ^ + Td3[Te2[(rk[1] >> 24) ] & 0xff]; + rk[2] = + Td0[Te2[(rk[2] ) & 0xff] & 0xff] ^ + Td1[Te2[(rk[2] >> 8) & 0xff] & 0xff] ^ + Td2[Te2[(rk[2] >> 16) & 0xff] & 0xff] ^ + Td3[Te2[(rk[2] >> 24) ] & 0xff]; + rk[3] = + Td0[Te2[(rk[3] ) & 0xff] & 0xff] ^ + Td1[Te2[(rk[3] >> 8) & 0xff] & 0xff] ^ + Td2[Te2[(rk[3] >> 16) & 0xff] & 0xff] ^ + Td3[Te2[(rk[3] >> 24) ] & 0xff]; +#endif + } + return 0; +} + +/* + * Encrypt a single block + * in and out can overlap + */ +void AES_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key) +{ + + const u32 *rk; + u32 s0, s1, s2, s3, t[4]; + int r; + + assert(in && out && key); + rk = key->rd_key; + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(in ) ^ rk[0]; + s1 = GETU32(in + 4) ^ rk[1]; + s2 = GETU32(in + 8) ^ rk[2]; + s3 = GETU32(in + 12) ^ rk[3]; + +#if defined(AES_COMPACT_IN_OUTER_ROUNDS) + prefetch256(Te4); + + t[0] = (u32)Te4[(s0 ) & 0xff] ^ + (u32)Te4[(s1 >> 8) & 0xff] << 8 ^ + (u32)Te4[(s2 >> 16) & 0xff] << 16 ^ + (u32)Te4[(s3 >> 24) ] << 24; + t[1] = (u32)Te4[(s1 ) & 0xff] ^ + (u32)Te4[(s2 >> 8) & 0xff] << 8 ^ + (u32)Te4[(s3 >> 16) & 0xff] << 16 ^ + (u32)Te4[(s0 >> 24) ] << 24; + t[2] = (u32)Te4[(s2 ) & 0xff] ^ + (u32)Te4[(s3 >> 8) & 0xff] << 8 ^ + (u32)Te4[(s0 >> 16) & 0xff] << 16 ^ + (u32)Te4[(s1 >> 24) ] << 24; + t[3] = (u32)Te4[(s3 ) & 0xff] ^ + (u32)Te4[(s0 >> 8) & 0xff] << 8 ^ + (u32)Te4[(s1 >> 16) & 0xff] << 16 ^ + (u32)Te4[(s2 >> 24) ] << 24; + + /* now do the linear transform using words */ + { int i; + u32 r0, r1, r2; + + for (i = 0; i < 4; i++) { + r0 = t[i]; + r1 = r0 & 0x80808080; + r2 = ((r0 & 0x7f7f7f7f) << 1) ^ + ((r1 - (r1 >> 7)) & 0x1b1b1b1b); +#if defined(ROTATE) + t[i] = r2 ^ ROTATE(r2,24) ^ ROTATE(r0,24) ^ + ROTATE(r0,16) ^ ROTATE(r0,8); +#else + t[i] = r2 ^ ((r2 ^ r0) << 24) ^ ((r2 ^ r0) >> 8) ^ + (r0 << 16) ^ (r0 >> 16) ^ + (r0 << 8) ^ (r0 >> 24); +#endif + t[i] ^= rk[4+i]; + } + } +#else + t[0] = Te0[(s0 ) & 0xff] ^ + Te1[(s1 >> 8) & 0xff] ^ + Te2[(s2 >> 16) & 0xff] ^ + Te3[(s3 >> 24) ] ^ + rk[4]; + t[1] = Te0[(s1 ) & 0xff] ^ + Te1[(s2 >> 8) & 0xff] ^ + Te2[(s3 >> 16) & 0xff] ^ + Te3[(s0 >> 24) ] ^ + rk[5]; + t[2] = Te0[(s2 ) & 0xff] ^ + Te1[(s3 >> 8) & 0xff] ^ + Te2[(s0 >> 16) & 0xff] ^ + Te3[(s1 >> 24) ] ^ + rk[6]; + t[3] = Te0[(s3 ) & 0xff] ^ + Te1[(s0 >> 8) & 0xff] ^ + Te2[(s1 >> 16) & 0xff] ^ + Te3[(s2 >> 24) ] ^ + rk[7]; +#endif + s0 = t[0]; s1 = t[1]; s2 = t[2]; s3 = t[3]; + + /* + * Nr - 2 full rounds: + */ + for (rk+=8,r=key->rounds-2; r>0; rk+=4,r--) { +#if defined(AES_COMPACT_IN_INNER_ROUNDS) + t[0] = (u32)Te4[(s0 ) & 0xff] ^ + (u32)Te4[(s1 >> 8) & 0xff] << 8 ^ + (u32)Te4[(s2 >> 16) & 0xff] << 16 ^ + (u32)Te4[(s3 >> 24) ] << 24; + t[1] = (u32)Te4[(s1 ) & 0xff] ^ + (u32)Te4[(s2 >> 8) & 0xff] << 8 ^ + (u32)Te4[(s3 >> 16) & 0xff] << 16 ^ + (u32)Te4[(s0 >> 24) ] << 24; + t[2] = (u32)Te4[(s2 ) & 0xff] ^ + (u32)Te4[(s3 >> 8) & 0xff] << 8 ^ + (u32)Te4[(s0 >> 16) & 0xff] << 16 ^ + (u32)Te4[(s1 >> 24) ] << 24; + t[3] = (u32)Te4[(s3 ) & 0xff] ^ + (u32)Te4[(s0 >> 8) & 0xff] << 8 ^ + (u32)Te4[(s1 >> 16) & 0xff] << 16 ^ + (u32)Te4[(s2 >> 24) ] << 24; + + /* now do the linear transform using words */ + { + int i; + u32 r0, r1, r2; + + for (i = 0; i < 4; i++) { + r0 = t[i]; + r1 = r0 & 0x80808080; + r2 = ((r0 & 0x7f7f7f7f) << 1) ^ + ((r1 - (r1 >> 7)) & 0x1b1b1b1b); +#if defined(ROTATE) + t[i] = r2 ^ ROTATE(r2,24) ^ ROTATE(r0,24) ^ + ROTATE(r0,16) ^ ROTATE(r0,8); +#else + t[i] = r2 ^ ((r2 ^ r0) << 24) ^ ((r2 ^ r0) >> 8) ^ + (r0 << 16) ^ (r0 >> 16) ^ + (r0 << 8) ^ (r0 >> 24); +#endif + t[i] ^= rk[i]; + } + } +#else + t[0] = Te0[(s0 ) & 0xff] ^ + Te1[(s1 >> 8) & 0xff] ^ + Te2[(s2 >> 16) & 0xff] ^ + Te3[(s3 >> 24) ] ^ + rk[0]; + t[1] = Te0[(s1 ) & 0xff] ^ + Te1[(s2 >> 8) & 0xff] ^ + Te2[(s3 >> 16) & 0xff] ^ + Te3[(s0 >> 24) ] ^ + rk[1]; + t[2] = Te0[(s2 ) & 0xff] ^ + Te1[(s3 >> 8) & 0xff] ^ + Te2[(s0 >> 16) & 0xff] ^ + Te3[(s1 >> 24) ] ^ + rk[2]; + t[3] = Te0[(s3 ) & 0xff] ^ + Te1[(s0 >> 8) & 0xff] ^ + Te2[(s1 >> 16) & 0xff] ^ + Te3[(s2 >> 24) ] ^ + rk[3]; +#endif + s0 = t[0]; s1 = t[1]; s2 = t[2]; s3 = t[3]; + } + /* + * apply last round and + * map cipher state to byte array block: + */ +#if defined(AES_COMPACT_IN_OUTER_ROUNDS) + prefetch256(Te4); + + *(u32*)(out+0) = + (u32)Te4[(s0 ) & 0xff] ^ + (u32)Te4[(s1 >> 8) & 0xff] << 8 ^ + (u32)Te4[(s2 >> 16) & 0xff] << 16 ^ + (u32)Te4[(s3 >> 24) ] << 24 ^ + rk[0]; + *(u32*)(out+4) = + (u32)Te4[(s1 ) & 0xff] ^ + (u32)Te4[(s2 >> 8) & 0xff] << 8 ^ + (u32)Te4[(s3 >> 16) & 0xff] << 16 ^ + (u32)Te4[(s0 >> 24) ] << 24 ^ + rk[1]; + *(u32*)(out+8) = + (u32)Te4[(s2 ) & 0xff] ^ + (u32)Te4[(s3 >> 8) & 0xff] << 8 ^ + (u32)Te4[(s0 >> 16) & 0xff] << 16 ^ + (u32)Te4[(s1 >> 24) ] << 24 ^ + rk[2]; + *(u32*)(out+12) = + (u32)Te4[(s3 ) & 0xff] ^ + (u32)Te4[(s0 >> 8) & 0xff] << 8 ^ + (u32)Te4[(s1 >> 16) & 0xff] << 16 ^ + (u32)Te4[(s2 >> 24) ] << 24 ^ + rk[3]; +#else + *(u32*)(out+0) = + (Te2[(s0 ) & 0xff] & 0x000000ffU) ^ + (Te3[(s1 >> 8) & 0xff] & 0x0000ff00U) ^ + (Te0[(s2 >> 16) & 0xff] & 0x00ff0000U) ^ + (Te1[(s3 >> 24) ] & 0xff000000U) ^ + rk[0]; + *(u32*)(out+4) = + (Te2[(s1 ) & 0xff] & 0x000000ffU) ^ + (Te3[(s2 >> 8) & 0xff] & 0x0000ff00U) ^ + (Te0[(s3 >> 16) & 0xff] & 0x00ff0000U) ^ + (Te1[(s0 >> 24) ] & 0xff000000U) ^ + rk[1]; + *(u32*)(out+8) = + (Te2[(s2 ) & 0xff] & 0x000000ffU) ^ + (Te3[(s3 >> 8) & 0xff] & 0x0000ff00U) ^ + (Te0[(s0 >> 16) & 0xff] & 0x00ff0000U) ^ + (Te1[(s1 >> 24) ] & 0xff000000U) ^ + rk[2]; + *(u32*)(out+12) = + (Te2[(s3 ) & 0xff] & 0x000000ffU) ^ + (Te3[(s0 >> 8) & 0xff] & 0x0000ff00U) ^ + (Te0[(s1 >> 16) & 0xff] & 0x00ff0000U) ^ + (Te1[(s2 >> 24) ] & 0xff000000U) ^ + rk[3]; +#endif +} + +/* + * Decrypt a single block + * in and out can overlap + */ +void AES_decrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key) +{ + + const u32 *rk; + u32 s0, s1, s2, s3, t[4]; + int r; + + assert(in && out && key); + rk = key->rd_key; + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(in ) ^ rk[0]; + s1 = GETU32(in + 4) ^ rk[1]; + s2 = GETU32(in + 8) ^ rk[2]; + s3 = GETU32(in + 12) ^ rk[3]; + +#if defined(AES_COMPACT_IN_OUTER_ROUNDS) + prefetch256(Td4); + + t[0] = (u32)Td4[(s0 ) & 0xff] ^ + (u32)Td4[(s3 >> 8) & 0xff] << 8 ^ + (u32)Td4[(s2 >> 16) & 0xff] << 16 ^ + (u32)Td4[(s1 >> 24) ] << 24; + t[1] = (u32)Td4[(s1 ) & 0xff] ^ + (u32)Td4[(s0 >> 8) & 0xff] << 8 ^ + (u32)Td4[(s3 >> 16) & 0xff] << 16 ^ + (u32)Td4[(s2 >> 24) ] << 24; + t[2] = (u32)Td4[(s2 ) & 0xff] ^ + (u32)Td4[(s1 >> 8) & 0xff] << 8 ^ + (u32)Td4[(s0 >> 16) & 0xff] << 16 ^ + (u32)Td4[(s3 >> 24) ] << 24; + t[3] = (u32)Td4[(s3 ) & 0xff] ^ + (u32)Td4[(s2 >> 8) & 0xff] << 8 ^ + (u32)Td4[(s1 >> 16) & 0xff] << 16 ^ + (u32)Td4[(s0 >> 24) ] << 24; + + /* now do the linear transform using words */ + { + int i; + u32 tp1, tp2, tp4, tp8, tp9, tpb, tpd, tpe, m; + + for (i = 0; i < 4; i++) { + tp1 = t[i]; + m = tp1 & 0x80808080; + tp2 = ((tp1 & 0x7f7f7f7f) << 1) ^ + ((m - (m >> 7)) & 0x1b1b1b1b); + m = tp2 & 0x80808080; + tp4 = ((tp2 & 0x7f7f7f7f) << 1) ^ + ((m - (m >> 7)) & 0x1b1b1b1b); + m = tp4 & 0x80808080; + tp8 = ((tp4 & 0x7f7f7f7f) << 1) ^ + ((m - (m >> 7)) & 0x1b1b1b1b); + tp9 = tp8 ^ tp1; + tpb = tp9 ^ tp2; + tpd = tp9 ^ tp4; + tpe = tp8 ^ tp4 ^ tp2; +#if defined(ROTATE) + t[i] = tpe ^ ROTATE(tpd,16) ^ + ROTATE(tp9,8) ^ ROTATE(tpb,24); +#else + t[i] = tpe ^ (tpd >> 16) ^ (tpd << 16) ^ + (tp9 >> 24) ^ (tp9 << 8) ^ + (tpb >> 8) ^ (tpb << 24); +#endif + t[i] ^= rk[4+i]; + } + } +#else + t[0] = Td0[(s0 ) & 0xff] ^ + Td1[(s3 >> 8) & 0xff] ^ + Td2[(s2 >> 16) & 0xff] ^ + Td3[(s1 >> 24) ] ^ + rk[4]; + t[1] = Td0[(s1 ) & 0xff] ^ + Td1[(s0 >> 8) & 0xff] ^ + Td2[(s3 >> 16) & 0xff] ^ + Td3[(s2 >> 24) ] ^ + rk[5]; + t[2] = Td0[(s2 ) & 0xff] ^ + Td1[(s1 >> 8) & 0xff] ^ + Td2[(s0 >> 16) & 0xff] ^ + Td3[(s3 >> 24) ] ^ + rk[6]; + t[3] = Td0[(s3 ) & 0xff] ^ + Td1[(s2 >> 8) & 0xff] ^ + Td2[(s1 >> 16) & 0xff] ^ + Td3[(s0 >> 24) ] ^ + rk[7]; +#endif + s0 = t[0]; s1 = t[1]; s2 = t[2]; s3 = t[3]; + + /* + * Nr - 2 full rounds: + */ + for (rk+=8,r=key->rounds-2; r>0; rk+=4,r--) { +#if defined(AES_COMPACT_IN_INNER_ROUNDS) + t[0] = (u32)Td4[(s0 ) & 0xff] ^ + (u32)Td4[(s3 >> 8) & 0xff] << 8 ^ + (u32)Td4[(s2 >> 16) & 0xff] << 16 ^ + (u32)Td4[(s1 >> 24) ] << 24; + t[1] = (u32)Td4[(s1 ) & 0xff] ^ + (u32)Td4[(s0 >> 8) & 0xff] << 8 ^ + (u32)Td4[(s3 >> 16) & 0xff] << 16 ^ + (u32)Td4[(s2 >> 24) ] << 24; + t[2] = (u32)Td4[(s2 ) & 0xff] ^ + (u32)Td4[(s1 >> 8) & 0xff] << 8 ^ + (u32)Td4[(s0 >> 16) & 0xff] << 16 ^ + (u32)Td4[(s3 >> 24) ] << 24; + t[3] = (u32)Td4[(s3 ) & 0xff] ^ + (u32)Td4[(s2 >> 8) & 0xff] << 8 ^ + (u32)Td4[(s1 >> 16) & 0xff] << 16 ^ + (u32)Td4[(s0 >> 24) ] << 24; + + /* now do the linear transform using words */ + { + int i; + u32 tp1, tp2, tp4, tp8, tp9, tpb, tpd, tpe, m; + + for (i = 0; i < 4; i++) { + tp1 = t[i]; + m = tp1 & 0x80808080; + tp2 = ((tp1 & 0x7f7f7f7f) << 1) ^ + ((m - (m >> 7)) & 0x1b1b1b1b); + m = tp2 & 0x80808080; + tp4 = ((tp2 & 0x7f7f7f7f) << 1) ^ + ((m - (m >> 7)) & 0x1b1b1b1b); + m = tp4 & 0x80808080; + tp8 = ((tp4 & 0x7f7f7f7f) << 1) ^ + ((m - (m >> 7)) & 0x1b1b1b1b); + tp9 = tp8 ^ tp1; + tpb = tp9 ^ tp2; + tpd = tp9 ^ tp4; + tpe = tp8 ^ tp4 ^ tp2; +#if defined(ROTATE) + t[i] = tpe ^ ROTATE(tpd,16) ^ + ROTATE(tp9,8) ^ ROTATE(tpb,24); +#else + t[i] = tpe ^ (tpd >> 16) ^ (tpd << 16) ^ + (tp9 >> 24) ^ (tp9 << 8) ^ + (tpb >> 8) ^ (tpb << 24); +#endif + t[i] ^= rk[i]; + } + } +#else + t[0] = Td0[(s0 ) & 0xff] ^ + Td1[(s3 >> 8) & 0xff] ^ + Td2[(s2 >> 16) & 0xff] ^ + Td3[(s1 >> 24) ] ^ + rk[0]; + t[1] = Td0[(s1 ) & 0xff] ^ + Td1[(s0 >> 8) & 0xff] ^ + Td2[(s3 >> 16) & 0xff] ^ + Td3[(s2 >> 24) ] ^ + rk[1]; + t[2] = Td0[(s2 ) & 0xff] ^ + Td1[(s1 >> 8) & 0xff] ^ + Td2[(s0 >> 16) & 0xff] ^ + Td3[(s3 >> 24) ] ^ + rk[2]; + t[3] = Td0[(s3 ) & 0xff] ^ + Td1[(s2 >> 8) & 0xff] ^ + Td2[(s1 >> 16) & 0xff] ^ + Td3[(s0 >> 24) ] ^ + rk[3]; +#endif + s0 = t[0]; s1 = t[1]; s2 = t[2]; s3 = t[3]; + } + /* + * apply last round and + * map cipher state to byte array block: + */ + prefetch256(Td4); + + *(u32*)(out+0) = + ((u32)Td4[(s0 ) & 0xff]) ^ + ((u32)Td4[(s3 >> 8) & 0xff] << 8) ^ + ((u32)Td4[(s2 >> 16) & 0xff] << 16) ^ + ((u32)Td4[(s1 >> 24) ] << 24) ^ + rk[0]; + *(u32*)(out+4) = + ((u32)Td4[(s1 ) & 0xff]) ^ + ((u32)Td4[(s0 >> 8) & 0xff] << 8) ^ + ((u32)Td4[(s3 >> 16) & 0xff] << 16) ^ + ((u32)Td4[(s2 >> 24) ] << 24) ^ + rk[1]; + *(u32*)(out+8) = + ((u32)Td4[(s2 ) & 0xff]) ^ + ((u32)Td4[(s1 >> 8) & 0xff] << 8) ^ + ((u32)Td4[(s0 >> 16) & 0xff] << 16) ^ + ((u32)Td4[(s3 >> 24) ] << 24) ^ + rk[2]; + *(u32*)(out+12) = + ((u32)Td4[(s3 ) & 0xff]) ^ + ((u32)Td4[(s2 >> 8) & 0xff] << 8) ^ + ((u32)Td4[(s1 >> 16) & 0xff] << 16) ^ + ((u32)Td4[(s0 >> 24) ] << 24) ^ + rk[3]; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-586.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-586.pl new file mode 100755 index 000000000..29059edf8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-586.pl @@ -0,0 +1,3000 @@ +#! /usr/bin/env perl +# Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# Version 4.3. +# +# You might fail to appreciate this module performance from the first +# try. If compared to "vanilla" linux-ia32-icc target, i.e. considered +# to be *the* best Intel C compiler without -KPIC, performance appears +# to be virtually identical... But try to re-configure with shared +# library support... Aha! Intel compiler "suddenly" lags behind by 30% +# [on P4, more on others]:-) And if compared to position-independent +# code generated by GNU C, this code performs *more* than *twice* as +# fast! Yes, all this buzz about PIC means that unlike other hand- +# coded implementations, this one was explicitly designed to be safe +# to use even in shared library context... This also means that this +# code isn't necessarily absolutely fastest "ever," because in order +# to achieve position independence an extra register has to be +# off-loaded to stack, which affects the benchmark result. +# +# Special note about instruction choice. Do you recall RC4_INT code +# performing poorly on P4? It might be the time to figure out why. +# RC4_INT code implies effective address calculations in base+offset*4 +# form. Trouble is that it seems that offset scaling turned to be +# critical path... At least eliminating scaling resulted in 2.8x RC4 +# performance improvement [as you might recall]. As AES code is hungry +# for scaling too, I [try to] avoid the latter by favoring off-by-2 +# shifts and masking the result with 0xFF<<2 instead of "boring" 0xFF. +# +# As was shown by Dean Gaudet, the above note turned out to be +# void. Performance improvement with off-by-2 shifts was observed on +# intermediate implementation, which was spilling yet another register +# to stack... Final offset*4 code below runs just a tad faster on P4, +# but exhibits up to 10% improvement on other cores. +# +# Second version is "monolithic" replacement for aes_core.c, which in +# addition to AES_[de|en]crypt implements AES_set_[de|en]cryption_key. +# This made it possible to implement little-endian variant of the +# algorithm without modifying the base C code. Motivating factor for +# the undertaken effort was that it appeared that in tight IA-32 +# register window little-endian flavor could achieve slightly higher +# Instruction Level Parallelism, and it indeed resulted in up to 15% +# better performance on most recent µ-archs... +# +# Third version adds AES_cbc_encrypt implementation, which resulted in +# up to 40% performance improvement of CBC benchmark results. 40% was +# observed on P4 core, where "overall" improvement coefficient, i.e. if +# compared to PIC generated by GCC and in CBC mode, was observed to be +# as large as 4x:-) CBC performance is virtually identical to ECB now +# and on some platforms even better, e.g. 17.6 "small" cycles/byte on +# Opteron, because certain function prologues and epilogues are +# effectively taken out of the loop... +# +# Version 3.2 implements compressed tables and prefetch of these tables +# in CBC[!] mode. Former means that 3/4 of table references are now +# misaligned, which unfortunately has negative impact on elder IA-32 +# implementations, Pentium suffered 30% penalty, PIII - 10%. +# +# Version 3.3 avoids L1 cache aliasing between stack frame and +# S-boxes, and 3.4 - L1 cache aliasing even between key schedule. The +# latter is achieved by copying the key schedule to controlled place in +# stack. This unfortunately has rather strong impact on small block CBC +# performance, ~2x deterioration on 16-byte block if compared to 3.3. +# +# Version 3.5 checks if there is L1 cache aliasing between user-supplied +# key schedule and S-boxes and abstains from copying the former if +# there is no. This allows end-user to consciously retain small block +# performance by aligning key schedule in specific manner. +# +# Version 3.6 compresses Td4 to 256 bytes and prefetches it in ECB. +# +# Current ECB performance numbers for 128-bit key in CPU cycles per +# processed byte [measure commonly used by AES benchmarkers] are: +# +# small footprint fully unrolled +# P4 24 22 +# AMD K8 20 19 +# PIII 25 23 +# Pentium 81 78 +# +# Version 3.7 reimplements outer rounds as "compact." Meaning that +# first and last rounds reference compact 256 bytes S-box. This means +# that first round consumes a lot more CPU cycles and that encrypt +# and decrypt performance becomes asymmetric. Encrypt performance +# drops by 10-12%, while decrypt - by 20-25%:-( 256 bytes S-box is +# aggressively pre-fetched. +# +# Version 4.0 effectively rolls back to 3.6 and instead implements +# additional set of functions, _[x86|sse]_AES_[en|de]crypt_compact, +# which use exclusively 256 byte S-box. These functions are to be +# called in modes not concealing plain text, such as ECB, or when +# we're asked to process smaller amount of data [or unconditionally +# on hyper-threading CPU]. Currently it's called unconditionally from +# AES_[en|de]crypt, which affects all modes, but CBC. CBC routine +# still needs to be modified to switch between slower and faster +# mode when appropriate... But in either case benchmark landscape +# changes dramatically and below numbers are CPU cycles per processed +# byte for 128-bit key. +# +# ECB encrypt ECB decrypt CBC large chunk +# P4 52[54] 83[95] 23 +# AMD K8 46[41] 66[70] 18 +# PIII 41[50] 60[77] 24 +# Core 2 31[36] 45[64] 18.5 +# Atom 76[100] 96[138] 60 +# Pentium 115 150 77 +# +# Version 4.1 switches to compact S-box even in key schedule setup. +# +# Version 4.2 prefetches compact S-box in every SSE round or in other +# words every cache-line is *guaranteed* to be accessed within ~50 +# cycles window. Why just SSE? Because it's needed on hyper-threading +# CPU! Which is also why it's prefetched with 64 byte stride. Best +# part is that it has no negative effect on performance:-) +# +# Version 4.3 implements switch between compact and non-compact block +# functions in AES_cbc_encrypt depending on how much data was asked +# to be processed in one stroke. +# +###################################################################### +# Timing attacks are classified in two classes: synchronous when +# attacker consciously initiates cryptographic operation and collects +# timing data of various character afterwards, and asynchronous when +# malicious code is executed on same CPU simultaneously with AES, +# instruments itself and performs statistical analysis of this data. +# +# As far as synchronous attacks go the root to the AES timing +# vulnerability is twofold. Firstly, of 256 S-box elements at most 160 +# are referred to in single 128-bit block operation. Well, in C +# implementation with 4 distinct tables it's actually as little as 40 +# references per 256 elements table, but anyway... Secondly, even +# though S-box elements are clustered into smaller amount of cache- +# lines, smaller than 160 and even 40, it turned out that for certain +# plain-text pattern[s] or simply put chosen plain-text and given key +# few cache-lines remain unaccessed during block operation. Now, if +# attacker can figure out this access pattern, he can deduct the key +# [or at least part of it]. The natural way to mitigate this kind of +# attacks is to minimize the amount of cache-lines in S-box and/or +# prefetch them to ensure that every one is accessed for more uniform +# timing. But note that *if* plain-text was concealed in such way that +# input to block function is distributed *uniformly*, then attack +# wouldn't apply. Now note that some encryption modes, most notably +# CBC, do mask the plain-text in this exact way [secure cipher output +# is distributed uniformly]. Yes, one still might find input that +# would reveal the information about given key, but if amount of +# candidate inputs to be tried is larger than amount of possible key +# combinations then attack becomes infeasible. This is why revised +# AES_cbc_encrypt "dares" to switch to larger S-box when larger chunk +# of data is to be processed in one stroke. The current size limit of +# 512 bytes is chosen to provide same [diminishingly low] probability +# for cache-line to remain untouched in large chunk operation with +# large S-box as for single block operation with compact S-box and +# surely needs more careful consideration... +# +# As for asynchronous attacks. There are two flavours: attacker code +# being interleaved with AES on hyper-threading CPU at *instruction* +# level, and two processes time sharing single core. As for latter. +# Two vectors. 1. Given that attacker process has higher priority, +# yield execution to process performing AES just before timer fires +# off the scheduler, immediately regain control of CPU and analyze the +# cache state. For this attack to be efficient attacker would have to +# effectively slow down the operation by several *orders* of magnitude, +# by ratio of time slice to duration of handful of AES rounds, which +# unlikely to remain unnoticed. Not to mention that this also means +# that he would spend correspondingly more time to collect enough +# statistical data to mount the attack. It's probably appropriate to +# say that if adversary reckons that this attack is beneficial and +# risks to be noticed, you probably have larger problems having him +# mere opportunity. In other words suggested code design expects you +# to preclude/mitigate this attack by overall system security design. +# 2. Attacker manages to make his code interrupt driven. In order for +# this kind of attack to be feasible, interrupt rate has to be high +# enough, again comparable to duration of handful of AES rounds. But +# is there interrupt source of such rate? Hardly, not even 1Gbps NIC +# generates interrupts at such raging rate... +# +# And now back to the former, hyper-threading CPU or more specifically +# Intel P4. Recall that asynchronous attack implies that malicious +# code instruments itself. And naturally instrumentation granularity +# has be noticeably lower than duration of codepath accessing S-box. +# Given that all cache-lines are accessed during that time that is. +# Current implementation accesses *all* cache-lines within ~50 cycles +# window, which is actually *less* than RDTSC latency on Intel P4! + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +$output = pop; +open OUT,">$output"; +*STDOUT=*OUT; + +&asm_init($ARGV[0],$x86only = $ARGV[$#ARGV] eq "386"); +&static_label("AES_Te"); +&static_label("AES_Td"); + +$s0="eax"; +$s1="ebx"; +$s2="ecx"; +$s3="edx"; +$key="edi"; +$acc="esi"; +$tbl="ebp"; + +# stack frame layout in _[x86|sse]_AES_* routines, frame is allocated +# by caller +$__ra=&DWP(0,"esp"); # return address +$__s0=&DWP(4,"esp"); # s0 backing store +$__s1=&DWP(8,"esp"); # s1 backing store +$__s2=&DWP(12,"esp"); # s2 backing store +$__s3=&DWP(16,"esp"); # s3 backing store +$__key=&DWP(20,"esp"); # pointer to key schedule +$__end=&DWP(24,"esp"); # pointer to end of key schedule +$__tbl=&DWP(28,"esp"); # %ebp backing store + +# stack frame layout in AES_[en|crypt] routines, which differs from +# above by 4 and overlaps by %ebp backing store +$_tbl=&DWP(24,"esp"); +$_esp=&DWP(28,"esp"); + +sub _data_word() { my $i; while(defined($i=shift)) { &data_word($i,$i); } } + +$speed_limit=512; # chunks smaller than $speed_limit are + # processed with compact routine in CBC mode +$small_footprint=1; # $small_footprint=1 code is ~5% slower [on + # recent µ-archs], but ~5 times smaller! + # I favor compact code to minimize cache + # contention and in hope to "collect" 5% back + # in real-life applications... + +$vertical_spin=0; # shift "vertically" defaults to 0, because of + # its proof-of-concept status... +# Note that there is no decvert(), as well as last encryption round is +# performed with "horizontal" shifts. This is because this "vertical" +# implementation [one which groups shifts on a given $s[i] to form a +# "column," unlike "horizontal" one, which groups shifts on different +# $s[i] to form a "row"] is work in progress. It was observed to run +# few percents faster on Intel cores, but not AMD. On AMD K8 core it's +# whole 12% slower:-( So we face a trade-off... Shall it be resolved +# some day? Till then the code is considered experimental and by +# default remains dormant... + +sub encvert() +{ my ($te,@s) = @_; + my ($v0,$v1) = ($acc,$key); + + &mov ($v0,$s[3]); # copy s3 + &mov (&DWP(4,"esp"),$s[2]); # save s2 + &mov ($v1,$s[0]); # copy s0 + &mov (&DWP(8,"esp"),$s[1]); # save s1 + + &movz ($s[2],&HB($s[0])); + &and ($s[0],0xFF); + &mov ($s[0],&DWP(0,$te,$s[0],8)); # s0>>0 + &shr ($v1,16); + &mov ($s[3],&DWP(3,$te,$s[2],8)); # s0>>8 + &movz ($s[1],&HB($v1)); + &and ($v1,0xFF); + &mov ($s[2],&DWP(2,$te,$v1,8)); # s0>>16 + &mov ($v1,$v0); + &mov ($s[1],&DWP(1,$te,$s[1],8)); # s0>>24 + + &and ($v0,0xFF); + &xor ($s[3],&DWP(0,$te,$v0,8)); # s3>>0 + &movz ($v0,&HB($v1)); + &shr ($v1,16); + &xor ($s[2],&DWP(3,$te,$v0,8)); # s3>>8 + &movz ($v0,&HB($v1)); + &and ($v1,0xFF); + &xor ($s[1],&DWP(2,$te,$v1,8)); # s3>>16 + &mov ($v1,&DWP(4,"esp")); # restore s2 + &xor ($s[0],&DWP(1,$te,$v0,8)); # s3>>24 + + &mov ($v0,$v1); + &and ($v1,0xFF); + &xor ($s[2],&DWP(0,$te,$v1,8)); # s2>>0 + &movz ($v1,&HB($v0)); + &shr ($v0,16); + &xor ($s[1],&DWP(3,$te,$v1,8)); # s2>>8 + &movz ($v1,&HB($v0)); + &and ($v0,0xFF); + &xor ($s[0],&DWP(2,$te,$v0,8)); # s2>>16 + &mov ($v0,&DWP(8,"esp")); # restore s1 + &xor ($s[3],&DWP(1,$te,$v1,8)); # s2>>24 + + &mov ($v1,$v0); + &and ($v0,0xFF); + &xor ($s[1],&DWP(0,$te,$v0,8)); # s1>>0 + &movz ($v0,&HB($v1)); + &shr ($v1,16); + &xor ($s[0],&DWP(3,$te,$v0,8)); # s1>>8 + &movz ($v0,&HB($v1)); + &and ($v1,0xFF); + &xor ($s[3],&DWP(2,$te,$v1,8)); # s1>>16 + &mov ($key,$__key); # reincarnate v1 as key + &xor ($s[2],&DWP(1,$te,$v0,8)); # s1>>24 +} + +# Another experimental routine, which features "horizontal spin," but +# eliminates one reference to stack. Strangely enough runs slower... +sub enchoriz() +{ my ($v0,$v1) = ($key,$acc); + + &movz ($v0,&LB($s0)); # 3, 2, 1, 0* + &rotr ($s2,8); # 8,11,10, 9 + &mov ($v1,&DWP(0,$te,$v0,8)); # 0 + &movz ($v0,&HB($s1)); # 7, 6, 5*, 4 + &rotr ($s3,16); # 13,12,15,14 + &xor ($v1,&DWP(3,$te,$v0,8)); # 5 + &movz ($v0,&HB($s2)); # 8,11,10*, 9 + &rotr ($s0,16); # 1, 0, 3, 2 + &xor ($v1,&DWP(2,$te,$v0,8)); # 10 + &movz ($v0,&HB($s3)); # 13,12,15*,14 + &xor ($v1,&DWP(1,$te,$v0,8)); # 15, t[0] collected + &mov ($__s0,$v1); # t[0] saved + + &movz ($v0,&LB($s1)); # 7, 6, 5, 4* + &shr ($s1,16); # -, -, 7, 6 + &mov ($v1,&DWP(0,$te,$v0,8)); # 4 + &movz ($v0,&LB($s3)); # 13,12,15,14* + &xor ($v1,&DWP(2,$te,$v0,8)); # 14 + &movz ($v0,&HB($s0)); # 1, 0, 3*, 2 + &and ($s3,0xffff0000); # 13,12, -, - + &xor ($v1,&DWP(1,$te,$v0,8)); # 3 + &movz ($v0,&LB($s2)); # 8,11,10, 9* + &or ($s3,$s1); # 13,12, 7, 6 + &xor ($v1,&DWP(3,$te,$v0,8)); # 9, t[1] collected + &mov ($s1,$v1); # s[1]=t[1] + + &movz ($v0,&LB($s0)); # 1, 0, 3, 2* + &shr ($s2,16); # -, -, 8,11 + &mov ($v1,&DWP(2,$te,$v0,8)); # 2 + &movz ($v0,&HB($s3)); # 13,12, 7*, 6 + &xor ($v1,&DWP(1,$te,$v0,8)); # 7 + &movz ($v0,&HB($s2)); # -, -, 8*,11 + &xor ($v1,&DWP(0,$te,$v0,8)); # 8 + &mov ($v0,$s3); + &shr ($v0,24); # 13 + &xor ($v1,&DWP(3,$te,$v0,8)); # 13, t[2] collected + + &movz ($v0,&LB($s2)); # -, -, 8,11* + &shr ($s0,24); # 1* + &mov ($s2,&DWP(1,$te,$v0,8)); # 11 + &xor ($s2,&DWP(3,$te,$s0,8)); # 1 + &mov ($s0,$__s0); # s[0]=t[0] + &movz ($v0,&LB($s3)); # 13,12, 7, 6* + &shr ($s3,16); # , ,13,12 + &xor ($s2,&DWP(2,$te,$v0,8)); # 6 + &mov ($key,$__key); # reincarnate v0 as key + &and ($s3,0xff); # , ,13,12* + &mov ($s3,&DWP(0,$te,$s3,8)); # 12 + &xor ($s3,$s2); # s[2]=t[3] collected + &mov ($s2,$v1); # s[2]=t[2] +} + +# More experimental code... SSE one... Even though this one eliminates +# *all* references to stack, it's not faster... +sub sse_encbody() +{ + &movz ($acc,&LB("eax")); # 0 + &mov ("ecx",&DWP(0,$tbl,$acc,8)); # 0 + &pshufw ("mm2","mm0",0x0d); # 7, 6, 3, 2 + &movz ("edx",&HB("eax")); # 1 + &mov ("edx",&DWP(3,$tbl,"edx",8)); # 1 + &shr ("eax",16); # 5, 4 + + &movz ($acc,&LB("ebx")); # 10 + &xor ("ecx",&DWP(2,$tbl,$acc,8)); # 10 + &pshufw ("mm6","mm4",0x08); # 13,12, 9, 8 + &movz ($acc,&HB("ebx")); # 11 + &xor ("edx",&DWP(1,$tbl,$acc,8)); # 11 + &shr ("ebx",16); # 15,14 + + &movz ($acc,&HB("eax")); # 5 + &xor ("ecx",&DWP(3,$tbl,$acc,8)); # 5 + &movq ("mm3",QWP(16,$key)); + &movz ($acc,&HB("ebx")); # 15 + &xor ("ecx",&DWP(1,$tbl,$acc,8)); # 15 + &movd ("mm0","ecx"); # t[0] collected + + &movz ($acc,&LB("eax")); # 4 + &mov ("ecx",&DWP(0,$tbl,$acc,8)); # 4 + &movd ("eax","mm2"); # 7, 6, 3, 2 + &movz ($acc,&LB("ebx")); # 14 + &xor ("ecx",&DWP(2,$tbl,$acc,8)); # 14 + &movd ("ebx","mm6"); # 13,12, 9, 8 + + &movz ($acc,&HB("eax")); # 3 + &xor ("ecx",&DWP(1,$tbl,$acc,8)); # 3 + &movz ($acc,&HB("ebx")); # 9 + &xor ("ecx",&DWP(3,$tbl,$acc,8)); # 9 + &movd ("mm1","ecx"); # t[1] collected + + &movz ($acc,&LB("eax")); # 2 + &mov ("ecx",&DWP(2,$tbl,$acc,8)); # 2 + &shr ("eax",16); # 7, 6 + &punpckldq ("mm0","mm1"); # t[0,1] collected + &movz ($acc,&LB("ebx")); # 8 + &xor ("ecx",&DWP(0,$tbl,$acc,8)); # 8 + &shr ("ebx",16); # 13,12 + + &movz ($acc,&HB("eax")); # 7 + &xor ("ecx",&DWP(1,$tbl,$acc,8)); # 7 + &pxor ("mm0","mm3"); + &movz ("eax",&LB("eax")); # 6 + &xor ("edx",&DWP(2,$tbl,"eax",8)); # 6 + &pshufw ("mm1","mm0",0x08); # 5, 4, 1, 0 + &movz ($acc,&HB("ebx")); # 13 + &xor ("ecx",&DWP(3,$tbl,$acc,8)); # 13 + &xor ("ecx",&DWP(24,$key)); # t[2] + &movd ("mm4","ecx"); # t[2] collected + &movz ("ebx",&LB("ebx")); # 12 + &xor ("edx",&DWP(0,$tbl,"ebx",8)); # 12 + &shr ("ecx",16); + &movd ("eax","mm1"); # 5, 4, 1, 0 + &mov ("ebx",&DWP(28,$key)); # t[3] + &xor ("ebx","edx"); + &movd ("mm5","ebx"); # t[3] collected + &and ("ebx",0xffff0000); + &or ("ebx","ecx"); + + &punpckldq ("mm4","mm5"); # t[2,3] collected +} + +###################################################################### +# "Compact" block function +###################################################################### + +sub enccompact() +{ my $Fn = \&mov; + while ($#_>5) { pop(@_); $Fn=sub{}; } + my ($i,$te,@s)=@_; + my $tmp = $key; + my $out = $i==3?$s[0]:$acc; + + # $Fn is used in first compact round and its purpose is to + # void restoration of some values from stack, so that after + # 4xenccompact with extra argument $key value is left there... + if ($i==3) { &$Fn ($key,$__key); }##%edx + else { &mov ($out,$s[0]); } + &and ($out,0xFF); + if ($i==1) { &shr ($s[0],16); }#%ebx[1] + if ($i==2) { &shr ($s[0],24); }#%ecx[2] + &movz ($out,&BP(-128,$te,$out,1)); + + if ($i==3) { $tmp=$s[1]; }##%eax + &movz ($tmp,&HB($s[1])); + &movz ($tmp,&BP(-128,$te,$tmp,1)); + &shl ($tmp,8); + &xor ($out,$tmp); + + if ($i==3) { $tmp=$s[2]; &mov ($s[1],$__s0); }##%ebx + else { &mov ($tmp,$s[2]); + &shr ($tmp,16); } + if ($i==2) { &and ($s[1],0xFF); }#%edx[2] + &and ($tmp,0xFF); + &movz ($tmp,&BP(-128,$te,$tmp,1)); + &shl ($tmp,16); + &xor ($out,$tmp); + + if ($i==3) { $tmp=$s[3]; &mov ($s[2],$__s1); }##%ecx + elsif($i==2){ &movz ($tmp,&HB($s[3])); }#%ebx[2] + else { &mov ($tmp,$s[3]); + &shr ($tmp,24); } + &movz ($tmp,&BP(-128,$te,$tmp,1)); + &shl ($tmp,24); + &xor ($out,$tmp); + if ($i<2) { &mov (&DWP(4+4*$i,"esp"),$out); } + if ($i==3) { &mov ($s[3],$acc); } + &comment(); +} + +sub enctransform() +{ my @s = ($s0,$s1,$s2,$s3); + my $i = shift; + my $tmp = $tbl; + my $r2 = $key ; + + &and ($tmp,$s[$i]); + &lea ($r2,&DWP(0,$s[$i],$s[$i])); + &mov ($acc,$tmp); + &shr ($tmp,7); + &and ($r2,0xfefefefe); + &sub ($acc,$tmp); + &mov ($tmp,$s[$i]); + &and ($acc,0x1b1b1b1b); + &rotr ($tmp,16); + &xor ($acc,$r2); # r2 + &mov ($r2,$s[$i]); + + &xor ($s[$i],$acc); # r0 ^ r2 + &rotr ($r2,16+8); + &xor ($acc,$tmp); + &rotl ($s[$i],24); + &xor ($acc,$r2); + &mov ($tmp,0x80808080) if ($i!=1); + &xor ($s[$i],$acc); # ROTATE(r2^r0,24) ^ r2 +} + +&function_begin_B("_x86_AES_encrypt_compact"); + # note that caller is expected to allocate stack frame for me! + &mov ($__key,$key); # save key + + &xor ($s0,&DWP(0,$key)); # xor with key + &xor ($s1,&DWP(4,$key)); + &xor ($s2,&DWP(8,$key)); + &xor ($s3,&DWP(12,$key)); + + &mov ($acc,&DWP(240,$key)); # load key->rounds + &lea ($acc,&DWP(-2,$acc,$acc)); + &lea ($acc,&DWP(0,$key,$acc,8)); + &mov ($__end,$acc); # end of key schedule + + # prefetch Te4 + &mov ($key,&DWP(0-128,$tbl)); + &mov ($acc,&DWP(32-128,$tbl)); + &mov ($key,&DWP(64-128,$tbl)); + &mov ($acc,&DWP(96-128,$tbl)); + &mov ($key,&DWP(128-128,$tbl)); + &mov ($acc,&DWP(160-128,$tbl)); + &mov ($key,&DWP(192-128,$tbl)); + &mov ($acc,&DWP(224-128,$tbl)); + + &set_label("loop",16); + + &enccompact(0,$tbl,$s0,$s1,$s2,$s3,1); + &enccompact(1,$tbl,$s1,$s2,$s3,$s0,1); + &enccompact(2,$tbl,$s2,$s3,$s0,$s1,1); + &enccompact(3,$tbl,$s3,$s0,$s1,$s2,1); + &mov ($tbl,0x80808080); + &enctransform(2); + &enctransform(3); + &enctransform(0); + &enctransform(1); + &mov ($key,$__key); + &mov ($tbl,$__tbl); + &add ($key,16); # advance rd_key + &xor ($s0,&DWP(0,$key)); + &xor ($s1,&DWP(4,$key)); + &xor ($s2,&DWP(8,$key)); + &xor ($s3,&DWP(12,$key)); + + &cmp ($key,$__end); + &mov ($__key,$key); + &jb (&label("loop")); + + &enccompact(0,$tbl,$s0,$s1,$s2,$s3); + &enccompact(1,$tbl,$s1,$s2,$s3,$s0); + &enccompact(2,$tbl,$s2,$s3,$s0,$s1); + &enccompact(3,$tbl,$s3,$s0,$s1,$s2); + + &xor ($s0,&DWP(16,$key)); + &xor ($s1,&DWP(20,$key)); + &xor ($s2,&DWP(24,$key)); + &xor ($s3,&DWP(28,$key)); + + &ret (); +&function_end_B("_x86_AES_encrypt_compact"); + +###################################################################### +# "Compact" SSE block function. +###################################################################### +# +# Performance is not actually extraordinary in comparison to pure +# x86 code. In particular encrypt performance is virtually the same. +# Decrypt performance on the other hand is 15-20% better on newer +# µ-archs [but we're thankful for *any* improvement here], and ~50% +# better on PIII:-) And additionally on the pros side this code +# eliminates redundant references to stack and thus relieves/ +# minimizes the pressure on the memory bus. +# +# MMX register layout lsb +# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +# | mm4 | mm0 | +# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +# | s3 | s2 | s1 | s0 | +# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +# |15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0| +# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +# +# Indexes translate as s[N/4]>>(8*(N%4)), e.g. 5 means s1>>8. +# In this terms encryption and decryption "compact" permutation +# matrices can be depicted as following: +# +# encryption lsb # decryption lsb +# +----++----+----+----+----+ # +----++----+----+----+----+ +# | t0 || 15 | 10 | 5 | 0 | # | t0 || 7 | 10 | 13 | 0 | +# +----++----+----+----+----+ # +----++----+----+----+----+ +# | t1 || 3 | 14 | 9 | 4 | # | t1 || 11 | 14 | 1 | 4 | +# +----++----+----+----+----+ # +----++----+----+----+----+ +# | t2 || 7 | 2 | 13 | 8 | # | t2 || 15 | 2 | 5 | 8 | +# +----++----+----+----+----+ # +----++----+----+----+----+ +# | t3 || 11 | 6 | 1 | 12 | # | t3 || 3 | 6 | 9 | 12 | +# +----++----+----+----+----+ # +----++----+----+----+----+ +# +###################################################################### +# Why not xmm registers? Short answer. It was actually tested and +# was not any faster, but *contrary*, most notably on Intel CPUs. +# Longer answer. Main advantage of using mm registers is that movd +# latency is lower, especially on Intel P4. While arithmetic +# instructions are twice as many, they can be scheduled every cycle +# and not every second one when they are operating on xmm register, +# so that "arithmetic throughput" remains virtually the same. And +# finally the code can be executed even on elder SSE-only CPUs:-) + +sub sse_enccompact() +{ + &pshufw ("mm1","mm0",0x08); # 5, 4, 1, 0 + &pshufw ("mm5","mm4",0x0d); # 15,14,11,10 + &movd ("eax","mm1"); # 5, 4, 1, 0 + &movd ("ebx","mm5"); # 15,14,11,10 + &mov ($__key,$key); + + &movz ($acc,&LB("eax")); # 0 + &movz ("edx",&HB("eax")); # 1 + &pshufw ("mm2","mm0",0x0d); # 7, 6, 3, 2 + &movz ("ecx",&BP(-128,$tbl,$acc,1)); # 0 + &movz ($key,&LB("ebx")); # 10 + &movz ("edx",&BP(-128,$tbl,"edx",1)); # 1 + &shr ("eax",16); # 5, 4 + &shl ("edx",8); # 1 + + &movz ($acc,&BP(-128,$tbl,$key,1)); # 10 + &movz ($key,&HB("ebx")); # 11 + &shl ($acc,16); # 10 + &pshufw ("mm6","mm4",0x08); # 13,12, 9, 8 + &or ("ecx",$acc); # 10 + &movz ($acc,&BP(-128,$tbl,$key,1)); # 11 + &movz ($key,&HB("eax")); # 5 + &shl ($acc,24); # 11 + &shr ("ebx",16); # 15,14 + &or ("edx",$acc); # 11 + + &movz ($acc,&BP(-128,$tbl,$key,1)); # 5 + &movz ($key,&HB("ebx")); # 15 + &shl ($acc,8); # 5 + &or ("ecx",$acc); # 5 + &movz ($acc,&BP(-128,$tbl,$key,1)); # 15 + &movz ($key,&LB("eax")); # 4 + &shl ($acc,24); # 15 + &or ("ecx",$acc); # 15 + + &movz ($acc,&BP(-128,$tbl,$key,1)); # 4 + &movz ($key,&LB("ebx")); # 14 + &movd ("eax","mm2"); # 7, 6, 3, 2 + &movd ("mm0","ecx"); # t[0] collected + &movz ("ecx",&BP(-128,$tbl,$key,1)); # 14 + &movz ($key,&HB("eax")); # 3 + &shl ("ecx",16); # 14 + &movd ("ebx","mm6"); # 13,12, 9, 8 + &or ("ecx",$acc); # 14 + + &movz ($acc,&BP(-128,$tbl,$key,1)); # 3 + &movz ($key,&HB("ebx")); # 9 + &shl ($acc,24); # 3 + &or ("ecx",$acc); # 3 + &movz ($acc,&BP(-128,$tbl,$key,1)); # 9 + &movz ($key,&LB("ebx")); # 8 + &shl ($acc,8); # 9 + &shr ("ebx",16); # 13,12 + &or ("ecx",$acc); # 9 + + &movz ($acc,&BP(-128,$tbl,$key,1)); # 8 + &movz ($key,&LB("eax")); # 2 + &shr ("eax",16); # 7, 6 + &movd ("mm1","ecx"); # t[1] collected + &movz ("ecx",&BP(-128,$tbl,$key,1)); # 2 + &movz ($key,&HB("eax")); # 7 + &shl ("ecx",16); # 2 + &and ("eax",0xff); # 6 + &or ("ecx",$acc); # 2 + + &punpckldq ("mm0","mm1"); # t[0,1] collected + + &movz ($acc,&BP(-128,$tbl,$key,1)); # 7 + &movz ($key,&HB("ebx")); # 13 + &shl ($acc,24); # 7 + &and ("ebx",0xff); # 12 + &movz ("eax",&BP(-128,$tbl,"eax",1)); # 6 + &or ("ecx",$acc); # 7 + &shl ("eax",16); # 6 + &movz ($acc,&BP(-128,$tbl,$key,1)); # 13 + &or ("edx","eax"); # 6 + &shl ($acc,8); # 13 + &movz ("ebx",&BP(-128,$tbl,"ebx",1)); # 12 + &or ("ecx",$acc); # 13 + &or ("edx","ebx"); # 12 + &mov ($key,$__key); + &movd ("mm4","ecx"); # t[2] collected + &movd ("mm5","edx"); # t[3] collected + + &punpckldq ("mm4","mm5"); # t[2,3] collected +} + + if (!$x86only) { +&function_begin_B("_sse_AES_encrypt_compact"); + &pxor ("mm0",&QWP(0,$key)); # 7, 6, 5, 4, 3, 2, 1, 0 + &pxor ("mm4",&QWP(8,$key)); # 15,14,13,12,11,10, 9, 8 + + # note that caller is expected to allocate stack frame for me! + &mov ($acc,&DWP(240,$key)); # load key->rounds + &lea ($acc,&DWP(-2,$acc,$acc)); + &lea ($acc,&DWP(0,$key,$acc,8)); + &mov ($__end,$acc); # end of key schedule + + &mov ($s0,0x1b1b1b1b); # magic constant + &mov (&DWP(8,"esp"),$s0); + &mov (&DWP(12,"esp"),$s0); + + # prefetch Te4 + &mov ($s0,&DWP(0-128,$tbl)); + &mov ($s1,&DWP(32-128,$tbl)); + &mov ($s2,&DWP(64-128,$tbl)); + &mov ($s3,&DWP(96-128,$tbl)); + &mov ($s0,&DWP(128-128,$tbl)); + &mov ($s1,&DWP(160-128,$tbl)); + &mov ($s2,&DWP(192-128,$tbl)); + &mov ($s3,&DWP(224-128,$tbl)); + + &set_label("loop",16); + &sse_enccompact(); + &add ($key,16); + &cmp ($key,$__end); + &ja (&label("out")); + + &movq ("mm2",&QWP(8,"esp")); + &pxor ("mm3","mm3"); &pxor ("mm7","mm7"); + &movq ("mm1","mm0"); &movq ("mm5","mm4"); # r0 + &pcmpgtb("mm3","mm0"); &pcmpgtb("mm7","mm4"); + &pand ("mm3","mm2"); &pand ("mm7","mm2"); + &pshufw ("mm2","mm0",0xb1); &pshufw ("mm6","mm4",0xb1);# ROTATE(r0,16) + &paddb ("mm0","mm0"); &paddb ("mm4","mm4"); + &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # = r2 + &pshufw ("mm3","mm2",0xb1); &pshufw ("mm7","mm6",0xb1);# r0 + &pxor ("mm1","mm0"); &pxor ("mm5","mm4"); # r0^r2 + &pxor ("mm0","mm2"); &pxor ("mm4","mm6"); # ^= ROTATE(r0,16) + + &movq ("mm2","mm3"); &movq ("mm6","mm7"); + &pslld ("mm3",8); &pslld ("mm7",8); + &psrld ("mm2",24); &psrld ("mm6",24); + &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= r0<<8 + &pxor ("mm0","mm2"); &pxor ("mm4","mm6"); # ^= r0>>24 + + &movq ("mm3","mm1"); &movq ("mm7","mm5"); + &movq ("mm2",&QWP(0,$key)); &movq ("mm6",&QWP(8,$key)); + &psrld ("mm1",8); &psrld ("mm5",8); + &mov ($s0,&DWP(0-128,$tbl)); + &pslld ("mm3",24); &pslld ("mm7",24); + &mov ($s1,&DWP(64-128,$tbl)); + &pxor ("mm0","mm1"); &pxor ("mm4","mm5"); # ^= (r2^r0)<<8 + &mov ($s2,&DWP(128-128,$tbl)); + &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= (r2^r0)>>24 + &mov ($s3,&DWP(192-128,$tbl)); + + &pxor ("mm0","mm2"); &pxor ("mm4","mm6"); + &jmp (&label("loop")); + + &set_label("out",16); + &pxor ("mm0",&QWP(0,$key)); + &pxor ("mm4",&QWP(8,$key)); + + &ret (); +&function_end_B("_sse_AES_encrypt_compact"); + } + +###################################################################### +# Vanilla block function. +###################################################################### + +sub encstep() +{ my ($i,$te,@s) = @_; + my $tmp = $key; + my $out = $i==3?$s[0]:$acc; + + # lines marked with #%e?x[i] denote "reordered" instructions... + if ($i==3) { &mov ($key,$__key); }##%edx + else { &mov ($out,$s[0]); + &and ($out,0xFF); } + if ($i==1) { &shr ($s[0],16); }#%ebx[1] + if ($i==2) { &shr ($s[0],24); }#%ecx[2] + &mov ($out,&DWP(0,$te,$out,8)); + + if ($i==3) { $tmp=$s[1]; }##%eax + &movz ($tmp,&HB($s[1])); + &xor ($out,&DWP(3,$te,$tmp,8)); + + if ($i==3) { $tmp=$s[2]; &mov ($s[1],$__s0); }##%ebx + else { &mov ($tmp,$s[2]); + &shr ($tmp,16); } + if ($i==2) { &and ($s[1],0xFF); }#%edx[2] + &and ($tmp,0xFF); + &xor ($out,&DWP(2,$te,$tmp,8)); + + if ($i==3) { $tmp=$s[3]; &mov ($s[2],$__s1); }##%ecx + elsif($i==2){ &movz ($tmp,&HB($s[3])); }#%ebx[2] + else { &mov ($tmp,$s[3]); + &shr ($tmp,24) } + &xor ($out,&DWP(1,$te,$tmp,8)); + if ($i<2) { &mov (&DWP(4+4*$i,"esp"),$out); } + if ($i==3) { &mov ($s[3],$acc); } + &comment(); +} + +sub enclast() +{ my ($i,$te,@s)=@_; + my $tmp = $key; + my $out = $i==3?$s[0]:$acc; + + if ($i==3) { &mov ($key,$__key); }##%edx + else { &mov ($out,$s[0]); } + &and ($out,0xFF); + if ($i==1) { &shr ($s[0],16); }#%ebx[1] + if ($i==2) { &shr ($s[0],24); }#%ecx[2] + &mov ($out,&DWP(2,$te,$out,8)); + &and ($out,0x000000ff); + + if ($i==3) { $tmp=$s[1]; }##%eax + &movz ($tmp,&HB($s[1])); + &mov ($tmp,&DWP(0,$te,$tmp,8)); + &and ($tmp,0x0000ff00); + &xor ($out,$tmp); + + if ($i==3) { $tmp=$s[2]; &mov ($s[1],$__s0); }##%ebx + else { &mov ($tmp,$s[2]); + &shr ($tmp,16); } + if ($i==2) { &and ($s[1],0xFF); }#%edx[2] + &and ($tmp,0xFF); + &mov ($tmp,&DWP(0,$te,$tmp,8)); + &and ($tmp,0x00ff0000); + &xor ($out,$tmp); + + if ($i==3) { $tmp=$s[3]; &mov ($s[2],$__s1); }##%ecx + elsif($i==2){ &movz ($tmp,&HB($s[3])); }#%ebx[2] + else { &mov ($tmp,$s[3]); + &shr ($tmp,24); } + &mov ($tmp,&DWP(2,$te,$tmp,8)); + &and ($tmp,0xff000000); + &xor ($out,$tmp); + if ($i<2) { &mov (&DWP(4+4*$i,"esp"),$out); } + if ($i==3) { &mov ($s[3],$acc); } +} + +&function_begin_B("_x86_AES_encrypt"); + if ($vertical_spin) { + # I need high parts of volatile registers to be accessible... + &exch ($s1="edi",$key="ebx"); + &mov ($s2="esi",$acc="ecx"); + } + + # note that caller is expected to allocate stack frame for me! + &mov ($__key,$key); # save key + + &xor ($s0,&DWP(0,$key)); # xor with key + &xor ($s1,&DWP(4,$key)); + &xor ($s2,&DWP(8,$key)); + &xor ($s3,&DWP(12,$key)); + + &mov ($acc,&DWP(240,$key)); # load key->rounds + + if ($small_footprint) { + &lea ($acc,&DWP(-2,$acc,$acc)); + &lea ($acc,&DWP(0,$key,$acc,8)); + &mov ($__end,$acc); # end of key schedule + + &set_label("loop",16); + if ($vertical_spin) { + &encvert($tbl,$s0,$s1,$s2,$s3); + } else { + &encstep(0,$tbl,$s0,$s1,$s2,$s3); + &encstep(1,$tbl,$s1,$s2,$s3,$s0); + &encstep(2,$tbl,$s2,$s3,$s0,$s1); + &encstep(3,$tbl,$s3,$s0,$s1,$s2); + } + &add ($key,16); # advance rd_key + &xor ($s0,&DWP(0,$key)); + &xor ($s1,&DWP(4,$key)); + &xor ($s2,&DWP(8,$key)); + &xor ($s3,&DWP(12,$key)); + &cmp ($key,$__end); + &mov ($__key,$key); + &jb (&label("loop")); + } + else { + &cmp ($acc,10); + &jle (&label("10rounds")); + &cmp ($acc,12); + &jle (&label("12rounds")); + + &set_label("14rounds",4); + for ($i=1;$i<3;$i++) { + if ($vertical_spin) { + &encvert($tbl,$s0,$s1,$s2,$s3); + } else { + &encstep(0,$tbl,$s0,$s1,$s2,$s3); + &encstep(1,$tbl,$s1,$s2,$s3,$s0); + &encstep(2,$tbl,$s2,$s3,$s0,$s1); + &encstep(3,$tbl,$s3,$s0,$s1,$s2); + } + &xor ($s0,&DWP(16*$i+0,$key)); + &xor ($s1,&DWP(16*$i+4,$key)); + &xor ($s2,&DWP(16*$i+8,$key)); + &xor ($s3,&DWP(16*$i+12,$key)); + } + &add ($key,32); + &mov ($__key,$key); # advance rd_key + &set_label("12rounds",4); + for ($i=1;$i<3;$i++) { + if ($vertical_spin) { + &encvert($tbl,$s0,$s1,$s2,$s3); + } else { + &encstep(0,$tbl,$s0,$s1,$s2,$s3); + &encstep(1,$tbl,$s1,$s2,$s3,$s0); + &encstep(2,$tbl,$s2,$s3,$s0,$s1); + &encstep(3,$tbl,$s3,$s0,$s1,$s2); + } + &xor ($s0,&DWP(16*$i+0,$key)); + &xor ($s1,&DWP(16*$i+4,$key)); + &xor ($s2,&DWP(16*$i+8,$key)); + &xor ($s3,&DWP(16*$i+12,$key)); + } + &add ($key,32); + &mov ($__key,$key); # advance rd_key + &set_label("10rounds",4); + for ($i=1;$i<10;$i++) { + if ($vertical_spin) { + &encvert($tbl,$s0,$s1,$s2,$s3); + } else { + &encstep(0,$tbl,$s0,$s1,$s2,$s3); + &encstep(1,$tbl,$s1,$s2,$s3,$s0); + &encstep(2,$tbl,$s2,$s3,$s0,$s1); + &encstep(3,$tbl,$s3,$s0,$s1,$s2); + } + &xor ($s0,&DWP(16*$i+0,$key)); + &xor ($s1,&DWP(16*$i+4,$key)); + &xor ($s2,&DWP(16*$i+8,$key)); + &xor ($s3,&DWP(16*$i+12,$key)); + } + } + + if ($vertical_spin) { + # "reincarnate" some registers for "horizontal" spin... + &mov ($s1="ebx",$key="edi"); + &mov ($s2="ecx",$acc="esi"); + } + &enclast(0,$tbl,$s0,$s1,$s2,$s3); + &enclast(1,$tbl,$s1,$s2,$s3,$s0); + &enclast(2,$tbl,$s2,$s3,$s0,$s1); + &enclast(3,$tbl,$s3,$s0,$s1,$s2); + + &add ($key,$small_footprint?16:160); + &xor ($s0,&DWP(0,$key)); + &xor ($s1,&DWP(4,$key)); + &xor ($s2,&DWP(8,$key)); + &xor ($s3,&DWP(12,$key)); + + &ret (); + +&set_label("AES_Te",64); # Yes! I keep it in the code segment! + &_data_word(0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6); + &_data_word(0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591); + &_data_word(0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56); + &_data_word(0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec); + &_data_word(0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa); + &_data_word(0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb); + &_data_word(0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45); + &_data_word(0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b); + &_data_word(0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c); + &_data_word(0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83); + &_data_word(0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9); + &_data_word(0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a); + &_data_word(0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d); + &_data_word(0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f); + &_data_word(0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df); + &_data_word(0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea); + &_data_word(0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34); + &_data_word(0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b); + &_data_word(0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d); + &_data_word(0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413); + &_data_word(0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1); + &_data_word(0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6); + &_data_word(0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972); + &_data_word(0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85); + &_data_word(0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed); + &_data_word(0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511); + &_data_word(0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe); + &_data_word(0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b); + &_data_word(0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05); + &_data_word(0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1); + &_data_word(0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142); + &_data_word(0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf); + &_data_word(0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3); + &_data_word(0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e); + &_data_word(0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a); + &_data_word(0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6); + &_data_word(0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3); + &_data_word(0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b); + &_data_word(0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428); + &_data_word(0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad); + &_data_word(0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14); + &_data_word(0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8); + &_data_word(0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4); + &_data_word(0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2); + &_data_word(0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda); + &_data_word(0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949); + &_data_word(0xb46c6cd8, 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf); + &_data_word(0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810); + &_data_word(0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c); + &_data_word(0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697); + &_data_word(0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e); + &_data_word(0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f); + &_data_word(0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc); + &_data_word(0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c); + &_data_word(0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969); + &_data_word(0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27); + &_data_word(0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122); + &_data_word(0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433); + &_data_word(0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9); + &_data_word(0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5); + &_data_word(0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a); + &_data_word(0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0); + &_data_word(0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e); + &_data_word(0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c); + +#Te4 # four copies of Te4 to choose from to avoid L1 aliasing + &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5); + &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76); + &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0); + &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0); + &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc); + &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15); + &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a); + &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75); + &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0); + &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84); + &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b); + &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf); + &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85); + &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8); + &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5); + &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2); + &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17); + &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73); + &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88); + &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb); + &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c); + &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79); + &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9); + &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08); + &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6); + &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a); + &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e); + &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e); + &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94); + &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf); + &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68); + &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16); + + &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5); + &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76); + &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0); + &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0); + &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc); + &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15); + &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a); + &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75); + &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0); + &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84); + &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b); + &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf); + &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85); + &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8); + &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5); + &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2); + &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17); + &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73); + &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88); + &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb); + &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c); + &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79); + &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9); + &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08); + &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6); + &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a); + &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e); + &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e); + &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94); + &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf); + &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68); + &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16); + + &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5); + &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76); + &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0); + &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0); + &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc); + &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15); + &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a); + &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75); + &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0); + &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84); + &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b); + &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf); + &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85); + &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8); + &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5); + &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2); + &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17); + &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73); + &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88); + &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb); + &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c); + &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79); + &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9); + &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08); + &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6); + &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a); + &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e); + &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e); + &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94); + &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf); + &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68); + &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16); + + &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5); + &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76); + &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0); + &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0); + &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc); + &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15); + &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a); + &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75); + &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0); + &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84); + &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b); + &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf); + &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85); + &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8); + &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5); + &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2); + &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17); + &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73); + &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88); + &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb); + &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c); + &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79); + &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9); + &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08); + &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6); + &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a); + &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e); + &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e); + &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94); + &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf); + &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68); + &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16); +#rcon: + &data_word(0x00000001, 0x00000002, 0x00000004, 0x00000008); + &data_word(0x00000010, 0x00000020, 0x00000040, 0x00000080); + &data_word(0x0000001b, 0x00000036, 0x00000000, 0x00000000); + &data_word(0x00000000, 0x00000000, 0x00000000, 0x00000000); +&function_end_B("_x86_AES_encrypt"); + +# void AES_encrypt (const void *inp,void *out,const AES_KEY *key); +&function_begin("AES_encrypt"); + &mov ($acc,&wparam(0)); # load inp + &mov ($key,&wparam(2)); # load key + + &mov ($s0,"esp"); + &sub ("esp",36); + &and ("esp",-64); # align to cache-line + + # place stack frame just "above" the key schedule + &lea ($s1,&DWP(-64-63,$key)); + &sub ($s1,"esp"); + &neg ($s1); + &and ($s1,0x3C0); # modulo 1024, but aligned to cache-line + &sub ("esp",$s1); + &add ("esp",4); # 4 is reserved for caller's return address + &mov ($_esp,$s0); # save stack pointer + + &call (&label("pic_point")); # make it PIC! + &set_label("pic_point"); + &blindpop($tbl); + &picmeup($s0,"OPENSSL_ia32cap_P",$tbl,&label("pic_point")) if (!$x86only); + &lea ($tbl,&DWP(&label("AES_Te")."-".&label("pic_point"),$tbl)); + + # pick Te4 copy which can't "overlap" with stack frame or key schedule + &lea ($s1,&DWP(768-4,"esp")); + &sub ($s1,$tbl); + &and ($s1,0x300); + &lea ($tbl,&DWP(2048+128,$tbl,$s1)); + + if (!$x86only) { + &bt (&DWP(0,$s0),25); # check for SSE bit + &jnc (&label("x86")); + + &movq ("mm0",&QWP(0,$acc)); + &movq ("mm4",&QWP(8,$acc)); + &call ("_sse_AES_encrypt_compact"); + &mov ("esp",$_esp); # restore stack pointer + &mov ($acc,&wparam(1)); # load out + &movq (&QWP(0,$acc),"mm0"); # write output data + &movq (&QWP(8,$acc),"mm4"); + &emms (); + &function_end_A(); + } + &set_label("x86",16); + &mov ($_tbl,$tbl); + &mov ($s0,&DWP(0,$acc)); # load input data + &mov ($s1,&DWP(4,$acc)); + &mov ($s2,&DWP(8,$acc)); + &mov ($s3,&DWP(12,$acc)); + &call ("_x86_AES_encrypt_compact"); + &mov ("esp",$_esp); # restore stack pointer + &mov ($acc,&wparam(1)); # load out + &mov (&DWP(0,$acc),$s0); # write output data + &mov (&DWP(4,$acc),$s1); + &mov (&DWP(8,$acc),$s2); + &mov (&DWP(12,$acc),$s3); +&function_end("AES_encrypt"); + +#--------------------------------------------------------------------# + +###################################################################### +# "Compact" block function +###################################################################### + +sub deccompact() +{ my $Fn = \&mov; + while ($#_>5) { pop(@_); $Fn=sub{}; } + my ($i,$td,@s)=@_; + my $tmp = $key; + my $out = $i==3?$s[0]:$acc; + + # $Fn is used in first compact round and its purpose is to + # void restoration of some values from stack, so that after + # 4xdeccompact with extra argument $key, $s0 and $s1 values + # are left there... + if($i==3) { &$Fn ($key,$__key); } + else { &mov ($out,$s[0]); } + &and ($out,0xFF); + &movz ($out,&BP(-128,$td,$out,1)); + + if ($i==3) { $tmp=$s[1]; } + &movz ($tmp,&HB($s[1])); + &movz ($tmp,&BP(-128,$td,$tmp,1)); + &shl ($tmp,8); + &xor ($out,$tmp); + + if ($i==3) { $tmp=$s[2]; &mov ($s[1],$acc); } + else { mov ($tmp,$s[2]); } + &shr ($tmp,16); + &and ($tmp,0xFF); + &movz ($tmp,&BP(-128,$td,$tmp,1)); + &shl ($tmp,16); + &xor ($out,$tmp); + + if ($i==3) { $tmp=$s[3]; &$Fn ($s[2],$__s1); } + else { &mov ($tmp,$s[3]); } + &shr ($tmp,24); + &movz ($tmp,&BP(-128,$td,$tmp,1)); + &shl ($tmp,24); + &xor ($out,$tmp); + if ($i<2) { &mov (&DWP(4+4*$i,"esp"),$out); } + if ($i==3) { &$Fn ($s[3],$__s0); } +} + +# must be called with 2,3,0,1 as argument sequence!!! +sub dectransform() +{ my @s = ($s0,$s1,$s2,$s3); + my $i = shift; + my $tmp = $key; + my $tp2 = @s[($i+2)%4]; $tp2 = @s[2] if ($i==1); + my $tp4 = @s[($i+3)%4]; $tp4 = @s[3] if ($i==1); + my $tp8 = $tbl; + + &mov ($tmp,0x80808080); + &and ($tmp,$s[$i]); + &mov ($acc,$tmp); + &shr ($tmp,7); + &lea ($tp2,&DWP(0,$s[$i],$s[$i])); + &sub ($acc,$tmp); + &and ($tp2,0xfefefefe); + &and ($acc,0x1b1b1b1b); + &xor ($tp2,$acc); + &mov ($tmp,0x80808080); + + &and ($tmp,$tp2); + &mov ($acc,$tmp); + &shr ($tmp,7); + &lea ($tp4,&DWP(0,$tp2,$tp2)); + &sub ($acc,$tmp); + &and ($tp4,0xfefefefe); + &and ($acc,0x1b1b1b1b); + &xor ($tp2,$s[$i]); # tp2^tp1 + &xor ($tp4,$acc); + &mov ($tmp,0x80808080); + + &and ($tmp,$tp4); + &mov ($acc,$tmp); + &shr ($tmp,7); + &lea ($tp8,&DWP(0,$tp4,$tp4)); + &sub ($acc,$tmp); + &and ($tp8,0xfefefefe); + &and ($acc,0x1b1b1b1b); + &xor ($tp4,$s[$i]); # tp4^tp1 + &rotl ($s[$i],8); # = ROTATE(tp1,8) + &xor ($tp8,$acc); + + &xor ($s[$i],$tp2); + &xor ($tp2,$tp8); + &xor ($s[$i],$tp4); + &xor ($tp4,$tp8); + &rotl ($tp2,24); + &xor ($s[$i],$tp8); # ^= tp8^(tp4^tp1)^(tp2^tp1) + &rotl ($tp4,16); + &xor ($s[$i],$tp2); # ^= ROTATE(tp8^tp2^tp1,24) + &rotl ($tp8,8); + &xor ($s[$i],$tp4); # ^= ROTATE(tp8^tp4^tp1,16) + &mov ($s[0],$__s0) if($i==2); #prefetch $s0 + &mov ($s[1],$__s1) if($i==3); #prefetch $s1 + &mov ($s[2],$__s2) if($i==1); + &xor ($s[$i],$tp8); # ^= ROTATE(tp8,8) + + &mov ($s[3],$__s3) if($i==1); + &mov (&DWP(4+4*$i,"esp"),$s[$i]) if($i>=2); +} + +&function_begin_B("_x86_AES_decrypt_compact"); + # note that caller is expected to allocate stack frame for me! + &mov ($__key,$key); # save key + + &xor ($s0,&DWP(0,$key)); # xor with key + &xor ($s1,&DWP(4,$key)); + &xor ($s2,&DWP(8,$key)); + &xor ($s3,&DWP(12,$key)); + + &mov ($acc,&DWP(240,$key)); # load key->rounds + + &lea ($acc,&DWP(-2,$acc,$acc)); + &lea ($acc,&DWP(0,$key,$acc,8)); + &mov ($__end,$acc); # end of key schedule + + # prefetch Td4 + &mov ($key,&DWP(0-128,$tbl)); + &mov ($acc,&DWP(32-128,$tbl)); + &mov ($key,&DWP(64-128,$tbl)); + &mov ($acc,&DWP(96-128,$tbl)); + &mov ($key,&DWP(128-128,$tbl)); + &mov ($acc,&DWP(160-128,$tbl)); + &mov ($key,&DWP(192-128,$tbl)); + &mov ($acc,&DWP(224-128,$tbl)); + + &set_label("loop",16); + + &deccompact(0,$tbl,$s0,$s3,$s2,$s1,1); + &deccompact(1,$tbl,$s1,$s0,$s3,$s2,1); + &deccompact(2,$tbl,$s2,$s1,$s0,$s3,1); + &deccompact(3,$tbl,$s3,$s2,$s1,$s0,1); + &dectransform(2); + &dectransform(3); + &dectransform(0); + &dectransform(1); + &mov ($key,$__key); + &mov ($tbl,$__tbl); + &add ($key,16); # advance rd_key + &xor ($s0,&DWP(0,$key)); + &xor ($s1,&DWP(4,$key)); + &xor ($s2,&DWP(8,$key)); + &xor ($s3,&DWP(12,$key)); + + &cmp ($key,$__end); + &mov ($__key,$key); + &jb (&label("loop")); + + &deccompact(0,$tbl,$s0,$s3,$s2,$s1); + &deccompact(1,$tbl,$s1,$s0,$s3,$s2); + &deccompact(2,$tbl,$s2,$s1,$s0,$s3); + &deccompact(3,$tbl,$s3,$s2,$s1,$s0); + + &xor ($s0,&DWP(16,$key)); + &xor ($s1,&DWP(20,$key)); + &xor ($s2,&DWP(24,$key)); + &xor ($s3,&DWP(28,$key)); + + &ret (); +&function_end_B("_x86_AES_decrypt_compact"); + +###################################################################### +# "Compact" SSE block function. +###################################################################### + +sub sse_deccompact() +{ + &pshufw ("mm1","mm0",0x0c); # 7, 6, 1, 0 + &pshufw ("mm5","mm4",0x09); # 13,12,11,10 + &movd ("eax","mm1"); # 7, 6, 1, 0 + &movd ("ebx","mm5"); # 13,12,11,10 + &mov ($__key,$key); + + &movz ($acc,&LB("eax")); # 0 + &movz ("edx",&HB("eax")); # 1 + &pshufw ("mm2","mm0",0x06); # 3, 2, 5, 4 + &movz ("ecx",&BP(-128,$tbl,$acc,1)); # 0 + &movz ($key,&LB("ebx")); # 10 + &movz ("edx",&BP(-128,$tbl,"edx",1)); # 1 + &shr ("eax",16); # 7, 6 + &shl ("edx",8); # 1 + + &movz ($acc,&BP(-128,$tbl,$key,1)); # 10 + &movz ($key,&HB("ebx")); # 11 + &shl ($acc,16); # 10 + &pshufw ("mm6","mm4",0x03); # 9, 8,15,14 + &or ("ecx",$acc); # 10 + &movz ($acc,&BP(-128,$tbl,$key,1)); # 11 + &movz ($key,&HB("eax")); # 7 + &shl ($acc,24); # 11 + &shr ("ebx",16); # 13,12 + &or ("edx",$acc); # 11 + + &movz ($acc,&BP(-128,$tbl,$key,1)); # 7 + &movz ($key,&HB("ebx")); # 13 + &shl ($acc,24); # 7 + &or ("ecx",$acc); # 7 + &movz ($acc,&BP(-128,$tbl,$key,1)); # 13 + &movz ($key,&LB("eax")); # 6 + &shl ($acc,8); # 13 + &movd ("eax","mm2"); # 3, 2, 5, 4 + &or ("ecx",$acc); # 13 + + &movz ($acc,&BP(-128,$tbl,$key,1)); # 6 + &movz ($key,&LB("ebx")); # 12 + &shl ($acc,16); # 6 + &movd ("ebx","mm6"); # 9, 8,15,14 + &movd ("mm0","ecx"); # t[0] collected + &movz ("ecx",&BP(-128,$tbl,$key,1)); # 12 + &movz ($key,&LB("eax")); # 4 + &or ("ecx",$acc); # 12 + + &movz ($acc,&BP(-128,$tbl,$key,1)); # 4 + &movz ($key,&LB("ebx")); # 14 + &or ("edx",$acc); # 4 + &movz ($acc,&BP(-128,$tbl,$key,1)); # 14 + &movz ($key,&HB("eax")); # 5 + &shl ($acc,16); # 14 + &shr ("eax",16); # 3, 2 + &or ("edx",$acc); # 14 + + &movz ($acc,&BP(-128,$tbl,$key,1)); # 5 + &movz ($key,&HB("ebx")); # 15 + &shr ("ebx",16); # 9, 8 + &shl ($acc,8); # 5 + &movd ("mm1","edx"); # t[1] collected + &movz ("edx",&BP(-128,$tbl,$key,1)); # 15 + &movz ($key,&HB("ebx")); # 9 + &shl ("edx",24); # 15 + &and ("ebx",0xff); # 8 + &or ("edx",$acc); # 15 + + &punpckldq ("mm0","mm1"); # t[0,1] collected + + &movz ($acc,&BP(-128,$tbl,$key,1)); # 9 + &movz ($key,&LB("eax")); # 2 + &shl ($acc,8); # 9 + &movz ("eax",&HB("eax")); # 3 + &movz ("ebx",&BP(-128,$tbl,"ebx",1)); # 8 + &or ("ecx",$acc); # 9 + &movz ($acc,&BP(-128,$tbl,$key,1)); # 2 + &or ("edx","ebx"); # 8 + &shl ($acc,16); # 2 + &movz ("eax",&BP(-128,$tbl,"eax",1)); # 3 + &or ("edx",$acc); # 2 + &shl ("eax",24); # 3 + &or ("ecx","eax"); # 3 + &mov ($key,$__key); + &movd ("mm4","edx"); # t[2] collected + &movd ("mm5","ecx"); # t[3] collected + + &punpckldq ("mm4","mm5"); # t[2,3] collected +} + + if (!$x86only) { +&function_begin_B("_sse_AES_decrypt_compact"); + &pxor ("mm0",&QWP(0,$key)); # 7, 6, 5, 4, 3, 2, 1, 0 + &pxor ("mm4",&QWP(8,$key)); # 15,14,13,12,11,10, 9, 8 + + # note that caller is expected to allocate stack frame for me! + &mov ($acc,&DWP(240,$key)); # load key->rounds + &lea ($acc,&DWP(-2,$acc,$acc)); + &lea ($acc,&DWP(0,$key,$acc,8)); + &mov ($__end,$acc); # end of key schedule + + &mov ($s0,0x1b1b1b1b); # magic constant + &mov (&DWP(8,"esp"),$s0); + &mov (&DWP(12,"esp"),$s0); + + # prefetch Td4 + &mov ($s0,&DWP(0-128,$tbl)); + &mov ($s1,&DWP(32-128,$tbl)); + &mov ($s2,&DWP(64-128,$tbl)); + &mov ($s3,&DWP(96-128,$tbl)); + &mov ($s0,&DWP(128-128,$tbl)); + &mov ($s1,&DWP(160-128,$tbl)); + &mov ($s2,&DWP(192-128,$tbl)); + &mov ($s3,&DWP(224-128,$tbl)); + + &set_label("loop",16); + &sse_deccompact(); + &add ($key,16); + &cmp ($key,$__end); + &ja (&label("out")); + + # ROTATE(x^y,N) == ROTATE(x,N)^ROTATE(y,N) + &movq ("mm3","mm0"); &movq ("mm7","mm4"); + &movq ("mm2","mm0",1); &movq ("mm6","mm4",1); + &movq ("mm1","mm0"); &movq ("mm5","mm4"); + &pshufw ("mm0","mm0",0xb1); &pshufw ("mm4","mm4",0xb1);# = ROTATE(tp0,16) + &pslld ("mm2",8); &pslld ("mm6",8); + &psrld ("mm3",8); &psrld ("mm7",8); + &pxor ("mm0","mm2"); &pxor ("mm4","mm6"); # ^= tp0<<8 + &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= tp0>>8 + &pslld ("mm2",16); &pslld ("mm6",16); + &psrld ("mm3",16); &psrld ("mm7",16); + &pxor ("mm0","mm2"); &pxor ("mm4","mm6"); # ^= tp0<<24 + &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= tp0>>24 + + &movq ("mm3",&QWP(8,"esp")); + &pxor ("mm2","mm2"); &pxor ("mm6","mm6"); + &pcmpgtb("mm2","mm1"); &pcmpgtb("mm6","mm5"); + &pand ("mm2","mm3"); &pand ("mm6","mm3"); + &paddb ("mm1","mm1"); &paddb ("mm5","mm5"); + &pxor ("mm1","mm2"); &pxor ("mm5","mm6"); # tp2 + &movq ("mm3","mm1"); &movq ("mm7","mm5"); + &movq ("mm2","mm1"); &movq ("mm6","mm5"); + &pxor ("mm0","mm1"); &pxor ("mm4","mm5"); # ^= tp2 + &pslld ("mm3",24); &pslld ("mm7",24); + &psrld ("mm2",8); &psrld ("mm6",8); + &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= tp2<<24 + &pxor ("mm0","mm2"); &pxor ("mm4","mm6"); # ^= tp2>>8 + + &movq ("mm2",&QWP(8,"esp")); + &pxor ("mm3","mm3"); &pxor ("mm7","mm7"); + &pcmpgtb("mm3","mm1"); &pcmpgtb("mm7","mm5"); + &pand ("mm3","mm2"); &pand ("mm7","mm2"); + &paddb ("mm1","mm1"); &paddb ("mm5","mm5"); + &pxor ("mm1","mm3"); &pxor ("mm5","mm7"); # tp4 + &pshufw ("mm3","mm1",0xb1); &pshufw ("mm7","mm5",0xb1); + &pxor ("mm0","mm1"); &pxor ("mm4","mm5"); # ^= tp4 + &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= ROTATE(tp4,16) + + &pxor ("mm3","mm3"); &pxor ("mm7","mm7"); + &pcmpgtb("mm3","mm1"); &pcmpgtb("mm7","mm5"); + &pand ("mm3","mm2"); &pand ("mm7","mm2"); + &paddb ("mm1","mm1"); &paddb ("mm5","mm5"); + &pxor ("mm1","mm3"); &pxor ("mm5","mm7"); # tp8 + &pxor ("mm0","mm1"); &pxor ("mm4","mm5"); # ^= tp8 + &movq ("mm3","mm1"); &movq ("mm7","mm5"); + &pshufw ("mm2","mm1",0xb1); &pshufw ("mm6","mm5",0xb1); + &pxor ("mm0","mm2"); &pxor ("mm4","mm6"); # ^= ROTATE(tp8,16) + &pslld ("mm1",8); &pslld ("mm5",8); + &psrld ("mm3",8); &psrld ("mm7",8); + &movq ("mm2",&QWP(0,$key)); &movq ("mm6",&QWP(8,$key)); + &pxor ("mm0","mm1"); &pxor ("mm4","mm5"); # ^= tp8<<8 + &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= tp8>>8 + &mov ($s0,&DWP(0-128,$tbl)); + &pslld ("mm1",16); &pslld ("mm5",16); + &mov ($s1,&DWP(64-128,$tbl)); + &psrld ("mm3",16); &psrld ("mm7",16); + &mov ($s2,&DWP(128-128,$tbl)); + &pxor ("mm0","mm1"); &pxor ("mm4","mm5"); # ^= tp8<<24 + &mov ($s3,&DWP(192-128,$tbl)); + &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= tp8>>24 + + &pxor ("mm0","mm2"); &pxor ("mm4","mm6"); + &jmp (&label("loop")); + + &set_label("out",16); + &pxor ("mm0",&QWP(0,$key)); + &pxor ("mm4",&QWP(8,$key)); + + &ret (); +&function_end_B("_sse_AES_decrypt_compact"); + } + +###################################################################### +# Vanilla block function. +###################################################################### + +sub decstep() +{ my ($i,$td,@s) = @_; + my $tmp = $key; + my $out = $i==3?$s[0]:$acc; + + # no instructions are reordered, as performance appears + # optimal... or rather that all attempts to reorder didn't + # result in better performance [which by the way is not a + # bit lower than encryption]. + if($i==3) { &mov ($key,$__key); } + else { &mov ($out,$s[0]); } + &and ($out,0xFF); + &mov ($out,&DWP(0,$td,$out,8)); + + if ($i==3) { $tmp=$s[1]; } + &movz ($tmp,&HB($s[1])); + &xor ($out,&DWP(3,$td,$tmp,8)); + + if ($i==3) { $tmp=$s[2]; &mov ($s[1],$acc); } + else { &mov ($tmp,$s[2]); } + &shr ($tmp,16); + &and ($tmp,0xFF); + &xor ($out,&DWP(2,$td,$tmp,8)); + + if ($i==3) { $tmp=$s[3]; &mov ($s[2],$__s1); } + else { &mov ($tmp,$s[3]); } + &shr ($tmp,24); + &xor ($out,&DWP(1,$td,$tmp,8)); + if ($i<2) { &mov (&DWP(4+4*$i,"esp"),$out); } + if ($i==3) { &mov ($s[3],$__s0); } + &comment(); +} + +sub declast() +{ my ($i,$td,@s)=@_; + my $tmp = $key; + my $out = $i==3?$s[0]:$acc; + + if($i==0) { &lea ($td,&DWP(2048+128,$td)); + &mov ($tmp,&DWP(0-128,$td)); + &mov ($acc,&DWP(32-128,$td)); + &mov ($tmp,&DWP(64-128,$td)); + &mov ($acc,&DWP(96-128,$td)); + &mov ($tmp,&DWP(128-128,$td)); + &mov ($acc,&DWP(160-128,$td)); + &mov ($tmp,&DWP(192-128,$td)); + &mov ($acc,&DWP(224-128,$td)); + &lea ($td,&DWP(-128,$td)); } + if($i==3) { &mov ($key,$__key); } + else { &mov ($out,$s[0]); } + &and ($out,0xFF); + &movz ($out,&BP(0,$td,$out,1)); + + if ($i==3) { $tmp=$s[1]; } + &movz ($tmp,&HB($s[1])); + &movz ($tmp,&BP(0,$td,$tmp,1)); + &shl ($tmp,8); + &xor ($out,$tmp); + + if ($i==3) { $tmp=$s[2]; &mov ($s[1],$acc); } + else { mov ($tmp,$s[2]); } + &shr ($tmp,16); + &and ($tmp,0xFF); + &movz ($tmp,&BP(0,$td,$tmp,1)); + &shl ($tmp,16); + &xor ($out,$tmp); + + if ($i==3) { $tmp=$s[3]; &mov ($s[2],$__s1); } + else { &mov ($tmp,$s[3]); } + &shr ($tmp,24); + &movz ($tmp,&BP(0,$td,$tmp,1)); + &shl ($tmp,24); + &xor ($out,$tmp); + if ($i<2) { &mov (&DWP(4+4*$i,"esp"),$out); } + if ($i==3) { &mov ($s[3],$__s0); + &lea ($td,&DWP(-2048,$td)); } +} + +&function_begin_B("_x86_AES_decrypt"); + # note that caller is expected to allocate stack frame for me! + &mov ($__key,$key); # save key + + &xor ($s0,&DWP(0,$key)); # xor with key + &xor ($s1,&DWP(4,$key)); + &xor ($s2,&DWP(8,$key)); + &xor ($s3,&DWP(12,$key)); + + &mov ($acc,&DWP(240,$key)); # load key->rounds + + if ($small_footprint) { + &lea ($acc,&DWP(-2,$acc,$acc)); + &lea ($acc,&DWP(0,$key,$acc,8)); + &mov ($__end,$acc); # end of key schedule + &set_label("loop",16); + &decstep(0,$tbl,$s0,$s3,$s2,$s1); + &decstep(1,$tbl,$s1,$s0,$s3,$s2); + &decstep(2,$tbl,$s2,$s1,$s0,$s3); + &decstep(3,$tbl,$s3,$s2,$s1,$s0); + &add ($key,16); # advance rd_key + &xor ($s0,&DWP(0,$key)); + &xor ($s1,&DWP(4,$key)); + &xor ($s2,&DWP(8,$key)); + &xor ($s3,&DWP(12,$key)); + &cmp ($key,$__end); + &mov ($__key,$key); + &jb (&label("loop")); + } + else { + &cmp ($acc,10); + &jle (&label("10rounds")); + &cmp ($acc,12); + &jle (&label("12rounds")); + + &set_label("14rounds",4); + for ($i=1;$i<3;$i++) { + &decstep(0,$tbl,$s0,$s3,$s2,$s1); + &decstep(1,$tbl,$s1,$s0,$s3,$s2); + &decstep(2,$tbl,$s2,$s1,$s0,$s3); + &decstep(3,$tbl,$s3,$s2,$s1,$s0); + &xor ($s0,&DWP(16*$i+0,$key)); + &xor ($s1,&DWP(16*$i+4,$key)); + &xor ($s2,&DWP(16*$i+8,$key)); + &xor ($s3,&DWP(16*$i+12,$key)); + } + &add ($key,32); + &mov ($__key,$key); # advance rd_key + &set_label("12rounds",4); + for ($i=1;$i<3;$i++) { + &decstep(0,$tbl,$s0,$s3,$s2,$s1); + &decstep(1,$tbl,$s1,$s0,$s3,$s2); + &decstep(2,$tbl,$s2,$s1,$s0,$s3); + &decstep(3,$tbl,$s3,$s2,$s1,$s0); + &xor ($s0,&DWP(16*$i+0,$key)); + &xor ($s1,&DWP(16*$i+4,$key)); + &xor ($s2,&DWP(16*$i+8,$key)); + &xor ($s3,&DWP(16*$i+12,$key)); + } + &add ($key,32); + &mov ($__key,$key); # advance rd_key + &set_label("10rounds",4); + for ($i=1;$i<10;$i++) { + &decstep(0,$tbl,$s0,$s3,$s2,$s1); + &decstep(1,$tbl,$s1,$s0,$s3,$s2); + &decstep(2,$tbl,$s2,$s1,$s0,$s3); + &decstep(3,$tbl,$s3,$s2,$s1,$s0); + &xor ($s0,&DWP(16*$i+0,$key)); + &xor ($s1,&DWP(16*$i+4,$key)); + &xor ($s2,&DWP(16*$i+8,$key)); + &xor ($s3,&DWP(16*$i+12,$key)); + } + } + + &declast(0,$tbl,$s0,$s3,$s2,$s1); + &declast(1,$tbl,$s1,$s0,$s3,$s2); + &declast(2,$tbl,$s2,$s1,$s0,$s3); + &declast(3,$tbl,$s3,$s2,$s1,$s0); + + &add ($key,$small_footprint?16:160); + &xor ($s0,&DWP(0,$key)); + &xor ($s1,&DWP(4,$key)); + &xor ($s2,&DWP(8,$key)); + &xor ($s3,&DWP(12,$key)); + + &ret (); + +&set_label("AES_Td",64); # Yes! I keep it in the code segment! + &_data_word(0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a); + &_data_word(0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b); + &_data_word(0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5); + &_data_word(0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5); + &_data_word(0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d); + &_data_word(0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b); + &_data_word(0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295); + &_data_word(0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e); + &_data_word(0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927); + &_data_word(0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d); + &_data_word(0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362); + &_data_word(0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9); + &_data_word(0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52); + &_data_word(0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566); + &_data_word(0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3); + &_data_word(0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed); + &_data_word(0x2b1ccf8a, 0x92b479a7, 0xf0f207f3, 0xa1e2694e); + &_data_word(0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4); + &_data_word(0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4); + &_data_word(0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd); + &_data_word(0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d); + &_data_word(0xb58d5491, 0x055dc471, 0x6fd40604, 0xff155060); + &_data_word(0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967); + &_data_word(0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879); + &_data_word(0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000); + &_data_word(0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c); + &_data_word(0xfbff0efd, 0x5638850f, 0x1ed5ae3d, 0x27392d36); + &_data_word(0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624); + &_data_word(0xb1670a0c, 0x0fe75793, 0xd296eeb4, 0x9e919b1b); + &_data_word(0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c); + &_data_word(0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12); + &_data_word(0x0b0d090e, 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14); + &_data_word(0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3); + &_data_word(0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b); + &_data_word(0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8); + &_data_word(0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684); + &_data_word(0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7); + &_data_word(0x4b2f9e1d, 0xf330b2dc, 0xec52860d, 0xd0e3c177); + &_data_word(0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947); + &_data_word(0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322); + &_data_word(0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498); + &_data_word(0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f); + &_data_word(0xe49d3a2c, 0x0d927850, 0x9bcc5f6a, 0x62467e54); + &_data_word(0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382); + &_data_word(0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf); + &_data_word(0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb); + &_data_word(0x097826cd, 0xf418596e, 0x01b79aec, 0xa89a4f83); + &_data_word(0x656e95e6, 0x7ee6ffaa, 0x08cfbc21, 0xe6e815ef); + &_data_word(0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029); + &_data_word(0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235); + &_data_word(0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733); + &_data_word(0x4a9804f1, 0xf7daec41, 0x0e50cd7f, 0x2ff69117); + &_data_word(0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4); + &_data_word(0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546); + &_data_word(0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb); + &_data_word(0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d); + &_data_word(0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb); + &_data_word(0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a); + &_data_word(0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773); + &_data_word(0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478); + &_data_word(0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2); + &_data_word(0x72c31d16, 0x0c25e2bc, 0x8b493c28, 0x41950dff); + &_data_word(0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664); + &_data_word(0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0); + +#Td4: # four copies of Td4 to choose from to avoid L1 aliasing + &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38); + &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb); + &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87); + &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb); + &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d); + &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e); + &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2); + &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25); + &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16); + &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92); + &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda); + &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84); + &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a); + &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06); + &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02); + &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b); + &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea); + &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73); + &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85); + &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e); + &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89); + &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b); + &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20); + &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4); + &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31); + &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f); + &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d); + &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef); + &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0); + &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61); + &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26); + &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d); + + &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38); + &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb); + &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87); + &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb); + &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d); + &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e); + &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2); + &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25); + &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16); + &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92); + &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda); + &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84); + &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a); + &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06); + &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02); + &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b); + &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea); + &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73); + &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85); + &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e); + &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89); + &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b); + &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20); + &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4); + &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31); + &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f); + &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d); + &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef); + &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0); + &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61); + &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26); + &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d); + + &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38); + &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb); + &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87); + &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb); + &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d); + &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e); + &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2); + &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25); + &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16); + &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92); + &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda); + &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84); + &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a); + &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06); + &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02); + &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b); + &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea); + &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73); + &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85); + &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e); + &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89); + &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b); + &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20); + &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4); + &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31); + &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f); + &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d); + &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef); + &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0); + &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61); + &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26); + &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d); + + &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38); + &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb); + &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87); + &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb); + &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d); + &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e); + &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2); + &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25); + &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16); + &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92); + &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda); + &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84); + &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a); + &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06); + &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02); + &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b); + &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea); + &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73); + &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85); + &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e); + &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89); + &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b); + &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20); + &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4); + &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31); + &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f); + &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d); + &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef); + &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0); + &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61); + &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26); + &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d); +&function_end_B("_x86_AES_decrypt"); + +# void AES_decrypt (const void *inp,void *out,const AES_KEY *key); +&function_begin("AES_decrypt"); + &mov ($acc,&wparam(0)); # load inp + &mov ($key,&wparam(2)); # load key + + &mov ($s0,"esp"); + &sub ("esp",36); + &and ("esp",-64); # align to cache-line + + # place stack frame just "above" the key schedule + &lea ($s1,&DWP(-64-63,$key)); + &sub ($s1,"esp"); + &neg ($s1); + &and ($s1,0x3C0); # modulo 1024, but aligned to cache-line + &sub ("esp",$s1); + &add ("esp",4); # 4 is reserved for caller's return address + &mov ($_esp,$s0); # save stack pointer + + &call (&label("pic_point")); # make it PIC! + &set_label("pic_point"); + &blindpop($tbl); + &picmeup($s0,"OPENSSL_ia32cap_P",$tbl,&label("pic_point")) if(!$x86only); + &lea ($tbl,&DWP(&label("AES_Td")."-".&label("pic_point"),$tbl)); + + # pick Td4 copy which can't "overlap" with stack frame or key schedule + &lea ($s1,&DWP(768-4,"esp")); + &sub ($s1,$tbl); + &and ($s1,0x300); + &lea ($tbl,&DWP(2048+128,$tbl,$s1)); + + if (!$x86only) { + &bt (&DWP(0,$s0),25); # check for SSE bit + &jnc (&label("x86")); + + &movq ("mm0",&QWP(0,$acc)); + &movq ("mm4",&QWP(8,$acc)); + &call ("_sse_AES_decrypt_compact"); + &mov ("esp",$_esp); # restore stack pointer + &mov ($acc,&wparam(1)); # load out + &movq (&QWP(0,$acc),"mm0"); # write output data + &movq (&QWP(8,$acc),"mm4"); + &emms (); + &function_end_A(); + } + &set_label("x86",16); + &mov ($_tbl,$tbl); + &mov ($s0,&DWP(0,$acc)); # load input data + &mov ($s1,&DWP(4,$acc)); + &mov ($s2,&DWP(8,$acc)); + &mov ($s3,&DWP(12,$acc)); + &call ("_x86_AES_decrypt_compact"); + &mov ("esp",$_esp); # restore stack pointer + &mov ($acc,&wparam(1)); # load out + &mov (&DWP(0,$acc),$s0); # write output data + &mov (&DWP(4,$acc),$s1); + &mov (&DWP(8,$acc),$s2); + &mov (&DWP(12,$acc),$s3); +&function_end("AES_decrypt"); + +# void AES_cbc_encrypt (const void char *inp, unsigned char *out, +# size_t length, const AES_KEY *key, +# unsigned char *ivp,const int enc); +{ +# stack frame layout +# -4(%esp) # return address 0(%esp) +# 0(%esp) # s0 backing store 4(%esp) +# 4(%esp) # s1 backing store 8(%esp) +# 8(%esp) # s2 backing store 12(%esp) +# 12(%esp) # s3 backing store 16(%esp) +# 16(%esp) # key backup 20(%esp) +# 20(%esp) # end of key schedule 24(%esp) +# 24(%esp) # %ebp backup 28(%esp) +# 28(%esp) # %esp backup +my $_inp=&DWP(32,"esp"); # copy of wparam(0) +my $_out=&DWP(36,"esp"); # copy of wparam(1) +my $_len=&DWP(40,"esp"); # copy of wparam(2) +my $_key=&DWP(44,"esp"); # copy of wparam(3) +my $_ivp=&DWP(48,"esp"); # copy of wparam(4) +my $_tmp=&DWP(52,"esp"); # volatile variable +# +my $ivec=&DWP(60,"esp"); # ivec[16] +my $aes_key=&DWP(76,"esp"); # copy of aes_key +my $mark=&DWP(76+240,"esp"); # copy of aes_key->rounds + +&function_begin("AES_cbc_encrypt"); + &mov ($s2 eq "ecx"? $s2 : "",&wparam(2)); # load len + &cmp ($s2,0); + &je (&label("drop_out")); + + &call (&label("pic_point")); # make it PIC! + &set_label("pic_point"); + &blindpop($tbl); + &picmeup($s0,"OPENSSL_ia32cap_P",$tbl,&label("pic_point")) if(!$x86only); + + &cmp (&wparam(5),0); + &lea ($tbl,&DWP(&label("AES_Te")."-".&label("pic_point"),$tbl)); + &jne (&label("picked_te")); + &lea ($tbl,&DWP(&label("AES_Td")."-".&label("AES_Te"),$tbl)); + &set_label("picked_te"); + + # one can argue if this is required + &pushf (); + &cld (); + + &cmp ($s2,$speed_limit); + &jb (&label("slow_way")); + &test ($s2,15); + &jnz (&label("slow_way")); + if (!$x86only) { + &bt (&DWP(0,$s0),28); # check for hyper-threading bit + &jc (&label("slow_way")); + } + # pre-allocate aligned stack frame... + &lea ($acc,&DWP(-80-244,"esp")); + &and ($acc,-64); + + # ... and make sure it doesn't alias with $tbl modulo 4096 + &mov ($s0,$tbl); + &lea ($s1,&DWP(2048+256,$tbl)); + &mov ($s3,$acc); + &and ($s0,0xfff); # s = %ebp&0xfff + &and ($s1,0xfff); # e = (%ebp+2048+256)&0xfff + &and ($s3,0xfff); # p = %esp&0xfff + + &cmp ($s3,$s1); # if (p>=e) %esp =- (p-e); + &jb (&label("tbl_break_out")); + &sub ($s3,$s1); + &sub ($acc,$s3); + &jmp (&label("tbl_ok")); + &set_label("tbl_break_out",4); # else %esp -= (p-s)&0xfff + framesz; + &sub ($s3,$s0); + &and ($s3,0xfff); + &add ($s3,384); + &sub ($acc,$s3); + &set_label("tbl_ok",4); + + &lea ($s3,&wparam(0)); # obtain pointer to parameter block + &exch ("esp",$acc); # allocate stack frame + &add ("esp",4); # reserve for return address! + &mov ($_tbl,$tbl); # save %ebp + &mov ($_esp,$acc); # save %esp + + &mov ($s0,&DWP(0,$s3)); # load inp + &mov ($s1,&DWP(4,$s3)); # load out + #&mov ($s2,&DWP(8,$s3)); # load len + &mov ($key,&DWP(12,$s3)); # load key + &mov ($acc,&DWP(16,$s3)); # load ivp + &mov ($s3,&DWP(20,$s3)); # load enc flag + + &mov ($_inp,$s0); # save copy of inp + &mov ($_out,$s1); # save copy of out + &mov ($_len,$s2); # save copy of len + &mov ($_key,$key); # save copy of key + &mov ($_ivp,$acc); # save copy of ivp + + &mov ($mark,0); # copy of aes_key->rounds = 0; + # do we copy key schedule to stack? + &mov ($s1 eq "ebx" ? $s1 : "",$key); + &mov ($s2 eq "ecx" ? $s2 : "",244/4); + &sub ($s1,$tbl); + &mov ("esi",$key); + &and ($s1,0xfff); + &lea ("edi",$aes_key); + &cmp ($s1,2048+256); + &jb (&label("do_copy")); + &cmp ($s1,4096-244); + &jb (&label("skip_copy")); + &set_label("do_copy",4); + &mov ($_key,"edi"); + &data_word(0xA5F3F689); # rep movsd + &set_label("skip_copy"); + + &mov ($key,16); + &set_label("prefetch_tbl",4); + &mov ($s0,&DWP(0,$tbl)); + &mov ($s1,&DWP(32,$tbl)); + &mov ($s2,&DWP(64,$tbl)); + &mov ($acc,&DWP(96,$tbl)); + &lea ($tbl,&DWP(128,$tbl)); + &sub ($key,1); + &jnz (&label("prefetch_tbl")); + &sub ($tbl,2048); + + &mov ($acc,$_inp); + &mov ($key,$_ivp); + + &cmp ($s3,0); + &je (&label("fast_decrypt")); + +#----------------------------- ENCRYPT -----------------------------# + &mov ($s0,&DWP(0,$key)); # load iv + &mov ($s1,&DWP(4,$key)); + + &set_label("fast_enc_loop",16); + &mov ($s2,&DWP(8,$key)); + &mov ($s3,&DWP(12,$key)); + + &xor ($s0,&DWP(0,$acc)); # xor input data + &xor ($s1,&DWP(4,$acc)); + &xor ($s2,&DWP(8,$acc)); + &xor ($s3,&DWP(12,$acc)); + + &mov ($key,$_key); # load key + &call ("_x86_AES_encrypt"); + + &mov ($acc,$_inp); # load inp + &mov ($key,$_out); # load out + + &mov (&DWP(0,$key),$s0); # save output data + &mov (&DWP(4,$key),$s1); + &mov (&DWP(8,$key),$s2); + &mov (&DWP(12,$key),$s3); + + &lea ($acc,&DWP(16,$acc)); # advance inp + &mov ($s2,$_len); # load len + &mov ($_inp,$acc); # save inp + &lea ($s3,&DWP(16,$key)); # advance out + &mov ($_out,$s3); # save out + &sub ($s2,16); # decrease len + &mov ($_len,$s2); # save len + &jnz (&label("fast_enc_loop")); + &mov ($acc,$_ivp); # load ivp + &mov ($s2,&DWP(8,$key)); # restore last 2 dwords + &mov ($s3,&DWP(12,$key)); + &mov (&DWP(0,$acc),$s0); # save ivec + &mov (&DWP(4,$acc),$s1); + &mov (&DWP(8,$acc),$s2); + &mov (&DWP(12,$acc),$s3); + + &cmp ($mark,0); # was the key schedule copied? + &mov ("edi",$_key); + &je (&label("skip_ezero")); + # zero copy of key schedule + &mov ("ecx",240/4); + &xor ("eax","eax"); + &align (4); + &data_word(0xABF3F689); # rep stosd + &set_label("skip_ezero"); + &mov ("esp",$_esp); + &popf (); + &set_label("drop_out"); + &function_end_A(); + &pushf (); # kludge, never executed + +#----------------------------- DECRYPT -----------------------------# +&set_label("fast_decrypt",16); + + &cmp ($acc,$_out); + &je (&label("fast_dec_in_place")); # in-place processing... + + &mov ($_tmp,$key); + + &align (4); + &set_label("fast_dec_loop",16); + &mov ($s0,&DWP(0,$acc)); # read input + &mov ($s1,&DWP(4,$acc)); + &mov ($s2,&DWP(8,$acc)); + &mov ($s3,&DWP(12,$acc)); + + &mov ($key,$_key); # load key + &call ("_x86_AES_decrypt"); + + &mov ($key,$_tmp); # load ivp + &mov ($acc,$_len); # load len + &xor ($s0,&DWP(0,$key)); # xor iv + &xor ($s1,&DWP(4,$key)); + &xor ($s2,&DWP(8,$key)); + &xor ($s3,&DWP(12,$key)); + + &mov ($key,$_out); # load out + &mov ($acc,$_inp); # load inp + + &mov (&DWP(0,$key),$s0); # write output + &mov (&DWP(4,$key),$s1); + &mov (&DWP(8,$key),$s2); + &mov (&DWP(12,$key),$s3); + + &mov ($s2,$_len); # load len + &mov ($_tmp,$acc); # save ivp + &lea ($acc,&DWP(16,$acc)); # advance inp + &mov ($_inp,$acc); # save inp + &lea ($key,&DWP(16,$key)); # advance out + &mov ($_out,$key); # save out + &sub ($s2,16); # decrease len + &mov ($_len,$s2); # save len + &jnz (&label("fast_dec_loop")); + &mov ($key,$_tmp); # load temp ivp + &mov ($acc,$_ivp); # load user ivp + &mov ($s0,&DWP(0,$key)); # load iv + &mov ($s1,&DWP(4,$key)); + &mov ($s2,&DWP(8,$key)); + &mov ($s3,&DWP(12,$key)); + &mov (&DWP(0,$acc),$s0); # copy back to user + &mov (&DWP(4,$acc),$s1); + &mov (&DWP(8,$acc),$s2); + &mov (&DWP(12,$acc),$s3); + &jmp (&label("fast_dec_out")); + + &set_label("fast_dec_in_place",16); + &set_label("fast_dec_in_place_loop"); + &mov ($s0,&DWP(0,$acc)); # read input + &mov ($s1,&DWP(4,$acc)); + &mov ($s2,&DWP(8,$acc)); + &mov ($s3,&DWP(12,$acc)); + + &lea ($key,$ivec); + &mov (&DWP(0,$key),$s0); # copy to temp + &mov (&DWP(4,$key),$s1); + &mov (&DWP(8,$key),$s2); + &mov (&DWP(12,$key),$s3); + + &mov ($key,$_key); # load key + &call ("_x86_AES_decrypt"); + + &mov ($key,$_ivp); # load ivp + &mov ($acc,$_out); # load out + &xor ($s0,&DWP(0,$key)); # xor iv + &xor ($s1,&DWP(4,$key)); + &xor ($s2,&DWP(8,$key)); + &xor ($s3,&DWP(12,$key)); + + &mov (&DWP(0,$acc),$s0); # write output + &mov (&DWP(4,$acc),$s1); + &mov (&DWP(8,$acc),$s2); + &mov (&DWP(12,$acc),$s3); + + &lea ($acc,&DWP(16,$acc)); # advance out + &mov ($_out,$acc); # save out + + &lea ($acc,$ivec); + &mov ($s0,&DWP(0,$acc)); # read temp + &mov ($s1,&DWP(4,$acc)); + &mov ($s2,&DWP(8,$acc)); + &mov ($s3,&DWP(12,$acc)); + + &mov (&DWP(0,$key),$s0); # copy iv + &mov (&DWP(4,$key),$s1); + &mov (&DWP(8,$key),$s2); + &mov (&DWP(12,$key),$s3); + + &mov ($acc,$_inp); # load inp + &mov ($s2,$_len); # load len + &lea ($acc,&DWP(16,$acc)); # advance inp + &mov ($_inp,$acc); # save inp + &sub ($s2,16); # decrease len + &mov ($_len,$s2); # save len + &jnz (&label("fast_dec_in_place_loop")); + + &set_label("fast_dec_out",4); + &cmp ($mark,0); # was the key schedule copied? + &mov ("edi",$_key); + &je (&label("skip_dzero")); + # zero copy of key schedule + &mov ("ecx",240/4); + &xor ("eax","eax"); + &align (4); + &data_word(0xABF3F689); # rep stosd + &set_label("skip_dzero"); + &mov ("esp",$_esp); + &popf (); + &function_end_A(); + &pushf (); # kludge, never executed + +#--------------------------- SLOW ROUTINE ---------------------------# +&set_label("slow_way",16); + + &mov ($s0,&DWP(0,$s0)) if (!$x86only);# load OPENSSL_ia32cap + &mov ($key,&wparam(3)); # load key + + # pre-allocate aligned stack frame... + &lea ($acc,&DWP(-80,"esp")); + &and ($acc,-64); + + # ... and make sure it doesn't alias with $key modulo 1024 + &lea ($s1,&DWP(-80-63,$key)); + &sub ($s1,$acc); + &neg ($s1); + &and ($s1,0x3C0); # modulo 1024, but aligned to cache-line + &sub ($acc,$s1); + + # pick S-box copy which can't overlap with stack frame or $key + &lea ($s1,&DWP(768,$acc)); + &sub ($s1,$tbl); + &and ($s1,0x300); + &lea ($tbl,&DWP(2048+128,$tbl,$s1)); + + &lea ($s3,&wparam(0)); # pointer to parameter block + + &exch ("esp",$acc); + &add ("esp",4); # reserve for return address! + &mov ($_tbl,$tbl); # save %ebp + &mov ($_esp,$acc); # save %esp + &mov ($_tmp,$s0); # save OPENSSL_ia32cap + + &mov ($s0,&DWP(0,$s3)); # load inp + &mov ($s1,&DWP(4,$s3)); # load out + #&mov ($s2,&DWP(8,$s3)); # load len + #&mov ($key,&DWP(12,$s3)); # load key + &mov ($acc,&DWP(16,$s3)); # load ivp + &mov ($s3,&DWP(20,$s3)); # load enc flag + + &mov ($_inp,$s0); # save copy of inp + &mov ($_out,$s1); # save copy of out + &mov ($_len,$s2); # save copy of len + &mov ($_key,$key); # save copy of key + &mov ($_ivp,$acc); # save copy of ivp + + &mov ($key,$acc); + &mov ($acc,$s0); + + &cmp ($s3,0); + &je (&label("slow_decrypt")); + +#--------------------------- SLOW ENCRYPT ---------------------------# + &cmp ($s2,16); + &mov ($s3,$s1); + &jb (&label("slow_enc_tail")); + + if (!$x86only) { + &bt ($_tmp,25); # check for SSE bit + &jnc (&label("slow_enc_x86")); + + &movq ("mm0",&QWP(0,$key)); # load iv + &movq ("mm4",&QWP(8,$key)); + + &set_label("slow_enc_loop_sse",16); + &pxor ("mm0",&QWP(0,$acc)); # xor input data + &pxor ("mm4",&QWP(8,$acc)); + + &mov ($key,$_key); + &call ("_sse_AES_encrypt_compact"); + + &mov ($acc,$_inp); # load inp + &mov ($key,$_out); # load out + &mov ($s2,$_len); # load len + + &movq (&QWP(0,$key),"mm0"); # save output data + &movq (&QWP(8,$key),"mm4"); + + &lea ($acc,&DWP(16,$acc)); # advance inp + &mov ($_inp,$acc); # save inp + &lea ($s3,&DWP(16,$key)); # advance out + &mov ($_out,$s3); # save out + &sub ($s2,16); # decrease len + &cmp ($s2,16); + &mov ($_len,$s2); # save len + &jae (&label("slow_enc_loop_sse")); + &test ($s2,15); + &jnz (&label("slow_enc_tail")); + &mov ($acc,$_ivp); # load ivp + &movq (&QWP(0,$acc),"mm0"); # save ivec + &movq (&QWP(8,$acc),"mm4"); + &emms (); + &mov ("esp",$_esp); + &popf (); + &function_end_A(); + &pushf (); # kludge, never executed + } + &set_label("slow_enc_x86",16); + &mov ($s0,&DWP(0,$key)); # load iv + &mov ($s1,&DWP(4,$key)); + + &set_label("slow_enc_loop_x86",4); + &mov ($s2,&DWP(8,$key)); + &mov ($s3,&DWP(12,$key)); + + &xor ($s0,&DWP(0,$acc)); # xor input data + &xor ($s1,&DWP(4,$acc)); + &xor ($s2,&DWP(8,$acc)); + &xor ($s3,&DWP(12,$acc)); + + &mov ($key,$_key); # load key + &call ("_x86_AES_encrypt_compact"); + + &mov ($acc,$_inp); # load inp + &mov ($key,$_out); # load out + + &mov (&DWP(0,$key),$s0); # save output data + &mov (&DWP(4,$key),$s1); + &mov (&DWP(8,$key),$s2); + &mov (&DWP(12,$key),$s3); + + &mov ($s2,$_len); # load len + &lea ($acc,&DWP(16,$acc)); # advance inp + &mov ($_inp,$acc); # save inp + &lea ($s3,&DWP(16,$key)); # advance out + &mov ($_out,$s3); # save out + &sub ($s2,16); # decrease len + &cmp ($s2,16); + &mov ($_len,$s2); # save len + &jae (&label("slow_enc_loop_x86")); + &test ($s2,15); + &jnz (&label("slow_enc_tail")); + &mov ($acc,$_ivp); # load ivp + &mov ($s2,&DWP(8,$key)); # restore last dwords + &mov ($s3,&DWP(12,$key)); + &mov (&DWP(0,$acc),$s0); # save ivec + &mov (&DWP(4,$acc),$s1); + &mov (&DWP(8,$acc),$s2); + &mov (&DWP(12,$acc),$s3); + + &mov ("esp",$_esp); + &popf (); + &function_end_A(); + &pushf (); # kludge, never executed + + &set_label("slow_enc_tail",16); + &emms () if (!$x86only); + &mov ($key eq "edi"? $key:"",$s3); # load out to edi + &mov ($s1,16); + &sub ($s1,$s2); + &cmp ($key,$acc eq "esi"? $acc:""); # compare with inp + &je (&label("enc_in_place")); + &align (4); + &data_word(0xA4F3F689); # rep movsb # copy input + &jmp (&label("enc_skip_in_place")); + &set_label("enc_in_place"); + &lea ($key,&DWP(0,$key,$s2)); + &set_label("enc_skip_in_place"); + &mov ($s2,$s1); + &xor ($s0,$s0); + &align (4); + &data_word(0xAAF3F689); # rep stosb # zero tail + + &mov ($key,$_ivp); # restore ivp + &mov ($acc,$s3); # output as input + &mov ($s0,&DWP(0,$key)); + &mov ($s1,&DWP(4,$key)); + &mov ($_len,16); # len=16 + &jmp (&label("slow_enc_loop_x86")); # one more spin... + +#--------------------------- SLOW DECRYPT ---------------------------# +&set_label("slow_decrypt",16); + if (!$x86only) { + &bt ($_tmp,25); # check for SSE bit + &jnc (&label("slow_dec_loop_x86")); + + &set_label("slow_dec_loop_sse",4); + &movq ("mm0",&QWP(0,$acc)); # read input + &movq ("mm4",&QWP(8,$acc)); + + &mov ($key,$_key); + &call ("_sse_AES_decrypt_compact"); + + &mov ($acc,$_inp); # load inp + &lea ($s0,$ivec); + &mov ($s1,$_out); # load out + &mov ($s2,$_len); # load len + &mov ($key,$_ivp); # load ivp + + &movq ("mm1",&QWP(0,$acc)); # re-read input + &movq ("mm5",&QWP(8,$acc)); + + &pxor ("mm0",&QWP(0,$key)); # xor iv + &pxor ("mm4",&QWP(8,$key)); + + &movq (&QWP(0,$key),"mm1"); # copy input to iv + &movq (&QWP(8,$key),"mm5"); + + &sub ($s2,16); # decrease len + &jc (&label("slow_dec_partial_sse")); + + &movq (&QWP(0,$s1),"mm0"); # write output + &movq (&QWP(8,$s1),"mm4"); + + &lea ($s1,&DWP(16,$s1)); # advance out + &mov ($_out,$s1); # save out + &lea ($acc,&DWP(16,$acc)); # advance inp + &mov ($_inp,$acc); # save inp + &mov ($_len,$s2); # save len + &jnz (&label("slow_dec_loop_sse")); + &emms (); + &mov ("esp",$_esp); + &popf (); + &function_end_A(); + &pushf (); # kludge, never executed + + &set_label("slow_dec_partial_sse",16); + &movq (&QWP(0,$s0),"mm0"); # save output to temp + &movq (&QWP(8,$s0),"mm4"); + &emms (); + + &add ($s2 eq "ecx" ? "ecx":"",16); + &mov ("edi",$s1); # out + &mov ("esi",$s0); # temp + &align (4); + &data_word(0xA4F3F689); # rep movsb # copy partial output + + &mov ("esp",$_esp); + &popf (); + &function_end_A(); + &pushf (); # kludge, never executed + } + &set_label("slow_dec_loop_x86",16); + &mov ($s0,&DWP(0,$acc)); # read input + &mov ($s1,&DWP(4,$acc)); + &mov ($s2,&DWP(8,$acc)); + &mov ($s3,&DWP(12,$acc)); + + &lea ($key,$ivec); + &mov (&DWP(0,$key),$s0); # copy to temp + &mov (&DWP(4,$key),$s1); + &mov (&DWP(8,$key),$s2); + &mov (&DWP(12,$key),$s3); + + &mov ($key,$_key); # load key + &call ("_x86_AES_decrypt_compact"); + + &mov ($key,$_ivp); # load ivp + &mov ($acc,$_len); # load len + &xor ($s0,&DWP(0,$key)); # xor iv + &xor ($s1,&DWP(4,$key)); + &xor ($s2,&DWP(8,$key)); + &xor ($s3,&DWP(12,$key)); + + &sub ($acc,16); + &jc (&label("slow_dec_partial_x86")); + + &mov ($_len,$acc); # save len + &mov ($acc,$_out); # load out + + &mov (&DWP(0,$acc),$s0); # write output + &mov (&DWP(4,$acc),$s1); + &mov (&DWP(8,$acc),$s2); + &mov (&DWP(12,$acc),$s3); + + &lea ($acc,&DWP(16,$acc)); # advance out + &mov ($_out,$acc); # save out + + &lea ($acc,$ivec); + &mov ($s0,&DWP(0,$acc)); # read temp + &mov ($s1,&DWP(4,$acc)); + &mov ($s2,&DWP(8,$acc)); + &mov ($s3,&DWP(12,$acc)); + + &mov (&DWP(0,$key),$s0); # copy it to iv + &mov (&DWP(4,$key),$s1); + &mov (&DWP(8,$key),$s2); + &mov (&DWP(12,$key),$s3); + + &mov ($acc,$_inp); # load inp + &lea ($acc,&DWP(16,$acc)); # advance inp + &mov ($_inp,$acc); # save inp + &jnz (&label("slow_dec_loop_x86")); + &mov ("esp",$_esp); + &popf (); + &function_end_A(); + &pushf (); # kludge, never executed + + &set_label("slow_dec_partial_x86",16); + &lea ($acc,$ivec); + &mov (&DWP(0,$acc),$s0); # save output to temp + &mov (&DWP(4,$acc),$s1); + &mov (&DWP(8,$acc),$s2); + &mov (&DWP(12,$acc),$s3); + + &mov ($acc,$_inp); + &mov ($s0,&DWP(0,$acc)); # re-read input + &mov ($s1,&DWP(4,$acc)); + &mov ($s2,&DWP(8,$acc)); + &mov ($s3,&DWP(12,$acc)); + + &mov (&DWP(0,$key),$s0); # copy it to iv + &mov (&DWP(4,$key),$s1); + &mov (&DWP(8,$key),$s2); + &mov (&DWP(12,$key),$s3); + + &mov ("ecx",$_len); + &mov ("edi",$_out); + &lea ("esi",$ivec); + &align (4); + &data_word(0xA4F3F689); # rep movsb # copy partial output + + &mov ("esp",$_esp); + &popf (); +&function_end("AES_cbc_encrypt"); +} + +#------------------------------------------------------------------# + +sub enckey() +{ + &movz ("esi",&LB("edx")); # rk[i]>>0 + &movz ("ebx",&BP(-128,$tbl,"esi",1)); + &movz ("esi",&HB("edx")); # rk[i]>>8 + &shl ("ebx",24); + &xor ("eax","ebx"); + + &movz ("ebx",&BP(-128,$tbl,"esi",1)); + &shr ("edx",16); + &movz ("esi",&LB("edx")); # rk[i]>>16 + &xor ("eax","ebx"); + + &movz ("ebx",&BP(-128,$tbl,"esi",1)); + &movz ("esi",&HB("edx")); # rk[i]>>24 + &shl ("ebx",8); + &xor ("eax","ebx"); + + &movz ("ebx",&BP(-128,$tbl,"esi",1)); + &shl ("ebx",16); + &xor ("eax","ebx"); + + &xor ("eax",&DWP(1024-128,$tbl,"ecx",4)); # rcon +} + +&function_begin("_x86_AES_set_encrypt_key"); + &mov ("esi",&wparam(1)); # user supplied key + &mov ("edi",&wparam(3)); # private key schedule + + &test ("esi",-1); + &jz (&label("badpointer")); + &test ("edi",-1); + &jz (&label("badpointer")); + + &call (&label("pic_point")); + &set_label("pic_point"); + &blindpop($tbl); + &lea ($tbl,&DWP(&label("AES_Te")."-".&label("pic_point"),$tbl)); + &lea ($tbl,&DWP(2048+128,$tbl)); + + # prefetch Te4 + &mov ("eax",&DWP(0-128,$tbl)); + &mov ("ebx",&DWP(32-128,$tbl)); + &mov ("ecx",&DWP(64-128,$tbl)); + &mov ("edx",&DWP(96-128,$tbl)); + &mov ("eax",&DWP(128-128,$tbl)); + &mov ("ebx",&DWP(160-128,$tbl)); + &mov ("ecx",&DWP(192-128,$tbl)); + &mov ("edx",&DWP(224-128,$tbl)); + + &mov ("ecx",&wparam(2)); # number of bits in key + &cmp ("ecx",128); + &je (&label("10rounds")); + &cmp ("ecx",192); + &je (&label("12rounds")); + &cmp ("ecx",256); + &je (&label("14rounds")); + &mov ("eax",-2); # invalid number of bits + &jmp (&label("exit")); + + &set_label("10rounds"); + &mov ("eax",&DWP(0,"esi")); # copy first 4 dwords + &mov ("ebx",&DWP(4,"esi")); + &mov ("ecx",&DWP(8,"esi")); + &mov ("edx",&DWP(12,"esi")); + &mov (&DWP(0,"edi"),"eax"); + &mov (&DWP(4,"edi"),"ebx"); + &mov (&DWP(8,"edi"),"ecx"); + &mov (&DWP(12,"edi"),"edx"); + + &xor ("ecx","ecx"); + &jmp (&label("10shortcut")); + + &align (4); + &set_label("10loop"); + &mov ("eax",&DWP(0,"edi")); # rk[0] + &mov ("edx",&DWP(12,"edi")); # rk[3] + &set_label("10shortcut"); + &enckey (); + + &mov (&DWP(16,"edi"),"eax"); # rk[4] + &xor ("eax",&DWP(4,"edi")); + &mov (&DWP(20,"edi"),"eax"); # rk[5] + &xor ("eax",&DWP(8,"edi")); + &mov (&DWP(24,"edi"),"eax"); # rk[6] + &xor ("eax",&DWP(12,"edi")); + &mov (&DWP(28,"edi"),"eax"); # rk[7] + &inc ("ecx"); + &add ("edi",16); + &cmp ("ecx",10); + &jl (&label("10loop")); + + &mov (&DWP(80,"edi"),10); # setup number of rounds + &xor ("eax","eax"); + &jmp (&label("exit")); + + &set_label("12rounds"); + &mov ("eax",&DWP(0,"esi")); # copy first 6 dwords + &mov ("ebx",&DWP(4,"esi")); + &mov ("ecx",&DWP(8,"esi")); + &mov ("edx",&DWP(12,"esi")); + &mov (&DWP(0,"edi"),"eax"); + &mov (&DWP(4,"edi"),"ebx"); + &mov (&DWP(8,"edi"),"ecx"); + &mov (&DWP(12,"edi"),"edx"); + &mov ("ecx",&DWP(16,"esi")); + &mov ("edx",&DWP(20,"esi")); + &mov (&DWP(16,"edi"),"ecx"); + &mov (&DWP(20,"edi"),"edx"); + + &xor ("ecx","ecx"); + &jmp (&label("12shortcut")); + + &align (4); + &set_label("12loop"); + &mov ("eax",&DWP(0,"edi")); # rk[0] + &mov ("edx",&DWP(20,"edi")); # rk[5] + &set_label("12shortcut"); + &enckey (); + + &mov (&DWP(24,"edi"),"eax"); # rk[6] + &xor ("eax",&DWP(4,"edi")); + &mov (&DWP(28,"edi"),"eax"); # rk[7] + &xor ("eax",&DWP(8,"edi")); + &mov (&DWP(32,"edi"),"eax"); # rk[8] + &xor ("eax",&DWP(12,"edi")); + &mov (&DWP(36,"edi"),"eax"); # rk[9] + + &cmp ("ecx",7); + &je (&label("12break")); + &inc ("ecx"); + + &xor ("eax",&DWP(16,"edi")); + &mov (&DWP(40,"edi"),"eax"); # rk[10] + &xor ("eax",&DWP(20,"edi")); + &mov (&DWP(44,"edi"),"eax"); # rk[11] + + &add ("edi",24); + &jmp (&label("12loop")); + + &set_label("12break"); + &mov (&DWP(72,"edi"),12); # setup number of rounds + &xor ("eax","eax"); + &jmp (&label("exit")); + + &set_label("14rounds"); + &mov ("eax",&DWP(0,"esi")); # copy first 8 dwords + &mov ("ebx",&DWP(4,"esi")); + &mov ("ecx",&DWP(8,"esi")); + &mov ("edx",&DWP(12,"esi")); + &mov (&DWP(0,"edi"),"eax"); + &mov (&DWP(4,"edi"),"ebx"); + &mov (&DWP(8,"edi"),"ecx"); + &mov (&DWP(12,"edi"),"edx"); + &mov ("eax",&DWP(16,"esi")); + &mov ("ebx",&DWP(20,"esi")); + &mov ("ecx",&DWP(24,"esi")); + &mov ("edx",&DWP(28,"esi")); + &mov (&DWP(16,"edi"),"eax"); + &mov (&DWP(20,"edi"),"ebx"); + &mov (&DWP(24,"edi"),"ecx"); + &mov (&DWP(28,"edi"),"edx"); + + &xor ("ecx","ecx"); + &jmp (&label("14shortcut")); + + &align (4); + &set_label("14loop"); + &mov ("edx",&DWP(28,"edi")); # rk[7] + &set_label("14shortcut"); + &mov ("eax",&DWP(0,"edi")); # rk[0] + + &enckey (); + + &mov (&DWP(32,"edi"),"eax"); # rk[8] + &xor ("eax",&DWP(4,"edi")); + &mov (&DWP(36,"edi"),"eax"); # rk[9] + &xor ("eax",&DWP(8,"edi")); + &mov (&DWP(40,"edi"),"eax"); # rk[10] + &xor ("eax",&DWP(12,"edi")); + &mov (&DWP(44,"edi"),"eax"); # rk[11] + + &cmp ("ecx",6); + &je (&label("14break")); + &inc ("ecx"); + + &mov ("edx","eax"); + &mov ("eax",&DWP(16,"edi")); # rk[4] + &movz ("esi",&LB("edx")); # rk[11]>>0 + &movz ("ebx",&BP(-128,$tbl,"esi",1)); + &movz ("esi",&HB("edx")); # rk[11]>>8 + &xor ("eax","ebx"); + + &movz ("ebx",&BP(-128,$tbl,"esi",1)); + &shr ("edx",16); + &shl ("ebx",8); + &movz ("esi",&LB("edx")); # rk[11]>>16 + &xor ("eax","ebx"); + + &movz ("ebx",&BP(-128,$tbl,"esi",1)); + &movz ("esi",&HB("edx")); # rk[11]>>24 + &shl ("ebx",16); + &xor ("eax","ebx"); + + &movz ("ebx",&BP(-128,$tbl,"esi",1)); + &shl ("ebx",24); + &xor ("eax","ebx"); + + &mov (&DWP(48,"edi"),"eax"); # rk[12] + &xor ("eax",&DWP(20,"edi")); + &mov (&DWP(52,"edi"),"eax"); # rk[13] + &xor ("eax",&DWP(24,"edi")); + &mov (&DWP(56,"edi"),"eax"); # rk[14] + &xor ("eax",&DWP(28,"edi")); + &mov (&DWP(60,"edi"),"eax"); # rk[15] + + &add ("edi",32); + &jmp (&label("14loop")); + + &set_label("14break"); + &mov (&DWP(48,"edi"),14); # setup number of rounds + &xor ("eax","eax"); + &jmp (&label("exit")); + + &set_label("badpointer"); + &mov ("eax",-1); + &set_label("exit"); +&function_end("_x86_AES_set_encrypt_key"); + +# int AES_set_encrypt_key(const unsigned char *userKey, const int bits, +# AES_KEY *key) +&function_begin_B("AES_set_encrypt_key"); + &call ("_x86_AES_set_encrypt_key"); + &ret (); +&function_end_B("AES_set_encrypt_key"); + +sub deckey() +{ my ($i,$key,$tp1,$tp2,$tp4,$tp8) = @_; + my $tmp = $tbl; + + &mov ($tmp,0x80808080); + &and ($tmp,$tp1); + &lea ($tp2,&DWP(0,$tp1,$tp1)); + &mov ($acc,$tmp); + &shr ($tmp,7); + &sub ($acc,$tmp); + &and ($tp2,0xfefefefe); + &and ($acc,0x1b1b1b1b); + &xor ($tp2,$acc); + &mov ($tmp,0x80808080); + + &and ($tmp,$tp2); + &lea ($tp4,&DWP(0,$tp2,$tp2)); + &mov ($acc,$tmp); + &shr ($tmp,7); + &sub ($acc,$tmp); + &and ($tp4,0xfefefefe); + &and ($acc,0x1b1b1b1b); + &xor ($tp2,$tp1); # tp2^tp1 + &xor ($tp4,$acc); + &mov ($tmp,0x80808080); + + &and ($tmp,$tp4); + &lea ($tp8,&DWP(0,$tp4,$tp4)); + &mov ($acc,$tmp); + &shr ($tmp,7); + &xor ($tp4,$tp1); # tp4^tp1 + &sub ($acc,$tmp); + &and ($tp8,0xfefefefe); + &and ($acc,0x1b1b1b1b); + &rotl ($tp1,8); # = ROTATE(tp1,8) + &xor ($tp8,$acc); + + &mov ($tmp,&DWP(4*($i+1),$key)); # modulo-scheduled load + + &xor ($tp1,$tp2); + &xor ($tp2,$tp8); + &xor ($tp1,$tp4); + &rotl ($tp2,24); + &xor ($tp4,$tp8); + &xor ($tp1,$tp8); # ^= tp8^(tp4^tp1)^(tp2^tp1) + &rotl ($tp4,16); + &xor ($tp1,$tp2); # ^= ROTATE(tp8^tp2^tp1,24) + &rotl ($tp8,8); + &xor ($tp1,$tp4); # ^= ROTATE(tp8^tp4^tp1,16) + &mov ($tp2,$tmp); + &xor ($tp1,$tp8); # ^= ROTATE(tp8,8) + + &mov (&DWP(4*$i,$key),$tp1); +} + +# int AES_set_decrypt_key(const unsigned char *userKey, const int bits, +# AES_KEY *key) +&function_begin_B("AES_set_decrypt_key"); + &call ("_x86_AES_set_encrypt_key"); + &cmp ("eax",0); + &je (&label("proceed")); + &ret (); + + &set_label("proceed"); + &push ("ebp"); + &push ("ebx"); + &push ("esi"); + &push ("edi"); + + &mov ("esi",&wparam(2)); + &mov ("ecx",&DWP(240,"esi")); # pull number of rounds + &lea ("ecx",&DWP(0,"","ecx",4)); + &lea ("edi",&DWP(0,"esi","ecx",4)); # pointer to last chunk + + &set_label("invert",4); # invert order of chunks + &mov ("eax",&DWP(0,"esi")); + &mov ("ebx",&DWP(4,"esi")); + &mov ("ecx",&DWP(0,"edi")); + &mov ("edx",&DWP(4,"edi")); + &mov (&DWP(0,"edi"),"eax"); + &mov (&DWP(4,"edi"),"ebx"); + &mov (&DWP(0,"esi"),"ecx"); + &mov (&DWP(4,"esi"),"edx"); + &mov ("eax",&DWP(8,"esi")); + &mov ("ebx",&DWP(12,"esi")); + &mov ("ecx",&DWP(8,"edi")); + &mov ("edx",&DWP(12,"edi")); + &mov (&DWP(8,"edi"),"eax"); + &mov (&DWP(12,"edi"),"ebx"); + &mov (&DWP(8,"esi"),"ecx"); + &mov (&DWP(12,"esi"),"edx"); + &add ("esi",16); + &sub ("edi",16); + &cmp ("esi","edi"); + &jne (&label("invert")); + + &mov ($key,&wparam(2)); + &mov ($acc,&DWP(240,$key)); # pull number of rounds + &lea ($acc,&DWP(-2,$acc,$acc)); + &lea ($acc,&DWP(0,$key,$acc,8)); + &mov (&wparam(2),$acc); + + &mov ($s0,&DWP(16,$key)); # modulo-scheduled load + &set_label("permute",4); # permute the key schedule + &add ($key,16); + &deckey (0,$key,$s0,$s1,$s2,$s3); + &deckey (1,$key,$s1,$s2,$s3,$s0); + &deckey (2,$key,$s2,$s3,$s0,$s1); + &deckey (3,$key,$s3,$s0,$s1,$s2); + &cmp ($key,&wparam(2)); + &jb (&label("permute")); + + &xor ("eax","eax"); # return success +&function_end("AES_set_decrypt_key"); +&asciz("AES for x86, CRYPTOGAMS by "); + +&asm_finish(); + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-armv4.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-armv4.pl new file mode 100644 index 000000000..998158998 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-armv4.pl @@ -0,0 +1,1245 @@ +#! /usr/bin/env perl +# Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# AES for ARMv4 + +# January 2007. +# +# Code uses single 1K S-box and is >2 times faster than code generated +# by gcc-3.4.1. This is thanks to unique feature of ARMv4 ISA, which +# allows to merge logical or arithmetic operation with shift or rotate +# in one instruction and emit combined result every cycle. The module +# is endian-neutral. The performance is ~42 cycles/byte for 128-bit +# key [on single-issue Xscale PXA250 core]. + +# May 2007. +# +# AES_set_[en|de]crypt_key is added. + +# July 2010. +# +# Rescheduling for dual-issue pipeline resulted in 12% improvement on +# Cortex A8 core and ~25 cycles per byte processed with 128-bit key. + +# February 2011. +# +# Profiler-assisted and platform-specific optimization resulted in 16% +# improvement on Cortex A8 core and ~21.5 cycles per byte. + +$flavour = shift; +if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + open STDOUT,">$output"; +} + +$s0="r0"; +$s1="r1"; +$s2="r2"; +$s3="r3"; +$t1="r4"; +$t2="r5"; +$t3="r6"; +$i1="r7"; +$i2="r8"; +$i3="r9"; + +$tbl="r10"; +$key="r11"; +$rounds="r12"; + +$code=<<___; +#ifndef __KERNEL__ +# include "arm_arch.h" +#else +# define __ARM_ARCH__ __LINUX_ARM_ARCH__ +#endif + +.text +#if defined(__thumb2__) && !defined(__APPLE__) +.syntax unified +.thumb +#else +.code 32 +#undef __thumb2__ +#endif + +.type AES_Te,%object +.align 5 +AES_Te: +.word 0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d +.word 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554 +.word 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d +.word 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a +.word 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87 +.word 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b +.word 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea +.word 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b +.word 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a +.word 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f +.word 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108 +.word 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f +.word 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e +.word 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5 +.word 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d +.word 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f +.word 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e +.word 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb +.word 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce +.word 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497 +.word 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c +.word 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed +.word 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b +.word 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a +.word 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16 +.word 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594 +.word 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81 +.word 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3 +.word 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a +.word 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504 +.word 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163 +.word 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d +.word 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f +.word 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739 +.word 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47 +.word 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395 +.word 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f +.word 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883 +.word 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c +.word 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76 +.word 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e +.word 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4 +.word 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6 +.word 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b +.word 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7 +.word 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0 +.word 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25 +.word 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818 +.word 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72 +.word 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651 +.word 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21 +.word 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85 +.word 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa +.word 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12 +.word 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0 +.word 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9 +.word 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133 +.word 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7 +.word 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920 +.word 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a +.word 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17 +.word 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8 +.word 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11 +.word 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a +@ Te4[256] +.byte 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5 +.byte 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76 +.byte 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0 +.byte 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0 +.byte 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc +.byte 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15 +.byte 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a +.byte 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75 +.byte 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0 +.byte 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84 +.byte 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b +.byte 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf +.byte 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85 +.byte 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8 +.byte 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5 +.byte 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2 +.byte 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17 +.byte 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73 +.byte 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88 +.byte 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb +.byte 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c +.byte 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79 +.byte 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9 +.byte 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08 +.byte 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6 +.byte 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a +.byte 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e +.byte 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e +.byte 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94 +.byte 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf +.byte 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68 +.byte 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +@ rcon[] +.word 0x01000000, 0x02000000, 0x04000000, 0x08000000 +.word 0x10000000, 0x20000000, 0x40000000, 0x80000000 +.word 0x1B000000, 0x36000000, 0, 0, 0, 0, 0, 0 +.size AES_Te,.-AES_Te + +@ void AES_encrypt(const unsigned char *in, unsigned char *out, +@ const AES_KEY *key) { +.global AES_encrypt +.type AES_encrypt,%function +.align 5 +AES_encrypt: +#ifndef __thumb2__ + sub r3,pc,#8 @ AES_encrypt +#else + adr r3,. +#endif + stmdb sp!,{r1,r4-r12,lr} +#if defined(__thumb2__) || defined(__APPLE__) + adr $tbl,AES_Te +#else + sub $tbl,r3,#AES_encrypt-AES_Te @ Te +#endif + mov $rounds,r0 @ inp + mov $key,r2 +#if __ARM_ARCH__<7 + ldrb $s0,[$rounds,#3] @ load input data in endian-neutral + ldrb $t1,[$rounds,#2] @ manner... + ldrb $t2,[$rounds,#1] + ldrb $t3,[$rounds,#0] + orr $s0,$s0,$t1,lsl#8 + ldrb $s1,[$rounds,#7] + orr $s0,$s0,$t2,lsl#16 + ldrb $t1,[$rounds,#6] + orr $s0,$s0,$t3,lsl#24 + ldrb $t2,[$rounds,#5] + ldrb $t3,[$rounds,#4] + orr $s1,$s1,$t1,lsl#8 + ldrb $s2,[$rounds,#11] + orr $s1,$s1,$t2,lsl#16 + ldrb $t1,[$rounds,#10] + orr $s1,$s1,$t3,lsl#24 + ldrb $t2,[$rounds,#9] + ldrb $t3,[$rounds,#8] + orr $s2,$s2,$t1,lsl#8 + ldrb $s3,[$rounds,#15] + orr $s2,$s2,$t2,lsl#16 + ldrb $t1,[$rounds,#14] + orr $s2,$s2,$t3,lsl#24 + ldrb $t2,[$rounds,#13] + ldrb $t3,[$rounds,#12] + orr $s3,$s3,$t1,lsl#8 + orr $s3,$s3,$t2,lsl#16 + orr $s3,$s3,$t3,lsl#24 +#else + ldr $s0,[$rounds,#0] + ldr $s1,[$rounds,#4] + ldr $s2,[$rounds,#8] + ldr $s3,[$rounds,#12] +#ifdef __ARMEL__ + rev $s0,$s0 + rev $s1,$s1 + rev $s2,$s2 + rev $s3,$s3 +#endif +#endif + bl _armv4_AES_encrypt + + ldr $rounds,[sp],#4 @ pop out +#if __ARM_ARCH__>=7 +#ifdef __ARMEL__ + rev $s0,$s0 + rev $s1,$s1 + rev $s2,$s2 + rev $s3,$s3 +#endif + str $s0,[$rounds,#0] + str $s1,[$rounds,#4] + str $s2,[$rounds,#8] + str $s3,[$rounds,#12] +#else + mov $t1,$s0,lsr#24 @ write output in endian-neutral + mov $t2,$s0,lsr#16 @ manner... + mov $t3,$s0,lsr#8 + strb $t1,[$rounds,#0] + strb $t2,[$rounds,#1] + mov $t1,$s1,lsr#24 + strb $t3,[$rounds,#2] + mov $t2,$s1,lsr#16 + strb $s0,[$rounds,#3] + mov $t3,$s1,lsr#8 + strb $t1,[$rounds,#4] + strb $t2,[$rounds,#5] + mov $t1,$s2,lsr#24 + strb $t3,[$rounds,#6] + mov $t2,$s2,lsr#16 + strb $s1,[$rounds,#7] + mov $t3,$s2,lsr#8 + strb $t1,[$rounds,#8] + strb $t2,[$rounds,#9] + mov $t1,$s3,lsr#24 + strb $t3,[$rounds,#10] + mov $t2,$s3,lsr#16 + strb $s2,[$rounds,#11] + mov $t3,$s3,lsr#8 + strb $t1,[$rounds,#12] + strb $t2,[$rounds,#13] + strb $t3,[$rounds,#14] + strb $s3,[$rounds,#15] +#endif +#if __ARM_ARCH__>=5 + ldmia sp!,{r4-r12,pc} +#else + ldmia sp!,{r4-r12,lr} + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.size AES_encrypt,.-AES_encrypt + +.type _armv4_AES_encrypt,%function +.align 2 +_armv4_AES_encrypt: + str lr,[sp,#-4]! @ push lr + ldmia $key!,{$t1-$i1} + eor $s0,$s0,$t1 + ldr $rounds,[$key,#240-16] + eor $s1,$s1,$t2 + eor $s2,$s2,$t3 + eor $s3,$s3,$i1 + sub $rounds,$rounds,#1 + mov lr,#255 + + and $i1,lr,$s0 + and $i2,lr,$s0,lsr#8 + and $i3,lr,$s0,lsr#16 + mov $s0,$s0,lsr#24 +.Lenc_loop: + ldr $t1,[$tbl,$i1,lsl#2] @ Te3[s0>>0] + and $i1,lr,$s1,lsr#16 @ i0 + ldr $t2,[$tbl,$i2,lsl#2] @ Te2[s0>>8] + and $i2,lr,$s1 + ldr $t3,[$tbl,$i3,lsl#2] @ Te1[s0>>16] + and $i3,lr,$s1,lsr#8 + ldr $s0,[$tbl,$s0,lsl#2] @ Te0[s0>>24] + mov $s1,$s1,lsr#24 + + ldr $i1,[$tbl,$i1,lsl#2] @ Te1[s1>>16] + ldr $i2,[$tbl,$i2,lsl#2] @ Te3[s1>>0] + ldr $i3,[$tbl,$i3,lsl#2] @ Te2[s1>>8] + eor $s0,$s0,$i1,ror#8 + ldr $s1,[$tbl,$s1,lsl#2] @ Te0[s1>>24] + and $i1,lr,$s2,lsr#8 @ i0 + eor $t2,$t2,$i2,ror#8 + and $i2,lr,$s2,lsr#16 @ i1 + eor $t3,$t3,$i3,ror#8 + and $i3,lr,$s2 + ldr $i1,[$tbl,$i1,lsl#2] @ Te2[s2>>8] + eor $s1,$s1,$t1,ror#24 + ldr $i2,[$tbl,$i2,lsl#2] @ Te1[s2>>16] + mov $s2,$s2,lsr#24 + + ldr $i3,[$tbl,$i3,lsl#2] @ Te3[s2>>0] + eor $s0,$s0,$i1,ror#16 + ldr $s2,[$tbl,$s2,lsl#2] @ Te0[s2>>24] + and $i1,lr,$s3 @ i0 + eor $s1,$s1,$i2,ror#8 + and $i2,lr,$s3,lsr#8 @ i1 + eor $t3,$t3,$i3,ror#16 + and $i3,lr,$s3,lsr#16 @ i2 + ldr $i1,[$tbl,$i1,lsl#2] @ Te3[s3>>0] + eor $s2,$s2,$t2,ror#16 + ldr $i2,[$tbl,$i2,lsl#2] @ Te2[s3>>8] + mov $s3,$s3,lsr#24 + + ldr $i3,[$tbl,$i3,lsl#2] @ Te1[s3>>16] + eor $s0,$s0,$i1,ror#24 + ldr $i1,[$key],#16 + eor $s1,$s1,$i2,ror#16 + ldr $s3,[$tbl,$s3,lsl#2] @ Te0[s3>>24] + eor $s2,$s2,$i3,ror#8 + ldr $t1,[$key,#-12] + eor $s3,$s3,$t3,ror#8 + + ldr $t2,[$key,#-8] + eor $s0,$s0,$i1 + ldr $t3,[$key,#-4] + and $i1,lr,$s0 + eor $s1,$s1,$t1 + and $i2,lr,$s0,lsr#8 + eor $s2,$s2,$t2 + and $i3,lr,$s0,lsr#16 + eor $s3,$s3,$t3 + mov $s0,$s0,lsr#24 + + subs $rounds,$rounds,#1 + bne .Lenc_loop + + add $tbl,$tbl,#2 + + ldrb $t1,[$tbl,$i1,lsl#2] @ Te4[s0>>0] + and $i1,lr,$s1,lsr#16 @ i0 + ldrb $t2,[$tbl,$i2,lsl#2] @ Te4[s0>>8] + and $i2,lr,$s1 + ldrb $t3,[$tbl,$i3,lsl#2] @ Te4[s0>>16] + and $i3,lr,$s1,lsr#8 + ldrb $s0,[$tbl,$s0,lsl#2] @ Te4[s0>>24] + mov $s1,$s1,lsr#24 + + ldrb $i1,[$tbl,$i1,lsl#2] @ Te4[s1>>16] + ldrb $i2,[$tbl,$i2,lsl#2] @ Te4[s1>>0] + ldrb $i3,[$tbl,$i3,lsl#2] @ Te4[s1>>8] + eor $s0,$i1,$s0,lsl#8 + ldrb $s1,[$tbl,$s1,lsl#2] @ Te4[s1>>24] + and $i1,lr,$s2,lsr#8 @ i0 + eor $t2,$i2,$t2,lsl#8 + and $i2,lr,$s2,lsr#16 @ i1 + eor $t3,$i3,$t3,lsl#8 + and $i3,lr,$s2 + ldrb $i1,[$tbl,$i1,lsl#2] @ Te4[s2>>8] + eor $s1,$t1,$s1,lsl#24 + ldrb $i2,[$tbl,$i2,lsl#2] @ Te4[s2>>16] + mov $s2,$s2,lsr#24 + + ldrb $i3,[$tbl,$i3,lsl#2] @ Te4[s2>>0] + eor $s0,$i1,$s0,lsl#8 + ldrb $s2,[$tbl,$s2,lsl#2] @ Te4[s2>>24] + and $i1,lr,$s3 @ i0 + eor $s1,$s1,$i2,lsl#16 + and $i2,lr,$s3,lsr#8 @ i1 + eor $t3,$i3,$t3,lsl#8 + and $i3,lr,$s3,lsr#16 @ i2 + ldrb $i1,[$tbl,$i1,lsl#2] @ Te4[s3>>0] + eor $s2,$t2,$s2,lsl#24 + ldrb $i2,[$tbl,$i2,lsl#2] @ Te4[s3>>8] + mov $s3,$s3,lsr#24 + + ldrb $i3,[$tbl,$i3,lsl#2] @ Te4[s3>>16] + eor $s0,$i1,$s0,lsl#8 + ldr $i1,[$key,#0] + ldrb $s3,[$tbl,$s3,lsl#2] @ Te4[s3>>24] + eor $s1,$s1,$i2,lsl#8 + ldr $t1,[$key,#4] + eor $s2,$s2,$i3,lsl#16 + ldr $t2,[$key,#8] + eor $s3,$t3,$s3,lsl#24 + ldr $t3,[$key,#12] + + eor $s0,$s0,$i1 + eor $s1,$s1,$t1 + eor $s2,$s2,$t2 + eor $s3,$s3,$t3 + + sub $tbl,$tbl,#2 + ldr pc,[sp],#4 @ pop and return +.size _armv4_AES_encrypt,.-_armv4_AES_encrypt + +.global AES_set_encrypt_key +.type AES_set_encrypt_key,%function +.align 5 +AES_set_encrypt_key: +_armv4_AES_set_encrypt_key: +#ifndef __thumb2__ + sub r3,pc,#8 @ AES_set_encrypt_key +#else + adr r3,. +#endif + teq r0,#0 +#ifdef __thumb2__ + itt eq @ Thumb2 thing, sanity check in ARM +#endif + moveq r0,#-1 + beq .Labrt + teq r2,#0 +#ifdef __thumb2__ + itt eq @ Thumb2 thing, sanity check in ARM +#endif + moveq r0,#-1 + beq .Labrt + + teq r1,#128 + beq .Lok + teq r1,#192 + beq .Lok + teq r1,#256 +#ifdef __thumb2__ + itt ne @ Thumb2 thing, sanity check in ARM +#endif + movne r0,#-1 + bne .Labrt + +.Lok: stmdb sp!,{r4-r12,lr} + mov $rounds,r0 @ inp + mov lr,r1 @ bits + mov $key,r2 @ key + +#if defined(__thumb2__) || defined(__APPLE__) + adr $tbl,AES_Te+1024 @ Te4 +#else + sub $tbl,r3,#_armv4_AES_set_encrypt_key-AES_Te-1024 @ Te4 +#endif + +#if __ARM_ARCH__<7 + ldrb $s0,[$rounds,#3] @ load input data in endian-neutral + ldrb $t1,[$rounds,#2] @ manner... + ldrb $t2,[$rounds,#1] + ldrb $t3,[$rounds,#0] + orr $s0,$s0,$t1,lsl#8 + ldrb $s1,[$rounds,#7] + orr $s0,$s0,$t2,lsl#16 + ldrb $t1,[$rounds,#6] + orr $s0,$s0,$t3,lsl#24 + ldrb $t2,[$rounds,#5] + ldrb $t3,[$rounds,#4] + orr $s1,$s1,$t1,lsl#8 + ldrb $s2,[$rounds,#11] + orr $s1,$s1,$t2,lsl#16 + ldrb $t1,[$rounds,#10] + orr $s1,$s1,$t3,lsl#24 + ldrb $t2,[$rounds,#9] + ldrb $t3,[$rounds,#8] + orr $s2,$s2,$t1,lsl#8 + ldrb $s3,[$rounds,#15] + orr $s2,$s2,$t2,lsl#16 + ldrb $t1,[$rounds,#14] + orr $s2,$s2,$t3,lsl#24 + ldrb $t2,[$rounds,#13] + ldrb $t3,[$rounds,#12] + orr $s3,$s3,$t1,lsl#8 + str $s0,[$key],#16 + orr $s3,$s3,$t2,lsl#16 + str $s1,[$key,#-12] + orr $s3,$s3,$t3,lsl#24 + str $s2,[$key,#-8] + str $s3,[$key,#-4] +#else + ldr $s0,[$rounds,#0] + ldr $s1,[$rounds,#4] + ldr $s2,[$rounds,#8] + ldr $s3,[$rounds,#12] +#ifdef __ARMEL__ + rev $s0,$s0 + rev $s1,$s1 + rev $s2,$s2 + rev $s3,$s3 +#endif + str $s0,[$key],#16 + str $s1,[$key,#-12] + str $s2,[$key,#-8] + str $s3,[$key,#-4] +#endif + + teq lr,#128 + bne .Lnot128 + mov $rounds,#10 + str $rounds,[$key,#240-16] + add $t3,$tbl,#256 @ rcon + mov lr,#255 + +.L128_loop: + and $t2,lr,$s3,lsr#24 + and $i1,lr,$s3,lsr#16 + ldrb $t2,[$tbl,$t2] + and $i2,lr,$s3,lsr#8 + ldrb $i1,[$tbl,$i1] + and $i3,lr,$s3 + ldrb $i2,[$tbl,$i2] + orr $t2,$t2,$i1,lsl#24 + ldrb $i3,[$tbl,$i3] + orr $t2,$t2,$i2,lsl#16 + ldr $t1,[$t3],#4 @ rcon[i++] + orr $t2,$t2,$i3,lsl#8 + eor $t2,$t2,$t1 + eor $s0,$s0,$t2 @ rk[4]=rk[0]^... + eor $s1,$s1,$s0 @ rk[5]=rk[1]^rk[4] + str $s0,[$key],#16 + eor $s2,$s2,$s1 @ rk[6]=rk[2]^rk[5] + str $s1,[$key,#-12] + eor $s3,$s3,$s2 @ rk[7]=rk[3]^rk[6] + str $s2,[$key,#-8] + subs $rounds,$rounds,#1 + str $s3,[$key,#-4] + bne .L128_loop + sub r2,$key,#176 + b .Ldone + +.Lnot128: +#if __ARM_ARCH__<7 + ldrb $i2,[$rounds,#19] + ldrb $t1,[$rounds,#18] + ldrb $t2,[$rounds,#17] + ldrb $t3,[$rounds,#16] + orr $i2,$i2,$t1,lsl#8 + ldrb $i3,[$rounds,#23] + orr $i2,$i2,$t2,lsl#16 + ldrb $t1,[$rounds,#22] + orr $i2,$i2,$t3,lsl#24 + ldrb $t2,[$rounds,#21] + ldrb $t3,[$rounds,#20] + orr $i3,$i3,$t1,lsl#8 + orr $i3,$i3,$t2,lsl#16 + str $i2,[$key],#8 + orr $i3,$i3,$t3,lsl#24 + str $i3,[$key,#-4] +#else + ldr $i2,[$rounds,#16] + ldr $i3,[$rounds,#20] +#ifdef __ARMEL__ + rev $i2,$i2 + rev $i3,$i3 +#endif + str $i2,[$key],#8 + str $i3,[$key,#-4] +#endif + + teq lr,#192 + bne .Lnot192 + mov $rounds,#12 + str $rounds,[$key,#240-24] + add $t3,$tbl,#256 @ rcon + mov lr,#255 + mov $rounds,#8 + +.L192_loop: + and $t2,lr,$i3,lsr#24 + and $i1,lr,$i3,lsr#16 + ldrb $t2,[$tbl,$t2] + and $i2,lr,$i3,lsr#8 + ldrb $i1,[$tbl,$i1] + and $i3,lr,$i3 + ldrb $i2,[$tbl,$i2] + orr $t2,$t2,$i1,lsl#24 + ldrb $i3,[$tbl,$i3] + orr $t2,$t2,$i2,lsl#16 + ldr $t1,[$t3],#4 @ rcon[i++] + orr $t2,$t2,$i3,lsl#8 + eor $i3,$t2,$t1 + eor $s0,$s0,$i3 @ rk[6]=rk[0]^... + eor $s1,$s1,$s0 @ rk[7]=rk[1]^rk[6] + str $s0,[$key],#24 + eor $s2,$s2,$s1 @ rk[8]=rk[2]^rk[7] + str $s1,[$key,#-20] + eor $s3,$s3,$s2 @ rk[9]=rk[3]^rk[8] + str $s2,[$key,#-16] + subs $rounds,$rounds,#1 + str $s3,[$key,#-12] +#ifdef __thumb2__ + itt eq @ Thumb2 thing, sanity check in ARM +#endif + subeq r2,$key,#216 + beq .Ldone + + ldr $i1,[$key,#-32] + ldr $i2,[$key,#-28] + eor $i1,$i1,$s3 @ rk[10]=rk[4]^rk[9] + eor $i3,$i2,$i1 @ rk[11]=rk[5]^rk[10] + str $i1,[$key,#-8] + str $i3,[$key,#-4] + b .L192_loop + +.Lnot192: +#if __ARM_ARCH__<7 + ldrb $i2,[$rounds,#27] + ldrb $t1,[$rounds,#26] + ldrb $t2,[$rounds,#25] + ldrb $t3,[$rounds,#24] + orr $i2,$i2,$t1,lsl#8 + ldrb $i3,[$rounds,#31] + orr $i2,$i2,$t2,lsl#16 + ldrb $t1,[$rounds,#30] + orr $i2,$i2,$t3,lsl#24 + ldrb $t2,[$rounds,#29] + ldrb $t3,[$rounds,#28] + orr $i3,$i3,$t1,lsl#8 + orr $i3,$i3,$t2,lsl#16 + str $i2,[$key],#8 + orr $i3,$i3,$t3,lsl#24 + str $i3,[$key,#-4] +#else + ldr $i2,[$rounds,#24] + ldr $i3,[$rounds,#28] +#ifdef __ARMEL__ + rev $i2,$i2 + rev $i3,$i3 +#endif + str $i2,[$key],#8 + str $i3,[$key,#-4] +#endif + + mov $rounds,#14 + str $rounds,[$key,#240-32] + add $t3,$tbl,#256 @ rcon + mov lr,#255 + mov $rounds,#7 + +.L256_loop: + and $t2,lr,$i3,lsr#24 + and $i1,lr,$i3,lsr#16 + ldrb $t2,[$tbl,$t2] + and $i2,lr,$i3,lsr#8 + ldrb $i1,[$tbl,$i1] + and $i3,lr,$i3 + ldrb $i2,[$tbl,$i2] + orr $t2,$t2,$i1,lsl#24 + ldrb $i3,[$tbl,$i3] + orr $t2,$t2,$i2,lsl#16 + ldr $t1,[$t3],#4 @ rcon[i++] + orr $t2,$t2,$i3,lsl#8 + eor $i3,$t2,$t1 + eor $s0,$s0,$i3 @ rk[8]=rk[0]^... + eor $s1,$s1,$s0 @ rk[9]=rk[1]^rk[8] + str $s0,[$key],#32 + eor $s2,$s2,$s1 @ rk[10]=rk[2]^rk[9] + str $s1,[$key,#-28] + eor $s3,$s3,$s2 @ rk[11]=rk[3]^rk[10] + str $s2,[$key,#-24] + subs $rounds,$rounds,#1 + str $s3,[$key,#-20] +#ifdef __thumb2__ + itt eq @ Thumb2 thing, sanity check in ARM +#endif + subeq r2,$key,#256 + beq .Ldone + + and $t2,lr,$s3 + and $i1,lr,$s3,lsr#8 + ldrb $t2,[$tbl,$t2] + and $i2,lr,$s3,lsr#16 + ldrb $i1,[$tbl,$i1] + and $i3,lr,$s3,lsr#24 + ldrb $i2,[$tbl,$i2] + orr $t2,$t2,$i1,lsl#8 + ldrb $i3,[$tbl,$i3] + orr $t2,$t2,$i2,lsl#16 + ldr $t1,[$key,#-48] + orr $t2,$t2,$i3,lsl#24 + + ldr $i1,[$key,#-44] + ldr $i2,[$key,#-40] + eor $t1,$t1,$t2 @ rk[12]=rk[4]^... + ldr $i3,[$key,#-36] + eor $i1,$i1,$t1 @ rk[13]=rk[5]^rk[12] + str $t1,[$key,#-16] + eor $i2,$i2,$i1 @ rk[14]=rk[6]^rk[13] + str $i1,[$key,#-12] + eor $i3,$i3,$i2 @ rk[15]=rk[7]^rk[14] + str $i2,[$key,#-8] + str $i3,[$key,#-4] + b .L256_loop + +.align 2 +.Ldone: mov r0,#0 + ldmia sp!,{r4-r12,lr} +.Labrt: +#if __ARM_ARCH__>=5 + ret @ bx lr +#else + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.size AES_set_encrypt_key,.-AES_set_encrypt_key + +.global AES_set_decrypt_key +.type AES_set_decrypt_key,%function +.align 5 +AES_set_decrypt_key: + str lr,[sp,#-4]! @ push lr + bl _armv4_AES_set_encrypt_key + teq r0,#0 + ldr lr,[sp],#4 @ pop lr + bne .Labrt + + mov r0,r2 @ AES_set_encrypt_key preserves r2, + mov r1,r2 @ which is AES_KEY *key + b _armv4_AES_set_enc2dec_key +.size AES_set_decrypt_key,.-AES_set_decrypt_key + +@ void AES_set_enc2dec_key(const AES_KEY *inp,AES_KEY *out) +.global AES_set_enc2dec_key +.type AES_set_enc2dec_key,%function +.align 5 +AES_set_enc2dec_key: +_armv4_AES_set_enc2dec_key: + stmdb sp!,{r4-r12,lr} + + ldr $rounds,[r0,#240] + mov $i1,r0 @ input + add $i2,r0,$rounds,lsl#4 + mov $key,r1 @ output + add $tbl,r1,$rounds,lsl#4 + str $rounds,[r1,#240] + +.Linv: ldr $s0,[$i1],#16 + ldr $s1,[$i1,#-12] + ldr $s2,[$i1,#-8] + ldr $s3,[$i1,#-4] + ldr $t1,[$i2],#-16 + ldr $t2,[$i2,#16+4] + ldr $t3,[$i2,#16+8] + ldr $i3,[$i2,#16+12] + str $s0,[$tbl],#-16 + str $s1,[$tbl,#16+4] + str $s2,[$tbl,#16+8] + str $s3,[$tbl,#16+12] + str $t1,[$key],#16 + str $t2,[$key,#-12] + str $t3,[$key,#-8] + str $i3,[$key,#-4] + teq $i1,$i2 + bne .Linv + + ldr $s0,[$i1] + ldr $s1,[$i1,#4] + ldr $s2,[$i1,#8] + ldr $s3,[$i1,#12] + str $s0,[$key] + str $s1,[$key,#4] + str $s2,[$key,#8] + str $s3,[$key,#12] + sub $key,$key,$rounds,lsl#3 +___ +$mask80=$i1; +$mask1b=$i2; +$mask7f=$i3; +$code.=<<___; + ldr $s0,[$key,#16]! @ prefetch tp1 + mov $mask80,#0x80 + mov $mask1b,#0x1b + orr $mask80,$mask80,#0x8000 + orr $mask1b,$mask1b,#0x1b00 + orr $mask80,$mask80,$mask80,lsl#16 + orr $mask1b,$mask1b,$mask1b,lsl#16 + sub $rounds,$rounds,#1 + mvn $mask7f,$mask80 + mov $rounds,$rounds,lsl#2 @ (rounds-1)*4 + +.Lmix: and $t1,$s0,$mask80 + and $s1,$s0,$mask7f + sub $t1,$t1,$t1,lsr#7 + and $t1,$t1,$mask1b + eor $s1,$t1,$s1,lsl#1 @ tp2 + + and $t1,$s1,$mask80 + and $s2,$s1,$mask7f + sub $t1,$t1,$t1,lsr#7 + and $t1,$t1,$mask1b + eor $s2,$t1,$s2,lsl#1 @ tp4 + + and $t1,$s2,$mask80 + and $s3,$s2,$mask7f + sub $t1,$t1,$t1,lsr#7 + and $t1,$t1,$mask1b + eor $s3,$t1,$s3,lsl#1 @ tp8 + + eor $t1,$s1,$s2 + eor $t2,$s0,$s3 @ tp9 + eor $t1,$t1,$s3 @ tpe + eor $t1,$t1,$s1,ror#24 + eor $t1,$t1,$t2,ror#24 @ ^= ROTATE(tpb=tp9^tp2,8) + eor $t1,$t1,$s2,ror#16 + eor $t1,$t1,$t2,ror#16 @ ^= ROTATE(tpd=tp9^tp4,16) + eor $t1,$t1,$t2,ror#8 @ ^= ROTATE(tp9,24) + + ldr $s0,[$key,#4] @ prefetch tp1 + str $t1,[$key],#4 + subs $rounds,$rounds,#1 + bne .Lmix + + mov r0,#0 +#if __ARM_ARCH__>=5 + ldmia sp!,{r4-r12,pc} +#else + ldmia sp!,{r4-r12,lr} + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.size AES_set_enc2dec_key,.-AES_set_enc2dec_key + +.type AES_Td,%object +.align 5 +AES_Td: +.word 0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96 +.word 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393 +.word 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25 +.word 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f +.word 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1 +.word 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6 +.word 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da +.word 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844 +.word 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd +.word 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4 +.word 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45 +.word 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94 +.word 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7 +.word 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a +.word 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5 +.word 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c +.word 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1 +.word 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a +.word 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75 +.word 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051 +.word 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46 +.word 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff +.word 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77 +.word 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb +.word 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000 +.word 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e +.word 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927 +.word 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a +.word 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e +.word 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16 +.word 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d +.word 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8 +.word 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd +.word 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34 +.word 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163 +.word 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120 +.word 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d +.word 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0 +.word 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422 +.word 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef +.word 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36 +.word 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4 +.word 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662 +.word 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5 +.word 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3 +.word 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b +.word 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8 +.word 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6 +.word 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6 +.word 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0 +.word 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815 +.word 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f +.word 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df +.word 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f +.word 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e +.word 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713 +.word 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89 +.word 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c +.word 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf +.word 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86 +.word 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f +.word 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541 +.word 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190 +.word 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742 +@ Td4[256] +.byte 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38 +.byte 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb +.byte 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87 +.byte 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb +.byte 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d +.byte 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e +.byte 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2 +.byte 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 +.byte 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16 +.byte 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 +.byte 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda +.byte 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 +.byte 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a +.byte 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 +.byte 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02 +.byte 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b +.byte 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea +.byte 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 +.byte 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85 +.byte 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e +.byte 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89 +.byte 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b +.byte 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20 +.byte 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 +.byte 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31 +.byte 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f +.byte 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d +.byte 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef +.byte 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0 +.byte 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 +.byte 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26 +.byte 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d +.size AES_Td,.-AES_Td + +@ void AES_decrypt(const unsigned char *in, unsigned char *out, +@ const AES_KEY *key) { +.global AES_decrypt +.type AES_decrypt,%function +.align 5 +AES_decrypt: +#ifndef __thumb2__ + sub r3,pc,#8 @ AES_decrypt +#else + adr r3,. +#endif + stmdb sp!,{r1,r4-r12,lr} +#if defined(__thumb2__) || defined(__APPLE__) + adr $tbl,AES_Td +#else + sub $tbl,r3,#AES_decrypt-AES_Td @ Td +#endif + mov $rounds,r0 @ inp + mov $key,r2 +#if __ARM_ARCH__<7 + ldrb $s0,[$rounds,#3] @ load input data in endian-neutral + ldrb $t1,[$rounds,#2] @ manner... + ldrb $t2,[$rounds,#1] + ldrb $t3,[$rounds,#0] + orr $s0,$s0,$t1,lsl#8 + ldrb $s1,[$rounds,#7] + orr $s0,$s0,$t2,lsl#16 + ldrb $t1,[$rounds,#6] + orr $s0,$s0,$t3,lsl#24 + ldrb $t2,[$rounds,#5] + ldrb $t3,[$rounds,#4] + orr $s1,$s1,$t1,lsl#8 + ldrb $s2,[$rounds,#11] + orr $s1,$s1,$t2,lsl#16 + ldrb $t1,[$rounds,#10] + orr $s1,$s1,$t3,lsl#24 + ldrb $t2,[$rounds,#9] + ldrb $t3,[$rounds,#8] + orr $s2,$s2,$t1,lsl#8 + ldrb $s3,[$rounds,#15] + orr $s2,$s2,$t2,lsl#16 + ldrb $t1,[$rounds,#14] + orr $s2,$s2,$t3,lsl#24 + ldrb $t2,[$rounds,#13] + ldrb $t3,[$rounds,#12] + orr $s3,$s3,$t1,lsl#8 + orr $s3,$s3,$t2,lsl#16 + orr $s3,$s3,$t3,lsl#24 +#else + ldr $s0,[$rounds,#0] + ldr $s1,[$rounds,#4] + ldr $s2,[$rounds,#8] + ldr $s3,[$rounds,#12] +#ifdef __ARMEL__ + rev $s0,$s0 + rev $s1,$s1 + rev $s2,$s2 + rev $s3,$s3 +#endif +#endif + bl _armv4_AES_decrypt + + ldr $rounds,[sp],#4 @ pop out +#if __ARM_ARCH__>=7 +#ifdef __ARMEL__ + rev $s0,$s0 + rev $s1,$s1 + rev $s2,$s2 + rev $s3,$s3 +#endif + str $s0,[$rounds,#0] + str $s1,[$rounds,#4] + str $s2,[$rounds,#8] + str $s3,[$rounds,#12] +#else + mov $t1,$s0,lsr#24 @ write output in endian-neutral + mov $t2,$s0,lsr#16 @ manner... + mov $t3,$s0,lsr#8 + strb $t1,[$rounds,#0] + strb $t2,[$rounds,#1] + mov $t1,$s1,lsr#24 + strb $t3,[$rounds,#2] + mov $t2,$s1,lsr#16 + strb $s0,[$rounds,#3] + mov $t3,$s1,lsr#8 + strb $t1,[$rounds,#4] + strb $t2,[$rounds,#5] + mov $t1,$s2,lsr#24 + strb $t3,[$rounds,#6] + mov $t2,$s2,lsr#16 + strb $s1,[$rounds,#7] + mov $t3,$s2,lsr#8 + strb $t1,[$rounds,#8] + strb $t2,[$rounds,#9] + mov $t1,$s3,lsr#24 + strb $t3,[$rounds,#10] + mov $t2,$s3,lsr#16 + strb $s2,[$rounds,#11] + mov $t3,$s3,lsr#8 + strb $t1,[$rounds,#12] + strb $t2,[$rounds,#13] + strb $t3,[$rounds,#14] + strb $s3,[$rounds,#15] +#endif +#if __ARM_ARCH__>=5 + ldmia sp!,{r4-r12,pc} +#else + ldmia sp!,{r4-r12,lr} + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.size AES_decrypt,.-AES_decrypt + +.type _armv4_AES_decrypt,%function +.align 2 +_armv4_AES_decrypt: + str lr,[sp,#-4]! @ push lr + ldmia $key!,{$t1-$i1} + eor $s0,$s0,$t1 + ldr $rounds,[$key,#240-16] + eor $s1,$s1,$t2 + eor $s2,$s2,$t3 + eor $s3,$s3,$i1 + sub $rounds,$rounds,#1 + mov lr,#255 + + and $i1,lr,$s0,lsr#16 + and $i2,lr,$s0,lsr#8 + and $i3,lr,$s0 + mov $s0,$s0,lsr#24 +.Ldec_loop: + ldr $t1,[$tbl,$i1,lsl#2] @ Td1[s0>>16] + and $i1,lr,$s1 @ i0 + ldr $t2,[$tbl,$i2,lsl#2] @ Td2[s0>>8] + and $i2,lr,$s1,lsr#16 + ldr $t3,[$tbl,$i3,lsl#2] @ Td3[s0>>0] + and $i3,lr,$s1,lsr#8 + ldr $s0,[$tbl,$s0,lsl#2] @ Td0[s0>>24] + mov $s1,$s1,lsr#24 + + ldr $i1,[$tbl,$i1,lsl#2] @ Td3[s1>>0] + ldr $i2,[$tbl,$i2,lsl#2] @ Td1[s1>>16] + ldr $i3,[$tbl,$i3,lsl#2] @ Td2[s1>>8] + eor $s0,$s0,$i1,ror#24 + ldr $s1,[$tbl,$s1,lsl#2] @ Td0[s1>>24] + and $i1,lr,$s2,lsr#8 @ i0 + eor $t2,$i2,$t2,ror#8 + and $i2,lr,$s2 @ i1 + eor $t3,$i3,$t3,ror#8 + and $i3,lr,$s2,lsr#16 + ldr $i1,[$tbl,$i1,lsl#2] @ Td2[s2>>8] + eor $s1,$s1,$t1,ror#8 + ldr $i2,[$tbl,$i2,lsl#2] @ Td3[s2>>0] + mov $s2,$s2,lsr#24 + + ldr $i3,[$tbl,$i3,lsl#2] @ Td1[s2>>16] + eor $s0,$s0,$i1,ror#16 + ldr $s2,[$tbl,$s2,lsl#2] @ Td0[s2>>24] + and $i1,lr,$s3,lsr#16 @ i0 + eor $s1,$s1,$i2,ror#24 + and $i2,lr,$s3,lsr#8 @ i1 + eor $t3,$i3,$t3,ror#8 + and $i3,lr,$s3 @ i2 + ldr $i1,[$tbl,$i1,lsl#2] @ Td1[s3>>16] + eor $s2,$s2,$t2,ror#8 + ldr $i2,[$tbl,$i2,lsl#2] @ Td2[s3>>8] + mov $s3,$s3,lsr#24 + + ldr $i3,[$tbl,$i3,lsl#2] @ Td3[s3>>0] + eor $s0,$s0,$i1,ror#8 + ldr $i1,[$key],#16 + eor $s1,$s1,$i2,ror#16 + ldr $s3,[$tbl,$s3,lsl#2] @ Td0[s3>>24] + eor $s2,$s2,$i3,ror#24 + + ldr $t1,[$key,#-12] + eor $s0,$s0,$i1 + ldr $t2,[$key,#-8] + eor $s3,$s3,$t3,ror#8 + ldr $t3,[$key,#-4] + and $i1,lr,$s0,lsr#16 + eor $s1,$s1,$t1 + and $i2,lr,$s0,lsr#8 + eor $s2,$s2,$t2 + and $i3,lr,$s0 + eor $s3,$s3,$t3 + mov $s0,$s0,lsr#24 + + subs $rounds,$rounds,#1 + bne .Ldec_loop + + add $tbl,$tbl,#1024 + + ldr $t2,[$tbl,#0] @ prefetch Td4 + ldr $t3,[$tbl,#32] + ldr $t1,[$tbl,#64] + ldr $t2,[$tbl,#96] + ldr $t3,[$tbl,#128] + ldr $t1,[$tbl,#160] + ldr $t2,[$tbl,#192] + ldr $t3,[$tbl,#224] + + ldrb $s0,[$tbl,$s0] @ Td4[s0>>24] + ldrb $t1,[$tbl,$i1] @ Td4[s0>>16] + and $i1,lr,$s1 @ i0 + ldrb $t2,[$tbl,$i2] @ Td4[s0>>8] + and $i2,lr,$s1,lsr#16 + ldrb $t3,[$tbl,$i3] @ Td4[s0>>0] + and $i3,lr,$s1,lsr#8 + + add $s1,$tbl,$s1,lsr#24 + ldrb $i1,[$tbl,$i1] @ Td4[s1>>0] + ldrb $s1,[$s1] @ Td4[s1>>24] + ldrb $i2,[$tbl,$i2] @ Td4[s1>>16] + eor $s0,$i1,$s0,lsl#24 + ldrb $i3,[$tbl,$i3] @ Td4[s1>>8] + eor $s1,$t1,$s1,lsl#8 + and $i1,lr,$s2,lsr#8 @ i0 + eor $t2,$t2,$i2,lsl#8 + and $i2,lr,$s2 @ i1 + ldrb $i1,[$tbl,$i1] @ Td4[s2>>8] + eor $t3,$t3,$i3,lsl#8 + ldrb $i2,[$tbl,$i2] @ Td4[s2>>0] + and $i3,lr,$s2,lsr#16 + + add $s2,$tbl,$s2,lsr#24 + ldrb $s2,[$s2] @ Td4[s2>>24] + eor $s0,$s0,$i1,lsl#8 + ldrb $i3,[$tbl,$i3] @ Td4[s2>>16] + eor $s1,$i2,$s1,lsl#16 + and $i1,lr,$s3,lsr#16 @ i0 + eor $s2,$t2,$s2,lsl#16 + and $i2,lr,$s3,lsr#8 @ i1 + ldrb $i1,[$tbl,$i1] @ Td4[s3>>16] + eor $t3,$t3,$i3,lsl#16 + ldrb $i2,[$tbl,$i2] @ Td4[s3>>8] + and $i3,lr,$s3 @ i2 + + add $s3,$tbl,$s3,lsr#24 + ldrb $i3,[$tbl,$i3] @ Td4[s3>>0] + ldrb $s3,[$s3] @ Td4[s3>>24] + eor $s0,$s0,$i1,lsl#16 + ldr $i1,[$key,#0] + eor $s1,$s1,$i2,lsl#8 + ldr $t1,[$key,#4] + eor $s2,$i3,$s2,lsl#8 + ldr $t2,[$key,#8] + eor $s3,$t3,$s3,lsl#24 + ldr $t3,[$key,#12] + + eor $s0,$s0,$i1 + eor $s1,$s1,$t1 + eor $s2,$s2,$t2 + eor $s3,$s3,$t3 + + sub $tbl,$tbl,#1024 + ldr pc,[sp],#4 @ pop and return +.size _armv4_AES_decrypt,.-_armv4_AES_decrypt +.asciz "AES for ARMv4, CRYPTOGAMS by " +.align 2 +___ + +$code =~ s/\bbx\s+lr\b/.word\t0xe12fff1e/gm; # make it possible to compile with -march=armv4 +$code =~ s/\bret\b/bx\tlr/gm; + +open SELF,$0; +while() { + next if (/^#!/); + last if (!s/^#/@/ and !/^$/); + print; +} +close SELF; + +print $code; +close STDOUT; # enforce flush diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-c64xplus.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-c64xplus.pl new file mode 100644 index 000000000..19d2cc176 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-c64xplus.pl @@ -0,0 +1,1382 @@ +#! /usr/bin/env perl +# Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# [Endian-neutral] AES for C64x+. +# +# Even though SPLOOPs are scheduled for 13 cycles, and thus expected +# performance is ~8.5 cycles per byte processed with 128-bit key, +# measured performance turned to be ~10 cycles per byte. Discrepancy +# must be caused by limitations of L1D memory banking(*), see SPRU871 +# TI publication for further details. If any consolation it's still +# ~20% faster than TI's linear assembly module anyway... Compared to +# aes_core.c compiled with cl6x 6.0 with -mv6400+ -o2 options this +# code is 3.75x faster and almost 3x smaller (tables included). +# +# (*) This means that there might be subtle correlation between data +# and timing and one can wonder if it can be ... attacked:-( +# On the other hand this also means that *if* one chooses to +# implement *4* T-tables variant [instead of 1 T-table as in +# this implementation, or in addition to], then one ought to +# *interleave* them. Even though it complicates addressing, +# references to interleaved tables would be guaranteed not to +# clash. I reckon that it should be possible to break 8 cycles +# per byte "barrier," i.e. improve by ~20%, naturally at the +# cost of 8x increased pressure on L1D. 8x because you'd have +# to interleave both Te and Td tables... + +while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} +open STDOUT,">$output"; + +($TEA,$TEB)=("A5","B5"); +($KPA,$KPB)=("A3","B1"); +@K=("A6","B6","A7","B7"); +@s=("A8","B8","A9","B9"); +@Te0=@Td0=("A16","B16","A17","B17"); +@Te1=@Td1=("A18","B18","A19","B19"); +@Te2=@Td2=("A20","B20","A21","B21"); +@Te3=@Td3=("A22","B22","A23","B23"); + +$code=<<___; + .text + + .if .ASSEMBLER_VERSION<7000000 + .asg 0,__TI_EABI__ + .endif + .if __TI_EABI__ + .nocmp + .asg AES_encrypt,_AES_encrypt + .asg AES_decrypt,_AES_decrypt + .asg AES_set_encrypt_key,_AES_set_encrypt_key + .asg AES_set_decrypt_key,_AES_set_decrypt_key + .asg AES_ctr32_encrypt,_AES_ctr32_encrypt + .endif + + .asg B3,RA + .asg A4,INP + .asg B4,OUT + .asg A6,KEY + .asg A4,RET + .asg B15,SP + + .eval 24,EXT0 + .eval 16,EXT1 + .eval 8,EXT2 + .eval 0,EXT3 + .eval 8,TBL1 + .eval 16,TBL2 + .eval 24,TBL3 + + .if .BIG_ENDIAN + .eval 24-EXT0,EXT0 + .eval 24-EXT1,EXT1 + .eval 24-EXT2,EXT2 + .eval 24-EXT3,EXT3 + .eval 32-TBL1,TBL1 + .eval 32-TBL2,TBL2 + .eval 32-TBL3,TBL3 + .endif + + .global _AES_encrypt +_AES_encrypt: + .asmfunc + MVK 1,B2 +__encrypt: + .if __TI_EABI__ + [B2] LDNDW *INP++,A9:A8 ; load input +|| MVKL \$PCR_OFFSET(AES_Te,__encrypt),$TEA +|| ADDKPC __encrypt,B0 + [B2] LDNDW *INP++,B9:B8 +|| MVKH \$PCR_OFFSET(AES_Te,__encrypt),$TEA +|| ADD 0,KEY,$KPA +|| ADD 4,KEY,$KPB + .else + [B2] LDNDW *INP++,A9:A8 ; load input +|| MVKL (AES_Te-__encrypt),$TEA +|| ADDKPC __encrypt,B0 + [B2] LDNDW *INP++,B9:B8 +|| MVKH (AES_Te-__encrypt),$TEA +|| ADD 0,KEY,$KPA +|| ADD 4,KEY,$KPB + .endif + LDW *$KPA++[2],$Te0[0] ; zero round key +|| LDW *$KPB++[2],$Te0[1] +|| MVK 60,A0 +|| ADD B0,$TEA,$TEA ; AES_Te + LDW *KEY[A0],B0 ; rounds +|| MVK 1024,A0 ; sizeof(AES_Te) + LDW *$KPA++[2],$Te0[2] +|| LDW *$KPB++[2],$Te0[3] +|| MV $TEA,$TEB + NOP + .if .BIG_ENDIAN + MV A9,$s[0] +|| MV A8,$s[1] +|| MV B9,$s[2] +|| MV B8,$s[3] + .else + MV A8,$s[0] +|| MV A9,$s[1] +|| MV B8,$s[2] +|| MV B9,$s[3] + .endif + XOR $Te0[0],$s[0],$s[0] +|| XOR $Te0[1],$s[1],$s[1] +|| LDW *$KPA++[2],$K[0] ; 1st round key +|| LDW *$KPB++[2],$K[1] + SUB B0,2,B0 + + SPLOOPD 13 +|| MVC B0,ILC +|| LDW *$KPA++[2],$K[2] +|| LDW *$KPB++[2],$K[3] +;;==================================================================== + EXTU $s[1],EXT1,24,$Te1[1] +|| EXTU $s[0],EXT3,24,$Te3[0] + LDW *${TEB}[$Te1[1]],$Te1[1] ; Te1[s1>>8], t0 +|| LDW *${TEA}[$Te3[0]],$Te3[0] ; Te3[s0>>24], t1 +|| XOR $s[2],$Te0[2],$s[2] ; modulo-scheduled +|| XOR $s[3],$Te0[3],$s[3] ; modulo-scheduled +|| EXTU $s[1],EXT3,24,$Te3[1] +|| EXTU $s[0],EXT1,24,$Te1[0] + LDW *${TEB}[$Te3[1]],$Te3[1] ; Te3[s1>>24], t2 +|| LDW *${TEA}[$Te1[0]],$Te1[0] ; Te1[s0>>8], t3 +|| EXTU $s[2],EXT2,24,$Te2[2] +|| EXTU $s[3],EXT2,24,$Te2[3] + LDW *${TEA}[$Te2[2]],$Te2[2] ; Te2[s2>>16], t0 +|| LDW *${TEB}[$Te2[3]],$Te2[3] ; Te2[s3>>16], t1 +|| EXTU $s[3],EXT3,24,$Te3[3] +|| EXTU $s[2],EXT1,24,$Te1[2] + LDW *${TEB}[$Te3[3]],$Te3[3] ; Te3[s3>>24], t0 +|| LDW *${TEA}[$Te1[2]],$Te1[2] ; Te1[s2>>8], t1 +|| EXTU $s[0],EXT2,24,$Te2[0] +|| EXTU $s[1],EXT2,24,$Te2[1] + LDW *${TEA}[$Te2[0]],$Te2[0] ; Te2[s0>>16], t2 +|| LDW *${TEB}[$Te2[1]],$Te2[1] ; Te2[s1>>16], t3 +|| EXTU $s[3],EXT1,24,$Te1[3] +|| EXTU $s[2],EXT3,24,$Te3[2] + LDW *${TEB}[$Te1[3]],$Te1[3] ; Te1[s3>>8], t2 +|| LDW *${TEA}[$Te3[2]],$Te3[2] ; Te3[s2>>24], t3 +|| ROTL $Te1[1],TBL1,$Te3[0] ; t0 +|| ROTL $Te3[0],TBL3,$Te1[1] ; t1 +|| EXTU $s[0],EXT0,24,$Te0[0] +|| EXTU $s[1],EXT0,24,$Te0[1] + LDW *${TEA}[$Te0[0]],$Te0[0] ; Te0[s0], t0 +|| LDW *${TEB}[$Te0[1]],$Te0[1] ; Te0[s1], t1 +|| ROTL $Te3[1],TBL3,$Te1[0] ; t2 +|| ROTL $Te1[0],TBL1,$Te3[1] ; t3 +|| EXTU $s[2],EXT0,24,$Te0[2] +|| EXTU $s[3],EXT0,24,$Te0[3] + LDW *${TEA}[$Te0[2]],$Te0[2] ; Te0[s2], t2 +|| LDW *${TEB}[$Te0[3]],$Te0[3] ; Te0[s3], t3 +|| ROTL $Te2[2],TBL2,$Te2[2] ; t0 +|| ROTL $Te2[3],TBL2,$Te2[3] ; t1 +|| XOR $K[0],$Te3[0],$s[0] +|| XOR $K[1],$Te1[1],$s[1] + ROTL $Te3[3],TBL3,$Te1[2] ; t0 +|| ROTL $Te1[2],TBL1,$Te3[3] ; t1 +|| XOR $K[2],$Te1[0],$s[2] +|| XOR $K[3],$Te3[1],$s[3] +|| LDW *$KPA++[2],$K[0] ; next round key +|| LDW *$KPB++[2],$K[1] + ROTL $Te2[0],TBL2,$Te2[0] ; t2 +|| ROTL $Te2[1],TBL2,$Te2[1] ; t3 +|| XOR $s[0],$Te2[2],$s[0] +|| XOR $s[1],$Te2[3],$s[1] +|| LDW *$KPA++[2],$K[2] +|| LDW *$KPB++[2],$K[3] + ROTL $Te1[3],TBL1,$Te3[2] ; t2 +|| ROTL $Te3[2],TBL3,$Te1[3] ; t3 +|| XOR $s[0],$Te1[2],$s[0] +|| XOR $s[1],$Te3[3],$s[1] + XOR $s[2],$Te2[0],$s[2] +|| XOR $s[3],$Te2[1],$s[3] +|| XOR $s[0],$Te0[0],$s[0] +|| XOR $s[1],$Te0[1],$s[1] + SPKERNEL +|| XOR.L $s[2],$Te3[2],$s[2] +|| XOR.L $s[3],$Te1[3],$s[3] +;;==================================================================== + ADD.D ${TEA},A0,${TEA} ; point to Te4 +|| ADD.D ${TEB},A0,${TEB} +|| EXTU $s[1],EXT1,24,$Te1[1] +|| EXTU $s[0],EXT3,24,$Te3[0] + LDBU *${TEB}[$Te1[1]],$Te1[1] ; Te1[s1>>8], t0 +|| LDBU *${TEA}[$Te3[0]],$Te3[0] ; Te3[s0>>24], t1 +|| XOR $s[2],$Te0[2],$s[2] ; modulo-scheduled +|| XOR $s[3],$Te0[3],$s[3] ; modulo-scheduled +|| EXTU $s[0],EXT0,24,$Te0[0] +|| EXTU $s[1],EXT0,24,$Te0[1] + LDBU *${TEA}[$Te0[0]],$Te0[0] ; Te0[s0], t0 +|| LDBU *${TEB}[$Te0[1]],$Te0[1] ; Te0[s1], t1 +|| EXTU $s[3],EXT3,24,$Te3[3] +|| EXTU $s[2],EXT1,24,$Te1[2] + LDBU *${TEB}[$Te3[3]],$Te3[3] ; Te3[s3>>24], t0 +|| LDBU *${TEA}[$Te1[2]],$Te1[2] ; Te1[s2>>8], t1 +|| EXTU $s[2],EXT2,24,$Te2[2] +|| EXTU $s[3],EXT2,24,$Te2[3] + LDBU *${TEA}[$Te2[2]],$Te2[2] ; Te2[s2>>16], t0 +|| LDBU *${TEB}[$Te2[3]],$Te2[3] ; Te2[s3>>16], t1 +|| EXTU $s[1],EXT3,24,$Te3[1] +|| EXTU $s[0],EXT1,24,$Te1[0] + LDBU *${TEB}[$Te3[1]],$Te3[1] ; Te3[s1>>24], t2 +|| LDBU *${TEA}[$Te1[0]],$Te1[0] ; Te1[s0>>8], t3 +|| EXTU $s[3],EXT1,24,$Te1[3] +|| EXTU $s[2],EXT3,24,$Te3[2] + LDBU *${TEB}[$Te1[3]],$Te1[3] ; Te1[s3>>8], t2 +|| LDBU *${TEA}[$Te3[2]],$Te3[2] ; Te3[s2>>24], t3 +|| EXTU $s[2],EXT0,24,$Te0[2] +|| EXTU $s[3],EXT0,24,$Te0[3] + LDBU *${TEA}[$Te0[2]],$Te0[2] ; Te0[s2], t2 +|| LDBU *${TEB}[$Te0[3]],$Te0[3] ; Te0[s3], t3 +|| EXTU $s[0],EXT2,24,$Te2[0] +|| EXTU $s[1],EXT2,24,$Te2[1] + LDBU *${TEA}[$Te2[0]],$Te2[0] ; Te2[s0>>16], t2 +|| LDBU *${TEB}[$Te2[1]],$Te2[1] ; Te2[s1>>16], t3 + + .if .BIG_ENDIAN + PACK2 $Te0[0],$Te1[1],$Te0[0] +|| PACK2 $Te0[1],$Te1[2],$Te0[1] + PACK2 $Te2[2],$Te3[3],$Te2[2] +|| PACK2 $Te2[3],$Te3[0],$Te2[3] + PACKL4 $Te0[0],$Te2[2],$Te0[0] +|| PACKL4 $Te0[1],$Te2[3],$Te0[1] + XOR $K[0],$Te0[0],$Te0[0] ; s[0] +|| XOR $K[1],$Te0[1],$Te0[1] ; s[1] + + PACK2 $Te0[2],$Te1[3],$Te0[2] +|| PACK2 $Te0[3],$Te1[0],$Te0[3] + PACK2 $Te2[0],$Te3[1],$Te2[0] +|| PACK2 $Te2[1],$Te3[2],$Te2[1] +|| BNOP RA + PACKL4 $Te0[2],$Te2[0],$Te0[2] +|| PACKL4 $Te0[3],$Te2[1],$Te0[3] + XOR $K[2],$Te0[2],$Te0[2] ; s[2] +|| XOR $K[3],$Te0[3],$Te0[3] ; s[3] + + MV $Te0[0],A9 +|| MV $Te0[1],A8 + MV $Te0[2],B9 +|| MV $Te0[3],B8 +|| [B2] STNDW A9:A8,*OUT++ + [B2] STNDW B9:B8,*OUT++ + .else + PACK2 $Te1[1],$Te0[0],$Te1[1] +|| PACK2 $Te1[2],$Te0[1],$Te1[2] + PACK2 $Te3[3],$Te2[2],$Te3[3] +|| PACK2 $Te3[0],$Te2[3],$Te3[0] + PACKL4 $Te3[3],$Te1[1],$Te1[1] +|| PACKL4 $Te3[0],$Te1[2],$Te1[2] + XOR $K[0],$Te1[1],$Te1[1] ; s[0] +|| XOR $K[1],$Te1[2],$Te1[2] ; s[1] + + PACK2 $Te1[3],$Te0[2],$Te1[3] +|| PACK2 $Te1[0],$Te0[3],$Te1[0] + PACK2 $Te3[1],$Te2[0],$Te3[1] +|| PACK2 $Te3[2],$Te2[1],$Te3[2] +|| BNOP RA + PACKL4 $Te3[1],$Te1[3],$Te1[3] +|| PACKL4 $Te3[2],$Te1[0],$Te1[0] + XOR $K[2],$Te1[3],$Te1[3] ; s[2] +|| XOR $K[3],$Te1[0],$Te1[0] ; s[3] + + MV $Te1[1],A8 +|| MV $Te1[2],A9 + MV $Te1[3],B8 +|| MV $Te1[0],B9 +|| [B2] STNDW A9:A8,*OUT++ + [B2] STNDW B9:B8,*OUT++ + .endif + .endasmfunc + + .global _AES_decrypt +_AES_decrypt: + .asmfunc + MVK 1,B2 +__decrypt: + .if __TI_EABI__ + [B2] LDNDW *INP++,A9:A8 ; load input +|| MVKL \$PCR_OFFSET(AES_Td,__decrypt),$TEA +|| ADDKPC __decrypt,B0 + [B2] LDNDW *INP++,B9:B8 +|| MVKH \$PCR_OFFSET(AES_Td,__decrypt),$TEA +|| ADD 0,KEY,$KPA +|| ADD 4,KEY,$KPB + .else + [B2] LDNDW *INP++,A9:A8 ; load input +|| MVKL (AES_Td-__decrypt),$TEA +|| ADDKPC __decrypt,B0 + [B2] LDNDW *INP++,B9:B8 +|| MVKH (AES_Td-__decrypt),$TEA +|| ADD 0,KEY,$KPA +|| ADD 4,KEY,$KPB + .endif + LDW *$KPA++[2],$Td0[0] ; zero round key +|| LDW *$KPB++[2],$Td0[1] +|| MVK 60,A0 +|| ADD B0,$TEA,$TEA ; AES_Td + LDW *KEY[A0],B0 ; rounds +|| MVK 1024,A0 ; sizeof(AES_Td) + LDW *$KPA++[2],$Td0[2] +|| LDW *$KPB++[2],$Td0[3] +|| MV $TEA,$TEB + NOP + .if .BIG_ENDIAN + MV A9,$s[0] +|| MV A8,$s[1] +|| MV B9,$s[2] +|| MV B8,$s[3] + .else + MV A8,$s[0] +|| MV A9,$s[1] +|| MV B8,$s[2] +|| MV B9,$s[3] + .endif + XOR $Td0[0],$s[0],$s[0] +|| XOR $Td0[1],$s[1],$s[1] +|| LDW *$KPA++[2],$K[0] ; 1st round key +|| LDW *$KPB++[2],$K[1] + SUB B0,2,B0 + + SPLOOPD 13 +|| MVC B0,ILC +|| LDW *$KPA++[2],$K[2] +|| LDW *$KPB++[2],$K[3] +;;==================================================================== + EXTU $s[1],EXT3,24,$Td3[1] +|| EXTU $s[0],EXT1,24,$Td1[0] + LDW *${TEB}[$Td3[1]],$Td3[1] ; Td3[s1>>24], t0 +|| LDW *${TEA}[$Td1[0]],$Td1[0] ; Td1[s0>>8], t1 +|| XOR $s[2],$Td0[2],$s[2] ; modulo-scheduled +|| XOR $s[3],$Td0[3],$s[3] ; modulo-scheduled +|| EXTU $s[1],EXT1,24,$Td1[1] +|| EXTU $s[0],EXT3,24,$Td3[0] + LDW *${TEB}[$Td1[1]],$Td1[1] ; Td1[s1>>8], t2 +|| LDW *${TEA}[$Td3[0]],$Td3[0] ; Td3[s0>>24], t3 +|| EXTU $s[2],EXT2,24,$Td2[2] +|| EXTU $s[3],EXT2,24,$Td2[3] + LDW *${TEA}[$Td2[2]],$Td2[2] ; Td2[s2>>16], t0 +|| LDW *${TEB}[$Td2[3]],$Td2[3] ; Td2[s3>>16], t1 +|| EXTU $s[3],EXT1,24,$Td1[3] +|| EXTU $s[2],EXT3,24,$Td3[2] + LDW *${TEB}[$Td1[3]],$Td1[3] ; Td1[s3>>8], t0 +|| LDW *${TEA}[$Td3[2]],$Td3[2] ; Td3[s2>>24], t1 +|| EXTU $s[0],EXT2,24,$Td2[0] +|| EXTU $s[1],EXT2,24,$Td2[1] + LDW *${TEA}[$Td2[0]],$Td2[0] ; Td2[s0>>16], t2 +|| LDW *${TEB}[$Td2[1]],$Td2[1] ; Td2[s1>>16], t3 +|| EXTU $s[3],EXT3,24,$Td3[3] +|| EXTU $s[2],EXT1,24,$Td1[2] + LDW *${TEB}[$Td3[3]],$Td3[3] ; Td3[s3>>24], t2 +|| LDW *${TEA}[$Td1[2]],$Td1[2] ; Td1[s2>>8], t3 +|| ROTL $Td3[1],TBL3,$Td1[0] ; t0 +|| ROTL $Td1[0],TBL1,$Td3[1] ; t1 +|| EXTU $s[0],EXT0,24,$Td0[0] +|| EXTU $s[1],EXT0,24,$Td0[1] + LDW *${TEA}[$Td0[0]],$Td0[0] ; Td0[s0], t0 +|| LDW *${TEB}[$Td0[1]],$Td0[1] ; Td0[s1], t1 +|| ROTL $Td1[1],TBL1,$Td3[0] ; t2 +|| ROTL $Td3[0],TBL3,$Td1[1] ; t3 +|| EXTU $s[2],EXT0,24,$Td0[2] +|| EXTU $s[3],EXT0,24,$Td0[3] + LDW *${TEA}[$Td0[2]],$Td0[2] ; Td0[s2], t2 +|| LDW *${TEB}[$Td0[3]],$Td0[3] ; Td0[s3], t3 +|| ROTL $Td2[2],TBL2,$Td2[2] ; t0 +|| ROTL $Td2[3],TBL2,$Td2[3] ; t1 +|| XOR $K[0],$Td1[0],$s[0] +|| XOR $K[1],$Td3[1],$s[1] + ROTL $Td1[3],TBL1,$Td3[2] ; t0 +|| ROTL $Td3[2],TBL3,$Td1[3] ; t1 +|| XOR $K[2],$Td3[0],$s[2] +|| XOR $K[3],$Td1[1],$s[3] +|| LDW *$KPA++[2],$K[0] ; next round key +|| LDW *$KPB++[2],$K[1] + ROTL $Td2[0],TBL2,$Td2[0] ; t2 +|| ROTL $Td2[1],TBL2,$Td2[1] ; t3 +|| XOR $s[0],$Td2[2],$s[0] +|| XOR $s[1],$Td2[3],$s[1] +|| LDW *$KPA++[2],$K[2] +|| LDW *$KPB++[2],$K[3] + ROTL $Td3[3],TBL3,$Td1[2] ; t2 +|| ROTL $Td1[2],TBL1,$Td3[3] ; t3 +|| XOR $s[0],$Td3[2],$s[0] +|| XOR $s[1],$Td1[3],$s[1] + XOR $s[2],$Td2[0],$s[2] +|| XOR $s[3],$Td2[1],$s[3] +|| XOR $s[0],$Td0[0],$s[0] +|| XOR $s[1],$Td0[1],$s[1] + SPKERNEL +|| XOR.L $s[2],$Td1[2],$s[2] +|| XOR.L $s[3],$Td3[3],$s[3] +;;==================================================================== + ADD.D ${TEA},A0,${TEA} ; point to Td4 +|| ADD.D ${TEB},A0,${TEB} +|| EXTU $s[1],EXT3,24,$Td3[1] +|| EXTU $s[0],EXT1,24,$Td1[0] + LDBU *${TEB}[$Td3[1]],$Td3[1] ; Td3[s1>>24], t0 +|| LDBU *${TEA}[$Td1[0]],$Td1[0] ; Td1[s0>>8], t1 +|| XOR $s[2],$Td0[2],$s[2] ; modulo-scheduled +|| XOR $s[3],$Td0[3],$s[3] ; modulo-scheduled +|| EXTU $s[0],EXT0,24,$Td0[0] +|| EXTU $s[1],EXT0,24,$Td0[1] + LDBU *${TEA}[$Td0[0]],$Td0[0] ; Td0[s0], t0 +|| LDBU *${TEB}[$Td0[1]],$Td0[1] ; Td0[s1], t1 +|| EXTU $s[2],EXT2,24,$Td2[2] +|| EXTU $s[3],EXT2,24,$Td2[3] + LDBU *${TEA}[$Td2[2]],$Td2[2] ; Td2[s2>>16], t0 +|| LDBU *${TEB}[$Td2[3]],$Td2[3] ; Td2[s3>>16], t1 +|| EXTU $s[3],EXT1,24,$Td1[3] +|| EXTU $s[2],EXT3,24,$Td3[2] + LDBU *${TEB}[$Td1[3]],$Td1[3] ; Td1[s3>>8], t0 +|| LDBU *${TEA}[$Td3[2]],$Td3[2] ; Td3[s2>>24], t1 +|| EXTU $s[1],EXT1,24,$Td1[1] +|| EXTU $s[0],EXT3,24,$Td3[0] + LDBU *${TEB}[$Td1[1]],$Td1[1] ; Td1[s1>>8], t2 +|| LDBU *${TEA}[$Td3[0]],$Td3[0] ; Td3[s0>>24], t3 +|| EXTU $s[0],EXT2,24,$Td2[0] +|| EXTU $s[1],EXT2,24,$Td2[1] + LDBU *${TEA}[$Td2[0]],$Td2[0] ; Td2[s0>>16], t2 +|| LDBU *${TEB}[$Td2[1]],$Td2[1] ; Td2[s1>>16], t3 +|| EXTU $s[3],EXT3,24,$Td3[3] +|| EXTU $s[2],EXT1,24,$Td1[2] + LDBU *${TEB}[$Td3[3]],$Td3[3] ; Td3[s3>>24], t2 +|| LDBU *${TEA}[$Td1[2]],$Td1[2] ; Td1[s2>>8], t3 +|| EXTU $s[2],EXT0,24,$Td0[2] +|| EXTU $s[3],EXT0,24,$Td0[3] + LDBU *${TEA}[$Td0[2]],$Td0[2] ; Td0[s2], t2 +|| LDBU *${TEB}[$Td0[3]],$Td0[3] ; Td0[s3], t3 + + .if .BIG_ENDIAN + PACK2 $Td0[0],$Td1[3],$Td0[0] +|| PACK2 $Td0[1],$Td1[0],$Td0[1] + PACK2 $Td2[2],$Td3[1],$Td2[2] +|| PACK2 $Td2[3],$Td3[2],$Td2[3] + PACKL4 $Td0[0],$Td2[2],$Td0[0] +|| PACKL4 $Td0[1],$Td2[3],$Td0[1] + XOR $K[0],$Td0[0],$Td0[0] ; s[0] +|| XOR $K[1],$Td0[1],$Td0[1] ; s[1] + + PACK2 $Td0[2],$Td1[1],$Td0[2] +|| PACK2 $Td0[3],$Td1[2],$Td0[3] + PACK2 $Td2[0],$Td3[3],$Td2[0] +|| PACK2 $Td2[1],$Td3[0],$Td2[1] +|| BNOP RA + PACKL4 $Td0[2],$Td2[0],$Td0[2] +|| PACKL4 $Td0[3],$Td2[1],$Td0[3] + XOR $K[2],$Td0[2],$Td0[2] ; s[2] +|| XOR $K[3],$Td0[3],$Td0[3] ; s[3] + + MV $Td0[0],A9 +|| MV $Td0[1],A8 + MV $Td0[2],B9 +|| MV $Td0[3],B8 +|| [B2] STNDW A9:A8,*OUT++ + [B2] STNDW B9:B8,*OUT++ + .else + PACK2 $Td1[3],$Td0[0],$Td1[3] +|| PACK2 $Td1[0],$Td0[1],$Td1[0] + PACK2 $Td3[1],$Td2[2],$Td3[1] +|| PACK2 $Td3[2],$Td2[3],$Td3[2] + PACKL4 $Td3[1],$Td1[3],$Td1[3] +|| PACKL4 $Td3[2],$Td1[0],$Td1[0] + XOR $K[0],$Td1[3],$Td1[3] ; s[0] +|| XOR $K[1],$Td1[0],$Td1[0] ; s[1] + + PACK2 $Td1[1],$Td0[2],$Td1[1] +|| PACK2 $Td1[2],$Td0[3],$Td1[2] + PACK2 $Td3[3],$Td2[0],$Td3[3] +|| PACK2 $Td3[0],$Td2[1],$Td3[0] +|| BNOP RA + PACKL4 $Td3[3],$Td1[1],$Td1[1] +|| PACKL4 $Td3[0],$Td1[2],$Td1[2] + XOR $K[2],$Td1[1],$Td1[1] ; s[2] +|| XOR $K[3],$Td1[2],$Td1[2] ; s[3] + + MV $Td1[3],A8 +|| MV $Td1[0],A9 + MV $Td1[1],B8 +|| MV $Td1[2],B9 +|| [B2] STNDW A9:A8,*OUT++ + [B2] STNDW B9:B8,*OUT++ + .endif + .endasmfunc +___ +{ +my @K=(@K,@s); # extended key +my @Te4=map("B$_",(16..19)); + +my @Kx9=@Te0; # used in AES_set_decrypt_key +my @KxB=@Te1; +my @KxD=@Te2; +my @KxE=@Te3; + +$code.=<<___; + .asg OUT,BITS + + .global _AES_set_encrypt_key +_AES_set_encrypt_key: +__set_encrypt_key: + .asmfunc + MV INP,A0 +|| SHRU BITS,5,BITS ; 128-192-256 -> 4-6-8 +|| MV KEY,A1 + [!A0] B RA +||[!A0] MVK -1,RET +||[!A0] MVK 1,A1 ; only one B RA + [!A1] B RA +||[!A1] MVK -1,RET +||[!A1] MVK 0,A0 +|| MVK 0,B0 +|| MVK 0,A1 + [A0] LDNDW *INP++,A9:A8 +|| [A0] CMPEQ 4,BITS,B0 +|| [A0] CMPLT 3,BITS,A1 + [B0] B key128? +|| [A1] LDNDW *INP++,B9:B8 +|| [A0] CMPEQ 6,BITS,B0 +|| [A0] CMPLT 5,BITS,A1 + [B0] B key192? +|| [A1] LDNDW *INP++,B17:B16 +|| [A0] CMPEQ 8,BITS,B0 +|| [A0] CMPLT 7,BITS,A1 + [B0] B key256? +|| [A1] LDNDW *INP++,B19:B18 + + .if __TI_EABI__ + [A0] ADD 0,KEY,$KPA +|| [A0] ADD 4,KEY,$KPB +|| [A0] MVKL \$PCR_OFFSET(AES_Te4,__set_encrypt_key),$TEA +|| [A0] ADDKPC __set_encrypt_key,B6 + [A0] MVKH \$PCR_OFFSET(AES_Te4,__set_encrypt_key),$TEA + [A0] ADD B6,$TEA,$TEA ; AES_Te4 + .else + [A0] ADD 0,KEY,$KPA +|| [A0] ADD 4,KEY,$KPB +|| [A0] MVKL (AES_Te4-__set_encrypt_key),$TEA +|| [A0] ADDKPC __set_encrypt_key,B6 + [A0] MVKH (AES_Te4-__set_encrypt_key),$TEA + [A0] ADD B6,$TEA,$TEA ; AES_Te4 + .endif + NOP + NOP + + BNOP RA,5 +|| MVK -2,RET ; unknown bit length +|| MVK 0,B0 ; redundant +;;==================================================================== +;;==================================================================== +key128?: + .if .BIG_ENDIAN + MV A9,$K[0] +|| MV A8,$K[1] +|| MV B9,$Te4[2] +|| MV B8,$K[3] + .else + MV A8,$K[0] +|| MV A9,$K[1] +|| MV B8,$Te4[2] +|| MV B9,$K[3] + .endif + + MVK 256,A0 +|| MVK 9,B0 + + SPLOOPD 14 +|| MVC B0,ILC +|| MV $TEA,$TEB +|| ADD $TEA,A0,A30 ; rcon +;;==================================================================== + LDW *A30++[1],A31 ; rcon[i] +|| MV $Te4[2],$K[2] +|| EXTU $K[3],EXT1,24,$Te4[0] + LDBU *${TEB}[$Te4[0]],$Te4[0] +|| MV $K[3],A0 +|| EXTU $K[3],EXT2,24,$Te4[1] + LDBU *${TEB}[$Te4[1]],$Te4[1] +|| EXTU A0,EXT3,24,A0 +|| EXTU $K[3],EXT0,24,$Te4[3] + .if .BIG_ENDIAN + LDBU *${TEA}[A0],$Te4[3] +|| LDBU *${TEB}[$Te4[3]],A0 + .else + LDBU *${TEA}[A0],A0 +|| LDBU *${TEB}[$Te4[3]],$Te4[3] + .endif + + STW $K[0],*$KPA++[2] +|| STW $K[1],*$KPB++[2] + STW $K[2],*$KPA++[2] +|| STW $K[3],*$KPB++[2] + + XOR A31,$K[0],$K[0] ; ^=rcon[i] + .if .BIG_ENDIAN + PACK2 $Te4[0],$Te4[1],$Te4[1] + PACK2 $Te4[3],A0,$Te4[3] + PACKL4 $Te4[1],$Te4[3],$Te4[3] + .else + PACK2 $Te4[1],$Te4[0],$Te4[1] + PACK2 $Te4[3],A0,$Te4[3] + PACKL4 $Te4[3],$Te4[1],$Te4[3] + .endif + XOR $Te4[3],$K[0],$Te4[0] ; K[0] + XOR $Te4[0],$K[1],$K[1] ; K[1] + MV $Te4[0],$K[0] +|| XOR $K[1],$K[2],$Te4[2] ; K[2] + XOR $Te4[2],$K[3],$K[3] ; K[3] + SPKERNEL +;;==================================================================== + BNOP RA + MV $Te4[2],$K[2] +|| STW $K[0],*$KPA++[2] +|| STW $K[1],*$KPB++[2] + STW $K[2],*$KPA++[2] +|| STW $K[3],*$KPB++[2] + MVK 10,B0 ; rounds + STW B0,*++${KPB}[15] + MVK 0,RET +;;==================================================================== +;;==================================================================== +key192?: + .if .BIG_ENDIAN + MV A9,$K[0] +|| MV A8,$K[1] +|| MV B9,$K[2] +|| MV B8,$K[3] + MV B17,$Te4[2] +|| MV B16,$K[5] + .else + MV A8,$K[0] +|| MV A9,$K[1] +|| MV B8,$K[2] +|| MV B9,$K[3] + MV B16,$Te4[2] +|| MV B17,$K[5] + .endif + + MVK 256,A0 +|| MVK 6,B0 + MV $TEA,$TEB +|| ADD $TEA,A0,A30 ; rcon +;;==================================================================== +loop192?: + LDW *A30++[1],A31 ; rcon[i] +|| MV $Te4[2],$K[4] +|| EXTU $K[5],EXT1,24,$Te4[0] + LDBU *${TEB}[$Te4[0]],$Te4[0] +|| MV $K[5],A0 +|| EXTU $K[5],EXT2,24,$Te4[1] + LDBU *${TEB}[$Te4[1]],$Te4[1] +|| EXTU A0,EXT3,24,A0 +|| EXTU $K[5],EXT0,24,$Te4[3] + .if .BIG_ENDIAN + LDBU *${TEA}[A0],$Te4[3] +|| LDBU *${TEB}[$Te4[3]],A0 + .else + LDBU *${TEA}[A0],A0 +|| LDBU *${TEB}[$Te4[3]],$Te4[3] + .endif + + STW $K[0],*$KPA++[2] +|| STW $K[1],*$KPB++[2] + STW $K[2],*$KPA++[2] +|| STW $K[3],*$KPB++[2] + STW $K[4],*$KPA++[2] +|| STW $K[5],*$KPB++[2] + + XOR A31,$K[0],$K[0] ; ^=rcon[i] + .if .BIG_ENDIAN + PACK2 $Te4[0],$Te4[1],$Te4[1] +|| PACK2 $Te4[3],A0,$Te4[3] + PACKL4 $Te4[1],$Te4[3],$Te4[3] + .else + PACK2 $Te4[1],$Te4[0],$Te4[1] +|| PACK2 $Te4[3],A0,$Te4[3] + PACKL4 $Te4[3],$Te4[1],$Te4[3] + .endif + BDEC loop192?,B0 +|| XOR $Te4[3],$K[0],$Te4[0] ; K[0] + XOR $Te4[0],$K[1],$K[1] ; K[1] + MV $Te4[0],$K[0] +|| XOR $K[1],$K[2],$Te4[2] ; K[2] + XOR $Te4[2],$K[3],$K[3] ; K[3] + MV $Te4[2],$K[2] +|| XOR $K[3],$K[4],$Te4[2] ; K[4] + XOR $Te4[2],$K[5],$K[5] ; K[5] +;;==================================================================== + BNOP RA + STW $K[0],*$KPA++[2] +|| STW $K[1],*$KPB++[2] + STW $K[2],*$KPA++[2] +|| STW $K[3],*$KPB++[2] + MVK 12,B0 ; rounds + STW B0,*++${KPB}[7] + MVK 0,RET +;;==================================================================== +;;==================================================================== +key256?: + .if .BIG_ENDIAN + MV A9,$K[0] +|| MV A8,$K[1] +|| MV B9,$K[2] +|| MV B8,$K[3] + MV B17,$K[4] +|| MV B16,$K[5] +|| MV B19,$Te4[2] +|| MV B18,$K[7] + .else + MV A8,$K[0] +|| MV A9,$K[1] +|| MV B8,$K[2] +|| MV B9,$K[3] + MV B16,$K[4] +|| MV B17,$K[5] +|| MV B18,$Te4[2] +|| MV B19,$K[7] + .endif + + MVK 256,A0 +|| MVK 6,B0 + MV $TEA,$TEB +|| ADD $TEA,A0,A30 ; rcon +;;==================================================================== +loop256?: + LDW *A30++[1],A31 ; rcon[i] +|| MV $Te4[2],$K[6] +|| EXTU $K[7],EXT1,24,$Te4[0] + LDBU *${TEB}[$Te4[0]],$Te4[0] +|| MV $K[7],A0 +|| EXTU $K[7],EXT2,24,$Te4[1] + LDBU *${TEB}[$Te4[1]],$Te4[1] +|| EXTU A0,EXT3,24,A0 +|| EXTU $K[7],EXT0,24,$Te4[3] + .if .BIG_ENDIAN + LDBU *${TEA}[A0],$Te4[3] +|| LDBU *${TEB}[$Te4[3]],A0 + .else + LDBU *${TEA}[A0],A0 +|| LDBU *${TEB}[$Te4[3]],$Te4[3] + .endif + + STW $K[0],*$KPA++[2] +|| STW $K[1],*$KPB++[2] + STW $K[2],*$KPA++[2] +|| STW $K[3],*$KPB++[2] + STW $K[4],*$KPA++[2] +|| STW $K[5],*$KPB++[2] + STW $K[6],*$KPA++[2] +|| STW $K[7],*$KPB++[2] +|| XOR A31,$K[0],$K[0] ; ^=rcon[i] + .if .BIG_ENDIAN + PACK2 $Te4[0],$Te4[1],$Te4[1] +|| PACK2 $Te4[3],A0,$Te4[3] + PACKL4 $Te4[1],$Te4[3],$Te4[3] +||[!B0] B done256? + .else + PACK2 $Te4[1],$Te4[0],$Te4[1] +|| PACK2 $Te4[3],A0,$Te4[3] + PACKL4 $Te4[3],$Te4[1],$Te4[3] +||[!B0] B done256? + .endif + XOR $Te4[3],$K[0],$Te4[0] ; K[0] + XOR $Te4[0],$K[1],$K[1] ; K[1] + MV $Te4[0],$K[0] +|| XOR $K[1],$K[2],$Te4[2] ; K[2] + XOR $Te4[2],$K[3],$K[3] ; K[3] + + MV $Te4[2],$K[2] +|| [B0] EXTU $K[3],EXT0,24,$Te4[0] +|| [B0] SUB B0,1,B0 + LDBU *${TEB}[$Te4[0]],$Te4[0] +|| MV $K[3],A0 +|| EXTU $K[3],EXT1,24,$Te4[1] + LDBU *${TEB}[$Te4[1]],$Te4[1] +|| EXTU A0,EXT2,24,A0 +|| EXTU $K[3],EXT3,24,$Te4[3] + + .if .BIG_ENDIAN + LDBU *${TEA}[A0],$Te4[3] +|| LDBU *${TEB}[$Te4[3]],A0 + NOP 3 + PACK2 $Te4[0],$Te4[1],$Te4[1] + PACK2 $Te4[3],A0,$Te4[3] +|| B loop256? + PACKL4 $Te4[1],$Te4[3],$Te4[3] + .else + LDBU *${TEA}[A0],A0 +|| LDBU *${TEB}[$Te4[3]],$Te4[3] + NOP 3 + PACK2 $Te4[1],$Te4[0],$Te4[1] + PACK2 $Te4[3],A0,$Te4[3] +|| B loop256? + PACKL4 $Te4[3],$Te4[1],$Te4[3] + .endif + + XOR $Te4[3],$K[4],$Te4[0] ; K[4] + XOR $Te4[0],$K[5],$K[5] ; K[5] + MV $Te4[0],$K[4] +|| XOR $K[5],$K[6],$Te4[2] ; K[6] + XOR $Te4[2],$K[7],$K[7] ; K[7] +;;==================================================================== +done256?: + BNOP RA + STW $K[0],*$KPA++[2] +|| STW $K[1],*$KPB++[2] + STW $K[2],*$KPA++[2] +|| STW $K[3],*$KPB++[2] + MVK 14,B0 ; rounds + STW B0,*--${KPB}[1] + MVK 0,RET + .endasmfunc + + .global _AES_set_decrypt_key +_AES_set_decrypt_key: + .asmfunc + B __set_encrypt_key ; guarantee local call + MV KEY,B30 ; B30 is not modified + MV RA, B31 ; B31 is not modified + ADDKPC ret?,RA,2 +ret?: ; B0 holds rounds or zero + [!B0] BNOP B31 ; return if zero + [B0] SHL B0,4,A0 ; offset to last round key + [B0] SHRU B0,1,B1 + [B0] SUB B1,1,B1 + [B0] MVK 0x0000001B,B3 ; AES polynomial + [B0] MVKH 0x07000000,B3 + + SPLOOPD 9 ; flip round keys +|| MVC B1,ILC +|| MV B30,$KPA +|| ADD B30,A0,$KPB +|| MVK 16,A0 ; sizeof(round key) +;;==================================================================== + LDW *${KPA}[0],A16 +|| LDW *${KPB}[0],B16 + LDW *${KPA}[1],A17 +|| LDW *${KPB}[1],B17 + LDW *${KPA}[2],A18 +|| LDW *${KPB}[2],B18 + LDW *${KPA}[3],A19 +|| ADD $KPA,A0,$KPA +|| LDW *${KPB}[3],B19 +|| SUB $KPB,A0,$KPB + NOP + STW B16,*${KPA}[-4] +|| STW A16,*${KPB}[4] + STW B17,*${KPA}[-3] +|| STW A17,*${KPB}[5] + STW B18,*${KPA}[-2] +|| STW A18,*${KPB}[6] + STW B19,*${KPA}[-1] +|| STW A19,*${KPB}[7] + SPKERNEL +;;==================================================================== + SUB B0,1,B0 ; skip last round +|| ADD B30,A0,$KPA ; skip first round +|| ADD B30,A0,$KPB +|| MVC GFPGFR,B30 ; save GFPGFR + LDW *${KPA}[0],$K[0] +|| LDW *${KPB}[1],$K[1] +|| MVC B3,GFPGFR + LDW *${KPA}[2],$K[2] +|| LDW *${KPB}[3],$K[3] + MVK 0x00000909,A24 +|| MVK 0x00000B0B,B24 + MVKH 0x09090000,A24 +|| MVKH 0x0B0B0000,B24 + MVC B0,ILC +|| SUB B0,1,B0 + + GMPY4 $K[0],A24,$Kx9[0] ; ·0x09 +|| GMPY4 $K[1],A24,$Kx9[1] +|| MVK 0x00000D0D,A25 +|| MVK 0x00000E0E,B25 + GMPY4 $K[2],A24,$Kx9[2] +|| GMPY4 $K[3],A24,$Kx9[3] +|| MVKH 0x0D0D0000,A25 +|| MVKH 0x0E0E0000,B25 + + GMPY4 $K[0],B24,$KxB[0] ; ·0x0B +|| GMPY4 $K[1],B24,$KxB[1] + GMPY4 $K[2],B24,$KxB[2] +|| GMPY4 $K[3],B24,$KxB[3] + + SPLOOP 11 ; InvMixColumns +;;==================================================================== + GMPY4 $K[0],A25,$KxD[0] ; ·0x0D +|| GMPY4 $K[1],A25,$KxD[1] +|| SWAP2 $Kx9[0],$Kx9[0] ; rotate by 16 +|| SWAP2 $Kx9[1],$Kx9[1] +|| MV $K[0],$s[0] ; this or DINT +|| MV $K[1],$s[1] +|| [B0] LDW *${KPA}[4],$K[0] +|| [B0] LDW *${KPB}[5],$K[1] + GMPY4 $K[2],A25,$KxD[2] +|| GMPY4 $K[3],A25,$KxD[3] +|| SWAP2 $Kx9[2],$Kx9[2] +|| SWAP2 $Kx9[3],$Kx9[3] +|| MV $K[2],$s[2] +|| MV $K[3],$s[3] +|| [B0] LDW *${KPA}[6],$K[2] +|| [B0] LDW *${KPB}[7],$K[3] + + GMPY4 $s[0],B25,$KxE[0] ; ·0x0E +|| GMPY4 $s[1],B25,$KxE[1] +|| XOR $Kx9[0],$KxB[0],$KxB[0] +|| XOR $Kx9[1],$KxB[1],$KxB[1] + GMPY4 $s[2],B25,$KxE[2] +|| GMPY4 $s[3],B25,$KxE[3] +|| XOR $Kx9[2],$KxB[2],$KxB[2] +|| XOR $Kx9[3],$KxB[3],$KxB[3] + + ROTL $KxB[0],TBL3,$KxB[0] +|| ROTL $KxB[1],TBL3,$KxB[1] +|| SWAP2 $KxD[0],$KxD[0] ; rotate by 16 +|| SWAP2 $KxD[1],$KxD[1] + ROTL $KxB[2],TBL3,$KxB[2] +|| ROTL $KxB[3],TBL3,$KxB[3] +|| SWAP2 $KxD[2],$KxD[2] +|| SWAP2 $KxD[3],$KxD[3] + + XOR $KxE[0],$KxD[0],$KxE[0] +|| XOR $KxE[1],$KxD[1],$KxE[1] +|| [B0] GMPY4 $K[0],A24,$Kx9[0] ; ·0x09 +|| [B0] GMPY4 $K[1],A24,$Kx9[1] +|| ADDAW $KPA,4,$KPA + XOR $KxE[2],$KxD[2],$KxE[2] +|| XOR $KxE[3],$KxD[3],$KxE[3] +|| [B0] GMPY4 $K[2],A24,$Kx9[2] +|| [B0] GMPY4 $K[3],A24,$Kx9[3] +|| ADDAW $KPB,4,$KPB + + XOR $KxB[0],$KxE[0],$KxE[0] +|| XOR $KxB[1],$KxE[1],$KxE[1] +|| [B0] GMPY4 $K[0],B24,$KxB[0] ; ·0x0B +|| [B0] GMPY4 $K[1],B24,$KxB[1] + XOR $KxB[2],$KxE[2],$KxE[2] +|| XOR $KxB[3],$KxE[3],$KxE[3] +|| [B0] GMPY4 $K[2],B24,$KxB[2] +|| [B0] GMPY4 $K[3],B24,$KxB[3] +|| STW $KxE[0],*${KPA}[-4] +|| STW $KxE[1],*${KPB}[-3] + STW $KxE[2],*${KPA}[-2] +|| STW $KxE[3],*${KPB}[-1] +|| [B0] SUB B0,1,B0 + SPKERNEL +;;==================================================================== + BNOP B31,3 + MVC B30,GFPGFR ; restore GFPGFR(*) + MVK 0,RET + .endasmfunc +___ +# (*) Even though ABI doesn't specify GFPGFR as non-volatile, there +# are code samples out there that *assume* its default value. +} +{ +my ($inp,$out,$blocks,$key,$ivp)=("A4","B4","A6","B6","A8"); +$code.=<<___; + .global _AES_ctr32_encrypt +_AES_ctr32_encrypt: + .asmfunc + LDNDW *${ivp}[0],A31:A30 ; load counter value +|| MV $blocks,A2 ; reassign $blocks +|| DMV RA,$key,B27:B26 ; reassign RA and $key + LDNDW *${ivp}[1],B31:B30 +|| MVK 0,B2 ; don't let __encrypt load input +|| MVK 0,A1 ; and postpone writing output + .if .BIG_ENDIAN + NOP + .else + NOP 4 + SWAP2 B31,B31 ; keep least significant 32 bits + SWAP4 B31,B31 ; in host byte order + .endif +ctr32_loop?: + [A2] BNOP __encrypt +|| [A1] XOR A29,A9,A9 ; input^Ek(counter) +|| [A1] XOR A28,A8,A8 +|| [A2] LDNDW *INP++,A29:A28 ; load input + [!A2] BNOP B27 ; return +|| [A1] XOR B29,B9,B9 +|| [A1] XOR B28,B8,B8 +|| [A2] LDNDW *INP++,B29:B28 + .if .BIG_ENDIAN + [A1] STNDW A9:A8,*OUT++ ; save output +|| [A2] DMV A31,A30,A9:A8 ; pass counter value to __encrypt + [A1] STNDW B9:B8,*OUT++ +|| [A2] DMV B31,B30,B9:B8 +|| [A2] ADD B30,1,B30 ; counter++ + .else + [A1] STNDW A9:A8,*OUT++ ; save output +|| [A2] DMV A31,A30,A9:A8 +|| [A2] SWAP2 B31,B0 +|| [A2] ADD B31,1,B31 ; counter++ + [A1] STNDW B9:B8,*OUT++ +|| [A2] MV B30,B8 +|| [A2] SWAP4 B0,B9 + .endif + [A2] ADDKPC ctr32_loop?,RA ; return to ctr32_loop? +|| [A2] MV B26,KEY ; pass $key +|| [A2] SUB A2,1,A2 ; $blocks-- +||[!A1] MVK 1,A1 + NOP + NOP + .endasmfunc +___ +} +# Tables are kept in endian-neutral manner +$code.=<<___; + .if __TI_EABI__ + .sect ".text:aes_asm.const" + .else + .sect ".const:aes_asm" + .endif + .align 128 +AES_Te: + .byte 0xc6,0x63,0x63,0xa5, 0xf8,0x7c,0x7c,0x84 + .byte 0xee,0x77,0x77,0x99, 0xf6,0x7b,0x7b,0x8d + .byte 0xff,0xf2,0xf2,0x0d, 0xd6,0x6b,0x6b,0xbd + .byte 0xde,0x6f,0x6f,0xb1, 0x91,0xc5,0xc5,0x54 + .byte 0x60,0x30,0x30,0x50, 0x02,0x01,0x01,0x03 + .byte 0xce,0x67,0x67,0xa9, 0x56,0x2b,0x2b,0x7d + .byte 0xe7,0xfe,0xfe,0x19, 0xb5,0xd7,0xd7,0x62 + .byte 0x4d,0xab,0xab,0xe6, 0xec,0x76,0x76,0x9a + .byte 0x8f,0xca,0xca,0x45, 0x1f,0x82,0x82,0x9d + .byte 0x89,0xc9,0xc9,0x40, 0xfa,0x7d,0x7d,0x87 + .byte 0xef,0xfa,0xfa,0x15, 0xb2,0x59,0x59,0xeb + .byte 0x8e,0x47,0x47,0xc9, 0xfb,0xf0,0xf0,0x0b + .byte 0x41,0xad,0xad,0xec, 0xb3,0xd4,0xd4,0x67 + .byte 0x5f,0xa2,0xa2,0xfd, 0x45,0xaf,0xaf,0xea + .byte 0x23,0x9c,0x9c,0xbf, 0x53,0xa4,0xa4,0xf7 + .byte 0xe4,0x72,0x72,0x96, 0x9b,0xc0,0xc0,0x5b + .byte 0x75,0xb7,0xb7,0xc2, 0xe1,0xfd,0xfd,0x1c + .byte 0x3d,0x93,0x93,0xae, 0x4c,0x26,0x26,0x6a + .byte 0x6c,0x36,0x36,0x5a, 0x7e,0x3f,0x3f,0x41 + .byte 0xf5,0xf7,0xf7,0x02, 0x83,0xcc,0xcc,0x4f + .byte 0x68,0x34,0x34,0x5c, 0x51,0xa5,0xa5,0xf4 + .byte 0xd1,0xe5,0xe5,0x34, 0xf9,0xf1,0xf1,0x08 + .byte 0xe2,0x71,0x71,0x93, 0xab,0xd8,0xd8,0x73 + .byte 0x62,0x31,0x31,0x53, 0x2a,0x15,0x15,0x3f + .byte 0x08,0x04,0x04,0x0c, 0x95,0xc7,0xc7,0x52 + .byte 0x46,0x23,0x23,0x65, 0x9d,0xc3,0xc3,0x5e + .byte 0x30,0x18,0x18,0x28, 0x37,0x96,0x96,0xa1 + .byte 0x0a,0x05,0x05,0x0f, 0x2f,0x9a,0x9a,0xb5 + .byte 0x0e,0x07,0x07,0x09, 0x24,0x12,0x12,0x36 + .byte 0x1b,0x80,0x80,0x9b, 0xdf,0xe2,0xe2,0x3d + .byte 0xcd,0xeb,0xeb,0x26, 0x4e,0x27,0x27,0x69 + .byte 0x7f,0xb2,0xb2,0xcd, 0xea,0x75,0x75,0x9f + .byte 0x12,0x09,0x09,0x1b, 0x1d,0x83,0x83,0x9e + .byte 0x58,0x2c,0x2c,0x74, 0x34,0x1a,0x1a,0x2e + .byte 0x36,0x1b,0x1b,0x2d, 0xdc,0x6e,0x6e,0xb2 + .byte 0xb4,0x5a,0x5a,0xee, 0x5b,0xa0,0xa0,0xfb + .byte 0xa4,0x52,0x52,0xf6, 0x76,0x3b,0x3b,0x4d + .byte 0xb7,0xd6,0xd6,0x61, 0x7d,0xb3,0xb3,0xce + .byte 0x52,0x29,0x29,0x7b, 0xdd,0xe3,0xe3,0x3e + .byte 0x5e,0x2f,0x2f,0x71, 0x13,0x84,0x84,0x97 + .byte 0xa6,0x53,0x53,0xf5, 0xb9,0xd1,0xd1,0x68 + .byte 0x00,0x00,0x00,0x00, 0xc1,0xed,0xed,0x2c + .byte 0x40,0x20,0x20,0x60, 0xe3,0xfc,0xfc,0x1f + .byte 0x79,0xb1,0xb1,0xc8, 0xb6,0x5b,0x5b,0xed + .byte 0xd4,0x6a,0x6a,0xbe, 0x8d,0xcb,0xcb,0x46 + .byte 0x67,0xbe,0xbe,0xd9, 0x72,0x39,0x39,0x4b + .byte 0x94,0x4a,0x4a,0xde, 0x98,0x4c,0x4c,0xd4 + .byte 0xb0,0x58,0x58,0xe8, 0x85,0xcf,0xcf,0x4a + .byte 0xbb,0xd0,0xd0,0x6b, 0xc5,0xef,0xef,0x2a + .byte 0x4f,0xaa,0xaa,0xe5, 0xed,0xfb,0xfb,0x16 + .byte 0x86,0x43,0x43,0xc5, 0x9a,0x4d,0x4d,0xd7 + .byte 0x66,0x33,0x33,0x55, 0x11,0x85,0x85,0x94 + .byte 0x8a,0x45,0x45,0xcf, 0xe9,0xf9,0xf9,0x10 + .byte 0x04,0x02,0x02,0x06, 0xfe,0x7f,0x7f,0x81 + .byte 0xa0,0x50,0x50,0xf0, 0x78,0x3c,0x3c,0x44 + .byte 0x25,0x9f,0x9f,0xba, 0x4b,0xa8,0xa8,0xe3 + .byte 0xa2,0x51,0x51,0xf3, 0x5d,0xa3,0xa3,0xfe + .byte 0x80,0x40,0x40,0xc0, 0x05,0x8f,0x8f,0x8a + .byte 0x3f,0x92,0x92,0xad, 0x21,0x9d,0x9d,0xbc + .byte 0x70,0x38,0x38,0x48, 0xf1,0xf5,0xf5,0x04 + .byte 0x63,0xbc,0xbc,0xdf, 0x77,0xb6,0xb6,0xc1 + .byte 0xaf,0xda,0xda,0x75, 0x42,0x21,0x21,0x63 + .byte 0x20,0x10,0x10,0x30, 0xe5,0xff,0xff,0x1a + .byte 0xfd,0xf3,0xf3,0x0e, 0xbf,0xd2,0xd2,0x6d + .byte 0x81,0xcd,0xcd,0x4c, 0x18,0x0c,0x0c,0x14 + .byte 0x26,0x13,0x13,0x35, 0xc3,0xec,0xec,0x2f + .byte 0xbe,0x5f,0x5f,0xe1, 0x35,0x97,0x97,0xa2 + .byte 0x88,0x44,0x44,0xcc, 0x2e,0x17,0x17,0x39 + .byte 0x93,0xc4,0xc4,0x57, 0x55,0xa7,0xa7,0xf2 + .byte 0xfc,0x7e,0x7e,0x82, 0x7a,0x3d,0x3d,0x47 + .byte 0xc8,0x64,0x64,0xac, 0xba,0x5d,0x5d,0xe7 + .byte 0x32,0x19,0x19,0x2b, 0xe6,0x73,0x73,0x95 + .byte 0xc0,0x60,0x60,0xa0, 0x19,0x81,0x81,0x98 + .byte 0x9e,0x4f,0x4f,0xd1, 0xa3,0xdc,0xdc,0x7f + .byte 0x44,0x22,0x22,0x66, 0x54,0x2a,0x2a,0x7e + .byte 0x3b,0x90,0x90,0xab, 0x0b,0x88,0x88,0x83 + .byte 0x8c,0x46,0x46,0xca, 0xc7,0xee,0xee,0x29 + .byte 0x6b,0xb8,0xb8,0xd3, 0x28,0x14,0x14,0x3c + .byte 0xa7,0xde,0xde,0x79, 0xbc,0x5e,0x5e,0xe2 + .byte 0x16,0x0b,0x0b,0x1d, 0xad,0xdb,0xdb,0x76 + .byte 0xdb,0xe0,0xe0,0x3b, 0x64,0x32,0x32,0x56 + .byte 0x74,0x3a,0x3a,0x4e, 0x14,0x0a,0x0a,0x1e + .byte 0x92,0x49,0x49,0xdb, 0x0c,0x06,0x06,0x0a + .byte 0x48,0x24,0x24,0x6c, 0xb8,0x5c,0x5c,0xe4 + .byte 0x9f,0xc2,0xc2,0x5d, 0xbd,0xd3,0xd3,0x6e + .byte 0x43,0xac,0xac,0xef, 0xc4,0x62,0x62,0xa6 + .byte 0x39,0x91,0x91,0xa8, 0x31,0x95,0x95,0xa4 + .byte 0xd3,0xe4,0xe4,0x37, 0xf2,0x79,0x79,0x8b + .byte 0xd5,0xe7,0xe7,0x32, 0x8b,0xc8,0xc8,0x43 + .byte 0x6e,0x37,0x37,0x59, 0xda,0x6d,0x6d,0xb7 + .byte 0x01,0x8d,0x8d,0x8c, 0xb1,0xd5,0xd5,0x64 + .byte 0x9c,0x4e,0x4e,0xd2, 0x49,0xa9,0xa9,0xe0 + .byte 0xd8,0x6c,0x6c,0xb4, 0xac,0x56,0x56,0xfa + .byte 0xf3,0xf4,0xf4,0x07, 0xcf,0xea,0xea,0x25 + .byte 0xca,0x65,0x65,0xaf, 0xf4,0x7a,0x7a,0x8e + .byte 0x47,0xae,0xae,0xe9, 0x10,0x08,0x08,0x18 + .byte 0x6f,0xba,0xba,0xd5, 0xf0,0x78,0x78,0x88 + .byte 0x4a,0x25,0x25,0x6f, 0x5c,0x2e,0x2e,0x72 + .byte 0x38,0x1c,0x1c,0x24, 0x57,0xa6,0xa6,0xf1 + .byte 0x73,0xb4,0xb4,0xc7, 0x97,0xc6,0xc6,0x51 + .byte 0xcb,0xe8,0xe8,0x23, 0xa1,0xdd,0xdd,0x7c + .byte 0xe8,0x74,0x74,0x9c, 0x3e,0x1f,0x1f,0x21 + .byte 0x96,0x4b,0x4b,0xdd, 0x61,0xbd,0xbd,0xdc + .byte 0x0d,0x8b,0x8b,0x86, 0x0f,0x8a,0x8a,0x85 + .byte 0xe0,0x70,0x70,0x90, 0x7c,0x3e,0x3e,0x42 + .byte 0x71,0xb5,0xb5,0xc4, 0xcc,0x66,0x66,0xaa + .byte 0x90,0x48,0x48,0xd8, 0x06,0x03,0x03,0x05 + .byte 0xf7,0xf6,0xf6,0x01, 0x1c,0x0e,0x0e,0x12 + .byte 0xc2,0x61,0x61,0xa3, 0x6a,0x35,0x35,0x5f + .byte 0xae,0x57,0x57,0xf9, 0x69,0xb9,0xb9,0xd0 + .byte 0x17,0x86,0x86,0x91, 0x99,0xc1,0xc1,0x58 + .byte 0x3a,0x1d,0x1d,0x27, 0x27,0x9e,0x9e,0xb9 + .byte 0xd9,0xe1,0xe1,0x38, 0xeb,0xf8,0xf8,0x13 + .byte 0x2b,0x98,0x98,0xb3, 0x22,0x11,0x11,0x33 + .byte 0xd2,0x69,0x69,0xbb, 0xa9,0xd9,0xd9,0x70 + .byte 0x07,0x8e,0x8e,0x89, 0x33,0x94,0x94,0xa7 + .byte 0x2d,0x9b,0x9b,0xb6, 0x3c,0x1e,0x1e,0x22 + .byte 0x15,0x87,0x87,0x92, 0xc9,0xe9,0xe9,0x20 + .byte 0x87,0xce,0xce,0x49, 0xaa,0x55,0x55,0xff + .byte 0x50,0x28,0x28,0x78, 0xa5,0xdf,0xdf,0x7a + .byte 0x03,0x8c,0x8c,0x8f, 0x59,0xa1,0xa1,0xf8 + .byte 0x09,0x89,0x89,0x80, 0x1a,0x0d,0x0d,0x17 + .byte 0x65,0xbf,0xbf,0xda, 0xd7,0xe6,0xe6,0x31 + .byte 0x84,0x42,0x42,0xc6, 0xd0,0x68,0x68,0xb8 + .byte 0x82,0x41,0x41,0xc3, 0x29,0x99,0x99,0xb0 + .byte 0x5a,0x2d,0x2d,0x77, 0x1e,0x0f,0x0f,0x11 + .byte 0x7b,0xb0,0xb0,0xcb, 0xa8,0x54,0x54,0xfc + .byte 0x6d,0xbb,0xbb,0xd6, 0x2c,0x16,0x16,0x3a +AES_Te4: + .byte 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5 + .byte 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76 + .byte 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0 + .byte 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0 + .byte 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc + .byte 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15 + .byte 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a + .byte 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75 + .byte 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0 + .byte 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84 + .byte 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b + .byte 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf + .byte 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85 + .byte 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8 + .byte 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5 + .byte 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2 + .byte 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17 + .byte 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73 + .byte 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88 + .byte 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb + .byte 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c + .byte 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79 + .byte 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9 + .byte 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08 + .byte 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6 + .byte 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a + .byte 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e + .byte 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e + .byte 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94 + .byte 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf + .byte 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68 + .byte 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +rcon: + .byte 0x01,0x00,0x00,0x00, 0x02,0x00,0x00,0x00 + .byte 0x04,0x00,0x00,0x00, 0x08,0x00,0x00,0x00 + .byte 0x10,0x00,0x00,0x00, 0x20,0x00,0x00,0x00 + .byte 0x40,0x00,0x00,0x00, 0x80,0x00,0x00,0x00 + .byte 0x1B,0x00,0x00,0x00, 0x36,0x00,0x00,0x00 + .align 128 +AES_Td: + .byte 0x51,0xf4,0xa7,0x50, 0x7e,0x41,0x65,0x53 + .byte 0x1a,0x17,0xa4,0xc3, 0x3a,0x27,0x5e,0x96 + .byte 0x3b,0xab,0x6b,0xcb, 0x1f,0x9d,0x45,0xf1 + .byte 0xac,0xfa,0x58,0xab, 0x4b,0xe3,0x03,0x93 + .byte 0x20,0x30,0xfa,0x55, 0xad,0x76,0x6d,0xf6 + .byte 0x88,0xcc,0x76,0x91, 0xf5,0x02,0x4c,0x25 + .byte 0x4f,0xe5,0xd7,0xfc, 0xc5,0x2a,0xcb,0xd7 + .byte 0x26,0x35,0x44,0x80, 0xb5,0x62,0xa3,0x8f + .byte 0xde,0xb1,0x5a,0x49, 0x25,0xba,0x1b,0x67 + .byte 0x45,0xea,0x0e,0x98, 0x5d,0xfe,0xc0,0xe1 + .byte 0xc3,0x2f,0x75,0x02, 0x81,0x4c,0xf0,0x12 + .byte 0x8d,0x46,0x97,0xa3, 0x6b,0xd3,0xf9,0xc6 + .byte 0x03,0x8f,0x5f,0xe7, 0x15,0x92,0x9c,0x95 + .byte 0xbf,0x6d,0x7a,0xeb, 0x95,0x52,0x59,0xda + .byte 0xd4,0xbe,0x83,0x2d, 0x58,0x74,0x21,0xd3 + .byte 0x49,0xe0,0x69,0x29, 0x8e,0xc9,0xc8,0x44 + .byte 0x75,0xc2,0x89,0x6a, 0xf4,0x8e,0x79,0x78 + .byte 0x99,0x58,0x3e,0x6b, 0x27,0xb9,0x71,0xdd + .byte 0xbe,0xe1,0x4f,0xb6, 0xf0,0x88,0xad,0x17 + .byte 0xc9,0x20,0xac,0x66, 0x7d,0xce,0x3a,0xb4 + .byte 0x63,0xdf,0x4a,0x18, 0xe5,0x1a,0x31,0x82 + .byte 0x97,0x51,0x33,0x60, 0x62,0x53,0x7f,0x45 + .byte 0xb1,0x64,0x77,0xe0, 0xbb,0x6b,0xae,0x84 + .byte 0xfe,0x81,0xa0,0x1c, 0xf9,0x08,0x2b,0x94 + .byte 0x70,0x48,0x68,0x58, 0x8f,0x45,0xfd,0x19 + .byte 0x94,0xde,0x6c,0x87, 0x52,0x7b,0xf8,0xb7 + .byte 0xab,0x73,0xd3,0x23, 0x72,0x4b,0x02,0xe2 + .byte 0xe3,0x1f,0x8f,0x57, 0x66,0x55,0xab,0x2a + .byte 0xb2,0xeb,0x28,0x07, 0x2f,0xb5,0xc2,0x03 + .byte 0x86,0xc5,0x7b,0x9a, 0xd3,0x37,0x08,0xa5 + .byte 0x30,0x28,0x87,0xf2, 0x23,0xbf,0xa5,0xb2 + .byte 0x02,0x03,0x6a,0xba, 0xed,0x16,0x82,0x5c + .byte 0x8a,0xcf,0x1c,0x2b, 0xa7,0x79,0xb4,0x92 + .byte 0xf3,0x07,0xf2,0xf0, 0x4e,0x69,0xe2,0xa1 + .byte 0x65,0xda,0xf4,0xcd, 0x06,0x05,0xbe,0xd5 + .byte 0xd1,0x34,0x62,0x1f, 0xc4,0xa6,0xfe,0x8a + .byte 0x34,0x2e,0x53,0x9d, 0xa2,0xf3,0x55,0xa0 + .byte 0x05,0x8a,0xe1,0x32, 0xa4,0xf6,0xeb,0x75 + .byte 0x0b,0x83,0xec,0x39, 0x40,0x60,0xef,0xaa + .byte 0x5e,0x71,0x9f,0x06, 0xbd,0x6e,0x10,0x51 + .byte 0x3e,0x21,0x8a,0xf9, 0x96,0xdd,0x06,0x3d + .byte 0xdd,0x3e,0x05,0xae, 0x4d,0xe6,0xbd,0x46 + .byte 0x91,0x54,0x8d,0xb5, 0x71,0xc4,0x5d,0x05 + .byte 0x04,0x06,0xd4,0x6f, 0x60,0x50,0x15,0xff + .byte 0x19,0x98,0xfb,0x24, 0xd6,0xbd,0xe9,0x97 + .byte 0x89,0x40,0x43,0xcc, 0x67,0xd9,0x9e,0x77 + .byte 0xb0,0xe8,0x42,0xbd, 0x07,0x89,0x8b,0x88 + .byte 0xe7,0x19,0x5b,0x38, 0x79,0xc8,0xee,0xdb + .byte 0xa1,0x7c,0x0a,0x47, 0x7c,0x42,0x0f,0xe9 + .byte 0xf8,0x84,0x1e,0xc9, 0x00,0x00,0x00,0x00 + .byte 0x09,0x80,0x86,0x83, 0x32,0x2b,0xed,0x48 + .byte 0x1e,0x11,0x70,0xac, 0x6c,0x5a,0x72,0x4e + .byte 0xfd,0x0e,0xff,0xfb, 0x0f,0x85,0x38,0x56 + .byte 0x3d,0xae,0xd5,0x1e, 0x36,0x2d,0x39,0x27 + .byte 0x0a,0x0f,0xd9,0x64, 0x68,0x5c,0xa6,0x21 + .byte 0x9b,0x5b,0x54,0xd1, 0x24,0x36,0x2e,0x3a + .byte 0x0c,0x0a,0x67,0xb1, 0x93,0x57,0xe7,0x0f + .byte 0xb4,0xee,0x96,0xd2, 0x1b,0x9b,0x91,0x9e + .byte 0x80,0xc0,0xc5,0x4f, 0x61,0xdc,0x20,0xa2 + .byte 0x5a,0x77,0x4b,0x69, 0x1c,0x12,0x1a,0x16 + .byte 0xe2,0x93,0xba,0x0a, 0xc0,0xa0,0x2a,0xe5 + .byte 0x3c,0x22,0xe0,0x43, 0x12,0x1b,0x17,0x1d + .byte 0x0e,0x09,0x0d,0x0b, 0xf2,0x8b,0xc7,0xad + .byte 0x2d,0xb6,0xa8,0xb9, 0x14,0x1e,0xa9,0xc8 + .byte 0x57,0xf1,0x19,0x85, 0xaf,0x75,0x07,0x4c + .byte 0xee,0x99,0xdd,0xbb, 0xa3,0x7f,0x60,0xfd + .byte 0xf7,0x01,0x26,0x9f, 0x5c,0x72,0xf5,0xbc + .byte 0x44,0x66,0x3b,0xc5, 0x5b,0xfb,0x7e,0x34 + .byte 0x8b,0x43,0x29,0x76, 0xcb,0x23,0xc6,0xdc + .byte 0xb6,0xed,0xfc,0x68, 0xb8,0xe4,0xf1,0x63 + .byte 0xd7,0x31,0xdc,0xca, 0x42,0x63,0x85,0x10 + .byte 0x13,0x97,0x22,0x40, 0x84,0xc6,0x11,0x20 + .byte 0x85,0x4a,0x24,0x7d, 0xd2,0xbb,0x3d,0xf8 + .byte 0xae,0xf9,0x32,0x11, 0xc7,0x29,0xa1,0x6d + .byte 0x1d,0x9e,0x2f,0x4b, 0xdc,0xb2,0x30,0xf3 + .byte 0x0d,0x86,0x52,0xec, 0x77,0xc1,0xe3,0xd0 + .byte 0x2b,0xb3,0x16,0x6c, 0xa9,0x70,0xb9,0x99 + .byte 0x11,0x94,0x48,0xfa, 0x47,0xe9,0x64,0x22 + .byte 0xa8,0xfc,0x8c,0xc4, 0xa0,0xf0,0x3f,0x1a + .byte 0x56,0x7d,0x2c,0xd8, 0x22,0x33,0x90,0xef + .byte 0x87,0x49,0x4e,0xc7, 0xd9,0x38,0xd1,0xc1 + .byte 0x8c,0xca,0xa2,0xfe, 0x98,0xd4,0x0b,0x36 + .byte 0xa6,0xf5,0x81,0xcf, 0xa5,0x7a,0xde,0x28 + .byte 0xda,0xb7,0x8e,0x26, 0x3f,0xad,0xbf,0xa4 + .byte 0x2c,0x3a,0x9d,0xe4, 0x50,0x78,0x92,0x0d + .byte 0x6a,0x5f,0xcc,0x9b, 0x54,0x7e,0x46,0x62 + .byte 0xf6,0x8d,0x13,0xc2, 0x90,0xd8,0xb8,0xe8 + .byte 0x2e,0x39,0xf7,0x5e, 0x82,0xc3,0xaf,0xf5 + .byte 0x9f,0x5d,0x80,0xbe, 0x69,0xd0,0x93,0x7c + .byte 0x6f,0xd5,0x2d,0xa9, 0xcf,0x25,0x12,0xb3 + .byte 0xc8,0xac,0x99,0x3b, 0x10,0x18,0x7d,0xa7 + .byte 0xe8,0x9c,0x63,0x6e, 0xdb,0x3b,0xbb,0x7b + .byte 0xcd,0x26,0x78,0x09, 0x6e,0x59,0x18,0xf4 + .byte 0xec,0x9a,0xb7,0x01, 0x83,0x4f,0x9a,0xa8 + .byte 0xe6,0x95,0x6e,0x65, 0xaa,0xff,0xe6,0x7e + .byte 0x21,0xbc,0xcf,0x08, 0xef,0x15,0xe8,0xe6 + .byte 0xba,0xe7,0x9b,0xd9, 0x4a,0x6f,0x36,0xce + .byte 0xea,0x9f,0x09,0xd4, 0x29,0xb0,0x7c,0xd6 + .byte 0x31,0xa4,0xb2,0xaf, 0x2a,0x3f,0x23,0x31 + .byte 0xc6,0xa5,0x94,0x30, 0x35,0xa2,0x66,0xc0 + .byte 0x74,0x4e,0xbc,0x37, 0xfc,0x82,0xca,0xa6 + .byte 0xe0,0x90,0xd0,0xb0, 0x33,0xa7,0xd8,0x15 + .byte 0xf1,0x04,0x98,0x4a, 0x41,0xec,0xda,0xf7 + .byte 0x7f,0xcd,0x50,0x0e, 0x17,0x91,0xf6,0x2f + .byte 0x76,0x4d,0xd6,0x8d, 0x43,0xef,0xb0,0x4d + .byte 0xcc,0xaa,0x4d,0x54, 0xe4,0x96,0x04,0xdf + .byte 0x9e,0xd1,0xb5,0xe3, 0x4c,0x6a,0x88,0x1b + .byte 0xc1,0x2c,0x1f,0xb8, 0x46,0x65,0x51,0x7f + .byte 0x9d,0x5e,0xea,0x04, 0x01,0x8c,0x35,0x5d + .byte 0xfa,0x87,0x74,0x73, 0xfb,0x0b,0x41,0x2e + .byte 0xb3,0x67,0x1d,0x5a, 0x92,0xdb,0xd2,0x52 + .byte 0xe9,0x10,0x56,0x33, 0x6d,0xd6,0x47,0x13 + .byte 0x9a,0xd7,0x61,0x8c, 0x37,0xa1,0x0c,0x7a + .byte 0x59,0xf8,0x14,0x8e, 0xeb,0x13,0x3c,0x89 + .byte 0xce,0xa9,0x27,0xee, 0xb7,0x61,0xc9,0x35 + .byte 0xe1,0x1c,0xe5,0xed, 0x7a,0x47,0xb1,0x3c + .byte 0x9c,0xd2,0xdf,0x59, 0x55,0xf2,0x73,0x3f + .byte 0x18,0x14,0xce,0x79, 0x73,0xc7,0x37,0xbf + .byte 0x53,0xf7,0xcd,0xea, 0x5f,0xfd,0xaa,0x5b + .byte 0xdf,0x3d,0x6f,0x14, 0x78,0x44,0xdb,0x86 + .byte 0xca,0xaf,0xf3,0x81, 0xb9,0x68,0xc4,0x3e + .byte 0x38,0x24,0x34,0x2c, 0xc2,0xa3,0x40,0x5f + .byte 0x16,0x1d,0xc3,0x72, 0xbc,0xe2,0x25,0x0c + .byte 0x28,0x3c,0x49,0x8b, 0xff,0x0d,0x95,0x41 + .byte 0x39,0xa8,0x01,0x71, 0x08,0x0c,0xb3,0xde + .byte 0xd8,0xb4,0xe4,0x9c, 0x64,0x56,0xc1,0x90 + .byte 0x7b,0xcb,0x84,0x61, 0xd5,0x32,0xb6,0x70 + .byte 0x48,0x6c,0x5c,0x74, 0xd0,0xb8,0x57,0x42 +AES_Td4: + .byte 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38 + .byte 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb + .byte 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87 + .byte 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb + .byte 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d + .byte 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e + .byte 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2 + .byte 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 + .byte 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16 + .byte 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 + .byte 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda + .byte 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 + .byte 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a + .byte 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 + .byte 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02 + .byte 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b + .byte 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea + .byte 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 + .byte 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85 + .byte 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e + .byte 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89 + .byte 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b + .byte 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20 + .byte 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 + .byte 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31 + .byte 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f + .byte 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d + .byte 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef + .byte 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0 + .byte 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 + .byte 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26 + .byte 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d + .cstring "AES for C64x+, CRYPTOGAMS by " + .align 4 +___ + +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-ia64.S b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-ia64.S new file mode 100644 index 000000000..03f79b7ae --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-ia64.S @@ -0,0 +1,1130 @@ +// Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. +// +// Licensed under the OpenSSL license (the "License"). You may not use +// this file except in compliance with the License. You can obtain a copy +// in the file LICENSE in the source distribution or at +// https://www.openssl.org/source/license.html +// +// ==================================================================== +// Written by Andy Polyakov for the OpenSSL +// project. Rights for redistribution and usage in source and binary +// forms are granted according to the OpenSSL license. +// ==================================================================== +// +// What's wrong with compiler generated code? Compiler never uses +// variable 'shr' which is pairable with 'extr'/'dep' instructions. +// Then it uses 'zxt' which is an I-type, but can be replaced with +// 'and' which in turn can be assigned to M-port [there're double as +// much M-ports as there're I-ports on Itanium 2]. By sacrificing few +// registers for small constants (255, 24 and 16) to be used with +// 'shr' and 'and' instructions I can achieve better ILP, Instruction +// Level Parallelism, and performance. This code outperforms GCC 3.3 +// generated code by over factor of 2 (two), GCC 3.4 - by 70% and +// HP C - by 40%. Measured best-case scenario, i.e. aligned +// big-endian input, ECB timing on Itanium 2 is (18 + 13*rounds) +// ticks per block, or 9.25 CPU cycles per byte for 128 bit key. + +// Version 1.2 mitigates the hazard of cache-timing attacks by +// a) compressing S-boxes from 8KB to 2KB+256B, b) scheduling +// references to S-boxes for L2 cache latency, c) prefetching T[ed]4 +// prior last round. As result performance dropped to (26 + 15*rounds) +// ticks per block or 11 cycles per byte processed with 128-bit key. +// This is ~16% deterioration. For reference Itanium 2 L1 cache has +// 64 bytes line size and L2 - 128 bytes... + +.ident "aes-ia64.S, version 1.2" +.ident "IA-64 ISA artwork by Andy Polyakov " +.explicit +.text + +rk0=r8; rk1=r9; + +pfssave=r2; +lcsave=r10; +prsave=r3; +maskff=r11; +twenty4=r14; +sixteen=r15; + +te00=r16; te11=r17; te22=r18; te33=r19; +te01=r20; te12=r21; te23=r22; te30=r23; +te02=r24; te13=r25; te20=r26; te31=r27; +te03=r28; te10=r29; te21=r30; te32=r31; + +// these are rotating... +t0=r32; s0=r33; +t1=r34; s1=r35; +t2=r36; s2=r37; +t3=r38; s3=r39; + +te0=r40; te1=r41; te2=r42; te3=r43; + +#if defined(_HPUX_SOURCE) && !defined(_LP64) +# define ADDP addp4 +#else +# define ADDP add +#endif + +// Offsets from Te0 +#define TE0 0 +#define TE2 2 +#if defined(_HPUX_SOURCE) || defined(B_ENDIAN) +#define TE1 3 +#define TE3 1 +#else +#define TE1 1 +#define TE3 3 +#endif + +// This implies that AES_KEY comprises 32-bit key schedule elements +// even on LP64 platforms. +#ifndef KSZ +# define KSZ 4 +# define LDKEY ld4 +#endif + +.proc _ia64_AES_encrypt# +// Input: rk0-rk1 +// te0 +// te3 as AES_KEY->rounds!!! +// s0-s3 +// maskff,twenty4,sixteen +// Output: r16,r20,r24,r28 as s0-s3 +// Clobber: r16-r31,rk0-rk1,r32-r43 +.align 32 +_ia64_AES_encrypt: + .prologue + .altrp b6 + .body +{ .mmi; alloc r16=ar.pfs,12,0,0,8 + LDKEY t0=[rk0],2*KSZ + mov pr.rot=1<<16 } +{ .mmi; LDKEY t1=[rk1],2*KSZ + add te1=TE1,te0 + add te3=-3,te3 };; +{ .mib; LDKEY t2=[rk0],2*KSZ + mov ar.ec=2 } +{ .mib; LDKEY t3=[rk1],2*KSZ + add te2=TE2,te0 + brp.loop.imp .Le_top,.Le_end-16 };; + +{ .mmi; xor s0=s0,t0 + xor s1=s1,t1 + mov ar.lc=te3 } +{ .mmi; xor s2=s2,t2 + xor s3=s3,t3 + add te3=TE3,te0 };; + +.align 32 +.Le_top: +{ .mmi; (p0) LDKEY t0=[rk0],2*KSZ // 0/0:rk[0] + (p0) and te33=s3,maskff // 0/0:s3&0xff + (p0) extr.u te22=s2,8,8 } // 0/0:s2>>8&0xff +{ .mmi; (p0) LDKEY t1=[rk1],2*KSZ // 0/1:rk[1] + (p0) and te30=s0,maskff // 0/1:s0&0xff + (p0) shr.u te00=s0,twenty4 };; // 0/0:s0>>24 +{ .mmi; (p0) LDKEY t2=[rk0],2*KSZ // 1/2:rk[2] + (p0) shladd te33=te33,3,te3 // 1/0:te0+s0>>24 + (p0) extr.u te23=s3,8,8 } // 1/1:s3>>8&0xff +{ .mmi; (p0) LDKEY t3=[rk1],2*KSZ // 1/3:rk[3] + (p0) shladd te30=te30,3,te3 // 1/1:te3+s0 + (p0) shr.u te01=s1,twenty4 };; // 1/1:s1>>24 +{ .mmi; (p0) ld4 te33=[te33] // 2/0:te3[s3&0xff] + (p0) shladd te22=te22,3,te2 // 2/0:te2+s2>>8&0xff + (p0) extr.u te20=s0,8,8 } // 2/2:s0>>8&0xff +{ .mmi; (p0) ld4 te30=[te30] // 2/1:te3[s0] + (p0) shladd te23=te23,3,te2 // 2/1:te2+s3>>8 + (p0) shr.u te02=s2,twenty4 };; // 2/2:s2>>24 +{ .mmi; (p0) ld4 te22=[te22] // 3/0:te2[s2>>8] + (p0) shladd te20=te20,3,te2 // 3/2:te2+s0>>8 + (p0) extr.u te21=s1,8,8 } // 3/3:s1>>8&0xff +{ .mmi; (p0) ld4 te23=[te23] // 3/1:te2[s3>>8] + (p0) shladd te00=te00,3,te0 // 3/0:te0+s0>>24 + (p0) shr.u te03=s3,twenty4 };; // 3/3:s3>>24 +{ .mmi; (p0) ld4 te20=[te20] // 4/2:te2[s0>>8] + (p0) shladd te21=te21,3,te2 // 4/3:te3+s2 + (p0) extr.u te11=s1,16,8 } // 4/0:s1>>16&0xff +{ .mmi; (p0) ld4 te00=[te00] // 4/0:te0[s0>>24] + (p0) shladd te01=te01,3,te0 // 4/1:te0+s1>>24 + (p0) shr.u te13=s3,sixteen };; // 4/2:s3>>16 +{ .mmi; (p0) ld4 te21=[te21] // 5/3:te2[s1>>8] + (p0) shladd te11=te11,3,te1 // 5/0:te1+s1>>16 + (p0) extr.u te12=s2,16,8 } // 5/1:s2>>16&0xff +{ .mmi; (p0) ld4 te01=[te01] // 5/1:te0[s1>>24] + (p0) shladd te02=te02,3,te0 // 5/2:te0+s2>>24 + (p0) and te31=s1,maskff };; // 5/2:s1&0xff +{ .mmi; (p0) ld4 te11=[te11] // 6/0:te1[s1>>16] + (p0) shladd te12=te12,3,te1 // 6/1:te1+s2>>16 + (p0) extr.u te10=s0,16,8 } // 6/3:s0>>16&0xff +{ .mmi; (p0) ld4 te02=[te02] // 6/2:te0[s2>>24] + (p0) shladd te03=te03,3,te0 // 6/3:te1+s0>>16 + (p0) and te32=s2,maskff };; // 6/3:s2&0xff + +{ .mmi; (p0) ld4 te12=[te12] // 7/1:te1[s2>>16] + (p0) shladd te31=te31,3,te3 // 7/2:te3+s1&0xff + (p0) and te13=te13,maskff} // 7/2:s3>>16&0xff +{ .mmi; (p0) ld4 te03=[te03] // 7/3:te0[s3>>24] + (p0) shladd te32=te32,3,te3 // 7/3:te3+s2 + (p0) xor t0=t0,te33 };; // 7/0: +{ .mmi; (p0) ld4 te31=[te31] // 8/2:te3[s1] + (p0) shladd te13=te13,3,te1 // 8/2:te1+s3>>16 + (p0) xor t0=t0,te22 } // 8/0: +{ .mmi; (p0) ld4 te32=[te32] // 8/3:te3[s2] + (p0) shladd te10=te10,3,te1 // 8/3:te1+s0>>16 + (p0) xor t1=t1,te30 };; // 8/1: +{ .mmi; (p0) ld4 te13=[te13] // 9/2:te1[s3>>16] + (p0) ld4 te10=[te10] // 9/3:te1[s0>>16] + (p0) xor t0=t0,te00 };; // 9/0: !L2 scheduling +{ .mmi; (p0) xor t1=t1,te23 // 10[9]/1: + (p0) xor t2=t2,te20 // 10[9]/2: + (p0) xor t3=t3,te21 };; // 10[9]/3: +{ .mmi; (p0) xor t0=t0,te11 // 11[10]/0:done! + (p0) xor t1=t1,te01 // 11[10]/1: + (p0) xor t2=t2,te02 };; // 11[10]/2: !L2 scheduling +{ .mmi; (p0) xor t3=t3,te03 // 12[10]/3: + (p16) cmp.eq p0,p17=r0,r0 };; // 12[10]/clear (p17) +{ .mmi; (p0) xor t1=t1,te12 // 13[11]/1:done! + (p0) xor t2=t2,te31 // 13[11]/2: + (p0) xor t3=t3,te32 } // 13[11]/3: +{ .mmi; (p17) add te0=2048,te0 // 13[11]/ + (p17) add te1=2048+64-TE1,te1};; // 13[11]/ +{ .mib; (p0) xor t2=t2,te13 // 14[12]/2:done! + (p17) add te2=2048+128-TE2,te2} // 14[12]/ +{ .mib; (p0) xor t3=t3,te10 // 14[12]/3:done! + (p17) add te3=2048+192-TE3,te3 // 14[12]/ + br.ctop.sptk .Le_top };; +.Le_end: + + +{ .mmi; ld8 te12=[te0] // prefetch Te4 + ld8 te31=[te1] } +{ .mmi; ld8 te10=[te2] + ld8 te32=[te3] } + +{ .mmi; LDKEY t0=[rk0],2*KSZ // 0/0:rk[0] + and te33=s3,maskff // 0/0:s3&0xff + extr.u te22=s2,8,8 } // 0/0:s2>>8&0xff +{ .mmi; LDKEY t1=[rk1],2*KSZ // 0/1:rk[1] + and te30=s0,maskff // 0/1:s0&0xff + shr.u te00=s0,twenty4 };; // 0/0:s0>>24 +{ .mmi; LDKEY t2=[rk0],2*KSZ // 1/2:rk[2] + add te33=te33,te0 // 1/0:te0+s0>>24 + extr.u te23=s3,8,8 } // 1/1:s3>>8&0xff +{ .mmi; LDKEY t3=[rk1],2*KSZ // 1/3:rk[3] + add te30=te30,te0 // 1/1:te0+s0 + shr.u te01=s1,twenty4 };; // 1/1:s1>>24 +{ .mmi; ld1 te33=[te33] // 2/0:te0[s3&0xff] + add te22=te22,te0 // 2/0:te0+s2>>8&0xff + extr.u te20=s0,8,8 } // 2/2:s0>>8&0xff +{ .mmi; ld1 te30=[te30] // 2/1:te0[s0] + add te23=te23,te0 // 2/1:te0+s3>>8 + shr.u te02=s2,twenty4 };; // 2/2:s2>>24 +{ .mmi; ld1 te22=[te22] // 3/0:te0[s2>>8] + add te20=te20,te0 // 3/2:te0+s0>>8 + extr.u te21=s1,8,8 } // 3/3:s1>>8&0xff +{ .mmi; ld1 te23=[te23] // 3/1:te0[s3>>8] + add te00=te00,te0 // 3/0:te0+s0>>24 + shr.u te03=s3,twenty4 };; // 3/3:s3>>24 +{ .mmi; ld1 te20=[te20] // 4/2:te0[s0>>8] + add te21=te21,te0 // 4/3:te0+s2 + extr.u te11=s1,16,8 } // 4/0:s1>>16&0xff +{ .mmi; ld1 te00=[te00] // 4/0:te0[s0>>24] + add te01=te01,te0 // 4/1:te0+s1>>24 + shr.u te13=s3,sixteen };; // 4/2:s3>>16 +{ .mmi; ld1 te21=[te21] // 5/3:te0[s1>>8] + add te11=te11,te0 // 5/0:te0+s1>>16 + extr.u te12=s2,16,8 } // 5/1:s2>>16&0xff +{ .mmi; ld1 te01=[te01] // 5/1:te0[s1>>24] + add te02=te02,te0 // 5/2:te0+s2>>24 + and te31=s1,maskff };; // 5/2:s1&0xff +{ .mmi; ld1 te11=[te11] // 6/0:te0[s1>>16] + add te12=te12,te0 // 6/1:te0+s2>>16 + extr.u te10=s0,16,8 } // 6/3:s0>>16&0xff +{ .mmi; ld1 te02=[te02] // 6/2:te0[s2>>24] + add te03=te03,te0 // 6/3:te0+s0>>16 + and te32=s2,maskff };; // 6/3:s2&0xff + +{ .mmi; ld1 te12=[te12] // 7/1:te0[s2>>16] + add te31=te31,te0 // 7/2:te0+s1&0xff + dep te33=te22,te33,8,8} // 7/0: +{ .mmi; ld1 te03=[te03] // 7/3:te0[s3>>24] + add te32=te32,te0 // 7/3:te0+s2 + and te13=te13,maskff};; // 7/2:s3>>16&0xff +{ .mmi; ld1 te31=[te31] // 8/2:te0[s1] + add te13=te13,te0 // 8/2:te0+s3>>16 + dep te30=te23,te30,8,8} // 8/1: +{ .mmi; ld1 te32=[te32] // 8/3:te0[s2] + add te10=te10,te0 // 8/3:te0+s0>>16 + shl te00=te00,twenty4};; // 8/0: +{ .mii; ld1 te13=[te13] // 9/2:te0[s3>>16] + dep te33=te11,te33,16,8 // 9/0: + shl te01=te01,twenty4};; // 9/1: +{ .mii; ld1 te10=[te10] // 10/3:te0[s0>>16] + dep te31=te20,te31,8,8 // 10/2: + shl te02=te02,twenty4};; // 10/2: +{ .mii; xor t0=t0,te33 // 11/0: + dep te32=te21,te32,8,8 // 11/3: + shl te12=te12,sixteen};; // 11/1: +{ .mii; xor r16=t0,te00 // 12/0:done! + dep te31=te13,te31,16,8 // 12/2: + shl te03=te03,twenty4};; // 12/3: +{ .mmi; xor t1=t1,te01 // 13/1: + xor t2=t2,te02 // 13/2: + dep te32=te10,te32,16,8};; // 13/3: +{ .mmi; xor t1=t1,te30 // 14/1: + xor r24=t2,te31 // 14/2:done! + xor t3=t3,te32 };; // 14/3: +{ .mib; xor r20=t1,te12 // 15/1:done! + xor r28=t3,te03 // 15/3:done! + br.ret.sptk b6 };; +.endp _ia64_AES_encrypt# + +// void AES_encrypt (const void *in,void *out,const AES_KEY *key); +.global AES_encrypt# +.proc AES_encrypt# +.align 32 +AES_encrypt: + .prologue + .save ar.pfs,pfssave +{ .mmi; alloc pfssave=ar.pfs,3,1,12,0 + and out0=3,in0 + mov r3=ip } +{ .mmi; ADDP in0=0,in0 + mov loc0=psr.um + ADDP out11=KSZ*60,in2 };; // &AES_KEY->rounds + +{ .mmi; ld4 out11=[out11] // AES_KEY->rounds + add out8=(AES_Te#-AES_encrypt#),r3 // Te0 + .save pr,prsave + mov prsave=pr } +{ .mmi; rum 1<<3 // clear um.ac + .save ar.lc,lcsave + mov lcsave=ar.lc };; + + .body +#if defined(_HPUX_SOURCE) // HPUX is big-endian, cut 15+15 cycles... +{ .mib; cmp.ne p6,p0=out0,r0 + add out0=4,in0 +(p6) br.dpnt.many .Le_i_unaligned };; + +{ .mmi; ld4 out1=[in0],8 // s0 + and out9=3,in1 + mov twenty4=24 } +{ .mmi; ld4 out3=[out0],8 // s1 + ADDP rk0=0,in2 + mov sixteen=16 };; +{ .mmi; ld4 out5=[in0] // s2 + cmp.ne p6,p0=out9,r0 + mov maskff=0xff } +{ .mmb; ld4 out7=[out0] // s3 + ADDP rk1=KSZ,in2 + br.call.sptk.many b6=_ia64_AES_encrypt };; + +{ .mib; ADDP in0=4,in1 + ADDP in1=0,in1 +(p6) br.spnt .Le_o_unaligned };; + +{ .mii; mov psr.um=loc0 + mov ar.pfs=pfssave + mov ar.lc=lcsave };; +{ .mmi; st4 [in1]=r16,8 // s0 + st4 [in0]=r20,8 // s1 + mov pr=prsave,0x1ffff };; +{ .mmb; st4 [in1]=r24 // s2 + st4 [in0]=r28 // s3 + br.ret.sptk.many b0 };; +#endif + +.align 32 +.Le_i_unaligned: +{ .mmi; add out0=1,in0 + add out2=2,in0 + add out4=3,in0 };; +{ .mmi; ld1 r16=[in0],4 + ld1 r17=[out0],4 }//;; +{ .mmi; ld1 r18=[out2],4 + ld1 out1=[out4],4 };; // s0 +{ .mmi; ld1 r20=[in0],4 + ld1 r21=[out0],4 }//;; +{ .mmi; ld1 r22=[out2],4 + ld1 out3=[out4],4 };; // s1 +{ .mmi; ld1 r24=[in0],4 + ld1 r25=[out0],4 }//;; +{ .mmi; ld1 r26=[out2],4 + ld1 out5=[out4],4 };; // s2 +{ .mmi; ld1 r28=[in0] + ld1 r29=[out0] }//;; +{ .mmi; ld1 r30=[out2] + ld1 out7=[out4] };; // s3 + +{ .mii; + dep out1=r16,out1,24,8 //;; + dep out3=r20,out3,24,8 }//;; +{ .mii; ADDP rk0=0,in2 + dep out5=r24,out5,24,8 //;; + dep out7=r28,out7,24,8 };; +{ .mii; ADDP rk1=KSZ,in2 + dep out1=r17,out1,16,8 //;; + dep out3=r21,out3,16,8 }//;; +{ .mii; mov twenty4=24 + dep out5=r25,out5,16,8 //;; + dep out7=r29,out7,16,8 };; +{ .mii; mov sixteen=16 + dep out1=r18,out1,8,8 //;; + dep out3=r22,out3,8,8 }//;; +{ .mii; mov maskff=0xff + dep out5=r26,out5,8,8 //;; + dep out7=r30,out7,8,8 };; + +{ .mib; br.call.sptk.many b6=_ia64_AES_encrypt };; + +.Le_o_unaligned: +{ .mii; ADDP out0=0,in1 + extr.u r17=r16,8,8 // s0 + shr.u r19=r16,twenty4 }//;; +{ .mii; ADDP out1=1,in1 + extr.u r18=r16,16,8 + shr.u r23=r20,twenty4 }//;; // s1 +{ .mii; ADDP out2=2,in1 + extr.u r21=r20,8,8 + shr.u r22=r20,sixteen }//;; +{ .mii; ADDP out3=3,in1 + extr.u r25=r24,8,8 // s2 + shr.u r27=r24,twenty4 };; +{ .mii; st1 [out3]=r16,4 + extr.u r26=r24,16,8 + shr.u r31=r28,twenty4 }//;; // s3 +{ .mii; st1 [out2]=r17,4 + extr.u r29=r28,8,8 + shr.u r30=r28,sixteen }//;; + +{ .mmi; st1 [out1]=r18,4 + st1 [out0]=r19,4 };; +{ .mmi; st1 [out3]=r20,4 + st1 [out2]=r21,4 }//;; +{ .mmi; st1 [out1]=r22,4 + st1 [out0]=r23,4 };; +{ .mmi; st1 [out3]=r24,4 + st1 [out2]=r25,4 + mov pr=prsave,0x1ffff }//;; +{ .mmi; st1 [out1]=r26,4 + st1 [out0]=r27,4 + mov ar.pfs=pfssave };; +{ .mmi; st1 [out3]=r28 + st1 [out2]=r29 + mov ar.lc=lcsave }//;; +{ .mmi; st1 [out1]=r30 + st1 [out0]=r31 } +{ .mfb; mov psr.um=loc0 // restore user mask + br.ret.sptk.many b0 };; +.endp AES_encrypt# + +// *AES_decrypt are autogenerated by the following script: +#if 0 +#!/usr/bin/env perl +print "// *AES_decrypt are autogenerated by the following script:\n#if 0\n"; +open(PROG,'<'.$0); while() { print; } close(PROG); +print "#endif\n"; +while(<>) { + $process=1 if (/\.proc\s+_ia64_AES_encrypt/); + next if (!$process); + + #s/te00=s0/td00=s0/; s/te00/td00/g; + s/te11=s1/td13=s3/; s/te11/td13/g; + #s/te22=s2/td22=s2/; s/te22/td22/g; + s/te33=s3/td31=s1/; s/te33/td31/g; + + #s/te01=s1/td01=s1/; s/te01/td01/g; + s/te12=s2/td10=s0/; s/te12/td10/g; + #s/te23=s3/td23=s3/; s/te23/td23/g; + s/te30=s0/td32=s2/; s/te30/td32/g; + + #s/te02=s2/td02=s2/; s/te02/td02/g; + s/te13=s3/td11=s1/; s/te13/td11/g; + #s/te20=s0/td20=s0/; s/te20/td20/g; + s/te31=s1/td33=s3/; s/te31/td33/g; + + #s/te03=s3/td03=s3/; s/te03/td03/g; + s/te10=s0/td12=s2/; s/te10/td12/g; + #s/te21=s1/td21=s1/; s/te21/td21/g; + s/te32=s2/td30=s0/; s/te32/td30/g; + + s/td/te/g; + + s/AES_encrypt/AES_decrypt/g; + s/\.Le_/.Ld_/g; + s/AES_Te#/AES_Td#/g; + + print; + + exit if (/\.endp\s+AES_decrypt/); +} +#endif +.proc _ia64_AES_decrypt# +// Input: rk0-rk1 +// te0 +// te3 as AES_KEY->rounds!!! +// s0-s3 +// maskff,twenty4,sixteen +// Output: r16,r20,r24,r28 as s0-s3 +// Clobber: r16-r31,rk0-rk1,r32-r43 +.align 32 +_ia64_AES_decrypt: + .prologue + .altrp b6 + .body +{ .mmi; alloc r16=ar.pfs,12,0,0,8 + LDKEY t0=[rk0],2*KSZ + mov pr.rot=1<<16 } +{ .mmi; LDKEY t1=[rk1],2*KSZ + add te1=TE1,te0 + add te3=-3,te3 };; +{ .mib; LDKEY t2=[rk0],2*KSZ + mov ar.ec=2 } +{ .mib; LDKEY t3=[rk1],2*KSZ + add te2=TE2,te0 + brp.loop.imp .Ld_top,.Ld_end-16 };; + +{ .mmi; xor s0=s0,t0 + xor s1=s1,t1 + mov ar.lc=te3 } +{ .mmi; xor s2=s2,t2 + xor s3=s3,t3 + add te3=TE3,te0 };; + +.align 32 +.Ld_top: +{ .mmi; (p0) LDKEY t0=[rk0],2*KSZ // 0/0:rk[0] + (p0) and te31=s1,maskff // 0/0:s3&0xff + (p0) extr.u te22=s2,8,8 } // 0/0:s2>>8&0xff +{ .mmi; (p0) LDKEY t1=[rk1],2*KSZ // 0/1:rk[1] + (p0) and te32=s2,maskff // 0/1:s0&0xff + (p0) shr.u te00=s0,twenty4 };; // 0/0:s0>>24 +{ .mmi; (p0) LDKEY t2=[rk0],2*KSZ // 1/2:rk[2] + (p0) shladd te31=te31,3,te3 // 1/0:te0+s0>>24 + (p0) extr.u te23=s3,8,8 } // 1/1:s3>>8&0xff +{ .mmi; (p0) LDKEY t3=[rk1],2*KSZ // 1/3:rk[3] + (p0) shladd te32=te32,3,te3 // 1/1:te3+s0 + (p0) shr.u te01=s1,twenty4 };; // 1/1:s1>>24 +{ .mmi; (p0) ld4 te31=[te31] // 2/0:te3[s3&0xff] + (p0) shladd te22=te22,3,te2 // 2/0:te2+s2>>8&0xff + (p0) extr.u te20=s0,8,8 } // 2/2:s0>>8&0xff +{ .mmi; (p0) ld4 te32=[te32] // 2/1:te3[s0] + (p0) shladd te23=te23,3,te2 // 2/1:te2+s3>>8 + (p0) shr.u te02=s2,twenty4 };; // 2/2:s2>>24 +{ .mmi; (p0) ld4 te22=[te22] // 3/0:te2[s2>>8] + (p0) shladd te20=te20,3,te2 // 3/2:te2+s0>>8 + (p0) extr.u te21=s1,8,8 } // 3/3:s1>>8&0xff +{ .mmi; (p0) ld4 te23=[te23] // 3/1:te2[s3>>8] + (p0) shladd te00=te00,3,te0 // 3/0:te0+s0>>24 + (p0) shr.u te03=s3,twenty4 };; // 3/3:s3>>24 +{ .mmi; (p0) ld4 te20=[te20] // 4/2:te2[s0>>8] + (p0) shladd te21=te21,3,te2 // 4/3:te3+s2 + (p0) extr.u te13=s3,16,8 } // 4/0:s1>>16&0xff +{ .mmi; (p0) ld4 te00=[te00] // 4/0:te0[s0>>24] + (p0) shladd te01=te01,3,te0 // 4/1:te0+s1>>24 + (p0) shr.u te11=s1,sixteen };; // 4/2:s3>>16 +{ .mmi; (p0) ld4 te21=[te21] // 5/3:te2[s1>>8] + (p0) shladd te13=te13,3,te1 // 5/0:te1+s1>>16 + (p0) extr.u te10=s0,16,8 } // 5/1:s2>>16&0xff +{ .mmi; (p0) ld4 te01=[te01] // 5/1:te0[s1>>24] + (p0) shladd te02=te02,3,te0 // 5/2:te0+s2>>24 + (p0) and te33=s3,maskff };; // 5/2:s1&0xff +{ .mmi; (p0) ld4 te13=[te13] // 6/0:te1[s1>>16] + (p0) shladd te10=te10,3,te1 // 6/1:te1+s2>>16 + (p0) extr.u te12=s2,16,8 } // 6/3:s0>>16&0xff +{ .mmi; (p0) ld4 te02=[te02] // 6/2:te0[s2>>24] + (p0) shladd te03=te03,3,te0 // 6/3:te1+s0>>16 + (p0) and te30=s0,maskff };; // 6/3:s2&0xff + +{ .mmi; (p0) ld4 te10=[te10] // 7/1:te1[s2>>16] + (p0) shladd te33=te33,3,te3 // 7/2:te3+s1&0xff + (p0) and te11=te11,maskff} // 7/2:s3>>16&0xff +{ .mmi; (p0) ld4 te03=[te03] // 7/3:te0[s3>>24] + (p0) shladd te30=te30,3,te3 // 7/3:te3+s2 + (p0) xor t0=t0,te31 };; // 7/0: +{ .mmi; (p0) ld4 te33=[te33] // 8/2:te3[s1] + (p0) shladd te11=te11,3,te1 // 8/2:te1+s3>>16 + (p0) xor t0=t0,te22 } // 8/0: +{ .mmi; (p0) ld4 te30=[te30] // 8/3:te3[s2] + (p0) shladd te12=te12,3,te1 // 8/3:te1+s0>>16 + (p0) xor t1=t1,te32 };; // 8/1: +{ .mmi; (p0) ld4 te11=[te11] // 9/2:te1[s3>>16] + (p0) ld4 te12=[te12] // 9/3:te1[s0>>16] + (p0) xor t0=t0,te00 };; // 9/0: !L2 scheduling +{ .mmi; (p0) xor t1=t1,te23 // 10[9]/1: + (p0) xor t2=t2,te20 // 10[9]/2: + (p0) xor t3=t3,te21 };; // 10[9]/3: +{ .mmi; (p0) xor t0=t0,te13 // 11[10]/0:done! + (p0) xor t1=t1,te01 // 11[10]/1: + (p0) xor t2=t2,te02 };; // 11[10]/2: !L2 scheduling +{ .mmi; (p0) xor t3=t3,te03 // 12[10]/3: + (p16) cmp.eq p0,p17=r0,r0 };; // 12[10]/clear (p17) +{ .mmi; (p0) xor t1=t1,te10 // 13[11]/1:done! + (p0) xor t2=t2,te33 // 13[11]/2: + (p0) xor t3=t3,te30 } // 13[11]/3: +{ .mmi; (p17) add te0=2048,te0 // 13[11]/ + (p17) add te1=2048+64-TE1,te1};; // 13[11]/ +{ .mib; (p0) xor t2=t2,te11 // 14[12]/2:done! + (p17) add te2=2048+128-TE2,te2} // 14[12]/ +{ .mib; (p0) xor t3=t3,te12 // 14[12]/3:done! + (p17) add te3=2048+192-TE3,te3 // 14[12]/ + br.ctop.sptk .Ld_top };; +.Ld_end: + + +{ .mmi; ld8 te10=[te0] // prefetch Td4 + ld8 te33=[te1] } +{ .mmi; ld8 te12=[te2] + ld8 te30=[te3] } + +{ .mmi; LDKEY t0=[rk0],2*KSZ // 0/0:rk[0] + and te31=s1,maskff // 0/0:s3&0xff + extr.u te22=s2,8,8 } // 0/0:s2>>8&0xff +{ .mmi; LDKEY t1=[rk1],2*KSZ // 0/1:rk[1] + and te32=s2,maskff // 0/1:s0&0xff + shr.u te00=s0,twenty4 };; // 0/0:s0>>24 +{ .mmi; LDKEY t2=[rk0],2*KSZ // 1/2:rk[2] + add te31=te31,te0 // 1/0:te0+s0>>24 + extr.u te23=s3,8,8 } // 1/1:s3>>8&0xff +{ .mmi; LDKEY t3=[rk1],2*KSZ // 1/3:rk[3] + add te32=te32,te0 // 1/1:te0+s0 + shr.u te01=s1,twenty4 };; // 1/1:s1>>24 +{ .mmi; ld1 te31=[te31] // 2/0:te0[s3&0xff] + add te22=te22,te0 // 2/0:te0+s2>>8&0xff + extr.u te20=s0,8,8 } // 2/2:s0>>8&0xff +{ .mmi; ld1 te32=[te32] // 2/1:te0[s0] + add te23=te23,te0 // 2/1:te0+s3>>8 + shr.u te02=s2,twenty4 };; // 2/2:s2>>24 +{ .mmi; ld1 te22=[te22] // 3/0:te0[s2>>8] + add te20=te20,te0 // 3/2:te0+s0>>8 + extr.u te21=s1,8,8 } // 3/3:s1>>8&0xff +{ .mmi; ld1 te23=[te23] // 3/1:te0[s3>>8] + add te00=te00,te0 // 3/0:te0+s0>>24 + shr.u te03=s3,twenty4 };; // 3/3:s3>>24 +{ .mmi; ld1 te20=[te20] // 4/2:te0[s0>>8] + add te21=te21,te0 // 4/3:te0+s2 + extr.u te13=s3,16,8 } // 4/0:s1>>16&0xff +{ .mmi; ld1 te00=[te00] // 4/0:te0[s0>>24] + add te01=te01,te0 // 4/1:te0+s1>>24 + shr.u te11=s1,sixteen };; // 4/2:s3>>16 +{ .mmi; ld1 te21=[te21] // 5/3:te0[s1>>8] + add te13=te13,te0 // 5/0:te0+s1>>16 + extr.u te10=s0,16,8 } // 5/1:s2>>16&0xff +{ .mmi; ld1 te01=[te01] // 5/1:te0[s1>>24] + add te02=te02,te0 // 5/2:te0+s2>>24 + and te33=s3,maskff };; // 5/2:s1&0xff +{ .mmi; ld1 te13=[te13] // 6/0:te0[s1>>16] + add te10=te10,te0 // 6/1:te0+s2>>16 + extr.u te12=s2,16,8 } // 6/3:s0>>16&0xff +{ .mmi; ld1 te02=[te02] // 6/2:te0[s2>>24] + add te03=te03,te0 // 6/3:te0+s0>>16 + and te30=s0,maskff };; // 6/3:s2&0xff + +{ .mmi; ld1 te10=[te10] // 7/1:te0[s2>>16] + add te33=te33,te0 // 7/2:te0+s1&0xff + dep te31=te22,te31,8,8} // 7/0: +{ .mmi; ld1 te03=[te03] // 7/3:te0[s3>>24] + add te30=te30,te0 // 7/3:te0+s2 + and te11=te11,maskff};; // 7/2:s3>>16&0xff +{ .mmi; ld1 te33=[te33] // 8/2:te0[s1] + add te11=te11,te0 // 8/2:te0+s3>>16 + dep te32=te23,te32,8,8} // 8/1: +{ .mmi; ld1 te30=[te30] // 8/3:te0[s2] + add te12=te12,te0 // 8/3:te0+s0>>16 + shl te00=te00,twenty4};; // 8/0: +{ .mii; ld1 te11=[te11] // 9/2:te0[s3>>16] + dep te31=te13,te31,16,8 // 9/0: + shl te01=te01,twenty4};; // 9/1: +{ .mii; ld1 te12=[te12] // 10/3:te0[s0>>16] + dep te33=te20,te33,8,8 // 10/2: + shl te02=te02,twenty4};; // 10/2: +{ .mii; xor t0=t0,te31 // 11/0: + dep te30=te21,te30,8,8 // 11/3: + shl te10=te10,sixteen};; // 11/1: +{ .mii; xor r16=t0,te00 // 12/0:done! + dep te33=te11,te33,16,8 // 12/2: + shl te03=te03,twenty4};; // 12/3: +{ .mmi; xor t1=t1,te01 // 13/1: + xor t2=t2,te02 // 13/2: + dep te30=te12,te30,16,8};; // 13/3: +{ .mmi; xor t1=t1,te32 // 14/1: + xor r24=t2,te33 // 14/2:done! + xor t3=t3,te30 };; // 14/3: +{ .mib; xor r20=t1,te10 // 15/1:done! + xor r28=t3,te03 // 15/3:done! + br.ret.sptk b6 };; +.endp _ia64_AES_decrypt# + +// void AES_decrypt (const void *in,void *out,const AES_KEY *key); +.global AES_decrypt# +.proc AES_decrypt# +.align 32 +AES_decrypt: + .prologue + .save ar.pfs,pfssave +{ .mmi; alloc pfssave=ar.pfs,3,1,12,0 + and out0=3,in0 + mov r3=ip } +{ .mmi; ADDP in0=0,in0 + mov loc0=psr.um + ADDP out11=KSZ*60,in2 };; // &AES_KEY->rounds + +{ .mmi; ld4 out11=[out11] // AES_KEY->rounds + add out8=(AES_Td#-AES_decrypt#),r3 // Te0 + .save pr,prsave + mov prsave=pr } +{ .mmi; rum 1<<3 // clear um.ac + .save ar.lc,lcsave + mov lcsave=ar.lc };; + + .body +#if defined(_HPUX_SOURCE) // HPUX is big-endian, cut 15+15 cycles... +{ .mib; cmp.ne p6,p0=out0,r0 + add out0=4,in0 +(p6) br.dpnt.many .Ld_i_unaligned };; + +{ .mmi; ld4 out1=[in0],8 // s0 + and out9=3,in1 + mov twenty4=24 } +{ .mmi; ld4 out3=[out0],8 // s1 + ADDP rk0=0,in2 + mov sixteen=16 };; +{ .mmi; ld4 out5=[in0] // s2 + cmp.ne p6,p0=out9,r0 + mov maskff=0xff } +{ .mmb; ld4 out7=[out0] // s3 + ADDP rk1=KSZ,in2 + br.call.sptk.many b6=_ia64_AES_decrypt };; + +{ .mib; ADDP in0=4,in1 + ADDP in1=0,in1 +(p6) br.spnt .Ld_o_unaligned };; + +{ .mii; mov psr.um=loc0 + mov ar.pfs=pfssave + mov ar.lc=lcsave };; +{ .mmi; st4 [in1]=r16,8 // s0 + st4 [in0]=r20,8 // s1 + mov pr=prsave,0x1ffff };; +{ .mmb; st4 [in1]=r24 // s2 + st4 [in0]=r28 // s3 + br.ret.sptk.many b0 };; +#endif + +.align 32 +.Ld_i_unaligned: +{ .mmi; add out0=1,in0 + add out2=2,in0 + add out4=3,in0 };; +{ .mmi; ld1 r16=[in0],4 + ld1 r17=[out0],4 }//;; +{ .mmi; ld1 r18=[out2],4 + ld1 out1=[out4],4 };; // s0 +{ .mmi; ld1 r20=[in0],4 + ld1 r21=[out0],4 }//;; +{ .mmi; ld1 r22=[out2],4 + ld1 out3=[out4],4 };; // s1 +{ .mmi; ld1 r24=[in0],4 + ld1 r25=[out0],4 }//;; +{ .mmi; ld1 r26=[out2],4 + ld1 out5=[out4],4 };; // s2 +{ .mmi; ld1 r28=[in0] + ld1 r29=[out0] }//;; +{ .mmi; ld1 r30=[out2] + ld1 out7=[out4] };; // s3 + +{ .mii; + dep out1=r16,out1,24,8 //;; + dep out3=r20,out3,24,8 }//;; +{ .mii; ADDP rk0=0,in2 + dep out5=r24,out5,24,8 //;; + dep out7=r28,out7,24,8 };; +{ .mii; ADDP rk1=KSZ,in2 + dep out1=r17,out1,16,8 //;; + dep out3=r21,out3,16,8 }//;; +{ .mii; mov twenty4=24 + dep out5=r25,out5,16,8 //;; + dep out7=r29,out7,16,8 };; +{ .mii; mov sixteen=16 + dep out1=r18,out1,8,8 //;; + dep out3=r22,out3,8,8 }//;; +{ .mii; mov maskff=0xff + dep out5=r26,out5,8,8 //;; + dep out7=r30,out7,8,8 };; + +{ .mib; br.call.sptk.many b6=_ia64_AES_decrypt };; + +.Ld_o_unaligned: +{ .mii; ADDP out0=0,in1 + extr.u r17=r16,8,8 // s0 + shr.u r19=r16,twenty4 }//;; +{ .mii; ADDP out1=1,in1 + extr.u r18=r16,16,8 + shr.u r23=r20,twenty4 }//;; // s1 +{ .mii; ADDP out2=2,in1 + extr.u r21=r20,8,8 + shr.u r22=r20,sixteen }//;; +{ .mii; ADDP out3=3,in1 + extr.u r25=r24,8,8 // s2 + shr.u r27=r24,twenty4 };; +{ .mii; st1 [out3]=r16,4 + extr.u r26=r24,16,8 + shr.u r31=r28,twenty4 }//;; // s3 +{ .mii; st1 [out2]=r17,4 + extr.u r29=r28,8,8 + shr.u r30=r28,sixteen }//;; + +{ .mmi; st1 [out1]=r18,4 + st1 [out0]=r19,4 };; +{ .mmi; st1 [out3]=r20,4 + st1 [out2]=r21,4 }//;; +{ .mmi; st1 [out1]=r22,4 + st1 [out0]=r23,4 };; +{ .mmi; st1 [out3]=r24,4 + st1 [out2]=r25,4 + mov pr=prsave,0x1ffff }//;; +{ .mmi; st1 [out1]=r26,4 + st1 [out0]=r27,4 + mov ar.pfs=pfssave };; +{ .mmi; st1 [out3]=r28 + st1 [out2]=r29 + mov ar.lc=lcsave }//;; +{ .mmi; st1 [out1]=r30 + st1 [out0]=r31 } +{ .mfb; mov psr.um=loc0 // restore user mask + br.ret.sptk.many b0 };; +.endp AES_decrypt# + +// leave it in .text segment... +.align 64 +.global AES_Te# +.type AES_Te#,@object +AES_Te: data4 0xc66363a5,0xc66363a5, 0xf87c7c84,0xf87c7c84 + data4 0xee777799,0xee777799, 0xf67b7b8d,0xf67b7b8d + data4 0xfff2f20d,0xfff2f20d, 0xd66b6bbd,0xd66b6bbd + data4 0xde6f6fb1,0xde6f6fb1, 0x91c5c554,0x91c5c554 + data4 0x60303050,0x60303050, 0x02010103,0x02010103 + data4 0xce6767a9,0xce6767a9, 0x562b2b7d,0x562b2b7d + data4 0xe7fefe19,0xe7fefe19, 0xb5d7d762,0xb5d7d762 + data4 0x4dababe6,0x4dababe6, 0xec76769a,0xec76769a + data4 0x8fcaca45,0x8fcaca45, 0x1f82829d,0x1f82829d + data4 0x89c9c940,0x89c9c940, 0xfa7d7d87,0xfa7d7d87 + data4 0xeffafa15,0xeffafa15, 0xb25959eb,0xb25959eb + data4 0x8e4747c9,0x8e4747c9, 0xfbf0f00b,0xfbf0f00b + data4 0x41adadec,0x41adadec, 0xb3d4d467,0xb3d4d467 + data4 0x5fa2a2fd,0x5fa2a2fd, 0x45afafea,0x45afafea + data4 0x239c9cbf,0x239c9cbf, 0x53a4a4f7,0x53a4a4f7 + data4 0xe4727296,0xe4727296, 0x9bc0c05b,0x9bc0c05b + data4 0x75b7b7c2,0x75b7b7c2, 0xe1fdfd1c,0xe1fdfd1c + data4 0x3d9393ae,0x3d9393ae, 0x4c26266a,0x4c26266a + data4 0x6c36365a,0x6c36365a, 0x7e3f3f41,0x7e3f3f41 + data4 0xf5f7f702,0xf5f7f702, 0x83cccc4f,0x83cccc4f + data4 0x6834345c,0x6834345c, 0x51a5a5f4,0x51a5a5f4 + data4 0xd1e5e534,0xd1e5e534, 0xf9f1f108,0xf9f1f108 + data4 0xe2717193,0xe2717193, 0xabd8d873,0xabd8d873 + data4 0x62313153,0x62313153, 0x2a15153f,0x2a15153f + data4 0x0804040c,0x0804040c, 0x95c7c752,0x95c7c752 + data4 0x46232365,0x46232365, 0x9dc3c35e,0x9dc3c35e + data4 0x30181828,0x30181828, 0x379696a1,0x379696a1 + data4 0x0a05050f,0x0a05050f, 0x2f9a9ab5,0x2f9a9ab5 + data4 0x0e070709,0x0e070709, 0x24121236,0x24121236 + data4 0x1b80809b,0x1b80809b, 0xdfe2e23d,0xdfe2e23d + data4 0xcdebeb26,0xcdebeb26, 0x4e272769,0x4e272769 + data4 0x7fb2b2cd,0x7fb2b2cd, 0xea75759f,0xea75759f + data4 0x1209091b,0x1209091b, 0x1d83839e,0x1d83839e + data4 0x582c2c74,0x582c2c74, 0x341a1a2e,0x341a1a2e + data4 0x361b1b2d,0x361b1b2d, 0xdc6e6eb2,0xdc6e6eb2 + data4 0xb45a5aee,0xb45a5aee, 0x5ba0a0fb,0x5ba0a0fb + data4 0xa45252f6,0xa45252f6, 0x763b3b4d,0x763b3b4d + data4 0xb7d6d661,0xb7d6d661, 0x7db3b3ce,0x7db3b3ce + data4 0x5229297b,0x5229297b, 0xdde3e33e,0xdde3e33e + data4 0x5e2f2f71,0x5e2f2f71, 0x13848497,0x13848497 + data4 0xa65353f5,0xa65353f5, 0xb9d1d168,0xb9d1d168 + data4 0x00000000,0x00000000, 0xc1eded2c,0xc1eded2c + data4 0x40202060,0x40202060, 0xe3fcfc1f,0xe3fcfc1f + data4 0x79b1b1c8,0x79b1b1c8, 0xb65b5bed,0xb65b5bed + data4 0xd46a6abe,0xd46a6abe, 0x8dcbcb46,0x8dcbcb46 + data4 0x67bebed9,0x67bebed9, 0x7239394b,0x7239394b + data4 0x944a4ade,0x944a4ade, 0x984c4cd4,0x984c4cd4 + data4 0xb05858e8,0xb05858e8, 0x85cfcf4a,0x85cfcf4a + data4 0xbbd0d06b,0xbbd0d06b, 0xc5efef2a,0xc5efef2a + data4 0x4faaaae5,0x4faaaae5, 0xedfbfb16,0xedfbfb16 + data4 0x864343c5,0x864343c5, 0x9a4d4dd7,0x9a4d4dd7 + data4 0x66333355,0x66333355, 0x11858594,0x11858594 + data4 0x8a4545cf,0x8a4545cf, 0xe9f9f910,0xe9f9f910 + data4 0x04020206,0x04020206, 0xfe7f7f81,0xfe7f7f81 + data4 0xa05050f0,0xa05050f0, 0x783c3c44,0x783c3c44 + data4 0x259f9fba,0x259f9fba, 0x4ba8a8e3,0x4ba8a8e3 + data4 0xa25151f3,0xa25151f3, 0x5da3a3fe,0x5da3a3fe + data4 0x804040c0,0x804040c0, 0x058f8f8a,0x058f8f8a + data4 0x3f9292ad,0x3f9292ad, 0x219d9dbc,0x219d9dbc + data4 0x70383848,0x70383848, 0xf1f5f504,0xf1f5f504 + data4 0x63bcbcdf,0x63bcbcdf, 0x77b6b6c1,0x77b6b6c1 + data4 0xafdada75,0xafdada75, 0x42212163,0x42212163 + data4 0x20101030,0x20101030, 0xe5ffff1a,0xe5ffff1a + data4 0xfdf3f30e,0xfdf3f30e, 0xbfd2d26d,0xbfd2d26d + data4 0x81cdcd4c,0x81cdcd4c, 0x180c0c14,0x180c0c14 + data4 0x26131335,0x26131335, 0xc3ecec2f,0xc3ecec2f + data4 0xbe5f5fe1,0xbe5f5fe1, 0x359797a2,0x359797a2 + data4 0x884444cc,0x884444cc, 0x2e171739,0x2e171739 + data4 0x93c4c457,0x93c4c457, 0x55a7a7f2,0x55a7a7f2 + data4 0xfc7e7e82,0xfc7e7e82, 0x7a3d3d47,0x7a3d3d47 + data4 0xc86464ac,0xc86464ac, 0xba5d5de7,0xba5d5de7 + data4 0x3219192b,0x3219192b, 0xe6737395,0xe6737395 + data4 0xc06060a0,0xc06060a0, 0x19818198,0x19818198 + data4 0x9e4f4fd1,0x9e4f4fd1, 0xa3dcdc7f,0xa3dcdc7f + data4 0x44222266,0x44222266, 0x542a2a7e,0x542a2a7e + data4 0x3b9090ab,0x3b9090ab, 0x0b888883,0x0b888883 + data4 0x8c4646ca,0x8c4646ca, 0xc7eeee29,0xc7eeee29 + data4 0x6bb8b8d3,0x6bb8b8d3, 0x2814143c,0x2814143c + data4 0xa7dede79,0xa7dede79, 0xbc5e5ee2,0xbc5e5ee2 + data4 0x160b0b1d,0x160b0b1d, 0xaddbdb76,0xaddbdb76 + data4 0xdbe0e03b,0xdbe0e03b, 0x64323256,0x64323256 + data4 0x743a3a4e,0x743a3a4e, 0x140a0a1e,0x140a0a1e + data4 0x924949db,0x924949db, 0x0c06060a,0x0c06060a + data4 0x4824246c,0x4824246c, 0xb85c5ce4,0xb85c5ce4 + data4 0x9fc2c25d,0x9fc2c25d, 0xbdd3d36e,0xbdd3d36e + data4 0x43acacef,0x43acacef, 0xc46262a6,0xc46262a6 + data4 0x399191a8,0x399191a8, 0x319595a4,0x319595a4 + data4 0xd3e4e437,0xd3e4e437, 0xf279798b,0xf279798b + data4 0xd5e7e732,0xd5e7e732, 0x8bc8c843,0x8bc8c843 + data4 0x6e373759,0x6e373759, 0xda6d6db7,0xda6d6db7 + data4 0x018d8d8c,0x018d8d8c, 0xb1d5d564,0xb1d5d564 + data4 0x9c4e4ed2,0x9c4e4ed2, 0x49a9a9e0,0x49a9a9e0 + data4 0xd86c6cb4,0xd86c6cb4, 0xac5656fa,0xac5656fa + data4 0xf3f4f407,0xf3f4f407, 0xcfeaea25,0xcfeaea25 + data4 0xca6565af,0xca6565af, 0xf47a7a8e,0xf47a7a8e + data4 0x47aeaee9,0x47aeaee9, 0x10080818,0x10080818 + data4 0x6fbabad5,0x6fbabad5, 0xf0787888,0xf0787888 + data4 0x4a25256f,0x4a25256f, 0x5c2e2e72,0x5c2e2e72 + data4 0x381c1c24,0x381c1c24, 0x57a6a6f1,0x57a6a6f1 + data4 0x73b4b4c7,0x73b4b4c7, 0x97c6c651,0x97c6c651 + data4 0xcbe8e823,0xcbe8e823, 0xa1dddd7c,0xa1dddd7c + data4 0xe874749c,0xe874749c, 0x3e1f1f21,0x3e1f1f21 + data4 0x964b4bdd,0x964b4bdd, 0x61bdbddc,0x61bdbddc + data4 0x0d8b8b86,0x0d8b8b86, 0x0f8a8a85,0x0f8a8a85 + data4 0xe0707090,0xe0707090, 0x7c3e3e42,0x7c3e3e42 + data4 0x71b5b5c4,0x71b5b5c4, 0xcc6666aa,0xcc6666aa + data4 0x904848d8,0x904848d8, 0x06030305,0x06030305 + data4 0xf7f6f601,0xf7f6f601, 0x1c0e0e12,0x1c0e0e12 + data4 0xc26161a3,0xc26161a3, 0x6a35355f,0x6a35355f + data4 0xae5757f9,0xae5757f9, 0x69b9b9d0,0x69b9b9d0 + data4 0x17868691,0x17868691, 0x99c1c158,0x99c1c158 + data4 0x3a1d1d27,0x3a1d1d27, 0x279e9eb9,0x279e9eb9 + data4 0xd9e1e138,0xd9e1e138, 0xebf8f813,0xebf8f813 + data4 0x2b9898b3,0x2b9898b3, 0x22111133,0x22111133 + data4 0xd26969bb,0xd26969bb, 0xa9d9d970,0xa9d9d970 + data4 0x078e8e89,0x078e8e89, 0x339494a7,0x339494a7 + data4 0x2d9b9bb6,0x2d9b9bb6, 0x3c1e1e22,0x3c1e1e22 + data4 0x15878792,0x15878792, 0xc9e9e920,0xc9e9e920 + data4 0x87cece49,0x87cece49, 0xaa5555ff,0xaa5555ff + data4 0x50282878,0x50282878, 0xa5dfdf7a,0xa5dfdf7a + data4 0x038c8c8f,0x038c8c8f, 0x59a1a1f8,0x59a1a1f8 + data4 0x09898980,0x09898980, 0x1a0d0d17,0x1a0d0d17 + data4 0x65bfbfda,0x65bfbfda, 0xd7e6e631,0xd7e6e631 + data4 0x844242c6,0x844242c6, 0xd06868b8,0xd06868b8 + data4 0x824141c3,0x824141c3, 0x299999b0,0x299999b0 + data4 0x5a2d2d77,0x5a2d2d77, 0x1e0f0f11,0x1e0f0f11 + data4 0x7bb0b0cb,0x7bb0b0cb, 0xa85454fc,0xa85454fc + data4 0x6dbbbbd6,0x6dbbbbd6, 0x2c16163a,0x2c16163a +// Te4: + data1 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5 + data1 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76 + data1 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0 + data1 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0 + data1 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc + data1 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15 + data1 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a + data1 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75 + data1 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0 + data1 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84 + data1 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b + data1 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf + data1 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85 + data1 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8 + data1 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5 + data1 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2 + data1 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17 + data1 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73 + data1 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88 + data1 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb + data1 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c + data1 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79 + data1 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9 + data1 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08 + data1 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6 + data1 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a + data1 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e + data1 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e + data1 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94 + data1 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf + data1 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68 + data1 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +.size AES_Te#,2048+256 // HP-UX assembler fails to ".-AES_Te#" + +.align 64 +.global AES_Td# +.type AES_Td#,@object +AES_Td: data4 0x51f4a750,0x51f4a750, 0x7e416553,0x7e416553 + data4 0x1a17a4c3,0x1a17a4c3, 0x3a275e96,0x3a275e96 + data4 0x3bab6bcb,0x3bab6bcb, 0x1f9d45f1,0x1f9d45f1 + data4 0xacfa58ab,0xacfa58ab, 0x4be30393,0x4be30393 + data4 0x2030fa55,0x2030fa55, 0xad766df6,0xad766df6 + data4 0x88cc7691,0x88cc7691, 0xf5024c25,0xf5024c25 + data4 0x4fe5d7fc,0x4fe5d7fc, 0xc52acbd7,0xc52acbd7 + data4 0x26354480,0x26354480, 0xb562a38f,0xb562a38f + data4 0xdeb15a49,0xdeb15a49, 0x25ba1b67,0x25ba1b67 + data4 0x45ea0e98,0x45ea0e98, 0x5dfec0e1,0x5dfec0e1 + data4 0xc32f7502,0xc32f7502, 0x814cf012,0x814cf012 + data4 0x8d4697a3,0x8d4697a3, 0x6bd3f9c6,0x6bd3f9c6 + data4 0x038f5fe7,0x038f5fe7, 0x15929c95,0x15929c95 + data4 0xbf6d7aeb,0xbf6d7aeb, 0x955259da,0x955259da + data4 0xd4be832d,0xd4be832d, 0x587421d3,0x587421d3 + data4 0x49e06929,0x49e06929, 0x8ec9c844,0x8ec9c844 + data4 0x75c2896a,0x75c2896a, 0xf48e7978,0xf48e7978 + data4 0x99583e6b,0x99583e6b, 0x27b971dd,0x27b971dd + data4 0xbee14fb6,0xbee14fb6, 0xf088ad17,0xf088ad17 + data4 0xc920ac66,0xc920ac66, 0x7dce3ab4,0x7dce3ab4 + data4 0x63df4a18,0x63df4a18, 0xe51a3182,0xe51a3182 + data4 0x97513360,0x97513360, 0x62537f45,0x62537f45 + data4 0xb16477e0,0xb16477e0, 0xbb6bae84,0xbb6bae84 + data4 0xfe81a01c,0xfe81a01c, 0xf9082b94,0xf9082b94 + data4 0x70486858,0x70486858, 0x8f45fd19,0x8f45fd19 + data4 0x94de6c87,0x94de6c87, 0x527bf8b7,0x527bf8b7 + data4 0xab73d323,0xab73d323, 0x724b02e2,0x724b02e2 + data4 0xe31f8f57,0xe31f8f57, 0x6655ab2a,0x6655ab2a + data4 0xb2eb2807,0xb2eb2807, 0x2fb5c203,0x2fb5c203 + data4 0x86c57b9a,0x86c57b9a, 0xd33708a5,0xd33708a5 + data4 0x302887f2,0x302887f2, 0x23bfa5b2,0x23bfa5b2 + data4 0x02036aba,0x02036aba, 0xed16825c,0xed16825c + data4 0x8acf1c2b,0x8acf1c2b, 0xa779b492,0xa779b492 + data4 0xf307f2f0,0xf307f2f0, 0x4e69e2a1,0x4e69e2a1 + data4 0x65daf4cd,0x65daf4cd, 0x0605bed5,0x0605bed5 + data4 0xd134621f,0xd134621f, 0xc4a6fe8a,0xc4a6fe8a + data4 0x342e539d,0x342e539d, 0xa2f355a0,0xa2f355a0 + data4 0x058ae132,0x058ae132, 0xa4f6eb75,0xa4f6eb75 + data4 0x0b83ec39,0x0b83ec39, 0x4060efaa,0x4060efaa + data4 0x5e719f06,0x5e719f06, 0xbd6e1051,0xbd6e1051 + data4 0x3e218af9,0x3e218af9, 0x96dd063d,0x96dd063d + data4 0xdd3e05ae,0xdd3e05ae, 0x4de6bd46,0x4de6bd46 + data4 0x91548db5,0x91548db5, 0x71c45d05,0x71c45d05 + data4 0x0406d46f,0x0406d46f, 0x605015ff,0x605015ff + data4 0x1998fb24,0x1998fb24, 0xd6bde997,0xd6bde997 + data4 0x894043cc,0x894043cc, 0x67d99e77,0x67d99e77 + data4 0xb0e842bd,0xb0e842bd, 0x07898b88,0x07898b88 + data4 0xe7195b38,0xe7195b38, 0x79c8eedb,0x79c8eedb + data4 0xa17c0a47,0xa17c0a47, 0x7c420fe9,0x7c420fe9 + data4 0xf8841ec9,0xf8841ec9, 0x00000000,0x00000000 + data4 0x09808683,0x09808683, 0x322bed48,0x322bed48 + data4 0x1e1170ac,0x1e1170ac, 0x6c5a724e,0x6c5a724e + data4 0xfd0efffb,0xfd0efffb, 0x0f853856,0x0f853856 + data4 0x3daed51e,0x3daed51e, 0x362d3927,0x362d3927 + data4 0x0a0fd964,0x0a0fd964, 0x685ca621,0x685ca621 + data4 0x9b5b54d1,0x9b5b54d1, 0x24362e3a,0x24362e3a + data4 0x0c0a67b1,0x0c0a67b1, 0x9357e70f,0x9357e70f + data4 0xb4ee96d2,0xb4ee96d2, 0x1b9b919e,0x1b9b919e + data4 0x80c0c54f,0x80c0c54f, 0x61dc20a2,0x61dc20a2 + data4 0x5a774b69,0x5a774b69, 0x1c121a16,0x1c121a16 + data4 0xe293ba0a,0xe293ba0a, 0xc0a02ae5,0xc0a02ae5 + data4 0x3c22e043,0x3c22e043, 0x121b171d,0x121b171d + data4 0x0e090d0b,0x0e090d0b, 0xf28bc7ad,0xf28bc7ad + data4 0x2db6a8b9,0x2db6a8b9, 0x141ea9c8,0x141ea9c8 + data4 0x57f11985,0x57f11985, 0xaf75074c,0xaf75074c + data4 0xee99ddbb,0xee99ddbb, 0xa37f60fd,0xa37f60fd + data4 0xf701269f,0xf701269f, 0x5c72f5bc,0x5c72f5bc + data4 0x44663bc5,0x44663bc5, 0x5bfb7e34,0x5bfb7e34 + data4 0x8b432976,0x8b432976, 0xcb23c6dc,0xcb23c6dc + data4 0xb6edfc68,0xb6edfc68, 0xb8e4f163,0xb8e4f163 + data4 0xd731dcca,0xd731dcca, 0x42638510,0x42638510 + data4 0x13972240,0x13972240, 0x84c61120,0x84c61120 + data4 0x854a247d,0x854a247d, 0xd2bb3df8,0xd2bb3df8 + data4 0xaef93211,0xaef93211, 0xc729a16d,0xc729a16d + data4 0x1d9e2f4b,0x1d9e2f4b, 0xdcb230f3,0xdcb230f3 + data4 0x0d8652ec,0x0d8652ec, 0x77c1e3d0,0x77c1e3d0 + data4 0x2bb3166c,0x2bb3166c, 0xa970b999,0xa970b999 + data4 0x119448fa,0x119448fa, 0x47e96422,0x47e96422 + data4 0xa8fc8cc4,0xa8fc8cc4, 0xa0f03f1a,0xa0f03f1a + data4 0x567d2cd8,0x567d2cd8, 0x223390ef,0x223390ef + data4 0x87494ec7,0x87494ec7, 0xd938d1c1,0xd938d1c1 + data4 0x8ccaa2fe,0x8ccaa2fe, 0x98d40b36,0x98d40b36 + data4 0xa6f581cf,0xa6f581cf, 0xa57ade28,0xa57ade28 + data4 0xdab78e26,0xdab78e26, 0x3fadbfa4,0x3fadbfa4 + data4 0x2c3a9de4,0x2c3a9de4, 0x5078920d,0x5078920d + data4 0x6a5fcc9b,0x6a5fcc9b, 0x547e4662,0x547e4662 + data4 0xf68d13c2,0xf68d13c2, 0x90d8b8e8,0x90d8b8e8 + data4 0x2e39f75e,0x2e39f75e, 0x82c3aff5,0x82c3aff5 + data4 0x9f5d80be,0x9f5d80be, 0x69d0937c,0x69d0937c + data4 0x6fd52da9,0x6fd52da9, 0xcf2512b3,0xcf2512b3 + data4 0xc8ac993b,0xc8ac993b, 0x10187da7,0x10187da7 + data4 0xe89c636e,0xe89c636e, 0xdb3bbb7b,0xdb3bbb7b + data4 0xcd267809,0xcd267809, 0x6e5918f4,0x6e5918f4 + data4 0xec9ab701,0xec9ab701, 0x834f9aa8,0x834f9aa8 + data4 0xe6956e65,0xe6956e65, 0xaaffe67e,0xaaffe67e + data4 0x21bccf08,0x21bccf08, 0xef15e8e6,0xef15e8e6 + data4 0xbae79bd9,0xbae79bd9, 0x4a6f36ce,0x4a6f36ce + data4 0xea9f09d4,0xea9f09d4, 0x29b07cd6,0x29b07cd6 + data4 0x31a4b2af,0x31a4b2af, 0x2a3f2331,0x2a3f2331 + data4 0xc6a59430,0xc6a59430, 0x35a266c0,0x35a266c0 + data4 0x744ebc37,0x744ebc37, 0xfc82caa6,0xfc82caa6 + data4 0xe090d0b0,0xe090d0b0, 0x33a7d815,0x33a7d815 + data4 0xf104984a,0xf104984a, 0x41ecdaf7,0x41ecdaf7 + data4 0x7fcd500e,0x7fcd500e, 0x1791f62f,0x1791f62f + data4 0x764dd68d,0x764dd68d, 0x43efb04d,0x43efb04d + data4 0xccaa4d54,0xccaa4d54, 0xe49604df,0xe49604df + data4 0x9ed1b5e3,0x9ed1b5e3, 0x4c6a881b,0x4c6a881b + data4 0xc12c1fb8,0xc12c1fb8, 0x4665517f,0x4665517f + data4 0x9d5eea04,0x9d5eea04, 0x018c355d,0x018c355d + data4 0xfa877473,0xfa877473, 0xfb0b412e,0xfb0b412e + data4 0xb3671d5a,0xb3671d5a, 0x92dbd252,0x92dbd252 + data4 0xe9105633,0xe9105633, 0x6dd64713,0x6dd64713 + data4 0x9ad7618c,0x9ad7618c, 0x37a10c7a,0x37a10c7a + data4 0x59f8148e,0x59f8148e, 0xeb133c89,0xeb133c89 + data4 0xcea927ee,0xcea927ee, 0xb761c935,0xb761c935 + data4 0xe11ce5ed,0xe11ce5ed, 0x7a47b13c,0x7a47b13c + data4 0x9cd2df59,0x9cd2df59, 0x55f2733f,0x55f2733f + data4 0x1814ce79,0x1814ce79, 0x73c737bf,0x73c737bf + data4 0x53f7cdea,0x53f7cdea, 0x5ffdaa5b,0x5ffdaa5b + data4 0xdf3d6f14,0xdf3d6f14, 0x7844db86,0x7844db86 + data4 0xcaaff381,0xcaaff381, 0xb968c43e,0xb968c43e + data4 0x3824342c,0x3824342c, 0xc2a3405f,0xc2a3405f + data4 0x161dc372,0x161dc372, 0xbce2250c,0xbce2250c + data4 0x283c498b,0x283c498b, 0xff0d9541,0xff0d9541 + data4 0x39a80171,0x39a80171, 0x080cb3de,0x080cb3de + data4 0xd8b4e49c,0xd8b4e49c, 0x6456c190,0x6456c190 + data4 0x7bcb8461,0x7bcb8461, 0xd532b670,0xd532b670 + data4 0x486c5c74,0x486c5c74, 0xd0b85742,0xd0b85742 +// Td4: + data1 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38 + data1 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb + data1 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87 + data1 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb + data1 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d + data1 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e + data1 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2 + data1 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 + data1 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16 + data1 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 + data1 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda + data1 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 + data1 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a + data1 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 + data1 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02 + data1 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b + data1 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea + data1 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 + data1 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85 + data1 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e + data1 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89 + data1 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b + data1 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20 + data1 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 + data1 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31 + data1 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f + data1 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d + data1 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef + data1 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0 + data1 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 + data1 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26 + data1 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d +.size AES_Td#,2048+256 // HP-UX assembler fails to ".-AES_Td#" diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-mips.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-mips.pl new file mode 100644 index 000000000..716c3356e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-mips.pl @@ -0,0 +1,2170 @@ +#! /usr/bin/env perl +# Copyright 2010-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# AES for MIPS + +# October 2010 +# +# Code uses 1K[+256B] S-box and on single-issue core [such as R5000] +# spends ~68 cycles per byte processed with 128-bit key. This is ~16% +# faster than gcc-generated code, which is not very impressive. But +# recall that compressed S-box requires extra processing, namely +# additional rotations. Rotations are implemented with lwl/lwr pairs, +# which is normally used for loading unaligned data. Another cool +# thing about this module is its endian neutrality, which means that +# it processes data without ever changing byte order... + +# September 2012 +# +# Add MIPS32R2 (~10% less instructions) and SmartMIPS ASE (further +# ~25% less instructions) code. Note that there is no run-time switch, +# instead, code path is chosen upon pre-process time, pass -mips32r2 +# or/and -msmartmips. + +###################################################################### +# There is a number of MIPS ABI in use, O32 and N32/64 are most +# widely used. Then there is a new contender: NUBI. It appears that if +# one picks the latter, it's possible to arrange code in ABI neutral +# manner. Therefore let's stick to NUBI register layout: +# +($zero,$at,$t0,$t1,$t2)=map("\$$_",(0..2,24,25)); +($a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7)=map("\$$_",(4..11)); +($s0,$s1,$s2,$s3,$s4,$s5,$s6,$s7,$s8,$s9,$s10,$s11)=map("\$$_",(12..23)); +($gp,$tp,$sp,$fp,$ra)=map("\$$_",(3,28..31)); +# +# The return value is placed in $a0. Following coding rules facilitate +# interoperability: +# +# - never ever touch $tp, "thread pointer", former $gp; +# - copy return value to $t0, former $v0 [or to $a0 if you're adapting +# old code]; +# - on O32 populate $a4-$a7 with 'lw $aN,4*N($sp)' if necessary; +# +# For reference here is register layout for N32/64 MIPS ABIs: +# +# ($zero,$at,$v0,$v1)=map("\$$_",(0..3)); +# ($a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7)=map("\$$_",(4..11)); +# ($t0,$t1,$t2,$t3,$t8,$t9)=map("\$$_",(12..15,24,25)); +# ($s0,$s1,$s2,$s3,$s4,$s5,$s6,$s7)=map("\$$_",(16..23)); +# ($gp,$sp,$fp,$ra)=map("\$$_",(28..31)); +# +$flavour = shift || "o32"; # supported flavours are o32,n32,64,nubi32,nubi64 + +if ($flavour =~ /64|n32/i) { + $PTR_LA="dla"; + $PTR_ADD="daddu"; # incidentally works even on n32 + $PTR_SUB="dsubu"; # incidentally works even on n32 + $PTR_INS="dins"; + $REG_S="sd"; + $REG_L="ld"; + $PTR_SLL="dsll"; # incidentally works even on n32 + $SZREG=8; +} else { + $PTR_LA="la"; + $PTR_ADD="addu"; + $PTR_SUB="subu"; + $PTR_INS="ins"; + $REG_S="sw"; + $REG_L="lw"; + $PTR_SLL="sll"; + $SZREG=4; +} +$pf = ($flavour =~ /nubi/i) ? $t0 : $t2; +# +# +# +###################################################################### + +$big_endian=(`echo MIPSEB | $ENV{CC} -E -`=~/MIPSEB/)?0:1 if ($ENV{CC}); + +for (@ARGV) { $output=$_ if (/\w[\w\-]*\.\w+$/); } +open STDOUT,">$output"; + +if (!defined($big_endian)) +{ $big_endian=(unpack('L',pack('N',1))==1); } + +while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} +open STDOUT,">$output"; + +my ($MSB,$LSB)=(0,3); # automatically converted to little-endian + +$code.=<<___; +#include "mips_arch.h" + +.text +#if !defined(__mips_eabi) && (!defined(__vxworks) || defined(__pic__)) +.option pic2 +#endif +.set noat +___ + +{{{ +my $FRAMESIZE=16*$SZREG; +my $SAVED_REGS_MASK = ($flavour =~ /nubi/i) ? "0xc0fff008" : "0xc0ff0000"; + +my ($inp,$out,$key,$Tbl,$s0,$s1,$s2,$s3)=($a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7); +my ($i0,$i1,$i2,$i3)=($at,$t0,$t1,$t2); +my ($t0,$t1,$t2,$t3,$t4,$t5,$t6,$t7,$t8,$t9,$t10,$t11) = map("\$$_",(12..23)); +my ($key0,$cnt)=($gp,$fp); + +# instruction ordering is "stolen" from output from MIPSpro assembler +# invoked with -mips3 -O3 arguments... +$code.=<<___; +.align 5 +.ent _mips_AES_encrypt +_mips_AES_encrypt: + .frame $sp,0,$ra + .set reorder + lw $t0,0($key) + lw $t1,4($key) + lw $t2,8($key) + lw $t3,12($key) + lw $cnt,240($key) + $PTR_ADD $key0,$key,16 + + xor $s0,$t0 + xor $s1,$t1 + xor $s2,$t2 + xor $s3,$t3 + + subu $cnt,1 +#if defined(__mips_smartmips) + ext $i0,$s1,16,8 +.Loop_enc: + ext $i1,$s2,16,8 + ext $i2,$s3,16,8 + ext $i3,$s0,16,8 + lwxs $t0,$i0($Tbl) # Te1[s1>>16] + ext $i0,$s2,8,8 + lwxs $t1,$i1($Tbl) # Te1[s2>>16] + ext $i1,$s3,8,8 + lwxs $t2,$i2($Tbl) # Te1[s3>>16] + ext $i2,$s0,8,8 + lwxs $t3,$i3($Tbl) # Te1[s0>>16] + ext $i3,$s1,8,8 + + lwxs $t4,$i0($Tbl) # Te2[s2>>8] + ext $i0,$s3,0,8 + lwxs $t5,$i1($Tbl) # Te2[s3>>8] + ext $i1,$s0,0,8 + lwxs $t6,$i2($Tbl) # Te2[s0>>8] + ext $i2,$s1,0,8 + lwxs $t7,$i3($Tbl) # Te2[s1>>8] + ext $i3,$s2,0,8 + + lwxs $t8,$i0($Tbl) # Te3[s3] + ext $i0,$s0,24,8 + lwxs $t9,$i1($Tbl) # Te3[s0] + ext $i1,$s1,24,8 + lwxs $t10,$i2($Tbl) # Te3[s1] + ext $i2,$s2,24,8 + lwxs $t11,$i3($Tbl) # Te3[s2] + ext $i3,$s3,24,8 + + rotr $t0,$t0,8 + rotr $t1,$t1,8 + rotr $t2,$t2,8 + rotr $t3,$t3,8 + + rotr $t4,$t4,16 + rotr $t5,$t5,16 + rotr $t6,$t6,16 + rotr $t7,$t7,16 + + xor $t0,$t4 + lwxs $t4,$i0($Tbl) # Te0[s0>>24] + xor $t1,$t5 + lwxs $t5,$i1($Tbl) # Te0[s1>>24] + xor $t2,$t6 + lwxs $t6,$i2($Tbl) # Te0[s2>>24] + xor $t3,$t7 + lwxs $t7,$i3($Tbl) # Te0[s3>>24] + + rotr $t8,$t8,24 + lw $s0,0($key0) + rotr $t9,$t9,24 + lw $s1,4($key0) + rotr $t10,$t10,24 + lw $s2,8($key0) + rotr $t11,$t11,24 + lw $s3,12($key0) + + xor $t0,$t8 + xor $t1,$t9 + xor $t2,$t10 + xor $t3,$t11 + + xor $t0,$t4 + xor $t1,$t5 + xor $t2,$t6 + xor $t3,$t7 + + subu $cnt,1 + $PTR_ADD $key0,16 + xor $s0,$t0 + xor $s1,$t1 + xor $s2,$t2 + xor $s3,$t3 + .set noreorder + bnez $cnt,.Loop_enc + ext $i0,$s1,16,8 + + _xtr $i0,$s1,16-2 +#else + _xtr $i0,$s1,16-2 +.Loop_enc: + _xtr $i1,$s2,16-2 + _xtr $i2,$s3,16-2 + _xtr $i3,$s0,16-2 + and $i0,0x3fc + and $i1,0x3fc + and $i2,0x3fc + and $i3,0x3fc + $PTR_ADD $i0,$Tbl + $PTR_ADD $i1,$Tbl + $PTR_ADD $i2,$Tbl + $PTR_ADD $i3,$Tbl +#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2) + lw $t0,0($i0) # Te1[s1>>16] + _xtr $i0,$s2,8-2 + lw $t1,0($i1) # Te1[s2>>16] + _xtr $i1,$s3,8-2 + lw $t2,0($i2) # Te1[s3>>16] + _xtr $i2,$s0,8-2 + lw $t3,0($i3) # Te1[s0>>16] + _xtr $i3,$s1,8-2 +#else + lwl $t0,3($i0) # Te1[s1>>16] + lwl $t1,3($i1) # Te1[s2>>16] + lwl $t2,3($i2) # Te1[s3>>16] + lwl $t3,3($i3) # Te1[s0>>16] + lwr $t0,2($i0) # Te1[s1>>16] + _xtr $i0,$s2,8-2 + lwr $t1,2($i1) # Te1[s2>>16] + _xtr $i1,$s3,8-2 + lwr $t2,2($i2) # Te1[s3>>16] + _xtr $i2,$s0,8-2 + lwr $t3,2($i3) # Te1[s0>>16] + _xtr $i3,$s1,8-2 +#endif + and $i0,0x3fc + and $i1,0x3fc + and $i2,0x3fc + and $i3,0x3fc + $PTR_ADD $i0,$Tbl + $PTR_ADD $i1,$Tbl + $PTR_ADD $i2,$Tbl + $PTR_ADD $i3,$Tbl +#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2) + rotr $t0,$t0,8 + rotr $t1,$t1,8 + rotr $t2,$t2,8 + rotr $t3,$t3,8 +# if defined(_MIPSEL) + lw $t4,0($i0) # Te2[s2>>8] + _xtr $i0,$s3,0-2 + lw $t5,0($i1) # Te2[s3>>8] + _xtr $i1,$s0,0-2 + lw $t6,0($i2) # Te2[s0>>8] + _xtr $i2,$s1,0-2 + lw $t7,0($i3) # Te2[s1>>8] + _xtr $i3,$s2,0-2 + + and $i0,0x3fc + and $i1,0x3fc + and $i2,0x3fc + and $i3,0x3fc + $PTR_ADD $i0,$Tbl + $PTR_ADD $i1,$Tbl + $PTR_ADD $i2,$Tbl + $PTR_ADD $i3,$Tbl + lw $t8,0($i0) # Te3[s3] + $PTR_INS $i0,$s0,2,8 + lw $t9,0($i1) # Te3[s0] + $PTR_INS $i1,$s1,2,8 + lw $t10,0($i2) # Te3[s1] + $PTR_INS $i2,$s2,2,8 + lw $t11,0($i3) # Te3[s2] + $PTR_INS $i3,$s3,2,8 +# else + lw $t4,0($i0) # Te2[s2>>8] + $PTR_INS $i0,$s3,2,8 + lw $t5,0($i1) # Te2[s3>>8] + $PTR_INS $i1,$s0,2,8 + lw $t6,0($i2) # Te2[s0>>8] + $PTR_INS $i2,$s1,2,8 + lw $t7,0($i3) # Te2[s1>>8] + $PTR_INS $i3,$s2,2,8 + + lw $t8,0($i0) # Te3[s3] + _xtr $i0,$s0,24-2 + lw $t9,0($i1) # Te3[s0] + _xtr $i1,$s1,24-2 + lw $t10,0($i2) # Te3[s1] + _xtr $i2,$s2,24-2 + lw $t11,0($i3) # Te3[s2] + _xtr $i3,$s3,24-2 + + and $i0,0x3fc + and $i1,0x3fc + and $i2,0x3fc + and $i3,0x3fc + $PTR_ADD $i0,$Tbl + $PTR_ADD $i1,$Tbl + $PTR_ADD $i2,$Tbl + $PTR_ADD $i3,$Tbl +# endif + rotr $t4,$t4,16 + rotr $t5,$t5,16 + rotr $t6,$t6,16 + rotr $t7,$t7,16 + + rotr $t8,$t8,24 + rotr $t9,$t9,24 + rotr $t10,$t10,24 + rotr $t11,$t11,24 +#else + lwl $t4,2($i0) # Te2[s2>>8] + lwl $t5,2($i1) # Te2[s3>>8] + lwl $t6,2($i2) # Te2[s0>>8] + lwl $t7,2($i3) # Te2[s1>>8] + lwr $t4,1($i0) # Te2[s2>>8] + _xtr $i0,$s3,0-2 + lwr $t5,1($i1) # Te2[s3>>8] + _xtr $i1,$s0,0-2 + lwr $t6,1($i2) # Te2[s0>>8] + _xtr $i2,$s1,0-2 + lwr $t7,1($i3) # Te2[s1>>8] + _xtr $i3,$s2,0-2 + + and $i0,0x3fc + and $i1,0x3fc + and $i2,0x3fc + and $i3,0x3fc + $PTR_ADD $i0,$Tbl + $PTR_ADD $i1,$Tbl + $PTR_ADD $i2,$Tbl + $PTR_ADD $i3,$Tbl + lwl $t8,1($i0) # Te3[s3] + lwl $t9,1($i1) # Te3[s0] + lwl $t10,1($i2) # Te3[s1] + lwl $t11,1($i3) # Te3[s2] + lwr $t8,0($i0) # Te3[s3] + _xtr $i0,$s0,24-2 + lwr $t9,0($i1) # Te3[s0] + _xtr $i1,$s1,24-2 + lwr $t10,0($i2) # Te3[s1] + _xtr $i2,$s2,24-2 + lwr $t11,0($i3) # Te3[s2] + _xtr $i3,$s3,24-2 + + and $i0,0x3fc + and $i1,0x3fc + and $i2,0x3fc + and $i3,0x3fc + $PTR_ADD $i0,$Tbl + $PTR_ADD $i1,$Tbl + $PTR_ADD $i2,$Tbl + $PTR_ADD $i3,$Tbl +#endif + xor $t0,$t4 + lw $t4,0($i0) # Te0[s0>>24] + xor $t1,$t5 + lw $t5,0($i1) # Te0[s1>>24] + xor $t2,$t6 + lw $t6,0($i2) # Te0[s2>>24] + xor $t3,$t7 + lw $t7,0($i3) # Te0[s3>>24] + + xor $t0,$t8 + lw $s0,0($key0) + xor $t1,$t9 + lw $s1,4($key0) + xor $t2,$t10 + lw $s2,8($key0) + xor $t3,$t11 + lw $s3,12($key0) + + xor $t0,$t4 + xor $t1,$t5 + xor $t2,$t6 + xor $t3,$t7 + + subu $cnt,1 + $PTR_ADD $key0,16 + xor $s0,$t0 + xor $s1,$t1 + xor $s2,$t2 + xor $s3,$t3 + .set noreorder + bnez $cnt,.Loop_enc + _xtr $i0,$s1,16-2 +#endif + + .set reorder + _xtr $i1,$s2,16-2 + _xtr $i2,$s3,16-2 + _xtr $i3,$s0,16-2 + and $i0,0x3fc + and $i1,0x3fc + and $i2,0x3fc + and $i3,0x3fc + $PTR_ADD $i0,$Tbl + $PTR_ADD $i1,$Tbl + $PTR_ADD $i2,$Tbl + $PTR_ADD $i3,$Tbl + lbu $t0,2($i0) # Te4[s1>>16] + _xtr $i0,$s2,8-2 + lbu $t1,2($i1) # Te4[s2>>16] + _xtr $i1,$s3,8-2 + lbu $t2,2($i2) # Te4[s3>>16] + _xtr $i2,$s0,8-2 + lbu $t3,2($i3) # Te4[s0>>16] + _xtr $i3,$s1,8-2 + + and $i0,0x3fc + and $i1,0x3fc + and $i2,0x3fc + and $i3,0x3fc + $PTR_ADD $i0,$Tbl + $PTR_ADD $i1,$Tbl + $PTR_ADD $i2,$Tbl + $PTR_ADD $i3,$Tbl +#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2) +# if defined(_MIPSEL) + lbu $t4,2($i0) # Te4[s2>>8] + $PTR_INS $i0,$s0,2,8 + lbu $t5,2($i1) # Te4[s3>>8] + $PTR_INS $i1,$s1,2,8 + lbu $t6,2($i2) # Te4[s0>>8] + $PTR_INS $i2,$s2,2,8 + lbu $t7,2($i3) # Te4[s1>>8] + $PTR_INS $i3,$s3,2,8 + + lbu $t8,2($i0) # Te4[s0>>24] + _xtr $i0,$s3,0-2 + lbu $t9,2($i1) # Te4[s1>>24] + _xtr $i1,$s0,0-2 + lbu $t10,2($i2) # Te4[s2>>24] + _xtr $i2,$s1,0-2 + lbu $t11,2($i3) # Te4[s3>>24] + _xtr $i3,$s2,0-2 + + and $i0,0x3fc + and $i1,0x3fc + and $i2,0x3fc + and $i3,0x3fc + $PTR_ADD $i0,$Tbl + $PTR_ADD $i1,$Tbl + $PTR_ADD $i2,$Tbl + $PTR_ADD $i3,$Tbl +# else + lbu $t4,2($i0) # Te4[s2>>8] + _xtr $i0,$s0,24-2 + lbu $t5,2($i1) # Te4[s3>>8] + _xtr $i1,$s1,24-2 + lbu $t6,2($i2) # Te4[s0>>8] + _xtr $i2,$s2,24-2 + lbu $t7,2($i3) # Te4[s1>>8] + _xtr $i3,$s3,24-2 + + and $i0,0x3fc + and $i1,0x3fc + and $i2,0x3fc + and $i3,0x3fc + $PTR_ADD $i0,$Tbl + $PTR_ADD $i1,$Tbl + $PTR_ADD $i2,$Tbl + $PTR_ADD $i3,$Tbl + lbu $t8,2($i0) # Te4[s0>>24] + $PTR_INS $i0,$s3,2,8 + lbu $t9,2($i1) # Te4[s1>>24] + $PTR_INS $i1,$s0,2,8 + lbu $t10,2($i2) # Te4[s2>>24] + $PTR_INS $i2,$s1,2,8 + lbu $t11,2($i3) # Te4[s3>>24] + $PTR_INS $i3,$s2,2,8 +# endif + _ins $t0,16 + _ins $t1,16 + _ins $t2,16 + _ins $t3,16 + + _ins2 $t0,$t4,8 + lbu $t4,2($i0) # Te4[s3] + _ins2 $t1,$t5,8 + lbu $t5,2($i1) # Te4[s0] + _ins2 $t2,$t6,8 + lbu $t6,2($i2) # Te4[s1] + _ins2 $t3,$t7,8 + lbu $t7,2($i3) # Te4[s2] + + _ins2 $t0,$t8,24 + lw $s0,0($key0) + _ins2 $t1,$t9,24 + lw $s1,4($key0) + _ins2 $t2,$t10,24 + lw $s2,8($key0) + _ins2 $t3,$t11,24 + lw $s3,12($key0) + + _ins2 $t0,$t4,0 + _ins2 $t1,$t5,0 + _ins2 $t2,$t6,0 + _ins2 $t3,$t7,0 +#else + lbu $t4,2($i0) # Te4[s2>>8] + _xtr $i0,$s0,24-2 + lbu $t5,2($i1) # Te4[s3>>8] + _xtr $i1,$s1,24-2 + lbu $t6,2($i2) # Te4[s0>>8] + _xtr $i2,$s2,24-2 + lbu $t7,2($i3) # Te4[s1>>8] + _xtr $i3,$s3,24-2 + + and $i0,0x3fc + and $i1,0x3fc + and $i2,0x3fc + and $i3,0x3fc + $PTR_ADD $i0,$Tbl + $PTR_ADD $i1,$Tbl + $PTR_ADD $i2,$Tbl + $PTR_ADD $i3,$Tbl + lbu $t8,2($i0) # Te4[s0>>24] + _xtr $i0,$s3,0-2 + lbu $t9,2($i1) # Te4[s1>>24] + _xtr $i1,$s0,0-2 + lbu $t10,2($i2) # Te4[s2>>24] + _xtr $i2,$s1,0-2 + lbu $t11,2($i3) # Te4[s3>>24] + _xtr $i3,$s2,0-2 + + and $i0,0x3fc + and $i1,0x3fc + and $i2,0x3fc + and $i3,0x3fc + $PTR_ADD $i0,$Tbl + $PTR_ADD $i1,$Tbl + $PTR_ADD $i2,$Tbl + $PTR_ADD $i3,$Tbl + + _ins $t0,16 + _ins $t1,16 + _ins $t2,16 + _ins $t3,16 + + _ins $t4,8 + _ins $t5,8 + _ins $t6,8 + _ins $t7,8 + + xor $t0,$t4 + lbu $t4,2($i0) # Te4[s3] + xor $t1,$t5 + lbu $t5,2($i1) # Te4[s0] + xor $t2,$t6 + lbu $t6,2($i2) # Te4[s1] + xor $t3,$t7 + lbu $t7,2($i3) # Te4[s2] + + _ins $t8,24 + lw $s0,0($key0) + _ins $t9,24 + lw $s1,4($key0) + _ins $t10,24 + lw $s2,8($key0) + _ins $t11,24 + lw $s3,12($key0) + + xor $t0,$t8 + xor $t1,$t9 + xor $t2,$t10 + xor $t3,$t11 + + _ins $t4,0 + _ins $t5,0 + _ins $t6,0 + _ins $t7,0 + + xor $t0,$t4 + xor $t1,$t5 + xor $t2,$t6 + xor $t3,$t7 +#endif + xor $s0,$t0 + xor $s1,$t1 + xor $s2,$t2 + xor $s3,$t3 + + jr $ra +.end _mips_AES_encrypt + +.align 5 +.globl AES_encrypt +.ent AES_encrypt +AES_encrypt: + .frame $sp,$FRAMESIZE,$ra + .mask $SAVED_REGS_MASK,-$SZREG + .set noreorder +___ +$code.=<<___ if ($flavour =~ /o32/i); # o32 PIC-ification + .cpload $pf +___ +$code.=<<___; + $PTR_SUB $sp,$FRAMESIZE + $REG_S $ra,$FRAMESIZE-1*$SZREG($sp) + $REG_S $fp,$FRAMESIZE-2*$SZREG($sp) + $REG_S $s11,$FRAMESIZE-3*$SZREG($sp) + $REG_S $s10,$FRAMESIZE-4*$SZREG($sp) + $REG_S $s9,$FRAMESIZE-5*$SZREG($sp) + $REG_S $s8,$FRAMESIZE-6*$SZREG($sp) + $REG_S $s7,$FRAMESIZE-7*$SZREG($sp) + $REG_S $s6,$FRAMESIZE-8*$SZREG($sp) + $REG_S $s5,$FRAMESIZE-9*$SZREG($sp) + $REG_S $s4,$FRAMESIZE-10*$SZREG($sp) +___ +$code.=<<___ if ($flavour =~ /nubi/i); # optimize non-nubi prologue + $REG_S \$15,$FRAMESIZE-11*$SZREG($sp) + $REG_S \$14,$FRAMESIZE-12*$SZREG($sp) + $REG_S \$13,$FRAMESIZE-13*$SZREG($sp) + $REG_S \$12,$FRAMESIZE-14*$SZREG($sp) + $REG_S $gp,$FRAMESIZE-15*$SZREG($sp) +___ +$code.=<<___ if ($flavour !~ /o32/i); # non-o32 PIC-ification + .cplocal $Tbl + .cpsetup $pf,$zero,AES_encrypt +___ +$code.=<<___; + .set reorder + $PTR_LA $Tbl,AES_Te # PIC-ified 'load address' + +#if defined(_MIPS_ARCH_MIPS32R6) || defined(_MIPS_ARCH_MIPS64R6) + lw $s0,0($inp) + lw $s1,4($inp) + lw $s2,8($inp) + lw $s3,12($inp) +#else + lwl $s0,0+$MSB($inp) + lwl $s1,4+$MSB($inp) + lwl $s2,8+$MSB($inp) + lwl $s3,12+$MSB($inp) + lwr $s0,0+$LSB($inp) + lwr $s1,4+$LSB($inp) + lwr $s2,8+$LSB($inp) + lwr $s3,12+$LSB($inp) +#endif + + bal _mips_AES_encrypt + +#if defined(_MIPS_ARCH_MIPS32R6) || defined(_MIPS_ARCH_MIPS64R6) + sw $s0,0($out) + sw $s1,4($out) + sw $s2,8($out) + sw $s3,12($out) +#else + swr $s0,0+$LSB($out) + swr $s1,4+$LSB($out) + swr $s2,8+$LSB($out) + swr $s3,12+$LSB($out) + swl $s0,0+$MSB($out) + swl $s1,4+$MSB($out) + swl $s2,8+$MSB($out) + swl $s3,12+$MSB($out) +#endif + + .set noreorder + $REG_L $ra,$FRAMESIZE-1*$SZREG($sp) + $REG_L $fp,$FRAMESIZE-2*$SZREG($sp) + $REG_L $s11,$FRAMESIZE-3*$SZREG($sp) + $REG_L $s10,$FRAMESIZE-4*$SZREG($sp) + $REG_L $s9,$FRAMESIZE-5*$SZREG($sp) + $REG_L $s8,$FRAMESIZE-6*$SZREG($sp) + $REG_L $s7,$FRAMESIZE-7*$SZREG($sp) + $REG_L $s6,$FRAMESIZE-8*$SZREG($sp) + $REG_L $s5,$FRAMESIZE-9*$SZREG($sp) + $REG_L $s4,$FRAMESIZE-10*$SZREG($sp) +___ +$code.=<<___ if ($flavour =~ /nubi/i); + $REG_L \$15,$FRAMESIZE-11*$SZREG($sp) + $REG_L \$14,$FRAMESIZE-12*$SZREG($sp) + $REG_L \$13,$FRAMESIZE-13*$SZREG($sp) + $REG_L \$12,$FRAMESIZE-14*$SZREG($sp) + $REG_L $gp,$FRAMESIZE-15*$SZREG($sp) +___ +$code.=<<___; + jr $ra + $PTR_ADD $sp,$FRAMESIZE +.end AES_encrypt +___ + +$code.=<<___; +.align 5 +.ent _mips_AES_decrypt +_mips_AES_decrypt: + .frame $sp,0,$ra + .set reorder + lw $t0,0($key) + lw $t1,4($key) + lw $t2,8($key) + lw $t3,12($key) + lw $cnt,240($key) + $PTR_ADD $key0,$key,16 + + xor $s0,$t0 + xor $s1,$t1 + xor $s2,$t2 + xor $s3,$t3 + + subu $cnt,1 +#if defined(__mips_smartmips) + ext $i0,$s3,16,8 +.Loop_dec: + ext $i1,$s0,16,8 + ext $i2,$s1,16,8 + ext $i3,$s2,16,8 + lwxs $t0,$i0($Tbl) # Td1[s3>>16] + ext $i0,$s2,8,8 + lwxs $t1,$i1($Tbl) # Td1[s0>>16] + ext $i1,$s3,8,8 + lwxs $t2,$i2($Tbl) # Td1[s1>>16] + ext $i2,$s0,8,8 + lwxs $t3,$i3($Tbl) # Td1[s2>>16] + ext $i3,$s1,8,8 + + lwxs $t4,$i0($Tbl) # Td2[s2>>8] + ext $i0,$s1,0,8 + lwxs $t5,$i1($Tbl) # Td2[s3>>8] + ext $i1,$s2,0,8 + lwxs $t6,$i2($Tbl) # Td2[s0>>8] + ext $i2,$s3,0,8 + lwxs $t7,$i3($Tbl) # Td2[s1>>8] + ext $i3,$s0,0,8 + + lwxs $t8,$i0($Tbl) # Td3[s1] + ext $i0,$s0,24,8 + lwxs $t9,$i1($Tbl) # Td3[s2] + ext $i1,$s1,24,8 + lwxs $t10,$i2($Tbl) # Td3[s3] + ext $i2,$s2,24,8 + lwxs $t11,$i3($Tbl) # Td3[s0] + ext $i3,$s3,24,8 + + rotr $t0,$t0,8 + rotr $t1,$t1,8 + rotr $t2,$t2,8 + rotr $t3,$t3,8 + + rotr $t4,$t4,16 + rotr $t5,$t5,16 + rotr $t6,$t6,16 + rotr $t7,$t7,16 + + xor $t0,$t4 + lwxs $t4,$i0($Tbl) # Td0[s0>>24] + xor $t1,$t5 + lwxs $t5,$i1($Tbl) # Td0[s1>>24] + xor $t2,$t6 + lwxs $t6,$i2($Tbl) # Td0[s2>>24] + xor $t3,$t7 + lwxs $t7,$i3($Tbl) # Td0[s3>>24] + + rotr $t8,$t8,24 + lw $s0,0($key0) + rotr $t9,$t9,24 + lw $s1,4($key0) + rotr $t10,$t10,24 + lw $s2,8($key0) + rotr $t11,$t11,24 + lw $s3,12($key0) + + xor $t0,$t8 + xor $t1,$t9 + xor $t2,$t10 + xor $t3,$t11 + + xor $t0,$t4 + xor $t1,$t5 + xor $t2,$t6 + xor $t3,$t7 + + subu $cnt,1 + $PTR_ADD $key0,16 + xor $s0,$t0 + xor $s1,$t1 + xor $s2,$t2 + xor $s3,$t3 + .set noreorder + bnez $cnt,.Loop_dec + ext $i0,$s3,16,8 + + _xtr $i0,$s3,16-2 +#else + _xtr $i0,$s3,16-2 +.Loop_dec: + _xtr $i1,$s0,16-2 + _xtr $i2,$s1,16-2 + _xtr $i3,$s2,16-2 + and $i0,0x3fc + and $i1,0x3fc + and $i2,0x3fc + and $i3,0x3fc + $PTR_ADD $i0,$Tbl + $PTR_ADD $i1,$Tbl + $PTR_ADD $i2,$Tbl + $PTR_ADD $i3,$Tbl +#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2) + lw $t0,0($i0) # Td1[s3>>16] + _xtr $i0,$s2,8-2 + lw $t1,0($i1) # Td1[s0>>16] + _xtr $i1,$s3,8-2 + lw $t2,0($i2) # Td1[s1>>16] + _xtr $i2,$s0,8-2 + lw $t3,0($i3) # Td1[s2>>16] + _xtr $i3,$s1,8-2 +#else + lwl $t0,3($i0) # Td1[s3>>16] + lwl $t1,3($i1) # Td1[s0>>16] + lwl $t2,3($i2) # Td1[s1>>16] + lwl $t3,3($i3) # Td1[s2>>16] + lwr $t0,2($i0) # Td1[s3>>16] + _xtr $i0,$s2,8-2 + lwr $t1,2($i1) # Td1[s0>>16] + _xtr $i1,$s3,8-2 + lwr $t2,2($i2) # Td1[s1>>16] + _xtr $i2,$s0,8-2 + lwr $t3,2($i3) # Td1[s2>>16] + _xtr $i3,$s1,8-2 +#endif + + and $i0,0x3fc + and $i1,0x3fc + and $i2,0x3fc + and $i3,0x3fc + $PTR_ADD $i0,$Tbl + $PTR_ADD $i1,$Tbl + $PTR_ADD $i2,$Tbl + $PTR_ADD $i3,$Tbl +#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2) + rotr $t0,$t0,8 + rotr $t1,$t1,8 + rotr $t2,$t2,8 + rotr $t3,$t3,8 +# if defined(_MIPSEL) + lw $t4,0($i0) # Td2[s2>>8] + _xtr $i0,$s1,0-2 + lw $t5,0($i1) # Td2[s3>>8] + _xtr $i1,$s2,0-2 + lw $t6,0($i2) # Td2[s0>>8] + _xtr $i2,$s3,0-2 + lw $t7,0($i3) # Td2[s1>>8] + _xtr $i3,$s0,0-2 + + and $i0,0x3fc + and $i1,0x3fc + and $i2,0x3fc + and $i3,0x3fc + $PTR_ADD $i0,$Tbl + $PTR_ADD $i1,$Tbl + $PTR_ADD $i2,$Tbl + $PTR_ADD $i3,$Tbl + lw $t8,0($i0) # Td3[s1] + $PTR_INS $i0,$s0,2,8 + lw $t9,0($i1) # Td3[s2] + $PTR_INS $i1,$s1,2,8 + lw $t10,0($i2) # Td3[s3] + $PTR_INS $i2,$s2,2,8 + lw $t11,0($i3) # Td3[s0] + $PTR_INS $i3,$s3,2,8 +#else + lw $t4,0($i0) # Td2[s2>>8] + $PTR_INS $i0,$s1,2,8 + lw $t5,0($i1) # Td2[s3>>8] + $PTR_INS $i1,$s2,2,8 + lw $t6,0($i2) # Td2[s0>>8] + $PTR_INS $i2,$s3,2,8 + lw $t7,0($i3) # Td2[s1>>8] + $PTR_INS $i3,$s0,2,8 + + lw $t8,0($i0) # Td3[s1] + _xtr $i0,$s0,24-2 + lw $t9,0($i1) # Td3[s2] + _xtr $i1,$s1,24-2 + lw $t10,0($i2) # Td3[s3] + _xtr $i2,$s2,24-2 + lw $t11,0($i3) # Td3[s0] + _xtr $i3,$s3,24-2 + + and $i0,0x3fc + and $i1,0x3fc + and $i2,0x3fc + and $i3,0x3fc + $PTR_ADD $i0,$Tbl + $PTR_ADD $i1,$Tbl + $PTR_ADD $i2,$Tbl + $PTR_ADD $i3,$Tbl +#endif + rotr $t4,$t4,16 + rotr $t5,$t5,16 + rotr $t6,$t6,16 + rotr $t7,$t7,16 + + rotr $t8,$t8,24 + rotr $t9,$t9,24 + rotr $t10,$t10,24 + rotr $t11,$t11,24 +#else + lwl $t4,2($i0) # Td2[s2>>8] + lwl $t5,2($i1) # Td2[s3>>8] + lwl $t6,2($i2) # Td2[s0>>8] + lwl $t7,2($i3) # Td2[s1>>8] + lwr $t4,1($i0) # Td2[s2>>8] + _xtr $i0,$s1,0-2 + lwr $t5,1($i1) # Td2[s3>>8] + _xtr $i1,$s2,0-2 + lwr $t6,1($i2) # Td2[s0>>8] + _xtr $i2,$s3,0-2 + lwr $t7,1($i3) # Td2[s1>>8] + _xtr $i3,$s0,0-2 + + and $i0,0x3fc + and $i1,0x3fc + and $i2,0x3fc + and $i3,0x3fc + $PTR_ADD $i0,$Tbl + $PTR_ADD $i1,$Tbl + $PTR_ADD $i2,$Tbl + $PTR_ADD $i3,$Tbl + lwl $t8,1($i0) # Td3[s1] + lwl $t9,1($i1) # Td3[s2] + lwl $t10,1($i2) # Td3[s3] + lwl $t11,1($i3) # Td3[s0] + lwr $t8,0($i0) # Td3[s1] + _xtr $i0,$s0,24-2 + lwr $t9,0($i1) # Td3[s2] + _xtr $i1,$s1,24-2 + lwr $t10,0($i2) # Td3[s3] + _xtr $i2,$s2,24-2 + lwr $t11,0($i3) # Td3[s0] + _xtr $i3,$s3,24-2 + + and $i0,0x3fc + and $i1,0x3fc + and $i2,0x3fc + and $i3,0x3fc + $PTR_ADD $i0,$Tbl + $PTR_ADD $i1,$Tbl + $PTR_ADD $i2,$Tbl + $PTR_ADD $i3,$Tbl +#endif + + xor $t0,$t4 + lw $t4,0($i0) # Td0[s0>>24] + xor $t1,$t5 + lw $t5,0($i1) # Td0[s1>>24] + xor $t2,$t6 + lw $t6,0($i2) # Td0[s2>>24] + xor $t3,$t7 + lw $t7,0($i3) # Td0[s3>>24] + + xor $t0,$t8 + lw $s0,0($key0) + xor $t1,$t9 + lw $s1,4($key0) + xor $t2,$t10 + lw $s2,8($key0) + xor $t3,$t11 + lw $s3,12($key0) + + xor $t0,$t4 + xor $t1,$t5 + xor $t2,$t6 + xor $t3,$t7 + + subu $cnt,1 + $PTR_ADD $key0,16 + xor $s0,$t0 + xor $s1,$t1 + xor $s2,$t2 + xor $s3,$t3 + .set noreorder + bnez $cnt,.Loop_dec + _xtr $i0,$s3,16-2 +#endif + + .set reorder + lw $t4,1024($Tbl) # prefetch Td4 + _xtr $i0,$s3,16 + lw $t5,1024+32($Tbl) + _xtr $i1,$s0,16 + lw $t6,1024+64($Tbl) + _xtr $i2,$s1,16 + lw $t7,1024+96($Tbl) + _xtr $i3,$s2,16 + lw $t8,1024+128($Tbl) + and $i0,0xff + lw $t9,1024+160($Tbl) + and $i1,0xff + lw $t10,1024+192($Tbl) + and $i2,0xff + lw $t11,1024+224($Tbl) + and $i3,0xff + + $PTR_ADD $i0,$Tbl + $PTR_ADD $i1,$Tbl + $PTR_ADD $i2,$Tbl + $PTR_ADD $i3,$Tbl + lbu $t0,1024($i0) # Td4[s3>>16] + _xtr $i0,$s2,8 + lbu $t1,1024($i1) # Td4[s0>>16] + _xtr $i1,$s3,8 + lbu $t2,1024($i2) # Td4[s1>>16] + _xtr $i2,$s0,8 + lbu $t3,1024($i3) # Td4[s2>>16] + _xtr $i3,$s1,8 + + and $i0,0xff + and $i1,0xff + and $i2,0xff + and $i3,0xff + $PTR_ADD $i0,$Tbl + $PTR_ADD $i1,$Tbl + $PTR_ADD $i2,$Tbl + $PTR_ADD $i3,$Tbl +#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2) +# if defined(_MIPSEL) + lbu $t4,1024($i0) # Td4[s2>>8] + $PTR_INS $i0,$s0,0,8 + lbu $t5,1024($i1) # Td4[s3>>8] + $PTR_INS $i1,$s1,0,8 + lbu $t6,1024($i2) # Td4[s0>>8] + $PTR_INS $i2,$s2,0,8 + lbu $t7,1024($i3) # Td4[s1>>8] + $PTR_INS $i3,$s3,0,8 + + lbu $t8,1024($i0) # Td4[s0>>24] + _xtr $i0,$s1,0 + lbu $t9,1024($i1) # Td4[s1>>24] + _xtr $i1,$s2,0 + lbu $t10,1024($i2) # Td4[s2>>24] + _xtr $i2,$s3,0 + lbu $t11,1024($i3) # Td4[s3>>24] + _xtr $i3,$s0,0 + + $PTR_ADD $i0,$Tbl + $PTR_ADD $i1,$Tbl + $PTR_ADD $i2,$Tbl + $PTR_ADD $i3,$Tbl +# else + lbu $t4,1024($i0) # Td4[s2>>8] + _xtr $i0,$s0,24 + lbu $t5,1024($i1) # Td4[s3>>8] + _xtr $i1,$s1,24 + lbu $t6,1024($i2) # Td4[s0>>8] + _xtr $i2,$s2,24 + lbu $t7,1024($i3) # Td4[s1>>8] + _xtr $i3,$s3,24 + + $PTR_ADD $i0,$Tbl + $PTR_ADD $i1,$Tbl + $PTR_ADD $i2,$Tbl + $PTR_ADD $i3,$Tbl + lbu $t8,1024($i0) # Td4[s0>>24] + $PTR_INS $i0,$s1,0,8 + lbu $t9,1024($i1) # Td4[s1>>24] + $PTR_INS $i1,$s2,0,8 + lbu $t10,1024($i2) # Td4[s2>>24] + $PTR_INS $i2,$s3,0,8 + lbu $t11,1024($i3) # Td4[s3>>24] + $PTR_INS $i3,$s0,0,8 +# endif + _ins $t0,16 + _ins $t1,16 + _ins $t2,16 + _ins $t3,16 + + _ins2 $t0,$t4,8 + lbu $t4,1024($i0) # Td4[s1] + _ins2 $t1,$t5,8 + lbu $t5,1024($i1) # Td4[s2] + _ins2 $t2,$t6,8 + lbu $t6,1024($i2) # Td4[s3] + _ins2 $t3,$t7,8 + lbu $t7,1024($i3) # Td4[s0] + + _ins2 $t0,$t8,24 + lw $s0,0($key0) + _ins2 $t1,$t9,24 + lw $s1,4($key0) + _ins2 $t2,$t10,24 + lw $s2,8($key0) + _ins2 $t3,$t11,24 + lw $s3,12($key0) + + _ins2 $t0,$t4,0 + _ins2 $t1,$t5,0 + _ins2 $t2,$t6,0 + _ins2 $t3,$t7,0 +#else + lbu $t4,1024($i0) # Td4[s2>>8] + _xtr $i0,$s0,24 + lbu $t5,1024($i1) # Td4[s3>>8] + _xtr $i1,$s1,24 + lbu $t6,1024($i2) # Td4[s0>>8] + _xtr $i2,$s2,24 + lbu $t7,1024($i3) # Td4[s1>>8] + _xtr $i3,$s3,24 + + $PTR_ADD $i0,$Tbl + $PTR_ADD $i1,$Tbl + $PTR_ADD $i2,$Tbl + $PTR_ADD $i3,$Tbl + lbu $t8,1024($i0) # Td4[s0>>24] + _xtr $i0,$s1,0 + lbu $t9,1024($i1) # Td4[s1>>24] + _xtr $i1,$s2,0 + lbu $t10,1024($i2) # Td4[s2>>24] + _xtr $i2,$s3,0 + lbu $t11,1024($i3) # Td4[s3>>24] + _xtr $i3,$s0,0 + + $PTR_ADD $i0,$Tbl + $PTR_ADD $i1,$Tbl + $PTR_ADD $i2,$Tbl + $PTR_ADD $i3,$Tbl + + _ins $t0,16 + _ins $t1,16 + _ins $t2,16 + _ins $t3,16 + + _ins $t4,8 + _ins $t5,8 + _ins $t6,8 + _ins $t7,8 + + xor $t0,$t4 + lbu $t4,1024($i0) # Td4[s1] + xor $t1,$t5 + lbu $t5,1024($i1) # Td4[s2] + xor $t2,$t6 + lbu $t6,1024($i2) # Td4[s3] + xor $t3,$t7 + lbu $t7,1024($i3) # Td4[s0] + + _ins $t8,24 + lw $s0,0($key0) + _ins $t9,24 + lw $s1,4($key0) + _ins $t10,24 + lw $s2,8($key0) + _ins $t11,24 + lw $s3,12($key0) + + xor $t0,$t8 + xor $t1,$t9 + xor $t2,$t10 + xor $t3,$t11 + + _ins $t4,0 + _ins $t5,0 + _ins $t6,0 + _ins $t7,0 + + xor $t0,$t4 + xor $t1,$t5 + xor $t2,$t6 + xor $t3,$t7 +#endif + + xor $s0,$t0 + xor $s1,$t1 + xor $s2,$t2 + xor $s3,$t3 + + jr $ra +.end _mips_AES_decrypt + +.align 5 +.globl AES_decrypt +.ent AES_decrypt +AES_decrypt: + .frame $sp,$FRAMESIZE,$ra + .mask $SAVED_REGS_MASK,-$SZREG + .set noreorder +___ +$code.=<<___ if ($flavour =~ /o32/i); # o32 PIC-ification + .cpload $pf +___ +$code.=<<___; + $PTR_SUB $sp,$FRAMESIZE + $REG_S $ra,$FRAMESIZE-1*$SZREG($sp) + $REG_S $fp,$FRAMESIZE-2*$SZREG($sp) + $REG_S $s11,$FRAMESIZE-3*$SZREG($sp) + $REG_S $s10,$FRAMESIZE-4*$SZREG($sp) + $REG_S $s9,$FRAMESIZE-5*$SZREG($sp) + $REG_S $s8,$FRAMESIZE-6*$SZREG($sp) + $REG_S $s7,$FRAMESIZE-7*$SZREG($sp) + $REG_S $s6,$FRAMESIZE-8*$SZREG($sp) + $REG_S $s5,$FRAMESIZE-9*$SZREG($sp) + $REG_S $s4,$FRAMESIZE-10*$SZREG($sp) +___ +$code.=<<___ if ($flavour =~ /nubi/i); # optimize non-nubi prologue + $REG_S \$15,$FRAMESIZE-11*$SZREG($sp) + $REG_S \$14,$FRAMESIZE-12*$SZREG($sp) + $REG_S \$13,$FRAMESIZE-13*$SZREG($sp) + $REG_S \$12,$FRAMESIZE-14*$SZREG($sp) + $REG_S $gp,$FRAMESIZE-15*$SZREG($sp) +___ +$code.=<<___ if ($flavour !~ /o32/i); # non-o32 PIC-ification + .cplocal $Tbl + .cpsetup $pf,$zero,AES_decrypt +___ +$code.=<<___; + .set reorder + $PTR_LA $Tbl,AES_Td # PIC-ified 'load address' + +#if defined(_MIPS_ARCH_MIPS32R6) || defined(_MIPS_ARCH_MIPS64R6) + lw $s0,0($inp) + lw $s1,4($inp) + lw $s2,8($inp) + lw $s3,12($inp) +#else + lwl $s0,0+$MSB($inp) + lwl $s1,4+$MSB($inp) + lwl $s2,8+$MSB($inp) + lwl $s3,12+$MSB($inp) + lwr $s0,0+$LSB($inp) + lwr $s1,4+$LSB($inp) + lwr $s2,8+$LSB($inp) + lwr $s3,12+$LSB($inp) +#endif + + bal _mips_AES_decrypt + +#if defined(_MIPS_ARCH_MIPS32R6) || defined(_MIPS_ARCH_MIPS64R6) + sw $s0,0($out) + sw $s1,4($out) + sw $s2,8($out) + sw $s3,12($out) +#else + swr $s0,0+$LSB($out) + swr $s1,4+$LSB($out) + swr $s2,8+$LSB($out) + swr $s3,12+$LSB($out) + swl $s0,0+$MSB($out) + swl $s1,4+$MSB($out) + swl $s2,8+$MSB($out) + swl $s3,12+$MSB($out) +#endif + + .set noreorder + $REG_L $ra,$FRAMESIZE-1*$SZREG($sp) + $REG_L $fp,$FRAMESIZE-2*$SZREG($sp) + $REG_L $s11,$FRAMESIZE-3*$SZREG($sp) + $REG_L $s10,$FRAMESIZE-4*$SZREG($sp) + $REG_L $s9,$FRAMESIZE-5*$SZREG($sp) + $REG_L $s8,$FRAMESIZE-6*$SZREG($sp) + $REG_L $s7,$FRAMESIZE-7*$SZREG($sp) + $REG_L $s6,$FRAMESIZE-8*$SZREG($sp) + $REG_L $s5,$FRAMESIZE-9*$SZREG($sp) + $REG_L $s4,$FRAMESIZE-10*$SZREG($sp) +___ +$code.=<<___ if ($flavour =~ /nubi/i); + $REG_L \$15,$FRAMESIZE-11*$SZREG($sp) + $REG_L \$14,$FRAMESIZE-12*$SZREG($sp) + $REG_L \$13,$FRAMESIZE-13*$SZREG($sp) + $REG_L \$12,$FRAMESIZE-14*$SZREG($sp) + $REG_L $gp,$FRAMESIZE-15*$SZREG($sp) +___ +$code.=<<___; + jr $ra + $PTR_ADD $sp,$FRAMESIZE +.end AES_decrypt +___ +}}} + +{{{ +my $FRAMESIZE=8*$SZREG; +my $SAVED_REGS_MASK = ($flavour =~ /nubi/i) ? "0xc000f008" : "0xc0000000"; + +my ($inp,$bits,$key,$Tbl)=($a0,$a1,$a2,$a3); +my ($rk0,$rk1,$rk2,$rk3,$rk4,$rk5,$rk6,$rk7)=($a4,$a5,$a6,$a7,$s0,$s1,$s2,$s3); +my ($i0,$i1,$i2,$i3)=($at,$t0,$t1,$t2); +my ($rcon,$cnt)=($gp,$fp); + +$code.=<<___; +.align 5 +.ent _mips_AES_set_encrypt_key +_mips_AES_set_encrypt_key: + .frame $sp,0,$ra + .set noreorder + beqz $inp,.Lekey_done + li $t0,-1 + beqz $key,.Lekey_done + $PTR_ADD $rcon,$Tbl,256 + + .set reorder +#if defined(_MIPS_ARCH_MIPS32R6) || defined(_MIPS_ARCH_MIPS64R6) + lw $rk0,0($inp) # load 128 bits + lw $rk1,4($inp) + lw $rk2,8($inp) + lw $rk3,12($inp) +#else + lwl $rk0,0+$MSB($inp) # load 128 bits + lwl $rk1,4+$MSB($inp) + lwl $rk2,8+$MSB($inp) + lwl $rk3,12+$MSB($inp) + lwr $rk0,0+$LSB($inp) + lwr $rk1,4+$LSB($inp) + lwr $rk2,8+$LSB($inp) + lwr $rk3,12+$LSB($inp) +#endif + li $at,128 + .set noreorder + beq $bits,$at,.L128bits + li $cnt,10 + + .set reorder +#if defined(_MIPS_ARCH_MIPS32R6) || defined(_MIPS_ARCH_MIPS64R6) + lw $rk4,16($inp) # load 192 bits + lw $rk5,20($inp) +#else + lwl $rk4,16+$MSB($inp) # load 192 bits + lwl $rk5,20+$MSB($inp) + lwr $rk4,16+$LSB($inp) + lwr $rk5,20+$LSB($inp) +#endif + li $at,192 + .set noreorder + beq $bits,$at,.L192bits + li $cnt,8 + + .set reorder +#if defined(_MIPS_ARCH_MIPS32R6) || defined(_MIPS_ARCH_MIPS64R6) + lw $rk6,24($inp) # load 256 bits + lw $rk7,28($inp) +#else + lwl $rk6,24+$MSB($inp) # load 256 bits + lwl $rk7,28+$MSB($inp) + lwr $rk6,24+$LSB($inp) + lwr $rk7,28+$LSB($inp) +#endif + li $at,256 + .set noreorder + beq $bits,$at,.L256bits + li $cnt,7 + + b .Lekey_done + li $t0,-2 + +.align 4 +.L128bits: + .set reorder + srl $i0,$rk3,16 + srl $i1,$rk3,8 + and $i0,0xff + and $i1,0xff + and $i2,$rk3,0xff + srl $i3,$rk3,24 + $PTR_ADD $i0,$Tbl + $PTR_ADD $i1,$Tbl + $PTR_ADD $i2,$Tbl + $PTR_ADD $i3,$Tbl + lbu $i0,0($i0) + lbu $i1,0($i1) + lbu $i2,0($i2) + lbu $i3,0($i3) + + sw $rk0,0($key) + sw $rk1,4($key) + sw $rk2,8($key) + sw $rk3,12($key) + subu $cnt,1 + $PTR_ADD $key,16 + + _bias $i0,24 + _bias $i1,16 + _bias $i2,8 + _bias $i3,0 + + xor $rk0,$i0 + lw $i0,0($rcon) + xor $rk0,$i1 + xor $rk0,$i2 + xor $rk0,$i3 + xor $rk0,$i0 + + xor $rk1,$rk0 + xor $rk2,$rk1 + xor $rk3,$rk2 + + .set noreorder + bnez $cnt,.L128bits + $PTR_ADD $rcon,4 + + sw $rk0,0($key) + sw $rk1,4($key) + sw $rk2,8($key) + li $cnt,10 + sw $rk3,12($key) + li $t0,0 + sw $cnt,80($key) + b .Lekey_done + $PTR_SUB $key,10*16 + +.align 4 +.L192bits: + .set reorder + srl $i0,$rk5,16 + srl $i1,$rk5,8 + and $i0,0xff + and $i1,0xff + and $i2,$rk5,0xff + srl $i3,$rk5,24 + $PTR_ADD $i0,$Tbl + $PTR_ADD $i1,$Tbl + $PTR_ADD $i2,$Tbl + $PTR_ADD $i3,$Tbl + lbu $i0,0($i0) + lbu $i1,0($i1) + lbu $i2,0($i2) + lbu $i3,0($i3) + + sw $rk0,0($key) + sw $rk1,4($key) + sw $rk2,8($key) + sw $rk3,12($key) + sw $rk4,16($key) + sw $rk5,20($key) + subu $cnt,1 + $PTR_ADD $key,24 + + _bias $i0,24 + _bias $i1,16 + _bias $i2,8 + _bias $i3,0 + + xor $rk0,$i0 + lw $i0,0($rcon) + xor $rk0,$i1 + xor $rk0,$i2 + xor $rk0,$i3 + xor $rk0,$i0 + + xor $rk1,$rk0 + xor $rk2,$rk1 + xor $rk3,$rk2 + xor $rk4,$rk3 + xor $rk5,$rk4 + + .set noreorder + bnez $cnt,.L192bits + $PTR_ADD $rcon,4 + + sw $rk0,0($key) + sw $rk1,4($key) + sw $rk2,8($key) + li $cnt,12 + sw $rk3,12($key) + li $t0,0 + sw $cnt,48($key) + b .Lekey_done + $PTR_SUB $key,12*16 + +.align 4 +.L256bits: + .set reorder + srl $i0,$rk7,16 + srl $i1,$rk7,8 + and $i0,0xff + and $i1,0xff + and $i2,$rk7,0xff + srl $i3,$rk7,24 + $PTR_ADD $i0,$Tbl + $PTR_ADD $i1,$Tbl + $PTR_ADD $i2,$Tbl + $PTR_ADD $i3,$Tbl + lbu $i0,0($i0) + lbu $i1,0($i1) + lbu $i2,0($i2) + lbu $i3,0($i3) + + sw $rk0,0($key) + sw $rk1,4($key) + sw $rk2,8($key) + sw $rk3,12($key) + sw $rk4,16($key) + sw $rk5,20($key) + sw $rk6,24($key) + sw $rk7,28($key) + subu $cnt,1 + + _bias $i0,24 + _bias $i1,16 + _bias $i2,8 + _bias $i3,0 + + xor $rk0,$i0 + lw $i0,0($rcon) + xor $rk0,$i1 + xor $rk0,$i2 + xor $rk0,$i3 + xor $rk0,$i0 + + xor $rk1,$rk0 + xor $rk2,$rk1 + xor $rk3,$rk2 + beqz $cnt,.L256bits_done + + srl $i0,$rk3,24 + srl $i1,$rk3,16 + srl $i2,$rk3,8 + and $i3,$rk3,0xff + and $i1,0xff + and $i2,0xff + $PTR_ADD $i0,$Tbl + $PTR_ADD $i1,$Tbl + $PTR_ADD $i2,$Tbl + $PTR_ADD $i3,$Tbl + lbu $i0,0($i0) + lbu $i1,0($i1) + lbu $i2,0($i2) + lbu $i3,0($i3) + sll $i0,24 + sll $i1,16 + sll $i2,8 + + xor $rk4,$i0 + xor $rk4,$i1 + xor $rk4,$i2 + xor $rk4,$i3 + + xor $rk5,$rk4 + xor $rk6,$rk5 + xor $rk7,$rk6 + + $PTR_ADD $key,32 + .set noreorder + b .L256bits + $PTR_ADD $rcon,4 + +.L256bits_done: + sw $rk0,32($key) + sw $rk1,36($key) + sw $rk2,40($key) + li $cnt,14 + sw $rk3,44($key) + li $t0,0 + sw $cnt,48($key) + $PTR_SUB $key,12*16 + +.Lekey_done: + jr $ra + nop +.end _mips_AES_set_encrypt_key + +.globl AES_set_encrypt_key +.ent AES_set_encrypt_key +AES_set_encrypt_key: + .frame $sp,$FRAMESIZE,$ra + .mask $SAVED_REGS_MASK,-$SZREG + .set noreorder +___ +$code.=<<___ if ($flavour =~ /o32/i); # o32 PIC-ification + .cpload $pf +___ +$code.=<<___; + $PTR_SUB $sp,$FRAMESIZE + $REG_S $ra,$FRAMESIZE-1*$SZREG($sp) + $REG_S $fp,$FRAMESIZE-2*$SZREG($sp) +___ +$code.=<<___ if ($flavour =~ /nubi/i); # optimize non-nubi prologue + $REG_S $s3,$FRAMESIZE-3*$SZREG($sp) + $REG_S $s2,$FRAMESIZE-4*$SZREG($sp) + $REG_S $s1,$FRAMESIZE-5*$SZREG($sp) + $REG_S $s0,$FRAMESIZE-6*$SZREG($sp) + $REG_S $gp,$FRAMESIZE-7*$SZREG($sp) +___ +$code.=<<___ if ($flavour !~ /o32/i); # non-o32 PIC-ification + .cplocal $Tbl + .cpsetup $pf,$zero,AES_set_encrypt_key +___ +$code.=<<___; + .set reorder + $PTR_LA $Tbl,AES_Te4 # PIC-ified 'load address' + + bal _mips_AES_set_encrypt_key + + .set noreorder + move $a0,$t0 + $REG_L $ra,$FRAMESIZE-1*$SZREG($sp) + $REG_L $fp,$FRAMESIZE-2*$SZREG($sp) +___ +$code.=<<___ if ($flavour =~ /nubi/i); + $REG_L $s3,$FRAMESIZE-11*$SZREG($sp) + $REG_L $s2,$FRAMESIZE-12*$SZREG($sp) + $REG_L $s1,$FRAMESIZE-13*$SZREG($sp) + $REG_L $s0,$FRAMESIZE-14*$SZREG($sp) + $REG_L $gp,$FRAMESIZE-15*$SZREG($sp) +___ +$code.=<<___; + jr $ra + $PTR_ADD $sp,$FRAMESIZE +.end AES_set_encrypt_key +___ + +my ($head,$tail)=($inp,$bits); +my ($tp1,$tp2,$tp4,$tp8,$tp9,$tpb,$tpd,$tpe)=($a4,$a5,$a6,$a7,$s0,$s1,$s2,$s3); +my ($m,$x80808080,$x7f7f7f7f,$x1b1b1b1b)=($at,$t0,$t1,$t2); +$code.=<<___; +.align 5 +.globl AES_set_decrypt_key +.ent AES_set_decrypt_key +AES_set_decrypt_key: + .frame $sp,$FRAMESIZE,$ra + .mask $SAVED_REGS_MASK,-$SZREG + .set noreorder +___ +$code.=<<___ if ($flavour =~ /o32/i); # o32 PIC-ification + .cpload $pf +___ +$code.=<<___; + $PTR_SUB $sp,$FRAMESIZE + $REG_S $ra,$FRAMESIZE-1*$SZREG($sp) + $REG_S $fp,$FRAMESIZE-2*$SZREG($sp) +___ +$code.=<<___ if ($flavour =~ /nubi/i); # optimize non-nubi prologue + $REG_S $s3,$FRAMESIZE-3*$SZREG($sp) + $REG_S $s2,$FRAMESIZE-4*$SZREG($sp) + $REG_S $s1,$FRAMESIZE-5*$SZREG($sp) + $REG_S $s0,$FRAMESIZE-6*$SZREG($sp) + $REG_S $gp,$FRAMESIZE-7*$SZREG($sp) +___ +$code.=<<___ if ($flavour !~ /o32/i); # non-o32 PIC-ification + .cplocal $Tbl + .cpsetup $pf,$zero,AES_set_decrypt_key +___ +$code.=<<___; + .set reorder + $PTR_LA $Tbl,AES_Te4 # PIC-ified 'load address' + + bal _mips_AES_set_encrypt_key + + bltz $t0,.Ldkey_done + + sll $at,$cnt,4 + $PTR_ADD $head,$key,0 + $PTR_ADD $tail,$key,$at +.align 4 +.Lswap: + lw $rk0,0($head) + lw $rk1,4($head) + lw $rk2,8($head) + lw $rk3,12($head) + lw $rk4,0($tail) + lw $rk5,4($tail) + lw $rk6,8($tail) + lw $rk7,12($tail) + sw $rk0,0($tail) + sw $rk1,4($tail) + sw $rk2,8($tail) + sw $rk3,12($tail) + $PTR_ADD $head,16 + $PTR_SUB $tail,16 + sw $rk4,-16($head) + sw $rk5,-12($head) + sw $rk6,-8($head) + sw $rk7,-4($head) + bne $head,$tail,.Lswap + + lw $tp1,16($key) # modulo-scheduled + lui $x80808080,0x8080 + subu $cnt,1 + or $x80808080,0x8080 + sll $cnt,2 + $PTR_ADD $key,16 + lui $x1b1b1b1b,0x1b1b + nor $x7f7f7f7f,$zero,$x80808080 + or $x1b1b1b1b,0x1b1b +.align 4 +.Lmix: + and $m,$tp1,$x80808080 + and $tp2,$tp1,$x7f7f7f7f + srl $tp4,$m,7 + addu $tp2,$tp2 # tp2<<1 + subu $m,$tp4 + and $m,$x1b1b1b1b + xor $tp2,$m + + and $m,$tp2,$x80808080 + and $tp4,$tp2,$x7f7f7f7f + srl $tp8,$m,7 + addu $tp4,$tp4 # tp4<<1 + subu $m,$tp8 + and $m,$x1b1b1b1b + xor $tp4,$m + + and $m,$tp4,$x80808080 + and $tp8,$tp4,$x7f7f7f7f + srl $tp9,$m,7 + addu $tp8,$tp8 # tp8<<1 + subu $m,$tp9 + and $m,$x1b1b1b1b + xor $tp8,$m + + xor $tp9,$tp8,$tp1 + xor $tpe,$tp8,$tp4 + xor $tpb,$tp9,$tp2 + xor $tpd,$tp9,$tp4 + +#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2) + rotr $tp1,$tpd,16 + xor $tpe,$tp2 + rotr $tp2,$tp9,8 + xor $tpe,$tp1 + rotr $tp4,$tpb,24 + xor $tpe,$tp2 + lw $tp1,4($key) # modulo-scheduled + xor $tpe,$tp4 +#else + _ror $tp1,$tpd,16 + xor $tpe,$tp2 + _ror $tp2,$tpd,-16 + xor $tpe,$tp1 + _ror $tp1,$tp9,8 + xor $tpe,$tp2 + _ror $tp2,$tp9,-24 + xor $tpe,$tp1 + _ror $tp1,$tpb,24 + xor $tpe,$tp2 + _ror $tp2,$tpb,-8 + xor $tpe,$tp1 + lw $tp1,4($key) # modulo-scheduled + xor $tpe,$tp2 +#endif + subu $cnt,1 + sw $tpe,0($key) + $PTR_ADD $key,4 + bnez $cnt,.Lmix + + li $t0,0 +.Ldkey_done: + .set noreorder + move $a0,$t0 + $REG_L $ra,$FRAMESIZE-1*$SZREG($sp) + $REG_L $fp,$FRAMESIZE-2*$SZREG($sp) +___ +$code.=<<___ if ($flavour =~ /nubi/i); + $REG_L $s3,$FRAMESIZE-11*$SZREG($sp) + $REG_L $s2,$FRAMESIZE-12*$SZREG($sp) + $REG_L $s1,$FRAMESIZE-13*$SZREG($sp) + $REG_L $s0,$FRAMESIZE-14*$SZREG($sp) + $REG_L $gp,$FRAMESIZE-15*$SZREG($sp) +___ +$code.=<<___; + jr $ra + $PTR_ADD $sp,$FRAMESIZE +.end AES_set_decrypt_key +___ +}}} + +###################################################################### +# Tables are kept in endian-neutral manner +$code.=<<___; +.rdata +.align 10 +AES_Te: +.byte 0xc6,0x63,0x63,0xa5, 0xf8,0x7c,0x7c,0x84 # Te0 +.byte 0xee,0x77,0x77,0x99, 0xf6,0x7b,0x7b,0x8d +.byte 0xff,0xf2,0xf2,0x0d, 0xd6,0x6b,0x6b,0xbd +.byte 0xde,0x6f,0x6f,0xb1, 0x91,0xc5,0xc5,0x54 +.byte 0x60,0x30,0x30,0x50, 0x02,0x01,0x01,0x03 +.byte 0xce,0x67,0x67,0xa9, 0x56,0x2b,0x2b,0x7d +.byte 0xe7,0xfe,0xfe,0x19, 0xb5,0xd7,0xd7,0x62 +.byte 0x4d,0xab,0xab,0xe6, 0xec,0x76,0x76,0x9a +.byte 0x8f,0xca,0xca,0x45, 0x1f,0x82,0x82,0x9d +.byte 0x89,0xc9,0xc9,0x40, 0xfa,0x7d,0x7d,0x87 +.byte 0xef,0xfa,0xfa,0x15, 0xb2,0x59,0x59,0xeb +.byte 0x8e,0x47,0x47,0xc9, 0xfb,0xf0,0xf0,0x0b +.byte 0x41,0xad,0xad,0xec, 0xb3,0xd4,0xd4,0x67 +.byte 0x5f,0xa2,0xa2,0xfd, 0x45,0xaf,0xaf,0xea +.byte 0x23,0x9c,0x9c,0xbf, 0x53,0xa4,0xa4,0xf7 +.byte 0xe4,0x72,0x72,0x96, 0x9b,0xc0,0xc0,0x5b +.byte 0x75,0xb7,0xb7,0xc2, 0xe1,0xfd,0xfd,0x1c +.byte 0x3d,0x93,0x93,0xae, 0x4c,0x26,0x26,0x6a +.byte 0x6c,0x36,0x36,0x5a, 0x7e,0x3f,0x3f,0x41 +.byte 0xf5,0xf7,0xf7,0x02, 0x83,0xcc,0xcc,0x4f +.byte 0x68,0x34,0x34,0x5c, 0x51,0xa5,0xa5,0xf4 +.byte 0xd1,0xe5,0xe5,0x34, 0xf9,0xf1,0xf1,0x08 +.byte 0xe2,0x71,0x71,0x93, 0xab,0xd8,0xd8,0x73 +.byte 0x62,0x31,0x31,0x53, 0x2a,0x15,0x15,0x3f +.byte 0x08,0x04,0x04,0x0c, 0x95,0xc7,0xc7,0x52 +.byte 0x46,0x23,0x23,0x65, 0x9d,0xc3,0xc3,0x5e +.byte 0x30,0x18,0x18,0x28, 0x37,0x96,0x96,0xa1 +.byte 0x0a,0x05,0x05,0x0f, 0x2f,0x9a,0x9a,0xb5 +.byte 0x0e,0x07,0x07,0x09, 0x24,0x12,0x12,0x36 +.byte 0x1b,0x80,0x80,0x9b, 0xdf,0xe2,0xe2,0x3d +.byte 0xcd,0xeb,0xeb,0x26, 0x4e,0x27,0x27,0x69 +.byte 0x7f,0xb2,0xb2,0xcd, 0xea,0x75,0x75,0x9f +.byte 0x12,0x09,0x09,0x1b, 0x1d,0x83,0x83,0x9e +.byte 0x58,0x2c,0x2c,0x74, 0x34,0x1a,0x1a,0x2e +.byte 0x36,0x1b,0x1b,0x2d, 0xdc,0x6e,0x6e,0xb2 +.byte 0xb4,0x5a,0x5a,0xee, 0x5b,0xa0,0xa0,0xfb +.byte 0xa4,0x52,0x52,0xf6, 0x76,0x3b,0x3b,0x4d +.byte 0xb7,0xd6,0xd6,0x61, 0x7d,0xb3,0xb3,0xce +.byte 0x52,0x29,0x29,0x7b, 0xdd,0xe3,0xe3,0x3e +.byte 0x5e,0x2f,0x2f,0x71, 0x13,0x84,0x84,0x97 +.byte 0xa6,0x53,0x53,0xf5, 0xb9,0xd1,0xd1,0x68 +.byte 0x00,0x00,0x00,0x00, 0xc1,0xed,0xed,0x2c +.byte 0x40,0x20,0x20,0x60, 0xe3,0xfc,0xfc,0x1f +.byte 0x79,0xb1,0xb1,0xc8, 0xb6,0x5b,0x5b,0xed +.byte 0xd4,0x6a,0x6a,0xbe, 0x8d,0xcb,0xcb,0x46 +.byte 0x67,0xbe,0xbe,0xd9, 0x72,0x39,0x39,0x4b +.byte 0x94,0x4a,0x4a,0xde, 0x98,0x4c,0x4c,0xd4 +.byte 0xb0,0x58,0x58,0xe8, 0x85,0xcf,0xcf,0x4a +.byte 0xbb,0xd0,0xd0,0x6b, 0xc5,0xef,0xef,0x2a +.byte 0x4f,0xaa,0xaa,0xe5, 0xed,0xfb,0xfb,0x16 +.byte 0x86,0x43,0x43,0xc5, 0x9a,0x4d,0x4d,0xd7 +.byte 0x66,0x33,0x33,0x55, 0x11,0x85,0x85,0x94 +.byte 0x8a,0x45,0x45,0xcf, 0xe9,0xf9,0xf9,0x10 +.byte 0x04,0x02,0x02,0x06, 0xfe,0x7f,0x7f,0x81 +.byte 0xa0,0x50,0x50,0xf0, 0x78,0x3c,0x3c,0x44 +.byte 0x25,0x9f,0x9f,0xba, 0x4b,0xa8,0xa8,0xe3 +.byte 0xa2,0x51,0x51,0xf3, 0x5d,0xa3,0xa3,0xfe +.byte 0x80,0x40,0x40,0xc0, 0x05,0x8f,0x8f,0x8a +.byte 0x3f,0x92,0x92,0xad, 0x21,0x9d,0x9d,0xbc +.byte 0x70,0x38,0x38,0x48, 0xf1,0xf5,0xf5,0x04 +.byte 0x63,0xbc,0xbc,0xdf, 0x77,0xb6,0xb6,0xc1 +.byte 0xaf,0xda,0xda,0x75, 0x42,0x21,0x21,0x63 +.byte 0x20,0x10,0x10,0x30, 0xe5,0xff,0xff,0x1a +.byte 0xfd,0xf3,0xf3,0x0e, 0xbf,0xd2,0xd2,0x6d +.byte 0x81,0xcd,0xcd,0x4c, 0x18,0x0c,0x0c,0x14 +.byte 0x26,0x13,0x13,0x35, 0xc3,0xec,0xec,0x2f +.byte 0xbe,0x5f,0x5f,0xe1, 0x35,0x97,0x97,0xa2 +.byte 0x88,0x44,0x44,0xcc, 0x2e,0x17,0x17,0x39 +.byte 0x93,0xc4,0xc4,0x57, 0x55,0xa7,0xa7,0xf2 +.byte 0xfc,0x7e,0x7e,0x82, 0x7a,0x3d,0x3d,0x47 +.byte 0xc8,0x64,0x64,0xac, 0xba,0x5d,0x5d,0xe7 +.byte 0x32,0x19,0x19,0x2b, 0xe6,0x73,0x73,0x95 +.byte 0xc0,0x60,0x60,0xa0, 0x19,0x81,0x81,0x98 +.byte 0x9e,0x4f,0x4f,0xd1, 0xa3,0xdc,0xdc,0x7f +.byte 0x44,0x22,0x22,0x66, 0x54,0x2a,0x2a,0x7e +.byte 0x3b,0x90,0x90,0xab, 0x0b,0x88,0x88,0x83 +.byte 0x8c,0x46,0x46,0xca, 0xc7,0xee,0xee,0x29 +.byte 0x6b,0xb8,0xb8,0xd3, 0x28,0x14,0x14,0x3c +.byte 0xa7,0xde,0xde,0x79, 0xbc,0x5e,0x5e,0xe2 +.byte 0x16,0x0b,0x0b,0x1d, 0xad,0xdb,0xdb,0x76 +.byte 0xdb,0xe0,0xe0,0x3b, 0x64,0x32,0x32,0x56 +.byte 0x74,0x3a,0x3a,0x4e, 0x14,0x0a,0x0a,0x1e +.byte 0x92,0x49,0x49,0xdb, 0x0c,0x06,0x06,0x0a +.byte 0x48,0x24,0x24,0x6c, 0xb8,0x5c,0x5c,0xe4 +.byte 0x9f,0xc2,0xc2,0x5d, 0xbd,0xd3,0xd3,0x6e +.byte 0x43,0xac,0xac,0xef, 0xc4,0x62,0x62,0xa6 +.byte 0x39,0x91,0x91,0xa8, 0x31,0x95,0x95,0xa4 +.byte 0xd3,0xe4,0xe4,0x37, 0xf2,0x79,0x79,0x8b +.byte 0xd5,0xe7,0xe7,0x32, 0x8b,0xc8,0xc8,0x43 +.byte 0x6e,0x37,0x37,0x59, 0xda,0x6d,0x6d,0xb7 +.byte 0x01,0x8d,0x8d,0x8c, 0xb1,0xd5,0xd5,0x64 +.byte 0x9c,0x4e,0x4e,0xd2, 0x49,0xa9,0xa9,0xe0 +.byte 0xd8,0x6c,0x6c,0xb4, 0xac,0x56,0x56,0xfa +.byte 0xf3,0xf4,0xf4,0x07, 0xcf,0xea,0xea,0x25 +.byte 0xca,0x65,0x65,0xaf, 0xf4,0x7a,0x7a,0x8e +.byte 0x47,0xae,0xae,0xe9, 0x10,0x08,0x08,0x18 +.byte 0x6f,0xba,0xba,0xd5, 0xf0,0x78,0x78,0x88 +.byte 0x4a,0x25,0x25,0x6f, 0x5c,0x2e,0x2e,0x72 +.byte 0x38,0x1c,0x1c,0x24, 0x57,0xa6,0xa6,0xf1 +.byte 0x73,0xb4,0xb4,0xc7, 0x97,0xc6,0xc6,0x51 +.byte 0xcb,0xe8,0xe8,0x23, 0xa1,0xdd,0xdd,0x7c +.byte 0xe8,0x74,0x74,0x9c, 0x3e,0x1f,0x1f,0x21 +.byte 0x96,0x4b,0x4b,0xdd, 0x61,0xbd,0xbd,0xdc +.byte 0x0d,0x8b,0x8b,0x86, 0x0f,0x8a,0x8a,0x85 +.byte 0xe0,0x70,0x70,0x90, 0x7c,0x3e,0x3e,0x42 +.byte 0x71,0xb5,0xb5,0xc4, 0xcc,0x66,0x66,0xaa +.byte 0x90,0x48,0x48,0xd8, 0x06,0x03,0x03,0x05 +.byte 0xf7,0xf6,0xf6,0x01, 0x1c,0x0e,0x0e,0x12 +.byte 0xc2,0x61,0x61,0xa3, 0x6a,0x35,0x35,0x5f +.byte 0xae,0x57,0x57,0xf9, 0x69,0xb9,0xb9,0xd0 +.byte 0x17,0x86,0x86,0x91, 0x99,0xc1,0xc1,0x58 +.byte 0x3a,0x1d,0x1d,0x27, 0x27,0x9e,0x9e,0xb9 +.byte 0xd9,0xe1,0xe1,0x38, 0xeb,0xf8,0xf8,0x13 +.byte 0x2b,0x98,0x98,0xb3, 0x22,0x11,0x11,0x33 +.byte 0xd2,0x69,0x69,0xbb, 0xa9,0xd9,0xd9,0x70 +.byte 0x07,0x8e,0x8e,0x89, 0x33,0x94,0x94,0xa7 +.byte 0x2d,0x9b,0x9b,0xb6, 0x3c,0x1e,0x1e,0x22 +.byte 0x15,0x87,0x87,0x92, 0xc9,0xe9,0xe9,0x20 +.byte 0x87,0xce,0xce,0x49, 0xaa,0x55,0x55,0xff +.byte 0x50,0x28,0x28,0x78, 0xa5,0xdf,0xdf,0x7a +.byte 0x03,0x8c,0x8c,0x8f, 0x59,0xa1,0xa1,0xf8 +.byte 0x09,0x89,0x89,0x80, 0x1a,0x0d,0x0d,0x17 +.byte 0x65,0xbf,0xbf,0xda, 0xd7,0xe6,0xe6,0x31 +.byte 0x84,0x42,0x42,0xc6, 0xd0,0x68,0x68,0xb8 +.byte 0x82,0x41,0x41,0xc3, 0x29,0x99,0x99,0xb0 +.byte 0x5a,0x2d,0x2d,0x77, 0x1e,0x0f,0x0f,0x11 +.byte 0x7b,0xb0,0xb0,0xcb, 0xa8,0x54,0x54,0xfc +.byte 0x6d,0xbb,0xbb,0xd6, 0x2c,0x16,0x16,0x3a + +AES_Td: +.byte 0x51,0xf4,0xa7,0x50, 0x7e,0x41,0x65,0x53 # Td0 +.byte 0x1a,0x17,0xa4,0xc3, 0x3a,0x27,0x5e,0x96 +.byte 0x3b,0xab,0x6b,0xcb, 0x1f,0x9d,0x45,0xf1 +.byte 0xac,0xfa,0x58,0xab, 0x4b,0xe3,0x03,0x93 +.byte 0x20,0x30,0xfa,0x55, 0xad,0x76,0x6d,0xf6 +.byte 0x88,0xcc,0x76,0x91, 0xf5,0x02,0x4c,0x25 +.byte 0x4f,0xe5,0xd7,0xfc, 0xc5,0x2a,0xcb,0xd7 +.byte 0x26,0x35,0x44,0x80, 0xb5,0x62,0xa3,0x8f +.byte 0xde,0xb1,0x5a,0x49, 0x25,0xba,0x1b,0x67 +.byte 0x45,0xea,0x0e,0x98, 0x5d,0xfe,0xc0,0xe1 +.byte 0xc3,0x2f,0x75,0x02, 0x81,0x4c,0xf0,0x12 +.byte 0x8d,0x46,0x97,0xa3, 0x6b,0xd3,0xf9,0xc6 +.byte 0x03,0x8f,0x5f,0xe7, 0x15,0x92,0x9c,0x95 +.byte 0xbf,0x6d,0x7a,0xeb, 0x95,0x52,0x59,0xda +.byte 0xd4,0xbe,0x83,0x2d, 0x58,0x74,0x21,0xd3 +.byte 0x49,0xe0,0x69,0x29, 0x8e,0xc9,0xc8,0x44 +.byte 0x75,0xc2,0x89,0x6a, 0xf4,0x8e,0x79,0x78 +.byte 0x99,0x58,0x3e,0x6b, 0x27,0xb9,0x71,0xdd +.byte 0xbe,0xe1,0x4f,0xb6, 0xf0,0x88,0xad,0x17 +.byte 0xc9,0x20,0xac,0x66, 0x7d,0xce,0x3a,0xb4 +.byte 0x63,0xdf,0x4a,0x18, 0xe5,0x1a,0x31,0x82 +.byte 0x97,0x51,0x33,0x60, 0x62,0x53,0x7f,0x45 +.byte 0xb1,0x64,0x77,0xe0, 0xbb,0x6b,0xae,0x84 +.byte 0xfe,0x81,0xa0,0x1c, 0xf9,0x08,0x2b,0x94 +.byte 0x70,0x48,0x68,0x58, 0x8f,0x45,0xfd,0x19 +.byte 0x94,0xde,0x6c,0x87, 0x52,0x7b,0xf8,0xb7 +.byte 0xab,0x73,0xd3,0x23, 0x72,0x4b,0x02,0xe2 +.byte 0xe3,0x1f,0x8f,0x57, 0x66,0x55,0xab,0x2a +.byte 0xb2,0xeb,0x28,0x07, 0x2f,0xb5,0xc2,0x03 +.byte 0x86,0xc5,0x7b,0x9a, 0xd3,0x37,0x08,0xa5 +.byte 0x30,0x28,0x87,0xf2, 0x23,0xbf,0xa5,0xb2 +.byte 0x02,0x03,0x6a,0xba, 0xed,0x16,0x82,0x5c +.byte 0x8a,0xcf,0x1c,0x2b, 0xa7,0x79,0xb4,0x92 +.byte 0xf3,0x07,0xf2,0xf0, 0x4e,0x69,0xe2,0xa1 +.byte 0x65,0xda,0xf4,0xcd, 0x06,0x05,0xbe,0xd5 +.byte 0xd1,0x34,0x62,0x1f, 0xc4,0xa6,0xfe,0x8a +.byte 0x34,0x2e,0x53,0x9d, 0xa2,0xf3,0x55,0xa0 +.byte 0x05,0x8a,0xe1,0x32, 0xa4,0xf6,0xeb,0x75 +.byte 0x0b,0x83,0xec,0x39, 0x40,0x60,0xef,0xaa +.byte 0x5e,0x71,0x9f,0x06, 0xbd,0x6e,0x10,0x51 +.byte 0x3e,0x21,0x8a,0xf9, 0x96,0xdd,0x06,0x3d +.byte 0xdd,0x3e,0x05,0xae, 0x4d,0xe6,0xbd,0x46 +.byte 0x91,0x54,0x8d,0xb5, 0x71,0xc4,0x5d,0x05 +.byte 0x04,0x06,0xd4,0x6f, 0x60,0x50,0x15,0xff +.byte 0x19,0x98,0xfb,0x24, 0xd6,0xbd,0xe9,0x97 +.byte 0x89,0x40,0x43,0xcc, 0x67,0xd9,0x9e,0x77 +.byte 0xb0,0xe8,0x42,0xbd, 0x07,0x89,0x8b,0x88 +.byte 0xe7,0x19,0x5b,0x38, 0x79,0xc8,0xee,0xdb +.byte 0xa1,0x7c,0x0a,0x47, 0x7c,0x42,0x0f,0xe9 +.byte 0xf8,0x84,0x1e,0xc9, 0x00,0x00,0x00,0x00 +.byte 0x09,0x80,0x86,0x83, 0x32,0x2b,0xed,0x48 +.byte 0x1e,0x11,0x70,0xac, 0x6c,0x5a,0x72,0x4e +.byte 0xfd,0x0e,0xff,0xfb, 0x0f,0x85,0x38,0x56 +.byte 0x3d,0xae,0xd5,0x1e, 0x36,0x2d,0x39,0x27 +.byte 0x0a,0x0f,0xd9,0x64, 0x68,0x5c,0xa6,0x21 +.byte 0x9b,0x5b,0x54,0xd1, 0x24,0x36,0x2e,0x3a +.byte 0x0c,0x0a,0x67,0xb1, 0x93,0x57,0xe7,0x0f +.byte 0xb4,0xee,0x96,0xd2, 0x1b,0x9b,0x91,0x9e +.byte 0x80,0xc0,0xc5,0x4f, 0x61,0xdc,0x20,0xa2 +.byte 0x5a,0x77,0x4b,0x69, 0x1c,0x12,0x1a,0x16 +.byte 0xe2,0x93,0xba,0x0a, 0xc0,0xa0,0x2a,0xe5 +.byte 0x3c,0x22,0xe0,0x43, 0x12,0x1b,0x17,0x1d +.byte 0x0e,0x09,0x0d,0x0b, 0xf2,0x8b,0xc7,0xad +.byte 0x2d,0xb6,0xa8,0xb9, 0x14,0x1e,0xa9,0xc8 +.byte 0x57,0xf1,0x19,0x85, 0xaf,0x75,0x07,0x4c +.byte 0xee,0x99,0xdd,0xbb, 0xa3,0x7f,0x60,0xfd +.byte 0xf7,0x01,0x26,0x9f, 0x5c,0x72,0xf5,0xbc +.byte 0x44,0x66,0x3b,0xc5, 0x5b,0xfb,0x7e,0x34 +.byte 0x8b,0x43,0x29,0x76, 0xcb,0x23,0xc6,0xdc +.byte 0xb6,0xed,0xfc,0x68, 0xb8,0xe4,0xf1,0x63 +.byte 0xd7,0x31,0xdc,0xca, 0x42,0x63,0x85,0x10 +.byte 0x13,0x97,0x22,0x40, 0x84,0xc6,0x11,0x20 +.byte 0x85,0x4a,0x24,0x7d, 0xd2,0xbb,0x3d,0xf8 +.byte 0xae,0xf9,0x32,0x11, 0xc7,0x29,0xa1,0x6d +.byte 0x1d,0x9e,0x2f,0x4b, 0xdc,0xb2,0x30,0xf3 +.byte 0x0d,0x86,0x52,0xec, 0x77,0xc1,0xe3,0xd0 +.byte 0x2b,0xb3,0x16,0x6c, 0xa9,0x70,0xb9,0x99 +.byte 0x11,0x94,0x48,0xfa, 0x47,0xe9,0x64,0x22 +.byte 0xa8,0xfc,0x8c,0xc4, 0xa0,0xf0,0x3f,0x1a +.byte 0x56,0x7d,0x2c,0xd8, 0x22,0x33,0x90,0xef +.byte 0x87,0x49,0x4e,0xc7, 0xd9,0x38,0xd1,0xc1 +.byte 0x8c,0xca,0xa2,0xfe, 0x98,0xd4,0x0b,0x36 +.byte 0xa6,0xf5,0x81,0xcf, 0xa5,0x7a,0xde,0x28 +.byte 0xda,0xb7,0x8e,0x26, 0x3f,0xad,0xbf,0xa4 +.byte 0x2c,0x3a,0x9d,0xe4, 0x50,0x78,0x92,0x0d +.byte 0x6a,0x5f,0xcc,0x9b, 0x54,0x7e,0x46,0x62 +.byte 0xf6,0x8d,0x13,0xc2, 0x90,0xd8,0xb8,0xe8 +.byte 0x2e,0x39,0xf7,0x5e, 0x82,0xc3,0xaf,0xf5 +.byte 0x9f,0x5d,0x80,0xbe, 0x69,0xd0,0x93,0x7c +.byte 0x6f,0xd5,0x2d,0xa9, 0xcf,0x25,0x12,0xb3 +.byte 0xc8,0xac,0x99,0x3b, 0x10,0x18,0x7d,0xa7 +.byte 0xe8,0x9c,0x63,0x6e, 0xdb,0x3b,0xbb,0x7b +.byte 0xcd,0x26,0x78,0x09, 0x6e,0x59,0x18,0xf4 +.byte 0xec,0x9a,0xb7,0x01, 0x83,0x4f,0x9a,0xa8 +.byte 0xe6,0x95,0x6e,0x65, 0xaa,0xff,0xe6,0x7e +.byte 0x21,0xbc,0xcf,0x08, 0xef,0x15,0xe8,0xe6 +.byte 0xba,0xe7,0x9b,0xd9, 0x4a,0x6f,0x36,0xce +.byte 0xea,0x9f,0x09,0xd4, 0x29,0xb0,0x7c,0xd6 +.byte 0x31,0xa4,0xb2,0xaf, 0x2a,0x3f,0x23,0x31 +.byte 0xc6,0xa5,0x94,0x30, 0x35,0xa2,0x66,0xc0 +.byte 0x74,0x4e,0xbc,0x37, 0xfc,0x82,0xca,0xa6 +.byte 0xe0,0x90,0xd0,0xb0, 0x33,0xa7,0xd8,0x15 +.byte 0xf1,0x04,0x98,0x4a, 0x41,0xec,0xda,0xf7 +.byte 0x7f,0xcd,0x50,0x0e, 0x17,0x91,0xf6,0x2f +.byte 0x76,0x4d,0xd6,0x8d, 0x43,0xef,0xb0,0x4d +.byte 0xcc,0xaa,0x4d,0x54, 0xe4,0x96,0x04,0xdf +.byte 0x9e,0xd1,0xb5,0xe3, 0x4c,0x6a,0x88,0x1b +.byte 0xc1,0x2c,0x1f,0xb8, 0x46,0x65,0x51,0x7f +.byte 0x9d,0x5e,0xea,0x04, 0x01,0x8c,0x35,0x5d +.byte 0xfa,0x87,0x74,0x73, 0xfb,0x0b,0x41,0x2e +.byte 0xb3,0x67,0x1d,0x5a, 0x92,0xdb,0xd2,0x52 +.byte 0xe9,0x10,0x56,0x33, 0x6d,0xd6,0x47,0x13 +.byte 0x9a,0xd7,0x61,0x8c, 0x37,0xa1,0x0c,0x7a +.byte 0x59,0xf8,0x14,0x8e, 0xeb,0x13,0x3c,0x89 +.byte 0xce,0xa9,0x27,0xee, 0xb7,0x61,0xc9,0x35 +.byte 0xe1,0x1c,0xe5,0xed, 0x7a,0x47,0xb1,0x3c +.byte 0x9c,0xd2,0xdf,0x59, 0x55,0xf2,0x73,0x3f +.byte 0x18,0x14,0xce,0x79, 0x73,0xc7,0x37,0xbf +.byte 0x53,0xf7,0xcd,0xea, 0x5f,0xfd,0xaa,0x5b +.byte 0xdf,0x3d,0x6f,0x14, 0x78,0x44,0xdb,0x86 +.byte 0xca,0xaf,0xf3,0x81, 0xb9,0x68,0xc4,0x3e +.byte 0x38,0x24,0x34,0x2c, 0xc2,0xa3,0x40,0x5f +.byte 0x16,0x1d,0xc3,0x72, 0xbc,0xe2,0x25,0x0c +.byte 0x28,0x3c,0x49,0x8b, 0xff,0x0d,0x95,0x41 +.byte 0x39,0xa8,0x01,0x71, 0x08,0x0c,0xb3,0xde +.byte 0xd8,0xb4,0xe4,0x9c, 0x64,0x56,0xc1,0x90 +.byte 0x7b,0xcb,0x84,0x61, 0xd5,0x32,0xb6,0x70 +.byte 0x48,0x6c,0x5c,0x74, 0xd0,0xb8,0x57,0x42 + +.byte 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38 # Td4 +.byte 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb +.byte 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87 +.byte 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb +.byte 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d +.byte 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e +.byte 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2 +.byte 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 +.byte 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16 +.byte 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 +.byte 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda +.byte 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 +.byte 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a +.byte 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 +.byte 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02 +.byte 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b +.byte 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea +.byte 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 +.byte 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85 +.byte 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e +.byte 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89 +.byte 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b +.byte 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20 +.byte 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 +.byte 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31 +.byte 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f +.byte 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d +.byte 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef +.byte 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0 +.byte 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 +.byte 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26 +.byte 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d + +AES_Te4: +.byte 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5 # Te4 +.byte 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76 +.byte 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0 +.byte 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0 +.byte 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc +.byte 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15 +.byte 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a +.byte 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75 +.byte 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0 +.byte 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84 +.byte 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b +.byte 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf +.byte 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85 +.byte 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8 +.byte 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5 +.byte 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2 +.byte 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17 +.byte 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73 +.byte 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88 +.byte 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb +.byte 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c +.byte 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79 +.byte 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9 +.byte 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08 +.byte 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6 +.byte 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a +.byte 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e +.byte 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e +.byte 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94 +.byte 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf +.byte 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68 +.byte 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 + +.byte 0x01,0x00,0x00,0x00, 0x02,0x00,0x00,0x00 # rcon +.byte 0x04,0x00,0x00,0x00, 0x08,0x00,0x00,0x00 +.byte 0x10,0x00,0x00,0x00, 0x20,0x00,0x00,0x00 +.byte 0x40,0x00,0x00,0x00, 0x80,0x00,0x00,0x00 +.byte 0x1B,0x00,0x00,0x00, 0x36,0x00,0x00,0x00 +___ + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/ge; + + # made-up _instructions, _xtr, _ins, _ror and _bias, cope + # with byte order dependencies... + if (/^\s+_/) { + s/(_[a-z]+\s+)(\$[0-9]+),([^,]+)(#.*)*$/$1$2,$2,$3/; + + s/_xtr\s+(\$[0-9]+),(\$[0-9]+),([0-9]+(\-2)*)/ + sprintf("srl\t$1,$2,%d",$big_endian ? eval($3) + : eval("24-$3"))/e or + s/_ins\s+(\$[0-9]+),(\$[0-9]+),([0-9]+)/ + sprintf("sll\t$1,$2,%d",$big_endian ? eval($3) + : eval("24-$3"))/e or + s/_ins2\s+(\$[0-9]+),(\$[0-9]+),([0-9]+)/ + sprintf("ins\t$1,$2,%d,8",$big_endian ? eval($3) + : eval("24-$3"))/e or + s/_ror\s+(\$[0-9]+),(\$[0-9]+),(\-?[0-9]+)/ + sprintf("srl\t$1,$2,%d",$big_endian ? eval($3) + : eval("$3*-1"))/e or + s/_bias\s+(\$[0-9]+),(\$[0-9]+),([0-9]+)/ + sprintf("sll\t$1,$2,%d",$big_endian ? eval($3) + : eval("($3-16)&31"))/e; + + s/srl\s+(\$[0-9]+),(\$[0-9]+),\-([0-9]+)/ + sprintf("sll\t$1,$2,$3")/e or + s/srl\s+(\$[0-9]+),(\$[0-9]+),0/ + sprintf("and\t$1,$2,0xff")/e or + s/(sll\s+\$[0-9]+,\$[0-9]+,0)/#$1/; + } + + # convert lwl/lwr and swr/swl to little-endian order + if (!$big_endian && /^\s+[sl]w[lr]\s+/) { + s/([sl]wl.*)([0-9]+)\((\$[0-9]+)\)/ + sprintf("$1%d($3)",eval("$2-$2%4+($2%4-1)&3"))/e or + s/([sl]wr.*)([0-9]+)\((\$[0-9]+)\)/ + sprintf("$1%d($3)",eval("$2-$2%4+($2%4+1)&3"))/e; + } + + if (!$big_endian) { + s/(rotr\s+\$[0-9]+,\$[0-9]+),([0-9]+)/sprintf("$1,%d",32-$2)/e; + s/(ext\s+\$[0-9]+,\$[0-9]+),([0-9]+),8/sprintf("$1,%d,8",24-$2)/e; + } + + print $_,"\n"; +} + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-parisc.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-parisc.pl new file mode 100644 index 000000000..e817c757f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-parisc.pl @@ -0,0 +1,1038 @@ +#! /usr/bin/env perl +# Copyright 2009-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# AES for PA-RISC. +# +# June 2009. +# +# The module is mechanical transliteration of aes-sparcv9.pl, but with +# a twist: S-boxes are compressed even further down to 1K+256B. On +# PA-7100LC performance is ~40% better than gcc 3.2 generated code and +# is about 33 cycles per byte processed with 128-bit key. Newer CPUs +# perform at 16 cycles per byte. It's not faster than code generated +# by vendor compiler, but recall that it has compressed S-boxes, which +# requires extra processing. +# +# Special thanks to polarhome.com for providing HP-UX account. + +$flavour = shift; +$output = shift; +open STDOUT,">$output"; + +if ($flavour =~ /64/) { + $LEVEL ="2.0W"; + $SIZE_T =8; + $FRAME_MARKER =80; + $SAVED_RP =16; + $PUSH ="std"; + $PUSHMA ="std,ma"; + $POP ="ldd"; + $POPMB ="ldd,mb"; +} else { + $LEVEL ="1.0"; + $SIZE_T =4; + $FRAME_MARKER =48; + $SAVED_RP =20; + $PUSH ="stw"; + $PUSHMA ="stwm"; + $POP ="ldw"; + $POPMB ="ldwm"; +} + +$FRAME=16*$SIZE_T+$FRAME_MARKER;# 16 saved regs + frame marker + # [+ argument transfer] +$inp="%r26"; # arg0 +$out="%r25"; # arg1 +$key="%r24"; # arg2 + +($s0,$s1,$s2,$s3) = ("%r1","%r2","%r3","%r4"); +($t0,$t1,$t2,$t3) = ("%r5","%r6","%r7","%r8"); + +($acc0, $acc1, $acc2, $acc3, $acc4, $acc5, $acc6, $acc7, + $acc8, $acc9,$acc10,$acc11,$acc12,$acc13,$acc14,$acc15) = +("%r9","%r10","%r11","%r12","%r13","%r14","%r15","%r16", +"%r17","%r18","%r19","%r20","%r21","%r22","%r23","%r26"); + +$tbl="%r28"; +$rounds="%r29"; + +$code=<<___; + .LEVEL $LEVEL + .SPACE \$TEXT\$ + .SUBSPA \$CODE\$,QUAD=0,ALIGN=8,ACCESS=0x2C,CODE_ONLY + + .EXPORT AES_encrypt,ENTRY,ARGW0=GR,ARGW1=GR,ARGW2=GR + .ALIGN 64 +AES_encrypt + .PROC + .CALLINFO FRAME=`$FRAME-16*$SIZE_T`,NO_CALLS,SAVE_RP,ENTRY_GR=18 + .ENTRY + $PUSH %r2,-$SAVED_RP(%sp) ; standard prologue + $PUSHMA %r3,$FRAME(%sp) + $PUSH %r4,`-$FRAME+1*$SIZE_T`(%sp) + $PUSH %r5,`-$FRAME+2*$SIZE_T`(%sp) + $PUSH %r6,`-$FRAME+3*$SIZE_T`(%sp) + $PUSH %r7,`-$FRAME+4*$SIZE_T`(%sp) + $PUSH %r8,`-$FRAME+5*$SIZE_T`(%sp) + $PUSH %r9,`-$FRAME+6*$SIZE_T`(%sp) + $PUSH %r10,`-$FRAME+7*$SIZE_T`(%sp) + $PUSH %r11,`-$FRAME+8*$SIZE_T`(%sp) + $PUSH %r12,`-$FRAME+9*$SIZE_T`(%sp) + $PUSH %r13,`-$FRAME+10*$SIZE_T`(%sp) + $PUSH %r14,`-$FRAME+11*$SIZE_T`(%sp) + $PUSH %r15,`-$FRAME+12*$SIZE_T`(%sp) + $PUSH %r16,`-$FRAME+13*$SIZE_T`(%sp) + $PUSH %r17,`-$FRAME+14*$SIZE_T`(%sp) + $PUSH %r18,`-$FRAME+15*$SIZE_T`(%sp) + + blr %r0,$tbl + ldi 3,$t0 +L\$enc_pic + andcm $tbl,$t0,$tbl + ldo L\$AES_Te-L\$enc_pic($tbl),$tbl + + and $inp,$t0,$t0 + sub $inp,$t0,$inp + ldw 0($inp),$s0 + ldw 4($inp),$s1 + ldw 8($inp),$s2 + comib,= 0,$t0,L\$enc_inp_aligned + ldw 12($inp),$s3 + + sh3addl $t0,%r0,$t0 + subi 32,$t0,$t0 + mtctl $t0,%cr11 + ldw 16($inp),$t1 + vshd $s0,$s1,$s0 + vshd $s1,$s2,$s1 + vshd $s2,$s3,$s2 + vshd $s3,$t1,$s3 + +L\$enc_inp_aligned + bl _parisc_AES_encrypt,%r31 + nop + + extru,<> $out,31,2,%r0 + b L\$enc_out_aligned + nop + + _srm $s0,24,$acc0 + _srm $s0,16,$acc1 + stb $acc0,0($out) + _srm $s0,8,$acc2 + stb $acc1,1($out) + _srm $s1,24,$acc4 + stb $acc2,2($out) + _srm $s1,16,$acc5 + stb $s0,3($out) + _srm $s1,8,$acc6 + stb $acc4,4($out) + _srm $s2,24,$acc0 + stb $acc5,5($out) + _srm $s2,16,$acc1 + stb $acc6,6($out) + _srm $s2,8,$acc2 + stb $s1,7($out) + _srm $s3,24,$acc4 + stb $acc0,8($out) + _srm $s3,16,$acc5 + stb $acc1,9($out) + _srm $s3,8,$acc6 + stb $acc2,10($out) + stb $s2,11($out) + stb $acc4,12($out) + stb $acc5,13($out) + stb $acc6,14($out) + b L\$enc_done + stb $s3,15($out) + +L\$enc_out_aligned + stw $s0,0($out) + stw $s1,4($out) + stw $s2,8($out) + stw $s3,12($out) + +L\$enc_done + $POP `-$FRAME-$SAVED_RP`(%sp),%r2 ; standard epilogue + $POP `-$FRAME+1*$SIZE_T`(%sp),%r4 + $POP `-$FRAME+2*$SIZE_T`(%sp),%r5 + $POP `-$FRAME+3*$SIZE_T`(%sp),%r6 + $POP `-$FRAME+4*$SIZE_T`(%sp),%r7 + $POP `-$FRAME+5*$SIZE_T`(%sp),%r8 + $POP `-$FRAME+6*$SIZE_T`(%sp),%r9 + $POP `-$FRAME+7*$SIZE_T`(%sp),%r10 + $POP `-$FRAME+8*$SIZE_T`(%sp),%r11 + $POP `-$FRAME+9*$SIZE_T`(%sp),%r12 + $POP `-$FRAME+10*$SIZE_T`(%sp),%r13 + $POP `-$FRAME+11*$SIZE_T`(%sp),%r14 + $POP `-$FRAME+12*$SIZE_T`(%sp),%r15 + $POP `-$FRAME+13*$SIZE_T`(%sp),%r16 + $POP `-$FRAME+14*$SIZE_T`(%sp),%r17 + $POP `-$FRAME+15*$SIZE_T`(%sp),%r18 + bv (%r2) + .EXIT + $POPMB -$FRAME(%sp),%r3 + .PROCEND + + .ALIGN 16 +_parisc_AES_encrypt + .PROC + .CALLINFO MILLICODE + .ENTRY + ldw 240($key),$rounds + ldw 0($key),$t0 + ldw 4($key),$t1 + ldw 8($key),$t2 + _srm $rounds,1,$rounds + xor $t0,$s0,$s0 + ldw 12($key),$t3 + _srm $s0,24,$acc0 + xor $t1,$s1,$s1 + ldw 16($key),$t0 + _srm $s1,16,$acc1 + xor $t2,$s2,$s2 + ldw 20($key),$t1 + xor $t3,$s3,$s3 + ldw 24($key),$t2 + ldw 28($key),$t3 +L\$enc_loop + _srm $s2,8,$acc2 + ldwx,s $acc0($tbl),$acc0 + _srm $s3,0,$acc3 + ldwx,s $acc1($tbl),$acc1 + _srm $s1,24,$acc4 + ldwx,s $acc2($tbl),$acc2 + _srm $s2,16,$acc5 + ldwx,s $acc3($tbl),$acc3 + _srm $s3,8,$acc6 + ldwx,s $acc4($tbl),$acc4 + _srm $s0,0,$acc7 + ldwx,s $acc5($tbl),$acc5 + _srm $s2,24,$acc8 + ldwx,s $acc6($tbl),$acc6 + _srm $s3,16,$acc9 + ldwx,s $acc7($tbl),$acc7 + _srm $s0,8,$acc10 + ldwx,s $acc8($tbl),$acc8 + _srm $s1,0,$acc11 + ldwx,s $acc9($tbl),$acc9 + _srm $s3,24,$acc12 + ldwx,s $acc10($tbl),$acc10 + _srm $s0,16,$acc13 + ldwx,s $acc11($tbl),$acc11 + _srm $s1,8,$acc14 + ldwx,s $acc12($tbl),$acc12 + _srm $s2,0,$acc15 + ldwx,s $acc13($tbl),$acc13 + ldwx,s $acc14($tbl),$acc14 + ldwx,s $acc15($tbl),$acc15 + addib,= -1,$rounds,L\$enc_last + ldo 32($key),$key + + _ror $acc1,8,$acc1 + xor $acc0,$t0,$t0 + ldw 0($key),$s0 + _ror $acc2,16,$acc2 + xor $acc1,$t0,$t0 + ldw 4($key),$s1 + _ror $acc3,24,$acc3 + xor $acc2,$t0,$t0 + ldw 8($key),$s2 + _ror $acc5,8,$acc5 + xor $acc3,$t0,$t0 + ldw 12($key),$s3 + _ror $acc6,16,$acc6 + xor $acc4,$t1,$t1 + _ror $acc7,24,$acc7 + xor $acc5,$t1,$t1 + _ror $acc9,8,$acc9 + xor $acc6,$t1,$t1 + _ror $acc10,16,$acc10 + xor $acc7,$t1,$t1 + _ror $acc11,24,$acc11 + xor $acc8,$t2,$t2 + _ror $acc13,8,$acc13 + xor $acc9,$t2,$t2 + _ror $acc14,16,$acc14 + xor $acc10,$t2,$t2 + _ror $acc15,24,$acc15 + xor $acc11,$t2,$t2 + xor $acc12,$acc14,$acc14 + xor $acc13,$t3,$t3 + _srm $t0,24,$acc0 + xor $acc14,$t3,$t3 + _srm $t1,16,$acc1 + xor $acc15,$t3,$t3 + + _srm $t2,8,$acc2 + ldwx,s $acc0($tbl),$acc0 + _srm $t3,0,$acc3 + ldwx,s $acc1($tbl),$acc1 + _srm $t1,24,$acc4 + ldwx,s $acc2($tbl),$acc2 + _srm $t2,16,$acc5 + ldwx,s $acc3($tbl),$acc3 + _srm $t3,8,$acc6 + ldwx,s $acc4($tbl),$acc4 + _srm $t0,0,$acc7 + ldwx,s $acc5($tbl),$acc5 + _srm $t2,24,$acc8 + ldwx,s $acc6($tbl),$acc6 + _srm $t3,16,$acc9 + ldwx,s $acc7($tbl),$acc7 + _srm $t0,8,$acc10 + ldwx,s $acc8($tbl),$acc8 + _srm $t1,0,$acc11 + ldwx,s $acc9($tbl),$acc9 + _srm $t3,24,$acc12 + ldwx,s $acc10($tbl),$acc10 + _srm $t0,16,$acc13 + ldwx,s $acc11($tbl),$acc11 + _srm $t1,8,$acc14 + ldwx,s $acc12($tbl),$acc12 + _srm $t2,0,$acc15 + ldwx,s $acc13($tbl),$acc13 + _ror $acc1,8,$acc1 + ldwx,s $acc14($tbl),$acc14 + + _ror $acc2,16,$acc2 + xor $acc0,$s0,$s0 + ldwx,s $acc15($tbl),$acc15 + _ror $acc3,24,$acc3 + xor $acc1,$s0,$s0 + ldw 16($key),$t0 + _ror $acc5,8,$acc5 + xor $acc2,$s0,$s0 + ldw 20($key),$t1 + _ror $acc6,16,$acc6 + xor $acc3,$s0,$s0 + ldw 24($key),$t2 + _ror $acc7,24,$acc7 + xor $acc4,$s1,$s1 + ldw 28($key),$t3 + _ror $acc9,8,$acc9 + xor $acc5,$s1,$s1 + ldw 1024+0($tbl),%r0 ; prefetch te4 + _ror $acc10,16,$acc10 + xor $acc6,$s1,$s1 + ldw 1024+32($tbl),%r0 ; prefetch te4 + _ror $acc11,24,$acc11 + xor $acc7,$s1,$s1 + ldw 1024+64($tbl),%r0 ; prefetch te4 + _ror $acc13,8,$acc13 + xor $acc8,$s2,$s2 + ldw 1024+96($tbl),%r0 ; prefetch te4 + _ror $acc14,16,$acc14 + xor $acc9,$s2,$s2 + ldw 1024+128($tbl),%r0 ; prefetch te4 + _ror $acc15,24,$acc15 + xor $acc10,$s2,$s2 + ldw 1024+160($tbl),%r0 ; prefetch te4 + _srm $s0,24,$acc0 + xor $acc11,$s2,$s2 + ldw 1024+192($tbl),%r0 ; prefetch te4 + xor $acc12,$acc14,$acc14 + xor $acc13,$s3,$s3 + ldw 1024+224($tbl),%r0 ; prefetch te4 + _srm $s1,16,$acc1 + xor $acc14,$s3,$s3 + b L\$enc_loop + xor $acc15,$s3,$s3 + + .ALIGN 16 +L\$enc_last + ldo 1024($tbl),$rounds + _ror $acc1,8,$acc1 + xor $acc0,$t0,$t0 + ldw 0($key),$s0 + _ror $acc2,16,$acc2 + xor $acc1,$t0,$t0 + ldw 4($key),$s1 + _ror $acc3,24,$acc3 + xor $acc2,$t0,$t0 + ldw 8($key),$s2 + _ror $acc5,8,$acc5 + xor $acc3,$t0,$t0 + ldw 12($key),$s3 + _ror $acc6,16,$acc6 + xor $acc4,$t1,$t1 + _ror $acc7,24,$acc7 + xor $acc5,$t1,$t1 + _ror $acc9,8,$acc9 + xor $acc6,$t1,$t1 + _ror $acc10,16,$acc10 + xor $acc7,$t1,$t1 + _ror $acc11,24,$acc11 + xor $acc8,$t2,$t2 + _ror $acc13,8,$acc13 + xor $acc9,$t2,$t2 + _ror $acc14,16,$acc14 + xor $acc10,$t2,$t2 + _ror $acc15,24,$acc15 + xor $acc11,$t2,$t2 + xor $acc12,$acc14,$acc14 + xor $acc13,$t3,$t3 + _srm $t0,24,$acc0 + xor $acc14,$t3,$t3 + _srm $t1,16,$acc1 + xor $acc15,$t3,$t3 + + _srm $t2,8,$acc2 + ldbx $acc0($rounds),$acc0 + _srm $t1,24,$acc4 + ldbx $acc1($rounds),$acc1 + _srm $t2,16,$acc5 + _srm $t3,0,$acc3 + ldbx $acc2($rounds),$acc2 + ldbx $acc3($rounds),$acc3 + _srm $t3,8,$acc6 + ldbx $acc4($rounds),$acc4 + _srm $t2,24,$acc8 + ldbx $acc5($rounds),$acc5 + _srm $t3,16,$acc9 + _srm $t0,0,$acc7 + ldbx $acc6($rounds),$acc6 + ldbx $acc7($rounds),$acc7 + _srm $t0,8,$acc10 + ldbx $acc8($rounds),$acc8 + _srm $t3,24,$acc12 + ldbx $acc9($rounds),$acc9 + _srm $t0,16,$acc13 + _srm $t1,0,$acc11 + ldbx $acc10($rounds),$acc10 + _srm $t1,8,$acc14 + ldbx $acc11($rounds),$acc11 + ldbx $acc12($rounds),$acc12 + ldbx $acc13($rounds),$acc13 + _srm $t2,0,$acc15 + ldbx $acc14($rounds),$acc14 + + dep $acc0,7,8,$acc3 + ldbx $acc15($rounds),$acc15 + dep $acc4,7,8,$acc7 + dep $acc1,15,8,$acc3 + dep $acc5,15,8,$acc7 + dep $acc2,23,8,$acc3 + dep $acc6,23,8,$acc7 + xor $acc3,$s0,$s0 + xor $acc7,$s1,$s1 + dep $acc8,7,8,$acc11 + dep $acc12,7,8,$acc15 + dep $acc9,15,8,$acc11 + dep $acc13,15,8,$acc15 + dep $acc10,23,8,$acc11 + dep $acc14,23,8,$acc15 + xor $acc11,$s2,$s2 + + bv (%r31) + .EXIT + xor $acc15,$s3,$s3 + .PROCEND + + .ALIGN 64 +L\$AES_Te + .WORD 0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d + .WORD 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554 + .WORD 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d + .WORD 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a + .WORD 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87 + .WORD 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b + .WORD 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea + .WORD 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b + .WORD 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a + .WORD 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f + .WORD 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108 + .WORD 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f + .WORD 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e + .WORD 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5 + .WORD 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d + .WORD 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f + .WORD 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e + .WORD 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb + .WORD 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce + .WORD 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497 + .WORD 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c + .WORD 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed + .WORD 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b + .WORD 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a + .WORD 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16 + .WORD 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594 + .WORD 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81 + .WORD 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3 + .WORD 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a + .WORD 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504 + .WORD 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163 + .WORD 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d + .WORD 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f + .WORD 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739 + .WORD 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47 + .WORD 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395 + .WORD 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f + .WORD 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883 + .WORD 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c + .WORD 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76 + .WORD 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e + .WORD 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4 + .WORD 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6 + .WORD 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b + .WORD 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7 + .WORD 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0 + .WORD 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25 + .WORD 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818 + .WORD 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72 + .WORD 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651 + .WORD 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21 + .WORD 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85 + .WORD 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa + .WORD 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12 + .WORD 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0 + .WORD 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9 + .WORD 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133 + .WORD 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7 + .WORD 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920 + .WORD 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a + .WORD 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17 + .WORD 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8 + .WORD 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11 + .WORD 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a + .BYTE 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5 + .BYTE 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76 + .BYTE 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0 + .BYTE 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0 + .BYTE 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc + .BYTE 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15 + .BYTE 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a + .BYTE 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75 + .BYTE 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0 + .BYTE 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84 + .BYTE 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b + .BYTE 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf + .BYTE 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85 + .BYTE 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8 + .BYTE 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5 + .BYTE 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2 + .BYTE 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17 + .BYTE 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73 + .BYTE 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88 + .BYTE 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb + .BYTE 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c + .BYTE 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79 + .BYTE 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9 + .BYTE 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08 + .BYTE 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6 + .BYTE 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a + .BYTE 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e + .BYTE 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e + .BYTE 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94 + .BYTE 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf + .BYTE 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68 + .BYTE 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +___ + +$code.=<<___; + .EXPORT AES_decrypt,ENTRY,ARGW0=GR,ARGW1=GR,ARGW2=GR + .ALIGN 16 +AES_decrypt + .PROC + .CALLINFO FRAME=`$FRAME-16*$SIZE_T`,NO_CALLS,SAVE_RP,ENTRY_GR=18 + .ENTRY + $PUSH %r2,-$SAVED_RP(%sp) ; standard prologue + $PUSHMA %r3,$FRAME(%sp) + $PUSH %r4,`-$FRAME+1*$SIZE_T`(%sp) + $PUSH %r5,`-$FRAME+2*$SIZE_T`(%sp) + $PUSH %r6,`-$FRAME+3*$SIZE_T`(%sp) + $PUSH %r7,`-$FRAME+4*$SIZE_T`(%sp) + $PUSH %r8,`-$FRAME+5*$SIZE_T`(%sp) + $PUSH %r9,`-$FRAME+6*$SIZE_T`(%sp) + $PUSH %r10,`-$FRAME+7*$SIZE_T`(%sp) + $PUSH %r11,`-$FRAME+8*$SIZE_T`(%sp) + $PUSH %r12,`-$FRAME+9*$SIZE_T`(%sp) + $PUSH %r13,`-$FRAME+10*$SIZE_T`(%sp) + $PUSH %r14,`-$FRAME+11*$SIZE_T`(%sp) + $PUSH %r15,`-$FRAME+12*$SIZE_T`(%sp) + $PUSH %r16,`-$FRAME+13*$SIZE_T`(%sp) + $PUSH %r17,`-$FRAME+14*$SIZE_T`(%sp) + $PUSH %r18,`-$FRAME+15*$SIZE_T`(%sp) + + blr %r0,$tbl + ldi 3,$t0 +L\$dec_pic + andcm $tbl,$t0,$tbl + ldo L\$AES_Td-L\$dec_pic($tbl),$tbl + + and $inp,$t0,$t0 + sub $inp,$t0,$inp + ldw 0($inp),$s0 + ldw 4($inp),$s1 + ldw 8($inp),$s2 + comib,= 0,$t0,L\$dec_inp_aligned + ldw 12($inp),$s3 + + sh3addl $t0,%r0,$t0 + subi 32,$t0,$t0 + mtctl $t0,%cr11 + ldw 16($inp),$t1 + vshd $s0,$s1,$s0 + vshd $s1,$s2,$s1 + vshd $s2,$s3,$s2 + vshd $s3,$t1,$s3 + +L\$dec_inp_aligned + bl _parisc_AES_decrypt,%r31 + nop + + extru,<> $out,31,2,%r0 + b L\$dec_out_aligned + nop + + _srm $s0,24,$acc0 + _srm $s0,16,$acc1 + stb $acc0,0($out) + _srm $s0,8,$acc2 + stb $acc1,1($out) + _srm $s1,24,$acc4 + stb $acc2,2($out) + _srm $s1,16,$acc5 + stb $s0,3($out) + _srm $s1,8,$acc6 + stb $acc4,4($out) + _srm $s2,24,$acc0 + stb $acc5,5($out) + _srm $s2,16,$acc1 + stb $acc6,6($out) + _srm $s2,8,$acc2 + stb $s1,7($out) + _srm $s3,24,$acc4 + stb $acc0,8($out) + _srm $s3,16,$acc5 + stb $acc1,9($out) + _srm $s3,8,$acc6 + stb $acc2,10($out) + stb $s2,11($out) + stb $acc4,12($out) + stb $acc5,13($out) + stb $acc6,14($out) + b L\$dec_done + stb $s3,15($out) + +L\$dec_out_aligned + stw $s0,0($out) + stw $s1,4($out) + stw $s2,8($out) + stw $s3,12($out) + +L\$dec_done + $POP `-$FRAME-$SAVED_RP`(%sp),%r2 ; standard epilogue + $POP `-$FRAME+1*$SIZE_T`(%sp),%r4 + $POP `-$FRAME+2*$SIZE_T`(%sp),%r5 + $POP `-$FRAME+3*$SIZE_T`(%sp),%r6 + $POP `-$FRAME+4*$SIZE_T`(%sp),%r7 + $POP `-$FRAME+5*$SIZE_T`(%sp),%r8 + $POP `-$FRAME+6*$SIZE_T`(%sp),%r9 + $POP `-$FRAME+7*$SIZE_T`(%sp),%r10 + $POP `-$FRAME+8*$SIZE_T`(%sp),%r11 + $POP `-$FRAME+9*$SIZE_T`(%sp),%r12 + $POP `-$FRAME+10*$SIZE_T`(%sp),%r13 + $POP `-$FRAME+11*$SIZE_T`(%sp),%r14 + $POP `-$FRAME+12*$SIZE_T`(%sp),%r15 + $POP `-$FRAME+13*$SIZE_T`(%sp),%r16 + $POP `-$FRAME+14*$SIZE_T`(%sp),%r17 + $POP `-$FRAME+15*$SIZE_T`(%sp),%r18 + bv (%r2) + .EXIT + $POPMB -$FRAME(%sp),%r3 + .PROCEND + + .ALIGN 16 +_parisc_AES_decrypt + .PROC + .CALLINFO MILLICODE + .ENTRY + ldw 240($key),$rounds + ldw 0($key),$t0 + ldw 4($key),$t1 + ldw 8($key),$t2 + ldw 12($key),$t3 + _srm $rounds,1,$rounds + xor $t0,$s0,$s0 + ldw 16($key),$t0 + xor $t1,$s1,$s1 + ldw 20($key),$t1 + _srm $s0,24,$acc0 + xor $t2,$s2,$s2 + ldw 24($key),$t2 + xor $t3,$s3,$s3 + ldw 28($key),$t3 + _srm $s3,16,$acc1 +L\$dec_loop + _srm $s2,8,$acc2 + ldwx,s $acc0($tbl),$acc0 + _srm $s1,0,$acc3 + ldwx,s $acc1($tbl),$acc1 + _srm $s1,24,$acc4 + ldwx,s $acc2($tbl),$acc2 + _srm $s0,16,$acc5 + ldwx,s $acc3($tbl),$acc3 + _srm $s3,8,$acc6 + ldwx,s $acc4($tbl),$acc4 + _srm $s2,0,$acc7 + ldwx,s $acc5($tbl),$acc5 + _srm $s2,24,$acc8 + ldwx,s $acc6($tbl),$acc6 + _srm $s1,16,$acc9 + ldwx,s $acc7($tbl),$acc7 + _srm $s0,8,$acc10 + ldwx,s $acc8($tbl),$acc8 + _srm $s3,0,$acc11 + ldwx,s $acc9($tbl),$acc9 + _srm $s3,24,$acc12 + ldwx,s $acc10($tbl),$acc10 + _srm $s2,16,$acc13 + ldwx,s $acc11($tbl),$acc11 + _srm $s1,8,$acc14 + ldwx,s $acc12($tbl),$acc12 + _srm $s0,0,$acc15 + ldwx,s $acc13($tbl),$acc13 + ldwx,s $acc14($tbl),$acc14 + ldwx,s $acc15($tbl),$acc15 + addib,= -1,$rounds,L\$dec_last + ldo 32($key),$key + + _ror $acc1,8,$acc1 + xor $acc0,$t0,$t0 + ldw 0($key),$s0 + _ror $acc2,16,$acc2 + xor $acc1,$t0,$t0 + ldw 4($key),$s1 + _ror $acc3,24,$acc3 + xor $acc2,$t0,$t0 + ldw 8($key),$s2 + _ror $acc5,8,$acc5 + xor $acc3,$t0,$t0 + ldw 12($key),$s3 + _ror $acc6,16,$acc6 + xor $acc4,$t1,$t1 + _ror $acc7,24,$acc7 + xor $acc5,$t1,$t1 + _ror $acc9,8,$acc9 + xor $acc6,$t1,$t1 + _ror $acc10,16,$acc10 + xor $acc7,$t1,$t1 + _ror $acc11,24,$acc11 + xor $acc8,$t2,$t2 + _ror $acc13,8,$acc13 + xor $acc9,$t2,$t2 + _ror $acc14,16,$acc14 + xor $acc10,$t2,$t2 + _ror $acc15,24,$acc15 + xor $acc11,$t2,$t2 + xor $acc12,$acc14,$acc14 + xor $acc13,$t3,$t3 + _srm $t0,24,$acc0 + xor $acc14,$t3,$t3 + xor $acc15,$t3,$t3 + _srm $t3,16,$acc1 + + _srm $t2,8,$acc2 + ldwx,s $acc0($tbl),$acc0 + _srm $t1,0,$acc3 + ldwx,s $acc1($tbl),$acc1 + _srm $t1,24,$acc4 + ldwx,s $acc2($tbl),$acc2 + _srm $t0,16,$acc5 + ldwx,s $acc3($tbl),$acc3 + _srm $t3,8,$acc6 + ldwx,s $acc4($tbl),$acc4 + _srm $t2,0,$acc7 + ldwx,s $acc5($tbl),$acc5 + _srm $t2,24,$acc8 + ldwx,s $acc6($tbl),$acc6 + _srm $t1,16,$acc9 + ldwx,s $acc7($tbl),$acc7 + _srm $t0,8,$acc10 + ldwx,s $acc8($tbl),$acc8 + _srm $t3,0,$acc11 + ldwx,s $acc9($tbl),$acc9 + _srm $t3,24,$acc12 + ldwx,s $acc10($tbl),$acc10 + _srm $t2,16,$acc13 + ldwx,s $acc11($tbl),$acc11 + _srm $t1,8,$acc14 + ldwx,s $acc12($tbl),$acc12 + _srm $t0,0,$acc15 + ldwx,s $acc13($tbl),$acc13 + _ror $acc1,8,$acc1 + ldwx,s $acc14($tbl),$acc14 + + _ror $acc2,16,$acc2 + xor $acc0,$s0,$s0 + ldwx,s $acc15($tbl),$acc15 + _ror $acc3,24,$acc3 + xor $acc1,$s0,$s0 + ldw 16($key),$t0 + _ror $acc5,8,$acc5 + xor $acc2,$s0,$s0 + ldw 20($key),$t1 + _ror $acc6,16,$acc6 + xor $acc3,$s0,$s0 + ldw 24($key),$t2 + _ror $acc7,24,$acc7 + xor $acc4,$s1,$s1 + ldw 28($key),$t3 + _ror $acc9,8,$acc9 + xor $acc5,$s1,$s1 + ldw 1024+0($tbl),%r0 ; prefetch td4 + _ror $acc10,16,$acc10 + xor $acc6,$s1,$s1 + ldw 1024+32($tbl),%r0 ; prefetch td4 + _ror $acc11,24,$acc11 + xor $acc7,$s1,$s1 + ldw 1024+64($tbl),%r0 ; prefetch td4 + _ror $acc13,8,$acc13 + xor $acc8,$s2,$s2 + ldw 1024+96($tbl),%r0 ; prefetch td4 + _ror $acc14,16,$acc14 + xor $acc9,$s2,$s2 + ldw 1024+128($tbl),%r0 ; prefetch td4 + _ror $acc15,24,$acc15 + xor $acc10,$s2,$s2 + ldw 1024+160($tbl),%r0 ; prefetch td4 + _srm $s0,24,$acc0 + xor $acc11,$s2,$s2 + ldw 1024+192($tbl),%r0 ; prefetch td4 + xor $acc12,$acc14,$acc14 + xor $acc13,$s3,$s3 + ldw 1024+224($tbl),%r0 ; prefetch td4 + xor $acc14,$s3,$s3 + xor $acc15,$s3,$s3 + b L\$dec_loop + _srm $s3,16,$acc1 + + .ALIGN 16 +L\$dec_last + ldo 1024($tbl),$rounds + _ror $acc1,8,$acc1 + xor $acc0,$t0,$t0 + ldw 0($key),$s0 + _ror $acc2,16,$acc2 + xor $acc1,$t0,$t0 + ldw 4($key),$s1 + _ror $acc3,24,$acc3 + xor $acc2,$t0,$t0 + ldw 8($key),$s2 + _ror $acc5,8,$acc5 + xor $acc3,$t0,$t0 + ldw 12($key),$s3 + _ror $acc6,16,$acc6 + xor $acc4,$t1,$t1 + _ror $acc7,24,$acc7 + xor $acc5,$t1,$t1 + _ror $acc9,8,$acc9 + xor $acc6,$t1,$t1 + _ror $acc10,16,$acc10 + xor $acc7,$t1,$t1 + _ror $acc11,24,$acc11 + xor $acc8,$t2,$t2 + _ror $acc13,8,$acc13 + xor $acc9,$t2,$t2 + _ror $acc14,16,$acc14 + xor $acc10,$t2,$t2 + _ror $acc15,24,$acc15 + xor $acc11,$t2,$t2 + xor $acc12,$acc14,$acc14 + xor $acc13,$t3,$t3 + _srm $t0,24,$acc0 + xor $acc14,$t3,$t3 + xor $acc15,$t3,$t3 + _srm $t3,16,$acc1 + + _srm $t2,8,$acc2 + ldbx $acc0($rounds),$acc0 + _srm $t1,24,$acc4 + ldbx $acc1($rounds),$acc1 + _srm $t0,16,$acc5 + _srm $t1,0,$acc3 + ldbx $acc2($rounds),$acc2 + ldbx $acc3($rounds),$acc3 + _srm $t3,8,$acc6 + ldbx $acc4($rounds),$acc4 + _srm $t2,24,$acc8 + ldbx $acc5($rounds),$acc5 + _srm $t1,16,$acc9 + _srm $t2,0,$acc7 + ldbx $acc6($rounds),$acc6 + ldbx $acc7($rounds),$acc7 + _srm $t0,8,$acc10 + ldbx $acc8($rounds),$acc8 + _srm $t3,24,$acc12 + ldbx $acc9($rounds),$acc9 + _srm $t2,16,$acc13 + _srm $t3,0,$acc11 + ldbx $acc10($rounds),$acc10 + _srm $t1,8,$acc14 + ldbx $acc11($rounds),$acc11 + ldbx $acc12($rounds),$acc12 + ldbx $acc13($rounds),$acc13 + _srm $t0,0,$acc15 + ldbx $acc14($rounds),$acc14 + + dep $acc0,7,8,$acc3 + ldbx $acc15($rounds),$acc15 + dep $acc4,7,8,$acc7 + dep $acc1,15,8,$acc3 + dep $acc5,15,8,$acc7 + dep $acc2,23,8,$acc3 + dep $acc6,23,8,$acc7 + xor $acc3,$s0,$s0 + xor $acc7,$s1,$s1 + dep $acc8,7,8,$acc11 + dep $acc12,7,8,$acc15 + dep $acc9,15,8,$acc11 + dep $acc13,15,8,$acc15 + dep $acc10,23,8,$acc11 + dep $acc14,23,8,$acc15 + xor $acc11,$s2,$s2 + + bv (%r31) + .EXIT + xor $acc15,$s3,$s3 + .PROCEND + + .ALIGN 64 +L\$AES_Td + .WORD 0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96 + .WORD 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393 + .WORD 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25 + .WORD 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f + .WORD 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1 + .WORD 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6 + .WORD 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da + .WORD 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844 + .WORD 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd + .WORD 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4 + .WORD 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45 + .WORD 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94 + .WORD 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7 + .WORD 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a + .WORD 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5 + .WORD 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c + .WORD 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1 + .WORD 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a + .WORD 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75 + .WORD 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051 + .WORD 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46 + .WORD 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff + .WORD 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77 + .WORD 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb + .WORD 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000 + .WORD 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e + .WORD 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927 + .WORD 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a + .WORD 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e + .WORD 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16 + .WORD 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d + .WORD 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8 + .WORD 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd + .WORD 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34 + .WORD 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163 + .WORD 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120 + .WORD 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d + .WORD 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0 + .WORD 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422 + .WORD 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef + .WORD 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36 + .WORD 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4 + .WORD 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662 + .WORD 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5 + .WORD 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3 + .WORD 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b + .WORD 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8 + .WORD 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6 + .WORD 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6 + .WORD 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0 + .WORD 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815 + .WORD 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f + .WORD 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df + .WORD 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f + .WORD 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e + .WORD 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713 + .WORD 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89 + .WORD 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c + .WORD 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf + .WORD 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86 + .WORD 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f + .WORD 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541 + .WORD 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190 + .WORD 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742 + .BYTE 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38 + .BYTE 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb + .BYTE 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87 + .BYTE 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb + .BYTE 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d + .BYTE 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e + .BYTE 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2 + .BYTE 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 + .BYTE 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16 + .BYTE 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 + .BYTE 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda + .BYTE 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 + .BYTE 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a + .BYTE 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 + .BYTE 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02 + .BYTE 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b + .BYTE 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea + .BYTE 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 + .BYTE 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85 + .BYTE 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e + .BYTE 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89 + .BYTE 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b + .BYTE 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20 + .BYTE 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 + .BYTE 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31 + .BYTE 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f + .BYTE 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d + .BYTE 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef + .BYTE 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0 + .BYTE 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 + .BYTE 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26 + .BYTE 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d + .STRINGZ "AES for PA-RISC, CRYPTOGAMS by " +___ + +if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler/) { + $gnuas = 1; +} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/ge; + + # translate made up instructions: _ror, _srm + s/_ror(\s+)(%r[0-9]+),/shd$1$2,$2,/ or + + s/_srm(\s+%r[0-9]+),([0-9]+),/ + $SIZE_T==4 ? sprintf("extru%s,%d,8,",$1,31-$2) + : sprintf("extrd,u%s,%d,8,",$1,63-$2)/e; + + s/(\.LEVEL\s+2\.0)W/$1w/ if ($gnuas && $SIZE_T==8); + s/\.SPACE\s+\$TEXT\$/.text/ if ($gnuas && $SIZE_T==8); + s/\.SUBSPA.*// if ($gnuas && $SIZE_T==8); + s/,\*/,/ if ($SIZE_T==4); + s/\bbv\b(.*\(%r2\))/bve$1/ if ($SIZE_T==8); + + print $_,"\n"; +} +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-ppc.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-ppc.pl new file mode 100644 index 000000000..ca69df4c3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-ppc.pl @@ -0,0 +1,1459 @@ +#! /usr/bin/env perl +# Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# Needs more work: key setup, CBC routine... +# +# ppc_AES_[en|de]crypt perform at 18 cycles per byte processed with +# 128-bit key, which is ~40% better than 64-bit code generated by gcc +# 4.0. But these are not the ones currently used! Their "compact" +# counterparts are, for security reason. ppc_AES_encrypt_compact runs +# at 1/2 of ppc_AES_encrypt speed, while ppc_AES_decrypt_compact - +# at 1/3 of ppc_AES_decrypt. + +# February 2010 +# +# Rescheduling instructions to favour Power6 pipeline gave 10% +# performance improvement on the platform in question (and marginal +# improvement even on others). It should be noted that Power6 fails +# to process byte in 18 cycles, only in 23, because it fails to issue +# 4 load instructions in two cycles, only in 3. As result non-compact +# block subroutines are 25% slower than one would expect. Compact +# functions scale better, because they have pure computational part, +# which scales perfectly with clock frequency. To be specific +# ppc_AES_encrypt_compact operates at 42 cycles per byte, while +# ppc_AES_decrypt_compact - at 55 (in 64-bit build). + +$flavour = shift; + +if ($flavour =~ /64/) { + $SIZE_T =8; + $LRSAVE =2*$SIZE_T; + $STU ="stdu"; + $POP ="ld"; + $PUSH ="std"; +} elsif ($flavour =~ /32/) { + $SIZE_T =4; + $LRSAVE =$SIZE_T; + $STU ="stwu"; + $POP ="lwz"; + $PUSH ="stw"; +} else { die "nonsense $flavour"; } + +$LITTLE_ENDIAN = ($flavour=~/le$/) ? $SIZE_T : 0; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or +die "can't locate ppc-xlate.pl"; + +open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!"; + +$FRAME=32*$SIZE_T; + +sub _data_word() +{ my $i; + while(defined($i=shift)) { $code.=sprintf"\t.long\t0x%08x,0x%08x\n",$i,$i; } +} + +$sp="r1"; +$toc="r2"; +$inp="r3"; +$out="r4"; +$key="r5"; + +$Tbl0="r3"; +$Tbl1="r6"; +$Tbl2="r7"; +$Tbl3=$out; # stay away from "r2"; $out is offloaded to stack + +$s0="r8"; +$s1="r9"; +$s2="r10"; +$s3="r11"; + +$t0="r12"; +$t1="r0"; # stay away from "r13"; +$t2="r14"; +$t3="r15"; + +$acc00="r16"; +$acc01="r17"; +$acc02="r18"; +$acc03="r19"; + +$acc04="r20"; +$acc05="r21"; +$acc06="r22"; +$acc07="r23"; + +$acc08="r24"; +$acc09="r25"; +$acc10="r26"; +$acc11="r27"; + +$acc12="r28"; +$acc13="r29"; +$acc14="r30"; +$acc15="r31"; + +$mask80=$Tbl2; +$mask1b=$Tbl3; + +$code.=<<___; +.machine "any" +.text + +.align 7 +LAES_Te: + mflr r0 + bcl 20,31,\$+4 + mflr $Tbl0 ; vvvvv "distance" between . and 1st data entry + addi $Tbl0,$Tbl0,`128-8` + mtlr r0 + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 + .space `64-9*4` +LAES_Td: + mflr r0 + bcl 20,31,\$+4 + mflr $Tbl0 ; vvvvvvvv "distance" between . and 1st data entry + addi $Tbl0,$Tbl0,`128-64-8+2048+256` + mtlr r0 + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 + .space `128-64-9*4` +___ +&_data_word( + 0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, + 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, + 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, + 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, + 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, + 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, + 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, + 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, + 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, + 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, + 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, + 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f, + 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, + 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, + 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, + 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, + 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, + 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, + 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, + 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, + 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, + 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, + 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, + 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, + 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, + 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, + 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, + 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, + 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, + 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, + 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, + 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d, + 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, + 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, + 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, + 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, + 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, + 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, + 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, + 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, + 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, + 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, + 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, + 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b, + 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, + 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, + 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, + 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818, + 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, + 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, + 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, + 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, + 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, + 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, + 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, + 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, + 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, + 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, + 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, + 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a, + 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, + 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, + 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, + 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a); +$code.=<<___; +.byte 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5 +.byte 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76 +.byte 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0 +.byte 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0 +.byte 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc +.byte 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15 +.byte 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a +.byte 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75 +.byte 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0 +.byte 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84 +.byte 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b +.byte 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf +.byte 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85 +.byte 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8 +.byte 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5 +.byte 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2 +.byte 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17 +.byte 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73 +.byte 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88 +.byte 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb +.byte 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c +.byte 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79 +.byte 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9 +.byte 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08 +.byte 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6 +.byte 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a +.byte 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e +.byte 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e +.byte 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94 +.byte 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf +.byte 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68 +.byte 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +___ +&_data_word( + 0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, + 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, + 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, + 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, + 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, + 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, + 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, + 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844, + 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, + 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, + 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, + 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94, + 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, + 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a, + 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, + 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c, + 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, + 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, + 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, + 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, + 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, + 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, + 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, + 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, + 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, + 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, + 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, + 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a, + 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, + 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16, + 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, + 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8, + 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, + 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, + 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, + 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120, + 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, + 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, + 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, + 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, + 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, + 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, + 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, + 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5, + 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, + 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, + 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, + 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6, + 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, + 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0, + 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, + 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f, + 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, + 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, + 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, + 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, + 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, + 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, + 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, + 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86, + 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, + 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, + 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, + 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742); +$code.=<<___; +.byte 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38 +.byte 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb +.byte 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87 +.byte 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb +.byte 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d +.byte 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e +.byte 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2 +.byte 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 +.byte 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16 +.byte 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 +.byte 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda +.byte 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 +.byte 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a +.byte 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 +.byte 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02 +.byte 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b +.byte 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea +.byte 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 +.byte 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85 +.byte 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e +.byte 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89 +.byte 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b +.byte 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20 +.byte 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 +.byte 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31 +.byte 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f +.byte 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d +.byte 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef +.byte 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0 +.byte 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 +.byte 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26 +.byte 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d + + +.globl .AES_encrypt +.align 7 +.AES_encrypt: + $STU $sp,-$FRAME($sp) + mflr r0 + + $PUSH $out,`$FRAME-$SIZE_T*19`($sp) + $PUSH r14,`$FRAME-$SIZE_T*18`($sp) + $PUSH r15,`$FRAME-$SIZE_T*17`($sp) + $PUSH r16,`$FRAME-$SIZE_T*16`($sp) + $PUSH r17,`$FRAME-$SIZE_T*15`($sp) + $PUSH r18,`$FRAME-$SIZE_T*14`($sp) + $PUSH r19,`$FRAME-$SIZE_T*13`($sp) + $PUSH r20,`$FRAME-$SIZE_T*12`($sp) + $PUSH r21,`$FRAME-$SIZE_T*11`($sp) + $PUSH r22,`$FRAME-$SIZE_T*10`($sp) + $PUSH r23,`$FRAME-$SIZE_T*9`($sp) + $PUSH r24,`$FRAME-$SIZE_T*8`($sp) + $PUSH r25,`$FRAME-$SIZE_T*7`($sp) + $PUSH r26,`$FRAME-$SIZE_T*6`($sp) + $PUSH r27,`$FRAME-$SIZE_T*5`($sp) + $PUSH r28,`$FRAME-$SIZE_T*4`($sp) + $PUSH r29,`$FRAME-$SIZE_T*3`($sp) + $PUSH r30,`$FRAME-$SIZE_T*2`($sp) + $PUSH r31,`$FRAME-$SIZE_T*1`($sp) + $PUSH r0,`$FRAME+$LRSAVE`($sp) + + andi. $t0,$inp,3 + andi. $t1,$out,3 + or. $t0,$t0,$t1 + bne Lenc_unaligned + +Lenc_unaligned_ok: +___ +$code.=<<___ if (!$LITTLE_ENDIAN); + lwz $s0,0($inp) + lwz $s1,4($inp) + lwz $s2,8($inp) + lwz $s3,12($inp) +___ +$code.=<<___ if ($LITTLE_ENDIAN); + lwz $t0,0($inp) + lwz $t1,4($inp) + lwz $t2,8($inp) + lwz $t3,12($inp) + rotlwi $s0,$t0,8 + rotlwi $s1,$t1,8 + rotlwi $s2,$t2,8 + rotlwi $s3,$t3,8 + rlwimi $s0,$t0,24,0,7 + rlwimi $s1,$t1,24,0,7 + rlwimi $s2,$t2,24,0,7 + rlwimi $s3,$t3,24,0,7 + rlwimi $s0,$t0,24,16,23 + rlwimi $s1,$t1,24,16,23 + rlwimi $s2,$t2,24,16,23 + rlwimi $s3,$t3,24,16,23 +___ +$code.=<<___; + bl LAES_Te + bl Lppc_AES_encrypt_compact + $POP $out,`$FRAME-$SIZE_T*19`($sp) +___ +$code.=<<___ if ($LITTLE_ENDIAN); + rotlwi $t0,$s0,8 + rotlwi $t1,$s1,8 + rotlwi $t2,$s2,8 + rotlwi $t3,$s3,8 + rlwimi $t0,$s0,24,0,7 + rlwimi $t1,$s1,24,0,7 + rlwimi $t2,$s2,24,0,7 + rlwimi $t3,$s3,24,0,7 + rlwimi $t0,$s0,24,16,23 + rlwimi $t1,$s1,24,16,23 + rlwimi $t2,$s2,24,16,23 + rlwimi $t3,$s3,24,16,23 + stw $t0,0($out) + stw $t1,4($out) + stw $t2,8($out) + stw $t3,12($out) +___ +$code.=<<___ if (!$LITTLE_ENDIAN); + stw $s0,0($out) + stw $s1,4($out) + stw $s2,8($out) + stw $s3,12($out) +___ +$code.=<<___; + b Lenc_done + +Lenc_unaligned: + subfic $t0,$inp,4096 + subfic $t1,$out,4096 + andi. $t0,$t0,4096-16 + beq Lenc_xpage + andi. $t1,$t1,4096-16 + bne Lenc_unaligned_ok + +Lenc_xpage: + lbz $acc00,0($inp) + lbz $acc01,1($inp) + lbz $acc02,2($inp) + lbz $s0,3($inp) + lbz $acc04,4($inp) + lbz $acc05,5($inp) + lbz $acc06,6($inp) + lbz $s1,7($inp) + lbz $acc08,8($inp) + lbz $acc09,9($inp) + lbz $acc10,10($inp) + insrwi $s0,$acc00,8,0 + lbz $s2,11($inp) + insrwi $s1,$acc04,8,0 + lbz $acc12,12($inp) + insrwi $s0,$acc01,8,8 + lbz $acc13,13($inp) + insrwi $s1,$acc05,8,8 + lbz $acc14,14($inp) + insrwi $s0,$acc02,8,16 + lbz $s3,15($inp) + insrwi $s1,$acc06,8,16 + insrwi $s2,$acc08,8,0 + insrwi $s3,$acc12,8,0 + insrwi $s2,$acc09,8,8 + insrwi $s3,$acc13,8,8 + insrwi $s2,$acc10,8,16 + insrwi $s3,$acc14,8,16 + + bl LAES_Te + bl Lppc_AES_encrypt_compact + $POP $out,`$FRAME-$SIZE_T*19`($sp) + + extrwi $acc00,$s0,8,0 + extrwi $acc01,$s0,8,8 + stb $acc00,0($out) + extrwi $acc02,$s0,8,16 + stb $acc01,1($out) + stb $acc02,2($out) + extrwi $acc04,$s1,8,0 + stb $s0,3($out) + extrwi $acc05,$s1,8,8 + stb $acc04,4($out) + extrwi $acc06,$s1,8,16 + stb $acc05,5($out) + stb $acc06,6($out) + extrwi $acc08,$s2,8,0 + stb $s1,7($out) + extrwi $acc09,$s2,8,8 + stb $acc08,8($out) + extrwi $acc10,$s2,8,16 + stb $acc09,9($out) + stb $acc10,10($out) + extrwi $acc12,$s3,8,0 + stb $s2,11($out) + extrwi $acc13,$s3,8,8 + stb $acc12,12($out) + extrwi $acc14,$s3,8,16 + stb $acc13,13($out) + stb $acc14,14($out) + stb $s3,15($out) + +Lenc_done: + $POP r0,`$FRAME+$LRSAVE`($sp) + $POP r14,`$FRAME-$SIZE_T*18`($sp) + $POP r15,`$FRAME-$SIZE_T*17`($sp) + $POP r16,`$FRAME-$SIZE_T*16`($sp) + $POP r17,`$FRAME-$SIZE_T*15`($sp) + $POP r18,`$FRAME-$SIZE_T*14`($sp) + $POP r19,`$FRAME-$SIZE_T*13`($sp) + $POP r20,`$FRAME-$SIZE_T*12`($sp) + $POP r21,`$FRAME-$SIZE_T*11`($sp) + $POP r22,`$FRAME-$SIZE_T*10`($sp) + $POP r23,`$FRAME-$SIZE_T*9`($sp) + $POP r24,`$FRAME-$SIZE_T*8`($sp) + $POP r25,`$FRAME-$SIZE_T*7`($sp) + $POP r26,`$FRAME-$SIZE_T*6`($sp) + $POP r27,`$FRAME-$SIZE_T*5`($sp) + $POP r28,`$FRAME-$SIZE_T*4`($sp) + $POP r29,`$FRAME-$SIZE_T*3`($sp) + $POP r30,`$FRAME-$SIZE_T*2`($sp) + $POP r31,`$FRAME-$SIZE_T*1`($sp) + mtlr r0 + addi $sp,$sp,$FRAME + blr + .long 0 + .byte 0,12,4,1,0x80,18,3,0 + .long 0 + +.align 5 +Lppc_AES_encrypt: + lwz $acc00,240($key) + addi $Tbl1,$Tbl0,3 + lwz $t0,0($key) + addi $Tbl2,$Tbl0,2 + lwz $t1,4($key) + addi $Tbl3,$Tbl0,1 + lwz $t2,8($key) + addi $acc00,$acc00,-1 + lwz $t3,12($key) + addi $key,$key,16 + xor $s0,$s0,$t0 + xor $s1,$s1,$t1 + xor $s2,$s2,$t2 + xor $s3,$s3,$t3 + mtctr $acc00 +.align 4 +Lenc_loop: + rlwinm $acc00,$s0,`32-24+3`,21,28 + rlwinm $acc01,$s1,`32-24+3`,21,28 + rlwinm $acc02,$s2,`32-24+3`,21,28 + rlwinm $acc03,$s3,`32-24+3`,21,28 + lwz $t0,0($key) + rlwinm $acc04,$s1,`32-16+3`,21,28 + lwz $t1,4($key) + rlwinm $acc05,$s2,`32-16+3`,21,28 + lwz $t2,8($key) + rlwinm $acc06,$s3,`32-16+3`,21,28 + lwz $t3,12($key) + rlwinm $acc07,$s0,`32-16+3`,21,28 + lwzx $acc00,$Tbl0,$acc00 + rlwinm $acc08,$s2,`32-8+3`,21,28 + lwzx $acc01,$Tbl0,$acc01 + rlwinm $acc09,$s3,`32-8+3`,21,28 + lwzx $acc02,$Tbl0,$acc02 + rlwinm $acc10,$s0,`32-8+3`,21,28 + lwzx $acc03,$Tbl0,$acc03 + rlwinm $acc11,$s1,`32-8+3`,21,28 + lwzx $acc04,$Tbl1,$acc04 + rlwinm $acc12,$s3,`0+3`,21,28 + lwzx $acc05,$Tbl1,$acc05 + rlwinm $acc13,$s0,`0+3`,21,28 + lwzx $acc06,$Tbl1,$acc06 + rlwinm $acc14,$s1,`0+3`,21,28 + lwzx $acc07,$Tbl1,$acc07 + rlwinm $acc15,$s2,`0+3`,21,28 + lwzx $acc08,$Tbl2,$acc08 + xor $t0,$t0,$acc00 + lwzx $acc09,$Tbl2,$acc09 + xor $t1,$t1,$acc01 + lwzx $acc10,$Tbl2,$acc10 + xor $t2,$t2,$acc02 + lwzx $acc11,$Tbl2,$acc11 + xor $t3,$t3,$acc03 + lwzx $acc12,$Tbl3,$acc12 + xor $t0,$t0,$acc04 + lwzx $acc13,$Tbl3,$acc13 + xor $t1,$t1,$acc05 + lwzx $acc14,$Tbl3,$acc14 + xor $t2,$t2,$acc06 + lwzx $acc15,$Tbl3,$acc15 + xor $t3,$t3,$acc07 + xor $t0,$t0,$acc08 + xor $t1,$t1,$acc09 + xor $t2,$t2,$acc10 + xor $t3,$t3,$acc11 + xor $s0,$t0,$acc12 + xor $s1,$t1,$acc13 + xor $s2,$t2,$acc14 + xor $s3,$t3,$acc15 + addi $key,$key,16 + bdnz Lenc_loop + + addi $Tbl2,$Tbl0,2048 + nop + lwz $t0,0($key) + rlwinm $acc00,$s0,`32-24`,24,31 + lwz $t1,4($key) + rlwinm $acc01,$s1,`32-24`,24,31 + lwz $t2,8($key) + rlwinm $acc02,$s2,`32-24`,24,31 + lwz $t3,12($key) + rlwinm $acc03,$s3,`32-24`,24,31 + lwz $acc08,`2048+0`($Tbl0) ! prefetch Te4 + rlwinm $acc04,$s1,`32-16`,24,31 + lwz $acc09,`2048+32`($Tbl0) + rlwinm $acc05,$s2,`32-16`,24,31 + lwz $acc10,`2048+64`($Tbl0) + rlwinm $acc06,$s3,`32-16`,24,31 + lwz $acc11,`2048+96`($Tbl0) + rlwinm $acc07,$s0,`32-16`,24,31 + lwz $acc12,`2048+128`($Tbl0) + rlwinm $acc08,$s2,`32-8`,24,31 + lwz $acc13,`2048+160`($Tbl0) + rlwinm $acc09,$s3,`32-8`,24,31 + lwz $acc14,`2048+192`($Tbl0) + rlwinm $acc10,$s0,`32-8`,24,31 + lwz $acc15,`2048+224`($Tbl0) + rlwinm $acc11,$s1,`32-8`,24,31 + lbzx $acc00,$Tbl2,$acc00 + rlwinm $acc12,$s3,`0`,24,31 + lbzx $acc01,$Tbl2,$acc01 + rlwinm $acc13,$s0,`0`,24,31 + lbzx $acc02,$Tbl2,$acc02 + rlwinm $acc14,$s1,`0`,24,31 + lbzx $acc03,$Tbl2,$acc03 + rlwinm $acc15,$s2,`0`,24,31 + lbzx $acc04,$Tbl2,$acc04 + rlwinm $s0,$acc00,24,0,7 + lbzx $acc05,$Tbl2,$acc05 + rlwinm $s1,$acc01,24,0,7 + lbzx $acc06,$Tbl2,$acc06 + rlwinm $s2,$acc02,24,0,7 + lbzx $acc07,$Tbl2,$acc07 + rlwinm $s3,$acc03,24,0,7 + lbzx $acc08,$Tbl2,$acc08 + rlwimi $s0,$acc04,16,8,15 + lbzx $acc09,$Tbl2,$acc09 + rlwimi $s1,$acc05,16,8,15 + lbzx $acc10,$Tbl2,$acc10 + rlwimi $s2,$acc06,16,8,15 + lbzx $acc11,$Tbl2,$acc11 + rlwimi $s3,$acc07,16,8,15 + lbzx $acc12,$Tbl2,$acc12 + rlwimi $s0,$acc08,8,16,23 + lbzx $acc13,$Tbl2,$acc13 + rlwimi $s1,$acc09,8,16,23 + lbzx $acc14,$Tbl2,$acc14 + rlwimi $s2,$acc10,8,16,23 + lbzx $acc15,$Tbl2,$acc15 + rlwimi $s3,$acc11,8,16,23 + or $s0,$s0,$acc12 + or $s1,$s1,$acc13 + or $s2,$s2,$acc14 + or $s3,$s3,$acc15 + xor $s0,$s0,$t0 + xor $s1,$s1,$t1 + xor $s2,$s2,$t2 + xor $s3,$s3,$t3 + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 + +.align 4 +Lppc_AES_encrypt_compact: + lwz $acc00,240($key) + addi $Tbl1,$Tbl0,2048 + lwz $t0,0($key) + lis $mask80,0x8080 + lwz $t1,4($key) + lis $mask1b,0x1b1b + lwz $t2,8($key) + ori $mask80,$mask80,0x8080 + lwz $t3,12($key) + ori $mask1b,$mask1b,0x1b1b + addi $key,$key,16 + mtctr $acc00 +.align 4 +Lenc_compact_loop: + xor $s0,$s0,$t0 + xor $s1,$s1,$t1 + rlwinm $acc00,$s0,`32-24`,24,31 + xor $s2,$s2,$t2 + rlwinm $acc01,$s1,`32-24`,24,31 + xor $s3,$s3,$t3 + rlwinm $acc02,$s2,`32-24`,24,31 + rlwinm $acc03,$s3,`32-24`,24,31 + rlwinm $acc04,$s1,`32-16`,24,31 + rlwinm $acc05,$s2,`32-16`,24,31 + rlwinm $acc06,$s3,`32-16`,24,31 + rlwinm $acc07,$s0,`32-16`,24,31 + lbzx $acc00,$Tbl1,$acc00 + rlwinm $acc08,$s2,`32-8`,24,31 + lbzx $acc01,$Tbl1,$acc01 + rlwinm $acc09,$s3,`32-8`,24,31 + lbzx $acc02,$Tbl1,$acc02 + rlwinm $acc10,$s0,`32-8`,24,31 + lbzx $acc03,$Tbl1,$acc03 + rlwinm $acc11,$s1,`32-8`,24,31 + lbzx $acc04,$Tbl1,$acc04 + rlwinm $acc12,$s3,`0`,24,31 + lbzx $acc05,$Tbl1,$acc05 + rlwinm $acc13,$s0,`0`,24,31 + lbzx $acc06,$Tbl1,$acc06 + rlwinm $acc14,$s1,`0`,24,31 + lbzx $acc07,$Tbl1,$acc07 + rlwinm $acc15,$s2,`0`,24,31 + lbzx $acc08,$Tbl1,$acc08 + rlwinm $s0,$acc00,24,0,7 + lbzx $acc09,$Tbl1,$acc09 + rlwinm $s1,$acc01,24,0,7 + lbzx $acc10,$Tbl1,$acc10 + rlwinm $s2,$acc02,24,0,7 + lbzx $acc11,$Tbl1,$acc11 + rlwinm $s3,$acc03,24,0,7 + lbzx $acc12,$Tbl1,$acc12 + rlwimi $s0,$acc04,16,8,15 + lbzx $acc13,$Tbl1,$acc13 + rlwimi $s1,$acc05,16,8,15 + lbzx $acc14,$Tbl1,$acc14 + rlwimi $s2,$acc06,16,8,15 + lbzx $acc15,$Tbl1,$acc15 + rlwimi $s3,$acc07,16,8,15 + rlwimi $s0,$acc08,8,16,23 + rlwimi $s1,$acc09,8,16,23 + rlwimi $s2,$acc10,8,16,23 + rlwimi $s3,$acc11,8,16,23 + lwz $t0,0($key) + or $s0,$s0,$acc12 + lwz $t1,4($key) + or $s1,$s1,$acc13 + lwz $t2,8($key) + or $s2,$s2,$acc14 + lwz $t3,12($key) + or $s3,$s3,$acc15 + + addi $key,$key,16 + bdz Lenc_compact_done + + and $acc00,$s0,$mask80 # r1=r0&0x80808080 + and $acc01,$s1,$mask80 + and $acc02,$s2,$mask80 + and $acc03,$s3,$mask80 + srwi $acc04,$acc00,7 # r1>>7 + andc $acc08,$s0,$mask80 # r0&0x7f7f7f7f + srwi $acc05,$acc01,7 + andc $acc09,$s1,$mask80 + srwi $acc06,$acc02,7 + andc $acc10,$s2,$mask80 + srwi $acc07,$acc03,7 + andc $acc11,$s3,$mask80 + sub $acc00,$acc00,$acc04 # r1-(r1>>7) + sub $acc01,$acc01,$acc05 + sub $acc02,$acc02,$acc06 + sub $acc03,$acc03,$acc07 + add $acc08,$acc08,$acc08 # (r0&0x7f7f7f7f)<<1 + add $acc09,$acc09,$acc09 + add $acc10,$acc10,$acc10 + add $acc11,$acc11,$acc11 + and $acc00,$acc00,$mask1b # (r1-(r1>>7))&0x1b1b1b1b + and $acc01,$acc01,$mask1b + and $acc02,$acc02,$mask1b + and $acc03,$acc03,$mask1b + xor $acc00,$acc00,$acc08 # r2 + xor $acc01,$acc01,$acc09 + rotlwi $acc12,$s0,16 # ROTATE(r0,16) + xor $acc02,$acc02,$acc10 + rotlwi $acc13,$s1,16 + xor $acc03,$acc03,$acc11 + rotlwi $acc14,$s2,16 + + xor $s0,$s0,$acc00 # r0^r2 + rotlwi $acc15,$s3,16 + xor $s1,$s1,$acc01 + rotrwi $s0,$s0,24 # ROTATE(r2^r0,24) + xor $s2,$s2,$acc02 + rotrwi $s1,$s1,24 + xor $s3,$s3,$acc03 + rotrwi $s2,$s2,24 + xor $s0,$s0,$acc00 # ROTATE(r2^r0,24)^r2 + rotrwi $s3,$s3,24 + xor $s1,$s1,$acc01 + xor $s2,$s2,$acc02 + xor $s3,$s3,$acc03 + rotlwi $acc08,$acc12,8 # ROTATE(r0,24) + xor $s0,$s0,$acc12 # + rotlwi $acc09,$acc13,8 + xor $s1,$s1,$acc13 + rotlwi $acc10,$acc14,8 + xor $s2,$s2,$acc14 + rotlwi $acc11,$acc15,8 + xor $s3,$s3,$acc15 + xor $s0,$s0,$acc08 # + xor $s1,$s1,$acc09 + xor $s2,$s2,$acc10 + xor $s3,$s3,$acc11 + + b Lenc_compact_loop +.align 4 +Lenc_compact_done: + xor $s0,$s0,$t0 + xor $s1,$s1,$t1 + xor $s2,$s2,$t2 + xor $s3,$s3,$t3 + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 +.size .AES_encrypt,.-.AES_encrypt + +.globl .AES_decrypt +.align 7 +.AES_decrypt: + $STU $sp,-$FRAME($sp) + mflr r0 + + $PUSH $out,`$FRAME-$SIZE_T*19`($sp) + $PUSH r14,`$FRAME-$SIZE_T*18`($sp) + $PUSH r15,`$FRAME-$SIZE_T*17`($sp) + $PUSH r16,`$FRAME-$SIZE_T*16`($sp) + $PUSH r17,`$FRAME-$SIZE_T*15`($sp) + $PUSH r18,`$FRAME-$SIZE_T*14`($sp) + $PUSH r19,`$FRAME-$SIZE_T*13`($sp) + $PUSH r20,`$FRAME-$SIZE_T*12`($sp) + $PUSH r21,`$FRAME-$SIZE_T*11`($sp) + $PUSH r22,`$FRAME-$SIZE_T*10`($sp) + $PUSH r23,`$FRAME-$SIZE_T*9`($sp) + $PUSH r24,`$FRAME-$SIZE_T*8`($sp) + $PUSH r25,`$FRAME-$SIZE_T*7`($sp) + $PUSH r26,`$FRAME-$SIZE_T*6`($sp) + $PUSH r27,`$FRAME-$SIZE_T*5`($sp) + $PUSH r28,`$FRAME-$SIZE_T*4`($sp) + $PUSH r29,`$FRAME-$SIZE_T*3`($sp) + $PUSH r30,`$FRAME-$SIZE_T*2`($sp) + $PUSH r31,`$FRAME-$SIZE_T*1`($sp) + $PUSH r0,`$FRAME+$LRSAVE`($sp) + + andi. $t0,$inp,3 + andi. $t1,$out,3 + or. $t0,$t0,$t1 + bne Ldec_unaligned + +Ldec_unaligned_ok: +___ +$code.=<<___ if (!$LITTLE_ENDIAN); + lwz $s0,0($inp) + lwz $s1,4($inp) + lwz $s2,8($inp) + lwz $s3,12($inp) +___ +$code.=<<___ if ($LITTLE_ENDIAN); + lwz $t0,0($inp) + lwz $t1,4($inp) + lwz $t2,8($inp) + lwz $t3,12($inp) + rotlwi $s0,$t0,8 + rotlwi $s1,$t1,8 + rotlwi $s2,$t2,8 + rotlwi $s3,$t3,8 + rlwimi $s0,$t0,24,0,7 + rlwimi $s1,$t1,24,0,7 + rlwimi $s2,$t2,24,0,7 + rlwimi $s3,$t3,24,0,7 + rlwimi $s0,$t0,24,16,23 + rlwimi $s1,$t1,24,16,23 + rlwimi $s2,$t2,24,16,23 + rlwimi $s3,$t3,24,16,23 +___ +$code.=<<___; + bl LAES_Td + bl Lppc_AES_decrypt_compact + $POP $out,`$FRAME-$SIZE_T*19`($sp) +___ +$code.=<<___ if ($LITTLE_ENDIAN); + rotlwi $t0,$s0,8 + rotlwi $t1,$s1,8 + rotlwi $t2,$s2,8 + rotlwi $t3,$s3,8 + rlwimi $t0,$s0,24,0,7 + rlwimi $t1,$s1,24,0,7 + rlwimi $t2,$s2,24,0,7 + rlwimi $t3,$s3,24,0,7 + rlwimi $t0,$s0,24,16,23 + rlwimi $t1,$s1,24,16,23 + rlwimi $t2,$s2,24,16,23 + rlwimi $t3,$s3,24,16,23 + stw $t0,0($out) + stw $t1,4($out) + stw $t2,8($out) + stw $t3,12($out) +___ +$code.=<<___ if (!$LITTLE_ENDIAN); + stw $s0,0($out) + stw $s1,4($out) + stw $s2,8($out) + stw $s3,12($out) +___ +$code.=<<___; + b Ldec_done + +Ldec_unaligned: + subfic $t0,$inp,4096 + subfic $t1,$out,4096 + andi. $t0,$t0,4096-16 + beq Ldec_xpage + andi. $t1,$t1,4096-16 + bne Ldec_unaligned_ok + +Ldec_xpage: + lbz $acc00,0($inp) + lbz $acc01,1($inp) + lbz $acc02,2($inp) + lbz $s0,3($inp) + lbz $acc04,4($inp) + lbz $acc05,5($inp) + lbz $acc06,6($inp) + lbz $s1,7($inp) + lbz $acc08,8($inp) + lbz $acc09,9($inp) + lbz $acc10,10($inp) + insrwi $s0,$acc00,8,0 + lbz $s2,11($inp) + insrwi $s1,$acc04,8,0 + lbz $acc12,12($inp) + insrwi $s0,$acc01,8,8 + lbz $acc13,13($inp) + insrwi $s1,$acc05,8,8 + lbz $acc14,14($inp) + insrwi $s0,$acc02,8,16 + lbz $s3,15($inp) + insrwi $s1,$acc06,8,16 + insrwi $s2,$acc08,8,0 + insrwi $s3,$acc12,8,0 + insrwi $s2,$acc09,8,8 + insrwi $s3,$acc13,8,8 + insrwi $s2,$acc10,8,16 + insrwi $s3,$acc14,8,16 + + bl LAES_Td + bl Lppc_AES_decrypt_compact + $POP $out,`$FRAME-$SIZE_T*19`($sp) + + extrwi $acc00,$s0,8,0 + extrwi $acc01,$s0,8,8 + stb $acc00,0($out) + extrwi $acc02,$s0,8,16 + stb $acc01,1($out) + stb $acc02,2($out) + extrwi $acc04,$s1,8,0 + stb $s0,3($out) + extrwi $acc05,$s1,8,8 + stb $acc04,4($out) + extrwi $acc06,$s1,8,16 + stb $acc05,5($out) + stb $acc06,6($out) + extrwi $acc08,$s2,8,0 + stb $s1,7($out) + extrwi $acc09,$s2,8,8 + stb $acc08,8($out) + extrwi $acc10,$s2,8,16 + stb $acc09,9($out) + stb $acc10,10($out) + extrwi $acc12,$s3,8,0 + stb $s2,11($out) + extrwi $acc13,$s3,8,8 + stb $acc12,12($out) + extrwi $acc14,$s3,8,16 + stb $acc13,13($out) + stb $acc14,14($out) + stb $s3,15($out) + +Ldec_done: + $POP r0,`$FRAME+$LRSAVE`($sp) + $POP r14,`$FRAME-$SIZE_T*18`($sp) + $POP r15,`$FRAME-$SIZE_T*17`($sp) + $POP r16,`$FRAME-$SIZE_T*16`($sp) + $POP r17,`$FRAME-$SIZE_T*15`($sp) + $POP r18,`$FRAME-$SIZE_T*14`($sp) + $POP r19,`$FRAME-$SIZE_T*13`($sp) + $POP r20,`$FRAME-$SIZE_T*12`($sp) + $POP r21,`$FRAME-$SIZE_T*11`($sp) + $POP r22,`$FRAME-$SIZE_T*10`($sp) + $POP r23,`$FRAME-$SIZE_T*9`($sp) + $POP r24,`$FRAME-$SIZE_T*8`($sp) + $POP r25,`$FRAME-$SIZE_T*7`($sp) + $POP r26,`$FRAME-$SIZE_T*6`($sp) + $POP r27,`$FRAME-$SIZE_T*5`($sp) + $POP r28,`$FRAME-$SIZE_T*4`($sp) + $POP r29,`$FRAME-$SIZE_T*3`($sp) + $POP r30,`$FRAME-$SIZE_T*2`($sp) + $POP r31,`$FRAME-$SIZE_T*1`($sp) + mtlr r0 + addi $sp,$sp,$FRAME + blr + .long 0 + .byte 0,12,4,1,0x80,18,3,0 + .long 0 + +.align 5 +Lppc_AES_decrypt: + lwz $acc00,240($key) + addi $Tbl1,$Tbl0,3 + lwz $t0,0($key) + addi $Tbl2,$Tbl0,2 + lwz $t1,4($key) + addi $Tbl3,$Tbl0,1 + lwz $t2,8($key) + addi $acc00,$acc00,-1 + lwz $t3,12($key) + addi $key,$key,16 + xor $s0,$s0,$t0 + xor $s1,$s1,$t1 + xor $s2,$s2,$t2 + xor $s3,$s3,$t3 + mtctr $acc00 +.align 4 +Ldec_loop: + rlwinm $acc00,$s0,`32-24+3`,21,28 + rlwinm $acc01,$s1,`32-24+3`,21,28 + rlwinm $acc02,$s2,`32-24+3`,21,28 + rlwinm $acc03,$s3,`32-24+3`,21,28 + lwz $t0,0($key) + rlwinm $acc04,$s3,`32-16+3`,21,28 + lwz $t1,4($key) + rlwinm $acc05,$s0,`32-16+3`,21,28 + lwz $t2,8($key) + rlwinm $acc06,$s1,`32-16+3`,21,28 + lwz $t3,12($key) + rlwinm $acc07,$s2,`32-16+3`,21,28 + lwzx $acc00,$Tbl0,$acc00 + rlwinm $acc08,$s2,`32-8+3`,21,28 + lwzx $acc01,$Tbl0,$acc01 + rlwinm $acc09,$s3,`32-8+3`,21,28 + lwzx $acc02,$Tbl0,$acc02 + rlwinm $acc10,$s0,`32-8+3`,21,28 + lwzx $acc03,$Tbl0,$acc03 + rlwinm $acc11,$s1,`32-8+3`,21,28 + lwzx $acc04,$Tbl1,$acc04 + rlwinm $acc12,$s1,`0+3`,21,28 + lwzx $acc05,$Tbl1,$acc05 + rlwinm $acc13,$s2,`0+3`,21,28 + lwzx $acc06,$Tbl1,$acc06 + rlwinm $acc14,$s3,`0+3`,21,28 + lwzx $acc07,$Tbl1,$acc07 + rlwinm $acc15,$s0,`0+3`,21,28 + lwzx $acc08,$Tbl2,$acc08 + xor $t0,$t0,$acc00 + lwzx $acc09,$Tbl2,$acc09 + xor $t1,$t1,$acc01 + lwzx $acc10,$Tbl2,$acc10 + xor $t2,$t2,$acc02 + lwzx $acc11,$Tbl2,$acc11 + xor $t3,$t3,$acc03 + lwzx $acc12,$Tbl3,$acc12 + xor $t0,$t0,$acc04 + lwzx $acc13,$Tbl3,$acc13 + xor $t1,$t1,$acc05 + lwzx $acc14,$Tbl3,$acc14 + xor $t2,$t2,$acc06 + lwzx $acc15,$Tbl3,$acc15 + xor $t3,$t3,$acc07 + xor $t0,$t0,$acc08 + xor $t1,$t1,$acc09 + xor $t2,$t2,$acc10 + xor $t3,$t3,$acc11 + xor $s0,$t0,$acc12 + xor $s1,$t1,$acc13 + xor $s2,$t2,$acc14 + xor $s3,$t3,$acc15 + addi $key,$key,16 + bdnz Ldec_loop + + addi $Tbl2,$Tbl0,2048 + nop + lwz $t0,0($key) + rlwinm $acc00,$s0,`32-24`,24,31 + lwz $t1,4($key) + rlwinm $acc01,$s1,`32-24`,24,31 + lwz $t2,8($key) + rlwinm $acc02,$s2,`32-24`,24,31 + lwz $t3,12($key) + rlwinm $acc03,$s3,`32-24`,24,31 + lwz $acc08,`2048+0`($Tbl0) ! prefetch Td4 + rlwinm $acc04,$s3,`32-16`,24,31 + lwz $acc09,`2048+32`($Tbl0) + rlwinm $acc05,$s0,`32-16`,24,31 + lwz $acc10,`2048+64`($Tbl0) + lbzx $acc00,$Tbl2,$acc00 + lwz $acc11,`2048+96`($Tbl0) + lbzx $acc01,$Tbl2,$acc01 + lwz $acc12,`2048+128`($Tbl0) + rlwinm $acc06,$s1,`32-16`,24,31 + lwz $acc13,`2048+160`($Tbl0) + rlwinm $acc07,$s2,`32-16`,24,31 + lwz $acc14,`2048+192`($Tbl0) + rlwinm $acc08,$s2,`32-8`,24,31 + lwz $acc15,`2048+224`($Tbl0) + rlwinm $acc09,$s3,`32-8`,24,31 + lbzx $acc02,$Tbl2,$acc02 + rlwinm $acc10,$s0,`32-8`,24,31 + lbzx $acc03,$Tbl2,$acc03 + rlwinm $acc11,$s1,`32-8`,24,31 + lbzx $acc04,$Tbl2,$acc04 + rlwinm $acc12,$s1,`0`,24,31 + lbzx $acc05,$Tbl2,$acc05 + rlwinm $acc13,$s2,`0`,24,31 + lbzx $acc06,$Tbl2,$acc06 + rlwinm $acc14,$s3,`0`,24,31 + lbzx $acc07,$Tbl2,$acc07 + rlwinm $acc15,$s0,`0`,24,31 + lbzx $acc08,$Tbl2,$acc08 + rlwinm $s0,$acc00,24,0,7 + lbzx $acc09,$Tbl2,$acc09 + rlwinm $s1,$acc01,24,0,7 + lbzx $acc10,$Tbl2,$acc10 + rlwinm $s2,$acc02,24,0,7 + lbzx $acc11,$Tbl2,$acc11 + rlwinm $s3,$acc03,24,0,7 + lbzx $acc12,$Tbl2,$acc12 + rlwimi $s0,$acc04,16,8,15 + lbzx $acc13,$Tbl2,$acc13 + rlwimi $s1,$acc05,16,8,15 + lbzx $acc14,$Tbl2,$acc14 + rlwimi $s2,$acc06,16,8,15 + lbzx $acc15,$Tbl2,$acc15 + rlwimi $s3,$acc07,16,8,15 + rlwimi $s0,$acc08,8,16,23 + rlwimi $s1,$acc09,8,16,23 + rlwimi $s2,$acc10,8,16,23 + rlwimi $s3,$acc11,8,16,23 + or $s0,$s0,$acc12 + or $s1,$s1,$acc13 + or $s2,$s2,$acc14 + or $s3,$s3,$acc15 + xor $s0,$s0,$t0 + xor $s1,$s1,$t1 + xor $s2,$s2,$t2 + xor $s3,$s3,$t3 + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 + +.align 4 +Lppc_AES_decrypt_compact: + lwz $acc00,240($key) + addi $Tbl1,$Tbl0,2048 + lwz $t0,0($key) + lis $mask80,0x8080 + lwz $t1,4($key) + lis $mask1b,0x1b1b + lwz $t2,8($key) + ori $mask80,$mask80,0x8080 + lwz $t3,12($key) + ori $mask1b,$mask1b,0x1b1b + addi $key,$key,16 +___ +$code.=<<___ if ($SIZE_T==8); + insrdi $mask80,$mask80,32,0 + insrdi $mask1b,$mask1b,32,0 +___ +$code.=<<___; + mtctr $acc00 +.align 4 +Ldec_compact_loop: + xor $s0,$s0,$t0 + xor $s1,$s1,$t1 + rlwinm $acc00,$s0,`32-24`,24,31 + xor $s2,$s2,$t2 + rlwinm $acc01,$s1,`32-24`,24,31 + xor $s3,$s3,$t3 + rlwinm $acc02,$s2,`32-24`,24,31 + rlwinm $acc03,$s3,`32-24`,24,31 + rlwinm $acc04,$s3,`32-16`,24,31 + rlwinm $acc05,$s0,`32-16`,24,31 + rlwinm $acc06,$s1,`32-16`,24,31 + rlwinm $acc07,$s2,`32-16`,24,31 + lbzx $acc00,$Tbl1,$acc00 + rlwinm $acc08,$s2,`32-8`,24,31 + lbzx $acc01,$Tbl1,$acc01 + rlwinm $acc09,$s3,`32-8`,24,31 + lbzx $acc02,$Tbl1,$acc02 + rlwinm $acc10,$s0,`32-8`,24,31 + lbzx $acc03,$Tbl1,$acc03 + rlwinm $acc11,$s1,`32-8`,24,31 + lbzx $acc04,$Tbl1,$acc04 + rlwinm $acc12,$s1,`0`,24,31 + lbzx $acc05,$Tbl1,$acc05 + rlwinm $acc13,$s2,`0`,24,31 + lbzx $acc06,$Tbl1,$acc06 + rlwinm $acc14,$s3,`0`,24,31 + lbzx $acc07,$Tbl1,$acc07 + rlwinm $acc15,$s0,`0`,24,31 + lbzx $acc08,$Tbl1,$acc08 + rlwinm $s0,$acc00,24,0,7 + lbzx $acc09,$Tbl1,$acc09 + rlwinm $s1,$acc01,24,0,7 + lbzx $acc10,$Tbl1,$acc10 + rlwinm $s2,$acc02,24,0,7 + lbzx $acc11,$Tbl1,$acc11 + rlwinm $s3,$acc03,24,0,7 + lbzx $acc12,$Tbl1,$acc12 + rlwimi $s0,$acc04,16,8,15 + lbzx $acc13,$Tbl1,$acc13 + rlwimi $s1,$acc05,16,8,15 + lbzx $acc14,$Tbl1,$acc14 + rlwimi $s2,$acc06,16,8,15 + lbzx $acc15,$Tbl1,$acc15 + rlwimi $s3,$acc07,16,8,15 + rlwimi $s0,$acc08,8,16,23 + rlwimi $s1,$acc09,8,16,23 + rlwimi $s2,$acc10,8,16,23 + rlwimi $s3,$acc11,8,16,23 + lwz $t0,0($key) + or $s0,$s0,$acc12 + lwz $t1,4($key) + or $s1,$s1,$acc13 + lwz $t2,8($key) + or $s2,$s2,$acc14 + lwz $t3,12($key) + or $s3,$s3,$acc15 + + addi $key,$key,16 + bdz Ldec_compact_done +___ +$code.=<<___ if ($SIZE_T==8); + # vectorized permutation improves decrypt performance by 10% + insrdi $s0,$s1,32,0 + insrdi $s2,$s3,32,0 + + and $acc00,$s0,$mask80 # r1=r0&0x80808080 + and $acc02,$s2,$mask80 + srdi $acc04,$acc00,7 # r1>>7 + srdi $acc06,$acc02,7 + andc $acc08,$s0,$mask80 # r0&0x7f7f7f7f + andc $acc10,$s2,$mask80 + sub $acc00,$acc00,$acc04 # r1-(r1>>7) + sub $acc02,$acc02,$acc06 + add $acc08,$acc08,$acc08 # (r0&0x7f7f7f7f)<<1 + add $acc10,$acc10,$acc10 + and $acc00,$acc00,$mask1b # (r1-(r1>>7))&0x1b1b1b1b + and $acc02,$acc02,$mask1b + xor $acc00,$acc00,$acc08 # r2 + xor $acc02,$acc02,$acc10 + + and $acc04,$acc00,$mask80 # r1=r2&0x80808080 + and $acc06,$acc02,$mask80 + srdi $acc08,$acc04,7 # r1>>7 + srdi $acc10,$acc06,7 + andc $acc12,$acc00,$mask80 # r2&0x7f7f7f7f + andc $acc14,$acc02,$mask80 + sub $acc04,$acc04,$acc08 # r1-(r1>>7) + sub $acc06,$acc06,$acc10 + add $acc12,$acc12,$acc12 # (r2&0x7f7f7f7f)<<1 + add $acc14,$acc14,$acc14 + and $acc04,$acc04,$mask1b # (r1-(r1>>7))&0x1b1b1b1b + and $acc06,$acc06,$mask1b + xor $acc04,$acc04,$acc12 # r4 + xor $acc06,$acc06,$acc14 + + and $acc08,$acc04,$mask80 # r1=r4&0x80808080 + and $acc10,$acc06,$mask80 + srdi $acc12,$acc08,7 # r1>>7 + srdi $acc14,$acc10,7 + sub $acc08,$acc08,$acc12 # r1-(r1>>7) + sub $acc10,$acc10,$acc14 + andc $acc12,$acc04,$mask80 # r4&0x7f7f7f7f + andc $acc14,$acc06,$mask80 + add $acc12,$acc12,$acc12 # (r4&0x7f7f7f7f)<<1 + add $acc14,$acc14,$acc14 + and $acc08,$acc08,$mask1b # (r1-(r1>>7))&0x1b1b1b1b + and $acc10,$acc10,$mask1b + xor $acc08,$acc08,$acc12 # r8 + xor $acc10,$acc10,$acc14 + + xor $acc00,$acc00,$s0 # r2^r0 + xor $acc02,$acc02,$s2 + xor $acc04,$acc04,$s0 # r4^r0 + xor $acc06,$acc06,$s2 + + extrdi $acc01,$acc00,32,0 + extrdi $acc03,$acc02,32,0 + extrdi $acc05,$acc04,32,0 + extrdi $acc07,$acc06,32,0 + extrdi $acc09,$acc08,32,0 + extrdi $acc11,$acc10,32,0 +___ +$code.=<<___ if ($SIZE_T==4); + and $acc00,$s0,$mask80 # r1=r0&0x80808080 + and $acc01,$s1,$mask80 + and $acc02,$s2,$mask80 + and $acc03,$s3,$mask80 + srwi $acc04,$acc00,7 # r1>>7 + andc $acc08,$s0,$mask80 # r0&0x7f7f7f7f + srwi $acc05,$acc01,7 + andc $acc09,$s1,$mask80 + srwi $acc06,$acc02,7 + andc $acc10,$s2,$mask80 + srwi $acc07,$acc03,7 + andc $acc11,$s3,$mask80 + sub $acc00,$acc00,$acc04 # r1-(r1>>7) + sub $acc01,$acc01,$acc05 + sub $acc02,$acc02,$acc06 + sub $acc03,$acc03,$acc07 + add $acc08,$acc08,$acc08 # (r0&0x7f7f7f7f)<<1 + add $acc09,$acc09,$acc09 + add $acc10,$acc10,$acc10 + add $acc11,$acc11,$acc11 + and $acc00,$acc00,$mask1b # (r1-(r1>>7))&0x1b1b1b1b + and $acc01,$acc01,$mask1b + and $acc02,$acc02,$mask1b + and $acc03,$acc03,$mask1b + xor $acc00,$acc00,$acc08 # r2 + xor $acc01,$acc01,$acc09 + xor $acc02,$acc02,$acc10 + xor $acc03,$acc03,$acc11 + + and $acc04,$acc00,$mask80 # r1=r2&0x80808080 + and $acc05,$acc01,$mask80 + and $acc06,$acc02,$mask80 + and $acc07,$acc03,$mask80 + srwi $acc08,$acc04,7 # r1>>7 + andc $acc12,$acc00,$mask80 # r2&0x7f7f7f7f + srwi $acc09,$acc05,7 + andc $acc13,$acc01,$mask80 + srwi $acc10,$acc06,7 + andc $acc14,$acc02,$mask80 + srwi $acc11,$acc07,7 + andc $acc15,$acc03,$mask80 + sub $acc04,$acc04,$acc08 # r1-(r1>>7) + sub $acc05,$acc05,$acc09 + sub $acc06,$acc06,$acc10 + sub $acc07,$acc07,$acc11 + add $acc12,$acc12,$acc12 # (r2&0x7f7f7f7f)<<1 + add $acc13,$acc13,$acc13 + add $acc14,$acc14,$acc14 + add $acc15,$acc15,$acc15 + and $acc04,$acc04,$mask1b # (r1-(r1>>7))&0x1b1b1b1b + and $acc05,$acc05,$mask1b + and $acc06,$acc06,$mask1b + and $acc07,$acc07,$mask1b + xor $acc04,$acc04,$acc12 # r4 + xor $acc05,$acc05,$acc13 + xor $acc06,$acc06,$acc14 + xor $acc07,$acc07,$acc15 + + and $acc08,$acc04,$mask80 # r1=r4&0x80808080 + and $acc09,$acc05,$mask80 + srwi $acc12,$acc08,7 # r1>>7 + and $acc10,$acc06,$mask80 + srwi $acc13,$acc09,7 + and $acc11,$acc07,$mask80 + srwi $acc14,$acc10,7 + sub $acc08,$acc08,$acc12 # r1-(r1>>7) + srwi $acc15,$acc11,7 + sub $acc09,$acc09,$acc13 + sub $acc10,$acc10,$acc14 + sub $acc11,$acc11,$acc15 + andc $acc12,$acc04,$mask80 # r4&0x7f7f7f7f + andc $acc13,$acc05,$mask80 + andc $acc14,$acc06,$mask80 + andc $acc15,$acc07,$mask80 + add $acc12,$acc12,$acc12 # (r4&0x7f7f7f7f)<<1 + add $acc13,$acc13,$acc13 + add $acc14,$acc14,$acc14 + add $acc15,$acc15,$acc15 + and $acc08,$acc08,$mask1b # (r1-(r1>>7))&0x1b1b1b1b + and $acc09,$acc09,$mask1b + and $acc10,$acc10,$mask1b + and $acc11,$acc11,$mask1b + xor $acc08,$acc08,$acc12 # r8 + xor $acc09,$acc09,$acc13 + xor $acc10,$acc10,$acc14 + xor $acc11,$acc11,$acc15 + + xor $acc00,$acc00,$s0 # r2^r0 + xor $acc01,$acc01,$s1 + xor $acc02,$acc02,$s2 + xor $acc03,$acc03,$s3 + xor $acc04,$acc04,$s0 # r4^r0 + xor $acc05,$acc05,$s1 + xor $acc06,$acc06,$s2 + xor $acc07,$acc07,$s3 +___ +$code.=<<___; + rotrwi $s0,$s0,8 # = ROTATE(r0,8) + rotrwi $s1,$s1,8 + xor $s0,$s0,$acc00 # ^= r2^r0 + rotrwi $s2,$s2,8 + xor $s1,$s1,$acc01 + rotrwi $s3,$s3,8 + xor $s2,$s2,$acc02 + xor $s3,$s3,$acc03 + xor $acc00,$acc00,$acc08 + xor $acc01,$acc01,$acc09 + xor $acc02,$acc02,$acc10 + xor $acc03,$acc03,$acc11 + xor $s0,$s0,$acc04 # ^= r4^r0 + rotrwi $acc00,$acc00,24 + xor $s1,$s1,$acc05 + rotrwi $acc01,$acc01,24 + xor $s2,$s2,$acc06 + rotrwi $acc02,$acc02,24 + xor $s3,$s3,$acc07 + rotrwi $acc03,$acc03,24 + xor $acc04,$acc04,$acc08 + xor $acc05,$acc05,$acc09 + xor $acc06,$acc06,$acc10 + xor $acc07,$acc07,$acc11 + xor $s0,$s0,$acc08 # ^= r8 [^((r4^r0)^(r2^r0)=r4^r2)] + rotrwi $acc04,$acc04,16 + xor $s1,$s1,$acc09 + rotrwi $acc05,$acc05,16 + xor $s2,$s2,$acc10 + rotrwi $acc06,$acc06,16 + xor $s3,$s3,$acc11 + rotrwi $acc07,$acc07,16 + xor $s0,$s0,$acc00 # ^= ROTATE(r8^r2^r0,24) + rotrwi $acc08,$acc08,8 + xor $s1,$s1,$acc01 + rotrwi $acc09,$acc09,8 + xor $s2,$s2,$acc02 + rotrwi $acc10,$acc10,8 + xor $s3,$s3,$acc03 + rotrwi $acc11,$acc11,8 + xor $s0,$s0,$acc04 # ^= ROTATE(r8^r4^r0,16) + xor $s1,$s1,$acc05 + xor $s2,$s2,$acc06 + xor $s3,$s3,$acc07 + xor $s0,$s0,$acc08 # ^= ROTATE(r8,8) + xor $s1,$s1,$acc09 + xor $s2,$s2,$acc10 + xor $s3,$s3,$acc11 + + b Ldec_compact_loop +.align 4 +Ldec_compact_done: + xor $s0,$s0,$t0 + xor $s1,$s1,$t1 + xor $s2,$s2,$t2 + xor $s3,$s3,$t3 + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 +.size .AES_decrypt,.-.AES_decrypt + +.asciz "AES for PPC, CRYPTOGAMS by " +.align 7 +___ + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-s390x.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-s390x.pl new file mode 100644 index 000000000..0c4005906 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-s390x.pl @@ -0,0 +1,2282 @@ +#! /usr/bin/env perl +# Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# AES for s390x. + +# April 2007. +# +# Software performance improvement over gcc-generated code is ~70% and +# in absolute terms is ~73 cycles per byte processed with 128-bit key. +# You're likely to exclaim "why so slow?" Keep in mind that z-CPUs are +# *strictly* in-order execution and issued instruction [in this case +# load value from memory is critical] has to complete before execution +# flow proceeds. S-boxes are compressed to 2KB[+256B]. +# +# As for hardware acceleration support. It's basically a "teaser," as +# it can and should be improved in several ways. Most notably support +# for CBC is not utilized, nor multiple blocks are ever processed. +# Then software key schedule can be postponed till hardware support +# detection... Performance improvement over assembler is reportedly +# ~2.5x, but can reach >8x [naturally on larger chunks] if proper +# support is implemented. + +# May 2007. +# +# Implement AES_set_[en|de]crypt_key. Key schedule setup is avoided +# for 128-bit keys, if hardware support is detected. + +# Januray 2009. +# +# Add support for hardware AES192/256 and reschedule instructions to +# minimize/avoid Address Generation Interlock hazard and to favour +# dual-issue z10 pipeline. This gave ~25% improvement on z10 and +# almost 50% on z9. The gain is smaller on z10, because being dual- +# issue z10 makes it impossible to eliminate the interlock condition: +# critial path is not long enough. Yet it spends ~24 cycles per byte +# processed with 128-bit key. +# +# Unlike previous version hardware support detection takes place only +# at the moment of key schedule setup, which is denoted in key->rounds. +# This is done, because deferred key setup can't be made MT-safe, not +# for keys longer than 128 bits. +# +# Add AES_cbc_encrypt, which gives incredible performance improvement, +# it was measured to be ~6.6x. It's less than previously mentioned 8x, +# because software implementation was optimized. + +# May 2010. +# +# Add AES_ctr32_encrypt. If hardware-assisted, it provides up to 4.3x +# performance improvement over "generic" counter mode routine relying +# on single-block, also hardware-assisted, AES_encrypt. "Up to" refers +# to the fact that exact throughput value depends on current stack +# frame alignment within 4KB page. In worst case you get ~75% of the +# maximum, but *on average* it would be as much as ~98%. Meaning that +# worst case is unlike, it's like hitting ravine on plateau. + +# November 2010. +# +# Adapt for -m31 build. If kernel supports what's called "highgprs" +# feature on Linux [see /proc/cpuinfo], it's possible to use 64-bit +# instructions and achieve "64-bit" performance even in 31-bit legacy +# application context. The feature is not specific to any particular +# processor, as long as it's "z-CPU". Latter implies that the code +# remains z/Architecture specific. On z990 it was measured to perform +# 2x better than code generated by gcc 4.3. + +# December 2010. +# +# Add support for z196 "cipher message with counter" instruction. +# Note however that it's disengaged, because it was measured to +# perform ~12% worse than vanilla km-based code... + +# February 2011. +# +# Add AES_xts_[en|de]crypt. This includes support for z196 km-xts-aes +# instructions, which deliver ~70% improvement at 8KB block size over +# vanilla km-based code, 37% - at most like 512-bytes block size. + +$flavour = shift; + +if ($flavour =~ /3[12]/) { + $SIZE_T=4; + $g=""; +} else { + $SIZE_T=8; + $g="g"; +} + +while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} +open STDOUT,">$output"; + +$softonly=0; # allow hardware support + +$t0="%r0"; $mask="%r0"; +$t1="%r1"; +$t2="%r2"; $inp="%r2"; +$t3="%r3"; $out="%r3"; $bits="%r3"; +$key="%r4"; +$i1="%r5"; +$i2="%r6"; +$i3="%r7"; +$s0="%r8"; +$s1="%r9"; +$s2="%r10"; +$s3="%r11"; +$tbl="%r12"; +$rounds="%r13"; +$ra="%r14"; +$sp="%r15"; + +$stdframe=16*$SIZE_T+4*8; + +sub _data_word() +{ my $i; + while(defined($i=shift)) { $code.=sprintf".long\t0x%08x,0x%08x\n",$i,$i; } +} + +$code=<<___; +#include "s390x_arch.h" + +.text + +.type AES_Te,\@object +.align 256 +AES_Te: +___ +&_data_word( + 0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, + 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, + 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, + 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, + 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, + 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, + 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, + 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, + 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, + 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, + 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, + 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f, + 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, + 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, + 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, + 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, + 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, + 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, + 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, + 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, + 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, + 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, + 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, + 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, + 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, + 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, + 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, + 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, + 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, + 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, + 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, + 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d, + 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, + 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, + 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, + 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, + 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, + 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, + 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, + 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, + 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, + 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, + 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, + 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b, + 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, + 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, + 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, + 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818, + 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, + 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, + 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, + 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, + 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, + 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, + 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, + 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, + 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, + 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, + 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, + 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a, + 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, + 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, + 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, + 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a); +$code.=<<___; +# Te4[256] +.byte 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5 +.byte 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76 +.byte 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0 +.byte 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0 +.byte 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc +.byte 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15 +.byte 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a +.byte 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75 +.byte 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0 +.byte 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84 +.byte 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b +.byte 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf +.byte 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85 +.byte 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8 +.byte 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5 +.byte 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2 +.byte 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17 +.byte 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73 +.byte 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88 +.byte 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb +.byte 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c +.byte 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79 +.byte 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9 +.byte 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08 +.byte 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6 +.byte 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a +.byte 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e +.byte 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e +.byte 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94 +.byte 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf +.byte 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68 +.byte 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +# rcon[] +.long 0x01000000, 0x02000000, 0x04000000, 0x08000000 +.long 0x10000000, 0x20000000, 0x40000000, 0x80000000 +.long 0x1B000000, 0x36000000, 0, 0, 0, 0, 0, 0 +.align 256 +.size AES_Te,.-AES_Te + +# void AES_encrypt(const unsigned char *inp, unsigned char *out, +# const AES_KEY *key) { +.globl AES_encrypt +.type AES_encrypt,\@function +AES_encrypt: +___ +$code.=<<___ if (!$softonly); + l %r0,240($key) + lhi %r1,16 + clr %r0,%r1 + jl .Lesoft + + la %r1,0($key) + #la %r2,0($inp) + la %r4,0($out) + lghi %r3,16 # single block length + .long 0xb92e0042 # km %r4,%r2 + brc 1,.-4 # can this happen? + br %r14 +.align 64 +.Lesoft: +___ +$code.=<<___; + stm${g} %r3,$ra,3*$SIZE_T($sp) + + llgf $s0,0($inp) + llgf $s1,4($inp) + llgf $s2,8($inp) + llgf $s3,12($inp) + + larl $tbl,AES_Te + bras $ra,_s390x_AES_encrypt + + l${g} $out,3*$SIZE_T($sp) + st $s0,0($out) + st $s1,4($out) + st $s2,8($out) + st $s3,12($out) + + lm${g} %r6,$ra,6*$SIZE_T($sp) + br $ra +.size AES_encrypt,.-AES_encrypt + +.type _s390x_AES_encrypt,\@function +.align 16 +_s390x_AES_encrypt: + st${g} $ra,15*$SIZE_T($sp) + x $s0,0($key) + x $s1,4($key) + x $s2,8($key) + x $s3,12($key) + l $rounds,240($key) + llill $mask,`0xff<<3` + aghi $rounds,-1 + j .Lenc_loop +.align 16 +.Lenc_loop: + sllg $t1,$s0,`0+3` + srlg $t2,$s0,`8-3` + srlg $t3,$s0,`16-3` + srl $s0,`24-3` + nr $s0,$mask + ngr $t1,$mask + nr $t2,$mask + nr $t3,$mask + + srlg $i1,$s1,`16-3` # i0 + sllg $i2,$s1,`0+3` + srlg $i3,$s1,`8-3` + srl $s1,`24-3` + nr $i1,$mask + nr $s1,$mask + ngr $i2,$mask + nr $i3,$mask + + l $s0,0($s0,$tbl) # Te0[s0>>24] + l $t1,1($t1,$tbl) # Te3[s0>>0] + l $t2,2($t2,$tbl) # Te2[s0>>8] + l $t3,3($t3,$tbl) # Te1[s0>>16] + + x $s0,3($i1,$tbl) # Te1[s1>>16] + l $s1,0($s1,$tbl) # Te0[s1>>24] + x $t2,1($i2,$tbl) # Te3[s1>>0] + x $t3,2($i3,$tbl) # Te2[s1>>8] + + srlg $i1,$s2,`8-3` # i0 + srlg $i2,$s2,`16-3` # i1 + nr $i1,$mask + nr $i2,$mask + sllg $i3,$s2,`0+3` + srl $s2,`24-3` + nr $s2,$mask + ngr $i3,$mask + + xr $s1,$t1 + srlg $ra,$s3,`8-3` # i1 + sllg $t1,$s3,`0+3` # i0 + nr $ra,$mask + la $key,16($key) + ngr $t1,$mask + + x $s0,2($i1,$tbl) # Te2[s2>>8] + x $s1,3($i2,$tbl) # Te1[s2>>16] + l $s2,0($s2,$tbl) # Te0[s2>>24] + x $t3,1($i3,$tbl) # Te3[s2>>0] + + srlg $i3,$s3,`16-3` # i2 + xr $s2,$t2 + srl $s3,`24-3` + nr $i3,$mask + nr $s3,$mask + + x $s0,0($key) + x $s1,4($key) + x $s2,8($key) + x $t3,12($key) + + x $s0,1($t1,$tbl) # Te3[s3>>0] + x $s1,2($ra,$tbl) # Te2[s3>>8] + x $s2,3($i3,$tbl) # Te1[s3>>16] + l $s3,0($s3,$tbl) # Te0[s3>>24] + xr $s3,$t3 + + brct $rounds,.Lenc_loop + .align 16 + + sllg $t1,$s0,`0+3` + srlg $t2,$s0,`8-3` + ngr $t1,$mask + srlg $t3,$s0,`16-3` + srl $s0,`24-3` + nr $s0,$mask + nr $t2,$mask + nr $t3,$mask + + srlg $i1,$s1,`16-3` # i0 + sllg $i2,$s1,`0+3` + ngr $i2,$mask + srlg $i3,$s1,`8-3` + srl $s1,`24-3` + nr $i1,$mask + nr $s1,$mask + nr $i3,$mask + + llgc $s0,2($s0,$tbl) # Te4[s0>>24] + llgc $t1,2($t1,$tbl) # Te4[s0>>0] + sll $s0,24 + llgc $t2,2($t2,$tbl) # Te4[s0>>8] + llgc $t3,2($t3,$tbl) # Te4[s0>>16] + sll $t2,8 + sll $t3,16 + + llgc $i1,2($i1,$tbl) # Te4[s1>>16] + llgc $s1,2($s1,$tbl) # Te4[s1>>24] + llgc $i2,2($i2,$tbl) # Te4[s1>>0] + llgc $i3,2($i3,$tbl) # Te4[s1>>8] + sll $i1,16 + sll $s1,24 + sll $i3,8 + or $s0,$i1 + or $s1,$t1 + or $t2,$i2 + or $t3,$i3 + + srlg $i1,$s2,`8-3` # i0 + srlg $i2,$s2,`16-3` # i1 + nr $i1,$mask + nr $i2,$mask + sllg $i3,$s2,`0+3` + srl $s2,`24-3` + ngr $i3,$mask + nr $s2,$mask + + sllg $t1,$s3,`0+3` # i0 + srlg $ra,$s3,`8-3` # i1 + ngr $t1,$mask + + llgc $i1,2($i1,$tbl) # Te4[s2>>8] + llgc $i2,2($i2,$tbl) # Te4[s2>>16] + sll $i1,8 + llgc $s2,2($s2,$tbl) # Te4[s2>>24] + llgc $i3,2($i3,$tbl) # Te4[s2>>0] + sll $i2,16 + nr $ra,$mask + sll $s2,24 + or $s0,$i1 + or $s1,$i2 + or $s2,$t2 + or $t3,$i3 + + srlg $i3,$s3,`16-3` # i2 + srl $s3,`24-3` + nr $i3,$mask + nr $s3,$mask + + l $t0,16($key) + l $t2,20($key) + + llgc $i1,2($t1,$tbl) # Te4[s3>>0] + llgc $i2,2($ra,$tbl) # Te4[s3>>8] + llgc $i3,2($i3,$tbl) # Te4[s3>>16] + llgc $s3,2($s3,$tbl) # Te4[s3>>24] + sll $i2,8 + sll $i3,16 + sll $s3,24 + or $s0,$i1 + or $s1,$i2 + or $s2,$i3 + or $s3,$t3 + + l${g} $ra,15*$SIZE_T($sp) + xr $s0,$t0 + xr $s1,$t2 + x $s2,24($key) + x $s3,28($key) + + br $ra +.size _s390x_AES_encrypt,.-_s390x_AES_encrypt +___ + +$code.=<<___; +.type AES_Td,\@object +.align 256 +AES_Td: +___ +&_data_word( + 0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, + 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, + 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, + 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, + 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, + 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, + 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, + 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844, + 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, + 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, + 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, + 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94, + 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, + 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a, + 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, + 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c, + 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, + 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, + 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, + 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, + 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, + 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, + 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, + 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, + 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, + 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, + 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, + 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a, + 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, + 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16, + 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, + 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8, + 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, + 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, + 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, + 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120, + 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, + 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, + 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, + 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, + 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, + 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, + 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, + 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5, + 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, + 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, + 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, + 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6, + 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, + 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0, + 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, + 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f, + 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, + 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, + 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, + 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, + 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, + 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, + 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, + 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86, + 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, + 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, + 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, + 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742); +$code.=<<___; +# Td4[256] +.byte 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38 +.byte 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb +.byte 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87 +.byte 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb +.byte 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d +.byte 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e +.byte 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2 +.byte 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 +.byte 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16 +.byte 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 +.byte 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda +.byte 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 +.byte 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a +.byte 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 +.byte 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02 +.byte 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b +.byte 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea +.byte 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 +.byte 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85 +.byte 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e +.byte 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89 +.byte 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b +.byte 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20 +.byte 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 +.byte 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31 +.byte 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f +.byte 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d +.byte 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef +.byte 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0 +.byte 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 +.byte 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26 +.byte 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d +.size AES_Td,.-AES_Td + +# void AES_decrypt(const unsigned char *inp, unsigned char *out, +# const AES_KEY *key) { +.globl AES_decrypt +.type AES_decrypt,\@function +AES_decrypt: +___ +$code.=<<___ if (!$softonly); + l %r0,240($key) + lhi %r1,16 + clr %r0,%r1 + jl .Ldsoft + + la %r1,0($key) + #la %r2,0($inp) + la %r4,0($out) + lghi %r3,16 # single block length + .long 0xb92e0042 # km %r4,%r2 + brc 1,.-4 # can this happen? + br %r14 +.align 64 +.Ldsoft: +___ +$code.=<<___; + stm${g} %r3,$ra,3*$SIZE_T($sp) + + llgf $s0,0($inp) + llgf $s1,4($inp) + llgf $s2,8($inp) + llgf $s3,12($inp) + + larl $tbl,AES_Td + bras $ra,_s390x_AES_decrypt + + l${g} $out,3*$SIZE_T($sp) + st $s0,0($out) + st $s1,4($out) + st $s2,8($out) + st $s3,12($out) + + lm${g} %r6,$ra,6*$SIZE_T($sp) + br $ra +.size AES_decrypt,.-AES_decrypt + +.type _s390x_AES_decrypt,\@function +.align 16 +_s390x_AES_decrypt: + st${g} $ra,15*$SIZE_T($sp) + x $s0,0($key) + x $s1,4($key) + x $s2,8($key) + x $s3,12($key) + l $rounds,240($key) + llill $mask,`0xff<<3` + aghi $rounds,-1 + j .Ldec_loop +.align 16 +.Ldec_loop: + srlg $t1,$s0,`16-3` + srlg $t2,$s0,`8-3` + sllg $t3,$s0,`0+3` + srl $s0,`24-3` + nr $s0,$mask + nr $t1,$mask + nr $t2,$mask + ngr $t3,$mask + + sllg $i1,$s1,`0+3` # i0 + srlg $i2,$s1,`16-3` + srlg $i3,$s1,`8-3` + srl $s1,`24-3` + ngr $i1,$mask + nr $s1,$mask + nr $i2,$mask + nr $i3,$mask + + l $s0,0($s0,$tbl) # Td0[s0>>24] + l $t1,3($t1,$tbl) # Td1[s0>>16] + l $t2,2($t2,$tbl) # Td2[s0>>8] + l $t3,1($t3,$tbl) # Td3[s0>>0] + + x $s0,1($i1,$tbl) # Td3[s1>>0] + l $s1,0($s1,$tbl) # Td0[s1>>24] + x $t2,3($i2,$tbl) # Td1[s1>>16] + x $t3,2($i3,$tbl) # Td2[s1>>8] + + srlg $i1,$s2,`8-3` # i0 + sllg $i2,$s2,`0+3` # i1 + srlg $i3,$s2,`16-3` + srl $s2,`24-3` + nr $i1,$mask + ngr $i2,$mask + nr $s2,$mask + nr $i3,$mask + + xr $s1,$t1 + srlg $ra,$s3,`8-3` # i1 + srlg $t1,$s3,`16-3` # i0 + nr $ra,$mask + la $key,16($key) + nr $t1,$mask + + x $s0,2($i1,$tbl) # Td2[s2>>8] + x $s1,1($i2,$tbl) # Td3[s2>>0] + l $s2,0($s2,$tbl) # Td0[s2>>24] + x $t3,3($i3,$tbl) # Td1[s2>>16] + + sllg $i3,$s3,`0+3` # i2 + srl $s3,`24-3` + ngr $i3,$mask + nr $s3,$mask + + xr $s2,$t2 + x $s0,0($key) + x $s1,4($key) + x $s2,8($key) + x $t3,12($key) + + x $s0,3($t1,$tbl) # Td1[s3>>16] + x $s1,2($ra,$tbl) # Td2[s3>>8] + x $s2,1($i3,$tbl) # Td3[s3>>0] + l $s3,0($s3,$tbl) # Td0[s3>>24] + xr $s3,$t3 + + brct $rounds,.Ldec_loop + .align 16 + + l $t1,`2048+0`($tbl) # prefetch Td4 + l $t2,`2048+64`($tbl) + l $t3,`2048+128`($tbl) + l $i1,`2048+192`($tbl) + llill $mask,0xff + + srlg $i3,$s0,24 # i0 + srlg $t1,$s0,16 + srlg $t2,$s0,8 + nr $s0,$mask # i3 + nr $t1,$mask + + srlg $i1,$s1,24 + nr $t2,$mask + srlg $i2,$s1,16 + srlg $ra,$s1,8 + nr $s1,$mask # i0 + nr $i2,$mask + nr $ra,$mask + + llgc $i3,2048($i3,$tbl) # Td4[s0>>24] + llgc $t1,2048($t1,$tbl) # Td4[s0>>16] + llgc $t2,2048($t2,$tbl) # Td4[s0>>8] + sll $t1,16 + llgc $t3,2048($s0,$tbl) # Td4[s0>>0] + sllg $s0,$i3,24 + sll $t2,8 + + llgc $s1,2048($s1,$tbl) # Td4[s1>>0] + llgc $i1,2048($i1,$tbl) # Td4[s1>>24] + llgc $i2,2048($i2,$tbl) # Td4[s1>>16] + sll $i1,24 + llgc $i3,2048($ra,$tbl) # Td4[s1>>8] + sll $i2,16 + sll $i3,8 + or $s0,$s1 + or $t1,$i1 + or $t2,$i2 + or $t3,$i3 + + srlg $i1,$s2,8 # i0 + srlg $i2,$s2,24 + srlg $i3,$s2,16 + nr $s2,$mask # i1 + nr $i1,$mask + nr $i3,$mask + llgc $i1,2048($i1,$tbl) # Td4[s2>>8] + llgc $s1,2048($s2,$tbl) # Td4[s2>>0] + llgc $i2,2048($i2,$tbl) # Td4[s2>>24] + llgc $i3,2048($i3,$tbl) # Td4[s2>>16] + sll $i1,8 + sll $i2,24 + or $s0,$i1 + sll $i3,16 + or $t2,$i2 + or $t3,$i3 + + srlg $i1,$s3,16 # i0 + srlg $i2,$s3,8 # i1 + srlg $i3,$s3,24 + nr $s3,$mask # i2 + nr $i1,$mask + nr $i2,$mask + + l${g} $ra,15*$SIZE_T($sp) + or $s1,$t1 + l $t0,16($key) + l $t1,20($key) + + llgc $i1,2048($i1,$tbl) # Td4[s3>>16] + llgc $i2,2048($i2,$tbl) # Td4[s3>>8] + sll $i1,16 + llgc $s2,2048($s3,$tbl) # Td4[s3>>0] + llgc $s3,2048($i3,$tbl) # Td4[s3>>24] + sll $i2,8 + sll $s3,24 + or $s0,$i1 + or $s1,$i2 + or $s2,$t2 + or $s3,$t3 + + xr $s0,$t0 + xr $s1,$t1 + x $s2,24($key) + x $s3,28($key) + + br $ra +.size _s390x_AES_decrypt,.-_s390x_AES_decrypt +___ + +$code.=<<___; +# void AES_set_encrypt_key(const unsigned char *in, int bits, +# AES_KEY *key) { +.globl AES_set_encrypt_key +.type AES_set_encrypt_key,\@function +.align 16 +AES_set_encrypt_key: +_s390x_AES_set_encrypt_key: + lghi $t0,0 + cl${g}r $inp,$t0 + je .Lminus1 + cl${g}r $key,$t0 + je .Lminus1 + + lghi $t0,128 + clr $bits,$t0 + je .Lproceed + lghi $t0,192 + clr $bits,$t0 + je .Lproceed + lghi $t0,256 + clr $bits,$t0 + je .Lproceed + lghi %r2,-2 + br %r14 + +.align 16 +.Lproceed: +___ +$code.=<<___ if (!$softonly); + # convert bits to km(c) code, [128,192,256]->[18,19,20] + lhi %r5,-128 + lhi %r0,18 + ar %r5,$bits + srl %r5,6 + ar %r5,%r0 + + larl %r1,OPENSSL_s390xcap_P + llihh %r0,0x8000 + srlg %r0,%r0,0(%r5) + ng %r0,S390X_KM(%r1) # check availability of both km... + ng %r0,S390X_KMC(%r1) # ...and kmc support for given key length + jz .Lekey_internal + + lmg %r0,%r1,0($inp) # just copy 128 bits... + stmg %r0,%r1,0($key) + lhi %r0,192 + cr $bits,%r0 + jl 1f + lg %r1,16($inp) + stg %r1,16($key) + je 1f + lg %r1,24($inp) + stg %r1,24($key) +1: st $bits,236($key) # save bits [for debugging purposes] + lgr $t0,%r5 + st %r5,240($key) # save km(c) code + lghi %r2,0 + br %r14 +___ +$code.=<<___; +.align 16 +.Lekey_internal: + stm${g} %r4,%r13,4*$SIZE_T($sp) # all non-volatile regs and $key + + larl $tbl,AES_Te+2048 + + llgf $s0,0($inp) + llgf $s1,4($inp) + llgf $s2,8($inp) + llgf $s3,12($inp) + st $s0,0($key) + st $s1,4($key) + st $s2,8($key) + st $s3,12($key) + lghi $t0,128 + cr $bits,$t0 + jne .Lnot128 + + llill $mask,0xff + lghi $t3,0 # i=0 + lghi $rounds,10 + st $rounds,240($key) + + llgfr $t2,$s3 # temp=rk[3] + srlg $i1,$s3,8 + srlg $i2,$s3,16 + srlg $i3,$s3,24 + nr $t2,$mask + nr $i1,$mask + nr $i2,$mask + +.align 16 +.L128_loop: + la $t2,0($t2,$tbl) + la $i1,0($i1,$tbl) + la $i2,0($i2,$tbl) + la $i3,0($i3,$tbl) + icm $t2,2,0($t2) # Te4[rk[3]>>0]<<8 + icm $t2,4,0($i1) # Te4[rk[3]>>8]<<16 + icm $t2,8,0($i2) # Te4[rk[3]>>16]<<24 + icm $t2,1,0($i3) # Te4[rk[3]>>24] + x $t2,256($t3,$tbl) # rcon[i] + xr $s0,$t2 # rk[4]=rk[0]^... + xr $s1,$s0 # rk[5]=rk[1]^rk[4] + xr $s2,$s1 # rk[6]=rk[2]^rk[5] + xr $s3,$s2 # rk[7]=rk[3]^rk[6] + + llgfr $t2,$s3 # temp=rk[3] + srlg $i1,$s3,8 + srlg $i2,$s3,16 + nr $t2,$mask + nr $i1,$mask + srlg $i3,$s3,24 + nr $i2,$mask + + st $s0,16($key) + st $s1,20($key) + st $s2,24($key) + st $s3,28($key) + la $key,16($key) # key+=4 + la $t3,4($t3) # i++ + brct $rounds,.L128_loop + lghi $t0,10 + lghi %r2,0 + lm${g} %r4,%r13,4*$SIZE_T($sp) + br $ra + +.align 16 +.Lnot128: + llgf $t0,16($inp) + llgf $t1,20($inp) + st $t0,16($key) + st $t1,20($key) + lghi $t0,192 + cr $bits,$t0 + jne .Lnot192 + + llill $mask,0xff + lghi $t3,0 # i=0 + lghi $rounds,12 + st $rounds,240($key) + lghi $rounds,8 + + srlg $i1,$t1,8 + srlg $i2,$t1,16 + srlg $i3,$t1,24 + nr $t1,$mask + nr $i1,$mask + nr $i2,$mask + +.align 16 +.L192_loop: + la $t1,0($t1,$tbl) + la $i1,0($i1,$tbl) + la $i2,0($i2,$tbl) + la $i3,0($i3,$tbl) + icm $t1,2,0($t1) # Te4[rk[5]>>0]<<8 + icm $t1,4,0($i1) # Te4[rk[5]>>8]<<16 + icm $t1,8,0($i2) # Te4[rk[5]>>16]<<24 + icm $t1,1,0($i3) # Te4[rk[5]>>24] + x $t1,256($t3,$tbl) # rcon[i] + xr $s0,$t1 # rk[6]=rk[0]^... + xr $s1,$s0 # rk[7]=rk[1]^rk[6] + xr $s2,$s1 # rk[8]=rk[2]^rk[7] + xr $s3,$s2 # rk[9]=rk[3]^rk[8] + + st $s0,24($key) + st $s1,28($key) + st $s2,32($key) + st $s3,36($key) + brct $rounds,.L192_continue + lghi $t0,12 + lghi %r2,0 + lm${g} %r4,%r13,4*$SIZE_T($sp) + br $ra + +.align 16 +.L192_continue: + lgr $t1,$s3 + x $t1,16($key) # rk[10]=rk[4]^rk[9] + st $t1,40($key) + x $t1,20($key) # rk[11]=rk[5]^rk[10] + st $t1,44($key) + + srlg $i1,$t1,8 + srlg $i2,$t1,16 + srlg $i3,$t1,24 + nr $t1,$mask + nr $i1,$mask + nr $i2,$mask + + la $key,24($key) # key+=6 + la $t3,4($t3) # i++ + j .L192_loop + +.align 16 +.Lnot192: + llgf $t0,24($inp) + llgf $t1,28($inp) + st $t0,24($key) + st $t1,28($key) + llill $mask,0xff + lghi $t3,0 # i=0 + lghi $rounds,14 + st $rounds,240($key) + lghi $rounds,7 + + srlg $i1,$t1,8 + srlg $i2,$t1,16 + srlg $i3,$t1,24 + nr $t1,$mask + nr $i1,$mask + nr $i2,$mask + +.align 16 +.L256_loop: + la $t1,0($t1,$tbl) + la $i1,0($i1,$tbl) + la $i2,0($i2,$tbl) + la $i3,0($i3,$tbl) + icm $t1,2,0($t1) # Te4[rk[7]>>0]<<8 + icm $t1,4,0($i1) # Te4[rk[7]>>8]<<16 + icm $t1,8,0($i2) # Te4[rk[7]>>16]<<24 + icm $t1,1,0($i3) # Te4[rk[7]>>24] + x $t1,256($t3,$tbl) # rcon[i] + xr $s0,$t1 # rk[8]=rk[0]^... + xr $s1,$s0 # rk[9]=rk[1]^rk[8] + xr $s2,$s1 # rk[10]=rk[2]^rk[9] + xr $s3,$s2 # rk[11]=rk[3]^rk[10] + st $s0,32($key) + st $s1,36($key) + st $s2,40($key) + st $s3,44($key) + brct $rounds,.L256_continue + lghi $t0,14 + lghi %r2,0 + lm${g} %r4,%r13,4*$SIZE_T($sp) + br $ra + +.align 16 +.L256_continue: + lgr $t1,$s3 # temp=rk[11] + srlg $i1,$s3,8 + srlg $i2,$s3,16 + srlg $i3,$s3,24 + nr $t1,$mask + nr $i1,$mask + nr $i2,$mask + la $t1,0($t1,$tbl) + la $i1,0($i1,$tbl) + la $i2,0($i2,$tbl) + la $i3,0($i3,$tbl) + llgc $t1,0($t1) # Te4[rk[11]>>0] + icm $t1,2,0($i1) # Te4[rk[11]>>8]<<8 + icm $t1,4,0($i2) # Te4[rk[11]>>16]<<16 + icm $t1,8,0($i3) # Te4[rk[11]>>24]<<24 + x $t1,16($key) # rk[12]=rk[4]^... + st $t1,48($key) + x $t1,20($key) # rk[13]=rk[5]^rk[12] + st $t1,52($key) + x $t1,24($key) # rk[14]=rk[6]^rk[13] + st $t1,56($key) + x $t1,28($key) # rk[15]=rk[7]^rk[14] + st $t1,60($key) + + srlg $i1,$t1,8 + srlg $i2,$t1,16 + srlg $i3,$t1,24 + nr $t1,$mask + nr $i1,$mask + nr $i2,$mask + + la $key,32($key) # key+=8 + la $t3,4($t3) # i++ + j .L256_loop + +.Lminus1: + lghi %r2,-1 + br $ra +.size AES_set_encrypt_key,.-AES_set_encrypt_key + +# void AES_set_decrypt_key(const unsigned char *in, int bits, +# AES_KEY *key) { +.globl AES_set_decrypt_key +.type AES_set_decrypt_key,\@function +.align 16 +AES_set_decrypt_key: + #st${g} $key,4*$SIZE_T($sp) # I rely on AES_set_encrypt_key to + st${g} $ra,14*$SIZE_T($sp) # save non-volatile registers and $key! + bras $ra,_s390x_AES_set_encrypt_key + #l${g} $key,4*$SIZE_T($sp) + l${g} $ra,14*$SIZE_T($sp) + ltgr %r2,%r2 + bnzr $ra +___ +$code.=<<___ if (!$softonly); + #l $t0,240($key) + lhi $t1,16 + cr $t0,$t1 + jl .Lgo + oill $t0,S390X_DECRYPT # set "decrypt" bit + st $t0,240($key) + br $ra +___ +$code.=<<___; +.align 16 +.Lgo: lgr $rounds,$t0 #llgf $rounds,240($key) + la $i1,0($key) + sllg $i2,$rounds,4 + la $i2,0($i2,$key) + srl $rounds,1 + lghi $t1,-16 + +.align 16 +.Linv: lmg $s0,$s1,0($i1) + lmg $s2,$s3,0($i2) + stmg $s0,$s1,0($i2) + stmg $s2,$s3,0($i1) + la $i1,16($i1) + la $i2,0($t1,$i2) + brct $rounds,.Linv +___ +$mask80=$i1; +$mask1b=$i2; +$maskfe=$i3; +$code.=<<___; + llgf $rounds,240($key) + aghi $rounds,-1 + sll $rounds,2 # (rounds-1)*4 + llilh $mask80,0x8080 + llilh $mask1b,0x1b1b + llilh $maskfe,0xfefe + oill $mask80,0x8080 + oill $mask1b,0x1b1b + oill $maskfe,0xfefe + +.align 16 +.Lmix: l $s0,16($key) # tp1 + lr $s1,$s0 + ngr $s1,$mask80 + srlg $t1,$s1,7 + slr $s1,$t1 + nr $s1,$mask1b + sllg $t1,$s0,1 + nr $t1,$maskfe + xr $s1,$t1 # tp2 + + lr $s2,$s1 + ngr $s2,$mask80 + srlg $t1,$s2,7 + slr $s2,$t1 + nr $s2,$mask1b + sllg $t1,$s1,1 + nr $t1,$maskfe + xr $s2,$t1 # tp4 + + lr $s3,$s2 + ngr $s3,$mask80 + srlg $t1,$s3,7 + slr $s3,$t1 + nr $s3,$mask1b + sllg $t1,$s2,1 + nr $t1,$maskfe + xr $s3,$t1 # tp8 + + xr $s1,$s0 # tp2^tp1 + xr $s2,$s0 # tp4^tp1 + rll $s0,$s0,24 # = ROTATE(tp1,8) + xr $s2,$s3 # ^=tp8 + xr $s0,$s1 # ^=tp2^tp1 + xr $s1,$s3 # tp2^tp1^tp8 + xr $s0,$s2 # ^=tp4^tp1^tp8 + rll $s1,$s1,8 + rll $s2,$s2,16 + xr $s0,$s1 # ^= ROTATE(tp8^tp2^tp1,24) + rll $s3,$s3,24 + xr $s0,$s2 # ^= ROTATE(tp8^tp4^tp1,16) + xr $s0,$s3 # ^= ROTATE(tp8,8) + + st $s0,16($key) + la $key,4($key) + brct $rounds,.Lmix + + lm${g} %r6,%r13,6*$SIZE_T($sp)# as was saved by AES_set_encrypt_key! + lghi %r2,0 + br $ra +.size AES_set_decrypt_key,.-AES_set_decrypt_key +___ + +######################################################################## +# void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, +# size_t length, const AES_KEY *key, +# unsigned char *ivec, const int enc) +{ +my $inp="%r2"; +my $out="%r4"; # length and out are swapped +my $len="%r3"; +my $key="%r5"; +my $ivp="%r6"; + +$code.=<<___; +.globl AES_cbc_encrypt +.type AES_cbc_encrypt,\@function +.align 16 +AES_cbc_encrypt: + xgr %r3,%r4 # flip %r3 and %r4, out and len + xgr %r4,%r3 + xgr %r3,%r4 +___ +$code.=<<___ if (!$softonly); + lhi %r0,16 + cl %r0,240($key) + jh .Lcbc_software + + lg %r0,0($ivp) # copy ivec + lg %r1,8($ivp) + stmg %r0,%r1,16($sp) + lmg %r0,%r1,0($key) # copy key, cover 256 bit + stmg %r0,%r1,32($sp) + lmg %r0,%r1,16($key) + stmg %r0,%r1,48($sp) + l %r0,240($key) # load kmc code + lghi $key,15 # res=len%16, len-=res; + ngr $key,$len + sl${g}r $len,$key + la %r1,16($sp) # parameter block - ivec || key + jz .Lkmc_truncated + .long 0xb92f0042 # kmc %r4,%r2 + brc 1,.-4 # pay attention to "partial completion" + ltr $key,$key + jnz .Lkmc_truncated +.Lkmc_done: + lmg %r0,%r1,16($sp) # copy ivec to caller + stg %r0,0($ivp) + stg %r1,8($ivp) + br $ra +.align 16 +.Lkmc_truncated: + ahi $key,-1 # it's the way it's encoded in mvc + tmll %r0,S390X_DECRYPT + jnz .Lkmc_truncated_dec + lghi %r1,0 + stg %r1,16*$SIZE_T($sp) + stg %r1,16*$SIZE_T+8($sp) + bras %r1,1f + mvc 16*$SIZE_T(1,$sp),0($inp) +1: ex $key,0(%r1) + la %r1,16($sp) # restore parameter block + la $inp,16*$SIZE_T($sp) + lghi $len,16 + .long 0xb92f0042 # kmc %r4,%r2 + j .Lkmc_done +.align 16 +.Lkmc_truncated_dec: + st${g} $out,4*$SIZE_T($sp) + la $out,16*$SIZE_T($sp) + lghi $len,16 + .long 0xb92f0042 # kmc %r4,%r2 + l${g} $out,4*$SIZE_T($sp) + bras %r1,2f + mvc 0(1,$out),16*$SIZE_T($sp) +2: ex $key,0(%r1) + j .Lkmc_done +.align 16 +.Lcbc_software: +___ +$code.=<<___; + stm${g} $key,$ra,5*$SIZE_T($sp) + lhi %r0,0 + cl %r0,`$stdframe+$SIZE_T-4`($sp) + je .Lcbc_decrypt + + larl $tbl,AES_Te + + llgf $s0,0($ivp) + llgf $s1,4($ivp) + llgf $s2,8($ivp) + llgf $s3,12($ivp) + + lghi $t0,16 + sl${g}r $len,$t0 + brc 4,.Lcbc_enc_tail # if borrow +.Lcbc_enc_loop: + stm${g} $inp,$out,2*$SIZE_T($sp) + x $s0,0($inp) + x $s1,4($inp) + x $s2,8($inp) + x $s3,12($inp) + lgr %r4,$key + + bras $ra,_s390x_AES_encrypt + + lm${g} $inp,$key,2*$SIZE_T($sp) + st $s0,0($out) + st $s1,4($out) + st $s2,8($out) + st $s3,12($out) + + la $inp,16($inp) + la $out,16($out) + lghi $t0,16 + lt${g}r $len,$len + jz .Lcbc_enc_done + sl${g}r $len,$t0 + brc 4,.Lcbc_enc_tail # if borrow + j .Lcbc_enc_loop +.align 16 +.Lcbc_enc_done: + l${g} $ivp,6*$SIZE_T($sp) + st $s0,0($ivp) + st $s1,4($ivp) + st $s2,8($ivp) + st $s3,12($ivp) + + lm${g} %r7,$ra,7*$SIZE_T($sp) + br $ra + +.align 16 +.Lcbc_enc_tail: + aghi $len,15 + lghi $t0,0 + stg $t0,16*$SIZE_T($sp) + stg $t0,16*$SIZE_T+8($sp) + bras $t1,3f + mvc 16*$SIZE_T(1,$sp),0($inp) +3: ex $len,0($t1) + lghi $len,0 + la $inp,16*$SIZE_T($sp) + j .Lcbc_enc_loop + +.align 16 +.Lcbc_decrypt: + larl $tbl,AES_Td + + lg $t0,0($ivp) + lg $t1,8($ivp) + stmg $t0,$t1,16*$SIZE_T($sp) + +.Lcbc_dec_loop: + stm${g} $inp,$out,2*$SIZE_T($sp) + llgf $s0,0($inp) + llgf $s1,4($inp) + llgf $s2,8($inp) + llgf $s3,12($inp) + lgr %r4,$key + + bras $ra,_s390x_AES_decrypt + + lm${g} $inp,$key,2*$SIZE_T($sp) + sllg $s0,$s0,32 + sllg $s2,$s2,32 + lr $s0,$s1 + lr $s2,$s3 + + lg $t0,0($inp) + lg $t1,8($inp) + xg $s0,16*$SIZE_T($sp) + xg $s2,16*$SIZE_T+8($sp) + lghi $s1,16 + sl${g}r $len,$s1 + brc 4,.Lcbc_dec_tail # if borrow + brc 2,.Lcbc_dec_done # if zero + stg $s0,0($out) + stg $s2,8($out) + stmg $t0,$t1,16*$SIZE_T($sp) + + la $inp,16($inp) + la $out,16($out) + j .Lcbc_dec_loop + +.Lcbc_dec_done: + stg $s0,0($out) + stg $s2,8($out) +.Lcbc_dec_exit: + lm${g} %r6,$ra,6*$SIZE_T($sp) + stmg $t0,$t1,0($ivp) + + br $ra + +.align 16 +.Lcbc_dec_tail: + aghi $len,15 + stg $s0,16*$SIZE_T($sp) + stg $s2,16*$SIZE_T+8($sp) + bras $s1,4f + mvc 0(1,$out),16*$SIZE_T($sp) +4: ex $len,0($s1) + j .Lcbc_dec_exit +.size AES_cbc_encrypt,.-AES_cbc_encrypt +___ +} +######################################################################## +# void AES_ctr32_encrypt(const unsigned char *in, unsigned char *out, +# size_t blocks, const AES_KEY *key, +# const unsigned char *ivec) +{ +my $inp="%r2"; +my $out="%r4"; # blocks and out are swapped +my $len="%r3"; +my $key="%r5"; my $iv0="%r5"; +my $ivp="%r6"; +my $fp ="%r7"; + +$code.=<<___; +.globl AES_ctr32_encrypt +.type AES_ctr32_encrypt,\@function +.align 16 +AES_ctr32_encrypt: + xgr %r3,%r4 # flip %r3 and %r4, $out and $len + xgr %r4,%r3 + xgr %r3,%r4 + llgfr $len,$len # safe in ctr32 subroutine even in 64-bit case +___ +$code.=<<___ if (!$softonly); + l %r0,240($key) + lhi %r1,16 + clr %r0,%r1 + jl .Lctr32_software + + st${g} $s2,10*$SIZE_T($sp) + st${g} $s3,11*$SIZE_T($sp) + + clr $len,%r1 # does work even in 64-bit mode + jle .Lctr32_nokma # kma is slower for <= 16 blocks + + larl %r1,OPENSSL_s390xcap_P + lr $s2,%r0 + llihh $s3,0x8000 + srlg $s3,$s3,0($s2) + ng $s3,S390X_KMA(%r1) # check kma capability vector + jz .Lctr32_nokma + + l${g}hi %r1,-$stdframe-112 + l${g}r $s3,$sp + la $sp,0(%r1,$sp) # prepare parameter block + + lhi %r1,0x0600 + sllg $len,$len,4 + or %r0,%r1 # set HS and LAAD flags + + st${g} $s3,0($sp) # backchain + la %r1,$stdframe($sp) + + lmg $s2,$s3,0($key) # copy key + stg $s2,$stdframe+80($sp) + stg $s3,$stdframe+88($sp) + lmg $s2,$s3,16($key) + stg $s2,$stdframe+96($sp) + stg $s3,$stdframe+104($sp) + + lmg $s2,$s3,0($ivp) # copy iv + stg $s2,$stdframe+64($sp) + ahi $s3,-1 # kma requires counter-1 + stg $s3,$stdframe+72($sp) + st $s3,$stdframe+12($sp) # copy counter + + lghi $s2,0 # no AAD + lghi $s3,0 + + .long 0xb929a042 # kma $out,$s2,$inp + brc 1,.-4 # pay attention to "partial completion" + + stg %r0,$stdframe+80($sp) # wipe key + stg %r0,$stdframe+88($sp) + stg %r0,$stdframe+96($sp) + stg %r0,$stdframe+104($sp) + la $sp,$stdframe+112($sp) + + lm${g} $s2,$s3,10*$SIZE_T($sp) + br $ra + +.align 16 +.Lctr32_nokma: + stm${g} %r6,$s1,6*$SIZE_T($sp) + + slgr $out,$inp + la %r1,0($key) # %r1 is permanent copy of $key + lg $iv0,0($ivp) # load ivec + lg $ivp,8($ivp) + + # prepare and allocate stack frame at the top of 4K page + # with 1K reserved for eventual signal handling + lghi $s0,-1024-256-16# guarantee at least 256-bytes buffer + lghi $s1,-4096 + algr $s0,$sp + lgr $fp,$sp + ngr $s0,$s1 # align at page boundary + slgr $fp,$s0 # total buffer size + lgr $s2,$sp + lghi $s1,1024+16 # sl[g]fi is extended-immediate facility + slgr $fp,$s1 # deduct reservation to get usable buffer size + # buffer size is at lest 256 and at most 3072+256-16 + + la $sp,1024($s0) # alloca + srlg $fp,$fp,4 # convert bytes to blocks, minimum 16 + st${g} $s2,0($sp) # back-chain + st${g} $fp,$SIZE_T($sp) + + slgr $len,$fp + brc 1,.Lctr32_hw_switch # not zero, no borrow + algr $fp,$len # input is shorter than allocated buffer + lghi $len,0 + st${g} $fp,$SIZE_T($sp) + +.Lctr32_hw_switch: +___ +$code.=<<___ if (!$softonly && 0);# kmctr code was measured to be ~12% slower + llgfr $s0,%r0 + lgr $s1,%r1 + larl %r1,OPENSSL_s390xcap_P + llihh %r0,0x8000 # check if kmctr supports the function code + srlg %r0,%r0,0($s0) + ng %r0,S390X_KMCTR(%r1) # check kmctr capability vector + lgr %r0,$s0 + lgr %r1,$s1 + jz .Lctr32_km_loop + +####### kmctr code + algr $out,$inp # restore $out + lgr $s1,$len # $s1 undertakes $len + j .Lctr32_kmctr_loop +.align 16 +.Lctr32_kmctr_loop: + la $s2,16($sp) + lgr $s3,$fp +.Lctr32_kmctr_prepare: + stg $iv0,0($s2) + stg $ivp,8($s2) + la $s2,16($s2) + ahi $ivp,1 # 32-bit increment, preserves upper half + brct $s3,.Lctr32_kmctr_prepare + + #la $inp,0($inp) # inp + sllg $len,$fp,4 # len + #la $out,0($out) # out + la $s2,16($sp) # iv + .long 0xb92da042 # kmctr $out,$s2,$inp + brc 1,.-4 # pay attention to "partial completion" + + slgr $s1,$fp + brc 1,.Lctr32_kmctr_loop # not zero, no borrow + algr $fp,$s1 + lghi $s1,0 + brc 4+1,.Lctr32_kmctr_loop # not zero + + l${g} $sp,0($sp) + lm${g} %r6,$s3,6*$SIZE_T($sp) + br $ra +.align 16 +___ +$code.=<<___ if (!$softonly); +.Lctr32_km_loop: + la $s2,16($sp) + lgr $s3,$fp +.Lctr32_km_prepare: + stg $iv0,0($s2) + stg $ivp,8($s2) + la $s2,16($s2) + ahi $ivp,1 # 32-bit increment, preserves upper half + brct $s3,.Lctr32_km_prepare + + la $s0,16($sp) # inp + sllg $s1,$fp,4 # len + la $s2,16($sp) # out + .long 0xb92e00a8 # km %r10,%r8 + brc 1,.-4 # pay attention to "partial completion" + + la $s2,16($sp) + lgr $s3,$fp + slgr $s2,$inp +.Lctr32_km_xor: + lg $s0,0($inp) + lg $s1,8($inp) + xg $s0,0($s2,$inp) + xg $s1,8($s2,$inp) + stg $s0,0($out,$inp) + stg $s1,8($out,$inp) + la $inp,16($inp) + brct $s3,.Lctr32_km_xor + + slgr $len,$fp + brc 1,.Lctr32_km_loop # not zero, no borrow + algr $fp,$len + lghi $len,0 + brc 4+1,.Lctr32_km_loop # not zero + + l${g} $s0,0($sp) + l${g} $s1,$SIZE_T($sp) + la $s2,16($sp) +.Lctr32_km_zap: + stg $s0,0($s2) + stg $s0,8($s2) + la $s2,16($s2) + brct $s1,.Lctr32_km_zap + + la $sp,0($s0) + lm${g} %r6,$s3,6*$SIZE_T($sp) + br $ra +.align 16 +.Lctr32_software: +___ +$code.=<<___; + stm${g} $key,$ra,5*$SIZE_T($sp) + sl${g}r $inp,$out + larl $tbl,AES_Te + llgf $t1,12($ivp) + +.Lctr32_loop: + stm${g} $inp,$out,2*$SIZE_T($sp) + llgf $s0,0($ivp) + llgf $s1,4($ivp) + llgf $s2,8($ivp) + lgr $s3,$t1 + st $t1,16*$SIZE_T($sp) + lgr %r4,$key + + bras $ra,_s390x_AES_encrypt + + lm${g} $inp,$ivp,2*$SIZE_T($sp) + llgf $t1,16*$SIZE_T($sp) + x $s0,0($inp,$out) + x $s1,4($inp,$out) + x $s2,8($inp,$out) + x $s3,12($inp,$out) + stm $s0,$s3,0($out) + + la $out,16($out) + ahi $t1,1 # 32-bit increment + brct $len,.Lctr32_loop + + lm${g} %r6,$ra,6*$SIZE_T($sp) + br $ra +.size AES_ctr32_encrypt,.-AES_ctr32_encrypt +___ +} + +######################################################################## +# void AES_xts_encrypt(const unsigned char *inp, unsigned char *out, +# size_t len, const AES_KEY *key1, const AES_KEY *key2, +# const unsigned char iv[16]); +# +{ +my $inp="%r2"; +my $out="%r4"; # len and out are swapped +my $len="%r3"; +my $key1="%r5"; # $i1 +my $key2="%r6"; # $i2 +my $fp="%r7"; # $i3 +my $tweak=16*$SIZE_T+16; # or $stdframe-16, bottom of the frame... + +$code.=<<___; +.type _s390x_xts_km,\@function +.align 16 +_s390x_xts_km: +___ +$code.=<<___ if(1); + llgfr $s0,%r0 # put aside the function code + lghi $s1,0x7f + nr $s1,%r0 + larl %r1,OPENSSL_s390xcap_P + llihh %r0,0x8000 + srlg %r0,%r0,32($s1) # check for 32+function code + ng %r0,S390X_KM(%r1) # check km capability vector + lgr %r0,$s0 # restore the function code + la %r1,0($key1) # restore $key1 + jz .Lxts_km_vanilla + + lmg $i2,$i3,$tweak($sp) # put aside the tweak value + algr $out,$inp + + oill %r0,32 # switch to xts function code + aghi $s1,-18 # + sllg $s1,$s1,3 # (function code - 18)*8, 0 or 16 + la %r1,$tweak-16($sp) + slgr %r1,$s1 # parameter block position + lmg $s0,$s3,0($key1) # load 256 bits of key material, + stmg $s0,$s3,0(%r1) # and copy it to parameter block. + # yes, it contains junk and overlaps + # with the tweak in 128-bit case. + # it's done to avoid conditional + # branch. + stmg $i2,$i3,$tweak($sp) # "re-seat" the tweak value + + .long 0xb92e0042 # km %r4,%r2 + brc 1,.-4 # pay attention to "partial completion" + + lrvg $s0,$tweak+0($sp) # load the last tweak + lrvg $s1,$tweak+8($sp) + stmg %r0,%r3,$tweak-32($sp) # wipe copy of the key + + nill %r0,0xffdf # switch back to original function code + la %r1,0($key1) # restore pointer to $key1 + slgr $out,$inp + + llgc $len,2*$SIZE_T-1($sp) + nill $len,0x0f # $len%=16 + br $ra + +.align 16 +.Lxts_km_vanilla: +___ +$code.=<<___; + # prepare and allocate stack frame at the top of 4K page + # with 1K reserved for eventual signal handling + lghi $s0,-1024-256-16# guarantee at least 256-bytes buffer + lghi $s1,-4096 + algr $s0,$sp + lgr $fp,$sp + ngr $s0,$s1 # align at page boundary + slgr $fp,$s0 # total buffer size + lgr $s2,$sp + lghi $s1,1024+16 # sl[g]fi is extended-immediate facility + slgr $fp,$s1 # deduct reservation to get usable buffer size + # buffer size is at lest 256 and at most 3072+256-16 + + la $sp,1024($s0) # alloca + nill $fp,0xfff0 # round to 16*n + st${g} $s2,0($sp) # back-chain + nill $len,0xfff0 # redundant + st${g} $fp,$SIZE_T($sp) + + slgr $len,$fp + brc 1,.Lxts_km_go # not zero, no borrow + algr $fp,$len # input is shorter than allocated buffer + lghi $len,0 + st${g} $fp,$SIZE_T($sp) + +.Lxts_km_go: + lrvg $s0,$tweak+0($s2) # load the tweak value in little-endian + lrvg $s1,$tweak+8($s2) + + la $s2,16($sp) # vector of ascending tweak values + slgr $s2,$inp + srlg $s3,$fp,4 + j .Lxts_km_start + +.Lxts_km_loop: + la $s2,16($sp) + slgr $s2,$inp + srlg $s3,$fp,4 +.Lxts_km_prepare: + lghi $i1,0x87 + srag $i2,$s1,63 # broadcast upper bit + ngr $i1,$i2 # rem + algr $s0,$s0 + alcgr $s1,$s1 + xgr $s0,$i1 +.Lxts_km_start: + lrvgr $i1,$s0 # flip byte order + lrvgr $i2,$s1 + stg $i1,0($s2,$inp) + stg $i2,8($s2,$inp) + xg $i1,0($inp) + xg $i2,8($inp) + stg $i1,0($out,$inp) + stg $i2,8($out,$inp) + la $inp,16($inp) + brct $s3,.Lxts_km_prepare + + slgr $inp,$fp # rewind $inp + la $s2,0($out,$inp) + lgr $s3,$fp + .long 0xb92e00aa # km $s2,$s2 + brc 1,.-4 # pay attention to "partial completion" + + la $s2,16($sp) + slgr $s2,$inp + srlg $s3,$fp,4 +.Lxts_km_xor: + lg $i1,0($out,$inp) + lg $i2,8($out,$inp) + xg $i1,0($s2,$inp) + xg $i2,8($s2,$inp) + stg $i1,0($out,$inp) + stg $i2,8($out,$inp) + la $inp,16($inp) + brct $s3,.Lxts_km_xor + + slgr $len,$fp + brc 1,.Lxts_km_loop # not zero, no borrow + algr $fp,$len + lghi $len,0 + brc 4+1,.Lxts_km_loop # not zero + + l${g} $i1,0($sp) # back-chain + llgf $fp,`2*$SIZE_T-4`($sp) # bytes used + la $i2,16($sp) + srlg $fp,$fp,4 +.Lxts_km_zap: + stg $i1,0($i2) + stg $i1,8($i2) + la $i2,16($i2) + brct $fp,.Lxts_km_zap + + la $sp,0($i1) + llgc $len,2*$SIZE_T-1($i1) + nill $len,0x0f # $len%=16 + bzr $ra + + # generate one more tweak... + lghi $i1,0x87 + srag $i2,$s1,63 # broadcast upper bit + ngr $i1,$i2 # rem + algr $s0,$s0 + alcgr $s1,$s1 + xgr $s0,$i1 + + ltr $len,$len # clear zero flag + br $ra +.size _s390x_xts_km,.-_s390x_xts_km + +.globl AES_xts_encrypt +.type AES_xts_encrypt,\@function +.align 16 +AES_xts_encrypt: + xgr %r3,%r4 # flip %r3 and %r4, $out and $len + xgr %r4,%r3 + xgr %r3,%r4 +___ +$code.=<<___ if ($SIZE_T==4); + llgfr $len,$len +___ +$code.=<<___; + st${g} $len,1*$SIZE_T($sp) # save copy of $len + srag $len,$len,4 # formally wrong, because it expands + # sign byte, but who can afford asking + # to process more than 2^63-1 bytes? + # I use it, because it sets condition + # code... + bcr 8,$ra # abort if zero (i.e. less than 16) +___ +$code.=<<___ if (!$softonly); + llgf %r0,240($key2) + lhi %r1,16 + clr %r0,%r1 + jl .Lxts_enc_software + + st${g} $ra,5*$SIZE_T($sp) + stm${g} %r6,$s3,6*$SIZE_T($sp) + + sllg $len,$len,4 # $len&=~15 + slgr $out,$inp + + # generate the tweak value + l${g} $s3,$stdframe($sp) # pointer to iv + la $s2,$tweak($sp) + lmg $s0,$s1,0($s3) + lghi $s3,16 + stmg $s0,$s1,0($s2) + la %r1,0($key2) # $key2 is not needed anymore + .long 0xb92e00aa # km $s2,$s2, generate the tweak + brc 1,.-4 # can this happen? + + l %r0,240($key1) + la %r1,0($key1) # $key1 is not needed anymore + bras $ra,_s390x_xts_km + jz .Lxts_enc_km_done + + aghi $inp,-16 # take one step back + la $i3,0($out,$inp) # put aside real $out +.Lxts_enc_km_steal: + llgc $i1,16($inp) + llgc $i2,0($out,$inp) + stc $i1,0($out,$inp) + stc $i2,16($out,$inp) + la $inp,1($inp) + brct $len,.Lxts_enc_km_steal + + la $s2,0($i3) + lghi $s3,16 + lrvgr $i1,$s0 # flip byte order + lrvgr $i2,$s1 + xg $i1,0($s2) + xg $i2,8($s2) + stg $i1,0($s2) + stg $i2,8($s2) + .long 0xb92e00aa # km $s2,$s2 + brc 1,.-4 # can this happen? + lrvgr $i1,$s0 # flip byte order + lrvgr $i2,$s1 + xg $i1,0($i3) + xg $i2,8($i3) + stg $i1,0($i3) + stg $i2,8($i3) + +.Lxts_enc_km_done: + stg $sp,$tweak+0($sp) # wipe tweak + stg $sp,$tweak+8($sp) + l${g} $ra,5*$SIZE_T($sp) + lm${g} %r6,$s3,6*$SIZE_T($sp) + br $ra +.align 16 +.Lxts_enc_software: +___ +$code.=<<___; + stm${g} %r6,$ra,6*$SIZE_T($sp) + + slgr $out,$inp + + l${g} $s3,$stdframe($sp) # ivp + llgf $s0,0($s3) # load iv + llgf $s1,4($s3) + llgf $s2,8($s3) + llgf $s3,12($s3) + stm${g} %r2,%r5,2*$SIZE_T($sp) + la $key,0($key2) + larl $tbl,AES_Te + bras $ra,_s390x_AES_encrypt # generate the tweak + lm${g} %r2,%r5,2*$SIZE_T($sp) + stm $s0,$s3,$tweak($sp) # save the tweak + j .Lxts_enc_enter + +.align 16 +.Lxts_enc_loop: + lrvg $s1,$tweak+0($sp) # load the tweak in little-endian + lrvg $s3,$tweak+8($sp) + lghi %r1,0x87 + srag %r0,$s3,63 # broadcast upper bit + ngr %r1,%r0 # rem + algr $s1,$s1 + alcgr $s3,$s3 + xgr $s1,%r1 + lrvgr $s1,$s1 # flip byte order + lrvgr $s3,$s3 + srlg $s0,$s1,32 # smash the tweak to 4x32-bits + stg $s1,$tweak+0($sp) # save the tweak + llgfr $s1,$s1 + srlg $s2,$s3,32 + stg $s3,$tweak+8($sp) + llgfr $s3,$s3 + la $inp,16($inp) # $inp+=16 +.Lxts_enc_enter: + x $s0,0($inp) # ^=*($inp) + x $s1,4($inp) + x $s2,8($inp) + x $s3,12($inp) + stm${g} %r2,%r3,2*$SIZE_T($sp) # only two registers are changing + la $key,0($key1) + bras $ra,_s390x_AES_encrypt + lm${g} %r2,%r5,2*$SIZE_T($sp) + x $s0,$tweak+0($sp) # ^=tweak + x $s1,$tweak+4($sp) + x $s2,$tweak+8($sp) + x $s3,$tweak+12($sp) + st $s0,0($out,$inp) + st $s1,4($out,$inp) + st $s2,8($out,$inp) + st $s3,12($out,$inp) + brct${g} $len,.Lxts_enc_loop + + llgc $len,`2*$SIZE_T-1`($sp) + nill $len,0x0f # $len%16 + jz .Lxts_enc_done + + la $i3,0($inp,$out) # put aside real $out +.Lxts_enc_steal: + llgc %r0,16($inp) + llgc %r1,0($out,$inp) + stc %r0,0($out,$inp) + stc %r1,16($out,$inp) + la $inp,1($inp) + brct $len,.Lxts_enc_steal + la $out,0($i3) # restore real $out + + # generate last tweak... + lrvg $s1,$tweak+0($sp) # load the tweak in little-endian + lrvg $s3,$tweak+8($sp) + lghi %r1,0x87 + srag %r0,$s3,63 # broadcast upper bit + ngr %r1,%r0 # rem + algr $s1,$s1 + alcgr $s3,$s3 + xgr $s1,%r1 + lrvgr $s1,$s1 # flip byte order + lrvgr $s3,$s3 + srlg $s0,$s1,32 # smash the tweak to 4x32-bits + stg $s1,$tweak+0($sp) # save the tweak + llgfr $s1,$s1 + srlg $s2,$s3,32 + stg $s3,$tweak+8($sp) + llgfr $s3,$s3 + + x $s0,0($out) # ^=*(inp)|stolen cipther-text + x $s1,4($out) + x $s2,8($out) + x $s3,12($out) + st${g} $out,4*$SIZE_T($sp) + la $key,0($key1) + bras $ra,_s390x_AES_encrypt + l${g} $out,4*$SIZE_T($sp) + x $s0,`$tweak+0`($sp) # ^=tweak + x $s1,`$tweak+4`($sp) + x $s2,`$tweak+8`($sp) + x $s3,`$tweak+12`($sp) + st $s0,0($out) + st $s1,4($out) + st $s2,8($out) + st $s3,12($out) + +.Lxts_enc_done: + stg $sp,$tweak+0($sp) # wipe tweak + stg $sp,$twesk+8($sp) + lm${g} %r6,$ra,6*$SIZE_T($sp) + br $ra +.size AES_xts_encrypt,.-AES_xts_encrypt +___ +# void AES_xts_decrypt(const unsigned char *inp, unsigned char *out, +# size_t len, const AES_KEY *key1, const AES_KEY *key2, +# const unsigned char iv[16]); +# +$code.=<<___; +.globl AES_xts_decrypt +.type AES_xts_decrypt,\@function +.align 16 +AES_xts_decrypt: + xgr %r3,%r4 # flip %r3 and %r4, $out and $len + xgr %r4,%r3 + xgr %r3,%r4 +___ +$code.=<<___ if ($SIZE_T==4); + llgfr $len,$len +___ +$code.=<<___; + st${g} $len,1*$SIZE_T($sp) # save copy of $len + aghi $len,-16 + bcr 4,$ra # abort if less than zero. formally + # wrong, because $len is unsigned, + # but who can afford asking to + # process more than 2^63-1 bytes? + tmll $len,0x0f + jnz .Lxts_dec_proceed + aghi $len,16 +.Lxts_dec_proceed: +___ +$code.=<<___ if (!$softonly); + llgf %r0,240($key2) + lhi %r1,16 + clr %r0,%r1 + jl .Lxts_dec_software + + st${g} $ra,5*$SIZE_T($sp) + stm${g} %r6,$s3,6*$SIZE_T($sp) + + nill $len,0xfff0 # $len&=~15 + slgr $out,$inp + + # generate the tweak value + l${g} $s3,$stdframe($sp) # pointer to iv + la $s2,$tweak($sp) + lmg $s0,$s1,0($s3) + lghi $s3,16 + stmg $s0,$s1,0($s2) + la %r1,0($key2) # $key2 is not needed past this point + .long 0xb92e00aa # km $s2,$s2, generate the tweak + brc 1,.-4 # can this happen? + + l %r0,240($key1) + la %r1,0($key1) # $key1 is not needed anymore + + ltgr $len,$len + jz .Lxts_dec_km_short + bras $ra,_s390x_xts_km + jz .Lxts_dec_km_done + + lrvgr $s2,$s0 # make copy in reverse byte order + lrvgr $s3,$s1 + j .Lxts_dec_km_2ndtweak + +.Lxts_dec_km_short: + llgc $len,`2*$SIZE_T-1`($sp) + nill $len,0x0f # $len%=16 + lrvg $s0,$tweak+0($sp) # load the tweak + lrvg $s1,$tweak+8($sp) + lrvgr $s2,$s0 # make copy in reverse byte order + lrvgr $s3,$s1 + +.Lxts_dec_km_2ndtweak: + lghi $i1,0x87 + srag $i2,$s1,63 # broadcast upper bit + ngr $i1,$i2 # rem + algr $s0,$s0 + alcgr $s1,$s1 + xgr $s0,$i1 + lrvgr $i1,$s0 # flip byte order + lrvgr $i2,$s1 + + xg $i1,0($inp) + xg $i2,8($inp) + stg $i1,0($out,$inp) + stg $i2,8($out,$inp) + la $i2,0($out,$inp) + lghi $i3,16 + .long 0xb92e0066 # km $i2,$i2 + brc 1,.-4 # can this happen? + lrvgr $i1,$s0 + lrvgr $i2,$s1 + xg $i1,0($out,$inp) + xg $i2,8($out,$inp) + stg $i1,0($out,$inp) + stg $i2,8($out,$inp) + + la $i3,0($out,$inp) # put aside real $out +.Lxts_dec_km_steal: + llgc $i1,16($inp) + llgc $i2,0($out,$inp) + stc $i1,0($out,$inp) + stc $i2,16($out,$inp) + la $inp,1($inp) + brct $len,.Lxts_dec_km_steal + + lgr $s0,$s2 + lgr $s1,$s3 + xg $s0,0($i3) + xg $s1,8($i3) + stg $s0,0($i3) + stg $s1,8($i3) + la $s0,0($i3) + lghi $s1,16 + .long 0xb92e0088 # km $s0,$s0 + brc 1,.-4 # can this happen? + xg $s2,0($i3) + xg $s3,8($i3) + stg $s2,0($i3) + stg $s3,8($i3) +.Lxts_dec_km_done: + stg $sp,$tweak+0($sp) # wipe tweak + stg $sp,$tweak+8($sp) + l${g} $ra,5*$SIZE_T($sp) + lm${g} %r6,$s3,6*$SIZE_T($sp) + br $ra +.align 16 +.Lxts_dec_software: +___ +$code.=<<___; + stm${g} %r6,$ra,6*$SIZE_T($sp) + + srlg $len,$len,4 + slgr $out,$inp + + l${g} $s3,$stdframe($sp) # ivp + llgf $s0,0($s3) # load iv + llgf $s1,4($s3) + llgf $s2,8($s3) + llgf $s3,12($s3) + stm${g} %r2,%r5,2*$SIZE_T($sp) + la $key,0($key2) + larl $tbl,AES_Te + bras $ra,_s390x_AES_encrypt # generate the tweak + lm${g} %r2,%r5,2*$SIZE_T($sp) + larl $tbl,AES_Td + lt${g}r $len,$len + stm $s0,$s3,$tweak($sp) # save the tweak + jz .Lxts_dec_short + j .Lxts_dec_enter + +.align 16 +.Lxts_dec_loop: + lrvg $s1,$tweak+0($sp) # load the tweak in little-endian + lrvg $s3,$tweak+8($sp) + lghi %r1,0x87 + srag %r0,$s3,63 # broadcast upper bit + ngr %r1,%r0 # rem + algr $s1,$s1 + alcgr $s3,$s3 + xgr $s1,%r1 + lrvgr $s1,$s1 # flip byte order + lrvgr $s3,$s3 + srlg $s0,$s1,32 # smash the tweak to 4x32-bits + stg $s1,$tweak+0($sp) # save the tweak + llgfr $s1,$s1 + srlg $s2,$s3,32 + stg $s3,$tweak+8($sp) + llgfr $s3,$s3 +.Lxts_dec_enter: + x $s0,0($inp) # tweak^=*(inp) + x $s1,4($inp) + x $s2,8($inp) + x $s3,12($inp) + stm${g} %r2,%r3,2*$SIZE_T($sp) # only two registers are changing + la $key,0($key1) + bras $ra,_s390x_AES_decrypt + lm${g} %r2,%r5,2*$SIZE_T($sp) + x $s0,$tweak+0($sp) # ^=tweak + x $s1,$tweak+4($sp) + x $s2,$tweak+8($sp) + x $s3,$tweak+12($sp) + st $s0,0($out,$inp) + st $s1,4($out,$inp) + st $s2,8($out,$inp) + st $s3,12($out,$inp) + la $inp,16($inp) + brct${g} $len,.Lxts_dec_loop + + llgc $len,`2*$SIZE_T-1`($sp) + nill $len,0x0f # $len%16 + jz .Lxts_dec_done + + # generate pair of tweaks... + lrvg $s1,$tweak+0($sp) # load the tweak in little-endian + lrvg $s3,$tweak+8($sp) + lghi %r1,0x87 + srag %r0,$s3,63 # broadcast upper bit + ngr %r1,%r0 # rem + algr $s1,$s1 + alcgr $s3,$s3 + xgr $s1,%r1 + lrvgr $i2,$s1 # flip byte order + lrvgr $i3,$s3 + stmg $i2,$i3,$tweak($sp) # save the 1st tweak + j .Lxts_dec_2ndtweak + +.align 16 +.Lxts_dec_short: + llgc $len,`2*$SIZE_T-1`($sp) + nill $len,0x0f # $len%16 + lrvg $s1,$tweak+0($sp) # load the tweak in little-endian + lrvg $s3,$tweak+8($sp) +.Lxts_dec_2ndtweak: + lghi %r1,0x87 + srag %r0,$s3,63 # broadcast upper bit + ngr %r1,%r0 # rem + algr $s1,$s1 + alcgr $s3,$s3 + xgr $s1,%r1 + lrvgr $s1,$s1 # flip byte order + lrvgr $s3,$s3 + srlg $s0,$s1,32 # smash the tweak to 4x32-bits + stg $s1,$tweak-16+0($sp) # save the 2nd tweak + llgfr $s1,$s1 + srlg $s2,$s3,32 + stg $s3,$tweak-16+8($sp) + llgfr $s3,$s3 + + x $s0,0($inp) # tweak_the_2nd^=*(inp) + x $s1,4($inp) + x $s2,8($inp) + x $s3,12($inp) + stm${g} %r2,%r3,2*$SIZE_T($sp) + la $key,0($key1) + bras $ra,_s390x_AES_decrypt + lm${g} %r2,%r5,2*$SIZE_T($sp) + x $s0,$tweak-16+0($sp) # ^=tweak_the_2nd + x $s1,$tweak-16+4($sp) + x $s2,$tweak-16+8($sp) + x $s3,$tweak-16+12($sp) + st $s0,0($out,$inp) + st $s1,4($out,$inp) + st $s2,8($out,$inp) + st $s3,12($out,$inp) + + la $i3,0($out,$inp) # put aside real $out +.Lxts_dec_steal: + llgc %r0,16($inp) + llgc %r1,0($out,$inp) + stc %r0,0($out,$inp) + stc %r1,16($out,$inp) + la $inp,1($inp) + brct $len,.Lxts_dec_steal + la $out,0($i3) # restore real $out + + lm $s0,$s3,$tweak($sp) # load the 1st tweak + x $s0,0($out) # tweak^=*(inp)|stolen cipher-text + x $s1,4($out) + x $s2,8($out) + x $s3,12($out) + st${g} $out,4*$SIZE_T($sp) + la $key,0($key1) + bras $ra,_s390x_AES_decrypt + l${g} $out,4*$SIZE_T($sp) + x $s0,$tweak+0($sp) # ^=tweak + x $s1,$tweak+4($sp) + x $s2,$tweak+8($sp) + x $s3,$tweak+12($sp) + st $s0,0($out) + st $s1,4($out) + st $s2,8($out) + st $s3,12($out) + stg $sp,$tweak-16+0($sp) # wipe 2nd tweak + stg $sp,$tweak-16+8($sp) +.Lxts_dec_done: + stg $sp,$tweak+0($sp) # wipe tweak + stg $sp,$twesk+8($sp) + lm${g} %r6,$ra,6*$SIZE_T($sp) + br $ra +.size AES_xts_decrypt,.-AES_xts_decrypt +___ +} +$code.=<<___; +.string "AES for s390x, CRYPTOGAMS by " +___ + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +print $code; +close STDOUT; # force flush diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-sparcv9.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-sparcv9.pl new file mode 100755 index 000000000..40d1f94cc --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-sparcv9.pl @@ -0,0 +1,1192 @@ +#! /usr/bin/env perl +# Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. Rights for redistribution and usage in source and binary +# forms are granted according to the OpenSSL license. +# ==================================================================== +# +# Version 1.1 +# +# The major reason for undertaken effort was to mitigate the hazard of +# cache-timing attack. This is [currently and initially!] addressed in +# two ways. 1. S-boxes are compressed from 5KB to 2KB+256B size each. +# 2. References to them are scheduled for L2 cache latency, meaning +# that the tables don't have to reside in L1 cache. Once again, this +# is an initial draft and one should expect more countermeasures to +# be implemented... +# +# Version 1.1 prefetches T[ed]4 in order to mitigate attack on last +# round. +# +# Even though performance was not the primary goal [on the contrary, +# extra shifts "induced" by compressed S-box and longer loop epilogue +# "induced" by scheduling for L2 have negative effect on performance], +# the code turned out to run in ~23 cycles per processed byte en-/ +# decrypted with 128-bit key. This is pretty good result for code +# with mentioned qualities and UltraSPARC core. Compared to Sun C +# generated code my encrypt procedure runs just few percents faster, +# while decrypt one - whole 50% faster [yes, Sun C failed to generate +# optimal decrypt procedure]. Compared to GNU C generated code both +# procedures are more than 60% faster:-) + +$output = pop; +open STDOUT,">$output"; + +$frame="STACK_FRAME"; +$bias="STACK_BIAS"; +$locals=16; + +$acc0="%l0"; +$acc1="%o0"; +$acc2="%o1"; +$acc3="%o2"; + +$acc4="%l1"; +$acc5="%o3"; +$acc6="%o4"; +$acc7="%o5"; + +$acc8="%l2"; +$acc9="%o7"; +$acc10="%g1"; +$acc11="%g2"; + +$acc12="%l3"; +$acc13="%g3"; +$acc14="%g4"; +$acc15="%g5"; + +$t0="%l4"; +$t1="%l5"; +$t2="%l6"; +$t3="%l7"; + +$s0="%i0"; +$s1="%i1"; +$s2="%i2"; +$s3="%i3"; +$tbl="%i4"; +$key="%i5"; +$rounds="%i7"; # aliases with return address, which is off-loaded to stack + +sub _data_word() +{ my $i; + while(defined($i=shift)) { $code.=sprintf"\t.long\t0x%08x,0x%08x\n",$i,$i; } +} + +$code.=<<___; +#include "sparc_arch.h" + +#ifdef __arch64__ +.register %g2,#scratch +.register %g3,#scratch +#endif +.section ".text",#alloc,#execinstr + +.align 256 +AES_Te: +___ +&_data_word( + 0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, + 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, + 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, + 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, + 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, + 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, + 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, + 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, + 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, + 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, + 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, + 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f, + 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, + 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, + 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, + 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, + 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, + 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, + 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, + 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, + 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, + 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, + 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, + 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, + 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, + 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, + 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, + 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, + 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, + 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, + 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, + 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d, + 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, + 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, + 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, + 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, + 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, + 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, + 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, + 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, + 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, + 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, + 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, + 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b, + 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, + 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, + 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, + 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818, + 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, + 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, + 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, + 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, + 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, + 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, + 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, + 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, + 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, + 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, + 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, + 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a, + 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, + 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, + 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, + 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a); +$code.=<<___; + .byte 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5 + .byte 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76 + .byte 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0 + .byte 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0 + .byte 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc + .byte 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15 + .byte 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a + .byte 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75 + .byte 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0 + .byte 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84 + .byte 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b + .byte 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf + .byte 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85 + .byte 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8 + .byte 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5 + .byte 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2 + .byte 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17 + .byte 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73 + .byte 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88 + .byte 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb + .byte 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c + .byte 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79 + .byte 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9 + .byte 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08 + .byte 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6 + .byte 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a + .byte 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e + .byte 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e + .byte 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94 + .byte 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf + .byte 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68 + .byte 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +.type AES_Te,#object +.size AES_Te,(.-AES_Te) + +.align 64 +.skip 16 +_sparcv9_AES_encrypt: + save %sp,-$frame-$locals,%sp + stx %i7,[%sp+$bias+$frame+0] ! off-load return address + ld [$key+240],$rounds + ld [$key+0],$t0 + ld [$key+4],$t1 ! + ld [$key+8],$t2 + srl $rounds,1,$rounds + xor $t0,$s0,$s0 + ld [$key+12],$t3 + srl $s0,21,$acc0 + xor $t1,$s1,$s1 + ld [$key+16],$t0 + srl $s1,13,$acc1 ! + xor $t2,$s2,$s2 + ld [$key+20],$t1 + xor $t3,$s3,$s3 + ld [$key+24],$t2 + and $acc0,2040,$acc0 + ld [$key+28],$t3 + nop +.Lenc_loop: + srl $s2,5,$acc2 ! + and $acc1,2040,$acc1 + ldx [$tbl+$acc0],$acc0 + sll $s3,3,$acc3 + and $acc2,2040,$acc2 + ldx [$tbl+$acc1],$acc1 + srl $s1,21,$acc4 + and $acc3,2040,$acc3 + ldx [$tbl+$acc2],$acc2 ! + srl $s2,13,$acc5 + and $acc4,2040,$acc4 + ldx [$tbl+$acc3],$acc3 + srl $s3,5,$acc6 + and $acc5,2040,$acc5 + ldx [$tbl+$acc4],$acc4 + fmovs %f0,%f0 + sll $s0,3,$acc7 ! + and $acc6,2040,$acc6 + ldx [$tbl+$acc5],$acc5 + srl $s2,21,$acc8 + and $acc7,2040,$acc7 + ldx [$tbl+$acc6],$acc6 + srl $s3,13,$acc9 + and $acc8,2040,$acc8 + ldx [$tbl+$acc7],$acc7 ! + srl $s0,5,$acc10 + and $acc9,2040,$acc9 + ldx [$tbl+$acc8],$acc8 + sll $s1,3,$acc11 + and $acc10,2040,$acc10 + ldx [$tbl+$acc9],$acc9 + fmovs %f0,%f0 + srl $s3,21,$acc12 ! + and $acc11,2040,$acc11 + ldx [$tbl+$acc10],$acc10 + srl $s0,13,$acc13 + and $acc12,2040,$acc12 + ldx [$tbl+$acc11],$acc11 + srl $s1,5,$acc14 + and $acc13,2040,$acc13 + ldx [$tbl+$acc12],$acc12 ! + sll $s2,3,$acc15 + and $acc14,2040,$acc14 + ldx [$tbl+$acc13],$acc13 + and $acc15,2040,$acc15 + add $key,32,$key + ldx [$tbl+$acc14],$acc14 + fmovs %f0,%f0 + subcc $rounds,1,$rounds ! + ldx [$tbl+$acc15],$acc15 + bz,a,pn %icc,.Lenc_last + add $tbl,2048,$rounds + + srlx $acc1,8,$acc1 + xor $acc0,$t0,$t0 + ld [$key+0],$s0 + fmovs %f0,%f0 + srlx $acc2,16,$acc2 ! + xor $acc1,$t0,$t0 + ld [$key+4],$s1 + srlx $acc3,24,$acc3 + xor $acc2,$t0,$t0 + ld [$key+8],$s2 + srlx $acc5,8,$acc5 + xor $acc3,$t0,$t0 + ld [$key+12],$s3 ! + srlx $acc6,16,$acc6 + xor $acc4,$t1,$t1 + fmovs %f0,%f0 + srlx $acc7,24,$acc7 + xor $acc5,$t1,$t1 + srlx $acc9,8,$acc9 + xor $acc6,$t1,$t1 + srlx $acc10,16,$acc10 ! + xor $acc7,$t1,$t1 + srlx $acc11,24,$acc11 + xor $acc8,$t2,$t2 + srlx $acc13,8,$acc13 + xor $acc9,$t2,$t2 + srlx $acc14,16,$acc14 + xor $acc10,$t2,$t2 + srlx $acc15,24,$acc15 ! + xor $acc11,$t2,$t2 + xor $acc12,$acc14,$acc14 + xor $acc13,$t3,$t3 + srl $t0,21,$acc0 + xor $acc14,$t3,$t3 + srl $t1,13,$acc1 + xor $acc15,$t3,$t3 + + and $acc0,2040,$acc0 ! + srl $t2,5,$acc2 + and $acc1,2040,$acc1 + ldx [$tbl+$acc0],$acc0 + sll $t3,3,$acc3 + and $acc2,2040,$acc2 + ldx [$tbl+$acc1],$acc1 + fmovs %f0,%f0 + srl $t1,21,$acc4 ! + and $acc3,2040,$acc3 + ldx [$tbl+$acc2],$acc2 + srl $t2,13,$acc5 + and $acc4,2040,$acc4 + ldx [$tbl+$acc3],$acc3 + srl $t3,5,$acc6 + and $acc5,2040,$acc5 + ldx [$tbl+$acc4],$acc4 ! + sll $t0,3,$acc7 + and $acc6,2040,$acc6 + ldx [$tbl+$acc5],$acc5 + srl $t2,21,$acc8 + and $acc7,2040,$acc7 + ldx [$tbl+$acc6],$acc6 + fmovs %f0,%f0 + srl $t3,13,$acc9 ! + and $acc8,2040,$acc8 + ldx [$tbl+$acc7],$acc7 + srl $t0,5,$acc10 + and $acc9,2040,$acc9 + ldx [$tbl+$acc8],$acc8 + sll $t1,3,$acc11 + and $acc10,2040,$acc10 + ldx [$tbl+$acc9],$acc9 ! + srl $t3,21,$acc12 + and $acc11,2040,$acc11 + ldx [$tbl+$acc10],$acc10 + srl $t0,13,$acc13 + and $acc12,2040,$acc12 + ldx [$tbl+$acc11],$acc11 + fmovs %f0,%f0 + srl $t1,5,$acc14 ! + and $acc13,2040,$acc13 + ldx [$tbl+$acc12],$acc12 + sll $t2,3,$acc15 + and $acc14,2040,$acc14 + ldx [$tbl+$acc13],$acc13 + srlx $acc1,8,$acc1 + and $acc15,2040,$acc15 + ldx [$tbl+$acc14],$acc14 ! + + srlx $acc2,16,$acc2 + xor $acc0,$s0,$s0 + ldx [$tbl+$acc15],$acc15 + srlx $acc3,24,$acc3 + xor $acc1,$s0,$s0 + ld [$key+16],$t0 + fmovs %f0,%f0 + srlx $acc5,8,$acc5 ! + xor $acc2,$s0,$s0 + ld [$key+20],$t1 + srlx $acc6,16,$acc6 + xor $acc3,$s0,$s0 + ld [$key+24],$t2 + srlx $acc7,24,$acc7 + xor $acc4,$s1,$s1 + ld [$key+28],$t3 ! + srlx $acc9,8,$acc9 + xor $acc5,$s1,$s1 + ldx [$tbl+2048+0],%g0 ! prefetch te4 + srlx $acc10,16,$acc10 + xor $acc6,$s1,$s1 + ldx [$tbl+2048+32],%g0 ! prefetch te4 + srlx $acc11,24,$acc11 + xor $acc7,$s1,$s1 + ldx [$tbl+2048+64],%g0 ! prefetch te4 + srlx $acc13,8,$acc13 + xor $acc8,$s2,$s2 + ldx [$tbl+2048+96],%g0 ! prefetch te4 + srlx $acc14,16,$acc14 ! + xor $acc9,$s2,$s2 + ldx [$tbl+2048+128],%g0 ! prefetch te4 + srlx $acc15,24,$acc15 + xor $acc10,$s2,$s2 + ldx [$tbl+2048+160],%g0 ! prefetch te4 + srl $s0,21,$acc0 + xor $acc11,$s2,$s2 + ldx [$tbl+2048+192],%g0 ! prefetch te4 + xor $acc12,$acc14,$acc14 + xor $acc13,$s3,$s3 + ldx [$tbl+2048+224],%g0 ! prefetch te4 + srl $s1,13,$acc1 ! + xor $acc14,$s3,$s3 + xor $acc15,$s3,$s3 + ba .Lenc_loop + and $acc0,2040,$acc0 + +.align 32 +.Lenc_last: + srlx $acc1,8,$acc1 ! + xor $acc0,$t0,$t0 + ld [$key+0],$s0 + srlx $acc2,16,$acc2 + xor $acc1,$t0,$t0 + ld [$key+4],$s1 + srlx $acc3,24,$acc3 + xor $acc2,$t0,$t0 + ld [$key+8],$s2 ! + srlx $acc5,8,$acc5 + xor $acc3,$t0,$t0 + ld [$key+12],$s3 + srlx $acc6,16,$acc6 + xor $acc4,$t1,$t1 + srlx $acc7,24,$acc7 + xor $acc5,$t1,$t1 + srlx $acc9,8,$acc9 ! + xor $acc6,$t1,$t1 + srlx $acc10,16,$acc10 + xor $acc7,$t1,$t1 + srlx $acc11,24,$acc11 + xor $acc8,$t2,$t2 + srlx $acc13,8,$acc13 + xor $acc9,$t2,$t2 + srlx $acc14,16,$acc14 ! + xor $acc10,$t2,$t2 + srlx $acc15,24,$acc15 + xor $acc11,$t2,$t2 + xor $acc12,$acc14,$acc14 + xor $acc13,$t3,$t3 + srl $t0,24,$acc0 + xor $acc14,$t3,$t3 + srl $t1,16,$acc1 ! + xor $acc15,$t3,$t3 + + srl $t2,8,$acc2 + and $acc1,255,$acc1 + ldub [$rounds+$acc0],$acc0 + srl $t1,24,$acc4 + and $acc2,255,$acc2 + ldub [$rounds+$acc1],$acc1 + srl $t2,16,$acc5 ! + and $t3,255,$acc3 + ldub [$rounds+$acc2],$acc2 + ldub [$rounds+$acc3],$acc3 + srl $t3,8,$acc6 + and $acc5,255,$acc5 + ldub [$rounds+$acc4],$acc4 + fmovs %f0,%f0 + srl $t2,24,$acc8 ! + and $acc6,255,$acc6 + ldub [$rounds+$acc5],$acc5 + srl $t3,16,$acc9 + and $t0,255,$acc7 + ldub [$rounds+$acc6],$acc6 + ldub [$rounds+$acc7],$acc7 + fmovs %f0,%f0 + srl $t0,8,$acc10 ! + and $acc9,255,$acc9 + ldub [$rounds+$acc8],$acc8 + srl $t3,24,$acc12 + and $acc10,255,$acc10 + ldub [$rounds+$acc9],$acc9 + srl $t0,16,$acc13 + and $t1,255,$acc11 + ldub [$rounds+$acc10],$acc10 ! + srl $t1,8,$acc14 + and $acc13,255,$acc13 + ldub [$rounds+$acc11],$acc11 + ldub [$rounds+$acc12],$acc12 + and $acc14,255,$acc14 + ldub [$rounds+$acc13],$acc13 + and $t2,255,$acc15 + ldub [$rounds+$acc14],$acc14 ! + + sll $acc0,24,$acc0 + xor $acc3,$s0,$s0 + ldub [$rounds+$acc15],$acc15 + sll $acc1,16,$acc1 + xor $acc0,$s0,$s0 + ldx [%sp+$bias+$frame+0],%i7 ! restore return address + fmovs %f0,%f0 + sll $acc2,8,$acc2 ! + xor $acc1,$s0,$s0 + sll $acc4,24,$acc4 + xor $acc2,$s0,$s0 + sll $acc5,16,$acc5 + xor $acc7,$s1,$s1 + sll $acc6,8,$acc6 + xor $acc4,$s1,$s1 + sll $acc8,24,$acc8 ! + xor $acc5,$s1,$s1 + sll $acc9,16,$acc9 + xor $acc11,$s2,$s2 + sll $acc10,8,$acc10 + xor $acc6,$s1,$s1 + sll $acc12,24,$acc12 + xor $acc8,$s2,$s2 + sll $acc13,16,$acc13 ! + xor $acc9,$s2,$s2 + sll $acc14,8,$acc14 + xor $acc10,$s2,$s2 + xor $acc12,$acc14,$acc14 + xor $acc13,$s3,$s3 + xor $acc14,$s3,$s3 + xor $acc15,$s3,$s3 + + ret + restore +.type _sparcv9_AES_encrypt,#function +.size _sparcv9_AES_encrypt,(.-_sparcv9_AES_encrypt) + +.align 32 +.globl AES_encrypt +AES_encrypt: + or %o0,%o1,%g1 + andcc %g1,3,%g0 + bnz,pn %xcc,.Lunaligned_enc + save %sp,-$frame,%sp + + ld [%i0+0],%o0 + ld [%i0+4],%o1 + ld [%i0+8],%o2 + ld [%i0+12],%o3 + +1: call .+8 + add %o7,AES_Te-1b,%o4 + call _sparcv9_AES_encrypt + mov %i2,%o5 + + st %o0,[%i1+0] + st %o1,[%i1+4] + st %o2,[%i1+8] + st %o3,[%i1+12] + + ret + restore + +.align 32 +.Lunaligned_enc: + ldub [%i0+0],%l0 + ldub [%i0+1],%l1 + ldub [%i0+2],%l2 + + sll %l0,24,%l0 + ldub [%i0+3],%l3 + sll %l1,16,%l1 + ldub [%i0+4],%l4 + sll %l2,8,%l2 + or %l1,%l0,%l0 + ldub [%i0+5],%l5 + sll %l4,24,%l4 + or %l3,%l2,%l2 + ldub [%i0+6],%l6 + sll %l5,16,%l5 + or %l0,%l2,%o0 + ldub [%i0+7],%l7 + + sll %l6,8,%l6 + or %l5,%l4,%l4 + ldub [%i0+8],%l0 + or %l7,%l6,%l6 + ldub [%i0+9],%l1 + or %l4,%l6,%o1 + ldub [%i0+10],%l2 + + sll %l0,24,%l0 + ldub [%i0+11],%l3 + sll %l1,16,%l1 + ldub [%i0+12],%l4 + sll %l2,8,%l2 + or %l1,%l0,%l0 + ldub [%i0+13],%l5 + sll %l4,24,%l4 + or %l3,%l2,%l2 + ldub [%i0+14],%l6 + sll %l5,16,%l5 + or %l0,%l2,%o2 + ldub [%i0+15],%l7 + + sll %l6,8,%l6 + or %l5,%l4,%l4 + or %l7,%l6,%l6 + or %l4,%l6,%o3 + +1: call .+8 + add %o7,AES_Te-1b,%o4 + call _sparcv9_AES_encrypt + mov %i2,%o5 + + srl %o0,24,%l0 + srl %o0,16,%l1 + stb %l0,[%i1+0] + srl %o0,8,%l2 + stb %l1,[%i1+1] + stb %l2,[%i1+2] + srl %o1,24,%l4 + stb %o0,[%i1+3] + + srl %o1,16,%l5 + stb %l4,[%i1+4] + srl %o1,8,%l6 + stb %l5,[%i1+5] + stb %l6,[%i1+6] + srl %o2,24,%l0 + stb %o1,[%i1+7] + + srl %o2,16,%l1 + stb %l0,[%i1+8] + srl %o2,8,%l2 + stb %l1,[%i1+9] + stb %l2,[%i1+10] + srl %o3,24,%l4 + stb %o2,[%i1+11] + + srl %o3,16,%l5 + stb %l4,[%i1+12] + srl %o3,8,%l6 + stb %l5,[%i1+13] + stb %l6,[%i1+14] + stb %o3,[%i1+15] + + ret + restore +.type AES_encrypt,#function +.size AES_encrypt,(.-AES_encrypt) + +___ + +$code.=<<___; +.align 256 +AES_Td: +___ +&_data_word( + 0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, + 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, + 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, + 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, + 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, + 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, + 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, + 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844, + 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, + 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, + 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, + 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94, + 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, + 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a, + 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, + 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c, + 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, + 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, + 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, + 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, + 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, + 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, + 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, + 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, + 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, + 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, + 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, + 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a, + 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, + 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16, + 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, + 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8, + 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, + 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, + 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, + 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120, + 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, + 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, + 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, + 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, + 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, + 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, + 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, + 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5, + 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, + 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, + 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, + 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6, + 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, + 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0, + 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, + 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f, + 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, + 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, + 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, + 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, + 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, + 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, + 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, + 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86, + 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, + 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, + 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, + 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742); +$code.=<<___; + .byte 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38 + .byte 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb + .byte 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87 + .byte 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb + .byte 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d + .byte 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e + .byte 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2 + .byte 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 + .byte 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16 + .byte 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 + .byte 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda + .byte 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 + .byte 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a + .byte 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 + .byte 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02 + .byte 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b + .byte 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea + .byte 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 + .byte 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85 + .byte 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e + .byte 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89 + .byte 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b + .byte 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20 + .byte 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 + .byte 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31 + .byte 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f + .byte 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d + .byte 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef + .byte 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0 + .byte 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 + .byte 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26 + .byte 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d +.type AES_Td,#object +.size AES_Td,(.-AES_Td) + +.align 64 +.skip 16 +_sparcv9_AES_decrypt: + save %sp,-$frame-$locals,%sp + stx %i7,[%sp+$bias+$frame+0] ! off-load return address + ld [$key+240],$rounds + ld [$key+0],$t0 + ld [$key+4],$t1 ! + ld [$key+8],$t2 + ld [$key+12],$t3 + srl $rounds,1,$rounds + xor $t0,$s0,$s0 + ld [$key+16],$t0 + xor $t1,$s1,$s1 + ld [$key+20],$t1 + srl $s0,21,$acc0 ! + xor $t2,$s2,$s2 + ld [$key+24],$t2 + xor $t3,$s3,$s3 + and $acc0,2040,$acc0 + ld [$key+28],$t3 + srl $s3,13,$acc1 + nop +.Ldec_loop: + srl $s2,5,$acc2 ! + and $acc1,2040,$acc1 + ldx [$tbl+$acc0],$acc0 + sll $s1,3,$acc3 + and $acc2,2040,$acc2 + ldx [$tbl+$acc1],$acc1 + srl $s1,21,$acc4 + and $acc3,2040,$acc3 + ldx [$tbl+$acc2],$acc2 ! + srl $s0,13,$acc5 + and $acc4,2040,$acc4 + ldx [$tbl+$acc3],$acc3 + srl $s3,5,$acc6 + and $acc5,2040,$acc5 + ldx [$tbl+$acc4],$acc4 + fmovs %f0,%f0 + sll $s2,3,$acc7 ! + and $acc6,2040,$acc6 + ldx [$tbl+$acc5],$acc5 + srl $s2,21,$acc8 + and $acc7,2040,$acc7 + ldx [$tbl+$acc6],$acc6 + srl $s1,13,$acc9 + and $acc8,2040,$acc8 + ldx [$tbl+$acc7],$acc7 ! + srl $s0,5,$acc10 + and $acc9,2040,$acc9 + ldx [$tbl+$acc8],$acc8 + sll $s3,3,$acc11 + and $acc10,2040,$acc10 + ldx [$tbl+$acc9],$acc9 + fmovs %f0,%f0 + srl $s3,21,$acc12 ! + and $acc11,2040,$acc11 + ldx [$tbl+$acc10],$acc10 + srl $s2,13,$acc13 + and $acc12,2040,$acc12 + ldx [$tbl+$acc11],$acc11 + srl $s1,5,$acc14 + and $acc13,2040,$acc13 + ldx [$tbl+$acc12],$acc12 ! + sll $s0,3,$acc15 + and $acc14,2040,$acc14 + ldx [$tbl+$acc13],$acc13 + and $acc15,2040,$acc15 + add $key,32,$key + ldx [$tbl+$acc14],$acc14 + fmovs %f0,%f0 + subcc $rounds,1,$rounds ! + ldx [$tbl+$acc15],$acc15 + bz,a,pn %icc,.Ldec_last + add $tbl,2048,$rounds + + srlx $acc1,8,$acc1 + xor $acc0,$t0,$t0 + ld [$key+0],$s0 + fmovs %f0,%f0 + srlx $acc2,16,$acc2 ! + xor $acc1,$t0,$t0 + ld [$key+4],$s1 + srlx $acc3,24,$acc3 + xor $acc2,$t0,$t0 + ld [$key+8],$s2 + srlx $acc5,8,$acc5 + xor $acc3,$t0,$t0 + ld [$key+12],$s3 ! + srlx $acc6,16,$acc6 + xor $acc4,$t1,$t1 + fmovs %f0,%f0 + srlx $acc7,24,$acc7 + xor $acc5,$t1,$t1 + srlx $acc9,8,$acc9 + xor $acc6,$t1,$t1 + srlx $acc10,16,$acc10 ! + xor $acc7,$t1,$t1 + srlx $acc11,24,$acc11 + xor $acc8,$t2,$t2 + srlx $acc13,8,$acc13 + xor $acc9,$t2,$t2 + srlx $acc14,16,$acc14 + xor $acc10,$t2,$t2 + srlx $acc15,24,$acc15 ! + xor $acc11,$t2,$t2 + xor $acc12,$acc14,$acc14 + xor $acc13,$t3,$t3 + srl $t0,21,$acc0 + xor $acc14,$t3,$t3 + xor $acc15,$t3,$t3 + srl $t3,13,$acc1 + + and $acc0,2040,$acc0 ! + srl $t2,5,$acc2 + and $acc1,2040,$acc1 + ldx [$tbl+$acc0],$acc0 + sll $t1,3,$acc3 + and $acc2,2040,$acc2 + ldx [$tbl+$acc1],$acc1 + fmovs %f0,%f0 + srl $t1,21,$acc4 ! + and $acc3,2040,$acc3 + ldx [$tbl+$acc2],$acc2 + srl $t0,13,$acc5 + and $acc4,2040,$acc4 + ldx [$tbl+$acc3],$acc3 + srl $t3,5,$acc6 + and $acc5,2040,$acc5 + ldx [$tbl+$acc4],$acc4 ! + sll $t2,3,$acc7 + and $acc6,2040,$acc6 + ldx [$tbl+$acc5],$acc5 + srl $t2,21,$acc8 + and $acc7,2040,$acc7 + ldx [$tbl+$acc6],$acc6 + fmovs %f0,%f0 + srl $t1,13,$acc9 ! + and $acc8,2040,$acc8 + ldx [$tbl+$acc7],$acc7 + srl $t0,5,$acc10 + and $acc9,2040,$acc9 + ldx [$tbl+$acc8],$acc8 + sll $t3,3,$acc11 + and $acc10,2040,$acc10 + ldx [$tbl+$acc9],$acc9 ! + srl $t3,21,$acc12 + and $acc11,2040,$acc11 + ldx [$tbl+$acc10],$acc10 + srl $t2,13,$acc13 + and $acc12,2040,$acc12 + ldx [$tbl+$acc11],$acc11 + fmovs %f0,%f0 + srl $t1,5,$acc14 ! + and $acc13,2040,$acc13 + ldx [$tbl+$acc12],$acc12 + sll $t0,3,$acc15 + and $acc14,2040,$acc14 + ldx [$tbl+$acc13],$acc13 + srlx $acc1,8,$acc1 + and $acc15,2040,$acc15 + ldx [$tbl+$acc14],$acc14 ! + + srlx $acc2,16,$acc2 + xor $acc0,$s0,$s0 + ldx [$tbl+$acc15],$acc15 + srlx $acc3,24,$acc3 + xor $acc1,$s0,$s0 + ld [$key+16],$t0 + fmovs %f0,%f0 + srlx $acc5,8,$acc5 ! + xor $acc2,$s0,$s0 + ld [$key+20],$t1 + srlx $acc6,16,$acc6 + xor $acc3,$s0,$s0 + ld [$key+24],$t2 + srlx $acc7,24,$acc7 + xor $acc4,$s1,$s1 + ld [$key+28],$t3 ! + srlx $acc9,8,$acc9 + xor $acc5,$s1,$s1 + ldx [$tbl+2048+0],%g0 ! prefetch td4 + srlx $acc10,16,$acc10 + xor $acc6,$s1,$s1 + ldx [$tbl+2048+32],%g0 ! prefetch td4 + srlx $acc11,24,$acc11 + xor $acc7,$s1,$s1 + ldx [$tbl+2048+64],%g0 ! prefetch td4 + srlx $acc13,8,$acc13 + xor $acc8,$s2,$s2 + ldx [$tbl+2048+96],%g0 ! prefetch td4 + srlx $acc14,16,$acc14 ! + xor $acc9,$s2,$s2 + ldx [$tbl+2048+128],%g0 ! prefetch td4 + srlx $acc15,24,$acc15 + xor $acc10,$s2,$s2 + ldx [$tbl+2048+160],%g0 ! prefetch td4 + srl $s0,21,$acc0 + xor $acc11,$s2,$s2 + ldx [$tbl+2048+192],%g0 ! prefetch td4 + xor $acc12,$acc14,$acc14 + xor $acc13,$s3,$s3 + ldx [$tbl+2048+224],%g0 ! prefetch td4 + and $acc0,2040,$acc0 ! + xor $acc14,$s3,$s3 + xor $acc15,$s3,$s3 + ba .Ldec_loop + srl $s3,13,$acc1 + +.align 32 +.Ldec_last: + srlx $acc1,8,$acc1 ! + xor $acc0,$t0,$t0 + ld [$key+0],$s0 + srlx $acc2,16,$acc2 + xor $acc1,$t0,$t0 + ld [$key+4],$s1 + srlx $acc3,24,$acc3 + xor $acc2,$t0,$t0 + ld [$key+8],$s2 ! + srlx $acc5,8,$acc5 + xor $acc3,$t0,$t0 + ld [$key+12],$s3 + srlx $acc6,16,$acc6 + xor $acc4,$t1,$t1 + srlx $acc7,24,$acc7 + xor $acc5,$t1,$t1 + srlx $acc9,8,$acc9 ! + xor $acc6,$t1,$t1 + srlx $acc10,16,$acc10 + xor $acc7,$t1,$t1 + srlx $acc11,24,$acc11 + xor $acc8,$t2,$t2 + srlx $acc13,8,$acc13 + xor $acc9,$t2,$t2 + srlx $acc14,16,$acc14 ! + xor $acc10,$t2,$t2 + srlx $acc15,24,$acc15 + xor $acc11,$t2,$t2 + xor $acc12,$acc14,$acc14 + xor $acc13,$t3,$t3 + srl $t0,24,$acc0 + xor $acc14,$t3,$t3 + xor $acc15,$t3,$t3 ! + srl $t3,16,$acc1 + + srl $t2,8,$acc2 + and $acc1,255,$acc1 + ldub [$rounds+$acc0],$acc0 + srl $t1,24,$acc4 + and $acc2,255,$acc2 + ldub [$rounds+$acc1],$acc1 + srl $t0,16,$acc5 ! + and $t1,255,$acc3 + ldub [$rounds+$acc2],$acc2 + ldub [$rounds+$acc3],$acc3 + srl $t3,8,$acc6 + and $acc5,255,$acc5 + ldub [$rounds+$acc4],$acc4 + fmovs %f0,%f0 + srl $t2,24,$acc8 ! + and $acc6,255,$acc6 + ldub [$rounds+$acc5],$acc5 + srl $t1,16,$acc9 + and $t2,255,$acc7 + ldub [$rounds+$acc6],$acc6 + ldub [$rounds+$acc7],$acc7 + fmovs %f0,%f0 + srl $t0,8,$acc10 ! + and $acc9,255,$acc9 + ldub [$rounds+$acc8],$acc8 + srl $t3,24,$acc12 + and $acc10,255,$acc10 + ldub [$rounds+$acc9],$acc9 + srl $t2,16,$acc13 + and $t3,255,$acc11 + ldub [$rounds+$acc10],$acc10 ! + srl $t1,8,$acc14 + and $acc13,255,$acc13 + ldub [$rounds+$acc11],$acc11 + ldub [$rounds+$acc12],$acc12 + and $acc14,255,$acc14 + ldub [$rounds+$acc13],$acc13 + and $t0,255,$acc15 + ldub [$rounds+$acc14],$acc14 ! + + sll $acc0,24,$acc0 + xor $acc3,$s0,$s0 + ldub [$rounds+$acc15],$acc15 + sll $acc1,16,$acc1 + xor $acc0,$s0,$s0 + ldx [%sp+$bias+$frame+0],%i7 ! restore return address + fmovs %f0,%f0 + sll $acc2,8,$acc2 ! + xor $acc1,$s0,$s0 + sll $acc4,24,$acc4 + xor $acc2,$s0,$s0 + sll $acc5,16,$acc5 + xor $acc7,$s1,$s1 + sll $acc6,8,$acc6 + xor $acc4,$s1,$s1 + sll $acc8,24,$acc8 ! + xor $acc5,$s1,$s1 + sll $acc9,16,$acc9 + xor $acc11,$s2,$s2 + sll $acc10,8,$acc10 + xor $acc6,$s1,$s1 + sll $acc12,24,$acc12 + xor $acc8,$s2,$s2 + sll $acc13,16,$acc13 ! + xor $acc9,$s2,$s2 + sll $acc14,8,$acc14 + xor $acc10,$s2,$s2 + xor $acc12,$acc14,$acc14 + xor $acc13,$s3,$s3 + xor $acc14,$s3,$s3 + xor $acc15,$s3,$s3 + + ret + restore +.type _sparcv9_AES_decrypt,#function +.size _sparcv9_AES_decrypt,(.-_sparcv9_AES_decrypt) + +.align 32 +.globl AES_decrypt +AES_decrypt: + or %o0,%o1,%g1 + andcc %g1,3,%g0 + bnz,pn %xcc,.Lunaligned_dec + save %sp,-$frame,%sp + + ld [%i0+0],%o0 + ld [%i0+4],%o1 + ld [%i0+8],%o2 + ld [%i0+12],%o3 + +1: call .+8 + add %o7,AES_Td-1b,%o4 + call _sparcv9_AES_decrypt + mov %i2,%o5 + + st %o0,[%i1+0] + st %o1,[%i1+4] + st %o2,[%i1+8] + st %o3,[%i1+12] + + ret + restore + +.align 32 +.Lunaligned_dec: + ldub [%i0+0],%l0 + ldub [%i0+1],%l1 + ldub [%i0+2],%l2 + + sll %l0,24,%l0 + ldub [%i0+3],%l3 + sll %l1,16,%l1 + ldub [%i0+4],%l4 + sll %l2,8,%l2 + or %l1,%l0,%l0 + ldub [%i0+5],%l5 + sll %l4,24,%l4 + or %l3,%l2,%l2 + ldub [%i0+6],%l6 + sll %l5,16,%l5 + or %l0,%l2,%o0 + ldub [%i0+7],%l7 + + sll %l6,8,%l6 + or %l5,%l4,%l4 + ldub [%i0+8],%l0 + or %l7,%l6,%l6 + ldub [%i0+9],%l1 + or %l4,%l6,%o1 + ldub [%i0+10],%l2 + + sll %l0,24,%l0 + ldub [%i0+11],%l3 + sll %l1,16,%l1 + ldub [%i0+12],%l4 + sll %l2,8,%l2 + or %l1,%l0,%l0 + ldub [%i0+13],%l5 + sll %l4,24,%l4 + or %l3,%l2,%l2 + ldub [%i0+14],%l6 + sll %l5,16,%l5 + or %l0,%l2,%o2 + ldub [%i0+15],%l7 + + sll %l6,8,%l6 + or %l5,%l4,%l4 + or %l7,%l6,%l6 + or %l4,%l6,%o3 + +1: call .+8 + add %o7,AES_Td-1b,%o4 + call _sparcv9_AES_decrypt + mov %i2,%o5 + + srl %o0,24,%l0 + srl %o0,16,%l1 + stb %l0,[%i1+0] + srl %o0,8,%l2 + stb %l1,[%i1+1] + stb %l2,[%i1+2] + srl %o1,24,%l4 + stb %o0,[%i1+3] + + srl %o1,16,%l5 + stb %l4,[%i1+4] + srl %o1,8,%l6 + stb %l5,[%i1+5] + stb %l6,[%i1+6] + srl %o2,24,%l0 + stb %o1,[%i1+7] + + srl %o2,16,%l1 + stb %l0,[%i1+8] + srl %o2,8,%l2 + stb %l1,[%i1+9] + stb %l2,[%i1+10] + srl %o3,24,%l4 + stb %o2,[%i1+11] + + srl %o3,16,%l5 + stb %l4,[%i1+12] + srl %o3,8,%l6 + stb %l5,[%i1+13] + stb %l6,[%i1+14] + stb %o3,[%i1+15] + + ret + restore +.type AES_decrypt,#function +.size AES_decrypt,(.-AES_decrypt) +___ + +# fmovs instructions substituting for FP nops were originally added +# to meet specific instruction alignment requirements to maximize ILP. +# As UltraSPARC T1, a.k.a. Niagara, has shared FPU, FP nops can have +# undesired effect, so just omit them and sacrifice some portion of +# percent in performance... +$code =~ s/fmovs.*$//gm; + +print $code; +close STDOUT; # ensure flush diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-x86_64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-x86_64.pl new file mode 100755 index 000000000..d87e20114 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aes-x86_64.pl @@ -0,0 +1,2916 @@ +#! /usr/bin/env perl +# Copyright 2005-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# Version 2.1. +# +# aes-*-cbc benchmarks are improved by >70% [compared to gcc 3.3.2 on +# Opteron 240 CPU] plus all the bells-n-whistles from 32-bit version +# [you'll notice a lot of resemblance], such as compressed S-boxes +# in little-endian byte order, prefetch of these tables in CBC mode, +# as well as avoiding L1 cache aliasing between stack frame and key +# schedule and already mentioned tables, compressed Td4... +# +# Performance in number of cycles per processed byte for 128-bit key: +# +# ECB encrypt ECB decrypt CBC large chunk +# AMD64 33 43 13.0 +# EM64T 38 56 18.6(*) +# Core 2 30 42 14.5(*) +# Atom 65 86 32.1(*) +# +# (*) with hyper-threading off + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +*STDOUT=*OUT; + +$verticalspin=1; # unlike 32-bit version $verticalspin performs + # ~15% better on both AMD and Intel cores +$speed_limit=512; # see aes-586.pl for details + +$code=".text\n"; + +$s0="%eax"; +$s1="%ebx"; +$s2="%ecx"; +$s3="%edx"; +$acc0="%esi"; $mask80="%rsi"; +$acc1="%edi"; $maskfe="%rdi"; +$acc2="%ebp"; $mask1b="%rbp"; +$inp="%r8"; +$out="%r9"; +$t0="%r10d"; +$t1="%r11d"; +$t2="%r12d"; +$rnds="%r13d"; +$sbox="%r14"; +$key="%r15"; + +sub hi() { my $r=shift; $r =~ s/%[er]([a-d])x/%\1h/; $r; } +sub lo() { my $r=shift; $r =~ s/%[er]([a-d])x/%\1l/; + $r =~ s/%[er]([sd]i)/%\1l/; + $r =~ s/%(r[0-9]+)[d]?/%\1b/; $r; } +sub LO() { my $r=shift; $r =~ s/%r([a-z]+)/%e\1/; + $r =~ s/%r([0-9]+)/%r\1d/; $r; } +sub _data_word() +{ my $i; + while(defined($i=shift)) { $code.=sprintf".long\t0x%08x,0x%08x\n",$i,$i; } +} +sub data_word() +{ my $i; + my $last=pop(@_); + $code.=".long\t"; + while(defined($i=shift)) { $code.=sprintf"0x%08x,",$i; } + $code.=sprintf"0x%08x\n",$last; +} + +sub data_byte() +{ my $i; + my $last=pop(@_); + $code.=".byte\t"; + while(defined($i=shift)) { $code.=sprintf"0x%02x,",$i&0xff; } + $code.=sprintf"0x%02x\n",$last&0xff; +} + +sub encvert() +{ my $t3="%r8d"; # zaps $inp! + +$code.=<<___; + # favor 3-way issue Opteron pipeline... + movzb `&lo("$s0")`,$acc0 + movzb `&lo("$s1")`,$acc1 + movzb `&lo("$s2")`,$acc2 + mov 0($sbox,$acc0,8),$t0 + mov 0($sbox,$acc1,8),$t1 + mov 0($sbox,$acc2,8),$t2 + + movzb `&hi("$s1")`,$acc0 + movzb `&hi("$s2")`,$acc1 + movzb `&lo("$s3")`,$acc2 + xor 3($sbox,$acc0,8),$t0 + xor 3($sbox,$acc1,8),$t1 + mov 0($sbox,$acc2,8),$t3 + + movzb `&hi("$s3")`,$acc0 + shr \$16,$s2 + movzb `&hi("$s0")`,$acc2 + xor 3($sbox,$acc0,8),$t2 + shr \$16,$s3 + xor 3($sbox,$acc2,8),$t3 + + shr \$16,$s1 + lea 16($key),$key + shr \$16,$s0 + + movzb `&lo("$s2")`,$acc0 + movzb `&lo("$s3")`,$acc1 + movzb `&lo("$s0")`,$acc2 + xor 2($sbox,$acc0,8),$t0 + xor 2($sbox,$acc1,8),$t1 + xor 2($sbox,$acc2,8),$t2 + + movzb `&hi("$s3")`,$acc0 + movzb `&hi("$s0")`,$acc1 + movzb `&lo("$s1")`,$acc2 + xor 1($sbox,$acc0,8),$t0 + xor 1($sbox,$acc1,8),$t1 + xor 2($sbox,$acc2,8),$t3 + + mov 12($key),$s3 + movzb `&hi("$s1")`,$acc1 + movzb `&hi("$s2")`,$acc2 + mov 0($key),$s0 + xor 1($sbox,$acc1,8),$t2 + xor 1($sbox,$acc2,8),$t3 + + mov 4($key),$s1 + mov 8($key),$s2 + xor $t0,$s0 + xor $t1,$s1 + xor $t2,$s2 + xor $t3,$s3 +___ +} + +sub enclastvert() +{ my $t3="%r8d"; # zaps $inp! + +$code.=<<___; + movzb `&lo("$s0")`,$acc0 + movzb `&lo("$s1")`,$acc1 + movzb `&lo("$s2")`,$acc2 + movzb 2($sbox,$acc0,8),$t0 + movzb 2($sbox,$acc1,8),$t1 + movzb 2($sbox,$acc2,8),$t2 + + movzb `&lo("$s3")`,$acc0 + movzb `&hi("$s1")`,$acc1 + movzb `&hi("$s2")`,$acc2 + movzb 2($sbox,$acc0,8),$t3 + mov 0($sbox,$acc1,8),$acc1 #$t0 + mov 0($sbox,$acc2,8),$acc2 #$t1 + + and \$0x0000ff00,$acc1 + and \$0x0000ff00,$acc2 + + xor $acc1,$t0 + xor $acc2,$t1 + shr \$16,$s2 + + movzb `&hi("$s3")`,$acc0 + movzb `&hi("$s0")`,$acc1 + shr \$16,$s3 + mov 0($sbox,$acc0,8),$acc0 #$t2 + mov 0($sbox,$acc1,8),$acc1 #$t3 + + and \$0x0000ff00,$acc0 + and \$0x0000ff00,$acc1 + shr \$16,$s1 + xor $acc0,$t2 + xor $acc1,$t3 + shr \$16,$s0 + + movzb `&lo("$s2")`,$acc0 + movzb `&lo("$s3")`,$acc1 + movzb `&lo("$s0")`,$acc2 + mov 0($sbox,$acc0,8),$acc0 #$t0 + mov 0($sbox,$acc1,8),$acc1 #$t1 + mov 0($sbox,$acc2,8),$acc2 #$t2 + + and \$0x00ff0000,$acc0 + and \$0x00ff0000,$acc1 + and \$0x00ff0000,$acc2 + + xor $acc0,$t0 + xor $acc1,$t1 + xor $acc2,$t2 + + movzb `&lo("$s1")`,$acc0 + movzb `&hi("$s3")`,$acc1 + movzb `&hi("$s0")`,$acc2 + mov 0($sbox,$acc0,8),$acc0 #$t3 + mov 2($sbox,$acc1,8),$acc1 #$t0 + mov 2($sbox,$acc2,8),$acc2 #$t1 + + and \$0x00ff0000,$acc0 + and \$0xff000000,$acc1 + and \$0xff000000,$acc2 + + xor $acc0,$t3 + xor $acc1,$t0 + xor $acc2,$t1 + + movzb `&hi("$s1")`,$acc0 + movzb `&hi("$s2")`,$acc1 + mov 16+12($key),$s3 + mov 2($sbox,$acc0,8),$acc0 #$t2 + mov 2($sbox,$acc1,8),$acc1 #$t3 + mov 16+0($key),$s0 + + and \$0xff000000,$acc0 + and \$0xff000000,$acc1 + + xor $acc0,$t2 + xor $acc1,$t3 + + mov 16+4($key),$s1 + mov 16+8($key),$s2 + xor $t0,$s0 + xor $t1,$s1 + xor $t2,$s2 + xor $t3,$s3 +___ +} + +sub encstep() +{ my ($i,@s) = @_; + my $tmp0=$acc0; + my $tmp1=$acc1; + my $tmp2=$acc2; + my $out=($t0,$t1,$t2,$s[0])[$i]; + + if ($i==3) { + $tmp0=$s[1]; + $tmp1=$s[2]; + $tmp2=$s[3]; + } + $code.=" movzb ".&lo($s[0]).",$out\n"; + $code.=" mov $s[2],$tmp1\n" if ($i!=3); + $code.=" lea 16($key),$key\n" if ($i==0); + + $code.=" movzb ".&hi($s[1]).",$tmp0\n"; + $code.=" mov 0($sbox,$out,8),$out\n"; + + $code.=" shr \$16,$tmp1\n"; + $code.=" mov $s[3],$tmp2\n" if ($i!=3); + $code.=" xor 3($sbox,$tmp0,8),$out\n"; + + $code.=" movzb ".&lo($tmp1).",$tmp1\n"; + $code.=" shr \$24,$tmp2\n"; + $code.=" xor 4*$i($key),$out\n"; + + $code.=" xor 2($sbox,$tmp1,8),$out\n"; + $code.=" xor 1($sbox,$tmp2,8),$out\n"; + + $code.=" mov $t0,$s[1]\n" if ($i==3); + $code.=" mov $t1,$s[2]\n" if ($i==3); + $code.=" mov $t2,$s[3]\n" if ($i==3); + $code.="\n"; +} + +sub enclast() +{ my ($i,@s)=@_; + my $tmp0=$acc0; + my $tmp1=$acc1; + my $tmp2=$acc2; + my $out=($t0,$t1,$t2,$s[0])[$i]; + + if ($i==3) { + $tmp0=$s[1]; + $tmp1=$s[2]; + $tmp2=$s[3]; + } + $code.=" movzb ".&lo($s[0]).",$out\n"; + $code.=" mov $s[2],$tmp1\n" if ($i!=3); + + $code.=" mov 2($sbox,$out,8),$out\n"; + $code.=" shr \$16,$tmp1\n"; + $code.=" mov $s[3],$tmp2\n" if ($i!=3); + + $code.=" and \$0x000000ff,$out\n"; + $code.=" movzb ".&hi($s[1]).",$tmp0\n"; + $code.=" movzb ".&lo($tmp1).",$tmp1\n"; + $code.=" shr \$24,$tmp2\n"; + + $code.=" mov 0($sbox,$tmp0,8),$tmp0\n"; + $code.=" mov 0($sbox,$tmp1,8),$tmp1\n"; + $code.=" mov 2($sbox,$tmp2,8),$tmp2\n"; + + $code.=" and \$0x0000ff00,$tmp0\n"; + $code.=" and \$0x00ff0000,$tmp1\n"; + $code.=" and \$0xff000000,$tmp2\n"; + + $code.=" xor $tmp0,$out\n"; + $code.=" mov $t0,$s[1]\n" if ($i==3); + $code.=" xor $tmp1,$out\n"; + $code.=" mov $t1,$s[2]\n" if ($i==3); + $code.=" xor $tmp2,$out\n"; + $code.=" mov $t2,$s[3]\n" if ($i==3); + $code.="\n"; +} + +$code.=<<___; +.type _x86_64_AES_encrypt,\@abi-omnipotent +.align 16 +_x86_64_AES_encrypt: + xor 0($key),$s0 # xor with key + xor 4($key),$s1 + xor 8($key),$s2 + xor 12($key),$s3 + + mov 240($key),$rnds # load key->rounds + sub \$1,$rnds + jmp .Lenc_loop +.align 16 +.Lenc_loop: +___ + if ($verticalspin) { &encvert(); } + else { &encstep(0,$s0,$s1,$s2,$s3); + &encstep(1,$s1,$s2,$s3,$s0); + &encstep(2,$s2,$s3,$s0,$s1); + &encstep(3,$s3,$s0,$s1,$s2); + } +$code.=<<___; + sub \$1,$rnds + jnz .Lenc_loop +___ + if ($verticalspin) { &enclastvert(); } + else { &enclast(0,$s0,$s1,$s2,$s3); + &enclast(1,$s1,$s2,$s3,$s0); + &enclast(2,$s2,$s3,$s0,$s1); + &enclast(3,$s3,$s0,$s1,$s2); + $code.=<<___; + xor 16+0($key),$s0 # xor with key + xor 16+4($key),$s1 + xor 16+8($key),$s2 + xor 16+12($key),$s3 +___ + } +$code.=<<___; + .byte 0xf3,0xc3 # rep ret +.size _x86_64_AES_encrypt,.-_x86_64_AES_encrypt +___ + +# it's possible to implement this by shifting tN by 8, filling least +# significant byte with byte load and finally bswap-ing at the end, +# but such partial register load kills Core 2... +sub enccompactvert() +{ my ($t3,$t4,$t5)=("%r8d","%r9d","%r13d"); + +$code.=<<___; + movzb `&lo("$s0")`,$t0 + movzb `&lo("$s1")`,$t1 + movzb `&lo("$s2")`,$t2 + movzb `&lo("$s3")`,$t3 + movzb `&hi("$s1")`,$acc0 + movzb `&hi("$s2")`,$acc1 + shr \$16,$s2 + movzb `&hi("$s3")`,$acc2 + movzb ($sbox,$t0,1),$t0 + movzb ($sbox,$t1,1),$t1 + movzb ($sbox,$t2,1),$t2 + movzb ($sbox,$t3,1),$t3 + + movzb ($sbox,$acc0,1),$t4 #$t0 + movzb `&hi("$s0")`,$acc0 + movzb ($sbox,$acc1,1),$t5 #$t1 + movzb `&lo("$s2")`,$acc1 + movzb ($sbox,$acc2,1),$acc2 #$t2 + movzb ($sbox,$acc0,1),$acc0 #$t3 + + shl \$8,$t4 + shr \$16,$s3 + shl \$8,$t5 + xor $t4,$t0 + shr \$16,$s0 + movzb `&lo("$s3")`,$t4 + shr \$16,$s1 + xor $t5,$t1 + shl \$8,$acc2 + movzb `&lo("$s0")`,$t5 + movzb ($sbox,$acc1,1),$acc1 #$t0 + xor $acc2,$t2 + + shl \$8,$acc0 + movzb `&lo("$s1")`,$acc2 + shl \$16,$acc1 + xor $acc0,$t3 + movzb ($sbox,$t4,1),$t4 #$t1 + movzb `&hi("$s3")`,$acc0 + movzb ($sbox,$t5,1),$t5 #$t2 + xor $acc1,$t0 + + shr \$8,$s2 + movzb `&hi("$s0")`,$acc1 + shl \$16,$t4 + shr \$8,$s1 + shl \$16,$t5 + xor $t4,$t1 + movzb ($sbox,$acc2,1),$acc2 #$t3 + movzb ($sbox,$acc0,1),$acc0 #$t0 + movzb ($sbox,$acc1,1),$acc1 #$t1 + movzb ($sbox,$s2,1),$s3 #$t3 + movzb ($sbox,$s1,1),$s2 #$t2 + + shl \$16,$acc2 + xor $t5,$t2 + shl \$24,$acc0 + xor $acc2,$t3 + shl \$24,$acc1 + xor $acc0,$t0 + shl \$24,$s3 + xor $acc1,$t1 + shl \$24,$s2 + mov $t0,$s0 + mov $t1,$s1 + xor $t2,$s2 + xor $t3,$s3 +___ +} + +sub enctransform_ref() +{ my $sn = shift; + my ($acc,$r2,$tmp)=("%r8d","%r9d","%r13d"); + +$code.=<<___; + mov $sn,$acc + and \$0x80808080,$acc + mov $acc,$tmp + shr \$7,$tmp + lea ($sn,$sn),$r2 + sub $tmp,$acc + and \$0xfefefefe,$r2 + and \$0x1b1b1b1b,$acc + mov $sn,$tmp + xor $acc,$r2 + + xor $r2,$sn + rol \$24,$sn + xor $r2,$sn + ror \$16,$tmp + xor $tmp,$sn + ror \$8,$tmp + xor $tmp,$sn +___ +} + +# unlike decrypt case it does not pay off to parallelize enctransform +sub enctransform() +{ my ($t3,$r20,$r21)=($acc2,"%r8d","%r9d"); + +$code.=<<___; + mov \$0x80808080,$t0 + mov \$0x80808080,$t1 + and $s0,$t0 + and $s1,$t1 + mov $t0,$acc0 + mov $t1,$acc1 + shr \$7,$t0 + lea ($s0,$s0),$r20 + shr \$7,$t1 + lea ($s1,$s1),$r21 + sub $t0,$acc0 + sub $t1,$acc1 + and \$0xfefefefe,$r20 + and \$0xfefefefe,$r21 + and \$0x1b1b1b1b,$acc0 + and \$0x1b1b1b1b,$acc1 + mov $s0,$t0 + mov $s1,$t1 + xor $acc0,$r20 + xor $acc1,$r21 + + xor $r20,$s0 + xor $r21,$s1 + mov \$0x80808080,$t2 + rol \$24,$s0 + mov \$0x80808080,$t3 + rol \$24,$s1 + and $s2,$t2 + and $s3,$t3 + xor $r20,$s0 + xor $r21,$s1 + mov $t2,$acc0 + ror \$16,$t0 + mov $t3,$acc1 + ror \$16,$t1 + lea ($s2,$s2),$r20 + shr \$7,$t2 + xor $t0,$s0 + shr \$7,$t3 + xor $t1,$s1 + ror \$8,$t0 + lea ($s3,$s3),$r21 + ror \$8,$t1 + sub $t2,$acc0 + sub $t3,$acc1 + xor $t0,$s0 + xor $t1,$s1 + + and \$0xfefefefe,$r20 + and \$0xfefefefe,$r21 + and \$0x1b1b1b1b,$acc0 + and \$0x1b1b1b1b,$acc1 + mov $s2,$t2 + mov $s3,$t3 + xor $acc0,$r20 + xor $acc1,$r21 + + ror \$16,$t2 + xor $r20,$s2 + ror \$16,$t3 + xor $r21,$s3 + rol \$24,$s2 + mov 0($sbox),$acc0 # prefetch Te4 + rol \$24,$s3 + xor $r20,$s2 + mov 64($sbox),$acc1 + xor $r21,$s3 + mov 128($sbox),$r20 + xor $t2,$s2 + ror \$8,$t2 + xor $t3,$s3 + ror \$8,$t3 + xor $t2,$s2 + mov 192($sbox),$r21 + xor $t3,$s3 +___ +} + +$code.=<<___; +.type _x86_64_AES_encrypt_compact,\@abi-omnipotent +.align 16 +_x86_64_AES_encrypt_compact: +.cfi_startproc + lea 128($sbox),$inp # size optimization + mov 0-128($inp),$acc1 # prefetch Te4 + mov 32-128($inp),$acc2 + mov 64-128($inp),$t0 + mov 96-128($inp),$t1 + mov 128-128($inp),$acc1 + mov 160-128($inp),$acc2 + mov 192-128($inp),$t0 + mov 224-128($inp),$t1 + jmp .Lenc_loop_compact +.align 16 +.Lenc_loop_compact: + xor 0($key),$s0 # xor with key + xor 4($key),$s1 + xor 8($key),$s2 + xor 12($key),$s3 + lea 16($key),$key +___ + &enccompactvert(); +$code.=<<___; + cmp 16(%rsp),$key + je .Lenc_compact_done +___ + &enctransform(); +$code.=<<___; + jmp .Lenc_loop_compact +.align 16 +.Lenc_compact_done: + xor 0($key),$s0 + xor 4($key),$s1 + xor 8($key),$s2 + xor 12($key),$s3 + .byte 0xf3,0xc3 # rep ret +.cfi_endproc +.size _x86_64_AES_encrypt_compact,.-_x86_64_AES_encrypt_compact +___ + +# void AES_encrypt (const void *inp,void *out,const AES_KEY *key); +$code.=<<___; +.globl AES_encrypt +.type AES_encrypt,\@function,3 +.align 16 +.globl asm_AES_encrypt +.hidden asm_AES_encrypt +asm_AES_encrypt: +AES_encrypt: +.cfi_startproc + mov %rsp,%rax +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + + # allocate frame "above" key schedule + lea -63(%rdx),%rcx # %rdx is key argument + and \$-64,%rsp + sub %rsp,%rcx + neg %rcx + and \$0x3c0,%rcx + sub %rcx,%rsp + sub \$32,%rsp + + mov %rsi,16(%rsp) # save out + mov %rax,24(%rsp) # save original stack pointer +.cfi_cfa_expression %rsp+24,deref,+8 +.Lenc_prologue: + + mov %rdx,$key + mov 240($key),$rnds # load rounds + + mov 0(%rdi),$s0 # load input vector + mov 4(%rdi),$s1 + mov 8(%rdi),$s2 + mov 12(%rdi),$s3 + + shl \$4,$rnds + lea ($key,$rnds),%rbp + mov $key,(%rsp) # key schedule + mov %rbp,8(%rsp) # end of key schedule + + # pick Te4 copy which can't "overlap" with stack frame or key schedule + lea .LAES_Te+2048(%rip),$sbox + lea 768(%rsp),%rbp + sub $sbox,%rbp + and \$0x300,%rbp + lea ($sbox,%rbp),$sbox + + call _x86_64_AES_encrypt_compact + + mov 16(%rsp),$out # restore out + mov 24(%rsp),%rsi # restore saved stack pointer +.cfi_def_cfa %rsi,8 + mov $s0,0($out) # write output vector + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + + mov -48(%rsi),%r15 +.cfi_restore %r15 + mov -40(%rsi),%r14 +.cfi_restore %r14 + mov -32(%rsi),%r13 +.cfi_restore %r13 + mov -24(%rsi),%r12 +.cfi_restore %r12 + mov -16(%rsi),%rbp +.cfi_restore %rbp + mov -8(%rsi),%rbx +.cfi_restore %rbx + lea (%rsi),%rsp +.cfi_def_cfa_register %rsp +.Lenc_epilogue: + ret +.cfi_endproc +.size AES_encrypt,.-AES_encrypt +___ + +#------------------------------------------------------------------# + +sub decvert() +{ my $t3="%r8d"; # zaps $inp! + +$code.=<<___; + # favor 3-way issue Opteron pipeline... + movzb `&lo("$s0")`,$acc0 + movzb `&lo("$s1")`,$acc1 + movzb `&lo("$s2")`,$acc2 + mov 0($sbox,$acc0,8),$t0 + mov 0($sbox,$acc1,8),$t1 + mov 0($sbox,$acc2,8),$t2 + + movzb `&hi("$s3")`,$acc0 + movzb `&hi("$s0")`,$acc1 + movzb `&lo("$s3")`,$acc2 + xor 3($sbox,$acc0,8),$t0 + xor 3($sbox,$acc1,8),$t1 + mov 0($sbox,$acc2,8),$t3 + + movzb `&hi("$s1")`,$acc0 + shr \$16,$s0 + movzb `&hi("$s2")`,$acc2 + xor 3($sbox,$acc0,8),$t2 + shr \$16,$s3 + xor 3($sbox,$acc2,8),$t3 + + shr \$16,$s1 + lea 16($key),$key + shr \$16,$s2 + + movzb `&lo("$s2")`,$acc0 + movzb `&lo("$s3")`,$acc1 + movzb `&lo("$s0")`,$acc2 + xor 2($sbox,$acc0,8),$t0 + xor 2($sbox,$acc1,8),$t1 + xor 2($sbox,$acc2,8),$t2 + + movzb `&hi("$s1")`,$acc0 + movzb `&hi("$s2")`,$acc1 + movzb `&lo("$s1")`,$acc2 + xor 1($sbox,$acc0,8),$t0 + xor 1($sbox,$acc1,8),$t1 + xor 2($sbox,$acc2,8),$t3 + + movzb `&hi("$s3")`,$acc0 + mov 12($key),$s3 + movzb `&hi("$s0")`,$acc2 + xor 1($sbox,$acc0,8),$t2 + mov 0($key),$s0 + xor 1($sbox,$acc2,8),$t3 + + xor $t0,$s0 + mov 4($key),$s1 + mov 8($key),$s2 + xor $t2,$s2 + xor $t1,$s1 + xor $t3,$s3 +___ +} + +sub declastvert() +{ my $t3="%r8d"; # zaps $inp! + +$code.=<<___; + lea 2048($sbox),$sbox # size optimization + movzb `&lo("$s0")`,$acc0 + movzb `&lo("$s1")`,$acc1 + movzb `&lo("$s2")`,$acc2 + movzb ($sbox,$acc0,1),$t0 + movzb ($sbox,$acc1,1),$t1 + movzb ($sbox,$acc2,1),$t2 + + movzb `&lo("$s3")`,$acc0 + movzb `&hi("$s3")`,$acc1 + movzb `&hi("$s0")`,$acc2 + movzb ($sbox,$acc0,1),$t3 + movzb ($sbox,$acc1,1),$acc1 #$t0 + movzb ($sbox,$acc2,1),$acc2 #$t1 + + shl \$8,$acc1 + shl \$8,$acc2 + + xor $acc1,$t0 + xor $acc2,$t1 + shr \$16,$s3 + + movzb `&hi("$s1")`,$acc0 + movzb `&hi("$s2")`,$acc1 + shr \$16,$s0 + movzb ($sbox,$acc0,1),$acc0 #$t2 + movzb ($sbox,$acc1,1),$acc1 #$t3 + + shl \$8,$acc0 + shl \$8,$acc1 + shr \$16,$s1 + xor $acc0,$t2 + xor $acc1,$t3 + shr \$16,$s2 + + movzb `&lo("$s2")`,$acc0 + movzb `&lo("$s3")`,$acc1 + movzb `&lo("$s0")`,$acc2 + movzb ($sbox,$acc0,1),$acc0 #$t0 + movzb ($sbox,$acc1,1),$acc1 #$t1 + movzb ($sbox,$acc2,1),$acc2 #$t2 + + shl \$16,$acc0 + shl \$16,$acc1 + shl \$16,$acc2 + + xor $acc0,$t0 + xor $acc1,$t1 + xor $acc2,$t2 + + movzb `&lo("$s1")`,$acc0 + movzb `&hi("$s1")`,$acc1 + movzb `&hi("$s2")`,$acc2 + movzb ($sbox,$acc0,1),$acc0 #$t3 + movzb ($sbox,$acc1,1),$acc1 #$t0 + movzb ($sbox,$acc2,1),$acc2 #$t1 + + shl \$16,$acc0 + shl \$24,$acc1 + shl \$24,$acc2 + + xor $acc0,$t3 + xor $acc1,$t0 + xor $acc2,$t1 + + movzb `&hi("$s3")`,$acc0 + movzb `&hi("$s0")`,$acc1 + mov 16+12($key),$s3 + movzb ($sbox,$acc0,1),$acc0 #$t2 + movzb ($sbox,$acc1,1),$acc1 #$t3 + mov 16+0($key),$s0 + + shl \$24,$acc0 + shl \$24,$acc1 + + xor $acc0,$t2 + xor $acc1,$t3 + + mov 16+4($key),$s1 + mov 16+8($key),$s2 + lea -2048($sbox),$sbox + xor $t0,$s0 + xor $t1,$s1 + xor $t2,$s2 + xor $t3,$s3 +___ +} + +sub decstep() +{ my ($i,@s) = @_; + my $tmp0=$acc0; + my $tmp1=$acc1; + my $tmp2=$acc2; + my $out=($t0,$t1,$t2,$s[0])[$i]; + + $code.=" mov $s[0],$out\n" if ($i!=3); + $tmp1=$s[2] if ($i==3); + $code.=" mov $s[2],$tmp1\n" if ($i!=3); + $code.=" and \$0xFF,$out\n"; + + $code.=" mov 0($sbox,$out,8),$out\n"; + $code.=" shr \$16,$tmp1\n"; + $tmp2=$s[3] if ($i==3); + $code.=" mov $s[3],$tmp2\n" if ($i!=3); + + $tmp0=$s[1] if ($i==3); + $code.=" movzb ".&hi($s[1]).",$tmp0\n"; + $code.=" and \$0xFF,$tmp1\n"; + $code.=" shr \$24,$tmp2\n"; + + $code.=" xor 3($sbox,$tmp0,8),$out\n"; + $code.=" xor 2($sbox,$tmp1,8),$out\n"; + $code.=" xor 1($sbox,$tmp2,8),$out\n"; + + $code.=" mov $t2,$s[1]\n" if ($i==3); + $code.=" mov $t1,$s[2]\n" if ($i==3); + $code.=" mov $t0,$s[3]\n" if ($i==3); + $code.="\n"; +} + +sub declast() +{ my ($i,@s)=@_; + my $tmp0=$acc0; + my $tmp1=$acc1; + my $tmp2=$acc2; + my $out=($t0,$t1,$t2,$s[0])[$i]; + + $code.=" mov $s[0],$out\n" if ($i!=3); + $tmp1=$s[2] if ($i==3); + $code.=" mov $s[2],$tmp1\n" if ($i!=3); + $code.=" and \$0xFF,$out\n"; + + $code.=" movzb 2048($sbox,$out,1),$out\n"; + $code.=" shr \$16,$tmp1\n"; + $tmp2=$s[3] if ($i==3); + $code.=" mov $s[3],$tmp2\n" if ($i!=3); + + $tmp0=$s[1] if ($i==3); + $code.=" movzb ".&hi($s[1]).",$tmp0\n"; + $code.=" and \$0xFF,$tmp1\n"; + $code.=" shr \$24,$tmp2\n"; + + $code.=" movzb 2048($sbox,$tmp0,1),$tmp0\n"; + $code.=" movzb 2048($sbox,$tmp1,1),$tmp1\n"; + $code.=" movzb 2048($sbox,$tmp2,1),$tmp2\n"; + + $code.=" shl \$8,$tmp0\n"; + $code.=" shl \$16,$tmp1\n"; + $code.=" shl \$24,$tmp2\n"; + + $code.=" xor $tmp0,$out\n"; + $code.=" mov $t2,$s[1]\n" if ($i==3); + $code.=" xor $tmp1,$out\n"; + $code.=" mov $t1,$s[2]\n" if ($i==3); + $code.=" xor $tmp2,$out\n"; + $code.=" mov $t0,$s[3]\n" if ($i==3); + $code.="\n"; +} + +$code.=<<___; +.type _x86_64_AES_decrypt,\@abi-omnipotent +.align 16 +_x86_64_AES_decrypt: + xor 0($key),$s0 # xor with key + xor 4($key),$s1 + xor 8($key),$s2 + xor 12($key),$s3 + + mov 240($key),$rnds # load key->rounds + sub \$1,$rnds + jmp .Ldec_loop +.align 16 +.Ldec_loop: +___ + if ($verticalspin) { &decvert(); } + else { &decstep(0,$s0,$s3,$s2,$s1); + &decstep(1,$s1,$s0,$s3,$s2); + &decstep(2,$s2,$s1,$s0,$s3); + &decstep(3,$s3,$s2,$s1,$s0); + $code.=<<___; + lea 16($key),$key + xor 0($key),$s0 # xor with key + xor 4($key),$s1 + xor 8($key),$s2 + xor 12($key),$s3 +___ + } +$code.=<<___; + sub \$1,$rnds + jnz .Ldec_loop +___ + if ($verticalspin) { &declastvert(); } + else { &declast(0,$s0,$s3,$s2,$s1); + &declast(1,$s1,$s0,$s3,$s2); + &declast(2,$s2,$s1,$s0,$s3); + &declast(3,$s3,$s2,$s1,$s0); + $code.=<<___; + xor 16+0($key),$s0 # xor with key + xor 16+4($key),$s1 + xor 16+8($key),$s2 + xor 16+12($key),$s3 +___ + } +$code.=<<___; + .byte 0xf3,0xc3 # rep ret +.size _x86_64_AES_decrypt,.-_x86_64_AES_decrypt +___ + +sub deccompactvert() +{ my ($t3,$t4,$t5)=("%r8d","%r9d","%r13d"); + +$code.=<<___; + movzb `&lo("$s0")`,$t0 + movzb `&lo("$s1")`,$t1 + movzb `&lo("$s2")`,$t2 + movzb `&lo("$s3")`,$t3 + movzb `&hi("$s3")`,$acc0 + movzb `&hi("$s0")`,$acc1 + shr \$16,$s3 + movzb `&hi("$s1")`,$acc2 + movzb ($sbox,$t0,1),$t0 + movzb ($sbox,$t1,1),$t1 + movzb ($sbox,$t2,1),$t2 + movzb ($sbox,$t3,1),$t3 + + movzb ($sbox,$acc0,1),$t4 #$t0 + movzb `&hi("$s2")`,$acc0 + movzb ($sbox,$acc1,1),$t5 #$t1 + movzb ($sbox,$acc2,1),$acc2 #$t2 + movzb ($sbox,$acc0,1),$acc0 #$t3 + + shr \$16,$s2 + shl \$8,$t5 + shl \$8,$t4 + movzb `&lo("$s2")`,$acc1 + shr \$16,$s0 + xor $t4,$t0 + shr \$16,$s1 + movzb `&lo("$s3")`,$t4 + + shl \$8,$acc2 + xor $t5,$t1 + shl \$8,$acc0 + movzb `&lo("$s0")`,$t5 + movzb ($sbox,$acc1,1),$acc1 #$t0 + xor $acc2,$t2 + movzb `&lo("$s1")`,$acc2 + + shl \$16,$acc1 + xor $acc0,$t3 + movzb ($sbox,$t4,1),$t4 #$t1 + movzb `&hi("$s1")`,$acc0 + movzb ($sbox,$acc2,1),$acc2 #$t3 + xor $acc1,$t0 + movzb ($sbox,$t5,1),$t5 #$t2 + movzb `&hi("$s2")`,$acc1 + + shl \$16,$acc2 + shl \$16,$t4 + shl \$16,$t5 + xor $acc2,$t3 + movzb `&hi("$s3")`,$acc2 + xor $t4,$t1 + shr \$8,$s0 + xor $t5,$t2 + + movzb ($sbox,$acc0,1),$acc0 #$t0 + movzb ($sbox,$acc1,1),$s1 #$t1 + movzb ($sbox,$acc2,1),$s2 #$t2 + movzb ($sbox,$s0,1),$s3 #$t3 + + mov $t0,$s0 + shl \$24,$acc0 + shl \$24,$s1 + shl \$24,$s2 + xor $acc0,$s0 + shl \$24,$s3 + xor $t1,$s1 + xor $t2,$s2 + xor $t3,$s3 +___ +} + +# parallelized version! input is pair of 64-bit values: %rax=s1.s0 +# and %rcx=s3.s2, output is four 32-bit values in %eax=s0, %ebx=s1, +# %ecx=s2 and %edx=s3. +sub dectransform() +{ my ($tp10,$tp20,$tp40,$tp80,$acc0)=("%rax","%r8", "%r9", "%r10","%rbx"); + my ($tp18,$tp28,$tp48,$tp88,$acc8)=("%rcx","%r11","%r12","%r13","%rdx"); + my $prefetch = shift; + +$code.=<<___; + mov $mask80,$tp40 + mov $mask80,$tp48 + and $tp10,$tp40 + and $tp18,$tp48 + mov $tp40,$acc0 + mov $tp48,$acc8 + shr \$7,$tp40 + lea ($tp10,$tp10),$tp20 + shr \$7,$tp48 + lea ($tp18,$tp18),$tp28 + sub $tp40,$acc0 + sub $tp48,$acc8 + and $maskfe,$tp20 + and $maskfe,$tp28 + and $mask1b,$acc0 + and $mask1b,$acc8 + xor $acc0,$tp20 + xor $acc8,$tp28 + mov $mask80,$tp80 + mov $mask80,$tp88 + + and $tp20,$tp80 + and $tp28,$tp88 + mov $tp80,$acc0 + mov $tp88,$acc8 + shr \$7,$tp80 + lea ($tp20,$tp20),$tp40 + shr \$7,$tp88 + lea ($tp28,$tp28),$tp48 + sub $tp80,$acc0 + sub $tp88,$acc8 + and $maskfe,$tp40 + and $maskfe,$tp48 + and $mask1b,$acc0 + and $mask1b,$acc8 + xor $acc0,$tp40 + xor $acc8,$tp48 + mov $mask80,$tp80 + mov $mask80,$tp88 + + and $tp40,$tp80 + and $tp48,$tp88 + mov $tp80,$acc0 + mov $tp88,$acc8 + shr \$7,$tp80 + xor $tp10,$tp20 # tp2^=tp1 + shr \$7,$tp88 + xor $tp18,$tp28 # tp2^=tp1 + sub $tp80,$acc0 + sub $tp88,$acc8 + lea ($tp40,$tp40),$tp80 + lea ($tp48,$tp48),$tp88 + xor $tp10,$tp40 # tp4^=tp1 + xor $tp18,$tp48 # tp4^=tp1 + and $maskfe,$tp80 + and $maskfe,$tp88 + and $mask1b,$acc0 + and $mask1b,$acc8 + xor $acc0,$tp80 + xor $acc8,$tp88 + + xor $tp80,$tp10 # tp1^=tp8 + xor $tp88,$tp18 # tp1^=tp8 + xor $tp80,$tp20 # tp2^tp1^=tp8 + xor $tp88,$tp28 # tp2^tp1^=tp8 + mov $tp10,$acc0 + mov $tp18,$acc8 + xor $tp80,$tp40 # tp4^tp1^=tp8 + shr \$32,$acc0 + xor $tp88,$tp48 # tp4^tp1^=tp8 + shr \$32,$acc8 + xor $tp20,$tp80 # tp8^=tp8^tp2^tp1=tp2^tp1 + rol \$8,`&LO("$tp10")` # ROTATE(tp1^tp8,8) + xor $tp28,$tp88 # tp8^=tp8^tp2^tp1=tp2^tp1 + rol \$8,`&LO("$tp18")` # ROTATE(tp1^tp8,8) + xor $tp40,$tp80 # tp2^tp1^=tp8^tp4^tp1=tp8^tp4^tp2 + rol \$8,`&LO("$acc0")` # ROTATE(tp1^tp8,8) + xor $tp48,$tp88 # tp2^tp1^=tp8^tp4^tp1=tp8^tp4^tp2 + + rol \$8,`&LO("$acc8")` # ROTATE(tp1^tp8,8) + xor `&LO("$tp80")`,`&LO("$tp10")` + shr \$32,$tp80 + xor `&LO("$tp88")`,`&LO("$tp18")` + shr \$32,$tp88 + xor `&LO("$tp80")`,`&LO("$acc0")` + xor `&LO("$tp88")`,`&LO("$acc8")` + + mov $tp20,$tp80 + rol \$24,`&LO("$tp20")` # ROTATE(tp2^tp1^tp8,24) + mov $tp28,$tp88 + rol \$24,`&LO("$tp28")` # ROTATE(tp2^tp1^tp8,24) + shr \$32,$tp80 + xor `&LO("$tp20")`,`&LO("$tp10")` + shr \$32,$tp88 + xor `&LO("$tp28")`,`&LO("$tp18")` + rol \$24,`&LO("$tp80")` # ROTATE(tp2^tp1^tp8,24) + mov $tp40,$tp20 + rol \$24,`&LO("$tp88")` # ROTATE(tp2^tp1^tp8,24) + mov $tp48,$tp28 + shr \$32,$tp20 + xor `&LO("$tp80")`,`&LO("$acc0")` + shr \$32,$tp28 + xor `&LO("$tp88")`,`&LO("$acc8")` + + `"mov 0($sbox),$mask80" if ($prefetch)` + rol \$16,`&LO("$tp40")` # ROTATE(tp4^tp1^tp8,16) + `"mov 64($sbox),$maskfe" if ($prefetch)` + rol \$16,`&LO("$tp48")` # ROTATE(tp4^tp1^tp8,16) + `"mov 128($sbox),$mask1b" if ($prefetch)` + rol \$16,`&LO("$tp20")` # ROTATE(tp4^tp1^tp8,16) + `"mov 192($sbox),$tp80" if ($prefetch)` + xor `&LO("$tp40")`,`&LO("$tp10")` + rol \$16,`&LO("$tp28")` # ROTATE(tp4^tp1^tp8,16) + xor `&LO("$tp48")`,`&LO("$tp18")` + `"mov 256($sbox),$tp88" if ($prefetch)` + xor `&LO("$tp20")`,`&LO("$acc0")` + xor `&LO("$tp28")`,`&LO("$acc8")` +___ +} + +$code.=<<___; +.type _x86_64_AES_decrypt_compact,\@abi-omnipotent +.align 16 +_x86_64_AES_decrypt_compact: +.cfi_startproc + lea 128($sbox),$inp # size optimization + mov 0-128($inp),$acc1 # prefetch Td4 + mov 32-128($inp),$acc2 + mov 64-128($inp),$t0 + mov 96-128($inp),$t1 + mov 128-128($inp),$acc1 + mov 160-128($inp),$acc2 + mov 192-128($inp),$t0 + mov 224-128($inp),$t1 + jmp .Ldec_loop_compact + +.align 16 +.Ldec_loop_compact: + xor 0($key),$s0 # xor with key + xor 4($key),$s1 + xor 8($key),$s2 + xor 12($key),$s3 + lea 16($key),$key +___ + &deccompactvert(); +$code.=<<___; + cmp 16(%rsp),$key + je .Ldec_compact_done + + mov 256+0($sbox),$mask80 + shl \$32,%rbx + shl \$32,%rdx + mov 256+8($sbox),$maskfe + or %rbx,%rax + or %rdx,%rcx + mov 256+16($sbox),$mask1b +___ + &dectransform(1); +$code.=<<___; + jmp .Ldec_loop_compact +.align 16 +.Ldec_compact_done: + xor 0($key),$s0 + xor 4($key),$s1 + xor 8($key),$s2 + xor 12($key),$s3 + .byte 0xf3,0xc3 # rep ret +.cfi_endproc +.size _x86_64_AES_decrypt_compact,.-_x86_64_AES_decrypt_compact +___ + +# void AES_decrypt (const void *inp,void *out,const AES_KEY *key); +$code.=<<___; +.globl AES_decrypt +.type AES_decrypt,\@function,3 +.align 16 +.globl asm_AES_decrypt +.hidden asm_AES_decrypt +asm_AES_decrypt: +AES_decrypt: +.cfi_startproc + mov %rsp,%rax +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + + # allocate frame "above" key schedule + lea -63(%rdx),%rcx # %rdx is key argument + and \$-64,%rsp + sub %rsp,%rcx + neg %rcx + and \$0x3c0,%rcx + sub %rcx,%rsp + sub \$32,%rsp + + mov %rsi,16(%rsp) # save out + mov %rax,24(%rsp) # save original stack pointer +.cfi_cfa_expression %rsp+24,deref,+8 +.Ldec_prologue: + + mov %rdx,$key + mov 240($key),$rnds # load rounds + + mov 0(%rdi),$s0 # load input vector + mov 4(%rdi),$s1 + mov 8(%rdi),$s2 + mov 12(%rdi),$s3 + + shl \$4,$rnds + lea ($key,$rnds),%rbp + mov $key,(%rsp) # key schedule + mov %rbp,8(%rsp) # end of key schedule + + # pick Td4 copy which can't "overlap" with stack frame or key schedule + lea .LAES_Td+2048(%rip),$sbox + lea 768(%rsp),%rbp + sub $sbox,%rbp + and \$0x300,%rbp + lea ($sbox,%rbp),$sbox + shr \$3,%rbp # recall "magic" constants! + add %rbp,$sbox + + call _x86_64_AES_decrypt_compact + + mov 16(%rsp),$out # restore out + mov 24(%rsp),%rsi # restore saved stack pointer +.cfi_def_cfa %rsi,8 + mov $s0,0($out) # write output vector + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + + mov -48(%rsi),%r15 +.cfi_restore %r15 + mov -40(%rsi),%r14 +.cfi_restore %r14 + mov -32(%rsi),%r13 +.cfi_restore %r13 + mov -24(%rsi),%r12 +.cfi_restore %r12 + mov -16(%rsi),%rbp +.cfi_restore %rbp + mov -8(%rsi),%rbx +.cfi_restore %rbx + lea (%rsi),%rsp +.cfi_def_cfa_register %rsp +.Ldec_epilogue: + ret +.cfi_endproc +.size AES_decrypt,.-AES_decrypt +___ +#------------------------------------------------------------------# + +sub enckey() +{ +$code.=<<___; + movz %dl,%esi # rk[i]>>0 + movzb -128(%rbp,%rsi),%ebx + movz %dh,%esi # rk[i]>>8 + shl \$24,%ebx + xor %ebx,%eax + + movzb -128(%rbp,%rsi),%ebx + shr \$16,%edx + movz %dl,%esi # rk[i]>>16 + xor %ebx,%eax + + movzb -128(%rbp,%rsi),%ebx + movz %dh,%esi # rk[i]>>24 + shl \$8,%ebx + xor %ebx,%eax + + movzb -128(%rbp,%rsi),%ebx + shl \$16,%ebx + xor %ebx,%eax + + xor 1024-128(%rbp,%rcx,4),%eax # rcon +___ +} + +# int AES_set_encrypt_key(const unsigned char *userKey, const int bits, +# AES_KEY *key) +$code.=<<___; +.globl AES_set_encrypt_key +.type AES_set_encrypt_key,\@function,3 +.align 16 +AES_set_encrypt_key: +.cfi_startproc + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 # redundant, but allows to share +.cfi_push %r12 + push %r13 # exception handler... +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + sub \$8,%rsp +.cfi_adjust_cfa_offset 8 +.Lenc_key_prologue: + + call _x86_64_AES_set_encrypt_key + + mov 40(%rsp),%rbp +.cfi_restore %rbp + mov 48(%rsp),%rbx +.cfi_restore %rbx + add \$56,%rsp +.cfi_adjust_cfa_offset -56 +.Lenc_key_epilogue: + ret +.cfi_endproc +.size AES_set_encrypt_key,.-AES_set_encrypt_key + +.type _x86_64_AES_set_encrypt_key,\@abi-omnipotent +.align 16 +_x86_64_AES_set_encrypt_key: +.cfi_startproc + mov %esi,%ecx # %ecx=bits + mov %rdi,%rsi # %rsi=userKey + mov %rdx,%rdi # %rdi=key + + test \$-1,%rsi + jz .Lbadpointer + test \$-1,%rdi + jz .Lbadpointer + + lea .LAES_Te(%rip),%rbp + lea 2048+128(%rbp),%rbp + + # prefetch Te4 + mov 0-128(%rbp),%eax + mov 32-128(%rbp),%ebx + mov 64-128(%rbp),%r8d + mov 96-128(%rbp),%edx + mov 128-128(%rbp),%eax + mov 160-128(%rbp),%ebx + mov 192-128(%rbp),%r8d + mov 224-128(%rbp),%edx + + cmp \$128,%ecx + je .L10rounds + cmp \$192,%ecx + je .L12rounds + cmp \$256,%ecx + je .L14rounds + mov \$-2,%rax # invalid number of bits + jmp .Lexit + +.L10rounds: + mov 0(%rsi),%rax # copy first 4 dwords + mov 8(%rsi),%rdx + mov %rax,0(%rdi) + mov %rdx,8(%rdi) + + shr \$32,%rdx + xor %ecx,%ecx + jmp .L10shortcut +.align 4 +.L10loop: + mov 0(%rdi),%eax # rk[0] + mov 12(%rdi),%edx # rk[3] +.L10shortcut: +___ + &enckey (); +$code.=<<___; + mov %eax,16(%rdi) # rk[4] + xor 4(%rdi),%eax + mov %eax,20(%rdi) # rk[5] + xor 8(%rdi),%eax + mov %eax,24(%rdi) # rk[6] + xor 12(%rdi),%eax + mov %eax,28(%rdi) # rk[7] + add \$1,%ecx + lea 16(%rdi),%rdi + cmp \$10,%ecx + jl .L10loop + + movl \$10,80(%rdi) # setup number of rounds + xor %rax,%rax + jmp .Lexit + +.L12rounds: + mov 0(%rsi),%rax # copy first 6 dwords + mov 8(%rsi),%rbx + mov 16(%rsi),%rdx + mov %rax,0(%rdi) + mov %rbx,8(%rdi) + mov %rdx,16(%rdi) + + shr \$32,%rdx + xor %ecx,%ecx + jmp .L12shortcut +.align 4 +.L12loop: + mov 0(%rdi),%eax # rk[0] + mov 20(%rdi),%edx # rk[5] +.L12shortcut: +___ + &enckey (); +$code.=<<___; + mov %eax,24(%rdi) # rk[6] + xor 4(%rdi),%eax + mov %eax,28(%rdi) # rk[7] + xor 8(%rdi),%eax + mov %eax,32(%rdi) # rk[8] + xor 12(%rdi),%eax + mov %eax,36(%rdi) # rk[9] + + cmp \$7,%ecx + je .L12break + add \$1,%ecx + + xor 16(%rdi),%eax + mov %eax,40(%rdi) # rk[10] + xor 20(%rdi),%eax + mov %eax,44(%rdi) # rk[11] + + lea 24(%rdi),%rdi + jmp .L12loop +.L12break: + movl \$12,72(%rdi) # setup number of rounds + xor %rax,%rax + jmp .Lexit + +.L14rounds: + mov 0(%rsi),%rax # copy first 8 dwords + mov 8(%rsi),%rbx + mov 16(%rsi),%rcx + mov 24(%rsi),%rdx + mov %rax,0(%rdi) + mov %rbx,8(%rdi) + mov %rcx,16(%rdi) + mov %rdx,24(%rdi) + + shr \$32,%rdx + xor %ecx,%ecx + jmp .L14shortcut +.align 4 +.L14loop: + mov 0(%rdi),%eax # rk[0] + mov 28(%rdi),%edx # rk[4] +.L14shortcut: +___ + &enckey (); +$code.=<<___; + mov %eax,32(%rdi) # rk[8] + xor 4(%rdi),%eax + mov %eax,36(%rdi) # rk[9] + xor 8(%rdi),%eax + mov %eax,40(%rdi) # rk[10] + xor 12(%rdi),%eax + mov %eax,44(%rdi) # rk[11] + + cmp \$6,%ecx + je .L14break + add \$1,%ecx + + mov %eax,%edx + mov 16(%rdi),%eax # rk[4] + movz %dl,%esi # rk[11]>>0 + movzb -128(%rbp,%rsi),%ebx + movz %dh,%esi # rk[11]>>8 + xor %ebx,%eax + + movzb -128(%rbp,%rsi),%ebx + shr \$16,%edx + shl \$8,%ebx + movz %dl,%esi # rk[11]>>16 + xor %ebx,%eax + + movzb -128(%rbp,%rsi),%ebx + movz %dh,%esi # rk[11]>>24 + shl \$16,%ebx + xor %ebx,%eax + + movzb -128(%rbp,%rsi),%ebx + shl \$24,%ebx + xor %ebx,%eax + + mov %eax,48(%rdi) # rk[12] + xor 20(%rdi),%eax + mov %eax,52(%rdi) # rk[13] + xor 24(%rdi),%eax + mov %eax,56(%rdi) # rk[14] + xor 28(%rdi),%eax + mov %eax,60(%rdi) # rk[15] + + lea 32(%rdi),%rdi + jmp .L14loop +.L14break: + movl \$14,48(%rdi) # setup number of rounds + xor %rax,%rax + jmp .Lexit + +.Lbadpointer: + mov \$-1,%rax +.Lexit: + .byte 0xf3,0xc3 # rep ret +.cfi_endproc +.size _x86_64_AES_set_encrypt_key,.-_x86_64_AES_set_encrypt_key +___ + +sub deckey_ref() +{ my ($i,$ptr,$te,$td) = @_; + my ($tp1,$tp2,$tp4,$tp8,$acc)=("%eax","%ebx","%edi","%edx","%r8d"); +$code.=<<___; + mov $i($ptr),$tp1 + mov $tp1,$acc + and \$0x80808080,$acc + mov $acc,$tp4 + shr \$7,$tp4 + lea 0($tp1,$tp1),$tp2 + sub $tp4,$acc + and \$0xfefefefe,$tp2 + and \$0x1b1b1b1b,$acc + xor $tp2,$acc + mov $acc,$tp2 + + and \$0x80808080,$acc + mov $acc,$tp8 + shr \$7,$tp8 + lea 0($tp2,$tp2),$tp4 + sub $tp8,$acc + and \$0xfefefefe,$tp4 + and \$0x1b1b1b1b,$acc + xor $tp1,$tp2 # tp2^tp1 + xor $tp4,$acc + mov $acc,$tp4 + + and \$0x80808080,$acc + mov $acc,$tp8 + shr \$7,$tp8 + sub $tp8,$acc + lea 0($tp4,$tp4),$tp8 + xor $tp1,$tp4 # tp4^tp1 + and \$0xfefefefe,$tp8 + and \$0x1b1b1b1b,$acc + xor $acc,$tp8 + + xor $tp8,$tp1 # tp1^tp8 + rol \$8,$tp1 # ROTATE(tp1^tp8,8) + xor $tp8,$tp2 # tp2^tp1^tp8 + xor $tp8,$tp4 # tp4^tp1^tp8 + xor $tp2,$tp8 + xor $tp4,$tp8 # tp8^(tp8^tp4^tp1)^(tp8^tp2^tp1)=tp8^tp4^tp2 + + xor $tp8,$tp1 + rol \$24,$tp2 # ROTATE(tp2^tp1^tp8,24) + xor $tp2,$tp1 + rol \$16,$tp4 # ROTATE(tp4^tp1^tp8,16) + xor $tp4,$tp1 + + mov $tp1,$i($ptr) +___ +} + +# int AES_set_decrypt_key(const unsigned char *userKey, const int bits, +# AES_KEY *key) +$code.=<<___; +.globl AES_set_decrypt_key +.type AES_set_decrypt_key,\@function,3 +.align 16 +AES_set_decrypt_key: +.cfi_startproc + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + push %rdx # save key schedule +.cfi_adjust_cfa_offset 8 +.Ldec_key_prologue: + + call _x86_64_AES_set_encrypt_key + mov (%rsp),%r8 # restore key schedule + cmp \$0,%eax + jne .Labort + + mov 240(%r8),%r14d # pull number of rounds + xor %rdi,%rdi + lea (%rdi,%r14d,4),%rcx + mov %r8,%rsi + lea (%r8,%rcx,4),%rdi # pointer to last chunk +.align 4 +.Linvert: + mov 0(%rsi),%rax + mov 8(%rsi),%rbx + mov 0(%rdi),%rcx + mov 8(%rdi),%rdx + mov %rax,0(%rdi) + mov %rbx,8(%rdi) + mov %rcx,0(%rsi) + mov %rdx,8(%rsi) + lea 16(%rsi),%rsi + lea -16(%rdi),%rdi + cmp %rsi,%rdi + jne .Linvert + + lea .LAES_Te+2048+1024(%rip),%rax # rcon + + mov 40(%rax),$mask80 + mov 48(%rax),$maskfe + mov 56(%rax),$mask1b + + mov %r8,$key + sub \$1,%r14d +.align 4 +.Lpermute: + lea 16($key),$key + mov 0($key),%rax + mov 8($key),%rcx +___ + &dectransform (); +$code.=<<___; + mov %eax,0($key) + mov %ebx,4($key) + mov %ecx,8($key) + mov %edx,12($key) + sub \$1,%r14d + jnz .Lpermute + + xor %rax,%rax +.Labort: + mov 8(%rsp),%r15 +.cfi_restore %r15 + mov 16(%rsp),%r14 +.cfi_restore %r14 + mov 24(%rsp),%r13 +.cfi_restore %r13 + mov 32(%rsp),%r12 +.cfi_restore %r12 + mov 40(%rsp),%rbp +.cfi_restore %rbp + mov 48(%rsp),%rbx +.cfi_restore %rbx + add \$56,%rsp +.cfi_adjust_cfa_offset -56 +.Ldec_key_epilogue: + ret +.cfi_endproc +.size AES_set_decrypt_key,.-AES_set_decrypt_key +___ + +# void AES_cbc_encrypt (const void char *inp, unsigned char *out, +# size_t length, const AES_KEY *key, +# unsigned char *ivp,const int enc); +{ +# stack frame layout +# -8(%rsp) return address +my $keyp="0(%rsp)"; # one to pass as $key +my $keyend="8(%rsp)"; # &(keyp->rd_key[4*keyp->rounds]) +my $_rsp="16(%rsp)"; # saved %rsp +my $_inp="24(%rsp)"; # copy of 1st parameter, inp +my $_out="32(%rsp)"; # copy of 2nd parameter, out +my $_len="40(%rsp)"; # copy of 3rd parameter, length +my $_key="48(%rsp)"; # copy of 4th parameter, key +my $_ivp="56(%rsp)"; # copy of 5th parameter, ivp +my $ivec="64(%rsp)"; # ivec[16] +my $aes_key="80(%rsp)"; # copy of aes_key +my $mark="80+240(%rsp)"; # copy of aes_key->rounds + +$code.=<<___; +.globl AES_cbc_encrypt +.type AES_cbc_encrypt,\@function,6 +.align 16 +.extern OPENSSL_ia32cap_P +.globl asm_AES_cbc_encrypt +.hidden asm_AES_cbc_encrypt +asm_AES_cbc_encrypt: +AES_cbc_encrypt: +.cfi_startproc + cmp \$0,%rdx # check length + je .Lcbc_epilogue + pushfq +# This could be .cfi_push 49, but libunwind fails on registers it does not +# recognize. See https://bugzilla.redhat.com/show_bug.cgi?id=217087. +.cfi_adjust_cfa_offset 8 + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +.Lcbc_prologue: + + cld + mov %r9d,%r9d # clear upper half of enc + + lea .LAES_Te(%rip),$sbox + lea .LAES_Td(%rip),%r10 + cmp \$0,%r9 + cmoveq %r10,$sbox + +.cfi_remember_state + mov OPENSSL_ia32cap_P(%rip),%r10d + cmp \$$speed_limit,%rdx + jb .Lcbc_slow_prologue + test \$15,%rdx + jnz .Lcbc_slow_prologue + bt \$28,%r10d + jc .Lcbc_slow_prologue + + # allocate aligned stack frame... + lea -88-248(%rsp),$key + and \$-64,$key + + # ... and make sure it doesn't alias with AES_T[ed] modulo 4096 + mov $sbox,%r10 + lea 2304($sbox),%r11 + mov $key,%r12 + and \$0xFFF,%r10 # s = $sbox&0xfff + and \$0xFFF,%r11 # e = ($sbox+2048)&0xfff + and \$0xFFF,%r12 # p = %rsp&0xfff + + cmp %r11,%r12 # if (p=>e) %rsp =- (p-e); + jb .Lcbc_te_break_out + sub %r11,%r12 + sub %r12,$key + jmp .Lcbc_te_ok +.Lcbc_te_break_out: # else %rsp -= (p-s)&0xfff + framesz + sub %r10,%r12 + and \$0xFFF,%r12 + add \$320,%r12 + sub %r12,$key +.align 4 +.Lcbc_te_ok: + + xchg %rsp,$key +.cfi_def_cfa_register $key + #add \$8,%rsp # reserve for return address! + mov $key,$_rsp # save %rsp +.cfi_cfa_expression $_rsp,deref,+64 +.Lcbc_fast_body: + mov %rdi,$_inp # save copy of inp + mov %rsi,$_out # save copy of out + mov %rdx,$_len # save copy of len + mov %rcx,$_key # save copy of key + mov %r8,$_ivp # save copy of ivp + movl \$0,$mark # copy of aes_key->rounds = 0; + mov %r8,%rbp # rearrange input arguments + mov %r9,%rbx + mov %rsi,$out + mov %rdi,$inp + mov %rcx,$key + + mov 240($key),%eax # key->rounds + # do we copy key schedule to stack? + mov $key,%r10 + sub $sbox,%r10 + and \$0xfff,%r10 + cmp \$2304,%r10 + jb .Lcbc_do_ecopy + cmp \$4096-248,%r10 + jb .Lcbc_skip_ecopy +.align 4 +.Lcbc_do_ecopy: + mov $key,%rsi + lea $aes_key,%rdi + lea $aes_key,$key + mov \$240/8,%ecx + .long 0x90A548F3 # rep movsq + mov %eax,(%rdi) # copy aes_key->rounds +.Lcbc_skip_ecopy: + mov $key,$keyp # save key pointer + + mov \$18,%ecx +.align 4 +.Lcbc_prefetch_te: + mov 0($sbox),%r10 + mov 32($sbox),%r11 + mov 64($sbox),%r12 + mov 96($sbox),%r13 + lea 128($sbox),$sbox + sub \$1,%ecx + jnz .Lcbc_prefetch_te + lea -2304($sbox),$sbox + + cmp \$0,%rbx + je .LFAST_DECRYPT + +#----------------------------- ENCRYPT -----------------------------# + mov 0(%rbp),$s0 # load iv + mov 4(%rbp),$s1 + mov 8(%rbp),$s2 + mov 12(%rbp),$s3 + +.align 4 +.Lcbc_fast_enc_loop: + xor 0($inp),$s0 + xor 4($inp),$s1 + xor 8($inp),$s2 + xor 12($inp),$s3 + mov $keyp,$key # restore key + mov $inp,$_inp # if ($verticalspin) save inp + + call _x86_64_AES_encrypt + + mov $_inp,$inp # if ($verticalspin) restore inp + mov $_len,%r10 + mov $s0,0($out) + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + + lea 16($inp),$inp + lea 16($out),$out + sub \$16,%r10 + test \$-16,%r10 + mov %r10,$_len + jnz .Lcbc_fast_enc_loop + mov $_ivp,%rbp # restore ivp + mov $s0,0(%rbp) # save ivec + mov $s1,4(%rbp) + mov $s2,8(%rbp) + mov $s3,12(%rbp) + + jmp .Lcbc_fast_cleanup + +#----------------------------- DECRYPT -----------------------------# +.align 16 +.LFAST_DECRYPT: + cmp $inp,$out + je .Lcbc_fast_dec_in_place + + mov %rbp,$ivec +.align 4 +.Lcbc_fast_dec_loop: + mov 0($inp),$s0 # read input + mov 4($inp),$s1 + mov 8($inp),$s2 + mov 12($inp),$s3 + mov $keyp,$key # restore key + mov $inp,$_inp # if ($verticalspin) save inp + + call _x86_64_AES_decrypt + + mov $ivec,%rbp # load ivp + mov $_inp,$inp # if ($verticalspin) restore inp + mov $_len,%r10 # load len + xor 0(%rbp),$s0 # xor iv + xor 4(%rbp),$s1 + xor 8(%rbp),$s2 + xor 12(%rbp),$s3 + mov $inp,%rbp # current input, next iv + + sub \$16,%r10 + mov %r10,$_len # update len + mov %rbp,$ivec # update ivp + + mov $s0,0($out) # write output + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + + lea 16($inp),$inp + lea 16($out),$out + jnz .Lcbc_fast_dec_loop + mov $_ivp,%r12 # load user ivp + mov 0(%rbp),%r10 # load iv + mov 8(%rbp),%r11 + mov %r10,0(%r12) # copy back to user + mov %r11,8(%r12) + jmp .Lcbc_fast_cleanup + +.align 16 +.Lcbc_fast_dec_in_place: + mov 0(%rbp),%r10 # copy iv to stack + mov 8(%rbp),%r11 + mov %r10,0+$ivec + mov %r11,8+$ivec +.align 4 +.Lcbc_fast_dec_in_place_loop: + mov 0($inp),$s0 # load input + mov 4($inp),$s1 + mov 8($inp),$s2 + mov 12($inp),$s3 + mov $keyp,$key # restore key + mov $inp,$_inp # if ($verticalspin) save inp + + call _x86_64_AES_decrypt + + mov $_inp,$inp # if ($verticalspin) restore inp + mov $_len,%r10 + xor 0+$ivec,$s0 + xor 4+$ivec,$s1 + xor 8+$ivec,$s2 + xor 12+$ivec,$s3 + + mov 0($inp),%r11 # load input + mov 8($inp),%r12 + sub \$16,%r10 + jz .Lcbc_fast_dec_in_place_done + + mov %r11,0+$ivec # copy input to iv + mov %r12,8+$ivec + + mov $s0,0($out) # save output [zaps input] + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + + lea 16($inp),$inp + lea 16($out),$out + mov %r10,$_len + jmp .Lcbc_fast_dec_in_place_loop +.Lcbc_fast_dec_in_place_done: + mov $_ivp,%rdi + mov %r11,0(%rdi) # copy iv back to user + mov %r12,8(%rdi) + + mov $s0,0($out) # save output [zaps input] + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + +.align 4 +.Lcbc_fast_cleanup: + cmpl \$0,$mark # was the key schedule copied? + lea $aes_key,%rdi + je .Lcbc_exit + mov \$240/8,%ecx + xor %rax,%rax + .long 0x90AB48F3 # rep stosq + + jmp .Lcbc_exit + +#--------------------------- SLOW ROUTINE ---------------------------# +.align 16 +.Lcbc_slow_prologue: +.cfi_restore_state + # allocate aligned stack frame... + lea -88(%rsp),%rbp + and \$-64,%rbp + # ... just "above" key schedule + lea -88-63(%rcx),%r10 + sub %rbp,%r10 + neg %r10 + and \$0x3c0,%r10 + sub %r10,%rbp + + xchg %rsp,%rbp +.cfi_def_cfa_register %rbp + #add \$8,%rsp # reserve for return address! + mov %rbp,$_rsp # save %rsp +.cfi_cfa_expression $_rsp,deref,+64 +.Lcbc_slow_body: + #mov %rdi,$_inp # save copy of inp + #mov %rsi,$_out # save copy of out + #mov %rdx,$_len # save copy of len + #mov %rcx,$_key # save copy of key + mov %r8,$_ivp # save copy of ivp + mov %r8,%rbp # rearrange input arguments + mov %r9,%rbx + mov %rsi,$out + mov %rdi,$inp + mov %rcx,$key + mov %rdx,%r10 + + mov 240($key),%eax + mov $key,$keyp # save key pointer + shl \$4,%eax + lea ($key,%rax),%rax + mov %rax,$keyend + + # pick Te4 copy which can't "overlap" with stack frame or key schedule + lea 2048($sbox),$sbox + lea 768-8(%rsp),%rax + sub $sbox,%rax + and \$0x300,%rax + lea ($sbox,%rax),$sbox + + cmp \$0,%rbx + je .LSLOW_DECRYPT + +#--------------------------- SLOW ENCRYPT ---------------------------# + test \$-16,%r10 # check upon length + mov 0(%rbp),$s0 # load iv + mov 4(%rbp),$s1 + mov 8(%rbp),$s2 + mov 12(%rbp),$s3 + jz .Lcbc_slow_enc_tail # short input... + +.align 4 +.Lcbc_slow_enc_loop: + xor 0($inp),$s0 + xor 4($inp),$s1 + xor 8($inp),$s2 + xor 12($inp),$s3 + mov $keyp,$key # restore key + mov $inp,$_inp # save inp + mov $out,$_out # save out + mov %r10,$_len # save len + + call _x86_64_AES_encrypt_compact + + mov $_inp,$inp # restore inp + mov $_out,$out # restore out + mov $_len,%r10 # restore len + mov $s0,0($out) + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + + lea 16($inp),$inp + lea 16($out),$out + sub \$16,%r10 + test \$-16,%r10 + jnz .Lcbc_slow_enc_loop + test \$15,%r10 + jnz .Lcbc_slow_enc_tail + mov $_ivp,%rbp # restore ivp + mov $s0,0(%rbp) # save ivec + mov $s1,4(%rbp) + mov $s2,8(%rbp) + mov $s3,12(%rbp) + + jmp .Lcbc_exit + +.align 4 +.Lcbc_slow_enc_tail: + mov %rax,%r11 + mov %rcx,%r12 + mov %r10,%rcx + mov $inp,%rsi + mov $out,%rdi + .long 0x9066A4F3 # rep movsb + mov \$16,%rcx # zero tail + sub %r10,%rcx + xor %rax,%rax + .long 0x9066AAF3 # rep stosb + mov $out,$inp # this is not a mistake! + mov \$16,%r10 # len=16 + mov %r11,%rax + mov %r12,%rcx + jmp .Lcbc_slow_enc_loop # one more spin... +#--------------------------- SLOW DECRYPT ---------------------------# +.align 16 +.LSLOW_DECRYPT: + shr \$3,%rax + add %rax,$sbox # recall "magic" constants! + + mov 0(%rbp),%r11 # copy iv to stack + mov 8(%rbp),%r12 + mov %r11,0+$ivec + mov %r12,8+$ivec + +.align 4 +.Lcbc_slow_dec_loop: + mov 0($inp),$s0 # load input + mov 4($inp),$s1 + mov 8($inp),$s2 + mov 12($inp),$s3 + mov $keyp,$key # restore key + mov $inp,$_inp # save inp + mov $out,$_out # save out + mov %r10,$_len # save len + + call _x86_64_AES_decrypt_compact + + mov $_inp,$inp # restore inp + mov $_out,$out # restore out + mov $_len,%r10 + xor 0+$ivec,$s0 + xor 4+$ivec,$s1 + xor 8+$ivec,$s2 + xor 12+$ivec,$s3 + + mov 0($inp),%r11 # load input + mov 8($inp),%r12 + sub \$16,%r10 + jc .Lcbc_slow_dec_partial + jz .Lcbc_slow_dec_done + + mov %r11,0+$ivec # copy input to iv + mov %r12,8+$ivec + + mov $s0,0($out) # save output [can zap input] + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + + lea 16($inp),$inp + lea 16($out),$out + jmp .Lcbc_slow_dec_loop +.Lcbc_slow_dec_done: + mov $_ivp,%rdi + mov %r11,0(%rdi) # copy iv back to user + mov %r12,8(%rdi) + + mov $s0,0($out) # save output [can zap input] + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + + jmp .Lcbc_exit + +.align 4 +.Lcbc_slow_dec_partial: + mov $_ivp,%rdi + mov %r11,0(%rdi) # copy iv back to user + mov %r12,8(%rdi) + + mov $s0,0+$ivec # save output to stack + mov $s1,4+$ivec + mov $s2,8+$ivec + mov $s3,12+$ivec + + mov $out,%rdi + lea $ivec,%rsi + lea 16(%r10),%rcx + .long 0x9066A4F3 # rep movsb + jmp .Lcbc_exit + +.align 16 +.Lcbc_exit: + mov $_rsp,%rsi +.cfi_def_cfa %rsi,64 + mov (%rsi),%r15 +.cfi_restore %r15 + mov 8(%rsi),%r14 +.cfi_restore %r14 + mov 16(%rsi),%r13 +.cfi_restore %r13 + mov 24(%rsi),%r12 +.cfi_restore %r12 + mov 32(%rsi),%rbp +.cfi_restore %rbp + mov 40(%rsi),%rbx +.cfi_restore %rbx + lea 48(%rsi),%rsp +.cfi_def_cfa %rsp,16 +.Lcbc_popfq: + popfq +# This could be .cfi_pop 49, but libunwind fails on registers it does not +# recognize. See https://bugzilla.redhat.com/show_bug.cgi?id=217087. +.cfi_adjust_cfa_offset -8 +.Lcbc_epilogue: + ret +.cfi_endproc +.size AES_cbc_encrypt,.-AES_cbc_encrypt +___ +} + +$code.=<<___; +.align 64 +.LAES_Te: +___ + &_data_word(0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6); + &_data_word(0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591); + &_data_word(0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56); + &_data_word(0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec); + &_data_word(0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa); + &_data_word(0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb); + &_data_word(0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45); + &_data_word(0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b); + &_data_word(0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c); + &_data_word(0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83); + &_data_word(0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9); + &_data_word(0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a); + &_data_word(0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d); + &_data_word(0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f); + &_data_word(0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df); + &_data_word(0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea); + &_data_word(0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34); + &_data_word(0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b); + &_data_word(0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d); + &_data_word(0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413); + &_data_word(0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1); + &_data_word(0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6); + &_data_word(0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972); + &_data_word(0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85); + &_data_word(0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed); + &_data_word(0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511); + &_data_word(0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe); + &_data_word(0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b); + &_data_word(0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05); + &_data_word(0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1); + &_data_word(0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142); + &_data_word(0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf); + &_data_word(0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3); + &_data_word(0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e); + &_data_word(0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a); + &_data_word(0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6); + &_data_word(0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3); + &_data_word(0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b); + &_data_word(0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428); + &_data_word(0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad); + &_data_word(0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14); + &_data_word(0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8); + &_data_word(0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4); + &_data_word(0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2); + &_data_word(0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda); + &_data_word(0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949); + &_data_word(0xb46c6cd8, 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf); + &_data_word(0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810); + &_data_word(0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c); + &_data_word(0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697); + &_data_word(0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e); + &_data_word(0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f); + &_data_word(0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc); + &_data_word(0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c); + &_data_word(0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969); + &_data_word(0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27); + &_data_word(0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122); + &_data_word(0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433); + &_data_word(0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9); + &_data_word(0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5); + &_data_word(0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a); + &_data_word(0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0); + &_data_word(0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e); + &_data_word(0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c); + +#Te4 # four copies of Te4 to choose from to avoid L1 aliasing + &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5); + &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76); + &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0); + &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0); + &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc); + &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15); + &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a); + &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75); + &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0); + &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84); + &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b); + &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf); + &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85); + &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8); + &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5); + &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2); + &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17); + &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73); + &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88); + &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb); + &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c); + &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79); + &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9); + &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08); + &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6); + &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a); + &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e); + &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e); + &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94); + &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf); + &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68); + &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16); + + &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5); + &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76); + &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0); + &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0); + &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc); + &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15); + &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a); + &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75); + &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0); + &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84); + &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b); + &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf); + &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85); + &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8); + &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5); + &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2); + &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17); + &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73); + &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88); + &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb); + &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c); + &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79); + &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9); + &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08); + &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6); + &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a); + &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e); + &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e); + &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94); + &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf); + &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68); + &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16); + + &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5); + &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76); + &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0); + &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0); + &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc); + &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15); + &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a); + &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75); + &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0); + &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84); + &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b); + &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf); + &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85); + &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8); + &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5); + &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2); + &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17); + &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73); + &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88); + &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb); + &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c); + &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79); + &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9); + &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08); + &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6); + &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a); + &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e); + &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e); + &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94); + &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf); + &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68); + &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16); + + &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5); + &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76); + &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0); + &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0); + &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc); + &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15); + &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a); + &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75); + &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0); + &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84); + &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b); + &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf); + &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85); + &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8); + &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5); + &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2); + &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17); + &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73); + &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88); + &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb); + &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c); + &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79); + &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9); + &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08); + &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6); + &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a); + &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e); + &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e); + &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94); + &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf); + &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68); + &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16); +#rcon: +$code.=<<___; + .long 0x00000001, 0x00000002, 0x00000004, 0x00000008 + .long 0x00000010, 0x00000020, 0x00000040, 0x00000080 + .long 0x0000001b, 0x00000036, 0x80808080, 0x80808080 + .long 0xfefefefe, 0xfefefefe, 0x1b1b1b1b, 0x1b1b1b1b +___ +$code.=<<___; +.align 64 +.LAES_Td: +___ + &_data_word(0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a); + &_data_word(0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b); + &_data_word(0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5); + &_data_word(0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5); + &_data_word(0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d); + &_data_word(0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b); + &_data_word(0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295); + &_data_word(0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e); + &_data_word(0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927); + &_data_word(0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d); + &_data_word(0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362); + &_data_word(0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9); + &_data_word(0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52); + &_data_word(0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566); + &_data_word(0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3); + &_data_word(0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed); + &_data_word(0x2b1ccf8a, 0x92b479a7, 0xf0f207f3, 0xa1e2694e); + &_data_word(0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4); + &_data_word(0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4); + &_data_word(0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd); + &_data_word(0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d); + &_data_word(0xb58d5491, 0x055dc471, 0x6fd40604, 0xff155060); + &_data_word(0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967); + &_data_word(0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879); + &_data_word(0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000); + &_data_word(0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c); + &_data_word(0xfbff0efd, 0x5638850f, 0x1ed5ae3d, 0x27392d36); + &_data_word(0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624); + &_data_word(0xb1670a0c, 0x0fe75793, 0xd296eeb4, 0x9e919b1b); + &_data_word(0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c); + &_data_word(0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12); + &_data_word(0x0b0d090e, 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14); + &_data_word(0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3); + &_data_word(0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b); + &_data_word(0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8); + &_data_word(0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684); + &_data_word(0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7); + &_data_word(0x4b2f9e1d, 0xf330b2dc, 0xec52860d, 0xd0e3c177); + &_data_word(0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947); + &_data_word(0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322); + &_data_word(0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498); + &_data_word(0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f); + &_data_word(0xe49d3a2c, 0x0d927850, 0x9bcc5f6a, 0x62467e54); + &_data_word(0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382); + &_data_word(0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf); + &_data_word(0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb); + &_data_word(0x097826cd, 0xf418596e, 0x01b79aec, 0xa89a4f83); + &_data_word(0x656e95e6, 0x7ee6ffaa, 0x08cfbc21, 0xe6e815ef); + &_data_word(0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029); + &_data_word(0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235); + &_data_word(0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733); + &_data_word(0x4a9804f1, 0xf7daec41, 0x0e50cd7f, 0x2ff69117); + &_data_word(0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4); + &_data_word(0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546); + &_data_word(0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb); + &_data_word(0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d); + &_data_word(0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb); + &_data_word(0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a); + &_data_word(0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773); + &_data_word(0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478); + &_data_word(0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2); + &_data_word(0x72c31d16, 0x0c25e2bc, 0x8b493c28, 0x41950dff); + &_data_word(0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664); + &_data_word(0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0); + +#Td4: # four copies of Td4 to choose from to avoid L1 aliasing + &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38); + &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb); + &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87); + &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb); + &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d); + &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e); + &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2); + &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25); + &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16); + &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92); + &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda); + &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84); + &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a); + &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06); + &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02); + &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b); + &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea); + &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73); + &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85); + &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e); + &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89); + &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b); + &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20); + &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4); + &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31); + &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f); + &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d); + &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef); + &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0); + &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61); + &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26); + &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d); +$code.=<<___; + .long 0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe + .long 0x1b1b1b1b, 0x1b1b1b1b, 0, 0 +___ + &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38); + &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb); + &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87); + &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb); + &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d); + &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e); + &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2); + &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25); + &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16); + &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92); + &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda); + &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84); + &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a); + &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06); + &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02); + &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b); + &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea); + &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73); + &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85); + &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e); + &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89); + &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b); + &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20); + &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4); + &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31); + &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f); + &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d); + &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef); + &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0); + &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61); + &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26); + &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d); +$code.=<<___; + .long 0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe + .long 0x1b1b1b1b, 0x1b1b1b1b, 0, 0 +___ + &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38); + &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb); + &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87); + &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb); + &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d); + &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e); + &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2); + &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25); + &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16); + &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92); + &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda); + &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84); + &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a); + &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06); + &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02); + &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b); + &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea); + &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73); + &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85); + &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e); + &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89); + &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b); + &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20); + &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4); + &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31); + &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f); + &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d); + &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef); + &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0); + &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61); + &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26); + &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d); +$code.=<<___; + .long 0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe + .long 0x1b1b1b1b, 0x1b1b1b1b, 0, 0 +___ + &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38); + &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb); + &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87); + &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb); + &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d); + &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e); + &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2); + &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25); + &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16); + &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92); + &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda); + &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84); + &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a); + &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06); + &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02); + &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b); + &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea); + &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73); + &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85); + &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e); + &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89); + &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b); + &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20); + &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4); + &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31); + &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f); + &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d); + &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef); + &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0); + &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61); + &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26); + &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d); +$code.=<<___; + .long 0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe + .long 0x1b1b1b1b, 0x1b1b1b1b, 0, 0 +.asciz "AES for x86_64, CRYPTOGAMS by " +.align 64 +___ + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type block_se_handler,\@abi-omnipotent +.align 16 +block_se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lin_block_prologue + + mov 24(%rax),%rax # pull saved real stack pointer + + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov -48(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + +.Lin_block_prologue: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + jmp .Lcommon_seh_exit +.size block_se_handler,.-block_se_handler + +.type key_se_handler,\@abi-omnipotent +.align 16 +key_se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lin_key_prologue + + lea 56(%rax),%rax + + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov -48(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + +.Lin_key_prologue: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + jmp .Lcommon_seh_exit +.size key_se_handler,.-key_se_handler + +.type cbc_se_handler,\@abi-omnipotent +.align 16 +cbc_se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + lea .Lcbc_prologue(%rip),%r10 + cmp %r10,%rbx # context->Rip<.Lcbc_prologue + jb .Lin_cbc_prologue + + lea .Lcbc_fast_body(%rip),%r10 + cmp %r10,%rbx # context->Rip<.Lcbc_fast_body + jb .Lin_cbc_frame_setup + + lea .Lcbc_slow_prologue(%rip),%r10 + cmp %r10,%rbx # context->Rip<.Lcbc_slow_prologue + jb .Lin_cbc_body + + lea .Lcbc_slow_body(%rip),%r10 + cmp %r10,%rbx # context->Rip<.Lcbc_slow_body + jb .Lin_cbc_frame_setup + +.Lin_cbc_body: + mov 152($context),%rax # pull context->Rsp + + lea .Lcbc_epilogue(%rip),%r10 + cmp %r10,%rbx # context->Rip>=.Lcbc_epilogue + jae .Lin_cbc_prologue + + lea 8(%rax),%rax + + lea .Lcbc_popfq(%rip),%r10 + cmp %r10,%rbx # context->Rip>=.Lcbc_popfq + jae .Lin_cbc_prologue + + mov `16-8`(%rax),%rax # biased $_rsp + lea 56(%rax),%rax + +.Lin_cbc_frame_setup: + mov -16(%rax),%rbx + mov -24(%rax),%rbp + mov -32(%rax),%r12 + mov -40(%rax),%r13 + mov -48(%rax),%r14 + mov -56(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + +.Lin_cbc_prologue: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + +.Lcommon_seh_exit: + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$`1232/8`,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size cbc_se_handler,.-cbc_se_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_AES_encrypt + .rva .LSEH_end_AES_encrypt + .rva .LSEH_info_AES_encrypt + + .rva .LSEH_begin_AES_decrypt + .rva .LSEH_end_AES_decrypt + .rva .LSEH_info_AES_decrypt + + .rva .LSEH_begin_AES_set_encrypt_key + .rva .LSEH_end_AES_set_encrypt_key + .rva .LSEH_info_AES_set_encrypt_key + + .rva .LSEH_begin_AES_set_decrypt_key + .rva .LSEH_end_AES_set_decrypt_key + .rva .LSEH_info_AES_set_decrypt_key + + .rva .LSEH_begin_AES_cbc_encrypt + .rva .LSEH_end_AES_cbc_encrypt + .rva .LSEH_info_AES_cbc_encrypt + +.section .xdata +.align 8 +.LSEH_info_AES_encrypt: + .byte 9,0,0,0 + .rva block_se_handler + .rva .Lenc_prologue,.Lenc_epilogue # HandlerData[] +.LSEH_info_AES_decrypt: + .byte 9,0,0,0 + .rva block_se_handler + .rva .Ldec_prologue,.Ldec_epilogue # HandlerData[] +.LSEH_info_AES_set_encrypt_key: + .byte 9,0,0,0 + .rva key_se_handler + .rva .Lenc_key_prologue,.Lenc_key_epilogue # HandlerData[] +.LSEH_info_AES_set_decrypt_key: + .byte 9,0,0,0 + .rva key_se_handler + .rva .Ldec_key_prologue,.Ldec_key_epilogue # HandlerData[] +.LSEH_info_AES_cbc_encrypt: + .byte 9,0,0,0 + .rva cbc_se_handler +___ +} + +$code =~ s/\`([^\`]*)\`/eval($1)/gem; + +print $code; + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesfx-sparcv9.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesfx-sparcv9.pl new file mode 100644 index 000000000..9ddf0b4b0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesfx-sparcv9.pl @@ -0,0 +1,1270 @@ +#! /usr/bin/env perl +# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# March 2016 +# +# Initial support for Fujitsu SPARC64 X/X+ comprises minimally +# required key setup and single-block procedures. +# +# April 2016 +# +# Add "teaser" CBC and CTR mode-specific subroutines. "Teaser" means +# that parallelizable nature of CBC decrypt and CTR is not utilized +# yet. CBC encrypt on the other hand is as good as it can possibly +# get processing one byte in 4.1 cycles with 128-bit key on SPARC64 X. +# This is ~6x faster than pure software implementation... +# +# July 2016 +# +# Switch from faligndata to fshiftorx, which allows to omit alignaddr +# instructions and improve single-block and short-input performance +# with misaligned data. + +$output = pop; +open STDOUT,">$output"; + +{ +my ($inp,$out,$key,$rounds,$tmp,$mask) = map("%o$_",(0..5)); + +$code.=<<___; +#include "sparc_arch.h" + +#define LOCALS (STACK_BIAS+STACK_FRAME) + +.text + +.globl aes_fx_encrypt +.align 32 +aes_fx_encrypt: + and $inp, 7, $tmp ! is input aligned? + andn $inp, 7, $inp + ldd [$key + 0], %f6 ! round[0] + ldd [$key + 8], %f8 + mov %o7, %g1 + ld [$key + 240], $rounds + +1: call .+8 + add %o7, .Linp_align-1b, %o7 + + sll $tmp, 3, $tmp + ldd [$inp + 0], %f0 ! load input + brz,pt $tmp, .Lenc_inp_aligned + ldd [$inp + 8], %f2 + + ldd [%o7 + $tmp], %f14 ! shift left params + ldd [$inp + 16], %f4 + fshiftorx %f0, %f2, %f14, %f0 + fshiftorx %f2, %f4, %f14, %f2 + +.Lenc_inp_aligned: + ldd [$key + 16], %f10 ! round[1] + ldd [$key + 24], %f12 + + fxor %f0, %f6, %f0 ! ^=round[0] + fxor %f2, %f8, %f2 + ldd [$key + 32], %f6 ! round[2] + ldd [$key + 40], %f8 + add $key, 32, $key + sub $rounds, 4, $rounds + +.Loop_enc: + fmovd %f0, %f4 + faesencx %f2, %f10, %f0 + faesencx %f4, %f12, %f2 + ldd [$key + 16], %f10 + ldd [$key + 24], %f12 + add $key, 32, $key + + fmovd %f0, %f4 + faesencx %f2, %f6, %f0 + faesencx %f4, %f8, %f2 + ldd [$key + 0], %f6 + ldd [$key + 8], %f8 + + brnz,a $rounds, .Loop_enc + sub $rounds, 2, $rounds + + andcc $out, 7, $tmp ! is output aligned? + andn $out, 7, $out + mov 0xff, $mask + srl $mask, $tmp, $mask + add %o7, 64, %o7 + sll $tmp, 3, $tmp + + fmovd %f0, %f4 + faesencx %f2, %f10, %f0 + faesencx %f4, %f12, %f2 + ldd [%o7 + $tmp], %f14 ! shift right params + + fmovd %f0, %f4 + faesenclx %f2, %f6, %f0 + faesenclx %f4, %f8, %f2 + + bnz,pn %icc, .Lenc_out_unaligned + mov %g1, %o7 + + std %f0, [$out + 0] + retl + std %f2, [$out + 8] + +.align 16 +.Lenc_out_unaligned: + add $out, 16, $inp + orn %g0, $mask, $tmp + fshiftorx %f0, %f0, %f14, %f4 + fshiftorx %f0, %f2, %f14, %f6 + fshiftorx %f2, %f2, %f14, %f8 + + stda %f4, [$out + $mask]0xc0 ! partial store + std %f6, [$out + 8] + stda %f8, [$inp + $tmp]0xc0 ! partial store + retl + nop +.type aes_fx_encrypt,#function +.size aes_fx_encrypt,.-aes_fx_encrypt + +.globl aes_fx_decrypt +.align 32 +aes_fx_decrypt: + and $inp, 7, $tmp ! is input aligned? + andn $inp, 7, $inp + ldd [$key + 0], %f6 ! round[0] + ldd [$key + 8], %f8 + mov %o7, %g1 + ld [$key + 240], $rounds + +1: call .+8 + add %o7, .Linp_align-1b, %o7 + + sll $tmp, 3, $tmp + ldd [$inp + 0], %f0 ! load input + brz,pt $tmp, .Ldec_inp_aligned + ldd [$inp + 8], %f2 + + ldd [%o7 + $tmp], %f14 ! shift left params + ldd [$inp + 16], %f4 + fshiftorx %f0, %f2, %f14, %f0 + fshiftorx %f2, %f4, %f14, %f2 + +.Ldec_inp_aligned: + ldd [$key + 16], %f10 ! round[1] + ldd [$key + 24], %f12 + + fxor %f0, %f6, %f0 ! ^=round[0] + fxor %f2, %f8, %f2 + ldd [$key + 32], %f6 ! round[2] + ldd [$key + 40], %f8 + add $key, 32, $key + sub $rounds, 4, $rounds + +.Loop_dec: + fmovd %f0, %f4 + faesdecx %f2, %f10, %f0 + faesdecx %f4, %f12, %f2 + ldd [$key + 16], %f10 + ldd [$key + 24], %f12 + add $key, 32, $key + + fmovd %f0, %f4 + faesdecx %f2, %f6, %f0 + faesdecx %f4, %f8, %f2 + ldd [$key + 0], %f6 + ldd [$key + 8], %f8 + + brnz,a $rounds, .Loop_dec + sub $rounds, 2, $rounds + + andcc $out, 7, $tmp ! is output aligned? + andn $out, 7, $out + mov 0xff, $mask + srl $mask, $tmp, $mask + add %o7, 64, %o7 + sll $tmp, 3, $tmp + + fmovd %f0, %f4 + faesdecx %f2, %f10, %f0 + faesdecx %f4, %f12, %f2 + ldd [%o7 + $tmp], %f14 ! shift right params + + fmovd %f0, %f4 + faesdeclx %f2, %f6, %f0 + faesdeclx %f4, %f8, %f2 + + bnz,pn %icc, .Ldec_out_unaligned + mov %g1, %o7 + + std %f0, [$out + 0] + retl + std %f2, [$out + 8] + +.align 16 +.Ldec_out_unaligned: + add $out, 16, $inp + orn %g0, $mask, $tmp + fshiftorx %f0, %f0, %f14, %f4 + fshiftorx %f0, %f2, %f14, %f6 + fshiftorx %f2, %f2, %f14, %f8 + + stda %f4, [$out + $mask]0xc0 ! partial store + std %f6, [$out + 8] + stda %f8, [$inp + $tmp]0xc0 ! partial store + retl + nop +.type aes_fx_decrypt,#function +.size aes_fx_decrypt,.-aes_fx_decrypt +___ +} +{ +my ($inp,$bits,$out,$tmp,$inc) = map("%o$_",(0..5)); +$code.=<<___; +.globl aes_fx_set_decrypt_key +.align 32 +aes_fx_set_decrypt_key: + b .Lset_encrypt_key + mov -1, $inc + retl + nop +.type aes_fx_set_decrypt_key,#function +.size aes_fx_set_decrypt_key,.-aes_fx_set_decrypt_key + +.globl aes_fx_set_encrypt_key +.align 32 +aes_fx_set_encrypt_key: + mov 1, $inc + nop +.Lset_encrypt_key: + and $inp, 7, $tmp + andn $inp, 7, $inp + sll $tmp, 3, $tmp + mov %o7, %g1 + +1: call .+8 + add %o7, .Linp_align-1b, %o7 + + ldd [%o7 + $tmp], %f10 ! shift left params + mov %g1, %o7 + + cmp $bits, 192 + ldd [$inp + 0], %f0 + bl,pt %icc, .L128 + ldd [$inp + 8], %f2 + + be,pt %icc, .L192 + ldd [$inp + 16], %f4 + brz,pt $tmp, .L256aligned + ldd [$inp + 24], %f6 + + ldd [$inp + 32], %f8 + fshiftorx %f0, %f2, %f10, %f0 + fshiftorx %f2, %f4, %f10, %f2 + fshiftorx %f4, %f6, %f10, %f4 + fshiftorx %f6, %f8, %f10, %f6 + +.L256aligned: + mov 14, $bits + and $inc, `14*16`, $tmp + st $bits, [$out + 240] ! store rounds + add $out, $tmp, $out ! start or end of key schedule + sllx $inc, 4, $inc ! 16 or -16 +___ +for ($i=0; $i<6; $i++) { + $code.=<<___; + std %f0, [$out + 0] + faeskeyx %f6, `0x10+$i`, %f0 + std %f2, [$out + 8] + add $out, $inc, $out + faeskeyx %f0, 0x00, %f2 + std %f4, [$out + 0] + faeskeyx %f2, 0x01, %f4 + std %f6, [$out + 8] + add $out, $inc, $out + faeskeyx %f4, 0x00, %f6 +___ +} +$code.=<<___; + std %f0, [$out + 0] + faeskeyx %f6, `0x10+$i`, %f0 + std %f2, [$out + 8] + add $out, $inc, $out + faeskeyx %f0, 0x00, %f2 + std %f4,[$out + 0] + std %f6,[$out + 8] + add $out, $inc, $out + std %f0,[$out + 0] + std %f2,[$out + 8] + retl + xor %o0, %o0, %o0 ! return 0 + +.align 16 +.L192: + brz,pt $tmp, .L192aligned + nop + + ldd [$inp + 24], %f6 + fshiftorx %f0, %f2, %f10, %f0 + fshiftorx %f2, %f4, %f10, %f2 + fshiftorx %f4, %f6, %f10, %f4 + +.L192aligned: + mov 12, $bits + and $inc, `12*16`, $tmp + st $bits, [$out + 240] ! store rounds + add $out, $tmp, $out ! start or end of key schedule + sllx $inc, 4, $inc ! 16 or -16 +___ +for ($i=0; $i<8; $i+=2) { + $code.=<<___; + std %f0, [$out + 0] + faeskeyx %f4, `0x10+$i`, %f0 + std %f2, [$out + 8] + add $out, $inc, $out + faeskeyx %f0, 0x00, %f2 + std %f4, [$out + 0] + faeskeyx %f2, 0x00, %f4 + std %f0, [$out + 8] + add $out, $inc, $out + faeskeyx %f4, `0x10+$i+1`, %f0 + std %f2, [$out + 0] + faeskeyx %f0, 0x00, %f2 + std %f4, [$out + 8] + add $out, $inc, $out +___ +$code.=<<___ if ($i<6); + faeskeyx %f2, 0x00, %f4 +___ +} +$code.=<<___; + std %f0, [$out + 0] + std %f2, [$out + 8] + retl + xor %o0, %o0, %o0 ! return 0 + +.align 16 +.L128: + brz,pt $tmp, .L128aligned + nop + + ldd [$inp + 16], %f4 + fshiftorx %f0, %f2, %f10, %f0 + fshiftorx %f2, %f4, %f10, %f2 + +.L128aligned: + mov 10, $bits + and $inc, `10*16`, $tmp + st $bits, [$out + 240] ! store rounds + add $out, $tmp, $out ! start or end of key schedule + sllx $inc, 4, $inc ! 16 or -16 +___ +for ($i=0; $i<10; $i++) { + $code.=<<___; + std %f0, [$out + 0] + faeskeyx %f2, `0x10+$i`, %f0 + std %f2, [$out + 8] + add $out, $inc, $out + faeskeyx %f0, 0x00, %f2 +___ +} +$code.=<<___; + std %f0, [$out + 0] + std %f2, [$out + 8] + retl + xor %o0, %o0, %o0 ! return 0 +.type aes_fx_set_encrypt_key,#function +.size aes_fx_set_encrypt_key,.-aes_fx_set_encrypt_key +___ +} +{ +my ($inp,$out,$len,$key,$ivp,$dir) = map("%i$_",(0..5)); +my ($rounds,$inner,$end,$inc,$ialign,$oalign,$mask) = map("%l$_",(0..7)); +my ($iv0,$iv1,$r0hi,$r0lo,$rlhi,$rllo,$in0,$in1,$intail,$outhead,$fshift) + = map("%f$_",grep { !($_ & 1) } (16 .. 62)); +my ($ileft,$iright) = ($ialign,$oalign); + +$code.=<<___; +.globl aes_fx_cbc_encrypt +.align 32 +aes_fx_cbc_encrypt: + save %sp, -STACK_FRAME-16, %sp + srln $len, 4, $len + and $inp, 7, $ialign + andn $inp, 7, $inp + brz,pn $len, .Lcbc_no_data + sll $ialign, 3, $ileft + +1: call .+8 + add %o7, .Linp_align-1b, %o7 + + ld [$key + 240], $rounds + and $out, 7, $oalign + ld [$ivp + 0], %f0 ! load ivec + andn $out, 7, $out + ld [$ivp + 4], %f1 + sll $oalign, 3, $mask + ld [$ivp + 8], %f2 + ld [$ivp + 12], %f3 + + sll $rounds, 4, $rounds + add $rounds, $key, $end + ldd [$key + 0], $r0hi ! round[0] + ldd [$key + 8], $r0lo + + add $inp, 16, $inp + sub $len, 1, $len + ldd [$end + 0], $rlhi ! round[last] + ldd [$end + 8], $rllo + + mov 16, $inc + movrz $len, 0, $inc + ldd [$key + 16], %f10 ! round[1] + ldd [$key + 24], %f12 + + ldd [%o7 + $ileft], $fshift ! shift left params + add %o7, 64, %o7 + ldd [$inp - 16], $in0 ! load input + ldd [$inp - 8], $in1 + ldda [$inp]0x82, $intail ! non-faulting load + brz $dir, .Lcbc_decrypt + add $inp, $inc, $inp ! inp+=16 + + fxor $r0hi, %f0, %f0 ! ivec^=round[0] + fxor $r0lo, %f2, %f2 + fshiftorx $in0, $in1, $fshift, $in0 + fshiftorx $in1, $intail, $fshift, $in1 + nop + +.Loop_cbc_enc: + fxor $in0, %f0, %f0 ! inp^ivec^round[0] + fxor $in1, %f2, %f2 + ldd [$key + 32], %f6 ! round[2] + ldd [$key + 40], %f8 + add $key, 32, $end + sub $rounds, 16*6, $inner + +.Lcbc_enc: + fmovd %f0, %f4 + faesencx %f2, %f10, %f0 + faesencx %f4, %f12, %f2 + ldd [$end + 16], %f10 + ldd [$end + 24], %f12 + add $end, 32, $end + + fmovd %f0, %f4 + faesencx %f2, %f6, %f0 + faesencx %f4, %f8, %f2 + ldd [$end + 0], %f6 + ldd [$end + 8], %f8 + + brnz,a $inner, .Lcbc_enc + sub $inner, 16*2, $inner + + fmovd %f0, %f4 + faesencx %f2, %f10, %f0 + faesencx %f4, %f12, %f2 + ldd [$end + 16], %f10 ! round[last-1] + ldd [$end + 24], %f12 + + movrz $len, 0, $inc + fmovd $intail, $in0 + ldd [$inp - 8], $in1 ! load next input block + ldda [$inp]0x82, $intail ! non-faulting load + add $inp, $inc, $inp ! inp+=16 + + fmovd %f0, %f4 + faesencx %f2, %f6, %f0 + faesencx %f4, %f8, %f2 + + fshiftorx $in0, $in1, $fshift, $in0 + fshiftorx $in1, $intail, $fshift, $in1 + + fmovd %f0, %f4 + faesencx %f2, %f10, %f0 + faesencx %f4, %f12, %f2 + ldd [$key + 16], %f10 ! round[1] + ldd [$key + 24], %f12 + + fxor $r0hi, $in0, $in0 ! inp^=round[0] + fxor $r0lo, $in1, $in1 + + fmovd %f0, %f4 + faesenclx %f2, $rlhi, %f0 + faesenclx %f4, $rllo, %f2 + + brnz,pn $oalign, .Lcbc_enc_unaligned_out + nop + + std %f0, [$out + 0] + std %f2, [$out + 8] + add $out, 16, $out + + brnz,a $len, .Loop_cbc_enc + sub $len, 1, $len + + st %f0, [$ivp + 0] ! output ivec + st %f1, [$ivp + 4] + st %f2, [$ivp + 8] + st %f3, [$ivp + 12] + +.Lcbc_no_data: + ret + restore + +.align 32 +.Lcbc_enc_unaligned_out: + ldd [%o7 + $mask], $fshift ! shift right params + mov 0xff, $mask + srl $mask, $oalign, $mask + sub %g0, $ileft, $iright + + fshiftorx %f0, %f0, $fshift, %f6 + fshiftorx %f0, %f2, $fshift, %f8 + + stda %f6, [$out + $mask]0xc0 ! partial store + orn %g0, $mask, $mask + std %f8, [$out + 8] + add $out, 16, $out + brz $len, .Lcbc_enc_unaligned_out_done + sub $len, 1, $len + b .Loop_cbc_enc_unaligned_out + nop + +.align 32 +.Loop_cbc_enc_unaligned_out: + fmovd %f2, $outhead + fxor $in0, %f0, %f0 ! inp^ivec^round[0] + fxor $in1, %f2, %f2 + ldd [$key + 32], %f6 ! round[2] + ldd [$key + 40], %f8 + + fmovd %f0, %f4 + faesencx %f2, %f10, %f0 + faesencx %f4, %f12, %f2 + ldd [$key + 48], %f10 ! round[3] + ldd [$key + 56], %f12 + + ldx [$inp - 16], %o0 + ldx [$inp - 8], %o1 + brz $ileft, .Lcbc_enc_aligned_inp + movrz $len, 0, $inc + + ldx [$inp], %o2 + sllx %o0, $ileft, %o0 + srlx %o1, $iright, %g1 + sllx %o1, $ileft, %o1 + or %g1, %o0, %o0 + srlx %o2, $iright, %o2 + or %o2, %o1, %o1 + +.Lcbc_enc_aligned_inp: + fmovd %f0, %f4 + faesencx %f2, %f6, %f0 + faesencx %f4, %f8, %f2 + ldd [$key + 64], %f6 ! round[4] + ldd [$key + 72], %f8 + add $key, 64, $end + sub $rounds, 16*8, $inner + + stx %o0, [%sp + LOCALS + 0] + stx %o1, [%sp + LOCALS + 8] + add $inp, $inc, $inp ! inp+=16 + nop + +.Lcbc_enc_unaligned: + fmovd %f0, %f4 + faesencx %f2, %f10, %f0 + faesencx %f4, %f12, %f2 + ldd [$end + 16], %f10 + ldd [$end + 24], %f12 + add $end, 32, $end + + fmovd %f0, %f4 + faesencx %f2, %f6, %f0 + faesencx %f4, %f8, %f2 + ldd [$end + 0], %f6 + ldd [$end + 8], %f8 + + brnz,a $inner, .Lcbc_enc_unaligned + sub $inner, 16*2, $inner + + fmovd %f0, %f4 + faesencx %f2, %f10, %f0 + faesencx %f4, %f12, %f2 + ldd [$end + 16], %f10 ! round[last-1] + ldd [$end + 24], %f12 + + fmovd %f0, %f4 + faesencx %f2, %f6, %f0 + faesencx %f4, %f8, %f2 + + ldd [%sp + LOCALS + 0], $in0 + ldd [%sp + LOCALS + 8], $in1 + + fmovd %f0, %f4 + faesencx %f2, %f10, %f0 + faesencx %f4, %f12, %f2 + ldd [$key + 16], %f10 ! round[1] + ldd [$key + 24], %f12 + + fxor $r0hi, $in0, $in0 ! inp^=round[0] + fxor $r0lo, $in1, $in1 + + fmovd %f0, %f4 + faesenclx %f2, $rlhi, %f0 + faesenclx %f4, $rllo, %f2 + + fshiftorx $outhead, %f0, $fshift, %f6 + fshiftorx %f0, %f2, $fshift, %f8 + std %f6, [$out + 0] + std %f8, [$out + 8] + add $out, 16, $out + + brnz,a $len, .Loop_cbc_enc_unaligned_out + sub $len, 1, $len + +.Lcbc_enc_unaligned_out_done: + fshiftorx %f2, %f2, $fshift, %f8 + stda %f8, [$out + $mask]0xc0 ! partial store + + st %f0, [$ivp + 0] ! output ivec + st %f1, [$ivp + 4] + st %f2, [$ivp + 8] + st %f3, [$ivp + 12] + + ret + restore + +.align 32 +.Lcbc_decrypt: + fshiftorx $in0, $in1, $fshift, $in0 + fshiftorx $in1, $intail, $fshift, $in1 + fmovd %f0, $iv0 + fmovd %f2, $iv1 + +.Loop_cbc_dec: + fxor $in0, $r0hi, %f0 ! inp^round[0] + fxor $in1, $r0lo, %f2 + ldd [$key + 32], %f6 ! round[2] + ldd [$key + 40], %f8 + add $key, 32, $end + sub $rounds, 16*6, $inner + +.Lcbc_dec: + fmovd %f0, %f4 + faesdecx %f2, %f10, %f0 + faesdecx %f4, %f12, %f2 + ldd [$end + 16], %f10 + ldd [$end + 24], %f12 + add $end, 32, $end + + fmovd %f0, %f4 + faesdecx %f2, %f6, %f0 + faesdecx %f4, %f8, %f2 + ldd [$end + 0], %f6 + ldd [$end + 8], %f8 + + brnz,a $inner, .Lcbc_dec + sub $inner, 16*2, $inner + + fmovd %f0, %f4 + faesdecx %f2, %f10, %f0 + faesdecx %f4, %f12, %f2 + ldd [$end + 16], %f10 ! round[last-1] + ldd [$end + 24], %f12 + + fmovd %f0, %f4 + faesdecx %f2, %f6, %f0 + faesdecx %f4, %f8, %f2 + fxor $iv0, $rlhi, %f6 ! ivec^round[last] + fxor $iv1, $rllo, %f8 + fmovd $in0, $iv0 + fmovd $in1, $iv1 + + movrz $len, 0, $inc + fmovd $intail, $in0 + ldd [$inp - 8], $in1 ! load next input block + ldda [$inp]0x82, $intail ! non-faulting load + add $inp, $inc, $inp ! inp+=16 + + fmovd %f0, %f4 + faesdecx %f2, %f10, %f0 + faesdecx %f4, %f12, %f2 + ldd [$key + 16], %f10 ! round[1] + ldd [$key + 24], %f12 + + fshiftorx $in0, $in1, $fshift, $in0 + fshiftorx $in1, $intail, $fshift, $in1 + + fmovd %f0, %f4 + faesdeclx %f2, %f6, %f0 + faesdeclx %f4, %f8, %f2 + + brnz,pn $oalign, .Lcbc_dec_unaligned_out + nop + + std %f0, [$out + 0] + std %f2, [$out + 8] + add $out, 16, $out + + brnz,a $len, .Loop_cbc_dec + sub $len, 1, $len + + st $iv0, [$ivp + 0] ! output ivec + st $iv0#lo, [$ivp + 4] + st $iv1, [$ivp + 8] + st $iv1#lo, [$ivp + 12] + + ret + restore + +.align 32 +.Lcbc_dec_unaligned_out: + ldd [%o7 + $mask], $fshift ! shift right params + mov 0xff, $mask + srl $mask, $oalign, $mask + sub %g0, $ileft, $iright + + fshiftorx %f0, %f0, $fshift, %f6 + fshiftorx %f0, %f2, $fshift, %f8 + + stda %f6, [$out + $mask]0xc0 ! partial store + orn %g0, $mask, $mask + std %f8, [$out + 8] + add $out, 16, $out + brz $len, .Lcbc_dec_unaligned_out_done + sub $len, 1, $len + b .Loop_cbc_dec_unaligned_out + nop + +.align 32 +.Loop_cbc_dec_unaligned_out: + fmovd %f2, $outhead + fxor $in0, $r0hi, %f0 ! inp^round[0] + fxor $in1, $r0lo, %f2 + ldd [$key + 32], %f6 ! round[2] + ldd [$key + 40], %f8 + + fmovd %f0, %f4 + faesdecx %f2, %f10, %f0 + faesdecx %f4, %f12, %f2 + ldd [$key + 48], %f10 ! round[3] + ldd [$key + 56], %f12 + + ldx [$inp - 16], %o0 + ldx [$inp - 8], %o1 + brz $ileft, .Lcbc_dec_aligned_inp + movrz $len, 0, $inc + + ldx [$inp], %o2 + sllx %o0, $ileft, %o0 + srlx %o1, $iright, %g1 + sllx %o1, $ileft, %o1 + or %g1, %o0, %o0 + srlx %o2, $iright, %o2 + or %o2, %o1, %o1 + +.Lcbc_dec_aligned_inp: + fmovd %f0, %f4 + faesdecx %f2, %f6, %f0 + faesdecx %f4, %f8, %f2 + ldd [$key + 64], %f6 ! round[4] + ldd [$key + 72], %f8 + add $key, 64, $end + sub $rounds, 16*8, $inner + + stx %o0, [%sp + LOCALS + 0] + stx %o1, [%sp + LOCALS + 8] + add $inp, $inc, $inp ! inp+=16 + nop + +.Lcbc_dec_unaligned: + fmovd %f0, %f4 + faesdecx %f2, %f10, %f0 + faesdecx %f4, %f12, %f2 + ldd [$end + 16], %f10 + ldd [$end + 24], %f12 + add $end, 32, $end + + fmovd %f0, %f4 + faesdecx %f2, %f6, %f0 + faesdecx %f4, %f8, %f2 + ldd [$end + 0], %f6 + ldd [$end + 8], %f8 + + brnz,a $inner, .Lcbc_dec_unaligned + sub $inner, 16*2, $inner + + fmovd %f0, %f4 + faesdecx %f2, %f10, %f0 + faesdecx %f4, %f12, %f2 + ldd [$end + 16], %f10 ! round[last-1] + ldd [$end + 24], %f12 + + fmovd %f0, %f4 + faesdecx %f2, %f6, %f0 + faesdecx %f4, %f8, %f2 + + fxor $iv0, $rlhi, %f6 ! ivec^round[last] + fxor $iv1, $rllo, %f8 + fmovd $in0, $iv0 + fmovd $in1, $iv1 + ldd [%sp + LOCALS + 0], $in0 + ldd [%sp + LOCALS + 8], $in1 + + fmovd %f0, %f4 + faesdecx %f2, %f10, %f0 + faesdecx %f4, %f12, %f2 + ldd [$key + 16], %f10 ! round[1] + ldd [$key + 24], %f12 + + fmovd %f0, %f4 + faesdeclx %f2, %f6, %f0 + faesdeclx %f4, %f8, %f2 + + fshiftorx $outhead, %f0, $fshift, %f6 + fshiftorx %f0, %f2, $fshift, %f8 + std %f6, [$out + 0] + std %f8, [$out + 8] + add $out, 16, $out + + brnz,a $len, .Loop_cbc_dec_unaligned_out + sub $len, 1, $len + +.Lcbc_dec_unaligned_out_done: + fshiftorx %f2, %f2, $fshift, %f8 + stda %f8, [$out + $mask]0xc0 ! partial store + + st $iv0, [$ivp + 0] ! output ivec + st $iv0#lo, [$ivp + 4] + st $iv1, [$ivp + 8] + st $iv1#lo, [$ivp + 12] + + ret + restore +.type aes_fx_cbc_encrypt,#function +.size aes_fx_cbc_encrypt,.-aes_fx_cbc_encrypt +___ +} +{ +my ($inp,$out,$len,$key,$ivp) = map("%i$_",(0..5)); +my ($rounds,$inner,$end,$inc,$ialign,$oalign,$mask) = map("%l$_",(0..7)); +my ($ctr0,$ctr1,$r0hi,$r0lo,$rlhi,$rllo,$in0,$in1,$intail,$outhead,$fshift) + = map("%f$_",grep { !($_ & 1) } (16 .. 62)); +my ($ileft,$iright) = ($ialign, $oalign); +my $one = "%f14"; + +$code.=<<___; +.globl aes_fx_ctr32_encrypt_blocks +.align 32 +aes_fx_ctr32_encrypt_blocks: + save %sp, -STACK_FRAME-16, %sp + srln $len, 0, $len + and $inp, 7, $ialign + andn $inp, 7, $inp + brz,pn $len, .Lctr32_no_data + sll $ialign, 3, $ileft + +.Lpic: call .+8 + add %o7, .Linp_align - .Lpic, %o7 + + ld [$key + 240], $rounds + and $out, 7, $oalign + ld [$ivp + 0], $ctr0 ! load counter + andn $out, 7, $out + ld [$ivp + 4], $ctr0#lo + sll $oalign, 3, $mask + ld [$ivp + 8], $ctr1 + ld [$ivp + 12], $ctr1#lo + ldd [%o7 + 128], $one + + sll $rounds, 4, $rounds + add $rounds, $key, $end + ldd [$key + 0], $r0hi ! round[0] + ldd [$key + 8], $r0lo + + add $inp, 16, $inp + sub $len, 1, $len + ldd [$key + 16], %f10 ! round[1] + ldd [$key + 24], %f12 + + mov 16, $inc + movrz $len, 0, $inc + ldd [$end + 0], $rlhi ! round[last] + ldd [$end + 8], $rllo + + ldd [%o7 + $ileft], $fshift ! shiftleft params + add %o7, 64, %o7 + ldd [$inp - 16], $in0 ! load input + ldd [$inp - 8], $in1 + ldda [$inp]0x82, $intail ! non-faulting load + add $inp, $inc, $inp ! inp+=16 + + fshiftorx $in0, $in1, $fshift, $in0 + fshiftorx $in1, $intail, $fshift, $in1 + +.Loop_ctr32: + fxor $ctr0, $r0hi, %f0 ! counter^round[0] + fxor $ctr1, $r0lo, %f2 + ldd [$key + 32], %f6 ! round[2] + ldd [$key + 40], %f8 + add $key, 32, $end + sub $rounds, 16*6, $inner + +.Lctr32_enc: + fmovd %f0, %f4 + faesencx %f2, %f10, %f0 + faesencx %f4, %f12, %f2 + ldd [$end + 16], %f10 + ldd [$end + 24], %f12 + add $end, 32, $end + + fmovd %f0, %f4 + faesencx %f2, %f6, %f0 + faesencx %f4, %f8, %f2 + ldd [$end + 0], %f6 + ldd [$end + 8], %f8 + + brnz,a $inner, .Lctr32_enc + sub $inner, 16*2, $inner + + fmovd %f0, %f4 + faesencx %f2, %f10, %f0 + faesencx %f4, %f12, %f2 + ldd [$end + 16], %f10 ! round[last-1] + ldd [$end + 24], %f12 + + fmovd %f0, %f4 + faesencx %f2, %f6, %f0 + faesencx %f4, %f8, %f2 + fxor $in0, $rlhi, %f6 ! inp^round[last] + fxor $in1, $rllo, %f8 + + movrz $len, 0, $inc + fmovd $intail, $in0 + ldd [$inp - 8], $in1 ! load next input block + ldda [$inp]0x82, $intail ! non-faulting load + add $inp, $inc, $inp ! inp+=16 + + fmovd %f0, %f4 + faesencx %f2, %f10, %f0 + faesencx %f4, %f12, %f2 + ldd [$key + 16], %f10 ! round[1] + ldd [$key + 24], %f12 + + fshiftorx $in0, $in1, $fshift, $in0 + fshiftorx $in1, $intail, $fshift, $in1 + fpadd32 $ctr1, $one, $ctr1 ! increment counter + + fmovd %f0, %f4 + faesenclx %f2, %f6, %f0 + faesenclx %f4, %f8, %f2 + + brnz,pn $oalign, .Lctr32_unaligned_out + nop + + std %f0, [$out + 0] + std %f2, [$out + 8] + add $out, 16, $out + + brnz,a $len, .Loop_ctr32 + sub $len, 1, $len + +.Lctr32_no_data: + ret + restore + +.align 32 +.Lctr32_unaligned_out: + ldd [%o7 + $mask], $fshift ! shift right params + mov 0xff, $mask + srl $mask, $oalign, $mask + sub %g0, $ileft, $iright + + fshiftorx %f0, %f0, $fshift, %f6 + fshiftorx %f0, %f2, $fshift, %f8 + + stda %f6, [$out + $mask]0xc0 ! partial store + orn %g0, $mask, $mask + std %f8, [$out + 8] + add $out, 16, $out + brz $len, .Lctr32_unaligned_out_done + sub $len, 1, $len + b .Loop_ctr32_unaligned_out + nop + +.align 32 +.Loop_ctr32_unaligned_out: + fmovd %f2, $outhead + fxor $ctr0, $r0hi, %f0 ! counter^round[0] + fxor $ctr1, $r0lo, %f2 + ldd [$key + 32], %f6 ! round[2] + ldd [$key + 40], %f8 + + fmovd %f0, %f4 + faesencx %f2, %f10, %f0 + faesencx %f4, %f12, %f2 + ldd [$key + 48], %f10 ! round[3] + ldd [$key + 56], %f12 + + ldx [$inp - 16], %o0 + ldx [$inp - 8], %o1 + brz $ileft, .Lctr32_aligned_inp + movrz $len, 0, $inc + + ldx [$inp], %o2 + sllx %o0, $ileft, %o0 + srlx %o1, $iright, %g1 + sllx %o1, $ileft, %o1 + or %g1, %o0, %o0 + srlx %o2, $iright, %o2 + or %o2, %o1, %o1 + +.Lctr32_aligned_inp: + fmovd %f0, %f4 + faesencx %f2, %f6, %f0 + faesencx %f4, %f8, %f2 + ldd [$key + 64], %f6 ! round[4] + ldd [$key + 72], %f8 + add $key, 64, $end + sub $rounds, 16*8, $inner + + stx %o0, [%sp + LOCALS + 0] + stx %o1, [%sp + LOCALS + 8] + add $inp, $inc, $inp ! inp+=16 + nop + +.Lctr32_enc_unaligned: + fmovd %f0, %f4 + faesencx %f2, %f10, %f0 + faesencx %f4, %f12, %f2 + ldd [$end + 16], %f10 + ldd [$end + 24], %f12 + add $end, 32, $end + + fmovd %f0, %f4 + faesencx %f2, %f6, %f0 + faesencx %f4, %f8, %f2 + ldd [$end + 0], %f6 + ldd [$end + 8], %f8 + + brnz,a $inner, .Lctr32_enc_unaligned + sub $inner, 16*2, $inner + + fmovd %f0, %f4 + faesencx %f2, %f10, %f0 + faesencx %f4, %f12, %f2 + ldd [$end + 16], %f10 ! round[last-1] + ldd [$end + 24], %f12 + fpadd32 $ctr1, $one, $ctr1 ! increment counter + + fmovd %f0, %f4 + faesencx %f2, %f6, %f0 + faesencx %f4, %f8, %f2 + fxor $in0, $rlhi, %f6 ! inp^round[last] + fxor $in1, $rllo, %f8 + ldd [%sp + LOCALS + 0], $in0 + ldd [%sp + LOCALS + 8], $in1 + + fmovd %f0, %f4 + faesencx %f2, %f10, %f0 + faesencx %f4, %f12, %f2 + ldd [$key + 16], %f10 ! round[1] + ldd [$key + 24], %f12 + + fmovd %f0, %f4 + faesenclx %f2, %f6, %f0 + faesenclx %f4, %f8, %f2 + + fshiftorx $outhead, %f0, $fshift, %f6 + fshiftorx %f0, %f2, $fshift, %f8 + std %f6, [$out + 0] + std %f8, [$out + 8] + add $out, 16, $out + + brnz,a $len, .Loop_ctr32_unaligned_out + sub $len, 1, $len + +.Lctr32_unaligned_out_done: + fshiftorx %f2, %f2, $fshift, %f8 + stda %f8, [$out + $mask]0xc0 ! partial store + + ret + restore +.type aes_fx_ctr32_encrypt_blocks,#function +.size aes_fx_ctr32_encrypt_blocks,.-aes_fx_ctr32_encrypt_blocks + +.align 32 +.Linp_align: ! fshiftorx parameters for left shift toward %rs1 + .byte 0, 0, 64, 0, 0, 64, 0, -64 + .byte 0, 0, 56, 8, 0, 56, 8, -56 + .byte 0, 0, 48, 16, 0, 48, 16, -48 + .byte 0, 0, 40, 24, 0, 40, 24, -40 + .byte 0, 0, 32, 32, 0, 32, 32, -32 + .byte 0, 0, 24, 40, 0, 24, 40, -24 + .byte 0, 0, 16, 48, 0, 16, 48, -16 + .byte 0, 0, 8, 56, 0, 8, 56, -8 +.Lout_align: ! fshiftorx parameters for right shift toward %rs2 + .byte 0, 0, 0, 64, 0, 0, 64, 0 + .byte 0, 0, 8, 56, 0, 8, 56, -8 + .byte 0, 0, 16, 48, 0, 16, 48, -16 + .byte 0, 0, 24, 40, 0, 24, 40, -24 + .byte 0, 0, 32, 32, 0, 32, 32, -32 + .byte 0, 0, 40, 24, 0, 40, 24, -40 + .byte 0, 0, 48, 16, 0, 48, 16, -48 + .byte 0, 0, 56, 8, 0, 56, 8, -56 +.Lone: + .word 0, 1 +.asciz "AES for Fujitsu SPARC64 X, CRYPTOGAMS by " +.align 4 +___ +} +# Purpose of these subroutines is to explicitly encode VIS instructions, +# so that one can compile the module without having to specify VIS +# extensions on compiler command line, e.g. -xarch=v9 vs. -xarch=v9a. +# Idea is to reserve for option to produce "universal" binary and let +# programmer detect if current CPU is VIS capable at run-time. +sub unvis { +my ($mnemonic,$rs1,$rs2,$rd)=@_; +my ($ref,$opf); +my %visopf = ( "faligndata" => 0x048, + "bshuffle" => 0x04c, + "fpadd32" => 0x052, + "fxor" => 0x06c, + "fsrc2" => 0x078 ); + + $ref = "$mnemonic\t$rs1,$rs2,$rd"; + + if ($opf=$visopf{$mnemonic}) { + foreach ($rs1,$rs2,$rd) { + return $ref if (!/%f([0-9]{1,2})/); + $_=$1; + if ($1>=32) { + return $ref if ($1&1); + # re-encode for upper double register addressing + $_=($1|$1>>5)&31; + } + } + + return sprintf ".word\t0x%08x !%s", + 0x81b00000|$rd<<25|$rs1<<14|$opf<<5|$rs2, + $ref; + } else { + return $ref; + } +} + +sub unvis3 { +my ($mnemonic,$rs1,$rs2,$rd)=@_; +my %bias = ( "g" => 0, "o" => 8, "l" => 16, "i" => 24 ); +my ($ref,$opf); +my %visopf = ( "alignaddr" => 0x018, + "bmask" => 0x019, + "alignaddrl" => 0x01a ); + + $ref = "$mnemonic\t$rs1,$rs2,$rd"; + + if ($opf=$visopf{$mnemonic}) { + foreach ($rs1,$rs2,$rd) { + return $ref if (!/%([goli])([0-9])/); + $_=$bias{$1}+$2; + } + + return sprintf ".word\t0x%08x !%s", + 0x81b00000|$rd<<25|$rs1<<14|$opf<<5|$rs2, + $ref; + } else { + return $ref; + } +} + +sub unfx { +my ($mnemonic,$rs1,$rs2,$rd)=@_; +my ($ref,$opf); +my %aesopf = ( "faesencx" => 0x90, + "faesdecx" => 0x91, + "faesenclx" => 0x92, + "faesdeclx" => 0x93, + "faeskeyx" => 0x94 ); + + $ref = "$mnemonic\t$rs1,$rs2,$rd"; + + if (defined($opf=$aesopf{$mnemonic})) { + $rs2 = ($rs2 =~ /%f([0-6]*[02468])/) ? (($1|$1>>5)&31) : $rs2; + $rs2 = oct($rs2) if ($rs2 =~ /^0/); + + foreach ($rs1,$rd) { + return $ref if (!/%f([0-9]{1,2})/); + $_=$1; + if ($1>=32) { + return $ref if ($1&1); + # re-encode for upper double register addressing + $_=($1|$1>>5)&31; + } + } + + return sprintf ".word\t0x%08x !%s", + 2<<30|$rd<<25|0x36<<19|$rs1<<14|$opf<<5|$rs2, + $ref; + } else { + return $ref; + } +} + +sub unfx3src { +my ($mnemonic,$rs1,$rs2,$rs3,$rd)=@_; +my ($ref,$opf); +my %aesopf = ( "fshiftorx" => 0x0b ); + + $ref = "$mnemonic\t$rs1,$rs2,$rs3,$rd"; + + if (defined($opf=$aesopf{$mnemonic})) { + foreach ($rs1,$rs2,$rs3,$rd) { + return $ref if (!/%f([0-9]{1,2})/); + $_=$1; + if ($1>=32) { + return $ref if ($1&1); + # re-encode for upper double register addressing + $_=($1|$1>>5)&31; + } + } + + return sprintf ".word\t0x%08x !%s", + 2<<30|$rd<<25|0x37<<19|$rs1<<14|$rs3<<9|$opf<<5|$rs2, + $ref; + } else { + return $ref; + } +} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/ge; + + s/%f([0-9]+)#lo/sprintf "%%f%d",$1+1/ge; + + s/\b(faes[^x]{3,4}x)\s+(%f[0-9]{1,2}),\s*([%fx0-9]+),\s*(%f[0-9]{1,2})/ + &unfx($1,$2,$3,$4) + /ge or + s/\b([f][^\s]*)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*(%f[0-9]{1,2})/ + &unfx3src($1,$2,$3,$4,$5) + /ge or + s/\b([fb][^\s]*)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*(%f[0-9]{1,2})/ + &unvis($1,$2,$3,$4) + /ge or + s/\b(alignaddr[l]*)\s+(%[goli][0-7]),\s*(%[goli][0-7]),\s*(%[goli][0-7])/ + &unvis3($1,$2,$3,$4) + /ge; + print $_,"\n"; +} + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesni-mb-x86_64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesni-mb-x86_64.pl new file mode 100644 index 000000000..1f356d2d3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesni-mb-x86_64.pl @@ -0,0 +1,1474 @@ +#! /usr/bin/env perl +# Copyright 2013-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# Multi-buffer AES-NI procedures process several independent buffers +# in parallel by interleaving independent instructions. +# +# Cycles per byte for interleave factor 4: +# +# asymptotic measured +# --------------------------- +# Westmere 5.00/4=1.25 5.13/4=1.28 +# Atom 15.0/4=3.75 ?15.7/4=3.93 +# Sandy Bridge 5.06/4=1.27 5.18/4=1.29 +# Ivy Bridge 5.06/4=1.27 5.14/4=1.29 +# Haswell 4.44/4=1.11 4.44/4=1.11 +# Bulldozer 5.75/4=1.44 5.76/4=1.44 +# +# Cycles per byte for interleave factor 8 (not implemented for +# pre-AVX processors, where higher interleave factor incidentally +# doesn't result in improvement): +# +# asymptotic measured +# --------------------------- +# Sandy Bridge 5.06/8=0.64 7.10/8=0.89(*) +# Ivy Bridge 5.06/8=0.64 7.14/8=0.89(*) +# Haswell 5.00/8=0.63 5.00/8=0.63 +# Bulldozer 5.75/8=0.72 5.77/8=0.72 +# +# (*) Sandy/Ivy Bridge are known to handle high interleave factors +# suboptimally; + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +$avx=0; + +if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler version ([2-9]\.[0-9]+)/) { + $avx = ($1>=2.19) + ($1>=2.22); +} + +if (!$avx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) && + `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) { + $avx = ($1>=2.09) + ($1>=2.10); +} + +if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && + `ml64 2>&1` =~ /Version ([0-9]+)\./) { + $avx = ($1>=10) + ($1>=11); +} + +if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9]\.[0-9]+)/) { + $avx = ($2>=3.0) + ($2>3.0); +} + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +*STDOUT=*OUT; + +# void aesni_multi_cbc_encrypt ( +# struct { void *inp,*out; int blocks; double iv[2]; } inp[8]; +# const AES_KEY *key, +# int num); /* 1 or 2 */ +# +$inp="%rdi"; # 1st arg +$key="%rsi"; # 2nd arg +$num="%edx"; + +@inptr=map("%r$_",(8..11)); +@outptr=map("%r$_",(12..15)); + +($rndkey0,$rndkey1)=("%xmm0","%xmm1"); +@out=map("%xmm$_",(2..5)); +@inp=map("%xmm$_",(6..9)); +($counters,$mask,$zero)=map("%xmm$_",(10..12)); + +($rounds,$one,$sink,$offset)=("%eax","%ecx","%rbp","%rbx"); + +$code.=<<___; +.text + +.extern OPENSSL_ia32cap_P + +.globl aesni_multi_cbc_encrypt +.type aesni_multi_cbc_encrypt,\@function,3 +.align 32 +aesni_multi_cbc_encrypt: +.cfi_startproc +___ +$code.=<<___ if ($avx); + cmp \$2,$num + jb .Lenc_non_avx + mov OPENSSL_ia32cap_P+4(%rip),%ecx + test \$`1<<28`,%ecx # AVX bit + jnz _avx_cbc_enc_shortcut + jmp .Lenc_non_avx +.align 16 +.Lenc_non_avx: +___ +$code.=<<___; + mov %rsp,%rax +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +___ +$code.=<<___ if ($win64); + lea -0xa8(%rsp),%rsp + movaps %xmm6,(%rsp) + movaps %xmm7,0x10(%rsp) + movaps %xmm8,0x20(%rsp) + movaps %xmm9,0x30(%rsp) + movaps %xmm10,0x40(%rsp) + movaps %xmm11,0x50(%rsp) + movaps %xmm12,0x60(%rsp) + movaps %xmm13,-0x68(%rax) # not used, saved to share se_handler + movaps %xmm14,-0x58(%rax) + movaps %xmm15,-0x48(%rax) +___ +$code.=<<___; + # stack layout + # + # +0 output sink + # +16 input sink [original %rsp and $num] + # +32 counters + + sub \$48,%rsp + and \$-64,%rsp + mov %rax,16(%rsp) # original %rsp +.cfi_cfa_expression %rsp+16,deref,+8 + +.Lenc4x_body: + movdqu ($key),$zero # 0-round key + lea 0x78($key),$key # size optimization + lea 40*2($inp),$inp + +.Lenc4x_loop_grande: + mov $num,24(%rsp) # original $num + xor $num,$num +___ +for($i=0;$i<4;$i++) { + $code.=<<___; + mov `40*$i+16-40*2`($inp),$one # borrow $one for number of blocks + mov `40*$i+0-40*2`($inp),@inptr[$i] + cmp $num,$one + mov `40*$i+8-40*2`($inp),@outptr[$i] + cmovg $one,$num # find maximum + test $one,$one + movdqu `40*$i+24-40*2`($inp),@out[$i] # load IV + mov $one,`32+4*$i`(%rsp) # initialize counters + cmovle %rsp,@inptr[$i] # cancel input +___ +} +$code.=<<___; + test $num,$num + jz .Lenc4x_done + + movups 0x10-0x78($key),$rndkey1 + pxor $zero,@out[0] + movups 0x20-0x78($key),$rndkey0 + pxor $zero,@out[1] + mov 0xf0-0x78($key),$rounds + pxor $zero,@out[2] + movdqu (@inptr[0]),@inp[0] # load inputs + pxor $zero,@out[3] + movdqu (@inptr[1]),@inp[1] + pxor @inp[0],@out[0] + movdqu (@inptr[2]),@inp[2] + pxor @inp[1],@out[1] + movdqu (@inptr[3]),@inp[3] + pxor @inp[2],@out[2] + pxor @inp[3],@out[3] + movdqa 32(%rsp),$counters # load counters + xor $offset,$offset + jmp .Loop_enc4x + +.align 32 +.Loop_enc4x: + add \$16,$offset + lea 16(%rsp),$sink # sink pointer + mov \$1,$one # constant of 1 + sub $offset,$sink + + aesenc $rndkey1,@out[0] + prefetcht0 31(@inptr[0],$offset) # prefetch input + prefetcht0 31(@inptr[1],$offset) + aesenc $rndkey1,@out[1] + prefetcht0 31(@inptr[2],$offset) + prefetcht0 31(@inptr[2],$offset) + aesenc $rndkey1,@out[2] + aesenc $rndkey1,@out[3] + movups 0x30-0x78($key),$rndkey1 +___ +for($i=0;$i<4;$i++) { +my $rndkey = ($i&1) ? $rndkey1 : $rndkey0; +$code.=<<___; + cmp `32+4*$i`(%rsp),$one + aesenc $rndkey,@out[0] + aesenc $rndkey,@out[1] + aesenc $rndkey,@out[2] + cmovge $sink,@inptr[$i] # cancel input + cmovg $sink,@outptr[$i] # sink output + aesenc $rndkey,@out[3] + movups `0x40+16*$i-0x78`($key),$rndkey +___ +} +$code.=<<___; + movdqa $counters,$mask + aesenc $rndkey0,@out[0] + prefetcht0 15(@outptr[0],$offset) # prefetch output + prefetcht0 15(@outptr[1],$offset) + aesenc $rndkey0,@out[1] + prefetcht0 15(@outptr[2],$offset) + prefetcht0 15(@outptr[3],$offset) + aesenc $rndkey0,@out[2] + aesenc $rndkey0,@out[3] + movups 0x80-0x78($key),$rndkey0 + pxor $zero,$zero + + aesenc $rndkey1,@out[0] + pcmpgtd $zero,$mask + movdqu -0x78($key),$zero # reload 0-round key + aesenc $rndkey1,@out[1] + paddd $mask,$counters # decrement counters + movdqa $counters,32(%rsp) # update counters + aesenc $rndkey1,@out[2] + aesenc $rndkey1,@out[3] + movups 0x90-0x78($key),$rndkey1 + + cmp \$11,$rounds + + aesenc $rndkey0,@out[0] + aesenc $rndkey0,@out[1] + aesenc $rndkey0,@out[2] + aesenc $rndkey0,@out[3] + movups 0xa0-0x78($key),$rndkey0 + + jb .Lenc4x_tail + + aesenc $rndkey1,@out[0] + aesenc $rndkey1,@out[1] + aesenc $rndkey1,@out[2] + aesenc $rndkey1,@out[3] + movups 0xb0-0x78($key),$rndkey1 + + aesenc $rndkey0,@out[0] + aesenc $rndkey0,@out[1] + aesenc $rndkey0,@out[2] + aesenc $rndkey0,@out[3] + movups 0xc0-0x78($key),$rndkey0 + + je .Lenc4x_tail + + aesenc $rndkey1,@out[0] + aesenc $rndkey1,@out[1] + aesenc $rndkey1,@out[2] + aesenc $rndkey1,@out[3] + movups 0xd0-0x78($key),$rndkey1 + + aesenc $rndkey0,@out[0] + aesenc $rndkey0,@out[1] + aesenc $rndkey0,@out[2] + aesenc $rndkey0,@out[3] + movups 0xe0-0x78($key),$rndkey0 + jmp .Lenc4x_tail + +.align 32 +.Lenc4x_tail: + aesenc $rndkey1,@out[0] + aesenc $rndkey1,@out[1] + aesenc $rndkey1,@out[2] + aesenc $rndkey1,@out[3] + movdqu (@inptr[0],$offset),@inp[0] + movdqu 0x10-0x78($key),$rndkey1 + + aesenclast $rndkey0,@out[0] + movdqu (@inptr[1],$offset),@inp[1] + pxor $zero,@inp[0] + aesenclast $rndkey0,@out[1] + movdqu (@inptr[2],$offset),@inp[2] + pxor $zero,@inp[1] + aesenclast $rndkey0,@out[2] + movdqu (@inptr[3],$offset),@inp[3] + pxor $zero,@inp[2] + aesenclast $rndkey0,@out[3] + movdqu 0x20-0x78($key),$rndkey0 + pxor $zero,@inp[3] + + movups @out[0],-16(@outptr[0],$offset) + pxor @inp[0],@out[0] + movups @out[1],-16(@outptr[1],$offset) + pxor @inp[1],@out[1] + movups @out[2],-16(@outptr[2],$offset) + pxor @inp[2],@out[2] + movups @out[3],-16(@outptr[3],$offset) + pxor @inp[3],@out[3] + + dec $num + jnz .Loop_enc4x + + mov 16(%rsp),%rax # original %rsp +.cfi_def_cfa %rax,8 + mov 24(%rsp),$num + + #pxor @inp[0],@out[0] + #pxor @inp[1],@out[1] + #movdqu @out[0],`40*0+24-40*2`($inp) # output iv FIX ME! + #pxor @inp[2],@out[2] + #movdqu @out[1],`40*1+24-40*2`($inp) + #pxor @inp[3],@out[3] + #movdqu @out[2],`40*2+24-40*2`($inp) # won't fix, let caller + #movdqu @out[3],`40*3+24-40*2`($inp) # figure this out... + + lea `40*4`($inp),$inp + dec $num + jnz .Lenc4x_loop_grande + +.Lenc4x_done: +___ +$code.=<<___ if ($win64); + movaps -0xd8(%rax),%xmm6 + movaps -0xc8(%rax),%xmm7 + movaps -0xb8(%rax),%xmm8 + movaps -0xa8(%rax),%xmm9 + movaps -0x98(%rax),%xmm10 + movaps -0x88(%rax),%xmm11 + movaps -0x78(%rax),%xmm12 + #movaps -0x68(%rax),%xmm13 + #movaps -0x58(%rax),%xmm14 + #movaps -0x48(%rax),%xmm15 +___ +$code.=<<___; + mov -48(%rax),%r15 +.cfi_restore %r15 + mov -40(%rax),%r14 +.cfi_restore %r14 + mov -32(%rax),%r13 +.cfi_restore %r13 + mov -24(%rax),%r12 +.cfi_restore %r12 + mov -16(%rax),%rbp +.cfi_restore %rbp + mov -8(%rax),%rbx +.cfi_restore %rbx + lea (%rax),%rsp +.cfi_def_cfa_register %rsp +.Lenc4x_epilogue: + ret +.cfi_endproc +.size aesni_multi_cbc_encrypt,.-aesni_multi_cbc_encrypt + +.globl aesni_multi_cbc_decrypt +.type aesni_multi_cbc_decrypt,\@function,3 +.align 32 +aesni_multi_cbc_decrypt: +.cfi_startproc +___ +$code.=<<___ if ($avx); + cmp \$2,$num + jb .Ldec_non_avx + mov OPENSSL_ia32cap_P+4(%rip),%ecx + test \$`1<<28`,%ecx # AVX bit + jnz _avx_cbc_dec_shortcut + jmp .Ldec_non_avx +.align 16 +.Ldec_non_avx: +___ +$code.=<<___; + mov %rsp,%rax +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +___ +$code.=<<___ if ($win64); + lea -0xa8(%rsp),%rsp + movaps %xmm6,(%rsp) + movaps %xmm7,0x10(%rsp) + movaps %xmm8,0x20(%rsp) + movaps %xmm9,0x30(%rsp) + movaps %xmm10,0x40(%rsp) + movaps %xmm11,0x50(%rsp) + movaps %xmm12,0x60(%rsp) + movaps %xmm13,-0x68(%rax) # not used, saved to share se_handler + movaps %xmm14,-0x58(%rax) + movaps %xmm15,-0x48(%rax) +___ +$code.=<<___; + # stack layout + # + # +0 output sink + # +16 input sink [original %rsp and $num] + # +32 counters + + sub \$48,%rsp + and \$-64,%rsp + mov %rax,16(%rsp) # original %rsp +.cfi_cfa_expression %rsp+16,deref,+8 + +.Ldec4x_body: + movdqu ($key),$zero # 0-round key + lea 0x78($key),$key # size optimization + lea 40*2($inp),$inp + +.Ldec4x_loop_grande: + mov $num,24(%rsp) # original $num + xor $num,$num +___ +for($i=0;$i<4;$i++) { + $code.=<<___; + mov `40*$i+16-40*2`($inp),$one # borrow $one for number of blocks + mov `40*$i+0-40*2`($inp),@inptr[$i] + cmp $num,$one + mov `40*$i+8-40*2`($inp),@outptr[$i] + cmovg $one,$num # find maximum + test $one,$one + movdqu `40*$i+24-40*2`($inp),@inp[$i] # load IV + mov $one,`32+4*$i`(%rsp) # initialize counters + cmovle %rsp,@inptr[$i] # cancel input +___ +} +$code.=<<___; + test $num,$num + jz .Ldec4x_done + + movups 0x10-0x78($key),$rndkey1 + movups 0x20-0x78($key),$rndkey0 + mov 0xf0-0x78($key),$rounds + movdqu (@inptr[0]),@out[0] # load inputs + movdqu (@inptr[1]),@out[1] + pxor $zero,@out[0] + movdqu (@inptr[2]),@out[2] + pxor $zero,@out[1] + movdqu (@inptr[3]),@out[3] + pxor $zero,@out[2] + pxor $zero,@out[3] + movdqa 32(%rsp),$counters # load counters + xor $offset,$offset + jmp .Loop_dec4x + +.align 32 +.Loop_dec4x: + add \$16,$offset + lea 16(%rsp),$sink # sink pointer + mov \$1,$one # constant of 1 + sub $offset,$sink + + aesdec $rndkey1,@out[0] + prefetcht0 31(@inptr[0],$offset) # prefetch input + prefetcht0 31(@inptr[1],$offset) + aesdec $rndkey1,@out[1] + prefetcht0 31(@inptr[2],$offset) + prefetcht0 31(@inptr[3],$offset) + aesdec $rndkey1,@out[2] + aesdec $rndkey1,@out[3] + movups 0x30-0x78($key),$rndkey1 +___ +for($i=0;$i<4;$i++) { +my $rndkey = ($i&1) ? $rndkey1 : $rndkey0; +$code.=<<___; + cmp `32+4*$i`(%rsp),$one + aesdec $rndkey,@out[0] + aesdec $rndkey,@out[1] + aesdec $rndkey,@out[2] + cmovge $sink,@inptr[$i] # cancel input + cmovg $sink,@outptr[$i] # sink output + aesdec $rndkey,@out[3] + movups `0x40+16*$i-0x78`($key),$rndkey +___ +} +$code.=<<___; + movdqa $counters,$mask + aesdec $rndkey0,@out[0] + prefetcht0 15(@outptr[0],$offset) # prefetch output + prefetcht0 15(@outptr[1],$offset) + aesdec $rndkey0,@out[1] + prefetcht0 15(@outptr[2],$offset) + prefetcht0 15(@outptr[3],$offset) + aesdec $rndkey0,@out[2] + aesdec $rndkey0,@out[3] + movups 0x80-0x78($key),$rndkey0 + pxor $zero,$zero + + aesdec $rndkey1,@out[0] + pcmpgtd $zero,$mask + movdqu -0x78($key),$zero # reload 0-round key + aesdec $rndkey1,@out[1] + paddd $mask,$counters # decrement counters + movdqa $counters,32(%rsp) # update counters + aesdec $rndkey1,@out[2] + aesdec $rndkey1,@out[3] + movups 0x90-0x78($key),$rndkey1 + + cmp \$11,$rounds + + aesdec $rndkey0,@out[0] + aesdec $rndkey0,@out[1] + aesdec $rndkey0,@out[2] + aesdec $rndkey0,@out[3] + movups 0xa0-0x78($key),$rndkey0 + + jb .Ldec4x_tail + + aesdec $rndkey1,@out[0] + aesdec $rndkey1,@out[1] + aesdec $rndkey1,@out[2] + aesdec $rndkey1,@out[3] + movups 0xb0-0x78($key),$rndkey1 + + aesdec $rndkey0,@out[0] + aesdec $rndkey0,@out[1] + aesdec $rndkey0,@out[2] + aesdec $rndkey0,@out[3] + movups 0xc0-0x78($key),$rndkey0 + + je .Ldec4x_tail + + aesdec $rndkey1,@out[0] + aesdec $rndkey1,@out[1] + aesdec $rndkey1,@out[2] + aesdec $rndkey1,@out[3] + movups 0xd0-0x78($key),$rndkey1 + + aesdec $rndkey0,@out[0] + aesdec $rndkey0,@out[1] + aesdec $rndkey0,@out[2] + aesdec $rndkey0,@out[3] + movups 0xe0-0x78($key),$rndkey0 + jmp .Ldec4x_tail + +.align 32 +.Ldec4x_tail: + aesdec $rndkey1,@out[0] + aesdec $rndkey1,@out[1] + aesdec $rndkey1,@out[2] + pxor $rndkey0,@inp[0] + pxor $rndkey0,@inp[1] + aesdec $rndkey1,@out[3] + movdqu 0x10-0x78($key),$rndkey1 + pxor $rndkey0,@inp[2] + pxor $rndkey0,@inp[3] + movdqu 0x20-0x78($key),$rndkey0 + + aesdeclast @inp[0],@out[0] + aesdeclast @inp[1],@out[1] + movdqu -16(@inptr[0],$offset),@inp[0] # load next IV + movdqu -16(@inptr[1],$offset),@inp[1] + aesdeclast @inp[2],@out[2] + aesdeclast @inp[3],@out[3] + movdqu -16(@inptr[2],$offset),@inp[2] + movdqu -16(@inptr[3],$offset),@inp[3] + + movups @out[0],-16(@outptr[0],$offset) + movdqu (@inptr[0],$offset),@out[0] + movups @out[1],-16(@outptr[1],$offset) + movdqu (@inptr[1],$offset),@out[1] + pxor $zero,@out[0] + movups @out[2],-16(@outptr[2],$offset) + movdqu (@inptr[2],$offset),@out[2] + pxor $zero,@out[1] + movups @out[3],-16(@outptr[3],$offset) + movdqu (@inptr[3],$offset),@out[3] + pxor $zero,@out[2] + pxor $zero,@out[3] + + dec $num + jnz .Loop_dec4x + + mov 16(%rsp),%rax # original %rsp +.cfi_def_cfa %rax,8 + mov 24(%rsp),$num + + lea `40*4`($inp),$inp + dec $num + jnz .Ldec4x_loop_grande + +.Ldec4x_done: +___ +$code.=<<___ if ($win64); + movaps -0xd8(%rax),%xmm6 + movaps -0xc8(%rax),%xmm7 + movaps -0xb8(%rax),%xmm8 + movaps -0xa8(%rax),%xmm9 + movaps -0x98(%rax),%xmm10 + movaps -0x88(%rax),%xmm11 + movaps -0x78(%rax),%xmm12 + #movaps -0x68(%rax),%xmm13 + #movaps -0x58(%rax),%xmm14 + #movaps -0x48(%rax),%xmm15 +___ +$code.=<<___; + mov -48(%rax),%r15 +.cfi_restore %r15 + mov -40(%rax),%r14 +.cfi_restore %r14 + mov -32(%rax),%r13 +.cfi_restore %r13 + mov -24(%rax),%r12 +.cfi_restore %r12 + mov -16(%rax),%rbp +.cfi_restore %rbp + mov -8(%rax),%rbx +.cfi_restore %rbx + lea (%rax),%rsp +.cfi_def_cfa_register %rsp +.Ldec4x_epilogue: + ret +.cfi_endproc +.size aesni_multi_cbc_decrypt,.-aesni_multi_cbc_decrypt +___ + + if ($avx) {{{ +my @ptr=map("%r$_",(8..15)); +my $offload=$sink; + +my @out=map("%xmm$_",(2..9)); +my @inp=map("%xmm$_",(10..13)); +my ($counters,$zero)=("%xmm14","%xmm15"); + +$code.=<<___; +.type aesni_multi_cbc_encrypt_avx,\@function,3 +.align 32 +aesni_multi_cbc_encrypt_avx: +.cfi_startproc +_avx_cbc_enc_shortcut: + mov %rsp,%rax +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +___ +$code.=<<___ if ($win64); + lea -0xa8(%rsp),%rsp + movaps %xmm6,(%rsp) + movaps %xmm7,0x10(%rsp) + movaps %xmm8,0x20(%rsp) + movaps %xmm9,0x30(%rsp) + movaps %xmm10,0x40(%rsp) + movaps %xmm11,0x50(%rsp) + movaps %xmm12,-0x78(%rax) + movaps %xmm13,-0x68(%rax) + movaps %xmm14,-0x58(%rax) + movaps %xmm15,-0x48(%rax) +___ +$code.=<<___; + # stack layout + # + # +0 output sink + # +16 input sink [original %rsp and $num] + # +32 counters + # +64 distances between inputs and outputs + # +128 off-load area for @inp[0..3] + + sub \$192,%rsp + and \$-128,%rsp + mov %rax,16(%rsp) # original %rsp +.cfi_cfa_expression %rsp+16,deref,+8 + +.Lenc8x_body: + vzeroupper + vmovdqu ($key),$zero # 0-round key + lea 0x78($key),$key # size optimization + lea 40*4($inp),$inp + shr \$1,$num + +.Lenc8x_loop_grande: + #mov $num,24(%rsp) # original $num + xor $num,$num +___ +for($i=0;$i<8;$i++) { + my $temp = $i ? $offload : $offset; + $code.=<<___; + mov `40*$i+16-40*4`($inp),$one # borrow $one for number of blocks + mov `40*$i+0-40*4`($inp),@ptr[$i] # input pointer + cmp $num,$one + mov `40*$i+8-40*4`($inp),$temp # output pointer + cmovg $one,$num # find maximum + test $one,$one + vmovdqu `40*$i+24-40*4`($inp),@out[$i] # load IV + mov $one,`32+4*$i`(%rsp) # initialize counters + cmovle %rsp,@ptr[$i] # cancel input + sub @ptr[$i],$temp # distance between input and output + mov $temp,`64+8*$i`(%rsp) # initialize distances +___ +} +$code.=<<___; + test $num,$num + jz .Lenc8x_done + + vmovups 0x10-0x78($key),$rndkey1 + vmovups 0x20-0x78($key),$rndkey0 + mov 0xf0-0x78($key),$rounds + + vpxor (@ptr[0]),$zero,@inp[0] # load inputs and xor with 0-round + lea 128(%rsp),$offload # offload area + vpxor (@ptr[1]),$zero,@inp[1] + vpxor (@ptr[2]),$zero,@inp[2] + vpxor (@ptr[3]),$zero,@inp[3] + vpxor @inp[0],@out[0],@out[0] + vpxor (@ptr[4]),$zero,@inp[0] + vpxor @inp[1],@out[1],@out[1] + vpxor (@ptr[5]),$zero,@inp[1] + vpxor @inp[2],@out[2],@out[2] + vpxor (@ptr[6]),$zero,@inp[2] + vpxor @inp[3],@out[3],@out[3] + vpxor (@ptr[7]),$zero,@inp[3] + vpxor @inp[0],@out[4],@out[4] + mov \$1,$one # constant of 1 + vpxor @inp[1],@out[5],@out[5] + vpxor @inp[2],@out[6],@out[6] + vpxor @inp[3],@out[7],@out[7] + jmp .Loop_enc8x + +.align 32 +.Loop_enc8x: +___ +for($i=0;$i<8;$i++) { +my $rndkey=($i&1)?$rndkey0:$rndkey1; +$code.=<<___; + vaesenc $rndkey,@out[0],@out[0] + cmp 32+4*$i(%rsp),$one +___ +$code.=<<___ if ($i); + mov 64+8*$i(%rsp),$offset +___ +$code.=<<___; + vaesenc $rndkey,@out[1],@out[1] + prefetcht0 31(@ptr[$i]) # prefetch input + vaesenc $rndkey,@out[2],@out[2] +___ +$code.=<<___ if ($i>1); + prefetcht0 15(@ptr[$i-2]) # prefetch output +___ +$code.=<<___; + vaesenc $rndkey,@out[3],@out[3] + lea (@ptr[$i],$offset),$offset + cmovge %rsp,@ptr[$i] # cancel input + vaesenc $rndkey,@out[4],@out[4] + cmovg %rsp,$offset # sink output + vaesenc $rndkey,@out[5],@out[5] + sub @ptr[$i],$offset + vaesenc $rndkey,@out[6],@out[6] + vpxor 16(@ptr[$i]),$zero,@inp[$i%4] # load input and xor with 0-round + mov $offset,64+8*$i(%rsp) + vaesenc $rndkey,@out[7],@out[7] + vmovups `16*(3+$i)-0x78`($key),$rndkey + lea 16(@ptr[$i],$offset),@ptr[$i] # switch to output +___ +$code.=<<___ if ($i<4) + vmovdqu @inp[$i%4],`16*$i`($offload) # off-load +___ +} +$code.=<<___; + vmovdqu 32(%rsp),$counters + prefetcht0 15(@ptr[$i-2]) # prefetch output + prefetcht0 15(@ptr[$i-1]) + cmp \$11,$rounds + jb .Lenc8x_tail + + vaesenc $rndkey1,@out[0],@out[0] + vaesenc $rndkey1,@out[1],@out[1] + vaesenc $rndkey1,@out[2],@out[2] + vaesenc $rndkey1,@out[3],@out[3] + vaesenc $rndkey1,@out[4],@out[4] + vaesenc $rndkey1,@out[5],@out[5] + vaesenc $rndkey1,@out[6],@out[6] + vaesenc $rndkey1,@out[7],@out[7] + vmovups 0xb0-0x78($key),$rndkey1 + + vaesenc $rndkey0,@out[0],@out[0] + vaesenc $rndkey0,@out[1],@out[1] + vaesenc $rndkey0,@out[2],@out[2] + vaesenc $rndkey0,@out[3],@out[3] + vaesenc $rndkey0,@out[4],@out[4] + vaesenc $rndkey0,@out[5],@out[5] + vaesenc $rndkey0,@out[6],@out[6] + vaesenc $rndkey0,@out[7],@out[7] + vmovups 0xc0-0x78($key),$rndkey0 + je .Lenc8x_tail + + vaesenc $rndkey1,@out[0],@out[0] + vaesenc $rndkey1,@out[1],@out[1] + vaesenc $rndkey1,@out[2],@out[2] + vaesenc $rndkey1,@out[3],@out[3] + vaesenc $rndkey1,@out[4],@out[4] + vaesenc $rndkey1,@out[5],@out[5] + vaesenc $rndkey1,@out[6],@out[6] + vaesenc $rndkey1,@out[7],@out[7] + vmovups 0xd0-0x78($key),$rndkey1 + + vaesenc $rndkey0,@out[0],@out[0] + vaesenc $rndkey0,@out[1],@out[1] + vaesenc $rndkey0,@out[2],@out[2] + vaesenc $rndkey0,@out[3],@out[3] + vaesenc $rndkey0,@out[4],@out[4] + vaesenc $rndkey0,@out[5],@out[5] + vaesenc $rndkey0,@out[6],@out[6] + vaesenc $rndkey0,@out[7],@out[7] + vmovups 0xe0-0x78($key),$rndkey0 + +.Lenc8x_tail: + vaesenc $rndkey1,@out[0],@out[0] + vpxor $zero,$zero,$zero + vaesenc $rndkey1,@out[1],@out[1] + vaesenc $rndkey1,@out[2],@out[2] + vpcmpgtd $zero,$counters,$zero + vaesenc $rndkey1,@out[3],@out[3] + vaesenc $rndkey1,@out[4],@out[4] + vpaddd $counters,$zero,$zero # decrement counters + vmovdqu 48(%rsp),$counters + vaesenc $rndkey1,@out[5],@out[5] + mov 64(%rsp),$offset # pre-load 1st offset + vaesenc $rndkey1,@out[6],@out[6] + vaesenc $rndkey1,@out[7],@out[7] + vmovups 0x10-0x78($key),$rndkey1 + + vaesenclast $rndkey0,@out[0],@out[0] + vmovdqa $zero,32(%rsp) # update counters + vpxor $zero,$zero,$zero + vaesenclast $rndkey0,@out[1],@out[1] + vaesenclast $rndkey0,@out[2],@out[2] + vpcmpgtd $zero,$counters,$zero + vaesenclast $rndkey0,@out[3],@out[3] + vaesenclast $rndkey0,@out[4],@out[4] + vpaddd $zero,$counters,$counters # decrement counters + vmovdqu -0x78($key),$zero # 0-round + vaesenclast $rndkey0,@out[5],@out[5] + vaesenclast $rndkey0,@out[6],@out[6] + vmovdqa $counters,48(%rsp) # update counters + vaesenclast $rndkey0,@out[7],@out[7] + vmovups 0x20-0x78($key),$rndkey0 + + vmovups @out[0],-16(@ptr[0]) # write output + sub $offset,@ptr[0] # switch to input + vpxor 0x00($offload),@out[0],@out[0] + vmovups @out[1],-16(@ptr[1]) + sub `64+1*8`(%rsp),@ptr[1] + vpxor 0x10($offload),@out[1],@out[1] + vmovups @out[2],-16(@ptr[2]) + sub `64+2*8`(%rsp),@ptr[2] + vpxor 0x20($offload),@out[2],@out[2] + vmovups @out[3],-16(@ptr[3]) + sub `64+3*8`(%rsp),@ptr[3] + vpxor 0x30($offload),@out[3],@out[3] + vmovups @out[4],-16(@ptr[4]) + sub `64+4*8`(%rsp),@ptr[4] + vpxor @inp[0],@out[4],@out[4] + vmovups @out[5],-16(@ptr[5]) + sub `64+5*8`(%rsp),@ptr[5] + vpxor @inp[1],@out[5],@out[5] + vmovups @out[6],-16(@ptr[6]) + sub `64+6*8`(%rsp),@ptr[6] + vpxor @inp[2],@out[6],@out[6] + vmovups @out[7],-16(@ptr[7]) + sub `64+7*8`(%rsp),@ptr[7] + vpxor @inp[3],@out[7],@out[7] + + dec $num + jnz .Loop_enc8x + + mov 16(%rsp),%rax # original %rsp +.cfi_def_cfa %rax,8 + #mov 24(%rsp),$num + #lea `40*8`($inp),$inp + #dec $num + #jnz .Lenc8x_loop_grande + +.Lenc8x_done: + vzeroupper +___ +$code.=<<___ if ($win64); + movaps -0xd8(%rax),%xmm6 + movaps -0xc8(%rax),%xmm7 + movaps -0xb8(%rax),%xmm8 + movaps -0xa8(%rax),%xmm9 + movaps -0x98(%rax),%xmm10 + movaps -0x88(%rax),%xmm11 + movaps -0x78(%rax),%xmm12 + movaps -0x68(%rax),%xmm13 + movaps -0x58(%rax),%xmm14 + movaps -0x48(%rax),%xmm15 +___ +$code.=<<___; + mov -48(%rax),%r15 +.cfi_restore %r15 + mov -40(%rax),%r14 +.cfi_restore %r14 + mov -32(%rax),%r13 +.cfi_restore %r13 + mov -24(%rax),%r12 +.cfi_restore %r12 + mov -16(%rax),%rbp +.cfi_restore %rbp + mov -8(%rax),%rbx +.cfi_restore %rbx + lea (%rax),%rsp +.cfi_def_cfa_register %rsp +.Lenc8x_epilogue: + ret +.cfi_endproc +.size aesni_multi_cbc_encrypt_avx,.-aesni_multi_cbc_encrypt_avx + +.type aesni_multi_cbc_decrypt_avx,\@function,3 +.align 32 +aesni_multi_cbc_decrypt_avx: +.cfi_startproc +_avx_cbc_dec_shortcut: + mov %rsp,%rax +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +___ +$code.=<<___ if ($win64); + lea -0xa8(%rsp),%rsp + movaps %xmm6,(%rsp) + movaps %xmm7,0x10(%rsp) + movaps %xmm8,0x20(%rsp) + movaps %xmm9,0x30(%rsp) + movaps %xmm10,0x40(%rsp) + movaps %xmm11,0x50(%rsp) + movaps %xmm12,-0x78(%rax) + movaps %xmm13,-0x68(%rax) + movaps %xmm14,-0x58(%rax) + movaps %xmm15,-0x48(%rax) +___ +$code.=<<___; + # stack layout + # + # +0 output sink + # +16 input sink [original %rsp and $num] + # +32 counters + # +64 distances between inputs and outputs + # +128 off-load area for @inp[0..3] + # +192 IV/input offload + + sub \$256,%rsp + and \$-256,%rsp + sub \$192,%rsp + mov %rax,16(%rsp) # original %rsp +.cfi_cfa_expression %rsp+16,deref,+8 + +.Ldec8x_body: + vzeroupper + vmovdqu ($key),$zero # 0-round key + lea 0x78($key),$key # size optimization + lea 40*4($inp),$inp + shr \$1,$num + +.Ldec8x_loop_grande: + #mov $num,24(%rsp) # original $num + xor $num,$num +___ +for($i=0;$i<8;$i++) { + my $temp = $i ? $offload : $offset; + $code.=<<___; + mov `40*$i+16-40*4`($inp),$one # borrow $one for number of blocks + mov `40*$i+0-40*4`($inp),@ptr[$i] # input pointer + cmp $num,$one + mov `40*$i+8-40*4`($inp),$temp # output pointer + cmovg $one,$num # find maximum + test $one,$one + vmovdqu `40*$i+24-40*4`($inp),@out[$i] # load IV + mov $one,`32+4*$i`(%rsp) # initialize counters + cmovle %rsp,@ptr[$i] # cancel input + sub @ptr[$i],$temp # distance between input and output + mov $temp,`64+8*$i`(%rsp) # initialize distances + vmovdqu @out[$i],`192+16*$i`(%rsp) # offload IV +___ +} +$code.=<<___; + test $num,$num + jz .Ldec8x_done + + vmovups 0x10-0x78($key),$rndkey1 + vmovups 0x20-0x78($key),$rndkey0 + mov 0xf0-0x78($key),$rounds + lea 192+128(%rsp),$offload # offload area + + vmovdqu (@ptr[0]),@out[0] # load inputs + vmovdqu (@ptr[1]),@out[1] + vmovdqu (@ptr[2]),@out[2] + vmovdqu (@ptr[3]),@out[3] + vmovdqu (@ptr[4]),@out[4] + vmovdqu (@ptr[5]),@out[5] + vmovdqu (@ptr[6]),@out[6] + vmovdqu (@ptr[7]),@out[7] + vmovdqu @out[0],0x00($offload) # offload inputs + vpxor $zero,@out[0],@out[0] # xor inputs with 0-round + vmovdqu @out[1],0x10($offload) + vpxor $zero,@out[1],@out[1] + vmovdqu @out[2],0x20($offload) + vpxor $zero,@out[2],@out[2] + vmovdqu @out[3],0x30($offload) + vpxor $zero,@out[3],@out[3] + vmovdqu @out[4],0x40($offload) + vpxor $zero,@out[4],@out[4] + vmovdqu @out[5],0x50($offload) + vpxor $zero,@out[5],@out[5] + vmovdqu @out[6],0x60($offload) + vpxor $zero,@out[6],@out[6] + vmovdqu @out[7],0x70($offload) + vpxor $zero,@out[7],@out[7] + xor \$0x80,$offload + mov \$1,$one # constant of 1 + jmp .Loop_dec8x + +.align 32 +.Loop_dec8x: +___ +for($i=0;$i<8;$i++) { +my $rndkey=($i&1)?$rndkey0:$rndkey1; +$code.=<<___; + vaesdec $rndkey,@out[0],@out[0] + cmp 32+4*$i(%rsp),$one +___ +$code.=<<___ if ($i); + mov 64+8*$i(%rsp),$offset +___ +$code.=<<___; + vaesdec $rndkey,@out[1],@out[1] + prefetcht0 31(@ptr[$i]) # prefetch input + vaesdec $rndkey,@out[2],@out[2] +___ +$code.=<<___ if ($i>1); + prefetcht0 15(@ptr[$i-2]) # prefetch output +___ +$code.=<<___; + vaesdec $rndkey,@out[3],@out[3] + lea (@ptr[$i],$offset),$offset + cmovge %rsp,@ptr[$i] # cancel input + vaesdec $rndkey,@out[4],@out[4] + cmovg %rsp,$offset # sink output + vaesdec $rndkey,@out[5],@out[5] + sub @ptr[$i],$offset + vaesdec $rndkey,@out[6],@out[6] + vmovdqu 16(@ptr[$i]),@inp[$i%4] # load input + mov $offset,64+8*$i(%rsp) + vaesdec $rndkey,@out[7],@out[7] + vmovups `16*(3+$i)-0x78`($key),$rndkey + lea 16(@ptr[$i],$offset),@ptr[$i] # switch to output +___ +$code.=<<___ if ($i<4); + vmovdqu @inp[$i%4],`128+16*$i`(%rsp) # off-load +___ +} +$code.=<<___; + vmovdqu 32(%rsp),$counters + prefetcht0 15(@ptr[$i-2]) # prefetch output + prefetcht0 15(@ptr[$i-1]) + cmp \$11,$rounds + jb .Ldec8x_tail + + vaesdec $rndkey1,@out[0],@out[0] + vaesdec $rndkey1,@out[1],@out[1] + vaesdec $rndkey1,@out[2],@out[2] + vaesdec $rndkey1,@out[3],@out[3] + vaesdec $rndkey1,@out[4],@out[4] + vaesdec $rndkey1,@out[5],@out[5] + vaesdec $rndkey1,@out[6],@out[6] + vaesdec $rndkey1,@out[7],@out[7] + vmovups 0xb0-0x78($key),$rndkey1 + + vaesdec $rndkey0,@out[0],@out[0] + vaesdec $rndkey0,@out[1],@out[1] + vaesdec $rndkey0,@out[2],@out[2] + vaesdec $rndkey0,@out[3],@out[3] + vaesdec $rndkey0,@out[4],@out[4] + vaesdec $rndkey0,@out[5],@out[5] + vaesdec $rndkey0,@out[6],@out[6] + vaesdec $rndkey0,@out[7],@out[7] + vmovups 0xc0-0x78($key),$rndkey0 + je .Ldec8x_tail + + vaesdec $rndkey1,@out[0],@out[0] + vaesdec $rndkey1,@out[1],@out[1] + vaesdec $rndkey1,@out[2],@out[2] + vaesdec $rndkey1,@out[3],@out[3] + vaesdec $rndkey1,@out[4],@out[4] + vaesdec $rndkey1,@out[5],@out[5] + vaesdec $rndkey1,@out[6],@out[6] + vaesdec $rndkey1,@out[7],@out[7] + vmovups 0xd0-0x78($key),$rndkey1 + + vaesdec $rndkey0,@out[0],@out[0] + vaesdec $rndkey0,@out[1],@out[1] + vaesdec $rndkey0,@out[2],@out[2] + vaesdec $rndkey0,@out[3],@out[3] + vaesdec $rndkey0,@out[4],@out[4] + vaesdec $rndkey0,@out[5],@out[5] + vaesdec $rndkey0,@out[6],@out[6] + vaesdec $rndkey0,@out[7],@out[7] + vmovups 0xe0-0x78($key),$rndkey0 + +.Ldec8x_tail: + vaesdec $rndkey1,@out[0],@out[0] + vpxor $zero,$zero,$zero + vaesdec $rndkey1,@out[1],@out[1] + vaesdec $rndkey1,@out[2],@out[2] + vpcmpgtd $zero,$counters,$zero + vaesdec $rndkey1,@out[3],@out[3] + vaesdec $rndkey1,@out[4],@out[4] + vpaddd $counters,$zero,$zero # decrement counters + vmovdqu 48(%rsp),$counters + vaesdec $rndkey1,@out[5],@out[5] + mov 64(%rsp),$offset # pre-load 1st offset + vaesdec $rndkey1,@out[6],@out[6] + vaesdec $rndkey1,@out[7],@out[7] + vmovups 0x10-0x78($key),$rndkey1 + + vaesdeclast $rndkey0,@out[0],@out[0] + vmovdqa $zero,32(%rsp) # update counters + vpxor $zero,$zero,$zero + vaesdeclast $rndkey0,@out[1],@out[1] + vpxor 0x00($offload),@out[0],@out[0] # xor with IV + vaesdeclast $rndkey0,@out[2],@out[2] + vpxor 0x10($offload),@out[1],@out[1] + vpcmpgtd $zero,$counters,$zero + vaesdeclast $rndkey0,@out[3],@out[3] + vpxor 0x20($offload),@out[2],@out[2] + vaesdeclast $rndkey0,@out[4],@out[4] + vpxor 0x30($offload),@out[3],@out[3] + vpaddd $zero,$counters,$counters # decrement counters + vmovdqu -0x78($key),$zero # 0-round + vaesdeclast $rndkey0,@out[5],@out[5] + vpxor 0x40($offload),@out[4],@out[4] + vaesdeclast $rndkey0,@out[6],@out[6] + vpxor 0x50($offload),@out[5],@out[5] + vmovdqa $counters,48(%rsp) # update counters + vaesdeclast $rndkey0,@out[7],@out[7] + vpxor 0x60($offload),@out[6],@out[6] + vmovups 0x20-0x78($key),$rndkey0 + + vmovups @out[0],-16(@ptr[0]) # write output + sub $offset,@ptr[0] # switch to input + vmovdqu 128+0(%rsp),@out[0] + vpxor 0x70($offload),@out[7],@out[7] + vmovups @out[1],-16(@ptr[1]) + sub `64+1*8`(%rsp),@ptr[1] + vmovdqu @out[0],0x00($offload) + vpxor $zero,@out[0],@out[0] + vmovdqu 128+16(%rsp),@out[1] + vmovups @out[2],-16(@ptr[2]) + sub `64+2*8`(%rsp),@ptr[2] + vmovdqu @out[1],0x10($offload) + vpxor $zero,@out[1],@out[1] + vmovdqu 128+32(%rsp),@out[2] + vmovups @out[3],-16(@ptr[3]) + sub `64+3*8`(%rsp),@ptr[3] + vmovdqu @out[2],0x20($offload) + vpxor $zero,@out[2],@out[2] + vmovdqu 128+48(%rsp),@out[3] + vmovups @out[4],-16(@ptr[4]) + sub `64+4*8`(%rsp),@ptr[4] + vmovdqu @out[3],0x30($offload) + vpxor $zero,@out[3],@out[3] + vmovdqu @inp[0],0x40($offload) + vpxor @inp[0],$zero,@out[4] + vmovups @out[5],-16(@ptr[5]) + sub `64+5*8`(%rsp),@ptr[5] + vmovdqu @inp[1],0x50($offload) + vpxor @inp[1],$zero,@out[5] + vmovups @out[6],-16(@ptr[6]) + sub `64+6*8`(%rsp),@ptr[6] + vmovdqu @inp[2],0x60($offload) + vpxor @inp[2],$zero,@out[6] + vmovups @out[7],-16(@ptr[7]) + sub `64+7*8`(%rsp),@ptr[7] + vmovdqu @inp[3],0x70($offload) + vpxor @inp[3],$zero,@out[7] + + xor \$128,$offload + dec $num + jnz .Loop_dec8x + + mov 16(%rsp),%rax # original %rsp +.cfi_def_cfa %rax,8 + #mov 24(%rsp),$num + #lea `40*8`($inp),$inp + #dec $num + #jnz .Ldec8x_loop_grande + +.Ldec8x_done: + vzeroupper +___ +$code.=<<___ if ($win64); + movaps -0xd8(%rax),%xmm6 + movaps -0xc8(%rax),%xmm7 + movaps -0xb8(%rax),%xmm8 + movaps -0xa8(%rax),%xmm9 + movaps -0x98(%rax),%xmm10 + movaps -0x88(%rax),%xmm11 + movaps -0x78(%rax),%xmm12 + movaps -0x68(%rax),%xmm13 + movaps -0x58(%rax),%xmm14 + movaps -0x48(%rax),%xmm15 +___ +$code.=<<___; + mov -48(%rax),%r15 +.cfi_restore %r15 + mov -40(%rax),%r14 +.cfi_restore %r14 + mov -32(%rax),%r13 +.cfi_restore %r13 + mov -24(%rax),%r12 +.cfi_restore %r12 + mov -16(%rax),%rbp +.cfi_restore %rbp + mov -8(%rax),%rbx +.cfi_restore %rbx + lea (%rax),%rsp +.cfi_def_cfa_register %rsp +.Ldec8x_epilogue: + ret +.cfi_endproc +.size aesni_multi_cbc_decrypt_avx,.-aesni_multi_cbc_decrypt_avx +___ + }}} + +if ($win64) { +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type se_handler,\@abi-omnipotent +.align 16 +se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->Rip<.Lprologue + jb .Lin_prologue + + mov 152($context),%rax # pull context->Rsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=.Lepilogue + jae .Lin_prologue + + mov 16(%rax),%rax # pull saved stack pointer + + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov -48(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + + lea -56-10*16(%rax),%rsi + lea 512($context),%rdi # &context.Xmm6 + mov \$20,%ecx + .long 0xa548f3fc # cld; rep movsq + +.Lin_prologue: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size se_handler,.-se_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_aesni_multi_cbc_encrypt + .rva .LSEH_end_aesni_multi_cbc_encrypt + .rva .LSEH_info_aesni_multi_cbc_encrypt + .rva .LSEH_begin_aesni_multi_cbc_decrypt + .rva .LSEH_end_aesni_multi_cbc_decrypt + .rva .LSEH_info_aesni_multi_cbc_decrypt +___ +$code.=<<___ if ($avx); + .rva .LSEH_begin_aesni_multi_cbc_encrypt_avx + .rva .LSEH_end_aesni_multi_cbc_encrypt_avx + .rva .LSEH_info_aesni_multi_cbc_encrypt_avx + .rva .LSEH_begin_aesni_multi_cbc_decrypt_avx + .rva .LSEH_end_aesni_multi_cbc_decrypt_avx + .rva .LSEH_info_aesni_multi_cbc_decrypt_avx +___ +$code.=<<___; +.section .xdata +.align 8 +.LSEH_info_aesni_multi_cbc_encrypt: + .byte 9,0,0,0 + .rva se_handler + .rva .Lenc4x_body,.Lenc4x_epilogue # HandlerData[] +.LSEH_info_aesni_multi_cbc_decrypt: + .byte 9,0,0,0 + .rva se_handler + .rva .Ldec4x_body,.Ldec4x_epilogue # HandlerData[] +___ +$code.=<<___ if ($avx); +.LSEH_info_aesni_multi_cbc_encrypt_avx: + .byte 9,0,0,0 + .rva se_handler + .rva .Lenc8x_body,.Lenc8x_epilogue # HandlerData[] +.LSEH_info_aesni_multi_cbc_decrypt_avx: + .byte 9,0,0,0 + .rva se_handler + .rva .Ldec8x_body,.Ldec8x_epilogue # HandlerData[] +___ +} +#################################################################### + +sub rex { + local *opcode=shift; + my ($dst,$src)=@_; + my $rex=0; + + $rex|=0x04 if($dst>=8); + $rex|=0x01 if($src>=8); + push @opcode,$rex|0x40 if($rex); +} + +sub aesni { + my $line=shift; + my @opcode=(0x66); + + if ($line=~/(aeskeygenassist)\s+\$([x0-9a-f]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) { + rex(\@opcode,$4,$3); + push @opcode,0x0f,0x3a,0xdf; + push @opcode,0xc0|($3&7)|(($4&7)<<3); # ModR/M + my $c=$2; + push @opcode,$c=~/^0/?oct($c):$c; + return ".byte\t".join(',',@opcode); + } + elsif ($line=~/(aes[a-z]+)\s+%xmm([0-9]+),\s*%xmm([0-9]+)/) { + my %opcodelet = ( + "aesimc" => 0xdb, + "aesenc" => 0xdc, "aesenclast" => 0xdd, + "aesdec" => 0xde, "aesdeclast" => 0xdf + ); + return undef if (!defined($opcodelet{$1})); + rex(\@opcode,$3,$2); + push @opcode,0x0f,0x38,$opcodelet{$1}; + push @opcode,0xc0|($2&7)|(($3&7)<<3); # ModR/M + return ".byte\t".join(',',@opcode); + } + elsif ($line=~/(aes[a-z]+)\s+([0x1-9a-fA-F]*)\(%rsp\),\s*%xmm([0-9]+)/) { + my %opcodelet = ( + "aesenc" => 0xdc, "aesenclast" => 0xdd, + "aesdec" => 0xde, "aesdeclast" => 0xdf + ); + return undef if (!defined($opcodelet{$1})); + my $off = $2; + push @opcode,0x44 if ($3>=8); + push @opcode,0x0f,0x38,$opcodelet{$1}; + push @opcode,0x44|(($3&7)<<3),0x24; # ModR/M + push @opcode,($off=~/^0/?oct($off):$off)&0xff; + return ".byte\t".join(',',@opcode); + } + return $line; +} + +$code =~ s/\`([^\`]*)\`/eval($1)/gem; +$code =~ s/\b(aes.*%xmm[0-9]+).*$/aesni($1)/gem; + +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesni-sha1-x86_64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesni-sha1-x86_64.pl new file mode 100644 index 000000000..b01a4c55c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesni-sha1-x86_64.pl @@ -0,0 +1,2140 @@ +#! /usr/bin/env perl +# Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# June 2011 +# +# This is AESNI-CBC+SHA1 "stitch" implementation. The idea, as spelled +# in http://download.intel.com/design/intarch/papers/323686.pdf, is +# that since AESNI-CBC encrypt exhibit *very* low instruction-level +# parallelism, interleaving it with another algorithm would allow to +# utilize processor resources better and achieve better performance. +# SHA1 instruction sequences(*) are taken from sha1-x86_64.pl and +# AESNI code is weaved into it. Below are performance numbers in +# cycles per processed byte, less is better, for standalone AESNI-CBC +# encrypt, sum of the latter and standalone SHA1, and "stitched" +# subroutine: +# +# AES-128-CBC +SHA1 stitch gain +# Westmere 3.77[+5.3] 9.07 6.55 +38% +# Sandy Bridge 5.05[+5.0(6.1)] 10.06(11.15) 5.98(7.05) +68%(+58%) +# Ivy Bridge 5.05[+4.6] 9.65 5.54 +74% +# Haswell 4.43[+3.6(4.2)] 8.00(8.58) 4.55(5.21) +75%(+65%) +# Skylake 2.63[+3.5(4.1)] 6.17(6.69) 4.23(4.44) +46%(+51%) +# Bulldozer 5.77[+6.0] 11.72 6.37 +84% +# Ryzen(**) 2.71[+1.93] 4.64 2.74 +69% +# Goldmont(**) 3.82[+1.70] 5.52 4.20 +31% +# +# AES-192-CBC +# Westmere 4.51 9.81 6.80 +44% +# Sandy Bridge 6.05 11.06(12.15) 6.11(7.19) +81%(+69%) +# Ivy Bridge 6.05 10.65 6.07 +75% +# Haswell 5.29 8.86(9.44) 5.32(5.32) +67%(+77%) +# Bulldozer 6.89 12.84 6.96 +84% +# +# AES-256-CBC +# Westmere 5.25 10.55 7.21 +46% +# Sandy Bridge 7.05 12.06(13.15) 7.12(7.72) +69%(+70%) +# Ivy Bridge 7.05 11.65 7.12 +64% +# Haswell 6.19 9.76(10.34) 6.21(6.25) +57%(+65%) +# Skylake 3.62 7.16(7.68) 4.56(4.76) +57%(+61%) +# Bulldozer 8.00 13.95 8.25 +69% +# Ryzen(**) 3.71 5.64 3.72 +52% +# Goldmont(**) 5.35 7.05 5.76 +22% +# +# (*) There are two code paths: SSSE3 and AVX. See sha1-568.pl for +# background information. Above numbers in parentheses are SSSE3 +# results collected on AVX-capable CPU, i.e. apply on OSes that +# don't support AVX. +# (**) SHAEXT results. +# +# Needless to mention that it makes no sense to implement "stitched" +# *decrypt* subroutine. Because *both* AESNI-CBC decrypt and SHA1 +# fully utilize parallelism, so stitching would not give any gain +# anyway. Well, there might be some, e.g. because of better cache +# locality... For reference, here are performance results for +# standalone AESNI-CBC decrypt: +# +# AES-128-CBC AES-192-CBC AES-256-CBC +# Westmere 1.25 1.50 1.75 +# Sandy Bridge 0.74 0.91 1.09 +# Ivy Bridge 0.74 0.90 1.11 +# Haswell 0.63 0.76 0.88 +# Bulldozer 0.70 0.85 0.99 + +# And indeed: +# +# AES-256-CBC +SHA1 stitch gain +# Westmere 1.75 7.20 6.68 +7.8% +# Sandy Bridge 1.09 6.09(7.22) 5.82(6.95) +4.6%(+3.9%) +# Ivy Bridge 1.11 5.70 5.45 +4.6% +# Haswell 0.88 4.45(5.00) 4.39(4.69) +1.4%(*)(+6.6%) +# Bulldozer 0.99 6.95 5.95 +17%(**) +# +# (*) Tiny improvement coefficient on Haswell is because we compare +# AVX1 stitch to sum with AVX2 SHA1. +# (**) Execution is fully dominated by integer code sequence and +# SIMD still hardly shows [in single-process benchmark;-] + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +$avx=1 if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler version ([2-9]\.[0-9]+)/ && + $1>=2.19); +$avx=1 if (!$avx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) && + `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/ && + $1>=2.09); +$avx=1 if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && + `ml64 2>&1` =~ /Version ([0-9]+)\./ && + $1>=10); +$avx=1 if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9]\.[0-9]+)/ && $2>=3.0); + +$shaext=1; ### set to zero if compiling for 1.0.1 + +$stitched_decrypt=0; + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +*STDOUT=*OUT; + +# void aesni_cbc_sha1_enc(const void *inp, +# void *out, +# size_t length, +# const AES_KEY *key, +# unsigned char *iv, +# SHA_CTX *ctx, +# const void *in0); + +$code.=<<___; +.text +.extern OPENSSL_ia32cap_P + +.globl aesni_cbc_sha1_enc +.type aesni_cbc_sha1_enc,\@abi-omnipotent +.align 32 +aesni_cbc_sha1_enc: + # caller should check for SSSE3 and AES-NI bits + mov OPENSSL_ia32cap_P+0(%rip),%r10d + mov OPENSSL_ia32cap_P+4(%rip),%r11 +___ +$code.=<<___ if ($shaext); + bt \$61,%r11 # check SHA bit + jc aesni_cbc_sha1_enc_shaext +___ +$code.=<<___ if ($avx); + and \$`1<<28`,%r11d # mask AVX bit + and \$`1<<30`,%r10d # mask "Intel CPU" bit + or %r11d,%r10d + cmp \$`1<<28|1<<30`,%r10d + je aesni_cbc_sha1_enc_avx +___ +$code.=<<___; + jmp aesni_cbc_sha1_enc_ssse3 + ret +.size aesni_cbc_sha1_enc,.-aesni_cbc_sha1_enc +___ + +my ($in0,$out,$len,$key,$ivp,$ctx,$inp)=("%rdi","%rsi","%rdx","%rcx","%r8","%r9","%r10"); + +my $Xi=4; +my @X=map("%xmm$_",(4..7,0..3)); +my @Tx=map("%xmm$_",(8..10)); +my @V=($A,$B,$C,$D,$E)=("%eax","%ebx","%ecx","%edx","%ebp"); # size optimization +my @T=("%esi","%edi"); +my $j=0; my $jj=0; my $r=0; my $sn=0; my $rx=0; +my $K_XX_XX="%r11"; +my ($rndkey0,$iv,$in)=map("%xmm$_",(11..13)); # for enc +my @rndkey=("%xmm14","%xmm15"); # for enc +my ($inout0,$inout1,$inout2,$inout3)=map("%xmm$_",(12..15)); # for dec + +if (1) { # reassign for Atom Silvermont + # The goal is to minimize amount of instructions with more than + # 3 prefix bytes. Or in more practical terms to keep AES-NI *and* + # SSSE3 instructions to upper half of the register bank. + @X=map("%xmm$_",(8..11,4..7)); + @Tx=map("%xmm$_",(12,13,3)); + ($iv,$in,$rndkey0)=map("%xmm$_",(2,14,15)); + @rndkey=("%xmm0","%xmm1"); +} + +sub AUTOLOAD() # thunk [simplified] 32-bit style perlasm +{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; + my $arg = pop; + $arg = "\$$arg" if ($arg*1 eq $arg); + $code .= "\t$opcode\t".join(',',$arg,reverse @_)."\n"; +} + +my $_rol=sub { &rol(@_) }; +my $_ror=sub { &ror(@_) }; + +$code.=<<___; +.type aesni_cbc_sha1_enc_ssse3,\@function,6 +.align 32 +aesni_cbc_sha1_enc_ssse3: +.cfi_startproc + mov `($win64?56:8)`(%rsp),$inp # load 7th argument + #shr \$6,$len # debugging artefact + #jz .Lepilogue_ssse3 # debugging artefact + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + lea `-104-($win64?10*16:0)`(%rsp),%rsp +.cfi_adjust_cfa_offset `104+($win64?10*16:0)` + #mov $in0,$inp # debugging artefact + #lea 64(%rsp),$ctx # debugging artefact +___ +$code.=<<___ if ($win64); + movaps %xmm6,96+0(%rsp) + movaps %xmm7,96+16(%rsp) + movaps %xmm8,96+32(%rsp) + movaps %xmm9,96+48(%rsp) + movaps %xmm10,96+64(%rsp) + movaps %xmm11,96+80(%rsp) + movaps %xmm12,96+96(%rsp) + movaps %xmm13,96+112(%rsp) + movaps %xmm14,96+128(%rsp) + movaps %xmm15,96+144(%rsp) +.Lprologue_ssse3: +___ +$code.=<<___; + mov $in0,%r12 # reassign arguments + mov $out,%r13 + mov $len,%r14 + lea 112($key),%r15 # size optimization + movdqu ($ivp),$iv # load IV + mov $ivp,88(%rsp) # save $ivp +___ +($in0,$out,$len,$key)=map("%r$_",(12..15)); # reassign arguments +my $rounds="${ivp}d"; +$code.=<<___; + shl \$6,$len + sub $in0,$out + mov 240-112($key),$rounds + add $inp,$len # end of input + + lea K_XX_XX(%rip),$K_XX_XX + mov 0($ctx),$A # load context + mov 4($ctx),$B + mov 8($ctx),$C + mov 12($ctx),$D + mov $B,@T[0] # magic seed + mov 16($ctx),$E + mov $C,@T[1] + xor $D,@T[1] + and @T[1],@T[0] + + movdqa 64($K_XX_XX),@Tx[2] # pbswap mask + movdqa 0($K_XX_XX),@Tx[1] # K_00_19 + movdqu 0($inp),@X[-4&7] # load input to %xmm[0-3] + movdqu 16($inp),@X[-3&7] + movdqu 32($inp),@X[-2&7] + movdqu 48($inp),@X[-1&7] + pshufb @Tx[2],@X[-4&7] # byte swap + pshufb @Tx[2],@X[-3&7] + pshufb @Tx[2],@X[-2&7] + add \$64,$inp + paddd @Tx[1],@X[-4&7] # add K_00_19 + pshufb @Tx[2],@X[-1&7] + paddd @Tx[1],@X[-3&7] + paddd @Tx[1],@X[-2&7] + movdqa @X[-4&7],0(%rsp) # X[]+K xfer to IALU + psubd @Tx[1],@X[-4&7] # restore X[] + movdqa @X[-3&7],16(%rsp) + psubd @Tx[1],@X[-3&7] + movdqa @X[-2&7],32(%rsp) + psubd @Tx[1],@X[-2&7] + movups -112($key),$rndkey0 # $key[0] + movups 16-112($key),$rndkey[0] # forward reference + jmp .Loop_ssse3 +___ + +my $aesenc=sub { + use integer; + my ($n,$k)=($r/10,$r%10); + if ($k==0) { + $code.=<<___; + movups `16*$n`($in0),$in # load input + xorps $rndkey0,$in +___ + $code.=<<___ if ($n); + movups $iv,`16*($n-1)`($out,$in0) # write output +___ + $code.=<<___; + xorps $in,$iv + movups `32+16*$k-112`($key),$rndkey[1] + aesenc $rndkey[0],$iv +___ + } elsif ($k==9) { + $sn++; + $code.=<<___; + cmp \$11,$rounds + jb .Laesenclast$sn + movups `32+16*($k+0)-112`($key),$rndkey[1] + aesenc $rndkey[0],$iv + movups `32+16*($k+1)-112`($key),$rndkey[0] + aesenc $rndkey[1],$iv + je .Laesenclast$sn + movups `32+16*($k+2)-112`($key),$rndkey[1] + aesenc $rndkey[0],$iv + movups `32+16*($k+3)-112`($key),$rndkey[0] + aesenc $rndkey[1],$iv +.Laesenclast$sn: + aesenclast $rndkey[0],$iv + movups 16-112($key),$rndkey[1] # forward reference +___ + } else { + $code.=<<___; + movups `32+16*$k-112`($key),$rndkey[1] + aesenc $rndkey[0],$iv +___ + } + $r++; unshift(@rndkey,pop(@rndkey)); +}; + +sub Xupdate_ssse3_16_31() # recall that $Xi starts with 4 +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 40 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); # ror + &pshufd (@X[0],@X[-4&7],0xee); # was &movdqa (@X[0],@X[-3&7]); + eval(shift(@insns)); + &movdqa (@Tx[0],@X[-1&7]); + &paddd (@Tx[1],@X[-1&7]); + eval(shift(@insns)); + eval(shift(@insns)); + + &punpcklqdq(@X[0],@X[-3&7]); # compose "X[-14]" in "X[0]", was &palignr(@X[0],@X[-4&7],8); + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)); + &psrldq (@Tx[0],4); # "X[-3]", 3 dwords + eval(shift(@insns)); + eval(shift(@insns)); + + &pxor (@X[0],@X[-4&7]); # "X[0]"^="X[-16]" + eval(shift(@insns)); + eval(shift(@insns)); # ror + &pxor (@Tx[0],@X[-2&7]); # "X[-3]"^"X[-8]" + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &pxor (@X[0],@Tx[0]); # "X[0]"^="X[-3]"^"X[-8]" + eval(shift(@insns)); + eval(shift(@insns)); # rol + &movdqa (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU + eval(shift(@insns)); + eval(shift(@insns)); + + &movdqa (@Tx[2],@X[0]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # ror + &movdqa (@Tx[0],@X[0]); + eval(shift(@insns)); + + &pslldq (@Tx[2],12); # "X[0]"<<96, extract one dword + &paddd (@X[0],@X[0]); + eval(shift(@insns)); + eval(shift(@insns)); + + &psrld (@Tx[0],31); + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)); + &movdqa (@Tx[1],@Tx[2]); + eval(shift(@insns)); + eval(shift(@insns)); + + &psrld (@Tx[2],30); + eval(shift(@insns)); + eval(shift(@insns)); # ror + &por (@X[0],@Tx[0]); # "X[0]"<<<=1 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &pslld (@Tx[1],2); + &pxor (@X[0],@Tx[2]); + eval(shift(@insns)); + &movdqa (@Tx[2],eval(16*(($Xi)/5))."($K_XX_XX)"); # K_XX_XX + eval(shift(@insns)); # rol + eval(shift(@insns)); + eval(shift(@insns)); + + &pxor (@X[0],@Tx[1]); # "X[0]"^=("X[0]">>96)<<<2 + &pshufd (@Tx[1],@X[-1&7],0xee) if ($Xi==7); # was &movdqa (@Tx[0],@X[-1&7]) in Xupdate_ssse3_32_79 + + foreach (@insns) { eval; } # remaining instructions [if any] + + $Xi++; push(@X,shift(@X)); # "rotate" X[] + push(@Tx,shift(@Tx)); +} + +sub Xupdate_ssse3_32_79() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 to 44 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)) if ($Xi==8); + &pxor (@X[0],@X[-4&7]); # "X[0]"="X[-32]"^"X[-16]" + eval(shift(@insns)) if ($Xi==8); + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + eval(shift(@insns)) if (@insns[1] =~ /_ror/); + eval(shift(@insns)) if (@insns[0] =~ /_ror/); + &punpcklqdq(@Tx[0],@X[-1&7]); # compose "X[-6]", was &palignr(@Tx[0],@X[-2&7],8); + eval(shift(@insns)); + eval(shift(@insns)); # rol + + &pxor (@X[0],@X[-7&7]); # "X[0]"^="X[-28]" + eval(shift(@insns)); + eval(shift(@insns)); + if ($Xi%5) { + &movdqa (@Tx[2],@Tx[1]);# "perpetuate" K_XX_XX... + } else { # ... or load next one + &movdqa (@Tx[2],eval(16*($Xi/5))."($K_XX_XX)"); + } + eval(shift(@insns)); # ror + &paddd (@Tx[1],@X[-1&7]); + eval(shift(@insns)); + + &pxor (@X[0],@Tx[0]); # "X[0]"^="X[-6]" + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)) if (@insns[0] =~ /_ror/); + + &movdqa (@Tx[0],@X[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &movdqa (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU + eval(shift(@insns)); # ror + eval(shift(@insns)); + eval(shift(@insns)); # body_20_39 + + &pslld (@X[0],2); + eval(shift(@insns)); + eval(shift(@insns)); + &psrld (@Tx[0],30); + eval(shift(@insns)) if (@insns[0] =~ /_rol/);# rol + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # ror + + &por (@X[0],@Tx[0]); # "X[0]"<<<=2 + eval(shift(@insns)); + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)) if (@insns[1] =~ /_rol/); + eval(shift(@insns)) if (@insns[0] =~ /_rol/); + &pshufd(@Tx[1],@X[-1&7],0xee) if ($Xi<19); # was &movdqa (@Tx[1],@X[0]) + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)); + + foreach (@insns) { eval; } # remaining instructions + + $Xi++; push(@X,shift(@X)); # "rotate" X[] + push(@Tx,shift(@Tx)); +} + +sub Xuplast_ssse3_80() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &paddd (@Tx[1],@X[-1&7]); + eval(shift(@insns)); + eval(shift(@insns)); + + &movdqa (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer IALU + + foreach (@insns) { eval; } # remaining instructions + + &cmp ($inp,$len); + &je (shift); + + unshift(@Tx,pop(@Tx)); + + &movdqa (@Tx[2],"64($K_XX_XX)"); # pbswap mask + &movdqa (@Tx[1],"0($K_XX_XX)"); # K_00_19 + &movdqu (@X[-4&7],"0($inp)"); # load input + &movdqu (@X[-3&7],"16($inp)"); + &movdqu (@X[-2&7],"32($inp)"); + &movdqu (@X[-1&7],"48($inp)"); + &pshufb (@X[-4&7],@Tx[2]); # byte swap + &add ($inp,64); + + $Xi=0; +} + +sub Xloop_ssse3() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &pshufb (@X[($Xi-3)&7],@Tx[2]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &paddd (@X[($Xi-4)&7],@Tx[1]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &movdqa (eval(16*$Xi)."(%rsp)",@X[($Xi-4)&7]); # X[]+K xfer to IALU + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &psubd (@X[($Xi-4)&7],@Tx[1]); + + foreach (@insns) { eval; } + $Xi++; +} + +sub Xtail_ssse3() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + foreach (@insns) { eval; } +} + +my @body_00_19 = ( + '($a,$b,$c,$d,$e)=@V;'. + '&$_ror ($b,$j?7:2);', # $b>>>2 + '&xor (@T[0],$d);', + '&mov (@T[1],$a);', # $b for next round + + '&add ($e,eval(4*($j&15))."(%rsp)");',# X[]+K xfer + '&xor ($b,$c);', # $c^$d for next round + + '&$_rol ($a,5);', + '&add ($e,@T[0]);', + '&and (@T[1],$b);', # ($b&($c^$d)) for next round + + '&xor ($b,$c);', # restore $b + '&add ($e,$a);' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));' + ); + +sub body_00_19 () { # ((c^d)&b)^d + # on start @T[0]=(c^d)&b + return &body_20_39() if ($rx==19); $rx++; + + use integer; + my ($k,$n); + my @r=@body_00_19; + + $n = scalar(@r); + $k = (($jj+1)*12/20)*20*$n/12; # 12 aesencs per these 20 rounds + @r[$k%$n].='&$aesenc();' if ($jj==$k/$n); + $jj++; + + return @r; +} + +my @body_20_39 = ( + '($a,$b,$c,$d,$e)=@V;'. + '&add ($e,eval(4*($j&15))."(%rsp)");',# X[]+K xfer + '&xor (@T[0],$d) if($j==19);'. + '&xor (@T[0],$c) if($j> 19);', # ($b^$d^$c) + '&mov (@T[1],$a);', # $b for next round + + '&$_rol ($a,5);', + '&add ($e,@T[0]);', + '&xor (@T[1],$c) if ($j< 79);', # $b^$d for next round + + '&$_ror ($b,7);', # $b>>>2 + '&add ($e,$a);' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));' + ); + +sub body_20_39 () { # b^d^c + # on entry @T[0]=b^d + return &body_40_59() if ($rx==39); $rx++; + + use integer; + my ($k,$n); + my @r=@body_20_39; + + $n = scalar(@r); + $k = (($jj+1)*8/20)*20*$n/8; # 8 aesencs per these 20 rounds + @r[$k%$n].='&$aesenc();' if ($jj==$k/$n && $rx!=20); + $jj++; + + return @r; +} + +my @body_40_59 = ( + '($a,$b,$c,$d,$e)=@V;'. + '&add ($e,eval(4*($j&15))."(%rsp)");',# X[]+K xfer + '&and (@T[0],$c) if ($j>=40);', # (b^c)&(c^d) + '&xor ($c,$d) if ($j>=40);', # restore $c + + '&$_ror ($b,7);', # $b>>>2 + '&mov (@T[1],$a);', # $b for next round + '&xor (@T[0],$c);', + + '&$_rol ($a,5);', + '&add ($e,@T[0]);', + '&xor (@T[1],$c) if ($j==59);'. + '&xor (@T[1],$b) if ($j< 59);', # b^c for next round + + '&xor ($b,$c) if ($j< 59);', # c^d for next round + '&add ($e,$a);' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));' + ); + +sub body_40_59 () { # ((b^c)&(c^d))^c + # on entry @T[0]=(b^c), (c^=d) + $rx++; + + use integer; + my ($k,$n); + my @r=@body_40_59; + + $n = scalar(@r); + $k=(($jj+1)*12/20)*20*$n/12; # 12 aesencs per these 20 rounds + @r[$k%$n].='&$aesenc();' if ($jj==$k/$n && $rx!=40); + $jj++; + + return @r; +} +$code.=<<___; +.align 32 +.Loop_ssse3: +___ + &Xupdate_ssse3_16_31(\&body_00_19); + &Xupdate_ssse3_16_31(\&body_00_19); + &Xupdate_ssse3_16_31(\&body_00_19); + &Xupdate_ssse3_16_31(\&body_00_19); + &Xupdate_ssse3_32_79(\&body_00_19); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xupdate_ssse3_32_79(\&body_40_59); + &Xupdate_ssse3_32_79(\&body_40_59); + &Xupdate_ssse3_32_79(\&body_40_59); + &Xupdate_ssse3_32_79(\&body_40_59); + &Xupdate_ssse3_32_79(\&body_40_59); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xuplast_ssse3_80(\&body_20_39,".Ldone_ssse3"); # can jump to "done" + + $saved_j=$j; @saved_V=@V; + $saved_r=$r; @saved_rndkey=@rndkey; + + &Xloop_ssse3(\&body_20_39); + &Xloop_ssse3(\&body_20_39); + &Xloop_ssse3(\&body_20_39); + +$code.=<<___; + movups $iv,48($out,$in0) # write output + lea 64($in0),$in0 + + add 0($ctx),$A # update context + add 4($ctx),@T[0] + add 8($ctx),$C + add 12($ctx),$D + mov $A,0($ctx) + add 16($ctx),$E + mov @T[0],4($ctx) + mov @T[0],$B # magic seed + mov $C,8($ctx) + mov $C,@T[1] + mov $D,12($ctx) + xor $D,@T[1] + mov $E,16($ctx) + and @T[1],@T[0] + jmp .Loop_ssse3 + +.Ldone_ssse3: +___ + $jj=$j=$saved_j; @V=@saved_V; + $r=$saved_r; @rndkey=@saved_rndkey; + + &Xtail_ssse3(\&body_20_39); + &Xtail_ssse3(\&body_20_39); + &Xtail_ssse3(\&body_20_39); + +$code.=<<___; + movups $iv,48($out,$in0) # write output + mov 88(%rsp),$ivp # restore $ivp + + add 0($ctx),$A # update context + add 4($ctx),@T[0] + add 8($ctx),$C + mov $A,0($ctx) + add 12($ctx),$D + mov @T[0],4($ctx) + add 16($ctx),$E + mov $C,8($ctx) + mov $D,12($ctx) + mov $E,16($ctx) + movups $iv,($ivp) # write IV +___ +$code.=<<___ if ($win64); + movaps 96+0(%rsp),%xmm6 + movaps 96+16(%rsp),%xmm7 + movaps 96+32(%rsp),%xmm8 + movaps 96+48(%rsp),%xmm9 + movaps 96+64(%rsp),%xmm10 + movaps 96+80(%rsp),%xmm11 + movaps 96+96(%rsp),%xmm12 + movaps 96+112(%rsp),%xmm13 + movaps 96+128(%rsp),%xmm14 + movaps 96+144(%rsp),%xmm15 +___ +$code.=<<___; + lea `104+($win64?10*16:0)`(%rsp),%rsi +.cfi_def_cfa %rsi,56 + mov 0(%rsi),%r15 +.cfi_restore %r15 + mov 8(%rsi),%r14 +.cfi_restore %r14 + mov 16(%rsi),%r13 +.cfi_restore %r13 + mov 24(%rsi),%r12 +.cfi_restore %r12 + mov 32(%rsi),%rbp +.cfi_restore %rbp + mov 40(%rsi),%rbx +.cfi_restore %rbx + lea 48(%rsi),%rsp +.cfi_def_cfa %rsp,8 +.Lepilogue_ssse3: + ret +.cfi_endproc +.size aesni_cbc_sha1_enc_ssse3,.-aesni_cbc_sha1_enc_ssse3 +___ + + if ($stitched_decrypt) {{{ +# reset +($in0,$out,$len,$key,$ivp,$ctx,$inp)=("%rdi","%rsi","%rdx","%rcx","%r8","%r9","%r10"); +$j=$jj=$r=$rx=0; +$Xi=4; + +# reassign for Atom Silvermont (see above) +($inout0,$inout1,$inout2,$inout3,$rndkey0)=map("%xmm$_",(0..4)); +@X=map("%xmm$_",(8..13,6,7)); +@Tx=map("%xmm$_",(14,15,5)); + +my @aes256_dec = ( + '&movdqu($inout0,"0x00($in0)");', + '&movdqu($inout1,"0x10($in0)"); &pxor ($inout0,$rndkey0);', + '&movdqu($inout2,"0x20($in0)"); &pxor ($inout1,$rndkey0);', + '&movdqu($inout3,"0x30($in0)"); &pxor ($inout2,$rndkey0);', + + '&pxor ($inout3,$rndkey0); &movups ($rndkey0,"16-112($key)");', + '&movaps("64(%rsp)",@X[2]);', # save IV, originally @X[3] + undef,undef + ); +for ($i=0;$i<13;$i++) { + push (@aes256_dec,( + '&aesdec ($inout0,$rndkey0);', + '&aesdec ($inout1,$rndkey0);', + '&aesdec ($inout2,$rndkey0);', + '&aesdec ($inout3,$rndkey0); &movups($rndkey0,"'.(16*($i+2)-112).'($key)");' + )); + push (@aes256_dec,(undef,undef)) if (($i>=3 && $i<=5) || $i>=11); + push (@aes256_dec,(undef,undef)) if ($i==5); +} +push(@aes256_dec,( + '&aesdeclast ($inout0,$rndkey0); &movups (@X[0],"0x00($in0)");', + '&aesdeclast ($inout1,$rndkey0); &movups (@X[1],"0x10($in0)");', + '&aesdeclast ($inout2,$rndkey0); &movups (@X[2],"0x20($in0)");', + '&aesdeclast ($inout3,$rndkey0); &movups (@X[3],"0x30($in0)");', + + '&xorps ($inout0,"64(%rsp)"); &movdqu ($rndkey0,"-112($key)");', + '&xorps ($inout1,@X[0]); &movups ("0x00($out,$in0)",$inout0);', + '&xorps ($inout2,@X[1]); &movups ("0x10($out,$in0)",$inout1);', + '&xorps ($inout3,@X[2]); &movups ("0x20($out,$in0)",$inout2);', + + '&movups ("0x30($out,$in0)",$inout3);' + )); + +sub body_00_19_dec () { # ((c^d)&b)^d + # on start @T[0]=(c^d)&b + return &body_20_39_dec() if ($rx==19); + + my @r=@body_00_19; + + unshift (@r,@aes256_dec[$rx]) if (@aes256_dec[$rx]); + $rx++; + + return @r; +} + +sub body_20_39_dec () { # b^d^c + # on entry @T[0]=b^d + return &body_40_59_dec() if ($rx==39); + + my @r=@body_20_39; + + unshift (@r,@aes256_dec[$rx]) if (@aes256_dec[$rx]); + $rx++; + + return @r; +} + +sub body_40_59_dec () { # ((b^c)&(c^d))^c + # on entry @T[0]=(b^c), (c^=d) + + my @r=@body_40_59; + + unshift (@r,@aes256_dec[$rx]) if (@aes256_dec[$rx]); + $rx++; + + return @r; +} + +$code.=<<___; +.globl aesni256_cbc_sha1_dec +.type aesni256_cbc_sha1_dec,\@abi-omnipotent +.align 32 +aesni256_cbc_sha1_dec: + # caller should check for SSSE3 and AES-NI bits + mov OPENSSL_ia32cap_P+0(%rip),%r10d + mov OPENSSL_ia32cap_P+4(%rip),%r11d +___ +$code.=<<___ if ($avx); + and \$`1<<28`,%r11d # mask AVX bit + and \$`1<<30`,%r10d # mask "Intel CPU" bit + or %r11d,%r10d + cmp \$`1<<28|1<<30`,%r10d + je aesni256_cbc_sha1_dec_avx +___ +$code.=<<___; + jmp aesni256_cbc_sha1_dec_ssse3 + ret +.size aesni256_cbc_sha1_dec,.-aesni256_cbc_sha1_dec + +.type aesni256_cbc_sha1_dec_ssse3,\@function,6 +.align 32 +aesni256_cbc_sha1_dec_ssse3: +.cfi_startproc + mov `($win64?56:8)`(%rsp),$inp # load 7th argument + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + lea `-104-($win64?10*16:0)`(%rsp),%rsp +.cfi_adjust_cfa_offset `104+($win64?10*16:0)` +___ +$code.=<<___ if ($win64); + movaps %xmm6,96+0(%rsp) + movaps %xmm7,96+16(%rsp) + movaps %xmm8,96+32(%rsp) + movaps %xmm9,96+48(%rsp) + movaps %xmm10,96+64(%rsp) + movaps %xmm11,96+80(%rsp) + movaps %xmm12,96+96(%rsp) + movaps %xmm13,96+112(%rsp) + movaps %xmm14,96+128(%rsp) + movaps %xmm15,96+144(%rsp) +.Lprologue_dec_ssse3: +___ +$code.=<<___; + mov $in0,%r12 # reassign arguments + mov $out,%r13 + mov $len,%r14 + lea 112($key),%r15 # size optimization + movdqu ($ivp),@X[3] # load IV + #mov $ivp,88(%rsp) # save $ivp +___ +($in0,$out,$len,$key)=map("%r$_",(12..15)); # reassign arguments +$code.=<<___; + shl \$6,$len + sub $in0,$out + add $inp,$len # end of input + + lea K_XX_XX(%rip),$K_XX_XX + mov 0($ctx),$A # load context + mov 4($ctx),$B + mov 8($ctx),$C + mov 12($ctx),$D + mov $B,@T[0] # magic seed + mov 16($ctx),$E + mov $C,@T[1] + xor $D,@T[1] + and @T[1],@T[0] + + movdqa 64($K_XX_XX),@Tx[2] # pbswap mask + movdqa 0($K_XX_XX),@Tx[1] # K_00_19 + movdqu 0($inp),@X[-4&7] # load input to %xmm[0-3] + movdqu 16($inp),@X[-3&7] + movdqu 32($inp),@X[-2&7] + movdqu 48($inp),@X[-1&7] + pshufb @Tx[2],@X[-4&7] # byte swap + add \$64,$inp + pshufb @Tx[2],@X[-3&7] + pshufb @Tx[2],@X[-2&7] + pshufb @Tx[2],@X[-1&7] + paddd @Tx[1],@X[-4&7] # add K_00_19 + paddd @Tx[1],@X[-3&7] + paddd @Tx[1],@X[-2&7] + movdqa @X[-4&7],0(%rsp) # X[]+K xfer to IALU + psubd @Tx[1],@X[-4&7] # restore X[] + movdqa @X[-3&7],16(%rsp) + psubd @Tx[1],@X[-3&7] + movdqa @X[-2&7],32(%rsp) + psubd @Tx[1],@X[-2&7] + movdqu -112($key),$rndkey0 # $key[0] + jmp .Loop_dec_ssse3 + +.align 32 +.Loop_dec_ssse3: +___ + &Xupdate_ssse3_16_31(\&body_00_19_dec); + &Xupdate_ssse3_16_31(\&body_00_19_dec); + &Xupdate_ssse3_16_31(\&body_00_19_dec); + &Xupdate_ssse3_16_31(\&body_00_19_dec); + &Xupdate_ssse3_32_79(\&body_00_19_dec); + &Xupdate_ssse3_32_79(\&body_20_39_dec); + &Xupdate_ssse3_32_79(\&body_20_39_dec); + &Xupdate_ssse3_32_79(\&body_20_39_dec); + &Xupdate_ssse3_32_79(\&body_20_39_dec); + &Xupdate_ssse3_32_79(\&body_20_39_dec); + &Xupdate_ssse3_32_79(\&body_40_59_dec); + &Xupdate_ssse3_32_79(\&body_40_59_dec); + &Xupdate_ssse3_32_79(\&body_40_59_dec); + &Xupdate_ssse3_32_79(\&body_40_59_dec); + &Xupdate_ssse3_32_79(\&body_40_59_dec); + &Xupdate_ssse3_32_79(\&body_20_39_dec); + &Xuplast_ssse3_80(\&body_20_39_dec,".Ldone_dec_ssse3"); # can jump to "done" + + $saved_j=$j; @saved_V=@V; + $saved_rx=$rx; + + &Xloop_ssse3(\&body_20_39_dec); + &Xloop_ssse3(\&body_20_39_dec); + &Xloop_ssse3(\&body_20_39_dec); + + eval(@aes256_dec[-1]); # last store +$code.=<<___; + lea 64($in0),$in0 + + add 0($ctx),$A # update context + add 4($ctx),@T[0] + add 8($ctx),$C + add 12($ctx),$D + mov $A,0($ctx) + add 16($ctx),$E + mov @T[0],4($ctx) + mov @T[0],$B # magic seed + mov $C,8($ctx) + mov $C,@T[1] + mov $D,12($ctx) + xor $D,@T[1] + mov $E,16($ctx) + and @T[1],@T[0] + jmp .Loop_dec_ssse3 + +.Ldone_dec_ssse3: +___ + $jj=$j=$saved_j; @V=@saved_V; + $rx=$saved_rx; + + &Xtail_ssse3(\&body_20_39_dec); + &Xtail_ssse3(\&body_20_39_dec); + &Xtail_ssse3(\&body_20_39_dec); + + eval(@aes256_dec[-1]); # last store +$code.=<<___; + add 0($ctx),$A # update context + add 4($ctx),@T[0] + add 8($ctx),$C + mov $A,0($ctx) + add 12($ctx),$D + mov @T[0],4($ctx) + add 16($ctx),$E + mov $C,8($ctx) + mov $D,12($ctx) + mov $E,16($ctx) + movups @X[3],($ivp) # write IV +___ +$code.=<<___ if ($win64); + movaps 96+0(%rsp),%xmm6 + movaps 96+16(%rsp),%xmm7 + movaps 96+32(%rsp),%xmm8 + movaps 96+48(%rsp),%xmm9 + movaps 96+64(%rsp),%xmm10 + movaps 96+80(%rsp),%xmm11 + movaps 96+96(%rsp),%xmm12 + movaps 96+112(%rsp),%xmm13 + movaps 96+128(%rsp),%xmm14 + movaps 96+144(%rsp),%xmm15 +___ +$code.=<<___; + lea `104+($win64?10*16:0)`(%rsp),%rsi +.cfi_cfa_def %rsi,56 + mov 0(%rsi),%r15 +.cfi_restore %r15 + mov 8(%rsi),%r14 +.cfi_restore %r14 + mov 16(%rsi),%r13 +.cfi_restore %r13 + mov 24(%rsi),%r12 +.cfi_restore %r12 + mov 32(%rsi),%rbp +.cfi_restore %rbp + mov 40(%rsi),%rbx +.cfi_restore %rbx + lea 48(%rsi),%rsp +.cfi_cfa_def %rsp,8 +.Lepilogue_dec_ssse3: + ret +.cfi_endproc +.size aesni256_cbc_sha1_dec_ssse3,.-aesni256_cbc_sha1_dec_ssse3 +___ + }}} +$j=$jj=$r=$rx=0; + +if ($avx) { +my ($in0,$out,$len,$key,$ivp,$ctx,$inp)=("%rdi","%rsi","%rdx","%rcx","%r8","%r9","%r10"); + +my $Xi=4; +my @X=map("%xmm$_",(4..7,0..3)); +my @Tx=map("%xmm$_",(8..10)); +my @V=($A,$B,$C,$D,$E)=("%eax","%ebx","%ecx","%edx","%ebp"); # size optimization +my @T=("%esi","%edi"); +my ($rndkey0,$iv,$in)=map("%xmm$_",(11..13)); +my @rndkey=("%xmm14","%xmm15"); +my ($inout0,$inout1,$inout2,$inout3)=map("%xmm$_",(12..15)); # for dec +my $Kx=@Tx[2]; + +my $_rol=sub { &shld(@_[0],@_) }; +my $_ror=sub { &shrd(@_[0],@_) }; + +$code.=<<___; +.type aesni_cbc_sha1_enc_avx,\@function,6 +.align 32 +aesni_cbc_sha1_enc_avx: +.cfi_startproc + mov `($win64?56:8)`(%rsp),$inp # load 7th argument + #shr \$6,$len # debugging artefact + #jz .Lepilogue_avx # debugging artefact + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + lea `-104-($win64?10*16:0)`(%rsp),%rsp +.cfi_adjust_cfa_offset `104+($win64?10*16:0)` + #mov $in0,$inp # debugging artefact + #lea 64(%rsp),$ctx # debugging artefact +___ +$code.=<<___ if ($win64); + movaps %xmm6,96+0(%rsp) + movaps %xmm7,96+16(%rsp) + movaps %xmm8,96+32(%rsp) + movaps %xmm9,96+48(%rsp) + movaps %xmm10,96+64(%rsp) + movaps %xmm11,96+80(%rsp) + movaps %xmm12,96+96(%rsp) + movaps %xmm13,96+112(%rsp) + movaps %xmm14,96+128(%rsp) + movaps %xmm15,96+144(%rsp) +.Lprologue_avx: +___ +$code.=<<___; + vzeroall + mov $in0,%r12 # reassign arguments + mov $out,%r13 + mov $len,%r14 + lea 112($key),%r15 # size optimization + vmovdqu ($ivp),$iv # load IV + mov $ivp,88(%rsp) # save $ivp +___ +($in0,$out,$len,$key)=map("%r$_",(12..15)); # reassign arguments +my $rounds="${ivp}d"; +$code.=<<___; + shl \$6,$len + sub $in0,$out + mov 240-112($key),$rounds + add $inp,$len # end of input + + lea K_XX_XX(%rip),$K_XX_XX + mov 0($ctx),$A # load context + mov 4($ctx),$B + mov 8($ctx),$C + mov 12($ctx),$D + mov $B,@T[0] # magic seed + mov 16($ctx),$E + mov $C,@T[1] + xor $D,@T[1] + and @T[1],@T[0] + + vmovdqa 64($K_XX_XX),@X[2] # pbswap mask + vmovdqa 0($K_XX_XX),$Kx # K_00_19 + vmovdqu 0($inp),@X[-4&7] # load input to %xmm[0-3] + vmovdqu 16($inp),@X[-3&7] + vmovdqu 32($inp),@X[-2&7] + vmovdqu 48($inp),@X[-1&7] + vpshufb @X[2],@X[-4&7],@X[-4&7] # byte swap + add \$64,$inp + vpshufb @X[2],@X[-3&7],@X[-3&7] + vpshufb @X[2],@X[-2&7],@X[-2&7] + vpshufb @X[2],@X[-1&7],@X[-1&7] + vpaddd $Kx,@X[-4&7],@X[0] # add K_00_19 + vpaddd $Kx,@X[-3&7],@X[1] + vpaddd $Kx,@X[-2&7],@X[2] + vmovdqa @X[0],0(%rsp) # X[]+K xfer to IALU + vmovdqa @X[1],16(%rsp) + vmovdqa @X[2],32(%rsp) + vmovups -112($key),$rndkey[1] # $key[0] + vmovups 16-112($key),$rndkey[0] # forward reference + jmp .Loop_avx +___ + +my $aesenc=sub { + use integer; + my ($n,$k)=($r/10,$r%10); + if ($k==0) { + $code.=<<___; + vmovdqu `16*$n`($in0),$in # load input + vpxor $rndkey[1],$in,$in +___ + $code.=<<___ if ($n); + vmovups $iv,`16*($n-1)`($out,$in0) # write output +___ + $code.=<<___; + vpxor $in,$iv,$iv + vaesenc $rndkey[0],$iv,$iv + vmovups `32+16*$k-112`($key),$rndkey[1] +___ + } elsif ($k==9) { + $sn++; + $code.=<<___; + cmp \$11,$rounds + jb .Lvaesenclast$sn + vaesenc $rndkey[0],$iv,$iv + vmovups `32+16*($k+0)-112`($key),$rndkey[1] + vaesenc $rndkey[1],$iv,$iv + vmovups `32+16*($k+1)-112`($key),$rndkey[0] + je .Lvaesenclast$sn + vaesenc $rndkey[0],$iv,$iv + vmovups `32+16*($k+2)-112`($key),$rndkey[1] + vaesenc $rndkey[1],$iv,$iv + vmovups `32+16*($k+3)-112`($key),$rndkey[0] +.Lvaesenclast$sn: + vaesenclast $rndkey[0],$iv,$iv + vmovups -112($key),$rndkey[0] + vmovups 16-112($key),$rndkey[1] # forward reference +___ + } else { + $code.=<<___; + vaesenc $rndkey[0],$iv,$iv + vmovups `32+16*$k-112`($key),$rndkey[1] +___ + } + $r++; unshift(@rndkey,pop(@rndkey)); +}; + +sub Xupdate_avx_16_31() # recall that $Xi starts with 4 +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 40 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); + eval(shift(@insns)); + &vpalignr(@X[0],@X[-3&7],@X[-4&7],8); # compose "X[-14]" in "X[0]" + eval(shift(@insns)); + eval(shift(@insns)); + + &vpaddd (@Tx[1],$Kx,@X[-1&7]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpsrldq(@Tx[0],@X[-1&7],4); # "X[-3]", 3 dwords + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor (@X[0],@X[0],@X[-4&7]); # "X[0]"^="X[-16]" + eval(shift(@insns)); + eval(shift(@insns)); + + &vpxor (@Tx[0],@Tx[0],@X[-2&7]); # "X[-3]"^"X[-8]" + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpxor (@X[0],@X[0],@Tx[0]); # "X[0]"^="X[-3]"^"X[-8]" + eval(shift(@insns)); + eval(shift(@insns)); + &vmovdqa (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU + eval(shift(@insns)); + eval(shift(@insns)); + + &vpsrld (@Tx[0],@X[0],31); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpslldq(@Tx[1],@X[0],12); # "X[0]"<<96, extract one dword + &vpaddd (@X[0],@X[0],@X[0]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpor (@X[0],@X[0],@Tx[0]); # "X[0]"<<<=1 + &vpsrld (@Tx[0],@Tx[1],30); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpslld (@Tx[1],@Tx[1],2); + &vpxor (@X[0],@X[0],@Tx[0]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpxor (@X[0],@X[0],@Tx[1]); # "X[0]"^=("X[0]">>96)<<<2 + eval(shift(@insns)); + eval(shift(@insns)); + &vmovdqa ($Kx,eval(16*(($Xi)/5))."($K_XX_XX)") if ($Xi%5==0); # K_XX_XX + eval(shift(@insns)); + eval(shift(@insns)); + + + foreach (@insns) { eval; } # remaining instructions [if any] + + $Xi++; push(@X,shift(@X)); # "rotate" X[] +} + +sub Xupdate_avx_32_79() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 to 48 instructions + my ($a,$b,$c,$d,$e); + + &vpalignr(@Tx[0],@X[-1&7],@X[-2&7],8); # compose "X[-6]" + &vpxor (@X[0],@X[0],@X[-4&7]); # "X[0]"="X[-32]"^"X[-16]" + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + + &vpxor (@X[0],@X[0],@X[-7&7]); # "X[0]"^="X[-28]" + eval(shift(@insns)); + eval(shift(@insns)) if (@insns[0] !~ /&ro[rl]/); + &vpaddd (@Tx[1],$Kx,@X[-1&7]); + &vmovdqa ($Kx,eval(16*($Xi/5))."($K_XX_XX)") if ($Xi%5==0); + eval(shift(@insns)); # ror + eval(shift(@insns)); + + &vpxor (@X[0],@X[0],@Tx[0]); # "X[0]"^="X[-6]" + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + + &vpsrld (@Tx[0],@X[0],30); + &vmovdqa (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # ror + eval(shift(@insns)); + + &vpslld (@X[0],@X[0],2); + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # ror + eval(shift(@insns)); + + &vpor (@X[0],@X[0],@Tx[0]); # "X[0]"<<<=2 + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)); + + foreach (@insns) { eval; } # remaining instructions + + $Xi++; push(@X,shift(@X)); # "rotate" X[] +} + +sub Xuplast_avx_80() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); + &vpaddd (@Tx[1],$Kx,@X[-1&7]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vmovdqa (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer IALU + + foreach (@insns) { eval; } # remaining instructions + + &cmp ($inp,$len); + &je (shift); + + &vmovdqa(@Tx[1],"64($K_XX_XX)"); # pbswap mask + &vmovdqa($Kx,"0($K_XX_XX)"); # K_00_19 + &vmovdqu(@X[-4&7],"0($inp)"); # load input + &vmovdqu(@X[-3&7],"16($inp)"); + &vmovdqu(@X[-2&7],"32($inp)"); + &vmovdqu(@X[-1&7],"48($inp)"); + &vpshufb(@X[-4&7],@X[-4&7],@Tx[1]); # byte swap + &add ($inp,64); + + $Xi=0; +} + +sub Xloop_avx() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); + eval(shift(@insns)); + &vpshufb(@X[($Xi-3)&7],@X[($Xi-3)&7],@Tx[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpaddd (@Tx[0],@X[($Xi-4)&7],$Kx); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vmovdqa(eval(16*$Xi)."(%rsp)",@Tx[0]); # X[]+K xfer to IALU + eval(shift(@insns)); + eval(shift(@insns)); + + foreach (@insns) { eval; } + $Xi++; +} + +sub Xtail_avx() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + foreach (@insns) { eval; } +} + +$code.=<<___; +.align 32 +.Loop_avx: +___ + &Xupdate_avx_16_31(\&body_00_19); + &Xupdate_avx_16_31(\&body_00_19); + &Xupdate_avx_16_31(\&body_00_19); + &Xupdate_avx_16_31(\&body_00_19); + &Xupdate_avx_32_79(\&body_00_19); + &Xupdate_avx_32_79(\&body_20_39); + &Xupdate_avx_32_79(\&body_20_39); + &Xupdate_avx_32_79(\&body_20_39); + &Xupdate_avx_32_79(\&body_20_39); + &Xupdate_avx_32_79(\&body_20_39); + &Xupdate_avx_32_79(\&body_40_59); + &Xupdate_avx_32_79(\&body_40_59); + &Xupdate_avx_32_79(\&body_40_59); + &Xupdate_avx_32_79(\&body_40_59); + &Xupdate_avx_32_79(\&body_40_59); + &Xupdate_avx_32_79(\&body_20_39); + &Xuplast_avx_80(\&body_20_39,".Ldone_avx"); # can jump to "done" + + $saved_j=$j; @saved_V=@V; + $saved_r=$r; @saved_rndkey=@rndkey; + + &Xloop_avx(\&body_20_39); + &Xloop_avx(\&body_20_39); + &Xloop_avx(\&body_20_39); + +$code.=<<___; + vmovups $iv,48($out,$in0) # write output + lea 64($in0),$in0 + + add 0($ctx),$A # update context + add 4($ctx),@T[0] + add 8($ctx),$C + add 12($ctx),$D + mov $A,0($ctx) + add 16($ctx),$E + mov @T[0],4($ctx) + mov @T[0],$B # magic seed + mov $C,8($ctx) + mov $C,@T[1] + mov $D,12($ctx) + xor $D,@T[1] + mov $E,16($ctx) + and @T[1],@T[0] + jmp .Loop_avx + +.Ldone_avx: +___ + $jj=$j=$saved_j; @V=@saved_V; + $r=$saved_r; @rndkey=@saved_rndkey; + + &Xtail_avx(\&body_20_39); + &Xtail_avx(\&body_20_39); + &Xtail_avx(\&body_20_39); + +$code.=<<___; + vmovups $iv,48($out,$in0) # write output + mov 88(%rsp),$ivp # restore $ivp + + add 0($ctx),$A # update context + add 4($ctx),@T[0] + add 8($ctx),$C + mov $A,0($ctx) + add 12($ctx),$D + mov @T[0],4($ctx) + add 16($ctx),$E + mov $C,8($ctx) + mov $D,12($ctx) + mov $E,16($ctx) + vmovups $iv,($ivp) # write IV + vzeroall +___ +$code.=<<___ if ($win64); + movaps 96+0(%rsp),%xmm6 + movaps 96+16(%rsp),%xmm7 + movaps 96+32(%rsp),%xmm8 + movaps 96+48(%rsp),%xmm9 + movaps 96+64(%rsp),%xmm10 + movaps 96+80(%rsp),%xmm11 + movaps 96+96(%rsp),%xmm12 + movaps 96+112(%rsp),%xmm13 + movaps 96+128(%rsp),%xmm14 + movaps 96+144(%rsp),%xmm15 +___ +$code.=<<___; + lea `104+($win64?10*16:0)`(%rsp),%rsi +.cfi_def_cfa %rsi,56 + mov 0(%rsi),%r15 +.cfi_restore %r15 + mov 8(%rsi),%r14 +.cfi_restore %r14 + mov 16(%rsi),%r13 +.cfi_restore %r13 + mov 24(%rsi),%r12 +.cfi_restore %r12 + mov 32(%rsi),%rbp +.cfi_restore %rbp + mov 40(%rsi),%rbx +.cfi_restore %rbx + lea 48(%rsi),%rsp +.cfi_def_cfa %rsp,8 +.Lepilogue_avx: + ret +.cfi_endproc +.size aesni_cbc_sha1_enc_avx,.-aesni_cbc_sha1_enc_avx +___ + + if ($stitched_decrypt) {{{ +# reset +($in0,$out,$len,$key,$ivp,$ctx,$inp)=("%rdi","%rsi","%rdx","%rcx","%r8","%r9","%r10"); + +$j=$jj=$r=$rx=0; +$Xi=4; + +@aes256_dec = ( + '&vpxor ($inout0,$rndkey0,"0x00($in0)");', + '&vpxor ($inout1,$rndkey0,"0x10($in0)");', + '&vpxor ($inout2,$rndkey0,"0x20($in0)");', + '&vpxor ($inout3,$rndkey0,"0x30($in0)");', + + '&vmovups($rndkey0,"16-112($key)");', + '&vmovups("64(%rsp)",@X[2]);', # save IV, originally @X[3] + undef,undef + ); +for ($i=0;$i<13;$i++) { + push (@aes256_dec,( + '&vaesdec ($inout0,$inout0,$rndkey0);', + '&vaesdec ($inout1,$inout1,$rndkey0);', + '&vaesdec ($inout2,$inout2,$rndkey0);', + '&vaesdec ($inout3,$inout3,$rndkey0); &vmovups($rndkey0,"'.(16*($i+2)-112).'($key)");' + )); + push (@aes256_dec,(undef,undef)) if (($i>=3 && $i<=5) || $i>=11); + push (@aes256_dec,(undef,undef)) if ($i==5); +} +push(@aes256_dec,( + '&vaesdeclast ($inout0,$inout0,$rndkey0); &vmovups(@X[0],"0x00($in0)");', + '&vaesdeclast ($inout1,$inout1,$rndkey0); &vmovups(@X[1],"0x10($in0)");', + '&vaesdeclast ($inout2,$inout2,$rndkey0); &vmovups(@X[2],"0x20($in0)");', + '&vaesdeclast ($inout3,$inout3,$rndkey0); &vmovups(@X[3],"0x30($in0)");', + + '&vxorps ($inout0,$inout0,"64(%rsp)"); &vmovdqu($rndkey0,"-112($key)");', + '&vxorps ($inout1,$inout1,@X[0]); &vmovups("0x00($out,$in0)",$inout0);', + '&vxorps ($inout2,$inout2,@X[1]); &vmovups("0x10($out,$in0)",$inout1);', + '&vxorps ($inout3,$inout3,@X[2]); &vmovups("0x20($out,$in0)",$inout2);', + + '&vmovups ("0x30($out,$in0)",$inout3);' + )); + +$code.=<<___; +.type aesni256_cbc_sha1_dec_avx,\@function,6 +.align 32 +aesni256_cbc_sha1_dec_avx: +.cfi_startproc + mov `($win64?56:8)`(%rsp),$inp # load 7th argument + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + lea `-104-($win64?10*16:0)`(%rsp),%rsp +.cfi_adjust_cfa_offset `104+($win64?10*16:0)` +___ +$code.=<<___ if ($win64); + movaps %xmm6,96+0(%rsp) + movaps %xmm7,96+16(%rsp) + movaps %xmm8,96+32(%rsp) + movaps %xmm9,96+48(%rsp) + movaps %xmm10,96+64(%rsp) + movaps %xmm11,96+80(%rsp) + movaps %xmm12,96+96(%rsp) + movaps %xmm13,96+112(%rsp) + movaps %xmm14,96+128(%rsp) + movaps %xmm15,96+144(%rsp) +.Lprologue_dec_avx: +___ +$code.=<<___; + vzeroall + mov $in0,%r12 # reassign arguments + mov $out,%r13 + mov $len,%r14 + lea 112($key),%r15 # size optimization + vmovdqu ($ivp),@X[3] # load IV +___ +($in0,$out,$len,$key)=map("%r$_",(12..15)); # reassign arguments +$code.=<<___; + shl \$6,$len + sub $in0,$out + add $inp,$len # end of input + + lea K_XX_XX(%rip),$K_XX_XX + mov 0($ctx),$A # load context + mov 4($ctx),$B + mov 8($ctx),$C + mov 12($ctx),$D + mov $B,@T[0] # magic seed + mov 16($ctx),$E + mov $C,@T[1] + xor $D,@T[1] + and @T[1],@T[0] + + vmovdqa 64($K_XX_XX),@X[2] # pbswap mask + vmovdqa 0($K_XX_XX),$Kx # K_00_19 + vmovdqu 0($inp),@X[-4&7] # load input to %xmm[0-3] + vmovdqu 16($inp),@X[-3&7] + vmovdqu 32($inp),@X[-2&7] + vmovdqu 48($inp),@X[-1&7] + vpshufb @X[2],@X[-4&7],@X[-4&7] # byte swap + add \$64,$inp + vpshufb @X[2],@X[-3&7],@X[-3&7] + vpshufb @X[2],@X[-2&7],@X[-2&7] + vpshufb @X[2],@X[-1&7],@X[-1&7] + vpaddd $Kx,@X[-4&7],@X[0] # add K_00_19 + vpaddd $Kx,@X[-3&7],@X[1] + vpaddd $Kx,@X[-2&7],@X[2] + vmovdqa @X[0],0(%rsp) # X[]+K xfer to IALU + vmovdqa @X[1],16(%rsp) + vmovdqa @X[2],32(%rsp) + vmovups -112($key),$rndkey0 # $key[0] + jmp .Loop_dec_avx + +.align 32 +.Loop_dec_avx: +___ + &Xupdate_avx_16_31(\&body_00_19_dec); + &Xupdate_avx_16_31(\&body_00_19_dec); + &Xupdate_avx_16_31(\&body_00_19_dec); + &Xupdate_avx_16_31(\&body_00_19_dec); + &Xupdate_avx_32_79(\&body_00_19_dec); + &Xupdate_avx_32_79(\&body_20_39_dec); + &Xupdate_avx_32_79(\&body_20_39_dec); + &Xupdate_avx_32_79(\&body_20_39_dec); + &Xupdate_avx_32_79(\&body_20_39_dec); + &Xupdate_avx_32_79(\&body_20_39_dec); + &Xupdate_avx_32_79(\&body_40_59_dec); + &Xupdate_avx_32_79(\&body_40_59_dec); + &Xupdate_avx_32_79(\&body_40_59_dec); + &Xupdate_avx_32_79(\&body_40_59_dec); + &Xupdate_avx_32_79(\&body_40_59_dec); + &Xupdate_avx_32_79(\&body_20_39_dec); + &Xuplast_avx_80(\&body_20_39_dec,".Ldone_dec_avx"); # can jump to "done" + + $saved_j=$j; @saved_V=@V; + $saved_rx=$rx; + + &Xloop_avx(\&body_20_39_dec); + &Xloop_avx(\&body_20_39_dec); + &Xloop_avx(\&body_20_39_dec); + + eval(@aes256_dec[-1]); # last store +$code.=<<___; + lea 64($in0),$in0 + + add 0($ctx),$A # update context + add 4($ctx),@T[0] + add 8($ctx),$C + add 12($ctx),$D + mov $A,0($ctx) + add 16($ctx),$E + mov @T[0],4($ctx) + mov @T[0],$B # magic seed + mov $C,8($ctx) + mov $C,@T[1] + mov $D,12($ctx) + xor $D,@T[1] + mov $E,16($ctx) + and @T[1],@T[0] + jmp .Loop_dec_avx + +.Ldone_dec_avx: +___ + $jj=$j=$saved_j; @V=@saved_V; + $rx=$saved_rx; + + &Xtail_avx(\&body_20_39_dec); + &Xtail_avx(\&body_20_39_dec); + &Xtail_avx(\&body_20_39_dec); + + eval(@aes256_dec[-1]); # last store +$code.=<<___; + + add 0($ctx),$A # update context + add 4($ctx),@T[0] + add 8($ctx),$C + mov $A,0($ctx) + add 12($ctx),$D + mov @T[0],4($ctx) + add 16($ctx),$E + mov $C,8($ctx) + mov $D,12($ctx) + mov $E,16($ctx) + vmovups @X[3],($ivp) # write IV + vzeroall +___ +$code.=<<___ if ($win64); + movaps 96+0(%rsp),%xmm6 + movaps 96+16(%rsp),%xmm7 + movaps 96+32(%rsp),%xmm8 + movaps 96+48(%rsp),%xmm9 + movaps 96+64(%rsp),%xmm10 + movaps 96+80(%rsp),%xmm11 + movaps 96+96(%rsp),%xmm12 + movaps 96+112(%rsp),%xmm13 + movaps 96+128(%rsp),%xmm14 + movaps 96+144(%rsp),%xmm15 +___ +$code.=<<___; + lea `104+($win64?10*16:0)`(%rsp),%rsi +.cfi_def_cfa %rsi,56 + mov 0(%rsi),%r15 +.cfi_restore %r15 + mov 8(%rsi),%r14 +.cfi_restore %r14 + mov 16(%rsi),%r13 +.cfi_restore %r13 + mov 24(%rsi),%r12 +.cfi_restore %r12 + mov 32(%rsi),%rbp +.cfi_restore %rbp + mov 40(%rsi),%rbx +.cfi_restore %rbx + lea 48(%rsi),%rsp +.cfi_def_cfa %rsp,8 +.Lepilogue_dec_avx: + ret +.cfi_endproc +.size aesni256_cbc_sha1_dec_avx,.-aesni256_cbc_sha1_dec_avx +___ + }}} +} +$code.=<<___; +.align 64 +K_XX_XX: +.long 0x5a827999,0x5a827999,0x5a827999,0x5a827999 # K_00_19 +.long 0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1 # K_20_39 +.long 0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc # K_40_59 +.long 0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6 # K_60_79 +.long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f # pbswap mask +.byte 0xf,0xe,0xd,0xc,0xb,0xa,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0 + +.asciz "AESNI-CBC+SHA1 stitch for x86_64, CRYPTOGAMS by " +.align 64 +___ + if ($shaext) {{{ +($in0,$out,$len,$key,$ivp,$ctx,$inp)=("%rdi","%rsi","%rdx","%rcx","%r8","%r9","%r10"); + +$rounds="%r11d"; + +($iv,$in,$rndkey0)=map("%xmm$_",(2,14,15)); +@rndkey=("%xmm0","%xmm1"); +$r=0; + +my ($BSWAP,$ABCD,$E,$E_,$ABCD_SAVE,$E_SAVE)=map("%xmm$_",(7..12)); +my @MSG=map("%xmm$_",(3..6)); + +$code.=<<___; +.type aesni_cbc_sha1_enc_shaext,\@function,6 +.align 32 +aesni_cbc_sha1_enc_shaext: + mov `($win64?56:8)`(%rsp),$inp # load 7th argument +___ +$code.=<<___ if ($win64); + lea `-8-10*16`(%rsp),%rsp + movaps %xmm6,-8-10*16(%rax) + movaps %xmm7,-8-9*16(%rax) + movaps %xmm8,-8-8*16(%rax) + movaps %xmm9,-8-7*16(%rax) + movaps %xmm10,-8-6*16(%rax) + movaps %xmm11,-8-5*16(%rax) + movaps %xmm12,-8-4*16(%rax) + movaps %xmm13,-8-3*16(%rax) + movaps %xmm14,-8-2*16(%rax) + movaps %xmm15,-8-1*16(%rax) +.Lprologue_shaext: +___ +$code.=<<___; + movdqu ($ctx),$ABCD + movd 16($ctx),$E + movdqa K_XX_XX+0x50(%rip),$BSWAP # byte-n-word swap + + mov 240($key),$rounds + sub $in0,$out + movups ($key),$rndkey0 # $key[0] + movups ($ivp),$iv # load IV + movups 16($key),$rndkey[0] # forward reference + lea 112($key),$key # size optimization + + pshufd \$0b00011011,$ABCD,$ABCD # flip word order + pshufd \$0b00011011,$E,$E # flip word order + jmp .Loop_shaext + +.align 16 +.Loop_shaext: +___ + &$aesenc(); +$code.=<<___; + movdqu ($inp),@MSG[0] + movdqa $E,$E_SAVE # offload $E + pshufb $BSWAP,@MSG[0] + movdqu 0x10($inp),@MSG[1] + movdqa $ABCD,$ABCD_SAVE # offload $ABCD +___ + &$aesenc(); +$code.=<<___; + pshufb $BSWAP,@MSG[1] + + paddd @MSG[0],$E + movdqu 0x20($inp),@MSG[2] + lea 0x40($inp),$inp + pxor $E_SAVE,@MSG[0] # black magic +___ + &$aesenc(); +$code.=<<___; + pxor $E_SAVE,@MSG[0] # black magic + movdqa $ABCD,$E_ + pshufb $BSWAP,@MSG[2] + sha1rnds4 \$0,$E,$ABCD # 0-3 + sha1nexte @MSG[1],$E_ +___ + &$aesenc(); +$code.=<<___; + sha1msg1 @MSG[1],@MSG[0] + movdqu -0x10($inp),@MSG[3] + movdqa $ABCD,$E + pshufb $BSWAP,@MSG[3] +___ + &$aesenc(); +$code.=<<___; + sha1rnds4 \$0,$E_,$ABCD # 4-7 + sha1nexte @MSG[2],$E + pxor @MSG[2],@MSG[0] + sha1msg1 @MSG[2],@MSG[1] +___ + &$aesenc(); + +for($i=2;$i<20-4;$i++) { +$code.=<<___; + movdqa $ABCD,$E_ + sha1rnds4 \$`int($i/5)`,$E,$ABCD # 8-11 + sha1nexte @MSG[3],$E_ +___ + &$aesenc(); +$code.=<<___; + sha1msg2 @MSG[3],@MSG[0] + pxor @MSG[3],@MSG[1] + sha1msg1 @MSG[3],@MSG[2] +___ + ($E,$E_)=($E_,$E); + push(@MSG,shift(@MSG)); + + &$aesenc(); +} +$code.=<<___; + movdqa $ABCD,$E_ + sha1rnds4 \$3,$E,$ABCD # 64-67 + sha1nexte @MSG[3],$E_ + sha1msg2 @MSG[3],@MSG[0] + pxor @MSG[3],@MSG[1] +___ + &$aesenc(); +$code.=<<___; + movdqa $ABCD,$E + sha1rnds4 \$3,$E_,$ABCD # 68-71 + sha1nexte @MSG[0],$E + sha1msg2 @MSG[0],@MSG[1] +___ + &$aesenc(); +$code.=<<___; + movdqa $E_SAVE,@MSG[0] + movdqa $ABCD,$E_ + sha1rnds4 \$3,$E,$ABCD # 72-75 + sha1nexte @MSG[1],$E_ +___ + &$aesenc(); +$code.=<<___; + movdqa $ABCD,$E + sha1rnds4 \$3,$E_,$ABCD # 76-79 + sha1nexte $MSG[0],$E +___ + while($r<40) { &$aesenc(); } # remaining aesenc's +$code.=<<___; + dec $len + + paddd $ABCD_SAVE,$ABCD + movups $iv,48($out,$in0) # write output + lea 64($in0),$in0 + jnz .Loop_shaext + + pshufd \$0b00011011,$ABCD,$ABCD + pshufd \$0b00011011,$E,$E + movups $iv,($ivp) # write IV + movdqu $ABCD,($ctx) + movd $E,16($ctx) +___ +$code.=<<___ if ($win64); + movaps -8-10*16(%rax),%xmm6 + movaps -8-9*16(%rax),%xmm7 + movaps -8-8*16(%rax),%xmm8 + movaps -8-7*16(%rax),%xmm9 + movaps -8-6*16(%rax),%xmm10 + movaps -8-5*16(%rax),%xmm11 + movaps -8-4*16(%rax),%xmm12 + movaps -8-3*16(%rax),%xmm13 + movaps -8-2*16(%rax),%xmm14 + movaps -8-1*16(%rax),%xmm15 + mov %rax,%rsp +.Lepilogue_shaext: +___ +$code.=<<___; + ret +.size aesni_cbc_sha1_enc_shaext,.-aesni_cbc_sha1_enc_shaext +___ + }}} +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type ssse3_handler,\@abi-omnipotent +.align 16 +ssse3_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lcommon_seh_tail +___ +$code.=<<___ if ($shaext); + lea aesni_cbc_sha1_enc_shaext(%rip),%r10 + cmp %r10,%rbx + jb .Lseh_no_shaext + + lea (%rax),%rsi + lea 512($context),%rdi # &context.Xmm6 + mov \$20,%ecx + .long 0xa548f3fc # cld; rep movsq + lea 168(%rax),%rax # adjust stack pointer + jmp .Lcommon_seh_tail +.Lseh_no_shaext: +___ +$code.=<<___; + lea 96(%rax),%rsi + lea 512($context),%rdi # &context.Xmm6 + mov \$20,%ecx + .long 0xa548f3fc # cld; rep movsq + lea `104+10*16`(%rax),%rax # adjust stack pointer + + mov 0(%rax),%r15 + mov 8(%rax),%r14 + mov 16(%rax),%r13 + mov 24(%rax),%r12 + mov 32(%rax),%rbp + mov 40(%rax),%rbx + lea 48(%rax),%rax + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + +.Lcommon_seh_tail: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size ssse3_handler,.-ssse3_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_aesni_cbc_sha1_enc_ssse3 + .rva .LSEH_end_aesni_cbc_sha1_enc_ssse3 + .rva .LSEH_info_aesni_cbc_sha1_enc_ssse3 +___ +$code.=<<___ if ($avx); + .rva .LSEH_begin_aesni_cbc_sha1_enc_avx + .rva .LSEH_end_aesni_cbc_sha1_enc_avx + .rva .LSEH_info_aesni_cbc_sha1_enc_avx +___ +$code.=<<___ if ($shaext); + .rva .LSEH_begin_aesni_cbc_sha1_enc_shaext + .rva .LSEH_end_aesni_cbc_sha1_enc_shaext + .rva .LSEH_info_aesni_cbc_sha1_enc_shaext +___ +$code.=<<___; +.section .xdata +.align 8 +.LSEH_info_aesni_cbc_sha1_enc_ssse3: + .byte 9,0,0,0 + .rva ssse3_handler + .rva .Lprologue_ssse3,.Lepilogue_ssse3 # HandlerData[] +___ +$code.=<<___ if ($avx); +.LSEH_info_aesni_cbc_sha1_enc_avx: + .byte 9,0,0,0 + .rva ssse3_handler + .rva .Lprologue_avx,.Lepilogue_avx # HandlerData[] +___ +$code.=<<___ if ($shaext); +.LSEH_info_aesni_cbc_sha1_enc_shaext: + .byte 9,0,0,0 + .rva ssse3_handler + .rva .Lprologue_shaext,.Lepilogue_shaext # HandlerData[] +___ +} + +#################################################################### +sub rex { + local *opcode=shift; + my ($dst,$src)=@_; + my $rex=0; + + $rex|=0x04 if($dst>=8); + $rex|=0x01 if($src>=8); + unshift @opcode,$rex|0x40 if($rex); +} + +sub sha1rnds4 { + if (@_[0] =~ /\$([x0-9a-f]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) { + my @opcode=(0x0f,0x3a,0xcc); + rex(\@opcode,$3,$2); + push @opcode,0xc0|($2&7)|(($3&7)<<3); # ModR/M + my $c=$1; + push @opcode,$c=~/^0/?oct($c):$c; + return ".byte\t".join(',',@opcode); + } else { + return "sha1rnds4\t".@_[0]; + } +} + +sub sha1op38 { + my $instr = shift; + my %opcodelet = ( + "sha1nexte" => 0xc8, + "sha1msg1" => 0xc9, + "sha1msg2" => 0xca ); + + if (defined($opcodelet{$instr}) && @_[0] =~ /%xmm([0-9]+),\s*%xmm([0-9]+)/) { + my @opcode=(0x0f,0x38); + rex(\@opcode,$2,$1); + push @opcode,$opcodelet{$instr}; + push @opcode,0xc0|($1&7)|(($2&7)<<3); # ModR/M + return ".byte\t".join(',',@opcode); + } else { + return $instr."\t".@_[0]; + } +} + +sub aesni { + my $line=shift; + my @opcode=(0x0f,0x38); + + if ($line=~/(aes[a-z]+)\s+%xmm([0-9]+),\s*%xmm([0-9]+)/) { + my %opcodelet = ( + "aesenc" => 0xdc, "aesenclast" => 0xdd, + "aesdec" => 0xde, "aesdeclast" => 0xdf + ); + return undef if (!defined($opcodelet{$1})); + rex(\@opcode,$3,$2); + push @opcode,$opcodelet{$1},0xc0|($2&7)|(($3&7)<<3); # ModR/M + unshift @opcode,0x66; + return ".byte\t".join(',',@opcode); + } + return $line; +} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/geo; + + s/\b(sha1rnds4)\s+(.*)/sha1rnds4($2)/geo or + s/\b(sha1[^\s]*)\s+(.*)/sha1op38($1,$2)/geo or + s/\b(aes.*%xmm[0-9]+).*$/aesni($1)/geo; + + print $_,"\n"; +} +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesni-sha256-x86_64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesni-sha256-x86_64.pl new file mode 100644 index 000000000..ef4602371 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesni-sha256-x86_64.pl @@ -0,0 +1,1770 @@ +#! /usr/bin/env perl +# Copyright 2013-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# January 2013 +# +# This is AESNI-CBC+SHA256 stitch implementation. The idea, as spelled +# in http://download.intel.com/design/intarch/papers/323686.pdf, is +# that since AESNI-CBC encrypt exhibit *very* low instruction-level +# parallelism, interleaving it with another algorithm would allow to +# utilize processor resources better and achieve better performance. +# SHA256 instruction sequences(*) are taken from sha512-x86_64.pl and +# AESNI code is weaved into it. As SHA256 dominates execution time, +# stitch performance does not depend on AES key length. Below are +# performance numbers in cycles per processed byte, less is better, +# for standalone AESNI-CBC encrypt, standalone SHA256, and stitched +# subroutine: +# +# AES-128/-192/-256+SHA256 this(**) gain +# Sandy Bridge 5.05/6.05/7.05+11.6 13.0 +28%/36%/43% +# Ivy Bridge 5.05/6.05/7.05+10.3 11.6 +32%/41%/50% +# Haswell 4.43/5.29/6.19+7.80 8.79 +39%/49%/59% +# Skylake 2.62/3.14/3.62+7.70 8.10 +27%/34%/40% +# Bulldozer 5.77/6.89/8.00+13.7 13.7 +42%/50%/58% +# Ryzen(***) 2.71/-/3.71+2.05 2.74/-/3.73 +74%/-/54% +# Goldmont(***) 3.82/-/5.35+4.16 4.73/-/5.94 +69%/-/60% +# +# (*) there are XOP, AVX1 and AVX2 code paths, meaning that +# Westmere is omitted from loop, this is because gain was not +# estimated high enough to justify the effort; +# (**) these are EVP-free results, results obtained with 'speed +# -evp aes-256-cbc-hmac-sha256' will vary by percent or two; +# (***) these are SHAEXT results; + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler version ([2-9]\.[0-9]+)/) { + $avx = ($1>=2.19) + ($1>=2.22); +} + +if (!$avx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) && + `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) { + $avx = ($1>=2.09) + ($1>=2.10); +} + +if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && + `ml64 2>&1` =~ /Version ([0-9]+)\./) { + $avx = ($1>=10) + ($1>=12); +} + +if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9]\.[0-9]+)/) { + $avx = ($2>=3.0) + ($2>3.0); +} + +$shaext=$avx; ### set to zero if compiling for 1.0.1 +$avx=1 if (!$shaext && $avx); + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +*STDOUT=*OUT; + +$func="aesni_cbc_sha256_enc"; +$TABLE="K256"; +$SZ=4; +@ROT=($A,$B,$C,$D,$E,$F,$G,$H)=("%eax","%ebx","%ecx","%edx", + "%r8d","%r9d","%r10d","%r11d"); +($T1,$a0,$a1,$a2,$a3)=("%r12d","%r13d","%r14d","%r15d","%esi"); +@Sigma0=( 2,13,22); +@Sigma1=( 6,11,25); +@sigma0=( 7,18, 3); +@sigma1=(17,19,10); +$rounds=64; + +######################################################################## +# void aesni_cbc_sha256_enc(const void *inp, +# void *out, +# size_t length, +# const AES_KEY *key, +# unsigned char *iv, +# SHA256_CTX *ctx, +# const void *in0); +($inp, $out, $len, $key, $ivp, $ctx, $in0) = +("%rdi","%rsi","%rdx","%rcx","%r8","%r9","%r10"); + +$Tbl="%rbp"; + +$_inp="16*$SZ+0*8(%rsp)"; +$_out="16*$SZ+1*8(%rsp)"; +$_end="16*$SZ+2*8(%rsp)"; +$_key="16*$SZ+3*8(%rsp)"; +$_ivp="16*$SZ+4*8(%rsp)"; +$_ctx="16*$SZ+5*8(%rsp)"; +$_in0="16*$SZ+6*8(%rsp)"; +$_rsp="`16*$SZ+7*8`(%rsp)"; +$framesz=16*$SZ+8*8; + +$code=<<___; +.text + +.extern OPENSSL_ia32cap_P +.globl $func +.type $func,\@abi-omnipotent +.align 16 +$func: +___ + if ($avx) { +$code.=<<___; + lea OPENSSL_ia32cap_P(%rip),%r11 + mov \$1,%eax + cmp \$0,`$win64?"%rcx":"%rdi"` + je .Lprobe + mov 0(%r11),%eax + mov 4(%r11),%r10 +___ +$code.=<<___ if ($shaext); + bt \$61,%r10 # check for SHA + jc ${func}_shaext +___ +$code.=<<___; + mov %r10,%r11 + shr \$32,%r11 + + test \$`1<<11`,%r10d # check for XOP + jnz ${func}_xop +___ +$code.=<<___ if ($avx>1); + and \$`1<<8|1<<5|1<<3`,%r11d # check for BMI2+AVX2+BMI1 + cmp \$`1<<8|1<<5|1<<3`,%r11d + je ${func}_avx2 +___ +$code.=<<___; + and \$`1<<28`,%r10d # check for AVX + jnz ${func}_avx + ud2 +___ + } +$code.=<<___; + xor %eax,%eax + cmp \$0,`$win64?"%rcx":"%rdi"` + je .Lprobe + ud2 +.Lprobe: + ret +.size $func,.-$func + +.align 64 +.type $TABLE,\@object +$TABLE: + .long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 + .long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 + .long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 + .long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 + .long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 + .long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 + .long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 + .long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 + .long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc + .long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc + .long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da + .long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da + .long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 + .long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 + .long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967 + .long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967 + .long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 + .long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 + .long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 + .long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 + .long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 + .long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 + .long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 + .long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 + .long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 + .long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 + .long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 + .long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 + .long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 + .long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 + .long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 + .long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 + + .long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f + .long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f + .long 0,0,0,0, 0,0,0,0, -1,-1,-1,-1 + .long 0,0,0,0, 0,0,0,0 + .asciz "AESNI-CBC+SHA256 stitch for x86_64, CRYPTOGAMS by " +.align 64 +___ + +###################################################################### +# SIMD code paths +# +{{{ +($iv,$inout,$roundkey,$temp, + $mask10,$mask12,$mask14,$offload)=map("%xmm$_",(8..15)); + +$aesni_cbc_idx=0; +@aesni_cbc_block = ( +## &vmovdqu ($roundkey,"0x00-0x80($inp)");' +## &vmovdqu ($inout,($inp)); +## &mov ($_inp,$inp); + + '&vpxor ($inout,$inout,$roundkey);'. + ' &vmovdqu ($roundkey,"0x10-0x80($inp)");', + + '&vpxor ($inout,$inout,$iv);', + + '&vaesenc ($inout,$inout,$roundkey);'. + ' &vmovdqu ($roundkey,"0x20-0x80($inp)");', + + '&vaesenc ($inout,$inout,$roundkey);'. + ' &vmovdqu ($roundkey,"0x30-0x80($inp)");', + + '&vaesenc ($inout,$inout,$roundkey);'. + ' &vmovdqu ($roundkey,"0x40-0x80($inp)");', + + '&vaesenc ($inout,$inout,$roundkey);'. + ' &vmovdqu ($roundkey,"0x50-0x80($inp)");', + + '&vaesenc ($inout,$inout,$roundkey);'. + ' &vmovdqu ($roundkey,"0x60-0x80($inp)");', + + '&vaesenc ($inout,$inout,$roundkey);'. + ' &vmovdqu ($roundkey,"0x70-0x80($inp)");', + + '&vaesenc ($inout,$inout,$roundkey);'. + ' &vmovdqu ($roundkey,"0x80-0x80($inp)");', + + '&vaesenc ($inout,$inout,$roundkey);'. + ' &vmovdqu ($roundkey,"0x90-0x80($inp)");', + + '&vaesenc ($inout,$inout,$roundkey);'. + ' &vmovdqu ($roundkey,"0xa0-0x80($inp)");', + + '&vaesenclast ($temp,$inout,$roundkey);'. + ' &vaesenc ($inout,$inout,$roundkey);'. + ' &vmovdqu ($roundkey,"0xb0-0x80($inp)");', + + '&vpand ($iv,$temp,$mask10);'. + ' &vaesenc ($inout,$inout,$roundkey);'. + ' &vmovdqu ($roundkey,"0xc0-0x80($inp)");', + + '&vaesenclast ($temp,$inout,$roundkey);'. + ' &vaesenc ($inout,$inout,$roundkey);'. + ' &vmovdqu ($roundkey,"0xd0-0x80($inp)");', + + '&vpand ($temp,$temp,$mask12);'. + ' &vaesenc ($inout,$inout,$roundkey);'. + '&vmovdqu ($roundkey,"0xe0-0x80($inp)");', + + '&vpor ($iv,$iv,$temp);'. + ' &vaesenclast ($temp,$inout,$roundkey);'. + ' &vmovdqu ($roundkey,"0x00-0x80($inp)");' + +## &mov ($inp,$_inp); +## &mov ($out,$_out); +## &vpand ($temp,$temp,$mask14); +## &vpor ($iv,$iv,$temp); +## &vmovdqu ($iv,($out,$inp); +## &lea (inp,16($inp)); +); + +my $a4=$T1; +my ($a,$b,$c,$d,$e,$f,$g,$h); + +sub AUTOLOAD() # thunk [simplified] 32-bit style perlasm +{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; + my $arg = pop; + $arg = "\$$arg" if ($arg*1 eq $arg); + $code .= "\t$opcode\t".join(',',$arg,reverse @_)."\n"; +} + +sub body_00_15 () { + ( + '($a,$b,$c,$d,$e,$f,$g,$h)=@ROT;'. + + '&ror ($a0,$Sigma1[2]-$Sigma1[1])', + '&mov ($a,$a1)', + '&mov ($a4,$f)', + + '&xor ($a0,$e)', + '&ror ($a1,$Sigma0[2]-$Sigma0[1])', + '&xor ($a4,$g)', # f^g + + '&ror ($a0,$Sigma1[1]-$Sigma1[0])', + '&xor ($a1,$a)', + '&and ($a4,$e)', # (f^g)&e + + @aesni_cbc_block[$aesni_cbc_idx++]. + '&xor ($a0,$e)', + '&add ($h,$SZ*($i&15)."(%rsp)")', # h+=X[i]+K[i] + '&mov ($a2,$a)', + + '&ror ($a1,$Sigma0[1]-$Sigma0[0])', + '&xor ($a4,$g)', # Ch(e,f,g)=((f^g)&e)^g + '&xor ($a2,$b)', # a^b, b^c in next round + + '&ror ($a0,$Sigma1[0])', # Sigma1(e) + '&add ($h,$a4)', # h+=Ch(e,f,g) + '&and ($a3,$a2)', # (b^c)&(a^b) + + '&xor ($a1,$a)', + '&add ($h,$a0)', # h+=Sigma1(e) + '&xor ($a3,$b)', # Maj(a,b,c)=Ch(a^b,c,b) + + '&add ($d,$h)', # d+=h + '&ror ($a1,$Sigma0[0])', # Sigma0(a) + '&add ($h,$a3)', # h+=Maj(a,b,c) + + '&mov ($a0,$d)', + '&add ($a1,$h);'. # h+=Sigma0(a) + '($a2,$a3) = ($a3,$a2); unshift(@ROT,pop(@ROT)); $i++;' + ); +} + +if ($avx) {{ +###################################################################### +# XOP code path +# +$code.=<<___; +.type ${func}_xop,\@function,6 +.align 64 +${func}_xop: +.cfi_startproc +.Lxop_shortcut: + mov `($win64?56:8)`(%rsp),$in0 # load 7th parameter + mov %rsp,%rax # copy %rsp +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + sub \$`$framesz+$win64*16*10`,%rsp + and \$-64,%rsp # align stack frame + + shl \$6,$len + sub $inp,$out # re-bias + sub $inp,$in0 + add $inp,$len # end of input + + #mov $inp,$_inp # saved later + mov $out,$_out + mov $len,$_end + #mov $key,$_key # remains resident in $inp register + mov $ivp,$_ivp + mov $ctx,$_ctx + mov $in0,$_in0 + mov %rax,$_rsp +.cfi_cfa_expression $_rsp,deref,+8 +___ +$code.=<<___ if ($win64); + movaps %xmm6,`$framesz+16*0`(%rsp) + movaps %xmm7,`$framesz+16*1`(%rsp) + movaps %xmm8,`$framesz+16*2`(%rsp) + movaps %xmm9,`$framesz+16*3`(%rsp) + movaps %xmm10,`$framesz+16*4`(%rsp) + movaps %xmm11,`$framesz+16*5`(%rsp) + movaps %xmm12,`$framesz+16*6`(%rsp) + movaps %xmm13,`$framesz+16*7`(%rsp) + movaps %xmm14,`$framesz+16*8`(%rsp) + movaps %xmm15,`$framesz+16*9`(%rsp) +___ +$code.=<<___; +.Lprologue_xop: + vzeroall + + mov $inp,%r12 # borrow $a4 + lea 0x80($key),$inp # size optimization, reassign + lea $TABLE+`$SZ*2*$rounds+32`(%rip),%r13 # borrow $a0 + mov 0xf0-0x80($inp),%r14d # rounds, borrow $a1 + mov $ctx,%r15 # borrow $a2 + mov $in0,%rsi # borrow $a3 + vmovdqu ($ivp),$iv # load IV + sub \$9,%r14 + + mov $SZ*0(%r15),$A + mov $SZ*1(%r15),$B + mov $SZ*2(%r15),$C + mov $SZ*3(%r15),$D + mov $SZ*4(%r15),$E + mov $SZ*5(%r15),$F + mov $SZ*6(%r15),$G + mov $SZ*7(%r15),$H + + vmovdqa 0x00(%r13,%r14,8),$mask14 + vmovdqa 0x10(%r13,%r14,8),$mask12 + vmovdqa 0x20(%r13,%r14,8),$mask10 + vmovdqu 0x00-0x80($inp),$roundkey + jmp .Lloop_xop +___ + if ($SZ==4) { # SHA256 + my @X = map("%xmm$_",(0..3)); + my ($t0,$t1,$t2,$t3) = map("%xmm$_",(4..7)); + +$code.=<<___; +.align 16 +.Lloop_xop: + vmovdqa $TABLE+`$SZ*2*$rounds`(%rip),$t3 + vmovdqu 0x00(%rsi,%r12),@X[0] + vmovdqu 0x10(%rsi,%r12),@X[1] + vmovdqu 0x20(%rsi,%r12),@X[2] + vmovdqu 0x30(%rsi,%r12),@X[3] + vpshufb $t3,@X[0],@X[0] + lea $TABLE(%rip),$Tbl + vpshufb $t3,@X[1],@X[1] + vpshufb $t3,@X[2],@X[2] + vpaddd 0x00($Tbl),@X[0],$t0 + vpshufb $t3,@X[3],@X[3] + vpaddd 0x20($Tbl),@X[1],$t1 + vpaddd 0x40($Tbl),@X[2],$t2 + vpaddd 0x60($Tbl),@X[3],$t3 + vmovdqa $t0,0x00(%rsp) + mov $A,$a1 + vmovdqa $t1,0x10(%rsp) + mov $B,$a3 + vmovdqa $t2,0x20(%rsp) + xor $C,$a3 # magic + vmovdqa $t3,0x30(%rsp) + mov $E,$a0 + jmp .Lxop_00_47 + +.align 16 +.Lxop_00_47: + sub \$-16*2*$SZ,$Tbl # size optimization + vmovdqu (%r12),$inout # $a4 + mov %r12,$_inp # $a4 +___ +sub XOP_256_00_47 () { +my $j = shift; +my $body = shift; +my @X = @_; +my @insns = (&$body,&$body,&$body,&$body); # 104 instructions + + &vpalignr ($t0,@X[1],@X[0],$SZ); # X[1..4] + eval(shift(@insns)); + eval(shift(@insns)); + &vpalignr ($t3,@X[3],@X[2],$SZ); # X[9..12] + eval(shift(@insns)); + eval(shift(@insns)); + &vprotd ($t1,$t0,8*$SZ-$sigma0[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpsrld ($t0,$t0,$sigma0[2]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpaddd (@X[0],@X[0],$t3); # X[0..3] += X[9..12] + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vprotd ($t2,$t1,$sigma0[1]-$sigma0[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor ($t0,$t0,$t1); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vprotd ($t3,@X[3],8*$SZ-$sigma1[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor ($t0,$t0,$t2); # sigma0(X[1..4]) + eval(shift(@insns)); + eval(shift(@insns)); + &vpsrld ($t2,@X[3],$sigma1[2]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpaddd (@X[0],@X[0],$t0); # X[0..3] += sigma0(X[1..4]) + eval(shift(@insns)); + eval(shift(@insns)); + &vprotd ($t1,$t3,$sigma1[1]-$sigma1[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor ($t3,$t3,$t2); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor ($t3,$t3,$t1); # sigma1(X[14..15]) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vpsrldq ($t3,$t3,8); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vpaddd (@X[0],@X[0],$t3); # X[0..1] += sigma1(X[14..15]) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vprotd ($t3,@X[0],8*$SZ-$sigma1[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpsrld ($t2,@X[0],$sigma1[2]); + eval(shift(@insns)); + eval(shift(@insns)); + &vprotd ($t1,$t3,$sigma1[1]-$sigma1[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor ($t3,$t3,$t2); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor ($t3,$t3,$t1); # sigma1(X[16..17]) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vpslldq ($t3,$t3,8); # 22 instructions + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vpaddd (@X[0],@X[0],$t3); # X[2..3] += sigma1(X[16..17]) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vpaddd ($t2,@X[0],16*2*$j."($Tbl)"); + foreach (@insns) { eval; } # remaining instructions + &vmovdqa (16*$j."(%rsp)",$t2); +} + + $aesni_cbc_idx=0; + for ($i=0,$j=0; $j<4; $j++) { + &XOP_256_00_47($j,\&body_00_15,@X); + push(@X,shift(@X)); # rotate(@X) + } + &mov ("%r12",$_inp); # borrow $a4 + &vpand ($temp,$temp,$mask14); + &mov ("%r15",$_out); # borrow $a2 + &vpor ($iv,$iv,$temp); + &vmovdqu ("(%r15,%r12)",$iv); # write output + &lea ("%r12","16(%r12)"); # inp++ + + &cmpb ($SZ-1+16*2*$SZ."($Tbl)",0); + &jne (".Lxop_00_47"); + + &vmovdqu ($inout,"(%r12)"); + &mov ($_inp,"%r12"); + + $aesni_cbc_idx=0; + for ($i=0; $i<16; ) { + foreach(body_00_15()) { eval; } + } + } +$code.=<<___; + mov $_inp,%r12 # borrow $a4 + mov $_out,%r13 # borrow $a0 + mov $_ctx,%r15 # borrow $a2 + mov $_in0,%rsi # borrow $a3 + + vpand $mask14,$temp,$temp + mov $a1,$A + vpor $temp,$iv,$iv + vmovdqu $iv,(%r13,%r12) # write output + lea 16(%r12),%r12 # inp++ + + add $SZ*0(%r15),$A + add $SZ*1(%r15),$B + add $SZ*2(%r15),$C + add $SZ*3(%r15),$D + add $SZ*4(%r15),$E + add $SZ*5(%r15),$F + add $SZ*6(%r15),$G + add $SZ*7(%r15),$H + + cmp $_end,%r12 + + mov $A,$SZ*0(%r15) + mov $B,$SZ*1(%r15) + mov $C,$SZ*2(%r15) + mov $D,$SZ*3(%r15) + mov $E,$SZ*4(%r15) + mov $F,$SZ*5(%r15) + mov $G,$SZ*6(%r15) + mov $H,$SZ*7(%r15) + + jb .Lloop_xop + + mov $_ivp,$ivp + mov $_rsp,%rsi +.cfi_def_cfa %rsi,8 + vmovdqu $iv,($ivp) # output IV + vzeroall +___ +$code.=<<___ if ($win64); + movaps `$framesz+16*0`(%rsp),%xmm6 + movaps `$framesz+16*1`(%rsp),%xmm7 + movaps `$framesz+16*2`(%rsp),%xmm8 + movaps `$framesz+16*3`(%rsp),%xmm9 + movaps `$framesz+16*4`(%rsp),%xmm10 + movaps `$framesz+16*5`(%rsp),%xmm11 + movaps `$framesz+16*6`(%rsp),%xmm12 + movaps `$framesz+16*7`(%rsp),%xmm13 + movaps `$framesz+16*8`(%rsp),%xmm14 + movaps `$framesz+16*9`(%rsp),%xmm15 +___ +$code.=<<___; + mov -48(%rsi),%r15 +.cfi_restore %r15 + mov -40(%rsi),%r14 +.cfi_restore %r14 + mov -32(%rsi),%r13 +.cfi_restore %r13 + mov -24(%rsi),%r12 +.cfi_restore %r12 + mov -16(%rsi),%rbp +.cfi_restore %rbp + mov -8(%rsi),%rbx +.cfi_restore %rbx + lea (%rsi),%rsp +.cfi_def_cfa_register %rsp +.Lepilogue_xop: + ret +.cfi_endproc +.size ${func}_xop,.-${func}_xop +___ +###################################################################### +# AVX+shrd code path +# +local *ror = sub { &shrd(@_[0],@_) }; + +$code.=<<___; +.type ${func}_avx,\@function,6 +.align 64 +${func}_avx: +.cfi_startproc +.Lavx_shortcut: + mov `($win64?56:8)`(%rsp),$in0 # load 7th parameter + mov %rsp,%rax # copy %rsp +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + sub \$`$framesz+$win64*16*10`,%rsp + and \$-64,%rsp # align stack frame + + shl \$6,$len + sub $inp,$out # re-bias + sub $inp,$in0 + add $inp,$len # end of input + + #mov $inp,$_inp # saved later + mov $out,$_out + mov $len,$_end + #mov $key,$_key # remains resident in $inp register + mov $ivp,$_ivp + mov $ctx,$_ctx + mov $in0,$_in0 + mov %rax,$_rsp +.cfi_cfa_expression $_rsp,deref,+8 +___ +$code.=<<___ if ($win64); + movaps %xmm6,`$framesz+16*0`(%rsp) + movaps %xmm7,`$framesz+16*1`(%rsp) + movaps %xmm8,`$framesz+16*2`(%rsp) + movaps %xmm9,`$framesz+16*3`(%rsp) + movaps %xmm10,`$framesz+16*4`(%rsp) + movaps %xmm11,`$framesz+16*5`(%rsp) + movaps %xmm12,`$framesz+16*6`(%rsp) + movaps %xmm13,`$framesz+16*7`(%rsp) + movaps %xmm14,`$framesz+16*8`(%rsp) + movaps %xmm15,`$framesz+16*9`(%rsp) +___ +$code.=<<___; +.Lprologue_avx: + vzeroall + + mov $inp,%r12 # borrow $a4 + lea 0x80($key),$inp # size optimization, reassign + lea $TABLE+`$SZ*2*$rounds+32`(%rip),%r13 # borrow $a0 + mov 0xf0-0x80($inp),%r14d # rounds, borrow $a1 + mov $ctx,%r15 # borrow $a2 + mov $in0,%rsi # borrow $a3 + vmovdqu ($ivp),$iv # load IV + sub \$9,%r14 + + mov $SZ*0(%r15),$A + mov $SZ*1(%r15),$B + mov $SZ*2(%r15),$C + mov $SZ*3(%r15),$D + mov $SZ*4(%r15),$E + mov $SZ*5(%r15),$F + mov $SZ*6(%r15),$G + mov $SZ*7(%r15),$H + + vmovdqa 0x00(%r13,%r14,8),$mask14 + vmovdqa 0x10(%r13,%r14,8),$mask12 + vmovdqa 0x20(%r13,%r14,8),$mask10 + vmovdqu 0x00-0x80($inp),$roundkey +___ + if ($SZ==4) { # SHA256 + my @X = map("%xmm$_",(0..3)); + my ($t0,$t1,$t2,$t3) = map("%xmm$_",(4..7)); + +$code.=<<___; + jmp .Lloop_avx +.align 16 +.Lloop_avx: + vmovdqa $TABLE+`$SZ*2*$rounds`(%rip),$t3 + vmovdqu 0x00(%rsi,%r12),@X[0] + vmovdqu 0x10(%rsi,%r12),@X[1] + vmovdqu 0x20(%rsi,%r12),@X[2] + vmovdqu 0x30(%rsi,%r12),@X[3] + vpshufb $t3,@X[0],@X[0] + lea $TABLE(%rip),$Tbl + vpshufb $t3,@X[1],@X[1] + vpshufb $t3,@X[2],@X[2] + vpaddd 0x00($Tbl),@X[0],$t0 + vpshufb $t3,@X[3],@X[3] + vpaddd 0x20($Tbl),@X[1],$t1 + vpaddd 0x40($Tbl),@X[2],$t2 + vpaddd 0x60($Tbl),@X[3],$t3 + vmovdqa $t0,0x00(%rsp) + mov $A,$a1 + vmovdqa $t1,0x10(%rsp) + mov $B,$a3 + vmovdqa $t2,0x20(%rsp) + xor $C,$a3 # magic + vmovdqa $t3,0x30(%rsp) + mov $E,$a0 + jmp .Lavx_00_47 + +.align 16 +.Lavx_00_47: + sub \$-16*2*$SZ,$Tbl # size optimization + vmovdqu (%r12),$inout # $a4 + mov %r12,$_inp # $a4 +___ +sub Xupdate_256_AVX () { + ( + '&vpalignr ($t0,@X[1],@X[0],$SZ)', # X[1..4] + '&vpalignr ($t3,@X[3],@X[2],$SZ)', # X[9..12] + '&vpsrld ($t2,$t0,$sigma0[0]);', + '&vpaddd (@X[0],@X[0],$t3)', # X[0..3] += X[9..12] + '&vpsrld ($t3,$t0,$sigma0[2])', + '&vpslld ($t1,$t0,8*$SZ-$sigma0[1]);', + '&vpxor ($t0,$t3,$t2)', + '&vpshufd ($t3,@X[3],0b11111010)',# X[14..15] + '&vpsrld ($t2,$t2,$sigma0[1]-$sigma0[0]);', + '&vpxor ($t0,$t0,$t1)', + '&vpslld ($t1,$t1,$sigma0[1]-$sigma0[0]);', + '&vpxor ($t0,$t0,$t2)', + '&vpsrld ($t2,$t3,$sigma1[2]);', + '&vpxor ($t0,$t0,$t1)', # sigma0(X[1..4]) + '&vpsrlq ($t3,$t3,$sigma1[0]);', + '&vpaddd (@X[0],@X[0],$t0)', # X[0..3] += sigma0(X[1..4]) + '&vpxor ($t2,$t2,$t3);', + '&vpsrlq ($t3,$t3,$sigma1[1]-$sigma1[0])', + '&vpxor ($t2,$t2,$t3)', # sigma1(X[14..15]) + '&vpshufd ($t2,$t2,0b10000100)', + '&vpsrldq ($t2,$t2,8)', + '&vpaddd (@X[0],@X[0],$t2)', # X[0..1] += sigma1(X[14..15]) + '&vpshufd ($t3,@X[0],0b01010000)',# X[16..17] + '&vpsrld ($t2,$t3,$sigma1[2])', + '&vpsrlq ($t3,$t3,$sigma1[0])', + '&vpxor ($t2,$t2,$t3);', + '&vpsrlq ($t3,$t3,$sigma1[1]-$sigma1[0])', + '&vpxor ($t2,$t2,$t3)', + '&vpshufd ($t2,$t2,0b11101000)', + '&vpslldq ($t2,$t2,8)', + '&vpaddd (@X[0],@X[0],$t2)' # X[2..3] += sigma1(X[16..17]) + ); +} + +sub AVX_256_00_47 () { +my $j = shift; +my $body = shift; +my @X = @_; +my @insns = (&$body,&$body,&$body,&$body); # 104 instructions + + foreach (Xupdate_256_AVX()) { # 29 instructions + eval; + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + } + &vpaddd ($t2,@X[0],16*2*$j."($Tbl)"); + foreach (@insns) { eval; } # remaining instructions + &vmovdqa (16*$j."(%rsp)",$t2); +} + + $aesni_cbc_idx=0; + for ($i=0,$j=0; $j<4; $j++) { + &AVX_256_00_47($j,\&body_00_15,@X); + push(@X,shift(@X)); # rotate(@X) + } + &mov ("%r12",$_inp); # borrow $a4 + &vpand ($temp,$temp,$mask14); + &mov ("%r15",$_out); # borrow $a2 + &vpor ($iv,$iv,$temp); + &vmovdqu ("(%r15,%r12)",$iv); # write output + &lea ("%r12","16(%r12)"); # inp++ + + &cmpb ($SZ-1+16*2*$SZ."($Tbl)",0); + &jne (".Lavx_00_47"); + + &vmovdqu ($inout,"(%r12)"); + &mov ($_inp,"%r12"); + + $aesni_cbc_idx=0; + for ($i=0; $i<16; ) { + foreach(body_00_15()) { eval; } + } + + } +$code.=<<___; + mov $_inp,%r12 # borrow $a4 + mov $_out,%r13 # borrow $a0 + mov $_ctx,%r15 # borrow $a2 + mov $_in0,%rsi # borrow $a3 + + vpand $mask14,$temp,$temp + mov $a1,$A + vpor $temp,$iv,$iv + vmovdqu $iv,(%r13,%r12) # write output + lea 16(%r12),%r12 # inp++ + + add $SZ*0(%r15),$A + add $SZ*1(%r15),$B + add $SZ*2(%r15),$C + add $SZ*3(%r15),$D + add $SZ*4(%r15),$E + add $SZ*5(%r15),$F + add $SZ*6(%r15),$G + add $SZ*7(%r15),$H + + cmp $_end,%r12 + + mov $A,$SZ*0(%r15) + mov $B,$SZ*1(%r15) + mov $C,$SZ*2(%r15) + mov $D,$SZ*3(%r15) + mov $E,$SZ*4(%r15) + mov $F,$SZ*5(%r15) + mov $G,$SZ*6(%r15) + mov $H,$SZ*7(%r15) + jb .Lloop_avx + + mov $_ivp,$ivp + mov $_rsp,%rsi +.cfi_def_cfa %rsi,8 + vmovdqu $iv,($ivp) # output IV + vzeroall +___ +$code.=<<___ if ($win64); + movaps `$framesz+16*0`(%rsp),%xmm6 + movaps `$framesz+16*1`(%rsp),%xmm7 + movaps `$framesz+16*2`(%rsp),%xmm8 + movaps `$framesz+16*3`(%rsp),%xmm9 + movaps `$framesz+16*4`(%rsp),%xmm10 + movaps `$framesz+16*5`(%rsp),%xmm11 + movaps `$framesz+16*6`(%rsp),%xmm12 + movaps `$framesz+16*7`(%rsp),%xmm13 + movaps `$framesz+16*8`(%rsp),%xmm14 + movaps `$framesz+16*9`(%rsp),%xmm15 +___ +$code.=<<___; + mov -48(%rsi),%r15 +.cfi_restore %r15 + mov -40(%rsi),%r14 +.cfi_restore %r14 + mov -32(%rsi),%r13 +.cfi_restore %r13 + mov -24(%rsi),%r12 +.cfi_restore %r12 + mov -16(%rsi),%rbp +.cfi_restore %rbp + mov -8(%rsi),%rbx +.cfi_restore %rbx + lea (%rsi),%rsp +.cfi_def_cfa_register %rsp +.Lepilogue_avx: + ret +.cfi_endproc +.size ${func}_avx,.-${func}_avx +___ + +if ($avx>1) {{ +###################################################################### +# AVX2+BMI code path +# +my $a5=$SZ==4?"%esi":"%rsi"; # zap $inp +my $PUSH8=8*2*$SZ; +use integer; + +sub bodyx_00_15 () { + # at start $a1 should be zero, $a3 - $b^$c and $a4 copy of $f + ( + '($a,$b,$c,$d,$e,$f,$g,$h)=@ROT;'. + + '&add ($h,(32*($i/(16/$SZ))+$SZ*($i%(16/$SZ)))%$PUSH8.$base)', # h+=X[i]+K[i] + '&and ($a4,$e)', # f&e + '&rorx ($a0,$e,$Sigma1[2])', + '&rorx ($a2,$e,$Sigma1[1])', + + '&lea ($a,"($a,$a1)")', # h+=Sigma0(a) from the past + '&lea ($h,"($h,$a4)")', + '&andn ($a4,$e,$g)', # ~e&g + '&xor ($a0,$a2)', + + '&rorx ($a1,$e,$Sigma1[0])', + '&lea ($h,"($h,$a4)")', # h+=Ch(e,f,g)=(e&f)+(~e&g) + '&xor ($a0,$a1)', # Sigma1(e) + '&mov ($a2,$a)', + + '&rorx ($a4,$a,$Sigma0[2])', + '&lea ($h,"($h,$a0)")', # h+=Sigma1(e) + '&xor ($a2,$b)', # a^b, b^c in next round + '&rorx ($a1,$a,$Sigma0[1])', + + '&rorx ($a0,$a,$Sigma0[0])', + '&lea ($d,"($d,$h)")', # d+=h + '&and ($a3,$a2)', # (b^c)&(a^b) + @aesni_cbc_block[$aesni_cbc_idx++]. + '&xor ($a1,$a4)', + + '&xor ($a3,$b)', # Maj(a,b,c)=Ch(a^b,c,b) + '&xor ($a1,$a0)', # Sigma0(a) + '&lea ($h,"($h,$a3)");'. # h+=Maj(a,b,c) + '&mov ($a4,$e)', # copy of f in future + + '($a2,$a3) = ($a3,$a2); unshift(@ROT,pop(@ROT)); $i++;' + ); + # and at the finish one has to $a+=$a1 +} + +$code.=<<___; +.type ${func}_avx2,\@function,6 +.align 64 +${func}_avx2: +.cfi_startproc +.Lavx2_shortcut: + mov `($win64?56:8)`(%rsp),$in0 # load 7th parameter + mov %rsp,%rax # copy %rsp +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + sub \$`2*$SZ*$rounds+8*8+$win64*16*10`,%rsp + and \$-256*$SZ,%rsp # align stack frame + add \$`2*$SZ*($rounds-8)`,%rsp + + shl \$6,$len + sub $inp,$out # re-bias + sub $inp,$in0 + add $inp,$len # end of input + + #mov $inp,$_inp # saved later + #mov $out,$_out # kept in $offload + mov $len,$_end + #mov $key,$_key # remains resident in $inp register + mov $ivp,$_ivp + mov $ctx,$_ctx + mov $in0,$_in0 + mov %rax,$_rsp +.cfi_cfa_expression $_rsp,deref,+8 +___ +$code.=<<___ if ($win64); + movaps %xmm6,`$framesz+16*0`(%rsp) + movaps %xmm7,`$framesz+16*1`(%rsp) + movaps %xmm8,`$framesz+16*2`(%rsp) + movaps %xmm9,`$framesz+16*3`(%rsp) + movaps %xmm10,`$framesz+16*4`(%rsp) + movaps %xmm11,`$framesz+16*5`(%rsp) + movaps %xmm12,`$framesz+16*6`(%rsp) + movaps %xmm13,`$framesz+16*7`(%rsp) + movaps %xmm14,`$framesz+16*8`(%rsp) + movaps %xmm15,`$framesz+16*9`(%rsp) +___ +$code.=<<___; +.Lprologue_avx2: + vzeroall + + mov $inp,%r13 # borrow $a0 + vpinsrq \$1,$out,$offload,$offload + lea 0x80($key),$inp # size optimization, reassign + lea $TABLE+`$SZ*2*$rounds+32`(%rip),%r12 # borrow $a4 + mov 0xf0-0x80($inp),%r14d # rounds, borrow $a1 + mov $ctx,%r15 # borrow $a2 + mov $in0,%rsi # borrow $a3 + vmovdqu ($ivp),$iv # load IV + lea -9(%r14),%r14 + + vmovdqa 0x00(%r12,%r14,8),$mask14 + vmovdqa 0x10(%r12,%r14,8),$mask12 + vmovdqa 0x20(%r12,%r14,8),$mask10 + + sub \$-16*$SZ,%r13 # inp++, size optimization + mov $SZ*0(%r15),$A + lea (%rsi,%r13),%r12 # borrow $a0 + mov $SZ*1(%r15),$B + cmp $len,%r13 # $_end + mov $SZ*2(%r15),$C + cmove %rsp,%r12 # next block or random data + mov $SZ*3(%r15),$D + mov $SZ*4(%r15),$E + mov $SZ*5(%r15),$F + mov $SZ*6(%r15),$G + mov $SZ*7(%r15),$H + vmovdqu 0x00-0x80($inp),$roundkey +___ + if ($SZ==4) { # SHA256 + my @X = map("%ymm$_",(0..3)); + my ($t0,$t1,$t2,$t3) = map("%ymm$_",(4..7)); + +$code.=<<___; + jmp .Loop_avx2 +.align 16 +.Loop_avx2: + vmovdqa $TABLE+`$SZ*2*$rounds`(%rip),$t3 + vmovdqu -16*$SZ+0(%rsi,%r13),%xmm0 + vmovdqu -16*$SZ+16(%rsi,%r13),%xmm1 + vmovdqu -16*$SZ+32(%rsi,%r13),%xmm2 + vmovdqu -16*$SZ+48(%rsi,%r13),%xmm3 + + vinserti128 \$1,(%r12),@X[0],@X[0] + vinserti128 \$1,16(%r12),@X[1],@X[1] + vpshufb $t3,@X[0],@X[0] + vinserti128 \$1,32(%r12),@X[2],@X[2] + vpshufb $t3,@X[1],@X[1] + vinserti128 \$1,48(%r12),@X[3],@X[3] + + lea $TABLE(%rip),$Tbl + vpshufb $t3,@X[2],@X[2] + lea -16*$SZ(%r13),%r13 + vpaddd 0x00($Tbl),@X[0],$t0 + vpshufb $t3,@X[3],@X[3] + vpaddd 0x20($Tbl),@X[1],$t1 + vpaddd 0x40($Tbl),@X[2],$t2 + vpaddd 0x60($Tbl),@X[3],$t3 + vmovdqa $t0,0x00(%rsp) + xor $a1,$a1 + vmovdqa $t1,0x20(%rsp) + lea -$PUSH8(%rsp),%rsp + mov $B,$a3 + vmovdqa $t2,0x00(%rsp) + xor $C,$a3 # magic + vmovdqa $t3,0x20(%rsp) + mov $F,$a4 + sub \$-16*2*$SZ,$Tbl # size optimization + jmp .Lavx2_00_47 + +.align 16 +.Lavx2_00_47: + vmovdqu (%r13),$inout + vpinsrq \$0,%r13,$offload,$offload +___ + +sub AVX2_256_00_47 () { +my $j = shift; +my $body = shift; +my @X = @_; +my @insns = (&$body,&$body,&$body,&$body); # 96 instructions +my $base = "+2*$PUSH8(%rsp)"; + + &lea ("%rsp","-$PUSH8(%rsp)") if (($j%2)==0); + foreach (Xupdate_256_AVX()) { # 29 instructions + eval; + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + } + &vpaddd ($t2,@X[0],16*2*$j."($Tbl)"); + foreach (@insns) { eval; } # remaining instructions + &vmovdqa ((32*$j)%$PUSH8."(%rsp)",$t2); +} + $aesni_cbc_idx=0; + for ($i=0,$j=0; $j<4; $j++) { + &AVX2_256_00_47($j,\&bodyx_00_15,@X); + push(@X,shift(@X)); # rotate(@X) + } + &vmovq ("%r13",$offload); # borrow $a0 + &vpextrq ("%r15",$offload,1); # borrow $a2 + &vpand ($temp,$temp,$mask14); + &vpor ($iv,$iv,$temp); + &vmovdqu ("(%r15,%r13)",$iv); # write output + &lea ("%r13","16(%r13)"); # inp++ + + &lea ($Tbl,16*2*$SZ."($Tbl)"); + &cmpb (($SZ-1)."($Tbl)",0); + &jne (".Lavx2_00_47"); + + &vmovdqu ($inout,"(%r13)"); + &vpinsrq ($offload,$offload,"%r13",0); + + $aesni_cbc_idx=0; + for ($i=0; $i<16; ) { + my $base=$i<8?"+$PUSH8(%rsp)":"(%rsp)"; + foreach(bodyx_00_15()) { eval; } + } + } +$code.=<<___; + vpextrq \$1,$offload,%r12 # $_out, borrow $a4 + vmovq $offload,%r13 # $_inp, borrow $a0 + mov `2*$SZ*$rounds+5*8`(%rsp),%r15 # $_ctx, borrow $a2 + add $a1,$A + lea `2*$SZ*($rounds-8)`(%rsp),$Tbl + + vpand $mask14,$temp,$temp + vpor $temp,$iv,$iv + vmovdqu $iv,(%r12,%r13) # write output + lea 16(%r13),%r13 + + add $SZ*0(%r15),$A + add $SZ*1(%r15),$B + add $SZ*2(%r15),$C + add $SZ*3(%r15),$D + add $SZ*4(%r15),$E + add $SZ*5(%r15),$F + add $SZ*6(%r15),$G + add $SZ*7(%r15),$H + + mov $A,$SZ*0(%r15) + mov $B,$SZ*1(%r15) + mov $C,$SZ*2(%r15) + mov $D,$SZ*3(%r15) + mov $E,$SZ*4(%r15) + mov $F,$SZ*5(%r15) + mov $G,$SZ*6(%r15) + mov $H,$SZ*7(%r15) + + cmp `$PUSH8+2*8`($Tbl),%r13 # $_end + je .Ldone_avx2 + + xor $a1,$a1 + mov $B,$a3 + mov $F,$a4 + xor $C,$a3 # magic + jmp .Lower_avx2 +.align 16 +.Lower_avx2: + vmovdqu (%r13),$inout + vpinsrq \$0,%r13,$offload,$offload +___ + $aesni_cbc_idx=0; + for ($i=0; $i<16; ) { + my $base="+16($Tbl)"; + foreach(bodyx_00_15()) { eval; } + &lea ($Tbl,"-$PUSH8($Tbl)") if ($i==8); + } +$code.=<<___; + vmovq $offload,%r13 # borrow $a0 + vpextrq \$1,$offload,%r15 # borrow $a2 + vpand $mask14,$temp,$temp + vpor $temp,$iv,$iv + lea -$PUSH8($Tbl),$Tbl + vmovdqu $iv,(%r15,%r13) # write output + lea 16(%r13),%r13 # inp++ + cmp %rsp,$Tbl + jae .Lower_avx2 + + mov `2*$SZ*$rounds+5*8`(%rsp),%r15 # $_ctx, borrow $a2 + lea 16*$SZ(%r13),%r13 + mov `2*$SZ*$rounds+6*8`(%rsp),%rsi # $_in0, borrow $a3 + add $a1,$A + lea `2*$SZ*($rounds-8)`(%rsp),%rsp + + add $SZ*0(%r15),$A + add $SZ*1(%r15),$B + add $SZ*2(%r15),$C + add $SZ*3(%r15),$D + add $SZ*4(%r15),$E + add $SZ*5(%r15),$F + add $SZ*6(%r15),$G + lea (%rsi,%r13),%r12 + add $SZ*7(%r15),$H + + cmp $_end,%r13 + + mov $A,$SZ*0(%r15) + cmove %rsp,%r12 # next block or stale data + mov $B,$SZ*1(%r15) + mov $C,$SZ*2(%r15) + mov $D,$SZ*3(%r15) + mov $E,$SZ*4(%r15) + mov $F,$SZ*5(%r15) + mov $G,$SZ*6(%r15) + mov $H,$SZ*7(%r15) + + jbe .Loop_avx2 + lea (%rsp),$Tbl + +.Ldone_avx2: + lea ($Tbl),%rsp + mov $_ivp,$ivp + mov $_rsp,%rsi +.cfi_def_cfa %rsi,8 + vmovdqu $iv,($ivp) # output IV + vzeroall +___ +$code.=<<___ if ($win64); + movaps `$framesz+16*0`(%rsp),%xmm6 + movaps `$framesz+16*1`(%rsp),%xmm7 + movaps `$framesz+16*2`(%rsp),%xmm8 + movaps `$framesz+16*3`(%rsp),%xmm9 + movaps `$framesz+16*4`(%rsp),%xmm10 + movaps `$framesz+16*5`(%rsp),%xmm11 + movaps `$framesz+16*6`(%rsp),%xmm12 + movaps `$framesz+16*7`(%rsp),%xmm13 + movaps `$framesz+16*8`(%rsp),%xmm14 + movaps `$framesz+16*9`(%rsp),%xmm15 +___ +$code.=<<___; + mov -48(%rsi),%r15 +.cfi_restore %r15 + mov -40(%rsi),%r14 +.cfi_restore %r14 + mov -32(%rsi),%r13 +.cfi_restore %r13 + mov -24(%rsi),%r12 +.cfi_restore %r12 + mov -16(%rsi),%rbp +.cfi_restore %rbp + mov -8(%rsi),%rbx +.cfi_restore %rbx + lea (%rsi),%rsp +.cfi_def_cfa_register %rsp +.Lepilogue_avx2: + ret +.cfi_endproc +.size ${func}_avx2,.-${func}_avx2 +___ +}} +}} +{{ +my ($in0,$out,$len,$key,$ivp,$ctx,$inp)=("%rdi","%rsi","%rdx","%rcx","%r8","%r9","%r10"); + +my ($rounds,$Tbl)=("%r11d","%rbx"); + +my ($iv,$in,$rndkey0)=map("%xmm$_",(6,14,15)); +my @rndkey=("%xmm4","%xmm5"); +my $r=0; +my $sn=0; + +my ($Wi,$ABEF,$CDGH,$TMP,$BSWAP,$ABEF_SAVE,$CDGH_SAVE)=map("%xmm$_",(0..3,7..9)); +my @MSG=map("%xmm$_",(10..13)); + +my $aesenc=sub { + use integer; + my ($n,$k)=($r/10,$r%10); + if ($k==0) { + $code.=<<___; + movups `16*$n`($in0),$in # load input + xorps $rndkey0,$in +___ + $code.=<<___ if ($n); + movups $iv,`16*($n-1)`($out,$in0) # write output +___ + $code.=<<___; + xorps $in,$iv + movups `32+16*$k-112`($key),$rndkey[1] + aesenc $rndkey[0],$iv +___ + } elsif ($k==9) { + $sn++; + $code.=<<___; + cmp \$11,$rounds + jb .Laesenclast$sn + movups `32+16*($k+0)-112`($key),$rndkey[1] + aesenc $rndkey[0],$iv + movups `32+16*($k+1)-112`($key),$rndkey[0] + aesenc $rndkey[1],$iv + je .Laesenclast$sn + movups `32+16*($k+2)-112`($key),$rndkey[1] + aesenc $rndkey[0],$iv + movups `32+16*($k+3)-112`($key),$rndkey[0] + aesenc $rndkey[1],$iv +.Laesenclast$sn: + aesenclast $rndkey[0],$iv + movups 16-112($key),$rndkey[1] # forward reference + nop +___ + } else { + $code.=<<___; + movups `32+16*$k-112`($key),$rndkey[1] + aesenc $rndkey[0],$iv +___ + } + $r++; unshift(@rndkey,pop(@rndkey)); +}; + +if ($shaext) { +my $Tbl="%rax"; + +$code.=<<___; +.type ${func}_shaext,\@function,6 +.align 32 +${func}_shaext: + mov `($win64?56:8)`(%rsp),$inp # load 7th argument +___ +$code.=<<___ if ($win64); + lea `-8-10*16`(%rsp),%rsp + movaps %xmm6,-8-10*16(%rax) + movaps %xmm7,-8-9*16(%rax) + movaps %xmm8,-8-8*16(%rax) + movaps %xmm9,-8-7*16(%rax) + movaps %xmm10,-8-6*16(%rax) + movaps %xmm11,-8-5*16(%rax) + movaps %xmm12,-8-4*16(%rax) + movaps %xmm13,-8-3*16(%rax) + movaps %xmm14,-8-2*16(%rax) + movaps %xmm15,-8-1*16(%rax) +.Lprologue_shaext: +___ +$code.=<<___; + lea K256+0x80(%rip),$Tbl + movdqu ($ctx),$ABEF # DCBA + movdqu 16($ctx),$CDGH # HGFE + movdqa 0x200-0x80($Tbl),$TMP # byte swap mask + + mov 240($key),$rounds + sub $in0,$out + movups ($key),$rndkey0 # $key[0] + movups ($ivp),$iv # load IV + movups 16($key),$rndkey[0] # forward reference + lea 112($key),$key # size optimization + + pshufd \$0x1b,$ABEF,$Wi # ABCD + pshufd \$0xb1,$ABEF,$ABEF # CDAB + pshufd \$0x1b,$CDGH,$CDGH # EFGH + movdqa $TMP,$BSWAP # offload + palignr \$8,$CDGH,$ABEF # ABEF + punpcklqdq $Wi,$CDGH # CDGH + + jmp .Loop_shaext + +.align 16 +.Loop_shaext: + movdqu ($inp),@MSG[0] + movdqu 0x10($inp),@MSG[1] + movdqu 0x20($inp),@MSG[2] + pshufb $TMP,@MSG[0] + movdqu 0x30($inp),@MSG[3] + + movdqa 0*32-0x80($Tbl),$Wi + paddd @MSG[0],$Wi + pshufb $TMP,@MSG[1] + movdqa $CDGH,$CDGH_SAVE # offload + movdqa $ABEF,$ABEF_SAVE # offload +___ + &$aesenc(); +$code.=<<___; + sha256rnds2 $ABEF,$CDGH # 0-3 + pshufd \$0x0e,$Wi,$Wi +___ + &$aesenc(); +$code.=<<___; + sha256rnds2 $CDGH,$ABEF + + movdqa 1*32-0x80($Tbl),$Wi + paddd @MSG[1],$Wi + pshufb $TMP,@MSG[2] + lea 0x40($inp),$inp +___ + &$aesenc(); +$code.=<<___; + sha256rnds2 $ABEF,$CDGH # 4-7 + pshufd \$0x0e,$Wi,$Wi +___ + &$aesenc(); +$code.=<<___; + sha256rnds2 $CDGH,$ABEF + + movdqa 2*32-0x80($Tbl),$Wi + paddd @MSG[2],$Wi + pshufb $TMP,@MSG[3] + sha256msg1 @MSG[1],@MSG[0] +___ + &$aesenc(); +$code.=<<___; + sha256rnds2 $ABEF,$CDGH # 8-11 + pshufd \$0x0e,$Wi,$Wi + movdqa @MSG[3],$TMP + palignr \$4,@MSG[2],$TMP + paddd $TMP,@MSG[0] +___ + &$aesenc(); +$code.=<<___; + sha256rnds2 $CDGH,$ABEF + + movdqa 3*32-0x80($Tbl),$Wi + paddd @MSG[3],$Wi + sha256msg2 @MSG[3],@MSG[0] + sha256msg1 @MSG[2],@MSG[1] +___ + &$aesenc(); +$code.=<<___; + sha256rnds2 $ABEF,$CDGH # 12-15 + pshufd \$0x0e,$Wi,$Wi +___ + &$aesenc(); +$code.=<<___; + movdqa @MSG[0],$TMP + palignr \$4,@MSG[3],$TMP + paddd $TMP,@MSG[1] + sha256rnds2 $CDGH,$ABEF +___ +for($i=4;$i<16-3;$i++) { + &$aesenc() if (($r%10)==0); +$code.=<<___; + movdqa $i*32-0x80($Tbl),$Wi + paddd @MSG[0],$Wi + sha256msg2 @MSG[0],@MSG[1] + sha256msg1 @MSG[3],@MSG[2] +___ + &$aesenc(); +$code.=<<___; + sha256rnds2 $ABEF,$CDGH # 16-19... + pshufd \$0x0e,$Wi,$Wi + movdqa @MSG[1],$TMP + palignr \$4,@MSG[0],$TMP + paddd $TMP,@MSG[2] +___ + &$aesenc(); + &$aesenc() if ($r==19); +$code.=<<___; + sha256rnds2 $CDGH,$ABEF +___ + push(@MSG,shift(@MSG)); +} +$code.=<<___; + movdqa 13*32-0x80($Tbl),$Wi + paddd @MSG[0],$Wi + sha256msg2 @MSG[0],@MSG[1] + sha256msg1 @MSG[3],@MSG[2] +___ + &$aesenc(); +$code.=<<___; + sha256rnds2 $ABEF,$CDGH # 52-55 + pshufd \$0x0e,$Wi,$Wi + movdqa @MSG[1],$TMP + palignr \$4,@MSG[0],$TMP + paddd $TMP,@MSG[2] +___ + &$aesenc(); + &$aesenc(); +$code.=<<___; + sha256rnds2 $CDGH,$ABEF + + movdqa 14*32-0x80($Tbl),$Wi + paddd @MSG[1],$Wi + sha256msg2 @MSG[1],@MSG[2] + movdqa $BSWAP,$TMP +___ + &$aesenc(); +$code.=<<___; + sha256rnds2 $ABEF,$CDGH # 56-59 + pshufd \$0x0e,$Wi,$Wi +___ + &$aesenc(); +$code.=<<___; + sha256rnds2 $CDGH,$ABEF + + movdqa 15*32-0x80($Tbl),$Wi + paddd @MSG[2],$Wi +___ + &$aesenc(); + &$aesenc(); +$code.=<<___; + sha256rnds2 $ABEF,$CDGH # 60-63 + pshufd \$0x0e,$Wi,$Wi +___ + &$aesenc(); +$code.=<<___; + sha256rnds2 $CDGH,$ABEF + #pxor $CDGH,$rndkey0 # black magic +___ + while ($r<40) { &$aesenc(); } # remaining aesenc's +$code.=<<___; + #xorps $CDGH,$rndkey0 # black magic + paddd $CDGH_SAVE,$CDGH + paddd $ABEF_SAVE,$ABEF + + dec $len + movups $iv,48($out,$in0) # write output + lea 64($in0),$in0 + jnz .Loop_shaext + + pshufd \$0xb1,$CDGH,$CDGH # DCHG + pshufd \$0x1b,$ABEF,$TMP # FEBA + pshufd \$0xb1,$ABEF,$ABEF # BAFE + punpckhqdq $CDGH,$ABEF # DCBA + palignr \$8,$TMP,$CDGH # HGFE + + movups $iv,($ivp) # write IV + movdqu $ABEF,($ctx) + movdqu $CDGH,16($ctx) +___ +$code.=<<___ if ($win64); + movaps 0*16(%rsp),%xmm6 + movaps 1*16(%rsp),%xmm7 + movaps 2*16(%rsp),%xmm8 + movaps 3*16(%rsp),%xmm9 + movaps 4*16(%rsp),%xmm10 + movaps 5*16(%rsp),%xmm11 + movaps 6*16(%rsp),%xmm12 + movaps 7*16(%rsp),%xmm13 + movaps 8*16(%rsp),%xmm14 + movaps 9*16(%rsp),%xmm15 + lea 8+10*16(%rsp),%rsp +.Lepilogue_shaext: +___ +$code.=<<___; + ret +.size ${func}_shaext,.-${func}_shaext +___ +} +}}}}} + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64 && $avx) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type se_handler,\@abi-omnipotent +.align 16 +se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HanderlData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lin_prologue +___ +$code.=<<___ if ($shaext); + lea aesni_cbc_sha256_enc_shaext(%rip),%r10 + cmp %r10,%rbx + jb .Lnot_in_shaext + + lea (%rax),%rsi + lea 512($context),%rdi # &context.Xmm6 + mov \$20,%ecx + .long 0xa548f3fc # cld; rep movsq + lea 168(%rax),%rax # adjust stack pointer + jmp .Lin_prologue +.Lnot_in_shaext: +___ +$code.=<<___ if ($avx>1); + lea .Lavx2_shortcut(%rip),%r10 + cmp %r10,%rbx # context->RipRbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + + lea 16*$SZ+8*8(%rsi),%rsi # Xmm6- save area + lea 512($context),%rdi # &context.Xmm6 + mov \$20,%ecx + .long 0xa548f3fc # cld; rep movsq + +.Lin_prologue: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size se_handler,.-se_handler + +.section .pdata + .rva .LSEH_begin_${func}_xop + .rva .LSEH_end_${func}_xop + .rva .LSEH_info_${func}_xop + + .rva .LSEH_begin_${func}_avx + .rva .LSEH_end_${func}_avx + .rva .LSEH_info_${func}_avx +___ +$code.=<<___ if ($avx>1); + .rva .LSEH_begin_${func}_avx2 + .rva .LSEH_end_${func}_avx2 + .rva .LSEH_info_${func}_avx2 +___ +$code.=<<___ if ($shaext); + .rva .LSEH_begin_${func}_shaext + .rva .LSEH_end_${func}_shaext + .rva .LSEH_info_${func}_shaext +___ +$code.=<<___; +.section .xdata +.align 8 +.LSEH_info_${func}_xop: + .byte 9,0,0,0 + .rva se_handler + .rva .Lprologue_xop,.Lepilogue_xop # HandlerData[] + +.LSEH_info_${func}_avx: + .byte 9,0,0,0 + .rva se_handler + .rva .Lprologue_avx,.Lepilogue_avx # HandlerData[] +___ +$code.=<<___ if ($avx>1); +.LSEH_info_${func}_avx2: + .byte 9,0,0,0 + .rva se_handler + .rva .Lprologue_avx2,.Lepilogue_avx2 # HandlerData[] +___ +$code.=<<___ if ($shaext); +.LSEH_info_${func}_shaext: + .byte 9,0,0,0 + .rva se_handler + .rva .Lprologue_shaext,.Lepilogue_shaext # HandlerData[] +___ +} + +#################################################################### +sub rex { + local *opcode=shift; + my ($dst,$src)=@_; + my $rex=0; + + $rex|=0x04 if($dst>=8); + $rex|=0x01 if($src>=8); + unshift @opcode,$rex|0x40 if($rex); +} + +{ + my %opcodelet = ( + "sha256rnds2" => 0xcb, + "sha256msg1" => 0xcc, + "sha256msg2" => 0xcd ); + + sub sha256op38 { + my $instr = shift; + + if (defined($opcodelet{$instr}) && @_[0] =~ /%xmm([0-9]+),\s*%xmm([0-9]+)/) { + my @opcode=(0x0f,0x38); + rex(\@opcode,$2,$1); + push @opcode,$opcodelet{$instr}; + push @opcode,0xc0|($1&7)|(($2&7)<<3); # ModR/M + return ".byte\t".join(',',@opcode); + } else { + return $instr."\t".@_[0]; + } + } +} + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +$code =~ s/\b(sha256[^\s]*)\s+(.*)/sha256op38($1,$2)/gem; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesni-x86.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesni-x86.pl new file mode 100644 index 000000000..b351fca28 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesni-x86.pl @@ -0,0 +1,3415 @@ +#! /usr/bin/env perl +# Copyright 2009-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# This module implements support for Intel AES-NI extension. In +# OpenSSL context it's used with Intel engine, but can also be used as +# drop-in replacement for crypto/aes/asm/aes-586.pl [see below for +# details]. +# +# Performance. +# +# To start with see corresponding paragraph in aesni-x86_64.pl... +# Instead of filling table similar to one found there I've chosen to +# summarize *comparison* results for raw ECB, CTR and CBC benchmarks. +# The simplified table below represents 32-bit performance relative +# to 64-bit one in every given point. Ratios vary for different +# encryption modes, therefore interval values. +# +# 16-byte 64-byte 256-byte 1-KB 8-KB +# 53-67% 67-84% 91-94% 95-98% 97-99.5% +# +# Lower ratios for smaller block sizes are perfectly understandable, +# because function call overhead is higher in 32-bit mode. Largest +# 8-KB block performance is virtually same: 32-bit code is less than +# 1% slower for ECB, CBC and CCM, and ~3% slower otherwise. + +# January 2011 +# +# See aesni-x86_64.pl for details. Unlike x86_64 version this module +# interleaves at most 6 aes[enc|dec] instructions, because there are +# not enough registers for 8x interleave [which should be optimal for +# Sandy Bridge]. Actually, performance results for 6x interleave +# factor presented in aesni-x86_64.pl (except for CTR) are for this +# module. + +# April 2011 +# +# Add aesni_xts_[en|de]crypt. Westmere spends 1.50 cycles processing +# one byte out of 8KB with 128-bit key, Sandy Bridge - 1.09. + +# November 2015 +# +# Add aesni_ocb_[en|de]crypt. + +###################################################################### +# Current large-block performance in cycles per byte processed with +# 128-bit key (less is better). +# +# CBC en-/decrypt CTR XTS ECB OCB +# Westmere 3.77/1.37 1.37 1.52 1.27 +# * Bridge 5.07/0.98 0.99 1.09 0.91 1.10 +# Haswell 4.44/0.80 0.97 1.03 0.72 0.76 +# Skylake 2.68/0.65 0.65 0.66 0.64 0.66 +# Silvermont 5.77/3.56 3.67 4.03 3.46 4.03 +# Goldmont 3.84/1.39 1.39 1.63 1.31 1.70 +# Bulldozer 5.80/0.98 1.05 1.24 0.93 1.23 + +$PREFIX="aesni"; # if $PREFIX is set to "AES", the script + # generates drop-in replacement for + # crypto/aes/asm/aes-586.pl:-) +$inline=1; # inline _aesni_[en|de]crypt + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +$output = pop; +open OUT,">$output"; +*STDOUT=*OUT; + +&asm_init($ARGV[0]); + +&external_label("OPENSSL_ia32cap_P"); +&static_label("key_const"); + +if ($PREFIX eq "aesni") { $movekey=\&movups; } +else { $movekey=\&movups; } + +$len="eax"; +$rounds="ecx"; +$key="edx"; +$inp="esi"; +$out="edi"; +$rounds_="ebx"; # backup copy for $rounds +$key_="ebp"; # backup copy for $key + +$rndkey0="xmm0"; +$rndkey1="xmm1"; +$inout0="xmm2"; +$inout1="xmm3"; +$inout2="xmm4"; +$inout3="xmm5"; $in1="xmm5"; +$inout4="xmm6"; $in0="xmm6"; +$inout5="xmm7"; $ivec="xmm7"; + +# AESNI extension +sub aeskeygenassist +{ my($dst,$src,$imm)=@_; + if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/) + { &data_byte(0x66,0x0f,0x3a,0xdf,0xc0|($1<<3)|$2,$imm); } +} +sub aescommon +{ my($opcodelet,$dst,$src)=@_; + if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/) + { &data_byte(0x66,0x0f,0x38,$opcodelet,0xc0|($1<<3)|$2);} +} +sub aesimc { aescommon(0xdb,@_); } +sub aesenc { aescommon(0xdc,@_); } +sub aesenclast { aescommon(0xdd,@_); } +sub aesdec { aescommon(0xde,@_); } +sub aesdeclast { aescommon(0xdf,@_); } + +# Inline version of internal aesni_[en|de]crypt1 +{ my $sn; +sub aesni_inline_generate1 +{ my ($p,$inout,$ivec)=@_; $inout=$inout0 if (!defined($inout)); + $sn++; + + &$movekey ($rndkey0,&QWP(0,$key)); + &$movekey ($rndkey1,&QWP(16,$key)); + &xorps ($ivec,$rndkey0) if (defined($ivec)); + &lea ($key,&DWP(32,$key)); + &xorps ($inout,$ivec) if (defined($ivec)); + &xorps ($inout,$rndkey0) if (!defined($ivec)); + &set_label("${p}1_loop_$sn"); + eval"&aes${p} ($inout,$rndkey1)"; + &dec ($rounds); + &$movekey ($rndkey1,&QWP(0,$key)); + &lea ($key,&DWP(16,$key)); + &jnz (&label("${p}1_loop_$sn")); + eval"&aes${p}last ($inout,$rndkey1)"; +}} + +sub aesni_generate1 # fully unrolled loop +{ my ($p,$inout)=@_; $inout=$inout0 if (!defined($inout)); + + &function_begin_B("_aesni_${p}rypt1"); + &movups ($rndkey0,&QWP(0,$key)); + &$movekey ($rndkey1,&QWP(0x10,$key)); + &xorps ($inout,$rndkey0); + &$movekey ($rndkey0,&QWP(0x20,$key)); + &lea ($key,&DWP(0x30,$key)); + &cmp ($rounds,11); + &jb (&label("${p}128")); + &lea ($key,&DWP(0x20,$key)); + &je (&label("${p}192")); + &lea ($key,&DWP(0x20,$key)); + eval"&aes${p} ($inout,$rndkey1)"; + &$movekey ($rndkey1,&QWP(-0x40,$key)); + eval"&aes${p} ($inout,$rndkey0)"; + &$movekey ($rndkey0,&QWP(-0x30,$key)); + &set_label("${p}192"); + eval"&aes${p} ($inout,$rndkey1)"; + &$movekey ($rndkey1,&QWP(-0x20,$key)); + eval"&aes${p} ($inout,$rndkey0)"; + &$movekey ($rndkey0,&QWP(-0x10,$key)); + &set_label("${p}128"); + eval"&aes${p} ($inout,$rndkey1)"; + &$movekey ($rndkey1,&QWP(0,$key)); + eval"&aes${p} ($inout,$rndkey0)"; + &$movekey ($rndkey0,&QWP(0x10,$key)); + eval"&aes${p} ($inout,$rndkey1)"; + &$movekey ($rndkey1,&QWP(0x20,$key)); + eval"&aes${p} ($inout,$rndkey0)"; + &$movekey ($rndkey0,&QWP(0x30,$key)); + eval"&aes${p} ($inout,$rndkey1)"; + &$movekey ($rndkey1,&QWP(0x40,$key)); + eval"&aes${p} ($inout,$rndkey0)"; + &$movekey ($rndkey0,&QWP(0x50,$key)); + eval"&aes${p} ($inout,$rndkey1)"; + &$movekey ($rndkey1,&QWP(0x60,$key)); + eval"&aes${p} ($inout,$rndkey0)"; + &$movekey ($rndkey0,&QWP(0x70,$key)); + eval"&aes${p} ($inout,$rndkey1)"; + eval"&aes${p}last ($inout,$rndkey0)"; + &ret(); + &function_end_B("_aesni_${p}rypt1"); +} + +# void $PREFIX_encrypt (const void *inp,void *out,const AES_KEY *key); +&aesni_generate1("enc") if (!$inline); +&function_begin_B("${PREFIX}_encrypt"); + &mov ("eax",&wparam(0)); + &mov ($key,&wparam(2)); + &movups ($inout0,&QWP(0,"eax")); + &mov ($rounds,&DWP(240,$key)); + &mov ("eax",&wparam(1)); + if ($inline) + { &aesni_inline_generate1("enc"); } + else + { &call ("_aesni_encrypt1"); } + &pxor ($rndkey0,$rndkey0); # clear register bank + &pxor ($rndkey1,$rndkey1); + &movups (&QWP(0,"eax"),$inout0); + &pxor ($inout0,$inout0); + &ret (); +&function_end_B("${PREFIX}_encrypt"); + +# void $PREFIX_decrypt (const void *inp,void *out,const AES_KEY *key); +&aesni_generate1("dec") if(!$inline); +&function_begin_B("${PREFIX}_decrypt"); + &mov ("eax",&wparam(0)); + &mov ($key,&wparam(2)); + &movups ($inout0,&QWP(0,"eax")); + &mov ($rounds,&DWP(240,$key)); + &mov ("eax",&wparam(1)); + if ($inline) + { &aesni_inline_generate1("dec"); } + else + { &call ("_aesni_decrypt1"); } + &pxor ($rndkey0,$rndkey0); # clear register bank + &pxor ($rndkey1,$rndkey1); + &movups (&QWP(0,"eax"),$inout0); + &pxor ($inout0,$inout0); + &ret (); +&function_end_B("${PREFIX}_decrypt"); + +# _aesni_[en|de]cryptN are private interfaces, N denotes interleave +# factor. Why 3x subroutine were originally used in loops? Even though +# aes[enc|dec] latency was originally 6, it could be scheduled only +# every *2nd* cycle. Thus 3x interleave was the one providing optimal +# utilization, i.e. when subroutine's throughput is virtually same as +# of non-interleaved subroutine [for number of input blocks up to 3]. +# This is why it originally made no sense to implement 2x subroutine. +# But times change and it became appropriate to spend extra 192 bytes +# on 2x subroutine on Atom Silvermont account. For processors that +# can schedule aes[enc|dec] every cycle optimal interleave factor +# equals to corresponding instructions latency. 8x is optimal for +# * Bridge, but it's unfeasible to accommodate such implementation +# in XMM registers addressable in 32-bit mode and therefore maximum +# of 6x is used instead... + +sub aesni_generate2 +{ my $p=shift; + + &function_begin_B("_aesni_${p}rypt2"); + &$movekey ($rndkey0,&QWP(0,$key)); + &shl ($rounds,4); + &$movekey ($rndkey1,&QWP(16,$key)); + &xorps ($inout0,$rndkey0); + &pxor ($inout1,$rndkey0); + &$movekey ($rndkey0,&QWP(32,$key)); + &lea ($key,&DWP(32,$key,$rounds)); + &neg ($rounds); + &add ($rounds,16); + + &set_label("${p}2_loop"); + eval"&aes${p} ($inout0,$rndkey1)"; + eval"&aes${p} ($inout1,$rndkey1)"; + &$movekey ($rndkey1,&QWP(0,$key,$rounds)); + &add ($rounds,32); + eval"&aes${p} ($inout0,$rndkey0)"; + eval"&aes${p} ($inout1,$rndkey0)"; + &$movekey ($rndkey0,&QWP(-16,$key,$rounds)); + &jnz (&label("${p}2_loop")); + eval"&aes${p} ($inout0,$rndkey1)"; + eval"&aes${p} ($inout1,$rndkey1)"; + eval"&aes${p}last ($inout0,$rndkey0)"; + eval"&aes${p}last ($inout1,$rndkey0)"; + &ret(); + &function_end_B("_aesni_${p}rypt2"); +} + +sub aesni_generate3 +{ my $p=shift; + + &function_begin_B("_aesni_${p}rypt3"); + &$movekey ($rndkey0,&QWP(0,$key)); + &shl ($rounds,4); + &$movekey ($rndkey1,&QWP(16,$key)); + &xorps ($inout0,$rndkey0); + &pxor ($inout1,$rndkey0); + &pxor ($inout2,$rndkey0); + &$movekey ($rndkey0,&QWP(32,$key)); + &lea ($key,&DWP(32,$key,$rounds)); + &neg ($rounds); + &add ($rounds,16); + + &set_label("${p}3_loop"); + eval"&aes${p} ($inout0,$rndkey1)"; + eval"&aes${p} ($inout1,$rndkey1)"; + eval"&aes${p} ($inout2,$rndkey1)"; + &$movekey ($rndkey1,&QWP(0,$key,$rounds)); + &add ($rounds,32); + eval"&aes${p} ($inout0,$rndkey0)"; + eval"&aes${p} ($inout1,$rndkey0)"; + eval"&aes${p} ($inout2,$rndkey0)"; + &$movekey ($rndkey0,&QWP(-16,$key,$rounds)); + &jnz (&label("${p}3_loop")); + eval"&aes${p} ($inout0,$rndkey1)"; + eval"&aes${p} ($inout1,$rndkey1)"; + eval"&aes${p} ($inout2,$rndkey1)"; + eval"&aes${p}last ($inout0,$rndkey0)"; + eval"&aes${p}last ($inout1,$rndkey0)"; + eval"&aes${p}last ($inout2,$rndkey0)"; + &ret(); + &function_end_B("_aesni_${p}rypt3"); +} + +# 4x interleave is implemented to improve small block performance, +# most notably [and naturally] 4 block by ~30%. One can argue that one +# should have implemented 5x as well, but improvement would be <20%, +# so it's not worth it... +sub aesni_generate4 +{ my $p=shift; + + &function_begin_B("_aesni_${p}rypt4"); + &$movekey ($rndkey0,&QWP(0,$key)); + &$movekey ($rndkey1,&QWP(16,$key)); + &shl ($rounds,4); + &xorps ($inout0,$rndkey0); + &pxor ($inout1,$rndkey0); + &pxor ($inout2,$rndkey0); + &pxor ($inout3,$rndkey0); + &$movekey ($rndkey0,&QWP(32,$key)); + &lea ($key,&DWP(32,$key,$rounds)); + &neg ($rounds); + &data_byte (0x0f,0x1f,0x40,0x00); + &add ($rounds,16); + + &set_label("${p}4_loop"); + eval"&aes${p} ($inout0,$rndkey1)"; + eval"&aes${p} ($inout1,$rndkey1)"; + eval"&aes${p} ($inout2,$rndkey1)"; + eval"&aes${p} ($inout3,$rndkey1)"; + &$movekey ($rndkey1,&QWP(0,$key,$rounds)); + &add ($rounds,32); + eval"&aes${p} ($inout0,$rndkey0)"; + eval"&aes${p} ($inout1,$rndkey0)"; + eval"&aes${p} ($inout2,$rndkey0)"; + eval"&aes${p} ($inout3,$rndkey0)"; + &$movekey ($rndkey0,&QWP(-16,$key,$rounds)); + &jnz (&label("${p}4_loop")); + + eval"&aes${p} ($inout0,$rndkey1)"; + eval"&aes${p} ($inout1,$rndkey1)"; + eval"&aes${p} ($inout2,$rndkey1)"; + eval"&aes${p} ($inout3,$rndkey1)"; + eval"&aes${p}last ($inout0,$rndkey0)"; + eval"&aes${p}last ($inout1,$rndkey0)"; + eval"&aes${p}last ($inout2,$rndkey0)"; + eval"&aes${p}last ($inout3,$rndkey0)"; + &ret(); + &function_end_B("_aesni_${p}rypt4"); +} + +sub aesni_generate6 +{ my $p=shift; + + &function_begin_B("_aesni_${p}rypt6"); + &static_label("_aesni_${p}rypt6_enter"); + &$movekey ($rndkey0,&QWP(0,$key)); + &shl ($rounds,4); + &$movekey ($rndkey1,&QWP(16,$key)); + &xorps ($inout0,$rndkey0); + &pxor ($inout1,$rndkey0); # pxor does better here + &pxor ($inout2,$rndkey0); + eval"&aes${p} ($inout0,$rndkey1)"; + &pxor ($inout3,$rndkey0); + &pxor ($inout4,$rndkey0); + eval"&aes${p} ($inout1,$rndkey1)"; + &lea ($key,&DWP(32,$key,$rounds)); + &neg ($rounds); + eval"&aes${p} ($inout2,$rndkey1)"; + &pxor ($inout5,$rndkey0); + &$movekey ($rndkey0,&QWP(0,$key,$rounds)); + &add ($rounds,16); + &jmp (&label("_aesni_${p}rypt6_inner")); + + &set_label("${p}6_loop",16); + eval"&aes${p} ($inout0,$rndkey1)"; + eval"&aes${p} ($inout1,$rndkey1)"; + eval"&aes${p} ($inout2,$rndkey1)"; + &set_label("_aesni_${p}rypt6_inner"); + eval"&aes${p} ($inout3,$rndkey1)"; + eval"&aes${p} ($inout4,$rndkey1)"; + eval"&aes${p} ($inout5,$rndkey1)"; + &set_label("_aesni_${p}rypt6_enter"); + &$movekey ($rndkey1,&QWP(0,$key,$rounds)); + &add ($rounds,32); + eval"&aes${p} ($inout0,$rndkey0)"; + eval"&aes${p} ($inout1,$rndkey0)"; + eval"&aes${p} ($inout2,$rndkey0)"; + eval"&aes${p} ($inout3,$rndkey0)"; + eval"&aes${p} ($inout4,$rndkey0)"; + eval"&aes${p} ($inout5,$rndkey0)"; + &$movekey ($rndkey0,&QWP(-16,$key,$rounds)); + &jnz (&label("${p}6_loop")); + + eval"&aes${p} ($inout0,$rndkey1)"; + eval"&aes${p} ($inout1,$rndkey1)"; + eval"&aes${p} ($inout2,$rndkey1)"; + eval"&aes${p} ($inout3,$rndkey1)"; + eval"&aes${p} ($inout4,$rndkey1)"; + eval"&aes${p} ($inout5,$rndkey1)"; + eval"&aes${p}last ($inout0,$rndkey0)"; + eval"&aes${p}last ($inout1,$rndkey0)"; + eval"&aes${p}last ($inout2,$rndkey0)"; + eval"&aes${p}last ($inout3,$rndkey0)"; + eval"&aes${p}last ($inout4,$rndkey0)"; + eval"&aes${p}last ($inout5,$rndkey0)"; + &ret(); + &function_end_B("_aesni_${p}rypt6"); +} +&aesni_generate2("enc") if ($PREFIX eq "aesni"); +&aesni_generate2("dec"); +&aesni_generate3("enc") if ($PREFIX eq "aesni"); +&aesni_generate3("dec"); +&aesni_generate4("enc") if ($PREFIX eq "aesni"); +&aesni_generate4("dec"); +&aesni_generate6("enc") if ($PREFIX eq "aesni"); +&aesni_generate6("dec"); + +if ($PREFIX eq "aesni") { +###################################################################### +# void aesni_ecb_encrypt (const void *in, void *out, +# size_t length, const AES_KEY *key, +# int enc); +&function_begin("aesni_ecb_encrypt"); + &mov ($inp,&wparam(0)); + &mov ($out,&wparam(1)); + &mov ($len,&wparam(2)); + &mov ($key,&wparam(3)); + &mov ($rounds_,&wparam(4)); + &and ($len,-16); + &jz (&label("ecb_ret")); + &mov ($rounds,&DWP(240,$key)); + &test ($rounds_,$rounds_); + &jz (&label("ecb_decrypt")); + + &mov ($key_,$key); # backup $key + &mov ($rounds_,$rounds); # backup $rounds + &cmp ($len,0x60); + &jb (&label("ecb_enc_tail")); + + &movdqu ($inout0,&QWP(0,$inp)); + &movdqu ($inout1,&QWP(0x10,$inp)); + &movdqu ($inout2,&QWP(0x20,$inp)); + &movdqu ($inout3,&QWP(0x30,$inp)); + &movdqu ($inout4,&QWP(0x40,$inp)); + &movdqu ($inout5,&QWP(0x50,$inp)); + &lea ($inp,&DWP(0x60,$inp)); + &sub ($len,0x60); + &jmp (&label("ecb_enc_loop6_enter")); + +&set_label("ecb_enc_loop6",16); + &movups (&QWP(0,$out),$inout0); + &movdqu ($inout0,&QWP(0,$inp)); + &movups (&QWP(0x10,$out),$inout1); + &movdqu ($inout1,&QWP(0x10,$inp)); + &movups (&QWP(0x20,$out),$inout2); + &movdqu ($inout2,&QWP(0x20,$inp)); + &movups (&QWP(0x30,$out),$inout3); + &movdqu ($inout3,&QWP(0x30,$inp)); + &movups (&QWP(0x40,$out),$inout4); + &movdqu ($inout4,&QWP(0x40,$inp)); + &movups (&QWP(0x50,$out),$inout5); + &lea ($out,&DWP(0x60,$out)); + &movdqu ($inout5,&QWP(0x50,$inp)); + &lea ($inp,&DWP(0x60,$inp)); +&set_label("ecb_enc_loop6_enter"); + + &call ("_aesni_encrypt6"); + + &mov ($key,$key_); # restore $key + &mov ($rounds,$rounds_); # restore $rounds + &sub ($len,0x60); + &jnc (&label("ecb_enc_loop6")); + + &movups (&QWP(0,$out),$inout0); + &movups (&QWP(0x10,$out),$inout1); + &movups (&QWP(0x20,$out),$inout2); + &movups (&QWP(0x30,$out),$inout3); + &movups (&QWP(0x40,$out),$inout4); + &movups (&QWP(0x50,$out),$inout5); + &lea ($out,&DWP(0x60,$out)); + &add ($len,0x60); + &jz (&label("ecb_ret")); + +&set_label("ecb_enc_tail"); + &movups ($inout0,&QWP(0,$inp)); + &cmp ($len,0x20); + &jb (&label("ecb_enc_one")); + &movups ($inout1,&QWP(0x10,$inp)); + &je (&label("ecb_enc_two")); + &movups ($inout2,&QWP(0x20,$inp)); + &cmp ($len,0x40); + &jb (&label("ecb_enc_three")); + &movups ($inout3,&QWP(0x30,$inp)); + &je (&label("ecb_enc_four")); + &movups ($inout4,&QWP(0x40,$inp)); + &xorps ($inout5,$inout5); + &call ("_aesni_encrypt6"); + &movups (&QWP(0,$out),$inout0); + &movups (&QWP(0x10,$out),$inout1); + &movups (&QWP(0x20,$out),$inout2); + &movups (&QWP(0x30,$out),$inout3); + &movups (&QWP(0x40,$out),$inout4); + jmp (&label("ecb_ret")); + +&set_label("ecb_enc_one",16); + if ($inline) + { &aesni_inline_generate1("enc"); } + else + { &call ("_aesni_encrypt1"); } + &movups (&QWP(0,$out),$inout0); + &jmp (&label("ecb_ret")); + +&set_label("ecb_enc_two",16); + &call ("_aesni_encrypt2"); + &movups (&QWP(0,$out),$inout0); + &movups (&QWP(0x10,$out),$inout1); + &jmp (&label("ecb_ret")); + +&set_label("ecb_enc_three",16); + &call ("_aesni_encrypt3"); + &movups (&QWP(0,$out),$inout0); + &movups (&QWP(0x10,$out),$inout1); + &movups (&QWP(0x20,$out),$inout2); + &jmp (&label("ecb_ret")); + +&set_label("ecb_enc_four",16); + &call ("_aesni_encrypt4"); + &movups (&QWP(0,$out),$inout0); + &movups (&QWP(0x10,$out),$inout1); + &movups (&QWP(0x20,$out),$inout2); + &movups (&QWP(0x30,$out),$inout3); + &jmp (&label("ecb_ret")); +###################################################################### +&set_label("ecb_decrypt",16); + &mov ($key_,$key); # backup $key + &mov ($rounds_,$rounds); # backup $rounds + &cmp ($len,0x60); + &jb (&label("ecb_dec_tail")); + + &movdqu ($inout0,&QWP(0,$inp)); + &movdqu ($inout1,&QWP(0x10,$inp)); + &movdqu ($inout2,&QWP(0x20,$inp)); + &movdqu ($inout3,&QWP(0x30,$inp)); + &movdqu ($inout4,&QWP(0x40,$inp)); + &movdqu ($inout5,&QWP(0x50,$inp)); + &lea ($inp,&DWP(0x60,$inp)); + &sub ($len,0x60); + &jmp (&label("ecb_dec_loop6_enter")); + +&set_label("ecb_dec_loop6",16); + &movups (&QWP(0,$out),$inout0); + &movdqu ($inout0,&QWP(0,$inp)); + &movups (&QWP(0x10,$out),$inout1); + &movdqu ($inout1,&QWP(0x10,$inp)); + &movups (&QWP(0x20,$out),$inout2); + &movdqu ($inout2,&QWP(0x20,$inp)); + &movups (&QWP(0x30,$out),$inout3); + &movdqu ($inout3,&QWP(0x30,$inp)); + &movups (&QWP(0x40,$out),$inout4); + &movdqu ($inout4,&QWP(0x40,$inp)); + &movups (&QWP(0x50,$out),$inout5); + &lea ($out,&DWP(0x60,$out)); + &movdqu ($inout5,&QWP(0x50,$inp)); + &lea ($inp,&DWP(0x60,$inp)); +&set_label("ecb_dec_loop6_enter"); + + &call ("_aesni_decrypt6"); + + &mov ($key,$key_); # restore $key + &mov ($rounds,$rounds_); # restore $rounds + &sub ($len,0x60); + &jnc (&label("ecb_dec_loop6")); + + &movups (&QWP(0,$out),$inout0); + &movups (&QWP(0x10,$out),$inout1); + &movups (&QWP(0x20,$out),$inout2); + &movups (&QWP(0x30,$out),$inout3); + &movups (&QWP(0x40,$out),$inout4); + &movups (&QWP(0x50,$out),$inout5); + &lea ($out,&DWP(0x60,$out)); + &add ($len,0x60); + &jz (&label("ecb_ret")); + +&set_label("ecb_dec_tail"); + &movups ($inout0,&QWP(0,$inp)); + &cmp ($len,0x20); + &jb (&label("ecb_dec_one")); + &movups ($inout1,&QWP(0x10,$inp)); + &je (&label("ecb_dec_two")); + &movups ($inout2,&QWP(0x20,$inp)); + &cmp ($len,0x40); + &jb (&label("ecb_dec_three")); + &movups ($inout3,&QWP(0x30,$inp)); + &je (&label("ecb_dec_four")); + &movups ($inout4,&QWP(0x40,$inp)); + &xorps ($inout5,$inout5); + &call ("_aesni_decrypt6"); + &movups (&QWP(0,$out),$inout0); + &movups (&QWP(0x10,$out),$inout1); + &movups (&QWP(0x20,$out),$inout2); + &movups (&QWP(0x30,$out),$inout3); + &movups (&QWP(0x40,$out),$inout4); + &jmp (&label("ecb_ret")); + +&set_label("ecb_dec_one",16); + if ($inline) + { &aesni_inline_generate1("dec"); } + else + { &call ("_aesni_decrypt1"); } + &movups (&QWP(0,$out),$inout0); + &jmp (&label("ecb_ret")); + +&set_label("ecb_dec_two",16); + &call ("_aesni_decrypt2"); + &movups (&QWP(0,$out),$inout0); + &movups (&QWP(0x10,$out),$inout1); + &jmp (&label("ecb_ret")); + +&set_label("ecb_dec_three",16); + &call ("_aesni_decrypt3"); + &movups (&QWP(0,$out),$inout0); + &movups (&QWP(0x10,$out),$inout1); + &movups (&QWP(0x20,$out),$inout2); + &jmp (&label("ecb_ret")); + +&set_label("ecb_dec_four",16); + &call ("_aesni_decrypt4"); + &movups (&QWP(0,$out),$inout0); + &movups (&QWP(0x10,$out),$inout1); + &movups (&QWP(0x20,$out),$inout2); + &movups (&QWP(0x30,$out),$inout3); + +&set_label("ecb_ret"); + &pxor ("xmm0","xmm0"); # clear register bank + &pxor ("xmm1","xmm1"); + &pxor ("xmm2","xmm2"); + &pxor ("xmm3","xmm3"); + &pxor ("xmm4","xmm4"); + &pxor ("xmm5","xmm5"); + &pxor ("xmm6","xmm6"); + &pxor ("xmm7","xmm7"); +&function_end("aesni_ecb_encrypt"); + +###################################################################### +# void aesni_ccm64_[en|de]crypt_blocks (const void *in, void *out, +# size_t blocks, const AES_KEY *key, +# const char *ivec,char *cmac); +# +# Handles only complete blocks, operates on 64-bit counter and +# does not update *ivec! Nor does it finalize CMAC value +# (see engine/eng_aesni.c for details) +# +{ my $cmac=$inout1; +&function_begin("aesni_ccm64_encrypt_blocks"); + &mov ($inp,&wparam(0)); + &mov ($out,&wparam(1)); + &mov ($len,&wparam(2)); + &mov ($key,&wparam(3)); + &mov ($rounds_,&wparam(4)); + &mov ($rounds,&wparam(5)); + &mov ($key_,"esp"); + &sub ("esp",60); + &and ("esp",-16); # align stack + &mov (&DWP(48,"esp"),$key_); + + &movdqu ($ivec,&QWP(0,$rounds_)); # load ivec + &movdqu ($cmac,&QWP(0,$rounds)); # load cmac + &mov ($rounds,&DWP(240,$key)); + + # compose byte-swap control mask for pshufb on stack + &mov (&DWP(0,"esp"),0x0c0d0e0f); + &mov (&DWP(4,"esp"),0x08090a0b); + &mov (&DWP(8,"esp"),0x04050607); + &mov (&DWP(12,"esp"),0x00010203); + + # compose counter increment vector on stack + &mov ($rounds_,1); + &xor ($key_,$key_); + &mov (&DWP(16,"esp"),$rounds_); + &mov (&DWP(20,"esp"),$key_); + &mov (&DWP(24,"esp"),$key_); + &mov (&DWP(28,"esp"),$key_); + + &shl ($rounds,4); + &mov ($rounds_,16); + &lea ($key_,&DWP(0,$key)); + &movdqa ($inout3,&QWP(0,"esp")); + &movdqa ($inout0,$ivec); + &lea ($key,&DWP(32,$key,$rounds)); + &sub ($rounds_,$rounds); + &pshufb ($ivec,$inout3); + +&set_label("ccm64_enc_outer"); + &$movekey ($rndkey0,&QWP(0,$key_)); + &mov ($rounds,$rounds_); + &movups ($in0,&QWP(0,$inp)); + + &xorps ($inout0,$rndkey0); + &$movekey ($rndkey1,&QWP(16,$key_)); + &xorps ($rndkey0,$in0); + &xorps ($cmac,$rndkey0); # cmac^=inp + &$movekey ($rndkey0,&QWP(32,$key_)); + +&set_label("ccm64_enc2_loop"); + &aesenc ($inout0,$rndkey1); + &aesenc ($cmac,$rndkey1); + &$movekey ($rndkey1,&QWP(0,$key,$rounds)); + &add ($rounds,32); + &aesenc ($inout0,$rndkey0); + &aesenc ($cmac,$rndkey0); + &$movekey ($rndkey0,&QWP(-16,$key,$rounds)); + &jnz (&label("ccm64_enc2_loop")); + &aesenc ($inout0,$rndkey1); + &aesenc ($cmac,$rndkey1); + &paddq ($ivec,&QWP(16,"esp")); + &dec ($len); + &aesenclast ($inout0,$rndkey0); + &aesenclast ($cmac,$rndkey0); + + &lea ($inp,&DWP(16,$inp)); + &xorps ($in0,$inout0); # inp^=E(ivec) + &movdqa ($inout0,$ivec); + &movups (&QWP(0,$out),$in0); # save output + &pshufb ($inout0,$inout3); + &lea ($out,&DWP(16,$out)); + &jnz (&label("ccm64_enc_outer")); + + &mov ("esp",&DWP(48,"esp")); + &mov ($out,&wparam(5)); + &movups (&QWP(0,$out),$cmac); + + &pxor ("xmm0","xmm0"); # clear register bank + &pxor ("xmm1","xmm1"); + &pxor ("xmm2","xmm2"); + &pxor ("xmm3","xmm3"); + &pxor ("xmm4","xmm4"); + &pxor ("xmm5","xmm5"); + &pxor ("xmm6","xmm6"); + &pxor ("xmm7","xmm7"); +&function_end("aesni_ccm64_encrypt_blocks"); + +&function_begin("aesni_ccm64_decrypt_blocks"); + &mov ($inp,&wparam(0)); + &mov ($out,&wparam(1)); + &mov ($len,&wparam(2)); + &mov ($key,&wparam(3)); + &mov ($rounds_,&wparam(4)); + &mov ($rounds,&wparam(5)); + &mov ($key_,"esp"); + &sub ("esp",60); + &and ("esp",-16); # align stack + &mov (&DWP(48,"esp"),$key_); + + &movdqu ($ivec,&QWP(0,$rounds_)); # load ivec + &movdqu ($cmac,&QWP(0,$rounds)); # load cmac + &mov ($rounds,&DWP(240,$key)); + + # compose byte-swap control mask for pshufb on stack + &mov (&DWP(0,"esp"),0x0c0d0e0f); + &mov (&DWP(4,"esp"),0x08090a0b); + &mov (&DWP(8,"esp"),0x04050607); + &mov (&DWP(12,"esp"),0x00010203); + + # compose counter increment vector on stack + &mov ($rounds_,1); + &xor ($key_,$key_); + &mov (&DWP(16,"esp"),$rounds_); + &mov (&DWP(20,"esp"),$key_); + &mov (&DWP(24,"esp"),$key_); + &mov (&DWP(28,"esp"),$key_); + + &movdqa ($inout3,&QWP(0,"esp")); # bswap mask + &movdqa ($inout0,$ivec); + + &mov ($key_,$key); + &mov ($rounds_,$rounds); + + &pshufb ($ivec,$inout3); + if ($inline) + { &aesni_inline_generate1("enc"); } + else + { &call ("_aesni_encrypt1"); } + &shl ($rounds_,4); + &mov ($rounds,16); + &movups ($in0,&QWP(0,$inp)); # load inp + &paddq ($ivec,&QWP(16,"esp")); + &lea ($inp,&QWP(16,$inp)); + &sub ($rounds,$rounds_); + &lea ($key,&DWP(32,$key_,$rounds_)); + &mov ($rounds_,$rounds); + &jmp (&label("ccm64_dec_outer")); + +&set_label("ccm64_dec_outer",16); + &xorps ($in0,$inout0); # inp ^= E(ivec) + &movdqa ($inout0,$ivec); + &movups (&QWP(0,$out),$in0); # save output + &lea ($out,&DWP(16,$out)); + &pshufb ($inout0,$inout3); + + &sub ($len,1); + &jz (&label("ccm64_dec_break")); + + &$movekey ($rndkey0,&QWP(0,$key_)); + &mov ($rounds,$rounds_); + &$movekey ($rndkey1,&QWP(16,$key_)); + &xorps ($in0,$rndkey0); + &xorps ($inout0,$rndkey0); + &xorps ($cmac,$in0); # cmac^=out + &$movekey ($rndkey0,&QWP(32,$key_)); + +&set_label("ccm64_dec2_loop"); + &aesenc ($inout0,$rndkey1); + &aesenc ($cmac,$rndkey1); + &$movekey ($rndkey1,&QWP(0,$key,$rounds)); + &add ($rounds,32); + &aesenc ($inout0,$rndkey0); + &aesenc ($cmac,$rndkey0); + &$movekey ($rndkey0,&QWP(-16,$key,$rounds)); + &jnz (&label("ccm64_dec2_loop")); + &movups ($in0,&QWP(0,$inp)); # load inp + &paddq ($ivec,&QWP(16,"esp")); + &aesenc ($inout0,$rndkey1); + &aesenc ($cmac,$rndkey1); + &aesenclast ($inout0,$rndkey0); + &aesenclast ($cmac,$rndkey0); + &lea ($inp,&QWP(16,$inp)); + &jmp (&label("ccm64_dec_outer")); + +&set_label("ccm64_dec_break",16); + &mov ($rounds,&DWP(240,$key_)); + &mov ($key,$key_); + if ($inline) + { &aesni_inline_generate1("enc",$cmac,$in0); } + else + { &call ("_aesni_encrypt1",$cmac); } + + &mov ("esp",&DWP(48,"esp")); + &mov ($out,&wparam(5)); + &movups (&QWP(0,$out),$cmac); + + &pxor ("xmm0","xmm0"); # clear register bank + &pxor ("xmm1","xmm1"); + &pxor ("xmm2","xmm2"); + &pxor ("xmm3","xmm3"); + &pxor ("xmm4","xmm4"); + &pxor ("xmm5","xmm5"); + &pxor ("xmm6","xmm6"); + &pxor ("xmm7","xmm7"); +&function_end("aesni_ccm64_decrypt_blocks"); +} + +###################################################################### +# void aesni_ctr32_encrypt_blocks (const void *in, void *out, +# size_t blocks, const AES_KEY *key, +# const char *ivec); +# +# Handles only complete blocks, operates on 32-bit counter and +# does not update *ivec! (see crypto/modes/ctr128.c for details) +# +# stack layout: +# 0 pshufb mask +# 16 vector addend: 0,6,6,6 +# 32 counter-less ivec +# 48 1st triplet of counter vector +# 64 2nd triplet of counter vector +# 80 saved %esp + +&function_begin("aesni_ctr32_encrypt_blocks"); + &mov ($inp,&wparam(0)); + &mov ($out,&wparam(1)); + &mov ($len,&wparam(2)); + &mov ($key,&wparam(3)); + &mov ($rounds_,&wparam(4)); + &mov ($key_,"esp"); + &sub ("esp",88); + &and ("esp",-16); # align stack + &mov (&DWP(80,"esp"),$key_); + + &cmp ($len,1); + &je (&label("ctr32_one_shortcut")); + + &movdqu ($inout5,&QWP(0,$rounds_)); # load ivec + + # compose byte-swap control mask for pshufb on stack + &mov (&DWP(0,"esp"),0x0c0d0e0f); + &mov (&DWP(4,"esp"),0x08090a0b); + &mov (&DWP(8,"esp"),0x04050607); + &mov (&DWP(12,"esp"),0x00010203); + + # compose counter increment vector on stack + &mov ($rounds,6); + &xor ($key_,$key_); + &mov (&DWP(16,"esp"),$rounds); + &mov (&DWP(20,"esp"),$rounds); + &mov (&DWP(24,"esp"),$rounds); + &mov (&DWP(28,"esp"),$key_); + + &pextrd ($rounds_,$inout5,3); # pull 32-bit counter + &pinsrd ($inout5,$key_,3); # wipe 32-bit counter + + &mov ($rounds,&DWP(240,$key)); # key->rounds + + # compose 2 vectors of 3x32-bit counters + &bswap ($rounds_); + &pxor ($rndkey0,$rndkey0); + &pxor ($rndkey1,$rndkey1); + &movdqa ($inout0,&QWP(0,"esp")); # load byte-swap mask + &pinsrd ($rndkey0,$rounds_,0); + &lea ($key_,&DWP(3,$rounds_)); + &pinsrd ($rndkey1,$key_,0); + &inc ($rounds_); + &pinsrd ($rndkey0,$rounds_,1); + &inc ($key_); + &pinsrd ($rndkey1,$key_,1); + &inc ($rounds_); + &pinsrd ($rndkey0,$rounds_,2); + &inc ($key_); + &pinsrd ($rndkey1,$key_,2); + &movdqa (&QWP(48,"esp"),$rndkey0); # save 1st triplet + &pshufb ($rndkey0,$inout0); # byte swap + &movdqu ($inout4,&QWP(0,$key)); # key[0] + &movdqa (&QWP(64,"esp"),$rndkey1); # save 2nd triplet + &pshufb ($rndkey1,$inout0); # byte swap + + &pshufd ($inout0,$rndkey0,3<<6); # place counter to upper dword + &pshufd ($inout1,$rndkey0,2<<6); + &cmp ($len,6); + &jb (&label("ctr32_tail")); + &pxor ($inout5,$inout4); # counter-less ivec^key[0] + &shl ($rounds,4); + &mov ($rounds_,16); + &movdqa (&QWP(32,"esp"),$inout5); # save counter-less ivec^key[0] + &mov ($key_,$key); # backup $key + &sub ($rounds_,$rounds); # backup twisted $rounds + &lea ($key,&DWP(32,$key,$rounds)); + &sub ($len,6); + &jmp (&label("ctr32_loop6")); + +&set_label("ctr32_loop6",16); + # inlining _aesni_encrypt6's prologue gives ~6% improvement... + &pshufd ($inout2,$rndkey0,1<<6); + &movdqa ($rndkey0,&QWP(32,"esp")); # pull counter-less ivec + &pshufd ($inout3,$rndkey1,3<<6); + &pxor ($inout0,$rndkey0); # merge counter-less ivec + &pshufd ($inout4,$rndkey1,2<<6); + &pxor ($inout1,$rndkey0); + &pshufd ($inout5,$rndkey1,1<<6); + &$movekey ($rndkey1,&QWP(16,$key_)); + &pxor ($inout2,$rndkey0); + &pxor ($inout3,$rndkey0); + &aesenc ($inout0,$rndkey1); + &pxor ($inout4,$rndkey0); + &pxor ($inout5,$rndkey0); + &aesenc ($inout1,$rndkey1); + &$movekey ($rndkey0,&QWP(32,$key_)); + &mov ($rounds,$rounds_); + &aesenc ($inout2,$rndkey1); + &aesenc ($inout3,$rndkey1); + &aesenc ($inout4,$rndkey1); + &aesenc ($inout5,$rndkey1); + + &call (&label("_aesni_encrypt6_enter")); + + &movups ($rndkey1,&QWP(0,$inp)); + &movups ($rndkey0,&QWP(0x10,$inp)); + &xorps ($inout0,$rndkey1); + &movups ($rndkey1,&QWP(0x20,$inp)); + &xorps ($inout1,$rndkey0); + &movups (&QWP(0,$out),$inout0); + &movdqa ($rndkey0,&QWP(16,"esp")); # load increment + &xorps ($inout2,$rndkey1); + &movdqa ($rndkey1,&QWP(64,"esp")); # load 2nd triplet + &movups (&QWP(0x10,$out),$inout1); + &movups (&QWP(0x20,$out),$inout2); + + &paddd ($rndkey1,$rndkey0); # 2nd triplet increment + &paddd ($rndkey0,&QWP(48,"esp")); # 1st triplet increment + &movdqa ($inout0,&QWP(0,"esp")); # load byte swap mask + + &movups ($inout1,&QWP(0x30,$inp)); + &movups ($inout2,&QWP(0x40,$inp)); + &xorps ($inout3,$inout1); + &movups ($inout1,&QWP(0x50,$inp)); + &lea ($inp,&DWP(0x60,$inp)); + &movdqa (&QWP(48,"esp"),$rndkey0); # save 1st triplet + &pshufb ($rndkey0,$inout0); # byte swap + &xorps ($inout4,$inout2); + &movups (&QWP(0x30,$out),$inout3); + &xorps ($inout5,$inout1); + &movdqa (&QWP(64,"esp"),$rndkey1); # save 2nd triplet + &pshufb ($rndkey1,$inout0); # byte swap + &movups (&QWP(0x40,$out),$inout4); + &pshufd ($inout0,$rndkey0,3<<6); + &movups (&QWP(0x50,$out),$inout5); + &lea ($out,&DWP(0x60,$out)); + + &pshufd ($inout1,$rndkey0,2<<6); + &sub ($len,6); + &jnc (&label("ctr32_loop6")); + + &add ($len,6); + &jz (&label("ctr32_ret")); + &movdqu ($inout5,&QWP(0,$key_)); + &mov ($key,$key_); + &pxor ($inout5,&QWP(32,"esp")); # restore count-less ivec + &mov ($rounds,&DWP(240,$key_)); # restore $rounds + +&set_label("ctr32_tail"); + &por ($inout0,$inout5); + &cmp ($len,2); + &jb (&label("ctr32_one")); + + &pshufd ($inout2,$rndkey0,1<<6); + &por ($inout1,$inout5); + &je (&label("ctr32_two")); + + &pshufd ($inout3,$rndkey1,3<<6); + &por ($inout2,$inout5); + &cmp ($len,4); + &jb (&label("ctr32_three")); + + &pshufd ($inout4,$rndkey1,2<<6); + &por ($inout3,$inout5); + &je (&label("ctr32_four")); + + &por ($inout4,$inout5); + &call ("_aesni_encrypt6"); + &movups ($rndkey1,&QWP(0,$inp)); + &movups ($rndkey0,&QWP(0x10,$inp)); + &xorps ($inout0,$rndkey1); + &movups ($rndkey1,&QWP(0x20,$inp)); + &xorps ($inout1,$rndkey0); + &movups ($rndkey0,&QWP(0x30,$inp)); + &xorps ($inout2,$rndkey1); + &movups ($rndkey1,&QWP(0x40,$inp)); + &xorps ($inout3,$rndkey0); + &movups (&QWP(0,$out),$inout0); + &xorps ($inout4,$rndkey1); + &movups (&QWP(0x10,$out),$inout1); + &movups (&QWP(0x20,$out),$inout2); + &movups (&QWP(0x30,$out),$inout3); + &movups (&QWP(0x40,$out),$inout4); + &jmp (&label("ctr32_ret")); + +&set_label("ctr32_one_shortcut",16); + &movups ($inout0,&QWP(0,$rounds_)); # load ivec + &mov ($rounds,&DWP(240,$key)); + +&set_label("ctr32_one"); + if ($inline) + { &aesni_inline_generate1("enc"); } + else + { &call ("_aesni_encrypt1"); } + &movups ($in0,&QWP(0,$inp)); + &xorps ($in0,$inout0); + &movups (&QWP(0,$out),$in0); + &jmp (&label("ctr32_ret")); + +&set_label("ctr32_two",16); + &call ("_aesni_encrypt2"); + &movups ($inout3,&QWP(0,$inp)); + &movups ($inout4,&QWP(0x10,$inp)); + &xorps ($inout0,$inout3); + &xorps ($inout1,$inout4); + &movups (&QWP(0,$out),$inout0); + &movups (&QWP(0x10,$out),$inout1); + &jmp (&label("ctr32_ret")); + +&set_label("ctr32_three",16); + &call ("_aesni_encrypt3"); + &movups ($inout3,&QWP(0,$inp)); + &movups ($inout4,&QWP(0x10,$inp)); + &xorps ($inout0,$inout3); + &movups ($inout5,&QWP(0x20,$inp)); + &xorps ($inout1,$inout4); + &movups (&QWP(0,$out),$inout0); + &xorps ($inout2,$inout5); + &movups (&QWP(0x10,$out),$inout1); + &movups (&QWP(0x20,$out),$inout2); + &jmp (&label("ctr32_ret")); + +&set_label("ctr32_four",16); + &call ("_aesni_encrypt4"); + &movups ($inout4,&QWP(0,$inp)); + &movups ($inout5,&QWP(0x10,$inp)); + &movups ($rndkey1,&QWP(0x20,$inp)); + &xorps ($inout0,$inout4); + &movups ($rndkey0,&QWP(0x30,$inp)); + &xorps ($inout1,$inout5); + &movups (&QWP(0,$out),$inout0); + &xorps ($inout2,$rndkey1); + &movups (&QWP(0x10,$out),$inout1); + &xorps ($inout3,$rndkey0); + &movups (&QWP(0x20,$out),$inout2); + &movups (&QWP(0x30,$out),$inout3); + +&set_label("ctr32_ret"); + &pxor ("xmm0","xmm0"); # clear register bank + &pxor ("xmm1","xmm1"); + &pxor ("xmm2","xmm2"); + &pxor ("xmm3","xmm3"); + &pxor ("xmm4","xmm4"); + &movdqa (&QWP(32,"esp"),"xmm0"); # clear stack + &pxor ("xmm5","xmm5"); + &movdqa (&QWP(48,"esp"),"xmm0"); + &pxor ("xmm6","xmm6"); + &movdqa (&QWP(64,"esp"),"xmm0"); + &pxor ("xmm7","xmm7"); + &mov ("esp",&DWP(80,"esp")); +&function_end("aesni_ctr32_encrypt_blocks"); + +###################################################################### +# void aesni_xts_[en|de]crypt(const char *inp,char *out,size_t len, +# const AES_KEY *key1, const AES_KEY *key2 +# const unsigned char iv[16]); +# +{ my ($tweak,$twtmp,$twres,$twmask)=($rndkey1,$rndkey0,$inout0,$inout1); + +&function_begin("aesni_xts_encrypt"); + &mov ($key,&wparam(4)); # key2 + &mov ($inp,&wparam(5)); # clear-text tweak + + &mov ($rounds,&DWP(240,$key)); # key2->rounds + &movups ($inout0,&QWP(0,$inp)); + if ($inline) + { &aesni_inline_generate1("enc"); } + else + { &call ("_aesni_encrypt1"); } + + &mov ($inp,&wparam(0)); + &mov ($out,&wparam(1)); + &mov ($len,&wparam(2)); + &mov ($key,&wparam(3)); # key1 + + &mov ($key_,"esp"); + &sub ("esp",16*7+8); + &mov ($rounds,&DWP(240,$key)); # key1->rounds + &and ("esp",-16); # align stack + + &mov (&DWP(16*6+0,"esp"),0x87); # compose the magic constant + &mov (&DWP(16*6+4,"esp"),0); + &mov (&DWP(16*6+8,"esp"),1); + &mov (&DWP(16*6+12,"esp"),0); + &mov (&DWP(16*7+0,"esp"),$len); # save original $len + &mov (&DWP(16*7+4,"esp"),$key_); # save original %esp + + &movdqa ($tweak,$inout0); + &pxor ($twtmp,$twtmp); + &movdqa ($twmask,&QWP(6*16,"esp")); # 0x0...010...87 + &pcmpgtd($twtmp,$tweak); # broadcast upper bits + + &and ($len,-16); + &mov ($key_,$key); # backup $key + &mov ($rounds_,$rounds); # backup $rounds + &sub ($len,16*6); + &jc (&label("xts_enc_short")); + + &shl ($rounds,4); + &mov ($rounds_,16); + &sub ($rounds_,$rounds); + &lea ($key,&DWP(32,$key,$rounds)); + &jmp (&label("xts_enc_loop6")); + +&set_label("xts_enc_loop6",16); + for ($i=0;$i<4;$i++) { + &pshufd ($twres,$twtmp,0x13); + &pxor ($twtmp,$twtmp); + &movdqa (&QWP(16*$i,"esp"),$tweak); + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &pand ($twres,$twmask); # isolate carry and residue + &pcmpgtd ($twtmp,$tweak); # broadcast upper bits + &pxor ($tweak,$twres); + } + &pshufd ($inout5,$twtmp,0x13); + &movdqa (&QWP(16*$i++,"esp"),$tweak); + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &$movekey ($rndkey0,&QWP(0,$key_)); + &pand ($inout5,$twmask); # isolate carry and residue + &movups ($inout0,&QWP(0,$inp)); # load input + &pxor ($inout5,$tweak); + + # inline _aesni_encrypt6 prologue and flip xor with tweak and key[0] + &mov ($rounds,$rounds_); # restore $rounds + &movdqu ($inout1,&QWP(16*1,$inp)); + &xorps ($inout0,$rndkey0); # input^=rndkey[0] + &movdqu ($inout2,&QWP(16*2,$inp)); + &pxor ($inout1,$rndkey0); + &movdqu ($inout3,&QWP(16*3,$inp)); + &pxor ($inout2,$rndkey0); + &movdqu ($inout4,&QWP(16*4,$inp)); + &pxor ($inout3,$rndkey0); + &movdqu ($rndkey1,&QWP(16*5,$inp)); + &pxor ($inout4,$rndkey0); + &lea ($inp,&DWP(16*6,$inp)); + &pxor ($inout0,&QWP(16*0,"esp")); # input^=tweak + &movdqa (&QWP(16*$i,"esp"),$inout5); # save last tweak + &pxor ($inout5,$rndkey1); + + &$movekey ($rndkey1,&QWP(16,$key_)); + &pxor ($inout1,&QWP(16*1,"esp")); + &pxor ($inout2,&QWP(16*2,"esp")); + &aesenc ($inout0,$rndkey1); + &pxor ($inout3,&QWP(16*3,"esp")); + &pxor ($inout4,&QWP(16*4,"esp")); + &aesenc ($inout1,$rndkey1); + &pxor ($inout5,$rndkey0); + &$movekey ($rndkey0,&QWP(32,$key_)); + &aesenc ($inout2,$rndkey1); + &aesenc ($inout3,$rndkey1); + &aesenc ($inout4,$rndkey1); + &aesenc ($inout5,$rndkey1); + &call (&label("_aesni_encrypt6_enter")); + + &movdqa ($tweak,&QWP(16*5,"esp")); # last tweak + &pxor ($twtmp,$twtmp); + &xorps ($inout0,&QWP(16*0,"esp")); # output^=tweak + &pcmpgtd ($twtmp,$tweak); # broadcast upper bits + &xorps ($inout1,&QWP(16*1,"esp")); + &movups (&QWP(16*0,$out),$inout0); # write output + &xorps ($inout2,&QWP(16*2,"esp")); + &movups (&QWP(16*1,$out),$inout1); + &xorps ($inout3,&QWP(16*3,"esp")); + &movups (&QWP(16*2,$out),$inout2); + &xorps ($inout4,&QWP(16*4,"esp")); + &movups (&QWP(16*3,$out),$inout3); + &xorps ($inout5,$tweak); + &movups (&QWP(16*4,$out),$inout4); + &pshufd ($twres,$twtmp,0x13); + &movups (&QWP(16*5,$out),$inout5); + &lea ($out,&DWP(16*6,$out)); + &movdqa ($twmask,&QWP(16*6,"esp")); # 0x0...010...87 + + &pxor ($twtmp,$twtmp); + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &pand ($twres,$twmask); # isolate carry and residue + &pcmpgtd($twtmp,$tweak); # broadcast upper bits + &pxor ($tweak,$twres); + + &sub ($len,16*6); + &jnc (&label("xts_enc_loop6")); + + &mov ($rounds,&DWP(240,$key_)); # restore $rounds + &mov ($key,$key_); # restore $key + &mov ($rounds_,$rounds); + +&set_label("xts_enc_short"); + &add ($len,16*6); + &jz (&label("xts_enc_done6x")); + + &movdqa ($inout3,$tweak); # put aside previous tweak + &cmp ($len,0x20); + &jb (&label("xts_enc_one")); + + &pshufd ($twres,$twtmp,0x13); + &pxor ($twtmp,$twtmp); + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &pand ($twres,$twmask); # isolate carry and residue + &pcmpgtd($twtmp,$tweak); # broadcast upper bits + &pxor ($tweak,$twres); + &je (&label("xts_enc_two")); + + &pshufd ($twres,$twtmp,0x13); + &pxor ($twtmp,$twtmp); + &movdqa ($inout4,$tweak); # put aside previous tweak + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &pand ($twres,$twmask); # isolate carry and residue + &pcmpgtd($twtmp,$tweak); # broadcast upper bits + &pxor ($tweak,$twres); + &cmp ($len,0x40); + &jb (&label("xts_enc_three")); + + &pshufd ($twres,$twtmp,0x13); + &pxor ($twtmp,$twtmp); + &movdqa ($inout5,$tweak); # put aside previous tweak + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &pand ($twres,$twmask); # isolate carry and residue + &pcmpgtd($twtmp,$tweak); # broadcast upper bits + &pxor ($tweak,$twres); + &movdqa (&QWP(16*0,"esp"),$inout3); + &movdqa (&QWP(16*1,"esp"),$inout4); + &je (&label("xts_enc_four")); + + &movdqa (&QWP(16*2,"esp"),$inout5); + &pshufd ($inout5,$twtmp,0x13); + &movdqa (&QWP(16*3,"esp"),$tweak); + &paddq ($tweak,$tweak); # &psllq($inout0,1); + &pand ($inout5,$twmask); # isolate carry and residue + &pxor ($inout5,$tweak); + + &movdqu ($inout0,&QWP(16*0,$inp)); # load input + &movdqu ($inout1,&QWP(16*1,$inp)); + &movdqu ($inout2,&QWP(16*2,$inp)); + &pxor ($inout0,&QWP(16*0,"esp")); # input^=tweak + &movdqu ($inout3,&QWP(16*3,$inp)); + &pxor ($inout1,&QWP(16*1,"esp")); + &movdqu ($inout4,&QWP(16*4,$inp)); + &pxor ($inout2,&QWP(16*2,"esp")); + &lea ($inp,&DWP(16*5,$inp)); + &pxor ($inout3,&QWP(16*3,"esp")); + &movdqa (&QWP(16*4,"esp"),$inout5); # save last tweak + &pxor ($inout4,$inout5); + + &call ("_aesni_encrypt6"); + + &movaps ($tweak,&QWP(16*4,"esp")); # last tweak + &xorps ($inout0,&QWP(16*0,"esp")); # output^=tweak + &xorps ($inout1,&QWP(16*1,"esp")); + &xorps ($inout2,&QWP(16*2,"esp")); + &movups (&QWP(16*0,$out),$inout0); # write output + &xorps ($inout3,&QWP(16*3,"esp")); + &movups (&QWP(16*1,$out),$inout1); + &xorps ($inout4,$tweak); + &movups (&QWP(16*2,$out),$inout2); + &movups (&QWP(16*3,$out),$inout3); + &movups (&QWP(16*4,$out),$inout4); + &lea ($out,&DWP(16*5,$out)); + &jmp (&label("xts_enc_done")); + +&set_label("xts_enc_one",16); + &movups ($inout0,&QWP(16*0,$inp)); # load input + &lea ($inp,&DWP(16*1,$inp)); + &xorps ($inout0,$inout3); # input^=tweak + if ($inline) + { &aesni_inline_generate1("enc"); } + else + { &call ("_aesni_encrypt1"); } + &xorps ($inout0,$inout3); # output^=tweak + &movups (&QWP(16*0,$out),$inout0); # write output + &lea ($out,&DWP(16*1,$out)); + + &movdqa ($tweak,$inout3); # last tweak + &jmp (&label("xts_enc_done")); + +&set_label("xts_enc_two",16); + &movaps ($inout4,$tweak); # put aside last tweak + + &movups ($inout0,&QWP(16*0,$inp)); # load input + &movups ($inout1,&QWP(16*1,$inp)); + &lea ($inp,&DWP(16*2,$inp)); + &xorps ($inout0,$inout3); # input^=tweak + &xorps ($inout1,$inout4); + + &call ("_aesni_encrypt2"); + + &xorps ($inout0,$inout3); # output^=tweak + &xorps ($inout1,$inout4); + &movups (&QWP(16*0,$out),$inout0); # write output + &movups (&QWP(16*1,$out),$inout1); + &lea ($out,&DWP(16*2,$out)); + + &movdqa ($tweak,$inout4); # last tweak + &jmp (&label("xts_enc_done")); + +&set_label("xts_enc_three",16); + &movaps ($inout5,$tweak); # put aside last tweak + &movups ($inout0,&QWP(16*0,$inp)); # load input + &movups ($inout1,&QWP(16*1,$inp)); + &movups ($inout2,&QWP(16*2,$inp)); + &lea ($inp,&DWP(16*3,$inp)); + &xorps ($inout0,$inout3); # input^=tweak + &xorps ($inout1,$inout4); + &xorps ($inout2,$inout5); + + &call ("_aesni_encrypt3"); + + &xorps ($inout0,$inout3); # output^=tweak + &xorps ($inout1,$inout4); + &xorps ($inout2,$inout5); + &movups (&QWP(16*0,$out),$inout0); # write output + &movups (&QWP(16*1,$out),$inout1); + &movups (&QWP(16*2,$out),$inout2); + &lea ($out,&DWP(16*3,$out)); + + &movdqa ($tweak,$inout5); # last tweak + &jmp (&label("xts_enc_done")); + +&set_label("xts_enc_four",16); + &movaps ($inout4,$tweak); # put aside last tweak + + &movups ($inout0,&QWP(16*0,$inp)); # load input + &movups ($inout1,&QWP(16*1,$inp)); + &movups ($inout2,&QWP(16*2,$inp)); + &xorps ($inout0,&QWP(16*0,"esp")); # input^=tweak + &movups ($inout3,&QWP(16*3,$inp)); + &lea ($inp,&DWP(16*4,$inp)); + &xorps ($inout1,&QWP(16*1,"esp")); + &xorps ($inout2,$inout5); + &xorps ($inout3,$inout4); + + &call ("_aesni_encrypt4"); + + &xorps ($inout0,&QWP(16*0,"esp")); # output^=tweak + &xorps ($inout1,&QWP(16*1,"esp")); + &xorps ($inout2,$inout5); + &movups (&QWP(16*0,$out),$inout0); # write output + &xorps ($inout3,$inout4); + &movups (&QWP(16*1,$out),$inout1); + &movups (&QWP(16*2,$out),$inout2); + &movups (&QWP(16*3,$out),$inout3); + &lea ($out,&DWP(16*4,$out)); + + &movdqa ($tweak,$inout4); # last tweak + &jmp (&label("xts_enc_done")); + +&set_label("xts_enc_done6x",16); # $tweak is pre-calculated + &mov ($len,&DWP(16*7+0,"esp")); # restore original $len + &and ($len,15); + &jz (&label("xts_enc_ret")); + &movdqa ($inout3,$tweak); + &mov (&DWP(16*7+0,"esp"),$len); # save $len%16 + &jmp (&label("xts_enc_steal")); + +&set_label("xts_enc_done",16); + &mov ($len,&DWP(16*7+0,"esp")); # restore original $len + &pxor ($twtmp,$twtmp); + &and ($len,15); + &jz (&label("xts_enc_ret")); + + &pcmpgtd($twtmp,$tweak); # broadcast upper bits + &mov (&DWP(16*7+0,"esp"),$len); # save $len%16 + &pshufd ($inout3,$twtmp,0x13); + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &pand ($inout3,&QWP(16*6,"esp")); # isolate carry and residue + &pxor ($inout3,$tweak); + +&set_label("xts_enc_steal"); + &movz ($rounds,&BP(0,$inp)); + &movz ($key,&BP(-16,$out)); + &lea ($inp,&DWP(1,$inp)); + &mov (&BP(-16,$out),&LB($rounds)); + &mov (&BP(0,$out),&LB($key)); + &lea ($out,&DWP(1,$out)); + &sub ($len,1); + &jnz (&label("xts_enc_steal")); + + &sub ($out,&DWP(16*7+0,"esp")); # rewind $out + &mov ($key,$key_); # restore $key + &mov ($rounds,$rounds_); # restore $rounds + + &movups ($inout0,&QWP(-16,$out)); # load input + &xorps ($inout0,$inout3); # input^=tweak + if ($inline) + { &aesni_inline_generate1("enc"); } + else + { &call ("_aesni_encrypt1"); } + &xorps ($inout0,$inout3); # output^=tweak + &movups (&QWP(-16,$out),$inout0); # write output + +&set_label("xts_enc_ret"); + &pxor ("xmm0","xmm0"); # clear register bank + &pxor ("xmm1","xmm1"); + &pxor ("xmm2","xmm2"); + &movdqa (&QWP(16*0,"esp"),"xmm0"); # clear stack + &pxor ("xmm3","xmm3"); + &movdqa (&QWP(16*1,"esp"),"xmm0"); + &pxor ("xmm4","xmm4"); + &movdqa (&QWP(16*2,"esp"),"xmm0"); + &pxor ("xmm5","xmm5"); + &movdqa (&QWP(16*3,"esp"),"xmm0"); + &pxor ("xmm6","xmm6"); + &movdqa (&QWP(16*4,"esp"),"xmm0"); + &pxor ("xmm7","xmm7"); + &movdqa (&QWP(16*5,"esp"),"xmm0"); + &mov ("esp",&DWP(16*7+4,"esp")); # restore %esp +&function_end("aesni_xts_encrypt"); + +&function_begin("aesni_xts_decrypt"); + &mov ($key,&wparam(4)); # key2 + &mov ($inp,&wparam(5)); # clear-text tweak + + &mov ($rounds,&DWP(240,$key)); # key2->rounds + &movups ($inout0,&QWP(0,$inp)); + if ($inline) + { &aesni_inline_generate1("enc"); } + else + { &call ("_aesni_encrypt1"); } + + &mov ($inp,&wparam(0)); + &mov ($out,&wparam(1)); + &mov ($len,&wparam(2)); + &mov ($key,&wparam(3)); # key1 + + &mov ($key_,"esp"); + &sub ("esp",16*7+8); + &and ("esp",-16); # align stack + + &xor ($rounds_,$rounds_); # if(len%16) len-=16; + &test ($len,15); + &setnz (&LB($rounds_)); + &shl ($rounds_,4); + &sub ($len,$rounds_); + + &mov (&DWP(16*6+0,"esp"),0x87); # compose the magic constant + &mov (&DWP(16*6+4,"esp"),0); + &mov (&DWP(16*6+8,"esp"),1); + &mov (&DWP(16*6+12,"esp"),0); + &mov (&DWP(16*7+0,"esp"),$len); # save original $len + &mov (&DWP(16*7+4,"esp"),$key_); # save original %esp + + &mov ($rounds,&DWP(240,$key)); # key1->rounds + &mov ($key_,$key); # backup $key + &mov ($rounds_,$rounds); # backup $rounds + + &movdqa ($tweak,$inout0); + &pxor ($twtmp,$twtmp); + &movdqa ($twmask,&QWP(6*16,"esp")); # 0x0...010...87 + &pcmpgtd($twtmp,$tweak); # broadcast upper bits + + &and ($len,-16); + &sub ($len,16*6); + &jc (&label("xts_dec_short")); + + &shl ($rounds,4); + &mov ($rounds_,16); + &sub ($rounds_,$rounds); + &lea ($key,&DWP(32,$key,$rounds)); + &jmp (&label("xts_dec_loop6")); + +&set_label("xts_dec_loop6",16); + for ($i=0;$i<4;$i++) { + &pshufd ($twres,$twtmp,0x13); + &pxor ($twtmp,$twtmp); + &movdqa (&QWP(16*$i,"esp"),$tweak); + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &pand ($twres,$twmask); # isolate carry and residue + &pcmpgtd ($twtmp,$tweak); # broadcast upper bits + &pxor ($tweak,$twres); + } + &pshufd ($inout5,$twtmp,0x13); + &movdqa (&QWP(16*$i++,"esp"),$tweak); + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &$movekey ($rndkey0,&QWP(0,$key_)); + &pand ($inout5,$twmask); # isolate carry and residue + &movups ($inout0,&QWP(0,$inp)); # load input + &pxor ($inout5,$tweak); + + # inline _aesni_encrypt6 prologue and flip xor with tweak and key[0] + &mov ($rounds,$rounds_); + &movdqu ($inout1,&QWP(16*1,$inp)); + &xorps ($inout0,$rndkey0); # input^=rndkey[0] + &movdqu ($inout2,&QWP(16*2,$inp)); + &pxor ($inout1,$rndkey0); + &movdqu ($inout3,&QWP(16*3,$inp)); + &pxor ($inout2,$rndkey0); + &movdqu ($inout4,&QWP(16*4,$inp)); + &pxor ($inout3,$rndkey0); + &movdqu ($rndkey1,&QWP(16*5,$inp)); + &pxor ($inout4,$rndkey0); + &lea ($inp,&DWP(16*6,$inp)); + &pxor ($inout0,&QWP(16*0,"esp")); # input^=tweak + &movdqa (&QWP(16*$i,"esp"),$inout5); # save last tweak + &pxor ($inout5,$rndkey1); + + &$movekey ($rndkey1,&QWP(16,$key_)); + &pxor ($inout1,&QWP(16*1,"esp")); + &pxor ($inout2,&QWP(16*2,"esp")); + &aesdec ($inout0,$rndkey1); + &pxor ($inout3,&QWP(16*3,"esp")); + &pxor ($inout4,&QWP(16*4,"esp")); + &aesdec ($inout1,$rndkey1); + &pxor ($inout5,$rndkey0); + &$movekey ($rndkey0,&QWP(32,$key_)); + &aesdec ($inout2,$rndkey1); + &aesdec ($inout3,$rndkey1); + &aesdec ($inout4,$rndkey1); + &aesdec ($inout5,$rndkey1); + &call (&label("_aesni_decrypt6_enter")); + + &movdqa ($tweak,&QWP(16*5,"esp")); # last tweak + &pxor ($twtmp,$twtmp); + &xorps ($inout0,&QWP(16*0,"esp")); # output^=tweak + &pcmpgtd ($twtmp,$tweak); # broadcast upper bits + &xorps ($inout1,&QWP(16*1,"esp")); + &movups (&QWP(16*0,$out),$inout0); # write output + &xorps ($inout2,&QWP(16*2,"esp")); + &movups (&QWP(16*1,$out),$inout1); + &xorps ($inout3,&QWP(16*3,"esp")); + &movups (&QWP(16*2,$out),$inout2); + &xorps ($inout4,&QWP(16*4,"esp")); + &movups (&QWP(16*3,$out),$inout3); + &xorps ($inout5,$tweak); + &movups (&QWP(16*4,$out),$inout4); + &pshufd ($twres,$twtmp,0x13); + &movups (&QWP(16*5,$out),$inout5); + &lea ($out,&DWP(16*6,$out)); + &movdqa ($twmask,&QWP(16*6,"esp")); # 0x0...010...87 + + &pxor ($twtmp,$twtmp); + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &pand ($twres,$twmask); # isolate carry and residue + &pcmpgtd($twtmp,$tweak); # broadcast upper bits + &pxor ($tweak,$twres); + + &sub ($len,16*6); + &jnc (&label("xts_dec_loop6")); + + &mov ($rounds,&DWP(240,$key_)); # restore $rounds + &mov ($key,$key_); # restore $key + &mov ($rounds_,$rounds); + +&set_label("xts_dec_short"); + &add ($len,16*6); + &jz (&label("xts_dec_done6x")); + + &movdqa ($inout3,$tweak); # put aside previous tweak + &cmp ($len,0x20); + &jb (&label("xts_dec_one")); + + &pshufd ($twres,$twtmp,0x13); + &pxor ($twtmp,$twtmp); + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &pand ($twres,$twmask); # isolate carry and residue + &pcmpgtd($twtmp,$tweak); # broadcast upper bits + &pxor ($tweak,$twres); + &je (&label("xts_dec_two")); + + &pshufd ($twres,$twtmp,0x13); + &pxor ($twtmp,$twtmp); + &movdqa ($inout4,$tweak); # put aside previous tweak + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &pand ($twres,$twmask); # isolate carry and residue + &pcmpgtd($twtmp,$tweak); # broadcast upper bits + &pxor ($tweak,$twres); + &cmp ($len,0x40); + &jb (&label("xts_dec_three")); + + &pshufd ($twres,$twtmp,0x13); + &pxor ($twtmp,$twtmp); + &movdqa ($inout5,$tweak); # put aside previous tweak + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &pand ($twres,$twmask); # isolate carry and residue + &pcmpgtd($twtmp,$tweak); # broadcast upper bits + &pxor ($tweak,$twres); + &movdqa (&QWP(16*0,"esp"),$inout3); + &movdqa (&QWP(16*1,"esp"),$inout4); + &je (&label("xts_dec_four")); + + &movdqa (&QWP(16*2,"esp"),$inout5); + &pshufd ($inout5,$twtmp,0x13); + &movdqa (&QWP(16*3,"esp"),$tweak); + &paddq ($tweak,$tweak); # &psllq($inout0,1); + &pand ($inout5,$twmask); # isolate carry and residue + &pxor ($inout5,$tweak); + + &movdqu ($inout0,&QWP(16*0,$inp)); # load input + &movdqu ($inout1,&QWP(16*1,$inp)); + &movdqu ($inout2,&QWP(16*2,$inp)); + &pxor ($inout0,&QWP(16*0,"esp")); # input^=tweak + &movdqu ($inout3,&QWP(16*3,$inp)); + &pxor ($inout1,&QWP(16*1,"esp")); + &movdqu ($inout4,&QWP(16*4,$inp)); + &pxor ($inout2,&QWP(16*2,"esp")); + &lea ($inp,&DWP(16*5,$inp)); + &pxor ($inout3,&QWP(16*3,"esp")); + &movdqa (&QWP(16*4,"esp"),$inout5); # save last tweak + &pxor ($inout4,$inout5); + + &call ("_aesni_decrypt6"); + + &movaps ($tweak,&QWP(16*4,"esp")); # last tweak + &xorps ($inout0,&QWP(16*0,"esp")); # output^=tweak + &xorps ($inout1,&QWP(16*1,"esp")); + &xorps ($inout2,&QWP(16*2,"esp")); + &movups (&QWP(16*0,$out),$inout0); # write output + &xorps ($inout3,&QWP(16*3,"esp")); + &movups (&QWP(16*1,$out),$inout1); + &xorps ($inout4,$tweak); + &movups (&QWP(16*2,$out),$inout2); + &movups (&QWP(16*3,$out),$inout3); + &movups (&QWP(16*4,$out),$inout4); + &lea ($out,&DWP(16*5,$out)); + &jmp (&label("xts_dec_done")); + +&set_label("xts_dec_one",16); + &movups ($inout0,&QWP(16*0,$inp)); # load input + &lea ($inp,&DWP(16*1,$inp)); + &xorps ($inout0,$inout3); # input^=tweak + if ($inline) + { &aesni_inline_generate1("dec"); } + else + { &call ("_aesni_decrypt1"); } + &xorps ($inout0,$inout3); # output^=tweak + &movups (&QWP(16*0,$out),$inout0); # write output + &lea ($out,&DWP(16*1,$out)); + + &movdqa ($tweak,$inout3); # last tweak + &jmp (&label("xts_dec_done")); + +&set_label("xts_dec_two",16); + &movaps ($inout4,$tweak); # put aside last tweak + + &movups ($inout0,&QWP(16*0,$inp)); # load input + &movups ($inout1,&QWP(16*1,$inp)); + &lea ($inp,&DWP(16*2,$inp)); + &xorps ($inout0,$inout3); # input^=tweak + &xorps ($inout1,$inout4); + + &call ("_aesni_decrypt2"); + + &xorps ($inout0,$inout3); # output^=tweak + &xorps ($inout1,$inout4); + &movups (&QWP(16*0,$out),$inout0); # write output + &movups (&QWP(16*1,$out),$inout1); + &lea ($out,&DWP(16*2,$out)); + + &movdqa ($tweak,$inout4); # last tweak + &jmp (&label("xts_dec_done")); + +&set_label("xts_dec_three",16); + &movaps ($inout5,$tweak); # put aside last tweak + &movups ($inout0,&QWP(16*0,$inp)); # load input + &movups ($inout1,&QWP(16*1,$inp)); + &movups ($inout2,&QWP(16*2,$inp)); + &lea ($inp,&DWP(16*3,$inp)); + &xorps ($inout0,$inout3); # input^=tweak + &xorps ($inout1,$inout4); + &xorps ($inout2,$inout5); + + &call ("_aesni_decrypt3"); + + &xorps ($inout0,$inout3); # output^=tweak + &xorps ($inout1,$inout4); + &xorps ($inout2,$inout5); + &movups (&QWP(16*0,$out),$inout0); # write output + &movups (&QWP(16*1,$out),$inout1); + &movups (&QWP(16*2,$out),$inout2); + &lea ($out,&DWP(16*3,$out)); + + &movdqa ($tweak,$inout5); # last tweak + &jmp (&label("xts_dec_done")); + +&set_label("xts_dec_four",16); + &movaps ($inout4,$tweak); # put aside last tweak + + &movups ($inout0,&QWP(16*0,$inp)); # load input + &movups ($inout1,&QWP(16*1,$inp)); + &movups ($inout2,&QWP(16*2,$inp)); + &xorps ($inout0,&QWP(16*0,"esp")); # input^=tweak + &movups ($inout3,&QWP(16*3,$inp)); + &lea ($inp,&DWP(16*4,$inp)); + &xorps ($inout1,&QWP(16*1,"esp")); + &xorps ($inout2,$inout5); + &xorps ($inout3,$inout4); + + &call ("_aesni_decrypt4"); + + &xorps ($inout0,&QWP(16*0,"esp")); # output^=tweak + &xorps ($inout1,&QWP(16*1,"esp")); + &xorps ($inout2,$inout5); + &movups (&QWP(16*0,$out),$inout0); # write output + &xorps ($inout3,$inout4); + &movups (&QWP(16*1,$out),$inout1); + &movups (&QWP(16*2,$out),$inout2); + &movups (&QWP(16*3,$out),$inout3); + &lea ($out,&DWP(16*4,$out)); + + &movdqa ($tweak,$inout4); # last tweak + &jmp (&label("xts_dec_done")); + +&set_label("xts_dec_done6x",16); # $tweak is pre-calculated + &mov ($len,&DWP(16*7+0,"esp")); # restore original $len + &and ($len,15); + &jz (&label("xts_dec_ret")); + &mov (&DWP(16*7+0,"esp"),$len); # save $len%16 + &jmp (&label("xts_dec_only_one_more")); + +&set_label("xts_dec_done",16); + &mov ($len,&DWP(16*7+0,"esp")); # restore original $len + &pxor ($twtmp,$twtmp); + &and ($len,15); + &jz (&label("xts_dec_ret")); + + &pcmpgtd($twtmp,$tweak); # broadcast upper bits + &mov (&DWP(16*7+0,"esp"),$len); # save $len%16 + &pshufd ($twres,$twtmp,0x13); + &pxor ($twtmp,$twtmp); + &movdqa ($twmask,&QWP(16*6,"esp")); + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &pand ($twres,$twmask); # isolate carry and residue + &pcmpgtd($twtmp,$tweak); # broadcast upper bits + &pxor ($tweak,$twres); + +&set_label("xts_dec_only_one_more"); + &pshufd ($inout3,$twtmp,0x13); + &movdqa ($inout4,$tweak); # put aside previous tweak + &paddq ($tweak,$tweak); # &psllq($tweak,1); + &pand ($inout3,$twmask); # isolate carry and residue + &pxor ($inout3,$tweak); + + &mov ($key,$key_); # restore $key + &mov ($rounds,$rounds_); # restore $rounds + + &movups ($inout0,&QWP(0,$inp)); # load input + &xorps ($inout0,$inout3); # input^=tweak + if ($inline) + { &aesni_inline_generate1("dec"); } + else + { &call ("_aesni_decrypt1"); } + &xorps ($inout0,$inout3); # output^=tweak + &movups (&QWP(0,$out),$inout0); # write output + +&set_label("xts_dec_steal"); + &movz ($rounds,&BP(16,$inp)); + &movz ($key,&BP(0,$out)); + &lea ($inp,&DWP(1,$inp)); + &mov (&BP(0,$out),&LB($rounds)); + &mov (&BP(16,$out),&LB($key)); + &lea ($out,&DWP(1,$out)); + &sub ($len,1); + &jnz (&label("xts_dec_steal")); + + &sub ($out,&DWP(16*7+0,"esp")); # rewind $out + &mov ($key,$key_); # restore $key + &mov ($rounds,$rounds_); # restore $rounds + + &movups ($inout0,&QWP(0,$out)); # load input + &xorps ($inout0,$inout4); # input^=tweak + if ($inline) + { &aesni_inline_generate1("dec"); } + else + { &call ("_aesni_decrypt1"); } + &xorps ($inout0,$inout4); # output^=tweak + &movups (&QWP(0,$out),$inout0); # write output + +&set_label("xts_dec_ret"); + &pxor ("xmm0","xmm0"); # clear register bank + &pxor ("xmm1","xmm1"); + &pxor ("xmm2","xmm2"); + &movdqa (&QWP(16*0,"esp"),"xmm0"); # clear stack + &pxor ("xmm3","xmm3"); + &movdqa (&QWP(16*1,"esp"),"xmm0"); + &pxor ("xmm4","xmm4"); + &movdqa (&QWP(16*2,"esp"),"xmm0"); + &pxor ("xmm5","xmm5"); + &movdqa (&QWP(16*3,"esp"),"xmm0"); + &pxor ("xmm6","xmm6"); + &movdqa (&QWP(16*4,"esp"),"xmm0"); + &pxor ("xmm7","xmm7"); + &movdqa (&QWP(16*5,"esp"),"xmm0"); + &mov ("esp",&DWP(16*7+4,"esp")); # restore %esp +&function_end("aesni_xts_decrypt"); +} + +###################################################################### +# void aesni_ocb_[en|de]crypt(const char *inp, char *out, size_t blocks, +# const AES_KEY *key, unsigned int start_block_num, +# unsigned char offset_i[16], const unsigned char L_[][16], +# unsigned char checksum[16]); +# +{ +# offsets within stack frame +my $checksum = 16*6; +my ($key_off,$rounds_off,$out_off,$end_off,$esp_off)=map(16*7+4*$_,(0..4)); + +# reassigned registers +my ($l_,$block,$i1,$i3,$i5) = ($rounds_,$key_,$rounds,$len,$out); +# $l_, $blocks, $inp, $key are permanently allocated in registers; +# remaining non-volatile ones are offloaded to stack, which even +# stay invariant after written to stack. + +&function_begin("aesni_ocb_encrypt"); + &mov ($rounds,&wparam(5)); # &offset_i + &mov ($rounds_,&wparam(7)); # &checksum + + &mov ($inp,&wparam(0)); + &mov ($out,&wparam(1)); + &mov ($len,&wparam(2)); + &mov ($key,&wparam(3)); + &movdqu ($rndkey0,&QWP(0,$rounds)); # load offset_i + &mov ($block,&wparam(4)); # start_block_num + &movdqu ($rndkey1,&QWP(0,$rounds_)); # load checksum + &mov ($l_,&wparam(6)); # L_ + + &mov ($rounds,"esp"); + &sub ("esp",$esp_off+4); # alloca + &and ("esp",-16); # align stack + + &sub ($out,$inp); + &shl ($len,4); + &lea ($len,&DWP(-16*6,$inp,$len)); # end of input - 16*6 + &mov (&DWP($out_off,"esp"),$out); + &mov (&DWP($end_off,"esp"),$len); + &mov (&DWP($esp_off,"esp"),$rounds); + + &mov ($rounds,&DWP(240,$key)); + + &test ($block,1); + &jnz (&label("odd")); + + &bsf ($i3,$block); + &add ($block,1); + &shl ($i3,4); + &movdqu ($inout5,&QWP(0,$l_,$i3)); + &mov ($i3,$key); # put aside key + + &movdqu ($inout0,&QWP(16*0,$inp)); # load input + &lea ($inp,&DWP(16,$inp)); + + &pxor ($inout5,$rndkey0); # ^ last offset_i + &pxor ($rndkey1,$inout0); # checksum + &pxor ($inout0,$inout5); # ^ offset_i + + &movdqa ($inout4,$rndkey1); + if ($inline) + { &aesni_inline_generate1("enc"); } + else + { &call ("_aesni_encrypt1"); } + + &xorps ($inout0,$inout5); # ^ offset_i + &movdqa ($rndkey0,$inout5); # pass last offset_i + &movdqa ($rndkey1,$inout4); # pass the checksum + + &movups (&QWP(-16,$out,$inp),$inout0); # store output + + &mov ($rounds,&DWP(240,$i3)); + &mov ($key,$i3); # restore key + &mov ($len,&DWP($end_off,"esp")); + +&set_label("odd"); + &shl ($rounds,4); + &mov ($out,16); + &sub ($out,$rounds); # twisted rounds + &mov (&DWP($key_off,"esp"),$key); + &lea ($key,&DWP(32,$key,$rounds)); # end of key schedule + &mov (&DWP($rounds_off,"esp"),$out); + + &cmp ($inp,$len); + &ja (&label("short")); + &jmp (&label("grandloop")); + +&set_label("grandloop",32); + &lea ($i1,&DWP(1,$block)); + &lea ($i3,&DWP(3,$block)); + &lea ($i5,&DWP(5,$block)); + &add ($block,6); + &bsf ($i1,$i1); + &bsf ($i3,$i3); + &bsf ($i5,$i5); + &shl ($i1,4); + &shl ($i3,4); + &shl ($i5,4); + &movdqu ($inout0,&QWP(0,$l_)); + &movdqu ($inout1,&QWP(0,$l_,$i1)); + &mov ($rounds,&DWP($rounds_off,"esp")); + &movdqa ($inout2,$inout0); + &movdqu ($inout3,&QWP(0,$l_,$i3)); + &movdqa ($inout4,$inout0); + &movdqu ($inout5,&QWP(0,$l_,$i5)); + + &pxor ($inout0,$rndkey0); # ^ last offset_i + &pxor ($inout1,$inout0); + &movdqa (&QWP(16*0,"esp"),$inout0); + &pxor ($inout2,$inout1); + &movdqa (&QWP(16*1,"esp"),$inout1); + &pxor ($inout3,$inout2); + &movdqa (&QWP(16*2,"esp"),$inout2); + &pxor ($inout4,$inout3); + &movdqa (&QWP(16*3,"esp"),$inout3); + &pxor ($inout5,$inout4); + &movdqa (&QWP(16*4,"esp"),$inout4); + &movdqa (&QWP(16*5,"esp"),$inout5); + + &$movekey ($rndkey0,&QWP(-48,$key,$rounds)); + &movdqu ($inout0,&QWP(16*0,$inp)); # load input + &movdqu ($inout1,&QWP(16*1,$inp)); + &movdqu ($inout2,&QWP(16*2,$inp)); + &movdqu ($inout3,&QWP(16*3,$inp)); + &movdqu ($inout4,&QWP(16*4,$inp)); + &movdqu ($inout5,&QWP(16*5,$inp)); + &lea ($inp,&DWP(16*6,$inp)); + + &pxor ($rndkey1,$inout0); # checksum + &pxor ($inout0,$rndkey0); # ^ roundkey[0] + &pxor ($rndkey1,$inout1); + &pxor ($inout1,$rndkey0); + &pxor ($rndkey1,$inout2); + &pxor ($inout2,$rndkey0); + &pxor ($rndkey1,$inout3); + &pxor ($inout3,$rndkey0); + &pxor ($rndkey1,$inout4); + &pxor ($inout4,$rndkey0); + &pxor ($rndkey1,$inout5); + &pxor ($inout5,$rndkey0); + &movdqa (&QWP($checksum,"esp"),$rndkey1); + + &$movekey ($rndkey1,&QWP(-32,$key,$rounds)); + &pxor ($inout0,&QWP(16*0,"esp")); # ^ offset_i + &pxor ($inout1,&QWP(16*1,"esp")); + &pxor ($inout2,&QWP(16*2,"esp")); + &pxor ($inout3,&QWP(16*3,"esp")); + &pxor ($inout4,&QWP(16*4,"esp")); + &pxor ($inout5,&QWP(16*5,"esp")); + + &$movekey ($rndkey0,&QWP(-16,$key,$rounds)); + &aesenc ($inout0,$rndkey1); + &aesenc ($inout1,$rndkey1); + &aesenc ($inout2,$rndkey1); + &aesenc ($inout3,$rndkey1); + &aesenc ($inout4,$rndkey1); + &aesenc ($inout5,$rndkey1); + + &mov ($out,&DWP($out_off,"esp")); + &mov ($len,&DWP($end_off,"esp")); + &call ("_aesni_encrypt6_enter"); + + &movdqa ($rndkey0,&QWP(16*5,"esp")); # pass last offset_i + &pxor ($inout0,&QWP(16*0,"esp")); # ^ offset_i + &pxor ($inout1,&QWP(16*1,"esp")); + &pxor ($inout2,&QWP(16*2,"esp")); + &pxor ($inout3,&QWP(16*3,"esp")); + &pxor ($inout4,&QWP(16*4,"esp")); + &pxor ($inout5,$rndkey0); + &movdqa ($rndkey1,&QWP($checksum,"esp"));# pass the checksum + + &movdqu (&QWP(-16*6,$out,$inp),$inout0);# store output + &movdqu (&QWP(-16*5,$out,$inp),$inout1); + &movdqu (&QWP(-16*4,$out,$inp),$inout2); + &movdqu (&QWP(-16*3,$out,$inp),$inout3); + &movdqu (&QWP(-16*2,$out,$inp),$inout4); + &movdqu (&QWP(-16*1,$out,$inp),$inout5); + &cmp ($inp,$len); # done yet? + &jb (&label("grandloop")); + +&set_label("short"); + &add ($len,16*6); + &sub ($len,$inp); + &jz (&label("done")); + + &cmp ($len,16*2); + &jb (&label("one")); + &je (&label("two")); + + &cmp ($len,16*4); + &jb (&label("three")); + &je (&label("four")); + + &lea ($i1,&DWP(1,$block)); + &lea ($i3,&DWP(3,$block)); + &bsf ($i1,$i1); + &bsf ($i3,$i3); + &shl ($i1,4); + &shl ($i3,4); + &movdqu ($inout0,&QWP(0,$l_)); + &movdqu ($inout1,&QWP(0,$l_,$i1)); + &mov ($rounds,&DWP($rounds_off,"esp")); + &movdqa ($inout2,$inout0); + &movdqu ($inout3,&QWP(0,$l_,$i3)); + &movdqa ($inout4,$inout0); + + &pxor ($inout0,$rndkey0); # ^ last offset_i + &pxor ($inout1,$inout0); + &movdqa (&QWP(16*0,"esp"),$inout0); + &pxor ($inout2,$inout1); + &movdqa (&QWP(16*1,"esp"),$inout1); + &pxor ($inout3,$inout2); + &movdqa (&QWP(16*2,"esp"),$inout2); + &pxor ($inout4,$inout3); + &movdqa (&QWP(16*3,"esp"),$inout3); + &pxor ($inout5,$inout4); + &movdqa (&QWP(16*4,"esp"),$inout4); + + &$movekey ($rndkey0,&QWP(-48,$key,$rounds)); + &movdqu ($inout0,&QWP(16*0,$inp)); # load input + &movdqu ($inout1,&QWP(16*1,$inp)); + &movdqu ($inout2,&QWP(16*2,$inp)); + &movdqu ($inout3,&QWP(16*3,$inp)); + &movdqu ($inout4,&QWP(16*4,$inp)); + &pxor ($inout5,$inout5); + + &pxor ($rndkey1,$inout0); # checksum + &pxor ($inout0,$rndkey0); # ^ roundkey[0] + &pxor ($rndkey1,$inout1); + &pxor ($inout1,$rndkey0); + &pxor ($rndkey1,$inout2); + &pxor ($inout2,$rndkey0); + &pxor ($rndkey1,$inout3); + &pxor ($inout3,$rndkey0); + &pxor ($rndkey1,$inout4); + &pxor ($inout4,$rndkey0); + &movdqa (&QWP($checksum,"esp"),$rndkey1); + + &$movekey ($rndkey1,&QWP(-32,$key,$rounds)); + &pxor ($inout0,&QWP(16*0,"esp")); # ^ offset_i + &pxor ($inout1,&QWP(16*1,"esp")); + &pxor ($inout2,&QWP(16*2,"esp")); + &pxor ($inout3,&QWP(16*3,"esp")); + &pxor ($inout4,&QWP(16*4,"esp")); + + &$movekey ($rndkey0,&QWP(-16,$key,$rounds)); + &aesenc ($inout0,$rndkey1); + &aesenc ($inout1,$rndkey1); + &aesenc ($inout2,$rndkey1); + &aesenc ($inout3,$rndkey1); + &aesenc ($inout4,$rndkey1); + &aesenc ($inout5,$rndkey1); + + &mov ($out,&DWP($out_off,"esp")); + &call ("_aesni_encrypt6_enter"); + + &movdqa ($rndkey0,&QWP(16*4,"esp")); # pass last offset_i + &pxor ($inout0,&QWP(16*0,"esp")); # ^ offset_i + &pxor ($inout1,&QWP(16*1,"esp")); + &pxor ($inout2,&QWP(16*2,"esp")); + &pxor ($inout3,&QWP(16*3,"esp")); + &pxor ($inout4,$rndkey0); + &movdqa ($rndkey1,&QWP($checksum,"esp"));# pass the checksum + + &movdqu (&QWP(16*0,$out,$inp),$inout0); # store output + &movdqu (&QWP(16*1,$out,$inp),$inout1); + &movdqu (&QWP(16*2,$out,$inp),$inout2); + &movdqu (&QWP(16*3,$out,$inp),$inout3); + &movdqu (&QWP(16*4,$out,$inp),$inout4); + + &jmp (&label("done")); + +&set_label("one",16); + &movdqu ($inout5,&QWP(0,$l_)); + &mov ($key,&DWP($key_off,"esp")); # restore key + + &movdqu ($inout0,&QWP(16*0,$inp)); # load input + &mov ($rounds,&DWP(240,$key)); + + &pxor ($inout5,$rndkey0); # ^ last offset_i + &pxor ($rndkey1,$inout0); # checksum + &pxor ($inout0,$inout5); # ^ offset_i + + &movdqa ($inout4,$rndkey1); + &mov ($out,&DWP($out_off,"esp")); + if ($inline) + { &aesni_inline_generate1("enc"); } + else + { &call ("_aesni_encrypt1"); } + + &xorps ($inout0,$inout5); # ^ offset_i + &movdqa ($rndkey0,$inout5); # pass last offset_i + &movdqa ($rndkey1,$inout4); # pass the checksum + &movups (&QWP(0,$out,$inp),$inout0); + + &jmp (&label("done")); + +&set_label("two",16); + &lea ($i1,&DWP(1,$block)); + &mov ($key,&DWP($key_off,"esp")); # restore key + &bsf ($i1,$i1); + &shl ($i1,4); + &movdqu ($inout4,&QWP(0,$l_)); + &movdqu ($inout5,&QWP(0,$l_,$i1)); + + &movdqu ($inout0,&QWP(16*0,$inp)); # load input + &movdqu ($inout1,&QWP(16*1,$inp)); + &mov ($rounds,&DWP(240,$key)); + + &pxor ($inout4,$rndkey0); # ^ last offset_i + &pxor ($inout5,$inout4); + + &pxor ($rndkey1,$inout0); # checksum + &pxor ($inout0,$inout4); # ^ offset_i + &pxor ($rndkey1,$inout1); + &pxor ($inout1,$inout5); + + &movdqa ($inout3,$rndkey1) + &mov ($out,&DWP($out_off,"esp")); + &call ("_aesni_encrypt2"); + + &xorps ($inout0,$inout4); # ^ offset_i + &xorps ($inout1,$inout5); + &movdqa ($rndkey0,$inout5); # pass last offset_i + &movdqa ($rndkey1,$inout3); # pass the checksum + &movups (&QWP(16*0,$out,$inp),$inout0); # store output + &movups (&QWP(16*1,$out,$inp),$inout1); + + &jmp (&label("done")); + +&set_label("three",16); + &lea ($i1,&DWP(1,$block)); + &mov ($key,&DWP($key_off,"esp")); # restore key + &bsf ($i1,$i1); + &shl ($i1,4); + &movdqu ($inout3,&QWP(0,$l_)); + &movdqu ($inout4,&QWP(0,$l_,$i1)); + &movdqa ($inout5,$inout3); + + &movdqu ($inout0,&QWP(16*0,$inp)); # load input + &movdqu ($inout1,&QWP(16*1,$inp)); + &movdqu ($inout2,&QWP(16*2,$inp)); + &mov ($rounds,&DWP(240,$key)); + + &pxor ($inout3,$rndkey0); # ^ last offset_i + &pxor ($inout4,$inout3); + &pxor ($inout5,$inout4); + + &pxor ($rndkey1,$inout0); # checksum + &pxor ($inout0,$inout3); # ^ offset_i + &pxor ($rndkey1,$inout1); + &pxor ($inout1,$inout4); + &pxor ($rndkey1,$inout2); + &pxor ($inout2,$inout5); + + &movdqa (&QWP($checksum,"esp"),$rndkey1); + &mov ($out,&DWP($out_off,"esp")); + &call ("_aesni_encrypt3"); + + &xorps ($inout0,$inout3); # ^ offset_i + &xorps ($inout1,$inout4); + &xorps ($inout2,$inout5); + &movdqa ($rndkey0,$inout5); # pass last offset_i + &movdqa ($rndkey1,&QWP($checksum,"esp"));# pass the checksum + &movups (&QWP(16*0,$out,$inp),$inout0); # store output + &movups (&QWP(16*1,$out,$inp),$inout1); + &movups (&QWP(16*2,$out,$inp),$inout2); + + &jmp (&label("done")); + +&set_label("four",16); + &lea ($i1,&DWP(1,$block)); + &lea ($i3,&DWP(3,$block)); + &bsf ($i1,$i1); + &bsf ($i3,$i3); + &mov ($key,&DWP($key_off,"esp")); # restore key + &shl ($i1,4); + &shl ($i3,4); + &movdqu ($inout2,&QWP(0,$l_)); + &movdqu ($inout3,&QWP(0,$l_,$i1)); + &movdqa ($inout4,$inout2); + &movdqu ($inout5,&QWP(0,$l_,$i3)); + + &pxor ($inout2,$rndkey0); # ^ last offset_i + &movdqu ($inout0,&QWP(16*0,$inp)); # load input + &pxor ($inout3,$inout2); + &movdqu ($inout1,&QWP(16*1,$inp)); + &pxor ($inout4,$inout3); + &movdqa (&QWP(16*0,"esp"),$inout2); + &pxor ($inout5,$inout4); + &movdqa (&QWP(16*1,"esp"),$inout3); + &movdqu ($inout2,&QWP(16*2,$inp)); + &movdqu ($inout3,&QWP(16*3,$inp)); + &mov ($rounds,&DWP(240,$key)); + + &pxor ($rndkey1,$inout0); # checksum + &pxor ($inout0,&QWP(16*0,"esp")); # ^ offset_i + &pxor ($rndkey1,$inout1); + &pxor ($inout1,&QWP(16*1,"esp")); + &pxor ($rndkey1,$inout2); + &pxor ($inout2,$inout4); + &pxor ($rndkey1,$inout3); + &pxor ($inout3,$inout5); + + &movdqa (&QWP($checksum,"esp"),$rndkey1) + &mov ($out,&DWP($out_off,"esp")); + &call ("_aesni_encrypt4"); + + &xorps ($inout0,&QWP(16*0,"esp")); # ^ offset_i + &xorps ($inout1,&QWP(16*1,"esp")); + &xorps ($inout2,$inout4); + &movups (&QWP(16*0,$out,$inp),$inout0); # store output + &xorps ($inout3,$inout5); + &movups (&QWP(16*1,$out,$inp),$inout1); + &movdqa ($rndkey0,$inout5); # pass last offset_i + &movups (&QWP(16*2,$out,$inp),$inout2); + &movdqa ($rndkey1,&QWP($checksum,"esp"));# pass the checksum + &movups (&QWP(16*3,$out,$inp),$inout3); + +&set_label("done"); + &mov ($key,&DWP($esp_off,"esp")); + &pxor ($inout0,$inout0); # clear register bank + &pxor ($inout1,$inout1); + &movdqa (&QWP(16*0,"esp"),$inout0); # clear stack + &pxor ($inout2,$inout2); + &movdqa (&QWP(16*1,"esp"),$inout0); + &pxor ($inout3,$inout3); + &movdqa (&QWP(16*2,"esp"),$inout0); + &pxor ($inout4,$inout4); + &movdqa (&QWP(16*3,"esp"),$inout0); + &pxor ($inout5,$inout5); + &movdqa (&QWP(16*4,"esp"),$inout0); + &movdqa (&QWP(16*5,"esp"),$inout0); + &movdqa (&QWP(16*6,"esp"),$inout0); + + &lea ("esp",&DWP(0,$key)); + &mov ($rounds,&wparam(5)); # &offset_i + &mov ($rounds_,&wparam(7)); # &checksum + &movdqu (&QWP(0,$rounds),$rndkey0); + &pxor ($rndkey0,$rndkey0); + &movdqu (&QWP(0,$rounds_),$rndkey1); + &pxor ($rndkey1,$rndkey1); +&function_end("aesni_ocb_encrypt"); + +&function_begin("aesni_ocb_decrypt"); + &mov ($rounds,&wparam(5)); # &offset_i + &mov ($rounds_,&wparam(7)); # &checksum + + &mov ($inp,&wparam(0)); + &mov ($out,&wparam(1)); + &mov ($len,&wparam(2)); + &mov ($key,&wparam(3)); + &movdqu ($rndkey0,&QWP(0,$rounds)); # load offset_i + &mov ($block,&wparam(4)); # start_block_num + &movdqu ($rndkey1,&QWP(0,$rounds_)); # load checksum + &mov ($l_,&wparam(6)); # L_ + + &mov ($rounds,"esp"); + &sub ("esp",$esp_off+4); # alloca + &and ("esp",-16); # align stack + + &sub ($out,$inp); + &shl ($len,4); + &lea ($len,&DWP(-16*6,$inp,$len)); # end of input - 16*6 + &mov (&DWP($out_off,"esp"),$out); + &mov (&DWP($end_off,"esp"),$len); + &mov (&DWP($esp_off,"esp"),$rounds); + + &mov ($rounds,&DWP(240,$key)); + + &test ($block,1); + &jnz (&label("odd")); + + &bsf ($i3,$block); + &add ($block,1); + &shl ($i3,4); + &movdqu ($inout5,&QWP(0,$l_,$i3)); + &mov ($i3,$key); # put aside key + + &movdqu ($inout0,&QWP(16*0,$inp)); # load input + &lea ($inp,&DWP(16,$inp)); + + &pxor ($inout5,$rndkey0); # ^ last offset_i + &pxor ($inout0,$inout5); # ^ offset_i + + &movdqa ($inout4,$rndkey1); + if ($inline) + { &aesni_inline_generate1("dec"); } + else + { &call ("_aesni_decrypt1"); } + + &xorps ($inout0,$inout5); # ^ offset_i + &movaps ($rndkey1,$inout4); # pass the checksum + &movdqa ($rndkey0,$inout5); # pass last offset_i + &xorps ($rndkey1,$inout0); # checksum + &movups (&QWP(-16,$out,$inp),$inout0); # store output + + &mov ($rounds,&DWP(240,$i3)); + &mov ($key,$i3); # restore key + &mov ($len,&DWP($end_off,"esp")); + +&set_label("odd"); + &shl ($rounds,4); + &mov ($out,16); + &sub ($out,$rounds); # twisted rounds + &mov (&DWP($key_off,"esp"),$key); + &lea ($key,&DWP(32,$key,$rounds)); # end of key schedule + &mov (&DWP($rounds_off,"esp"),$out); + + &cmp ($inp,$len); + &ja (&label("short")); + &jmp (&label("grandloop")); + +&set_label("grandloop",32); + &lea ($i1,&DWP(1,$block)); + &lea ($i3,&DWP(3,$block)); + &lea ($i5,&DWP(5,$block)); + &add ($block,6); + &bsf ($i1,$i1); + &bsf ($i3,$i3); + &bsf ($i5,$i5); + &shl ($i1,4); + &shl ($i3,4); + &shl ($i5,4); + &movdqu ($inout0,&QWP(0,$l_)); + &movdqu ($inout1,&QWP(0,$l_,$i1)); + &mov ($rounds,&DWP($rounds_off,"esp")); + &movdqa ($inout2,$inout0); + &movdqu ($inout3,&QWP(0,$l_,$i3)); + &movdqa ($inout4,$inout0); + &movdqu ($inout5,&QWP(0,$l_,$i5)); + + &pxor ($inout0,$rndkey0); # ^ last offset_i + &pxor ($inout1,$inout0); + &movdqa (&QWP(16*0,"esp"),$inout0); + &pxor ($inout2,$inout1); + &movdqa (&QWP(16*1,"esp"),$inout1); + &pxor ($inout3,$inout2); + &movdqa (&QWP(16*2,"esp"),$inout2); + &pxor ($inout4,$inout3); + &movdqa (&QWP(16*3,"esp"),$inout3); + &pxor ($inout5,$inout4); + &movdqa (&QWP(16*4,"esp"),$inout4); + &movdqa (&QWP(16*5,"esp"),$inout5); + + &$movekey ($rndkey0,&QWP(-48,$key,$rounds)); + &movdqu ($inout0,&QWP(16*0,$inp)); # load input + &movdqu ($inout1,&QWP(16*1,$inp)); + &movdqu ($inout2,&QWP(16*2,$inp)); + &movdqu ($inout3,&QWP(16*3,$inp)); + &movdqu ($inout4,&QWP(16*4,$inp)); + &movdqu ($inout5,&QWP(16*5,$inp)); + &lea ($inp,&DWP(16*6,$inp)); + + &movdqa (&QWP($checksum,"esp"),$rndkey1); + &pxor ($inout0,$rndkey0); # ^ roundkey[0] + &pxor ($inout1,$rndkey0); + &pxor ($inout2,$rndkey0); + &pxor ($inout3,$rndkey0); + &pxor ($inout4,$rndkey0); + &pxor ($inout5,$rndkey0); + + &$movekey ($rndkey1,&QWP(-32,$key,$rounds)); + &pxor ($inout0,&QWP(16*0,"esp")); # ^ offset_i + &pxor ($inout1,&QWP(16*1,"esp")); + &pxor ($inout2,&QWP(16*2,"esp")); + &pxor ($inout3,&QWP(16*3,"esp")); + &pxor ($inout4,&QWP(16*4,"esp")); + &pxor ($inout5,&QWP(16*5,"esp")); + + &$movekey ($rndkey0,&QWP(-16,$key,$rounds)); + &aesdec ($inout0,$rndkey1); + &aesdec ($inout1,$rndkey1); + &aesdec ($inout2,$rndkey1); + &aesdec ($inout3,$rndkey1); + &aesdec ($inout4,$rndkey1); + &aesdec ($inout5,$rndkey1); + + &mov ($out,&DWP($out_off,"esp")); + &mov ($len,&DWP($end_off,"esp")); + &call ("_aesni_decrypt6_enter"); + + &movdqa ($rndkey0,&QWP(16*5,"esp")); # pass last offset_i + &pxor ($inout0,&QWP(16*0,"esp")); # ^ offset_i + &movdqa ($rndkey1,&QWP($checksum,"esp")); + &pxor ($inout1,&QWP(16*1,"esp")); + &pxor ($inout2,&QWP(16*2,"esp")); + &pxor ($inout3,&QWP(16*3,"esp")); + &pxor ($inout4,&QWP(16*4,"esp")); + &pxor ($inout5,$rndkey0); + + &pxor ($rndkey1,$inout0); # checksum + &movdqu (&QWP(-16*6,$out,$inp),$inout0);# store output + &pxor ($rndkey1,$inout1); + &movdqu (&QWP(-16*5,$out,$inp),$inout1); + &pxor ($rndkey1,$inout2); + &movdqu (&QWP(-16*4,$out,$inp),$inout2); + &pxor ($rndkey1,$inout3); + &movdqu (&QWP(-16*3,$out,$inp),$inout3); + &pxor ($rndkey1,$inout4); + &movdqu (&QWP(-16*2,$out,$inp),$inout4); + &pxor ($rndkey1,$inout5); + &movdqu (&QWP(-16*1,$out,$inp),$inout5); + &cmp ($inp,$len); # done yet? + &jb (&label("grandloop")); + +&set_label("short"); + &add ($len,16*6); + &sub ($len,$inp); + &jz (&label("done")); + + &cmp ($len,16*2); + &jb (&label("one")); + &je (&label("two")); + + &cmp ($len,16*4); + &jb (&label("three")); + &je (&label("four")); + + &lea ($i1,&DWP(1,$block)); + &lea ($i3,&DWP(3,$block)); + &bsf ($i1,$i1); + &bsf ($i3,$i3); + &shl ($i1,4); + &shl ($i3,4); + &movdqu ($inout0,&QWP(0,$l_)); + &movdqu ($inout1,&QWP(0,$l_,$i1)); + &mov ($rounds,&DWP($rounds_off,"esp")); + &movdqa ($inout2,$inout0); + &movdqu ($inout3,&QWP(0,$l_,$i3)); + &movdqa ($inout4,$inout0); + + &pxor ($inout0,$rndkey0); # ^ last offset_i + &pxor ($inout1,$inout0); + &movdqa (&QWP(16*0,"esp"),$inout0); + &pxor ($inout2,$inout1); + &movdqa (&QWP(16*1,"esp"),$inout1); + &pxor ($inout3,$inout2); + &movdqa (&QWP(16*2,"esp"),$inout2); + &pxor ($inout4,$inout3); + &movdqa (&QWP(16*3,"esp"),$inout3); + &pxor ($inout5,$inout4); + &movdqa (&QWP(16*4,"esp"),$inout4); + + &$movekey ($rndkey0,&QWP(-48,$key,$rounds)); + &movdqu ($inout0,&QWP(16*0,$inp)); # load input + &movdqu ($inout1,&QWP(16*1,$inp)); + &movdqu ($inout2,&QWP(16*2,$inp)); + &movdqu ($inout3,&QWP(16*3,$inp)); + &movdqu ($inout4,&QWP(16*4,$inp)); + &pxor ($inout5,$inout5); + + &movdqa (&QWP($checksum,"esp"),$rndkey1); + &pxor ($inout0,$rndkey0); # ^ roundkey[0] + &pxor ($inout1,$rndkey0); + &pxor ($inout2,$rndkey0); + &pxor ($inout3,$rndkey0); + &pxor ($inout4,$rndkey0); + + &$movekey ($rndkey1,&QWP(-32,$key,$rounds)); + &pxor ($inout0,&QWP(16*0,"esp")); # ^ offset_i + &pxor ($inout1,&QWP(16*1,"esp")); + &pxor ($inout2,&QWP(16*2,"esp")); + &pxor ($inout3,&QWP(16*3,"esp")); + &pxor ($inout4,&QWP(16*4,"esp")); + + &$movekey ($rndkey0,&QWP(-16,$key,$rounds)); + &aesdec ($inout0,$rndkey1); + &aesdec ($inout1,$rndkey1); + &aesdec ($inout2,$rndkey1); + &aesdec ($inout3,$rndkey1); + &aesdec ($inout4,$rndkey1); + &aesdec ($inout5,$rndkey1); + + &mov ($out,&DWP($out_off,"esp")); + &call ("_aesni_decrypt6_enter"); + + &movdqa ($rndkey0,&QWP(16*4,"esp")); # pass last offset_i + &pxor ($inout0,&QWP(16*0,"esp")); # ^ offset_i + &movdqa ($rndkey1,&QWP($checksum,"esp")); + &pxor ($inout1,&QWP(16*1,"esp")); + &pxor ($inout2,&QWP(16*2,"esp")); + &pxor ($inout3,&QWP(16*3,"esp")); + &pxor ($inout4,$rndkey0); + + &pxor ($rndkey1,$inout0); # checksum + &movdqu (&QWP(16*0,$out,$inp),$inout0); # store output + &pxor ($rndkey1,$inout1); + &movdqu (&QWP(16*1,$out,$inp),$inout1); + &pxor ($rndkey1,$inout2); + &movdqu (&QWP(16*2,$out,$inp),$inout2); + &pxor ($rndkey1,$inout3); + &movdqu (&QWP(16*3,$out,$inp),$inout3); + &pxor ($rndkey1,$inout4); + &movdqu (&QWP(16*4,$out,$inp),$inout4); + + &jmp (&label("done")); + +&set_label("one",16); + &movdqu ($inout5,&QWP(0,$l_)); + &mov ($key,&DWP($key_off,"esp")); # restore key + + &movdqu ($inout0,&QWP(16*0,$inp)); # load input + &mov ($rounds,&DWP(240,$key)); + + &pxor ($inout5,$rndkey0); # ^ last offset_i + &pxor ($inout0,$inout5); # ^ offset_i + + &movdqa ($inout4,$rndkey1); + &mov ($out,&DWP($out_off,"esp")); + if ($inline) + { &aesni_inline_generate1("dec"); } + else + { &call ("_aesni_decrypt1"); } + + &xorps ($inout0,$inout5); # ^ offset_i + &movaps ($rndkey1,$inout4); # pass the checksum + &movdqa ($rndkey0,$inout5); # pass last offset_i + &xorps ($rndkey1,$inout0); # checksum + &movups (&QWP(0,$out,$inp),$inout0); + + &jmp (&label("done")); + +&set_label("two",16); + &lea ($i1,&DWP(1,$block)); + &mov ($key,&DWP($key_off,"esp")); # restore key + &bsf ($i1,$i1); + &shl ($i1,4); + &movdqu ($inout4,&QWP(0,$l_)); + &movdqu ($inout5,&QWP(0,$l_,$i1)); + + &movdqu ($inout0,&QWP(16*0,$inp)); # load input + &movdqu ($inout1,&QWP(16*1,$inp)); + &mov ($rounds,&DWP(240,$key)); + + &movdqa ($inout3,$rndkey1); + &pxor ($inout4,$rndkey0); # ^ last offset_i + &pxor ($inout5,$inout4); + + &pxor ($inout0,$inout4); # ^ offset_i + &pxor ($inout1,$inout5); + + &mov ($out,&DWP($out_off,"esp")); + &call ("_aesni_decrypt2"); + + &xorps ($inout0,$inout4); # ^ offset_i + &xorps ($inout1,$inout5); + &movdqa ($rndkey0,$inout5); # pass last offset_i + &xorps ($inout3,$inout0); # checksum + &movups (&QWP(16*0,$out,$inp),$inout0); # store output + &xorps ($inout3,$inout1); + &movups (&QWP(16*1,$out,$inp),$inout1); + &movaps ($rndkey1,$inout3); # pass the checksum + + &jmp (&label("done")); + +&set_label("three",16); + &lea ($i1,&DWP(1,$block)); + &mov ($key,&DWP($key_off,"esp")); # restore key + &bsf ($i1,$i1); + &shl ($i1,4); + &movdqu ($inout3,&QWP(0,$l_)); + &movdqu ($inout4,&QWP(0,$l_,$i1)); + &movdqa ($inout5,$inout3); + + &movdqu ($inout0,&QWP(16*0,$inp)); # load input + &movdqu ($inout1,&QWP(16*1,$inp)); + &movdqu ($inout2,&QWP(16*2,$inp)); + &mov ($rounds,&DWP(240,$key)); + + &movdqa (&QWP($checksum,"esp"),$rndkey1); + &pxor ($inout3,$rndkey0); # ^ last offset_i + &pxor ($inout4,$inout3); + &pxor ($inout5,$inout4); + + &pxor ($inout0,$inout3); # ^ offset_i + &pxor ($inout1,$inout4); + &pxor ($inout2,$inout5); + + &mov ($out,&DWP($out_off,"esp")); + &call ("_aesni_decrypt3"); + + &movdqa ($rndkey1,&QWP($checksum,"esp"));# pass the checksum + &xorps ($inout0,$inout3); # ^ offset_i + &xorps ($inout1,$inout4); + &xorps ($inout2,$inout5); + &movups (&QWP(16*0,$out,$inp),$inout0); # store output + &pxor ($rndkey1,$inout0); # checksum + &movdqa ($rndkey0,$inout5); # pass last offset_i + &movups (&QWP(16*1,$out,$inp),$inout1); + &pxor ($rndkey1,$inout1); + &movups (&QWP(16*2,$out,$inp),$inout2); + &pxor ($rndkey1,$inout2); + + &jmp (&label("done")); + +&set_label("four",16); + &lea ($i1,&DWP(1,$block)); + &lea ($i3,&DWP(3,$block)); + &bsf ($i1,$i1); + &bsf ($i3,$i3); + &mov ($key,&DWP($key_off,"esp")); # restore key + &shl ($i1,4); + &shl ($i3,4); + &movdqu ($inout2,&QWP(0,$l_)); + &movdqu ($inout3,&QWP(0,$l_,$i1)); + &movdqa ($inout4,$inout2); + &movdqu ($inout5,&QWP(0,$l_,$i3)); + + &pxor ($inout2,$rndkey0); # ^ last offset_i + &movdqu ($inout0,&QWP(16*0,$inp)); # load input + &pxor ($inout3,$inout2); + &movdqu ($inout1,&QWP(16*1,$inp)); + &pxor ($inout4,$inout3); + &movdqa (&QWP(16*0,"esp"),$inout2); + &pxor ($inout5,$inout4); + &movdqa (&QWP(16*1,"esp"),$inout3); + &movdqu ($inout2,&QWP(16*2,$inp)); + &movdqu ($inout3,&QWP(16*3,$inp)); + &mov ($rounds,&DWP(240,$key)); + + &movdqa (&QWP($checksum,"esp"),$rndkey1); + &pxor ($inout0,&QWP(16*0,"esp")); # ^ offset_i + &pxor ($inout1,&QWP(16*1,"esp")); + &pxor ($inout2,$inout4); + &pxor ($inout3,$inout5); + + &mov ($out,&DWP($out_off,"esp")); + &call ("_aesni_decrypt4"); + + &movdqa ($rndkey1,&QWP($checksum,"esp"));# pass the checksum + &xorps ($inout0,&QWP(16*0,"esp")); # ^ offset_i + &xorps ($inout1,&QWP(16*1,"esp")); + &xorps ($inout2,$inout4); + &movups (&QWP(16*0,$out,$inp),$inout0); # store output + &pxor ($rndkey1,$inout0); # checksum + &xorps ($inout3,$inout5); + &movups (&QWP(16*1,$out,$inp),$inout1); + &pxor ($rndkey1,$inout1); + &movdqa ($rndkey0,$inout5); # pass last offset_i + &movups (&QWP(16*2,$out,$inp),$inout2); + &pxor ($rndkey1,$inout2); + &movups (&QWP(16*3,$out,$inp),$inout3); + &pxor ($rndkey1,$inout3); + +&set_label("done"); + &mov ($key,&DWP($esp_off,"esp")); + &pxor ($inout0,$inout0); # clear register bank + &pxor ($inout1,$inout1); + &movdqa (&QWP(16*0,"esp"),$inout0); # clear stack + &pxor ($inout2,$inout2); + &movdqa (&QWP(16*1,"esp"),$inout0); + &pxor ($inout3,$inout3); + &movdqa (&QWP(16*2,"esp"),$inout0); + &pxor ($inout4,$inout4); + &movdqa (&QWP(16*3,"esp"),$inout0); + &pxor ($inout5,$inout5); + &movdqa (&QWP(16*4,"esp"),$inout0); + &movdqa (&QWP(16*5,"esp"),$inout0); + &movdqa (&QWP(16*6,"esp"),$inout0); + + &lea ("esp",&DWP(0,$key)); + &mov ($rounds,&wparam(5)); # &offset_i + &mov ($rounds_,&wparam(7)); # &checksum + &movdqu (&QWP(0,$rounds),$rndkey0); + &pxor ($rndkey0,$rndkey0); + &movdqu (&QWP(0,$rounds_),$rndkey1); + &pxor ($rndkey1,$rndkey1); +&function_end("aesni_ocb_decrypt"); +} +} + +###################################################################### +# void $PREFIX_cbc_encrypt (const void *inp, void *out, +# size_t length, const AES_KEY *key, +# unsigned char *ivp,const int enc); +&function_begin("${PREFIX}_cbc_encrypt"); + &mov ($inp,&wparam(0)); + &mov ($rounds_,"esp"); + &mov ($out,&wparam(1)); + &sub ($rounds_,24); + &mov ($len,&wparam(2)); + &and ($rounds_,-16); + &mov ($key,&wparam(3)); + &mov ($key_,&wparam(4)); + &test ($len,$len); + &jz (&label("cbc_abort")); + + &cmp (&wparam(5),0); + &xchg ($rounds_,"esp"); # alloca + &movups ($ivec,&QWP(0,$key_)); # load IV + &mov ($rounds,&DWP(240,$key)); + &mov ($key_,$key); # backup $key + &mov (&DWP(16,"esp"),$rounds_); # save original %esp + &mov ($rounds_,$rounds); # backup $rounds + &je (&label("cbc_decrypt")); + + &movaps ($inout0,$ivec); + &cmp ($len,16); + &jb (&label("cbc_enc_tail")); + &sub ($len,16); + &jmp (&label("cbc_enc_loop")); + +&set_label("cbc_enc_loop",16); + &movups ($ivec,&QWP(0,$inp)); # input actually + &lea ($inp,&DWP(16,$inp)); + if ($inline) + { &aesni_inline_generate1("enc",$inout0,$ivec); } + else + { &xorps($inout0,$ivec); &call("_aesni_encrypt1"); } + &mov ($rounds,$rounds_); # restore $rounds + &mov ($key,$key_); # restore $key + &movups (&QWP(0,$out),$inout0); # store output + &lea ($out,&DWP(16,$out)); + &sub ($len,16); + &jnc (&label("cbc_enc_loop")); + &add ($len,16); + &jnz (&label("cbc_enc_tail")); + &movaps ($ivec,$inout0); + &pxor ($inout0,$inout0); + &jmp (&label("cbc_ret")); + +&set_label("cbc_enc_tail"); + &mov ("ecx",$len); # zaps $rounds + &data_word(0xA4F3F689); # rep movsb + &mov ("ecx",16); # zero tail + &sub ("ecx",$len); + &xor ("eax","eax"); # zaps $len + &data_word(0xAAF3F689); # rep stosb + &lea ($out,&DWP(-16,$out)); # rewind $out by 1 block + &mov ($rounds,$rounds_); # restore $rounds + &mov ($inp,$out); # $inp and $out are the same + &mov ($key,$key_); # restore $key + &jmp (&label("cbc_enc_loop")); +###################################################################### +&set_label("cbc_decrypt",16); + &cmp ($len,0x50); + &jbe (&label("cbc_dec_tail")); + &movaps (&QWP(0,"esp"),$ivec); # save IV + &sub ($len,0x50); + &jmp (&label("cbc_dec_loop6_enter")); + +&set_label("cbc_dec_loop6",16); + &movaps (&QWP(0,"esp"),$rndkey0); # save IV + &movups (&QWP(0,$out),$inout5); + &lea ($out,&DWP(0x10,$out)); +&set_label("cbc_dec_loop6_enter"); + &movdqu ($inout0,&QWP(0,$inp)); + &movdqu ($inout1,&QWP(0x10,$inp)); + &movdqu ($inout2,&QWP(0x20,$inp)); + &movdqu ($inout3,&QWP(0x30,$inp)); + &movdqu ($inout4,&QWP(0x40,$inp)); + &movdqu ($inout5,&QWP(0x50,$inp)); + + &call ("_aesni_decrypt6"); + + &movups ($rndkey1,&QWP(0,$inp)); + &movups ($rndkey0,&QWP(0x10,$inp)); + &xorps ($inout0,&QWP(0,"esp")); # ^=IV + &xorps ($inout1,$rndkey1); + &movups ($rndkey1,&QWP(0x20,$inp)); + &xorps ($inout2,$rndkey0); + &movups ($rndkey0,&QWP(0x30,$inp)); + &xorps ($inout3,$rndkey1); + &movups ($rndkey1,&QWP(0x40,$inp)); + &xorps ($inout4,$rndkey0); + &movups ($rndkey0,&QWP(0x50,$inp)); # IV + &xorps ($inout5,$rndkey1); + &movups (&QWP(0,$out),$inout0); + &movups (&QWP(0x10,$out),$inout1); + &lea ($inp,&DWP(0x60,$inp)); + &movups (&QWP(0x20,$out),$inout2); + &mov ($rounds,$rounds_); # restore $rounds + &movups (&QWP(0x30,$out),$inout3); + &mov ($key,$key_); # restore $key + &movups (&QWP(0x40,$out),$inout4); + &lea ($out,&DWP(0x50,$out)); + &sub ($len,0x60); + &ja (&label("cbc_dec_loop6")); + + &movaps ($inout0,$inout5); + &movaps ($ivec,$rndkey0); + &add ($len,0x50); + &jle (&label("cbc_dec_clear_tail_collected")); + &movups (&QWP(0,$out),$inout0); + &lea ($out,&DWP(0x10,$out)); +&set_label("cbc_dec_tail"); + &movups ($inout0,&QWP(0,$inp)); + &movaps ($in0,$inout0); + &cmp ($len,0x10); + &jbe (&label("cbc_dec_one")); + + &movups ($inout1,&QWP(0x10,$inp)); + &movaps ($in1,$inout1); + &cmp ($len,0x20); + &jbe (&label("cbc_dec_two")); + + &movups ($inout2,&QWP(0x20,$inp)); + &cmp ($len,0x30); + &jbe (&label("cbc_dec_three")); + + &movups ($inout3,&QWP(0x30,$inp)); + &cmp ($len,0x40); + &jbe (&label("cbc_dec_four")); + + &movups ($inout4,&QWP(0x40,$inp)); + &movaps (&QWP(0,"esp"),$ivec); # save IV + &movups ($inout0,&QWP(0,$inp)); + &xorps ($inout5,$inout5); + &call ("_aesni_decrypt6"); + &movups ($rndkey1,&QWP(0,$inp)); + &movups ($rndkey0,&QWP(0x10,$inp)); + &xorps ($inout0,&QWP(0,"esp")); # ^= IV + &xorps ($inout1,$rndkey1); + &movups ($rndkey1,&QWP(0x20,$inp)); + &xorps ($inout2,$rndkey0); + &movups ($rndkey0,&QWP(0x30,$inp)); + &xorps ($inout3,$rndkey1); + &movups ($ivec,&QWP(0x40,$inp)); # IV + &xorps ($inout4,$rndkey0); + &movups (&QWP(0,$out),$inout0); + &movups (&QWP(0x10,$out),$inout1); + &pxor ($inout1,$inout1); + &movups (&QWP(0x20,$out),$inout2); + &pxor ($inout2,$inout2); + &movups (&QWP(0x30,$out),$inout3); + &pxor ($inout3,$inout3); + &lea ($out,&DWP(0x40,$out)); + &movaps ($inout0,$inout4); + &pxor ($inout4,$inout4); + &sub ($len,0x50); + &jmp (&label("cbc_dec_tail_collected")); + +&set_label("cbc_dec_one",16); + if ($inline) + { &aesni_inline_generate1("dec"); } + else + { &call ("_aesni_decrypt1"); } + &xorps ($inout0,$ivec); + &movaps ($ivec,$in0); + &sub ($len,0x10); + &jmp (&label("cbc_dec_tail_collected")); + +&set_label("cbc_dec_two",16); + &call ("_aesni_decrypt2"); + &xorps ($inout0,$ivec); + &xorps ($inout1,$in0); + &movups (&QWP(0,$out),$inout0); + &movaps ($inout0,$inout1); + &pxor ($inout1,$inout1); + &lea ($out,&DWP(0x10,$out)); + &movaps ($ivec,$in1); + &sub ($len,0x20); + &jmp (&label("cbc_dec_tail_collected")); + +&set_label("cbc_dec_three",16); + &call ("_aesni_decrypt3"); + &xorps ($inout0,$ivec); + &xorps ($inout1,$in0); + &xorps ($inout2,$in1); + &movups (&QWP(0,$out),$inout0); + &movaps ($inout0,$inout2); + &pxor ($inout2,$inout2); + &movups (&QWP(0x10,$out),$inout1); + &pxor ($inout1,$inout1); + &lea ($out,&DWP(0x20,$out)); + &movups ($ivec,&QWP(0x20,$inp)); + &sub ($len,0x30); + &jmp (&label("cbc_dec_tail_collected")); + +&set_label("cbc_dec_four",16); + &call ("_aesni_decrypt4"); + &movups ($rndkey1,&QWP(0x10,$inp)); + &movups ($rndkey0,&QWP(0x20,$inp)); + &xorps ($inout0,$ivec); + &movups ($ivec,&QWP(0x30,$inp)); + &xorps ($inout1,$in0); + &movups (&QWP(0,$out),$inout0); + &xorps ($inout2,$rndkey1); + &movups (&QWP(0x10,$out),$inout1); + &pxor ($inout1,$inout1); + &xorps ($inout3,$rndkey0); + &movups (&QWP(0x20,$out),$inout2); + &pxor ($inout2,$inout2); + &lea ($out,&DWP(0x30,$out)); + &movaps ($inout0,$inout3); + &pxor ($inout3,$inout3); + &sub ($len,0x40); + &jmp (&label("cbc_dec_tail_collected")); + +&set_label("cbc_dec_clear_tail_collected",16); + &pxor ($inout1,$inout1); + &pxor ($inout2,$inout2); + &pxor ($inout3,$inout3); + &pxor ($inout4,$inout4); +&set_label("cbc_dec_tail_collected"); + &and ($len,15); + &jnz (&label("cbc_dec_tail_partial")); + &movups (&QWP(0,$out),$inout0); + &pxor ($rndkey0,$rndkey0); + &jmp (&label("cbc_ret")); + +&set_label("cbc_dec_tail_partial",16); + &movaps (&QWP(0,"esp"),$inout0); + &pxor ($rndkey0,$rndkey0); + &mov ("ecx",16); + &mov ($inp,"esp"); + &sub ("ecx",$len); + &data_word(0xA4F3F689); # rep movsb + &movdqa (&QWP(0,"esp"),$inout0); + +&set_label("cbc_ret"); + &mov ("esp",&DWP(16,"esp")); # pull original %esp + &mov ($key_,&wparam(4)); + &pxor ($inout0,$inout0); + &pxor ($rndkey1,$rndkey1); + &movups (&QWP(0,$key_),$ivec); # output IV + &pxor ($ivec,$ivec); +&set_label("cbc_abort"); +&function_end("${PREFIX}_cbc_encrypt"); + +###################################################################### +# Mechanical port from aesni-x86_64.pl. +# +# _aesni_set_encrypt_key is private interface, +# input: +# "eax" const unsigned char *userKey +# $rounds int bits +# $key AES_KEY *key +# output: +# "eax" return code +# $round rounds + +&function_begin_B("_aesni_set_encrypt_key"); + &push ("ebp"); + &push ("ebx"); + &test ("eax","eax"); + &jz (&label("bad_pointer")); + &test ($key,$key); + &jz (&label("bad_pointer")); + + &call (&label("pic")); +&set_label("pic"); + &blindpop("ebx"); + &lea ("ebx",&DWP(&label("key_const")."-".&label("pic"),"ebx")); + + &picmeup("ebp","OPENSSL_ia32cap_P","ebx",&label("key_const")); + &movups ("xmm0",&QWP(0,"eax")); # pull first 128 bits of *userKey + &xorps ("xmm4","xmm4"); # low dword of xmm4 is assumed 0 + &mov ("ebp",&DWP(4,"ebp")); + &lea ($key,&DWP(16,$key)); + &and ("ebp",1<<28|1<<11); # AVX and XOP bits + &cmp ($rounds,256); + &je (&label("14rounds")); + &cmp ($rounds,192); + &je (&label("12rounds")); + &cmp ($rounds,128); + &jne (&label("bad_keybits")); + +&set_label("10rounds",16); + &cmp ("ebp",1<<28); + &je (&label("10rounds_alt")); + + &mov ($rounds,9); + &$movekey (&QWP(-16,$key),"xmm0"); # round 0 + &aeskeygenassist("xmm1","xmm0",0x01); # round 1 + &call (&label("key_128_cold")); + &aeskeygenassist("xmm1","xmm0",0x2); # round 2 + &call (&label("key_128")); + &aeskeygenassist("xmm1","xmm0",0x04); # round 3 + &call (&label("key_128")); + &aeskeygenassist("xmm1","xmm0",0x08); # round 4 + &call (&label("key_128")); + &aeskeygenassist("xmm1","xmm0",0x10); # round 5 + &call (&label("key_128")); + &aeskeygenassist("xmm1","xmm0",0x20); # round 6 + &call (&label("key_128")); + &aeskeygenassist("xmm1","xmm0",0x40); # round 7 + &call (&label("key_128")); + &aeskeygenassist("xmm1","xmm0",0x80); # round 8 + &call (&label("key_128")); + &aeskeygenassist("xmm1","xmm0",0x1b); # round 9 + &call (&label("key_128")); + &aeskeygenassist("xmm1","xmm0",0x36); # round 10 + &call (&label("key_128")); + &$movekey (&QWP(0,$key),"xmm0"); + &mov (&DWP(80,$key),$rounds); + + &jmp (&label("good_key")); + +&set_label("key_128",16); + &$movekey (&QWP(0,$key),"xmm0"); + &lea ($key,&DWP(16,$key)); +&set_label("key_128_cold"); + &shufps ("xmm4","xmm0",0b00010000); + &xorps ("xmm0","xmm4"); + &shufps ("xmm4","xmm0",0b10001100); + &xorps ("xmm0","xmm4"); + &shufps ("xmm1","xmm1",0b11111111); # critical path + &xorps ("xmm0","xmm1"); + &ret(); + +&set_label("10rounds_alt",16); + &movdqa ("xmm5",&QWP(0x00,"ebx")); + &mov ($rounds,8); + &movdqa ("xmm4",&QWP(0x20,"ebx")); + &movdqa ("xmm2","xmm0"); + &movdqu (&QWP(-16,$key),"xmm0"); + +&set_label("loop_key128"); + &pshufb ("xmm0","xmm5"); + &aesenclast ("xmm0","xmm4"); + &pslld ("xmm4",1); + &lea ($key,&DWP(16,$key)); + + &movdqa ("xmm3","xmm2"); + &pslldq ("xmm2",4); + &pxor ("xmm3","xmm2"); + &pslldq ("xmm2",4); + &pxor ("xmm3","xmm2"); + &pslldq ("xmm2",4); + &pxor ("xmm2","xmm3"); + + &pxor ("xmm0","xmm2"); + &movdqu (&QWP(-16,$key),"xmm0"); + &movdqa ("xmm2","xmm0"); + + &dec ($rounds); + &jnz (&label("loop_key128")); + + &movdqa ("xmm4",&QWP(0x30,"ebx")); + + &pshufb ("xmm0","xmm5"); + &aesenclast ("xmm0","xmm4"); + &pslld ("xmm4",1); + + &movdqa ("xmm3","xmm2"); + &pslldq ("xmm2",4); + &pxor ("xmm3","xmm2"); + &pslldq ("xmm2",4); + &pxor ("xmm3","xmm2"); + &pslldq ("xmm2",4); + &pxor ("xmm2","xmm3"); + + &pxor ("xmm0","xmm2"); + &movdqu (&QWP(0,$key),"xmm0"); + + &movdqa ("xmm2","xmm0"); + &pshufb ("xmm0","xmm5"); + &aesenclast ("xmm0","xmm4"); + + &movdqa ("xmm3","xmm2"); + &pslldq ("xmm2",4); + &pxor ("xmm3","xmm2"); + &pslldq ("xmm2",4); + &pxor ("xmm3","xmm2"); + &pslldq ("xmm2",4); + &pxor ("xmm2","xmm3"); + + &pxor ("xmm0","xmm2"); + &movdqu (&QWP(16,$key),"xmm0"); + + &mov ($rounds,9); + &mov (&DWP(96,$key),$rounds); + + &jmp (&label("good_key")); + +&set_label("12rounds",16); + &movq ("xmm2",&QWP(16,"eax")); # remaining 1/3 of *userKey + &cmp ("ebp",1<<28); + &je (&label("12rounds_alt")); + + &mov ($rounds,11); + &$movekey (&QWP(-16,$key),"xmm0"); # round 0 + &aeskeygenassist("xmm1","xmm2",0x01); # round 1,2 + &call (&label("key_192a_cold")); + &aeskeygenassist("xmm1","xmm2",0x02); # round 2,3 + &call (&label("key_192b")); + &aeskeygenassist("xmm1","xmm2",0x04); # round 4,5 + &call (&label("key_192a")); + &aeskeygenassist("xmm1","xmm2",0x08); # round 5,6 + &call (&label("key_192b")); + &aeskeygenassist("xmm1","xmm2",0x10); # round 7,8 + &call (&label("key_192a")); + &aeskeygenassist("xmm1","xmm2",0x20); # round 8,9 + &call (&label("key_192b")); + &aeskeygenassist("xmm1","xmm2",0x40); # round 10,11 + &call (&label("key_192a")); + &aeskeygenassist("xmm1","xmm2",0x80); # round 11,12 + &call (&label("key_192b")); + &$movekey (&QWP(0,$key),"xmm0"); + &mov (&DWP(48,$key),$rounds); + + &jmp (&label("good_key")); + +&set_label("key_192a",16); + &$movekey (&QWP(0,$key),"xmm0"); + &lea ($key,&DWP(16,$key)); +&set_label("key_192a_cold",16); + &movaps ("xmm5","xmm2"); +&set_label("key_192b_warm"); + &shufps ("xmm4","xmm0",0b00010000); + &movdqa ("xmm3","xmm2"); + &xorps ("xmm0","xmm4"); + &shufps ("xmm4","xmm0",0b10001100); + &pslldq ("xmm3",4); + &xorps ("xmm0","xmm4"); + &pshufd ("xmm1","xmm1",0b01010101); # critical path + &pxor ("xmm2","xmm3"); + &pxor ("xmm0","xmm1"); + &pshufd ("xmm3","xmm0",0b11111111); + &pxor ("xmm2","xmm3"); + &ret(); + +&set_label("key_192b",16); + &movaps ("xmm3","xmm0"); + &shufps ("xmm5","xmm0",0b01000100); + &$movekey (&QWP(0,$key),"xmm5"); + &shufps ("xmm3","xmm2",0b01001110); + &$movekey (&QWP(16,$key),"xmm3"); + &lea ($key,&DWP(32,$key)); + &jmp (&label("key_192b_warm")); + +&set_label("12rounds_alt",16); + &movdqa ("xmm5",&QWP(0x10,"ebx")); + &movdqa ("xmm4",&QWP(0x20,"ebx")); + &mov ($rounds,8); + &movdqu (&QWP(-16,$key),"xmm0"); + +&set_label("loop_key192"); + &movq (&QWP(0,$key),"xmm2"); + &movdqa ("xmm1","xmm2"); + &pshufb ("xmm2","xmm5"); + &aesenclast ("xmm2","xmm4"); + &pslld ("xmm4",1); + &lea ($key,&DWP(24,$key)); + + &movdqa ("xmm3","xmm0"); + &pslldq ("xmm0",4); + &pxor ("xmm3","xmm0"); + &pslldq ("xmm0",4); + &pxor ("xmm3","xmm0"); + &pslldq ("xmm0",4); + &pxor ("xmm0","xmm3"); + + &pshufd ("xmm3","xmm0",0xff); + &pxor ("xmm3","xmm1"); + &pslldq ("xmm1",4); + &pxor ("xmm3","xmm1"); + + &pxor ("xmm0","xmm2"); + &pxor ("xmm2","xmm3"); + &movdqu (&QWP(-16,$key),"xmm0"); + + &dec ($rounds); + &jnz (&label("loop_key192")); + + &mov ($rounds,11); + &mov (&DWP(32,$key),$rounds); + + &jmp (&label("good_key")); + +&set_label("14rounds",16); + &movups ("xmm2",&QWP(16,"eax")); # remaining half of *userKey + &lea ($key,&DWP(16,$key)); + &cmp ("ebp",1<<28); + &je (&label("14rounds_alt")); + + &mov ($rounds,13); + &$movekey (&QWP(-32,$key),"xmm0"); # round 0 + &$movekey (&QWP(-16,$key),"xmm2"); # round 1 + &aeskeygenassist("xmm1","xmm2",0x01); # round 2 + &call (&label("key_256a_cold")); + &aeskeygenassist("xmm1","xmm0",0x01); # round 3 + &call (&label("key_256b")); + &aeskeygenassist("xmm1","xmm2",0x02); # round 4 + &call (&label("key_256a")); + &aeskeygenassist("xmm1","xmm0",0x02); # round 5 + &call (&label("key_256b")); + &aeskeygenassist("xmm1","xmm2",0x04); # round 6 + &call (&label("key_256a")); + &aeskeygenassist("xmm1","xmm0",0x04); # round 7 + &call (&label("key_256b")); + &aeskeygenassist("xmm1","xmm2",0x08); # round 8 + &call (&label("key_256a")); + &aeskeygenassist("xmm1","xmm0",0x08); # round 9 + &call (&label("key_256b")); + &aeskeygenassist("xmm1","xmm2",0x10); # round 10 + &call (&label("key_256a")); + &aeskeygenassist("xmm1","xmm0",0x10); # round 11 + &call (&label("key_256b")); + &aeskeygenassist("xmm1","xmm2",0x20); # round 12 + &call (&label("key_256a")); + &aeskeygenassist("xmm1","xmm0",0x20); # round 13 + &call (&label("key_256b")); + &aeskeygenassist("xmm1","xmm2",0x40); # round 14 + &call (&label("key_256a")); + &$movekey (&QWP(0,$key),"xmm0"); + &mov (&DWP(16,$key),$rounds); + &xor ("eax","eax"); + + &jmp (&label("good_key")); + +&set_label("key_256a",16); + &$movekey (&QWP(0,$key),"xmm2"); + &lea ($key,&DWP(16,$key)); +&set_label("key_256a_cold"); + &shufps ("xmm4","xmm0",0b00010000); + &xorps ("xmm0","xmm4"); + &shufps ("xmm4","xmm0",0b10001100); + &xorps ("xmm0","xmm4"); + &shufps ("xmm1","xmm1",0b11111111); # critical path + &xorps ("xmm0","xmm1"); + &ret(); + +&set_label("key_256b",16); + &$movekey (&QWP(0,$key),"xmm0"); + &lea ($key,&DWP(16,$key)); + + &shufps ("xmm4","xmm2",0b00010000); + &xorps ("xmm2","xmm4"); + &shufps ("xmm4","xmm2",0b10001100); + &xorps ("xmm2","xmm4"); + &shufps ("xmm1","xmm1",0b10101010); # critical path + &xorps ("xmm2","xmm1"); + &ret(); + +&set_label("14rounds_alt",16); + &movdqa ("xmm5",&QWP(0x00,"ebx")); + &movdqa ("xmm4",&QWP(0x20,"ebx")); + &mov ($rounds,7); + &movdqu (&QWP(-32,$key),"xmm0"); + &movdqa ("xmm1","xmm2"); + &movdqu (&QWP(-16,$key),"xmm2"); + +&set_label("loop_key256"); + &pshufb ("xmm2","xmm5"); + &aesenclast ("xmm2","xmm4"); + + &movdqa ("xmm3","xmm0"); + &pslldq ("xmm0",4); + &pxor ("xmm3","xmm0"); + &pslldq ("xmm0",4); + &pxor ("xmm3","xmm0"); + &pslldq ("xmm0",4); + &pxor ("xmm0","xmm3"); + &pslld ("xmm4",1); + + &pxor ("xmm0","xmm2"); + &movdqu (&QWP(0,$key),"xmm0"); + + &dec ($rounds); + &jz (&label("done_key256")); + + &pshufd ("xmm2","xmm0",0xff); + &pxor ("xmm3","xmm3"); + &aesenclast ("xmm2","xmm3"); + + &movdqa ("xmm3","xmm1"); + &pslldq ("xmm1",4); + &pxor ("xmm3","xmm1"); + &pslldq ("xmm1",4); + &pxor ("xmm3","xmm1"); + &pslldq ("xmm1",4); + &pxor ("xmm1","xmm3"); + + &pxor ("xmm2","xmm1"); + &movdqu (&QWP(16,$key),"xmm2"); + &lea ($key,&DWP(32,$key)); + &movdqa ("xmm1","xmm2"); + &jmp (&label("loop_key256")); + +&set_label("done_key256"); + &mov ($rounds,13); + &mov (&DWP(16,$key),$rounds); + +&set_label("good_key"); + &pxor ("xmm0","xmm0"); + &pxor ("xmm1","xmm1"); + &pxor ("xmm2","xmm2"); + &pxor ("xmm3","xmm3"); + &pxor ("xmm4","xmm4"); + &pxor ("xmm5","xmm5"); + &xor ("eax","eax"); + &pop ("ebx"); + &pop ("ebp"); + &ret (); + +&set_label("bad_pointer",4); + &mov ("eax",-1); + &pop ("ebx"); + &pop ("ebp"); + &ret (); +&set_label("bad_keybits",4); + &pxor ("xmm0","xmm0"); + &mov ("eax",-2); + &pop ("ebx"); + &pop ("ebp"); + &ret (); +&function_end_B("_aesni_set_encrypt_key"); + +# int $PREFIX_set_encrypt_key (const unsigned char *userKey, int bits, +# AES_KEY *key) +&function_begin_B("${PREFIX}_set_encrypt_key"); + &mov ("eax",&wparam(0)); + &mov ($rounds,&wparam(1)); + &mov ($key,&wparam(2)); + &call ("_aesni_set_encrypt_key"); + &ret (); +&function_end_B("${PREFIX}_set_encrypt_key"); + +# int $PREFIX_set_decrypt_key (const unsigned char *userKey, int bits, +# AES_KEY *key) +&function_begin_B("${PREFIX}_set_decrypt_key"); + &mov ("eax",&wparam(0)); + &mov ($rounds,&wparam(1)); + &mov ($key,&wparam(2)); + &call ("_aesni_set_encrypt_key"); + &mov ($key,&wparam(2)); + &shl ($rounds,4); # rounds-1 after _aesni_set_encrypt_key + &test ("eax","eax"); + &jnz (&label("dec_key_ret")); + &lea ("eax",&DWP(16,$key,$rounds)); # end of key schedule + + &$movekey ("xmm0",&QWP(0,$key)); # just swap + &$movekey ("xmm1",&QWP(0,"eax")); + &$movekey (&QWP(0,"eax"),"xmm0"); + &$movekey (&QWP(0,$key),"xmm1"); + &lea ($key,&DWP(16,$key)); + &lea ("eax",&DWP(-16,"eax")); + +&set_label("dec_key_inverse"); + &$movekey ("xmm0",&QWP(0,$key)); # swap and inverse + &$movekey ("xmm1",&QWP(0,"eax")); + &aesimc ("xmm0","xmm0"); + &aesimc ("xmm1","xmm1"); + &lea ($key,&DWP(16,$key)); + &lea ("eax",&DWP(-16,"eax")); + &$movekey (&QWP(16,"eax"),"xmm0"); + &$movekey (&QWP(-16,$key),"xmm1"); + &cmp ("eax",$key); + &ja (&label("dec_key_inverse")); + + &$movekey ("xmm0",&QWP(0,$key)); # inverse middle + &aesimc ("xmm0","xmm0"); + &$movekey (&QWP(0,$key),"xmm0"); + + &pxor ("xmm0","xmm0"); + &pxor ("xmm1","xmm1"); + &xor ("eax","eax"); # return success +&set_label("dec_key_ret"); + &ret (); +&function_end_B("${PREFIX}_set_decrypt_key"); + +&set_label("key_const",64); +&data_word(0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d); +&data_word(0x04070605,0x04070605,0x04070605,0x04070605); +&data_word(1,1,1,1); +&data_word(0x1b,0x1b,0x1b,0x1b); +&asciz("AES for Intel AES-NI, CRYPTOGAMS by "); + +&asm_finish(); + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesni-x86_64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesni-x86_64.pl new file mode 100644 index 000000000..b68c14da6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesni-x86_64.pl @@ -0,0 +1,5141 @@ +#! /usr/bin/env perl +# Copyright 2009-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# This module implements support for Intel AES-NI extension. In +# OpenSSL context it's used with Intel engine, but can also be used as +# drop-in replacement for crypto/aes/asm/aes-x86_64.pl [see below for +# details]. +# +# Performance. +# +# Given aes(enc|dec) instructions' latency asymptotic performance for +# non-parallelizable modes such as CBC encrypt is 3.75 cycles per byte +# processed with 128-bit key. And given their throughput asymptotic +# performance for parallelizable modes is 1.25 cycles per byte. Being +# asymptotic limit it's not something you commonly achieve in reality, +# but how close does one get? Below are results collected for +# different modes and block sized. Pairs of numbers are for en-/ +# decryption. +# +# 16-byte 64-byte 256-byte 1-KB 8-KB +# ECB 4.25/4.25 1.38/1.38 1.28/1.28 1.26/1.26 1.26/1.26 +# CTR 5.42/5.42 1.92/1.92 1.44/1.44 1.28/1.28 1.26/1.26 +# CBC 4.38/4.43 4.15/1.43 4.07/1.32 4.07/1.29 4.06/1.28 +# CCM 5.66/9.42 4.42/5.41 4.16/4.40 4.09/4.15 4.06/4.07 +# OFB 5.42/5.42 4.64/4.64 4.44/4.44 4.39/4.39 4.38/4.38 +# CFB 5.73/5.85 5.56/5.62 5.48/5.56 5.47/5.55 5.47/5.55 +# +# ECB, CTR, CBC and CCM results are free from EVP overhead. This means +# that otherwise used 'openssl speed -evp aes-128-??? -engine aesni +# [-decrypt]' will exhibit 10-15% worse results for smaller blocks. +# The results were collected with specially crafted speed.c benchmark +# in order to compare them with results reported in "Intel Advanced +# Encryption Standard (AES) New Instruction Set" White Paper Revision +# 3.0 dated May 2010. All above results are consistently better. This +# module also provides better performance for block sizes smaller than +# 128 bytes in points *not* represented in the above table. +# +# Looking at the results for 8-KB buffer. +# +# CFB and OFB results are far from the limit, because implementation +# uses "generic" CRYPTO_[c|o]fb128_encrypt interfaces relying on +# single-block aesni_encrypt, which is not the most optimal way to go. +# CBC encrypt result is unexpectedly high and there is no documented +# explanation for it. Seemingly there is a small penalty for feeding +# the result back to AES unit the way it's done in CBC mode. There is +# nothing one can do and the result appears optimal. CCM result is +# identical to CBC, because CBC-MAC is essentially CBC encrypt without +# saving output. CCM CTR "stays invisible," because it's neatly +# interleaved wih CBC-MAC. This provides ~30% improvement over +# "straightforward" CCM implementation with CTR and CBC-MAC performed +# disjointly. Parallelizable modes practically achieve the theoretical +# limit. +# +# Looking at how results vary with buffer size. +# +# Curves are practically saturated at 1-KB buffer size. In most cases +# "256-byte" performance is >95%, and "64-byte" is ~90% of "8-KB" one. +# CTR curve doesn't follow this pattern and is "slowest" changing one +# with "256-byte" result being 87% of "8-KB." This is because overhead +# in CTR mode is most computationally intensive. Small-block CCM +# decrypt is slower than encrypt, because first CTR and last CBC-MAC +# iterations can't be interleaved. +# +# Results for 192- and 256-bit keys. +# +# EVP-free results were observed to scale perfectly with number of +# rounds for larger block sizes, i.e. 192-bit result being 10/12 times +# lower and 256-bit one - 10/14. Well, in CBC encrypt case differences +# are a tad smaller, because the above mentioned penalty biases all +# results by same constant value. In similar way function call +# overhead affects small-block performance, as well as OFB and CFB +# results. Differences are not large, most common coefficients are +# 10/11.7 and 10/13.4 (as opposite to 10/12.0 and 10/14.0), but one +# observe even 10/11.2 and 10/12.4 (CTR, OFB, CFB)... + +# January 2011 +# +# While Westmere processor features 6 cycles latency for aes[enc|dec] +# instructions, which can be scheduled every second cycle, Sandy +# Bridge spends 8 cycles per instruction, but it can schedule them +# every cycle. This means that code targeting Westmere would perform +# suboptimally on Sandy Bridge. Therefore this update. +# +# In addition, non-parallelizable CBC encrypt (as well as CCM) is +# optimized. Relative improvement might appear modest, 8% on Westmere, +# but in absolute terms it's 3.77 cycles per byte encrypted with +# 128-bit key on Westmere, and 5.07 - on Sandy Bridge. These numbers +# should be compared to asymptotic limits of 3.75 for Westmere and +# 5.00 for Sandy Bridge. Actually, the fact that they get this close +# to asymptotic limits is quite amazing. Indeed, the limit is +# calculated as latency times number of rounds, 10 for 128-bit key, +# and divided by 16, the number of bytes in block, or in other words +# it accounts *solely* for aesenc instructions. But there are extra +# instructions, and numbers so close to the asymptotic limits mean +# that it's as if it takes as little as *one* additional cycle to +# execute all of them. How is it possible? It is possible thanks to +# out-of-order execution logic, which manages to overlap post- +# processing of previous block, things like saving the output, with +# actual encryption of current block, as well as pre-processing of +# current block, things like fetching input and xor-ing it with +# 0-round element of the key schedule, with actual encryption of +# previous block. Keep this in mind... +# +# For parallelizable modes, such as ECB, CBC decrypt, CTR, higher +# performance is achieved by interleaving instructions working on +# independent blocks. In which case asymptotic limit for such modes +# can be obtained by dividing above mentioned numbers by AES +# instructions' interleave factor. Westmere can execute at most 3 +# instructions at a time, meaning that optimal interleave factor is 3, +# and that's where the "magic" number of 1.25 come from. "Optimal +# interleave factor" means that increase of interleave factor does +# not improve performance. The formula has proven to reflect reality +# pretty well on Westmere... Sandy Bridge on the other hand can +# execute up to 8 AES instructions at a time, so how does varying +# interleave factor affect the performance? Here is table for ECB +# (numbers are cycles per byte processed with 128-bit key): +# +# instruction interleave factor 3x 6x 8x +# theoretical asymptotic limit 1.67 0.83 0.625 +# measured performance for 8KB block 1.05 0.86 0.84 +# +# "as if" interleave factor 4.7x 5.8x 6.0x +# +# Further data for other parallelizable modes: +# +# CBC decrypt 1.16 0.93 0.74 +# CTR 1.14 0.91 0.74 +# +# Well, given 3x column it's probably inappropriate to call the limit +# asymptotic, if it can be surpassed, isn't it? What happens there? +# Rewind to CBC paragraph for the answer. Yes, out-of-order execution +# magic is responsible for this. Processor overlaps not only the +# additional instructions with AES ones, but even AES instructions +# processing adjacent triplets of independent blocks. In the 6x case +# additional instructions still claim disproportionally small amount +# of additional cycles, but in 8x case number of instructions must be +# a tad too high for out-of-order logic to cope with, and AES unit +# remains underutilized... As you can see 8x interleave is hardly +# justifiable, so there no need to feel bad that 32-bit aesni-x86.pl +# utilizes 6x interleave because of limited register bank capacity. +# +# Higher interleave factors do have negative impact on Westmere +# performance. While for ECB mode it's negligible ~1.5%, other +# parallelizables perform ~5% worse, which is outweighed by ~25% +# improvement on Sandy Bridge. To balance regression on Westmere +# CTR mode was implemented with 6x aesenc interleave factor. + +# April 2011 +# +# Add aesni_xts_[en|de]crypt. Westmere spends 1.25 cycles processing +# one byte out of 8KB with 128-bit key, Sandy Bridge - 0.90. Just like +# in CTR mode AES instruction interleave factor was chosen to be 6x. + +# November 2015 +# +# Add aesni_ocb_[en|de]crypt. AES instruction interleave factor was +# chosen to be 6x. + +###################################################################### +# Current large-block performance in cycles per byte processed with +# 128-bit key (less is better). +# +# CBC en-/decrypt CTR XTS ECB OCB +# Westmere 3.77/1.25 1.25 1.25 1.26 +# * Bridge 5.07/0.74 0.75 0.90 0.85 0.98 +# Haswell 4.44/0.63 0.63 0.73 0.63 0.70 +# Skylake 2.62/0.63 0.63 0.63 0.63 +# Silvermont 5.75/3.54 3.56 4.12 3.87(*) 4.11 +# Knights L 2.54/0.77 0.78 0.85 - 1.50 +# Goldmont 3.82/1.26 1.26 1.29 1.29 1.50 +# Bulldozer 5.77/0.70 0.72 0.90 0.70 0.95 +# Ryzen 2.71/0.35 0.35 0.44 0.38 0.49 +# +# (*) Atom Silvermont ECB result is suboptimal because of penalties +# incurred by operations on %xmm8-15. As ECB is not considered +# critical, nothing was done to mitigate the problem. + +$PREFIX="aesni"; # if $PREFIX is set to "AES", the script + # generates drop-in replacement for + # crypto/aes/asm/aes-x86_64.pl:-) + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +*STDOUT=*OUT; + +$movkey = $PREFIX eq "aesni" ? "movups" : "movups"; +@_4args=$win64? ("%rcx","%rdx","%r8", "%r9") : # Win64 order + ("%rdi","%rsi","%rdx","%rcx"); # Unix order + +$code=".text\n"; +$code.=".extern OPENSSL_ia32cap_P\n"; + +$rounds="%eax"; # input to and changed by aesni_[en|de]cryptN !!! +# this is natural Unix argument order for public $PREFIX_[ecb|cbc]_encrypt ... +$inp="%rdi"; +$out="%rsi"; +$len="%rdx"; +$key="%rcx"; # input to and changed by aesni_[en|de]cryptN !!! +$ivp="%r8"; # cbc, ctr, ... + +$rnds_="%r10d"; # backup copy for $rounds +$key_="%r11"; # backup copy for $key + +# %xmm register layout +$rndkey0="%xmm0"; $rndkey1="%xmm1"; +$inout0="%xmm2"; $inout1="%xmm3"; +$inout2="%xmm4"; $inout3="%xmm5"; +$inout4="%xmm6"; $inout5="%xmm7"; +$inout6="%xmm8"; $inout7="%xmm9"; + +$in2="%xmm6"; $in1="%xmm7"; # used in CBC decrypt, CTR, ... +$in0="%xmm8"; $iv="%xmm9"; + +# Inline version of internal aesni_[en|de]crypt1. +# +# Why folded loop? Because aes[enc|dec] is slow enough to accommodate +# cycles which take care of loop variables... +{ my $sn; +sub aesni_generate1 { +my ($p,$key,$rounds,$inout,$ivec)=@_; $inout=$inout0 if (!defined($inout)); +++$sn; +$code.=<<___; + $movkey ($key),$rndkey0 + $movkey 16($key),$rndkey1 +___ +$code.=<<___ if (defined($ivec)); + xorps $rndkey0,$ivec + lea 32($key),$key + xorps $ivec,$inout +___ +$code.=<<___ if (!defined($ivec)); + lea 32($key),$key + xorps $rndkey0,$inout +___ +$code.=<<___; +.Loop_${p}1_$sn: + aes${p} $rndkey1,$inout + dec $rounds + $movkey ($key),$rndkey1 + lea 16($key),$key + jnz .Loop_${p}1_$sn # loop body is 16 bytes + aes${p}last $rndkey1,$inout +___ +}} +# void $PREFIX_[en|de]crypt (const void *inp,void *out,const AES_KEY *key); +# +{ my ($inp,$out,$key) = @_4args; + +$code.=<<___; +.globl ${PREFIX}_encrypt +.type ${PREFIX}_encrypt,\@abi-omnipotent +.align 16 +${PREFIX}_encrypt: +.cfi_startproc + movups ($inp),$inout0 # load input + mov 240($key),$rounds # key->rounds +___ + &aesni_generate1("enc",$key,$rounds); +$code.=<<___; + pxor $rndkey0,$rndkey0 # clear register bank + pxor $rndkey1,$rndkey1 + movups $inout0,($out) # output + pxor $inout0,$inout0 + ret +.cfi_endproc +.size ${PREFIX}_encrypt,.-${PREFIX}_encrypt + +.globl ${PREFIX}_decrypt +.type ${PREFIX}_decrypt,\@abi-omnipotent +.align 16 +${PREFIX}_decrypt: +.cfi_startproc + movups ($inp),$inout0 # load input + mov 240($key),$rounds # key->rounds +___ + &aesni_generate1("dec",$key,$rounds); +$code.=<<___; + pxor $rndkey0,$rndkey0 # clear register bank + pxor $rndkey1,$rndkey1 + movups $inout0,($out) # output + pxor $inout0,$inout0 + ret +.cfi_endproc +.size ${PREFIX}_decrypt, .-${PREFIX}_decrypt +___ +} + +# _aesni_[en|de]cryptN are private interfaces, N denotes interleave +# factor. Why 3x subroutine were originally used in loops? Even though +# aes[enc|dec] latency was originally 6, it could be scheduled only +# every *2nd* cycle. Thus 3x interleave was the one providing optimal +# utilization, i.e. when subroutine's throughput is virtually same as +# of non-interleaved subroutine [for number of input blocks up to 3]. +# This is why it originally made no sense to implement 2x subroutine. +# But times change and it became appropriate to spend extra 192 bytes +# on 2x subroutine on Atom Silvermont account. For processors that +# can schedule aes[enc|dec] every cycle optimal interleave factor +# equals to corresponding instructions latency. 8x is optimal for +# * Bridge and "super-optimal" for other Intel CPUs... + +sub aesni_generate2 { +my $dir=shift; +# As already mentioned it takes in $key and $rounds, which are *not* +# preserved. $inout[0-1] is cipher/clear text... +$code.=<<___; +.type _aesni_${dir}rypt2,\@abi-omnipotent +.align 16 +_aesni_${dir}rypt2: +.cfi_startproc + $movkey ($key),$rndkey0 + shl \$4,$rounds + $movkey 16($key),$rndkey1 + xorps $rndkey0,$inout0 + xorps $rndkey0,$inout1 + $movkey 32($key),$rndkey0 + lea 32($key,$rounds),$key + neg %rax # $rounds + add \$16,%rax + +.L${dir}_loop2: + aes${dir} $rndkey1,$inout0 + aes${dir} $rndkey1,$inout1 + $movkey ($key,%rax),$rndkey1 + add \$32,%rax + aes${dir} $rndkey0,$inout0 + aes${dir} $rndkey0,$inout1 + $movkey -16($key,%rax),$rndkey0 + jnz .L${dir}_loop2 + + aes${dir} $rndkey1,$inout0 + aes${dir} $rndkey1,$inout1 + aes${dir}last $rndkey0,$inout0 + aes${dir}last $rndkey0,$inout1 + ret +.cfi_endproc +.size _aesni_${dir}rypt2,.-_aesni_${dir}rypt2 +___ +} +sub aesni_generate3 { +my $dir=shift; +# As already mentioned it takes in $key and $rounds, which are *not* +# preserved. $inout[0-2] is cipher/clear text... +$code.=<<___; +.type _aesni_${dir}rypt3,\@abi-omnipotent +.align 16 +_aesni_${dir}rypt3: +.cfi_startproc + $movkey ($key),$rndkey0 + shl \$4,$rounds + $movkey 16($key),$rndkey1 + xorps $rndkey0,$inout0 + xorps $rndkey0,$inout1 + xorps $rndkey0,$inout2 + $movkey 32($key),$rndkey0 + lea 32($key,$rounds),$key + neg %rax # $rounds + add \$16,%rax + +.L${dir}_loop3: + aes${dir} $rndkey1,$inout0 + aes${dir} $rndkey1,$inout1 + aes${dir} $rndkey1,$inout2 + $movkey ($key,%rax),$rndkey1 + add \$32,%rax + aes${dir} $rndkey0,$inout0 + aes${dir} $rndkey0,$inout1 + aes${dir} $rndkey0,$inout2 + $movkey -16($key,%rax),$rndkey0 + jnz .L${dir}_loop3 + + aes${dir} $rndkey1,$inout0 + aes${dir} $rndkey1,$inout1 + aes${dir} $rndkey1,$inout2 + aes${dir}last $rndkey0,$inout0 + aes${dir}last $rndkey0,$inout1 + aes${dir}last $rndkey0,$inout2 + ret +.cfi_endproc +.size _aesni_${dir}rypt3,.-_aesni_${dir}rypt3 +___ +} +# 4x interleave is implemented to improve small block performance, +# most notably [and naturally] 4 block by ~30%. One can argue that one +# should have implemented 5x as well, but improvement would be <20%, +# so it's not worth it... +sub aesni_generate4 { +my $dir=shift; +# As already mentioned it takes in $key and $rounds, which are *not* +# preserved. $inout[0-3] is cipher/clear text... +$code.=<<___; +.type _aesni_${dir}rypt4,\@abi-omnipotent +.align 16 +_aesni_${dir}rypt4: +.cfi_startproc + $movkey ($key),$rndkey0 + shl \$4,$rounds + $movkey 16($key),$rndkey1 + xorps $rndkey0,$inout0 + xorps $rndkey0,$inout1 + xorps $rndkey0,$inout2 + xorps $rndkey0,$inout3 + $movkey 32($key),$rndkey0 + lea 32($key,$rounds),$key + neg %rax # $rounds + .byte 0x0f,0x1f,0x00 + add \$16,%rax + +.L${dir}_loop4: + aes${dir} $rndkey1,$inout0 + aes${dir} $rndkey1,$inout1 + aes${dir} $rndkey1,$inout2 + aes${dir} $rndkey1,$inout3 + $movkey ($key,%rax),$rndkey1 + add \$32,%rax + aes${dir} $rndkey0,$inout0 + aes${dir} $rndkey0,$inout1 + aes${dir} $rndkey0,$inout2 + aes${dir} $rndkey0,$inout3 + $movkey -16($key,%rax),$rndkey0 + jnz .L${dir}_loop4 + + aes${dir} $rndkey1,$inout0 + aes${dir} $rndkey1,$inout1 + aes${dir} $rndkey1,$inout2 + aes${dir} $rndkey1,$inout3 + aes${dir}last $rndkey0,$inout0 + aes${dir}last $rndkey0,$inout1 + aes${dir}last $rndkey0,$inout2 + aes${dir}last $rndkey0,$inout3 + ret +.cfi_endproc +.size _aesni_${dir}rypt4,.-_aesni_${dir}rypt4 +___ +} +sub aesni_generate6 { +my $dir=shift; +# As already mentioned it takes in $key and $rounds, which are *not* +# preserved. $inout[0-5] is cipher/clear text... +$code.=<<___; +.type _aesni_${dir}rypt6,\@abi-omnipotent +.align 16 +_aesni_${dir}rypt6: +.cfi_startproc + $movkey ($key),$rndkey0 + shl \$4,$rounds + $movkey 16($key),$rndkey1 + xorps $rndkey0,$inout0 + pxor $rndkey0,$inout1 + pxor $rndkey0,$inout2 + aes${dir} $rndkey1,$inout0 + lea 32($key,$rounds),$key + neg %rax # $rounds + aes${dir} $rndkey1,$inout1 + pxor $rndkey0,$inout3 + pxor $rndkey0,$inout4 + aes${dir} $rndkey1,$inout2 + pxor $rndkey0,$inout5 + $movkey ($key,%rax),$rndkey0 + add \$16,%rax + jmp .L${dir}_loop6_enter +.align 16 +.L${dir}_loop6: + aes${dir} $rndkey1,$inout0 + aes${dir} $rndkey1,$inout1 + aes${dir} $rndkey1,$inout2 +.L${dir}_loop6_enter: + aes${dir} $rndkey1,$inout3 + aes${dir} $rndkey1,$inout4 + aes${dir} $rndkey1,$inout5 + $movkey ($key,%rax),$rndkey1 + add \$32,%rax + aes${dir} $rndkey0,$inout0 + aes${dir} $rndkey0,$inout1 + aes${dir} $rndkey0,$inout2 + aes${dir} $rndkey0,$inout3 + aes${dir} $rndkey0,$inout4 + aes${dir} $rndkey0,$inout5 + $movkey -16($key,%rax),$rndkey0 + jnz .L${dir}_loop6 + + aes${dir} $rndkey1,$inout0 + aes${dir} $rndkey1,$inout1 + aes${dir} $rndkey1,$inout2 + aes${dir} $rndkey1,$inout3 + aes${dir} $rndkey1,$inout4 + aes${dir} $rndkey1,$inout5 + aes${dir}last $rndkey0,$inout0 + aes${dir}last $rndkey0,$inout1 + aes${dir}last $rndkey0,$inout2 + aes${dir}last $rndkey0,$inout3 + aes${dir}last $rndkey0,$inout4 + aes${dir}last $rndkey0,$inout5 + ret +.cfi_endproc +.size _aesni_${dir}rypt6,.-_aesni_${dir}rypt6 +___ +} +sub aesni_generate8 { +my $dir=shift; +# As already mentioned it takes in $key and $rounds, which are *not* +# preserved. $inout[0-7] is cipher/clear text... +$code.=<<___; +.type _aesni_${dir}rypt8,\@abi-omnipotent +.align 16 +_aesni_${dir}rypt8: +.cfi_startproc + $movkey ($key),$rndkey0 + shl \$4,$rounds + $movkey 16($key),$rndkey1 + xorps $rndkey0,$inout0 + xorps $rndkey0,$inout1 + pxor $rndkey0,$inout2 + pxor $rndkey0,$inout3 + pxor $rndkey0,$inout4 + lea 32($key,$rounds),$key + neg %rax # $rounds + aes${dir} $rndkey1,$inout0 + pxor $rndkey0,$inout5 + pxor $rndkey0,$inout6 + aes${dir} $rndkey1,$inout1 + pxor $rndkey0,$inout7 + $movkey ($key,%rax),$rndkey0 + add \$16,%rax + jmp .L${dir}_loop8_inner +.align 16 +.L${dir}_loop8: + aes${dir} $rndkey1,$inout0 + aes${dir} $rndkey1,$inout1 +.L${dir}_loop8_inner: + aes${dir} $rndkey1,$inout2 + aes${dir} $rndkey1,$inout3 + aes${dir} $rndkey1,$inout4 + aes${dir} $rndkey1,$inout5 + aes${dir} $rndkey1,$inout6 + aes${dir} $rndkey1,$inout7 +.L${dir}_loop8_enter: + $movkey ($key,%rax),$rndkey1 + add \$32,%rax + aes${dir} $rndkey0,$inout0 + aes${dir} $rndkey0,$inout1 + aes${dir} $rndkey0,$inout2 + aes${dir} $rndkey0,$inout3 + aes${dir} $rndkey0,$inout4 + aes${dir} $rndkey0,$inout5 + aes${dir} $rndkey0,$inout6 + aes${dir} $rndkey0,$inout7 + $movkey -16($key,%rax),$rndkey0 + jnz .L${dir}_loop8 + + aes${dir} $rndkey1,$inout0 + aes${dir} $rndkey1,$inout1 + aes${dir} $rndkey1,$inout2 + aes${dir} $rndkey1,$inout3 + aes${dir} $rndkey1,$inout4 + aes${dir} $rndkey1,$inout5 + aes${dir} $rndkey1,$inout6 + aes${dir} $rndkey1,$inout7 + aes${dir}last $rndkey0,$inout0 + aes${dir}last $rndkey0,$inout1 + aes${dir}last $rndkey0,$inout2 + aes${dir}last $rndkey0,$inout3 + aes${dir}last $rndkey0,$inout4 + aes${dir}last $rndkey0,$inout5 + aes${dir}last $rndkey0,$inout6 + aes${dir}last $rndkey0,$inout7 + ret +.cfi_endproc +.size _aesni_${dir}rypt8,.-_aesni_${dir}rypt8 +___ +} +&aesni_generate2("enc") if ($PREFIX eq "aesni"); +&aesni_generate2("dec"); +&aesni_generate3("enc") if ($PREFIX eq "aesni"); +&aesni_generate3("dec"); +&aesni_generate4("enc") if ($PREFIX eq "aesni"); +&aesni_generate4("dec"); +&aesni_generate6("enc") if ($PREFIX eq "aesni"); +&aesni_generate6("dec"); +&aesni_generate8("enc") if ($PREFIX eq "aesni"); +&aesni_generate8("dec"); + +if ($PREFIX eq "aesni") { +######################################################################## +# void aesni_ecb_encrypt (const void *in, void *out, +# size_t length, const AES_KEY *key, +# int enc); +$code.=<<___; +.globl aesni_ecb_encrypt +.type aesni_ecb_encrypt,\@function,5 +.align 16 +aesni_ecb_encrypt: +.cfi_startproc +___ +$code.=<<___ if ($win64); + lea -0x58(%rsp),%rsp + movaps %xmm6,(%rsp) # offload $inout4..7 + movaps %xmm7,0x10(%rsp) + movaps %xmm8,0x20(%rsp) + movaps %xmm9,0x30(%rsp) +.Lecb_enc_body: +___ +$code.=<<___; + and \$-16,$len # if ($len<16) + jz .Lecb_ret # return + + mov 240($key),$rounds # key->rounds + $movkey ($key),$rndkey0 + mov $key,$key_ # backup $key + mov $rounds,$rnds_ # backup $rounds + test %r8d,%r8d # 5th argument + jz .Lecb_decrypt +#--------------------------- ECB ENCRYPT ------------------------------# + cmp \$0x80,$len # if ($len<8*16) + jb .Lecb_enc_tail # short input + + movdqu ($inp),$inout0 # load 8 input blocks + movdqu 0x10($inp),$inout1 + movdqu 0x20($inp),$inout2 + movdqu 0x30($inp),$inout3 + movdqu 0x40($inp),$inout4 + movdqu 0x50($inp),$inout5 + movdqu 0x60($inp),$inout6 + movdqu 0x70($inp),$inout7 + lea 0x80($inp),$inp # $inp+=8*16 + sub \$0x80,$len # $len-=8*16 (can be zero) + jmp .Lecb_enc_loop8_enter +.align 16 +.Lecb_enc_loop8: + movups $inout0,($out) # store 8 output blocks + mov $key_,$key # restore $key + movdqu ($inp),$inout0 # load 8 input blocks + mov $rnds_,$rounds # restore $rounds + movups $inout1,0x10($out) + movdqu 0x10($inp),$inout1 + movups $inout2,0x20($out) + movdqu 0x20($inp),$inout2 + movups $inout3,0x30($out) + movdqu 0x30($inp),$inout3 + movups $inout4,0x40($out) + movdqu 0x40($inp),$inout4 + movups $inout5,0x50($out) + movdqu 0x50($inp),$inout5 + movups $inout6,0x60($out) + movdqu 0x60($inp),$inout6 + movups $inout7,0x70($out) + lea 0x80($out),$out # $out+=8*16 + movdqu 0x70($inp),$inout7 + lea 0x80($inp),$inp # $inp+=8*16 +.Lecb_enc_loop8_enter: + + call _aesni_encrypt8 + + sub \$0x80,$len + jnc .Lecb_enc_loop8 # loop if $len-=8*16 didn't borrow + + movups $inout0,($out) # store 8 output blocks + mov $key_,$key # restore $key + movups $inout1,0x10($out) + mov $rnds_,$rounds # restore $rounds + movups $inout2,0x20($out) + movups $inout3,0x30($out) + movups $inout4,0x40($out) + movups $inout5,0x50($out) + movups $inout6,0x60($out) + movups $inout7,0x70($out) + lea 0x80($out),$out # $out+=8*16 + add \$0x80,$len # restore real remaining $len + jz .Lecb_ret # done if ($len==0) + +.Lecb_enc_tail: # $len is less than 8*16 + movups ($inp),$inout0 + cmp \$0x20,$len + jb .Lecb_enc_one + movups 0x10($inp),$inout1 + je .Lecb_enc_two + movups 0x20($inp),$inout2 + cmp \$0x40,$len + jb .Lecb_enc_three + movups 0x30($inp),$inout3 + je .Lecb_enc_four + movups 0x40($inp),$inout4 + cmp \$0x60,$len + jb .Lecb_enc_five + movups 0x50($inp),$inout5 + je .Lecb_enc_six + movdqu 0x60($inp),$inout6 + xorps $inout7,$inout7 + call _aesni_encrypt8 + movups $inout0,($out) # store 7 output blocks + movups $inout1,0x10($out) + movups $inout2,0x20($out) + movups $inout3,0x30($out) + movups $inout4,0x40($out) + movups $inout5,0x50($out) + movups $inout6,0x60($out) + jmp .Lecb_ret +.align 16 +.Lecb_enc_one: +___ + &aesni_generate1("enc",$key,$rounds); +$code.=<<___; + movups $inout0,($out) # store one output block + jmp .Lecb_ret +.align 16 +.Lecb_enc_two: + call _aesni_encrypt2 + movups $inout0,($out) # store 2 output blocks + movups $inout1,0x10($out) + jmp .Lecb_ret +.align 16 +.Lecb_enc_three: + call _aesni_encrypt3 + movups $inout0,($out) # store 3 output blocks + movups $inout1,0x10($out) + movups $inout2,0x20($out) + jmp .Lecb_ret +.align 16 +.Lecb_enc_four: + call _aesni_encrypt4 + movups $inout0,($out) # store 4 output blocks + movups $inout1,0x10($out) + movups $inout2,0x20($out) + movups $inout3,0x30($out) + jmp .Lecb_ret +.align 16 +.Lecb_enc_five: + xorps $inout5,$inout5 + call _aesni_encrypt6 + movups $inout0,($out) # store 5 output blocks + movups $inout1,0x10($out) + movups $inout2,0x20($out) + movups $inout3,0x30($out) + movups $inout4,0x40($out) + jmp .Lecb_ret +.align 16 +.Lecb_enc_six: + call _aesni_encrypt6 + movups $inout0,($out) # store 6 output blocks + movups $inout1,0x10($out) + movups $inout2,0x20($out) + movups $inout3,0x30($out) + movups $inout4,0x40($out) + movups $inout5,0x50($out) + jmp .Lecb_ret + #--------------------------- ECB DECRYPT ------------------------------# +.align 16 +.Lecb_decrypt: + cmp \$0x80,$len # if ($len<8*16) + jb .Lecb_dec_tail # short input + + movdqu ($inp),$inout0 # load 8 input blocks + movdqu 0x10($inp),$inout1 + movdqu 0x20($inp),$inout2 + movdqu 0x30($inp),$inout3 + movdqu 0x40($inp),$inout4 + movdqu 0x50($inp),$inout5 + movdqu 0x60($inp),$inout6 + movdqu 0x70($inp),$inout7 + lea 0x80($inp),$inp # $inp+=8*16 + sub \$0x80,$len # $len-=8*16 (can be zero) + jmp .Lecb_dec_loop8_enter +.align 16 +.Lecb_dec_loop8: + movups $inout0,($out) # store 8 output blocks + mov $key_,$key # restore $key + movdqu ($inp),$inout0 # load 8 input blocks + mov $rnds_,$rounds # restore $rounds + movups $inout1,0x10($out) + movdqu 0x10($inp),$inout1 + movups $inout2,0x20($out) + movdqu 0x20($inp),$inout2 + movups $inout3,0x30($out) + movdqu 0x30($inp),$inout3 + movups $inout4,0x40($out) + movdqu 0x40($inp),$inout4 + movups $inout5,0x50($out) + movdqu 0x50($inp),$inout5 + movups $inout6,0x60($out) + movdqu 0x60($inp),$inout6 + movups $inout7,0x70($out) + lea 0x80($out),$out # $out+=8*16 + movdqu 0x70($inp),$inout7 + lea 0x80($inp),$inp # $inp+=8*16 +.Lecb_dec_loop8_enter: + + call _aesni_decrypt8 + + $movkey ($key_),$rndkey0 + sub \$0x80,$len + jnc .Lecb_dec_loop8 # loop if $len-=8*16 didn't borrow + + movups $inout0,($out) # store 8 output blocks + pxor $inout0,$inout0 # clear register bank + mov $key_,$key # restore $key + movups $inout1,0x10($out) + pxor $inout1,$inout1 + mov $rnds_,$rounds # restore $rounds + movups $inout2,0x20($out) + pxor $inout2,$inout2 + movups $inout3,0x30($out) + pxor $inout3,$inout3 + movups $inout4,0x40($out) + pxor $inout4,$inout4 + movups $inout5,0x50($out) + pxor $inout5,$inout5 + movups $inout6,0x60($out) + pxor $inout6,$inout6 + movups $inout7,0x70($out) + pxor $inout7,$inout7 + lea 0x80($out),$out # $out+=8*16 + add \$0x80,$len # restore real remaining $len + jz .Lecb_ret # done if ($len==0) + +.Lecb_dec_tail: + movups ($inp),$inout0 + cmp \$0x20,$len + jb .Lecb_dec_one + movups 0x10($inp),$inout1 + je .Lecb_dec_two + movups 0x20($inp),$inout2 + cmp \$0x40,$len + jb .Lecb_dec_three + movups 0x30($inp),$inout3 + je .Lecb_dec_four + movups 0x40($inp),$inout4 + cmp \$0x60,$len + jb .Lecb_dec_five + movups 0x50($inp),$inout5 + je .Lecb_dec_six + movups 0x60($inp),$inout6 + $movkey ($key),$rndkey0 + xorps $inout7,$inout7 + call _aesni_decrypt8 + movups $inout0,($out) # store 7 output blocks + pxor $inout0,$inout0 # clear register bank + movups $inout1,0x10($out) + pxor $inout1,$inout1 + movups $inout2,0x20($out) + pxor $inout2,$inout2 + movups $inout3,0x30($out) + pxor $inout3,$inout3 + movups $inout4,0x40($out) + pxor $inout4,$inout4 + movups $inout5,0x50($out) + pxor $inout5,$inout5 + movups $inout6,0x60($out) + pxor $inout6,$inout6 + pxor $inout7,$inout7 + jmp .Lecb_ret +.align 16 +.Lecb_dec_one: +___ + &aesni_generate1("dec",$key,$rounds); +$code.=<<___; + movups $inout0,($out) # store one output block + pxor $inout0,$inout0 # clear register bank + jmp .Lecb_ret +.align 16 +.Lecb_dec_two: + call _aesni_decrypt2 + movups $inout0,($out) # store 2 output blocks + pxor $inout0,$inout0 # clear register bank + movups $inout1,0x10($out) + pxor $inout1,$inout1 + jmp .Lecb_ret +.align 16 +.Lecb_dec_three: + call _aesni_decrypt3 + movups $inout0,($out) # store 3 output blocks + pxor $inout0,$inout0 # clear register bank + movups $inout1,0x10($out) + pxor $inout1,$inout1 + movups $inout2,0x20($out) + pxor $inout2,$inout2 + jmp .Lecb_ret +.align 16 +.Lecb_dec_four: + call _aesni_decrypt4 + movups $inout0,($out) # store 4 output blocks + pxor $inout0,$inout0 # clear register bank + movups $inout1,0x10($out) + pxor $inout1,$inout1 + movups $inout2,0x20($out) + pxor $inout2,$inout2 + movups $inout3,0x30($out) + pxor $inout3,$inout3 + jmp .Lecb_ret +.align 16 +.Lecb_dec_five: + xorps $inout5,$inout5 + call _aesni_decrypt6 + movups $inout0,($out) # store 5 output blocks + pxor $inout0,$inout0 # clear register bank + movups $inout1,0x10($out) + pxor $inout1,$inout1 + movups $inout2,0x20($out) + pxor $inout2,$inout2 + movups $inout3,0x30($out) + pxor $inout3,$inout3 + movups $inout4,0x40($out) + pxor $inout4,$inout4 + pxor $inout5,$inout5 + jmp .Lecb_ret +.align 16 +.Lecb_dec_six: + call _aesni_decrypt6 + movups $inout0,($out) # store 6 output blocks + pxor $inout0,$inout0 # clear register bank + movups $inout1,0x10($out) + pxor $inout1,$inout1 + movups $inout2,0x20($out) + pxor $inout2,$inout2 + movups $inout3,0x30($out) + pxor $inout3,$inout3 + movups $inout4,0x40($out) + pxor $inout4,$inout4 + movups $inout5,0x50($out) + pxor $inout5,$inout5 + +.Lecb_ret: + xorps $rndkey0,$rndkey0 # %xmm0 + pxor $rndkey1,$rndkey1 +___ +$code.=<<___ if ($win64); + movaps (%rsp),%xmm6 + movaps %xmm0,(%rsp) # clear stack + movaps 0x10(%rsp),%xmm7 + movaps %xmm0,0x10(%rsp) + movaps 0x20(%rsp),%xmm8 + movaps %xmm0,0x20(%rsp) + movaps 0x30(%rsp),%xmm9 + movaps %xmm0,0x30(%rsp) + lea 0x58(%rsp),%rsp +.Lecb_enc_ret: +___ +$code.=<<___; + ret +.cfi_endproc +.size aesni_ecb_encrypt,.-aesni_ecb_encrypt +___ + +{ +###################################################################### +# void aesni_ccm64_[en|de]crypt_blocks (const void *in, void *out, +# size_t blocks, const AES_KEY *key, +# const char *ivec,char *cmac); +# +# Handles only complete blocks, operates on 64-bit counter and +# does not update *ivec! Nor does it finalize CMAC value +# (see engine/eng_aesni.c for details) +# +{ +my $cmac="%r9"; # 6th argument + +my $increment="%xmm9"; +my $iv="%xmm6"; +my $bswap_mask="%xmm7"; + +$code.=<<___; +.globl aesni_ccm64_encrypt_blocks +.type aesni_ccm64_encrypt_blocks,\@function,6 +.align 16 +aesni_ccm64_encrypt_blocks: +___ +$code.=<<___ if ($win64); + lea -0x58(%rsp),%rsp + movaps %xmm6,(%rsp) # $iv + movaps %xmm7,0x10(%rsp) # $bswap_mask + movaps %xmm8,0x20(%rsp) # $in0 + movaps %xmm9,0x30(%rsp) # $increment +.Lccm64_enc_body: +___ +$code.=<<___; + mov 240($key),$rounds # key->rounds + movdqu ($ivp),$iv + movdqa .Lincrement64(%rip),$increment + movdqa .Lbswap_mask(%rip),$bswap_mask + + shl \$4,$rounds + mov \$16,$rnds_ + lea 0($key),$key_ + movdqu ($cmac),$inout1 + movdqa $iv,$inout0 + lea 32($key,$rounds),$key # end of key schedule + pshufb $bswap_mask,$iv + sub %rax,%r10 # twisted $rounds + jmp .Lccm64_enc_outer +.align 16 +.Lccm64_enc_outer: + $movkey ($key_),$rndkey0 + mov %r10,%rax + movups ($inp),$in0 # load inp + + xorps $rndkey0,$inout0 # counter + $movkey 16($key_),$rndkey1 + xorps $in0,$rndkey0 + xorps $rndkey0,$inout1 # cmac^=inp + $movkey 32($key_),$rndkey0 + +.Lccm64_enc2_loop: + aesenc $rndkey1,$inout0 + aesenc $rndkey1,$inout1 + $movkey ($key,%rax),$rndkey1 + add \$32,%rax + aesenc $rndkey0,$inout0 + aesenc $rndkey0,$inout1 + $movkey -16($key,%rax),$rndkey0 + jnz .Lccm64_enc2_loop + aesenc $rndkey1,$inout0 + aesenc $rndkey1,$inout1 + paddq $increment,$iv + dec $len # $len-- ($len is in blocks) + aesenclast $rndkey0,$inout0 + aesenclast $rndkey0,$inout1 + + lea 16($inp),$inp + xorps $inout0,$in0 # inp ^= E(iv) + movdqa $iv,$inout0 + movups $in0,($out) # save output + pshufb $bswap_mask,$inout0 + lea 16($out),$out # $out+=16 + jnz .Lccm64_enc_outer # loop if ($len!=0) + + pxor $rndkey0,$rndkey0 # clear register bank + pxor $rndkey1,$rndkey1 + pxor $inout0,$inout0 + movups $inout1,($cmac) # store resulting mac + pxor $inout1,$inout1 + pxor $in0,$in0 + pxor $iv,$iv +___ +$code.=<<___ if ($win64); + movaps (%rsp),%xmm6 + movaps %xmm0,(%rsp) # clear stack + movaps 0x10(%rsp),%xmm7 + movaps %xmm0,0x10(%rsp) + movaps 0x20(%rsp),%xmm8 + movaps %xmm0,0x20(%rsp) + movaps 0x30(%rsp),%xmm9 + movaps %xmm0,0x30(%rsp) + lea 0x58(%rsp),%rsp +.Lccm64_enc_ret: +___ +$code.=<<___; + ret +.size aesni_ccm64_encrypt_blocks,.-aesni_ccm64_encrypt_blocks +___ +###################################################################### +$code.=<<___; +.globl aesni_ccm64_decrypt_blocks +.type aesni_ccm64_decrypt_blocks,\@function,6 +.align 16 +aesni_ccm64_decrypt_blocks: +___ +$code.=<<___ if ($win64); + lea -0x58(%rsp),%rsp + movaps %xmm6,(%rsp) # $iv + movaps %xmm7,0x10(%rsp) # $bswap_mask + movaps %xmm8,0x20(%rsp) # $in8 + movaps %xmm9,0x30(%rsp) # $increment +.Lccm64_dec_body: +___ +$code.=<<___; + mov 240($key),$rounds # key->rounds + movups ($ivp),$iv + movdqu ($cmac),$inout1 + movdqa .Lincrement64(%rip),$increment + movdqa .Lbswap_mask(%rip),$bswap_mask + + movaps $iv,$inout0 + mov $rounds,$rnds_ + mov $key,$key_ + pshufb $bswap_mask,$iv +___ + &aesni_generate1("enc",$key,$rounds); +$code.=<<___; + shl \$4,$rnds_ + mov \$16,$rounds + movups ($inp),$in0 # load inp + paddq $increment,$iv + lea 16($inp),$inp # $inp+=16 + sub %r10,%rax # twisted $rounds + lea 32($key_,$rnds_),$key # end of key schedule + mov %rax,%r10 + jmp .Lccm64_dec_outer +.align 16 +.Lccm64_dec_outer: + xorps $inout0,$in0 # inp ^= E(iv) + movdqa $iv,$inout0 + movups $in0,($out) # save output + lea 16($out),$out # $out+=16 + pshufb $bswap_mask,$inout0 + + sub \$1,$len # $len-- ($len is in blocks) + jz .Lccm64_dec_break # if ($len==0) break + + $movkey ($key_),$rndkey0 + mov %r10,%rax + $movkey 16($key_),$rndkey1 + xorps $rndkey0,$in0 + xorps $rndkey0,$inout0 + xorps $in0,$inout1 # cmac^=out + $movkey 32($key_),$rndkey0 + jmp .Lccm64_dec2_loop +.align 16 +.Lccm64_dec2_loop: + aesenc $rndkey1,$inout0 + aesenc $rndkey1,$inout1 + $movkey ($key,%rax),$rndkey1 + add \$32,%rax + aesenc $rndkey0,$inout0 + aesenc $rndkey0,$inout1 + $movkey -16($key,%rax),$rndkey0 + jnz .Lccm64_dec2_loop + movups ($inp),$in0 # load input + paddq $increment,$iv + aesenc $rndkey1,$inout0 + aesenc $rndkey1,$inout1 + aesenclast $rndkey0,$inout0 + aesenclast $rndkey0,$inout1 + lea 16($inp),$inp # $inp+=16 + jmp .Lccm64_dec_outer + +.align 16 +.Lccm64_dec_break: + #xorps $in0,$inout1 # cmac^=out + mov 240($key_),$rounds +___ + &aesni_generate1("enc",$key_,$rounds,$inout1,$in0); +$code.=<<___; + pxor $rndkey0,$rndkey0 # clear register bank + pxor $rndkey1,$rndkey1 + pxor $inout0,$inout0 + movups $inout1,($cmac) # store resulting mac + pxor $inout1,$inout1 + pxor $in0,$in0 + pxor $iv,$iv +___ +$code.=<<___ if ($win64); + movaps (%rsp),%xmm6 + movaps %xmm0,(%rsp) # clear stack + movaps 0x10(%rsp),%xmm7 + movaps %xmm0,0x10(%rsp) + movaps 0x20(%rsp),%xmm8 + movaps %xmm0,0x20(%rsp) + movaps 0x30(%rsp),%xmm9 + movaps %xmm0,0x30(%rsp) + lea 0x58(%rsp),%rsp +.Lccm64_dec_ret: +___ +$code.=<<___; + ret +.size aesni_ccm64_decrypt_blocks,.-aesni_ccm64_decrypt_blocks +___ +} +###################################################################### +# void aesni_ctr32_encrypt_blocks (const void *in, void *out, +# size_t blocks, const AES_KEY *key, +# const char *ivec); +# +# Handles only complete blocks, operates on 32-bit counter and +# does not update *ivec! (see crypto/modes/ctr128.c for details) +# +# Overhaul based on suggestions from Shay Gueron and Vlad Krasnov, +# http://rt.openssl.org/Ticket/Display.html?id=3021&user=guest&pass=guest. +# Keywords are full unroll and modulo-schedule counter calculations +# with zero-round key xor. +{ +my ($in0,$in1,$in2,$in3,$in4,$in5)=map("%xmm$_",(10..15)); +my ($key0,$ctr)=("%ebp","${ivp}d"); +my $frame_size = 0x80 + ($win64?160:0); + +$code.=<<___; +.globl aesni_ctr32_encrypt_blocks +.type aesni_ctr32_encrypt_blocks,\@function,5 +.align 16 +aesni_ctr32_encrypt_blocks: +.cfi_startproc + cmp \$1,$len + jne .Lctr32_bulk + + # handle single block without allocating stack frame, + # useful when handling edges + movups ($ivp),$inout0 + movups ($inp),$inout1 + mov 240($key),%edx # key->rounds +___ + &aesni_generate1("enc",$key,"%edx"); +$code.=<<___; + pxor $rndkey0,$rndkey0 # clear register bank + pxor $rndkey1,$rndkey1 + xorps $inout1,$inout0 + pxor $inout1,$inout1 + movups $inout0,($out) + xorps $inout0,$inout0 + jmp .Lctr32_epilogue + +.align 16 +.Lctr32_bulk: + lea (%rsp),$key_ # use $key_ as frame pointer +.cfi_def_cfa_register $key_ + push %rbp +.cfi_push %rbp + sub \$$frame_size,%rsp + and \$-16,%rsp # Linux kernel stack can be incorrectly seeded +___ +$code.=<<___ if ($win64); + movaps %xmm6,-0xa8($key_) # offload everything + movaps %xmm7,-0x98($key_) + movaps %xmm8,-0x88($key_) + movaps %xmm9,-0x78($key_) + movaps %xmm10,-0x68($key_) + movaps %xmm11,-0x58($key_) + movaps %xmm12,-0x48($key_) + movaps %xmm13,-0x38($key_) + movaps %xmm14,-0x28($key_) + movaps %xmm15,-0x18($key_) +.Lctr32_body: +___ +$code.=<<___; + + # 8 16-byte words on top of stack are counter values + # xor-ed with zero-round key + + movdqu ($ivp),$inout0 + movdqu ($key),$rndkey0 + mov 12($ivp),$ctr # counter LSB + pxor $rndkey0,$inout0 + mov 12($key),$key0 # 0-round key LSB + movdqa $inout0,0x00(%rsp) # populate counter block + bswap $ctr + movdqa $inout0,$inout1 + movdqa $inout0,$inout2 + movdqa $inout0,$inout3 + movdqa $inout0,0x40(%rsp) + movdqa $inout0,0x50(%rsp) + movdqa $inout0,0x60(%rsp) + mov %rdx,%r10 # about to borrow %rdx + movdqa $inout0,0x70(%rsp) + + lea 1($ctr),%rax + lea 2($ctr),%rdx + bswap %eax + bswap %edx + xor $key0,%eax + xor $key0,%edx + pinsrd \$3,%eax,$inout1 + lea 3($ctr),%rax + movdqa $inout1,0x10(%rsp) + pinsrd \$3,%edx,$inout2 + bswap %eax + mov %r10,%rdx # restore %rdx + lea 4($ctr),%r10 + movdqa $inout2,0x20(%rsp) + xor $key0,%eax + bswap %r10d + pinsrd \$3,%eax,$inout3 + xor $key0,%r10d + movdqa $inout3,0x30(%rsp) + lea 5($ctr),%r9 + mov %r10d,0x40+12(%rsp) + bswap %r9d + lea 6($ctr),%r10 + mov 240($key),$rounds # key->rounds + xor $key0,%r9d + bswap %r10d + mov %r9d,0x50+12(%rsp) + xor $key0,%r10d + lea 7($ctr),%r9 + mov %r10d,0x60+12(%rsp) + bswap %r9d + mov OPENSSL_ia32cap_P+4(%rip),%r10d + xor $key0,%r9d + and \$`1<<26|1<<22`,%r10d # isolate XSAVE+MOVBE + mov %r9d,0x70+12(%rsp) + + $movkey 0x10($key),$rndkey1 + + movdqa 0x40(%rsp),$inout4 + movdqa 0x50(%rsp),$inout5 + + cmp \$8,$len # $len is in blocks + jb .Lctr32_tail # short input if ($len<8) + + sub \$6,$len # $len is biased by -6 + cmp \$`1<<22`,%r10d # check for MOVBE without XSAVE + je .Lctr32_6x # [which denotes Atom Silvermont] + + lea 0x80($key),$key # size optimization + sub \$2,$len # $len is biased by -8 + jmp .Lctr32_loop8 + +.align 16 +.Lctr32_6x: + shl \$4,$rounds + mov \$48,$rnds_ + bswap $key0 + lea 32($key,$rounds),$key # end of key schedule + sub %rax,%r10 # twisted $rounds + jmp .Lctr32_loop6 + +.align 16 +.Lctr32_loop6: + add \$6,$ctr # next counter value + $movkey -48($key,$rnds_),$rndkey0 + aesenc $rndkey1,$inout0 + mov $ctr,%eax + xor $key0,%eax + aesenc $rndkey1,$inout1 + movbe %eax,`0x00+12`(%rsp) # store next counter value + lea 1($ctr),%eax + aesenc $rndkey1,$inout2 + xor $key0,%eax + movbe %eax,`0x10+12`(%rsp) + aesenc $rndkey1,$inout3 + lea 2($ctr),%eax + xor $key0,%eax + aesenc $rndkey1,$inout4 + movbe %eax,`0x20+12`(%rsp) + lea 3($ctr),%eax + aesenc $rndkey1,$inout5 + $movkey -32($key,$rnds_),$rndkey1 + xor $key0,%eax + + aesenc $rndkey0,$inout0 + movbe %eax,`0x30+12`(%rsp) + lea 4($ctr),%eax + aesenc $rndkey0,$inout1 + xor $key0,%eax + movbe %eax,`0x40+12`(%rsp) + aesenc $rndkey0,$inout2 + lea 5($ctr),%eax + xor $key0,%eax + aesenc $rndkey0,$inout3 + movbe %eax,`0x50+12`(%rsp) + mov %r10,%rax # mov $rnds_,$rounds + aesenc $rndkey0,$inout4 + aesenc $rndkey0,$inout5 + $movkey -16($key,$rnds_),$rndkey0 + + call .Lenc_loop6 + + movdqu ($inp),$inout6 # load 6 input blocks + movdqu 0x10($inp),$inout7 + movdqu 0x20($inp),$in0 + movdqu 0x30($inp),$in1 + movdqu 0x40($inp),$in2 + movdqu 0x50($inp),$in3 + lea 0x60($inp),$inp # $inp+=6*16 + $movkey -64($key,$rnds_),$rndkey1 + pxor $inout0,$inout6 # inp^=E(ctr) + movaps 0x00(%rsp),$inout0 # load next counter [xor-ed with 0 round] + pxor $inout1,$inout7 + movaps 0x10(%rsp),$inout1 + pxor $inout2,$in0 + movaps 0x20(%rsp),$inout2 + pxor $inout3,$in1 + movaps 0x30(%rsp),$inout3 + pxor $inout4,$in2 + movaps 0x40(%rsp),$inout4 + pxor $inout5,$in3 + movaps 0x50(%rsp),$inout5 + movdqu $inout6,($out) # store 6 output blocks + movdqu $inout7,0x10($out) + movdqu $in0,0x20($out) + movdqu $in1,0x30($out) + movdqu $in2,0x40($out) + movdqu $in3,0x50($out) + lea 0x60($out),$out # $out+=6*16 + + sub \$6,$len + jnc .Lctr32_loop6 # loop if $len-=6 didn't borrow + + add \$6,$len # restore real remaining $len + jz .Lctr32_done # done if ($len==0) + + lea -48($rnds_),$rounds + lea -80($key,$rnds_),$key # restore $key + neg $rounds + shr \$4,$rounds # restore $rounds + jmp .Lctr32_tail + +.align 32 +.Lctr32_loop8: + add \$8,$ctr # next counter value + movdqa 0x60(%rsp),$inout6 + aesenc $rndkey1,$inout0 + mov $ctr,%r9d + movdqa 0x70(%rsp),$inout7 + aesenc $rndkey1,$inout1 + bswap %r9d + $movkey 0x20-0x80($key),$rndkey0 + aesenc $rndkey1,$inout2 + xor $key0,%r9d + nop + aesenc $rndkey1,$inout3 + mov %r9d,0x00+12(%rsp) # store next counter value + lea 1($ctr),%r9 + aesenc $rndkey1,$inout4 + aesenc $rndkey1,$inout5 + aesenc $rndkey1,$inout6 + aesenc $rndkey1,$inout7 + $movkey 0x30-0x80($key),$rndkey1 +___ +for($i=2;$i<8;$i++) { +my $rndkeyx = ($i&1)?$rndkey1:$rndkey0; +$code.=<<___; + bswap %r9d + aesenc $rndkeyx,$inout0 + aesenc $rndkeyx,$inout1 + xor $key0,%r9d + .byte 0x66,0x90 + aesenc $rndkeyx,$inout2 + aesenc $rndkeyx,$inout3 + mov %r9d,`0x10*($i-1)`+12(%rsp) + lea $i($ctr),%r9 + aesenc $rndkeyx,$inout4 + aesenc $rndkeyx,$inout5 + aesenc $rndkeyx,$inout6 + aesenc $rndkeyx,$inout7 + $movkey `0x20+0x10*$i`-0x80($key),$rndkeyx +___ +} +$code.=<<___; + bswap %r9d + aesenc $rndkey0,$inout0 + aesenc $rndkey0,$inout1 + aesenc $rndkey0,$inout2 + xor $key0,%r9d + movdqu 0x00($inp),$in0 # start loading input + aesenc $rndkey0,$inout3 + mov %r9d,0x70+12(%rsp) + cmp \$11,$rounds + aesenc $rndkey0,$inout4 + aesenc $rndkey0,$inout5 + aesenc $rndkey0,$inout6 + aesenc $rndkey0,$inout7 + $movkey 0xa0-0x80($key),$rndkey0 + + jb .Lctr32_enc_done + + aesenc $rndkey1,$inout0 + aesenc $rndkey1,$inout1 + aesenc $rndkey1,$inout2 + aesenc $rndkey1,$inout3 + aesenc $rndkey1,$inout4 + aesenc $rndkey1,$inout5 + aesenc $rndkey1,$inout6 + aesenc $rndkey1,$inout7 + $movkey 0xb0-0x80($key),$rndkey1 + + aesenc $rndkey0,$inout0 + aesenc $rndkey0,$inout1 + aesenc $rndkey0,$inout2 + aesenc $rndkey0,$inout3 + aesenc $rndkey0,$inout4 + aesenc $rndkey0,$inout5 + aesenc $rndkey0,$inout6 + aesenc $rndkey0,$inout7 + $movkey 0xc0-0x80($key),$rndkey0 + je .Lctr32_enc_done + + aesenc $rndkey1,$inout0 + aesenc $rndkey1,$inout1 + aesenc $rndkey1,$inout2 + aesenc $rndkey1,$inout3 + aesenc $rndkey1,$inout4 + aesenc $rndkey1,$inout5 + aesenc $rndkey1,$inout6 + aesenc $rndkey1,$inout7 + $movkey 0xd0-0x80($key),$rndkey1 + + aesenc $rndkey0,$inout0 + aesenc $rndkey0,$inout1 + aesenc $rndkey0,$inout2 + aesenc $rndkey0,$inout3 + aesenc $rndkey0,$inout4 + aesenc $rndkey0,$inout5 + aesenc $rndkey0,$inout6 + aesenc $rndkey0,$inout7 + $movkey 0xe0-0x80($key),$rndkey0 + jmp .Lctr32_enc_done + +.align 16 +.Lctr32_enc_done: + movdqu 0x10($inp),$in1 + pxor $rndkey0,$in0 # input^=round[last] + movdqu 0x20($inp),$in2 + pxor $rndkey0,$in1 + movdqu 0x30($inp),$in3 + pxor $rndkey0,$in2 + movdqu 0x40($inp),$in4 + pxor $rndkey0,$in3 + movdqu 0x50($inp),$in5 + pxor $rndkey0,$in4 + pxor $rndkey0,$in5 + aesenc $rndkey1,$inout0 + aesenc $rndkey1,$inout1 + aesenc $rndkey1,$inout2 + aesenc $rndkey1,$inout3 + aesenc $rndkey1,$inout4 + aesenc $rndkey1,$inout5 + aesenc $rndkey1,$inout6 + aesenc $rndkey1,$inout7 + movdqu 0x60($inp),$rndkey1 # borrow $rndkey1 for inp[6] + lea 0x80($inp),$inp # $inp+=8*16 + + aesenclast $in0,$inout0 # $inN is inp[N]^round[last] + pxor $rndkey0,$rndkey1 # borrowed $rndkey + movdqu 0x70-0x80($inp),$in0 + aesenclast $in1,$inout1 + pxor $rndkey0,$in0 + movdqa 0x00(%rsp),$in1 # load next counter block + aesenclast $in2,$inout2 + aesenclast $in3,$inout3 + movdqa 0x10(%rsp),$in2 + movdqa 0x20(%rsp),$in3 + aesenclast $in4,$inout4 + aesenclast $in5,$inout5 + movdqa 0x30(%rsp),$in4 + movdqa 0x40(%rsp),$in5 + aesenclast $rndkey1,$inout6 + movdqa 0x50(%rsp),$rndkey0 + $movkey 0x10-0x80($key),$rndkey1#real 1st-round key + aesenclast $in0,$inout7 + + movups $inout0,($out) # store 8 output blocks + movdqa $in1,$inout0 + movups $inout1,0x10($out) + movdqa $in2,$inout1 + movups $inout2,0x20($out) + movdqa $in3,$inout2 + movups $inout3,0x30($out) + movdqa $in4,$inout3 + movups $inout4,0x40($out) + movdqa $in5,$inout4 + movups $inout5,0x50($out) + movdqa $rndkey0,$inout5 + movups $inout6,0x60($out) + movups $inout7,0x70($out) + lea 0x80($out),$out # $out+=8*16 + + sub \$8,$len + jnc .Lctr32_loop8 # loop if $len-=8 didn't borrow + + add \$8,$len # restore real remaining $len + jz .Lctr32_done # done if ($len==0) + lea -0x80($key),$key + +.Lctr32_tail: + # note that at this point $inout0..5 are populated with + # counter values xor-ed with 0-round key + lea 16($key),$key + cmp \$4,$len + jb .Lctr32_loop3 + je .Lctr32_loop4 + + # if ($len>4) compute 7 E(counter) + shl \$4,$rounds + movdqa 0x60(%rsp),$inout6 + pxor $inout7,$inout7 + + $movkey 16($key),$rndkey0 + aesenc $rndkey1,$inout0 + aesenc $rndkey1,$inout1 + lea 32-16($key,$rounds),$key# prepare for .Lenc_loop8_enter + neg %rax + aesenc $rndkey1,$inout2 + add \$16,%rax # prepare for .Lenc_loop8_enter + movups ($inp),$in0 + aesenc $rndkey1,$inout3 + aesenc $rndkey1,$inout4 + movups 0x10($inp),$in1 # pre-load input + movups 0x20($inp),$in2 + aesenc $rndkey1,$inout5 + aesenc $rndkey1,$inout6 + + call .Lenc_loop8_enter + + movdqu 0x30($inp),$in3 + pxor $in0,$inout0 + movdqu 0x40($inp),$in0 + pxor $in1,$inout1 + movdqu $inout0,($out) # store output + pxor $in2,$inout2 + movdqu $inout1,0x10($out) + pxor $in3,$inout3 + movdqu $inout2,0x20($out) + pxor $in0,$inout4 + movdqu $inout3,0x30($out) + movdqu $inout4,0x40($out) + cmp \$6,$len + jb .Lctr32_done # $len was 5, stop store + + movups 0x50($inp),$in1 + xorps $in1,$inout5 + movups $inout5,0x50($out) + je .Lctr32_done # $len was 6, stop store + + movups 0x60($inp),$in2 + xorps $in2,$inout6 + movups $inout6,0x60($out) + jmp .Lctr32_done # $len was 7, stop store + +.align 32 +.Lctr32_loop4: + aesenc $rndkey1,$inout0 + lea 16($key),$key + dec $rounds + aesenc $rndkey1,$inout1 + aesenc $rndkey1,$inout2 + aesenc $rndkey1,$inout3 + $movkey ($key),$rndkey1 + jnz .Lctr32_loop4 + aesenclast $rndkey1,$inout0 + aesenclast $rndkey1,$inout1 + movups ($inp),$in0 # load input + movups 0x10($inp),$in1 + aesenclast $rndkey1,$inout2 + aesenclast $rndkey1,$inout3 + movups 0x20($inp),$in2 + movups 0x30($inp),$in3 + + xorps $in0,$inout0 + movups $inout0,($out) # store output + xorps $in1,$inout1 + movups $inout1,0x10($out) + pxor $in2,$inout2 + movdqu $inout2,0x20($out) + pxor $in3,$inout3 + movdqu $inout3,0x30($out) + jmp .Lctr32_done # $len was 4, stop store + +.align 32 +.Lctr32_loop3: + aesenc $rndkey1,$inout0 + lea 16($key),$key + dec $rounds + aesenc $rndkey1,$inout1 + aesenc $rndkey1,$inout2 + $movkey ($key),$rndkey1 + jnz .Lctr32_loop3 + aesenclast $rndkey1,$inout0 + aesenclast $rndkey1,$inout1 + aesenclast $rndkey1,$inout2 + + movups ($inp),$in0 # load input + xorps $in0,$inout0 + movups $inout0,($out) # store output + cmp \$2,$len + jb .Lctr32_done # $len was 1, stop store + + movups 0x10($inp),$in1 + xorps $in1,$inout1 + movups $inout1,0x10($out) + je .Lctr32_done # $len was 2, stop store + + movups 0x20($inp),$in2 + xorps $in2,$inout2 + movups $inout2,0x20($out) # $len was 3, stop store + +.Lctr32_done: + xorps %xmm0,%xmm0 # clear register bank + xor $key0,$key0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 +___ +$code.=<<___ if (!$win64); + pxor %xmm6,%xmm6 + pxor %xmm7,%xmm7 + movaps %xmm0,0x00(%rsp) # clear stack + pxor %xmm8,%xmm8 + movaps %xmm0,0x10(%rsp) + pxor %xmm9,%xmm9 + movaps %xmm0,0x20(%rsp) + pxor %xmm10,%xmm10 + movaps %xmm0,0x30(%rsp) + pxor %xmm11,%xmm11 + movaps %xmm0,0x40(%rsp) + pxor %xmm12,%xmm12 + movaps %xmm0,0x50(%rsp) + pxor %xmm13,%xmm13 + movaps %xmm0,0x60(%rsp) + pxor %xmm14,%xmm14 + movaps %xmm0,0x70(%rsp) + pxor %xmm15,%xmm15 +___ +$code.=<<___ if ($win64); + movaps -0xa8($key_),%xmm6 + movaps %xmm0,-0xa8($key_) # clear stack + movaps -0x98($key_),%xmm7 + movaps %xmm0,-0x98($key_) + movaps -0x88($key_),%xmm8 + movaps %xmm0,-0x88($key_) + movaps -0x78($key_),%xmm9 + movaps %xmm0,-0x78($key_) + movaps -0x68($key_),%xmm10 + movaps %xmm0,-0x68($key_) + movaps -0x58($key_),%xmm11 + movaps %xmm0,-0x58($key_) + movaps -0x48($key_),%xmm12 + movaps %xmm0,-0x48($key_) + movaps -0x38($key_),%xmm13 + movaps %xmm0,-0x38($key_) + movaps -0x28($key_),%xmm14 + movaps %xmm0,-0x28($key_) + movaps -0x18($key_),%xmm15 + movaps %xmm0,-0x18($key_) + movaps %xmm0,0x00(%rsp) + movaps %xmm0,0x10(%rsp) + movaps %xmm0,0x20(%rsp) + movaps %xmm0,0x30(%rsp) + movaps %xmm0,0x40(%rsp) + movaps %xmm0,0x50(%rsp) + movaps %xmm0,0x60(%rsp) + movaps %xmm0,0x70(%rsp) +___ +$code.=<<___; + mov -8($key_),%rbp +.cfi_restore %rbp + lea ($key_),%rsp +.cfi_def_cfa_register %rsp +.Lctr32_epilogue: + ret +.cfi_endproc +.size aesni_ctr32_encrypt_blocks,.-aesni_ctr32_encrypt_blocks +___ +} + +###################################################################### +# void aesni_xts_[en|de]crypt(const char *inp,char *out,size_t len, +# const AES_KEY *key1, const AES_KEY *key2 +# const unsigned char iv[16]); +# +{ +my @tweak=map("%xmm$_",(10..15)); +my ($twmask,$twres,$twtmp)=("%xmm8","%xmm9",@tweak[4]); +my ($key2,$ivp,$len_)=("%r8","%r9","%r9"); +my $frame_size = 0x70 + ($win64?160:0); +my $key_ = "%rbp"; # override so that we can use %r11 as FP + +$code.=<<___; +.globl aesni_xts_encrypt +.type aesni_xts_encrypt,\@function,6 +.align 16 +aesni_xts_encrypt: +.cfi_startproc + lea (%rsp),%r11 # frame pointer +.cfi_def_cfa_register %r11 + push %rbp +.cfi_push %rbp + sub \$$frame_size,%rsp + and \$-16,%rsp # Linux kernel stack can be incorrectly seeded +___ +$code.=<<___ if ($win64); + movaps %xmm6,-0xa8(%r11) # offload everything + movaps %xmm7,-0x98(%r11) + movaps %xmm8,-0x88(%r11) + movaps %xmm9,-0x78(%r11) + movaps %xmm10,-0x68(%r11) + movaps %xmm11,-0x58(%r11) + movaps %xmm12,-0x48(%r11) + movaps %xmm13,-0x38(%r11) + movaps %xmm14,-0x28(%r11) + movaps %xmm15,-0x18(%r11) +.Lxts_enc_body: +___ +$code.=<<___; + movups ($ivp),$inout0 # load clear-text tweak + mov 240(%r8),$rounds # key2->rounds + mov 240($key),$rnds_ # key1->rounds +___ + # generate the tweak + &aesni_generate1("enc",$key2,$rounds,$inout0); +$code.=<<___; + $movkey ($key),$rndkey0 # zero round key + mov $key,$key_ # backup $key + mov $rnds_,$rounds # backup $rounds + shl \$4,$rnds_ + mov $len,$len_ # backup $len + and \$-16,$len + + $movkey 16($key,$rnds_),$rndkey1 # last round key + + movdqa .Lxts_magic(%rip),$twmask + movdqa $inout0,@tweak[5] + pshufd \$0x5f,$inout0,$twres + pxor $rndkey0,$rndkey1 +___ + # alternative tweak calculation algorithm is based on suggestions + # by Shay Gueron. psrad doesn't conflict with AES-NI instructions + # and should help in the future... + for ($i=0;$i<4;$i++) { + $code.=<<___; + movdqa $twres,$twtmp + paddd $twres,$twres + movdqa @tweak[5],@tweak[$i] + psrad \$31,$twtmp # broadcast upper bits + paddq @tweak[5],@tweak[5] + pand $twmask,$twtmp + pxor $rndkey0,@tweak[$i] + pxor $twtmp,@tweak[5] +___ + } +$code.=<<___; + movdqa @tweak[5],@tweak[4] + psrad \$31,$twres + paddq @tweak[5],@tweak[5] + pand $twmask,$twres + pxor $rndkey0,@tweak[4] + pxor $twres,@tweak[5] + movaps $rndkey1,0x60(%rsp) # save round[0]^round[last] + + sub \$16*6,$len + jc .Lxts_enc_short # if $len-=6*16 borrowed + + mov \$16+96,$rounds + lea 32($key_,$rnds_),$key # end of key schedule + sub %r10,%rax # twisted $rounds + $movkey 16($key_),$rndkey1 + mov %rax,%r10 # backup twisted $rounds + lea .Lxts_magic(%rip),%r8 + jmp .Lxts_enc_grandloop + +.align 32 +.Lxts_enc_grandloop: + movdqu `16*0`($inp),$inout0 # load input + movdqa $rndkey0,$twmask + movdqu `16*1`($inp),$inout1 + pxor @tweak[0],$inout0 # input^=tweak^round[0] + movdqu `16*2`($inp),$inout2 + pxor @tweak[1],$inout1 + aesenc $rndkey1,$inout0 + movdqu `16*3`($inp),$inout3 + pxor @tweak[2],$inout2 + aesenc $rndkey1,$inout1 + movdqu `16*4`($inp),$inout4 + pxor @tweak[3],$inout3 + aesenc $rndkey1,$inout2 + movdqu `16*5`($inp),$inout5 + pxor @tweak[5],$twmask # round[0]^=tweak[5] + movdqa 0x60(%rsp),$twres # load round[0]^round[last] + pxor @tweak[4],$inout4 + aesenc $rndkey1,$inout3 + $movkey 32($key_),$rndkey0 + lea `16*6`($inp),$inp + pxor $twmask,$inout5 + + pxor $twres,@tweak[0] # calculate tweaks^round[last] + aesenc $rndkey1,$inout4 + pxor $twres,@tweak[1] + movdqa @tweak[0],`16*0`(%rsp) # put aside tweaks^round[last] + aesenc $rndkey1,$inout5 + $movkey 48($key_),$rndkey1 + pxor $twres,@tweak[2] + + aesenc $rndkey0,$inout0 + pxor $twres,@tweak[3] + movdqa @tweak[1],`16*1`(%rsp) + aesenc $rndkey0,$inout1 + pxor $twres,@tweak[4] + movdqa @tweak[2],`16*2`(%rsp) + aesenc $rndkey0,$inout2 + aesenc $rndkey0,$inout3 + pxor $twres,$twmask + movdqa @tweak[4],`16*4`(%rsp) + aesenc $rndkey0,$inout4 + aesenc $rndkey0,$inout5 + $movkey 64($key_),$rndkey0 + movdqa $twmask,`16*5`(%rsp) + pshufd \$0x5f,@tweak[5],$twres + jmp .Lxts_enc_loop6 +.align 32 +.Lxts_enc_loop6: + aesenc $rndkey1,$inout0 + aesenc $rndkey1,$inout1 + aesenc $rndkey1,$inout2 + aesenc $rndkey1,$inout3 + aesenc $rndkey1,$inout4 + aesenc $rndkey1,$inout5 + $movkey -64($key,%rax),$rndkey1 + add \$32,%rax + + aesenc $rndkey0,$inout0 + aesenc $rndkey0,$inout1 + aesenc $rndkey0,$inout2 + aesenc $rndkey0,$inout3 + aesenc $rndkey0,$inout4 + aesenc $rndkey0,$inout5 + $movkey -80($key,%rax),$rndkey0 + jnz .Lxts_enc_loop6 + + movdqa (%r8),$twmask # start calculating next tweak + movdqa $twres,$twtmp + paddd $twres,$twres + aesenc $rndkey1,$inout0 + paddq @tweak[5],@tweak[5] + psrad \$31,$twtmp + aesenc $rndkey1,$inout1 + pand $twmask,$twtmp + $movkey ($key_),@tweak[0] # load round[0] + aesenc $rndkey1,$inout2 + aesenc $rndkey1,$inout3 + aesenc $rndkey1,$inout4 + pxor $twtmp,@tweak[5] + movaps @tweak[0],@tweak[1] # copy round[0] + aesenc $rndkey1,$inout5 + $movkey -64($key),$rndkey1 + + movdqa $twres,$twtmp + aesenc $rndkey0,$inout0 + paddd $twres,$twres + pxor @tweak[5],@tweak[0] + aesenc $rndkey0,$inout1 + psrad \$31,$twtmp + paddq @tweak[5],@tweak[5] + aesenc $rndkey0,$inout2 + aesenc $rndkey0,$inout3 + pand $twmask,$twtmp + movaps @tweak[1],@tweak[2] + aesenc $rndkey0,$inout4 + pxor $twtmp,@tweak[5] + movdqa $twres,$twtmp + aesenc $rndkey0,$inout5 + $movkey -48($key),$rndkey0 + + paddd $twres,$twres + aesenc $rndkey1,$inout0 + pxor @tweak[5],@tweak[1] + psrad \$31,$twtmp + aesenc $rndkey1,$inout1 + paddq @tweak[5],@tweak[5] + pand $twmask,$twtmp + aesenc $rndkey1,$inout2 + aesenc $rndkey1,$inout3 + movdqa @tweak[3],`16*3`(%rsp) + pxor $twtmp,@tweak[5] + aesenc $rndkey1,$inout4 + movaps @tweak[2],@tweak[3] + movdqa $twres,$twtmp + aesenc $rndkey1,$inout5 + $movkey -32($key),$rndkey1 + + paddd $twres,$twres + aesenc $rndkey0,$inout0 + pxor @tweak[5],@tweak[2] + psrad \$31,$twtmp + aesenc $rndkey0,$inout1 + paddq @tweak[5],@tweak[5] + pand $twmask,$twtmp + aesenc $rndkey0,$inout2 + aesenc $rndkey0,$inout3 + aesenc $rndkey0,$inout4 + pxor $twtmp,@tweak[5] + movaps @tweak[3],@tweak[4] + aesenc $rndkey0,$inout5 + + movdqa $twres,$rndkey0 + paddd $twres,$twres + aesenc $rndkey1,$inout0 + pxor @tweak[5],@tweak[3] + psrad \$31,$rndkey0 + aesenc $rndkey1,$inout1 + paddq @tweak[5],@tweak[5] + pand $twmask,$rndkey0 + aesenc $rndkey1,$inout2 + aesenc $rndkey1,$inout3 + pxor $rndkey0,@tweak[5] + $movkey ($key_),$rndkey0 + aesenc $rndkey1,$inout4 + aesenc $rndkey1,$inout5 + $movkey 16($key_),$rndkey1 + + pxor @tweak[5],@tweak[4] + aesenclast `16*0`(%rsp),$inout0 + psrad \$31,$twres + paddq @tweak[5],@tweak[5] + aesenclast `16*1`(%rsp),$inout1 + aesenclast `16*2`(%rsp),$inout2 + pand $twmask,$twres + mov %r10,%rax # restore $rounds + aesenclast `16*3`(%rsp),$inout3 + aesenclast `16*4`(%rsp),$inout4 + aesenclast `16*5`(%rsp),$inout5 + pxor $twres,@tweak[5] + + lea `16*6`($out),$out # $out+=6*16 + movups $inout0,`-16*6`($out) # store 6 output blocks + movups $inout1,`-16*5`($out) + movups $inout2,`-16*4`($out) + movups $inout3,`-16*3`($out) + movups $inout4,`-16*2`($out) + movups $inout5,`-16*1`($out) + sub \$16*6,$len + jnc .Lxts_enc_grandloop # loop if $len-=6*16 didn't borrow + + mov \$16+96,$rounds + sub $rnds_,$rounds + mov $key_,$key # restore $key + shr \$4,$rounds # restore original value + +.Lxts_enc_short: + # at the point @tweak[0..5] are populated with tweak values + mov $rounds,$rnds_ # backup $rounds + pxor $rndkey0,@tweak[0] + add \$16*6,$len # restore real remaining $len + jz .Lxts_enc_done # done if ($len==0) + + pxor $rndkey0,@tweak[1] + cmp \$0x20,$len + jb .Lxts_enc_one # $len is 1*16 + pxor $rndkey0,@tweak[2] + je .Lxts_enc_two # $len is 2*16 + + pxor $rndkey0,@tweak[3] + cmp \$0x40,$len + jb .Lxts_enc_three # $len is 3*16 + pxor $rndkey0,@tweak[4] + je .Lxts_enc_four # $len is 4*16 + + movdqu ($inp),$inout0 # $len is 5*16 + movdqu 16*1($inp),$inout1 + movdqu 16*2($inp),$inout2 + pxor @tweak[0],$inout0 + movdqu 16*3($inp),$inout3 + pxor @tweak[1],$inout1 + movdqu 16*4($inp),$inout4 + lea 16*5($inp),$inp # $inp+=5*16 + pxor @tweak[2],$inout2 + pxor @tweak[3],$inout3 + pxor @tweak[4],$inout4 + pxor $inout5,$inout5 + + call _aesni_encrypt6 + + xorps @tweak[0],$inout0 + movdqa @tweak[5],@tweak[0] + xorps @tweak[1],$inout1 + xorps @tweak[2],$inout2 + movdqu $inout0,($out) # store 5 output blocks + xorps @tweak[3],$inout3 + movdqu $inout1,16*1($out) + xorps @tweak[4],$inout4 + movdqu $inout2,16*2($out) + movdqu $inout3,16*3($out) + movdqu $inout4,16*4($out) + lea 16*5($out),$out # $out+=5*16 + jmp .Lxts_enc_done + +.align 16 +.Lxts_enc_one: + movups ($inp),$inout0 + lea 16*1($inp),$inp # inp+=1*16 + xorps @tweak[0],$inout0 +___ + &aesni_generate1("enc",$key,$rounds); +$code.=<<___; + xorps @tweak[0],$inout0 + movdqa @tweak[1],@tweak[0] + movups $inout0,($out) # store one output block + lea 16*1($out),$out # $out+=1*16 + jmp .Lxts_enc_done + +.align 16 +.Lxts_enc_two: + movups ($inp),$inout0 + movups 16($inp),$inout1 + lea 32($inp),$inp # $inp+=2*16 + xorps @tweak[0],$inout0 + xorps @tweak[1],$inout1 + + call _aesni_encrypt2 + + xorps @tweak[0],$inout0 + movdqa @tweak[2],@tweak[0] + xorps @tweak[1],$inout1 + movups $inout0,($out) # store 2 output blocks + movups $inout1,16*1($out) + lea 16*2($out),$out # $out+=2*16 + jmp .Lxts_enc_done + +.align 16 +.Lxts_enc_three: + movups ($inp),$inout0 + movups 16*1($inp),$inout1 + movups 16*2($inp),$inout2 + lea 16*3($inp),$inp # $inp+=3*16 + xorps @tweak[0],$inout0 + xorps @tweak[1],$inout1 + xorps @tweak[2],$inout2 + + call _aesni_encrypt3 + + xorps @tweak[0],$inout0 + movdqa @tweak[3],@tweak[0] + xorps @tweak[1],$inout1 + xorps @tweak[2],$inout2 + movups $inout0,($out) # store 3 output blocks + movups $inout1,16*1($out) + movups $inout2,16*2($out) + lea 16*3($out),$out # $out+=3*16 + jmp .Lxts_enc_done + +.align 16 +.Lxts_enc_four: + movups ($inp),$inout0 + movups 16*1($inp),$inout1 + movups 16*2($inp),$inout2 + xorps @tweak[0],$inout0 + movups 16*3($inp),$inout3 + lea 16*4($inp),$inp # $inp+=4*16 + xorps @tweak[1],$inout1 + xorps @tweak[2],$inout2 + xorps @tweak[3],$inout3 + + call _aesni_encrypt4 + + pxor @tweak[0],$inout0 + movdqa @tweak[4],@tweak[0] + pxor @tweak[1],$inout1 + pxor @tweak[2],$inout2 + movdqu $inout0,($out) # store 4 output blocks + pxor @tweak[3],$inout3 + movdqu $inout1,16*1($out) + movdqu $inout2,16*2($out) + movdqu $inout3,16*3($out) + lea 16*4($out),$out # $out+=4*16 + jmp .Lxts_enc_done + +.align 16 +.Lxts_enc_done: + and \$15,$len_ # see if $len%16 is 0 + jz .Lxts_enc_ret + mov $len_,$len + +.Lxts_enc_steal: + movzb ($inp),%eax # borrow $rounds ... + movzb -16($out),%ecx # ... and $key + lea 1($inp),$inp + mov %al,-16($out) + mov %cl,0($out) + lea 1($out),$out + sub \$1,$len + jnz .Lxts_enc_steal + + sub $len_,$out # rewind $out + mov $key_,$key # restore $key + mov $rnds_,$rounds # restore $rounds + + movups -16($out),$inout0 + xorps @tweak[0],$inout0 +___ + &aesni_generate1("enc",$key,$rounds); +$code.=<<___; + xorps @tweak[0],$inout0 + movups $inout0,-16($out) + +.Lxts_enc_ret: + xorps %xmm0,%xmm0 # clear register bank + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 +___ +$code.=<<___ if (!$win64); + pxor %xmm6,%xmm6 + pxor %xmm7,%xmm7 + movaps %xmm0,0x00(%rsp) # clear stack + pxor %xmm8,%xmm8 + movaps %xmm0,0x10(%rsp) + pxor %xmm9,%xmm9 + movaps %xmm0,0x20(%rsp) + pxor %xmm10,%xmm10 + movaps %xmm0,0x30(%rsp) + pxor %xmm11,%xmm11 + movaps %xmm0,0x40(%rsp) + pxor %xmm12,%xmm12 + movaps %xmm0,0x50(%rsp) + pxor %xmm13,%xmm13 + movaps %xmm0,0x60(%rsp) + pxor %xmm14,%xmm14 + pxor %xmm15,%xmm15 +___ +$code.=<<___ if ($win64); + movaps -0xa8(%r11),%xmm6 + movaps %xmm0,-0xa8(%r11) # clear stack + movaps -0x98(%r11),%xmm7 + movaps %xmm0,-0x98(%r11) + movaps -0x88(%r11),%xmm8 + movaps %xmm0,-0x88(%r11) + movaps -0x78(%r11),%xmm9 + movaps %xmm0,-0x78(%r11) + movaps -0x68(%r11),%xmm10 + movaps %xmm0,-0x68(%r11) + movaps -0x58(%r11),%xmm11 + movaps %xmm0,-0x58(%r11) + movaps -0x48(%r11),%xmm12 + movaps %xmm0,-0x48(%r11) + movaps -0x38(%r11),%xmm13 + movaps %xmm0,-0x38(%r11) + movaps -0x28(%r11),%xmm14 + movaps %xmm0,-0x28(%r11) + movaps -0x18(%r11),%xmm15 + movaps %xmm0,-0x18(%r11) + movaps %xmm0,0x00(%rsp) + movaps %xmm0,0x10(%rsp) + movaps %xmm0,0x20(%rsp) + movaps %xmm0,0x30(%rsp) + movaps %xmm0,0x40(%rsp) + movaps %xmm0,0x50(%rsp) + movaps %xmm0,0x60(%rsp) +___ +$code.=<<___; + mov -8(%r11),%rbp +.cfi_restore %rbp + lea (%r11),%rsp +.cfi_def_cfa_register %rsp +.Lxts_enc_epilogue: + ret +.cfi_endproc +.size aesni_xts_encrypt,.-aesni_xts_encrypt +___ + +$code.=<<___; +.globl aesni_xts_decrypt +.type aesni_xts_decrypt,\@function,6 +.align 16 +aesni_xts_decrypt: +.cfi_startproc + lea (%rsp),%r11 # frame pointer +.cfi_def_cfa_register %r11 + push %rbp +.cfi_push %rbp + sub \$$frame_size,%rsp + and \$-16,%rsp # Linux kernel stack can be incorrectly seeded +___ +$code.=<<___ if ($win64); + movaps %xmm6,-0xa8(%r11) # offload everything + movaps %xmm7,-0x98(%r11) + movaps %xmm8,-0x88(%r11) + movaps %xmm9,-0x78(%r11) + movaps %xmm10,-0x68(%r11) + movaps %xmm11,-0x58(%r11) + movaps %xmm12,-0x48(%r11) + movaps %xmm13,-0x38(%r11) + movaps %xmm14,-0x28(%r11) + movaps %xmm15,-0x18(%r11) +.Lxts_dec_body: +___ +$code.=<<___; + movups ($ivp),$inout0 # load clear-text tweak + mov 240($key2),$rounds # key2->rounds + mov 240($key),$rnds_ # key1->rounds +___ + # generate the tweak + &aesni_generate1("enc",$key2,$rounds,$inout0); +$code.=<<___; + xor %eax,%eax # if ($len%16) len-=16; + test \$15,$len + setnz %al + shl \$4,%rax + sub %rax,$len + + $movkey ($key),$rndkey0 # zero round key + mov $key,$key_ # backup $key + mov $rnds_,$rounds # backup $rounds + shl \$4,$rnds_ + mov $len,$len_ # backup $len + and \$-16,$len + + $movkey 16($key,$rnds_),$rndkey1 # last round key + + movdqa .Lxts_magic(%rip),$twmask + movdqa $inout0,@tweak[5] + pshufd \$0x5f,$inout0,$twres + pxor $rndkey0,$rndkey1 +___ + for ($i=0;$i<4;$i++) { + $code.=<<___; + movdqa $twres,$twtmp + paddd $twres,$twres + movdqa @tweak[5],@tweak[$i] + psrad \$31,$twtmp # broadcast upper bits + paddq @tweak[5],@tweak[5] + pand $twmask,$twtmp + pxor $rndkey0,@tweak[$i] + pxor $twtmp,@tweak[5] +___ + } +$code.=<<___; + movdqa @tweak[5],@tweak[4] + psrad \$31,$twres + paddq @tweak[5],@tweak[5] + pand $twmask,$twres + pxor $rndkey0,@tweak[4] + pxor $twres,@tweak[5] + movaps $rndkey1,0x60(%rsp) # save round[0]^round[last] + + sub \$16*6,$len + jc .Lxts_dec_short # if $len-=6*16 borrowed + + mov \$16+96,$rounds + lea 32($key_,$rnds_),$key # end of key schedule + sub %r10,%rax # twisted $rounds + $movkey 16($key_),$rndkey1 + mov %rax,%r10 # backup twisted $rounds + lea .Lxts_magic(%rip),%r8 + jmp .Lxts_dec_grandloop + +.align 32 +.Lxts_dec_grandloop: + movdqu `16*0`($inp),$inout0 # load input + movdqa $rndkey0,$twmask + movdqu `16*1`($inp),$inout1 + pxor @tweak[0],$inout0 # intput^=tweak^round[0] + movdqu `16*2`($inp),$inout2 + pxor @tweak[1],$inout1 + aesdec $rndkey1,$inout0 + movdqu `16*3`($inp),$inout3 + pxor @tweak[2],$inout2 + aesdec $rndkey1,$inout1 + movdqu `16*4`($inp),$inout4 + pxor @tweak[3],$inout3 + aesdec $rndkey1,$inout2 + movdqu `16*5`($inp),$inout5 + pxor @tweak[5],$twmask # round[0]^=tweak[5] + movdqa 0x60(%rsp),$twres # load round[0]^round[last] + pxor @tweak[4],$inout4 + aesdec $rndkey1,$inout3 + $movkey 32($key_),$rndkey0 + lea `16*6`($inp),$inp + pxor $twmask,$inout5 + + pxor $twres,@tweak[0] # calculate tweaks^round[last] + aesdec $rndkey1,$inout4 + pxor $twres,@tweak[1] + movdqa @tweak[0],`16*0`(%rsp) # put aside tweaks^last round key + aesdec $rndkey1,$inout5 + $movkey 48($key_),$rndkey1 + pxor $twres,@tweak[2] + + aesdec $rndkey0,$inout0 + pxor $twres,@tweak[3] + movdqa @tweak[1],`16*1`(%rsp) + aesdec $rndkey0,$inout1 + pxor $twres,@tweak[4] + movdqa @tweak[2],`16*2`(%rsp) + aesdec $rndkey0,$inout2 + aesdec $rndkey0,$inout3 + pxor $twres,$twmask + movdqa @tweak[4],`16*4`(%rsp) + aesdec $rndkey0,$inout4 + aesdec $rndkey0,$inout5 + $movkey 64($key_),$rndkey0 + movdqa $twmask,`16*5`(%rsp) + pshufd \$0x5f,@tweak[5],$twres + jmp .Lxts_dec_loop6 +.align 32 +.Lxts_dec_loop6: + aesdec $rndkey1,$inout0 + aesdec $rndkey1,$inout1 + aesdec $rndkey1,$inout2 + aesdec $rndkey1,$inout3 + aesdec $rndkey1,$inout4 + aesdec $rndkey1,$inout5 + $movkey -64($key,%rax),$rndkey1 + add \$32,%rax + + aesdec $rndkey0,$inout0 + aesdec $rndkey0,$inout1 + aesdec $rndkey0,$inout2 + aesdec $rndkey0,$inout3 + aesdec $rndkey0,$inout4 + aesdec $rndkey0,$inout5 + $movkey -80($key,%rax),$rndkey0 + jnz .Lxts_dec_loop6 + + movdqa (%r8),$twmask # start calculating next tweak + movdqa $twres,$twtmp + paddd $twres,$twres + aesdec $rndkey1,$inout0 + paddq @tweak[5],@tweak[5] + psrad \$31,$twtmp + aesdec $rndkey1,$inout1 + pand $twmask,$twtmp + $movkey ($key_),@tweak[0] # load round[0] + aesdec $rndkey1,$inout2 + aesdec $rndkey1,$inout3 + aesdec $rndkey1,$inout4 + pxor $twtmp,@tweak[5] + movaps @tweak[0],@tweak[1] # copy round[0] + aesdec $rndkey1,$inout5 + $movkey -64($key),$rndkey1 + + movdqa $twres,$twtmp + aesdec $rndkey0,$inout0 + paddd $twres,$twres + pxor @tweak[5],@tweak[0] + aesdec $rndkey0,$inout1 + psrad \$31,$twtmp + paddq @tweak[5],@tweak[5] + aesdec $rndkey0,$inout2 + aesdec $rndkey0,$inout3 + pand $twmask,$twtmp + movaps @tweak[1],@tweak[2] + aesdec $rndkey0,$inout4 + pxor $twtmp,@tweak[5] + movdqa $twres,$twtmp + aesdec $rndkey0,$inout5 + $movkey -48($key),$rndkey0 + + paddd $twres,$twres + aesdec $rndkey1,$inout0 + pxor @tweak[5],@tweak[1] + psrad \$31,$twtmp + aesdec $rndkey1,$inout1 + paddq @tweak[5],@tweak[5] + pand $twmask,$twtmp + aesdec $rndkey1,$inout2 + aesdec $rndkey1,$inout3 + movdqa @tweak[3],`16*3`(%rsp) + pxor $twtmp,@tweak[5] + aesdec $rndkey1,$inout4 + movaps @tweak[2],@tweak[3] + movdqa $twres,$twtmp + aesdec $rndkey1,$inout5 + $movkey -32($key),$rndkey1 + + paddd $twres,$twres + aesdec $rndkey0,$inout0 + pxor @tweak[5],@tweak[2] + psrad \$31,$twtmp + aesdec $rndkey0,$inout1 + paddq @tweak[5],@tweak[5] + pand $twmask,$twtmp + aesdec $rndkey0,$inout2 + aesdec $rndkey0,$inout3 + aesdec $rndkey0,$inout4 + pxor $twtmp,@tweak[5] + movaps @tweak[3],@tweak[4] + aesdec $rndkey0,$inout5 + + movdqa $twres,$rndkey0 + paddd $twres,$twres + aesdec $rndkey1,$inout0 + pxor @tweak[5],@tweak[3] + psrad \$31,$rndkey0 + aesdec $rndkey1,$inout1 + paddq @tweak[5],@tweak[5] + pand $twmask,$rndkey0 + aesdec $rndkey1,$inout2 + aesdec $rndkey1,$inout3 + pxor $rndkey0,@tweak[5] + $movkey ($key_),$rndkey0 + aesdec $rndkey1,$inout4 + aesdec $rndkey1,$inout5 + $movkey 16($key_),$rndkey1 + + pxor @tweak[5],@tweak[4] + aesdeclast `16*0`(%rsp),$inout0 + psrad \$31,$twres + paddq @tweak[5],@tweak[5] + aesdeclast `16*1`(%rsp),$inout1 + aesdeclast `16*2`(%rsp),$inout2 + pand $twmask,$twres + mov %r10,%rax # restore $rounds + aesdeclast `16*3`(%rsp),$inout3 + aesdeclast `16*4`(%rsp),$inout4 + aesdeclast `16*5`(%rsp),$inout5 + pxor $twres,@tweak[5] + + lea `16*6`($out),$out # $out+=6*16 + movups $inout0,`-16*6`($out) # store 6 output blocks + movups $inout1,`-16*5`($out) + movups $inout2,`-16*4`($out) + movups $inout3,`-16*3`($out) + movups $inout4,`-16*2`($out) + movups $inout5,`-16*1`($out) + sub \$16*6,$len + jnc .Lxts_dec_grandloop # loop if $len-=6*16 didn't borrow + + mov \$16+96,$rounds + sub $rnds_,$rounds + mov $key_,$key # restore $key + shr \$4,$rounds # restore original value + +.Lxts_dec_short: + # at the point @tweak[0..5] are populated with tweak values + mov $rounds,$rnds_ # backup $rounds + pxor $rndkey0,@tweak[0] + pxor $rndkey0,@tweak[1] + add \$16*6,$len # restore real remaining $len + jz .Lxts_dec_done # done if ($len==0) + + pxor $rndkey0,@tweak[2] + cmp \$0x20,$len + jb .Lxts_dec_one # $len is 1*16 + pxor $rndkey0,@tweak[3] + je .Lxts_dec_two # $len is 2*16 + + pxor $rndkey0,@tweak[4] + cmp \$0x40,$len + jb .Lxts_dec_three # $len is 3*16 + je .Lxts_dec_four # $len is 4*16 + + movdqu ($inp),$inout0 # $len is 5*16 + movdqu 16*1($inp),$inout1 + movdqu 16*2($inp),$inout2 + pxor @tweak[0],$inout0 + movdqu 16*3($inp),$inout3 + pxor @tweak[1],$inout1 + movdqu 16*4($inp),$inout4 + lea 16*5($inp),$inp # $inp+=5*16 + pxor @tweak[2],$inout2 + pxor @tweak[3],$inout3 + pxor @tweak[4],$inout4 + + call _aesni_decrypt6 + + xorps @tweak[0],$inout0 + xorps @tweak[1],$inout1 + xorps @tweak[2],$inout2 + movdqu $inout0,($out) # store 5 output blocks + xorps @tweak[3],$inout3 + movdqu $inout1,16*1($out) + xorps @tweak[4],$inout4 + movdqu $inout2,16*2($out) + pxor $twtmp,$twtmp + movdqu $inout3,16*3($out) + pcmpgtd @tweak[5],$twtmp + movdqu $inout4,16*4($out) + lea 16*5($out),$out # $out+=5*16 + pshufd \$0x13,$twtmp,@tweak[1] # $twres + and \$15,$len_ + jz .Lxts_dec_ret + + movdqa @tweak[5],@tweak[0] + paddq @tweak[5],@tweak[5] # psllq 1,$tweak + pand $twmask,@tweak[1] # isolate carry and residue + pxor @tweak[5],@tweak[1] + jmp .Lxts_dec_done2 + +.align 16 +.Lxts_dec_one: + movups ($inp),$inout0 + lea 16*1($inp),$inp # $inp+=1*16 + xorps @tweak[0],$inout0 +___ + &aesni_generate1("dec",$key,$rounds); +$code.=<<___; + xorps @tweak[0],$inout0 + movdqa @tweak[1],@tweak[0] + movups $inout0,($out) # store one output block + movdqa @tweak[2],@tweak[1] + lea 16*1($out),$out # $out+=1*16 + jmp .Lxts_dec_done + +.align 16 +.Lxts_dec_two: + movups ($inp),$inout0 + movups 16($inp),$inout1 + lea 32($inp),$inp # $inp+=2*16 + xorps @tweak[0],$inout0 + xorps @tweak[1],$inout1 + + call _aesni_decrypt2 + + xorps @tweak[0],$inout0 + movdqa @tweak[2],@tweak[0] + xorps @tweak[1],$inout1 + movdqa @tweak[3],@tweak[1] + movups $inout0,($out) # store 2 output blocks + movups $inout1,16*1($out) + lea 16*2($out),$out # $out+=2*16 + jmp .Lxts_dec_done + +.align 16 +.Lxts_dec_three: + movups ($inp),$inout0 + movups 16*1($inp),$inout1 + movups 16*2($inp),$inout2 + lea 16*3($inp),$inp # $inp+=3*16 + xorps @tweak[0],$inout0 + xorps @tweak[1],$inout1 + xorps @tweak[2],$inout2 + + call _aesni_decrypt3 + + xorps @tweak[0],$inout0 + movdqa @tweak[3],@tweak[0] + xorps @tweak[1],$inout1 + movdqa @tweak[4],@tweak[1] + xorps @tweak[2],$inout2 + movups $inout0,($out) # store 3 output blocks + movups $inout1,16*1($out) + movups $inout2,16*2($out) + lea 16*3($out),$out # $out+=3*16 + jmp .Lxts_dec_done + +.align 16 +.Lxts_dec_four: + movups ($inp),$inout0 + movups 16*1($inp),$inout1 + movups 16*2($inp),$inout2 + xorps @tweak[0],$inout0 + movups 16*3($inp),$inout3 + lea 16*4($inp),$inp # $inp+=4*16 + xorps @tweak[1],$inout1 + xorps @tweak[2],$inout2 + xorps @tweak[3],$inout3 + + call _aesni_decrypt4 + + pxor @tweak[0],$inout0 + movdqa @tweak[4],@tweak[0] + pxor @tweak[1],$inout1 + movdqa @tweak[5],@tweak[1] + pxor @tweak[2],$inout2 + movdqu $inout0,($out) # store 4 output blocks + pxor @tweak[3],$inout3 + movdqu $inout1,16*1($out) + movdqu $inout2,16*2($out) + movdqu $inout3,16*3($out) + lea 16*4($out),$out # $out+=4*16 + jmp .Lxts_dec_done + +.align 16 +.Lxts_dec_done: + and \$15,$len_ # see if $len%16 is 0 + jz .Lxts_dec_ret +.Lxts_dec_done2: + mov $len_,$len + mov $key_,$key # restore $key + mov $rnds_,$rounds # restore $rounds + + movups ($inp),$inout0 + xorps @tweak[1],$inout0 +___ + &aesni_generate1("dec",$key,$rounds); +$code.=<<___; + xorps @tweak[1],$inout0 + movups $inout0,($out) + +.Lxts_dec_steal: + movzb 16($inp),%eax # borrow $rounds ... + movzb ($out),%ecx # ... and $key + lea 1($inp),$inp + mov %al,($out) + mov %cl,16($out) + lea 1($out),$out + sub \$1,$len + jnz .Lxts_dec_steal + + sub $len_,$out # rewind $out + mov $key_,$key # restore $key + mov $rnds_,$rounds # restore $rounds + + movups ($out),$inout0 + xorps @tweak[0],$inout0 +___ + &aesni_generate1("dec",$key,$rounds); +$code.=<<___; + xorps @tweak[0],$inout0 + movups $inout0,($out) + +.Lxts_dec_ret: + xorps %xmm0,%xmm0 # clear register bank + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 +___ +$code.=<<___ if (!$win64); + pxor %xmm6,%xmm6 + pxor %xmm7,%xmm7 + movaps %xmm0,0x00(%rsp) # clear stack + pxor %xmm8,%xmm8 + movaps %xmm0,0x10(%rsp) + pxor %xmm9,%xmm9 + movaps %xmm0,0x20(%rsp) + pxor %xmm10,%xmm10 + movaps %xmm0,0x30(%rsp) + pxor %xmm11,%xmm11 + movaps %xmm0,0x40(%rsp) + pxor %xmm12,%xmm12 + movaps %xmm0,0x50(%rsp) + pxor %xmm13,%xmm13 + movaps %xmm0,0x60(%rsp) + pxor %xmm14,%xmm14 + pxor %xmm15,%xmm15 +___ +$code.=<<___ if ($win64); + movaps -0xa8(%r11),%xmm6 + movaps %xmm0,-0xa8(%r11) # clear stack + movaps -0x98(%r11),%xmm7 + movaps %xmm0,-0x98(%r11) + movaps -0x88(%r11),%xmm8 + movaps %xmm0,-0x88(%r11) + movaps -0x78(%r11),%xmm9 + movaps %xmm0,-0x78(%r11) + movaps -0x68(%r11),%xmm10 + movaps %xmm0,-0x68(%r11) + movaps -0x58(%r11),%xmm11 + movaps %xmm0,-0x58(%r11) + movaps -0x48(%r11),%xmm12 + movaps %xmm0,-0x48(%r11) + movaps -0x38(%r11),%xmm13 + movaps %xmm0,-0x38(%r11) + movaps -0x28(%r11),%xmm14 + movaps %xmm0,-0x28(%r11) + movaps -0x18(%r11),%xmm15 + movaps %xmm0,-0x18(%r11) + movaps %xmm0,0x00(%rsp) + movaps %xmm0,0x10(%rsp) + movaps %xmm0,0x20(%rsp) + movaps %xmm0,0x30(%rsp) + movaps %xmm0,0x40(%rsp) + movaps %xmm0,0x50(%rsp) + movaps %xmm0,0x60(%rsp) +___ +$code.=<<___; + mov -8(%r11),%rbp +.cfi_restore %rbp + lea (%r11),%rsp +.cfi_def_cfa_register %rsp +.Lxts_dec_epilogue: + ret +.cfi_endproc +.size aesni_xts_decrypt,.-aesni_xts_decrypt +___ +} + +###################################################################### +# void aesni_ocb_[en|de]crypt(const char *inp, char *out, size_t blocks, +# const AES_KEY *key, unsigned int start_block_num, +# unsigned char offset_i[16], const unsigned char L_[][16], +# unsigned char checksum[16]); +# +{ +my @offset=map("%xmm$_",(10..15)); +my ($checksum,$rndkey0l)=("%xmm8","%xmm9"); +my ($block_num,$offset_p)=("%r8","%r9"); # 5th and 6th arguments +my ($L_p,$checksum_p) = ("%rbx","%rbp"); +my ($i1,$i3,$i5) = ("%r12","%r13","%r14"); +my $seventh_arg = $win64 ? 56 : 8; +my $blocks = $len; + +$code.=<<___; +.globl aesni_ocb_encrypt +.type aesni_ocb_encrypt,\@function,6 +.align 32 +aesni_ocb_encrypt: +.cfi_startproc + lea (%rsp),%rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 +___ +$code.=<<___ if ($win64); + lea -0xa0(%rsp),%rsp + movaps %xmm6,0x00(%rsp) # offload everything + movaps %xmm7,0x10(%rsp) + movaps %xmm8,0x20(%rsp) + movaps %xmm9,0x30(%rsp) + movaps %xmm10,0x40(%rsp) + movaps %xmm11,0x50(%rsp) + movaps %xmm12,0x60(%rsp) + movaps %xmm13,0x70(%rsp) + movaps %xmm14,0x80(%rsp) + movaps %xmm15,0x90(%rsp) +.Locb_enc_body: +___ +$code.=<<___; + mov $seventh_arg(%rax),$L_p # 7th argument + mov $seventh_arg+8(%rax),$checksum_p# 8th argument + + mov 240($key),$rnds_ + mov $key,$key_ + shl \$4,$rnds_ + $movkey ($key),$rndkey0l # round[0] + $movkey 16($key,$rnds_),$rndkey1 # round[last] + + movdqu ($offset_p),@offset[5] # load last offset_i + pxor $rndkey1,$rndkey0l # round[0] ^ round[last] + pxor $rndkey1,@offset[5] # offset_i ^ round[last] + + mov \$16+32,$rounds + lea 32($key_,$rnds_),$key + $movkey 16($key_),$rndkey1 # round[1] + sub %r10,%rax # twisted $rounds + mov %rax,%r10 # backup twisted $rounds + + movdqu ($L_p),@offset[0] # L_0 for all odd-numbered blocks + movdqu ($checksum_p),$checksum # load checksum + + test \$1,$block_num # is first block number odd? + jnz .Locb_enc_odd + + bsf $block_num,$i1 + add \$1,$block_num + shl \$4,$i1 + movdqu ($L_p,$i1),$inout5 # borrow + movdqu ($inp),$inout0 + lea 16($inp),$inp + + call __ocb_encrypt1 + + movdqa $inout5,@offset[5] + movups $inout0,($out) + lea 16($out),$out + sub \$1,$blocks + jz .Locb_enc_done + +.Locb_enc_odd: + lea 1($block_num),$i1 # even-numbered blocks + lea 3($block_num),$i3 + lea 5($block_num),$i5 + lea 6($block_num),$block_num + bsf $i1,$i1 # ntz(block) + bsf $i3,$i3 + bsf $i5,$i5 + shl \$4,$i1 # ntz(block) -> table offset + shl \$4,$i3 + shl \$4,$i5 + + sub \$6,$blocks + jc .Locb_enc_short + jmp .Locb_enc_grandloop + +.align 32 +.Locb_enc_grandloop: + movdqu `16*0`($inp),$inout0 # load input + movdqu `16*1`($inp),$inout1 + movdqu `16*2`($inp),$inout2 + movdqu `16*3`($inp),$inout3 + movdqu `16*4`($inp),$inout4 + movdqu `16*5`($inp),$inout5 + lea `16*6`($inp),$inp + + call __ocb_encrypt6 + + movups $inout0,`16*0`($out) # store output + movups $inout1,`16*1`($out) + movups $inout2,`16*2`($out) + movups $inout3,`16*3`($out) + movups $inout4,`16*4`($out) + movups $inout5,`16*5`($out) + lea `16*6`($out),$out + sub \$6,$blocks + jnc .Locb_enc_grandloop + +.Locb_enc_short: + add \$6,$blocks + jz .Locb_enc_done + + movdqu `16*0`($inp),$inout0 + cmp \$2,$blocks + jb .Locb_enc_one + movdqu `16*1`($inp),$inout1 + je .Locb_enc_two + + movdqu `16*2`($inp),$inout2 + cmp \$4,$blocks + jb .Locb_enc_three + movdqu `16*3`($inp),$inout3 + je .Locb_enc_four + + movdqu `16*4`($inp),$inout4 + pxor $inout5,$inout5 + + call __ocb_encrypt6 + + movdqa @offset[4],@offset[5] + movups $inout0,`16*0`($out) + movups $inout1,`16*1`($out) + movups $inout2,`16*2`($out) + movups $inout3,`16*3`($out) + movups $inout4,`16*4`($out) + + jmp .Locb_enc_done + +.align 16 +.Locb_enc_one: + movdqa @offset[0],$inout5 # borrow + + call __ocb_encrypt1 + + movdqa $inout5,@offset[5] + movups $inout0,`16*0`($out) + jmp .Locb_enc_done + +.align 16 +.Locb_enc_two: + pxor $inout2,$inout2 + pxor $inout3,$inout3 + + call __ocb_encrypt4 + + movdqa @offset[1],@offset[5] + movups $inout0,`16*0`($out) + movups $inout1,`16*1`($out) + + jmp .Locb_enc_done + +.align 16 +.Locb_enc_three: + pxor $inout3,$inout3 + + call __ocb_encrypt4 + + movdqa @offset[2],@offset[5] + movups $inout0,`16*0`($out) + movups $inout1,`16*1`($out) + movups $inout2,`16*2`($out) + + jmp .Locb_enc_done + +.align 16 +.Locb_enc_four: + call __ocb_encrypt4 + + movdqa @offset[3],@offset[5] + movups $inout0,`16*0`($out) + movups $inout1,`16*1`($out) + movups $inout2,`16*2`($out) + movups $inout3,`16*3`($out) + +.Locb_enc_done: + pxor $rndkey0,@offset[5] # "remove" round[last] + movdqu $checksum,($checksum_p) # store checksum + movdqu @offset[5],($offset_p) # store last offset_i + + xorps %xmm0,%xmm0 # clear register bank + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 +___ +$code.=<<___ if (!$win64); + pxor %xmm6,%xmm6 + pxor %xmm7,%xmm7 + pxor %xmm8,%xmm8 + pxor %xmm9,%xmm9 + pxor %xmm10,%xmm10 + pxor %xmm11,%xmm11 + pxor %xmm12,%xmm12 + pxor %xmm13,%xmm13 + pxor %xmm14,%xmm14 + pxor %xmm15,%xmm15 + lea 0x28(%rsp),%rax +.cfi_def_cfa %rax,8 +___ +$code.=<<___ if ($win64); + movaps 0x00(%rsp),%xmm6 + movaps %xmm0,0x00(%rsp) # clear stack + movaps 0x10(%rsp),%xmm7 + movaps %xmm0,0x10(%rsp) + movaps 0x20(%rsp),%xmm8 + movaps %xmm0,0x20(%rsp) + movaps 0x30(%rsp),%xmm9 + movaps %xmm0,0x30(%rsp) + movaps 0x40(%rsp),%xmm10 + movaps %xmm0,0x40(%rsp) + movaps 0x50(%rsp),%xmm11 + movaps %xmm0,0x50(%rsp) + movaps 0x60(%rsp),%xmm12 + movaps %xmm0,0x60(%rsp) + movaps 0x70(%rsp),%xmm13 + movaps %xmm0,0x70(%rsp) + movaps 0x80(%rsp),%xmm14 + movaps %xmm0,0x80(%rsp) + movaps 0x90(%rsp),%xmm15 + movaps %xmm0,0x90(%rsp) + lea 0xa0+0x28(%rsp),%rax +.Locb_enc_pop: +___ +$code.=<<___; + mov -40(%rax),%r14 +.cfi_restore %r14 + mov -32(%rax),%r13 +.cfi_restore %r13 + mov -24(%rax),%r12 +.cfi_restore %r12 + mov -16(%rax),%rbp +.cfi_restore %rbp + mov -8(%rax),%rbx +.cfi_restore %rbx + lea (%rax),%rsp +.cfi_def_cfa_register %rsp +.Locb_enc_epilogue: + ret +.cfi_endproc +.size aesni_ocb_encrypt,.-aesni_ocb_encrypt + +.type __ocb_encrypt6,\@abi-omnipotent +.align 32 +__ocb_encrypt6: + pxor $rndkey0l,@offset[5] # offset_i ^ round[0] + movdqu ($L_p,$i1),@offset[1] + movdqa @offset[0],@offset[2] + movdqu ($L_p,$i3),@offset[3] + movdqa @offset[0],@offset[4] + pxor @offset[5],@offset[0] + movdqu ($L_p,$i5),@offset[5] + pxor @offset[0],@offset[1] + pxor $inout0,$checksum # accumulate checksum + pxor @offset[0],$inout0 # input ^ round[0] ^ offset_i + pxor @offset[1],@offset[2] + pxor $inout1,$checksum + pxor @offset[1],$inout1 + pxor @offset[2],@offset[3] + pxor $inout2,$checksum + pxor @offset[2],$inout2 + pxor @offset[3],@offset[4] + pxor $inout3,$checksum + pxor @offset[3],$inout3 + pxor @offset[4],@offset[5] + pxor $inout4,$checksum + pxor @offset[4],$inout4 + pxor $inout5,$checksum + pxor @offset[5],$inout5 + $movkey 32($key_),$rndkey0 + + lea 1($block_num),$i1 # even-numbered blocks + lea 3($block_num),$i3 + lea 5($block_num),$i5 + add \$6,$block_num + pxor $rndkey0l,@offset[0] # offset_i ^ round[last] + bsf $i1,$i1 # ntz(block) + bsf $i3,$i3 + bsf $i5,$i5 + + aesenc $rndkey1,$inout0 + aesenc $rndkey1,$inout1 + aesenc $rndkey1,$inout2 + aesenc $rndkey1,$inout3 + pxor $rndkey0l,@offset[1] + pxor $rndkey0l,@offset[2] + aesenc $rndkey1,$inout4 + pxor $rndkey0l,@offset[3] + pxor $rndkey0l,@offset[4] + aesenc $rndkey1,$inout5 + $movkey 48($key_),$rndkey1 + pxor $rndkey0l,@offset[5] + + aesenc $rndkey0,$inout0 + aesenc $rndkey0,$inout1 + aesenc $rndkey0,$inout2 + aesenc $rndkey0,$inout3 + aesenc $rndkey0,$inout4 + aesenc $rndkey0,$inout5 + $movkey 64($key_),$rndkey0 + shl \$4,$i1 # ntz(block) -> table offset + shl \$4,$i3 + jmp .Locb_enc_loop6 + +.align 32 +.Locb_enc_loop6: + aesenc $rndkey1,$inout0 + aesenc $rndkey1,$inout1 + aesenc $rndkey1,$inout2 + aesenc $rndkey1,$inout3 + aesenc $rndkey1,$inout4 + aesenc $rndkey1,$inout5 + $movkey ($key,%rax),$rndkey1 + add \$32,%rax + + aesenc $rndkey0,$inout0 + aesenc $rndkey0,$inout1 + aesenc $rndkey0,$inout2 + aesenc $rndkey0,$inout3 + aesenc $rndkey0,$inout4 + aesenc $rndkey0,$inout5 + $movkey -16($key,%rax),$rndkey0 + jnz .Locb_enc_loop6 + + aesenc $rndkey1,$inout0 + aesenc $rndkey1,$inout1 + aesenc $rndkey1,$inout2 + aesenc $rndkey1,$inout3 + aesenc $rndkey1,$inout4 + aesenc $rndkey1,$inout5 + $movkey 16($key_),$rndkey1 + shl \$4,$i5 + + aesenclast @offset[0],$inout0 + movdqu ($L_p),@offset[0] # L_0 for all odd-numbered blocks + mov %r10,%rax # restore twisted rounds + aesenclast @offset[1],$inout1 + aesenclast @offset[2],$inout2 + aesenclast @offset[3],$inout3 + aesenclast @offset[4],$inout4 + aesenclast @offset[5],$inout5 + ret +.size __ocb_encrypt6,.-__ocb_encrypt6 + +.type __ocb_encrypt4,\@abi-omnipotent +.align 32 +__ocb_encrypt4: + pxor $rndkey0l,@offset[5] # offset_i ^ round[0] + movdqu ($L_p,$i1),@offset[1] + movdqa @offset[0],@offset[2] + movdqu ($L_p,$i3),@offset[3] + pxor @offset[5],@offset[0] + pxor @offset[0],@offset[1] + pxor $inout0,$checksum # accumulate checksum + pxor @offset[0],$inout0 # input ^ round[0] ^ offset_i + pxor @offset[1],@offset[2] + pxor $inout1,$checksum + pxor @offset[1],$inout1 + pxor @offset[2],@offset[3] + pxor $inout2,$checksum + pxor @offset[2],$inout2 + pxor $inout3,$checksum + pxor @offset[3],$inout3 + $movkey 32($key_),$rndkey0 + + pxor $rndkey0l,@offset[0] # offset_i ^ round[last] + pxor $rndkey0l,@offset[1] + pxor $rndkey0l,@offset[2] + pxor $rndkey0l,@offset[3] + + aesenc $rndkey1,$inout0 + aesenc $rndkey1,$inout1 + aesenc $rndkey1,$inout2 + aesenc $rndkey1,$inout3 + $movkey 48($key_),$rndkey1 + + aesenc $rndkey0,$inout0 + aesenc $rndkey0,$inout1 + aesenc $rndkey0,$inout2 + aesenc $rndkey0,$inout3 + $movkey 64($key_),$rndkey0 + jmp .Locb_enc_loop4 + +.align 32 +.Locb_enc_loop4: + aesenc $rndkey1,$inout0 + aesenc $rndkey1,$inout1 + aesenc $rndkey1,$inout2 + aesenc $rndkey1,$inout3 + $movkey ($key,%rax),$rndkey1 + add \$32,%rax + + aesenc $rndkey0,$inout0 + aesenc $rndkey0,$inout1 + aesenc $rndkey0,$inout2 + aesenc $rndkey0,$inout3 + $movkey -16($key,%rax),$rndkey0 + jnz .Locb_enc_loop4 + + aesenc $rndkey1,$inout0 + aesenc $rndkey1,$inout1 + aesenc $rndkey1,$inout2 + aesenc $rndkey1,$inout3 + $movkey 16($key_),$rndkey1 + mov %r10,%rax # restore twisted rounds + + aesenclast @offset[0],$inout0 + aesenclast @offset[1],$inout1 + aesenclast @offset[2],$inout2 + aesenclast @offset[3],$inout3 + ret +.size __ocb_encrypt4,.-__ocb_encrypt4 + +.type __ocb_encrypt1,\@abi-omnipotent +.align 32 +__ocb_encrypt1: + pxor @offset[5],$inout5 # offset_i + pxor $rndkey0l,$inout5 # offset_i ^ round[0] + pxor $inout0,$checksum # accumulate checksum + pxor $inout5,$inout0 # input ^ round[0] ^ offset_i + $movkey 32($key_),$rndkey0 + + aesenc $rndkey1,$inout0 + $movkey 48($key_),$rndkey1 + pxor $rndkey0l,$inout5 # offset_i ^ round[last] + + aesenc $rndkey0,$inout0 + $movkey 64($key_),$rndkey0 + jmp .Locb_enc_loop1 + +.align 32 +.Locb_enc_loop1: + aesenc $rndkey1,$inout0 + $movkey ($key,%rax),$rndkey1 + add \$32,%rax + + aesenc $rndkey0,$inout0 + $movkey -16($key,%rax),$rndkey0 + jnz .Locb_enc_loop1 + + aesenc $rndkey1,$inout0 + $movkey 16($key_),$rndkey1 # redundant in tail + mov %r10,%rax # restore twisted rounds + + aesenclast $inout5,$inout0 + ret +.size __ocb_encrypt1,.-__ocb_encrypt1 + +.globl aesni_ocb_decrypt +.type aesni_ocb_decrypt,\@function,6 +.align 32 +aesni_ocb_decrypt: +.cfi_startproc + lea (%rsp),%rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 +___ +$code.=<<___ if ($win64); + lea -0xa0(%rsp),%rsp + movaps %xmm6,0x00(%rsp) # offload everything + movaps %xmm7,0x10(%rsp) + movaps %xmm8,0x20(%rsp) + movaps %xmm9,0x30(%rsp) + movaps %xmm10,0x40(%rsp) + movaps %xmm11,0x50(%rsp) + movaps %xmm12,0x60(%rsp) + movaps %xmm13,0x70(%rsp) + movaps %xmm14,0x80(%rsp) + movaps %xmm15,0x90(%rsp) +.Locb_dec_body: +___ +$code.=<<___; + mov $seventh_arg(%rax),$L_p # 7th argument + mov $seventh_arg+8(%rax),$checksum_p# 8th argument + + mov 240($key),$rnds_ + mov $key,$key_ + shl \$4,$rnds_ + $movkey ($key),$rndkey0l # round[0] + $movkey 16($key,$rnds_),$rndkey1 # round[last] + + movdqu ($offset_p),@offset[5] # load last offset_i + pxor $rndkey1,$rndkey0l # round[0] ^ round[last] + pxor $rndkey1,@offset[5] # offset_i ^ round[last] + + mov \$16+32,$rounds + lea 32($key_,$rnds_),$key + $movkey 16($key_),$rndkey1 # round[1] + sub %r10,%rax # twisted $rounds + mov %rax,%r10 # backup twisted $rounds + + movdqu ($L_p),@offset[0] # L_0 for all odd-numbered blocks + movdqu ($checksum_p),$checksum # load checksum + + test \$1,$block_num # is first block number odd? + jnz .Locb_dec_odd + + bsf $block_num,$i1 + add \$1,$block_num + shl \$4,$i1 + movdqu ($L_p,$i1),$inout5 # borrow + movdqu ($inp),$inout0 + lea 16($inp),$inp + + call __ocb_decrypt1 + + movdqa $inout5,@offset[5] + movups $inout0,($out) + xorps $inout0,$checksum # accumulate checksum + lea 16($out),$out + sub \$1,$blocks + jz .Locb_dec_done + +.Locb_dec_odd: + lea 1($block_num),$i1 # even-numbered blocks + lea 3($block_num),$i3 + lea 5($block_num),$i5 + lea 6($block_num),$block_num + bsf $i1,$i1 # ntz(block) + bsf $i3,$i3 + bsf $i5,$i5 + shl \$4,$i1 # ntz(block) -> table offset + shl \$4,$i3 + shl \$4,$i5 + + sub \$6,$blocks + jc .Locb_dec_short + jmp .Locb_dec_grandloop + +.align 32 +.Locb_dec_grandloop: + movdqu `16*0`($inp),$inout0 # load input + movdqu `16*1`($inp),$inout1 + movdqu `16*2`($inp),$inout2 + movdqu `16*3`($inp),$inout3 + movdqu `16*4`($inp),$inout4 + movdqu `16*5`($inp),$inout5 + lea `16*6`($inp),$inp + + call __ocb_decrypt6 + + movups $inout0,`16*0`($out) # store output + pxor $inout0,$checksum # accumulate checksum + movups $inout1,`16*1`($out) + pxor $inout1,$checksum + movups $inout2,`16*2`($out) + pxor $inout2,$checksum + movups $inout3,`16*3`($out) + pxor $inout3,$checksum + movups $inout4,`16*4`($out) + pxor $inout4,$checksum + movups $inout5,`16*5`($out) + pxor $inout5,$checksum + lea `16*6`($out),$out + sub \$6,$blocks + jnc .Locb_dec_grandloop + +.Locb_dec_short: + add \$6,$blocks + jz .Locb_dec_done + + movdqu `16*0`($inp),$inout0 + cmp \$2,$blocks + jb .Locb_dec_one + movdqu `16*1`($inp),$inout1 + je .Locb_dec_two + + movdqu `16*2`($inp),$inout2 + cmp \$4,$blocks + jb .Locb_dec_three + movdqu `16*3`($inp),$inout3 + je .Locb_dec_four + + movdqu `16*4`($inp),$inout4 + pxor $inout5,$inout5 + + call __ocb_decrypt6 + + movdqa @offset[4],@offset[5] + movups $inout0,`16*0`($out) # store output + pxor $inout0,$checksum # accumulate checksum + movups $inout1,`16*1`($out) + pxor $inout1,$checksum + movups $inout2,`16*2`($out) + pxor $inout2,$checksum + movups $inout3,`16*3`($out) + pxor $inout3,$checksum + movups $inout4,`16*4`($out) + pxor $inout4,$checksum + + jmp .Locb_dec_done + +.align 16 +.Locb_dec_one: + movdqa @offset[0],$inout5 # borrow + + call __ocb_decrypt1 + + movdqa $inout5,@offset[5] + movups $inout0,`16*0`($out) # store output + xorps $inout0,$checksum # accumulate checksum + jmp .Locb_dec_done + +.align 16 +.Locb_dec_two: + pxor $inout2,$inout2 + pxor $inout3,$inout3 + + call __ocb_decrypt4 + + movdqa @offset[1],@offset[5] + movups $inout0,`16*0`($out) # store output + xorps $inout0,$checksum # accumulate checksum + movups $inout1,`16*1`($out) + xorps $inout1,$checksum + + jmp .Locb_dec_done + +.align 16 +.Locb_dec_three: + pxor $inout3,$inout3 + + call __ocb_decrypt4 + + movdqa @offset[2],@offset[5] + movups $inout0,`16*0`($out) # store output + xorps $inout0,$checksum # accumulate checksum + movups $inout1,`16*1`($out) + xorps $inout1,$checksum + movups $inout2,`16*2`($out) + xorps $inout2,$checksum + + jmp .Locb_dec_done + +.align 16 +.Locb_dec_four: + call __ocb_decrypt4 + + movdqa @offset[3],@offset[5] + movups $inout0,`16*0`($out) # store output + pxor $inout0,$checksum # accumulate checksum + movups $inout1,`16*1`($out) + pxor $inout1,$checksum + movups $inout2,`16*2`($out) + pxor $inout2,$checksum + movups $inout3,`16*3`($out) + pxor $inout3,$checksum + +.Locb_dec_done: + pxor $rndkey0,@offset[5] # "remove" round[last] + movdqu $checksum,($checksum_p) # store checksum + movdqu @offset[5],($offset_p) # store last offset_i + + xorps %xmm0,%xmm0 # clear register bank + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 +___ +$code.=<<___ if (!$win64); + pxor %xmm6,%xmm6 + pxor %xmm7,%xmm7 + pxor %xmm8,%xmm8 + pxor %xmm9,%xmm9 + pxor %xmm10,%xmm10 + pxor %xmm11,%xmm11 + pxor %xmm12,%xmm12 + pxor %xmm13,%xmm13 + pxor %xmm14,%xmm14 + pxor %xmm15,%xmm15 + lea 0x28(%rsp),%rax +.cfi_def_cfa %rax,8 +___ +$code.=<<___ if ($win64); + movaps 0x00(%rsp),%xmm6 + movaps %xmm0,0x00(%rsp) # clear stack + movaps 0x10(%rsp),%xmm7 + movaps %xmm0,0x10(%rsp) + movaps 0x20(%rsp),%xmm8 + movaps %xmm0,0x20(%rsp) + movaps 0x30(%rsp),%xmm9 + movaps %xmm0,0x30(%rsp) + movaps 0x40(%rsp),%xmm10 + movaps %xmm0,0x40(%rsp) + movaps 0x50(%rsp),%xmm11 + movaps %xmm0,0x50(%rsp) + movaps 0x60(%rsp),%xmm12 + movaps %xmm0,0x60(%rsp) + movaps 0x70(%rsp),%xmm13 + movaps %xmm0,0x70(%rsp) + movaps 0x80(%rsp),%xmm14 + movaps %xmm0,0x80(%rsp) + movaps 0x90(%rsp),%xmm15 + movaps %xmm0,0x90(%rsp) + lea 0xa0+0x28(%rsp),%rax +.Locb_dec_pop: +___ +$code.=<<___; + mov -40(%rax),%r14 +.cfi_restore %r14 + mov -32(%rax),%r13 +.cfi_restore %r13 + mov -24(%rax),%r12 +.cfi_restore %r12 + mov -16(%rax),%rbp +.cfi_restore %rbp + mov -8(%rax),%rbx +.cfi_restore %rbx + lea (%rax),%rsp +.cfi_def_cfa_register %rsp +.Locb_dec_epilogue: + ret +.cfi_endproc +.size aesni_ocb_decrypt,.-aesni_ocb_decrypt + +.type __ocb_decrypt6,\@abi-omnipotent +.align 32 +__ocb_decrypt6: + pxor $rndkey0l,@offset[5] # offset_i ^ round[0] + movdqu ($L_p,$i1),@offset[1] + movdqa @offset[0],@offset[2] + movdqu ($L_p,$i3),@offset[3] + movdqa @offset[0],@offset[4] + pxor @offset[5],@offset[0] + movdqu ($L_p,$i5),@offset[5] + pxor @offset[0],@offset[1] + pxor @offset[0],$inout0 # input ^ round[0] ^ offset_i + pxor @offset[1],@offset[2] + pxor @offset[1],$inout1 + pxor @offset[2],@offset[3] + pxor @offset[2],$inout2 + pxor @offset[3],@offset[4] + pxor @offset[3],$inout3 + pxor @offset[4],@offset[5] + pxor @offset[4],$inout4 + pxor @offset[5],$inout5 + $movkey 32($key_),$rndkey0 + + lea 1($block_num),$i1 # even-numbered blocks + lea 3($block_num),$i3 + lea 5($block_num),$i5 + add \$6,$block_num + pxor $rndkey0l,@offset[0] # offset_i ^ round[last] + bsf $i1,$i1 # ntz(block) + bsf $i3,$i3 + bsf $i5,$i5 + + aesdec $rndkey1,$inout0 + aesdec $rndkey1,$inout1 + aesdec $rndkey1,$inout2 + aesdec $rndkey1,$inout3 + pxor $rndkey0l,@offset[1] + pxor $rndkey0l,@offset[2] + aesdec $rndkey1,$inout4 + pxor $rndkey0l,@offset[3] + pxor $rndkey0l,@offset[4] + aesdec $rndkey1,$inout5 + $movkey 48($key_),$rndkey1 + pxor $rndkey0l,@offset[5] + + aesdec $rndkey0,$inout0 + aesdec $rndkey0,$inout1 + aesdec $rndkey0,$inout2 + aesdec $rndkey0,$inout3 + aesdec $rndkey0,$inout4 + aesdec $rndkey0,$inout5 + $movkey 64($key_),$rndkey0 + shl \$4,$i1 # ntz(block) -> table offset + shl \$4,$i3 + jmp .Locb_dec_loop6 + +.align 32 +.Locb_dec_loop6: + aesdec $rndkey1,$inout0 + aesdec $rndkey1,$inout1 + aesdec $rndkey1,$inout2 + aesdec $rndkey1,$inout3 + aesdec $rndkey1,$inout4 + aesdec $rndkey1,$inout5 + $movkey ($key,%rax),$rndkey1 + add \$32,%rax + + aesdec $rndkey0,$inout0 + aesdec $rndkey0,$inout1 + aesdec $rndkey0,$inout2 + aesdec $rndkey0,$inout3 + aesdec $rndkey0,$inout4 + aesdec $rndkey0,$inout5 + $movkey -16($key,%rax),$rndkey0 + jnz .Locb_dec_loop6 + + aesdec $rndkey1,$inout0 + aesdec $rndkey1,$inout1 + aesdec $rndkey1,$inout2 + aesdec $rndkey1,$inout3 + aesdec $rndkey1,$inout4 + aesdec $rndkey1,$inout5 + $movkey 16($key_),$rndkey1 + shl \$4,$i5 + + aesdeclast @offset[0],$inout0 + movdqu ($L_p),@offset[0] # L_0 for all odd-numbered blocks + mov %r10,%rax # restore twisted rounds + aesdeclast @offset[1],$inout1 + aesdeclast @offset[2],$inout2 + aesdeclast @offset[3],$inout3 + aesdeclast @offset[4],$inout4 + aesdeclast @offset[5],$inout5 + ret +.size __ocb_decrypt6,.-__ocb_decrypt6 + +.type __ocb_decrypt4,\@abi-omnipotent +.align 32 +__ocb_decrypt4: + pxor $rndkey0l,@offset[5] # offset_i ^ round[0] + movdqu ($L_p,$i1),@offset[1] + movdqa @offset[0],@offset[2] + movdqu ($L_p,$i3),@offset[3] + pxor @offset[5],@offset[0] + pxor @offset[0],@offset[1] + pxor @offset[0],$inout0 # input ^ round[0] ^ offset_i + pxor @offset[1],@offset[2] + pxor @offset[1],$inout1 + pxor @offset[2],@offset[3] + pxor @offset[2],$inout2 + pxor @offset[3],$inout3 + $movkey 32($key_),$rndkey0 + + pxor $rndkey0l,@offset[0] # offset_i ^ round[last] + pxor $rndkey0l,@offset[1] + pxor $rndkey0l,@offset[2] + pxor $rndkey0l,@offset[3] + + aesdec $rndkey1,$inout0 + aesdec $rndkey1,$inout1 + aesdec $rndkey1,$inout2 + aesdec $rndkey1,$inout3 + $movkey 48($key_),$rndkey1 + + aesdec $rndkey0,$inout0 + aesdec $rndkey0,$inout1 + aesdec $rndkey0,$inout2 + aesdec $rndkey0,$inout3 + $movkey 64($key_),$rndkey0 + jmp .Locb_dec_loop4 + +.align 32 +.Locb_dec_loop4: + aesdec $rndkey1,$inout0 + aesdec $rndkey1,$inout1 + aesdec $rndkey1,$inout2 + aesdec $rndkey1,$inout3 + $movkey ($key,%rax),$rndkey1 + add \$32,%rax + + aesdec $rndkey0,$inout0 + aesdec $rndkey0,$inout1 + aesdec $rndkey0,$inout2 + aesdec $rndkey0,$inout3 + $movkey -16($key,%rax),$rndkey0 + jnz .Locb_dec_loop4 + + aesdec $rndkey1,$inout0 + aesdec $rndkey1,$inout1 + aesdec $rndkey1,$inout2 + aesdec $rndkey1,$inout3 + $movkey 16($key_),$rndkey1 + mov %r10,%rax # restore twisted rounds + + aesdeclast @offset[0],$inout0 + aesdeclast @offset[1],$inout1 + aesdeclast @offset[2],$inout2 + aesdeclast @offset[3],$inout3 + ret +.size __ocb_decrypt4,.-__ocb_decrypt4 + +.type __ocb_decrypt1,\@abi-omnipotent +.align 32 +__ocb_decrypt1: + pxor @offset[5],$inout5 # offset_i + pxor $rndkey0l,$inout5 # offset_i ^ round[0] + pxor $inout5,$inout0 # input ^ round[0] ^ offset_i + $movkey 32($key_),$rndkey0 + + aesdec $rndkey1,$inout0 + $movkey 48($key_),$rndkey1 + pxor $rndkey0l,$inout5 # offset_i ^ round[last] + + aesdec $rndkey0,$inout0 + $movkey 64($key_),$rndkey0 + jmp .Locb_dec_loop1 + +.align 32 +.Locb_dec_loop1: + aesdec $rndkey1,$inout0 + $movkey ($key,%rax),$rndkey1 + add \$32,%rax + + aesdec $rndkey0,$inout0 + $movkey -16($key,%rax),$rndkey0 + jnz .Locb_dec_loop1 + + aesdec $rndkey1,$inout0 + $movkey 16($key_),$rndkey1 # redundant in tail + mov %r10,%rax # restore twisted rounds + + aesdeclast $inout5,$inout0 + ret +.size __ocb_decrypt1,.-__ocb_decrypt1 +___ +} }} + +######################################################################## +# void $PREFIX_cbc_encrypt (const void *inp, void *out, +# size_t length, const AES_KEY *key, +# unsigned char *ivp,const int enc); +{ +my $frame_size = 0x10 + ($win64?0xa0:0); # used in decrypt +my ($iv,$in0,$in1,$in2,$in3,$in4)=map("%xmm$_",(10..15)); + +$code.=<<___; +.globl ${PREFIX}_cbc_encrypt +.type ${PREFIX}_cbc_encrypt,\@function,6 +.align 16 +${PREFIX}_cbc_encrypt: +.cfi_startproc + test $len,$len # check length + jz .Lcbc_ret + + mov 240($key),$rnds_ # key->rounds + mov $key,$key_ # backup $key + test %r9d,%r9d # 6th argument + jz .Lcbc_decrypt +#--------------------------- CBC ENCRYPT ------------------------------# + movups ($ivp),$inout0 # load iv as initial state + mov $rnds_,$rounds + cmp \$16,$len + jb .Lcbc_enc_tail + sub \$16,$len + jmp .Lcbc_enc_loop +.align 16 +.Lcbc_enc_loop: + movups ($inp),$inout1 # load input + lea 16($inp),$inp + #xorps $inout1,$inout0 +___ + &aesni_generate1("enc",$key,$rounds,$inout0,$inout1); +$code.=<<___; + mov $rnds_,$rounds # restore $rounds + mov $key_,$key # restore $key + movups $inout0,0($out) # store output + lea 16($out),$out + sub \$16,$len + jnc .Lcbc_enc_loop + add \$16,$len + jnz .Lcbc_enc_tail + pxor $rndkey0,$rndkey0 # clear register bank + pxor $rndkey1,$rndkey1 + movups $inout0,($ivp) + pxor $inout0,$inout0 + pxor $inout1,$inout1 + jmp .Lcbc_ret + +.Lcbc_enc_tail: + mov $len,%rcx # zaps $key + xchg $inp,$out # $inp is %rsi and $out is %rdi now + .long 0x9066A4F3 # rep movsb + mov \$16,%ecx # zero tail + sub $len,%rcx + xor %eax,%eax + .long 0x9066AAF3 # rep stosb + lea -16(%rdi),%rdi # rewind $out by 1 block + mov $rnds_,$rounds # restore $rounds + mov %rdi,%rsi # $inp and $out are the same + mov $key_,$key # restore $key + xor $len,$len # len=16 + jmp .Lcbc_enc_loop # one more spin + #--------------------------- CBC DECRYPT ------------------------------# +.align 16 +.Lcbc_decrypt: + cmp \$16,$len + jne .Lcbc_decrypt_bulk + + # handle single block without allocating stack frame, + # useful in ciphertext stealing mode + movdqu ($inp),$inout0 # load input + movdqu ($ivp),$inout1 # load iv + movdqa $inout0,$inout2 # future iv +___ + &aesni_generate1("dec",$key,$rnds_); +$code.=<<___; + pxor $rndkey0,$rndkey0 # clear register bank + pxor $rndkey1,$rndkey1 + movdqu $inout2,($ivp) # store iv + xorps $inout1,$inout0 # ^=iv + pxor $inout1,$inout1 + movups $inout0,($out) # store output + pxor $inout0,$inout0 + jmp .Lcbc_ret +.align 16 +.Lcbc_decrypt_bulk: + lea (%rsp),%r11 # frame pointer +.cfi_def_cfa_register %r11 + push %rbp +.cfi_push %rbp + sub \$$frame_size,%rsp + and \$-16,%rsp # Linux kernel stack can be incorrectly seeded +___ +$code.=<<___ if ($win64); + movaps %xmm6,0x10(%rsp) + movaps %xmm7,0x20(%rsp) + movaps %xmm8,0x30(%rsp) + movaps %xmm9,0x40(%rsp) + movaps %xmm10,0x50(%rsp) + movaps %xmm11,0x60(%rsp) + movaps %xmm12,0x70(%rsp) + movaps %xmm13,0x80(%rsp) + movaps %xmm14,0x90(%rsp) + movaps %xmm15,0xa0(%rsp) +.Lcbc_decrypt_body: +___ + +my $inp_=$key_="%rbp"; # reassign $key_ + +$code.=<<___; + mov $key,$key_ # [re-]backup $key [after reassignment] + movups ($ivp),$iv + mov $rnds_,$rounds + cmp \$0x50,$len + jbe .Lcbc_dec_tail + + $movkey ($key),$rndkey0 + movdqu 0x00($inp),$inout0 # load input + movdqu 0x10($inp),$inout1 + movdqa $inout0,$in0 + movdqu 0x20($inp),$inout2 + movdqa $inout1,$in1 + movdqu 0x30($inp),$inout3 + movdqa $inout2,$in2 + movdqu 0x40($inp),$inout4 + movdqa $inout3,$in3 + movdqu 0x50($inp),$inout5 + movdqa $inout4,$in4 + mov OPENSSL_ia32cap_P+4(%rip),%r9d + cmp \$0x70,$len + jbe .Lcbc_dec_six_or_seven + + and \$`1<<26|1<<22`,%r9d # isolate XSAVE+MOVBE + sub \$0x50,$len # $len is biased by -5*16 + cmp \$`1<<22`,%r9d # check for MOVBE without XSAVE + je .Lcbc_dec_loop6_enter # [which denotes Atom Silvermont] + sub \$0x20,$len # $len is biased by -7*16 + lea 0x70($key),$key # size optimization + jmp .Lcbc_dec_loop8_enter +.align 16 +.Lcbc_dec_loop8: + movups $inout7,($out) + lea 0x10($out),$out +.Lcbc_dec_loop8_enter: + movdqu 0x60($inp),$inout6 + pxor $rndkey0,$inout0 + movdqu 0x70($inp),$inout7 + pxor $rndkey0,$inout1 + $movkey 0x10-0x70($key),$rndkey1 + pxor $rndkey0,$inout2 + mov \$-1,$inp_ + cmp \$0x70,$len # is there at least 0x60 bytes ahead? + pxor $rndkey0,$inout3 + pxor $rndkey0,$inout4 + pxor $rndkey0,$inout5 + pxor $rndkey0,$inout6 + + aesdec $rndkey1,$inout0 + pxor $rndkey0,$inout7 + $movkey 0x20-0x70($key),$rndkey0 + aesdec $rndkey1,$inout1 + aesdec $rndkey1,$inout2 + aesdec $rndkey1,$inout3 + aesdec $rndkey1,$inout4 + aesdec $rndkey1,$inout5 + aesdec $rndkey1,$inout6 + adc \$0,$inp_ + and \$128,$inp_ + aesdec $rndkey1,$inout7 + add $inp,$inp_ + $movkey 0x30-0x70($key),$rndkey1 +___ +for($i=1;$i<12;$i++) { +my $rndkeyx = ($i&1)?$rndkey0:$rndkey1; +$code.=<<___ if ($i==7); + cmp \$11,$rounds +___ +$code.=<<___; + aesdec $rndkeyx,$inout0 + aesdec $rndkeyx,$inout1 + aesdec $rndkeyx,$inout2 + aesdec $rndkeyx,$inout3 + aesdec $rndkeyx,$inout4 + aesdec $rndkeyx,$inout5 + aesdec $rndkeyx,$inout6 + aesdec $rndkeyx,$inout7 + $movkey `0x30+0x10*$i`-0x70($key),$rndkeyx +___ +$code.=<<___ if ($i<6 || (!($i&1) && $i>7)); + nop +___ +$code.=<<___ if ($i==7); + jb .Lcbc_dec_done +___ +$code.=<<___ if ($i==9); + je .Lcbc_dec_done +___ +$code.=<<___ if ($i==11); + jmp .Lcbc_dec_done +___ +} +$code.=<<___; +.align 16 +.Lcbc_dec_done: + aesdec $rndkey1,$inout0 + aesdec $rndkey1,$inout1 + pxor $rndkey0,$iv + pxor $rndkey0,$in0 + aesdec $rndkey1,$inout2 + aesdec $rndkey1,$inout3 + pxor $rndkey0,$in1 + pxor $rndkey0,$in2 + aesdec $rndkey1,$inout4 + aesdec $rndkey1,$inout5 + pxor $rndkey0,$in3 + pxor $rndkey0,$in4 + aesdec $rndkey1,$inout6 + aesdec $rndkey1,$inout7 + movdqu 0x50($inp),$rndkey1 + + aesdeclast $iv,$inout0 + movdqu 0x60($inp),$iv # borrow $iv + pxor $rndkey0,$rndkey1 + aesdeclast $in0,$inout1 + pxor $rndkey0,$iv + movdqu 0x70($inp),$rndkey0 # next IV + aesdeclast $in1,$inout2 + lea 0x80($inp),$inp + movdqu 0x00($inp_),$in0 + aesdeclast $in2,$inout3 + aesdeclast $in3,$inout4 + movdqu 0x10($inp_),$in1 + movdqu 0x20($inp_),$in2 + aesdeclast $in4,$inout5 + aesdeclast $rndkey1,$inout6 + movdqu 0x30($inp_),$in3 + movdqu 0x40($inp_),$in4 + aesdeclast $iv,$inout7 + movdqa $rndkey0,$iv # return $iv + movdqu 0x50($inp_),$rndkey1 + $movkey -0x70($key),$rndkey0 + + movups $inout0,($out) # store output + movdqa $in0,$inout0 + movups $inout1,0x10($out) + movdqa $in1,$inout1 + movups $inout2,0x20($out) + movdqa $in2,$inout2 + movups $inout3,0x30($out) + movdqa $in3,$inout3 + movups $inout4,0x40($out) + movdqa $in4,$inout4 + movups $inout5,0x50($out) + movdqa $rndkey1,$inout5 + movups $inout6,0x60($out) + lea 0x70($out),$out + + sub \$0x80,$len + ja .Lcbc_dec_loop8 + + movaps $inout7,$inout0 + lea -0x70($key),$key + add \$0x70,$len + jle .Lcbc_dec_clear_tail_collected + movups $inout7,($out) + lea 0x10($out),$out + cmp \$0x50,$len + jbe .Lcbc_dec_tail + + movaps $in0,$inout0 +.Lcbc_dec_six_or_seven: + cmp \$0x60,$len + ja .Lcbc_dec_seven + + movaps $inout5,$inout6 + call _aesni_decrypt6 + pxor $iv,$inout0 # ^= IV + movaps $inout6,$iv + pxor $in0,$inout1 + movdqu $inout0,($out) + pxor $in1,$inout2 + movdqu $inout1,0x10($out) + pxor $inout1,$inout1 # clear register bank + pxor $in2,$inout3 + movdqu $inout2,0x20($out) + pxor $inout2,$inout2 + pxor $in3,$inout4 + movdqu $inout3,0x30($out) + pxor $inout3,$inout3 + pxor $in4,$inout5 + movdqu $inout4,0x40($out) + pxor $inout4,$inout4 + lea 0x50($out),$out + movdqa $inout5,$inout0 + pxor $inout5,$inout5 + jmp .Lcbc_dec_tail_collected + +.align 16 +.Lcbc_dec_seven: + movups 0x60($inp),$inout6 + xorps $inout7,$inout7 + call _aesni_decrypt8 + movups 0x50($inp),$inout7 + pxor $iv,$inout0 # ^= IV + movups 0x60($inp),$iv + pxor $in0,$inout1 + movdqu $inout0,($out) + pxor $in1,$inout2 + movdqu $inout1,0x10($out) + pxor $inout1,$inout1 # clear register bank + pxor $in2,$inout3 + movdqu $inout2,0x20($out) + pxor $inout2,$inout2 + pxor $in3,$inout4 + movdqu $inout3,0x30($out) + pxor $inout3,$inout3 + pxor $in4,$inout5 + movdqu $inout4,0x40($out) + pxor $inout4,$inout4 + pxor $inout7,$inout6 + movdqu $inout5,0x50($out) + pxor $inout5,$inout5 + lea 0x60($out),$out + movdqa $inout6,$inout0 + pxor $inout6,$inout6 + pxor $inout7,$inout7 + jmp .Lcbc_dec_tail_collected + +.align 16 +.Lcbc_dec_loop6: + movups $inout5,($out) + lea 0x10($out),$out + movdqu 0x00($inp),$inout0 # load input + movdqu 0x10($inp),$inout1 + movdqa $inout0,$in0 + movdqu 0x20($inp),$inout2 + movdqa $inout1,$in1 + movdqu 0x30($inp),$inout3 + movdqa $inout2,$in2 + movdqu 0x40($inp),$inout4 + movdqa $inout3,$in3 + movdqu 0x50($inp),$inout5 + movdqa $inout4,$in4 +.Lcbc_dec_loop6_enter: + lea 0x60($inp),$inp + movdqa $inout5,$inout6 + + call _aesni_decrypt6 + + pxor $iv,$inout0 # ^= IV + movdqa $inout6,$iv + pxor $in0,$inout1 + movdqu $inout0,($out) + pxor $in1,$inout2 + movdqu $inout1,0x10($out) + pxor $in2,$inout3 + movdqu $inout2,0x20($out) + pxor $in3,$inout4 + mov $key_,$key + movdqu $inout3,0x30($out) + pxor $in4,$inout5 + mov $rnds_,$rounds + movdqu $inout4,0x40($out) + lea 0x50($out),$out + sub \$0x60,$len + ja .Lcbc_dec_loop6 + + movdqa $inout5,$inout0 + add \$0x50,$len + jle .Lcbc_dec_clear_tail_collected + movups $inout5,($out) + lea 0x10($out),$out + +.Lcbc_dec_tail: + movups ($inp),$inout0 + sub \$0x10,$len + jbe .Lcbc_dec_one # $len is 1*16 or less + + movups 0x10($inp),$inout1 + movaps $inout0,$in0 + sub \$0x10,$len + jbe .Lcbc_dec_two # $len is 2*16 or less + + movups 0x20($inp),$inout2 + movaps $inout1,$in1 + sub \$0x10,$len + jbe .Lcbc_dec_three # $len is 3*16 or less + + movups 0x30($inp),$inout3 + movaps $inout2,$in2 + sub \$0x10,$len + jbe .Lcbc_dec_four # $len is 4*16 or less + + movups 0x40($inp),$inout4 # $len is 5*16 or less + movaps $inout3,$in3 + movaps $inout4,$in4 + xorps $inout5,$inout5 + call _aesni_decrypt6 + pxor $iv,$inout0 + movaps $in4,$iv + pxor $in0,$inout1 + movdqu $inout0,($out) + pxor $in1,$inout2 + movdqu $inout1,0x10($out) + pxor $inout1,$inout1 # clear register bank + pxor $in2,$inout3 + movdqu $inout2,0x20($out) + pxor $inout2,$inout2 + pxor $in3,$inout4 + movdqu $inout3,0x30($out) + pxor $inout3,$inout3 + lea 0x40($out),$out + movdqa $inout4,$inout0 + pxor $inout4,$inout4 + pxor $inout5,$inout5 + sub \$0x10,$len + jmp .Lcbc_dec_tail_collected + +.align 16 +.Lcbc_dec_one: + movaps $inout0,$in0 +___ + &aesni_generate1("dec",$key,$rounds); +$code.=<<___; + xorps $iv,$inout0 + movaps $in0,$iv + jmp .Lcbc_dec_tail_collected +.align 16 +.Lcbc_dec_two: + movaps $inout1,$in1 + call _aesni_decrypt2 + pxor $iv,$inout0 + movaps $in1,$iv + pxor $in0,$inout1 + movdqu $inout0,($out) + movdqa $inout1,$inout0 + pxor $inout1,$inout1 # clear register bank + lea 0x10($out),$out + jmp .Lcbc_dec_tail_collected +.align 16 +.Lcbc_dec_three: + movaps $inout2,$in2 + call _aesni_decrypt3 + pxor $iv,$inout0 + movaps $in2,$iv + pxor $in0,$inout1 + movdqu $inout0,($out) + pxor $in1,$inout2 + movdqu $inout1,0x10($out) + pxor $inout1,$inout1 # clear register bank + movdqa $inout2,$inout0 + pxor $inout2,$inout2 + lea 0x20($out),$out + jmp .Lcbc_dec_tail_collected +.align 16 +.Lcbc_dec_four: + movaps $inout3,$in3 + call _aesni_decrypt4 + pxor $iv,$inout0 + movaps $in3,$iv + pxor $in0,$inout1 + movdqu $inout0,($out) + pxor $in1,$inout2 + movdqu $inout1,0x10($out) + pxor $inout1,$inout1 # clear register bank + pxor $in2,$inout3 + movdqu $inout2,0x20($out) + pxor $inout2,$inout2 + movdqa $inout3,$inout0 + pxor $inout3,$inout3 + lea 0x30($out),$out + jmp .Lcbc_dec_tail_collected + +.align 16 +.Lcbc_dec_clear_tail_collected: + pxor $inout1,$inout1 # clear register bank + pxor $inout2,$inout2 + pxor $inout3,$inout3 +___ +$code.=<<___ if (!$win64); + pxor $inout4,$inout4 # %xmm6..9 + pxor $inout5,$inout5 + pxor $inout6,$inout6 + pxor $inout7,$inout7 +___ +$code.=<<___; +.Lcbc_dec_tail_collected: + movups $iv,($ivp) + and \$15,$len + jnz .Lcbc_dec_tail_partial + movups $inout0,($out) + pxor $inout0,$inout0 + jmp .Lcbc_dec_ret +.align 16 +.Lcbc_dec_tail_partial: + movaps $inout0,(%rsp) + pxor $inout0,$inout0 + mov \$16,%rcx + mov $out,%rdi + sub $len,%rcx + lea (%rsp),%rsi + .long 0x9066A4F3 # rep movsb + movdqa $inout0,(%rsp) + +.Lcbc_dec_ret: + xorps $rndkey0,$rndkey0 # %xmm0 + pxor $rndkey1,$rndkey1 +___ +$code.=<<___ if ($win64); + movaps 0x10(%rsp),%xmm6 + movaps %xmm0,0x10(%rsp) # clear stack + movaps 0x20(%rsp),%xmm7 + movaps %xmm0,0x20(%rsp) + movaps 0x30(%rsp),%xmm8 + movaps %xmm0,0x30(%rsp) + movaps 0x40(%rsp),%xmm9 + movaps %xmm0,0x40(%rsp) + movaps 0x50(%rsp),%xmm10 + movaps %xmm0,0x50(%rsp) + movaps 0x60(%rsp),%xmm11 + movaps %xmm0,0x60(%rsp) + movaps 0x70(%rsp),%xmm12 + movaps %xmm0,0x70(%rsp) + movaps 0x80(%rsp),%xmm13 + movaps %xmm0,0x80(%rsp) + movaps 0x90(%rsp),%xmm14 + movaps %xmm0,0x90(%rsp) + movaps 0xa0(%rsp),%xmm15 + movaps %xmm0,0xa0(%rsp) +___ +$code.=<<___; + mov -8(%r11),%rbp +.cfi_restore %rbp + lea (%r11),%rsp +.cfi_def_cfa_register %rsp +.Lcbc_ret: + ret +.cfi_endproc +.size ${PREFIX}_cbc_encrypt,.-${PREFIX}_cbc_encrypt +___ +} +# int ${PREFIX}_set_decrypt_key(const unsigned char *inp, +# int bits, AES_KEY *key) +# +# input: $inp user-supplied key +# $bits $inp length in bits +# $key pointer to key schedule +# output: %eax 0 denoting success, -1 or -2 - failure (see C) +# *$key key schedule +# +{ my ($inp,$bits,$key) = @_4args; + $bits =~ s/%r/%e/; + +$code.=<<___; +.globl ${PREFIX}_set_decrypt_key +.type ${PREFIX}_set_decrypt_key,\@abi-omnipotent +.align 16 +${PREFIX}_set_decrypt_key: +.cfi_startproc + .byte 0x48,0x83,0xEC,0x08 # sub rsp,8 +.cfi_adjust_cfa_offset 8 + call __aesni_set_encrypt_key + shl \$4,$bits # rounds-1 after _aesni_set_encrypt_key + test %eax,%eax + jnz .Ldec_key_ret + lea 16($key,$bits),$inp # points at the end of key schedule + + $movkey ($key),%xmm0 # just swap + $movkey ($inp),%xmm1 + $movkey %xmm0,($inp) + $movkey %xmm1,($key) + lea 16($key),$key + lea -16($inp),$inp + +.Ldec_key_inverse: + $movkey ($key),%xmm0 # swap and inverse + $movkey ($inp),%xmm1 + aesimc %xmm0,%xmm0 + aesimc %xmm1,%xmm1 + lea 16($key),$key + lea -16($inp),$inp + $movkey %xmm0,16($inp) + $movkey %xmm1,-16($key) + cmp $key,$inp + ja .Ldec_key_inverse + + $movkey ($key),%xmm0 # inverse middle + aesimc %xmm0,%xmm0 + pxor %xmm1,%xmm1 + $movkey %xmm0,($inp) + pxor %xmm0,%xmm0 +.Ldec_key_ret: + add \$8,%rsp +.cfi_adjust_cfa_offset -8 + ret +.cfi_endproc +.LSEH_end_set_decrypt_key: +.size ${PREFIX}_set_decrypt_key,.-${PREFIX}_set_decrypt_key +___ + +# This is based on submission from Intel by +# Huang Ying +# Vinodh Gopal +# Kahraman Akdemir +# +# Aggressively optimized in respect to aeskeygenassist's critical path +# and is contained in %xmm0-5 to meet Win64 ABI requirement. +# +# int ${PREFIX}_set_encrypt_key(const unsigned char *inp, +# int bits, AES_KEY * const key); +# +# input: $inp user-supplied key +# $bits $inp length in bits +# $key pointer to key schedule +# output: %eax 0 denoting success, -1 or -2 - failure (see C) +# $bits rounds-1 (used in aesni_set_decrypt_key) +# *$key key schedule +# $key pointer to key schedule (used in +# aesni_set_decrypt_key) +# +# Subroutine is frame-less, which means that only volatile registers +# are used. Note that it's declared "abi-omnipotent", which means that +# amount of volatile registers is smaller on Windows. +# +$code.=<<___; +.globl ${PREFIX}_set_encrypt_key +.type ${PREFIX}_set_encrypt_key,\@abi-omnipotent +.align 16 +${PREFIX}_set_encrypt_key: +__aesni_set_encrypt_key: +.cfi_startproc + .byte 0x48,0x83,0xEC,0x08 # sub rsp,8 +.cfi_adjust_cfa_offset 8 + mov \$-1,%rax + test $inp,$inp + jz .Lenc_key_ret + test $key,$key + jz .Lenc_key_ret + + mov \$`1<<28|1<<11`,%r10d # AVX and XOP bits + movups ($inp),%xmm0 # pull first 128 bits of *userKey + xorps %xmm4,%xmm4 # low dword of xmm4 is assumed 0 + and OPENSSL_ia32cap_P+4(%rip),%r10d + lea 16($key),%rax # %rax is used as modifiable copy of $key + cmp \$256,$bits + je .L14rounds + cmp \$192,$bits + je .L12rounds + cmp \$128,$bits + jne .Lbad_keybits + +.L10rounds: + mov \$9,$bits # 10 rounds for 128-bit key + cmp \$`1<<28`,%r10d # AVX, bit no XOP + je .L10rounds_alt + + $movkey %xmm0,($key) # round 0 + aeskeygenassist \$0x1,%xmm0,%xmm1 # round 1 + call .Lkey_expansion_128_cold + aeskeygenassist \$0x2,%xmm0,%xmm1 # round 2 + call .Lkey_expansion_128 + aeskeygenassist \$0x4,%xmm0,%xmm1 # round 3 + call .Lkey_expansion_128 + aeskeygenassist \$0x8,%xmm0,%xmm1 # round 4 + call .Lkey_expansion_128 + aeskeygenassist \$0x10,%xmm0,%xmm1 # round 5 + call .Lkey_expansion_128 + aeskeygenassist \$0x20,%xmm0,%xmm1 # round 6 + call .Lkey_expansion_128 + aeskeygenassist \$0x40,%xmm0,%xmm1 # round 7 + call .Lkey_expansion_128 + aeskeygenassist \$0x80,%xmm0,%xmm1 # round 8 + call .Lkey_expansion_128 + aeskeygenassist \$0x1b,%xmm0,%xmm1 # round 9 + call .Lkey_expansion_128 + aeskeygenassist \$0x36,%xmm0,%xmm1 # round 10 + call .Lkey_expansion_128 + $movkey %xmm0,(%rax) + mov $bits,80(%rax) # 240(%rdx) + xor %eax,%eax + jmp .Lenc_key_ret + +.align 16 +.L10rounds_alt: + movdqa .Lkey_rotate(%rip),%xmm5 + mov \$8,%r10d + movdqa .Lkey_rcon1(%rip),%xmm4 + movdqa %xmm0,%xmm2 + movdqu %xmm0,($key) + jmp .Loop_key128 + +.align 16 +.Loop_key128: + pshufb %xmm5,%xmm0 + aesenclast %xmm4,%xmm0 + pslld \$1,%xmm4 + lea 16(%rax),%rax + + movdqa %xmm2,%xmm3 + pslldq \$4,%xmm2 + pxor %xmm2,%xmm3 + pslldq \$4,%xmm2 + pxor %xmm2,%xmm3 + pslldq \$4,%xmm2 + pxor %xmm3,%xmm2 + + pxor %xmm2,%xmm0 + movdqu %xmm0,-16(%rax) + movdqa %xmm0,%xmm2 + + dec %r10d + jnz .Loop_key128 + + movdqa .Lkey_rcon1b(%rip),%xmm4 + + pshufb %xmm5,%xmm0 + aesenclast %xmm4,%xmm0 + pslld \$1,%xmm4 + + movdqa %xmm2,%xmm3 + pslldq \$4,%xmm2 + pxor %xmm2,%xmm3 + pslldq \$4,%xmm2 + pxor %xmm2,%xmm3 + pslldq \$4,%xmm2 + pxor %xmm3,%xmm2 + + pxor %xmm2,%xmm0 + movdqu %xmm0,(%rax) + + movdqa %xmm0,%xmm2 + pshufb %xmm5,%xmm0 + aesenclast %xmm4,%xmm0 + + movdqa %xmm2,%xmm3 + pslldq \$4,%xmm2 + pxor %xmm2,%xmm3 + pslldq \$4,%xmm2 + pxor %xmm2,%xmm3 + pslldq \$4,%xmm2 + pxor %xmm3,%xmm2 + + pxor %xmm2,%xmm0 + movdqu %xmm0,16(%rax) + + mov $bits,96(%rax) # 240($key) + xor %eax,%eax + jmp .Lenc_key_ret + +.align 16 +.L12rounds: + movq 16($inp),%xmm2 # remaining 1/3 of *userKey + mov \$11,$bits # 12 rounds for 192 + cmp \$`1<<28`,%r10d # AVX, but no XOP + je .L12rounds_alt + + $movkey %xmm0,($key) # round 0 + aeskeygenassist \$0x1,%xmm2,%xmm1 # round 1,2 + call .Lkey_expansion_192a_cold + aeskeygenassist \$0x2,%xmm2,%xmm1 # round 2,3 + call .Lkey_expansion_192b + aeskeygenassist \$0x4,%xmm2,%xmm1 # round 4,5 + call .Lkey_expansion_192a + aeskeygenassist \$0x8,%xmm2,%xmm1 # round 5,6 + call .Lkey_expansion_192b + aeskeygenassist \$0x10,%xmm2,%xmm1 # round 7,8 + call .Lkey_expansion_192a + aeskeygenassist \$0x20,%xmm2,%xmm1 # round 8,9 + call .Lkey_expansion_192b + aeskeygenassist \$0x40,%xmm2,%xmm1 # round 10,11 + call .Lkey_expansion_192a + aeskeygenassist \$0x80,%xmm2,%xmm1 # round 11,12 + call .Lkey_expansion_192b + $movkey %xmm0,(%rax) + mov $bits,48(%rax) # 240(%rdx) + xor %rax, %rax + jmp .Lenc_key_ret + +.align 16 +.L12rounds_alt: + movdqa .Lkey_rotate192(%rip),%xmm5 + movdqa .Lkey_rcon1(%rip),%xmm4 + mov \$8,%r10d + movdqu %xmm0,($key) + jmp .Loop_key192 + +.align 16 +.Loop_key192: + movq %xmm2,0(%rax) + movdqa %xmm2,%xmm1 + pshufb %xmm5,%xmm2 + aesenclast %xmm4,%xmm2 + pslld \$1, %xmm4 + lea 24(%rax),%rax + + movdqa %xmm0,%xmm3 + pslldq \$4,%xmm0 + pxor %xmm0,%xmm3 + pslldq \$4,%xmm0 + pxor %xmm0,%xmm3 + pslldq \$4,%xmm0 + pxor %xmm3,%xmm0 + + pshufd \$0xff,%xmm0,%xmm3 + pxor %xmm1,%xmm3 + pslldq \$4,%xmm1 + pxor %xmm1,%xmm3 + + pxor %xmm2,%xmm0 + pxor %xmm3,%xmm2 + movdqu %xmm0,-16(%rax) + + dec %r10d + jnz .Loop_key192 + + mov $bits,32(%rax) # 240($key) + xor %eax,%eax + jmp .Lenc_key_ret + +.align 16 +.L14rounds: + movups 16($inp),%xmm2 # remaining half of *userKey + mov \$13,$bits # 14 rounds for 256 + lea 16(%rax),%rax + cmp \$`1<<28`,%r10d # AVX, but no XOP + je .L14rounds_alt + + $movkey %xmm0,($key) # round 0 + $movkey %xmm2,16($key) # round 1 + aeskeygenassist \$0x1,%xmm2,%xmm1 # round 2 + call .Lkey_expansion_256a_cold + aeskeygenassist \$0x1,%xmm0,%xmm1 # round 3 + call .Lkey_expansion_256b + aeskeygenassist \$0x2,%xmm2,%xmm1 # round 4 + call .Lkey_expansion_256a + aeskeygenassist \$0x2,%xmm0,%xmm1 # round 5 + call .Lkey_expansion_256b + aeskeygenassist \$0x4,%xmm2,%xmm1 # round 6 + call .Lkey_expansion_256a + aeskeygenassist \$0x4,%xmm0,%xmm1 # round 7 + call .Lkey_expansion_256b + aeskeygenassist \$0x8,%xmm2,%xmm1 # round 8 + call .Lkey_expansion_256a + aeskeygenassist \$0x8,%xmm0,%xmm1 # round 9 + call .Lkey_expansion_256b + aeskeygenassist \$0x10,%xmm2,%xmm1 # round 10 + call .Lkey_expansion_256a + aeskeygenassist \$0x10,%xmm0,%xmm1 # round 11 + call .Lkey_expansion_256b + aeskeygenassist \$0x20,%xmm2,%xmm1 # round 12 + call .Lkey_expansion_256a + aeskeygenassist \$0x20,%xmm0,%xmm1 # round 13 + call .Lkey_expansion_256b + aeskeygenassist \$0x40,%xmm2,%xmm1 # round 14 + call .Lkey_expansion_256a + $movkey %xmm0,(%rax) + mov $bits,16(%rax) # 240(%rdx) + xor %rax,%rax + jmp .Lenc_key_ret + +.align 16 +.L14rounds_alt: + movdqa .Lkey_rotate(%rip),%xmm5 + movdqa .Lkey_rcon1(%rip),%xmm4 + mov \$7,%r10d + movdqu %xmm0,0($key) + movdqa %xmm2,%xmm1 + movdqu %xmm2,16($key) + jmp .Loop_key256 + +.align 16 +.Loop_key256: + pshufb %xmm5,%xmm2 + aesenclast %xmm4,%xmm2 + + movdqa %xmm0,%xmm3 + pslldq \$4,%xmm0 + pxor %xmm0,%xmm3 + pslldq \$4,%xmm0 + pxor %xmm0,%xmm3 + pslldq \$4,%xmm0 + pxor %xmm3,%xmm0 + pslld \$1,%xmm4 + + pxor %xmm2,%xmm0 + movdqu %xmm0,(%rax) + + dec %r10d + jz .Ldone_key256 + + pshufd \$0xff,%xmm0,%xmm2 + pxor %xmm3,%xmm3 + aesenclast %xmm3,%xmm2 + + movdqa %xmm1,%xmm3 + pslldq \$4,%xmm1 + pxor %xmm1,%xmm3 + pslldq \$4,%xmm1 + pxor %xmm1,%xmm3 + pslldq \$4,%xmm1 + pxor %xmm3,%xmm1 + + pxor %xmm1,%xmm2 + movdqu %xmm2,16(%rax) + lea 32(%rax),%rax + movdqa %xmm2,%xmm1 + + jmp .Loop_key256 + +.Ldone_key256: + mov $bits,16(%rax) # 240($key) + xor %eax,%eax + jmp .Lenc_key_ret + +.align 16 +.Lbad_keybits: + mov \$-2,%rax +.Lenc_key_ret: + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 + add \$8,%rsp +.cfi_adjust_cfa_offset -8 + ret +.cfi_endproc +.LSEH_end_set_encrypt_key: + +.align 16 +.Lkey_expansion_128: + $movkey %xmm0,(%rax) + lea 16(%rax),%rax +.Lkey_expansion_128_cold: + shufps \$0b00010000,%xmm0,%xmm4 + xorps %xmm4, %xmm0 + shufps \$0b10001100,%xmm0,%xmm4 + xorps %xmm4, %xmm0 + shufps \$0b11111111,%xmm1,%xmm1 # critical path + xorps %xmm1,%xmm0 + ret + +.align 16 +.Lkey_expansion_192a: + $movkey %xmm0,(%rax) + lea 16(%rax),%rax +.Lkey_expansion_192a_cold: + movaps %xmm2, %xmm5 +.Lkey_expansion_192b_warm: + shufps \$0b00010000,%xmm0,%xmm4 + movdqa %xmm2,%xmm3 + xorps %xmm4,%xmm0 + shufps \$0b10001100,%xmm0,%xmm4 + pslldq \$4,%xmm3 + xorps %xmm4,%xmm0 + pshufd \$0b01010101,%xmm1,%xmm1 # critical path + pxor %xmm3,%xmm2 + pxor %xmm1,%xmm0 + pshufd \$0b11111111,%xmm0,%xmm3 + pxor %xmm3,%xmm2 + ret + +.align 16 +.Lkey_expansion_192b: + movaps %xmm0,%xmm3 + shufps \$0b01000100,%xmm0,%xmm5 + $movkey %xmm5,(%rax) + shufps \$0b01001110,%xmm2,%xmm3 + $movkey %xmm3,16(%rax) + lea 32(%rax),%rax + jmp .Lkey_expansion_192b_warm + +.align 16 +.Lkey_expansion_256a: + $movkey %xmm2,(%rax) + lea 16(%rax),%rax +.Lkey_expansion_256a_cold: + shufps \$0b00010000,%xmm0,%xmm4 + xorps %xmm4,%xmm0 + shufps \$0b10001100,%xmm0,%xmm4 + xorps %xmm4,%xmm0 + shufps \$0b11111111,%xmm1,%xmm1 # critical path + xorps %xmm1,%xmm0 + ret + +.align 16 +.Lkey_expansion_256b: + $movkey %xmm0,(%rax) + lea 16(%rax),%rax + + shufps \$0b00010000,%xmm2,%xmm4 + xorps %xmm4,%xmm2 + shufps \$0b10001100,%xmm2,%xmm4 + xorps %xmm4,%xmm2 + shufps \$0b10101010,%xmm1,%xmm1 # critical path + xorps %xmm1,%xmm2 + ret +.size ${PREFIX}_set_encrypt_key,.-${PREFIX}_set_encrypt_key +.size __aesni_set_encrypt_key,.-__aesni_set_encrypt_key +___ +} + +$code.=<<___; +.align 64 +.Lbswap_mask: + .byte 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 +.Lincrement32: + .long 6,6,6,0 +.Lincrement64: + .long 1,0,0,0 +.Lxts_magic: + .long 0x87,0,1,0 +.Lincrement1: + .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 +.Lkey_rotate: + .long 0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d +.Lkey_rotate192: + .long 0x04070605,0x04070605,0x04070605,0x04070605 +.Lkey_rcon1: + .long 1,1,1,1 +.Lkey_rcon1b: + .long 0x1b,0x1b,0x1b,0x1b + +.asciz "AES for Intel AES-NI, CRYPTOGAMS by " +.align 64 +___ + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +___ +$code.=<<___ if ($PREFIX eq "aesni"); +.type ecb_ccm64_se_handler,\@abi-omnipotent +.align 16 +ecb_ccm64_se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lcommon_seh_tail + + lea 0(%rax),%rsi # %xmm save area + lea 512($context),%rdi # &context.Xmm6 + mov \$8,%ecx # 4*sizeof(%xmm0)/sizeof(%rax) + .long 0xa548f3fc # cld; rep movsq + lea 0x58(%rax),%rax # adjust stack pointer + + jmp .Lcommon_seh_tail +.size ecb_ccm64_se_handler,.-ecb_ccm64_se_handler + +.type ctr_xts_se_handler,\@abi-omnipotent +.align 16 +ctr_xts_se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue lable + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lcommon_seh_tail + + mov 208($context),%rax # pull context->R11 + + lea -0xa8(%rax),%rsi # %xmm save area + lea 512($context),%rdi # & context.Xmm6 + mov \$20,%ecx # 10*sizeof(%xmm0)/sizeof(%rax) + .long 0xa548f3fc # cld; rep movsq + + mov -8(%rax),%rbp # restore saved %rbp + mov %rbp,160($context) # restore context->Rbp + jmp .Lcommon_seh_tail +.size ctr_xts_se_handler,.-ctr_xts_se_handler + +.type ocb_se_handler,\@abi-omnipotent +.align 16 +ocb_se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue lable + cmp %r10,%rbx # context->RipRip>=epilogue label + jae .Lcommon_seh_tail + + mov 8(%r11),%r10d # HandlerData[2] + lea (%rsi,%r10),%r10 + cmp %r10,%rbx # context->Rip>=pop label + jae .Locb_no_xmm + + mov 152($context),%rax # pull context->Rsp + + lea (%rax),%rsi # %xmm save area + lea 512($context),%rdi # & context.Xmm6 + mov \$20,%ecx # 10*sizeof(%xmm0)/sizeof(%rax) + .long 0xa548f3fc # cld; rep movsq + lea 0xa0+0x28(%rax),%rax + +.Locb_no_xmm: + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + + jmp .Lcommon_seh_tail +.size ocb_se_handler,.-ocb_se_handler +___ +$code.=<<___; +.type cbc_se_handler,\@abi-omnipotent +.align 16 +cbc_se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 152($context),%rax # pull context->Rsp + mov 248($context),%rbx # pull context->Rip + + lea .Lcbc_decrypt_bulk(%rip),%r10 + cmp %r10,%rbx # context->Rip<"prologue" label + jb .Lcommon_seh_tail + + mov 120($context),%rax # pull context->Rax + + lea .Lcbc_decrypt_body(%rip),%r10 + cmp %r10,%rbx # context->RipRsp + + lea .Lcbc_ret(%rip),%r10 + cmp %r10,%rbx # context->Rip>="epilogue" label + jae .Lcommon_seh_tail + + lea 16(%rax),%rsi # %xmm save area + lea 512($context),%rdi # &context.Xmm6 + mov \$20,%ecx # 10*sizeof(%xmm0)/sizeof(%rax) + .long 0xa548f3fc # cld; rep movsq + + mov 208($context),%rax # pull context->R11 + + mov -8(%rax),%rbp # restore saved %rbp + mov %rbp,160($context) # restore context->Rbp + +.Lcommon_seh_tail: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size cbc_se_handler,.-cbc_se_handler + +.section .pdata +.align 4 +___ +$code.=<<___ if ($PREFIX eq "aesni"); + .rva .LSEH_begin_aesni_ecb_encrypt + .rva .LSEH_end_aesni_ecb_encrypt + .rva .LSEH_info_ecb + + .rva .LSEH_begin_aesni_ccm64_encrypt_blocks + .rva .LSEH_end_aesni_ccm64_encrypt_blocks + .rva .LSEH_info_ccm64_enc + + .rva .LSEH_begin_aesni_ccm64_decrypt_blocks + .rva .LSEH_end_aesni_ccm64_decrypt_blocks + .rva .LSEH_info_ccm64_dec + + .rva .LSEH_begin_aesni_ctr32_encrypt_blocks + .rva .LSEH_end_aesni_ctr32_encrypt_blocks + .rva .LSEH_info_ctr32 + + .rva .LSEH_begin_aesni_xts_encrypt + .rva .LSEH_end_aesni_xts_encrypt + .rva .LSEH_info_xts_enc + + .rva .LSEH_begin_aesni_xts_decrypt + .rva .LSEH_end_aesni_xts_decrypt + .rva .LSEH_info_xts_dec + + .rva .LSEH_begin_aesni_ocb_encrypt + .rva .LSEH_end_aesni_ocb_encrypt + .rva .LSEH_info_ocb_enc + + .rva .LSEH_begin_aesni_ocb_decrypt + .rva .LSEH_end_aesni_ocb_decrypt + .rva .LSEH_info_ocb_dec +___ +$code.=<<___; + .rva .LSEH_begin_${PREFIX}_cbc_encrypt + .rva .LSEH_end_${PREFIX}_cbc_encrypt + .rva .LSEH_info_cbc + + .rva ${PREFIX}_set_decrypt_key + .rva .LSEH_end_set_decrypt_key + .rva .LSEH_info_key + + .rva ${PREFIX}_set_encrypt_key + .rva .LSEH_end_set_encrypt_key + .rva .LSEH_info_key +.section .xdata +.align 8 +___ +$code.=<<___ if ($PREFIX eq "aesni"); +.LSEH_info_ecb: + .byte 9,0,0,0 + .rva ecb_ccm64_se_handler + .rva .Lecb_enc_body,.Lecb_enc_ret # HandlerData[] +.LSEH_info_ccm64_enc: + .byte 9,0,0,0 + .rva ecb_ccm64_se_handler + .rva .Lccm64_enc_body,.Lccm64_enc_ret # HandlerData[] +.LSEH_info_ccm64_dec: + .byte 9,0,0,0 + .rva ecb_ccm64_se_handler + .rva .Lccm64_dec_body,.Lccm64_dec_ret # HandlerData[] +.LSEH_info_ctr32: + .byte 9,0,0,0 + .rva ctr_xts_se_handler + .rva .Lctr32_body,.Lctr32_epilogue # HandlerData[] +.LSEH_info_xts_enc: + .byte 9,0,0,0 + .rva ctr_xts_se_handler + .rva .Lxts_enc_body,.Lxts_enc_epilogue # HandlerData[] +.LSEH_info_xts_dec: + .byte 9,0,0,0 + .rva ctr_xts_se_handler + .rva .Lxts_dec_body,.Lxts_dec_epilogue # HandlerData[] +.LSEH_info_ocb_enc: + .byte 9,0,0,0 + .rva ocb_se_handler + .rva .Locb_enc_body,.Locb_enc_epilogue # HandlerData[] + .rva .Locb_enc_pop + .long 0 +.LSEH_info_ocb_dec: + .byte 9,0,0,0 + .rva ocb_se_handler + .rva .Locb_dec_body,.Locb_dec_epilogue # HandlerData[] + .rva .Locb_dec_pop + .long 0 +___ +$code.=<<___; +.LSEH_info_cbc: + .byte 9,0,0,0 + .rva cbc_se_handler +.LSEH_info_key: + .byte 0x01,0x04,0x01,0x00 + .byte 0x04,0x02,0x00,0x00 # sub rsp,8 +___ +} + +sub rex { + local *opcode=shift; + my ($dst,$src)=@_; + my $rex=0; + + $rex|=0x04 if($dst>=8); + $rex|=0x01 if($src>=8); + push @opcode,$rex|0x40 if($rex); +} + +sub aesni { + my $line=shift; + my @opcode=(0x66); + + if ($line=~/(aeskeygenassist)\s+\$([x0-9a-f]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) { + rex(\@opcode,$4,$3); + push @opcode,0x0f,0x3a,0xdf; + push @opcode,0xc0|($3&7)|(($4&7)<<3); # ModR/M + my $c=$2; + push @opcode,$c=~/^0/?oct($c):$c; + return ".byte\t".join(',',@opcode); + } + elsif ($line=~/(aes[a-z]+)\s+%xmm([0-9]+),\s*%xmm([0-9]+)/) { + my %opcodelet = ( + "aesimc" => 0xdb, + "aesenc" => 0xdc, "aesenclast" => 0xdd, + "aesdec" => 0xde, "aesdeclast" => 0xdf + ); + return undef if (!defined($opcodelet{$1})); + rex(\@opcode,$3,$2); + push @opcode,0x0f,0x38,$opcodelet{$1}; + push @opcode,0xc0|($2&7)|(($3&7)<<3); # ModR/M + return ".byte\t".join(',',@opcode); + } + elsif ($line=~/(aes[a-z]+)\s+([0x1-9a-fA-F]*)\(%rsp\),\s*%xmm([0-9]+)/) { + my %opcodelet = ( + "aesenc" => 0xdc, "aesenclast" => 0xdd, + "aesdec" => 0xde, "aesdeclast" => 0xdf + ); + return undef if (!defined($opcodelet{$1})); + my $off = $2; + push @opcode,0x44 if ($3>=8); + push @opcode,0x0f,0x38,$opcodelet{$1}; + push @opcode,0x44|(($3&7)<<3),0x24; # ModR/M + push @opcode,($off=~/^0/?oct($off):$off)&0xff; + return ".byte\t".join(',',@opcode); + } + return $line; +} + +sub movbe { + ".byte 0x0f,0x38,0xf1,0x44,0x24,".shift; +} + +$code =~ s/\`([^\`]*)\`/eval($1)/gem; +$code =~ s/\b(aes.*%xmm[0-9]+).*$/aesni($1)/gem; +#$code =~ s/\bmovbe\s+%eax/bswap %eax; mov %eax/gm; # debugging artefact +$code =~ s/\bmovbe\s+%eax,\s*([0-9]+)\(%rsp\)/movbe($1)/gem; + +print $code; + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesp8-ppc.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesp8-ppc.pl new file mode 100755 index 000000000..488b13325 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesp8-ppc.pl @@ -0,0 +1,3807 @@ +#! /usr/bin/env perl +# Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# This module implements support for AES instructions as per PowerISA +# specification version 2.07, first implemented by POWER8 processor. +# The module is endian-agnostic in sense that it supports both big- +# and little-endian cases. Data alignment in parallelizable modes is +# handled with VSX loads and stores, which implies MSR.VSX flag being +# set. It should also be noted that ISA specification doesn't prohibit +# alignment exceptions for these instructions on page boundaries. +# Initially alignment was handled in pure AltiVec/VMX way [when data +# is aligned programmatically, which in turn guarantees exception- +# free execution], but it turned to hamper performance when vcipher +# instructions are interleaved. It's reckoned that eventual +# misalignment penalties at page boundaries are in average lower +# than additional overhead in pure AltiVec approach. +# +# May 2016 +# +# Add XTS subroutine, 9x on little- and 12x improvement on big-endian +# systems were measured. +# +###################################################################### +# Current large-block performance in cycles per byte processed with +# 128-bit key (less is better). +# +# CBC en-/decrypt CTR XTS +# POWER8[le] 3.96/0.72 0.74 1.1 +# POWER8[be] 3.75/0.65 0.66 1.0 +# POWER9[le] 4.02/0.86 0.84 1.05 +# POWER9[be] 3.99/0.78 0.79 0.97 + +$flavour = shift; + +if ($flavour =~ /64/) { + $SIZE_T =8; + $LRSAVE =2*$SIZE_T; + $STU ="stdu"; + $POP ="ld"; + $PUSH ="std"; + $UCMP ="cmpld"; + $SHL ="sldi"; +} elsif ($flavour =~ /32/) { + $SIZE_T =4; + $LRSAVE =$SIZE_T; + $STU ="stwu"; + $POP ="lwz"; + $PUSH ="stw"; + $UCMP ="cmplw"; + $SHL ="slwi"; +} else { die "nonsense $flavour"; } + +$LITTLE_ENDIAN = ($flavour=~/le$/) ? $SIZE_T : 0; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or +die "can't locate ppc-xlate.pl"; + +open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!"; + +$FRAME=8*$SIZE_T; +$prefix="aes_p8"; + +$sp="r1"; +$vrsave="r12"; + +######################################################################### +{{{ # Key setup procedures # +my ($inp,$bits,$out,$ptr,$cnt,$rounds)=map("r$_",(3..8)); +my ($zero,$in0,$in1,$key,$rcon,$mask,$tmp)=map("v$_",(0..6)); +my ($stage,$outperm,$outmask,$outhead,$outtail)=map("v$_",(7..11)); + +$code.=<<___; +.machine "any" + +.text + +.align 7 +rcon: +.long 0x01000000, 0x01000000, 0x01000000, 0x01000000 ?rev +.long 0x1b000000, 0x1b000000, 0x1b000000, 0x1b000000 ?rev +.long 0x0d0e0f0c, 0x0d0e0f0c, 0x0d0e0f0c, 0x0d0e0f0c ?rev +.long 0,0,0,0 ?asis +Lconsts: + mflr r0 + bcl 20,31,\$+4 + mflr $ptr #vvvvv "distance between . and rcon + addi $ptr,$ptr,-0x48 + mtlr r0 + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 +.asciz "AES for PowerISA 2.07, CRYPTOGAMS by " + +.globl .${prefix}_set_encrypt_key +.align 5 +.${prefix}_set_encrypt_key: +Lset_encrypt_key: + mflr r11 + $PUSH r11,$LRSAVE($sp) + + li $ptr,-1 + ${UCMP}i $inp,0 + beq- Lenc_key_abort # if ($inp==0) return -1; + ${UCMP}i $out,0 + beq- Lenc_key_abort # if ($out==0) return -1; + li $ptr,-2 + cmpwi $bits,128 + blt- Lenc_key_abort + cmpwi $bits,256 + bgt- Lenc_key_abort + andi. r0,$bits,0x3f + bne- Lenc_key_abort + + lis r0,0xfff0 + mfspr $vrsave,256 + mtspr 256,r0 + + bl Lconsts + mtlr r11 + + neg r9,$inp + lvx $in0,0,$inp + addi $inp,$inp,15 # 15 is not typo + lvsr $key,0,r9 # borrow $key + li r8,0x20 + cmpwi $bits,192 + lvx $in1,0,$inp + le?vspltisb $mask,0x0f # borrow $mask + lvx $rcon,0,$ptr + le?vxor $key,$key,$mask # adjust for byte swap + lvx $mask,r8,$ptr + addi $ptr,$ptr,0x10 + vperm $in0,$in0,$in1,$key # align [and byte swap in LE] + li $cnt,8 + vxor $zero,$zero,$zero + mtctr $cnt + + ?lvsr $outperm,0,$out + vspltisb $outmask,-1 + lvx $outhead,0,$out + ?vperm $outmask,$zero,$outmask,$outperm + + blt Loop128 + addi $inp,$inp,8 + beq L192 + addi $inp,$inp,8 + b L256 + +.align 4 +Loop128: + vperm $key,$in0,$in0,$mask # rotate-n-splat + vsldoi $tmp,$zero,$in0,12 # >>32 + vperm $outtail,$in0,$in0,$outperm # rotate + vsel $stage,$outhead,$outtail,$outmask + vmr $outhead,$outtail + vcipherlast $key,$key,$rcon + stvx $stage,0,$out + addi $out,$out,16 + + vxor $in0,$in0,$tmp + vsldoi $tmp,$zero,$tmp,12 # >>32 + vxor $in0,$in0,$tmp + vsldoi $tmp,$zero,$tmp,12 # >>32 + vxor $in0,$in0,$tmp + vadduwm $rcon,$rcon,$rcon + vxor $in0,$in0,$key + bdnz Loop128 + + lvx $rcon,0,$ptr # last two round keys + + vperm $key,$in0,$in0,$mask # rotate-n-splat + vsldoi $tmp,$zero,$in0,12 # >>32 + vperm $outtail,$in0,$in0,$outperm # rotate + vsel $stage,$outhead,$outtail,$outmask + vmr $outhead,$outtail + vcipherlast $key,$key,$rcon + stvx $stage,0,$out + addi $out,$out,16 + + vxor $in0,$in0,$tmp + vsldoi $tmp,$zero,$tmp,12 # >>32 + vxor $in0,$in0,$tmp + vsldoi $tmp,$zero,$tmp,12 # >>32 + vxor $in0,$in0,$tmp + vadduwm $rcon,$rcon,$rcon + vxor $in0,$in0,$key + + vperm $key,$in0,$in0,$mask # rotate-n-splat + vsldoi $tmp,$zero,$in0,12 # >>32 + vperm $outtail,$in0,$in0,$outperm # rotate + vsel $stage,$outhead,$outtail,$outmask + vmr $outhead,$outtail + vcipherlast $key,$key,$rcon + stvx $stage,0,$out + addi $out,$out,16 + + vxor $in0,$in0,$tmp + vsldoi $tmp,$zero,$tmp,12 # >>32 + vxor $in0,$in0,$tmp + vsldoi $tmp,$zero,$tmp,12 # >>32 + vxor $in0,$in0,$tmp + vxor $in0,$in0,$key + vperm $outtail,$in0,$in0,$outperm # rotate + vsel $stage,$outhead,$outtail,$outmask + vmr $outhead,$outtail + stvx $stage,0,$out + + addi $inp,$out,15 # 15 is not typo + addi $out,$out,0x50 + + li $rounds,10 + b Ldone + +.align 4 +L192: + lvx $tmp,0,$inp + li $cnt,4 + vperm $outtail,$in0,$in0,$outperm # rotate + vsel $stage,$outhead,$outtail,$outmask + vmr $outhead,$outtail + stvx $stage,0,$out + addi $out,$out,16 + vperm $in1,$in1,$tmp,$key # align [and byte swap in LE] + vspltisb $key,8 # borrow $key + mtctr $cnt + vsububm $mask,$mask,$key # adjust the mask + +Loop192: + vperm $key,$in1,$in1,$mask # roate-n-splat + vsldoi $tmp,$zero,$in0,12 # >>32 + vcipherlast $key,$key,$rcon + + vxor $in0,$in0,$tmp + vsldoi $tmp,$zero,$tmp,12 # >>32 + vxor $in0,$in0,$tmp + vsldoi $tmp,$zero,$tmp,12 # >>32 + vxor $in0,$in0,$tmp + + vsldoi $stage,$zero,$in1,8 + vspltw $tmp,$in0,3 + vxor $tmp,$tmp,$in1 + vsldoi $in1,$zero,$in1,12 # >>32 + vadduwm $rcon,$rcon,$rcon + vxor $in1,$in1,$tmp + vxor $in0,$in0,$key + vxor $in1,$in1,$key + vsldoi $stage,$stage,$in0,8 + + vperm $key,$in1,$in1,$mask # rotate-n-splat + vsldoi $tmp,$zero,$in0,12 # >>32 + vperm $outtail,$stage,$stage,$outperm # rotate + vsel $stage,$outhead,$outtail,$outmask + vmr $outhead,$outtail + vcipherlast $key,$key,$rcon + stvx $stage,0,$out + addi $out,$out,16 + + vsldoi $stage,$in0,$in1,8 + vxor $in0,$in0,$tmp + vsldoi $tmp,$zero,$tmp,12 # >>32 + vperm $outtail,$stage,$stage,$outperm # rotate + vsel $stage,$outhead,$outtail,$outmask + vmr $outhead,$outtail + vxor $in0,$in0,$tmp + vsldoi $tmp,$zero,$tmp,12 # >>32 + vxor $in0,$in0,$tmp + stvx $stage,0,$out + addi $out,$out,16 + + vspltw $tmp,$in0,3 + vxor $tmp,$tmp,$in1 + vsldoi $in1,$zero,$in1,12 # >>32 + vadduwm $rcon,$rcon,$rcon + vxor $in1,$in1,$tmp + vxor $in0,$in0,$key + vxor $in1,$in1,$key + vperm $outtail,$in0,$in0,$outperm # rotate + vsel $stage,$outhead,$outtail,$outmask + vmr $outhead,$outtail + stvx $stage,0,$out + addi $inp,$out,15 # 15 is not typo + addi $out,$out,16 + bdnz Loop192 + + li $rounds,12 + addi $out,$out,0x20 + b Ldone + +.align 4 +L256: + lvx $tmp,0,$inp + li $cnt,7 + li $rounds,14 + vperm $outtail,$in0,$in0,$outperm # rotate + vsel $stage,$outhead,$outtail,$outmask + vmr $outhead,$outtail + stvx $stage,0,$out + addi $out,$out,16 + vperm $in1,$in1,$tmp,$key # align [and byte swap in LE] + mtctr $cnt + +Loop256: + vperm $key,$in1,$in1,$mask # rotate-n-splat + vsldoi $tmp,$zero,$in0,12 # >>32 + vperm $outtail,$in1,$in1,$outperm # rotate + vsel $stage,$outhead,$outtail,$outmask + vmr $outhead,$outtail + vcipherlast $key,$key,$rcon + stvx $stage,0,$out + addi $out,$out,16 + + vxor $in0,$in0,$tmp + vsldoi $tmp,$zero,$tmp,12 # >>32 + vxor $in0,$in0,$tmp + vsldoi $tmp,$zero,$tmp,12 # >>32 + vxor $in0,$in0,$tmp + vadduwm $rcon,$rcon,$rcon + vxor $in0,$in0,$key + vperm $outtail,$in0,$in0,$outperm # rotate + vsel $stage,$outhead,$outtail,$outmask + vmr $outhead,$outtail + stvx $stage,0,$out + addi $inp,$out,15 # 15 is not typo + addi $out,$out,16 + bdz Ldone + + vspltw $key,$in0,3 # just splat + vsldoi $tmp,$zero,$in1,12 # >>32 + vsbox $key,$key + + vxor $in1,$in1,$tmp + vsldoi $tmp,$zero,$tmp,12 # >>32 + vxor $in1,$in1,$tmp + vsldoi $tmp,$zero,$tmp,12 # >>32 + vxor $in1,$in1,$tmp + + vxor $in1,$in1,$key + b Loop256 + +.align 4 +Ldone: + lvx $in1,0,$inp # redundant in aligned case + vsel $in1,$outhead,$in1,$outmask + stvx $in1,0,$inp + li $ptr,0 + mtspr 256,$vrsave + stw $rounds,0($out) + +Lenc_key_abort: + mr r3,$ptr + blr + .long 0 + .byte 0,12,0x14,1,0,0,3,0 + .long 0 +.size .${prefix}_set_encrypt_key,.-.${prefix}_set_encrypt_key + +.globl .${prefix}_set_decrypt_key +.align 5 +.${prefix}_set_decrypt_key: + $STU $sp,-$FRAME($sp) + mflr r10 + $PUSH r10,$FRAME+$LRSAVE($sp) + bl Lset_encrypt_key + mtlr r10 + + cmpwi r3,0 + bne- Ldec_key_abort + + slwi $cnt,$rounds,4 + subi $inp,$out,240 # first round key + srwi $rounds,$rounds,1 + add $out,$inp,$cnt # last round key + mtctr $rounds + +Ldeckey: + lwz r0, 0($inp) + lwz r6, 4($inp) + lwz r7, 8($inp) + lwz r8, 12($inp) + addi $inp,$inp,16 + lwz r9, 0($out) + lwz r10,4($out) + lwz r11,8($out) + lwz r12,12($out) + stw r0, 0($out) + stw r6, 4($out) + stw r7, 8($out) + stw r8, 12($out) + subi $out,$out,16 + stw r9, -16($inp) + stw r10,-12($inp) + stw r11,-8($inp) + stw r12,-4($inp) + bdnz Ldeckey + + xor r3,r3,r3 # return value +Ldec_key_abort: + addi $sp,$sp,$FRAME + blr + .long 0 + .byte 0,12,4,1,0x80,0,3,0 + .long 0 +.size .${prefix}_set_decrypt_key,.-.${prefix}_set_decrypt_key +___ +}}} +######################################################################### +{{{ # Single block en- and decrypt procedures # +sub gen_block () { +my $dir = shift; +my $n = $dir eq "de" ? "n" : ""; +my ($inp,$out,$key,$rounds,$idx)=map("r$_",(3..7)); + +$code.=<<___; +.globl .${prefix}_${dir}crypt +.align 5 +.${prefix}_${dir}crypt: + lwz $rounds,240($key) + lis r0,0xfc00 + mfspr $vrsave,256 + li $idx,15 # 15 is not typo + mtspr 256,r0 + + lvx v0,0,$inp + neg r11,$out + lvx v1,$idx,$inp + lvsl v2,0,$inp # inpperm + le?vspltisb v4,0x0f + ?lvsl v3,0,r11 # outperm + le?vxor v2,v2,v4 + li $idx,16 + vperm v0,v0,v1,v2 # align [and byte swap in LE] + lvx v1,0,$key + ?lvsl v5,0,$key # keyperm + srwi $rounds,$rounds,1 + lvx v2,$idx,$key + addi $idx,$idx,16 + subi $rounds,$rounds,1 + ?vperm v1,v1,v2,v5 # align round key + + vxor v0,v0,v1 + lvx v1,$idx,$key + addi $idx,$idx,16 + mtctr $rounds + +Loop_${dir}c: + ?vperm v2,v2,v1,v5 + v${n}cipher v0,v0,v2 + lvx v2,$idx,$key + addi $idx,$idx,16 + ?vperm v1,v1,v2,v5 + v${n}cipher v0,v0,v1 + lvx v1,$idx,$key + addi $idx,$idx,16 + bdnz Loop_${dir}c + + ?vperm v2,v2,v1,v5 + v${n}cipher v0,v0,v2 + lvx v2,$idx,$key + ?vperm v1,v1,v2,v5 + v${n}cipherlast v0,v0,v1 + + vspltisb v2,-1 + vxor v1,v1,v1 + li $idx,15 # 15 is not typo + ?vperm v2,v1,v2,v3 # outmask + le?vxor v3,v3,v4 + lvx v1,0,$out # outhead + vperm v0,v0,v0,v3 # rotate [and byte swap in LE] + vsel v1,v1,v0,v2 + lvx v4,$idx,$out + stvx v1,0,$out + vsel v0,v0,v4,v2 + stvx v0,$idx,$out + + mtspr 256,$vrsave + blr + .long 0 + .byte 0,12,0x14,0,0,0,3,0 + .long 0 +.size .${prefix}_${dir}crypt,.-.${prefix}_${dir}crypt +___ +} +&gen_block("en"); +&gen_block("de"); +}}} +######################################################################### +{{{ # CBC en- and decrypt procedures # +my ($inp,$out,$len,$key,$ivp,$enc,$rounds,$idx)=map("r$_",(3..10)); +my ($rndkey0,$rndkey1,$inout,$tmp)= map("v$_",(0..3)); +my ($ivec,$inptail,$inpperm,$outhead,$outperm,$outmask,$keyperm)= + map("v$_",(4..10)); +$code.=<<___; +.globl .${prefix}_cbc_encrypt +.align 5 +.${prefix}_cbc_encrypt: + ${UCMP}i $len,16 + bltlr- + + cmpwi $enc,0 # test direction + lis r0,0xffe0 + mfspr $vrsave,256 + mtspr 256,r0 + + li $idx,15 + vxor $rndkey0,$rndkey0,$rndkey0 + le?vspltisb $tmp,0x0f + + lvx $ivec,0,$ivp # load [unaligned] iv + lvsl $inpperm,0,$ivp + lvx $inptail,$idx,$ivp + le?vxor $inpperm,$inpperm,$tmp + vperm $ivec,$ivec,$inptail,$inpperm + + neg r11,$inp + ?lvsl $keyperm,0,$key # prepare for unaligned key + lwz $rounds,240($key) + + lvsr $inpperm,0,r11 # prepare for unaligned load + lvx $inptail,0,$inp + addi $inp,$inp,15 # 15 is not typo + le?vxor $inpperm,$inpperm,$tmp + + ?lvsr $outperm,0,$out # prepare for unaligned store + vspltisb $outmask,-1 + lvx $outhead,0,$out + ?vperm $outmask,$rndkey0,$outmask,$outperm + le?vxor $outperm,$outperm,$tmp + + srwi $rounds,$rounds,1 + li $idx,16 + subi $rounds,$rounds,1 + beq Lcbc_dec + +Lcbc_enc: + vmr $inout,$inptail + lvx $inptail,0,$inp + addi $inp,$inp,16 + mtctr $rounds + subi $len,$len,16 # len-=16 + + lvx $rndkey0,0,$key + vperm $inout,$inout,$inptail,$inpperm + lvx $rndkey1,$idx,$key + addi $idx,$idx,16 + ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm + vxor $inout,$inout,$rndkey0 + lvx $rndkey0,$idx,$key + addi $idx,$idx,16 + vxor $inout,$inout,$ivec + +Loop_cbc_enc: + ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm + vcipher $inout,$inout,$rndkey1 + lvx $rndkey1,$idx,$key + addi $idx,$idx,16 + ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm + vcipher $inout,$inout,$rndkey0 + lvx $rndkey0,$idx,$key + addi $idx,$idx,16 + bdnz Loop_cbc_enc + + ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm + vcipher $inout,$inout,$rndkey1 + lvx $rndkey1,$idx,$key + li $idx,16 + ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm + vcipherlast $ivec,$inout,$rndkey0 + ${UCMP}i $len,16 + + vperm $tmp,$ivec,$ivec,$outperm + vsel $inout,$outhead,$tmp,$outmask + vmr $outhead,$tmp + stvx $inout,0,$out + addi $out,$out,16 + bge Lcbc_enc + + b Lcbc_done + +.align 4 +Lcbc_dec: + ${UCMP}i $len,128 + bge _aesp8_cbc_decrypt8x + vmr $tmp,$inptail + lvx $inptail,0,$inp + addi $inp,$inp,16 + mtctr $rounds + subi $len,$len,16 # len-=16 + + lvx $rndkey0,0,$key + vperm $tmp,$tmp,$inptail,$inpperm + lvx $rndkey1,$idx,$key + addi $idx,$idx,16 + ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm + vxor $inout,$tmp,$rndkey0 + lvx $rndkey0,$idx,$key + addi $idx,$idx,16 + +Loop_cbc_dec: + ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm + vncipher $inout,$inout,$rndkey1 + lvx $rndkey1,$idx,$key + addi $idx,$idx,16 + ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm + vncipher $inout,$inout,$rndkey0 + lvx $rndkey0,$idx,$key + addi $idx,$idx,16 + bdnz Loop_cbc_dec + + ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm + vncipher $inout,$inout,$rndkey1 + lvx $rndkey1,$idx,$key + li $idx,16 + ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm + vncipherlast $inout,$inout,$rndkey0 + ${UCMP}i $len,16 + + vxor $inout,$inout,$ivec + vmr $ivec,$tmp + vperm $tmp,$inout,$inout,$outperm + vsel $inout,$outhead,$tmp,$outmask + vmr $outhead,$tmp + stvx $inout,0,$out + addi $out,$out,16 + bge Lcbc_dec + +Lcbc_done: + addi $out,$out,-1 + lvx $inout,0,$out # redundant in aligned case + vsel $inout,$outhead,$inout,$outmask + stvx $inout,0,$out + + neg $enc,$ivp # write [unaligned] iv + li $idx,15 # 15 is not typo + vxor $rndkey0,$rndkey0,$rndkey0 + vspltisb $outmask,-1 + le?vspltisb $tmp,0x0f + ?lvsl $outperm,0,$enc + ?vperm $outmask,$rndkey0,$outmask,$outperm + le?vxor $outperm,$outperm,$tmp + lvx $outhead,0,$ivp + vperm $ivec,$ivec,$ivec,$outperm + vsel $inout,$outhead,$ivec,$outmask + lvx $inptail,$idx,$ivp + stvx $inout,0,$ivp + vsel $inout,$ivec,$inptail,$outmask + stvx $inout,$idx,$ivp + + mtspr 256,$vrsave + blr + .long 0 + .byte 0,12,0x14,0,0,0,6,0 + .long 0 +___ +######################################################################### +{{ # Optimized CBC decrypt procedure # +my $key_="r11"; +my ($x00,$x10,$x20,$x30,$x40,$x50,$x60,$x70)=map("r$_",(0,8,26..31)); + $x00=0 if ($flavour =~ /osx/); +my ($in0, $in1, $in2, $in3, $in4, $in5, $in6, $in7 )=map("v$_",(0..3,10..13)); +my ($out0,$out1,$out2,$out3,$out4,$out5,$out6,$out7)=map("v$_",(14..21)); +my $rndkey0="v23"; # v24-v25 rotating buffer for first found keys + # v26-v31 last 6 round keys +my ($tmp,$keyperm)=($in3,$in4); # aliases with "caller", redundant assignment + +$code.=<<___; +.align 5 +_aesp8_cbc_decrypt8x: + $STU $sp,-`($FRAME+21*16+6*$SIZE_T)`($sp) + li r10,`$FRAME+8*16+15` + li r11,`$FRAME+8*16+31` + stvx v20,r10,$sp # ABI says so + addi r10,r10,32 + stvx v21,r11,$sp + addi r11,r11,32 + stvx v22,r10,$sp + addi r10,r10,32 + stvx v23,r11,$sp + addi r11,r11,32 + stvx v24,r10,$sp + addi r10,r10,32 + stvx v25,r11,$sp + addi r11,r11,32 + stvx v26,r10,$sp + addi r10,r10,32 + stvx v27,r11,$sp + addi r11,r11,32 + stvx v28,r10,$sp + addi r10,r10,32 + stvx v29,r11,$sp + addi r11,r11,32 + stvx v30,r10,$sp + stvx v31,r11,$sp + li r0,-1 + stw $vrsave,`$FRAME+21*16-4`($sp) # save vrsave + li $x10,0x10 + $PUSH r26,`$FRAME+21*16+0*$SIZE_T`($sp) + li $x20,0x20 + $PUSH r27,`$FRAME+21*16+1*$SIZE_T`($sp) + li $x30,0x30 + $PUSH r28,`$FRAME+21*16+2*$SIZE_T`($sp) + li $x40,0x40 + $PUSH r29,`$FRAME+21*16+3*$SIZE_T`($sp) + li $x50,0x50 + $PUSH r30,`$FRAME+21*16+4*$SIZE_T`($sp) + li $x60,0x60 + $PUSH r31,`$FRAME+21*16+5*$SIZE_T`($sp) + li $x70,0x70 + mtspr 256,r0 + + subi $rounds,$rounds,3 # -4 in total + subi $len,$len,128 # bias + + lvx $rndkey0,$x00,$key # load key schedule + lvx v30,$x10,$key + addi $key,$key,0x20 + lvx v31,$x00,$key + ?vperm $rndkey0,$rndkey0,v30,$keyperm + addi $key_,$sp,$FRAME+15 + mtctr $rounds + +Load_cbc_dec_key: + ?vperm v24,v30,v31,$keyperm + lvx v30,$x10,$key + addi $key,$key,0x20 + stvx v24,$x00,$key_ # off-load round[1] + ?vperm v25,v31,v30,$keyperm + lvx v31,$x00,$key + stvx v25,$x10,$key_ # off-load round[2] + addi $key_,$key_,0x20 + bdnz Load_cbc_dec_key + + lvx v26,$x10,$key + ?vperm v24,v30,v31,$keyperm + lvx v27,$x20,$key + stvx v24,$x00,$key_ # off-load round[3] + ?vperm v25,v31,v26,$keyperm + lvx v28,$x30,$key + stvx v25,$x10,$key_ # off-load round[4] + addi $key_,$sp,$FRAME+15 # rewind $key_ + ?vperm v26,v26,v27,$keyperm + lvx v29,$x40,$key + ?vperm v27,v27,v28,$keyperm + lvx v30,$x50,$key + ?vperm v28,v28,v29,$keyperm + lvx v31,$x60,$key + ?vperm v29,v29,v30,$keyperm + lvx $out0,$x70,$key # borrow $out0 + ?vperm v30,v30,v31,$keyperm + lvx v24,$x00,$key_ # pre-load round[1] + ?vperm v31,v31,$out0,$keyperm + lvx v25,$x10,$key_ # pre-load round[2] + + #lvx $inptail,0,$inp # "caller" already did this + #addi $inp,$inp,15 # 15 is not typo + subi $inp,$inp,15 # undo "caller" + + le?li $idx,8 + lvx_u $in0,$x00,$inp # load first 8 "words" + le?lvsl $inpperm,0,$idx + le?vspltisb $tmp,0x0f + lvx_u $in1,$x10,$inp + le?vxor $inpperm,$inpperm,$tmp # transform for lvx_u/stvx_u + lvx_u $in2,$x20,$inp + le?vperm $in0,$in0,$in0,$inpperm + lvx_u $in3,$x30,$inp + le?vperm $in1,$in1,$in1,$inpperm + lvx_u $in4,$x40,$inp + le?vperm $in2,$in2,$in2,$inpperm + vxor $out0,$in0,$rndkey0 + lvx_u $in5,$x50,$inp + le?vperm $in3,$in3,$in3,$inpperm + vxor $out1,$in1,$rndkey0 + lvx_u $in6,$x60,$inp + le?vperm $in4,$in4,$in4,$inpperm + vxor $out2,$in2,$rndkey0 + lvx_u $in7,$x70,$inp + addi $inp,$inp,0x80 + le?vperm $in5,$in5,$in5,$inpperm + vxor $out3,$in3,$rndkey0 + le?vperm $in6,$in6,$in6,$inpperm + vxor $out4,$in4,$rndkey0 + le?vperm $in7,$in7,$in7,$inpperm + vxor $out5,$in5,$rndkey0 + vxor $out6,$in6,$rndkey0 + vxor $out7,$in7,$rndkey0 + + mtctr $rounds + b Loop_cbc_dec8x +.align 5 +Loop_cbc_dec8x: + vncipher $out0,$out0,v24 + vncipher $out1,$out1,v24 + vncipher $out2,$out2,v24 + vncipher $out3,$out3,v24 + vncipher $out4,$out4,v24 + vncipher $out5,$out5,v24 + vncipher $out6,$out6,v24 + vncipher $out7,$out7,v24 + lvx v24,$x20,$key_ # round[3] + addi $key_,$key_,0x20 + + vncipher $out0,$out0,v25 + vncipher $out1,$out1,v25 + vncipher $out2,$out2,v25 + vncipher $out3,$out3,v25 + vncipher $out4,$out4,v25 + vncipher $out5,$out5,v25 + vncipher $out6,$out6,v25 + vncipher $out7,$out7,v25 + lvx v25,$x10,$key_ # round[4] + bdnz Loop_cbc_dec8x + + subic $len,$len,128 # $len-=128 + vncipher $out0,$out0,v24 + vncipher $out1,$out1,v24 + vncipher $out2,$out2,v24 + vncipher $out3,$out3,v24 + vncipher $out4,$out4,v24 + vncipher $out5,$out5,v24 + vncipher $out6,$out6,v24 + vncipher $out7,$out7,v24 + + subfe. r0,r0,r0 # borrow?-1:0 + vncipher $out0,$out0,v25 + vncipher $out1,$out1,v25 + vncipher $out2,$out2,v25 + vncipher $out3,$out3,v25 + vncipher $out4,$out4,v25 + vncipher $out5,$out5,v25 + vncipher $out6,$out6,v25 + vncipher $out7,$out7,v25 + + and r0,r0,$len + vncipher $out0,$out0,v26 + vncipher $out1,$out1,v26 + vncipher $out2,$out2,v26 + vncipher $out3,$out3,v26 + vncipher $out4,$out4,v26 + vncipher $out5,$out5,v26 + vncipher $out6,$out6,v26 + vncipher $out7,$out7,v26 + + add $inp,$inp,r0 # $inp is adjusted in such + # way that at exit from the + # loop inX-in7 are loaded + # with last "words" + vncipher $out0,$out0,v27 + vncipher $out1,$out1,v27 + vncipher $out2,$out2,v27 + vncipher $out3,$out3,v27 + vncipher $out4,$out4,v27 + vncipher $out5,$out5,v27 + vncipher $out6,$out6,v27 + vncipher $out7,$out7,v27 + + addi $key_,$sp,$FRAME+15 # rewind $key_ + vncipher $out0,$out0,v28 + vncipher $out1,$out1,v28 + vncipher $out2,$out2,v28 + vncipher $out3,$out3,v28 + vncipher $out4,$out4,v28 + vncipher $out5,$out5,v28 + vncipher $out6,$out6,v28 + vncipher $out7,$out7,v28 + lvx v24,$x00,$key_ # re-pre-load round[1] + + vncipher $out0,$out0,v29 + vncipher $out1,$out1,v29 + vncipher $out2,$out2,v29 + vncipher $out3,$out3,v29 + vncipher $out4,$out4,v29 + vncipher $out5,$out5,v29 + vncipher $out6,$out6,v29 + vncipher $out7,$out7,v29 + lvx v25,$x10,$key_ # re-pre-load round[2] + + vncipher $out0,$out0,v30 + vxor $ivec,$ivec,v31 # xor with last round key + vncipher $out1,$out1,v30 + vxor $in0,$in0,v31 + vncipher $out2,$out2,v30 + vxor $in1,$in1,v31 + vncipher $out3,$out3,v30 + vxor $in2,$in2,v31 + vncipher $out4,$out4,v30 + vxor $in3,$in3,v31 + vncipher $out5,$out5,v30 + vxor $in4,$in4,v31 + vncipher $out6,$out6,v30 + vxor $in5,$in5,v31 + vncipher $out7,$out7,v30 + vxor $in6,$in6,v31 + + vncipherlast $out0,$out0,$ivec + vncipherlast $out1,$out1,$in0 + lvx_u $in0,$x00,$inp # load next input block + vncipherlast $out2,$out2,$in1 + lvx_u $in1,$x10,$inp + vncipherlast $out3,$out3,$in2 + le?vperm $in0,$in0,$in0,$inpperm + lvx_u $in2,$x20,$inp + vncipherlast $out4,$out4,$in3 + le?vperm $in1,$in1,$in1,$inpperm + lvx_u $in3,$x30,$inp + vncipherlast $out5,$out5,$in4 + le?vperm $in2,$in2,$in2,$inpperm + lvx_u $in4,$x40,$inp + vncipherlast $out6,$out6,$in5 + le?vperm $in3,$in3,$in3,$inpperm + lvx_u $in5,$x50,$inp + vncipherlast $out7,$out7,$in6 + le?vperm $in4,$in4,$in4,$inpperm + lvx_u $in6,$x60,$inp + vmr $ivec,$in7 + le?vperm $in5,$in5,$in5,$inpperm + lvx_u $in7,$x70,$inp + addi $inp,$inp,0x80 + + le?vperm $out0,$out0,$out0,$inpperm + le?vperm $out1,$out1,$out1,$inpperm + stvx_u $out0,$x00,$out + le?vperm $in6,$in6,$in6,$inpperm + vxor $out0,$in0,$rndkey0 + le?vperm $out2,$out2,$out2,$inpperm + stvx_u $out1,$x10,$out + le?vperm $in7,$in7,$in7,$inpperm + vxor $out1,$in1,$rndkey0 + le?vperm $out3,$out3,$out3,$inpperm + stvx_u $out2,$x20,$out + vxor $out2,$in2,$rndkey0 + le?vperm $out4,$out4,$out4,$inpperm + stvx_u $out3,$x30,$out + vxor $out3,$in3,$rndkey0 + le?vperm $out5,$out5,$out5,$inpperm + stvx_u $out4,$x40,$out + vxor $out4,$in4,$rndkey0 + le?vperm $out6,$out6,$out6,$inpperm + stvx_u $out5,$x50,$out + vxor $out5,$in5,$rndkey0 + le?vperm $out7,$out7,$out7,$inpperm + stvx_u $out6,$x60,$out + vxor $out6,$in6,$rndkey0 + stvx_u $out7,$x70,$out + addi $out,$out,0x80 + vxor $out7,$in7,$rndkey0 + + mtctr $rounds + beq Loop_cbc_dec8x # did $len-=128 borrow? + + addic. $len,$len,128 + beq Lcbc_dec8x_done + nop + nop + +Loop_cbc_dec8x_tail: # up to 7 "words" tail... + vncipher $out1,$out1,v24 + vncipher $out2,$out2,v24 + vncipher $out3,$out3,v24 + vncipher $out4,$out4,v24 + vncipher $out5,$out5,v24 + vncipher $out6,$out6,v24 + vncipher $out7,$out7,v24 + lvx v24,$x20,$key_ # round[3] + addi $key_,$key_,0x20 + + vncipher $out1,$out1,v25 + vncipher $out2,$out2,v25 + vncipher $out3,$out3,v25 + vncipher $out4,$out4,v25 + vncipher $out5,$out5,v25 + vncipher $out6,$out6,v25 + vncipher $out7,$out7,v25 + lvx v25,$x10,$key_ # round[4] + bdnz Loop_cbc_dec8x_tail + + vncipher $out1,$out1,v24 + vncipher $out2,$out2,v24 + vncipher $out3,$out3,v24 + vncipher $out4,$out4,v24 + vncipher $out5,$out5,v24 + vncipher $out6,$out6,v24 + vncipher $out7,$out7,v24 + + vncipher $out1,$out1,v25 + vncipher $out2,$out2,v25 + vncipher $out3,$out3,v25 + vncipher $out4,$out4,v25 + vncipher $out5,$out5,v25 + vncipher $out6,$out6,v25 + vncipher $out7,$out7,v25 + + vncipher $out1,$out1,v26 + vncipher $out2,$out2,v26 + vncipher $out3,$out3,v26 + vncipher $out4,$out4,v26 + vncipher $out5,$out5,v26 + vncipher $out6,$out6,v26 + vncipher $out7,$out7,v26 + + vncipher $out1,$out1,v27 + vncipher $out2,$out2,v27 + vncipher $out3,$out3,v27 + vncipher $out4,$out4,v27 + vncipher $out5,$out5,v27 + vncipher $out6,$out6,v27 + vncipher $out7,$out7,v27 + + vncipher $out1,$out1,v28 + vncipher $out2,$out2,v28 + vncipher $out3,$out3,v28 + vncipher $out4,$out4,v28 + vncipher $out5,$out5,v28 + vncipher $out6,$out6,v28 + vncipher $out7,$out7,v28 + + vncipher $out1,$out1,v29 + vncipher $out2,$out2,v29 + vncipher $out3,$out3,v29 + vncipher $out4,$out4,v29 + vncipher $out5,$out5,v29 + vncipher $out6,$out6,v29 + vncipher $out7,$out7,v29 + + vncipher $out1,$out1,v30 + vxor $ivec,$ivec,v31 # last round key + vncipher $out2,$out2,v30 + vxor $in1,$in1,v31 + vncipher $out3,$out3,v30 + vxor $in2,$in2,v31 + vncipher $out4,$out4,v30 + vxor $in3,$in3,v31 + vncipher $out5,$out5,v30 + vxor $in4,$in4,v31 + vncipher $out6,$out6,v30 + vxor $in5,$in5,v31 + vncipher $out7,$out7,v30 + vxor $in6,$in6,v31 + + cmplwi $len,32 # switch($len) + blt Lcbc_dec8x_one + nop + beq Lcbc_dec8x_two + cmplwi $len,64 + blt Lcbc_dec8x_three + nop + beq Lcbc_dec8x_four + cmplwi $len,96 + blt Lcbc_dec8x_five + nop + beq Lcbc_dec8x_six + +Lcbc_dec8x_seven: + vncipherlast $out1,$out1,$ivec + vncipherlast $out2,$out2,$in1 + vncipherlast $out3,$out3,$in2 + vncipherlast $out4,$out4,$in3 + vncipherlast $out5,$out5,$in4 + vncipherlast $out6,$out6,$in5 + vncipherlast $out7,$out7,$in6 + vmr $ivec,$in7 + + le?vperm $out1,$out1,$out1,$inpperm + le?vperm $out2,$out2,$out2,$inpperm + stvx_u $out1,$x00,$out + le?vperm $out3,$out3,$out3,$inpperm + stvx_u $out2,$x10,$out + le?vperm $out4,$out4,$out4,$inpperm + stvx_u $out3,$x20,$out + le?vperm $out5,$out5,$out5,$inpperm + stvx_u $out4,$x30,$out + le?vperm $out6,$out6,$out6,$inpperm + stvx_u $out5,$x40,$out + le?vperm $out7,$out7,$out7,$inpperm + stvx_u $out6,$x50,$out + stvx_u $out7,$x60,$out + addi $out,$out,0x70 + b Lcbc_dec8x_done + +.align 5 +Lcbc_dec8x_six: + vncipherlast $out2,$out2,$ivec + vncipherlast $out3,$out3,$in2 + vncipherlast $out4,$out4,$in3 + vncipherlast $out5,$out5,$in4 + vncipherlast $out6,$out6,$in5 + vncipherlast $out7,$out7,$in6 + vmr $ivec,$in7 + + le?vperm $out2,$out2,$out2,$inpperm + le?vperm $out3,$out3,$out3,$inpperm + stvx_u $out2,$x00,$out + le?vperm $out4,$out4,$out4,$inpperm + stvx_u $out3,$x10,$out + le?vperm $out5,$out5,$out5,$inpperm + stvx_u $out4,$x20,$out + le?vperm $out6,$out6,$out6,$inpperm + stvx_u $out5,$x30,$out + le?vperm $out7,$out7,$out7,$inpperm + stvx_u $out6,$x40,$out + stvx_u $out7,$x50,$out + addi $out,$out,0x60 + b Lcbc_dec8x_done + +.align 5 +Lcbc_dec8x_five: + vncipherlast $out3,$out3,$ivec + vncipherlast $out4,$out4,$in3 + vncipherlast $out5,$out5,$in4 + vncipherlast $out6,$out6,$in5 + vncipherlast $out7,$out7,$in6 + vmr $ivec,$in7 + + le?vperm $out3,$out3,$out3,$inpperm + le?vperm $out4,$out4,$out4,$inpperm + stvx_u $out3,$x00,$out + le?vperm $out5,$out5,$out5,$inpperm + stvx_u $out4,$x10,$out + le?vperm $out6,$out6,$out6,$inpperm + stvx_u $out5,$x20,$out + le?vperm $out7,$out7,$out7,$inpperm + stvx_u $out6,$x30,$out + stvx_u $out7,$x40,$out + addi $out,$out,0x50 + b Lcbc_dec8x_done + +.align 5 +Lcbc_dec8x_four: + vncipherlast $out4,$out4,$ivec + vncipherlast $out5,$out5,$in4 + vncipherlast $out6,$out6,$in5 + vncipherlast $out7,$out7,$in6 + vmr $ivec,$in7 + + le?vperm $out4,$out4,$out4,$inpperm + le?vperm $out5,$out5,$out5,$inpperm + stvx_u $out4,$x00,$out + le?vperm $out6,$out6,$out6,$inpperm + stvx_u $out5,$x10,$out + le?vperm $out7,$out7,$out7,$inpperm + stvx_u $out6,$x20,$out + stvx_u $out7,$x30,$out + addi $out,$out,0x40 + b Lcbc_dec8x_done + +.align 5 +Lcbc_dec8x_three: + vncipherlast $out5,$out5,$ivec + vncipherlast $out6,$out6,$in5 + vncipherlast $out7,$out7,$in6 + vmr $ivec,$in7 + + le?vperm $out5,$out5,$out5,$inpperm + le?vperm $out6,$out6,$out6,$inpperm + stvx_u $out5,$x00,$out + le?vperm $out7,$out7,$out7,$inpperm + stvx_u $out6,$x10,$out + stvx_u $out7,$x20,$out + addi $out,$out,0x30 + b Lcbc_dec8x_done + +.align 5 +Lcbc_dec8x_two: + vncipherlast $out6,$out6,$ivec + vncipherlast $out7,$out7,$in6 + vmr $ivec,$in7 + + le?vperm $out6,$out6,$out6,$inpperm + le?vperm $out7,$out7,$out7,$inpperm + stvx_u $out6,$x00,$out + stvx_u $out7,$x10,$out + addi $out,$out,0x20 + b Lcbc_dec8x_done + +.align 5 +Lcbc_dec8x_one: + vncipherlast $out7,$out7,$ivec + vmr $ivec,$in7 + + le?vperm $out7,$out7,$out7,$inpperm + stvx_u $out7,0,$out + addi $out,$out,0x10 + +Lcbc_dec8x_done: + le?vperm $ivec,$ivec,$ivec,$inpperm + stvx_u $ivec,0,$ivp # write [unaligned] iv + + li r10,`$FRAME+15` + li r11,`$FRAME+31` + stvx $inpperm,r10,$sp # wipe copies of round keys + addi r10,r10,32 + stvx $inpperm,r11,$sp + addi r11,r11,32 + stvx $inpperm,r10,$sp + addi r10,r10,32 + stvx $inpperm,r11,$sp + addi r11,r11,32 + stvx $inpperm,r10,$sp + addi r10,r10,32 + stvx $inpperm,r11,$sp + addi r11,r11,32 + stvx $inpperm,r10,$sp + addi r10,r10,32 + stvx $inpperm,r11,$sp + addi r11,r11,32 + + mtspr 256,$vrsave + lvx v20,r10,$sp # ABI says so + addi r10,r10,32 + lvx v21,r11,$sp + addi r11,r11,32 + lvx v22,r10,$sp + addi r10,r10,32 + lvx v23,r11,$sp + addi r11,r11,32 + lvx v24,r10,$sp + addi r10,r10,32 + lvx v25,r11,$sp + addi r11,r11,32 + lvx v26,r10,$sp + addi r10,r10,32 + lvx v27,r11,$sp + addi r11,r11,32 + lvx v28,r10,$sp + addi r10,r10,32 + lvx v29,r11,$sp + addi r11,r11,32 + lvx v30,r10,$sp + lvx v31,r11,$sp + $POP r26,`$FRAME+21*16+0*$SIZE_T`($sp) + $POP r27,`$FRAME+21*16+1*$SIZE_T`($sp) + $POP r28,`$FRAME+21*16+2*$SIZE_T`($sp) + $POP r29,`$FRAME+21*16+3*$SIZE_T`($sp) + $POP r30,`$FRAME+21*16+4*$SIZE_T`($sp) + $POP r31,`$FRAME+21*16+5*$SIZE_T`($sp) + addi $sp,$sp,`$FRAME+21*16+6*$SIZE_T` + blr + .long 0 + .byte 0,12,0x04,0,0x80,6,6,0 + .long 0 +.size .${prefix}_cbc_encrypt,.-.${prefix}_cbc_encrypt +___ +}} }}} + +######################################################################### +{{{ # CTR procedure[s] # +my ($inp,$out,$len,$key,$ivp,$x10,$rounds,$idx)=map("r$_",(3..10)); +my ($rndkey0,$rndkey1,$inout,$tmp)= map("v$_",(0..3)); +my ($ivec,$inptail,$inpperm,$outhead,$outperm,$outmask,$keyperm,$one)= + map("v$_",(4..11)); +my $dat=$tmp; + +$code.=<<___; +.globl .${prefix}_ctr32_encrypt_blocks +.align 5 +.${prefix}_ctr32_encrypt_blocks: + ${UCMP}i $len,1 + bltlr- + + lis r0,0xfff0 + mfspr $vrsave,256 + mtspr 256,r0 + + li $idx,15 + vxor $rndkey0,$rndkey0,$rndkey0 + le?vspltisb $tmp,0x0f + + lvx $ivec,0,$ivp # load [unaligned] iv + lvsl $inpperm,0,$ivp + lvx $inptail,$idx,$ivp + vspltisb $one,1 + le?vxor $inpperm,$inpperm,$tmp + vperm $ivec,$ivec,$inptail,$inpperm + vsldoi $one,$rndkey0,$one,1 + + neg r11,$inp + ?lvsl $keyperm,0,$key # prepare for unaligned key + lwz $rounds,240($key) + + lvsr $inpperm,0,r11 # prepare for unaligned load + lvx $inptail,0,$inp + addi $inp,$inp,15 # 15 is not typo + le?vxor $inpperm,$inpperm,$tmp + + srwi $rounds,$rounds,1 + li $idx,16 + subi $rounds,$rounds,1 + + ${UCMP}i $len,8 + bge _aesp8_ctr32_encrypt8x + + ?lvsr $outperm,0,$out # prepare for unaligned store + vspltisb $outmask,-1 + lvx $outhead,0,$out + ?vperm $outmask,$rndkey0,$outmask,$outperm + le?vxor $outperm,$outperm,$tmp + + lvx $rndkey0,0,$key + mtctr $rounds + lvx $rndkey1,$idx,$key + addi $idx,$idx,16 + ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm + vxor $inout,$ivec,$rndkey0 + lvx $rndkey0,$idx,$key + addi $idx,$idx,16 + b Loop_ctr32_enc + +.align 5 +Loop_ctr32_enc: + ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm + vcipher $inout,$inout,$rndkey1 + lvx $rndkey1,$idx,$key + addi $idx,$idx,16 + ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm + vcipher $inout,$inout,$rndkey0 + lvx $rndkey0,$idx,$key + addi $idx,$idx,16 + bdnz Loop_ctr32_enc + + vadduwm $ivec,$ivec,$one + vmr $dat,$inptail + lvx $inptail,0,$inp + addi $inp,$inp,16 + subic. $len,$len,1 # blocks-- + + ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm + vcipher $inout,$inout,$rndkey1 + lvx $rndkey1,$idx,$key + vperm $dat,$dat,$inptail,$inpperm + li $idx,16 + ?vperm $rndkey1,$rndkey0,$rndkey1,$keyperm + lvx $rndkey0,0,$key + vxor $dat,$dat,$rndkey1 # last round key + vcipherlast $inout,$inout,$dat + + lvx $rndkey1,$idx,$key + addi $idx,$idx,16 + vperm $inout,$inout,$inout,$outperm + vsel $dat,$outhead,$inout,$outmask + mtctr $rounds + ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm + vmr $outhead,$inout + vxor $inout,$ivec,$rndkey0 + lvx $rndkey0,$idx,$key + addi $idx,$idx,16 + stvx $dat,0,$out + addi $out,$out,16 + bne Loop_ctr32_enc + + addi $out,$out,-1 + lvx $inout,0,$out # redundant in aligned case + vsel $inout,$outhead,$inout,$outmask + stvx $inout,0,$out + + mtspr 256,$vrsave + blr + .long 0 + .byte 0,12,0x14,0,0,0,6,0 + .long 0 +___ +######################################################################### +{{ # Optimized CTR procedure # +my $key_="r11"; +my ($x00,$x10,$x20,$x30,$x40,$x50,$x60,$x70)=map("r$_",(0,8,26..31)); + $x00=0 if ($flavour =~ /osx/); +my ($in0, $in1, $in2, $in3, $in4, $in5, $in6, $in7 )=map("v$_",(0..3,10,12..14)); +my ($out0,$out1,$out2,$out3,$out4,$out5,$out6,$out7)=map("v$_",(15..22)); +my $rndkey0="v23"; # v24-v25 rotating buffer for first found keys + # v26-v31 last 6 round keys +my ($tmp,$keyperm)=($in3,$in4); # aliases with "caller", redundant assignment +my ($two,$three,$four)=($outhead,$outperm,$outmask); + +$code.=<<___; +.align 5 +_aesp8_ctr32_encrypt8x: + $STU $sp,-`($FRAME+21*16+6*$SIZE_T)`($sp) + li r10,`$FRAME+8*16+15` + li r11,`$FRAME+8*16+31` + stvx v20,r10,$sp # ABI says so + addi r10,r10,32 + stvx v21,r11,$sp + addi r11,r11,32 + stvx v22,r10,$sp + addi r10,r10,32 + stvx v23,r11,$sp + addi r11,r11,32 + stvx v24,r10,$sp + addi r10,r10,32 + stvx v25,r11,$sp + addi r11,r11,32 + stvx v26,r10,$sp + addi r10,r10,32 + stvx v27,r11,$sp + addi r11,r11,32 + stvx v28,r10,$sp + addi r10,r10,32 + stvx v29,r11,$sp + addi r11,r11,32 + stvx v30,r10,$sp + stvx v31,r11,$sp + li r0,-1 + stw $vrsave,`$FRAME+21*16-4`($sp) # save vrsave + li $x10,0x10 + $PUSH r26,`$FRAME+21*16+0*$SIZE_T`($sp) + li $x20,0x20 + $PUSH r27,`$FRAME+21*16+1*$SIZE_T`($sp) + li $x30,0x30 + $PUSH r28,`$FRAME+21*16+2*$SIZE_T`($sp) + li $x40,0x40 + $PUSH r29,`$FRAME+21*16+3*$SIZE_T`($sp) + li $x50,0x50 + $PUSH r30,`$FRAME+21*16+4*$SIZE_T`($sp) + li $x60,0x60 + $PUSH r31,`$FRAME+21*16+5*$SIZE_T`($sp) + li $x70,0x70 + mtspr 256,r0 + + subi $rounds,$rounds,3 # -4 in total + + lvx $rndkey0,$x00,$key # load key schedule + lvx v30,$x10,$key + addi $key,$key,0x20 + lvx v31,$x00,$key + ?vperm $rndkey0,$rndkey0,v30,$keyperm + addi $key_,$sp,$FRAME+15 + mtctr $rounds + +Load_ctr32_enc_key: + ?vperm v24,v30,v31,$keyperm + lvx v30,$x10,$key + addi $key,$key,0x20 + stvx v24,$x00,$key_ # off-load round[1] + ?vperm v25,v31,v30,$keyperm + lvx v31,$x00,$key + stvx v25,$x10,$key_ # off-load round[2] + addi $key_,$key_,0x20 + bdnz Load_ctr32_enc_key + + lvx v26,$x10,$key + ?vperm v24,v30,v31,$keyperm + lvx v27,$x20,$key + stvx v24,$x00,$key_ # off-load round[3] + ?vperm v25,v31,v26,$keyperm + lvx v28,$x30,$key + stvx v25,$x10,$key_ # off-load round[4] + addi $key_,$sp,$FRAME+15 # rewind $key_ + ?vperm v26,v26,v27,$keyperm + lvx v29,$x40,$key + ?vperm v27,v27,v28,$keyperm + lvx v30,$x50,$key + ?vperm v28,v28,v29,$keyperm + lvx v31,$x60,$key + ?vperm v29,v29,v30,$keyperm + lvx $out0,$x70,$key # borrow $out0 + ?vperm v30,v30,v31,$keyperm + lvx v24,$x00,$key_ # pre-load round[1] + ?vperm v31,v31,$out0,$keyperm + lvx v25,$x10,$key_ # pre-load round[2] + + vadduwm $two,$one,$one + subi $inp,$inp,15 # undo "caller" + $SHL $len,$len,4 + + vadduwm $out1,$ivec,$one # counter values ... + vadduwm $out2,$ivec,$two + vxor $out0,$ivec,$rndkey0 # ... xored with rndkey[0] + le?li $idx,8 + vadduwm $out3,$out1,$two + vxor $out1,$out1,$rndkey0 + le?lvsl $inpperm,0,$idx + vadduwm $out4,$out2,$two + vxor $out2,$out2,$rndkey0 + le?vspltisb $tmp,0x0f + vadduwm $out5,$out3,$two + vxor $out3,$out3,$rndkey0 + le?vxor $inpperm,$inpperm,$tmp # transform for lvx_u/stvx_u + vadduwm $out6,$out4,$two + vxor $out4,$out4,$rndkey0 + vadduwm $out7,$out5,$two + vxor $out5,$out5,$rndkey0 + vadduwm $ivec,$out6,$two # next counter value + vxor $out6,$out6,$rndkey0 + vxor $out7,$out7,$rndkey0 + + mtctr $rounds + b Loop_ctr32_enc8x +.align 5 +Loop_ctr32_enc8x: + vcipher $out0,$out0,v24 + vcipher $out1,$out1,v24 + vcipher $out2,$out2,v24 + vcipher $out3,$out3,v24 + vcipher $out4,$out4,v24 + vcipher $out5,$out5,v24 + vcipher $out6,$out6,v24 + vcipher $out7,$out7,v24 +Loop_ctr32_enc8x_middle: + lvx v24,$x20,$key_ # round[3] + addi $key_,$key_,0x20 + + vcipher $out0,$out0,v25 + vcipher $out1,$out1,v25 + vcipher $out2,$out2,v25 + vcipher $out3,$out3,v25 + vcipher $out4,$out4,v25 + vcipher $out5,$out5,v25 + vcipher $out6,$out6,v25 + vcipher $out7,$out7,v25 + lvx v25,$x10,$key_ # round[4] + bdnz Loop_ctr32_enc8x + + subic r11,$len,256 # $len-256, borrow $key_ + vcipher $out0,$out0,v24 + vcipher $out1,$out1,v24 + vcipher $out2,$out2,v24 + vcipher $out3,$out3,v24 + vcipher $out4,$out4,v24 + vcipher $out5,$out5,v24 + vcipher $out6,$out6,v24 + vcipher $out7,$out7,v24 + + subfe r0,r0,r0 # borrow?-1:0 + vcipher $out0,$out0,v25 + vcipher $out1,$out1,v25 + vcipher $out2,$out2,v25 + vcipher $out3,$out3,v25 + vcipher $out4,$out4,v25 + vcipher $out5,$out5,v25 + vcipher $out6,$out6,v25 + vcipher $out7,$out7,v25 + + and r0,r0,r11 + addi $key_,$sp,$FRAME+15 # rewind $key_ + vcipher $out0,$out0,v26 + vcipher $out1,$out1,v26 + vcipher $out2,$out2,v26 + vcipher $out3,$out3,v26 + vcipher $out4,$out4,v26 + vcipher $out5,$out5,v26 + vcipher $out6,$out6,v26 + vcipher $out7,$out7,v26 + lvx v24,$x00,$key_ # re-pre-load round[1] + + subic $len,$len,129 # $len-=129 + vcipher $out0,$out0,v27 + addi $len,$len,1 # $len-=128 really + vcipher $out1,$out1,v27 + vcipher $out2,$out2,v27 + vcipher $out3,$out3,v27 + vcipher $out4,$out4,v27 + vcipher $out5,$out5,v27 + vcipher $out6,$out6,v27 + vcipher $out7,$out7,v27 + lvx v25,$x10,$key_ # re-pre-load round[2] + + vcipher $out0,$out0,v28 + lvx_u $in0,$x00,$inp # load input + vcipher $out1,$out1,v28 + lvx_u $in1,$x10,$inp + vcipher $out2,$out2,v28 + lvx_u $in2,$x20,$inp + vcipher $out3,$out3,v28 + lvx_u $in3,$x30,$inp + vcipher $out4,$out4,v28 + lvx_u $in4,$x40,$inp + vcipher $out5,$out5,v28 + lvx_u $in5,$x50,$inp + vcipher $out6,$out6,v28 + lvx_u $in6,$x60,$inp + vcipher $out7,$out7,v28 + lvx_u $in7,$x70,$inp + addi $inp,$inp,0x80 + + vcipher $out0,$out0,v29 + le?vperm $in0,$in0,$in0,$inpperm + vcipher $out1,$out1,v29 + le?vperm $in1,$in1,$in1,$inpperm + vcipher $out2,$out2,v29 + le?vperm $in2,$in2,$in2,$inpperm + vcipher $out3,$out3,v29 + le?vperm $in3,$in3,$in3,$inpperm + vcipher $out4,$out4,v29 + le?vperm $in4,$in4,$in4,$inpperm + vcipher $out5,$out5,v29 + le?vperm $in5,$in5,$in5,$inpperm + vcipher $out6,$out6,v29 + le?vperm $in6,$in6,$in6,$inpperm + vcipher $out7,$out7,v29 + le?vperm $in7,$in7,$in7,$inpperm + + add $inp,$inp,r0 # $inp is adjusted in such + # way that at exit from the + # loop inX-in7 are loaded + # with last "words" + subfe. r0,r0,r0 # borrow?-1:0 + vcipher $out0,$out0,v30 + vxor $in0,$in0,v31 # xor with last round key + vcipher $out1,$out1,v30 + vxor $in1,$in1,v31 + vcipher $out2,$out2,v30 + vxor $in2,$in2,v31 + vcipher $out3,$out3,v30 + vxor $in3,$in3,v31 + vcipher $out4,$out4,v30 + vxor $in4,$in4,v31 + vcipher $out5,$out5,v30 + vxor $in5,$in5,v31 + vcipher $out6,$out6,v30 + vxor $in6,$in6,v31 + vcipher $out7,$out7,v30 + vxor $in7,$in7,v31 + + bne Lctr32_enc8x_break # did $len-129 borrow? + + vcipherlast $in0,$out0,$in0 + vcipherlast $in1,$out1,$in1 + vadduwm $out1,$ivec,$one # counter values ... + vcipherlast $in2,$out2,$in2 + vadduwm $out2,$ivec,$two + vxor $out0,$ivec,$rndkey0 # ... xored with rndkey[0] + vcipherlast $in3,$out3,$in3 + vadduwm $out3,$out1,$two + vxor $out1,$out1,$rndkey0 + vcipherlast $in4,$out4,$in4 + vadduwm $out4,$out2,$two + vxor $out2,$out2,$rndkey0 + vcipherlast $in5,$out5,$in5 + vadduwm $out5,$out3,$two + vxor $out3,$out3,$rndkey0 + vcipherlast $in6,$out6,$in6 + vadduwm $out6,$out4,$two + vxor $out4,$out4,$rndkey0 + vcipherlast $in7,$out7,$in7 + vadduwm $out7,$out5,$two + vxor $out5,$out5,$rndkey0 + le?vperm $in0,$in0,$in0,$inpperm + vadduwm $ivec,$out6,$two # next counter value + vxor $out6,$out6,$rndkey0 + le?vperm $in1,$in1,$in1,$inpperm + vxor $out7,$out7,$rndkey0 + mtctr $rounds + + vcipher $out0,$out0,v24 + stvx_u $in0,$x00,$out + le?vperm $in2,$in2,$in2,$inpperm + vcipher $out1,$out1,v24 + stvx_u $in1,$x10,$out + le?vperm $in3,$in3,$in3,$inpperm + vcipher $out2,$out2,v24 + stvx_u $in2,$x20,$out + le?vperm $in4,$in4,$in4,$inpperm + vcipher $out3,$out3,v24 + stvx_u $in3,$x30,$out + le?vperm $in5,$in5,$in5,$inpperm + vcipher $out4,$out4,v24 + stvx_u $in4,$x40,$out + le?vperm $in6,$in6,$in6,$inpperm + vcipher $out5,$out5,v24 + stvx_u $in5,$x50,$out + le?vperm $in7,$in7,$in7,$inpperm + vcipher $out6,$out6,v24 + stvx_u $in6,$x60,$out + vcipher $out7,$out7,v24 + stvx_u $in7,$x70,$out + addi $out,$out,0x80 + + b Loop_ctr32_enc8x_middle + +.align 5 +Lctr32_enc8x_break: + cmpwi $len,-0x60 + blt Lctr32_enc8x_one + nop + beq Lctr32_enc8x_two + cmpwi $len,-0x40 + blt Lctr32_enc8x_three + nop + beq Lctr32_enc8x_four + cmpwi $len,-0x20 + blt Lctr32_enc8x_five + nop + beq Lctr32_enc8x_six + cmpwi $len,0x00 + blt Lctr32_enc8x_seven + +Lctr32_enc8x_eight: + vcipherlast $out0,$out0,$in0 + vcipherlast $out1,$out1,$in1 + vcipherlast $out2,$out2,$in2 + vcipherlast $out3,$out3,$in3 + vcipherlast $out4,$out4,$in4 + vcipherlast $out5,$out5,$in5 + vcipherlast $out6,$out6,$in6 + vcipherlast $out7,$out7,$in7 + + le?vperm $out0,$out0,$out0,$inpperm + le?vperm $out1,$out1,$out1,$inpperm + stvx_u $out0,$x00,$out + le?vperm $out2,$out2,$out2,$inpperm + stvx_u $out1,$x10,$out + le?vperm $out3,$out3,$out3,$inpperm + stvx_u $out2,$x20,$out + le?vperm $out4,$out4,$out4,$inpperm + stvx_u $out3,$x30,$out + le?vperm $out5,$out5,$out5,$inpperm + stvx_u $out4,$x40,$out + le?vperm $out6,$out6,$out6,$inpperm + stvx_u $out5,$x50,$out + le?vperm $out7,$out7,$out7,$inpperm + stvx_u $out6,$x60,$out + stvx_u $out7,$x70,$out + addi $out,$out,0x80 + b Lctr32_enc8x_done + +.align 5 +Lctr32_enc8x_seven: + vcipherlast $out0,$out0,$in1 + vcipherlast $out1,$out1,$in2 + vcipherlast $out2,$out2,$in3 + vcipherlast $out3,$out3,$in4 + vcipherlast $out4,$out4,$in5 + vcipherlast $out5,$out5,$in6 + vcipherlast $out6,$out6,$in7 + + le?vperm $out0,$out0,$out0,$inpperm + le?vperm $out1,$out1,$out1,$inpperm + stvx_u $out0,$x00,$out + le?vperm $out2,$out2,$out2,$inpperm + stvx_u $out1,$x10,$out + le?vperm $out3,$out3,$out3,$inpperm + stvx_u $out2,$x20,$out + le?vperm $out4,$out4,$out4,$inpperm + stvx_u $out3,$x30,$out + le?vperm $out5,$out5,$out5,$inpperm + stvx_u $out4,$x40,$out + le?vperm $out6,$out6,$out6,$inpperm + stvx_u $out5,$x50,$out + stvx_u $out6,$x60,$out + addi $out,$out,0x70 + b Lctr32_enc8x_done + +.align 5 +Lctr32_enc8x_six: + vcipherlast $out0,$out0,$in2 + vcipherlast $out1,$out1,$in3 + vcipherlast $out2,$out2,$in4 + vcipherlast $out3,$out3,$in5 + vcipherlast $out4,$out4,$in6 + vcipherlast $out5,$out5,$in7 + + le?vperm $out0,$out0,$out0,$inpperm + le?vperm $out1,$out1,$out1,$inpperm + stvx_u $out0,$x00,$out + le?vperm $out2,$out2,$out2,$inpperm + stvx_u $out1,$x10,$out + le?vperm $out3,$out3,$out3,$inpperm + stvx_u $out2,$x20,$out + le?vperm $out4,$out4,$out4,$inpperm + stvx_u $out3,$x30,$out + le?vperm $out5,$out5,$out5,$inpperm + stvx_u $out4,$x40,$out + stvx_u $out5,$x50,$out + addi $out,$out,0x60 + b Lctr32_enc8x_done + +.align 5 +Lctr32_enc8x_five: + vcipherlast $out0,$out0,$in3 + vcipherlast $out1,$out1,$in4 + vcipherlast $out2,$out2,$in5 + vcipherlast $out3,$out3,$in6 + vcipherlast $out4,$out4,$in7 + + le?vperm $out0,$out0,$out0,$inpperm + le?vperm $out1,$out1,$out1,$inpperm + stvx_u $out0,$x00,$out + le?vperm $out2,$out2,$out2,$inpperm + stvx_u $out1,$x10,$out + le?vperm $out3,$out3,$out3,$inpperm + stvx_u $out2,$x20,$out + le?vperm $out4,$out4,$out4,$inpperm + stvx_u $out3,$x30,$out + stvx_u $out4,$x40,$out + addi $out,$out,0x50 + b Lctr32_enc8x_done + +.align 5 +Lctr32_enc8x_four: + vcipherlast $out0,$out0,$in4 + vcipherlast $out1,$out1,$in5 + vcipherlast $out2,$out2,$in6 + vcipherlast $out3,$out3,$in7 + + le?vperm $out0,$out0,$out0,$inpperm + le?vperm $out1,$out1,$out1,$inpperm + stvx_u $out0,$x00,$out + le?vperm $out2,$out2,$out2,$inpperm + stvx_u $out1,$x10,$out + le?vperm $out3,$out3,$out3,$inpperm + stvx_u $out2,$x20,$out + stvx_u $out3,$x30,$out + addi $out,$out,0x40 + b Lctr32_enc8x_done + +.align 5 +Lctr32_enc8x_three: + vcipherlast $out0,$out0,$in5 + vcipherlast $out1,$out1,$in6 + vcipherlast $out2,$out2,$in7 + + le?vperm $out0,$out0,$out0,$inpperm + le?vperm $out1,$out1,$out1,$inpperm + stvx_u $out0,$x00,$out + le?vperm $out2,$out2,$out2,$inpperm + stvx_u $out1,$x10,$out + stvx_u $out2,$x20,$out + addi $out,$out,0x30 + b Lcbc_dec8x_done + +.align 5 +Lctr32_enc8x_two: + vcipherlast $out0,$out0,$in6 + vcipherlast $out1,$out1,$in7 + + le?vperm $out0,$out0,$out0,$inpperm + le?vperm $out1,$out1,$out1,$inpperm + stvx_u $out0,$x00,$out + stvx_u $out1,$x10,$out + addi $out,$out,0x20 + b Lcbc_dec8x_done + +.align 5 +Lctr32_enc8x_one: + vcipherlast $out0,$out0,$in7 + + le?vperm $out0,$out0,$out0,$inpperm + stvx_u $out0,0,$out + addi $out,$out,0x10 + +Lctr32_enc8x_done: + li r10,`$FRAME+15` + li r11,`$FRAME+31` + stvx $inpperm,r10,$sp # wipe copies of round keys + addi r10,r10,32 + stvx $inpperm,r11,$sp + addi r11,r11,32 + stvx $inpperm,r10,$sp + addi r10,r10,32 + stvx $inpperm,r11,$sp + addi r11,r11,32 + stvx $inpperm,r10,$sp + addi r10,r10,32 + stvx $inpperm,r11,$sp + addi r11,r11,32 + stvx $inpperm,r10,$sp + addi r10,r10,32 + stvx $inpperm,r11,$sp + addi r11,r11,32 + + mtspr 256,$vrsave + lvx v20,r10,$sp # ABI says so + addi r10,r10,32 + lvx v21,r11,$sp + addi r11,r11,32 + lvx v22,r10,$sp + addi r10,r10,32 + lvx v23,r11,$sp + addi r11,r11,32 + lvx v24,r10,$sp + addi r10,r10,32 + lvx v25,r11,$sp + addi r11,r11,32 + lvx v26,r10,$sp + addi r10,r10,32 + lvx v27,r11,$sp + addi r11,r11,32 + lvx v28,r10,$sp + addi r10,r10,32 + lvx v29,r11,$sp + addi r11,r11,32 + lvx v30,r10,$sp + lvx v31,r11,$sp + $POP r26,`$FRAME+21*16+0*$SIZE_T`($sp) + $POP r27,`$FRAME+21*16+1*$SIZE_T`($sp) + $POP r28,`$FRAME+21*16+2*$SIZE_T`($sp) + $POP r29,`$FRAME+21*16+3*$SIZE_T`($sp) + $POP r30,`$FRAME+21*16+4*$SIZE_T`($sp) + $POP r31,`$FRAME+21*16+5*$SIZE_T`($sp) + addi $sp,$sp,`$FRAME+21*16+6*$SIZE_T` + blr + .long 0 + .byte 0,12,0x04,0,0x80,6,6,0 + .long 0 +.size .${prefix}_ctr32_encrypt_blocks,.-.${prefix}_ctr32_encrypt_blocks +___ +}} }}} + +######################################################################### +{{{ # XTS procedures # +# int aes_p8_xts_[en|de]crypt(const char *inp, char *out, size_t len, # +# const AES_KEY *key1, const AES_KEY *key2, # +# [const] unsigned char iv[16]); # +# If $key2 is NULL, then a "tweak chaining" mode is engaged, in which # +# input tweak value is assumed to be encrypted already, and last tweak # +# value, one suitable for consecutive call on same chunk of data, is # +# written back to original buffer. In addition, in "tweak chaining" # +# mode only complete input blocks are processed. # + +my ($inp,$out,$len,$key1,$key2,$ivp,$rounds,$idx) = map("r$_",(3..10)); +my ($rndkey0,$rndkey1,$inout) = map("v$_",(0..2)); +my ($output,$inptail,$inpperm,$leperm,$keyperm) = map("v$_",(3..7)); +my ($tweak,$seven,$eighty7,$tmp,$tweak1) = map("v$_",(8..12)); +my $taillen = $key2; + + ($inp,$idx) = ($idx,$inp); # reassign + +$code.=<<___; +.globl .${prefix}_xts_encrypt +.align 5 +.${prefix}_xts_encrypt: + mr $inp,r3 # reassign + li r3,-1 + ${UCMP}i $len,16 + bltlr- + + lis r0,0xfff0 + mfspr r12,256 # save vrsave + li r11,0 + mtspr 256,r0 + + vspltisb $seven,0x07 # 0x070707..07 + le?lvsl $leperm,r11,r11 + le?vspltisb $tmp,0x0f + le?vxor $leperm,$leperm,$seven + + li $idx,15 + lvx $tweak,0,$ivp # load [unaligned] iv + lvsl $inpperm,0,$ivp + lvx $inptail,$idx,$ivp + le?vxor $inpperm,$inpperm,$tmp + vperm $tweak,$tweak,$inptail,$inpperm + + neg r11,$inp + lvsr $inpperm,0,r11 # prepare for unaligned load + lvx $inout,0,$inp + addi $inp,$inp,15 # 15 is not typo + le?vxor $inpperm,$inpperm,$tmp + + ${UCMP}i $key2,0 # key2==NULL? + beq Lxts_enc_no_key2 + + ?lvsl $keyperm,0,$key2 # prepare for unaligned key + lwz $rounds,240($key2) + srwi $rounds,$rounds,1 + subi $rounds,$rounds,1 + li $idx,16 + + lvx $rndkey0,0,$key2 + lvx $rndkey1,$idx,$key2 + addi $idx,$idx,16 + ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm + vxor $tweak,$tweak,$rndkey0 + lvx $rndkey0,$idx,$key2 + addi $idx,$idx,16 + mtctr $rounds + +Ltweak_xts_enc: + ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm + vcipher $tweak,$tweak,$rndkey1 + lvx $rndkey1,$idx,$key2 + addi $idx,$idx,16 + ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm + vcipher $tweak,$tweak,$rndkey0 + lvx $rndkey0,$idx,$key2 + addi $idx,$idx,16 + bdnz Ltweak_xts_enc + + ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm + vcipher $tweak,$tweak,$rndkey1 + lvx $rndkey1,$idx,$key2 + ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm + vcipherlast $tweak,$tweak,$rndkey0 + + li $ivp,0 # don't chain the tweak + b Lxts_enc + +Lxts_enc_no_key2: + li $idx,-16 + and $len,$len,$idx # in "tweak chaining" + # mode only complete + # blocks are processed +Lxts_enc: + lvx $inptail,0,$inp + addi $inp,$inp,16 + + ?lvsl $keyperm,0,$key1 # prepare for unaligned key + lwz $rounds,240($key1) + srwi $rounds,$rounds,1 + subi $rounds,$rounds,1 + li $idx,16 + + vslb $eighty7,$seven,$seven # 0x808080..80 + vor $eighty7,$eighty7,$seven # 0x878787..87 + vspltisb $tmp,1 # 0x010101..01 + vsldoi $eighty7,$eighty7,$tmp,15 # 0x870101..01 + + ${UCMP}i $len,96 + bge _aesp8_xts_encrypt6x + + andi. $taillen,$len,15 + subic r0,$len,32 + subi $taillen,$taillen,16 + subfe r0,r0,r0 + and r0,r0,$taillen + add $inp,$inp,r0 + + lvx $rndkey0,0,$key1 + lvx $rndkey1,$idx,$key1 + addi $idx,$idx,16 + vperm $inout,$inout,$inptail,$inpperm + ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm + vxor $inout,$inout,$tweak + vxor $inout,$inout,$rndkey0 + lvx $rndkey0,$idx,$key1 + addi $idx,$idx,16 + mtctr $rounds + b Loop_xts_enc + +.align 5 +Loop_xts_enc: + ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm + vcipher $inout,$inout,$rndkey1 + lvx $rndkey1,$idx,$key1 + addi $idx,$idx,16 + ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm + vcipher $inout,$inout,$rndkey0 + lvx $rndkey0,$idx,$key1 + addi $idx,$idx,16 + bdnz Loop_xts_enc + + ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm + vcipher $inout,$inout,$rndkey1 + lvx $rndkey1,$idx,$key1 + li $idx,16 + ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm + vxor $rndkey0,$rndkey0,$tweak + vcipherlast $output,$inout,$rndkey0 + + le?vperm $tmp,$output,$output,$leperm + be?nop + le?stvx_u $tmp,0,$out + be?stvx_u $output,0,$out + addi $out,$out,16 + + subic. $len,$len,16 + beq Lxts_enc_done + + vmr $inout,$inptail + lvx $inptail,0,$inp + addi $inp,$inp,16 + lvx $rndkey0,0,$key1 + lvx $rndkey1,$idx,$key1 + addi $idx,$idx,16 + + subic r0,$len,32 + subfe r0,r0,r0 + and r0,r0,$taillen + add $inp,$inp,r0 + + vsrab $tmp,$tweak,$seven # next tweak value + vaddubm $tweak,$tweak,$tweak + vsldoi $tmp,$tmp,$tmp,15 + vand $tmp,$tmp,$eighty7 + vxor $tweak,$tweak,$tmp + + vperm $inout,$inout,$inptail,$inpperm + ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm + vxor $inout,$inout,$tweak + vxor $output,$output,$rndkey0 # just in case $len<16 + vxor $inout,$inout,$rndkey0 + lvx $rndkey0,$idx,$key1 + addi $idx,$idx,16 + + mtctr $rounds + ${UCMP}i $len,16 + bge Loop_xts_enc + + vxor $output,$output,$tweak + lvsr $inpperm,0,$len # $inpperm is no longer needed + vxor $inptail,$inptail,$inptail # $inptail is no longer needed + vspltisb $tmp,-1 + vperm $inptail,$inptail,$tmp,$inpperm + vsel $inout,$inout,$output,$inptail + + subi r11,$out,17 + subi $out,$out,16 + mtctr $len + li $len,16 +Loop_xts_enc_steal: + lbzu r0,1(r11) + stb r0,16(r11) + bdnz Loop_xts_enc_steal + + mtctr $rounds + b Loop_xts_enc # one more time... + +Lxts_enc_done: + ${UCMP}i $ivp,0 + beq Lxts_enc_ret + + vsrab $tmp,$tweak,$seven # next tweak value + vaddubm $tweak,$tweak,$tweak + vsldoi $tmp,$tmp,$tmp,15 + vand $tmp,$tmp,$eighty7 + vxor $tweak,$tweak,$tmp + + le?vperm $tweak,$tweak,$tweak,$leperm + stvx_u $tweak,0,$ivp + +Lxts_enc_ret: + mtspr 256,r12 # restore vrsave + li r3,0 + blr + .long 0 + .byte 0,12,0x04,0,0x80,6,6,0 + .long 0 +.size .${prefix}_xts_encrypt,.-.${prefix}_xts_encrypt + +.globl .${prefix}_xts_decrypt +.align 5 +.${prefix}_xts_decrypt: + mr $inp,r3 # reassign + li r3,-1 + ${UCMP}i $len,16 + bltlr- + + lis r0,0xfff8 + mfspr r12,256 # save vrsave + li r11,0 + mtspr 256,r0 + + andi. r0,$len,15 + neg r0,r0 + andi. r0,r0,16 + sub $len,$len,r0 + + vspltisb $seven,0x07 # 0x070707..07 + le?lvsl $leperm,r11,r11 + le?vspltisb $tmp,0x0f + le?vxor $leperm,$leperm,$seven + + li $idx,15 + lvx $tweak,0,$ivp # load [unaligned] iv + lvsl $inpperm,0,$ivp + lvx $inptail,$idx,$ivp + le?vxor $inpperm,$inpperm,$tmp + vperm $tweak,$tweak,$inptail,$inpperm + + neg r11,$inp + lvsr $inpperm,0,r11 # prepare for unaligned load + lvx $inout,0,$inp + addi $inp,$inp,15 # 15 is not typo + le?vxor $inpperm,$inpperm,$tmp + + ${UCMP}i $key2,0 # key2==NULL? + beq Lxts_dec_no_key2 + + ?lvsl $keyperm,0,$key2 # prepare for unaligned key + lwz $rounds,240($key2) + srwi $rounds,$rounds,1 + subi $rounds,$rounds,1 + li $idx,16 + + lvx $rndkey0,0,$key2 + lvx $rndkey1,$idx,$key2 + addi $idx,$idx,16 + ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm + vxor $tweak,$tweak,$rndkey0 + lvx $rndkey0,$idx,$key2 + addi $idx,$idx,16 + mtctr $rounds + +Ltweak_xts_dec: + ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm + vcipher $tweak,$tweak,$rndkey1 + lvx $rndkey1,$idx,$key2 + addi $idx,$idx,16 + ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm + vcipher $tweak,$tweak,$rndkey0 + lvx $rndkey0,$idx,$key2 + addi $idx,$idx,16 + bdnz Ltweak_xts_dec + + ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm + vcipher $tweak,$tweak,$rndkey1 + lvx $rndkey1,$idx,$key2 + ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm + vcipherlast $tweak,$tweak,$rndkey0 + + li $ivp,0 # don't chain the tweak + b Lxts_dec + +Lxts_dec_no_key2: + neg $idx,$len + andi. $idx,$idx,15 + add $len,$len,$idx # in "tweak chaining" + # mode only complete + # blocks are processed +Lxts_dec: + lvx $inptail,0,$inp + addi $inp,$inp,16 + + ?lvsl $keyperm,0,$key1 # prepare for unaligned key + lwz $rounds,240($key1) + srwi $rounds,$rounds,1 + subi $rounds,$rounds,1 + li $idx,16 + + vslb $eighty7,$seven,$seven # 0x808080..80 + vor $eighty7,$eighty7,$seven # 0x878787..87 + vspltisb $tmp,1 # 0x010101..01 + vsldoi $eighty7,$eighty7,$tmp,15 # 0x870101..01 + + ${UCMP}i $len,96 + bge _aesp8_xts_decrypt6x + + lvx $rndkey0,0,$key1 + lvx $rndkey1,$idx,$key1 + addi $idx,$idx,16 + vperm $inout,$inout,$inptail,$inpperm + ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm + vxor $inout,$inout,$tweak + vxor $inout,$inout,$rndkey0 + lvx $rndkey0,$idx,$key1 + addi $idx,$idx,16 + mtctr $rounds + + ${UCMP}i $len,16 + blt Ltail_xts_dec + be?b Loop_xts_dec + +.align 5 +Loop_xts_dec: + ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm + vncipher $inout,$inout,$rndkey1 + lvx $rndkey1,$idx,$key1 + addi $idx,$idx,16 + ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm + vncipher $inout,$inout,$rndkey0 + lvx $rndkey0,$idx,$key1 + addi $idx,$idx,16 + bdnz Loop_xts_dec + + ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm + vncipher $inout,$inout,$rndkey1 + lvx $rndkey1,$idx,$key1 + li $idx,16 + ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm + vxor $rndkey0,$rndkey0,$tweak + vncipherlast $output,$inout,$rndkey0 + + le?vperm $tmp,$output,$output,$leperm + be?nop + le?stvx_u $tmp,0,$out + be?stvx_u $output,0,$out + addi $out,$out,16 + + subic. $len,$len,16 + beq Lxts_dec_done + + vmr $inout,$inptail + lvx $inptail,0,$inp + addi $inp,$inp,16 + lvx $rndkey0,0,$key1 + lvx $rndkey1,$idx,$key1 + addi $idx,$idx,16 + + vsrab $tmp,$tweak,$seven # next tweak value + vaddubm $tweak,$tweak,$tweak + vsldoi $tmp,$tmp,$tmp,15 + vand $tmp,$tmp,$eighty7 + vxor $tweak,$tweak,$tmp + + vperm $inout,$inout,$inptail,$inpperm + ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm + vxor $inout,$inout,$tweak + vxor $inout,$inout,$rndkey0 + lvx $rndkey0,$idx,$key1 + addi $idx,$idx,16 + + mtctr $rounds + ${UCMP}i $len,16 + bge Loop_xts_dec + +Ltail_xts_dec: + vsrab $tmp,$tweak,$seven # next tweak value + vaddubm $tweak1,$tweak,$tweak + vsldoi $tmp,$tmp,$tmp,15 + vand $tmp,$tmp,$eighty7 + vxor $tweak1,$tweak1,$tmp + + subi $inp,$inp,16 + add $inp,$inp,$len + + vxor $inout,$inout,$tweak # :-( + vxor $inout,$inout,$tweak1 # :-) + +Loop_xts_dec_short: + ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm + vncipher $inout,$inout,$rndkey1 + lvx $rndkey1,$idx,$key1 + addi $idx,$idx,16 + ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm + vncipher $inout,$inout,$rndkey0 + lvx $rndkey0,$idx,$key1 + addi $idx,$idx,16 + bdnz Loop_xts_dec_short + + ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm + vncipher $inout,$inout,$rndkey1 + lvx $rndkey1,$idx,$key1 + li $idx,16 + ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm + vxor $rndkey0,$rndkey0,$tweak1 + vncipherlast $output,$inout,$rndkey0 + + le?vperm $tmp,$output,$output,$leperm + be?nop + le?stvx_u $tmp,0,$out + be?stvx_u $output,0,$out + + vmr $inout,$inptail + lvx $inptail,0,$inp + #addi $inp,$inp,16 + lvx $rndkey0,0,$key1 + lvx $rndkey1,$idx,$key1 + addi $idx,$idx,16 + vperm $inout,$inout,$inptail,$inpperm + ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm + + lvsr $inpperm,0,$len # $inpperm is no longer needed + vxor $inptail,$inptail,$inptail # $inptail is no longer needed + vspltisb $tmp,-1 + vperm $inptail,$inptail,$tmp,$inpperm + vsel $inout,$inout,$output,$inptail + + vxor $rndkey0,$rndkey0,$tweak + vxor $inout,$inout,$rndkey0 + lvx $rndkey0,$idx,$key1 + addi $idx,$idx,16 + + subi r11,$out,1 + mtctr $len + li $len,16 +Loop_xts_dec_steal: + lbzu r0,1(r11) + stb r0,16(r11) + bdnz Loop_xts_dec_steal + + mtctr $rounds + b Loop_xts_dec # one more time... + +Lxts_dec_done: + ${UCMP}i $ivp,0 + beq Lxts_dec_ret + + vsrab $tmp,$tweak,$seven # next tweak value + vaddubm $tweak,$tweak,$tweak + vsldoi $tmp,$tmp,$tmp,15 + vand $tmp,$tmp,$eighty7 + vxor $tweak,$tweak,$tmp + + le?vperm $tweak,$tweak,$tweak,$leperm + stvx_u $tweak,0,$ivp + +Lxts_dec_ret: + mtspr 256,r12 # restore vrsave + li r3,0 + blr + .long 0 + .byte 0,12,0x04,0,0x80,6,6,0 + .long 0 +.size .${prefix}_xts_decrypt,.-.${prefix}_xts_decrypt +___ +######################################################################### +{{ # Optimized XTS procedures # +my $key_=$key2; +my ($x00,$x10,$x20,$x30,$x40,$x50,$x60,$x70)=map("r$_",(0,3,26..31)); + $x00=0 if ($flavour =~ /osx/); +my ($in0, $in1, $in2, $in3, $in4, $in5 )=map("v$_",(0..5)); +my ($out0, $out1, $out2, $out3, $out4, $out5)=map("v$_",(7,12..16)); +my ($twk0, $twk1, $twk2, $twk3, $twk4, $twk5)=map("v$_",(17..22)); +my $rndkey0="v23"; # v24-v25 rotating buffer for first found keys + # v26-v31 last 6 round keys +my ($keyperm)=($out0); # aliases with "caller", redundant assignment +my $taillen=$x70; + +$code.=<<___; +.align 5 +_aesp8_xts_encrypt6x: + $STU $sp,-`($FRAME+21*16+6*$SIZE_T)`($sp) + mflr r11 + li r7,`$FRAME+8*16+15` + li r3,`$FRAME+8*16+31` + $PUSH r11,`$FRAME+21*16+6*$SIZE_T+$LRSAVE`($sp) + stvx v20,r7,$sp # ABI says so + addi r7,r7,32 + stvx v21,r3,$sp + addi r3,r3,32 + stvx v22,r7,$sp + addi r7,r7,32 + stvx v23,r3,$sp + addi r3,r3,32 + stvx v24,r7,$sp + addi r7,r7,32 + stvx v25,r3,$sp + addi r3,r3,32 + stvx v26,r7,$sp + addi r7,r7,32 + stvx v27,r3,$sp + addi r3,r3,32 + stvx v28,r7,$sp + addi r7,r7,32 + stvx v29,r3,$sp + addi r3,r3,32 + stvx v30,r7,$sp + stvx v31,r3,$sp + li r0,-1 + stw $vrsave,`$FRAME+21*16-4`($sp) # save vrsave + li $x10,0x10 + $PUSH r26,`$FRAME+21*16+0*$SIZE_T`($sp) + li $x20,0x20 + $PUSH r27,`$FRAME+21*16+1*$SIZE_T`($sp) + li $x30,0x30 + $PUSH r28,`$FRAME+21*16+2*$SIZE_T`($sp) + li $x40,0x40 + $PUSH r29,`$FRAME+21*16+3*$SIZE_T`($sp) + li $x50,0x50 + $PUSH r30,`$FRAME+21*16+4*$SIZE_T`($sp) + li $x60,0x60 + $PUSH r31,`$FRAME+21*16+5*$SIZE_T`($sp) + li $x70,0x70 + mtspr 256,r0 + + subi $rounds,$rounds,3 # -4 in total + + lvx $rndkey0,$x00,$key1 # load key schedule + lvx v30,$x10,$key1 + addi $key1,$key1,0x20 + lvx v31,$x00,$key1 + ?vperm $rndkey0,$rndkey0,v30,$keyperm + addi $key_,$sp,$FRAME+15 + mtctr $rounds + +Load_xts_enc_key: + ?vperm v24,v30,v31,$keyperm + lvx v30,$x10,$key1 + addi $key1,$key1,0x20 + stvx v24,$x00,$key_ # off-load round[1] + ?vperm v25,v31,v30,$keyperm + lvx v31,$x00,$key1 + stvx v25,$x10,$key_ # off-load round[2] + addi $key_,$key_,0x20 + bdnz Load_xts_enc_key + + lvx v26,$x10,$key1 + ?vperm v24,v30,v31,$keyperm + lvx v27,$x20,$key1 + stvx v24,$x00,$key_ # off-load round[3] + ?vperm v25,v31,v26,$keyperm + lvx v28,$x30,$key1 + stvx v25,$x10,$key_ # off-load round[4] + addi $key_,$sp,$FRAME+15 # rewind $key_ + ?vperm v26,v26,v27,$keyperm + lvx v29,$x40,$key1 + ?vperm v27,v27,v28,$keyperm + lvx v30,$x50,$key1 + ?vperm v28,v28,v29,$keyperm + lvx v31,$x60,$key1 + ?vperm v29,v29,v30,$keyperm + lvx $twk5,$x70,$key1 # borrow $twk5 + ?vperm v30,v30,v31,$keyperm + lvx v24,$x00,$key_ # pre-load round[1] + ?vperm v31,v31,$twk5,$keyperm + lvx v25,$x10,$key_ # pre-load round[2] + + vperm $in0,$inout,$inptail,$inpperm + subi $inp,$inp,31 # undo "caller" + vxor $twk0,$tweak,$rndkey0 + vsrab $tmp,$tweak,$seven # next tweak value + vaddubm $tweak,$tweak,$tweak + vsldoi $tmp,$tmp,$tmp,15 + vand $tmp,$tmp,$eighty7 + vxor $out0,$in0,$twk0 + vxor $tweak,$tweak,$tmp + + lvx_u $in1,$x10,$inp + vxor $twk1,$tweak,$rndkey0 + vsrab $tmp,$tweak,$seven # next tweak value + vaddubm $tweak,$tweak,$tweak + vsldoi $tmp,$tmp,$tmp,15 + le?vperm $in1,$in1,$in1,$leperm + vand $tmp,$tmp,$eighty7 + vxor $out1,$in1,$twk1 + vxor $tweak,$tweak,$tmp + + lvx_u $in2,$x20,$inp + andi. $taillen,$len,15 + vxor $twk2,$tweak,$rndkey0 + vsrab $tmp,$tweak,$seven # next tweak value + vaddubm $tweak,$tweak,$tweak + vsldoi $tmp,$tmp,$tmp,15 + le?vperm $in2,$in2,$in2,$leperm + vand $tmp,$tmp,$eighty7 + vxor $out2,$in2,$twk2 + vxor $tweak,$tweak,$tmp + + lvx_u $in3,$x30,$inp + sub $len,$len,$taillen + vxor $twk3,$tweak,$rndkey0 + vsrab $tmp,$tweak,$seven # next tweak value + vaddubm $tweak,$tweak,$tweak + vsldoi $tmp,$tmp,$tmp,15 + le?vperm $in3,$in3,$in3,$leperm + vand $tmp,$tmp,$eighty7 + vxor $out3,$in3,$twk3 + vxor $tweak,$tweak,$tmp + + lvx_u $in4,$x40,$inp + subi $len,$len,0x60 + vxor $twk4,$tweak,$rndkey0 + vsrab $tmp,$tweak,$seven # next tweak value + vaddubm $tweak,$tweak,$tweak + vsldoi $tmp,$tmp,$tmp,15 + le?vperm $in4,$in4,$in4,$leperm + vand $tmp,$tmp,$eighty7 + vxor $out4,$in4,$twk4 + vxor $tweak,$tweak,$tmp + + lvx_u $in5,$x50,$inp + addi $inp,$inp,0x60 + vxor $twk5,$tweak,$rndkey0 + vsrab $tmp,$tweak,$seven # next tweak value + vaddubm $tweak,$tweak,$tweak + vsldoi $tmp,$tmp,$tmp,15 + le?vperm $in5,$in5,$in5,$leperm + vand $tmp,$tmp,$eighty7 + vxor $out5,$in5,$twk5 + vxor $tweak,$tweak,$tmp + + vxor v31,v31,$rndkey0 + mtctr $rounds + b Loop_xts_enc6x + +.align 5 +Loop_xts_enc6x: + vcipher $out0,$out0,v24 + vcipher $out1,$out1,v24 + vcipher $out2,$out2,v24 + vcipher $out3,$out3,v24 + vcipher $out4,$out4,v24 + vcipher $out5,$out5,v24 + lvx v24,$x20,$key_ # round[3] + addi $key_,$key_,0x20 + + vcipher $out0,$out0,v25 + vcipher $out1,$out1,v25 + vcipher $out2,$out2,v25 + vcipher $out3,$out3,v25 + vcipher $out4,$out4,v25 + vcipher $out5,$out5,v25 + lvx v25,$x10,$key_ # round[4] + bdnz Loop_xts_enc6x + + subic $len,$len,96 # $len-=96 + vxor $in0,$twk0,v31 # xor with last round key + vcipher $out0,$out0,v24 + vcipher $out1,$out1,v24 + vsrab $tmp,$tweak,$seven # next tweak value + vxor $twk0,$tweak,$rndkey0 + vaddubm $tweak,$tweak,$tweak + vcipher $out2,$out2,v24 + vcipher $out3,$out3,v24 + vsldoi $tmp,$tmp,$tmp,15 + vcipher $out4,$out4,v24 + vcipher $out5,$out5,v24 + + subfe. r0,r0,r0 # borrow?-1:0 + vand $tmp,$tmp,$eighty7 + vcipher $out0,$out0,v25 + vcipher $out1,$out1,v25 + vxor $tweak,$tweak,$tmp + vcipher $out2,$out2,v25 + vcipher $out3,$out3,v25 + vxor $in1,$twk1,v31 + vsrab $tmp,$tweak,$seven # next tweak value + vxor $twk1,$tweak,$rndkey0 + vcipher $out4,$out4,v25 + vcipher $out5,$out5,v25 + + and r0,r0,$len + vaddubm $tweak,$tweak,$tweak + vsldoi $tmp,$tmp,$tmp,15 + vcipher $out0,$out0,v26 + vcipher $out1,$out1,v26 + vand $tmp,$tmp,$eighty7 + vcipher $out2,$out2,v26 + vcipher $out3,$out3,v26 + vxor $tweak,$tweak,$tmp + vcipher $out4,$out4,v26 + vcipher $out5,$out5,v26 + + add $inp,$inp,r0 # $inp is adjusted in such + # way that at exit from the + # loop inX-in5 are loaded + # with last "words" + vxor $in2,$twk2,v31 + vsrab $tmp,$tweak,$seven # next tweak value + vxor $twk2,$tweak,$rndkey0 + vaddubm $tweak,$tweak,$tweak + vcipher $out0,$out0,v27 + vcipher $out1,$out1,v27 + vsldoi $tmp,$tmp,$tmp,15 + vcipher $out2,$out2,v27 + vcipher $out3,$out3,v27 + vand $tmp,$tmp,$eighty7 + vcipher $out4,$out4,v27 + vcipher $out5,$out5,v27 + + addi $key_,$sp,$FRAME+15 # rewind $key_ + vxor $tweak,$tweak,$tmp + vcipher $out0,$out0,v28 + vcipher $out1,$out1,v28 + vxor $in3,$twk3,v31 + vsrab $tmp,$tweak,$seven # next tweak value + vxor $twk3,$tweak,$rndkey0 + vcipher $out2,$out2,v28 + vcipher $out3,$out3,v28 + vaddubm $tweak,$tweak,$tweak + vsldoi $tmp,$tmp,$tmp,15 + vcipher $out4,$out4,v28 + vcipher $out5,$out5,v28 + lvx v24,$x00,$key_ # re-pre-load round[1] + vand $tmp,$tmp,$eighty7 + + vcipher $out0,$out0,v29 + vcipher $out1,$out1,v29 + vxor $tweak,$tweak,$tmp + vcipher $out2,$out2,v29 + vcipher $out3,$out3,v29 + vxor $in4,$twk4,v31 + vsrab $tmp,$tweak,$seven # next tweak value + vxor $twk4,$tweak,$rndkey0 + vcipher $out4,$out4,v29 + vcipher $out5,$out5,v29 + lvx v25,$x10,$key_ # re-pre-load round[2] + vaddubm $tweak,$tweak,$tweak + vsldoi $tmp,$tmp,$tmp,15 + + vcipher $out0,$out0,v30 + vcipher $out1,$out1,v30 + vand $tmp,$tmp,$eighty7 + vcipher $out2,$out2,v30 + vcipher $out3,$out3,v30 + vxor $tweak,$tweak,$tmp + vcipher $out4,$out4,v30 + vcipher $out5,$out5,v30 + vxor $in5,$twk5,v31 + vsrab $tmp,$tweak,$seven # next tweak value + vxor $twk5,$tweak,$rndkey0 + + vcipherlast $out0,$out0,$in0 + lvx_u $in0,$x00,$inp # load next input block + vaddubm $tweak,$tweak,$tweak + vsldoi $tmp,$tmp,$tmp,15 + vcipherlast $out1,$out1,$in1 + lvx_u $in1,$x10,$inp + vcipherlast $out2,$out2,$in2 + le?vperm $in0,$in0,$in0,$leperm + lvx_u $in2,$x20,$inp + vand $tmp,$tmp,$eighty7 + vcipherlast $out3,$out3,$in3 + le?vperm $in1,$in1,$in1,$leperm + lvx_u $in3,$x30,$inp + vcipherlast $out4,$out4,$in4 + le?vperm $in2,$in2,$in2,$leperm + lvx_u $in4,$x40,$inp + vxor $tweak,$tweak,$tmp + vcipherlast $tmp,$out5,$in5 # last block might be needed + # in stealing mode + le?vperm $in3,$in3,$in3,$leperm + lvx_u $in5,$x50,$inp + addi $inp,$inp,0x60 + le?vperm $in4,$in4,$in4,$leperm + le?vperm $in5,$in5,$in5,$leperm + + le?vperm $out0,$out0,$out0,$leperm + le?vperm $out1,$out1,$out1,$leperm + stvx_u $out0,$x00,$out # store output + vxor $out0,$in0,$twk0 + le?vperm $out2,$out2,$out2,$leperm + stvx_u $out1,$x10,$out + vxor $out1,$in1,$twk1 + le?vperm $out3,$out3,$out3,$leperm + stvx_u $out2,$x20,$out + vxor $out2,$in2,$twk2 + le?vperm $out4,$out4,$out4,$leperm + stvx_u $out3,$x30,$out + vxor $out3,$in3,$twk3 + le?vperm $out5,$tmp,$tmp,$leperm + stvx_u $out4,$x40,$out + vxor $out4,$in4,$twk4 + le?stvx_u $out5,$x50,$out + be?stvx_u $tmp, $x50,$out + vxor $out5,$in5,$twk5 + addi $out,$out,0x60 + + mtctr $rounds + beq Loop_xts_enc6x # did $len-=96 borrow? + + addic. $len,$len,0x60 + beq Lxts_enc6x_zero + cmpwi $len,0x20 + blt Lxts_enc6x_one + nop + beq Lxts_enc6x_two + cmpwi $len,0x40 + blt Lxts_enc6x_three + nop + beq Lxts_enc6x_four + +Lxts_enc6x_five: + vxor $out0,$in1,$twk0 + vxor $out1,$in2,$twk1 + vxor $out2,$in3,$twk2 + vxor $out3,$in4,$twk3 + vxor $out4,$in5,$twk4 + + bl _aesp8_xts_enc5x + + le?vperm $out0,$out0,$out0,$leperm + vmr $twk0,$twk5 # unused tweak + le?vperm $out1,$out1,$out1,$leperm + stvx_u $out0,$x00,$out # store output + le?vperm $out2,$out2,$out2,$leperm + stvx_u $out1,$x10,$out + le?vperm $out3,$out3,$out3,$leperm + stvx_u $out2,$x20,$out + vxor $tmp,$out4,$twk5 # last block prep for stealing + le?vperm $out4,$out4,$out4,$leperm + stvx_u $out3,$x30,$out + stvx_u $out4,$x40,$out + addi $out,$out,0x50 + bne Lxts_enc6x_steal + b Lxts_enc6x_done + +.align 4 +Lxts_enc6x_four: + vxor $out0,$in2,$twk0 + vxor $out1,$in3,$twk1 + vxor $out2,$in4,$twk2 + vxor $out3,$in5,$twk3 + vxor $out4,$out4,$out4 + + bl _aesp8_xts_enc5x + + le?vperm $out0,$out0,$out0,$leperm + vmr $twk0,$twk4 # unused tweak + le?vperm $out1,$out1,$out1,$leperm + stvx_u $out0,$x00,$out # store output + le?vperm $out2,$out2,$out2,$leperm + stvx_u $out1,$x10,$out + vxor $tmp,$out3,$twk4 # last block prep for stealing + le?vperm $out3,$out3,$out3,$leperm + stvx_u $out2,$x20,$out + stvx_u $out3,$x30,$out + addi $out,$out,0x40 + bne Lxts_enc6x_steal + b Lxts_enc6x_done + +.align 4 +Lxts_enc6x_three: + vxor $out0,$in3,$twk0 + vxor $out1,$in4,$twk1 + vxor $out2,$in5,$twk2 + vxor $out3,$out3,$out3 + vxor $out4,$out4,$out4 + + bl _aesp8_xts_enc5x + + le?vperm $out0,$out0,$out0,$leperm + vmr $twk0,$twk3 # unused tweak + le?vperm $out1,$out1,$out1,$leperm + stvx_u $out0,$x00,$out # store output + vxor $tmp,$out2,$twk3 # last block prep for stealing + le?vperm $out2,$out2,$out2,$leperm + stvx_u $out1,$x10,$out + stvx_u $out2,$x20,$out + addi $out,$out,0x30 + bne Lxts_enc6x_steal + b Lxts_enc6x_done + +.align 4 +Lxts_enc6x_two: + vxor $out0,$in4,$twk0 + vxor $out1,$in5,$twk1 + vxor $out2,$out2,$out2 + vxor $out3,$out3,$out3 + vxor $out4,$out4,$out4 + + bl _aesp8_xts_enc5x + + le?vperm $out0,$out0,$out0,$leperm + vmr $twk0,$twk2 # unused tweak + vxor $tmp,$out1,$twk2 # last block prep for stealing + le?vperm $out1,$out1,$out1,$leperm + stvx_u $out0,$x00,$out # store output + stvx_u $out1,$x10,$out + addi $out,$out,0x20 + bne Lxts_enc6x_steal + b Lxts_enc6x_done + +.align 4 +Lxts_enc6x_one: + vxor $out0,$in5,$twk0 + nop +Loop_xts_enc1x: + vcipher $out0,$out0,v24 + lvx v24,$x20,$key_ # round[3] + addi $key_,$key_,0x20 + + vcipher $out0,$out0,v25 + lvx v25,$x10,$key_ # round[4] + bdnz Loop_xts_enc1x + + add $inp,$inp,$taillen + cmpwi $taillen,0 + vcipher $out0,$out0,v24 + + subi $inp,$inp,16 + vcipher $out0,$out0,v25 + + lvsr $inpperm,0,$taillen + vcipher $out0,$out0,v26 + + lvx_u $in0,0,$inp + vcipher $out0,$out0,v27 + + addi $key_,$sp,$FRAME+15 # rewind $key_ + vcipher $out0,$out0,v28 + lvx v24,$x00,$key_ # re-pre-load round[1] + + vcipher $out0,$out0,v29 + lvx v25,$x10,$key_ # re-pre-load round[2] + vxor $twk0,$twk0,v31 + + le?vperm $in0,$in0,$in0,$leperm + vcipher $out0,$out0,v30 + + vperm $in0,$in0,$in0,$inpperm + vcipherlast $out0,$out0,$twk0 + + vmr $twk0,$twk1 # unused tweak + vxor $tmp,$out0,$twk1 # last block prep for stealing + le?vperm $out0,$out0,$out0,$leperm + stvx_u $out0,$x00,$out # store output + addi $out,$out,0x10 + bne Lxts_enc6x_steal + b Lxts_enc6x_done + +.align 4 +Lxts_enc6x_zero: + cmpwi $taillen,0 + beq Lxts_enc6x_done + + add $inp,$inp,$taillen + subi $inp,$inp,16 + lvx_u $in0,0,$inp + lvsr $inpperm,0,$taillen # $in5 is no more + le?vperm $in0,$in0,$in0,$leperm + vperm $in0,$in0,$in0,$inpperm + vxor $tmp,$tmp,$twk0 +Lxts_enc6x_steal: + vxor $in0,$in0,$twk0 + vxor $out0,$out0,$out0 + vspltisb $out1,-1 + vperm $out0,$out0,$out1,$inpperm + vsel $out0,$in0,$tmp,$out0 # $tmp is last block, remember? + + subi r30,$out,17 + subi $out,$out,16 + mtctr $taillen +Loop_xts_enc6x_steal: + lbzu r0,1(r30) + stb r0,16(r30) + bdnz Loop_xts_enc6x_steal + + li $taillen,0 + mtctr $rounds + b Loop_xts_enc1x # one more time... + +.align 4 +Lxts_enc6x_done: + ${UCMP}i $ivp,0 + beq Lxts_enc6x_ret + + vxor $tweak,$twk0,$rndkey0 + le?vperm $tweak,$tweak,$tweak,$leperm + stvx_u $tweak,0,$ivp + +Lxts_enc6x_ret: + mtlr r11 + li r10,`$FRAME+15` + li r11,`$FRAME+31` + stvx $seven,r10,$sp # wipe copies of round keys + addi r10,r10,32 + stvx $seven,r11,$sp + addi r11,r11,32 + stvx $seven,r10,$sp + addi r10,r10,32 + stvx $seven,r11,$sp + addi r11,r11,32 + stvx $seven,r10,$sp + addi r10,r10,32 + stvx $seven,r11,$sp + addi r11,r11,32 + stvx $seven,r10,$sp + addi r10,r10,32 + stvx $seven,r11,$sp + addi r11,r11,32 + + mtspr 256,$vrsave + lvx v20,r10,$sp # ABI says so + addi r10,r10,32 + lvx v21,r11,$sp + addi r11,r11,32 + lvx v22,r10,$sp + addi r10,r10,32 + lvx v23,r11,$sp + addi r11,r11,32 + lvx v24,r10,$sp + addi r10,r10,32 + lvx v25,r11,$sp + addi r11,r11,32 + lvx v26,r10,$sp + addi r10,r10,32 + lvx v27,r11,$sp + addi r11,r11,32 + lvx v28,r10,$sp + addi r10,r10,32 + lvx v29,r11,$sp + addi r11,r11,32 + lvx v30,r10,$sp + lvx v31,r11,$sp + $POP r26,`$FRAME+21*16+0*$SIZE_T`($sp) + $POP r27,`$FRAME+21*16+1*$SIZE_T`($sp) + $POP r28,`$FRAME+21*16+2*$SIZE_T`($sp) + $POP r29,`$FRAME+21*16+3*$SIZE_T`($sp) + $POP r30,`$FRAME+21*16+4*$SIZE_T`($sp) + $POP r31,`$FRAME+21*16+5*$SIZE_T`($sp) + addi $sp,$sp,`$FRAME+21*16+6*$SIZE_T` + blr + .long 0 + .byte 0,12,0x04,1,0x80,6,6,0 + .long 0 + +.align 5 +_aesp8_xts_enc5x: + vcipher $out0,$out0,v24 + vcipher $out1,$out1,v24 + vcipher $out2,$out2,v24 + vcipher $out3,$out3,v24 + vcipher $out4,$out4,v24 + lvx v24,$x20,$key_ # round[3] + addi $key_,$key_,0x20 + + vcipher $out0,$out0,v25 + vcipher $out1,$out1,v25 + vcipher $out2,$out2,v25 + vcipher $out3,$out3,v25 + vcipher $out4,$out4,v25 + lvx v25,$x10,$key_ # round[4] + bdnz _aesp8_xts_enc5x + + add $inp,$inp,$taillen + cmpwi $taillen,0 + vcipher $out0,$out0,v24 + vcipher $out1,$out1,v24 + vcipher $out2,$out2,v24 + vcipher $out3,$out3,v24 + vcipher $out4,$out4,v24 + + subi $inp,$inp,16 + vcipher $out0,$out0,v25 + vcipher $out1,$out1,v25 + vcipher $out2,$out2,v25 + vcipher $out3,$out3,v25 + vcipher $out4,$out4,v25 + vxor $twk0,$twk0,v31 + + vcipher $out0,$out0,v26 + lvsr $inpperm,0,$taillen # $in5 is no more + vcipher $out1,$out1,v26 + vcipher $out2,$out2,v26 + vcipher $out3,$out3,v26 + vcipher $out4,$out4,v26 + vxor $in1,$twk1,v31 + + vcipher $out0,$out0,v27 + lvx_u $in0,0,$inp + vcipher $out1,$out1,v27 + vcipher $out2,$out2,v27 + vcipher $out3,$out3,v27 + vcipher $out4,$out4,v27 + vxor $in2,$twk2,v31 + + addi $key_,$sp,$FRAME+15 # rewind $key_ + vcipher $out0,$out0,v28 + vcipher $out1,$out1,v28 + vcipher $out2,$out2,v28 + vcipher $out3,$out3,v28 + vcipher $out4,$out4,v28 + lvx v24,$x00,$key_ # re-pre-load round[1] + vxor $in3,$twk3,v31 + + vcipher $out0,$out0,v29 + le?vperm $in0,$in0,$in0,$leperm + vcipher $out1,$out1,v29 + vcipher $out2,$out2,v29 + vcipher $out3,$out3,v29 + vcipher $out4,$out4,v29 + lvx v25,$x10,$key_ # re-pre-load round[2] + vxor $in4,$twk4,v31 + + vcipher $out0,$out0,v30 + vperm $in0,$in0,$in0,$inpperm + vcipher $out1,$out1,v30 + vcipher $out2,$out2,v30 + vcipher $out3,$out3,v30 + vcipher $out4,$out4,v30 + + vcipherlast $out0,$out0,$twk0 + vcipherlast $out1,$out1,$in1 + vcipherlast $out2,$out2,$in2 + vcipherlast $out3,$out3,$in3 + vcipherlast $out4,$out4,$in4 + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 + +.align 5 +_aesp8_xts_decrypt6x: + $STU $sp,-`($FRAME+21*16+6*$SIZE_T)`($sp) + mflr r11 + li r7,`$FRAME+8*16+15` + li r3,`$FRAME+8*16+31` + $PUSH r11,`$FRAME+21*16+6*$SIZE_T+$LRSAVE`($sp) + stvx v20,r7,$sp # ABI says so + addi r7,r7,32 + stvx v21,r3,$sp + addi r3,r3,32 + stvx v22,r7,$sp + addi r7,r7,32 + stvx v23,r3,$sp + addi r3,r3,32 + stvx v24,r7,$sp + addi r7,r7,32 + stvx v25,r3,$sp + addi r3,r3,32 + stvx v26,r7,$sp + addi r7,r7,32 + stvx v27,r3,$sp + addi r3,r3,32 + stvx v28,r7,$sp + addi r7,r7,32 + stvx v29,r3,$sp + addi r3,r3,32 + stvx v30,r7,$sp + stvx v31,r3,$sp + li r0,-1 + stw $vrsave,`$FRAME+21*16-4`($sp) # save vrsave + li $x10,0x10 + $PUSH r26,`$FRAME+21*16+0*$SIZE_T`($sp) + li $x20,0x20 + $PUSH r27,`$FRAME+21*16+1*$SIZE_T`($sp) + li $x30,0x30 + $PUSH r28,`$FRAME+21*16+2*$SIZE_T`($sp) + li $x40,0x40 + $PUSH r29,`$FRAME+21*16+3*$SIZE_T`($sp) + li $x50,0x50 + $PUSH r30,`$FRAME+21*16+4*$SIZE_T`($sp) + li $x60,0x60 + $PUSH r31,`$FRAME+21*16+5*$SIZE_T`($sp) + li $x70,0x70 + mtspr 256,r0 + + subi $rounds,$rounds,3 # -4 in total + + lvx $rndkey0,$x00,$key1 # load key schedule + lvx v30,$x10,$key1 + addi $key1,$key1,0x20 + lvx v31,$x00,$key1 + ?vperm $rndkey0,$rndkey0,v30,$keyperm + addi $key_,$sp,$FRAME+15 + mtctr $rounds + +Load_xts_dec_key: + ?vperm v24,v30,v31,$keyperm + lvx v30,$x10,$key1 + addi $key1,$key1,0x20 + stvx v24,$x00,$key_ # off-load round[1] + ?vperm v25,v31,v30,$keyperm + lvx v31,$x00,$key1 + stvx v25,$x10,$key_ # off-load round[2] + addi $key_,$key_,0x20 + bdnz Load_xts_dec_key + + lvx v26,$x10,$key1 + ?vperm v24,v30,v31,$keyperm + lvx v27,$x20,$key1 + stvx v24,$x00,$key_ # off-load round[3] + ?vperm v25,v31,v26,$keyperm + lvx v28,$x30,$key1 + stvx v25,$x10,$key_ # off-load round[4] + addi $key_,$sp,$FRAME+15 # rewind $key_ + ?vperm v26,v26,v27,$keyperm + lvx v29,$x40,$key1 + ?vperm v27,v27,v28,$keyperm + lvx v30,$x50,$key1 + ?vperm v28,v28,v29,$keyperm + lvx v31,$x60,$key1 + ?vperm v29,v29,v30,$keyperm + lvx $twk5,$x70,$key1 # borrow $twk5 + ?vperm v30,v30,v31,$keyperm + lvx v24,$x00,$key_ # pre-load round[1] + ?vperm v31,v31,$twk5,$keyperm + lvx v25,$x10,$key_ # pre-load round[2] + + vperm $in0,$inout,$inptail,$inpperm + subi $inp,$inp,31 # undo "caller" + vxor $twk0,$tweak,$rndkey0 + vsrab $tmp,$tweak,$seven # next tweak value + vaddubm $tweak,$tweak,$tweak + vsldoi $tmp,$tmp,$tmp,15 + vand $tmp,$tmp,$eighty7 + vxor $out0,$in0,$twk0 + vxor $tweak,$tweak,$tmp + + lvx_u $in1,$x10,$inp + vxor $twk1,$tweak,$rndkey0 + vsrab $tmp,$tweak,$seven # next tweak value + vaddubm $tweak,$tweak,$tweak + vsldoi $tmp,$tmp,$tmp,15 + le?vperm $in1,$in1,$in1,$leperm + vand $tmp,$tmp,$eighty7 + vxor $out1,$in1,$twk1 + vxor $tweak,$tweak,$tmp + + lvx_u $in2,$x20,$inp + andi. $taillen,$len,15 + vxor $twk2,$tweak,$rndkey0 + vsrab $tmp,$tweak,$seven # next tweak value + vaddubm $tweak,$tweak,$tweak + vsldoi $tmp,$tmp,$tmp,15 + le?vperm $in2,$in2,$in2,$leperm + vand $tmp,$tmp,$eighty7 + vxor $out2,$in2,$twk2 + vxor $tweak,$tweak,$tmp + + lvx_u $in3,$x30,$inp + sub $len,$len,$taillen + vxor $twk3,$tweak,$rndkey0 + vsrab $tmp,$tweak,$seven # next tweak value + vaddubm $tweak,$tweak,$tweak + vsldoi $tmp,$tmp,$tmp,15 + le?vperm $in3,$in3,$in3,$leperm + vand $tmp,$tmp,$eighty7 + vxor $out3,$in3,$twk3 + vxor $tweak,$tweak,$tmp + + lvx_u $in4,$x40,$inp + subi $len,$len,0x60 + vxor $twk4,$tweak,$rndkey0 + vsrab $tmp,$tweak,$seven # next tweak value + vaddubm $tweak,$tweak,$tweak + vsldoi $tmp,$tmp,$tmp,15 + le?vperm $in4,$in4,$in4,$leperm + vand $tmp,$tmp,$eighty7 + vxor $out4,$in4,$twk4 + vxor $tweak,$tweak,$tmp + + lvx_u $in5,$x50,$inp + addi $inp,$inp,0x60 + vxor $twk5,$tweak,$rndkey0 + vsrab $tmp,$tweak,$seven # next tweak value + vaddubm $tweak,$tweak,$tweak + vsldoi $tmp,$tmp,$tmp,15 + le?vperm $in5,$in5,$in5,$leperm + vand $tmp,$tmp,$eighty7 + vxor $out5,$in5,$twk5 + vxor $tweak,$tweak,$tmp + + vxor v31,v31,$rndkey0 + mtctr $rounds + b Loop_xts_dec6x + +.align 5 +Loop_xts_dec6x: + vncipher $out0,$out0,v24 + vncipher $out1,$out1,v24 + vncipher $out2,$out2,v24 + vncipher $out3,$out3,v24 + vncipher $out4,$out4,v24 + vncipher $out5,$out5,v24 + lvx v24,$x20,$key_ # round[3] + addi $key_,$key_,0x20 + + vncipher $out0,$out0,v25 + vncipher $out1,$out1,v25 + vncipher $out2,$out2,v25 + vncipher $out3,$out3,v25 + vncipher $out4,$out4,v25 + vncipher $out5,$out5,v25 + lvx v25,$x10,$key_ # round[4] + bdnz Loop_xts_dec6x + + subic $len,$len,96 # $len-=96 + vxor $in0,$twk0,v31 # xor with last round key + vncipher $out0,$out0,v24 + vncipher $out1,$out1,v24 + vsrab $tmp,$tweak,$seven # next tweak value + vxor $twk0,$tweak,$rndkey0 + vaddubm $tweak,$tweak,$tweak + vncipher $out2,$out2,v24 + vncipher $out3,$out3,v24 + vsldoi $tmp,$tmp,$tmp,15 + vncipher $out4,$out4,v24 + vncipher $out5,$out5,v24 + + subfe. r0,r0,r0 # borrow?-1:0 + vand $tmp,$tmp,$eighty7 + vncipher $out0,$out0,v25 + vncipher $out1,$out1,v25 + vxor $tweak,$tweak,$tmp + vncipher $out2,$out2,v25 + vncipher $out3,$out3,v25 + vxor $in1,$twk1,v31 + vsrab $tmp,$tweak,$seven # next tweak value + vxor $twk1,$tweak,$rndkey0 + vncipher $out4,$out4,v25 + vncipher $out5,$out5,v25 + + and r0,r0,$len + vaddubm $tweak,$tweak,$tweak + vsldoi $tmp,$tmp,$tmp,15 + vncipher $out0,$out0,v26 + vncipher $out1,$out1,v26 + vand $tmp,$tmp,$eighty7 + vncipher $out2,$out2,v26 + vncipher $out3,$out3,v26 + vxor $tweak,$tweak,$tmp + vncipher $out4,$out4,v26 + vncipher $out5,$out5,v26 + + add $inp,$inp,r0 # $inp is adjusted in such + # way that at exit from the + # loop inX-in5 are loaded + # with last "words" + vxor $in2,$twk2,v31 + vsrab $tmp,$tweak,$seven # next tweak value + vxor $twk2,$tweak,$rndkey0 + vaddubm $tweak,$tweak,$tweak + vncipher $out0,$out0,v27 + vncipher $out1,$out1,v27 + vsldoi $tmp,$tmp,$tmp,15 + vncipher $out2,$out2,v27 + vncipher $out3,$out3,v27 + vand $tmp,$tmp,$eighty7 + vncipher $out4,$out4,v27 + vncipher $out5,$out5,v27 + + addi $key_,$sp,$FRAME+15 # rewind $key_ + vxor $tweak,$tweak,$tmp + vncipher $out0,$out0,v28 + vncipher $out1,$out1,v28 + vxor $in3,$twk3,v31 + vsrab $tmp,$tweak,$seven # next tweak value + vxor $twk3,$tweak,$rndkey0 + vncipher $out2,$out2,v28 + vncipher $out3,$out3,v28 + vaddubm $tweak,$tweak,$tweak + vsldoi $tmp,$tmp,$tmp,15 + vncipher $out4,$out4,v28 + vncipher $out5,$out5,v28 + lvx v24,$x00,$key_ # re-pre-load round[1] + vand $tmp,$tmp,$eighty7 + + vncipher $out0,$out0,v29 + vncipher $out1,$out1,v29 + vxor $tweak,$tweak,$tmp + vncipher $out2,$out2,v29 + vncipher $out3,$out3,v29 + vxor $in4,$twk4,v31 + vsrab $tmp,$tweak,$seven # next tweak value + vxor $twk4,$tweak,$rndkey0 + vncipher $out4,$out4,v29 + vncipher $out5,$out5,v29 + lvx v25,$x10,$key_ # re-pre-load round[2] + vaddubm $tweak,$tweak,$tweak + vsldoi $tmp,$tmp,$tmp,15 + + vncipher $out0,$out0,v30 + vncipher $out1,$out1,v30 + vand $tmp,$tmp,$eighty7 + vncipher $out2,$out2,v30 + vncipher $out3,$out3,v30 + vxor $tweak,$tweak,$tmp + vncipher $out4,$out4,v30 + vncipher $out5,$out5,v30 + vxor $in5,$twk5,v31 + vsrab $tmp,$tweak,$seven # next tweak value + vxor $twk5,$tweak,$rndkey0 + + vncipherlast $out0,$out0,$in0 + lvx_u $in0,$x00,$inp # load next input block + vaddubm $tweak,$tweak,$tweak + vsldoi $tmp,$tmp,$tmp,15 + vncipherlast $out1,$out1,$in1 + lvx_u $in1,$x10,$inp + vncipherlast $out2,$out2,$in2 + le?vperm $in0,$in0,$in0,$leperm + lvx_u $in2,$x20,$inp + vand $tmp,$tmp,$eighty7 + vncipherlast $out3,$out3,$in3 + le?vperm $in1,$in1,$in1,$leperm + lvx_u $in3,$x30,$inp + vncipherlast $out4,$out4,$in4 + le?vperm $in2,$in2,$in2,$leperm + lvx_u $in4,$x40,$inp + vxor $tweak,$tweak,$tmp + vncipherlast $out5,$out5,$in5 + le?vperm $in3,$in3,$in3,$leperm + lvx_u $in5,$x50,$inp + addi $inp,$inp,0x60 + le?vperm $in4,$in4,$in4,$leperm + le?vperm $in5,$in5,$in5,$leperm + + le?vperm $out0,$out0,$out0,$leperm + le?vperm $out1,$out1,$out1,$leperm + stvx_u $out0,$x00,$out # store output + vxor $out0,$in0,$twk0 + le?vperm $out2,$out2,$out2,$leperm + stvx_u $out1,$x10,$out + vxor $out1,$in1,$twk1 + le?vperm $out3,$out3,$out3,$leperm + stvx_u $out2,$x20,$out + vxor $out2,$in2,$twk2 + le?vperm $out4,$out4,$out4,$leperm + stvx_u $out3,$x30,$out + vxor $out3,$in3,$twk3 + le?vperm $out5,$out5,$out5,$leperm + stvx_u $out4,$x40,$out + vxor $out4,$in4,$twk4 + stvx_u $out5,$x50,$out + vxor $out5,$in5,$twk5 + addi $out,$out,0x60 + + mtctr $rounds + beq Loop_xts_dec6x # did $len-=96 borrow? + + addic. $len,$len,0x60 + beq Lxts_dec6x_zero + cmpwi $len,0x20 + blt Lxts_dec6x_one + nop + beq Lxts_dec6x_two + cmpwi $len,0x40 + blt Lxts_dec6x_three + nop + beq Lxts_dec6x_four + +Lxts_dec6x_five: + vxor $out0,$in1,$twk0 + vxor $out1,$in2,$twk1 + vxor $out2,$in3,$twk2 + vxor $out3,$in4,$twk3 + vxor $out4,$in5,$twk4 + + bl _aesp8_xts_dec5x + + le?vperm $out0,$out0,$out0,$leperm + vmr $twk0,$twk5 # unused tweak + vxor $twk1,$tweak,$rndkey0 + le?vperm $out1,$out1,$out1,$leperm + stvx_u $out0,$x00,$out # store output + vxor $out0,$in0,$twk1 + le?vperm $out2,$out2,$out2,$leperm + stvx_u $out1,$x10,$out + le?vperm $out3,$out3,$out3,$leperm + stvx_u $out2,$x20,$out + le?vperm $out4,$out4,$out4,$leperm + stvx_u $out3,$x30,$out + stvx_u $out4,$x40,$out + addi $out,$out,0x50 + bne Lxts_dec6x_steal + b Lxts_dec6x_done + +.align 4 +Lxts_dec6x_four: + vxor $out0,$in2,$twk0 + vxor $out1,$in3,$twk1 + vxor $out2,$in4,$twk2 + vxor $out3,$in5,$twk3 + vxor $out4,$out4,$out4 + + bl _aesp8_xts_dec5x + + le?vperm $out0,$out0,$out0,$leperm + vmr $twk0,$twk4 # unused tweak + vmr $twk1,$twk5 + le?vperm $out1,$out1,$out1,$leperm + stvx_u $out0,$x00,$out # store output + vxor $out0,$in0,$twk5 + le?vperm $out2,$out2,$out2,$leperm + stvx_u $out1,$x10,$out + le?vperm $out3,$out3,$out3,$leperm + stvx_u $out2,$x20,$out + stvx_u $out3,$x30,$out + addi $out,$out,0x40 + bne Lxts_dec6x_steal + b Lxts_dec6x_done + +.align 4 +Lxts_dec6x_three: + vxor $out0,$in3,$twk0 + vxor $out1,$in4,$twk1 + vxor $out2,$in5,$twk2 + vxor $out3,$out3,$out3 + vxor $out4,$out4,$out4 + + bl _aesp8_xts_dec5x + + le?vperm $out0,$out0,$out0,$leperm + vmr $twk0,$twk3 # unused tweak + vmr $twk1,$twk4 + le?vperm $out1,$out1,$out1,$leperm + stvx_u $out0,$x00,$out # store output + vxor $out0,$in0,$twk4 + le?vperm $out2,$out2,$out2,$leperm + stvx_u $out1,$x10,$out + stvx_u $out2,$x20,$out + addi $out,$out,0x30 + bne Lxts_dec6x_steal + b Lxts_dec6x_done + +.align 4 +Lxts_dec6x_two: + vxor $out0,$in4,$twk0 + vxor $out1,$in5,$twk1 + vxor $out2,$out2,$out2 + vxor $out3,$out3,$out3 + vxor $out4,$out4,$out4 + + bl _aesp8_xts_dec5x + + le?vperm $out0,$out0,$out0,$leperm + vmr $twk0,$twk2 # unused tweak + vmr $twk1,$twk3 + le?vperm $out1,$out1,$out1,$leperm + stvx_u $out0,$x00,$out # store output + vxor $out0,$in0,$twk3 + stvx_u $out1,$x10,$out + addi $out,$out,0x20 + bne Lxts_dec6x_steal + b Lxts_dec6x_done + +.align 4 +Lxts_dec6x_one: + vxor $out0,$in5,$twk0 + nop +Loop_xts_dec1x: + vncipher $out0,$out0,v24 + lvx v24,$x20,$key_ # round[3] + addi $key_,$key_,0x20 + + vncipher $out0,$out0,v25 + lvx v25,$x10,$key_ # round[4] + bdnz Loop_xts_dec1x + + subi r0,$taillen,1 + vncipher $out0,$out0,v24 + + andi. r0,r0,16 + cmpwi $taillen,0 + vncipher $out0,$out0,v25 + + sub $inp,$inp,r0 + vncipher $out0,$out0,v26 + + lvx_u $in0,0,$inp + vncipher $out0,$out0,v27 + + addi $key_,$sp,$FRAME+15 # rewind $key_ + vncipher $out0,$out0,v28 + lvx v24,$x00,$key_ # re-pre-load round[1] + + vncipher $out0,$out0,v29 + lvx v25,$x10,$key_ # re-pre-load round[2] + vxor $twk0,$twk0,v31 + + le?vperm $in0,$in0,$in0,$leperm + vncipher $out0,$out0,v30 + + mtctr $rounds + vncipherlast $out0,$out0,$twk0 + + vmr $twk0,$twk1 # unused tweak + vmr $twk1,$twk2 + le?vperm $out0,$out0,$out0,$leperm + stvx_u $out0,$x00,$out # store output + addi $out,$out,0x10 + vxor $out0,$in0,$twk2 + bne Lxts_dec6x_steal + b Lxts_dec6x_done + +.align 4 +Lxts_dec6x_zero: + cmpwi $taillen,0 + beq Lxts_dec6x_done + + lvx_u $in0,0,$inp + le?vperm $in0,$in0,$in0,$leperm + vxor $out0,$in0,$twk1 +Lxts_dec6x_steal: + vncipher $out0,$out0,v24 + lvx v24,$x20,$key_ # round[3] + addi $key_,$key_,0x20 + + vncipher $out0,$out0,v25 + lvx v25,$x10,$key_ # round[4] + bdnz Lxts_dec6x_steal + + add $inp,$inp,$taillen + vncipher $out0,$out0,v24 + + cmpwi $taillen,0 + vncipher $out0,$out0,v25 + + lvx_u $in0,0,$inp + vncipher $out0,$out0,v26 + + lvsr $inpperm,0,$taillen # $in5 is no more + vncipher $out0,$out0,v27 + + addi $key_,$sp,$FRAME+15 # rewind $key_ + vncipher $out0,$out0,v28 + lvx v24,$x00,$key_ # re-pre-load round[1] + + vncipher $out0,$out0,v29 + lvx v25,$x10,$key_ # re-pre-load round[2] + vxor $twk1,$twk1,v31 + + le?vperm $in0,$in0,$in0,$leperm + vncipher $out0,$out0,v30 + + vperm $in0,$in0,$in0,$inpperm + vncipherlast $tmp,$out0,$twk1 + + le?vperm $out0,$tmp,$tmp,$leperm + le?stvx_u $out0,0,$out + be?stvx_u $tmp,0,$out + + vxor $out0,$out0,$out0 + vspltisb $out1,-1 + vperm $out0,$out0,$out1,$inpperm + vsel $out0,$in0,$tmp,$out0 + vxor $out0,$out0,$twk0 + + subi r30,$out,1 + mtctr $taillen +Loop_xts_dec6x_steal: + lbzu r0,1(r30) + stb r0,16(r30) + bdnz Loop_xts_dec6x_steal + + li $taillen,0 + mtctr $rounds + b Loop_xts_dec1x # one more time... + +.align 4 +Lxts_dec6x_done: + ${UCMP}i $ivp,0 + beq Lxts_dec6x_ret + + vxor $tweak,$twk0,$rndkey0 + le?vperm $tweak,$tweak,$tweak,$leperm + stvx_u $tweak,0,$ivp + +Lxts_dec6x_ret: + mtlr r11 + li r10,`$FRAME+15` + li r11,`$FRAME+31` + stvx $seven,r10,$sp # wipe copies of round keys + addi r10,r10,32 + stvx $seven,r11,$sp + addi r11,r11,32 + stvx $seven,r10,$sp + addi r10,r10,32 + stvx $seven,r11,$sp + addi r11,r11,32 + stvx $seven,r10,$sp + addi r10,r10,32 + stvx $seven,r11,$sp + addi r11,r11,32 + stvx $seven,r10,$sp + addi r10,r10,32 + stvx $seven,r11,$sp + addi r11,r11,32 + + mtspr 256,$vrsave + lvx v20,r10,$sp # ABI says so + addi r10,r10,32 + lvx v21,r11,$sp + addi r11,r11,32 + lvx v22,r10,$sp + addi r10,r10,32 + lvx v23,r11,$sp + addi r11,r11,32 + lvx v24,r10,$sp + addi r10,r10,32 + lvx v25,r11,$sp + addi r11,r11,32 + lvx v26,r10,$sp + addi r10,r10,32 + lvx v27,r11,$sp + addi r11,r11,32 + lvx v28,r10,$sp + addi r10,r10,32 + lvx v29,r11,$sp + addi r11,r11,32 + lvx v30,r10,$sp + lvx v31,r11,$sp + $POP r26,`$FRAME+21*16+0*$SIZE_T`($sp) + $POP r27,`$FRAME+21*16+1*$SIZE_T`($sp) + $POP r28,`$FRAME+21*16+2*$SIZE_T`($sp) + $POP r29,`$FRAME+21*16+3*$SIZE_T`($sp) + $POP r30,`$FRAME+21*16+4*$SIZE_T`($sp) + $POP r31,`$FRAME+21*16+5*$SIZE_T`($sp) + addi $sp,$sp,`$FRAME+21*16+6*$SIZE_T` + blr + .long 0 + .byte 0,12,0x04,1,0x80,6,6,0 + .long 0 + +.align 5 +_aesp8_xts_dec5x: + vncipher $out0,$out0,v24 + vncipher $out1,$out1,v24 + vncipher $out2,$out2,v24 + vncipher $out3,$out3,v24 + vncipher $out4,$out4,v24 + lvx v24,$x20,$key_ # round[3] + addi $key_,$key_,0x20 + + vncipher $out0,$out0,v25 + vncipher $out1,$out1,v25 + vncipher $out2,$out2,v25 + vncipher $out3,$out3,v25 + vncipher $out4,$out4,v25 + lvx v25,$x10,$key_ # round[4] + bdnz _aesp8_xts_dec5x + + subi r0,$taillen,1 + vncipher $out0,$out0,v24 + vncipher $out1,$out1,v24 + vncipher $out2,$out2,v24 + vncipher $out3,$out3,v24 + vncipher $out4,$out4,v24 + + andi. r0,r0,16 + cmpwi $taillen,0 + vncipher $out0,$out0,v25 + vncipher $out1,$out1,v25 + vncipher $out2,$out2,v25 + vncipher $out3,$out3,v25 + vncipher $out4,$out4,v25 + vxor $twk0,$twk0,v31 + + sub $inp,$inp,r0 + vncipher $out0,$out0,v26 + vncipher $out1,$out1,v26 + vncipher $out2,$out2,v26 + vncipher $out3,$out3,v26 + vncipher $out4,$out4,v26 + vxor $in1,$twk1,v31 + + vncipher $out0,$out0,v27 + lvx_u $in0,0,$inp + vncipher $out1,$out1,v27 + vncipher $out2,$out2,v27 + vncipher $out3,$out3,v27 + vncipher $out4,$out4,v27 + vxor $in2,$twk2,v31 + + addi $key_,$sp,$FRAME+15 # rewind $key_ + vncipher $out0,$out0,v28 + vncipher $out1,$out1,v28 + vncipher $out2,$out2,v28 + vncipher $out3,$out3,v28 + vncipher $out4,$out4,v28 + lvx v24,$x00,$key_ # re-pre-load round[1] + vxor $in3,$twk3,v31 + + vncipher $out0,$out0,v29 + le?vperm $in0,$in0,$in0,$leperm + vncipher $out1,$out1,v29 + vncipher $out2,$out2,v29 + vncipher $out3,$out3,v29 + vncipher $out4,$out4,v29 + lvx v25,$x10,$key_ # re-pre-load round[2] + vxor $in4,$twk4,v31 + + vncipher $out0,$out0,v30 + vncipher $out1,$out1,v30 + vncipher $out2,$out2,v30 + vncipher $out3,$out3,v30 + vncipher $out4,$out4,v30 + + vncipherlast $out0,$out0,$twk0 + vncipherlast $out1,$out1,$in1 + vncipherlast $out2,$out2,$in2 + vncipherlast $out3,$out3,$in3 + vncipherlast $out4,$out4,$in4 + mtctr $rounds + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 +___ +}} }}} + +my $consts=1; +foreach(split("\n",$code)) { + s/\`([^\`]*)\`/eval($1)/geo; + + # constants table endian-specific conversion + if ($consts && m/\.(long|byte)\s+(.+)\s+(\?[a-z]*)$/o) { + my $conv=$3; + my @bytes=(); + + # convert to endian-agnostic format + if ($1 eq "long") { + foreach (split(/,\s*/,$2)) { + my $l = /^0/?oct:int; + push @bytes,($l>>24)&0xff,($l>>16)&0xff,($l>>8)&0xff,$l&0xff; + } + } else { + @bytes = map(/^0/?oct:int,split(/,\s*/,$2)); + } + + # little-endian conversion + if ($flavour =~ /le$/o) { + SWITCH: for($conv) { + /\?inv/ && do { @bytes=map($_^0xf,@bytes); last; }; + /\?rev/ && do { @bytes=reverse(@bytes); last; }; + } + } + + #emit + print ".byte\t",join(',',map (sprintf("0x%02x",$_),@bytes)),"\n"; + next; + } + $consts=0 if (m/Lconsts:/o); # end of table + + # instructions prefixed with '?' are endian-specific and need + # to be adjusted accordingly... + if ($flavour =~ /le$/o) { # little-endian + s/le\?//o or + s/be\?/#be#/o or + s/\?lvsr/lvsl/o or + s/\?lvsl/lvsr/o or + s/\?(vperm\s+v[0-9]+,\s*)(v[0-9]+,\s*)(v[0-9]+,\s*)(v[0-9]+)/$1$3$2$4/o or + s/\?(vsldoi\s+v[0-9]+,\s*)(v[0-9]+,)\s*(v[0-9]+,\s*)([0-9]+)/$1$3$2 16-$4/o or + s/\?(vspltw\s+v[0-9]+,\s*)(v[0-9]+,)\s*([0-9])/$1$2 3-$3/o; + } else { # big-endian + s/le\?/#le#/o or + s/be\?//o or + s/\?([a-z]+)/$1/o; + } + + print $_,"\n"; +} + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aest4-sparcv9.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aest4-sparcv9.pl new file mode 100644 index 000000000..54d0c5882 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aest4-sparcv9.pl @@ -0,0 +1,929 @@ +#! /usr/bin/env perl +# Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by David S. Miller and Andy Polyakov. +# The module is licensed under 2-clause BSD license. October 2012. +# All rights reserved. +# ==================================================================== + +###################################################################### +# AES for SPARC T4. +# +# AES round instructions complete in 3 cycles and can be issued every +# cycle. It means that round calculations should take 4*rounds cycles, +# because any given round instruction depends on result of *both* +# previous instructions: +# +# |0 |1 |2 |3 |4 +# |01|01|01| +# |23|23|23| +# |01|01|... +# |23|... +# +# Provided that fxor [with IV] takes 3 cycles to complete, critical +# path length for CBC encrypt would be 3+4*rounds, or in other words +# it should process one byte in at least (3+4*rounds)/16 cycles. This +# estimate doesn't account for "collateral" instructions, such as +# fetching input from memory, xor-ing it with zero-round key and +# storing the result. Yet, *measured* performance [for data aligned +# at 64-bit boundary!] deviates from this equation by less than 0.5%: +# +# 128-bit key 192- 256- +# CBC encrypt 2.70/2.90(*) 3.20/3.40 3.70/3.90 +# (*) numbers after slash are for +# misaligned data. +# +# Out-of-order execution logic managed to fully overlap "collateral" +# instructions with those on critical path. Amazing! +# +# As with Intel AES-NI, question is if it's possible to improve +# performance of parallelizable modes by interleaving round +# instructions. Provided round instruction latency and throughput +# optimal interleave factor is 2. But can we expect 2x performance +# improvement? Well, as round instructions can be issued one per +# cycle, they don't saturate the 2-way issue pipeline and therefore +# there is room for "collateral" calculations... Yet, 2x speed-up +# over CBC encrypt remains unattaintable: +# +# 128-bit key 192- 256- +# CBC decrypt 1.64/2.11 1.89/2.37 2.23/2.61 +# CTR 1.64/2.08(*) 1.89/2.33 2.23/2.61 +# (*) numbers after slash are for +# misaligned data. +# +# Estimates based on amount of instructions under assumption that +# round instructions are not pairable with any other instruction +# suggest that latter is the actual case and pipeline runs +# underutilized. It should be noted that T4 out-of-order execution +# logic is so capable that performance gain from 2x interleave is +# not even impressive, ~7-13% over non-interleaved code, largest +# for 256-bit keys. + +# To anchor to something else, software implementation processes +# one byte in 29 cycles with 128-bit key on same processor. Intel +# Sandy Bridge encrypts byte in 5.07 cycles in CBC mode and decrypts +# in 0.93, naturally with AES-NI. + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "sparcv9_modes.pl"; + +$output = pop; +open STDOUT,">$output"; + +$::evp=1; # if $evp is set to 0, script generates module with +# AES_[en|de]crypt, AES_set_[en|de]crypt_key and AES_cbc_encrypt entry +# points. These however are not fully compatible with openssl/aes.h, +# because they expect AES_KEY to be aligned at 64-bit boundary. When +# used through EVP, alignment is arranged at EVP layer. Second thing +# that is arranged by EVP is at least 32-bit alignment of IV. + +###################################################################### +# single-round subroutines +# +{ +my ($inp,$out,$key,$rounds,$tmp,$mask)=map("%o$_",(0..5)); + +$code.=<<___; +#include "sparc_arch.h" + +#ifdef __arch64__ +.register %g2,#scratch +.register %g3,#scratch +#endif + +.text + +.globl aes_t4_encrypt +.align 32 +aes_t4_encrypt: + andcc $inp, 7, %g1 ! is input aligned? + andn $inp, 7, $inp + + ldx [$key + 0], %g4 + ldx [$key + 8], %g5 + + ldx [$inp + 0], %o4 + bz,pt %icc, 1f + ldx [$inp + 8], %o5 + ldx [$inp + 16], $inp + sll %g1, 3, %g1 + sub %g0, %g1, %o3 + sllx %o4, %g1, %o4 + sllx %o5, %g1, %g1 + srlx %o5, %o3, %o5 + srlx $inp, %o3, %o3 + or %o5, %o4, %o4 + or %o3, %g1, %o5 +1: + ld [$key + 240], $rounds + ldd [$key + 16], %f12 + ldd [$key + 24], %f14 + xor %g4, %o4, %o4 + xor %g5, %o5, %o5 + movxtod %o4, %f0 + movxtod %o5, %f2 + srl $rounds, 1, $rounds + ldd [$key + 32], %f16 + sub $rounds, 1, $rounds + ldd [$key + 40], %f18 + add $key, 48, $key + +.Lenc: + aes_eround01 %f12, %f0, %f2, %f4 + aes_eround23 %f14, %f0, %f2, %f2 + ldd [$key + 0], %f12 + ldd [$key + 8], %f14 + sub $rounds,1,$rounds + aes_eround01 %f16, %f4, %f2, %f0 + aes_eround23 %f18, %f4, %f2, %f2 + ldd [$key + 16], %f16 + ldd [$key + 24], %f18 + brnz,pt $rounds, .Lenc + add $key, 32, $key + + andcc $out, 7, $tmp ! is output aligned? + aes_eround01 %f12, %f0, %f2, %f4 + aes_eround23 %f14, %f0, %f2, %f2 + aes_eround01_l %f16, %f4, %f2, %f0 + aes_eround23_l %f18, %f4, %f2, %f2 + + bnz,pn %icc, 2f + nop + + std %f0, [$out + 0] + retl + std %f2, [$out + 8] + +2: alignaddrl $out, %g0, $out + mov 0xff, $mask + srl $mask, $tmp, $mask + + faligndata %f0, %f0, %f4 + faligndata %f0, %f2, %f6 + faligndata %f2, %f2, %f8 + + stda %f4, [$out + $mask]0xc0 ! partial store + std %f6, [$out + 8] + add $out, 16, $out + orn %g0, $mask, $mask + retl + stda %f8, [$out + $mask]0xc0 ! partial store +.type aes_t4_encrypt,#function +.size aes_t4_encrypt,.-aes_t4_encrypt + +.globl aes_t4_decrypt +.align 32 +aes_t4_decrypt: + andcc $inp, 7, %g1 ! is input aligned? + andn $inp, 7, $inp + + ldx [$key + 0], %g4 + ldx [$key + 8], %g5 + + ldx [$inp + 0], %o4 + bz,pt %icc, 1f + ldx [$inp + 8], %o5 + ldx [$inp + 16], $inp + sll %g1, 3, %g1 + sub %g0, %g1, %o3 + sllx %o4, %g1, %o4 + sllx %o5, %g1, %g1 + srlx %o5, %o3, %o5 + srlx $inp, %o3, %o3 + or %o5, %o4, %o4 + or %o3, %g1, %o5 +1: + ld [$key + 240], $rounds + ldd [$key + 16], %f12 + ldd [$key + 24], %f14 + xor %g4, %o4, %o4 + xor %g5, %o5, %o5 + movxtod %o4, %f0 + movxtod %o5, %f2 + srl $rounds, 1, $rounds + ldd [$key + 32], %f16 + sub $rounds, 1, $rounds + ldd [$key + 40], %f18 + add $key, 48, $key + +.Ldec: + aes_dround01 %f12, %f0, %f2, %f4 + aes_dround23 %f14, %f0, %f2, %f2 + ldd [$key + 0], %f12 + ldd [$key + 8], %f14 + sub $rounds,1,$rounds + aes_dround01 %f16, %f4, %f2, %f0 + aes_dround23 %f18, %f4, %f2, %f2 + ldd [$key + 16], %f16 + ldd [$key + 24], %f18 + brnz,pt $rounds, .Ldec + add $key, 32, $key + + andcc $out, 7, $tmp ! is output aligned? + aes_dround01 %f12, %f0, %f2, %f4 + aes_dround23 %f14, %f0, %f2, %f2 + aes_dround01_l %f16, %f4, %f2, %f0 + aes_dround23_l %f18, %f4, %f2, %f2 + + bnz,pn %icc, 2f + nop + + std %f0, [$out + 0] + retl + std %f2, [$out + 8] + +2: alignaddrl $out, %g0, $out + mov 0xff, $mask + srl $mask, $tmp, $mask + + faligndata %f0, %f0, %f4 + faligndata %f0, %f2, %f6 + faligndata %f2, %f2, %f8 + + stda %f4, [$out + $mask]0xc0 ! partial store + std %f6, [$out + 8] + add $out, 16, $out + orn %g0, $mask, $mask + retl + stda %f8, [$out + $mask]0xc0 ! partial store +.type aes_t4_decrypt,#function +.size aes_t4_decrypt,.-aes_t4_decrypt +___ +} + +###################################################################### +# key setup subroutines +# +{ +my ($inp,$bits,$out,$tmp)=map("%o$_",(0..5)); +$code.=<<___; +.globl aes_t4_set_encrypt_key +.align 32 +aes_t4_set_encrypt_key: +.Lset_encrypt_key: + and $inp, 7, $tmp + alignaddr $inp, %g0, $inp + cmp $bits, 192 + ldd [$inp + 0], %f0 + bl,pt %icc,.L128 + ldd [$inp + 8], %f2 + + be,pt %icc,.L192 + ldd [$inp + 16], %f4 + brz,pt $tmp, .L256aligned + ldd [$inp + 24], %f6 + + ldd [$inp + 32], %f8 + faligndata %f0, %f2, %f0 + faligndata %f2, %f4, %f2 + faligndata %f4, %f6, %f4 + faligndata %f6, %f8, %f6 +.L256aligned: +___ +for ($i=0; $i<6; $i++) { + $code.=<<___; + std %f0, [$out + `32*$i+0`] + aes_kexpand1 %f0, %f6, $i, %f0 + std %f2, [$out + `32*$i+8`] + aes_kexpand2 %f2, %f0, %f2 + std %f4, [$out + `32*$i+16`] + aes_kexpand0 %f4, %f2, %f4 + std %f6, [$out + `32*$i+24`] + aes_kexpand2 %f6, %f4, %f6 +___ +} +$code.=<<___; + std %f0, [$out + `32*$i+0`] + aes_kexpand1 %f0, %f6, $i, %f0 + std %f2, [$out + `32*$i+8`] + aes_kexpand2 %f2, %f0, %f2 + std %f4, [$out + `32*$i+16`] + std %f6, [$out + `32*$i+24`] + std %f0, [$out + `32*$i+32`] + std %f2, [$out + `32*$i+40`] + + mov 14, $tmp + st $tmp, [$out + 240] + retl + xor %o0, %o0, %o0 + +.align 16 +.L192: + brz,pt $tmp, .L192aligned + nop + + ldd [$inp + 24], %f6 + faligndata %f0, %f2, %f0 + faligndata %f2, %f4, %f2 + faligndata %f4, %f6, %f4 +.L192aligned: +___ +for ($i=0; $i<7; $i++) { + $code.=<<___; + std %f0, [$out + `24*$i+0`] + aes_kexpand1 %f0, %f4, $i, %f0 + std %f2, [$out + `24*$i+8`] + aes_kexpand2 %f2, %f0, %f2 + std %f4, [$out + `24*$i+16`] + aes_kexpand2 %f4, %f2, %f4 +___ +} +$code.=<<___; + std %f0, [$out + `24*$i+0`] + aes_kexpand1 %f0, %f4, $i, %f0 + std %f2, [$out + `24*$i+8`] + aes_kexpand2 %f2, %f0, %f2 + std %f4, [$out + `24*$i+16`] + std %f0, [$out + `24*$i+24`] + std %f2, [$out + `24*$i+32`] + + mov 12, $tmp + st $tmp, [$out + 240] + retl + xor %o0, %o0, %o0 + +.align 16 +.L128: + brz,pt $tmp, .L128aligned + nop + + ldd [$inp + 16], %f4 + faligndata %f0, %f2, %f0 + faligndata %f2, %f4, %f2 +.L128aligned: +___ +for ($i=0; $i<10; $i++) { + $code.=<<___; + std %f0, [$out + `16*$i+0`] + aes_kexpand1 %f0, %f2, $i, %f0 + std %f2, [$out + `16*$i+8`] + aes_kexpand2 %f2, %f0, %f2 +___ +} +$code.=<<___; + std %f0, [$out + `16*$i+0`] + std %f2, [$out + `16*$i+8`] + + mov 10, $tmp + st $tmp, [$out + 240] + retl + xor %o0, %o0, %o0 +.type aes_t4_set_encrypt_key,#function +.size aes_t4_set_encrypt_key,.-aes_t4_set_encrypt_key + +.globl aes_t4_set_decrypt_key +.align 32 +aes_t4_set_decrypt_key: + mov %o7, %o5 + call .Lset_encrypt_key + nop + + mov %o5, %o7 + sll $tmp, 4, $inp ! $tmp is number of rounds + add $tmp, 2, $tmp + add $out, $inp, $inp ! $inp=$out+16*rounds + srl $tmp, 2, $tmp ! $tmp=(rounds+2)/4 + +.Lkey_flip: + ldd [$out + 0], %f0 + ldd [$out + 8], %f2 + ldd [$out + 16], %f4 + ldd [$out + 24], %f6 + ldd [$inp + 0], %f8 + ldd [$inp + 8], %f10 + ldd [$inp - 16], %f12 + ldd [$inp - 8], %f14 + sub $tmp, 1, $tmp + std %f0, [$inp + 0] + std %f2, [$inp + 8] + std %f4, [$inp - 16] + std %f6, [$inp - 8] + std %f8, [$out + 0] + std %f10, [$out + 8] + std %f12, [$out + 16] + std %f14, [$out + 24] + add $out, 32, $out + brnz $tmp, .Lkey_flip + sub $inp, 32, $inp + + retl + xor %o0, %o0, %o0 +.type aes_t4_set_decrypt_key,#function +.size aes_t4_set_decrypt_key,.-aes_t4_set_decrypt_key +___ +} + +{{{ +my ($inp,$out,$len,$key,$ivec,$enc)=map("%i$_",(0..5)); +my ($ileft,$iright,$ooff,$omask,$ivoff)=map("%l$_",(1..7)); + +$code.=<<___; +.align 32 +_aes128_encrypt_1x: +___ +for ($i=0; $i<4; $i++) { + $code.=<<___; + aes_eround01 %f`16+8*$i+0`, %f0, %f2, %f4 + aes_eround23 %f`16+8*$i+2`, %f0, %f2, %f2 + aes_eround01 %f`16+8*$i+4`, %f4, %f2, %f0 + aes_eround23 %f`16+8*$i+6`, %f4, %f2, %f2 +___ +} +$code.=<<___; + aes_eround01 %f48, %f0, %f2, %f4 + aes_eround23 %f50, %f0, %f2, %f2 + aes_eround01_l %f52, %f4, %f2, %f0 + retl + aes_eround23_l %f54, %f4, %f2, %f2 +.type _aes128_encrypt_1x,#function +.size _aes128_encrypt_1x,.-_aes128_encrypt_1x + +.align 32 +_aes128_encrypt_2x: +___ +for ($i=0; $i<4; $i++) { + $code.=<<___; + aes_eround01 %f`16+8*$i+0`, %f0, %f2, %f8 + aes_eround23 %f`16+8*$i+2`, %f0, %f2, %f2 + aes_eround01 %f`16+8*$i+0`, %f4, %f6, %f10 + aes_eround23 %f`16+8*$i+2`, %f4, %f6, %f6 + aes_eround01 %f`16+8*$i+4`, %f8, %f2, %f0 + aes_eround23 %f`16+8*$i+6`, %f8, %f2, %f2 + aes_eround01 %f`16+8*$i+4`, %f10, %f6, %f4 + aes_eround23 %f`16+8*$i+6`, %f10, %f6, %f6 +___ +} +$code.=<<___; + aes_eround01 %f48, %f0, %f2, %f8 + aes_eround23 %f50, %f0, %f2, %f2 + aes_eround01 %f48, %f4, %f6, %f10 + aes_eround23 %f50, %f4, %f6, %f6 + aes_eround01_l %f52, %f8, %f2, %f0 + aes_eround23_l %f54, %f8, %f2, %f2 + aes_eround01_l %f52, %f10, %f6, %f4 + retl + aes_eround23_l %f54, %f10, %f6, %f6 +.type _aes128_encrypt_2x,#function +.size _aes128_encrypt_2x,.-_aes128_encrypt_2x + +.align 32 +_aes128_loadkey: + ldx [$key + 0], %g4 + ldx [$key + 8], %g5 +___ +for ($i=2; $i<22;$i++) { # load key schedule + $code.=<<___; + ldd [$key + `8*$i`], %f`12+2*$i` +___ +} +$code.=<<___; + retl + nop +.type _aes128_loadkey,#function +.size _aes128_loadkey,.-_aes128_loadkey +_aes128_load_enckey=_aes128_loadkey +_aes128_load_deckey=_aes128_loadkey + +___ + +&alg_cbc_encrypt_implement("aes",128); +if ($::evp) { + &alg_ctr32_implement("aes",128); + &alg_xts_implement("aes",128,"en"); + &alg_xts_implement("aes",128,"de"); +} +&alg_cbc_decrypt_implement("aes",128); + +$code.=<<___; +.align 32 +_aes128_decrypt_1x: +___ +for ($i=0; $i<4; $i++) { + $code.=<<___; + aes_dround01 %f`16+8*$i+0`, %f0, %f2, %f4 + aes_dround23 %f`16+8*$i+2`, %f0, %f2, %f2 + aes_dround01 %f`16+8*$i+4`, %f4, %f2, %f0 + aes_dround23 %f`16+8*$i+6`, %f4, %f2, %f2 +___ +} +$code.=<<___; + aes_dround01 %f48, %f0, %f2, %f4 + aes_dround23 %f50, %f0, %f2, %f2 + aes_dround01_l %f52, %f4, %f2, %f0 + retl + aes_dround23_l %f54, %f4, %f2, %f2 +.type _aes128_decrypt_1x,#function +.size _aes128_decrypt_1x,.-_aes128_decrypt_1x + +.align 32 +_aes128_decrypt_2x: +___ +for ($i=0; $i<4; $i++) { + $code.=<<___; + aes_dround01 %f`16+8*$i+0`, %f0, %f2, %f8 + aes_dround23 %f`16+8*$i+2`, %f0, %f2, %f2 + aes_dround01 %f`16+8*$i+0`, %f4, %f6, %f10 + aes_dround23 %f`16+8*$i+2`, %f4, %f6, %f6 + aes_dround01 %f`16+8*$i+4`, %f8, %f2, %f0 + aes_dround23 %f`16+8*$i+6`, %f8, %f2, %f2 + aes_dround01 %f`16+8*$i+4`, %f10, %f6, %f4 + aes_dround23 %f`16+8*$i+6`, %f10, %f6, %f6 +___ +} +$code.=<<___; + aes_dround01 %f48, %f0, %f2, %f8 + aes_dround23 %f50, %f0, %f2, %f2 + aes_dround01 %f48, %f4, %f6, %f10 + aes_dround23 %f50, %f4, %f6, %f6 + aes_dround01_l %f52, %f8, %f2, %f0 + aes_dround23_l %f54, %f8, %f2, %f2 + aes_dround01_l %f52, %f10, %f6, %f4 + retl + aes_dround23_l %f54, %f10, %f6, %f6 +.type _aes128_decrypt_2x,#function +.size _aes128_decrypt_2x,.-_aes128_decrypt_2x +___ + +$code.=<<___; +.align 32 +_aes192_encrypt_1x: +___ +for ($i=0; $i<5; $i++) { + $code.=<<___; + aes_eround01 %f`16+8*$i+0`, %f0, %f2, %f4 + aes_eround23 %f`16+8*$i+2`, %f0, %f2, %f2 + aes_eround01 %f`16+8*$i+4`, %f4, %f2, %f0 + aes_eround23 %f`16+8*$i+6`, %f4, %f2, %f2 +___ +} +$code.=<<___; + aes_eround01 %f56, %f0, %f2, %f4 + aes_eround23 %f58, %f0, %f2, %f2 + aes_eround01_l %f60, %f4, %f2, %f0 + retl + aes_eround23_l %f62, %f4, %f2, %f2 +.type _aes192_encrypt_1x,#function +.size _aes192_encrypt_1x,.-_aes192_encrypt_1x + +.align 32 +_aes192_encrypt_2x: +___ +for ($i=0; $i<5; $i++) { + $code.=<<___; + aes_eround01 %f`16+8*$i+0`, %f0, %f2, %f8 + aes_eround23 %f`16+8*$i+2`, %f0, %f2, %f2 + aes_eround01 %f`16+8*$i+0`, %f4, %f6, %f10 + aes_eround23 %f`16+8*$i+2`, %f4, %f6, %f6 + aes_eround01 %f`16+8*$i+4`, %f8, %f2, %f0 + aes_eround23 %f`16+8*$i+6`, %f8, %f2, %f2 + aes_eround01 %f`16+8*$i+4`, %f10, %f6, %f4 + aes_eround23 %f`16+8*$i+6`, %f10, %f6, %f6 +___ +} +$code.=<<___; + aes_eround01 %f56, %f0, %f2, %f8 + aes_eround23 %f58, %f0, %f2, %f2 + aes_eround01 %f56, %f4, %f6, %f10 + aes_eround23 %f58, %f4, %f6, %f6 + aes_eround01_l %f60, %f8, %f2, %f0 + aes_eround23_l %f62, %f8, %f2, %f2 + aes_eround01_l %f60, %f10, %f6, %f4 + retl + aes_eround23_l %f62, %f10, %f6, %f6 +.type _aes192_encrypt_2x,#function +.size _aes192_encrypt_2x,.-_aes192_encrypt_2x + +.align 32 +_aes256_encrypt_1x: + aes_eround01 %f16, %f0, %f2, %f4 + aes_eround23 %f18, %f0, %f2, %f2 + ldd [$key + 208], %f16 + ldd [$key + 216], %f18 + aes_eround01 %f20, %f4, %f2, %f0 + aes_eround23 %f22, %f4, %f2, %f2 + ldd [$key + 224], %f20 + ldd [$key + 232], %f22 +___ +for ($i=1; $i<6; $i++) { + $code.=<<___; + aes_eround01 %f`16+8*$i+0`, %f0, %f2, %f4 + aes_eround23 %f`16+8*$i+2`, %f0, %f2, %f2 + aes_eround01 %f`16+8*$i+4`, %f4, %f2, %f0 + aes_eround23 %f`16+8*$i+6`, %f4, %f2, %f2 +___ +} +$code.=<<___; + aes_eround01 %f16, %f0, %f2, %f4 + aes_eround23 %f18, %f0, %f2, %f2 + ldd [$key + 16], %f16 + ldd [$key + 24], %f18 + aes_eround01_l %f20, %f4, %f2, %f0 + aes_eround23_l %f22, %f4, %f2, %f2 + ldd [$key + 32], %f20 + retl + ldd [$key + 40], %f22 +.type _aes256_encrypt_1x,#function +.size _aes256_encrypt_1x,.-_aes256_encrypt_1x + +.align 32 +_aes256_encrypt_2x: + aes_eround01 %f16, %f0, %f2, %f8 + aes_eround23 %f18, %f0, %f2, %f2 + aes_eround01 %f16, %f4, %f6, %f10 + aes_eround23 %f18, %f4, %f6, %f6 + ldd [$key + 208], %f16 + ldd [$key + 216], %f18 + aes_eround01 %f20, %f8, %f2, %f0 + aes_eround23 %f22, %f8, %f2, %f2 + aes_eround01 %f20, %f10, %f6, %f4 + aes_eround23 %f22, %f10, %f6, %f6 + ldd [$key + 224], %f20 + ldd [$key + 232], %f22 +___ +for ($i=1; $i<6; $i++) { + $code.=<<___; + aes_eround01 %f`16+8*$i+0`, %f0, %f2, %f8 + aes_eround23 %f`16+8*$i+2`, %f0, %f2, %f2 + aes_eround01 %f`16+8*$i+0`, %f4, %f6, %f10 + aes_eround23 %f`16+8*$i+2`, %f4, %f6, %f6 + aes_eround01 %f`16+8*$i+4`, %f8, %f2, %f0 + aes_eround23 %f`16+8*$i+6`, %f8, %f2, %f2 + aes_eround01 %f`16+8*$i+4`, %f10, %f6, %f4 + aes_eround23 %f`16+8*$i+6`, %f10, %f6, %f6 +___ +} +$code.=<<___; + aes_eround01 %f16, %f0, %f2, %f8 + aes_eround23 %f18, %f0, %f2, %f2 + aes_eround01 %f16, %f4, %f6, %f10 + aes_eround23 %f18, %f4, %f6, %f6 + ldd [$key + 16], %f16 + ldd [$key + 24], %f18 + aes_eround01_l %f20, %f8, %f2, %f0 + aes_eround23_l %f22, %f8, %f2, %f2 + aes_eround01_l %f20, %f10, %f6, %f4 + aes_eround23_l %f22, %f10, %f6, %f6 + ldd [$key + 32], %f20 + retl + ldd [$key + 40], %f22 +.type _aes256_encrypt_2x,#function +.size _aes256_encrypt_2x,.-_aes256_encrypt_2x + +.align 32 +_aes192_loadkey: + ldx [$key + 0], %g4 + ldx [$key + 8], %g5 +___ +for ($i=2; $i<26;$i++) { # load key schedule + $code.=<<___; + ldd [$key + `8*$i`], %f`12+2*$i` +___ +} +$code.=<<___; + retl + nop +.type _aes192_loadkey,#function +.size _aes192_loadkey,.-_aes192_loadkey +_aes256_loadkey=_aes192_loadkey +_aes192_load_enckey=_aes192_loadkey +_aes192_load_deckey=_aes192_loadkey +_aes256_load_enckey=_aes192_loadkey +_aes256_load_deckey=_aes192_loadkey +___ + +&alg_cbc_encrypt_implement("aes",256); +&alg_cbc_encrypt_implement("aes",192); +if ($::evp) { + &alg_ctr32_implement("aes",256); + &alg_xts_implement("aes",256,"en"); + &alg_xts_implement("aes",256,"de"); + &alg_ctr32_implement("aes",192); +} +&alg_cbc_decrypt_implement("aes",192); +&alg_cbc_decrypt_implement("aes",256); + +$code.=<<___; +.align 32 +_aes256_decrypt_1x: + aes_dround01 %f16, %f0, %f2, %f4 + aes_dround23 %f18, %f0, %f2, %f2 + ldd [$key + 208], %f16 + ldd [$key + 216], %f18 + aes_dround01 %f20, %f4, %f2, %f0 + aes_dround23 %f22, %f4, %f2, %f2 + ldd [$key + 224], %f20 + ldd [$key + 232], %f22 +___ +for ($i=1; $i<6; $i++) { + $code.=<<___; + aes_dround01 %f`16+8*$i+0`, %f0, %f2, %f4 + aes_dround23 %f`16+8*$i+2`, %f0, %f2, %f2 + aes_dround01 %f`16+8*$i+4`, %f4, %f2, %f0 + aes_dround23 %f`16+8*$i+6`, %f4, %f2, %f2 +___ +} +$code.=<<___; + aes_dround01 %f16, %f0, %f2, %f4 + aes_dround23 %f18, %f0, %f2, %f2 + ldd [$key + 16], %f16 + ldd [$key + 24], %f18 + aes_dround01_l %f20, %f4, %f2, %f0 + aes_dround23_l %f22, %f4, %f2, %f2 + ldd [$key + 32], %f20 + retl + ldd [$key + 40], %f22 +.type _aes256_decrypt_1x,#function +.size _aes256_decrypt_1x,.-_aes256_decrypt_1x + +.align 32 +_aes256_decrypt_2x: + aes_dround01 %f16, %f0, %f2, %f8 + aes_dround23 %f18, %f0, %f2, %f2 + aes_dround01 %f16, %f4, %f6, %f10 + aes_dround23 %f18, %f4, %f6, %f6 + ldd [$key + 208], %f16 + ldd [$key + 216], %f18 + aes_dround01 %f20, %f8, %f2, %f0 + aes_dround23 %f22, %f8, %f2, %f2 + aes_dround01 %f20, %f10, %f6, %f4 + aes_dround23 %f22, %f10, %f6, %f6 + ldd [$key + 224], %f20 + ldd [$key + 232], %f22 +___ +for ($i=1; $i<6; $i++) { + $code.=<<___; + aes_dround01 %f`16+8*$i+0`, %f0, %f2, %f8 + aes_dround23 %f`16+8*$i+2`, %f0, %f2, %f2 + aes_dround01 %f`16+8*$i+0`, %f4, %f6, %f10 + aes_dround23 %f`16+8*$i+2`, %f4, %f6, %f6 + aes_dround01 %f`16+8*$i+4`, %f8, %f2, %f0 + aes_dround23 %f`16+8*$i+6`, %f8, %f2, %f2 + aes_dround01 %f`16+8*$i+4`, %f10, %f6, %f4 + aes_dround23 %f`16+8*$i+6`, %f10, %f6, %f6 +___ +} +$code.=<<___; + aes_dround01 %f16, %f0, %f2, %f8 + aes_dround23 %f18, %f0, %f2, %f2 + aes_dround01 %f16, %f4, %f6, %f10 + aes_dround23 %f18, %f4, %f6, %f6 + ldd [$key + 16], %f16 + ldd [$key + 24], %f18 + aes_dround01_l %f20, %f8, %f2, %f0 + aes_dround23_l %f22, %f8, %f2, %f2 + aes_dround01_l %f20, %f10, %f6, %f4 + aes_dround23_l %f22, %f10, %f6, %f6 + ldd [$key + 32], %f20 + retl + ldd [$key + 40], %f22 +.type _aes256_decrypt_2x,#function +.size _aes256_decrypt_2x,.-_aes256_decrypt_2x + +.align 32 +_aes192_decrypt_1x: +___ +for ($i=0; $i<5; $i++) { + $code.=<<___; + aes_dround01 %f`16+8*$i+0`, %f0, %f2, %f4 + aes_dround23 %f`16+8*$i+2`, %f0, %f2, %f2 + aes_dround01 %f`16+8*$i+4`, %f4, %f2, %f0 + aes_dround23 %f`16+8*$i+6`, %f4, %f2, %f2 +___ +} +$code.=<<___; + aes_dround01 %f56, %f0, %f2, %f4 + aes_dround23 %f58, %f0, %f2, %f2 + aes_dround01_l %f60, %f4, %f2, %f0 + retl + aes_dround23_l %f62, %f4, %f2, %f2 +.type _aes192_decrypt_1x,#function +.size _aes192_decrypt_1x,.-_aes192_decrypt_1x + +.align 32 +_aes192_decrypt_2x: +___ +for ($i=0; $i<5; $i++) { + $code.=<<___; + aes_dround01 %f`16+8*$i+0`, %f0, %f2, %f8 + aes_dround23 %f`16+8*$i+2`, %f0, %f2, %f2 + aes_dround01 %f`16+8*$i+0`, %f4, %f6, %f10 + aes_dround23 %f`16+8*$i+2`, %f4, %f6, %f6 + aes_dround01 %f`16+8*$i+4`, %f8, %f2, %f0 + aes_dround23 %f`16+8*$i+6`, %f8, %f2, %f2 + aes_dround01 %f`16+8*$i+4`, %f10, %f6, %f4 + aes_dround23 %f`16+8*$i+6`, %f10, %f6, %f6 +___ +} +$code.=<<___; + aes_dround01 %f56, %f0, %f2, %f8 + aes_dround23 %f58, %f0, %f2, %f2 + aes_dround01 %f56, %f4, %f6, %f10 + aes_dround23 %f58, %f4, %f6, %f6 + aes_dround01_l %f60, %f8, %f2, %f0 + aes_dround23_l %f62, %f8, %f2, %f2 + aes_dround01_l %f60, %f10, %f6, %f4 + retl + aes_dround23_l %f62, %f10, %f6, %f6 +.type _aes192_decrypt_2x,#function +.size _aes192_decrypt_2x,.-_aes192_decrypt_2x +___ +}}} + +if (!$::evp) { +$code.=<<___; +.global AES_encrypt +AES_encrypt=aes_t4_encrypt +.global AES_decrypt +AES_decrypt=aes_t4_decrypt +.global AES_set_encrypt_key +.align 32 +AES_set_encrypt_key: + andcc %o2, 7, %g0 ! check alignment + bnz,a,pn %icc, 1f + mov -1, %o0 + brz,a,pn %o0, 1f + mov -1, %o0 + brz,a,pn %o2, 1f + mov -1, %o0 + andncc %o1, 0x1c0, %g0 + bnz,a,pn %icc, 1f + mov -2, %o0 + cmp %o1, 128 + bl,a,pn %icc, 1f + mov -2, %o0 + b aes_t4_set_encrypt_key + nop +1: retl + nop +.type AES_set_encrypt_key,#function +.size AES_set_encrypt_key,.-AES_set_encrypt_key + +.global AES_set_decrypt_key +.align 32 +AES_set_decrypt_key: + andcc %o2, 7, %g0 ! check alignment + bnz,a,pn %icc, 1f + mov -1, %o0 + brz,a,pn %o0, 1f + mov -1, %o0 + brz,a,pn %o2, 1f + mov -1, %o0 + andncc %o1, 0x1c0, %g0 + bnz,a,pn %icc, 1f + mov -2, %o0 + cmp %o1, 128 + bl,a,pn %icc, 1f + mov -2, %o0 + b aes_t4_set_decrypt_key + nop +1: retl + nop +.type AES_set_decrypt_key,#function +.size AES_set_decrypt_key,.-AES_set_decrypt_key +___ + +my ($inp,$out,$len,$key,$ivec,$enc)=map("%o$_",(0..5)); + +$code.=<<___; +.globl AES_cbc_encrypt +.align 32 +AES_cbc_encrypt: + ld [$key + 240], %g1 + nop + brz $enc, .Lcbc_decrypt + cmp %g1, 12 + + bl,pt %icc, aes128_t4_cbc_encrypt + nop + be,pn %icc, aes192_t4_cbc_encrypt + nop + ba aes256_t4_cbc_encrypt + nop + +.Lcbc_decrypt: + bl,pt %icc, aes128_t4_cbc_decrypt + nop + be,pn %icc, aes192_t4_cbc_decrypt + nop + ba aes256_t4_cbc_decrypt + nop +.type AES_cbc_encrypt,#function +.size AES_cbc_encrypt,.-AES_cbc_encrypt +___ +} +$code.=<<___; +.asciz "AES for SPARC T4, David S. Miller, Andy Polyakov" +.align 4 +___ + +&emit_assembler(); + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesv8-armx.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesv8-armx.pl new file mode 100755 index 000000000..eec0ed230 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/aesv8-armx.pl @@ -0,0 +1,1011 @@ +#! /usr/bin/env perl +# Copyright 2014-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# This module implements support for ARMv8 AES instructions. The +# module is endian-agnostic in sense that it supports both big- and +# little-endian cases. As does it support both 32- and 64-bit modes +# of operation. Latter is achieved by limiting amount of utilized +# registers to 16, which implies additional NEON load and integer +# instructions. This has no effect on mighty Apple A7, where results +# are literally equal to the theoretical estimates based on AES +# instruction latencies and issue rates. On Cortex-A53, an in-order +# execution core, this costs up to 10-15%, which is partially +# compensated by implementing dedicated code path for 128-bit +# CBC encrypt case. On Cortex-A57 parallelizable mode performance +# seems to be limited by sheer amount of NEON instructions... +# +# Performance in cycles per byte processed with 128-bit key: +# +# CBC enc CBC dec CTR +# Apple A7 2.39 1.20 1.20 +# Cortex-A53 1.32 1.29 1.46 +# Cortex-A57(*) 1.95 0.85 0.93 +# Denver 1.96 0.86 0.80 +# Mongoose 1.33 1.20 1.20 +# Kryo 1.26 0.94 1.00 +# +# (*) original 3.64/1.34/1.32 results were for r0p0 revision +# and are still same even for updated module; + +$flavour = shift; +$output = shift; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or +die "can't locate arm-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +$prefix="aes_v8"; + +$code=<<___; +#include "arm_arch.h" + +#if __ARM_MAX_ARCH__>=7 +.text +___ +$code.=".arch armv8-a+crypto\n" if ($flavour =~ /64/); +$code.=<<___ if ($flavour !~ /64/); +.arch armv7-a // don't confuse not-so-latest binutils with argv8 :-) +.fpu neon +.code 32 +#undef __thumb2__ +___ + +# Assembler mnemonics are an eclectic mix of 32- and 64-bit syntax, +# NEON is mostly 32-bit mnemonics, integer - mostly 64. Goal is to +# maintain both 32- and 64-bit codes within single module and +# transliterate common code to either flavour with regex vodoo. +# +{{{ +my ($inp,$bits,$out,$ptr,$rounds)=("x0","w1","x2","x3","w12"); +my ($zero,$rcon,$mask,$in0,$in1,$tmp,$key)= + $flavour=~/64/? map("q$_",(0..6)) : map("q$_",(0..3,8..10)); + + +$code.=<<___; +.align 5 +.Lrcon: +.long 0x01,0x01,0x01,0x01 +.long 0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d // rotate-n-splat +.long 0x1b,0x1b,0x1b,0x1b + +.globl ${prefix}_set_encrypt_key +.type ${prefix}_set_encrypt_key,%function +.align 5 +${prefix}_set_encrypt_key: +.Lenc_key: +___ +$code.=<<___ if ($flavour =~ /64/); + stp x29,x30,[sp,#-16]! + add x29,sp,#0 +___ +$code.=<<___; + mov $ptr,#-1 + cmp $inp,#0 + b.eq .Lenc_key_abort + cmp $out,#0 + b.eq .Lenc_key_abort + mov $ptr,#-2 + cmp $bits,#128 + b.lt .Lenc_key_abort + cmp $bits,#256 + b.gt .Lenc_key_abort + tst $bits,#0x3f + b.ne .Lenc_key_abort + + adr $ptr,.Lrcon + cmp $bits,#192 + + veor $zero,$zero,$zero + vld1.8 {$in0},[$inp],#16 + mov $bits,#8 // reuse $bits + vld1.32 {$rcon,$mask},[$ptr],#32 + + b.lt .Loop128 + b.eq .L192 + b .L256 + +.align 4 +.Loop128: + vtbl.8 $key,{$in0},$mask + vext.8 $tmp,$zero,$in0,#12 + vst1.32 {$in0},[$out],#16 + aese $key,$zero + subs $bits,$bits,#1 + + veor $in0,$in0,$tmp + vext.8 $tmp,$zero,$tmp,#12 + veor $in0,$in0,$tmp + vext.8 $tmp,$zero,$tmp,#12 + veor $key,$key,$rcon + veor $in0,$in0,$tmp + vshl.u8 $rcon,$rcon,#1 + veor $in0,$in0,$key + b.ne .Loop128 + + vld1.32 {$rcon},[$ptr] + + vtbl.8 $key,{$in0},$mask + vext.8 $tmp,$zero,$in0,#12 + vst1.32 {$in0},[$out],#16 + aese $key,$zero + + veor $in0,$in0,$tmp + vext.8 $tmp,$zero,$tmp,#12 + veor $in0,$in0,$tmp + vext.8 $tmp,$zero,$tmp,#12 + veor $key,$key,$rcon + veor $in0,$in0,$tmp + vshl.u8 $rcon,$rcon,#1 + veor $in0,$in0,$key + + vtbl.8 $key,{$in0},$mask + vext.8 $tmp,$zero,$in0,#12 + vst1.32 {$in0},[$out],#16 + aese $key,$zero + + veor $in0,$in0,$tmp + vext.8 $tmp,$zero,$tmp,#12 + veor $in0,$in0,$tmp + vext.8 $tmp,$zero,$tmp,#12 + veor $key,$key,$rcon + veor $in0,$in0,$tmp + veor $in0,$in0,$key + vst1.32 {$in0},[$out] + add $out,$out,#0x50 + + mov $rounds,#10 + b .Ldone + +.align 4 +.L192: + vld1.8 {$in1},[$inp],#8 + vmov.i8 $key,#8 // borrow $key + vst1.32 {$in0},[$out],#16 + vsub.i8 $mask,$mask,$key // adjust the mask + +.Loop192: + vtbl.8 $key,{$in1},$mask + vext.8 $tmp,$zero,$in0,#12 + vst1.32 {$in1},[$out],#8 + aese $key,$zero + subs $bits,$bits,#1 + + veor $in0,$in0,$tmp + vext.8 $tmp,$zero,$tmp,#12 + veor $in0,$in0,$tmp + vext.8 $tmp,$zero,$tmp,#12 + veor $in0,$in0,$tmp + + vdup.32 $tmp,${in0}[3] + veor $tmp,$tmp,$in1 + veor $key,$key,$rcon + vext.8 $in1,$zero,$in1,#12 + vshl.u8 $rcon,$rcon,#1 + veor $in1,$in1,$tmp + veor $in0,$in0,$key + veor $in1,$in1,$key + vst1.32 {$in0},[$out],#16 + b.ne .Loop192 + + mov $rounds,#12 + add $out,$out,#0x20 + b .Ldone + +.align 4 +.L256: + vld1.8 {$in1},[$inp] + mov $bits,#7 + mov $rounds,#14 + vst1.32 {$in0},[$out],#16 + +.Loop256: + vtbl.8 $key,{$in1},$mask + vext.8 $tmp,$zero,$in0,#12 + vst1.32 {$in1},[$out],#16 + aese $key,$zero + subs $bits,$bits,#1 + + veor $in0,$in0,$tmp + vext.8 $tmp,$zero,$tmp,#12 + veor $in0,$in0,$tmp + vext.8 $tmp,$zero,$tmp,#12 + veor $key,$key,$rcon + veor $in0,$in0,$tmp + vshl.u8 $rcon,$rcon,#1 + veor $in0,$in0,$key + vst1.32 {$in0},[$out],#16 + b.eq .Ldone + + vdup.32 $key,${in0}[3] // just splat + vext.8 $tmp,$zero,$in1,#12 + aese $key,$zero + + veor $in1,$in1,$tmp + vext.8 $tmp,$zero,$tmp,#12 + veor $in1,$in1,$tmp + vext.8 $tmp,$zero,$tmp,#12 + veor $in1,$in1,$tmp + + veor $in1,$in1,$key + b .Loop256 + +.Ldone: + str $rounds,[$out] + mov $ptr,#0 + +.Lenc_key_abort: + mov x0,$ptr // return value + `"ldr x29,[sp],#16" if ($flavour =~ /64/)` + ret +.size ${prefix}_set_encrypt_key,.-${prefix}_set_encrypt_key + +.globl ${prefix}_set_decrypt_key +.type ${prefix}_set_decrypt_key,%function +.align 5 +${prefix}_set_decrypt_key: +___ +$code.=<<___ if ($flavour =~ /64/); + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-16]! + add x29,sp,#0 +___ +$code.=<<___ if ($flavour !~ /64/); + stmdb sp!,{r4,lr} +___ +$code.=<<___; + bl .Lenc_key + + cmp x0,#0 + b.ne .Ldec_key_abort + + sub $out,$out,#240 // restore original $out + mov x4,#-16 + add $inp,$out,x12,lsl#4 // end of key schedule + + vld1.32 {v0.16b},[$out] + vld1.32 {v1.16b},[$inp] + vst1.32 {v0.16b},[$inp],x4 + vst1.32 {v1.16b},[$out],#16 + +.Loop_imc: + vld1.32 {v0.16b},[$out] + vld1.32 {v1.16b},[$inp] + aesimc v0.16b,v0.16b + aesimc v1.16b,v1.16b + vst1.32 {v0.16b},[$inp],x4 + vst1.32 {v1.16b},[$out],#16 + cmp $inp,$out + b.hi .Loop_imc + + vld1.32 {v0.16b},[$out] + aesimc v0.16b,v0.16b + vst1.32 {v0.16b},[$inp] + + eor x0,x0,x0 // return value +.Ldec_key_abort: +___ +$code.=<<___ if ($flavour !~ /64/); + ldmia sp!,{r4,pc} +___ +$code.=<<___ if ($flavour =~ /64/); + ldp x29,x30,[sp],#16 + .inst 0xd50323bf // autiasp + ret +___ +$code.=<<___; +.size ${prefix}_set_decrypt_key,.-${prefix}_set_decrypt_key +___ +}}} +{{{ +sub gen_block () { +my $dir = shift; +my ($e,$mc) = $dir eq "en" ? ("e","mc") : ("d","imc"); +my ($inp,$out,$key)=map("x$_",(0..2)); +my $rounds="w3"; +my ($rndkey0,$rndkey1,$inout)=map("q$_",(0..3)); + +$code.=<<___; +.globl ${prefix}_${dir}crypt +.type ${prefix}_${dir}crypt,%function +.align 5 +${prefix}_${dir}crypt: + ldr $rounds,[$key,#240] + vld1.32 {$rndkey0},[$key],#16 + vld1.8 {$inout},[$inp] + sub $rounds,$rounds,#2 + vld1.32 {$rndkey1},[$key],#16 + +.Loop_${dir}c: + aes$e $inout,$rndkey0 + aes$mc $inout,$inout + vld1.32 {$rndkey0},[$key],#16 + subs $rounds,$rounds,#2 + aes$e $inout,$rndkey1 + aes$mc $inout,$inout + vld1.32 {$rndkey1},[$key],#16 + b.gt .Loop_${dir}c + + aes$e $inout,$rndkey0 + aes$mc $inout,$inout + vld1.32 {$rndkey0},[$key] + aes$e $inout,$rndkey1 + veor $inout,$inout,$rndkey0 + + vst1.8 {$inout},[$out] + ret +.size ${prefix}_${dir}crypt,.-${prefix}_${dir}crypt +___ +} +&gen_block("en"); +&gen_block("de"); +}}} +{{{ +my ($inp,$out,$len,$key,$ivp)=map("x$_",(0..4)); my $enc="w5"; +my ($rounds,$cnt,$key_,$step,$step1)=($enc,"w6","x7","x8","x12"); +my ($dat0,$dat1,$in0,$in1,$tmp0,$tmp1,$ivec,$rndlast)=map("q$_",(0..7)); + +my ($dat,$tmp,$rndzero_n_last)=($dat0,$tmp0,$tmp1); +my ($key4,$key5,$key6,$key7)=("x6","x12","x14",$key); + +### q8-q15 preloaded key schedule + +$code.=<<___; +.globl ${prefix}_cbc_encrypt +.type ${prefix}_cbc_encrypt,%function +.align 5 +${prefix}_cbc_encrypt: +___ +$code.=<<___ if ($flavour =~ /64/); + stp x29,x30,[sp,#-16]! + add x29,sp,#0 +___ +$code.=<<___ if ($flavour !~ /64/); + mov ip,sp + stmdb sp!,{r4-r8,lr} + vstmdb sp!,{d8-d15} @ ABI specification says so + ldmia ip,{r4-r5} @ load remaining args +___ +$code.=<<___; + subs $len,$len,#16 + mov $step,#16 + b.lo .Lcbc_abort + cclr $step,eq + + cmp $enc,#0 // en- or decrypting? + ldr $rounds,[$key,#240] + and $len,$len,#-16 + vld1.8 {$ivec},[$ivp] + vld1.8 {$dat},[$inp],$step + + vld1.32 {q8-q9},[$key] // load key schedule... + sub $rounds,$rounds,#6 + add $key_,$key,x5,lsl#4 // pointer to last 7 round keys + sub $rounds,$rounds,#2 + vld1.32 {q10-q11},[$key_],#32 + vld1.32 {q12-q13},[$key_],#32 + vld1.32 {q14-q15},[$key_],#32 + vld1.32 {$rndlast},[$key_] + + add $key_,$key,#32 + mov $cnt,$rounds + b.eq .Lcbc_dec + + cmp $rounds,#2 + veor $dat,$dat,$ivec + veor $rndzero_n_last,q8,$rndlast + b.eq .Lcbc_enc128 + + vld1.32 {$in0-$in1},[$key_] + add $key_,$key,#16 + add $key4,$key,#16*4 + add $key5,$key,#16*5 + aese $dat,q8 + aesmc $dat,$dat + add $key6,$key,#16*6 + add $key7,$key,#16*7 + b .Lenter_cbc_enc + +.align 4 +.Loop_cbc_enc: + aese $dat,q8 + aesmc $dat,$dat + vst1.8 {$ivec},[$out],#16 +.Lenter_cbc_enc: + aese $dat,q9 + aesmc $dat,$dat + aese $dat,$in0 + aesmc $dat,$dat + vld1.32 {q8},[$key4] + cmp $rounds,#4 + aese $dat,$in1 + aesmc $dat,$dat + vld1.32 {q9},[$key5] + b.eq .Lcbc_enc192 + + aese $dat,q8 + aesmc $dat,$dat + vld1.32 {q8},[$key6] + aese $dat,q9 + aesmc $dat,$dat + vld1.32 {q9},[$key7] + nop + +.Lcbc_enc192: + aese $dat,q8 + aesmc $dat,$dat + subs $len,$len,#16 + aese $dat,q9 + aesmc $dat,$dat + cclr $step,eq + aese $dat,q10 + aesmc $dat,$dat + aese $dat,q11 + aesmc $dat,$dat + vld1.8 {q8},[$inp],$step + aese $dat,q12 + aesmc $dat,$dat + veor q8,q8,$rndzero_n_last + aese $dat,q13 + aesmc $dat,$dat + vld1.32 {q9},[$key_] // re-pre-load rndkey[1] + aese $dat,q14 + aesmc $dat,$dat + aese $dat,q15 + veor $ivec,$dat,$rndlast + b.hs .Loop_cbc_enc + + vst1.8 {$ivec},[$out],#16 + b .Lcbc_done + +.align 5 +.Lcbc_enc128: + vld1.32 {$in0-$in1},[$key_] + aese $dat,q8 + aesmc $dat,$dat + b .Lenter_cbc_enc128 +.Loop_cbc_enc128: + aese $dat,q8 + aesmc $dat,$dat + vst1.8 {$ivec},[$out],#16 +.Lenter_cbc_enc128: + aese $dat,q9 + aesmc $dat,$dat + subs $len,$len,#16 + aese $dat,$in0 + aesmc $dat,$dat + cclr $step,eq + aese $dat,$in1 + aesmc $dat,$dat + aese $dat,q10 + aesmc $dat,$dat + aese $dat,q11 + aesmc $dat,$dat + vld1.8 {q8},[$inp],$step + aese $dat,q12 + aesmc $dat,$dat + aese $dat,q13 + aesmc $dat,$dat + aese $dat,q14 + aesmc $dat,$dat + veor q8,q8,$rndzero_n_last + aese $dat,q15 + veor $ivec,$dat,$rndlast + b.hs .Loop_cbc_enc128 + + vst1.8 {$ivec},[$out],#16 + b .Lcbc_done +___ +{ +my ($dat2,$in2,$tmp2)=map("q$_",(10,11,9)); +$code.=<<___; +.align 5 +.Lcbc_dec: + vld1.8 {$dat2},[$inp],#16 + subs $len,$len,#32 // bias + add $cnt,$rounds,#2 + vorr $in1,$dat,$dat + vorr $dat1,$dat,$dat + vorr $in2,$dat2,$dat2 + b.lo .Lcbc_dec_tail + + vorr $dat1,$dat2,$dat2 + vld1.8 {$dat2},[$inp],#16 + vorr $in0,$dat,$dat + vorr $in1,$dat1,$dat1 + vorr $in2,$dat2,$dat2 + +.Loop3x_cbc_dec: + aesd $dat0,q8 + aesimc $dat0,$dat0 + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + vld1.32 {q8},[$key_],#16 + subs $cnt,$cnt,#2 + aesd $dat0,q9 + aesimc $dat0,$dat0 + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + vld1.32 {q9},[$key_],#16 + b.gt .Loop3x_cbc_dec + + aesd $dat0,q8 + aesimc $dat0,$dat0 + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + veor $tmp0,$ivec,$rndlast + subs $len,$len,#0x30 + veor $tmp1,$in0,$rndlast + mov.lo x6,$len // x6, $cnt, is zero at this point + aesd $dat0,q9 + aesimc $dat0,$dat0 + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + veor $tmp2,$in1,$rndlast + add $inp,$inp,x6 // $inp is adjusted in such way that + // at exit from the loop $dat1-$dat2 + // are loaded with last "words" + vorr $ivec,$in2,$in2 + mov $key_,$key + aesd $dat0,q12 + aesimc $dat0,$dat0 + aesd $dat1,q12 + aesimc $dat1,$dat1 + aesd $dat2,q12 + aesimc $dat2,$dat2 + vld1.8 {$in0},[$inp],#16 + aesd $dat0,q13 + aesimc $dat0,$dat0 + aesd $dat1,q13 + aesimc $dat1,$dat1 + aesd $dat2,q13 + aesimc $dat2,$dat2 + vld1.8 {$in1},[$inp],#16 + aesd $dat0,q14 + aesimc $dat0,$dat0 + aesd $dat1,q14 + aesimc $dat1,$dat1 + aesd $dat2,q14 + aesimc $dat2,$dat2 + vld1.8 {$in2},[$inp],#16 + aesd $dat0,q15 + aesd $dat1,q15 + aesd $dat2,q15 + vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0] + add $cnt,$rounds,#2 + veor $tmp0,$tmp0,$dat0 + veor $tmp1,$tmp1,$dat1 + veor $dat2,$dat2,$tmp2 + vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1] + vst1.8 {$tmp0},[$out],#16 + vorr $dat0,$in0,$in0 + vst1.8 {$tmp1},[$out],#16 + vorr $dat1,$in1,$in1 + vst1.8 {$dat2},[$out],#16 + vorr $dat2,$in2,$in2 + b.hs .Loop3x_cbc_dec + + cmn $len,#0x30 + b.eq .Lcbc_done + nop + +.Lcbc_dec_tail: + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + vld1.32 {q8},[$key_],#16 + subs $cnt,$cnt,#2 + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + vld1.32 {q9},[$key_],#16 + b.gt .Lcbc_dec_tail + + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + aesd $dat1,q12 + aesimc $dat1,$dat1 + aesd $dat2,q12 + aesimc $dat2,$dat2 + cmn $len,#0x20 + aesd $dat1,q13 + aesimc $dat1,$dat1 + aesd $dat2,q13 + aesimc $dat2,$dat2 + veor $tmp1,$ivec,$rndlast + aesd $dat1,q14 + aesimc $dat1,$dat1 + aesd $dat2,q14 + aesimc $dat2,$dat2 + veor $tmp2,$in1,$rndlast + aesd $dat1,q15 + aesd $dat2,q15 + b.eq .Lcbc_dec_one + veor $tmp1,$tmp1,$dat1 + veor $tmp2,$tmp2,$dat2 + vorr $ivec,$in2,$in2 + vst1.8 {$tmp1},[$out],#16 + vst1.8 {$tmp2},[$out],#16 + b .Lcbc_done + +.Lcbc_dec_one: + veor $tmp1,$tmp1,$dat2 + vorr $ivec,$in2,$in2 + vst1.8 {$tmp1},[$out],#16 + +.Lcbc_done: + vst1.8 {$ivec},[$ivp] +.Lcbc_abort: +___ +} +$code.=<<___ if ($flavour !~ /64/); + vldmia sp!,{d8-d15} + ldmia sp!,{r4-r8,pc} +___ +$code.=<<___ if ($flavour =~ /64/); + ldr x29,[sp],#16 + ret +___ +$code.=<<___; +.size ${prefix}_cbc_encrypt,.-${prefix}_cbc_encrypt +___ +}}} +{{{ +my ($inp,$out,$len,$key,$ivp)=map("x$_",(0..4)); +my ($rounds,$cnt,$key_)=("w5","w6","x7"); +my ($ctr,$tctr0,$tctr1,$tctr2)=map("w$_",(8..10,12)); +my $step="x12"; # aliases with $tctr2 + +my ($dat0,$dat1,$in0,$in1,$tmp0,$tmp1,$ivec,$rndlast)=map("q$_",(0..7)); +my ($dat2,$in2,$tmp2)=map("q$_",(10,11,9)); + +my ($dat,$tmp)=($dat0,$tmp0); + +### q8-q15 preloaded key schedule + +$code.=<<___; +.globl ${prefix}_ctr32_encrypt_blocks +.type ${prefix}_ctr32_encrypt_blocks,%function +.align 5 +${prefix}_ctr32_encrypt_blocks: +___ +$code.=<<___ if ($flavour =~ /64/); + stp x29,x30,[sp,#-16]! + add x29,sp,#0 +___ +$code.=<<___ if ($flavour !~ /64/); + mov ip,sp + stmdb sp!,{r4-r10,lr} + vstmdb sp!,{d8-d15} @ ABI specification says so + ldr r4, [ip] @ load remaining arg +___ +$code.=<<___; + ldr $rounds,[$key,#240] + + ldr $ctr, [$ivp, #12] + vld1.32 {$dat0},[$ivp] + + vld1.32 {q8-q9},[$key] // load key schedule... + sub $rounds,$rounds,#4 + mov $step,#16 + cmp $len,#2 + add $key_,$key,x5,lsl#4 // pointer to last 5 round keys + sub $rounds,$rounds,#2 + vld1.32 {q12-q13},[$key_],#32 + vld1.32 {q14-q15},[$key_],#32 + vld1.32 {$rndlast},[$key_] + add $key_,$key,#32 + mov $cnt,$rounds + cclr $step,lo +#ifndef __ARMEB__ + rev $ctr, $ctr +#endif + vorr $dat1,$dat0,$dat0 + add $tctr1, $ctr, #1 + vorr $dat2,$dat0,$dat0 + add $ctr, $ctr, #2 + vorr $ivec,$dat0,$dat0 + rev $tctr1, $tctr1 + vmov.32 ${dat1}[3],$tctr1 + b.ls .Lctr32_tail + rev $tctr2, $ctr + sub $len,$len,#3 // bias + vmov.32 ${dat2}[3],$tctr2 + b .Loop3x_ctr32 + +.align 4 +.Loop3x_ctr32: + aese $dat0,q8 + aesmc $dat0,$dat0 + aese $dat1,q8 + aesmc $dat1,$dat1 + aese $dat2,q8 + aesmc $dat2,$dat2 + vld1.32 {q8},[$key_],#16 + subs $cnt,$cnt,#2 + aese $dat0,q9 + aesmc $dat0,$dat0 + aese $dat1,q9 + aesmc $dat1,$dat1 + aese $dat2,q9 + aesmc $dat2,$dat2 + vld1.32 {q9},[$key_],#16 + b.gt .Loop3x_ctr32 + + aese $dat0,q8 + aesmc $tmp0,$dat0 + aese $dat1,q8 + aesmc $tmp1,$dat1 + vld1.8 {$in0},[$inp],#16 + vorr $dat0,$ivec,$ivec + aese $dat2,q8 + aesmc $dat2,$dat2 + vld1.8 {$in1},[$inp],#16 + vorr $dat1,$ivec,$ivec + aese $tmp0,q9 + aesmc $tmp0,$tmp0 + aese $tmp1,q9 + aesmc $tmp1,$tmp1 + vld1.8 {$in2},[$inp],#16 + mov $key_,$key + aese $dat2,q9 + aesmc $tmp2,$dat2 + vorr $dat2,$ivec,$ivec + add $tctr0,$ctr,#1 + aese $tmp0,q12 + aesmc $tmp0,$tmp0 + aese $tmp1,q12 + aesmc $tmp1,$tmp1 + veor $in0,$in0,$rndlast + add $tctr1,$ctr,#2 + aese $tmp2,q12 + aesmc $tmp2,$tmp2 + veor $in1,$in1,$rndlast + add $ctr,$ctr,#3 + aese $tmp0,q13 + aesmc $tmp0,$tmp0 + aese $tmp1,q13 + aesmc $tmp1,$tmp1 + veor $in2,$in2,$rndlast + rev $tctr0,$tctr0 + aese $tmp2,q13 + aesmc $tmp2,$tmp2 + vmov.32 ${dat0}[3], $tctr0 + rev $tctr1,$tctr1 + aese $tmp0,q14 + aesmc $tmp0,$tmp0 + aese $tmp1,q14 + aesmc $tmp1,$tmp1 + vmov.32 ${dat1}[3], $tctr1 + rev $tctr2,$ctr + aese $tmp2,q14 + aesmc $tmp2,$tmp2 + vmov.32 ${dat2}[3], $tctr2 + subs $len,$len,#3 + aese $tmp0,q15 + aese $tmp1,q15 + aese $tmp2,q15 + + veor $in0,$in0,$tmp0 + vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0] + vst1.8 {$in0},[$out],#16 + veor $in1,$in1,$tmp1 + mov $cnt,$rounds + vst1.8 {$in1},[$out],#16 + veor $in2,$in2,$tmp2 + vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1] + vst1.8 {$in2},[$out],#16 + b.hs .Loop3x_ctr32 + + adds $len,$len,#3 + b.eq .Lctr32_done + cmp $len,#1 + mov $step,#16 + cclr $step,eq + +.Lctr32_tail: + aese $dat0,q8 + aesmc $dat0,$dat0 + aese $dat1,q8 + aesmc $dat1,$dat1 + vld1.32 {q8},[$key_],#16 + subs $cnt,$cnt,#2 + aese $dat0,q9 + aesmc $dat0,$dat0 + aese $dat1,q9 + aesmc $dat1,$dat1 + vld1.32 {q9},[$key_],#16 + b.gt .Lctr32_tail + + aese $dat0,q8 + aesmc $dat0,$dat0 + aese $dat1,q8 + aesmc $dat1,$dat1 + aese $dat0,q9 + aesmc $dat0,$dat0 + aese $dat1,q9 + aesmc $dat1,$dat1 + vld1.8 {$in0},[$inp],$step + aese $dat0,q12 + aesmc $dat0,$dat0 + aese $dat1,q12 + aesmc $dat1,$dat1 + vld1.8 {$in1},[$inp] + aese $dat0,q13 + aesmc $dat0,$dat0 + aese $dat1,q13 + aesmc $dat1,$dat1 + veor $in0,$in0,$rndlast + aese $dat0,q14 + aesmc $dat0,$dat0 + aese $dat1,q14 + aesmc $dat1,$dat1 + veor $in1,$in1,$rndlast + aese $dat0,q15 + aese $dat1,q15 + + cmp $len,#1 + veor $in0,$in0,$dat0 + veor $in1,$in1,$dat1 + vst1.8 {$in0},[$out],#16 + b.eq .Lctr32_done + vst1.8 {$in1},[$out] + +.Lctr32_done: +___ +$code.=<<___ if ($flavour !~ /64/); + vldmia sp!,{d8-d15} + ldmia sp!,{r4-r10,pc} +___ +$code.=<<___ if ($flavour =~ /64/); + ldr x29,[sp],#16 + ret +___ +$code.=<<___; +.size ${prefix}_ctr32_encrypt_blocks,.-${prefix}_ctr32_encrypt_blocks +___ +}}} +$code.=<<___; +#endif +___ +######################################## +if ($flavour =~ /64/) { ######## 64-bit code + my %opcode = ( + "aesd" => 0x4e285800, "aese" => 0x4e284800, + "aesimc"=> 0x4e287800, "aesmc" => 0x4e286800 ); + + local *unaes = sub { + my ($mnemonic,$arg)=@_; + + $arg =~ m/[qv]([0-9]+)[^,]*,\s*[qv]([0-9]+)/o && + sprintf ".inst\t0x%08x\t//%s %s", + $opcode{$mnemonic}|$1|($2<<5), + $mnemonic,$arg; + }; + + foreach(split("\n",$code)) { + s/\`([^\`]*)\`/eval($1)/geo; + + s/\bq([0-9]+)\b/"v".($1<8?$1:$1+8).".16b"/geo; # old->new registers + s/@\s/\/\//o; # old->new style commentary + + #s/[v]?(aes\w+)\s+([qv].*)/unaes($1,$2)/geo or + s/cclr\s+([wx])([^,]+),\s*([a-z]+)/csel $1$2,$1zr,$1$2,$3/o or + s/mov\.([a-z]+)\s+([wx][0-9]+),\s*([wx][0-9]+)/csel $2,$3,$2,$1/o or + s/vmov\.i8/movi/o or # fix up legacy mnemonics + s/vext\.8/ext/o or + s/vrev32\.8/rev32/o or + s/vtst\.8/cmtst/o or + s/vshr/ushr/o or + s/^(\s+)v/$1/o or # strip off v prefix + s/\bbx\s+lr\b/ret/o; + + # fix up remaining legacy suffixes + s/\.[ui]?8//o; + m/\],#8/o and s/\.16b/\.8b/go; + s/\.[ui]?32//o and s/\.16b/\.4s/go; + s/\.[ui]?64//o and s/\.16b/\.2d/go; + s/\.[42]([sd])\[([0-3])\]/\.$1\[$2\]/o; + + print $_,"\n"; + } +} else { ######## 32-bit code + my %opcode = ( + "aesd" => 0xf3b00340, "aese" => 0xf3b00300, + "aesimc"=> 0xf3b003c0, "aesmc" => 0xf3b00380 ); + + local *unaes = sub { + my ($mnemonic,$arg)=@_; + + if ($arg =~ m/[qv]([0-9]+)[^,]*,\s*[qv]([0-9]+)/o) { + my $word = $opcode{$mnemonic}|(($1&7)<<13)|(($1&8)<<19) + |(($2&7)<<1) |(($2&8)<<2); + # since ARMv7 instructions are always encoded little-endian. + # correct solution is to use .inst directive, but older + # assemblers don't implement it:-( + sprintf ".byte\t0x%02x,0x%02x,0x%02x,0x%02x\t@ %s %s", + $word&0xff,($word>>8)&0xff, + ($word>>16)&0xff,($word>>24)&0xff, + $mnemonic,$arg; + } + }; + + sub unvtbl { + my $arg=shift; + + $arg =~ m/q([0-9]+),\s*\{q([0-9]+)\},\s*q([0-9]+)/o && + sprintf "vtbl.8 d%d,{q%d},d%d\n\t". + "vtbl.8 d%d,{q%d},d%d", 2*$1,$2,2*$3, 2*$1+1,$2,2*$3+1; + } + + sub unvdup32 { + my $arg=shift; + + $arg =~ m/q([0-9]+),\s*q([0-9]+)\[([0-3])\]/o && + sprintf "vdup.32 q%d,d%d[%d]",$1,2*$2+($3>>1),$3&1; + } + + sub unvmov32 { + my $arg=shift; + + $arg =~ m/q([0-9]+)\[([0-3])\],(.*)/o && + sprintf "vmov.32 d%d[%d],%s",2*$1+($2>>1),$2&1,$3; + } + + foreach(split("\n",$code)) { + s/\`([^\`]*)\`/eval($1)/geo; + + s/\b[wx]([0-9]+)\b/r$1/go; # new->old registers + s/\bv([0-9])\.[12468]+[bsd]\b/q$1/go; # new->old registers + s/\/\/\s?/@ /o; # new->old style commentary + + # fix up remaining new-style suffixes + s/\{q([0-9]+)\},\s*\[(.+)\],#8/sprintf "{d%d},[$2]!",2*$1/eo or + s/\],#[0-9]+/]!/o; + + s/[v]?(aes\w+)\s+([qv].*)/unaes($1,$2)/geo or + s/cclr\s+([^,]+),\s*([a-z]+)/mov$2 $1,#0/o or + s/vtbl\.8\s+(.*)/unvtbl($1)/geo or + s/vdup\.32\s+(.*)/unvdup32($1)/geo or + s/vmov\.32\s+(.*)/unvmov32($1)/geo or + s/^(\s+)b\./$1b/o or + s/^(\s+)mov\./$1mov/o or + s/^(\s+)ret/$1bx\tlr/o; + + print $_,"\n"; + } +} + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/bsaes-armv7.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/bsaes-armv7.pl new file mode 100644 index 000000000..bfe825af0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/bsaes-armv7.pl @@ -0,0 +1,2491 @@ +#! /usr/bin/env perl +# Copyright 2012-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# +# Specific modes and adaptation for Linux kernel by Ard Biesheuvel +# of Linaro. Permission to use under GPL terms is granted. +# ==================================================================== + +# Bit-sliced AES for ARM NEON +# +# February 2012. +# +# This implementation is direct adaptation of bsaes-x86_64 module for +# ARM NEON. Except that this module is endian-neutral [in sense that +# it can be compiled for either endianness] by courtesy of vld1.8's +# neutrality. Initial version doesn't implement interface to OpenSSL, +# only low-level primitives and unsupported entry points, just enough +# to collect performance results, which for Cortex-A8 core are: +# +# encrypt 19.5 cycles per byte processed with 128-bit key +# decrypt 22.1 cycles per byte processed with 128-bit key +# key conv. 440 cycles per 128-bit key/0.18 of 8x block +# +# Snapdragon S4 encrypts byte in 17.6 cycles and decrypts in 19.7, +# which is [much] worse than anticipated (for further details see +# http://www.openssl.org/~appro/Snapdragon-S4.html). +# +# Cortex-A15 manages in 14.2/16.1 cycles [when integer-only code +# manages in 20.0 cycles]. +# +# When comparing to x86_64 results keep in mind that NEON unit is +# [mostly] single-issue and thus can't [fully] benefit from +# instruction-level parallelism. And when comparing to aes-armv4 +# results keep in mind key schedule conversion overhead (see +# bsaes-x86_64.pl for further details)... +# +# + +# April-August 2013 +# Add CBC, CTR and XTS subroutines and adapt for kernel use; courtesy of Ard. + +$flavour = shift; +if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + open STDOUT,">$output"; +} + +my ($inp,$out,$len,$key)=("r0","r1","r2","r3"); +my @XMM=map("q$_",(0..15)); + +{ +my ($key,$rounds,$const)=("r4","r5","r6"); + +sub Dlo() { shift=~m|q([1]?[0-9])|?"d".($1*2):""; } +sub Dhi() { shift=~m|q([1]?[0-9])|?"d".($1*2+1):""; } + +sub Sbox { +# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb +# output in lsb > [b0, b1, b4, b6, b3, b7, b2, b5] < msb +my @b=@_[0..7]; +my @t=@_[8..11]; +my @s=@_[12..15]; + &InBasisChange (@b); + &Inv_GF256 (@b[6,5,0,3,7,1,4,2],@t,@s); + &OutBasisChange (@b[7,1,4,2,6,5,0,3]); +} + +sub InBasisChange { +# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb +# output in lsb > [b6, b5, b0, b3, b7, b1, b4, b2] < msb +my @b=@_[0..7]; +$code.=<<___; + veor @b[2], @b[2], @b[1] + veor @b[5], @b[5], @b[6] + veor @b[3], @b[3], @b[0] + veor @b[6], @b[6], @b[2] + veor @b[5], @b[5], @b[0] + + veor @b[6], @b[6], @b[3] + veor @b[3], @b[3], @b[7] + veor @b[7], @b[7], @b[5] + veor @b[3], @b[3], @b[4] + veor @b[4], @b[4], @b[5] + + veor @b[2], @b[2], @b[7] + veor @b[3], @b[3], @b[1] + veor @b[1], @b[1], @b[5] +___ +} + +sub OutBasisChange { +# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb +# output in lsb > [b6, b1, b2, b4, b7, b0, b3, b5] < msb +my @b=@_[0..7]; +$code.=<<___; + veor @b[0], @b[0], @b[6] + veor @b[1], @b[1], @b[4] + veor @b[4], @b[4], @b[6] + veor @b[2], @b[2], @b[0] + veor @b[6], @b[6], @b[1] + + veor @b[1], @b[1], @b[5] + veor @b[5], @b[5], @b[3] + veor @b[3], @b[3], @b[7] + veor @b[7], @b[7], @b[5] + veor @b[2], @b[2], @b[5] + + veor @b[4], @b[4], @b[7] +___ +} + +sub InvSbox { +# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb +# output in lsb > [b0, b1, b6, b4, b2, b7, b3, b5] < msb +my @b=@_[0..7]; +my @t=@_[8..11]; +my @s=@_[12..15]; + &InvInBasisChange (@b); + &Inv_GF256 (@b[5,1,2,6,3,7,0,4],@t,@s); + &InvOutBasisChange (@b[3,7,0,4,5,1,2,6]); +} + +sub InvInBasisChange { # OutBasisChange in reverse (with twist) +my @b=@_[5,1,2,6,3,7,0,4]; +$code.=<<___ + veor @b[1], @b[1], @b[7] + veor @b[4], @b[4], @b[7] + + veor @b[7], @b[7], @b[5] + veor @b[1], @b[1], @b[3] + veor @b[2], @b[2], @b[5] + veor @b[3], @b[3], @b[7] + + veor @b[6], @b[6], @b[1] + veor @b[2], @b[2], @b[0] + veor @b[5], @b[5], @b[3] + veor @b[4], @b[4], @b[6] + veor @b[0], @b[0], @b[6] + veor @b[1], @b[1], @b[4] +___ +} + +sub InvOutBasisChange { # InBasisChange in reverse +my @b=@_[2,5,7,3,6,1,0,4]; +$code.=<<___; + veor @b[1], @b[1], @b[5] + veor @b[2], @b[2], @b[7] + + veor @b[3], @b[3], @b[1] + veor @b[4], @b[4], @b[5] + veor @b[7], @b[7], @b[5] + veor @b[3], @b[3], @b[4] + veor @b[5], @b[5], @b[0] + veor @b[3], @b[3], @b[7] + veor @b[6], @b[6], @b[2] + veor @b[2], @b[2], @b[1] + veor @b[6], @b[6], @b[3] + + veor @b[3], @b[3], @b[0] + veor @b[5], @b[5], @b[6] +___ +} + +sub Mul_GF4 { +#;************************************************************* +#;* Mul_GF4: Input x0-x1,y0-y1 Output x0-x1 Temp t0 (8) * +#;************************************************************* +my ($x0,$x1,$y0,$y1,$t0,$t1)=@_; +$code.=<<___; + veor $t0, $y0, $y1 + vand $t0, $t0, $x0 + veor $x0, $x0, $x1 + vand $t1, $x1, $y0 + vand $x0, $x0, $y1 + veor $x1, $t1, $t0 + veor $x0, $x0, $t1 +___ +} + +sub Mul_GF4_N { # not used, see next subroutine +# multiply and scale by N +my ($x0,$x1,$y0,$y1,$t0)=@_; +$code.=<<___; + veor $t0, $y0, $y1 + vand $t0, $t0, $x0 + veor $x0, $x0, $x1 + vand $x1, $x1, $y0 + vand $x0, $x0, $y1 + veor $x1, $x1, $x0 + veor $x0, $x0, $t0 +___ +} + +sub Mul_GF4_N_GF4 { +# interleaved Mul_GF4_N and Mul_GF4 +my ($x0,$x1,$y0,$y1,$t0, + $x2,$x3,$y2,$y3,$t1)=@_; +$code.=<<___; + veor $t0, $y0, $y1 + veor $t1, $y2, $y3 + vand $t0, $t0, $x0 + vand $t1, $t1, $x2 + veor $x0, $x0, $x1 + veor $x2, $x2, $x3 + vand $x1, $x1, $y0 + vand $x3, $x3, $y2 + vand $x0, $x0, $y1 + vand $x2, $x2, $y3 + veor $x1, $x1, $x0 + veor $x2, $x2, $x3 + veor $x0, $x0, $t0 + veor $x3, $x3, $t1 +___ +} +sub Mul_GF16_2 { +my @x=@_[0..7]; +my @y=@_[8..11]; +my @t=@_[12..15]; +$code.=<<___; + veor @t[0], @x[0], @x[2] + veor @t[1], @x[1], @x[3] +___ + &Mul_GF4 (@x[0], @x[1], @y[0], @y[1], @t[2..3]); +$code.=<<___; + veor @y[0], @y[0], @y[2] + veor @y[1], @y[1], @y[3] +___ + Mul_GF4_N_GF4 (@t[0], @t[1], @y[0], @y[1], @t[3], + @x[2], @x[3], @y[2], @y[3], @t[2]); +$code.=<<___; + veor @x[0], @x[0], @t[0] + veor @x[2], @x[2], @t[0] + veor @x[1], @x[1], @t[1] + veor @x[3], @x[3], @t[1] + + veor @t[0], @x[4], @x[6] + veor @t[1], @x[5], @x[7] +___ + &Mul_GF4_N_GF4 (@t[0], @t[1], @y[0], @y[1], @t[3], + @x[6], @x[7], @y[2], @y[3], @t[2]); +$code.=<<___; + veor @y[0], @y[0], @y[2] + veor @y[1], @y[1], @y[3] +___ + &Mul_GF4 (@x[4], @x[5], @y[0], @y[1], @t[2..3]); +$code.=<<___; + veor @x[4], @x[4], @t[0] + veor @x[6], @x[6], @t[0] + veor @x[5], @x[5], @t[1] + veor @x[7], @x[7], @t[1] +___ +} +sub Inv_GF256 { +#;******************************************************************** +#;* Inv_GF256: Input x0-x7 Output x0-x7 Temp t0-t3,s0-s3 (144) * +#;******************************************************************** +my @x=@_[0..7]; +my @t=@_[8..11]; +my @s=@_[12..15]; +# direct optimizations from hardware +$code.=<<___; + veor @t[3], @x[4], @x[6] + veor @t[2], @x[5], @x[7] + veor @t[1], @x[1], @x[3] + veor @s[1], @x[7], @x[6] + vmov @t[0], @t[2] + veor @s[0], @x[0], @x[2] + + vorr @t[2], @t[2], @t[1] + veor @s[3], @t[3], @t[0] + vand @s[2], @t[3], @s[0] + vorr @t[3], @t[3], @s[0] + veor @s[0], @s[0], @t[1] + vand @t[0], @t[0], @t[1] + veor @t[1], @x[3], @x[2] + vand @s[3], @s[3], @s[0] + vand @s[1], @s[1], @t[1] + veor @t[1], @x[4], @x[5] + veor @s[0], @x[1], @x[0] + veor @t[3], @t[3], @s[1] + veor @t[2], @t[2], @s[1] + vand @s[1], @t[1], @s[0] + vorr @t[1], @t[1], @s[0] + veor @t[3], @t[3], @s[3] + veor @t[0], @t[0], @s[1] + veor @t[2], @t[2], @s[2] + veor @t[1], @t[1], @s[3] + veor @t[0], @t[0], @s[2] + vand @s[0], @x[7], @x[3] + veor @t[1], @t[1], @s[2] + vand @s[1], @x[6], @x[2] + vand @s[2], @x[5], @x[1] + vorr @s[3], @x[4], @x[0] + veor @t[3], @t[3], @s[0] + veor @t[1], @t[1], @s[2] + veor @t[0], @t[0], @s[3] + veor @t[2], @t[2], @s[1] + + @ Inv_GF16 \t0, \t1, \t2, \t3, \s0, \s1, \s2, \s3 + + @ new smaller inversion + + vand @s[2], @t[3], @t[1] + vmov @s[0], @t[0] + + veor @s[1], @t[2], @s[2] + veor @s[3], @t[0], @s[2] + veor @s[2], @t[0], @s[2] @ @s[2]=@s[3] + + vbsl @s[1], @t[1], @t[0] + vbsl @s[3], @t[3], @t[2] + veor @t[3], @t[3], @t[2] + + vbsl @s[0], @s[1], @s[2] + vbsl @t[0], @s[2], @s[1] + + vand @s[2], @s[0], @s[3] + veor @t[1], @t[1], @t[0] + + veor @s[2], @s[2], @t[3] +___ +# output in s3, s2, s1, t1 + +# Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \t2, \t3, \t0, \t1, \s0, \s1, \s2, \s3 + +# Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \s3, \s2, \s1, \t1, \s0, \t0, \t2, \t3 + &Mul_GF16_2(@x,@s[3,2,1],@t[1],@s[0],@t[0,2,3]); + +### output msb > [x3,x2,x1,x0,x7,x6,x5,x4] < lsb +} + +# AES linear components + +sub ShiftRows { +my @x=@_[0..7]; +my @t=@_[8..11]; +my $mask=pop; +$code.=<<___; + vldmia $key!, {@t[0]-@t[3]} + veor @t[0], @t[0], @x[0] + veor @t[1], @t[1], @x[1] + vtbl.8 `&Dlo(@x[0])`, {@t[0]}, `&Dlo($mask)` + vtbl.8 `&Dhi(@x[0])`, {@t[0]}, `&Dhi($mask)` + vldmia $key!, {@t[0]} + veor @t[2], @t[2], @x[2] + vtbl.8 `&Dlo(@x[1])`, {@t[1]}, `&Dlo($mask)` + vtbl.8 `&Dhi(@x[1])`, {@t[1]}, `&Dhi($mask)` + vldmia $key!, {@t[1]} + veor @t[3], @t[3], @x[3] + vtbl.8 `&Dlo(@x[2])`, {@t[2]}, `&Dlo($mask)` + vtbl.8 `&Dhi(@x[2])`, {@t[2]}, `&Dhi($mask)` + vldmia $key!, {@t[2]} + vtbl.8 `&Dlo(@x[3])`, {@t[3]}, `&Dlo($mask)` + vtbl.8 `&Dhi(@x[3])`, {@t[3]}, `&Dhi($mask)` + vldmia $key!, {@t[3]} + veor @t[0], @t[0], @x[4] + veor @t[1], @t[1], @x[5] + vtbl.8 `&Dlo(@x[4])`, {@t[0]}, `&Dlo($mask)` + vtbl.8 `&Dhi(@x[4])`, {@t[0]}, `&Dhi($mask)` + veor @t[2], @t[2], @x[6] + vtbl.8 `&Dlo(@x[5])`, {@t[1]}, `&Dlo($mask)` + vtbl.8 `&Dhi(@x[5])`, {@t[1]}, `&Dhi($mask)` + veor @t[3], @t[3], @x[7] + vtbl.8 `&Dlo(@x[6])`, {@t[2]}, `&Dlo($mask)` + vtbl.8 `&Dhi(@x[6])`, {@t[2]}, `&Dhi($mask)` + vtbl.8 `&Dlo(@x[7])`, {@t[3]}, `&Dlo($mask)` + vtbl.8 `&Dhi(@x[7])`, {@t[3]}, `&Dhi($mask)` +___ +} + +sub MixColumns { +# modified to emit output in order suitable for feeding back to aesenc[last] +my @x=@_[0..7]; +my @t=@_[8..15]; +my $inv=@_[16]; # optional +$code.=<<___; + vext.8 @t[0], @x[0], @x[0], #12 @ x0 <<< 32 + vext.8 @t[1], @x[1], @x[1], #12 + veor @x[0], @x[0], @t[0] @ x0 ^ (x0 <<< 32) + vext.8 @t[2], @x[2], @x[2], #12 + veor @x[1], @x[1], @t[1] + vext.8 @t[3], @x[3], @x[3], #12 + veor @x[2], @x[2], @t[2] + vext.8 @t[4], @x[4], @x[4], #12 + veor @x[3], @x[3], @t[3] + vext.8 @t[5], @x[5], @x[5], #12 + veor @x[4], @x[4], @t[4] + vext.8 @t[6], @x[6], @x[6], #12 + veor @x[5], @x[5], @t[5] + vext.8 @t[7], @x[7], @x[7], #12 + veor @x[6], @x[6], @t[6] + + veor @t[1], @t[1], @x[0] + veor @x[7], @x[7], @t[7] + vext.8 @x[0], @x[0], @x[0], #8 @ (x0 ^ (x0 <<< 32)) <<< 64) + veor @t[2], @t[2], @x[1] + veor @t[0], @t[0], @x[7] + veor @t[1], @t[1], @x[7] + vext.8 @x[1], @x[1], @x[1], #8 + veor @t[5], @t[5], @x[4] + veor @x[0], @x[0], @t[0] + veor @t[6], @t[6], @x[5] + veor @x[1], @x[1], @t[1] + vext.8 @t[0], @x[4], @x[4], #8 + veor @t[4], @t[4], @x[3] + vext.8 @t[1], @x[5], @x[5], #8 + veor @t[7], @t[7], @x[6] + vext.8 @x[4], @x[3], @x[3], #8 + veor @t[3], @t[3], @x[2] + vext.8 @x[5], @x[7], @x[7], #8 + veor @t[4], @t[4], @x[7] + vext.8 @x[3], @x[6], @x[6], #8 + veor @t[3], @t[3], @x[7] + vext.8 @x[6], @x[2], @x[2], #8 + veor @x[7], @t[1], @t[5] +___ +$code.=<<___ if (!$inv); + veor @x[2], @t[0], @t[4] + veor @x[4], @x[4], @t[3] + veor @x[5], @x[5], @t[7] + veor @x[3], @x[3], @t[6] + @ vmov @x[2], @t[0] + veor @x[6], @x[6], @t[2] + @ vmov @x[7], @t[1] +___ +$code.=<<___ if ($inv); + veor @t[3], @t[3], @x[4] + veor @x[5], @x[5], @t[7] + veor @x[2], @x[3], @t[6] + veor @x[3], @t[0], @t[4] + veor @x[4], @x[6], @t[2] + vmov @x[6], @t[3] + @ vmov @x[7], @t[1] +___ +} + +sub InvMixColumns_orig { +my @x=@_[0..7]; +my @t=@_[8..15]; + +$code.=<<___; + @ multiplication by 0x0e + vext.8 @t[7], @x[7], @x[7], #12 + vmov @t[2], @x[2] + veor @x[2], @x[2], @x[5] @ 2 5 + veor @x[7], @x[7], @x[5] @ 7 5 + vext.8 @t[0], @x[0], @x[0], #12 + vmov @t[5], @x[5] + veor @x[5], @x[5], @x[0] @ 5 0 [1] + veor @x[0], @x[0], @x[1] @ 0 1 + vext.8 @t[1], @x[1], @x[1], #12 + veor @x[1], @x[1], @x[2] @ 1 25 + veor @x[0], @x[0], @x[6] @ 01 6 [2] + vext.8 @t[3], @x[3], @x[3], #12 + veor @x[1], @x[1], @x[3] @ 125 3 [4] + veor @x[2], @x[2], @x[0] @ 25 016 [3] + veor @x[3], @x[3], @x[7] @ 3 75 + veor @x[7], @x[7], @x[6] @ 75 6 [0] + vext.8 @t[6], @x[6], @x[6], #12 + vmov @t[4], @x[4] + veor @x[6], @x[6], @x[4] @ 6 4 + veor @x[4], @x[4], @x[3] @ 4 375 [6] + veor @x[3], @x[3], @x[7] @ 375 756=36 + veor @x[6], @x[6], @t[5] @ 64 5 [7] + veor @x[3], @x[3], @t[2] @ 36 2 + vext.8 @t[5], @t[5], @t[5], #12 + veor @x[3], @x[3], @t[4] @ 362 4 [5] +___ + my @y = @x[7,5,0,2,1,3,4,6]; +$code.=<<___; + @ multiplication by 0x0b + veor @y[1], @y[1], @y[0] + veor @y[0], @y[0], @t[0] + vext.8 @t[2], @t[2], @t[2], #12 + veor @y[1], @y[1], @t[1] + veor @y[0], @y[0], @t[5] + vext.8 @t[4], @t[4], @t[4], #12 + veor @y[1], @y[1], @t[6] + veor @y[0], @y[0], @t[7] + veor @t[7], @t[7], @t[6] @ clobber t[7] + + veor @y[3], @y[3], @t[0] + veor @y[1], @y[1], @y[0] + vext.8 @t[0], @t[0], @t[0], #12 + veor @y[2], @y[2], @t[1] + veor @y[4], @y[4], @t[1] + vext.8 @t[1], @t[1], @t[1], #12 + veor @y[2], @y[2], @t[2] + veor @y[3], @y[3], @t[2] + veor @y[5], @y[5], @t[2] + veor @y[2], @y[2], @t[7] + vext.8 @t[2], @t[2], @t[2], #12 + veor @y[3], @y[3], @t[3] + veor @y[6], @y[6], @t[3] + veor @y[4], @y[4], @t[3] + veor @y[7], @y[7], @t[4] + vext.8 @t[3], @t[3], @t[3], #12 + veor @y[5], @y[5], @t[4] + veor @y[7], @y[7], @t[7] + veor @t[7], @t[7], @t[5] @ clobber t[7] even more + veor @y[3], @y[3], @t[5] + veor @y[4], @y[4], @t[4] + + veor @y[5], @y[5], @t[7] + vext.8 @t[4], @t[4], @t[4], #12 + veor @y[6], @y[6], @t[7] + veor @y[4], @y[4], @t[7] + + veor @t[7], @t[7], @t[5] + vext.8 @t[5], @t[5], @t[5], #12 + + @ multiplication by 0x0d + veor @y[4], @y[4], @y[7] + veor @t[7], @t[7], @t[6] @ restore t[7] + veor @y[7], @y[7], @t[4] + vext.8 @t[6], @t[6], @t[6], #12 + veor @y[2], @y[2], @t[0] + veor @y[7], @y[7], @t[5] + vext.8 @t[7], @t[7], @t[7], #12 + veor @y[2], @y[2], @t[2] + + veor @y[3], @y[3], @y[1] + veor @y[1], @y[1], @t[1] + veor @y[0], @y[0], @t[0] + veor @y[3], @y[3], @t[0] + veor @y[1], @y[1], @t[5] + veor @y[0], @y[0], @t[5] + vext.8 @t[0], @t[0], @t[0], #12 + veor @y[1], @y[1], @t[7] + veor @y[0], @y[0], @t[6] + veor @y[3], @y[3], @y[1] + veor @y[4], @y[4], @t[1] + vext.8 @t[1], @t[1], @t[1], #12 + + veor @y[7], @y[7], @t[7] + veor @y[4], @y[4], @t[2] + veor @y[5], @y[5], @t[2] + veor @y[2], @y[2], @t[6] + veor @t[6], @t[6], @t[3] @ clobber t[6] + vext.8 @t[2], @t[2], @t[2], #12 + veor @y[4], @y[4], @y[7] + veor @y[3], @y[3], @t[6] + + veor @y[6], @y[6], @t[6] + veor @y[5], @y[5], @t[5] + vext.8 @t[5], @t[5], @t[5], #12 + veor @y[6], @y[6], @t[4] + vext.8 @t[4], @t[4], @t[4], #12 + veor @y[5], @y[5], @t[6] + veor @y[6], @y[6], @t[7] + vext.8 @t[7], @t[7], @t[7], #12 + veor @t[6], @t[6], @t[3] @ restore t[6] + vext.8 @t[3], @t[3], @t[3], #12 + + @ multiplication by 0x09 + veor @y[4], @y[4], @y[1] + veor @t[1], @t[1], @y[1] @ t[1]=y[1] + veor @t[0], @t[0], @t[5] @ clobber t[0] + vext.8 @t[6], @t[6], @t[6], #12 + veor @t[1], @t[1], @t[5] + veor @y[3], @y[3], @t[0] + veor @t[0], @t[0], @y[0] @ t[0]=y[0] + veor @t[1], @t[1], @t[6] + veor @t[6], @t[6], @t[7] @ clobber t[6] + veor @y[4], @y[4], @t[1] + veor @y[7], @y[7], @t[4] + veor @y[6], @y[6], @t[3] + veor @y[5], @y[5], @t[2] + veor @t[4], @t[4], @y[4] @ t[4]=y[4] + veor @t[3], @t[3], @y[3] @ t[3]=y[3] + veor @t[5], @t[5], @y[5] @ t[5]=y[5] + veor @t[2], @t[2], @y[2] @ t[2]=y[2] + veor @t[3], @t[3], @t[7] + veor @XMM[5], @t[5], @t[6] + veor @XMM[6], @t[6], @y[6] @ t[6]=y[6] + veor @XMM[2], @t[2], @t[6] + veor @XMM[7], @t[7], @y[7] @ t[7]=y[7] + + vmov @XMM[0], @t[0] + vmov @XMM[1], @t[1] + @ vmov @XMM[2], @t[2] + vmov @XMM[3], @t[3] + vmov @XMM[4], @t[4] + @ vmov @XMM[5], @t[5] + @ vmov @XMM[6], @t[6] + @ vmov @XMM[7], @t[7] +___ +} + +sub InvMixColumns { +my @x=@_[0..7]; +my @t=@_[8..15]; + +# Thanks to Jussi Kivilinna for providing pointer to +# +# | 0e 0b 0d 09 | | 02 03 01 01 | | 05 00 04 00 | +# | 09 0e 0b 0d | = | 01 02 03 01 | x | 00 05 00 04 | +# | 0d 09 0e 0b | | 01 01 02 03 | | 04 00 05 00 | +# | 0b 0d 09 0e | | 03 01 01 02 | | 00 04 00 05 | + +$code.=<<___; + @ multiplication by 0x05-0x00-0x04-0x00 + vext.8 @t[0], @x[0], @x[0], #8 + vext.8 @t[6], @x[6], @x[6], #8 + vext.8 @t[7], @x[7], @x[7], #8 + veor @t[0], @t[0], @x[0] + vext.8 @t[1], @x[1], @x[1], #8 + veor @t[6], @t[6], @x[6] + vext.8 @t[2], @x[2], @x[2], #8 + veor @t[7], @t[7], @x[7] + vext.8 @t[3], @x[3], @x[3], #8 + veor @t[1], @t[1], @x[1] + vext.8 @t[4], @x[4], @x[4], #8 + veor @t[2], @t[2], @x[2] + vext.8 @t[5], @x[5], @x[5], #8 + veor @t[3], @t[3], @x[3] + veor @t[4], @t[4], @x[4] + veor @t[5], @t[5], @x[5] + + veor @x[0], @x[0], @t[6] + veor @x[1], @x[1], @t[6] + veor @x[2], @x[2], @t[0] + veor @x[4], @x[4], @t[2] + veor @x[3], @x[3], @t[1] + veor @x[1], @x[1], @t[7] + veor @x[2], @x[2], @t[7] + veor @x[4], @x[4], @t[6] + veor @x[5], @x[5], @t[3] + veor @x[3], @x[3], @t[6] + veor @x[6], @x[6], @t[4] + veor @x[4], @x[4], @t[7] + veor @x[5], @x[5], @t[7] + veor @x[7], @x[7], @t[5] +___ + &MixColumns (@x,@t,1); # flipped 2<->3 and 4<->6 +} + +sub swapmove { +my ($a,$b,$n,$mask,$t)=@_; +$code.=<<___; + vshr.u64 $t, $b, #$n + veor $t, $t, $a + vand $t, $t, $mask + veor $a, $a, $t + vshl.u64 $t, $t, #$n + veor $b, $b, $t +___ +} +sub swapmove2x { +my ($a0,$b0,$a1,$b1,$n,$mask,$t0,$t1)=@_; +$code.=<<___; + vshr.u64 $t0, $b0, #$n + vshr.u64 $t1, $b1, #$n + veor $t0, $t0, $a0 + veor $t1, $t1, $a1 + vand $t0, $t0, $mask + vand $t1, $t1, $mask + veor $a0, $a0, $t0 + vshl.u64 $t0, $t0, #$n + veor $a1, $a1, $t1 + vshl.u64 $t1, $t1, #$n + veor $b0, $b0, $t0 + veor $b1, $b1, $t1 +___ +} + +sub bitslice { +my @x=reverse(@_[0..7]); +my ($t0,$t1,$t2,$t3)=@_[8..11]; +$code.=<<___; + vmov.i8 $t0,#0x55 @ compose .LBS0 + vmov.i8 $t1,#0x33 @ compose .LBS1 +___ + &swapmove2x(@x[0,1,2,3],1,$t0,$t2,$t3); + &swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3); +$code.=<<___; + vmov.i8 $t0,#0x0f @ compose .LBS2 +___ + &swapmove2x(@x[0,2,1,3],2,$t1,$t2,$t3); + &swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3); + + &swapmove2x(@x[0,4,1,5],4,$t0,$t2,$t3); + &swapmove2x(@x[2,6,3,7],4,$t0,$t2,$t3); +} + +$code.=<<___; +#ifndef __KERNEL__ +# include "arm_arch.h" + +# define VFP_ABI_PUSH vstmdb sp!,{d8-d15} +# define VFP_ABI_POP vldmia sp!,{d8-d15} +# define VFP_ABI_FRAME 0x40 +#else +# define VFP_ABI_PUSH +# define VFP_ABI_POP +# define VFP_ABI_FRAME 0 +# define BSAES_ASM_EXTENDED_KEY +# define XTS_CHAIN_TWEAK +# define __ARM_ARCH__ __LINUX_ARM_ARCH__ +# define __ARM_MAX_ARCH__ 7 +#endif + +#ifdef __thumb__ +# define adrl adr +#endif + +#if __ARM_MAX_ARCH__>=7 +.arch armv7-a +.fpu neon + +.text +.syntax unified @ ARMv7-capable assembler is expected to handle this +#if defined(__thumb2__) && !defined(__APPLE__) +.thumb +#else +.code 32 +# undef __thumb2__ +#endif + +.type _bsaes_decrypt8,%function +.align 4 +_bsaes_decrypt8: + adr $const,. + vldmia $key!, {@XMM[9]} @ round 0 key +#if defined(__thumb2__) || defined(__APPLE__) + adr $const,.LM0ISR +#else + add $const,$const,#.LM0ISR-_bsaes_decrypt8 +#endif + + vldmia $const!, {@XMM[8]} @ .LM0ISR + veor @XMM[10], @XMM[0], @XMM[9] @ xor with round0 key + veor @XMM[11], @XMM[1], @XMM[9] + vtbl.8 `&Dlo(@XMM[0])`, {@XMM[10]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[0])`, {@XMM[10]}, `&Dhi(@XMM[8])` + veor @XMM[12], @XMM[2], @XMM[9] + vtbl.8 `&Dlo(@XMM[1])`, {@XMM[11]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[1])`, {@XMM[11]}, `&Dhi(@XMM[8])` + veor @XMM[13], @XMM[3], @XMM[9] + vtbl.8 `&Dlo(@XMM[2])`, {@XMM[12]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[2])`, {@XMM[12]}, `&Dhi(@XMM[8])` + veor @XMM[14], @XMM[4], @XMM[9] + vtbl.8 `&Dlo(@XMM[3])`, {@XMM[13]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[3])`, {@XMM[13]}, `&Dhi(@XMM[8])` + veor @XMM[15], @XMM[5], @XMM[9] + vtbl.8 `&Dlo(@XMM[4])`, {@XMM[14]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[4])`, {@XMM[14]}, `&Dhi(@XMM[8])` + veor @XMM[10], @XMM[6], @XMM[9] + vtbl.8 `&Dlo(@XMM[5])`, {@XMM[15]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[5])`, {@XMM[15]}, `&Dhi(@XMM[8])` + veor @XMM[11], @XMM[7], @XMM[9] + vtbl.8 `&Dlo(@XMM[6])`, {@XMM[10]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[6])`, {@XMM[10]}, `&Dhi(@XMM[8])` + vtbl.8 `&Dlo(@XMM[7])`, {@XMM[11]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[7])`, {@XMM[11]}, `&Dhi(@XMM[8])` +___ + &bitslice (@XMM[0..7, 8..11]); +$code.=<<___; + sub $rounds,$rounds,#1 + b .Ldec_sbox +.align 4 +.Ldec_loop: +___ + &ShiftRows (@XMM[0..7, 8..12]); +$code.=".Ldec_sbox:\n"; + &InvSbox (@XMM[0..7, 8..15]); +$code.=<<___; + subs $rounds,$rounds,#1 + bcc .Ldec_done +___ + &InvMixColumns (@XMM[0,1,6,4,2,7,3,5, 8..15]); +$code.=<<___; + vldmia $const, {@XMM[12]} @ .LISR + ite eq @ Thumb2 thing, sanity check in ARM + addeq $const,$const,#0x10 + bne .Ldec_loop + vldmia $const, {@XMM[12]} @ .LISRM0 + b .Ldec_loop +.align 4 +.Ldec_done: +___ + &bitslice (@XMM[0,1,6,4,2,7,3,5, 8..11]); +$code.=<<___; + vldmia $key, {@XMM[8]} @ last round key + veor @XMM[6], @XMM[6], @XMM[8] + veor @XMM[4], @XMM[4], @XMM[8] + veor @XMM[2], @XMM[2], @XMM[8] + veor @XMM[7], @XMM[7], @XMM[8] + veor @XMM[3], @XMM[3], @XMM[8] + veor @XMM[5], @XMM[5], @XMM[8] + veor @XMM[0], @XMM[0], @XMM[8] + veor @XMM[1], @XMM[1], @XMM[8] + bx lr +.size _bsaes_decrypt8,.-_bsaes_decrypt8 + +.type _bsaes_const,%object +.align 6 +_bsaes_const: +.LM0ISR: @ InvShiftRows constants + .quad 0x0a0e0206070b0f03, 0x0004080c0d010509 +.LISR: + .quad 0x0504070602010003, 0x0f0e0d0c080b0a09 +.LISRM0: + .quad 0x01040b0e0205080f, 0x0306090c00070a0d +.LM0SR: @ ShiftRows constants + .quad 0x0a0e02060f03070b, 0x0004080c05090d01 +.LSR: + .quad 0x0504070600030201, 0x0f0e0d0c0a09080b +.LSRM0: + .quad 0x0304090e00050a0f, 0x01060b0c0207080d +.LM0: + .quad 0x02060a0e03070b0f, 0x0004080c0105090d +.LREVM0SR: + .quad 0x090d01050c000408, 0x03070b0f060a0e02 +.asciz "Bit-sliced AES for NEON, CRYPTOGAMS by " +.align 6 +.size _bsaes_const,.-_bsaes_const + +.type _bsaes_encrypt8,%function +.align 4 +_bsaes_encrypt8: + adr $const,. + vldmia $key!, {@XMM[9]} @ round 0 key +#if defined(__thumb2__) || defined(__APPLE__) + adr $const,.LM0SR +#else + sub $const,$const,#_bsaes_encrypt8-.LM0SR +#endif + + vldmia $const!, {@XMM[8]} @ .LM0SR +_bsaes_encrypt8_alt: + veor @XMM[10], @XMM[0], @XMM[9] @ xor with round0 key + veor @XMM[11], @XMM[1], @XMM[9] + vtbl.8 `&Dlo(@XMM[0])`, {@XMM[10]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[0])`, {@XMM[10]}, `&Dhi(@XMM[8])` + veor @XMM[12], @XMM[2], @XMM[9] + vtbl.8 `&Dlo(@XMM[1])`, {@XMM[11]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[1])`, {@XMM[11]}, `&Dhi(@XMM[8])` + veor @XMM[13], @XMM[3], @XMM[9] + vtbl.8 `&Dlo(@XMM[2])`, {@XMM[12]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[2])`, {@XMM[12]}, `&Dhi(@XMM[8])` + veor @XMM[14], @XMM[4], @XMM[9] + vtbl.8 `&Dlo(@XMM[3])`, {@XMM[13]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[3])`, {@XMM[13]}, `&Dhi(@XMM[8])` + veor @XMM[15], @XMM[5], @XMM[9] + vtbl.8 `&Dlo(@XMM[4])`, {@XMM[14]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[4])`, {@XMM[14]}, `&Dhi(@XMM[8])` + veor @XMM[10], @XMM[6], @XMM[9] + vtbl.8 `&Dlo(@XMM[5])`, {@XMM[15]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[5])`, {@XMM[15]}, `&Dhi(@XMM[8])` + veor @XMM[11], @XMM[7], @XMM[9] + vtbl.8 `&Dlo(@XMM[6])`, {@XMM[10]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[6])`, {@XMM[10]}, `&Dhi(@XMM[8])` + vtbl.8 `&Dlo(@XMM[7])`, {@XMM[11]}, `&Dlo(@XMM[8])` + vtbl.8 `&Dhi(@XMM[7])`, {@XMM[11]}, `&Dhi(@XMM[8])` +_bsaes_encrypt8_bitslice: +___ + &bitslice (@XMM[0..7, 8..11]); +$code.=<<___; + sub $rounds,$rounds,#1 + b .Lenc_sbox +.align 4 +.Lenc_loop: +___ + &ShiftRows (@XMM[0..7, 8..12]); +$code.=".Lenc_sbox:\n"; + &Sbox (@XMM[0..7, 8..15]); +$code.=<<___; + subs $rounds,$rounds,#1 + bcc .Lenc_done +___ + &MixColumns (@XMM[0,1,4,6,3,7,2,5, 8..15]); +$code.=<<___; + vldmia $const, {@XMM[12]} @ .LSR + ite eq @ Thumb2 thing, samity check in ARM + addeq $const,$const,#0x10 + bne .Lenc_loop + vldmia $const, {@XMM[12]} @ .LSRM0 + b .Lenc_loop +.align 4 +.Lenc_done: +___ + # output in lsb > [t0, t1, t4, t6, t3, t7, t2, t5] < msb + &bitslice (@XMM[0,1,4,6,3,7,2,5, 8..11]); +$code.=<<___; + vldmia $key, {@XMM[8]} @ last round key + veor @XMM[4], @XMM[4], @XMM[8] + veor @XMM[6], @XMM[6], @XMM[8] + veor @XMM[3], @XMM[3], @XMM[8] + veor @XMM[7], @XMM[7], @XMM[8] + veor @XMM[2], @XMM[2], @XMM[8] + veor @XMM[5], @XMM[5], @XMM[8] + veor @XMM[0], @XMM[0], @XMM[8] + veor @XMM[1], @XMM[1], @XMM[8] + bx lr +.size _bsaes_encrypt8,.-_bsaes_encrypt8 +___ +} +{ +my ($out,$inp,$rounds,$const)=("r12","r4","r5","r6"); + +sub bitslice_key { +my @x=reverse(@_[0..7]); +my ($bs0,$bs1,$bs2,$t2,$t3)=@_[8..12]; + + &swapmove (@x[0,1],1,$bs0,$t2,$t3); +$code.=<<___; + @ &swapmove(@x[2,3],1,$t0,$t2,$t3); + vmov @x[2], @x[0] + vmov @x[3], @x[1] +___ + #&swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3); + + &swapmove2x (@x[0,2,1,3],2,$bs1,$t2,$t3); +$code.=<<___; + @ &swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3); + vmov @x[4], @x[0] + vmov @x[6], @x[2] + vmov @x[5], @x[1] + vmov @x[7], @x[3] +___ + &swapmove2x (@x[0,4,1,5],4,$bs2,$t2,$t3); + &swapmove2x (@x[2,6,3,7],4,$bs2,$t2,$t3); +} + +$code.=<<___; +.type _bsaes_key_convert,%function +.align 4 +_bsaes_key_convert: + adr $const,. + vld1.8 {@XMM[7]}, [$inp]! @ load round 0 key +#if defined(__thumb2__) || defined(__APPLE__) + adr $const,.LM0 +#else + sub $const,$const,#_bsaes_key_convert-.LM0 +#endif + vld1.8 {@XMM[15]}, [$inp]! @ load round 1 key + + vmov.i8 @XMM[8], #0x01 @ bit masks + vmov.i8 @XMM[9], #0x02 + vmov.i8 @XMM[10], #0x04 + vmov.i8 @XMM[11], #0x08 + vmov.i8 @XMM[12], #0x10 + vmov.i8 @XMM[13], #0x20 + vldmia $const, {@XMM[14]} @ .LM0 + +#ifdef __ARMEL__ + vrev32.8 @XMM[7], @XMM[7] + vrev32.8 @XMM[15], @XMM[15] +#endif + sub $rounds,$rounds,#1 + vstmia $out!, {@XMM[7]} @ save round 0 key + b .Lkey_loop + +.align 4 +.Lkey_loop: + vtbl.8 `&Dlo(@XMM[7])`,{@XMM[15]},`&Dlo(@XMM[14])` + vtbl.8 `&Dhi(@XMM[7])`,{@XMM[15]},`&Dhi(@XMM[14])` + vmov.i8 @XMM[6], #0x40 + vmov.i8 @XMM[15], #0x80 + + vtst.8 @XMM[0], @XMM[7], @XMM[8] + vtst.8 @XMM[1], @XMM[7], @XMM[9] + vtst.8 @XMM[2], @XMM[7], @XMM[10] + vtst.8 @XMM[3], @XMM[7], @XMM[11] + vtst.8 @XMM[4], @XMM[7], @XMM[12] + vtst.8 @XMM[5], @XMM[7], @XMM[13] + vtst.8 @XMM[6], @XMM[7], @XMM[6] + vtst.8 @XMM[7], @XMM[7], @XMM[15] + vld1.8 {@XMM[15]}, [$inp]! @ load next round key + vmvn @XMM[0], @XMM[0] @ "pnot" + vmvn @XMM[1], @XMM[1] + vmvn @XMM[5], @XMM[5] + vmvn @XMM[6], @XMM[6] +#ifdef __ARMEL__ + vrev32.8 @XMM[15], @XMM[15] +#endif + subs $rounds,$rounds,#1 + vstmia $out!,{@XMM[0]-@XMM[7]} @ write bit-sliced round key + bne .Lkey_loop + + vmov.i8 @XMM[7],#0x63 @ compose .L63 + @ don't save last round key + bx lr +.size _bsaes_key_convert,.-_bsaes_key_convert +___ +} + +if (0) { # following four functions are unsupported interface + # used for benchmarking... +$code.=<<___; +.globl bsaes_enc_key_convert +.type bsaes_enc_key_convert,%function +.align 4 +bsaes_enc_key_convert: + stmdb sp!,{r4-r6,lr} + vstmdb sp!,{d8-d15} @ ABI specification says so + + ldr r5,[$inp,#240] @ pass rounds + mov r4,$inp @ pass key + mov r12,$out @ pass key schedule + bl _bsaes_key_convert + veor @XMM[7],@XMM[7],@XMM[15] @ fix up last round key + vstmia r12, {@XMM[7]} @ save last round key + + vldmia sp!,{d8-d15} + ldmia sp!,{r4-r6,pc} +.size bsaes_enc_key_convert,.-bsaes_enc_key_convert + +.globl bsaes_encrypt_128 +.type bsaes_encrypt_128,%function +.align 4 +bsaes_encrypt_128: + stmdb sp!,{r4-r6,lr} + vstmdb sp!,{d8-d15} @ ABI specification says so +.Lenc128_loop: + vld1.8 {@XMM[0]-@XMM[1]}, [$inp]! @ load input + vld1.8 {@XMM[2]-@XMM[3]}, [$inp]! + mov r4,$key @ pass the key + vld1.8 {@XMM[4]-@XMM[5]}, [$inp]! + mov r5,#10 @ pass rounds + vld1.8 {@XMM[6]-@XMM[7]}, [$inp]! + + bl _bsaes_encrypt8 + + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output + vst1.8 {@XMM[4]}, [$out]! + vst1.8 {@XMM[6]}, [$out]! + vst1.8 {@XMM[3]}, [$out]! + vst1.8 {@XMM[7]}, [$out]! + vst1.8 {@XMM[2]}, [$out]! + subs $len,$len,#0x80 + vst1.8 {@XMM[5]}, [$out]! + bhi .Lenc128_loop + + vldmia sp!,{d8-d15} + ldmia sp!,{r4-r6,pc} +.size bsaes_encrypt_128,.-bsaes_encrypt_128 + +.globl bsaes_dec_key_convert +.type bsaes_dec_key_convert,%function +.align 4 +bsaes_dec_key_convert: + stmdb sp!,{r4-r6,lr} + vstmdb sp!,{d8-d15} @ ABI specification says so + + ldr r5,[$inp,#240] @ pass rounds + mov r4,$inp @ pass key + mov r12,$out @ pass key schedule + bl _bsaes_key_convert + vldmia $out, {@XMM[6]} + vstmia r12, {@XMM[15]} @ save last round key + veor @XMM[7], @XMM[7], @XMM[6] @ fix up round 0 key + vstmia $out, {@XMM[7]} + + vldmia sp!,{d8-d15} + ldmia sp!,{r4-r6,pc} +.size bsaes_dec_key_convert,.-bsaes_dec_key_convert + +.globl bsaes_decrypt_128 +.type bsaes_decrypt_128,%function +.align 4 +bsaes_decrypt_128: + stmdb sp!,{r4-r6,lr} + vstmdb sp!,{d8-d15} @ ABI specification says so +.Ldec128_loop: + vld1.8 {@XMM[0]-@XMM[1]}, [$inp]! @ load input + vld1.8 {@XMM[2]-@XMM[3]}, [$inp]! + mov r4,$key @ pass the key + vld1.8 {@XMM[4]-@XMM[5]}, [$inp]! + mov r5,#10 @ pass rounds + vld1.8 {@XMM[6]-@XMM[7]}, [$inp]! + + bl _bsaes_decrypt8 + + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output + vst1.8 {@XMM[6]}, [$out]! + vst1.8 {@XMM[4]}, [$out]! + vst1.8 {@XMM[2]}, [$out]! + vst1.8 {@XMM[7]}, [$out]! + vst1.8 {@XMM[3]}, [$out]! + subs $len,$len,#0x80 + vst1.8 {@XMM[5]}, [$out]! + bhi .Ldec128_loop + + vldmia sp!,{d8-d15} + ldmia sp!,{r4-r6,pc} +.size bsaes_decrypt_128,.-bsaes_decrypt_128 +___ +} +{ +my ($inp,$out,$len,$key, $ivp,$fp,$rounds)=map("r$_",(0..3,8..10)); +my ($keysched)=("sp"); + +$code.=<<___; +.extern AES_cbc_encrypt +.extern AES_decrypt + +.global bsaes_cbc_encrypt +.type bsaes_cbc_encrypt,%function +.align 5 +bsaes_cbc_encrypt: +#ifndef __KERNEL__ + cmp $len, #128 +#ifndef __thumb__ + blo AES_cbc_encrypt +#else + bhs 1f + b AES_cbc_encrypt +1: +#endif +#endif + + @ it is up to the caller to make sure we are called with enc == 0 + + mov ip, sp + stmdb sp!, {r4-r10, lr} + VFP_ABI_PUSH + ldr $ivp, [ip] @ IV is 1st arg on the stack + mov $len, $len, lsr#4 @ len in 16 byte blocks + sub sp, #0x10 @ scratch space to carry over the IV + mov $fp, sp @ save sp + + ldr $rounds, [$key, #240] @ get # of rounds +#ifndef BSAES_ASM_EXTENDED_KEY + @ allocate the key schedule on the stack + sub r12, sp, $rounds, lsl#7 @ 128 bytes per inner round key + add r12, #`128-32` @ sifze of bit-slices key schedule + + @ populate the key schedule + mov r4, $key @ pass key + mov r5, $rounds @ pass # of rounds + mov sp, r12 @ sp is $keysched + bl _bsaes_key_convert + vldmia $keysched, {@XMM[6]} + vstmia r12, {@XMM[15]} @ save last round key + veor @XMM[7], @XMM[7], @XMM[6] @ fix up round 0 key + vstmia $keysched, {@XMM[7]} +#else + ldr r12, [$key, #244] + eors r12, #1 + beq 0f + + @ populate the key schedule + str r12, [$key, #244] + mov r4, $key @ pass key + mov r5, $rounds @ pass # of rounds + add r12, $key, #248 @ pass key schedule + bl _bsaes_key_convert + add r4, $key, #248 + vldmia r4, {@XMM[6]} + vstmia r12, {@XMM[15]} @ save last round key + veor @XMM[7], @XMM[7], @XMM[6] @ fix up round 0 key + vstmia r4, {@XMM[7]} + +.align 2 +0: +#endif + + vld1.8 {@XMM[15]}, [$ivp] @ load IV + b .Lcbc_dec_loop + +.align 4 +.Lcbc_dec_loop: + subs $len, $len, #0x8 + bmi .Lcbc_dec_loop_finish + + vld1.8 {@XMM[0]-@XMM[1]}, [$inp]! @ load input + vld1.8 {@XMM[2]-@XMM[3]}, [$inp]! +#ifndef BSAES_ASM_EXTENDED_KEY + mov r4, $keysched @ pass the key +#else + add r4, $key, #248 +#endif + vld1.8 {@XMM[4]-@XMM[5]}, [$inp]! + mov r5, $rounds + vld1.8 {@XMM[6]-@XMM[7]}, [$inp] + sub $inp, $inp, #0x60 + vstmia $fp, {@XMM[15]} @ put aside IV + + bl _bsaes_decrypt8 + + vldmia $fp, {@XMM[14]} @ reload IV + vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input + veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV + vld1.8 {@XMM[10]-@XMM[11]}, [$inp]! + veor @XMM[1], @XMM[1], @XMM[8] + veor @XMM[6], @XMM[6], @XMM[9] + vld1.8 {@XMM[12]-@XMM[13]}, [$inp]! + veor @XMM[4], @XMM[4], @XMM[10] + veor @XMM[2], @XMM[2], @XMM[11] + vld1.8 {@XMM[14]-@XMM[15]}, [$inp]! + veor @XMM[7], @XMM[7], @XMM[12] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output + veor @XMM[3], @XMM[3], @XMM[13] + vst1.8 {@XMM[6]}, [$out]! + veor @XMM[5], @XMM[5], @XMM[14] + vst1.8 {@XMM[4]}, [$out]! + vst1.8 {@XMM[2]}, [$out]! + vst1.8 {@XMM[7]}, [$out]! + vst1.8 {@XMM[3]}, [$out]! + vst1.8 {@XMM[5]}, [$out]! + + b .Lcbc_dec_loop + +.Lcbc_dec_loop_finish: + adds $len, $len, #8 + beq .Lcbc_dec_done + + vld1.8 {@XMM[0]}, [$inp]! @ load input + cmp $len, #2 + blo .Lcbc_dec_one + vld1.8 {@XMM[1]}, [$inp]! +#ifndef BSAES_ASM_EXTENDED_KEY + mov r4, $keysched @ pass the key +#else + add r4, $key, #248 +#endif + mov r5, $rounds + vstmia $fp, {@XMM[15]} @ put aside IV + beq .Lcbc_dec_two + vld1.8 {@XMM[2]}, [$inp]! + cmp $len, #4 + blo .Lcbc_dec_three + vld1.8 {@XMM[3]}, [$inp]! + beq .Lcbc_dec_four + vld1.8 {@XMM[4]}, [$inp]! + cmp $len, #6 + blo .Lcbc_dec_five + vld1.8 {@XMM[5]}, [$inp]! + beq .Lcbc_dec_six + vld1.8 {@XMM[6]}, [$inp]! + sub $inp, $inp, #0x70 + + bl _bsaes_decrypt8 + + vldmia $fp, {@XMM[14]} @ reload IV + vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input + veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV + vld1.8 {@XMM[10]-@XMM[11]}, [$inp]! + veor @XMM[1], @XMM[1], @XMM[8] + veor @XMM[6], @XMM[6], @XMM[9] + vld1.8 {@XMM[12]-@XMM[13]}, [$inp]! + veor @XMM[4], @XMM[4], @XMM[10] + veor @XMM[2], @XMM[2], @XMM[11] + vld1.8 {@XMM[15]}, [$inp]! + veor @XMM[7], @XMM[7], @XMM[12] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output + veor @XMM[3], @XMM[3], @XMM[13] + vst1.8 {@XMM[6]}, [$out]! + vst1.8 {@XMM[4]}, [$out]! + vst1.8 {@XMM[2]}, [$out]! + vst1.8 {@XMM[7]}, [$out]! + vst1.8 {@XMM[3]}, [$out]! + b .Lcbc_dec_done +.align 4 +.Lcbc_dec_six: + sub $inp, $inp, #0x60 + bl _bsaes_decrypt8 + vldmia $fp,{@XMM[14]} @ reload IV + vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input + veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV + vld1.8 {@XMM[10]-@XMM[11]}, [$inp]! + veor @XMM[1], @XMM[1], @XMM[8] + veor @XMM[6], @XMM[6], @XMM[9] + vld1.8 {@XMM[12]}, [$inp]! + veor @XMM[4], @XMM[4], @XMM[10] + veor @XMM[2], @XMM[2], @XMM[11] + vld1.8 {@XMM[15]}, [$inp]! + veor @XMM[7], @XMM[7], @XMM[12] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output + vst1.8 {@XMM[6]}, [$out]! + vst1.8 {@XMM[4]}, [$out]! + vst1.8 {@XMM[2]}, [$out]! + vst1.8 {@XMM[7]}, [$out]! + b .Lcbc_dec_done +.align 4 +.Lcbc_dec_five: + sub $inp, $inp, #0x50 + bl _bsaes_decrypt8 + vldmia $fp, {@XMM[14]} @ reload IV + vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input + veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV + vld1.8 {@XMM[10]-@XMM[11]}, [$inp]! + veor @XMM[1], @XMM[1], @XMM[8] + veor @XMM[6], @XMM[6], @XMM[9] + vld1.8 {@XMM[15]}, [$inp]! + veor @XMM[4], @XMM[4], @XMM[10] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output + veor @XMM[2], @XMM[2], @XMM[11] + vst1.8 {@XMM[6]}, [$out]! + vst1.8 {@XMM[4]}, [$out]! + vst1.8 {@XMM[2]}, [$out]! + b .Lcbc_dec_done +.align 4 +.Lcbc_dec_four: + sub $inp, $inp, #0x40 + bl _bsaes_decrypt8 + vldmia $fp, {@XMM[14]} @ reload IV + vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input + veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV + vld1.8 {@XMM[10]}, [$inp]! + veor @XMM[1], @XMM[1], @XMM[8] + veor @XMM[6], @XMM[6], @XMM[9] + vld1.8 {@XMM[15]}, [$inp]! + veor @XMM[4], @XMM[4], @XMM[10] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output + vst1.8 {@XMM[6]}, [$out]! + vst1.8 {@XMM[4]}, [$out]! + b .Lcbc_dec_done +.align 4 +.Lcbc_dec_three: + sub $inp, $inp, #0x30 + bl _bsaes_decrypt8 + vldmia $fp, {@XMM[14]} @ reload IV + vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input + veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV + vld1.8 {@XMM[15]}, [$inp]! + veor @XMM[1], @XMM[1], @XMM[8] + veor @XMM[6], @XMM[6], @XMM[9] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output + vst1.8 {@XMM[6]}, [$out]! + b .Lcbc_dec_done +.align 4 +.Lcbc_dec_two: + sub $inp, $inp, #0x20 + bl _bsaes_decrypt8 + vldmia $fp, {@XMM[14]} @ reload IV + vld1.8 {@XMM[8]}, [$inp]! @ reload input + veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV + vld1.8 {@XMM[15]}, [$inp]! @ reload input + veor @XMM[1], @XMM[1], @XMM[8] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output + b .Lcbc_dec_done +.align 4 +.Lcbc_dec_one: + sub $inp, $inp, #0x10 + mov $rounds, $out @ save original out pointer + mov $out, $fp @ use the iv scratch space as out buffer + mov r2, $key + vmov @XMM[4],@XMM[15] @ just in case ensure that IV + vmov @XMM[5],@XMM[0] @ and input are preserved + bl AES_decrypt + vld1.8 {@XMM[0]}, [$fp] @ load result + veor @XMM[0], @XMM[0], @XMM[4] @ ^= IV + vmov @XMM[15], @XMM[5] @ @XMM[5] holds input + vst1.8 {@XMM[0]}, [$rounds] @ write output + +.Lcbc_dec_done: +#ifndef BSAES_ASM_EXTENDED_KEY + vmov.i32 q0, #0 + vmov.i32 q1, #0 +.Lcbc_dec_bzero: @ wipe key schedule [if any] + vstmia $keysched!, {q0-q1} + cmp $keysched, $fp + bne .Lcbc_dec_bzero +#endif + + mov sp, $fp + add sp, #0x10 @ add sp,$fp,#0x10 is no good for thumb + vst1.8 {@XMM[15]}, [$ivp] @ return IV + VFP_ABI_POP + ldmia sp!, {r4-r10, pc} +.size bsaes_cbc_encrypt,.-bsaes_cbc_encrypt +___ +} +{ +my ($inp,$out,$len,$key, $ctr,$fp,$rounds)=(map("r$_",(0..3,8..10))); +my $const = "r6"; # shared with _bsaes_encrypt8_alt +my $keysched = "sp"; + +$code.=<<___; +.extern AES_encrypt +.global bsaes_ctr32_encrypt_blocks +.type bsaes_ctr32_encrypt_blocks,%function +.align 5 +bsaes_ctr32_encrypt_blocks: + cmp $len, #8 @ use plain AES for + blo .Lctr_enc_short @ small sizes + + mov ip, sp + stmdb sp!, {r4-r10, lr} + VFP_ABI_PUSH + ldr $ctr, [ip] @ ctr is 1st arg on the stack + sub sp, sp, #0x10 @ scratch space to carry over the ctr + mov $fp, sp @ save sp + + ldr $rounds, [$key, #240] @ get # of rounds +#ifndef BSAES_ASM_EXTENDED_KEY + @ allocate the key schedule on the stack + sub r12, sp, $rounds, lsl#7 @ 128 bytes per inner round key + add r12, #`128-32` @ size of bit-sliced key schedule + + @ populate the key schedule + mov r4, $key @ pass key + mov r5, $rounds @ pass # of rounds + mov sp, r12 @ sp is $keysched + bl _bsaes_key_convert + veor @XMM[7],@XMM[7],@XMM[15] @ fix up last round key + vstmia r12, {@XMM[7]} @ save last round key + + vld1.8 {@XMM[0]}, [$ctr] @ load counter +#ifdef __APPLE__ + mov $ctr, #:lower16:(.LREVM0SR-.LM0) + add $ctr, $const, $ctr +#else + add $ctr, $const, #.LREVM0SR-.LM0 @ borrow $ctr +#endif + vldmia $keysched, {@XMM[4]} @ load round0 key +#else + ldr r12, [$key, #244] + eors r12, #1 + beq 0f + + @ populate the key schedule + str r12, [$key, #244] + mov r4, $key @ pass key + mov r5, $rounds @ pass # of rounds + add r12, $key, #248 @ pass key schedule + bl _bsaes_key_convert + veor @XMM[7],@XMM[7],@XMM[15] @ fix up last round key + vstmia r12, {@XMM[7]} @ save last round key + +.align 2 +0: add r12, $key, #248 + vld1.8 {@XMM[0]}, [$ctr] @ load counter + adrl $ctr, .LREVM0SR @ borrow $ctr + vldmia r12, {@XMM[4]} @ load round0 key + sub sp, #0x10 @ place for adjusted round0 key +#endif + + vmov.i32 @XMM[8],#1 @ compose 1<<96 + veor @XMM[9],@XMM[9],@XMM[9] + vrev32.8 @XMM[0],@XMM[0] + vext.8 @XMM[8],@XMM[9],@XMM[8],#4 + vrev32.8 @XMM[4],@XMM[4] + vadd.u32 @XMM[9],@XMM[8],@XMM[8] @ compose 2<<96 + vstmia $keysched, {@XMM[4]} @ save adjusted round0 key + b .Lctr_enc_loop + +.align 4 +.Lctr_enc_loop: + vadd.u32 @XMM[10], @XMM[8], @XMM[9] @ compose 3<<96 + vadd.u32 @XMM[1], @XMM[0], @XMM[8] @ +1 + vadd.u32 @XMM[2], @XMM[0], @XMM[9] @ +2 + vadd.u32 @XMM[3], @XMM[0], @XMM[10] @ +3 + vadd.u32 @XMM[4], @XMM[1], @XMM[10] + vadd.u32 @XMM[5], @XMM[2], @XMM[10] + vadd.u32 @XMM[6], @XMM[3], @XMM[10] + vadd.u32 @XMM[7], @XMM[4], @XMM[10] + vadd.u32 @XMM[10], @XMM[5], @XMM[10] @ next counter + + @ Borrow prologue from _bsaes_encrypt8 to use the opportunity + @ to flip byte order in 32-bit counter + + vldmia $keysched, {@XMM[9]} @ load round0 key +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, $keysched, #0x10 @ pass next round key +#else + add r4, $key, #`248+16` +#endif + vldmia $ctr, {@XMM[8]} @ .LREVM0SR + mov r5, $rounds @ pass rounds + vstmia $fp, {@XMM[10]} @ save next counter +#ifdef __APPLE__ + mov $const, #:lower16:(.LREVM0SR-.LSR) + sub $const, $ctr, $const +#else + sub $const, $ctr, #.LREVM0SR-.LSR @ pass constants +#endif + + bl _bsaes_encrypt8_alt + + subs $len, $len, #8 + blo .Lctr_enc_loop_done + + vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ load input + vld1.8 {@XMM[10]-@XMM[11]}, [$inp]! + veor @XMM[0], @XMM[8] + veor @XMM[1], @XMM[9] + vld1.8 {@XMM[12]-@XMM[13]}, [$inp]! + veor @XMM[4], @XMM[10] + veor @XMM[6], @XMM[11] + vld1.8 {@XMM[14]-@XMM[15]}, [$inp]! + veor @XMM[3], @XMM[12] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output + veor @XMM[7], @XMM[13] + veor @XMM[2], @XMM[14] + vst1.8 {@XMM[4]}, [$out]! + veor @XMM[5], @XMM[15] + vst1.8 {@XMM[6]}, [$out]! + vmov.i32 @XMM[8], #1 @ compose 1<<96 + vst1.8 {@XMM[3]}, [$out]! + veor @XMM[9], @XMM[9], @XMM[9] + vst1.8 {@XMM[7]}, [$out]! + vext.8 @XMM[8], @XMM[9], @XMM[8], #4 + vst1.8 {@XMM[2]}, [$out]! + vadd.u32 @XMM[9],@XMM[8],@XMM[8] @ compose 2<<96 + vst1.8 {@XMM[5]}, [$out]! + vldmia $fp, {@XMM[0]} @ load counter + + bne .Lctr_enc_loop + b .Lctr_enc_done + +.align 4 +.Lctr_enc_loop_done: + add $len, $len, #8 + vld1.8 {@XMM[8]}, [$inp]! @ load input + veor @XMM[0], @XMM[8] + vst1.8 {@XMM[0]}, [$out]! @ write output + cmp $len, #2 + blo .Lctr_enc_done + vld1.8 {@XMM[9]}, [$inp]! + veor @XMM[1], @XMM[9] + vst1.8 {@XMM[1]}, [$out]! + beq .Lctr_enc_done + vld1.8 {@XMM[10]}, [$inp]! + veor @XMM[4], @XMM[10] + vst1.8 {@XMM[4]}, [$out]! + cmp $len, #4 + blo .Lctr_enc_done + vld1.8 {@XMM[11]}, [$inp]! + veor @XMM[6], @XMM[11] + vst1.8 {@XMM[6]}, [$out]! + beq .Lctr_enc_done + vld1.8 {@XMM[12]}, [$inp]! + veor @XMM[3], @XMM[12] + vst1.8 {@XMM[3]}, [$out]! + cmp $len, #6 + blo .Lctr_enc_done + vld1.8 {@XMM[13]}, [$inp]! + veor @XMM[7], @XMM[13] + vst1.8 {@XMM[7]}, [$out]! + beq .Lctr_enc_done + vld1.8 {@XMM[14]}, [$inp] + veor @XMM[2], @XMM[14] + vst1.8 {@XMM[2]}, [$out]! + +.Lctr_enc_done: + vmov.i32 q0, #0 + vmov.i32 q1, #0 +#ifndef BSAES_ASM_EXTENDED_KEY +.Lctr_enc_bzero: @ wipe key schedule [if any] + vstmia $keysched!, {q0-q1} + cmp $keysched, $fp + bne .Lctr_enc_bzero +#else + vstmia $keysched, {q0-q1} +#endif + + mov sp, $fp + add sp, #0x10 @ add sp,$fp,#0x10 is no good for thumb + VFP_ABI_POP + ldmia sp!, {r4-r10, pc} @ return + +.align 4 +.Lctr_enc_short: + ldr ip, [sp] @ ctr pointer is passed on stack + stmdb sp!, {r4-r8, lr} + + mov r4, $inp @ copy arguments + mov r5, $out + mov r6, $len + mov r7, $key + ldr r8, [ip, #12] @ load counter LSW + vld1.8 {@XMM[1]}, [ip] @ load whole counter value +#ifdef __ARMEL__ + rev r8, r8 +#endif + sub sp, sp, #0x10 + vst1.8 {@XMM[1]}, [sp] @ copy counter value + sub sp, sp, #0x10 + +.Lctr_enc_short_loop: + add r0, sp, #0x10 @ input counter value + mov r1, sp @ output on the stack + mov r2, r7 @ key + + bl AES_encrypt + + vld1.8 {@XMM[0]}, [r4]! @ load input + vld1.8 {@XMM[1]}, [sp] @ load encrypted counter + add r8, r8, #1 +#ifdef __ARMEL__ + rev r0, r8 + str r0, [sp, #0x1c] @ next counter value +#else + str r8, [sp, #0x1c] @ next counter value +#endif + veor @XMM[0],@XMM[0],@XMM[1] + vst1.8 {@XMM[0]}, [r5]! @ store output + subs r6, r6, #1 + bne .Lctr_enc_short_loop + + vmov.i32 q0, #0 + vmov.i32 q1, #0 + vstmia sp!, {q0-q1} + + ldmia sp!, {r4-r8, pc} +.size bsaes_ctr32_encrypt_blocks,.-bsaes_ctr32_encrypt_blocks +___ +} +{ +###################################################################### +# void bsaes_xts_[en|de]crypt(const char *inp,char *out,size_t len, +# const AES_KEY *key1, const AES_KEY *key2, +# const unsigned char iv[16]); +# +my ($inp,$out,$len,$key,$rounds,$magic,$fp)=(map("r$_",(7..10,1..3))); +my $const="r6"; # returned by _bsaes_key_convert +my $twmask=@XMM[5]; +my @T=@XMM[6..7]; + +$code.=<<___; +.globl bsaes_xts_encrypt +.type bsaes_xts_encrypt,%function +.align 4 +bsaes_xts_encrypt: + mov ip, sp + stmdb sp!, {r4-r10, lr} @ 0x20 + VFP_ABI_PUSH + mov r6, sp @ future $fp + + mov $inp, r0 + mov $out, r1 + mov $len, r2 + mov $key, r3 + + sub r0, sp, #0x10 @ 0x10 + bic r0, #0xf @ align at 16 bytes + mov sp, r0 + +#ifdef XTS_CHAIN_TWEAK + ldr r0, [ip] @ pointer to input tweak +#else + @ generate initial tweak + ldr r0, [ip, #4] @ iv[] + mov r1, sp + ldr r2, [ip, #0] @ key2 + bl AES_encrypt + mov r0,sp @ pointer to initial tweak +#endif + + ldr $rounds, [$key, #240] @ get # of rounds + mov $fp, r6 +#ifndef BSAES_ASM_EXTENDED_KEY + @ allocate the key schedule on the stack + sub r12, sp, $rounds, lsl#7 @ 128 bytes per inner round key + @ add r12, #`128-32` @ size of bit-sliced key schedule + sub r12, #`32+16` @ place for tweak[9] + + @ populate the key schedule + mov r4, $key @ pass key + mov r5, $rounds @ pass # of rounds + mov sp, r12 + add r12, #0x90 @ pass key schedule + bl _bsaes_key_convert + veor @XMM[7], @XMM[7], @XMM[15] @ fix up last round key + vstmia r12, {@XMM[7]} @ save last round key +#else + ldr r12, [$key, #244] + eors r12, #1 + beq 0f + + str r12, [$key, #244] + mov r4, $key @ pass key + mov r5, $rounds @ pass # of rounds + add r12, $key, #248 @ pass key schedule + bl _bsaes_key_convert + veor @XMM[7], @XMM[7], @XMM[15] @ fix up last round key + vstmia r12, {@XMM[7]} + +.align 2 +0: sub sp, #0x90 @ place for tweak[9] +#endif + + vld1.8 {@XMM[8]}, [r0] @ initial tweak + adr $magic, .Lxts_magic + + subs $len, #0x80 + blo .Lxts_enc_short + b .Lxts_enc_loop + +.align 4 +.Lxts_enc_loop: + vldmia $magic, {$twmask} @ load XTS magic + vshr.s64 @T[0], @XMM[8], #63 + mov r0, sp + vand @T[0], @T[0], $twmask +___ +for($i=9;$i<16;$i++) { +$code.=<<___; + vadd.u64 @XMM[$i], @XMM[$i-1], @XMM[$i-1] + vst1.64 {@XMM[$i-1]}, [r0,:128]! + vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")` + vshr.s64 @T[1], @XMM[$i], #63 + veor @XMM[$i], @XMM[$i], @T[0] + vand @T[1], @T[1], $twmask +___ + @T=reverse(@T); + +$code.=<<___ if ($i>=10); + vld1.8 {@XMM[$i-10]}, [$inp]! +___ +$code.=<<___ if ($i>=11); + veor @XMM[$i-11], @XMM[$i-11], @XMM[$i-3] +___ +} +$code.=<<___; + vadd.u64 @XMM[8], @XMM[15], @XMM[15] + vst1.64 {@XMM[15]}, [r0,:128]! + vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")` + veor @XMM[8], @XMM[8], @T[0] + vst1.64 {@XMM[8]}, [r0,:128] @ next round tweak + + vld1.8 {@XMM[6]-@XMM[7]}, [$inp]! + veor @XMM[5], @XMM[5], @XMM[13] +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, sp, #0x90 @ pass key schedule +#else + add r4, $key, #248 @ pass key schedule +#endif + veor @XMM[6], @XMM[6], @XMM[14] + mov r5, $rounds @ pass rounds + veor @XMM[7], @XMM[7], @XMM[15] + mov r0, sp + + bl _bsaes_encrypt8 + + vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]! + vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]! + veor @XMM[0], @XMM[0], @XMM[ 8] + vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]! + veor @XMM[1], @XMM[1], @XMM[ 9] + veor @XMM[8], @XMM[4], @XMM[10] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! + veor @XMM[9], @XMM[6], @XMM[11] + vld1.64 {@XMM[14]-@XMM[15]}, [r0,:128]! + veor @XMM[10], @XMM[3], @XMM[12] + vst1.8 {@XMM[8]-@XMM[9]}, [$out]! + veor @XMM[11], @XMM[7], @XMM[13] + veor @XMM[12], @XMM[2], @XMM[14] + vst1.8 {@XMM[10]-@XMM[11]}, [$out]! + veor @XMM[13], @XMM[5], @XMM[15] + vst1.8 {@XMM[12]-@XMM[13]}, [$out]! + + vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak + + subs $len, #0x80 + bpl .Lxts_enc_loop + +.Lxts_enc_short: + adds $len, #0x70 + bmi .Lxts_enc_done + + vldmia $magic, {$twmask} @ load XTS magic + vshr.s64 @T[0], @XMM[8], #63 + mov r0, sp + vand @T[0], @T[0], $twmask +___ +for($i=9;$i<16;$i++) { +$code.=<<___; + vadd.u64 @XMM[$i], @XMM[$i-1], @XMM[$i-1] + vst1.64 {@XMM[$i-1]}, [r0,:128]! + vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")` + vshr.s64 @T[1], @XMM[$i], #63 + veor @XMM[$i], @XMM[$i], @T[0] + vand @T[1], @T[1], $twmask +___ + @T=reverse(@T); + +$code.=<<___ if ($i>=10); + vld1.8 {@XMM[$i-10]}, [$inp]! + subs $len, #0x10 + bmi .Lxts_enc_`$i-9` +___ +$code.=<<___ if ($i>=11); + veor @XMM[$i-11], @XMM[$i-11], @XMM[$i-3] +___ +} +$code.=<<___; + sub $len, #0x10 + vst1.64 {@XMM[15]}, [r0,:128] @ next round tweak + + vld1.8 {@XMM[6]}, [$inp]! + veor @XMM[5], @XMM[5], @XMM[13] +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, sp, #0x90 @ pass key schedule +#else + add r4, $key, #248 @ pass key schedule +#endif + veor @XMM[6], @XMM[6], @XMM[14] + mov r5, $rounds @ pass rounds + mov r0, sp + + bl _bsaes_encrypt8 + + vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]! + vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]! + veor @XMM[0], @XMM[0], @XMM[ 8] + vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]! + veor @XMM[1], @XMM[1], @XMM[ 9] + veor @XMM[8], @XMM[4], @XMM[10] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! + veor @XMM[9], @XMM[6], @XMM[11] + vld1.64 {@XMM[14]}, [r0,:128]! + veor @XMM[10], @XMM[3], @XMM[12] + vst1.8 {@XMM[8]-@XMM[9]}, [$out]! + veor @XMM[11], @XMM[7], @XMM[13] + veor @XMM[12], @XMM[2], @XMM[14] + vst1.8 {@XMM[10]-@XMM[11]}, [$out]! + vst1.8 {@XMM[12]}, [$out]! + + vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak + b .Lxts_enc_done +.align 4 +.Lxts_enc_6: + veor @XMM[4], @XMM[4], @XMM[12] +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, sp, #0x90 @ pass key schedule +#else + add r4, $key, #248 @ pass key schedule +#endif + veor @XMM[5], @XMM[5], @XMM[13] + mov r5, $rounds @ pass rounds + mov r0, sp + + bl _bsaes_encrypt8 + + vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]! + vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]! + veor @XMM[0], @XMM[0], @XMM[ 8] + vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]! + veor @XMM[1], @XMM[1], @XMM[ 9] + veor @XMM[8], @XMM[4], @XMM[10] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! + veor @XMM[9], @XMM[6], @XMM[11] + veor @XMM[10], @XMM[3], @XMM[12] + vst1.8 {@XMM[8]-@XMM[9]}, [$out]! + veor @XMM[11], @XMM[7], @XMM[13] + vst1.8 {@XMM[10]-@XMM[11]}, [$out]! + + vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak + b .Lxts_enc_done + +@ put this in range for both ARM and Thumb mode adr instructions +.align 5 +.Lxts_magic: + .quad 1, 0x87 + +.align 5 +.Lxts_enc_5: + veor @XMM[3], @XMM[3], @XMM[11] +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, sp, #0x90 @ pass key schedule +#else + add r4, $key, #248 @ pass key schedule +#endif + veor @XMM[4], @XMM[4], @XMM[12] + mov r5, $rounds @ pass rounds + mov r0, sp + + bl _bsaes_encrypt8 + + vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]! + vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]! + veor @XMM[0], @XMM[0], @XMM[ 8] + vld1.64 {@XMM[12]}, [r0,:128]! + veor @XMM[1], @XMM[1], @XMM[ 9] + veor @XMM[8], @XMM[4], @XMM[10] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! + veor @XMM[9], @XMM[6], @XMM[11] + veor @XMM[10], @XMM[3], @XMM[12] + vst1.8 {@XMM[8]-@XMM[9]}, [$out]! + vst1.8 {@XMM[10]}, [$out]! + + vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak + b .Lxts_enc_done +.align 4 +.Lxts_enc_4: + veor @XMM[2], @XMM[2], @XMM[10] +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, sp, #0x90 @ pass key schedule +#else + add r4, $key, #248 @ pass key schedule +#endif + veor @XMM[3], @XMM[3], @XMM[11] + mov r5, $rounds @ pass rounds + mov r0, sp + + bl _bsaes_encrypt8 + + vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]! + vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]! + veor @XMM[0], @XMM[0], @XMM[ 8] + veor @XMM[1], @XMM[1], @XMM[ 9] + veor @XMM[8], @XMM[4], @XMM[10] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! + veor @XMM[9], @XMM[6], @XMM[11] + vst1.8 {@XMM[8]-@XMM[9]}, [$out]! + + vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak + b .Lxts_enc_done +.align 4 +.Lxts_enc_3: + veor @XMM[1], @XMM[1], @XMM[9] +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, sp, #0x90 @ pass key schedule +#else + add r4, $key, #248 @ pass key schedule +#endif + veor @XMM[2], @XMM[2], @XMM[10] + mov r5, $rounds @ pass rounds + mov r0, sp + + bl _bsaes_encrypt8 + + vld1.64 {@XMM[8]-@XMM[9]}, [r0,:128]! + vld1.64 {@XMM[10]}, [r0,:128]! + veor @XMM[0], @XMM[0], @XMM[ 8] + veor @XMM[1], @XMM[1], @XMM[ 9] + veor @XMM[8], @XMM[4], @XMM[10] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! + vst1.8 {@XMM[8]}, [$out]! + + vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak + b .Lxts_enc_done +.align 4 +.Lxts_enc_2: + veor @XMM[0], @XMM[0], @XMM[8] +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, sp, #0x90 @ pass key schedule +#else + add r4, $key, #248 @ pass key schedule +#endif + veor @XMM[1], @XMM[1], @XMM[9] + mov r5, $rounds @ pass rounds + mov r0, sp + + bl _bsaes_encrypt8 + + vld1.64 {@XMM[8]-@XMM[9]}, [r0,:128]! + veor @XMM[0], @XMM[0], @XMM[ 8] + veor @XMM[1], @XMM[1], @XMM[ 9] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! + + vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak + b .Lxts_enc_done +.align 4 +.Lxts_enc_1: + mov r0, sp + veor @XMM[0], @XMM[0], @XMM[8] + mov r1, sp + vst1.8 {@XMM[0]}, [sp,:128] + mov r2, $key + mov r4, $fp @ preserve fp + + bl AES_encrypt + + vld1.8 {@XMM[0]}, [sp,:128] + veor @XMM[0], @XMM[0], @XMM[8] + vst1.8 {@XMM[0]}, [$out]! + mov $fp, r4 + + vmov @XMM[8], @XMM[9] @ next round tweak + +.Lxts_enc_done: +#ifndef XTS_CHAIN_TWEAK + adds $len, #0x10 + beq .Lxts_enc_ret + sub r6, $out, #0x10 + +.Lxts_enc_steal: + ldrb r0, [$inp], #1 + ldrb r1, [$out, #-0x10] + strb r0, [$out, #-0x10] + strb r1, [$out], #1 + + subs $len, #1 + bhi .Lxts_enc_steal + + vld1.8 {@XMM[0]}, [r6] + mov r0, sp + veor @XMM[0], @XMM[0], @XMM[8] + mov r1, sp + vst1.8 {@XMM[0]}, [sp,:128] + mov r2, $key + mov r4, $fp @ preserve fp + + bl AES_encrypt + + vld1.8 {@XMM[0]}, [sp,:128] + veor @XMM[0], @XMM[0], @XMM[8] + vst1.8 {@XMM[0]}, [r6] + mov $fp, r4 +#endif + +.Lxts_enc_ret: + bic r0, $fp, #0xf + vmov.i32 q0, #0 + vmov.i32 q1, #0 +#ifdef XTS_CHAIN_TWEAK + ldr r1, [$fp, #0x20+VFP_ABI_FRAME] @ chain tweak +#endif +.Lxts_enc_bzero: @ wipe key schedule [if any] + vstmia sp!, {q0-q1} + cmp sp, r0 + bne .Lxts_enc_bzero + + mov sp, $fp +#ifdef XTS_CHAIN_TWEAK + vst1.8 {@XMM[8]}, [r1] +#endif + VFP_ABI_POP + ldmia sp!, {r4-r10, pc} @ return + +.size bsaes_xts_encrypt,.-bsaes_xts_encrypt + +.globl bsaes_xts_decrypt +.type bsaes_xts_decrypt,%function +.align 4 +bsaes_xts_decrypt: + mov ip, sp + stmdb sp!, {r4-r10, lr} @ 0x20 + VFP_ABI_PUSH + mov r6, sp @ future $fp + + mov $inp, r0 + mov $out, r1 + mov $len, r2 + mov $key, r3 + + sub r0, sp, #0x10 @ 0x10 + bic r0, #0xf @ align at 16 bytes + mov sp, r0 + +#ifdef XTS_CHAIN_TWEAK + ldr r0, [ip] @ pointer to input tweak +#else + @ generate initial tweak + ldr r0, [ip, #4] @ iv[] + mov r1, sp + ldr r2, [ip, #0] @ key2 + bl AES_encrypt + mov r0, sp @ pointer to initial tweak +#endif + + ldr $rounds, [$key, #240] @ get # of rounds + mov $fp, r6 +#ifndef BSAES_ASM_EXTENDED_KEY + @ allocate the key schedule on the stack + sub r12, sp, $rounds, lsl#7 @ 128 bytes per inner round key + @ add r12, #`128-32` @ size of bit-sliced key schedule + sub r12, #`32+16` @ place for tweak[9] + + @ populate the key schedule + mov r4, $key @ pass key + mov r5, $rounds @ pass # of rounds + mov sp, r12 + add r12, #0x90 @ pass key schedule + bl _bsaes_key_convert + add r4, sp, #0x90 + vldmia r4, {@XMM[6]} + vstmia r12, {@XMM[15]} @ save last round key + veor @XMM[7], @XMM[7], @XMM[6] @ fix up round 0 key + vstmia r4, {@XMM[7]} +#else + ldr r12, [$key, #244] + eors r12, #1 + beq 0f + + str r12, [$key, #244] + mov r4, $key @ pass key + mov r5, $rounds @ pass # of rounds + add r12, $key, #248 @ pass key schedule + bl _bsaes_key_convert + add r4, $key, #248 + vldmia r4, {@XMM[6]} + vstmia r12, {@XMM[15]} @ save last round key + veor @XMM[7], @XMM[7], @XMM[6] @ fix up round 0 key + vstmia r4, {@XMM[7]} + +.align 2 +0: sub sp, #0x90 @ place for tweak[9] +#endif + vld1.8 {@XMM[8]}, [r0] @ initial tweak + adr $magic, .Lxts_magic + +#ifndef XTS_CHAIN_TWEAK + tst $len, #0xf @ if not multiple of 16 + it ne @ Thumb2 thing, sanity check in ARM + subne $len, #0x10 @ subtract another 16 bytes +#endif + subs $len, #0x80 + + blo .Lxts_dec_short + b .Lxts_dec_loop + +.align 4 +.Lxts_dec_loop: + vldmia $magic, {$twmask} @ load XTS magic + vshr.s64 @T[0], @XMM[8], #63 + mov r0, sp + vand @T[0], @T[0], $twmask +___ +for($i=9;$i<16;$i++) { +$code.=<<___; + vadd.u64 @XMM[$i], @XMM[$i-1], @XMM[$i-1] + vst1.64 {@XMM[$i-1]}, [r0,:128]! + vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")` + vshr.s64 @T[1], @XMM[$i], #63 + veor @XMM[$i], @XMM[$i], @T[0] + vand @T[1], @T[1], $twmask +___ + @T=reverse(@T); + +$code.=<<___ if ($i>=10); + vld1.8 {@XMM[$i-10]}, [$inp]! +___ +$code.=<<___ if ($i>=11); + veor @XMM[$i-11], @XMM[$i-11], @XMM[$i-3] +___ +} +$code.=<<___; + vadd.u64 @XMM[8], @XMM[15], @XMM[15] + vst1.64 {@XMM[15]}, [r0,:128]! + vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")` + veor @XMM[8], @XMM[8], @T[0] + vst1.64 {@XMM[8]}, [r0,:128] @ next round tweak + + vld1.8 {@XMM[6]-@XMM[7]}, [$inp]! + veor @XMM[5], @XMM[5], @XMM[13] +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, sp, #0x90 @ pass key schedule +#else + add r4, $key, #248 @ pass key schedule +#endif + veor @XMM[6], @XMM[6], @XMM[14] + mov r5, $rounds @ pass rounds + veor @XMM[7], @XMM[7], @XMM[15] + mov r0, sp + + bl _bsaes_decrypt8 + + vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]! + vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]! + veor @XMM[0], @XMM[0], @XMM[ 8] + vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]! + veor @XMM[1], @XMM[1], @XMM[ 9] + veor @XMM[8], @XMM[6], @XMM[10] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! + veor @XMM[9], @XMM[4], @XMM[11] + vld1.64 {@XMM[14]-@XMM[15]}, [r0,:128]! + veor @XMM[10], @XMM[2], @XMM[12] + vst1.8 {@XMM[8]-@XMM[9]}, [$out]! + veor @XMM[11], @XMM[7], @XMM[13] + veor @XMM[12], @XMM[3], @XMM[14] + vst1.8 {@XMM[10]-@XMM[11]}, [$out]! + veor @XMM[13], @XMM[5], @XMM[15] + vst1.8 {@XMM[12]-@XMM[13]}, [$out]! + + vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak + + subs $len, #0x80 + bpl .Lxts_dec_loop + +.Lxts_dec_short: + adds $len, #0x70 + bmi .Lxts_dec_done + + vldmia $magic, {$twmask} @ load XTS magic + vshr.s64 @T[0], @XMM[8], #63 + mov r0, sp + vand @T[0], @T[0], $twmask +___ +for($i=9;$i<16;$i++) { +$code.=<<___; + vadd.u64 @XMM[$i], @XMM[$i-1], @XMM[$i-1] + vst1.64 {@XMM[$i-1]}, [r0,:128]! + vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")` + vshr.s64 @T[1], @XMM[$i], #63 + veor @XMM[$i], @XMM[$i], @T[0] + vand @T[1], @T[1], $twmask +___ + @T=reverse(@T); + +$code.=<<___ if ($i>=10); + vld1.8 {@XMM[$i-10]}, [$inp]! + subs $len, #0x10 + bmi .Lxts_dec_`$i-9` +___ +$code.=<<___ if ($i>=11); + veor @XMM[$i-11], @XMM[$i-11], @XMM[$i-3] +___ +} +$code.=<<___; + sub $len, #0x10 + vst1.64 {@XMM[15]}, [r0,:128] @ next round tweak + + vld1.8 {@XMM[6]}, [$inp]! + veor @XMM[5], @XMM[5], @XMM[13] +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, sp, #0x90 @ pass key schedule +#else + add r4, $key, #248 @ pass key schedule +#endif + veor @XMM[6], @XMM[6], @XMM[14] + mov r5, $rounds @ pass rounds + mov r0, sp + + bl _bsaes_decrypt8 + + vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]! + vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]! + veor @XMM[0], @XMM[0], @XMM[ 8] + vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]! + veor @XMM[1], @XMM[1], @XMM[ 9] + veor @XMM[8], @XMM[6], @XMM[10] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! + veor @XMM[9], @XMM[4], @XMM[11] + vld1.64 {@XMM[14]}, [r0,:128]! + veor @XMM[10], @XMM[2], @XMM[12] + vst1.8 {@XMM[8]-@XMM[9]}, [$out]! + veor @XMM[11], @XMM[7], @XMM[13] + veor @XMM[12], @XMM[3], @XMM[14] + vst1.8 {@XMM[10]-@XMM[11]}, [$out]! + vst1.8 {@XMM[12]}, [$out]! + + vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak + b .Lxts_dec_done +.align 4 +.Lxts_dec_6: + vst1.64 {@XMM[14]}, [r0,:128] @ next round tweak + + veor @XMM[4], @XMM[4], @XMM[12] +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, sp, #0x90 @ pass key schedule +#else + add r4, $key, #248 @ pass key schedule +#endif + veor @XMM[5], @XMM[5], @XMM[13] + mov r5, $rounds @ pass rounds + mov r0, sp + + bl _bsaes_decrypt8 + + vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]! + vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]! + veor @XMM[0], @XMM[0], @XMM[ 8] + vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]! + veor @XMM[1], @XMM[1], @XMM[ 9] + veor @XMM[8], @XMM[6], @XMM[10] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! + veor @XMM[9], @XMM[4], @XMM[11] + veor @XMM[10], @XMM[2], @XMM[12] + vst1.8 {@XMM[8]-@XMM[9]}, [$out]! + veor @XMM[11], @XMM[7], @XMM[13] + vst1.8 {@XMM[10]-@XMM[11]}, [$out]! + + vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak + b .Lxts_dec_done +.align 4 +.Lxts_dec_5: + veor @XMM[3], @XMM[3], @XMM[11] +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, sp, #0x90 @ pass key schedule +#else + add r4, $key, #248 @ pass key schedule +#endif + veor @XMM[4], @XMM[4], @XMM[12] + mov r5, $rounds @ pass rounds + mov r0, sp + + bl _bsaes_decrypt8 + + vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]! + vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]! + veor @XMM[0], @XMM[0], @XMM[ 8] + vld1.64 {@XMM[12]}, [r0,:128]! + veor @XMM[1], @XMM[1], @XMM[ 9] + veor @XMM[8], @XMM[6], @XMM[10] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! + veor @XMM[9], @XMM[4], @XMM[11] + veor @XMM[10], @XMM[2], @XMM[12] + vst1.8 {@XMM[8]-@XMM[9]}, [$out]! + vst1.8 {@XMM[10]}, [$out]! + + vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak + b .Lxts_dec_done +.align 4 +.Lxts_dec_4: + veor @XMM[2], @XMM[2], @XMM[10] +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, sp, #0x90 @ pass key schedule +#else + add r4, $key, #248 @ pass key schedule +#endif + veor @XMM[3], @XMM[3], @XMM[11] + mov r5, $rounds @ pass rounds + mov r0, sp + + bl _bsaes_decrypt8 + + vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]! + vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]! + veor @XMM[0], @XMM[0], @XMM[ 8] + veor @XMM[1], @XMM[1], @XMM[ 9] + veor @XMM[8], @XMM[6], @XMM[10] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! + veor @XMM[9], @XMM[4], @XMM[11] + vst1.8 {@XMM[8]-@XMM[9]}, [$out]! + + vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak + b .Lxts_dec_done +.align 4 +.Lxts_dec_3: + veor @XMM[1], @XMM[1], @XMM[9] +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, sp, #0x90 @ pass key schedule +#else + add r4, $key, #248 @ pass key schedule +#endif + veor @XMM[2], @XMM[2], @XMM[10] + mov r5, $rounds @ pass rounds + mov r0, sp + + bl _bsaes_decrypt8 + + vld1.64 {@XMM[8]-@XMM[9]}, [r0,:128]! + vld1.64 {@XMM[10]}, [r0,:128]! + veor @XMM[0], @XMM[0], @XMM[ 8] + veor @XMM[1], @XMM[1], @XMM[ 9] + veor @XMM[8], @XMM[6], @XMM[10] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! + vst1.8 {@XMM[8]}, [$out]! + + vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak + b .Lxts_dec_done +.align 4 +.Lxts_dec_2: + veor @XMM[0], @XMM[0], @XMM[8] +#ifndef BSAES_ASM_EXTENDED_KEY + add r4, sp, #0x90 @ pass key schedule +#else + add r4, $key, #248 @ pass key schedule +#endif + veor @XMM[1], @XMM[1], @XMM[9] + mov r5, $rounds @ pass rounds + mov r0, sp + + bl _bsaes_decrypt8 + + vld1.64 {@XMM[8]-@XMM[9]}, [r0,:128]! + veor @XMM[0], @XMM[0], @XMM[ 8] + veor @XMM[1], @XMM[1], @XMM[ 9] + vst1.8 {@XMM[0]-@XMM[1]}, [$out]! + + vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak + b .Lxts_dec_done +.align 4 +.Lxts_dec_1: + mov r0, sp + veor @XMM[0], @XMM[0], @XMM[8] + mov r1, sp + vst1.8 {@XMM[0]}, [sp,:128] + mov r5, $magic @ preserve magic + mov r2, $key + mov r4, $fp @ preserve fp + + bl AES_decrypt + + vld1.8 {@XMM[0]}, [sp,:128] + veor @XMM[0], @XMM[0], @XMM[8] + vst1.8 {@XMM[0]}, [$out]! + mov $fp, r4 + mov $magic, r5 + + vmov @XMM[8], @XMM[9] @ next round tweak + +.Lxts_dec_done: +#ifndef XTS_CHAIN_TWEAK + adds $len, #0x10 + beq .Lxts_dec_ret + + @ calculate one round of extra tweak for the stolen ciphertext + vldmia $magic, {$twmask} + vshr.s64 @XMM[6], @XMM[8], #63 + vand @XMM[6], @XMM[6], $twmask + vadd.u64 @XMM[9], @XMM[8], @XMM[8] + vswp `&Dhi("@XMM[6]")`,`&Dlo("@XMM[6]")` + veor @XMM[9], @XMM[9], @XMM[6] + + @ perform the final decryption with the last tweak value + vld1.8 {@XMM[0]}, [$inp]! + mov r0, sp + veor @XMM[0], @XMM[0], @XMM[9] + mov r1, sp + vst1.8 {@XMM[0]}, [sp,:128] + mov r2, $key + mov r4, $fp @ preserve fp + + bl AES_decrypt + + vld1.8 {@XMM[0]}, [sp,:128] + veor @XMM[0], @XMM[0], @XMM[9] + vst1.8 {@XMM[0]}, [$out] + + mov r6, $out +.Lxts_dec_steal: + ldrb r1, [$out] + ldrb r0, [$inp], #1 + strb r1, [$out, #0x10] + strb r0, [$out], #1 + + subs $len, #1 + bhi .Lxts_dec_steal + + vld1.8 {@XMM[0]}, [r6] + mov r0, sp + veor @XMM[0], @XMM[8] + mov r1, sp + vst1.8 {@XMM[0]}, [sp,:128] + mov r2, $key + + bl AES_decrypt + + vld1.8 {@XMM[0]}, [sp,:128] + veor @XMM[0], @XMM[0], @XMM[8] + vst1.8 {@XMM[0]}, [r6] + mov $fp, r4 +#endif + +.Lxts_dec_ret: + bic r0, $fp, #0xf + vmov.i32 q0, #0 + vmov.i32 q1, #0 +#ifdef XTS_CHAIN_TWEAK + ldr r1, [$fp, #0x20+VFP_ABI_FRAME] @ chain tweak +#endif +.Lxts_dec_bzero: @ wipe key schedule [if any] + vstmia sp!, {q0-q1} + cmp sp, r0 + bne .Lxts_dec_bzero + + mov sp, $fp +#ifdef XTS_CHAIN_TWEAK + vst1.8 {@XMM[8]}, [r1] +#endif + VFP_ABI_POP + ldmia sp!, {r4-r10, pc} @ return + +.size bsaes_xts_decrypt,.-bsaes_xts_decrypt +___ +} +$code.=<<___; +#endif +___ + +$code =~ s/\`([^\`]*)\`/eval($1)/gem; + +open SELF,$0; +while() { + next if (/^#!/); + last if (!s/^#/@/ and !/^$/); + print; +} +close SELF; + +print $code; + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/bsaes-x86_64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/bsaes-x86_64.pl new file mode 100644 index 000000000..e62342729 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/bsaes-x86_64.pl @@ -0,0 +1,3239 @@ +#! /usr/bin/env perl +# Copyright 2011-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +################################################################### +### AES-128 [originally in CTR mode] ### +### bitsliced implementation for Intel Core 2 processors ### +### requires support of SSE extensions up to SSSE3 ### +### Author: Emilia Käsper and Peter Schwabe ### +### Date: 2009-03-19 ### +### Public domain ### +### ### +### See http://homes.esat.kuleuven.be/~ekasper/#software for ### +### further information. ### +################################################################### +# +# September 2011. +# +# Started as transliteration to "perlasm" the original code has +# undergone following changes: +# +# - code was made position-independent; +# - rounds were folded into a loop resulting in >5x size reduction +# from 12.5KB to 2.2KB; +# - above was possibile thanks to mixcolumns() modification that +# allowed to feed its output back to aesenc[last], this was +# achieved at cost of two additional inter-registers moves; +# - some instruction reordering and interleaving; +# - this module doesn't implement key setup subroutine, instead it +# relies on conversion of "conventional" key schedule as returned +# by AES_set_encrypt_key (see discussion below); +# - first and last round keys are treated differently, which allowed +# to skip one shiftrows(), reduce bit-sliced key schedule and +# speed-up conversion by 22%; +# - support for 192- and 256-bit keys was added; +# +# Resulting performance in CPU cycles spent to encrypt one byte out +# of 4096-byte buffer with 128-bit key is: +# +# Emilia's this(*) difference +# +# Core 2 9.30 8.69 +7% +# Nehalem(**) 7.63 6.88 +11% +# Atom 17.1 16.4 +4% +# Silvermont - 12.9 +# Goldmont - 8.85 +# +# (*) Comparison is not completely fair, because "this" is ECB, +# i.e. no extra processing such as counter values calculation +# and xor-ing input as in Emilia's CTR implementation is +# performed. However, the CTR calculations stand for not more +# than 1% of total time, so comparison is *rather* fair. +# +# (**) Results were collected on Westmere, which is considered to +# be equivalent to Nehalem for this code. +# +# As for key schedule conversion subroutine. Interface to OpenSSL +# relies on per-invocation on-the-fly conversion. This naturally +# has impact on performance, especially for short inputs. Conversion +# time in CPU cycles and its ratio to CPU cycles spent in 8x block +# function is: +# +# conversion conversion/8x block +# Core 2 240 0.22 +# Nehalem 180 0.20 +# Atom 430 0.20 +# +# The ratio values mean that 128-byte blocks will be processed +# 16-18% slower, 256-byte blocks - 9-10%, 384-byte blocks - 6-7%, +# etc. Then keep in mind that input sizes not divisible by 128 are +# *effectively* slower, especially shortest ones, e.g. consecutive +# 144-byte blocks are processed 44% slower than one would expect, +# 272 - 29%, 400 - 22%, etc. Yet, despite all these "shortcomings" +# it's still faster than ["hyper-threading-safe" code path in] +# aes-x86_64.pl on all lengths above 64 bytes... +# +# October 2011. +# +# Add decryption procedure. Performance in CPU cycles spent to decrypt +# one byte out of 4096-byte buffer with 128-bit key is: +# +# Core 2 9.98 +# Nehalem 7.80 +# Atom 17.9 +# Silvermont 14.0 +# Goldmont 10.2 +# +# November 2011. +# +# Add bsaes_xts_[en|de]crypt. Less-than-80-bytes-block performance is +# suboptimal, but XTS is meant to be used with larger blocks... +# +# + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +*STDOUT=*OUT; + +my ($inp,$out,$len,$key,$ivp)=("%rdi","%rsi","%rdx","%rcx"); +my @XMM=map("%xmm$_",(15,0..14)); # best on Atom, +10% over (0..15) +my $ecb=0; # suppress unreferenced ECB subroutines, spare some space... + +{ +my ($key,$rounds,$const)=("%rax","%r10d","%r11"); + +sub Sbox { +# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb +# output in lsb > [b0, b1, b4, b6, b3, b7, b2, b5] < msb +my @b=@_[0..7]; +my @t=@_[8..11]; +my @s=@_[12..15]; + &InBasisChange (@b); + &Inv_GF256 (@b[6,5,0,3,7,1,4,2],@t,@s); + &OutBasisChange (@b[7,1,4,2,6,5,0,3]); +} + +sub InBasisChange { +# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb +# output in lsb > [b6, b5, b0, b3, b7, b1, b4, b2] < msb +my @b=@_[0..7]; +$code.=<<___; + pxor @b[6], @b[5] + pxor @b[1], @b[2] + pxor @b[0], @b[3] + pxor @b[2], @b[6] + pxor @b[0], @b[5] + + pxor @b[3], @b[6] + pxor @b[7], @b[3] + pxor @b[5], @b[7] + pxor @b[4], @b[3] + pxor @b[5], @b[4] + pxor @b[1], @b[3] + + pxor @b[7], @b[2] + pxor @b[5], @b[1] +___ +} + +sub OutBasisChange { +# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb +# output in lsb > [b6, b1, b2, b4, b7, b0, b3, b5] < msb +my @b=@_[0..7]; +$code.=<<___; + pxor @b[6], @b[0] + pxor @b[4], @b[1] + pxor @b[0], @b[2] + pxor @b[6], @b[4] + pxor @b[1], @b[6] + + pxor @b[5], @b[1] + pxor @b[3], @b[5] + pxor @b[7], @b[3] + pxor @b[5], @b[7] + pxor @b[5], @b[2] + + pxor @b[7], @b[4] +___ +} + +sub InvSbox { +# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb +# output in lsb > [b0, b1, b6, b4, b2, b7, b3, b5] < msb +my @b=@_[0..7]; +my @t=@_[8..11]; +my @s=@_[12..15]; + &InvInBasisChange (@b); + &Inv_GF256 (@b[5,1,2,6,3,7,0,4],@t,@s); + &InvOutBasisChange (@b[3,7,0,4,5,1,2,6]); +} + +sub InvInBasisChange { # OutBasisChange in reverse +my @b=@_[5,1,2,6,3,7,0,4]; +$code.=<<___ + pxor @b[7], @b[4] + + pxor @b[5], @b[7] + pxor @b[5], @b[2] + pxor @b[7], @b[3] + pxor @b[3], @b[5] + pxor @b[5], @b[1] + + pxor @b[1], @b[6] + pxor @b[0], @b[2] + pxor @b[6], @b[4] + pxor @b[6], @b[0] + pxor @b[4], @b[1] +___ +} + +sub InvOutBasisChange { # InBasisChange in reverse +my @b=@_[2,5,7,3,6,1,0,4]; +$code.=<<___; + pxor @b[5], @b[1] + pxor @b[7], @b[2] + + pxor @b[1], @b[3] + pxor @b[5], @b[4] + pxor @b[5], @b[7] + pxor @b[4], @b[3] + pxor @b[0], @b[5] + pxor @b[7], @b[3] + pxor @b[2], @b[6] + pxor @b[1], @b[2] + pxor @b[3], @b[6] + + pxor @b[0], @b[3] + pxor @b[6], @b[5] +___ +} + +sub Mul_GF4 { +#;************************************************************* +#;* Mul_GF4: Input x0-x1,y0-y1 Output x0-x1 Temp t0 (8) * +#;************************************************************* +my ($x0,$x1,$y0,$y1,$t0)=@_; +$code.=<<___; + movdqa $y0, $t0 + pxor $y1, $t0 + pand $x0, $t0 + pxor $x1, $x0 + pand $y0, $x1 + pand $y1, $x0 + pxor $x1, $x0 + pxor $t0, $x1 +___ +} + +sub Mul_GF4_N { # not used, see next subroutine +# multiply and scale by N +my ($x0,$x1,$y0,$y1,$t0)=@_; +$code.=<<___; + movdqa $y0, $t0 + pxor $y1, $t0 + pand $x0, $t0 + pxor $x1, $x0 + pand $y0, $x1 + pand $y1, $x0 + pxor $x0, $x1 + pxor $t0, $x0 +___ +} + +sub Mul_GF4_N_GF4 { +# interleaved Mul_GF4_N and Mul_GF4 +my ($x0,$x1,$y0,$y1,$t0, + $x2,$x3,$y2,$y3,$t1)=@_; +$code.=<<___; + movdqa $y0, $t0 + movdqa $y2, $t1 + pxor $y1, $t0 + pxor $y3, $t1 + pand $x0, $t0 + pand $x2, $t1 + pxor $x1, $x0 + pxor $x3, $x2 + pand $y0, $x1 + pand $y2, $x3 + pand $y1, $x0 + pand $y3, $x2 + pxor $x0, $x1 + pxor $x3, $x2 + pxor $t0, $x0 + pxor $t1, $x3 +___ +} +sub Mul_GF16_2 { +my @x=@_[0..7]; +my @y=@_[8..11]; +my @t=@_[12..15]; +$code.=<<___; + movdqa @x[0], @t[0] + movdqa @x[1], @t[1] +___ + &Mul_GF4 (@x[0], @x[1], @y[0], @y[1], @t[2]); +$code.=<<___; + pxor @x[2], @t[0] + pxor @x[3], @t[1] + pxor @y[2], @y[0] + pxor @y[3], @y[1] +___ + Mul_GF4_N_GF4 (@t[0], @t[1], @y[0], @y[1], @t[3], + @x[2], @x[3], @y[2], @y[3], @t[2]); +$code.=<<___; + pxor @t[0], @x[0] + pxor @t[0], @x[2] + pxor @t[1], @x[1] + pxor @t[1], @x[3] + + movdqa @x[4], @t[0] + movdqa @x[5], @t[1] + pxor @x[6], @t[0] + pxor @x[7], @t[1] +___ + &Mul_GF4_N_GF4 (@t[0], @t[1], @y[0], @y[1], @t[3], + @x[6], @x[7], @y[2], @y[3], @t[2]); +$code.=<<___; + pxor @y[2], @y[0] + pxor @y[3], @y[1] +___ + &Mul_GF4 (@x[4], @x[5], @y[0], @y[1], @t[3]); +$code.=<<___; + pxor @t[0], @x[4] + pxor @t[0], @x[6] + pxor @t[1], @x[5] + pxor @t[1], @x[7] +___ +} +sub Inv_GF256 { +#;******************************************************************** +#;* Inv_GF256: Input x0-x7 Output x0-x7 Temp t0-t3,s0-s3 (144) * +#;******************************************************************** +my @x=@_[0..7]; +my @t=@_[8..11]; +my @s=@_[12..15]; +# direct optimizations from hardware +$code.=<<___; + movdqa @x[4], @t[3] + movdqa @x[5], @t[2] + movdqa @x[1], @t[1] + movdqa @x[7], @s[1] + movdqa @x[0], @s[0] + + pxor @x[6], @t[3] + pxor @x[7], @t[2] + pxor @x[3], @t[1] + movdqa @t[3], @s[2] + pxor @x[6], @s[1] + movdqa @t[2], @t[0] + pxor @x[2], @s[0] + movdqa @t[3], @s[3] + + por @t[1], @t[2] + por @s[0], @t[3] + pxor @t[0], @s[3] + pand @s[0], @s[2] + pxor @t[1], @s[0] + pand @t[1], @t[0] + pand @s[0], @s[3] + movdqa @x[3], @s[0] + pxor @x[2], @s[0] + pand @s[0], @s[1] + pxor @s[1], @t[3] + pxor @s[1], @t[2] + movdqa @x[4], @s[1] + movdqa @x[1], @s[0] + pxor @x[5], @s[1] + pxor @x[0], @s[0] + movdqa @s[1], @t[1] + pand @s[0], @s[1] + por @s[0], @t[1] + pxor @s[1], @t[0] + pxor @s[3], @t[3] + pxor @s[2], @t[2] + pxor @s[3], @t[1] + movdqa @x[7], @s[0] + pxor @s[2], @t[0] + movdqa @x[6], @s[1] + pxor @s[2], @t[1] + movdqa @x[5], @s[2] + pand @x[3], @s[0] + movdqa @x[4], @s[3] + pand @x[2], @s[1] + pand @x[1], @s[2] + por @x[0], @s[3] + pxor @s[0], @t[3] + pxor @s[1], @t[2] + pxor @s[2], @t[1] + pxor @s[3], @t[0] + + #Inv_GF16 \t0, \t1, \t2, \t3, \s0, \s1, \s2, \s3 + + # new smaller inversion + + movdqa @t[3], @s[0] + pand @t[1], @t[3] + pxor @t[2], @s[0] + + movdqa @t[0], @s[2] + movdqa @s[0], @s[3] + pxor @t[3], @s[2] + pand @s[2], @s[3] + + movdqa @t[1], @s[1] + pxor @t[2], @s[3] + pxor @t[0], @s[1] + + pxor @t[2], @t[3] + + pand @t[3], @s[1] + + movdqa @s[2], @t[2] + pxor @t[0], @s[1] + + pxor @s[1], @t[2] + pxor @s[1], @t[1] + + pand @t[0], @t[2] + + pxor @t[2], @s[2] + pxor @t[2], @t[1] + + pand @s[3], @s[2] + + pxor @s[0], @s[2] +___ +# output in s3, s2, s1, t1 + +# Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \t2, \t3, \t0, \t1, \s0, \s1, \s2, \s3 + +# Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \s3, \s2, \s1, \t1, \s0, \t0, \t2, \t3 + &Mul_GF16_2(@x,@s[3,2,1],@t[1],@s[0],@t[0,2,3]); + +### output msb > [x3,x2,x1,x0,x7,x6,x5,x4] < lsb +} + +# AES linear components + +sub ShiftRows { +my @x=@_[0..7]; +my $mask=pop; +$code.=<<___; + pxor 0x00($key),@x[0] + pxor 0x10($key),@x[1] + pxor 0x20($key),@x[2] + pxor 0x30($key),@x[3] + pshufb $mask,@x[0] + pshufb $mask,@x[1] + pxor 0x40($key),@x[4] + pxor 0x50($key),@x[5] + pshufb $mask,@x[2] + pshufb $mask,@x[3] + pxor 0x60($key),@x[6] + pxor 0x70($key),@x[7] + pshufb $mask,@x[4] + pshufb $mask,@x[5] + pshufb $mask,@x[6] + pshufb $mask,@x[7] + lea 0x80($key),$key +___ +} + +sub MixColumns { +# modified to emit output in order suitable for feeding back to aesenc[last] +my @x=@_[0..7]; +my @t=@_[8..15]; +my $inv=@_[16]; # optional +$code.=<<___; + pshufd \$0x93, @x[0], @t[0] # x0 <<< 32 + pshufd \$0x93, @x[1], @t[1] + pxor @t[0], @x[0] # x0 ^ (x0 <<< 32) + pshufd \$0x93, @x[2], @t[2] + pxor @t[1], @x[1] + pshufd \$0x93, @x[3], @t[3] + pxor @t[2], @x[2] + pshufd \$0x93, @x[4], @t[4] + pxor @t[3], @x[3] + pshufd \$0x93, @x[5], @t[5] + pxor @t[4], @x[4] + pshufd \$0x93, @x[6], @t[6] + pxor @t[5], @x[5] + pshufd \$0x93, @x[7], @t[7] + pxor @t[6], @x[6] + pxor @t[7], @x[7] + + pxor @x[0], @t[1] + pxor @x[7], @t[0] + pxor @x[7], @t[1] + pshufd \$0x4E, @x[0], @x[0] # (x0 ^ (x0 <<< 32)) <<< 64) + pxor @x[1], @t[2] + pshufd \$0x4E, @x[1], @x[1] + pxor @x[4], @t[5] + pxor @t[0], @x[0] + pxor @x[5], @t[6] + pxor @t[1], @x[1] + pxor @x[3], @t[4] + pshufd \$0x4E, @x[4], @t[0] + pxor @x[6], @t[7] + pshufd \$0x4E, @x[5], @t[1] + pxor @x[2], @t[3] + pshufd \$0x4E, @x[3], @x[4] + pxor @x[7], @t[3] + pshufd \$0x4E, @x[7], @x[5] + pxor @x[7], @t[4] + pshufd \$0x4E, @x[6], @x[3] + pxor @t[4], @t[0] + pshufd \$0x4E, @x[2], @x[6] + pxor @t[5], @t[1] +___ +$code.=<<___ if (!$inv); + pxor @t[3], @x[4] + pxor @t[7], @x[5] + pxor @t[6], @x[3] + movdqa @t[0], @x[2] + pxor @t[2], @x[6] + movdqa @t[1], @x[7] +___ +$code.=<<___ if ($inv); + pxor @x[4], @t[3] + pxor @t[7], @x[5] + pxor @x[3], @t[6] + movdqa @t[0], @x[3] + pxor @t[2], @x[6] + movdqa @t[6], @x[2] + movdqa @t[1], @x[7] + movdqa @x[6], @x[4] + movdqa @t[3], @x[6] +___ +} + +sub InvMixColumns_orig { +my @x=@_[0..7]; +my @t=@_[8..15]; + +$code.=<<___; + # multiplication by 0x0e + pshufd \$0x93, @x[7], @t[7] + movdqa @x[2], @t[2] + pxor @x[5], @x[7] # 7 5 + pxor @x[5], @x[2] # 2 5 + pshufd \$0x93, @x[0], @t[0] + movdqa @x[5], @t[5] + pxor @x[0], @x[5] # 5 0 [1] + pxor @x[1], @x[0] # 0 1 + pshufd \$0x93, @x[1], @t[1] + pxor @x[2], @x[1] # 1 25 + pxor @x[6], @x[0] # 01 6 [2] + pxor @x[3], @x[1] # 125 3 [4] + pshufd \$0x93, @x[3], @t[3] + pxor @x[0], @x[2] # 25 016 [3] + pxor @x[7], @x[3] # 3 75 + pxor @x[6], @x[7] # 75 6 [0] + pshufd \$0x93, @x[6], @t[6] + movdqa @x[4], @t[4] + pxor @x[4], @x[6] # 6 4 + pxor @x[3], @x[4] # 4 375 [6] + pxor @x[7], @x[3] # 375 756=36 + pxor @t[5], @x[6] # 64 5 [7] + pxor @t[2], @x[3] # 36 2 + pxor @t[4], @x[3] # 362 4 [5] + pshufd \$0x93, @t[5], @t[5] +___ + my @y = @x[7,5,0,2,1,3,4,6]; +$code.=<<___; + # multiplication by 0x0b + pxor @y[0], @y[1] + pxor @t[0], @y[0] + pxor @t[1], @y[1] + pshufd \$0x93, @t[2], @t[2] + pxor @t[5], @y[0] + pxor @t[6], @y[1] + pxor @t[7], @y[0] + pshufd \$0x93, @t[4], @t[4] + pxor @t[6], @t[7] # clobber t[7] + pxor @y[0], @y[1] + + pxor @t[0], @y[3] + pshufd \$0x93, @t[0], @t[0] + pxor @t[1], @y[2] + pxor @t[1], @y[4] + pxor @t[2], @y[2] + pshufd \$0x93, @t[1], @t[1] + pxor @t[2], @y[3] + pxor @t[2], @y[5] + pxor @t[7], @y[2] + pshufd \$0x93, @t[2], @t[2] + pxor @t[3], @y[3] + pxor @t[3], @y[6] + pxor @t[3], @y[4] + pshufd \$0x93, @t[3], @t[3] + pxor @t[4], @y[7] + pxor @t[4], @y[5] + pxor @t[7], @y[7] + pxor @t[5], @y[3] + pxor @t[4], @y[4] + pxor @t[5], @t[7] # clobber t[7] even more + + pxor @t[7], @y[5] + pshufd \$0x93, @t[4], @t[4] + pxor @t[7], @y[6] + pxor @t[7], @y[4] + + pxor @t[5], @t[7] + pshufd \$0x93, @t[5], @t[5] + pxor @t[6], @t[7] # restore t[7] + + # multiplication by 0x0d + pxor @y[7], @y[4] + pxor @t[4], @y[7] + pshufd \$0x93, @t[6], @t[6] + pxor @t[0], @y[2] + pxor @t[5], @y[7] + pxor @t[2], @y[2] + pshufd \$0x93, @t[7], @t[7] + + pxor @y[1], @y[3] + pxor @t[1], @y[1] + pxor @t[0], @y[0] + pxor @t[0], @y[3] + pxor @t[5], @y[1] + pxor @t[5], @y[0] + pxor @t[7], @y[1] + pshufd \$0x93, @t[0], @t[0] + pxor @t[6], @y[0] + pxor @y[1], @y[3] + pxor @t[1], @y[4] + pshufd \$0x93, @t[1], @t[1] + + pxor @t[7], @y[7] + pxor @t[2], @y[4] + pxor @t[2], @y[5] + pshufd \$0x93, @t[2], @t[2] + pxor @t[6], @y[2] + pxor @t[3], @t[6] # clobber t[6] + pxor @y[7], @y[4] + pxor @t[6], @y[3] + + pxor @t[6], @y[6] + pxor @t[5], @y[5] + pxor @t[4], @y[6] + pshufd \$0x93, @t[4], @t[4] + pxor @t[6], @y[5] + pxor @t[7], @y[6] + pxor @t[3], @t[6] # restore t[6] + + pshufd \$0x93, @t[5], @t[5] + pshufd \$0x93, @t[6], @t[6] + pshufd \$0x93, @t[7], @t[7] + pshufd \$0x93, @t[3], @t[3] + + # multiplication by 0x09 + pxor @y[1], @y[4] + pxor @y[1], @t[1] # t[1]=y[1] + pxor @t[5], @t[0] # clobber t[0] + pxor @t[5], @t[1] + pxor @t[0], @y[3] + pxor @y[0], @t[0] # t[0]=y[0] + pxor @t[6], @t[1] + pxor @t[7], @t[6] # clobber t[6] + pxor @t[1], @y[4] + pxor @t[4], @y[7] + pxor @y[4], @t[4] # t[4]=y[4] + pxor @t[3], @y[6] + pxor @y[3], @t[3] # t[3]=y[3] + pxor @t[2], @y[5] + pxor @y[2], @t[2] # t[2]=y[2] + pxor @t[7], @t[3] + pxor @y[5], @t[5] # t[5]=y[5] + pxor @t[6], @t[2] + pxor @t[6], @t[5] + pxor @y[6], @t[6] # t[6]=y[6] + pxor @y[7], @t[7] # t[7]=y[7] + + movdqa @t[0],@XMM[0] + movdqa @t[1],@XMM[1] + movdqa @t[2],@XMM[2] + movdqa @t[3],@XMM[3] + movdqa @t[4],@XMM[4] + movdqa @t[5],@XMM[5] + movdqa @t[6],@XMM[6] + movdqa @t[7],@XMM[7] +___ +} + +sub InvMixColumns { +my @x=@_[0..7]; +my @t=@_[8..15]; + +# Thanks to Jussi Kivilinna for providing pointer to +# +# | 0e 0b 0d 09 | | 02 03 01 01 | | 05 00 04 00 | +# | 09 0e 0b 0d | = | 01 02 03 01 | x | 00 05 00 04 | +# | 0d 09 0e 0b | | 01 01 02 03 | | 04 00 05 00 | +# | 0b 0d 09 0e | | 03 01 01 02 | | 00 04 00 05 | + +$code.=<<___; + # multiplication by 0x05-0x00-0x04-0x00 + pshufd \$0x4E, @x[0], @t[0] + pshufd \$0x4E, @x[6], @t[6] + pxor @x[0], @t[0] + pshufd \$0x4E, @x[7], @t[7] + pxor @x[6], @t[6] + pshufd \$0x4E, @x[1], @t[1] + pxor @x[7], @t[7] + pshufd \$0x4E, @x[2], @t[2] + pxor @x[1], @t[1] + pshufd \$0x4E, @x[3], @t[3] + pxor @x[2], @t[2] + pxor @t[6], @x[0] + pxor @t[6], @x[1] + pshufd \$0x4E, @x[4], @t[4] + pxor @x[3], @t[3] + pxor @t[0], @x[2] + pxor @t[1], @x[3] + pshufd \$0x4E, @x[5], @t[5] + pxor @x[4], @t[4] + pxor @t[7], @x[1] + pxor @t[2], @x[4] + pxor @x[5], @t[5] + + pxor @t[7], @x[2] + pxor @t[6], @x[3] + pxor @t[6], @x[4] + pxor @t[3], @x[5] + pxor @t[4], @x[6] + pxor @t[7], @x[4] + pxor @t[7], @x[5] + pxor @t[5], @x[7] +___ + &MixColumns (@x,@t,1); # flipped 2<->3 and 4<->6 +} + +sub aesenc { # not used +my @b=@_[0..7]; +my @t=@_[8..15]; +$code.=<<___; + movdqa 0x30($const),@t[0] # .LSR +___ + &ShiftRows (@b,@t[0]); + &Sbox (@b,@t); + &MixColumns (@b[0,1,4,6,3,7,2,5],@t); +} + +sub aesenclast { # not used +my @b=@_[0..7]; +my @t=@_[8..15]; +$code.=<<___; + movdqa 0x40($const),@t[0] # .LSRM0 +___ + &ShiftRows (@b,@t[0]); + &Sbox (@b,@t); +$code.=<<___ + pxor 0x00($key),@b[0] + pxor 0x10($key),@b[1] + pxor 0x20($key),@b[4] + pxor 0x30($key),@b[6] + pxor 0x40($key),@b[3] + pxor 0x50($key),@b[7] + pxor 0x60($key),@b[2] + pxor 0x70($key),@b[5] +___ +} + +sub swapmove { +my ($a,$b,$n,$mask,$t)=@_; +$code.=<<___; + movdqa $b,$t + psrlq \$$n,$b + pxor $a,$b + pand $mask,$b + pxor $b,$a + psllq \$$n,$b + pxor $t,$b +___ +} +sub swapmove2x { +my ($a0,$b0,$a1,$b1,$n,$mask,$t0,$t1)=@_; +$code.=<<___; + movdqa $b0,$t0 + psrlq \$$n,$b0 + movdqa $b1,$t1 + psrlq \$$n,$b1 + pxor $a0,$b0 + pxor $a1,$b1 + pand $mask,$b0 + pand $mask,$b1 + pxor $b0,$a0 + psllq \$$n,$b0 + pxor $b1,$a1 + psllq \$$n,$b1 + pxor $t0,$b0 + pxor $t1,$b1 +___ +} + +sub bitslice { +my @x=reverse(@_[0..7]); +my ($t0,$t1,$t2,$t3)=@_[8..11]; +$code.=<<___; + movdqa 0x00($const),$t0 # .LBS0 + movdqa 0x10($const),$t1 # .LBS1 +___ + &swapmove2x(@x[0,1,2,3],1,$t0,$t2,$t3); + &swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3); +$code.=<<___; + movdqa 0x20($const),$t0 # .LBS2 +___ + &swapmove2x(@x[0,2,1,3],2,$t1,$t2,$t3); + &swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3); + + &swapmove2x(@x[0,4,1,5],4,$t0,$t2,$t3); + &swapmove2x(@x[2,6,3,7],4,$t0,$t2,$t3); +} + +$code.=<<___; +.text + +.extern asm_AES_encrypt +.extern asm_AES_decrypt + +.type _bsaes_encrypt8,\@abi-omnipotent +.align 64 +_bsaes_encrypt8: +.cfi_startproc + lea .LBS0(%rip), $const # constants table + + movdqa ($key), @XMM[9] # round 0 key + lea 0x10($key), $key + movdqa 0x50($const), @XMM[8] # .LM0SR + pxor @XMM[9], @XMM[0] # xor with round0 key + pxor @XMM[9], @XMM[1] + pxor @XMM[9], @XMM[2] + pxor @XMM[9], @XMM[3] + pshufb @XMM[8], @XMM[0] + pshufb @XMM[8], @XMM[1] + pxor @XMM[9], @XMM[4] + pxor @XMM[9], @XMM[5] + pshufb @XMM[8], @XMM[2] + pshufb @XMM[8], @XMM[3] + pxor @XMM[9], @XMM[6] + pxor @XMM[9], @XMM[7] + pshufb @XMM[8], @XMM[4] + pshufb @XMM[8], @XMM[5] + pshufb @XMM[8], @XMM[6] + pshufb @XMM[8], @XMM[7] +_bsaes_encrypt8_bitslice: +___ + &bitslice (@XMM[0..7, 8..11]); +$code.=<<___; + dec $rounds + jmp .Lenc_sbox +.align 16 +.Lenc_loop: +___ + &ShiftRows (@XMM[0..7, 8]); +$code.=".Lenc_sbox:\n"; + &Sbox (@XMM[0..7, 8..15]); +$code.=<<___; + dec $rounds + jl .Lenc_done +___ + &MixColumns (@XMM[0,1,4,6,3,7,2,5, 8..15]); +$code.=<<___; + movdqa 0x30($const), @XMM[8] # .LSR + jnz .Lenc_loop + movdqa 0x40($const), @XMM[8] # .LSRM0 + jmp .Lenc_loop +.align 16 +.Lenc_done: +___ + # output in lsb > [t0, t1, t4, t6, t3, t7, t2, t5] < msb + &bitslice (@XMM[0,1,4,6,3,7,2,5, 8..11]); +$code.=<<___; + movdqa ($key), @XMM[8] # last round key + pxor @XMM[8], @XMM[4] + pxor @XMM[8], @XMM[6] + pxor @XMM[8], @XMM[3] + pxor @XMM[8], @XMM[7] + pxor @XMM[8], @XMM[2] + pxor @XMM[8], @XMM[5] + pxor @XMM[8], @XMM[0] + pxor @XMM[8], @XMM[1] + ret +.cfi_endproc +.size _bsaes_encrypt8,.-_bsaes_encrypt8 + +.type _bsaes_decrypt8,\@abi-omnipotent +.align 64 +_bsaes_decrypt8: +.cfi_startproc + lea .LBS0(%rip), $const # constants table + + movdqa ($key), @XMM[9] # round 0 key + lea 0x10($key), $key + movdqa -0x30($const), @XMM[8] # .LM0ISR + pxor @XMM[9], @XMM[0] # xor with round0 key + pxor @XMM[9], @XMM[1] + pxor @XMM[9], @XMM[2] + pxor @XMM[9], @XMM[3] + pshufb @XMM[8], @XMM[0] + pshufb @XMM[8], @XMM[1] + pxor @XMM[9], @XMM[4] + pxor @XMM[9], @XMM[5] + pshufb @XMM[8], @XMM[2] + pshufb @XMM[8], @XMM[3] + pxor @XMM[9], @XMM[6] + pxor @XMM[9], @XMM[7] + pshufb @XMM[8], @XMM[4] + pshufb @XMM[8], @XMM[5] + pshufb @XMM[8], @XMM[6] + pshufb @XMM[8], @XMM[7] +___ + &bitslice (@XMM[0..7, 8..11]); +$code.=<<___; + dec $rounds + jmp .Ldec_sbox +.align 16 +.Ldec_loop: +___ + &ShiftRows (@XMM[0..7, 8]); +$code.=".Ldec_sbox:\n"; + &InvSbox (@XMM[0..7, 8..15]); +$code.=<<___; + dec $rounds + jl .Ldec_done +___ + &InvMixColumns (@XMM[0,1,6,4,2,7,3,5, 8..15]); +$code.=<<___; + movdqa -0x10($const), @XMM[8] # .LISR + jnz .Ldec_loop + movdqa -0x20($const), @XMM[8] # .LISRM0 + jmp .Ldec_loop +.align 16 +.Ldec_done: +___ + &bitslice (@XMM[0,1,6,4,2,7,3,5, 8..11]); +$code.=<<___; + movdqa ($key), @XMM[8] # last round key + pxor @XMM[8], @XMM[6] + pxor @XMM[8], @XMM[4] + pxor @XMM[8], @XMM[2] + pxor @XMM[8], @XMM[7] + pxor @XMM[8], @XMM[3] + pxor @XMM[8], @XMM[5] + pxor @XMM[8], @XMM[0] + pxor @XMM[8], @XMM[1] + ret +.cfi_endproc +.size _bsaes_decrypt8,.-_bsaes_decrypt8 +___ +} +{ +my ($out,$inp,$rounds,$const)=("%rax","%rcx","%r10d","%r11"); + +sub bitslice_key { +my @x=reverse(@_[0..7]); +my ($bs0,$bs1,$bs2,$t2,$t3)=@_[8..12]; + + &swapmove (@x[0,1],1,$bs0,$t2,$t3); +$code.=<<___; + #&swapmove(@x[2,3],1,$t0,$t2,$t3); + movdqa @x[0], @x[2] + movdqa @x[1], @x[3] +___ + #&swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3); + + &swapmove2x (@x[0,2,1,3],2,$bs1,$t2,$t3); +$code.=<<___; + #&swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3); + movdqa @x[0], @x[4] + movdqa @x[2], @x[6] + movdqa @x[1], @x[5] + movdqa @x[3], @x[7] +___ + &swapmove2x (@x[0,4,1,5],4,$bs2,$t2,$t3); + &swapmove2x (@x[2,6,3,7],4,$bs2,$t2,$t3); +} + +$code.=<<___; +.type _bsaes_key_convert,\@abi-omnipotent +.align 16 +_bsaes_key_convert: +.cfi_startproc + lea .Lmasks(%rip), $const + movdqu ($inp), %xmm7 # load round 0 key + lea 0x10($inp), $inp + movdqa 0x00($const), %xmm0 # 0x01... + movdqa 0x10($const), %xmm1 # 0x02... + movdqa 0x20($const), %xmm2 # 0x04... + movdqa 0x30($const), %xmm3 # 0x08... + movdqa 0x40($const), %xmm4 # .LM0 + pcmpeqd %xmm5, %xmm5 # .LNOT + + movdqu ($inp), %xmm6 # load round 1 key + movdqa %xmm7, ($out) # save round 0 key + lea 0x10($out), $out + dec $rounds + jmp .Lkey_loop +.align 16 +.Lkey_loop: + pshufb %xmm4, %xmm6 # .LM0 + + movdqa %xmm0, %xmm8 + movdqa %xmm1, %xmm9 + + pand %xmm6, %xmm8 + pand %xmm6, %xmm9 + movdqa %xmm2, %xmm10 + pcmpeqb %xmm0, %xmm8 + psllq \$4, %xmm0 # 0x10... + movdqa %xmm3, %xmm11 + pcmpeqb %xmm1, %xmm9 + psllq \$4, %xmm1 # 0x20... + + pand %xmm6, %xmm10 + pand %xmm6, %xmm11 + movdqa %xmm0, %xmm12 + pcmpeqb %xmm2, %xmm10 + psllq \$4, %xmm2 # 0x40... + movdqa %xmm1, %xmm13 + pcmpeqb %xmm3, %xmm11 + psllq \$4, %xmm3 # 0x80... + + movdqa %xmm2, %xmm14 + movdqa %xmm3, %xmm15 + pxor %xmm5, %xmm8 # "pnot" + pxor %xmm5, %xmm9 + + pand %xmm6, %xmm12 + pand %xmm6, %xmm13 + movdqa %xmm8, 0x00($out) # write bit-sliced round key + pcmpeqb %xmm0, %xmm12 + psrlq \$4, %xmm0 # 0x01... + movdqa %xmm9, 0x10($out) + pcmpeqb %xmm1, %xmm13 + psrlq \$4, %xmm1 # 0x02... + lea 0x10($inp), $inp + + pand %xmm6, %xmm14 + pand %xmm6, %xmm15 + movdqa %xmm10, 0x20($out) + pcmpeqb %xmm2, %xmm14 + psrlq \$4, %xmm2 # 0x04... + movdqa %xmm11, 0x30($out) + pcmpeqb %xmm3, %xmm15 + psrlq \$4, %xmm3 # 0x08... + movdqu ($inp), %xmm6 # load next round key + + pxor %xmm5, %xmm13 # "pnot" + pxor %xmm5, %xmm14 + movdqa %xmm12, 0x40($out) + movdqa %xmm13, 0x50($out) + movdqa %xmm14, 0x60($out) + movdqa %xmm15, 0x70($out) + lea 0x80($out),$out + dec $rounds + jnz .Lkey_loop + + movdqa 0x50($const), %xmm7 # .L63 + #movdqa %xmm6, ($out) # don't save last round key + ret +.cfi_endproc +.size _bsaes_key_convert,.-_bsaes_key_convert +___ +} + +if (0 && !$win64) { # following four functions are unsupported interface + # used for benchmarking... +$code.=<<___; +.globl bsaes_enc_key_convert +.type bsaes_enc_key_convert,\@function,2 +.align 16 +bsaes_enc_key_convert: + mov 240($inp),%r10d # pass rounds + mov $inp,%rcx # pass key + mov $out,%rax # pass key schedule + call _bsaes_key_convert + pxor %xmm6,%xmm7 # fix up last round key + movdqa %xmm7,(%rax) # save last round key + ret +.size bsaes_enc_key_convert,.-bsaes_enc_key_convert + +.globl bsaes_encrypt_128 +.type bsaes_encrypt_128,\@function,4 +.align 16 +bsaes_encrypt_128: +.Lenc128_loop: + movdqu 0x00($inp), @XMM[0] # load input + movdqu 0x10($inp), @XMM[1] + movdqu 0x20($inp), @XMM[2] + movdqu 0x30($inp), @XMM[3] + movdqu 0x40($inp), @XMM[4] + movdqu 0x50($inp), @XMM[5] + movdqu 0x60($inp), @XMM[6] + movdqu 0x70($inp), @XMM[7] + mov $key, %rax # pass the $key + lea 0x80($inp), $inp + mov \$10,%r10d + + call _bsaes_encrypt8 + + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[4], 0x20($out) + movdqu @XMM[6], 0x30($out) + movdqu @XMM[3], 0x40($out) + movdqu @XMM[7], 0x50($out) + movdqu @XMM[2], 0x60($out) + movdqu @XMM[5], 0x70($out) + lea 0x80($out), $out + sub \$0x80,$len + ja .Lenc128_loop + ret +.size bsaes_encrypt_128,.-bsaes_encrypt_128 + +.globl bsaes_dec_key_convert +.type bsaes_dec_key_convert,\@function,2 +.align 16 +bsaes_dec_key_convert: + mov 240($inp),%r10d # pass rounds + mov $inp,%rcx # pass key + mov $out,%rax # pass key schedule + call _bsaes_key_convert + pxor ($out),%xmm7 # fix up round 0 key + movdqa %xmm6,(%rax) # save last round key + movdqa %xmm7,($out) + ret +.size bsaes_dec_key_convert,.-bsaes_dec_key_convert + +.globl bsaes_decrypt_128 +.type bsaes_decrypt_128,\@function,4 +.align 16 +bsaes_decrypt_128: +.Ldec128_loop: + movdqu 0x00($inp), @XMM[0] # load input + movdqu 0x10($inp), @XMM[1] + movdqu 0x20($inp), @XMM[2] + movdqu 0x30($inp), @XMM[3] + movdqu 0x40($inp), @XMM[4] + movdqu 0x50($inp), @XMM[5] + movdqu 0x60($inp), @XMM[6] + movdqu 0x70($inp), @XMM[7] + mov $key, %rax # pass the $key + lea 0x80($inp), $inp + mov \$10,%r10d + + call _bsaes_decrypt8 + + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + movdqu @XMM[7], 0x50($out) + movdqu @XMM[3], 0x60($out) + movdqu @XMM[5], 0x70($out) + lea 0x80($out), $out + sub \$0x80,$len + ja .Ldec128_loop + ret +.size bsaes_decrypt_128,.-bsaes_decrypt_128 +___ +} +{ +###################################################################### +# +# OpenSSL interface +# +my ($arg1,$arg2,$arg3,$arg4,$arg5,$arg6)=$win64 ? ("%rcx","%rdx","%r8","%r9","%r10","%r11d") + : ("%rdi","%rsi","%rdx","%rcx","%r8","%r9d"); +my ($inp,$out,$len,$key)=("%r12","%r13","%r14","%r15"); + +if ($ecb) { +$code.=<<___; +.globl bsaes_ecb_encrypt_blocks +.type bsaes_ecb_encrypt_blocks,\@abi-omnipotent +.align 16 +bsaes_ecb_encrypt_blocks: +.cfi_startproc + mov %rsp, %rax +.Lecb_enc_prologue: + push %rbp +.cfi_push %rbp + push %rbx +.cfi_push %rbx + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + lea -0x48(%rsp),%rsp +.cfi_adjust_cfa_offset 0x48 +___ +$code.=<<___ if ($win64); + lea -0xa0(%rsp), %rsp + movaps %xmm6, 0x40(%rsp) + movaps %xmm7, 0x50(%rsp) + movaps %xmm8, 0x60(%rsp) + movaps %xmm9, 0x70(%rsp) + movaps %xmm10, 0x80(%rsp) + movaps %xmm11, 0x90(%rsp) + movaps %xmm12, 0xa0(%rsp) + movaps %xmm13, 0xb0(%rsp) + movaps %xmm14, 0xc0(%rsp) + movaps %xmm15, 0xd0(%rsp) +.Lecb_enc_body: +___ +$code.=<<___; + mov %rsp,%rbp # backup %rsp +.cfi_def_cfa_register %rbp + mov 240($arg4),%eax # rounds + mov $arg1,$inp # backup arguments + mov $arg2,$out + mov $arg3,$len + mov $arg4,$key + cmp \$8,$arg3 + jb .Lecb_enc_short + + mov %eax,%ebx # backup rounds + shl \$7,%rax # 128 bytes per inner round key + sub \$`128-32`,%rax # size of bit-sliced key schedule + sub %rax,%rsp + mov %rsp,%rax # pass key schedule + mov $key,%rcx # pass key + mov %ebx,%r10d # pass rounds + call _bsaes_key_convert + pxor %xmm6,%xmm7 # fix up last round key + movdqa %xmm7,(%rax) # save last round key + + sub \$8,$len +.Lecb_enc_loop: + movdqu 0x00($inp), @XMM[0] # load input + movdqu 0x10($inp), @XMM[1] + movdqu 0x20($inp), @XMM[2] + movdqu 0x30($inp), @XMM[3] + movdqu 0x40($inp), @XMM[4] + movdqu 0x50($inp), @XMM[5] + mov %rsp, %rax # pass key schedule + movdqu 0x60($inp), @XMM[6] + mov %ebx,%r10d # pass rounds + movdqu 0x70($inp), @XMM[7] + lea 0x80($inp), $inp + + call _bsaes_encrypt8 + + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[4], 0x20($out) + movdqu @XMM[6], 0x30($out) + movdqu @XMM[3], 0x40($out) + movdqu @XMM[7], 0x50($out) + movdqu @XMM[2], 0x60($out) + movdqu @XMM[5], 0x70($out) + lea 0x80($out), $out + sub \$8,$len + jnc .Lecb_enc_loop + + add \$8,$len + jz .Lecb_enc_done + + movdqu 0x00($inp), @XMM[0] # load input + mov %rsp, %rax # pass key schedule + mov %ebx,%r10d # pass rounds + cmp \$2,$len + jb .Lecb_enc_one + movdqu 0x10($inp), @XMM[1] + je .Lecb_enc_two + movdqu 0x20($inp), @XMM[2] + cmp \$4,$len + jb .Lecb_enc_three + movdqu 0x30($inp), @XMM[3] + je .Lecb_enc_four + movdqu 0x40($inp), @XMM[4] + cmp \$6,$len + jb .Lecb_enc_five + movdqu 0x50($inp), @XMM[5] + je .Lecb_enc_six + movdqu 0x60($inp), @XMM[6] + call _bsaes_encrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[4], 0x20($out) + movdqu @XMM[6], 0x30($out) + movdqu @XMM[3], 0x40($out) + movdqu @XMM[7], 0x50($out) + movdqu @XMM[2], 0x60($out) + jmp .Lecb_enc_done +.align 16 +.Lecb_enc_six: + call _bsaes_encrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[4], 0x20($out) + movdqu @XMM[6], 0x30($out) + movdqu @XMM[3], 0x40($out) + movdqu @XMM[7], 0x50($out) + jmp .Lecb_enc_done +.align 16 +.Lecb_enc_five: + call _bsaes_encrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[4], 0x20($out) + movdqu @XMM[6], 0x30($out) + movdqu @XMM[3], 0x40($out) + jmp .Lecb_enc_done +.align 16 +.Lecb_enc_four: + call _bsaes_encrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[4], 0x20($out) + movdqu @XMM[6], 0x30($out) + jmp .Lecb_enc_done +.align 16 +.Lecb_enc_three: + call _bsaes_encrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[4], 0x20($out) + jmp .Lecb_enc_done +.align 16 +.Lecb_enc_two: + call _bsaes_encrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + jmp .Lecb_enc_done +.align 16 +.Lecb_enc_one: + call _bsaes_encrypt8 + movdqu @XMM[0], 0x00($out) # write output + jmp .Lecb_enc_done +.align 16 +.Lecb_enc_short: + lea ($inp), $arg1 + lea ($out), $arg2 + lea ($key), $arg3 + call asm_AES_encrypt + lea 16($inp), $inp + lea 16($out), $out + dec $len + jnz .Lecb_enc_short + +.Lecb_enc_done: + lea (%rsp),%rax + pxor %xmm0, %xmm0 +.Lecb_enc_bzero: # wipe key schedule [if any] + movdqa %xmm0, 0x00(%rax) + movdqa %xmm0, 0x10(%rax) + lea 0x20(%rax), %rax + cmp %rax, %rbp + jb .Lecb_enc_bzero + + lea 0x78(%rbp),%rax +.cfi_def_cfa %rax,8 +___ +$code.=<<___ if ($win64); + movaps 0x40(%rbp), %xmm6 + movaps 0x50(%rbp), %xmm7 + movaps 0x60(%rbp), %xmm8 + movaps 0x70(%rbp), %xmm9 + movaps 0x80(%rbp), %xmm10 + movaps 0x90(%rbp), %xmm11 + movaps 0xa0(%rbp), %xmm12 + movaps 0xb0(%rbp), %xmm13 + movaps 0xc0(%rbp), %xmm14 + movaps 0xd0(%rbp), %xmm15 + lea 0xa0(%rax), %rax +.Lecb_enc_tail: +___ +$code.=<<___; + mov -48(%rax), %r15 +.cfi_restore %r15 + mov -40(%rax), %r14 +.cfi_restore %r14 + mov -32(%rax), %r13 +.cfi_restore %r13 + mov -24(%rax), %r12 +.cfi_restore %r12 + mov -16(%rax), %rbx +.cfi_restore %rbx + mov -8(%rax), %rbp +.cfi_restore %rbp + lea (%rax), %rsp # restore %rsp +.cfi_def_cfa_register %rsp +.Lecb_enc_epilogue: + ret +.cfi_endproc +.size bsaes_ecb_encrypt_blocks,.-bsaes_ecb_encrypt_blocks + +.globl bsaes_ecb_decrypt_blocks +.type bsaes_ecb_decrypt_blocks,\@abi-omnipotent +.align 16 +bsaes_ecb_decrypt_blocks: +.cfi_startproc + mov %rsp, %rax +.Lecb_dec_prologue: + push %rbp +.cfi_push %rbp + push %rbx +.cfi_push %rbx + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + lea -0x48(%rsp),%rsp +.cfi_adjust_cfa_offset 0x48 +___ +$code.=<<___ if ($win64); + lea -0xa0(%rsp), %rsp + movaps %xmm6, 0x40(%rsp) + movaps %xmm7, 0x50(%rsp) + movaps %xmm8, 0x60(%rsp) + movaps %xmm9, 0x70(%rsp) + movaps %xmm10, 0x80(%rsp) + movaps %xmm11, 0x90(%rsp) + movaps %xmm12, 0xa0(%rsp) + movaps %xmm13, 0xb0(%rsp) + movaps %xmm14, 0xc0(%rsp) + movaps %xmm15, 0xd0(%rsp) +.Lecb_dec_body: +___ +$code.=<<___; + mov %rsp,%rbp # backup %rsp +.cfi_def_cfa_register %rbp + mov 240($arg4),%eax # rounds + mov $arg1,$inp # backup arguments + mov $arg2,$out + mov $arg3,$len + mov $arg4,$key + cmp \$8,$arg3 + jb .Lecb_dec_short + + mov %eax,%ebx # backup rounds + shl \$7,%rax # 128 bytes per inner round key + sub \$`128-32`,%rax # size of bit-sliced key schedule + sub %rax,%rsp + mov %rsp,%rax # pass key schedule + mov $key,%rcx # pass key + mov %ebx,%r10d # pass rounds + call _bsaes_key_convert + pxor (%rsp),%xmm7 # fix up 0 round key + movdqa %xmm6,(%rax) # save last round key + movdqa %xmm7,(%rsp) + + sub \$8,$len +.Lecb_dec_loop: + movdqu 0x00($inp), @XMM[0] # load input + movdqu 0x10($inp), @XMM[1] + movdqu 0x20($inp), @XMM[2] + movdqu 0x30($inp), @XMM[3] + movdqu 0x40($inp), @XMM[4] + movdqu 0x50($inp), @XMM[5] + mov %rsp, %rax # pass key schedule + movdqu 0x60($inp), @XMM[6] + mov %ebx,%r10d # pass rounds + movdqu 0x70($inp), @XMM[7] + lea 0x80($inp), $inp + + call _bsaes_decrypt8 + + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + movdqu @XMM[7], 0x50($out) + movdqu @XMM[3], 0x60($out) + movdqu @XMM[5], 0x70($out) + lea 0x80($out), $out + sub \$8,$len + jnc .Lecb_dec_loop + + add \$8,$len + jz .Lecb_dec_done + + movdqu 0x00($inp), @XMM[0] # load input + mov %rsp, %rax # pass key schedule + mov %ebx,%r10d # pass rounds + cmp \$2,$len + jb .Lecb_dec_one + movdqu 0x10($inp), @XMM[1] + je .Lecb_dec_two + movdqu 0x20($inp), @XMM[2] + cmp \$4,$len + jb .Lecb_dec_three + movdqu 0x30($inp), @XMM[3] + je .Lecb_dec_four + movdqu 0x40($inp), @XMM[4] + cmp \$6,$len + jb .Lecb_dec_five + movdqu 0x50($inp), @XMM[5] + je .Lecb_dec_six + movdqu 0x60($inp), @XMM[6] + call _bsaes_decrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + movdqu @XMM[7], 0x50($out) + movdqu @XMM[3], 0x60($out) + jmp .Lecb_dec_done +.align 16 +.Lecb_dec_six: + call _bsaes_decrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + movdqu @XMM[7], 0x50($out) + jmp .Lecb_dec_done +.align 16 +.Lecb_dec_five: + call _bsaes_decrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + jmp .Lecb_dec_done +.align 16 +.Lecb_dec_four: + call _bsaes_decrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + jmp .Lecb_dec_done +.align 16 +.Lecb_dec_three: + call _bsaes_decrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + jmp .Lecb_dec_done +.align 16 +.Lecb_dec_two: + call _bsaes_decrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + jmp .Lecb_dec_done +.align 16 +.Lecb_dec_one: + call _bsaes_decrypt8 + movdqu @XMM[0], 0x00($out) # write output + jmp .Lecb_dec_done +.align 16 +.Lecb_dec_short: + lea ($inp), $arg1 + lea ($out), $arg2 + lea ($key), $arg3 + call asm_AES_decrypt + lea 16($inp), $inp + lea 16($out), $out + dec $len + jnz .Lecb_dec_short + +.Lecb_dec_done: + lea (%rsp),%rax + pxor %xmm0, %xmm0 +.Lecb_dec_bzero: # wipe key schedule [if any] + movdqa %xmm0, 0x00(%rax) + movdqa %xmm0, 0x10(%rax) + lea 0x20(%rax), %rax + cmp %rax, %rbp + jb .Lecb_dec_bzero + + lea 0x78(%rbp),%rax +.cfi_def_cfa %rax,8 +___ +$code.=<<___ if ($win64); + movaps 0x40(%rbp), %xmm6 + movaps 0x50(%rbp), %xmm7 + movaps 0x60(%rbp), %xmm8 + movaps 0x70(%rbp), %xmm9 + movaps 0x80(%rbp), %xmm10 + movaps 0x90(%rbp), %xmm11 + movaps 0xa0(%rbp), %xmm12 + movaps 0xb0(%rbp), %xmm13 + movaps 0xc0(%rbp), %xmm14 + movaps 0xd0(%rbp), %xmm15 + lea 0xa0(%rax), %rax +.Lecb_dec_tail: +___ +$code.=<<___; + mov -48(%rax), %r15 +.cfi_restore %r15 + mov -40(%rax), %r14 +.cfi_restore %r14 + mov -32(%rax), %r13 +.cfi_restore %r13 + mov -24(%rax), %r12 +.cfi_restore %r12 + mov -16(%rax), %rbx +.cfi_restore %rbx + mov -8(%rax), %rbp +.cfi_restore %rbp + lea (%rax), %rsp # restore %rsp +.cfi_def_cfa_register %rsp +.Lecb_dec_epilogue: + ret +.cfi_endproc +.size bsaes_ecb_decrypt_blocks,.-bsaes_ecb_decrypt_blocks +___ +} +$code.=<<___; +.extern asm_AES_cbc_encrypt +.globl bsaes_cbc_encrypt +.type bsaes_cbc_encrypt,\@abi-omnipotent +.align 16 +bsaes_cbc_encrypt: +.cfi_startproc +___ +$code.=<<___ if ($win64); + mov 48(%rsp),$arg6 # pull direction flag +___ +$code.=<<___; + cmp \$0,$arg6 + jne asm_AES_cbc_encrypt + cmp \$128,$arg3 + jb asm_AES_cbc_encrypt + + mov %rsp, %rax +.Lcbc_dec_prologue: + push %rbp +.cfi_push %rbp + push %rbx +.cfi_push %rbx + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + lea -0x48(%rsp), %rsp +.cfi_adjust_cfa_offset 0x48 +___ +$code.=<<___ if ($win64); + mov 0xa0(%rsp),$arg5 # pull ivp + lea -0xa0(%rsp), %rsp + movaps %xmm6, 0x40(%rsp) + movaps %xmm7, 0x50(%rsp) + movaps %xmm8, 0x60(%rsp) + movaps %xmm9, 0x70(%rsp) + movaps %xmm10, 0x80(%rsp) + movaps %xmm11, 0x90(%rsp) + movaps %xmm12, 0xa0(%rsp) + movaps %xmm13, 0xb0(%rsp) + movaps %xmm14, 0xc0(%rsp) + movaps %xmm15, 0xd0(%rsp) +.Lcbc_dec_body: +___ +$code.=<<___; + mov %rsp, %rbp # backup %rsp +.cfi_def_cfa_register %rbp + mov 240($arg4), %eax # rounds + mov $arg1, $inp # backup arguments + mov $arg2, $out + mov $arg3, $len + mov $arg4, $key + mov $arg5, %rbx + shr \$4, $len # bytes to blocks + + mov %eax, %edx # rounds + shl \$7, %rax # 128 bytes per inner round key + sub \$`128-32`, %rax # size of bit-sliced key schedule + sub %rax, %rsp + + mov %rsp, %rax # pass key schedule + mov $key, %rcx # pass key + mov %edx, %r10d # pass rounds + call _bsaes_key_convert + pxor (%rsp),%xmm7 # fix up 0 round key + movdqa %xmm6,(%rax) # save last round key + movdqa %xmm7,(%rsp) + + movdqu (%rbx), @XMM[15] # load IV + sub \$8,$len +.Lcbc_dec_loop: + movdqu 0x00($inp), @XMM[0] # load input + movdqu 0x10($inp), @XMM[1] + movdqu 0x20($inp), @XMM[2] + movdqu 0x30($inp), @XMM[3] + movdqu 0x40($inp), @XMM[4] + movdqu 0x50($inp), @XMM[5] + mov %rsp, %rax # pass key schedule + movdqu 0x60($inp), @XMM[6] + mov %edx,%r10d # pass rounds + movdqu 0x70($inp), @XMM[7] + movdqa @XMM[15], 0x20(%rbp) # put aside IV + + call _bsaes_decrypt8 + + pxor 0x20(%rbp), @XMM[0] # ^= IV + movdqu 0x00($inp), @XMM[8] # re-load input + movdqu 0x10($inp), @XMM[9] + pxor @XMM[8], @XMM[1] + movdqu 0x20($inp), @XMM[10] + pxor @XMM[9], @XMM[6] + movdqu 0x30($inp), @XMM[11] + pxor @XMM[10], @XMM[4] + movdqu 0x40($inp), @XMM[12] + pxor @XMM[11], @XMM[2] + movdqu 0x50($inp), @XMM[13] + pxor @XMM[12], @XMM[7] + movdqu 0x60($inp), @XMM[14] + pxor @XMM[13], @XMM[3] + movdqu 0x70($inp), @XMM[15] # IV + pxor @XMM[14], @XMM[5] + movdqu @XMM[0], 0x00($out) # write output + lea 0x80($inp), $inp + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + movdqu @XMM[7], 0x50($out) + movdqu @XMM[3], 0x60($out) + movdqu @XMM[5], 0x70($out) + lea 0x80($out), $out + sub \$8,$len + jnc .Lcbc_dec_loop + + add \$8,$len + jz .Lcbc_dec_done + + movdqu 0x00($inp), @XMM[0] # load input + mov %rsp, %rax # pass key schedule + mov %edx, %r10d # pass rounds + cmp \$2,$len + jb .Lcbc_dec_one + movdqu 0x10($inp), @XMM[1] + je .Lcbc_dec_two + movdqu 0x20($inp), @XMM[2] + cmp \$4,$len + jb .Lcbc_dec_three + movdqu 0x30($inp), @XMM[3] + je .Lcbc_dec_four + movdqu 0x40($inp), @XMM[4] + cmp \$6,$len + jb .Lcbc_dec_five + movdqu 0x50($inp), @XMM[5] + je .Lcbc_dec_six + movdqu 0x60($inp), @XMM[6] + movdqa @XMM[15], 0x20(%rbp) # put aside IV + call _bsaes_decrypt8 + pxor 0x20(%rbp), @XMM[0] # ^= IV + movdqu 0x00($inp), @XMM[8] # re-load input + movdqu 0x10($inp), @XMM[9] + pxor @XMM[8], @XMM[1] + movdqu 0x20($inp), @XMM[10] + pxor @XMM[9], @XMM[6] + movdqu 0x30($inp), @XMM[11] + pxor @XMM[10], @XMM[4] + movdqu 0x40($inp), @XMM[12] + pxor @XMM[11], @XMM[2] + movdqu 0x50($inp), @XMM[13] + pxor @XMM[12], @XMM[7] + movdqu 0x60($inp), @XMM[15] # IV + pxor @XMM[13], @XMM[3] + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + movdqu @XMM[7], 0x50($out) + movdqu @XMM[3], 0x60($out) + jmp .Lcbc_dec_done +.align 16 +.Lcbc_dec_six: + movdqa @XMM[15], 0x20(%rbp) # put aside IV + call _bsaes_decrypt8 + pxor 0x20(%rbp), @XMM[0] # ^= IV + movdqu 0x00($inp), @XMM[8] # re-load input + movdqu 0x10($inp), @XMM[9] + pxor @XMM[8], @XMM[1] + movdqu 0x20($inp), @XMM[10] + pxor @XMM[9], @XMM[6] + movdqu 0x30($inp), @XMM[11] + pxor @XMM[10], @XMM[4] + movdqu 0x40($inp), @XMM[12] + pxor @XMM[11], @XMM[2] + movdqu 0x50($inp), @XMM[15] # IV + pxor @XMM[12], @XMM[7] + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + movdqu @XMM[7], 0x50($out) + jmp .Lcbc_dec_done +.align 16 +.Lcbc_dec_five: + movdqa @XMM[15], 0x20(%rbp) # put aside IV + call _bsaes_decrypt8 + pxor 0x20(%rbp), @XMM[0] # ^= IV + movdqu 0x00($inp), @XMM[8] # re-load input + movdqu 0x10($inp), @XMM[9] + pxor @XMM[8], @XMM[1] + movdqu 0x20($inp), @XMM[10] + pxor @XMM[9], @XMM[6] + movdqu 0x30($inp), @XMM[11] + pxor @XMM[10], @XMM[4] + movdqu 0x40($inp), @XMM[15] # IV + pxor @XMM[11], @XMM[2] + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + jmp .Lcbc_dec_done +.align 16 +.Lcbc_dec_four: + movdqa @XMM[15], 0x20(%rbp) # put aside IV + call _bsaes_decrypt8 + pxor 0x20(%rbp), @XMM[0] # ^= IV + movdqu 0x00($inp), @XMM[8] # re-load input + movdqu 0x10($inp), @XMM[9] + pxor @XMM[8], @XMM[1] + movdqu 0x20($inp), @XMM[10] + pxor @XMM[9], @XMM[6] + movdqu 0x30($inp), @XMM[15] # IV + pxor @XMM[10], @XMM[4] + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + jmp .Lcbc_dec_done +.align 16 +.Lcbc_dec_three: + movdqa @XMM[15], 0x20(%rbp) # put aside IV + call _bsaes_decrypt8 + pxor 0x20(%rbp), @XMM[0] # ^= IV + movdqu 0x00($inp), @XMM[8] # re-load input + movdqu 0x10($inp), @XMM[9] + pxor @XMM[8], @XMM[1] + movdqu 0x20($inp), @XMM[15] # IV + pxor @XMM[9], @XMM[6] + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + jmp .Lcbc_dec_done +.align 16 +.Lcbc_dec_two: + movdqa @XMM[15], 0x20(%rbp) # put aside IV + call _bsaes_decrypt8 + pxor 0x20(%rbp), @XMM[0] # ^= IV + movdqu 0x00($inp), @XMM[8] # re-load input + movdqu 0x10($inp), @XMM[15] # IV + pxor @XMM[8], @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + jmp .Lcbc_dec_done +.align 16 +.Lcbc_dec_one: + lea ($inp), $arg1 + lea 0x20(%rbp), $arg2 # buffer output + lea ($key), $arg3 + call asm_AES_decrypt # doesn't touch %xmm + pxor 0x20(%rbp), @XMM[15] # ^= IV + movdqu @XMM[15], ($out) # write output + movdqa @XMM[0], @XMM[15] # IV + +.Lcbc_dec_done: + movdqu @XMM[15], (%rbx) # return IV + lea (%rsp), %rax + pxor %xmm0, %xmm0 +.Lcbc_dec_bzero: # wipe key schedule [if any] + movdqa %xmm0, 0x00(%rax) + movdqa %xmm0, 0x10(%rax) + lea 0x20(%rax), %rax + cmp %rax, %rbp + ja .Lcbc_dec_bzero + + lea 0x78(%rbp),%rax +.cfi_def_cfa %rax,8 +___ +$code.=<<___ if ($win64); + movaps 0x40(%rbp), %xmm6 + movaps 0x50(%rbp), %xmm7 + movaps 0x60(%rbp), %xmm8 + movaps 0x70(%rbp), %xmm9 + movaps 0x80(%rbp), %xmm10 + movaps 0x90(%rbp), %xmm11 + movaps 0xa0(%rbp), %xmm12 + movaps 0xb0(%rbp), %xmm13 + movaps 0xc0(%rbp), %xmm14 + movaps 0xd0(%rbp), %xmm15 + lea 0xa0(%rax), %rax +.Lcbc_dec_tail: +___ +$code.=<<___; + mov -48(%rax), %r15 +.cfi_restore %r15 + mov -40(%rax), %r14 +.cfi_restore %r14 + mov -32(%rax), %r13 +.cfi_restore %r13 + mov -24(%rax), %r12 +.cfi_restore %r12 + mov -16(%rax), %rbx +.cfi_restore %rbx + mov -8(%rax), %rbp +.cfi_restore %rbp + lea (%rax), %rsp # restore %rsp +.cfi_def_cfa_register %rsp +.Lcbc_dec_epilogue: + ret +.cfi_endproc +.size bsaes_cbc_encrypt,.-bsaes_cbc_encrypt + +.globl bsaes_ctr32_encrypt_blocks +.type bsaes_ctr32_encrypt_blocks,\@abi-omnipotent +.align 16 +bsaes_ctr32_encrypt_blocks: +.cfi_startproc + mov %rsp, %rax +.Lctr_enc_prologue: + push %rbp +.cfi_push %rbp + push %rbx +.cfi_push %rbx + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + lea -0x48(%rsp), %rsp +.cfi_adjust_cfa_offset 0x48 +___ +$code.=<<___ if ($win64); + mov 0xa0(%rsp),$arg5 # pull ivp + lea -0xa0(%rsp), %rsp + movaps %xmm6, 0x40(%rsp) + movaps %xmm7, 0x50(%rsp) + movaps %xmm8, 0x60(%rsp) + movaps %xmm9, 0x70(%rsp) + movaps %xmm10, 0x80(%rsp) + movaps %xmm11, 0x90(%rsp) + movaps %xmm12, 0xa0(%rsp) + movaps %xmm13, 0xb0(%rsp) + movaps %xmm14, 0xc0(%rsp) + movaps %xmm15, 0xd0(%rsp) +.Lctr_enc_body: +___ +$code.=<<___; + mov %rsp, %rbp # backup %rsp +.cfi_def_cfa_register %rbp + movdqu ($arg5), %xmm0 # load counter + mov 240($arg4), %eax # rounds + mov $arg1, $inp # backup arguments + mov $arg2, $out + mov $arg3, $len + mov $arg4, $key + movdqa %xmm0, 0x20(%rbp) # copy counter + cmp \$8, $arg3 + jb .Lctr_enc_short + + mov %eax, %ebx # rounds + shl \$7, %rax # 128 bytes per inner round key + sub \$`128-32`, %rax # size of bit-sliced key schedule + sub %rax, %rsp + + mov %rsp, %rax # pass key schedule + mov $key, %rcx # pass key + mov %ebx, %r10d # pass rounds + call _bsaes_key_convert + pxor %xmm6,%xmm7 # fix up last round key + movdqa %xmm7,(%rax) # save last round key + + movdqa (%rsp), @XMM[9] # load round0 key + lea .LADD1(%rip), %r11 + movdqa 0x20(%rbp), @XMM[0] # counter copy + movdqa -0x20(%r11), @XMM[8] # .LSWPUP + pshufb @XMM[8], @XMM[9] # byte swap upper part + pshufb @XMM[8], @XMM[0] + movdqa @XMM[9], (%rsp) # save adjusted round0 key + jmp .Lctr_enc_loop +.align 16 +.Lctr_enc_loop: + movdqa @XMM[0], 0x20(%rbp) # save counter + movdqa @XMM[0], @XMM[1] # prepare 8 counter values + movdqa @XMM[0], @XMM[2] + paddd 0x00(%r11), @XMM[1] # .LADD1 + movdqa @XMM[0], @XMM[3] + paddd 0x10(%r11), @XMM[2] # .LADD2 + movdqa @XMM[0], @XMM[4] + paddd 0x20(%r11), @XMM[3] # .LADD3 + movdqa @XMM[0], @XMM[5] + paddd 0x30(%r11), @XMM[4] # .LADD4 + movdqa @XMM[0], @XMM[6] + paddd 0x40(%r11), @XMM[5] # .LADD5 + movdqa @XMM[0], @XMM[7] + paddd 0x50(%r11), @XMM[6] # .LADD6 + paddd 0x60(%r11), @XMM[7] # .LADD7 + + # Borrow prologue from _bsaes_encrypt8 to use the opportunity + # to flip byte order in 32-bit counter + movdqa (%rsp), @XMM[9] # round 0 key + lea 0x10(%rsp), %rax # pass key schedule + movdqa -0x10(%r11), @XMM[8] # .LSWPUPM0SR + pxor @XMM[9], @XMM[0] # xor with round0 key + pxor @XMM[9], @XMM[1] + pxor @XMM[9], @XMM[2] + pxor @XMM[9], @XMM[3] + pshufb @XMM[8], @XMM[0] + pshufb @XMM[8], @XMM[1] + pxor @XMM[9], @XMM[4] + pxor @XMM[9], @XMM[5] + pshufb @XMM[8], @XMM[2] + pshufb @XMM[8], @XMM[3] + pxor @XMM[9], @XMM[6] + pxor @XMM[9], @XMM[7] + pshufb @XMM[8], @XMM[4] + pshufb @XMM[8], @XMM[5] + pshufb @XMM[8], @XMM[6] + pshufb @XMM[8], @XMM[7] + lea .LBS0(%rip), %r11 # constants table + mov %ebx,%r10d # pass rounds + + call _bsaes_encrypt8_bitslice + + sub \$8,$len + jc .Lctr_enc_loop_done + + movdqu 0x00($inp), @XMM[8] # load input + movdqu 0x10($inp), @XMM[9] + movdqu 0x20($inp), @XMM[10] + movdqu 0x30($inp), @XMM[11] + movdqu 0x40($inp), @XMM[12] + movdqu 0x50($inp), @XMM[13] + movdqu 0x60($inp), @XMM[14] + movdqu 0x70($inp), @XMM[15] + lea 0x80($inp),$inp + pxor @XMM[0], @XMM[8] + movdqa 0x20(%rbp), @XMM[0] # load counter + pxor @XMM[9], @XMM[1] + movdqu @XMM[8], 0x00($out) # write output + pxor @XMM[10], @XMM[4] + movdqu @XMM[1], 0x10($out) + pxor @XMM[11], @XMM[6] + movdqu @XMM[4], 0x20($out) + pxor @XMM[12], @XMM[3] + movdqu @XMM[6], 0x30($out) + pxor @XMM[13], @XMM[7] + movdqu @XMM[3], 0x40($out) + pxor @XMM[14], @XMM[2] + movdqu @XMM[7], 0x50($out) + pxor @XMM[15], @XMM[5] + movdqu @XMM[2], 0x60($out) + lea .LADD1(%rip), %r11 + movdqu @XMM[5], 0x70($out) + lea 0x80($out), $out + paddd 0x70(%r11), @XMM[0] # .LADD8 + jnz .Lctr_enc_loop + + jmp .Lctr_enc_done +.align 16 +.Lctr_enc_loop_done: + add \$8, $len + movdqu 0x00($inp), @XMM[8] # load input + pxor @XMM[8], @XMM[0] + movdqu @XMM[0], 0x00($out) # write output + cmp \$2,$len + jb .Lctr_enc_done + movdqu 0x10($inp), @XMM[9] + pxor @XMM[9], @XMM[1] + movdqu @XMM[1], 0x10($out) + je .Lctr_enc_done + movdqu 0x20($inp), @XMM[10] + pxor @XMM[10], @XMM[4] + movdqu @XMM[4], 0x20($out) + cmp \$4,$len + jb .Lctr_enc_done + movdqu 0x30($inp), @XMM[11] + pxor @XMM[11], @XMM[6] + movdqu @XMM[6], 0x30($out) + je .Lctr_enc_done + movdqu 0x40($inp), @XMM[12] + pxor @XMM[12], @XMM[3] + movdqu @XMM[3], 0x40($out) + cmp \$6,$len + jb .Lctr_enc_done + movdqu 0x50($inp), @XMM[13] + pxor @XMM[13], @XMM[7] + movdqu @XMM[7], 0x50($out) + je .Lctr_enc_done + movdqu 0x60($inp), @XMM[14] + pxor @XMM[14], @XMM[2] + movdqu @XMM[2], 0x60($out) + jmp .Lctr_enc_done + +.align 16 +.Lctr_enc_short: + lea 0x20(%rbp), $arg1 + lea 0x30(%rbp), $arg2 + lea ($key), $arg3 + call asm_AES_encrypt + movdqu ($inp), @XMM[1] + lea 16($inp), $inp + mov 0x2c(%rbp), %eax # load 32-bit counter + bswap %eax + pxor 0x30(%rbp), @XMM[1] + inc %eax # increment + movdqu @XMM[1], ($out) + bswap %eax + lea 16($out), $out + mov %eax, 0x2c(%rsp) # save 32-bit counter + dec $len + jnz .Lctr_enc_short + +.Lctr_enc_done: + lea (%rsp), %rax + pxor %xmm0, %xmm0 +.Lctr_enc_bzero: # wipe key schedule [if any] + movdqa %xmm0, 0x00(%rax) + movdqa %xmm0, 0x10(%rax) + lea 0x20(%rax), %rax + cmp %rax, %rbp + ja .Lctr_enc_bzero + + lea 0x78(%rbp),%rax +.cfi_def_cfa %rax,8 +___ +$code.=<<___ if ($win64); + movaps 0x40(%rbp), %xmm6 + movaps 0x50(%rbp), %xmm7 + movaps 0x60(%rbp), %xmm8 + movaps 0x70(%rbp), %xmm9 + movaps 0x80(%rbp), %xmm10 + movaps 0x90(%rbp), %xmm11 + movaps 0xa0(%rbp), %xmm12 + movaps 0xb0(%rbp), %xmm13 + movaps 0xc0(%rbp), %xmm14 + movaps 0xd0(%rbp), %xmm15 + lea 0xa0(%rax), %rax +.Lctr_enc_tail: +___ +$code.=<<___; + mov -48(%rax), %r15 +.cfi_restore %r15 + mov -40(%rax), %r14 +.cfi_restore %r14 + mov -32(%rax), %r13 +.cfi_restore %r13 + mov -24(%rax), %r12 +.cfi_restore %r12 + mov -16(%rax), %rbx +.cfi_restore %rbx + mov -8(%rax), %rbp +.cfi_restore %rbp + lea (%rax), %rsp # restore %rsp +.cfi_def_cfa_register %rsp +.Lctr_enc_epilogue: + ret +.cfi_endproc +.size bsaes_ctr32_encrypt_blocks,.-bsaes_ctr32_encrypt_blocks +___ +###################################################################### +# void bsaes_xts_[en|de]crypt(const char *inp,char *out,size_t len, +# const AES_KEY *key1, const AES_KEY *key2, +# const unsigned char iv[16]); +# +my ($twmask,$twres,$twtmp)=@XMM[13..15]; +$arg6=~s/d$//; + +$code.=<<___; +.globl bsaes_xts_encrypt +.type bsaes_xts_encrypt,\@abi-omnipotent +.align 16 +bsaes_xts_encrypt: +.cfi_startproc + mov %rsp, %rax +.Lxts_enc_prologue: + push %rbp +.cfi_push %rbp + push %rbx +.cfi_push %rbx + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + lea -0x48(%rsp), %rsp +.cfi_adjust_cfa_offset 0x48 +___ +$code.=<<___ if ($win64); + mov 0xa0(%rsp),$arg5 # pull key2 + mov 0xa8(%rsp),$arg6 # pull ivp + lea -0xa0(%rsp), %rsp + movaps %xmm6, 0x40(%rsp) + movaps %xmm7, 0x50(%rsp) + movaps %xmm8, 0x60(%rsp) + movaps %xmm9, 0x70(%rsp) + movaps %xmm10, 0x80(%rsp) + movaps %xmm11, 0x90(%rsp) + movaps %xmm12, 0xa0(%rsp) + movaps %xmm13, 0xb0(%rsp) + movaps %xmm14, 0xc0(%rsp) + movaps %xmm15, 0xd0(%rsp) +.Lxts_enc_body: +___ +$code.=<<___; + mov %rsp, %rbp # backup %rsp +.cfi_def_cfa_register %rbp + mov $arg1, $inp # backup arguments + mov $arg2, $out + mov $arg3, $len + mov $arg4, $key + + lea ($arg6), $arg1 + lea 0x20(%rbp), $arg2 + lea ($arg5), $arg3 + call asm_AES_encrypt # generate initial tweak + + mov 240($key), %eax # rounds + mov $len, %rbx # backup $len + + mov %eax, %edx # rounds + shl \$7, %rax # 128 bytes per inner round key + sub \$`128-32`, %rax # size of bit-sliced key schedule + sub %rax, %rsp + + mov %rsp, %rax # pass key schedule + mov $key, %rcx # pass key + mov %edx, %r10d # pass rounds + call _bsaes_key_convert + pxor %xmm6, %xmm7 # fix up last round key + movdqa %xmm7, (%rax) # save last round key + + and \$-16, $len + sub \$0x80, %rsp # place for tweak[8] + movdqa 0x20(%rbp), @XMM[7] # initial tweak + + pxor $twtmp, $twtmp + movdqa .Lxts_magic(%rip), $twmask + pcmpgtd @XMM[7], $twtmp # broadcast upper bits + + sub \$0x80, $len + jc .Lxts_enc_short + jmp .Lxts_enc_loop + +.align 16 +.Lxts_enc_loop: +___ + for ($i=0;$i<7;$i++) { + $code.=<<___; + pshufd \$0x13, $twtmp, $twres + pxor $twtmp, $twtmp + movdqa @XMM[7], @XMM[$i] + movdqa @XMM[7], `0x10*$i`(%rsp)# save tweak[$i] + paddq @XMM[7], @XMM[7] # psllq 1,$tweak + pand $twmask, $twres # isolate carry and residue + pcmpgtd @XMM[7], $twtmp # broadcast upper bits + pxor $twres, @XMM[7] +___ + $code.=<<___ if ($i>=1); + movdqu `0x10*($i-1)`($inp), @XMM[8+$i-1] +___ + $code.=<<___ if ($i>=2); + pxor @XMM[8+$i-2], @XMM[$i-2]# input[] ^ tweak[] +___ + } +$code.=<<___; + movdqu 0x60($inp), @XMM[8+6] + pxor @XMM[8+5], @XMM[5] + movdqu 0x70($inp), @XMM[8+7] + lea 0x80($inp), $inp + movdqa @XMM[7], 0x70(%rsp) + pxor @XMM[8+6], @XMM[6] + lea 0x80(%rsp), %rax # pass key schedule + pxor @XMM[8+7], @XMM[7] + mov %edx, %r10d # pass rounds + + call _bsaes_encrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[4] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[6] + movdqu @XMM[4], 0x20($out) + pxor 0x40(%rsp), @XMM[3] + movdqu @XMM[6], 0x30($out) + pxor 0x50(%rsp), @XMM[7] + movdqu @XMM[3], 0x40($out) + pxor 0x60(%rsp), @XMM[2] + movdqu @XMM[7], 0x50($out) + pxor 0x70(%rsp), @XMM[5] + movdqu @XMM[2], 0x60($out) + movdqu @XMM[5], 0x70($out) + lea 0x80($out), $out + + movdqa 0x70(%rsp), @XMM[7] # prepare next iteration tweak + pxor $twtmp, $twtmp + movdqa .Lxts_magic(%rip), $twmask + pcmpgtd @XMM[7], $twtmp + pshufd \$0x13, $twtmp, $twres + pxor $twtmp, $twtmp + paddq @XMM[7], @XMM[7] # psllq 1,$tweak + pand $twmask, $twres # isolate carry and residue + pcmpgtd @XMM[7], $twtmp # broadcast upper bits + pxor $twres, @XMM[7] + + sub \$0x80,$len + jnc .Lxts_enc_loop + +.Lxts_enc_short: + add \$0x80, $len + jz .Lxts_enc_done +___ + for ($i=0;$i<7;$i++) { + $code.=<<___; + pshufd \$0x13, $twtmp, $twres + pxor $twtmp, $twtmp + movdqa @XMM[7], @XMM[$i] + movdqa @XMM[7], `0x10*$i`(%rsp)# save tweak[$i] + paddq @XMM[7], @XMM[7] # psllq 1,$tweak + pand $twmask, $twres # isolate carry and residue + pcmpgtd @XMM[7], $twtmp # broadcast upper bits + pxor $twres, @XMM[7] +___ + $code.=<<___ if ($i>=1); + movdqu `0x10*($i-1)`($inp), @XMM[8+$i-1] + cmp \$`0x10*$i`,$len + je .Lxts_enc_$i +___ + $code.=<<___ if ($i>=2); + pxor @XMM[8+$i-2], @XMM[$i-2]# input[] ^ tweak[] +___ + } +$code.=<<___; + movdqu 0x60($inp), @XMM[8+6] + pxor @XMM[8+5], @XMM[5] + movdqa @XMM[7], 0x70(%rsp) + lea 0x70($inp), $inp + pxor @XMM[8+6], @XMM[6] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_encrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[4] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[6] + movdqu @XMM[4], 0x20($out) + pxor 0x40(%rsp), @XMM[3] + movdqu @XMM[6], 0x30($out) + pxor 0x50(%rsp), @XMM[7] + movdqu @XMM[3], 0x40($out) + pxor 0x60(%rsp), @XMM[2] + movdqu @XMM[7], 0x50($out) + movdqu @XMM[2], 0x60($out) + lea 0x70($out), $out + + movdqa 0x70(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_enc_done +.align 16 +.Lxts_enc_6: + pxor @XMM[8+4], @XMM[4] + lea 0x60($inp), $inp + pxor @XMM[8+5], @XMM[5] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_encrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[4] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[6] + movdqu @XMM[4], 0x20($out) + pxor 0x40(%rsp), @XMM[3] + movdqu @XMM[6], 0x30($out) + pxor 0x50(%rsp), @XMM[7] + movdqu @XMM[3], 0x40($out) + movdqu @XMM[7], 0x50($out) + lea 0x60($out), $out + + movdqa 0x60(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_enc_done +.align 16 +.Lxts_enc_5: + pxor @XMM[8+3], @XMM[3] + lea 0x50($inp), $inp + pxor @XMM[8+4], @XMM[4] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_encrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[4] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[6] + movdqu @XMM[4], 0x20($out) + pxor 0x40(%rsp), @XMM[3] + movdqu @XMM[6], 0x30($out) + movdqu @XMM[3], 0x40($out) + lea 0x50($out), $out + + movdqa 0x50(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_enc_done +.align 16 +.Lxts_enc_4: + pxor @XMM[8+2], @XMM[2] + lea 0x40($inp), $inp + pxor @XMM[8+3], @XMM[3] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_encrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[4] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[6] + movdqu @XMM[4], 0x20($out) + movdqu @XMM[6], 0x30($out) + lea 0x40($out), $out + + movdqa 0x40(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_enc_done +.align 16 +.Lxts_enc_3: + pxor @XMM[8+1], @XMM[1] + lea 0x30($inp), $inp + pxor @XMM[8+2], @XMM[2] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_encrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[4] + movdqu @XMM[1], 0x10($out) + movdqu @XMM[4], 0x20($out) + lea 0x30($out), $out + + movdqa 0x30(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_enc_done +.align 16 +.Lxts_enc_2: + pxor @XMM[8+0], @XMM[0] + lea 0x20($inp), $inp + pxor @XMM[8+1], @XMM[1] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_encrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + lea 0x20($out), $out + + movdqa 0x20(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_enc_done +.align 16 +.Lxts_enc_1: + pxor @XMM[0], @XMM[8] + lea 0x10($inp), $inp + movdqa @XMM[8], 0x20(%rbp) + lea 0x20(%rbp), $arg1 + lea 0x20(%rbp), $arg2 + lea ($key), $arg3 + call asm_AES_encrypt # doesn't touch %xmm + pxor 0x20(%rbp), @XMM[0] # ^= tweak[] + #pxor @XMM[8], @XMM[0] + #lea 0x80(%rsp), %rax # pass key schedule + #mov %edx, %r10d # pass rounds + #call _bsaes_encrypt8 + #pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + movdqu @XMM[0], 0x00($out) # write output + lea 0x10($out), $out + + movdqa 0x10(%rsp), @XMM[7] # next iteration tweak + +.Lxts_enc_done: + and \$15, %ebx + jz .Lxts_enc_ret + mov $out, %rdx + +.Lxts_enc_steal: + movzb ($inp), %eax + movzb -16(%rdx), %ecx + lea 1($inp), $inp + mov %al, -16(%rdx) + mov %cl, 0(%rdx) + lea 1(%rdx), %rdx + sub \$1,%ebx + jnz .Lxts_enc_steal + + movdqu -16($out), @XMM[0] + lea 0x20(%rbp), $arg1 + pxor @XMM[7], @XMM[0] + lea 0x20(%rbp), $arg2 + movdqa @XMM[0], 0x20(%rbp) + lea ($key), $arg3 + call asm_AES_encrypt # doesn't touch %xmm + pxor 0x20(%rbp), @XMM[7] + movdqu @XMM[7], -16($out) + +.Lxts_enc_ret: + lea (%rsp), %rax + pxor %xmm0, %xmm0 +.Lxts_enc_bzero: # wipe key schedule [if any] + movdqa %xmm0, 0x00(%rax) + movdqa %xmm0, 0x10(%rax) + lea 0x20(%rax), %rax + cmp %rax, %rbp + ja .Lxts_enc_bzero + + lea 0x78(%rbp),%rax +.cfi_def_cfa %rax,8 +___ +$code.=<<___ if ($win64); + movaps 0x40(%rbp), %xmm6 + movaps 0x50(%rbp), %xmm7 + movaps 0x60(%rbp), %xmm8 + movaps 0x70(%rbp), %xmm9 + movaps 0x80(%rbp), %xmm10 + movaps 0x90(%rbp), %xmm11 + movaps 0xa0(%rbp), %xmm12 + movaps 0xb0(%rbp), %xmm13 + movaps 0xc0(%rbp), %xmm14 + movaps 0xd0(%rbp), %xmm15 + lea 0xa0(%rax), %rax +.Lxts_enc_tail: +___ +$code.=<<___; + mov -48(%rax), %r15 +.cfi_restore %r15 + mov -40(%rax), %r14 +.cfi_restore %r14 + mov -32(%rax), %r13 +.cfi_restore %r13 + mov -24(%rax), %r12 +.cfi_restore %r12 + mov -16(%rax), %rbx +.cfi_restore %rbx + mov -8(%rax), %rbp +.cfi_restore %rbp + lea (%rax), %rsp # restore %rsp +.cfi_def_cfa_register %rsp +.Lxts_enc_epilogue: + ret +.cfi_endproc +.size bsaes_xts_encrypt,.-bsaes_xts_encrypt + +.globl bsaes_xts_decrypt +.type bsaes_xts_decrypt,\@abi-omnipotent +.align 16 +bsaes_xts_decrypt: +.cfi_startproc + mov %rsp, %rax +.Lxts_dec_prologue: + push %rbp +.cfi_push %rbp + push %rbx +.cfi_push %rbx + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + lea -0x48(%rsp), %rsp +.cfi_adjust_cfa_offset 0x48 +___ +$code.=<<___ if ($win64); + mov 0xa0(%rsp),$arg5 # pull key2 + mov 0xa8(%rsp),$arg6 # pull ivp + lea -0xa0(%rsp), %rsp + movaps %xmm6, 0x40(%rsp) + movaps %xmm7, 0x50(%rsp) + movaps %xmm8, 0x60(%rsp) + movaps %xmm9, 0x70(%rsp) + movaps %xmm10, 0x80(%rsp) + movaps %xmm11, 0x90(%rsp) + movaps %xmm12, 0xa0(%rsp) + movaps %xmm13, 0xb0(%rsp) + movaps %xmm14, 0xc0(%rsp) + movaps %xmm15, 0xd0(%rsp) +.Lxts_dec_body: +___ +$code.=<<___; + mov %rsp, %rbp # backup %rsp + mov $arg1, $inp # backup arguments + mov $arg2, $out + mov $arg3, $len + mov $arg4, $key + + lea ($arg6), $arg1 + lea 0x20(%rbp), $arg2 + lea ($arg5), $arg3 + call asm_AES_encrypt # generate initial tweak + + mov 240($key), %eax # rounds + mov $len, %rbx # backup $len + + mov %eax, %edx # rounds + shl \$7, %rax # 128 bytes per inner round key + sub \$`128-32`, %rax # size of bit-sliced key schedule + sub %rax, %rsp + + mov %rsp, %rax # pass key schedule + mov $key, %rcx # pass key + mov %edx, %r10d # pass rounds + call _bsaes_key_convert + pxor (%rsp), %xmm7 # fix up round 0 key + movdqa %xmm6, (%rax) # save last round key + movdqa %xmm7, (%rsp) + + xor %eax, %eax # if ($len%16) len-=16; + and \$-16, $len + test \$15, %ebx + setnz %al + shl \$4, %rax + sub %rax, $len + + sub \$0x80, %rsp # place for tweak[8] + movdqa 0x20(%rbp), @XMM[7] # initial tweak + + pxor $twtmp, $twtmp + movdqa .Lxts_magic(%rip), $twmask + pcmpgtd @XMM[7], $twtmp # broadcast upper bits + + sub \$0x80, $len + jc .Lxts_dec_short + jmp .Lxts_dec_loop + +.align 16 +.Lxts_dec_loop: +___ + for ($i=0;$i<7;$i++) { + $code.=<<___; + pshufd \$0x13, $twtmp, $twres + pxor $twtmp, $twtmp + movdqa @XMM[7], @XMM[$i] + movdqa @XMM[7], `0x10*$i`(%rsp)# save tweak[$i] + paddq @XMM[7], @XMM[7] # psllq 1,$tweak + pand $twmask, $twres # isolate carry and residue + pcmpgtd @XMM[7], $twtmp # broadcast upper bits + pxor $twres, @XMM[7] +___ + $code.=<<___ if ($i>=1); + movdqu `0x10*($i-1)`($inp), @XMM[8+$i-1] +___ + $code.=<<___ if ($i>=2); + pxor @XMM[8+$i-2], @XMM[$i-2]# input[] ^ tweak[] +___ + } +$code.=<<___; + movdqu 0x60($inp), @XMM[8+6] + pxor @XMM[8+5], @XMM[5] + movdqu 0x70($inp), @XMM[8+7] + lea 0x80($inp), $inp + movdqa @XMM[7], 0x70(%rsp) + pxor @XMM[8+6], @XMM[6] + lea 0x80(%rsp), %rax # pass key schedule + pxor @XMM[8+7], @XMM[7] + mov %edx, %r10d # pass rounds + + call _bsaes_decrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[6] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[4] + movdqu @XMM[6], 0x20($out) + pxor 0x40(%rsp), @XMM[2] + movdqu @XMM[4], 0x30($out) + pxor 0x50(%rsp), @XMM[7] + movdqu @XMM[2], 0x40($out) + pxor 0x60(%rsp), @XMM[3] + movdqu @XMM[7], 0x50($out) + pxor 0x70(%rsp), @XMM[5] + movdqu @XMM[3], 0x60($out) + movdqu @XMM[5], 0x70($out) + lea 0x80($out), $out + + movdqa 0x70(%rsp), @XMM[7] # prepare next iteration tweak + pxor $twtmp, $twtmp + movdqa .Lxts_magic(%rip), $twmask + pcmpgtd @XMM[7], $twtmp + pshufd \$0x13, $twtmp, $twres + pxor $twtmp, $twtmp + paddq @XMM[7], @XMM[7] # psllq 1,$tweak + pand $twmask, $twres # isolate carry and residue + pcmpgtd @XMM[7], $twtmp # broadcast upper bits + pxor $twres, @XMM[7] + + sub \$0x80,$len + jnc .Lxts_dec_loop + +.Lxts_dec_short: + add \$0x80, $len + jz .Lxts_dec_done +___ + for ($i=0;$i<7;$i++) { + $code.=<<___; + pshufd \$0x13, $twtmp, $twres + pxor $twtmp, $twtmp + movdqa @XMM[7], @XMM[$i] + movdqa @XMM[7], `0x10*$i`(%rsp)# save tweak[$i] + paddq @XMM[7], @XMM[7] # psllq 1,$tweak + pand $twmask, $twres # isolate carry and residue + pcmpgtd @XMM[7], $twtmp # broadcast upper bits + pxor $twres, @XMM[7] +___ + $code.=<<___ if ($i>=1); + movdqu `0x10*($i-1)`($inp), @XMM[8+$i-1] + cmp \$`0x10*$i`,$len + je .Lxts_dec_$i +___ + $code.=<<___ if ($i>=2); + pxor @XMM[8+$i-2], @XMM[$i-2]# input[] ^ tweak[] +___ + } +$code.=<<___; + movdqu 0x60($inp), @XMM[8+6] + pxor @XMM[8+5], @XMM[5] + movdqa @XMM[7], 0x70(%rsp) + lea 0x70($inp), $inp + pxor @XMM[8+6], @XMM[6] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_decrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[6] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[4] + movdqu @XMM[6], 0x20($out) + pxor 0x40(%rsp), @XMM[2] + movdqu @XMM[4], 0x30($out) + pxor 0x50(%rsp), @XMM[7] + movdqu @XMM[2], 0x40($out) + pxor 0x60(%rsp), @XMM[3] + movdqu @XMM[7], 0x50($out) + movdqu @XMM[3], 0x60($out) + lea 0x70($out), $out + + movdqa 0x70(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_dec_done +.align 16 +.Lxts_dec_6: + pxor @XMM[8+4], @XMM[4] + lea 0x60($inp), $inp + pxor @XMM[8+5], @XMM[5] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_decrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[6] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[4] + movdqu @XMM[6], 0x20($out) + pxor 0x40(%rsp), @XMM[2] + movdqu @XMM[4], 0x30($out) + pxor 0x50(%rsp), @XMM[7] + movdqu @XMM[2], 0x40($out) + movdqu @XMM[7], 0x50($out) + lea 0x60($out), $out + + movdqa 0x60(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_dec_done +.align 16 +.Lxts_dec_5: + pxor @XMM[8+3], @XMM[3] + lea 0x50($inp), $inp + pxor @XMM[8+4], @XMM[4] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_decrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[6] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[4] + movdqu @XMM[6], 0x20($out) + pxor 0x40(%rsp), @XMM[2] + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + lea 0x50($out), $out + + movdqa 0x50(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_dec_done +.align 16 +.Lxts_dec_4: + pxor @XMM[8+2], @XMM[2] + lea 0x40($inp), $inp + pxor @XMM[8+3], @XMM[3] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_decrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[6] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[4] + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + lea 0x40($out), $out + + movdqa 0x40(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_dec_done +.align 16 +.Lxts_dec_3: + pxor @XMM[8+1], @XMM[1] + lea 0x30($inp), $inp + pxor @XMM[8+2], @XMM[2] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_decrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[6] + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + lea 0x30($out), $out + + movdqa 0x30(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_dec_done +.align 16 +.Lxts_dec_2: + pxor @XMM[8+0], @XMM[0] + lea 0x20($inp), $inp + pxor @XMM[8+1], @XMM[1] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_decrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + lea 0x20($out), $out + + movdqa 0x20(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_dec_done +.align 16 +.Lxts_dec_1: + pxor @XMM[0], @XMM[8] + lea 0x10($inp), $inp + movdqa @XMM[8], 0x20(%rbp) + lea 0x20(%rbp), $arg1 + lea 0x20(%rbp), $arg2 + lea ($key), $arg3 + call asm_AES_decrypt # doesn't touch %xmm + pxor 0x20(%rbp), @XMM[0] # ^= tweak[] + #pxor @XMM[8], @XMM[0] + #lea 0x80(%rsp), %rax # pass key schedule + #mov %edx, %r10d # pass rounds + #call _bsaes_decrypt8 + #pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + movdqu @XMM[0], 0x00($out) # write output + lea 0x10($out), $out + + movdqa 0x10(%rsp), @XMM[7] # next iteration tweak + +.Lxts_dec_done: + and \$15, %ebx + jz .Lxts_dec_ret + + pxor $twtmp, $twtmp + movdqa .Lxts_magic(%rip), $twmask + pcmpgtd @XMM[7], $twtmp + pshufd \$0x13, $twtmp, $twres + movdqa @XMM[7], @XMM[6] + paddq @XMM[7], @XMM[7] # psllq 1,$tweak + pand $twmask, $twres # isolate carry and residue + movdqu ($inp), @XMM[0] + pxor $twres, @XMM[7] + + lea 0x20(%rbp), $arg1 + pxor @XMM[7], @XMM[0] + lea 0x20(%rbp), $arg2 + movdqa @XMM[0], 0x20(%rbp) + lea ($key), $arg3 + call asm_AES_decrypt # doesn't touch %xmm + pxor 0x20(%rbp), @XMM[7] + mov $out, %rdx + movdqu @XMM[7], ($out) + +.Lxts_dec_steal: + movzb 16($inp), %eax + movzb (%rdx), %ecx + lea 1($inp), $inp + mov %al, (%rdx) + mov %cl, 16(%rdx) + lea 1(%rdx), %rdx + sub \$1,%ebx + jnz .Lxts_dec_steal + + movdqu ($out), @XMM[0] + lea 0x20(%rbp), $arg1 + pxor @XMM[6], @XMM[0] + lea 0x20(%rbp), $arg2 + movdqa @XMM[0], 0x20(%rbp) + lea ($key), $arg3 + call asm_AES_decrypt # doesn't touch %xmm + pxor 0x20(%rbp), @XMM[6] + movdqu @XMM[6], ($out) + +.Lxts_dec_ret: + lea (%rsp), %rax + pxor %xmm0, %xmm0 +.Lxts_dec_bzero: # wipe key schedule [if any] + movdqa %xmm0, 0x00(%rax) + movdqa %xmm0, 0x10(%rax) + lea 0x20(%rax), %rax + cmp %rax, %rbp + ja .Lxts_dec_bzero + + lea 0x78(%rbp),%rax +.cfi_def_cfa %rax,8 +___ +$code.=<<___ if ($win64); + movaps 0x40(%rbp), %xmm6 + movaps 0x50(%rbp), %xmm7 + movaps 0x60(%rbp), %xmm8 + movaps 0x70(%rbp), %xmm9 + movaps 0x80(%rbp), %xmm10 + movaps 0x90(%rbp), %xmm11 + movaps 0xa0(%rbp), %xmm12 + movaps 0xb0(%rbp), %xmm13 + movaps 0xc0(%rbp), %xmm14 + movaps 0xd0(%rbp), %xmm15 + lea 0xa0(%rax), %rax +.Lxts_dec_tail: +___ +$code.=<<___; + mov -48(%rax), %r15 +.cfi_restore %r15 + mov -40(%rax), %r14 +.cfi_restore %r14 + mov -32(%rax), %r13 +.cfi_restore %r13 + mov -24(%rax), %r12 +.cfi_restore %r12 + mov -16(%rax), %rbx +.cfi_restore %rbx + mov -8(%rax), %rbp +.cfi_restore %rbp + lea (%rax), %rsp # restore %rsp +.cfi_def_cfa_register %rsp +.Lxts_dec_epilogue: + ret +.cfi_endproc +.size bsaes_xts_decrypt,.-bsaes_xts_decrypt +___ +} +$code.=<<___; +.type _bsaes_const,\@object +.align 64 +_bsaes_const: +.LM0ISR: # InvShiftRows constants + .quad 0x0a0e0206070b0f03, 0x0004080c0d010509 +.LISRM0: + .quad 0x01040b0e0205080f, 0x0306090c00070a0d +.LISR: + .quad 0x0504070602010003, 0x0f0e0d0c080b0a09 +.LBS0: # bit-slice constants + .quad 0x5555555555555555, 0x5555555555555555 +.LBS1: + .quad 0x3333333333333333, 0x3333333333333333 +.LBS2: + .quad 0x0f0f0f0f0f0f0f0f, 0x0f0f0f0f0f0f0f0f +.LSR: # shiftrows constants + .quad 0x0504070600030201, 0x0f0e0d0c0a09080b +.LSRM0: + .quad 0x0304090e00050a0f, 0x01060b0c0207080d +.LM0SR: + .quad 0x0a0e02060f03070b, 0x0004080c05090d01 +.LSWPUP: # byte-swap upper dword + .quad 0x0706050403020100, 0x0c0d0e0f0b0a0908 +.LSWPUPM0SR: + .quad 0x0a0d02060c03070b, 0x0004080f05090e01 +.LADD1: # counter increment constants + .quad 0x0000000000000000, 0x0000000100000000 +.LADD2: + .quad 0x0000000000000000, 0x0000000200000000 +.LADD3: + .quad 0x0000000000000000, 0x0000000300000000 +.LADD4: + .quad 0x0000000000000000, 0x0000000400000000 +.LADD5: + .quad 0x0000000000000000, 0x0000000500000000 +.LADD6: + .quad 0x0000000000000000, 0x0000000600000000 +.LADD7: + .quad 0x0000000000000000, 0x0000000700000000 +.LADD8: + .quad 0x0000000000000000, 0x0000000800000000 +.Lxts_magic: + .long 0x87,0,1,0 +.Lmasks: + .quad 0x0101010101010101, 0x0101010101010101 + .quad 0x0202020202020202, 0x0202020202020202 + .quad 0x0404040404040404, 0x0404040404040404 + .quad 0x0808080808080808, 0x0808080808080808 +.LM0: + .quad 0x02060a0e03070b0f, 0x0004080c0105090d +.L63: + .quad 0x6363636363636363, 0x6363636363636363 +.asciz "Bit-sliced AES for x86_64/SSSE3, Emilia Käsper, Peter Schwabe, Andy Polyakov" +.align 64 +.size _bsaes_const,.-_bsaes_const +___ + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type se_handler,\@abi-omnipotent +.align 16 +se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->Rip<=prologue label + jbe .Lin_prologue + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lin_prologue + + mov 8(%r11),%r10d # HandlerData[2] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=tail label + jae .Lin_tail + + mov 160($context),%rax # pull context->Rbp + + lea 0x40(%rax),%rsi # %xmm save area + lea 512($context),%rdi # &context.Xmm6 + mov \$20,%ecx # 10*sizeof(%xmm0)/sizeof(%rax) + .long 0xa548f3fc # cld; rep movsq + lea 0xa0+0x78(%rax),%rax # adjust stack pointer + +.Lin_tail: + mov -48(%rax),%rbp + mov -40(%rax),%rbx + mov -32(%rax),%r12 + mov -24(%rax),%r13 + mov -16(%rax),%r14 + mov -8(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + +.Lin_prologue: + mov %rax,152($context) # restore context->Rsp + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$`1232/8`,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size se_handler,.-se_handler + +.section .pdata +.align 4 +___ +$code.=<<___ if ($ecb); + .rva .Lecb_enc_prologue + .rva .Lecb_enc_epilogue + .rva .Lecb_enc_info + + .rva .Lecb_dec_prologue + .rva .Lecb_dec_epilogue + .rva .Lecb_dec_info +___ +$code.=<<___; + .rva .Lcbc_dec_prologue + .rva .Lcbc_dec_epilogue + .rva .Lcbc_dec_info + + .rva .Lctr_enc_prologue + .rva .Lctr_enc_epilogue + .rva .Lctr_enc_info + + .rva .Lxts_enc_prologue + .rva .Lxts_enc_epilogue + .rva .Lxts_enc_info + + .rva .Lxts_dec_prologue + .rva .Lxts_dec_epilogue + .rva .Lxts_dec_info + +.section .xdata +.align 8 +___ +$code.=<<___ if ($ecb); +.Lecb_enc_info: + .byte 9,0,0,0 + .rva se_handler + .rva .Lecb_enc_body,.Lecb_enc_epilogue # HandlerData[] + .rva .Lecb_enc_tail + .long 0 +.Lecb_dec_info: + .byte 9,0,0,0 + .rva se_handler + .rva .Lecb_dec_body,.Lecb_dec_epilogue # HandlerData[] + .rva .Lecb_dec_tail + .long 0 +___ +$code.=<<___; +.Lcbc_dec_info: + .byte 9,0,0,0 + .rva se_handler + .rva .Lcbc_dec_body,.Lcbc_dec_epilogue # HandlerData[] + .rva .Lcbc_dec_tail + .long 0 +.Lctr_enc_info: + .byte 9,0,0,0 + .rva se_handler + .rva .Lctr_enc_body,.Lctr_enc_epilogue # HandlerData[] + .rva .Lctr_enc_tail + .long 0 +.Lxts_enc_info: + .byte 9,0,0,0 + .rva se_handler + .rva .Lxts_enc_body,.Lxts_enc_epilogue # HandlerData[] + .rva .Lxts_enc_tail + .long 0 +.Lxts_dec_info: + .byte 9,0,0,0 + .rva se_handler + .rva .Lxts_dec_body,.Lxts_dec_epilogue # HandlerData[] + .rva .Lxts_dec_tail + .long 0 +___ +} + +$code =~ s/\`([^\`]*)\`/eval($1)/gem; + +print $code; + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/vpaes-armv8.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/vpaes-armv8.pl new file mode 100755 index 000000000..e38288af5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/vpaes-armv8.pl @@ -0,0 +1,1277 @@ +#! /usr/bin/env perl +# Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +###################################################################### +## Constant-time SSSE3 AES core implementation. +## version 0.1 +## +## By Mike Hamburg (Stanford University), 2009 +## Public domain. +## +## For details see http://shiftleft.org/papers/vector_aes/ and +## http://crypto.stanford.edu/vpaes/. +## +###################################################################### +# ARMv8 NEON adaptation by +# +# Reason for undertaken effort is that there is at least one popular +# SoC based on Cortex-A53 that doesn't have crypto extensions. +# +# CBC enc ECB enc/dec(*) [bit-sliced enc/dec] +# Cortex-A53 21.5 18.1/20.6 [17.5/19.8 ] +# Cortex-A57 36.0(**) 20.4/24.9(**) [14.4/16.6 ] +# X-Gene 45.9(**) 45.8/57.7(**) [33.1/37.6(**) ] +# Denver(***) 16.6(**) 15.1/17.8(**) [8.80/9.93 ] +# Apple A7(***) 22.7(**) 10.9/14.3 [8.45/10.0 ] +# Mongoose(***) 26.3(**) 21.0/25.0(**) [13.3/16.8 ] +# +# (*) ECB denotes approximate result for parallelizable modes +# such as CBC decrypt, CTR, etc.; +# (**) these results are worse than scalar compiler-generated +# code, but it's constant-time and therefore preferred; +# (***) presented for reference/comparison purposes; + +$flavour = shift; +while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or +die "can't locate arm-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +$code.=<<___; +.text + +.type _vpaes_consts,%object +.align 7 // totally strategic alignment +_vpaes_consts: +.Lk_mc_forward: // mc_forward + .quad 0x0407060500030201, 0x0C0F0E0D080B0A09 + .quad 0x080B0A0904070605, 0x000302010C0F0E0D + .quad 0x0C0F0E0D080B0A09, 0x0407060500030201 + .quad 0x000302010C0F0E0D, 0x080B0A0904070605 +.Lk_mc_backward:// mc_backward + .quad 0x0605040702010003, 0x0E0D0C0F0A09080B + .quad 0x020100030E0D0C0F, 0x0A09080B06050407 + .quad 0x0E0D0C0F0A09080B, 0x0605040702010003 + .quad 0x0A09080B06050407, 0x020100030E0D0C0F +.Lk_sr: // sr + .quad 0x0706050403020100, 0x0F0E0D0C0B0A0908 + .quad 0x030E09040F0A0500, 0x0B06010C07020D08 + .quad 0x0F060D040B020900, 0x070E050C030A0108 + .quad 0x0B0E0104070A0D00, 0x0306090C0F020508 + +// +// "Hot" constants +// +.Lk_inv: // inv, inva + .quad 0x0E05060F0D080180, 0x040703090A0B0C02 + .quad 0x01040A060F0B0780, 0x030D0E0C02050809 +.Lk_ipt: // input transform (lo, hi) + .quad 0xC2B2E8985A2A7000, 0xCABAE09052227808 + .quad 0x4C01307D317C4D00, 0xCD80B1FCB0FDCC81 +.Lk_sbo: // sbou, sbot + .quad 0xD0D26D176FBDC700, 0x15AABF7AC502A878 + .quad 0xCFE474A55FBB6A00, 0x8E1E90D1412B35FA +.Lk_sb1: // sb1u, sb1t + .quad 0x3618D415FAE22300, 0x3BF7CCC10D2ED9EF + .quad 0xB19BE18FCB503E00, 0xA5DF7A6E142AF544 +.Lk_sb2: // sb2u, sb2t + .quad 0x69EB88400AE12900, 0xC2A163C8AB82234A + .quad 0xE27A93C60B712400, 0x5EB7E955BC982FCD + +// +// Decryption stuff +// +.Lk_dipt: // decryption input transform + .quad 0x0F505B040B545F00, 0x154A411E114E451A + .quad 0x86E383E660056500, 0x12771772F491F194 +.Lk_dsbo: // decryption sbox final output + .quad 0x1387EA537EF94000, 0xC7AA6DB9D4943E2D + .quad 0x12D7560F93441D00, 0xCA4B8159D8C58E9C +.Lk_dsb9: // decryption sbox output *9*u, *9*t + .quad 0x851C03539A86D600, 0xCAD51F504F994CC9 + .quad 0xC03B1789ECD74900, 0x725E2C9EB2FBA565 +.Lk_dsbd: // decryption sbox output *D*u, *D*t + .quad 0x7D57CCDFE6B1A200, 0xF56E9B13882A4439 + .quad 0x3CE2FAF724C6CB00, 0x2931180D15DEEFD3 +.Lk_dsbb: // decryption sbox output *B*u, *B*t + .quad 0xD022649296B44200, 0x602646F6B0F2D404 + .quad 0xC19498A6CD596700, 0xF3FF0C3E3255AA6B +.Lk_dsbe: // decryption sbox output *E*u, *E*t + .quad 0x46F2929626D4D000, 0x2242600464B4F6B0 + .quad 0x0C55A6CDFFAAC100, 0x9467F36B98593E32 + +// +// Key schedule constants +// +.Lk_dksd: // decryption key schedule: invskew x*D + .quad 0xFEB91A5DA3E44700, 0x0740E3A45A1DBEF9 + .quad 0x41C277F4B5368300, 0x5FDC69EAAB289D1E +.Lk_dksb: // decryption key schedule: invskew x*B + .quad 0x9A4FCA1F8550D500, 0x03D653861CC94C99 + .quad 0x115BEDA7B6FC4A00, 0xD993256F7E3482C8 +.Lk_dkse: // decryption key schedule: invskew x*E + 0x63 + .quad 0xD5031CCA1FC9D600, 0x53859A4C994F5086 + .quad 0xA23196054FDC7BE8, 0xCD5EF96A20B31487 +.Lk_dks9: // decryption key schedule: invskew x*9 + .quad 0xB6116FC87ED9A700, 0x4AED933482255BFC + .quad 0x4576516227143300, 0x8BB89FACE9DAFDCE + +.Lk_rcon: // rcon + .quad 0x1F8391B9AF9DEEB6, 0x702A98084D7C7D81 + +.Lk_opt: // output transform + .quad 0xFF9F4929D6B66000, 0xF7974121DEBE6808 + .quad 0x01EDBD5150BCEC00, 0xE10D5DB1B05C0CE0 +.Lk_deskew: // deskew tables: inverts the sbox's "skew" + .quad 0x07E4A34047A4E300, 0x1DFEB95A5DBEF91A + .quad 0x5F36B5DC83EA6900, 0x2841C2ABF49D1E77 + +.asciz "Vector Permutation AES for ARMv8, Mike Hamburg (Stanford University)" +.size _vpaes_consts,.-_vpaes_consts +.align 6 +___ + +{ +my ($inp,$out,$key) = map("x$_",(0..2)); + +my ($invlo,$invhi,$iptlo,$ipthi,$sbou,$sbot) = map("v$_.16b",(18..23)); +my ($sb1u,$sb1t,$sb2u,$sb2t) = map("v$_.16b",(24..27)); +my ($sb9u,$sb9t,$sbdu,$sbdt,$sbbu,$sbbt,$sbeu,$sbet)=map("v$_.16b",(24..31)); + +$code.=<<___; +## +## _aes_preheat +## +## Fills register %r10 -> .aes_consts (so you can -fPIC) +## and %xmm9-%xmm15 as specified below. +## +.type _vpaes_encrypt_preheat,%function +.align 4 +_vpaes_encrypt_preheat: + adr x10, .Lk_inv + movi v17.16b, #0x0f + ld1 {v18.2d-v19.2d}, [x10],#32 // .Lk_inv + ld1 {v20.2d-v23.2d}, [x10],#64 // .Lk_ipt, .Lk_sbo + ld1 {v24.2d-v27.2d}, [x10] // .Lk_sb1, .Lk_sb2 + ret +.size _vpaes_encrypt_preheat,.-_vpaes_encrypt_preheat + +## +## _aes_encrypt_core +## +## AES-encrypt %xmm0. +## +## Inputs: +## %xmm0 = input +## %xmm9-%xmm15 as in _vpaes_preheat +## (%rdx) = scheduled keys +## +## Output in %xmm0 +## Clobbers %xmm1-%xmm5, %r9, %r10, %r11, %rax +## Preserves %xmm6 - %xmm8 so you get some local vectors +## +## +.type _vpaes_encrypt_core,%function +.align 4 +_vpaes_encrypt_core: + mov x9, $key + ldr w8, [$key,#240] // pull rounds + adr x11, .Lk_mc_forward+16 + // vmovdqa .Lk_ipt(%rip), %xmm2 # iptlo + ld1 {v16.2d}, [x9], #16 // vmovdqu (%r9), %xmm5 # round0 key + and v1.16b, v7.16b, v17.16b // vpand %xmm9, %xmm0, %xmm1 + ushr v0.16b, v7.16b, #4 // vpsrlb \$4, %xmm0, %xmm0 + tbl v1.16b, {$iptlo}, v1.16b // vpshufb %xmm1, %xmm2, %xmm1 + // vmovdqa .Lk_ipt+16(%rip), %xmm3 # ipthi + tbl v2.16b, {$ipthi}, v0.16b // vpshufb %xmm0, %xmm3, %xmm2 + eor v0.16b, v1.16b, v16.16b // vpxor %xmm5, %xmm1, %xmm0 + eor v0.16b, v0.16b, v2.16b // vpxor %xmm2, %xmm0, %xmm0 + b .Lenc_entry + +.align 4 +.Lenc_loop: + // middle of middle round + add x10, x11, #0x40 + tbl v4.16b, {$sb1t}, v2.16b // vpshufb %xmm2, %xmm13, %xmm4 # 4 = sb1u + ld1 {v1.2d}, [x11], #16 // vmovdqa -0x40(%r11,%r10), %xmm1 # .Lk_mc_forward[] + tbl v0.16b, {$sb1u}, v3.16b // vpshufb %xmm3, %xmm12, %xmm0 # 0 = sb1t + eor v4.16b, v4.16b, v16.16b // vpxor %xmm5, %xmm4, %xmm4 # 4 = sb1u + k + tbl v5.16b, {$sb2t}, v2.16b // vpshufb %xmm2, %xmm15, %xmm5 # 4 = sb2u + eor v0.16b, v0.16b, v4.16b // vpxor %xmm4, %xmm0, %xmm0 # 0 = A + tbl v2.16b, {$sb2u}, v3.16b // vpshufb %xmm3, %xmm14, %xmm2 # 2 = sb2t + ld1 {v4.2d}, [x10] // vmovdqa (%r11,%r10), %xmm4 # .Lk_mc_backward[] + tbl v3.16b, {v0.16b}, v1.16b // vpshufb %xmm1, %xmm0, %xmm3 # 0 = B + eor v2.16b, v2.16b, v5.16b // vpxor %xmm5, %xmm2, %xmm2 # 2 = 2A + tbl v0.16b, {v0.16b}, v4.16b // vpshufb %xmm4, %xmm0, %xmm0 # 3 = D + eor v3.16b, v3.16b, v2.16b // vpxor %xmm2, %xmm3, %xmm3 # 0 = 2A+B + tbl v4.16b, {v3.16b}, v1.16b // vpshufb %xmm1, %xmm3, %xmm4 # 0 = 2B+C + eor v0.16b, v0.16b, v3.16b // vpxor %xmm3, %xmm0, %xmm0 # 3 = 2A+B+D + and x11, x11, #~(1<<6) // and \$0x30, %r11 # ... mod 4 + eor v0.16b, v0.16b, v4.16b // vpxor %xmm4, %xmm0, %xmm0 # 0 = 2A+3B+C+D + sub w8, w8, #1 // nr-- + +.Lenc_entry: + // top of round + and v1.16b, v0.16b, v17.16b // vpand %xmm0, %xmm9, %xmm1 # 0 = k + ushr v0.16b, v0.16b, #4 // vpsrlb \$4, %xmm0, %xmm0 # 1 = i + tbl v5.16b, {$invhi}, v1.16b // vpshufb %xmm1, %xmm11, %xmm5 # 2 = a/k + eor v1.16b, v1.16b, v0.16b // vpxor %xmm0, %xmm1, %xmm1 # 0 = j + tbl v3.16b, {$invlo}, v0.16b // vpshufb %xmm0, %xmm10, %xmm3 # 3 = 1/i + tbl v4.16b, {$invlo}, v1.16b // vpshufb %xmm1, %xmm10, %xmm4 # 4 = 1/j + eor v3.16b, v3.16b, v5.16b // vpxor %xmm5, %xmm3, %xmm3 # 3 = iak = 1/i + a/k + eor v4.16b, v4.16b, v5.16b // vpxor %xmm5, %xmm4, %xmm4 # 4 = jak = 1/j + a/k + tbl v2.16b, {$invlo}, v3.16b // vpshufb %xmm3, %xmm10, %xmm2 # 2 = 1/iak + tbl v3.16b, {$invlo}, v4.16b // vpshufb %xmm4, %xmm10, %xmm3 # 3 = 1/jak + eor v2.16b, v2.16b, v1.16b // vpxor %xmm1, %xmm2, %xmm2 # 2 = io + eor v3.16b, v3.16b, v0.16b // vpxor %xmm0, %xmm3, %xmm3 # 3 = jo + ld1 {v16.2d}, [x9],#16 // vmovdqu (%r9), %xmm5 + cbnz w8, .Lenc_loop + + // middle of last round + add x10, x11, #0x80 + // vmovdqa -0x60(%r10), %xmm4 # 3 : sbou .Lk_sbo + // vmovdqa -0x50(%r10), %xmm0 # 0 : sbot .Lk_sbo+16 + tbl v4.16b, {$sbou}, v2.16b // vpshufb %xmm2, %xmm4, %xmm4 # 4 = sbou + ld1 {v1.2d}, [x10] // vmovdqa 0x40(%r11,%r10), %xmm1 # .Lk_sr[] + tbl v0.16b, {$sbot}, v3.16b // vpshufb %xmm3, %xmm0, %xmm0 # 0 = sb1t + eor v4.16b, v4.16b, v16.16b // vpxor %xmm5, %xmm4, %xmm4 # 4 = sb1u + k + eor v0.16b, v0.16b, v4.16b // vpxor %xmm4, %xmm0, %xmm0 # 0 = A + tbl v0.16b, {v0.16b}, v1.16b // vpshufb %xmm1, %xmm0, %xmm0 + ret +.size _vpaes_encrypt_core,.-_vpaes_encrypt_core + +.globl vpaes_encrypt +.type vpaes_encrypt,%function +.align 4 +vpaes_encrypt: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-16]! + add x29,sp,#0 + + ld1 {v7.16b}, [$inp] + bl _vpaes_encrypt_preheat + bl _vpaes_encrypt_core + st1 {v0.16b}, [$out] + + ldp x29,x30,[sp],#16 + .inst 0xd50323bf // autiasp + ret +.size vpaes_encrypt,.-vpaes_encrypt + +.type _vpaes_encrypt_2x,%function +.align 4 +_vpaes_encrypt_2x: + mov x9, $key + ldr w8, [$key,#240] // pull rounds + adr x11, .Lk_mc_forward+16 + // vmovdqa .Lk_ipt(%rip), %xmm2 # iptlo + ld1 {v16.2d}, [x9], #16 // vmovdqu (%r9), %xmm5 # round0 key + and v1.16b, v14.16b, v17.16b // vpand %xmm9, %xmm0, %xmm1 + ushr v0.16b, v14.16b, #4 // vpsrlb \$4, %xmm0, %xmm0 + and v9.16b, v15.16b, v17.16b + ushr v8.16b, v15.16b, #4 + tbl v1.16b, {$iptlo}, v1.16b // vpshufb %xmm1, %xmm2, %xmm1 + tbl v9.16b, {$iptlo}, v9.16b + // vmovdqa .Lk_ipt+16(%rip), %xmm3 # ipthi + tbl v2.16b, {$ipthi}, v0.16b // vpshufb %xmm0, %xmm3, %xmm2 + tbl v10.16b, {$ipthi}, v8.16b + eor v0.16b, v1.16b, v16.16b // vpxor %xmm5, %xmm1, %xmm0 + eor v8.16b, v9.16b, v16.16b + eor v0.16b, v0.16b, v2.16b // vpxor %xmm2, %xmm0, %xmm0 + eor v8.16b, v8.16b, v10.16b + b .Lenc_2x_entry + +.align 4 +.Lenc_2x_loop: + // middle of middle round + add x10, x11, #0x40 + tbl v4.16b, {$sb1t}, v2.16b // vpshufb %xmm2, %xmm13, %xmm4 # 4 = sb1u + tbl v12.16b, {$sb1t}, v10.16b + ld1 {v1.2d}, [x11], #16 // vmovdqa -0x40(%r11,%r10), %xmm1 # .Lk_mc_forward[] + tbl v0.16b, {$sb1u}, v3.16b // vpshufb %xmm3, %xmm12, %xmm0 # 0 = sb1t + tbl v8.16b, {$sb1u}, v11.16b + eor v4.16b, v4.16b, v16.16b // vpxor %xmm5, %xmm4, %xmm4 # 4 = sb1u + k + eor v12.16b, v12.16b, v16.16b + tbl v5.16b, {$sb2t}, v2.16b // vpshufb %xmm2, %xmm15, %xmm5 # 4 = sb2u + tbl v13.16b, {$sb2t}, v10.16b + eor v0.16b, v0.16b, v4.16b // vpxor %xmm4, %xmm0, %xmm0 # 0 = A + eor v8.16b, v8.16b, v12.16b + tbl v2.16b, {$sb2u}, v3.16b // vpshufb %xmm3, %xmm14, %xmm2 # 2 = sb2t + tbl v10.16b, {$sb2u}, v11.16b + ld1 {v4.2d}, [x10] // vmovdqa (%r11,%r10), %xmm4 # .Lk_mc_backward[] + tbl v3.16b, {v0.16b}, v1.16b // vpshufb %xmm1, %xmm0, %xmm3 # 0 = B + tbl v11.16b, {v8.16b}, v1.16b + eor v2.16b, v2.16b, v5.16b // vpxor %xmm5, %xmm2, %xmm2 # 2 = 2A + eor v10.16b, v10.16b, v13.16b + tbl v0.16b, {v0.16b}, v4.16b // vpshufb %xmm4, %xmm0, %xmm0 # 3 = D + tbl v8.16b, {v8.16b}, v4.16b + eor v3.16b, v3.16b, v2.16b // vpxor %xmm2, %xmm3, %xmm3 # 0 = 2A+B + eor v11.16b, v11.16b, v10.16b + tbl v4.16b, {v3.16b}, v1.16b // vpshufb %xmm1, %xmm3, %xmm4 # 0 = 2B+C + tbl v12.16b, {v11.16b},v1.16b + eor v0.16b, v0.16b, v3.16b // vpxor %xmm3, %xmm0, %xmm0 # 3 = 2A+B+D + eor v8.16b, v8.16b, v11.16b + and x11, x11, #~(1<<6) // and \$0x30, %r11 # ... mod 4 + eor v0.16b, v0.16b, v4.16b // vpxor %xmm4, %xmm0, %xmm0 # 0 = 2A+3B+C+D + eor v8.16b, v8.16b, v12.16b + sub w8, w8, #1 // nr-- + +.Lenc_2x_entry: + // top of round + and v1.16b, v0.16b, v17.16b // vpand %xmm0, %xmm9, %xmm1 # 0 = k + ushr v0.16b, v0.16b, #4 // vpsrlb \$4, %xmm0, %xmm0 # 1 = i + and v9.16b, v8.16b, v17.16b + ushr v8.16b, v8.16b, #4 + tbl v5.16b, {$invhi},v1.16b // vpshufb %xmm1, %xmm11, %xmm5 # 2 = a/k + tbl v13.16b, {$invhi},v9.16b + eor v1.16b, v1.16b, v0.16b // vpxor %xmm0, %xmm1, %xmm1 # 0 = j + eor v9.16b, v9.16b, v8.16b + tbl v3.16b, {$invlo},v0.16b // vpshufb %xmm0, %xmm10, %xmm3 # 3 = 1/i + tbl v11.16b, {$invlo},v8.16b + tbl v4.16b, {$invlo},v1.16b // vpshufb %xmm1, %xmm10, %xmm4 # 4 = 1/j + tbl v12.16b, {$invlo},v9.16b + eor v3.16b, v3.16b, v5.16b // vpxor %xmm5, %xmm3, %xmm3 # 3 = iak = 1/i + a/k + eor v11.16b, v11.16b, v13.16b + eor v4.16b, v4.16b, v5.16b // vpxor %xmm5, %xmm4, %xmm4 # 4 = jak = 1/j + a/k + eor v12.16b, v12.16b, v13.16b + tbl v2.16b, {$invlo},v3.16b // vpshufb %xmm3, %xmm10, %xmm2 # 2 = 1/iak + tbl v10.16b, {$invlo},v11.16b + tbl v3.16b, {$invlo},v4.16b // vpshufb %xmm4, %xmm10, %xmm3 # 3 = 1/jak + tbl v11.16b, {$invlo},v12.16b + eor v2.16b, v2.16b, v1.16b // vpxor %xmm1, %xmm2, %xmm2 # 2 = io + eor v10.16b, v10.16b, v9.16b + eor v3.16b, v3.16b, v0.16b // vpxor %xmm0, %xmm3, %xmm3 # 3 = jo + eor v11.16b, v11.16b, v8.16b + ld1 {v16.2d}, [x9],#16 // vmovdqu (%r9), %xmm5 + cbnz w8, .Lenc_2x_loop + + // middle of last round + add x10, x11, #0x80 + // vmovdqa -0x60(%r10), %xmm4 # 3 : sbou .Lk_sbo + // vmovdqa -0x50(%r10), %xmm0 # 0 : sbot .Lk_sbo+16 + tbl v4.16b, {$sbou}, v2.16b // vpshufb %xmm2, %xmm4, %xmm4 # 4 = sbou + tbl v12.16b, {$sbou}, v10.16b + ld1 {v1.2d}, [x10] // vmovdqa 0x40(%r11,%r10), %xmm1 # .Lk_sr[] + tbl v0.16b, {$sbot}, v3.16b // vpshufb %xmm3, %xmm0, %xmm0 # 0 = sb1t + tbl v8.16b, {$sbot}, v11.16b + eor v4.16b, v4.16b, v16.16b // vpxor %xmm5, %xmm4, %xmm4 # 4 = sb1u + k + eor v12.16b, v12.16b, v16.16b + eor v0.16b, v0.16b, v4.16b // vpxor %xmm4, %xmm0, %xmm0 # 0 = A + eor v8.16b, v8.16b, v12.16b + tbl v0.16b, {v0.16b},v1.16b // vpshufb %xmm1, %xmm0, %xmm0 + tbl v1.16b, {v8.16b},v1.16b + ret +.size _vpaes_encrypt_2x,.-_vpaes_encrypt_2x + +.type _vpaes_decrypt_preheat,%function +.align 4 +_vpaes_decrypt_preheat: + adr x10, .Lk_inv + movi v17.16b, #0x0f + adr x11, .Lk_dipt + ld1 {v18.2d-v19.2d}, [x10],#32 // .Lk_inv + ld1 {v20.2d-v23.2d}, [x11],#64 // .Lk_dipt, .Lk_dsbo + ld1 {v24.2d-v27.2d}, [x11],#64 // .Lk_dsb9, .Lk_dsbd + ld1 {v28.2d-v31.2d}, [x11] // .Lk_dsbb, .Lk_dsbe + ret +.size _vpaes_decrypt_preheat,.-_vpaes_decrypt_preheat + +## +## Decryption core +## +## Same API as encryption core. +## +.type _vpaes_decrypt_core,%function +.align 4 +_vpaes_decrypt_core: + mov x9, $key + ldr w8, [$key,#240] // pull rounds + + // vmovdqa .Lk_dipt(%rip), %xmm2 # iptlo + lsl x11, x8, #4 // mov %rax, %r11; shl \$4, %r11 + eor x11, x11, #0x30 // xor \$0x30, %r11 + adr x10, .Lk_sr + and x11, x11, #0x30 // and \$0x30, %r11 + add x11, x11, x10 + adr x10, .Lk_mc_forward+48 + + ld1 {v16.2d}, [x9],#16 // vmovdqu (%r9), %xmm4 # round0 key + and v1.16b, v7.16b, v17.16b // vpand %xmm9, %xmm0, %xmm1 + ushr v0.16b, v7.16b, #4 // vpsrlb \$4, %xmm0, %xmm0 + tbl v2.16b, {$iptlo}, v1.16b // vpshufb %xmm1, %xmm2, %xmm2 + ld1 {v5.2d}, [x10] // vmovdqa .Lk_mc_forward+48(%rip), %xmm5 + // vmovdqa .Lk_dipt+16(%rip), %xmm1 # ipthi + tbl v0.16b, {$ipthi}, v0.16b // vpshufb %xmm0, %xmm1, %xmm0 + eor v2.16b, v2.16b, v16.16b // vpxor %xmm4, %xmm2, %xmm2 + eor v0.16b, v0.16b, v2.16b // vpxor %xmm2, %xmm0, %xmm0 + b .Ldec_entry + +.align 4 +.Ldec_loop: +// +// Inverse mix columns +// + // vmovdqa -0x20(%r10),%xmm4 # 4 : sb9u + // vmovdqa -0x10(%r10),%xmm1 # 0 : sb9t + tbl v4.16b, {$sb9u}, v2.16b // vpshufb %xmm2, %xmm4, %xmm4 # 4 = sb9u + tbl v1.16b, {$sb9t}, v3.16b // vpshufb %xmm3, %xmm1, %xmm1 # 0 = sb9t + eor v0.16b, v4.16b, v16.16b // vpxor %xmm4, %xmm0, %xmm0 + // vmovdqa 0x00(%r10),%xmm4 # 4 : sbdu + eor v0.16b, v0.16b, v1.16b // vpxor %xmm1, %xmm0, %xmm0 # 0 = ch + // vmovdqa 0x10(%r10),%xmm1 # 0 : sbdt + + tbl v4.16b, {$sbdu}, v2.16b // vpshufb %xmm2, %xmm4, %xmm4 # 4 = sbdu + tbl v0.16b, {v0.16b}, v5.16b // vpshufb %xmm5, %xmm0, %xmm0 # MC ch + tbl v1.16b, {$sbdt}, v3.16b // vpshufb %xmm3, %xmm1, %xmm1 # 0 = sbdt + eor v0.16b, v0.16b, v4.16b // vpxor %xmm4, %xmm0, %xmm0 # 4 = ch + // vmovdqa 0x20(%r10), %xmm4 # 4 : sbbu + eor v0.16b, v0.16b, v1.16b // vpxor %xmm1, %xmm0, %xmm0 # 0 = ch + // vmovdqa 0x30(%r10), %xmm1 # 0 : sbbt + + tbl v4.16b, {$sbbu}, v2.16b // vpshufb %xmm2, %xmm4, %xmm4 # 4 = sbbu + tbl v0.16b, {v0.16b}, v5.16b // vpshufb %xmm5, %xmm0, %xmm0 # MC ch + tbl v1.16b, {$sbbt}, v3.16b // vpshufb %xmm3, %xmm1, %xmm1 # 0 = sbbt + eor v0.16b, v0.16b, v4.16b // vpxor %xmm4, %xmm0, %xmm0 # 4 = ch + // vmovdqa 0x40(%r10), %xmm4 # 4 : sbeu + eor v0.16b, v0.16b, v1.16b // vpxor %xmm1, %xmm0, %xmm0 # 0 = ch + // vmovdqa 0x50(%r10), %xmm1 # 0 : sbet + + tbl v4.16b, {$sbeu}, v2.16b // vpshufb %xmm2, %xmm4, %xmm4 # 4 = sbeu + tbl v0.16b, {v0.16b}, v5.16b // vpshufb %xmm5, %xmm0, %xmm0 # MC ch + tbl v1.16b, {$sbet}, v3.16b // vpshufb %xmm3, %xmm1, %xmm1 # 0 = sbet + eor v0.16b, v0.16b, v4.16b // vpxor %xmm4, %xmm0, %xmm0 # 4 = ch + ext v5.16b, v5.16b, v5.16b, #12 // vpalignr \$12, %xmm5, %xmm5, %xmm5 + eor v0.16b, v0.16b, v1.16b // vpxor %xmm1, %xmm0, %xmm0 # 0 = ch + sub w8, w8, #1 // sub \$1,%rax # nr-- + +.Ldec_entry: + // top of round + and v1.16b, v0.16b, v17.16b // vpand %xmm9, %xmm0, %xmm1 # 0 = k + ushr v0.16b, v0.16b, #4 // vpsrlb \$4, %xmm0, %xmm0 # 1 = i + tbl v2.16b, {$invhi}, v1.16b // vpshufb %xmm1, %xmm11, %xmm2 # 2 = a/k + eor v1.16b, v1.16b, v0.16b // vpxor %xmm0, %xmm1, %xmm1 # 0 = j + tbl v3.16b, {$invlo}, v0.16b // vpshufb %xmm0, %xmm10, %xmm3 # 3 = 1/i + tbl v4.16b, {$invlo}, v1.16b // vpshufb %xmm1, %xmm10, %xmm4 # 4 = 1/j + eor v3.16b, v3.16b, v2.16b // vpxor %xmm2, %xmm3, %xmm3 # 3 = iak = 1/i + a/k + eor v4.16b, v4.16b, v2.16b // vpxor %xmm2, %xmm4, %xmm4 # 4 = jak = 1/j + a/k + tbl v2.16b, {$invlo}, v3.16b // vpshufb %xmm3, %xmm10, %xmm2 # 2 = 1/iak + tbl v3.16b, {$invlo}, v4.16b // vpshufb %xmm4, %xmm10, %xmm3 # 3 = 1/jak + eor v2.16b, v2.16b, v1.16b // vpxor %xmm1, %xmm2, %xmm2 # 2 = io + eor v3.16b, v3.16b, v0.16b // vpxor %xmm0, %xmm3, %xmm3 # 3 = jo + ld1 {v16.2d}, [x9],#16 // vmovdqu (%r9), %xmm0 + cbnz w8, .Ldec_loop + + // middle of last round + // vmovdqa 0x60(%r10), %xmm4 # 3 : sbou + tbl v4.16b, {$sbou}, v2.16b // vpshufb %xmm2, %xmm4, %xmm4 # 4 = sbou + // vmovdqa 0x70(%r10), %xmm1 # 0 : sbot + ld1 {v2.2d}, [x11] // vmovdqa -0x160(%r11), %xmm2 # .Lk_sr-.Lk_dsbd=-0x160 + tbl v1.16b, {$sbot}, v3.16b // vpshufb %xmm3, %xmm1, %xmm1 # 0 = sb1t + eor v4.16b, v4.16b, v16.16b // vpxor %xmm0, %xmm4, %xmm4 # 4 = sb1u + k + eor v0.16b, v1.16b, v4.16b // vpxor %xmm4, %xmm1, %xmm0 # 0 = A + tbl v0.16b, {v0.16b}, v2.16b // vpshufb %xmm2, %xmm0, %xmm0 + ret +.size _vpaes_decrypt_core,.-_vpaes_decrypt_core + +.globl vpaes_decrypt +.type vpaes_decrypt,%function +.align 4 +vpaes_decrypt: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-16]! + add x29,sp,#0 + + ld1 {v7.16b}, [$inp] + bl _vpaes_decrypt_preheat + bl _vpaes_decrypt_core + st1 {v0.16b}, [$out] + + ldp x29,x30,[sp],#16 + .inst 0xd50323bf // autiasp + ret +.size vpaes_decrypt,.-vpaes_decrypt + +// v14-v15 input, v0-v1 output +.type _vpaes_decrypt_2x,%function +.align 4 +_vpaes_decrypt_2x: + mov x9, $key + ldr w8, [$key,#240] // pull rounds + + // vmovdqa .Lk_dipt(%rip), %xmm2 # iptlo + lsl x11, x8, #4 // mov %rax, %r11; shl \$4, %r11 + eor x11, x11, #0x30 // xor \$0x30, %r11 + adr x10, .Lk_sr + and x11, x11, #0x30 // and \$0x30, %r11 + add x11, x11, x10 + adr x10, .Lk_mc_forward+48 + + ld1 {v16.2d}, [x9],#16 // vmovdqu (%r9), %xmm4 # round0 key + and v1.16b, v14.16b, v17.16b // vpand %xmm9, %xmm0, %xmm1 + ushr v0.16b, v14.16b, #4 // vpsrlb \$4, %xmm0, %xmm0 + and v9.16b, v15.16b, v17.16b + ushr v8.16b, v15.16b, #4 + tbl v2.16b, {$iptlo},v1.16b // vpshufb %xmm1, %xmm2, %xmm2 + tbl v10.16b, {$iptlo},v9.16b + ld1 {v5.2d}, [x10] // vmovdqa .Lk_mc_forward+48(%rip), %xmm5 + // vmovdqa .Lk_dipt+16(%rip), %xmm1 # ipthi + tbl v0.16b, {$ipthi},v0.16b // vpshufb %xmm0, %xmm1, %xmm0 + tbl v8.16b, {$ipthi},v8.16b + eor v2.16b, v2.16b, v16.16b // vpxor %xmm4, %xmm2, %xmm2 + eor v10.16b, v10.16b, v16.16b + eor v0.16b, v0.16b, v2.16b // vpxor %xmm2, %xmm0, %xmm0 + eor v8.16b, v8.16b, v10.16b + b .Ldec_2x_entry + +.align 4 +.Ldec_2x_loop: +// +// Inverse mix columns +// + // vmovdqa -0x20(%r10),%xmm4 # 4 : sb9u + // vmovdqa -0x10(%r10),%xmm1 # 0 : sb9t + tbl v4.16b, {$sb9u}, v2.16b // vpshufb %xmm2, %xmm4, %xmm4 # 4 = sb9u + tbl v12.16b, {$sb9u}, v10.16b + tbl v1.16b, {$sb9t}, v3.16b // vpshufb %xmm3, %xmm1, %xmm1 # 0 = sb9t + tbl v9.16b, {$sb9t}, v11.16b + eor v0.16b, v4.16b, v16.16b // vpxor %xmm4, %xmm0, %xmm0 + eor v8.16b, v12.16b, v16.16b + // vmovdqa 0x00(%r10),%xmm4 # 4 : sbdu + eor v0.16b, v0.16b, v1.16b // vpxor %xmm1, %xmm0, %xmm0 # 0 = ch + eor v8.16b, v8.16b, v9.16b // vpxor %xmm1, %xmm0, %xmm0 # 0 = ch + // vmovdqa 0x10(%r10),%xmm1 # 0 : sbdt + + tbl v4.16b, {$sbdu}, v2.16b // vpshufb %xmm2, %xmm4, %xmm4 # 4 = sbdu + tbl v12.16b, {$sbdu}, v10.16b + tbl v0.16b, {v0.16b},v5.16b // vpshufb %xmm5, %xmm0, %xmm0 # MC ch + tbl v8.16b, {v8.16b},v5.16b + tbl v1.16b, {$sbdt}, v3.16b // vpshufb %xmm3, %xmm1, %xmm1 # 0 = sbdt + tbl v9.16b, {$sbdt}, v11.16b + eor v0.16b, v0.16b, v4.16b // vpxor %xmm4, %xmm0, %xmm0 # 4 = ch + eor v8.16b, v8.16b, v12.16b + // vmovdqa 0x20(%r10), %xmm4 # 4 : sbbu + eor v0.16b, v0.16b, v1.16b // vpxor %xmm1, %xmm0, %xmm0 # 0 = ch + eor v8.16b, v8.16b, v9.16b + // vmovdqa 0x30(%r10), %xmm1 # 0 : sbbt + + tbl v4.16b, {$sbbu}, v2.16b // vpshufb %xmm2, %xmm4, %xmm4 # 4 = sbbu + tbl v12.16b, {$sbbu}, v10.16b + tbl v0.16b, {v0.16b},v5.16b // vpshufb %xmm5, %xmm0, %xmm0 # MC ch + tbl v8.16b, {v8.16b},v5.16b + tbl v1.16b, {$sbbt}, v3.16b // vpshufb %xmm3, %xmm1, %xmm1 # 0 = sbbt + tbl v9.16b, {$sbbt}, v11.16b + eor v0.16b, v0.16b, v4.16b // vpxor %xmm4, %xmm0, %xmm0 # 4 = ch + eor v8.16b, v8.16b, v12.16b + // vmovdqa 0x40(%r10), %xmm4 # 4 : sbeu + eor v0.16b, v0.16b, v1.16b // vpxor %xmm1, %xmm0, %xmm0 # 0 = ch + eor v8.16b, v8.16b, v9.16b + // vmovdqa 0x50(%r10), %xmm1 # 0 : sbet + + tbl v4.16b, {$sbeu}, v2.16b // vpshufb %xmm2, %xmm4, %xmm4 # 4 = sbeu + tbl v12.16b, {$sbeu}, v10.16b + tbl v0.16b, {v0.16b},v5.16b // vpshufb %xmm5, %xmm0, %xmm0 # MC ch + tbl v8.16b, {v8.16b},v5.16b + tbl v1.16b, {$sbet}, v3.16b // vpshufb %xmm3, %xmm1, %xmm1 # 0 = sbet + tbl v9.16b, {$sbet}, v11.16b + eor v0.16b, v0.16b, v4.16b // vpxor %xmm4, %xmm0, %xmm0 # 4 = ch + eor v8.16b, v8.16b, v12.16b + ext v5.16b, v5.16b, v5.16b, #12 // vpalignr \$12, %xmm5, %xmm5, %xmm5 + eor v0.16b, v0.16b, v1.16b // vpxor %xmm1, %xmm0, %xmm0 # 0 = ch + eor v8.16b, v8.16b, v9.16b + sub w8, w8, #1 // sub \$1,%rax # nr-- + +.Ldec_2x_entry: + // top of round + and v1.16b, v0.16b, v17.16b // vpand %xmm9, %xmm0, %xmm1 # 0 = k + ushr v0.16b, v0.16b, #4 // vpsrlb \$4, %xmm0, %xmm0 # 1 = i + and v9.16b, v8.16b, v17.16b + ushr v8.16b, v8.16b, #4 + tbl v2.16b, {$invhi},v1.16b // vpshufb %xmm1, %xmm11, %xmm2 # 2 = a/k + tbl v10.16b, {$invhi},v9.16b + eor v1.16b, v1.16b, v0.16b // vpxor %xmm0, %xmm1, %xmm1 # 0 = j + eor v9.16b, v9.16b, v8.16b + tbl v3.16b, {$invlo},v0.16b // vpshufb %xmm0, %xmm10, %xmm3 # 3 = 1/i + tbl v11.16b, {$invlo},v8.16b + tbl v4.16b, {$invlo},v1.16b // vpshufb %xmm1, %xmm10, %xmm4 # 4 = 1/j + tbl v12.16b, {$invlo},v9.16b + eor v3.16b, v3.16b, v2.16b // vpxor %xmm2, %xmm3, %xmm3 # 3 = iak = 1/i + a/k + eor v11.16b, v11.16b, v10.16b + eor v4.16b, v4.16b, v2.16b // vpxor %xmm2, %xmm4, %xmm4 # 4 = jak = 1/j + a/k + eor v12.16b, v12.16b, v10.16b + tbl v2.16b, {$invlo},v3.16b // vpshufb %xmm3, %xmm10, %xmm2 # 2 = 1/iak + tbl v10.16b, {$invlo},v11.16b + tbl v3.16b, {$invlo},v4.16b // vpshufb %xmm4, %xmm10, %xmm3 # 3 = 1/jak + tbl v11.16b, {$invlo},v12.16b + eor v2.16b, v2.16b, v1.16b // vpxor %xmm1, %xmm2, %xmm2 # 2 = io + eor v10.16b, v10.16b, v9.16b + eor v3.16b, v3.16b, v0.16b // vpxor %xmm0, %xmm3, %xmm3 # 3 = jo + eor v11.16b, v11.16b, v8.16b + ld1 {v16.2d}, [x9],#16 // vmovdqu (%r9), %xmm0 + cbnz w8, .Ldec_2x_loop + + // middle of last round + // vmovdqa 0x60(%r10), %xmm4 # 3 : sbou + tbl v4.16b, {$sbou}, v2.16b // vpshufb %xmm2, %xmm4, %xmm4 # 4 = sbou + tbl v12.16b, {$sbou}, v10.16b + // vmovdqa 0x70(%r10), %xmm1 # 0 : sbot + tbl v1.16b, {$sbot}, v3.16b // vpshufb %xmm3, %xmm1, %xmm1 # 0 = sb1t + tbl v9.16b, {$sbot}, v11.16b + ld1 {v2.2d}, [x11] // vmovdqa -0x160(%r11), %xmm2 # .Lk_sr-.Lk_dsbd=-0x160 + eor v4.16b, v4.16b, v16.16b // vpxor %xmm0, %xmm4, %xmm4 # 4 = sb1u + k + eor v12.16b, v12.16b, v16.16b + eor v0.16b, v1.16b, v4.16b // vpxor %xmm4, %xmm1, %xmm0 # 0 = A + eor v8.16b, v9.16b, v12.16b + tbl v0.16b, {v0.16b},v2.16b // vpshufb %xmm2, %xmm0, %xmm0 + tbl v1.16b, {v8.16b},v2.16b + ret +.size _vpaes_decrypt_2x,.-_vpaes_decrypt_2x +___ +} +{ +my ($inp,$bits,$out,$dir)=("x0","w1","x2","w3"); +my ($invlo,$invhi,$iptlo,$ipthi,$rcon) = map("v$_.16b",(18..21,8)); + +$code.=<<___; +######################################################## +## ## +## AES key schedule ## +## ## +######################################################## +.type _vpaes_key_preheat,%function +.align 4 +_vpaes_key_preheat: + adr x10, .Lk_inv + movi v16.16b, #0x5b // .Lk_s63 + adr x11, .Lk_sb1 + movi v17.16b, #0x0f // .Lk_s0F + ld1 {v18.2d-v21.2d}, [x10] // .Lk_inv, .Lk_ipt + adr x10, .Lk_dksd + ld1 {v22.2d-v23.2d}, [x11] // .Lk_sb1 + adr x11, .Lk_mc_forward + ld1 {v24.2d-v27.2d}, [x10],#64 // .Lk_dksd, .Lk_dksb + ld1 {v28.2d-v31.2d}, [x10],#64 // .Lk_dkse, .Lk_dks9 + ld1 {v8.2d}, [x10] // .Lk_rcon + ld1 {v9.2d}, [x11] // .Lk_mc_forward[0] + ret +.size _vpaes_key_preheat,.-_vpaes_key_preheat + +.type _vpaes_schedule_core,%function +.align 4 +_vpaes_schedule_core: + .inst 0xd503233f // paciasp + stp x29, x30, [sp,#-16]! + add x29,sp,#0 + + bl _vpaes_key_preheat // load the tables + + ld1 {v0.16b}, [$inp],#16 // vmovdqu (%rdi), %xmm0 # load key (unaligned) + + // input transform + mov v3.16b, v0.16b // vmovdqa %xmm0, %xmm3 + bl _vpaes_schedule_transform + mov v7.16b, v0.16b // vmovdqa %xmm0, %xmm7 + + adr x10, .Lk_sr // lea .Lk_sr(%rip),%r10 + add x8, x8, x10 + cbnz $dir, .Lschedule_am_decrypting + + // encrypting, output zeroth round key after transform + st1 {v0.2d}, [$out] // vmovdqu %xmm0, (%rdx) + b .Lschedule_go + +.Lschedule_am_decrypting: + // decrypting, output zeroth round key after shiftrows + ld1 {v1.2d}, [x8] // vmovdqa (%r8,%r10), %xmm1 + tbl v3.16b, {v3.16b}, v1.16b // vpshufb %xmm1, %xmm3, %xmm3 + st1 {v3.2d}, [$out] // vmovdqu %xmm3, (%rdx) + eor x8, x8, #0x30 // xor \$0x30, %r8 + +.Lschedule_go: + cmp $bits, #192 // cmp \$192, %esi + b.hi .Lschedule_256 + b.eq .Lschedule_192 + // 128: fall though + +## +## .schedule_128 +## +## 128-bit specific part of key schedule. +## +## This schedule is really simple, because all its parts +## are accomplished by the subroutines. +## +.Lschedule_128: + mov $inp, #10 // mov \$10, %esi + +.Loop_schedule_128: + sub $inp, $inp, #1 // dec %esi + bl _vpaes_schedule_round + cbz $inp, .Lschedule_mangle_last + bl _vpaes_schedule_mangle // write output + b .Loop_schedule_128 + +## +## .aes_schedule_192 +## +## 192-bit specific part of key schedule. +## +## The main body of this schedule is the same as the 128-bit +## schedule, but with more smearing. The long, high side is +## stored in %xmm7 as before, and the short, low side is in +## the high bits of %xmm6. +## +## This schedule is somewhat nastier, however, because each +## round produces 192 bits of key material, or 1.5 round keys. +## Therefore, on each cycle we do 2 rounds and produce 3 round +## keys. +## +.align 4 +.Lschedule_192: + sub $inp, $inp, #8 + ld1 {v0.16b}, [$inp] // vmovdqu 8(%rdi),%xmm0 # load key part 2 (very unaligned) + bl _vpaes_schedule_transform // input transform + mov v6.16b, v0.16b // vmovdqa %xmm0, %xmm6 # save short part + eor v4.16b, v4.16b, v4.16b // vpxor %xmm4, %xmm4, %xmm4 # clear 4 + ins v6.d[0], v4.d[0] // vmovhlps %xmm4, %xmm6, %xmm6 # clobber low side with zeros + mov $inp, #4 // mov \$4, %esi + +.Loop_schedule_192: + sub $inp, $inp, #1 // dec %esi + bl _vpaes_schedule_round + ext v0.16b, v6.16b, v0.16b, #8 // vpalignr \$8,%xmm6,%xmm0,%xmm0 + bl _vpaes_schedule_mangle // save key n + bl _vpaes_schedule_192_smear + bl _vpaes_schedule_mangle // save key n+1 + bl _vpaes_schedule_round + cbz $inp, .Lschedule_mangle_last + bl _vpaes_schedule_mangle // save key n+2 + bl _vpaes_schedule_192_smear + b .Loop_schedule_192 + +## +## .aes_schedule_256 +## +## 256-bit specific part of key schedule. +## +## The structure here is very similar to the 128-bit +## schedule, but with an additional "low side" in +## %xmm6. The low side's rounds are the same as the +## high side's, except no rcon and no rotation. +## +.align 4 +.Lschedule_256: + ld1 {v0.16b}, [$inp] // vmovdqu 16(%rdi),%xmm0 # load key part 2 (unaligned) + bl _vpaes_schedule_transform // input transform + mov $inp, #7 // mov \$7, %esi + +.Loop_schedule_256: + sub $inp, $inp, #1 // dec %esi + bl _vpaes_schedule_mangle // output low result + mov v6.16b, v0.16b // vmovdqa %xmm0, %xmm6 # save cur_lo in xmm6 + + // high round + bl _vpaes_schedule_round + cbz $inp, .Lschedule_mangle_last + bl _vpaes_schedule_mangle + + // low round. swap xmm7 and xmm6 + dup v0.4s, v0.s[3] // vpshufd \$0xFF, %xmm0, %xmm0 + movi v4.16b, #0 + mov v5.16b, v7.16b // vmovdqa %xmm7, %xmm5 + mov v7.16b, v6.16b // vmovdqa %xmm6, %xmm7 + bl _vpaes_schedule_low_round + mov v7.16b, v5.16b // vmovdqa %xmm5, %xmm7 + + b .Loop_schedule_256 + +## +## .aes_schedule_mangle_last +## +## Mangler for last round of key schedule +## Mangles %xmm0 +## when encrypting, outputs out(%xmm0) ^ 63 +## when decrypting, outputs unskew(%xmm0) +## +## Always called right before return... jumps to cleanup and exits +## +.align 4 +.Lschedule_mangle_last: + // schedule last round key from xmm0 + adr x11, .Lk_deskew // lea .Lk_deskew(%rip),%r11 # prepare to deskew + cbnz $dir, .Lschedule_mangle_last_dec + + // encrypting + ld1 {v1.2d}, [x8] // vmovdqa (%r8,%r10),%xmm1 + adr x11, .Lk_opt // lea .Lk_opt(%rip), %r11 # prepare to output transform + add $out, $out, #32 // add \$32, %rdx + tbl v0.16b, {v0.16b}, v1.16b // vpshufb %xmm1, %xmm0, %xmm0 # output permute + +.Lschedule_mangle_last_dec: + ld1 {v20.2d-v21.2d}, [x11] // reload constants + sub $out, $out, #16 // add \$-16, %rdx + eor v0.16b, v0.16b, v16.16b // vpxor .Lk_s63(%rip), %xmm0, %xmm0 + bl _vpaes_schedule_transform // output transform + st1 {v0.2d}, [$out] // vmovdqu %xmm0, (%rdx) # save last key + + // cleanup + eor v0.16b, v0.16b, v0.16b // vpxor %xmm0, %xmm0, %xmm0 + eor v1.16b, v1.16b, v1.16b // vpxor %xmm1, %xmm1, %xmm1 + eor v2.16b, v2.16b, v2.16b // vpxor %xmm2, %xmm2, %xmm2 + eor v3.16b, v3.16b, v3.16b // vpxor %xmm3, %xmm3, %xmm3 + eor v4.16b, v4.16b, v4.16b // vpxor %xmm4, %xmm4, %xmm4 + eor v5.16b, v5.16b, v5.16b // vpxor %xmm5, %xmm5, %xmm5 + eor v6.16b, v6.16b, v6.16b // vpxor %xmm6, %xmm6, %xmm6 + eor v7.16b, v7.16b, v7.16b // vpxor %xmm7, %xmm7, %xmm7 + ldp x29, x30, [sp],#16 + .inst 0xd50323bf // autiasp + ret +.size _vpaes_schedule_core,.-_vpaes_schedule_core + +## +## .aes_schedule_192_smear +## +## Smear the short, low side in the 192-bit key schedule. +## +## Inputs: +## %xmm7: high side, b a x y +## %xmm6: low side, d c 0 0 +## %xmm13: 0 +## +## Outputs: +## %xmm6: b+c+d b+c 0 0 +## %xmm0: b+c+d b+c b a +## +.type _vpaes_schedule_192_smear,%function +.align 4 +_vpaes_schedule_192_smear: + movi v1.16b, #0 + dup v0.4s, v7.s[3] + ins v1.s[3], v6.s[2] // vpshufd \$0x80, %xmm6, %xmm1 # d c 0 0 -> c 0 0 0 + ins v0.s[0], v7.s[2] // vpshufd \$0xFE, %xmm7, %xmm0 # b a _ _ -> b b b a + eor v6.16b, v6.16b, v1.16b // vpxor %xmm1, %xmm6, %xmm6 # -> c+d c 0 0 + eor v1.16b, v1.16b, v1.16b // vpxor %xmm1, %xmm1, %xmm1 + eor v6.16b, v6.16b, v0.16b // vpxor %xmm0, %xmm6, %xmm6 # -> b+c+d b+c b a + mov v0.16b, v6.16b // vmovdqa %xmm6, %xmm0 + ins v6.d[0], v1.d[0] // vmovhlps %xmm1, %xmm6, %xmm6 # clobber low side with zeros + ret +.size _vpaes_schedule_192_smear,.-_vpaes_schedule_192_smear + +## +## .aes_schedule_round +## +## Runs one main round of the key schedule on %xmm0, %xmm7 +## +## Specifically, runs subbytes on the high dword of %xmm0 +## then rotates it by one byte and xors into the low dword of +## %xmm7. +## +## Adds rcon from low byte of %xmm8, then rotates %xmm8 for +## next rcon. +## +## Smears the dwords of %xmm7 by xoring the low into the +## second low, result into third, result into highest. +## +## Returns results in %xmm7 = %xmm0. +## Clobbers %xmm1-%xmm4, %r11. +## +.type _vpaes_schedule_round,%function +.align 4 +_vpaes_schedule_round: + // extract rcon from xmm8 + movi v4.16b, #0 // vpxor %xmm4, %xmm4, %xmm4 + ext v1.16b, $rcon, v4.16b, #15 // vpalignr \$15, %xmm8, %xmm4, %xmm1 + ext $rcon, $rcon, $rcon, #15 // vpalignr \$15, %xmm8, %xmm8, %xmm8 + eor v7.16b, v7.16b, v1.16b // vpxor %xmm1, %xmm7, %xmm7 + + // rotate + dup v0.4s, v0.s[3] // vpshufd \$0xFF, %xmm0, %xmm0 + ext v0.16b, v0.16b, v0.16b, #1 // vpalignr \$1, %xmm0, %xmm0, %xmm0 + + // fall through... + + // low round: same as high round, but no rotation and no rcon. +_vpaes_schedule_low_round: + // smear xmm7 + ext v1.16b, v4.16b, v7.16b, #12 // vpslldq \$4, %xmm7, %xmm1 + eor v7.16b, v7.16b, v1.16b // vpxor %xmm1, %xmm7, %xmm7 + ext v4.16b, v4.16b, v7.16b, #8 // vpslldq \$8, %xmm7, %xmm4 + + // subbytes + and v1.16b, v0.16b, v17.16b // vpand %xmm9, %xmm0, %xmm1 # 0 = k + ushr v0.16b, v0.16b, #4 // vpsrlb \$4, %xmm0, %xmm0 # 1 = i + eor v7.16b, v7.16b, v4.16b // vpxor %xmm4, %xmm7, %xmm7 + tbl v2.16b, {$invhi}, v1.16b // vpshufb %xmm1, %xmm11, %xmm2 # 2 = a/k + eor v1.16b, v1.16b, v0.16b // vpxor %xmm0, %xmm1, %xmm1 # 0 = j + tbl v3.16b, {$invlo}, v0.16b // vpshufb %xmm0, %xmm10, %xmm3 # 3 = 1/i + eor v3.16b, v3.16b, v2.16b // vpxor %xmm2, %xmm3, %xmm3 # 3 = iak = 1/i + a/k + tbl v4.16b, {$invlo}, v1.16b // vpshufb %xmm1, %xmm10, %xmm4 # 4 = 1/j + eor v7.16b, v7.16b, v16.16b // vpxor .Lk_s63(%rip), %xmm7, %xmm7 + tbl v3.16b, {$invlo}, v3.16b // vpshufb %xmm3, %xmm10, %xmm3 # 2 = 1/iak + eor v4.16b, v4.16b, v2.16b // vpxor %xmm2, %xmm4, %xmm4 # 4 = jak = 1/j + a/k + tbl v2.16b, {$invlo}, v4.16b // vpshufb %xmm4, %xmm10, %xmm2 # 3 = 1/jak + eor v3.16b, v3.16b, v1.16b // vpxor %xmm1, %xmm3, %xmm3 # 2 = io + eor v2.16b, v2.16b, v0.16b // vpxor %xmm0, %xmm2, %xmm2 # 3 = jo + tbl v4.16b, {v23.16b}, v3.16b // vpshufb %xmm3, %xmm13, %xmm4 # 4 = sbou + tbl v1.16b, {v22.16b}, v2.16b // vpshufb %xmm2, %xmm12, %xmm1 # 0 = sb1t + eor v1.16b, v1.16b, v4.16b // vpxor %xmm4, %xmm1, %xmm1 # 0 = sbox output + + // add in smeared stuff + eor v0.16b, v1.16b, v7.16b // vpxor %xmm7, %xmm1, %xmm0 + eor v7.16b, v1.16b, v7.16b // vmovdqa %xmm0, %xmm7 + ret +.size _vpaes_schedule_round,.-_vpaes_schedule_round + +## +## .aes_schedule_transform +## +## Linear-transform %xmm0 according to tables at (%r11) +## +## Requires that %xmm9 = 0x0F0F... as in preheat +## Output in %xmm0 +## Clobbers %xmm1, %xmm2 +## +.type _vpaes_schedule_transform,%function +.align 4 +_vpaes_schedule_transform: + and v1.16b, v0.16b, v17.16b // vpand %xmm9, %xmm0, %xmm1 + ushr v0.16b, v0.16b, #4 // vpsrlb \$4, %xmm0, %xmm0 + // vmovdqa (%r11), %xmm2 # lo + tbl v2.16b, {$iptlo}, v1.16b // vpshufb %xmm1, %xmm2, %xmm2 + // vmovdqa 16(%r11), %xmm1 # hi + tbl v0.16b, {$ipthi}, v0.16b // vpshufb %xmm0, %xmm1, %xmm0 + eor v0.16b, v0.16b, v2.16b // vpxor %xmm2, %xmm0, %xmm0 + ret +.size _vpaes_schedule_transform,.-_vpaes_schedule_transform + +## +## .aes_schedule_mangle +## +## Mangle xmm0 from (basis-transformed) standard version +## to our version. +## +## On encrypt, +## xor with 0x63 +## multiply by circulant 0,1,1,1 +## apply shiftrows transform +## +## On decrypt, +## xor with 0x63 +## multiply by "inverse mixcolumns" circulant E,B,D,9 +## deskew +## apply shiftrows transform +## +## +## Writes out to (%rdx), and increments or decrements it +## Keeps track of round number mod 4 in %r8 +## Preserves xmm0 +## Clobbers xmm1-xmm5 +## +.type _vpaes_schedule_mangle,%function +.align 4 +_vpaes_schedule_mangle: + mov v4.16b, v0.16b // vmovdqa %xmm0, %xmm4 # save xmm0 for later + // vmovdqa .Lk_mc_forward(%rip),%xmm5 + cbnz $dir, .Lschedule_mangle_dec + + // encrypting + eor v4.16b, v0.16b, v16.16b // vpxor .Lk_s63(%rip), %xmm0, %xmm4 + add $out, $out, #16 // add \$16, %rdx + tbl v4.16b, {v4.16b}, v9.16b // vpshufb %xmm5, %xmm4, %xmm4 + tbl v1.16b, {v4.16b}, v9.16b // vpshufb %xmm5, %xmm4, %xmm1 + tbl v3.16b, {v1.16b}, v9.16b // vpshufb %xmm5, %xmm1, %xmm3 + eor v4.16b, v4.16b, v1.16b // vpxor %xmm1, %xmm4, %xmm4 + ld1 {v1.2d}, [x8] // vmovdqa (%r8,%r10), %xmm1 + eor v3.16b, v3.16b, v4.16b // vpxor %xmm4, %xmm3, %xmm3 + + b .Lschedule_mangle_both +.align 4 +.Lschedule_mangle_dec: + // inverse mix columns + // lea .Lk_dksd(%rip),%r11 + ushr v1.16b, v4.16b, #4 // vpsrlb \$4, %xmm4, %xmm1 # 1 = hi + and v4.16b, v4.16b, v17.16b // vpand %xmm9, %xmm4, %xmm4 # 4 = lo + + // vmovdqa 0x00(%r11), %xmm2 + tbl v2.16b, {v24.16b}, v4.16b // vpshufb %xmm4, %xmm2, %xmm2 + // vmovdqa 0x10(%r11), %xmm3 + tbl v3.16b, {v25.16b}, v1.16b // vpshufb %xmm1, %xmm3, %xmm3 + eor v3.16b, v3.16b, v2.16b // vpxor %xmm2, %xmm3, %xmm3 + tbl v3.16b, {v3.16b}, v9.16b // vpshufb %xmm5, %xmm3, %xmm3 + + // vmovdqa 0x20(%r11), %xmm2 + tbl v2.16b, {v26.16b}, v4.16b // vpshufb %xmm4, %xmm2, %xmm2 + eor v2.16b, v2.16b, v3.16b // vpxor %xmm3, %xmm2, %xmm2 + // vmovdqa 0x30(%r11), %xmm3 + tbl v3.16b, {v27.16b}, v1.16b // vpshufb %xmm1, %xmm3, %xmm3 + eor v3.16b, v3.16b, v2.16b // vpxor %xmm2, %xmm3, %xmm3 + tbl v3.16b, {v3.16b}, v9.16b // vpshufb %xmm5, %xmm3, %xmm3 + + // vmovdqa 0x40(%r11), %xmm2 + tbl v2.16b, {v28.16b}, v4.16b // vpshufb %xmm4, %xmm2, %xmm2 + eor v2.16b, v2.16b, v3.16b // vpxor %xmm3, %xmm2, %xmm2 + // vmovdqa 0x50(%r11), %xmm3 + tbl v3.16b, {v29.16b}, v1.16b // vpshufb %xmm1, %xmm3, %xmm3 + eor v3.16b, v3.16b, v2.16b // vpxor %xmm2, %xmm3, %xmm3 + + // vmovdqa 0x60(%r11), %xmm2 + tbl v2.16b, {v30.16b}, v4.16b // vpshufb %xmm4, %xmm2, %xmm2 + tbl v3.16b, {v3.16b}, v9.16b // vpshufb %xmm5, %xmm3, %xmm3 + // vmovdqa 0x70(%r11), %xmm4 + tbl v4.16b, {v31.16b}, v1.16b // vpshufb %xmm1, %xmm4, %xmm4 + ld1 {v1.2d}, [x8] // vmovdqa (%r8,%r10), %xmm1 + eor v2.16b, v2.16b, v3.16b // vpxor %xmm3, %xmm2, %xmm2 + eor v3.16b, v4.16b, v2.16b // vpxor %xmm2, %xmm4, %xmm3 + + sub $out, $out, #16 // add \$-16, %rdx + +.Lschedule_mangle_both: + tbl v3.16b, {v3.16b}, v1.16b // vpshufb %xmm1, %xmm3, %xmm3 + add x8, x8, #64-16 // add \$-16, %r8 + and x8, x8, #~(1<<6) // and \$0x30, %r8 + st1 {v3.2d}, [$out] // vmovdqu %xmm3, (%rdx) + ret +.size _vpaes_schedule_mangle,.-_vpaes_schedule_mangle + +.globl vpaes_set_encrypt_key +.type vpaes_set_encrypt_key,%function +.align 4 +vpaes_set_encrypt_key: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-16]! + add x29,sp,#0 + stp d8,d9,[sp,#-16]! // ABI spec says so + + lsr w9, $bits, #5 // shr \$5,%eax + add w9, w9, #5 // \$5,%eax + str w9, [$out,#240] // mov %eax,240(%rdx) # AES_KEY->rounds = nbits/32+5; + + mov $dir, #0 // mov \$0,%ecx + mov x8, #0x30 // mov \$0x30,%r8d + bl _vpaes_schedule_core + eor x0, x0, x0 + + ldp d8,d9,[sp],#16 + ldp x29,x30,[sp],#16 + .inst 0xd50323bf // autiasp + ret +.size vpaes_set_encrypt_key,.-vpaes_set_encrypt_key + +.globl vpaes_set_decrypt_key +.type vpaes_set_decrypt_key,%function +.align 4 +vpaes_set_decrypt_key: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-16]! + add x29,sp,#0 + stp d8,d9,[sp,#-16]! // ABI spec says so + + lsr w9, $bits, #5 // shr \$5,%eax + add w9, w9, #5 // \$5,%eax + str w9, [$out,#240] // mov %eax,240(%rdx) # AES_KEY->rounds = nbits/32+5; + lsl w9, w9, #4 // shl \$4,%eax + add $out, $out, #16 // lea 16(%rdx,%rax),%rdx + add $out, $out, x9 + + mov $dir, #1 // mov \$1,%ecx + lsr w8, $bits, #1 // shr \$1,%r8d + and x8, x8, #32 // and \$32,%r8d + eor x8, x8, #32 // xor \$32,%r8d # nbits==192?0:32 + bl _vpaes_schedule_core + + ldp d8,d9,[sp],#16 + ldp x29,x30,[sp],#16 + .inst 0xd50323bf // autiasp + ret +.size vpaes_set_decrypt_key,.-vpaes_set_decrypt_key +___ +} +{ +my ($inp,$out,$len,$key,$ivec,$dir) = map("x$_",(0..5)); + +$code.=<<___; +.globl vpaes_cbc_encrypt +.type vpaes_cbc_encrypt,%function +.align 4 +vpaes_cbc_encrypt: + cbz $len, .Lcbc_abort + cmp w5, #0 // check direction + b.eq vpaes_cbc_decrypt + + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-16]! + add x29,sp,#0 + + mov x17, $len // reassign + mov x2, $key // reassign + + ld1 {v0.16b}, [$ivec] // load ivec + bl _vpaes_encrypt_preheat + b .Lcbc_enc_loop + +.align 4 +.Lcbc_enc_loop: + ld1 {v7.16b}, [$inp],#16 // load input + eor v7.16b, v7.16b, v0.16b // xor with ivec + bl _vpaes_encrypt_core + st1 {v0.16b}, [$out],#16 // save output + subs x17, x17, #16 + b.hi .Lcbc_enc_loop + + st1 {v0.16b}, [$ivec] // write ivec + + ldp x29,x30,[sp],#16 + .inst 0xd50323bf // autiasp +.Lcbc_abort: + ret +.size vpaes_cbc_encrypt,.-vpaes_cbc_encrypt + +.type vpaes_cbc_decrypt,%function +.align 4 +vpaes_cbc_decrypt: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-16]! + add x29,sp,#0 + stp d8,d9,[sp,#-16]! // ABI spec says so + stp d10,d11,[sp,#-16]! + stp d12,d13,[sp,#-16]! + stp d14,d15,[sp,#-16]! + + mov x17, $len // reassign + mov x2, $key // reassign + ld1 {v6.16b}, [$ivec] // load ivec + bl _vpaes_decrypt_preheat + tst x17, #16 + b.eq .Lcbc_dec_loop2x + + ld1 {v7.16b}, [$inp], #16 // load input + bl _vpaes_decrypt_core + eor v0.16b, v0.16b, v6.16b // xor with ivec + orr v6.16b, v7.16b, v7.16b // next ivec value + st1 {v0.16b}, [$out], #16 + subs x17, x17, #16 + b.ls .Lcbc_dec_done + +.align 4 +.Lcbc_dec_loop2x: + ld1 {v14.16b,v15.16b}, [$inp], #32 + bl _vpaes_decrypt_2x + eor v0.16b, v0.16b, v6.16b // xor with ivec + eor v1.16b, v1.16b, v14.16b + orr v6.16b, v15.16b, v15.16b + st1 {v0.16b,v1.16b}, [$out], #32 + subs x17, x17, #32 + b.hi .Lcbc_dec_loop2x + +.Lcbc_dec_done: + st1 {v6.16b}, [$ivec] + + ldp d14,d15,[sp],#16 + ldp d12,d13,[sp],#16 + ldp d10,d11,[sp],#16 + ldp d8,d9,[sp],#16 + ldp x29,x30,[sp],#16 + .inst 0xd50323bf // autiasp + ret +.size vpaes_cbc_decrypt,.-vpaes_cbc_decrypt +___ +if (1) { +$code.=<<___; +.globl vpaes_ecb_encrypt +.type vpaes_ecb_encrypt,%function +.align 4 +vpaes_ecb_encrypt: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-16]! + add x29,sp,#0 + stp d8,d9,[sp,#-16]! // ABI spec says so + stp d10,d11,[sp,#-16]! + stp d12,d13,[sp,#-16]! + stp d14,d15,[sp,#-16]! + + mov x17, $len + mov x2, $key + bl _vpaes_encrypt_preheat + tst x17, #16 + b.eq .Lecb_enc_loop + + ld1 {v7.16b}, [$inp],#16 + bl _vpaes_encrypt_core + st1 {v0.16b}, [$out],#16 + subs x17, x17, #16 + b.ls .Lecb_enc_done + +.align 4 +.Lecb_enc_loop: + ld1 {v14.16b,v15.16b}, [$inp], #32 + bl _vpaes_encrypt_2x + st1 {v0.16b,v1.16b}, [$out], #32 + subs x17, x17, #32 + b.hi .Lecb_enc_loop + +.Lecb_enc_done: + ldp d14,d15,[sp],#16 + ldp d12,d13,[sp],#16 + ldp d10,d11,[sp],#16 + ldp d8,d9,[sp],#16 + ldp x29,x30,[sp],#16 + .inst 0xd50323bf // autiasp + ret +.size vpaes_ecb_encrypt,.-vpaes_ecb_encrypt + +.globl vpaes_ecb_decrypt +.type vpaes_ecb_decrypt,%function +.align 4 +vpaes_ecb_decrypt: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-16]! + add x29,sp,#0 + stp d8,d9,[sp,#-16]! // ABI spec says so + stp d10,d11,[sp,#-16]! + stp d12,d13,[sp,#-16]! + stp d14,d15,[sp,#-16]! + + mov x17, $len + mov x2, $key + bl _vpaes_decrypt_preheat + tst x17, #16 + b.eq .Lecb_dec_loop + + ld1 {v7.16b}, [$inp],#16 + bl _vpaes_encrypt_core + st1 {v0.16b}, [$out],#16 + subs x17, x17, #16 + b.ls .Lecb_dec_done + +.align 4 +.Lecb_dec_loop: + ld1 {v14.16b,v15.16b}, [$inp], #32 + bl _vpaes_decrypt_2x + st1 {v0.16b,v1.16b}, [$out], #32 + subs x17, x17, #32 + b.hi .Lecb_dec_loop + +.Lecb_dec_done: + ldp d14,d15,[sp],#16 + ldp d12,d13,[sp],#16 + ldp d10,d11,[sp],#16 + ldp d8,d9,[sp],#16 + ldp x29,x30,[sp],#16 + .inst 0xd50323bf // autiasp + ret +.size vpaes_ecb_decrypt,.-vpaes_ecb_decrypt +___ +} } +print $code; + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/vpaes-ppc.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/vpaes-ppc.pl new file mode 100644 index 000000000..3c771a7e9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/vpaes-ppc.pl @@ -0,0 +1,1594 @@ +#! /usr/bin/env perl +# Copyright 2013-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +###################################################################### +## Constant-time SSSE3 AES core implementation. +## version 0.1 +## +## By Mike Hamburg (Stanford University), 2009 +## Public domain. +## +## For details see http://shiftleft.org/papers/vector_aes/ and +## http://crypto.stanford.edu/vpaes/. + +# CBC encrypt/decrypt performance in cycles per byte processed with +# 128-bit key. +# +# aes-ppc.pl this +# PPC74x0/G4e 35.5/52.1/(23.8) 11.9(*)/15.4 +# PPC970/G5 37.9/55.0/(28.5) 22.2/28.5 +# POWER6 42.7/54.3/(28.2) 63.0/92.8(**) +# POWER7 32.3/42.9/(18.4) 18.5/23.3 +# +# (*) This is ~10% worse than reported in paper. The reason is +# twofold. This module doesn't make any assumption about +# key schedule (or data for that matter) alignment and handles +# it in-line. Secondly it, being transliterated from +# vpaes-x86_64.pl, relies on "nested inversion" better suited +# for Intel CPUs. +# (**) Inadequate POWER6 performance is due to astronomic AltiVec +# latency, 9 cycles per simple logical operation. + +$flavour = shift; + +if ($flavour =~ /64/) { + $SIZE_T =8; + $LRSAVE =2*$SIZE_T; + $STU ="stdu"; + $POP ="ld"; + $PUSH ="std"; + $UCMP ="cmpld"; +} elsif ($flavour =~ /32/) { + $SIZE_T =4; + $LRSAVE =$SIZE_T; + $STU ="stwu"; + $POP ="lwz"; + $PUSH ="stw"; + $UCMP ="cmplw"; +} else { die "nonsense $flavour"; } + +$sp="r1"; +$FRAME=6*$SIZE_T+13*16; # 13*16 is for v20-v31 offload + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or +die "can't locate ppc-xlate.pl"; + +open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!"; + +$code.=<<___; +.machine "any" + +.text + +.align 7 # totally strategic alignment +_vpaes_consts: +Lk_mc_forward: # mc_forward + .long 0x01020300, 0x05060704, 0x090a0b08, 0x0d0e0f0c ?inv + .long 0x05060704, 0x090a0b08, 0x0d0e0f0c, 0x01020300 ?inv + .long 0x090a0b08, 0x0d0e0f0c, 0x01020300, 0x05060704 ?inv + .long 0x0d0e0f0c, 0x01020300, 0x05060704, 0x090a0b08 ?inv +Lk_mc_backward: # mc_backward + .long 0x03000102, 0x07040506, 0x0b08090a, 0x0f0c0d0e ?inv + .long 0x0f0c0d0e, 0x03000102, 0x07040506, 0x0b08090a ?inv + .long 0x0b08090a, 0x0f0c0d0e, 0x03000102, 0x07040506 ?inv + .long 0x07040506, 0x0b08090a, 0x0f0c0d0e, 0x03000102 ?inv +Lk_sr: # sr + .long 0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f ?inv + .long 0x00050a0f, 0x04090e03, 0x080d0207, 0x0c01060b ?inv + .long 0x0009020b, 0x040d060f, 0x08010a03, 0x0c050e07 ?inv + .long 0x000d0a07, 0x04010e0b, 0x0805020f, 0x0c090603 ?inv + +## +## "Hot" constants +## +Lk_inv: # inv, inva + .long 0xf001080d, 0x0f06050e, 0x020c0b0a, 0x09030704 ?rev + .long 0xf0070b0f, 0x060a0401, 0x09080502, 0x0c0e0d03 ?rev +Lk_ipt: # input transform (lo, hi) + .long 0x00702a5a, 0x98e8b2c2, 0x08782252, 0x90e0baca ?rev + .long 0x004d7c31, 0x7d30014c, 0x81ccfdb0, 0xfcb180cd ?rev +Lk_sbo: # sbou, sbot + .long 0x00c7bd6f, 0x176dd2d0, 0x78a802c5, 0x7abfaa15 ?rev + .long 0x006abb5f, 0xa574e4cf, 0xfa352b41, 0xd1901e8e ?rev +Lk_sb1: # sb1u, sb1t + .long 0x0023e2fa, 0x15d41836, 0xefd92e0d, 0xc1ccf73b ?rev + .long 0x003e50cb, 0x8fe19bb1, 0x44f52a14, 0x6e7adfa5 ?rev +Lk_sb2: # sb2u, sb2t + .long 0x0029e10a, 0x4088eb69, 0x4a2382ab, 0xc863a1c2 ?rev + .long 0x0024710b, 0xc6937ae2, 0xcd2f98bc, 0x55e9b75e ?rev + +## +## Decryption stuff +## +Lk_dipt: # decryption input transform + .long 0x005f540b, 0x045b500f, 0x1a454e11, 0x1e414a15 ?rev + .long 0x00650560, 0xe683e386, 0x94f191f4, 0x72177712 ?rev +Lk_dsbo: # decryption sbox final output + .long 0x0040f97e, 0x53ea8713, 0x2d3e94d4, 0xb96daac7 ?rev + .long 0x001d4493, 0x0f56d712, 0x9c8ec5d8, 0x59814bca ?rev +Lk_dsb9: # decryption sbox output *9*u, *9*t + .long 0x00d6869a, 0x53031c85, 0xc94c994f, 0x501fd5ca ?rev + .long 0x0049d7ec, 0x89173bc0, 0x65a5fbb2, 0x9e2c5e72 ?rev +Lk_dsbd: # decryption sbox output *D*u, *D*t + .long 0x00a2b1e6, 0xdfcc577d, 0x39442a88, 0x139b6ef5 ?rev + .long 0x00cbc624, 0xf7fae23c, 0xd3efde15, 0x0d183129 ?rev +Lk_dsbb: # decryption sbox output *B*u, *B*t + .long 0x0042b496, 0x926422d0, 0x04d4f2b0, 0xf6462660 ?rev + .long 0x006759cd, 0xa69894c1, 0x6baa5532, 0x3e0cfff3 ?rev +Lk_dsbe: # decryption sbox output *E*u, *E*t + .long 0x00d0d426, 0x9692f246, 0xb0f6b464, 0x04604222 ?rev + .long 0x00c1aaff, 0xcda6550c, 0x323e5998, 0x6bf36794 ?rev + +## +## Key schedule constants +## +Lk_dksd: # decryption key schedule: invskew x*D + .long 0x0047e4a3, 0x5d1ab9fe, 0xf9be1d5a, 0xa4e34007 ?rev + .long 0x008336b5, 0xf477c241, 0x1e9d28ab, 0xea69dc5f ?rev +Lk_dksb: # decryption key schedule: invskew x*B + .long 0x00d55085, 0x1fca4f9a, 0x994cc91c, 0x8653d603 ?rev + .long 0x004afcb6, 0xa7ed5b11, 0xc882347e, 0x6f2593d9 ?rev +Lk_dkse: # decryption key schedule: invskew x*E + 0x63 + .long 0x00d6c91f, 0xca1c03d5, 0x86504f99, 0x4c9a8553 ?rev + .long 0xe87bdc4f, 0x059631a2, 0x8714b320, 0x6af95ecd ?rev +Lk_dks9: # decryption key schedule: invskew x*9 + .long 0x00a7d97e, 0xc86f11b6, 0xfc5b2582, 0x3493ed4a ?rev + .long 0x00331427, 0x62517645, 0xcefddae9, 0xac9fb88b ?rev + +Lk_rcon: # rcon + .long 0xb6ee9daf, 0xb991831f, 0x817d7c4d, 0x08982a70 ?asis +Lk_s63: + .long 0x5b5b5b5b, 0x5b5b5b5b, 0x5b5b5b5b, 0x5b5b5b5b ?asis + +Lk_opt: # output transform + .long 0x0060b6d6, 0x29499fff, 0x0868bede, 0x214197f7 ?rev + .long 0x00ecbc50, 0x51bded01, 0xe00c5cb0, 0xb15d0de1 ?rev +Lk_deskew: # deskew tables: inverts the sbox's "skew" + .long 0x00e3a447, 0x40a3e407, 0x1af9be5d, 0x5ab9fe1d ?rev + .long 0x0069ea83, 0xdcb5365f, 0x771e9df4, 0xabc24128 ?rev +.align 5 +Lconsts: + mflr r0 + bcl 20,31,\$+4 + mflr r12 #vvvvv "distance between . and _vpaes_consts + addi r12,r12,-0x308 + mtlr r0 + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 +.asciz "Vector Permutation AES for AltiVec, Mike Hamburg (Stanford University)" +.align 6 +___ + +my ($inptail,$inpperm,$outhead,$outperm,$outmask,$keyperm) = map("v$_",(26..31)); +{ +my ($inp,$out,$key) = map("r$_",(3..5)); + +my ($invlo,$invhi,$iptlo,$ipthi,$sbou,$sbot) = map("v$_",(10..15)); +my ($sb1u,$sb1t,$sb2u,$sb2t) = map("v$_",(16..19)); +my ($sb9u,$sb9t,$sbdu,$sbdt,$sbbu,$sbbt,$sbeu,$sbet)=map("v$_",(16..23)); + +$code.=<<___; +## +## _aes_preheat +## +## Fills register %r10 -> .aes_consts (so you can -fPIC) +## and %xmm9-%xmm15 as specified below. +## +.align 4 +_vpaes_encrypt_preheat: + mflr r8 + bl Lconsts + mtlr r8 + li r11, 0xc0 # Lk_inv + li r10, 0xd0 + li r9, 0xe0 # Lk_ipt + li r8, 0xf0 + vxor v7, v7, v7 # 0x00..00 + vspltisb v8,4 # 0x04..04 + vspltisb v9,0x0f # 0x0f..0f + lvx $invlo, r12, r11 + li r11, 0x100 + lvx $invhi, r12, r10 + li r10, 0x110 + lvx $iptlo, r12, r9 + li r9, 0x120 + lvx $ipthi, r12, r8 + li r8, 0x130 + lvx $sbou, r12, r11 + li r11, 0x140 + lvx $sbot, r12, r10 + li r10, 0x150 + lvx $sb1u, r12, r9 + lvx $sb1t, r12, r8 + lvx $sb2u, r12, r11 + lvx $sb2t, r12, r10 + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 + +## +## _aes_encrypt_core +## +## AES-encrypt %xmm0. +## +## Inputs: +## %xmm0 = input +## %xmm9-%xmm15 as in _vpaes_preheat +## (%rdx) = scheduled keys +## +## Output in %xmm0 +## Clobbers %xmm1-%xmm6, %r9, %r10, %r11, %rax +## +## +.align 5 +_vpaes_encrypt_core: + lwz r8, 240($key) # pull rounds + li r9, 16 + lvx v5, 0, $key # vmovdqu (%r9), %xmm5 # round0 key + li r11, 0x10 + lvx v6, r9, $key + addi r9, r9, 16 + ?vperm v5, v5, v6, $keyperm # align round key + addi r10, r11, 0x40 + vsrb v1, v0, v8 # vpsrlb \$4, %xmm0, %xmm0 + vperm v0, $iptlo, $iptlo, v0 # vpshufb %xmm1, %xmm2, %xmm1 + vperm v1, $ipthi, $ipthi, v1 # vpshufb %xmm0, %xmm3, %xmm2 + vxor v0, v0, v5 # vpxor %xmm5, %xmm1, %xmm0 + vxor v0, v0, v1 # vpxor %xmm2, %xmm0, %xmm0 + mtctr r8 + b Lenc_entry + +.align 4 +Lenc_loop: + # middle of middle round + vperm v4, $sb1t, v7, v2 # vpshufb %xmm2, %xmm13, %xmm4 # 4 = sb1u + lvx v1, r12, r11 # vmovdqa -0x40(%r11,%r10), %xmm1 # .Lk_mc_forward[] + addi r11, r11, 16 + vperm v0, $sb1u, v7, v3 # vpshufb %xmm3, %xmm12, %xmm0 # 0 = sb1t + vxor v4, v4, v5 # vpxor %xmm5, %xmm4, %xmm4 # 4 = sb1u + k + andi. r11, r11, 0x30 # and \$0x30, %r11 # ... mod 4 + vperm v5, $sb2t, v7, v2 # vpshufb %xmm2, %xmm15, %xmm5 # 4 = sb2u + vxor v0, v0, v4 # vpxor %xmm4, %xmm0, %xmm0 # 0 = A + vperm v2, $sb2u, v7, v3 # vpshufb %xmm3, %xmm14, %xmm2 # 2 = sb2t + lvx v4, r12, r10 # vmovdqa (%r11,%r10), %xmm4 # .Lk_mc_backward[] + addi r10, r11, 0x40 + vperm v3, v0, v7, v1 # vpshufb %xmm1, %xmm0, %xmm3 # 0 = B + vxor v2, v2, v5 # vpxor %xmm5, %xmm2, %xmm2 # 2 = 2A + vperm v0, v0, v7, v4 # vpshufb %xmm4, %xmm0, %xmm0 # 3 = D + vxor v3, v3, v2 # vpxor %xmm2, %xmm3, %xmm3 # 0 = 2A+B + vperm v4, v3, v7, v1 # vpshufb %xmm1, %xmm3, %xmm4 # 0 = 2B+C + vxor v0, v0, v3 # vpxor %xmm3, %xmm0, %xmm0 # 3 = 2A+B+D + vxor v0, v0, v4 # vpxor %xmm4, %xmm0, %xmm0 # 0 = 2A+3B+C+D + +Lenc_entry: + # top of round + vsrb v1, v0, v8 # vpsrlb \$4, %xmm0, %xmm0 # 1 = i + vperm v5, $invhi, $invhi, v0 # vpshufb %xmm1, %xmm11, %xmm5 # 2 = a/k + vxor v0, v0, v1 # vpxor %xmm0, %xmm1, %xmm1 # 0 = j + vperm v3, $invlo, $invlo, v1 # vpshufb %xmm0, %xmm10, %xmm3 # 3 = 1/i + vperm v4, $invlo, $invlo, v0 # vpshufb %xmm1, %xmm10, %xmm4 # 4 = 1/j + vand v0, v0, v9 + vxor v3, v3, v5 # vpxor %xmm5, %xmm3, %xmm3 # 3 = iak = 1/i + a/k + vxor v4, v4, v5 # vpxor %xmm5, %xmm4, %xmm4 # 4 = jak = 1/j + a/k + vperm v2, $invlo, v7, v3 # vpshufb %xmm3, %xmm10, %xmm2 # 2 = 1/iak + vmr v5, v6 + lvx v6, r9, $key # vmovdqu (%r9), %xmm5 + vperm v3, $invlo, v7, v4 # vpshufb %xmm4, %xmm10, %xmm3 # 3 = 1/jak + addi r9, r9, 16 + vxor v2, v2, v0 # vpxor %xmm1, %xmm2, %xmm2 # 2 = io + ?vperm v5, v5, v6, $keyperm # align round key + vxor v3, v3, v1 # vpxor %xmm0, %xmm3, %xmm3 # 3 = jo + bdnz Lenc_loop + + # middle of last round + addi r10, r11, 0x80 + # vmovdqa -0x60(%r10), %xmm4 # 3 : sbou .Lk_sbo + # vmovdqa -0x50(%r10), %xmm0 # 0 : sbot .Lk_sbo+16 + vperm v4, $sbou, v7, v2 # vpshufb %xmm2, %xmm4, %xmm4 # 4 = sbou + lvx v1, r12, r10 # vmovdqa 0x40(%r11,%r10), %xmm1 # .Lk_sr[] + vperm v0, $sbot, v7, v3 # vpshufb %xmm3, %xmm0, %xmm0 # 0 = sb1t + vxor v4, v4, v5 # vpxor %xmm5, %xmm4, %xmm4 # 4 = sb1u + k + vxor v0, v0, v4 # vpxor %xmm4, %xmm0, %xmm0 # 0 = A + vperm v0, v0, v7, v1 # vpshufb %xmm1, %xmm0, %xmm0 + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 + +.globl .vpaes_encrypt +.align 5 +.vpaes_encrypt: + $STU $sp,-$FRAME($sp) + li r10,`15+6*$SIZE_T` + li r11,`31+6*$SIZE_T` + mflr r6 + mfspr r7, 256 # save vrsave + stvx v20,r10,$sp + addi r10,r10,32 + stvx v21,r11,$sp + addi r11,r11,32 + stvx v22,r10,$sp + addi r10,r10,32 + stvx v23,r11,$sp + addi r11,r11,32 + stvx v24,r10,$sp + addi r10,r10,32 + stvx v25,r11,$sp + addi r11,r11,32 + stvx v26,r10,$sp + addi r10,r10,32 + stvx v27,r11,$sp + addi r11,r11,32 + stvx v28,r10,$sp + addi r10,r10,32 + stvx v29,r11,$sp + addi r11,r11,32 + stvx v30,r10,$sp + stvx v31,r11,$sp + stw r7,`$FRAME-4`($sp) # save vrsave + li r0, -1 + $PUSH r6,`$FRAME+$LRSAVE`($sp) + mtspr 256, r0 # preserve all AltiVec registers + + bl _vpaes_encrypt_preheat + + ?lvsl $inpperm, 0, $inp # prepare for unaligned access + lvx v0, 0, $inp + addi $inp, $inp, 15 # 15 is not a typo + ?lvsr $outperm, 0, $out + ?lvsl $keyperm, 0, $key # prepare for unaligned access + lvx $inptail, 0, $inp # redundant in aligned case + ?vperm v0, v0, $inptail, $inpperm + + bl _vpaes_encrypt_core + + andi. r8, $out, 15 + li r9, 16 + beq Lenc_out_aligned + + vperm v0, v0, v0, $outperm # rotate right/left + mtctr r9 +Lenc_out_unaligned: + stvebx v0, 0, $out + addi $out, $out, 1 + bdnz Lenc_out_unaligned + b Lenc_done + +.align 4 +Lenc_out_aligned: + stvx v0, 0, $out +Lenc_done: + + li r10,`15+6*$SIZE_T` + li r11,`31+6*$SIZE_T` + mtlr r6 + mtspr 256, r7 # restore vrsave + lvx v20,r10,$sp + addi r10,r10,32 + lvx v21,r11,$sp + addi r11,r11,32 + lvx v22,r10,$sp + addi r10,r10,32 + lvx v23,r11,$sp + addi r11,r11,32 + lvx v24,r10,$sp + addi r10,r10,32 + lvx v25,r11,$sp + addi r11,r11,32 + lvx v26,r10,$sp + addi r10,r10,32 + lvx v27,r11,$sp + addi r11,r11,32 + lvx v28,r10,$sp + addi r10,r10,32 + lvx v29,r11,$sp + addi r11,r11,32 + lvx v30,r10,$sp + lvx v31,r11,$sp + addi $sp,$sp,$FRAME + blr + .long 0 + .byte 0,12,0x04,1,0x80,0,3,0 + .long 0 +.size .vpaes_encrypt,.-.vpaes_encrypt + +.align 4 +_vpaes_decrypt_preheat: + mflr r8 + bl Lconsts + mtlr r8 + li r11, 0xc0 # Lk_inv + li r10, 0xd0 + li r9, 0x160 # Ldipt + li r8, 0x170 + vxor v7, v7, v7 # 0x00..00 + vspltisb v8,4 # 0x04..04 + vspltisb v9,0x0f # 0x0f..0f + lvx $invlo, r12, r11 + li r11, 0x180 + lvx $invhi, r12, r10 + li r10, 0x190 + lvx $iptlo, r12, r9 + li r9, 0x1a0 + lvx $ipthi, r12, r8 + li r8, 0x1b0 + lvx $sbou, r12, r11 + li r11, 0x1c0 + lvx $sbot, r12, r10 + li r10, 0x1d0 + lvx $sb9u, r12, r9 + li r9, 0x1e0 + lvx $sb9t, r12, r8 + li r8, 0x1f0 + lvx $sbdu, r12, r11 + li r11, 0x200 + lvx $sbdt, r12, r10 + li r10, 0x210 + lvx $sbbu, r12, r9 + lvx $sbbt, r12, r8 + lvx $sbeu, r12, r11 + lvx $sbet, r12, r10 + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 + +## +## Decryption core +## +## Same API as encryption core. +## +.align 4 +_vpaes_decrypt_core: + lwz r8, 240($key) # pull rounds + li r9, 16 + lvx v5, 0, $key # vmovdqu (%r9), %xmm4 # round0 key + li r11, 0x30 + lvx v6, r9, $key + addi r9, r9, 16 + ?vperm v5, v5, v6, $keyperm # align round key + vsrb v1, v0, v8 # vpsrlb \$4, %xmm0, %xmm0 + vperm v0, $iptlo, $iptlo, v0 # vpshufb %xmm1, %xmm2, %xmm2 + vperm v1, $ipthi, $ipthi, v1 # vpshufb %xmm0, %xmm1, %xmm0 + vxor v0, v0, v5 # vpxor %xmm4, %xmm2, %xmm2 + vxor v0, v0, v1 # vpxor %xmm2, %xmm0, %xmm0 + mtctr r8 + b Ldec_entry + +.align 4 +Ldec_loop: +# +# Inverse mix columns +# + lvx v0, r12, r11 # v5 and v0 are flipped + # vmovdqa -0x20(%r10),%xmm4 # 4 : sb9u + # vmovdqa -0x10(%r10),%xmm1 # 0 : sb9t + vperm v4, $sb9u, v7, v2 # vpshufb %xmm2, %xmm4, %xmm4 # 4 = sb9u + subi r11, r11, 16 + vperm v1, $sb9t, v7, v3 # vpshufb %xmm3, %xmm1, %xmm1 # 0 = sb9t + andi. r11, r11, 0x30 + vxor v5, v5, v4 # vpxor %xmm4, %xmm0, %xmm0 + # vmovdqa 0x00(%r10),%xmm4 # 4 : sbdu + vxor v5, v5, v1 # vpxor %xmm1, %xmm0, %xmm0 # 0 = ch + # vmovdqa 0x10(%r10),%xmm1 # 0 : sbdt + + vperm v4, $sbdu, v7, v2 # vpshufb %xmm2, %xmm4, %xmm4 # 4 = sbdu + vperm v5, v5, v7, v0 # vpshufb %xmm5, %xmm0, %xmm0 # MC ch + vperm v1, $sbdt, v7, v3 # vpshufb %xmm3, %xmm1, %xmm1 # 0 = sbdt + vxor v5, v5, v4 # vpxor %xmm4, %xmm0, %xmm0 # 4 = ch + # vmovdqa 0x20(%r10), %xmm4 # 4 : sbbu + vxor v5, v5, v1 # vpxor %xmm1, %xmm0, %xmm0 # 0 = ch + # vmovdqa 0x30(%r10), %xmm1 # 0 : sbbt + + vperm v4, $sbbu, v7, v2 # vpshufb %xmm2, %xmm4, %xmm4 # 4 = sbbu + vperm v5, v5, v7, v0 # vpshufb %xmm5, %xmm0, %xmm0 # MC ch + vperm v1, $sbbt, v7, v3 # vpshufb %xmm3, %xmm1, %xmm1 # 0 = sbbt + vxor v5, v5, v4 # vpxor %xmm4, %xmm0, %xmm0 # 4 = ch + # vmovdqa 0x40(%r10), %xmm4 # 4 : sbeu + vxor v5, v5, v1 # vpxor %xmm1, %xmm0, %xmm0 # 0 = ch + # vmovdqa 0x50(%r10), %xmm1 # 0 : sbet + + vperm v4, $sbeu, v7, v2 # vpshufb %xmm2, %xmm4, %xmm4 # 4 = sbeu + vperm v5, v5, v7, v0 # vpshufb %xmm5, %xmm0, %xmm0 # MC ch + vperm v1, $sbet, v7, v3 # vpshufb %xmm3, %xmm1, %xmm1 # 0 = sbet + vxor v0, v5, v4 # vpxor %xmm4, %xmm0, %xmm0 # 4 = ch + vxor v0, v0, v1 # vpxor %xmm1, %xmm0, %xmm0 # 0 = ch + +Ldec_entry: + # top of round + vsrb v1, v0, v8 # vpsrlb \$4, %xmm0, %xmm0 # 1 = i + vperm v2, $invhi, $invhi, v0 # vpshufb %xmm1, %xmm11, %xmm2 # 2 = a/k + vxor v0, v0, v1 # vpxor %xmm0, %xmm1, %xmm1 # 0 = j + vperm v3, $invlo, $invlo, v1 # vpshufb %xmm0, %xmm10, %xmm3 # 3 = 1/i + vperm v4, $invlo, $invlo, v0 # vpshufb %xmm1, %xmm10, %xmm4 # 4 = 1/j + vand v0, v0, v9 + vxor v3, v3, v2 # vpxor %xmm2, %xmm3, %xmm3 # 3 = iak = 1/i + a/k + vxor v4, v4, v2 # vpxor %xmm2, %xmm4, %xmm4 # 4 = jak = 1/j + a/k + vperm v2, $invlo, v7, v3 # vpshufb %xmm3, %xmm10, %xmm2 # 2 = 1/iak + vmr v5, v6 + lvx v6, r9, $key # vmovdqu (%r9), %xmm0 + vperm v3, $invlo, v7, v4 # vpshufb %xmm4, %xmm10, %xmm3 # 3 = 1/jak + addi r9, r9, 16 + vxor v2, v2, v0 # vpxor %xmm1, %xmm2, %xmm2 # 2 = io + ?vperm v5, v5, v6, $keyperm # align round key + vxor v3, v3, v1 # vpxor %xmm0, %xmm3, %xmm3 # 3 = jo + bdnz Ldec_loop + + # middle of last round + addi r10, r11, 0x80 + # vmovdqa 0x60(%r10), %xmm4 # 3 : sbou + vperm v4, $sbou, v7, v2 # vpshufb %xmm2, %xmm4, %xmm4 # 4 = sbou + # vmovdqa 0x70(%r10), %xmm1 # 0 : sbot + lvx v2, r12, r10 # vmovdqa -0x160(%r11), %xmm2 # .Lk_sr-.Lk_dsbd=-0x160 + vperm v1, $sbot, v7, v3 # vpshufb %xmm3, %xmm1, %xmm1 # 0 = sb1t + vxor v4, v4, v5 # vpxor %xmm0, %xmm4, %xmm4 # 4 = sb1u + k + vxor v0, v1, v4 # vpxor %xmm4, %xmm1, %xmm0 # 0 = A + vperm v0, v0, v7, v2 # vpshufb %xmm2, %xmm0, %xmm0 + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 + +.globl .vpaes_decrypt +.align 5 +.vpaes_decrypt: + $STU $sp,-$FRAME($sp) + li r10,`15+6*$SIZE_T` + li r11,`31+6*$SIZE_T` + mflr r6 + mfspr r7, 256 # save vrsave + stvx v20,r10,$sp + addi r10,r10,32 + stvx v21,r11,$sp + addi r11,r11,32 + stvx v22,r10,$sp + addi r10,r10,32 + stvx v23,r11,$sp + addi r11,r11,32 + stvx v24,r10,$sp + addi r10,r10,32 + stvx v25,r11,$sp + addi r11,r11,32 + stvx v26,r10,$sp + addi r10,r10,32 + stvx v27,r11,$sp + addi r11,r11,32 + stvx v28,r10,$sp + addi r10,r10,32 + stvx v29,r11,$sp + addi r11,r11,32 + stvx v30,r10,$sp + stvx v31,r11,$sp + stw r7,`$FRAME-4`($sp) # save vrsave + li r0, -1 + $PUSH r6,`$FRAME+$LRSAVE`($sp) + mtspr 256, r0 # preserve all AltiVec registers + + bl _vpaes_decrypt_preheat + + ?lvsl $inpperm, 0, $inp # prepare for unaligned access + lvx v0, 0, $inp + addi $inp, $inp, 15 # 15 is not a typo + ?lvsr $outperm, 0, $out + ?lvsl $keyperm, 0, $key + lvx $inptail, 0, $inp # redundant in aligned case + ?vperm v0, v0, $inptail, $inpperm + + bl _vpaes_decrypt_core + + andi. r8, $out, 15 + li r9, 16 + beq Ldec_out_aligned + + vperm v0, v0, v0, $outperm # rotate right/left + mtctr r9 +Ldec_out_unaligned: + stvebx v0, 0, $out + addi $out, $out, 1 + bdnz Ldec_out_unaligned + b Ldec_done + +.align 4 +Ldec_out_aligned: + stvx v0, 0, $out +Ldec_done: + + li r10,`15+6*$SIZE_T` + li r11,`31+6*$SIZE_T` + mtlr r6 + mtspr 256, r7 # restore vrsave + lvx v20,r10,$sp + addi r10,r10,32 + lvx v21,r11,$sp + addi r11,r11,32 + lvx v22,r10,$sp + addi r10,r10,32 + lvx v23,r11,$sp + addi r11,r11,32 + lvx v24,r10,$sp + addi r10,r10,32 + lvx v25,r11,$sp + addi r11,r11,32 + lvx v26,r10,$sp + addi r10,r10,32 + lvx v27,r11,$sp + addi r11,r11,32 + lvx v28,r10,$sp + addi r10,r10,32 + lvx v29,r11,$sp + addi r11,r11,32 + lvx v30,r10,$sp + lvx v31,r11,$sp + addi $sp,$sp,$FRAME + blr + .long 0 + .byte 0,12,0x04,1,0x80,0,3,0 + .long 0 +.size .vpaes_decrypt,.-.vpaes_decrypt + +.globl .vpaes_cbc_encrypt +.align 5 +.vpaes_cbc_encrypt: + ${UCMP}i r5,16 + bltlr- + + $STU $sp,-`($FRAME+2*$SIZE_T)`($sp) + mflr r0 + li r10,`15+6*$SIZE_T` + li r11,`31+6*$SIZE_T` + mfspr r12, 256 + stvx v20,r10,$sp + addi r10,r10,32 + stvx v21,r11,$sp + addi r11,r11,32 + stvx v22,r10,$sp + addi r10,r10,32 + stvx v23,r11,$sp + addi r11,r11,32 + stvx v24,r10,$sp + addi r10,r10,32 + stvx v25,r11,$sp + addi r11,r11,32 + stvx v26,r10,$sp + addi r10,r10,32 + stvx v27,r11,$sp + addi r11,r11,32 + stvx v28,r10,$sp + addi r10,r10,32 + stvx v29,r11,$sp + addi r11,r11,32 + stvx v30,r10,$sp + stvx v31,r11,$sp + stw r12,`$FRAME-4`($sp) # save vrsave + $PUSH r30,`$FRAME+$SIZE_T*0`($sp) + $PUSH r31,`$FRAME+$SIZE_T*1`($sp) + li r9, -16 + $PUSH r0, `$FRAME+$SIZE_T*2+$LRSAVE`($sp) + + and r30, r5, r9 # copy length&-16 + andi. r9, $out, 15 # is $out aligned? + mr r5, r6 # copy pointer to key + mr r31, r7 # copy pointer to iv + li r6, -1 + mcrf cr1, cr0 # put aside $out alignment flag + mr r7, r12 # copy vrsave + mtspr 256, r6 # preserve all AltiVec registers + + lvx v24, 0, r31 # load [potentially unaligned] iv + li r9, 15 + ?lvsl $inpperm, 0, r31 + lvx v25, r9, r31 + ?vperm v24, v24, v25, $inpperm + + cmpwi r8, 0 # test direction + neg r8, $inp # prepare for unaligned access + vxor v7, v7, v7 + ?lvsl $keyperm, 0, $key + ?lvsr $outperm, 0, $out + ?lvsr $inpperm, 0, r8 # -$inp + vnor $outmask, v7, v7 # 0xff..ff + lvx $inptail, 0, $inp + ?vperm $outmask, v7, $outmask, $outperm + addi $inp, $inp, 15 # 15 is not a typo + + beq Lcbc_decrypt + + bl _vpaes_encrypt_preheat + li r0, 16 + + beq cr1, Lcbc_enc_loop # $out is aligned + + vmr v0, $inptail + lvx $inptail, 0, $inp + addi $inp, $inp, 16 + ?vperm v0, v0, $inptail, $inpperm + vxor v0, v0, v24 # ^= iv + + bl _vpaes_encrypt_core + + andi. r8, $out, 15 + vmr v24, v0 # put aside iv + sub r9, $out, r8 + vperm $outhead, v0, v0, $outperm # rotate right/left + +Lcbc_enc_head: + stvebx $outhead, r8, r9 + cmpwi r8, 15 + addi r8, r8, 1 + bne Lcbc_enc_head + + sub. r30, r30, r0 # len -= 16 + addi $out, $out, 16 + beq Lcbc_unaligned_done + +Lcbc_enc_loop: + vmr v0, $inptail + lvx $inptail, 0, $inp + addi $inp, $inp, 16 + ?vperm v0, v0, $inptail, $inpperm + vxor v0, v0, v24 # ^= iv + + bl _vpaes_encrypt_core + + vmr v24, v0 # put aside iv + sub. r30, r30, r0 # len -= 16 + vperm v0, v0, v0, $outperm # rotate right/left + vsel v1, $outhead, v0, $outmask + vmr $outhead, v0 + stvx v1, 0, $out + addi $out, $out, 16 + bne Lcbc_enc_loop + + b Lcbc_done + +.align 5 +Lcbc_decrypt: + bl _vpaes_decrypt_preheat + li r0, 16 + + beq cr1, Lcbc_dec_loop # $out is aligned + + vmr v0, $inptail + lvx $inptail, 0, $inp + addi $inp, $inp, 16 + ?vperm v0, v0, $inptail, $inpperm + vmr v25, v0 # put aside input + + bl _vpaes_decrypt_core + + andi. r8, $out, 15 + vxor v0, v0, v24 # ^= iv + vmr v24, v25 + sub r9, $out, r8 + vperm $outhead, v0, v0, $outperm # rotate right/left + +Lcbc_dec_head: + stvebx $outhead, r8, r9 + cmpwi r8, 15 + addi r8, r8, 1 + bne Lcbc_dec_head + + sub. r30, r30, r0 # len -= 16 + addi $out, $out, 16 + beq Lcbc_unaligned_done + +Lcbc_dec_loop: + vmr v0, $inptail + lvx $inptail, 0, $inp + addi $inp, $inp, 16 + ?vperm v0, v0, $inptail, $inpperm + vmr v25, v0 # put aside input + + bl _vpaes_decrypt_core + + vxor v0, v0, v24 # ^= iv + vmr v24, v25 + sub. r30, r30, r0 # len -= 16 + vperm v0, v0, v0, $outperm # rotate right/left + vsel v1, $outhead, v0, $outmask + vmr $outhead, v0 + stvx v1, 0, $out + addi $out, $out, 16 + bne Lcbc_dec_loop + +Lcbc_done: + beq cr1, Lcbc_write_iv # $out is aligned + +Lcbc_unaligned_done: + andi. r8, $out, 15 + sub $out, $out, r8 + li r9, 0 +Lcbc_tail: + stvebx $outhead, r9, $out + addi r9, r9, 1 + cmpw r9, r8 + bne Lcbc_tail + +Lcbc_write_iv: + neg r8, r31 # write [potentially unaligned] iv + li r10, 4 + ?lvsl $outperm, 0, r8 + li r11, 8 + li r12, 12 + vperm v24, v24, v24, $outperm # rotate right/left + stvewx v24, 0, r31 # ivp is at least 32-bit aligned + stvewx v24, r10, r31 + stvewx v24, r11, r31 + stvewx v24, r12, r31 + + mtspr 256, r7 # restore vrsave + li r10,`15+6*$SIZE_T` + li r11,`31+6*$SIZE_T` + lvx v20,r10,$sp + addi r10,r10,32 + lvx v21,r11,$sp + addi r11,r11,32 + lvx v22,r10,$sp + addi r10,r10,32 + lvx v23,r11,$sp + addi r11,r11,32 + lvx v24,r10,$sp + addi r10,r10,32 + lvx v25,r11,$sp + addi r11,r11,32 + lvx v26,r10,$sp + addi r10,r10,32 + lvx v27,r11,$sp + addi r11,r11,32 + lvx v28,r10,$sp + addi r10,r10,32 + lvx v29,r11,$sp + addi r11,r11,32 + lvx v30,r10,$sp + lvx v31,r11,$sp +Lcbc_abort: + $POP r0, `$FRAME+$SIZE_T*2+$LRSAVE`($sp) + $POP r30,`$FRAME+$SIZE_T*0`($sp) + $POP r31,`$FRAME+$SIZE_T*1`($sp) + mtlr r0 + addi $sp,$sp,`$FRAME+$SIZE_T*2` + blr + .long 0 + .byte 0,12,0x04,1,0x80,2,6,0 + .long 0 +.size .vpaes_cbc_encrypt,.-.vpaes_cbc_encrypt +___ +} +{ +my ($inp,$bits,$out)=map("r$_",(3..5)); +my $dir="cr1"; +my ($invlo,$invhi,$iptlo,$ipthi,$rcon) = map("v$_",(10..13,24)); + +$code.=<<___; +######################################################## +## ## +## AES key schedule ## +## ## +######################################################## +.align 4 +_vpaes_key_preheat: + mflr r8 + bl Lconsts + mtlr r8 + li r11, 0xc0 # Lk_inv + li r10, 0xd0 + li r9, 0xe0 # L_ipt + li r8, 0xf0 + + vspltisb v8,4 # 0x04..04 + vxor v9,v9,v9 # 0x00..00 + lvx $invlo, r12, r11 # Lk_inv + li r11, 0x120 + lvx $invhi, r12, r10 + li r10, 0x130 + lvx $iptlo, r12, r9 # Lk_ipt + li r9, 0x220 + lvx $ipthi, r12, r8 + li r8, 0x230 + + lvx v14, r12, r11 # Lk_sb1 + li r11, 0x240 + lvx v15, r12, r10 + li r10, 0x250 + + lvx v16, r12, r9 # Lk_dksd + li r9, 0x260 + lvx v17, r12, r8 + li r8, 0x270 + lvx v18, r12, r11 # Lk_dksb + li r11, 0x280 + lvx v19, r12, r10 + li r10, 0x290 + lvx v20, r12, r9 # Lk_dkse + li r9, 0x2a0 + lvx v21, r12, r8 + li r8, 0x2b0 + lvx v22, r12, r11 # Lk_dks9 + lvx v23, r12, r10 + + lvx v24, r12, r9 # Lk_rcon + lvx v25, 0, r12 # Lk_mc_forward[0] + lvx v26, r12, r8 # Lks63 + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 + +.align 4 +_vpaes_schedule_core: + mflr r7 + + bl _vpaes_key_preheat # load the tables + + #lvx v0, 0, $inp # vmovdqu (%rdi), %xmm0 # load key (unaligned) + neg r8, $inp # prepare for unaligned access + lvx v0, 0, $inp + addi $inp, $inp, 15 # 15 is not typo + ?lvsr $inpperm, 0, r8 # -$inp + lvx v6, 0, $inp # v6 serves as inptail + addi $inp, $inp, 8 + ?vperm v0, v0, v6, $inpperm + + # input transform + vmr v3, v0 # vmovdqa %xmm0, %xmm3 + bl _vpaes_schedule_transform + vmr v7, v0 # vmovdqa %xmm0, %xmm7 + + bne $dir, Lschedule_am_decrypting + + # encrypting, output zeroth round key after transform + li r8, 0x30 # mov \$0x30,%r8d + li r9, 4 + li r10, 8 + li r11, 12 + + ?lvsr $outperm, 0, $out # prepare for unaligned access + vnor $outmask, v9, v9 # 0xff..ff + ?vperm $outmask, v9, $outmask, $outperm + + #stvx v0, 0, $out # vmovdqu %xmm0, (%rdx) + vperm $outhead, v0, v0, $outperm # rotate right/left + stvewx $outhead, 0, $out # some are superfluous + stvewx $outhead, r9, $out + stvewx $outhead, r10, $out + addi r10, r12, 0x80 # lea .Lk_sr(%rip),%r10 + stvewx $outhead, r11, $out + b Lschedule_go + +Lschedule_am_decrypting: + srwi r8, $bits, 1 # shr \$1,%r8d + andi. r8, r8, 32 # and \$32,%r8d + xori r8, r8, 32 # xor \$32,%r8d # nbits==192?0:32 + addi r10, r12, 0x80 # lea .Lk_sr(%rip),%r10 + # decrypting, output zeroth round key after shiftrows + lvx v1, r8, r10 # vmovdqa (%r8,%r10), %xmm1 + li r9, 4 + li r10, 8 + li r11, 12 + vperm v4, v3, v3, v1 # vpshufb %xmm1, %xmm3, %xmm3 + + neg r0, $out # prepare for unaligned access + ?lvsl $outperm, 0, r0 + vnor $outmask, v9, v9 # 0xff..ff + ?vperm $outmask, $outmask, v9, $outperm + + #stvx v4, 0, $out # vmovdqu %xmm3, (%rdx) + vperm $outhead, v4, v4, $outperm # rotate right/left + stvewx $outhead, 0, $out # some are superfluous + stvewx $outhead, r9, $out + stvewx $outhead, r10, $out + addi r10, r12, 0x80 # lea .Lk_sr(%rip),%r10 + stvewx $outhead, r11, $out + addi $out, $out, 15 # 15 is not typo + xori r8, r8, 0x30 # xor \$0x30, %r8 + +Lschedule_go: + cmplwi $bits, 192 # cmp \$192, %esi + bgt Lschedule_256 + beq Lschedule_192 + # 128: fall though + +## +## .schedule_128 +## +## 128-bit specific part of key schedule. +## +## This schedule is really simple, because all its parts +## are accomplished by the subroutines. +## +Lschedule_128: + li r0, 10 # mov \$10, %esi + mtctr r0 + +Loop_schedule_128: + bl _vpaes_schedule_round + bdz Lschedule_mangle_last # dec %esi + bl _vpaes_schedule_mangle # write output + b Loop_schedule_128 + +## +## .aes_schedule_192 +## +## 192-bit specific part of key schedule. +## +## The main body of this schedule is the same as the 128-bit +## schedule, but with more smearing. The long, high side is +## stored in %xmm7 as before, and the short, low side is in +## the high bits of %xmm6. +## +## This schedule is somewhat nastier, however, because each +## round produces 192 bits of key material, or 1.5 round keys. +## Therefore, on each cycle we do 2 rounds and produce 3 round +## keys. +## +.align 4 +Lschedule_192: + li r0, 4 # mov \$4, %esi + lvx v0, 0, $inp + ?vperm v0, v6, v0, $inpperm + ?vsldoi v0, v3, v0, 8 # vmovdqu 8(%rdi),%xmm0 # load key part 2 (very unaligned) + bl _vpaes_schedule_transform # input transform + ?vsldoi v6, v0, v9, 8 + ?vsldoi v6, v9, v6, 8 # clobber "low" side with zeros + mtctr r0 + +Loop_schedule_192: + bl _vpaes_schedule_round + ?vsldoi v0, v6, v0, 8 # vpalignr \$8,%xmm6,%xmm0,%xmm0 + bl _vpaes_schedule_mangle # save key n + bl _vpaes_schedule_192_smear + bl _vpaes_schedule_mangle # save key n+1 + bl _vpaes_schedule_round + bdz Lschedule_mangle_last # dec %esi + bl _vpaes_schedule_mangle # save key n+2 + bl _vpaes_schedule_192_smear + b Loop_schedule_192 + +## +## .aes_schedule_256 +## +## 256-bit specific part of key schedule. +## +## The structure here is very similar to the 128-bit +## schedule, but with an additional "low side" in +## %xmm6. The low side's rounds are the same as the +## high side's, except no rcon and no rotation. +## +.align 4 +Lschedule_256: + li r0, 7 # mov \$7, %esi + addi $inp, $inp, 8 + lvx v0, 0, $inp # vmovdqu 16(%rdi),%xmm0 # load key part 2 (unaligned) + ?vperm v0, v6, v0, $inpperm + bl _vpaes_schedule_transform # input transform + mtctr r0 + +Loop_schedule_256: + bl _vpaes_schedule_mangle # output low result + vmr v6, v0 # vmovdqa %xmm0, %xmm6 # save cur_lo in xmm6 + + # high round + bl _vpaes_schedule_round + bdz Lschedule_mangle_last # dec %esi + bl _vpaes_schedule_mangle + + # low round. swap xmm7 and xmm6 + ?vspltw v0, v0, 3 # vpshufd \$0xFF, %xmm0, %xmm0 + vmr v5, v7 # vmovdqa %xmm7, %xmm5 + vmr v7, v6 # vmovdqa %xmm6, %xmm7 + bl _vpaes_schedule_low_round + vmr v7, v5 # vmovdqa %xmm5, %xmm7 + + b Loop_schedule_256 +## +## .aes_schedule_mangle_last +## +## Mangler for last round of key schedule +## Mangles %xmm0 +## when encrypting, outputs out(%xmm0) ^ 63 +## when decrypting, outputs unskew(%xmm0) +## +## Always called right before return... jumps to cleanup and exits +## +.align 4 +Lschedule_mangle_last: + # schedule last round key from xmm0 + li r11, 0x2e0 # lea .Lk_deskew(%rip),%r11 + li r9, 0x2f0 + bne $dir, Lschedule_mangle_last_dec + + # encrypting + lvx v1, r8, r10 # vmovdqa (%r8,%r10),%xmm1 + li r11, 0x2c0 # lea .Lk_opt(%rip), %r11 # prepare to output transform + li r9, 0x2d0 # prepare to output transform + vperm v0, v0, v0, v1 # vpshufb %xmm1, %xmm0, %xmm0 # output permute + + lvx $iptlo, r11, r12 # reload $ipt + lvx $ipthi, r9, r12 + addi $out, $out, 16 # add \$16, %rdx + vxor v0, v0, v26 # vpxor .Lk_s63(%rip), %xmm0, %xmm0 + bl _vpaes_schedule_transform # output transform + + #stvx v0, r0, $out # vmovdqu %xmm0, (%rdx) # save last key + vperm v0, v0, v0, $outperm # rotate right/left + li r10, 4 + vsel v2, $outhead, v0, $outmask + li r11, 8 + stvx v2, 0, $out + li r12, 12 + stvewx v0, 0, $out # some (or all) are redundant + stvewx v0, r10, $out + stvewx v0, r11, $out + stvewx v0, r12, $out + b Lschedule_mangle_done + +.align 4 +Lschedule_mangle_last_dec: + lvx $iptlo, r11, r12 # reload $ipt + lvx $ipthi, r9, r12 + addi $out, $out, -16 # add \$-16, %rdx + vxor v0, v0, v26 # vpxor .Lk_s63(%rip), %xmm0, %xmm0 + bl _vpaes_schedule_transform # output transform + + #stvx v0, r0, $out # vmovdqu %xmm0, (%rdx) # save last key + addi r9, $out, -15 # -15 is not typo + vperm v0, v0, v0, $outperm # rotate right/left + li r10, 4 + vsel v2, $outhead, v0, $outmask + li r11, 8 + stvx v2, 0, $out + li r12, 12 + stvewx v0, 0, r9 # some (or all) are redundant + stvewx v0, r10, r9 + stvewx v0, r11, r9 + stvewx v0, r12, r9 + + +Lschedule_mangle_done: + mtlr r7 + # cleanup + vxor v0, v0, v0 # vpxor %xmm0, %xmm0, %xmm0 + vxor v1, v1, v1 # vpxor %xmm1, %xmm1, %xmm1 + vxor v2, v2, v2 # vpxor %xmm2, %xmm2, %xmm2 + vxor v3, v3, v3 # vpxor %xmm3, %xmm3, %xmm3 + vxor v4, v4, v4 # vpxor %xmm4, %xmm4, %xmm4 + vxor v5, v5, v5 # vpxor %xmm5, %xmm5, %xmm5 + vxor v6, v6, v6 # vpxor %xmm6, %xmm6, %xmm6 + vxor v7, v7, v7 # vpxor %xmm7, %xmm7, %xmm7 + + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 + +## +## .aes_schedule_192_smear +## +## Smear the short, low side in the 192-bit key schedule. +## +## Inputs: +## %xmm7: high side, b a x y +## %xmm6: low side, d c 0 0 +## %xmm13: 0 +## +## Outputs: +## %xmm6: b+c+d b+c 0 0 +## %xmm0: b+c+d b+c b a +## +.align 4 +_vpaes_schedule_192_smear: + ?vspltw v0, v7, 3 + ?vsldoi v1, v9, v6, 12 # vpshufd \$0x80, %xmm6, %xmm1 # d c 0 0 -> c 0 0 0 + ?vsldoi v0, v7, v0, 8 # vpshufd \$0xFE, %xmm7, %xmm0 # b a _ _ -> b b b a + vxor v6, v6, v1 # vpxor %xmm1, %xmm6, %xmm6 # -> c+d c 0 0 + vxor v6, v6, v0 # vpxor %xmm0, %xmm6, %xmm6 # -> b+c+d b+c b a + vmr v0, v6 + ?vsldoi v6, v6, v9, 8 + ?vsldoi v6, v9, v6, 8 # clobber low side with zeros + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 + +## +## .aes_schedule_round +## +## Runs one main round of the key schedule on %xmm0, %xmm7 +## +## Specifically, runs subbytes on the high dword of %xmm0 +## then rotates it by one byte and xors into the low dword of +## %xmm7. +## +## Adds rcon from low byte of %xmm8, then rotates %xmm8 for +## next rcon. +## +## Smears the dwords of %xmm7 by xoring the low into the +## second low, result into third, result into highest. +## +## Returns results in %xmm7 = %xmm0. +## Clobbers %xmm1-%xmm4, %r11. +## +.align 4 +_vpaes_schedule_round: + # extract rcon from xmm8 + #vxor v4, v4, v4 # vpxor %xmm4, %xmm4, %xmm4 + ?vsldoi v1, $rcon, v9, 15 # vpalignr \$15, %xmm8, %xmm4, %xmm1 + ?vsldoi $rcon, $rcon, $rcon, 15 # vpalignr \$15, %xmm8, %xmm8, %xmm8 + vxor v7, v7, v1 # vpxor %xmm1, %xmm7, %xmm7 + + # rotate + ?vspltw v0, v0, 3 # vpshufd \$0xFF, %xmm0, %xmm0 + ?vsldoi v0, v0, v0, 1 # vpalignr \$1, %xmm0, %xmm0, %xmm0 + + # fall through... + + # low round: same as high round, but no rotation and no rcon. +_vpaes_schedule_low_round: + # smear xmm7 + ?vsldoi v1, v9, v7, 12 # vpslldq \$4, %xmm7, %xmm1 + vxor v7, v7, v1 # vpxor %xmm1, %xmm7, %xmm7 + vspltisb v1, 0x0f # 0x0f..0f + ?vsldoi v4, v9, v7, 8 # vpslldq \$8, %xmm7, %xmm4 + + # subbytes + vand v1, v1, v0 # vpand %xmm9, %xmm0, %xmm1 # 0 = k + vsrb v0, v0, v8 # vpsrlb \$4, %xmm0, %xmm0 # 1 = i + vxor v7, v7, v4 # vpxor %xmm4, %xmm7, %xmm7 + vperm v2, $invhi, v9, v1 # vpshufb %xmm1, %xmm11, %xmm2 # 2 = a/k + vxor v1, v1, v0 # vpxor %xmm0, %xmm1, %xmm1 # 0 = j + vperm v3, $invlo, v9, v0 # vpshufb %xmm0, %xmm10, %xmm3 # 3 = 1/i + vxor v3, v3, v2 # vpxor %xmm2, %xmm3, %xmm3 # 3 = iak = 1/i + a/k + vperm v4, $invlo, v9, v1 # vpshufb %xmm1, %xmm10, %xmm4 # 4 = 1/j + vxor v7, v7, v26 # vpxor .Lk_s63(%rip), %xmm7, %xmm7 + vperm v3, $invlo, v9, v3 # vpshufb %xmm3, %xmm10, %xmm3 # 2 = 1/iak + vxor v4, v4, v2 # vpxor %xmm2, %xmm4, %xmm4 # 4 = jak = 1/j + a/k + vperm v2, $invlo, v9, v4 # vpshufb %xmm4, %xmm10, %xmm2 # 3 = 1/jak + vxor v3, v3, v1 # vpxor %xmm1, %xmm3, %xmm3 # 2 = io + vxor v2, v2, v0 # vpxor %xmm0, %xmm2, %xmm2 # 3 = jo + vperm v4, v15, v9, v3 # vpshufb %xmm3, %xmm13, %xmm4 # 4 = sbou + vperm v1, v14, v9, v2 # vpshufb %xmm2, %xmm12, %xmm1 # 0 = sb1t + vxor v1, v1, v4 # vpxor %xmm4, %xmm1, %xmm1 # 0 = sbox output + + # add in smeared stuff + vxor v0, v1, v7 # vpxor %xmm7, %xmm1, %xmm0 + vxor v7, v1, v7 # vmovdqa %xmm0, %xmm7 + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 + +## +## .aes_schedule_transform +## +## Linear-transform %xmm0 according to tables at (%r11) +## +## Requires that %xmm9 = 0x0F0F... as in preheat +## Output in %xmm0 +## Clobbers %xmm2 +## +.align 4 +_vpaes_schedule_transform: + #vand v1, v0, v9 # vpand %xmm9, %xmm0, %xmm1 + vsrb v2, v0, v8 # vpsrlb \$4, %xmm0, %xmm0 + # vmovdqa (%r11), %xmm2 # lo + vperm v0, $iptlo, $iptlo, v0 # vpshufb %xmm1, %xmm2, %xmm2 + # vmovdqa 16(%r11), %xmm1 # hi + vperm v2, $ipthi, $ipthi, v2 # vpshufb %xmm0, %xmm1, %xmm0 + vxor v0, v0, v2 # vpxor %xmm2, %xmm0, %xmm0 + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 + +## +## .aes_schedule_mangle +## +## Mangle xmm0 from (basis-transformed) standard version +## to our version. +## +## On encrypt, +## xor with 0x63 +## multiply by circulant 0,1,1,1 +## apply shiftrows transform +## +## On decrypt, +## xor with 0x63 +## multiply by "inverse mixcolumns" circulant E,B,D,9 +## deskew +## apply shiftrows transform +## +## +## Writes out to (%rdx), and increments or decrements it +## Keeps track of round number mod 4 in %r8 +## Preserves xmm0 +## Clobbers xmm1-xmm5 +## +.align 4 +_vpaes_schedule_mangle: + #vmr v4, v0 # vmovdqa %xmm0, %xmm4 # save xmm0 for later + # vmovdqa .Lk_mc_forward(%rip),%xmm5 + bne $dir, Lschedule_mangle_dec + + # encrypting + vxor v4, v0, v26 # vpxor .Lk_s63(%rip), %xmm0, %xmm4 + addi $out, $out, 16 # add \$16, %rdx + vperm v4, v4, v4, v25 # vpshufb %xmm5, %xmm4, %xmm4 + vperm v1, v4, v4, v25 # vpshufb %xmm5, %xmm4, %xmm1 + vperm v3, v1, v1, v25 # vpshufb %xmm5, %xmm1, %xmm3 + vxor v4, v4, v1 # vpxor %xmm1, %xmm4, %xmm4 + lvx v1, r8, r10 # vmovdqa (%r8,%r10), %xmm1 + vxor v3, v3, v4 # vpxor %xmm4, %xmm3, %xmm3 + + vperm v3, v3, v3, v1 # vpshufb %xmm1, %xmm3, %xmm3 + addi r8, r8, -16 # add \$-16, %r8 + andi. r8, r8, 0x30 # and \$0x30, %r8 + + #stvx v3, 0, $out # vmovdqu %xmm3, (%rdx) + vperm v1, v3, v3, $outperm # rotate right/left + vsel v2, $outhead, v1, $outmask + vmr $outhead, v1 + stvx v2, 0, $out + blr + +.align 4 +Lschedule_mangle_dec: + # inverse mix columns + # lea .Lk_dksd(%rip),%r11 + vsrb v1, v0, v8 # vpsrlb \$4, %xmm4, %xmm1 # 1 = hi + #and v4, v0, v9 # vpand %xmm9, %xmm4, %xmm4 # 4 = lo + + # vmovdqa 0x00(%r11), %xmm2 + vperm v2, v16, v16, v0 # vpshufb %xmm4, %xmm2, %xmm2 + # vmovdqa 0x10(%r11), %xmm3 + vperm v3, v17, v17, v1 # vpshufb %xmm1, %xmm3, %xmm3 + vxor v3, v3, v2 # vpxor %xmm2, %xmm3, %xmm3 + vperm v3, v3, v9, v25 # vpshufb %xmm5, %xmm3, %xmm3 + + # vmovdqa 0x20(%r11), %xmm2 + vperm v2, v18, v18, v0 # vpshufb %xmm4, %xmm2, %xmm2 + vxor v2, v2, v3 # vpxor %xmm3, %xmm2, %xmm2 + # vmovdqa 0x30(%r11), %xmm3 + vperm v3, v19, v19, v1 # vpshufb %xmm1, %xmm3, %xmm3 + vxor v3, v3, v2 # vpxor %xmm2, %xmm3, %xmm3 + vperm v3, v3, v9, v25 # vpshufb %xmm5, %xmm3, %xmm3 + + # vmovdqa 0x40(%r11), %xmm2 + vperm v2, v20, v20, v0 # vpshufb %xmm4, %xmm2, %xmm2 + vxor v2, v2, v3 # vpxor %xmm3, %xmm2, %xmm2 + # vmovdqa 0x50(%r11), %xmm3 + vperm v3, v21, v21, v1 # vpshufb %xmm1, %xmm3, %xmm3 + vxor v3, v3, v2 # vpxor %xmm2, %xmm3, %xmm3 + + # vmovdqa 0x60(%r11), %xmm2 + vperm v2, v22, v22, v0 # vpshufb %xmm4, %xmm2, %xmm2 + vperm v3, v3, v9, v25 # vpshufb %xmm5, %xmm3, %xmm3 + # vmovdqa 0x70(%r11), %xmm4 + vperm v4, v23, v23, v1 # vpshufb %xmm1, %xmm4, %xmm4 + lvx v1, r8, r10 # vmovdqa (%r8,%r10), %xmm1 + vxor v2, v2, v3 # vpxor %xmm3, %xmm2, %xmm2 + vxor v3, v4, v2 # vpxor %xmm2, %xmm4, %xmm3 + + addi $out, $out, -16 # add \$-16, %rdx + + vperm v3, v3, v3, v1 # vpshufb %xmm1, %xmm3, %xmm3 + addi r8, r8, -16 # add \$-16, %r8 + andi. r8, r8, 0x30 # and \$0x30, %r8 + + #stvx v3, 0, $out # vmovdqu %xmm3, (%rdx) + vperm v1, v3, v3, $outperm # rotate right/left + vsel v2, $outhead, v1, $outmask + vmr $outhead, v1 + stvx v2, 0, $out + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 + +.globl .vpaes_set_encrypt_key +.align 5 +.vpaes_set_encrypt_key: + $STU $sp,-$FRAME($sp) + li r10,`15+6*$SIZE_T` + li r11,`31+6*$SIZE_T` + mflr r0 + mfspr r6, 256 # save vrsave + stvx v20,r10,$sp + addi r10,r10,32 + stvx v21,r11,$sp + addi r11,r11,32 + stvx v22,r10,$sp + addi r10,r10,32 + stvx v23,r11,$sp + addi r11,r11,32 + stvx v24,r10,$sp + addi r10,r10,32 + stvx v25,r11,$sp + addi r11,r11,32 + stvx v26,r10,$sp + addi r10,r10,32 + stvx v27,r11,$sp + addi r11,r11,32 + stvx v28,r10,$sp + addi r10,r10,32 + stvx v29,r11,$sp + addi r11,r11,32 + stvx v30,r10,$sp + stvx v31,r11,$sp + stw r6,`$FRAME-4`($sp) # save vrsave + li r7, -1 + $PUSH r0, `$FRAME+$LRSAVE`($sp) + mtspr 256, r7 # preserve all AltiVec registers + + srwi r9, $bits, 5 # shr \$5,%eax + addi r9, r9, 6 # add \$5,%eax + stw r9, 240($out) # mov %eax,240(%rdx) # AES_KEY->rounds = nbits/32+5; + + cmplw $dir, $bits, $bits # set encrypt direction + li r8, 0x30 # mov \$0x30,%r8d + bl _vpaes_schedule_core + + $POP r0, `$FRAME+$LRSAVE`($sp) + li r10,`15+6*$SIZE_T` + li r11,`31+6*$SIZE_T` + mtspr 256, r6 # restore vrsave + mtlr r0 + xor r3, r3, r3 + lvx v20,r10,$sp + addi r10,r10,32 + lvx v21,r11,$sp + addi r11,r11,32 + lvx v22,r10,$sp + addi r10,r10,32 + lvx v23,r11,$sp + addi r11,r11,32 + lvx v24,r10,$sp + addi r10,r10,32 + lvx v25,r11,$sp + addi r11,r11,32 + lvx v26,r10,$sp + addi r10,r10,32 + lvx v27,r11,$sp + addi r11,r11,32 + lvx v28,r10,$sp + addi r10,r10,32 + lvx v29,r11,$sp + addi r11,r11,32 + lvx v30,r10,$sp + lvx v31,r11,$sp + addi $sp,$sp,$FRAME + blr + .long 0 + .byte 0,12,0x04,1,0x80,0,3,0 + .long 0 +.size .vpaes_set_encrypt_key,.-.vpaes_set_encrypt_key + +.globl .vpaes_set_decrypt_key +.align 4 +.vpaes_set_decrypt_key: + $STU $sp,-$FRAME($sp) + li r10,`15+6*$SIZE_T` + li r11,`31+6*$SIZE_T` + mflr r0 + mfspr r6, 256 # save vrsave + stvx v20,r10,$sp + addi r10,r10,32 + stvx v21,r11,$sp + addi r11,r11,32 + stvx v22,r10,$sp + addi r10,r10,32 + stvx v23,r11,$sp + addi r11,r11,32 + stvx v24,r10,$sp + addi r10,r10,32 + stvx v25,r11,$sp + addi r11,r11,32 + stvx v26,r10,$sp + addi r10,r10,32 + stvx v27,r11,$sp + addi r11,r11,32 + stvx v28,r10,$sp + addi r10,r10,32 + stvx v29,r11,$sp + addi r11,r11,32 + stvx v30,r10,$sp + stvx v31,r11,$sp + stw r6,`$FRAME-4`($sp) # save vrsave + li r7, -1 + $PUSH r0, `$FRAME+$LRSAVE`($sp) + mtspr 256, r7 # preserve all AltiVec registers + + srwi r9, $bits, 5 # shr \$5,%eax + addi r9, r9, 6 # add \$5,%eax + stw r9, 240($out) # mov %eax,240(%rdx) # AES_KEY->rounds = nbits/32+5; + + slwi r9, r9, 4 # shl \$4,%eax + add $out, $out, r9 # lea (%rdx,%rax),%rdx + + cmplwi $dir, $bits, 0 # set decrypt direction + srwi r8, $bits, 1 # shr \$1,%r8d + andi. r8, r8, 32 # and \$32,%r8d + xori r8, r8, 32 # xor \$32,%r8d # nbits==192?0:32 + bl _vpaes_schedule_core + + $POP r0, `$FRAME+$LRSAVE`($sp) + li r10,`15+6*$SIZE_T` + li r11,`31+6*$SIZE_T` + mtspr 256, r6 # restore vrsave + mtlr r0 + xor r3, r3, r3 + lvx v20,r10,$sp + addi r10,r10,32 + lvx v21,r11,$sp + addi r11,r11,32 + lvx v22,r10,$sp + addi r10,r10,32 + lvx v23,r11,$sp + addi r11,r11,32 + lvx v24,r10,$sp + addi r10,r10,32 + lvx v25,r11,$sp + addi r11,r11,32 + lvx v26,r10,$sp + addi r10,r10,32 + lvx v27,r11,$sp + addi r11,r11,32 + lvx v28,r10,$sp + addi r10,r10,32 + lvx v29,r11,$sp + addi r11,r11,32 + lvx v30,r10,$sp + lvx v31,r11,$sp + addi $sp,$sp,$FRAME + blr + .long 0 + .byte 0,12,0x04,1,0x80,0,3,0 + .long 0 +.size .vpaes_set_decrypt_key,.-.vpaes_set_decrypt_key +___ +} + +my $consts=1; +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/geo; + + # constants table endian-specific conversion + if ($consts && m/\.long\s+(.+)\s+(\?[a-z]*)$/o) { + my $conv=$2; + my @bytes=(); + + # convert to endian-agnostic format + foreach (split(/,\s+/,$1)) { + my $l = /^0/?oct:int; + push @bytes,($l>>24)&0xff,($l>>16)&0xff,($l>>8)&0xff,$l&0xff; + } + + # little-endian conversion + if ($flavour =~ /le$/o) { + SWITCH: for($conv) { + /\?inv/ && do { @bytes=map($_^0xf,@bytes); last; }; + /\?rev/ && do { @bytes=reverse(@bytes); last; }; + } + } + + #emit + print ".byte\t",join(',',map (sprintf("0x%02x",$_),@bytes)),"\n"; + next; + } + $consts=0 if (m/Lconsts:/o); # end of table + + # instructions prefixed with '?' are endian-specific and need + # to be adjusted accordingly... + if ($flavour =~ /le$/o) { # little-endian + s/\?lvsr/lvsl/o or + s/\?lvsl/lvsr/o or + s/\?(vperm\s+v[0-9]+,\s*)(v[0-9]+,\s*)(v[0-9]+,\s*)(v[0-9]+)/$1$3$2$4/o or + s/\?(vsldoi\s+v[0-9]+,\s*)(v[0-9]+,)\s*(v[0-9]+,\s*)([0-9]+)/$1$3$2 16-$4/o or + s/\?(vspltw\s+v[0-9]+,\s*)(v[0-9]+,)\s*([0-9])/$1$2 3-$3/o; + } else { # big-endian + s/\?([a-z]+)/$1/o; + } + + print $_,"\n"; +} + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/vpaes-x86.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/vpaes-x86.pl new file mode 100644 index 000000000..7d57edc0e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/vpaes-x86.pl @@ -0,0 +1,916 @@ +#! /usr/bin/env perl +# Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +###################################################################### +## Constant-time SSSE3 AES core implementation. +## version 0.1 +## +## By Mike Hamburg (Stanford University), 2009 +## Public domain. +## +## For details see http://shiftleft.org/papers/vector_aes/ and +## http://crypto.stanford.edu/vpaes/. + +###################################################################### +# September 2011. +# +# Port vpaes-x86_64.pl as 32-bit "almost" drop-in replacement for +# aes-586.pl. "Almost" refers to the fact that AES_cbc_encrypt +# doesn't handle partial vectors (doesn't have to if called from +# EVP only). "Drop-in" implies that this module doesn't share key +# schedule structure with the original nor does it make assumption +# about its alignment... +# +# Performance summary. aes-586.pl column lists large-block CBC +# encrypt/decrypt/with-hyper-threading-off(*) results in cycles per +# byte processed with 128-bit key, and vpaes-x86.pl column - [also +# large-block CBC] encrypt/decrypt. +# +# aes-586.pl vpaes-x86.pl +# +# Core 2(**) 28.1/41.4/18.3 21.9/25.2(***) +# Nehalem 27.9/40.4/18.1 10.2/11.9 +# Atom 70.7/92.1/60.1 61.1/75.4(***) +# Silvermont 45.4/62.9/24.1 49.2/61.1(***) +# +# (*) "Hyper-threading" in the context refers rather to cache shared +# among multiple cores, than to specifically Intel HTT. As vast +# majority of contemporary cores share cache, slower code path +# is common place. In other words "with-hyper-threading-off" +# results are presented mostly for reference purposes. +# +# (**) "Core 2" refers to initial 65nm design, a.k.a. Conroe. +# +# (***) Less impressive improvement on Core 2 and Atom is due to slow +# pshufb, yet it's respectable +28%/64% improvement on Core 2 +# and +15% on Atom (as implied, over "hyper-threading-safe" +# code path). +# +# + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +$output = pop; +open OUT,">$output"; +*STDOUT=*OUT; + +&asm_init($ARGV[0],$x86only = $ARGV[$#ARGV] eq "386"); + +$PREFIX="vpaes"; + +my ($round, $base, $magic, $key, $const, $inp, $out)= + ("eax", "ebx", "ecx", "edx","ebp", "esi","edi"); + +&static_label("_vpaes_consts"); +&static_label("_vpaes_schedule_low_round"); + +&set_label("_vpaes_consts",64); +$k_inv=-0x30; # inv, inva + &data_word(0x0D080180,0x0E05060F,0x0A0B0C02,0x04070309); + &data_word(0x0F0B0780,0x01040A06,0x02050809,0x030D0E0C); + +$k_s0F=-0x10; # s0F + &data_word(0x0F0F0F0F,0x0F0F0F0F,0x0F0F0F0F,0x0F0F0F0F); + +$k_ipt=0x00; # input transform (lo, hi) + &data_word(0x5A2A7000,0xC2B2E898,0x52227808,0xCABAE090); + &data_word(0x317C4D00,0x4C01307D,0xB0FDCC81,0xCD80B1FC); + +$k_sb1=0x20; # sb1u, sb1t + &data_word(0xCB503E00,0xB19BE18F,0x142AF544,0xA5DF7A6E); + &data_word(0xFAE22300,0x3618D415,0x0D2ED9EF,0x3BF7CCC1); +$k_sb2=0x40; # sb2u, sb2t + &data_word(0x0B712400,0xE27A93C6,0xBC982FCD,0x5EB7E955); + &data_word(0x0AE12900,0x69EB8840,0xAB82234A,0xC2A163C8); +$k_sbo=0x60; # sbou, sbot + &data_word(0x6FBDC700,0xD0D26D17,0xC502A878,0x15AABF7A); + &data_word(0x5FBB6A00,0xCFE474A5,0x412B35FA,0x8E1E90D1); + +$k_mc_forward=0x80; # mc_forward + &data_word(0x00030201,0x04070605,0x080B0A09,0x0C0F0E0D); + &data_word(0x04070605,0x080B0A09,0x0C0F0E0D,0x00030201); + &data_word(0x080B0A09,0x0C0F0E0D,0x00030201,0x04070605); + &data_word(0x0C0F0E0D,0x00030201,0x04070605,0x080B0A09); + +$k_mc_backward=0xc0; # mc_backward + &data_word(0x02010003,0x06050407,0x0A09080B,0x0E0D0C0F); + &data_word(0x0E0D0C0F,0x02010003,0x06050407,0x0A09080B); + &data_word(0x0A09080B,0x0E0D0C0F,0x02010003,0x06050407); + &data_word(0x06050407,0x0A09080B,0x0E0D0C0F,0x02010003); + +$k_sr=0x100; # sr + &data_word(0x03020100,0x07060504,0x0B0A0908,0x0F0E0D0C); + &data_word(0x0F0A0500,0x030E0904,0x07020D08,0x0B06010C); + &data_word(0x0B020900,0x0F060D04,0x030A0108,0x070E050C); + &data_word(0x070A0D00,0x0B0E0104,0x0F020508,0x0306090C); + +$k_rcon=0x140; # rcon + &data_word(0xAF9DEEB6,0x1F8391B9,0x4D7C7D81,0x702A9808); + +$k_s63=0x150; # s63: all equal to 0x63 transformed + &data_word(0x5B5B5B5B,0x5B5B5B5B,0x5B5B5B5B,0x5B5B5B5B); + +$k_opt=0x160; # output transform + &data_word(0xD6B66000,0xFF9F4929,0xDEBE6808,0xF7974121); + &data_word(0x50BCEC00,0x01EDBD51,0xB05C0CE0,0xE10D5DB1); + +$k_deskew=0x180; # deskew tables: inverts the sbox's "skew" + &data_word(0x47A4E300,0x07E4A340,0x5DBEF91A,0x1DFEB95A); + &data_word(0x83EA6900,0x5F36B5DC,0xF49D1E77,0x2841C2AB); +## +## Decryption stuff +## Key schedule constants +## +$k_dksd=0x1a0; # decryption key schedule: invskew x*D + &data_word(0xA3E44700,0xFEB91A5D,0x5A1DBEF9,0x0740E3A4); + &data_word(0xB5368300,0x41C277F4,0xAB289D1E,0x5FDC69EA); +$k_dksb=0x1c0; # decryption key schedule: invskew x*B + &data_word(0x8550D500,0x9A4FCA1F,0x1CC94C99,0x03D65386); + &data_word(0xB6FC4A00,0x115BEDA7,0x7E3482C8,0xD993256F); +$k_dkse=0x1e0; # decryption key schedule: invskew x*E + 0x63 + &data_word(0x1FC9D600,0xD5031CCA,0x994F5086,0x53859A4C); + &data_word(0x4FDC7BE8,0xA2319605,0x20B31487,0xCD5EF96A); +$k_dks9=0x200; # decryption key schedule: invskew x*9 + &data_word(0x7ED9A700,0xB6116FC8,0x82255BFC,0x4AED9334); + &data_word(0x27143300,0x45765162,0xE9DAFDCE,0x8BB89FAC); + +## +## Decryption stuff +## Round function constants +## +$k_dipt=0x220; # decryption input transform + &data_word(0x0B545F00,0x0F505B04,0x114E451A,0x154A411E); + &data_word(0x60056500,0x86E383E6,0xF491F194,0x12771772); + +$k_dsb9=0x240; # decryption sbox output *9*u, *9*t + &data_word(0x9A86D600,0x851C0353,0x4F994CC9,0xCAD51F50); + &data_word(0xECD74900,0xC03B1789,0xB2FBA565,0x725E2C9E); +$k_dsbd=0x260; # decryption sbox output *D*u, *D*t + &data_word(0xE6B1A200,0x7D57CCDF,0x882A4439,0xF56E9B13); + &data_word(0x24C6CB00,0x3CE2FAF7,0x15DEEFD3,0x2931180D); +$k_dsbb=0x280; # decryption sbox output *B*u, *B*t + &data_word(0x96B44200,0xD0226492,0xB0F2D404,0x602646F6); + &data_word(0xCD596700,0xC19498A6,0x3255AA6B,0xF3FF0C3E); +$k_dsbe=0x2a0; # decryption sbox output *E*u, *E*t + &data_word(0x26D4D000,0x46F29296,0x64B4F6B0,0x22426004); + &data_word(0xFFAAC100,0x0C55A6CD,0x98593E32,0x9467F36B); +$k_dsbo=0x2c0; # decryption sbox final output + &data_word(0x7EF94000,0x1387EA53,0xD4943E2D,0xC7AA6DB9); + &data_word(0x93441D00,0x12D7560F,0xD8C58E9C,0xCA4B8159); +&asciz ("Vector Permutation AES for x86/SSSE3, Mike Hamburg (Stanford University)"); +&align (64); + +&function_begin_B("_vpaes_preheat"); + &add ($const,&DWP(0,"esp")); + &movdqa ("xmm7",&QWP($k_inv,$const)); + &movdqa ("xmm6",&QWP($k_s0F,$const)); + &ret (); +&function_end_B("_vpaes_preheat"); + +## +## _aes_encrypt_core +## +## AES-encrypt %xmm0. +## +## Inputs: +## %xmm0 = input +## %xmm6-%xmm7 as in _vpaes_preheat +## (%edx) = scheduled keys +## +## Output in %xmm0 +## Clobbers %xmm1-%xmm5, %eax, %ebx, %ecx, %edx +## +## +&function_begin_B("_vpaes_encrypt_core"); + &mov ($magic,16); + &mov ($round,&DWP(240,$key)); + &movdqa ("xmm1","xmm6") + &movdqa ("xmm2",&QWP($k_ipt,$const)); + &pandn ("xmm1","xmm0"); + &pand ("xmm0","xmm6"); + &movdqu ("xmm5",&QWP(0,$key)); + &pshufb ("xmm2","xmm0"); + &movdqa ("xmm0",&QWP($k_ipt+16,$const)); + &pxor ("xmm2","xmm5"); + &psrld ("xmm1",4); + &add ($key,16); + &pshufb ("xmm0","xmm1"); + &lea ($base,&DWP($k_mc_backward,$const)); + &pxor ("xmm0","xmm2"); + &jmp (&label("enc_entry")); + + +&set_label("enc_loop",16); + # middle of middle round + &movdqa ("xmm4",&QWP($k_sb1,$const)); # 4 : sb1u + &movdqa ("xmm0",&QWP($k_sb1+16,$const));# 0 : sb1t + &pshufb ("xmm4","xmm2"); # 4 = sb1u + &pshufb ("xmm0","xmm3"); # 0 = sb1t + &pxor ("xmm4","xmm5"); # 4 = sb1u + k + &movdqa ("xmm5",&QWP($k_sb2,$const)); # 4 : sb2u + &pxor ("xmm0","xmm4"); # 0 = A + &movdqa ("xmm1",&QWP(-0x40,$base,$magic));# .Lk_mc_forward[] + &pshufb ("xmm5","xmm2"); # 4 = sb2u + &movdqa ("xmm2",&QWP($k_sb2+16,$const));# 2 : sb2t + &movdqa ("xmm4",&QWP(0,$base,$magic)); # .Lk_mc_backward[] + &pshufb ("xmm2","xmm3"); # 2 = sb2t + &movdqa ("xmm3","xmm0"); # 3 = A + &pxor ("xmm2","xmm5"); # 2 = 2A + &pshufb ("xmm0","xmm1"); # 0 = B + &add ($key,16); # next key + &pxor ("xmm0","xmm2"); # 0 = 2A+B + &pshufb ("xmm3","xmm4"); # 3 = D + &add ($magic,16); # next mc + &pxor ("xmm3","xmm0"); # 3 = 2A+B+D + &pshufb ("xmm0","xmm1"); # 0 = 2B+C + &and ($magic,0x30); # ... mod 4 + &sub ($round,1); # nr-- + &pxor ("xmm0","xmm3"); # 0 = 2A+3B+C+D + +&set_label("enc_entry"); + # top of round + &movdqa ("xmm1","xmm6"); # 1 : i + &movdqa ("xmm5",&QWP($k_inv+16,$const));# 2 : a/k + &pandn ("xmm1","xmm0"); # 1 = i<<4 + &psrld ("xmm1",4); # 1 = i + &pand ("xmm0","xmm6"); # 0 = k + &pshufb ("xmm5","xmm0"); # 2 = a/k + &movdqa ("xmm3","xmm7"); # 3 : 1/i + &pxor ("xmm0","xmm1"); # 0 = j + &pshufb ("xmm3","xmm1"); # 3 = 1/i + &movdqa ("xmm4","xmm7"); # 4 : 1/j + &pxor ("xmm3","xmm5"); # 3 = iak = 1/i + a/k + &pshufb ("xmm4","xmm0"); # 4 = 1/j + &movdqa ("xmm2","xmm7"); # 2 : 1/iak + &pxor ("xmm4","xmm5"); # 4 = jak = 1/j + a/k + &pshufb ("xmm2","xmm3"); # 2 = 1/iak + &movdqa ("xmm3","xmm7"); # 3 : 1/jak + &pxor ("xmm2","xmm0"); # 2 = io + &pshufb ("xmm3","xmm4"); # 3 = 1/jak + &movdqu ("xmm5",&QWP(0,$key)); + &pxor ("xmm3","xmm1"); # 3 = jo + &jnz (&label("enc_loop")); + + # middle of last round + &movdqa ("xmm4",&QWP($k_sbo,$const)); # 3 : sbou .Lk_sbo + &movdqa ("xmm0",&QWP($k_sbo+16,$const));# 3 : sbot .Lk_sbo+16 + &pshufb ("xmm4","xmm2"); # 4 = sbou + &pxor ("xmm4","xmm5"); # 4 = sb1u + k + &pshufb ("xmm0","xmm3"); # 0 = sb1t + &movdqa ("xmm1",&QWP(0x40,$base,$magic));# .Lk_sr[] + &pxor ("xmm0","xmm4"); # 0 = A + &pshufb ("xmm0","xmm1"); + &ret (); +&function_end_B("_vpaes_encrypt_core"); + +## +## Decryption core +## +## Same API as encryption core. +## +&function_begin_B("_vpaes_decrypt_core"); + &lea ($base,&DWP($k_dsbd,$const)); + &mov ($round,&DWP(240,$key)); + &movdqa ("xmm1","xmm6"); + &movdqa ("xmm2",&QWP($k_dipt-$k_dsbd,$base)); + &pandn ("xmm1","xmm0"); + &mov ($magic,$round); + &psrld ("xmm1",4) + &movdqu ("xmm5",&QWP(0,$key)); + &shl ($magic,4); + &pand ("xmm0","xmm6"); + &pshufb ("xmm2","xmm0"); + &movdqa ("xmm0",&QWP($k_dipt-$k_dsbd+16,$base)); + &xor ($magic,0x30); + &pshufb ("xmm0","xmm1"); + &and ($magic,0x30); + &pxor ("xmm2","xmm5"); + &movdqa ("xmm5",&QWP($k_mc_forward+48,$const)); + &pxor ("xmm0","xmm2"); + &add ($key,16); + &lea ($magic,&DWP($k_sr-$k_dsbd,$base,$magic)); + &jmp (&label("dec_entry")); + +&set_label("dec_loop",16); +## +## Inverse mix columns +## + &movdqa ("xmm4",&QWP(-0x20,$base)); # 4 : sb9u + &movdqa ("xmm1",&QWP(-0x10,$base)); # 0 : sb9t + &pshufb ("xmm4","xmm2"); # 4 = sb9u + &pshufb ("xmm1","xmm3"); # 0 = sb9t + &pxor ("xmm0","xmm4"); + &movdqa ("xmm4",&QWP(0,$base)); # 4 : sbdu + &pxor ("xmm0","xmm1"); # 0 = ch + &movdqa ("xmm1",&QWP(0x10,$base)); # 0 : sbdt + + &pshufb ("xmm4","xmm2"); # 4 = sbdu + &pshufb ("xmm0","xmm5"); # MC ch + &pshufb ("xmm1","xmm3"); # 0 = sbdt + &pxor ("xmm0","xmm4"); # 4 = ch + &movdqa ("xmm4",&QWP(0x20,$base)); # 4 : sbbu + &pxor ("xmm0","xmm1"); # 0 = ch + &movdqa ("xmm1",&QWP(0x30,$base)); # 0 : sbbt + + &pshufb ("xmm4","xmm2"); # 4 = sbbu + &pshufb ("xmm0","xmm5"); # MC ch + &pshufb ("xmm1","xmm3"); # 0 = sbbt + &pxor ("xmm0","xmm4"); # 4 = ch + &movdqa ("xmm4",&QWP(0x40,$base)); # 4 : sbeu + &pxor ("xmm0","xmm1"); # 0 = ch + &movdqa ("xmm1",&QWP(0x50,$base)); # 0 : sbet + + &pshufb ("xmm4","xmm2"); # 4 = sbeu + &pshufb ("xmm0","xmm5"); # MC ch + &pshufb ("xmm1","xmm3"); # 0 = sbet + &pxor ("xmm0","xmm4"); # 4 = ch + &add ($key,16); # next round key + &palignr("xmm5","xmm5",12); + &pxor ("xmm0","xmm1"); # 0 = ch + &sub ($round,1); # nr-- + +&set_label("dec_entry"); + # top of round + &movdqa ("xmm1","xmm6"); # 1 : i + &movdqa ("xmm2",&QWP($k_inv+16,$const));# 2 : a/k + &pandn ("xmm1","xmm0"); # 1 = i<<4 + &pand ("xmm0","xmm6"); # 0 = k + &psrld ("xmm1",4); # 1 = i + &pshufb ("xmm2","xmm0"); # 2 = a/k + &movdqa ("xmm3","xmm7"); # 3 : 1/i + &pxor ("xmm0","xmm1"); # 0 = j + &pshufb ("xmm3","xmm1"); # 3 = 1/i + &movdqa ("xmm4","xmm7"); # 4 : 1/j + &pxor ("xmm3","xmm2"); # 3 = iak = 1/i + a/k + &pshufb ("xmm4","xmm0"); # 4 = 1/j + &pxor ("xmm4","xmm2"); # 4 = jak = 1/j + a/k + &movdqa ("xmm2","xmm7"); # 2 : 1/iak + &pshufb ("xmm2","xmm3"); # 2 = 1/iak + &movdqa ("xmm3","xmm7"); # 3 : 1/jak + &pxor ("xmm2","xmm0"); # 2 = io + &pshufb ("xmm3","xmm4"); # 3 = 1/jak + &movdqu ("xmm0",&QWP(0,$key)); + &pxor ("xmm3","xmm1"); # 3 = jo + &jnz (&label("dec_loop")); + + # middle of last round + &movdqa ("xmm4",&QWP(0x60,$base)); # 3 : sbou + &pshufb ("xmm4","xmm2"); # 4 = sbou + &pxor ("xmm4","xmm0"); # 4 = sb1u + k + &movdqa ("xmm0",&QWP(0x70,$base)); # 0 : sbot + &movdqa ("xmm2",&QWP(0,$magic)); + &pshufb ("xmm0","xmm3"); # 0 = sb1t + &pxor ("xmm0","xmm4"); # 0 = A + &pshufb ("xmm0","xmm2"); + &ret (); +&function_end_B("_vpaes_decrypt_core"); + +######################################################## +## ## +## AES key schedule ## +## ## +######################################################## +&function_begin_B("_vpaes_schedule_core"); + &add ($const,&DWP(0,"esp")); + &movdqu ("xmm0",&QWP(0,$inp)); # load key (unaligned) + &movdqa ("xmm2",&QWP($k_rcon,$const)); # load rcon + + # input transform + &movdqa ("xmm3","xmm0"); + &lea ($base,&DWP($k_ipt,$const)); + &movdqa (&QWP(4,"esp"),"xmm2"); # xmm8 + &call ("_vpaes_schedule_transform"); + &movdqa ("xmm7","xmm0"); + + &test ($out,$out); + &jnz (&label("schedule_am_decrypting")); + + # encrypting, output zeroth round key after transform + &movdqu (&QWP(0,$key),"xmm0"); + &jmp (&label("schedule_go")); + +&set_label("schedule_am_decrypting"); + # decrypting, output zeroth round key after shiftrows + &movdqa ("xmm1",&QWP($k_sr,$const,$magic)); + &pshufb ("xmm3","xmm1"); + &movdqu (&QWP(0,$key),"xmm3"); + &xor ($magic,0x30); + +&set_label("schedule_go"); + &cmp ($round,192); + &ja (&label("schedule_256")); + &je (&label("schedule_192")); + # 128: fall though + +## +## .schedule_128 +## +## 128-bit specific part of key schedule. +## +## This schedule is really simple, because all its parts +## are accomplished by the subroutines. +## +&set_label("schedule_128"); + &mov ($round,10); + +&set_label("loop_schedule_128"); + &call ("_vpaes_schedule_round"); + &dec ($round); + &jz (&label("schedule_mangle_last")); + &call ("_vpaes_schedule_mangle"); # write output + &jmp (&label("loop_schedule_128")); + +## +## .aes_schedule_192 +## +## 192-bit specific part of key schedule. +## +## The main body of this schedule is the same as the 128-bit +## schedule, but with more smearing. The long, high side is +## stored in %xmm7 as before, and the short, low side is in +## the high bits of %xmm6. +## +## This schedule is somewhat nastier, however, because each +## round produces 192 bits of key material, or 1.5 round keys. +## Therefore, on each cycle we do 2 rounds and produce 3 round +## keys. +## +&set_label("schedule_192",16); + &movdqu ("xmm0",&QWP(8,$inp)); # load key part 2 (very unaligned) + &call ("_vpaes_schedule_transform"); # input transform + &movdqa ("xmm6","xmm0"); # save short part + &pxor ("xmm4","xmm4"); # clear 4 + &movhlps("xmm6","xmm4"); # clobber low side with zeros + &mov ($round,4); + +&set_label("loop_schedule_192"); + &call ("_vpaes_schedule_round"); + &palignr("xmm0","xmm6",8); + &call ("_vpaes_schedule_mangle"); # save key n + &call ("_vpaes_schedule_192_smear"); + &call ("_vpaes_schedule_mangle"); # save key n+1 + &call ("_vpaes_schedule_round"); + &dec ($round); + &jz (&label("schedule_mangle_last")); + &call ("_vpaes_schedule_mangle"); # save key n+2 + &call ("_vpaes_schedule_192_smear"); + &jmp (&label("loop_schedule_192")); + +## +## .aes_schedule_256 +## +## 256-bit specific part of key schedule. +## +## The structure here is very similar to the 128-bit +## schedule, but with an additional "low side" in +## %xmm6. The low side's rounds are the same as the +## high side's, except no rcon and no rotation. +## +&set_label("schedule_256",16); + &movdqu ("xmm0",&QWP(16,$inp)); # load key part 2 (unaligned) + &call ("_vpaes_schedule_transform"); # input transform + &mov ($round,7); + +&set_label("loop_schedule_256"); + &call ("_vpaes_schedule_mangle"); # output low result + &movdqa ("xmm6","xmm0"); # save cur_lo in xmm6 + + # high round + &call ("_vpaes_schedule_round"); + &dec ($round); + &jz (&label("schedule_mangle_last")); + &call ("_vpaes_schedule_mangle"); + + # low round. swap xmm7 and xmm6 + &pshufd ("xmm0","xmm0",0xFF); + &movdqa (&QWP(20,"esp"),"xmm7"); + &movdqa ("xmm7","xmm6"); + &call ("_vpaes_schedule_low_round"); + &movdqa ("xmm7",&QWP(20,"esp")); + + &jmp (&label("loop_schedule_256")); + +## +## .aes_schedule_mangle_last +## +## Mangler for last round of key schedule +## Mangles %xmm0 +## when encrypting, outputs out(%xmm0) ^ 63 +## when decrypting, outputs unskew(%xmm0) +## +## Always called right before return... jumps to cleanup and exits +## +&set_label("schedule_mangle_last",16); + # schedule last round key from xmm0 + &lea ($base,&DWP($k_deskew,$const)); + &test ($out,$out); + &jnz (&label("schedule_mangle_last_dec")); + + # encrypting + &movdqa ("xmm1",&QWP($k_sr,$const,$magic)); + &pshufb ("xmm0","xmm1"); # output permute + &lea ($base,&DWP($k_opt,$const)); # prepare to output transform + &add ($key,32); + +&set_label("schedule_mangle_last_dec"); + &add ($key,-16); + &pxor ("xmm0",&QWP($k_s63,$const)); + &call ("_vpaes_schedule_transform"); # output transform + &movdqu (&QWP(0,$key),"xmm0"); # save last key + + # cleanup + &pxor ("xmm0","xmm0"); + &pxor ("xmm1","xmm1"); + &pxor ("xmm2","xmm2"); + &pxor ("xmm3","xmm3"); + &pxor ("xmm4","xmm4"); + &pxor ("xmm5","xmm5"); + &pxor ("xmm6","xmm6"); + &pxor ("xmm7","xmm7"); + &ret (); +&function_end_B("_vpaes_schedule_core"); + +## +## .aes_schedule_192_smear +## +## Smear the short, low side in the 192-bit key schedule. +## +## Inputs: +## %xmm7: high side, b a x y +## %xmm6: low side, d c 0 0 +## %xmm13: 0 +## +## Outputs: +## %xmm6: b+c+d b+c 0 0 +## %xmm0: b+c+d b+c b a +## +&function_begin_B("_vpaes_schedule_192_smear"); + &pshufd ("xmm1","xmm6",0x80); # d c 0 0 -> c 0 0 0 + &pshufd ("xmm0","xmm7",0xFE); # b a _ _ -> b b b a + &pxor ("xmm6","xmm1"); # -> c+d c 0 0 + &pxor ("xmm1","xmm1"); + &pxor ("xmm6","xmm0"); # -> b+c+d b+c b a + &movdqa ("xmm0","xmm6"); + &movhlps("xmm6","xmm1"); # clobber low side with zeros + &ret (); +&function_end_B("_vpaes_schedule_192_smear"); + +## +## .aes_schedule_round +## +## Runs one main round of the key schedule on %xmm0, %xmm7 +## +## Specifically, runs subbytes on the high dword of %xmm0 +## then rotates it by one byte and xors into the low dword of +## %xmm7. +## +## Adds rcon from low byte of %xmm8, then rotates %xmm8 for +## next rcon. +## +## Smears the dwords of %xmm7 by xoring the low into the +## second low, result into third, result into highest. +## +## Returns results in %xmm7 = %xmm0. +## Clobbers %xmm1-%xmm5. +## +&function_begin_B("_vpaes_schedule_round"); + # extract rcon from xmm8 + &movdqa ("xmm2",&QWP(8,"esp")); # xmm8 + &pxor ("xmm1","xmm1"); + &palignr("xmm1","xmm2",15); + &palignr("xmm2","xmm2",15); + &pxor ("xmm7","xmm1"); + + # rotate + &pshufd ("xmm0","xmm0",0xFF); + &palignr("xmm0","xmm0",1); + + # fall through... + &movdqa (&QWP(8,"esp"),"xmm2"); # xmm8 + + # low round: same as high round, but no rotation and no rcon. +&set_label("_vpaes_schedule_low_round"); + # smear xmm7 + &movdqa ("xmm1","xmm7"); + &pslldq ("xmm7",4); + &pxor ("xmm7","xmm1"); + &movdqa ("xmm1","xmm7"); + &pslldq ("xmm7",8); + &pxor ("xmm7","xmm1"); + &pxor ("xmm7",&QWP($k_s63,$const)); + + # subbyte + &movdqa ("xmm4",&QWP($k_s0F,$const)); + &movdqa ("xmm5",&QWP($k_inv,$const)); # 4 : 1/j + &movdqa ("xmm1","xmm4"); + &pandn ("xmm1","xmm0"); + &psrld ("xmm1",4); # 1 = i + &pand ("xmm0","xmm4"); # 0 = k + &movdqa ("xmm2",&QWP($k_inv+16,$const));# 2 : a/k + &pshufb ("xmm2","xmm0"); # 2 = a/k + &pxor ("xmm0","xmm1"); # 0 = j + &movdqa ("xmm3","xmm5"); # 3 : 1/i + &pshufb ("xmm3","xmm1"); # 3 = 1/i + &pxor ("xmm3","xmm2"); # 3 = iak = 1/i + a/k + &movdqa ("xmm4","xmm5"); # 4 : 1/j + &pshufb ("xmm4","xmm0"); # 4 = 1/j + &pxor ("xmm4","xmm2"); # 4 = jak = 1/j + a/k + &movdqa ("xmm2","xmm5"); # 2 : 1/iak + &pshufb ("xmm2","xmm3"); # 2 = 1/iak + &pxor ("xmm2","xmm0"); # 2 = io + &movdqa ("xmm3","xmm5"); # 3 : 1/jak + &pshufb ("xmm3","xmm4"); # 3 = 1/jak + &pxor ("xmm3","xmm1"); # 3 = jo + &movdqa ("xmm4",&QWP($k_sb1,$const)); # 4 : sbou + &pshufb ("xmm4","xmm2"); # 4 = sbou + &movdqa ("xmm0",&QWP($k_sb1+16,$const));# 0 : sbot + &pshufb ("xmm0","xmm3"); # 0 = sb1t + &pxor ("xmm0","xmm4"); # 0 = sbox output + + # add in smeared stuff + &pxor ("xmm0","xmm7"); + &movdqa ("xmm7","xmm0"); + &ret (); +&function_end_B("_vpaes_schedule_round"); + +## +## .aes_schedule_transform +## +## Linear-transform %xmm0 according to tables at (%ebx) +## +## Output in %xmm0 +## Clobbers %xmm1, %xmm2 +## +&function_begin_B("_vpaes_schedule_transform"); + &movdqa ("xmm2",&QWP($k_s0F,$const)); + &movdqa ("xmm1","xmm2"); + &pandn ("xmm1","xmm0"); + &psrld ("xmm1",4); + &pand ("xmm0","xmm2"); + &movdqa ("xmm2",&QWP(0,$base)); + &pshufb ("xmm2","xmm0"); + &movdqa ("xmm0",&QWP(16,$base)); + &pshufb ("xmm0","xmm1"); + &pxor ("xmm0","xmm2"); + &ret (); +&function_end_B("_vpaes_schedule_transform"); + +## +## .aes_schedule_mangle +## +## Mangle xmm0 from (basis-transformed) standard version +## to our version. +## +## On encrypt, +## xor with 0x63 +## multiply by circulant 0,1,1,1 +## apply shiftrows transform +## +## On decrypt, +## xor with 0x63 +## multiply by "inverse mixcolumns" circulant E,B,D,9 +## deskew +## apply shiftrows transform +## +## +## Writes out to (%edx), and increments or decrements it +## Keeps track of round number mod 4 in %ecx +## Preserves xmm0 +## Clobbers xmm1-xmm5 +## +&function_begin_B("_vpaes_schedule_mangle"); + &movdqa ("xmm4","xmm0"); # save xmm0 for later + &movdqa ("xmm5",&QWP($k_mc_forward,$const)); + &test ($out,$out); + &jnz (&label("schedule_mangle_dec")); + + # encrypting + &add ($key,16); + &pxor ("xmm4",&QWP($k_s63,$const)); + &pshufb ("xmm4","xmm5"); + &movdqa ("xmm3","xmm4"); + &pshufb ("xmm4","xmm5"); + &pxor ("xmm3","xmm4"); + &pshufb ("xmm4","xmm5"); + &pxor ("xmm3","xmm4"); + + &jmp (&label("schedule_mangle_both")); + +&set_label("schedule_mangle_dec",16); + # inverse mix columns + &movdqa ("xmm2",&QWP($k_s0F,$const)); + &lea ($inp,&DWP($k_dksd,$const)); + &movdqa ("xmm1","xmm2"); + &pandn ("xmm1","xmm4"); + &psrld ("xmm1",4); # 1 = hi + &pand ("xmm4","xmm2"); # 4 = lo + + &movdqa ("xmm2",&QWP(0,$inp)); + &pshufb ("xmm2","xmm4"); + &movdqa ("xmm3",&QWP(0x10,$inp)); + &pshufb ("xmm3","xmm1"); + &pxor ("xmm3","xmm2"); + &pshufb ("xmm3","xmm5"); + + &movdqa ("xmm2",&QWP(0x20,$inp)); + &pshufb ("xmm2","xmm4"); + &pxor ("xmm2","xmm3"); + &movdqa ("xmm3",&QWP(0x30,$inp)); + &pshufb ("xmm3","xmm1"); + &pxor ("xmm3","xmm2"); + &pshufb ("xmm3","xmm5"); + + &movdqa ("xmm2",&QWP(0x40,$inp)); + &pshufb ("xmm2","xmm4"); + &pxor ("xmm2","xmm3"); + &movdqa ("xmm3",&QWP(0x50,$inp)); + &pshufb ("xmm3","xmm1"); + &pxor ("xmm3","xmm2"); + &pshufb ("xmm3","xmm5"); + + &movdqa ("xmm2",&QWP(0x60,$inp)); + &pshufb ("xmm2","xmm4"); + &pxor ("xmm2","xmm3"); + &movdqa ("xmm3",&QWP(0x70,$inp)); + &pshufb ("xmm3","xmm1"); + &pxor ("xmm3","xmm2"); + + &add ($key,-16); + +&set_label("schedule_mangle_both"); + &movdqa ("xmm1",&QWP($k_sr,$const,$magic)); + &pshufb ("xmm3","xmm1"); + &add ($magic,-16); + &and ($magic,0x30); + &movdqu (&QWP(0,$key),"xmm3"); + &ret (); +&function_end_B("_vpaes_schedule_mangle"); + +# +# Interface to OpenSSL +# +&function_begin("${PREFIX}_set_encrypt_key"); + &mov ($inp,&wparam(0)); # inp + &lea ($base,&DWP(-56,"esp")); + &mov ($round,&wparam(1)); # bits + &and ($base,-16); + &mov ($key,&wparam(2)); # key + &xchg ($base,"esp"); # alloca + &mov (&DWP(48,"esp"),$base); + + &mov ($base,$round); + &shr ($base,5); + &add ($base,5); + &mov (&DWP(240,$key),$base); # AES_KEY->rounds = nbits/32+5; + &mov ($magic,0x30); + &mov ($out,0); + + &lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point"))); + &call ("_vpaes_schedule_core"); +&set_label("pic_point"); + + &mov ("esp",&DWP(48,"esp")); + &xor ("eax","eax"); +&function_end("${PREFIX}_set_encrypt_key"); + +&function_begin("${PREFIX}_set_decrypt_key"); + &mov ($inp,&wparam(0)); # inp + &lea ($base,&DWP(-56,"esp")); + &mov ($round,&wparam(1)); # bits + &and ($base,-16); + &mov ($key,&wparam(2)); # key + &xchg ($base,"esp"); # alloca + &mov (&DWP(48,"esp"),$base); + + &mov ($base,$round); + &shr ($base,5); + &add ($base,5); + &mov (&DWP(240,$key),$base); # AES_KEY->rounds = nbits/32+5; + &shl ($base,4); + &lea ($key,&DWP(16,$key,$base)); + + &mov ($out,1); + &mov ($magic,$round); + &shr ($magic,1); + &and ($magic,32); + &xor ($magic,32); # nbist==192?0:32; + + &lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point"))); + &call ("_vpaes_schedule_core"); +&set_label("pic_point"); + + &mov ("esp",&DWP(48,"esp")); + &xor ("eax","eax"); +&function_end("${PREFIX}_set_decrypt_key"); + +&function_begin("${PREFIX}_encrypt"); + &lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point"))); + &call ("_vpaes_preheat"); +&set_label("pic_point"); + &mov ($inp,&wparam(0)); # inp + &lea ($base,&DWP(-56,"esp")); + &mov ($out,&wparam(1)); # out + &and ($base,-16); + &mov ($key,&wparam(2)); # key + &xchg ($base,"esp"); # alloca + &mov (&DWP(48,"esp"),$base); + + &movdqu ("xmm0",&QWP(0,$inp)); + &call ("_vpaes_encrypt_core"); + &movdqu (&QWP(0,$out),"xmm0"); + + &mov ("esp",&DWP(48,"esp")); +&function_end("${PREFIX}_encrypt"); + +&function_begin("${PREFIX}_decrypt"); + &lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point"))); + &call ("_vpaes_preheat"); +&set_label("pic_point"); + &mov ($inp,&wparam(0)); # inp + &lea ($base,&DWP(-56,"esp")); + &mov ($out,&wparam(1)); # out + &and ($base,-16); + &mov ($key,&wparam(2)); # key + &xchg ($base,"esp"); # alloca + &mov (&DWP(48,"esp"),$base); + + &movdqu ("xmm0",&QWP(0,$inp)); + &call ("_vpaes_decrypt_core"); + &movdqu (&QWP(0,$out),"xmm0"); + + &mov ("esp",&DWP(48,"esp")); +&function_end("${PREFIX}_decrypt"); + +&function_begin("${PREFIX}_cbc_encrypt"); + &mov ($inp,&wparam(0)); # inp + &mov ($out,&wparam(1)); # out + &mov ($round,&wparam(2)); # len + &mov ($key,&wparam(3)); # key + &sub ($round,16); + &jc (&label("cbc_abort")); + &lea ($base,&DWP(-56,"esp")); + &mov ($const,&wparam(4)); # ivp + &and ($base,-16); + &mov ($magic,&wparam(5)); # enc + &xchg ($base,"esp"); # alloca + &movdqu ("xmm1",&QWP(0,$const)); # load IV + &sub ($out,$inp); + &mov (&DWP(48,"esp"),$base); + + &mov (&DWP(0,"esp"),$out); # save out + &mov (&DWP(4,"esp"),$key) # save key + &mov (&DWP(8,"esp"),$const); # save ivp + &mov ($out,$round); # $out works as $len + + &lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point"))); + &call ("_vpaes_preheat"); +&set_label("pic_point"); + &cmp ($magic,0); + &je (&label("cbc_dec_loop")); + &jmp (&label("cbc_enc_loop")); + +&set_label("cbc_enc_loop",16); + &movdqu ("xmm0",&QWP(0,$inp)); # load input + &pxor ("xmm0","xmm1"); # inp^=iv + &call ("_vpaes_encrypt_core"); + &mov ($base,&DWP(0,"esp")); # restore out + &mov ($key,&DWP(4,"esp")); # restore key + &movdqa ("xmm1","xmm0"); + &movdqu (&QWP(0,$base,$inp),"xmm0"); # write output + &lea ($inp,&DWP(16,$inp)); + &sub ($out,16); + &jnc (&label("cbc_enc_loop")); + &jmp (&label("cbc_done")); + +&set_label("cbc_dec_loop",16); + &movdqu ("xmm0",&QWP(0,$inp)); # load input + &movdqa (&QWP(16,"esp"),"xmm1"); # save IV + &movdqa (&QWP(32,"esp"),"xmm0"); # save future IV + &call ("_vpaes_decrypt_core"); + &mov ($base,&DWP(0,"esp")); # restore out + &mov ($key,&DWP(4,"esp")); # restore key + &pxor ("xmm0",&QWP(16,"esp")); # out^=iv + &movdqa ("xmm1",&QWP(32,"esp")); # load next IV + &movdqu (&QWP(0,$base,$inp),"xmm0"); # write output + &lea ($inp,&DWP(16,$inp)); + &sub ($out,16); + &jnc (&label("cbc_dec_loop")); + +&set_label("cbc_done"); + &mov ($base,&DWP(8,"esp")); # restore ivp + &mov ("esp",&DWP(48,"esp")); + &movdqu (&QWP(0,$base),"xmm1"); # write IV +&set_label("cbc_abort"); +&function_end("${PREFIX}_cbc_encrypt"); + +&asm_finish(); + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/vpaes-x86_64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/vpaes-x86_64.pl new file mode 100644 index 000000000..33d293e62 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/asm/vpaes-x86_64.pl @@ -0,0 +1,1241 @@ +#! /usr/bin/env perl +# Copyright 2011-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +###################################################################### +## Constant-time SSSE3 AES core implementation. +## version 0.1 +## +## By Mike Hamburg (Stanford University), 2009 +## Public domain. +## +## For details see http://shiftleft.org/papers/vector_aes/ and +## http://crypto.stanford.edu/vpaes/. + +###################################################################### +# September 2011. +# +# Interface to OpenSSL as "almost" drop-in replacement for +# aes-x86_64.pl. "Almost" refers to the fact that AES_cbc_encrypt +# doesn't handle partial vectors (doesn't have to if called from +# EVP only). "Drop-in" implies that this module doesn't share key +# schedule structure with the original nor does it make assumption +# about its alignment... +# +# Performance summary. aes-x86_64.pl column lists large-block CBC +# encrypt/decrypt/with-hyper-threading-off(*) results in cycles per +# byte processed with 128-bit key, and vpaes-x86_64.pl column - +# [also large-block CBC] encrypt/decrypt. +# +# aes-x86_64.pl vpaes-x86_64.pl +# +# Core 2(**) 29.6/41.1/14.3 21.9/25.2(***) +# Nehalem 29.6/40.3/14.6 10.0/11.8 +# Atom 57.3/74.2/32.1 60.9/77.2(***) +# Silvermont 52.7/64.0/19.5 48.8/60.8(***) +# Goldmont 38.9/49.0/17.8 10.6/12.6 +# +# (*) "Hyper-threading" in the context refers rather to cache shared +# among multiple cores, than to specifically Intel HTT. As vast +# majority of contemporary cores share cache, slower code path +# is common place. In other words "with-hyper-threading-off" +# results are presented mostly for reference purposes. +# +# (**) "Core 2" refers to initial 65nm design, a.k.a. Conroe. +# +# (***) Less impressive improvement on Core 2 and Atom is due to slow +# pshufb, yet it's respectable +36%/62% improvement on Core 2 +# (as implied, over "hyper-threading-safe" code path). +# +# + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +*STDOUT=*OUT; + +$PREFIX="vpaes"; + +$code.=<<___; +.text + +## +## _aes_encrypt_core +## +## AES-encrypt %xmm0. +## +## Inputs: +## %xmm0 = input +## %xmm9-%xmm15 as in _vpaes_preheat +## (%rdx) = scheduled keys +## +## Output in %xmm0 +## Clobbers %xmm1-%xmm5, %r9, %r10, %r11, %rax +## Preserves %xmm6 - %xmm8 so you get some local vectors +## +## +.type _vpaes_encrypt_core,\@abi-omnipotent +.align 16 +_vpaes_encrypt_core: +.cfi_startproc + mov %rdx, %r9 + mov \$16, %r11 + mov 240(%rdx),%eax + movdqa %xmm9, %xmm1 + movdqa .Lk_ipt(%rip), %xmm2 # iptlo + pandn %xmm0, %xmm1 + movdqu (%r9), %xmm5 # round0 key + psrld \$4, %xmm1 + pand %xmm9, %xmm0 + pshufb %xmm0, %xmm2 + movdqa .Lk_ipt+16(%rip), %xmm0 # ipthi + pshufb %xmm1, %xmm0 + pxor %xmm5, %xmm2 + add \$16, %r9 + pxor %xmm2, %xmm0 + lea .Lk_mc_backward(%rip),%r10 + jmp .Lenc_entry + +.align 16 +.Lenc_loop: + # middle of middle round + movdqa %xmm13, %xmm4 # 4 : sb1u + movdqa %xmm12, %xmm0 # 0 : sb1t + pshufb %xmm2, %xmm4 # 4 = sb1u + pshufb %xmm3, %xmm0 # 0 = sb1t + pxor %xmm5, %xmm4 # 4 = sb1u + k + movdqa %xmm15, %xmm5 # 4 : sb2u + pxor %xmm4, %xmm0 # 0 = A + movdqa -0x40(%r11,%r10), %xmm1 # .Lk_mc_forward[] + pshufb %xmm2, %xmm5 # 4 = sb2u + movdqa (%r11,%r10), %xmm4 # .Lk_mc_backward[] + movdqa %xmm14, %xmm2 # 2 : sb2t + pshufb %xmm3, %xmm2 # 2 = sb2t + movdqa %xmm0, %xmm3 # 3 = A + pxor %xmm5, %xmm2 # 2 = 2A + pshufb %xmm1, %xmm0 # 0 = B + add \$16, %r9 # next key + pxor %xmm2, %xmm0 # 0 = 2A+B + pshufb %xmm4, %xmm3 # 3 = D + add \$16, %r11 # next mc + pxor %xmm0, %xmm3 # 3 = 2A+B+D + pshufb %xmm1, %xmm0 # 0 = 2B+C + and \$0x30, %r11 # ... mod 4 + sub \$1,%rax # nr-- + pxor %xmm3, %xmm0 # 0 = 2A+3B+C+D + +.Lenc_entry: + # top of round + movdqa %xmm9, %xmm1 # 1 : i + movdqa %xmm11, %xmm5 # 2 : a/k + pandn %xmm0, %xmm1 # 1 = i<<4 + psrld \$4, %xmm1 # 1 = i + pand %xmm9, %xmm0 # 0 = k + pshufb %xmm0, %xmm5 # 2 = a/k + movdqa %xmm10, %xmm3 # 3 : 1/i + pxor %xmm1, %xmm0 # 0 = j + pshufb %xmm1, %xmm3 # 3 = 1/i + movdqa %xmm10, %xmm4 # 4 : 1/j + pxor %xmm5, %xmm3 # 3 = iak = 1/i + a/k + pshufb %xmm0, %xmm4 # 4 = 1/j + movdqa %xmm10, %xmm2 # 2 : 1/iak + pxor %xmm5, %xmm4 # 4 = jak = 1/j + a/k + pshufb %xmm3, %xmm2 # 2 = 1/iak + movdqa %xmm10, %xmm3 # 3 : 1/jak + pxor %xmm0, %xmm2 # 2 = io + pshufb %xmm4, %xmm3 # 3 = 1/jak + movdqu (%r9), %xmm5 + pxor %xmm1, %xmm3 # 3 = jo + jnz .Lenc_loop + + # middle of last round + movdqa -0x60(%r10), %xmm4 # 3 : sbou .Lk_sbo + movdqa -0x50(%r10), %xmm0 # 0 : sbot .Lk_sbo+16 + pshufb %xmm2, %xmm4 # 4 = sbou + pxor %xmm5, %xmm4 # 4 = sb1u + k + pshufb %xmm3, %xmm0 # 0 = sb1t + movdqa 0x40(%r11,%r10), %xmm1 # .Lk_sr[] + pxor %xmm4, %xmm0 # 0 = A + pshufb %xmm1, %xmm0 + ret +.cfi_endproc +.size _vpaes_encrypt_core,.-_vpaes_encrypt_core + +## +## Decryption core +## +## Same API as encryption core. +## +.type _vpaes_decrypt_core,\@abi-omnipotent +.align 16 +_vpaes_decrypt_core: +.cfi_startproc + mov %rdx, %r9 # load key + mov 240(%rdx),%eax + movdqa %xmm9, %xmm1 + movdqa .Lk_dipt(%rip), %xmm2 # iptlo + pandn %xmm0, %xmm1 + mov %rax, %r11 + psrld \$4, %xmm1 + movdqu (%r9), %xmm5 # round0 key + shl \$4, %r11 + pand %xmm9, %xmm0 + pshufb %xmm0, %xmm2 + movdqa .Lk_dipt+16(%rip), %xmm0 # ipthi + xor \$0x30, %r11 + lea .Lk_dsbd(%rip),%r10 + pshufb %xmm1, %xmm0 + and \$0x30, %r11 + pxor %xmm5, %xmm2 + movdqa .Lk_mc_forward+48(%rip), %xmm5 + pxor %xmm2, %xmm0 + add \$16, %r9 + add %r10, %r11 + jmp .Ldec_entry + +.align 16 +.Ldec_loop: +## +## Inverse mix columns +## + movdqa -0x20(%r10),%xmm4 # 4 : sb9u + movdqa -0x10(%r10),%xmm1 # 0 : sb9t + pshufb %xmm2, %xmm4 # 4 = sb9u + pshufb %xmm3, %xmm1 # 0 = sb9t + pxor %xmm4, %xmm0 + movdqa 0x00(%r10),%xmm4 # 4 : sbdu + pxor %xmm1, %xmm0 # 0 = ch + movdqa 0x10(%r10),%xmm1 # 0 : sbdt + + pshufb %xmm2, %xmm4 # 4 = sbdu + pshufb %xmm5, %xmm0 # MC ch + pshufb %xmm3, %xmm1 # 0 = sbdt + pxor %xmm4, %xmm0 # 4 = ch + movdqa 0x20(%r10),%xmm4 # 4 : sbbu + pxor %xmm1, %xmm0 # 0 = ch + movdqa 0x30(%r10),%xmm1 # 0 : sbbt + + pshufb %xmm2, %xmm4 # 4 = sbbu + pshufb %xmm5, %xmm0 # MC ch + pshufb %xmm3, %xmm1 # 0 = sbbt + pxor %xmm4, %xmm0 # 4 = ch + movdqa 0x40(%r10),%xmm4 # 4 : sbeu + pxor %xmm1, %xmm0 # 0 = ch + movdqa 0x50(%r10),%xmm1 # 0 : sbet + + pshufb %xmm2, %xmm4 # 4 = sbeu + pshufb %xmm5, %xmm0 # MC ch + pshufb %xmm3, %xmm1 # 0 = sbet + pxor %xmm4, %xmm0 # 4 = ch + add \$16, %r9 # next round key + palignr \$12, %xmm5, %xmm5 + pxor %xmm1, %xmm0 # 0 = ch + sub \$1,%rax # nr-- + +.Ldec_entry: + # top of round + movdqa %xmm9, %xmm1 # 1 : i + pandn %xmm0, %xmm1 # 1 = i<<4 + movdqa %xmm11, %xmm2 # 2 : a/k + psrld \$4, %xmm1 # 1 = i + pand %xmm9, %xmm0 # 0 = k + pshufb %xmm0, %xmm2 # 2 = a/k + movdqa %xmm10, %xmm3 # 3 : 1/i + pxor %xmm1, %xmm0 # 0 = j + pshufb %xmm1, %xmm3 # 3 = 1/i + movdqa %xmm10, %xmm4 # 4 : 1/j + pxor %xmm2, %xmm3 # 3 = iak = 1/i + a/k + pshufb %xmm0, %xmm4 # 4 = 1/j + pxor %xmm2, %xmm4 # 4 = jak = 1/j + a/k + movdqa %xmm10, %xmm2 # 2 : 1/iak + pshufb %xmm3, %xmm2 # 2 = 1/iak + movdqa %xmm10, %xmm3 # 3 : 1/jak + pxor %xmm0, %xmm2 # 2 = io + pshufb %xmm4, %xmm3 # 3 = 1/jak + movdqu (%r9), %xmm0 + pxor %xmm1, %xmm3 # 3 = jo + jnz .Ldec_loop + + # middle of last round + movdqa 0x60(%r10), %xmm4 # 3 : sbou + pshufb %xmm2, %xmm4 # 4 = sbou + pxor %xmm0, %xmm4 # 4 = sb1u + k + movdqa 0x70(%r10), %xmm0 # 0 : sbot + movdqa -0x160(%r11), %xmm2 # .Lk_sr-.Lk_dsbd=-0x160 + pshufb %xmm3, %xmm0 # 0 = sb1t + pxor %xmm4, %xmm0 # 0 = A + pshufb %xmm2, %xmm0 + ret +.cfi_endproc +.size _vpaes_decrypt_core,.-_vpaes_decrypt_core + +######################################################## +## ## +## AES key schedule ## +## ## +######################################################## +.type _vpaes_schedule_core,\@abi-omnipotent +.align 16 +_vpaes_schedule_core: +.cfi_startproc + # rdi = key + # rsi = size in bits + # rdx = buffer + # rcx = direction. 0=encrypt, 1=decrypt + + call _vpaes_preheat # load the tables + movdqa .Lk_rcon(%rip), %xmm8 # load rcon + movdqu (%rdi), %xmm0 # load key (unaligned) + + # input transform + movdqa %xmm0, %xmm3 + lea .Lk_ipt(%rip), %r11 + call _vpaes_schedule_transform + movdqa %xmm0, %xmm7 + + lea .Lk_sr(%rip),%r10 + test %rcx, %rcx + jnz .Lschedule_am_decrypting + + # encrypting, output zeroth round key after transform + movdqu %xmm0, (%rdx) + jmp .Lschedule_go + +.Lschedule_am_decrypting: + # decrypting, output zeroth round key after shiftrows + movdqa (%r8,%r10),%xmm1 + pshufb %xmm1, %xmm3 + movdqu %xmm3, (%rdx) + xor \$0x30, %r8 + +.Lschedule_go: + cmp \$192, %esi + ja .Lschedule_256 + je .Lschedule_192 + # 128: fall though + +## +## .schedule_128 +## +## 128-bit specific part of key schedule. +## +## This schedule is really simple, because all its parts +## are accomplished by the subroutines. +## +.Lschedule_128: + mov \$10, %esi + +.Loop_schedule_128: + call _vpaes_schedule_round + dec %rsi + jz .Lschedule_mangle_last + call _vpaes_schedule_mangle # write output + jmp .Loop_schedule_128 + +## +## .aes_schedule_192 +## +## 192-bit specific part of key schedule. +## +## The main body of this schedule is the same as the 128-bit +## schedule, but with more smearing. The long, high side is +## stored in %xmm7 as before, and the short, low side is in +## the high bits of %xmm6. +## +## This schedule is somewhat nastier, however, because each +## round produces 192 bits of key material, or 1.5 round keys. +## Therefore, on each cycle we do 2 rounds and produce 3 round +## keys. +## +.align 16 +.Lschedule_192: + movdqu 8(%rdi),%xmm0 # load key part 2 (very unaligned) + call _vpaes_schedule_transform # input transform + movdqa %xmm0, %xmm6 # save short part + pxor %xmm4, %xmm4 # clear 4 + movhlps %xmm4, %xmm6 # clobber low side with zeros + mov \$4, %esi + +.Loop_schedule_192: + call _vpaes_schedule_round + palignr \$8,%xmm6,%xmm0 + call _vpaes_schedule_mangle # save key n + call _vpaes_schedule_192_smear + call _vpaes_schedule_mangle # save key n+1 + call _vpaes_schedule_round + dec %rsi + jz .Lschedule_mangle_last + call _vpaes_schedule_mangle # save key n+2 + call _vpaes_schedule_192_smear + jmp .Loop_schedule_192 + +## +## .aes_schedule_256 +## +## 256-bit specific part of key schedule. +## +## The structure here is very similar to the 128-bit +## schedule, but with an additional "low side" in +## %xmm6. The low side's rounds are the same as the +## high side's, except no rcon and no rotation. +## +.align 16 +.Lschedule_256: + movdqu 16(%rdi),%xmm0 # load key part 2 (unaligned) + call _vpaes_schedule_transform # input transform + mov \$7, %esi + +.Loop_schedule_256: + call _vpaes_schedule_mangle # output low result + movdqa %xmm0, %xmm6 # save cur_lo in xmm6 + + # high round + call _vpaes_schedule_round + dec %rsi + jz .Lschedule_mangle_last + call _vpaes_schedule_mangle + + # low round. swap xmm7 and xmm6 + pshufd \$0xFF, %xmm0, %xmm0 + movdqa %xmm7, %xmm5 + movdqa %xmm6, %xmm7 + call _vpaes_schedule_low_round + movdqa %xmm5, %xmm7 + + jmp .Loop_schedule_256 + + +## +## .aes_schedule_mangle_last +## +## Mangler for last round of key schedule +## Mangles %xmm0 +## when encrypting, outputs out(%xmm0) ^ 63 +## when decrypting, outputs unskew(%xmm0) +## +## Always called right before return... jumps to cleanup and exits +## +.align 16 +.Lschedule_mangle_last: + # schedule last round key from xmm0 + lea .Lk_deskew(%rip),%r11 # prepare to deskew + test %rcx, %rcx + jnz .Lschedule_mangle_last_dec + + # encrypting + movdqa (%r8,%r10),%xmm1 + pshufb %xmm1, %xmm0 # output permute + lea .Lk_opt(%rip), %r11 # prepare to output transform + add \$32, %rdx + +.Lschedule_mangle_last_dec: + add \$-16, %rdx + pxor .Lk_s63(%rip), %xmm0 + call _vpaes_schedule_transform # output transform + movdqu %xmm0, (%rdx) # save last key + + # cleanup + pxor %xmm0, %xmm0 + pxor %xmm1, %xmm1 + pxor %xmm2, %xmm2 + pxor %xmm3, %xmm3 + pxor %xmm4, %xmm4 + pxor %xmm5, %xmm5 + pxor %xmm6, %xmm6 + pxor %xmm7, %xmm7 + ret +.cfi_endproc +.size _vpaes_schedule_core,.-_vpaes_schedule_core + +## +## .aes_schedule_192_smear +## +## Smear the short, low side in the 192-bit key schedule. +## +## Inputs: +## %xmm7: high side, b a x y +## %xmm6: low side, d c 0 0 +## %xmm13: 0 +## +## Outputs: +## %xmm6: b+c+d b+c 0 0 +## %xmm0: b+c+d b+c b a +## +.type _vpaes_schedule_192_smear,\@abi-omnipotent +.align 16 +_vpaes_schedule_192_smear: +.cfi_startproc + pshufd \$0x80, %xmm6, %xmm1 # d c 0 0 -> c 0 0 0 + pshufd \$0xFE, %xmm7, %xmm0 # b a _ _ -> b b b a + pxor %xmm1, %xmm6 # -> c+d c 0 0 + pxor %xmm1, %xmm1 + pxor %xmm0, %xmm6 # -> b+c+d b+c b a + movdqa %xmm6, %xmm0 + movhlps %xmm1, %xmm6 # clobber low side with zeros + ret +.cfi_endproc +.size _vpaes_schedule_192_smear,.-_vpaes_schedule_192_smear + +## +## .aes_schedule_round +## +## Runs one main round of the key schedule on %xmm0, %xmm7 +## +## Specifically, runs subbytes on the high dword of %xmm0 +## then rotates it by one byte and xors into the low dword of +## %xmm7. +## +## Adds rcon from low byte of %xmm8, then rotates %xmm8 for +## next rcon. +## +## Smears the dwords of %xmm7 by xoring the low into the +## second low, result into third, result into highest. +## +## Returns results in %xmm7 = %xmm0. +## Clobbers %xmm1-%xmm4, %r11. +## +.type _vpaes_schedule_round,\@abi-omnipotent +.align 16 +_vpaes_schedule_round: +.cfi_startproc + # extract rcon from xmm8 + pxor %xmm1, %xmm1 + palignr \$15, %xmm8, %xmm1 + palignr \$15, %xmm8, %xmm8 + pxor %xmm1, %xmm7 + + # rotate + pshufd \$0xFF, %xmm0, %xmm0 + palignr \$1, %xmm0, %xmm0 + + # fall through... + + # low round: same as high round, but no rotation and no rcon. +_vpaes_schedule_low_round: + # smear xmm7 + movdqa %xmm7, %xmm1 + pslldq \$4, %xmm7 + pxor %xmm1, %xmm7 + movdqa %xmm7, %xmm1 + pslldq \$8, %xmm7 + pxor %xmm1, %xmm7 + pxor .Lk_s63(%rip), %xmm7 + + # subbytes + movdqa %xmm9, %xmm1 + pandn %xmm0, %xmm1 + psrld \$4, %xmm1 # 1 = i + pand %xmm9, %xmm0 # 0 = k + movdqa %xmm11, %xmm2 # 2 : a/k + pshufb %xmm0, %xmm2 # 2 = a/k + pxor %xmm1, %xmm0 # 0 = j + movdqa %xmm10, %xmm3 # 3 : 1/i + pshufb %xmm1, %xmm3 # 3 = 1/i + pxor %xmm2, %xmm3 # 3 = iak = 1/i + a/k + movdqa %xmm10, %xmm4 # 4 : 1/j + pshufb %xmm0, %xmm4 # 4 = 1/j + pxor %xmm2, %xmm4 # 4 = jak = 1/j + a/k + movdqa %xmm10, %xmm2 # 2 : 1/iak + pshufb %xmm3, %xmm2 # 2 = 1/iak + pxor %xmm0, %xmm2 # 2 = io + movdqa %xmm10, %xmm3 # 3 : 1/jak + pshufb %xmm4, %xmm3 # 3 = 1/jak + pxor %xmm1, %xmm3 # 3 = jo + movdqa %xmm13, %xmm4 # 4 : sbou + pshufb %xmm2, %xmm4 # 4 = sbou + movdqa %xmm12, %xmm0 # 0 : sbot + pshufb %xmm3, %xmm0 # 0 = sb1t + pxor %xmm4, %xmm0 # 0 = sbox output + + # add in smeared stuff + pxor %xmm7, %xmm0 + movdqa %xmm0, %xmm7 + ret +.cfi_endproc +.size _vpaes_schedule_round,.-_vpaes_schedule_round + +## +## .aes_schedule_transform +## +## Linear-transform %xmm0 according to tables at (%r11) +## +## Requires that %xmm9 = 0x0F0F... as in preheat +## Output in %xmm0 +## Clobbers %xmm1, %xmm2 +## +.type _vpaes_schedule_transform,\@abi-omnipotent +.align 16 +_vpaes_schedule_transform: +.cfi_startproc + movdqa %xmm9, %xmm1 + pandn %xmm0, %xmm1 + psrld \$4, %xmm1 + pand %xmm9, %xmm0 + movdqa (%r11), %xmm2 # lo + pshufb %xmm0, %xmm2 + movdqa 16(%r11), %xmm0 # hi + pshufb %xmm1, %xmm0 + pxor %xmm2, %xmm0 + ret +.cfi_endproc +.size _vpaes_schedule_transform,.-_vpaes_schedule_transform + +## +## .aes_schedule_mangle +## +## Mangle xmm0 from (basis-transformed) standard version +## to our version. +## +## On encrypt, +## xor with 0x63 +## multiply by circulant 0,1,1,1 +## apply shiftrows transform +## +## On decrypt, +## xor with 0x63 +## multiply by "inverse mixcolumns" circulant E,B,D,9 +## deskew +## apply shiftrows transform +## +## +## Writes out to (%rdx), and increments or decrements it +## Keeps track of round number mod 4 in %r8 +## Preserves xmm0 +## Clobbers xmm1-xmm5 +## +.type _vpaes_schedule_mangle,\@abi-omnipotent +.align 16 +_vpaes_schedule_mangle: +.cfi_startproc + movdqa %xmm0, %xmm4 # save xmm0 for later + movdqa .Lk_mc_forward(%rip),%xmm5 + test %rcx, %rcx + jnz .Lschedule_mangle_dec + + # encrypting + add \$16, %rdx + pxor .Lk_s63(%rip),%xmm4 + pshufb %xmm5, %xmm4 + movdqa %xmm4, %xmm3 + pshufb %xmm5, %xmm4 + pxor %xmm4, %xmm3 + pshufb %xmm5, %xmm4 + pxor %xmm4, %xmm3 + + jmp .Lschedule_mangle_both +.align 16 +.Lschedule_mangle_dec: + # inverse mix columns + lea .Lk_dksd(%rip),%r11 + movdqa %xmm9, %xmm1 + pandn %xmm4, %xmm1 + psrld \$4, %xmm1 # 1 = hi + pand %xmm9, %xmm4 # 4 = lo + + movdqa 0x00(%r11), %xmm2 + pshufb %xmm4, %xmm2 + movdqa 0x10(%r11), %xmm3 + pshufb %xmm1, %xmm3 + pxor %xmm2, %xmm3 + pshufb %xmm5, %xmm3 + + movdqa 0x20(%r11), %xmm2 + pshufb %xmm4, %xmm2 + pxor %xmm3, %xmm2 + movdqa 0x30(%r11), %xmm3 + pshufb %xmm1, %xmm3 + pxor %xmm2, %xmm3 + pshufb %xmm5, %xmm3 + + movdqa 0x40(%r11), %xmm2 + pshufb %xmm4, %xmm2 + pxor %xmm3, %xmm2 + movdqa 0x50(%r11), %xmm3 + pshufb %xmm1, %xmm3 + pxor %xmm2, %xmm3 + pshufb %xmm5, %xmm3 + + movdqa 0x60(%r11), %xmm2 + pshufb %xmm4, %xmm2 + pxor %xmm3, %xmm2 + movdqa 0x70(%r11), %xmm3 + pshufb %xmm1, %xmm3 + pxor %xmm2, %xmm3 + + add \$-16, %rdx + +.Lschedule_mangle_both: + movdqa (%r8,%r10),%xmm1 + pshufb %xmm1,%xmm3 + add \$-16, %r8 + and \$0x30, %r8 + movdqu %xmm3, (%rdx) + ret +.cfi_endproc +.size _vpaes_schedule_mangle,.-_vpaes_schedule_mangle + +# +# Interface to OpenSSL +# +.globl ${PREFIX}_set_encrypt_key +.type ${PREFIX}_set_encrypt_key,\@function,3 +.align 16 +${PREFIX}_set_encrypt_key: +.cfi_startproc +___ +$code.=<<___ if ($win64); + lea -0xb8(%rsp),%rsp + movaps %xmm6,0x10(%rsp) + movaps %xmm7,0x20(%rsp) + movaps %xmm8,0x30(%rsp) + movaps %xmm9,0x40(%rsp) + movaps %xmm10,0x50(%rsp) + movaps %xmm11,0x60(%rsp) + movaps %xmm12,0x70(%rsp) + movaps %xmm13,0x80(%rsp) + movaps %xmm14,0x90(%rsp) + movaps %xmm15,0xa0(%rsp) +.Lenc_key_body: +___ +$code.=<<___; + mov %esi,%eax + shr \$5,%eax + add \$5,%eax + mov %eax,240(%rdx) # AES_KEY->rounds = nbits/32+5; + + mov \$0,%ecx + mov \$0x30,%r8d + call _vpaes_schedule_core +___ +$code.=<<___ if ($win64); + movaps 0x10(%rsp),%xmm6 + movaps 0x20(%rsp),%xmm7 + movaps 0x30(%rsp),%xmm8 + movaps 0x40(%rsp),%xmm9 + movaps 0x50(%rsp),%xmm10 + movaps 0x60(%rsp),%xmm11 + movaps 0x70(%rsp),%xmm12 + movaps 0x80(%rsp),%xmm13 + movaps 0x90(%rsp),%xmm14 + movaps 0xa0(%rsp),%xmm15 + lea 0xb8(%rsp),%rsp +.Lenc_key_epilogue: +___ +$code.=<<___; + xor %eax,%eax + ret +.cfi_endproc +.size ${PREFIX}_set_encrypt_key,.-${PREFIX}_set_encrypt_key + +.globl ${PREFIX}_set_decrypt_key +.type ${PREFIX}_set_decrypt_key,\@function,3 +.align 16 +${PREFIX}_set_decrypt_key: +.cfi_startproc +___ +$code.=<<___ if ($win64); + lea -0xb8(%rsp),%rsp + movaps %xmm6,0x10(%rsp) + movaps %xmm7,0x20(%rsp) + movaps %xmm8,0x30(%rsp) + movaps %xmm9,0x40(%rsp) + movaps %xmm10,0x50(%rsp) + movaps %xmm11,0x60(%rsp) + movaps %xmm12,0x70(%rsp) + movaps %xmm13,0x80(%rsp) + movaps %xmm14,0x90(%rsp) + movaps %xmm15,0xa0(%rsp) +.Ldec_key_body: +___ +$code.=<<___; + mov %esi,%eax + shr \$5,%eax + add \$5,%eax + mov %eax,240(%rdx) # AES_KEY->rounds = nbits/32+5; + shl \$4,%eax + lea 16(%rdx,%rax),%rdx + + mov \$1,%ecx + mov %esi,%r8d + shr \$1,%r8d + and \$32,%r8d + xor \$32,%r8d # nbits==192?0:32 + call _vpaes_schedule_core +___ +$code.=<<___ if ($win64); + movaps 0x10(%rsp),%xmm6 + movaps 0x20(%rsp),%xmm7 + movaps 0x30(%rsp),%xmm8 + movaps 0x40(%rsp),%xmm9 + movaps 0x50(%rsp),%xmm10 + movaps 0x60(%rsp),%xmm11 + movaps 0x70(%rsp),%xmm12 + movaps 0x80(%rsp),%xmm13 + movaps 0x90(%rsp),%xmm14 + movaps 0xa0(%rsp),%xmm15 + lea 0xb8(%rsp),%rsp +.Ldec_key_epilogue: +___ +$code.=<<___; + xor %eax,%eax + ret +.cfi_endproc +.size ${PREFIX}_set_decrypt_key,.-${PREFIX}_set_decrypt_key + +.globl ${PREFIX}_encrypt +.type ${PREFIX}_encrypt,\@function,3 +.align 16 +${PREFIX}_encrypt: +.cfi_startproc +___ +$code.=<<___ if ($win64); + lea -0xb8(%rsp),%rsp + movaps %xmm6,0x10(%rsp) + movaps %xmm7,0x20(%rsp) + movaps %xmm8,0x30(%rsp) + movaps %xmm9,0x40(%rsp) + movaps %xmm10,0x50(%rsp) + movaps %xmm11,0x60(%rsp) + movaps %xmm12,0x70(%rsp) + movaps %xmm13,0x80(%rsp) + movaps %xmm14,0x90(%rsp) + movaps %xmm15,0xa0(%rsp) +.Lenc_body: +___ +$code.=<<___; + movdqu (%rdi),%xmm0 + call _vpaes_preheat + call _vpaes_encrypt_core + movdqu %xmm0,(%rsi) +___ +$code.=<<___ if ($win64); + movaps 0x10(%rsp),%xmm6 + movaps 0x20(%rsp),%xmm7 + movaps 0x30(%rsp),%xmm8 + movaps 0x40(%rsp),%xmm9 + movaps 0x50(%rsp),%xmm10 + movaps 0x60(%rsp),%xmm11 + movaps 0x70(%rsp),%xmm12 + movaps 0x80(%rsp),%xmm13 + movaps 0x90(%rsp),%xmm14 + movaps 0xa0(%rsp),%xmm15 + lea 0xb8(%rsp),%rsp +.Lenc_epilogue: +___ +$code.=<<___; + ret +.cfi_endproc +.size ${PREFIX}_encrypt,.-${PREFIX}_encrypt + +.globl ${PREFIX}_decrypt +.type ${PREFIX}_decrypt,\@function,3 +.align 16 +${PREFIX}_decrypt: +.cfi_startproc +___ +$code.=<<___ if ($win64); + lea -0xb8(%rsp),%rsp + movaps %xmm6,0x10(%rsp) + movaps %xmm7,0x20(%rsp) + movaps %xmm8,0x30(%rsp) + movaps %xmm9,0x40(%rsp) + movaps %xmm10,0x50(%rsp) + movaps %xmm11,0x60(%rsp) + movaps %xmm12,0x70(%rsp) + movaps %xmm13,0x80(%rsp) + movaps %xmm14,0x90(%rsp) + movaps %xmm15,0xa0(%rsp) +.Ldec_body: +___ +$code.=<<___; + movdqu (%rdi),%xmm0 + call _vpaes_preheat + call _vpaes_decrypt_core + movdqu %xmm0,(%rsi) +___ +$code.=<<___ if ($win64); + movaps 0x10(%rsp),%xmm6 + movaps 0x20(%rsp),%xmm7 + movaps 0x30(%rsp),%xmm8 + movaps 0x40(%rsp),%xmm9 + movaps 0x50(%rsp),%xmm10 + movaps 0x60(%rsp),%xmm11 + movaps 0x70(%rsp),%xmm12 + movaps 0x80(%rsp),%xmm13 + movaps 0x90(%rsp),%xmm14 + movaps 0xa0(%rsp),%xmm15 + lea 0xb8(%rsp),%rsp +.Ldec_epilogue: +___ +$code.=<<___; + ret +.cfi_endproc +.size ${PREFIX}_decrypt,.-${PREFIX}_decrypt +___ +{ +my ($inp,$out,$len,$key,$ivp,$enc)=("%rdi","%rsi","%rdx","%rcx","%r8","%r9"); +# void AES_cbc_encrypt (const void char *inp, unsigned char *out, +# size_t length, const AES_KEY *key, +# unsigned char *ivp,const int enc); +$code.=<<___; +.globl ${PREFIX}_cbc_encrypt +.type ${PREFIX}_cbc_encrypt,\@function,6 +.align 16 +${PREFIX}_cbc_encrypt: +.cfi_startproc + xchg $key,$len +___ +($len,$key)=($key,$len); +$code.=<<___; + sub \$16,$len + jc .Lcbc_abort +___ +$code.=<<___ if ($win64); + lea -0xb8(%rsp),%rsp + movaps %xmm6,0x10(%rsp) + movaps %xmm7,0x20(%rsp) + movaps %xmm8,0x30(%rsp) + movaps %xmm9,0x40(%rsp) + movaps %xmm10,0x50(%rsp) + movaps %xmm11,0x60(%rsp) + movaps %xmm12,0x70(%rsp) + movaps %xmm13,0x80(%rsp) + movaps %xmm14,0x90(%rsp) + movaps %xmm15,0xa0(%rsp) +.Lcbc_body: +___ +$code.=<<___; + movdqu ($ivp),%xmm6 # load IV + sub $inp,$out + call _vpaes_preheat + cmp \$0,${enc}d + je .Lcbc_dec_loop + jmp .Lcbc_enc_loop +.align 16 +.Lcbc_enc_loop: + movdqu ($inp),%xmm0 + pxor %xmm6,%xmm0 + call _vpaes_encrypt_core + movdqa %xmm0,%xmm6 + movdqu %xmm0,($out,$inp) + lea 16($inp),$inp + sub \$16,$len + jnc .Lcbc_enc_loop + jmp .Lcbc_done +.align 16 +.Lcbc_dec_loop: + movdqu ($inp),%xmm0 + movdqa %xmm0,%xmm7 + call _vpaes_decrypt_core + pxor %xmm6,%xmm0 + movdqa %xmm7,%xmm6 + movdqu %xmm0,($out,$inp) + lea 16($inp),$inp + sub \$16,$len + jnc .Lcbc_dec_loop +.Lcbc_done: + movdqu %xmm6,($ivp) # save IV +___ +$code.=<<___ if ($win64); + movaps 0x10(%rsp),%xmm6 + movaps 0x20(%rsp),%xmm7 + movaps 0x30(%rsp),%xmm8 + movaps 0x40(%rsp),%xmm9 + movaps 0x50(%rsp),%xmm10 + movaps 0x60(%rsp),%xmm11 + movaps 0x70(%rsp),%xmm12 + movaps 0x80(%rsp),%xmm13 + movaps 0x90(%rsp),%xmm14 + movaps 0xa0(%rsp),%xmm15 + lea 0xb8(%rsp),%rsp +.Lcbc_epilogue: +___ +$code.=<<___; +.Lcbc_abort: + ret +.cfi_endproc +.size ${PREFIX}_cbc_encrypt,.-${PREFIX}_cbc_encrypt +___ +} +$code.=<<___; +## +## _aes_preheat +## +## Fills register %r10 -> .aes_consts (so you can -fPIC) +## and %xmm9-%xmm15 as specified below. +## +.type _vpaes_preheat,\@abi-omnipotent +.align 16 +_vpaes_preheat: +.cfi_startproc + lea .Lk_s0F(%rip), %r10 + movdqa -0x20(%r10), %xmm10 # .Lk_inv + movdqa -0x10(%r10), %xmm11 # .Lk_inv+16 + movdqa 0x00(%r10), %xmm9 # .Lk_s0F + movdqa 0x30(%r10), %xmm13 # .Lk_sb1 + movdqa 0x40(%r10), %xmm12 # .Lk_sb1+16 + movdqa 0x50(%r10), %xmm15 # .Lk_sb2 + movdqa 0x60(%r10), %xmm14 # .Lk_sb2+16 + ret +.cfi_endproc +.size _vpaes_preheat,.-_vpaes_preheat +######################################################## +## ## +## Constants ## +## ## +######################################################## +.type _vpaes_consts,\@object +.align 64 +_vpaes_consts: +.Lk_inv: # inv, inva + .quad 0x0E05060F0D080180, 0x040703090A0B0C02 + .quad 0x01040A060F0B0780, 0x030D0E0C02050809 + +.Lk_s0F: # s0F + .quad 0x0F0F0F0F0F0F0F0F, 0x0F0F0F0F0F0F0F0F + +.Lk_ipt: # input transform (lo, hi) + .quad 0xC2B2E8985A2A7000, 0xCABAE09052227808 + .quad 0x4C01307D317C4D00, 0xCD80B1FCB0FDCC81 + +.Lk_sb1: # sb1u, sb1t + .quad 0xB19BE18FCB503E00, 0xA5DF7A6E142AF544 + .quad 0x3618D415FAE22300, 0x3BF7CCC10D2ED9EF +.Lk_sb2: # sb2u, sb2t + .quad 0xE27A93C60B712400, 0x5EB7E955BC982FCD + .quad 0x69EB88400AE12900, 0xC2A163C8AB82234A +.Lk_sbo: # sbou, sbot + .quad 0xD0D26D176FBDC700, 0x15AABF7AC502A878 + .quad 0xCFE474A55FBB6A00, 0x8E1E90D1412B35FA + +.Lk_mc_forward: # mc_forward + .quad 0x0407060500030201, 0x0C0F0E0D080B0A09 + .quad 0x080B0A0904070605, 0x000302010C0F0E0D + .quad 0x0C0F0E0D080B0A09, 0x0407060500030201 + .quad 0x000302010C0F0E0D, 0x080B0A0904070605 + +.Lk_mc_backward:# mc_backward + .quad 0x0605040702010003, 0x0E0D0C0F0A09080B + .quad 0x020100030E0D0C0F, 0x0A09080B06050407 + .quad 0x0E0D0C0F0A09080B, 0x0605040702010003 + .quad 0x0A09080B06050407, 0x020100030E0D0C0F + +.Lk_sr: # sr + .quad 0x0706050403020100, 0x0F0E0D0C0B0A0908 + .quad 0x030E09040F0A0500, 0x0B06010C07020D08 + .quad 0x0F060D040B020900, 0x070E050C030A0108 + .quad 0x0B0E0104070A0D00, 0x0306090C0F020508 + +.Lk_rcon: # rcon + .quad 0x1F8391B9AF9DEEB6, 0x702A98084D7C7D81 + +.Lk_s63: # s63: all equal to 0x63 transformed + .quad 0x5B5B5B5B5B5B5B5B, 0x5B5B5B5B5B5B5B5B + +.Lk_opt: # output transform + .quad 0xFF9F4929D6B66000, 0xF7974121DEBE6808 + .quad 0x01EDBD5150BCEC00, 0xE10D5DB1B05C0CE0 + +.Lk_deskew: # deskew tables: inverts the sbox's "skew" + .quad 0x07E4A34047A4E300, 0x1DFEB95A5DBEF91A + .quad 0x5F36B5DC83EA6900, 0x2841C2ABF49D1E77 + +## +## Decryption stuff +## Key schedule constants +## +.Lk_dksd: # decryption key schedule: invskew x*D + .quad 0xFEB91A5DA3E44700, 0x0740E3A45A1DBEF9 + .quad 0x41C277F4B5368300, 0x5FDC69EAAB289D1E +.Lk_dksb: # decryption key schedule: invskew x*B + .quad 0x9A4FCA1F8550D500, 0x03D653861CC94C99 + .quad 0x115BEDA7B6FC4A00, 0xD993256F7E3482C8 +.Lk_dkse: # decryption key schedule: invskew x*E + 0x63 + .quad 0xD5031CCA1FC9D600, 0x53859A4C994F5086 + .quad 0xA23196054FDC7BE8, 0xCD5EF96A20B31487 +.Lk_dks9: # decryption key schedule: invskew x*9 + .quad 0xB6116FC87ED9A700, 0x4AED933482255BFC + .quad 0x4576516227143300, 0x8BB89FACE9DAFDCE + +## +## Decryption stuff +## Round function constants +## +.Lk_dipt: # decryption input transform + .quad 0x0F505B040B545F00, 0x154A411E114E451A + .quad 0x86E383E660056500, 0x12771772F491F194 + +.Lk_dsb9: # decryption sbox output *9*u, *9*t + .quad 0x851C03539A86D600, 0xCAD51F504F994CC9 + .quad 0xC03B1789ECD74900, 0x725E2C9EB2FBA565 +.Lk_dsbd: # decryption sbox output *D*u, *D*t + .quad 0x7D57CCDFE6B1A200, 0xF56E9B13882A4439 + .quad 0x3CE2FAF724C6CB00, 0x2931180D15DEEFD3 +.Lk_dsbb: # decryption sbox output *B*u, *B*t + .quad 0xD022649296B44200, 0x602646F6B0F2D404 + .quad 0xC19498A6CD596700, 0xF3FF0C3E3255AA6B +.Lk_dsbe: # decryption sbox output *E*u, *E*t + .quad 0x46F2929626D4D000, 0x2242600464B4F6B0 + .quad 0x0C55A6CDFFAAC100, 0x9467F36B98593E32 +.Lk_dsbo: # decryption sbox final output + .quad 0x1387EA537EF94000, 0xC7AA6DB9D4943E2D + .quad 0x12D7560F93441D00, 0xCA4B8159D8C58E9C +.asciz "Vector Permutation AES for x86_64/SSSE3, Mike Hamburg (Stanford University)" +.align 64 +.size _vpaes_consts,.-_vpaes_consts +___ + +if ($win64) { +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type se_handler,\@abi-omnipotent +.align 16 +se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lin_prologue + + lea 16(%rax),%rsi # %xmm save area + lea 512($context),%rdi # &context.Xmm6 + mov \$20,%ecx # 10*sizeof(%xmm0)/sizeof(%rax) + .long 0xa548f3fc # cld; rep movsq + lea 0xb8(%rax),%rax # adjust stack pointer + +.Lin_prologue: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$`1232/8`,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size se_handler,.-se_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_${PREFIX}_set_encrypt_key + .rva .LSEH_end_${PREFIX}_set_encrypt_key + .rva .LSEH_info_${PREFIX}_set_encrypt_key + + .rva .LSEH_begin_${PREFIX}_set_decrypt_key + .rva .LSEH_end_${PREFIX}_set_decrypt_key + .rva .LSEH_info_${PREFIX}_set_decrypt_key + + .rva .LSEH_begin_${PREFIX}_encrypt + .rva .LSEH_end_${PREFIX}_encrypt + .rva .LSEH_info_${PREFIX}_encrypt + + .rva .LSEH_begin_${PREFIX}_decrypt + .rva .LSEH_end_${PREFIX}_decrypt + .rva .LSEH_info_${PREFIX}_decrypt + + .rva .LSEH_begin_${PREFIX}_cbc_encrypt + .rva .LSEH_end_${PREFIX}_cbc_encrypt + .rva .LSEH_info_${PREFIX}_cbc_encrypt + +.section .xdata +.align 8 +.LSEH_info_${PREFIX}_set_encrypt_key: + .byte 9,0,0,0 + .rva se_handler + .rva .Lenc_key_body,.Lenc_key_epilogue # HandlerData[] +.LSEH_info_${PREFIX}_set_decrypt_key: + .byte 9,0,0,0 + .rva se_handler + .rva .Ldec_key_body,.Ldec_key_epilogue # HandlerData[] +.LSEH_info_${PREFIX}_encrypt: + .byte 9,0,0,0 + .rva se_handler + .rva .Lenc_body,.Lenc_epilogue # HandlerData[] +.LSEH_info_${PREFIX}_decrypt: + .byte 9,0,0,0 + .rva se_handler + .rva .Ldec_body,.Ldec_epilogue # HandlerData[] +.LSEH_info_${PREFIX}_cbc_encrypt: + .byte 9,0,0,0 + .rva se_handler + .rva .Lcbc_body,.Lcbc_epilogue # HandlerData[] +___ +} + +$code =~ s/\`([^\`]*)\`/eval($1)/gem; + +print $code; + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aes/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/build.info new file mode 100644 index 000000000..0f0486364 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aes/build.info @@ -0,0 +1,64 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + aes_misc.c aes_ecb.c aes_cfb.c aes_ofb.c \ + aes_ige.c aes_wrap.c {- $target{aes_asm_src} -} + +GENERATE[aes-ia64.s]=asm/aes-ia64.S + +GENERATE[aes-586.s]=asm/aes-586.pl \ + $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) +DEPEND[aes-586.s]=../perlasm/x86asm.pl +GENERATE[vpaes-x86.s]=asm/vpaes-x86.pl \ + $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) +DEPEND[vpaes-586.s]=../perlasm/x86asm.pl +GENERATE[aesni-x86.s]=asm/aesni-x86.pl \ + $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) +DEPEND[aesni-586.s]=../perlasm/x86asm.pl + +GENERATE[aes-x86_64.s]=asm/aes-x86_64.pl $(PERLASM_SCHEME) +GENERATE[vpaes-x86_64.s]=asm/vpaes-x86_64.pl $(PERLASM_SCHEME) +GENERATE[bsaes-x86_64.s]=asm/bsaes-x86_64.pl $(PERLASM_SCHEME) +GENERATE[aesni-x86_64.s]=asm/aesni-x86_64.pl $(PERLASM_SCHEME) +GENERATE[aesni-sha1-x86_64.s]=asm/aesni-sha1-x86_64.pl $(PERLASM_SCHEME) +GENERATE[aesni-sha256-x86_64.s]=asm/aesni-sha256-x86_64.pl $(PERLASM_SCHEME) +GENERATE[aesni-mb-x86_64.s]=asm/aesni-mb-x86_64.pl $(PERLASM_SCHEME) + +GENERATE[aes-sparcv9.S]=asm/aes-sparcv9.pl $(PERLASM_SCHEME) +INCLUDE[aes-sparcv9.o]=.. +GENERATE[aest4-sparcv9.S]=asm/aest4-sparcv9.pl $(PERLASM_SCHEME) +INCLUDE[aest4-sparcv9.o]=.. +DEPEND[aest4-sparcv9.S]=../perlasm/sparcv9_modes.pl +GENERATE[aesfx-sparcv9.S]=asm/aesfx-sparcv9.pl $(PERLASM_SCHEME) +INCLUDE[aesfx-sparcv9.o]=.. + +GENERATE[aes-ppc.s]=asm/aes-ppc.pl $(PERLASM_SCHEME) +GENERATE[vpaes-ppc.s]=asm/vpaes-ppc.pl $(PERLASM_SCHEME) +GENERATE[aesp8-ppc.s]=asm/aesp8-ppc.pl $(PERLASM_SCHEME) + +GENERATE[aes-parisc.s]=asm/aes-parisc.pl $(PERLASM_SCHEME) + +GENERATE[aes-mips.S]=asm/aes-mips.pl $(PERLASM_SCHEME) +INCLUDE[aes-mips.o]=.. + +GENERATE[aesv8-armx.S]=asm/aesv8-armx.pl $(PERLASM_SCHEME) +INCLUDE[aesv8-armx.o]=.. +GENERATE[vpaes-armv8.S]=asm/vpaes-armv8.pl $(PERLASM_SCHEME) + +GENERATE[aes-armv4.S]=asm/aes-armv4.pl $(PERLASM_SCHEME) +INCLUDE[aes-armv4.o]=.. +GENERATE[bsaes-armv7.S]=asm/bsaes-armv7.pl $(PERLASM_SCHEME) +INCLUDE[bsaes-armv7.o]=.. + +GENERATE[aes-s390x.S]=asm/aes-s390x.pl $(PERLASM_SCHEME) +INCLUDE[aes-s390x.o]=.. + +BEGINRAW[Makefile] +##### AES assembler implementations + +# GNU make "catch all" +{- $builddir -}/aes-%.S: {- $sourcedir -}/asm/aes-%.pl + CC="$(CC)" $(PERL) $< $(PERLASM_SCHEME) $@ +{- $builddir -}/bsaes-%.S: {- $sourcedir -}/asm/bsaes-%.pl + CC="$(CC)" $(PERL) $< $(PERLASM_SCHEME) $@ + +ENDRAW[Makefile] diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/alphacpuid.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/alphacpuid.pl new file mode 100644 index 000000000..6c7fd4c9d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/alphacpuid.pl @@ -0,0 +1,257 @@ +#! /usr/bin/env perl +# Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +$output = pop; +open STDOUT,">$output"; + +print <<'___'; +.text + +.set noat + +.globl OPENSSL_cpuid_setup +.ent OPENSSL_cpuid_setup +OPENSSL_cpuid_setup: + .frame $30,0,$26 + .prologue 0 + ret ($26) +.end OPENSSL_cpuid_setup + +.globl OPENSSL_wipe_cpu +.ent OPENSSL_wipe_cpu +OPENSSL_wipe_cpu: + .frame $30,0,$26 + .prologue 0 + clr $1 + clr $2 + clr $3 + clr $4 + clr $5 + clr $6 + clr $7 + clr $8 + clr $16 + clr $17 + clr $18 + clr $19 + clr $20 + clr $21 + clr $22 + clr $23 + clr $24 + clr $25 + clr $27 + clr $at + clr $29 + fclr $f0 + fclr $f1 + fclr $f10 + fclr $f11 + fclr $f12 + fclr $f13 + fclr $f14 + fclr $f15 + fclr $f16 + fclr $f17 + fclr $f18 + fclr $f19 + fclr $f20 + fclr $f21 + fclr $f22 + fclr $f23 + fclr $f24 + fclr $f25 + fclr $f26 + fclr $f27 + fclr $f28 + fclr $f29 + fclr $f30 + mov $sp,$0 + ret ($26) +.end OPENSSL_wipe_cpu + +.globl OPENSSL_atomic_add +.ent OPENSSL_atomic_add +OPENSSL_atomic_add: + .frame $30,0,$26 + .prologue 0 +1: ldl_l $0,0($16) + addl $0,$17,$1 + stl_c $1,0($16) + beq $1,1b + addl $0,$17,$0 + ret ($26) +.end OPENSSL_atomic_add + +.globl OPENSSL_rdtsc +.ent OPENSSL_rdtsc +OPENSSL_rdtsc: + .frame $30,0,$26 + .prologue 0 + rpcc $0 + ret ($26) +.end OPENSSL_rdtsc + +.globl OPENSSL_cleanse +.ent OPENSSL_cleanse +OPENSSL_cleanse: + .frame $30,0,$26 + .prologue 0 + beq $17,.Ldone + and $16,7,$0 + bic $17,7,$at + beq $at,.Little + beq $0,.Laligned + +.Little: + subq $0,8,$0 + ldq_u $1,0($16) + mov $16,$2 +.Lalign: + mskbl $1,$16,$1 + lda $16,1($16) + subq $17,1,$17 + addq $0,1,$0 + beq $17,.Lout + bne $0,.Lalign +.Lout: stq_u $1,0($2) + beq $17,.Ldone + bic $17,7,$at + beq $at,.Little + +.Laligned: + stq $31,0($16) + subq $17,8,$17 + lda $16,8($16) + bic $17,7,$at + bne $at,.Laligned + bne $17,.Little +.Ldone: ret ($26) +.end OPENSSL_cleanse + +.globl CRYPTO_memcmp +.ent CRYPTO_memcmp +CRYPTO_memcmp: + .frame $30,0,$26 + .prologue 0 + xor $0,$0,$0 + beq $18,.Lno_data + + xor $1,$1,$1 + nop +.Loop_cmp: + ldq_u $2,0($16) + subq $18,1,$18 + ldq_u $3,0($17) + extbl $2,$16,$2 + lda $16,1($16) + extbl $3,$17,$3 + lda $17,1($17) + xor $3,$2,$2 + or $2,$0,$0 + bne $18,.Loop_cmp + + subq $31,$0,$0 + srl $0,63,$0 +.Lno_data: + ret ($26) +.end CRYPTO_memcmp +___ +{ +my ($out,$cnt,$max)=("\$16","\$17","\$18"); +my ($tick,$lasttick)=("\$19","\$20"); +my ($diff,$lastdiff)=("\$21","\$22"); +my ($v0,$ra,$sp,$zero)=("\$0","\$26","\$30","\$31"); + +print <<___; +.globl OPENSSL_instrument_bus +.ent OPENSSL_instrument_bus +OPENSSL_instrument_bus: + .frame $sp,0,$ra + .prologue 0 + mov $cnt,$v0 + + rpcc $lasttick + mov 0,$diff + + ecb ($out) + ldl_l $tick,0($out) + addl $diff,$tick,$tick + mov $tick,$diff + stl_c $tick,0($out) + stl $diff,0($out) + +.Loop: rpcc $tick + subq $tick,$lasttick,$diff + mov $tick,$lasttick + + ecb ($out) + ldl_l $tick,0($out) + addl $diff,$tick,$tick + mov $tick,$diff + stl_c $tick,0($out) + stl $diff,0($out) + + subl $cnt,1,$cnt + lda $out,4($out) + bne $cnt,.Loop + + ret ($ra) +.end OPENSSL_instrument_bus + +.globl OPENSSL_instrument_bus2 +.ent OPENSSL_instrument_bus2 +OPENSSL_instrument_bus2: + .frame $sp,0,$ra + .prologue 0 + mov $cnt,$v0 + + rpcc $lasttick + mov 0,$diff + + ecb ($out) + ldl_l $tick,0($out) + addl $diff,$tick,$tick + mov $tick,$diff + stl_c $tick,0($out) + stl $diff,0($out) + + rpcc $tick + subq $tick,$lasttick,$diff + mov $tick,$lasttick + mov $diff,$lastdiff +.Loop2: + ecb ($out) + ldl_l $tick,0($out) + addl $diff,$tick,$tick + mov $tick,$diff + stl_c $tick,0($out) + stl $diff,0($out) + + subl $max,1,$max + beq $max,.Ldone2 + + rpcc $tick + subq $tick,$lasttick,$diff + mov $tick,$lasttick + subq $lastdiff,$diff,$tick + mov $diff,$lastdiff + cmovne $tick,1,$tick + subl $cnt,$tick,$cnt + s4addq $tick,$out,$out + bne $cnt,.Loop2 + +.Ldone2: + subl $v0,$cnt,$v0 + ret ($ra) +.end OPENSSL_instrument_bus2 +___ +} + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aria/aria.c b/trunk/3rdparty/openssl-1.1-fit/crypto/aria/aria.c new file mode 100644 index 000000000..293bcc72b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aria/aria.c @@ -0,0 +1,1212 @@ +/* + * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Copyright (C) 2017 National Security Research Institute. All Rights Reserved. + * + * Information for ARIA + * http://210.104.33.10/ARIA/index-e.html (English) + * http://seed.kisa.or.kr/ (Korean) + * + * Public domain version is distributed above. + */ + +#include +#include "internal/aria.h" + +#include +#include + +#ifndef OPENSSL_SMALL_FOOTPRINT + +/* Begin macro */ + +/* rotation */ +#define rotl32(v, r) (((uint32_t)(v) << (r)) | ((uint32_t)(v) >> (32 - r))) +#define rotr32(v, r) (((uint32_t)(v) >> (r)) | ((uint32_t)(v) << (32 - r))) + +#define bswap32(v) \ + (((v) << 24) ^ ((v) >> 24) ^ \ + (((v) & 0x0000ff00) << 8) ^ (((v) & 0x00ff0000) >> 8)) + +#define GET_U8_BE(X, Y) ((uint8_t)((X) >> ((3 - Y) * 8))) +#define GET_U32_BE(X, Y) ( \ + ((uint32_t)((const uint8_t *)(X))[Y * 4 ] << 24) ^ \ + ((uint32_t)((const uint8_t *)(X))[Y * 4 + 1] << 16) ^ \ + ((uint32_t)((const uint8_t *)(X))[Y * 4 + 2] << 8) ^ \ + ((uint32_t)((const uint8_t *)(X))[Y * 4 + 3] ) ) + +#define PUT_U32_BE(DEST, IDX, VAL) \ + do { \ + ((uint8_t *)(DEST))[IDX * 4 ] = GET_U8_BE(VAL, 0); \ + ((uint8_t *)(DEST))[IDX * 4 + 1] = GET_U8_BE(VAL, 1); \ + ((uint8_t *)(DEST))[IDX * 4 + 2] = GET_U8_BE(VAL, 2); \ + ((uint8_t *)(DEST))[IDX * 4 + 3] = GET_U8_BE(VAL, 3); \ + } while(0) + +#define MAKE_U32(V0, V1, V2, V3) ( \ + ((uint32_t)((uint8_t)(V0)) << 24) | \ + ((uint32_t)((uint8_t)(V1)) << 16) | \ + ((uint32_t)((uint8_t)(V2)) << 8) | \ + ((uint32_t)((uint8_t)(V3)) ) ) + +/* End Macro*/ + +/* Key Constant + * 128bit : 0, 1, 2 + * 192bit : 1, 2, 3(0) + * 256bit : 2, 3(0), 4(1) + */ +static const uint32_t Key_RC[5][4] = { + { 0x517cc1b7, 0x27220a94, 0xfe13abe8, 0xfa9a6ee0 }, + { 0x6db14acc, 0x9e21c820, 0xff28b1d5, 0xef5de2b0 }, + { 0xdb92371d, 0x2126e970, 0x03249775, 0x04e8c90e }, + { 0x517cc1b7, 0x27220a94, 0xfe13abe8, 0xfa9a6ee0 }, + { 0x6db14acc, 0x9e21c820, 0xff28b1d5, 0xef5de2b0 } +}; + +/* 32bit expanded s-box */ +static const uint32_t S1[256] = { + 0x00636363, 0x007c7c7c, 0x00777777, 0x007b7b7b, + 0x00f2f2f2, 0x006b6b6b, 0x006f6f6f, 0x00c5c5c5, + 0x00303030, 0x00010101, 0x00676767, 0x002b2b2b, + 0x00fefefe, 0x00d7d7d7, 0x00ababab, 0x00767676, + 0x00cacaca, 0x00828282, 0x00c9c9c9, 0x007d7d7d, + 0x00fafafa, 0x00595959, 0x00474747, 0x00f0f0f0, + 0x00adadad, 0x00d4d4d4, 0x00a2a2a2, 0x00afafaf, + 0x009c9c9c, 0x00a4a4a4, 0x00727272, 0x00c0c0c0, + 0x00b7b7b7, 0x00fdfdfd, 0x00939393, 0x00262626, + 0x00363636, 0x003f3f3f, 0x00f7f7f7, 0x00cccccc, + 0x00343434, 0x00a5a5a5, 0x00e5e5e5, 0x00f1f1f1, + 0x00717171, 0x00d8d8d8, 0x00313131, 0x00151515, + 0x00040404, 0x00c7c7c7, 0x00232323, 0x00c3c3c3, + 0x00181818, 0x00969696, 0x00050505, 0x009a9a9a, + 0x00070707, 0x00121212, 0x00808080, 0x00e2e2e2, + 0x00ebebeb, 0x00272727, 0x00b2b2b2, 0x00757575, + 0x00090909, 0x00838383, 0x002c2c2c, 0x001a1a1a, + 0x001b1b1b, 0x006e6e6e, 0x005a5a5a, 0x00a0a0a0, + 0x00525252, 0x003b3b3b, 0x00d6d6d6, 0x00b3b3b3, + 0x00292929, 0x00e3e3e3, 0x002f2f2f, 0x00848484, + 0x00535353, 0x00d1d1d1, 0x00000000, 0x00ededed, + 0x00202020, 0x00fcfcfc, 0x00b1b1b1, 0x005b5b5b, + 0x006a6a6a, 0x00cbcbcb, 0x00bebebe, 0x00393939, + 0x004a4a4a, 0x004c4c4c, 0x00585858, 0x00cfcfcf, + 0x00d0d0d0, 0x00efefef, 0x00aaaaaa, 0x00fbfbfb, + 0x00434343, 0x004d4d4d, 0x00333333, 0x00858585, + 0x00454545, 0x00f9f9f9, 0x00020202, 0x007f7f7f, + 0x00505050, 0x003c3c3c, 0x009f9f9f, 0x00a8a8a8, + 0x00515151, 0x00a3a3a3, 0x00404040, 0x008f8f8f, + 0x00929292, 0x009d9d9d, 0x00383838, 0x00f5f5f5, + 0x00bcbcbc, 0x00b6b6b6, 0x00dadada, 0x00212121, + 0x00101010, 0x00ffffff, 0x00f3f3f3, 0x00d2d2d2, + 0x00cdcdcd, 0x000c0c0c, 0x00131313, 0x00ececec, + 0x005f5f5f, 0x00979797, 0x00444444, 0x00171717, + 0x00c4c4c4, 0x00a7a7a7, 0x007e7e7e, 0x003d3d3d, + 0x00646464, 0x005d5d5d, 0x00191919, 0x00737373, + 0x00606060, 0x00818181, 0x004f4f4f, 0x00dcdcdc, + 0x00222222, 0x002a2a2a, 0x00909090, 0x00888888, + 0x00464646, 0x00eeeeee, 0x00b8b8b8, 0x00141414, + 0x00dedede, 0x005e5e5e, 0x000b0b0b, 0x00dbdbdb, + 0x00e0e0e0, 0x00323232, 0x003a3a3a, 0x000a0a0a, + 0x00494949, 0x00060606, 0x00242424, 0x005c5c5c, + 0x00c2c2c2, 0x00d3d3d3, 0x00acacac, 0x00626262, + 0x00919191, 0x00959595, 0x00e4e4e4, 0x00797979, + 0x00e7e7e7, 0x00c8c8c8, 0x00373737, 0x006d6d6d, + 0x008d8d8d, 0x00d5d5d5, 0x004e4e4e, 0x00a9a9a9, + 0x006c6c6c, 0x00565656, 0x00f4f4f4, 0x00eaeaea, + 0x00656565, 0x007a7a7a, 0x00aeaeae, 0x00080808, + 0x00bababa, 0x00787878, 0x00252525, 0x002e2e2e, + 0x001c1c1c, 0x00a6a6a6, 0x00b4b4b4, 0x00c6c6c6, + 0x00e8e8e8, 0x00dddddd, 0x00747474, 0x001f1f1f, + 0x004b4b4b, 0x00bdbdbd, 0x008b8b8b, 0x008a8a8a, + 0x00707070, 0x003e3e3e, 0x00b5b5b5, 0x00666666, + 0x00484848, 0x00030303, 0x00f6f6f6, 0x000e0e0e, + 0x00616161, 0x00353535, 0x00575757, 0x00b9b9b9, + 0x00868686, 0x00c1c1c1, 0x001d1d1d, 0x009e9e9e, + 0x00e1e1e1, 0x00f8f8f8, 0x00989898, 0x00111111, + 0x00696969, 0x00d9d9d9, 0x008e8e8e, 0x00949494, + 0x009b9b9b, 0x001e1e1e, 0x00878787, 0x00e9e9e9, + 0x00cecece, 0x00555555, 0x00282828, 0x00dfdfdf, + 0x008c8c8c, 0x00a1a1a1, 0x00898989, 0x000d0d0d, + 0x00bfbfbf, 0x00e6e6e6, 0x00424242, 0x00686868, + 0x00414141, 0x00999999, 0x002d2d2d, 0x000f0f0f, + 0x00b0b0b0, 0x00545454, 0x00bbbbbb, 0x00161616 +}; + +static const uint32_t S2[256] = { + 0xe200e2e2, 0x4e004e4e, 0x54005454, 0xfc00fcfc, + 0x94009494, 0xc200c2c2, 0x4a004a4a, 0xcc00cccc, + 0x62006262, 0x0d000d0d, 0x6a006a6a, 0x46004646, + 0x3c003c3c, 0x4d004d4d, 0x8b008b8b, 0xd100d1d1, + 0x5e005e5e, 0xfa00fafa, 0x64006464, 0xcb00cbcb, + 0xb400b4b4, 0x97009797, 0xbe00bebe, 0x2b002b2b, + 0xbc00bcbc, 0x77007777, 0x2e002e2e, 0x03000303, + 0xd300d3d3, 0x19001919, 0x59005959, 0xc100c1c1, + 0x1d001d1d, 0x06000606, 0x41004141, 0x6b006b6b, + 0x55005555, 0xf000f0f0, 0x99009999, 0x69006969, + 0xea00eaea, 0x9c009c9c, 0x18001818, 0xae00aeae, + 0x63006363, 0xdf00dfdf, 0xe700e7e7, 0xbb00bbbb, + 0x00000000, 0x73007373, 0x66006666, 0xfb00fbfb, + 0x96009696, 0x4c004c4c, 0x85008585, 0xe400e4e4, + 0x3a003a3a, 0x09000909, 0x45004545, 0xaa00aaaa, + 0x0f000f0f, 0xee00eeee, 0x10001010, 0xeb00ebeb, + 0x2d002d2d, 0x7f007f7f, 0xf400f4f4, 0x29002929, + 0xac00acac, 0xcf00cfcf, 0xad00adad, 0x91009191, + 0x8d008d8d, 0x78007878, 0xc800c8c8, 0x95009595, + 0xf900f9f9, 0x2f002f2f, 0xce00cece, 0xcd00cdcd, + 0x08000808, 0x7a007a7a, 0x88008888, 0x38003838, + 0x5c005c5c, 0x83008383, 0x2a002a2a, 0x28002828, + 0x47004747, 0xdb00dbdb, 0xb800b8b8, 0xc700c7c7, + 0x93009393, 0xa400a4a4, 0x12001212, 0x53005353, + 0xff00ffff, 0x87008787, 0x0e000e0e, 0x31003131, + 0x36003636, 0x21002121, 0x58005858, 0x48004848, + 0x01000101, 0x8e008e8e, 0x37003737, 0x74007474, + 0x32003232, 0xca00caca, 0xe900e9e9, 0xb100b1b1, + 0xb700b7b7, 0xab00abab, 0x0c000c0c, 0xd700d7d7, + 0xc400c4c4, 0x56005656, 0x42004242, 0x26002626, + 0x07000707, 0x98009898, 0x60006060, 0xd900d9d9, + 0xb600b6b6, 0xb900b9b9, 0x11001111, 0x40004040, + 0xec00ecec, 0x20002020, 0x8c008c8c, 0xbd00bdbd, + 0xa000a0a0, 0xc900c9c9, 0x84008484, 0x04000404, + 0x49004949, 0x23002323, 0xf100f1f1, 0x4f004f4f, + 0x50005050, 0x1f001f1f, 0x13001313, 0xdc00dcdc, + 0xd800d8d8, 0xc000c0c0, 0x9e009e9e, 0x57005757, + 0xe300e3e3, 0xc300c3c3, 0x7b007b7b, 0x65006565, + 0x3b003b3b, 0x02000202, 0x8f008f8f, 0x3e003e3e, + 0xe800e8e8, 0x25002525, 0x92009292, 0xe500e5e5, + 0x15001515, 0xdd00dddd, 0xfd00fdfd, 0x17001717, + 0xa900a9a9, 0xbf00bfbf, 0xd400d4d4, 0x9a009a9a, + 0x7e007e7e, 0xc500c5c5, 0x39003939, 0x67006767, + 0xfe00fefe, 0x76007676, 0x9d009d9d, 0x43004343, + 0xa700a7a7, 0xe100e1e1, 0xd000d0d0, 0xf500f5f5, + 0x68006868, 0xf200f2f2, 0x1b001b1b, 0x34003434, + 0x70007070, 0x05000505, 0xa300a3a3, 0x8a008a8a, + 0xd500d5d5, 0x79007979, 0x86008686, 0xa800a8a8, + 0x30003030, 0xc600c6c6, 0x51005151, 0x4b004b4b, + 0x1e001e1e, 0xa600a6a6, 0x27002727, 0xf600f6f6, + 0x35003535, 0xd200d2d2, 0x6e006e6e, 0x24002424, + 0x16001616, 0x82008282, 0x5f005f5f, 0xda00dada, + 0xe600e6e6, 0x75007575, 0xa200a2a2, 0xef00efef, + 0x2c002c2c, 0xb200b2b2, 0x1c001c1c, 0x9f009f9f, + 0x5d005d5d, 0x6f006f6f, 0x80008080, 0x0a000a0a, + 0x72007272, 0x44004444, 0x9b009b9b, 0x6c006c6c, + 0x90009090, 0x0b000b0b, 0x5b005b5b, 0x33003333, + 0x7d007d7d, 0x5a005a5a, 0x52005252, 0xf300f3f3, + 0x61006161, 0xa100a1a1, 0xf700f7f7, 0xb000b0b0, + 0xd600d6d6, 0x3f003f3f, 0x7c007c7c, 0x6d006d6d, + 0xed00eded, 0x14001414, 0xe000e0e0, 0xa500a5a5, + 0x3d003d3d, 0x22002222, 0xb300b3b3, 0xf800f8f8, + 0x89008989, 0xde00dede, 0x71007171, 0x1a001a1a, + 0xaf00afaf, 0xba00baba, 0xb500b5b5, 0x81008181 +}; + +static const uint32_t X1[256] = { + 0x52520052, 0x09090009, 0x6a6a006a, 0xd5d500d5, + 0x30300030, 0x36360036, 0xa5a500a5, 0x38380038, + 0xbfbf00bf, 0x40400040, 0xa3a300a3, 0x9e9e009e, + 0x81810081, 0xf3f300f3, 0xd7d700d7, 0xfbfb00fb, + 0x7c7c007c, 0xe3e300e3, 0x39390039, 0x82820082, + 0x9b9b009b, 0x2f2f002f, 0xffff00ff, 0x87870087, + 0x34340034, 0x8e8e008e, 0x43430043, 0x44440044, + 0xc4c400c4, 0xdede00de, 0xe9e900e9, 0xcbcb00cb, + 0x54540054, 0x7b7b007b, 0x94940094, 0x32320032, + 0xa6a600a6, 0xc2c200c2, 0x23230023, 0x3d3d003d, + 0xeeee00ee, 0x4c4c004c, 0x95950095, 0x0b0b000b, + 0x42420042, 0xfafa00fa, 0xc3c300c3, 0x4e4e004e, + 0x08080008, 0x2e2e002e, 0xa1a100a1, 0x66660066, + 0x28280028, 0xd9d900d9, 0x24240024, 0xb2b200b2, + 0x76760076, 0x5b5b005b, 0xa2a200a2, 0x49490049, + 0x6d6d006d, 0x8b8b008b, 0xd1d100d1, 0x25250025, + 0x72720072, 0xf8f800f8, 0xf6f600f6, 0x64640064, + 0x86860086, 0x68680068, 0x98980098, 0x16160016, + 0xd4d400d4, 0xa4a400a4, 0x5c5c005c, 0xcccc00cc, + 0x5d5d005d, 0x65650065, 0xb6b600b6, 0x92920092, + 0x6c6c006c, 0x70700070, 0x48480048, 0x50500050, + 0xfdfd00fd, 0xeded00ed, 0xb9b900b9, 0xdada00da, + 0x5e5e005e, 0x15150015, 0x46460046, 0x57570057, + 0xa7a700a7, 0x8d8d008d, 0x9d9d009d, 0x84840084, + 0x90900090, 0xd8d800d8, 0xabab00ab, 0x00000000, + 0x8c8c008c, 0xbcbc00bc, 0xd3d300d3, 0x0a0a000a, + 0xf7f700f7, 0xe4e400e4, 0x58580058, 0x05050005, + 0xb8b800b8, 0xb3b300b3, 0x45450045, 0x06060006, + 0xd0d000d0, 0x2c2c002c, 0x1e1e001e, 0x8f8f008f, + 0xcaca00ca, 0x3f3f003f, 0x0f0f000f, 0x02020002, + 0xc1c100c1, 0xafaf00af, 0xbdbd00bd, 0x03030003, + 0x01010001, 0x13130013, 0x8a8a008a, 0x6b6b006b, + 0x3a3a003a, 0x91910091, 0x11110011, 0x41410041, + 0x4f4f004f, 0x67670067, 0xdcdc00dc, 0xeaea00ea, + 0x97970097, 0xf2f200f2, 0xcfcf00cf, 0xcece00ce, + 0xf0f000f0, 0xb4b400b4, 0xe6e600e6, 0x73730073, + 0x96960096, 0xacac00ac, 0x74740074, 0x22220022, + 0xe7e700e7, 0xadad00ad, 0x35350035, 0x85850085, + 0xe2e200e2, 0xf9f900f9, 0x37370037, 0xe8e800e8, + 0x1c1c001c, 0x75750075, 0xdfdf00df, 0x6e6e006e, + 0x47470047, 0xf1f100f1, 0x1a1a001a, 0x71710071, + 0x1d1d001d, 0x29290029, 0xc5c500c5, 0x89890089, + 0x6f6f006f, 0xb7b700b7, 0x62620062, 0x0e0e000e, + 0xaaaa00aa, 0x18180018, 0xbebe00be, 0x1b1b001b, + 0xfcfc00fc, 0x56560056, 0x3e3e003e, 0x4b4b004b, + 0xc6c600c6, 0xd2d200d2, 0x79790079, 0x20200020, + 0x9a9a009a, 0xdbdb00db, 0xc0c000c0, 0xfefe00fe, + 0x78780078, 0xcdcd00cd, 0x5a5a005a, 0xf4f400f4, + 0x1f1f001f, 0xdddd00dd, 0xa8a800a8, 0x33330033, + 0x88880088, 0x07070007, 0xc7c700c7, 0x31310031, + 0xb1b100b1, 0x12120012, 0x10100010, 0x59590059, + 0x27270027, 0x80800080, 0xecec00ec, 0x5f5f005f, + 0x60600060, 0x51510051, 0x7f7f007f, 0xa9a900a9, + 0x19190019, 0xb5b500b5, 0x4a4a004a, 0x0d0d000d, + 0x2d2d002d, 0xe5e500e5, 0x7a7a007a, 0x9f9f009f, + 0x93930093, 0xc9c900c9, 0x9c9c009c, 0xefef00ef, + 0xa0a000a0, 0xe0e000e0, 0x3b3b003b, 0x4d4d004d, + 0xaeae00ae, 0x2a2a002a, 0xf5f500f5, 0xb0b000b0, + 0xc8c800c8, 0xebeb00eb, 0xbbbb00bb, 0x3c3c003c, + 0x83830083, 0x53530053, 0x99990099, 0x61610061, + 0x17170017, 0x2b2b002b, 0x04040004, 0x7e7e007e, + 0xbaba00ba, 0x77770077, 0xd6d600d6, 0x26260026, + 0xe1e100e1, 0x69690069, 0x14140014, 0x63630063, + 0x55550055, 0x21210021, 0x0c0c000c, 0x7d7d007d +}; + +static const uint32_t X2[256] = { + 0x30303000, 0x68686800, 0x99999900, 0x1b1b1b00, + 0x87878700, 0xb9b9b900, 0x21212100, 0x78787800, + 0x50505000, 0x39393900, 0xdbdbdb00, 0xe1e1e100, + 0x72727200, 0x09090900, 0x62626200, 0x3c3c3c00, + 0x3e3e3e00, 0x7e7e7e00, 0x5e5e5e00, 0x8e8e8e00, + 0xf1f1f100, 0xa0a0a000, 0xcccccc00, 0xa3a3a300, + 0x2a2a2a00, 0x1d1d1d00, 0xfbfbfb00, 0xb6b6b600, + 0xd6d6d600, 0x20202000, 0xc4c4c400, 0x8d8d8d00, + 0x81818100, 0x65656500, 0xf5f5f500, 0x89898900, + 0xcbcbcb00, 0x9d9d9d00, 0x77777700, 0xc6c6c600, + 0x57575700, 0x43434300, 0x56565600, 0x17171700, + 0xd4d4d400, 0x40404000, 0x1a1a1a00, 0x4d4d4d00, + 0xc0c0c000, 0x63636300, 0x6c6c6c00, 0xe3e3e300, + 0xb7b7b700, 0xc8c8c800, 0x64646400, 0x6a6a6a00, + 0x53535300, 0xaaaaaa00, 0x38383800, 0x98989800, + 0x0c0c0c00, 0xf4f4f400, 0x9b9b9b00, 0xededed00, + 0x7f7f7f00, 0x22222200, 0x76767600, 0xafafaf00, + 0xdddddd00, 0x3a3a3a00, 0x0b0b0b00, 0x58585800, + 0x67676700, 0x88888800, 0x06060600, 0xc3c3c300, + 0x35353500, 0x0d0d0d00, 0x01010100, 0x8b8b8b00, + 0x8c8c8c00, 0xc2c2c200, 0xe6e6e600, 0x5f5f5f00, + 0x02020200, 0x24242400, 0x75757500, 0x93939300, + 0x66666600, 0x1e1e1e00, 0xe5e5e500, 0xe2e2e200, + 0x54545400, 0xd8d8d800, 0x10101000, 0xcecece00, + 0x7a7a7a00, 0xe8e8e800, 0x08080800, 0x2c2c2c00, + 0x12121200, 0x97979700, 0x32323200, 0xababab00, + 0xb4b4b400, 0x27272700, 0x0a0a0a00, 0x23232300, + 0xdfdfdf00, 0xefefef00, 0xcacaca00, 0xd9d9d900, + 0xb8b8b800, 0xfafafa00, 0xdcdcdc00, 0x31313100, + 0x6b6b6b00, 0xd1d1d100, 0xadadad00, 0x19191900, + 0x49494900, 0xbdbdbd00, 0x51515100, 0x96969600, + 0xeeeeee00, 0xe4e4e400, 0xa8a8a800, 0x41414100, + 0xdadada00, 0xffffff00, 0xcdcdcd00, 0x55555500, + 0x86868600, 0x36363600, 0xbebebe00, 0x61616100, + 0x52525200, 0xf8f8f800, 0xbbbbbb00, 0x0e0e0e00, + 0x82828200, 0x48484800, 0x69696900, 0x9a9a9a00, + 0xe0e0e000, 0x47474700, 0x9e9e9e00, 0x5c5c5c00, + 0x04040400, 0x4b4b4b00, 0x34343400, 0x15151500, + 0x79797900, 0x26262600, 0xa7a7a700, 0xdedede00, + 0x29292900, 0xaeaeae00, 0x92929200, 0xd7d7d700, + 0x84848400, 0xe9e9e900, 0xd2d2d200, 0xbababa00, + 0x5d5d5d00, 0xf3f3f300, 0xc5c5c500, 0xb0b0b000, + 0xbfbfbf00, 0xa4a4a400, 0x3b3b3b00, 0x71717100, + 0x44444400, 0x46464600, 0x2b2b2b00, 0xfcfcfc00, + 0xebebeb00, 0x6f6f6f00, 0xd5d5d500, 0xf6f6f600, + 0x14141400, 0xfefefe00, 0x7c7c7c00, 0x70707000, + 0x5a5a5a00, 0x7d7d7d00, 0xfdfdfd00, 0x2f2f2f00, + 0x18181800, 0x83838300, 0x16161600, 0xa5a5a500, + 0x91919100, 0x1f1f1f00, 0x05050500, 0x95959500, + 0x74747400, 0xa9a9a900, 0xc1c1c100, 0x5b5b5b00, + 0x4a4a4a00, 0x85858500, 0x6d6d6d00, 0x13131300, + 0x07070700, 0x4f4f4f00, 0x4e4e4e00, 0x45454500, + 0xb2b2b200, 0x0f0f0f00, 0xc9c9c900, 0x1c1c1c00, + 0xa6a6a600, 0xbcbcbc00, 0xececec00, 0x73737300, + 0x90909000, 0x7b7b7b00, 0xcfcfcf00, 0x59595900, + 0x8f8f8f00, 0xa1a1a100, 0xf9f9f900, 0x2d2d2d00, + 0xf2f2f200, 0xb1b1b100, 0x00000000, 0x94949400, + 0x37373700, 0x9f9f9f00, 0xd0d0d000, 0x2e2e2e00, + 0x9c9c9c00, 0x6e6e6e00, 0x28282800, 0x3f3f3f00, + 0x80808000, 0xf0f0f000, 0x3d3d3d00, 0xd3d3d300, + 0x25252500, 0x8a8a8a00, 0xb5b5b500, 0xe7e7e700, + 0x42424200, 0xb3b3b300, 0xc7c7c700, 0xeaeaea00, + 0xf7f7f700, 0x4c4c4c00, 0x11111100, 0x33333300, + 0x03030300, 0xa2a2a200, 0xacacac00, 0x60606000 +}; + +/* Key XOR Layer */ +#define ARIA_ADD_ROUND_KEY(RK, T0, T1, T2, T3) \ + do { \ + (T0) ^= (RK)->u[0]; \ + (T1) ^= (RK)->u[1]; \ + (T2) ^= (RK)->u[2]; \ + (T3) ^= (RK)->u[3]; \ + } while(0) + +/* S-Box Layer 1 + M */ +#define ARIA_SBOX_LAYER1_WITH_PRE_DIFF(T0, T1, T2, T3) \ + do { \ + (T0) = \ + S1[GET_U8_BE(T0, 0)] ^ \ + S2[GET_U8_BE(T0, 1)] ^ \ + X1[GET_U8_BE(T0, 2)] ^ \ + X2[GET_U8_BE(T0, 3)]; \ + (T1) = \ + S1[GET_U8_BE(T1, 0)] ^ \ + S2[GET_U8_BE(T1, 1)] ^ \ + X1[GET_U8_BE(T1, 2)] ^ \ + X2[GET_U8_BE(T1, 3)]; \ + (T2) = \ + S1[GET_U8_BE(T2, 0)] ^ \ + S2[GET_U8_BE(T2, 1)] ^ \ + X1[GET_U8_BE(T2, 2)] ^ \ + X2[GET_U8_BE(T2, 3)]; \ + (T3) = \ + S1[GET_U8_BE(T3, 0)] ^ \ + S2[GET_U8_BE(T3, 1)] ^ \ + X1[GET_U8_BE(T3, 2)] ^ \ + X2[GET_U8_BE(T3, 3)]; \ + } while(0) + +/* S-Box Layer 2 + M */ +#define ARIA_SBOX_LAYER2_WITH_PRE_DIFF(T0, T1, T2, T3) \ + do { \ + (T0) = \ + X1[GET_U8_BE(T0, 0)] ^ \ + X2[GET_U8_BE(T0, 1)] ^ \ + S1[GET_U8_BE(T0, 2)] ^ \ + S2[GET_U8_BE(T0, 3)]; \ + (T1) = \ + X1[GET_U8_BE(T1, 0)] ^ \ + X2[GET_U8_BE(T1, 1)] ^ \ + S1[GET_U8_BE(T1, 2)] ^ \ + S2[GET_U8_BE(T1, 3)]; \ + (T2) = \ + X1[GET_U8_BE(T2, 0)] ^ \ + X2[GET_U8_BE(T2, 1)] ^ \ + S1[GET_U8_BE(T2, 2)] ^ \ + S2[GET_U8_BE(T2, 3)]; \ + (T3) = \ + X1[GET_U8_BE(T3, 0)] ^ \ + X2[GET_U8_BE(T3, 1)] ^ \ + S1[GET_U8_BE(T3, 2)] ^ \ + S2[GET_U8_BE(T3, 3)]; \ + } while(0) + +/* Word-level diffusion */ +#define ARIA_DIFF_WORD(T0,T1,T2,T3) \ + do { \ + (T1) ^= (T2); \ + (T2) ^= (T3); \ + (T0) ^= (T1); \ + \ + (T3) ^= (T1); \ + (T2) ^= (T0); \ + (T1) ^= (T2); \ + } while(0) + +/* Byte-level diffusion */ +#define ARIA_DIFF_BYTE(T0, T1, T2, T3) \ + do { \ + (T1) = (((T1) << 8) & 0xff00ff00) ^ (((T1) >> 8) & 0x00ff00ff); \ + (T2) = rotr32(T2, 16); \ + (T3) = bswap32(T3); \ + } while(0) + +/* Odd round Substitution & Diffusion */ +#define ARIA_SUBST_DIFF_ODD(T0, T1, T2, T3) \ + do { \ + ARIA_SBOX_LAYER1_WITH_PRE_DIFF(T0, T1, T2, T3); \ + ARIA_DIFF_WORD(T0, T1, T2, T3); \ + ARIA_DIFF_BYTE(T0, T1, T2, T3); \ + ARIA_DIFF_WORD(T0, T1, T2, T3); \ + } while(0) + +/* Even round Substitution & Diffusion */ +#define ARIA_SUBST_DIFF_EVEN(T0, T1, T2, T3) \ + do { \ + ARIA_SBOX_LAYER2_WITH_PRE_DIFF(T0, T1, T2, T3); \ + ARIA_DIFF_WORD(T0, T1, T2, T3); \ + ARIA_DIFF_BYTE(T2, T3, T0, T1); \ + ARIA_DIFF_WORD(T0, T1, T2, T3); \ + } while(0) + +/* Q, R Macro expanded ARIA GSRK */ +#define _ARIA_GSRK(RK, X, Y, Q, R) \ + do { \ + (RK)->u[0] = \ + ((X)[0]) ^ \ + (((Y)[((Q) ) % 4]) >> (R)) ^ \ + (((Y)[((Q) + 3) % 4]) << (32 - (R))); \ + (RK)->u[1] = \ + ((X)[1]) ^ \ + (((Y)[((Q) + 1) % 4]) >> (R)) ^ \ + (((Y)[((Q) ) % 4]) << (32 - (R))); \ + (RK)->u[2] = \ + ((X)[2]) ^ \ + (((Y)[((Q) + 2) % 4]) >> (R)) ^ \ + (((Y)[((Q) + 1) % 4]) << (32 - (R))); \ + (RK)->u[3] = \ + ((X)[3]) ^ \ + (((Y)[((Q) + 3) % 4]) >> (R)) ^ \ + (((Y)[((Q) + 2) % 4]) << (32 - (R))); \ + } while(0) + +#define ARIA_GSRK(RK, X, Y, N) _ARIA_GSRK(RK, X, Y, 4 - ((N) / 32), (N) % 32) + +#define ARIA_DEC_DIFF_BYTE(X, Y, TMP, TMP2) \ + do { \ + (TMP) = (X); \ + (TMP2) = rotr32((TMP), 8); \ + (Y) = (TMP2) ^ rotr32((TMP) ^ (TMP2), 16); \ + } while(0) + +void aria_encrypt(const unsigned char *in, unsigned char *out, + const ARIA_KEY *key) +{ + register uint32_t reg0, reg1, reg2, reg3; + int Nr; + const ARIA_u128 *rk; + + if (in == NULL || out == NULL || key == NULL) { + return; + } + + rk = key->rd_key; + Nr = key->rounds; + + if (Nr != 12 && Nr != 14 && Nr != 16) { + return; + } + + reg0 = GET_U32_BE(in, 0); + reg1 = GET_U32_BE(in, 1); + reg2 = GET_U32_BE(in, 2); + reg3 = GET_U32_BE(in, 3); + + ARIA_ADD_ROUND_KEY(rk, reg0, reg1, reg2, reg3); + rk++; + + ARIA_SUBST_DIFF_ODD(reg0, reg1, reg2, reg3); + ARIA_ADD_ROUND_KEY(rk, reg0, reg1, reg2, reg3); + rk++; + + while(Nr -= 2){ + ARIA_SUBST_DIFF_EVEN(reg0, reg1, reg2, reg3); + ARIA_ADD_ROUND_KEY(rk, reg0, reg1, reg2, reg3); + rk++; + + ARIA_SUBST_DIFF_ODD(reg0, reg1, reg2, reg3); + ARIA_ADD_ROUND_KEY(rk, reg0, reg1, reg2, reg3); + rk++; + } + + reg0 = rk->u[0] ^ MAKE_U32( + (uint8_t)(X1[GET_U8_BE(reg0, 0)] ), + (uint8_t)(X2[GET_U8_BE(reg0, 1)] >> 8), + (uint8_t)(S1[GET_U8_BE(reg0, 2)] ), + (uint8_t)(S2[GET_U8_BE(reg0, 3)] )); + reg1 = rk->u[1] ^ MAKE_U32( + (uint8_t)(X1[GET_U8_BE(reg1, 0)] ), + (uint8_t)(X2[GET_U8_BE(reg1, 1)] >> 8), + (uint8_t)(S1[GET_U8_BE(reg1, 2)] ), + (uint8_t)(S2[GET_U8_BE(reg1, 3)] )); + reg2 = rk->u[2] ^ MAKE_U32( + (uint8_t)(X1[GET_U8_BE(reg2, 0)] ), + (uint8_t)(X2[GET_U8_BE(reg2, 1)] >> 8), + (uint8_t)(S1[GET_U8_BE(reg2, 2)] ), + (uint8_t)(S2[GET_U8_BE(reg2, 3)] )); + reg3 = rk->u[3] ^ MAKE_U32( + (uint8_t)(X1[GET_U8_BE(reg3, 0)] ), + (uint8_t)(X2[GET_U8_BE(reg3, 1)] >> 8), + (uint8_t)(S1[GET_U8_BE(reg3, 2)] ), + (uint8_t)(S2[GET_U8_BE(reg3, 3)] )); + + PUT_U32_BE(out, 0, reg0); + PUT_U32_BE(out, 1, reg1); + PUT_U32_BE(out, 2, reg2); + PUT_U32_BE(out, 3, reg3); +} + +int aria_set_encrypt_key(const unsigned char *userKey, const int bits, + ARIA_KEY *key) +{ + register uint32_t reg0, reg1, reg2, reg3; + uint32_t w0[4], w1[4], w2[4], w3[4]; + const uint32_t *ck; + + ARIA_u128 *rk; + int Nr = (bits + 256) / 32; + + if (userKey == NULL || key == NULL) { + return -1; + } + if (bits != 128 && bits != 192 && bits != 256) { + return -2; + } + + rk = key->rd_key; + key->rounds = Nr; + ck = &Key_RC[(bits - 128) / 64][0]; + + w0[0] = GET_U32_BE(userKey, 0); + w0[1] = GET_U32_BE(userKey, 1); + w0[2] = GET_U32_BE(userKey, 2); + w0[3] = GET_U32_BE(userKey, 3); + + reg0 = w0[0] ^ ck[0]; + reg1 = w0[1] ^ ck[1]; + reg2 = w0[2] ^ ck[2]; + reg3 = w0[3] ^ ck[3]; + + ARIA_SUBST_DIFF_ODD(reg0, reg1, reg2, reg3); + + if (bits > 128) { + w1[0] = GET_U32_BE(userKey, 4); + w1[1] = GET_U32_BE(userKey, 5); + if (bits > 192) { + w1[2] = GET_U32_BE(userKey, 6); + w1[3] = GET_U32_BE(userKey, 7); + } + else { + w1[2] = w1[3] = 0; + } + } + else { + w1[0] = w1[1] = w1[2] = w1[3] = 0; + } + + w1[0] ^= reg0; + w1[1] ^= reg1; + w1[2] ^= reg2; + w1[3] ^= reg3; + + reg0 = w1[0]; + reg1 = w1[1]; + reg2 = w1[2]; + reg3 = w1[3]; + + reg0 ^= ck[4]; + reg1 ^= ck[5]; + reg2 ^= ck[6]; + reg3 ^= ck[7]; + + ARIA_SUBST_DIFF_EVEN(reg0, reg1, reg2, reg3); + + reg0 ^= w0[0]; + reg1 ^= w0[1]; + reg2 ^= w0[2]; + reg3 ^= w0[3]; + + w2[0] = reg0; + w2[1] = reg1; + w2[2] = reg2; + w2[3] = reg3; + + reg0 ^= ck[8]; + reg1 ^= ck[9]; + reg2 ^= ck[10]; + reg3 ^= ck[11]; + + ARIA_SUBST_DIFF_ODD(reg0, reg1, reg2, reg3); + + w3[0] = reg0 ^ w1[0]; + w3[1] = reg1 ^ w1[1]; + w3[2] = reg2 ^ w1[2]; + w3[3] = reg3 ^ w1[3]; + + ARIA_GSRK(rk, w0, w1, 19); + rk++; + ARIA_GSRK(rk, w1, w2, 19); + rk++; + ARIA_GSRK(rk, w2, w3, 19); + rk++; + ARIA_GSRK(rk, w3, w0, 19); + + rk++; + ARIA_GSRK(rk, w0, w1, 31); + rk++; + ARIA_GSRK(rk, w1, w2, 31); + rk++; + ARIA_GSRK(rk, w2, w3, 31); + rk++; + ARIA_GSRK(rk, w3, w0, 31); + + rk++; + ARIA_GSRK(rk, w0, w1, 67); + rk++; + ARIA_GSRK(rk, w1, w2, 67); + rk++; + ARIA_GSRK(rk, w2, w3, 67); + rk++; + ARIA_GSRK(rk, w3, w0, 67); + + rk++; + ARIA_GSRK(rk, w0, w1, 97); + if (bits > 128) { + rk++; + ARIA_GSRK(rk, w1, w2, 97); + rk++; + ARIA_GSRK(rk, w2, w3, 97); + } + if (bits > 192) { + rk++; + ARIA_GSRK(rk, w3, w0, 97); + + rk++; + ARIA_GSRK(rk, w0, w1, 109); + } + + return 0; +} + +int aria_set_decrypt_key(const unsigned char *userKey, const int bits, + ARIA_KEY *key) +{ + ARIA_u128 *rk_head; + ARIA_u128 *rk_tail; + register uint32_t w1, w2; + register uint32_t reg0, reg1, reg2, reg3; + uint32_t s0, s1, s2, s3; + + const int r = aria_set_encrypt_key(userKey, bits, key); + + if (r != 0) { + return r; + } + + rk_head = key->rd_key; + rk_tail = rk_head + key->rounds; + + reg0 = rk_head->u[0]; + reg1 = rk_head->u[1]; + reg2 = rk_head->u[2]; + reg3 = rk_head->u[3]; + + memcpy(rk_head, rk_tail, ARIA_BLOCK_SIZE); + + rk_tail->u[0] = reg0; + rk_tail->u[1] = reg1; + rk_tail->u[2] = reg2; + rk_tail->u[3] = reg3; + + rk_head++; + rk_tail--; + + for (; rk_head < rk_tail; rk_head++, rk_tail--) { + ARIA_DEC_DIFF_BYTE(rk_head->u[0], reg0, w1, w2); + ARIA_DEC_DIFF_BYTE(rk_head->u[1], reg1, w1, w2); + ARIA_DEC_DIFF_BYTE(rk_head->u[2], reg2, w1, w2); + ARIA_DEC_DIFF_BYTE(rk_head->u[3], reg3, w1, w2); + + ARIA_DIFF_WORD(reg0, reg1, reg2, reg3); + ARIA_DIFF_BYTE(reg0, reg1, reg2, reg3); + ARIA_DIFF_WORD(reg0, reg1, reg2, reg3); + + s0 = reg0; + s1 = reg1; + s2 = reg2; + s3 = reg3; + + ARIA_DEC_DIFF_BYTE(rk_tail->u[0], reg0, w1, w2); + ARIA_DEC_DIFF_BYTE(rk_tail->u[1], reg1, w1, w2); + ARIA_DEC_DIFF_BYTE(rk_tail->u[2], reg2, w1, w2); + ARIA_DEC_DIFF_BYTE(rk_tail->u[3], reg3, w1, w2); + + ARIA_DIFF_WORD(reg0, reg1, reg2, reg3); + ARIA_DIFF_BYTE(reg0, reg1, reg2, reg3); + ARIA_DIFF_WORD(reg0, reg1, reg2, reg3); + + rk_head->u[0] = reg0; + rk_head->u[1] = reg1; + rk_head->u[2] = reg2; + rk_head->u[3] = reg3; + + rk_tail->u[0] = s0; + rk_tail->u[1] = s1; + rk_tail->u[2] = s2; + rk_tail->u[3] = s3; + } + ARIA_DEC_DIFF_BYTE(rk_head->u[0], reg0, w1, w2); + ARIA_DEC_DIFF_BYTE(rk_head->u[1], reg1, w1, w2); + ARIA_DEC_DIFF_BYTE(rk_head->u[2], reg2, w1, w2); + ARIA_DEC_DIFF_BYTE(rk_head->u[3], reg3, w1, w2); + + ARIA_DIFF_WORD(reg0, reg1, reg2, reg3); + ARIA_DIFF_BYTE(reg0, reg1, reg2, reg3); + ARIA_DIFF_WORD(reg0, reg1, reg2, reg3); + + rk_tail->u[0] = reg0; + rk_tail->u[1] = reg1; + rk_tail->u[2] = reg2; + rk_tail->u[3] = reg3; + + return 0; +} + +#else + +static const unsigned char sb1[256] = { + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, + 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, + 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, + 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, + 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, + 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, + 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, + 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, + 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, + 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, + 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, + 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, + 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, + 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, + 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, + 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, + 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +}; + +static const unsigned char sb2[256] = { + 0xe2, 0x4e, 0x54, 0xfc, 0x94, 0xc2, 0x4a, 0xcc, + 0x62, 0x0d, 0x6a, 0x46, 0x3c, 0x4d, 0x8b, 0xd1, + 0x5e, 0xfa, 0x64, 0xcb, 0xb4, 0x97, 0xbe, 0x2b, + 0xbc, 0x77, 0x2e, 0x03, 0xd3, 0x19, 0x59, 0xc1, + 0x1d, 0x06, 0x41, 0x6b, 0x55, 0xf0, 0x99, 0x69, + 0xea, 0x9c, 0x18, 0xae, 0x63, 0xdf, 0xe7, 0xbb, + 0x00, 0x73, 0x66, 0xfb, 0x96, 0x4c, 0x85, 0xe4, + 0x3a, 0x09, 0x45, 0xaa, 0x0f, 0xee, 0x10, 0xeb, + 0x2d, 0x7f, 0xf4, 0x29, 0xac, 0xcf, 0xad, 0x91, + 0x8d, 0x78, 0xc8, 0x95, 0xf9, 0x2f, 0xce, 0xcd, + 0x08, 0x7a, 0x88, 0x38, 0x5c, 0x83, 0x2a, 0x28, + 0x47, 0xdb, 0xb8, 0xc7, 0x93, 0xa4, 0x12, 0x53, + 0xff, 0x87, 0x0e, 0x31, 0x36, 0x21, 0x58, 0x48, + 0x01, 0x8e, 0x37, 0x74, 0x32, 0xca, 0xe9, 0xb1, + 0xb7, 0xab, 0x0c, 0xd7, 0xc4, 0x56, 0x42, 0x26, + 0x07, 0x98, 0x60, 0xd9, 0xb6, 0xb9, 0x11, 0x40, + 0xec, 0x20, 0x8c, 0xbd, 0xa0, 0xc9, 0x84, 0x04, + 0x49, 0x23, 0xf1, 0x4f, 0x50, 0x1f, 0x13, 0xdc, + 0xd8, 0xc0, 0x9e, 0x57, 0xe3, 0xc3, 0x7b, 0x65, + 0x3b, 0x02, 0x8f, 0x3e, 0xe8, 0x25, 0x92, 0xe5, + 0x15, 0xdd, 0xfd, 0x17, 0xa9, 0xbf, 0xd4, 0x9a, + 0x7e, 0xc5, 0x39, 0x67, 0xfe, 0x76, 0x9d, 0x43, + 0xa7, 0xe1, 0xd0, 0xf5, 0x68, 0xf2, 0x1b, 0x34, + 0x70, 0x05, 0xa3, 0x8a, 0xd5, 0x79, 0x86, 0xa8, + 0x30, 0xc6, 0x51, 0x4b, 0x1e, 0xa6, 0x27, 0xf6, + 0x35, 0xd2, 0x6e, 0x24, 0x16, 0x82, 0x5f, 0xda, + 0xe6, 0x75, 0xa2, 0xef, 0x2c, 0xb2, 0x1c, 0x9f, + 0x5d, 0x6f, 0x80, 0x0a, 0x72, 0x44, 0x9b, 0x6c, + 0x90, 0x0b, 0x5b, 0x33, 0x7d, 0x5a, 0x52, 0xf3, + 0x61, 0xa1, 0xf7, 0xb0, 0xd6, 0x3f, 0x7c, 0x6d, + 0xed, 0x14, 0xe0, 0xa5, 0x3d, 0x22, 0xb3, 0xf8, + 0x89, 0xde, 0x71, 0x1a, 0xaf, 0xba, 0xb5, 0x81 +}; + +static const unsigned char sb3[256] = { + 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, + 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, + 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, + 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, + 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, + 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, + 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, + 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, + 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, + 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, + 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, + 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, + 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, + 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, + 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, + 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, + 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, + 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, + 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, + 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, + 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, + 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, + 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, + 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, + 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, + 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, + 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, + 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, + 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, + 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d +}; + +static const unsigned char sb4[256] = { + 0x30, 0x68, 0x99, 0x1b, 0x87, 0xb9, 0x21, 0x78, + 0x50, 0x39, 0xdb, 0xe1, 0x72, 0x09, 0x62, 0x3c, + 0x3e, 0x7e, 0x5e, 0x8e, 0xf1, 0xa0, 0xcc, 0xa3, + 0x2a, 0x1d, 0xfb, 0xb6, 0xd6, 0x20, 0xc4, 0x8d, + 0x81, 0x65, 0xf5, 0x89, 0xcb, 0x9d, 0x77, 0xc6, + 0x57, 0x43, 0x56, 0x17, 0xd4, 0x40, 0x1a, 0x4d, + 0xc0, 0x63, 0x6c, 0xe3, 0xb7, 0xc8, 0x64, 0x6a, + 0x53, 0xaa, 0x38, 0x98, 0x0c, 0xf4, 0x9b, 0xed, + 0x7f, 0x22, 0x76, 0xaf, 0xdd, 0x3a, 0x0b, 0x58, + 0x67, 0x88, 0x06, 0xc3, 0x35, 0x0d, 0x01, 0x8b, + 0x8c, 0xc2, 0xe6, 0x5f, 0x02, 0x24, 0x75, 0x93, + 0x66, 0x1e, 0xe5, 0xe2, 0x54, 0xd8, 0x10, 0xce, + 0x7a, 0xe8, 0x08, 0x2c, 0x12, 0x97, 0x32, 0xab, + 0xb4, 0x27, 0x0a, 0x23, 0xdf, 0xef, 0xca, 0xd9, + 0xb8, 0xfa, 0xdc, 0x31, 0x6b, 0xd1, 0xad, 0x19, + 0x49, 0xbd, 0x51, 0x96, 0xee, 0xe4, 0xa8, 0x41, + 0xda, 0xff, 0xcd, 0x55, 0x86, 0x36, 0xbe, 0x61, + 0x52, 0xf8, 0xbb, 0x0e, 0x82, 0x48, 0x69, 0x9a, + 0xe0, 0x47, 0x9e, 0x5c, 0x04, 0x4b, 0x34, 0x15, + 0x79, 0x26, 0xa7, 0xde, 0x29, 0xae, 0x92, 0xd7, + 0x84, 0xe9, 0xd2, 0xba, 0x5d, 0xf3, 0xc5, 0xb0, + 0xbf, 0xa4, 0x3b, 0x71, 0x44, 0x46, 0x2b, 0xfc, + 0xeb, 0x6f, 0xd5, 0xf6, 0x14, 0xfe, 0x7c, 0x70, + 0x5a, 0x7d, 0xfd, 0x2f, 0x18, 0x83, 0x16, 0xa5, + 0x91, 0x1f, 0x05, 0x95, 0x74, 0xa9, 0xc1, 0x5b, + 0x4a, 0x85, 0x6d, 0x13, 0x07, 0x4f, 0x4e, 0x45, + 0xb2, 0x0f, 0xc9, 0x1c, 0xa6, 0xbc, 0xec, 0x73, + 0x90, 0x7b, 0xcf, 0x59, 0x8f, 0xa1, 0xf9, 0x2d, + 0xf2, 0xb1, 0x00, 0x94, 0x37, 0x9f, 0xd0, 0x2e, + 0x9c, 0x6e, 0x28, 0x3f, 0x80, 0xf0, 0x3d, 0xd3, + 0x25, 0x8a, 0xb5, 0xe7, 0x42, 0xb3, 0xc7, 0xea, + 0xf7, 0x4c, 0x11, 0x33, 0x03, 0xa2, 0xac, 0x60 +}; + +static const ARIA_u128 c1 = {{ + 0x51, 0x7c, 0xc1, 0xb7, 0x27, 0x22, 0x0a, 0x94, + 0xfe, 0x13, 0xab, 0xe8, 0xfa, 0x9a, 0x6e, 0xe0 +}}; + +static const ARIA_u128 c2 = {{ + 0x6d, 0xb1, 0x4a, 0xcc, 0x9e, 0x21, 0xc8, 0x20, + 0xff, 0x28, 0xb1, 0xd5, 0xef, 0x5d, 0xe2, 0xb0 +}}; + +static const ARIA_u128 c3 = {{ + 0xdb, 0x92, 0x37, 0x1d, 0x21, 0x26, 0xe9, 0x70, + 0x03, 0x24, 0x97, 0x75, 0x04, 0xe8, 0xc9, 0x0e +}}; + +/* + * Exclusive or two 128 bit values into the result. + * It is safe for the result to be the same as the either input. + */ +static void xor128(ARIA_c128 o, const ARIA_c128 x, const ARIA_u128 *y) +{ + int i; + + for (i = 0; i < ARIA_BLOCK_SIZE; i++) + o[i] = x[i] ^ y->c[i]; +} + +/* + * Generalised circular rotate right and exclusive or function. + * It is safe for the output to overlap either input. + */ +static ossl_inline void rotnr(unsigned int n, ARIA_u128 *o, + const ARIA_u128 *xor, const ARIA_u128 *z) +{ + const unsigned int bytes = n / 8, bits = n % 8; + unsigned int i; + ARIA_u128 t; + + for (i = 0; i < ARIA_BLOCK_SIZE; i++) + t.c[(i + bytes) % ARIA_BLOCK_SIZE] = z->c[i]; + for (i = 0; i < ARIA_BLOCK_SIZE; i++) + o->c[i] = ((t.c[i] >> bits) | + (t.c[i ? i - 1 : ARIA_BLOCK_SIZE - 1] << (8 - bits))) ^ + xor->c[i]; +} + +/* + * Circular rotate 19 bits right and xor. + * It is safe for the output to overlap either input. + */ +static void rot19r(ARIA_u128 *o, const ARIA_u128 *xor, const ARIA_u128 *z) +{ + rotnr(19, o, xor, z); +} + +/* + * Circular rotate 31 bits right and xor. + * It is safe for the output to overlap either input. + */ +static void rot31r(ARIA_u128 *o, const ARIA_u128 *xor, const ARIA_u128 *z) +{ + rotnr(31, o, xor, z); +} + +/* + * Circular rotate 61 bits left and xor. + * It is safe for the output to overlap either input. + */ +static void rot61l(ARIA_u128 *o, const ARIA_u128 *xor, const ARIA_u128 *z) +{ + rotnr(8 * ARIA_BLOCK_SIZE - 61, o, xor, z); +} + +/* + * Circular rotate 31 bits left and xor. + * It is safe for the output to overlap either input. + */ +static void rot31l(ARIA_u128 *o, const ARIA_u128 *xor, const ARIA_u128 *z) +{ + rotnr(8 * ARIA_BLOCK_SIZE - 31, o, xor, z); +} + +/* + * Circular rotate 19 bits left and xor. + * It is safe for the output to overlap either input. + */ +static void rot19l(ARIA_u128 *o, const ARIA_u128 *xor, const ARIA_u128 *z) +{ + rotnr(8 * ARIA_BLOCK_SIZE - 19, o, xor, z); +} + +/* + * First substitution and xor layer, used for odd steps. + * It is safe for the input and output to be the same. + */ +static void sl1(ARIA_u128 *o, const ARIA_u128 *x, const ARIA_u128 *y) +{ + unsigned int i; + for (i = 0; i < ARIA_BLOCK_SIZE; i += 4) { + o->c[i ] = sb1[x->c[i ] ^ y->c[i ]]; + o->c[i + 1] = sb2[x->c[i + 1] ^ y->c[i + 1]]; + o->c[i + 2] = sb3[x->c[i + 2] ^ y->c[i + 2]]; + o->c[i + 3] = sb4[x->c[i + 3] ^ y->c[i + 3]]; + } +} + +/* + * Second substitution and xor layer, used for even steps. + * It is safe for the input and output to be the same. + */ +static void sl2(ARIA_c128 o, const ARIA_u128 *x, const ARIA_u128 *y) +{ + unsigned int i; + for (i = 0; i < ARIA_BLOCK_SIZE; i += 4) { + o[i ] = sb3[x->c[i ] ^ y->c[i ]]; + o[i + 1] = sb4[x->c[i + 1] ^ y->c[i + 1]]; + o[i + 2] = sb1[x->c[i + 2] ^ y->c[i + 2]]; + o[i + 3] = sb2[x->c[i + 3] ^ y->c[i + 3]]; + } +} + +/* + * Diffusion layer step + * It is NOT safe for the input and output to overlap. + */ +static void a(ARIA_u128 *y, const ARIA_u128 *x) +{ + y->c[ 0] = x->c[ 3] ^ x->c[ 4] ^ x->c[ 6] ^ x->c[ 8] ^ + x->c[ 9] ^ x->c[13] ^ x->c[14]; + y->c[ 1] = x->c[ 2] ^ x->c[ 5] ^ x->c[ 7] ^ x->c[ 8] ^ + x->c[ 9] ^ x->c[12] ^ x->c[15]; + y->c[ 2] = x->c[ 1] ^ x->c[ 4] ^ x->c[ 6] ^ x->c[10] ^ + x->c[11] ^ x->c[12] ^ x->c[15]; + y->c[ 3] = x->c[ 0] ^ x->c[ 5] ^ x->c[ 7] ^ x->c[10] ^ + x->c[11] ^ x->c[13] ^ x->c[14]; + y->c[ 4] = x->c[ 0] ^ x->c[ 2] ^ x->c[ 5] ^ x->c[ 8] ^ + x->c[11] ^ x->c[14] ^ x->c[15]; + y->c[ 5] = x->c[ 1] ^ x->c[ 3] ^ x->c[ 4] ^ x->c[ 9] ^ + x->c[10] ^ x->c[14] ^ x->c[15]; + y->c[ 6] = x->c[ 0] ^ x->c[ 2] ^ x->c[ 7] ^ x->c[ 9] ^ + x->c[10] ^ x->c[12] ^ x->c[13]; + y->c[ 7] = x->c[ 1] ^ x->c[ 3] ^ x->c[ 6] ^ x->c[ 8] ^ + x->c[11] ^ x->c[12] ^ x->c[13]; + y->c[ 8] = x->c[ 0] ^ x->c[ 1] ^ x->c[ 4] ^ x->c[ 7] ^ + x->c[10] ^ x->c[13] ^ x->c[15]; + y->c[ 9] = x->c[ 0] ^ x->c[ 1] ^ x->c[ 5] ^ x->c[ 6] ^ + x->c[11] ^ x->c[12] ^ x->c[14]; + y->c[10] = x->c[ 2] ^ x->c[ 3] ^ x->c[ 5] ^ x->c[ 6] ^ + x->c[ 8] ^ x->c[13] ^ x->c[15]; + y->c[11] = x->c[ 2] ^ x->c[ 3] ^ x->c[ 4] ^ x->c[ 7] ^ + x->c[ 9] ^ x->c[12] ^ x->c[14]; + y->c[12] = x->c[ 1] ^ x->c[ 2] ^ x->c[ 6] ^ x->c[ 7] ^ + x->c[ 9] ^ x->c[11] ^ x->c[12]; + y->c[13] = x->c[ 0] ^ x->c[ 3] ^ x->c[ 6] ^ x->c[ 7] ^ + x->c[ 8] ^ x->c[10] ^ x->c[13]; + y->c[14] = x->c[ 0] ^ x->c[ 3] ^ x->c[ 4] ^ x->c[ 5] ^ + x->c[ 9] ^ x->c[11] ^ x->c[14]; + y->c[15] = x->c[ 1] ^ x->c[ 2] ^ x->c[ 4] ^ x->c[ 5] ^ + x->c[ 8] ^ x->c[10] ^ x->c[15]; +} + +/* + * Odd round function + * Apply the first substitution layer and then a diffusion step. + * It is safe for the input and output to overlap. + */ +static ossl_inline void FO(ARIA_u128 *o, const ARIA_u128 *d, + const ARIA_u128 *rk) +{ + ARIA_u128 y; + + sl1(&y, d, rk); + a(o, &y); +} + +/* + * Even round function + * Apply the second substitution layer and then a diffusion step. + * It is safe for the input and output to overlap. + */ +static ossl_inline void FE(ARIA_u128 *o, const ARIA_u128 *d, + const ARIA_u128 *rk) +{ + ARIA_u128 y; + + sl2(y.c, d, rk); + a(o, &y); +} + +/* + * Encrypt or decrypt a single block + * in and out can overlap + */ +static void do_encrypt(unsigned char *o, const unsigned char *pin, + unsigned int rounds, const ARIA_u128 *keys) +{ + ARIA_u128 p; + unsigned int i; + + memcpy(&p, pin, sizeof(p)); + for (i = 0; i < rounds - 2; i += 2) { + FO(&p, &p, &keys[i]); + FE(&p, &p, &keys[i + 1]); + } + FO(&p, &p, &keys[rounds - 2]); + sl2(o, &p, &keys[rounds - 1]); + xor128(o, o, &keys[rounds]); +} + +/* + * Encrypt a single block + * in and out can overlap + */ +void aria_encrypt(const unsigned char *in, unsigned char *out, + const ARIA_KEY *key) +{ + assert(in != NULL && out != NULL && key != NULL); + do_encrypt(out, in, key->rounds, key->rd_key); +} + + +/* + * Expand the cipher key into the encryption key schedule. + * We short circuit execution of the last two + * or four rotations based on the key size. + */ +int aria_set_encrypt_key(const unsigned char *userKey, const int bits, + ARIA_KEY *key) +{ + const ARIA_u128 *ck1, *ck2, *ck3; + ARIA_u128 kr, w0, w1, w2, w3; + + if (!userKey || !key) + return -1; + memcpy(w0.c, userKey, sizeof(w0)); + switch (bits) { + default: + return -2; + case 128: + key->rounds = 12; + ck1 = &c1; + ck2 = &c2; + ck3 = &c3; + memset(kr.c, 0, sizeof(kr)); + break; + + case 192: + key->rounds = 14; + ck1 = &c2; + ck2 = &c3; + ck3 = &c1; + memcpy(kr.c, userKey + ARIA_BLOCK_SIZE, sizeof(kr) / 2); + memset(kr.c + ARIA_BLOCK_SIZE / 2, 0, sizeof(kr) / 2); + break; + + case 256: + key->rounds = 16; + ck1 = &c3; + ck2 = &c1; + ck3 = &c2; + memcpy(kr.c, userKey + ARIA_BLOCK_SIZE, sizeof(kr)); + break; + } + + FO(&w3, &w0, ck1); xor128(w1.c, w3.c, &kr); + FE(&w3, &w1, ck2); xor128(w2.c, w3.c, &w0); + FO(&kr, &w2, ck3); xor128(w3.c, kr.c, &w1); + + rot19r(&key->rd_key[ 0], &w0, &w1); + rot19r(&key->rd_key[ 1], &w1, &w2); + rot19r(&key->rd_key[ 2], &w2, &w3); + rot19r(&key->rd_key[ 3], &w3, &w0); + + rot31r(&key->rd_key[ 4], &w0, &w1); + rot31r(&key->rd_key[ 5], &w1, &w2); + rot31r(&key->rd_key[ 6], &w2, &w3); + rot31r(&key->rd_key[ 7], &w3, &w0); + + rot61l(&key->rd_key[ 8], &w0, &w1); + rot61l(&key->rd_key[ 9], &w1, &w2); + rot61l(&key->rd_key[10], &w2, &w3); + rot61l(&key->rd_key[11], &w3, &w0); + + rot31l(&key->rd_key[12], &w0, &w1); + if (key->rounds > 12) { + rot31l(&key->rd_key[13], &w1, &w2); + rot31l(&key->rd_key[14], &w2, &w3); + + if (key->rounds > 14) { + rot31l(&key->rd_key[15], &w3, &w0); + rot19l(&key->rd_key[16], &w0, &w1); + } + } + return 0; +} + +/* + * Expand the cipher key into the decryption key schedule. + */ +int aria_set_decrypt_key(const unsigned char *userKey, const int bits, + ARIA_KEY *key) +{ + ARIA_KEY ek; + const int r = aria_set_encrypt_key(userKey, bits, &ek); + unsigned int i, rounds = ek.rounds; + + if (r == 0) { + key->rounds = rounds; + memcpy(&key->rd_key[0], &ek.rd_key[rounds], sizeof(key->rd_key[0])); + for (i = 1; i < rounds; i++) + a(&key->rd_key[i], &ek.rd_key[rounds - i]); + memcpy(&key->rd_key[rounds], &ek.rd_key[0], sizeof(key->rd_key[rounds])); + } + return r; +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/aria/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/aria/build.info new file mode 100644 index 000000000..218d0612f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/aria/build.info @@ -0,0 +1,4 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + aria.c + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/arm64cpuid.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/arm64cpuid.pl new file mode 100755 index 000000000..06c8add7a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/arm64cpuid.pl @@ -0,0 +1,147 @@ +#! /usr/bin/env perl +# Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +$flavour = shift; +$output = shift; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or +( $xlate="${dir}perlasm/arm-xlate.pl" and -f $xlate) or +die "can't locate arm-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +$code.=<<___; +#include "arm_arch.h" + +.text +.arch armv8-a+crypto + +.align 5 +.globl _armv7_neon_probe +.type _armv7_neon_probe,%function +_armv7_neon_probe: + orr v15.16b, v15.16b, v15.16b + ret +.size _armv7_neon_probe,.-_armv7_neon_probe + +.globl _armv7_tick +.type _armv7_tick,%function +_armv7_tick: +#ifdef __APPLE__ + mrs x0, CNTPCT_EL0 +#else + mrs x0, CNTVCT_EL0 +#endif + ret +.size _armv7_tick,.-_armv7_tick + +.globl _armv8_aes_probe +.type _armv8_aes_probe,%function +_armv8_aes_probe: + aese v0.16b, v0.16b + ret +.size _armv8_aes_probe,.-_armv8_aes_probe + +.globl _armv8_sha1_probe +.type _armv8_sha1_probe,%function +_armv8_sha1_probe: + sha1h s0, s0 + ret +.size _armv8_sha1_probe,.-_armv8_sha1_probe + +.globl _armv8_sha256_probe +.type _armv8_sha256_probe,%function +_armv8_sha256_probe: + sha256su0 v0.4s, v0.4s + ret +.size _armv8_sha256_probe,.-_armv8_sha256_probe + +.globl _armv8_pmull_probe +.type _armv8_pmull_probe,%function +_armv8_pmull_probe: + pmull v0.1q, v0.1d, v0.1d + ret +.size _armv8_pmull_probe,.-_armv8_pmull_probe + +.globl _armv8_sha512_probe +.type _armv8_sha512_probe,%function +_armv8_sha512_probe: + .long 0xcec08000 // sha512su0 v0.2d,v0.2d + ret +.size _armv8_sha512_probe,.-_armv8_sha512_probe + +.globl OPENSSL_cleanse +.type OPENSSL_cleanse,%function +.align 5 +OPENSSL_cleanse: + cbz x1,.Lret // len==0? + cmp x1,#15 + b.hi .Lot // len>15 + nop +.Little: + strb wzr,[x0],#1 // store byte-by-byte + subs x1,x1,#1 + b.ne .Little +.Lret: ret + +.align 4 +.Lot: tst x0,#7 + b.eq .Laligned // inp is aligned + strb wzr,[x0],#1 // store byte-by-byte + sub x1,x1,#1 + b .Lot + +.align 4 +.Laligned: + str xzr,[x0],#8 // store word-by-word + sub x1,x1,#8 + tst x1,#-8 + b.ne .Laligned // len>=8 + cbnz x1,.Little // len!=0? + ret +.size OPENSSL_cleanse,.-OPENSSL_cleanse + +.globl CRYPTO_memcmp +.type CRYPTO_memcmp,%function +.align 4 +CRYPTO_memcmp: + eor w3,w3,w3 + cbz x2,.Lno_data // len==0? + cmp x2,#16 + b.ne .Loop_cmp + ldp x8,x9,[x0] + ldp x10,x11,[x1] + eor x8,x8,x10 + eor x9,x9,x11 + orr x8,x8,x9 + mov x0,#1 + cmp x8,#0 + csel x0,xzr,x0,eq + ret + +.align 4 +.Loop_cmp: + ldrb w4,[x0],#1 + ldrb w5,[x1],#1 + eor w4,w4,w5 + orr w3,w3,w4 + subs x2,x2,#1 + b.ne .Loop_cmp + +.Lno_data: + neg w0,w3 + lsr w0,w0,#31 + ret +.size CRYPTO_memcmp,.-CRYPTO_memcmp +___ + +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/arm_arch.h b/trunk/3rdparty/openssl-1.1-fit/crypto/arm_arch.h new file mode 100644 index 000000000..f11b543df --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/arm_arch.h @@ -0,0 +1,84 @@ +/* + * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef __ARM_ARCH_H__ +# define __ARM_ARCH_H__ + +# if !defined(__ARM_ARCH__) +# if defined(__CC_ARM) +# define __ARM_ARCH__ __TARGET_ARCH_ARM +# if defined(__BIG_ENDIAN) +# define __ARMEB__ +# else +# define __ARMEL__ +# endif +# elif defined(__GNUC__) +# if defined(__aarch64__) +# define __ARM_ARCH__ 8 +# if __BYTE_ORDER__==__ORDER_BIG_ENDIAN__ +# define __ARMEB__ +# else +# define __ARMEL__ +# endif + /* + * Why doesn't gcc define __ARM_ARCH__? Instead it defines + * bunch of below macros. See all_architectures[] table in + * gcc/config/arm/arm.c. On a side note it defines + * __ARMEL__/__ARMEB__ for little-/big-endian. + */ +# elif defined(__ARM_ARCH) +# define __ARM_ARCH__ __ARM_ARCH +# elif defined(__ARM_ARCH_8A__) +# define __ARM_ARCH__ 8 +# elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \ + defined(__ARM_ARCH_7R__)|| defined(__ARM_ARCH_7M__) || \ + defined(__ARM_ARCH_7EM__) +# define __ARM_ARCH__ 7 +# elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \ + defined(__ARM_ARCH_6K__)|| defined(__ARM_ARCH_6M__) || \ + defined(__ARM_ARCH_6Z__)|| defined(__ARM_ARCH_6ZK__) || \ + defined(__ARM_ARCH_6T2__) +# define __ARM_ARCH__ 6 +# elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) || \ + defined(__ARM_ARCH_5E__)|| defined(__ARM_ARCH_5TE__) || \ + defined(__ARM_ARCH_5TEJ__) +# define __ARM_ARCH__ 5 +# elif defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) +# define __ARM_ARCH__ 4 +# else +# error "unsupported ARM architecture" +# endif +# endif +# endif + +# if !defined(__ARM_MAX_ARCH__) +# define __ARM_MAX_ARCH__ __ARM_ARCH__ +# endif + +# if __ARM_MAX_ARCH__<__ARM_ARCH__ +# error "__ARM_MAX_ARCH__ can't be less than __ARM_ARCH__" +# elif __ARM_MAX_ARCH__!=__ARM_ARCH__ +# if __ARM_ARCH__<7 && __ARM_MAX_ARCH__>=7 && defined(__ARMEB__) +# error "can't build universal big-endian binary" +# endif +# endif + +# ifndef __ASSEMBLER__ +extern unsigned int OPENSSL_armcap_P; +# endif + +# define ARMV7_NEON (1<<0) +# define ARMV7_TICK (1<<1) +# define ARMV8_AES (1<<2) +# define ARMV8_SHA1 (1<<3) +# define ARMV8_SHA256 (1<<4) +# define ARMV8_PMULL (1<<5) +# define ARMV8_SHA512 (1<<6) + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/armcap.c b/trunk/3rdparty/openssl-1.1-fit/crypto/armcap.c new file mode 100644 index 000000000..58e54f0da --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/armcap.c @@ -0,0 +1,214 @@ +/* + * Copyright 2011-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include +#include "internal/cryptlib.h" + +#include "arm_arch.h" + +unsigned int OPENSSL_armcap_P = 0; + +#if __ARM_MAX_ARCH__<7 +void OPENSSL_cpuid_setup(void) +{ +} + +uint32_t OPENSSL_rdtsc(void) +{ + return 0; +} +#else +static sigset_t all_masked; + +static sigjmp_buf ill_jmp; +static void ill_handler(int sig) +{ + siglongjmp(ill_jmp, sig); +} + +/* + * Following subroutines could have been inlined, but it's not all + * ARM compilers support inline assembler... + */ +void _armv7_neon_probe(void); +void _armv8_aes_probe(void); +void _armv8_sha1_probe(void); +void _armv8_sha256_probe(void); +void _armv8_pmull_probe(void); +# ifdef __aarch64__ +void _armv8_sha512_probe(void); +# endif +uint32_t _armv7_tick(void); + +uint32_t OPENSSL_rdtsc(void) +{ + if (OPENSSL_armcap_P & ARMV7_TICK) + return _armv7_tick(); + else + return 0; +} + +# if defined(__GNUC__) && __GNUC__>=2 +void OPENSSL_cpuid_setup(void) __attribute__ ((constructor)); +# endif + +# if defined(__GLIBC__) && defined(__GLIBC_PREREQ) +# if __GLIBC_PREREQ(2, 16) +# include +# define OSSL_IMPLEMENT_GETAUXVAL +# endif +# endif + +/* + * ARM puts the feature bits for Crypto Extensions in AT_HWCAP2, whereas + * AArch64 used AT_HWCAP. + */ +# if defined(__arm__) || defined (__arm) +# define HWCAP 16 + /* AT_HWCAP */ +# define HWCAP_NEON (1 << 12) + +# define HWCAP_CE 26 + /* AT_HWCAP2 */ +# define HWCAP_CE_AES (1 << 0) +# define HWCAP_CE_PMULL (1 << 1) +# define HWCAP_CE_SHA1 (1 << 2) +# define HWCAP_CE_SHA256 (1 << 3) +# elif defined(__aarch64__) +# define HWCAP 16 + /* AT_HWCAP */ +# define HWCAP_NEON (1 << 1) + +# define HWCAP_CE HWCAP +# define HWCAP_CE_AES (1 << 3) +# define HWCAP_CE_PMULL (1 << 4) +# define HWCAP_CE_SHA1 (1 << 5) +# define HWCAP_CE_SHA256 (1 << 6) +# define HWCAP_CE_SHA512 (1 << 21) +# endif + +void OPENSSL_cpuid_setup(void) +{ + const char *e; + struct sigaction ill_oact, ill_act; + sigset_t oset; + static int trigger = 0; + + if (trigger) + return; + trigger = 1; + + if ((e = getenv("OPENSSL_armcap"))) { + OPENSSL_armcap_P = (unsigned int)strtoul(e, NULL, 0); + return; + } + +# if defined(__APPLE__) && !defined(__aarch64__) + /* + * Capability probing by catching SIGILL appears to be problematic + * on iOS. But since Apple universe is "monocultural", it's actually + * possible to simply set pre-defined processor capability mask. + */ + if (1) { + OPENSSL_armcap_P = ARMV7_NEON; + return; + } + /* + * One could do same even for __aarch64__ iOS builds. It's not done + * exclusively for reasons of keeping code unified across platforms. + * Unified code works because it never triggers SIGILL on Apple + * devices... + */ +# endif + + OPENSSL_armcap_P = 0; + +# ifdef OSSL_IMPLEMENT_GETAUXVAL + if (getauxval(HWCAP) & HWCAP_NEON) { + unsigned long hwcap = getauxval(HWCAP_CE); + + OPENSSL_armcap_P |= ARMV7_NEON; + + if (hwcap & HWCAP_CE_AES) + OPENSSL_armcap_P |= ARMV8_AES; + + if (hwcap & HWCAP_CE_PMULL) + OPENSSL_armcap_P |= ARMV8_PMULL; + + if (hwcap & HWCAP_CE_SHA1) + OPENSSL_armcap_P |= ARMV8_SHA1; + + if (hwcap & HWCAP_CE_SHA256) + OPENSSL_armcap_P |= ARMV8_SHA256; + +# ifdef __aarch64__ + if (hwcap & HWCAP_CE_SHA512) + OPENSSL_armcap_P |= ARMV8_SHA512; +# endif + } +# endif + + sigfillset(&all_masked); + sigdelset(&all_masked, SIGILL); + sigdelset(&all_masked, SIGTRAP); + sigdelset(&all_masked, SIGFPE); + sigdelset(&all_masked, SIGBUS); + sigdelset(&all_masked, SIGSEGV); + + memset(&ill_act, 0, sizeof(ill_act)); + ill_act.sa_handler = ill_handler; + ill_act.sa_mask = all_masked; + + sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset); + sigaction(SIGILL, &ill_act, &ill_oact); + + /* If we used getauxval, we already have all the values */ +# ifndef OSSL_IMPLEMENT_GETAUXVAL + if (sigsetjmp(ill_jmp, 1) == 0) { + _armv7_neon_probe(); + OPENSSL_armcap_P |= ARMV7_NEON; + if (sigsetjmp(ill_jmp, 1) == 0) { + _armv8_pmull_probe(); + OPENSSL_armcap_P |= ARMV8_PMULL | ARMV8_AES; + } else if (sigsetjmp(ill_jmp, 1) == 0) { + _armv8_aes_probe(); + OPENSSL_armcap_P |= ARMV8_AES; + } + if (sigsetjmp(ill_jmp, 1) == 0) { + _armv8_sha1_probe(); + OPENSSL_armcap_P |= ARMV8_SHA1; + } + if (sigsetjmp(ill_jmp, 1) == 0) { + _armv8_sha256_probe(); + OPENSSL_armcap_P |= ARMV8_SHA256; + } +# if defined(__aarch64__) && !defined(__APPLE__) + if (sigsetjmp(ill_jmp, 1) == 0) { + _armv8_sha512_probe(); + OPENSSL_armcap_P |= ARMV8_SHA512; + } +# endif + } +# endif + + /* Things that getauxval didn't tell us */ + if (sigsetjmp(ill_jmp, 1) == 0) { + _armv7_tick(); + OPENSSL_armcap_P |= ARMV7_TICK; + } + + sigaction(SIGILL, &ill_oact, NULL); + sigprocmask(SIG_SETMASK, &oset, NULL); +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/armv4cpuid.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/armv4cpuid.pl new file mode 100644 index 000000000..ab007c19c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/armv4cpuid.pl @@ -0,0 +1,296 @@ +#! /usr/bin/env perl +# Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +$flavour = shift; +$output = shift; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or +( $xlate="${dir}perlasm/arm-xlate.pl" and -f $xlate) or +die "can't locate arm-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +$code.=<<___; +#include "arm_arch.h" + +.text +#if defined(__thumb2__) && !defined(__APPLE__) +.syntax unified +.thumb +#else +.code 32 +#undef __thumb2__ +#endif + +.align 5 +.global OPENSSL_atomic_add +.type OPENSSL_atomic_add,%function +OPENSSL_atomic_add: +#if __ARM_ARCH__>=6 +.Ladd: ldrex r2,[r0] + add r3,r2,r1 + strex r2,r3,[r0] + cmp r2,#0 + bne .Ladd + mov r0,r3 + bx lr +#else + stmdb sp!,{r4-r6,lr} + ldr r2,.Lspinlock + adr r3,.Lspinlock + mov r4,r0 + mov r5,r1 + add r6,r3,r2 @ &spinlock + b .+8 +.Lspin: bl sched_yield + mov r0,#-1 + swp r0,r0,[r6] + cmp r0,#0 + bne .Lspin + + ldr r2,[r4] + add r2,r2,r5 + str r2,[r4] + str r0,[r6] @ release spinlock + ldmia sp!,{r4-r6,lr} + tst lr,#1 + moveq pc,lr + .word 0xe12fff1e @ bx lr +#endif +.size OPENSSL_atomic_add,.-OPENSSL_atomic_add + +.global OPENSSL_cleanse +.type OPENSSL_cleanse,%function +OPENSSL_cleanse: + eor ip,ip,ip + cmp r1,#7 +#ifdef __thumb2__ + itt hs +#endif + subhs r1,r1,#4 + bhs .Lot + cmp r1,#0 + beq .Lcleanse_done +.Little: + strb ip,[r0],#1 + subs r1,r1,#1 + bhi .Little + b .Lcleanse_done + +.Lot: tst r0,#3 + beq .Laligned + strb ip,[r0],#1 + sub r1,r1,#1 + b .Lot +.Laligned: + str ip,[r0],#4 + subs r1,r1,#4 + bhs .Laligned + adds r1,r1,#4 + bne .Little +.Lcleanse_done: +#if __ARM_ARCH__>=5 + bx lr +#else + tst lr,#1 + moveq pc,lr + .word 0xe12fff1e @ bx lr +#endif +.size OPENSSL_cleanse,.-OPENSSL_cleanse + +.global CRYPTO_memcmp +.type CRYPTO_memcmp,%function +.align 4 +CRYPTO_memcmp: + eor ip,ip,ip + cmp r2,#0 + beq .Lno_data + stmdb sp!,{r4,r5} + +.Loop_cmp: + ldrb r4,[r0],#1 + ldrb r5,[r1],#1 + eor r4,r4,r5 + orr ip,ip,r4 + subs r2,r2,#1 + bne .Loop_cmp + + ldmia sp!,{r4,r5} +.Lno_data: + rsb r0,ip,#0 + mov r0,r0,lsr#31 +#if __ARM_ARCH__>=5 + bx lr +#else + tst lr,#1 + moveq pc,lr + .word 0xe12fff1e @ bx lr +#endif +.size CRYPTO_memcmp,.-CRYPTO_memcmp + +#if __ARM_MAX_ARCH__>=7 +.arch armv7-a +.fpu neon + +.align 5 +.global _armv7_neon_probe +.type _armv7_neon_probe,%function +_armv7_neon_probe: + vorr q0,q0,q0 + bx lr +.size _armv7_neon_probe,.-_armv7_neon_probe + +.global _armv7_tick +.type _armv7_tick,%function +_armv7_tick: +#ifdef __APPLE__ + mrrc p15,0,r0,r1,c14 @ CNTPCT +#else + mrrc p15,1,r0,r1,c14 @ CNTVCT +#endif + bx lr +.size _armv7_tick,.-_armv7_tick + +.global _armv8_aes_probe +.type _armv8_aes_probe,%function +_armv8_aes_probe: +#if defined(__thumb2__) && !defined(__APPLE__) + .byte 0xb0,0xff,0x00,0x03 @ aese.8 q0,q0 +#else + .byte 0x00,0x03,0xb0,0xf3 @ aese.8 q0,q0 +#endif + bx lr +.size _armv8_aes_probe,.-_armv8_aes_probe + +.global _armv8_sha1_probe +.type _armv8_sha1_probe,%function +_armv8_sha1_probe: +#if defined(__thumb2__) && !defined(__APPLE__) + .byte 0x00,0xef,0x40,0x0c @ sha1c.32 q0,q0,q0 +#else + .byte 0x40,0x0c,0x00,0xf2 @ sha1c.32 q0,q0,q0 +#endif + bx lr +.size _armv8_sha1_probe,.-_armv8_sha1_probe + +.global _armv8_sha256_probe +.type _armv8_sha256_probe,%function +_armv8_sha256_probe: +#if defined(__thumb2__) && !defined(__APPLE__) + .byte 0x00,0xff,0x40,0x0c @ sha256h.32 q0,q0,q0 +#else + .byte 0x40,0x0c,0x00,0xf3 @ sha256h.32 q0,q0,q0 +#endif + bx lr +.size _armv8_sha256_probe,.-_armv8_sha256_probe +.global _armv8_pmull_probe +.type _armv8_pmull_probe,%function +_armv8_pmull_probe: +#if defined(__thumb2__) && !defined(__APPLE__) + .byte 0xa0,0xef,0x00,0x0e @ vmull.p64 q0,d0,d0 +#else + .byte 0x00,0x0e,0xa0,0xf2 @ vmull.p64 q0,d0,d0 +#endif + bx lr +.size _armv8_pmull_probe,.-_armv8_pmull_probe +#endif + +.global OPENSSL_wipe_cpu +.type OPENSSL_wipe_cpu,%function +OPENSSL_wipe_cpu: +#if __ARM_MAX_ARCH__>=7 + ldr r0,.LOPENSSL_armcap + adr r1,.LOPENSSL_armcap + ldr r0,[r1,r0] +#ifdef __APPLE__ + ldr r0,[r0] +#endif +#endif + eor r2,r2,r2 + eor r3,r3,r3 + eor ip,ip,ip +#if __ARM_MAX_ARCH__>=7 + tst r0,#1 + beq .Lwipe_done + veor q0, q0, q0 + veor q1, q1, q1 + veor q2, q2, q2 + veor q3, q3, q3 + veor q8, q8, q8 + veor q9, q9, q9 + veor q10, q10, q10 + veor q11, q11, q11 + veor q12, q12, q12 + veor q13, q13, q13 + veor q14, q14, q14 + veor q15, q15, q15 +.Lwipe_done: +#endif + mov r0,sp +#if __ARM_ARCH__>=5 + bx lr +#else + tst lr,#1 + moveq pc,lr + .word 0xe12fff1e @ bx lr +#endif +.size OPENSSL_wipe_cpu,.-OPENSSL_wipe_cpu + +.global OPENSSL_instrument_bus +.type OPENSSL_instrument_bus,%function +OPENSSL_instrument_bus: + eor r0,r0,r0 +#if __ARM_ARCH__>=5 + bx lr +#else + tst lr,#1 + moveq pc,lr + .word 0xe12fff1e @ bx lr +#endif +.size OPENSSL_instrument_bus,.-OPENSSL_instrument_bus + +.global OPENSSL_instrument_bus2 +.type OPENSSL_instrument_bus2,%function +OPENSSL_instrument_bus2: + eor r0,r0,r0 +#if __ARM_ARCH__>=5 + bx lr +#else + tst lr,#1 + moveq pc,lr + .word 0xe12fff1e @ bx lr +#endif +.size OPENSSL_instrument_bus2,.-OPENSSL_instrument_bus2 + +.align 5 +#if __ARM_MAX_ARCH__>=7 +.LOPENSSL_armcap: +.word OPENSSL_armcap_P-. +#endif +#if __ARM_ARCH__>=6 +.align 5 +#else +.Lspinlock: +.word atomic_add_spinlock-.Lspinlock +.align 5 + +.data +.align 2 +atomic_add_spinlock: +.word 0 +#endif + +.comm OPENSSL_armcap_P,4,4 +.hidden OPENSSL_armcap_P +___ + +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_bitstr.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_bitstr.c new file mode 100644 index 000000000..bffbd160a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_bitstr.c @@ -0,0 +1,216 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include +#include "asn1_locl.h" + +int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len) +{ + return ASN1_STRING_set(x, d, len); +} + +int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp) +{ + int ret, j, bits, len; + unsigned char *p, *d; + + if (a == NULL) + return 0; + + len = a->length; + + if (len > 0) { + if (a->flags & ASN1_STRING_FLAG_BITS_LEFT) { + bits = (int)a->flags & 0x07; + } else { + for (; len > 0; len--) { + if (a->data[len - 1]) + break; + } + j = a->data[len - 1]; + if (j & 0x01) + bits = 0; + else if (j & 0x02) + bits = 1; + else if (j & 0x04) + bits = 2; + else if (j & 0x08) + bits = 3; + else if (j & 0x10) + bits = 4; + else if (j & 0x20) + bits = 5; + else if (j & 0x40) + bits = 6; + else if (j & 0x80) + bits = 7; + else + bits = 0; /* should not happen */ + } + } else + bits = 0; + + ret = 1 + len; + if (pp == NULL) + return ret; + + p = *pp; + + *(p++) = (unsigned char)bits; + d = a->data; + if (len > 0) { + memcpy(p, d, len); + p += len; + p[-1] &= (0xff << bits); + } + *pp = p; + return ret; +} + +ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, + const unsigned char **pp, long len) +{ + ASN1_BIT_STRING *ret = NULL; + const unsigned char *p; + unsigned char *s; + int i; + + if (len < 1) { + i = ASN1_R_STRING_TOO_SHORT; + goto err; + } + + if (len > INT_MAX) { + i = ASN1_R_STRING_TOO_LONG; + goto err; + } + + if ((a == NULL) || ((*a) == NULL)) { + if ((ret = ASN1_BIT_STRING_new()) == NULL) + return NULL; + } else + ret = (*a); + + p = *pp; + i = *(p++); + if (i > 7) { + i = ASN1_R_INVALID_BIT_STRING_BITS_LEFT; + goto err; + } + /* + * We do this to preserve the settings. If we modify the settings, via + * the _set_bit function, we will recalculate on output + */ + ret->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear */ + ret->flags |= (ASN1_STRING_FLAG_BITS_LEFT | i); /* set */ + + if (len-- > 1) { /* using one because of the bits left byte */ + s = OPENSSL_malloc((int)len); + if (s == NULL) { + i = ERR_R_MALLOC_FAILURE; + goto err; + } + memcpy(s, p, (int)len); + s[len - 1] &= (0xff << i); + p += len; + } else + s = NULL; + + ret->length = (int)len; + OPENSSL_free(ret->data); + ret->data = s; + ret->type = V_ASN1_BIT_STRING; + if (a != NULL) + (*a) = ret; + *pp = p; + return ret; + err: + ASN1err(ASN1_F_C2I_ASN1_BIT_STRING, i); + if ((a == NULL) || (*a != ret)) + ASN1_BIT_STRING_free(ret); + return NULL; +} + +/* + * These next 2 functions from Goetz Babin-Ebell. + */ +int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value) +{ + int w, v, iv; + unsigned char *c; + + w = n / 8; + v = 1 << (7 - (n & 0x07)); + iv = ~v; + if (!value) + v = 0; + + if (a == NULL) + return 0; + + a->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear, set on write */ + + if ((a->length < (w + 1)) || (a->data == NULL)) { + if (!value) + return 1; /* Don't need to set */ + c = OPENSSL_clear_realloc(a->data, a->length, w + 1); + if (c == NULL) { + ASN1err(ASN1_F_ASN1_BIT_STRING_SET_BIT, ERR_R_MALLOC_FAILURE); + return 0; + } + if (w + 1 - a->length > 0) + memset(c + a->length, 0, w + 1 - a->length); + a->data = c; + a->length = w + 1; + } + a->data[w] = ((a->data[w]) & iv) | v; + while ((a->length > 0) && (a->data[a->length - 1] == 0)) + a->length--; + return 1; +} + +int ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n) +{ + int w, v; + + w = n / 8; + v = 1 << (7 - (n & 0x07)); + if ((a == NULL) || (a->length < (w + 1)) || (a->data == NULL)) + return 0; + return ((a->data[w] & v) != 0); +} + +/* + * Checks if the given bit string contains only bits specified by + * the flags vector. Returns 0 if there is at least one bit set in 'a' + * which is not specified in 'flags', 1 otherwise. + * 'len' is the length of 'flags'. + */ +int ASN1_BIT_STRING_check(const ASN1_BIT_STRING *a, + const unsigned char *flags, int flags_len) +{ + int i, ok; + /* Check if there is one bit set at all. */ + if (!a || !a->data) + return 1; + + /* + * Check each byte of the internal representation of the bit string. + */ + ok = 1; + for (i = 0; i < a->length && ok; ++i) { + unsigned char mask = i < flags_len ? ~flags[i] : 0xff; + /* We are done if there is an unneeded bit set. */ + ok = (a->data[i] & mask) == 0; + } + return ok; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_d2i_fp.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_d2i_fp.c new file mode 100644 index 000000000..a1a17901b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_d2i_fp.c @@ -0,0 +1,234 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include "internal/numbers.h" +#include +#include +#include "internal/asn1_int.h" + +#ifndef NO_OLD_ASN1 +# ifndef OPENSSL_NO_STDIO + +void *ASN1_d2i_fp(void *(*xnew) (void), d2i_of_void *d2i, FILE *in, void **x) +{ + BIO *b; + void *ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + ASN1err(ASN1_F_ASN1_D2I_FP, ERR_R_BUF_LIB); + return NULL; + } + BIO_set_fp(b, in, BIO_NOCLOSE); + ret = ASN1_d2i_bio(xnew, d2i, b, x); + BIO_free(b); + return ret; +} +# endif + +void *ASN1_d2i_bio(void *(*xnew) (void), d2i_of_void *d2i, BIO *in, void **x) +{ + BUF_MEM *b = NULL; + const unsigned char *p; + void *ret = NULL; + int len; + + len = asn1_d2i_read_bio(in, &b); + if (len < 0) + goto err; + + p = (unsigned char *)b->data; + ret = d2i(x, &p, len); + err: + BUF_MEM_free(b); + return ret; +} + +#endif + +void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x) +{ + BUF_MEM *b = NULL; + const unsigned char *p; + void *ret = NULL; + int len; + + len = asn1_d2i_read_bio(in, &b); + if (len < 0) + goto err; + + p = (const unsigned char *)b->data; + ret = ASN1_item_d2i(x, &p, len, it); + err: + BUF_MEM_free(b); + return ret; +} + +#ifndef OPENSSL_NO_STDIO +void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x) +{ + BIO *b; + char *ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + ASN1err(ASN1_F_ASN1_ITEM_D2I_FP, ERR_R_BUF_LIB); + return NULL; + } + BIO_set_fp(b, in, BIO_NOCLOSE); + ret = ASN1_item_d2i_bio(it, b, x); + BIO_free(b); + return ret; +} +#endif + +#define HEADER_SIZE 8 +#define ASN1_CHUNK_INITIAL_SIZE (16 * 1024) +int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) +{ + BUF_MEM *b; + unsigned char *p; + int i; + size_t want = HEADER_SIZE; + uint32_t eos = 0; + size_t off = 0; + size_t len = 0; + + const unsigned char *q; + long slen; + int inf, tag, xclass; + + b = BUF_MEM_new(); + if (b == NULL) { + ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE); + return -1; + } + + ERR_clear_error(); + for (;;) { + if (want >= (len - off)) { + want -= (len - off); + + if (len + want < len || !BUF_MEM_grow_clean(b, len + want)) { + ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE); + goto err; + } + i = BIO_read(in, &(b->data[len]), want); + if ((i < 0) && ((len - off) == 0)) { + ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_NOT_ENOUGH_DATA); + goto err; + } + if (i > 0) { + if (len + i < len) { + ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG); + goto err; + } + len += i; + } + } + /* else data already loaded */ + + p = (unsigned char *)&(b->data[off]); + q = p; + inf = ASN1_get_object(&q, &slen, &tag, &xclass, len - off); + if (inf & 0x80) { + unsigned long e; + + e = ERR_GET_REASON(ERR_peek_error()); + if (e != ASN1_R_TOO_LONG) + goto err; + else + ERR_clear_error(); /* clear error */ + } + i = q - p; /* header length */ + off += i; /* end of data */ + + if (inf & 1) { + /* no data body so go round again */ + if (eos == UINT32_MAX) { + ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_HEADER_TOO_LONG); + goto err; + } + eos++; + want = HEADER_SIZE; + } else if (eos && (slen == 0) && (tag == V_ASN1_EOC)) { + /* eos value, so go back and read another header */ + eos--; + if (eos == 0) + break; + else + want = HEADER_SIZE; + } else { + /* suck in slen bytes of data */ + want = slen; + if (want > (len - off)) { + size_t chunk_max = ASN1_CHUNK_INITIAL_SIZE; + + want -= (len - off); + if (want > INT_MAX /* BIO_read takes an int length */ || + len + want < len) { + ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG); + goto err; + } + while (want > 0) { + /* + * Read content in chunks of increasing size + * so we can return an error for EOF without + * having to allocate the entire content length + * in one go. + */ + size_t chunk = want > chunk_max ? chunk_max : want; + + if (!BUF_MEM_grow_clean(b, len + chunk)) { + ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE); + goto err; + } + want -= chunk; + while (chunk > 0) { + i = BIO_read(in, &(b->data[len]), chunk); + if (i <= 0) { + ASN1err(ASN1_F_ASN1_D2I_READ_BIO, + ASN1_R_NOT_ENOUGH_DATA); + goto err; + } + /* + * This can't overflow because |len+want| didn't + * overflow. + */ + len += i; + chunk -= i; + } + if (chunk_max < INT_MAX/2) + chunk_max *= 2; + } + } + if (off + slen < off) { + ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG); + goto err; + } + off += slen; + if (eos == 0) { + break; + } else + want = HEADER_SIZE; + } + } + + if (off > INT_MAX) { + ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG); + goto err; + } + + *pb = b; + return off; + err: + BUF_MEM_free(b); + return -1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_digest.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_digest.c new file mode 100644 index 000000000..cc3532ea7 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_digest.c @@ -0,0 +1,67 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include + +#include "internal/cryptlib.h" + +#include +#include +#include +#include + +#ifndef NO_ASN1_OLD + +int ASN1_digest(i2d_of_void *i2d, const EVP_MD *type, char *data, + unsigned char *md, unsigned int *len) +{ + int inl; + unsigned char *str, *p; + + inl = i2d(data, NULL); + if (inl <= 0) { + ASN1err(ASN1_F_ASN1_DIGEST, ERR_R_INTERNAL_ERROR); + return 0; + } + if ((str = OPENSSL_malloc(inl)) == NULL) { + ASN1err(ASN1_F_ASN1_DIGEST, ERR_R_MALLOC_FAILURE); + return 0; + } + p = str; + i2d(data, &p); + + if (!EVP_Digest(str, inl, md, len, type, NULL)) { + OPENSSL_free(str); + return 0; + } + OPENSSL_free(str); + return 1; +} + +#endif + +int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *asn, + unsigned char *md, unsigned int *len) +{ + int i; + unsigned char *str = NULL; + + i = ASN1_item_i2d(asn, &str, it); + if (!str) + return 0; + + if (!EVP_Digest(str, i, md, len, type, NULL)) { + OPENSSL_free(str); + return 0; + } + OPENSSL_free(str); + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_dup.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_dup.c new file mode 100644 index 000000000..50af6b000 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_dup.c @@ -0,0 +1,68 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include + +#ifndef NO_OLD_ASN1 + +void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x) +{ + unsigned char *b, *p; + const unsigned char *p2; + int i; + char *ret; + + if (x == NULL) + return NULL; + + i = i2d(x, NULL); + b = OPENSSL_malloc(i + 10); + if (b == NULL) { + ASN1err(ASN1_F_ASN1_DUP, ERR_R_MALLOC_FAILURE); + return NULL; + } + p = b; + i = i2d(x, &p); + p2 = b; + ret = d2i(NULL, &p2, i); + OPENSSL_free(b); + return ret; +} + +#endif + +/* + * ASN1_ITEM version of dup: this follows the model above except we don't + * need to allocate the buffer. At some point this could be rewritten to + * directly dup the underlying structure instead of doing and encode and + * decode. + */ + +void *ASN1_item_dup(const ASN1_ITEM *it, void *x) +{ + unsigned char *b = NULL; + const unsigned char *p; + long i; + void *ret; + + if (x == NULL) + return NULL; + + i = ASN1_item_i2d(x, &b, it); + if (b == NULL) { + ASN1err(ASN1_F_ASN1_ITEM_DUP, ERR_R_MALLOC_FAILURE); + return NULL; + } + p = b; + ret = ASN1_item_d2i(NULL, &p, i, it); + OPENSSL_free(b); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_gentm.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_gentm.c new file mode 100644 index 000000000..d3878d6e5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_gentm.c @@ -0,0 +1,82 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * GENERALIZEDTIME implementation. Based on UTCTIME + */ + +#include +#include +#include "internal/cryptlib.h" +#include +#include "asn1_locl.h" + +/* This is the primary function used to parse ASN1_GENERALIZEDTIME */ +int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d) +{ + /* wrapper around asn1_time_to_tm */ + if (d->type != V_ASN1_GENERALIZEDTIME) + return 0; + return asn1_time_to_tm(tm, d); +} + +int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *d) +{ + return asn1_generalizedtime_to_tm(NULL, d); +} + +int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str) +{ + ASN1_GENERALIZEDTIME t; + + t.type = V_ASN1_GENERALIZEDTIME; + t.length = strlen(str); + t.data = (unsigned char *)str; + t.flags = 0; + + if (!ASN1_GENERALIZEDTIME_check(&t)) + return 0; + + if (s != NULL && !ASN1_STRING_copy(s, &t)) + return 0; + + return 1; +} + +ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s, + time_t t) +{ + return ASN1_GENERALIZEDTIME_adj(s, t, 0, 0); +} + +ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, + time_t t, int offset_day, + long offset_sec) +{ + struct tm *ts; + struct tm data; + + ts = OPENSSL_gmtime(&t, &data); + if (ts == NULL) + return NULL; + + if (offset_day || offset_sec) { + if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec)) + return NULL; + } + + return asn1_time_from_tm(s, ts, V_ASN1_GENERALIZEDTIME); +} + +int ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm) +{ + if (tm->type != V_ASN1_GENERALIZEDTIME) + return 0; + return ASN1_TIME_print(bp, tm); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_i2d_fp.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_i2d_fp.c new file mode 100644 index 000000000..980c65a25 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_i2d_fp.c @@ -0,0 +1,111 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include + +#ifndef NO_OLD_ASN1 + +# ifndef OPENSSL_NO_STDIO +int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x) +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + ASN1err(ASN1_F_ASN1_I2D_FP, ERR_R_BUF_LIB); + return 0; + } + BIO_set_fp(b, out, BIO_NOCLOSE); + ret = ASN1_i2d_bio(i2d, b, x); + BIO_free(b); + return ret; +} +# endif + +int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, unsigned char *x) +{ + char *b; + unsigned char *p; + int i, j = 0, n, ret = 1; + + n = i2d(x, NULL); + if (n <= 0) + return 0; + + b = OPENSSL_malloc(n); + if (b == NULL) { + ASN1err(ASN1_F_ASN1_I2D_BIO, ERR_R_MALLOC_FAILURE); + return 0; + } + + p = (unsigned char *)b; + i2d(x, &p); + + for (;;) { + i = BIO_write(out, &(b[j]), n); + if (i == n) + break; + if (i <= 0) { + ret = 0; + break; + } + j += i; + n -= i; + } + OPENSSL_free(b); + return ret; +} + +#endif + +#ifndef OPENSSL_NO_STDIO +int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x) +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + ASN1err(ASN1_F_ASN1_ITEM_I2D_FP, ERR_R_BUF_LIB); + return 0; + } + BIO_set_fp(b, out, BIO_NOCLOSE); + ret = ASN1_item_i2d_bio(it, b, x); + BIO_free(b); + return ret; +} +#endif + +int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x) +{ + unsigned char *b = NULL; + int i, j = 0, n, ret = 1; + + n = ASN1_item_i2d(x, &b, it); + if (b == NULL) { + ASN1err(ASN1_F_ASN1_ITEM_I2D_BIO, ERR_R_MALLOC_FAILURE); + return 0; + } + + for (;;) { + i = BIO_write(out, &(b[j]), n); + if (i == n) + break; + if (i <= 0) { + ret = 0; + break; + } + j += i; + n -= i; + } + OPENSSL_free(b); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_int.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_int.c new file mode 100644 index 000000000..70a45cb3c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_int.c @@ -0,0 +1,630 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include "internal/numbers.h" +#include +#include +#include +#include "asn1_locl.h" + +ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x) +{ + return ASN1_STRING_dup(x); +} + +int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y) +{ + int neg, ret; + /* Compare signs */ + neg = x->type & V_ASN1_NEG; + if (neg != (y->type & V_ASN1_NEG)) { + if (neg) + return -1; + else + return 1; + } + + ret = ASN1_STRING_cmp(x, y); + + if (neg) + return -ret; + else + return ret; +} + +/*- + * This converts a big endian buffer and sign into its content encoding. + * This is used for INTEGER and ENUMERATED types. + * The internal representation is an ASN1_STRING whose data is a big endian + * representation of the value, ignoring the sign. The sign is determined by + * the type: if type & V_ASN1_NEG is true it is negative, otherwise positive. + * + * Positive integers are no problem: they are almost the same as the DER + * encoding, except if the first byte is >= 0x80 we need to add a zero pad. + * + * Negative integers are a bit trickier... + * The DER representation of negative integers is in 2s complement form. + * The internal form is converted by complementing each octet and finally + * adding one to the result. This can be done less messily with a little trick. + * If the internal form has trailing zeroes then they will become FF by the + * complement and 0 by the add one (due to carry) so just copy as many trailing + * zeros to the destination as there are in the source. The carry will add one + * to the last none zero octet: so complement this octet and add one and finally + * complement any left over until you get to the start of the string. + * + * Padding is a little trickier too. If the first bytes is > 0x80 then we pad + * with 0xff. However if the first byte is 0x80 and one of the following bytes + * is non-zero we pad with 0xff. The reason for this distinction is that 0x80 + * followed by optional zeros isn't padded. + */ + +/* + * If |pad| is zero, the operation is effectively reduced to memcpy, + * and if |pad| is 0xff, then it performs two's complement, ~dst + 1. + * Note that in latter case sequence of zeros yields itself, and so + * does 0x80 followed by any number of zeros. These properties are + * used elsewhere below... + */ +static void twos_complement(unsigned char *dst, const unsigned char *src, + size_t len, unsigned char pad) +{ + unsigned int carry = pad & 1; + + /* Begin at the end of the encoding */ + dst += len; + src += len; + /* two's complement value: ~value + 1 */ + while (len-- != 0) { + *(--dst) = (unsigned char)(carry += *(--src) ^ pad); + carry >>= 8; + } +} + +static size_t i2c_ibuf(const unsigned char *b, size_t blen, int neg, + unsigned char **pp) +{ + unsigned int pad = 0; + size_t ret, i; + unsigned char *p, pb = 0; + + if (b != NULL && blen) { + ret = blen; + i = b[0]; + if (!neg && (i > 127)) { + pad = 1; + pb = 0; + } else if (neg) { + pb = 0xFF; + if (i > 128) { + pad = 1; + } else if (i == 128) { + /* + * Special case [of minimal negative for given length]: + * if any other bytes non zero we pad, otherwise we don't. + */ + for (pad = 0, i = 1; i < blen; i++) + pad |= b[i]; + pb = pad != 0 ? 0xffU : 0; + pad = pb & 1; + } + } + ret += pad; + } else { + ret = 1; + blen = 0; /* reduce '(b == NULL || blen == 0)' to '(blen == 0)' */ + } + + if (pp == NULL || (p = *pp) == NULL) + return ret; + + /* + * This magically handles all corner cases, such as '(b == NULL || + * blen == 0)', non-negative value, "negative" zero, 0x80 followed + * by any number of zeros... + */ + *p = pb; + p += pad; /* yes, p[0] can be written twice, but it's little + * price to pay for eliminated branches */ + twos_complement(p, b, blen, pb); + + *pp += ret; + return ret; +} + +/* + * convert content octets into a big endian buffer. Returns the length + * of buffer or 0 on error: for malformed INTEGER. If output buffer is + * NULL just return length. + */ + +static size_t c2i_ibuf(unsigned char *b, int *pneg, + const unsigned char *p, size_t plen) +{ + int neg, pad; + /* Zero content length is illegal */ + if (plen == 0) { + ASN1err(ASN1_F_C2I_IBUF, ASN1_R_ILLEGAL_ZERO_CONTENT); + return 0; + } + neg = p[0] & 0x80; + if (pneg) + *pneg = neg; + /* Handle common case where length is 1 octet separately */ + if (plen == 1) { + if (b != NULL) { + if (neg) + b[0] = (p[0] ^ 0xFF) + 1; + else + b[0] = p[0]; + } + return 1; + } + + pad = 0; + if (p[0] == 0) { + pad = 1; + } else if (p[0] == 0xFF) { + size_t i; + + /* + * Special case [of "one less minimal negative" for given length]: + * if any other bytes non zero it was padded, otherwise not. + */ + for (pad = 0, i = 1; i < plen; i++) + pad |= p[i]; + pad = pad != 0 ? 1 : 0; + } + /* reject illegal padding: first two octets MSB can't match */ + if (pad && (neg == (p[1] & 0x80))) { + ASN1err(ASN1_F_C2I_IBUF, ASN1_R_ILLEGAL_PADDING); + return 0; + } + + /* skip over pad */ + p += pad; + plen -= pad; + + if (b != NULL) + twos_complement(b, p, plen, neg ? 0xffU : 0); + + return plen; +} + +int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp) +{ + return i2c_ibuf(a->data, a->length, a->type & V_ASN1_NEG, pp); +} + +/* Convert big endian buffer into uint64_t, return 0 on error */ +static int asn1_get_uint64(uint64_t *pr, const unsigned char *b, size_t blen) +{ + size_t i; + uint64_t r; + + if (blen > sizeof(*pr)) { + ASN1err(ASN1_F_ASN1_GET_UINT64, ASN1_R_TOO_LARGE); + return 0; + } + if (b == NULL) + return 0; + for (r = 0, i = 0; i < blen; i++) { + r <<= 8; + r |= b[i]; + } + *pr = r; + return 1; +} + +/* + * Write uint64_t to big endian buffer and return offset to first + * written octet. In other words it returns offset in range from 0 + * to 7, with 0 denoting 8 written octets and 7 - one. + */ +static size_t asn1_put_uint64(unsigned char b[sizeof(uint64_t)], uint64_t r) +{ + size_t off = sizeof(uint64_t); + + do { + b[--off] = (unsigned char)r; + } while (r >>= 8); + + return off; +} + +/* + * Absolute value of INT64_MIN: we can't just use -INT64_MIN as gcc produces + * overflow warnings. + */ +#define ABS_INT64_MIN ((uint64_t)INT64_MAX + (-(INT64_MIN + INT64_MAX))) + +/* signed version of asn1_get_uint64 */ +static int asn1_get_int64(int64_t *pr, const unsigned char *b, size_t blen, + int neg) +{ + uint64_t r; + if (asn1_get_uint64(&r, b, blen) == 0) + return 0; + if (neg) { + if (r <= INT64_MAX) { + /* Most significant bit is guaranteed to be clear, negation + * is guaranteed to be meaningful in platform-neutral sense. */ + *pr = -(int64_t)r; + } else if (r == ABS_INT64_MIN) { + /* This never happens if INT64_MAX == ABS_INT64_MIN, e.g. + * on ones'-complement system. */ + *pr = (int64_t)(0 - r); + } else { + ASN1err(ASN1_F_ASN1_GET_INT64, ASN1_R_TOO_SMALL); + return 0; + } + } else { + if (r <= INT64_MAX) { + *pr = (int64_t)r; + } else { + ASN1err(ASN1_F_ASN1_GET_INT64, ASN1_R_TOO_LARGE); + return 0; + } + } + return 1; +} + +/* Convert ASN1 INTEGER content octets to ASN1_INTEGER structure */ +ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp, + long len) +{ + ASN1_INTEGER *ret = NULL; + size_t r; + int neg; + + r = c2i_ibuf(NULL, NULL, *pp, len); + + if (r == 0) + return NULL; + + if ((a == NULL) || ((*a) == NULL)) { + ret = ASN1_INTEGER_new(); + if (ret == NULL) + return NULL; + ret->type = V_ASN1_INTEGER; + } else + ret = *a; + + if (ASN1_STRING_set(ret, NULL, r) == 0) + goto err; + + c2i_ibuf(ret->data, &neg, *pp, len); + + if (neg) + ret->type |= V_ASN1_NEG; + + *pp += len; + if (a != NULL) + (*a) = ret; + return ret; + err: + ASN1err(ASN1_F_C2I_ASN1_INTEGER, ERR_R_MALLOC_FAILURE); + if ((a == NULL) || (*a != ret)) + ASN1_INTEGER_free(ret); + return NULL; +} + +static int asn1_string_get_int64(int64_t *pr, const ASN1_STRING *a, int itype) +{ + if (a == NULL) { + ASN1err(ASN1_F_ASN1_STRING_GET_INT64, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if ((a->type & ~V_ASN1_NEG) != itype) { + ASN1err(ASN1_F_ASN1_STRING_GET_INT64, ASN1_R_WRONG_INTEGER_TYPE); + return 0; + } + return asn1_get_int64(pr, a->data, a->length, a->type & V_ASN1_NEG); +} + +static int asn1_string_set_int64(ASN1_STRING *a, int64_t r, int itype) +{ + unsigned char tbuf[sizeof(r)]; + size_t off; + + a->type = itype; + if (r < 0) { + /* Most obvious '-r' triggers undefined behaviour for most + * common INT64_MIN. Even though below '0 - (uint64_t)r' can + * appear two's-complement centric, it does produce correct/ + * expected result even on one's-complement. This is because + * cast to unsigned has to change bit pattern... */ + off = asn1_put_uint64(tbuf, 0 - (uint64_t)r); + a->type |= V_ASN1_NEG; + } else { + off = asn1_put_uint64(tbuf, r); + a->type &= ~V_ASN1_NEG; + } + return ASN1_STRING_set(a, tbuf + off, sizeof(tbuf) - off); +} + +static int asn1_string_get_uint64(uint64_t *pr, const ASN1_STRING *a, + int itype) +{ + if (a == NULL) { + ASN1err(ASN1_F_ASN1_STRING_GET_UINT64, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if ((a->type & ~V_ASN1_NEG) != itype) { + ASN1err(ASN1_F_ASN1_STRING_GET_UINT64, ASN1_R_WRONG_INTEGER_TYPE); + return 0; + } + if (a->type & V_ASN1_NEG) { + ASN1err(ASN1_F_ASN1_STRING_GET_UINT64, ASN1_R_ILLEGAL_NEGATIVE_VALUE); + return 0; + } + return asn1_get_uint64(pr, a->data, a->length); +} + +static int asn1_string_set_uint64(ASN1_STRING *a, uint64_t r, int itype) +{ + unsigned char tbuf[sizeof(r)]; + size_t off; + + a->type = itype; + off = asn1_put_uint64(tbuf, r); + return ASN1_STRING_set(a, tbuf + off, sizeof(tbuf) - off); +} + +/* + * This is a version of d2i_ASN1_INTEGER that ignores the sign bit of ASN1 + * integers: some broken software can encode a positive INTEGER with its MSB + * set as negative (it doesn't add a padding zero). + */ + +ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp, + long length) +{ + ASN1_INTEGER *ret = NULL; + const unsigned char *p; + unsigned char *s; + long len; + int inf, tag, xclass; + int i; + + if ((a == NULL) || ((*a) == NULL)) { + if ((ret = ASN1_INTEGER_new()) == NULL) + return NULL; + ret->type = V_ASN1_INTEGER; + } else + ret = (*a); + + p = *pp; + inf = ASN1_get_object(&p, &len, &tag, &xclass, length); + if (inf & 0x80) { + i = ASN1_R_BAD_OBJECT_HEADER; + goto err; + } + + if (tag != V_ASN1_INTEGER) { + i = ASN1_R_EXPECTING_AN_INTEGER; + goto err; + } + + /* + * We must OPENSSL_malloc stuff, even for 0 bytes otherwise it signifies + * a missing NULL parameter. + */ + s = OPENSSL_malloc((int)len + 1); + if (s == NULL) { + i = ERR_R_MALLOC_FAILURE; + goto err; + } + ret->type = V_ASN1_INTEGER; + if (len) { + if ((*p == 0) && (len != 1)) { + p++; + len--; + } + memcpy(s, p, (int)len); + p += len; + } + + OPENSSL_free(ret->data); + ret->data = s; + ret->length = (int)len; + if (a != NULL) + (*a) = ret; + *pp = p; + return ret; + err: + ASN1err(ASN1_F_D2I_ASN1_UINTEGER, i); + if ((a == NULL) || (*a != ret)) + ASN1_INTEGER_free(ret); + return NULL; +} + +static ASN1_STRING *bn_to_asn1_string(const BIGNUM *bn, ASN1_STRING *ai, + int atype) +{ + ASN1_INTEGER *ret; + int len; + + if (ai == NULL) { + ret = ASN1_STRING_type_new(atype); + } else { + ret = ai; + ret->type = atype; + } + + if (ret == NULL) { + ASN1err(ASN1_F_BN_TO_ASN1_STRING, ERR_R_NESTED_ASN1_ERROR); + goto err; + } + + if (BN_is_negative(bn) && !BN_is_zero(bn)) + ret->type |= V_ASN1_NEG_INTEGER; + + len = BN_num_bytes(bn); + + if (len == 0) + len = 1; + + if (ASN1_STRING_set(ret, NULL, len) == 0) { + ASN1err(ASN1_F_BN_TO_ASN1_STRING, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* Correct zero case */ + if (BN_is_zero(bn)) + ret->data[0] = 0; + else + len = BN_bn2bin(bn, ret->data); + ret->length = len; + return ret; + err: + if (ret != ai) + ASN1_INTEGER_free(ret); + return NULL; +} + +static BIGNUM *asn1_string_to_bn(const ASN1_INTEGER *ai, BIGNUM *bn, + int itype) +{ + BIGNUM *ret; + + if ((ai->type & ~V_ASN1_NEG) != itype) { + ASN1err(ASN1_F_ASN1_STRING_TO_BN, ASN1_R_WRONG_INTEGER_TYPE); + return NULL; + } + + ret = BN_bin2bn(ai->data, ai->length, bn); + if (ret == NULL) { + ASN1err(ASN1_F_ASN1_STRING_TO_BN, ASN1_R_BN_LIB); + return NULL; + } + if (ai->type & V_ASN1_NEG) + BN_set_negative(ret, 1); + return ret; +} + +int ASN1_INTEGER_get_int64(int64_t *pr, const ASN1_INTEGER *a) +{ + return asn1_string_get_int64(pr, a, V_ASN1_INTEGER); +} + +int ASN1_INTEGER_set_int64(ASN1_INTEGER *a, int64_t r) +{ + return asn1_string_set_int64(a, r, V_ASN1_INTEGER); +} + +int ASN1_INTEGER_get_uint64(uint64_t *pr, const ASN1_INTEGER *a) +{ + return asn1_string_get_uint64(pr, a, V_ASN1_INTEGER); +} + +int ASN1_INTEGER_set_uint64(ASN1_INTEGER *a, uint64_t r) +{ + return asn1_string_set_uint64(a, r, V_ASN1_INTEGER); +} + +int ASN1_INTEGER_set(ASN1_INTEGER *a, long v) +{ + return ASN1_INTEGER_set_int64(a, v); +} + +long ASN1_INTEGER_get(const ASN1_INTEGER *a) +{ + int i; + int64_t r; + if (a == NULL) + return 0; + i = ASN1_INTEGER_get_int64(&r, a); + if (i == 0) + return -1; + if (r > LONG_MAX || r < LONG_MIN) + return -1; + return (long)r; +} + +ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai) +{ + return bn_to_asn1_string(bn, ai, V_ASN1_INTEGER); +} + +BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn) +{ + return asn1_string_to_bn(ai, bn, V_ASN1_INTEGER); +} + +int ASN1_ENUMERATED_get_int64(int64_t *pr, const ASN1_ENUMERATED *a) +{ + return asn1_string_get_int64(pr, a, V_ASN1_ENUMERATED); +} + +int ASN1_ENUMERATED_set_int64(ASN1_ENUMERATED *a, int64_t r) +{ + return asn1_string_set_int64(a, r, V_ASN1_ENUMERATED); +} + +int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v) +{ + return ASN1_ENUMERATED_set_int64(a, v); +} + +long ASN1_ENUMERATED_get(const ASN1_ENUMERATED *a) +{ + int i; + int64_t r; + if (a == NULL) + return 0; + if ((a->type & ~V_ASN1_NEG) != V_ASN1_ENUMERATED) + return -1; + if (a->length > (int)sizeof(long)) + return 0xffffffffL; + i = ASN1_ENUMERATED_get_int64(&r, a); + if (i == 0) + return -1; + if (r > LONG_MAX || r < LONG_MIN) + return -1; + return (long)r; +} + +ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(const BIGNUM *bn, ASN1_ENUMERATED *ai) +{ + return bn_to_asn1_string(bn, ai, V_ASN1_ENUMERATED); +} + +BIGNUM *ASN1_ENUMERATED_to_BN(const ASN1_ENUMERATED *ai, BIGNUM *bn) +{ + return asn1_string_to_bn(ai, bn, V_ASN1_ENUMERATED); +} + +/* Internal functions used by x_int64.c */ +int c2i_uint64_int(uint64_t *ret, int *neg, const unsigned char **pp, long len) +{ + unsigned char buf[sizeof(uint64_t)]; + size_t buflen; + + buflen = c2i_ibuf(NULL, NULL, *pp, len); + if (buflen == 0) + return 0; + if (buflen > sizeof(uint64_t)) { + ASN1err(ASN1_F_C2I_UINT64_INT, ASN1_R_TOO_LARGE); + return 0; + } + (void)c2i_ibuf(buf, neg, *pp, len); + return asn1_get_uint64(ret, buf, buflen); +} + +int i2c_uint64_int(unsigned char *p, uint64_t r, int neg) +{ + unsigned char buf[sizeof(uint64_t)]; + size_t off; + + off = asn1_put_uint64(buf, r); + return i2c_ibuf(buf + off, sizeof(buf) - off, neg, &p); +} + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_mbstr.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_mbstr.c new file mode 100644 index 000000000..949fe6c16 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_mbstr.c @@ -0,0 +1,343 @@ +/* + * Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/ctype.h" +#include "internal/cryptlib.h" +#include + +static int traverse_string(const unsigned char *p, int len, int inform, + int (*rfunc) (unsigned long value, void *in), + void *arg); +static int in_utf8(unsigned long value, void *arg); +static int out_utf8(unsigned long value, void *arg); +static int type_str(unsigned long value, void *arg); +static int cpy_asc(unsigned long value, void *arg); +static int cpy_bmp(unsigned long value, void *arg); +static int cpy_univ(unsigned long value, void *arg); +static int cpy_utf8(unsigned long value, void *arg); + +/* + * These functions take a string in UTF8, ASCII or multibyte form and a mask + * of permissible ASN1 string types. It then works out the minimal type + * (using the order Numeric < Printable < IA5 < T61 < BMP < Universal < UTF8) + * and creates a string of the correct type with the supplied data. Yes this is + * horrible: it has to be :-( The 'ncopy' form checks minimum and maximum + * size limits too. + */ + +int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len, + int inform, unsigned long mask) +{ + return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0); +} + +int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, + int inform, unsigned long mask, + long minsize, long maxsize) +{ + int str_type; + int ret; + char free_out; + int outform, outlen = 0; + ASN1_STRING *dest; + unsigned char *p; + int nchar; + char strbuf[32]; + int (*cpyfunc) (unsigned long, void *) = NULL; + if (len == -1) + len = strlen((const char *)in); + if (!mask) + mask = DIRSTRING_TYPE; + + /* First do a string check and work out the number of characters */ + switch (inform) { + + case MBSTRING_BMP: + if (len & 1) { + ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, + ASN1_R_INVALID_BMPSTRING_LENGTH); + return -1; + } + nchar = len >> 1; + break; + + case MBSTRING_UNIV: + if (len & 3) { + ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, + ASN1_R_INVALID_UNIVERSALSTRING_LENGTH); + return -1; + } + nchar = len >> 2; + break; + + case MBSTRING_UTF8: + nchar = 0; + /* This counts the characters and does utf8 syntax checking */ + ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar); + if (ret < 0) { + ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_INVALID_UTF8STRING); + return -1; + } + break; + + case MBSTRING_ASC: + nchar = len; + break; + + default: + ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_UNKNOWN_FORMAT); + return -1; + } + + if ((minsize > 0) && (nchar < minsize)) { + ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_STRING_TOO_SHORT); + BIO_snprintf(strbuf, sizeof(strbuf), "%ld", minsize); + ERR_add_error_data(2, "minsize=", strbuf); + return -1; + } + + if ((maxsize > 0) && (nchar > maxsize)) { + ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_STRING_TOO_LONG); + BIO_snprintf(strbuf, sizeof(strbuf), "%ld", maxsize); + ERR_add_error_data(2, "maxsize=", strbuf); + return -1; + } + + /* Now work out minimal type (if any) */ + if (traverse_string(in, len, inform, type_str, &mask) < 0) { + ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_ILLEGAL_CHARACTERS); + return -1; + } + + /* Now work out output format and string type */ + outform = MBSTRING_ASC; + if (mask & B_ASN1_NUMERICSTRING) + str_type = V_ASN1_NUMERICSTRING; + else if (mask & B_ASN1_PRINTABLESTRING) + str_type = V_ASN1_PRINTABLESTRING; + else if (mask & B_ASN1_IA5STRING) + str_type = V_ASN1_IA5STRING; + else if (mask & B_ASN1_T61STRING) + str_type = V_ASN1_T61STRING; + else if (mask & B_ASN1_BMPSTRING) { + str_type = V_ASN1_BMPSTRING; + outform = MBSTRING_BMP; + } else if (mask & B_ASN1_UNIVERSALSTRING) { + str_type = V_ASN1_UNIVERSALSTRING; + outform = MBSTRING_UNIV; + } else { + str_type = V_ASN1_UTF8STRING; + outform = MBSTRING_UTF8; + } + if (!out) + return str_type; + if (*out) { + free_out = 0; + dest = *out; + OPENSSL_free(dest->data); + dest->data = NULL; + dest->length = 0; + dest->type = str_type; + } else { + free_out = 1; + dest = ASN1_STRING_type_new(str_type); + if (dest == NULL) { + ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ERR_R_MALLOC_FAILURE); + return -1; + } + *out = dest; + } + /* If both the same type just copy across */ + if (inform == outform) { + if (!ASN1_STRING_set(dest, in, len)) { + ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ERR_R_MALLOC_FAILURE); + return -1; + } + return str_type; + } + + /* Work out how much space the destination will need */ + switch (outform) { + case MBSTRING_ASC: + outlen = nchar; + cpyfunc = cpy_asc; + break; + + case MBSTRING_BMP: + outlen = nchar << 1; + cpyfunc = cpy_bmp; + break; + + case MBSTRING_UNIV: + outlen = nchar << 2; + cpyfunc = cpy_univ; + break; + + case MBSTRING_UTF8: + outlen = 0; + traverse_string(in, len, inform, out_utf8, &outlen); + cpyfunc = cpy_utf8; + break; + } + if ((p = OPENSSL_malloc(outlen + 1)) == NULL) { + if (free_out) + ASN1_STRING_free(dest); + ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ERR_R_MALLOC_FAILURE); + return -1; + } + dest->length = outlen; + dest->data = p; + p[outlen] = 0; + traverse_string(in, len, inform, cpyfunc, &p); + return str_type; +} + +/* + * This function traverses a string and passes the value of each character to + * an optional function along with a void * argument. + */ + +static int traverse_string(const unsigned char *p, int len, int inform, + int (*rfunc) (unsigned long value, void *in), + void *arg) +{ + unsigned long value; + int ret; + while (len) { + if (inform == MBSTRING_ASC) { + value = *p++; + len--; + } else if (inform == MBSTRING_BMP) { + value = *p++ << 8; + value |= *p++; + len -= 2; + } else if (inform == MBSTRING_UNIV) { + value = ((unsigned long)*p++) << 24; + value |= ((unsigned long)*p++) << 16; + value |= *p++ << 8; + value |= *p++; + len -= 4; + } else { + ret = UTF8_getc(p, len, &value); + if (ret < 0) + return -1; + len -= ret; + p += ret; + } + if (rfunc) { + ret = rfunc(value, arg); + if (ret <= 0) + return ret; + } + } + return 1; +} + +/* Various utility functions for traverse_string */ + +/* Just count number of characters */ + +static int in_utf8(unsigned long value, void *arg) +{ + int *nchar; + nchar = arg; + (*nchar)++; + return 1; +} + +/* Determine size of output as a UTF8 String */ + +static int out_utf8(unsigned long value, void *arg) +{ + int *outlen; + outlen = arg; + *outlen += UTF8_putc(NULL, -1, value); + return 1; +} + +/* + * Determine the "type" of a string: check each character against a supplied + * "mask". + */ + +static int type_str(unsigned long value, void *arg) +{ + unsigned long types = *((unsigned long *)arg); + const int native = value > INT_MAX ? INT_MAX : ossl_fromascii(value); + + if ((types & B_ASN1_NUMERICSTRING) && !(ossl_isdigit(native) + || native == ' ')) + types &= ~B_ASN1_NUMERICSTRING; + if ((types & B_ASN1_PRINTABLESTRING) && !ossl_isasn1print(native)) + types &= ~B_ASN1_PRINTABLESTRING; + if ((types & B_ASN1_IA5STRING) && !ossl_isascii(native)) + types &= ~B_ASN1_IA5STRING; + if ((types & B_ASN1_T61STRING) && (value > 0xff)) + types &= ~B_ASN1_T61STRING; + if ((types & B_ASN1_BMPSTRING) && (value > 0xffff)) + types &= ~B_ASN1_BMPSTRING; + if (!types) + return -1; + *((unsigned long *)arg) = types; + return 1; +} + +/* Copy one byte per character ASCII like strings */ + +static int cpy_asc(unsigned long value, void *arg) +{ + unsigned char **p, *q; + p = arg; + q = *p; + *q = (unsigned char)value; + (*p)++; + return 1; +} + +/* Copy two byte per character BMPStrings */ + +static int cpy_bmp(unsigned long value, void *arg) +{ + unsigned char **p, *q; + p = arg; + q = *p; + *q++ = (unsigned char)((value >> 8) & 0xff); + *q = (unsigned char)(value & 0xff); + *p += 2; + return 1; +} + +/* Copy four byte per character UniversalStrings */ + +static int cpy_univ(unsigned long value, void *arg) +{ + unsigned char **p, *q; + p = arg; + q = *p; + *q++ = (unsigned char)((value >> 24) & 0xff); + *q++ = (unsigned char)((value >> 16) & 0xff); + *q++ = (unsigned char)((value >> 8) & 0xff); + *q = (unsigned char)(value & 0xff); + *p += 4; + return 1; +} + +/* Copy to a UTF8String */ + +static int cpy_utf8(unsigned long value, void *arg) +{ + unsigned char **p; + int ret; + p = arg; + /* We already know there is enough room so pass 0xff as the length */ + ret = UTF8_putc(*p, 0xff, value); + *p += ret; + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_object.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_object.c new file mode 100644 index 000000000..5e1424a80 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_object.c @@ -0,0 +1,383 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/ctype.h" +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "internal/asn1_int.h" +#include "asn1_locl.h" + +int i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp) +{ + unsigned char *p, *allocated = NULL; + int objsize; + + if ((a == NULL) || (a->data == NULL)) + return 0; + + objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT); + if (pp == NULL || objsize == -1) + return objsize; + + if (*pp == NULL) { + if ((p = allocated = OPENSSL_malloc(objsize)) == NULL) { + ASN1err(ASN1_F_I2D_ASN1_OBJECT, ERR_R_MALLOC_FAILURE); + return 0; + } + } else { + p = *pp; + } + + ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL); + memcpy(p, a->data, a->length); + + /* + * If a new buffer was allocated, just return it back. + * If not, return the incremented buffer pointer. + */ + *pp = allocated != NULL ? allocated : p + a->length; + return objsize; +} + +int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num) +{ + int i, first, len = 0, c, use_bn; + char ftmp[24], *tmp = ftmp; + int tmpsize = sizeof(ftmp); + const char *p; + unsigned long l; + BIGNUM *bl = NULL; + + if (num == 0) + return 0; + else if (num == -1) + num = strlen(buf); + + p = buf; + c = *(p++); + num--; + if ((c >= '0') && (c <= '2')) { + first = c - '0'; + } else { + ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_FIRST_NUM_TOO_LARGE); + goto err; + } + + if (num <= 0) { + ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_MISSING_SECOND_NUMBER); + goto err; + } + c = *(p++); + num--; + for (;;) { + if (num <= 0) + break; + if ((c != '.') && (c != ' ')) { + ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_INVALID_SEPARATOR); + goto err; + } + l = 0; + use_bn = 0; + for (;;) { + if (num <= 0) + break; + num--; + c = *(p++); + if ((c == ' ') || (c == '.')) + break; + if (!ossl_isdigit(c)) { + ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_INVALID_DIGIT); + goto err; + } + if (!use_bn && l >= ((ULONG_MAX - 80) / 10L)) { + use_bn = 1; + if (bl == NULL) + bl = BN_new(); + if (bl == NULL || !BN_set_word(bl, l)) + goto err; + } + if (use_bn) { + if (!BN_mul_word(bl, 10L) + || !BN_add_word(bl, c - '0')) + goto err; + } else + l = l * 10L + (long)(c - '0'); + } + if (len == 0) { + if ((first < 2) && (l >= 40)) { + ASN1err(ASN1_F_A2D_ASN1_OBJECT, + ASN1_R_SECOND_NUMBER_TOO_LARGE); + goto err; + } + if (use_bn) { + if (!BN_add_word(bl, first * 40)) + goto err; + } else + l += (long)first *40; + } + i = 0; + if (use_bn) { + int blsize; + blsize = BN_num_bits(bl); + blsize = (blsize + 6) / 7; + if (blsize > tmpsize) { + if (tmp != ftmp) + OPENSSL_free(tmp); + tmpsize = blsize + 32; + tmp = OPENSSL_malloc(tmpsize); + if (tmp == NULL) + goto err; + } + while (blsize--) { + BN_ULONG t = BN_div_word(bl, 0x80L); + if (t == (BN_ULONG)-1) + goto err; + tmp[i++] = (unsigned char)t; + } + } else { + + for (;;) { + tmp[i++] = (unsigned char)l & 0x7f; + l >>= 7L; + if (l == 0L) + break; + } + + } + if (out != NULL) { + if (len + i > olen) { + ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_BUFFER_TOO_SMALL); + goto err; + } + while (--i > 0) + out[len++] = tmp[i] | 0x80; + out[len++] = tmp[0]; + } else + len += i; + } + if (tmp != ftmp) + OPENSSL_free(tmp); + BN_free(bl); + return len; + err: + if (tmp != ftmp) + OPENSSL_free(tmp); + BN_free(bl); + return 0; +} + +int i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *a) +{ + return OBJ_obj2txt(buf, buf_len, a, 0); +} + +int i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a) +{ + char buf[80], *p = buf; + int i; + + if ((a == NULL) || (a->data == NULL)) + return BIO_write(bp, "NULL", 4); + i = i2t_ASN1_OBJECT(buf, sizeof(buf), a); + if (i > (int)(sizeof(buf) - 1)) { + if ((p = OPENSSL_malloc(i + 1)) == NULL) { + ASN1err(ASN1_F_I2A_ASN1_OBJECT, ERR_R_MALLOC_FAILURE); + return -1; + } + i2t_ASN1_OBJECT(p, i + 1, a); + } + if (i <= 0) { + i = BIO_write(bp, "", 9); + i += BIO_dump(bp, (const char *)a->data, a->length); + return i; + } + BIO_write(bp, p, i); + if (p != buf) + OPENSSL_free(p); + return i; +} + +ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, + long length) +{ + const unsigned char *p; + long len; + int tag, xclass; + int inf, i; + ASN1_OBJECT *ret = NULL; + p = *pp; + inf = ASN1_get_object(&p, &len, &tag, &xclass, length); + if (inf & 0x80) { + i = ASN1_R_BAD_OBJECT_HEADER; + goto err; + } + + if (tag != V_ASN1_OBJECT) { + i = ASN1_R_EXPECTING_AN_OBJECT; + goto err; + } + ret = c2i_ASN1_OBJECT(a, &p, len); + if (ret) + *pp = p; + return ret; + err: + ASN1err(ASN1_F_D2I_ASN1_OBJECT, i); + return NULL; +} + +ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, + long len) +{ + ASN1_OBJECT *ret = NULL, tobj; + const unsigned char *p; + unsigned char *data; + int i, length; + + /* + * Sanity check OID encoding. Need at least one content octet. MSB must + * be clear in the last octet. can't have leading 0x80 in subidentifiers, + * see: X.690 8.19.2 + */ + if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL || + p[len - 1] & 0x80) { + ASN1err(ASN1_F_C2I_ASN1_OBJECT, ASN1_R_INVALID_OBJECT_ENCODING); + return NULL; + } + /* Now 0 < len <= INT_MAX, so the cast is safe. */ + length = (int)len; + /* + * Try to lookup OID in table: these are all valid encodings so if we get + * a match we know the OID is valid. + */ + tobj.nid = NID_undef; + tobj.data = p; + tobj.length = length; + tobj.flags = 0; + i = OBJ_obj2nid(&tobj); + if (i != NID_undef) { + /* + * Return shared registered OID object: this improves efficiency + * because we don't have to return a dynamically allocated OID + * and NID lookups can use the cached value. + */ + ret = OBJ_nid2obj(i); + if (a) { + ASN1_OBJECT_free(*a); + *a = ret; + } + *pp += len; + return ret; + } + for (i = 0; i < length; i++, p++) { + if (*p == 0x80 && (!i || !(p[-1] & 0x80))) { + ASN1err(ASN1_F_C2I_ASN1_OBJECT, ASN1_R_INVALID_OBJECT_ENCODING); + return NULL; + } + } + + /* + * only the ASN1_OBJECTs from the 'table' will have values for ->sn or + * ->ln + */ + if ((a == NULL) || ((*a) == NULL) || + !((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC)) { + if ((ret = ASN1_OBJECT_new()) == NULL) + return NULL; + } else + ret = (*a); + + p = *pp; + /* detach data from object */ + data = (unsigned char *)ret->data; + ret->data = NULL; + /* once detached we can change it */ + if ((data == NULL) || (ret->length < length)) { + ret->length = 0; + OPENSSL_free(data); + data = OPENSSL_malloc(length); + if (data == NULL) { + i = ERR_R_MALLOC_FAILURE; + goto err; + } + ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA; + } + memcpy(data, p, length); + /* reattach data to object, after which it remains const */ + ret->data = data; + ret->length = length; + ret->sn = NULL; + ret->ln = NULL; + /* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */ + p += length; + + if (a != NULL) + (*a) = ret; + *pp = p; + return ret; + err: + ASN1err(ASN1_F_C2I_ASN1_OBJECT, i); + if ((a == NULL) || (*a != ret)) + ASN1_OBJECT_free(ret); + return NULL; +} + +ASN1_OBJECT *ASN1_OBJECT_new(void) +{ + ASN1_OBJECT *ret; + + ret = OPENSSL_zalloc(sizeof(*ret)); + if (ret == NULL) { + ASN1err(ASN1_F_ASN1_OBJECT_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + ret->flags = ASN1_OBJECT_FLAG_DYNAMIC; + return ret; +} + +void ASN1_OBJECT_free(ASN1_OBJECT *a) +{ + if (a == NULL) + return; + if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) { +#ifndef CONST_STRICT /* disable purely for compile-time strict + * const checking. Doing this on a "real" + * compile will cause memory leaks */ + OPENSSL_free((void*)a->sn); + OPENSSL_free((void*)a->ln); +#endif + a->sn = a->ln = NULL; + } + if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) { + OPENSSL_free((void*)a->data); + a->data = NULL; + a->length = 0; + } + if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC) + OPENSSL_free(a); +} + +ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data, int len, + const char *sn, const char *ln) +{ + ASN1_OBJECT o; + + o.sn = sn; + o.ln = ln; + o.data = data; + o.nid = nid; + o.length = len; + o.flags = ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS | + ASN1_OBJECT_FLAG_DYNAMIC_DATA; + return OBJ_dup(&o); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_octet.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_octet.c new file mode 100644 index 000000000..2e1205cae --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_octet.c @@ -0,0 +1,29 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include + +ASN1_OCTET_STRING *ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *x) +{ + return ASN1_STRING_dup(x); +} + +int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a, + const ASN1_OCTET_STRING *b) +{ + return ASN1_STRING_cmp(a, b); +} + +int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *x, const unsigned char *d, + int len) +{ + return ASN1_STRING_set(x, d, len); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_print.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_print.c new file mode 100644 index 000000000..8a373d9da --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_print.c @@ -0,0 +1,95 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/ctype.h" +#include "internal/cryptlib.h" +#include + +int ASN1_PRINTABLE_type(const unsigned char *s, int len) +{ + int c; + int ia5 = 0; + int t61 = 0; + + if (len <= 0) + len = -1; + if (s == NULL) + return V_ASN1_PRINTABLESTRING; + + while ((*s) && (len-- != 0)) { + c = *(s++); + if (!ossl_isasn1print(c)) + ia5 = 1; + if (!ossl_isascii(c)) + t61 = 1; + } + if (t61) + return V_ASN1_T61STRING; + if (ia5) + return V_ASN1_IA5STRING; + return V_ASN1_PRINTABLESTRING; +} + +int ASN1_UNIVERSALSTRING_to_string(ASN1_UNIVERSALSTRING *s) +{ + int i; + unsigned char *p; + + if (s->type != V_ASN1_UNIVERSALSTRING) + return 0; + if ((s->length % 4) != 0) + return 0; + p = s->data; + for (i = 0; i < s->length; i += 4) { + if ((p[0] != '\0') || (p[1] != '\0') || (p[2] != '\0')) + break; + else + p += 4; + } + if (i < s->length) + return 0; + p = s->data; + for (i = 3; i < s->length; i += 4) { + *(p++) = s->data[i]; + } + *(p) = '\0'; + s->length /= 4; + s->type = ASN1_PRINTABLE_type(s->data, s->length); + return 1; +} + +int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v) +{ + int i, n; + char buf[80]; + const char *p; + + if (v == NULL) + return 0; + n = 0; + p = (const char *)v->data; + for (i = 0; i < v->length; i++) { + if ((p[i] > '~') || ((p[i] < ' ') && + (p[i] != '\n') && (p[i] != '\r'))) + buf[n] = '.'; + else + buf[n] = p[i]; + n++; + if (n >= 80) { + if (BIO_write(bp, buf, n) <= 0) + return 0; + n = 0; + } + } + if (n > 0) + if (BIO_write(bp, buf, n) <= 0) + return 0; + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_sign.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_sign.c new file mode 100644 index 000000000..146fdb962 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_sign.c @@ -0,0 +1,241 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include + +#include "internal/cryptlib.h" + +#include +#include +#include +#include +#include +#include "internal/asn1_int.h" +#include "internal/evp_int.h" + +#ifndef NO_ASN1_OLD + +int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1, X509_ALGOR *algor2, + ASN1_BIT_STRING *signature, char *data, EVP_PKEY *pkey, + const EVP_MD *type) +{ + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + unsigned char *p, *buf_in = NULL, *buf_out = NULL; + int i, inl = 0, outl = 0; + size_t inll = 0, outll = 0; + X509_ALGOR *a; + + if (ctx == NULL) { + ASN1err(ASN1_F_ASN1_SIGN, ERR_R_MALLOC_FAILURE); + goto err; + } + for (i = 0; i < 2; i++) { + if (i == 0) + a = algor1; + else + a = algor2; + if (a == NULL) + continue; + if (type->pkey_type == NID_dsaWithSHA1) { + /* + * special case: RFC 2459 tells us to omit 'parameters' with + * id-dsa-with-sha1 + */ + ASN1_TYPE_free(a->parameter); + a->parameter = NULL; + } else if ((a->parameter == NULL) || + (a->parameter->type != V_ASN1_NULL)) { + ASN1_TYPE_free(a->parameter); + if ((a->parameter = ASN1_TYPE_new()) == NULL) + goto err; + a->parameter->type = V_ASN1_NULL; + } + ASN1_OBJECT_free(a->algorithm); + a->algorithm = OBJ_nid2obj(type->pkey_type); + if (a->algorithm == NULL) { + ASN1err(ASN1_F_ASN1_SIGN, ASN1_R_UNKNOWN_OBJECT_TYPE); + goto err; + } + if (a->algorithm->length == 0) { + ASN1err(ASN1_F_ASN1_SIGN, + ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD); + goto err; + } + } + inl = i2d(data, NULL); + if (inl <= 0) { + ASN1err(ASN1_F_ASN1_SIGN, ERR_R_INTERNAL_ERROR); + goto err; + } + inll = (size_t)inl; + buf_in = OPENSSL_malloc(inll); + outll = outl = EVP_PKEY_size(pkey); + buf_out = OPENSSL_malloc(outll); + if (buf_in == NULL || buf_out == NULL) { + outl = 0; + ASN1err(ASN1_F_ASN1_SIGN, ERR_R_MALLOC_FAILURE); + goto err; + } + p = buf_in; + + i2d(data, &p); + if (!EVP_SignInit_ex(ctx, type, NULL) + || !EVP_SignUpdate(ctx, (unsigned char *)buf_in, inl) + || !EVP_SignFinal(ctx, (unsigned char *)buf_out, + (unsigned int *)&outl, pkey)) { + outl = 0; + ASN1err(ASN1_F_ASN1_SIGN, ERR_R_EVP_LIB); + goto err; + } + OPENSSL_free(signature->data); + signature->data = buf_out; + buf_out = NULL; + signature->length = outl; + /* + * In the interests of compatibility, I'll make sure that the bit string + * has a 'not-used bits' value of 0 + */ + signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + signature->flags |= ASN1_STRING_FLAG_BITS_LEFT; + err: + EVP_MD_CTX_free(ctx); + OPENSSL_clear_free((char *)buf_in, inll); + OPENSSL_clear_free((char *)buf_out, outll); + return outl; +} + +#endif + +int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, + X509_ALGOR *algor2, ASN1_BIT_STRING *signature, void *asn, + EVP_PKEY *pkey, const EVP_MD *type) +{ + int rv; + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + + if (ctx == NULL) { + ASN1err(ASN1_F_ASN1_ITEM_SIGN, ERR_R_MALLOC_FAILURE); + return 0; + } + if (!EVP_DigestSignInit(ctx, NULL, type, NULL, pkey)) { + EVP_MD_CTX_free(ctx); + return 0; + } + + rv = ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, ctx); + + EVP_MD_CTX_free(ctx); + return rv; +} + +int ASN1_item_sign_ctx(const ASN1_ITEM *it, + X509_ALGOR *algor1, X509_ALGOR *algor2, + ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx) +{ + const EVP_MD *type; + EVP_PKEY *pkey; + unsigned char *buf_in = NULL, *buf_out = NULL; + size_t inl = 0, outl = 0, outll = 0; + int signid, paramtype, buf_len = 0; + int rv; + + type = EVP_MD_CTX_md(ctx); + pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_pkey_ctx(ctx)); + + if (pkey == NULL) { + ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_CONTEXT_NOT_INITIALISED); + goto err; + } + + if (pkey->ameth == NULL) { + ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED); + goto err; + } + + if (pkey->ameth->item_sign) { + rv = pkey->ameth->item_sign(ctx, it, asn, algor1, algor2, signature); + if (rv == 1) + outl = signature->length; + /*- + * Return value meanings: + * <=0: error. + * 1: method does everything. + * 2: carry on as normal. + * 3: ASN1 method sets algorithm identifiers: just sign. + */ + if (rv <= 0) + ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB); + if (rv <= 1) + goto err; + } else { + rv = 2; + } + + if (rv == 2) { + if (type == NULL) { + ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_CONTEXT_NOT_INITIALISED); + goto err; + } + if (!OBJ_find_sigid_by_algs(&signid, + EVP_MD_nid(type), + pkey->ameth->pkey_id)) { + ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, + ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED); + goto err; + } + + if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL) + paramtype = V_ASN1_NULL; + else + paramtype = V_ASN1_UNDEF; + + if (algor1) + X509_ALGOR_set0(algor1, OBJ_nid2obj(signid), paramtype, NULL); + if (algor2) + X509_ALGOR_set0(algor2, OBJ_nid2obj(signid), paramtype, NULL); + + } + + buf_len = ASN1_item_i2d(asn, &buf_in, it); + if (buf_len <= 0) { + outl = 0; + ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_INTERNAL_ERROR); + goto err; + } + inl = buf_len; + outll = outl = EVP_PKEY_size(pkey); + buf_out = OPENSSL_malloc(outll); + if (buf_in == NULL || buf_out == NULL) { + outl = 0; + ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!EVP_DigestSign(ctx, buf_out, &outl, buf_in, inl)) { + outl = 0; + ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB); + goto err; + } + OPENSSL_free(signature->data); + signature->data = buf_out; + buf_out = NULL; + signature->length = outl; + /* + * In the interests of compatibility, I'll make sure that the bit string + * has a 'not-used bits' value of 0 + */ + signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + signature->flags |= ASN1_STRING_FLAG_BITS_LEFT; + err: + OPENSSL_clear_free((char *)buf_in, inl); + OPENSSL_clear_free((char *)buf_out, outll); + return outl; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_strex.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_strex.c new file mode 100644 index 000000000..ea4dd1c5b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_strex.c @@ -0,0 +1,626 @@ +/* + * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include "internal/asn1_int.h" +#include +#include +#include + +#include "charmap.h" + +/* + * ASN1_STRING_print_ex() and X509_NAME_print_ex(). Enhanced string and name + * printing routines handling multibyte characters, RFC2253 and a host of + * other options. + */ + +#define CHARTYPE_BS_ESC (ASN1_STRFLGS_ESC_2253 | CHARTYPE_FIRST_ESC_2253 | CHARTYPE_LAST_ESC_2253) + +#define ESC_FLAGS (ASN1_STRFLGS_ESC_2253 | \ + ASN1_STRFLGS_ESC_2254 | \ + ASN1_STRFLGS_ESC_QUOTE | \ + ASN1_STRFLGS_ESC_CTRL | \ + ASN1_STRFLGS_ESC_MSB) + +/* + * Three IO functions for sending data to memory, a BIO and and a FILE + * pointer. + */ +static int send_bio_chars(void *arg, const void *buf, int len) +{ + if (!arg) + return 1; + if (BIO_write(arg, buf, len) != len) + return 0; + return 1; +} + +#ifndef OPENSSL_NO_STDIO +static int send_fp_chars(void *arg, const void *buf, int len) +{ + if (!arg) + return 1; + if (fwrite(buf, 1, len, arg) != (unsigned int)len) + return 0; + return 1; +} +#endif + +typedef int char_io (void *arg, const void *buf, int len); + +/* + * This function handles display of strings, one character at a time. It is + * passed an unsigned long for each character because it could come from 2 or + * even 4 byte forms. + */ + +static int do_esc_char(unsigned long c, unsigned short flags, char *do_quotes, + char_io *io_ch, void *arg) +{ + unsigned short chflgs; + unsigned char chtmp; + char tmphex[HEX_SIZE(long) + 3]; + + if (c > 0xffffffffL) + return -1; + if (c > 0xffff) { + BIO_snprintf(tmphex, sizeof(tmphex), "\\W%08lX", c); + if (!io_ch(arg, tmphex, 10)) + return -1; + return 10; + } + if (c > 0xff) { + BIO_snprintf(tmphex, sizeof(tmphex), "\\U%04lX", c); + if (!io_ch(arg, tmphex, 6)) + return -1; + return 6; + } + chtmp = (unsigned char)c; + if (chtmp > 0x7f) + chflgs = flags & ASN1_STRFLGS_ESC_MSB; + else + chflgs = char_type[chtmp] & flags; + if (chflgs & CHARTYPE_BS_ESC) { + /* If we don't escape with quotes, signal we need quotes */ + if (chflgs & ASN1_STRFLGS_ESC_QUOTE) { + if (do_quotes) + *do_quotes = 1; + if (!io_ch(arg, &chtmp, 1)) + return -1; + return 1; + } + if (!io_ch(arg, "\\", 1)) + return -1; + if (!io_ch(arg, &chtmp, 1)) + return -1; + return 2; + } + if (chflgs & (ASN1_STRFLGS_ESC_CTRL + | ASN1_STRFLGS_ESC_MSB + | ASN1_STRFLGS_ESC_2254)) { + BIO_snprintf(tmphex, 11, "\\%02X", chtmp); + if (!io_ch(arg, tmphex, 3)) + return -1; + return 3; + } + /* + * If we get this far and do any escaping at all must escape the escape + * character itself: backslash. + */ + if (chtmp == '\\' && (flags & ESC_FLAGS)) { + if (!io_ch(arg, "\\\\", 2)) + return -1; + return 2; + } + if (!io_ch(arg, &chtmp, 1)) + return -1; + return 1; +} + +#define BUF_TYPE_WIDTH_MASK 0x7 +#define BUF_TYPE_CONVUTF8 0x8 + +/* + * This function sends each character in a buffer to do_esc_char(). It + * interprets the content formats and converts to or from UTF8 as + * appropriate. + */ + +static int do_buf(unsigned char *buf, int buflen, + int type, unsigned short flags, char *quotes, char_io *io_ch, + void *arg) +{ + int i, outlen, len, charwidth; + unsigned short orflags; + unsigned char *p, *q; + unsigned long c; + + p = buf; + q = buf + buflen; + outlen = 0; + charwidth = type & BUF_TYPE_WIDTH_MASK; + + switch (charwidth) { + case 4: + if (buflen & 3) { + ASN1err(ASN1_F_DO_BUF, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH); + return -1; + } + break; + case 2: + if (buflen & 1) { + ASN1err(ASN1_F_DO_BUF, ASN1_R_INVALID_BMPSTRING_LENGTH); + return -1; + } + break; + default: + break; + } + + while (p != q) { + if (p == buf && flags & ASN1_STRFLGS_ESC_2253) + orflags = CHARTYPE_FIRST_ESC_2253; + else + orflags = 0; + + switch (charwidth) { + case 4: + c = ((unsigned long)*p++) << 24; + c |= ((unsigned long)*p++) << 16; + c |= ((unsigned long)*p++) << 8; + c |= *p++; + break; + + case 2: + c = ((unsigned long)*p++) << 8; + c |= *p++; + break; + + case 1: + c = *p++; + break; + + case 0: + i = UTF8_getc(p, buflen, &c); + if (i < 0) + return -1; /* Invalid UTF8String */ + buflen -= i; + p += i; + break; + default: + return -1; /* invalid width */ + } + if (p == q && flags & ASN1_STRFLGS_ESC_2253) + orflags = CHARTYPE_LAST_ESC_2253; + if (type & BUF_TYPE_CONVUTF8) { + unsigned char utfbuf[6]; + int utflen; + utflen = UTF8_putc(utfbuf, sizeof(utfbuf), c); + for (i = 0; i < utflen; i++) { + /* + * We don't need to worry about setting orflags correctly + * because if utflen==1 its value will be correct anyway + * otherwise each character will be > 0x7f and so the + * character will never be escaped on first and last. + */ + len = do_esc_char(utfbuf[i], flags | orflags, quotes, + io_ch, arg); + if (len < 0) + return -1; + outlen += len; + } + } else { + len = do_esc_char(c, flags | orflags, quotes, + io_ch, arg); + if (len < 0) + return -1; + outlen += len; + } + } + return outlen; +} + +/* This function hex dumps a buffer of characters */ + +static int do_hex_dump(char_io *io_ch, void *arg, unsigned char *buf, + int buflen) +{ + static const char hexdig[] = "0123456789ABCDEF"; + unsigned char *p, *q; + char hextmp[2]; + if (arg) { + p = buf; + q = buf + buflen; + while (p != q) { + hextmp[0] = hexdig[*p >> 4]; + hextmp[1] = hexdig[*p & 0xf]; + if (!io_ch(arg, hextmp, 2)) + return -1; + p++; + } + } + return buflen << 1; +} + +/* + * "dump" a string. This is done when the type is unknown, or the flags + * request it. We can either dump the content octets or the entire DER + * encoding. This uses the RFC2253 #01234 format. + */ + +static int do_dump(unsigned long lflags, char_io *io_ch, void *arg, + const ASN1_STRING *str) +{ + /* + * Placing the ASN1_STRING in a temp ASN1_TYPE allows the DER encoding to + * readily obtained + */ + ASN1_TYPE t; + unsigned char *der_buf, *p; + int outlen, der_len; + + if (!io_ch(arg, "#", 1)) + return -1; + /* If we don't dump DER encoding just dump content octets */ + if (!(lflags & ASN1_STRFLGS_DUMP_DER)) { + outlen = do_hex_dump(io_ch, arg, str->data, str->length); + if (outlen < 0) + return -1; + return outlen + 1; + } + t.type = str->type; + t.value.ptr = (char *)str; + der_len = i2d_ASN1_TYPE(&t, NULL); + if ((der_buf = OPENSSL_malloc(der_len)) == NULL) { + ASN1err(ASN1_F_DO_DUMP, ERR_R_MALLOC_FAILURE); + return -1; + } + p = der_buf; + i2d_ASN1_TYPE(&t, &p); + outlen = do_hex_dump(io_ch, arg, der_buf, der_len); + OPENSSL_free(der_buf); + if (outlen < 0) + return -1; + return outlen + 1; +} + +/* + * Lookup table to convert tags to character widths, 0 = UTF8 encoded, -1 is + * used for non string types otherwise it is the number of bytes per + * character + */ + +static const signed char tag2nbyte[] = { + -1, -1, -1, -1, -1, /* 0-4 */ + -1, -1, -1, -1, -1, /* 5-9 */ + -1, -1, /* 10-11 */ + 0, /* 12 V_ASN1_UTF8STRING */ + -1, -1, -1, -1, -1, /* 13-17 */ + 1, /* 18 V_ASN1_NUMERICSTRING */ + 1, /* 19 V_ASN1_PRINTABLESTRING */ + 1, /* 20 V_ASN1_T61STRING */ + -1, /* 21 */ + 1, /* 22 V_ASN1_IA5STRING */ + 1, /* 23 V_ASN1_UTCTIME */ + 1, /* 24 V_ASN1_GENERALIZEDTIME */ + -1, /* 25 */ + 1, /* 26 V_ASN1_ISO64STRING */ + -1, /* 27 */ + 4, /* 28 V_ASN1_UNIVERSALSTRING */ + -1, /* 29 */ + 2 /* 30 V_ASN1_BMPSTRING */ +}; + +/* + * This is the main function, print out an ASN1_STRING taking note of various + * escape and display options. Returns number of characters written or -1 if + * an error occurred. + */ + +static int do_print_ex(char_io *io_ch, void *arg, unsigned long lflags, + const ASN1_STRING *str) +{ + int outlen, len; + int type; + char quotes; + unsigned short flags; + quotes = 0; + /* Keep a copy of escape flags */ + flags = (unsigned short)(lflags & ESC_FLAGS); + + type = str->type; + + outlen = 0; + + if (lflags & ASN1_STRFLGS_SHOW_TYPE) { + const char *tagname; + tagname = ASN1_tag2str(type); + outlen += strlen(tagname); + if (!io_ch(arg, tagname, outlen) || !io_ch(arg, ":", 1)) + return -1; + outlen++; + } + + /* Decide what to do with type, either dump content or display it */ + + /* Dump everything */ + if (lflags & ASN1_STRFLGS_DUMP_ALL) + type = -1; + /* Ignore the string type */ + else if (lflags & ASN1_STRFLGS_IGNORE_TYPE) + type = 1; + else { + /* Else determine width based on type */ + if ((type > 0) && (type < 31)) + type = tag2nbyte[type]; + else + type = -1; + if ((type == -1) && !(lflags & ASN1_STRFLGS_DUMP_UNKNOWN)) + type = 1; + } + + if (type == -1) { + len = do_dump(lflags, io_ch, arg, str); + if (len < 0) + return -1; + outlen += len; + return outlen; + } + + if (lflags & ASN1_STRFLGS_UTF8_CONVERT) { + /* + * Note: if string is UTF8 and we want to convert to UTF8 then we + * just interpret it as 1 byte per character to avoid converting + * twice. + */ + if (!type) + type = 1; + else + type |= BUF_TYPE_CONVUTF8; + } + + len = do_buf(str->data, str->length, type, flags, "es, io_ch, NULL); + if (len < 0) + return -1; + outlen += len; + if (quotes) + outlen += 2; + if (!arg) + return outlen; + if (quotes && !io_ch(arg, "\"", 1)) + return -1; + if (do_buf(str->data, str->length, type, flags, NULL, io_ch, arg) < 0) + return -1; + if (quotes && !io_ch(arg, "\"", 1)) + return -1; + return outlen; +} + +/* Used for line indenting: print 'indent' spaces */ + +static int do_indent(char_io *io_ch, void *arg, int indent) +{ + int i; + for (i = 0; i < indent; i++) + if (!io_ch(arg, " ", 1)) + return 0; + return 1; +} + +#define FN_WIDTH_LN 25 +#define FN_WIDTH_SN 10 + +static int do_name_ex(char_io *io_ch, void *arg, const X509_NAME *n, + int indent, unsigned long flags) +{ + int i, prev = -1, orflags, cnt; + int fn_opt, fn_nid; + ASN1_OBJECT *fn; + const ASN1_STRING *val; + const X509_NAME_ENTRY *ent; + char objtmp[80]; + const char *objbuf; + int outlen, len; + char *sep_dn, *sep_mv, *sep_eq; + int sep_dn_len, sep_mv_len, sep_eq_len; + if (indent < 0) + indent = 0; + outlen = indent; + if (!do_indent(io_ch, arg, indent)) + return -1; + switch (flags & XN_FLAG_SEP_MASK) { + case XN_FLAG_SEP_MULTILINE: + sep_dn = "\n"; + sep_dn_len = 1; + sep_mv = " + "; + sep_mv_len = 3; + break; + + case XN_FLAG_SEP_COMMA_PLUS: + sep_dn = ","; + sep_dn_len = 1; + sep_mv = "+"; + sep_mv_len = 1; + indent = 0; + break; + + case XN_FLAG_SEP_CPLUS_SPC: + sep_dn = ", "; + sep_dn_len = 2; + sep_mv = " + "; + sep_mv_len = 3; + indent = 0; + break; + + case XN_FLAG_SEP_SPLUS_SPC: + sep_dn = "; "; + sep_dn_len = 2; + sep_mv = " + "; + sep_mv_len = 3; + indent = 0; + break; + + default: + return -1; + } + + if (flags & XN_FLAG_SPC_EQ) { + sep_eq = " = "; + sep_eq_len = 3; + } else { + sep_eq = "="; + sep_eq_len = 1; + } + + fn_opt = flags & XN_FLAG_FN_MASK; + + cnt = X509_NAME_entry_count(n); + for (i = 0; i < cnt; i++) { + if (flags & XN_FLAG_DN_REV) + ent = X509_NAME_get_entry(n, cnt - i - 1); + else + ent = X509_NAME_get_entry(n, i); + if (prev != -1) { + if (prev == X509_NAME_ENTRY_set(ent)) { + if (!io_ch(arg, sep_mv, sep_mv_len)) + return -1; + outlen += sep_mv_len; + } else { + if (!io_ch(arg, sep_dn, sep_dn_len)) + return -1; + outlen += sep_dn_len; + if (!do_indent(io_ch, arg, indent)) + return -1; + outlen += indent; + } + } + prev = X509_NAME_ENTRY_set(ent); + fn = X509_NAME_ENTRY_get_object(ent); + val = X509_NAME_ENTRY_get_data(ent); + fn_nid = OBJ_obj2nid(fn); + if (fn_opt != XN_FLAG_FN_NONE) { + int objlen, fld_len; + if ((fn_opt == XN_FLAG_FN_OID) || (fn_nid == NID_undef)) { + OBJ_obj2txt(objtmp, sizeof(objtmp), fn, 1); + fld_len = 0; /* XXX: what should this be? */ + objbuf = objtmp; + } else { + if (fn_opt == XN_FLAG_FN_SN) { + fld_len = FN_WIDTH_SN; + objbuf = OBJ_nid2sn(fn_nid); + } else if (fn_opt == XN_FLAG_FN_LN) { + fld_len = FN_WIDTH_LN; + objbuf = OBJ_nid2ln(fn_nid); + } else { + fld_len = 0; /* XXX: what should this be? */ + objbuf = ""; + } + } + objlen = strlen(objbuf); + if (!io_ch(arg, objbuf, objlen)) + return -1; + if ((objlen < fld_len) && (flags & XN_FLAG_FN_ALIGN)) { + if (!do_indent(io_ch, arg, fld_len - objlen)) + return -1; + outlen += fld_len - objlen; + } + if (!io_ch(arg, sep_eq, sep_eq_len)) + return -1; + outlen += objlen + sep_eq_len; + } + /* + * If the field name is unknown then fix up the DER dump flag. We + * might want to limit this further so it will DER dump on anything + * other than a few 'standard' fields. + */ + if ((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS)) + orflags = ASN1_STRFLGS_DUMP_ALL; + else + orflags = 0; + + len = do_print_ex(io_ch, arg, flags | orflags, val); + if (len < 0) + return -1; + outlen += len; + } + return outlen; +} + +/* Wrappers round the main functions */ + +int X509_NAME_print_ex(BIO *out, const X509_NAME *nm, int indent, + unsigned long flags) +{ + if (flags == XN_FLAG_COMPAT) + return X509_NAME_print(out, nm, indent); + return do_name_ex(send_bio_chars, out, nm, indent, flags); +} + +#ifndef OPENSSL_NO_STDIO +int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm, int indent, + unsigned long flags) +{ + if (flags == XN_FLAG_COMPAT) { + BIO *btmp; + int ret; + btmp = BIO_new_fp(fp, BIO_NOCLOSE); + if (!btmp) + return -1; + ret = X509_NAME_print(btmp, nm, indent); + BIO_free(btmp); + return ret; + } + return do_name_ex(send_fp_chars, fp, nm, indent, flags); +} +#endif + +int ASN1_STRING_print_ex(BIO *out, const ASN1_STRING *str, unsigned long flags) +{ + return do_print_ex(send_bio_chars, out, flags, str); +} + +#ifndef OPENSSL_NO_STDIO +int ASN1_STRING_print_ex_fp(FILE *fp, const ASN1_STRING *str, unsigned long flags) +{ + return do_print_ex(send_fp_chars, fp, flags, str); +} +#endif + +/* + * Utility function: convert any string type to UTF8, returns number of bytes + * in output string or a negative error code + */ + +int ASN1_STRING_to_UTF8(unsigned char **out, const ASN1_STRING *in) +{ + ASN1_STRING stmp, *str = &stmp; + int mbflag, type, ret; + if (!in) + return -1; + type = in->type; + if ((type < 0) || (type > 30)) + return -1; + mbflag = tag2nbyte[type]; + if (mbflag == -1) + return -1; + mbflag |= MBSTRING_FLAG; + stmp.data = NULL; + stmp.length = 0; + stmp.flags = 0; + ret = + ASN1_mbstring_copy(&str, in->data, in->length, mbflag, + B_ASN1_UTF8STRING); + if (ret < 0) + return ret; + *out = stmp.data; + return stmp.length; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_strnid.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_strnid.c new file mode 100644 index 000000000..f19a9de64 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_strnid.c @@ -0,0 +1,219 @@ +/* + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include + +static STACK_OF(ASN1_STRING_TABLE) *stable = NULL; +static void st_free(ASN1_STRING_TABLE *tbl); +static int sk_table_cmp(const ASN1_STRING_TABLE *const *a, + const ASN1_STRING_TABLE *const *b); + +/* + * This is the global mask for the mbstring functions: this is use to mask + * out certain types (such as BMPString and UTF8String) because certain + * software (e.g. Netscape) has problems with them. + */ + +static unsigned long global_mask = B_ASN1_UTF8STRING; + +void ASN1_STRING_set_default_mask(unsigned long mask) +{ + global_mask = mask; +} + +unsigned long ASN1_STRING_get_default_mask(void) +{ + return global_mask; +} + +/*- + * This function sets the default to various "flavours" of configuration. + * based on an ASCII string. Currently this is: + * MASK:XXXX : a numerical mask value. + * nobmp : Don't use BMPStrings (just Printable, T61). + * pkix : PKIX recommendation in RFC2459. + * utf8only : only use UTF8Strings (RFC2459 recommendation for 2004). + * default: the default value, Printable, T61, BMP. + */ + +int ASN1_STRING_set_default_mask_asc(const char *p) +{ + unsigned long mask; + char *end; + + if (strncmp(p, "MASK:", 5) == 0) { + if (!p[5]) + return 0; + mask = strtoul(p + 5, &end, 0); + if (*end) + return 0; + } else if (strcmp(p, "nombstr") == 0) + mask = ~((unsigned long)(B_ASN1_BMPSTRING | B_ASN1_UTF8STRING)); + else if (strcmp(p, "pkix") == 0) + mask = ~((unsigned long)B_ASN1_T61STRING); + else if (strcmp(p, "utf8only") == 0) + mask = B_ASN1_UTF8STRING; + else if (strcmp(p, "default") == 0) + mask = 0xFFFFFFFFL; + else + return 0; + ASN1_STRING_set_default_mask(mask); + return 1; +} + +/* + * The following function generates an ASN1_STRING based on limits in a + * table. Frequently the types and length of an ASN1_STRING are restricted by + * a corresponding OID. For example certificates and certificate requests. + */ + +ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, + const unsigned char *in, int inlen, + int inform, int nid) +{ + ASN1_STRING_TABLE *tbl; + ASN1_STRING *str = NULL; + unsigned long mask; + int ret; + + if (out == NULL) + out = &str; + tbl = ASN1_STRING_TABLE_get(nid); + if (tbl != NULL) { + mask = tbl->mask; + if (!(tbl->flags & STABLE_NO_MASK)) + mask &= global_mask; + ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask, + tbl->minsize, tbl->maxsize); + } else { + ret = ASN1_mbstring_copy(out, in, inlen, inform, + DIRSTRING_TYPE & global_mask); + } + if (ret <= 0) + return NULL; + return *out; +} + +/* + * Now the tables and helper functions for the string table: + */ + +#include "tbl_standard.h" + +static int sk_table_cmp(const ASN1_STRING_TABLE *const *a, + const ASN1_STRING_TABLE *const *b) +{ + return (*a)->nid - (*b)->nid; +} + +DECLARE_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table); + +static int table_cmp(const ASN1_STRING_TABLE *a, const ASN1_STRING_TABLE *b) +{ + return a->nid - b->nid; +} + +IMPLEMENT_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table); + +ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid) +{ + int idx; + ASN1_STRING_TABLE fnd; + + fnd.nid = nid; + if (stable) { + idx = sk_ASN1_STRING_TABLE_find(stable, &fnd); + if (idx >= 0) + return sk_ASN1_STRING_TABLE_value(stable, idx); + } + return OBJ_bsearch_table(&fnd, tbl_standard, OSSL_NELEM(tbl_standard)); +} + +/* + * Return a string table pointer which can be modified: either directly from + * table or a copy of an internal value added to the table. + */ + +static ASN1_STRING_TABLE *stable_get(int nid) +{ + ASN1_STRING_TABLE *tmp, *rv; + + /* Always need a string table so allocate one if NULL */ + if (stable == NULL) { + stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp); + if (stable == NULL) + return NULL; + } + tmp = ASN1_STRING_TABLE_get(nid); + if (tmp != NULL && tmp->flags & STABLE_FLAGS_MALLOC) + return tmp; + if ((rv = OPENSSL_zalloc(sizeof(*rv))) == NULL) { + ASN1err(ASN1_F_STABLE_GET, ERR_R_MALLOC_FAILURE); + return NULL; + } + if (!sk_ASN1_STRING_TABLE_push(stable, rv)) { + OPENSSL_free(rv); + return NULL; + } + if (tmp != NULL) { + rv->nid = tmp->nid; + rv->minsize = tmp->minsize; + rv->maxsize = tmp->maxsize; + rv->mask = tmp->mask; + rv->flags = tmp->flags | STABLE_FLAGS_MALLOC; + } else { + rv->nid = nid; + rv->minsize = -1; + rv->maxsize = -1; + rv->flags = STABLE_FLAGS_MALLOC; + } + return rv; +} + +int ASN1_STRING_TABLE_add(int nid, + long minsize, long maxsize, unsigned long mask, + unsigned long flags) +{ + ASN1_STRING_TABLE *tmp; + + tmp = stable_get(nid); + if (tmp == NULL) { + ASN1err(ASN1_F_ASN1_STRING_TABLE_ADD, ERR_R_MALLOC_FAILURE); + return 0; + } + if (minsize >= 0) + tmp->minsize = minsize; + if (maxsize >= 0) + tmp->maxsize = maxsize; + if (mask) + tmp->mask = mask; + if (flags) + tmp->flags = STABLE_FLAGS_MALLOC | flags; + return 1; +} + +void ASN1_STRING_TABLE_cleanup(void) +{ + STACK_OF(ASN1_STRING_TABLE) *tmp; + + tmp = stable; + if (tmp == NULL) + return; + stable = NULL; + sk_ASN1_STRING_TABLE_pop_free(tmp, st_free); +} + +static void st_free(ASN1_STRING_TABLE *tbl) +{ + if (tbl->flags & STABLE_FLAGS_MALLOC) + OPENSSL_free(tbl); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_time.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_time.c new file mode 100644 index 000000000..1babb9636 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_time.c @@ -0,0 +1,553 @@ +/* + * Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * This is an implementation of the ASN1 Time structure which is: + * Time ::= CHOICE { + * utcTime UTCTime, + * generalTime GeneralizedTime } + */ + +#include +#include +#include "internal/ctype.h" +#include "internal/cryptlib.h" +#include +#include "asn1_locl.h" + +IMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME) + +IMPLEMENT_ASN1_FUNCTIONS(ASN1_TIME) + +static int is_utc(const int year) +{ + if (50 <= year && year <= 149) + return 1; + return 0; +} + +static int leap_year(const int year) +{ + if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) + return 1; + return 0; +} + +/* + * Compute the day of the week and the day of the year from the year, month + * and day. The day of the year is straightforward, the day of the week uses + * a form of Zeller's congruence. For this months start with March and are + * numbered 4 through 15. + */ +static void determine_days(struct tm *tm) +{ + static const int ydays[12] = { + 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 + }; + int y = tm->tm_year + 1900; + int m = tm->tm_mon; + int d = tm->tm_mday; + int c; + + tm->tm_yday = ydays[m] + d - 1; + if (m >= 2) { + /* March and onwards can be one day further into the year */ + tm->tm_yday += leap_year(y); + m += 2; + } else { + /* Treat January and February as part of the previous year */ + m += 14; + y--; + } + c = y / 100; + y %= 100; + /* Zeller's congruance */ + tm->tm_wday = (d + (13 * m) / 5 + y + y / 4 + c / 4 + 5 * c + 6) % 7; +} + +int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d) +{ + static const int min[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 }; + static const int max[9] = { 99, 99, 12, 31, 23, 59, 59, 12, 59 }; + static const int mdays[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + char *a; + int n, i, i2, l, o, min_l = 11, strict = 0, end = 6, btz = 5, md; + struct tm tmp; + + /* + * ASN1_STRING_FLAG_X509_TIME is used to enforce RFC 5280 + * time string format, in which: + * + * 1. "seconds" is a 'MUST' + * 2. "Zulu" timezone is a 'MUST' + * 3. "+|-" is not allowed to indicate a time zone + */ + if (d->type == V_ASN1_UTCTIME) { + if (d->flags & ASN1_STRING_FLAG_X509_TIME) { + min_l = 13; + strict = 1; + } + } else if (d->type == V_ASN1_GENERALIZEDTIME) { + end = 7; + btz = 6; + if (d->flags & ASN1_STRING_FLAG_X509_TIME) { + min_l = 15; + strict = 1; + } else { + min_l = 13; + } + } else { + return 0; + } + + l = d->length; + a = (char *)d->data; + o = 0; + memset(&tmp, 0, sizeof(tmp)); + + /* + * GENERALIZEDTIME is similar to UTCTIME except the year is represented + * as YYYY. This stuff treats everything as a two digit field so make + * first two fields 00 to 99 + */ + + if (l < min_l) + goto err; + for (i = 0; i < end; i++) { + if (!strict && (i == btz) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) { + i++; + break; + } + if (!ossl_isdigit(a[o])) + goto err; + n = a[o] - '0'; + /* incomplete 2-digital number */ + if (++o == l) + goto err; + + if (!ossl_isdigit(a[o])) + goto err; + n = (n * 10) + a[o] - '0'; + /* no more bytes to read, but we haven't seen time-zone yet */ + if (++o == l) + goto err; + + i2 = (d->type == V_ASN1_UTCTIME) ? i + 1 : i; + + if ((n < min[i2]) || (n > max[i2])) + goto err; + switch (i2) { + case 0: + /* UTC will never be here */ + tmp.tm_year = n * 100 - 1900; + break; + case 1: + if (d->type == V_ASN1_UTCTIME) + tmp.tm_year = n < 50 ? n + 100 : n; + else + tmp.tm_year += n; + break; + case 2: + tmp.tm_mon = n - 1; + break; + case 3: + /* check if tm_mday is valid in tm_mon */ + if (tmp.tm_mon == 1) { + /* it's February */ + md = mdays[1] + leap_year(tmp.tm_year + 1900); + } else { + md = mdays[tmp.tm_mon]; + } + if (n > md) + goto err; + tmp.tm_mday = n; + determine_days(&tmp); + break; + case 4: + tmp.tm_hour = n; + break; + case 5: + tmp.tm_min = n; + break; + case 6: + tmp.tm_sec = n; + break; + } + } + + /* + * Optional fractional seconds: decimal point followed by one or more + * digits. + */ + if (d->type == V_ASN1_GENERALIZEDTIME && a[o] == '.') { + if (strict) + /* RFC 5280 forbids fractional seconds */ + goto err; + if (++o == l) + goto err; + i = o; + while ((o < l) && ossl_isdigit(a[o])) + o++; + /* Must have at least one digit after decimal point */ + if (i == o) + goto err; + /* no more bytes to read, but we haven't seen time-zone yet */ + if (o == l) + goto err; + } + + /* + * 'o' will never point to '\0' at this point, the only chance + * 'o' can point to '\0' is either the subsequent if or the first + * else if is true. + */ + if (a[o] == 'Z') { + o++; + } else if (!strict && ((a[o] == '+') || (a[o] == '-'))) { + int offsign = a[o] == '-' ? 1 : -1; + int offset = 0; + + o++; + /* + * if not equal, no need to do subsequent checks + * since the following for-loop will add 'o' by 4 + * and the final return statement will check if 'l' + * and 'o' are equal. + */ + if (o + 4 != l) + goto err; + for (i = end; i < end + 2; i++) { + if (!ossl_isdigit(a[o])) + goto err; + n = a[o] - '0'; + o++; + if (!ossl_isdigit(a[o])) + goto err; + n = (n * 10) + a[o] - '0'; + i2 = (d->type == V_ASN1_UTCTIME) ? i + 1 : i; + if ((n < min[i2]) || (n > max[i2])) + goto err; + /* if tm is NULL, no need to adjust */ + if (tm != NULL) { + if (i == end) + offset = n * 3600; + else if (i == end + 1) + offset += n * 60; + } + o++; + } + if (offset && !OPENSSL_gmtime_adj(&tmp, 0, offset * offsign)) + goto err; + } else { + /* not Z, or not +/- in non-strict mode */ + goto err; + } + if (o == l) { + /* success, check if tm should be filled */ + if (tm != NULL) + *tm = tmp; + return 1; + } + err: + return 0; +} + +ASN1_TIME *asn1_time_from_tm(ASN1_TIME *s, struct tm *ts, int type) +{ + char* p; + ASN1_TIME *tmps = NULL; + const size_t len = 20; + + if (type == V_ASN1_UNDEF) { + if (is_utc(ts->tm_year)) + type = V_ASN1_UTCTIME; + else + type = V_ASN1_GENERALIZEDTIME; + } else if (type == V_ASN1_UTCTIME) { + if (!is_utc(ts->tm_year)) + goto err; + } else if (type != V_ASN1_GENERALIZEDTIME) { + goto err; + } + + if (s == NULL) + tmps = ASN1_STRING_new(); + else + tmps = s; + if (tmps == NULL) + return NULL; + + if (!ASN1_STRING_set(tmps, NULL, len)) + goto err; + + tmps->type = type; + p = (char*)tmps->data; + + if (type == V_ASN1_GENERALIZEDTIME) + tmps->length = BIO_snprintf(p, len, "%04d%02d%02d%02d%02d%02dZ", + ts->tm_year + 1900, ts->tm_mon + 1, + ts->tm_mday, ts->tm_hour, ts->tm_min, + ts->tm_sec); + else + tmps->length = BIO_snprintf(p, len, "%02d%02d%02d%02d%02d%02dZ", + ts->tm_year % 100, ts->tm_mon + 1, + ts->tm_mday, ts->tm_hour, ts->tm_min, + ts->tm_sec); + +#ifdef CHARSET_EBCDIC_not + ebcdic2ascii(tmps->data, tmps->data, tmps->length); +#endif + return tmps; + err: + if (tmps != s) + ASN1_STRING_free(tmps); + return NULL; +} + +ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t) +{ + return ASN1_TIME_adj(s, t, 0, 0); +} + +ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t, + int offset_day, long offset_sec) +{ + struct tm *ts; + struct tm data; + + ts = OPENSSL_gmtime(&t, &data); + if (ts == NULL) { + ASN1err(ASN1_F_ASN1_TIME_ADJ, ASN1_R_ERROR_GETTING_TIME); + return NULL; + } + if (offset_day || offset_sec) { + if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec)) + return NULL; + } + return asn1_time_from_tm(s, ts, V_ASN1_UNDEF); +} + +int ASN1_TIME_check(const ASN1_TIME *t) +{ + if (t->type == V_ASN1_GENERALIZEDTIME) + return ASN1_GENERALIZEDTIME_check(t); + else if (t->type == V_ASN1_UTCTIME) + return ASN1_UTCTIME_check(t); + return 0; +} + +/* Convert an ASN1_TIME structure to GeneralizedTime */ +ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(const ASN1_TIME *t, + ASN1_GENERALIZEDTIME **out) +{ + ASN1_GENERALIZEDTIME *ret = NULL; + struct tm tm; + + if (!ASN1_TIME_to_tm(t, &tm)) + return NULL; + + if (out != NULL) + ret = *out; + + ret = asn1_time_from_tm(ret, &tm, V_ASN1_GENERALIZEDTIME); + + if (out != NULL && ret != NULL) + *out = ret; + + return ret; +} + +int ASN1_TIME_set_string(ASN1_TIME *s, const char *str) +{ + /* Try UTC, if that fails, try GENERALIZED */ + if (ASN1_UTCTIME_set_string(s, str)) + return 1; + return ASN1_GENERALIZEDTIME_set_string(s, str); +} + +int ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str) +{ + ASN1_TIME t; + struct tm tm; + int rv = 0; + + t.length = strlen(str); + t.data = (unsigned char *)str; + t.flags = ASN1_STRING_FLAG_X509_TIME; + + t.type = V_ASN1_UTCTIME; + + if (!ASN1_TIME_check(&t)) { + t.type = V_ASN1_GENERALIZEDTIME; + if (!ASN1_TIME_check(&t)) + goto out; + } + + /* + * Per RFC 5280 (section 4.1.2.5.), the valid input time + * strings should be encoded with the following rules: + * + * 1. UTC: YYMMDDHHMMSSZ, if YY < 50 (20YY) --> UTC: YYMMDDHHMMSSZ + * 2. UTC: YYMMDDHHMMSSZ, if YY >= 50 (19YY) --> UTC: YYMMDDHHMMSSZ + * 3. G'd: YYYYMMDDHHMMSSZ, if YYYY >= 2050 --> G'd: YYYYMMDDHHMMSSZ + * 4. G'd: YYYYMMDDHHMMSSZ, if YYYY < 2050 --> UTC: YYMMDDHHMMSSZ + * + * Only strings of the 4th rule should be reformatted, but since a + * UTC can only present [1950, 2050), so if the given time string + * is less than 1950 (e.g. 19230419000000Z), we do nothing... + */ + + if (s != NULL && t.type == V_ASN1_GENERALIZEDTIME) { + if (!asn1_time_to_tm(&tm, &t)) + goto out; + if (is_utc(tm.tm_year)) { + t.length -= 2; + /* + * it's OK to let original t.data go since that's assigned + * to a piece of memory allocated outside of this function. + * new t.data would be freed after ASN1_STRING_copy is done. + */ + t.data = OPENSSL_zalloc(t.length + 1); + if (t.data == NULL) + goto out; + memcpy(t.data, str + 2, t.length); + t.type = V_ASN1_UTCTIME; + } + } + + if (s == NULL || ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t)) + rv = 1; + + if (t.data != (unsigned char *)str) + OPENSSL_free(t.data); +out: + return rv; +} + +int ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm) +{ + if (s == NULL) { + time_t now_t; + + time(&now_t); + memset(tm, 0, sizeof(*tm)); + if (OPENSSL_gmtime(&now_t, tm) != NULL) + return 1; + return 0; + } + + return asn1_time_to_tm(tm, s); +} + +int ASN1_TIME_diff(int *pday, int *psec, + const ASN1_TIME *from, const ASN1_TIME *to) +{ + struct tm tm_from, tm_to; + + if (!ASN1_TIME_to_tm(from, &tm_from)) + return 0; + if (!ASN1_TIME_to_tm(to, &tm_to)) + return 0; + return OPENSSL_gmtime_diff(pday, psec, &tm_from, &tm_to); +} + +static const char _asn1_mon[12][4] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; + +int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm) +{ + char *v; + int gmt = 0, l; + struct tm stm; + + if (!asn1_time_to_tm(&stm, tm)) { + /* asn1_time_to_tm will check the time type */ + goto err; + } + + l = tm->length; + v = (char *)tm->data; + if (v[l - 1] == 'Z') + gmt = 1; + + if (tm->type == V_ASN1_GENERALIZEDTIME) { + char *f = NULL; + int f_len = 0; + + /* + * Try to parse fractional seconds. '14' is the place of + * 'fraction point' in a GeneralizedTime string. + */ + if (tm->length > 15 && v[14] == '.') { + f = &v[14]; + f_len = 1; + while (14 + f_len < l && ossl_isdigit(f[f_len])) + ++f_len; + } + + return BIO_printf(bp, "%s %2d %02d:%02d:%02d%.*s %d%s", + _asn1_mon[stm.tm_mon], stm.tm_mday, stm.tm_hour, + stm.tm_min, stm.tm_sec, f_len, f, stm.tm_year + 1900, + (gmt ? " GMT" : "")) > 0; + } else { + return BIO_printf(bp, "%s %2d %02d:%02d:%02d %d%s", + _asn1_mon[stm.tm_mon], stm.tm_mday, stm.tm_hour, + stm.tm_min, stm.tm_sec, stm.tm_year + 1900, + (gmt ? " GMT" : "")) > 0; + } + err: + BIO_write(bp, "Bad time value", 14); + return 0; +} + +int ASN1_TIME_cmp_time_t(const ASN1_TIME *s, time_t t) +{ + struct tm stm, ttm; + int day, sec; + + if (!ASN1_TIME_to_tm(s, &stm)) + return -2; + + if (!OPENSSL_gmtime(&t, &ttm)) + return -2; + + if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm)) + return -2; + + if (day > 0 || sec > 0) + return 1; + if (day < 0 || sec < 0) + return -1; + return 0; +} + +int ASN1_TIME_normalize(ASN1_TIME *t) +{ + struct tm tm; + + if (!ASN1_TIME_to_tm(t, &tm)) + return 0; + + return asn1_time_from_tm(t, &tm, V_ASN1_UNDEF) != NULL; +} + +int ASN1_TIME_compare(const ASN1_TIME *a, const ASN1_TIME *b) +{ + int day, sec; + + if (!ASN1_TIME_diff(&day, &sec, b, a)) + return -2; + if (day > 0 || sec > 0) + return 1; + if (day < 0 || sec < 0) + return -1; + return 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_type.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_type.c new file mode 100644 index 000000000..0c7aebe30 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_type.c @@ -0,0 +1,134 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include "asn1_locl.h" + +int ASN1_TYPE_get(const ASN1_TYPE *a) +{ + if ((a->value.ptr != NULL) || (a->type == V_ASN1_NULL)) + return a->type; + else + return 0; +} + +void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value) +{ + if (a->value.ptr != NULL) { + ASN1_TYPE **tmp_a = &a; + asn1_primitive_free((ASN1_VALUE **)tmp_a, NULL, 0); + } + a->type = type; + if (type == V_ASN1_BOOLEAN) + a->value.boolean = value ? 0xff : 0; + else + a->value.ptr = value; +} + +int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value) +{ + if (!value || (type == V_ASN1_BOOLEAN)) { + void *p = (void *)value; + ASN1_TYPE_set(a, type, p); + } else if (type == V_ASN1_OBJECT) { + ASN1_OBJECT *odup; + odup = OBJ_dup(value); + if (!odup) + return 0; + ASN1_TYPE_set(a, type, odup); + } else { + ASN1_STRING *sdup; + sdup = ASN1_STRING_dup(value); + if (!sdup) + return 0; + ASN1_TYPE_set(a, type, sdup); + } + return 1; +} + +/* Returns 0 if they are equal, != 0 otherwise. */ +int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b) +{ + int result = -1; + + if (!a || !b || a->type != b->type) + return -1; + + switch (a->type) { + case V_ASN1_OBJECT: + result = OBJ_cmp(a->value.object, b->value.object); + break; + case V_ASN1_BOOLEAN: + result = a->value.boolean - b->value.boolean; + break; + case V_ASN1_NULL: + result = 0; /* They do not have content. */ + break; + case V_ASN1_INTEGER: + case V_ASN1_ENUMERATED: + case V_ASN1_BIT_STRING: + case V_ASN1_OCTET_STRING: + case V_ASN1_SEQUENCE: + case V_ASN1_SET: + case V_ASN1_NUMERICSTRING: + case V_ASN1_PRINTABLESTRING: + case V_ASN1_T61STRING: + case V_ASN1_VIDEOTEXSTRING: + case V_ASN1_IA5STRING: + case V_ASN1_UTCTIME: + case V_ASN1_GENERALIZEDTIME: + case V_ASN1_GRAPHICSTRING: + case V_ASN1_VISIBLESTRING: + case V_ASN1_GENERALSTRING: + case V_ASN1_UNIVERSALSTRING: + case V_ASN1_BMPSTRING: + case V_ASN1_UTF8STRING: + case V_ASN1_OTHER: + default: + result = ASN1_STRING_cmp((ASN1_STRING *)a->value.ptr, + (ASN1_STRING *)b->value.ptr); + break; + } + + return result; +} + +ASN1_TYPE *ASN1_TYPE_pack_sequence(const ASN1_ITEM *it, void *s, ASN1_TYPE **t) +{ + ASN1_OCTET_STRING *oct; + ASN1_TYPE *rt; + + oct = ASN1_item_pack(s, it, NULL); + if (oct == NULL) + return NULL; + + if (t && *t) { + rt = *t; + } else { + rt = ASN1_TYPE_new(); + if (rt == NULL) { + ASN1_OCTET_STRING_free(oct); + return NULL; + } + if (t) + *t = rt; + } + ASN1_TYPE_set(rt, V_ASN1_SEQUENCE, oct); + return rt; +} + +void *ASN1_TYPE_unpack_sequence(const ASN1_ITEM *it, const ASN1_TYPE *t) +{ + if (t == NULL || t->type != V_ASN1_SEQUENCE || t->value.sequence == NULL) + return NULL; + return ASN1_item_unpack(t->value.sequence, it); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_utctm.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_utctm.c new file mode 100644 index 000000000..b224991aa --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_utctm.c @@ -0,0 +1,98 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include +#include "asn1_locl.h" + +/* This is the primary function used to parse ASN1_UTCTIME */ +int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d) +{ + /* wrapper around ans1_time_to_tm */ + if (d->type != V_ASN1_UTCTIME) + return 0; + return asn1_time_to_tm(tm, d); +} + +int ASN1_UTCTIME_check(const ASN1_UTCTIME *d) +{ + return asn1_utctime_to_tm(NULL, d); +} + +/* Sets the string via simple copy without cleaning it up */ +int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str) +{ + ASN1_UTCTIME t; + + t.type = V_ASN1_UTCTIME; + t.length = strlen(str); + t.data = (unsigned char *)str; + t.flags = 0; + + if (!ASN1_UTCTIME_check(&t)) + return 0; + + if (s != NULL && !ASN1_STRING_copy(s, &t)) + return 0; + + return 1; +} + +ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t) +{ + return ASN1_UTCTIME_adj(s, t, 0, 0); +} + +ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, + int offset_day, long offset_sec) +{ + struct tm *ts; + struct tm data; + + ts = OPENSSL_gmtime(&t, &data); + if (ts == NULL) + return NULL; + + if (offset_day || offset_sec) { + if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec)) + return NULL; + } + + return asn1_time_from_tm(s, ts, V_ASN1_UTCTIME); +} + +int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t) +{ + struct tm stm, ttm; + int day, sec; + + if (!asn1_utctime_to_tm(&stm, s)) + return -2; + + if (OPENSSL_gmtime(&t, &ttm) == NULL) + return -2; + + if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm)) + return -2; + + if (day > 0 || sec > 0) + return 1; + if (day < 0 || sec < 0) + return -1; + return 0; +} + +int ASN1_UTCTIME_print(BIO *bp, const ASN1_UTCTIME *tm) +{ + if (tm->type != V_ASN1_UTCTIME) + return 0; + return ASN1_TIME_print(bp, tm); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_utf8.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_utf8.c new file mode 100644 index 000000000..e2dc09f6a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_utf8.c @@ -0,0 +1,188 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include + +/* UTF8 utilities */ + +/*- + * This parses a UTF8 string one character at a time. It is passed a pointer + * to the string and the length of the string. It sets 'value' to the value of + * the current character. It returns the number of characters read or a + * negative error code: + * -1 = string too short + * -2 = illegal character + * -3 = subsequent characters not of the form 10xxxxxx + * -4 = character encoded incorrectly (not minimal length). + */ + +int UTF8_getc(const unsigned char *str, int len, unsigned long *val) +{ + const unsigned char *p; + unsigned long value; + int ret; + if (len <= 0) + return 0; + p = str; + + /* Check syntax and work out the encoded value (if correct) */ + if ((*p & 0x80) == 0) { + value = *p++ & 0x7f; + ret = 1; + } else if ((*p & 0xe0) == 0xc0) { + if (len < 2) + return -1; + if ((p[1] & 0xc0) != 0x80) + return -3; + value = (*p++ & 0x1f) << 6; + value |= *p++ & 0x3f; + if (value < 0x80) + return -4; + ret = 2; + } else if ((*p & 0xf0) == 0xe0) { + if (len < 3) + return -1; + if (((p[1] & 0xc0) != 0x80) + || ((p[2] & 0xc0) != 0x80)) + return -3; + value = (*p++ & 0xf) << 12; + value |= (*p++ & 0x3f) << 6; + value |= *p++ & 0x3f; + if (value < 0x800) + return -4; + ret = 3; + } else if ((*p & 0xf8) == 0xf0) { + if (len < 4) + return -1; + if (((p[1] & 0xc0) != 0x80) + || ((p[2] & 0xc0) != 0x80) + || ((p[3] & 0xc0) != 0x80)) + return -3; + value = ((unsigned long)(*p++ & 0x7)) << 18; + value |= (*p++ & 0x3f) << 12; + value |= (*p++ & 0x3f) << 6; + value |= *p++ & 0x3f; + if (value < 0x10000) + return -4; + ret = 4; + } else if ((*p & 0xfc) == 0xf8) { + if (len < 5) + return -1; + if (((p[1] & 0xc0) != 0x80) + || ((p[2] & 0xc0) != 0x80) + || ((p[3] & 0xc0) != 0x80) + || ((p[4] & 0xc0) != 0x80)) + return -3; + value = ((unsigned long)(*p++ & 0x3)) << 24; + value |= ((unsigned long)(*p++ & 0x3f)) << 18; + value |= ((unsigned long)(*p++ & 0x3f)) << 12; + value |= (*p++ & 0x3f) << 6; + value |= *p++ & 0x3f; + if (value < 0x200000) + return -4; + ret = 5; + } else if ((*p & 0xfe) == 0xfc) { + if (len < 6) + return -1; + if (((p[1] & 0xc0) != 0x80) + || ((p[2] & 0xc0) != 0x80) + || ((p[3] & 0xc0) != 0x80) + || ((p[4] & 0xc0) != 0x80) + || ((p[5] & 0xc0) != 0x80)) + return -3; + value = ((unsigned long)(*p++ & 0x1)) << 30; + value |= ((unsigned long)(*p++ & 0x3f)) << 24; + value |= ((unsigned long)(*p++ & 0x3f)) << 18; + value |= ((unsigned long)(*p++ & 0x3f)) << 12; + value |= (*p++ & 0x3f) << 6; + value |= *p++ & 0x3f; + if (value < 0x4000000) + return -4; + ret = 6; + } else + return -2; + *val = value; + return ret; +} + +/* + * This takes a character 'value' and writes the UTF8 encoded value in 'str' + * where 'str' is a buffer containing 'len' characters. Returns the number of + * characters written or -1 if 'len' is too small. 'str' can be set to NULL + * in which case it just returns the number of characters. It will need at + * most 6 characters. + */ + +int UTF8_putc(unsigned char *str, int len, unsigned long value) +{ + if (!str) + len = 6; /* Maximum we will need */ + else if (len <= 0) + return -1; + if (value < 0x80) { + if (str) + *str = (unsigned char)value; + return 1; + } + if (value < 0x800) { + if (len < 2) + return -1; + if (str) { + *str++ = (unsigned char)(((value >> 6) & 0x1f) | 0xc0); + *str = (unsigned char)((value & 0x3f) | 0x80); + } + return 2; + } + if (value < 0x10000) { + if (len < 3) + return -1; + if (str) { + *str++ = (unsigned char)(((value >> 12) & 0xf) | 0xe0); + *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); + *str = (unsigned char)((value & 0x3f) | 0x80); + } + return 3; + } + if (value < 0x200000) { + if (len < 4) + return -1; + if (str) { + *str++ = (unsigned char)(((value >> 18) & 0x7) | 0xf0); + *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); + *str = (unsigned char)((value & 0x3f) | 0x80); + } + return 4; + } + if (value < 0x4000000) { + if (len < 5) + return -1; + if (str) { + *str++ = (unsigned char)(((value >> 24) & 0x3) | 0xf8); + *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); + *str = (unsigned char)((value & 0x3f) | 0x80); + } + return 5; + } + if (len < 6) + return -1; + if (str) { + *str++ = (unsigned char)(((value >> 30) & 0x1) | 0xfc); + *str++ = (unsigned char)(((value >> 24) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); + *str = (unsigned char)((value & 0x3f) | 0x80); + } + return 6; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_verify.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_verify.c new file mode 100644 index 000000000..cdaf17c3c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/a_verify.c @@ -0,0 +1,178 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include + +#include "internal/cryptlib.h" + +#include +#include +#include +#include +#include +#include "internal/asn1_int.h" +#include "internal/evp_int.h" + +#ifndef NO_ASN1_OLD + +int ASN1_verify(i2d_of_void *i2d, X509_ALGOR *a, ASN1_BIT_STRING *signature, + char *data, EVP_PKEY *pkey) +{ + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + const EVP_MD *type; + unsigned char *p, *buf_in = NULL; + int ret = -1, i, inl; + + if (ctx == NULL) { + ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_MALLOC_FAILURE); + goto err; + } + i = OBJ_obj2nid(a->algorithm); + type = EVP_get_digestbyname(OBJ_nid2sn(i)); + if (type == NULL) { + ASN1err(ASN1_F_ASN1_VERIFY, ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM); + goto err; + } + + if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) { + ASN1err(ASN1_F_ASN1_VERIFY, ASN1_R_INVALID_BIT_STRING_BITS_LEFT); + goto err; + } + + inl = i2d(data, NULL); + if (inl <= 0) { + ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_INTERNAL_ERROR); + goto err; + } + buf_in = OPENSSL_malloc((unsigned int)inl); + if (buf_in == NULL) { + ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_MALLOC_FAILURE); + goto err; + } + p = buf_in; + + i2d(data, &p); + ret = EVP_VerifyInit_ex(ctx, type, NULL) + && EVP_VerifyUpdate(ctx, (unsigned char *)buf_in, inl); + + OPENSSL_clear_free(buf_in, (unsigned int)inl); + + if (!ret) { + ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_EVP_LIB); + goto err; + } + ret = -1; + + if (EVP_VerifyFinal(ctx, (unsigned char *)signature->data, + (unsigned int)signature->length, pkey) <= 0) { + ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_EVP_LIB); + ret = 0; + goto err; + } + ret = 1; + err: + EVP_MD_CTX_free(ctx); + return ret; +} + +#endif + +int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, + ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey) +{ + EVP_MD_CTX *ctx = NULL; + unsigned char *buf_in = NULL; + int ret = -1, inl = 0; + int mdnid, pknid; + size_t inll = 0; + + if (!pkey) { + ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + + if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) { + ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ASN1_R_INVALID_BIT_STRING_BITS_LEFT); + return -1; + } + + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) { + ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* Convert signature OID into digest and public key OIDs */ + if (!OBJ_find_sigid_algs(OBJ_obj2nid(a->algorithm), &mdnid, &pknid)) { + ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM); + goto err; + } + if (mdnid == NID_undef) { + if (!pkey->ameth || !pkey->ameth->item_verify) { + ASN1err(ASN1_F_ASN1_ITEM_VERIFY, + ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM); + goto err; + } + ret = pkey->ameth->item_verify(ctx, it, asn, a, signature, pkey); + /* + * Return value of 2 means carry on, anything else means we exit + * straight away: either a fatal error of the underlying verification + * routine handles all verification. + */ + if (ret != 2) + goto err; + ret = -1; + } else { + const EVP_MD *type = EVP_get_digestbynid(mdnid); + + if (type == NULL) { + ASN1err(ASN1_F_ASN1_ITEM_VERIFY, + ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM); + goto err; + } + + /* Check public key OID matches public key type */ + if (EVP_PKEY_type(pknid) != pkey->ameth->pkey_id) { + ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ASN1_R_WRONG_PUBLIC_KEY_TYPE); + goto err; + } + + if (!EVP_DigestVerifyInit(ctx, NULL, type, NULL, pkey)) { + ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_EVP_LIB); + ret = 0; + goto err; + } + + } + + inl = ASN1_item_i2d(asn, &buf_in, it); + if (inl <= 0) { + ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_INTERNAL_ERROR); + goto err; + } + if (buf_in == NULL) { + ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_MALLOC_FAILURE); + goto err; + } + inll = inl; + + ret = EVP_DigestVerify(ctx, signature->data, (size_t)signature->length, + buf_in, inl); + if (ret <= 0) { + ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_EVP_LIB); + goto err; + } + ret = 1; + err: + OPENSSL_clear_free(buf_in, inll); + EVP_MD_CTX_free(ctx); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/ameth_lib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/ameth_lib.c new file mode 100644 index 000000000..d7d270dbb --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/ameth_lib.c @@ -0,0 +1,451 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "e_os.h" /* for strncasecmp */ +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "internal/asn1_int.h" +#include "internal/evp_int.h" + +#include "standard_methods.h" + +typedef int sk_cmp_fn_type(const char *const *a, const char *const *b); +static STACK_OF(EVP_PKEY_ASN1_METHOD) *app_methods = NULL; + +DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_ASN1_METHOD *, + const EVP_PKEY_ASN1_METHOD *, ameth); + +static int ameth_cmp(const EVP_PKEY_ASN1_METHOD *const *a, + const EVP_PKEY_ASN1_METHOD *const *b) +{ + return ((*a)->pkey_id - (*b)->pkey_id); +} + +IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_ASN1_METHOD *, + const EVP_PKEY_ASN1_METHOD *, ameth); + +int EVP_PKEY_asn1_get_count(void) +{ + int num = OSSL_NELEM(standard_methods); + if (app_methods) + num += sk_EVP_PKEY_ASN1_METHOD_num(app_methods); + return num; +} + +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx) +{ + int num = OSSL_NELEM(standard_methods); + if (idx < 0) + return NULL; + if (idx < num) + return standard_methods[idx]; + idx -= num; + return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx); +} + +static const EVP_PKEY_ASN1_METHOD *pkey_asn1_find(int type) +{ + EVP_PKEY_ASN1_METHOD tmp; + const EVP_PKEY_ASN1_METHOD *t = &tmp, **ret; + tmp.pkey_id = type; + if (app_methods) { + int idx; + idx = sk_EVP_PKEY_ASN1_METHOD_find(app_methods, &tmp); + if (idx >= 0) + return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx); + } + ret = OBJ_bsearch_ameth(&t, standard_methods, OSSL_NELEM(standard_methods)); + if (!ret || !*ret) + return NULL; + return *ret; +} + +/* + * Find an implementation of an ASN1 algorithm. If 'pe' is not NULL also + * search through engines and set *pe to a functional reference to the engine + * implementing 'type' or NULL if no engine implements it. + */ + +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pe, int type) +{ + const EVP_PKEY_ASN1_METHOD *t; + + for (;;) { + t = pkey_asn1_find(type); + if (!t || !(t->pkey_flags & ASN1_PKEY_ALIAS)) + break; + type = t->pkey_base_id; + } + if (pe) { +#ifndef OPENSSL_NO_ENGINE + ENGINE *e; + /* type will contain the final unaliased type */ + e = ENGINE_get_pkey_asn1_meth_engine(type); + if (e) { + *pe = e; + return ENGINE_get_pkey_asn1_meth(e, type); + } +#endif + *pe = NULL; + } + return t; +} + +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe, + const char *str, int len) +{ + int i; + const EVP_PKEY_ASN1_METHOD *ameth = NULL; + + if (len == -1) + len = strlen(str); + if (pe) { +#ifndef OPENSSL_NO_ENGINE + ENGINE *e; + ameth = ENGINE_pkey_asn1_find_str(&e, str, len); + if (ameth) { + /* + * Convert structural into functional reference + */ + if (!ENGINE_init(e)) + ameth = NULL; + ENGINE_free(e); + *pe = e; + return ameth; + } +#endif + *pe = NULL; + } + for (i = EVP_PKEY_asn1_get_count(); i-- > 0; ) { + ameth = EVP_PKEY_asn1_get0(i); + if (ameth->pkey_flags & ASN1_PKEY_ALIAS) + continue; + if ((int)strlen(ameth->pem_str) == len + && strncasecmp(ameth->pem_str, str, len) == 0) + return ameth; + } + return NULL; +} + +int EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth) +{ + EVP_PKEY_ASN1_METHOD tmp = { 0, }; + + /* + * One of the following must be true: + * + * pem_str == NULL AND ASN1_PKEY_ALIAS is set + * pem_str != NULL AND ASN1_PKEY_ALIAS is clear + * + * Anything else is an error and may lead to a corrupt ASN1 method table + */ + if (!((ameth->pem_str == NULL + && (ameth->pkey_flags & ASN1_PKEY_ALIAS) != 0) + || (ameth->pem_str != NULL + && (ameth->pkey_flags & ASN1_PKEY_ALIAS) == 0))) { + EVPerr(EVP_F_EVP_PKEY_ASN1_ADD0, ERR_R_PASSED_INVALID_ARGUMENT); + return 0; + } + + if (app_methods == NULL) { + app_methods = sk_EVP_PKEY_ASN1_METHOD_new(ameth_cmp); + if (app_methods == NULL) + return 0; + } + + tmp.pkey_id = ameth->pkey_id; + if (sk_EVP_PKEY_ASN1_METHOD_find(app_methods, &tmp) >= 0) { + EVPerr(EVP_F_EVP_PKEY_ASN1_ADD0, + EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED); + return 0; + } + + if (!sk_EVP_PKEY_ASN1_METHOD_push(app_methods, ameth)) + return 0; + sk_EVP_PKEY_ASN1_METHOD_sort(app_methods); + return 1; +} + +int EVP_PKEY_asn1_add_alias(int to, int from) +{ + EVP_PKEY_ASN1_METHOD *ameth; + ameth = EVP_PKEY_asn1_new(from, ASN1_PKEY_ALIAS, NULL, NULL); + if (ameth == NULL) + return 0; + ameth->pkey_base_id = to; + if (!EVP_PKEY_asn1_add0(ameth)) { + EVP_PKEY_asn1_free(ameth); + return 0; + } + return 1; +} + +int EVP_PKEY_asn1_get0_info(int *ppkey_id, int *ppkey_base_id, + int *ppkey_flags, const char **pinfo, + const char **ppem_str, + const EVP_PKEY_ASN1_METHOD *ameth) +{ + if (!ameth) + return 0; + if (ppkey_id) + *ppkey_id = ameth->pkey_id; + if (ppkey_base_id) + *ppkey_base_id = ameth->pkey_base_id; + if (ppkey_flags) + *ppkey_flags = ameth->pkey_flags; + if (pinfo) + *pinfo = ameth->info; + if (ppem_str) + *ppem_str = ameth->pem_str; + return 1; +} + +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_get0_asn1(const EVP_PKEY *pkey) +{ + return pkey->ameth; +} + +EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_new(int id, int flags, + const char *pem_str, const char *info) +{ + EVP_PKEY_ASN1_METHOD *ameth = OPENSSL_zalloc(sizeof(*ameth)); + + if (ameth == NULL) + return NULL; + + ameth->pkey_id = id; + ameth->pkey_base_id = id; + ameth->pkey_flags = flags | ASN1_PKEY_DYNAMIC; + + if (info) { + ameth->info = OPENSSL_strdup(info); + if (!ameth->info) + goto err; + } + + if (pem_str) { + ameth->pem_str = OPENSSL_strdup(pem_str); + if (!ameth->pem_str) + goto err; + } + + return ameth; + + err: + EVP_PKEY_asn1_free(ameth); + return NULL; + +} + +void EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst, + const EVP_PKEY_ASN1_METHOD *src) +{ + + dst->pub_decode = src->pub_decode; + dst->pub_encode = src->pub_encode; + dst->pub_cmp = src->pub_cmp; + dst->pub_print = src->pub_print; + + dst->priv_decode = src->priv_decode; + dst->priv_encode = src->priv_encode; + dst->priv_print = src->priv_print; + + dst->old_priv_encode = src->old_priv_encode; + dst->old_priv_decode = src->old_priv_decode; + + dst->pkey_size = src->pkey_size; + dst->pkey_bits = src->pkey_bits; + + dst->param_decode = src->param_decode; + dst->param_encode = src->param_encode; + dst->param_missing = src->param_missing; + dst->param_copy = src->param_copy; + dst->param_cmp = src->param_cmp; + dst->param_print = src->param_print; + + dst->pkey_free = src->pkey_free; + dst->pkey_ctrl = src->pkey_ctrl; + + dst->item_sign = src->item_sign; + dst->item_verify = src->item_verify; + + dst->siginf_set = src->siginf_set; + + dst->pkey_check = src->pkey_check; + +} + +void EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth) +{ + if (ameth && (ameth->pkey_flags & ASN1_PKEY_DYNAMIC)) { + OPENSSL_free(ameth->pem_str); + OPENSSL_free(ameth->info); + OPENSSL_free(ameth); + } +} + +void EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth, + int (*pub_decode) (EVP_PKEY *pk, + X509_PUBKEY *pub), + int (*pub_encode) (X509_PUBKEY *pub, + const EVP_PKEY *pk), + int (*pub_cmp) (const EVP_PKEY *a, + const EVP_PKEY *b), + int (*pub_print) (BIO *out, + const EVP_PKEY *pkey, + int indent, ASN1_PCTX *pctx), + int (*pkey_size) (const EVP_PKEY *pk), + int (*pkey_bits) (const EVP_PKEY *pk)) +{ + ameth->pub_decode = pub_decode; + ameth->pub_encode = pub_encode; + ameth->pub_cmp = pub_cmp; + ameth->pub_print = pub_print; + ameth->pkey_size = pkey_size; + ameth->pkey_bits = pkey_bits; +} + +void EVP_PKEY_asn1_set_private(EVP_PKEY_ASN1_METHOD *ameth, + int (*priv_decode) (EVP_PKEY *pk, + const PKCS8_PRIV_KEY_INFO + *p8inf), + int (*priv_encode) (PKCS8_PRIV_KEY_INFO *p8, + const EVP_PKEY *pk), + int (*priv_print) (BIO *out, + const EVP_PKEY *pkey, + int indent, + ASN1_PCTX *pctx)) +{ + ameth->priv_decode = priv_decode; + ameth->priv_encode = priv_encode; + ameth->priv_print = priv_print; +} + +void EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth, + int (*param_decode) (EVP_PKEY *pkey, + const unsigned char **pder, + int derlen), + int (*param_encode) (const EVP_PKEY *pkey, + unsigned char **pder), + int (*param_missing) (const EVP_PKEY *pk), + int (*param_copy) (EVP_PKEY *to, + const EVP_PKEY *from), + int (*param_cmp) (const EVP_PKEY *a, + const EVP_PKEY *b), + int (*param_print) (BIO *out, + const EVP_PKEY *pkey, + int indent, ASN1_PCTX *pctx)) +{ + ameth->param_decode = param_decode; + ameth->param_encode = param_encode; + ameth->param_missing = param_missing; + ameth->param_copy = param_copy; + ameth->param_cmp = param_cmp; + ameth->param_print = param_print; +} + +void EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth, + void (*pkey_free) (EVP_PKEY *pkey)) +{ + ameth->pkey_free = pkey_free; +} + +void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth, + int (*pkey_ctrl) (EVP_PKEY *pkey, int op, + long arg1, void *arg2)) +{ + ameth->pkey_ctrl = pkey_ctrl; +} + +void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth, + int (*pkey_security_bits) (const EVP_PKEY + *pk)) +{ + ameth->pkey_security_bits = pkey_security_bits; +} + +void EVP_PKEY_asn1_set_item(EVP_PKEY_ASN1_METHOD *ameth, + int (*item_verify) (EVP_MD_CTX *ctx, + const ASN1_ITEM *it, + void *asn, + X509_ALGOR *a, + ASN1_BIT_STRING *sig, + EVP_PKEY *pkey), + int (*item_sign) (EVP_MD_CTX *ctx, + const ASN1_ITEM *it, + void *asn, + X509_ALGOR *alg1, + X509_ALGOR *alg2, + ASN1_BIT_STRING *sig)) +{ + ameth->item_sign = item_sign; + ameth->item_verify = item_verify; +} + +void EVP_PKEY_asn1_set_siginf(EVP_PKEY_ASN1_METHOD *ameth, + int (*siginf_set) (X509_SIG_INFO *siginf, + const X509_ALGOR *alg, + const ASN1_STRING *sig)) +{ + ameth->siginf_set = siginf_set; +} + +void EVP_PKEY_asn1_set_check(EVP_PKEY_ASN1_METHOD *ameth, + int (*pkey_check) (const EVP_PKEY *pk)) +{ + ameth->pkey_check = pkey_check; +} + +void EVP_PKEY_asn1_set_public_check(EVP_PKEY_ASN1_METHOD *ameth, + int (*pkey_pub_check) (const EVP_PKEY *pk)) +{ + ameth->pkey_public_check = pkey_pub_check; +} + +void EVP_PKEY_asn1_set_param_check(EVP_PKEY_ASN1_METHOD *ameth, + int (*pkey_param_check) (const EVP_PKEY *pk)) +{ + ameth->pkey_param_check = pkey_param_check; +} + +void EVP_PKEY_asn1_set_set_priv_key(EVP_PKEY_ASN1_METHOD *ameth, + int (*set_priv_key) (EVP_PKEY *pk, + const unsigned char + *priv, + size_t len)) +{ + ameth->set_priv_key = set_priv_key; +} + +void EVP_PKEY_asn1_set_set_pub_key(EVP_PKEY_ASN1_METHOD *ameth, + int (*set_pub_key) (EVP_PKEY *pk, + const unsigned char *pub, + size_t len)) +{ + ameth->set_pub_key = set_pub_key; +} + +void EVP_PKEY_asn1_set_get_priv_key(EVP_PKEY_ASN1_METHOD *ameth, + int (*get_priv_key) (const EVP_PKEY *pk, + unsigned char *priv, + size_t *len)) +{ + ameth->get_priv_key = get_priv_key; +} + +void EVP_PKEY_asn1_set_get_pub_key(EVP_PKEY_ASN1_METHOD *ameth, + int (*get_pub_key) (const EVP_PKEY *pk, + unsigned char *pub, + size_t *len)) +{ + ameth->get_pub_key = get_pub_key; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn1_err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn1_err.c new file mode 100644 index 000000000..613f9ae71 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn1_err.c @@ -0,0 +1,350 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA ASN1_str_functs[] = { + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_A2D_ASN1_OBJECT, 0), "a2d_ASN1_OBJECT"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_A2I_ASN1_INTEGER, 0), "a2i_ASN1_INTEGER"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_A2I_ASN1_STRING, 0), "a2i_ASN1_STRING"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_APPEND_EXP, 0), "append_exp"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_BIO_INIT, 0), "asn1_bio_init"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_BIT_STRING_SET_BIT, 0), + "ASN1_BIT_STRING_set_bit"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_CB, 0), "asn1_cb"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_CHECK_TLEN, 0), "asn1_check_tlen"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_COLLECT, 0), "asn1_collect"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_D2I_EX_PRIMITIVE, 0), + "asn1_d2i_ex_primitive"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_D2I_FP, 0), "ASN1_d2i_fp"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_D2I_READ_BIO, 0), "asn1_d2i_read_bio"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_DIGEST, 0), "ASN1_digest"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_DO_ADB, 0), "asn1_do_adb"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_DO_LOCK, 0), "asn1_do_lock"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_DUP, 0), "ASN1_dup"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ENC_SAVE, 0), "asn1_enc_save"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_EX_C2I, 0), "asn1_ex_c2i"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_FIND_END, 0), "asn1_find_end"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GENERALIZEDTIME_ADJ, 0), + "ASN1_GENERALIZEDTIME_adj"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GENERATE_V3, 0), "ASN1_generate_v3"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GET_INT64, 0), "asn1_get_int64"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GET_OBJECT, 0), "ASN1_get_object"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GET_UINT64, 0), "asn1_get_uint64"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_I2D_BIO, 0), "ASN1_i2d_bio"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_I2D_FP, 0), "ASN1_i2d_fp"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_D2I_FP, 0), "ASN1_item_d2i_fp"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_DUP, 0), "ASN1_item_dup"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_EMBED_D2I, 0), + "asn1_item_embed_d2i"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_EMBED_NEW, 0), + "asn1_item_embed_new"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_FLAGS_I2D, 0), + "asn1_item_flags_i2d"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_I2D_BIO, 0), "ASN1_item_i2d_bio"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_I2D_FP, 0), "ASN1_item_i2d_fp"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_PACK, 0), "ASN1_item_pack"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_SIGN, 0), "ASN1_item_sign"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_SIGN_CTX, 0), + "ASN1_item_sign_ctx"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_UNPACK, 0), "ASN1_item_unpack"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_VERIFY, 0), "ASN1_item_verify"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_MBSTRING_NCOPY, 0), + "ASN1_mbstring_ncopy"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_OBJECT_NEW, 0), "ASN1_OBJECT_new"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_OUTPUT_DATA, 0), "asn1_output_data"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_PCTX_NEW, 0), "ASN1_PCTX_new"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_PRIMITIVE_NEW, 0), + "asn1_primitive_new"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_SCTX_NEW, 0), "ASN1_SCTX_new"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_SIGN, 0), "ASN1_sign"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STR2TYPE, 0), "asn1_str2type"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_GET_INT64, 0), + "asn1_string_get_int64"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_GET_UINT64, 0), + "asn1_string_get_uint64"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_SET, 0), "ASN1_STRING_set"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_TABLE_ADD, 0), + "ASN1_STRING_TABLE_add"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_TO_BN, 0), "asn1_string_to_bn"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_TYPE_NEW, 0), + "ASN1_STRING_type_new"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TEMPLATE_EX_D2I, 0), + "asn1_template_ex_d2i"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TEMPLATE_NEW, 0), "asn1_template_new"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, 0), + "asn1_template_noexp_d2i"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TIME_ADJ, 0), "ASN1_TIME_adj"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING, 0), + "ASN1_TYPE_get_int_octetstring"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TYPE_GET_OCTETSTRING, 0), + "ASN1_TYPE_get_octetstring"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_UTCTIME_ADJ, 0), "ASN1_UTCTIME_adj"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_VERIFY, 0), "ASN1_verify"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_B64_READ_ASN1, 0), "b64_read_asn1"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_B64_WRITE_ASN1, 0), "B64_write_ASN1"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_BIO_NEW_NDEF, 0), "BIO_new_NDEF"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_BITSTR_CB, 0), "bitstr_cb"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_BN_TO_ASN1_STRING, 0), "bn_to_asn1_string"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_ASN1_BIT_STRING, 0), + "c2i_ASN1_BIT_STRING"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_ASN1_INTEGER, 0), "c2i_ASN1_INTEGER"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_ASN1_OBJECT, 0), "c2i_ASN1_OBJECT"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_IBUF, 0), "c2i_ibuf"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_UINT64_INT, 0), "c2i_uint64_int"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_COLLECT_DATA, 0), "collect_data"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_ASN1_OBJECT, 0), "d2i_ASN1_OBJECT"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_ASN1_UINTEGER, 0), "d2i_ASN1_UINTEGER"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_AUTOPRIVATEKEY, 0), + "d2i_AutoPrivateKey"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_PRIVATEKEY, 0), "d2i_PrivateKey"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_PUBLICKEY, 0), "d2i_PublicKey"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_BUF, 0), "do_buf"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_CREATE, 0), "do_create"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_DUMP, 0), "do_dump"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_TCREATE, 0), "do_tcreate"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2A_ASN1_OBJECT, 0), "i2a_ASN1_OBJECT"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_ASN1_BIO_STREAM, 0), + "i2d_ASN1_bio_stream"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_ASN1_OBJECT, 0), "i2d_ASN1_OBJECT"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_DSA_PUBKEY, 0), "i2d_DSA_PUBKEY"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_EC_PUBKEY, 0), "i2d_EC_PUBKEY"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_PRIVATEKEY, 0), "i2d_PrivateKey"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_PUBLICKEY, 0), "i2d_PublicKey"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_RSA_PUBKEY, 0), "i2d_RSA_PUBKEY"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_LONG_C2I, 0), "long_c2i"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_NDEF_PREFIX, 0), "ndef_prefix"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_NDEF_SUFFIX, 0), "ndef_suffix"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_OID_MODULE_INIT, 0), "oid_module_init"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_PARSE_TAGGING, 0), "parse_tagging"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBE2_SET_IV, 0), "PKCS5_pbe2_set_iv"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBE2_SET_SCRYPT, 0), + "PKCS5_pbe2_set_scrypt"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBE_SET, 0), "PKCS5_pbe_set"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBE_SET0_ALGOR, 0), + "PKCS5_pbe_set0_algor"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBKDF2_SET, 0), "PKCS5_pbkdf2_set"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_SCRYPT_SET, 0), "pkcs5_scrypt_set"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_SMIME_READ_ASN1, 0), "SMIME_read_ASN1"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_SMIME_TEXT, 0), "SMIME_text"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_STABLE_GET, 0), "stable_get"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_STBL_MODULE_INIT, 0), "stbl_module_init"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_UINT32_C2I, 0), "uint32_c2i"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_UINT32_NEW, 0), "uint32_new"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_UINT64_C2I, 0), "uint64_c2i"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_UINT64_NEW, 0), "uint64_new"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_CRL_ADD0_REVOKED, 0), + "X509_CRL_add0_revoked"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_INFO_NEW, 0), "X509_INFO_new"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_NAME_ENCODE, 0), "x509_name_encode"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_NAME_EX_D2I, 0), "x509_name_ex_d2i"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_NAME_EX_NEW, 0), "x509_name_ex_new"}, + {ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_PKEY_NEW, 0), "X509_PKEY_new"}, + {0, NULL} +}; + +static const ERR_STRING_DATA ASN1_str_reasons[] = { + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ADDING_OBJECT), "adding object"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ASN1_PARSE_ERROR), "asn1 parse error"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ASN1_SIG_PARSE_ERROR), + "asn1 sig parse error"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_AUX_ERROR), "aux error"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BAD_OBJECT_HEADER), "bad object header"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BMPSTRING_IS_WRONG_LENGTH), + "bmpstring is wrong length"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BN_LIB), "bn lib"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BOOLEAN_IS_WRONG_LENGTH), + "boolean is wrong length"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BUFFER_TOO_SMALL), "buffer too small"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER), + "cipher has no object identifier"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_CONTEXT_NOT_INITIALISED), + "context not initialised"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_DATA_IS_WRONG), "data is wrong"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_DECODE_ERROR), "decode error"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_DEPTH_EXCEEDED), "depth exceeded"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED), + "digest and key type not supported"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ENCODE_ERROR), "encode error"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ERROR_GETTING_TIME), + "error getting time"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ERROR_LOADING_SECTION), + "error loading section"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ERROR_SETTING_CIPHER_PARAMS), + "error setting cipher params"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPECTING_AN_INTEGER), + "expecting an integer"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPECTING_AN_OBJECT), + "expecting an object"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPLICIT_LENGTH_MISMATCH), + "explicit length mismatch"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED), + "explicit tag not constructed"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_FIELD_MISSING), "field missing"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_FIRST_NUM_TOO_LARGE), + "first num too large"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_HEADER_TOO_LONG), "header too long"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_BITSTRING_FORMAT), + "illegal bitstring format"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_BOOLEAN), "illegal boolean"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_CHARACTERS), + "illegal characters"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_FORMAT), "illegal format"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_HEX), "illegal hex"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_IMPLICIT_TAG), + "illegal implicit tag"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_INTEGER), "illegal integer"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_NEGATIVE_VALUE), + "illegal negative value"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_NESTED_TAGGING), + "illegal nested tagging"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_NULL), "illegal null"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_NULL_VALUE), + "illegal null value"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_OBJECT), "illegal object"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_OPTIONAL_ANY), + "illegal optional any"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE), + "illegal options on item template"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_PADDING), "illegal padding"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_TAGGED_ANY), + "illegal tagged any"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_TIME_VALUE), + "illegal time value"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_ZERO_CONTENT), + "illegal zero content"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INTEGER_NOT_ASCII_FORMAT), + "integer not ascii format"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG), + "integer too large for long"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_BIT_STRING_BITS_LEFT), + "invalid bit string bits left"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_BMPSTRING_LENGTH), + "invalid bmpstring length"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_DIGIT), "invalid digit"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_MIME_TYPE), "invalid mime type"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_MODIFIER), "invalid modifier"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_NUMBER), "invalid number"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_OBJECT_ENCODING), + "invalid object encoding"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_SCRYPT_PARAMETERS), + "invalid scrypt parameters"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_SEPARATOR), "invalid separator"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_STRING_TABLE_VALUE), + "invalid string table value"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH), + "invalid universalstring length"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_UTF8STRING), + "invalid utf8string"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_VALUE), "invalid value"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_LIST_ERROR), "list error"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MIME_NO_CONTENT_TYPE), + "mime no content type"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MIME_PARSE_ERROR), "mime parse error"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MIME_SIG_PARSE_ERROR), + "mime sig parse error"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MISSING_EOC), "missing eoc"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MISSING_SECOND_NUMBER), + "missing second number"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MISSING_VALUE), "missing value"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MSTRING_NOT_UNIVERSAL), + "mstring not universal"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MSTRING_WRONG_TAG), "mstring wrong tag"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NESTED_ASN1_STRING), + "nested asn1 string"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NESTED_TOO_DEEP), "nested too deep"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NON_HEX_CHARACTERS), + "non hex characters"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NOT_ASCII_FORMAT), "not ascii format"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NOT_ENOUGH_DATA), "not enough data"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_CONTENT_TYPE), "no content type"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_MATCHING_CHOICE_TYPE), + "no matching choice type"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_MULTIPART_BODY_FAILURE), + "no multipart body failure"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_MULTIPART_BOUNDARY), + "no multipart boundary"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_SIG_CONTENT_TYPE), + "no sig content type"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NULL_IS_WRONG_LENGTH), + "null is wrong length"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_OBJECT_NOT_ASCII_FORMAT), + "object not ascii format"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ODD_NUMBER_OF_CHARS), + "odd number of chars"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SECOND_NUMBER_TOO_LARGE), + "second number too large"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SEQUENCE_LENGTH_MISMATCH), + "sequence length mismatch"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SEQUENCE_NOT_CONSTRUCTED), + "sequence not constructed"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG), + "sequence or set needs config"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SHORT_LINE), "short line"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SIG_INVALID_MIME_TYPE), + "sig invalid mime type"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_STREAMING_NOT_SUPPORTED), + "streaming not supported"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_STRING_TOO_LONG), "string too long"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_STRING_TOO_SHORT), "string too short"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD), + "the asn1 object identifier is not known for this md"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TIME_NOT_ASCII_FORMAT), + "time not ascii format"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TOO_LARGE), "too large"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TOO_LONG), "too long"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TOO_SMALL), "too small"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TYPE_NOT_CONSTRUCTED), + "type not constructed"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TYPE_NOT_PRIMITIVE), + "type not primitive"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNEXPECTED_EOC), "unexpected eoc"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH), + "universalstring is wrong length"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_FORMAT), "unknown format"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM), + "unknown message digest algorithm"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_OBJECT_TYPE), + "unknown object type"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE), + "unknown public key type"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM), + "unknown signature algorithm"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_TAG), "unknown tag"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE), + "unsupported any defined by type"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_CIPHER), + "unsupported cipher"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE), + "unsupported public key type"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_TYPE), "unsupported type"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_WRONG_INTEGER_TYPE), + "wrong integer type"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_WRONG_PUBLIC_KEY_TYPE), + "wrong public key type"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_WRONG_TAG), "wrong tag"}, + {0, NULL} +}; + +#endif + +int ERR_load_ASN1_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(ASN1_str_functs[0].error) == NULL) { + ERR_load_strings_const(ASN1_str_functs); + ERR_load_strings_const(ASN1_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn1_gen.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn1_gen.c new file mode 100644 index 000000000..493a693aa --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn1_gen.c @@ -0,0 +1,789 @@ +/* + * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include +#include + +#define ASN1_GEN_FLAG 0x10000 +#define ASN1_GEN_FLAG_IMP (ASN1_GEN_FLAG|1) +#define ASN1_GEN_FLAG_EXP (ASN1_GEN_FLAG|2) +#define ASN1_GEN_FLAG_TAG (ASN1_GEN_FLAG|3) +#define ASN1_GEN_FLAG_BITWRAP (ASN1_GEN_FLAG|4) +#define ASN1_GEN_FLAG_OCTWRAP (ASN1_GEN_FLAG|5) +#define ASN1_GEN_FLAG_SEQWRAP (ASN1_GEN_FLAG|6) +#define ASN1_GEN_FLAG_SETWRAP (ASN1_GEN_FLAG|7) +#define ASN1_GEN_FLAG_FORMAT (ASN1_GEN_FLAG|8) + +#define ASN1_GEN_STR(str,val) {str, sizeof(str) - 1, val} + +#define ASN1_FLAG_EXP_MAX 20 +/* Maximum number of nested sequences */ +#define ASN1_GEN_SEQ_MAX_DEPTH 50 + +/* Input formats */ + +/* ASCII: default */ +#define ASN1_GEN_FORMAT_ASCII 1 +/* UTF8 */ +#define ASN1_GEN_FORMAT_UTF8 2 +/* Hex */ +#define ASN1_GEN_FORMAT_HEX 3 +/* List of bits */ +#define ASN1_GEN_FORMAT_BITLIST 4 + +struct tag_name_st { + const char *strnam; + int len; + int tag; +}; + +typedef struct { + int exp_tag; + int exp_class; + int exp_constructed; + int exp_pad; + long exp_len; +} tag_exp_type; + +typedef struct { + int imp_tag; + int imp_class; + int utype; + int format; + const char *str; + tag_exp_type exp_list[ASN1_FLAG_EXP_MAX]; + int exp_count; +} tag_exp_arg; + +static ASN1_TYPE *generate_v3(const char *str, X509V3_CTX *cnf, int depth, + int *perr); +static int bitstr_cb(const char *elem, int len, void *bitstr); +static int asn1_cb(const char *elem, int len, void *bitstr); +static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class, + int exp_constructed, int exp_pad, int imp_ok); +static int parse_tagging(const char *vstart, int vlen, int *ptag, + int *pclass); +static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf, + int depth, int *perr); +static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype); +static int asn1_str2tag(const char *tagstr, int len); + +ASN1_TYPE *ASN1_generate_nconf(const char *str, CONF *nconf) +{ + X509V3_CTX cnf; + + if (!nconf) + return ASN1_generate_v3(str, NULL); + + X509V3_set_nconf(&cnf, nconf); + return ASN1_generate_v3(str, &cnf); +} + +ASN1_TYPE *ASN1_generate_v3(const char *str, X509V3_CTX *cnf) +{ + int err = 0; + ASN1_TYPE *ret = generate_v3(str, cnf, 0, &err); + if (err) + ASN1err(ASN1_F_ASN1_GENERATE_V3, err); + return ret; +} + +static ASN1_TYPE *generate_v3(const char *str, X509V3_CTX *cnf, int depth, + int *perr) +{ + ASN1_TYPE *ret; + tag_exp_arg asn1_tags; + tag_exp_type *etmp; + + int i, len; + + unsigned char *orig_der = NULL, *new_der = NULL; + const unsigned char *cpy_start; + unsigned char *p; + const unsigned char *cp; + int cpy_len; + long hdr_len = 0; + int hdr_constructed = 0, hdr_tag, hdr_class; + int r; + + asn1_tags.imp_tag = -1; + asn1_tags.imp_class = -1; + asn1_tags.format = ASN1_GEN_FORMAT_ASCII; + asn1_tags.exp_count = 0; + if (CONF_parse_list(str, ',', 1, asn1_cb, &asn1_tags) != 0) { + *perr = ASN1_R_UNKNOWN_TAG; + return NULL; + } + + if ((asn1_tags.utype == V_ASN1_SEQUENCE) + || (asn1_tags.utype == V_ASN1_SET)) { + if (!cnf) { + *perr = ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG; + return NULL; + } + if (depth >= ASN1_GEN_SEQ_MAX_DEPTH) { + *perr = ASN1_R_ILLEGAL_NESTED_TAGGING; + return NULL; + } + ret = asn1_multi(asn1_tags.utype, asn1_tags.str, cnf, depth, perr); + } else + ret = asn1_str2type(asn1_tags.str, asn1_tags.format, asn1_tags.utype); + + if (!ret) + return NULL; + + /* If no tagging return base type */ + if ((asn1_tags.imp_tag == -1) && (asn1_tags.exp_count == 0)) + return ret; + + /* Generate the encoding */ + cpy_len = i2d_ASN1_TYPE(ret, &orig_der); + ASN1_TYPE_free(ret); + ret = NULL; + /* Set point to start copying for modified encoding */ + cpy_start = orig_der; + + /* Do we need IMPLICIT tagging? */ + if (asn1_tags.imp_tag != -1) { + /* If IMPLICIT we will replace the underlying tag */ + /* Skip existing tag+len */ + r = ASN1_get_object(&cpy_start, &hdr_len, &hdr_tag, &hdr_class, + cpy_len); + if (r & 0x80) + goto err; + /* Update copy length */ + cpy_len -= cpy_start - orig_der; + /* + * For IMPLICIT tagging the length should match the original length + * and constructed flag should be consistent. + */ + if (r & 0x1) { + /* Indefinite length constructed */ + hdr_constructed = 2; + hdr_len = 0; + } else + /* Just retain constructed flag */ + hdr_constructed = r & V_ASN1_CONSTRUCTED; + /* + * Work out new length with IMPLICIT tag: ignore constructed because + * it will mess up if indefinite length + */ + len = ASN1_object_size(0, hdr_len, asn1_tags.imp_tag); + } else + len = cpy_len; + + /* Work out length in any EXPLICIT, starting from end */ + + for (i = 0, etmp = asn1_tags.exp_list + asn1_tags.exp_count - 1; + i < asn1_tags.exp_count; i++, etmp--) { + /* Content length: number of content octets + any padding */ + len += etmp->exp_pad; + etmp->exp_len = len; + /* Total object length: length including new header */ + len = ASN1_object_size(0, len, etmp->exp_tag); + } + + /* Allocate buffer for new encoding */ + + new_der = OPENSSL_malloc(len); + if (new_der == NULL) + goto err; + + /* Generate tagged encoding */ + + p = new_der; + + /* Output explicit tags first */ + + for (i = 0, etmp = asn1_tags.exp_list; i < asn1_tags.exp_count; + i++, etmp++) { + ASN1_put_object(&p, etmp->exp_constructed, etmp->exp_len, + etmp->exp_tag, etmp->exp_class); + if (etmp->exp_pad) + *p++ = 0; + } + + /* If IMPLICIT, output tag */ + + if (asn1_tags.imp_tag != -1) { + if (asn1_tags.imp_class == V_ASN1_UNIVERSAL + && (asn1_tags.imp_tag == V_ASN1_SEQUENCE + || asn1_tags.imp_tag == V_ASN1_SET)) + hdr_constructed = V_ASN1_CONSTRUCTED; + ASN1_put_object(&p, hdr_constructed, hdr_len, + asn1_tags.imp_tag, asn1_tags.imp_class); + } + + /* Copy across original encoding */ + memcpy(p, cpy_start, cpy_len); + + cp = new_der; + + /* Obtain new ASN1_TYPE structure */ + ret = d2i_ASN1_TYPE(NULL, &cp, len); + + err: + OPENSSL_free(orig_der); + OPENSSL_free(new_der); + + return ret; + +} + +static int asn1_cb(const char *elem, int len, void *bitstr) +{ + tag_exp_arg *arg = bitstr; + int i; + int utype; + int vlen = 0; + const char *p, *vstart = NULL; + + int tmp_tag, tmp_class; + + if (elem == NULL) + return -1; + + for (i = 0, p = elem; i < len; p++, i++) { + /* Look for the ':' in name value pairs */ + if (*p == ':') { + vstart = p + 1; + vlen = len - (vstart - elem); + len = p - elem; + break; + } + } + + utype = asn1_str2tag(elem, len); + + if (utype == -1) { + ASN1err(ASN1_F_ASN1_CB, ASN1_R_UNKNOWN_TAG); + ERR_add_error_data(2, "tag=", elem); + return -1; + } + + /* If this is not a modifier mark end of string and exit */ + if (!(utype & ASN1_GEN_FLAG)) { + arg->utype = utype; + arg->str = vstart; + /* If no value and not end of string, error */ + if (!vstart && elem[len]) { + ASN1err(ASN1_F_ASN1_CB, ASN1_R_MISSING_VALUE); + return -1; + } + return 0; + } + + switch (utype) { + + case ASN1_GEN_FLAG_IMP: + /* Check for illegal multiple IMPLICIT tagging */ + if (arg->imp_tag != -1) { + ASN1err(ASN1_F_ASN1_CB, ASN1_R_ILLEGAL_NESTED_TAGGING); + return -1; + } + if (!parse_tagging(vstart, vlen, &arg->imp_tag, &arg->imp_class)) + return -1; + break; + + case ASN1_GEN_FLAG_EXP: + + if (!parse_tagging(vstart, vlen, &tmp_tag, &tmp_class)) + return -1; + if (!append_exp(arg, tmp_tag, tmp_class, 1, 0, 0)) + return -1; + break; + + case ASN1_GEN_FLAG_SEQWRAP: + if (!append_exp(arg, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL, 1, 0, 1)) + return -1; + break; + + case ASN1_GEN_FLAG_SETWRAP: + if (!append_exp(arg, V_ASN1_SET, V_ASN1_UNIVERSAL, 1, 0, 1)) + return -1; + break; + + case ASN1_GEN_FLAG_BITWRAP: + if (!append_exp(arg, V_ASN1_BIT_STRING, V_ASN1_UNIVERSAL, 0, 1, 1)) + return -1; + break; + + case ASN1_GEN_FLAG_OCTWRAP: + if (!append_exp(arg, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL, 0, 0, 1)) + return -1; + break; + + case ASN1_GEN_FLAG_FORMAT: + if (!vstart) { + ASN1err(ASN1_F_ASN1_CB, ASN1_R_UNKNOWN_FORMAT); + return -1; + } + if (strncmp(vstart, "ASCII", 5) == 0) + arg->format = ASN1_GEN_FORMAT_ASCII; + else if (strncmp(vstart, "UTF8", 4) == 0) + arg->format = ASN1_GEN_FORMAT_UTF8; + else if (strncmp(vstart, "HEX", 3) == 0) + arg->format = ASN1_GEN_FORMAT_HEX; + else if (strncmp(vstart, "BITLIST", 7) == 0) + arg->format = ASN1_GEN_FORMAT_BITLIST; + else { + ASN1err(ASN1_F_ASN1_CB, ASN1_R_UNKNOWN_FORMAT); + return -1; + } + break; + + } + + return 1; + +} + +static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass) +{ + char erch[2]; + long tag_num; + char *eptr; + if (!vstart) + return 0; + tag_num = strtoul(vstart, &eptr, 10); + /* Check we haven't gone past max length: should be impossible */ + if (eptr && *eptr && (eptr > vstart + vlen)) + return 0; + if (tag_num < 0) { + ASN1err(ASN1_F_PARSE_TAGGING, ASN1_R_INVALID_NUMBER); + return 0; + } + *ptag = tag_num; + /* If we have non numeric characters, parse them */ + if (eptr) + vlen -= eptr - vstart; + else + vlen = 0; + if (vlen) { + switch (*eptr) { + + case 'U': + *pclass = V_ASN1_UNIVERSAL; + break; + + case 'A': + *pclass = V_ASN1_APPLICATION; + break; + + case 'P': + *pclass = V_ASN1_PRIVATE; + break; + + case 'C': + *pclass = V_ASN1_CONTEXT_SPECIFIC; + break; + + default: + erch[0] = *eptr; + erch[1] = 0; + ASN1err(ASN1_F_PARSE_TAGGING, ASN1_R_INVALID_MODIFIER); + ERR_add_error_data(2, "Char=", erch); + return 0; + + } + } else + *pclass = V_ASN1_CONTEXT_SPECIFIC; + + return 1; + +} + +/* Handle multiple types: SET and SEQUENCE */ + +static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf, + int depth, int *perr) +{ + ASN1_TYPE *ret = NULL; + STACK_OF(ASN1_TYPE) *sk = NULL; + STACK_OF(CONF_VALUE) *sect = NULL; + unsigned char *der = NULL; + int derlen; + int i; + sk = sk_ASN1_TYPE_new_null(); + if (!sk) + goto bad; + if (section) { + if (!cnf) + goto bad; + sect = X509V3_get_section(cnf, (char *)section); + if (!sect) + goto bad; + for (i = 0; i < sk_CONF_VALUE_num(sect); i++) { + ASN1_TYPE *typ = + generate_v3(sk_CONF_VALUE_value(sect, i)->value, cnf, + depth + 1, perr); + if (!typ) + goto bad; + if (!sk_ASN1_TYPE_push(sk, typ)) + goto bad; + } + } + + /* + * Now we has a STACK of the components, convert to the correct form + */ + + if (utype == V_ASN1_SET) + derlen = i2d_ASN1_SET_ANY(sk, &der); + else + derlen = i2d_ASN1_SEQUENCE_ANY(sk, &der); + + if (derlen < 0) + goto bad; + if ((ret = ASN1_TYPE_new()) == NULL) + goto bad; + if ((ret->value.asn1_string = ASN1_STRING_type_new(utype)) == NULL) + goto bad; + + ret->type = utype; + ret->value.asn1_string->data = der; + ret->value.asn1_string->length = derlen; + + der = NULL; + + bad: + + OPENSSL_free(der); + + sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free); + X509V3_section_free(cnf, sect); + + return ret; +} + +static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class, + int exp_constructed, int exp_pad, int imp_ok) +{ + tag_exp_type *exp_tmp; + /* Can only have IMPLICIT if permitted */ + if ((arg->imp_tag != -1) && !imp_ok) { + ASN1err(ASN1_F_APPEND_EXP, ASN1_R_ILLEGAL_IMPLICIT_TAG); + return 0; + } + + if (arg->exp_count == ASN1_FLAG_EXP_MAX) { + ASN1err(ASN1_F_APPEND_EXP, ASN1_R_DEPTH_EXCEEDED); + return 0; + } + + exp_tmp = &arg->exp_list[arg->exp_count++]; + + /* + * If IMPLICIT set tag to implicit value then reset implicit tag since it + * has been used. + */ + if (arg->imp_tag != -1) { + exp_tmp->exp_tag = arg->imp_tag; + exp_tmp->exp_class = arg->imp_class; + arg->imp_tag = -1; + arg->imp_class = -1; + } else { + exp_tmp->exp_tag = exp_tag; + exp_tmp->exp_class = exp_class; + } + exp_tmp->exp_constructed = exp_constructed; + exp_tmp->exp_pad = exp_pad; + + return 1; +} + +static int asn1_str2tag(const char *tagstr, int len) +{ + unsigned int i; + static const struct tag_name_st *tntmp, tnst[] = { + ASN1_GEN_STR("BOOL", V_ASN1_BOOLEAN), + ASN1_GEN_STR("BOOLEAN", V_ASN1_BOOLEAN), + ASN1_GEN_STR("NULL", V_ASN1_NULL), + ASN1_GEN_STR("INT", V_ASN1_INTEGER), + ASN1_GEN_STR("INTEGER", V_ASN1_INTEGER), + ASN1_GEN_STR("ENUM", V_ASN1_ENUMERATED), + ASN1_GEN_STR("ENUMERATED", V_ASN1_ENUMERATED), + ASN1_GEN_STR("OID", V_ASN1_OBJECT), + ASN1_GEN_STR("OBJECT", V_ASN1_OBJECT), + ASN1_GEN_STR("UTCTIME", V_ASN1_UTCTIME), + ASN1_GEN_STR("UTC", V_ASN1_UTCTIME), + ASN1_GEN_STR("GENERALIZEDTIME", V_ASN1_GENERALIZEDTIME), + ASN1_GEN_STR("GENTIME", V_ASN1_GENERALIZEDTIME), + ASN1_GEN_STR("OCT", V_ASN1_OCTET_STRING), + ASN1_GEN_STR("OCTETSTRING", V_ASN1_OCTET_STRING), + ASN1_GEN_STR("BITSTR", V_ASN1_BIT_STRING), + ASN1_GEN_STR("BITSTRING", V_ASN1_BIT_STRING), + ASN1_GEN_STR("UNIVERSALSTRING", V_ASN1_UNIVERSALSTRING), + ASN1_GEN_STR("UNIV", V_ASN1_UNIVERSALSTRING), + ASN1_GEN_STR("IA5", V_ASN1_IA5STRING), + ASN1_GEN_STR("IA5STRING", V_ASN1_IA5STRING), + ASN1_GEN_STR("UTF8", V_ASN1_UTF8STRING), + ASN1_GEN_STR("UTF8String", V_ASN1_UTF8STRING), + ASN1_GEN_STR("BMP", V_ASN1_BMPSTRING), + ASN1_GEN_STR("BMPSTRING", V_ASN1_BMPSTRING), + ASN1_GEN_STR("VISIBLESTRING", V_ASN1_VISIBLESTRING), + ASN1_GEN_STR("VISIBLE", V_ASN1_VISIBLESTRING), + ASN1_GEN_STR("PRINTABLESTRING", V_ASN1_PRINTABLESTRING), + ASN1_GEN_STR("PRINTABLE", V_ASN1_PRINTABLESTRING), + ASN1_GEN_STR("T61", V_ASN1_T61STRING), + ASN1_GEN_STR("T61STRING", V_ASN1_T61STRING), + ASN1_GEN_STR("TELETEXSTRING", V_ASN1_T61STRING), + ASN1_GEN_STR("GeneralString", V_ASN1_GENERALSTRING), + ASN1_GEN_STR("GENSTR", V_ASN1_GENERALSTRING), + ASN1_GEN_STR("NUMERIC", V_ASN1_NUMERICSTRING), + ASN1_GEN_STR("NUMERICSTRING", V_ASN1_NUMERICSTRING), + + /* Special cases */ + ASN1_GEN_STR("SEQUENCE", V_ASN1_SEQUENCE), + ASN1_GEN_STR("SEQ", V_ASN1_SEQUENCE), + ASN1_GEN_STR("SET", V_ASN1_SET), + /* type modifiers */ + /* Explicit tag */ + ASN1_GEN_STR("EXP", ASN1_GEN_FLAG_EXP), + ASN1_GEN_STR("EXPLICIT", ASN1_GEN_FLAG_EXP), + /* Implicit tag */ + ASN1_GEN_STR("IMP", ASN1_GEN_FLAG_IMP), + ASN1_GEN_STR("IMPLICIT", ASN1_GEN_FLAG_IMP), + /* OCTET STRING wrapper */ + ASN1_GEN_STR("OCTWRAP", ASN1_GEN_FLAG_OCTWRAP), + /* SEQUENCE wrapper */ + ASN1_GEN_STR("SEQWRAP", ASN1_GEN_FLAG_SEQWRAP), + /* SET wrapper */ + ASN1_GEN_STR("SETWRAP", ASN1_GEN_FLAG_SETWRAP), + /* BIT STRING wrapper */ + ASN1_GEN_STR("BITWRAP", ASN1_GEN_FLAG_BITWRAP), + ASN1_GEN_STR("FORM", ASN1_GEN_FLAG_FORMAT), + ASN1_GEN_STR("FORMAT", ASN1_GEN_FLAG_FORMAT), + }; + + if (len == -1) + len = strlen(tagstr); + + tntmp = tnst; + for (i = 0; i < OSSL_NELEM(tnst); i++, tntmp++) { + if ((len == tntmp->len) && (strncmp(tntmp->strnam, tagstr, len) == 0)) + return tntmp->tag; + } + + return -1; +} + +static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype) +{ + ASN1_TYPE *atmp = NULL; + CONF_VALUE vtmp; + unsigned char *rdata; + long rdlen; + int no_unused = 1; + + if ((atmp = ASN1_TYPE_new()) == NULL) { + ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (!str) + str = ""; + + switch (utype) { + + case V_ASN1_NULL: + if (str && *str) { + ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_NULL_VALUE); + goto bad_form; + } + break; + + case V_ASN1_BOOLEAN: + if (format != ASN1_GEN_FORMAT_ASCII) { + ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_NOT_ASCII_FORMAT); + goto bad_form; + } + vtmp.name = NULL; + vtmp.section = NULL; + vtmp.value = (char *)str; + if (!X509V3_get_value_bool(&vtmp, &atmp->value.boolean)) { + ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_BOOLEAN); + goto bad_str; + } + break; + + case V_ASN1_INTEGER: + case V_ASN1_ENUMERATED: + if (format != ASN1_GEN_FORMAT_ASCII) { + ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_INTEGER_NOT_ASCII_FORMAT); + goto bad_form; + } + if ((atmp->value.integer + = s2i_ASN1_INTEGER(NULL, str)) == NULL) { + ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_INTEGER); + goto bad_str; + } + break; + + case V_ASN1_OBJECT: + if (format != ASN1_GEN_FORMAT_ASCII) { + ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_OBJECT_NOT_ASCII_FORMAT); + goto bad_form; + } + if ((atmp->value.object = OBJ_txt2obj(str, 0)) == NULL) { + ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_OBJECT); + goto bad_str; + } + break; + + case V_ASN1_UTCTIME: + case V_ASN1_GENERALIZEDTIME: + if (format != ASN1_GEN_FORMAT_ASCII) { + ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_TIME_NOT_ASCII_FORMAT); + goto bad_form; + } + if ((atmp->value.asn1_string = ASN1_STRING_new()) == NULL) { + ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE); + goto bad_str; + } + if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1)) { + ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE); + goto bad_str; + } + atmp->value.asn1_string->type = utype; + if (!ASN1_TIME_check(atmp->value.asn1_string)) { + ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_TIME_VALUE); + goto bad_str; + } + + break; + + case V_ASN1_BMPSTRING: + case V_ASN1_PRINTABLESTRING: + case V_ASN1_IA5STRING: + case V_ASN1_T61STRING: + case V_ASN1_UTF8STRING: + case V_ASN1_VISIBLESTRING: + case V_ASN1_UNIVERSALSTRING: + case V_ASN1_GENERALSTRING: + case V_ASN1_NUMERICSTRING: + if (format == ASN1_GEN_FORMAT_ASCII) + format = MBSTRING_ASC; + else if (format == ASN1_GEN_FORMAT_UTF8) + format = MBSTRING_UTF8; + else { + ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_FORMAT); + goto bad_form; + } + + if (ASN1_mbstring_copy(&atmp->value.asn1_string, (unsigned char *)str, + -1, format, ASN1_tag2bit(utype)) <= 0) { + ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE); + goto bad_str; + } + + break; + + case V_ASN1_BIT_STRING: + case V_ASN1_OCTET_STRING: + if ((atmp->value.asn1_string = ASN1_STRING_new()) == NULL) { + ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE); + goto bad_form; + } + + if (format == ASN1_GEN_FORMAT_HEX) { + if ((rdata = OPENSSL_hexstr2buf(str, &rdlen)) == NULL) { + ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_HEX); + goto bad_str; + } + atmp->value.asn1_string->data = rdata; + atmp->value.asn1_string->length = rdlen; + atmp->value.asn1_string->type = utype; + } else if (format == ASN1_GEN_FORMAT_ASCII) + ASN1_STRING_set(atmp->value.asn1_string, str, -1); + else if ((format == ASN1_GEN_FORMAT_BITLIST) + && (utype == V_ASN1_BIT_STRING)) { + if (!CONF_parse_list + (str, ',', 1, bitstr_cb, atmp->value.bit_string)) { + ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_LIST_ERROR); + goto bad_str; + } + no_unused = 0; + + } else { + ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_BITSTRING_FORMAT); + goto bad_form; + } + + if ((utype == V_ASN1_BIT_STRING) && no_unused) { + atmp->value.asn1_string->flags + &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + atmp->value.asn1_string->flags |= ASN1_STRING_FLAG_BITS_LEFT; + } + + break; + + default: + ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_UNSUPPORTED_TYPE); + goto bad_str; + } + + atmp->type = utype; + return atmp; + + bad_str: + ERR_add_error_data(2, "string=", str); + bad_form: + + ASN1_TYPE_free(atmp); + return NULL; + +} + +static int bitstr_cb(const char *elem, int len, void *bitstr) +{ + long bitnum; + char *eptr; + if (!elem) + return 0; + bitnum = strtoul(elem, &eptr, 10); + if (eptr && *eptr && (eptr != elem + len)) + return 0; + if (bitnum < 0) { + ASN1err(ASN1_F_BITSTR_CB, ASN1_R_INVALID_NUMBER); + return 0; + } + if (!ASN1_BIT_STRING_set_bit(bitstr, bitnum, 1)) { + ASN1err(ASN1_F_BITSTR_CB, ERR_R_MALLOC_FAILURE); + return 0; + } + return 1; +} + +static int mask_cb(const char *elem, int len, void *arg) +{ + unsigned long *pmask = arg, tmpmask; + int tag; + if (elem == NULL) + return 0; + if ((len == 3) && (strncmp(elem, "DIR", 3) == 0)) { + *pmask |= B_ASN1_DIRECTORYSTRING; + return 1; + } + tag = asn1_str2tag(elem, len); + if (!tag || (tag & ASN1_GEN_FLAG)) + return 0; + tmpmask = ASN1_tag2bit(tag); + if (!tmpmask) + return 0; + *pmask |= tmpmask; + return 1; +} + +int ASN1_str2mask(const char *str, unsigned long *pmask) +{ + *pmask = 0; + return CONF_parse_list(str, '|', 1, mask_cb, pmask); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn1_item_list.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn1_item_list.c new file mode 100644 index 000000000..9798192f4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn1_item_list.c @@ -0,0 +1,42 @@ +/* + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "asn1_item_list.h" + +const ASN1_ITEM *ASN1_ITEM_lookup(const char *name) +{ + size_t i; + + for (i = 0; i < OSSL_NELEM(asn1_item_list); i++) { + const ASN1_ITEM *it = ASN1_ITEM_ptr(asn1_item_list[i]); + + if (strcmp(it->sname, name) == 0) + return it; + } + return NULL; +} + +const ASN1_ITEM *ASN1_ITEM_get(size_t i) +{ + if (i >= OSSL_NELEM(asn1_item_list)) + return NULL; + return ASN1_ITEM_ptr(asn1_item_list[i]); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn1_item_list.h b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn1_item_list.h new file mode 100644 index 000000000..db8107ed1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn1_item_list.h @@ -0,0 +1,178 @@ +/* + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +static ASN1_ITEM_EXP *asn1_item_list[] = { + + ASN1_ITEM_ref(ACCESS_DESCRIPTION), +#ifndef OPENSSL_NO_RFC3779 + ASN1_ITEM_ref(ASIdOrRange), + ASN1_ITEM_ref(ASIdentifierChoice), + ASN1_ITEM_ref(ASIdentifiers), +#endif + ASN1_ITEM_ref(ASN1_ANY), + ASN1_ITEM_ref(ASN1_BIT_STRING), + ASN1_ITEM_ref(ASN1_BMPSTRING), + ASN1_ITEM_ref(ASN1_BOOLEAN), + ASN1_ITEM_ref(ASN1_ENUMERATED), + ASN1_ITEM_ref(ASN1_FBOOLEAN), + ASN1_ITEM_ref(ASN1_GENERALIZEDTIME), + ASN1_ITEM_ref(ASN1_GENERALSTRING), + ASN1_ITEM_ref(ASN1_IA5STRING), + ASN1_ITEM_ref(ASN1_INTEGER), + ASN1_ITEM_ref(ASN1_NULL), + ASN1_ITEM_ref(ASN1_OBJECT), + ASN1_ITEM_ref(ASN1_OCTET_STRING_NDEF), + ASN1_ITEM_ref(ASN1_OCTET_STRING), + ASN1_ITEM_ref(ASN1_PRINTABLESTRING), + ASN1_ITEM_ref(ASN1_PRINTABLE), + ASN1_ITEM_ref(ASN1_SEQUENCE_ANY), + ASN1_ITEM_ref(ASN1_SEQUENCE), + ASN1_ITEM_ref(ASN1_SET_ANY), + ASN1_ITEM_ref(ASN1_T61STRING), + ASN1_ITEM_ref(ASN1_TBOOLEAN), + ASN1_ITEM_ref(ASN1_TIME), + ASN1_ITEM_ref(ASN1_UNIVERSALSTRING), + ASN1_ITEM_ref(ASN1_UTCTIME), + ASN1_ITEM_ref(ASN1_UTF8STRING), + ASN1_ITEM_ref(ASN1_VISIBLESTRING), +#ifndef OPENSSL_NO_RFC3779 + ASN1_ITEM_ref(ASRange), +#endif + ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS), + ASN1_ITEM_ref(AUTHORITY_KEYID), + ASN1_ITEM_ref(BASIC_CONSTRAINTS), + ASN1_ITEM_ref(BIGNUM), + ASN1_ITEM_ref(CBIGNUM), + ASN1_ITEM_ref(CERTIFICATEPOLICIES), +#ifndef OPENSSL_NO_CMS + ASN1_ITEM_ref(CMS_ContentInfo), + ASN1_ITEM_ref(CMS_ReceiptRequest), +#endif + ASN1_ITEM_ref(CRL_DIST_POINTS), +#ifndef OPENSSL_NO_DH + ASN1_ITEM_ref(DHparams), +#endif + ASN1_ITEM_ref(DIRECTORYSTRING), + ASN1_ITEM_ref(DISPLAYTEXT), + ASN1_ITEM_ref(DIST_POINT_NAME), + ASN1_ITEM_ref(DIST_POINT), +#ifndef OPENSSL_NO_EC + ASN1_ITEM_ref(ECPARAMETERS), + ASN1_ITEM_ref(ECPKPARAMETERS), +#endif + ASN1_ITEM_ref(EDIPARTYNAME), + ASN1_ITEM_ref(EXTENDED_KEY_USAGE), + ASN1_ITEM_ref(GENERAL_NAMES), + ASN1_ITEM_ref(GENERAL_NAME), + ASN1_ITEM_ref(GENERAL_SUBTREE), +#ifndef OPENSSL_NO_RFC3779 + ASN1_ITEM_ref(IPAddressChoice), + ASN1_ITEM_ref(IPAddressFamily), + ASN1_ITEM_ref(IPAddressOrRange), + ASN1_ITEM_ref(IPAddressRange), +#endif + ASN1_ITEM_ref(ISSUING_DIST_POINT), +#if OPENSSL_API_COMPAT < 0x10200000L + ASN1_ITEM_ref(LONG), +#endif + ASN1_ITEM_ref(NAME_CONSTRAINTS), + ASN1_ITEM_ref(NETSCAPE_CERT_SEQUENCE), + ASN1_ITEM_ref(NETSCAPE_SPKAC), + ASN1_ITEM_ref(NETSCAPE_SPKI), + ASN1_ITEM_ref(NOTICEREF), +#ifndef OPENSSL_NO_OCSP + ASN1_ITEM_ref(OCSP_BASICRESP), + ASN1_ITEM_ref(OCSP_CERTID), + ASN1_ITEM_ref(OCSP_CERTSTATUS), + ASN1_ITEM_ref(OCSP_CRLID), + ASN1_ITEM_ref(OCSP_ONEREQ), + ASN1_ITEM_ref(OCSP_REQINFO), + ASN1_ITEM_ref(OCSP_REQUEST), + ASN1_ITEM_ref(OCSP_RESPBYTES), + ASN1_ITEM_ref(OCSP_RESPDATA), + ASN1_ITEM_ref(OCSP_RESPID), + ASN1_ITEM_ref(OCSP_RESPONSE), + ASN1_ITEM_ref(OCSP_REVOKEDINFO), + ASN1_ITEM_ref(OCSP_SERVICELOC), + ASN1_ITEM_ref(OCSP_SIGNATURE), + ASN1_ITEM_ref(OCSP_SINGLERESP), +#endif + ASN1_ITEM_ref(OTHERNAME), + ASN1_ITEM_ref(PBE2PARAM), + ASN1_ITEM_ref(PBEPARAM), + ASN1_ITEM_ref(PBKDF2PARAM), + ASN1_ITEM_ref(PKCS12_AUTHSAFES), + ASN1_ITEM_ref(PKCS12_BAGS), + ASN1_ITEM_ref(PKCS12_MAC_DATA), + ASN1_ITEM_ref(PKCS12_SAFEBAGS), + ASN1_ITEM_ref(PKCS12_SAFEBAG), + ASN1_ITEM_ref(PKCS12), + ASN1_ITEM_ref(PKCS7_ATTR_SIGN), + ASN1_ITEM_ref(PKCS7_ATTR_VERIFY), + ASN1_ITEM_ref(PKCS7_DIGEST), + ASN1_ITEM_ref(PKCS7_ENCRYPT), + ASN1_ITEM_ref(PKCS7_ENC_CONTENT), + ASN1_ITEM_ref(PKCS7_ENVELOPE), + ASN1_ITEM_ref(PKCS7_ISSUER_AND_SERIAL), + ASN1_ITEM_ref(PKCS7_RECIP_INFO), + ASN1_ITEM_ref(PKCS7_SIGNED), + ASN1_ITEM_ref(PKCS7_SIGNER_INFO), + ASN1_ITEM_ref(PKCS7_SIGN_ENVELOPE), + ASN1_ITEM_ref(PKCS7), + ASN1_ITEM_ref(PKCS8_PRIV_KEY_INFO), + ASN1_ITEM_ref(PKEY_USAGE_PERIOD), + ASN1_ITEM_ref(POLICYINFO), + ASN1_ITEM_ref(POLICYQUALINFO), + ASN1_ITEM_ref(POLICY_CONSTRAINTS), + ASN1_ITEM_ref(POLICY_MAPPINGS), + ASN1_ITEM_ref(POLICY_MAPPING), + ASN1_ITEM_ref(PROXY_CERT_INFO_EXTENSION), + ASN1_ITEM_ref(PROXY_POLICY), +#ifndef OPENSSL_NO_RSA + ASN1_ITEM_ref(RSAPrivateKey), + ASN1_ITEM_ref(RSAPublicKey), + ASN1_ITEM_ref(RSA_OAEP_PARAMS), + ASN1_ITEM_ref(RSA_PSS_PARAMS), +#endif +#ifndef OPENSSL_NO_SCRYPT + ASN1_ITEM_ref(SCRYPT_PARAMS), +#endif + ASN1_ITEM_ref(SXNETID), + ASN1_ITEM_ref(SXNET), + ASN1_ITEM_ref(USERNOTICE), + ASN1_ITEM_ref(X509_ALGORS), + ASN1_ITEM_ref(X509_ALGOR), + ASN1_ITEM_ref(X509_ATTRIBUTE), + ASN1_ITEM_ref(X509_CERT_AUX), + ASN1_ITEM_ref(X509_CINF), + ASN1_ITEM_ref(X509_CRL_INFO), + ASN1_ITEM_ref(X509_CRL), + ASN1_ITEM_ref(X509_EXTENSIONS), + ASN1_ITEM_ref(X509_EXTENSION), + ASN1_ITEM_ref(X509_NAME_ENTRY), + ASN1_ITEM_ref(X509_NAME), + ASN1_ITEM_ref(X509_PUBKEY), + ASN1_ITEM_ref(X509_REQ_INFO), + ASN1_ITEM_ref(X509_REQ), + ASN1_ITEM_ref(X509_REVOKED), + ASN1_ITEM_ref(X509_SIG), + ASN1_ITEM_ref(X509_VAL), + ASN1_ITEM_ref(X509), +#if OPENSSL_API_COMPAT < 0x10200000L + ASN1_ITEM_ref(ZLONG), +#endif + ASN1_ITEM_ref(INT32), + ASN1_ITEM_ref(UINT32), + ASN1_ITEM_ref(ZINT32), + ASN1_ITEM_ref(ZUINT32), + ASN1_ITEM_ref(INT64), + ASN1_ITEM_ref(UINT64), + ASN1_ITEM_ref(ZINT64), + ASN1_ITEM_ref(ZUINT64), +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn1_lib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn1_lib.c new file mode 100644 index 000000000..88c4b5391 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn1_lib.c @@ -0,0 +1,391 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include +#include "asn1_locl.h" + +static int asn1_get_length(const unsigned char **pp, int *inf, long *rl, + long max); +static void asn1_put_length(unsigned char **pp, int length); + +static int _asn1_check_infinite_end(const unsigned char **p, long len) +{ + /* + * If there is 0 or 1 byte left, the length check should pick things up + */ + if (len <= 0) + return 1; + else if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0)) { + (*p) += 2; + return 1; + } + return 0; +} + +int ASN1_check_infinite_end(unsigned char **p, long len) +{ + return _asn1_check_infinite_end((const unsigned char **)p, len); +} + +int ASN1_const_check_infinite_end(const unsigned char **p, long len) +{ + return _asn1_check_infinite_end(p, len); +} + +int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag, + int *pclass, long omax) +{ + int i, ret; + long l; + const unsigned char *p = *pp; + int tag, xclass, inf; + long max = omax; + + if (!max) + goto err; + ret = (*p & V_ASN1_CONSTRUCTED); + xclass = (*p & V_ASN1_PRIVATE); + i = *p & V_ASN1_PRIMITIVE_TAG; + if (i == V_ASN1_PRIMITIVE_TAG) { /* high-tag */ + p++; + if (--max == 0) + goto err; + l = 0; + while (*p & 0x80) { + l <<= 7L; + l |= *(p++) & 0x7f; + if (--max == 0) + goto err; + if (l > (INT_MAX >> 7L)) + goto err; + } + l <<= 7L; + l |= *(p++) & 0x7f; + tag = (int)l; + if (--max == 0) + goto err; + } else { + tag = i; + p++; + if (--max == 0) + goto err; + } + *ptag = tag; + *pclass = xclass; + if (!asn1_get_length(&p, &inf, plength, max)) + goto err; + + if (inf && !(ret & V_ASN1_CONSTRUCTED)) + goto err; + + if (*plength > (omax - (p - *pp))) { + ASN1err(ASN1_F_ASN1_GET_OBJECT, ASN1_R_TOO_LONG); + /* + * Set this so that even if things are not long enough the values are + * set correctly + */ + ret |= 0x80; + } + *pp = p; + return ret | inf; + err: + ASN1err(ASN1_F_ASN1_GET_OBJECT, ASN1_R_HEADER_TOO_LONG); + return 0x80; +} + +/* + * Decode a length field. + * The short form is a single byte defining a length 0 - 127. + * The long form is a byte 0 - 127 with the top bit set and this indicates + * the number of following octets that contain the length. These octets + * are stored most significant digit first. + */ +static int asn1_get_length(const unsigned char **pp, int *inf, long *rl, + long max) +{ + const unsigned char *p = *pp; + unsigned long ret = 0; + int i; + + if (max-- < 1) + return 0; + if (*p == 0x80) { + *inf = 1; + p++; + } else { + *inf = 0; + i = *p & 0x7f; + if (*p++ & 0x80) { + if (max < i + 1) + return 0; + /* Skip leading zeroes */ + while (i > 0 && *p == 0) { + p++; + i--; + } + if (i > (int)sizeof(long)) + return 0; + while (i > 0) { + ret <<= 8; + ret |= *p++; + i--; + } + if (ret > LONG_MAX) + return 0; + } else + ret = i; + } + *pp = p; + *rl = (long)ret; + return 1; +} + +/* + * class 0 is constructed constructed == 2 for indefinite length constructed + */ +void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag, + int xclass) +{ + unsigned char *p = *pp; + int i, ttag; + + i = (constructed) ? V_ASN1_CONSTRUCTED : 0; + i |= (xclass & V_ASN1_PRIVATE); + if (tag < 31) + *(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG); + else { + *(p++) = i | V_ASN1_PRIMITIVE_TAG; + for (i = 0, ttag = tag; ttag > 0; i++) + ttag >>= 7; + ttag = i; + while (i-- > 0) { + p[i] = tag & 0x7f; + if (i != (ttag - 1)) + p[i] |= 0x80; + tag >>= 7; + } + p += ttag; + } + if (constructed == 2) + *(p++) = 0x80; + else + asn1_put_length(&p, length); + *pp = p; +} + +int ASN1_put_eoc(unsigned char **pp) +{ + unsigned char *p = *pp; + *p++ = 0; + *p++ = 0; + *pp = p; + return 2; +} + +static void asn1_put_length(unsigned char **pp, int length) +{ + unsigned char *p = *pp; + int i, l; + if (length <= 127) + *(p++) = (unsigned char)length; + else { + l = length; + for (i = 0; l > 0; i++) + l >>= 8; + *(p++) = i | 0x80; + l = i; + while (i-- > 0) { + p[i] = length & 0xff; + length >>= 8; + } + p += l; + } + *pp = p; +} + +int ASN1_object_size(int constructed, int length, int tag) +{ + int ret = 1; + if (length < 0) + return -1; + if (tag >= 31) { + while (tag > 0) { + tag >>= 7; + ret++; + } + } + if (constructed == 2) { + ret += 3; + } else { + ret++; + if (length > 127) { + int tmplen = length; + while (tmplen > 0) { + tmplen >>= 8; + ret++; + } + } + } + if (ret >= INT_MAX - length) + return -1; + return ret + length; +} + +int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str) +{ + if (str == NULL) + return 0; + dst->type = str->type; + if (!ASN1_STRING_set(dst, str->data, str->length)) + return 0; + /* Copy flags but preserve embed value */ + dst->flags &= ASN1_STRING_FLAG_EMBED; + dst->flags |= str->flags & ~ASN1_STRING_FLAG_EMBED; + return 1; +} + +ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str) +{ + ASN1_STRING *ret; + if (!str) + return NULL; + ret = ASN1_STRING_new(); + if (ret == NULL) + return NULL; + if (!ASN1_STRING_copy(ret, str)) { + ASN1_STRING_free(ret); + return NULL; + } + return ret; +} + +int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len) +{ + unsigned char *c; + const char *data = _data; + + if (len < 0) { + if (data == NULL) + return 0; + else + len = strlen(data); + } + if ((str->length <= len) || (str->data == NULL)) { + c = str->data; + str->data = OPENSSL_realloc(c, len + 1); + if (str->data == NULL) { + ASN1err(ASN1_F_ASN1_STRING_SET, ERR_R_MALLOC_FAILURE); + str->data = c; + return 0; + } + } + str->length = len; + if (data != NULL) { + memcpy(str->data, data, len); + /* an allowance for strings :-) */ + str->data[len] = '\0'; + } + return 1; +} + +void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len) +{ + OPENSSL_free(str->data); + str->data = data; + str->length = len; +} + +ASN1_STRING *ASN1_STRING_new(void) +{ + return ASN1_STRING_type_new(V_ASN1_OCTET_STRING); +} + +ASN1_STRING *ASN1_STRING_type_new(int type) +{ + ASN1_STRING *ret; + + ret = OPENSSL_zalloc(sizeof(*ret)); + if (ret == NULL) { + ASN1err(ASN1_F_ASN1_STRING_TYPE_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + ret->type = type; + return ret; +} + +void asn1_string_embed_free(ASN1_STRING *a, int embed) +{ + if (a == NULL) + return; + if (!(a->flags & ASN1_STRING_FLAG_NDEF)) + OPENSSL_free(a->data); + if (embed == 0) + OPENSSL_free(a); +} + +void ASN1_STRING_free(ASN1_STRING *a) +{ + if (a == NULL) + return; + asn1_string_embed_free(a, a->flags & ASN1_STRING_FLAG_EMBED); +} + +void ASN1_STRING_clear_free(ASN1_STRING *a) +{ + if (a == NULL) + return; + if (a->data && !(a->flags & ASN1_STRING_FLAG_NDEF)) + OPENSSL_cleanse(a->data, a->length); + ASN1_STRING_free(a); +} + +int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b) +{ + int i; + + i = (a->length - b->length); + if (i == 0) { + i = memcmp(a->data, b->data, a->length); + if (i == 0) + return a->type - b->type; + else + return i; + } else + return i; +} + +int ASN1_STRING_length(const ASN1_STRING *x) +{ + return x->length; +} + +void ASN1_STRING_length_set(ASN1_STRING *x, int len) +{ + x->length = len; +} + +int ASN1_STRING_type(const ASN1_STRING *x) +{ + return x->type; +} + +const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x) +{ + return x->data; +} + +# if OPENSSL_API_COMPAT < 0x10100000L +unsigned char *ASN1_STRING_data(ASN1_STRING *x) +{ + return x->data; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn1_locl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn1_locl.h new file mode 100644 index 000000000..cec141721 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn1_locl.h @@ -0,0 +1,83 @@ +/* + * Copyright 2005-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Internal ASN1 structures and functions: not for application use */ + +int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d); +int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d); +int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d); + +/* ASN1 scan context structure */ + +struct asn1_sctx_st { + /* The ASN1_ITEM associated with this field */ + const ASN1_ITEM *it; + /* If ASN1_TEMPLATE associated with this field */ + const ASN1_TEMPLATE *tt; + /* Various flags associated with field and context */ + unsigned long flags; + /* If SEQUENCE OF or SET OF, field index */ + int skidx; + /* ASN1 depth of field */ + int depth; + /* Structure and field name */ + const char *sname, *fname; + /* If a primitive type the type of underlying field */ + int prim_type; + /* The field value itself */ + ASN1_VALUE **field; + /* Callback to pass information to */ + int (*scan_cb) (ASN1_SCTX *ctx); + /* Context specific application data */ + void *app_data; +} /* ASN1_SCTX */ ; + +typedef struct mime_param_st MIME_PARAM; +DEFINE_STACK_OF(MIME_PARAM) +typedef struct mime_header_st MIME_HEADER; +DEFINE_STACK_OF(MIME_HEADER) + +void asn1_string_embed_free(ASN1_STRING *a, int embed); + +int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it); +int asn1_set_choice_selector(ASN1_VALUE **pval, int value, + const ASN1_ITEM *it); + +ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); + +const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, + int nullerr); + +int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it); + +void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it); +void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it); +int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval, + const ASN1_ITEM *it); +int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen, + const ASN1_ITEM *it); + +void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed); +void asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed); +void asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); + +ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, + long length); +int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp); +ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, + const unsigned char **pp, long length); +int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp); +ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp, + long length); + +/* Internal functions used by x_int64.c */ +int c2i_uint64_int(uint64_t *ret, int *neg, const unsigned char **pp, long len); +int i2c_uint64_int(unsigned char *p, uint64_t r, int neg); + +ASN1_TIME *asn1_time_from_tm(ASN1_TIME *s, struct tm *ts, int type); diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn1_par.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn1_par.c new file mode 100644 index 000000000..4b60c615d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn1_par.c @@ -0,0 +1,375 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include + +#ifndef ASN1_PARSE_MAXDEPTH +#define ASN1_PARSE_MAXDEPTH 128 +#endif + +static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed, + int indent); +static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, + int offset, int depth, int indent, int dump); +static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed, + int indent) +{ + static const char fmt[] = "%-18s"; + char str[128]; + const char *p; + + if (constructed & V_ASN1_CONSTRUCTED) + p = "cons: "; + else + p = "prim: "; + if (BIO_write(bp, p, 6) < 6) + goto err; + BIO_indent(bp, indent, 128); + + p = str; + if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE) + BIO_snprintf(str, sizeof(str), "priv [ %d ] ", tag); + else if ((xclass & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC) + BIO_snprintf(str, sizeof(str), "cont [ %d ]", tag); + else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION) + BIO_snprintf(str, sizeof(str), "appl [ %d ]", tag); + else if (tag > 30) + BIO_snprintf(str, sizeof(str), "", tag); + else + p = ASN1_tag2str(tag); + + if (BIO_printf(bp, fmt, p) <= 0) + goto err; + return 1; + err: + return 0; +} + +int ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent) +{ + return asn1_parse2(bp, &pp, len, 0, 0, indent, 0); +} + +int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent, + int dump) +{ + return asn1_parse2(bp, &pp, len, 0, 0, indent, dump); +} + +static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, + int offset, int depth, int indent, int dump) +{ + const unsigned char *p, *ep, *tot, *op, *opp; + long len; + int tag, xclass, ret = 0; + int nl, hl, j, r; + ASN1_OBJECT *o = NULL; + ASN1_OCTET_STRING *os = NULL; + /* ASN1_BMPSTRING *bmp=NULL; */ + int dump_indent, dump_cont = 0; + + if (depth > ASN1_PARSE_MAXDEPTH) { + BIO_puts(bp, "BAD RECURSION DEPTH\n"); + return 0; + } + + dump_indent = 6; /* Because we know BIO_dump_indent() */ + p = *pp; + tot = p + length; + while (length > 0) { + op = p; + j = ASN1_get_object(&p, &len, &tag, &xclass, length); + if (j & 0x80) { + if (BIO_write(bp, "Error in encoding\n", 18) <= 0) + goto end; + ret = 0; + goto end; + } + hl = (p - op); + length -= hl; + /* + * if j == 0x21 it is a constructed indefinite length object + */ + if (BIO_printf(bp, "%5ld:", (long)offset + (long)(op - *pp)) + <= 0) + goto end; + + if (j != (V_ASN1_CONSTRUCTED | 1)) { + if (BIO_printf(bp, "d=%-2d hl=%ld l=%4ld ", + depth, (long)hl, len) <= 0) + goto end; + } else { + if (BIO_printf(bp, "d=%-2d hl=%ld l=inf ", depth, (long)hl) <= 0) + goto end; + } + if (!asn1_print_info(bp, tag, xclass, j, (indent) ? depth : 0)) + goto end; + if (j & V_ASN1_CONSTRUCTED) { + const unsigned char *sp = p; + + ep = p + len; + if (BIO_write(bp, "\n", 1) <= 0) + goto end; + if (len > length) { + BIO_printf(bp, "length is greater than %ld\n", length); + ret = 0; + goto end; + } + if ((j == 0x21) && (len == 0)) { + for (;;) { + r = asn1_parse2(bp, &p, (long)(tot - p), + offset + (p - *pp), depth + 1, + indent, dump); + if (r == 0) { + ret = 0; + goto end; + } + if ((r == 2) || (p >= tot)) { + len = p - sp; + break; + } + } + } else { + long tmp = len; + + while (p < ep) { + sp = p; + r = asn1_parse2(bp, &p, tmp, + offset + (p - *pp), depth + 1, + indent, dump); + if (r == 0) { + ret = 0; + goto end; + } + tmp -= p - sp; + } + } + } else if (xclass != 0) { + p += len; + if (BIO_write(bp, "\n", 1) <= 0) + goto end; + } else { + nl = 0; + if ((tag == V_ASN1_PRINTABLESTRING) || + (tag == V_ASN1_T61STRING) || + (tag == V_ASN1_IA5STRING) || + (tag == V_ASN1_VISIBLESTRING) || + (tag == V_ASN1_NUMERICSTRING) || + (tag == V_ASN1_UTF8STRING) || + (tag == V_ASN1_UTCTIME) || (tag == V_ASN1_GENERALIZEDTIME)) { + if (BIO_write(bp, ":", 1) <= 0) + goto end; + if ((len > 0) && BIO_write(bp, (const char *)p, (int)len) + != (int)len) + goto end; + } else if (tag == V_ASN1_OBJECT) { + opp = op; + if (d2i_ASN1_OBJECT(&o, &opp, len + hl) != NULL) { + if (BIO_write(bp, ":", 1) <= 0) + goto end; + i2a_ASN1_OBJECT(bp, o); + } else { + if (BIO_puts(bp, ":BAD OBJECT") <= 0) + goto end; + dump_cont = 1; + } + } else if (tag == V_ASN1_BOOLEAN) { + if (len != 1) { + if (BIO_puts(bp, ":BAD BOOLEAN") <= 0) + goto end; + dump_cont = 1; + } + if (len > 0) + BIO_printf(bp, ":%u", p[0]); + } else if (tag == V_ASN1_BMPSTRING) { + /* do the BMP thang */ + } else if (tag == V_ASN1_OCTET_STRING) { + int i, printable = 1; + + opp = op; + os = d2i_ASN1_OCTET_STRING(NULL, &opp, len + hl); + if (os != NULL && os->length > 0) { + opp = os->data; + /* + * testing whether the octet string is printable + */ + for (i = 0; i < os->length; i++) { + if (((opp[i] < ' ') && + (opp[i] != '\n') && + (opp[i] != '\r') && + (opp[i] != '\t')) || (opp[i] > '~')) { + printable = 0; + break; + } + } + if (printable) + /* printable string */ + { + if (BIO_write(bp, ":", 1) <= 0) + goto end; + if (BIO_write(bp, (const char *)opp, os->length) <= 0) + goto end; + } else if (!dump) + /* + * not printable => print octet string as hex dump + */ + { + if (BIO_write(bp, "[HEX DUMP]:", 11) <= 0) + goto end; + for (i = 0; i < os->length; i++) { + if (BIO_printf(bp, "%02X", opp[i]) <= 0) + goto end; + } + } else + /* print the normal dump */ + { + if (!nl) { + if (BIO_write(bp, "\n", 1) <= 0) + goto end; + } + if (BIO_dump_indent(bp, + (const char *)opp, + ((dump == -1 || dump > + os-> + length) ? os->length : dump), + dump_indent) <= 0) + goto end; + nl = 1; + } + } + ASN1_OCTET_STRING_free(os); + os = NULL; + } else if (tag == V_ASN1_INTEGER) { + ASN1_INTEGER *bs; + int i; + + opp = op; + bs = d2i_ASN1_INTEGER(NULL, &opp, len + hl); + if (bs != NULL) { + if (BIO_write(bp, ":", 1) <= 0) + goto end; + if (bs->type == V_ASN1_NEG_INTEGER) + if (BIO_write(bp, "-", 1) <= 0) + goto end; + for (i = 0; i < bs->length; i++) { + if (BIO_printf(bp, "%02X", bs->data[i]) <= 0) + goto end; + } + if (bs->length == 0) { + if (BIO_write(bp, "00", 2) <= 0) + goto end; + } + } else { + if (BIO_puts(bp, ":BAD INTEGER") <= 0) + goto end; + dump_cont = 1; + } + ASN1_INTEGER_free(bs); + } else if (tag == V_ASN1_ENUMERATED) { + ASN1_ENUMERATED *bs; + int i; + + opp = op; + bs = d2i_ASN1_ENUMERATED(NULL, &opp, len + hl); + if (bs != NULL) { + if (BIO_write(bp, ":", 1) <= 0) + goto end; + if (bs->type == V_ASN1_NEG_ENUMERATED) + if (BIO_write(bp, "-", 1) <= 0) + goto end; + for (i = 0; i < bs->length; i++) { + if (BIO_printf(bp, "%02X", bs->data[i]) <= 0) + goto end; + } + if (bs->length == 0) { + if (BIO_write(bp, "00", 2) <= 0) + goto end; + } + } else { + if (BIO_puts(bp, ":BAD ENUMERATED") <= 0) + goto end; + dump_cont = 1; + } + ASN1_ENUMERATED_free(bs); + } else if (len > 0 && dump) { + if (!nl) { + if (BIO_write(bp, "\n", 1) <= 0) + goto end; + } + if (BIO_dump_indent(bp, (const char *)p, + ((dump == -1 || dump > len) ? len : dump), + dump_indent) <= 0) + goto end; + nl = 1; + } + if (dump_cont) { + int i; + const unsigned char *tmp = op + hl; + if (BIO_puts(bp, ":[") <= 0) + goto end; + for (i = 0; i < len; i++) { + if (BIO_printf(bp, "%02X", tmp[i]) <= 0) + goto end; + } + if (BIO_puts(bp, "]") <= 0) + goto end; + } + + if (!nl) { + if (BIO_write(bp, "\n", 1) <= 0) + goto end; + } + p += len; + if ((tag == V_ASN1_EOC) && (xclass == 0)) { + ret = 2; /* End of sequence */ + goto end; + } + } + length -= len; + } + ret = 1; + end: + ASN1_OBJECT_free(o); + ASN1_OCTET_STRING_free(os); + *pp = p; + return ret; +} + +const char *ASN1_tag2str(int tag) +{ + static const char *const tag2str[] = { + /* 0-4 */ + "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", + /* 5-9 */ + "NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", + /* 10-13 */ + "ENUMERATED", "", "UTF8STRING", "", + /* 15-17 */ + "", "", "SEQUENCE", "SET", + /* 18-20 */ + "NUMERICSTRING", "PRINTABLESTRING", "T61STRING", + /* 21-24 */ + "VIDEOTEXSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME", + /* 25-27 */ + "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", + /* 28-30 */ + "UNIVERSALSTRING", "", "BMPSTRING" + }; + + if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED)) + tag &= ~0x100; + + if (tag < 0 || tag > 30) + return "(unknown)"; + return tag2str[tag]; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn_mime.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn_mime.c new file mode 100644 index 000000000..dfd5be634 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn_mime.c @@ -0,0 +1,963 @@ +/* + * Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/ctype.h" +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "internal/evp_int.h" +#include "internal/bio.h" +#include "asn1_locl.h" + +/* + * Generalised MIME like utilities for streaming ASN1. Although many have a + * PKCS7/CMS like flavour others are more general purpose. + */ + +/* + * MIME format structures Note that all are translated to lower case apart + * from parameter values. Quotes are stripped off + */ + +struct mime_param_st { + char *param_name; /* Param name e.g. "micalg" */ + char *param_value; /* Param value e.g. "sha1" */ +}; + +struct mime_header_st { + char *name; /* Name of line e.g. "content-type" */ + char *value; /* Value of line e.g. "text/plain" */ + STACK_OF(MIME_PARAM) *params; /* Zero or more parameters */ +}; + +static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags, + const ASN1_ITEM *it); +static char *strip_ends(char *name); +static char *strip_start(char *name); +static char *strip_end(char *name); +static MIME_HEADER *mime_hdr_new(const char *name, const char *value); +static int mime_hdr_addparam(MIME_HEADER *mhdr, const char *name, const char *value); +static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio); +static int mime_hdr_cmp(const MIME_HEADER *const *a, + const MIME_HEADER *const *b); +static int mime_param_cmp(const MIME_PARAM *const *a, + const MIME_PARAM *const *b); +static void mime_param_free(MIME_PARAM *param); +static int mime_bound_check(char *line, int linelen, const char *bound, int blen); +static int multi_split(BIO *bio, const char *bound, STACK_OF(BIO) **ret); +static int strip_eol(char *linebuf, int *plen, int flags); +static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, const char *name); +static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, const char *name); +static void mime_hdr_free(MIME_HEADER *hdr); + +#define MAX_SMLEN 1024 +#define mime_debug(x) /* x */ + +/* Output an ASN1 structure in BER format streaming if necessary */ + +int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags, + const ASN1_ITEM *it) +{ + /* If streaming create stream BIO and copy all content through it */ + if (flags & SMIME_STREAM) { + BIO *bio, *tbio; + bio = BIO_new_NDEF(out, val, it); + if (!bio) { + ASN1err(ASN1_F_I2D_ASN1_BIO_STREAM, ERR_R_MALLOC_FAILURE); + return 0; + } + SMIME_crlf_copy(in, bio, flags); + (void)BIO_flush(bio); + /* Free up successive BIOs until we hit the old output BIO */ + do { + tbio = BIO_pop(bio); + BIO_free(bio); + bio = tbio; + } while (bio != out); + } + /* + * else just write out ASN1 structure which will have all content stored + * internally + */ + else + ASN1_item_i2d_bio(it, out, val); + return 1; +} + +/* Base 64 read and write of ASN1 structure */ + +static int B64_write_ASN1(BIO *out, ASN1_VALUE *val, BIO *in, int flags, + const ASN1_ITEM *it) +{ + BIO *b64; + int r; + b64 = BIO_new(BIO_f_base64()); + if (b64 == NULL) { + ASN1err(ASN1_F_B64_WRITE_ASN1, ERR_R_MALLOC_FAILURE); + return 0; + } + /* + * prepend the b64 BIO so all data is base64 encoded. + */ + out = BIO_push(b64, out); + r = i2d_ASN1_bio_stream(out, val, in, flags, it); + (void)BIO_flush(out); + BIO_pop(out); + BIO_free(b64); + return r; +} + +/* Streaming ASN1 PEM write */ + +int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags, + const char *hdr, const ASN1_ITEM *it) +{ + int r; + BIO_printf(out, "-----BEGIN %s-----\n", hdr); + r = B64_write_ASN1(out, val, in, flags, it); + BIO_printf(out, "-----END %s-----\n", hdr); + return r; +} + +static ASN1_VALUE *b64_read_asn1(BIO *bio, const ASN1_ITEM *it) +{ + BIO *b64; + ASN1_VALUE *val; + + if ((b64 = BIO_new(BIO_f_base64())) == NULL) { + ASN1err(ASN1_F_B64_READ_ASN1, ERR_R_MALLOC_FAILURE); + return 0; + } + bio = BIO_push(b64, bio); + val = ASN1_item_d2i_bio(it, bio, NULL); + if (!val) + ASN1err(ASN1_F_B64_READ_ASN1, ASN1_R_DECODE_ERROR); + (void)BIO_flush(bio); + BIO_pop(bio); + BIO_free(b64); + return val; +} + +/* Generate the MIME "micalg" parameter from RFC3851, RFC4490 */ + +static int asn1_write_micalg(BIO *out, STACK_OF(X509_ALGOR) *mdalgs) +{ + const EVP_MD *md; + int i, have_unknown = 0, write_comma, ret = 0, md_nid; + have_unknown = 0; + write_comma = 0; + for (i = 0; i < sk_X509_ALGOR_num(mdalgs); i++) { + if (write_comma) + BIO_write(out, ",", 1); + write_comma = 1; + md_nid = OBJ_obj2nid(sk_X509_ALGOR_value(mdalgs, i)->algorithm); + md = EVP_get_digestbynid(md_nid); + if (md && md->md_ctrl) { + int rv; + char *micstr; + rv = md->md_ctrl(NULL, EVP_MD_CTRL_MICALG, 0, &micstr); + if (rv > 0) { + BIO_puts(out, micstr); + OPENSSL_free(micstr); + continue; + } + if (rv != -2) + goto err; + } + switch (md_nid) { + case NID_sha1: + BIO_puts(out, "sha1"); + break; + + case NID_md5: + BIO_puts(out, "md5"); + break; + + case NID_sha256: + BIO_puts(out, "sha-256"); + break; + + case NID_sha384: + BIO_puts(out, "sha-384"); + break; + + case NID_sha512: + BIO_puts(out, "sha-512"); + break; + + case NID_id_GostR3411_94: + BIO_puts(out, "gostr3411-94"); + goto err; + + default: + if (have_unknown) + write_comma = 0; + else { + BIO_puts(out, "unknown"); + have_unknown = 1; + } + break; + + } + } + + ret = 1; + err: + + return ret; + +} + +/* SMIME sender */ + +int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags, + int ctype_nid, int econt_nid, + STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it) +{ + char bound[33], c; + int i; + const char *mime_prefix, *mime_eol, *cname = "smime.p7m"; + const char *msg_type = NULL; + if (flags & SMIME_OLDMIME) + mime_prefix = "application/x-pkcs7-"; + else + mime_prefix = "application/pkcs7-"; + + if (flags & SMIME_CRLFEOL) + mime_eol = "\r\n"; + else + mime_eol = "\n"; + if ((flags & SMIME_DETACHED) && data) { + /* We want multipart/signed */ + /* Generate a random boundary */ + if (RAND_bytes((unsigned char *)bound, 32) <= 0) + return 0; + for (i = 0; i < 32; i++) { + c = bound[i] & 0xf; + if (c < 10) + c += '0'; + else + c += 'A' - 10; + bound[i] = c; + } + bound[32] = 0; + BIO_printf(bio, "MIME-Version: 1.0%s", mime_eol); + BIO_printf(bio, "Content-Type: multipart/signed;"); + BIO_printf(bio, " protocol=\"%ssignature\";", mime_prefix); + BIO_puts(bio, " micalg=\""); + asn1_write_micalg(bio, mdalgs); + BIO_printf(bio, "\"; boundary=\"----%s\"%s%s", + bound, mime_eol, mime_eol); + BIO_printf(bio, "This is an S/MIME signed message%s%s", + mime_eol, mime_eol); + /* Now write out the first part */ + BIO_printf(bio, "------%s%s", bound, mime_eol); + if (!asn1_output_data(bio, data, val, flags, it)) + return 0; + BIO_printf(bio, "%s------%s%s", mime_eol, bound, mime_eol); + + /* Headers for signature */ + + BIO_printf(bio, "Content-Type: %ssignature;", mime_prefix); + BIO_printf(bio, " name=\"smime.p7s\"%s", mime_eol); + BIO_printf(bio, "Content-Transfer-Encoding: base64%s", mime_eol); + BIO_printf(bio, "Content-Disposition: attachment;"); + BIO_printf(bio, " filename=\"smime.p7s\"%s%s", mime_eol, mime_eol); + B64_write_ASN1(bio, val, NULL, 0, it); + BIO_printf(bio, "%s------%s--%s%s", mime_eol, bound, + mime_eol, mime_eol); + return 1; + } + + /* Determine smime-type header */ + + if (ctype_nid == NID_pkcs7_enveloped) + msg_type = "enveloped-data"; + else if (ctype_nid == NID_pkcs7_signed) { + if (econt_nid == NID_id_smime_ct_receipt) + msg_type = "signed-receipt"; + else if (sk_X509_ALGOR_num(mdalgs) >= 0) + msg_type = "signed-data"; + else + msg_type = "certs-only"; + } else if (ctype_nid == NID_id_smime_ct_compressedData) { + msg_type = "compressed-data"; + cname = "smime.p7z"; + } + /* MIME headers */ + BIO_printf(bio, "MIME-Version: 1.0%s", mime_eol); + BIO_printf(bio, "Content-Disposition: attachment;"); + BIO_printf(bio, " filename=\"%s\"%s", cname, mime_eol); + BIO_printf(bio, "Content-Type: %smime;", mime_prefix); + if (msg_type) + BIO_printf(bio, " smime-type=%s;", msg_type); + BIO_printf(bio, " name=\"%s\"%s", cname, mime_eol); + BIO_printf(bio, "Content-Transfer-Encoding: base64%s%s", + mime_eol, mime_eol); + if (!B64_write_ASN1(bio, val, data, flags, it)) + return 0; + BIO_printf(bio, "%s", mime_eol); + return 1; +} + +/* Handle output of ASN1 data */ + +static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags, + const ASN1_ITEM *it) +{ + BIO *tmpbio; + const ASN1_AUX *aux = it->funcs; + ASN1_STREAM_ARG sarg; + int rv = 1; + + /* + * If data is not detached or resigning then the output BIO is already + * set up to finalise when it is written through. + */ + if (!(flags & SMIME_DETACHED) || (flags & PKCS7_REUSE_DIGEST)) { + SMIME_crlf_copy(data, out, flags); + return 1; + } + + if (!aux || !aux->asn1_cb) { + ASN1err(ASN1_F_ASN1_OUTPUT_DATA, ASN1_R_STREAMING_NOT_SUPPORTED); + return 0; + } + + sarg.out = out; + sarg.ndef_bio = NULL; + sarg.boundary = NULL; + + /* Let ASN1 code prepend any needed BIOs */ + + if (aux->asn1_cb(ASN1_OP_DETACHED_PRE, &val, it, &sarg) <= 0) + return 0; + + /* Copy data across, passing through filter BIOs for processing */ + SMIME_crlf_copy(data, sarg.ndef_bio, flags); + + /* Finalize structure */ + if (aux->asn1_cb(ASN1_OP_DETACHED_POST, &val, it, &sarg) <= 0) + rv = 0; + + /* Now remove any digests prepended to the BIO */ + + while (sarg.ndef_bio != out) { + tmpbio = BIO_pop(sarg.ndef_bio); + BIO_free(sarg.ndef_bio); + sarg.ndef_bio = tmpbio; + } + + return rv; + +} + +/* + * SMIME reader: handle multipart/signed and opaque signing. in multipart + * case the content is placed in a memory BIO pointed to by "bcont". In + * opaque this is set to NULL + */ + +ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it) +{ + BIO *asnin; + STACK_OF(MIME_HEADER) *headers = NULL; + STACK_OF(BIO) *parts = NULL; + MIME_HEADER *hdr; + MIME_PARAM *prm; + ASN1_VALUE *val; + int ret; + + if (bcont) + *bcont = NULL; + + if ((headers = mime_parse_hdr(bio)) == NULL) { + ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_MIME_PARSE_ERROR); + return NULL; + } + + if ((hdr = mime_hdr_find(headers, "content-type")) == NULL + || hdr->value == NULL) { + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); + ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_CONTENT_TYPE); + return NULL; + } + + /* Handle multipart/signed */ + + if (strcmp(hdr->value, "multipart/signed") == 0) { + /* Split into two parts */ + prm = mime_param_find(hdr, "boundary"); + if (!prm || !prm->param_value) { + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); + ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_MULTIPART_BOUNDARY); + return NULL; + } + ret = multi_split(bio, prm->param_value, &parts); + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); + if (!ret || (sk_BIO_num(parts) != 2)) { + ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_MULTIPART_BODY_FAILURE); + sk_BIO_pop_free(parts, BIO_vfree); + return NULL; + } + + /* Parse the signature piece */ + asnin = sk_BIO_value(parts, 1); + + if ((headers = mime_parse_hdr(asnin)) == NULL) { + ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_MIME_SIG_PARSE_ERROR); + sk_BIO_pop_free(parts, BIO_vfree); + return NULL; + } + + /* Get content type */ + + if ((hdr = mime_hdr_find(headers, "content-type")) == NULL + || hdr->value == NULL) { + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); + ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_SIG_CONTENT_TYPE); + sk_BIO_pop_free(parts, BIO_vfree); + return NULL; + } + + if (strcmp(hdr->value, "application/x-pkcs7-signature") && + strcmp(hdr->value, "application/pkcs7-signature")) { + ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_SIG_INVALID_MIME_TYPE); + ERR_add_error_data(2, "type: ", hdr->value); + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); + sk_BIO_pop_free(parts, BIO_vfree); + return NULL; + } + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); + /* Read in ASN1 */ + if ((val = b64_read_asn1(asnin, it)) == NULL) { + ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_ASN1_SIG_PARSE_ERROR); + sk_BIO_pop_free(parts, BIO_vfree); + return NULL; + } + + if (bcont) { + *bcont = sk_BIO_value(parts, 0); + BIO_free(asnin); + sk_BIO_free(parts); + } else + sk_BIO_pop_free(parts, BIO_vfree); + return val; + } + + /* OK, if not multipart/signed try opaque signature */ + + if (strcmp(hdr->value, "application/x-pkcs7-mime") && + strcmp(hdr->value, "application/pkcs7-mime")) { + ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_INVALID_MIME_TYPE); + ERR_add_error_data(2, "type: ", hdr->value); + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); + return NULL; + } + + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); + + if ((val = b64_read_asn1(bio, it)) == NULL) { + ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_ASN1_PARSE_ERROR); + return NULL; + } + return val; + +} + +/* Copy text from one BIO to another making the output CRLF at EOL */ +int SMIME_crlf_copy(BIO *in, BIO *out, int flags) +{ + BIO *bf; + char eol; + int len; + char linebuf[MAX_SMLEN]; + /* + * Buffer output so we don't write one line at a time. This is useful + * when streaming as we don't end up with one OCTET STRING per line. + */ + bf = BIO_new(BIO_f_buffer()); + if (bf == NULL) + return 0; + out = BIO_push(bf, out); + if (flags & SMIME_BINARY) { + while ((len = BIO_read(in, linebuf, MAX_SMLEN)) > 0) + BIO_write(out, linebuf, len); + } else { + int eolcnt = 0; + if (flags & SMIME_TEXT) + BIO_printf(out, "Content-Type: text/plain\r\n\r\n"); + while ((len = BIO_gets(in, linebuf, MAX_SMLEN)) > 0) { + eol = strip_eol(linebuf, &len, flags); + if (len) { + /* Not EOF: write out all CRLF */ + if (flags & SMIME_ASCIICRLF) { + int i; + for (i = 0; i < eolcnt; i++) + BIO_write(out, "\r\n", 2); + eolcnt = 0; + } + BIO_write(out, linebuf, len); + if (eol) + BIO_write(out, "\r\n", 2); + } else if (flags & SMIME_ASCIICRLF) + eolcnt++; + else if (eol) + BIO_write(out, "\r\n", 2); + } + } + (void)BIO_flush(out); + BIO_pop(out); + BIO_free(bf); + return 1; +} + +/* Strip off headers if they are text/plain */ +int SMIME_text(BIO *in, BIO *out) +{ + char iobuf[4096]; + int len; + STACK_OF(MIME_HEADER) *headers; + MIME_HEADER *hdr; + + if ((headers = mime_parse_hdr(in)) == NULL) { + ASN1err(ASN1_F_SMIME_TEXT, ASN1_R_MIME_PARSE_ERROR); + return 0; + } + if ((hdr = mime_hdr_find(headers, "content-type")) == NULL + || hdr->value == NULL) { + ASN1err(ASN1_F_SMIME_TEXT, ASN1_R_MIME_NO_CONTENT_TYPE); + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); + return 0; + } + if (strcmp(hdr->value, "text/plain")) { + ASN1err(ASN1_F_SMIME_TEXT, ASN1_R_INVALID_MIME_TYPE); + ERR_add_error_data(2, "type: ", hdr->value); + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); + return 0; + } + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); + while ((len = BIO_read(in, iobuf, sizeof(iobuf))) > 0) + BIO_write(out, iobuf, len); + if (len < 0) + return 0; + return 1; +} + +/* + * Split a multipart/XXX message body into component parts: result is + * canonical parts in a STACK of bios + */ + +static int multi_split(BIO *bio, const char *bound, STACK_OF(BIO) **ret) +{ + char linebuf[MAX_SMLEN]; + int len, blen; + int eol = 0, next_eol = 0; + BIO *bpart = NULL; + STACK_OF(BIO) *parts; + char state, part, first; + + blen = strlen(bound); + part = 0; + state = 0; + first = 1; + parts = sk_BIO_new_null(); + *ret = parts; + if (*ret == NULL) + return 0; + while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) { + state = mime_bound_check(linebuf, len, bound, blen); + if (state == 1) { + first = 1; + part++; + } else if (state == 2) { + if (!sk_BIO_push(parts, bpart)) { + BIO_free(bpart); + return 0; + } + return 1; + } else if (part) { + /* Strip CR+LF from linebuf */ + next_eol = strip_eol(linebuf, &len, 0); + if (first) { + first = 0; + if (bpart) + if (!sk_BIO_push(parts, bpart)) { + BIO_free(bpart); + return 0; + } + bpart = BIO_new(BIO_s_mem()); + if (bpart == NULL) + return 0; + BIO_set_mem_eof_return(bpart, 0); + } else if (eol) + BIO_write(bpart, "\r\n", 2); + eol = next_eol; + if (len) + BIO_write(bpart, linebuf, len); + } + } + BIO_free(bpart); + return 0; +} + +/* This is the big one: parse MIME header lines up to message body */ + +#define MIME_INVALID 0 +#define MIME_START 1 +#define MIME_TYPE 2 +#define MIME_NAME 3 +#define MIME_VALUE 4 +#define MIME_QUOTE 5 +#define MIME_COMMENT 6 + +static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio) +{ + char *p, *q, c; + char *ntmp; + char linebuf[MAX_SMLEN]; + MIME_HEADER *mhdr = NULL, *new_hdr = NULL; + STACK_OF(MIME_HEADER) *headers; + int len, state, save_state = 0; + + headers = sk_MIME_HEADER_new(mime_hdr_cmp); + if (headers == NULL) + return NULL; + while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) { + /* If whitespace at line start then continuation line */ + if (mhdr && ossl_isspace(linebuf[0])) + state = MIME_NAME; + else + state = MIME_START; + ntmp = NULL; + /* Go through all characters */ + for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && (c != '\n'); + p++) { + + /* + * State machine to handle MIME headers if this looks horrible + * that's because it *is* + */ + + switch (state) { + case MIME_START: + if (c == ':') { + state = MIME_TYPE; + *p = 0; + ntmp = strip_ends(q); + q = p + 1; + } + break; + + case MIME_TYPE: + if (c == ';') { + mime_debug("Found End Value\n"); + *p = 0; + new_hdr = mime_hdr_new(ntmp, strip_ends(q)); + if (new_hdr == NULL) + goto err; + if (!sk_MIME_HEADER_push(headers, new_hdr)) + goto err; + mhdr = new_hdr; + new_hdr = NULL; + ntmp = NULL; + q = p + 1; + state = MIME_NAME; + } else if (c == '(') { + save_state = state; + state = MIME_COMMENT; + } + break; + + case MIME_COMMENT: + if (c == ')') { + state = save_state; + } + break; + + case MIME_NAME: + if (c == '=') { + state = MIME_VALUE; + *p = 0; + ntmp = strip_ends(q); + q = p + 1; + } + break; + + case MIME_VALUE: + if (c == ';') { + state = MIME_NAME; + *p = 0; + mime_hdr_addparam(mhdr, ntmp, strip_ends(q)); + ntmp = NULL; + q = p + 1; + } else if (c == '"') { + mime_debug("Found Quote\n"); + state = MIME_QUOTE; + } else if (c == '(') { + save_state = state; + state = MIME_COMMENT; + } + break; + + case MIME_QUOTE: + if (c == '"') { + mime_debug("Found Match Quote\n"); + state = MIME_VALUE; + } + break; + } + } + + if (state == MIME_TYPE) { + new_hdr = mime_hdr_new(ntmp, strip_ends(q)); + if (new_hdr == NULL) + goto err; + if (!sk_MIME_HEADER_push(headers, new_hdr)) + goto err; + mhdr = new_hdr; + new_hdr = NULL; + } else if (state == MIME_VALUE) + mime_hdr_addparam(mhdr, ntmp, strip_ends(q)); + if (p == linebuf) + break; /* Blank line means end of headers */ + } + + return headers; + +err: + mime_hdr_free(new_hdr); + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); + return NULL; +} + +static char *strip_ends(char *name) +{ + return strip_end(strip_start(name)); +} + +/* Strip a parameter of whitespace from start of param */ +static char *strip_start(char *name) +{ + char *p, c; + /* Look for first non white space or quote */ + for (p = name; (c = *p); p++) { + if (c == '"') { + /* Next char is start of string if non null */ + if (p[1]) + return p + 1; + /* Else null string */ + return NULL; + } + if (!ossl_isspace(c)) + return p; + } + return NULL; +} + +/* As above but strip from end of string : maybe should handle brackets? */ +static char *strip_end(char *name) +{ + char *p, c; + if (!name) + return NULL; + /* Look for first non white space or quote */ + for (p = name + strlen(name) - 1; p >= name; p--) { + c = *p; + if (c == '"') { + if (p - 1 == name) + return NULL; + *p = 0; + return name; + } + if (ossl_isspace(c)) + *p = 0; + else + return name; + } + return NULL; +} + +static MIME_HEADER *mime_hdr_new(const char *name, const char *value) +{ + MIME_HEADER *mhdr = NULL; + char *tmpname = NULL, *tmpval = NULL, *p; + + if (name) { + if ((tmpname = OPENSSL_strdup(name)) == NULL) + return NULL; + for (p = tmpname; *p; p++) + *p = ossl_tolower(*p); + } + if (value) { + if ((tmpval = OPENSSL_strdup(value)) == NULL) + goto err; + for (p = tmpval; *p; p++) + *p = ossl_tolower(*p); + } + mhdr = OPENSSL_malloc(sizeof(*mhdr)); + if (mhdr == NULL) + goto err; + mhdr->name = tmpname; + mhdr->value = tmpval; + if ((mhdr->params = sk_MIME_PARAM_new(mime_param_cmp)) == NULL) + goto err; + return mhdr; + + err: + OPENSSL_free(tmpname); + OPENSSL_free(tmpval); + OPENSSL_free(mhdr); + return NULL; +} + +static int mime_hdr_addparam(MIME_HEADER *mhdr, const char *name, const char *value) +{ + char *tmpname = NULL, *tmpval = NULL, *p; + MIME_PARAM *mparam = NULL; + + if (name) { + tmpname = OPENSSL_strdup(name); + if (!tmpname) + goto err; + for (p = tmpname; *p; p++) + *p = ossl_tolower(*p); + } + if (value) { + tmpval = OPENSSL_strdup(value); + if (!tmpval) + goto err; + } + /* Parameter values are case sensitive so leave as is */ + mparam = OPENSSL_malloc(sizeof(*mparam)); + if (mparam == NULL) + goto err; + mparam->param_name = tmpname; + mparam->param_value = tmpval; + if (!sk_MIME_PARAM_push(mhdr->params, mparam)) + goto err; + return 1; + err: + OPENSSL_free(tmpname); + OPENSSL_free(tmpval); + OPENSSL_free(mparam); + return 0; +} + +static int mime_hdr_cmp(const MIME_HEADER *const *a, + const MIME_HEADER *const *b) +{ + if (!(*a)->name || !(*b)->name) + return ! !(*a)->name - ! !(*b)->name; + + return strcmp((*a)->name, (*b)->name); +} + +static int mime_param_cmp(const MIME_PARAM *const *a, + const MIME_PARAM *const *b) +{ + if (!(*a)->param_name || !(*b)->param_name) + return ! !(*a)->param_name - ! !(*b)->param_name; + return strcmp((*a)->param_name, (*b)->param_name); +} + +/* Find a header with a given name (if possible) */ + +static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, const char *name) +{ + MIME_HEADER htmp; + int idx; + + htmp.name = (char *)name; + htmp.value = NULL; + htmp.params = NULL; + + idx = sk_MIME_HEADER_find(hdrs, &htmp); + return sk_MIME_HEADER_value(hdrs, idx); +} + +static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, const char *name) +{ + MIME_PARAM param; + int idx; + + param.param_name = (char *)name; + param.param_value = NULL; + idx = sk_MIME_PARAM_find(hdr->params, ¶m); + return sk_MIME_PARAM_value(hdr->params, idx); +} + +static void mime_hdr_free(MIME_HEADER *hdr) +{ + if (hdr == NULL) + return; + OPENSSL_free(hdr->name); + OPENSSL_free(hdr->value); + if (hdr->params) + sk_MIME_PARAM_pop_free(hdr->params, mime_param_free); + OPENSSL_free(hdr); +} + +static void mime_param_free(MIME_PARAM *param) +{ + OPENSSL_free(param->param_name); + OPENSSL_free(param->param_value); + OPENSSL_free(param); +} + +/*- + * Check for a multipart boundary. Returns: + * 0 : no boundary + * 1 : part boundary + * 2 : final boundary + */ +static int mime_bound_check(char *line, int linelen, const char *bound, int blen) +{ + if (linelen == -1) + linelen = strlen(line); + if (blen == -1) + blen = strlen(bound); + /* Quickly eliminate if line length too short */ + if (blen + 2 > linelen) + return 0; + /* Check for part boundary */ + if ((strncmp(line, "--", 2) == 0) + && strncmp(line + 2, bound, blen) == 0) { + if (strncmp(line + blen + 2, "--", 2) == 0) + return 2; + else + return 1; + } + return 0; +} + +static int strip_eol(char *linebuf, int *plen, int flags) +{ + int len = *plen; + char *p, c; + int is_eol = 0; + + for (p = linebuf + len - 1; len > 0; len--, p--) { + c = *p; + if (c == '\n') { + is_eol = 1; + } else if (is_eol && flags & SMIME_ASCIICRLF && c == 32) { + /* Strip trailing space on a line; 32 == ASCII for ' ' */ + continue; + } else if (c != '\r') { + break; + } + } + *plen = len; + return is_eol; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn_moid.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn_moid.c new file mode 100644 index 000000000..68a01f311 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn_moid.c @@ -0,0 +1,100 @@ +/* + * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/ctype.h" +#include +#include "internal/cryptlib.h" +#include +#include +#include "internal/asn1_int.h" +#include "internal/objects.h" + +/* Simple ASN1 OID module: add all objects in a given section */ + +static int do_create(const char *value, const char *name); + +static int oid_module_init(CONF_IMODULE *md, const CONF *cnf) +{ + int i; + const char *oid_section; + STACK_OF(CONF_VALUE) *sktmp; + CONF_VALUE *oval; + + oid_section = CONF_imodule_get_value(md); + if ((sktmp = NCONF_get_section(cnf, oid_section)) == NULL) { + ASN1err(ASN1_F_OID_MODULE_INIT, ASN1_R_ERROR_LOADING_SECTION); + return 0; + } + for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) { + oval = sk_CONF_VALUE_value(sktmp, i); + if (!do_create(oval->value, oval->name)) { + ASN1err(ASN1_F_OID_MODULE_INIT, ASN1_R_ADDING_OBJECT); + return 0; + } + } + return 1; +} + +static void oid_module_finish(CONF_IMODULE *md) +{ +} + +void ASN1_add_oid_module(void) +{ + CONF_module_add("oid_section", oid_module_init, oid_module_finish); +} + +/*- + * Create an OID based on a name value pair. Accept two formats. + * shortname = 1.2.3.4 + * shortname = some long name, 1.2.3.4 + */ + +static int do_create(const char *value, const char *name) +{ + int nid; + const char *ln, *ostr, *p; + char *lntmp = NULL; + + p = strrchr(value, ','); + if (p == NULL) { + ln = name; + ostr = value; + } else { + ln = value; + ostr = p + 1; + if (*ostr == '\0') + return 0; + while (ossl_isspace(*ostr)) + ostr++; + while (ossl_isspace(*ln)) + ln++; + p--; + while (ossl_isspace(*p)) { + if (p == ln) + return 0; + p--; + } + p++; + if ((lntmp = OPENSSL_malloc((p - ln) + 1)) == NULL) { + ASN1err(ASN1_F_DO_CREATE, ERR_R_MALLOC_FAILURE); + return 0; + } + memcpy(lntmp, ln, p - ln); + lntmp[p - ln] = '\0'; + ln = lntmp; + } + + nid = OBJ_create(ostr, name, ln); + + OPENSSL_free(lntmp); + + return nid != NID_undef; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn_mstbl.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn_mstbl.c new file mode 100644 index 000000000..ddcbcd07f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn_mstbl.c @@ -0,0 +1,113 @@ +/* + * Copyright 2012-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include +#include + +/* Multi string module: add table entries from a given section */ + +static int do_tcreate(const char *value, const char *name); + +static int stbl_module_init(CONF_IMODULE *md, const CONF *cnf) +{ + int i; + const char *stbl_section; + STACK_OF(CONF_VALUE) *sktmp; + CONF_VALUE *mval; + + stbl_section = CONF_imodule_get_value(md); + if ((sktmp = NCONF_get_section(cnf, stbl_section)) == NULL) { + ASN1err(ASN1_F_STBL_MODULE_INIT, ASN1_R_ERROR_LOADING_SECTION); + return 0; + } + for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) { + mval = sk_CONF_VALUE_value(sktmp, i); + if (!do_tcreate(mval->value, mval->name)) { + ASN1err(ASN1_F_STBL_MODULE_INIT, ASN1_R_INVALID_VALUE); + return 0; + } + } + return 1; +} + +static void stbl_module_finish(CONF_IMODULE *md) +{ + ASN1_STRING_TABLE_cleanup(); +} + +void ASN1_add_stable_module(void) +{ + CONF_module_add("stbl_section", stbl_module_init, stbl_module_finish); +} + +/* + * Create an table entry based on a name value pair. format is oid_name = + * n1:v1, n2:v2,... where name is "min", "max", "mask" or "flags". + */ + +static int do_tcreate(const char *value, const char *name) +{ + char *eptr; + int nid, i, rv = 0; + long tbl_min = -1, tbl_max = -1; + unsigned long tbl_mask = 0, tbl_flags = 0; + STACK_OF(CONF_VALUE) *lst = NULL; + CONF_VALUE *cnf = NULL; + nid = OBJ_sn2nid(name); + if (nid == NID_undef) + nid = OBJ_ln2nid(name); + if (nid == NID_undef) + goto err; + lst = X509V3_parse_list(value); + if (!lst) + goto err; + for (i = 0; i < sk_CONF_VALUE_num(lst); i++) { + cnf = sk_CONF_VALUE_value(lst, i); + if (strcmp(cnf->name, "min") == 0) { + tbl_min = strtoul(cnf->value, &eptr, 0); + if (*eptr) + goto err; + } else if (strcmp(cnf->name, "max") == 0) { + tbl_max = strtoul(cnf->value, &eptr, 0); + if (*eptr) + goto err; + } else if (strcmp(cnf->name, "mask") == 0) { + if (!ASN1_str2mask(cnf->value, &tbl_mask) || !tbl_mask) + goto err; + } else if (strcmp(cnf->name, "flags") == 0) { + if (strcmp(cnf->value, "nomask") == 0) + tbl_flags = STABLE_NO_MASK; + else if (strcmp(cnf->value, "none") == 0) + tbl_flags = STABLE_FLAGS_CLEAR; + else + goto err; + } else + goto err; + } + rv = 1; + err: + if (rv == 0) { + ASN1err(ASN1_F_DO_TCREATE, ASN1_R_INVALID_STRING_TABLE_VALUE); + if (cnf) + ERR_add_error_data(4, "field=", cnf->name, + ", value=", cnf->value); + else + ERR_add_error_data(4, "name=", name, ", value=", value); + } else { + rv = ASN1_STRING_TABLE_add(nid, tbl_min, tbl_max, + tbl_mask, tbl_flags); + if (!rv) + ASN1err(ASN1_F_DO_TCREATE, ERR_R_MALLOC_FAILURE); + } + sk_CONF_VALUE_pop_free(lst, X509V3_conf_free); + return rv; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn_pack.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn_pack.c new file mode 100644 index 000000000..63bc30675 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/asn_pack.c @@ -0,0 +1,62 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include + +/* ASN1 packing and unpacking functions */ + +ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct) +{ + ASN1_STRING *octmp; + + if (oct == NULL || *oct == NULL) { + if ((octmp = ASN1_STRING_new()) == NULL) { + ASN1err(ASN1_F_ASN1_ITEM_PACK, ERR_R_MALLOC_FAILURE); + return NULL; + } + } else { + octmp = *oct; + } + + OPENSSL_free(octmp->data); + octmp->data = NULL; + + if ((octmp->length = ASN1_item_i2d(obj, &octmp->data, it)) == 0) { + ASN1err(ASN1_F_ASN1_ITEM_PACK, ASN1_R_ENCODE_ERROR); + goto err; + } + if (octmp->data == NULL) { + ASN1err(ASN1_F_ASN1_ITEM_PACK, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (oct != NULL && *oct == NULL) + *oct = octmp; + + return octmp; + err: + if (oct == NULL || *oct == NULL) + ASN1_STRING_free(octmp); + return NULL; +} + +/* Extract an ASN1 object from an ASN1_STRING */ + +void *ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it) +{ + const unsigned char *p; + void *ret; + + p = oct->data; + if ((ret = ASN1_item_d2i(NULL, &p, oct->length, it)) == NULL) + ASN1err(ASN1_F_ASN1_ITEM_UNPACK, ASN1_R_DECODE_ERROR); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/bio_asn1.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/bio_asn1.c new file mode 100644 index 000000000..86ee56632 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/bio_asn1.c @@ -0,0 +1,444 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Experimental ASN1 BIO. When written through the data is converted to an + * ASN1 string type: default is OCTET STRING. Additional functions can be + * provided to add prefix and suffix data. + */ + +#include +#include "internal/bio.h" +#include +#include "internal/cryptlib.h" + +/* Must be large enough for biggest tag+length */ +#define DEFAULT_ASN1_BUF_SIZE 20 + +typedef enum { + ASN1_STATE_START, + ASN1_STATE_PRE_COPY, + ASN1_STATE_HEADER, + ASN1_STATE_HEADER_COPY, + ASN1_STATE_DATA_COPY, + ASN1_STATE_POST_COPY, + ASN1_STATE_DONE +} asn1_bio_state_t; + +typedef struct BIO_ASN1_EX_FUNCS_st { + asn1_ps_func *ex_func; + asn1_ps_func *ex_free_func; +} BIO_ASN1_EX_FUNCS; + +typedef struct BIO_ASN1_BUF_CTX_t { + /* Internal state */ + asn1_bio_state_t state; + /* Internal buffer */ + unsigned char *buf; + /* Size of buffer */ + int bufsize; + /* Current position in buffer */ + int bufpos; + /* Current buffer length */ + int buflen; + /* Amount of data to copy */ + int copylen; + /* Class and tag to use */ + int asn1_class, asn1_tag; + asn1_ps_func *prefix, *prefix_free, *suffix, *suffix_free; + /* Extra buffer for prefix and suffix data */ + unsigned char *ex_buf; + int ex_len; + int ex_pos; + void *ex_arg; +} BIO_ASN1_BUF_CTX; + +static int asn1_bio_write(BIO *h, const char *buf, int num); +static int asn1_bio_read(BIO *h, char *buf, int size); +static int asn1_bio_puts(BIO *h, const char *str); +static int asn1_bio_gets(BIO *h, char *str, int size); +static long asn1_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int asn1_bio_new(BIO *h); +static int asn1_bio_free(BIO *data); +static long asn1_bio_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); + +static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size); +static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx, + asn1_ps_func *cleanup, asn1_bio_state_t next); +static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx, + asn1_ps_func *setup, + asn1_bio_state_t ex_state, + asn1_bio_state_t other_state); + +static const BIO_METHOD methods_asn1 = { + BIO_TYPE_ASN1, + "asn1", + /* TODO: Convert to new style write function */ + bwrite_conv, + asn1_bio_write, + /* TODO: Convert to new style read function */ + bread_conv, + asn1_bio_read, + asn1_bio_puts, + asn1_bio_gets, + asn1_bio_ctrl, + asn1_bio_new, + asn1_bio_free, + asn1_bio_callback_ctrl, +}; + +const BIO_METHOD *BIO_f_asn1(void) +{ + return &methods_asn1; +} + +static int asn1_bio_new(BIO *b) +{ + BIO_ASN1_BUF_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); + + if (ctx == NULL) + return 0; + if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE)) { + OPENSSL_free(ctx); + return 0; + } + BIO_set_data(b, ctx); + BIO_set_init(b, 1); + + return 1; +} + +static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size) +{ + if ((ctx->buf = OPENSSL_malloc(size)) == NULL) { + ASN1err(ASN1_F_ASN1_BIO_INIT, ERR_R_MALLOC_FAILURE); + return 0; + } + ctx->bufsize = size; + ctx->asn1_class = V_ASN1_UNIVERSAL; + ctx->asn1_tag = V_ASN1_OCTET_STRING; + ctx->state = ASN1_STATE_START; + return 1; +} + +static int asn1_bio_free(BIO *b) +{ + BIO_ASN1_BUF_CTX *ctx; + + if (b == NULL) + return 0; + + ctx = BIO_get_data(b); + if (ctx == NULL) + return 0; + + OPENSSL_free(ctx->buf); + OPENSSL_free(ctx); + BIO_set_data(b, NULL); + BIO_set_init(b, 0); + + return 1; +} + +static int asn1_bio_write(BIO *b, const char *in, int inl) +{ + BIO_ASN1_BUF_CTX *ctx; + int wrmax, wrlen, ret; + unsigned char *p; + BIO *next; + + ctx = BIO_get_data(b); + next = BIO_next(b); + if (in == NULL || inl < 0 || ctx == NULL || next == NULL) + return 0; + + wrlen = 0; + ret = -1; + + for (;;) { + switch (ctx->state) { + /* Setup prefix data, call it */ + case ASN1_STATE_START: + if (!asn1_bio_setup_ex(b, ctx, ctx->prefix, + ASN1_STATE_PRE_COPY, ASN1_STATE_HEADER)) + return 0; + break; + + /* Copy any pre data first */ + case ASN1_STATE_PRE_COPY: + + ret = asn1_bio_flush_ex(b, ctx, ctx->prefix_free, + ASN1_STATE_HEADER); + + if (ret <= 0) + goto done; + + break; + + case ASN1_STATE_HEADER: + ctx->buflen = ASN1_object_size(0, inl, ctx->asn1_tag) - inl; + if (!ossl_assert(ctx->buflen <= ctx->bufsize)) + return 0; + p = ctx->buf; + ASN1_put_object(&p, 0, inl, ctx->asn1_tag, ctx->asn1_class); + ctx->copylen = inl; + ctx->state = ASN1_STATE_HEADER_COPY; + + break; + + case ASN1_STATE_HEADER_COPY: + ret = BIO_write(next, ctx->buf + ctx->bufpos, ctx->buflen); + if (ret <= 0) + goto done; + + ctx->buflen -= ret; + if (ctx->buflen) + ctx->bufpos += ret; + else { + ctx->bufpos = 0; + ctx->state = ASN1_STATE_DATA_COPY; + } + + break; + + case ASN1_STATE_DATA_COPY: + + if (inl > ctx->copylen) + wrmax = ctx->copylen; + else + wrmax = inl; + ret = BIO_write(next, in, wrmax); + if (ret <= 0) + goto done; + wrlen += ret; + ctx->copylen -= ret; + in += ret; + inl -= ret; + + if (ctx->copylen == 0) + ctx->state = ASN1_STATE_HEADER; + + if (inl == 0) + goto done; + + break; + + case ASN1_STATE_POST_COPY: + case ASN1_STATE_DONE: + BIO_clear_retry_flags(b); + return 0; + + } + + } + + done: + BIO_clear_retry_flags(b); + BIO_copy_next_retry(b); + + return (wrlen > 0) ? wrlen : ret; + +} + +static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx, + asn1_ps_func *cleanup, asn1_bio_state_t next) +{ + int ret; + + if (ctx->ex_len <= 0) + return 1; + for (;;) { + ret = BIO_write(BIO_next(b), ctx->ex_buf + ctx->ex_pos, ctx->ex_len); + if (ret <= 0) + break; + ctx->ex_len -= ret; + if (ctx->ex_len > 0) + ctx->ex_pos += ret; + else { + if (cleanup) + cleanup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg); + ctx->state = next; + ctx->ex_pos = 0; + break; + } + } + return ret; +} + +static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx, + asn1_ps_func *setup, + asn1_bio_state_t ex_state, + asn1_bio_state_t other_state) +{ + if (setup && !setup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg)) { + BIO_clear_retry_flags(b); + return 0; + } + if (ctx->ex_len > 0) + ctx->state = ex_state; + else + ctx->state = other_state; + return 1; +} + +static int asn1_bio_read(BIO *b, char *in, int inl) +{ + BIO *next = BIO_next(b); + if (next == NULL) + return 0; + return BIO_read(next, in, inl); +} + +static int asn1_bio_puts(BIO *b, const char *str) +{ + return asn1_bio_write(b, str, strlen(str)); +} + +static int asn1_bio_gets(BIO *b, char *str, int size) +{ + BIO *next = BIO_next(b); + if (next == NULL) + return 0; + return BIO_gets(next, str, size); +} + +static long asn1_bio_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) +{ + BIO *next = BIO_next(b); + if (next == NULL) + return 0; + return BIO_callback_ctrl(next, cmd, fp); +} + +static long asn1_bio_ctrl(BIO *b, int cmd, long arg1, void *arg2) +{ + BIO_ASN1_BUF_CTX *ctx; + BIO_ASN1_EX_FUNCS *ex_func; + long ret = 1; + BIO *next; + + ctx = BIO_get_data(b); + if (ctx == NULL) + return 0; + next = BIO_next(b); + switch (cmd) { + + case BIO_C_SET_PREFIX: + ex_func = arg2; + ctx->prefix = ex_func->ex_func; + ctx->prefix_free = ex_func->ex_free_func; + break; + + case BIO_C_GET_PREFIX: + ex_func = arg2; + ex_func->ex_func = ctx->prefix; + ex_func->ex_free_func = ctx->prefix_free; + break; + + case BIO_C_SET_SUFFIX: + ex_func = arg2; + ctx->suffix = ex_func->ex_func; + ctx->suffix_free = ex_func->ex_free_func; + break; + + case BIO_C_GET_SUFFIX: + ex_func = arg2; + ex_func->ex_func = ctx->suffix; + ex_func->ex_free_func = ctx->suffix_free; + break; + + case BIO_C_SET_EX_ARG: + ctx->ex_arg = arg2; + break; + + case BIO_C_GET_EX_ARG: + *(void **)arg2 = ctx->ex_arg; + break; + + case BIO_CTRL_FLUSH: + if (next == NULL) + return 0; + + /* Call post function if possible */ + if (ctx->state == ASN1_STATE_HEADER) { + if (!asn1_bio_setup_ex(b, ctx, ctx->suffix, + ASN1_STATE_POST_COPY, ASN1_STATE_DONE)) + return 0; + } + + if (ctx->state == ASN1_STATE_POST_COPY) { + ret = asn1_bio_flush_ex(b, ctx, ctx->suffix_free, + ASN1_STATE_DONE); + if (ret <= 0) + return ret; + } + + if (ctx->state == ASN1_STATE_DONE) + return BIO_ctrl(next, cmd, arg1, arg2); + else { + BIO_clear_retry_flags(b); + return 0; + } + + default: + if (next == NULL) + return 0; + return BIO_ctrl(next, cmd, arg1, arg2); + + } + + return ret; +} + +static int asn1_bio_set_ex(BIO *b, int cmd, + asn1_ps_func *ex_func, asn1_ps_func *ex_free_func) +{ + BIO_ASN1_EX_FUNCS extmp; + extmp.ex_func = ex_func; + extmp.ex_free_func = ex_free_func; + return BIO_ctrl(b, cmd, 0, &extmp); +} + +static int asn1_bio_get_ex(BIO *b, int cmd, + asn1_ps_func **ex_func, + asn1_ps_func **ex_free_func) +{ + BIO_ASN1_EX_FUNCS extmp; + int ret; + ret = BIO_ctrl(b, cmd, 0, &extmp); + if (ret > 0) { + *ex_func = extmp.ex_func; + *ex_free_func = extmp.ex_free_func; + } + return ret; +} + +int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix, + asn1_ps_func *prefix_free) +{ + return asn1_bio_set_ex(b, BIO_C_SET_PREFIX, prefix, prefix_free); +} + +int BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix, + asn1_ps_func **pprefix_free) +{ + return asn1_bio_get_ex(b, BIO_C_GET_PREFIX, pprefix, pprefix_free); +} + +int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix, + asn1_ps_func *suffix_free) +{ + return asn1_bio_set_ex(b, BIO_C_SET_SUFFIX, suffix, suffix_free); +} + +int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix, + asn1_ps_func **psuffix_free) +{ + return asn1_bio_get_ex(b, BIO_C_GET_SUFFIX, psuffix, psuffix_free); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/bio_ndef.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/bio_ndef.c new file mode 100644 index 000000000..6222c9907 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/bio_ndef.c @@ -0,0 +1,201 @@ +/* + * Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include + +#include + +/* Experimental NDEF ASN1 BIO support routines */ + +/* + * The usage is quite simple, initialize an ASN1 structure, get a BIO from it + * then any data written through the BIO will end up translated to + * appropriate format on the fly. The data is streamed out and does *not* + * need to be all held in memory at once. When the BIO is flushed the output + * is finalized and any signatures etc written out. The BIO is a 'proper' + * BIO and can handle non blocking I/O correctly. The usage is simple. The + * implementation is *not*... + */ + +/* BIO support data stored in the ASN1 BIO ex_arg */ + +typedef struct ndef_aux_st { + /* ASN1 structure this BIO refers to */ + ASN1_VALUE *val; + const ASN1_ITEM *it; + /* Top of the BIO chain */ + BIO *ndef_bio; + /* Output BIO */ + BIO *out; + /* Boundary where content is inserted */ + unsigned char **boundary; + /* DER buffer start */ + unsigned char *derbuf; +} NDEF_SUPPORT; + +static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg); +static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, + void *parg); +static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg); +static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, + void *parg); + +BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it) +{ + NDEF_SUPPORT *ndef_aux = NULL; + BIO *asn_bio = NULL; + const ASN1_AUX *aux = it->funcs; + ASN1_STREAM_ARG sarg; + + if (!aux || !aux->asn1_cb) { + ASN1err(ASN1_F_BIO_NEW_NDEF, ASN1_R_STREAMING_NOT_SUPPORTED); + return NULL; + } + ndef_aux = OPENSSL_zalloc(sizeof(*ndef_aux)); + asn_bio = BIO_new(BIO_f_asn1()); + if (ndef_aux == NULL || asn_bio == NULL) + goto err; + + /* ASN1 bio needs to be next to output BIO */ + out = BIO_push(asn_bio, out); + if (out == NULL) + goto err; + + BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free); + BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free); + + /* + * Now let callback prepends any digest, cipher etc BIOs ASN1 structure + * needs. + */ + + sarg.out = out; + sarg.ndef_bio = NULL; + sarg.boundary = NULL; + + if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0) + goto err; + + ndef_aux->val = val; + ndef_aux->it = it; + ndef_aux->ndef_bio = sarg.ndef_bio; + ndef_aux->boundary = sarg.boundary; + ndef_aux->out = out; + + BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux); + + return sarg.ndef_bio; + + err: + BIO_free(asn_bio); + OPENSSL_free(ndef_aux); + return NULL; +} + +static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg) +{ + NDEF_SUPPORT *ndef_aux; + unsigned char *p; + int derlen; + + if (!parg) + return 0; + + ndef_aux = *(NDEF_SUPPORT **)parg; + + derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it); + if ((p = OPENSSL_malloc(derlen)) == NULL) { + ASN1err(ASN1_F_NDEF_PREFIX, ERR_R_MALLOC_FAILURE); + return 0; + } + + ndef_aux->derbuf = p; + *pbuf = p; + derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it); + + if (!*ndef_aux->boundary) + return 0; + + *plen = *ndef_aux->boundary - *pbuf; + + return 1; +} + +static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, + void *parg) +{ + NDEF_SUPPORT *ndef_aux; + + if (!parg) + return 0; + + ndef_aux = *(NDEF_SUPPORT **)parg; + + OPENSSL_free(ndef_aux->derbuf); + + ndef_aux->derbuf = NULL; + *pbuf = NULL; + *plen = 0; + return 1; +} + +static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, + void *parg) +{ + NDEF_SUPPORT **pndef_aux = (NDEF_SUPPORT **)parg; + if (!ndef_prefix_free(b, pbuf, plen, parg)) + return 0; + OPENSSL_free(*pndef_aux); + *pndef_aux = NULL; + return 1; +} + +static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg) +{ + NDEF_SUPPORT *ndef_aux; + unsigned char *p; + int derlen; + const ASN1_AUX *aux; + ASN1_STREAM_ARG sarg; + + if (!parg) + return 0; + + ndef_aux = *(NDEF_SUPPORT **)parg; + + aux = ndef_aux->it->funcs; + + /* Finalize structures */ + sarg.ndef_bio = ndef_aux->ndef_bio; + sarg.out = ndef_aux->out; + sarg.boundary = ndef_aux->boundary; + if (aux->asn1_cb(ASN1_OP_STREAM_POST, + &ndef_aux->val, ndef_aux->it, &sarg) <= 0) + return 0; + + derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it); + if ((p = OPENSSL_malloc(derlen)) == NULL) { + ASN1err(ASN1_F_NDEF_SUFFIX, ERR_R_MALLOC_FAILURE); + return 0; + } + + ndef_aux->derbuf = p; + *pbuf = p; + derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it); + + if (!*ndef_aux->boundary) + return 0; + *pbuf = *ndef_aux->boundary; + *plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf); + + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/build.info new file mode 100644 index 000000000..d3e92c81a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/build.info @@ -0,0 +1,16 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + a_object.c a_bitstr.c a_utctm.c a_gentm.c a_time.c a_int.c a_octet.c \ + a_print.c a_type.c a_dup.c a_d2i_fp.c a_i2d_fp.c \ + a_utf8.c a_sign.c a_digest.c a_verify.c a_mbstr.c a_strex.c \ + x_algor.c x_val.c x_sig.c x_bignum.c \ + x_long.c x_int64.c x_info.c x_spki.c nsseq.c \ + d2i_pu.c d2i_pr.c i2d_pu.c i2d_pr.c\ + t_pkey.c t_spki.c t_bitst.c \ + tasn_new.c tasn_fre.c tasn_enc.c tasn_dec.c tasn_utl.c tasn_typ.c \ + tasn_prn.c tasn_scn.c ameth_lib.c \ + f_int.c f_string.c n_pkey.c \ + x_pkey.c bio_asn1.c bio_ndef.c asn_mime.c \ + asn1_gen.c asn1_par.c asn1_lib.c asn1_err.c a_strnid.c \ + evp_asn1.c asn_pack.c p5_pbe.c p5_pbev2.c p5_scrypt.c p8_pkey.c \ + asn_moid.c asn_mstbl.c asn1_item_list.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/charmap.h b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/charmap.h new file mode 100644 index 000000000..f15d72d73 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/charmap.h @@ -0,0 +1,34 @@ +/* + * WARNING: do not edit! + * Generated by crypto/asn1/charmap.pl + * + * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#define CHARTYPE_HOST_ANY 4096 +#define CHARTYPE_HOST_DOT 8192 +#define CHARTYPE_HOST_HYPHEN 16384 +#define CHARTYPE_HOST_WILD 32768 + +/* + * Mask of various character properties + */ + +static const unsigned short char_type[] = { + 1026, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 120, 0, 1, 40, + 0, 0, 0, 16, 1040, 1040, 33792, 25, 25, 16400, 8208, 16, + 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 16, 9, + 9, 16, 9, 16, 0, 4112, 4112, 4112, 4112, 4112, 4112, 4112, + 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, + 4112, 4112, 4112, 4112, 4112, 4112, 4112, 0, 1025, 0, 0, 0, + 0, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, + 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, + 4112, 4112, 4112, 0, 0, 0, 0, 2 +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/charmap.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/charmap.pl new file mode 100644 index 000000000..dadd8df77 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/charmap.pl @@ -0,0 +1,119 @@ +#! /usr/bin/env perl +# Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use strict; + +my ($i, @arr); + +# Set up an array with the type of ASCII characters +# Each set bit represents a character property. + +# RFC2253 character properties +my $RFC2253_ESC = 1; # Character escaped with \ +my $ESC_CTRL = 2; # Escaped control character +# These are used with RFC1779 quoting using " +my $NOESC_QUOTE = 8; # Not escaped if quoted +my $PSTRING_CHAR = 0x10; # Valid PrintableString character +my $RFC2253_FIRST_ESC = 0x20; # Escaped with \ if first character +my $RFC2253_LAST_ESC = 0x40; # Escaped with \ if last character +my $RFC2254_ESC = 0x400; # Character escaped \XX +my $HOST_ANY = 0x1000; # Valid hostname character anywhere in label +my $HOST_DOT = 0x2000; # Dot: hostname label separator +my $HOST_HYPHEN = 0x4000; # Hyphen: not valid at start or end. +my $HOST_WILD = 0x8000; # Wildcard character + +for($i = 0; $i < 128; $i++) { + # Set the RFC2253 escape characters (control) + $arr[$i] = 0; + if(($i < 32) || ($i > 126)) { + $arr[$i] |= $ESC_CTRL; + } + + # Some PrintableString characters + if( ( ( $i >= ord("a")) && ( $i <= ord("z")) ) + || ( ( $i >= ord("A")) && ( $i <= ord("Z")) ) + || ( ( $i >= ord("0")) && ( $i <= ord("9")) ) ) { + $arr[$i] |= $PSTRING_CHAR | $HOST_ANY; + } +} + +# Now setup the rest + +# Remaining RFC2253 escaped characters + +$arr[ord(" ")] |= $NOESC_QUOTE | $RFC2253_FIRST_ESC | $RFC2253_LAST_ESC; +$arr[ord("#")] |= $NOESC_QUOTE | $RFC2253_FIRST_ESC; + +$arr[ord(",")] |= $NOESC_QUOTE | $RFC2253_ESC; +$arr[ord("+")] |= $NOESC_QUOTE | $RFC2253_ESC; +$arr[ord("\"")] |= $RFC2253_ESC; +$arr[ord("\\")] |= $RFC2253_ESC; +$arr[ord("<")] |= $NOESC_QUOTE | $RFC2253_ESC; +$arr[ord(">")] |= $NOESC_QUOTE | $RFC2253_ESC; +$arr[ord(";")] |= $NOESC_QUOTE | $RFC2253_ESC; + +# Remaining RFC2254 characters + +$arr[0] |= $RFC2254_ESC; +$arr[ord("(")] |= $RFC2254_ESC; +$arr[ord(")")] |= $RFC2254_ESC; +$arr[ord("*")] |= $RFC2254_ESC | $HOST_WILD; +$arr[ord("\\")] |= $RFC2254_ESC; + +# Remaining PrintableString characters + +$arr[ord(" ")] |= $PSTRING_CHAR; +$arr[ord("'")] |= $PSTRING_CHAR; +$arr[ord("(")] |= $PSTRING_CHAR; +$arr[ord(")")] |= $PSTRING_CHAR; +$arr[ord("+")] |= $PSTRING_CHAR; +$arr[ord(",")] |= $PSTRING_CHAR; +$arr[ord("-")] |= $PSTRING_CHAR | $HOST_HYPHEN; +$arr[ord(".")] |= $PSTRING_CHAR | $HOST_DOT; +$arr[ord("/")] |= $PSTRING_CHAR; +$arr[ord(":")] |= $PSTRING_CHAR; +$arr[ord("=")] |= $PSTRING_CHAR; +$arr[ord("?")] |= $PSTRING_CHAR; + +# Now generate the C code + +# Output year depends on the year of the script. +my $YEAR = [localtime([stat($0)]->[9])]->[5] + 1900; +print < +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include +#include "internal/asn1_int.h" +#include "internal/evp_int.h" + +EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp, + long length) +{ + EVP_PKEY *ret; + const unsigned char *p = *pp; + + if ((a == NULL) || (*a == NULL)) { + if ((ret = EVP_PKEY_new()) == NULL) { + ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_EVP_LIB); + return NULL; + } + } else { + ret = *a; +#ifndef OPENSSL_NO_ENGINE + ENGINE_finish(ret->engine); + ret->engine = NULL; +#endif + } + + if (!EVP_PKEY_set_type(ret, type)) { + ASN1err(ASN1_F_D2I_PRIVATEKEY, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE); + goto err; + } + + if (!ret->ameth->old_priv_decode || + !ret->ameth->old_priv_decode(ret, &p, length)) { + if (ret->ameth->priv_decode) { + EVP_PKEY *tmp; + PKCS8_PRIV_KEY_INFO *p8 = NULL; + p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length); + if (!p8) + goto err; + tmp = EVP_PKCS82PKEY(p8); + PKCS8_PRIV_KEY_INFO_free(p8); + if (tmp == NULL) + goto err; + EVP_PKEY_free(ret); + ret = tmp; + } else { + ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_ASN1_LIB); + goto err; + } + } + *pp = p; + if (a != NULL) + (*a) = ret; + return ret; + err: + if (a == NULL || *a != ret) + EVP_PKEY_free(ret); + return NULL; +} + +/* + * This works like d2i_PrivateKey() except it automatically works out the + * type + */ + +EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp, + long length) +{ + STACK_OF(ASN1_TYPE) *inkey; + const unsigned char *p; + int keytype; + p = *pp; + /* + * Dirty trick: read in the ASN1 data into a STACK_OF(ASN1_TYPE): by + * analyzing it we can determine the passed structure: this assumes the + * input is surrounded by an ASN1 SEQUENCE. + */ + inkey = d2i_ASN1_SEQUENCE_ANY(NULL, &p, length); + p = *pp; + /* + * Since we only need to discern "traditional format" RSA and DSA keys we + * can just count the elements. + */ + if (sk_ASN1_TYPE_num(inkey) == 6) + keytype = EVP_PKEY_DSA; + else if (sk_ASN1_TYPE_num(inkey) == 4) + keytype = EVP_PKEY_EC; + else if (sk_ASN1_TYPE_num(inkey) == 3) { /* This seems to be PKCS8, not + * traditional format */ + PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length); + EVP_PKEY *ret; + + sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free); + if (!p8) { + ASN1err(ASN1_F_D2I_AUTOPRIVATEKEY, + ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE); + return NULL; + } + ret = EVP_PKCS82PKEY(p8); + PKCS8_PRIV_KEY_INFO_free(p8); + if (ret == NULL) + return NULL; + *pp = p; + if (a) { + *a = ret; + } + return ret; + } else + keytype = EVP_PKEY_RSA; + sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free); + return d2i_PrivateKey(keytype, a, pp, length); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/d2i_pu.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/d2i_pu.c new file mode 100644 index 000000000..7bc16c7bc --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/d2i_pu.c @@ -0,0 +1,77 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include +#include + +#include "internal/evp_int.h" + +EVP_PKEY *d2i_PublicKey(int type, EVP_PKEY **a, const unsigned char **pp, + long length) +{ + EVP_PKEY *ret; + + if ((a == NULL) || (*a == NULL)) { + if ((ret = EVP_PKEY_new()) == NULL) { + ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_EVP_LIB); + return NULL; + } + } else + ret = *a; + + if (type != EVP_PKEY_id(ret) && !EVP_PKEY_set_type(ret, type)) { + ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_EVP_LIB); + goto err; + } + + switch (EVP_PKEY_id(ret)) { +#ifndef OPENSSL_NO_RSA + case EVP_PKEY_RSA: + if ((ret->pkey.rsa = d2i_RSAPublicKey(NULL, pp, length)) == NULL) { + ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_ASN1_LIB); + goto err; + } + break; +#endif +#ifndef OPENSSL_NO_DSA + case EVP_PKEY_DSA: + /* TMP UGLY CAST */ + if (!d2i_DSAPublicKey(&ret->pkey.dsa, pp, length)) { + ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_ASN1_LIB); + goto err; + } + break; +#endif +#ifndef OPENSSL_NO_EC + case EVP_PKEY_EC: + if (!o2i_ECPublicKey(&ret->pkey.ec, pp, length)) { + ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_ASN1_LIB); + goto err; + } + break; +#endif + default: + ASN1err(ASN1_F_D2I_PUBLICKEY, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE); + goto err; + } + if (a != NULL) + (*a) = ret; + return ret; + err: + if (a == NULL || *a != ret) + EVP_PKEY_free(ret); + return NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/evp_asn1.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/evp_asn1.c new file mode 100644 index 000000000..895085a52 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/evp_asn1.c @@ -0,0 +1,115 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include + +int ASN1_TYPE_set_octetstring(ASN1_TYPE *a, unsigned char *data, int len) +{ + ASN1_STRING *os; + + if ((os = ASN1_OCTET_STRING_new()) == NULL) + return 0; + if (!ASN1_OCTET_STRING_set(os, data, len)) { + ASN1_OCTET_STRING_free(os); + return 0; + } + ASN1_TYPE_set(a, V_ASN1_OCTET_STRING, os); + return 1; +} + +/* int max_len: for returned value */ +int ASN1_TYPE_get_octetstring(const ASN1_TYPE *a, unsigned char *data, int max_len) +{ + int ret, num; + const unsigned char *p; + + if ((a->type != V_ASN1_OCTET_STRING) || (a->value.octet_string == NULL)) { + ASN1err(ASN1_F_ASN1_TYPE_GET_OCTETSTRING, ASN1_R_DATA_IS_WRONG); + return -1; + } + p = ASN1_STRING_get0_data(a->value.octet_string); + ret = ASN1_STRING_length(a->value.octet_string); + if (ret < max_len) + num = ret; + else + num = max_len; + memcpy(data, p, num); + return ret; +} + +typedef struct { + int32_t num; + ASN1_OCTET_STRING *oct; +} asn1_int_oct; + +ASN1_SEQUENCE(asn1_int_oct) = { + ASN1_EMBED(asn1_int_oct, num, INT32), + ASN1_SIMPLE(asn1_int_oct, oct, ASN1_OCTET_STRING) +} static_ASN1_SEQUENCE_END(asn1_int_oct) + +DECLARE_ASN1_ITEM(asn1_int_oct) + +int ASN1_TYPE_set_int_octetstring(ASN1_TYPE *a, long num, unsigned char *data, + int len) +{ + asn1_int_oct atmp; + ASN1_OCTET_STRING oct; + + atmp.num = num; + atmp.oct = &oct; + oct.data = data; + oct.type = V_ASN1_OCTET_STRING; + oct.length = len; + oct.flags = 0; + + if (ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(asn1_int_oct), &atmp, &a)) + return 1; + return 0; +} + +/* + * we return the actual length... + */ +/* int max_len: for returned value */ +int ASN1_TYPE_get_int_octetstring(const ASN1_TYPE *a, long *num, + unsigned char *data, int max_len) +{ + asn1_int_oct *atmp = NULL; + int ret = -1, n; + + if ((a->type != V_ASN1_SEQUENCE) || (a->value.sequence == NULL)) { + goto err; + } + + atmp = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(asn1_int_oct), a); + + if (atmp == NULL) + goto err; + + if (num != NULL) + *num = atmp->num; + + ret = ASN1_STRING_length(atmp->oct); + if (max_len > ret) + n = ret; + else + n = max_len; + + if (data != NULL) + memcpy(data, ASN1_STRING_get0_data(atmp->oct), n); + if (ret == -1) { + err: + ASN1err(ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING, ASN1_R_DATA_IS_WRONG); + } + M_ASN1_free_of(atmp, asn1_int_oct); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/f_int.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/f_int.c new file mode 100644 index 000000000..6d6bddc65 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/f_int.c @@ -0,0 +1,156 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/ctype.h" +#include "internal/cryptlib.h" +#include +#include + +int i2a_ASN1_INTEGER(BIO *bp, const ASN1_INTEGER *a) +{ + int i, n = 0; + static const char *h = "0123456789ABCDEF"; + char buf[2]; + + if (a == NULL) + return 0; + + if (a->type & V_ASN1_NEG) { + if (BIO_write(bp, "-", 1) != 1) + goto err; + n = 1; + } + + if (a->length == 0) { + if (BIO_write(bp, "00", 2) != 2) + goto err; + n += 2; + } else { + for (i = 0; i < a->length; i++) { + if ((i != 0) && (i % 35 == 0)) { + if (BIO_write(bp, "\\\n", 2) != 2) + goto err; + n += 2; + } + buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f]; + buf[1] = h[((unsigned char)a->data[i]) & 0x0f]; + if (BIO_write(bp, buf, 2) != 2) + goto err; + n += 2; + } + } + return n; + err: + return -1; +} + +int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size) +{ + int i, j, k, m, n, again, bufsize; + unsigned char *s = NULL, *sp; + unsigned char *bufp; + int num = 0, slen = 0, first = 1; + + bs->type = V_ASN1_INTEGER; + + bufsize = BIO_gets(bp, buf, size); + for (;;) { + if (bufsize < 1) + goto err; + i = bufsize; + if (buf[i - 1] == '\n') + buf[--i] = '\0'; + if (i == 0) + goto err; + if (buf[i - 1] == '\r') + buf[--i] = '\0'; + if (i == 0) + goto err; + again = (buf[i - 1] == '\\'); + + for (j = 0; j < i; j++) { + if (!ossl_isxdigit(buf[j])) + { + i = j; + break; + } + } + buf[i] = '\0'; + /* + * We have now cleared all the crap off the end of the line + */ + if (i < 2) + goto err; + + bufp = (unsigned char *)buf; + if (first) { + first = 0; + if ((bufp[0] == '0') && (bufp[1] == '0')) { + bufp += 2; + i -= 2; + } + } + k = 0; + i -= again; + if (i % 2 != 0) { + ASN1err(ASN1_F_A2I_ASN1_INTEGER, ASN1_R_ODD_NUMBER_OF_CHARS); + OPENSSL_free(s); + return 0; + } + i /= 2; + if (num + i > slen) { + sp = OPENSSL_clear_realloc(s, slen, num + i * 2); + if (sp == NULL) { + ASN1err(ASN1_F_A2I_ASN1_INTEGER, ERR_R_MALLOC_FAILURE); + OPENSSL_free(s); + return 0; + } + s = sp; + slen = num + i * 2; + } + for (j = 0; j < i; j++, k += 2) { + for (n = 0; n < 2; n++) { + m = OPENSSL_hexchar2int(bufp[k + n]); + if (m < 0) { + ASN1err(ASN1_F_A2I_ASN1_INTEGER, + ASN1_R_NON_HEX_CHARACTERS); + goto err; + } + s[num + j] <<= 4; + s[num + j] |= m; + } + } + num += i; + if (again) + bufsize = BIO_gets(bp, buf, size); + else + break; + } + bs->length = num; + bs->data = s; + return 1; + err: + ASN1err(ASN1_F_A2I_ASN1_INTEGER, ASN1_R_SHORT_LINE); + OPENSSL_free(s); + return 0; +} + +int i2a_ASN1_ENUMERATED(BIO *bp, const ASN1_ENUMERATED *a) +{ + return i2a_ASN1_INTEGER(bp, a); +} + +int a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size) +{ + int rv = a2i_ASN1_INTEGER(bp, bs, buf, size); + if (rv == 1) + bs->type = V_ASN1_INTEGER | (bs->type & V_ASN1_NEG); + return rv; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/f_string.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/f_string.c new file mode 100644 index 000000000..f893489a6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/f_string.c @@ -0,0 +1,136 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/ctype.h" +#include "internal/cryptlib.h" +#include +#include + +int i2a_ASN1_STRING(BIO *bp, const ASN1_STRING *a, int type) +{ + int i, n = 0; + static const char *h = "0123456789ABCDEF"; + char buf[2]; + + if (a == NULL) + return 0; + + if (a->length == 0) { + if (BIO_write(bp, "0", 1) != 1) + goto err; + n = 1; + } else { + for (i = 0; i < a->length; i++) { + if ((i != 0) && (i % 35 == 0)) { + if (BIO_write(bp, "\\\n", 2) != 2) + goto err; + n += 2; + } + buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f]; + buf[1] = h[((unsigned char)a->data[i]) & 0x0f]; + if (BIO_write(bp, buf, 2) != 2) + goto err; + n += 2; + } + } + return n; + err: + return -1; +} + +int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size) +{ + int i, j, k, m, n, again, bufsize; + unsigned char *s = NULL, *sp; + unsigned char *bufp; + int num = 0, slen = 0, first = 1; + + bufsize = BIO_gets(bp, buf, size); + for (;;) { + if (bufsize < 1) { + if (first) + break; + else + goto err; + } + first = 0; + + i = bufsize; + if (buf[i - 1] == '\n') + buf[--i] = '\0'; + if (i == 0) + goto err; + if (buf[i - 1] == '\r') + buf[--i] = '\0'; + if (i == 0) + goto err; + again = (buf[i - 1] == '\\'); + + for (j = i - 1; j > 0; j--) { + if (!ossl_isxdigit(buf[j])) { + i = j; + break; + } + } + buf[i] = '\0'; + /* + * We have now cleared all the crap off the end of the line + */ + if (i < 2) + goto err; + + bufp = (unsigned char *)buf; + + k = 0; + i -= again; + if (i % 2 != 0) { + ASN1err(ASN1_F_A2I_ASN1_STRING, ASN1_R_ODD_NUMBER_OF_CHARS); + OPENSSL_free(s); + return 0; + } + i /= 2; + if (num + i > slen) { + sp = OPENSSL_realloc(s, (unsigned int)num + i * 2); + if (sp == NULL) { + ASN1err(ASN1_F_A2I_ASN1_STRING, ERR_R_MALLOC_FAILURE); + OPENSSL_free(s); + return 0; + } + s = sp; + slen = num + i * 2; + } + for (j = 0; j < i; j++, k += 2) { + for (n = 0; n < 2; n++) { + m = OPENSSL_hexchar2int(bufp[k + n]); + if (m < 0) { + ASN1err(ASN1_F_A2I_ASN1_STRING, + ASN1_R_NON_HEX_CHARACTERS); + OPENSSL_free(s); + return 0; + } + s[num + j] <<= 4; + s[num + j] |= m; + } + } + num += i; + if (again) + bufsize = BIO_gets(bp, buf, size); + else + break; + } + bs->length = num; + bs->data = s; + return 1; + + err: + ASN1err(ASN1_F_A2I_ASN1_STRING, ASN1_R_SHORT_LINE); + OPENSSL_free(s); + return 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/i2d_pr.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/i2d_pr.c new file mode 100644 index 000000000..445b0c842 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/i2d_pr.c @@ -0,0 +1,33 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include "internal/asn1_int.h" +#include "internal/evp_int.h" + +int i2d_PrivateKey(EVP_PKEY *a, unsigned char **pp) +{ + if (a->ameth && a->ameth->old_priv_encode) { + return a->ameth->old_priv_encode(a, pp); + } + if (a->ameth && a->ameth->priv_encode) { + PKCS8_PRIV_KEY_INFO *p8 = EVP_PKEY2PKCS8(a); + int ret = 0; + if (p8 != NULL) { + ret = i2d_PKCS8_PRIV_KEY_INFO(p8, pp); + PKCS8_PRIV_KEY_INFO_free(p8); + } + return ret; + } + ASN1err(ASN1_F_I2D_PRIVATEKEY, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE); + return -1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/i2d_pu.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/i2d_pu.c new file mode 100644 index 000000000..8986c43cb --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/i2d_pu.c @@ -0,0 +1,38 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include + +int i2d_PublicKey(EVP_PKEY *a, unsigned char **pp) +{ + switch (EVP_PKEY_id(a)) { +#ifndef OPENSSL_NO_RSA + case EVP_PKEY_RSA: + return i2d_RSAPublicKey(EVP_PKEY_get0_RSA(a), pp); +#endif +#ifndef OPENSSL_NO_DSA + case EVP_PKEY_DSA: + return i2d_DSAPublicKey(EVP_PKEY_get0_DSA(a), pp); +#endif +#ifndef OPENSSL_NO_EC + case EVP_PKEY_EC: + return i2o_ECPublicKey(EVP_PKEY_get0_EC_KEY(a), pp); +#endif + default: + ASN1err(ASN1_F_I2D_PUBLICKEY, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE); + return -1; + } +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/n_pkey.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/n_pkey.c new file mode 100644 index 000000000..d1fb8a146 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/n_pkey.c @@ -0,0 +1,62 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "openssl/opensslconf.h" +#ifdef OPENSSL_NO_RSA +NON_EMPTY_TRANSLATION_UNIT +#else + +# include "internal/cryptlib.h" +# include +# include +# include +# include +# include +# include + +# ifndef OPENSSL_NO_RC4 + +typedef struct netscape_pkey_st { + int32_t version; + X509_ALGOR *algor; + ASN1_OCTET_STRING *private_key; +} NETSCAPE_PKEY; + +typedef struct netscape_encrypted_pkey_st { + ASN1_OCTET_STRING *os; + /* + * This is the same structure as DigestInfo so use it: although this + * isn't really anything to do with digests. + */ + X509_SIG *enckey; +} NETSCAPE_ENCRYPTED_PKEY; + + +ASN1_BROKEN_SEQUENCE(NETSCAPE_ENCRYPTED_PKEY) = { + ASN1_SIMPLE(NETSCAPE_ENCRYPTED_PKEY, os, ASN1_OCTET_STRING), + ASN1_SIMPLE(NETSCAPE_ENCRYPTED_PKEY, enckey, X509_SIG) +} static_ASN1_BROKEN_SEQUENCE_END(NETSCAPE_ENCRYPTED_PKEY) + +DECLARE_ASN1_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY) +DECLARE_ASN1_ENCODE_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY,NETSCAPE_ENCRYPTED_PKEY) +IMPLEMENT_ASN1_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY) + +ASN1_SEQUENCE(NETSCAPE_PKEY) = { + ASN1_EMBED(NETSCAPE_PKEY, version, INT32), + ASN1_SIMPLE(NETSCAPE_PKEY, algor, X509_ALGOR), + ASN1_SIMPLE(NETSCAPE_PKEY, private_key, ASN1_OCTET_STRING) +} static_ASN1_SEQUENCE_END(NETSCAPE_PKEY) + +DECLARE_ASN1_FUNCTIONS_const(NETSCAPE_PKEY) +DECLARE_ASN1_ENCODE_FUNCTIONS_const(NETSCAPE_PKEY,NETSCAPE_PKEY) +IMPLEMENT_ASN1_FUNCTIONS_const(NETSCAPE_PKEY) + +# endif /* OPENSSL_NO_RC4 */ + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/nsseq.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/nsseq.c new file mode 100644 index 000000000..c7baf40d3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/nsseq.c @@ -0,0 +1,34 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include + +static int nsseq_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + if (operation == ASN1_OP_NEW_POST) { + NETSCAPE_CERT_SEQUENCE *nsseq; + nsseq = (NETSCAPE_CERT_SEQUENCE *)*pval; + nsseq->type = OBJ_nid2obj(NID_netscape_cert_sequence); + } + return 1; +} + +/* Netscape certificate sequence structure */ + +ASN1_SEQUENCE_cb(NETSCAPE_CERT_SEQUENCE, nsseq_cb) = { + ASN1_SIMPLE(NETSCAPE_CERT_SEQUENCE, type, ASN1_OBJECT), + ASN1_EXP_SEQUENCE_OF_OPT(NETSCAPE_CERT_SEQUENCE, certs, X509, 0) +} ASN1_SEQUENCE_END_cb(NETSCAPE_CERT_SEQUENCE, NETSCAPE_CERT_SEQUENCE) + +IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_CERT_SEQUENCE) diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/p5_pbe.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/p5_pbe.c new file mode 100644 index 000000000..ab7e16898 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/p5_pbe.c @@ -0,0 +1,96 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include + +/* PKCS#5 password based encryption structure */ + +ASN1_SEQUENCE(PBEPARAM) = { + ASN1_SIMPLE(PBEPARAM, salt, ASN1_OCTET_STRING), + ASN1_SIMPLE(PBEPARAM, iter, ASN1_INTEGER) +} ASN1_SEQUENCE_END(PBEPARAM) + +IMPLEMENT_ASN1_FUNCTIONS(PBEPARAM) + +/* Set an algorithm identifier for a PKCS#5 PBE algorithm */ + +int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter, + const unsigned char *salt, int saltlen) +{ + PBEPARAM *pbe = NULL; + ASN1_STRING *pbe_str = NULL; + unsigned char *sstr = NULL; + + pbe = PBEPARAM_new(); + if (pbe == NULL) { + ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR, ERR_R_MALLOC_FAILURE); + goto err; + } + if (iter <= 0) + iter = PKCS5_DEFAULT_ITER; + if (!ASN1_INTEGER_set(pbe->iter, iter)) { + ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!saltlen) + saltlen = PKCS5_SALT_LEN; + + sstr = OPENSSL_malloc(saltlen); + if (sstr == NULL) { + ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR, ERR_R_MALLOC_FAILURE); + goto err; + } + if (salt) + memcpy(sstr, salt, saltlen); + else if (RAND_bytes(sstr, saltlen) <= 0) + goto err; + + ASN1_STRING_set0(pbe->salt, sstr, saltlen); + sstr = NULL; + + if (!ASN1_item_pack(pbe, ASN1_ITEM_rptr(PBEPARAM), &pbe_str)) { + ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR, ERR_R_MALLOC_FAILURE); + goto err; + } + + PBEPARAM_free(pbe); + pbe = NULL; + + if (X509_ALGOR_set0(algor, OBJ_nid2obj(alg), V_ASN1_SEQUENCE, pbe_str)) + return 1; + + err: + OPENSSL_free(sstr); + PBEPARAM_free(pbe); + ASN1_STRING_free(pbe_str); + return 0; +} + +/* Return an algorithm identifier for a PKCS#5 PBE algorithm */ + +X509_ALGOR *PKCS5_pbe_set(int alg, int iter, + const unsigned char *salt, int saltlen) +{ + X509_ALGOR *ret; + ret = X509_ALGOR_new(); + if (ret == NULL) { + ASN1err(ASN1_F_PKCS5_PBE_SET, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (PKCS5_pbe_set0_algor(ret, alg, iter, salt, saltlen)) + return ret; + + X509_ALGOR_free(ret); + return NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/p5_pbev2.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/p5_pbev2.c new file mode 100644 index 000000000..f91ba08f1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/p5_pbev2.c @@ -0,0 +1,221 @@ +/* + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include + +/* PKCS#5 v2.0 password based encryption structures */ + +ASN1_SEQUENCE(PBE2PARAM) = { + ASN1_SIMPLE(PBE2PARAM, keyfunc, X509_ALGOR), + ASN1_SIMPLE(PBE2PARAM, encryption, X509_ALGOR) +} ASN1_SEQUENCE_END(PBE2PARAM) + +IMPLEMENT_ASN1_FUNCTIONS(PBE2PARAM) + +ASN1_SEQUENCE(PBKDF2PARAM) = { + ASN1_SIMPLE(PBKDF2PARAM, salt, ASN1_ANY), + ASN1_SIMPLE(PBKDF2PARAM, iter, ASN1_INTEGER), + ASN1_OPT(PBKDF2PARAM, keylength, ASN1_INTEGER), + ASN1_OPT(PBKDF2PARAM, prf, X509_ALGOR) +} ASN1_SEQUENCE_END(PBKDF2PARAM) + +IMPLEMENT_ASN1_FUNCTIONS(PBKDF2PARAM) + +/* + * Return an algorithm identifier for a PKCS#5 v2.0 PBE algorithm: yes I know + * this is horrible! Extended version to allow application supplied PRF NID + * and IV. + */ + +X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter, + unsigned char *salt, int saltlen, + unsigned char *aiv, int prf_nid) +{ + X509_ALGOR *scheme = NULL, *ret = NULL; + int alg_nid, keylen; + EVP_CIPHER_CTX *ctx = NULL; + unsigned char iv[EVP_MAX_IV_LENGTH]; + PBE2PARAM *pbe2 = NULL; + + alg_nid = EVP_CIPHER_type(cipher); + if (alg_nid == NID_undef) { + ASN1err(ASN1_F_PKCS5_PBE2_SET_IV, + ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER); + goto err; + } + + if ((pbe2 = PBE2PARAM_new()) == NULL) + goto merr; + + /* Setup the AlgorithmIdentifier for the encryption scheme */ + scheme = pbe2->encryption; + scheme->algorithm = OBJ_nid2obj(alg_nid); + if ((scheme->parameter = ASN1_TYPE_new()) == NULL) + goto merr; + + /* Create random IV */ + if (EVP_CIPHER_iv_length(cipher)) { + if (aiv) + memcpy(iv, aiv, EVP_CIPHER_iv_length(cipher)); + else if (RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)) <= 0) + goto err; + } + + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) + goto merr; + + /* Dummy cipherinit to just setup the IV, and PRF */ + if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, iv, 0)) + goto err; + if (EVP_CIPHER_param_to_asn1(ctx, scheme->parameter) <= 0) { + ASN1err(ASN1_F_PKCS5_PBE2_SET_IV, ASN1_R_ERROR_SETTING_CIPHER_PARAMS); + goto err; + } + /* + * If prf NID unspecified see if cipher has a preference. An error is OK + * here: just means use default PRF. + */ + if ((prf_nid == -1) && + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_PBE_PRF_NID, 0, &prf_nid) <= 0) { + ERR_clear_error(); + prf_nid = NID_hmacWithSHA256; + } + EVP_CIPHER_CTX_free(ctx); + ctx = NULL; + + /* If its RC2 then we'd better setup the key length */ + + if (alg_nid == NID_rc2_cbc) + keylen = EVP_CIPHER_key_length(cipher); + else + keylen = -1; + + /* Setup keyfunc */ + + X509_ALGOR_free(pbe2->keyfunc); + + pbe2->keyfunc = PKCS5_pbkdf2_set(iter, salt, saltlen, prf_nid, keylen); + + if (!pbe2->keyfunc) + goto merr; + + /* Now set up top level AlgorithmIdentifier */ + + if ((ret = X509_ALGOR_new()) == NULL) + goto merr; + + ret->algorithm = OBJ_nid2obj(NID_pbes2); + + /* Encode PBE2PARAM into parameter */ + + if (!ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(PBE2PARAM), pbe2, + &ret->parameter)) + goto merr; + + PBE2PARAM_free(pbe2); + pbe2 = NULL; + + return ret; + + merr: + ASN1err(ASN1_F_PKCS5_PBE2_SET_IV, ERR_R_MALLOC_FAILURE); + + err: + EVP_CIPHER_CTX_free(ctx); + PBE2PARAM_free(pbe2); + /* Note 'scheme' is freed as part of pbe2 */ + X509_ALGOR_free(ret); + + return NULL; +} + +X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter, + unsigned char *salt, int saltlen) +{ + return PKCS5_pbe2_set_iv(cipher, iter, salt, saltlen, NULL, -1); +} + +X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen, + int prf_nid, int keylen) +{ + X509_ALGOR *keyfunc = NULL; + PBKDF2PARAM *kdf = NULL; + ASN1_OCTET_STRING *osalt = NULL; + + if ((kdf = PBKDF2PARAM_new()) == NULL) + goto merr; + if ((osalt = ASN1_OCTET_STRING_new()) == NULL) + goto merr; + + kdf->salt->value.octet_string = osalt; + kdf->salt->type = V_ASN1_OCTET_STRING; + + if (saltlen == 0) + saltlen = PKCS5_SALT_LEN; + if ((osalt->data = OPENSSL_malloc(saltlen)) == NULL) + goto merr; + + osalt->length = saltlen; + + if (salt) + memcpy(osalt->data, salt, saltlen); + else if (RAND_bytes(osalt->data, saltlen) <= 0) + goto merr; + + if (iter <= 0) + iter = PKCS5_DEFAULT_ITER; + + if (!ASN1_INTEGER_set(kdf->iter, iter)) + goto merr; + + /* If have a key len set it up */ + + if (keylen > 0) { + if ((kdf->keylength = ASN1_INTEGER_new()) == NULL) + goto merr; + if (!ASN1_INTEGER_set(kdf->keylength, keylen)) + goto merr; + } + + /* prf can stay NULL if we are using hmacWithSHA1 */ + if (prf_nid > 0 && prf_nid != NID_hmacWithSHA1) { + kdf->prf = X509_ALGOR_new(); + if (kdf->prf == NULL) + goto merr; + X509_ALGOR_set0(kdf->prf, OBJ_nid2obj(prf_nid), V_ASN1_NULL, NULL); + } + + /* Finally setup the keyfunc structure */ + + keyfunc = X509_ALGOR_new(); + if (keyfunc == NULL) + goto merr; + + keyfunc->algorithm = OBJ_nid2obj(NID_id_pbkdf2); + + /* Encode PBKDF2PARAM into parameter of pbe2 */ + + if (!ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(PBKDF2PARAM), kdf, + &keyfunc->parameter)) + goto merr; + + PBKDF2PARAM_free(kdf); + return keyfunc; + + merr: + ASN1err(ASN1_F_PKCS5_PBKDF2_SET, ERR_R_MALLOC_FAILURE); + PBKDF2PARAM_free(kdf); + X509_ALGOR_free(keyfunc); + return NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/p5_scrypt.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/p5_scrypt.c new file mode 100644 index 000000000..1491d96ec --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/p5_scrypt.c @@ -0,0 +1,274 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include + +#ifndef OPENSSL_NO_SCRYPT +/* PKCS#5 scrypt password based encryption structures */ + +ASN1_SEQUENCE(SCRYPT_PARAMS) = { + ASN1_SIMPLE(SCRYPT_PARAMS, salt, ASN1_OCTET_STRING), + ASN1_SIMPLE(SCRYPT_PARAMS, costParameter, ASN1_INTEGER), + ASN1_SIMPLE(SCRYPT_PARAMS, blockSize, ASN1_INTEGER), + ASN1_SIMPLE(SCRYPT_PARAMS, parallelizationParameter, ASN1_INTEGER), + ASN1_OPT(SCRYPT_PARAMS, keyLength, ASN1_INTEGER), +} ASN1_SEQUENCE_END(SCRYPT_PARAMS) + +IMPLEMENT_ASN1_FUNCTIONS(SCRYPT_PARAMS) + +static X509_ALGOR *pkcs5_scrypt_set(const unsigned char *salt, size_t saltlen, + size_t keylen, uint64_t N, uint64_t r, + uint64_t p); + +/* + * Return an algorithm identifier for a PKCS#5 v2.0 PBE algorithm using scrypt + */ + +X509_ALGOR *PKCS5_pbe2_set_scrypt(const EVP_CIPHER *cipher, + const unsigned char *salt, int saltlen, + unsigned char *aiv, uint64_t N, uint64_t r, + uint64_t p) +{ + X509_ALGOR *scheme = NULL, *ret = NULL; + int alg_nid; + size_t keylen = 0; + EVP_CIPHER_CTX *ctx = NULL; + unsigned char iv[EVP_MAX_IV_LENGTH]; + PBE2PARAM *pbe2 = NULL; + + if (!cipher) { + ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT, ERR_R_PASSED_NULL_PARAMETER); + goto err; + } + + if (EVP_PBE_scrypt(NULL, 0, NULL, 0, N, r, p, 0, NULL, 0) == 0) { + ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT, + ASN1_R_INVALID_SCRYPT_PARAMETERS); + goto err; + } + + alg_nid = EVP_CIPHER_type(cipher); + if (alg_nid == NID_undef) { + ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT, + ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER); + goto err; + } + + pbe2 = PBE2PARAM_new(); + if (pbe2 == NULL) + goto merr; + + /* Setup the AlgorithmIdentifier for the encryption scheme */ + scheme = pbe2->encryption; + + scheme->algorithm = OBJ_nid2obj(alg_nid); + scheme->parameter = ASN1_TYPE_new(); + if (scheme->parameter == NULL) + goto merr; + + /* Create random IV */ + if (EVP_CIPHER_iv_length(cipher)) { + if (aiv) + memcpy(iv, aiv, EVP_CIPHER_iv_length(cipher)); + else if (RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)) <= 0) + goto err; + } + + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) + goto merr; + + /* Dummy cipherinit to just setup the IV */ + if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, iv, 0) == 0) + goto err; + if (EVP_CIPHER_param_to_asn1(ctx, scheme->parameter) <= 0) { + ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT, + ASN1_R_ERROR_SETTING_CIPHER_PARAMS); + goto err; + } + EVP_CIPHER_CTX_free(ctx); + ctx = NULL; + + /* If its RC2 then we'd better setup the key length */ + + if (alg_nid == NID_rc2_cbc) + keylen = EVP_CIPHER_key_length(cipher); + + /* Setup keyfunc */ + + X509_ALGOR_free(pbe2->keyfunc); + + pbe2->keyfunc = pkcs5_scrypt_set(salt, saltlen, keylen, N, r, p); + + if (pbe2->keyfunc == NULL) + goto merr; + + /* Now set up top level AlgorithmIdentifier */ + + ret = X509_ALGOR_new(); + if (ret == NULL) + goto merr; + + ret->algorithm = OBJ_nid2obj(NID_pbes2); + + /* Encode PBE2PARAM into parameter */ + + if (ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(PBE2PARAM), pbe2, + &ret->parameter) == NULL) + goto merr; + + PBE2PARAM_free(pbe2); + pbe2 = NULL; + + return ret; + + merr: + ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT, ERR_R_MALLOC_FAILURE); + + err: + PBE2PARAM_free(pbe2); + X509_ALGOR_free(ret); + EVP_CIPHER_CTX_free(ctx); + + return NULL; +} + +static X509_ALGOR *pkcs5_scrypt_set(const unsigned char *salt, size_t saltlen, + size_t keylen, uint64_t N, uint64_t r, + uint64_t p) +{ + X509_ALGOR *keyfunc = NULL; + SCRYPT_PARAMS *sparam = SCRYPT_PARAMS_new(); + + if (sparam == NULL) + goto merr; + + if (!saltlen) + saltlen = PKCS5_SALT_LEN; + + /* This will either copy salt or grow the buffer */ + if (ASN1_STRING_set(sparam->salt, salt, saltlen) == 0) + goto merr; + + if (salt == NULL && RAND_bytes(sparam->salt->data, saltlen) <= 0) + goto err; + + if (ASN1_INTEGER_set_uint64(sparam->costParameter, N) == 0) + goto merr; + + if (ASN1_INTEGER_set_uint64(sparam->blockSize, r) == 0) + goto merr; + + if (ASN1_INTEGER_set_uint64(sparam->parallelizationParameter, p) == 0) + goto merr; + + /* If have a key len set it up */ + + if (keylen > 0) { + sparam->keyLength = ASN1_INTEGER_new(); + if (sparam->keyLength == NULL) + goto merr; + if (ASN1_INTEGER_set_int64(sparam->keyLength, keylen) == 0) + goto merr; + } + + /* Finally setup the keyfunc structure */ + + keyfunc = X509_ALGOR_new(); + if (keyfunc == NULL) + goto merr; + + keyfunc->algorithm = OBJ_nid2obj(NID_id_scrypt); + + /* Encode SCRYPT_PARAMS into parameter of pbe2 */ + + if (ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(SCRYPT_PARAMS), sparam, + &keyfunc->parameter) == NULL) + goto merr; + + SCRYPT_PARAMS_free(sparam); + return keyfunc; + + merr: + ASN1err(ASN1_F_PKCS5_SCRYPT_SET, ERR_R_MALLOC_FAILURE); + err: + SCRYPT_PARAMS_free(sparam); + X509_ALGOR_free(keyfunc); + return NULL; +} + +int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, + int passlen, ASN1_TYPE *param, + const EVP_CIPHER *c, const EVP_MD *md, int en_de) +{ + unsigned char *salt, key[EVP_MAX_KEY_LENGTH]; + uint64_t p, r, N; + size_t saltlen; + size_t keylen = 0; + int rv = 0; + SCRYPT_PARAMS *sparam = NULL; + + if (EVP_CIPHER_CTX_cipher(ctx) == NULL) { + EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, EVP_R_NO_CIPHER_SET); + goto err; + } + + /* Decode parameter */ + + sparam = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(SCRYPT_PARAMS), param); + + if (sparam == NULL) { + EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, EVP_R_DECODE_ERROR); + goto err; + } + + keylen = EVP_CIPHER_CTX_key_length(ctx); + + /* Now check the parameters of sparam */ + + if (sparam->keyLength) { + uint64_t spkeylen; + if ((ASN1_INTEGER_get_uint64(&spkeylen, sparam->keyLength) == 0) + || (spkeylen != keylen)) { + EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, + EVP_R_UNSUPPORTED_KEYLENGTH); + goto err; + } + } + /* Check all parameters fit in uint64_t and are acceptable to scrypt */ + if (ASN1_INTEGER_get_uint64(&N, sparam->costParameter) == 0 + || ASN1_INTEGER_get_uint64(&r, sparam->blockSize) == 0 + || ASN1_INTEGER_get_uint64(&p, sparam->parallelizationParameter) == 0 + || EVP_PBE_scrypt(NULL, 0, NULL, 0, N, r, p, 0, NULL, 0) == 0) { + EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, + EVP_R_ILLEGAL_SCRYPT_PARAMETERS); + goto err; + } + + /* it seems that its all OK */ + + salt = sparam->salt->data; + saltlen = sparam->salt->length; + if (EVP_PBE_scrypt(pass, passlen, salt, saltlen, N, r, p, 0, key, keylen) + == 0) + goto err; + rv = EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, en_de); + err: + if (keylen) + OPENSSL_cleanse(key, keylen); + SCRYPT_PARAMS_free(sparam); + return rv; +} +#endif /* OPENSSL_NO_SCRYPT */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/p8_pkey.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/p8_pkey.c new file mode 100644 index 000000000..dbee827e0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/p8_pkey.c @@ -0,0 +1,80 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include "internal/x509_int.h" + +/* Minor tweak to operation: zero private key data */ +static int pkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + /* Since the structure must still be valid use ASN1_OP_FREE_PRE */ + if (operation == ASN1_OP_FREE_PRE) { + PKCS8_PRIV_KEY_INFO *key = (PKCS8_PRIV_KEY_INFO *)*pval; + if (key->pkey) + OPENSSL_cleanse(key->pkey->data, key->pkey->length); + } + return 1; +} + +ASN1_SEQUENCE_cb(PKCS8_PRIV_KEY_INFO, pkey_cb) = { + ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, version, ASN1_INTEGER), + ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkeyalg, X509_ALGOR), + ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkey, ASN1_OCTET_STRING), + ASN1_IMP_SET_OF_OPT(PKCS8_PRIV_KEY_INFO, attributes, X509_ATTRIBUTE, 0) +} ASN1_SEQUENCE_END_cb(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO) + +int PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj, + int version, + int ptype, void *pval, unsigned char *penc, int penclen) +{ + if (version >= 0) { + if (!ASN1_INTEGER_set(priv->version, version)) + return 0; + } + if (!X509_ALGOR_set0(priv->pkeyalg, aobj, ptype, pval)) + return 0; + if (penc) + ASN1_STRING_set0(priv->pkey, penc, penclen); + return 1; +} + +int PKCS8_pkey_get0(const ASN1_OBJECT **ppkalg, + const unsigned char **pk, int *ppklen, + const X509_ALGOR **pa, const PKCS8_PRIV_KEY_INFO *p8) +{ + if (ppkalg) + *ppkalg = p8->pkeyalg->algorithm; + if (pk) { + *pk = ASN1_STRING_get0_data(p8->pkey); + *ppklen = ASN1_STRING_length(p8->pkey); + } + if (pa) + *pa = p8->pkeyalg; + return 1; +} + +const STACK_OF(X509_ATTRIBUTE) * +PKCS8_pkey_get0_attrs(const PKCS8_PRIV_KEY_INFO *p8) +{ + return p8->attributes; +} + +int PKCS8_pkey_add1_attr_by_NID(PKCS8_PRIV_KEY_INFO *p8, int nid, int type, + const unsigned char *bytes, int len) +{ + if (X509at_add1_attr_by_NID(&p8->attributes, nid, type, bytes, len) != NULL) + return 1; + return 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/standard_methods.h b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/standard_methods.h new file mode 100644 index 000000000..e74de55ff --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/standard_methods.h @@ -0,0 +1,61 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This table MUST be kept in ascending order of the NID each method + * represents (corresponding to the pkey_id field) as OBJ_bsearch + * is used to search it. + */ +static const EVP_PKEY_ASN1_METHOD *standard_methods[] = { +#ifndef OPENSSL_NO_RSA + &rsa_asn1_meths[0], + &rsa_asn1_meths[1], +#endif +#ifndef OPENSSL_NO_DH + &dh_asn1_meth, +#endif +#ifndef OPENSSL_NO_DSA + &dsa_asn1_meths[0], + &dsa_asn1_meths[1], + &dsa_asn1_meths[2], + &dsa_asn1_meths[3], + &dsa_asn1_meths[4], +#endif +#ifndef OPENSSL_NO_EC + &eckey_asn1_meth, +#endif + &hmac_asn1_meth, +#ifndef OPENSSL_NO_CMAC + &cmac_asn1_meth, +#endif +#ifndef OPENSSL_NO_RSA + &rsa_pss_asn1_meth, +#endif +#ifndef OPENSSL_NO_DH + &dhx_asn1_meth, +#endif +#ifndef OPENSSL_NO_EC + &ecx25519_asn1_meth, + &ecx448_asn1_meth, +#endif +#ifndef OPENSSL_NO_POLY1305 + &poly1305_asn1_meth, +#endif +#ifndef OPENSSL_NO_SIPHASH + &siphash_asn1_meth, +#endif +#ifndef OPENSSL_NO_EC + &ed25519_asn1_meth, + &ed448_asn1_meth, +#endif +#ifndef OPENSSL_NO_SM2 + &sm2_asn1_meth, +#endif +}; + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/t_bitst.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/t_bitst.c new file mode 100644 index 000000000..c0aeca4c7 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/t_bitst.c @@ -0,0 +1,56 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include + +int ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs, + BIT_STRING_BITNAME *tbl, int indent) +{ + BIT_STRING_BITNAME *bnam; + char first = 1; + BIO_printf(out, "%*s", indent, ""); + for (bnam = tbl; bnam->lname; bnam++) { + if (ASN1_BIT_STRING_get_bit(bs, bnam->bitnum)) { + if (!first) + BIO_puts(out, ", "); + BIO_puts(out, bnam->lname); + first = 0; + } + } + BIO_puts(out, "\n"); + return 1; +} + +int ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, const char *name, int value, + BIT_STRING_BITNAME *tbl) +{ + int bitnum; + bitnum = ASN1_BIT_STRING_num_asc(name, tbl); + if (bitnum < 0) + return 0; + if (bs) { + if (!ASN1_BIT_STRING_set_bit(bs, bitnum, value)) + return 0; + } + return 1; +} + +int ASN1_BIT_STRING_num_asc(const char *name, BIT_STRING_BITNAME *tbl) +{ + BIT_STRING_BITNAME *bnam; + for (bnam = tbl; bnam->lname; bnam++) { + if ((strcmp(bnam->sname, name) == 0) + || (strcmp(bnam->lname, name) == 0)) + return bnam->bitnum; + } + return -1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/t_pkey.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/t_pkey.c new file mode 100644 index 000000000..3b2c9df89 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/t_pkey.c @@ -0,0 +1,93 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include "internal/bn_int.h" + +/* Number of octets per line */ +#define ASN1_BUF_PRINT_WIDTH 15 +/* Maximum indent */ +#define ASN1_PRINT_MAX_INDENT 128 + +int ASN1_buf_print(BIO *bp, const unsigned char *buf, size_t buflen, int indent) +{ + size_t i; + + for (i = 0; i < buflen; i++) { + if ((i % ASN1_BUF_PRINT_WIDTH) == 0) { + if (i > 0 && BIO_puts(bp, "\n") <= 0) + return 0; + if (!BIO_indent(bp, indent, ASN1_PRINT_MAX_INDENT)) + return 0; + } + /* + * Use colon separators for each octet for compatibility as + * this function is used to print out key components. + */ + if (BIO_printf(bp, "%02x%s", buf[i], + (i == buflen - 1) ? "" : ":") <= 0) + return 0; + } + if (BIO_write(bp, "\n", 1) <= 0) + return 0; + return 1; +} + +int ASN1_bn_print(BIO *bp, const char *number, const BIGNUM *num, + unsigned char *ign, int indent) +{ + int n, rv = 0; + const char *neg; + unsigned char *buf = NULL, *tmp = NULL; + int buflen; + + if (num == NULL) + return 1; + neg = BN_is_negative(num) ? "-" : ""; + if (!BIO_indent(bp, indent, ASN1_PRINT_MAX_INDENT)) + return 0; + if (BN_is_zero(num)) { + if (BIO_printf(bp, "%s 0\n", number) <= 0) + return 0; + return 1; + } + + if (BN_num_bytes(num) <= BN_BYTES) { + if (BIO_printf(bp, "%s %s%lu (%s0x%lx)\n", number, neg, + (unsigned long)bn_get_words(num)[0], neg, + (unsigned long)bn_get_words(num)[0]) <= 0) + return 0; + return 1; + } + + buflen = BN_num_bytes(num) + 1; + buf = tmp = OPENSSL_malloc(buflen); + if (buf == NULL) + goto err; + buf[0] = 0; + if (BIO_printf(bp, "%s%s\n", number, + (neg[0] == '-') ? " (Negative)" : "") <= 0) + goto err; + n = BN_bn2bin(num, buf + 1); + + if (buf[1] & 0x80) + n++; + else + tmp++; + + if (ASN1_buf_print(bp, tmp, n, indent + 4) == 0) + goto err; + rv = 1; + err: + OPENSSL_clear_free(buf, buflen); + return rv; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/t_spki.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/t_spki.c new file mode 100644 index 000000000..51b56d0aa --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/t_spki.c @@ -0,0 +1,56 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include + +/* Print out an SPKI */ + +int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki) +{ + EVP_PKEY *pkey; + ASN1_IA5STRING *chal; + ASN1_OBJECT *spkioid; + int i, n; + char *s; + BIO_printf(out, "Netscape SPKI:\n"); + X509_PUBKEY_get0_param(&spkioid, NULL, NULL, NULL, spki->spkac->pubkey); + i = OBJ_obj2nid(spkioid); + BIO_printf(out, " Public Key Algorithm: %s\n", + (i == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(i)); + pkey = X509_PUBKEY_get(spki->spkac->pubkey); + if (!pkey) + BIO_printf(out, " Unable to load public key\n"); + else { + EVP_PKEY_print_public(out, pkey, 4, NULL); + EVP_PKEY_free(pkey); + } + chal = spki->spkac->challenge; + if (chal->length) + BIO_printf(out, " Challenge String: %s\n", chal->data); + i = OBJ_obj2nid(spki->sig_algor.algorithm); + BIO_printf(out, " Signature Algorithm: %s", + (i == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(i)); + + n = spki->signature->length; + s = (char *)spki->signature->data; + for (i = 0; i < n; i++) { + if ((i % 18) == 0) + BIO_write(out, "\n ", 7); + BIO_printf(out, "%02x%s", (unsigned char)s[i], + ((i + 1) == n) ? "" : ":"); + } + BIO_write(out, "\n", 1); + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_dec.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_dec.c new file mode 100644 index 000000000..c2a521ed5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_dec.c @@ -0,0 +1,1160 @@ +/* + * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include "internal/numbers.h" +#include "asn1_locl.h" + + +/* + * Constructed types with a recursive definition (such as can be found in PKCS7) + * could eventually exceed the stack given malicious input with excessive + * recursion. Therefore we limit the stack depth. This is the maximum number of + * recursive invocations of asn1_item_embed_d2i(). + */ +#define ASN1_MAX_CONSTRUCTED_NEST 30 + +static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in, + long len, const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx, + int depth); + +static int asn1_check_eoc(const unsigned char **in, long len); +static int asn1_find_end(const unsigned char **in, long len, char inf); + +static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len, + char inf, int tag, int aclass, int depth); + +static int collect_data(BUF_MEM *buf, const unsigned char **p, long plen); + +static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, + char *inf, char *cst, + const unsigned char **in, long len, + int exptag, int expclass, char opt, ASN1_TLC *ctx); + +static int asn1_template_ex_d2i(ASN1_VALUE **pval, + const unsigned char **in, long len, + const ASN1_TEMPLATE *tt, char opt, + ASN1_TLC *ctx, int depth); +static int asn1_template_noexp_d2i(ASN1_VALUE **val, + const unsigned char **in, long len, + const ASN1_TEMPLATE *tt, char opt, + ASN1_TLC *ctx, int depth); +static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, + const unsigned char **in, long len, + const ASN1_ITEM *it, + int tag, int aclass, char opt, + ASN1_TLC *ctx); +static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, + int utype, char *free_cont, const ASN1_ITEM *it); + +/* Table to convert tags to bit values, used for MSTRING type */ +static const unsigned long tag2bit[32] = { + /* tags 0 - 3 */ + 0, 0, 0, B_ASN1_BIT_STRING, + /* tags 4- 7 */ + B_ASN1_OCTET_STRING, 0, 0, B_ASN1_UNKNOWN, + /* tags 8-11 */ + B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, + /* tags 12-15 */ + B_ASN1_UTF8STRING, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, + /* tags 16-19 */ + B_ASN1_SEQUENCE, 0, B_ASN1_NUMERICSTRING, B_ASN1_PRINTABLESTRING, + /* tags 20-22 */ + B_ASN1_T61STRING, B_ASN1_VIDEOTEXSTRING, B_ASN1_IA5STRING, + /* tags 23-24 */ + B_ASN1_UTCTIME, B_ASN1_GENERALIZEDTIME, + /* tags 25-27 */ + B_ASN1_GRAPHICSTRING, B_ASN1_ISO64STRING, B_ASN1_GENERALSTRING, + /* tags 28-31 */ + B_ASN1_UNIVERSALSTRING, B_ASN1_UNKNOWN, B_ASN1_BMPSTRING, B_ASN1_UNKNOWN, +}; + +unsigned long ASN1_tag2bit(int tag) +{ + if ((tag < 0) || (tag > 30)) + return 0; + return tag2bit[tag]; +} + +/* Macro to initialize and invalidate the cache */ + +#define asn1_tlc_clear(c) if (c) (c)->valid = 0 +/* Version to avoid compiler warning about 'c' always non-NULL */ +#define asn1_tlc_clear_nc(c) (c)->valid = 0 + +/* + * Decode an ASN1 item, this currently behaves just like a standard 'd2i' + * function. 'in' points to a buffer to read the data from, in future we + * will have more advanced versions that can input data a piece at a time and + * this will simply be a special case. + */ + +ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval, + const unsigned char **in, long len, + const ASN1_ITEM *it) +{ + ASN1_TLC c; + ASN1_VALUE *ptmpval = NULL; + if (!pval) + pval = &ptmpval; + asn1_tlc_clear_nc(&c); + if (ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0) + return *pval; + return NULL; +} + +int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, + const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx) +{ + int rv; + rv = asn1_item_embed_d2i(pval, in, len, it, tag, aclass, opt, ctx, 0); + if (rv <= 0) + ASN1_item_ex_free(pval, it); + return rv; +} + +/* + * Decode an item, taking care of IMPLICIT tagging, if any. If 'opt' set and + * tag mismatch return -1 to handle OPTIONAL + */ + +static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in, + long len, const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx, + int depth) +{ + const ASN1_TEMPLATE *tt, *errtt = NULL; + const ASN1_EXTERN_FUNCS *ef; + const ASN1_AUX *aux = it->funcs; + ASN1_aux_cb *asn1_cb; + const unsigned char *p = NULL, *q; + unsigned char oclass; + char seq_eoc, seq_nolen, cst, isopt; + long tmplen; + int i; + int otag; + int ret = 0; + ASN1_VALUE **pchptr; + if (!pval) + return 0; + if (aux && aux->asn1_cb) + asn1_cb = aux->asn1_cb; + else + asn1_cb = 0; + + if (++depth > ASN1_MAX_CONSTRUCTED_NEST) { + ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_NESTED_TOO_DEEP); + goto err; + } + + switch (it->itype) { + case ASN1_ITYPE_PRIMITIVE: + if (it->templates) { + /* + * tagging or OPTIONAL is currently illegal on an item template + * because the flags can't get passed down. In practice this + * isn't a problem: we include the relevant flags from the item + * template in the template itself. + */ + if ((tag != -1) || opt) { + ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, + ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE); + goto err; + } + return asn1_template_ex_d2i(pval, in, len, + it->templates, opt, ctx, depth); + } + return asn1_d2i_ex_primitive(pval, in, len, it, + tag, aclass, opt, ctx); + + case ASN1_ITYPE_MSTRING: + p = *in; + /* Just read in tag and class */ + ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, NULL, + &p, len, -1, 0, 1, ctx); + if (!ret) { + ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR); + goto err; + } + + /* Must be UNIVERSAL class */ + if (oclass != V_ASN1_UNIVERSAL) { + /* If OPTIONAL, assume this is OK */ + if (opt) + return -1; + ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_MSTRING_NOT_UNIVERSAL); + goto err; + } + /* Check tag matches bit map */ + if (!(ASN1_tag2bit(otag) & it->utype)) { + /* If OPTIONAL, assume this is OK */ + if (opt) + return -1; + ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_MSTRING_WRONG_TAG); + goto err; + } + return asn1_d2i_ex_primitive(pval, in, len, it, otag, 0, 0, ctx); + + case ASN1_ITYPE_EXTERN: + /* Use new style d2i */ + ef = it->funcs; + return ef->asn1_ex_d2i(pval, in, len, it, tag, aclass, opt, ctx); + + case ASN1_ITYPE_CHOICE: + if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL)) + goto auxerr; + if (*pval) { + /* Free up and zero CHOICE value if initialised */ + i = asn1_get_choice_selector(pval, it); + if ((i >= 0) && (i < it->tcount)) { + tt = it->templates + i; + pchptr = asn1_get_field_ptr(pval, tt); + asn1_template_free(pchptr, tt); + asn1_set_choice_selector(pval, -1, it); + } + } else if (!ASN1_item_ex_new(pval, it)) { + ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR); + goto err; + } + /* CHOICE type, try each possibility in turn */ + p = *in; + for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { + pchptr = asn1_get_field_ptr(pval, tt); + /* + * We mark field as OPTIONAL so its absence can be recognised. + */ + ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx, depth); + /* If field not present, try the next one */ + if (ret == -1) + continue; + /* If positive return, read OK, break loop */ + if (ret > 0) + break; + /* + * Must be an ASN1 parsing error. + * Free up any partial choice value + */ + asn1_template_free(pchptr, tt); + errtt = tt; + ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR); + goto err; + } + + /* Did we fall off the end without reading anything? */ + if (i == it->tcount) { + /* If OPTIONAL, this is OK */ + if (opt) { + /* Free and zero it */ + ASN1_item_ex_free(pval, it); + return -1; + } + ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_NO_MATCHING_CHOICE_TYPE); + goto err; + } + + asn1_set_choice_selector(pval, i, it); + + if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL)) + goto auxerr; + *in = p; + return 1; + + case ASN1_ITYPE_NDEF_SEQUENCE: + case ASN1_ITYPE_SEQUENCE: + p = *in; + tmplen = len; + + /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ + if (tag == -1) { + tag = V_ASN1_SEQUENCE; + aclass = V_ASN1_UNIVERSAL; + } + /* Get SEQUENCE length and update len, p */ + ret = asn1_check_tlen(&len, NULL, NULL, &seq_eoc, &cst, + &p, len, tag, aclass, opt, ctx); + if (!ret) { + ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR); + goto err; + } else if (ret == -1) + return -1; + if (aux && (aux->flags & ASN1_AFLG_BROKEN)) { + len = tmplen - (p - *in); + seq_nolen = 1; + } + /* If indefinite we don't do a length check */ + else + seq_nolen = seq_eoc; + if (!cst) { + ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_SEQUENCE_NOT_CONSTRUCTED); + goto err; + } + + if (!*pval && !ASN1_item_ex_new(pval, it)) { + ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR); + goto err; + } + + if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL)) + goto auxerr; + + /* Free up and zero any ADB found */ + for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { + if (tt->flags & ASN1_TFLG_ADB_MASK) { + const ASN1_TEMPLATE *seqtt; + ASN1_VALUE **pseqval; + seqtt = asn1_do_adb(pval, tt, 0); + if (seqtt == NULL) + continue; + pseqval = asn1_get_field_ptr(pval, seqtt); + asn1_template_free(pseqval, seqtt); + } + } + + /* Get each field entry */ + for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { + const ASN1_TEMPLATE *seqtt; + ASN1_VALUE **pseqval; + seqtt = asn1_do_adb(pval, tt, 1); + if (seqtt == NULL) + goto err; + pseqval = asn1_get_field_ptr(pval, seqtt); + /* Have we ran out of data? */ + if (!len) + break; + q = p; + if (asn1_check_eoc(&p, len)) { + if (!seq_eoc) { + ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_UNEXPECTED_EOC); + goto err; + } + len -= p - q; + seq_eoc = 0; + q = p; + break; + } + /* + * This determines the OPTIONAL flag value. The field cannot be + * omitted if it is the last of a SEQUENCE and there is still + * data to be read. This isn't strictly necessary but it + * increases efficiency in some cases. + */ + if (i == (it->tcount - 1)) + isopt = 0; + else + isopt = (char)(seqtt->flags & ASN1_TFLG_OPTIONAL); + /* + * attempt to read in field, allowing each to be OPTIONAL + */ + + ret = asn1_template_ex_d2i(pseqval, &p, len, seqtt, isopt, ctx, + depth); + if (!ret) { + errtt = seqtt; + goto err; + } else if (ret == -1) { + /* + * OPTIONAL component absent. Free and zero the field. + */ + asn1_template_free(pseqval, seqtt); + continue; + } + /* Update length */ + len -= p - q; + } + + /* Check for EOC if expecting one */ + if (seq_eoc && !asn1_check_eoc(&p, len)) { + ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_MISSING_EOC); + goto err; + } + /* Check all data read */ + if (!seq_nolen && len) { + ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_SEQUENCE_LENGTH_MISMATCH); + goto err; + } + + /* + * If we get here we've got no more data in the SEQUENCE, however we + * may not have read all fields so check all remaining are OPTIONAL + * and clear any that are. + */ + for (; i < it->tcount; tt++, i++) { + const ASN1_TEMPLATE *seqtt; + seqtt = asn1_do_adb(pval, tt, 1); + if (seqtt == NULL) + goto err; + if (seqtt->flags & ASN1_TFLG_OPTIONAL) { + ASN1_VALUE **pseqval; + pseqval = asn1_get_field_ptr(pval, seqtt); + asn1_template_free(pseqval, seqtt); + } else { + errtt = seqtt; + ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_FIELD_MISSING); + goto err; + } + } + /* Save encoding */ + if (!asn1_enc_save(pval, *in, p - *in, it)) + goto auxerr; + if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL)) + goto auxerr; + *in = p; + return 1; + + default: + return 0; + } + auxerr: + ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_AUX_ERROR); + err: + if (errtt) + ERR_add_error_data(4, "Field=", errtt->field_name, + ", Type=", it->sname); + else + ERR_add_error_data(2, "Type=", it->sname); + return 0; +} + +/* + * Templates are handled with two separate functions. One handles any + * EXPLICIT tag and the other handles the rest. + */ + +static int asn1_template_ex_d2i(ASN1_VALUE **val, + const unsigned char **in, long inlen, + const ASN1_TEMPLATE *tt, char opt, + ASN1_TLC *ctx, int depth) +{ + int flags, aclass; + int ret; + long len; + const unsigned char *p, *q; + char exp_eoc; + if (!val) + return 0; + flags = tt->flags; + aclass = flags & ASN1_TFLG_TAG_CLASS; + + p = *in; + + /* Check if EXPLICIT tag expected */ + if (flags & ASN1_TFLG_EXPTAG) { + char cst; + /* + * Need to work out amount of data available to the inner content and + * where it starts: so read in EXPLICIT header to get the info. + */ + ret = asn1_check_tlen(&len, NULL, NULL, &exp_eoc, &cst, + &p, inlen, tt->tag, aclass, opt, ctx); + q = p; + if (!ret) { + ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ERR_R_NESTED_ASN1_ERROR); + return 0; + } else if (ret == -1) + return -1; + if (!cst) { + ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, + ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED); + return 0; + } + /* We've found the field so it can't be OPTIONAL now */ + ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx, depth); + if (!ret) { + ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ERR_R_NESTED_ASN1_ERROR); + return 0; + } + /* We read the field in OK so update length */ + len -= p - q; + if (exp_eoc) { + /* If NDEF we must have an EOC here */ + if (!asn1_check_eoc(&p, len)) { + ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ASN1_R_MISSING_EOC); + goto err; + } + } else { + /* + * Otherwise we must hit the EXPLICIT tag end or its an error + */ + if (len) { + ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, + ASN1_R_EXPLICIT_LENGTH_MISMATCH); + goto err; + } + } + } else + return asn1_template_noexp_d2i(val, in, inlen, tt, opt, ctx, depth); + + *in = p; + return 1; + + err: + return 0; +} + +static int asn1_template_noexp_d2i(ASN1_VALUE **val, + const unsigned char **in, long len, + const ASN1_TEMPLATE *tt, char opt, + ASN1_TLC *ctx, int depth) +{ + int flags, aclass; + int ret; + ASN1_VALUE *tval; + const unsigned char *p, *q; + if (!val) + return 0; + flags = tt->flags; + aclass = flags & ASN1_TFLG_TAG_CLASS; + + p = *in; + q = p; + + /* + * If field is embedded then val needs fixing so it is a pointer to + * a pointer to a field. + */ + if (tt->flags & ASN1_TFLG_EMBED) { + tval = (ASN1_VALUE *)val; + val = &tval; + } + + if (flags & ASN1_TFLG_SK_MASK) { + /* SET OF, SEQUENCE OF */ + int sktag, skaclass; + char sk_eoc; + /* First work out expected inner tag value */ + if (flags & ASN1_TFLG_IMPTAG) { + sktag = tt->tag; + skaclass = aclass; + } else { + skaclass = V_ASN1_UNIVERSAL; + if (flags & ASN1_TFLG_SET_OF) + sktag = V_ASN1_SET; + else + sktag = V_ASN1_SEQUENCE; + } + /* Get the tag */ + ret = asn1_check_tlen(&len, NULL, NULL, &sk_eoc, NULL, + &p, len, sktag, skaclass, opt, ctx); + if (!ret) { + ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_NESTED_ASN1_ERROR); + return 0; + } else if (ret == -1) + return -1; + if (!*val) + *val = (ASN1_VALUE *)sk_ASN1_VALUE_new_null(); + else { + /* + * We've got a valid STACK: free up any items present + */ + STACK_OF(ASN1_VALUE) *sktmp = (STACK_OF(ASN1_VALUE) *)*val; + ASN1_VALUE *vtmp; + while (sk_ASN1_VALUE_num(sktmp) > 0) { + vtmp = sk_ASN1_VALUE_pop(sktmp); + ASN1_item_ex_free(&vtmp, ASN1_ITEM_ptr(tt->item)); + } + } + + if (!*val) { + ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* Read as many items as we can */ + while (len > 0) { + ASN1_VALUE *skfield; + q = p; + /* See if EOC found */ + if (asn1_check_eoc(&p, len)) { + if (!sk_eoc) { + ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, + ASN1_R_UNEXPECTED_EOC); + goto err; + } + len -= p - q; + sk_eoc = 0; + break; + } + skfield = NULL; + if (!asn1_item_embed_d2i(&skfield, &p, len, + ASN1_ITEM_ptr(tt->item), -1, 0, 0, ctx, + depth)) { + ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, + ERR_R_NESTED_ASN1_ERROR); + /* |skfield| may be partially allocated despite failure. */ + ASN1_item_free(skfield, ASN1_ITEM_ptr(tt->item)); + goto err; + } + len -= p - q; + if (!sk_ASN1_VALUE_push((STACK_OF(ASN1_VALUE) *)*val, skfield)) { + ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_MALLOC_FAILURE); + ASN1_item_free(skfield, ASN1_ITEM_ptr(tt->item)); + goto err; + } + } + if (sk_eoc) { + ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ASN1_R_MISSING_EOC); + goto err; + } + } else if (flags & ASN1_TFLG_IMPTAG) { + /* IMPLICIT tagging */ + ret = asn1_item_embed_d2i(val, &p, len, + ASN1_ITEM_ptr(tt->item), tt->tag, aclass, opt, + ctx, depth); + if (!ret) { + ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_NESTED_ASN1_ERROR); + goto err; + } else if (ret == -1) + return -1; + } else { + /* Nothing special */ + ret = asn1_item_embed_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), + -1, 0, opt, ctx, depth); + if (!ret) { + ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_NESTED_ASN1_ERROR); + goto err; + } else if (ret == -1) + return -1; + } + + *in = p; + return 1; + + err: + return 0; +} + +static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, + const unsigned char **in, long inlen, + const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx) +{ + int ret = 0, utype; + long plen; + char cst, inf, free_cont = 0; + const unsigned char *p; + BUF_MEM buf = { 0, NULL, 0, 0 }; + const unsigned char *cont = NULL; + long len; + if (!pval) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_ILLEGAL_NULL); + return 0; /* Should never happen */ + } + + if (it->itype == ASN1_ITYPE_MSTRING) { + utype = tag; + tag = -1; + } else + utype = it->utype; + + if (utype == V_ASN1_ANY) { + /* If type is ANY need to figure out type from tag */ + unsigned char oclass; + if (tag >= 0) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_ILLEGAL_TAGGED_ANY); + return 0; + } + if (opt) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, + ASN1_R_ILLEGAL_OPTIONAL_ANY); + return 0; + } + p = *in; + ret = asn1_check_tlen(NULL, &utype, &oclass, NULL, NULL, + &p, inlen, -1, 0, 0, ctx); + if (!ret) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_NESTED_ASN1_ERROR); + return 0; + } + if (oclass != V_ASN1_UNIVERSAL) + utype = V_ASN1_OTHER; + } + if (tag == -1) { + tag = utype; + aclass = V_ASN1_UNIVERSAL; + } + p = *in; + /* Check header */ + ret = asn1_check_tlen(&plen, NULL, NULL, &inf, &cst, + &p, inlen, tag, aclass, opt, ctx); + if (!ret) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_NESTED_ASN1_ERROR); + return 0; + } else if (ret == -1) + return -1; + ret = 0; + /* SEQUENCE, SET and "OTHER" are left in encoded form */ + if ((utype == V_ASN1_SEQUENCE) + || (utype == V_ASN1_SET) || (utype == V_ASN1_OTHER)) { + /* + * Clear context cache for type OTHER because the auto clear when we + * have a exact match won't work + */ + if (utype == V_ASN1_OTHER) { + asn1_tlc_clear(ctx); + } + /* SEQUENCE and SET must be constructed */ + else if (!cst) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, + ASN1_R_TYPE_NOT_CONSTRUCTED); + return 0; + } + + cont = *in; + /* If indefinite length constructed find the real end */ + if (inf) { + if (!asn1_find_end(&p, plen, inf)) + goto err; + len = p - cont; + } else { + len = p - cont + plen; + p += plen; + } + } else if (cst) { + if (utype == V_ASN1_NULL || utype == V_ASN1_BOOLEAN + || utype == V_ASN1_OBJECT || utype == V_ASN1_INTEGER + || utype == V_ASN1_ENUMERATED) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_TYPE_NOT_PRIMITIVE); + return 0; + } + + /* Free any returned 'buf' content */ + free_cont = 1; + /* + * Should really check the internal tags are correct but some things + * may get this wrong. The relevant specs say that constructed string + * types should be OCTET STRINGs internally irrespective of the type. + * So instead just check for UNIVERSAL class and ignore the tag. + */ + if (!asn1_collect(&buf, &p, plen, inf, -1, V_ASN1_UNIVERSAL, 0)) { + goto err; + } + len = buf.length; + /* Append a final null to string */ + if (!BUF_MEM_grow_clean(&buf, len + 1)) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_MALLOC_FAILURE); + goto err; + } + buf.data[len] = 0; + cont = (const unsigned char *)buf.data; + } else { + cont = p; + len = plen; + p += plen; + } + + /* We now have content length and type: translate into a structure */ + /* asn1_ex_c2i may reuse allocated buffer, and so sets free_cont to 0 */ + if (!asn1_ex_c2i(pval, cont, len, utype, &free_cont, it)) + goto err; + + *in = p; + ret = 1; + err: + if (free_cont) + OPENSSL_free(buf.data); + return ret; +} + +/* Translate ASN1 content octets into a structure */ + +static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, + int utype, char *free_cont, const ASN1_ITEM *it) +{ + ASN1_VALUE **opval = NULL; + ASN1_STRING *stmp; + ASN1_TYPE *typ = NULL; + int ret = 0; + const ASN1_PRIMITIVE_FUNCS *pf; + ASN1_INTEGER **tint; + pf = it->funcs; + + if (pf && pf->prim_c2i) + return pf->prim_c2i(pval, cont, len, utype, free_cont, it); + /* If ANY type clear type and set pointer to internal value */ + if (it->utype == V_ASN1_ANY) { + if (!*pval) { + typ = ASN1_TYPE_new(); + if (typ == NULL) + goto err; + *pval = (ASN1_VALUE *)typ; + } else + typ = (ASN1_TYPE *)*pval; + + if (utype != typ->type) + ASN1_TYPE_set(typ, utype, NULL); + opval = pval; + pval = &typ->value.asn1_value; + } + switch (utype) { + case V_ASN1_OBJECT: + if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len)) + goto err; + break; + + case V_ASN1_NULL: + if (len) { + ASN1err(ASN1_F_ASN1_EX_C2I, ASN1_R_NULL_IS_WRONG_LENGTH); + goto err; + } + *pval = (ASN1_VALUE *)1; + break; + + case V_ASN1_BOOLEAN: + if (len != 1) { + ASN1err(ASN1_F_ASN1_EX_C2I, ASN1_R_BOOLEAN_IS_WRONG_LENGTH); + goto err; + } else { + ASN1_BOOLEAN *tbool; + tbool = (ASN1_BOOLEAN *)pval; + *tbool = *cont; + } + break; + + case V_ASN1_BIT_STRING: + if (!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &cont, len)) + goto err; + break; + + case V_ASN1_INTEGER: + case V_ASN1_ENUMERATED: + tint = (ASN1_INTEGER **)pval; + if (!c2i_ASN1_INTEGER(tint, &cont, len)) + goto err; + /* Fixup type to match the expected form */ + (*tint)->type = utype | ((*tint)->type & V_ASN1_NEG); + break; + + case V_ASN1_OCTET_STRING: + case V_ASN1_NUMERICSTRING: + case V_ASN1_PRINTABLESTRING: + case V_ASN1_T61STRING: + case V_ASN1_VIDEOTEXSTRING: + case V_ASN1_IA5STRING: + case V_ASN1_UTCTIME: + case V_ASN1_GENERALIZEDTIME: + case V_ASN1_GRAPHICSTRING: + case V_ASN1_VISIBLESTRING: + case V_ASN1_GENERALSTRING: + case V_ASN1_UNIVERSALSTRING: + case V_ASN1_BMPSTRING: + case V_ASN1_UTF8STRING: + case V_ASN1_OTHER: + case V_ASN1_SET: + case V_ASN1_SEQUENCE: + default: + if (utype == V_ASN1_BMPSTRING && (len & 1)) { + ASN1err(ASN1_F_ASN1_EX_C2I, ASN1_R_BMPSTRING_IS_WRONG_LENGTH); + goto err; + } + if (utype == V_ASN1_UNIVERSALSTRING && (len & 3)) { + ASN1err(ASN1_F_ASN1_EX_C2I, + ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH); + goto err; + } + /* All based on ASN1_STRING and handled the same */ + if (!*pval) { + stmp = ASN1_STRING_type_new(utype); + if (stmp == NULL) { + ASN1err(ASN1_F_ASN1_EX_C2I, ERR_R_MALLOC_FAILURE); + goto err; + } + *pval = (ASN1_VALUE *)stmp; + } else { + stmp = (ASN1_STRING *)*pval; + stmp->type = utype; + } + /* If we've already allocated a buffer use it */ + if (*free_cont) { + OPENSSL_free(stmp->data); + stmp->data = (unsigned char *)cont; /* UGLY CAST! RL */ + stmp->length = len; + *free_cont = 0; + } else { + if (!ASN1_STRING_set(stmp, cont, len)) { + ASN1err(ASN1_F_ASN1_EX_C2I, ERR_R_MALLOC_FAILURE); + ASN1_STRING_free(stmp); + *pval = NULL; + goto err; + } + } + break; + } + /* If ASN1_ANY and NULL type fix up value */ + if (typ && (utype == V_ASN1_NULL)) + typ->value.ptr = NULL; + + ret = 1; + err: + if (!ret) { + ASN1_TYPE_free(typ); + if (opval) + *opval = NULL; + } + return ret; +} + +/* + * This function finds the end of an ASN1 structure when passed its maximum + * length, whether it is indefinite length and a pointer to the content. This + * is more efficient than calling asn1_collect because it does not recurse on + * each indefinite length header. + */ + +static int asn1_find_end(const unsigned char **in, long len, char inf) +{ + uint32_t expected_eoc; + long plen; + const unsigned char *p = *in, *q; + /* If not indefinite length constructed just add length */ + if (inf == 0) { + *in += len; + return 1; + } + expected_eoc = 1; + /* + * Indefinite length constructed form. Find the end when enough EOCs are + * found. If more indefinite length constructed headers are encountered + * increment the expected eoc count otherwise just skip to the end of the + * data. + */ + while (len > 0) { + if (asn1_check_eoc(&p, len)) { + expected_eoc--; + if (expected_eoc == 0) + break; + len -= 2; + continue; + } + q = p; + /* Just read in a header: only care about the length */ + if (!asn1_check_tlen(&plen, NULL, NULL, &inf, NULL, &p, len, + -1, 0, 0, NULL)) { + ASN1err(ASN1_F_ASN1_FIND_END, ERR_R_NESTED_ASN1_ERROR); + return 0; + } + if (inf) { + if (expected_eoc == UINT32_MAX) { + ASN1err(ASN1_F_ASN1_FIND_END, ERR_R_NESTED_ASN1_ERROR); + return 0; + } + expected_eoc++; + } else { + p += plen; + } + len -= p - q; + } + if (expected_eoc) { + ASN1err(ASN1_F_ASN1_FIND_END, ASN1_R_MISSING_EOC); + return 0; + } + *in = p; + return 1; +} + +/* + * This function collects the asn1 data from a constructed string type into + * a buffer. The values of 'in' and 'len' should refer to the contents of the + * constructed type and 'inf' should be set if it is indefinite length. + */ + +#ifndef ASN1_MAX_STRING_NEST +/* + * This determines how many levels of recursion are permitted in ASN1 string + * types. If it is not limited stack overflows can occur. If set to zero no + * recursion is allowed at all. Although zero should be adequate examples + * exist that require a value of 1. So 5 should be more than enough. + */ +# define ASN1_MAX_STRING_NEST 5 +#endif + +static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len, + char inf, int tag, int aclass, int depth) +{ + const unsigned char *p, *q; + long plen; + char cst, ininf; + p = *in; + inf &= 1; + /* + * If no buffer and not indefinite length constructed just pass over the + * encoded data + */ + if (!buf && !inf) { + *in += len; + return 1; + } + while (len > 0) { + q = p; + /* Check for EOC */ + if (asn1_check_eoc(&p, len)) { + /* + * EOC is illegal outside indefinite length constructed form + */ + if (!inf) { + ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_UNEXPECTED_EOC); + return 0; + } + inf = 0; + break; + } + + if (!asn1_check_tlen(&plen, NULL, NULL, &ininf, &cst, &p, + len, tag, aclass, 0, NULL)) { + ASN1err(ASN1_F_ASN1_COLLECT, ERR_R_NESTED_ASN1_ERROR); + return 0; + } + + /* If indefinite length constructed update max length */ + if (cst) { + if (depth >= ASN1_MAX_STRING_NEST) { + ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_NESTED_ASN1_STRING); + return 0; + } + if (!asn1_collect(buf, &p, plen, ininf, tag, aclass, depth + 1)) + return 0; + } else if (plen && !collect_data(buf, &p, plen)) + return 0; + len -= p - q; + } + if (inf) { + ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_MISSING_EOC); + return 0; + } + *in = p; + return 1; +} + +static int collect_data(BUF_MEM *buf, const unsigned char **p, long plen) +{ + int len; + if (buf) { + len = buf->length; + if (!BUF_MEM_grow_clean(buf, len + plen)) { + ASN1err(ASN1_F_COLLECT_DATA, ERR_R_MALLOC_FAILURE); + return 0; + } + memcpy(buf->data + len, *p, plen); + } + *p += plen; + return 1; +} + +/* Check for ASN1 EOC and swallow it if found */ + +static int asn1_check_eoc(const unsigned char **in, long len) +{ + const unsigned char *p; + if (len < 2) + return 0; + p = *in; + if (!p[0] && !p[1]) { + *in += 2; + return 1; + } + return 0; +} + +/* + * Check an ASN1 tag and length: a bit like ASN1_get_object but it sets the + * length for indefinite length constructed form, we don't know the exact + * length but we can set an upper bound to the amount of data available minus + * the header length just read. + */ + +static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, + char *inf, char *cst, + const unsigned char **in, long len, + int exptag, int expclass, char opt, ASN1_TLC *ctx) +{ + int i; + int ptag, pclass; + long plen; + const unsigned char *p, *q; + p = *in; + q = p; + + if (ctx && ctx->valid) { + i = ctx->ret; + plen = ctx->plen; + pclass = ctx->pclass; + ptag = ctx->ptag; + p += ctx->hdrlen; + } else { + i = ASN1_get_object(&p, &plen, &ptag, &pclass, len); + if (ctx) { + ctx->ret = i; + ctx->plen = plen; + ctx->pclass = pclass; + ctx->ptag = ptag; + ctx->hdrlen = p - q; + ctx->valid = 1; + /* + * If definite length, and no error, length + header can't exceed + * total amount of data available. + */ + if (!(i & 0x81) && ((plen + ctx->hdrlen) > len)) { + ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_TOO_LONG); + asn1_tlc_clear(ctx); + return 0; + } + } + } + + if (i & 0x80) { + ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_BAD_OBJECT_HEADER); + asn1_tlc_clear(ctx); + return 0; + } + if (exptag >= 0) { + if ((exptag != ptag) || (expclass != pclass)) { + /* + * If type is OPTIONAL, not an error: indicate missing type. + */ + if (opt) + return -1; + asn1_tlc_clear(ctx); + ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_WRONG_TAG); + return 0; + } + /* + * We have a tag and class match: assume we are going to do something + * with it + */ + asn1_tlc_clear(ctx); + } + + if (i & 1) + plen = len - (p - q); + + if (inf) + *inf = i & 1; + + if (cst) + *cst = i & V_ASN1_CONSTRUCTED; + + if (olen) + *olen = plen; + + if (oclass) + *oclass = pclass; + + if (otag) + *otag = ptag; + + *in = p; + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_enc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_enc.c new file mode 100644 index 000000000..30be314ff --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_enc.c @@ -0,0 +1,609 @@ +/* + * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include "internal/asn1_int.h" +#include "asn1_locl.h" + +static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, + const ASN1_ITEM *it, int tag, int aclass); +static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, + int skcontlen, const ASN1_ITEM *item, + int do_sort, int iclass); +static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, + const ASN1_TEMPLATE *tt, int tag, int aclass); +static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out, + const ASN1_ITEM *it, int flags); +static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype, + const ASN1_ITEM *it); + +/* + * Top level i2d equivalents: the 'ndef' variant instructs the encoder to use + * indefinite length constructed encoding, where appropriate + */ + +int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out, + const ASN1_ITEM *it) +{ + return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF); +} + +int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it) +{ + return asn1_item_flags_i2d(val, out, it, 0); +} + +/* + * Encode an ASN1 item, this is use by the standard 'i2d' function. 'out' + * points to a buffer to output the data to. The new i2d has one additional + * feature. If the output buffer is NULL (i.e. *out == NULL) then a buffer is + * allocated and populated with the encoding. + */ + +static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out, + const ASN1_ITEM *it, int flags) +{ + if (out && !*out) { + unsigned char *p, *buf; + int len; + + len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags); + if (len <= 0) + return len; + if ((buf = OPENSSL_malloc(len)) == NULL) { + ASN1err(ASN1_F_ASN1_ITEM_FLAGS_I2D, ERR_R_MALLOC_FAILURE); + return -1; + } + p = buf; + ASN1_item_ex_i2d(&val, &p, it, -1, flags); + *out = buf; + return len; + } + + return ASN1_item_ex_i2d(&val, out, it, -1, flags); +} + +/* + * Encode an item, taking care of IMPLICIT tagging (if any). This function + * performs the normal item handling: it can be used in external types. + */ + +int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, + const ASN1_ITEM *it, int tag, int aclass) +{ + const ASN1_TEMPLATE *tt = NULL; + int i, seqcontlen, seqlen, ndef = 1; + const ASN1_EXTERN_FUNCS *ef; + const ASN1_AUX *aux = it->funcs; + ASN1_aux_cb *asn1_cb = 0; + + if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) + return 0; + + if (aux && aux->asn1_cb) + asn1_cb = aux->asn1_cb; + + switch (it->itype) { + + case ASN1_ITYPE_PRIMITIVE: + if (it->templates) + return asn1_template_ex_i2d(pval, out, it->templates, + tag, aclass); + return asn1_i2d_ex_primitive(pval, out, it, tag, aclass); + + case ASN1_ITYPE_MSTRING: + return asn1_i2d_ex_primitive(pval, out, it, -1, aclass); + + case ASN1_ITYPE_CHOICE: + if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL)) + return 0; + i = asn1_get_choice_selector(pval, it); + if ((i >= 0) && (i < it->tcount)) { + ASN1_VALUE **pchval; + const ASN1_TEMPLATE *chtt; + chtt = it->templates + i; + pchval = asn1_get_field_ptr(pval, chtt); + return asn1_template_ex_i2d(pchval, out, chtt, -1, aclass); + } + /* Fixme: error condition if selector out of range */ + if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL)) + return 0; + break; + + case ASN1_ITYPE_EXTERN: + /* If new style i2d it does all the work */ + ef = it->funcs; + return ef->asn1_ex_i2d(pval, out, it, tag, aclass); + + case ASN1_ITYPE_NDEF_SEQUENCE: + /* Use indefinite length constructed if requested */ + if (aclass & ASN1_TFLG_NDEF) + ndef = 2; + /* fall through */ + + case ASN1_ITYPE_SEQUENCE: + i = asn1_enc_restore(&seqcontlen, out, pval, it); + /* An error occurred */ + if (i < 0) + return 0; + /* We have a valid cached encoding... */ + if (i > 0) + return seqcontlen; + /* Otherwise carry on */ + seqcontlen = 0; + /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ + if (tag == -1) { + tag = V_ASN1_SEQUENCE; + /* Retain any other flags in aclass */ + aclass = (aclass & ~ASN1_TFLG_TAG_CLASS) + | V_ASN1_UNIVERSAL; + } + if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL)) + return 0; + /* First work out sequence content length */ + for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { + const ASN1_TEMPLATE *seqtt; + ASN1_VALUE **pseqval; + int tmplen; + seqtt = asn1_do_adb(pval, tt, 1); + if (!seqtt) + return 0; + pseqval = asn1_get_field_ptr(pval, seqtt); + tmplen = asn1_template_ex_i2d(pseqval, NULL, seqtt, -1, aclass); + if (tmplen == -1 || (tmplen > INT_MAX - seqcontlen)) + return -1; + seqcontlen += tmplen; + } + + seqlen = ASN1_object_size(ndef, seqcontlen, tag); + if (!out || seqlen == -1) + return seqlen; + /* Output SEQUENCE header */ + ASN1_put_object(out, ndef, seqcontlen, tag, aclass); + for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { + const ASN1_TEMPLATE *seqtt; + ASN1_VALUE **pseqval; + seqtt = asn1_do_adb(pval, tt, 1); + if (!seqtt) + return 0; + pseqval = asn1_get_field_ptr(pval, seqtt); + /* FIXME: check for errors in enhanced version */ + asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass); + } + if (ndef == 2) + ASN1_put_eoc(out); + if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL)) + return 0; + return seqlen; + + default: + return 0; + + } + return 0; +} + +static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, + const ASN1_TEMPLATE *tt, int tag, int iclass) +{ + int i, ret, flags, ttag, tclass, ndef; + ASN1_VALUE *tval; + flags = tt->flags; + + /* + * If field is embedded then val needs fixing so it is a pointer to + * a pointer to a field. + */ + if (flags & ASN1_TFLG_EMBED) { + tval = (ASN1_VALUE *)pval; + pval = &tval; + } + /* + * Work out tag and class to use: tagging may come either from the + * template or the arguments, not both because this would create + * ambiguity. Additionally the iclass argument may contain some + * additional flags which should be noted and passed down to other + * levels. + */ + if (flags & ASN1_TFLG_TAG_MASK) { + /* Error if argument and template tagging */ + if (tag != -1) + /* FIXME: error code here */ + return -1; + /* Get tagging from template */ + ttag = tt->tag; + tclass = flags & ASN1_TFLG_TAG_CLASS; + } else if (tag != -1) { + /* No template tagging, get from arguments */ + ttag = tag; + tclass = iclass & ASN1_TFLG_TAG_CLASS; + } else { + ttag = -1; + tclass = 0; + } + /* + * Remove any class mask from iflag. + */ + iclass &= ~ASN1_TFLG_TAG_CLASS; + + /* + * At this point 'ttag' contains the outer tag to use, 'tclass' is the + * class and iclass is any flags passed to this function. + */ + + /* if template and arguments require ndef, use it */ + if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF)) + ndef = 2; + else + ndef = 1; + + if (flags & ASN1_TFLG_SK_MASK) { + /* SET OF, SEQUENCE OF */ + STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval; + int isset, sktag, skaclass; + int skcontlen, sklen; + ASN1_VALUE *skitem; + + if (!*pval) + return 0; + + if (flags & ASN1_TFLG_SET_OF) { + isset = 1; + /* 2 means we reorder */ + if (flags & ASN1_TFLG_SEQUENCE_OF) + isset = 2; + } else + isset = 0; + + /* + * Work out inner tag value: if EXPLICIT or no tagging use underlying + * type. + */ + if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) { + sktag = ttag; + skaclass = tclass; + } else { + skaclass = V_ASN1_UNIVERSAL; + if (isset) + sktag = V_ASN1_SET; + else + sktag = V_ASN1_SEQUENCE; + } + + /* Determine total length of items */ + skcontlen = 0; + for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) { + int tmplen; + skitem = sk_ASN1_VALUE_value(sk, i); + tmplen = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item), + -1, iclass); + if (tmplen == -1 || (skcontlen > INT_MAX - tmplen)) + return -1; + skcontlen += tmplen; + } + sklen = ASN1_object_size(ndef, skcontlen, sktag); + if (sklen == -1) + return -1; + /* If EXPLICIT need length of surrounding tag */ + if (flags & ASN1_TFLG_EXPTAG) + ret = ASN1_object_size(ndef, sklen, ttag); + else + ret = sklen; + + if (!out || ret == -1) + return ret; + + /* Now encode this lot... */ + /* EXPLICIT tag */ + if (flags & ASN1_TFLG_EXPTAG) + ASN1_put_object(out, ndef, sklen, ttag, tclass); + /* SET or SEQUENCE and IMPLICIT tag */ + ASN1_put_object(out, ndef, skcontlen, sktag, skaclass); + /* And the stuff itself */ + asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item), + isset, iclass); + if (ndef == 2) { + ASN1_put_eoc(out); + if (flags & ASN1_TFLG_EXPTAG) + ASN1_put_eoc(out); + } + + return ret; + } + + if (flags & ASN1_TFLG_EXPTAG) { + /* EXPLICIT tagging */ + /* Find length of tagged item */ + i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, iclass); + if (!i) + return 0; + /* Find length of EXPLICIT tag */ + ret = ASN1_object_size(ndef, i, ttag); + if (out && ret != -1) { + /* Output tag and item */ + ASN1_put_object(out, ndef, i, ttag, tclass); + ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, iclass); + if (ndef == 2) + ASN1_put_eoc(out); + } + return ret; + } + + /* Either normal or IMPLICIT tagging: combine class and flags */ + return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), + ttag, tclass | iclass); + +} + +/* Temporary structure used to hold DER encoding of items for SET OF */ + +typedef struct { + unsigned char *data; + int length; + ASN1_VALUE *field; +} DER_ENC; + +static int der_cmp(const void *a, const void *b) +{ + const DER_ENC *d1 = a, *d2 = b; + int cmplen, i; + cmplen = (d1->length < d2->length) ? d1->length : d2->length; + i = memcmp(d1->data, d2->data, cmplen); + if (i) + return i; + return d1->length - d2->length; +} + +/* Output the content octets of SET OF or SEQUENCE OF */ + +static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, + int skcontlen, const ASN1_ITEM *item, + int do_sort, int iclass) +{ + int i; + ASN1_VALUE *skitem; + unsigned char *tmpdat = NULL, *p = NULL; + DER_ENC *derlst = NULL, *tder; + if (do_sort) { + /* Don't need to sort less than 2 items */ + if (sk_ASN1_VALUE_num(sk) < 2) + do_sort = 0; + else { + derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk) + * sizeof(*derlst)); + if (derlst == NULL) + return 0; + tmpdat = OPENSSL_malloc(skcontlen); + if (tmpdat == NULL) { + OPENSSL_free(derlst); + return 0; + } + } + } + /* If not sorting just output each item */ + if (!do_sort) { + for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) { + skitem = sk_ASN1_VALUE_value(sk, i); + ASN1_item_ex_i2d(&skitem, out, item, -1, iclass); + } + return 1; + } + p = tmpdat; + + /* Doing sort: build up a list of each member's DER encoding */ + for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) { + skitem = sk_ASN1_VALUE_value(sk, i); + tder->data = p; + tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass); + tder->field = skitem; + } + + /* Now sort them */ + qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp); + /* Output sorted DER encoding */ + p = *out; + for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) { + memcpy(p, tder->data, tder->length); + p += tder->length; + } + *out = p; + /* If do_sort is 2 then reorder the STACK */ + if (do_sort == 2) { + for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) + (void)sk_ASN1_VALUE_set(sk, i, tder->field); + } + OPENSSL_free(derlst); + OPENSSL_free(tmpdat); + return 1; +} + +static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, + const ASN1_ITEM *it, int tag, int aclass) +{ + int len; + int utype; + int usetag; + int ndef = 0; + + utype = it->utype; + + /* + * Get length of content octets and maybe find out the underlying type. + */ + + len = asn1_ex_i2c(pval, NULL, &utype, it); + + /* + * If SEQUENCE, SET or OTHER then header is included in pseudo content + * octets so don't include tag+length. We need to check here because the + * call to asn1_ex_i2c() could change utype. + */ + if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) || + (utype == V_ASN1_OTHER)) + usetag = 0; + else + usetag = 1; + + /* -1 means omit type */ + + if (len == -1) + return 0; + + /* -2 return is special meaning use ndef */ + if (len == -2) { + ndef = 2; + len = 0; + } + + /* If not implicitly tagged get tag from underlying type */ + if (tag == -1) + tag = utype; + + /* Output tag+length followed by content octets */ + if (out) { + if (usetag) + ASN1_put_object(out, ndef, len, tag, aclass); + asn1_ex_i2c(pval, *out, &utype, it); + if (ndef) + ASN1_put_eoc(out); + else + *out += len; + } + + if (usetag) + return ASN1_object_size(ndef, len, tag); + return len; +} + +/* Produce content octets from a structure */ + +static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype, + const ASN1_ITEM *it) +{ + ASN1_BOOLEAN *tbool = NULL; + ASN1_STRING *strtmp; + ASN1_OBJECT *otmp; + int utype; + const unsigned char *cont; + unsigned char c; + int len; + const ASN1_PRIMITIVE_FUNCS *pf; + pf = it->funcs; + if (pf && pf->prim_i2c) + return pf->prim_i2c(pval, cout, putype, it); + + /* Should type be omitted? */ + if ((it->itype != ASN1_ITYPE_PRIMITIVE) + || (it->utype != V_ASN1_BOOLEAN)) { + if (!*pval) + return -1; + } + + if (it->itype == ASN1_ITYPE_MSTRING) { + /* If MSTRING type set the underlying type */ + strtmp = (ASN1_STRING *)*pval; + utype = strtmp->type; + *putype = utype; + } else if (it->utype == V_ASN1_ANY) { + /* If ANY set type and pointer to value */ + ASN1_TYPE *typ; + typ = (ASN1_TYPE *)*pval; + utype = typ->type; + *putype = utype; + pval = &typ->value.asn1_value; + } else + utype = *putype; + + switch (utype) { + case V_ASN1_OBJECT: + otmp = (ASN1_OBJECT *)*pval; + cont = otmp->data; + len = otmp->length; + if (cont == NULL || len == 0) + return -1; + break; + + case V_ASN1_NULL: + cont = NULL; + len = 0; + break; + + case V_ASN1_BOOLEAN: + tbool = (ASN1_BOOLEAN *)pval; + if (*tbool == -1) + return -1; + if (it->utype != V_ASN1_ANY) { + /* + * Default handling if value == size field then omit + */ + if (*tbool && (it->size > 0)) + return -1; + if (!*tbool && !it->size) + return -1; + } + c = (unsigned char)*tbool; + cont = &c; + len = 1; + break; + + case V_ASN1_BIT_STRING: + return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval, + cout ? &cout : NULL); + + case V_ASN1_INTEGER: + case V_ASN1_ENUMERATED: + /* + * These are all have the same content format as ASN1_INTEGER + */ + return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL); + + case V_ASN1_OCTET_STRING: + case V_ASN1_NUMERICSTRING: + case V_ASN1_PRINTABLESTRING: + case V_ASN1_T61STRING: + case V_ASN1_VIDEOTEXSTRING: + case V_ASN1_IA5STRING: + case V_ASN1_UTCTIME: + case V_ASN1_GENERALIZEDTIME: + case V_ASN1_GRAPHICSTRING: + case V_ASN1_VISIBLESTRING: + case V_ASN1_GENERALSTRING: + case V_ASN1_UNIVERSALSTRING: + case V_ASN1_BMPSTRING: + case V_ASN1_UTF8STRING: + case V_ASN1_SEQUENCE: + case V_ASN1_SET: + default: + /* All based on ASN1_STRING and handled the same */ + strtmp = (ASN1_STRING *)*pval; + /* Special handling for NDEF */ + if ((it->size == ASN1_TFLG_NDEF) + && (strtmp->flags & ASN1_STRING_FLAG_NDEF)) { + if (cout) { + strtmp->data = cout; + strtmp->length = 0; + } + /* Special return code */ + return -2; + } + cont = strtmp->data; + len = strtmp->length; + + break; + + } + if (cout && len) + memcpy(cout, cont, len); + return len; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_fre.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_fre.c new file mode 100644 index 000000000..bbce489fe --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_fre.c @@ -0,0 +1,208 @@ +/* + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include "asn1_locl.h" + +/* Free up an ASN1 structure */ + +void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it) +{ + asn1_item_embed_free(&val, it, 0); +} + +void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + asn1_item_embed_free(pval, it, 0); +} + +void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed) +{ + const ASN1_TEMPLATE *tt = NULL, *seqtt; + const ASN1_EXTERN_FUNCS *ef; + const ASN1_AUX *aux = it->funcs; + ASN1_aux_cb *asn1_cb; + int i; + + if (!pval) + return; + if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) + return; + if (aux && aux->asn1_cb) + asn1_cb = aux->asn1_cb; + else + asn1_cb = 0; + + switch (it->itype) { + + case ASN1_ITYPE_PRIMITIVE: + if (it->templates) + asn1_template_free(pval, it->templates); + else + asn1_primitive_free(pval, it, embed); + break; + + case ASN1_ITYPE_MSTRING: + asn1_primitive_free(pval, it, embed); + break; + + case ASN1_ITYPE_CHOICE: + if (asn1_cb) { + i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL); + if (i == 2) + return; + } + i = asn1_get_choice_selector(pval, it); + if ((i >= 0) && (i < it->tcount)) { + ASN1_VALUE **pchval; + + tt = it->templates + i; + pchval = asn1_get_field_ptr(pval, tt); + asn1_template_free(pchval, tt); + } + if (asn1_cb) + asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL); + if (embed == 0) { + OPENSSL_free(*pval); + *pval = NULL; + } + break; + + case ASN1_ITYPE_EXTERN: + ef = it->funcs; + if (ef && ef->asn1_ex_free) + ef->asn1_ex_free(pval, it); + break; + + case ASN1_ITYPE_NDEF_SEQUENCE: + case ASN1_ITYPE_SEQUENCE: + if (asn1_do_lock(pval, -1, it) != 0) /* if error or ref-counter > 0 */ + return; + if (asn1_cb) { + i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL); + if (i == 2) + return; + } + asn1_enc_free(pval, it); + /* + * If we free up as normal we will invalidate any ANY DEFINED BY + * field and we won't be able to determine the type of the field it + * defines. So free up in reverse order. + */ + tt = it->templates + it->tcount; + for (i = 0; i < it->tcount; i++) { + ASN1_VALUE **pseqval; + + tt--; + seqtt = asn1_do_adb(pval, tt, 0); + if (!seqtt) + continue; + pseqval = asn1_get_field_ptr(pval, seqtt); + asn1_template_free(pseqval, seqtt); + } + if (asn1_cb) + asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL); + if (embed == 0) { + OPENSSL_free(*pval); + *pval = NULL; + } + break; + } +} + +void asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) +{ + int embed = tt->flags & ASN1_TFLG_EMBED; + ASN1_VALUE *tval; + if (embed) { + tval = (ASN1_VALUE *)pval; + pval = &tval; + } + if (tt->flags & ASN1_TFLG_SK_MASK) { + STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval; + int i; + + for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) { + ASN1_VALUE *vtmp = sk_ASN1_VALUE_value(sk, i); + + asn1_item_embed_free(&vtmp, ASN1_ITEM_ptr(tt->item), embed); + } + sk_ASN1_VALUE_free(sk); + *pval = NULL; + } else { + asn1_item_embed_free(pval, ASN1_ITEM_ptr(tt->item), embed); + } +} + +void asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed) +{ + int utype; + + /* Special case: if 'it' is a primitive with a free_func, use that. */ + if (it) { + const ASN1_PRIMITIVE_FUNCS *pf = it->funcs; + + if (embed) { + if (pf && pf->prim_clear) { + pf->prim_clear(pval, it); + return; + } + } else if (pf && pf->prim_free) { + pf->prim_free(pval, it); + return; + } + } + + /* Special case: if 'it' is NULL, free contents of ASN1_TYPE */ + if (!it) { + ASN1_TYPE *typ = (ASN1_TYPE *)*pval; + + utype = typ->type; + pval = &typ->value.asn1_value; + if (!*pval) + return; + } else if (it->itype == ASN1_ITYPE_MSTRING) { + utype = -1; + if (!*pval) + return; + } else { + utype = it->utype; + if ((utype != V_ASN1_BOOLEAN) && !*pval) + return; + } + + switch (utype) { + case V_ASN1_OBJECT: + ASN1_OBJECT_free((ASN1_OBJECT *)*pval); + break; + + case V_ASN1_BOOLEAN: + if (it) + *(ASN1_BOOLEAN *)pval = it->size; + else + *(ASN1_BOOLEAN *)pval = -1; + return; + + case V_ASN1_NULL: + break; + + case V_ASN1_ANY: + asn1_primitive_free(pval, NULL, 0); + OPENSSL_free(*pval); + break; + + default: + asn1_string_embed_free((ASN1_STRING *)*pval, embed); + break; + } + *pval = NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_new.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_new.c new file mode 100644 index 000000000..6b8ea8ddd --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_new.c @@ -0,0 +1,349 @@ +/* + * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include +#include "asn1_locl.h" + +static int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, + int embed); +static int asn1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it, + int embed); +static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it); +static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); +static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); +static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it); + +ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it) +{ + ASN1_VALUE *ret = NULL; + if (ASN1_item_ex_new(&ret, it) > 0) + return ret; + return NULL; +} + +/* Allocate an ASN1 structure */ + +int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + return asn1_item_embed_new(pval, it, 0); +} + +int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed) +{ + const ASN1_TEMPLATE *tt = NULL; + const ASN1_EXTERN_FUNCS *ef; + const ASN1_AUX *aux = it->funcs; + ASN1_aux_cb *asn1_cb; + ASN1_VALUE **pseqval; + int i; + if (aux && aux->asn1_cb) + asn1_cb = aux->asn1_cb; + else + asn1_cb = 0; + +#ifndef OPENSSL_NO_CRYPTO_MDEBUG + OPENSSL_mem_debug_push(it->sname ? it->sname : "asn1_item_embed_new"); +#endif + + switch (it->itype) { + + case ASN1_ITYPE_EXTERN: + ef = it->funcs; + if (ef && ef->asn1_ex_new) { + if (!ef->asn1_ex_new(pval, it)) + goto memerr; + } + break; + + case ASN1_ITYPE_PRIMITIVE: + if (it->templates) { + if (!asn1_template_new(pval, it->templates)) + goto memerr; + } else if (!asn1_primitive_new(pval, it, embed)) + goto memerr; + break; + + case ASN1_ITYPE_MSTRING: + if (!asn1_primitive_new(pval, it, embed)) + goto memerr; + break; + + case ASN1_ITYPE_CHOICE: + if (asn1_cb) { + i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL); + if (!i) + goto auxerr; + if (i == 2) { +#ifndef OPENSSL_NO_CRYPTO_MDEBUG + OPENSSL_mem_debug_pop(); +#endif + return 1; + } + } + if (embed) { + memset(*pval, 0, it->size); + } else { + *pval = OPENSSL_zalloc(it->size); + if (*pval == NULL) + goto memerr; + } + asn1_set_choice_selector(pval, -1, it); + if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL)) + goto auxerr2; + break; + + case ASN1_ITYPE_NDEF_SEQUENCE: + case ASN1_ITYPE_SEQUENCE: + if (asn1_cb) { + i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL); + if (!i) + goto auxerr; + if (i == 2) { +#ifndef OPENSSL_NO_CRYPTO_MDEBUG + OPENSSL_mem_debug_pop(); +#endif + return 1; + } + } + if (embed) { + memset(*pval, 0, it->size); + } else { + *pval = OPENSSL_zalloc(it->size); + if (*pval == NULL) + goto memerr; + } + /* 0 : init. lock */ + if (asn1_do_lock(pval, 0, it) < 0) { + if (!embed) { + OPENSSL_free(*pval); + *pval = NULL; + } + goto memerr; + } + asn1_enc_init(pval, it); + for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { + pseqval = asn1_get_field_ptr(pval, tt); + if (!asn1_template_new(pseqval, tt)) + goto memerr2; + } + if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL)) + goto auxerr2; + break; + } +#ifndef OPENSSL_NO_CRYPTO_MDEBUG + OPENSSL_mem_debug_pop(); +#endif + return 1; + + memerr2: + asn1_item_embed_free(pval, it, embed); + memerr: + ASN1err(ASN1_F_ASN1_ITEM_EMBED_NEW, ERR_R_MALLOC_FAILURE); +#ifndef OPENSSL_NO_CRYPTO_MDEBUG + OPENSSL_mem_debug_pop(); +#endif + return 0; + + auxerr2: + asn1_item_embed_free(pval, it, embed); + auxerr: + ASN1err(ASN1_F_ASN1_ITEM_EMBED_NEW, ASN1_R_AUX_ERROR); +#ifndef OPENSSL_NO_CRYPTO_MDEBUG + OPENSSL_mem_debug_pop(); +#endif + return 0; + +} + +static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + const ASN1_EXTERN_FUNCS *ef; + + switch (it->itype) { + + case ASN1_ITYPE_EXTERN: + ef = it->funcs; + if (ef && ef->asn1_ex_clear) + ef->asn1_ex_clear(pval, it); + else + *pval = NULL; + break; + + case ASN1_ITYPE_PRIMITIVE: + if (it->templates) + asn1_template_clear(pval, it->templates); + else + asn1_primitive_clear(pval, it); + break; + + case ASN1_ITYPE_MSTRING: + asn1_primitive_clear(pval, it); + break; + + case ASN1_ITYPE_CHOICE: + case ASN1_ITYPE_SEQUENCE: + case ASN1_ITYPE_NDEF_SEQUENCE: + *pval = NULL; + break; + } +} + +static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) +{ + const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item); + int embed = tt->flags & ASN1_TFLG_EMBED; + ASN1_VALUE *tval; + int ret; + if (embed) { + tval = (ASN1_VALUE *)pval; + pval = &tval; + } + if (tt->flags & ASN1_TFLG_OPTIONAL) { + asn1_template_clear(pval, tt); + return 1; + } + /* If ANY DEFINED BY nothing to do */ + + if (tt->flags & ASN1_TFLG_ADB_MASK) { + *pval = NULL; + return 1; + } +#ifndef OPENSSL_NO_CRYPTO_MDEBUG + OPENSSL_mem_debug_push(tt->field_name + ? tt->field_name : "asn1_template_new"); +#endif + /* If SET OF or SEQUENCE OF, its a STACK */ + if (tt->flags & ASN1_TFLG_SK_MASK) { + STACK_OF(ASN1_VALUE) *skval; + skval = sk_ASN1_VALUE_new_null(); + if (!skval) { + ASN1err(ASN1_F_ASN1_TEMPLATE_NEW, ERR_R_MALLOC_FAILURE); + ret = 0; + goto done; + } + *pval = (ASN1_VALUE *)skval; + ret = 1; + goto done; + } + /* Otherwise pass it back to the item routine */ + ret = asn1_item_embed_new(pval, it, embed); + done: +#ifndef OPENSSL_NO_CRYPTO_MDEBUG + OPENSSL_mem_debug_pop(); +#endif + return ret; +} + +static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) +{ + /* If ADB or STACK just NULL the field */ + if (tt->flags & (ASN1_TFLG_ADB_MASK | ASN1_TFLG_SK_MASK)) + *pval = NULL; + else + asn1_item_clear(pval, ASN1_ITEM_ptr(tt->item)); +} + +/* + * NB: could probably combine most of the real XXX_new() behaviour and junk + * all the old functions. + */ + +static int asn1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it, + int embed) +{ + ASN1_TYPE *typ; + ASN1_STRING *str; + int utype; + + if (!it) + return 0; + + if (it->funcs) { + const ASN1_PRIMITIVE_FUNCS *pf = it->funcs; + if (embed) { + if (pf->prim_clear) { + pf->prim_clear(pval, it); + return 1; + } + } else if (pf->prim_new) { + return pf->prim_new(pval, it); + } + } + + if (it->itype == ASN1_ITYPE_MSTRING) + utype = -1; + else + utype = it->utype; + switch (utype) { + case V_ASN1_OBJECT: + *pval = (ASN1_VALUE *)OBJ_nid2obj(NID_undef); + return 1; + + case V_ASN1_BOOLEAN: + *(ASN1_BOOLEAN *)pval = it->size; + return 1; + + case V_ASN1_NULL: + *pval = (ASN1_VALUE *)1; + return 1; + + case V_ASN1_ANY: + if ((typ = OPENSSL_malloc(sizeof(*typ))) == NULL) { + ASN1err(ASN1_F_ASN1_PRIMITIVE_NEW, ERR_R_MALLOC_FAILURE); + return 0; + } + typ->value.ptr = NULL; + typ->type = -1; + *pval = (ASN1_VALUE *)typ; + break; + + default: + if (embed) { + str = *(ASN1_STRING **)pval; + memset(str, 0, sizeof(*str)); + str->type = utype; + str->flags = ASN1_STRING_FLAG_EMBED; + } else { + str = ASN1_STRING_type_new(utype); + *pval = (ASN1_VALUE *)str; + } + if (it->itype == ASN1_ITYPE_MSTRING && str) + str->flags |= ASN1_STRING_FLAG_MSTRING; + break; + } + if (*pval) + return 1; + return 0; +} + +static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + int utype; + if (it && it->funcs) { + const ASN1_PRIMITIVE_FUNCS *pf = it->funcs; + if (pf->prim_clear) + pf->prim_clear(pval, it); + else + *pval = NULL; + return; + } + if (!it || (it->itype == ASN1_ITYPE_MSTRING)) + utype = -1; + else + utype = it->utype; + if (utype == V_ASN1_BOOLEAN) + *(ASN1_BOOLEAN *)pval = it->size; + else + *pval = NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_prn.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_prn.c new file mode 100644 index 000000000..1fb66f106 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_prn.c @@ -0,0 +1,539 @@ +/* + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include +#include "internal/asn1_int.h" +#include "asn1_locl.h" + +/* + * Print routines. + */ + +/* ASN1_PCTX routines */ + +static ASN1_PCTX default_pctx = { + ASN1_PCTX_FLAGS_SHOW_ABSENT, /* flags */ + 0, /* nm_flags */ + 0, /* cert_flags */ + 0, /* oid_flags */ + 0 /* str_flags */ +}; + +ASN1_PCTX *ASN1_PCTX_new(void) +{ + ASN1_PCTX *ret; + + ret = OPENSSL_zalloc(sizeof(*ret)); + if (ret == NULL) { + ASN1err(ASN1_F_ASN1_PCTX_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + return ret; +} + +void ASN1_PCTX_free(ASN1_PCTX *p) +{ + OPENSSL_free(p); +} + +unsigned long ASN1_PCTX_get_flags(const ASN1_PCTX *p) +{ + return p->flags; +} + +void ASN1_PCTX_set_flags(ASN1_PCTX *p, unsigned long flags) +{ + p->flags = flags; +} + +unsigned long ASN1_PCTX_get_nm_flags(const ASN1_PCTX *p) +{ + return p->nm_flags; +} + +void ASN1_PCTX_set_nm_flags(ASN1_PCTX *p, unsigned long flags) +{ + p->nm_flags = flags; +} + +unsigned long ASN1_PCTX_get_cert_flags(const ASN1_PCTX *p) +{ + return p->cert_flags; +} + +void ASN1_PCTX_set_cert_flags(ASN1_PCTX *p, unsigned long flags) +{ + p->cert_flags = flags; +} + +unsigned long ASN1_PCTX_get_oid_flags(const ASN1_PCTX *p) +{ + return p->oid_flags; +} + +void ASN1_PCTX_set_oid_flags(ASN1_PCTX *p, unsigned long flags) +{ + p->oid_flags = flags; +} + +unsigned long ASN1_PCTX_get_str_flags(const ASN1_PCTX *p) +{ + return p->str_flags; +} + +void ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags) +{ + p->str_flags = flags; +} + +/* Main print routines */ + +static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent, + const ASN1_ITEM *it, + const char *fname, const char *sname, + int nohdr, const ASN1_PCTX *pctx); + +static int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent, + const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx); + +static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld, + const ASN1_ITEM *it, int indent, + const char *fname, const char *sname, + const ASN1_PCTX *pctx); + +static int asn1_print_fsname(BIO *out, int indent, + const char *fname, const char *sname, + const ASN1_PCTX *pctx); + +int ASN1_item_print(BIO *out, ASN1_VALUE *ifld, int indent, + const ASN1_ITEM *it, const ASN1_PCTX *pctx) +{ + const char *sname; + if (pctx == NULL) + pctx = &default_pctx; + if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME) + sname = NULL; + else + sname = it->sname; + return asn1_item_print_ctx(out, &ifld, indent, it, NULL, sname, 0, pctx); +} + +static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent, + const ASN1_ITEM *it, + const char *fname, const char *sname, + int nohdr, const ASN1_PCTX *pctx) +{ + const ASN1_TEMPLATE *tt; + const ASN1_EXTERN_FUNCS *ef; + ASN1_VALUE **tmpfld; + const ASN1_AUX *aux = it->funcs; + ASN1_aux_cb *asn1_cb; + ASN1_PRINT_ARG parg; + int i; + if (aux && aux->asn1_cb) { + parg.out = out; + parg.indent = indent; + parg.pctx = pctx; + asn1_cb = aux->asn1_cb; + } else + asn1_cb = 0; + + if (((it->itype != ASN1_ITYPE_PRIMITIVE) + || (it->utype != V_ASN1_BOOLEAN)) && *fld == NULL) { + if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_ABSENT) { + if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx)) + return 0; + if (BIO_puts(out, "\n") <= 0) + return 0; + } + return 1; + } + + switch (it->itype) { + case ASN1_ITYPE_PRIMITIVE: + if (it->templates) { + if (!asn1_template_print_ctx(out, fld, indent, + it->templates, pctx)) + return 0; + break; + } + /* fall through */ + case ASN1_ITYPE_MSTRING: + if (!asn1_primitive_print(out, fld, it, indent, fname, sname, pctx)) + return 0; + break; + + case ASN1_ITYPE_EXTERN: + if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx)) + return 0; + /* Use new style print routine if possible */ + ef = it->funcs; + if (ef && ef->asn1_ex_print) { + i = ef->asn1_ex_print(out, fld, indent, "", pctx); + if (!i) + return 0; + if ((i == 2) && (BIO_puts(out, "\n") <= 0)) + return 0; + return 1; + } else if (sname && + BIO_printf(out, ":EXTERNAL TYPE %s\n", sname) <= 0) + return 0; + break; + + case ASN1_ITYPE_CHOICE: + /* CHOICE type, get selector */ + i = asn1_get_choice_selector(fld, it); + /* This should never happen... */ + if ((i < 0) || (i >= it->tcount)) { + if (BIO_printf(out, "ERROR: selector [%d] invalid\n", i) <= 0) + return 0; + return 1; + } + tt = it->templates + i; + tmpfld = asn1_get_field_ptr(fld, tt); + if (!asn1_template_print_ctx(out, tmpfld, indent, tt, pctx)) + return 0; + break; + + case ASN1_ITYPE_SEQUENCE: + case ASN1_ITYPE_NDEF_SEQUENCE: + if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx)) + return 0; + if (fname || sname) { + if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) { + if (BIO_puts(out, " {\n") <= 0) + return 0; + } else { + if (BIO_puts(out, "\n") <= 0) + return 0; + } + } + + if (asn1_cb) { + i = asn1_cb(ASN1_OP_PRINT_PRE, fld, it, &parg); + if (i == 0) + return 0; + if (i == 2) + return 1; + } + + /* Print each field entry */ + for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { + const ASN1_TEMPLATE *seqtt; + seqtt = asn1_do_adb(fld, tt, 1); + if (!seqtt) + return 0; + tmpfld = asn1_get_field_ptr(fld, seqtt); + if (!asn1_template_print_ctx(out, tmpfld, + indent + 2, seqtt, pctx)) + return 0; + } + if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) { + if (BIO_printf(out, "%*s}\n", indent, "") < 0) + return 0; + } + + if (asn1_cb) { + i = asn1_cb(ASN1_OP_PRINT_POST, fld, it, &parg); + if (i == 0) + return 0; + } + break; + + default: + BIO_printf(out, "Unprocessed type %d\n", it->itype); + return 0; + } + + return 1; +} + +static int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent, + const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx) +{ + int i, flags; + const char *sname, *fname; + ASN1_VALUE *tfld; + flags = tt->flags; + if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME) + sname = ASN1_ITEM_ptr(tt->item)->sname; + else + sname = NULL; + if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME) + fname = NULL; + else + fname = tt->field_name; + + /* + * If field is embedded then fld needs fixing so it is a pointer to + * a pointer to a field. + */ + if (flags & ASN1_TFLG_EMBED) { + tfld = (ASN1_VALUE *)fld; + fld = &tfld; + } + + if (flags & ASN1_TFLG_SK_MASK) { + char *tname; + ASN1_VALUE *skitem; + STACK_OF(ASN1_VALUE) *stack; + + /* SET OF, SEQUENCE OF */ + if (fname) { + if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SSOF) { + if (flags & ASN1_TFLG_SET_OF) + tname = "SET"; + else + tname = "SEQUENCE"; + if (BIO_printf(out, "%*s%s OF %s {\n", + indent, "", tname, tt->field_name) <= 0) + return 0; + } else if (BIO_printf(out, "%*s%s:\n", indent, "", fname) <= 0) + return 0; + } + stack = (STACK_OF(ASN1_VALUE) *)*fld; + for (i = 0; i < sk_ASN1_VALUE_num(stack); i++) { + if ((i > 0) && (BIO_puts(out, "\n") <= 0)) + return 0; + + skitem = sk_ASN1_VALUE_value(stack, i); + if (!asn1_item_print_ctx(out, &skitem, indent + 2, + ASN1_ITEM_ptr(tt->item), NULL, NULL, 1, + pctx)) + return 0; + } + if (i == 0 && BIO_printf(out, "%*s<%s>\n", indent + 2, "", + stack == NULL ? "ABSENT" : "EMPTY") <= 0) + return 0; + if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) { + if (BIO_printf(out, "%*s}\n", indent, "") <= 0) + return 0; + } + return 1; + } + return asn1_item_print_ctx(out, fld, indent, ASN1_ITEM_ptr(tt->item), + fname, sname, 0, pctx); +} + +static int asn1_print_fsname(BIO *out, int indent, + const char *fname, const char *sname, + const ASN1_PCTX *pctx) +{ + static const char spaces[] = " "; + static const int nspaces = sizeof(spaces) - 1; + + while (indent > nspaces) { + if (BIO_write(out, spaces, nspaces) != nspaces) + return 0; + indent -= nspaces; + } + if (BIO_write(out, spaces, indent) != indent) + return 0; + if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME) + sname = NULL; + if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME) + fname = NULL; + if (!sname && !fname) + return 1; + if (fname) { + if (BIO_puts(out, fname) <= 0) + return 0; + } + if (sname) { + if (fname) { + if (BIO_printf(out, " (%s)", sname) <= 0) + return 0; + } else { + if (BIO_puts(out, sname) <= 0) + return 0; + } + } + if (BIO_write(out, ": ", 2) != 2) + return 0; + return 1; +} + +static int asn1_print_boolean(BIO *out, int boolval) +{ + const char *str; + switch (boolval) { + case -1: + str = "BOOL ABSENT"; + break; + + case 0: + str = "FALSE"; + break; + + default: + str = "TRUE"; + break; + + } + + if (BIO_puts(out, str) <= 0) + return 0; + return 1; + +} + +static int asn1_print_integer(BIO *out, const ASN1_INTEGER *str) +{ + char *s; + int ret = 1; + s = i2s_ASN1_INTEGER(NULL, str); + if (s == NULL) + return 0; + if (BIO_puts(out, s) <= 0) + ret = 0; + OPENSSL_free(s); + return ret; +} + +static int asn1_print_oid(BIO *out, const ASN1_OBJECT *oid) +{ + char objbuf[80]; + const char *ln; + ln = OBJ_nid2ln(OBJ_obj2nid(oid)); + if (!ln) + ln = ""; + OBJ_obj2txt(objbuf, sizeof(objbuf), oid, 1); + if (BIO_printf(out, "%s (%s)", ln, objbuf) <= 0) + return 0; + return 1; +} + +static int asn1_print_obstring(BIO *out, const ASN1_STRING *str, int indent) +{ + if (str->type == V_ASN1_BIT_STRING) { + if (BIO_printf(out, " (%ld unused bits)\n", str->flags & 0x7) <= 0) + return 0; + } else if (BIO_puts(out, "\n") <= 0) + return 0; + if ((str->length > 0) + && BIO_dump_indent(out, (const char *)str->data, str->length, + indent + 2) <= 0) + return 0; + return 1; +} + +static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld, + const ASN1_ITEM *it, int indent, + const char *fname, const char *sname, + const ASN1_PCTX *pctx) +{ + long utype; + ASN1_STRING *str; + int ret = 1, needlf = 1; + const char *pname; + const ASN1_PRIMITIVE_FUNCS *pf; + pf = it->funcs; + if (!asn1_print_fsname(out, indent, fname, sname, pctx)) + return 0; + if (pf && pf->prim_print) + return pf->prim_print(out, fld, it, indent, pctx); + if (it->itype == ASN1_ITYPE_MSTRING) { + str = (ASN1_STRING *)*fld; + utype = str->type & ~V_ASN1_NEG; + } else { + utype = it->utype; + if (utype == V_ASN1_BOOLEAN) + str = NULL; + else + str = (ASN1_STRING *)*fld; + } + if (utype == V_ASN1_ANY) { + ASN1_TYPE *atype = (ASN1_TYPE *)*fld; + utype = atype->type; + fld = &atype->value.asn1_value; + str = (ASN1_STRING *)*fld; + if (pctx->flags & ASN1_PCTX_FLAGS_NO_ANY_TYPE) + pname = NULL; + else + pname = ASN1_tag2str(utype); + } else { + if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_TYPE) + pname = ASN1_tag2str(utype); + else + pname = NULL; + } + + if (utype == V_ASN1_NULL) { + if (BIO_puts(out, "NULL\n") <= 0) + return 0; + return 1; + } + + if (pname) { + if (BIO_puts(out, pname) <= 0) + return 0; + if (BIO_puts(out, ":") <= 0) + return 0; + } + + switch (utype) { + case V_ASN1_BOOLEAN: + { + int boolval = *(int *)fld; + if (boolval == -1) + boolval = it->size; + ret = asn1_print_boolean(out, boolval); + } + break; + + case V_ASN1_INTEGER: + case V_ASN1_ENUMERATED: + ret = asn1_print_integer(out, str); + break; + + case V_ASN1_UTCTIME: + ret = ASN1_UTCTIME_print(out, str); + break; + + case V_ASN1_GENERALIZEDTIME: + ret = ASN1_GENERALIZEDTIME_print(out, str); + break; + + case V_ASN1_OBJECT: + ret = asn1_print_oid(out, (const ASN1_OBJECT *)*fld); + break; + + case V_ASN1_OCTET_STRING: + case V_ASN1_BIT_STRING: + ret = asn1_print_obstring(out, str, indent); + needlf = 0; + break; + + case V_ASN1_SEQUENCE: + case V_ASN1_SET: + case V_ASN1_OTHER: + if (BIO_puts(out, "\n") <= 0) + return 0; + if (ASN1_parse_dump(out, str->data, str->length, indent, 0) <= 0) + ret = 0; + needlf = 0; + break; + + default: + ret = ASN1_STRING_print_ex(out, str, pctx->str_flags); + + } + if (!ret) + return 0; + if (needlf && BIO_puts(out, "\n") <= 0) + return 0; + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_scn.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_scn.c new file mode 100644 index 000000000..e1df2cfca --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_scn.c @@ -0,0 +1,65 @@ +/* + * Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include +#include "asn1_locl.h" + +/* + * General ASN1 structure recursive scanner: iterate through all fields + * passing details to a callback. + */ + +ASN1_SCTX *ASN1_SCTX_new(int (*scan_cb) (ASN1_SCTX *ctx)) +{ + ASN1_SCTX *ret = OPENSSL_zalloc(sizeof(*ret)); + + if (ret == NULL) { + ASN1err(ASN1_F_ASN1_SCTX_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + ret->scan_cb = scan_cb; + return ret; +} + +void ASN1_SCTX_free(ASN1_SCTX *p) +{ + OPENSSL_free(p); +} + +const ASN1_ITEM *ASN1_SCTX_get_item(ASN1_SCTX *p) +{ + return p->it; +} + +const ASN1_TEMPLATE *ASN1_SCTX_get_template(ASN1_SCTX *p) +{ + return p->tt; +} + +unsigned long ASN1_SCTX_get_flags(ASN1_SCTX *p) +{ + return p->flags; +} + +void ASN1_SCTX_set_app_data(ASN1_SCTX *p, void *data) +{ + p->app_data = data; +} + +void *ASN1_SCTX_get_app_data(ASN1_SCTX *p) +{ + return p->app_data; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_typ.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_typ.c new file mode 100644 index 000000000..98d987901 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_typ.c @@ -0,0 +1,84 @@ +/* + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include + +/* Declarations for string types */ + +#define IMPLEMENT_ASN1_STRING_FUNCTIONS(sname) \ + IMPLEMENT_ASN1_TYPE(sname) \ + IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(sname, sname, sname) \ +sname *sname##_new(void) \ +{ \ + return ASN1_STRING_type_new(V_##sname); \ +} \ +void sname##_free(sname *x) \ +{ \ + ASN1_STRING_free(x); \ +} + +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_OCTET_STRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_INTEGER) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_ENUMERATED) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_BIT_STRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UTF8STRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_PRINTABLESTRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_T61STRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_IA5STRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_GENERALSTRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UTCTIME) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_GENERALIZEDTIME) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_VISIBLESTRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UNIVERSALSTRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_BMPSTRING) + +IMPLEMENT_ASN1_TYPE(ASN1_NULL) +IMPLEMENT_ASN1_FUNCTIONS(ASN1_NULL) + +IMPLEMENT_ASN1_TYPE(ASN1_OBJECT) + +IMPLEMENT_ASN1_TYPE(ASN1_ANY) + +/* Just swallow an ASN1_SEQUENCE in an ASN1_STRING */ +IMPLEMENT_ASN1_TYPE(ASN1_SEQUENCE) + +IMPLEMENT_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE) + +/* Multistring types */ + +IMPLEMENT_ASN1_MSTRING(ASN1_PRINTABLE, B_ASN1_PRINTABLE) +IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE) + +IMPLEMENT_ASN1_MSTRING(DISPLAYTEXT, B_ASN1_DISPLAYTEXT) +IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DISPLAYTEXT) + +IMPLEMENT_ASN1_MSTRING(DIRECTORYSTRING, B_ASN1_DIRECTORYSTRING) +IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING) + +/* Three separate BOOLEAN type: normal, DEFAULT TRUE and DEFAULT FALSE */ +IMPLEMENT_ASN1_TYPE_ex(ASN1_BOOLEAN, ASN1_BOOLEAN, -1) +IMPLEMENT_ASN1_TYPE_ex(ASN1_TBOOLEAN, ASN1_BOOLEAN, 1) +IMPLEMENT_ASN1_TYPE_ex(ASN1_FBOOLEAN, ASN1_BOOLEAN, 0) + +/* Special, OCTET STRING with indefinite length constructed support */ + +IMPLEMENT_ASN1_TYPE_ex(ASN1_OCTET_STRING_NDEF, ASN1_OCTET_STRING, ASN1_TFLG_NDEF) + +ASN1_ITEM_TEMPLATE(ASN1_SEQUENCE_ANY) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, ASN1_SEQUENCE_ANY, ASN1_ANY) +ASN1_ITEM_TEMPLATE_END(ASN1_SEQUENCE_ANY) + +ASN1_ITEM_TEMPLATE(ASN1_SET_ANY) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, ASN1_SET_ANY, ASN1_ANY) +ASN1_ITEM_TEMPLATE_END(ASN1_SET_ANY) + +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY) +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SET_ANY, ASN1_SET_ANY) diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_utl.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_utl.c new file mode 100644 index 000000000..7ceecffce --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tasn_utl.c @@ -0,0 +1,253 @@ +/* + * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include "internal/refcount.h" +#include +#include +#include +#include +#include "asn1_locl.h" + +/* Utility functions for manipulating fields and offsets */ + +/* Add 'offset' to 'addr' */ +#define offset2ptr(addr, offset) (void *)(((char *) addr) + offset) + +/* + * Given an ASN1_ITEM CHOICE type return the selector value + */ + +int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + int *sel = offset2ptr(*pval, it->utype); + return *sel; +} + +/* + * Given an ASN1_ITEM CHOICE type set the selector value, return old value. + */ + +int asn1_set_choice_selector(ASN1_VALUE **pval, int value, + const ASN1_ITEM *it) +{ + int *sel, ret; + sel = offset2ptr(*pval, it->utype); + ret = *sel; + *sel = value; + return ret; +} + +/* + * Do atomic reference counting. The value 'op' decides what to do. + * If it is +1 then the count is incremented. + * If |op| is 0, lock is initialised and count is set to 1. + * If |op| is -1, count is decremented and the return value is the current + * reference count or 0 if no reference count is active. + * It returns -1 on initialisation error. + * Used by ASN1_SEQUENCE construct of X509, X509_REQ, X509_CRL objects + */ +int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it) +{ + const ASN1_AUX *aux; + CRYPTO_REF_COUNT *lck; + CRYPTO_RWLOCK **lock; + int ret = -1; + + if ((it->itype != ASN1_ITYPE_SEQUENCE) + && (it->itype != ASN1_ITYPE_NDEF_SEQUENCE)) + return 0; + aux = it->funcs; + if (!aux || !(aux->flags & ASN1_AFLG_REFCOUNT)) + return 0; + lck = offset2ptr(*pval, aux->ref_offset); + lock = offset2ptr(*pval, aux->ref_lock); + + switch (op) { + case 0: + *lck = ret = 1; + *lock = CRYPTO_THREAD_lock_new(); + if (*lock == NULL) { + ASN1err(ASN1_F_ASN1_DO_LOCK, ERR_R_MALLOC_FAILURE); + return -1; + } + break; + case 1: + if (!CRYPTO_UP_REF(lck, &ret, *lock)) + return -1; + break; + case -1: + if (!CRYPTO_DOWN_REF(lck, &ret, *lock)) + return -1; /* failed */ +#ifdef REF_PRINT + fprintf(stderr, "%p:%4d:%s\n", it, ret, it->sname); +#endif + REF_ASSERT_ISNT(ret < 0); + if (ret == 0) { + CRYPTO_THREAD_lock_free(*lock); + *lock = NULL; + } + break; + } + + return ret; +} + +static ASN1_ENCODING *asn1_get_enc_ptr(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + const ASN1_AUX *aux; + if (!pval || !*pval) + return NULL; + aux = it->funcs; + if (!aux || !(aux->flags & ASN1_AFLG_ENCODING)) + return NULL; + return offset2ptr(*pval, aux->enc_offset); +} + +void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + ASN1_ENCODING *enc; + enc = asn1_get_enc_ptr(pval, it); + if (enc) { + enc->enc = NULL; + enc->len = 0; + enc->modified = 1; + } +} + +void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + ASN1_ENCODING *enc; + enc = asn1_get_enc_ptr(pval, it); + if (enc) { + OPENSSL_free(enc->enc); + enc->enc = NULL; + enc->len = 0; + enc->modified = 1; + } +} + +int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen, + const ASN1_ITEM *it) +{ + ASN1_ENCODING *enc; + enc = asn1_get_enc_ptr(pval, it); + if (!enc) + return 1; + + OPENSSL_free(enc->enc); + if ((enc->enc = OPENSSL_malloc(inlen)) == NULL) { + ASN1err(ASN1_F_ASN1_ENC_SAVE, ERR_R_MALLOC_FAILURE); + return 0; + } + memcpy(enc->enc, in, inlen); + enc->len = inlen; + enc->modified = 0; + + return 1; +} + +int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval, + const ASN1_ITEM *it) +{ + ASN1_ENCODING *enc; + enc = asn1_get_enc_ptr(pval, it); + if (!enc || enc->modified) + return 0; + if (out) { + memcpy(*out, enc->enc, enc->len); + *out += enc->len; + } + if (len) + *len = enc->len; + return 1; +} + +/* Given an ASN1_TEMPLATE get a pointer to a field */ +ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) +{ + ASN1_VALUE **pvaltmp; + pvaltmp = offset2ptr(*pval, tt->offset); + /* + * NOTE for BOOLEAN types the field is just a plain int so we can't + * return int **, so settle for (int *). + */ + return pvaltmp; +} + +/* + * Handle ANY DEFINED BY template, find the selector, look up the relevant + * ASN1_TEMPLATE in the table and return it. + */ + +const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, + int nullerr) +{ + const ASN1_ADB *adb; + const ASN1_ADB_TABLE *atbl; + long selector; + ASN1_VALUE **sfld; + int i; + if (!(tt->flags & ASN1_TFLG_ADB_MASK)) + return tt; + + /* Else ANY DEFINED BY ... get the table */ + adb = ASN1_ADB_ptr(tt->item); + + /* Get the selector field */ + sfld = offset2ptr(*pval, adb->offset); + + /* Check if NULL */ + if (*sfld == NULL) { + if (!adb->null_tt) + goto err; + return adb->null_tt; + } + + /* + * Convert type to a long: NB: don't check for NID_undef here because it + * might be a legitimate value in the table + */ + if (tt->flags & ASN1_TFLG_ADB_OID) + selector = OBJ_obj2nid((ASN1_OBJECT *)*sfld); + else + selector = ASN1_INTEGER_get((ASN1_INTEGER *)*sfld); + + /* Let application callback translate value */ + if (adb->adb_cb != NULL && adb->adb_cb(&selector) == 0) { + ASN1err(ASN1_F_ASN1_DO_ADB, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE); + return NULL; + } + + /* + * Try to find matching entry in table Maybe should check application + * types first to allow application override? Might also be useful to + * have a flag which indicates table is sorted and we can do a binary + * search. For now stick to a linear search. + */ + + for (atbl = adb->tbl, i = 0; i < adb->tblcount; i++, atbl++) + if (atbl->value == selector) + return &atbl->tt; + + /* FIXME: need to search application table too */ + + /* No match, return default type */ + if (!adb->default_tt) + goto err; + return adb->default_tt; + + err: + /* FIXME: should log the value or OID of unsupported type */ + if (nullerr) + ASN1err(ASN1_F_ASN1_DO_ADB, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE); + return NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tbl_standard.h b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tbl_standard.h new file mode 100644 index 000000000..777a73448 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/tbl_standard.h @@ -0,0 +1,61 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* size limits: this stuff is taken straight from RFC3280 */ + +#define ub_name 32768 +#define ub_common_name 64 +#define ub_locality_name 128 +#define ub_state_name 128 +#define ub_organization_name 64 +#define ub_organization_unit_name 64 +#define ub_title 64 +#define ub_email_address 128 +#define ub_serial_number 64 + +/* From RFC4524 */ + +#define ub_rfc822_mailbox 256 + +/* This table must be kept in NID order */ + +static const ASN1_STRING_TABLE tbl_standard[] = { + {NID_commonName, 1, ub_common_name, DIRSTRING_TYPE, 0}, + {NID_countryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK}, + {NID_localityName, 1, ub_locality_name, DIRSTRING_TYPE, 0}, + {NID_stateOrProvinceName, 1, ub_state_name, DIRSTRING_TYPE, 0}, + {NID_organizationName, 1, ub_organization_name, DIRSTRING_TYPE, 0}, + {NID_organizationalUnitName, 1, ub_organization_unit_name, DIRSTRING_TYPE, + 0}, + {NID_pkcs9_emailAddress, 1, ub_email_address, B_ASN1_IA5STRING, + STABLE_NO_MASK}, + {NID_pkcs9_unstructuredName, 1, -1, PKCS9STRING_TYPE, 0}, + {NID_pkcs9_challengePassword, 1, -1, PKCS9STRING_TYPE, 0}, + {NID_pkcs9_unstructuredAddress, 1, -1, DIRSTRING_TYPE, 0}, + {NID_givenName, 1, ub_name, DIRSTRING_TYPE, 0}, + {NID_surname, 1, ub_name, DIRSTRING_TYPE, 0}, + {NID_initials, 1, ub_name, DIRSTRING_TYPE, 0}, + {NID_serialNumber, 1, ub_serial_number, B_ASN1_PRINTABLESTRING, + STABLE_NO_MASK}, + {NID_friendlyName, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK}, + {NID_name, 1, ub_name, DIRSTRING_TYPE, 0}, + {NID_dnQualifier, -1, -1, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK}, + {NID_domainComponent, 1, -1, B_ASN1_IA5STRING, STABLE_NO_MASK}, + {NID_ms_csp_name, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK}, + {NID_rfc822Mailbox, 1, ub_rfc822_mailbox, B_ASN1_IA5STRING, + STABLE_NO_MASK}, + {NID_jurisdictionCountryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK}, + {NID_INN, 1, 12, B_ASN1_NUMERICSTRING, STABLE_NO_MASK}, + {NID_OGRN, 1, 13, B_ASN1_NUMERICSTRING, STABLE_NO_MASK}, + {NID_SNILS, 1, 11, B_ASN1_NUMERICSTRING, STABLE_NO_MASK}, + {NID_countryCode3c, 3, 3, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK}, + {NID_countryCode3n, 3, 3, B_ASN1_NUMERICSTRING, STABLE_NO_MASK}, + {NID_dnsName, 0, -1, B_ASN1_UTF8STRING, STABLE_NO_MASK} +}; + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_algor.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_algor.c new file mode 100644 index 000000000..853d45b8b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_algor.c @@ -0,0 +1,94 @@ +/* + * Copyright 1998-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include "internal/evp_int.h" + +ASN1_SEQUENCE(X509_ALGOR) = { + ASN1_SIMPLE(X509_ALGOR, algorithm, ASN1_OBJECT), + ASN1_OPT(X509_ALGOR, parameter, ASN1_ANY) +} ASN1_SEQUENCE_END(X509_ALGOR) + +ASN1_ITEM_TEMPLATE(X509_ALGORS) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, algorithms, X509_ALGOR) +ASN1_ITEM_TEMPLATE_END(X509_ALGORS) + +IMPLEMENT_ASN1_FUNCTIONS(X509_ALGOR) +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(X509_ALGORS, X509_ALGORS, X509_ALGORS) +IMPLEMENT_ASN1_DUP_FUNCTION(X509_ALGOR) + +int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype, void *pval) +{ + if (alg == NULL) + return 0; + + if (ptype != V_ASN1_UNDEF) { + if (alg->parameter == NULL) + alg->parameter = ASN1_TYPE_new(); + if (alg->parameter == NULL) + return 0; + } + + ASN1_OBJECT_free(alg->algorithm); + alg->algorithm = aobj; + + if (ptype == 0) + return 1; + if (ptype == V_ASN1_UNDEF) { + ASN1_TYPE_free(alg->parameter); + alg->parameter = NULL; + } else + ASN1_TYPE_set(alg->parameter, ptype, pval); + return 1; +} + +void X509_ALGOR_get0(const ASN1_OBJECT **paobj, int *pptype, + const void **ppval, const X509_ALGOR *algor) +{ + if (paobj) + *paobj = algor->algorithm; + if (pptype) { + if (algor->parameter == NULL) { + *pptype = V_ASN1_UNDEF; + return; + } else + *pptype = algor->parameter->type; + if (ppval) + *ppval = algor->parameter->value.ptr; + } +} + +/* Set up an X509_ALGOR DigestAlgorithmIdentifier from an EVP_MD */ + +void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md) +{ + int param_type; + + if (md->flags & EVP_MD_FLAG_DIGALGID_ABSENT) + param_type = V_ASN1_UNDEF; + else + param_type = V_ASN1_NULL; + + X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, NULL); + +} + +int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b) +{ + int rv; + rv = OBJ_cmp(a->algorithm, b->algorithm); + if (rv) + return rv; + if (!a->parameter && !b->parameter) + return 0; + return ASN1_TYPE_cmp(a->parameter, b->parameter); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_bignum.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_bignum.c new file mode 100644 index 000000000..da57e77a7 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_bignum.c @@ -0,0 +1,146 @@ +/* + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include + +/* + * Custom primitive type for BIGNUM handling. This reads in an ASN1_INTEGER + * as a BIGNUM directly. Currently it ignores the sign which isn't a problem + * since all BIGNUMs used are non negative and anything that looks negative + * is normally due to an encoding error. + */ + +#define BN_SENSITIVE 1 + +static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it); +static int bn_secure_new(ASN1_VALUE **pval, const ASN1_ITEM *it); +static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it); + +static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, + const ASN1_ITEM *it); +static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, + int utype, char *free_cont, const ASN1_ITEM *it); +static int bn_secure_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, + int utype, char *free_cont, const ASN1_ITEM *it); +static int bn_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, + int indent, const ASN1_PCTX *pctx); + +static ASN1_PRIMITIVE_FUNCS bignum_pf = { + NULL, 0, + bn_new, + bn_free, + 0, + bn_c2i, + bn_i2c, + bn_print +}; + +static ASN1_PRIMITIVE_FUNCS cbignum_pf = { + NULL, 0, + bn_secure_new, + bn_free, + 0, + bn_secure_c2i, + bn_i2c, + bn_print +}; + +ASN1_ITEM_start(BIGNUM) + ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, 0, "BIGNUM" +ASN1_ITEM_end(BIGNUM) + +ASN1_ITEM_start(CBIGNUM) + ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &cbignum_pf, BN_SENSITIVE, "CBIGNUM" +ASN1_ITEM_end(CBIGNUM) + +static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + *pval = (ASN1_VALUE *)BN_new(); + if (*pval != NULL) + return 1; + else + return 0; +} + +static int bn_secure_new(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + *pval = (ASN1_VALUE *)BN_secure_new(); + if (*pval != NULL) + return 1; + else + return 0; +} + +static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + if (!*pval) + return; + if (it->size & BN_SENSITIVE) + BN_clear_free((BIGNUM *)*pval); + else + BN_free((BIGNUM *)*pval); + *pval = NULL; +} + +static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, + const ASN1_ITEM *it) +{ + BIGNUM *bn; + int pad; + if (!*pval) + return -1; + bn = (BIGNUM *)*pval; + /* If MSB set in an octet we need a padding byte */ + if (BN_num_bits(bn) & 0x7) + pad = 0; + else + pad = 1; + if (cont) { + if (pad) + *cont++ = 0; + BN_bn2bin(bn, cont); + } + return pad + BN_num_bytes(bn); +} + +static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, + int utype, char *free_cont, const ASN1_ITEM *it) +{ + BIGNUM *bn; + + if (*pval == NULL && !bn_new(pval, it)) + return 0; + bn = (BIGNUM *)*pval; + if (!BN_bin2bn(cont, len, bn)) { + bn_free(pval, it); + return 0; + } + return 1; +} + +static int bn_secure_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, + int utype, char *free_cont, const ASN1_ITEM *it) +{ + if (!*pval) + bn_secure_new(pval, it); + return bn_c2i(pval, cont, len, utype, free_cont, it); +} + +static int bn_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, + int indent, const ASN1_PCTX *pctx) +{ + if (!BN_print(out, *(BIGNUM **)pval)) + return 0; + if (BIO_puts(out, "\n") <= 0) + return 0; + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_info.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_info.c new file mode 100644 index 000000000..8d99f07c6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_info.c @@ -0,0 +1,39 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include + +X509_INFO *X509_INFO_new(void) +{ + X509_INFO *ret; + + ret = OPENSSL_zalloc(sizeof(*ret)); + if (ret == NULL) { + ASN1err(ASN1_F_X509_INFO_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + return ret; +} + +void X509_INFO_free(X509_INFO *x) +{ + if (x == NULL) + return; + + X509_free(x->x509); + X509_CRL_free(x->crl); + X509_PKEY_free(x->x_pkey); + OPENSSL_free(x->enc_data); + OPENSSL_free(x); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_int64.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_int64.c new file mode 100644 index 000000000..0ee552cf0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_int64.c @@ -0,0 +1,291 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include "internal/numbers.h" +#include +#include +#include "asn1_locl.h" + +/* + * Custom primitive types for handling int32_t, int64_t, uint32_t, uint64_t. + * This converts between an ASN1_INTEGER and those types directly. + * This is preferred to using the LONG / ZLONG primitives. + */ + +/* + * We abuse the ASN1_ITEM fields |size| as a flags field + */ +#define INTxx_FLAG_ZERO_DEFAULT (1<<0) +#define INTxx_FLAG_SIGNED (1<<1) + +static int uint64_new(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + if ((*pval = (ASN1_VALUE *)OPENSSL_zalloc(sizeof(uint64_t))) == NULL) { + ASN1err(ASN1_F_UINT64_NEW, ERR_R_MALLOC_FAILURE); + return 0; + } + return 1; +} + +static void uint64_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + OPENSSL_free(*pval); + *pval = NULL; +} + +static void uint64_clear(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + **(uint64_t **)pval = 0; +} + +static int uint64_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, + const ASN1_ITEM *it) +{ + uint64_t utmp; + int neg = 0; + /* this exists to bypass broken gcc optimization */ + char *cp = (char *)*pval; + + /* use memcpy, because we may not be uint64_t aligned */ + memcpy(&utmp, cp, sizeof(utmp)); + + if ((it->size & INTxx_FLAG_ZERO_DEFAULT) == INTxx_FLAG_ZERO_DEFAULT + && utmp == 0) + return -1; + if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED + && (int64_t)utmp < 0) { + /* i2c_uint64_int() assumes positive values */ + utmp = 0 - utmp; + neg = 1; + } + + return i2c_uint64_int(cont, utmp, neg); +} + +static int uint64_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, + int utype, char *free_cont, const ASN1_ITEM *it) +{ + uint64_t utmp = 0; + char *cp; + int neg = 0; + + if (*pval == NULL && !uint64_new(pval, it)) + return 0; + + cp = (char *)*pval; + + /* + * Strictly speaking, zero length is malformed. However, long_c2i + * (x_long.c) encodes 0 as a zero length INTEGER (wrongly, of course), + * so for the sake of backward compatibility, we still decode zero + * length INTEGERs as the number zero. + */ + if (len == 0) + goto long_compat; + + if (!c2i_uint64_int(&utmp, &neg, &cont, len)) + return 0; + if ((it->size & INTxx_FLAG_SIGNED) == 0 && neg) { + ASN1err(ASN1_F_UINT64_C2I, ASN1_R_ILLEGAL_NEGATIVE_VALUE); + return 0; + } + if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED + && !neg && utmp > INT64_MAX) { + ASN1err(ASN1_F_UINT64_C2I, ASN1_R_TOO_LARGE); + return 0; + } + if (neg) + /* c2i_uint64_int() returns positive values */ + utmp = 0 - utmp; + + long_compat: + memcpy(cp, &utmp, sizeof(utmp)); + return 1; +} + +static int uint64_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, + int indent, const ASN1_PCTX *pctx) +{ + if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED) + return BIO_printf(out, "%jd\n", **(int64_t **)pval); + return BIO_printf(out, "%ju\n", **(uint64_t **)pval); +} + +/* 32-bit variants */ + +static int uint32_new(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + if ((*pval = (ASN1_VALUE *)OPENSSL_zalloc(sizeof(uint32_t))) == NULL) { + ASN1err(ASN1_F_UINT32_NEW, ERR_R_MALLOC_FAILURE); + return 0; + } + return 1; +} + +static void uint32_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + OPENSSL_free(*pval); + *pval = NULL; +} + +static void uint32_clear(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + **(uint32_t **)pval = 0; +} + +static int uint32_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, + const ASN1_ITEM *it) +{ + uint32_t utmp; + int neg = 0; + /* this exists to bypass broken gcc optimization */ + char *cp = (char *)*pval; + + /* use memcpy, because we may not be uint32_t aligned */ + memcpy(&utmp, cp, sizeof(utmp)); + + if ((it->size & INTxx_FLAG_ZERO_DEFAULT) == INTxx_FLAG_ZERO_DEFAULT + && utmp == 0) + return -1; + if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED + && (int32_t)utmp < 0) { + /* i2c_uint64_int() assumes positive values */ + utmp = 0 - utmp; + neg = 1; + } + + return i2c_uint64_int(cont, (uint64_t)utmp, neg); +} + +/* + * Absolute value of INT32_MIN: we can't just use -INT32_MIN as it produces + * overflow warnings. + */ + +#define ABS_INT32_MIN ((uint32_t)INT32_MAX + 1) + +static int uint32_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, + int utype, char *free_cont, const ASN1_ITEM *it) +{ + uint64_t utmp = 0; + uint32_t utmp2 = 0; + char *cp; + int neg = 0; + + if (*pval == NULL && !uint64_new(pval, it)) + return 0; + + cp = (char *)*pval; + + /* + * Strictly speaking, zero length is malformed. However, long_c2i + * (x_long.c) encodes 0 as a zero length INTEGER (wrongly, of course), + * so for the sake of backward compatibility, we still decode zero + * length INTEGERs as the number zero. + */ + if (len == 0) + goto long_compat; + + if (!c2i_uint64_int(&utmp, &neg, &cont, len)) + return 0; + if ((it->size & INTxx_FLAG_SIGNED) == 0 && neg) { + ASN1err(ASN1_F_UINT32_C2I, ASN1_R_ILLEGAL_NEGATIVE_VALUE); + return 0; + } + if (neg) { + if (utmp > ABS_INT32_MIN) { + ASN1err(ASN1_F_UINT32_C2I, ASN1_R_TOO_SMALL); + return 0; + } + utmp = 0 - utmp; + } else { + if (((it->size & INTxx_FLAG_SIGNED) != 0 && utmp > INT32_MAX) + || ((it->size & INTxx_FLAG_SIGNED) == 0 && utmp > UINT32_MAX)) { + ASN1err(ASN1_F_UINT32_C2I, ASN1_R_TOO_LARGE); + return 0; + } + } + + long_compat: + utmp2 = (uint32_t)utmp; + memcpy(cp, &utmp2, sizeof(utmp2)); + return 1; +} + +static int uint32_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, + int indent, const ASN1_PCTX *pctx) +{ + if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED) + return BIO_printf(out, "%d\n", **(int32_t **)pval); + return BIO_printf(out, "%u\n", **(uint32_t **)pval); +} + + +/* Define the primitives themselves */ + +static ASN1_PRIMITIVE_FUNCS uint32_pf = { + NULL, 0, + uint32_new, + uint32_free, + uint32_clear, + uint32_c2i, + uint32_i2c, + uint32_print +}; + +static ASN1_PRIMITIVE_FUNCS uint64_pf = { + NULL, 0, + uint64_new, + uint64_free, + uint64_clear, + uint64_c2i, + uint64_i2c, + uint64_print +}; + +ASN1_ITEM_start(INT32) + ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint32_pf, + INTxx_FLAG_SIGNED, "INT32" +ASN1_ITEM_end(INT32) + +ASN1_ITEM_start(UINT32) + ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint32_pf, 0, "UINT32" +ASN1_ITEM_end(UINT32) + +ASN1_ITEM_start(INT64) + ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint64_pf, + INTxx_FLAG_SIGNED, "INT64" +ASN1_ITEM_end(INT64) + +ASN1_ITEM_start(UINT64) + ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint64_pf, 0, "UINT64" +ASN1_ITEM_end(UINT64) + +ASN1_ITEM_start(ZINT32) + ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint32_pf, + INTxx_FLAG_ZERO_DEFAULT|INTxx_FLAG_SIGNED, "ZINT32" +ASN1_ITEM_end(ZINT32) + +ASN1_ITEM_start(ZUINT32) + ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint32_pf, + INTxx_FLAG_ZERO_DEFAULT, "ZUINT32" +ASN1_ITEM_end(ZUINT32) + +ASN1_ITEM_start(ZINT64) + ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint64_pf, + INTxx_FLAG_ZERO_DEFAULT|INTxx_FLAG_SIGNED, "ZINT64" +ASN1_ITEM_end(ZINT64) + +ASN1_ITEM_start(ZUINT64) + ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint64_pf, + INTxx_FLAG_ZERO_DEFAULT, "ZUINT64" +ASN1_ITEM_end(ZUINT64) + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_long.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_long.c new file mode 100644 index 000000000..bf9371ef5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_long.c @@ -0,0 +1,201 @@ +/* + * Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include + +#if !(OPENSSL_API_COMPAT < 0x10200000L) +NON_EMPTY_TRANSLATION_UNIT +#else + +#define COPY_SIZE(a, b) (sizeof(a) < sizeof(b) ? sizeof(a) : sizeof(b)) + +/* + * Custom primitive type for long handling. This converts between an + * ASN1_INTEGER and a long directly. + */ + +static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it); +static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it); + +static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, + const ASN1_ITEM *it); +static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, + int utype, char *free_cont, const ASN1_ITEM *it); +static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, + int indent, const ASN1_PCTX *pctx); + +static ASN1_PRIMITIVE_FUNCS long_pf = { + NULL, 0, + long_new, + long_free, + long_free, /* Clear should set to initial value */ + long_c2i, + long_i2c, + long_print +}; + +ASN1_ITEM_start(LONG) + ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, ASN1_LONG_UNDEF, "LONG" +ASN1_ITEM_end(LONG) + +ASN1_ITEM_start(ZLONG) + ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, 0, "ZLONG" +ASN1_ITEM_end(ZLONG) + +static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + memcpy(pval, &it->size, COPY_SIZE(*pval, it->size)); + return 1; +} + +static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + memcpy(pval, &it->size, COPY_SIZE(*pval, it->size)); +} + +/* + * Originally BN_num_bits_word was called to perform this operation, but + * trouble is that there is no guarantee that sizeof(long) equals to + * sizeof(BN_ULONG). BN_ULONG is a configurable type that can be as wide + * as long, but also double or half... + */ +static int num_bits_ulong(unsigned long value) +{ + size_t i; + unsigned long ret = 0; + + /* + * It is argued that *on average* constant counter loop performs + * not worse [if not better] than one with conditional break or + * mask-n-table-lookup-style, because of branch misprediction + * penalties. + */ + for (i = 0; i < sizeof(value) * 8; i++) { + ret += (value != 0); + value >>= 1; + } + + return (int)ret; +} + +static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, + const ASN1_ITEM *it) +{ + long ltmp; + unsigned long utmp, sign; + int clen, pad, i; + + memcpy(<mp, pval, COPY_SIZE(*pval, ltmp)); + if (ltmp == it->size) + return -1; + /* + * Convert the long to positive: we subtract one if negative so we can + * cleanly handle the padding if only the MSB of the leading octet is + * set. + */ + if (ltmp < 0) { + sign = 0xff; + utmp = 0 - (unsigned long)ltmp - 1; + } else { + sign = 0; + utmp = ltmp; + } + clen = num_bits_ulong(utmp); + /* If MSB of leading octet set we need to pad */ + if (!(clen & 0x7)) + pad = 1; + else + pad = 0; + + /* Convert number of bits to number of octets */ + clen = (clen + 7) >> 3; + + if (cont != NULL) { + if (pad) + *cont++ = (unsigned char)sign; + for (i = clen - 1; i >= 0; i--) { + cont[i] = (unsigned char)(utmp ^ sign); + utmp >>= 8; + } + } + return clen + pad; +} + +static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, + int utype, char *free_cont, const ASN1_ITEM *it) +{ + int i; + long ltmp; + unsigned long utmp = 0, sign = 0x100; + + if (len > 1) { + /* + * Check possible pad byte. Worst case, we're skipping past actual + * content, but since that's only with 0x00 and 0xff and we set neg + * accordingly, the result will be correct in the end anyway. + */ + switch (cont[0]) { + case 0xff: + cont++; + len--; + sign = 0xff; + break; + case 0: + cont++; + len--; + sign = 0; + break; + } + } + if (len > (int)sizeof(long)) { + ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG); + return 0; + } + + if (sign == 0x100) { + /* Is it negative? */ + if (len && (cont[0] & 0x80)) + sign = 0xff; + else + sign = 0; + } else if (((sign ^ cont[0]) & 0x80) == 0) { /* same sign bit? */ + ASN1err(ASN1_F_LONG_C2I, ASN1_R_ILLEGAL_PADDING); + return 0; + } + utmp = 0; + for (i = 0; i < len; i++) { + utmp <<= 8; + utmp |= cont[i] ^ sign; + } + ltmp = (long)utmp; + if (ltmp < 0) { + ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG); + return 0; + } + if (sign) + ltmp = -ltmp - 1; + if (ltmp == it->size) { + ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG); + return 0; + } + memcpy(pval, <mp, COPY_SIZE(*pval, ltmp)); + return 1; +} + +static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, + int indent, const ASN1_PCTX *pctx) +{ + long l; + + memcpy(&l, pval, COPY_SIZE(*pval, l)); + return BIO_printf(out, "%ld\n", l); +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_pkey.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_pkey.c new file mode 100644 index 000000000..593049f0f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_pkey.c @@ -0,0 +1,47 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include + +X509_PKEY *X509_PKEY_new(void) +{ + X509_PKEY *ret = NULL; + + ret = OPENSSL_zalloc(sizeof(*ret)); + if (ret == NULL) + goto err; + + ret->enc_algor = X509_ALGOR_new(); + ret->enc_pkey = ASN1_OCTET_STRING_new(); + if (ret->enc_algor == NULL || ret->enc_pkey == NULL) + goto err; + + return ret; +err: + X509_PKEY_free(ret); + ASN1err(ASN1_F_X509_PKEY_NEW, ERR_R_MALLOC_FAILURE); + return NULL; +} + +void X509_PKEY_free(X509_PKEY *x) +{ + if (x == NULL) + return; + + X509_ALGOR_free(x->enc_algor); + ASN1_OCTET_STRING_free(x->enc_pkey); + EVP_PKEY_free(x->dec_pkey); + if (x->key_free) + OPENSSL_free(x->key_data); + OPENSSL_free(x); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_sig.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_sig.c new file mode 100644 index 000000000..e465cf2d4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_sig.c @@ -0,0 +1,39 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include "internal/x509_int.h" + +ASN1_SEQUENCE(X509_SIG) = { + ASN1_SIMPLE(X509_SIG, algor, X509_ALGOR), + ASN1_SIMPLE(X509_SIG, digest, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(X509_SIG) + +IMPLEMENT_ASN1_FUNCTIONS(X509_SIG) + +void X509_SIG_get0(const X509_SIG *sig, const X509_ALGOR **palg, + const ASN1_OCTET_STRING **pdigest) +{ + if (palg) + *palg = sig->algor; + if (pdigest) + *pdigest = sig->digest; +} + +void X509_SIG_getm(X509_SIG *sig, X509_ALGOR **palg, + ASN1_OCTET_STRING **pdigest) +{ + if (palg) + *palg = sig->algor; + if (pdigest) + *pdigest = sig->digest; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_spki.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_spki.c new file mode 100644 index 000000000..0d72a3f3a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_spki.c @@ -0,0 +1,28 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include + +ASN1_SEQUENCE(NETSCAPE_SPKAC) = { + ASN1_SIMPLE(NETSCAPE_SPKAC, pubkey, X509_PUBKEY), + ASN1_SIMPLE(NETSCAPE_SPKAC, challenge, ASN1_IA5STRING) +} ASN1_SEQUENCE_END(NETSCAPE_SPKAC) + +IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_SPKAC) + +ASN1_SEQUENCE(NETSCAPE_SPKI) = { + ASN1_SIMPLE(NETSCAPE_SPKI, spkac, NETSCAPE_SPKAC), + ASN1_EMBED(NETSCAPE_SPKI, sig_algor, X509_ALGOR), + ASN1_SIMPLE(NETSCAPE_SPKI, signature, ASN1_BIT_STRING) +} ASN1_SEQUENCE_END(NETSCAPE_SPKI) + +IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_SPKI) diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_val.c b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_val.c new file mode 100644 index 000000000..d1f1d3bff --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/asn1/x_val.c @@ -0,0 +1,20 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include + +ASN1_SEQUENCE(X509_VAL) = { + ASN1_SIMPLE(X509_VAL, notBefore, ASN1_TIME), + ASN1_SIMPLE(X509_VAL, notAfter, ASN1_TIME) +} ASN1_SEQUENCE_END(X509_VAL) + +IMPLEMENT_ASN1_FUNCTIONS(X509_VAL) diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/async/arch/async_null.c b/trunk/3rdparty/openssl-1.1-fit/crypto/async/arch/async_null.c new file mode 100644 index 000000000..3eaf170f2 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/async/arch/async_null.c @@ -0,0 +1,23 @@ +/* + * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* This must be the first #include file */ +#include "../async_locl.h" + +#ifdef ASYNC_NULL +int ASYNC_is_capable(void) +{ + return 0; +} + +void async_local_cleanup(void) +{ +} +#endif + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/async/arch/async_null.h b/trunk/3rdparty/openssl-1.1-fit/crypto/async/arch/async_null.h new file mode 100644 index 000000000..aef40b5d9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/async/arch/async_null.h @@ -0,0 +1,30 @@ +/* + * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +/* + * If we haven't managed to detect any other async architecture then we default + * to NULL. + */ +#ifndef ASYNC_ARCH +# define ASYNC_NULL +# define ASYNC_ARCH + +typedef struct async_fibre_st { + int dummy; +} async_fibre; + + +# define async_fibre_swapcontext(o,n,r) 0 +# define async_fibre_makecontext(c) 0 +# define async_fibre_free(f) +# define async_fibre_init_dispatcher(f) + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/async/arch/async_posix.c b/trunk/3rdparty/openssl-1.1-fit/crypto/async/arch/async_posix.c new file mode 100644 index 000000000..02c342d3d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/async/arch/async_posix.c @@ -0,0 +1,58 @@ +/* + * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* This must be the first #include file */ +#include "../async_locl.h" + +#ifdef ASYNC_POSIX + +# include +# include + +#define STACKSIZE 32768 + +int ASYNC_is_capable(void) +{ + ucontext_t ctx; + + /* + * Some platforms provide getcontext() but it does not work (notably + * MacOSX PPC64). Check for a working getcontext(); + */ + return getcontext(&ctx) == 0; +} + +void async_local_cleanup(void) +{ +} + +int async_fibre_makecontext(async_fibre *fibre) +{ + fibre->env_init = 0; + if (getcontext(&fibre->fibre) == 0) { + fibre->fibre.uc_stack.ss_sp = OPENSSL_malloc(STACKSIZE); + if (fibre->fibre.uc_stack.ss_sp != NULL) { + fibre->fibre.uc_stack.ss_size = STACKSIZE; + fibre->fibre.uc_link = NULL; + makecontext(&fibre->fibre, async_start_func, 0); + return 1; + } + } else { + fibre->fibre.uc_stack.ss_sp = NULL; + } + return 0; +} + +void async_fibre_free(async_fibre *fibre) +{ + OPENSSL_free(fibre->fibre.uc_stack.ss_sp); + fibre->fibre.uc_stack.ss_sp = NULL; +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/async/arch/async_posix.h b/trunk/3rdparty/openssl-1.1-fit/crypto/async/arch/async_posix.h new file mode 100644 index 000000000..62449fe60 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/async/arch/async_posix.h @@ -0,0 +1,58 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OPENSSL_ASYNC_ARCH_ASYNC_POSIX_H +#define OPENSSL_ASYNC_ARCH_ASYNC_POSIX_H +#include + +#if defined(OPENSSL_SYS_UNIX) \ + && defined(OPENSSL_THREADS) && !defined(OPENSSL_NO_ASYNC) \ + && !defined(__ANDROID__) && !defined(__OpenBSD__) + +# include + +# if _POSIX_VERSION >= 200112L \ + && (_POSIX_VERSION < 200809L || defined(__GLIBC__)) + +# include + +# define ASYNC_POSIX +# define ASYNC_ARCH + +# include +# include + +typedef struct async_fibre_st { + ucontext_t fibre; + jmp_buf env; + int env_init; +} async_fibre; + +static ossl_inline int async_fibre_swapcontext(async_fibre *o, async_fibre *n, int r) +{ + o->env_init = 1; + + if (!r || !_setjmp(o->env)) { + if (n->env_init) + _longjmp(n->env, 1); + else + setcontext(&n->fibre); + } + + return 1; +} + +# define async_fibre_init_dispatcher(d) + +int async_fibre_makecontext(async_fibre *fibre); +void async_fibre_free(async_fibre *fibre); + +# endif +#endif +#endif /* OPENSSL_ASYNC_ARCH_ASYNC_POSIX_H */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/async/arch/async_win.c b/trunk/3rdparty/openssl-1.1-fit/crypto/async/arch/async_win.c new file mode 100644 index 000000000..077d56ced --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/async/arch/async_win.c @@ -0,0 +1,55 @@ +/* + * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* This must be the first #include file */ +#include "../async_locl.h" + +#ifdef ASYNC_WIN + +# include +# include "internal/cryptlib.h" + +int ASYNC_is_capable(void) +{ + return 1; +} + +void async_local_cleanup(void) +{ + async_ctx *ctx = async_get_ctx(); + if (ctx != NULL) { + async_fibre *fibre = &ctx->dispatcher; + if (fibre != NULL && fibre->fibre != NULL && fibre->converted) { + ConvertFiberToThread(); + fibre->fibre = NULL; + } + } +} + +int async_fibre_init_dispatcher(async_fibre *fibre) +{ + fibre->fibre = ConvertThreadToFiber(NULL); + if (fibre->fibre == NULL) { + fibre->converted = 0; + fibre->fibre = GetCurrentFiber(); + if (fibre->fibre == NULL) + return 0; + } else { + fibre->converted = 1; + } + + return 1; +} + +VOID CALLBACK async_start_func_win(PVOID unused) +{ + async_start_func(); +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/async/arch/async_win.h b/trunk/3rdparty/openssl-1.1-fit/crypto/async/arch/async_win.h new file mode 100644 index 000000000..61cfdd72d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/async/arch/async_win.h @@ -0,0 +1,36 @@ +/* + * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This is the same detection used in cryptlib to set up the thread local + * storage that we depend on, so just copy that + */ +#if defined(_WIN32) && !defined(OPENSSL_NO_ASYNC) +#include +# define ASYNC_WIN +# define ASYNC_ARCH + +# include +# include "internal/cryptlib.h" + +typedef struct async_fibre_st { + LPVOID fibre; + int converted; +} async_fibre; + +# define async_fibre_swapcontext(o,n,r) \ + (SwitchToFiber((n)->fibre), 1) +# define async_fibre_makecontext(c) \ + ((c)->fibre = CreateFiber(0, async_start_func_win, 0)) +# define async_fibre_free(f) (DeleteFiber((f)->fibre)) + +int async_fibre_init_dispatcher(async_fibre *fibre); +VOID CALLBACK async_start_func_win(PVOID unused); + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/async/async.c b/trunk/3rdparty/openssl-1.1-fit/crypto/async/async.c new file mode 100644 index 000000000..1d83e4576 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/async/async.c @@ -0,0 +1,451 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Without this we start getting longjmp crashes because it thinks we're jumping + * up the stack when in fact we are jumping to an entirely different stack. The + * cost of this is not having certain buffer overrun/underrun checks etc for + * this source file :-( + */ +#undef _FORTIFY_SOURCE + +/* This must be the first #include file */ +#include "async_locl.h" + +#include +#include "internal/cryptlib_int.h" +#include + +#define ASYNC_JOB_RUNNING 0 +#define ASYNC_JOB_PAUSING 1 +#define ASYNC_JOB_PAUSED 2 +#define ASYNC_JOB_STOPPING 3 + +static CRYPTO_THREAD_LOCAL ctxkey; +static CRYPTO_THREAD_LOCAL poolkey; + +static async_ctx *async_ctx_new(void) +{ + async_ctx *nctx; + + if (!ossl_init_thread_start(OPENSSL_INIT_THREAD_ASYNC)) + return NULL; + + nctx = OPENSSL_malloc(sizeof(*nctx)); + if (nctx == NULL) { + ASYNCerr(ASYNC_F_ASYNC_CTX_NEW, ERR_R_MALLOC_FAILURE); + goto err; + } + + async_fibre_init_dispatcher(&nctx->dispatcher); + nctx->currjob = NULL; + nctx->blocked = 0; + if (!CRYPTO_THREAD_set_local(&ctxkey, nctx)) + goto err; + + return nctx; +err: + OPENSSL_free(nctx); + + return NULL; +} + +async_ctx *async_get_ctx(void) +{ + return (async_ctx *)CRYPTO_THREAD_get_local(&ctxkey); +} + +static int async_ctx_free(void) +{ + async_ctx *ctx; + + ctx = async_get_ctx(); + + if (!CRYPTO_THREAD_set_local(&ctxkey, NULL)) + return 0; + + OPENSSL_free(ctx); + + return 1; +} + +static ASYNC_JOB *async_job_new(void) +{ + ASYNC_JOB *job = NULL; + + job = OPENSSL_zalloc(sizeof(*job)); + if (job == NULL) { + ASYNCerr(ASYNC_F_ASYNC_JOB_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + job->status = ASYNC_JOB_RUNNING; + + return job; +} + +static void async_job_free(ASYNC_JOB *job) +{ + if (job != NULL) { + OPENSSL_free(job->funcargs); + async_fibre_free(&job->fibrectx); + OPENSSL_free(job); + } +} + +static ASYNC_JOB *async_get_pool_job(void) { + ASYNC_JOB *job; + async_pool *pool; + + pool = (async_pool *)CRYPTO_THREAD_get_local(&poolkey); + if (pool == NULL) { + /* + * Pool has not been initialised, so init with the defaults, i.e. + * no max size and no pre-created jobs + */ + if (ASYNC_init_thread(0, 0) == 0) + return NULL; + pool = (async_pool *)CRYPTO_THREAD_get_local(&poolkey); + } + + job = sk_ASYNC_JOB_pop(pool->jobs); + if (job == NULL) { + /* Pool is empty */ + if ((pool->max_size != 0) && (pool->curr_size >= pool->max_size)) + return NULL; + + job = async_job_new(); + if (job != NULL) { + if (! async_fibre_makecontext(&job->fibrectx)) { + async_job_free(job); + return NULL; + } + pool->curr_size++; + } + } + return job; +} + +static void async_release_job(ASYNC_JOB *job) { + async_pool *pool; + + pool = (async_pool *)CRYPTO_THREAD_get_local(&poolkey); + OPENSSL_free(job->funcargs); + job->funcargs = NULL; + sk_ASYNC_JOB_push(pool->jobs, job); +} + +void async_start_func(void) +{ + ASYNC_JOB *job; + async_ctx *ctx = async_get_ctx(); + + while (1) { + /* Run the job */ + job = ctx->currjob; + job->ret = job->func(job->funcargs); + + /* Stop the job */ + job->status = ASYNC_JOB_STOPPING; + if (!async_fibre_swapcontext(&job->fibrectx, + &ctx->dispatcher, 1)) { + /* + * Should not happen. Getting here will close the thread...can't do + * much about it + */ + ASYNCerr(ASYNC_F_ASYNC_START_FUNC, ASYNC_R_FAILED_TO_SWAP_CONTEXT); + } + } +} + +int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *wctx, int *ret, + int (*func)(void *), void *args, size_t size) +{ + async_ctx *ctx; + + if (!OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL)) + return ASYNC_ERR; + + ctx = async_get_ctx(); + if (ctx == NULL) + ctx = async_ctx_new(); + if (ctx == NULL) + return ASYNC_ERR; + + if (*job) + ctx->currjob = *job; + + for (;;) { + if (ctx->currjob != NULL) { + if (ctx->currjob->status == ASYNC_JOB_STOPPING) { + *ret = ctx->currjob->ret; + ctx->currjob->waitctx = NULL; + async_release_job(ctx->currjob); + ctx->currjob = NULL; + *job = NULL; + return ASYNC_FINISH; + } + + if (ctx->currjob->status == ASYNC_JOB_PAUSING) { + *job = ctx->currjob; + ctx->currjob->status = ASYNC_JOB_PAUSED; + ctx->currjob = NULL; + return ASYNC_PAUSE; + } + + if (ctx->currjob->status == ASYNC_JOB_PAUSED) { + ctx->currjob = *job; + /* Resume previous job */ + if (!async_fibre_swapcontext(&ctx->dispatcher, + &ctx->currjob->fibrectx, 1)) { + ASYNCerr(ASYNC_F_ASYNC_START_JOB, + ASYNC_R_FAILED_TO_SWAP_CONTEXT); + goto err; + } + continue; + } + + /* Should not happen */ + ASYNCerr(ASYNC_F_ASYNC_START_JOB, ERR_R_INTERNAL_ERROR); + async_release_job(ctx->currjob); + ctx->currjob = NULL; + *job = NULL; + return ASYNC_ERR; + } + + /* Start a new job */ + if ((ctx->currjob = async_get_pool_job()) == NULL) + return ASYNC_NO_JOBS; + + if (args != NULL) { + ctx->currjob->funcargs = OPENSSL_malloc(size); + if (ctx->currjob->funcargs == NULL) { + ASYNCerr(ASYNC_F_ASYNC_START_JOB, ERR_R_MALLOC_FAILURE); + async_release_job(ctx->currjob); + ctx->currjob = NULL; + return ASYNC_ERR; + } + memcpy(ctx->currjob->funcargs, args, size); + } else { + ctx->currjob->funcargs = NULL; + } + + ctx->currjob->func = func; + ctx->currjob->waitctx = wctx; + if (!async_fibre_swapcontext(&ctx->dispatcher, + &ctx->currjob->fibrectx, 1)) { + ASYNCerr(ASYNC_F_ASYNC_START_JOB, ASYNC_R_FAILED_TO_SWAP_CONTEXT); + goto err; + } + } + +err: + async_release_job(ctx->currjob); + ctx->currjob = NULL; + *job = NULL; + return ASYNC_ERR; +} + +int ASYNC_pause_job(void) +{ + ASYNC_JOB *job; + async_ctx *ctx = async_get_ctx(); + + if (ctx == NULL + || ctx->currjob == NULL + || ctx->blocked) { + /* + * Could be we've deliberately not been started within a job so this is + * counted as success. + */ + return 1; + } + + job = ctx->currjob; + job->status = ASYNC_JOB_PAUSING; + + if (!async_fibre_swapcontext(&job->fibrectx, + &ctx->dispatcher, 1)) { + ASYNCerr(ASYNC_F_ASYNC_PAUSE_JOB, ASYNC_R_FAILED_TO_SWAP_CONTEXT); + return 0; + } + /* Reset counts of added and deleted fds */ + async_wait_ctx_reset_counts(job->waitctx); + + return 1; +} + +static void async_empty_pool(async_pool *pool) +{ + ASYNC_JOB *job; + + if (!pool || !pool->jobs) + return; + + do { + job = sk_ASYNC_JOB_pop(pool->jobs); + async_job_free(job); + } while (job); +} + +int async_init(void) +{ + if (!CRYPTO_THREAD_init_local(&ctxkey, NULL)) + return 0; + + if (!CRYPTO_THREAD_init_local(&poolkey, NULL)) { + CRYPTO_THREAD_cleanup_local(&ctxkey); + return 0; + } + + return 1; +} + +void async_deinit(void) +{ + CRYPTO_THREAD_cleanup_local(&ctxkey); + CRYPTO_THREAD_cleanup_local(&poolkey); +} + +int ASYNC_init_thread(size_t max_size, size_t init_size) +{ + async_pool *pool; + size_t curr_size = 0; + + if (init_size > max_size) { + ASYNCerr(ASYNC_F_ASYNC_INIT_THREAD, ASYNC_R_INVALID_POOL_SIZE); + return 0; + } + + if (!OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL)) + return 0; + + if (!ossl_init_thread_start(OPENSSL_INIT_THREAD_ASYNC)) + return 0; + + pool = OPENSSL_zalloc(sizeof(*pool)); + if (pool == NULL) { + ASYNCerr(ASYNC_F_ASYNC_INIT_THREAD, ERR_R_MALLOC_FAILURE); + return 0; + } + + pool->jobs = sk_ASYNC_JOB_new_reserve(NULL, init_size); + if (pool->jobs == NULL) { + ASYNCerr(ASYNC_F_ASYNC_INIT_THREAD, ERR_R_MALLOC_FAILURE); + OPENSSL_free(pool); + return 0; + } + + pool->max_size = max_size; + + /* Pre-create jobs as required */ + while (init_size--) { + ASYNC_JOB *job; + job = async_job_new(); + if (job == NULL || !async_fibre_makecontext(&job->fibrectx)) { + /* + * Not actually fatal because we already created the pool, just + * skip creation of any more jobs + */ + async_job_free(job); + break; + } + job->funcargs = NULL; + sk_ASYNC_JOB_push(pool->jobs, job); /* Cannot fail due to reserve */ + curr_size++; + } + pool->curr_size = curr_size; + if (!CRYPTO_THREAD_set_local(&poolkey, pool)) { + ASYNCerr(ASYNC_F_ASYNC_INIT_THREAD, ASYNC_R_FAILED_TO_SET_POOL); + goto err; + } + + return 1; +err: + async_empty_pool(pool); + sk_ASYNC_JOB_free(pool->jobs); + OPENSSL_free(pool); + return 0; +} + +void async_delete_thread_state(void) +{ + async_pool *pool = (async_pool *)CRYPTO_THREAD_get_local(&poolkey); + + if (pool != NULL) { + async_empty_pool(pool); + sk_ASYNC_JOB_free(pool->jobs); + OPENSSL_free(pool); + CRYPTO_THREAD_set_local(&poolkey, NULL); + } + async_local_cleanup(); + async_ctx_free(); +} + +void ASYNC_cleanup_thread(void) +{ + if (!OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL)) + return; + + async_delete_thread_state(); +} + +ASYNC_JOB *ASYNC_get_current_job(void) +{ + async_ctx *ctx; + + if (!OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL)) + return NULL; + + ctx = async_get_ctx(); + if (ctx == NULL) + return NULL; + + return ctx->currjob; +} + +ASYNC_WAIT_CTX *ASYNC_get_wait_ctx(ASYNC_JOB *job) +{ + return job->waitctx; +} + +void ASYNC_block_pause(void) +{ + async_ctx *ctx; + + if (!OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL)) + return; + + ctx = async_get_ctx(); + if (ctx == NULL || ctx->currjob == NULL) { + /* + * We're not in a job anyway so ignore this + */ + return; + } + ctx->blocked++; +} + +void ASYNC_unblock_pause(void) +{ + async_ctx *ctx; + + if (!OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL)) + return; + + ctx = async_get_ctx(); + if (ctx == NULL || ctx->currjob == NULL) { + /* + * We're not in a job anyway so ignore this + */ + return; + } + if (ctx->blocked > 0) + ctx->blocked--; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/async/async_err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/async/async_err.c new file mode 100644 index 000000000..fd5527aae --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/async/async_err.c @@ -0,0 +1,51 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA ASYNC_str_functs[] = { + {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_CTX_NEW, 0), "async_ctx_new"}, + {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_INIT_THREAD, 0), + "ASYNC_init_thread"}, + {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_JOB_NEW, 0), "async_job_new"}, + {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_PAUSE_JOB, 0), "ASYNC_pause_job"}, + {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_START_FUNC, 0), "async_start_func"}, + {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_START_JOB, 0), "ASYNC_start_job"}, + {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_WAIT_CTX_SET_WAIT_FD, 0), + "ASYNC_WAIT_CTX_set_wait_fd"}, + {0, NULL} +}; + +static const ERR_STRING_DATA ASYNC_str_reasons[] = { + {ERR_PACK(ERR_LIB_ASYNC, 0, ASYNC_R_FAILED_TO_SET_POOL), + "failed to set pool"}, + {ERR_PACK(ERR_LIB_ASYNC, 0, ASYNC_R_FAILED_TO_SWAP_CONTEXT), + "failed to swap context"}, + {ERR_PACK(ERR_LIB_ASYNC, 0, ASYNC_R_INIT_FAILED), "init failed"}, + {ERR_PACK(ERR_LIB_ASYNC, 0, ASYNC_R_INVALID_POOL_SIZE), + "invalid pool size"}, + {0, NULL} +}; + +#endif + +int ERR_load_ASYNC_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(ASYNC_str_functs[0].error) == NULL) { + ERR_load_strings_const(ASYNC_str_functs); + ERR_load_strings_const(ASYNC_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/async/async_locl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/async/async_locl.h new file mode 100644 index 000000000..d7790293f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/async/async_locl.h @@ -0,0 +1,77 @@ +/* + * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Must do this before including any header files, because on MacOS/X + * includes which includes + */ +#if defined(__APPLE__) && defined(__MACH__) && !defined(_XOPEN_SOURCE) +# define _XOPEN_SOURCE /* Otherwise incomplete ucontext_t structure */ +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + +#if defined(_WIN32) +# include +#endif + +#include "internal/async.h" +#include + +typedef struct async_ctx_st async_ctx; +typedef struct async_pool_st async_pool; + +#include "arch/async_win.h" +#include "arch/async_posix.h" +#include "arch/async_null.h" + +struct async_ctx_st { + async_fibre dispatcher; + ASYNC_JOB *currjob; + unsigned int blocked; +}; + +struct async_job_st { + async_fibre fibrectx; + int (*func) (void *); + void *funcargs; + int ret; + int status; + ASYNC_WAIT_CTX *waitctx; +}; + +struct fd_lookup_st { + const void *key; + OSSL_ASYNC_FD fd; + void *custom_data; + void (*cleanup)(ASYNC_WAIT_CTX *, const void *, OSSL_ASYNC_FD, void *); + int add; + int del; + struct fd_lookup_st *next; +}; + +struct async_wait_ctx_st { + struct fd_lookup_st *fds; + size_t numadd; + size_t numdel; +}; + +DEFINE_STACK_OF(ASYNC_JOB) + +struct async_pool_st { + STACK_OF(ASYNC_JOB) *jobs; + size_t curr_size; + size_t max_size; +}; + +void async_local_cleanup(void); +void async_start_func(void); +async_ctx *async_get_ctx(void); + +void async_wait_ctx_reset_counts(ASYNC_WAIT_CTX *ctx); + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/async/async_wait.c b/trunk/3rdparty/openssl-1.1-fit/crypto/async/async_wait.c new file mode 100644 index 000000000..b23e43e8c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/async/async_wait.c @@ -0,0 +1,213 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* This must be the first #include file */ +#include "async_locl.h" + +#include + +ASYNC_WAIT_CTX *ASYNC_WAIT_CTX_new(void) +{ + return OPENSSL_zalloc(sizeof(ASYNC_WAIT_CTX)); +} + +void ASYNC_WAIT_CTX_free(ASYNC_WAIT_CTX *ctx) +{ + struct fd_lookup_st *curr; + struct fd_lookup_st *next; + + if (ctx == NULL) + return; + + curr = ctx->fds; + while (curr != NULL) { + if (!curr->del) { + /* Only try and cleanup if it hasn't been marked deleted */ + if (curr->cleanup != NULL) + curr->cleanup(ctx, curr->key, curr->fd, curr->custom_data); + } + /* Always free the fd_lookup_st */ + next = curr->next; + OPENSSL_free(curr); + curr = next; + } + + OPENSSL_free(ctx); +} +int ASYNC_WAIT_CTX_set_wait_fd(ASYNC_WAIT_CTX *ctx, const void *key, + OSSL_ASYNC_FD fd, void *custom_data, + void (*cleanup)(ASYNC_WAIT_CTX *, const void *, + OSSL_ASYNC_FD, void *)) +{ + struct fd_lookup_st *fdlookup; + + if ((fdlookup = OPENSSL_zalloc(sizeof(*fdlookup))) == NULL) { + ASYNCerr(ASYNC_F_ASYNC_WAIT_CTX_SET_WAIT_FD, ERR_R_MALLOC_FAILURE); + return 0; + } + + fdlookup->key = key; + fdlookup->fd = fd; + fdlookup->custom_data = custom_data; + fdlookup->cleanup = cleanup; + fdlookup->add = 1; + fdlookup->next = ctx->fds; + ctx->fds = fdlookup; + ctx->numadd++; + return 1; +} + +int ASYNC_WAIT_CTX_get_fd(ASYNC_WAIT_CTX *ctx, const void *key, + OSSL_ASYNC_FD *fd, void **custom_data) +{ + struct fd_lookup_st *curr; + + curr = ctx->fds; + while (curr != NULL) { + if (curr->del) { + /* This one has been marked deleted so do nothing */ + curr = curr->next; + continue; + } + if (curr->key == key) { + *fd = curr->fd; + *custom_data = curr->custom_data; + return 1; + } + curr = curr->next; + } + return 0; +} + +int ASYNC_WAIT_CTX_get_all_fds(ASYNC_WAIT_CTX *ctx, OSSL_ASYNC_FD *fd, + size_t *numfds) +{ + struct fd_lookup_st *curr; + + curr = ctx->fds; + *numfds = 0; + while (curr != NULL) { + if (curr->del) { + /* This one has been marked deleted so do nothing */ + curr = curr->next; + continue; + } + if (fd != NULL) { + *fd = curr->fd; + fd++; + } + (*numfds)++; + curr = curr->next; + } + return 1; +} + +int ASYNC_WAIT_CTX_get_changed_fds(ASYNC_WAIT_CTX *ctx, OSSL_ASYNC_FD *addfd, + size_t *numaddfds, OSSL_ASYNC_FD *delfd, + size_t *numdelfds) +{ + struct fd_lookup_st *curr; + + *numaddfds = ctx->numadd; + *numdelfds = ctx->numdel; + if (addfd == NULL && delfd == NULL) + return 1; + + curr = ctx->fds; + + while (curr != NULL) { + /* We ignore fds that have been marked as both added and deleted */ + if (curr->del && !curr->add && (delfd != NULL)) { + *delfd = curr->fd; + delfd++; + } + if (curr->add && !curr->del && (addfd != NULL)) { + *addfd = curr->fd; + addfd++; + } + curr = curr->next; + } + + return 1; +} + +int ASYNC_WAIT_CTX_clear_fd(ASYNC_WAIT_CTX *ctx, const void *key) +{ + struct fd_lookup_st *curr, *prev; + + curr = ctx->fds; + prev = NULL; + while (curr != NULL) { + if (curr->del == 1) { + /* This one has been marked deleted already so do nothing */ + prev = curr; + curr = curr->next; + continue; + } + if (curr->key == key) { + /* If fd has just been added, remove it from the list */ + if (curr->add == 1) { + if (ctx->fds == curr) { + ctx->fds = curr->next; + } else { + prev->next = curr->next; + } + + /* It is responsibility of the caller to cleanup before calling + * ASYNC_WAIT_CTX_clear_fd + */ + OPENSSL_free(curr); + ctx->numadd--; + return 1; + } + + /* + * Mark it as deleted. We don't call cleanup if explicitly asked + * to clear an fd. We assume the caller is going to do that (if + * appropriate). + */ + curr->del = 1; + ctx->numdel++; + return 1; + } + prev = curr; + curr = curr->next; + } + return 0; +} + +void async_wait_ctx_reset_counts(ASYNC_WAIT_CTX *ctx) +{ + struct fd_lookup_st *curr, *prev = NULL; + + ctx->numadd = 0; + ctx->numdel = 0; + + curr = ctx->fds; + + while (curr != NULL) { + if (curr->del) { + if (prev == NULL) + ctx->fds = curr->next; + else + prev->next = curr->next; + OPENSSL_free(curr); + if (prev == NULL) + curr = ctx->fds; + else + curr = prev->next; + continue; + } + if (curr->add) { + curr->add = 0; + } + prev = curr; + curr = curr->next; + } +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/async/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/async/build.info new file mode 100644 index 000000000..278e3e9f8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/async/build.info @@ -0,0 +1,4 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + async.c async_wait.c async_err.c arch/async_posix.c arch/async_win.c \ + arch/async_null.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bf/asm/bf-586.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/bf/asm/bf-586.pl new file mode 100644 index 000000000..4e913aecf --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bf/asm/bf-586.pl @@ -0,0 +1,149 @@ +#! /usr/bin/env perl +# Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; +require "cbc.pl"; + +$output = pop; +open STDOUT,">$output"; + +&asm_init($ARGV[0],$ARGV[$#ARGV] eq "386"); + +$BF_ROUNDS=16; +$BF_OFF=($BF_ROUNDS+2)*4; +$L="edi"; +$R="esi"; +$P="ebp"; +$tmp1="eax"; +$tmp2="ebx"; +$tmp3="ecx"; +$tmp4="edx"; + +&BF_encrypt("BF_encrypt",1); +&BF_encrypt("BF_decrypt",0); +&cbc("BF_cbc_encrypt","BF_encrypt","BF_decrypt",1,4,5,3,-1,-1); +&asm_finish(); + +close STDOUT; + +sub BF_encrypt + { + local($name,$enc)=@_; + + &function_begin_B($name,""); + + &comment(""); + + &push("ebp"); + &push("ebx"); + &mov($tmp2,&wparam(0)); + &mov($P,&wparam(1)); + &push("esi"); + &push("edi"); + + &comment("Load the 2 words"); + &mov($L,&DWP(0,$tmp2,"",0)); + &mov($R,&DWP(4,$tmp2,"",0)); + + &xor( $tmp1, $tmp1); + + # encrypting part + + if ($enc) + { + &mov($tmp2,&DWP(0,$P,"",0)); + &xor( $tmp3, $tmp3); + + &xor($L,$tmp2); + for ($i=0; $i<$BF_ROUNDS; $i+=2) + { + &comment(""); + &comment("Round $i"); + &BF_ENCRYPT($i+1,$R,$L,$P,$tmp1,$tmp2,$tmp3,$tmp4,1); + + &comment(""); + &comment("Round ".sprintf("%d",$i+1)); + &BF_ENCRYPT($i+2,$L,$R,$P,$tmp1,$tmp2,$tmp3,$tmp4,1); + } + # &mov($tmp1,&wparam(0)); In last loop + &mov($tmp4,&DWP(($BF_ROUNDS+1)*4,$P,"",0)); + } + else + { + &mov($tmp2,&DWP(($BF_ROUNDS+1)*4,$P,"",0)); + &xor( $tmp3, $tmp3); + + &xor($L,$tmp2); + for ($i=$BF_ROUNDS; $i>0; $i-=2) + { + &comment(""); + &comment("Round $i"); + &BF_ENCRYPT($i,$R,$L,$P,$tmp1,$tmp2,$tmp3,$tmp4,0); + &comment(""); + &comment("Round ".sprintf("%d",$i-1)); + &BF_ENCRYPT($i-1,$L,$R,$P,$tmp1,$tmp2,$tmp3,$tmp4,0); + } + # &mov($tmp1,&wparam(0)); In last loop + &mov($tmp4,&DWP(0,$P,"",0)); + } + + &xor($R,$tmp4); + &mov(&DWP(4,$tmp1,"",0),$L); + + &mov(&DWP(0,$tmp1,"",0),$R); + &function_end($name); + } + +sub BF_ENCRYPT + { + local($i,$L,$R,$P,$tmp1,$tmp2,$tmp3,$tmp4,$enc)=@_; + + &mov( $tmp4, &DWP(&n2a($i*4),$P,"",0)); # for next round + + &mov( $tmp2, $R); + &xor( $L, $tmp4); + + &shr( $tmp2, 16); + &mov( $tmp4, $R); + + &movb( &LB($tmp1), &HB($tmp2)); # A + &and( $tmp2, 0xff); # B + + &movb( &LB($tmp3), &HB($tmp4)); # C + &and( $tmp4, 0xff); # D + + &mov( $tmp1, &DWP(&n2a($BF_OFF+0x0000),$P,$tmp1,4)); + &mov( $tmp2, &DWP(&n2a($BF_OFF+0x0400),$P,$tmp2,4)); + + &add( $tmp2, $tmp1); + &mov( $tmp1, &DWP(&n2a($BF_OFF+0x0800),$P,$tmp3,4)); + + &xor( $tmp2, $tmp1); + &mov( $tmp4, &DWP(&n2a($BF_OFF+0x0C00),$P,$tmp4,4)); + + &add( $tmp2, $tmp4); + if (($enc && ($i != 16)) || ((!$enc) && ($i != 1))) + { &xor( $tmp1, $tmp1); } + else + { + &comment("Load parameter 0 ($i) enc=$enc"); + &mov($tmp1,&wparam(0)); + } # In last loop + + &xor( $L, $tmp2); + # delay + } + +sub n2a + { + sprintf("%d",$_[0]); + } + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bf/bf_cfb64.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bf/bf_cfb64.c new file mode 100644 index 000000000..ce6e13b5a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bf/bf_cfb64.c @@ -0,0 +1,74 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "bf_locl.h" + +/* + * The input and output encrypted as though 64bit cfb mode is being used. + * The extra state information to record how much of the 64bit block we have + * used is contained in *num; + */ + +void BF_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, const BF_KEY *schedule, + unsigned char *ivec, int *num, int encrypt) +{ + register BF_LONG v0, v1, t; + register int n = *num; + register long l = length; + BF_LONG ti[2]; + unsigned char *iv, c, cc; + + iv = (unsigned char *)ivec; + if (encrypt) { + while (l--) { + if (n == 0) { + n2l(iv, v0); + ti[0] = v0; + n2l(iv, v1); + ti[1] = v1; + BF_encrypt((BF_LONG *)ti, schedule); + iv = (unsigned char *)ivec; + t = ti[0]; + l2n(t, iv); + t = ti[1]; + l2n(t, iv); + iv = (unsigned char *)ivec; + } + c = *(in++) ^ iv[n]; + *(out++) = c; + iv[n] = c; + n = (n + 1) & 0x07; + } + } else { + while (l--) { + if (n == 0) { + n2l(iv, v0); + ti[0] = v0; + n2l(iv, v1); + ti[1] = v1; + BF_encrypt((BF_LONG *)ti, schedule); + iv = (unsigned char *)ivec; + t = ti[0]; + l2n(t, iv); + t = ti[1]; + l2n(t, iv); + iv = (unsigned char *)ivec; + } + cc = *(in++); + c = iv[n]; + iv[n] = cc; + *(out++) = c ^ cc; + n = (n + 1) & 0x07; + } + } + v0 = v1 = ti[0] = ti[1] = t = c = cc = 0; + *num = n; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bf/bf_ecb.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bf/bf_ecb.c new file mode 100644 index 000000000..dc1becdbe --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bf/bf_ecb.c @@ -0,0 +1,43 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "bf_locl.h" +#include + +/* + * Blowfish as implemented from 'Blowfish: Springer-Verlag paper' (From + * LECTURE NOTES IN COMPUTER SCIENCE 809, FAST SOFTWARE ENCRYPTION, CAMBRIDGE + * SECURITY WORKSHOP, CAMBRIDGE, U.K., DECEMBER 9-11, 1993) + */ + +const char *BF_options(void) +{ + return "blowfish(ptr)"; +} + +void BF_ecb_encrypt(const unsigned char *in, unsigned char *out, + const BF_KEY *key, int encrypt) +{ + BF_LONG l, d[2]; + + n2l(in, l); + d[0] = l; + n2l(in, l); + d[1] = l; + if (encrypt) + BF_encrypt(d, key); + else + BF_decrypt(d, key); + l = d[0]; + l2n(l, out); + l = d[1]; + l2n(l, out); + l = d[0] = d[1] = 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bf/bf_enc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bf/bf_enc.c new file mode 100644 index 000000000..67c0d78ae --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bf/bf_enc.c @@ -0,0 +1,175 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "bf_locl.h" + +/* + * Blowfish as implemented from 'Blowfish: Springer-Verlag paper' (From + * LECTURE NOTES IN COMPUTER SCIENCE 809, FAST SOFTWARE ENCRYPTION, CAMBRIDGE + * SECURITY WORKSHOP, CAMBRIDGE, U.K., DECEMBER 9-11, 1993) + */ + +#if (BF_ROUNDS != 16) && (BF_ROUNDS != 20) +# error If you set BF_ROUNDS to some value other than 16 or 20, you will have \ +to modify the code. +#endif + +void BF_encrypt(BF_LONG *data, const BF_KEY *key) +{ + register BF_LONG l, r; + register const BF_LONG *p, *s; + + p = key->P; + s = &(key->S[0]); + l = data[0]; + r = data[1]; + + l ^= p[0]; + BF_ENC(r, l, s, p[1]); + BF_ENC(l, r, s, p[2]); + BF_ENC(r, l, s, p[3]); + BF_ENC(l, r, s, p[4]); + BF_ENC(r, l, s, p[5]); + BF_ENC(l, r, s, p[6]); + BF_ENC(r, l, s, p[7]); + BF_ENC(l, r, s, p[8]); + BF_ENC(r, l, s, p[9]); + BF_ENC(l, r, s, p[10]); + BF_ENC(r, l, s, p[11]); + BF_ENC(l, r, s, p[12]); + BF_ENC(r, l, s, p[13]); + BF_ENC(l, r, s, p[14]); + BF_ENC(r, l, s, p[15]); + BF_ENC(l, r, s, p[16]); +# if BF_ROUNDS == 20 + BF_ENC(r, l, s, p[17]); + BF_ENC(l, r, s, p[18]); + BF_ENC(r, l, s, p[19]); + BF_ENC(l, r, s, p[20]); +# endif + r ^= p[BF_ROUNDS + 1]; + + data[1] = l & 0xffffffffU; + data[0] = r & 0xffffffffU; +} + +void BF_decrypt(BF_LONG *data, const BF_KEY *key) +{ + register BF_LONG l, r; + register const BF_LONG *p, *s; + + p = key->P; + s = &(key->S[0]); + l = data[0]; + r = data[1]; + + l ^= p[BF_ROUNDS + 1]; +# if BF_ROUNDS == 20 + BF_ENC(r, l, s, p[20]); + BF_ENC(l, r, s, p[19]); + BF_ENC(r, l, s, p[18]); + BF_ENC(l, r, s, p[17]); +# endif + BF_ENC(r, l, s, p[16]); + BF_ENC(l, r, s, p[15]); + BF_ENC(r, l, s, p[14]); + BF_ENC(l, r, s, p[13]); + BF_ENC(r, l, s, p[12]); + BF_ENC(l, r, s, p[11]); + BF_ENC(r, l, s, p[10]); + BF_ENC(l, r, s, p[9]); + BF_ENC(r, l, s, p[8]); + BF_ENC(l, r, s, p[7]); + BF_ENC(r, l, s, p[6]); + BF_ENC(l, r, s, p[5]); + BF_ENC(r, l, s, p[4]); + BF_ENC(l, r, s, p[3]); + BF_ENC(r, l, s, p[2]); + BF_ENC(l, r, s, p[1]); + r ^= p[0]; + + data[1] = l & 0xffffffffU; + data[0] = r & 0xffffffffU; +} + +void BF_cbc_encrypt(const unsigned char *in, unsigned char *out, long length, + const BF_KEY *schedule, unsigned char *ivec, int encrypt) +{ + register BF_LONG tin0, tin1; + register BF_LONG tout0, tout1, xor0, xor1; + register long l = length; + BF_LONG tin[2]; + + if (encrypt) { + n2l(ivec, tout0); + n2l(ivec, tout1); + ivec -= 8; + for (l -= 8; l >= 0; l -= 8) { + n2l(in, tin0); + n2l(in, tin1); + tin0 ^= tout0; + tin1 ^= tout1; + tin[0] = tin0; + tin[1] = tin1; + BF_encrypt(tin, schedule); + tout0 = tin[0]; + tout1 = tin[1]; + l2n(tout0, out); + l2n(tout1, out); + } + if (l != -8) { + n2ln(in, tin0, tin1, l + 8); + tin0 ^= tout0; + tin1 ^= tout1; + tin[0] = tin0; + tin[1] = tin1; + BF_encrypt(tin, schedule); + tout0 = tin[0]; + tout1 = tin[1]; + l2n(tout0, out); + l2n(tout1, out); + } + l2n(tout0, ivec); + l2n(tout1, ivec); + } else { + n2l(ivec, xor0); + n2l(ivec, xor1); + ivec -= 8; + for (l -= 8; l >= 0; l -= 8) { + n2l(in, tin0); + n2l(in, tin1); + tin[0] = tin0; + tin[1] = tin1; + BF_decrypt(tin, schedule); + tout0 = tin[0] ^ xor0; + tout1 = tin[1] ^ xor1; + l2n(tout0, out); + l2n(tout1, out); + xor0 = tin0; + xor1 = tin1; + } + if (l != -8) { + n2l(in, tin0); + n2l(in, tin1); + tin[0] = tin0; + tin[1] = tin1; + BF_decrypt(tin, schedule); + tout0 = tin[0] ^ xor0; + tout1 = tin[1] ^ xor1; + l2nn(tout0, tout1, out, l + 8); + xor0 = tin0; + xor1 = tin1; + } + l2n(xor0, ivec); + l2n(xor1, ivec); + } + tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0; + tin[0] = tin[1] = 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bf/bf_locl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/bf/bf_locl.h new file mode 100644 index 000000000..b1a415e51 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bf/bf_locl.h @@ -0,0 +1,84 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_BF_LOCL_H +# define HEADER_BF_LOCL_H +# include + +/* NOTE - c is not incremented as per n2l */ +# define n2ln(c,l1,l2,n) { \ + c+=n; \ + l1=l2=0; \ + switch (n) { \ + case 8: l2 =((unsigned long)(*(--(c)))) ; \ + /* fall thru */ \ + case 7: l2|=((unsigned long)(*(--(c))))<< 8; \ + /* fall thru */ \ + case 6: l2|=((unsigned long)(*(--(c))))<<16; \ + /* fall thru */ \ + case 5: l2|=((unsigned long)(*(--(c))))<<24; \ + /* fall thru */ \ + case 4: l1 =((unsigned long)(*(--(c)))) ; \ + /* fall thru */ \ + case 3: l1|=((unsigned long)(*(--(c))))<< 8; \ + /* fall thru */ \ + case 2: l1|=((unsigned long)(*(--(c))))<<16; \ + /* fall thru */ \ + case 1: l1|=((unsigned long)(*(--(c))))<<24; \ + } \ + } + +/* NOTE - c is not incremented as per l2n */ +# define l2nn(l1,l2,c,n) { \ + c+=n; \ + switch (n) { \ + case 8: *(--(c))=(unsigned char)(((l2) )&0xff); \ + /* fall thru */ \ + case 7: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \ + /* fall thru */ \ + case 6: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \ + /* fall thru */ \ + case 5: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \ + /* fall thru */ \ + case 4: *(--(c))=(unsigned char)(((l1) )&0xff); \ + /* fall thru */ \ + case 3: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \ + /* fall thru */ \ + case 2: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \ + /* fall thru */ \ + case 1: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \ + } \ + } + +# undef n2l +# define n2l(c,l) (l =((unsigned long)(*((c)++)))<<24L, \ + l|=((unsigned long)(*((c)++)))<<16L, \ + l|=((unsigned long)(*((c)++)))<< 8L, \ + l|=((unsigned long)(*((c)++)))) + +# undef l2n +# define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +/* + * This is actually a big endian algorithm, the most significant byte is used + * to lookup array 0 + */ + +# define BF_ENC(LL,R,S,P) ( \ + LL^=P, \ + LL^=((( S[ ((R>>24)&0xff)] + \ + S[0x0100+((R>>16)&0xff)])^ \ + S[0x0200+((R>> 8)&0xff)])+ \ + S[0x0300+((R )&0xff)])&0xffffffffU \ + ) + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bf/bf_ofb64.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bf/bf_ofb64.c new file mode 100644 index 000000000..6418217b3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bf/bf_ofb64.c @@ -0,0 +1,61 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "bf_locl.h" + +/* + * The input and output encrypted as though 64bit ofb mode is being used. + * The extra state information to record how much of the 64bit block we have + * used is contained in *num; + */ +void BF_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, const BF_KEY *schedule, + unsigned char *ivec, int *num) +{ + register BF_LONG v0, v1, t; + register int n = *num; + register long l = length; + unsigned char d[8]; + register char *dp; + BF_LONG ti[2]; + unsigned char *iv; + int save = 0; + + iv = (unsigned char *)ivec; + n2l(iv, v0); + n2l(iv, v1); + ti[0] = v0; + ti[1] = v1; + dp = (char *)d; + l2n(v0, dp); + l2n(v1, dp); + while (l--) { + if (n == 0) { + BF_encrypt((BF_LONG *)ti, schedule); + dp = (char *)d; + t = ti[0]; + l2n(t, dp); + t = ti[1]; + l2n(t, dp); + save++; + } + *(out++) = *(in++) ^ d[n]; + n = (n + 1) & 0x07; + } + if (save) { + v0 = ti[0]; + v1 = ti[1]; + iv = (unsigned char *)ivec; + l2n(v0, iv); + l2n(v1, iv); + } + t = v0 = v1 = ti[0] = ti[1] = 0; + *num = n; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bf/bf_pi.h b/trunk/3rdparty/openssl-1.1-fit/crypto/bf/bf_pi.h new file mode 100644 index 000000000..a054b03f8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bf/bf_pi.h @@ -0,0 +1,530 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +static const BF_KEY bf_init = { + { + 0x243f6a88L, 0x85a308d3L, 0x13198a2eL, 0x03707344L, + 0xa4093822L, 0x299f31d0L, 0x082efa98L, 0xec4e6c89L, + 0x452821e6L, 0x38d01377L, 0xbe5466cfL, 0x34e90c6cL, + 0xc0ac29b7L, 0xc97c50ddL, 0x3f84d5b5L, 0xb5470917L, + 0x9216d5d9L, 0x8979fb1b}, { + 0xd1310ba6L, 0x98dfb5acL, 0x2ffd72dbL, + 0xd01adfb7L, + 0xb8e1afedL, 0x6a267e96L, 0xba7c9045L, + 0xf12c7f99L, + 0x24a19947L, 0xb3916cf7L, 0x0801f2e2L, + 0x858efc16L, + 0x636920d8L, 0x71574e69L, 0xa458fea3L, + 0xf4933d7eL, + 0x0d95748fL, 0x728eb658L, 0x718bcd58L, + 0x82154aeeL, + 0x7b54a41dL, 0xc25a59b5L, 0x9c30d539L, + 0x2af26013L, + 0xc5d1b023L, 0x286085f0L, 0xca417918L, + 0xb8db38efL, + 0x8e79dcb0L, 0x603a180eL, 0x6c9e0e8bL, + 0xb01e8a3eL, + 0xd71577c1L, 0xbd314b27L, 0x78af2fdaL, + 0x55605c60L, + 0xe65525f3L, 0xaa55ab94L, 0x57489862L, + 0x63e81440L, + 0x55ca396aL, 0x2aab10b6L, 0xb4cc5c34L, + 0x1141e8ceL, + 0xa15486afL, 0x7c72e993L, 0xb3ee1411L, + 0x636fbc2aL, + 0x2ba9c55dL, 0x741831f6L, 0xce5c3e16L, + 0x9b87931eL, + 0xafd6ba33L, 0x6c24cf5cL, 0x7a325381L, + 0x28958677L, + 0x3b8f4898L, 0x6b4bb9afL, 0xc4bfe81bL, + 0x66282193L, + 0x61d809ccL, 0xfb21a991L, 0x487cac60L, + 0x5dec8032L, + 0xef845d5dL, 0xe98575b1L, 0xdc262302L, + 0xeb651b88L, + 0x23893e81L, 0xd396acc5L, 0x0f6d6ff3L, + 0x83f44239L, + 0x2e0b4482L, 0xa4842004L, 0x69c8f04aL, + 0x9e1f9b5eL, + 0x21c66842L, 0xf6e96c9aL, 0x670c9c61L, + 0xabd388f0L, + 0x6a51a0d2L, 0xd8542f68L, 0x960fa728L, + 0xab5133a3L, + 0x6eef0b6cL, 0x137a3be4L, 0xba3bf050L, + 0x7efb2a98L, + 0xa1f1651dL, 0x39af0176L, 0x66ca593eL, + 0x82430e88L, + 0x8cee8619L, 0x456f9fb4L, 0x7d84a5c3L, + 0x3b8b5ebeL, + 0xe06f75d8L, 0x85c12073L, 0x401a449fL, + 0x56c16aa6L, + 0x4ed3aa62L, 0x363f7706L, 0x1bfedf72L, + 0x429b023dL, + 0x37d0d724L, 0xd00a1248L, 0xdb0fead3L, + 0x49f1c09bL, + 0x075372c9L, 0x80991b7bL, 0x25d479d8L, + 0xf6e8def7L, + 0xe3fe501aL, 0xb6794c3bL, 0x976ce0bdL, + 0x04c006baL, + 0xc1a94fb6L, 0x409f60c4L, 0x5e5c9ec2L, + 0x196a2463L, + 0x68fb6fafL, 0x3e6c53b5L, 0x1339b2ebL, + 0x3b52ec6fL, + 0x6dfc511fL, 0x9b30952cL, 0xcc814544L, + 0xaf5ebd09L, + 0xbee3d004L, 0xde334afdL, 0x660f2807L, + 0x192e4bb3L, + 0xc0cba857L, 0x45c8740fL, 0xd20b5f39L, + 0xb9d3fbdbL, + 0x5579c0bdL, 0x1a60320aL, 0xd6a100c6L, + 0x402c7279L, + 0x679f25feL, 0xfb1fa3ccL, 0x8ea5e9f8L, + 0xdb3222f8L, + 0x3c7516dfL, 0xfd616b15L, 0x2f501ec8L, + 0xad0552abL, + 0x323db5faL, 0xfd238760L, 0x53317b48L, + 0x3e00df82L, + 0x9e5c57bbL, 0xca6f8ca0L, 0x1a87562eL, + 0xdf1769dbL, + 0xd542a8f6L, 0x287effc3L, 0xac6732c6L, + 0x8c4f5573L, + 0x695b27b0L, 0xbbca58c8L, 0xe1ffa35dL, + 0xb8f011a0L, + 0x10fa3d98L, 0xfd2183b8L, 0x4afcb56cL, + 0x2dd1d35bL, + 0x9a53e479L, 0xb6f84565L, 0xd28e49bcL, + 0x4bfb9790L, + 0xe1ddf2daL, 0xa4cb7e33L, 0x62fb1341L, + 0xcee4c6e8L, + 0xef20cadaL, 0x36774c01L, 0xd07e9efeL, + 0x2bf11fb4L, + 0x95dbda4dL, 0xae909198L, 0xeaad8e71L, + 0x6b93d5a0L, + 0xd08ed1d0L, 0xafc725e0L, 0x8e3c5b2fL, + 0x8e7594b7L, + 0x8ff6e2fbL, 0xf2122b64L, 0x8888b812L, + 0x900df01cL, + 0x4fad5ea0L, 0x688fc31cL, 0xd1cff191L, + 0xb3a8c1adL, + 0x2f2f2218L, 0xbe0e1777L, 0xea752dfeL, + 0x8b021fa1L, + 0xe5a0cc0fL, 0xb56f74e8L, 0x18acf3d6L, + 0xce89e299L, + 0xb4a84fe0L, 0xfd13e0b7L, 0x7cc43b81L, + 0xd2ada8d9L, + 0x165fa266L, 0x80957705L, 0x93cc7314L, + 0x211a1477L, + 0xe6ad2065L, 0x77b5fa86L, 0xc75442f5L, + 0xfb9d35cfL, + 0xebcdaf0cL, 0x7b3e89a0L, 0xd6411bd3L, + 0xae1e7e49L, + 0x00250e2dL, 0x2071b35eL, 0x226800bbL, + 0x57b8e0afL, + 0x2464369bL, 0xf009b91eL, 0x5563911dL, + 0x59dfa6aaL, + 0x78c14389L, 0xd95a537fL, 0x207d5ba2L, + 0x02e5b9c5L, + 0x83260376L, 0x6295cfa9L, 0x11c81968L, + 0x4e734a41L, + 0xb3472dcaL, 0x7b14a94aL, 0x1b510052L, + 0x9a532915L, + 0xd60f573fL, 0xbc9bc6e4L, 0x2b60a476L, + 0x81e67400L, + 0x08ba6fb5L, 0x571be91fL, 0xf296ec6bL, + 0x2a0dd915L, + 0xb6636521L, 0xe7b9f9b6L, 0xff34052eL, + 0xc5855664L, + 0x53b02d5dL, 0xa99f8fa1L, 0x08ba4799L, + 0x6e85076aL, + 0x4b7a70e9L, 0xb5b32944L, 0xdb75092eL, + 0xc4192623L, + 0xad6ea6b0L, 0x49a7df7dL, 0x9cee60b8L, + 0x8fedb266L, + 0xecaa8c71L, 0x699a17ffL, 0x5664526cL, + 0xc2b19ee1L, + 0x193602a5L, 0x75094c29L, 0xa0591340L, + 0xe4183a3eL, + 0x3f54989aL, 0x5b429d65L, 0x6b8fe4d6L, + 0x99f73fd6L, + 0xa1d29c07L, 0xefe830f5L, 0x4d2d38e6L, + 0xf0255dc1L, + 0x4cdd2086L, 0x8470eb26L, 0x6382e9c6L, + 0x021ecc5eL, + 0x09686b3fL, 0x3ebaefc9L, 0x3c971814L, + 0x6b6a70a1L, + 0x687f3584L, 0x52a0e286L, 0xb79c5305L, + 0xaa500737L, + 0x3e07841cL, 0x7fdeae5cL, 0x8e7d44ecL, + 0x5716f2b8L, + 0xb03ada37L, 0xf0500c0dL, 0xf01c1f04L, + 0x0200b3ffL, + 0xae0cf51aL, 0x3cb574b2L, 0x25837a58L, + 0xdc0921bdL, + 0xd19113f9L, 0x7ca92ff6L, 0x94324773L, + 0x22f54701L, + 0x3ae5e581L, 0x37c2dadcL, 0xc8b57634L, + 0x9af3dda7L, + 0xa9446146L, 0x0fd0030eL, 0xecc8c73eL, + 0xa4751e41L, + 0xe238cd99L, 0x3bea0e2fL, 0x3280bba1L, + 0x183eb331L, + 0x4e548b38L, 0x4f6db908L, 0x6f420d03L, + 0xf60a04bfL, + 0x2cb81290L, 0x24977c79L, 0x5679b072L, + 0xbcaf89afL, + 0xde9a771fL, 0xd9930810L, 0xb38bae12L, + 0xdccf3f2eL, + 0x5512721fL, 0x2e6b7124L, 0x501adde6L, + 0x9f84cd87L, + 0x7a584718L, 0x7408da17L, 0xbc9f9abcL, + 0xe94b7d8cL, + 0xec7aec3aL, 0xdb851dfaL, 0x63094366L, + 0xc464c3d2L, + 0xef1c1847L, 0x3215d908L, 0xdd433b37L, + 0x24c2ba16L, + 0x12a14d43L, 0x2a65c451L, 0x50940002L, + 0x133ae4ddL, + 0x71dff89eL, 0x10314e55L, 0x81ac77d6L, + 0x5f11199bL, + 0x043556f1L, 0xd7a3c76bL, 0x3c11183bL, + 0x5924a509L, + 0xf28fe6edL, 0x97f1fbfaL, 0x9ebabf2cL, + 0x1e153c6eL, + 0x86e34570L, 0xeae96fb1L, 0x860e5e0aL, + 0x5a3e2ab3L, + 0x771fe71cL, 0x4e3d06faL, 0x2965dcb9L, + 0x99e71d0fL, + 0x803e89d6L, 0x5266c825L, 0x2e4cc978L, + 0x9c10b36aL, + 0xc6150ebaL, 0x94e2ea78L, 0xa5fc3c53L, + 0x1e0a2df4L, + 0xf2f74ea7L, 0x361d2b3dL, 0x1939260fL, + 0x19c27960L, + 0x5223a708L, 0xf71312b6L, 0xebadfe6eL, + 0xeac31f66L, + 0xe3bc4595L, 0xa67bc883L, 0xb17f37d1L, + 0x018cff28L, + 0xc332ddefL, 0xbe6c5aa5L, 0x65582185L, + 0x68ab9802L, + 0xeecea50fL, 0xdb2f953bL, 0x2aef7dadL, + 0x5b6e2f84L, + 0x1521b628L, 0x29076170L, 0xecdd4775L, + 0x619f1510L, + 0x13cca830L, 0xeb61bd96L, 0x0334fe1eL, + 0xaa0363cfL, + 0xb5735c90L, 0x4c70a239L, 0xd59e9e0bL, + 0xcbaade14L, + 0xeecc86bcL, 0x60622ca7L, 0x9cab5cabL, + 0xb2f3846eL, + 0x648b1eafL, 0x19bdf0caL, 0xa02369b9L, + 0x655abb50L, + 0x40685a32L, 0x3c2ab4b3L, 0x319ee9d5L, + 0xc021b8f7L, + 0x9b540b19L, 0x875fa099L, 0x95f7997eL, + 0x623d7da8L, + 0xf837889aL, 0x97e32d77L, 0x11ed935fL, + 0x16681281L, + 0x0e358829L, 0xc7e61fd6L, 0x96dedfa1L, + 0x7858ba99L, + 0x57f584a5L, 0x1b227263L, 0x9b83c3ffL, + 0x1ac24696L, + 0xcdb30aebL, 0x532e3054L, 0x8fd948e4L, + 0x6dbc3128L, + 0x58ebf2efL, 0x34c6ffeaL, 0xfe28ed61L, + 0xee7c3c73L, + 0x5d4a14d9L, 0xe864b7e3L, 0x42105d14L, + 0x203e13e0L, + 0x45eee2b6L, 0xa3aaabeaL, 0xdb6c4f15L, + 0xfacb4fd0L, + 0xc742f442L, 0xef6abbb5L, 0x654f3b1dL, + 0x41cd2105L, + 0xd81e799eL, 0x86854dc7L, 0xe44b476aL, + 0x3d816250L, + 0xcf62a1f2L, 0x5b8d2646L, 0xfc8883a0L, + 0xc1c7b6a3L, + 0x7f1524c3L, 0x69cb7492L, 0x47848a0bL, + 0x5692b285L, + 0x095bbf00L, 0xad19489dL, 0x1462b174L, + 0x23820e00L, + 0x58428d2aL, 0x0c55f5eaL, 0x1dadf43eL, + 0x233f7061L, + 0x3372f092L, 0x8d937e41L, 0xd65fecf1L, + 0x6c223bdbL, + 0x7cde3759L, 0xcbee7460L, 0x4085f2a7L, + 0xce77326eL, + 0xa6078084L, 0x19f8509eL, 0xe8efd855L, + 0x61d99735L, + 0xa969a7aaL, 0xc50c06c2L, 0x5a04abfcL, + 0x800bcadcL, + 0x9e447a2eL, 0xc3453484L, 0xfdd56705L, + 0x0e1e9ec9L, + 0xdb73dbd3L, 0x105588cdL, 0x675fda79L, + 0xe3674340L, + 0xc5c43465L, 0x713e38d8L, 0x3d28f89eL, + 0xf16dff20L, + 0x153e21e7L, 0x8fb03d4aL, 0xe6e39f2bL, + 0xdb83adf7L, + 0xe93d5a68L, 0x948140f7L, 0xf64c261cL, + 0x94692934L, + 0x411520f7L, 0x7602d4f7L, 0xbcf46b2eL, + 0xd4a20068L, + 0xd4082471L, 0x3320f46aL, 0x43b7d4b7L, + 0x500061afL, + 0x1e39f62eL, 0x97244546L, 0x14214f74L, + 0xbf8b8840L, + 0x4d95fc1dL, 0x96b591afL, 0x70f4ddd3L, + 0x66a02f45L, + 0xbfbc09ecL, 0x03bd9785L, 0x7fac6dd0L, + 0x31cb8504L, + 0x96eb27b3L, 0x55fd3941L, 0xda2547e6L, + 0xabca0a9aL, + 0x28507825L, 0x530429f4L, 0x0a2c86daL, + 0xe9b66dfbL, + 0x68dc1462L, 0xd7486900L, 0x680ec0a4L, + 0x27a18deeL, + 0x4f3ffea2L, 0xe887ad8cL, 0xb58ce006L, + 0x7af4d6b6L, + 0xaace1e7cL, 0xd3375fecL, 0xce78a399L, + 0x406b2a42L, + 0x20fe9e35L, 0xd9f385b9L, 0xee39d7abL, + 0x3b124e8bL, + 0x1dc9faf7L, 0x4b6d1856L, 0x26a36631L, + 0xeae397b2L, + 0x3a6efa74L, 0xdd5b4332L, 0x6841e7f7L, + 0xca7820fbL, + 0xfb0af54eL, 0xd8feb397L, 0x454056acL, + 0xba489527L, + 0x55533a3aL, 0x20838d87L, 0xfe6ba9b7L, + 0xd096954bL, + 0x55a867bcL, 0xa1159a58L, 0xcca92963L, + 0x99e1db33L, + 0xa62a4a56L, 0x3f3125f9L, 0x5ef47e1cL, + 0x9029317cL, + 0xfdf8e802L, 0x04272f70L, 0x80bb155cL, + 0x05282ce3L, + 0x95c11548L, 0xe4c66d22L, 0x48c1133fL, + 0xc70f86dcL, + 0x07f9c9eeL, 0x41041f0fL, 0x404779a4L, + 0x5d886e17L, + 0x325f51ebL, 0xd59bc0d1L, 0xf2bcc18fL, + 0x41113564L, + 0x257b7834L, 0x602a9c60L, 0xdff8e8a3L, + 0x1f636c1bL, + 0x0e12b4c2L, 0x02e1329eL, 0xaf664fd1L, + 0xcad18115L, + 0x6b2395e0L, 0x333e92e1L, 0x3b240b62L, + 0xeebeb922L, + 0x85b2a20eL, 0xe6ba0d99L, 0xde720c8cL, + 0x2da2f728L, + 0xd0127845L, 0x95b794fdL, 0x647d0862L, + 0xe7ccf5f0L, + 0x5449a36fL, 0x877d48faL, 0xc39dfd27L, + 0xf33e8d1eL, + 0x0a476341L, 0x992eff74L, 0x3a6f6eabL, + 0xf4f8fd37L, + 0xa812dc60L, 0xa1ebddf8L, 0x991be14cL, + 0xdb6e6b0dL, + 0xc67b5510L, 0x6d672c37L, 0x2765d43bL, + 0xdcd0e804L, + 0xf1290dc7L, 0xcc00ffa3L, 0xb5390f92L, + 0x690fed0bL, + 0x667b9ffbL, 0xcedb7d9cL, 0xa091cf0bL, + 0xd9155ea3L, + 0xbb132f88L, 0x515bad24L, 0x7b9479bfL, + 0x763bd6ebL, + 0x37392eb3L, 0xcc115979L, 0x8026e297L, + 0xf42e312dL, + 0x6842ada7L, 0xc66a2b3bL, 0x12754cccL, + 0x782ef11cL, + 0x6a124237L, 0xb79251e7L, 0x06a1bbe6L, + 0x4bfb6350L, + 0x1a6b1018L, 0x11caedfaL, 0x3d25bdd8L, + 0xe2e1c3c9L, + 0x44421659L, 0x0a121386L, 0xd90cec6eL, + 0xd5abea2aL, + 0x64af674eL, 0xda86a85fL, 0xbebfe988L, + 0x64e4c3feL, + 0x9dbc8057L, 0xf0f7c086L, 0x60787bf8L, + 0x6003604dL, + 0xd1fd8346L, 0xf6381fb0L, 0x7745ae04L, + 0xd736fcccL, + 0x83426b33L, 0xf01eab71L, 0xb0804187L, + 0x3c005e5fL, + 0x77a057beL, 0xbde8ae24L, 0x55464299L, + 0xbf582e61L, + 0x4e58f48fL, 0xf2ddfda2L, 0xf474ef38L, + 0x8789bdc2L, + 0x5366f9c3L, 0xc8b38e74L, 0xb475f255L, + 0x46fcd9b9L, + 0x7aeb2661L, 0x8b1ddf84L, 0x846a0e79L, + 0x915f95e2L, + 0x466e598eL, 0x20b45770L, 0x8cd55591L, + 0xc902de4cL, + 0xb90bace1L, 0xbb8205d0L, 0x11a86248L, + 0x7574a99eL, + 0xb77f19b6L, 0xe0a9dc09L, 0x662d09a1L, + 0xc4324633L, + 0xe85a1f02L, 0x09f0be8cL, 0x4a99a025L, + 0x1d6efe10L, + 0x1ab93d1dL, 0x0ba5a4dfL, 0xa186f20fL, + 0x2868f169L, + 0xdcb7da83L, 0x573906feL, 0xa1e2ce9bL, + 0x4fcd7f52L, + 0x50115e01L, 0xa70683faL, 0xa002b5c4L, + 0x0de6d027L, + 0x9af88c27L, 0x773f8641L, 0xc3604c06L, + 0x61a806b5L, + 0xf0177a28L, 0xc0f586e0L, 0x006058aaL, + 0x30dc7d62L, + 0x11e69ed7L, 0x2338ea63L, 0x53c2dd94L, + 0xc2c21634L, + 0xbbcbee56L, 0x90bcb6deL, 0xebfc7da1L, + 0xce591d76L, + 0x6f05e409L, 0x4b7c0188L, 0x39720a3dL, + 0x7c927c24L, + 0x86e3725fL, 0x724d9db9L, 0x1ac15bb4L, + 0xd39eb8fcL, + 0xed545578L, 0x08fca5b5L, 0xd83d7cd3L, + 0x4dad0fc4L, + 0x1e50ef5eL, 0xb161e6f8L, 0xa28514d9L, + 0x6c51133cL, + 0x6fd5c7e7L, 0x56e14ec4L, 0x362abfceL, + 0xddc6c837L, + 0xd79a3234L, 0x92638212L, 0x670efa8eL, + 0x406000e0L, + 0x3a39ce37L, 0xd3faf5cfL, 0xabc27737L, + 0x5ac52d1bL, + 0x5cb0679eL, 0x4fa33742L, 0xd3822740L, + 0x99bc9bbeL, + 0xd5118e9dL, 0xbf0f7315L, 0xd62d1c7eL, + 0xc700c47bL, + 0xb78c1b6bL, 0x21a19045L, 0xb26eb1beL, + 0x6a366eb4L, + 0x5748ab2fL, 0xbc946e79L, 0xc6a376d2L, + 0x6549c2c8L, + 0x530ff8eeL, 0x468dde7dL, 0xd5730a1dL, + 0x4cd04dc6L, + 0x2939bbdbL, 0xa9ba4650L, 0xac9526e8L, + 0xbe5ee304L, + 0xa1fad5f0L, 0x6a2d519aL, 0x63ef8ce2L, + 0x9a86ee22L, + 0xc089c2b8L, 0x43242ef6L, 0xa51e03aaL, + 0x9cf2d0a4L, + 0x83c061baL, 0x9be96a4dL, 0x8fe51550L, + 0xba645bd6L, + 0x2826a2f9L, 0xa73a3ae1L, 0x4ba99586L, + 0xef5562e9L, + 0xc72fefd3L, 0xf752f7daL, 0x3f046f69L, + 0x77fa0a59L, + 0x80e4a915L, 0x87b08601L, 0x9b09e6adL, + 0x3b3ee593L, + 0xe990fd5aL, 0x9e34d797L, 0x2cf0b7d9L, + 0x022b8b51L, + 0x96d5ac3aL, 0x017da67dL, 0xd1cf3ed6L, + 0x7c7d2d28L, + 0x1f9f25cfL, 0xadf2b89bL, 0x5ad6b472L, + 0x5a88f54cL, + 0xe029ac71L, 0xe019a5e6L, 0x47b0acfdL, + 0xed93fa9bL, + 0xe8d3c48dL, 0x283b57ccL, 0xf8d56629L, + 0x79132e28L, + 0x785f0191L, 0xed756055L, 0xf7960e44L, + 0xe3d35e8cL, + 0x15056dd4L, 0x88f46dbaL, 0x03a16125L, + 0x0564f0bdL, + 0xc3eb9e15L, 0x3c9057a2L, 0x97271aecL, + 0xa93a072aL, + 0x1b3f6d9bL, 0x1e6321f5L, 0xf59c66fbL, + 0x26dcf319L, + 0x7533d928L, 0xb155fdf5L, 0x03563482L, + 0x8aba3cbbL, + 0x28517711L, 0xc20ad9f8L, 0xabcc5167L, + 0xccad925fL, + 0x4de81751L, 0x3830dc8eL, 0x379d5862L, + 0x9320f991L, + 0xea7a90c2L, 0xfb3e7bceL, 0x5121ce64L, + 0x774fbe32L, + 0xa8b6e37eL, 0xc3293d46L, 0x48de5369L, + 0x6413e680L, + 0xa2ae0810L, 0xdd6db224L, 0x69852dfdL, + 0x09072166L, + 0xb39a460aL, 0x6445c0ddL, 0x586cdecfL, + 0x1c20c8aeL, + 0x5bbef7ddL, 0x1b588d40L, 0xccd2017fL, + 0x6bb4e3bbL, + 0xdda26a7eL, 0x3a59ff45L, 0x3e350a44L, + 0xbcb4cdd5L, + 0x72eacea8L, 0xfa6484bbL, 0x8d6612aeL, + 0xbf3c6f47L, + 0xd29be463L, 0x542f5d9eL, 0xaec2771bL, + 0xf64e6370L, + 0x740e0d8dL, 0xe75b1357L, 0xf8721671L, + 0xaf537d5dL, + 0x4040cb08L, 0x4eb4e2ccL, 0x34d2466aL, + 0x0115af84L, + 0xe1b00428L, 0x95983a1dL, 0x06b89fb4L, + 0xce6ea048L, + 0x6f3f3b82L, 0x3520ab82L, 0x011a1d4bL, + 0x277227f8L, + 0x611560b1L, 0xe7933fdcL, 0xbb3a792bL, + 0x344525bdL, + 0xa08839e1L, 0x51ce794bL, 0x2f32c9b7L, + 0xa01fbac9L, + 0xe01cc87eL, 0xbcc7d1f6L, 0xcf0111c3L, + 0xa1e8aac7L, + 0x1a908749L, 0xd44fbd9aL, 0xd0dadecbL, + 0xd50ada38L, + 0x0339c32aL, 0xc6913667L, 0x8df9317cL, + 0xe0b12b4fL, + 0xf79e59b7L, 0x43f5bb3aL, 0xf2d519ffL, + 0x27d9459cL, + 0xbf97222cL, 0x15e6fc2aL, 0x0f91fc71L, + 0x9b941525L, + 0xfae59361L, 0xceb69cebL, 0xc2a86459L, + 0x12baa8d1L, + 0xb6c1075eL, 0xe3056a0cL, 0x10d25065L, + 0xcb03a442L, + 0xe0ec6e0eL, 0x1698db3bL, 0x4c98a0beL, + 0x3278e964L, + 0x9f1f9532L, 0xe0d392dfL, 0xd3a0342bL, + 0x8971f21eL, + 0x1b0a7441L, 0x4ba3348cL, 0xc5be7120L, + 0xc37632d8L, + 0xdf359f8dL, 0x9b992f2eL, 0xe60b6f47L, + 0x0fe3f11dL, + 0xe54cda54L, 0x1edad891L, 0xce6279cfL, + 0xcd3e7e6fL, + 0x1618b166L, 0xfd2c1d05L, 0x848fd2c5L, + 0xf6fb2299L, + 0xf523f357L, 0xa6327623L, 0x93a83531L, + 0x56cccd02L, + 0xacf08162L, 0x5a75ebb5L, 0x6e163697L, + 0x88d273ccL, + 0xde966292L, 0x81b949d0L, 0x4c50901bL, + 0x71c65614L, + 0xe6c6c7bdL, 0x327a140aL, 0x45e1d006L, + 0xc3f27b9aL, + 0xc9aa53fdL, 0x62a80f00L, 0xbb25bfe2L, + 0x35bdd2f6L, + 0x71126905L, 0xb2040222L, 0xb6cbcf7cL, + 0xcd769c2bL, + 0x53113ec0L, 0x1640e3d3L, 0x38abbd60L, + 0x2547adf0L, + 0xba38209cL, 0xf746ce76L, 0x77afa1c5L, + 0x20756060L, + 0x85cbfe4eL, 0x8ae88dd8L, 0x7aaaf9b0L, + 0x4cf9aa7eL, + 0x1948c25cL, 0x02fb8a8cL, 0x01c36ae4L, + 0xd6ebe1f9L, + 0x90d4f869L, 0xa65cdea0L, 0x3f09252dL, + 0xc208e69fL, + 0xb74e6132L, 0xce77e25bL, 0x578fdfe3L, + 0x3ac372e6L, + } +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bf/bf_skey.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bf/bf_skey.c new file mode 100644 index 000000000..a4903a2a7 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bf/bf_skey.c @@ -0,0 +1,67 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "bf_locl.h" +#include "bf_pi.h" + +void BF_set_key(BF_KEY *key, int len, const unsigned char *data) +{ + int i; + BF_LONG *p, ri, in[2]; + const unsigned char *d, *end; + + memcpy(key, &bf_init, sizeof(BF_KEY)); + p = key->P; + + if (len > ((BF_ROUNDS + 2) * 4)) + len = (BF_ROUNDS + 2) * 4; + + d = data; + end = &(data[len]); + for (i = 0; i < (BF_ROUNDS + 2); i++) { + ri = *(d++); + if (d >= end) + d = data; + + ri <<= 8; + ri |= *(d++); + if (d >= end) + d = data; + + ri <<= 8; + ri |= *(d++); + if (d >= end) + d = data; + + ri <<= 8; + ri |= *(d++); + if (d >= end) + d = data; + + p[i] ^= ri; + } + + in[0] = 0L; + in[1] = 0L; + for (i = 0; i < (BF_ROUNDS + 2); i += 2) { + BF_encrypt(in, key); + p[i] = in[0]; + p[i + 1] = in[1]; + } + + p = key->S; + for (i = 0; i < 4 * 256; i += 2) { + BF_encrypt(in, key); + p[i] = in[0]; + p[i + 1] = in[1]; + } +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bf/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/bf/build.info new file mode 100644 index 000000000..29adc8ce5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bf/build.info @@ -0,0 +1,7 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=bf_skey.c bf_ecb.c bf_cfb64.c bf_ofb64.c \ + {- $target{bf_asm_src} -} + +GENERATE[bf-586.s]=asm/bf-586.pl \ + $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) +DEPEND[bf-586.s]=../perlasm/x86asm.pl ../perlasm/cbc.pl diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_addr.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_addr.c new file mode 100644 index 000000000..4395ab7a0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_addr.c @@ -0,0 +1,902 @@ +/* + * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#include "bio_lcl.h" +#include + +#ifndef OPENSSL_NO_SOCK +#include +#include +#include "internal/thread_once.h" + +CRYPTO_RWLOCK *bio_lookup_lock; +static CRYPTO_ONCE bio_lookup_init = CRYPTO_ONCE_STATIC_INIT; + +/* + * Throughout this file and bio_lcl.h, the existence of the macro + * AI_PASSIVE is used to detect the availability of struct addrinfo, + * getnameinfo() and getaddrinfo(). If that macro doesn't exist, + * we use our own implementation instead, using gethostbyname, + * getservbyname and a few other. + */ + +/********************************************************************** + * + * Address structure + * + */ + +BIO_ADDR *BIO_ADDR_new(void) +{ + BIO_ADDR *ret = OPENSSL_zalloc(sizeof(*ret)); + + if (ret == NULL) { + BIOerr(BIO_F_BIO_ADDR_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + ret->sa.sa_family = AF_UNSPEC; + return ret; +} + +void BIO_ADDR_free(BIO_ADDR *ap) +{ + OPENSSL_free(ap); +} + +void BIO_ADDR_clear(BIO_ADDR *ap) +{ + memset(ap, 0, sizeof(*ap)); + ap->sa.sa_family = AF_UNSPEC; +} + +/* + * BIO_ADDR_make - non-public routine to fill a BIO_ADDR with the contents + * of a struct sockaddr. + */ +int BIO_ADDR_make(BIO_ADDR *ap, const struct sockaddr *sa) +{ + if (sa->sa_family == AF_INET) { + memcpy(&(ap->s_in), sa, sizeof(struct sockaddr_in)); + return 1; + } +#ifdef AF_INET6 + if (sa->sa_family == AF_INET6) { + memcpy(&(ap->s_in6), sa, sizeof(struct sockaddr_in6)); + return 1; + } +#endif +#ifdef AF_UNIX + if (sa->sa_family == AF_UNIX) { + memcpy(&(ap->s_un), sa, sizeof(struct sockaddr_un)); + return 1; + } +#endif + + return 0; +} + +int BIO_ADDR_rawmake(BIO_ADDR *ap, int family, + const void *where, size_t wherelen, + unsigned short port) +{ +#ifdef AF_UNIX + if (family == AF_UNIX) { + if (wherelen + 1 > sizeof(ap->s_un.sun_path)) + return 0; + memset(&ap->s_un, 0, sizeof(ap->s_un)); + ap->s_un.sun_family = family; + strncpy(ap->s_un.sun_path, where, sizeof(ap->s_un.sun_path) - 1); + return 1; + } +#endif + if (family == AF_INET) { + if (wherelen != sizeof(struct in_addr)) + return 0; + memset(&ap->s_in, 0, sizeof(ap->s_in)); + ap->s_in.sin_family = family; + ap->s_in.sin_port = port; + ap->s_in.sin_addr = *(struct in_addr *)where; + return 1; + } +#ifdef AF_INET6 + if (family == AF_INET6) { + if (wherelen != sizeof(struct in6_addr)) + return 0; + memset(&ap->s_in6, 0, sizeof(ap->s_in6)); + ap->s_in6.sin6_family = family; + ap->s_in6.sin6_port = port; + ap->s_in6.sin6_addr = *(struct in6_addr *)where; + return 1; + } +#endif + + return 0; +} + +int BIO_ADDR_family(const BIO_ADDR *ap) +{ + return ap->sa.sa_family; +} + +int BIO_ADDR_rawaddress(const BIO_ADDR *ap, void *p, size_t *l) +{ + size_t len = 0; + const void *addrptr = NULL; + + if (ap->sa.sa_family == AF_INET) { + len = sizeof(ap->s_in.sin_addr); + addrptr = &ap->s_in.sin_addr; + } +#ifdef AF_INET6 + else if (ap->sa.sa_family == AF_INET6) { + len = sizeof(ap->s_in6.sin6_addr); + addrptr = &ap->s_in6.sin6_addr; + } +#endif +#ifdef AF_UNIX + else if (ap->sa.sa_family == AF_UNIX) { + len = strlen(ap->s_un.sun_path); + addrptr = &ap->s_un.sun_path; + } +#endif + + if (addrptr == NULL) + return 0; + + if (p != NULL) { + memcpy(p, addrptr, len); + } + if (l != NULL) + *l = len; + + return 1; +} + +unsigned short BIO_ADDR_rawport(const BIO_ADDR *ap) +{ + if (ap->sa.sa_family == AF_INET) + return ap->s_in.sin_port; +#ifdef AF_INET6 + if (ap->sa.sa_family == AF_INET6) + return ap->s_in6.sin6_port; +#endif + return 0; +} + +/*- + * addr_strings - helper function to get host and service names + * @ap: the BIO_ADDR that has the input info + * @numeric: 0 if actual names should be returned, 1 if the numeric + * representation should be returned. + * @hostname: a pointer to a pointer to a memory area to store the + * host name or numeric representation. Unused if NULL. + * @service: a pointer to a pointer to a memory area to store the + * service name or numeric representation. Unused if NULL. + * + * The return value is 0 on failure, with the error code in the error + * stack, and 1 on success. + */ +static int addr_strings(const BIO_ADDR *ap, int numeric, + char **hostname, char **service) +{ + if (BIO_sock_init() != 1) + return 0; + + if (1) { +#ifdef AI_PASSIVE + int ret = 0; + char host[NI_MAXHOST] = "", serv[NI_MAXSERV] = ""; + int flags = 0; + + if (numeric) + flags |= NI_NUMERICHOST | NI_NUMERICSERV; + + if ((ret = getnameinfo(BIO_ADDR_sockaddr(ap), + BIO_ADDR_sockaddr_size(ap), + host, sizeof(host), serv, sizeof(serv), + flags)) != 0) { +# ifdef EAI_SYSTEM + if (ret == EAI_SYSTEM) { + SYSerr(SYS_F_GETNAMEINFO, get_last_socket_error()); + BIOerr(BIO_F_ADDR_STRINGS, ERR_R_SYS_LIB); + } else +# endif + { + BIOerr(BIO_F_ADDR_STRINGS, ERR_R_SYS_LIB); + ERR_add_error_data(1, gai_strerror(ret)); + } + return 0; + } + + /* VMS getnameinfo() has a bug, it doesn't fill in serv, which + * leaves it with whatever garbage that happens to be there. + * However, we initialise serv with the empty string (serv[0] + * is therefore NUL), so it gets real easy to detect when things + * didn't go the way one might expect. + */ + if (serv[0] == '\0') { + BIO_snprintf(serv, sizeof(serv), "%d", + ntohs(BIO_ADDR_rawport(ap))); + } + + if (hostname != NULL) + *hostname = OPENSSL_strdup(host); + if (service != NULL) + *service = OPENSSL_strdup(serv); + } else { +#endif + if (hostname != NULL) + *hostname = OPENSSL_strdup(inet_ntoa(ap->s_in.sin_addr)); + if (service != NULL) { + char serv[6]; /* port is 16 bits => max 5 decimal digits */ + BIO_snprintf(serv, sizeof(serv), "%d", ntohs(ap->s_in.sin_port)); + *service = OPENSSL_strdup(serv); + } + } + + if ((hostname != NULL && *hostname == NULL) + || (service != NULL && *service == NULL)) { + if (hostname != NULL) { + OPENSSL_free(*hostname); + *hostname = NULL; + } + if (service != NULL) { + OPENSSL_free(*service); + *service = NULL; + } + BIOerr(BIO_F_ADDR_STRINGS, ERR_R_MALLOC_FAILURE); + return 0; + } + + return 1; +} + +char *BIO_ADDR_hostname_string(const BIO_ADDR *ap, int numeric) +{ + char *hostname = NULL; + + if (addr_strings(ap, numeric, &hostname, NULL)) + return hostname; + + return NULL; +} + +char *BIO_ADDR_service_string(const BIO_ADDR *ap, int numeric) +{ + char *service = NULL; + + if (addr_strings(ap, numeric, NULL, &service)) + return service; + + return NULL; +} + +char *BIO_ADDR_path_string(const BIO_ADDR *ap) +{ +#ifdef AF_UNIX + if (ap->sa.sa_family == AF_UNIX) + return OPENSSL_strdup(ap->s_un.sun_path); +#endif + return NULL; +} + +/* + * BIO_ADDR_sockaddr - non-public routine to return the struct sockaddr + * for a given BIO_ADDR. In reality, this is simply a type safe cast. + * The returned struct sockaddr is const, so it can't be tampered with. + */ +const struct sockaddr *BIO_ADDR_sockaddr(const BIO_ADDR *ap) +{ + return &(ap->sa); +} + +/* + * BIO_ADDR_sockaddr_noconst - non-public function that does the same + * as BIO_ADDR_sockaddr, but returns a non-const. USE WITH CARE, as + * it allows you to tamper with the data (and thereby the contents + * of the input BIO_ADDR). + */ +struct sockaddr *BIO_ADDR_sockaddr_noconst(BIO_ADDR *ap) +{ + return &(ap->sa); +} + +/* + * BIO_ADDR_sockaddr_size - non-public function that returns the size + * of the struct sockaddr the BIO_ADDR is using. If the protocol family + * isn't set or is something other than AF_INET, AF_INET6 or AF_UNIX, + * the size of the BIO_ADDR type is returned. + */ +socklen_t BIO_ADDR_sockaddr_size(const BIO_ADDR *ap) +{ + if (ap->sa.sa_family == AF_INET) + return sizeof(ap->s_in); +#ifdef AF_INET6 + if (ap->sa.sa_family == AF_INET6) + return sizeof(ap->s_in6); +#endif +#ifdef AF_UNIX + if (ap->sa.sa_family == AF_UNIX) + return sizeof(ap->s_un); +#endif + return sizeof(*ap); +} + +/********************************************************************** + * + * Address info database + * + */ + +const BIO_ADDRINFO *BIO_ADDRINFO_next(const BIO_ADDRINFO *bai) +{ + if (bai != NULL) + return bai->bai_next; + return NULL; +} + +int BIO_ADDRINFO_family(const BIO_ADDRINFO *bai) +{ + if (bai != NULL) + return bai->bai_family; + return 0; +} + +int BIO_ADDRINFO_socktype(const BIO_ADDRINFO *bai) +{ + if (bai != NULL) + return bai->bai_socktype; + return 0; +} + +int BIO_ADDRINFO_protocol(const BIO_ADDRINFO *bai) +{ + if (bai != NULL) { + if (bai->bai_protocol != 0) + return bai->bai_protocol; + +#ifdef AF_UNIX + if (bai->bai_family == AF_UNIX) + return 0; +#endif + + switch (bai->bai_socktype) { + case SOCK_STREAM: + return IPPROTO_TCP; + case SOCK_DGRAM: + return IPPROTO_UDP; + default: + break; + } + } + return 0; +} + +/* + * BIO_ADDRINFO_sockaddr_size - non-public function that returns the size + * of the struct sockaddr inside the BIO_ADDRINFO. + */ +socklen_t BIO_ADDRINFO_sockaddr_size(const BIO_ADDRINFO *bai) +{ + if (bai != NULL) + return bai->bai_addrlen; + return 0; +} + +/* + * BIO_ADDRINFO_sockaddr - non-public function that returns bai_addr + * as the struct sockaddr it is. + */ +const struct sockaddr *BIO_ADDRINFO_sockaddr(const BIO_ADDRINFO *bai) +{ + if (bai != NULL) + return bai->bai_addr; + return NULL; +} + +const BIO_ADDR *BIO_ADDRINFO_address(const BIO_ADDRINFO *bai) +{ + if (bai != NULL) + return (BIO_ADDR *)bai->bai_addr; + return NULL; +} + +void BIO_ADDRINFO_free(BIO_ADDRINFO *bai) +{ + if (bai == NULL) + return; + +#ifdef AI_PASSIVE +# ifdef AF_UNIX +# define _cond bai->bai_family != AF_UNIX +# else +# define _cond 1 +# endif + if (_cond) { + freeaddrinfo(bai); + return; + } +#endif + + /* Free manually when we know that addrinfo_wrap() was used. + * See further comment above addrinfo_wrap() + */ + while (bai != NULL) { + BIO_ADDRINFO *next = bai->bai_next; + OPENSSL_free(bai->bai_addr); + OPENSSL_free(bai); + bai = next; + } +} + +/********************************************************************** + * + * Service functions + * + */ + +/*- + * The specs in hostserv can take these forms: + * + * host:service => *host = "host", *service = "service" + * host:* => *host = "host", *service = NULL + * host: => *host = "host", *service = NULL + * :service => *host = NULL, *service = "service" + * *:service => *host = NULL, *service = "service" + * + * in case no : is present in the string, the result depends on + * hostserv_prio, as follows: + * + * when hostserv_prio == BIO_PARSE_PRIO_HOST + * host => *host = "host", *service untouched + * + * when hostserv_prio == BIO_PARSE_PRIO_SERV + * service => *host untouched, *service = "service" + * + */ +int BIO_parse_hostserv(const char *hostserv, char **host, char **service, + enum BIO_hostserv_priorities hostserv_prio) +{ + const char *h = NULL; size_t hl = 0; + const char *p = NULL; size_t pl = 0; + + if (*hostserv == '[') { + if ((p = strchr(hostserv, ']')) == NULL) + goto spec_err; + h = hostserv + 1; + hl = p - h; + p++; + if (*p == '\0') + p = NULL; + else if (*p != ':') + goto spec_err; + else { + p++; + pl = strlen(p); + } + } else { + const char *p2 = strrchr(hostserv, ':'); + p = strchr(hostserv, ':'); + + /*- + * Check for more than one colon. There are three possible + * interpretations: + * 1. IPv6 address with port number, last colon being separator. + * 2. IPv6 address only. + * 3. IPv6 address only if hostserv_prio == BIO_PARSE_PRIO_HOST, + * IPv6 address and port number if hostserv_prio == BIO_PARSE_PRIO_SERV + * Because of this ambiguity, we currently choose to make it an + * error. + */ + if (p != p2) + goto amb_err; + + if (p != NULL) { + h = hostserv; + hl = p - h; + p++; + pl = strlen(p); + } else if (hostserv_prio == BIO_PARSE_PRIO_HOST) { + h = hostserv; + hl = strlen(h); + } else { + p = hostserv; + pl = strlen(p); + } + } + + if (p != NULL && strchr(p, ':')) + goto spec_err; + + if (h != NULL && host != NULL) { + if (hl == 0 + || (hl == 1 && h[0] == '*')) { + *host = NULL; + } else { + *host = OPENSSL_strndup(h, hl); + if (*host == NULL) + goto memerr; + } + } + if (p != NULL && service != NULL) { + if (pl == 0 + || (pl == 1 && p[0] == '*')) { + *service = NULL; + } else { + *service = OPENSSL_strndup(p, pl); + if (*service == NULL) + goto memerr; + } + } + + return 1; + amb_err: + BIOerr(BIO_F_BIO_PARSE_HOSTSERV, BIO_R_AMBIGUOUS_HOST_OR_SERVICE); + return 0; + spec_err: + BIOerr(BIO_F_BIO_PARSE_HOSTSERV, BIO_R_MALFORMED_HOST_OR_SERVICE); + return 0; + memerr: + BIOerr(BIO_F_BIO_PARSE_HOSTSERV, ERR_R_MALLOC_FAILURE); + return 0; +} + +/* addrinfo_wrap is used to build our own addrinfo "chain". + * (it has only one entry, so calling it a chain may be a stretch) + * It should ONLY be called when getaddrinfo() and friends + * aren't available, OR when dealing with a non IP protocol + * family, such as AF_UNIX + * + * the return value is 1 on success, or 0 on failure, which + * only happens if a memory allocation error occurred. + */ +static int addrinfo_wrap(int family, int socktype, + const void *where, size_t wherelen, + unsigned short port, + BIO_ADDRINFO **bai) +{ + if ((*bai = OPENSSL_zalloc(sizeof(**bai))) == NULL) { + BIOerr(BIO_F_ADDRINFO_WRAP, ERR_R_MALLOC_FAILURE); + return 0; + } + + (*bai)->bai_family = family; + (*bai)->bai_socktype = socktype; + if (socktype == SOCK_STREAM) + (*bai)->bai_protocol = IPPROTO_TCP; + if (socktype == SOCK_DGRAM) + (*bai)->bai_protocol = IPPROTO_UDP; +#ifdef AF_UNIX + if (family == AF_UNIX) + (*bai)->bai_protocol = 0; +#endif + { + /* Magic: We know that BIO_ADDR_sockaddr_noconst is really + just an advanced cast of BIO_ADDR* to struct sockaddr * + by the power of union, so while it may seem that we're + creating a memory leak here, we are not. It will be + all right. */ + BIO_ADDR *addr = BIO_ADDR_new(); + if (addr != NULL) { + BIO_ADDR_rawmake(addr, family, where, wherelen, port); + (*bai)->bai_addr = BIO_ADDR_sockaddr_noconst(addr); + } + } + (*bai)->bai_next = NULL; + if ((*bai)->bai_addr == NULL) { + BIO_ADDRINFO_free(*bai); + *bai = NULL; + return 0; + } + return 1; +} + +DEFINE_RUN_ONCE_STATIC(do_bio_lookup_init) +{ + if (!OPENSSL_init_crypto(0, NULL)) + return 0; + bio_lookup_lock = CRYPTO_THREAD_lock_new(); + return bio_lookup_lock != NULL; +} + +int BIO_lookup(const char *host, const char *service, + enum BIO_lookup_type lookup_type, + int family, int socktype, BIO_ADDRINFO **res) +{ + return BIO_lookup_ex(host, service, lookup_type, family, socktype, 0, res); +} + +/*- + * BIO_lookup_ex - look up the node and service you want to connect to. + * @node: the node you want to connect to. + * @service: the service you want to connect to. + * @lookup_type: declare intent with the result, client or server. + * @family: the address family you want to use. Use AF_UNSPEC for any, or + * AF_INET, AF_INET6 or AF_UNIX. + * @socktype: The socket type you want to use. Can be SOCK_STREAM, SOCK_DGRAM + * or 0 for all. + * @protocol: The protocol to use, e.g. IPPROTO_TCP or IPPROTO_UDP or 0 for all. + * Note that some platforms may not return IPPROTO_SCTP without + * explicitly requesting it (i.e. IPPROTO_SCTP may not be returned + * with 0 for the protocol) + * @res: Storage place for the resulting list of returned addresses + * + * This will do a lookup of the node and service that you want to connect to. + * It returns a linked list of different addresses you can try to connect to. + * + * When no longer needed you should call BIO_ADDRINFO_free() to free the result. + * + * The return value is 1 on success or 0 in case of error. + */ +int BIO_lookup_ex(const char *host, const char *service, int lookup_type, + int family, int socktype, int protocol, BIO_ADDRINFO **res) +{ + int ret = 0; /* Assume failure */ + + switch(family) { + case AF_INET: +#ifdef AF_INET6 + case AF_INET6: +#endif +#ifdef AF_UNIX + case AF_UNIX: +#endif +#ifdef AF_UNSPEC + case AF_UNSPEC: +#endif + break; + default: + BIOerr(BIO_F_BIO_LOOKUP_EX, BIO_R_UNSUPPORTED_PROTOCOL_FAMILY); + return 0; + } + +#ifdef AF_UNIX + if (family == AF_UNIX) { + if (addrinfo_wrap(family, socktype, host, strlen(host), 0, res)) + return 1; + else + BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_MALLOC_FAILURE); + return 0; + } +#endif + + if (BIO_sock_init() != 1) + return 0; + + if (1) { +#ifdef AI_PASSIVE + int gai_ret = 0; + struct addrinfo hints; + + memset(&hints, 0, sizeof(hints)); + + hints.ai_family = family; + hints.ai_socktype = socktype; + hints.ai_protocol = protocol; + + if (lookup_type == BIO_LOOKUP_SERVER) + hints.ai_flags |= AI_PASSIVE; + + /* Note that |res| SHOULD be a 'struct addrinfo **' thanks to + * macro magic in bio_lcl.h + */ + switch ((gai_ret = getaddrinfo(host, service, &hints, res))) { +# ifdef EAI_SYSTEM + case EAI_SYSTEM: + SYSerr(SYS_F_GETADDRINFO, get_last_socket_error()); + BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_SYS_LIB); + break; +# endif + case 0: + ret = 1; /* Success */ + break; + default: + BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_SYS_LIB); + ERR_add_error_data(1, gai_strerror(gai_ret)); + break; + } + } else { +#endif + const struct hostent *he; +/* + * Because struct hostent is defined for 32-bit pointers only with + * VMS C, we need to make sure that '&he_fallback_address' and + * '&he_fallback_addresses' are 32-bit pointers + */ +#if defined(OPENSSL_SYS_VMS) && defined(__DECC) +# pragma pointer_size save +# pragma pointer_size 32 +#endif + /* Windows doesn't seem to have in_addr_t */ +#ifdef OPENSSL_SYS_WINDOWS + static uint32_t he_fallback_address; + static const char *he_fallback_addresses[] = + { (char *)&he_fallback_address, NULL }; +#else + static in_addr_t he_fallback_address; + static const char *he_fallback_addresses[] = + { (char *)&he_fallback_address, NULL }; +#endif + static const struct hostent he_fallback = + { NULL, NULL, AF_INET, sizeof(he_fallback_address), + (char **)&he_fallback_addresses }; +#if defined(OPENSSL_SYS_VMS) && defined(__DECC) +# pragma pointer_size restore +#endif + + struct servent *se; + /* Apparently, on WIN64, s_proto and s_port have traded places... */ +#ifdef _WIN64 + struct servent se_fallback = { NULL, NULL, NULL, 0 }; +#else + struct servent se_fallback = { NULL, NULL, 0, NULL }; +#endif + + if (!RUN_ONCE(&bio_lookup_init, do_bio_lookup_init)) { + BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_MALLOC_FAILURE); + ret = 0; + goto err; + } + + CRYPTO_THREAD_write_lock(bio_lookup_lock); + he_fallback_address = INADDR_ANY; + if (host == NULL) { + he = &he_fallback; + switch(lookup_type) { + case BIO_LOOKUP_CLIENT: + he_fallback_address = INADDR_LOOPBACK; + break; + case BIO_LOOKUP_SERVER: + he_fallback_address = INADDR_ANY; + break; + default: + /* We forgot to handle a lookup type! */ + assert("We forgot to handle a lookup type!" == NULL); + BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_INTERNAL_ERROR); + ret = 0; + goto err; + } + } else { + he = gethostbyname(host); + + if (he == NULL) { +#ifndef OPENSSL_SYS_WINDOWS + /* + * This might be misleading, because h_errno is used as if + * it was errno. To minimize mixup add 1000. Underlying + * reason for this is that hstrerror is declared obsolete, + * not to mention that a) h_errno is not always guaranteed + * to be meaningless; b) hstrerror can reside in yet another + * library, linking for sake of hstrerror is an overkill; + * c) this path is not executed on contemporary systems + * anyway [above getaddrinfo/gai_strerror is]. We just let + * system administrator figure this out... + */ +# if defined(OPENSSL_SYS_VXWORKS) + /* h_errno doesn't exist on VxWorks */ + SYSerr(SYS_F_GETHOSTBYNAME, 1000 ); +# else + SYSerr(SYS_F_GETHOSTBYNAME, 1000 + h_errno); +# endif +#else + SYSerr(SYS_F_GETHOSTBYNAME, WSAGetLastError()); +#endif + ret = 0; + goto err; + } + } + + if (service == NULL) { + se_fallback.s_port = 0; + se_fallback.s_proto = NULL; + se = &se_fallback; + } else { + char *endp = NULL; + long portnum = strtol(service, &endp, 10); + +/* + * Because struct servent is defined for 32-bit pointers only with + * VMS C, we need to make sure that 'proto' is a 32-bit pointer. + */ +#if defined(OPENSSL_SYS_VMS) && defined(__DECC) +# pragma pointer_size save +# pragma pointer_size 32 +#endif + char *proto = NULL; +#if defined(OPENSSL_SYS_VMS) && defined(__DECC) +# pragma pointer_size restore +#endif + + switch (socktype) { + case SOCK_STREAM: + proto = "tcp"; + break; + case SOCK_DGRAM: + proto = "udp"; + break; + } + + if (endp != service && *endp == '\0' + && portnum > 0 && portnum < 65536) { + se_fallback.s_port = htons((unsigned short)portnum); + se_fallback.s_proto = proto; + se = &se_fallback; + } else if (endp == service) { + se = getservbyname(service, proto); + + if (se == NULL) { +#ifndef OPENSSL_SYS_WINDOWS + SYSerr(SYS_F_GETSERVBYNAME, errno); +#else + SYSerr(SYS_F_GETSERVBYNAME, WSAGetLastError()); +#endif + goto err; + } + } else { + BIOerr(BIO_F_BIO_LOOKUP_EX, BIO_R_MALFORMED_HOST_OR_SERVICE); + goto err; + } + } + + *res = NULL; + + { +/* + * Because hostent::h_addr_list is an array of 32-bit pointers with VMS C, + * we must make sure our iterator designates the same element type, hence + * the pointer size dance. + */ +#if defined(OPENSSL_SYS_VMS) && defined(__DECC) +# pragma pointer_size save +# pragma pointer_size 32 +#endif + char **addrlistp; +#if defined(OPENSSL_SYS_VMS) && defined(__DECC) +# pragma pointer_size restore +#endif + size_t addresses; + BIO_ADDRINFO *tmp_bai = NULL; + + /* The easiest way to create a linked list from an + array is to start from the back */ + for(addrlistp = he->h_addr_list; *addrlistp != NULL; + addrlistp++) + ; + + for(addresses = addrlistp - he->h_addr_list; + addrlistp--, addresses-- > 0; ) { + if (!addrinfo_wrap(he->h_addrtype, socktype, + *addrlistp, he->h_length, + se->s_port, &tmp_bai)) + goto addrinfo_malloc_err; + tmp_bai->bai_next = *res; + *res = tmp_bai; + continue; + addrinfo_malloc_err: + BIO_ADDRINFO_free(*res); + *res = NULL; + BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_MALLOC_FAILURE); + ret = 0; + goto err; + } + + ret = 1; + } + err: + CRYPTO_THREAD_unlock(bio_lookup_lock); + } + + return ret; +} + +#endif /* OPENSSL_NO_SOCK */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_dump.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_dump.c new file mode 100644 index 000000000..0d06414e7 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_dump.c @@ -0,0 +1,148 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Stolen from tjh's ssl/ssl_trc.c stuff. + */ + +#include +#include "bio_lcl.h" + +#define DUMP_WIDTH 16 +#define DUMP_WIDTH_LESS_INDENT(i) (DUMP_WIDTH - ((i - (i > 6 ? 6 : i) + 3) / 4)) + +#define SPACE(buf, pos, n) (sizeof(buf) - (pos) > (n)) + +int BIO_dump_cb(int (*cb) (const void *data, size_t len, void *u), + void *u, const char *s, int len) +{ + return BIO_dump_indent_cb(cb, u, s, len, 0); +} + +int BIO_dump_indent_cb(int (*cb) (const void *data, size_t len, void *u), + void *u, const char *s, int len, int indent) +{ + int ret = 0; + char buf[288 + 1]; + int i, j, rows, n; + unsigned char ch; + int dump_width; + + if (indent < 0) + indent = 0; + else if (indent > 128) + indent = 128; + + dump_width = DUMP_WIDTH_LESS_INDENT(indent); + rows = len / dump_width; + if ((rows * dump_width) < len) + rows++; + for (i = 0; i < rows; i++) { + n = BIO_snprintf(buf, sizeof(buf), "%*s%04x - ", indent, "", + i * dump_width); + for (j = 0; j < dump_width; j++) { + if (SPACE(buf, n, 3)) { + if (((i * dump_width) + j) >= len) { + strcpy(buf + n, " "); + } else { + ch = ((unsigned char)*(s + i * dump_width + j)) & 0xff; + BIO_snprintf(buf + n, 4, "%02x%c", ch, + j == 7 ? '-' : ' '); + } + n += 3; + } + } + if (SPACE(buf, n, 2)) { + strcpy(buf + n, " "); + n += 2; + } + for (j = 0; j < dump_width; j++) { + if (((i * dump_width) + j) >= len) + break; + if (SPACE(buf, n, 1)) { + ch = ((unsigned char)*(s + i * dump_width + j)) & 0xff; +#ifndef CHARSET_EBCDIC + buf[n++] = ((ch >= ' ') && (ch <= '~')) ? ch : '.'; +#else + buf[n++] = ((ch >= os_toascii[' ']) && (ch <= os_toascii['~'])) + ? os_toebcdic[ch] + : '.'; +#endif + buf[n] = '\0'; + } + } + if (SPACE(buf, n, 1)) { + buf[n++] = '\n'; + buf[n] = '\0'; + } + /* + * if this is the last call then update the ddt_dump thing so that we + * will move the selection point in the debug window + */ + ret += cb((void *)buf, n, u); + } + return ret; +} + +#ifndef OPENSSL_NO_STDIO +static int write_fp(const void *data, size_t len, void *fp) +{ + return UP_fwrite(data, len, 1, fp); +} + +int BIO_dump_fp(FILE *fp, const char *s, int len) +{ + return BIO_dump_cb(write_fp, fp, s, len); +} + +int BIO_dump_indent_fp(FILE *fp, const char *s, int len, int indent) +{ + return BIO_dump_indent_cb(write_fp, fp, s, len, indent); +} +#endif + +static int write_bio(const void *data, size_t len, void *bp) +{ + return BIO_write((BIO *)bp, (const char *)data, len); +} + +int BIO_dump(BIO *bp, const char *s, int len) +{ + return BIO_dump_cb(write_bio, bp, s, len); +} + +int BIO_dump_indent(BIO *bp, const char *s, int len, int indent) +{ + return BIO_dump_indent_cb(write_bio, bp, s, len, indent); +} + +int BIO_hex_string(BIO *out, int indent, int width, unsigned char *data, + int datalen) +{ + int i, j = 0; + + if (datalen < 1) + return 1; + + for (i = 0; i < datalen - 1; i++) { + if (i && !j) + BIO_printf(out, "%*s", indent, ""); + + BIO_printf(out, "%02X:", data[i]); + + j = (j + 1) % width; + if (!j) + BIO_printf(out, "\n"); + } + + if (i && !j) + BIO_printf(out, "%*s", indent, ""); + BIO_printf(out, "%02X", data[datalen - 1]); + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_print.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_print.c new file mode 100644 index 000000000..9e907fcaa --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_print.c @@ -0,0 +1,930 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include "internal/ctype.h" +#include "internal/numbers.h" +#include + +/* + * Copyright Patrick Powell 1995 + * This code is based on code written by Patrick Powell + * It may be used for any purpose as long as this notice remains intact + * on all source code distributions. + */ + +#ifdef HAVE_LONG_DOUBLE +# define LDOUBLE long double +#else +# define LDOUBLE double +#endif + +static int fmtstr(char **, char **, size_t *, size_t *, + const char *, int, int, int); +static int fmtint(char **, char **, size_t *, size_t *, + int64_t, int, int, int, int); +static int fmtfp(char **, char **, size_t *, size_t *, + LDOUBLE, int, int, int, int); +static int doapr_outch(char **, char **, size_t *, size_t *, int); +static int _dopr(char **sbuffer, char **buffer, + size_t *maxlen, size_t *retlen, int *truncated, + const char *format, va_list args); + +/* format read states */ +#define DP_S_DEFAULT 0 +#define DP_S_FLAGS 1 +#define DP_S_MIN 2 +#define DP_S_DOT 3 +#define DP_S_MAX 4 +#define DP_S_MOD 5 +#define DP_S_CONV 6 +#define DP_S_DONE 7 + +/* format flags - Bits */ +/* left-aligned padding */ +#define DP_F_MINUS (1 << 0) +/* print an explicit '+' for a value with positive sign */ +#define DP_F_PLUS (1 << 1) +/* print an explicit ' ' for a value with positive sign */ +#define DP_F_SPACE (1 << 2) +/* print 0/0x prefix for octal/hex and decimal point for floating point */ +#define DP_F_NUM (1 << 3) +/* print leading zeroes */ +#define DP_F_ZERO (1 << 4) +/* print HEX in UPPPERcase */ +#define DP_F_UP (1 << 5) +/* treat value as unsigned */ +#define DP_F_UNSIGNED (1 << 6) + +/* conversion flags */ +#define DP_C_SHORT 1 +#define DP_C_LONG 2 +#define DP_C_LDOUBLE 3 +#define DP_C_LLONG 4 +#define DP_C_SIZE 5 + +/* Floating point formats */ +#define F_FORMAT 0 +#define E_FORMAT 1 +#define G_FORMAT 2 + +/* some handy macros */ +#define char_to_int(p) (p - '0') +#define OSSL_MAX(p,q) ((p >= q) ? p : q) + +static int +_dopr(char **sbuffer, + char **buffer, + size_t *maxlen, + size_t *retlen, int *truncated, const char *format, va_list args) +{ + char ch; + int64_t value; + LDOUBLE fvalue; + char *strvalue; + int min; + int max; + int state; + int flags; + int cflags; + size_t currlen; + + state = DP_S_DEFAULT; + flags = currlen = cflags = min = 0; + max = -1; + ch = *format++; + + while (state != DP_S_DONE) { + if (ch == '\0' || (buffer == NULL && currlen >= *maxlen)) + state = DP_S_DONE; + + switch (state) { + case DP_S_DEFAULT: + if (ch == '%') + state = DP_S_FLAGS; + else + if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch)) + return 0; + ch = *format++; + break; + case DP_S_FLAGS: + switch (ch) { + case '-': + flags |= DP_F_MINUS; + ch = *format++; + break; + case '+': + flags |= DP_F_PLUS; + ch = *format++; + break; + case ' ': + flags |= DP_F_SPACE; + ch = *format++; + break; + case '#': + flags |= DP_F_NUM; + ch = *format++; + break; + case '0': + flags |= DP_F_ZERO; + ch = *format++; + break; + default: + state = DP_S_MIN; + break; + } + break; + case DP_S_MIN: + if (ossl_isdigit(ch)) { + min = 10 * min + char_to_int(ch); + ch = *format++; + } else if (ch == '*') { + min = va_arg(args, int); + ch = *format++; + state = DP_S_DOT; + } else + state = DP_S_DOT; + break; + case DP_S_DOT: + if (ch == '.') { + state = DP_S_MAX; + ch = *format++; + } else + state = DP_S_MOD; + break; + case DP_S_MAX: + if (ossl_isdigit(ch)) { + if (max < 0) + max = 0; + max = 10 * max + char_to_int(ch); + ch = *format++; + } else if (ch == '*') { + max = va_arg(args, int); + ch = *format++; + state = DP_S_MOD; + } else + state = DP_S_MOD; + break; + case DP_S_MOD: + switch (ch) { + case 'h': + cflags = DP_C_SHORT; + ch = *format++; + break; + case 'l': + if (*format == 'l') { + cflags = DP_C_LLONG; + format++; + } else + cflags = DP_C_LONG; + ch = *format++; + break; + case 'q': + case 'j': + cflags = DP_C_LLONG; + ch = *format++; + break; + case 'L': + cflags = DP_C_LDOUBLE; + ch = *format++; + break; + case 'z': + cflags = DP_C_SIZE; + ch = *format++; + break; + default: + break; + } + state = DP_S_CONV; + break; + case DP_S_CONV: + switch (ch) { + case 'd': + case 'i': + switch (cflags) { + case DP_C_SHORT: + value = (short int)va_arg(args, int); + break; + case DP_C_LONG: + value = va_arg(args, long int); + break; + case DP_C_LLONG: + value = va_arg(args, int64_t); + break; + case DP_C_SIZE: + value = va_arg(args, ossl_ssize_t); + break; + default: + value = va_arg(args, int); + break; + } + if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min, + max, flags)) + return 0; + break; + case 'X': + flags |= DP_F_UP; + /* FALLTHROUGH */ + case 'x': + case 'o': + case 'u': + flags |= DP_F_UNSIGNED; + switch (cflags) { + case DP_C_SHORT: + value = (unsigned short int)va_arg(args, unsigned int); + break; + case DP_C_LONG: + value = va_arg(args, unsigned long int); + break; + case DP_C_LLONG: + value = va_arg(args, uint64_t); + break; + case DP_C_SIZE: + value = va_arg(args, size_t); + break; + default: + value = va_arg(args, unsigned int); + break; + } + if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, + ch == 'o' ? 8 : (ch == 'u' ? 10 : 16), + min, max, flags)) + return 0; + break; + case 'f': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg(args, LDOUBLE); + else + fvalue = va_arg(args, double); + if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max, + flags, F_FORMAT)) + return 0; + break; + case 'E': + flags |= DP_F_UP; + /* fall thru */ + case 'e': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg(args, LDOUBLE); + else + fvalue = va_arg(args, double); + if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max, + flags, E_FORMAT)) + return 0; + break; + case 'G': + flags |= DP_F_UP; + /* fall thru */ + case 'g': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg(args, LDOUBLE); + else + fvalue = va_arg(args, double); + if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max, + flags, G_FORMAT)) + return 0; + break; + case 'c': + if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, + va_arg(args, int))) + return 0; + break; + case 's': + strvalue = va_arg(args, char *); + if (max < 0) { + if (buffer) + max = INT_MAX; + else + max = *maxlen; + } + if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue, + flags, min, max)) + return 0; + break; + case 'p': + value = (size_t)va_arg(args, void *); + if (!fmtint(sbuffer, buffer, &currlen, maxlen, + value, 16, min, max, flags | DP_F_NUM)) + return 0; + break; + case 'n': + { + int *num; + num = va_arg(args, int *); + *num = currlen; + } + break; + case '%': + if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch)) + return 0; + break; + case 'w': + /* not supported yet, treat as next char */ + ch = *format++; + break; + default: + /* unknown, skip */ + break; + } + ch = *format++; + state = DP_S_DEFAULT; + flags = cflags = min = 0; + max = -1; + break; + case DP_S_DONE: + break; + default: + break; + } + } + /* + * We have to truncate if there is no dynamic buffer and we have filled the + * static buffer. + */ + if (buffer == NULL) { + *truncated = (currlen > *maxlen - 1); + if (*truncated) + currlen = *maxlen - 1; + } + if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0')) + return 0; + *retlen = currlen - 1; + return 1; +} + +static int +fmtstr(char **sbuffer, + char **buffer, + size_t *currlen, + size_t *maxlen, const char *value, int flags, int min, int max) +{ + int padlen; + size_t strln; + int cnt = 0; + + if (value == 0) + value = ""; + + strln = OPENSSL_strnlen(value, max < 0 ? SIZE_MAX : (size_t)max); + + padlen = min - strln; + if (min < 0 || padlen < 0) + padlen = 0; + if (max >= 0) { + /* + * Calculate the maximum output including padding. + * Make sure max doesn't overflow into negativity + */ + if (max < INT_MAX - padlen) + max += padlen; + else + max = INT_MAX; + } + if (flags & DP_F_MINUS) + padlen = -padlen; + + while ((padlen > 0) && (max < 0 || cnt < max)) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) + return 0; + --padlen; + ++cnt; + } + while (strln > 0 && (max < 0 || cnt < max)) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++)) + return 0; + --strln; + ++cnt; + } + while ((padlen < 0) && (max < 0 || cnt < max)) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) + return 0; + ++padlen; + ++cnt; + } + return 1; +} + +static int +fmtint(char **sbuffer, + char **buffer, + size_t *currlen, + size_t *maxlen, int64_t value, int base, int min, int max, int flags) +{ + int signvalue = 0; + const char *prefix = ""; + uint64_t uvalue; + char convert[DECIMAL_SIZE(value) + 3]; + int place = 0; + int spadlen = 0; + int zpadlen = 0; + int caps = 0; + + if (max < 0) + max = 0; + uvalue = value; + if (!(flags & DP_F_UNSIGNED)) { + if (value < 0) { + signvalue = '-'; + uvalue = 0 - (uint64_t)value; + } else if (flags & DP_F_PLUS) + signvalue = '+'; + else if (flags & DP_F_SPACE) + signvalue = ' '; + } + if (flags & DP_F_NUM) { + if (base == 8) + prefix = "0"; + if (base == 16) + prefix = "0x"; + } + if (flags & DP_F_UP) + caps = 1; + do { + convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef") + [uvalue % (unsigned)base]; + uvalue = (uvalue / (unsigned)base); + } while (uvalue && (place < (int)sizeof(convert))); + if (place == sizeof(convert)) + place--; + convert[place] = 0; + + zpadlen = max - place; + spadlen = + min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix); + if (zpadlen < 0) + zpadlen = 0; + if (spadlen < 0) + spadlen = 0; + if (flags & DP_F_ZERO) { + zpadlen = OSSL_MAX(zpadlen, spadlen); + spadlen = 0; + } + if (flags & DP_F_MINUS) + spadlen = -spadlen; + + /* spaces */ + while (spadlen > 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) + return 0; + --spadlen; + } + + /* sign */ + if (signvalue) + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) + return 0; + + /* prefix */ + while (*prefix) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix)) + return 0; + prefix++; + } + + /* zeros */ + if (zpadlen > 0) { + while (zpadlen > 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) + return 0; + --zpadlen; + } + } + /* digits */ + while (place > 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place])) + return 0; + } + + /* left justified spaces */ + while (spadlen < 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) + return 0; + ++spadlen; + } + return 1; +} + +static LDOUBLE abs_val(LDOUBLE value) +{ + LDOUBLE result = value; + if (value < 0) + result = -value; + return result; +} + +static LDOUBLE pow_10(int in_exp) +{ + LDOUBLE result = 1; + while (in_exp) { + result *= 10; + in_exp--; + } + return result; +} + +static long roundv(LDOUBLE value) +{ + long intpart; + intpart = (long)value; + value = value - intpart; + if (value >= 0.5) + intpart++; + return intpart; +} + +static int +fmtfp(char **sbuffer, + char **buffer, + size_t *currlen, + size_t *maxlen, LDOUBLE fvalue, int min, int max, int flags, int style) +{ + int signvalue = 0; + LDOUBLE ufvalue; + LDOUBLE tmpvalue; + char iconvert[20]; + char fconvert[20]; + char econvert[20]; + int iplace = 0; + int fplace = 0; + int eplace = 0; + int padlen = 0; + int zpadlen = 0; + long exp = 0; + unsigned long intpart; + unsigned long fracpart; + unsigned long max10; + int realstyle; + + if (max < 0) + max = 6; + + if (fvalue < 0) + signvalue = '-'; + else if (flags & DP_F_PLUS) + signvalue = '+'; + else if (flags & DP_F_SPACE) + signvalue = ' '; + + /* + * G_FORMAT sometimes prints like E_FORMAT and sometimes like F_FORMAT + * depending on the number to be printed. Work out which one it is and use + * that from here on. + */ + if (style == G_FORMAT) { + if (fvalue == 0.0) { + realstyle = F_FORMAT; + } else if (fvalue < 0.0001) { + realstyle = E_FORMAT; + } else if ((max == 0 && fvalue >= 10) + || (max > 0 && fvalue >= pow_10(max))) { + realstyle = E_FORMAT; + } else { + realstyle = F_FORMAT; + } + } else { + realstyle = style; + } + + if (style != F_FORMAT) { + tmpvalue = fvalue; + /* Calculate the exponent */ + if (fvalue != 0.0) { + while (tmpvalue < 1) { + tmpvalue *= 10; + exp--; + } + while (tmpvalue > 10) { + tmpvalue /= 10; + exp++; + } + } + if (style == G_FORMAT) { + /* + * In G_FORMAT the "precision" represents significant digits. We + * always have at least 1 significant digit. + */ + if (max == 0) + max = 1; + /* Now convert significant digits to decimal places */ + if (realstyle == F_FORMAT) { + max -= (exp + 1); + if (max < 0) { + /* + * Should not happen. If we're in F_FORMAT then exp < max? + */ + return 0; + } + } else { + /* + * In E_FORMAT there is always one significant digit in front + * of the decimal point, so: + * significant digits == 1 + decimal places + */ + max--; + } + } + if (realstyle == E_FORMAT) + fvalue = tmpvalue; + } + ufvalue = abs_val(fvalue); + if (ufvalue > ULONG_MAX) { + /* Number too big */ + return 0; + } + intpart = (unsigned long)ufvalue; + + /* + * sorry, we only support 9 digits past the decimal because of our + * conversion method + */ + if (max > 9) + max = 9; + + /* + * we "cheat" by converting the fractional part to integer by multiplying + * by a factor of 10 + */ + max10 = roundv(pow_10(max)); + fracpart = roundv(pow_10(max) * (ufvalue - intpart)); + + if (fracpart >= max10) { + intpart++; + fracpart -= max10; + } + + /* convert integer part */ + do { + iconvert[iplace++] = "0123456789"[intpart % 10]; + intpart = (intpart / 10); + } while (intpart && (iplace < (int)sizeof(iconvert))); + if (iplace == sizeof(iconvert)) + iplace--; + iconvert[iplace] = 0; + + /* convert fractional part */ + while (fplace < max) { + if (style == G_FORMAT && fplace == 0 && (fracpart % 10) == 0) { + /* We strip trailing zeros in G_FORMAT */ + max--; + fracpart = fracpart / 10; + if (fplace < max) + continue; + break; + } + fconvert[fplace++] = "0123456789"[fracpart % 10]; + fracpart = (fracpart / 10); + } + + if (fplace == sizeof(fconvert)) + fplace--; + fconvert[fplace] = 0; + + /* convert exponent part */ + if (realstyle == E_FORMAT) { + int tmpexp; + if (exp < 0) + tmpexp = -exp; + else + tmpexp = exp; + + do { + econvert[eplace++] = "0123456789"[tmpexp % 10]; + tmpexp = (tmpexp / 10); + } while (tmpexp > 0 && eplace < (int)sizeof(econvert)); + /* Exponent is huge!! Too big to print */ + if (tmpexp > 0) + return 0; + /* Add a leading 0 for single digit exponents */ + if (eplace == 1) + econvert[eplace++] = '0'; + } + + /* + * -1 for decimal point (if we have one, i.e. max > 0), + * another -1 if we are printing a sign + */ + padlen = min - iplace - max - (max > 0 ? 1 : 0) - ((signvalue) ? 1 : 0); + /* Take some off for exponent prefix "+e" and exponent */ + if (realstyle == E_FORMAT) + padlen -= 2 + eplace; + zpadlen = max - fplace; + if (zpadlen < 0) + zpadlen = 0; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; + + if ((flags & DP_F_ZERO) && (padlen > 0)) { + if (signvalue) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) + return 0; + --padlen; + signvalue = 0; + } + while (padlen > 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) + return 0; + --padlen; + } + } + while (padlen > 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) + return 0; + --padlen; + } + if (signvalue && !doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) + return 0; + + while (iplace > 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace])) + return 0; + } + + /* + * Decimal point. This should probably use locale to find the correct + * char to print out. + */ + if (max > 0 || (flags & DP_F_NUM)) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '.')) + return 0; + + while (fplace > 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, + fconvert[--fplace])) + return 0; + } + } + while (zpadlen > 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) + return 0; + --zpadlen; + } + if (realstyle == E_FORMAT) { + char ech; + + if ((flags & DP_F_UP) == 0) + ech = 'e'; + else + ech = 'E'; + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ech)) + return 0; + if (exp < 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '-')) + return 0; + } else { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '+')) + return 0; + } + while (eplace > 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, + econvert[--eplace])) + return 0; + } + } + + while (padlen < 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) + return 0; + ++padlen; + } + return 1; +} + +#define BUFFER_INC 1024 + +static int +doapr_outch(char **sbuffer, + char **buffer, size_t *currlen, size_t *maxlen, int c) +{ + /* If we haven't at least one buffer, someone has done a big booboo */ + if (!ossl_assert(*sbuffer != NULL || buffer != NULL)) + return 0; + + /* |currlen| must always be <= |*maxlen| */ + if (!ossl_assert(*currlen <= *maxlen)) + return 0; + + if (buffer && *currlen == *maxlen) { + if (*maxlen > INT_MAX - BUFFER_INC) + return 0; + + *maxlen += BUFFER_INC; + if (*buffer == NULL) { + if ((*buffer = OPENSSL_malloc(*maxlen)) == NULL) { + BIOerr(BIO_F_DOAPR_OUTCH, ERR_R_MALLOC_FAILURE); + return 0; + } + if (*currlen > 0) { + if (!ossl_assert(*sbuffer != NULL)) + return 0; + memcpy(*buffer, *sbuffer, *currlen); + } + *sbuffer = NULL; + } else { + char *tmpbuf; + tmpbuf = OPENSSL_realloc(*buffer, *maxlen); + if (tmpbuf == NULL) + return 0; + *buffer = tmpbuf; + } + } + + if (*currlen < *maxlen) { + if (*sbuffer) + (*sbuffer)[(*currlen)++] = (char)c; + else + (*buffer)[(*currlen)++] = (char)c; + } + + return 1; +} + +/***************************************************************************/ + +int BIO_printf(BIO *bio, const char *format, ...) +{ + va_list args; + int ret; + + va_start(args, format); + + ret = BIO_vprintf(bio, format, args); + + va_end(args); + return ret; +} + +int BIO_vprintf(BIO *bio, const char *format, va_list args) +{ + int ret; + size_t retlen; + char hugebuf[1024 * 2]; /* Was previously 10k, which is unreasonable + * in small-stack environments, like threads + * or DOS programs. */ + char *hugebufp = hugebuf; + size_t hugebufsize = sizeof(hugebuf); + char *dynbuf = NULL; + int ignored; + + dynbuf = NULL; + if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format, + args)) { + OPENSSL_free(dynbuf); + return -1; + } + if (dynbuf) { + ret = BIO_write(bio, dynbuf, (int)retlen); + OPENSSL_free(dynbuf); + } else { + ret = BIO_write(bio, hugebuf, (int)retlen); + } + return ret; +} + +/* + * As snprintf is not available everywhere, we provide our own + * implementation. This function has nothing to do with BIOs, but it's + * closely related to BIO_printf, and we need *some* name prefix ... (XXX the + * function should be renamed, but to what?) + */ +int BIO_snprintf(char *buf, size_t n, const char *format, ...) +{ + va_list args; + int ret; + + va_start(args, format); + + ret = BIO_vsnprintf(buf, n, format, args); + + va_end(args); + return ret; +} + +int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) +{ + size_t retlen; + int truncated; + + if (!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args)) + return -1; + + if (truncated) + /* + * In case of truncation, return -1 like traditional snprintf. + * (Current drafts for ISO/IEC 9899 say snprintf should return the + * number of characters that would have been written, had the buffer + * been large enough.) + */ + return -1; + else + return (retlen <= INT_MAX) ? (int)retlen : -1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_sock.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_sock.c new file mode 100644 index 000000000..e7a24d02c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_sock.c @@ -0,0 +1,369 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "bio_lcl.h" +#ifndef OPENSSL_NO_SOCK +# define SOCKET_PROTOCOL IPPROTO_TCP +# ifdef SO_MAXCONN +# define MAX_LISTEN SO_MAXCONN +# elif defined(SOMAXCONN) +# define MAX_LISTEN SOMAXCONN +# else +# define MAX_LISTEN 32 +# endif +# if defined(OPENSSL_SYS_WINDOWS) +static int wsa_init_done = 0; +# endif + +# if OPENSSL_API_COMPAT < 0x10100000L +int BIO_get_host_ip(const char *str, unsigned char *ip) +{ + BIO_ADDRINFO *res = NULL; + int ret = 0; + + if (BIO_sock_init() != 1) + return 0; /* don't generate another error code here */ + + if (BIO_lookup(str, NULL, BIO_LOOKUP_CLIENT, AF_INET, SOCK_STREAM, &res)) { + size_t l; + + if (BIO_ADDRINFO_family(res) != AF_INET) { + BIOerr(BIO_F_BIO_GET_HOST_IP, + BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET); + } else if (BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), NULL, &l)) { + /* + * Because only AF_INET addresses will reach this far, we can assert + * that l should be 4 + */ + if (ossl_assert(l == 4)) + ret = BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), ip, &l); + } + BIO_ADDRINFO_free(res); + } else { + ERR_add_error_data(2, "host=", str); + } + + return ret; +} + +int BIO_get_port(const char *str, unsigned short *port_ptr) +{ + BIO_ADDRINFO *res = NULL; + int ret = 0; + + if (str == NULL) { + BIOerr(BIO_F_BIO_GET_PORT, BIO_R_NO_PORT_DEFINED); + return 0; + } + + if (BIO_sock_init() != 1) + return 0; /* don't generate another error code here */ + + if (BIO_lookup(NULL, str, BIO_LOOKUP_CLIENT, AF_INET, SOCK_STREAM, &res)) { + if (BIO_ADDRINFO_family(res) != AF_INET) { + BIOerr(BIO_F_BIO_GET_PORT, + BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET); + } else { + *port_ptr = ntohs(BIO_ADDR_rawport(BIO_ADDRINFO_address(res))); + ret = 1; + } + BIO_ADDRINFO_free(res); + } else { + ERR_add_error_data(2, "host=", str); + } + + return ret; +} +# endif + +int BIO_sock_error(int sock) +{ + int j = 0, i; + socklen_t size = sizeof(j); + + /* + * Note: under Windows the third parameter is of type (char *) whereas + * under other systems it is (void *) if you don't have a cast it will + * choke the compiler: if you do have a cast then you can either go for + * (char *) or (void *). + */ + i = getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *)&j, &size); + if (i < 0) + return get_last_socket_error(); + else + return j; +} + +# if OPENSSL_API_COMPAT < 0x10100000L +struct hostent *BIO_gethostbyname(const char *name) +{ + /* + * Caching gethostbyname() results forever is wrong, so we have to let + * the true gethostbyname() worry about this + */ + return gethostbyname(name); +} +# endif + +int BIO_sock_init(void) +{ +# ifdef OPENSSL_SYS_WINDOWS + static struct WSAData wsa_state; + + if (!wsa_init_done) { + int err; + + wsa_init_done = 1; + memset(&wsa_state, 0, sizeof(wsa_state)); + /* + * Not making wsa_state available to the rest of the code is formally + * wrong. But the structures we use are [believed to be] invariable + * among Winsock DLLs, while API availability is [expected to be] + * probed at run-time with DSO_global_lookup. + */ + if (WSAStartup(0x0202, &wsa_state) != 0) { + err = WSAGetLastError(); + SYSerr(SYS_F_WSASTARTUP, err); + BIOerr(BIO_F_BIO_SOCK_INIT, BIO_R_WSASTARTUP); + return -1; + } + } +# endif /* OPENSSL_SYS_WINDOWS */ +# ifdef WATT32 + extern int _watt_do_exit; + _watt_do_exit = 0; /* don't make sock_init() call exit() */ + if (sock_init()) + return -1; +# endif + + return 1; +} + +void bio_sock_cleanup_int(void) +{ +# ifdef OPENSSL_SYS_WINDOWS + if (wsa_init_done) { + wsa_init_done = 0; + WSACleanup(); + } +# endif +} + +int BIO_socket_ioctl(int fd, long type, void *arg) +{ + int i; + +# ifdef __DJGPP__ + i = ioctlsocket(fd, type, (char *)arg); +# else +# if defined(OPENSSL_SYS_VMS) + /*- + * 2011-02-18 SMS. + * VMS ioctl() can't tolerate a 64-bit "void *arg", but we + * observe that all the consumers pass in an "unsigned long *", + * so we arrange a local copy with a short pointer, and use + * that, instead. + */ +# if __INITIAL_POINTER_SIZE == 64 +# define ARG arg_32p +# pragma pointer_size save +# pragma pointer_size 32 + unsigned long arg_32; + unsigned long *arg_32p; +# pragma pointer_size restore + arg_32p = &arg_32; + arg_32 = *((unsigned long *)arg); +# else /* __INITIAL_POINTER_SIZE == 64 */ +# define ARG arg +# endif /* __INITIAL_POINTER_SIZE == 64 [else] */ +# else /* defined(OPENSSL_SYS_VMS) */ +# define ARG arg +# endif /* defined(OPENSSL_SYS_VMS) [else] */ + + i = ioctlsocket(fd, type, ARG); +# endif /* __DJGPP__ */ + if (i < 0) + SYSerr(SYS_F_IOCTLSOCKET, get_last_socket_error()); + return i; +} + +# if OPENSSL_API_COMPAT < 0x10100000L +int BIO_get_accept_socket(char *host, int bind_mode) +{ + int s = INVALID_SOCKET; + char *h = NULL, *p = NULL; + BIO_ADDRINFO *res = NULL; + + if (!BIO_parse_hostserv(host, &h, &p, BIO_PARSE_PRIO_SERV)) + return INVALID_SOCKET; + + if (BIO_sock_init() != 1) + return INVALID_SOCKET; + + if (BIO_lookup(h, p, BIO_LOOKUP_SERVER, AF_UNSPEC, SOCK_STREAM, &res) != 0) + goto err; + + if ((s = BIO_socket(BIO_ADDRINFO_family(res), BIO_ADDRINFO_socktype(res), + BIO_ADDRINFO_protocol(res), 0)) == INVALID_SOCKET) { + s = INVALID_SOCKET; + goto err; + } + + if (!BIO_listen(s, BIO_ADDRINFO_address(res), + bind_mode ? BIO_SOCK_REUSEADDR : 0)) { + BIO_closesocket(s); + s = INVALID_SOCKET; + } + + err: + BIO_ADDRINFO_free(res); + OPENSSL_free(h); + OPENSSL_free(p); + + return s; +} + +int BIO_accept(int sock, char **ip_port) +{ + BIO_ADDR res; + int ret = -1; + + ret = BIO_accept_ex(sock, &res, 0); + if (ret == (int)INVALID_SOCKET) { + if (BIO_sock_should_retry(ret)) { + ret = -2; + goto end; + } + SYSerr(SYS_F_ACCEPT, get_last_socket_error()); + BIOerr(BIO_F_BIO_ACCEPT, BIO_R_ACCEPT_ERROR); + goto end; + } + + if (ip_port != NULL) { + char *host = BIO_ADDR_hostname_string(&res, 1); + char *port = BIO_ADDR_service_string(&res, 1); + if (host != NULL && port != NULL) + *ip_port = OPENSSL_zalloc(strlen(host) + strlen(port) + 2); + else + *ip_port = NULL; + + if (*ip_port == NULL) { + BIOerr(BIO_F_BIO_ACCEPT, ERR_R_MALLOC_FAILURE); + BIO_closesocket(ret); + ret = (int)INVALID_SOCKET; + } else { + strcpy(*ip_port, host); + strcat(*ip_port, ":"); + strcat(*ip_port, port); + } + OPENSSL_free(host); + OPENSSL_free(port); + } + + end: + return ret; +} +# endif + +int BIO_set_tcp_ndelay(int s, int on) +{ + int ret = 0; +# if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP)) + int opt; + +# ifdef SOL_TCP + opt = SOL_TCP; +# else +# ifdef IPPROTO_TCP + opt = IPPROTO_TCP; +# endif +# endif + + ret = setsockopt(s, opt, TCP_NODELAY, (char *)&on, sizeof(on)); +# endif + return (ret == 0); +} + +int BIO_socket_nbio(int s, int mode) +{ + int ret = -1; + int l; + + l = mode; +# ifdef FIONBIO + l = mode; + + ret = BIO_socket_ioctl(s, FIONBIO, &l); +# elif defined(F_GETFL) && defined(F_SETFL) && (defined(O_NONBLOCK) || defined(FNDELAY)) + /* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */ + + l = fcntl(s, F_GETFL, 0); + if (l == -1) { + SYSerr(SYS_F_FCNTL, get_last_sys_error()); + ret = -1; + } else { +# if defined(O_NONBLOCK) + l &= ~O_NONBLOCK; +# else + l &= ~FNDELAY; /* BSD4.x */ +# endif + if (mode) { +# if defined(O_NONBLOCK) + l |= O_NONBLOCK; +# else + l |= FNDELAY; /* BSD4.x */ +# endif + } + ret = fcntl(s, F_SETFL, l); + + if (ret < 0) { + SYSerr(SYS_F_FCNTL, get_last_sys_error()); + } + } +# else + /* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */ + BIOerr(BIO_F_BIO_SOCKET_NBIO, ERR_R_PASSED_INVALID_ARGUMENT); +# endif + + return (ret == 0); +} + +int BIO_sock_info(int sock, + enum BIO_sock_info_type type, union BIO_sock_info_u *info) +{ + switch (type) { + case BIO_SOCK_INFO_ADDRESS: + { + socklen_t addr_len; + int ret = 0; + addr_len = sizeof(*info->addr); + ret = getsockname(sock, BIO_ADDR_sockaddr_noconst(info->addr), + &addr_len); + if (ret == -1) { + SYSerr(SYS_F_GETSOCKNAME, get_last_socket_error()); + BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_GETSOCKNAME_ERROR); + return 0; + } + if ((size_t)addr_len > sizeof(*info->addr)) { + BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS); + return 0; + } + } + break; + default: + BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_UNKNOWN_INFO_TYPE); + return 0; + } + return 1; +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_sock2.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_sock2.c new file mode 100644 index 000000000..5d82ab22d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_sock2.c @@ -0,0 +1,317 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include + +#include "bio_lcl.h" + +#include + +#ifndef OPENSSL_NO_SOCK +# ifdef SO_MAXCONN +# define MAX_LISTEN SO_MAXCONN +# elif defined(SOMAXCONN) +# define MAX_LISTEN SOMAXCONN +# else +# define MAX_LISTEN 32 +# endif + +/*- + * BIO_socket - create a socket + * @domain: the socket domain (AF_INET, AF_INET6, AF_UNIX, ...) + * @socktype: the socket type (SOCK_STEAM, SOCK_DGRAM) + * @protocol: the protocol to use (IPPROTO_TCP, IPPROTO_UDP) + * @options: BIO socket options (currently unused) + * + * Creates a socket. This should be called before calling any + * of BIO_connect and BIO_listen. + * + * Returns the file descriptor on success or INVALID_SOCKET on failure. On + * failure errno is set, and a status is added to the OpenSSL error stack. + */ +int BIO_socket(int domain, int socktype, int protocol, int options) +{ + int sock = -1; + + if (BIO_sock_init() != 1) + return INVALID_SOCKET; + + sock = socket(domain, socktype, protocol); + if (sock == -1) { + SYSerr(SYS_F_SOCKET, get_last_socket_error()); + BIOerr(BIO_F_BIO_SOCKET, BIO_R_UNABLE_TO_CREATE_SOCKET); + return INVALID_SOCKET; + } + + return sock; +} + +/*- + * BIO_connect - connect to an address + * @sock: the socket to connect with + * @addr: the address to connect to + * @options: BIO socket options + * + * Connects to the address using the given socket and options. + * + * Options can be a combination of the following: + * - BIO_SOCK_KEEPALIVE: enable regularly sending keep-alive messages. + * - BIO_SOCK_NONBLOCK: Make the socket non-blocking. + * - BIO_SOCK_NODELAY: don't delay small messages. + * + * options holds BIO socket options that can be used + * You should call this for every address returned by BIO_lookup + * until the connection is successful. + * + * Returns 1 on success or 0 on failure. On failure errno is set + * and an error status is added to the OpenSSL error stack. + */ +int BIO_connect(int sock, const BIO_ADDR *addr, int options) +{ + const int on = 1; + + if (sock == -1) { + BIOerr(BIO_F_BIO_CONNECT, BIO_R_INVALID_SOCKET); + return 0; + } + + if (!BIO_socket_nbio(sock, (options & BIO_SOCK_NONBLOCK) != 0)) + return 0; + + if (options & BIO_SOCK_KEEPALIVE) { + if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, + (const void *)&on, sizeof(on)) != 0) { + SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error()); + BIOerr(BIO_F_BIO_CONNECT, BIO_R_UNABLE_TO_KEEPALIVE); + return 0; + } + } + + if (options & BIO_SOCK_NODELAY) { + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, + (const void *)&on, sizeof(on)) != 0) { + SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error()); + BIOerr(BIO_F_BIO_CONNECT, BIO_R_UNABLE_TO_NODELAY); + return 0; + } + } + + if (connect(sock, BIO_ADDR_sockaddr(addr), + BIO_ADDR_sockaddr_size(addr)) == -1) { + if (!BIO_sock_should_retry(-1)) { + SYSerr(SYS_F_CONNECT, get_last_socket_error()); + BIOerr(BIO_F_BIO_CONNECT, BIO_R_CONNECT_ERROR); + } + return 0; + } + return 1; +} + +/*- + * BIO_bind - bind socket to address + * @sock: the socket to set + * @addr: local address to bind to + * @options: BIO socket options + * + * Binds to the address using the given socket and options. + * + * Options can be a combination of the following: + * - BIO_SOCK_REUSEADDR: Try to reuse the address and port combination + * for a recently closed port. + * + * When restarting the program it could be that the port is still in use. If + * you set to BIO_SOCK_REUSEADDR option it will try to reuse the port anyway. + * It's recommended that you use this. + */ +int BIO_bind(int sock, const BIO_ADDR *addr, int options) +{ +# ifndef OPENSSL_SYS_WINDOWS + int on = 1; +# endif + + if (sock == -1) { + BIOerr(BIO_F_BIO_BIND, BIO_R_INVALID_SOCKET); + return 0; + } + +# ifndef OPENSSL_SYS_WINDOWS + /* + * SO_REUSEADDR has different behavior on Windows than on + * other operating systems, don't set it there. + */ + if (options & BIO_SOCK_REUSEADDR) { + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, + (const void *)&on, sizeof(on)) != 0) { + SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error()); + BIOerr(BIO_F_BIO_BIND, BIO_R_UNABLE_TO_REUSEADDR); + return 0; + } + } +# endif + + if (bind(sock, BIO_ADDR_sockaddr(addr), BIO_ADDR_sockaddr_size(addr)) != 0) { + SYSerr(SYS_F_BIND, get_last_socket_error()); + BIOerr(BIO_F_BIO_BIND, BIO_R_UNABLE_TO_BIND_SOCKET); + return 0; + } + + return 1; +} + +/*- + * BIO_listen - Creates a listen socket + * @sock: the socket to listen with + * @addr: local address to bind to + * @options: BIO socket options + * + * Binds to the address using the given socket and options, then + * starts listening for incoming connections. + * + * Options can be a combination of the following: + * - BIO_SOCK_KEEPALIVE: enable regularly sending keep-alive messages. + * - BIO_SOCK_NONBLOCK: Make the socket non-blocking. + * - BIO_SOCK_NODELAY: don't delay small messages. + * - BIO_SOCK_REUSEADDR: Try to reuse the address and port combination + * for a recently closed port. + * - BIO_SOCK_V6_ONLY: When creating an IPv6 socket, make it listen only + * for IPv6 addresses and not IPv4 addresses mapped to IPv6. + * + * It's recommended that you set up both an IPv6 and IPv4 listen socket, and + * then check both for new clients that connect to it. You want to set up + * the socket as non-blocking in that case since else it could hang. + * + * Not all operating systems support IPv4 addresses on an IPv6 socket, and for + * others it's an option. If you pass the BIO_LISTEN_V6_ONLY it will try to + * create the IPv6 sockets to only listen for IPv6 connection. + * + * It could be that the first BIO_listen() call will listen to all the IPv6 + * and IPv4 addresses and that then trying to bind to the IPv4 address will + * fail. We can't tell the difference between already listening ourself to + * it and someone else listening to it when failing and errno is EADDRINUSE, so + * it's recommended to not give an error in that case if the first call was + * successful. + * + * When restarting the program it could be that the port is still in use. If + * you set to BIO_SOCK_REUSEADDR option it will try to reuse the port anyway. + * It's recommended that you use this. + */ +int BIO_listen(int sock, const BIO_ADDR *addr, int options) +{ + int on = 1; + int socktype; + socklen_t socktype_len = sizeof(socktype); + + if (sock == -1) { + BIOerr(BIO_F_BIO_LISTEN, BIO_R_INVALID_SOCKET); + return 0; + } + + if (getsockopt(sock, SOL_SOCKET, SO_TYPE, + (void *)&socktype, &socktype_len) != 0 + || socktype_len != sizeof(socktype)) { + SYSerr(SYS_F_GETSOCKOPT, get_last_socket_error()); + BIOerr(BIO_F_BIO_LISTEN, BIO_R_GETTING_SOCKTYPE); + return 0; + } + + if (!BIO_socket_nbio(sock, (options & BIO_SOCK_NONBLOCK) != 0)) + return 0; + + if (options & BIO_SOCK_KEEPALIVE) { + if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, + (const void *)&on, sizeof(on)) != 0) { + SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error()); + BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_KEEPALIVE); + return 0; + } + } + + if (options & BIO_SOCK_NODELAY) { + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, + (const void *)&on, sizeof(on)) != 0) { + SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error()); + BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_NODELAY); + return 0; + } + } + +# ifdef IPV6_V6ONLY + if (BIO_ADDR_family(addr) == AF_INET6) { + /* + * Note: Windows default of IPV6_V6ONLY is ON, and Linux is OFF. + * Therefore we always have to use setsockopt here. + */ + on = options & BIO_SOCK_V6_ONLY ? 1 : 0; + if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, + (const void *)&on, sizeof(on)) != 0) { + SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error()); + BIOerr(BIO_F_BIO_LISTEN, BIO_R_LISTEN_V6_ONLY); + return 0; + } + } +# endif + + if (!BIO_bind(sock, addr, options)) + return 0; + + if (socktype != SOCK_DGRAM && listen(sock, MAX_LISTEN) == -1) { + SYSerr(SYS_F_LISTEN, get_last_socket_error()); + BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_LISTEN_SOCKET); + return 0; + } + + return 1; +} + +/*- + * BIO_accept_ex - Accept new incoming connections + * @sock: the listening socket + * @addr: the BIO_ADDR to store the peer address in + * @options: BIO socket options, applied on the accepted socket. + * + */ +int BIO_accept_ex(int accept_sock, BIO_ADDR *addr_, int options) +{ + socklen_t len; + int accepted_sock; + BIO_ADDR locaddr; + BIO_ADDR *addr = addr_ == NULL ? &locaddr : addr_; + + len = sizeof(*addr); + accepted_sock = accept(accept_sock, + BIO_ADDR_sockaddr_noconst(addr), &len); + if (accepted_sock == -1) { + if (!BIO_sock_should_retry(accepted_sock)) { + SYSerr(SYS_F_ACCEPT, get_last_socket_error()); + BIOerr(BIO_F_BIO_ACCEPT_EX, BIO_R_ACCEPT_ERROR); + } + return INVALID_SOCKET; + } + + if (!BIO_socket_nbio(accepted_sock, (options & BIO_SOCK_NONBLOCK) != 0)) { + closesocket(accepted_sock); + return INVALID_SOCKET; + } + + return accepted_sock; +} + +/*- + * BIO_closesocket - Close a socket + * @sock: the socket to close + */ +int BIO_closesocket(int sock) +{ + if (closesocket(sock) < 0) + return 0; + return 1; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bf_buff.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bf_buff.c new file mode 100644 index 000000000..8e87a629b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bf_buff.c @@ -0,0 +1,475 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "bio_lcl.h" +#include "internal/cryptlib.h" + +static int buffer_write(BIO *h, const char *buf, int num); +static int buffer_read(BIO *h, char *buf, int size); +static int buffer_puts(BIO *h, const char *str); +static int buffer_gets(BIO *h, char *str, int size); +static long buffer_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int buffer_new(BIO *h); +static int buffer_free(BIO *data); +static long buffer_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); +#define DEFAULT_BUFFER_SIZE 4096 + +static const BIO_METHOD methods_buffer = { + BIO_TYPE_BUFFER, + "buffer", + /* TODO: Convert to new style write function */ + bwrite_conv, + buffer_write, + /* TODO: Convert to new style read function */ + bread_conv, + buffer_read, + buffer_puts, + buffer_gets, + buffer_ctrl, + buffer_new, + buffer_free, + buffer_callback_ctrl, +}; + +const BIO_METHOD *BIO_f_buffer(void) +{ + return &methods_buffer; +} + +static int buffer_new(BIO *bi) +{ + BIO_F_BUFFER_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); + + if (ctx == NULL) + return 0; + ctx->ibuf_size = DEFAULT_BUFFER_SIZE; + ctx->ibuf = OPENSSL_malloc(DEFAULT_BUFFER_SIZE); + if (ctx->ibuf == NULL) { + OPENSSL_free(ctx); + return 0; + } + ctx->obuf_size = DEFAULT_BUFFER_SIZE; + ctx->obuf = OPENSSL_malloc(DEFAULT_BUFFER_SIZE); + if (ctx->obuf == NULL) { + OPENSSL_free(ctx->ibuf); + OPENSSL_free(ctx); + return 0; + } + + bi->init = 1; + bi->ptr = (char *)ctx; + bi->flags = 0; + return 1; +} + +static int buffer_free(BIO *a) +{ + BIO_F_BUFFER_CTX *b; + + if (a == NULL) + return 0; + b = (BIO_F_BUFFER_CTX *)a->ptr; + OPENSSL_free(b->ibuf); + OPENSSL_free(b->obuf); + OPENSSL_free(a->ptr); + a->ptr = NULL; + a->init = 0; + a->flags = 0; + return 1; +} + +static int buffer_read(BIO *b, char *out, int outl) +{ + int i, num = 0; + BIO_F_BUFFER_CTX *ctx; + + if (out == NULL) + return 0; + ctx = (BIO_F_BUFFER_CTX *)b->ptr; + + if ((ctx == NULL) || (b->next_bio == NULL)) + return 0; + num = 0; + BIO_clear_retry_flags(b); + + start: + i = ctx->ibuf_len; + /* If there is stuff left over, grab it */ + if (i != 0) { + if (i > outl) + i = outl; + memcpy(out, &(ctx->ibuf[ctx->ibuf_off]), i); + ctx->ibuf_off += i; + ctx->ibuf_len -= i; + num += i; + if (outl == i) + return num; + outl -= i; + out += i; + } + + /* + * We may have done a partial read. try to do more. We have nothing in + * the buffer. If we get an error and have read some data, just return it + * and let them retry to get the error again. copy direct to parent + * address space + */ + if (outl > ctx->ibuf_size) { + for (;;) { + i = BIO_read(b->next_bio, out, outl); + if (i <= 0) { + BIO_copy_next_retry(b); + if (i < 0) + return ((num > 0) ? num : i); + if (i == 0) + return num; + } + num += i; + if (outl == i) + return num; + out += i; + outl -= i; + } + } + /* else */ + + /* we are going to be doing some buffering */ + i = BIO_read(b->next_bio, ctx->ibuf, ctx->ibuf_size); + if (i <= 0) { + BIO_copy_next_retry(b); + if (i < 0) + return ((num > 0) ? num : i); + if (i == 0) + return num; + } + ctx->ibuf_off = 0; + ctx->ibuf_len = i; + + /* Lets re-read using ourselves :-) */ + goto start; +} + +static int buffer_write(BIO *b, const char *in, int inl) +{ + int i, num = 0; + BIO_F_BUFFER_CTX *ctx; + + if ((in == NULL) || (inl <= 0)) + return 0; + ctx = (BIO_F_BUFFER_CTX *)b->ptr; + if ((ctx == NULL) || (b->next_bio == NULL)) + return 0; + + BIO_clear_retry_flags(b); + start: + i = ctx->obuf_size - (ctx->obuf_len + ctx->obuf_off); + /* add to buffer and return */ + if (i >= inl) { + memcpy(&(ctx->obuf[ctx->obuf_off + ctx->obuf_len]), in, inl); + ctx->obuf_len += inl; + return (num + inl); + } + /* else */ + /* stuff already in buffer, so add to it first, then flush */ + if (ctx->obuf_len != 0) { + if (i > 0) { /* lets fill it up if we can */ + memcpy(&(ctx->obuf[ctx->obuf_off + ctx->obuf_len]), in, i); + in += i; + inl -= i; + num += i; + ctx->obuf_len += i; + } + /* we now have a full buffer needing flushing */ + for (;;) { + i = BIO_write(b->next_bio, &(ctx->obuf[ctx->obuf_off]), + ctx->obuf_len); + if (i <= 0) { + BIO_copy_next_retry(b); + + if (i < 0) + return ((num > 0) ? num : i); + if (i == 0) + return num; + } + ctx->obuf_off += i; + ctx->obuf_len -= i; + if (ctx->obuf_len == 0) + break; + } + } + /* + * we only get here if the buffer has been flushed and we still have + * stuff to write + */ + ctx->obuf_off = 0; + + /* we now have inl bytes to write */ + while (inl >= ctx->obuf_size) { + i = BIO_write(b->next_bio, in, inl); + if (i <= 0) { + BIO_copy_next_retry(b); + if (i < 0) + return ((num > 0) ? num : i); + if (i == 0) + return num; + } + num += i; + in += i; + inl -= i; + if (inl == 0) + return num; + } + + /* + * copy the rest into the buffer since we have only a small amount left + */ + goto start; +} + +static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + BIO *dbio; + BIO_F_BUFFER_CTX *ctx; + long ret = 1; + char *p1, *p2; + int r, i, *ip; + int ibs, obs; + + ctx = (BIO_F_BUFFER_CTX *)b->ptr; + + switch (cmd) { + case BIO_CTRL_RESET: + ctx->ibuf_off = 0; + ctx->ibuf_len = 0; + ctx->obuf_off = 0; + ctx->obuf_len = 0; + if (b->next_bio == NULL) + return 0; + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + break; + case BIO_CTRL_EOF: + if (ctx->ibuf_len > 0) + return 0; + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + break; + case BIO_CTRL_INFO: + ret = (long)ctx->obuf_len; + break; + case BIO_C_GET_BUFF_NUM_LINES: + ret = 0; + p1 = ctx->ibuf; + for (i = 0; i < ctx->ibuf_len; i++) { + if (p1[ctx->ibuf_off + i] == '\n') + ret++; + } + break; + case BIO_CTRL_WPENDING: + ret = (long)ctx->obuf_len; + if (ret == 0) { + if (b->next_bio == NULL) + return 0; + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + } + break; + case BIO_CTRL_PENDING: + ret = (long)ctx->ibuf_len; + if (ret == 0) { + if (b->next_bio == NULL) + return 0; + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + } + break; + case BIO_C_SET_BUFF_READ_DATA: + if (num > ctx->ibuf_size) { + p1 = OPENSSL_malloc((int)num); + if (p1 == NULL) + goto malloc_error; + OPENSSL_free(ctx->ibuf); + ctx->ibuf = p1; + } + ctx->ibuf_off = 0; + ctx->ibuf_len = (int)num; + memcpy(ctx->ibuf, ptr, (int)num); + ret = 1; + break; + case BIO_C_SET_BUFF_SIZE: + if (ptr != NULL) { + ip = (int *)ptr; + if (*ip == 0) { + ibs = (int)num; + obs = ctx->obuf_size; + } else { /* if (*ip == 1) */ + + ibs = ctx->ibuf_size; + obs = (int)num; + } + } else { + ibs = (int)num; + obs = (int)num; + } + p1 = ctx->ibuf; + p2 = ctx->obuf; + if ((ibs > DEFAULT_BUFFER_SIZE) && (ibs != ctx->ibuf_size)) { + p1 = OPENSSL_malloc((int)num); + if (p1 == NULL) + goto malloc_error; + } + if ((obs > DEFAULT_BUFFER_SIZE) && (obs != ctx->obuf_size)) { + p2 = OPENSSL_malloc((int)num); + if (p2 == NULL) { + if (p1 != ctx->ibuf) + OPENSSL_free(p1); + goto malloc_error; + } + } + if (ctx->ibuf != p1) { + OPENSSL_free(ctx->ibuf); + ctx->ibuf = p1; + ctx->ibuf_off = 0; + ctx->ibuf_len = 0; + ctx->ibuf_size = ibs; + } + if (ctx->obuf != p2) { + OPENSSL_free(ctx->obuf); + ctx->obuf = p2; + ctx->obuf_off = 0; + ctx->obuf_len = 0; + ctx->obuf_size = obs; + } + break; + case BIO_C_DO_STATE_MACHINE: + if (b->next_bio == NULL) + return 0; + BIO_clear_retry_flags(b); + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + BIO_copy_next_retry(b); + break; + + case BIO_CTRL_FLUSH: + if (b->next_bio == NULL) + return 0; + if (ctx->obuf_len <= 0) { + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + break; + } + + for (;;) { + BIO_clear_retry_flags(b); + if (ctx->obuf_len > 0) { + r = BIO_write(b->next_bio, + &(ctx->obuf[ctx->obuf_off]), ctx->obuf_len); + BIO_copy_next_retry(b); + if (r <= 0) + return (long)r; + ctx->obuf_off += r; + ctx->obuf_len -= r; + } else { + ctx->obuf_len = 0; + ctx->obuf_off = 0; + break; + } + } + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + break; + case BIO_CTRL_DUP: + dbio = (BIO *)ptr; + if (!BIO_set_read_buffer_size(dbio, ctx->ibuf_size) || + !BIO_set_write_buffer_size(dbio, ctx->obuf_size)) + ret = 0; + break; + case BIO_CTRL_PEEK: + /* Ensure there's stuff in the input buffer */ + { + char fake_buf[1]; + (void)buffer_read(b, fake_buf, 0); + } + if (num > ctx->ibuf_len) + num = ctx->ibuf_len; + memcpy(ptr, &(ctx->ibuf[ctx->ibuf_off]), num); + ret = num; + break; + default: + if (b->next_bio == NULL) + return 0; + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + break; + } + return ret; + malloc_error: + BIOerr(BIO_F_BUFFER_CTRL, ERR_R_MALLOC_FAILURE); + return 0; +} + +static long buffer_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) +{ + long ret = 1; + + if (b->next_bio == NULL) + return 0; + switch (cmd) { + default: + ret = BIO_callback_ctrl(b->next_bio, cmd, fp); + break; + } + return ret; +} + +static int buffer_gets(BIO *b, char *buf, int size) +{ + BIO_F_BUFFER_CTX *ctx; + int num = 0, i, flag; + char *p; + + ctx = (BIO_F_BUFFER_CTX *)b->ptr; + size--; /* reserve space for a '\0' */ + BIO_clear_retry_flags(b); + + for (;;) { + if (ctx->ibuf_len > 0) { + p = &(ctx->ibuf[ctx->ibuf_off]); + flag = 0; + for (i = 0; (i < ctx->ibuf_len) && (i < size); i++) { + *(buf++) = p[i]; + if (p[i] == '\n') { + flag = 1; + i++; + break; + } + } + num += i; + size -= i; + ctx->ibuf_len -= i; + ctx->ibuf_off += i; + if (flag || size == 0) { + *buf = '\0'; + return num; + } + } else { /* read another chunk */ + + i = BIO_read(b->next_bio, ctx->ibuf, ctx->ibuf_size); + if (i <= 0) { + BIO_copy_next_retry(b); + *buf = '\0'; + if (i < 0) + return ((num > 0) ? num : i); + if (i == 0) + return num; + } + ctx->ibuf_len = i; + ctx->ibuf_off = 0; + } + } +} + +static int buffer_puts(BIO *b, const char *str) +{ + return buffer_write(b, str, strlen(str)); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bf_lbuf.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bf_lbuf.c new file mode 100644 index 000000000..194c7b8af --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bf_lbuf.c @@ -0,0 +1,326 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "bio_lcl.h" +#include "internal/cryptlib.h" +#include + +static int linebuffer_write(BIO *h, const char *buf, int num); +static int linebuffer_read(BIO *h, char *buf, int size); +static int linebuffer_puts(BIO *h, const char *str); +static int linebuffer_gets(BIO *h, char *str, int size); +static long linebuffer_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int linebuffer_new(BIO *h); +static int linebuffer_free(BIO *data); +static long linebuffer_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); + +/* A 10k maximum should be enough for most purposes */ +#define DEFAULT_LINEBUFFER_SIZE 1024*10 + +/* #define DEBUG */ + +static const BIO_METHOD methods_linebuffer = { + BIO_TYPE_LINEBUFFER, + "linebuffer", + /* TODO: Convert to new style write function */ + bwrite_conv, + linebuffer_write, + /* TODO: Convert to new style read function */ + bread_conv, + linebuffer_read, + linebuffer_puts, + linebuffer_gets, + linebuffer_ctrl, + linebuffer_new, + linebuffer_free, + linebuffer_callback_ctrl, +}; + +const BIO_METHOD *BIO_f_linebuffer(void) +{ + return &methods_linebuffer; +} + +typedef struct bio_linebuffer_ctx_struct { + char *obuf; /* the output char array */ + int obuf_size; /* how big is the output buffer */ + int obuf_len; /* how many bytes are in it */ +} BIO_LINEBUFFER_CTX; + +static int linebuffer_new(BIO *bi) +{ + BIO_LINEBUFFER_CTX *ctx; + + if ((ctx = OPENSSL_malloc(sizeof(*ctx))) == NULL) { + BIOerr(BIO_F_LINEBUFFER_NEW, ERR_R_MALLOC_FAILURE); + return 0; + } + ctx->obuf = OPENSSL_malloc(DEFAULT_LINEBUFFER_SIZE); + if (ctx->obuf == NULL) { + BIOerr(BIO_F_LINEBUFFER_NEW, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ctx); + return 0; + } + ctx->obuf_size = DEFAULT_LINEBUFFER_SIZE; + ctx->obuf_len = 0; + + bi->init = 1; + bi->ptr = (char *)ctx; + bi->flags = 0; + return 1; +} + +static int linebuffer_free(BIO *a) +{ + BIO_LINEBUFFER_CTX *b; + + if (a == NULL) + return 0; + b = (BIO_LINEBUFFER_CTX *)a->ptr; + OPENSSL_free(b->obuf); + OPENSSL_free(a->ptr); + a->ptr = NULL; + a->init = 0; + a->flags = 0; + return 1; +} + +static int linebuffer_read(BIO *b, char *out, int outl) +{ + int ret = 0; + + if (out == NULL) + return 0; + if (b->next_bio == NULL) + return 0; + ret = BIO_read(b->next_bio, out, outl); + BIO_clear_retry_flags(b); + BIO_copy_next_retry(b); + return ret; +} + +static int linebuffer_write(BIO *b, const char *in, int inl) +{ + int i, num = 0, foundnl; + BIO_LINEBUFFER_CTX *ctx; + + if ((in == NULL) || (inl <= 0)) + return 0; + ctx = (BIO_LINEBUFFER_CTX *)b->ptr; + if ((ctx == NULL) || (b->next_bio == NULL)) + return 0; + + BIO_clear_retry_flags(b); + + do { + const char *p; + char c; + + for (p = in, c = '\0'; p < in + inl && (c = *p) != '\n'; p++) ; + if (c == '\n') { + p++; + foundnl = 1; + } else + foundnl = 0; + + /* + * If a NL was found and we already have text in the save buffer, + * concatenate them and write + */ + while ((foundnl || p - in > ctx->obuf_size - ctx->obuf_len) + && ctx->obuf_len > 0) { + int orig_olen = ctx->obuf_len; + + i = ctx->obuf_size - ctx->obuf_len; + if (p - in > 0) { + if (i >= p - in) { + memcpy(&(ctx->obuf[ctx->obuf_len]), in, p - in); + ctx->obuf_len += p - in; + inl -= p - in; + num += p - in; + in = p; + } else { + memcpy(&(ctx->obuf[ctx->obuf_len]), in, i); + ctx->obuf_len += i; + inl -= i; + in += i; + num += i; + } + } + i = BIO_write(b->next_bio, ctx->obuf, ctx->obuf_len); + if (i <= 0) { + ctx->obuf_len = orig_olen; + BIO_copy_next_retry(b); + + if (i < 0) + return ((num > 0) ? num : i); + if (i == 0) + return num; + } + if (i < ctx->obuf_len) + memmove(ctx->obuf, ctx->obuf + i, ctx->obuf_len - i); + ctx->obuf_len -= i; + } + + /* + * Now that the save buffer is emptied, let's write the input buffer + * if a NL was found and there is anything to write. + */ + if ((foundnl || p - in > ctx->obuf_size) && p - in > 0) { + i = BIO_write(b->next_bio, in, p - in); + if (i <= 0) { + BIO_copy_next_retry(b); + if (i < 0) + return ((num > 0) ? num : i); + if (i == 0) + return num; + } + num += i; + in += i; + inl -= i; + } + } + while (foundnl && inl > 0); + /* + * We've written as much as we can. The rest of the input buffer, if + * any, is text that doesn't and with a NL and therefore needs to be + * saved for the next trip. + */ + if (inl > 0) { + memcpy(&(ctx->obuf[ctx->obuf_len]), in, inl); + ctx->obuf_len += inl; + num += inl; + } + return num; +} + +static long linebuffer_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + BIO *dbio; + BIO_LINEBUFFER_CTX *ctx; + long ret = 1; + char *p; + int r; + int obs; + + ctx = (BIO_LINEBUFFER_CTX *)b->ptr; + + switch (cmd) { + case BIO_CTRL_RESET: + ctx->obuf_len = 0; + if (b->next_bio == NULL) + return 0; + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + break; + case BIO_CTRL_INFO: + ret = (long)ctx->obuf_len; + break; + case BIO_CTRL_WPENDING: + ret = (long)ctx->obuf_len; + if (ret == 0) { + if (b->next_bio == NULL) + return 0; + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + } + break; + case BIO_C_SET_BUFF_SIZE: + obs = (int)num; + p = ctx->obuf; + if ((obs > DEFAULT_LINEBUFFER_SIZE) && (obs != ctx->obuf_size)) { + p = OPENSSL_malloc((int)num); + if (p == NULL) + goto malloc_error; + } + if (ctx->obuf != p) { + if (ctx->obuf_len > obs) { + ctx->obuf_len = obs; + } + memcpy(p, ctx->obuf, ctx->obuf_len); + OPENSSL_free(ctx->obuf); + ctx->obuf = p; + ctx->obuf_size = obs; + } + break; + case BIO_C_DO_STATE_MACHINE: + if (b->next_bio == NULL) + return 0; + BIO_clear_retry_flags(b); + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + BIO_copy_next_retry(b); + break; + + case BIO_CTRL_FLUSH: + if (b->next_bio == NULL) + return 0; + if (ctx->obuf_len <= 0) { + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + break; + } + + for (;;) { + BIO_clear_retry_flags(b); + if (ctx->obuf_len > 0) { + r = BIO_write(b->next_bio, ctx->obuf, ctx->obuf_len); + BIO_copy_next_retry(b); + if (r <= 0) + return (long)r; + if (r < ctx->obuf_len) + memmove(ctx->obuf, ctx->obuf + r, ctx->obuf_len - r); + ctx->obuf_len -= r; + } else { + ctx->obuf_len = 0; + break; + } + } + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + break; + case BIO_CTRL_DUP: + dbio = (BIO *)ptr; + if (!BIO_set_write_buffer_size(dbio, ctx->obuf_size)) + ret = 0; + break; + default: + if (b->next_bio == NULL) + return 0; + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + break; + } + return ret; + malloc_error: + BIOerr(BIO_F_LINEBUFFER_CTRL, ERR_R_MALLOC_FAILURE); + return 0; +} + +static long linebuffer_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) +{ + long ret = 1; + + if (b->next_bio == NULL) + return 0; + switch (cmd) { + default: + ret = BIO_callback_ctrl(b->next_bio, cmd, fp); + break; + } + return ret; +} + +static int linebuffer_gets(BIO *b, char *buf, int size) +{ + if (b->next_bio == NULL) + return 0; + return BIO_gets(b->next_bio, buf, size); +} + +static int linebuffer_puts(BIO *b, const char *str) +{ + return linebuffer_write(b, str, strlen(str)); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bf_nbio.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bf_nbio.c new file mode 100644 index 000000000..4bc84eeba --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bf_nbio.c @@ -0,0 +1,200 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "bio_lcl.h" +#include "internal/cryptlib.h" +#include + +/* + * BIO_put and BIO_get both add to the digest, BIO_gets returns the digest + */ + +static int nbiof_write(BIO *h, const char *buf, int num); +static int nbiof_read(BIO *h, char *buf, int size); +static int nbiof_puts(BIO *h, const char *str); +static int nbiof_gets(BIO *h, char *str, int size); +static long nbiof_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int nbiof_new(BIO *h); +static int nbiof_free(BIO *data); +static long nbiof_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); +typedef struct nbio_test_st { + /* only set if we sent a 'should retry' error */ + int lrn; + int lwn; +} NBIO_TEST; + +static const BIO_METHOD methods_nbiof = { + BIO_TYPE_NBIO_TEST, + "non-blocking IO test filter", + /* TODO: Convert to new style write function */ + bwrite_conv, + nbiof_write, + /* TODO: Convert to new style read function */ + bread_conv, + nbiof_read, + nbiof_puts, + nbiof_gets, + nbiof_ctrl, + nbiof_new, + nbiof_free, + nbiof_callback_ctrl, +}; + +const BIO_METHOD *BIO_f_nbio_test(void) +{ + return &methods_nbiof; +} + +static int nbiof_new(BIO *bi) +{ + NBIO_TEST *nt; + + if ((nt = OPENSSL_zalloc(sizeof(*nt))) == NULL) { + BIOerr(BIO_F_NBIOF_NEW, ERR_R_MALLOC_FAILURE); + return 0; + } + nt->lrn = -1; + nt->lwn = -1; + bi->ptr = (char *)nt; + bi->init = 1; + return 1; +} + +static int nbiof_free(BIO *a) +{ + if (a == NULL) + return 0; + OPENSSL_free(a->ptr); + a->ptr = NULL; + a->init = 0; + a->flags = 0; + return 1; +} + +static int nbiof_read(BIO *b, char *out, int outl) +{ + int ret = 0; + int num; + unsigned char n; + + if (out == NULL) + return 0; + if (b->next_bio == NULL) + return 0; + + BIO_clear_retry_flags(b); + if (RAND_priv_bytes(&n, 1) <= 0) + return -1; + num = (n & 0x07); + + if (outl > num) + outl = num; + + if (num == 0) { + ret = -1; + BIO_set_retry_read(b); + } else { + ret = BIO_read(b->next_bio, out, outl); + if (ret < 0) + BIO_copy_next_retry(b); + } + return ret; +} + +static int nbiof_write(BIO *b, const char *in, int inl) +{ + NBIO_TEST *nt; + int ret = 0; + int num; + unsigned char n; + + if ((in == NULL) || (inl <= 0)) + return 0; + if (b->next_bio == NULL) + return 0; + nt = (NBIO_TEST *)b->ptr; + + BIO_clear_retry_flags(b); + + if (nt->lwn > 0) { + num = nt->lwn; + nt->lwn = 0; + } else { + if (RAND_priv_bytes(&n, 1) <= 0) + return -1; + num = (n & 7); + } + + if (inl > num) + inl = num; + + if (num == 0) { + ret = -1; + BIO_set_retry_write(b); + } else { + ret = BIO_write(b->next_bio, in, inl); + if (ret < 0) { + BIO_copy_next_retry(b); + nt->lwn = inl; + } + } + return ret; +} + +static long nbiof_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + long ret; + + if (b->next_bio == NULL) + return 0; + switch (cmd) { + case BIO_C_DO_STATE_MACHINE: + BIO_clear_retry_flags(b); + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + BIO_copy_next_retry(b); + break; + case BIO_CTRL_DUP: + ret = 0L; + break; + default: + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + break; + } + return ret; +} + +static long nbiof_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) +{ + long ret = 1; + + if (b->next_bio == NULL) + return 0; + switch (cmd) { + default: + ret = BIO_callback_ctrl(b->next_bio, cmd, fp); + break; + } + return ret; +} + +static int nbiof_gets(BIO *bp, char *buf, int size) +{ + if (bp->next_bio == NULL) + return 0; + return BIO_gets(bp->next_bio, buf, size); +} + +static int nbiof_puts(BIO *bp, const char *str) +{ + if (bp->next_bio == NULL) + return 0; + return BIO_puts(bp->next_bio, str); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bf_null.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bf_null.c new file mode 100644 index 000000000..613fb2e05 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bf_null.c @@ -0,0 +1,122 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "bio_lcl.h" +#include "internal/cryptlib.h" + +/* + * BIO_put and BIO_get both add to the digest, BIO_gets returns the digest + */ + +static int nullf_write(BIO *h, const char *buf, int num); +static int nullf_read(BIO *h, char *buf, int size); +static int nullf_puts(BIO *h, const char *str); +static int nullf_gets(BIO *h, char *str, int size); +static long nullf_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static long nullf_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); +static const BIO_METHOD methods_nullf = { + BIO_TYPE_NULL_FILTER, + "NULL filter", + /* TODO: Convert to new style write function */ + bwrite_conv, + nullf_write, + /* TODO: Convert to new style read function */ + bread_conv, + nullf_read, + nullf_puts, + nullf_gets, + nullf_ctrl, + NULL, + NULL, + nullf_callback_ctrl, +}; + +const BIO_METHOD *BIO_f_null(void) +{ + return &methods_nullf; +} + +static int nullf_read(BIO *b, char *out, int outl) +{ + int ret = 0; + + if (out == NULL) + return 0; + if (b->next_bio == NULL) + return 0; + ret = BIO_read(b->next_bio, out, outl); + BIO_clear_retry_flags(b); + BIO_copy_next_retry(b); + return ret; +} + +static int nullf_write(BIO *b, const char *in, int inl) +{ + int ret = 0; + + if ((in == NULL) || (inl <= 0)) + return 0; + if (b->next_bio == NULL) + return 0; + ret = BIO_write(b->next_bio, in, inl); + BIO_clear_retry_flags(b); + BIO_copy_next_retry(b); + return ret; +} + +static long nullf_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + long ret; + + if (b->next_bio == NULL) + return 0; + switch (cmd) { + case BIO_C_DO_STATE_MACHINE: + BIO_clear_retry_flags(b); + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + BIO_copy_next_retry(b); + break; + case BIO_CTRL_DUP: + ret = 0L; + break; + default: + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + } + return ret; +} + +static long nullf_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) +{ + long ret = 1; + + if (b->next_bio == NULL) + return 0; + switch (cmd) { + default: + ret = BIO_callback_ctrl(b->next_bio, cmd, fp); + break; + } + return ret; +} + +static int nullf_gets(BIO *bp, char *buf, int size) +{ + if (bp->next_bio == NULL) + return 0; + return BIO_gets(bp->next_bio, buf, size); +} + +static int nullf_puts(BIO *bp, const char *str) +{ + if (bp->next_bio == NULL) + return 0; + return BIO_puts(bp->next_bio, str); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_cb.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_cb.c new file mode 100644 index 000000000..1154c233a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_cb.c @@ -0,0 +1,98 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "bio_lcl.h" +#include "internal/cryptlib.h" +#include + +long BIO_debug_callback(BIO *bio, int cmd, const char *argp, + int argi, long argl, long ret) +{ + BIO *b; + char buf[256]; + char *p; + long r = 1; + int len, left; + + if (BIO_CB_RETURN & cmd) + r = ret; + + len = BIO_snprintf(buf, sizeof(buf), "BIO[%p]: ", (void *)bio); + + /* Ignore errors and continue printing the other information. */ + if (len < 0) + len = 0; + p = buf + len; + left = sizeof(buf) - len; + + switch (cmd) { + case BIO_CB_FREE: + BIO_snprintf(p, left, "Free - %s\n", bio->method->name); + break; + case BIO_CB_READ: + if (bio->method->type & BIO_TYPE_DESCRIPTOR) + BIO_snprintf(p, left, "read(%d,%lu) - %s fd=%d\n", + bio->num, (unsigned long)argi, + bio->method->name, bio->num); + else + BIO_snprintf(p, left, "read(%d,%lu) - %s\n", + bio->num, (unsigned long)argi, bio->method->name); + break; + case BIO_CB_WRITE: + if (bio->method->type & BIO_TYPE_DESCRIPTOR) + BIO_snprintf(p, left, "write(%d,%lu) - %s fd=%d\n", + bio->num, (unsigned long)argi, + bio->method->name, bio->num); + else + BIO_snprintf(p, left, "write(%d,%lu) - %s\n", + bio->num, (unsigned long)argi, bio->method->name); + break; + case BIO_CB_PUTS: + BIO_snprintf(p, left, "puts() - %s\n", bio->method->name); + break; + case BIO_CB_GETS: + BIO_snprintf(p, left, "gets(%lu) - %s\n", (unsigned long)argi, + bio->method->name); + break; + case BIO_CB_CTRL: + BIO_snprintf(p, left, "ctrl(%lu) - %s\n", (unsigned long)argi, + bio->method->name); + break; + case BIO_CB_RETURN | BIO_CB_READ: + BIO_snprintf(p, left, "read return %ld\n", ret); + break; + case BIO_CB_RETURN | BIO_CB_WRITE: + BIO_snprintf(p, left, "write return %ld\n", ret); + break; + case BIO_CB_RETURN | BIO_CB_GETS: + BIO_snprintf(p, left, "gets return %ld\n", ret); + break; + case BIO_CB_RETURN | BIO_CB_PUTS: + BIO_snprintf(p, left, "puts return %ld\n", ret); + break; + case BIO_CB_RETURN | BIO_CB_CTRL: + BIO_snprintf(p, left, "ctrl return %ld\n", ret); + break; + default: + BIO_snprintf(p, left, "bio callback - unknown type (%d)\n", cmd); + break; + } + + b = (BIO *)bio->cb_arg; + if (b != NULL) + BIO_write(b, buf, strlen(buf)); +#if !defined(OPENSSL_NO_STDIO) + else + fputs(buf, stderr); +#endif + return r; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_err.c new file mode 100644 index 000000000..7aa9dabb2 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_err.c @@ -0,0 +1,145 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA BIO_str_functs[] = { + {ERR_PACK(ERR_LIB_BIO, BIO_F_ACPT_STATE, 0), "acpt_state"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_ADDRINFO_WRAP, 0), "addrinfo_wrap"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_ADDR_STRINGS, 0), "addr_strings"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_ACCEPT, 0), "BIO_accept"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_ACCEPT_EX, 0), "BIO_accept_ex"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_ACCEPT_NEW, 0), "BIO_ACCEPT_new"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_ADDR_NEW, 0), "BIO_ADDR_new"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_BIND, 0), "BIO_bind"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_CALLBACK_CTRL, 0), "BIO_callback_ctrl"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_CONNECT, 0), "BIO_connect"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_CONNECT_NEW, 0), "BIO_CONNECT_new"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_CTRL, 0), "BIO_ctrl"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_GETS, 0), "BIO_gets"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_GET_HOST_IP, 0), "BIO_get_host_ip"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_GET_NEW_INDEX, 0), "BIO_get_new_index"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_GET_PORT, 0), "BIO_get_port"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_LISTEN, 0), "BIO_listen"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_LOOKUP, 0), "BIO_lookup"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_LOOKUP_EX, 0), "BIO_lookup_ex"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_MAKE_PAIR, 0), "bio_make_pair"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_METH_NEW, 0), "BIO_meth_new"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NEW, 0), "BIO_new"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NEW_DGRAM_SCTP, 0), "BIO_new_dgram_sctp"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NEW_FILE, 0), "BIO_new_file"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NEW_MEM_BUF, 0), "BIO_new_mem_buf"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NREAD, 0), "BIO_nread"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NREAD0, 0), "BIO_nread0"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NWRITE, 0), "BIO_nwrite"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NWRITE0, 0), "BIO_nwrite0"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_PARSE_HOSTSERV, 0), "BIO_parse_hostserv"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_PUTS, 0), "BIO_puts"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_READ, 0), "BIO_read"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_READ_EX, 0), "BIO_read_ex"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_READ_INTERN, 0), "bio_read_intern"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_SOCKET, 0), "BIO_socket"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_SOCKET_NBIO, 0), "BIO_socket_nbio"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_SOCK_INFO, 0), "BIO_sock_info"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_SOCK_INIT, 0), "BIO_sock_init"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_WRITE, 0), "BIO_write"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_WRITE_EX, 0), "BIO_write_ex"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_WRITE_INTERN, 0), "bio_write_intern"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_BUFFER_CTRL, 0), "buffer_ctrl"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_CONN_CTRL, 0), "conn_ctrl"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_CONN_STATE, 0), "conn_state"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_DGRAM_SCTP_NEW, 0), "dgram_sctp_new"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_DGRAM_SCTP_READ, 0), "dgram_sctp_read"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_DGRAM_SCTP_WRITE, 0), "dgram_sctp_write"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_DOAPR_OUTCH, 0), "doapr_outch"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_FILE_CTRL, 0), "file_ctrl"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_FILE_READ, 0), "file_read"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_LINEBUFFER_CTRL, 0), "linebuffer_ctrl"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_LINEBUFFER_NEW, 0), "linebuffer_new"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_MEM_WRITE, 0), "mem_write"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_NBIOF_NEW, 0), "nbiof_new"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_SLG_WRITE, 0), "slg_write"}, + {ERR_PACK(ERR_LIB_BIO, BIO_F_SSL_NEW, 0), "SSL_new"}, + {0, NULL} +}; + +static const ERR_STRING_DATA BIO_str_reasons[] = { + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_ACCEPT_ERROR), "accept error"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET), + "addrinfo addr is not af inet"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_AMBIGUOUS_HOST_OR_SERVICE), + "ambiguous host or service"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_BAD_FOPEN_MODE), "bad fopen mode"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_BROKEN_PIPE), "broken pipe"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_CONNECT_ERROR), "connect error"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET), + "gethostbyname addr is not af inet"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_GETSOCKNAME_ERROR), "getsockname error"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS), + "getsockname truncated address"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_GETTING_SOCKTYPE), "getting socktype"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_INVALID_ARGUMENT), "invalid argument"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_INVALID_SOCKET), "invalid socket"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_IN_USE), "in use"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_LENGTH_TOO_LONG), "length too long"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_LISTEN_V6_ONLY), "listen v6 only"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_LOOKUP_RETURNED_NOTHING), + "lookup returned nothing"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_MALFORMED_HOST_OR_SERVICE), + "malformed host or service"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NBIO_CONNECT_ERROR), "nbio connect error"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED), + "no accept addr or service specified"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED), + "no hostname or service specified"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NO_PORT_DEFINED), "no port defined"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NO_SUCH_FILE), "no such file"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NULL_PARAMETER), "null parameter"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNABLE_TO_BIND_SOCKET), + "unable to bind socket"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNABLE_TO_CREATE_SOCKET), + "unable to create socket"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNABLE_TO_KEEPALIVE), + "unable to keepalive"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNABLE_TO_LISTEN_SOCKET), + "unable to listen socket"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNABLE_TO_NODELAY), "unable to nodelay"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNABLE_TO_REUSEADDR), + "unable to reuseaddr"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNAVAILABLE_IP_FAMILY), + "unavailable ip family"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNINITIALIZED), "uninitialized"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNKNOWN_INFO_TYPE), "unknown info type"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNSUPPORTED_IP_FAMILY), + "unsupported ip family"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNSUPPORTED_METHOD), "unsupported method"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNSUPPORTED_PROTOCOL_FAMILY), + "unsupported protocol family"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_WRITE_TO_READ_ONLY_BIO), + "write to read only BIO"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_WSASTARTUP), "WSAStartup"}, + {0, NULL} +}; + +#endif + +int ERR_load_BIO_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(BIO_str_functs[0].error) == NULL) { + ERR_load_strings_const(BIO_str_functs); + ERR_load_strings_const(BIO_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_lcl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_lcl.h new file mode 100644 index 000000000..e2c05a20d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_lcl.h @@ -0,0 +1,190 @@ +/* + * Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "e_os.h" +#include "internal/sockets.h" +#include "internal/refcount.h" + +/* BEGIN BIO_ADDRINFO/BIO_ADDR stuff. */ + +#ifndef OPENSSL_NO_SOCK +/* + * Throughout this file and b_addr.c, the existence of the macro + * AI_PASSIVE is used to detect the availability of struct addrinfo, + * getnameinfo() and getaddrinfo(). If that macro doesn't exist, + * we use our own implementation instead. + */ + +/* + * It's imperative that these macros get defined before openssl/bio.h gets + * included. Otherwise, the AI_PASSIVE hack will not work properly. + * For clarity, we check for internal/cryptlib.h since it's a common header + * that also includes bio.h. + */ +# ifdef HEADER_CRYPTLIB_H +# error internal/cryptlib.h included before bio_lcl.h +# endif +# ifdef HEADER_BIO_H +# error openssl/bio.h included before bio_lcl.h +# endif + +/* + * Undefine AF_UNIX on systems that define it but don't support it. + */ +# if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_VMS) +# undef AF_UNIX +# endif + +# ifdef AI_PASSIVE + +/* + * There's a bug in VMS C header file netdb.h, where struct addrinfo + * always is the P32 variant, but the functions that handle that structure, + * such as getaddrinfo() and freeaddrinfo() adapt to the initial pointer + * size. The easiest workaround is to force struct addrinfo to be the + * 64-bit variant when compiling in P64 mode. + */ +# if defined(OPENSSL_SYS_VMS) && __INITIAL_POINTER_SIZE == 64 +# define addrinfo __addrinfo64 +# endif + +# define bio_addrinfo_st addrinfo +# define bai_family ai_family +# define bai_socktype ai_socktype +# define bai_protocol ai_protocol +# define bai_addrlen ai_addrlen +# define bai_addr ai_addr +# define bai_next ai_next +# else +struct bio_addrinfo_st { + int bai_family; + int bai_socktype; + int bai_protocol; + size_t bai_addrlen; + struct sockaddr *bai_addr; + struct bio_addrinfo_st *bai_next; +}; +# endif + +union bio_addr_st { + struct sockaddr sa; +# ifdef AF_INET6 + struct sockaddr_in6 s_in6; +# endif + struct sockaddr_in s_in; +# ifdef AF_UNIX + struct sockaddr_un s_un; +# endif +}; +#endif + +/* END BIO_ADDRINFO/BIO_ADDR stuff. */ + +#include "internal/cryptlib.h" +#include "internal/bio.h" + +typedef struct bio_f_buffer_ctx_struct { + /*- + * Buffers are setup like this: + * + * <---------------------- size -----------------------> + * +---------------------------------------------------+ + * | consumed | remaining | free space | + * +---------------------------------------------------+ + * <-- off --><------- len -------> + */ + /*- BIO *bio; *//* + * this is now in the BIO struct + */ + int ibuf_size; /* how big is the input buffer */ + int obuf_size; /* how big is the output buffer */ + char *ibuf; /* the char array */ + int ibuf_len; /* how many bytes are in it */ + int ibuf_off; /* write/read offset */ + char *obuf; /* the char array */ + int obuf_len; /* how many bytes are in it */ + int obuf_off; /* write/read offset */ +} BIO_F_BUFFER_CTX; + +struct bio_st { + const BIO_METHOD *method; + /* bio, mode, argp, argi, argl, ret */ + BIO_callback_fn callback; + BIO_callback_fn_ex callback_ex; + char *cb_arg; /* first argument for the callback */ + int init; + int shutdown; + int flags; /* extra storage */ + int retry_reason; + int num; + void *ptr; + struct bio_st *next_bio; /* used by filter BIOs */ + struct bio_st *prev_bio; /* used by filter BIOs */ + CRYPTO_REF_COUNT references; + uint64_t num_read; + uint64_t num_write; + CRYPTO_EX_DATA ex_data; + CRYPTO_RWLOCK *lock; +}; + +#ifndef OPENSSL_NO_SOCK +# ifdef OPENSSL_SYS_VMS +typedef unsigned int socklen_t; +# endif + +extern CRYPTO_RWLOCK *bio_lookup_lock; + +int BIO_ADDR_make(BIO_ADDR *ap, const struct sockaddr *sa); +const struct sockaddr *BIO_ADDR_sockaddr(const BIO_ADDR *ap); +struct sockaddr *BIO_ADDR_sockaddr_noconst(BIO_ADDR *ap); +socklen_t BIO_ADDR_sockaddr_size(const BIO_ADDR *ap); +socklen_t BIO_ADDRINFO_sockaddr_size(const BIO_ADDRINFO *bai); +const struct sockaddr *BIO_ADDRINFO_sockaddr(const BIO_ADDRINFO *bai); +#endif + +extern CRYPTO_RWLOCK *bio_type_lock; + +void bio_sock_cleanup_int(void); + +#if BIO_FLAGS_UPLINK==0 +/* Shortcut UPLINK calls on most platforms... */ +# define UP_stdin stdin +# define UP_stdout stdout +# define UP_stderr stderr +# define UP_fprintf fprintf +# define UP_fgets fgets +# define UP_fread fread +# define UP_fwrite fwrite +# undef UP_fsetmod +# define UP_feof feof +# define UP_fclose fclose + +# define UP_fopen fopen +# define UP_fseek fseek +# define UP_ftell ftell +# define UP_fflush fflush +# define UP_ferror ferror +# ifdef _WIN32 +# define UP_fileno _fileno +# define UP_open _open +# define UP_read _read +# define UP_write _write +# define UP_lseek _lseek +# define UP_close _close +# else +# define UP_fileno fileno +# define UP_open open +# define UP_read read +# define UP_write write +# define UP_lseek lseek +# define UP_close close +# endif + +#endif + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_lib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_lib.c new file mode 100644 index 000000000..ca375b911 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_lib.c @@ -0,0 +1,786 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "bio_lcl.h" +#include "internal/cryptlib.h" + + +/* + * Helper macro for the callback to determine whether an operator expects a + * len parameter or not + */ +#define HAS_LEN_OPER(o) ((o) == BIO_CB_READ || (o) == BIO_CB_WRITE || \ + (o) == BIO_CB_GETS) + +/* + * Helper function to work out whether to call the new style callback or the old + * one, and translate between the two. + * + * This has a long return type for consistency with the old callback. Similarly + * for the "long" used for "inret" + */ +static long bio_call_callback(BIO *b, int oper, const char *argp, size_t len, + int argi, long argl, long inret, size_t *processed) +{ + long ret; + int bareoper; + + if (b->callback_ex != NULL) + return b->callback_ex(b, oper, argp, len, argi, argl, inret, processed); + + /* Strip off any BIO_CB_RETURN flag */ + bareoper = oper & ~BIO_CB_RETURN; + + /* + * We have an old style callback, so we will have to do nasty casts and + * check for overflows. + */ + if (HAS_LEN_OPER(bareoper)) { + /* In this case |len| is set, and should be used instead of |argi| */ + if (len > INT_MAX) + return -1; + + argi = (int)len; + } + + if (inret > 0 && (oper & BIO_CB_RETURN) && bareoper != BIO_CB_CTRL) { + if (*processed > INT_MAX) + return -1; + inret = *processed; + } + + ret = b->callback(b, oper, argp, argi, argl, inret); + + if (ret > 0 && (oper & BIO_CB_RETURN) && bareoper != BIO_CB_CTRL) { + *processed = (size_t)ret; + ret = 1; + } + + return ret; +} + +BIO *BIO_new(const BIO_METHOD *method) +{ + BIO *bio = OPENSSL_zalloc(sizeof(*bio)); + + if (bio == NULL) { + BIOerr(BIO_F_BIO_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + bio->method = method; + bio->shutdown = 1; + bio->references = 1; + + if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data)) + goto err; + + bio->lock = CRYPTO_THREAD_lock_new(); + if (bio->lock == NULL) { + BIOerr(BIO_F_BIO_NEW, ERR_R_MALLOC_FAILURE); + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); + goto err; + } + + if (method->create != NULL && !method->create(bio)) { + BIOerr(BIO_F_BIO_NEW, ERR_R_INIT_FAIL); + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); + CRYPTO_THREAD_lock_free(bio->lock); + goto err; + } + if (method->create == NULL) + bio->init = 1; + + return bio; + +err: + OPENSSL_free(bio); + return NULL; +} + +int BIO_free(BIO *a) +{ + int ret; + + if (a == NULL) + return 0; + + if (CRYPTO_DOWN_REF(&a->references, &ret, a->lock) <= 0) + return 0; + + REF_PRINT_COUNT("BIO", a); + if (ret > 0) + return 1; + REF_ASSERT_ISNT(ret < 0); + + if (a->callback != NULL || a->callback_ex != NULL) { + ret = (int)bio_call_callback(a, BIO_CB_FREE, NULL, 0, 0, 0L, 1L, NULL); + if (ret <= 0) + return ret; + } + + if ((a->method != NULL) && (a->method->destroy != NULL)) + a->method->destroy(a); + + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data); + + CRYPTO_THREAD_lock_free(a->lock); + + OPENSSL_free(a); + + return 1; +} + +void BIO_set_data(BIO *a, void *ptr) +{ + a->ptr = ptr; +} + +void *BIO_get_data(BIO *a) +{ + return a->ptr; +} + +void BIO_set_init(BIO *a, int init) +{ + a->init = init; +} + +int BIO_get_init(BIO *a) +{ + return a->init; +} + +void BIO_set_shutdown(BIO *a, int shut) +{ + a->shutdown = shut; +} + +int BIO_get_shutdown(BIO *a) +{ + return a->shutdown; +} + +void BIO_vfree(BIO *a) +{ + BIO_free(a); +} + +int BIO_up_ref(BIO *a) +{ + int i; + + if (CRYPTO_UP_REF(&a->references, &i, a->lock) <= 0) + return 0; + + REF_PRINT_COUNT("BIO", a); + REF_ASSERT_ISNT(i < 2); + return ((i > 1) ? 1 : 0); +} + +void BIO_clear_flags(BIO *b, int flags) +{ + b->flags &= ~flags; +} + +int BIO_test_flags(const BIO *b, int flags) +{ + return (b->flags & flags); +} + +void BIO_set_flags(BIO *b, int flags) +{ + b->flags |= flags; +} + +BIO_callback_fn BIO_get_callback(const BIO *b) +{ + return b->callback; +} + +void BIO_set_callback(BIO *b, BIO_callback_fn cb) +{ + b->callback = cb; +} + +BIO_callback_fn_ex BIO_get_callback_ex(const BIO *b) +{ + return b->callback_ex; +} + +void BIO_set_callback_ex(BIO *b, BIO_callback_fn_ex cb) +{ + b->callback_ex = cb; +} + +void BIO_set_callback_arg(BIO *b, char *arg) +{ + b->cb_arg = arg; +} + +char *BIO_get_callback_arg(const BIO *b) +{ + return b->cb_arg; +} + +const char *BIO_method_name(const BIO *b) +{ + return b->method->name; +} + +int BIO_method_type(const BIO *b) +{ + return b->method->type; +} + +/* + * This is essentially the same as BIO_read_ex() except that it allows + * 0 or a negative value to indicate failure (retryable or not) in the return. + * This is for compatibility with the old style BIO_read(), where existing code + * may make assumptions about the return value that it might get. + */ +static int bio_read_intern(BIO *b, void *data, size_t dlen, size_t *readbytes) +{ + int ret; + + if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL)) { + BIOerr(BIO_F_BIO_READ_INTERN, BIO_R_UNSUPPORTED_METHOD); + return -2; + } + + if ((b->callback != NULL || b->callback_ex != NULL) && + ((ret = (int)bio_call_callback(b, BIO_CB_READ, data, dlen, 0, 0L, 1L, + NULL)) <= 0)) + return ret; + + if (!b->init) { + BIOerr(BIO_F_BIO_READ_INTERN, BIO_R_UNINITIALIZED); + return -2; + } + + ret = b->method->bread(b, data, dlen, readbytes); + + if (ret > 0) + b->num_read += (uint64_t)*readbytes; + + if (b->callback != NULL || b->callback_ex != NULL) + ret = (int)bio_call_callback(b, BIO_CB_READ | BIO_CB_RETURN, data, + dlen, 0, 0L, ret, readbytes); + + /* Shouldn't happen */ + if (ret > 0 && *readbytes > dlen) { + BIOerr(BIO_F_BIO_READ_INTERN, ERR_R_INTERNAL_ERROR); + return -1; + } + + return ret; +} + +int BIO_read(BIO *b, void *data, int dlen) +{ + size_t readbytes; + int ret; + + if (dlen < 0) + return 0; + + ret = bio_read_intern(b, data, (size_t)dlen, &readbytes); + + if (ret > 0) { + /* *readbytes should always be <= dlen */ + ret = (int)readbytes; + } + + return ret; +} + +int BIO_read_ex(BIO *b, void *data, size_t dlen, size_t *readbytes) +{ + int ret; + + ret = bio_read_intern(b, data, dlen, readbytes); + + if (ret > 0) + ret = 1; + else + ret = 0; + + return ret; +} + +static int bio_write_intern(BIO *b, const void *data, size_t dlen, + size_t *written) +{ + int ret; + + if (b == NULL) + return 0; + + if ((b->method == NULL) || (b->method->bwrite == NULL)) { + BIOerr(BIO_F_BIO_WRITE_INTERN, BIO_R_UNSUPPORTED_METHOD); + return -2; + } + + if ((b->callback != NULL || b->callback_ex != NULL) && + ((ret = (int)bio_call_callback(b, BIO_CB_WRITE, data, dlen, 0, 0L, 1L, + NULL)) <= 0)) + return ret; + + if (!b->init) { + BIOerr(BIO_F_BIO_WRITE_INTERN, BIO_R_UNINITIALIZED); + return -2; + } + + ret = b->method->bwrite(b, data, dlen, written); + + if (ret > 0) + b->num_write += (uint64_t)*written; + + if (b->callback != NULL || b->callback_ex != NULL) + ret = (int)bio_call_callback(b, BIO_CB_WRITE | BIO_CB_RETURN, data, + dlen, 0, 0L, ret, written); + + return ret; +} + +int BIO_write(BIO *b, const void *data, int dlen) +{ + size_t written; + int ret; + + if (dlen < 0) + return 0; + + ret = bio_write_intern(b, data, (size_t)dlen, &written); + + if (ret > 0) { + /* *written should always be <= dlen */ + ret = (int)written; + } + + return ret; +} + +int BIO_write_ex(BIO *b, const void *data, size_t dlen, size_t *written) +{ + int ret; + + ret = bio_write_intern(b, data, dlen, written); + + if (ret > 0) + ret = 1; + else + ret = 0; + + return ret; +} + +int BIO_puts(BIO *b, const char *buf) +{ + int ret; + size_t written = 0; + + if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL)) { + BIOerr(BIO_F_BIO_PUTS, BIO_R_UNSUPPORTED_METHOD); + return -2; + } + + if (b->callback != NULL || b->callback_ex != NULL) { + ret = (int)bio_call_callback(b, BIO_CB_PUTS, buf, 0, 0, 0L, 1L, NULL); + if (ret <= 0) + return ret; + } + + if (!b->init) { + BIOerr(BIO_F_BIO_PUTS, BIO_R_UNINITIALIZED); + return -2; + } + + ret = b->method->bputs(b, buf); + + if (ret > 0) { + b->num_write += (uint64_t)ret; + written = ret; + ret = 1; + } + + if (b->callback != NULL || b->callback_ex != NULL) + ret = (int)bio_call_callback(b, BIO_CB_PUTS | BIO_CB_RETURN, buf, 0, 0, + 0L, ret, &written); + + if (ret > 0) { + if (written > INT_MAX) { + BIOerr(BIO_F_BIO_PUTS, BIO_R_LENGTH_TOO_LONG); + ret = -1; + } else { + ret = (int)written; + } + } + + return ret; +} + +int BIO_gets(BIO *b, char *buf, int size) +{ + int ret; + size_t readbytes = 0; + + if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL)) { + BIOerr(BIO_F_BIO_GETS, BIO_R_UNSUPPORTED_METHOD); + return -2; + } + + if (size < 0) { + BIOerr(BIO_F_BIO_GETS, BIO_R_INVALID_ARGUMENT); + return 0; + } + + if (b->callback != NULL || b->callback_ex != NULL) { + ret = (int)bio_call_callback(b, BIO_CB_GETS, buf, size, 0, 0L, 1, NULL); + if (ret <= 0) + return ret; + } + + if (!b->init) { + BIOerr(BIO_F_BIO_GETS, BIO_R_UNINITIALIZED); + return -2; + } + + ret = b->method->bgets(b, buf, size); + + if (ret > 0) { + readbytes = ret; + ret = 1; + } + + if (b->callback != NULL || b->callback_ex != NULL) + ret = (int)bio_call_callback(b, BIO_CB_GETS | BIO_CB_RETURN, buf, size, + 0, 0L, ret, &readbytes); + + if (ret > 0) { + /* Shouldn't happen */ + if (readbytes > (size_t)size) + ret = -1; + else + ret = (int)readbytes; + } + + return ret; +} + +int BIO_indent(BIO *b, int indent, int max) +{ + if (indent < 0) + indent = 0; + if (indent > max) + indent = max; + while (indent--) + if (BIO_puts(b, " ") != 1) + return 0; + return 1; +} + +long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg) +{ + int i; + + i = iarg; + return BIO_ctrl(b, cmd, larg, (char *)&i); +} + +void *BIO_ptr_ctrl(BIO *b, int cmd, long larg) +{ + void *p = NULL; + + if (BIO_ctrl(b, cmd, larg, (char *)&p) <= 0) + return NULL; + else + return p; +} + +long BIO_ctrl(BIO *b, int cmd, long larg, void *parg) +{ + long ret; + + if (b == NULL) + return 0; + + if ((b->method == NULL) || (b->method->ctrl == NULL)) { + BIOerr(BIO_F_BIO_CTRL, BIO_R_UNSUPPORTED_METHOD); + return -2; + } + + if (b->callback != NULL || b->callback_ex != NULL) { + ret = bio_call_callback(b, BIO_CB_CTRL, parg, 0, cmd, larg, 1L, NULL); + if (ret <= 0) + return ret; + } + + ret = b->method->ctrl(b, cmd, larg, parg); + + if (b->callback != NULL || b->callback_ex != NULL) + ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, parg, 0, cmd, + larg, ret, NULL); + + return ret; +} + +long BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) +{ + long ret; + + if (b == NULL) + return 0; + + if ((b->method == NULL) || (b->method->callback_ctrl == NULL) + || (cmd != BIO_CTRL_SET_CALLBACK)) { + BIOerr(BIO_F_BIO_CALLBACK_CTRL, BIO_R_UNSUPPORTED_METHOD); + return -2; + } + + if (b->callback != NULL || b->callback_ex != NULL) { + ret = bio_call_callback(b, BIO_CB_CTRL, (void *)&fp, 0, cmd, 0, 1L, + NULL); + if (ret <= 0) + return ret; + } + + ret = b->method->callback_ctrl(b, cmd, fp); + + if (b->callback != NULL || b->callback_ex != NULL) + ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, (void *)&fp, 0, + cmd, 0, ret, NULL); + + return ret; +} + +/* + * It is unfortunate to duplicate in functions what the BIO_(w)pending macros + * do; but those macros have inappropriate return type, and for interfacing + * from other programming languages, C macros aren't much of a help anyway. + */ +size_t BIO_ctrl_pending(BIO *bio) +{ + return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL); +} + +size_t BIO_ctrl_wpending(BIO *bio) +{ + return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL); +} + +/* put the 'bio' on the end of b's list of operators */ +BIO *BIO_push(BIO *b, BIO *bio) +{ + BIO *lb; + + if (b == NULL) + return bio; + lb = b; + while (lb->next_bio != NULL) + lb = lb->next_bio; + lb->next_bio = bio; + if (bio != NULL) + bio->prev_bio = lb; + /* called to do internal processing */ + BIO_ctrl(b, BIO_CTRL_PUSH, 0, lb); + return b; +} + +/* Remove the first and return the rest */ +BIO *BIO_pop(BIO *b) +{ + BIO *ret; + + if (b == NULL) + return NULL; + ret = b->next_bio; + + BIO_ctrl(b, BIO_CTRL_POP, 0, b); + + if (b->prev_bio != NULL) + b->prev_bio->next_bio = b->next_bio; + if (b->next_bio != NULL) + b->next_bio->prev_bio = b->prev_bio; + + b->next_bio = NULL; + b->prev_bio = NULL; + return ret; +} + +BIO *BIO_get_retry_BIO(BIO *bio, int *reason) +{ + BIO *b, *last; + + b = last = bio; + for (;;) { + if (!BIO_should_retry(b)) + break; + last = b; + b = b->next_bio; + if (b == NULL) + break; + } + if (reason != NULL) + *reason = last->retry_reason; + return last; +} + +int BIO_get_retry_reason(BIO *bio) +{ + return bio->retry_reason; +} + +void BIO_set_retry_reason(BIO *bio, int reason) +{ + bio->retry_reason = reason; +} + +BIO *BIO_find_type(BIO *bio, int type) +{ + int mt, mask; + + if (bio == NULL) + return NULL; + mask = type & 0xff; + do { + if (bio->method != NULL) { + mt = bio->method->type; + + if (!mask) { + if (mt & type) + return bio; + } else if (mt == type) + return bio; + } + bio = bio->next_bio; + } while (bio != NULL); + return NULL; +} + +BIO *BIO_next(BIO *b) +{ + if (b == NULL) + return NULL; + return b->next_bio; +} + +void BIO_set_next(BIO *b, BIO *next) +{ + b->next_bio = next; +} + +void BIO_free_all(BIO *bio) +{ + BIO *b; + int ref; + + while (bio != NULL) { + b = bio; + ref = b->references; + bio = bio->next_bio; + BIO_free(b); + /* Since ref count > 1, don't free anyone else. */ + if (ref > 1) + break; + } +} + +BIO *BIO_dup_chain(BIO *in) +{ + BIO *ret = NULL, *eoc = NULL, *bio, *new_bio; + + for (bio = in; bio != NULL; bio = bio->next_bio) { + if ((new_bio = BIO_new(bio->method)) == NULL) + goto err; + new_bio->callback = bio->callback; + new_bio->callback_ex = bio->callback_ex; + new_bio->cb_arg = bio->cb_arg; + new_bio->init = bio->init; + new_bio->shutdown = bio->shutdown; + new_bio->flags = bio->flags; + + /* This will let SSL_s_sock() work with stdin/stdout */ + new_bio->num = bio->num; + + if (!BIO_dup_state(bio, (char *)new_bio)) { + BIO_free(new_bio); + goto err; + } + + /* copy app data */ + if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, &new_bio->ex_data, + &bio->ex_data)) { + BIO_free(new_bio); + goto err; + } + + if (ret == NULL) { + eoc = new_bio; + ret = eoc; + } else { + BIO_push(eoc, new_bio); + eoc = new_bio; + } + } + return ret; + err: + BIO_free_all(ret); + + return NULL; +} + +void BIO_copy_next_retry(BIO *b) +{ + BIO_set_flags(b, BIO_get_retry_flags(b->next_bio)); + b->retry_reason = b->next_bio->retry_reason; +} + +int BIO_set_ex_data(BIO *bio, int idx, void *data) +{ + return CRYPTO_set_ex_data(&(bio->ex_data), idx, data); +} + +void *BIO_get_ex_data(BIO *bio, int idx) +{ + return CRYPTO_get_ex_data(&(bio->ex_data), idx); +} + +uint64_t BIO_number_read(BIO *bio) +{ + if (bio) + return bio->num_read; + return 0; +} + +uint64_t BIO_number_written(BIO *bio) +{ + if (bio) + return bio->num_write; + return 0; +} + +void bio_free_ex_data(BIO *bio) +{ + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); +} + +void bio_cleanup(void) +{ +#ifndef OPENSSL_NO_SOCK + bio_sock_cleanup_int(); + CRYPTO_THREAD_lock_free(bio_lookup_lock); + bio_lookup_lock = NULL; +#endif + CRYPTO_THREAD_lock_free(bio_type_lock); + bio_type_lock = NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_meth.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_meth.c new file mode 100644 index 000000000..493ff63a9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_meth.c @@ -0,0 +1,220 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "bio_lcl.h" +#include "internal/thread_once.h" + +CRYPTO_RWLOCK *bio_type_lock = NULL; +static CRYPTO_ONCE bio_type_init = CRYPTO_ONCE_STATIC_INIT; + +DEFINE_RUN_ONCE_STATIC(do_bio_type_init) +{ + bio_type_lock = CRYPTO_THREAD_lock_new(); + return bio_type_lock != NULL; +} + +int BIO_get_new_index(void) +{ + static CRYPTO_REF_COUNT bio_count = BIO_TYPE_START; + int newval; + + if (!RUN_ONCE(&bio_type_init, do_bio_type_init)) { + BIOerr(BIO_F_BIO_GET_NEW_INDEX, ERR_R_MALLOC_FAILURE); + return -1; + } + if (!CRYPTO_UP_REF(&bio_count, &newval, bio_type_lock)) + return -1; + return newval; +} + +BIO_METHOD *BIO_meth_new(int type, const char *name) +{ + BIO_METHOD *biom = OPENSSL_zalloc(sizeof(BIO_METHOD)); + + if (biom == NULL + || (biom->name = OPENSSL_strdup(name)) == NULL) { + OPENSSL_free(biom); + BIOerr(BIO_F_BIO_METH_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + biom->type = type; + return biom; +} + +void BIO_meth_free(BIO_METHOD *biom) +{ + if (biom != NULL) { + OPENSSL_free(biom->name); + OPENSSL_free(biom); + } +} + +int (*BIO_meth_get_write(const BIO_METHOD *biom)) (BIO *, const char *, int) +{ + return biom->bwrite_old; +} + +int (*BIO_meth_get_write_ex(const BIO_METHOD *biom)) (BIO *, const char *, size_t, + size_t *) +{ + return biom->bwrite; +} + +/* Conversion for old style bwrite to new style */ +int bwrite_conv(BIO *bio, const char *data, size_t datal, size_t *written) +{ + int ret; + + if (datal > INT_MAX) + datal = INT_MAX; + + ret = bio->method->bwrite_old(bio, data, (int)datal); + + if (ret <= 0) { + *written = 0; + return ret; + } + + *written = (size_t)ret; + + return 1; +} + +int BIO_meth_set_write(BIO_METHOD *biom, + int (*bwrite) (BIO *, const char *, int)) +{ + biom->bwrite_old = bwrite; + biom->bwrite = bwrite_conv; + return 1; +} + +int BIO_meth_set_write_ex(BIO_METHOD *biom, + int (*bwrite) (BIO *, const char *, size_t, size_t *)) +{ + biom->bwrite_old = NULL; + biom->bwrite = bwrite; + return 1; +} + +int (*BIO_meth_get_read(const BIO_METHOD *biom)) (BIO *, char *, int) +{ + return biom->bread_old; +} + +int (*BIO_meth_get_read_ex(const BIO_METHOD *biom)) (BIO *, char *, size_t, size_t *) +{ + return biom->bread; +} + +/* Conversion for old style bread to new style */ +int bread_conv(BIO *bio, char *data, size_t datal, size_t *readbytes) +{ + int ret; + + if (datal > INT_MAX) + datal = INT_MAX; + + ret = bio->method->bread_old(bio, data, (int)datal); + + if (ret <= 0) { + *readbytes = 0; + return ret; + } + + *readbytes = (size_t)ret; + + return 1; +} + +int BIO_meth_set_read(BIO_METHOD *biom, + int (*bread) (BIO *, char *, int)) +{ + biom->bread_old = bread; + biom->bread = bread_conv; + return 1; +} + +int BIO_meth_set_read_ex(BIO_METHOD *biom, + int (*bread) (BIO *, char *, size_t, size_t *)) +{ + biom->bread_old = NULL; + biom->bread = bread; + return 1; +} + +int (*BIO_meth_get_puts(const BIO_METHOD *biom)) (BIO *, const char *) +{ + return biom->bputs; +} + +int BIO_meth_set_puts(BIO_METHOD *biom, + int (*bputs) (BIO *, const char *)) +{ + biom->bputs = bputs; + return 1; +} + +int (*BIO_meth_get_gets(const BIO_METHOD *biom)) (BIO *, char *, int) +{ + return biom->bgets; +} + +int BIO_meth_set_gets(BIO_METHOD *biom, + int (*bgets) (BIO *, char *, int)) +{ + biom->bgets = bgets; + return 1; +} + +long (*BIO_meth_get_ctrl(const BIO_METHOD *biom)) (BIO *, int, long, void *) +{ + return biom->ctrl; +} + +int BIO_meth_set_ctrl(BIO_METHOD *biom, + long (*ctrl) (BIO *, int, long, void *)) +{ + biom->ctrl = ctrl; + return 1; +} + +int (*BIO_meth_get_create(const BIO_METHOD *biom)) (BIO *) +{ + return biom->create; +} + +int BIO_meth_set_create(BIO_METHOD *biom, int (*create) (BIO *)) +{ + biom->create = create; + return 1; +} + +int (*BIO_meth_get_destroy(const BIO_METHOD *biom)) (BIO *) +{ + return biom->destroy; +} + +int BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy) (BIO *)) +{ + biom->destroy = destroy; + return 1; +} + +long (*BIO_meth_get_callback_ctrl(const BIO_METHOD *biom)) (BIO *, int, BIO_info_cb *) +{ + return biom->callback_ctrl; +} + +int BIO_meth_set_callback_ctrl(BIO_METHOD *biom, + long (*callback_ctrl) (BIO *, int, + BIO_info_cb *)) +{ + biom->callback_ctrl = callback_ctrl; + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_acpt.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_acpt.c new file mode 100644 index 000000000..993e5903a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_acpt.c @@ -0,0 +1,560 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "bio_lcl.h" + +#ifndef OPENSSL_NO_SOCK + +typedef struct bio_accept_st { + int state; + int accept_family; + int bind_mode; /* Socket mode for BIO_listen */ + int accepted_mode; /* Socket mode for BIO_accept (set on accepted sock) */ + char *param_addr; + char *param_serv; + + int accept_sock; + + BIO_ADDRINFO *addr_first; + const BIO_ADDRINFO *addr_iter; + BIO_ADDR cache_accepting_addr; /* Useful if we asked for port 0 */ + char *cache_accepting_name, *cache_accepting_serv; + BIO_ADDR cache_peer_addr; + char *cache_peer_name, *cache_peer_serv; + + BIO *bio_chain; +} BIO_ACCEPT; + +static int acpt_write(BIO *h, const char *buf, int num); +static int acpt_read(BIO *h, char *buf, int size); +static int acpt_puts(BIO *h, const char *str); +static long acpt_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int acpt_new(BIO *h); +static int acpt_free(BIO *data); +static int acpt_state(BIO *b, BIO_ACCEPT *c); +static void acpt_close_socket(BIO *data); +static BIO_ACCEPT *BIO_ACCEPT_new(void); +static void BIO_ACCEPT_free(BIO_ACCEPT *a); + +# define ACPT_S_BEFORE 1 +# define ACPT_S_GET_ADDR 2 +# define ACPT_S_CREATE_SOCKET 3 +# define ACPT_S_LISTEN 4 +# define ACPT_S_ACCEPT 5 +# define ACPT_S_OK 6 + +static const BIO_METHOD methods_acceptp = { + BIO_TYPE_ACCEPT, + "socket accept", + /* TODO: Convert to new style write function */ + bwrite_conv, + acpt_write, + /* TODO: Convert to new style read function */ + bread_conv, + acpt_read, + acpt_puts, + NULL, /* connect_gets, */ + acpt_ctrl, + acpt_new, + acpt_free, + NULL, /* connect_callback_ctrl */ +}; + +const BIO_METHOD *BIO_s_accept(void) +{ + return &methods_acceptp; +} + +static int acpt_new(BIO *bi) +{ + BIO_ACCEPT *ba; + + bi->init = 0; + bi->num = (int)INVALID_SOCKET; + bi->flags = 0; + if ((ba = BIO_ACCEPT_new()) == NULL) + return 0; + bi->ptr = (char *)ba; + ba->state = ACPT_S_BEFORE; + bi->shutdown = 1; + return 1; +} + +static BIO_ACCEPT *BIO_ACCEPT_new(void) +{ + BIO_ACCEPT *ret; + + if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) { + BIOerr(BIO_F_BIO_ACCEPT_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + ret->accept_family = BIO_FAMILY_IPANY; + ret->accept_sock = (int)INVALID_SOCKET; + return ret; +} + +static void BIO_ACCEPT_free(BIO_ACCEPT *a) +{ + if (a == NULL) + return; + OPENSSL_free(a->param_addr); + OPENSSL_free(a->param_serv); + BIO_ADDRINFO_free(a->addr_first); + OPENSSL_free(a->cache_accepting_name); + OPENSSL_free(a->cache_accepting_serv); + OPENSSL_free(a->cache_peer_name); + OPENSSL_free(a->cache_peer_serv); + BIO_free(a->bio_chain); + OPENSSL_free(a); +} + +static void acpt_close_socket(BIO *bio) +{ + BIO_ACCEPT *c; + + c = (BIO_ACCEPT *)bio->ptr; + if (c->accept_sock != (int)INVALID_SOCKET) { + shutdown(c->accept_sock, 2); + closesocket(c->accept_sock); + c->accept_sock = (int)INVALID_SOCKET; + bio->num = (int)INVALID_SOCKET; + } +} + +static int acpt_free(BIO *a) +{ + BIO_ACCEPT *data; + + if (a == NULL) + return 0; + data = (BIO_ACCEPT *)a->ptr; + + if (a->shutdown) { + acpt_close_socket(a); + BIO_ACCEPT_free(data); + a->ptr = NULL; + a->flags = 0; + a->init = 0; + } + return 1; +} + +static int acpt_state(BIO *b, BIO_ACCEPT *c) +{ + BIO *bio = NULL, *dbio; + int s = -1, ret = -1; + + for (;;) { + switch (c->state) { + case ACPT_S_BEFORE: + if (c->param_addr == NULL && c->param_serv == NULL) { + BIOerr(BIO_F_ACPT_STATE, BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED); + ERR_add_error_data(4, + "hostname=", c->param_addr, + " service=", c->param_serv); + goto exit_loop; + } + + /* Because we're starting a new bind, any cached name and serv + * are now obsolete and need to be cleaned out. + * QUESTION: should this be done in acpt_close_socket() instead? + */ + OPENSSL_free(c->cache_accepting_name); + c->cache_accepting_name = NULL; + OPENSSL_free(c->cache_accepting_serv); + c->cache_accepting_serv = NULL; + OPENSSL_free(c->cache_peer_name); + c->cache_peer_name = NULL; + OPENSSL_free(c->cache_peer_serv); + c->cache_peer_serv = NULL; + + c->state = ACPT_S_GET_ADDR; + break; + + case ACPT_S_GET_ADDR: + { + int family = AF_UNSPEC; + switch (c->accept_family) { + case BIO_FAMILY_IPV6: + if (1) { /* This is a trick we use to avoid bit rot. + * at least the "else" part will always be + * compiled. + */ +#ifdef AF_INET6 + family = AF_INET6; + } else { +#endif + BIOerr(BIO_F_ACPT_STATE, BIO_R_UNAVAILABLE_IP_FAMILY); + goto exit_loop; + } + break; + case BIO_FAMILY_IPV4: + family = AF_INET; + break; + case BIO_FAMILY_IPANY: + family = AF_UNSPEC; + break; + default: + BIOerr(BIO_F_ACPT_STATE, BIO_R_UNSUPPORTED_IP_FAMILY); + goto exit_loop; + } + if (BIO_lookup(c->param_addr, c->param_serv, BIO_LOOKUP_SERVER, + family, SOCK_STREAM, &c->addr_first) == 0) + goto exit_loop; + } + if (c->addr_first == NULL) { + BIOerr(BIO_F_ACPT_STATE, BIO_R_LOOKUP_RETURNED_NOTHING); + goto exit_loop; + } + /* We're currently not iterating, but set this as preparation + * for possible future development in that regard + */ + c->addr_iter = c->addr_first; + c->state = ACPT_S_CREATE_SOCKET; + break; + + case ACPT_S_CREATE_SOCKET: + ret = BIO_socket(BIO_ADDRINFO_family(c->addr_iter), + BIO_ADDRINFO_socktype(c->addr_iter), + BIO_ADDRINFO_protocol(c->addr_iter), 0); + if (ret == (int)INVALID_SOCKET) { + SYSerr(SYS_F_SOCKET, get_last_socket_error()); + ERR_add_error_data(4, + "hostname=", c->param_addr, + " service=", c->param_serv); + BIOerr(BIO_F_ACPT_STATE, BIO_R_UNABLE_TO_CREATE_SOCKET); + goto exit_loop; + } + c->accept_sock = ret; + b->num = ret; + c->state = ACPT_S_LISTEN; + break; + + case ACPT_S_LISTEN: + { + if (!BIO_listen(c->accept_sock, + BIO_ADDRINFO_address(c->addr_iter), + c->bind_mode)) { + BIO_closesocket(c->accept_sock); + goto exit_loop; + } + } + + { + union BIO_sock_info_u info; + + info.addr = &c->cache_accepting_addr; + if (!BIO_sock_info(c->accept_sock, BIO_SOCK_INFO_ADDRESS, + &info)) { + BIO_closesocket(c->accept_sock); + goto exit_loop; + } + } + + c->cache_accepting_name = + BIO_ADDR_hostname_string(&c->cache_accepting_addr, 1); + c->cache_accepting_serv = + BIO_ADDR_service_string(&c->cache_accepting_addr, 1); + c->state = ACPT_S_ACCEPT; + s = -1; + ret = 1; + goto end; + + case ACPT_S_ACCEPT: + if (b->next_bio != NULL) { + c->state = ACPT_S_OK; + break; + } + BIO_clear_retry_flags(b); + b->retry_reason = 0; + + OPENSSL_free(c->cache_peer_name); + c->cache_peer_name = NULL; + OPENSSL_free(c->cache_peer_serv); + c->cache_peer_serv = NULL; + + s = BIO_accept_ex(c->accept_sock, &c->cache_peer_addr, + c->accepted_mode); + + /* If the returned socket is invalid, this might still be + * retryable + */ + if (s < 0) { + if (BIO_sock_should_retry(s)) { + BIO_set_retry_special(b); + b->retry_reason = BIO_RR_ACCEPT; + goto end; + } + } + + /* If it wasn't retryable, we fail */ + if (s < 0) { + ret = s; + goto exit_loop; + } + + bio = BIO_new_socket(s, BIO_CLOSE); + if (bio == NULL) + goto exit_loop; + + BIO_set_callback(bio, BIO_get_callback(b)); + BIO_set_callback_arg(bio, BIO_get_callback_arg(b)); + + /* + * If the accept BIO has an bio_chain, we dup it and put the new + * socket at the end. + */ + if (c->bio_chain != NULL) { + if ((dbio = BIO_dup_chain(c->bio_chain)) == NULL) + goto exit_loop; + if (!BIO_push(dbio, bio)) + goto exit_loop; + bio = dbio; + } + if (BIO_push(b, bio) == NULL) + goto exit_loop; + + c->cache_peer_name = + BIO_ADDR_hostname_string(&c->cache_peer_addr, 1); + c->cache_peer_serv = + BIO_ADDR_service_string(&c->cache_peer_addr, 1); + c->state = ACPT_S_OK; + bio = NULL; + ret = 1; + goto end; + + case ACPT_S_OK: + if (b->next_bio == NULL) { + c->state = ACPT_S_ACCEPT; + break; + } + ret = 1; + goto end; + + default: + ret = 0; + goto end; + } + } + + exit_loop: + if (bio != NULL) + BIO_free(bio); + else if (s >= 0) + BIO_closesocket(s); + end: + return ret; +} + +static int acpt_read(BIO *b, char *out, int outl) +{ + int ret = 0; + BIO_ACCEPT *data; + + BIO_clear_retry_flags(b); + data = (BIO_ACCEPT *)b->ptr; + + while (b->next_bio == NULL) { + ret = acpt_state(b, data); + if (ret <= 0) + return ret; + } + + ret = BIO_read(b->next_bio, out, outl); + BIO_copy_next_retry(b); + return ret; +} + +static int acpt_write(BIO *b, const char *in, int inl) +{ + int ret; + BIO_ACCEPT *data; + + BIO_clear_retry_flags(b); + data = (BIO_ACCEPT *)b->ptr; + + while (b->next_bio == NULL) { + ret = acpt_state(b, data); + if (ret <= 0) + return ret; + } + + ret = BIO_write(b->next_bio, in, inl); + BIO_copy_next_retry(b); + return ret; +} + +static long acpt_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + int *ip; + long ret = 1; + BIO_ACCEPT *data; + char **pp; + + data = (BIO_ACCEPT *)b->ptr; + + switch (cmd) { + case BIO_CTRL_RESET: + ret = 0; + data->state = ACPT_S_BEFORE; + acpt_close_socket(b); + BIO_ADDRINFO_free(data->addr_first); + data->addr_first = NULL; + b->flags = 0; + break; + case BIO_C_DO_STATE_MACHINE: + /* use this one to start the connection */ + ret = (long)acpt_state(b, data); + break; + case BIO_C_SET_ACCEPT: + if (ptr != NULL) { + if (num == 0) { + char *hold_serv = data->param_serv; + /* We affect the hostname regardless. However, the input + * string might contain a host:service spec, so we must + * parse it, which might or might not affect the service + */ + OPENSSL_free(data->param_addr); + data->param_addr = NULL; + ret = BIO_parse_hostserv(ptr, + &data->param_addr, + &data->param_serv, + BIO_PARSE_PRIO_SERV); + if (hold_serv != data->param_serv) + OPENSSL_free(hold_serv); + b->init = 1; + } else if (num == 1) { + OPENSSL_free(data->param_serv); + data->param_serv = BUF_strdup(ptr); + b->init = 1; + } else if (num == 2) { + data->bind_mode |= BIO_SOCK_NONBLOCK; + } else if (num == 3) { + BIO_free(data->bio_chain); + data->bio_chain = (BIO *)ptr; + } else if (num == 4) { + data->accept_family = *(int *)ptr; + } + } else { + if (num == 2) { + data->bind_mode &= ~BIO_SOCK_NONBLOCK; + } + } + break; + case BIO_C_SET_NBIO: + if (num != 0) + data->accepted_mode |= BIO_SOCK_NONBLOCK; + else + data->accepted_mode &= ~BIO_SOCK_NONBLOCK; + break; + case BIO_C_SET_FD: + b->num = *((int *)ptr); + data->accept_sock = b->num; + data->state = ACPT_S_ACCEPT; + b->shutdown = (int)num; + b->init = 1; + break; + case BIO_C_GET_FD: + if (b->init) { + ip = (int *)ptr; + if (ip != NULL) + *ip = data->accept_sock; + ret = data->accept_sock; + } else + ret = -1; + break; + case BIO_C_GET_ACCEPT: + if (b->init) { + if (num == 0 && ptr != NULL) { + pp = (char **)ptr; + *pp = data->cache_accepting_name; + } else if (num == 1 && ptr != NULL) { + pp = (char **)ptr; + *pp = data->cache_accepting_serv; + } else if (num == 2 && ptr != NULL) { + pp = (char **)ptr; + *pp = data->cache_peer_name; + } else if (num == 3 && ptr != NULL) { + pp = (char **)ptr; + *pp = data->cache_peer_serv; + } else if (num == 4) { + switch (BIO_ADDRINFO_family(data->addr_iter)) { +#ifdef AF_INET6 + case AF_INET6: + ret = BIO_FAMILY_IPV6; + break; +#endif + case AF_INET: + ret = BIO_FAMILY_IPV4; + break; + case 0: + ret = data->accept_family; + break; + default: + ret = -1; + break; + } + } else + ret = -1; + } else + ret = -1; + break; + case BIO_CTRL_GET_CLOSE: + ret = b->shutdown; + break; + case BIO_CTRL_SET_CLOSE: + b->shutdown = (int)num; + break; + case BIO_CTRL_PENDING: + case BIO_CTRL_WPENDING: + ret = 0; + break; + case BIO_CTRL_FLUSH: + break; + case BIO_C_SET_BIND_MODE: + data->bind_mode = (int)num; + break; + case BIO_C_GET_BIND_MODE: + ret = (long)data->bind_mode; + break; + case BIO_CTRL_DUP: + break; + + default: + ret = 0; + break; + } + return ret; +} + +static int acpt_puts(BIO *bp, const char *str) +{ + int n, ret; + + n = strlen(str); + ret = acpt_write(bp, str, n); + return ret; +} + +BIO *BIO_new_accept(const char *str) +{ + BIO *ret; + + ret = BIO_new(BIO_s_accept()); + if (ret == NULL) + return NULL; + if (BIO_set_accept_name(ret, str)) + return ret; + BIO_free(ret); + return NULL; +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_bio.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_bio.c new file mode 100644 index 000000000..e34382c55 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_bio.c @@ -0,0 +1,808 @@ +/* + * Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Special method for a BIO where the other endpoint is also a BIO of this + * kind, handled by the same thread (i.e. the "peer" is actually ourselves, + * wearing a different hat). Such "BIO pairs" are mainly for using the SSL + * library with I/O interfaces for which no specific BIO method is available. + * See ssl/ssltest.c for some hints on how this can be used. + */ + +#include "e_os.h" +#include +#include +#include +#include + +#include "bio_lcl.h" +#include +#include + +static int bio_new(BIO *bio); +static int bio_free(BIO *bio); +static int bio_read(BIO *bio, char *buf, int size); +static int bio_write(BIO *bio, const char *buf, int num); +static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr); +static int bio_puts(BIO *bio, const char *str); + +static int bio_make_pair(BIO *bio1, BIO *bio2); +static void bio_destroy_pair(BIO *bio); + +static const BIO_METHOD methods_biop = { + BIO_TYPE_BIO, + "BIO pair", + /* TODO: Convert to new style write function */ + bwrite_conv, + bio_write, + /* TODO: Convert to new style read function */ + bread_conv, + bio_read, + bio_puts, + NULL /* no bio_gets */ , + bio_ctrl, + bio_new, + bio_free, + NULL /* no bio_callback_ctrl */ +}; + +const BIO_METHOD *BIO_s_bio(void) +{ + return &methods_biop; +} + +struct bio_bio_st { + BIO *peer; /* NULL if buf == NULL. If peer != NULL, then + * peer->ptr is also a bio_bio_st, and its + * "peer" member points back to us. peer != + * NULL iff init != 0 in the BIO. */ + /* This is for what we write (i.e. reading uses peer's struct): */ + int closed; /* valid iff peer != NULL */ + size_t len; /* valid iff buf != NULL; 0 if peer == NULL */ + size_t offset; /* valid iff buf != NULL; 0 if len == 0 */ + size_t size; + char *buf; /* "size" elements (if != NULL) */ + size_t request; /* valid iff peer != NULL; 0 if len != 0, + * otherwise set by peer to number of bytes + * it (unsuccessfully) tried to read, never + * more than buffer space (size-len) + * warrants. */ +}; + +static int bio_new(BIO *bio) +{ + struct bio_bio_st *b = OPENSSL_zalloc(sizeof(*b)); + + if (b == NULL) + return 0; + + /* enough for one TLS record (just a default) */ + b->size = 17 * 1024; + + bio->ptr = b; + return 1; +} + +static int bio_free(BIO *bio) +{ + struct bio_bio_st *b; + + if (bio == NULL) + return 0; + b = bio->ptr; + + assert(b != NULL); + + if (b->peer) + bio_destroy_pair(bio); + + OPENSSL_free(b->buf); + OPENSSL_free(b); + + return 1; +} + +static int bio_read(BIO *bio, char *buf, int size_) +{ + size_t size = size_; + size_t rest; + struct bio_bio_st *b, *peer_b; + + BIO_clear_retry_flags(bio); + + if (!bio->init) + return 0; + + b = bio->ptr; + assert(b != NULL); + assert(b->peer != NULL); + peer_b = b->peer->ptr; + assert(peer_b != NULL); + assert(peer_b->buf != NULL); + + peer_b->request = 0; /* will be set in "retry_read" situation */ + + if (buf == NULL || size == 0) + return 0; + + if (peer_b->len == 0) { + if (peer_b->closed) + return 0; /* writer has closed, and no data is left */ + else { + BIO_set_retry_read(bio); /* buffer is empty */ + if (size <= peer_b->size) + peer_b->request = size; + else + /* + * don't ask for more than the peer can deliver in one write + */ + peer_b->request = peer_b->size; + return -1; + } + } + + /* we can read */ + if (peer_b->len < size) + size = peer_b->len; + + /* now read "size" bytes */ + + rest = size; + + assert(rest > 0); + do { /* one or two iterations */ + size_t chunk; + + assert(rest <= peer_b->len); + if (peer_b->offset + rest <= peer_b->size) + chunk = rest; + else + /* wrap around ring buffer */ + chunk = peer_b->size - peer_b->offset; + assert(peer_b->offset + chunk <= peer_b->size); + + memcpy(buf, peer_b->buf + peer_b->offset, chunk); + + peer_b->len -= chunk; + if (peer_b->len) { + peer_b->offset += chunk; + assert(peer_b->offset <= peer_b->size); + if (peer_b->offset == peer_b->size) + peer_b->offset = 0; + buf += chunk; + } else { + /* buffer now empty, no need to advance "buf" */ + assert(chunk == rest); + peer_b->offset = 0; + } + rest -= chunk; + } + while (rest); + + return size; +} + +/*- + * non-copying interface: provide pointer to available data in buffer + * bio_nread0: return number of available bytes + * bio_nread: also advance index + * (example usage: bio_nread0(), read from buffer, bio_nread() + * or just bio_nread(), read from buffer) + */ +/* + * WARNING: The non-copying interface is largely untested as of yet and may + * contain bugs. + */ +static ossl_ssize_t bio_nread0(BIO *bio, char **buf) +{ + struct bio_bio_st *b, *peer_b; + ossl_ssize_t num; + + BIO_clear_retry_flags(bio); + + if (!bio->init) + return 0; + + b = bio->ptr; + assert(b != NULL); + assert(b->peer != NULL); + peer_b = b->peer->ptr; + assert(peer_b != NULL); + assert(peer_b->buf != NULL); + + peer_b->request = 0; + + if (peer_b->len == 0) { + char dummy; + + /* avoid code duplication -- nothing available for reading */ + return bio_read(bio, &dummy, 1); /* returns 0 or -1 */ + } + + num = peer_b->len; + if (peer_b->size < peer_b->offset + num) + /* no ring buffer wrap-around for non-copying interface */ + num = peer_b->size - peer_b->offset; + assert(num > 0); + + if (buf != NULL) + *buf = peer_b->buf + peer_b->offset; + return num; +} + +static ossl_ssize_t bio_nread(BIO *bio, char **buf, size_t num_) +{ + struct bio_bio_st *b, *peer_b; + ossl_ssize_t num, available; + + if (num_ > OSSL_SSIZE_MAX) + num = OSSL_SSIZE_MAX; + else + num = (ossl_ssize_t) num_; + + available = bio_nread0(bio, buf); + if (num > available) + num = available; + if (num <= 0) + return num; + + b = bio->ptr; + peer_b = b->peer->ptr; + + peer_b->len -= num; + if (peer_b->len) { + peer_b->offset += num; + assert(peer_b->offset <= peer_b->size); + if (peer_b->offset == peer_b->size) + peer_b->offset = 0; + } else + peer_b->offset = 0; + + return num; +} + +static int bio_write(BIO *bio, const char *buf, int num_) +{ + size_t num = num_; + size_t rest; + struct bio_bio_st *b; + + BIO_clear_retry_flags(bio); + + if (!bio->init || buf == NULL || num == 0) + return 0; + + b = bio->ptr; + assert(b != NULL); + assert(b->peer != NULL); + assert(b->buf != NULL); + + b->request = 0; + if (b->closed) { + /* we already closed */ + BIOerr(BIO_F_BIO_WRITE, BIO_R_BROKEN_PIPE); + return -1; + } + + assert(b->len <= b->size); + + if (b->len == b->size) { + BIO_set_retry_write(bio); /* buffer is full */ + return -1; + } + + /* we can write */ + if (num > b->size - b->len) + num = b->size - b->len; + + /* now write "num" bytes */ + + rest = num; + + assert(rest > 0); + do { /* one or two iterations */ + size_t write_offset; + size_t chunk; + + assert(b->len + rest <= b->size); + + write_offset = b->offset + b->len; + if (write_offset >= b->size) + write_offset -= b->size; + /* b->buf[write_offset] is the first byte we can write to. */ + + if (write_offset + rest <= b->size) + chunk = rest; + else + /* wrap around ring buffer */ + chunk = b->size - write_offset; + + memcpy(b->buf + write_offset, buf, chunk); + + b->len += chunk; + + assert(b->len <= b->size); + + rest -= chunk; + buf += chunk; + } + while (rest); + + return num; +} + +/*- + * non-copying interface: provide pointer to region to write to + * bio_nwrite0: check how much space is available + * bio_nwrite: also increase length + * (example usage: bio_nwrite0(), write to buffer, bio_nwrite() + * or just bio_nwrite(), write to buffer) + */ +static ossl_ssize_t bio_nwrite0(BIO *bio, char **buf) +{ + struct bio_bio_st *b; + size_t num; + size_t write_offset; + + BIO_clear_retry_flags(bio); + + if (!bio->init) + return 0; + + b = bio->ptr; + assert(b != NULL); + assert(b->peer != NULL); + assert(b->buf != NULL); + + b->request = 0; + if (b->closed) { + BIOerr(BIO_F_BIO_NWRITE0, BIO_R_BROKEN_PIPE); + return -1; + } + + assert(b->len <= b->size); + + if (b->len == b->size) { + BIO_set_retry_write(bio); + return -1; + } + + num = b->size - b->len; + write_offset = b->offset + b->len; + if (write_offset >= b->size) + write_offset -= b->size; + if (write_offset + num > b->size) + /* + * no ring buffer wrap-around for non-copying interface (to fulfil + * the promise by BIO_ctrl_get_write_guarantee, BIO_nwrite may have + * to be called twice) + */ + num = b->size - write_offset; + + if (buf != NULL) + *buf = b->buf + write_offset; + assert(write_offset + num <= b->size); + + return num; +} + +static ossl_ssize_t bio_nwrite(BIO *bio, char **buf, size_t num_) +{ + struct bio_bio_st *b; + ossl_ssize_t num, space; + + if (num_ > OSSL_SSIZE_MAX) + num = OSSL_SSIZE_MAX; + else + num = (ossl_ssize_t) num_; + + space = bio_nwrite0(bio, buf); + if (num > space) + num = space; + if (num <= 0) + return num; + b = bio->ptr; + assert(b != NULL); + b->len += num; + assert(b->len <= b->size); + + return num; +} + +static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) +{ + long ret; + struct bio_bio_st *b = bio->ptr; + + assert(b != NULL); + + switch (cmd) { + /* specific CTRL codes */ + + case BIO_C_SET_WRITE_BUF_SIZE: + if (b->peer) { + BIOerr(BIO_F_BIO_CTRL, BIO_R_IN_USE); + ret = 0; + } else if (num == 0) { + BIOerr(BIO_F_BIO_CTRL, BIO_R_INVALID_ARGUMENT); + ret = 0; + } else { + size_t new_size = num; + + if (b->size != new_size) { + OPENSSL_free(b->buf); + b->buf = NULL; + b->size = new_size; + } + ret = 1; + } + break; + + case BIO_C_GET_WRITE_BUF_SIZE: + ret = (long)b->size; + break; + + case BIO_C_MAKE_BIO_PAIR: + { + BIO *other_bio = ptr; + + if (bio_make_pair(bio, other_bio)) + ret = 1; + else + ret = 0; + } + break; + + case BIO_C_DESTROY_BIO_PAIR: + /* + * Affects both BIOs in the pair -- call just once! Or let + * BIO_free(bio1); BIO_free(bio2); do the job. + */ + bio_destroy_pair(bio); + ret = 1; + break; + + case BIO_C_GET_WRITE_GUARANTEE: + /* + * How many bytes can the caller feed to the next write without + * having to keep any? + */ + if (b->peer == NULL || b->closed) + ret = 0; + else + ret = (long)b->size - b->len; + break; + + case BIO_C_GET_READ_REQUEST: + /* + * If the peer unsuccessfully tried to read, how many bytes were + * requested? (As with BIO_CTRL_PENDING, that number can usually be + * treated as boolean.) + */ + ret = (long)b->request; + break; + + case BIO_C_RESET_READ_REQUEST: + /* + * Reset request. (Can be useful after read attempts at the other + * side that are meant to be non-blocking, e.g. when probing SSL_read + * to see if any data is available.) + */ + b->request = 0; + ret = 1; + break; + + case BIO_C_SHUTDOWN_WR: + /* similar to shutdown(..., SHUT_WR) */ + b->closed = 1; + ret = 1; + break; + + case BIO_C_NREAD0: + /* prepare for non-copying read */ + ret = (long)bio_nread0(bio, ptr); + break; + + case BIO_C_NREAD: + /* non-copying read */ + ret = (long)bio_nread(bio, ptr, (size_t)num); + break; + + case BIO_C_NWRITE0: + /* prepare for non-copying write */ + ret = (long)bio_nwrite0(bio, ptr); + break; + + case BIO_C_NWRITE: + /* non-copying write */ + ret = (long)bio_nwrite(bio, ptr, (size_t)num); + break; + + /* standard CTRL codes follow */ + + case BIO_CTRL_RESET: + if (b->buf != NULL) { + b->len = 0; + b->offset = 0; + } + ret = 0; + break; + + case BIO_CTRL_GET_CLOSE: + ret = bio->shutdown; + break; + + case BIO_CTRL_SET_CLOSE: + bio->shutdown = (int)num; + ret = 1; + break; + + case BIO_CTRL_PENDING: + if (b->peer != NULL) { + struct bio_bio_st *peer_b = b->peer->ptr; + + ret = (long)peer_b->len; + } else + ret = 0; + break; + + case BIO_CTRL_WPENDING: + if (b->buf != NULL) + ret = (long)b->len; + else + ret = 0; + break; + + case BIO_CTRL_DUP: + /* See BIO_dup_chain for circumstances we have to expect. */ + { + BIO *other_bio = ptr; + struct bio_bio_st *other_b; + + assert(other_bio != NULL); + other_b = other_bio->ptr; + assert(other_b != NULL); + + assert(other_b->buf == NULL); /* other_bio is always fresh */ + + other_b->size = b->size; + } + + ret = 1; + break; + + case BIO_CTRL_FLUSH: + ret = 1; + break; + + case BIO_CTRL_EOF: + if (b->peer != NULL) { + struct bio_bio_st *peer_b = b->peer->ptr; + + if (peer_b->len == 0 && peer_b->closed) + ret = 1; + else + ret = 0; + } else { + ret = 1; + } + break; + + default: + ret = 0; + } + return ret; +} + +static int bio_puts(BIO *bio, const char *str) +{ + return bio_write(bio, str, strlen(str)); +} + +static int bio_make_pair(BIO *bio1, BIO *bio2) +{ + struct bio_bio_st *b1, *b2; + + assert(bio1 != NULL); + assert(bio2 != NULL); + + b1 = bio1->ptr; + b2 = bio2->ptr; + + if (b1->peer != NULL || b2->peer != NULL) { + BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE); + return 0; + } + + if (b1->buf == NULL) { + b1->buf = OPENSSL_malloc(b1->size); + if (b1->buf == NULL) { + BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); + return 0; + } + b1->len = 0; + b1->offset = 0; + } + + if (b2->buf == NULL) { + b2->buf = OPENSSL_malloc(b2->size); + if (b2->buf == NULL) { + BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); + return 0; + } + b2->len = 0; + b2->offset = 0; + } + + b1->peer = bio2; + b1->closed = 0; + b1->request = 0; + b2->peer = bio1; + b2->closed = 0; + b2->request = 0; + + bio1->init = 1; + bio2->init = 1; + + return 1; +} + +static void bio_destroy_pair(BIO *bio) +{ + struct bio_bio_st *b = bio->ptr; + + if (b != NULL) { + BIO *peer_bio = b->peer; + + if (peer_bio != NULL) { + struct bio_bio_st *peer_b = peer_bio->ptr; + + assert(peer_b != NULL); + assert(peer_b->peer == bio); + + peer_b->peer = NULL; + peer_bio->init = 0; + assert(peer_b->buf != NULL); + peer_b->len = 0; + peer_b->offset = 0; + + b->peer = NULL; + bio->init = 0; + assert(b->buf != NULL); + b->len = 0; + b->offset = 0; + } + } +} + +/* Exported convenience functions */ +int BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1, + BIO **bio2_p, size_t writebuf2) +{ + BIO *bio1 = NULL, *bio2 = NULL; + long r; + int ret = 0; + + bio1 = BIO_new(BIO_s_bio()); + if (bio1 == NULL) + goto err; + bio2 = BIO_new(BIO_s_bio()); + if (bio2 == NULL) + goto err; + + if (writebuf1) { + r = BIO_set_write_buf_size(bio1, writebuf1); + if (!r) + goto err; + } + if (writebuf2) { + r = BIO_set_write_buf_size(bio2, writebuf2); + if (!r) + goto err; + } + + r = BIO_make_bio_pair(bio1, bio2); + if (!r) + goto err; + ret = 1; + + err: + if (ret == 0) { + BIO_free(bio1); + bio1 = NULL; + BIO_free(bio2); + bio2 = NULL; + } + + *bio1_p = bio1; + *bio2_p = bio2; + return ret; +} + +size_t BIO_ctrl_get_write_guarantee(BIO *bio) +{ + return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL); +} + +size_t BIO_ctrl_get_read_request(BIO *bio) +{ + return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL); +} + +int BIO_ctrl_reset_read_request(BIO *bio) +{ + return (BIO_ctrl(bio, BIO_C_RESET_READ_REQUEST, 0, NULL) != 0); +} + +/* + * BIO_nread0/nread/nwrite0/nwrite are available only for BIO pairs for now + * (conceivably some other BIOs could allow non-copying reads and writes + * too.) + */ +int BIO_nread0(BIO *bio, char **buf) +{ + long ret; + + if (!bio->init) { + BIOerr(BIO_F_BIO_NREAD0, BIO_R_UNINITIALIZED); + return -2; + } + + ret = BIO_ctrl(bio, BIO_C_NREAD0, 0, buf); + if (ret > INT_MAX) + return INT_MAX; + else + return (int)ret; +} + +int BIO_nread(BIO *bio, char **buf, int num) +{ + int ret; + + if (!bio->init) { + BIOerr(BIO_F_BIO_NREAD, BIO_R_UNINITIALIZED); + return -2; + } + + ret = (int)BIO_ctrl(bio, BIO_C_NREAD, num, buf); + if (ret > 0) + bio->num_read += ret; + return ret; +} + +int BIO_nwrite0(BIO *bio, char **buf) +{ + long ret; + + if (!bio->init) { + BIOerr(BIO_F_BIO_NWRITE0, BIO_R_UNINITIALIZED); + return -2; + } + + ret = BIO_ctrl(bio, BIO_C_NWRITE0, 0, buf); + if (ret > INT_MAX) + return INT_MAX; + else + return (int)ret; +} + +int BIO_nwrite(BIO *bio, char **buf, int num) +{ + int ret; + + if (!bio->init) { + BIOerr(BIO_F_BIO_NWRITE, BIO_R_UNINITIALIZED); + return -2; + } + + ret = BIO_ctrl(bio, BIO_C_NWRITE, num, buf); + if (ret > 0) + bio->num_write += ret; + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_conn.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_conn.c new file mode 100644 index 000000000..e9673fe78 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_conn.c @@ -0,0 +1,540 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#include "bio_lcl.h" + +#ifndef OPENSSL_NO_SOCK + +typedef struct bio_connect_st { + int state; + int connect_family; + char *param_hostname; + char *param_service; + int connect_mode; + + BIO_ADDRINFO *addr_first; + const BIO_ADDRINFO *addr_iter; + /* + * int socket; this will be kept in bio->num so that it is compatible + * with the bss_sock bio + */ + /* + * called when the connection is initially made callback(BIO,state,ret); + * The callback should return 'ret'. state is for compatibility with the + * ssl info_callback + */ + BIO_info_cb *info_callback; +} BIO_CONNECT; + +static int conn_write(BIO *h, const char *buf, int num); +static int conn_read(BIO *h, char *buf, int size); +static int conn_puts(BIO *h, const char *str); +static long conn_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int conn_new(BIO *h); +static int conn_free(BIO *data); +static long conn_callback_ctrl(BIO *h, int cmd, BIO_info_cb *); + +static int conn_state(BIO *b, BIO_CONNECT *c); +static void conn_close_socket(BIO *data); +BIO_CONNECT *BIO_CONNECT_new(void); +void BIO_CONNECT_free(BIO_CONNECT *a); + +#define BIO_CONN_S_BEFORE 1 +#define BIO_CONN_S_GET_ADDR 2 +#define BIO_CONN_S_CREATE_SOCKET 3 +#define BIO_CONN_S_CONNECT 4 +#define BIO_CONN_S_OK 5 +#define BIO_CONN_S_BLOCKED_CONNECT 6 + +static const BIO_METHOD methods_connectp = { + BIO_TYPE_CONNECT, + "socket connect", + /* TODO: Convert to new style write function */ + bwrite_conv, + conn_write, + /* TODO: Convert to new style read function */ + bread_conv, + conn_read, + conn_puts, + NULL, /* conn_gets, */ + conn_ctrl, + conn_new, + conn_free, + conn_callback_ctrl, +}; + +static int conn_state(BIO *b, BIO_CONNECT *c) +{ + int ret = -1, i; + BIO_info_cb *cb = NULL; + + if (c->info_callback != NULL) + cb = c->info_callback; + + for (;;) { + switch (c->state) { + case BIO_CONN_S_BEFORE: + if (c->param_hostname == NULL && c->param_service == NULL) { + BIOerr(BIO_F_CONN_STATE, BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED); + ERR_add_error_data(4, + "hostname=", c->param_hostname, + " service=", c->param_service); + goto exit_loop; + } + c->state = BIO_CONN_S_GET_ADDR; + break; + + case BIO_CONN_S_GET_ADDR: + { + int family = AF_UNSPEC; + switch (c->connect_family) { + case BIO_FAMILY_IPV6: + if (1) { /* This is a trick we use to avoid bit rot. + * at least the "else" part will always be + * compiled. + */ +#ifdef AF_INET6 + family = AF_INET6; + } else { +#endif + BIOerr(BIO_F_CONN_STATE, BIO_R_UNAVAILABLE_IP_FAMILY); + goto exit_loop; + } + break; + case BIO_FAMILY_IPV4: + family = AF_INET; + break; + case BIO_FAMILY_IPANY: + family = AF_UNSPEC; + break; + default: + BIOerr(BIO_F_CONN_STATE, BIO_R_UNSUPPORTED_IP_FAMILY); + goto exit_loop; + } + if (BIO_lookup(c->param_hostname, c->param_service, + BIO_LOOKUP_CLIENT, + family, SOCK_STREAM, &c->addr_first) == 0) + goto exit_loop; + } + if (c->addr_first == NULL) { + BIOerr(BIO_F_CONN_STATE, BIO_R_LOOKUP_RETURNED_NOTHING); + goto exit_loop; + } + c->addr_iter = c->addr_first; + c->state = BIO_CONN_S_CREATE_SOCKET; + break; + + case BIO_CONN_S_CREATE_SOCKET: + ret = BIO_socket(BIO_ADDRINFO_family(c->addr_iter), + BIO_ADDRINFO_socktype(c->addr_iter), + BIO_ADDRINFO_protocol(c->addr_iter), 0); + if (ret == (int)INVALID_SOCKET) { + SYSerr(SYS_F_SOCKET, get_last_socket_error()); + ERR_add_error_data(4, + "hostname=", c->param_hostname, + " service=", c->param_service); + BIOerr(BIO_F_CONN_STATE, BIO_R_UNABLE_TO_CREATE_SOCKET); + goto exit_loop; + } + b->num = ret; + c->state = BIO_CONN_S_CONNECT; + break; + + case BIO_CONN_S_CONNECT: + BIO_clear_retry_flags(b); + ret = BIO_connect(b->num, BIO_ADDRINFO_address(c->addr_iter), + BIO_SOCK_KEEPALIVE | c->connect_mode); + b->retry_reason = 0; + if (ret == 0) { + if (BIO_sock_should_retry(ret)) { + BIO_set_retry_special(b); + c->state = BIO_CONN_S_BLOCKED_CONNECT; + b->retry_reason = BIO_RR_CONNECT; + ERR_clear_error(); + } else if ((c->addr_iter = BIO_ADDRINFO_next(c->addr_iter)) + != NULL) { + /* + * if there are more addresses to try, do that first + */ + BIO_closesocket(b->num); + c->state = BIO_CONN_S_CREATE_SOCKET; + ERR_clear_error(); + break; + } else { + SYSerr(SYS_F_CONNECT, get_last_socket_error()); + ERR_add_error_data(4, + "hostname=", c->param_hostname, + " service=", c->param_service); + BIOerr(BIO_F_CONN_STATE, BIO_R_CONNECT_ERROR); + } + goto exit_loop; + } else { + c->state = BIO_CONN_S_OK; + } + break; + + case BIO_CONN_S_BLOCKED_CONNECT: + i = BIO_sock_error(b->num); + if (i) { + BIO_clear_retry_flags(b); + SYSerr(SYS_F_CONNECT, i); + ERR_add_error_data(4, + "hostname=", c->param_hostname, + " service=", c->param_service); + BIOerr(BIO_F_CONN_STATE, BIO_R_NBIO_CONNECT_ERROR); + ret = 0; + goto exit_loop; + } else + c->state = BIO_CONN_S_OK; + break; + + case BIO_CONN_S_OK: + ret = 1; + goto exit_loop; + default: + /* abort(); */ + goto exit_loop; + } + + if (cb != NULL) { + if ((ret = cb((BIO *)b, c->state, ret)) == 0) + goto end; + } + } + + /* Loop does not exit */ + exit_loop: + if (cb != NULL) + ret = cb((BIO *)b, c->state, ret); + end: + return ret; +} + +BIO_CONNECT *BIO_CONNECT_new(void) +{ + BIO_CONNECT *ret; + + if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) { + BIOerr(BIO_F_BIO_CONNECT_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + ret->state = BIO_CONN_S_BEFORE; + ret->connect_family = BIO_FAMILY_IPANY; + return ret; +} + +void BIO_CONNECT_free(BIO_CONNECT *a) +{ + if (a == NULL) + return; + OPENSSL_free(a->param_hostname); + OPENSSL_free(a->param_service); + BIO_ADDRINFO_free(a->addr_first); + OPENSSL_free(a); +} + +const BIO_METHOD *BIO_s_connect(void) +{ + return &methods_connectp; +} + +static int conn_new(BIO *bi) +{ + bi->init = 0; + bi->num = (int)INVALID_SOCKET; + bi->flags = 0; + if ((bi->ptr = (char *)BIO_CONNECT_new()) == NULL) + return 0; + else + return 1; +} + +static void conn_close_socket(BIO *bio) +{ + BIO_CONNECT *c; + + c = (BIO_CONNECT *)bio->ptr; + if (bio->num != (int)INVALID_SOCKET) { + /* Only do a shutdown if things were established */ + if (c->state == BIO_CONN_S_OK) + shutdown(bio->num, 2); + BIO_closesocket(bio->num); + bio->num = (int)INVALID_SOCKET; + } +} + +static int conn_free(BIO *a) +{ + BIO_CONNECT *data; + + if (a == NULL) + return 0; + data = (BIO_CONNECT *)a->ptr; + + if (a->shutdown) { + conn_close_socket(a); + BIO_CONNECT_free(data); + a->ptr = NULL; + a->flags = 0; + a->init = 0; + } + return 1; +} + +static int conn_read(BIO *b, char *out, int outl) +{ + int ret = 0; + BIO_CONNECT *data; + + data = (BIO_CONNECT *)b->ptr; + if (data->state != BIO_CONN_S_OK) { + ret = conn_state(b, data); + if (ret <= 0) + return ret; + } + + if (out != NULL) { + clear_socket_error(); + ret = readsocket(b->num, out, outl); + BIO_clear_retry_flags(b); + if (ret <= 0) { + if (BIO_sock_should_retry(ret)) + BIO_set_retry_read(b); + } + } + return ret; +} + +static int conn_write(BIO *b, const char *in, int inl) +{ + int ret; + BIO_CONNECT *data; + + data = (BIO_CONNECT *)b->ptr; + if (data->state != BIO_CONN_S_OK) { + ret = conn_state(b, data); + if (ret <= 0) + return ret; + } + + clear_socket_error(); + ret = writesocket(b->num, in, inl); + BIO_clear_retry_flags(b); + if (ret <= 0) { + if (BIO_sock_should_retry(ret)) + BIO_set_retry_write(b); + } + return ret; +} + +static long conn_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + BIO *dbio; + int *ip; + const char **pptr = NULL; + long ret = 1; + BIO_CONNECT *data; + + data = (BIO_CONNECT *)b->ptr; + + switch (cmd) { + case BIO_CTRL_RESET: + ret = 0; + data->state = BIO_CONN_S_BEFORE; + conn_close_socket(b); + BIO_ADDRINFO_free(data->addr_first); + data->addr_first = NULL; + b->flags = 0; + break; + case BIO_C_DO_STATE_MACHINE: + /* use this one to start the connection */ + if (data->state != BIO_CONN_S_OK) + ret = (long)conn_state(b, data); + else + ret = 1; + break; + case BIO_C_GET_CONNECT: + if (ptr != NULL) { + pptr = (const char **)ptr; + if (num == 0) { + *pptr = data->param_hostname; + } else if (num == 1) { + *pptr = data->param_service; + } else if (num == 2) { + *pptr = (const char *)BIO_ADDRINFO_address(data->addr_iter); + } else if (num == 3) { + switch (BIO_ADDRINFO_family(data->addr_iter)) { +# ifdef AF_INET6 + case AF_INET6: + ret = BIO_FAMILY_IPV6; + break; +# endif + case AF_INET: + ret = BIO_FAMILY_IPV4; + break; + case 0: + ret = data->connect_family; + break; + default: + ret = -1; + break; + } + } else { + ret = 0; + } + } else { + ret = 0; + } + break; + case BIO_C_SET_CONNECT: + if (ptr != NULL) { + b->init = 1; + if (num == 0) { + char *hold_service = data->param_service; + /* We affect the hostname regardless. However, the input + * string might contain a host:service spec, so we must + * parse it, which might or might not affect the service + */ + OPENSSL_free(data->param_hostname); + data->param_hostname = NULL; + ret = BIO_parse_hostserv(ptr, + &data->param_hostname, + &data->param_service, + BIO_PARSE_PRIO_HOST); + if (hold_service != data->param_service) + OPENSSL_free(hold_service); + } else if (num == 1) { + OPENSSL_free(data->param_service); + data->param_service = BUF_strdup(ptr); + } else if (num == 2) { + const BIO_ADDR *addr = (const BIO_ADDR *)ptr; + if (ret) { + data->param_hostname = BIO_ADDR_hostname_string(addr, 1); + data->param_service = BIO_ADDR_service_string(addr, 1); + BIO_ADDRINFO_free(data->addr_first); + data->addr_first = NULL; + data->addr_iter = NULL; + } + } else if (num == 3) { + data->connect_family = *(int *)ptr; + } else { + ret = 0; + } + } + break; + case BIO_C_SET_NBIO: + if (num != 0) + data->connect_mode |= BIO_SOCK_NONBLOCK; + else + data->connect_mode &= ~BIO_SOCK_NONBLOCK; + break; + case BIO_C_SET_CONNECT_MODE: + data->connect_mode = (int)num; + break; + case BIO_C_GET_FD: + if (b->init) { + ip = (int *)ptr; + if (ip != NULL) + *ip = b->num; + ret = b->num; + } else + ret = -1; + break; + case BIO_CTRL_GET_CLOSE: + ret = b->shutdown; + break; + case BIO_CTRL_SET_CLOSE: + b->shutdown = (int)num; + break; + case BIO_CTRL_PENDING: + case BIO_CTRL_WPENDING: + ret = 0; + break; + case BIO_CTRL_FLUSH: + break; + case BIO_CTRL_DUP: + { + dbio = (BIO *)ptr; + if (data->param_hostname) + BIO_set_conn_hostname(dbio, data->param_hostname); + if (data->param_service) + BIO_set_conn_port(dbio, data->param_service); + BIO_set_conn_ip_family(dbio, data->connect_family); + BIO_set_conn_mode(dbio, data->connect_mode); + /* + * FIXME: the cast of the function seems unlikely to be a good + * idea + */ + (void)BIO_set_info_callback(dbio, data->info_callback); + } + break; + case BIO_CTRL_SET_CALLBACK: + ret = 0; /* use callback ctrl */ + break; + case BIO_CTRL_GET_CALLBACK: + { + BIO_info_cb **fptr; + + fptr = (BIO_info_cb **)ptr; + *fptr = data->info_callback; + } + break; + default: + ret = 0; + break; + } + return ret; +} + +static long conn_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) +{ + long ret = 1; + BIO_CONNECT *data; + + data = (BIO_CONNECT *)b->ptr; + + switch (cmd) { + case BIO_CTRL_SET_CALLBACK: + { + data->info_callback = fp; + } + break; + default: + ret = 0; + break; + } + return ret; +} + +static int conn_puts(BIO *bp, const char *str) +{ + int n, ret; + + n = strlen(str); + ret = conn_write(bp, str, n); + return ret; +} + +BIO *BIO_new_connect(const char *str) +{ + BIO *ret; + + ret = BIO_new(BIO_s_connect()); + if (ret == NULL) + return NULL; + if (BIO_set_conn_hostname(ret, str)) + return ret; + BIO_free(ret); + return NULL; +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_dgram.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_dgram.c new file mode 100644 index 000000000..d5fe5bb5a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_dgram.c @@ -0,0 +1,1925 @@ +/* + * Copyright 2005-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#include "bio_lcl.h" +#ifndef OPENSSL_NO_DGRAM + +# ifndef OPENSSL_NO_SCTP +# include +# include +# define OPENSSL_SCTP_DATA_CHUNK_TYPE 0x00 +# define OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE 0xc0 +# endif + +# if defined(OPENSSL_SYS_LINUX) && !defined(IP_MTU) +# define IP_MTU 14 /* linux is lame */ +# endif + +# if OPENSSL_USE_IPV6 && !defined(IPPROTO_IPV6) +# define IPPROTO_IPV6 41 /* windows is lame */ +# endif + +# if defined(__FreeBSD__) && defined(IN6_IS_ADDR_V4MAPPED) +/* Standard definition causes type-punning problems. */ +# undef IN6_IS_ADDR_V4MAPPED +# define s6_addr32 __u6_addr.__u6_addr32 +# define IN6_IS_ADDR_V4MAPPED(a) \ + (((a)->s6_addr32[0] == 0) && \ + ((a)->s6_addr32[1] == 0) && \ + ((a)->s6_addr32[2] == htonl(0x0000ffff))) +# endif + +static int dgram_write(BIO *h, const char *buf, int num); +static int dgram_read(BIO *h, char *buf, int size); +static int dgram_puts(BIO *h, const char *str); +static long dgram_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int dgram_new(BIO *h); +static int dgram_free(BIO *data); +static int dgram_clear(BIO *bio); + +# ifndef OPENSSL_NO_SCTP +static int dgram_sctp_write(BIO *h, const char *buf, int num); +static int dgram_sctp_read(BIO *h, char *buf, int size); +static int dgram_sctp_puts(BIO *h, const char *str); +static long dgram_sctp_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int dgram_sctp_new(BIO *h); +static int dgram_sctp_free(BIO *data); +# ifdef SCTP_AUTHENTICATION_EVENT +static void dgram_sctp_handle_auth_free_key_event(BIO *b, union sctp_notification + *snp); +# endif +# endif + +static int BIO_dgram_should_retry(int s); + +static void get_current_time(struct timeval *t); + +static const BIO_METHOD methods_dgramp = { + BIO_TYPE_DGRAM, + "datagram socket", + /* TODO: Convert to new style write function */ + bwrite_conv, + dgram_write, + /* TODO: Convert to new style read function */ + bread_conv, + dgram_read, + dgram_puts, + NULL, /* dgram_gets, */ + dgram_ctrl, + dgram_new, + dgram_free, + NULL, /* dgram_callback_ctrl */ +}; + +# ifndef OPENSSL_NO_SCTP +static const BIO_METHOD methods_dgramp_sctp = { + BIO_TYPE_DGRAM_SCTP, + "datagram sctp socket", + /* TODO: Convert to new style write function */ + bwrite_conv, + dgram_sctp_write, + /* TODO: Convert to new style write function */ + bread_conv, + dgram_sctp_read, + dgram_sctp_puts, + NULL, /* dgram_gets, */ + dgram_sctp_ctrl, + dgram_sctp_new, + dgram_sctp_free, + NULL, /* dgram_callback_ctrl */ +}; +# endif + +typedef struct bio_dgram_data_st { + BIO_ADDR peer; + unsigned int connected; + unsigned int _errno; + unsigned int mtu; + struct timeval next_timeout; + struct timeval socket_timeout; + unsigned int peekmode; +} bio_dgram_data; + +# ifndef OPENSSL_NO_SCTP +typedef struct bio_dgram_sctp_save_message_st { + BIO *bio; + char *data; + int length; +} bio_dgram_sctp_save_message; + +typedef struct bio_dgram_sctp_data_st { + BIO_ADDR peer; + unsigned int connected; + unsigned int _errno; + unsigned int mtu; + struct bio_dgram_sctp_sndinfo sndinfo; + struct bio_dgram_sctp_rcvinfo rcvinfo; + struct bio_dgram_sctp_prinfo prinfo; + void (*handle_notifications) (BIO *bio, void *context, void *buf); + void *notification_context; + int in_handshake; + int ccs_rcvd; + int ccs_sent; + int save_shutdown; + int peer_auth_tested; +} bio_dgram_sctp_data; +# endif + +const BIO_METHOD *BIO_s_datagram(void) +{ + return &methods_dgramp; +} + +BIO *BIO_new_dgram(int fd, int close_flag) +{ + BIO *ret; + + ret = BIO_new(BIO_s_datagram()); + if (ret == NULL) + return NULL; + BIO_set_fd(ret, fd, close_flag); + return ret; +} + +static int dgram_new(BIO *bi) +{ + bio_dgram_data *data = OPENSSL_zalloc(sizeof(*data)); + + if (data == NULL) + return 0; + bi->ptr = data; + return 1; +} + +static int dgram_free(BIO *a) +{ + bio_dgram_data *data; + + if (a == NULL) + return 0; + if (!dgram_clear(a)) + return 0; + + data = (bio_dgram_data *)a->ptr; + OPENSSL_free(data); + + return 1; +} + +static int dgram_clear(BIO *a) +{ + if (a == NULL) + return 0; + if (a->shutdown) { + if (a->init) { + BIO_closesocket(a->num); + } + a->init = 0; + a->flags = 0; + } + return 1; +} + +static void dgram_adjust_rcv_timeout(BIO *b) +{ +# if defined(SO_RCVTIMEO) + bio_dgram_data *data = (bio_dgram_data *)b->ptr; + union { + size_t s; + int i; + } sz = { + 0 + }; + + /* Is a timer active? */ + if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0) { + struct timeval timenow, timeleft; + + /* Read current socket timeout */ +# ifdef OPENSSL_SYS_WINDOWS + int timeout; + + sz.i = sizeof(timeout); + if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, + (void *)&timeout, &sz.i) < 0) { + perror("getsockopt"); + } else { + data->socket_timeout.tv_sec = timeout / 1000; + data->socket_timeout.tv_usec = (timeout % 1000) * 1000; + } +# else + sz.i = sizeof(data->socket_timeout); + if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, + &(data->socket_timeout), (void *)&sz) < 0) { + perror("getsockopt"); + } else if (sizeof(sz.s) != sizeof(sz.i) && sz.i == 0) + OPENSSL_assert(sz.s <= sizeof(data->socket_timeout)); +# endif + + /* Get current time */ + get_current_time(&timenow); + + /* Calculate time left until timer expires */ + memcpy(&timeleft, &(data->next_timeout), sizeof(struct timeval)); + if (timeleft.tv_usec < timenow.tv_usec) { + timeleft.tv_usec = 1000000 - timenow.tv_usec + timeleft.tv_usec; + timeleft.tv_sec--; + } else { + timeleft.tv_usec -= timenow.tv_usec; + } + if (timeleft.tv_sec < timenow.tv_sec) { + timeleft.tv_sec = 0; + timeleft.tv_usec = 1; + } else { + timeleft.tv_sec -= timenow.tv_sec; + } + + /* + * Adjust socket timeout if next handshake message timer will expire + * earlier. + */ + if ((data->socket_timeout.tv_sec == 0 + && data->socket_timeout.tv_usec == 0) + || (data->socket_timeout.tv_sec > timeleft.tv_sec) + || (data->socket_timeout.tv_sec == timeleft.tv_sec + && data->socket_timeout.tv_usec >= timeleft.tv_usec)) { +# ifdef OPENSSL_SYS_WINDOWS + timeout = timeleft.tv_sec * 1000 + timeleft.tv_usec / 1000; + if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, + (void *)&timeout, sizeof(timeout)) < 0) { + perror("setsockopt"); + } +# else + if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, &timeleft, + sizeof(struct timeval)) < 0) { + perror("setsockopt"); + } +# endif + } + } +# endif +} + +static void dgram_reset_rcv_timeout(BIO *b) +{ +# if defined(SO_RCVTIMEO) + bio_dgram_data *data = (bio_dgram_data *)b->ptr; + + /* Is a timer active? */ + if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0) { +# ifdef OPENSSL_SYS_WINDOWS + int timeout = data->socket_timeout.tv_sec * 1000 + + data->socket_timeout.tv_usec / 1000; + if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, + (void *)&timeout, sizeof(timeout)) < 0) { + perror("setsockopt"); + } +# else + if (setsockopt + (b->num, SOL_SOCKET, SO_RCVTIMEO, &(data->socket_timeout), + sizeof(struct timeval)) < 0) { + perror("setsockopt"); + } +# endif + } +# endif +} + +static int dgram_read(BIO *b, char *out, int outl) +{ + int ret = 0; + bio_dgram_data *data = (bio_dgram_data *)b->ptr; + int flags = 0; + + BIO_ADDR peer; + socklen_t len = sizeof(peer); + + if (out != NULL) { + clear_socket_error(); + memset(&peer, 0, sizeof(peer)); + dgram_adjust_rcv_timeout(b); + if (data->peekmode) + flags = MSG_PEEK; + ret = recvfrom(b->num, out, outl, flags, + BIO_ADDR_sockaddr_noconst(&peer), &len); + + if (!data->connected && ret >= 0) + BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, &peer); + + BIO_clear_retry_flags(b); + if (ret < 0) { + if (BIO_dgram_should_retry(ret)) { + BIO_set_retry_read(b); + data->_errno = get_last_socket_error(); + } + } + + dgram_reset_rcv_timeout(b); + } + return ret; +} + +static int dgram_write(BIO *b, const char *in, int inl) +{ + int ret; + bio_dgram_data *data = (bio_dgram_data *)b->ptr; + clear_socket_error(); + + if (data->connected) + ret = writesocket(b->num, in, inl); + else { + int peerlen = BIO_ADDR_sockaddr_size(&data->peer); + + ret = sendto(b->num, in, inl, 0, + BIO_ADDR_sockaddr(&data->peer), peerlen); + } + + BIO_clear_retry_flags(b); + if (ret <= 0) { + if (BIO_dgram_should_retry(ret)) { + BIO_set_retry_write(b); + data->_errno = get_last_socket_error(); + } + } + return ret; +} + +static long dgram_get_mtu_overhead(bio_dgram_data *data) +{ + long ret; + + switch (BIO_ADDR_family(&data->peer)) { + case AF_INET: + /* + * Assume this is UDP - 20 bytes for IP, 8 bytes for UDP + */ + ret = 28; + break; +# if OPENSSL_USE_IPV6 + case AF_INET6: + { +# ifdef IN6_IS_ADDR_V4MAPPED + struct in6_addr tmp_addr; + if (BIO_ADDR_rawaddress(&data->peer, &tmp_addr, NULL) + && IN6_IS_ADDR_V4MAPPED(&tmp_addr)) + /* + * Assume this is UDP - 20 bytes for IP, 8 bytes for UDP + */ + ret = 28; + else +# endif + /* + * Assume this is UDP - 40 bytes for IP, 8 bytes for UDP + */ + ret = 48; + } + break; +# endif + default: + /* We don't know. Go with the historical default */ + ret = 28; + break; + } + return ret; +} + +static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + long ret = 1; + int *ip; + bio_dgram_data *data = NULL; + int sockopt_val = 0; + int d_errno; +# if defined(OPENSSL_SYS_LINUX) && (defined(IP_MTU_DISCOVER) || defined(IP_MTU)) + socklen_t sockopt_len; /* assume that system supporting IP_MTU is + * modern enough to define socklen_t */ + socklen_t addr_len; + BIO_ADDR addr; +# endif + + data = (bio_dgram_data *)b->ptr; + + switch (cmd) { + case BIO_CTRL_RESET: + num = 0; + ret = 0; + break; + case BIO_CTRL_INFO: + ret = 0; + break; + case BIO_C_SET_FD: + dgram_clear(b); + b->num = *((int *)ptr); + b->shutdown = (int)num; + b->init = 1; + break; + case BIO_C_GET_FD: + if (b->init) { + ip = (int *)ptr; + if (ip != NULL) + *ip = b->num; + ret = b->num; + } else + ret = -1; + break; + case BIO_CTRL_GET_CLOSE: + ret = b->shutdown; + break; + case BIO_CTRL_SET_CLOSE: + b->shutdown = (int)num; + break; + case BIO_CTRL_PENDING: + case BIO_CTRL_WPENDING: + ret = 0; + break; + case BIO_CTRL_DUP: + case BIO_CTRL_FLUSH: + ret = 1; + break; + case BIO_CTRL_DGRAM_CONNECT: + BIO_ADDR_make(&data->peer, BIO_ADDR_sockaddr((BIO_ADDR *)ptr)); + break; + /* (Linux)kernel sets DF bit on outgoing IP packets */ + case BIO_CTRL_DGRAM_MTU_DISCOVER: +# if defined(OPENSSL_SYS_LINUX) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO) + addr_len = (socklen_t) sizeof(addr); + memset(&addr, 0, sizeof(addr)); + if (getsockname(b->num, &addr.sa, &addr_len) < 0) { + ret = 0; + break; + } + switch (addr.sa.sa_family) { + case AF_INET: + sockopt_val = IP_PMTUDISC_DO; + if ((ret = setsockopt(b->num, IPPROTO_IP, IP_MTU_DISCOVER, + &sockopt_val, sizeof(sockopt_val))) < 0) + perror("setsockopt"); + break; +# if OPENSSL_USE_IPV6 && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO) + case AF_INET6: + sockopt_val = IPV6_PMTUDISC_DO; + if ((ret = setsockopt(b->num, IPPROTO_IPV6, IPV6_MTU_DISCOVER, + &sockopt_val, sizeof(sockopt_val))) < 0) + perror("setsockopt"); + break; +# endif + default: + ret = -1; + break; + } +# else + ret = -1; +# endif + break; + case BIO_CTRL_DGRAM_QUERY_MTU: +# if defined(OPENSSL_SYS_LINUX) && defined(IP_MTU) + addr_len = (socklen_t) sizeof(addr); + memset(&addr, 0, sizeof(addr)); + if (getsockname(b->num, &addr.sa, &addr_len) < 0) { + ret = 0; + break; + } + sockopt_len = sizeof(sockopt_val); + switch (addr.sa.sa_family) { + case AF_INET: + if ((ret = + getsockopt(b->num, IPPROTO_IP, IP_MTU, (void *)&sockopt_val, + &sockopt_len)) < 0 || sockopt_val < 0) { + ret = 0; + } else { + /* + * we assume that the transport protocol is UDP and no IP + * options are used. + */ + data->mtu = sockopt_val - 8 - 20; + ret = data->mtu; + } + break; +# if OPENSSL_USE_IPV6 && defined(IPV6_MTU) + case AF_INET6: + if ((ret = + getsockopt(b->num, IPPROTO_IPV6, IPV6_MTU, + (void *)&sockopt_val, &sockopt_len)) < 0 + || sockopt_val < 0) { + ret = 0; + } else { + /* + * we assume that the transport protocol is UDP and no IPV6 + * options are used. + */ + data->mtu = sockopt_val - 8 - 40; + ret = data->mtu; + } + break; +# endif + default: + ret = 0; + break; + } +# else + ret = 0; +# endif + break; + case BIO_CTRL_DGRAM_GET_FALLBACK_MTU: + ret = -dgram_get_mtu_overhead(data); + switch (BIO_ADDR_family(&data->peer)) { + case AF_INET: + ret += 576; + break; +# if OPENSSL_USE_IPV6 + case AF_INET6: + { +# ifdef IN6_IS_ADDR_V4MAPPED + struct in6_addr tmp_addr; + if (BIO_ADDR_rawaddress(&data->peer, &tmp_addr, NULL) + && IN6_IS_ADDR_V4MAPPED(&tmp_addr)) + ret += 576; + else +# endif + ret += 1280; + } + break; +# endif + default: + ret += 576; + break; + } + break; + case BIO_CTRL_DGRAM_GET_MTU: + return data->mtu; + case BIO_CTRL_DGRAM_SET_MTU: + data->mtu = num; + ret = num; + break; + case BIO_CTRL_DGRAM_SET_CONNECTED: + if (ptr != NULL) { + data->connected = 1; + BIO_ADDR_make(&data->peer, BIO_ADDR_sockaddr((BIO_ADDR *)ptr)); + } else { + data->connected = 0; + memset(&data->peer, 0, sizeof(data->peer)); + } + break; + case BIO_CTRL_DGRAM_GET_PEER: + ret = BIO_ADDR_sockaddr_size(&data->peer); + /* FIXME: if num < ret, we will only return part of an address. + That should bee an error, no? */ + if (num == 0 || num > ret) + num = ret; + memcpy(ptr, &data->peer, (ret = num)); + break; + case BIO_CTRL_DGRAM_SET_PEER: + BIO_ADDR_make(&data->peer, BIO_ADDR_sockaddr((BIO_ADDR *)ptr)); + break; + case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT: + memcpy(&(data->next_timeout), ptr, sizeof(struct timeval)); + break; +# if defined(SO_RCVTIMEO) + case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT: +# ifdef OPENSSL_SYS_WINDOWS + { + struct timeval *tv = (struct timeval *)ptr; + int timeout = tv->tv_sec * 1000 + tv->tv_usec / 1000; + if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, + (void *)&timeout, sizeof(timeout)) < 0) { + perror("setsockopt"); + ret = -1; + } + } +# else + if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, ptr, + sizeof(struct timeval)) < 0) { + perror("setsockopt"); + ret = -1; + } +# endif + break; + case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT: + { + union { + size_t s; + int i; + } sz = { + 0 + }; +# ifdef OPENSSL_SYS_WINDOWS + int timeout; + struct timeval *tv = (struct timeval *)ptr; + + sz.i = sizeof(timeout); + if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, + (void *)&timeout, &sz.i) < 0) { + perror("getsockopt"); + ret = -1; + } else { + tv->tv_sec = timeout / 1000; + tv->tv_usec = (timeout % 1000) * 1000; + ret = sizeof(*tv); + } +# else + sz.i = sizeof(struct timeval); + if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, + ptr, (void *)&sz) < 0) { + perror("getsockopt"); + ret = -1; + } else if (sizeof(sz.s) != sizeof(sz.i) && sz.i == 0) { + OPENSSL_assert(sz.s <= sizeof(struct timeval)); + ret = (int)sz.s; + } else + ret = sz.i; +# endif + } + break; +# endif +# if defined(SO_SNDTIMEO) + case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT: +# ifdef OPENSSL_SYS_WINDOWS + { + struct timeval *tv = (struct timeval *)ptr; + int timeout = tv->tv_sec * 1000 + tv->tv_usec / 1000; + if (setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, + (void *)&timeout, sizeof(timeout)) < 0) { + perror("setsockopt"); + ret = -1; + } + } +# else + if (setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, ptr, + sizeof(struct timeval)) < 0) { + perror("setsockopt"); + ret = -1; + } +# endif + break; + case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT: + { + union { + size_t s; + int i; + } sz = { + 0 + }; +# ifdef OPENSSL_SYS_WINDOWS + int timeout; + struct timeval *tv = (struct timeval *)ptr; + + sz.i = sizeof(timeout); + if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, + (void *)&timeout, &sz.i) < 0) { + perror("getsockopt"); + ret = -1; + } else { + tv->tv_sec = timeout / 1000; + tv->tv_usec = (timeout % 1000) * 1000; + ret = sizeof(*tv); + } +# else + sz.i = sizeof(struct timeval); + if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, + ptr, (void *)&sz) < 0) { + perror("getsockopt"); + ret = -1; + } else if (sizeof(sz.s) != sizeof(sz.i) && sz.i == 0) { + OPENSSL_assert(sz.s <= sizeof(struct timeval)); + ret = (int)sz.s; + } else + ret = sz.i; +# endif + } + break; +# endif + case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP: + /* fall-through */ + case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP: +# ifdef OPENSSL_SYS_WINDOWS + d_errno = (data->_errno == WSAETIMEDOUT); +# else + d_errno = (data->_errno == EAGAIN); +# endif + if (d_errno) { + ret = 1; + data->_errno = 0; + } else + ret = 0; + break; +# ifdef EMSGSIZE + case BIO_CTRL_DGRAM_MTU_EXCEEDED: + if (data->_errno == EMSGSIZE) { + ret = 1; + data->_errno = 0; + } else + ret = 0; + break; +# endif + case BIO_CTRL_DGRAM_SET_DONT_FRAG: + sockopt_val = num ? 1 : 0; + + switch (data->peer.sa.sa_family) { + case AF_INET: +# if defined(IP_DONTFRAG) + if ((ret = setsockopt(b->num, IPPROTO_IP, IP_DONTFRAG, + &sockopt_val, sizeof(sockopt_val))) < 0) { + perror("setsockopt"); + ret = -1; + } +# elif defined(OPENSSL_SYS_LINUX) && defined(IP_MTU_DISCOVER) && defined (IP_PMTUDISC_PROBE) + if ((sockopt_val = num ? IP_PMTUDISC_PROBE : IP_PMTUDISC_DONT), + (ret = setsockopt(b->num, IPPROTO_IP, IP_MTU_DISCOVER, + &sockopt_val, sizeof(sockopt_val))) < 0) { + perror("setsockopt"); + ret = -1; + } +# elif defined(OPENSSL_SYS_WINDOWS) && defined(IP_DONTFRAGMENT) + if ((ret = setsockopt(b->num, IPPROTO_IP, IP_DONTFRAGMENT, + (const char *)&sockopt_val, + sizeof(sockopt_val))) < 0) { + perror("setsockopt"); + ret = -1; + } +# else + ret = -1; +# endif + break; +# if OPENSSL_USE_IPV6 + case AF_INET6: +# if defined(IPV6_DONTFRAG) + if ((ret = setsockopt(b->num, IPPROTO_IPV6, IPV6_DONTFRAG, + (const void *)&sockopt_val, + sizeof(sockopt_val))) < 0) { + perror("setsockopt"); + ret = -1; + } +# elif defined(OPENSSL_SYS_LINUX) && defined(IPV6_MTUDISCOVER) + if ((sockopt_val = num ? IP_PMTUDISC_PROBE : IP_PMTUDISC_DONT), + (ret = setsockopt(b->num, IPPROTO_IPV6, IPV6_MTU_DISCOVER, + &sockopt_val, sizeof(sockopt_val))) < 0) { + perror("setsockopt"); + ret = -1; + } +# else + ret = -1; +# endif + break; +# endif + default: + ret = -1; + break; + } + break; + case BIO_CTRL_DGRAM_GET_MTU_OVERHEAD: + ret = dgram_get_mtu_overhead(data); + break; + + /* + * BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE is used here for compatibility + * reasons. When BIO_CTRL_DGRAM_SET_PEEK_MODE was first defined its value + * was incorrectly clashing with BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE. The + * value has been updated to a non-clashing value. However to preserve + * binary compatiblity we now respond to both the old value and the new one + */ + case BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE: + case BIO_CTRL_DGRAM_SET_PEEK_MODE: + data->peekmode = (unsigned int)num; + break; + default: + ret = 0; + break; + } + return ret; +} + +static int dgram_puts(BIO *bp, const char *str) +{ + int n, ret; + + n = strlen(str); + ret = dgram_write(bp, str, n); + return ret; +} + +# ifndef OPENSSL_NO_SCTP +const BIO_METHOD *BIO_s_datagram_sctp(void) +{ + return &methods_dgramp_sctp; +} + +BIO *BIO_new_dgram_sctp(int fd, int close_flag) +{ + BIO *bio; + int ret, optval = 20000; + int auth_data = 0, auth_forward = 0; + unsigned char *p; + struct sctp_authchunk auth; + struct sctp_authchunks *authchunks; + socklen_t sockopt_len; +# ifdef SCTP_AUTHENTICATION_EVENT +# ifdef SCTP_EVENT + struct sctp_event event; +# else + struct sctp_event_subscribe event; +# endif +# endif + + bio = BIO_new(BIO_s_datagram_sctp()); + if (bio == NULL) + return NULL; + BIO_set_fd(bio, fd, close_flag); + + /* Activate SCTP-AUTH for DATA and FORWARD-TSN chunks */ + auth.sauth_chunk = OPENSSL_SCTP_DATA_CHUNK_TYPE; + ret = + setsockopt(fd, IPPROTO_SCTP, SCTP_AUTH_CHUNK, &auth, + sizeof(struct sctp_authchunk)); + if (ret < 0) { + BIO_vfree(bio); + BIOerr(BIO_F_BIO_NEW_DGRAM_SCTP, ERR_R_SYS_LIB); + ERR_add_error_data(1, "Ensure SCTP AUTH chunks are enabled in kernel"); + return NULL; + } + auth.sauth_chunk = OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE; + ret = + setsockopt(fd, IPPROTO_SCTP, SCTP_AUTH_CHUNK, &auth, + sizeof(struct sctp_authchunk)); + if (ret < 0) { + BIO_vfree(bio); + BIOerr(BIO_F_BIO_NEW_DGRAM_SCTP, ERR_R_SYS_LIB); + ERR_add_error_data(1, "Ensure SCTP AUTH chunks are enabled in kernel"); + return NULL; + } + + /* + * Test if activation was successful. When using accept(), SCTP-AUTH has + * to be activated for the listening socket already, otherwise the + * connected socket won't use it. Similarly with connect(): the socket + * prior to connection must be activated for SCTP-AUTH + */ + sockopt_len = (socklen_t) (sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t)); + authchunks = OPENSSL_zalloc(sockopt_len); + if (authchunks == NULL) { + BIO_vfree(bio); + return NULL; + } + ret = getsockopt(fd, IPPROTO_SCTP, SCTP_LOCAL_AUTH_CHUNKS, authchunks, + &sockopt_len); + if (ret < 0) { + OPENSSL_free(authchunks); + BIO_vfree(bio); + return NULL; + } + + for (p = (unsigned char *)authchunks->gauth_chunks; + p < (unsigned char *)authchunks + sockopt_len; + p += sizeof(uint8_t)) { + if (*p == OPENSSL_SCTP_DATA_CHUNK_TYPE) + auth_data = 1; + if (*p == OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE) + auth_forward = 1; + } + + OPENSSL_free(authchunks); + + if (!auth_data || !auth_forward) { + BIO_vfree(bio); + BIOerr(BIO_F_BIO_NEW_DGRAM_SCTP, ERR_R_SYS_LIB); + ERR_add_error_data(1, + "Ensure SCTP AUTH chunks are enabled on the " + "underlying socket"); + return NULL; + } + +# ifdef SCTP_AUTHENTICATION_EVENT +# ifdef SCTP_EVENT + memset(&event, 0, sizeof(event)); + event.se_assoc_id = 0; + event.se_type = SCTP_AUTHENTICATION_EVENT; + event.se_on = 1; + ret = + setsockopt(fd, IPPROTO_SCTP, SCTP_EVENT, &event, + sizeof(struct sctp_event)); + if (ret < 0) { + BIO_vfree(bio); + return NULL; + } +# else + sockopt_len = (socklen_t) sizeof(struct sctp_event_subscribe); + ret = getsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, &sockopt_len); + if (ret < 0) { + BIO_vfree(bio); + return NULL; + } + + event.sctp_authentication_event = 1; + + ret = + setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, + sizeof(struct sctp_event_subscribe)); + if (ret < 0) { + BIO_vfree(bio); + return NULL; + } +# endif +# endif + + /* + * Disable partial delivery by setting the min size larger than the max + * record size of 2^14 + 2048 + 13 + */ + ret = + setsockopt(fd, IPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT, &optval, + sizeof(optval)); + if (ret < 0) { + BIO_vfree(bio); + return NULL; + } + + return bio; +} + +int BIO_dgram_is_sctp(BIO *bio) +{ + return (BIO_method_type(bio) == BIO_TYPE_DGRAM_SCTP); +} + +static int dgram_sctp_new(BIO *bi) +{ + bio_dgram_sctp_data *data = NULL; + + bi->init = 0; + bi->num = 0; + if ((data = OPENSSL_zalloc(sizeof(*data))) == NULL) { + BIOerr(BIO_F_DGRAM_SCTP_NEW, ERR_R_MALLOC_FAILURE); + return 0; + } +# ifdef SCTP_PR_SCTP_NONE + data->prinfo.pr_policy = SCTP_PR_SCTP_NONE; +# endif + bi->ptr = data; + + bi->flags = 0; + return 1; +} + +static int dgram_sctp_free(BIO *a) +{ + bio_dgram_sctp_data *data; + + if (a == NULL) + return 0; + if (!dgram_clear(a)) + return 0; + + data = (bio_dgram_sctp_data *) a->ptr; + if (data != NULL) + OPENSSL_free(data); + + return 1; +} + +# ifdef SCTP_AUTHENTICATION_EVENT +void dgram_sctp_handle_auth_free_key_event(BIO *b, + union sctp_notification *snp) +{ + int ret; + struct sctp_authkey_event *authkeyevent = &snp->sn_auth_event; + + if (authkeyevent->auth_indication == SCTP_AUTH_FREE_KEY) { + struct sctp_authkeyid authkeyid; + + /* delete key */ + authkeyid.scact_keynumber = authkeyevent->auth_keynumber; + ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DELETE_KEY, + &authkeyid, sizeof(struct sctp_authkeyid)); + } +} +# endif + +static int dgram_sctp_read(BIO *b, char *out, int outl) +{ + int ret = 0, n = 0, i, optval; + socklen_t optlen; + bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr; + union sctp_notification *snp; + struct msghdr msg; + struct iovec iov; + struct cmsghdr *cmsg; + char cmsgbuf[512]; + + if (out != NULL) { + clear_socket_error(); + + do { + memset(&data->rcvinfo, 0, sizeof(data->rcvinfo)); + iov.iov_base = out; + iov.iov_len = outl; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = cmsgbuf; + msg.msg_controllen = 512; + msg.msg_flags = 0; + n = recvmsg(b->num, &msg, 0); + + if (n <= 0) { + if (n < 0) + ret = n; + break; + } + + if (msg.msg_controllen > 0) { + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; + cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_level != IPPROTO_SCTP) + continue; +# ifdef SCTP_RCVINFO + if (cmsg->cmsg_type == SCTP_RCVINFO) { + struct sctp_rcvinfo *rcvinfo; + + rcvinfo = (struct sctp_rcvinfo *)CMSG_DATA(cmsg); + data->rcvinfo.rcv_sid = rcvinfo->rcv_sid; + data->rcvinfo.rcv_ssn = rcvinfo->rcv_ssn; + data->rcvinfo.rcv_flags = rcvinfo->rcv_flags; + data->rcvinfo.rcv_ppid = rcvinfo->rcv_ppid; + data->rcvinfo.rcv_tsn = rcvinfo->rcv_tsn; + data->rcvinfo.rcv_cumtsn = rcvinfo->rcv_cumtsn; + data->rcvinfo.rcv_context = rcvinfo->rcv_context; + } +# endif +# ifdef SCTP_SNDRCV + if (cmsg->cmsg_type == SCTP_SNDRCV) { + struct sctp_sndrcvinfo *sndrcvinfo; + + sndrcvinfo = + (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); + data->rcvinfo.rcv_sid = sndrcvinfo->sinfo_stream; + data->rcvinfo.rcv_ssn = sndrcvinfo->sinfo_ssn; + data->rcvinfo.rcv_flags = sndrcvinfo->sinfo_flags; + data->rcvinfo.rcv_ppid = sndrcvinfo->sinfo_ppid; + data->rcvinfo.rcv_tsn = sndrcvinfo->sinfo_tsn; + data->rcvinfo.rcv_cumtsn = sndrcvinfo->sinfo_cumtsn; + data->rcvinfo.rcv_context = sndrcvinfo->sinfo_context; + } +# endif + } + } + + if (msg.msg_flags & MSG_NOTIFICATION) { + snp = (union sctp_notification *)out; + if (snp->sn_header.sn_type == SCTP_SENDER_DRY_EVENT) { +# ifdef SCTP_EVENT + struct sctp_event event; +# else + struct sctp_event_subscribe event; + socklen_t eventsize; +# endif + + /* disable sender dry event */ +# ifdef SCTP_EVENT + memset(&event, 0, sizeof(event)); + event.se_assoc_id = 0; + event.se_type = SCTP_SENDER_DRY_EVENT; + event.se_on = 0; + i = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, + sizeof(struct sctp_event)); + if (i < 0) { + ret = i; + break; + } +# else + eventsize = sizeof(struct sctp_event_subscribe); + i = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, + &eventsize); + if (i < 0) { + ret = i; + break; + } + + event.sctp_sender_dry_event = 0; + + i = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, + sizeof(struct sctp_event_subscribe)); + if (i < 0) { + ret = i; + break; + } +# endif + } +# ifdef SCTP_AUTHENTICATION_EVENT + if (snp->sn_header.sn_type == SCTP_AUTHENTICATION_EVENT) + dgram_sctp_handle_auth_free_key_event(b, snp); +# endif + + if (data->handle_notifications != NULL) + data->handle_notifications(b, data->notification_context, + (void *)out); + + memset(out, 0, outl); + } else + ret += n; + } + while ((msg.msg_flags & MSG_NOTIFICATION) && (msg.msg_flags & MSG_EOR) + && (ret < outl)); + + if (ret > 0 && !(msg.msg_flags & MSG_EOR)) { + /* Partial message read, this should never happen! */ + + /* + * The buffer was too small, this means the peer sent a message + * that was larger than allowed. + */ + if (ret == outl) + return -1; + + /* + * Test if socket buffer can handle max record size (2^14 + 2048 + * + 13) + */ + optlen = (socklen_t) sizeof(int); + ret = getsockopt(b->num, SOL_SOCKET, SO_RCVBUF, &optval, &optlen); + if (ret >= 0) + OPENSSL_assert(optval >= 18445); + + /* + * Test if SCTP doesn't partially deliver below max record size + * (2^14 + 2048 + 13) + */ + optlen = (socklen_t) sizeof(int); + ret = + getsockopt(b->num, IPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT, + &optval, &optlen); + if (ret >= 0) + OPENSSL_assert(optval >= 18445); + + /* + * Partially delivered notification??? Probably a bug.... + */ + OPENSSL_assert(!(msg.msg_flags & MSG_NOTIFICATION)); + + /* + * Everything seems ok till now, so it's most likely a message + * dropped by PR-SCTP. + */ + memset(out, 0, outl); + BIO_set_retry_read(b); + return -1; + } + + BIO_clear_retry_flags(b); + if (ret < 0) { + if (BIO_dgram_should_retry(ret)) { + BIO_set_retry_read(b); + data->_errno = get_last_socket_error(); + } + } + + /* Test if peer uses SCTP-AUTH before continuing */ + if (!data->peer_auth_tested) { + int ii, auth_data = 0, auth_forward = 0; + unsigned char *p; + struct sctp_authchunks *authchunks; + + optlen = + (socklen_t) (sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t)); + authchunks = OPENSSL_malloc(optlen); + if (authchunks == NULL) { + BIOerr(BIO_F_DGRAM_SCTP_READ, ERR_R_MALLOC_FAILURE); + return -1; + } + memset(authchunks, 0, optlen); + ii = getsockopt(b->num, IPPROTO_SCTP, SCTP_PEER_AUTH_CHUNKS, + authchunks, &optlen); + + if (ii >= 0) + for (p = (unsigned char *)authchunks->gauth_chunks; + p < (unsigned char *)authchunks + optlen; + p += sizeof(uint8_t)) { + if (*p == OPENSSL_SCTP_DATA_CHUNK_TYPE) + auth_data = 1; + if (*p == OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE) + auth_forward = 1; + } + + OPENSSL_free(authchunks); + + if (!auth_data || !auth_forward) { + BIOerr(BIO_F_DGRAM_SCTP_READ, BIO_R_CONNECT_ERROR); + return -1; + } + + data->peer_auth_tested = 1; + } + } + return ret; +} + +/* + * dgram_sctp_write - send message on SCTP socket + * @b: BIO to write to + * @in: data to send + * @inl: amount of bytes in @in to send + * + * Returns -1 on error or the sent amount of bytes on success + */ +static int dgram_sctp_write(BIO *b, const char *in, int inl) +{ + int ret; + bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr; + struct bio_dgram_sctp_sndinfo *sinfo = &(data->sndinfo); + struct bio_dgram_sctp_prinfo *pinfo = &(data->prinfo); + struct bio_dgram_sctp_sndinfo handshake_sinfo; + struct iovec iov[1]; + struct msghdr msg; + struct cmsghdr *cmsg; +# if defined(SCTP_SNDINFO) && defined(SCTP_PRINFO) + char cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndinfo)) + + CMSG_SPACE(sizeof(struct sctp_prinfo))]; + struct sctp_sndinfo *sndinfo; + struct sctp_prinfo *prinfo; +# else + char cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))]; + struct sctp_sndrcvinfo *sndrcvinfo; +# endif + + clear_socket_error(); + + /* + * If we're send anything else than application data, disable all user + * parameters and flags. + */ + if (in[0] != 23) { + memset(&handshake_sinfo, 0, sizeof(handshake_sinfo)); +# ifdef SCTP_SACK_IMMEDIATELY + handshake_sinfo.snd_flags = SCTP_SACK_IMMEDIATELY; +# endif + sinfo = &handshake_sinfo; + } + + /* We can only send a shutdown alert if the socket is dry */ + if (data->save_shutdown) { + ret = BIO_dgram_sctp_wait_for_dry(b); + if (ret < 0) + return -1; + if (ret == 0) { + BIO_clear_retry_flags(b); + BIO_set_retry_write(b); + return -1; + } + } + + iov[0].iov_base = (char *)in; + iov[0].iov_len = inl; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_control = (caddr_t) cmsgbuf; + msg.msg_controllen = 0; + msg.msg_flags = 0; +# if defined(SCTP_SNDINFO) && defined(SCTP_PRINFO) + cmsg = (struct cmsghdr *)cmsgbuf; + cmsg->cmsg_level = IPPROTO_SCTP; + cmsg->cmsg_type = SCTP_SNDINFO; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndinfo)); + sndinfo = (struct sctp_sndinfo *)CMSG_DATA(cmsg); + memset(sndinfo, 0, sizeof(*sndinfo)); + sndinfo->snd_sid = sinfo->snd_sid; + sndinfo->snd_flags = sinfo->snd_flags; + sndinfo->snd_ppid = sinfo->snd_ppid; + sndinfo->snd_context = sinfo->snd_context; + msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndinfo)); + + cmsg = + (struct cmsghdr *)&cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndinfo))]; + cmsg->cmsg_level = IPPROTO_SCTP; + cmsg->cmsg_type = SCTP_PRINFO; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_prinfo)); + prinfo = (struct sctp_prinfo *)CMSG_DATA(cmsg); + memset(prinfo, 0, sizeof(*prinfo)); + prinfo->pr_policy = pinfo->pr_policy; + prinfo->pr_value = pinfo->pr_value; + msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_prinfo)); +# else + cmsg = (struct cmsghdr *)cmsgbuf; + cmsg->cmsg_level = IPPROTO_SCTP; + cmsg->cmsg_type = SCTP_SNDRCV; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo)); + sndrcvinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); + memset(sndrcvinfo, 0, sizeof(*sndrcvinfo)); + sndrcvinfo->sinfo_stream = sinfo->snd_sid; + sndrcvinfo->sinfo_flags = sinfo->snd_flags; +# ifdef __FreeBSD__ + sndrcvinfo->sinfo_flags |= pinfo->pr_policy; +# endif + sndrcvinfo->sinfo_ppid = sinfo->snd_ppid; + sndrcvinfo->sinfo_context = sinfo->snd_context; + sndrcvinfo->sinfo_timetolive = pinfo->pr_value; + msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndrcvinfo)); +# endif + + ret = sendmsg(b->num, &msg, 0); + + BIO_clear_retry_flags(b); + if (ret <= 0) { + if (BIO_dgram_should_retry(ret)) { + BIO_set_retry_write(b); + data->_errno = get_last_socket_error(); + } + } + return ret; +} + +static long dgram_sctp_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + long ret = 1; + bio_dgram_sctp_data *data = NULL; + socklen_t sockopt_len = 0; + struct sctp_authkeyid authkeyid; + struct sctp_authkey *authkey = NULL; + + data = (bio_dgram_sctp_data *) b->ptr; + + switch (cmd) { + case BIO_CTRL_DGRAM_QUERY_MTU: + /* + * Set to maximum (2^14) and ignore user input to enable transport + * protocol fragmentation. Returns always 2^14. + */ + data->mtu = 16384; + ret = data->mtu; + break; + case BIO_CTRL_DGRAM_SET_MTU: + /* + * Set to maximum (2^14) and ignore input to enable transport + * protocol fragmentation. Returns always 2^14. + */ + data->mtu = 16384; + ret = data->mtu; + break; + case BIO_CTRL_DGRAM_SET_CONNECTED: + case BIO_CTRL_DGRAM_CONNECT: + /* Returns always -1. */ + ret = -1; + break; + case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT: + /* + * SCTP doesn't need the DTLS timer Returns always 1. + */ + break; + case BIO_CTRL_DGRAM_GET_MTU_OVERHEAD: + /* + * We allow transport protocol fragmentation so this is irrelevant + */ + ret = 0; + break; + case BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE: + if (num > 0) + data->in_handshake = 1; + else + data->in_handshake = 0; + + ret = + setsockopt(b->num, IPPROTO_SCTP, SCTP_NODELAY, + &data->in_handshake, sizeof(int)); + break; + case BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY: + /* + * New shared key for SCTP AUTH. Returns 0 on success, -1 otherwise. + */ + + /* Get active key */ + sockopt_len = sizeof(struct sctp_authkeyid); + ret = + getsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, &authkeyid, + &sockopt_len); + if (ret < 0) + break; + + /* Add new key */ + sockopt_len = sizeof(struct sctp_authkey) + 64 * sizeof(uint8_t); + authkey = OPENSSL_malloc(sockopt_len); + if (authkey == NULL) { + ret = -1; + break; + } + memset(authkey, 0, sockopt_len); + authkey->sca_keynumber = authkeyid.scact_keynumber + 1; +# ifndef __FreeBSD__ + /* + * This field is missing in FreeBSD 8.2 and earlier, and FreeBSD 8.3 + * and higher work without it. + */ + authkey->sca_keylength = 64; +# endif + memcpy(&authkey->sca_key[0], ptr, 64 * sizeof(uint8_t)); + + ret = + setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_KEY, authkey, + sockopt_len); + OPENSSL_free(authkey); + authkey = NULL; + if (ret < 0) + break; + + /* Reset active key */ + ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, + &authkeyid, sizeof(struct sctp_authkeyid)); + if (ret < 0) + break; + + break; + case BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY: + /* Returns 0 on success, -1 otherwise. */ + + /* Get active key */ + sockopt_len = sizeof(struct sctp_authkeyid); + ret = + getsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, &authkeyid, + &sockopt_len); + if (ret < 0) + break; + + /* Set active key */ + authkeyid.scact_keynumber = authkeyid.scact_keynumber + 1; + ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, + &authkeyid, sizeof(struct sctp_authkeyid)); + if (ret < 0) + break; + + /* + * CCS has been sent, so remember that and fall through to check if + * we need to deactivate an old key + */ + data->ccs_sent = 1; + /* fall-through */ + + case BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD: + /* Returns 0 on success, -1 otherwise. */ + + /* + * Has this command really been called or is this just a + * fall-through? + */ + if (cmd == BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD) + data->ccs_rcvd = 1; + + /* + * CSS has been both, received and sent, so deactivate an old key + */ + if (data->ccs_rcvd == 1 && data->ccs_sent == 1) { + /* Get active key */ + sockopt_len = sizeof(struct sctp_authkeyid); + ret = + getsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, + &authkeyid, &sockopt_len); + if (ret < 0) + break; + + /* + * Deactivate key or delete second last key if + * SCTP_AUTHENTICATION_EVENT is not available. + */ + authkeyid.scact_keynumber = authkeyid.scact_keynumber - 1; +# ifdef SCTP_AUTH_DEACTIVATE_KEY + sockopt_len = sizeof(struct sctp_authkeyid); + ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DEACTIVATE_KEY, + &authkeyid, sockopt_len); + if (ret < 0) + break; +# endif +# ifndef SCTP_AUTHENTICATION_EVENT + if (authkeyid.scact_keynumber > 0) { + authkeyid.scact_keynumber = authkeyid.scact_keynumber - 1; + ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DELETE_KEY, + &authkeyid, sizeof(struct sctp_authkeyid)); + if (ret < 0) + break; + } +# endif + + data->ccs_rcvd = 0; + data->ccs_sent = 0; + } + break; + case BIO_CTRL_DGRAM_SCTP_GET_SNDINFO: + /* Returns the size of the copied struct. */ + if (num > (long)sizeof(struct bio_dgram_sctp_sndinfo)) + num = sizeof(struct bio_dgram_sctp_sndinfo); + + memcpy(ptr, &(data->sndinfo), num); + ret = num; + break; + case BIO_CTRL_DGRAM_SCTP_SET_SNDINFO: + /* Returns the size of the copied struct. */ + if (num > (long)sizeof(struct bio_dgram_sctp_sndinfo)) + num = sizeof(struct bio_dgram_sctp_sndinfo); + + memcpy(&(data->sndinfo), ptr, num); + break; + case BIO_CTRL_DGRAM_SCTP_GET_RCVINFO: + /* Returns the size of the copied struct. */ + if (num > (long)sizeof(struct bio_dgram_sctp_rcvinfo)) + num = sizeof(struct bio_dgram_sctp_rcvinfo); + + memcpy(ptr, &data->rcvinfo, num); + + ret = num; + break; + case BIO_CTRL_DGRAM_SCTP_SET_RCVINFO: + /* Returns the size of the copied struct. */ + if (num > (long)sizeof(struct bio_dgram_sctp_rcvinfo)) + num = sizeof(struct bio_dgram_sctp_rcvinfo); + + memcpy(&(data->rcvinfo), ptr, num); + break; + case BIO_CTRL_DGRAM_SCTP_GET_PRINFO: + /* Returns the size of the copied struct. */ + if (num > (long)sizeof(struct bio_dgram_sctp_prinfo)) + num = sizeof(struct bio_dgram_sctp_prinfo); + + memcpy(ptr, &(data->prinfo), num); + ret = num; + break; + case BIO_CTRL_DGRAM_SCTP_SET_PRINFO: + /* Returns the size of the copied struct. */ + if (num > (long)sizeof(struct bio_dgram_sctp_prinfo)) + num = sizeof(struct bio_dgram_sctp_prinfo); + + memcpy(&(data->prinfo), ptr, num); + break; + case BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN: + /* Returns always 1. */ + if (num > 0) + data->save_shutdown = 1; + else + data->save_shutdown = 0; + break; + + default: + /* + * Pass to default ctrl function to process SCTP unspecific commands + */ + ret = dgram_ctrl(b, cmd, num, ptr); + break; + } + return ret; +} + +int BIO_dgram_sctp_notification_cb(BIO *b, + void (*handle_notifications) (BIO *bio, + void + *context, + void *buf), + void *context) +{ + bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr; + + if (handle_notifications != NULL) { + data->handle_notifications = handle_notifications; + data->notification_context = context; + } else + return -1; + + return 0; +} + +/* + * BIO_dgram_sctp_wait_for_dry - Wait for SCTP SENDER_DRY event + * @b: The BIO to check for the dry event + * + * Wait until the peer confirms all packets have been received, and so that + * our kernel doesn't have anything to send anymore. This is only received by + * the peer's kernel, not the application. + * + * Returns: + * -1 on error + * 0 when not dry yet + * 1 when dry + */ +int BIO_dgram_sctp_wait_for_dry(BIO *b) +{ + int is_dry = 0; + int sockflags = 0; + int n, ret; + union sctp_notification snp; + struct msghdr msg; + struct iovec iov; +# ifdef SCTP_EVENT + struct sctp_event event; +# else + struct sctp_event_subscribe event; + socklen_t eventsize; +# endif + bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr; + + /* set sender dry event */ +# ifdef SCTP_EVENT + memset(&event, 0, sizeof(event)); + event.se_assoc_id = 0; + event.se_type = SCTP_SENDER_DRY_EVENT; + event.se_on = 1; + ret = + setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, + sizeof(struct sctp_event)); +# else + eventsize = sizeof(struct sctp_event_subscribe); + ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize); + if (ret < 0) + return -1; + + event.sctp_sender_dry_event = 1; + + ret = + setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, + sizeof(struct sctp_event_subscribe)); +# endif + if (ret < 0) + return -1; + + /* peek for notification */ + memset(&snp, 0, sizeof(snp)); + iov.iov_base = (char *)&snp; + iov.iov_len = sizeof(union sctp_notification); + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + + n = recvmsg(b->num, &msg, MSG_PEEK); + if (n <= 0) { + if ((n < 0) && (get_last_socket_error() != EAGAIN) + && (get_last_socket_error() != EWOULDBLOCK)) + return -1; + else + return 0; + } + + /* if we find a notification, process it and try again if necessary */ + while (msg.msg_flags & MSG_NOTIFICATION) { + memset(&snp, 0, sizeof(snp)); + iov.iov_base = (char *)&snp; + iov.iov_len = sizeof(union sctp_notification); + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + + n = recvmsg(b->num, &msg, 0); + if (n <= 0) { + if ((n < 0) && (get_last_socket_error() != EAGAIN) + && (get_last_socket_error() != EWOULDBLOCK)) + return -1; + else + return is_dry; + } + + if (snp.sn_header.sn_type == SCTP_SENDER_DRY_EVENT) { + is_dry = 1; + + /* disable sender dry event */ +# ifdef SCTP_EVENT + memset(&event, 0, sizeof(event)); + event.se_assoc_id = 0; + event.se_type = SCTP_SENDER_DRY_EVENT; + event.se_on = 0; + ret = + setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, + sizeof(struct sctp_event)); +# else + eventsize = (socklen_t) sizeof(struct sctp_event_subscribe); + ret = + getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, + &eventsize); + if (ret < 0) + return -1; + + event.sctp_sender_dry_event = 0; + + ret = + setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, + sizeof(struct sctp_event_subscribe)); +# endif + if (ret < 0) + return -1; + } +# ifdef SCTP_AUTHENTICATION_EVENT + if (snp.sn_header.sn_type == SCTP_AUTHENTICATION_EVENT) + dgram_sctp_handle_auth_free_key_event(b, &snp); +# endif + + if (data->handle_notifications != NULL) + data->handle_notifications(b, data->notification_context, + (void *)&snp); + + /* found notification, peek again */ + memset(&snp, 0, sizeof(snp)); + iov.iov_base = (char *)&snp; + iov.iov_len = sizeof(union sctp_notification); + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + + /* if we have seen the dry already, don't wait */ + if (is_dry) { + sockflags = fcntl(b->num, F_GETFL, 0); + fcntl(b->num, F_SETFL, O_NONBLOCK); + } + + n = recvmsg(b->num, &msg, MSG_PEEK); + + if (is_dry) { + fcntl(b->num, F_SETFL, sockflags); + } + + if (n <= 0) { + if ((n < 0) && (get_last_socket_error() != EAGAIN) + && (get_last_socket_error() != EWOULDBLOCK)) + return -1; + else + return is_dry; + } + } + + /* read anything else */ + return is_dry; +} + +int BIO_dgram_sctp_msg_waiting(BIO *b) +{ + int n, sockflags; + union sctp_notification snp; + struct msghdr msg; + struct iovec iov; + bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr; + + /* Check if there are any messages waiting to be read */ + do { + memset(&snp, 0, sizeof(snp)); + iov.iov_base = (char *)&snp; + iov.iov_len = sizeof(union sctp_notification); + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + + sockflags = fcntl(b->num, F_GETFL, 0); + fcntl(b->num, F_SETFL, O_NONBLOCK); + n = recvmsg(b->num, &msg, MSG_PEEK); + fcntl(b->num, F_SETFL, sockflags); + + /* if notification, process and try again */ + if (n > 0 && (msg.msg_flags & MSG_NOTIFICATION)) { +# ifdef SCTP_AUTHENTICATION_EVENT + if (snp.sn_header.sn_type == SCTP_AUTHENTICATION_EVENT) + dgram_sctp_handle_auth_free_key_event(b, &snp); +# endif + + memset(&snp, 0, sizeof(snp)); + iov.iov_base = (char *)&snp; + iov.iov_len = sizeof(union sctp_notification); + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + n = recvmsg(b->num, &msg, 0); + + if (data->handle_notifications != NULL) + data->handle_notifications(b, data->notification_context, + (void *)&snp); + } + + } while (n > 0 && (msg.msg_flags & MSG_NOTIFICATION)); + + /* Return 1 if there is a message to be read, return 0 otherwise. */ + if (n > 0) + return 1; + else + return 0; +} + +static int dgram_sctp_puts(BIO *bp, const char *str) +{ + int n, ret; + + n = strlen(str); + ret = dgram_sctp_write(bp, str, n); + return ret; +} +# endif + +static int BIO_dgram_should_retry(int i) +{ + int err; + + if ((i == 0) || (i == -1)) { + err = get_last_socket_error(); + +# if defined(OPENSSL_SYS_WINDOWS) + /* + * If the socket return value (i) is -1 and err is unexpectedly 0 at + * this point, the error code was overwritten by another system call + * before this error handling is called. + */ +# endif + + return BIO_dgram_non_fatal_error(err); + } + return 0; +} + +int BIO_dgram_non_fatal_error(int err) +{ + switch (err) { +# if defined(OPENSSL_SYS_WINDOWS) +# if defined(WSAEWOULDBLOCK) + case WSAEWOULDBLOCK: +# endif +# endif + +# ifdef EWOULDBLOCK +# ifdef WSAEWOULDBLOCK +# if WSAEWOULDBLOCK != EWOULDBLOCK + case EWOULDBLOCK: +# endif +# else + case EWOULDBLOCK: +# endif +# endif + +# ifdef EINTR + case EINTR: +# endif + +# ifdef EAGAIN +# if EWOULDBLOCK != EAGAIN + case EAGAIN: +# endif +# endif + +# ifdef EPROTO + case EPROTO: +# endif + +# ifdef EINPROGRESS + case EINPROGRESS: +# endif + +# ifdef EALREADY + case EALREADY: +# endif + + return 1; + default: + break; + } + return 0; +} + +static void get_current_time(struct timeval *t) +{ +# if defined(_WIN32) + SYSTEMTIME st; + union { + unsigned __int64 ul; + FILETIME ft; + } now; + + GetSystemTime(&st); + SystemTimeToFileTime(&st, &now.ft); +# ifdef __MINGW32__ + now.ul -= 116444736000000000ULL; +# else + now.ul -= 116444736000000000UI64; /* re-bias to 1/1/1970 */ +# endif + t->tv_sec = (long)(now.ul / 10000000); + t->tv_usec = ((int)(now.ul % 10000000)) / 10; +# else + gettimeofday(t, NULL); +# endif +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_fd.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_fd.c new file mode 100644 index 000000000..5bc539c90 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_fd.c @@ -0,0 +1,280 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#include "bio_lcl.h" + +#if defined(OPENSSL_NO_POSIX_IO) +/* + * Dummy placeholder for BIO_s_fd... + */ +BIO *BIO_new_fd(int fd, int close_flag) +{ + return NULL; +} + +int BIO_fd_non_fatal_error(int err) +{ + return 0; +} + +int BIO_fd_should_retry(int i) +{ + return 0; +} + +const BIO_METHOD *BIO_s_fd(void) +{ + return NULL; +} +#else +/* + * As for unconditional usage of "UPLINK" interface in this module. + * Trouble is that unlike Unix file descriptors [which are indexes + * in kernel-side per-process table], corresponding descriptors on + * platforms which require "UPLINK" interface seem to be indexes + * in a user-land, non-global table. Well, in fact they are indexes + * in stdio _iob[], and recall that _iob[] was the very reason why + * "UPLINK" interface was introduced in first place. But one way on + * another. Neither libcrypto or libssl use this BIO meaning that + * file descriptors can only be provided by application. Therefore + * "UPLINK" calls are due... + */ +static int fd_write(BIO *h, const char *buf, int num); +static int fd_read(BIO *h, char *buf, int size); +static int fd_puts(BIO *h, const char *str); +static int fd_gets(BIO *h, char *buf, int size); +static long fd_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int fd_new(BIO *h); +static int fd_free(BIO *data); +int BIO_fd_should_retry(int s); + +static const BIO_METHOD methods_fdp = { + BIO_TYPE_FD, + "file descriptor", + /* TODO: Convert to new style write function */ + bwrite_conv, + fd_write, + /* TODO: Convert to new style read function */ + bread_conv, + fd_read, + fd_puts, + fd_gets, + fd_ctrl, + fd_new, + fd_free, + NULL, /* fd_callback_ctrl */ +}; + +const BIO_METHOD *BIO_s_fd(void) +{ + return &methods_fdp; +} + +BIO *BIO_new_fd(int fd, int close_flag) +{ + BIO *ret; + ret = BIO_new(BIO_s_fd()); + if (ret == NULL) + return NULL; + BIO_set_fd(ret, fd, close_flag); + return ret; +} + +static int fd_new(BIO *bi) +{ + bi->init = 0; + bi->num = -1; + bi->ptr = NULL; + bi->flags = BIO_FLAGS_UPLINK; /* essentially redundant */ + return 1; +} + +static int fd_free(BIO *a) +{ + if (a == NULL) + return 0; + if (a->shutdown) { + if (a->init) { + UP_close(a->num); + } + a->init = 0; + a->flags = BIO_FLAGS_UPLINK; + } + return 1; +} + +static int fd_read(BIO *b, char *out, int outl) +{ + int ret = 0; + + if (out != NULL) { + clear_sys_error(); + ret = UP_read(b->num, out, outl); + BIO_clear_retry_flags(b); + if (ret <= 0) { + if (BIO_fd_should_retry(ret)) + BIO_set_retry_read(b); + } + } + return ret; +} + +static int fd_write(BIO *b, const char *in, int inl) +{ + int ret; + clear_sys_error(); + ret = UP_write(b->num, in, inl); + BIO_clear_retry_flags(b); + if (ret <= 0) { + if (BIO_fd_should_retry(ret)) + BIO_set_retry_write(b); + } + return ret; +} + +static long fd_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + long ret = 1; + int *ip; + + switch (cmd) { + case BIO_CTRL_RESET: + num = 0; + /* fall thru */ + case BIO_C_FILE_SEEK: + ret = (long)UP_lseek(b->num, num, 0); + break; + case BIO_C_FILE_TELL: + case BIO_CTRL_INFO: + ret = (long)UP_lseek(b->num, 0, 1); + break; + case BIO_C_SET_FD: + fd_free(b); + b->num = *((int *)ptr); + b->shutdown = (int)num; + b->init = 1; + break; + case BIO_C_GET_FD: + if (b->init) { + ip = (int *)ptr; + if (ip != NULL) + *ip = b->num; + ret = b->num; + } else + ret = -1; + break; + case BIO_CTRL_GET_CLOSE: + ret = b->shutdown; + break; + case BIO_CTRL_SET_CLOSE: + b->shutdown = (int)num; + break; + case BIO_CTRL_PENDING: + case BIO_CTRL_WPENDING: + ret = 0; + break; + case BIO_CTRL_DUP: + case BIO_CTRL_FLUSH: + ret = 1; + break; + default: + ret = 0; + break; + } + return ret; +} + +static int fd_puts(BIO *bp, const char *str) +{ + int n, ret; + + n = strlen(str); + ret = fd_write(bp, str, n); + return ret; +} + +static int fd_gets(BIO *bp, char *buf, int size) +{ + int ret = 0; + char *ptr = buf; + char *end = buf + size - 1; + + while (ptr < end && fd_read(bp, ptr, 1) > 0) { + if (*ptr++ == '\n') + break; + } + + ptr[0] = '\0'; + + if (buf[0] != '\0') + ret = strlen(buf); + return ret; +} + +int BIO_fd_should_retry(int i) +{ + int err; + + if ((i == 0) || (i == -1)) { + err = get_last_sys_error(); + + return BIO_fd_non_fatal_error(err); + } + return 0; +} + +int BIO_fd_non_fatal_error(int err) +{ + switch (err) { + +# ifdef EWOULDBLOCK +# ifdef WSAEWOULDBLOCK +# if WSAEWOULDBLOCK != EWOULDBLOCK + case EWOULDBLOCK: +# endif +# else + case EWOULDBLOCK: +# endif +# endif + +# if defined(ENOTCONN) + case ENOTCONN: +# endif + +# ifdef EINTR + case EINTR: +# endif + +# ifdef EAGAIN +# if EWOULDBLOCK != EAGAIN + case EAGAIN: +# endif +# endif + +# ifdef EPROTO + case EPROTO: +# endif + +# ifdef EINPROGRESS + case EINPROGRESS: +# endif + +# ifdef EALREADY + case EALREADY: +# endif + return 1; + default: + break; + } + return 0; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_file.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_file.c new file mode 100644 index 000000000..057344783 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_file.c @@ -0,0 +1,427 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_BSS_FILE_C +# define HEADER_BSS_FILE_C + +# if defined(__linux) || defined(__sun) || defined(__hpux) +/* + * Following definition aliases fopen to fopen64 on above mentioned + * platforms. This makes it possible to open and sequentially access files + * larger than 2GB from 32-bit application. It does not allow to traverse + * them beyond 2GB with fseek/ftell, but on the other hand *no* 32-bit + * platform permits that, not with fseek/ftell. Not to mention that breaking + * 2GB limit for seeking would require surgery to *our* API. But sequential + * access suffices for practical cases when you can run into large files, + * such as fingerprinting, so we can let API alone. For reference, the list + * of 32-bit platforms which allow for sequential access of large files + * without extra "magic" comprise *BSD, Darwin, IRIX... + */ +# ifndef _FILE_OFFSET_BITS +# define _FILE_OFFSET_BITS 64 +# endif +# endif + +# include +# include +# include "bio_lcl.h" +# include + +# if !defined(OPENSSL_NO_STDIO) + +static int file_write(BIO *h, const char *buf, int num); +static int file_read(BIO *h, char *buf, int size); +static int file_puts(BIO *h, const char *str); +static int file_gets(BIO *h, char *str, int size); +static long file_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int file_new(BIO *h); +static int file_free(BIO *data); +static const BIO_METHOD methods_filep = { + BIO_TYPE_FILE, + "FILE pointer", + /* TODO: Convert to new style write function */ + bwrite_conv, + file_write, + /* TODO: Convert to new style read function */ + bread_conv, + file_read, + file_puts, + file_gets, + file_ctrl, + file_new, + file_free, + NULL, /* file_callback_ctrl */ +}; + +BIO *BIO_new_file(const char *filename, const char *mode) +{ + BIO *ret; + FILE *file = openssl_fopen(filename, mode); + int fp_flags = BIO_CLOSE; + + if (strchr(mode, 'b') == NULL) + fp_flags |= BIO_FP_TEXT; + + if (file == NULL) { + SYSerr(SYS_F_FOPEN, get_last_sys_error()); + ERR_add_error_data(5, "fopen('", filename, "','", mode, "')"); + if (errno == ENOENT +# ifdef ENXIO + || errno == ENXIO +# endif + ) + BIOerr(BIO_F_BIO_NEW_FILE, BIO_R_NO_SUCH_FILE); + else + BIOerr(BIO_F_BIO_NEW_FILE, ERR_R_SYS_LIB); + return NULL; + } + if ((ret = BIO_new(BIO_s_file())) == NULL) { + fclose(file); + return NULL; + } + + BIO_clear_flags(ret, BIO_FLAGS_UPLINK); /* we did fopen -> we disengage + * UPLINK */ + BIO_set_fp(ret, file, fp_flags); + return ret; +} + +BIO *BIO_new_fp(FILE *stream, int close_flag) +{ + BIO *ret; + + if ((ret = BIO_new(BIO_s_file())) == NULL) + return NULL; + + /* redundant flag, left for documentation purposes */ + BIO_set_flags(ret, BIO_FLAGS_UPLINK); + BIO_set_fp(ret, stream, close_flag); + return ret; +} + +const BIO_METHOD *BIO_s_file(void) +{ + return &methods_filep; +} + +static int file_new(BIO *bi) +{ + bi->init = 0; + bi->num = 0; + bi->ptr = NULL; + bi->flags = BIO_FLAGS_UPLINK; /* default to UPLINK */ + return 1; +} + +static int file_free(BIO *a) +{ + if (a == NULL) + return 0; + if (a->shutdown) { + if ((a->init) && (a->ptr != NULL)) { + if (a->flags & BIO_FLAGS_UPLINK) + UP_fclose(a->ptr); + else + fclose(a->ptr); + a->ptr = NULL; + a->flags = BIO_FLAGS_UPLINK; + } + a->init = 0; + } + return 1; +} + +static int file_read(BIO *b, char *out, int outl) +{ + int ret = 0; + + if (b->init && (out != NULL)) { + if (b->flags & BIO_FLAGS_UPLINK) + ret = UP_fread(out, 1, (int)outl, b->ptr); + else + ret = fread(out, 1, (int)outl, (FILE *)b->ptr); + if (ret == 0 + && (b->flags & BIO_FLAGS_UPLINK) ? UP_ferror((FILE *)b->ptr) : + ferror((FILE *)b->ptr)) { + SYSerr(SYS_F_FREAD, get_last_sys_error()); + BIOerr(BIO_F_FILE_READ, ERR_R_SYS_LIB); + ret = -1; + } + } + return ret; +} + +static int file_write(BIO *b, const char *in, int inl) +{ + int ret = 0; + + if (b->init && (in != NULL)) { + if (b->flags & BIO_FLAGS_UPLINK) + ret = UP_fwrite(in, (int)inl, 1, b->ptr); + else + ret = fwrite(in, (int)inl, 1, (FILE *)b->ptr); + if (ret) + ret = inl; + /* ret=fwrite(in,1,(int)inl,(FILE *)b->ptr); */ + /* + * according to Tim Hudson , the commented out + * version above can cause 'inl' write calls under some stupid stdio + * implementations (VMS) + */ + } + return ret; +} + +static long file_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + long ret = 1; + FILE *fp = (FILE *)b->ptr; + FILE **fpp; + char p[4]; + int st; + + switch (cmd) { + case BIO_C_FILE_SEEK: + case BIO_CTRL_RESET: + if (b->flags & BIO_FLAGS_UPLINK) + ret = (long)UP_fseek(b->ptr, num, 0); + else + ret = (long)fseek(fp, num, 0); + break; + case BIO_CTRL_EOF: + if (b->flags & BIO_FLAGS_UPLINK) + ret = (long)UP_feof(fp); + else + ret = (long)feof(fp); + break; + case BIO_C_FILE_TELL: + case BIO_CTRL_INFO: + if (b->flags & BIO_FLAGS_UPLINK) + ret = UP_ftell(b->ptr); + else + ret = ftell(fp); + break; + case BIO_C_SET_FILE_PTR: + file_free(b); + b->shutdown = (int)num & BIO_CLOSE; + b->ptr = ptr; + b->init = 1; +# if BIO_FLAGS_UPLINK!=0 +# if defined(__MINGW32__) && defined(__MSVCRT__) && !defined(_IOB_ENTRIES) +# define _IOB_ENTRIES 20 +# endif + /* Safety net to catch purely internal BIO_set_fp calls */ +# if defined(_MSC_VER) && _MSC_VER>=1900 + if (ptr == stdin || ptr == stdout || ptr == stderr) + BIO_clear_flags(b, BIO_FLAGS_UPLINK); +# elif defined(_IOB_ENTRIES) + if ((size_t)ptr >= (size_t)stdin && + (size_t)ptr < (size_t)(stdin + _IOB_ENTRIES)) + BIO_clear_flags(b, BIO_FLAGS_UPLINK); +# endif +# endif +# ifdef UP_fsetmod + if (b->flags & BIO_FLAGS_UPLINK) + UP_fsetmod(b->ptr, (char)((num & BIO_FP_TEXT) ? 't' : 'b')); + else +# endif + { +# if defined(OPENSSL_SYS_WINDOWS) + int fd = _fileno((FILE *)ptr); + if (num & BIO_FP_TEXT) + _setmode(fd, _O_TEXT); + else + _setmode(fd, _O_BINARY); +# elif defined(OPENSSL_SYS_MSDOS) + int fd = fileno((FILE *)ptr); + /* Set correct text/binary mode */ + if (num & BIO_FP_TEXT) + _setmode(fd, _O_TEXT); + /* Dangerous to set stdin/stdout to raw (unless redirected) */ + else { + if (fd == STDIN_FILENO || fd == STDOUT_FILENO) { + if (isatty(fd) <= 0) + _setmode(fd, _O_BINARY); + } else + _setmode(fd, _O_BINARY); + } +# elif defined(OPENSSL_SYS_WIN32_CYGWIN) + int fd = fileno((FILE *)ptr); + if (!(num & BIO_FP_TEXT)) + setmode(fd, O_BINARY); +# endif + } + break; + case BIO_C_SET_FILENAME: + file_free(b); + b->shutdown = (int)num & BIO_CLOSE; + if (num & BIO_FP_APPEND) { + if (num & BIO_FP_READ) + OPENSSL_strlcpy(p, "a+", sizeof(p)); + else + OPENSSL_strlcpy(p, "a", sizeof(p)); + } else if ((num & BIO_FP_READ) && (num & BIO_FP_WRITE)) + OPENSSL_strlcpy(p, "r+", sizeof(p)); + else if (num & BIO_FP_WRITE) + OPENSSL_strlcpy(p, "w", sizeof(p)); + else if (num & BIO_FP_READ) + OPENSSL_strlcpy(p, "r", sizeof(p)); + else { + BIOerr(BIO_F_FILE_CTRL, BIO_R_BAD_FOPEN_MODE); + ret = 0; + break; + } +# if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WINDOWS) + if (!(num & BIO_FP_TEXT)) + OPENSSL_strlcat(p, "b", sizeof(p)); + else + OPENSSL_strlcat(p, "t", sizeof(p)); +# elif defined(OPENSSL_SYS_WIN32_CYGWIN) + if (!(num & BIO_FP_TEXT)) + OPENSSL_strlcat(p, "b", sizeof(p)); +# endif + fp = openssl_fopen(ptr, p); + if (fp == NULL) { + SYSerr(SYS_F_FOPEN, get_last_sys_error()); + ERR_add_error_data(5, "fopen('", ptr, "','", p, "')"); + BIOerr(BIO_F_FILE_CTRL, ERR_R_SYS_LIB); + ret = 0; + break; + } + b->ptr = fp; + b->init = 1; + BIO_clear_flags(b, BIO_FLAGS_UPLINK); /* we did fopen -> we disengage + * UPLINK */ + break; + case BIO_C_GET_FILE_PTR: + /* the ptr parameter is actually a FILE ** in this case. */ + if (ptr != NULL) { + fpp = (FILE **)ptr; + *fpp = (FILE *)b->ptr; + } + break; + case BIO_CTRL_GET_CLOSE: + ret = (long)b->shutdown; + break; + case BIO_CTRL_SET_CLOSE: + b->shutdown = (int)num; + break; + case BIO_CTRL_FLUSH: + st = b->flags & BIO_FLAGS_UPLINK + ? UP_fflush(b->ptr) : fflush((FILE *)b->ptr); + if (st == EOF) { + SYSerr(SYS_F_FFLUSH, get_last_sys_error()); + ERR_add_error_data(1, "fflush()"); + BIOerr(BIO_F_FILE_CTRL, ERR_R_SYS_LIB); + ret = 0; + } + break; + case BIO_CTRL_DUP: + ret = 1; + break; + + case BIO_CTRL_WPENDING: + case BIO_CTRL_PENDING: + case BIO_CTRL_PUSH: + case BIO_CTRL_POP: + default: + ret = 0; + break; + } + return ret; +} + +static int file_gets(BIO *bp, char *buf, int size) +{ + int ret = 0; + + buf[0] = '\0'; + if (bp->flags & BIO_FLAGS_UPLINK) { + if (!UP_fgets(buf, size, bp->ptr)) + goto err; + } else { + if (!fgets(buf, size, (FILE *)bp->ptr)) + goto err; + } + if (buf[0] != '\0') + ret = strlen(buf); + err: + return ret; +} + +static int file_puts(BIO *bp, const char *str) +{ + int n, ret; + + n = strlen(str); + ret = file_write(bp, str, n); + return ret; +} + +#else + +static int file_write(BIO *b, const char *in, int inl) +{ + return -1; +} +static int file_read(BIO *b, char *out, int outl) +{ + return -1; +} +static int file_puts(BIO *bp, const char *str) +{ + return -1; +} +static int file_gets(BIO *bp, char *buf, int size) +{ + return 0; +} +static long file_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + return 0; +} +static int file_new(BIO *bi) +{ + return 0; +} +static int file_free(BIO *a) +{ + return 0; +} + +static const BIO_METHOD methods_filep = { + BIO_TYPE_FILE, + "FILE pointer", + /* TODO: Convert to new style write function */ + bwrite_conv, + file_write, + /* TODO: Convert to new style read function */ + bread_conv, + file_read, + file_puts, + file_gets, + file_ctrl, + file_new, + file_free, + NULL, /* file_callback_ctrl */ +}; + +const BIO_METHOD *BIO_s_file(void) +{ + return &methods_filep; +} + +BIO *BIO_new_file(const char *filename, const char *mode) +{ + return NULL; +} + +# endif /* OPENSSL_NO_STDIO */ + +#endif /* HEADER_BSS_FILE_C */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_log.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_log.c new file mode 100644 index 000000000..e9ab932ec --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_log.c @@ -0,0 +1,416 @@ +/* + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Why BIO_s_log? + * + * BIO_s_log is useful for system daemons (or services under NT). It is + * one-way BIO, it sends all stuff to syslogd (on system that commonly use + * that), or event log (on NT), or OPCOM (on OpenVMS). + * + */ + +#include +#include + +#include "bio_lcl.h" +#include "internal/cryptlib.h" + +#if defined(OPENSSL_SYS_WINCE) +#elif defined(OPENSSL_SYS_WIN32) +#elif defined(OPENSSL_SYS_VMS) +# include +# include +# include +# include +/* Some compiler options may mask the declaration of "_malloc32". */ +# if __INITIAL_POINTER_SIZE && defined _ANSI_C_SOURCE +# if __INITIAL_POINTER_SIZE == 64 +# pragma pointer_size save +# pragma pointer_size 32 +void *_malloc32(__size_t); +# pragma pointer_size restore +# endif /* __INITIAL_POINTER_SIZE == 64 */ +# endif /* __INITIAL_POINTER_SIZE && defined + * _ANSI_C_SOURCE */ +#elif defined(__DJGPP__) && defined(OPENSSL_NO_SOCK) +# define NO_SYSLOG +#elif (!defined(MSDOS) || defined(WATT32)) && !defined(OPENSSL_SYS_VXWORKS) && !defined(NO_SYSLOG) +# include +#endif + +#include +#include + +#ifndef NO_SYSLOG + +# if defined(OPENSSL_SYS_WIN32) +# define LOG_EMERG 0 +# define LOG_ALERT 1 +# define LOG_CRIT 2 +# define LOG_ERR 3 +# define LOG_WARNING 4 +# define LOG_NOTICE 5 +# define LOG_INFO 6 +# define LOG_DEBUG 7 + +# define LOG_DAEMON (3<<3) +# elif defined(OPENSSL_SYS_VMS) +/* On VMS, we don't really care about these, but we need them to compile */ +# define LOG_EMERG 0 +# define LOG_ALERT 1 +# define LOG_CRIT 2 +# define LOG_ERR 3 +# define LOG_WARNING 4 +# define LOG_NOTICE 5 +# define LOG_INFO 6 +# define LOG_DEBUG 7 + +# define LOG_DAEMON OPC$M_NM_NTWORK +# endif + +static int slg_write(BIO *h, const char *buf, int num); +static int slg_puts(BIO *h, const char *str); +static long slg_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int slg_new(BIO *h); +static int slg_free(BIO *data); +static void xopenlog(BIO *bp, char *name, int level); +static void xsyslog(BIO *bp, int priority, const char *string); +static void xcloselog(BIO *bp); + +static const BIO_METHOD methods_slg = { + BIO_TYPE_MEM, + "syslog", + /* TODO: Convert to new style write function */ + bwrite_conv, + slg_write, + NULL, /* slg_write_old, */ + NULL, /* slg_read, */ + slg_puts, + NULL, + slg_ctrl, + slg_new, + slg_free, + NULL, /* slg_callback_ctrl */ +}; + +const BIO_METHOD *BIO_s_log(void) +{ + return &methods_slg; +} + +static int slg_new(BIO *bi) +{ + bi->init = 1; + bi->num = 0; + bi->ptr = NULL; + xopenlog(bi, "application", LOG_DAEMON); + return 1; +} + +static int slg_free(BIO *a) +{ + if (a == NULL) + return 0; + xcloselog(a); + return 1; +} + +static int slg_write(BIO *b, const char *in, int inl) +{ + int ret = inl; + char *buf; + char *pp; + int priority, i; + static const struct { + int strl; + char str[10]; + int log_level; + } mapping[] = { + { + 6, "PANIC ", LOG_EMERG + }, + { + 6, "EMERG ", LOG_EMERG + }, + { + 4, "EMR ", LOG_EMERG + }, + { + 6, "ALERT ", LOG_ALERT + }, + { + 4, "ALR ", LOG_ALERT + }, + { + 5, "CRIT ", LOG_CRIT + }, + { + 4, "CRI ", LOG_CRIT + }, + { + 6, "ERROR ", LOG_ERR + }, + { + 4, "ERR ", LOG_ERR + }, + { + 8, "WARNING ", LOG_WARNING + }, + { + 5, "WARN ", LOG_WARNING + }, + { + 4, "WAR ", LOG_WARNING + }, + { + 7, "NOTICE ", LOG_NOTICE + }, + { + 5, "NOTE ", LOG_NOTICE + }, + { + 4, "NOT ", LOG_NOTICE + }, + { + 5, "INFO ", LOG_INFO + }, + { + 4, "INF ", LOG_INFO + }, + { + 6, "DEBUG ", LOG_DEBUG + }, + { + 4, "DBG ", LOG_DEBUG + }, + { + 0, "", LOG_ERR + } + /* The default */ + }; + + if ((buf = OPENSSL_malloc(inl + 1)) == NULL) { + BIOerr(BIO_F_SLG_WRITE, ERR_R_MALLOC_FAILURE); + return 0; + } + memcpy(buf, in, inl); + buf[inl] = '\0'; + + i = 0; + while (strncmp(buf, mapping[i].str, mapping[i].strl) != 0) + i++; + priority = mapping[i].log_level; + pp = buf + mapping[i].strl; + + xsyslog(b, priority, pp); + + OPENSSL_free(buf); + return ret; +} + +static long slg_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + switch (cmd) { + case BIO_CTRL_SET: + xcloselog(b); + xopenlog(b, ptr, num); + break; + default: + break; + } + return 0; +} + +static int slg_puts(BIO *bp, const char *str) +{ + int n, ret; + + n = strlen(str); + ret = slg_write(bp, str, n); + return ret; +} + +# if defined(OPENSSL_SYS_WIN32) + +static void xopenlog(BIO *bp, char *name, int level) +{ + if (check_winnt()) + bp->ptr = RegisterEventSourceA(NULL, name); + else + bp->ptr = NULL; +} + +static void xsyslog(BIO *bp, int priority, const char *string) +{ + LPCSTR lpszStrings[2]; + WORD evtype = EVENTLOG_ERROR_TYPE; + char pidbuf[DECIMAL_SIZE(DWORD) + 4]; + + if (bp->ptr == NULL) + return; + + switch (priority) { + case LOG_EMERG: + case LOG_ALERT: + case LOG_CRIT: + case LOG_ERR: + evtype = EVENTLOG_ERROR_TYPE; + break; + case LOG_WARNING: + evtype = EVENTLOG_WARNING_TYPE; + break; + case LOG_NOTICE: + case LOG_INFO: + case LOG_DEBUG: + evtype = EVENTLOG_INFORMATION_TYPE; + break; + default: + /* + * Should never happen, but set it + * as error anyway. + */ + evtype = EVENTLOG_ERROR_TYPE; + break; + } + + sprintf(pidbuf, "[%lu] ", GetCurrentProcessId()); + lpszStrings[0] = pidbuf; + lpszStrings[1] = string; + + ReportEventA(bp->ptr, evtype, 0, 1024, NULL, 2, 0, lpszStrings, NULL); +} + +static void xcloselog(BIO *bp) +{ + if (bp->ptr) + DeregisterEventSource((HANDLE) (bp->ptr)); + bp->ptr = NULL; +} + +# elif defined(OPENSSL_SYS_VMS) + +static int VMS_OPC_target = LOG_DAEMON; + +static void xopenlog(BIO *bp, char *name, int level) +{ + VMS_OPC_target = level; +} + +static void xsyslog(BIO *bp, int priority, const char *string) +{ + struct dsc$descriptor_s opc_dsc; + +/* Arrange 32-bit pointer to opcdef buffer and malloc(), if needed. */ +# if __INITIAL_POINTER_SIZE == 64 +# pragma pointer_size save +# pragma pointer_size 32 +# define OPCDEF_TYPE __char_ptr32 +# define OPCDEF_MALLOC _malloc32 +# else /* __INITIAL_POINTER_SIZE == 64 */ +# define OPCDEF_TYPE char * +# define OPCDEF_MALLOC OPENSSL_malloc +# endif /* __INITIAL_POINTER_SIZE == 64 [else] */ + + struct opcdef *opcdef_p; + +# if __INITIAL_POINTER_SIZE == 64 +# pragma pointer_size restore +# endif /* __INITIAL_POINTER_SIZE == 64 */ + + char buf[10240]; + unsigned int len; + struct dsc$descriptor_s buf_dsc; + $DESCRIPTOR(fao_cmd, "!AZ: !AZ"); + char *priority_tag; + + switch (priority) { + case LOG_EMERG: + priority_tag = "Emergency"; + break; + case LOG_ALERT: + priority_tag = "Alert"; + break; + case LOG_CRIT: + priority_tag = "Critical"; + break; + case LOG_ERR: + priority_tag = "Error"; + break; + case LOG_WARNING: + priority_tag = "Warning"; + break; + case LOG_NOTICE: + priority_tag = "Notice"; + break; + case LOG_INFO: + priority_tag = "Info"; + break; + case LOG_DEBUG: + priority_tag = "DEBUG"; + break; + } + + buf_dsc.dsc$b_dtype = DSC$K_DTYPE_T; + buf_dsc.dsc$b_class = DSC$K_CLASS_S; + buf_dsc.dsc$a_pointer = buf; + buf_dsc.dsc$w_length = sizeof(buf) - 1; + + lib$sys_fao(&fao_cmd, &len, &buf_dsc, priority_tag, string); + + /* We know there's an 8-byte header. That's documented. */ + opcdef_p = OPCDEF_MALLOC(8 + len); + opcdef_p->opc$b_ms_type = OPC$_RQ_RQST; + memcpy(opcdef_p->opc$z_ms_target_classes, &VMS_OPC_target, 3); + opcdef_p->opc$l_ms_rqstid = 0; + memcpy(&opcdef_p->opc$l_ms_text, buf, len); + + opc_dsc.dsc$b_dtype = DSC$K_DTYPE_T; + opc_dsc.dsc$b_class = DSC$K_CLASS_S; + opc_dsc.dsc$a_pointer = (OPCDEF_TYPE) opcdef_p; + opc_dsc.dsc$w_length = len + 8; + + sys$sndopr(opc_dsc, 0); + + OPENSSL_free(opcdef_p); +} + +static void xcloselog(BIO *bp) +{ +} + +# else /* Unix/Watt32 */ + +static void xopenlog(BIO *bp, char *name, int level) +{ +# ifdef WATT32 /* djgpp/DOS */ + openlog(name, LOG_PID | LOG_CONS | LOG_NDELAY, level); +# else + openlog(name, LOG_PID | LOG_CONS, level); +# endif +} + +static void xsyslog(BIO *bp, int priority, const char *string) +{ + syslog(priority, "%s", string); +} + +static void xcloselog(BIO *bp) +{ + closelog(); +} + +# endif /* Unix */ + +#else /* NO_SYSLOG */ +const BIO_METHOD *BIO_s_log(void) +{ + return NULL; +} +#endif /* NO_SYSLOG */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_mem.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_mem.c new file mode 100644 index 000000000..10fcbf7a7 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_mem.c @@ -0,0 +1,357 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "bio_lcl.h" +#include "internal/cryptlib.h" + +static int mem_write(BIO *h, const char *buf, int num); +static int mem_read(BIO *h, char *buf, int size); +static int mem_puts(BIO *h, const char *str); +static int mem_gets(BIO *h, char *str, int size); +static long mem_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int mem_new(BIO *h); +static int secmem_new(BIO *h); +static int mem_free(BIO *data); +static int mem_buf_free(BIO *data); +static int mem_buf_sync(BIO *h); + +static const BIO_METHOD mem_method = { + BIO_TYPE_MEM, + "memory buffer", + /* TODO: Convert to new style write function */ + bwrite_conv, + mem_write, + /* TODO: Convert to new style read function */ + bread_conv, + mem_read, + mem_puts, + mem_gets, + mem_ctrl, + mem_new, + mem_free, + NULL, /* mem_callback_ctrl */ +}; + +static const BIO_METHOD secmem_method = { + BIO_TYPE_MEM, + "secure memory buffer", + /* TODO: Convert to new style write function */ + bwrite_conv, + mem_write, + /* TODO: Convert to new style read function */ + bread_conv, + mem_read, + mem_puts, + mem_gets, + mem_ctrl, + secmem_new, + mem_free, + NULL, /* mem_callback_ctrl */ +}; + +/* BIO memory stores buffer and read pointer */ +typedef struct bio_buf_mem_st { + struct buf_mem_st *buf; /* allocated buffer */ + struct buf_mem_st *readp; /* read pointer */ +} BIO_BUF_MEM; + +/* + * bio->num is used to hold the value to return on 'empty', if it is 0, + * should_retry is not set + */ + +const BIO_METHOD *BIO_s_mem(void) +{ + return &mem_method; +} + +const BIO_METHOD *BIO_s_secmem(void) +{ + return(&secmem_method); +} + +BIO *BIO_new_mem_buf(const void *buf, int len) +{ + BIO *ret; + BUF_MEM *b; + BIO_BUF_MEM *bb; + size_t sz; + + if (buf == NULL) { + BIOerr(BIO_F_BIO_NEW_MEM_BUF, BIO_R_NULL_PARAMETER); + return NULL; + } + sz = (len < 0) ? strlen(buf) : (size_t)len; + if ((ret = BIO_new(BIO_s_mem())) == NULL) + return NULL; + bb = (BIO_BUF_MEM *)ret->ptr; + b = bb->buf; + /* Cast away const and trust in the MEM_RDONLY flag. */ + b->data = (void *)buf; + b->length = sz; + b->max = sz; + *bb->readp = *bb->buf; + ret->flags |= BIO_FLAGS_MEM_RDONLY; + /* Since this is static data retrying won't help */ + ret->num = 0; + return ret; +} + +static int mem_init(BIO *bi, unsigned long flags) +{ + BIO_BUF_MEM *bb = OPENSSL_zalloc(sizeof(*bb)); + + if (bb == NULL) + return 0; + if ((bb->buf = BUF_MEM_new_ex(flags)) == NULL) { + OPENSSL_free(bb); + return 0; + } + if ((bb->readp = OPENSSL_zalloc(sizeof(*bb->readp))) == NULL) { + BUF_MEM_free(bb->buf); + OPENSSL_free(bb); + return 0; + } + *bb->readp = *bb->buf; + bi->shutdown = 1; + bi->init = 1; + bi->num = -1; + bi->ptr = (char *)bb; + return 1; +} + +static int mem_new(BIO *bi) +{ + return mem_init(bi, 0L); +} + +static int secmem_new(BIO *bi) +{ + return mem_init(bi, BUF_MEM_FLAG_SECURE); +} + +static int mem_free(BIO *a) +{ + BIO_BUF_MEM *bb; + + if (a == NULL) + return 0; + + bb = (BIO_BUF_MEM *)a->ptr; + if (!mem_buf_free(a)) + return 0; + OPENSSL_free(bb->readp); + OPENSSL_free(bb); + return 1; +} + +static int mem_buf_free(BIO *a) +{ + if (a == NULL) + return 0; + + if (a->shutdown && a->init && a->ptr != NULL) { + BIO_BUF_MEM *bb = (BIO_BUF_MEM *)a->ptr; + BUF_MEM *b = bb->buf; + + if (a->flags & BIO_FLAGS_MEM_RDONLY) + b->data = NULL; + BUF_MEM_free(b); + } + return 1; +} + +/* + * Reallocate memory buffer if read pointer differs + */ +static int mem_buf_sync(BIO *b) +{ + if (b != NULL && b->init != 0 && b->ptr != NULL) { + BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr; + + if (bbm->readp->data != bbm->buf->data) { + memmove(bbm->buf->data, bbm->readp->data, bbm->readp->length); + bbm->buf->length = bbm->readp->length; + bbm->readp->data = bbm->buf->data; + } + } + return 0; +} + +static int mem_read(BIO *b, char *out, int outl) +{ + int ret = -1; + BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr; + BUF_MEM *bm = bbm->readp; + + BIO_clear_retry_flags(b); + ret = (outl >= 0 && (size_t)outl > bm->length) ? (int)bm->length : outl; + if ((out != NULL) && (ret > 0)) { + memcpy(out, bm->data, ret); + bm->length -= ret; + bm->data += ret; + } else if (bm->length == 0) { + ret = b->num; + if (ret != 0) + BIO_set_retry_read(b); + } + return ret; +} + +static int mem_write(BIO *b, const char *in, int inl) +{ + int ret = -1; + int blen; + BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr; + + if (in == NULL) { + BIOerr(BIO_F_MEM_WRITE, BIO_R_NULL_PARAMETER); + goto end; + } + if (b->flags & BIO_FLAGS_MEM_RDONLY) { + BIOerr(BIO_F_MEM_WRITE, BIO_R_WRITE_TO_READ_ONLY_BIO); + goto end; + } + BIO_clear_retry_flags(b); + if (inl == 0) + return 0; + blen = bbm->readp->length; + mem_buf_sync(b); + if (BUF_MEM_grow_clean(bbm->buf, blen + inl) == 0) + goto end; + memcpy(bbm->buf->data + blen, in, inl); + *bbm->readp = *bbm->buf; + ret = inl; + end: + return ret; +} + +static long mem_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + long ret = 1; + char **pptr; + BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr; + BUF_MEM *bm; + + switch (cmd) { + case BIO_CTRL_RESET: + bm = bbm->buf; + if (bm->data != NULL) { + /* For read only case reset to the start again */ + if ((b->flags & BIO_FLAGS_MEM_RDONLY) || (b->flags & BIO_FLAGS_NONCLEAR_RST)) { + bm->length = bm->max; + } else { + memset(bm->data, 0, bm->max); + bm->length = 0; + } + *bbm->readp = *bbm->buf; + } + break; + case BIO_CTRL_EOF: + bm = bbm->readp; + ret = (long)(bm->length == 0); + break; + case BIO_C_SET_BUF_MEM_EOF_RETURN: + b->num = (int)num; + break; + case BIO_CTRL_INFO: + bm = bbm->readp; + ret = (long)bm->length; + if (ptr != NULL) { + pptr = (char **)ptr; + *pptr = (char *)&(bm->data[0]); + } + break; + case BIO_C_SET_BUF_MEM: + mem_buf_free(b); + b->shutdown = (int)num; + bbm->buf = ptr; + *bbm->readp = *bbm->buf; + break; + case BIO_C_GET_BUF_MEM_PTR: + if (ptr != NULL) { + mem_buf_sync(b); + bm = bbm->readp; + pptr = (char **)ptr; + *pptr = (char *)bm; + } + break; + case BIO_CTRL_GET_CLOSE: + ret = (long)b->shutdown; + break; + case BIO_CTRL_SET_CLOSE: + b->shutdown = (int)num; + break; + case BIO_CTRL_WPENDING: + ret = 0L; + break; + case BIO_CTRL_PENDING: + bm = bbm->readp; + ret = (long)bm->length; + break; + case BIO_CTRL_DUP: + case BIO_CTRL_FLUSH: + ret = 1; + break; + case BIO_CTRL_PUSH: + case BIO_CTRL_POP: + default: + ret = 0; + break; + } + return ret; +} + +static int mem_gets(BIO *bp, char *buf, int size) +{ + int i, j; + int ret = -1; + char *p; + BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)bp->ptr; + BUF_MEM *bm = bbm->readp; + + BIO_clear_retry_flags(bp); + j = bm->length; + if ((size - 1) < j) + j = size - 1; + if (j <= 0) { + *buf = '\0'; + return 0; + } + p = bm->data; + for (i = 0; i < j; i++) { + if (p[i] == '\n') { + i++; + break; + } + } + + /* + * i is now the max num of bytes to copy, either j or up to + * and including the first newline + */ + + i = mem_read(bp, buf, i); + if (i > 0) + buf[i] = '\0'; + ret = i; + return ret; +} + +static int mem_puts(BIO *bp, const char *str) +{ + int n, ret; + + n = strlen(str); + ret = mem_write(bp, str, n); + /* memory semantics is that it will always work */ + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_null.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_null.c new file mode 100644 index 000000000..08f1d2bc9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_null.c @@ -0,0 +1,87 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "bio_lcl.h" +#include "internal/cryptlib.h" + +static int null_write(BIO *h, const char *buf, int num); +static int null_read(BIO *h, char *buf, int size); +static int null_puts(BIO *h, const char *str); +static int null_gets(BIO *h, char *str, int size); +static long null_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static const BIO_METHOD null_method = { + BIO_TYPE_NULL, + "NULL", + /* TODO: Convert to new style write function */ + bwrite_conv, + null_write, + /* TODO: Convert to new style read function */ + bread_conv, + null_read, + null_puts, + null_gets, + null_ctrl, + NULL, + NULL, + NULL, /* null_callback_ctrl */ +}; + +const BIO_METHOD *BIO_s_null(void) +{ + return &null_method; +} + +static int null_read(BIO *b, char *out, int outl) +{ + return 0; +} + +static int null_write(BIO *b, const char *in, int inl) +{ + return inl; +} + +static long null_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + long ret = 1; + + switch (cmd) { + case BIO_CTRL_RESET: + case BIO_CTRL_EOF: + case BIO_CTRL_SET: + case BIO_CTRL_SET_CLOSE: + case BIO_CTRL_FLUSH: + case BIO_CTRL_DUP: + ret = 1; + break; + case BIO_CTRL_GET_CLOSE: + case BIO_CTRL_INFO: + case BIO_CTRL_GET: + case BIO_CTRL_PENDING: + case BIO_CTRL_WPENDING: + default: + ret = 0; + break; + } + return ret; +} + +static int null_gets(BIO *bp, char *buf, int size) +{ + return 0; +} + +static int null_puts(BIO *bp, const char *str) +{ + if (str == NULL) + return 0; + return strlen(str); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_sock.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_sock.c new file mode 100644 index 000000000..ad3845320 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_sock.c @@ -0,0 +1,233 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "bio_lcl.h" +#include "internal/cryptlib.h" + +#ifndef OPENSSL_NO_SOCK + +# include + +# ifdef WATT32 +/* Watt-32 uses same names */ +# undef sock_write +# undef sock_read +# undef sock_puts +# define sock_write SockWrite +# define sock_read SockRead +# define sock_puts SockPuts +# endif + +static int sock_write(BIO *h, const char *buf, int num); +static int sock_read(BIO *h, char *buf, int size); +static int sock_puts(BIO *h, const char *str); +static long sock_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int sock_new(BIO *h); +static int sock_free(BIO *data); +int BIO_sock_should_retry(int s); + +static const BIO_METHOD methods_sockp = { + BIO_TYPE_SOCKET, + "socket", + /* TODO: Convert to new style write function */ + bwrite_conv, + sock_write, + /* TODO: Convert to new style read function */ + bread_conv, + sock_read, + sock_puts, + NULL, /* sock_gets, */ + sock_ctrl, + sock_new, + sock_free, + NULL, /* sock_callback_ctrl */ +}; + +const BIO_METHOD *BIO_s_socket(void) +{ + return &methods_sockp; +} + +BIO *BIO_new_socket(int fd, int close_flag) +{ + BIO *ret; + + ret = BIO_new(BIO_s_socket()); + if (ret == NULL) + return NULL; + BIO_set_fd(ret, fd, close_flag); + return ret; +} + +static int sock_new(BIO *bi) +{ + bi->init = 0; + bi->num = 0; + bi->ptr = NULL; + bi->flags = 0; + return 1; +} + +static int sock_free(BIO *a) +{ + if (a == NULL) + return 0; + if (a->shutdown) { + if (a->init) { + BIO_closesocket(a->num); + } + a->init = 0; + a->flags = 0; + } + return 1; +} + +static int sock_read(BIO *b, char *out, int outl) +{ + int ret = 0; + + if (out != NULL) { + clear_socket_error(); + ret = readsocket(b->num, out, outl); + BIO_clear_retry_flags(b); + if (ret <= 0) { + if (BIO_sock_should_retry(ret)) + BIO_set_retry_read(b); + } + } + return ret; +} + +static int sock_write(BIO *b, const char *in, int inl) +{ + int ret; + + clear_socket_error(); + ret = writesocket(b->num, in, inl); + BIO_clear_retry_flags(b); + if (ret <= 0) { + if (BIO_sock_should_retry(ret)) + BIO_set_retry_write(b); + } + return ret; +} + +static long sock_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + long ret = 1; + int *ip; + + switch (cmd) { + case BIO_C_SET_FD: + sock_free(b); + b->num = *((int *)ptr); + b->shutdown = (int)num; + b->init = 1; + break; + case BIO_C_GET_FD: + if (b->init) { + ip = (int *)ptr; + if (ip != NULL) + *ip = b->num; + ret = b->num; + } else + ret = -1; + break; + case BIO_CTRL_GET_CLOSE: + ret = b->shutdown; + break; + case BIO_CTRL_SET_CLOSE: + b->shutdown = (int)num; + break; + case BIO_CTRL_DUP: + case BIO_CTRL_FLUSH: + ret = 1; + break; + default: + ret = 0; + break; + } + return ret; +} + +static int sock_puts(BIO *bp, const char *str) +{ + int n, ret; + + n = strlen(str); + ret = sock_write(bp, str, n); + return ret; +} + +int BIO_sock_should_retry(int i) +{ + int err; + + if ((i == 0) || (i == -1)) { + err = get_last_socket_error(); + + return BIO_sock_non_fatal_error(err); + } + return 0; +} + +int BIO_sock_non_fatal_error(int err) +{ + switch (err) { +# if defined(OPENSSL_SYS_WINDOWS) +# if defined(WSAEWOULDBLOCK) + case WSAEWOULDBLOCK: +# endif +# endif + +# ifdef EWOULDBLOCK +# ifdef WSAEWOULDBLOCK +# if WSAEWOULDBLOCK != EWOULDBLOCK + case EWOULDBLOCK: +# endif +# else + case EWOULDBLOCK: +# endif +# endif + +# if defined(ENOTCONN) + case ENOTCONN: +# endif + +# ifdef EINTR + case EINTR: +# endif + +# ifdef EAGAIN +# if EWOULDBLOCK != EAGAIN + case EAGAIN: +# endif +# endif + +# ifdef EPROTO + case EPROTO: +# endif + +# ifdef EINPROGRESS + case EINPROGRESS: +# endif + +# ifdef EALREADY + case EALREADY: +# endif + return 1; + default: + break; + } + return 0; +} + +#endif /* #ifndef OPENSSL_NO_SOCK */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bio/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/build.info new file mode 100644 index 000000000..d1e7d73c5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bio/build.info @@ -0,0 +1,8 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + bio_lib.c bio_cb.c bio_err.c \ + bss_mem.c bss_null.c bss_fd.c \ + bss_file.c bss_sock.c bss_conn.c \ + bf_null.c bf_buff.c b_print.c b_dump.c b_addr.c \ + b_sock.c b_sock2.c bss_acpt.c bf_nbio.c bss_log.c bss_bio.c \ + bss_dgram.c bio_meth.c bf_lbuf.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/blake2/blake2_impl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/blake2/blake2_impl.h new file mode 100644 index 000000000..80b717e79 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/blake2/blake2_impl.h @@ -0,0 +1,129 @@ +/* + * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Derived from the BLAKE2 reference implementation written by Samuel Neves. + * Copyright 2012, Samuel Neves + * More information about the BLAKE2 hash function and its implementations + * can be found at https://blake2.net. + */ + +#include + +static ossl_inline uint32_t load32(const uint8_t *src) +{ + const union { + long one; + char little; + } is_endian = { 1 }; + + if (is_endian.little) { + uint32_t w; + memcpy(&w, src, sizeof(w)); + return w; + } else { + uint32_t w = ((uint32_t)src[0]) + | ((uint32_t)src[1] << 8) + | ((uint32_t)src[2] << 16) + | ((uint32_t)src[3] << 24); + return w; + } +} + +static ossl_inline uint64_t load64(const uint8_t *src) +{ + const union { + long one; + char little; + } is_endian = { 1 }; + + if (is_endian.little) { + uint64_t w; + memcpy(&w, src, sizeof(w)); + return w; + } else { + uint64_t w = ((uint64_t)src[0]) + | ((uint64_t)src[1] << 8) + | ((uint64_t)src[2] << 16) + | ((uint64_t)src[3] << 24) + | ((uint64_t)src[4] << 32) + | ((uint64_t)src[5] << 40) + | ((uint64_t)src[6] << 48) + | ((uint64_t)src[7] << 56); + return w; + } +} + +static ossl_inline void store32(uint8_t *dst, uint32_t w) +{ + const union { + long one; + char little; + } is_endian = { 1 }; + + if (is_endian.little) { + memcpy(dst, &w, sizeof(w)); + } else { + uint8_t *p = (uint8_t *)dst; + int i; + + for (i = 0; i < 4; i++) + p[i] = (uint8_t)(w >> (8 * i)); + } +} + +static ossl_inline void store64(uint8_t *dst, uint64_t w) +{ + const union { + long one; + char little; + } is_endian = { 1 }; + + if (is_endian.little) { + memcpy(dst, &w, sizeof(w)); + } else { + uint8_t *p = (uint8_t *)dst; + int i; + + for (i = 0; i < 8; i++) + p[i] = (uint8_t)(w >> (8 * i)); + } +} + +static ossl_inline uint64_t load48(const uint8_t *src) +{ + uint64_t w = ((uint64_t)src[0]) + | ((uint64_t)src[1] << 8) + | ((uint64_t)src[2] << 16) + | ((uint64_t)src[3] << 24) + | ((uint64_t)src[4] << 32) + | ((uint64_t)src[5] << 40); + return w; +} + +static ossl_inline void store48(uint8_t *dst, uint64_t w) +{ + uint8_t *p = (uint8_t *)dst; + p[0] = (uint8_t)w; + p[1] = (uint8_t)(w>>8); + p[2] = (uint8_t)(w>>16); + p[3] = (uint8_t)(w>>24); + p[4] = (uint8_t)(w>>32); + p[5] = (uint8_t)(w>>40); +} + +static ossl_inline uint32_t rotr32(const uint32_t w, const unsigned int c) +{ + return (w >> c) | (w << (32 - c)); +} + +static ossl_inline uint64_t rotr64(const uint64_t w, const unsigned int c) +{ + return (w >> c) | (w << (64 - c)); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/blake2/blake2_locl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/blake2/blake2_locl.h new file mode 100644 index 000000000..926bae944 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/blake2/blake2_locl.h @@ -0,0 +1,90 @@ +/* + * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Derived from the BLAKE2 reference implementation written by Samuel Neves. + * Copyright 2012, Samuel Neves + * More information about the BLAKE2 hash function and its implementations + * can be found at https://blake2.net. + */ + +#include + +#define BLAKE2S_BLOCKBYTES 64 +#define BLAKE2S_OUTBYTES 32 +#define BLAKE2S_KEYBYTES 32 +#define BLAKE2S_SALTBYTES 8 +#define BLAKE2S_PERSONALBYTES 8 + +#define BLAKE2B_BLOCKBYTES 128 +#define BLAKE2B_OUTBYTES 64 +#define BLAKE2B_KEYBYTES 64 +#define BLAKE2B_SALTBYTES 16 +#define BLAKE2B_PERSONALBYTES 16 + +struct blake2s_param_st { + uint8_t digest_length; /* 1 */ + uint8_t key_length; /* 2 */ + uint8_t fanout; /* 3 */ + uint8_t depth; /* 4 */ + uint8_t leaf_length[4];/* 8 */ + uint8_t node_offset[6];/* 14 */ + uint8_t node_depth; /* 15 */ + uint8_t inner_length; /* 16 */ + uint8_t salt[BLAKE2S_SALTBYTES]; /* 24 */ + uint8_t personal[BLAKE2S_PERSONALBYTES]; /* 32 */ +}; + +typedef struct blake2s_param_st BLAKE2S_PARAM; + +struct blake2s_ctx_st { + uint32_t h[8]; + uint32_t t[2]; + uint32_t f[2]; + uint8_t buf[BLAKE2S_BLOCKBYTES]; + size_t buflen; +}; + +struct blake2b_param_st { + uint8_t digest_length; /* 1 */ + uint8_t key_length; /* 2 */ + uint8_t fanout; /* 3 */ + uint8_t depth; /* 4 */ + uint8_t leaf_length[4];/* 8 */ + uint8_t node_offset[8];/* 16 */ + uint8_t node_depth; /* 17 */ + uint8_t inner_length; /* 18 */ + uint8_t reserved[14]; /* 32 */ + uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */ + uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */ +}; + +typedef struct blake2b_param_st BLAKE2B_PARAM; + +struct blake2b_ctx_st { + uint64_t h[8]; + uint64_t t[2]; + uint64_t f[2]; + uint8_t buf[BLAKE2B_BLOCKBYTES]; + size_t buflen; +}; + +#define BLAKE2B_DIGEST_LENGTH 64 +#define BLAKE2S_DIGEST_LENGTH 32 + +typedef struct blake2s_ctx_st BLAKE2S_CTX; +typedef struct blake2b_ctx_st BLAKE2B_CTX; + +int BLAKE2b_Init(BLAKE2B_CTX *c); +int BLAKE2b_Update(BLAKE2B_CTX *c, const void *data, size_t datalen); +int BLAKE2b_Final(unsigned char *md, BLAKE2B_CTX *c); + +int BLAKE2s_Init(BLAKE2S_CTX *c); +int BLAKE2s_Update(BLAKE2S_CTX *c, const void *data, size_t datalen); +int BLAKE2s_Final(unsigned char *md, BLAKE2S_CTX *c); diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/blake2/blake2b.c b/trunk/3rdparty/openssl-1.1-fit/crypto/blake2/blake2b.c new file mode 100644 index 000000000..829ba5b50 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/blake2/blake2b.c @@ -0,0 +1,269 @@ +/* + * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Derived from the BLAKE2 reference implementation written by Samuel Neves. + * Copyright 2012, Samuel Neves + * More information about the BLAKE2 hash function and its implementations + * can be found at https://blake2.net. + */ + +#include +#include +#include + +#include "blake2_locl.h" +#include "blake2_impl.h" + +static const uint64_t blake2b_IV[8] = +{ + 0x6a09e667f3bcc908U, 0xbb67ae8584caa73bU, + 0x3c6ef372fe94f82bU, 0xa54ff53a5f1d36f1U, + 0x510e527fade682d1U, 0x9b05688c2b3e6c1fU, + 0x1f83d9abfb41bd6bU, 0x5be0cd19137e2179U +}; + +static const uint8_t blake2b_sigma[12][16] = +{ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , + { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , + { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , + { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , + { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , + { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , + { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , + { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , + { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } +}; + +/* Set that it's the last block we'll compress */ +static ossl_inline void blake2b_set_lastblock(BLAKE2B_CTX *S) +{ + S->f[0] = -1; +} + +/* Initialize the hashing state. */ +static ossl_inline void blake2b_init0(BLAKE2B_CTX *S) +{ + int i; + + memset(S, 0, sizeof(BLAKE2B_CTX)); + for (i = 0; i < 8; ++i) { + S->h[i] = blake2b_IV[i]; + } +} + +/* init xors IV with input parameter block */ +static void blake2b_init_param(BLAKE2B_CTX *S, const BLAKE2B_PARAM *P) +{ + size_t i; + const uint8_t *p = (const uint8_t *)(P); + blake2b_init0(S); + + /* The param struct is carefully hand packed, and should be 64 bytes on + * every platform. */ + assert(sizeof(BLAKE2B_PARAM) == 64); + /* IV XOR ParamBlock */ + for (i = 0; i < 8; ++i) { + S->h[i] ^= load64(p + sizeof(S->h[i]) * i); + } +} + +/* Initialize the hashing context. Always returns 1. */ +int BLAKE2b_Init(BLAKE2B_CTX *c) +{ + BLAKE2B_PARAM P[1]; + P->digest_length = BLAKE2B_DIGEST_LENGTH; + P->key_length = 0; + P->fanout = 1; + P->depth = 1; + store32(P->leaf_length, 0); + store64(P->node_offset, 0); + P->node_depth = 0; + P->inner_length = 0; + memset(P->reserved, 0, sizeof(P->reserved)); + memset(P->salt, 0, sizeof(P->salt)); + memset(P->personal, 0, sizeof(P->personal)); + blake2b_init_param(c, P); + return 1; +} + +/* Permute the state while xoring in the block of data. */ +static void blake2b_compress(BLAKE2B_CTX *S, + const uint8_t *blocks, + size_t len) +{ + uint64_t m[16]; + uint64_t v[16]; + int i; + size_t increment; + + /* + * There are two distinct usage vectors for this function: + * + * a) BLAKE2b_Update uses it to process complete blocks, + * possibly more than one at a time; + * + * b) BLAK2b_Final uses it to process last block, always + * single but possibly incomplete, in which case caller + * pads input with zeros. + */ + assert(len < BLAKE2B_BLOCKBYTES || len % BLAKE2B_BLOCKBYTES == 0); + + /* + * Since last block is always processed with separate call, + * |len| not being multiple of complete blocks can be observed + * only with |len| being less than BLAKE2B_BLOCKBYTES ("less" + * including even zero), which is why following assignment doesn't + * have to reside inside the main loop below. + */ + increment = len < BLAKE2B_BLOCKBYTES ? len : BLAKE2B_BLOCKBYTES; + + for (i = 0; i < 8; ++i) { + v[i] = S->h[i]; + } + + do { + for (i = 0; i < 16; ++i) { + m[i] = load64(blocks + i * sizeof(m[i])); + } + + /* blake2b_increment_counter */ + S->t[0] += increment; + S->t[1] += (S->t[0] < increment); + + v[8] = blake2b_IV[0]; + v[9] = blake2b_IV[1]; + v[10] = blake2b_IV[2]; + v[11] = blake2b_IV[3]; + v[12] = S->t[0] ^ blake2b_IV[4]; + v[13] = S->t[1] ^ blake2b_IV[5]; + v[14] = S->f[0] ^ blake2b_IV[6]; + v[15] = S->f[1] ^ blake2b_IV[7]; +#define G(r,i,a,b,c,d) \ + do { \ + a = a + b + m[blake2b_sigma[r][2*i+0]]; \ + d = rotr64(d ^ a, 32); \ + c = c + d; \ + b = rotr64(b ^ c, 24); \ + a = a + b + m[blake2b_sigma[r][2*i+1]]; \ + d = rotr64(d ^ a, 16); \ + c = c + d; \ + b = rotr64(b ^ c, 63); \ + } while (0) +#define ROUND(r) \ + do { \ + G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \ + G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \ + G(r,2,v[ 2],v[ 6],v[10],v[14]); \ + G(r,3,v[ 3],v[ 7],v[11],v[15]); \ + G(r,4,v[ 0],v[ 5],v[10],v[15]); \ + G(r,5,v[ 1],v[ 6],v[11],v[12]); \ + G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \ + G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \ + } while (0) +#if defined(OPENSSL_SMALL_FOOTPRINT) + /* 3x size reduction on x86_64, almost 7x on ARMv8, 9x on ARMv4 */ + for (i = 0; i < 12; i++) { + ROUND(i); + } +#else + ROUND(0); + ROUND(1); + ROUND(2); + ROUND(3); + ROUND(4); + ROUND(5); + ROUND(6); + ROUND(7); + ROUND(8); + ROUND(9); + ROUND(10); + ROUND(11); +#endif + + for (i = 0; i < 8; ++i) { + S->h[i] = v[i] ^= v[i + 8] ^ S->h[i]; + } +#undef G +#undef ROUND + blocks += increment; + len -= increment; + } while (len); +} + +/* Absorb the input data into the hash state. Always returns 1. */ +int BLAKE2b_Update(BLAKE2B_CTX *c, const void *data, size_t datalen) +{ + const uint8_t *in = data; + size_t fill; + + /* + * Intuitively one would expect intermediate buffer, c->buf, to + * store incomplete blocks. But in this case we are interested to + * temporarily stash even complete blocks, because last one in the + * stream has to be treated in special way, and at this point we + * don't know if last block in *this* call is last one "ever". This + * is the reason for why |datalen| is compared as >, and not >=. + */ + fill = sizeof(c->buf) - c->buflen; + if (datalen > fill) { + if (c->buflen) { + memcpy(c->buf + c->buflen, in, fill); /* Fill buffer */ + blake2b_compress(c, c->buf, BLAKE2B_BLOCKBYTES); + c->buflen = 0; + in += fill; + datalen -= fill; + } + if (datalen > BLAKE2B_BLOCKBYTES) { + size_t stashlen = datalen % BLAKE2B_BLOCKBYTES; + /* + * If |datalen| is a multiple of the blocksize, stash + * last complete block, it can be final one... + */ + stashlen = stashlen ? stashlen : BLAKE2B_BLOCKBYTES; + datalen -= stashlen; + blake2b_compress(c, in, datalen); + in += datalen; + datalen = stashlen; + } + } + + assert(datalen <= BLAKE2B_BLOCKBYTES); + + memcpy(c->buf + c->buflen, in, datalen); + c->buflen += datalen; /* Be lazy, do not compress */ + + return 1; +} + +/* + * Calculate the final hash and save it in md. + * Always returns 1. + */ +int BLAKE2b_Final(unsigned char *md, BLAKE2B_CTX *c) +{ + int i; + + blake2b_set_lastblock(c); + /* Padding */ + memset(c->buf + c->buflen, 0, sizeof(c->buf) - c->buflen); + blake2b_compress(c, c->buf, c->buflen); + + /* Output full hash to message digest */ + for (i = 0; i < 8; ++i) { + store64(md + sizeof(c->h[i]) * i, c->h[i]); + } + + OPENSSL_cleanse(c, sizeof(BLAKE2B_CTX)); + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/blake2/blake2s.c b/trunk/3rdparty/openssl-1.1-fit/crypto/blake2/blake2s.c new file mode 100644 index 000000000..8211374d1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/blake2/blake2s.c @@ -0,0 +1,263 @@ +/* + * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Derived from the BLAKE2 reference implementation written by Samuel Neves. + * Copyright 2012, Samuel Neves + * More information about the BLAKE2 hash function and its implementations + * can be found at https://blake2.net. + */ + +#include +#include +#include + +#include "blake2_locl.h" +#include "blake2_impl.h" + +static const uint32_t blake2s_IV[8] = +{ + 0x6A09E667U, 0xBB67AE85U, 0x3C6EF372U, 0xA54FF53AU, + 0x510E527FU, 0x9B05688CU, 0x1F83D9ABU, 0x5BE0CD19U +}; + +static const uint8_t blake2s_sigma[10][16] = +{ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , + { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , + { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , + { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , + { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , + { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , + { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , + { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , + { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , +}; + +/* Set that it's the last block we'll compress */ +static ossl_inline void blake2s_set_lastblock(BLAKE2S_CTX *S) +{ + S->f[0] = -1; +} + +/* Initialize the hashing state. */ +static ossl_inline void blake2s_init0(BLAKE2S_CTX *S) +{ + int i; + + memset(S, 0, sizeof(BLAKE2S_CTX)); + for (i = 0; i < 8; ++i) { + S->h[i] = blake2s_IV[i]; + } +} + +/* init2 xors IV with input parameter block */ +static void blake2s_init_param(BLAKE2S_CTX *S, const BLAKE2S_PARAM *P) +{ + const uint8_t *p = (const uint8_t *)(P); + size_t i; + + /* The param struct is carefully hand packed, and should be 32 bytes on + * every platform. */ + assert(sizeof(BLAKE2S_PARAM) == 32); + blake2s_init0(S); + /* IV XOR ParamBlock */ + for (i = 0; i < 8; ++i) { + S->h[i] ^= load32(&p[i*4]); + } +} + +/* Initialize the hashing context. Always returns 1. */ +int BLAKE2s_Init(BLAKE2S_CTX *c) +{ + BLAKE2S_PARAM P[1]; + + P->digest_length = BLAKE2S_DIGEST_LENGTH; + P->key_length = 0; + P->fanout = 1; + P->depth = 1; + store32(P->leaf_length, 0); + store48(P->node_offset, 0); + P->node_depth = 0; + P->inner_length = 0; + memset(P->salt, 0, sizeof(P->salt)); + memset(P->personal, 0, sizeof(P->personal)); + blake2s_init_param(c, P); + return 1; +} + +/* Permute the state while xoring in the block of data. */ +static void blake2s_compress(BLAKE2S_CTX *S, + const uint8_t *blocks, + size_t len) +{ + uint32_t m[16]; + uint32_t v[16]; + size_t i; + size_t increment; + + /* + * There are two distinct usage vectors for this function: + * + * a) BLAKE2s_Update uses it to process complete blocks, + * possibly more than one at a time; + * + * b) BLAK2s_Final uses it to process last block, always + * single but possibly incomplete, in which case caller + * pads input with zeros. + */ + assert(len < BLAKE2S_BLOCKBYTES || len % BLAKE2S_BLOCKBYTES == 0); + + /* + * Since last block is always processed with separate call, + * |len| not being multiple of complete blocks can be observed + * only with |len| being less than BLAKE2S_BLOCKBYTES ("less" + * including even zero), which is why following assignment doesn't + * have to reside inside the main loop below. + */ + increment = len < BLAKE2S_BLOCKBYTES ? len : BLAKE2S_BLOCKBYTES; + + for (i = 0; i < 8; ++i) { + v[i] = S->h[i]; + } + + do { + for (i = 0; i < 16; ++i) { + m[i] = load32(blocks + i * sizeof(m[i])); + } + + /* blake2s_increment_counter */ + S->t[0] += increment; + S->t[1] += (S->t[0] < increment); + + v[ 8] = blake2s_IV[0]; + v[ 9] = blake2s_IV[1]; + v[10] = blake2s_IV[2]; + v[11] = blake2s_IV[3]; + v[12] = S->t[0] ^ blake2s_IV[4]; + v[13] = S->t[1] ^ blake2s_IV[5]; + v[14] = S->f[0] ^ blake2s_IV[6]; + v[15] = S->f[1] ^ blake2s_IV[7]; +#define G(r,i,a,b,c,d) \ + do { \ + a = a + b + m[blake2s_sigma[r][2*i+0]]; \ + d = rotr32(d ^ a, 16); \ + c = c + d; \ + b = rotr32(b ^ c, 12); \ + a = a + b + m[blake2s_sigma[r][2*i+1]]; \ + d = rotr32(d ^ a, 8); \ + c = c + d; \ + b = rotr32(b ^ c, 7); \ + } while (0) +#define ROUND(r) \ + do { \ + G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \ + G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \ + G(r,2,v[ 2],v[ 6],v[10],v[14]); \ + G(r,3,v[ 3],v[ 7],v[11],v[15]); \ + G(r,4,v[ 0],v[ 5],v[10],v[15]); \ + G(r,5,v[ 1],v[ 6],v[11],v[12]); \ + G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \ + G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \ + } while (0) +#if defined(OPENSSL_SMALL_FOOTPRINT) + /* almost 3x reduction on x86_64, 4.5x on ARMv8, 4x on ARMv4 */ + for (i = 0; i < 10; i++) { + ROUND(i); + } +#else + ROUND(0); + ROUND(1); + ROUND(2); + ROUND(3); + ROUND(4); + ROUND(5); + ROUND(6); + ROUND(7); + ROUND(8); + ROUND(9); +#endif + + for (i = 0; i < 8; ++i) { + S->h[i] = v[i] ^= v[i + 8] ^ S->h[i]; + } +#undef G +#undef ROUND + blocks += increment; + len -= increment; + } while (len); +} + +/* Absorb the input data into the hash state. Always returns 1. */ +int BLAKE2s_Update(BLAKE2S_CTX *c, const void *data, size_t datalen) +{ + const uint8_t *in = data; + size_t fill; + + /* + * Intuitively one would expect intermediate buffer, c->buf, to + * store incomplete blocks. But in this case we are interested to + * temporarily stash even complete blocks, because last one in the + * stream has to be treated in special way, and at this point we + * don't know if last block in *this* call is last one "ever". This + * is the reason for why |datalen| is compared as >, and not >=. + */ + fill = sizeof(c->buf) - c->buflen; + if (datalen > fill) { + if (c->buflen) { + memcpy(c->buf + c->buflen, in, fill); /* Fill buffer */ + blake2s_compress(c, c->buf, BLAKE2S_BLOCKBYTES); + c->buflen = 0; + in += fill; + datalen -= fill; + } + if (datalen > BLAKE2S_BLOCKBYTES) { + size_t stashlen = datalen % BLAKE2S_BLOCKBYTES; + /* + * If |datalen| is a multiple of the blocksize, stash + * last complete block, it can be final one... + */ + stashlen = stashlen ? stashlen : BLAKE2S_BLOCKBYTES; + datalen -= stashlen; + blake2s_compress(c, in, datalen); + in += datalen; + datalen = stashlen; + } + } + + assert(datalen <= BLAKE2S_BLOCKBYTES); + + memcpy(c->buf + c->buflen, in, datalen); + c->buflen += datalen; /* Be lazy, do not compress */ + + return 1; +} + +/* + * Calculate the final hash and save it in md. + * Always returns 1. + */ +int BLAKE2s_Final(unsigned char *md, BLAKE2S_CTX *c) +{ + int i; + + blake2s_set_lastblock(c); + /* Padding */ + memset(c->buf + c->buflen, 0, sizeof(c->buf) - c->buflen); + blake2s_compress(c, c->buf, c->buflen); + + /* Output full hash to temp buffer */ + for (i = 0; i < 8; ++i) { + store32(md + sizeof(c->h[i]) * i, c->h[i]); + } + + OPENSSL_cleanse(c, sizeof(BLAKE2S_CTX)); + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/blake2/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/blake2/build.info new file mode 100644 index 000000000..0036f0848 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/blake2/build.info @@ -0,0 +1,3 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + blake2b.c blake2s.c m_blake2b.c m_blake2s.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/blake2/m_blake2b.c b/trunk/3rdparty/openssl-1.1-fit/crypto/blake2/m_blake2b.c new file mode 100644 index 000000000..c493648c3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/blake2/m_blake2b.c @@ -0,0 +1,59 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Derived from the BLAKE2 reference implementation written by Samuel Neves. + * Copyright 2012, Samuel Neves + * More information about the BLAKE2 hash function and its implementations + * can be found at https://blake2.net. + */ + +#include "internal/cryptlib.h" + +#ifndef OPENSSL_NO_BLAKE2 + +# include +# include +# include "blake2_locl.h" +# include "internal/evp_int.h" + +static int init(EVP_MD_CTX *ctx) +{ + return BLAKE2b_Init(EVP_MD_CTX_md_data(ctx)); +} + +static int update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ + return BLAKE2b_Update(EVP_MD_CTX_md_data(ctx), data, count); +} + +static int final(EVP_MD_CTX *ctx, unsigned char *md) +{ + return BLAKE2b_Final(md, EVP_MD_CTX_md_data(ctx)); +} + +static const EVP_MD blake2b_md = { + NID_blake2b512, + 0, + BLAKE2B_DIGEST_LENGTH, + 0, + init, + update, + final, + NULL, + NULL, + BLAKE2B_BLOCKBYTES, + sizeof(EVP_MD *) + sizeof(BLAKE2B_CTX), +}; + +const EVP_MD *EVP_blake2b512(void) +{ + return &blake2b_md; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/blake2/m_blake2s.c b/trunk/3rdparty/openssl-1.1-fit/crypto/blake2/m_blake2s.c new file mode 100644 index 000000000..83b2811e4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/blake2/m_blake2s.c @@ -0,0 +1,59 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Derived from the BLAKE2 reference implementation written by Samuel Neves. + * Copyright 2012, Samuel Neves + * More information about the BLAKE2 hash function and its implementations + * can be found at https://blake2.net. + */ + +#include "internal/cryptlib.h" + +#ifndef OPENSSL_NO_BLAKE2 + +# include +# include +# include "blake2_locl.h" +# include "internal/evp_int.h" + +static int init(EVP_MD_CTX *ctx) +{ + return BLAKE2s_Init(EVP_MD_CTX_md_data(ctx)); +} + +static int update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ + return BLAKE2s_Update(EVP_MD_CTX_md_data(ctx), data, count); +} + +static int final(EVP_MD_CTX *ctx, unsigned char *md) +{ + return BLAKE2s_Final(md, EVP_MD_CTX_md_data(ctx)); +} + +static const EVP_MD blake2s_md = { + NID_blake2s256, + 0, + BLAKE2S_DIGEST_LENGTH, + 0, + init, + update, + final, + NULL, + NULL, + BLAKE2S_BLOCKBYTES, + sizeof(EVP_MD *) + sizeof(BLAKE2S_CTX), +}; + +const EVP_MD *EVP_blake2s256(void) +{ + return &blake2s_md; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/README.pod b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/README.pod new file mode 100644 index 000000000..706a14034 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/README.pod @@ -0,0 +1,241 @@ +=pod + +=head1 NAME + +bn_mul_words, bn_mul_add_words, bn_sqr_words, bn_div_words, +bn_add_words, bn_sub_words, bn_mul_comba4, bn_mul_comba8, +bn_sqr_comba4, bn_sqr_comba8, bn_cmp_words, bn_mul_normal, +bn_mul_low_normal, bn_mul_recursive, bn_mul_part_recursive, +bn_mul_low_recursive, bn_sqr_normal, bn_sqr_recursive, +bn_expand, bn_wexpand, bn_expand2, bn_fix_top, bn_check_top, +bn_print, bn_dump, bn_set_max, bn_set_high, bn_set_low - BIGNUM +library internal functions + +=head1 SYNOPSIS + + #include + + BN_ULONG bn_mul_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w); + BN_ULONG bn_mul_add_words(BN_ULONG *rp, BN_ULONG *ap, int num, + BN_ULONG w); + void bn_sqr_words(BN_ULONG *rp, BN_ULONG *ap, int num); + BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d); + BN_ULONG bn_add_words(BN_ULONG *rp, BN_ULONG *ap, BN_ULONG *bp, + int num); + BN_ULONG bn_sub_words(BN_ULONG *rp, BN_ULONG *ap, BN_ULONG *bp, + int num); + + void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b); + void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b); + void bn_sqr_comba4(BN_ULONG *r, BN_ULONG *a); + void bn_sqr_comba8(BN_ULONG *r, BN_ULONG *a); + + int bn_cmp_words(BN_ULONG *a, BN_ULONG *b, int n); + + void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, + int nb); + void bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n); + void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2, + int dna, int dnb, BN_ULONG *tmp); + void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, + int n, int tna, int tnb, BN_ULONG *tmp); + void bn_mul_low_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, + int n2, BN_ULONG *tmp); + + void bn_sqr_normal(BN_ULONG *r, BN_ULONG *a, int n, BN_ULONG *tmp); + void bn_sqr_recursive(BN_ULONG *r, BN_ULONG *a, int n2, BN_ULONG *tmp); + + void mul(BN_ULONG r, BN_ULONG a, BN_ULONG w, BN_ULONG c); + void mul_add(BN_ULONG r, BN_ULONG a, BN_ULONG w, BN_ULONG c); + void sqr(BN_ULONG r0, BN_ULONG r1, BN_ULONG a); + + BIGNUM *bn_expand(BIGNUM *a, int bits); + BIGNUM *bn_wexpand(BIGNUM *a, int n); + BIGNUM *bn_expand2(BIGNUM *a, int n); + void bn_fix_top(BIGNUM *a); + + void bn_check_top(BIGNUM *a); + void bn_print(BIGNUM *a); + void bn_dump(BN_ULONG *d, int n); + void bn_set_max(BIGNUM *a); + void bn_set_high(BIGNUM *r, BIGNUM *a, int n); + void bn_set_low(BIGNUM *r, BIGNUM *a, int n); + +=head1 DESCRIPTION + +This page documents the internal functions used by the OpenSSL +B implementation. They are described here to facilitate +debugging and extending the library. They are I to be used by +applications. + +=head2 The BIGNUM structure + + typedef struct bignum_st BIGNUM; + + struct bignum_st + { + BN_ULONG *d; /* Pointer to an array of 'BN_BITS2' bit chunks. */ + int top; /* Index of last used d +1. */ + /* The next are internal book keeping for bn_expand. */ + int dmax; /* Size of the d array. */ + int neg; /* one if the number is negative */ + int flags; + }; + + +The integer value is stored in B, a malloc()ed array of words (B), +least significant word first. A B can be either 16, 32 or 64 bits +in size, depending on the 'number of bits' (B) specified in +C. + +B is the size of the B array that has been allocated. B +is the number of words being used, so for a value of 4, bn.d[0]=4 and +bn.top=1. B is 1 if the number is negative. When a B is +B<0>, the B field can be B and B == B<0>. + +B is a bit field of flags which are defined in C. The +flags begin with B. The macros BN_set_flags(b, n) and +BN_get_flags(b, n) exist to enable or fetch flag(s) B from B +structure B. + +Various routines in this library require the use of temporary +B variables during their execution. Since dynamic memory +allocation to create Bs is rather expensive when used in +conjunction with repeated subroutine calls, the B structure is +used. This structure contains B Bs, see +L. + +=head2 Low-level arithmetic operations + +These functions are implemented in C and for several platforms in +assembly language: + +bn_mul_words(B, B, B, B) operates on the B word +arrays B and B. It computes B * B, places the result +in B, and returns the high word (carry). + +bn_mul_add_words(B, B, B, B) operates on the B +word arrays B and B. It computes B * B + B, places +the result in B, and returns the high word (carry). + +bn_sqr_words(B, B, B) operates on the B word array +B and the 2*B word array B. It computes B * B +word-wise, and places the low and high bytes of the result in B. + +bn_div_words(B, B, B) divides the two word number (B, B) +by B and returns the result. + +bn_add_words(B, B, B, B) operates on the B word +arrays B, B and B. It computes B + B, places the +result in B, and returns the high word (carry). + +bn_sub_words(B, B, B, B) operates on the B word +arrays B, B and B. It computes B - B, places the +result in B, and returns the carry (1 if B E B, 0 +otherwise). + +bn_mul_comba4(B, B, B) operates on the 4 word arrays B and +B and the 8 word array B. It computes B*B and places the +result in B. + +bn_mul_comba8(B, B, B) operates on the 8 word arrays B and +B and the 16 word array B. It computes B*B and places the +result in B. + +bn_sqr_comba4(B, B, B) operates on the 4 word arrays B and +B and the 8 word array B. + +bn_sqr_comba8(B, B, B) operates on the 8 word arrays B and +B and the 16 word array B. + +The following functions are implemented in C: + +bn_cmp_words(B, B, B) operates on the B word arrays B +and B. It returns 1, 0 and -1 if B is greater than, equal and +less than B. + +bn_mul_normal(B, B, B, B, B) operates on the B +word array B, the B word array B and the B+B word +array B. It computes B*B and places the result in B. + +bn_mul_low_normal(B, B, B, B) operates on the B word +arrays B, B and B. It computes the B low words of +B*B and places the result in B. + +bn_mul_recursive(B, B, B, B, B, B, B) operates +on the word arrays B and B of length B+B and B+B +(B and B are currently allowed to be 0 or negative) and the 2*B +word arrays B and B. B must be a power of 2. It computes +B*B and places the result in B. + +bn_mul_part_recursive(B, B, B, B, B, B, B) +operates on the word arrays B and B of length B+B and +B+B and the 4*B word arrays B and B. + +bn_mul_low_recursive(B, B, B, B, B) operates on the +B word arrays B and B and the B/2 word arrays B +and B. + +BN_mul() calls bn_mul_normal(), or an optimized implementation if the +factors have the same size: bn_mul_comba8() is used if they are 8 +words long, bn_mul_recursive() if they are larger than +B and the size is an exact multiple of the word +size, and bn_mul_part_recursive() for others that are larger than +B. + +bn_sqr_normal(B, B, B, B) operates on the B word array +B and the 2*B word arrays B and B. + +The implementations use the following macros which, depending on the +architecture, may use "long long" C operations or inline assembler. +They are defined in C. + +mul(B, B, B, B) computes B*B+B and places the +low word of the result in B and the high word in B. + +mul_add(B, B, B, B) computes B*B+B+B and +places the low word of the result in B and the high word in B. + +sqr(B, B, B) computes B*B and places the low word +of the result in B and the high word in B. + +=head2 Size changes + +bn_expand() ensures that B has enough space for a B bit +number. bn_wexpand() ensures that B has enough space for an +B word number. If the number has to be expanded, both macros +call bn_expand2(), which allocates a new B array and copies the +data. They return B on error, B otherwise. + +The bn_fix_top() macro reduces Btop> to point to the most +significant non-zero word plus one when B has shrunk. + +=head2 Debugging + +bn_check_top() verifies that C<((a)-Etop E= 0 && (a)-Etop +E= (a)-Edmax)>. A violation will cause the program to abort. + +bn_print() prints B to stderr. bn_dump() prints B words at B +(in reverse order, i.e. most significant word first) to stderr. + +bn_set_max() makes B a static number with a B of its current size. +This is used by bn_set_low() and bn_set_high() to make B a read-only +B that contains the B low or high words of B. + +If B is not defined, bn_check_top(), bn_print(), bn_dump() +and bn_set_max() are defined as empty macros. + +=head1 SEE ALSO + +L + +=head1 COPYRIGHT + +Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the OpenSSL license (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/alpha-mont.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/alpha-mont.pl new file mode 100644 index 000000000..c9b962a15 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/alpha-mont.pl @@ -0,0 +1,328 @@ +#! /usr/bin/env perl +# Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# On 21264 RSA sign performance improves by 70/35/20/15 percent for +# 512/1024/2048/4096 bit key lengths. This is against vendor compiler +# instructed to '-tune host' code with in-line assembler. Other +# benchmarks improve by 15-20%. To anchor it to something else, the +# code provides approximately the same performance per GHz as AMD64. +# I.e. if you compare 1GHz 21264 and 2GHz Opteron, you'll observe ~2x +# difference. + +$output=pop; +open STDOUT,">$output"; + +# int bn_mul_mont( +$rp="a0"; # BN_ULONG *rp, +$ap="a1"; # const BN_ULONG *ap, +$bp="a2"; # const BN_ULONG *bp, +$np="a3"; # const BN_ULONG *np, +$n0="a4"; # const BN_ULONG *n0, +$num="a5"; # int num); + +$lo0="t0"; +$hi0="t1"; +$lo1="t2"; +$hi1="t3"; +$aj="t4"; +$bi="t5"; +$nj="t6"; +$tp="t7"; +$alo="t8"; +$ahi="t9"; +$nlo="t10"; +$nhi="t11"; +$tj="t12"; +$i="s3"; +$j="s4"; +$m1="s5"; + +$code=<<___; +#ifdef __linux__ +#include +#else +#include +#include +#endif + +.text + +.set noat +.set noreorder + +.globl bn_mul_mont +.align 5 +.ent bn_mul_mont +bn_mul_mont: + lda sp,-48(sp) + stq ra,0(sp) + stq s3,8(sp) + stq s4,16(sp) + stq s5,24(sp) + stq fp,32(sp) + mov sp,fp + .mask 0x0400f000,-48 + .frame fp,48,ra + .prologue 0 + + .align 4 + .set reorder + sextl $num,$num + mov 0,v0 + cmplt $num,4,AT + bne AT,.Lexit + + ldq $hi0,0($ap) # ap[0] + s8addq $num,16,AT + ldq $aj,8($ap) + subq sp,AT,sp + ldq $bi,0($bp) # bp[0] + lda AT,-4096(zero) # mov -4096,AT + ldq $n0,0($n0) + and sp,AT,sp + + mulq $hi0,$bi,$lo0 + ldq $hi1,0($np) # np[0] + umulh $hi0,$bi,$hi0 + ldq $nj,8($np) + + mulq $lo0,$n0,$m1 + + mulq $hi1,$m1,$lo1 + umulh $hi1,$m1,$hi1 + + addq $lo1,$lo0,$lo1 + cmpult $lo1,$lo0,AT + addq $hi1,AT,$hi1 + + mulq $aj,$bi,$alo + mov 2,$j + umulh $aj,$bi,$ahi + mov sp,$tp + + mulq $nj,$m1,$nlo + s8addq $j,$ap,$aj + umulh $nj,$m1,$nhi + s8addq $j,$np,$nj +.align 4 +.L1st: + .set noreorder + ldq $aj,0($aj) + addl $j,1,$j + ldq $nj,0($nj) + lda $tp,8($tp) + + addq $alo,$hi0,$lo0 + mulq $aj,$bi,$alo + cmpult $lo0,$hi0,AT + addq $nlo,$hi1,$lo1 + + mulq $nj,$m1,$nlo + addq $ahi,AT,$hi0 + cmpult $lo1,$hi1,v0 + cmplt $j,$num,$tj + + umulh $aj,$bi,$ahi + addq $nhi,v0,$hi1 + addq $lo1,$lo0,$lo1 + s8addq $j,$ap,$aj + + umulh $nj,$m1,$nhi + cmpult $lo1,$lo0,v0 + addq $hi1,v0,$hi1 + s8addq $j,$np,$nj + + stq $lo1,-8($tp) + nop + unop + bne $tj,.L1st + .set reorder + + addq $alo,$hi0,$lo0 + addq $nlo,$hi1,$lo1 + cmpult $lo0,$hi0,AT + cmpult $lo1,$hi1,v0 + addq $ahi,AT,$hi0 + addq $nhi,v0,$hi1 + + addq $lo1,$lo0,$lo1 + cmpult $lo1,$lo0,v0 + addq $hi1,v0,$hi1 + + stq $lo1,0($tp) + + addq $hi1,$hi0,$hi1 + cmpult $hi1,$hi0,AT + stq $hi1,8($tp) + stq AT,16($tp) + + mov 1,$i +.align 4 +.Louter: + s8addq $i,$bp,$bi + ldq $hi0,0($ap) + ldq $aj,8($ap) + ldq $bi,0($bi) + ldq $hi1,0($np) + ldq $nj,8($np) + ldq $tj,0(sp) + + mulq $hi0,$bi,$lo0 + umulh $hi0,$bi,$hi0 + + addq $lo0,$tj,$lo0 + cmpult $lo0,$tj,AT + addq $hi0,AT,$hi0 + + mulq $lo0,$n0,$m1 + + mulq $hi1,$m1,$lo1 + umulh $hi1,$m1,$hi1 + + addq $lo1,$lo0,$lo1 + cmpult $lo1,$lo0,AT + mov 2,$j + addq $hi1,AT,$hi1 + + mulq $aj,$bi,$alo + mov sp,$tp + umulh $aj,$bi,$ahi + + mulq $nj,$m1,$nlo + s8addq $j,$ap,$aj + umulh $nj,$m1,$nhi +.align 4 +.Linner: + .set noreorder + ldq $tj,8($tp) #L0 + nop #U1 + ldq $aj,0($aj) #L1 + s8addq $j,$np,$nj #U0 + + ldq $nj,0($nj) #L0 + nop #U1 + addq $alo,$hi0,$lo0 #L1 + lda $tp,8($tp) + + mulq $aj,$bi,$alo #U1 + cmpult $lo0,$hi0,AT #L0 + addq $nlo,$hi1,$lo1 #L1 + addl $j,1,$j + + mulq $nj,$m1,$nlo #U1 + addq $ahi,AT,$hi0 #L0 + addq $lo0,$tj,$lo0 #L1 + cmpult $lo1,$hi1,v0 #U0 + + umulh $aj,$bi,$ahi #U1 + cmpult $lo0,$tj,AT #L0 + addq $lo1,$lo0,$lo1 #L1 + addq $nhi,v0,$hi1 #U0 + + umulh $nj,$m1,$nhi #U1 + s8addq $j,$ap,$aj #L0 + cmpult $lo1,$lo0,v0 #L1 + cmplt $j,$num,$tj #U0 # borrow $tj + + addq $hi0,AT,$hi0 #L0 + addq $hi1,v0,$hi1 #U1 + stq $lo1,-8($tp) #L1 + bne $tj,.Linner #U0 + .set reorder + + ldq $tj,8($tp) + addq $alo,$hi0,$lo0 + addq $nlo,$hi1,$lo1 + cmpult $lo0,$hi0,AT + cmpult $lo1,$hi1,v0 + addq $ahi,AT,$hi0 + addq $nhi,v0,$hi1 + + addq $lo0,$tj,$lo0 + cmpult $lo0,$tj,AT + addq $hi0,AT,$hi0 + + ldq $tj,16($tp) + addq $lo1,$lo0,$j + cmpult $j,$lo0,v0 + addq $hi1,v0,$hi1 + + addq $hi1,$hi0,$lo1 + stq $j,0($tp) + cmpult $lo1,$hi0,$hi1 + addq $lo1,$tj,$lo1 + cmpult $lo1,$tj,AT + addl $i,1,$i + addq $hi1,AT,$hi1 + stq $lo1,8($tp) + cmplt $i,$num,$tj # borrow $tj + stq $hi1,16($tp) + bne $tj,.Louter + + s8addq $num,sp,$tj # &tp[num] + mov $rp,$bp # put rp aside + mov sp,$tp + mov sp,$ap + mov 0,$hi0 # clear borrow bit + +.align 4 +.Lsub: ldq $lo0,0($tp) + ldq $lo1,0($np) + lda $tp,8($tp) + lda $np,8($np) + subq $lo0,$lo1,$lo1 # tp[i]-np[i] + cmpult $lo0,$lo1,AT + subq $lo1,$hi0,$lo0 + cmpult $lo1,$lo0,$hi0 + or $hi0,AT,$hi0 + stq $lo0,0($rp) + cmpult $tp,$tj,v0 + lda $rp,8($rp) + bne v0,.Lsub + + subq $hi1,$hi0,$hi0 # handle upmost overflow bit + mov sp,$tp + mov $bp,$rp # restore rp + +.align 4 +.Lcopy: ldq $aj,0($tp) # conditional copy + ldq $nj,0($rp) + lda $tp,8($tp) + lda $rp,8($rp) + cmoveq $hi0,$nj,$aj + stq zero,-8($tp) # zap tp + cmpult $tp,$tj,AT + stq $aj,-8($rp) + bne AT,.Lcopy + mov 1,v0 + +.Lexit: + .set noreorder + mov fp,sp + /*ldq ra,0(sp)*/ + ldq s3,8(sp) + ldq s4,16(sp) + ldq s5,24(sp) + ldq fp,32(sp) + lda sp,48(sp) + ret (ra) +.end bn_mul_mont +.ascii "Montgomery Multiplication for Alpha, CRYPTOGAMS by " +.align 2 +___ + +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/armv4-gf2m.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/armv4-gf2m.pl new file mode 100644 index 000000000..7a0cdb2e8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/armv4-gf2m.pl @@ -0,0 +1,332 @@ +#! /usr/bin/env perl +# Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# May 2011 +# +# The module implements bn_GF2m_mul_2x2 polynomial multiplication +# used in bn_gf2m.c. It's kind of low-hanging mechanical port from +# C for the time being... Except that it has two code paths: pure +# integer code suitable for any ARMv4 and later CPU and NEON code +# suitable for ARMv7. Pure integer 1x1 multiplication subroutine runs +# in ~45 cycles on dual-issue core such as Cortex A8, which is ~50% +# faster than compiler-generated code. For ECDH and ECDSA verify (but +# not for ECDSA sign) it means 25%-45% improvement depending on key +# length, more for longer keys. Even though NEON 1x1 multiplication +# runs in even less cycles, ~30, improvement is measurable only on +# longer keys. One has to optimize code elsewhere to get NEON glow... +# +# April 2014 +# +# Double bn_GF2m_mul_2x2 performance by using algorithm from paper +# referred below, which improves ECDH and ECDSA verify benchmarks +# by 18-40%. +# +# Câmara, D.; Gouvêa, C. P. L.; López, J. & Dahab, R.: Fast Software +# Polynomial Multiplication on ARM Processors using the NEON Engine. +# +# http://conradoplg.cryptoland.net/files/2010/12/mocrysen13.pdf + +$flavour = shift; +if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + open STDOUT,">$output"; +} + +$code=<<___; +#include "arm_arch.h" + +.text +#if defined(__thumb2__) +.syntax unified +.thumb +#else +.code 32 +#endif +___ +################ +# private interface to mul_1x1_ialu +# +$a="r1"; +$b="r0"; + +($a0,$a1,$a2,$a12,$a4,$a14)= +($hi,$lo,$t0,$t1, $i0,$i1 )=map("r$_",(4..9),12); + +$mask="r12"; + +$code.=<<___; +.type mul_1x1_ialu,%function +.align 5 +mul_1x1_ialu: + mov $a0,#0 + bic $a1,$a,#3<<30 @ a1=a&0x3fffffff + str $a0,[sp,#0] @ tab[0]=0 + add $a2,$a1,$a1 @ a2=a1<<1 + str $a1,[sp,#4] @ tab[1]=a1 + eor $a12,$a1,$a2 @ a1^a2 + str $a2,[sp,#8] @ tab[2]=a2 + mov $a4,$a1,lsl#2 @ a4=a1<<2 + str $a12,[sp,#12] @ tab[3]=a1^a2 + eor $a14,$a1,$a4 @ a1^a4 + str $a4,[sp,#16] @ tab[4]=a4 + eor $a0,$a2,$a4 @ a2^a4 + str $a14,[sp,#20] @ tab[5]=a1^a4 + eor $a12,$a12,$a4 @ a1^a2^a4 + str $a0,[sp,#24] @ tab[6]=a2^a4 + and $i0,$mask,$b,lsl#2 + str $a12,[sp,#28] @ tab[7]=a1^a2^a4 + + and $i1,$mask,$b,lsr#1 + ldr $lo,[sp,$i0] @ tab[b & 0x7] + and $i0,$mask,$b,lsr#4 + ldr $t1,[sp,$i1] @ tab[b >> 3 & 0x7] + and $i1,$mask,$b,lsr#7 + ldr $t0,[sp,$i0] @ tab[b >> 6 & 0x7] + eor $lo,$lo,$t1,lsl#3 @ stall + mov $hi,$t1,lsr#29 + ldr $t1,[sp,$i1] @ tab[b >> 9 & 0x7] + + and $i0,$mask,$b,lsr#10 + eor $lo,$lo,$t0,lsl#6 + eor $hi,$hi,$t0,lsr#26 + ldr $t0,[sp,$i0] @ tab[b >> 12 & 0x7] + + and $i1,$mask,$b,lsr#13 + eor $lo,$lo,$t1,lsl#9 + eor $hi,$hi,$t1,lsr#23 + ldr $t1,[sp,$i1] @ tab[b >> 15 & 0x7] + + and $i0,$mask,$b,lsr#16 + eor $lo,$lo,$t0,lsl#12 + eor $hi,$hi,$t0,lsr#20 + ldr $t0,[sp,$i0] @ tab[b >> 18 & 0x7] + + and $i1,$mask,$b,lsr#19 + eor $lo,$lo,$t1,lsl#15 + eor $hi,$hi,$t1,lsr#17 + ldr $t1,[sp,$i1] @ tab[b >> 21 & 0x7] + + and $i0,$mask,$b,lsr#22 + eor $lo,$lo,$t0,lsl#18 + eor $hi,$hi,$t0,lsr#14 + ldr $t0,[sp,$i0] @ tab[b >> 24 & 0x7] + + and $i1,$mask,$b,lsr#25 + eor $lo,$lo,$t1,lsl#21 + eor $hi,$hi,$t1,lsr#11 + ldr $t1,[sp,$i1] @ tab[b >> 27 & 0x7] + + tst $a,#1<<30 + and $i0,$mask,$b,lsr#28 + eor $lo,$lo,$t0,lsl#24 + eor $hi,$hi,$t0,lsr#8 + ldr $t0,[sp,$i0] @ tab[b >> 30 ] + +#ifdef __thumb2__ + itt ne +#endif + eorne $lo,$lo,$b,lsl#30 + eorne $hi,$hi,$b,lsr#2 + tst $a,#1<<31 + eor $lo,$lo,$t1,lsl#27 + eor $hi,$hi,$t1,lsr#5 +#ifdef __thumb2__ + itt ne +#endif + eorne $lo,$lo,$b,lsl#31 + eorne $hi,$hi,$b,lsr#1 + eor $lo,$lo,$t0,lsl#30 + eor $hi,$hi,$t0,lsr#2 + + mov pc,lr +.size mul_1x1_ialu,.-mul_1x1_ialu +___ +################ +# void bn_GF2m_mul_2x2(BN_ULONG *r, +# BN_ULONG a1,BN_ULONG a0, +# BN_ULONG b1,BN_ULONG b0); # r[3..0]=a1a0·b1b0 +{ +$code.=<<___; +.global bn_GF2m_mul_2x2 +.type bn_GF2m_mul_2x2,%function +.align 5 +bn_GF2m_mul_2x2: +#if __ARM_MAX_ARCH__>=7 + stmdb sp!,{r10,lr} + ldr r12,.LOPENSSL_armcap + adr r10,.LOPENSSL_armcap + ldr r12,[r12,r10] +#ifdef __APPLE__ + ldr r12,[r12] +#endif + tst r12,#ARMV7_NEON + itt ne + ldrne r10,[sp],#8 + bne .LNEON + stmdb sp!,{r4-r9} +#else + stmdb sp!,{r4-r10,lr} +#endif +___ +$ret="r10"; # reassigned 1st argument +$code.=<<___; + mov $ret,r0 @ reassign 1st argument + mov $b,r3 @ $b=b1 + sub r7,sp,#36 + mov r8,sp + and r7,r7,#-32 + ldr r3,[sp,#32] @ load b0 + mov $mask,#7<<2 + mov sp,r7 @ allocate tab[8] + str r8,[r7,#32] + + bl mul_1x1_ialu @ a1·b1 + str $lo,[$ret,#8] + str $hi,[$ret,#12] + + eor $b,$b,r3 @ flip b0 and b1 + eor $a,$a,r2 @ flip a0 and a1 + eor r3,r3,$b + eor r2,r2,$a + eor $b,$b,r3 + eor $a,$a,r2 + bl mul_1x1_ialu @ a0·b0 + str $lo,[$ret] + str $hi,[$ret,#4] + + eor $a,$a,r2 + eor $b,$b,r3 + bl mul_1x1_ialu @ (a1+a0)·(b1+b0) +___ +@r=map("r$_",(6..9)); +$code.=<<___; + ldmia $ret,{@r[0]-@r[3]} + eor $lo,$lo,$hi + ldr sp,[sp,#32] @ destroy tab[8] + eor $hi,$hi,@r[1] + eor $lo,$lo,@r[0] + eor $hi,$hi,@r[2] + eor $lo,$lo,@r[3] + eor $hi,$hi,@r[3] + str $hi,[$ret,#8] + eor $lo,$lo,$hi + str $lo,[$ret,#4] + +#if __ARM_ARCH__>=5 + ldmia sp!,{r4-r10,pc} +#else + ldmia sp!,{r4-r10,lr} + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +___ +} +{ +my ($r,$t0,$t1,$t2,$t3)=map("q$_",(0..3,8..12)); +my ($a,$b,$k48,$k32,$k16)=map("d$_",(26..31)); + +$code.=<<___; +#if __ARM_MAX_ARCH__>=7 +.arch armv7-a +.fpu neon + +.align 5 +.LNEON: + ldr r12, [sp] @ 5th argument + vmov $a, r2, r1 + vmov $b, r12, r3 + vmov.i64 $k48, #0x0000ffffffffffff + vmov.i64 $k32, #0x00000000ffffffff + vmov.i64 $k16, #0x000000000000ffff + + vext.8 $t0#lo, $a, $a, #1 @ A1 + vmull.p8 $t0, $t0#lo, $b @ F = A1*B + vext.8 $r#lo, $b, $b, #1 @ B1 + vmull.p8 $r, $a, $r#lo @ E = A*B1 + vext.8 $t1#lo, $a, $a, #2 @ A2 + vmull.p8 $t1, $t1#lo, $b @ H = A2*B + vext.8 $t3#lo, $b, $b, #2 @ B2 + vmull.p8 $t3, $a, $t3#lo @ G = A*B2 + vext.8 $t2#lo, $a, $a, #3 @ A3 + veor $t0, $t0, $r @ L = E + F + vmull.p8 $t2, $t2#lo, $b @ J = A3*B + vext.8 $r#lo, $b, $b, #3 @ B3 + veor $t1, $t1, $t3 @ M = G + H + vmull.p8 $r, $a, $r#lo @ I = A*B3 + veor $t0#lo, $t0#lo, $t0#hi @ t0 = (L) (P0 + P1) << 8 + vand $t0#hi, $t0#hi, $k48 + vext.8 $t3#lo, $b, $b, #4 @ B4 + veor $t1#lo, $t1#lo, $t1#hi @ t1 = (M) (P2 + P3) << 16 + vand $t1#hi, $t1#hi, $k32 + vmull.p8 $t3, $a, $t3#lo @ K = A*B4 + veor $t2, $t2, $r @ N = I + J + veor $t0#lo, $t0#lo, $t0#hi + veor $t1#lo, $t1#lo, $t1#hi + veor $t2#lo, $t2#lo, $t2#hi @ t2 = (N) (P4 + P5) << 24 + vand $t2#hi, $t2#hi, $k16 + vext.8 $t0, $t0, $t0, #15 + veor $t3#lo, $t3#lo, $t3#hi @ t3 = (K) (P6 + P7) << 32 + vmov.i64 $t3#hi, #0 + vext.8 $t1, $t1, $t1, #14 + veor $t2#lo, $t2#lo, $t2#hi + vmull.p8 $r, $a, $b @ D = A*B + vext.8 $t3, $t3, $t3, #12 + vext.8 $t2, $t2, $t2, #13 + veor $t0, $t0, $t1 + veor $t2, $t2, $t3 + veor $r, $r, $t0 + veor $r, $r, $t2 + + vst1.32 {$r}, [r0] + ret @ bx lr +#endif +___ +} +$code.=<<___; +.size bn_GF2m_mul_2x2,.-bn_GF2m_mul_2x2 +#if __ARM_MAX_ARCH__>=7 +.align 5 +.LOPENSSL_armcap: +.word OPENSSL_armcap_P-. +#endif +.asciz "GF(2^m) Multiplication for ARMv4/NEON, CRYPTOGAMS by " +.align 5 + +#if __ARM_MAX_ARCH__>=7 +.comm OPENSSL_armcap_P,4,4 +#endif +___ + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/geo; + + s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo or + s/\bret\b/bx lr/go or + s/\bbx\s+lr\b/.word\t0xe12fff1e/go; # make it possible to compile with -march=armv4 + + print $_,"\n"; +} +close STDOUT; # enforce flush diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/armv4-mont.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/armv4-mont.pl new file mode 100644 index 000000000..6bedc62ba --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/armv4-mont.pl @@ -0,0 +1,757 @@ +#! /usr/bin/env perl +# Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# January 2007. + +# Montgomery multiplication for ARMv4. +# +# Performance improvement naturally varies among CPU implementations +# and compilers. The code was observed to provide +65-35% improvement +# [depending on key length, less for longer keys] on ARM920T, and +# +115-80% on Intel IXP425. This is compared to pre-bn_mul_mont code +# base and compiler generated code with in-lined umull and even umlal +# instructions. The latter means that this code didn't really have an +# "advantage" of utilizing some "secret" instruction. +# +# The code is interoperable with Thumb ISA and is rather compact, less +# than 1/2KB. Windows CE port would be trivial, as it's exclusively +# about decorations, ABI and instruction syntax are identical. + +# November 2013 +# +# Add NEON code path, which handles lengths divisible by 8. RSA/DSA +# performance improvement on Cortex-A8 is ~45-100% depending on key +# length, more for longer keys. On Cortex-A15 the span is ~10-105%. +# On Snapdragon S4 improvement was measured to vary from ~70% to +# incredible ~380%, yes, 4.8x faster, for RSA4096 sign. But this is +# rather because original integer-only code seems to perform +# suboptimally on S4. Situation on Cortex-A9 is unfortunately +# different. It's being looked into, but the trouble is that +# performance for vectors longer than 256 bits is actually couple +# of percent worse than for integer-only code. The code is chosen +# for execution on all NEON-capable processors, because gain on +# others outweighs the marginal loss on Cortex-A9. + +# September 2015 +# +# Align Cortex-A9 performance with November 2013 improvements, i.e. +# NEON code is now ~20-105% faster than integer-only one on this +# processor. But this optimization further improved performance even +# on other processors: NEON code path is ~45-180% faster than original +# integer-only on Cortex-A8, ~10-210% on Cortex-A15, ~70-450% on +# Snapdragon S4. + +$flavour = shift; +if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + open STDOUT,">$output"; +} + +$num="r0"; # starts as num argument, but holds &tp[num-1] +$ap="r1"; +$bp="r2"; $bi="r2"; $rp="r2"; +$np="r3"; +$tp="r4"; +$aj="r5"; +$nj="r6"; +$tj="r7"; +$n0="r8"; +########### # r9 is reserved by ELF as platform specific, e.g. TLS pointer +$alo="r10"; # sl, gcc uses it to keep @GOT +$ahi="r11"; # fp +$nlo="r12"; # ip +########### # r13 is stack pointer +$nhi="r14"; # lr +########### # r15 is program counter + +#### argument block layout relative to &tp[num-1], a.k.a. $num +$_rp="$num,#12*4"; +# ap permanently resides in r1 +$_bp="$num,#13*4"; +# np permanently resides in r3 +$_n0="$num,#14*4"; +$_num="$num,#15*4"; $_bpend=$_num; + +$code=<<___; +#include "arm_arch.h" + +.text +#if defined(__thumb2__) +.syntax unified +.thumb +#else +.code 32 +#endif + +#if __ARM_MAX_ARCH__>=7 +.align 5 +.LOPENSSL_armcap: +.word OPENSSL_armcap_P-.Lbn_mul_mont +#endif + +.global bn_mul_mont +.type bn_mul_mont,%function + +.align 5 +bn_mul_mont: +.Lbn_mul_mont: + ldr ip,[sp,#4] @ load num + stmdb sp!,{r0,r2} @ sp points at argument block +#if __ARM_MAX_ARCH__>=7 + tst ip,#7 + bne .Lialu + adr r0,.Lbn_mul_mont + ldr r2,.LOPENSSL_armcap + ldr r0,[r0,r2] +#ifdef __APPLE__ + ldr r0,[r0] +#endif + tst r0,#ARMV7_NEON @ NEON available? + ldmia sp, {r0,r2} + beq .Lialu + add sp,sp,#8 + b bn_mul8x_mont_neon +.align 4 +.Lialu: +#endif + cmp ip,#2 + mov $num,ip @ load num +#ifdef __thumb2__ + ittt lt +#endif + movlt r0,#0 + addlt sp,sp,#2*4 + blt .Labrt + + stmdb sp!,{r4-r12,lr} @ save 10 registers + + mov $num,$num,lsl#2 @ rescale $num for byte count + sub sp,sp,$num @ alloca(4*num) + sub sp,sp,#4 @ +extra dword + sub $num,$num,#4 @ "num=num-1" + add $tp,$bp,$num @ &bp[num-1] + + add $num,sp,$num @ $num to point at &tp[num-1] + ldr $n0,[$_n0] @ &n0 + ldr $bi,[$bp] @ bp[0] + ldr $aj,[$ap],#4 @ ap[0],ap++ + ldr $nj,[$np],#4 @ np[0],np++ + ldr $n0,[$n0] @ *n0 + str $tp,[$_bpend] @ save &bp[num] + + umull $alo,$ahi,$aj,$bi @ ap[0]*bp[0] + str $n0,[$_n0] @ save n0 value + mul $n0,$alo,$n0 @ "tp[0]"*n0 + mov $nlo,#0 + umlal $alo,$nlo,$nj,$n0 @ np[0]*n0+"t[0]" + mov $tp,sp + +.L1st: + ldr $aj,[$ap],#4 @ ap[j],ap++ + mov $alo,$ahi + ldr $nj,[$np],#4 @ np[j],np++ + mov $ahi,#0 + umlal $alo,$ahi,$aj,$bi @ ap[j]*bp[0] + mov $nhi,#0 + umlal $nlo,$nhi,$nj,$n0 @ np[j]*n0 + adds $nlo,$nlo,$alo + str $nlo,[$tp],#4 @ tp[j-1]=,tp++ + adc $nlo,$nhi,#0 + cmp $tp,$num + bne .L1st + + adds $nlo,$nlo,$ahi + ldr $tp,[$_bp] @ restore bp + mov $nhi,#0 + ldr $n0,[$_n0] @ restore n0 + adc $nhi,$nhi,#0 + str $nlo,[$num] @ tp[num-1]= + mov $tj,sp + str $nhi,[$num,#4] @ tp[num]= + +.Louter: + sub $tj,$num,$tj @ "original" $num-1 value + sub $ap,$ap,$tj @ "rewind" ap to &ap[1] + ldr $bi,[$tp,#4]! @ *(++bp) + sub $np,$np,$tj @ "rewind" np to &np[1] + ldr $aj,[$ap,#-4] @ ap[0] + ldr $alo,[sp] @ tp[0] + ldr $nj,[$np,#-4] @ np[0] + ldr $tj,[sp,#4] @ tp[1] + + mov $ahi,#0 + umlal $alo,$ahi,$aj,$bi @ ap[0]*bp[i]+tp[0] + str $tp,[$_bp] @ save bp + mul $n0,$alo,$n0 + mov $nlo,#0 + umlal $alo,$nlo,$nj,$n0 @ np[0]*n0+"tp[0]" + mov $tp,sp + +.Linner: + ldr $aj,[$ap],#4 @ ap[j],ap++ + adds $alo,$ahi,$tj @ +=tp[j] + ldr $nj,[$np],#4 @ np[j],np++ + mov $ahi,#0 + umlal $alo,$ahi,$aj,$bi @ ap[j]*bp[i] + mov $nhi,#0 + umlal $nlo,$nhi,$nj,$n0 @ np[j]*n0 + adc $ahi,$ahi,#0 + ldr $tj,[$tp,#8] @ tp[j+1] + adds $nlo,$nlo,$alo + str $nlo,[$tp],#4 @ tp[j-1]=,tp++ + adc $nlo,$nhi,#0 + cmp $tp,$num + bne .Linner + + adds $nlo,$nlo,$ahi + mov $nhi,#0 + ldr $tp,[$_bp] @ restore bp + adc $nhi,$nhi,#0 + ldr $n0,[$_n0] @ restore n0 + adds $nlo,$nlo,$tj + ldr $tj,[$_bpend] @ restore &bp[num] + adc $nhi,$nhi,#0 + str $nlo,[$num] @ tp[num-1]= + str $nhi,[$num,#4] @ tp[num]= + + cmp $tp,$tj +#ifdef __thumb2__ + itt ne +#endif + movne $tj,sp + bne .Louter + + ldr $rp,[$_rp] @ pull rp + mov $aj,sp + add $num,$num,#4 @ $num to point at &tp[num] + sub $aj,$num,$aj @ "original" num value + mov $tp,sp @ "rewind" $tp + mov $ap,$tp @ "borrow" $ap + sub $np,$np,$aj @ "rewind" $np to &np[0] + + subs $tj,$tj,$tj @ "clear" carry flag +.Lsub: ldr $tj,[$tp],#4 + ldr $nj,[$np],#4 + sbcs $tj,$tj,$nj @ tp[j]-np[j] + str $tj,[$rp],#4 @ rp[j]= + teq $tp,$num @ preserve carry + bne .Lsub + sbcs $nhi,$nhi,#0 @ upmost carry + mov $tp,sp @ "rewind" $tp + sub $rp,$rp,$aj @ "rewind" $rp + +.Lcopy: ldr $tj,[$tp] @ conditional copy + ldr $aj,[$rp] + str sp,[$tp],#4 @ zap tp +#ifdef __thumb2__ + it cc +#endif + movcc $aj,$tj + str $aj,[$rp],#4 + teq $tp,$num @ preserve carry + bne .Lcopy + + mov sp,$num + add sp,sp,#4 @ skip over tp[num+1] + ldmia sp!,{r4-r12,lr} @ restore registers + add sp,sp,#2*4 @ skip over {r0,r2} + mov r0,#1 +.Labrt: +#if __ARM_ARCH__>=5 + ret @ bx lr +#else + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.size bn_mul_mont,.-bn_mul_mont +___ +{ +my ($A0,$A1,$A2,$A3)=map("d$_",(0..3)); +my ($N0,$N1,$N2,$N3)=map("d$_",(4..7)); +my ($Z,$Temp)=("q4","q5"); +my @ACC=map("q$_",(6..13)); +my ($Bi,$Ni,$M0)=map("d$_",(28..31)); +my $zero="$Z#lo"; +my $temp="$Temp#lo"; + +my ($rptr,$aptr,$bptr,$nptr,$n0,$num)=map("r$_",(0..5)); +my ($tinptr,$toutptr,$inner,$outer,$bnptr)=map("r$_",(6..11)); + +$code.=<<___; +#if __ARM_MAX_ARCH__>=7 +.arch armv7-a +.fpu neon + +.type bn_mul8x_mont_neon,%function +.align 5 +bn_mul8x_mont_neon: + mov ip,sp + stmdb sp!,{r4-r11} + vstmdb sp!,{d8-d15} @ ABI specification says so + ldmia ip,{r4-r5} @ load rest of parameter block + mov ip,sp + + cmp $num,#8 + bhi .LNEON_8n + + @ special case for $num==8, everything is in register bank... + + vld1.32 {${Bi}[0]}, [$bptr,:32]! + veor $zero,$zero,$zero + sub $toutptr,sp,$num,lsl#4 + vld1.32 {$A0-$A3}, [$aptr]! @ can't specify :32 :-( + and $toutptr,$toutptr,#-64 + vld1.32 {${M0}[0]}, [$n0,:32] + mov sp,$toutptr @ alloca + vzip.16 $Bi,$zero + + vmull.u32 @ACC[0],$Bi,${A0}[0] + vmull.u32 @ACC[1],$Bi,${A0}[1] + vmull.u32 @ACC[2],$Bi,${A1}[0] + vshl.i64 $Ni,@ACC[0]#hi,#16 + vmull.u32 @ACC[3],$Bi,${A1}[1] + + vadd.u64 $Ni,$Ni,@ACC[0]#lo + veor $zero,$zero,$zero + vmul.u32 $Ni,$Ni,$M0 + + vmull.u32 @ACC[4],$Bi,${A2}[0] + vld1.32 {$N0-$N3}, [$nptr]! + vmull.u32 @ACC[5],$Bi,${A2}[1] + vmull.u32 @ACC[6],$Bi,${A3}[0] + vzip.16 $Ni,$zero + vmull.u32 @ACC[7],$Bi,${A3}[1] + + vmlal.u32 @ACC[0],$Ni,${N0}[0] + sub $outer,$num,#1 + vmlal.u32 @ACC[1],$Ni,${N0}[1] + vmlal.u32 @ACC[2],$Ni,${N1}[0] + vmlal.u32 @ACC[3],$Ni,${N1}[1] + + vmlal.u32 @ACC[4],$Ni,${N2}[0] + vmov $Temp,@ACC[0] + vmlal.u32 @ACC[5],$Ni,${N2}[1] + vmov @ACC[0],@ACC[1] + vmlal.u32 @ACC[6],$Ni,${N3}[0] + vmov @ACC[1],@ACC[2] + vmlal.u32 @ACC[7],$Ni,${N3}[1] + vmov @ACC[2],@ACC[3] + vmov @ACC[3],@ACC[4] + vshr.u64 $temp,$temp,#16 + vmov @ACC[4],@ACC[5] + vmov @ACC[5],@ACC[6] + vadd.u64 $temp,$temp,$Temp#hi + vmov @ACC[6],@ACC[7] + veor @ACC[7],@ACC[7] + vshr.u64 $temp,$temp,#16 + + b .LNEON_outer8 + +.align 4 +.LNEON_outer8: + vld1.32 {${Bi}[0]}, [$bptr,:32]! + veor $zero,$zero,$zero + vzip.16 $Bi,$zero + vadd.u64 @ACC[0]#lo,@ACC[0]#lo,$temp + + vmlal.u32 @ACC[0],$Bi,${A0}[0] + vmlal.u32 @ACC[1],$Bi,${A0}[1] + vmlal.u32 @ACC[2],$Bi,${A1}[0] + vshl.i64 $Ni,@ACC[0]#hi,#16 + vmlal.u32 @ACC[3],$Bi,${A1}[1] + + vadd.u64 $Ni,$Ni,@ACC[0]#lo + veor $zero,$zero,$zero + subs $outer,$outer,#1 + vmul.u32 $Ni,$Ni,$M0 + + vmlal.u32 @ACC[4],$Bi,${A2}[0] + vmlal.u32 @ACC[5],$Bi,${A2}[1] + vmlal.u32 @ACC[6],$Bi,${A3}[0] + vzip.16 $Ni,$zero + vmlal.u32 @ACC[7],$Bi,${A3}[1] + + vmlal.u32 @ACC[0],$Ni,${N0}[0] + vmlal.u32 @ACC[1],$Ni,${N0}[1] + vmlal.u32 @ACC[2],$Ni,${N1}[0] + vmlal.u32 @ACC[3],$Ni,${N1}[1] + + vmlal.u32 @ACC[4],$Ni,${N2}[0] + vmov $Temp,@ACC[0] + vmlal.u32 @ACC[5],$Ni,${N2}[1] + vmov @ACC[0],@ACC[1] + vmlal.u32 @ACC[6],$Ni,${N3}[0] + vmov @ACC[1],@ACC[2] + vmlal.u32 @ACC[7],$Ni,${N3}[1] + vmov @ACC[2],@ACC[3] + vmov @ACC[3],@ACC[4] + vshr.u64 $temp,$temp,#16 + vmov @ACC[4],@ACC[5] + vmov @ACC[5],@ACC[6] + vadd.u64 $temp,$temp,$Temp#hi + vmov @ACC[6],@ACC[7] + veor @ACC[7],@ACC[7] + vshr.u64 $temp,$temp,#16 + + bne .LNEON_outer8 + + vadd.u64 @ACC[0]#lo,@ACC[0]#lo,$temp + mov $toutptr,sp + vshr.u64 $temp,@ACC[0]#lo,#16 + mov $inner,$num + vadd.u64 @ACC[0]#hi,@ACC[0]#hi,$temp + add $tinptr,sp,#96 + vshr.u64 $temp,@ACC[0]#hi,#16 + vzip.16 @ACC[0]#lo,@ACC[0]#hi + + b .LNEON_tail_entry + +.align 4 +.LNEON_8n: + veor @ACC[0],@ACC[0],@ACC[0] + sub $toutptr,sp,#128 + veor @ACC[1],@ACC[1],@ACC[1] + sub $toutptr,$toutptr,$num,lsl#4 + veor @ACC[2],@ACC[2],@ACC[2] + and $toutptr,$toutptr,#-64 + veor @ACC[3],@ACC[3],@ACC[3] + mov sp,$toutptr @ alloca + veor @ACC[4],@ACC[4],@ACC[4] + add $toutptr,$toutptr,#256 + veor @ACC[5],@ACC[5],@ACC[5] + sub $inner,$num,#8 + veor @ACC[6],@ACC[6],@ACC[6] + veor @ACC[7],@ACC[7],@ACC[7] + +.LNEON_8n_init: + vst1.64 {@ACC[0]-@ACC[1]},[$toutptr,:256]! + subs $inner,$inner,#8 + vst1.64 {@ACC[2]-@ACC[3]},[$toutptr,:256]! + vst1.64 {@ACC[4]-@ACC[5]},[$toutptr,:256]! + vst1.64 {@ACC[6]-@ACC[7]},[$toutptr,:256]! + bne .LNEON_8n_init + + add $tinptr,sp,#256 + vld1.32 {$A0-$A3},[$aptr]! + add $bnptr,sp,#8 + vld1.32 {${M0}[0]},[$n0,:32] + mov $outer,$num + b .LNEON_8n_outer + +.align 4 +.LNEON_8n_outer: + vld1.32 {${Bi}[0]},[$bptr,:32]! @ *b++ + veor $zero,$zero,$zero + vzip.16 $Bi,$zero + add $toutptr,sp,#128 + vld1.32 {$N0-$N3},[$nptr]! + + vmlal.u32 @ACC[0],$Bi,${A0}[0] + vmlal.u32 @ACC[1],$Bi,${A0}[1] + veor $zero,$zero,$zero + vmlal.u32 @ACC[2],$Bi,${A1}[0] + vshl.i64 $Ni,@ACC[0]#hi,#16 + vmlal.u32 @ACC[3],$Bi,${A1}[1] + vadd.u64 $Ni,$Ni,@ACC[0]#lo + vmlal.u32 @ACC[4],$Bi,${A2}[0] + vmul.u32 $Ni,$Ni,$M0 + vmlal.u32 @ACC[5],$Bi,${A2}[1] + vst1.32 {$Bi},[sp,:64] @ put aside smashed b[8*i+0] + vmlal.u32 @ACC[6],$Bi,${A3}[0] + vzip.16 $Ni,$zero + vmlal.u32 @ACC[7],$Bi,${A3}[1] +___ +for ($i=0; $i<7;) { +$code.=<<___; + vld1.32 {${Bi}[0]},[$bptr,:32]! @ *b++ + vmlal.u32 @ACC[0],$Ni,${N0}[0] + veor $temp,$temp,$temp + vmlal.u32 @ACC[1],$Ni,${N0}[1] + vzip.16 $Bi,$temp + vmlal.u32 @ACC[2],$Ni,${N1}[0] + vshr.u64 @ACC[0]#lo,@ACC[0]#lo,#16 + vmlal.u32 @ACC[3],$Ni,${N1}[1] + vmlal.u32 @ACC[4],$Ni,${N2}[0] + vadd.u64 @ACC[0]#lo,@ACC[0]#lo,@ACC[0]#hi + vmlal.u32 @ACC[5],$Ni,${N2}[1] + vshr.u64 @ACC[0]#lo,@ACC[0]#lo,#16 + vmlal.u32 @ACC[6],$Ni,${N3}[0] + vmlal.u32 @ACC[7],$Ni,${N3}[1] + vadd.u64 @ACC[1]#lo,@ACC[1]#lo,@ACC[0]#lo + vst1.32 {$Ni},[$bnptr,:64]! @ put aside smashed m[8*i+$i] +___ + push(@ACC,shift(@ACC)); $i++; +$code.=<<___; + vmlal.u32 @ACC[0],$Bi,${A0}[0] + vld1.64 {@ACC[7]},[$tinptr,:128]! + vmlal.u32 @ACC[1],$Bi,${A0}[1] + veor $zero,$zero,$zero + vmlal.u32 @ACC[2],$Bi,${A1}[0] + vshl.i64 $Ni,@ACC[0]#hi,#16 + vmlal.u32 @ACC[3],$Bi,${A1}[1] + vadd.u64 $Ni,$Ni,@ACC[0]#lo + vmlal.u32 @ACC[4],$Bi,${A2}[0] + vmul.u32 $Ni,$Ni,$M0 + vmlal.u32 @ACC[5],$Bi,${A2}[1] + vst1.32 {$Bi},[$bnptr,:64]! @ put aside smashed b[8*i+$i] + vmlal.u32 @ACC[6],$Bi,${A3}[0] + vzip.16 $Ni,$zero + vmlal.u32 @ACC[7],$Bi,${A3}[1] +___ +} +$code.=<<___; + vld1.32 {$Bi},[sp,:64] @ pull smashed b[8*i+0] + vmlal.u32 @ACC[0],$Ni,${N0}[0] + vld1.32 {$A0-$A3},[$aptr]! + vmlal.u32 @ACC[1],$Ni,${N0}[1] + vmlal.u32 @ACC[2],$Ni,${N1}[0] + vshr.u64 @ACC[0]#lo,@ACC[0]#lo,#16 + vmlal.u32 @ACC[3],$Ni,${N1}[1] + vmlal.u32 @ACC[4],$Ni,${N2}[0] + vadd.u64 @ACC[0]#lo,@ACC[0]#lo,@ACC[0]#hi + vmlal.u32 @ACC[5],$Ni,${N2}[1] + vshr.u64 @ACC[0]#lo,@ACC[0]#lo,#16 + vmlal.u32 @ACC[6],$Ni,${N3}[0] + vmlal.u32 @ACC[7],$Ni,${N3}[1] + vadd.u64 @ACC[1]#lo,@ACC[1]#lo,@ACC[0]#lo + vst1.32 {$Ni},[$bnptr,:64] @ put aside smashed m[8*i+$i] + add $bnptr,sp,#8 @ rewind +___ + push(@ACC,shift(@ACC)); +$code.=<<___; + sub $inner,$num,#8 + b .LNEON_8n_inner + +.align 4 +.LNEON_8n_inner: + subs $inner,$inner,#8 + vmlal.u32 @ACC[0],$Bi,${A0}[0] + vld1.64 {@ACC[7]},[$tinptr,:128] + vmlal.u32 @ACC[1],$Bi,${A0}[1] + vld1.32 {$Ni},[$bnptr,:64]! @ pull smashed m[8*i+0] + vmlal.u32 @ACC[2],$Bi,${A1}[0] + vld1.32 {$N0-$N3},[$nptr]! + vmlal.u32 @ACC[3],$Bi,${A1}[1] + it ne + addne $tinptr,$tinptr,#16 @ don't advance in last iteration + vmlal.u32 @ACC[4],$Bi,${A2}[0] + vmlal.u32 @ACC[5],$Bi,${A2}[1] + vmlal.u32 @ACC[6],$Bi,${A3}[0] + vmlal.u32 @ACC[7],$Bi,${A3}[1] +___ +for ($i=1; $i<8; $i++) { +$code.=<<___; + vld1.32 {$Bi},[$bnptr,:64]! @ pull smashed b[8*i+$i] + vmlal.u32 @ACC[0],$Ni,${N0}[0] + vmlal.u32 @ACC[1],$Ni,${N0}[1] + vmlal.u32 @ACC[2],$Ni,${N1}[0] + vmlal.u32 @ACC[3],$Ni,${N1}[1] + vmlal.u32 @ACC[4],$Ni,${N2}[0] + vmlal.u32 @ACC[5],$Ni,${N2}[1] + vmlal.u32 @ACC[6],$Ni,${N3}[0] + vmlal.u32 @ACC[7],$Ni,${N3}[1] + vst1.64 {@ACC[0]},[$toutptr,:128]! +___ + push(@ACC,shift(@ACC)); +$code.=<<___; + vmlal.u32 @ACC[0],$Bi,${A0}[0] + vld1.64 {@ACC[7]},[$tinptr,:128] + vmlal.u32 @ACC[1],$Bi,${A0}[1] + vld1.32 {$Ni},[$bnptr,:64]! @ pull smashed m[8*i+$i] + vmlal.u32 @ACC[2],$Bi,${A1}[0] + it ne + addne $tinptr,$tinptr,#16 @ don't advance in last iteration + vmlal.u32 @ACC[3],$Bi,${A1}[1] + vmlal.u32 @ACC[4],$Bi,${A2}[0] + vmlal.u32 @ACC[5],$Bi,${A2}[1] + vmlal.u32 @ACC[6],$Bi,${A3}[0] + vmlal.u32 @ACC[7],$Bi,${A3}[1] +___ +} +$code.=<<___; + it eq + subeq $aptr,$aptr,$num,lsl#2 @ rewind + vmlal.u32 @ACC[0],$Ni,${N0}[0] + vld1.32 {$Bi},[sp,:64] @ pull smashed b[8*i+0] + vmlal.u32 @ACC[1],$Ni,${N0}[1] + vld1.32 {$A0-$A3},[$aptr]! + vmlal.u32 @ACC[2],$Ni,${N1}[0] + add $bnptr,sp,#8 @ rewind + vmlal.u32 @ACC[3],$Ni,${N1}[1] + vmlal.u32 @ACC[4],$Ni,${N2}[0] + vmlal.u32 @ACC[5],$Ni,${N2}[1] + vmlal.u32 @ACC[6],$Ni,${N3}[0] + vst1.64 {@ACC[0]},[$toutptr,:128]! + vmlal.u32 @ACC[7],$Ni,${N3}[1] + + bne .LNEON_8n_inner +___ + push(@ACC,shift(@ACC)); +$code.=<<___; + add $tinptr,sp,#128 + vst1.64 {@ACC[0]-@ACC[1]},[$toutptr,:256]! + veor q2,q2,q2 @ $N0-$N1 + vst1.64 {@ACC[2]-@ACC[3]},[$toutptr,:256]! + veor q3,q3,q3 @ $N2-$N3 + vst1.64 {@ACC[4]-@ACC[5]},[$toutptr,:256]! + vst1.64 {@ACC[6]},[$toutptr,:128] + + subs $outer,$outer,#8 + vld1.64 {@ACC[0]-@ACC[1]},[$tinptr,:256]! + vld1.64 {@ACC[2]-@ACC[3]},[$tinptr,:256]! + vld1.64 {@ACC[4]-@ACC[5]},[$tinptr,:256]! + vld1.64 {@ACC[6]-@ACC[7]},[$tinptr,:256]! + + itt ne + subne $nptr,$nptr,$num,lsl#2 @ rewind + bne .LNEON_8n_outer + + add $toutptr,sp,#128 + vst1.64 {q2-q3}, [sp,:256]! @ start wiping stack frame + vshr.u64 $temp,@ACC[0]#lo,#16 + vst1.64 {q2-q3},[sp,:256]! + vadd.u64 @ACC[0]#hi,@ACC[0]#hi,$temp + vst1.64 {q2-q3}, [sp,:256]! + vshr.u64 $temp,@ACC[0]#hi,#16 + vst1.64 {q2-q3}, [sp,:256]! + vzip.16 @ACC[0]#lo,@ACC[0]#hi + + mov $inner,$num + b .LNEON_tail_entry + +.align 4 +.LNEON_tail: + vadd.u64 @ACC[0]#lo,@ACC[0]#lo,$temp + vshr.u64 $temp,@ACC[0]#lo,#16 + vld1.64 {@ACC[2]-@ACC[3]}, [$tinptr, :256]! + vadd.u64 @ACC[0]#hi,@ACC[0]#hi,$temp + vld1.64 {@ACC[4]-@ACC[5]}, [$tinptr, :256]! + vshr.u64 $temp,@ACC[0]#hi,#16 + vld1.64 {@ACC[6]-@ACC[7]}, [$tinptr, :256]! + vzip.16 @ACC[0]#lo,@ACC[0]#hi + +.LNEON_tail_entry: +___ +for ($i=1; $i<8; $i++) { +$code.=<<___; + vadd.u64 @ACC[1]#lo,@ACC[1]#lo,$temp + vst1.32 {@ACC[0]#lo[0]}, [$toutptr, :32]! + vshr.u64 $temp,@ACC[1]#lo,#16 + vadd.u64 @ACC[1]#hi,@ACC[1]#hi,$temp + vshr.u64 $temp,@ACC[1]#hi,#16 + vzip.16 @ACC[1]#lo,@ACC[1]#hi +___ + push(@ACC,shift(@ACC)); +} + push(@ACC,shift(@ACC)); +$code.=<<___; + vld1.64 {@ACC[0]-@ACC[1]}, [$tinptr, :256]! + subs $inner,$inner,#8 + vst1.32 {@ACC[7]#lo[0]}, [$toutptr, :32]! + bne .LNEON_tail + + vst1.32 {${temp}[0]}, [$toutptr, :32] @ top-most bit + sub $nptr,$nptr,$num,lsl#2 @ rewind $nptr + subs $aptr,sp,#0 @ clear carry flag + add $bptr,sp,$num,lsl#2 + +.LNEON_sub: + ldmia $aptr!, {r4-r7} + ldmia $nptr!, {r8-r11} + sbcs r8, r4,r8 + sbcs r9, r5,r9 + sbcs r10,r6,r10 + sbcs r11,r7,r11 + teq $aptr,$bptr @ preserves carry + stmia $rptr!, {r8-r11} + bne .LNEON_sub + + ldr r10, [$aptr] @ load top-most bit + mov r11,sp + veor q0,q0,q0 + sub r11,$bptr,r11 @ this is num*4 + veor q1,q1,q1 + mov $aptr,sp + sub $rptr,$rptr,r11 @ rewind $rptr + mov $nptr,$bptr @ second 3/4th of frame + sbcs r10,r10,#0 @ result is carry flag + +.LNEON_copy_n_zap: + ldmia $aptr!, {r4-r7} + ldmia $rptr, {r8-r11} + it cc + movcc r8, r4 + vst1.64 {q0-q1}, [$nptr,:256]! @ wipe + itt cc + movcc r9, r5 + movcc r10,r6 + vst1.64 {q0-q1}, [$nptr,:256]! @ wipe + it cc + movcc r11,r7 + ldmia $aptr, {r4-r7} + stmia $rptr!, {r8-r11} + sub $aptr,$aptr,#16 + ldmia $rptr, {r8-r11} + it cc + movcc r8, r4 + vst1.64 {q0-q1}, [$aptr,:256]! @ wipe + itt cc + movcc r9, r5 + movcc r10,r6 + vst1.64 {q0-q1}, [$nptr,:256]! @ wipe + it cc + movcc r11,r7 + teq $aptr,$bptr @ preserves carry + stmia $rptr!, {r8-r11} + bne .LNEON_copy_n_zap + + mov sp,ip + vldmia sp!,{d8-d15} + ldmia sp!,{r4-r11} + ret @ bx lr +.size bn_mul8x_mont_neon,.-bn_mul8x_mont_neon +#endif +___ +} +$code.=<<___; +.asciz "Montgomery multiplication for ARMv4/NEON, CRYPTOGAMS by " +.align 2 +#if __ARM_MAX_ARCH__>=7 +.comm OPENSSL_armcap_P,4,4 +#endif +___ + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/ge; + + s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/ge or + s/\bret\b/bx lr/g or + s/\bbx\s+lr\b/.word\t0xe12fff1e/g; # make it possible to compile with -march=armv4 + + print $_,"\n"; +} + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/armv8-mont.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/armv8-mont.pl new file mode 100755 index 000000000..d8347bf93 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/armv8-mont.pl @@ -0,0 +1,1514 @@ +#! /usr/bin/env perl +# Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# March 2015 +# +# "Teaser" Montgomery multiplication module for ARMv8. Needs more +# work. While it does improve RSA sign performance by 20-30% (less for +# longer keys) on most processors, for some reason RSA2048 is not +# faster and RSA4096 goes 15-20% slower on Cortex-A57. Multiplication +# instruction issue rate is limited on processor in question, meaning +# that dedicated squaring procedure is a must. Well, actually all +# contemporary AArch64 processors seem to have limited multiplication +# issue rate, i.e. they can't issue multiplication every cycle, which +# explains moderate improvement coefficients in comparison to +# compiler-generated code. Recall that compiler is instructed to use +# umulh and therefore uses same amount of multiplication instructions +# to do the job. Assembly's edge is to minimize number of "collateral" +# instructions and of course instruction scheduling. +# +# April 2015 +# +# Squaring procedure that handles lengths divisible by 8 improves +# RSA/DSA performance by 25-40-60% depending on processor and key +# length. Overall improvement coefficients are always positive in +# comparison to compiler-generated code. On Cortex-A57 improvement +# is still modest on longest key lengths, while others exhibit e.g. +# 50-70% improvement for RSA4096 sign. RSA2048 sign is ~25% faster +# on Cortex-A57 and ~60-100% faster on others. + +$flavour = shift; +$output = shift; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or +die "can't locate arm-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +($lo0,$hi0,$aj,$m0,$alo,$ahi, + $lo1,$hi1,$nj,$m1,$nlo,$nhi, + $ovf, $i,$j,$tp,$tj) = map("x$_",6..17,19..24); + +# int bn_mul_mont( +$rp="x0"; # BN_ULONG *rp, +$ap="x1"; # const BN_ULONG *ap, +$bp="x2"; # const BN_ULONG *bp, +$np="x3"; # const BN_ULONG *np, +$n0="x4"; # const BN_ULONG *n0, +$num="x5"; # int num); + +$code.=<<___; +.text + +.globl bn_mul_mont +.type bn_mul_mont,%function +.align 5 +bn_mul_mont: + tst $num,#7 + b.eq __bn_sqr8x_mont + tst $num,#3 + b.eq __bn_mul4x_mont +.Lmul_mont: + stp x29,x30,[sp,#-64]! + add x29,sp,#0 + stp x19,x20,[sp,#16] + stp x21,x22,[sp,#32] + stp x23,x24,[sp,#48] + + ldr $m0,[$bp],#8 // bp[0] + sub $tp,sp,$num,lsl#3 + ldp $hi0,$aj,[$ap],#16 // ap[0..1] + lsl $num,$num,#3 + ldr $n0,[$n0] // *n0 + and $tp,$tp,#-16 // ABI says so + ldp $hi1,$nj,[$np],#16 // np[0..1] + + mul $lo0,$hi0,$m0 // ap[0]*bp[0] + sub $j,$num,#16 // j=num-2 + umulh $hi0,$hi0,$m0 + mul $alo,$aj,$m0 // ap[1]*bp[0] + umulh $ahi,$aj,$m0 + + mul $m1,$lo0,$n0 // "tp[0]"*n0 + mov sp,$tp // alloca + + // (*) mul $lo1,$hi1,$m1 // np[0]*m1 + umulh $hi1,$hi1,$m1 + mul $nlo,$nj,$m1 // np[1]*m1 + // (*) adds $lo1,$lo1,$lo0 // discarded + // (*) As for removal of first multiplication and addition + // instructions. The outcome of first addition is + // guaranteed to be zero, which leaves two computationally + // significant outcomes: it either carries or not. Then + // question is when does it carry? Is there alternative + // way to deduce it? If you follow operations, you can + // observe that condition for carry is quite simple: + // $lo0 being non-zero. So that carry can be calculated + // by adding -1 to $lo0. That's what next instruction does. + subs xzr,$lo0,#1 // (*) + umulh $nhi,$nj,$m1 + adc $hi1,$hi1,xzr + cbz $j,.L1st_skip + +.L1st: + ldr $aj,[$ap],#8 + adds $lo0,$alo,$hi0 + sub $j,$j,#8 // j-- + adc $hi0,$ahi,xzr + + ldr $nj,[$np],#8 + adds $lo1,$nlo,$hi1 + mul $alo,$aj,$m0 // ap[j]*bp[0] + adc $hi1,$nhi,xzr + umulh $ahi,$aj,$m0 + + adds $lo1,$lo1,$lo0 + mul $nlo,$nj,$m1 // np[j]*m1 + adc $hi1,$hi1,xzr + umulh $nhi,$nj,$m1 + str $lo1,[$tp],#8 // tp[j-1] + cbnz $j,.L1st + +.L1st_skip: + adds $lo0,$alo,$hi0 + sub $ap,$ap,$num // rewind $ap + adc $hi0,$ahi,xzr + + adds $lo1,$nlo,$hi1 + sub $np,$np,$num // rewind $np + adc $hi1,$nhi,xzr + + adds $lo1,$lo1,$lo0 + sub $i,$num,#8 // i=num-1 + adcs $hi1,$hi1,$hi0 + + adc $ovf,xzr,xzr // upmost overflow bit + stp $lo1,$hi1,[$tp] + +.Louter: + ldr $m0,[$bp],#8 // bp[i] + ldp $hi0,$aj,[$ap],#16 + ldr $tj,[sp] // tp[0] + add $tp,sp,#8 + + mul $lo0,$hi0,$m0 // ap[0]*bp[i] + sub $j,$num,#16 // j=num-2 + umulh $hi0,$hi0,$m0 + ldp $hi1,$nj,[$np],#16 + mul $alo,$aj,$m0 // ap[1]*bp[i] + adds $lo0,$lo0,$tj + umulh $ahi,$aj,$m0 + adc $hi0,$hi0,xzr + + mul $m1,$lo0,$n0 + sub $i,$i,#8 // i-- + + // (*) mul $lo1,$hi1,$m1 // np[0]*m1 + umulh $hi1,$hi1,$m1 + mul $nlo,$nj,$m1 // np[1]*m1 + // (*) adds $lo1,$lo1,$lo0 + subs xzr,$lo0,#1 // (*) + umulh $nhi,$nj,$m1 + cbz $j,.Linner_skip + +.Linner: + ldr $aj,[$ap],#8 + adc $hi1,$hi1,xzr + ldr $tj,[$tp],#8 // tp[j] + adds $lo0,$alo,$hi0 + sub $j,$j,#8 // j-- + adc $hi0,$ahi,xzr + + adds $lo1,$nlo,$hi1 + ldr $nj,[$np],#8 + adc $hi1,$nhi,xzr + + mul $alo,$aj,$m0 // ap[j]*bp[i] + adds $lo0,$lo0,$tj + umulh $ahi,$aj,$m0 + adc $hi0,$hi0,xzr + + mul $nlo,$nj,$m1 // np[j]*m1 + adds $lo1,$lo1,$lo0 + umulh $nhi,$nj,$m1 + str $lo1,[$tp,#-16] // tp[j-1] + cbnz $j,.Linner + +.Linner_skip: + ldr $tj,[$tp],#8 // tp[j] + adc $hi1,$hi1,xzr + adds $lo0,$alo,$hi0 + sub $ap,$ap,$num // rewind $ap + adc $hi0,$ahi,xzr + + adds $lo1,$nlo,$hi1 + sub $np,$np,$num // rewind $np + adcs $hi1,$nhi,$ovf + adc $ovf,xzr,xzr + + adds $lo0,$lo0,$tj + adc $hi0,$hi0,xzr + + adds $lo1,$lo1,$lo0 + adcs $hi1,$hi1,$hi0 + adc $ovf,$ovf,xzr // upmost overflow bit + stp $lo1,$hi1,[$tp,#-16] + + cbnz $i,.Louter + + // Final step. We see if result is larger than modulus, and + // if it is, subtract the modulus. But comparison implies + // subtraction. So we subtract modulus, see if it borrowed, + // and conditionally copy original value. + ldr $tj,[sp] // tp[0] + add $tp,sp,#8 + ldr $nj,[$np],#8 // np[0] + subs $j,$num,#8 // j=num-1 and clear borrow + mov $ap,$rp +.Lsub: + sbcs $aj,$tj,$nj // tp[j]-np[j] + ldr $tj,[$tp],#8 + sub $j,$j,#8 // j-- + ldr $nj,[$np],#8 + str $aj,[$ap],#8 // rp[j]=tp[j]-np[j] + cbnz $j,.Lsub + + sbcs $aj,$tj,$nj + sbcs $ovf,$ovf,xzr // did it borrow? + str $aj,[$ap],#8 // rp[num-1] + + ldr $tj,[sp] // tp[0] + add $tp,sp,#8 + ldr $aj,[$rp],#8 // rp[0] + sub $num,$num,#8 // num-- + nop +.Lcond_copy: + sub $num,$num,#8 // num-- + csel $nj,$tj,$aj,lo // did it borrow? + ldr $tj,[$tp],#8 + ldr $aj,[$rp],#8 + str xzr,[$tp,#-16] // wipe tp + str $nj,[$rp,#-16] + cbnz $num,.Lcond_copy + + csel $nj,$tj,$aj,lo + str xzr,[$tp,#-8] // wipe tp + str $nj,[$rp,#-8] + + ldp x19,x20,[x29,#16] + mov sp,x29 + ldp x21,x22,[x29,#32] + mov x0,#1 + ldp x23,x24,[x29,#48] + ldr x29,[sp],#64 + ret +.size bn_mul_mont,.-bn_mul_mont +___ +{ +######################################################################## +# Following is ARMv8 adaptation of sqrx8x_mont from x86_64-mont5 module. + +my ($a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7)=map("x$_",(6..13)); +my ($t0,$t1,$t2,$t3)=map("x$_",(14..17)); +my ($acc0,$acc1,$acc2,$acc3,$acc4,$acc5,$acc6,$acc7)=map("x$_",(19..26)); +my ($cnt,$carry,$topmost)=("x27","x28","x30"); +my ($tp,$ap_end,$na0)=($bp,$np,$carry); + +$code.=<<___; +.type __bn_sqr8x_mont,%function +.align 5 +__bn_sqr8x_mont: + cmp $ap,$bp + b.ne __bn_mul4x_mont +.Lsqr8x_mont: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-128]! + add x29,sp,#0 + stp x19,x20,[sp,#16] + stp x21,x22,[sp,#32] + stp x23,x24,[sp,#48] + stp x25,x26,[sp,#64] + stp x27,x28,[sp,#80] + stp $rp,$np,[sp,#96] // offload rp and np + + ldp $a0,$a1,[$ap,#8*0] + ldp $a2,$a3,[$ap,#8*2] + ldp $a4,$a5,[$ap,#8*4] + ldp $a6,$a7,[$ap,#8*6] + + sub $tp,sp,$num,lsl#4 + lsl $num,$num,#3 + ldr $n0,[$n0] // *n0 + mov sp,$tp // alloca + sub $cnt,$num,#8*8 + b .Lsqr8x_zero_start + +.Lsqr8x_zero: + sub $cnt,$cnt,#8*8 + stp xzr,xzr,[$tp,#8*0] + stp xzr,xzr,[$tp,#8*2] + stp xzr,xzr,[$tp,#8*4] + stp xzr,xzr,[$tp,#8*6] +.Lsqr8x_zero_start: + stp xzr,xzr,[$tp,#8*8] + stp xzr,xzr,[$tp,#8*10] + stp xzr,xzr,[$tp,#8*12] + stp xzr,xzr,[$tp,#8*14] + add $tp,$tp,#8*16 + cbnz $cnt,.Lsqr8x_zero + + add $ap_end,$ap,$num + add $ap,$ap,#8*8 + mov $acc0,xzr + mov $acc1,xzr + mov $acc2,xzr + mov $acc3,xzr + mov $acc4,xzr + mov $acc5,xzr + mov $acc6,xzr + mov $acc7,xzr + mov $tp,sp + str $n0,[x29,#112] // offload n0 + + // Multiply everything but a[i]*a[i] +.align 4 +.Lsqr8x_outer_loop: + // a[1]a[0] (i) + // a[2]a[0] + // a[3]a[0] + // a[4]a[0] + // a[5]a[0] + // a[6]a[0] + // a[7]a[0] + // a[2]a[1] (ii) + // a[3]a[1] + // a[4]a[1] + // a[5]a[1] + // a[6]a[1] + // a[7]a[1] + // a[3]a[2] (iii) + // a[4]a[2] + // a[5]a[2] + // a[6]a[2] + // a[7]a[2] + // a[4]a[3] (iv) + // a[5]a[3] + // a[6]a[3] + // a[7]a[3] + // a[5]a[4] (v) + // a[6]a[4] + // a[7]a[4] + // a[6]a[5] (vi) + // a[7]a[5] + // a[7]a[6] (vii) + + mul $t0,$a1,$a0 // lo(a[1..7]*a[0]) (i) + mul $t1,$a2,$a0 + mul $t2,$a3,$a0 + mul $t3,$a4,$a0 + adds $acc1,$acc1,$t0 // t[1]+lo(a[1]*a[0]) + mul $t0,$a5,$a0 + adcs $acc2,$acc2,$t1 + mul $t1,$a6,$a0 + adcs $acc3,$acc3,$t2 + mul $t2,$a7,$a0 + adcs $acc4,$acc4,$t3 + umulh $t3,$a1,$a0 // hi(a[1..7]*a[0]) + adcs $acc5,$acc5,$t0 + umulh $t0,$a2,$a0 + adcs $acc6,$acc6,$t1 + umulh $t1,$a3,$a0 + adcs $acc7,$acc7,$t2 + umulh $t2,$a4,$a0 + stp $acc0,$acc1,[$tp],#8*2 // t[0..1] + adc $acc0,xzr,xzr // t[8] + adds $acc2,$acc2,$t3 // t[2]+lo(a[1]*a[0]) + umulh $t3,$a5,$a0 + adcs $acc3,$acc3,$t0 + umulh $t0,$a6,$a0 + adcs $acc4,$acc4,$t1 + umulh $t1,$a7,$a0 + adcs $acc5,$acc5,$t2 + mul $t2,$a2,$a1 // lo(a[2..7]*a[1]) (ii) + adcs $acc6,$acc6,$t3 + mul $t3,$a3,$a1 + adcs $acc7,$acc7,$t0 + mul $t0,$a4,$a1 + adc $acc0,$acc0,$t1 + + mul $t1,$a5,$a1 + adds $acc3,$acc3,$t2 + mul $t2,$a6,$a1 + adcs $acc4,$acc4,$t3 + mul $t3,$a7,$a1 + adcs $acc5,$acc5,$t0 + umulh $t0,$a2,$a1 // hi(a[2..7]*a[1]) + adcs $acc6,$acc6,$t1 + umulh $t1,$a3,$a1 + adcs $acc7,$acc7,$t2 + umulh $t2,$a4,$a1 + adcs $acc0,$acc0,$t3 + umulh $t3,$a5,$a1 + stp $acc2,$acc3,[$tp],#8*2 // t[2..3] + adc $acc1,xzr,xzr // t[9] + adds $acc4,$acc4,$t0 + umulh $t0,$a6,$a1 + adcs $acc5,$acc5,$t1 + umulh $t1,$a7,$a1 + adcs $acc6,$acc6,$t2 + mul $t2,$a3,$a2 // lo(a[3..7]*a[2]) (iii) + adcs $acc7,$acc7,$t3 + mul $t3,$a4,$a2 + adcs $acc0,$acc0,$t0 + mul $t0,$a5,$a2 + adc $acc1,$acc1,$t1 + + mul $t1,$a6,$a2 + adds $acc5,$acc5,$t2 + mul $t2,$a7,$a2 + adcs $acc6,$acc6,$t3 + umulh $t3,$a3,$a2 // hi(a[3..7]*a[2]) + adcs $acc7,$acc7,$t0 + umulh $t0,$a4,$a2 + adcs $acc0,$acc0,$t1 + umulh $t1,$a5,$a2 + adcs $acc1,$acc1,$t2 + umulh $t2,$a6,$a2 + stp $acc4,$acc5,[$tp],#8*2 // t[4..5] + adc $acc2,xzr,xzr // t[10] + adds $acc6,$acc6,$t3 + umulh $t3,$a7,$a2 + adcs $acc7,$acc7,$t0 + mul $t0,$a4,$a3 // lo(a[4..7]*a[3]) (iv) + adcs $acc0,$acc0,$t1 + mul $t1,$a5,$a3 + adcs $acc1,$acc1,$t2 + mul $t2,$a6,$a3 + adc $acc2,$acc2,$t3 + + mul $t3,$a7,$a3 + adds $acc7,$acc7,$t0 + umulh $t0,$a4,$a3 // hi(a[4..7]*a[3]) + adcs $acc0,$acc0,$t1 + umulh $t1,$a5,$a3 + adcs $acc1,$acc1,$t2 + umulh $t2,$a6,$a3 + adcs $acc2,$acc2,$t3 + umulh $t3,$a7,$a3 + stp $acc6,$acc7,[$tp],#8*2 // t[6..7] + adc $acc3,xzr,xzr // t[11] + adds $acc0,$acc0,$t0 + mul $t0,$a5,$a4 // lo(a[5..7]*a[4]) (v) + adcs $acc1,$acc1,$t1 + mul $t1,$a6,$a4 + adcs $acc2,$acc2,$t2 + mul $t2,$a7,$a4 + adc $acc3,$acc3,$t3 + + umulh $t3,$a5,$a4 // hi(a[5..7]*a[4]) + adds $acc1,$acc1,$t0 + umulh $t0,$a6,$a4 + adcs $acc2,$acc2,$t1 + umulh $t1,$a7,$a4 + adcs $acc3,$acc3,$t2 + mul $t2,$a6,$a5 // lo(a[6..7]*a[5]) (vi) + adc $acc4,xzr,xzr // t[12] + adds $acc2,$acc2,$t3 + mul $t3,$a7,$a5 + adcs $acc3,$acc3,$t0 + umulh $t0,$a6,$a5 // hi(a[6..7]*a[5]) + adc $acc4,$acc4,$t1 + + umulh $t1,$a7,$a5 + adds $acc3,$acc3,$t2 + mul $t2,$a7,$a6 // lo(a[7]*a[6]) (vii) + adcs $acc4,$acc4,$t3 + umulh $t3,$a7,$a6 // hi(a[7]*a[6]) + adc $acc5,xzr,xzr // t[13] + adds $acc4,$acc4,$t0 + sub $cnt,$ap_end,$ap // done yet? + adc $acc5,$acc5,$t1 + + adds $acc5,$acc5,$t2 + sub $t0,$ap_end,$num // rewinded ap + adc $acc6,xzr,xzr // t[14] + add $acc6,$acc6,$t3 + + cbz $cnt,.Lsqr8x_outer_break + + mov $n0,$a0 + ldp $a0,$a1,[$tp,#8*0] + ldp $a2,$a3,[$tp,#8*2] + ldp $a4,$a5,[$tp,#8*4] + ldp $a6,$a7,[$tp,#8*6] + adds $acc0,$acc0,$a0 + adcs $acc1,$acc1,$a1 + ldp $a0,$a1,[$ap,#8*0] + adcs $acc2,$acc2,$a2 + adcs $acc3,$acc3,$a3 + ldp $a2,$a3,[$ap,#8*2] + adcs $acc4,$acc4,$a4 + adcs $acc5,$acc5,$a5 + ldp $a4,$a5,[$ap,#8*4] + adcs $acc6,$acc6,$a6 + mov $rp,$ap + adcs $acc7,xzr,$a7 + ldp $a6,$a7,[$ap,#8*6] + add $ap,$ap,#8*8 + //adc $carry,xzr,xzr // moved below + mov $cnt,#-8*8 + + // a[8]a[0] + // a[9]a[0] + // a[a]a[0] + // a[b]a[0] + // a[c]a[0] + // a[d]a[0] + // a[e]a[0] + // a[f]a[0] + // a[8]a[1] + // a[f]a[1]........................ + // a[8]a[2] + // a[f]a[2]........................ + // a[8]a[3] + // a[f]a[3]........................ + // a[8]a[4] + // a[f]a[4]........................ + // a[8]a[5] + // a[f]a[5]........................ + // a[8]a[6] + // a[f]a[6]........................ + // a[8]a[7] + // a[f]a[7]........................ +.Lsqr8x_mul: + mul $t0,$a0,$n0 + adc $carry,xzr,xzr // carry bit, modulo-scheduled + mul $t1,$a1,$n0 + add $cnt,$cnt,#8 + mul $t2,$a2,$n0 + mul $t3,$a3,$n0 + adds $acc0,$acc0,$t0 + mul $t0,$a4,$n0 + adcs $acc1,$acc1,$t1 + mul $t1,$a5,$n0 + adcs $acc2,$acc2,$t2 + mul $t2,$a6,$n0 + adcs $acc3,$acc3,$t3 + mul $t3,$a7,$n0 + adcs $acc4,$acc4,$t0 + umulh $t0,$a0,$n0 + adcs $acc5,$acc5,$t1 + umulh $t1,$a1,$n0 + adcs $acc6,$acc6,$t2 + umulh $t2,$a2,$n0 + adcs $acc7,$acc7,$t3 + umulh $t3,$a3,$n0 + adc $carry,$carry,xzr + str $acc0,[$tp],#8 + adds $acc0,$acc1,$t0 + umulh $t0,$a4,$n0 + adcs $acc1,$acc2,$t1 + umulh $t1,$a5,$n0 + adcs $acc2,$acc3,$t2 + umulh $t2,$a6,$n0 + adcs $acc3,$acc4,$t3 + umulh $t3,$a7,$n0 + ldr $n0,[$rp,$cnt] + adcs $acc4,$acc5,$t0 + adcs $acc5,$acc6,$t1 + adcs $acc6,$acc7,$t2 + adcs $acc7,$carry,$t3 + //adc $carry,xzr,xzr // moved above + cbnz $cnt,.Lsqr8x_mul + // note that carry flag is guaranteed + // to be zero at this point + cmp $ap,$ap_end // done yet? + b.eq .Lsqr8x_break + + ldp $a0,$a1,[$tp,#8*0] + ldp $a2,$a3,[$tp,#8*2] + ldp $a4,$a5,[$tp,#8*4] + ldp $a6,$a7,[$tp,#8*6] + adds $acc0,$acc0,$a0 + ldr $n0,[$rp,#-8*8] + adcs $acc1,$acc1,$a1 + ldp $a0,$a1,[$ap,#8*0] + adcs $acc2,$acc2,$a2 + adcs $acc3,$acc3,$a3 + ldp $a2,$a3,[$ap,#8*2] + adcs $acc4,$acc4,$a4 + adcs $acc5,$acc5,$a5 + ldp $a4,$a5,[$ap,#8*4] + adcs $acc6,$acc6,$a6 + mov $cnt,#-8*8 + adcs $acc7,$acc7,$a7 + ldp $a6,$a7,[$ap,#8*6] + add $ap,$ap,#8*8 + //adc $carry,xzr,xzr // moved above + b .Lsqr8x_mul + +.align 4 +.Lsqr8x_break: + ldp $a0,$a1,[$rp,#8*0] + add $ap,$rp,#8*8 + ldp $a2,$a3,[$rp,#8*2] + sub $t0,$ap_end,$ap // is it last iteration? + ldp $a4,$a5,[$rp,#8*4] + sub $t1,$tp,$t0 + ldp $a6,$a7,[$rp,#8*6] + cbz $t0,.Lsqr8x_outer_loop + + stp $acc0,$acc1,[$tp,#8*0] + ldp $acc0,$acc1,[$t1,#8*0] + stp $acc2,$acc3,[$tp,#8*2] + ldp $acc2,$acc3,[$t1,#8*2] + stp $acc4,$acc5,[$tp,#8*4] + ldp $acc4,$acc5,[$t1,#8*4] + stp $acc6,$acc7,[$tp,#8*6] + mov $tp,$t1 + ldp $acc6,$acc7,[$t1,#8*6] + b .Lsqr8x_outer_loop + +.align 4 +.Lsqr8x_outer_break: + // Now multiply above result by 2 and add a[n-1]*a[n-1]|...|a[0]*a[0] + ldp $a1,$a3,[$t0,#8*0] // recall that $t0 is &a[0] + ldp $t1,$t2,[sp,#8*1] + ldp $a5,$a7,[$t0,#8*2] + add $ap,$t0,#8*4 + ldp $t3,$t0,[sp,#8*3] + + stp $acc0,$acc1,[$tp,#8*0] + mul $acc0,$a1,$a1 + stp $acc2,$acc3,[$tp,#8*2] + umulh $a1,$a1,$a1 + stp $acc4,$acc5,[$tp,#8*4] + mul $a2,$a3,$a3 + stp $acc6,$acc7,[$tp,#8*6] + mov $tp,sp + umulh $a3,$a3,$a3 + adds $acc1,$a1,$t1,lsl#1 + extr $t1,$t2,$t1,#63 + sub $cnt,$num,#8*4 + +.Lsqr4x_shift_n_add: + adcs $acc2,$a2,$t1 + extr $t2,$t3,$t2,#63 + sub $cnt,$cnt,#8*4 + adcs $acc3,$a3,$t2 + ldp $t1,$t2,[$tp,#8*5] + mul $a4,$a5,$a5 + ldp $a1,$a3,[$ap],#8*2 + umulh $a5,$a5,$a5 + mul $a6,$a7,$a7 + umulh $a7,$a7,$a7 + extr $t3,$t0,$t3,#63 + stp $acc0,$acc1,[$tp,#8*0] + adcs $acc4,$a4,$t3 + extr $t0,$t1,$t0,#63 + stp $acc2,$acc3,[$tp,#8*2] + adcs $acc5,$a5,$t0 + ldp $t3,$t0,[$tp,#8*7] + extr $t1,$t2,$t1,#63 + adcs $acc6,$a6,$t1 + extr $t2,$t3,$t2,#63 + adcs $acc7,$a7,$t2 + ldp $t1,$t2,[$tp,#8*9] + mul $a0,$a1,$a1 + ldp $a5,$a7,[$ap],#8*2 + umulh $a1,$a1,$a1 + mul $a2,$a3,$a3 + umulh $a3,$a3,$a3 + stp $acc4,$acc5,[$tp,#8*4] + extr $t3,$t0,$t3,#63 + stp $acc6,$acc7,[$tp,#8*6] + add $tp,$tp,#8*8 + adcs $acc0,$a0,$t3 + extr $t0,$t1,$t0,#63 + adcs $acc1,$a1,$t0 + ldp $t3,$t0,[$tp,#8*3] + extr $t1,$t2,$t1,#63 + cbnz $cnt,.Lsqr4x_shift_n_add +___ +my ($np,$np_end)=($ap,$ap_end); +$code.=<<___; + ldp $np,$n0,[x29,#104] // pull np and n0 + + adcs $acc2,$a2,$t1 + extr $t2,$t3,$t2,#63 + adcs $acc3,$a3,$t2 + ldp $t1,$t2,[$tp,#8*5] + mul $a4,$a5,$a5 + umulh $a5,$a5,$a5 + stp $acc0,$acc1,[$tp,#8*0] + mul $a6,$a7,$a7 + umulh $a7,$a7,$a7 + stp $acc2,$acc3,[$tp,#8*2] + extr $t3,$t0,$t3,#63 + adcs $acc4,$a4,$t3 + extr $t0,$t1,$t0,#63 + ldp $acc0,$acc1,[sp,#8*0] + adcs $acc5,$a5,$t0 + extr $t1,$t2,$t1,#63 + ldp $a0,$a1,[$np,#8*0] + adcs $acc6,$a6,$t1 + extr $t2,xzr,$t2,#63 + ldp $a2,$a3,[$np,#8*2] + adc $acc7,$a7,$t2 + ldp $a4,$a5,[$np,#8*4] + + // Reduce by 512 bits per iteration + mul $na0,$n0,$acc0 // t[0]*n0 + ldp $a6,$a7,[$np,#8*6] + add $np_end,$np,$num + ldp $acc2,$acc3,[sp,#8*2] + stp $acc4,$acc5,[$tp,#8*4] + ldp $acc4,$acc5,[sp,#8*4] + stp $acc6,$acc7,[$tp,#8*6] + ldp $acc6,$acc7,[sp,#8*6] + add $np,$np,#8*8 + mov $topmost,xzr // initial top-most carry + mov $tp,sp + mov $cnt,#8 + +.Lsqr8x_reduction: + // (*) mul $t0,$a0,$na0 // lo(n[0-7])*lo(t[0]*n0) + mul $t1,$a1,$na0 + sub $cnt,$cnt,#1 + mul $t2,$a2,$na0 + str $na0,[$tp],#8 // put aside t[0]*n0 for tail processing + mul $t3,$a3,$na0 + // (*) adds xzr,$acc0,$t0 + subs xzr,$acc0,#1 // (*) + mul $t0,$a4,$na0 + adcs $acc0,$acc1,$t1 + mul $t1,$a5,$na0 + adcs $acc1,$acc2,$t2 + mul $t2,$a6,$na0 + adcs $acc2,$acc3,$t3 + mul $t3,$a7,$na0 + adcs $acc3,$acc4,$t0 + umulh $t0,$a0,$na0 // hi(n[0-7])*lo(t[0]*n0) + adcs $acc4,$acc5,$t1 + umulh $t1,$a1,$na0 + adcs $acc5,$acc6,$t2 + umulh $t2,$a2,$na0 + adcs $acc6,$acc7,$t3 + umulh $t3,$a3,$na0 + adc $acc7,xzr,xzr + adds $acc0,$acc0,$t0 + umulh $t0,$a4,$na0 + adcs $acc1,$acc1,$t1 + umulh $t1,$a5,$na0 + adcs $acc2,$acc2,$t2 + umulh $t2,$a6,$na0 + adcs $acc3,$acc3,$t3 + umulh $t3,$a7,$na0 + mul $na0,$n0,$acc0 // next t[0]*n0 + adcs $acc4,$acc4,$t0 + adcs $acc5,$acc5,$t1 + adcs $acc6,$acc6,$t2 + adc $acc7,$acc7,$t3 + cbnz $cnt,.Lsqr8x_reduction + + ldp $t0,$t1,[$tp,#8*0] + ldp $t2,$t3,[$tp,#8*2] + mov $rp,$tp + sub $cnt,$np_end,$np // done yet? + adds $acc0,$acc0,$t0 + adcs $acc1,$acc1,$t1 + ldp $t0,$t1,[$tp,#8*4] + adcs $acc2,$acc2,$t2 + adcs $acc3,$acc3,$t3 + ldp $t2,$t3,[$tp,#8*6] + adcs $acc4,$acc4,$t0 + adcs $acc5,$acc5,$t1 + adcs $acc6,$acc6,$t2 + adcs $acc7,$acc7,$t3 + //adc $carry,xzr,xzr // moved below + cbz $cnt,.Lsqr8x8_post_condition + + ldr $n0,[$tp,#-8*8] + ldp $a0,$a1,[$np,#8*0] + ldp $a2,$a3,[$np,#8*2] + ldp $a4,$a5,[$np,#8*4] + mov $cnt,#-8*8 + ldp $a6,$a7,[$np,#8*6] + add $np,$np,#8*8 + +.Lsqr8x_tail: + mul $t0,$a0,$n0 + adc $carry,xzr,xzr // carry bit, modulo-scheduled + mul $t1,$a1,$n0 + add $cnt,$cnt,#8 + mul $t2,$a2,$n0 + mul $t3,$a3,$n0 + adds $acc0,$acc0,$t0 + mul $t0,$a4,$n0 + adcs $acc1,$acc1,$t1 + mul $t1,$a5,$n0 + adcs $acc2,$acc2,$t2 + mul $t2,$a6,$n0 + adcs $acc3,$acc3,$t3 + mul $t3,$a7,$n0 + adcs $acc4,$acc4,$t0 + umulh $t0,$a0,$n0 + adcs $acc5,$acc5,$t1 + umulh $t1,$a1,$n0 + adcs $acc6,$acc6,$t2 + umulh $t2,$a2,$n0 + adcs $acc7,$acc7,$t3 + umulh $t3,$a3,$n0 + adc $carry,$carry,xzr + str $acc0,[$tp],#8 + adds $acc0,$acc1,$t0 + umulh $t0,$a4,$n0 + adcs $acc1,$acc2,$t1 + umulh $t1,$a5,$n0 + adcs $acc2,$acc3,$t2 + umulh $t2,$a6,$n0 + adcs $acc3,$acc4,$t3 + umulh $t3,$a7,$n0 + ldr $n0,[$rp,$cnt] + adcs $acc4,$acc5,$t0 + adcs $acc5,$acc6,$t1 + adcs $acc6,$acc7,$t2 + adcs $acc7,$carry,$t3 + //adc $carry,xzr,xzr // moved above + cbnz $cnt,.Lsqr8x_tail + // note that carry flag is guaranteed + // to be zero at this point + ldp $a0,$a1,[$tp,#8*0] + sub $cnt,$np_end,$np // done yet? + sub $t2,$np_end,$num // rewinded np + ldp $a2,$a3,[$tp,#8*2] + ldp $a4,$a5,[$tp,#8*4] + ldp $a6,$a7,[$tp,#8*6] + cbz $cnt,.Lsqr8x_tail_break + + ldr $n0,[$rp,#-8*8] + adds $acc0,$acc0,$a0 + adcs $acc1,$acc1,$a1 + ldp $a0,$a1,[$np,#8*0] + adcs $acc2,$acc2,$a2 + adcs $acc3,$acc3,$a3 + ldp $a2,$a3,[$np,#8*2] + adcs $acc4,$acc4,$a4 + adcs $acc5,$acc5,$a5 + ldp $a4,$a5,[$np,#8*4] + adcs $acc6,$acc6,$a6 + mov $cnt,#-8*8 + adcs $acc7,$acc7,$a7 + ldp $a6,$a7,[$np,#8*6] + add $np,$np,#8*8 + //adc $carry,xzr,xzr // moved above + b .Lsqr8x_tail + +.align 4 +.Lsqr8x_tail_break: + ldr $n0,[x29,#112] // pull n0 + add $cnt,$tp,#8*8 // end of current t[num] window + + subs xzr,$topmost,#1 // "move" top-most carry to carry bit + adcs $t0,$acc0,$a0 + adcs $t1,$acc1,$a1 + ldp $acc0,$acc1,[$rp,#8*0] + adcs $acc2,$acc2,$a2 + ldp $a0,$a1,[$t2,#8*0] // recall that $t2 is &n[0] + adcs $acc3,$acc3,$a3 + ldp $a2,$a3,[$t2,#8*2] + adcs $acc4,$acc4,$a4 + adcs $acc5,$acc5,$a5 + ldp $a4,$a5,[$t2,#8*4] + adcs $acc6,$acc6,$a6 + adcs $acc7,$acc7,$a7 + ldp $a6,$a7,[$t2,#8*6] + add $np,$t2,#8*8 + adc $topmost,xzr,xzr // top-most carry + mul $na0,$n0,$acc0 + stp $t0,$t1,[$tp,#8*0] + stp $acc2,$acc3,[$tp,#8*2] + ldp $acc2,$acc3,[$rp,#8*2] + stp $acc4,$acc5,[$tp,#8*4] + ldp $acc4,$acc5,[$rp,#8*4] + cmp $cnt,x29 // did we hit the bottom? + stp $acc6,$acc7,[$tp,#8*6] + mov $tp,$rp // slide the window + ldp $acc6,$acc7,[$rp,#8*6] + mov $cnt,#8 + b.ne .Lsqr8x_reduction + + // Final step. We see if result is larger than modulus, and + // if it is, subtract the modulus. But comparison implies + // subtraction. So we subtract modulus, see if it borrowed, + // and conditionally copy original value. + ldr $rp,[x29,#96] // pull rp + add $tp,$tp,#8*8 + subs $t0,$acc0,$a0 + sbcs $t1,$acc1,$a1 + sub $cnt,$num,#8*8 + mov $ap_end,$rp // $rp copy + +.Lsqr8x_sub: + sbcs $t2,$acc2,$a2 + ldp $a0,$a1,[$np,#8*0] + sbcs $t3,$acc3,$a3 + stp $t0,$t1,[$rp,#8*0] + sbcs $t0,$acc4,$a4 + ldp $a2,$a3,[$np,#8*2] + sbcs $t1,$acc5,$a5 + stp $t2,$t3,[$rp,#8*2] + sbcs $t2,$acc6,$a6 + ldp $a4,$a5,[$np,#8*4] + sbcs $t3,$acc7,$a7 + ldp $a6,$a7,[$np,#8*6] + add $np,$np,#8*8 + ldp $acc0,$acc1,[$tp,#8*0] + sub $cnt,$cnt,#8*8 + ldp $acc2,$acc3,[$tp,#8*2] + ldp $acc4,$acc5,[$tp,#8*4] + ldp $acc6,$acc7,[$tp,#8*6] + add $tp,$tp,#8*8 + stp $t0,$t1,[$rp,#8*4] + sbcs $t0,$acc0,$a0 + stp $t2,$t3,[$rp,#8*6] + add $rp,$rp,#8*8 + sbcs $t1,$acc1,$a1 + cbnz $cnt,.Lsqr8x_sub + + sbcs $t2,$acc2,$a2 + mov $tp,sp + add $ap,sp,$num + ldp $a0,$a1,[$ap_end,#8*0] + sbcs $t3,$acc3,$a3 + stp $t0,$t1,[$rp,#8*0] + sbcs $t0,$acc4,$a4 + ldp $a2,$a3,[$ap_end,#8*2] + sbcs $t1,$acc5,$a5 + stp $t2,$t3,[$rp,#8*2] + sbcs $t2,$acc6,$a6 + ldp $acc0,$acc1,[$ap,#8*0] + sbcs $t3,$acc7,$a7 + ldp $acc2,$acc3,[$ap,#8*2] + sbcs xzr,$topmost,xzr // did it borrow? + ldr x30,[x29,#8] // pull return address + stp $t0,$t1,[$rp,#8*4] + stp $t2,$t3,[$rp,#8*6] + + sub $cnt,$num,#8*4 +.Lsqr4x_cond_copy: + sub $cnt,$cnt,#8*4 + csel $t0,$acc0,$a0,lo + stp xzr,xzr,[$tp,#8*0] + csel $t1,$acc1,$a1,lo + ldp $a0,$a1,[$ap_end,#8*4] + ldp $acc0,$acc1,[$ap,#8*4] + csel $t2,$acc2,$a2,lo + stp xzr,xzr,[$tp,#8*2] + add $tp,$tp,#8*4 + csel $t3,$acc3,$a3,lo + ldp $a2,$a3,[$ap_end,#8*6] + ldp $acc2,$acc3,[$ap,#8*6] + add $ap,$ap,#8*4 + stp $t0,$t1,[$ap_end,#8*0] + stp $t2,$t3,[$ap_end,#8*2] + add $ap_end,$ap_end,#8*4 + stp xzr,xzr,[$ap,#8*0] + stp xzr,xzr,[$ap,#8*2] + cbnz $cnt,.Lsqr4x_cond_copy + + csel $t0,$acc0,$a0,lo + stp xzr,xzr,[$tp,#8*0] + csel $t1,$acc1,$a1,lo + stp xzr,xzr,[$tp,#8*2] + csel $t2,$acc2,$a2,lo + csel $t3,$acc3,$a3,lo + stp $t0,$t1,[$ap_end,#8*0] + stp $t2,$t3,[$ap_end,#8*2] + + b .Lsqr8x_done + +.align 4 +.Lsqr8x8_post_condition: + adc $carry,xzr,xzr + ldr x30,[x29,#8] // pull return address + // $acc0-7,$carry hold result, $a0-7 hold modulus + subs $a0,$acc0,$a0 + ldr $ap,[x29,#96] // pull rp + sbcs $a1,$acc1,$a1 + stp xzr,xzr,[sp,#8*0] + sbcs $a2,$acc2,$a2 + stp xzr,xzr,[sp,#8*2] + sbcs $a3,$acc3,$a3 + stp xzr,xzr,[sp,#8*4] + sbcs $a4,$acc4,$a4 + stp xzr,xzr,[sp,#8*6] + sbcs $a5,$acc5,$a5 + stp xzr,xzr,[sp,#8*8] + sbcs $a6,$acc6,$a6 + stp xzr,xzr,[sp,#8*10] + sbcs $a7,$acc7,$a7 + stp xzr,xzr,[sp,#8*12] + sbcs $carry,$carry,xzr // did it borrow? + stp xzr,xzr,[sp,#8*14] + + // $a0-7 hold result-modulus + csel $a0,$acc0,$a0,lo + csel $a1,$acc1,$a1,lo + csel $a2,$acc2,$a2,lo + csel $a3,$acc3,$a3,lo + stp $a0,$a1,[$ap,#8*0] + csel $a4,$acc4,$a4,lo + csel $a5,$acc5,$a5,lo + stp $a2,$a3,[$ap,#8*2] + csel $a6,$acc6,$a6,lo + csel $a7,$acc7,$a7,lo + stp $a4,$a5,[$ap,#8*4] + stp $a6,$a7,[$ap,#8*6] + +.Lsqr8x_done: + ldp x19,x20,[x29,#16] + mov sp,x29 + ldp x21,x22,[x29,#32] + mov x0,#1 + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x27,x28,[x29,#80] + ldr x29,[sp],#128 + .inst 0xd50323bf // autiasp + ret +.size __bn_sqr8x_mont,.-__bn_sqr8x_mont +___ +} + +{ +######################################################################## +# Even though this might look as ARMv8 adaptation of mulx4x_mont from +# x86_64-mont5 module, it's different in sense that it performs +# reduction 256 bits at a time. + +my ($a0,$a1,$a2,$a3, + $t0,$t1,$t2,$t3, + $m0,$m1,$m2,$m3, + $acc0,$acc1,$acc2,$acc3,$acc4, + $bi,$mi,$tp,$ap_end,$cnt) = map("x$_",(6..17,19..28)); +my $bp_end=$rp; +my ($carry,$topmost) = ($rp,"x30"); + +$code.=<<___; +.type __bn_mul4x_mont,%function +.align 5 +__bn_mul4x_mont: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-128]! + add x29,sp,#0 + stp x19,x20,[sp,#16] + stp x21,x22,[sp,#32] + stp x23,x24,[sp,#48] + stp x25,x26,[sp,#64] + stp x27,x28,[sp,#80] + + sub $tp,sp,$num,lsl#3 + lsl $num,$num,#3 + ldr $n0,[$n0] // *n0 + sub sp,$tp,#8*4 // alloca + + add $t0,$bp,$num + add $ap_end,$ap,$num + stp $rp,$t0,[x29,#96] // offload rp and &b[num] + + ldr $bi,[$bp,#8*0] // b[0] + ldp $a0,$a1,[$ap,#8*0] // a[0..3] + ldp $a2,$a3,[$ap,#8*2] + add $ap,$ap,#8*4 + mov $acc0,xzr + mov $acc1,xzr + mov $acc2,xzr + mov $acc3,xzr + ldp $m0,$m1,[$np,#8*0] // n[0..3] + ldp $m2,$m3,[$np,#8*2] + adds $np,$np,#8*4 // clear carry bit + mov $carry,xzr + mov $cnt,#0 + mov $tp,sp + +.Loop_mul4x_1st_reduction: + mul $t0,$a0,$bi // lo(a[0..3]*b[0]) + adc $carry,$carry,xzr // modulo-scheduled + mul $t1,$a1,$bi + add $cnt,$cnt,#8 + mul $t2,$a2,$bi + and $cnt,$cnt,#31 + mul $t3,$a3,$bi + adds $acc0,$acc0,$t0 + umulh $t0,$a0,$bi // hi(a[0..3]*b[0]) + adcs $acc1,$acc1,$t1 + mul $mi,$acc0,$n0 // t[0]*n0 + adcs $acc2,$acc2,$t2 + umulh $t1,$a1,$bi + adcs $acc3,$acc3,$t3 + umulh $t2,$a2,$bi + adc $acc4,xzr,xzr + umulh $t3,$a3,$bi + ldr $bi,[$bp,$cnt] // next b[i] (or b[0]) + adds $acc1,$acc1,$t0 + // (*) mul $t0,$m0,$mi // lo(n[0..3]*t[0]*n0) + str $mi,[$tp],#8 // put aside t[0]*n0 for tail processing + adcs $acc2,$acc2,$t1 + mul $t1,$m1,$mi + adcs $acc3,$acc3,$t2 + mul $t2,$m2,$mi + adc $acc4,$acc4,$t3 // can't overflow + mul $t3,$m3,$mi + // (*) adds xzr,$acc0,$t0 + subs xzr,$acc0,#1 // (*) + umulh $t0,$m0,$mi // hi(n[0..3]*t[0]*n0) + adcs $acc0,$acc1,$t1 + umulh $t1,$m1,$mi + adcs $acc1,$acc2,$t2 + umulh $t2,$m2,$mi + adcs $acc2,$acc3,$t3 + umulh $t3,$m3,$mi + adcs $acc3,$acc4,$carry + adc $carry,xzr,xzr + adds $acc0,$acc0,$t0 + sub $t0,$ap_end,$ap + adcs $acc1,$acc1,$t1 + adcs $acc2,$acc2,$t2 + adcs $acc3,$acc3,$t3 + //adc $carry,$carry,xzr + cbnz $cnt,.Loop_mul4x_1st_reduction + + cbz $t0,.Lmul4x4_post_condition + + ldp $a0,$a1,[$ap,#8*0] // a[4..7] + ldp $a2,$a3,[$ap,#8*2] + add $ap,$ap,#8*4 + ldr $mi,[sp] // a[0]*n0 + ldp $m0,$m1,[$np,#8*0] // n[4..7] + ldp $m2,$m3,[$np,#8*2] + add $np,$np,#8*4 + +.Loop_mul4x_1st_tail: + mul $t0,$a0,$bi // lo(a[4..7]*b[i]) + adc $carry,$carry,xzr // modulo-scheduled + mul $t1,$a1,$bi + add $cnt,$cnt,#8 + mul $t2,$a2,$bi + and $cnt,$cnt,#31 + mul $t3,$a3,$bi + adds $acc0,$acc0,$t0 + umulh $t0,$a0,$bi // hi(a[4..7]*b[i]) + adcs $acc1,$acc1,$t1 + umulh $t1,$a1,$bi + adcs $acc2,$acc2,$t2 + umulh $t2,$a2,$bi + adcs $acc3,$acc3,$t3 + umulh $t3,$a3,$bi + adc $acc4,xzr,xzr + ldr $bi,[$bp,$cnt] // next b[i] (or b[0]) + adds $acc1,$acc1,$t0 + mul $t0,$m0,$mi // lo(n[4..7]*a[0]*n0) + adcs $acc2,$acc2,$t1 + mul $t1,$m1,$mi + adcs $acc3,$acc3,$t2 + mul $t2,$m2,$mi + adc $acc4,$acc4,$t3 // can't overflow + mul $t3,$m3,$mi + adds $acc0,$acc0,$t0 + umulh $t0,$m0,$mi // hi(n[4..7]*a[0]*n0) + adcs $acc1,$acc1,$t1 + umulh $t1,$m1,$mi + adcs $acc2,$acc2,$t2 + umulh $t2,$m2,$mi + adcs $acc3,$acc3,$t3 + adcs $acc4,$acc4,$carry + umulh $t3,$m3,$mi + adc $carry,xzr,xzr + ldr $mi,[sp,$cnt] // next t[0]*n0 + str $acc0,[$tp],#8 // result!!! + adds $acc0,$acc1,$t0 + sub $t0,$ap_end,$ap // done yet? + adcs $acc1,$acc2,$t1 + adcs $acc2,$acc3,$t2 + adcs $acc3,$acc4,$t3 + //adc $carry,$carry,xzr + cbnz $cnt,.Loop_mul4x_1st_tail + + sub $t1,$ap_end,$num // rewinded $ap + cbz $t0,.Lmul4x_proceed + + ldp $a0,$a1,[$ap,#8*0] + ldp $a2,$a3,[$ap,#8*2] + add $ap,$ap,#8*4 + ldp $m0,$m1,[$np,#8*0] + ldp $m2,$m3,[$np,#8*2] + add $np,$np,#8*4 + b .Loop_mul4x_1st_tail + +.align 5 +.Lmul4x_proceed: + ldr $bi,[$bp,#8*4]! // *++b + adc $topmost,$carry,xzr + ldp $a0,$a1,[$t1,#8*0] // a[0..3] + sub $np,$np,$num // rewind np + ldp $a2,$a3,[$t1,#8*2] + add $ap,$t1,#8*4 + + stp $acc0,$acc1,[$tp,#8*0] // result!!! + ldp $acc0,$acc1,[sp,#8*4] // t[0..3] + stp $acc2,$acc3,[$tp,#8*2] // result!!! + ldp $acc2,$acc3,[sp,#8*6] + + ldp $m0,$m1,[$np,#8*0] // n[0..3] + mov $tp,sp + ldp $m2,$m3,[$np,#8*2] + adds $np,$np,#8*4 // clear carry bit + mov $carry,xzr + +.align 4 +.Loop_mul4x_reduction: + mul $t0,$a0,$bi // lo(a[0..3]*b[4]) + adc $carry,$carry,xzr // modulo-scheduled + mul $t1,$a1,$bi + add $cnt,$cnt,#8 + mul $t2,$a2,$bi + and $cnt,$cnt,#31 + mul $t3,$a3,$bi + adds $acc0,$acc0,$t0 + umulh $t0,$a0,$bi // hi(a[0..3]*b[4]) + adcs $acc1,$acc1,$t1 + mul $mi,$acc0,$n0 // t[0]*n0 + adcs $acc2,$acc2,$t2 + umulh $t1,$a1,$bi + adcs $acc3,$acc3,$t3 + umulh $t2,$a2,$bi + adc $acc4,xzr,xzr + umulh $t3,$a3,$bi + ldr $bi,[$bp,$cnt] // next b[i] + adds $acc1,$acc1,$t0 + // (*) mul $t0,$m0,$mi + str $mi,[$tp],#8 // put aside t[0]*n0 for tail processing + adcs $acc2,$acc2,$t1 + mul $t1,$m1,$mi // lo(n[0..3]*t[0]*n0 + adcs $acc3,$acc3,$t2 + mul $t2,$m2,$mi + adc $acc4,$acc4,$t3 // can't overflow + mul $t3,$m3,$mi + // (*) adds xzr,$acc0,$t0 + subs xzr,$acc0,#1 // (*) + umulh $t0,$m0,$mi // hi(n[0..3]*t[0]*n0 + adcs $acc0,$acc1,$t1 + umulh $t1,$m1,$mi + adcs $acc1,$acc2,$t2 + umulh $t2,$m2,$mi + adcs $acc2,$acc3,$t3 + umulh $t3,$m3,$mi + adcs $acc3,$acc4,$carry + adc $carry,xzr,xzr + adds $acc0,$acc0,$t0 + adcs $acc1,$acc1,$t1 + adcs $acc2,$acc2,$t2 + adcs $acc3,$acc3,$t3 + //adc $carry,$carry,xzr + cbnz $cnt,.Loop_mul4x_reduction + + adc $carry,$carry,xzr + ldp $t0,$t1,[$tp,#8*4] // t[4..7] + ldp $t2,$t3,[$tp,#8*6] + ldp $a0,$a1,[$ap,#8*0] // a[4..7] + ldp $a2,$a3,[$ap,#8*2] + add $ap,$ap,#8*4 + adds $acc0,$acc0,$t0 + adcs $acc1,$acc1,$t1 + adcs $acc2,$acc2,$t2 + adcs $acc3,$acc3,$t3 + //adc $carry,$carry,xzr + + ldr $mi,[sp] // t[0]*n0 + ldp $m0,$m1,[$np,#8*0] // n[4..7] + ldp $m2,$m3,[$np,#8*2] + add $np,$np,#8*4 + +.align 4 +.Loop_mul4x_tail: + mul $t0,$a0,$bi // lo(a[4..7]*b[4]) + adc $carry,$carry,xzr // modulo-scheduled + mul $t1,$a1,$bi + add $cnt,$cnt,#8 + mul $t2,$a2,$bi + and $cnt,$cnt,#31 + mul $t3,$a3,$bi + adds $acc0,$acc0,$t0 + umulh $t0,$a0,$bi // hi(a[4..7]*b[4]) + adcs $acc1,$acc1,$t1 + umulh $t1,$a1,$bi + adcs $acc2,$acc2,$t2 + umulh $t2,$a2,$bi + adcs $acc3,$acc3,$t3 + umulh $t3,$a3,$bi + adc $acc4,xzr,xzr + ldr $bi,[$bp,$cnt] // next b[i] + adds $acc1,$acc1,$t0 + mul $t0,$m0,$mi // lo(n[4..7]*t[0]*n0) + adcs $acc2,$acc2,$t1 + mul $t1,$m1,$mi + adcs $acc3,$acc3,$t2 + mul $t2,$m2,$mi + adc $acc4,$acc4,$t3 // can't overflow + mul $t3,$m3,$mi + adds $acc0,$acc0,$t0 + umulh $t0,$m0,$mi // hi(n[4..7]*t[0]*n0) + adcs $acc1,$acc1,$t1 + umulh $t1,$m1,$mi + adcs $acc2,$acc2,$t2 + umulh $t2,$m2,$mi + adcs $acc3,$acc3,$t3 + umulh $t3,$m3,$mi + adcs $acc4,$acc4,$carry + ldr $mi,[sp,$cnt] // next a[0]*n0 + adc $carry,xzr,xzr + str $acc0,[$tp],#8 // result!!! + adds $acc0,$acc1,$t0 + sub $t0,$ap_end,$ap // done yet? + adcs $acc1,$acc2,$t1 + adcs $acc2,$acc3,$t2 + adcs $acc3,$acc4,$t3 + //adc $carry,$carry,xzr + cbnz $cnt,.Loop_mul4x_tail + + sub $t1,$np,$num // rewinded np? + adc $carry,$carry,xzr + cbz $t0,.Loop_mul4x_break + + ldp $t0,$t1,[$tp,#8*4] + ldp $t2,$t3,[$tp,#8*6] + ldp $a0,$a1,[$ap,#8*0] + ldp $a2,$a3,[$ap,#8*2] + add $ap,$ap,#8*4 + adds $acc0,$acc0,$t0 + adcs $acc1,$acc1,$t1 + adcs $acc2,$acc2,$t2 + adcs $acc3,$acc3,$t3 + //adc $carry,$carry,xzr + ldp $m0,$m1,[$np,#8*0] + ldp $m2,$m3,[$np,#8*2] + add $np,$np,#8*4 + b .Loop_mul4x_tail + +.align 4 +.Loop_mul4x_break: + ldp $t2,$t3,[x29,#96] // pull rp and &b[num] + adds $acc0,$acc0,$topmost + add $bp,$bp,#8*4 // bp++ + adcs $acc1,$acc1,xzr + sub $ap,$ap,$num // rewind ap + adcs $acc2,$acc2,xzr + stp $acc0,$acc1,[$tp,#8*0] // result!!! + adcs $acc3,$acc3,xzr + ldp $acc0,$acc1,[sp,#8*4] // t[0..3] + adc $topmost,$carry,xzr + stp $acc2,$acc3,[$tp,#8*2] // result!!! + cmp $bp,$t3 // done yet? + ldp $acc2,$acc3,[sp,#8*6] + ldp $m0,$m1,[$t1,#8*0] // n[0..3] + ldp $m2,$m3,[$t1,#8*2] + add $np,$t1,#8*4 + b.eq .Lmul4x_post + + ldr $bi,[$bp] + ldp $a0,$a1,[$ap,#8*0] // a[0..3] + ldp $a2,$a3,[$ap,#8*2] + adds $ap,$ap,#8*4 // clear carry bit + mov $carry,xzr + mov $tp,sp + b .Loop_mul4x_reduction + +.align 4 +.Lmul4x_post: + // Final step. We see if result is larger than modulus, and + // if it is, subtract the modulus. But comparison implies + // subtraction. So we subtract modulus, see if it borrowed, + // and conditionally copy original value. + mov $rp,$t2 + mov $ap_end,$t2 // $rp copy + subs $t0,$acc0,$m0 + add $tp,sp,#8*8 + sbcs $t1,$acc1,$m1 + sub $cnt,$num,#8*4 + +.Lmul4x_sub: + sbcs $t2,$acc2,$m2 + ldp $m0,$m1,[$np,#8*0] + sub $cnt,$cnt,#8*4 + ldp $acc0,$acc1,[$tp,#8*0] + sbcs $t3,$acc3,$m3 + ldp $m2,$m3,[$np,#8*2] + add $np,$np,#8*4 + ldp $acc2,$acc3,[$tp,#8*2] + add $tp,$tp,#8*4 + stp $t0,$t1,[$rp,#8*0] + sbcs $t0,$acc0,$m0 + stp $t2,$t3,[$rp,#8*2] + add $rp,$rp,#8*4 + sbcs $t1,$acc1,$m1 + cbnz $cnt,.Lmul4x_sub + + sbcs $t2,$acc2,$m2 + mov $tp,sp + add $ap,sp,#8*4 + ldp $a0,$a1,[$ap_end,#8*0] + sbcs $t3,$acc3,$m3 + stp $t0,$t1,[$rp,#8*0] + ldp $a2,$a3,[$ap_end,#8*2] + stp $t2,$t3,[$rp,#8*2] + ldp $acc0,$acc1,[$ap,#8*0] + ldp $acc2,$acc3,[$ap,#8*2] + sbcs xzr,$topmost,xzr // did it borrow? + ldr x30,[x29,#8] // pull return address + + sub $cnt,$num,#8*4 +.Lmul4x_cond_copy: + sub $cnt,$cnt,#8*4 + csel $t0,$acc0,$a0,lo + stp xzr,xzr,[$tp,#8*0] + csel $t1,$acc1,$a1,lo + ldp $a0,$a1,[$ap_end,#8*4] + ldp $acc0,$acc1,[$ap,#8*4] + csel $t2,$acc2,$a2,lo + stp xzr,xzr,[$tp,#8*2] + add $tp,$tp,#8*4 + csel $t3,$acc3,$a3,lo + ldp $a2,$a3,[$ap_end,#8*6] + ldp $acc2,$acc3,[$ap,#8*6] + add $ap,$ap,#8*4 + stp $t0,$t1,[$ap_end,#8*0] + stp $t2,$t3,[$ap_end,#8*2] + add $ap_end,$ap_end,#8*4 + cbnz $cnt,.Lmul4x_cond_copy + + csel $t0,$acc0,$a0,lo + stp xzr,xzr,[$tp,#8*0] + csel $t1,$acc1,$a1,lo + stp xzr,xzr,[$tp,#8*2] + csel $t2,$acc2,$a2,lo + stp xzr,xzr,[$tp,#8*3] + csel $t3,$acc3,$a3,lo + stp xzr,xzr,[$tp,#8*4] + stp $t0,$t1,[$ap_end,#8*0] + stp $t2,$t3,[$ap_end,#8*2] + + b .Lmul4x_done + +.align 4 +.Lmul4x4_post_condition: + adc $carry,$carry,xzr + ldr $ap,[x29,#96] // pull rp + // $acc0-3,$carry hold result, $m0-7 hold modulus + subs $a0,$acc0,$m0 + ldr x30,[x29,#8] // pull return address + sbcs $a1,$acc1,$m1 + stp xzr,xzr,[sp,#8*0] + sbcs $a2,$acc2,$m2 + stp xzr,xzr,[sp,#8*2] + sbcs $a3,$acc3,$m3 + stp xzr,xzr,[sp,#8*4] + sbcs xzr,$carry,xzr // did it borrow? + stp xzr,xzr,[sp,#8*6] + + // $a0-3 hold result-modulus + csel $a0,$acc0,$a0,lo + csel $a1,$acc1,$a1,lo + csel $a2,$acc2,$a2,lo + csel $a3,$acc3,$a3,lo + stp $a0,$a1,[$ap,#8*0] + stp $a2,$a3,[$ap,#8*2] + +.Lmul4x_done: + ldp x19,x20,[x29,#16] + mov sp,x29 + ldp x21,x22,[x29,#32] + mov x0,#1 + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x27,x28,[x29,#80] + ldr x29,[sp],#128 + .inst 0xd50323bf // autiasp + ret +.size __bn_mul4x_mont,.-__bn_mul4x_mont +___ +} +$code.=<<___; +.asciz "Montgomery Multiplication for ARMv8, CRYPTOGAMS by " +.align 4 +___ + +print $code; + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/bn-586.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/bn-586.pl new file mode 100644 index 000000000..58effc880 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/bn-586.pl @@ -0,0 +1,785 @@ +#! /usr/bin/env perl +# Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +$output = pop; +open STDOUT,">$output"; + +&asm_init($ARGV[0]); + +$sse2=0; +for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); } + +&external_label("OPENSSL_ia32cap_P") if ($sse2); + +&bn_mul_add_words("bn_mul_add_words"); +&bn_mul_words("bn_mul_words"); +&bn_sqr_words("bn_sqr_words"); +&bn_div_words("bn_div_words"); +&bn_add_words("bn_add_words"); +&bn_sub_words("bn_sub_words"); +&bn_sub_part_words("bn_sub_part_words"); + +&asm_finish(); + +close STDOUT; + +sub bn_mul_add_words + { + local($name)=@_; + + &function_begin_B($name,$sse2?"EXTRN\t_OPENSSL_ia32cap_P:DWORD":""); + + $r="eax"; + $a="edx"; + $c="ecx"; + + if ($sse2) { + &picmeup("eax","OPENSSL_ia32cap_P"); + &bt(&DWP(0,"eax"),26); + &jnc(&label("maw_non_sse2")); + + &mov($r,&wparam(0)); + &mov($a,&wparam(1)); + &mov($c,&wparam(2)); + &movd("mm0",&wparam(3)); # mm0 = w + &pxor("mm1","mm1"); # mm1 = carry_in + &jmp(&label("maw_sse2_entry")); + + &set_label("maw_sse2_unrolled",16); + &movd("mm3",&DWP(0,$r,"",0)); # mm3 = r[0] + &paddq("mm1","mm3"); # mm1 = carry_in + r[0] + &movd("mm2",&DWP(0,$a,"",0)); # mm2 = a[0] + &pmuludq("mm2","mm0"); # mm2 = w*a[0] + &movd("mm4",&DWP(4,$a,"",0)); # mm4 = a[1] + &pmuludq("mm4","mm0"); # mm4 = w*a[1] + &movd("mm6",&DWP(8,$a,"",0)); # mm6 = a[2] + &pmuludq("mm6","mm0"); # mm6 = w*a[2] + &movd("mm7",&DWP(12,$a,"",0)); # mm7 = a[3] + &pmuludq("mm7","mm0"); # mm7 = w*a[3] + &paddq("mm1","mm2"); # mm1 = carry_in + r[0] + w*a[0] + &movd("mm3",&DWP(4,$r,"",0)); # mm3 = r[1] + &paddq("mm3","mm4"); # mm3 = r[1] + w*a[1] + &movd("mm5",&DWP(8,$r,"",0)); # mm5 = r[2] + &paddq("mm5","mm6"); # mm5 = r[2] + w*a[2] + &movd("mm4",&DWP(12,$r,"",0)); # mm4 = r[3] + &paddq("mm7","mm4"); # mm7 = r[3] + w*a[3] + &movd(&DWP(0,$r,"",0),"mm1"); + &movd("mm2",&DWP(16,$a,"",0)); # mm2 = a[4] + &pmuludq("mm2","mm0"); # mm2 = w*a[4] + &psrlq("mm1",32); # mm1 = carry0 + &movd("mm4",&DWP(20,$a,"",0)); # mm4 = a[5] + &pmuludq("mm4","mm0"); # mm4 = w*a[5] + &paddq("mm1","mm3"); # mm1 = carry0 + r[1] + w*a[1] + &movd("mm6",&DWP(24,$a,"",0)); # mm6 = a[6] + &pmuludq("mm6","mm0"); # mm6 = w*a[6] + &movd(&DWP(4,$r,"",0),"mm1"); + &psrlq("mm1",32); # mm1 = carry1 + &movd("mm3",&DWP(28,$a,"",0)); # mm3 = a[7] + &add($a,32); + &pmuludq("mm3","mm0"); # mm3 = w*a[7] + &paddq("mm1","mm5"); # mm1 = carry1 + r[2] + w*a[2] + &movd("mm5",&DWP(16,$r,"",0)); # mm5 = r[4] + &paddq("mm2","mm5"); # mm2 = r[4] + w*a[4] + &movd(&DWP(8,$r,"",0),"mm1"); + &psrlq("mm1",32); # mm1 = carry2 + &paddq("mm1","mm7"); # mm1 = carry2 + r[3] + w*a[3] + &movd("mm5",&DWP(20,$r,"",0)); # mm5 = r[5] + &paddq("mm4","mm5"); # mm4 = r[5] + w*a[5] + &movd(&DWP(12,$r,"",0),"mm1"); + &psrlq("mm1",32); # mm1 = carry3 + &paddq("mm1","mm2"); # mm1 = carry3 + r[4] + w*a[4] + &movd("mm5",&DWP(24,$r,"",0)); # mm5 = r[6] + &paddq("mm6","mm5"); # mm6 = r[6] + w*a[6] + &movd(&DWP(16,$r,"",0),"mm1"); + &psrlq("mm1",32); # mm1 = carry4 + &paddq("mm1","mm4"); # mm1 = carry4 + r[5] + w*a[5] + &movd("mm5",&DWP(28,$r,"",0)); # mm5 = r[7] + &paddq("mm3","mm5"); # mm3 = r[7] + w*a[7] + &movd(&DWP(20,$r,"",0),"mm1"); + &psrlq("mm1",32); # mm1 = carry5 + &paddq("mm1","mm6"); # mm1 = carry5 + r[6] + w*a[6] + &movd(&DWP(24,$r,"",0),"mm1"); + &psrlq("mm1",32); # mm1 = carry6 + &paddq("mm1","mm3"); # mm1 = carry6 + r[7] + w*a[7] + &movd(&DWP(28,$r,"",0),"mm1"); + &lea($r,&DWP(32,$r)); + &psrlq("mm1",32); # mm1 = carry_out + + &sub($c,8); + &jz(&label("maw_sse2_exit")); + &set_label("maw_sse2_entry"); + &test($c,0xfffffff8); + &jnz(&label("maw_sse2_unrolled")); + + &set_label("maw_sse2_loop",4); + &movd("mm2",&DWP(0,$a)); # mm2 = a[i] + &movd("mm3",&DWP(0,$r)); # mm3 = r[i] + &pmuludq("mm2","mm0"); # a[i] *= w + &lea($a,&DWP(4,$a)); + &paddq("mm1","mm3"); # carry += r[i] + &paddq("mm1","mm2"); # carry += a[i]*w + &movd(&DWP(0,$r),"mm1"); # r[i] = carry_low + &sub($c,1); + &psrlq("mm1",32); # carry = carry_high + &lea($r,&DWP(4,$r)); + &jnz(&label("maw_sse2_loop")); + &set_label("maw_sse2_exit"); + &movd("eax","mm1"); # c = carry_out + &emms(); + &ret(); + + &set_label("maw_non_sse2",16); + } + + # function_begin prologue + &push("ebp"); + &push("ebx"); + &push("esi"); + &push("edi"); + + &comment(""); + $Low="eax"; + $High="edx"; + $a="ebx"; + $w="ebp"; + $r="edi"; + $c="esi"; + + &xor($c,$c); # clear carry + &mov($r,&wparam(0)); # + + &mov("ecx",&wparam(2)); # + &mov($a,&wparam(1)); # + + &and("ecx",0xfffffff8); # num / 8 + &mov($w,&wparam(3)); # + + &push("ecx"); # Up the stack for a tmp variable + + &jz(&label("maw_finish")); + + &set_label("maw_loop",16); + + for ($i=0; $i<32; $i+=4) + { + &comment("Round $i"); + + &mov("eax",&DWP($i,$a)); # *a + &mul($w); # *a * w + &add("eax",$c); # L(t)+= c + &adc("edx",0); # H(t)+=carry + &add("eax",&DWP($i,$r)); # L(t)+= *r + &adc("edx",0); # H(t)+=carry + &mov(&DWP($i,$r),"eax"); # *r= L(t); + &mov($c,"edx"); # c= H(t); + } + + &comment(""); + &sub("ecx",8); + &lea($a,&DWP(32,$a)); + &lea($r,&DWP(32,$r)); + &jnz(&label("maw_loop")); + + &set_label("maw_finish",0); + &mov("ecx",&wparam(2)); # get num + &and("ecx",7); + &jnz(&label("maw_finish2")); # helps branch prediction + &jmp(&label("maw_end")); + + &set_label("maw_finish2",1); + for ($i=0; $i<7; $i++) + { + &comment("Tail Round $i"); + &mov("eax",&DWP($i*4,$a)); # *a + &mul($w); # *a * w + &add("eax",$c); # L(t)+=c + &adc("edx",0); # H(t)+=carry + &add("eax",&DWP($i*4,$r)); # L(t)+= *r + &adc("edx",0); # H(t)+=carry + &dec("ecx") if ($i != 7-1); + &mov(&DWP($i*4,$r),"eax"); # *r= L(t); + &mov($c,"edx"); # c= H(t); + &jz(&label("maw_end")) if ($i != 7-1); + } + &set_label("maw_end",0); + &mov("eax",$c); + + &pop("ecx"); # clear variable from + + &function_end($name); + } + +sub bn_mul_words + { + local($name)=@_; + + &function_begin_B($name,$sse2?"EXTRN\t_OPENSSL_ia32cap_P:DWORD":""); + + $r="eax"; + $a="edx"; + $c="ecx"; + + if ($sse2) { + &picmeup("eax","OPENSSL_ia32cap_P"); + &bt(&DWP(0,"eax"),26); + &jnc(&label("mw_non_sse2")); + + &mov($r,&wparam(0)); + &mov($a,&wparam(1)); + &mov($c,&wparam(2)); + &movd("mm0",&wparam(3)); # mm0 = w + &pxor("mm1","mm1"); # mm1 = carry = 0 + + &set_label("mw_sse2_loop",16); + &movd("mm2",&DWP(0,$a)); # mm2 = a[i] + &pmuludq("mm2","mm0"); # a[i] *= w + &lea($a,&DWP(4,$a)); + &paddq("mm1","mm2"); # carry += a[i]*w + &movd(&DWP(0,$r),"mm1"); # r[i] = carry_low + &sub($c,1); + &psrlq("mm1",32); # carry = carry_high + &lea($r,&DWP(4,$r)); + &jnz(&label("mw_sse2_loop")); + + &movd("eax","mm1"); # return carry + &emms(); + &ret(); + &set_label("mw_non_sse2",16); + } + + # function_begin prologue + &push("ebp"); + &push("ebx"); + &push("esi"); + &push("edi"); + + &comment(""); + $Low="eax"; + $High="edx"; + $a="ebx"; + $w="ecx"; + $r="edi"; + $c="esi"; + $num="ebp"; + + &xor($c,$c); # clear carry + &mov($r,&wparam(0)); # + &mov($a,&wparam(1)); # + &mov($num,&wparam(2)); # + &mov($w,&wparam(3)); # + + &and($num,0xfffffff8); # num / 8 + &jz(&label("mw_finish")); + + &set_label("mw_loop",0); + for ($i=0; $i<32; $i+=4) + { + &comment("Round $i"); + + &mov("eax",&DWP($i,$a,"",0)); # *a + &mul($w); # *a * w + &add("eax",$c); # L(t)+=c + # XXX + + &adc("edx",0); # H(t)+=carry + &mov(&DWP($i,$r,"",0),"eax"); # *r= L(t); + + &mov($c,"edx"); # c= H(t); + } + + &comment(""); + &add($a,32); + &add($r,32); + &sub($num,8); + &jz(&label("mw_finish")); + &jmp(&label("mw_loop")); + + &set_label("mw_finish",0); + &mov($num,&wparam(2)); # get num + &and($num,7); + &jnz(&label("mw_finish2")); + &jmp(&label("mw_end")); + + &set_label("mw_finish2",1); + for ($i=0; $i<7; $i++) + { + &comment("Tail Round $i"); + &mov("eax",&DWP($i*4,$a,"",0));# *a + &mul($w); # *a * w + &add("eax",$c); # L(t)+=c + # XXX + &adc("edx",0); # H(t)+=carry + &mov(&DWP($i*4,$r,"",0),"eax");# *r= L(t); + &mov($c,"edx"); # c= H(t); + &dec($num) if ($i != 7-1); + &jz(&label("mw_end")) if ($i != 7-1); + } + &set_label("mw_end",0); + &mov("eax",$c); + + &function_end($name); + } + +sub bn_sqr_words + { + local($name)=@_; + + &function_begin_B($name,$sse2?"EXTRN\t_OPENSSL_ia32cap_P:DWORD":""); + + $r="eax"; + $a="edx"; + $c="ecx"; + + if ($sse2) { + &picmeup("eax","OPENSSL_ia32cap_P"); + &bt(&DWP(0,"eax"),26); + &jnc(&label("sqr_non_sse2")); + + &mov($r,&wparam(0)); + &mov($a,&wparam(1)); + &mov($c,&wparam(2)); + + &set_label("sqr_sse2_loop",16); + &movd("mm0",&DWP(0,$a)); # mm0 = a[i] + &pmuludq("mm0","mm0"); # a[i] *= a[i] + &lea($a,&DWP(4,$a)); # a++ + &movq(&QWP(0,$r),"mm0"); # r[i] = a[i]*a[i] + &sub($c,1); + &lea($r,&DWP(8,$r)); # r += 2 + &jnz(&label("sqr_sse2_loop")); + + &emms(); + &ret(); + &set_label("sqr_non_sse2",16); + } + + # function_begin prologue + &push("ebp"); + &push("ebx"); + &push("esi"); + &push("edi"); + + &comment(""); + $r="esi"; + $a="edi"; + $num="ebx"; + + &mov($r,&wparam(0)); # + &mov($a,&wparam(1)); # + &mov($num,&wparam(2)); # + + &and($num,0xfffffff8); # num / 8 + &jz(&label("sw_finish")); + + &set_label("sw_loop",0); + for ($i=0; $i<32; $i+=4) + { + &comment("Round $i"); + &mov("eax",&DWP($i,$a,"",0)); # *a + # XXX + &mul("eax"); # *a * *a + &mov(&DWP($i*2,$r,"",0),"eax"); # + &mov(&DWP($i*2+4,$r,"",0),"edx");# + } + + &comment(""); + &add($a,32); + &add($r,64); + &sub($num,8); + &jnz(&label("sw_loop")); + + &set_label("sw_finish",0); + &mov($num,&wparam(2)); # get num + &and($num,7); + &jz(&label("sw_end")); + + for ($i=0; $i<7; $i++) + { + &comment("Tail Round $i"); + &mov("eax",&DWP($i*4,$a,"",0)); # *a + # XXX + &mul("eax"); # *a * *a + &mov(&DWP($i*8,$r,"",0),"eax"); # + &dec($num) if ($i != 7-1); + &mov(&DWP($i*8+4,$r,"",0),"edx"); + &jz(&label("sw_end")) if ($i != 7-1); + } + &set_label("sw_end",0); + + &function_end($name); + } + +sub bn_div_words + { + local($name)=@_; + + &function_begin_B($name,""); + &mov("edx",&wparam(0)); # + &mov("eax",&wparam(1)); # + &mov("ecx",&wparam(2)); # + &div("ecx"); + &ret(); + &function_end_B($name); + } + +sub bn_add_words + { + local($name)=@_; + + &function_begin($name,""); + + &comment(""); + $a="esi"; + $b="edi"; + $c="eax"; + $r="ebx"; + $tmp1="ecx"; + $tmp2="edx"; + $num="ebp"; + + &mov($r,&wparam(0)); # get r + &mov($a,&wparam(1)); # get a + &mov($b,&wparam(2)); # get b + &mov($num,&wparam(3)); # get num + &xor($c,$c); # clear carry + &and($num,0xfffffff8); # num / 8 + + &jz(&label("aw_finish")); + + &set_label("aw_loop",0); + for ($i=0; $i<8; $i++) + { + &comment("Round $i"); + + &mov($tmp1,&DWP($i*4,$a,"",0)); # *a + &mov($tmp2,&DWP($i*4,$b,"",0)); # *b + &add($tmp1,$c); + &mov($c,0); + &adc($c,$c); + &add($tmp1,$tmp2); + &adc($c,0); + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + } + + &comment(""); + &add($a,32); + &add($b,32); + &add($r,32); + &sub($num,8); + &jnz(&label("aw_loop")); + + &set_label("aw_finish",0); + &mov($num,&wparam(3)); # get num + &and($num,7); + &jz(&label("aw_end")); + + for ($i=0; $i<7; $i++) + { + &comment("Tail Round $i"); + &mov($tmp1,&DWP($i*4,$a,"",0)); # *a + &mov($tmp2,&DWP($i*4,$b,"",0));# *b + &add($tmp1,$c); + &mov($c,0); + &adc($c,$c); + &add($tmp1,$tmp2); + &adc($c,0); + &dec($num) if ($i != 6); + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + &jz(&label("aw_end")) if ($i != 6); + } + &set_label("aw_end",0); + +# &mov("eax",$c); # $c is "eax" + + &function_end($name); + } + +sub bn_sub_words + { + local($name)=@_; + + &function_begin($name,""); + + &comment(""); + $a="esi"; + $b="edi"; + $c="eax"; + $r="ebx"; + $tmp1="ecx"; + $tmp2="edx"; + $num="ebp"; + + &mov($r,&wparam(0)); # get r + &mov($a,&wparam(1)); # get a + &mov($b,&wparam(2)); # get b + &mov($num,&wparam(3)); # get num + &xor($c,$c); # clear carry + &and($num,0xfffffff8); # num / 8 + + &jz(&label("aw_finish")); + + &set_label("aw_loop",0); + for ($i=0; $i<8; $i++) + { + &comment("Round $i"); + + &mov($tmp1,&DWP($i*4,$a,"",0)); # *a + &mov($tmp2,&DWP($i*4,$b,"",0)); # *b + &sub($tmp1,$c); + &mov($c,0); + &adc($c,$c); + &sub($tmp1,$tmp2); + &adc($c,0); + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + } + + &comment(""); + &add($a,32); + &add($b,32); + &add($r,32); + &sub($num,8); + &jnz(&label("aw_loop")); + + &set_label("aw_finish",0); + &mov($num,&wparam(3)); # get num + &and($num,7); + &jz(&label("aw_end")); + + for ($i=0; $i<7; $i++) + { + &comment("Tail Round $i"); + &mov($tmp1,&DWP($i*4,$a,"",0)); # *a + &mov($tmp2,&DWP($i*4,$b,"",0));# *b + &sub($tmp1,$c); + &mov($c,0); + &adc($c,$c); + &sub($tmp1,$tmp2); + &adc($c,0); + &dec($num) if ($i != 6); + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + &jz(&label("aw_end")) if ($i != 6); + } + &set_label("aw_end",0); + +# &mov("eax",$c); # $c is "eax" + + &function_end($name); + } + +sub bn_sub_part_words + { + local($name)=@_; + + &function_begin($name,""); + + &comment(""); + $a="esi"; + $b="edi"; + $c="eax"; + $r="ebx"; + $tmp1="ecx"; + $tmp2="edx"; + $num="ebp"; + + &mov($r,&wparam(0)); # get r + &mov($a,&wparam(1)); # get a + &mov($b,&wparam(2)); # get b + &mov($num,&wparam(3)); # get num + &xor($c,$c); # clear carry + &and($num,0xfffffff8); # num / 8 + + &jz(&label("aw_finish")); + + &set_label("aw_loop",0); + for ($i=0; $i<8; $i++) + { + &comment("Round $i"); + + &mov($tmp1,&DWP($i*4,$a,"",0)); # *a + &mov($tmp2,&DWP($i*4,$b,"",0)); # *b + &sub($tmp1,$c); + &mov($c,0); + &adc($c,$c); + &sub($tmp1,$tmp2); + &adc($c,0); + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + } + + &comment(""); + &add($a,32); + &add($b,32); + &add($r,32); + &sub($num,8); + &jnz(&label("aw_loop")); + + &set_label("aw_finish",0); + &mov($num,&wparam(3)); # get num + &and($num,7); + &jz(&label("aw_end")); + + for ($i=0; $i<7; $i++) + { + &comment("Tail Round $i"); + &mov($tmp1,&DWP(0,$a,"",0)); # *a + &mov($tmp2,&DWP(0,$b,"",0));# *b + &sub($tmp1,$c); + &mov($c,0); + &adc($c,$c); + &sub($tmp1,$tmp2); + &adc($c,0); + &mov(&DWP(0,$r,"",0),$tmp1); # *r + &add($a, 4); + &add($b, 4); + &add($r, 4); + &dec($num) if ($i != 6); + &jz(&label("aw_end")) if ($i != 6); + } + &set_label("aw_end",0); + + &cmp(&wparam(4),0); + &je(&label("pw_end")); + + &mov($num,&wparam(4)); # get dl + &cmp($num,0); + &je(&label("pw_end")); + &jge(&label("pw_pos")); + + &comment("pw_neg"); + &mov($tmp2,0); + &sub($tmp2,$num); + &mov($num,$tmp2); + &and($num,0xfffffff8); # num / 8 + &jz(&label("pw_neg_finish")); + + &set_label("pw_neg_loop",0); + for ($i=0; $i<8; $i++) + { + &comment("dl<0 Round $i"); + + &mov($tmp1,0); + &mov($tmp2,&DWP($i*4,$b,"",0)); # *b + &sub($tmp1,$c); + &mov($c,0); + &adc($c,$c); + &sub($tmp1,$tmp2); + &adc($c,0); + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + } + + &comment(""); + &add($b,32); + &add($r,32); + &sub($num,8); + &jnz(&label("pw_neg_loop")); + + &set_label("pw_neg_finish",0); + &mov($tmp2,&wparam(4)); # get dl + &mov($num,0); + &sub($num,$tmp2); + &and($num,7); + &jz(&label("pw_end")); + + for ($i=0; $i<7; $i++) + { + &comment("dl<0 Tail Round $i"); + &mov($tmp1,0); + &mov($tmp2,&DWP($i*4,$b,"",0));# *b + &sub($tmp1,$c); + &mov($c,0); + &adc($c,$c); + &sub($tmp1,$tmp2); + &adc($c,0); + &dec($num) if ($i != 6); + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + &jz(&label("pw_end")) if ($i != 6); + } + + &jmp(&label("pw_end")); + + &set_label("pw_pos",0); + + &and($num,0xfffffff8); # num / 8 + &jz(&label("pw_pos_finish")); + + &set_label("pw_pos_loop",0); + + for ($i=0; $i<8; $i++) + { + &comment("dl>0 Round $i"); + + &mov($tmp1,&DWP($i*4,$a,"",0)); # *a + &sub($tmp1,$c); + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + &jnc(&label("pw_nc".$i)); + } + + &comment(""); + &add($a,32); + &add($r,32); + &sub($num,8); + &jnz(&label("pw_pos_loop")); + + &set_label("pw_pos_finish",0); + &mov($num,&wparam(4)); # get dl + &and($num,7); + &jz(&label("pw_end")); + + for ($i=0; $i<7; $i++) + { + &comment("dl>0 Tail Round $i"); + &mov($tmp1,&DWP($i*4,$a,"",0)); # *a + &sub($tmp1,$c); + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + &jnc(&label("pw_tail_nc".$i)); + &dec($num) if ($i != 6); + &jz(&label("pw_end")) if ($i != 6); + } + &mov($c,1); + &jmp(&label("pw_end")); + + &set_label("pw_nc_loop",0); + for ($i=0; $i<8; $i++) + { + &mov($tmp1,&DWP($i*4,$a,"",0)); # *a + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + &set_label("pw_nc".$i,0); + } + + &comment(""); + &add($a,32); + &add($r,32); + &sub($num,8); + &jnz(&label("pw_nc_loop")); + + &mov($num,&wparam(4)); # get dl + &and($num,7); + &jz(&label("pw_nc_end")); + + for ($i=0; $i<7; $i++) + { + &mov($tmp1,&DWP($i*4,$a,"",0)); # *a + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + &set_label("pw_tail_nc".$i,0); + &dec($num) if ($i != 6); + &jz(&label("pw_nc_end")) if ($i != 6); + } + + &set_label("pw_nc_end",0); + &mov($c,0); + + &set_label("pw_end",0); + +# &mov("eax",$c); # $c is "eax" + + &function_end($name); + } diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/bn-c64xplus.asm b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/bn-c64xplus.asm new file mode 100644 index 000000000..de6d37728 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/bn-c64xplus.asm @@ -0,0 +1,382 @@ +;; Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved. +;; +;; Licensed under the OpenSSL license (the "License"). You may not use +;; this file except in compliance with the License. You can obtain a copy +;; in the file LICENSE in the source distribution or at +;; https://www.openssl.org/source/license.html +;; +;;==================================================================== +;; Written by Andy Polyakov for the OpenSSL +;; project. +;; +;; Rights for redistribution and usage in source and binary forms are +;; granted according to the OpenSSL license. Warranty of any kind is +;; disclaimed. +;;==================================================================== +;; Compiler-generated multiply-n-add SPLOOP runs at 12*n cycles, n +;; being the number of 32-bit words, addition - 8*n. Corresponding 4x +;; unrolled SPLOOP-free loops - at ~8*n and ~5*n. Below assembler +;; SPLOOPs spin at ... 2*n cycles [plus epilogue]. +;;==================================================================== + .text + + .if .ASSEMBLER_VERSION<7000000 + .asg 0,__TI_EABI__ + .endif + .if __TI_EABI__ + .asg bn_mul_add_words,_bn_mul_add_words + .asg bn_mul_words,_bn_mul_words + .asg bn_sqr_words,_bn_sqr_words + .asg bn_add_words,_bn_add_words + .asg bn_sub_words,_bn_sub_words + .asg bn_div_words,_bn_div_words + .asg bn_sqr_comba8,_bn_sqr_comba8 + .asg bn_mul_comba8,_bn_mul_comba8 + .asg bn_sqr_comba4,_bn_sqr_comba4 + .asg bn_mul_comba4,_bn_mul_comba4 + .endif + + .asg B3,RA + .asg A4,ARG0 + .asg B4,ARG1 + .asg A6,ARG2 + .asg B6,ARG3 + .asg A8,ARG4 + .asg B8,ARG5 + .asg A4,RET + .asg A15,FP + .asg B14,DP + .asg B15,SP + + .global _bn_mul_add_words +_bn_mul_add_words: + .asmfunc + MV ARG2,B0 + [!B0] BNOP RA +||[!B0] MVK 0,RET + [B0] MVC B0,ILC + [B0] ZERO A19 ; high part of accumulator +|| [B0] MV ARG0,A2 +|| [B0] MV ARG3,A3 + NOP 3 + + SPLOOP 2 ; 2*n+10 +;;==================================================================== + LDW *ARG1++,B7 ; ap[i] + NOP 3 + LDW *ARG0++,A7 ; rp[i] + MPY32U B7,A3,A17:A16 + NOP 3 ; [2,0] in epilogue + ADDU A16,A7,A21:A20 + ADDU A19,A21:A20,A19:A18 +|| MV.S A17,A23 + SPKERNEL 2,1 ; leave slot for "return value" +|| STW A18,*A2++ ; rp[i] +|| ADD A19,A23,A19 +;;==================================================================== + BNOP RA,4 + MV A19,RET ; return value + .endasmfunc + + .global _bn_mul_words +_bn_mul_words: + .asmfunc + MV ARG2,B0 + [!B0] BNOP RA +||[!B0] MVK 0,RET + [B0] MVC B0,ILC + [B0] ZERO A19 ; high part of accumulator + NOP 3 + + SPLOOP 2 ; 2*n+10 +;;==================================================================== + LDW *ARG1++,A7 ; ap[i] + NOP 4 + MPY32U A7,ARG3,A17:A16 + NOP 4 ; [2,0] in epiloque + ADDU A19,A16,A19:A18 +|| MV.S A17,A21 + SPKERNEL 2,1 ; leave slot for "return value" +|| STW A18,*ARG0++ ; rp[i] +|| ADD.L A19,A21,A19 +;;==================================================================== + BNOP RA,4 + MV A19,RET ; return value + .endasmfunc + + .global _bn_sqr_words +_bn_sqr_words: + .asmfunc + MV ARG2,B0 + [!B0] BNOP RA +||[!B0] MVK 0,RET + [B0] MVC B0,ILC + [B0] MV ARG0,B2 +|| [B0] ADD 4,ARG0,ARG0 + NOP 3 + + SPLOOP 2 ; 2*n+10 +;;==================================================================== + LDW *ARG1++,B7 ; ap[i] + NOP 4 + MPY32U B7,B7,B1:B0 + NOP 3 ; [2,0] in epilogue + STW B0,*B2++(8) ; rp[2*i] + MV B1,A1 + SPKERNEL 2,0 ; fully overlap BNOP RA,5 +|| STW A1,*ARG0++(8) ; rp[2*i+1] +;;==================================================================== + BNOP RA,5 + .endasmfunc + + .global _bn_add_words +_bn_add_words: + .asmfunc + MV ARG3,B0 + [!B0] BNOP RA +||[!B0] MVK 0,RET + [B0] MVC B0,ILC + [B0] ZERO A1 ; carry flag +|| [B0] MV ARG0,A3 + NOP 3 + + SPLOOP 2 ; 2*n+6 +;;==================================================================== + LDW *ARG2++,A7 ; bp[i] +|| LDW *ARG1++,B7 ; ap[i] + NOP 4 + ADDU A7,B7,A9:A8 + ADDU A1,A9:A8,A1:A0 + SPKERNEL 0,0 ; fully overlap BNOP RA,5 +|| STW A0,*A3++ ; write result +|| MV A1,RET ; keep carry flag in RET +;;==================================================================== + BNOP RA,5 + .endasmfunc + + .global _bn_sub_words +_bn_sub_words: + .asmfunc + MV ARG3,B0 + [!B0] BNOP RA +||[!B0] MVK 0,RET + [B0] MVC B0,ILC + [B0] ZERO A2 ; borrow flag +|| [B0] MV ARG0,A3 + NOP 3 + + SPLOOP 2 ; 2*n+6 +;;==================================================================== + LDW *ARG2++,A7 ; bp[i] +|| LDW *ARG1++,B7 ; ap[i] + NOP 4 + SUBU B7,A7,A1:A0 + [A2] SUB A1:A0,1,A1:A0 + SPKERNEL 0,1 ; leave slot for "return borrow flag" +|| STW A0,*A3++ ; write result +|| AND 1,A1,A2 ; pass on borrow flag +;;==================================================================== + BNOP RA,4 + AND 1,A1,RET ; return borrow flag + .endasmfunc + + .global _bn_div_words +_bn_div_words: + .asmfunc + LMBD 1,A6,A0 ; leading zero bits in dv + LMBD 1,A4,A1 ; leading zero bits in hi +|| MVK 32,B0 + CMPLTU A1,A0,A2 +|| ADD A0,B0,B0 + [ A2] BNOP RA +||[ A2] MVK -1,A4 ; return overflow +||[!A2] MV A4,A3 ; reassign hi + [!A2] MV B4,A4 ; reassign lo, will be quotient +||[!A2] MVC B0,ILC + [!A2] SHL A6,A0,A6 ; normalize dv +|| MVK 1,A1 + + [!A2] CMPLTU A3,A6,A1 ; hi>31 + + SPLOOP 3 + [!A1] CMPLTU A3,A6,A1 ; hi>31 + SPKERNEL + + BNOP RA,5 + .endasmfunc + +;;==================================================================== +;; Not really Comba algorithm, just straightforward NxM... Dedicated +;; fully unrolled real Comba implementations are asymptotically 2x +;; faster, but naturally larger undertaking. Purpose of this exercise +;; was rather to learn to master nested SPLOOPs... +;;==================================================================== + .global _bn_sqr_comba8 + .global _bn_mul_comba8 +_bn_sqr_comba8: + MV ARG1,ARG2 +_bn_mul_comba8: + .asmfunc + MVK 8,B0 ; N, RILC +|| MVK 8,A0 ; M, outer loop counter +|| MV ARG1,A5 ; copy ap +|| MV ARG0,B4 ; copy rp +|| ZERO B19 ; high part of accumulator + MVC B0,RILC +|| SUB B0,2,B1 ; N-2, initial ILC +|| SUB B0,1,B2 ; const B2=N-1 +|| LDW *A5++,B6 ; ap[0] +|| MV A0,A3 ; const A3=M +sploopNxM?: ; for best performance arrange M<=N + [A0] SPLOOPD 2 ; 2*n+10 +|| MVC B1,ILC +|| ADDAW B4,B0,B5 +|| ZERO B7 +|| LDW *A5++,A9 ; pre-fetch ap[1] +|| ZERO A1 +|| SUB A0,1,A0 +;;==================================================================== +;; SPLOOP from bn_mul_add_words, but with flipped A<>B register files. +;; This is because of Advisory 15 from TI publication SPRZ247I. + LDW *ARG2++,A7 ; bp[i] + NOP 3 + [A1] LDW *B5++,B7 ; rp[i] + MPY32U A7,B6,B17:B16 + NOP 3 + ADDU B16,B7,B21:B20 + ADDU B19,B21:B20,B19:B18 +|| MV.S B17,B23 + SPKERNEL +|| STW B18,*B4++ ; rp[i] +|| ADD.S B19,B23,B19 +;;==================================================================== +outer?: ; m*2*(n+1)+10 + SUBAW ARG2,A3,ARG2 ; rewind bp to bp[0] + SPMASKR +|| CMPGT A0,1,A2 ; done pre-fetching ap[i+1]? + MVD A9,B6 ; move through .M unit(*) + [A2] LDW *A5++,A9 ; pre-fetch ap[i+1] + SUBAW B5,B2,B5 ; rewind rp to rp[1] + MVK 1,A1 + [A0] BNOP.S1 outer?,4 +|| [A0] SUB.L A0,1,A0 + STW B19,*B4--[B2] ; rewind rp tp rp[1] +|| ZERO.S B19 ; high part of accumulator +;; end of outer? + BNOP RA,5 ; return + .endasmfunc +;; (*) It should be noted that B6 is used as input to MPY32U in +;; chronologically next cycle in *preceding* SPLOOP iteration. +;; Normally such arrangement would require DINT, but at this +;; point SPLOOP is draining and interrupts are disabled +;; implicitly. + + .global _bn_sqr_comba4 + .global _bn_mul_comba4 +_bn_sqr_comba4: + MV ARG1,ARG2 +_bn_mul_comba4: + .asmfunc + .if 0 + BNOP sploopNxM?,3 + ;; Above mentioned m*2*(n+1)+10 does not apply in n=m=4 case, + ;; because of low-counter effect, when prologue phase finishes + ;; before SPKERNEL instruction is reached. As result it's 25% + ;; slower than expected... + MVK 4,B0 ; N, RILC +|| MVK 4,A0 ; M, outer loop counter +|| MV ARG1,A5 ; copy ap +|| MV ARG0,B4 ; copy rp +|| ZERO B19 ; high part of accumulator + MVC B0,RILC +|| SUB B0,2,B1 ; first ILC +|| SUB B0,1,B2 ; const B2=N-1 +|| LDW *A5++,B6 ; ap[0] +|| MV A0,A3 ; const A3=M + .else + ;; This alternative is an exercise in fully unrolled Comba + ;; algorithm implementation that operates at n*(n+1)+12, or + ;; as little as 32 cycles... + LDW *ARG1[0],B16 ; a[0] +|| LDW *ARG2[0],A16 ; b[0] + LDW *ARG1[1],B17 ; a[1] +|| LDW *ARG2[1],A17 ; b[1] + LDW *ARG1[2],B18 ; a[2] +|| LDW *ARG2[2],A18 ; b[2] + LDW *ARG1[3],B19 ; a[3] +|| LDW *ARG2[3],A19 ; b[3] + NOP + MPY32U A16,B16,A1:A0 ; a[0]*b[0] + MPY32U A17,B16,A23:A22 ; a[0]*b[1] + MPY32U A16,B17,A25:A24 ; a[1]*b[0] + MPY32U A16,B18,A27:A26 ; a[2]*b[0] + STW A0,*ARG0[0] +|| MPY32U A17,B17,A29:A28 ; a[1]*b[1] + MPY32U A18,B16,A31:A30 ; a[0]*b[2] +|| ADDU A22,A1,A1:A0 + MV A23,B0 +|| MPY32U A19,B16,A21:A20 ; a[3]*b[0] +|| ADDU A24,A1:A0,A1:A0 + ADDU A25,B0,B1:B0 +|| STW A0,*ARG0[1] +|| MPY32U A18,B17,A23:A22 ; a[2]*b[1] +|| ADDU A26,A1,A9:A8 + ADDU A27,B1,B9:B8 +|| MPY32U A17,B18,A25:A24 ; a[1]*b[2] +|| ADDU A28,A9:A8,A9:A8 + ADDU A29,B9:B8,B9:B8 +|| MPY32U A16,B19,A27:A26 ; a[0]*b[3] +|| ADDU A30,A9:A8,A9:A8 + ADDU A31,B9:B8,B9:B8 +|| ADDU B0,A9:A8,A9:A8 + STW A8,*ARG0[2] +|| ADDU A20,A9,A1:A0 + ADDU A21,B9,B1:B0 +|| MPY32U A19,B17,A21:A20 ; a[3]*b[1] +|| ADDU A22,A1:A0,A1:A0 + ADDU A23,B1:B0,B1:B0 +|| MPY32U A18,B18,A23:A22 ; a[2]*b[2] +|| ADDU A24,A1:A0,A1:A0 + ADDU A25,B1:B0,B1:B0 +|| MPY32U A17,B19,A25:A24 ; a[1]*b[3] +|| ADDU A26,A1:A0,A1:A0 + ADDU A27,B1:B0,B1:B0 +|| ADDU B8,A1:A0,A1:A0 + STW A0,*ARG0[3] +|| MPY32U A19,B18,A27:A26 ; a[3]*b[2] +|| ADDU A20,A1,A9:A8 + ADDU A21,B1,B9:B8 +|| MPY32U A18,B19,A29:A28 ; a[2]*b[3] +|| ADDU A22,A9:A8,A9:A8 + ADDU A23,B9:B8,B9:B8 +|| MPY32U A19,B19,A31:A30 ; a[3]*b[3] +|| ADDU A24,A9:A8,A9:A8 + ADDU A25,B9:B8,B9:B8 +|| ADDU B0,A9:A8,A9:A8 + STW A8,*ARG0[4] +|| ADDU A26,A9,A1:A0 + ADDU A27,B9,B1:B0 +|| ADDU A28,A1:A0,A1:A0 + ADDU A29,B1:B0,B1:B0 +|| BNOP RA +|| ADDU B8,A1:A0,A1:A0 + STW A0,*ARG0[5] +|| ADDU A30,A1,A9:A8 + ADD A31,B1,B8 + ADDU B0,A9:A8,A9:A8 ; removed || to avoid cross-path stall below + ADD B8,A9,A9 +|| STW A8,*ARG0[6] + STW A9,*ARG0[7] + .endif + .endasmfunc diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/c64xplus-gf2m.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/c64xplus-gf2m.pl new file mode 100644 index 000000000..9c46da3af --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/c64xplus-gf2m.pl @@ -0,0 +1,160 @@ +#! /usr/bin/env perl +# Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# February 2012 +# +# The module implements bn_GF2m_mul_2x2 polynomial multiplication +# used in bn_gf2m.c. It's kind of low-hanging mechanical port from +# C for the time being... The subroutine runs in 37 cycles, which is +# 4.5x faster than compiler-generated code. Though comparison is +# totally unfair, because this module utilizes Galois Field Multiply +# instruction. + +while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} +open STDOUT,">$output"; + +($rp,$a1,$a0,$b1,$b0)=("A4","B4","A6","B6","A8"); # argument vector + +($Alo,$Alox0,$Alox1,$Alox2,$Alox3)=map("A$_",(16..20)); +($Ahi,$Ahix0,$Ahix1,$Ahix2,$Ahix3)=map("B$_",(16..20)); +($B_0,$B_1,$B_2,$B_3)=("B5","A5","A7","B7"); +($A,$B)=($Alo,$B_1); +$xFF="B1"; + +sub mul_1x1_upper { +my ($A,$B)=@_; +$code.=<<___; + EXTU $B,8,24,$B_2 ; smash $B to 4 bytes +|| AND $B,$xFF,$B_0 +|| SHRU $B,24,$B_3 + SHRU $A,16, $Ahi ; smash $A to two halfwords +|| EXTU $A,16,16,$Alo + + XORMPY $Alo,$B_2,$Alox2 ; 16x8 bits multiplication +|| XORMPY $Ahi,$B_2,$Ahix2 +|| EXTU $B,16,24,$B_1 + XORMPY $Alo,$B_0,$Alox0 +|| XORMPY $Ahi,$B_0,$Ahix0 + XORMPY $Alo,$B_3,$Alox3 +|| XORMPY $Ahi,$B_3,$Ahix3 + XORMPY $Alo,$B_1,$Alox1 +|| XORMPY $Ahi,$B_1,$Ahix1 +___ +} +sub mul_1x1_merged { +my ($OUTlo,$OUThi,$A,$B)=@_; +$code.=<<___; + EXTU $B,8,24,$B_2 ; smash $B to 4 bytes +|| AND $B,$xFF,$B_0 +|| SHRU $B,24,$B_3 + SHRU $A,16, $Ahi ; smash $A to two halfwords +|| EXTU $A,16,16,$Alo + + XOR $Ahix0,$Alox2,$Ahix0 +|| MV $Ahix2,$OUThi +|| XORMPY $Alo,$B_2,$Alox2 + XORMPY $Ahi,$B_2,$Ahix2 +|| EXTU $B,16,24,$B_1 +|| XORMPY $Alo,$B_0,A1 ; $Alox0 + XOR $Ahix1,$Alox3,$Ahix1 +|| SHL $Ahix0,16,$OUTlo +|| SHRU $Ahix0,16,$Ahix0 + XOR $Alox0,$OUTlo,$OUTlo +|| XOR $Ahix0,$OUThi,$OUThi +|| XORMPY $Ahi,$B_0,$Ahix0 +|| XORMPY $Alo,$B_3,$Alox3 +|| SHL $Alox1,8,$Alox1 +|| SHL $Ahix3,8,$Ahix3 + XOR $Alox1,$OUTlo,$OUTlo +|| XOR $Ahix3,$OUThi,$OUThi +|| XORMPY $Ahi,$B_3,$Ahix3 +|| SHL $Ahix1,24,$Alox1 +|| SHRU $Ahix1,8, $Ahix1 + XOR $Alox1,$OUTlo,$OUTlo +|| XOR $Ahix1,$OUThi,$OUThi +|| XORMPY $Alo,$B_1,$Alox1 +|| XORMPY $Ahi,$B_1,$Ahix1 +|| MV A1,$Alox0 +___ +} +sub mul_1x1_lower { +my ($OUTlo,$OUThi)=@_; +$code.=<<___; + ;NOP + XOR $Ahix0,$Alox2,$Ahix0 +|| MV $Ahix2,$OUThi + NOP + XOR $Ahix1,$Alox3,$Ahix1 +|| SHL $Ahix0,16,$OUTlo +|| SHRU $Ahix0,16,$Ahix0 + XOR $Alox0,$OUTlo,$OUTlo +|| XOR $Ahix0,$OUThi,$OUThi +|| SHL $Alox1,8,$Alox1 +|| SHL $Ahix3,8,$Ahix3 + XOR $Alox1,$OUTlo,$OUTlo +|| XOR $Ahix3,$OUThi,$OUThi +|| SHL $Ahix1,24,$Alox1 +|| SHRU $Ahix1,8, $Ahix1 + XOR $Alox1,$OUTlo,$OUTlo +|| XOR $Ahix1,$OUThi,$OUThi +___ +} +$code.=<<___; + .text + + .if .ASSEMBLER_VERSION<7000000 + .asg 0,__TI_EABI__ + .endif + .if __TI_EABI__ + .asg bn_GF2m_mul_2x2,_bn_GF2m_mul_2x2 + .endif + + .global _bn_GF2m_mul_2x2 +_bn_GF2m_mul_2x2: + .asmfunc + MVK 0xFF,$xFF +___ + &mul_1x1_upper($a0,$b0); # a0·b0 +$code.=<<___; +|| MV $b1,$B + MV $a1,$A +___ + &mul_1x1_merged("A28","B28",$A,$B); # a0·b0/a1·b1 +$code.=<<___; +|| XOR $b0,$b1,$B + XOR $a0,$a1,$A +___ + &mul_1x1_merged("A31","B31",$A,$B); # a1·b1/(a0+a1)·(b0+b1) +$code.=<<___; + XOR A28,A31,A29 +|| XOR B28,B31,B29 ; a0·b0+a1·b1 +___ + &mul_1x1_lower("A30","B30"); # (a0+a1)·(b0+b1) +$code.=<<___; +|| BNOP B3 + XOR A29,A30,A30 +|| XOR B29,B30,B30 ; (a0+a1)·(b0+b1)-a0·b0-a1·b1 + XOR B28,A30,A30 +|| STW A28,*${rp}[0] + XOR B30,A31,A31 +|| STW A30,*${rp}[1] + STW A31,*${rp}[2] + STW B31,*${rp}[3] + .endasmfunc +___ + +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/co-586.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/co-586.pl new file mode 100644 index 000000000..97f5e3a19 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/co-586.pl @@ -0,0 +1,298 @@ +#! /usr/bin/env perl +# Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +$output = pop; +open STDOUT,">$output"; + +&asm_init($ARGV[0]); + +&bn_mul_comba("bn_mul_comba8",8); +&bn_mul_comba("bn_mul_comba4",4); +&bn_sqr_comba("bn_sqr_comba8",8); +&bn_sqr_comba("bn_sqr_comba4",4); + +&asm_finish(); + +close STDOUT; + +sub mul_add_c + { + local($a,$ai,$b,$bi,$c0,$c1,$c2,$pos,$i,$na,$nb)=@_; + + # pos == -1 if eax and edx are pre-loaded, 0 to load from next + # words, and 1 if load return value + + &comment("mul a[$ai]*b[$bi]"); + + # "eax" and "edx" will always be pre-loaded. + # &mov("eax",&DWP($ai*4,$a,"",0)) ; + # &mov("edx",&DWP($bi*4,$b,"",0)); + + &mul("edx"); + &add($c0,"eax"); + &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 0; # laod next a + &mov("eax",&wparam(0)) if $pos > 0; # load r[] + ### + &adc($c1,"edx"); + &mov("edx",&DWP(($nb)*4,$b,"",0)) if $pos == 0; # laod next b + &mov("edx",&DWP(($nb)*4,$b,"",0)) if $pos == 1; # laod next b + ### + &adc($c2,0); + # is pos > 1, it means it is the last loop + &mov(&DWP($i*4,"eax","",0),$c0) if $pos > 0; # save r[]; + &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1; # laod next a + } + +sub sqr_add_c + { + local($r,$a,$ai,$bi,$c0,$c1,$c2,$pos,$i,$na,$nb)=@_; + + # pos == -1 if eax and edx are pre-loaded, 0 to load from next + # words, and 1 if load return value + + &comment("sqr a[$ai]*a[$bi]"); + + # "eax" and "edx" will always be pre-loaded. + # &mov("eax",&DWP($ai*4,$a,"",0)) ; + # &mov("edx",&DWP($bi*4,$b,"",0)); + + if ($ai == $bi) + { &mul("eax");} + else + { &mul("edx");} + &add($c0,"eax"); + &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 0; # load next a + ### + &adc($c1,"edx"); + &mov("edx",&DWP(($nb)*4,$a,"",0)) if ($pos == 1) && ($na != $nb); + ### + &adc($c2,0); + # is pos > 1, it means it is the last loop + &mov(&DWP($i*4,$r,"",0),$c0) if $pos > 0; # save r[]; + &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1; # load next b + } + +sub sqr_add_c2 + { + local($r,$a,$ai,$bi,$c0,$c1,$c2,$pos,$i,$na,$nb)=@_; + + # pos == -1 if eax and edx are pre-loaded, 0 to load from next + # words, and 1 if load return value + + &comment("sqr a[$ai]*a[$bi]"); + + # "eax" and "edx" will always be pre-loaded. + # &mov("eax",&DWP($ai*4,$a,"",0)) ; + # &mov("edx",&DWP($bi*4,$a,"",0)); + + if ($ai == $bi) + { &mul("eax");} + else + { &mul("edx");} + &add("eax","eax"); + ### + &adc("edx","edx"); + ### + &adc($c2,0); + &add($c0,"eax"); + &adc($c1,"edx"); + &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 0; # load next a + &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1; # load next b + &adc($c2,0); + &mov(&DWP($i*4,$r,"",0),$c0) if $pos > 0; # save r[]; + &mov("edx",&DWP(($nb)*4,$a,"",0)) if ($pos <= 1) && ($na != $nb); + ### + } + +sub bn_mul_comba + { + local($name,$num)=@_; + local($a,$b,$c0,$c1,$c2); + local($i,$as,$ae,$bs,$be,$ai,$bi); + local($tot,$end); + + &function_begin_B($name,""); + + $c0="ebx"; + $c1="ecx"; + $c2="ebp"; + $a="esi"; + $b="edi"; + + $as=0; + $ae=0; + $bs=0; + $be=0; + $tot=$num+$num-1; + + &push("esi"); + &mov($a,&wparam(1)); + &push("edi"); + &mov($b,&wparam(2)); + &push("ebp"); + &push("ebx"); + + &xor($c0,$c0); + &mov("eax",&DWP(0,$a,"",0)); # load the first word + &xor($c1,$c1); + &mov("edx",&DWP(0,$b,"",0)); # load the first second + + for ($i=0; $i<$tot; $i++) + { + $ai=$as; + $bi=$bs; + $end=$be+1; + + &comment("################## Calculate word $i"); + + for ($j=$bs; $j<$end; $j++) + { + &xor($c2,$c2) if ($j == $bs); + if (($j+1) == $end) + { + $v=1; + $v=2 if (($i+1) == $tot); + } + else + { $v=0; } + if (($j+1) != $end) + { + $na=($ai-1); + $nb=($bi+1); + } + else + { + $na=$as+($i < ($num-1)); + $nb=$bs+($i >= ($num-1)); + } +#printf STDERR "[$ai,$bi] -> [$na,$nb]\n"; + &mul_add_c($a,$ai,$b,$bi,$c0,$c1,$c2,$v,$i,$na,$nb); + if ($v) + { + &comment("saved r[$i]"); + # &mov("eax",&wparam(0)); + # &mov(&DWP($i*4,"eax","",0),$c0); + ($c0,$c1,$c2)=($c1,$c2,$c0); + } + $ai--; + $bi++; + } + $as++ if ($i < ($num-1)); + $ae++ if ($i >= ($num-1)); + + $bs++ if ($i >= ($num-1)); + $be++ if ($i < ($num-1)); + } + &comment("save r[$i]"); + # &mov("eax",&wparam(0)); + &mov(&DWP($i*4,"eax","",0),$c0); + + &pop("ebx"); + &pop("ebp"); + &pop("edi"); + &pop("esi"); + &ret(); + &function_end_B($name); + } + +sub bn_sqr_comba + { + local($name,$num)=@_; + local($r,$a,$c0,$c1,$c2)=@_; + local($i,$as,$ae,$bs,$be,$ai,$bi); + local($b,$tot,$end,$half); + + &function_begin_B($name,""); + + $c0="ebx"; + $c1="ecx"; + $c2="ebp"; + $a="esi"; + $r="edi"; + + &push("esi"); + &push("edi"); + &push("ebp"); + &push("ebx"); + &mov($r,&wparam(0)); + &mov($a,&wparam(1)); + &xor($c0,$c0); + &xor($c1,$c1); + &mov("eax",&DWP(0,$a,"",0)); # load the first word + + $as=0; + $ae=0; + $bs=0; + $be=0; + $tot=$num+$num-1; + + for ($i=0; $i<$tot; $i++) + { + $ai=$as; + $bi=$bs; + $end=$be+1; + + &comment("############### Calculate word $i"); + for ($j=$bs; $j<$end; $j++) + { + &xor($c2,$c2) if ($j == $bs); + if (($ai-1) < ($bi+1)) + { + $v=1; + $v=2 if ($i+1) == $tot; + } + else + { $v=0; } + if (!$v) + { + $na=$ai-1; + $nb=$bi+1; + } + else + { + $na=$as+($i < ($num-1)); + $nb=$bs+($i >= ($num-1)); + } + if ($ai == $bi) + { + &sqr_add_c($r,$a,$ai,$bi, + $c0,$c1,$c2,$v,$i,$na,$nb); + } + else + { + &sqr_add_c2($r,$a,$ai,$bi, + $c0,$c1,$c2,$v,$i,$na,$nb); + } + if ($v) + { + &comment("saved r[$i]"); + #&mov(&DWP($i*4,$r,"",0),$c0); + ($c0,$c1,$c2)=($c1,$c2,$c0); + last; + } + $ai--; + $bi++; + } + $as++ if ($i < ($num-1)); + $ae++ if ($i >= ($num-1)); + + $bs++ if ($i >= ($num-1)); + $be++ if ($i < ($num-1)); + } + &mov(&DWP($i*4,$r,"",0),$c0); + &pop("ebx"); + &pop("ebp"); + &pop("edi"); + &pop("esi"); + &ret(); + &function_end_B($name); + } diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/ia64-mont.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/ia64-mont.pl new file mode 100644 index 000000000..ec486f777 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/ia64-mont.pl @@ -0,0 +1,860 @@ +#! /usr/bin/env perl +# Copyright 2010-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# January 2010 +# +# "Teaser" Montgomery multiplication module for IA-64. There are +# several possibilities for improvement: +# +# - modulo-scheduling outer loop would eliminate quite a number of +# stalls after ldf8, xma and getf.sig outside inner loop and +# improve shorter key performance; +# - shorter vector support [with input vectors being fetched only +# once] should be added; +# - 2x unroll with help of n0[1] would make the code scalable on +# "wider" IA-64, "wider" than Itanium 2 that is, which is not of +# acute interest, because upcoming Tukwila's individual cores are +# reportedly based on Itanium 2 design; +# - dedicated squaring procedure(?); +# +# January 2010 +# +# Shorter vector support is implemented by zero-padding ap and np +# vectors up to 8 elements, or 512 bits. This means that 256-bit +# inputs will be processed only 2 times faster than 512-bit inputs, +# not 4 [as one would expect, because algorithm complexity is n^2]. +# The reason for padding is that inputs shorter than 512 bits won't +# be processed faster anyway, because minimal critical path of the +# core loop happens to match 512-bit timing. Either way, it resulted +# in >100% improvement of 512-bit RSA sign benchmark and 50% - of +# 1024-bit one [in comparison to original version of *this* module]. +# +# So far 'openssl speed rsa dsa' output on 900MHz Itanium 2 *with* +# this module is: +# sign verify sign/s verify/s +# rsa 512 bits 0.000290s 0.000024s 3452.8 42031.4 +# rsa 1024 bits 0.000793s 0.000058s 1261.7 17172.0 +# rsa 2048 bits 0.005908s 0.000148s 169.3 6754.0 +# rsa 4096 bits 0.033456s 0.000469s 29.9 2133.6 +# dsa 512 bits 0.000253s 0.000198s 3949.9 5057.0 +# dsa 1024 bits 0.000585s 0.000607s 1708.4 1647.4 +# dsa 2048 bits 0.001453s 0.001703s 688.1 587.4 +# +# ... and *without* (but still with ia64.S): +# +# rsa 512 bits 0.000670s 0.000041s 1491.8 24145.5 +# rsa 1024 bits 0.001988s 0.000080s 502.9 12499.3 +# rsa 2048 bits 0.008702s 0.000189s 114.9 5293.9 +# rsa 4096 bits 0.043860s 0.000533s 22.8 1875.9 +# dsa 512 bits 0.000441s 0.000427s 2265.3 2340.6 +# dsa 1024 bits 0.000823s 0.000867s 1215.6 1153.2 +# dsa 2048 bits 0.001894s 0.002179s 528.1 458.9 +# +# As it can be seen, RSA sign performance improves by 130-30%, +# hereafter less for longer keys, while verify - by 74-13%. +# DSA performance improves by 115-30%. + +$output=pop; + +if ($^O eq "hpux") { + $ADDP="addp4"; + for (@ARGV) { $ADDP="add" if (/[\+DD|\-mlp]64/); } +} else { $ADDP="add"; } + +$code=<<___; +.explicit +.text + +// int bn_mul_mont (BN_ULONG *rp,const BN_ULONG *ap, +// const BN_ULONG *bp,const BN_ULONG *np, +// const BN_ULONG *n0p,int num); +.align 64 +.global bn_mul_mont# +.proc bn_mul_mont# +bn_mul_mont: + .prologue + .body +{ .mmi; cmp4.le p6,p7=2,r37;; +(p6) cmp4.lt.unc p8,p9=8,r37 + mov ret0=r0 };; +{ .bbb; +(p9) br.cond.dptk.many bn_mul_mont_8 +(p8) br.cond.dpnt.many bn_mul_mont_general +(p7) br.ret.spnt.many b0 };; +.endp bn_mul_mont# + +prevfs=r2; prevpr=r3; prevlc=r10; prevsp=r11; + +rptr=r8; aptr=r9; bptr=r14; nptr=r15; +tptr=r16; // &tp[0] +tp_1=r17; // &tp[-1] +num=r18; len=r19; lc=r20; +topbit=r21; // carry bit from tmp[num] + +n0=f6; +m0=f7; +bi=f8; + +.align 64 +.local bn_mul_mont_general# +.proc bn_mul_mont_general# +bn_mul_mont_general: + .prologue +{ .mmi; .save ar.pfs,prevfs + alloc prevfs=ar.pfs,6,2,0,8 + $ADDP aptr=0,in1 + .save ar.lc,prevlc + mov prevlc=ar.lc } +{ .mmi; .vframe prevsp + mov prevsp=sp + $ADDP bptr=0,in2 + .save pr,prevpr + mov prevpr=pr };; + + .body + .rotf alo[6],nlo[4],ahi[8],nhi[6] + .rotr a[3],n[3],t[2] + +{ .mmi; ldf8 bi=[bptr],8 // (*bp++) + ldf8 alo[4]=[aptr],16 // ap[0] + $ADDP r30=8,in1 };; +{ .mmi; ldf8 alo[3]=[r30],16 // ap[1] + ldf8 alo[2]=[aptr],16 // ap[2] + $ADDP in4=0,in4 };; +{ .mmi; ldf8 alo[1]=[r30] // ap[3] + ldf8 n0=[in4] // n0 + $ADDP rptr=0,in0 } +{ .mmi; $ADDP nptr=0,in3 + mov r31=16 + zxt4 num=in5 };; +{ .mmi; ldf8 nlo[2]=[nptr],8 // np[0] + shladd len=num,3,r0 + shladd r31=num,3,r31 };; +{ .mmi; ldf8 nlo[1]=[nptr],8 // np[1] + add lc=-5,num + sub r31=sp,r31 };; +{ .mfb; and sp=-16,r31 // alloca + xmpy.hu ahi[2]=alo[4],bi // ap[0]*bp[0] + nop.b 0 } +{ .mfb; nop.m 0 + xmpy.lu alo[4]=alo[4],bi + brp.loop.imp .L1st_ctop,.L1st_cend-16 + };; +{ .mfi; nop.m 0 + xma.hu ahi[1]=alo[3],bi,ahi[2] // ap[1]*bp[0] + add tp_1=8,sp } +{ .mfi; nop.m 0 + xma.lu alo[3]=alo[3],bi,ahi[2] + mov pr.rot=0x20001f<<16 + // ------^----- (p40) at first (p23) + // ----------^^ p[16:20]=1 + };; +{ .mfi; nop.m 0 + xmpy.lu m0=alo[4],n0 // (ap[0]*bp[0])*n0 + mov ar.lc=lc } +{ .mfi; nop.m 0 + fcvt.fxu.s1 nhi[1]=f0 + mov ar.ec=8 };; + +.align 32 +.L1st_ctop: +.pred.rel "mutex",p40,p42 +{ .mfi; (p16) ldf8 alo[0]=[aptr],8 // *(aptr++) + (p18) xma.hu ahi[0]=alo[2],bi,ahi[1] + (p40) add n[2]=n[2],a[2] } // (p23) } +{ .mfi; (p18) ldf8 nlo[0]=[nptr],8 // *(nptr++)(p16) + (p18) xma.lu alo[2]=alo[2],bi,ahi[1] + (p42) add n[2]=n[2],a[2],1 };; // (p23) +{ .mfi; (p21) getf.sig a[0]=alo[5] + (p20) xma.hu nhi[0]=nlo[2],m0,nhi[1] + (p42) cmp.leu p41,p39=n[2],a[2] } // (p23) +{ .mfi; (p23) st8 [tp_1]=n[2],8 + (p20) xma.lu nlo[2]=nlo[2],m0,nhi[1] + (p40) cmp.ltu p41,p39=n[2],a[2] } // (p23) +{ .mmb; (p21) getf.sig n[0]=nlo[3] + (p16) nop.m 0 + br.ctop.sptk .L1st_ctop };; +.L1st_cend: + +{ .mmi; getf.sig a[0]=ahi[6] // (p24) + getf.sig n[0]=nhi[4] + add num=-1,num };; // num-- +{ .mmi; .pred.rel "mutex",p40,p42 +(p40) add n[0]=n[0],a[0] +(p42) add n[0]=n[0],a[0],1 + sub aptr=aptr,len };; // rewind +{ .mmi; .pred.rel "mutex",p40,p42 +(p40) cmp.ltu p41,p39=n[0],a[0] +(p42) cmp.leu p41,p39=n[0],a[0] + sub nptr=nptr,len };; +{ .mmi; .pred.rel "mutex",p39,p41 +(p39) add topbit=r0,r0 +(p41) add topbit=r0,r0,1 + nop.i 0 } +{ .mmi; st8 [tp_1]=n[0] + add tptr=16,sp + add tp_1=8,sp };; + +.Louter: +{ .mmi; ldf8 bi=[bptr],8 // (*bp++) + ldf8 ahi[3]=[tptr] // tp[0] + add r30=8,aptr };; +{ .mmi; ldf8 alo[4]=[aptr],16 // ap[0] + ldf8 alo[3]=[r30],16 // ap[1] + add r31=8,nptr };; +{ .mfb; ldf8 alo[2]=[aptr],16 // ap[2] + xma.hu ahi[2]=alo[4],bi,ahi[3] // ap[0]*bp[i]+tp[0] + brp.loop.imp .Linner_ctop,.Linner_cend-16 + } +{ .mfb; ldf8 alo[1]=[r30] // ap[3] + xma.lu alo[4]=alo[4],bi,ahi[3] + clrrrb.pr };; +{ .mfi; ldf8 nlo[2]=[nptr],16 // np[0] + xma.hu ahi[1]=alo[3],bi,ahi[2] // ap[1]*bp[i] + nop.i 0 } +{ .mfi; ldf8 nlo[1]=[r31] // np[1] + xma.lu alo[3]=alo[3],bi,ahi[2] + mov pr.rot=0x20101f<<16 + // ------^----- (p40) at first (p23) + // --------^--- (p30) at first (p22) + // ----------^^ p[16:20]=1 + };; +{ .mfi; st8 [tptr]=r0 // tp[0] is already accounted + xmpy.lu m0=alo[4],n0 // (ap[0]*bp[i]+tp[0])*n0 + mov ar.lc=lc } +{ .mfi; + fcvt.fxu.s1 nhi[1]=f0 + mov ar.ec=8 };; + +// This loop spins in 4*(n+7) ticks on Itanium 2 and should spin in +// 7*(n+7) ticks on Itanium (the one codenamed Merced). Factor of 7 +// in latter case accounts for two-tick pipeline stall, which means +// that its performance would be ~20% lower than optimal one. No +// attempt was made to address this, because original Itanium is +// hardly represented out in the wild... +.align 32 +.Linner_ctop: +.pred.rel "mutex",p40,p42 +.pred.rel "mutex",p30,p32 +{ .mfi; (p16) ldf8 alo[0]=[aptr],8 // *(aptr++) + (p18) xma.hu ahi[0]=alo[2],bi,ahi[1] + (p40) add n[2]=n[2],a[2] } // (p23) +{ .mfi; (p16) nop.m 0 + (p18) xma.lu alo[2]=alo[2],bi,ahi[1] + (p42) add n[2]=n[2],a[2],1 };; // (p23) +{ .mfi; (p21) getf.sig a[0]=alo[5] + (p16) nop.f 0 + (p40) cmp.ltu p41,p39=n[2],a[2] } // (p23) +{ .mfi; (p21) ld8 t[0]=[tptr],8 + (p16) nop.f 0 + (p42) cmp.leu p41,p39=n[2],a[2] };; // (p23) +{ .mfi; (p18) ldf8 nlo[0]=[nptr],8 // *(nptr++) + (p20) xma.hu nhi[0]=nlo[2],m0,nhi[1] + (p30) add a[1]=a[1],t[1] } // (p22) +{ .mfi; (p16) nop.m 0 + (p20) xma.lu nlo[2]=nlo[2],m0,nhi[1] + (p32) add a[1]=a[1],t[1],1 };; // (p22) +{ .mmi; (p21) getf.sig n[0]=nlo[3] + (p16) nop.m 0 + (p30) cmp.ltu p31,p29=a[1],t[1] } // (p22) +{ .mmb; (p23) st8 [tp_1]=n[2],8 + (p32) cmp.leu p31,p29=a[1],t[1] // (p22) + br.ctop.sptk .Linner_ctop };; +.Linner_cend: + +{ .mmi; getf.sig a[0]=ahi[6] // (p24) + getf.sig n[0]=nhi[4] + nop.i 0 };; + +{ .mmi; .pred.rel "mutex",p31,p33 +(p31) add a[0]=a[0],topbit +(p33) add a[0]=a[0],topbit,1 + mov topbit=r0 };; +{ .mfi; .pred.rel "mutex",p31,p33 +(p31) cmp.ltu p32,p30=a[0],topbit +(p33) cmp.leu p32,p30=a[0],topbit + } +{ .mfi; .pred.rel "mutex",p40,p42 +(p40) add n[0]=n[0],a[0] +(p42) add n[0]=n[0],a[0],1 + };; +{ .mmi; .pred.rel "mutex",p44,p46 +(p40) cmp.ltu p41,p39=n[0],a[0] +(p42) cmp.leu p41,p39=n[0],a[0] +(p32) add topbit=r0,r0,1 } + +{ .mmi; st8 [tp_1]=n[0],8 + cmp4.ne p6,p0=1,num + sub aptr=aptr,len };; // rewind +{ .mmi; sub nptr=nptr,len +(p41) add topbit=r0,r0,1 + add tptr=16,sp } +{ .mmb; add tp_1=8,sp + add num=-1,num // num-- +(p6) br.cond.sptk.many .Louter };; + +{ .mbb; add lc=4,lc + brp.loop.imp .Lsub_ctop,.Lsub_cend-16 + clrrrb.pr };; +{ .mii; nop.m 0 + mov pr.rot=0x10001<<16 + // ------^---- (p33) at first (p17) + mov ar.lc=lc } +{ .mii; nop.m 0 + mov ar.ec=3 + nop.i 0 };; + +.Lsub_ctop: +.pred.rel "mutex",p33,p35 +{ .mfi; (p16) ld8 t[0]=[tptr],8 // t=*(tp++) + (p16) nop.f 0 + (p33) sub n[1]=t[1],n[1] } // (p17) +{ .mfi; (p16) ld8 n[0]=[nptr],8 // n=*(np++) + (p16) nop.f 0 + (p35) sub n[1]=t[1],n[1],1 };; // (p17) +{ .mib; (p18) st8 [rptr]=n[2],8 // *(rp++)=r + (p33) cmp.gtu p34,p32=n[1],t[1] // (p17) + (p18) nop.b 0 } +{ .mib; (p18) nop.m 0 + (p35) cmp.geu p34,p32=n[1],t[1] // (p17) + br.ctop.sptk .Lsub_ctop };; +.Lsub_cend: + +{ .mmb; .pred.rel "mutex",p34,p36 +(p34) sub topbit=topbit,r0 // (p19) +(p36) sub topbit=topbit,r0,1 + brp.loop.imp .Lcopy_ctop,.Lcopy_cend-16 + } +{ .mmb; sub rptr=rptr,len // rewind + sub tptr=tptr,len + clrrrb.pr };; +{ .mmi; mov aptr=rptr + mov bptr=tptr + mov pr.rot=1<<16 };; +{ .mii; cmp.eq p0,p6=topbit,r0 + mov ar.lc=lc + mov ar.ec=2 };; + +.Lcopy_ctop: +{ .mmi; (p16) ld8 a[0]=[aptr],8 + (p16) ld8 t[0]=[bptr],8 + (p6) mov a[1]=t[1] };; // (p17) +{ .mmb; (p17) st8 [rptr]=a[1],8 + (p17) st8 [tptr]=r0,8 + br.ctop.sptk .Lcopy_ctop };; +.Lcopy_cend: + +{ .mmi; mov ret0=1 // signal "handled" + rum 1<<5 // clear um.mfh + mov ar.lc=prevlc } +{ .mib; .restore sp + mov sp=prevsp + mov pr=prevpr,0x1ffff + br.ret.sptk.many b0 };; +.endp bn_mul_mont_general# + +a1=r16; a2=r17; a3=r18; a4=r19; a5=r20; a6=r21; a7=r22; a8=r23; +n1=r24; n2=r25; n3=r26; n4=r27; n5=r28; n6=r29; n7=r30; n8=r31; +t0=r15; + +ai0=f8; ai1=f9; ai2=f10; ai3=f11; ai4=f12; ai5=f13; ai6=f14; ai7=f15; +ni0=f16; ni1=f17; ni2=f18; ni3=f19; ni4=f20; ni5=f21; ni6=f22; ni7=f23; + +.align 64 +.skip 48 // aligns loop body +.local bn_mul_mont_8# +.proc bn_mul_mont_8# +bn_mul_mont_8: + .prologue +{ .mmi; .save ar.pfs,prevfs + alloc prevfs=ar.pfs,6,2,0,8 + .vframe prevsp + mov prevsp=sp + .save ar.lc,prevlc + mov prevlc=ar.lc } +{ .mmi; add r17=-6*16,sp + add sp=-7*16,sp + .save pr,prevpr + mov prevpr=pr };; + +{ .mmi; .save.gf 0,0x10 + stf.spill [sp]=f16,-16 + .save.gf 0,0x20 + stf.spill [r17]=f17,32 + add r16=-5*16,prevsp};; +{ .mmi; .save.gf 0,0x40 + stf.spill [r16]=f18,32 + .save.gf 0,0x80 + stf.spill [r17]=f19,32 + $ADDP aptr=0,in1 };; +{ .mmi; .save.gf 0,0x100 + stf.spill [r16]=f20,32 + .save.gf 0,0x200 + stf.spill [r17]=f21,32 + $ADDP r29=8,in1 };; +{ .mmi; .save.gf 0,0x400 + stf.spill [r16]=f22 + .save.gf 0,0x800 + stf.spill [r17]=f23 + $ADDP rptr=0,in0 };; + + .body + .rotf bj[8],mj[2],tf[2],alo[10],ahi[10],nlo[10],nhi[10] + .rotr t[8] + +// load input vectors padding them to 8 elements +{ .mmi; ldf8 ai0=[aptr],16 // ap[0] + ldf8 ai1=[r29],16 // ap[1] + $ADDP bptr=0,in2 } +{ .mmi; $ADDP r30=8,in2 + $ADDP nptr=0,in3 + $ADDP r31=8,in3 };; +{ .mmi; ldf8 bj[7]=[bptr],16 // bp[0] + ldf8 bj[6]=[r30],16 // bp[1] + cmp4.le p4,p5=3,in5 } +{ .mmi; ldf8 ni0=[nptr],16 // np[0] + ldf8 ni1=[r31],16 // np[1] + cmp4.le p6,p7=4,in5 };; + +{ .mfi; (p4)ldf8 ai2=[aptr],16 // ap[2] + (p5)fcvt.fxu ai2=f0 + cmp4.le p8,p9=5,in5 } +{ .mfi; (p6)ldf8 ai3=[r29],16 // ap[3] + (p7)fcvt.fxu ai3=f0 + cmp4.le p10,p11=6,in5 } +{ .mfi; (p4)ldf8 bj[5]=[bptr],16 // bp[2] + (p5)fcvt.fxu bj[5]=f0 + cmp4.le p12,p13=7,in5 } +{ .mfi; (p6)ldf8 bj[4]=[r30],16 // bp[3] + (p7)fcvt.fxu bj[4]=f0 + cmp4.le p14,p15=8,in5 } +{ .mfi; (p4)ldf8 ni2=[nptr],16 // np[2] + (p5)fcvt.fxu ni2=f0 + addp4 r28=-1,in5 } +{ .mfi; (p6)ldf8 ni3=[r31],16 // np[3] + (p7)fcvt.fxu ni3=f0 + $ADDP in4=0,in4 };; + +{ .mfi; ldf8 n0=[in4] + fcvt.fxu tf[1]=f0 + nop.i 0 } + +{ .mfi; (p8)ldf8 ai4=[aptr],16 // ap[4] + (p9)fcvt.fxu ai4=f0 + mov t[0]=r0 } +{ .mfi; (p10)ldf8 ai5=[r29],16 // ap[5] + (p11)fcvt.fxu ai5=f0 + mov t[1]=r0 } +{ .mfi; (p8)ldf8 bj[3]=[bptr],16 // bp[4] + (p9)fcvt.fxu bj[3]=f0 + mov t[2]=r0 } +{ .mfi; (p10)ldf8 bj[2]=[r30],16 // bp[5] + (p11)fcvt.fxu bj[2]=f0 + mov t[3]=r0 } +{ .mfi; (p8)ldf8 ni4=[nptr],16 // np[4] + (p9)fcvt.fxu ni4=f0 + mov t[4]=r0 } +{ .mfi; (p10)ldf8 ni5=[r31],16 // np[5] + (p11)fcvt.fxu ni5=f0 + mov t[5]=r0 };; + +{ .mfi; (p12)ldf8 ai6=[aptr],16 // ap[6] + (p13)fcvt.fxu ai6=f0 + mov t[6]=r0 } +{ .mfi; (p14)ldf8 ai7=[r29],16 // ap[7] + (p15)fcvt.fxu ai7=f0 + mov t[7]=r0 } +{ .mfi; (p12)ldf8 bj[1]=[bptr],16 // bp[6] + (p13)fcvt.fxu bj[1]=f0 + mov ar.lc=r28 } +{ .mfi; (p14)ldf8 bj[0]=[r30],16 // bp[7] + (p15)fcvt.fxu bj[0]=f0 + mov ar.ec=1 } +{ .mfi; (p12)ldf8 ni6=[nptr],16 // np[6] + (p13)fcvt.fxu ni6=f0 + mov pr.rot=1<<16 } +{ .mfb; (p14)ldf8 ni7=[r31],16 // np[7] + (p15)fcvt.fxu ni7=f0 + brp.loop.imp .Louter_8_ctop,.Louter_8_cend-16 + };; + +// The loop is scheduled for 32*n ticks on Itanium 2. Actual attempt +// to measure with help of Interval Time Counter indicated that the +// factor is a tad higher: 33 or 34, if not 35. Exact measurement and +// addressing the issue is problematic, because I don't have access +// to platform-specific instruction-level profiler. On Itanium it +// should run in 56*n ticks, because of higher xma latency... +.Louter_8_ctop: + .pred.rel "mutex",p40,p42 + .pred.rel "mutex",p48,p50 +{ .mfi; (p16) nop.m 0 // 0: + (p16) xma.hu ahi[0]=ai0,bj[7],tf[1] // ap[0]*b[i]+t[0] + (p40) add a3=a3,n3 } // (p17) a3+=n3 +{ .mfi; (p42) add a3=a3,n3,1 + (p16) xma.lu alo[0]=ai0,bj[7],tf[1] + (p16) nop.i 0 };; +{ .mii; (p17) getf.sig a7=alo[8] // 1: + (p48) add t[6]=t[6],a3 // (p17) t[6]+=a3 + (p50) add t[6]=t[6],a3,1 };; +{ .mfi; (p17) getf.sig a8=ahi[8] // 2: + (p17) xma.hu nhi[7]=ni6,mj[1],nhi[6] // np[6]*m0 + (p40) cmp.ltu p43,p41=a3,n3 } +{ .mfi; (p42) cmp.leu p43,p41=a3,n3 + (p17) xma.lu nlo[7]=ni6,mj[1],nhi[6] + (p16) nop.i 0 };; +{ .mii; (p17) getf.sig n5=nlo[6] // 3: + (p48) cmp.ltu p51,p49=t[6],a3 + (p50) cmp.leu p51,p49=t[6],a3 };; + .pred.rel "mutex",p41,p43 + .pred.rel "mutex",p49,p51 +{ .mfi; (p16) nop.m 0 // 4: + (p16) xma.hu ahi[1]=ai1,bj[7],ahi[0] // ap[1]*b[i] + (p41) add a4=a4,n4 } // (p17) a4+=n4 +{ .mfi; (p43) add a4=a4,n4,1 + (p16) xma.lu alo[1]=ai1,bj[7],ahi[0] + (p16) nop.i 0 };; +{ .mfi; (p49) add t[5]=t[5],a4 // 5: (p17) t[5]+=a4 + (p16) xmpy.lu mj[0]=alo[0],n0 // (ap[0]*b[i]+t[0])*n0 + (p51) add t[5]=t[5],a4,1 };; +{ .mfi; (p16) nop.m 0 // 6: + (p17) xma.hu nhi[8]=ni7,mj[1],nhi[7] // np[7]*m0 + (p41) cmp.ltu p42,p40=a4,n4 } +{ .mfi; (p43) cmp.leu p42,p40=a4,n4 + (p17) xma.lu nlo[8]=ni7,mj[1],nhi[7] + (p16) nop.i 0 };; +{ .mii; (p17) getf.sig n6=nlo[7] // 7: + (p49) cmp.ltu p50,p48=t[5],a4 + (p51) cmp.leu p50,p48=t[5],a4 };; + .pred.rel "mutex",p40,p42 + .pred.rel "mutex",p48,p50 +{ .mfi; (p16) nop.m 0 // 8: + (p16) xma.hu ahi[2]=ai2,bj[7],ahi[1] // ap[2]*b[i] + (p40) add a5=a5,n5 } // (p17) a5+=n5 +{ .mfi; (p42) add a5=a5,n5,1 + (p16) xma.lu alo[2]=ai2,bj[7],ahi[1] + (p16) nop.i 0 };; +{ .mii; (p16) getf.sig a1=alo[1] // 9: + (p48) add t[4]=t[4],a5 // p(17) t[4]+=a5 + (p50) add t[4]=t[4],a5,1 };; +{ .mfi; (p16) nop.m 0 // 10: + (p16) xma.hu nhi[0]=ni0,mj[0],alo[0] // np[0]*m0 + (p40) cmp.ltu p43,p41=a5,n5 } +{ .mfi; (p42) cmp.leu p43,p41=a5,n5 + (p16) xma.lu nlo[0]=ni0,mj[0],alo[0] + (p16) nop.i 0 };; +{ .mii; (p17) getf.sig n7=nlo[8] // 11: + (p48) cmp.ltu p51,p49=t[4],a5 + (p50) cmp.leu p51,p49=t[4],a5 };; + .pred.rel "mutex",p41,p43 + .pred.rel "mutex",p49,p51 +{ .mfi; (p17) getf.sig n8=nhi[8] // 12: + (p16) xma.hu ahi[3]=ai3,bj[7],ahi[2] // ap[3]*b[i] + (p41) add a6=a6,n6 } // (p17) a6+=n6 +{ .mfi; (p43) add a6=a6,n6,1 + (p16) xma.lu alo[3]=ai3,bj[7],ahi[2] + (p16) nop.i 0 };; +{ .mii; (p16) getf.sig a2=alo[2] // 13: + (p49) add t[3]=t[3],a6 // (p17) t[3]+=a6 + (p51) add t[3]=t[3],a6,1 };; +{ .mfi; (p16) nop.m 0 // 14: + (p16) xma.hu nhi[1]=ni1,mj[0],nhi[0] // np[1]*m0 + (p41) cmp.ltu p42,p40=a6,n6 } +{ .mfi; (p43) cmp.leu p42,p40=a6,n6 + (p16) xma.lu nlo[1]=ni1,mj[0],nhi[0] + (p16) nop.i 0 };; +{ .mii; (p16) nop.m 0 // 15: + (p49) cmp.ltu p50,p48=t[3],a6 + (p51) cmp.leu p50,p48=t[3],a6 };; + .pred.rel "mutex",p40,p42 + .pred.rel "mutex",p48,p50 +{ .mfi; (p16) nop.m 0 // 16: + (p16) xma.hu ahi[4]=ai4,bj[7],ahi[3] // ap[4]*b[i] + (p40) add a7=a7,n7 } // (p17) a7+=n7 +{ .mfi; (p42) add a7=a7,n7,1 + (p16) xma.lu alo[4]=ai4,bj[7],ahi[3] + (p16) nop.i 0 };; +{ .mii; (p16) getf.sig a3=alo[3] // 17: + (p48) add t[2]=t[2],a7 // (p17) t[2]+=a7 + (p50) add t[2]=t[2],a7,1 };; +{ .mfi; (p16) nop.m 0 // 18: + (p16) xma.hu nhi[2]=ni2,mj[0],nhi[1] // np[2]*m0 + (p40) cmp.ltu p43,p41=a7,n7 } +{ .mfi; (p42) cmp.leu p43,p41=a7,n7 + (p16) xma.lu nlo[2]=ni2,mj[0],nhi[1] + (p16) nop.i 0 };; +{ .mii; (p16) getf.sig n1=nlo[1] // 19: + (p48) cmp.ltu p51,p49=t[2],a7 + (p50) cmp.leu p51,p49=t[2],a7 };; + .pred.rel "mutex",p41,p43 + .pred.rel "mutex",p49,p51 +{ .mfi; (p16) nop.m 0 // 20: + (p16) xma.hu ahi[5]=ai5,bj[7],ahi[4] // ap[5]*b[i] + (p41) add a8=a8,n8 } // (p17) a8+=n8 +{ .mfi; (p43) add a8=a8,n8,1 + (p16) xma.lu alo[5]=ai5,bj[7],ahi[4] + (p16) nop.i 0 };; +{ .mii; (p16) getf.sig a4=alo[4] // 21: + (p49) add t[1]=t[1],a8 // (p17) t[1]+=a8 + (p51) add t[1]=t[1],a8,1 };; +{ .mfi; (p16) nop.m 0 // 22: + (p16) xma.hu nhi[3]=ni3,mj[0],nhi[2] // np[3]*m0 + (p41) cmp.ltu p42,p40=a8,n8 } +{ .mfi; (p43) cmp.leu p42,p40=a8,n8 + (p16) xma.lu nlo[3]=ni3,mj[0],nhi[2] + (p16) nop.i 0 };; +{ .mii; (p16) getf.sig n2=nlo[2] // 23: + (p49) cmp.ltu p50,p48=t[1],a8 + (p51) cmp.leu p50,p48=t[1],a8 };; +{ .mfi; (p16) nop.m 0 // 24: + (p16) xma.hu ahi[6]=ai6,bj[7],ahi[5] // ap[6]*b[i] + (p16) add a1=a1,n1 } // (p16) a1+=n1 +{ .mfi; (p16) nop.m 0 + (p16) xma.lu alo[6]=ai6,bj[7],ahi[5] + (p17) mov t[0]=r0 };; +{ .mii; (p16) getf.sig a5=alo[5] // 25: + (p16) add t0=t[7],a1 // (p16) t[7]+=a1 + (p42) add t[0]=t[0],r0,1 };; +{ .mfi; (p16) setf.sig tf[0]=t0 // 26: + (p16) xma.hu nhi[4]=ni4,mj[0],nhi[3] // np[4]*m0 + (p50) add t[0]=t[0],r0,1 } +{ .mfi; (p16) cmp.ltu.unc p42,p40=a1,n1 + (p16) xma.lu nlo[4]=ni4,mj[0],nhi[3] + (p16) nop.i 0 };; +{ .mii; (p16) getf.sig n3=nlo[3] // 27: + (p16) cmp.ltu.unc p50,p48=t0,a1 + (p16) nop.i 0 };; + .pred.rel "mutex",p40,p42 + .pred.rel "mutex",p48,p50 +{ .mfi; (p16) nop.m 0 // 28: + (p16) xma.hu ahi[7]=ai7,bj[7],ahi[6] // ap[7]*b[i] + (p40) add a2=a2,n2 } // (p16) a2+=n2 +{ .mfi; (p42) add a2=a2,n2,1 + (p16) xma.lu alo[7]=ai7,bj[7],ahi[6] + (p16) nop.i 0 };; +{ .mii; (p16) getf.sig a6=alo[6] // 29: + (p48) add t[6]=t[6],a2 // (p16) t[6]+=a2 + (p50) add t[6]=t[6],a2,1 };; +{ .mfi; (p16) nop.m 0 // 30: + (p16) xma.hu nhi[5]=ni5,mj[0],nhi[4] // np[5]*m0 + (p40) cmp.ltu p41,p39=a2,n2 } +{ .mfi; (p42) cmp.leu p41,p39=a2,n2 + (p16) xma.lu nlo[5]=ni5,mj[0],nhi[4] + (p16) nop.i 0 };; +{ .mfi; (p16) getf.sig n4=nlo[4] // 31: + (p16) nop.f 0 + (p48) cmp.ltu p49,p47=t[6],a2 } +{ .mfb; (p50) cmp.leu p49,p47=t[6],a2 + (p16) nop.f 0 + br.ctop.sptk.many .Louter_8_ctop };; +.Louter_8_cend: + +// above loop has to execute one more time, without (p16), which is +// replaced with merged move of np[8] to GPR bank + .pred.rel "mutex",p40,p42 + .pred.rel "mutex",p48,p50 +{ .mmi; (p0) getf.sig n1=ni0 // 0: + (p40) add a3=a3,n3 // (p17) a3+=n3 + (p42) add a3=a3,n3,1 };; +{ .mii; (p17) getf.sig a7=alo[8] // 1: + (p48) add t[6]=t[6],a3 // (p17) t[6]+=a3 + (p50) add t[6]=t[6],a3,1 };; +{ .mfi; (p17) getf.sig a8=ahi[8] // 2: + (p17) xma.hu nhi[7]=ni6,mj[1],nhi[6] // np[6]*m0 + (p40) cmp.ltu p43,p41=a3,n3 } +{ .mfi; (p42) cmp.leu p43,p41=a3,n3 + (p17) xma.lu nlo[7]=ni6,mj[1],nhi[6] + (p0) nop.i 0 };; +{ .mii; (p17) getf.sig n5=nlo[6] // 3: + (p48) cmp.ltu p51,p49=t[6],a3 + (p50) cmp.leu p51,p49=t[6],a3 };; + .pred.rel "mutex",p41,p43 + .pred.rel "mutex",p49,p51 +{ .mmi; (p0) getf.sig n2=ni1 // 4: + (p41) add a4=a4,n4 // (p17) a4+=n4 + (p43) add a4=a4,n4,1 };; +{ .mfi; (p49) add t[5]=t[5],a4 // 5: (p17) t[5]+=a4 + (p0) nop.f 0 + (p51) add t[5]=t[5],a4,1 };; +{ .mfi; (p0) getf.sig n3=ni2 // 6: + (p17) xma.hu nhi[8]=ni7,mj[1],nhi[7] // np[7]*m0 + (p41) cmp.ltu p42,p40=a4,n4 } +{ .mfi; (p43) cmp.leu p42,p40=a4,n4 + (p17) xma.lu nlo[8]=ni7,mj[1],nhi[7] + (p0) nop.i 0 };; +{ .mii; (p17) getf.sig n6=nlo[7] // 7: + (p49) cmp.ltu p50,p48=t[5],a4 + (p51) cmp.leu p50,p48=t[5],a4 };; + .pred.rel "mutex",p40,p42 + .pred.rel "mutex",p48,p50 +{ .mii; (p0) getf.sig n4=ni3 // 8: + (p40) add a5=a5,n5 // (p17) a5+=n5 + (p42) add a5=a5,n5,1 };; +{ .mii; (p0) nop.m 0 // 9: + (p48) add t[4]=t[4],a5 // p(17) t[4]+=a5 + (p50) add t[4]=t[4],a5,1 };; +{ .mii; (p0) nop.m 0 // 10: + (p40) cmp.ltu p43,p41=a5,n5 + (p42) cmp.leu p43,p41=a5,n5 };; +{ .mii; (p17) getf.sig n7=nlo[8] // 11: + (p48) cmp.ltu p51,p49=t[4],a5 + (p50) cmp.leu p51,p49=t[4],a5 };; + .pred.rel "mutex",p41,p43 + .pred.rel "mutex",p49,p51 +{ .mii; (p17) getf.sig n8=nhi[8] // 12: + (p41) add a6=a6,n6 // (p17) a6+=n6 + (p43) add a6=a6,n6,1 };; +{ .mii; (p0) getf.sig n5=ni4 // 13: + (p49) add t[3]=t[3],a6 // (p17) t[3]+=a6 + (p51) add t[3]=t[3],a6,1 };; +{ .mii; (p0) nop.m 0 // 14: + (p41) cmp.ltu p42,p40=a6,n6 + (p43) cmp.leu p42,p40=a6,n6 };; +{ .mii; (p0) getf.sig n6=ni5 // 15: + (p49) cmp.ltu p50,p48=t[3],a6 + (p51) cmp.leu p50,p48=t[3],a6 };; + .pred.rel "mutex",p40,p42 + .pred.rel "mutex",p48,p50 +{ .mii; (p0) nop.m 0 // 16: + (p40) add a7=a7,n7 // (p17) a7+=n7 + (p42) add a7=a7,n7,1 };; +{ .mii; (p0) nop.m 0 // 17: + (p48) add t[2]=t[2],a7 // (p17) t[2]+=a7 + (p50) add t[2]=t[2],a7,1 };; +{ .mii; (p0) nop.m 0 // 18: + (p40) cmp.ltu p43,p41=a7,n7 + (p42) cmp.leu p43,p41=a7,n7 };; +{ .mii; (p0) getf.sig n7=ni6 // 19: + (p48) cmp.ltu p51,p49=t[2],a7 + (p50) cmp.leu p51,p49=t[2],a7 };; + .pred.rel "mutex",p41,p43 + .pred.rel "mutex",p49,p51 +{ .mii; (p0) nop.m 0 // 20: + (p41) add a8=a8,n8 // (p17) a8+=n8 + (p43) add a8=a8,n8,1 };; +{ .mmi; (p0) nop.m 0 // 21: + (p49) add t[1]=t[1],a8 // (p17) t[1]+=a8 + (p51) add t[1]=t[1],a8,1 } +{ .mmi; (p17) mov t[0]=r0 + (p41) cmp.ltu p42,p40=a8,n8 + (p43) cmp.leu p42,p40=a8,n8 };; +{ .mmi; (p0) getf.sig n8=ni7 // 22: + (p49) cmp.ltu p50,p48=t[1],a8 + (p51) cmp.leu p50,p48=t[1],a8 } +{ .mmi; (p42) add t[0]=t[0],r0,1 + (p0) add r16=-7*16,prevsp + (p0) add r17=-6*16,prevsp };; + +// subtract np[8] from carrybit|tmp[8] +// carrybit|tmp[8] layout upon exit from above loop is: +// t[0]|t[1]|t[2]|t[3]|t[4]|t[5]|t[6]|t[7]|t0 (least significant) +{ .mmi; (p50)add t[0]=t[0],r0,1 + add r18=-5*16,prevsp + sub n1=t0,n1 };; +{ .mmi; cmp.gtu p34,p32=n1,t0;; + .pred.rel "mutex",p32,p34 + (p32)sub n2=t[7],n2 + (p34)sub n2=t[7],n2,1 };; +{ .mii; (p32)cmp.gtu p35,p33=n2,t[7] + (p34)cmp.geu p35,p33=n2,t[7];; + .pred.rel "mutex",p33,p35 + (p33)sub n3=t[6],n3 } +{ .mmi; (p35)sub n3=t[6],n3,1;; + (p33)cmp.gtu p34,p32=n3,t[6] + (p35)cmp.geu p34,p32=n3,t[6] };; + .pred.rel "mutex",p32,p34 +{ .mii; (p32)sub n4=t[5],n4 + (p34)sub n4=t[5],n4,1;; + (p32)cmp.gtu p35,p33=n4,t[5] } +{ .mmi; (p34)cmp.geu p35,p33=n4,t[5];; + .pred.rel "mutex",p33,p35 + (p33)sub n5=t[4],n5 + (p35)sub n5=t[4],n5,1 };; +{ .mii; (p33)cmp.gtu p34,p32=n5,t[4] + (p35)cmp.geu p34,p32=n5,t[4];; + .pred.rel "mutex",p32,p34 + (p32)sub n6=t[3],n6 } +{ .mmi; (p34)sub n6=t[3],n6,1;; + (p32)cmp.gtu p35,p33=n6,t[3] + (p34)cmp.geu p35,p33=n6,t[3] };; + .pred.rel "mutex",p33,p35 +{ .mii; (p33)sub n7=t[2],n7 + (p35)sub n7=t[2],n7,1;; + (p33)cmp.gtu p34,p32=n7,t[2] } +{ .mmi; (p35)cmp.geu p34,p32=n7,t[2];; + .pred.rel "mutex",p32,p34 + (p32)sub n8=t[1],n8 + (p34)sub n8=t[1],n8,1 };; +{ .mii; (p32)cmp.gtu p35,p33=n8,t[1] + (p34)cmp.geu p35,p33=n8,t[1];; + .pred.rel "mutex",p33,p35 + (p33)sub a8=t[0],r0 } +{ .mmi; (p35)sub a8=t[0],r0,1;; + (p33)cmp.gtu p34,p32=a8,t[0] + (p35)cmp.geu p34,p32=a8,t[0] };; + +// save the result, either tmp[num] or tmp[num]-np[num] + .pred.rel "mutex",p32,p34 +{ .mmi; (p32)st8 [rptr]=n1,8 + (p34)st8 [rptr]=t0,8 + add r19=-4*16,prevsp};; +{ .mmb; (p32)st8 [rptr]=n2,8 + (p34)st8 [rptr]=t[7],8 + (p5)br.cond.dpnt.few .Ldone };; +{ .mmb; (p32)st8 [rptr]=n3,8 + (p34)st8 [rptr]=t[6],8 + (p7)br.cond.dpnt.few .Ldone };; +{ .mmb; (p32)st8 [rptr]=n4,8 + (p34)st8 [rptr]=t[5],8 + (p9)br.cond.dpnt.few .Ldone };; +{ .mmb; (p32)st8 [rptr]=n5,8 + (p34)st8 [rptr]=t[4],8 + (p11)br.cond.dpnt.few .Ldone };; +{ .mmb; (p32)st8 [rptr]=n6,8 + (p34)st8 [rptr]=t[3],8 + (p13)br.cond.dpnt.few .Ldone };; +{ .mmb; (p32)st8 [rptr]=n7,8 + (p34)st8 [rptr]=t[2],8 + (p15)br.cond.dpnt.few .Ldone };; +{ .mmb; (p32)st8 [rptr]=n8,8 + (p34)st8 [rptr]=t[1],8 + nop.b 0 };; +.Ldone: // epilogue +{ .mmi; ldf.fill f16=[r16],64 + ldf.fill f17=[r17],64 + nop.i 0 } +{ .mmi; ldf.fill f18=[r18],64 + ldf.fill f19=[r19],64 + mov pr=prevpr,0x1ffff };; +{ .mmi; ldf.fill f20=[r16] + ldf.fill f21=[r17] + mov ar.lc=prevlc } +{ .mmi; ldf.fill f22=[r18] + ldf.fill f23=[r19] + mov ret0=1 } // signal "handled" +{ .mib; rum 1<<5 + .restore sp + mov sp=prevsp + br.ret.sptk.many b0 };; +.endp bn_mul_mont_8# + +.type copyright#,\@object +copyright: +stringz "Montgomery multiplication for IA-64, CRYPTOGAMS by " +___ + +open STDOUT,">$output" if $output; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/ia64.S b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/ia64.S new file mode 100644 index 000000000..0a26735c6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/ia64.S @@ -0,0 +1,1565 @@ +.explicit +.text +.ident "ia64.S, Version 2.1" +.ident "IA-64 ISA artwork by Andy Polyakov " + +// Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved. +// +// Licensed under the OpenSSL license (the "License"). You may not use +// this file except in compliance with the License. You can obtain a copy +// in the file LICENSE in the source distribution or at +// https://www.openssl.org/source/license.html + +// +// ==================================================================== +// Written by Andy Polyakov for the OpenSSL +// project. +// +// Rights for redistribution and usage in source and binary forms are +// granted according to the OpenSSL license. Warranty of any kind is +// disclaimed. +// ==================================================================== +// +// Version 2.x is Itanium2 re-tune. Few words about how Itanium2 is +// different from Itanium to this module viewpoint. Most notably, is it +// "wider" than Itanium? Can you experience loop scalability as +// discussed in commentary sections? Not really:-( Itanium2 has 6 +// integer ALU ports, i.e. it's 2 ports wider, but it's not enough to +// spin twice as fast, as I need 8 IALU ports. Amount of floating point +// ports is the same, i.e. 2, while I need 4. In other words, to this +// module Itanium2 remains effectively as "wide" as Itanium. Yet it's +// essentially different in respect to this module, and a re-tune was +// required. Well, because some instruction latencies has changed. Most +// noticeably those intensively used: +// +// Itanium Itanium2 +// ldf8 9 6 L2 hit +// ld8 2 1 L1 hit +// getf 2 5 +// xma[->getf] 7[+1] 4[+0] +// add[->st8] 1[+1] 1[+0] +// +// What does it mean? You might ratiocinate that the original code +// should run just faster... Because sum of latencies is smaller... +// Wrong! Note that getf latency increased. This means that if a loop is +// scheduled for lower latency (as they were), then it will suffer from +// stall condition and the code will therefore turn anti-scalable, e.g. +// original bn_mul_words spun at 5*n or 2.5 times slower than expected +// on Itanium2! What to do? Reschedule loops for Itanium2? But then +// Itanium would exhibit anti-scalability. So I've chosen to reschedule +// for worst latency for every instruction aiming for best *all-round* +// performance. + +// Q. How much faster does it get? +// A. Here is the output from 'openssl speed rsa dsa' for vanilla +// 0.9.6a compiled with gcc version 2.96 20000731 (Red Hat +// Linux 7.1 2.96-81): +// +// sign verify sign/s verify/s +// rsa 512 bits 0.0036s 0.0003s 275.3 2999.2 +// rsa 1024 bits 0.0203s 0.0011s 49.3 894.1 +// rsa 2048 bits 0.1331s 0.0040s 7.5 250.9 +// rsa 4096 bits 0.9270s 0.0147s 1.1 68.1 +// sign verify sign/s verify/s +// dsa 512 bits 0.0035s 0.0043s 288.3 234.8 +// dsa 1024 bits 0.0111s 0.0135s 90.0 74.2 +// +// And here is similar output but for this assembler +// implementation:-) +// +// sign verify sign/s verify/s +// rsa 512 bits 0.0021s 0.0001s 549.4 9638.5 +// rsa 1024 bits 0.0055s 0.0002s 183.8 4481.1 +// rsa 2048 bits 0.0244s 0.0006s 41.4 1726.3 +// rsa 4096 bits 0.1295s 0.0018s 7.7 561.5 +// sign verify sign/s verify/s +// dsa 512 bits 0.0012s 0.0013s 891.9 756.6 +// dsa 1024 bits 0.0023s 0.0028s 440.4 376.2 +// +// Yes, you may argue that it's not fair comparison as it's +// possible to craft the C implementation with BN_UMULT_HIGH +// inline assembler macro. But of course! Here is the output +// with the macro: +// +// sign verify sign/s verify/s +// rsa 512 bits 0.0020s 0.0002s 495.0 6561.0 +// rsa 1024 bits 0.0086s 0.0004s 116.2 2235.7 +// rsa 2048 bits 0.0519s 0.0015s 19.3 667.3 +// rsa 4096 bits 0.3464s 0.0053s 2.9 187.7 +// sign verify sign/s verify/s +// dsa 512 bits 0.0016s 0.0020s 613.1 510.5 +// dsa 1024 bits 0.0045s 0.0054s 221.0 183.9 +// +// My code is still way faster, huh:-) And I believe that even +// higher performance can be achieved. Note that as keys get +// longer, performance gain is larger. Why? According to the +// profiler there is another player in the field, namely +// BN_from_montgomery consuming larger and larger portion of CPU +// time as keysize decreases. I therefore consider putting effort +// to assembler implementation of the following routine: +// +// void bn_mul_add_mont (BN_ULONG *rp,BN_ULONG *np,int nl,BN_ULONG n0) +// { +// int i,j; +// BN_ULONG v; +// +// for (i=0; i for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# This module doesn't present direct interest for OpenSSL, because it +# doesn't provide better performance for longer keys, at least not on +# in-order-execution cores. While 512-bit RSA sign operations can be +# 65% faster in 64-bit mode, 1024-bit ones are only 15% faster, and +# 4096-bit ones are up to 15% slower. In 32-bit mode it varies from +# 16% improvement for 512-bit RSA sign to -33% for 4096-bit RSA +# verify:-( All comparisons are against bn_mul_mont-free assembler. +# The module might be of interest to embedded system developers, as +# the code is smaller than 1KB, yet offers >3x improvement on MIPS64 +# and 75-30% [less for longer keys] on MIPS32 over compiler-generated +# code. + +###################################################################### +# There is a number of MIPS ABI in use, O32 and N32/64 are most +# widely used. Then there is a new contender: NUBI. It appears that if +# one picks the latter, it's possible to arrange code in ABI neutral +# manner. Therefore let's stick to NUBI register layout: +# +($zero,$at,$t0,$t1,$t2)=map("\$$_",(0..2,24,25)); +($a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7)=map("\$$_",(4..11)); +($s0,$s1,$s2,$s3,$s4,$s5,$s6,$s7,$s8,$s9,$s10,$s11)=map("\$$_",(12..23)); +($gp,$tp,$sp,$fp,$ra)=map("\$$_",(3,28..31)); +# +# The return value is placed in $a0. Following coding rules facilitate +# interoperability: +# +# - never ever touch $tp, "thread pointer", former $gp; +# - copy return value to $t0, former $v0 [or to $a0 if you're adapting +# old code]; +# - on O32 populate $a4-$a7 with 'lw $aN,4*N($sp)' if necessary; +# +# For reference here is register layout for N32/64 MIPS ABIs: +# +# ($zero,$at,$v0,$v1)=map("\$$_",(0..3)); +# ($a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7)=map("\$$_",(4..11)); +# ($t0,$t1,$t2,$t3,$t8,$t9)=map("\$$_",(12..15,24,25)); +# ($s0,$s1,$s2,$s3,$s4,$s5,$s6,$s7)=map("\$$_",(16..23)); +# ($gp,$sp,$fp,$ra)=map("\$$_",(28..31)); +# +$flavour = shift || "o32"; # supported flavours are o32,n32,64,nubi32,nubi64 + +if ($flavour =~ /64|n32/i) { + $PTR_ADD="daddu"; # incidentally works even on n32 + $PTR_SUB="dsubu"; # incidentally works even on n32 + $REG_S="sd"; + $REG_L="ld"; + $SZREG=8; +} else { + $PTR_ADD="addu"; + $PTR_SUB="subu"; + $REG_S="sw"; + $REG_L="lw"; + $SZREG=4; +} +$SAVED_REGS_MASK = ($flavour =~ /nubi/i) ? 0x00fff000 : 0x00ff0000; +# +# +# +###################################################################### + +while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} +open STDOUT,">$output"; + +if ($flavour =~ /64|n32/i) { + $LD="ld"; + $ST="sd"; + $MULTU="dmultu"; + $ADDU="daddu"; + $SUBU="dsubu"; + $BNSZ=8; +} else { + $LD="lw"; + $ST="sw"; + $MULTU="multu"; + $ADDU="addu"; + $SUBU="subu"; + $BNSZ=4; +} + +# int bn_mul_mont( +$rp=$a0; # BN_ULONG *rp, +$ap=$a1; # const BN_ULONG *ap, +$bp=$a2; # const BN_ULONG *bp, +$np=$a3; # const BN_ULONG *np, +$n0=$a4; # const BN_ULONG *n0, +$num=$a5; # int num); + +$lo0=$a6; +$hi0=$a7; +$lo1=$t1; +$hi1=$t2; +$aj=$s0; +$bi=$s1; +$nj=$s2; +$tp=$s3; +$alo=$s4; +$ahi=$s5; +$nlo=$s6; +$nhi=$s7; +$tj=$s8; +$i=$s9; +$j=$s10; +$m1=$s11; + +$FRAMESIZE=14; + +$code=<<___; +#include "mips_arch.h" + +.text + +.set noat +.set noreorder + +.align 5 +.globl bn_mul_mont +.ent bn_mul_mont +bn_mul_mont: +___ +$code.=<<___ if ($flavour =~ /o32/i); + lw $n0,16($sp) + lw $num,20($sp) +___ +$code.=<<___; + slt $at,$num,4 + bnez $at,1f + li $t0,0 + slt $at,$num,17 # on in-order CPU + bnez $at,bn_mul_mont_internal + nop +1: jr $ra + li $a0,0 +.end bn_mul_mont + +.align 5 +.ent bn_mul_mont_internal +bn_mul_mont_internal: + .frame $fp,$FRAMESIZE*$SZREG,$ra + .mask 0x40000000|$SAVED_REGS_MASK,-$SZREG + $PTR_SUB $sp,$FRAMESIZE*$SZREG + $REG_S $fp,($FRAMESIZE-1)*$SZREG($sp) + $REG_S $s11,($FRAMESIZE-2)*$SZREG($sp) + $REG_S $s10,($FRAMESIZE-3)*$SZREG($sp) + $REG_S $s9,($FRAMESIZE-4)*$SZREG($sp) + $REG_S $s8,($FRAMESIZE-5)*$SZREG($sp) + $REG_S $s7,($FRAMESIZE-6)*$SZREG($sp) + $REG_S $s6,($FRAMESIZE-7)*$SZREG($sp) + $REG_S $s5,($FRAMESIZE-8)*$SZREG($sp) + $REG_S $s4,($FRAMESIZE-9)*$SZREG($sp) +___ +$code.=<<___ if ($flavour =~ /nubi/i); + $REG_S $s3,($FRAMESIZE-10)*$SZREG($sp) + $REG_S $s2,($FRAMESIZE-11)*$SZREG($sp) + $REG_S $s1,($FRAMESIZE-12)*$SZREG($sp) + $REG_S $s0,($FRAMESIZE-13)*$SZREG($sp) +___ +$code.=<<___; + move $fp,$sp + + .set reorder + $LD $n0,0($n0) + $LD $bi,0($bp) # bp[0] + $LD $aj,0($ap) # ap[0] + $LD $nj,0($np) # np[0] + + $PTR_SUB $sp,2*$BNSZ # place for two extra words + sll $num,`log($BNSZ)/log(2)` + li $at,-4096 + $PTR_SUB $sp,$num + and $sp,$at + + $MULTU ($aj,$bi) + $LD $ahi,$BNSZ($ap) + $LD $nhi,$BNSZ($np) + mflo ($lo0,$aj,$bi) + mfhi ($hi0,$aj,$bi) + $MULTU ($lo0,$n0) + mflo ($m1,$lo0,$n0) + + $MULTU ($ahi,$bi) + mflo ($alo,$ahi,$bi) + mfhi ($ahi,$ahi,$bi) + + $MULTU ($nj,$m1) + mflo ($lo1,$nj,$m1) + mfhi ($hi1,$nj,$m1) + $MULTU ($nhi,$m1) + $ADDU $lo1,$lo0 + sltu $at,$lo1,$lo0 + $ADDU $hi1,$at + mflo ($nlo,$nhi,$m1) + mfhi ($nhi,$nhi,$m1) + + move $tp,$sp + li $j,2*$BNSZ +.align 4 +.L1st: + .set noreorder + $PTR_ADD $aj,$ap,$j + $PTR_ADD $nj,$np,$j + $LD $aj,($aj) + $LD $nj,($nj) + + $MULTU ($aj,$bi) + $ADDU $lo0,$alo,$hi0 + $ADDU $lo1,$nlo,$hi1 + sltu $at,$lo0,$hi0 + sltu $t0,$lo1,$hi1 + $ADDU $hi0,$ahi,$at + $ADDU $hi1,$nhi,$t0 + mflo ($alo,$aj,$bi) + mfhi ($ahi,$aj,$bi) + + $ADDU $lo1,$lo0 + sltu $at,$lo1,$lo0 + $MULTU ($nj,$m1) + $ADDU $hi1,$at + addu $j,$BNSZ + $ST $lo1,($tp) + sltu $t0,$j,$num + mflo ($nlo,$nj,$m1) + mfhi ($nhi,$nj,$m1) + + bnez $t0,.L1st + $PTR_ADD $tp,$BNSZ + .set reorder + + $ADDU $lo0,$alo,$hi0 + sltu $at,$lo0,$hi0 + $ADDU $hi0,$ahi,$at + + $ADDU $lo1,$nlo,$hi1 + sltu $t0,$lo1,$hi1 + $ADDU $hi1,$nhi,$t0 + $ADDU $lo1,$lo0 + sltu $at,$lo1,$lo0 + $ADDU $hi1,$at + + $ST $lo1,($tp) + + $ADDU $hi1,$hi0 + sltu $at,$hi1,$hi0 + $ST $hi1,$BNSZ($tp) + $ST $at,2*$BNSZ($tp) + + li $i,$BNSZ +.align 4 +.Louter: + $PTR_ADD $bi,$bp,$i + $LD $bi,($bi) + $LD $aj,($ap) + $LD $ahi,$BNSZ($ap) + $LD $tj,($sp) + + $MULTU ($aj,$bi) + $LD $nj,($np) + $LD $nhi,$BNSZ($np) + mflo ($lo0,$aj,$bi) + mfhi ($hi0,$aj,$bi) + $ADDU $lo0,$tj + $MULTU ($lo0,$n0) + sltu $at,$lo0,$tj + $ADDU $hi0,$at + mflo ($m1,$lo0,$n0) + + $MULTU ($ahi,$bi) + mflo ($alo,$ahi,$bi) + mfhi ($ahi,$ahi,$bi) + + $MULTU ($nj,$m1) + mflo ($lo1,$nj,$m1) + mfhi ($hi1,$nj,$m1) + + $MULTU ($nhi,$m1) + $ADDU $lo1,$lo0 + sltu $at,$lo1,$lo0 + $ADDU $hi1,$at + mflo ($nlo,$nhi,$m1) + mfhi ($nhi,$nhi,$m1) + + move $tp,$sp + li $j,2*$BNSZ + $LD $tj,$BNSZ($tp) +.align 4 +.Linner: + .set noreorder + $PTR_ADD $aj,$ap,$j + $PTR_ADD $nj,$np,$j + $LD $aj,($aj) + $LD $nj,($nj) + + $MULTU ($aj,$bi) + $ADDU $lo0,$alo,$hi0 + $ADDU $lo1,$nlo,$hi1 + sltu $at,$lo0,$hi0 + sltu $t0,$lo1,$hi1 + $ADDU $hi0,$ahi,$at + $ADDU $hi1,$nhi,$t0 + mflo ($alo,$aj,$bi) + mfhi ($ahi,$aj,$bi) + + $ADDU $lo0,$tj + addu $j,$BNSZ + $MULTU ($nj,$m1) + sltu $at,$lo0,$tj + $ADDU $lo1,$lo0 + $ADDU $hi0,$at + sltu $t0,$lo1,$lo0 + $LD $tj,2*$BNSZ($tp) + $ADDU $hi1,$t0 + sltu $at,$j,$num + mflo ($nlo,$nj,$m1) + mfhi ($nhi,$nj,$m1) + $ST $lo1,($tp) + bnez $at,.Linner + $PTR_ADD $tp,$BNSZ + .set reorder + + $ADDU $lo0,$alo,$hi0 + sltu $at,$lo0,$hi0 + $ADDU $hi0,$ahi,$at + $ADDU $lo0,$tj + sltu $t0,$lo0,$tj + $ADDU $hi0,$t0 + + $LD $tj,2*$BNSZ($tp) + $ADDU $lo1,$nlo,$hi1 + sltu $at,$lo1,$hi1 + $ADDU $hi1,$nhi,$at + $ADDU $lo1,$lo0 + sltu $t0,$lo1,$lo0 + $ADDU $hi1,$t0 + $ST $lo1,($tp) + + $ADDU $lo1,$hi1,$hi0 + sltu $hi1,$lo1,$hi0 + $ADDU $lo1,$tj + sltu $at,$lo1,$tj + $ADDU $hi1,$at + $ST $lo1,$BNSZ($tp) + $ST $hi1,2*$BNSZ($tp) + + addu $i,$BNSZ + sltu $t0,$i,$num + bnez $t0,.Louter + + .set noreorder + $PTR_ADD $tj,$sp,$num # &tp[num] + move $tp,$sp + move $ap,$sp + li $hi0,0 # clear borrow bit + +.align 4 +.Lsub: $LD $lo0,($tp) + $LD $lo1,($np) + $PTR_ADD $tp,$BNSZ + $PTR_ADD $np,$BNSZ + $SUBU $lo1,$lo0,$lo1 # tp[i]-np[i] + sgtu $at,$lo1,$lo0 + $SUBU $lo0,$lo1,$hi0 + sgtu $hi0,$lo0,$lo1 + $ST $lo0,($rp) + or $hi0,$at + sltu $at,$tp,$tj + bnez $at,.Lsub + $PTR_ADD $rp,$BNSZ + + $SUBU $hi0,$hi1,$hi0 # handle upmost overflow bit + move $tp,$sp + $PTR_SUB $rp,$num # restore rp + not $hi1,$hi0 + +.Lcopy: $LD $nj,($tp) # conditional move + $LD $aj,($rp) + $ST $zero,($tp) + $PTR_ADD $tp,$BNSZ + and $nj,$hi0 + and $aj,$hi1 + or $aj,$nj + sltu $at,$tp,$tj + $ST $aj,($rp) + bnez $at,.Lcopy + $PTR_ADD $rp,$BNSZ + + li $a0,1 + li $t0,1 + + .set noreorder + move $sp,$fp + $REG_L $fp,($FRAMESIZE-1)*$SZREG($sp) + $REG_L $s11,($FRAMESIZE-2)*$SZREG($sp) + $REG_L $s10,($FRAMESIZE-3)*$SZREG($sp) + $REG_L $s9,($FRAMESIZE-4)*$SZREG($sp) + $REG_L $s8,($FRAMESIZE-5)*$SZREG($sp) + $REG_L $s7,($FRAMESIZE-6)*$SZREG($sp) + $REG_L $s6,($FRAMESIZE-7)*$SZREG($sp) + $REG_L $s5,($FRAMESIZE-8)*$SZREG($sp) + $REG_L $s4,($FRAMESIZE-9)*$SZREG($sp) +___ +$code.=<<___ if ($flavour =~ /nubi/i); + $REG_L $s3,($FRAMESIZE-10)*$SZREG($sp) + $REG_L $s2,($FRAMESIZE-11)*$SZREG($sp) + $REG_L $s1,($FRAMESIZE-12)*$SZREG($sp) + $REG_L $s0,($FRAMESIZE-13)*$SZREG($sp) +___ +$code.=<<___; + jr $ra + $PTR_ADD $sp,$FRAMESIZE*$SZREG +.end bn_mul_mont_internal +.rdata +.asciiz "Montgomery Multiplication for MIPS, CRYPTOGAMS by " +___ + +$code =~ s/\`([^\`]*)\`/eval $1/gem; + +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/mips.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/mips.pl new file mode 100644 index 000000000..3875132bd --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/mips.pl @@ -0,0 +1,2263 @@ +#! /usr/bin/env perl +# Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. +# +# Rights for redistribution and usage in source and binary forms are +# granted according to the OpenSSL license. Warranty of any kind is +# disclaimed. +# ==================================================================== + + +# July 1999 +# +# This is drop-in MIPS III/IV ISA replacement for crypto/bn/bn_asm.c. +# +# The module is designed to work with either of the "new" MIPS ABI(5), +# namely N32 or N64, offered by IRIX 6.x. It's not meant to work under +# IRIX 5.x not only because it doesn't support new ABIs but also +# because 5.x kernels put R4x00 CPU into 32-bit mode and all those +# 64-bit instructions (daddu, dmultu, etc.) found below gonna only +# cause illegal instruction exception:-( +# +# In addition the code depends on preprocessor flags set up by MIPSpro +# compiler driver (either as or cc) and therefore (probably?) can't be +# compiled by the GNU assembler. GNU C driver manages fine though... +# I mean as long as -mmips-as is specified or is the default option, +# because then it simply invokes /usr/bin/as which in turn takes +# perfect care of the preprocessor definitions. Another neat feature +# offered by the MIPSpro assembler is an optimization pass. This gave +# me the opportunity to have the code looking more regular as all those +# architecture dependent instruction rescheduling details were left to +# the assembler. Cool, huh? +# +# Performance improvement is astonishing! 'apps/openssl speed rsa dsa' +# goes way over 3 times faster! +# +# + +# October 2010 +# +# Adapt the module even for 32-bit ABIs and other OSes. The former was +# achieved by mechanical replacement of 64-bit arithmetic instructions +# such as dmultu, daddu, etc. with their 32-bit counterparts and +# adjusting offsets denoting multiples of BN_ULONG. Above mentioned +# >3x performance improvement naturally does not apply to 32-bit code +# [because there is no instruction 32-bit compiler can't use], one +# has to content with 40-85% improvement depending on benchmark and +# key length, more for longer keys. + +$flavour = shift || "o32"; +while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} +open STDOUT,">$output"; + +if ($flavour =~ /64|n32/i) { + $LD="ld"; + $ST="sd"; + $MULTU="dmultu"; + $DIVU="ddivu"; + $ADDU="daddu"; + $SUBU="dsubu"; + $SRL="dsrl"; + $SLL="dsll"; + $BNSZ=8; + $PTR_ADD="daddu"; + $PTR_SUB="dsubu"; + $SZREG=8; + $REG_S="sd"; + $REG_L="ld"; +} else { + $LD="lw"; + $ST="sw"; + $MULTU="multu"; + $DIVU="divu"; + $ADDU="addu"; + $SUBU="subu"; + $SRL="srl"; + $SLL="sll"; + $BNSZ=4; + $PTR_ADD="addu"; + $PTR_SUB="subu"; + $SZREG=4; + $REG_S="sw"; + $REG_L="lw"; + $code=".set mips2\n"; +} + +# Below is N32/64 register layout used in the original module. +# +($zero,$at,$v0,$v1)=map("\$$_",(0..3)); +($a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7)=map("\$$_",(4..11)); +($t0,$t1,$t2,$t3,$t8,$t9)=map("\$$_",(12..15,24,25)); +($s0,$s1,$s2,$s3,$s4,$s5,$s6,$s7)=map("\$$_",(16..23)); +($gp,$sp,$fp,$ra)=map("\$$_",(28..31)); +($ta0,$ta1,$ta2,$ta3)=($a4,$a5,$a6,$a7); +# +# No special adaptation is required for O32. NUBI on the other hand +# is treated by saving/restoring ($v1,$t0..$t3). + +$gp=$v1 if ($flavour =~ /nubi/i); + +$minus4=$v1; + +$code.=<<___; +#include "mips_arch.h" + +#if defined(_MIPS_ARCH_MIPS64R6) +# define ddivu(rs,rt) +# define mfqt(rd,rs,rt) ddivu rd,rs,rt +# define mfrm(rd,rs,rt) dmodu rd,rs,rt +#elif defined(_MIPS_ARCH_MIPS32R6) +# define divu(rs,rt) +# define mfqt(rd,rs,rt) divu rd,rs,rt +# define mfrm(rd,rs,rt) modu rd,rs,rt +#else +# define $DIVU(rs,rt) $DIVU $zero,rs,rt +# define mfqt(rd,rs,rt) mflo rd +# define mfrm(rd,rs,rt) mfhi rd +#endif + +.rdata +.asciiz "mips3.s, Version 1.2" +.asciiz "MIPS II/III/IV ISA artwork by Andy Polyakov " + +.text +.set noat + +.align 5 +.globl bn_mul_add_words +.ent bn_mul_add_words +bn_mul_add_words: + .set noreorder + bgtz $a2,bn_mul_add_words_internal + move $v0,$zero + jr $ra + move $a0,$v0 +.end bn_mul_add_words + +.align 5 +.ent bn_mul_add_words_internal +bn_mul_add_words_internal: +___ +$code.=<<___ if ($flavour =~ /nubi/i); + .frame $sp,6*$SZREG,$ra + .mask 0x8000f008,-$SZREG + .set noreorder + $PTR_SUB $sp,6*$SZREG + $REG_S $ra,5*$SZREG($sp) + $REG_S $t3,4*$SZREG($sp) + $REG_S $t2,3*$SZREG($sp) + $REG_S $t1,2*$SZREG($sp) + $REG_S $t0,1*$SZREG($sp) + $REG_S $gp,0*$SZREG($sp) +___ +$code.=<<___; + .set reorder + li $minus4,-4 + and $ta0,$a2,$minus4 + beqz $ta0,.L_bn_mul_add_words_tail + +.L_bn_mul_add_words_loop: + $LD $t0,0($a1) + $MULTU ($t0,$a3) + $LD $t1,0($a0) + $LD $t2,$BNSZ($a1) + $LD $t3,$BNSZ($a0) + $LD $ta0,2*$BNSZ($a1) + $LD $ta1,2*$BNSZ($a0) + $ADDU $t1,$v0 + sltu $v0,$t1,$v0 # All manuals say it "compares 32-bit + # values", but it seems to work fine + # even on 64-bit registers. + mflo ($at,$t0,$a3) + mfhi ($t0,$t0,$a3) + $ADDU $t1,$at + $ADDU $v0,$t0 + $MULTU ($t2,$a3) + sltu $at,$t1,$at + $ST $t1,0($a0) + $ADDU $v0,$at + + $LD $ta2,3*$BNSZ($a1) + $LD $ta3,3*$BNSZ($a0) + $ADDU $t3,$v0 + sltu $v0,$t3,$v0 + mflo ($at,$t2,$a3) + mfhi ($t2,$t2,$a3) + $ADDU $t3,$at + $ADDU $v0,$t2 + $MULTU ($ta0,$a3) + sltu $at,$t3,$at + $ST $t3,$BNSZ($a0) + $ADDU $v0,$at + + subu $a2,4 + $PTR_ADD $a0,4*$BNSZ + $PTR_ADD $a1,4*$BNSZ + $ADDU $ta1,$v0 + sltu $v0,$ta1,$v0 + mflo ($at,$ta0,$a3) + mfhi ($ta0,$ta0,$a3) + $ADDU $ta1,$at + $ADDU $v0,$ta0 + $MULTU ($ta2,$a3) + sltu $at,$ta1,$at + $ST $ta1,-2*$BNSZ($a0) + $ADDU $v0,$at + + + and $ta0,$a2,$minus4 + $ADDU $ta3,$v0 + sltu $v0,$ta3,$v0 + mflo ($at,$ta2,$a3) + mfhi ($ta2,$ta2,$a3) + $ADDU $ta3,$at + $ADDU $v0,$ta2 + sltu $at,$ta3,$at + $ST $ta3,-$BNSZ($a0) + .set noreorder + bgtz $ta0,.L_bn_mul_add_words_loop + $ADDU $v0,$at + + beqz $a2,.L_bn_mul_add_words_return + nop + +.L_bn_mul_add_words_tail: + .set reorder + $LD $t0,0($a1) + $MULTU ($t0,$a3) + $LD $t1,0($a0) + subu $a2,1 + $ADDU $t1,$v0 + sltu $v0,$t1,$v0 + mflo ($at,$t0,$a3) + mfhi ($t0,$t0,$a3) + $ADDU $t1,$at + $ADDU $v0,$t0 + sltu $at,$t1,$at + $ST $t1,0($a0) + $ADDU $v0,$at + beqz $a2,.L_bn_mul_add_words_return + + $LD $t0,$BNSZ($a1) + $MULTU ($t0,$a3) + $LD $t1,$BNSZ($a0) + subu $a2,1 + $ADDU $t1,$v0 + sltu $v0,$t1,$v0 + mflo ($at,$t0,$a3) + mfhi ($t0,$t0,$a3) + $ADDU $t1,$at + $ADDU $v0,$t0 + sltu $at,$t1,$at + $ST $t1,$BNSZ($a0) + $ADDU $v0,$at + beqz $a2,.L_bn_mul_add_words_return + + $LD $t0,2*$BNSZ($a1) + $MULTU ($t0,$a3) + $LD $t1,2*$BNSZ($a0) + $ADDU $t1,$v0 + sltu $v0,$t1,$v0 + mflo ($at,$t0,$a3) + mfhi ($t0,$t0,$a3) + $ADDU $t1,$at + $ADDU $v0,$t0 + sltu $at,$t1,$at + $ST $t1,2*$BNSZ($a0) + $ADDU $v0,$at + +.L_bn_mul_add_words_return: + .set noreorder +___ +$code.=<<___ if ($flavour =~ /nubi/i); + $REG_L $t3,4*$SZREG($sp) + $REG_L $t2,3*$SZREG($sp) + $REG_L $t1,2*$SZREG($sp) + $REG_L $t0,1*$SZREG($sp) + $REG_L $gp,0*$SZREG($sp) + $PTR_ADD $sp,6*$SZREG +___ +$code.=<<___; + jr $ra + move $a0,$v0 +.end bn_mul_add_words_internal + +.align 5 +.globl bn_mul_words +.ent bn_mul_words +bn_mul_words: + .set noreorder + bgtz $a2,bn_mul_words_internal + move $v0,$zero + jr $ra + move $a0,$v0 +.end bn_mul_words + +.align 5 +.ent bn_mul_words_internal +bn_mul_words_internal: +___ +$code.=<<___ if ($flavour =~ /nubi/i); + .frame $sp,6*$SZREG,$ra + .mask 0x8000f008,-$SZREG + .set noreorder + $PTR_SUB $sp,6*$SZREG + $REG_S $ra,5*$SZREG($sp) + $REG_S $t3,4*$SZREG($sp) + $REG_S $t2,3*$SZREG($sp) + $REG_S $t1,2*$SZREG($sp) + $REG_S $t0,1*$SZREG($sp) + $REG_S $gp,0*$SZREG($sp) +___ +$code.=<<___; + .set reorder + li $minus4,-4 + and $ta0,$a2,$minus4 + beqz $ta0,.L_bn_mul_words_tail + +.L_bn_mul_words_loop: + $LD $t0,0($a1) + $MULTU ($t0,$a3) + $LD $t2,$BNSZ($a1) + $LD $ta0,2*$BNSZ($a1) + $LD $ta2,3*$BNSZ($a1) + mflo ($at,$t0,$a3) + mfhi ($t0,$t0,$a3) + $ADDU $v0,$at + sltu $t1,$v0,$at + $MULTU ($t2,$a3) + $ST $v0,0($a0) + $ADDU $v0,$t1,$t0 + + subu $a2,4 + $PTR_ADD $a0,4*$BNSZ + $PTR_ADD $a1,4*$BNSZ + mflo ($at,$t2,$a3) + mfhi ($t2,$t2,$a3) + $ADDU $v0,$at + sltu $t3,$v0,$at + $MULTU ($ta0,$a3) + $ST $v0,-3*$BNSZ($a0) + $ADDU $v0,$t3,$t2 + + mflo ($at,$ta0,$a3) + mfhi ($ta0,$ta0,$a3) + $ADDU $v0,$at + sltu $ta1,$v0,$at + $MULTU ($ta2,$a3) + $ST $v0,-2*$BNSZ($a0) + $ADDU $v0,$ta1,$ta0 + + and $ta0,$a2,$minus4 + mflo ($at,$ta2,$a3) + mfhi ($ta2,$ta2,$a3) + $ADDU $v0,$at + sltu $ta3,$v0,$at + $ST $v0,-$BNSZ($a0) + .set noreorder + bgtz $ta0,.L_bn_mul_words_loop + $ADDU $v0,$ta3,$ta2 + + beqz $a2,.L_bn_mul_words_return + nop + +.L_bn_mul_words_tail: + .set reorder + $LD $t0,0($a1) + $MULTU ($t0,$a3) + subu $a2,1 + mflo ($at,$t0,$a3) + mfhi ($t0,$t0,$a3) + $ADDU $v0,$at + sltu $t1,$v0,$at + $ST $v0,0($a0) + $ADDU $v0,$t1,$t0 + beqz $a2,.L_bn_mul_words_return + + $LD $t0,$BNSZ($a1) + $MULTU ($t0,$a3) + subu $a2,1 + mflo ($at,$t0,$a3) + mfhi ($t0,$t0,$a3) + $ADDU $v0,$at + sltu $t1,$v0,$at + $ST $v0,$BNSZ($a0) + $ADDU $v0,$t1,$t0 + beqz $a2,.L_bn_mul_words_return + + $LD $t0,2*$BNSZ($a1) + $MULTU ($t0,$a3) + mflo ($at,$t0,$a3) + mfhi ($t0,$t0,$a3) + $ADDU $v0,$at + sltu $t1,$v0,$at + $ST $v0,2*$BNSZ($a0) + $ADDU $v0,$t1,$t0 + +.L_bn_mul_words_return: + .set noreorder +___ +$code.=<<___ if ($flavour =~ /nubi/i); + $REG_L $t3,4*$SZREG($sp) + $REG_L $t2,3*$SZREG($sp) + $REG_L $t1,2*$SZREG($sp) + $REG_L $t0,1*$SZREG($sp) + $REG_L $gp,0*$SZREG($sp) + $PTR_ADD $sp,6*$SZREG +___ +$code.=<<___; + jr $ra + move $a0,$v0 +.end bn_mul_words_internal + +.align 5 +.globl bn_sqr_words +.ent bn_sqr_words +bn_sqr_words: + .set noreorder + bgtz $a2,bn_sqr_words_internal + move $v0,$zero + jr $ra + move $a0,$v0 +.end bn_sqr_words + +.align 5 +.ent bn_sqr_words_internal +bn_sqr_words_internal: +___ +$code.=<<___ if ($flavour =~ /nubi/i); + .frame $sp,6*$SZREG,$ra + .mask 0x8000f008,-$SZREG + .set noreorder + $PTR_SUB $sp,6*$SZREG + $REG_S $ra,5*$SZREG($sp) + $REG_S $t3,4*$SZREG($sp) + $REG_S $t2,3*$SZREG($sp) + $REG_S $t1,2*$SZREG($sp) + $REG_S $t0,1*$SZREG($sp) + $REG_S $gp,0*$SZREG($sp) +___ +$code.=<<___; + .set reorder + li $minus4,-4 + and $ta0,$a2,$minus4 + beqz $ta0,.L_bn_sqr_words_tail + +.L_bn_sqr_words_loop: + $LD $t0,0($a1) + $MULTU ($t0,$t0) + $LD $t2,$BNSZ($a1) + $LD $ta0,2*$BNSZ($a1) + $LD $ta2,3*$BNSZ($a1) + mflo ($t1,$t0,$t0) + mfhi ($t0,$t0,$t0) + $ST $t1,0($a0) + $ST $t0,$BNSZ($a0) + + $MULTU ($t2,$t2) + subu $a2,4 + $PTR_ADD $a0,8*$BNSZ + $PTR_ADD $a1,4*$BNSZ + mflo ($t3,$t2,$t2) + mfhi ($t2,$t2,$t2) + $ST $t3,-6*$BNSZ($a0) + $ST $t2,-5*$BNSZ($a0) + + $MULTU ($ta0,$ta0) + mflo ($ta1,$ta0,$ta0) + mfhi ($ta0,$ta0,$ta0) + $ST $ta1,-4*$BNSZ($a0) + $ST $ta0,-3*$BNSZ($a0) + + + $MULTU ($ta2,$ta2) + and $ta0,$a2,$minus4 + mflo ($ta3,$ta2,$ta2) + mfhi ($ta2,$ta2,$ta2) + $ST $ta3,-2*$BNSZ($a0) + + .set noreorder + bgtz $ta0,.L_bn_sqr_words_loop + $ST $ta2,-$BNSZ($a0) + + beqz $a2,.L_bn_sqr_words_return + nop + +.L_bn_sqr_words_tail: + .set reorder + $LD $t0,0($a1) + $MULTU ($t0,$t0) + subu $a2,1 + mflo ($t1,$t0,$t0) + mfhi ($t0,$t0,$t0) + $ST $t1,0($a0) + $ST $t0,$BNSZ($a0) + beqz $a2,.L_bn_sqr_words_return + + $LD $t0,$BNSZ($a1) + $MULTU ($t0,$t0) + subu $a2,1 + mflo ($t1,$t0,$t0) + mfhi ($t0,$t0,$t0) + $ST $t1,2*$BNSZ($a0) + $ST $t0,3*$BNSZ($a0) + beqz $a2,.L_bn_sqr_words_return + + $LD $t0,2*$BNSZ($a1) + $MULTU ($t0,$t0) + mflo ($t1,$t0,$t0) + mfhi ($t0,$t0,$t0) + $ST $t1,4*$BNSZ($a0) + $ST $t0,5*$BNSZ($a0) + +.L_bn_sqr_words_return: + .set noreorder +___ +$code.=<<___ if ($flavour =~ /nubi/i); + $REG_L $t3,4*$SZREG($sp) + $REG_L $t2,3*$SZREG($sp) + $REG_L $t1,2*$SZREG($sp) + $REG_L $t0,1*$SZREG($sp) + $REG_L $gp,0*$SZREG($sp) + $PTR_ADD $sp,6*$SZREG +___ +$code.=<<___; + jr $ra + move $a0,$v0 + +.end bn_sqr_words_internal + +.align 5 +.globl bn_add_words +.ent bn_add_words +bn_add_words: + .set noreorder + bgtz $a3,bn_add_words_internal + move $v0,$zero + jr $ra + move $a0,$v0 +.end bn_add_words + +.align 5 +.ent bn_add_words_internal +bn_add_words_internal: +___ +$code.=<<___ if ($flavour =~ /nubi/i); + .frame $sp,6*$SZREG,$ra + .mask 0x8000f008,-$SZREG + .set noreorder + $PTR_SUB $sp,6*$SZREG + $REG_S $ra,5*$SZREG($sp) + $REG_S $t3,4*$SZREG($sp) + $REG_S $t2,3*$SZREG($sp) + $REG_S $t1,2*$SZREG($sp) + $REG_S $t0,1*$SZREG($sp) + $REG_S $gp,0*$SZREG($sp) +___ +$code.=<<___; + .set reorder + li $minus4,-4 + and $at,$a3,$minus4 + beqz $at,.L_bn_add_words_tail + +.L_bn_add_words_loop: + $LD $t0,0($a1) + $LD $ta0,0($a2) + subu $a3,4 + $LD $t1,$BNSZ($a1) + and $at,$a3,$minus4 + $LD $t2,2*$BNSZ($a1) + $PTR_ADD $a2,4*$BNSZ + $LD $t3,3*$BNSZ($a1) + $PTR_ADD $a0,4*$BNSZ + $LD $ta1,-3*$BNSZ($a2) + $PTR_ADD $a1,4*$BNSZ + $LD $ta2,-2*$BNSZ($a2) + $LD $ta3,-$BNSZ($a2) + $ADDU $ta0,$t0 + sltu $t8,$ta0,$t0 + $ADDU $t0,$ta0,$v0 + sltu $v0,$t0,$ta0 + $ST $t0,-4*$BNSZ($a0) + $ADDU $v0,$t8 + + $ADDU $ta1,$t1 + sltu $t9,$ta1,$t1 + $ADDU $t1,$ta1,$v0 + sltu $v0,$t1,$ta1 + $ST $t1,-3*$BNSZ($a0) + $ADDU $v0,$t9 + + $ADDU $ta2,$t2 + sltu $t8,$ta2,$t2 + $ADDU $t2,$ta2,$v0 + sltu $v0,$t2,$ta2 + $ST $t2,-2*$BNSZ($a0) + $ADDU $v0,$t8 + + $ADDU $ta3,$t3 + sltu $t9,$ta3,$t3 + $ADDU $t3,$ta3,$v0 + sltu $v0,$t3,$ta3 + $ST $t3,-$BNSZ($a0) + + .set noreorder + bgtz $at,.L_bn_add_words_loop + $ADDU $v0,$t9 + + beqz $a3,.L_bn_add_words_return + nop + +.L_bn_add_words_tail: + .set reorder + $LD $t0,0($a1) + $LD $ta0,0($a2) + $ADDU $ta0,$t0 + subu $a3,1 + sltu $t8,$ta0,$t0 + $ADDU $t0,$ta0,$v0 + sltu $v0,$t0,$ta0 + $ST $t0,0($a0) + $ADDU $v0,$t8 + beqz $a3,.L_bn_add_words_return + + $LD $t1,$BNSZ($a1) + $LD $ta1,$BNSZ($a2) + $ADDU $ta1,$t1 + subu $a3,1 + sltu $t9,$ta1,$t1 + $ADDU $t1,$ta1,$v0 + sltu $v0,$t1,$ta1 + $ST $t1,$BNSZ($a0) + $ADDU $v0,$t9 + beqz $a3,.L_bn_add_words_return + + $LD $t2,2*$BNSZ($a1) + $LD $ta2,2*$BNSZ($a2) + $ADDU $ta2,$t2 + sltu $t8,$ta2,$t2 + $ADDU $t2,$ta2,$v0 + sltu $v0,$t2,$ta2 + $ST $t2,2*$BNSZ($a0) + $ADDU $v0,$t8 + +.L_bn_add_words_return: + .set noreorder +___ +$code.=<<___ if ($flavour =~ /nubi/i); + $REG_L $t3,4*$SZREG($sp) + $REG_L $t2,3*$SZREG($sp) + $REG_L $t1,2*$SZREG($sp) + $REG_L $t0,1*$SZREG($sp) + $REG_L $gp,0*$SZREG($sp) + $PTR_ADD $sp,6*$SZREG +___ +$code.=<<___; + jr $ra + move $a0,$v0 + +.end bn_add_words_internal + +.align 5 +.globl bn_sub_words +.ent bn_sub_words +bn_sub_words: + .set noreorder + bgtz $a3,bn_sub_words_internal + move $v0,$zero + jr $ra + move $a0,$zero +.end bn_sub_words + +.align 5 +.ent bn_sub_words_internal +bn_sub_words_internal: +___ +$code.=<<___ if ($flavour =~ /nubi/i); + .frame $sp,6*$SZREG,$ra + .mask 0x8000f008,-$SZREG + .set noreorder + $PTR_SUB $sp,6*$SZREG + $REG_S $ra,5*$SZREG($sp) + $REG_S $t3,4*$SZREG($sp) + $REG_S $t2,3*$SZREG($sp) + $REG_S $t1,2*$SZREG($sp) + $REG_S $t0,1*$SZREG($sp) + $REG_S $gp,0*$SZREG($sp) +___ +$code.=<<___; + .set reorder + li $minus4,-4 + and $at,$a3,$minus4 + beqz $at,.L_bn_sub_words_tail + +.L_bn_sub_words_loop: + $LD $t0,0($a1) + $LD $ta0,0($a2) + subu $a3,4 + $LD $t1,$BNSZ($a1) + and $at,$a3,$minus4 + $LD $t2,2*$BNSZ($a1) + $PTR_ADD $a2,4*$BNSZ + $LD $t3,3*$BNSZ($a1) + $PTR_ADD $a0,4*$BNSZ + $LD $ta1,-3*$BNSZ($a2) + $PTR_ADD $a1,4*$BNSZ + $LD $ta2,-2*$BNSZ($a2) + $LD $ta3,-$BNSZ($a2) + sltu $t8,$t0,$ta0 + $SUBU $ta0,$t0,$ta0 + $SUBU $t0,$ta0,$v0 + sgtu $v0,$t0,$ta0 + $ST $t0,-4*$BNSZ($a0) + $ADDU $v0,$t8 + + sltu $t9,$t1,$ta1 + $SUBU $ta1,$t1,$ta1 + $SUBU $t1,$ta1,$v0 + sgtu $v0,$t1,$ta1 + $ST $t1,-3*$BNSZ($a0) + $ADDU $v0,$t9 + + + sltu $t8,$t2,$ta2 + $SUBU $ta2,$t2,$ta2 + $SUBU $t2,$ta2,$v0 + sgtu $v0,$t2,$ta2 + $ST $t2,-2*$BNSZ($a0) + $ADDU $v0,$t8 + + sltu $t9,$t3,$ta3 + $SUBU $ta3,$t3,$ta3 + $SUBU $t3,$ta3,$v0 + sgtu $v0,$t3,$ta3 + $ST $t3,-$BNSZ($a0) + + .set noreorder + bgtz $at,.L_bn_sub_words_loop + $ADDU $v0,$t9 + + beqz $a3,.L_bn_sub_words_return + nop + +.L_bn_sub_words_tail: + .set reorder + $LD $t0,0($a1) + $LD $ta0,0($a2) + subu $a3,1 + sltu $t8,$t0,$ta0 + $SUBU $ta0,$t0,$ta0 + $SUBU $t0,$ta0,$v0 + sgtu $v0,$t0,$ta0 + $ST $t0,0($a0) + $ADDU $v0,$t8 + beqz $a3,.L_bn_sub_words_return + + $LD $t1,$BNSZ($a1) + subu $a3,1 + $LD $ta1,$BNSZ($a2) + sltu $t9,$t1,$ta1 + $SUBU $ta1,$t1,$ta1 + $SUBU $t1,$ta1,$v0 + sgtu $v0,$t1,$ta1 + $ST $t1,$BNSZ($a0) + $ADDU $v0,$t9 + beqz $a3,.L_bn_sub_words_return + + $LD $t2,2*$BNSZ($a1) + $LD $ta2,2*$BNSZ($a2) + sltu $t8,$t2,$ta2 + $SUBU $ta2,$t2,$ta2 + $SUBU $t2,$ta2,$v0 + sgtu $v0,$t2,$ta2 + $ST $t2,2*$BNSZ($a0) + $ADDU $v0,$t8 + +.L_bn_sub_words_return: + .set noreorder +___ +$code.=<<___ if ($flavour =~ /nubi/i); + $REG_L $t3,4*$SZREG($sp) + $REG_L $t2,3*$SZREG($sp) + $REG_L $t1,2*$SZREG($sp) + $REG_L $t0,1*$SZREG($sp) + $REG_L $gp,0*$SZREG($sp) + $PTR_ADD $sp,6*$SZREG +___ +$code.=<<___; + jr $ra + move $a0,$v0 +.end bn_sub_words_internal + +#if 0 +/* + * The bn_div_3_words entry point is re-used for constant-time interface. + * Implementation is retained as hystorical reference. + */ +.align 5 +.globl bn_div_3_words +.ent bn_div_3_words +bn_div_3_words: + .set noreorder + move $a3,$a0 # we know that bn_div_words does not + # touch $a3, $ta2, $ta3 and preserves $a2 + # so that we can save two arguments + # and return address in registers + # instead of stack:-) + + $LD $a0,($a3) + move $ta2,$a1 + bne $a0,$a2,bn_div_3_words_internal + $LD $a1,-$BNSZ($a3) + li $v0,-1 + jr $ra + move $a0,$v0 +.end bn_div_3_words + +.align 5 +.ent bn_div_3_words_internal +bn_div_3_words_internal: +___ +$code.=<<___ if ($flavour =~ /nubi/i); + .frame $sp,6*$SZREG,$ra + .mask 0x8000f008,-$SZREG + .set noreorder + $PTR_SUB $sp,6*$SZREG + $REG_S $ra,5*$SZREG($sp) + $REG_S $t3,4*$SZREG($sp) + $REG_S $t2,3*$SZREG($sp) + $REG_S $t1,2*$SZREG($sp) + $REG_S $t0,1*$SZREG($sp) + $REG_S $gp,0*$SZREG($sp) +___ +$code.=<<___; + .set reorder + move $ta3,$ra + bal bn_div_words_internal + move $ra,$ta3 + $MULTU ($ta2,$v0) + $LD $t2,-2*$BNSZ($a3) + move $ta0,$zero + mfhi ($t1,$ta2,$v0) + mflo ($t0,$ta2,$v0) + sltu $t8,$t1,$a1 +.L_bn_div_3_words_inner_loop: + bnez $t8,.L_bn_div_3_words_inner_loop_done + sgeu $at,$t2,$t0 + seq $t9,$t1,$a1 + and $at,$t9 + sltu $t3,$t0,$ta2 + $ADDU $a1,$a2 + $SUBU $t1,$t3 + $SUBU $t0,$ta2 + sltu $t8,$t1,$a1 + sltu $ta0,$a1,$a2 + or $t8,$ta0 + .set noreorder + beqz $at,.L_bn_div_3_words_inner_loop + $SUBU $v0,1 + $ADDU $v0,1 + .set reorder +.L_bn_div_3_words_inner_loop_done: + .set noreorder +___ +$code.=<<___ if ($flavour =~ /nubi/i); + $REG_L $t3,4*$SZREG($sp) + $REG_L $t2,3*$SZREG($sp) + $REG_L $t1,2*$SZREG($sp) + $REG_L $t0,1*$SZREG($sp) + $REG_L $gp,0*$SZREG($sp) + $PTR_ADD $sp,6*$SZREG +___ +$code.=<<___; + jr $ra + move $a0,$v0 +.end bn_div_3_words_internal +#endif + +.align 5 +.globl bn_div_words +.ent bn_div_words +bn_div_words: + .set noreorder + bnez $a2,bn_div_words_internal + li $v0,-1 # I would rather signal div-by-zero + # which can be done with 'break 7' + jr $ra + move $a0,$v0 +.end bn_div_words + +.align 5 +.ent bn_div_words_internal +bn_div_words_internal: +___ +$code.=<<___ if ($flavour =~ /nubi/i); + .frame $sp,6*$SZREG,$ra + .mask 0x8000f008,-$SZREG + .set noreorder + $PTR_SUB $sp,6*$SZREG + $REG_S $ra,5*$SZREG($sp) + $REG_S $t3,4*$SZREG($sp) + $REG_S $t2,3*$SZREG($sp) + $REG_S $t1,2*$SZREG($sp) + $REG_S $t0,1*$SZREG($sp) + $REG_S $gp,0*$SZREG($sp) +___ +$code.=<<___; + move $v1,$zero + bltz $a2,.L_bn_div_words_body + move $t9,$v1 + $SLL $a2,1 + bgtz $a2,.-4 + addu $t9,1 + + .set reorder + negu $t1,$t9 + li $t2,-1 + $SLL $t2,$t1 + and $t2,$a0 + $SRL $at,$a1,$t1 + .set noreorder + beqz $t2,.+12 + nop + break 6 # signal overflow + .set reorder + $SLL $a0,$t9 + $SLL $a1,$t9 + or $a0,$at +___ +$QT=$ta0; +$HH=$ta1; +$DH=$v1; +$code.=<<___; +.L_bn_div_words_body: + $SRL $DH,$a2,4*$BNSZ # bits + sgeu $at,$a0,$a2 + .set noreorder + beqz $at,.+12 + nop + $SUBU $a0,$a2 + .set reorder + + li $QT,-1 + $SRL $HH,$a0,4*$BNSZ # bits + $SRL $QT,4*$BNSZ # q=0xffffffff + beq $DH,$HH,.L_bn_div_words_skip_div1 + $DIVU ($a0,$DH) + mfqt ($QT,$a0,$DH) +.L_bn_div_words_skip_div1: + $MULTU ($a2,$QT) + $SLL $t3,$a0,4*$BNSZ # bits + $SRL $at,$a1,4*$BNSZ # bits + or $t3,$at + mflo ($t0,$a2,$QT) + mfhi ($t1,$a2,$QT) +.L_bn_div_words_inner_loop1: + sltu $t2,$t3,$t0 + seq $t8,$HH,$t1 + sltu $at,$HH,$t1 + and $t2,$t8 + sltu $v0,$t0,$a2 + or $at,$t2 + .set noreorder + beqz $at,.L_bn_div_words_inner_loop1_done + $SUBU $t1,$v0 + $SUBU $t0,$a2 + b .L_bn_div_words_inner_loop1 + $SUBU $QT,1 + .set reorder +.L_bn_div_words_inner_loop1_done: + + $SLL $a1,4*$BNSZ # bits + $SUBU $a0,$t3,$t0 + $SLL $v0,$QT,4*$BNSZ # bits + + li $QT,-1 + $SRL $HH,$a0,4*$BNSZ # bits + $SRL $QT,4*$BNSZ # q=0xffffffff + beq $DH,$HH,.L_bn_div_words_skip_div2 + $DIVU ($a0,$DH) + mfqt ($QT,$a0,$DH) +.L_bn_div_words_skip_div2: + $MULTU ($a2,$QT) + $SLL $t3,$a0,4*$BNSZ # bits + $SRL $at,$a1,4*$BNSZ # bits + or $t3,$at + mflo ($t0,$a2,$QT) + mfhi ($t1,$a2,$QT) +.L_bn_div_words_inner_loop2: + sltu $t2,$t3,$t0 + seq $t8,$HH,$t1 + sltu $at,$HH,$t1 + and $t2,$t8 + sltu $v1,$t0,$a2 + or $at,$t2 + .set noreorder + beqz $at,.L_bn_div_words_inner_loop2_done + $SUBU $t1,$v1 + $SUBU $t0,$a2 + b .L_bn_div_words_inner_loop2 + $SUBU $QT,1 + .set reorder +.L_bn_div_words_inner_loop2_done: + + $SUBU $a0,$t3,$t0 + or $v0,$QT + $SRL $v1,$a0,$t9 # $v1 contains remainder if anybody wants it + $SRL $a2,$t9 # restore $a2 + + .set noreorder + move $a1,$v1 +___ +$code.=<<___ if ($flavour =~ /nubi/i); + $REG_L $t3,4*$SZREG($sp) + $REG_L $t2,3*$SZREG($sp) + $REG_L $t1,2*$SZREG($sp) + $REG_L $t0,1*$SZREG($sp) + $REG_L $gp,0*$SZREG($sp) + $PTR_ADD $sp,6*$SZREG +___ +$code.=<<___; + jr $ra + move $a0,$v0 +.end bn_div_words_internal +___ +undef $HH; undef $QT; undef $DH; + +($a_0,$a_1,$a_2,$a_3)=($t0,$t1,$t2,$t3); +($b_0,$b_1,$b_2,$b_3)=($ta0,$ta1,$ta2,$ta3); + +($a_4,$a_5,$a_6,$a_7)=($s0,$s2,$s4,$a1); # once we load a[7], no use for $a1 +($b_4,$b_5,$b_6,$b_7)=($s1,$s3,$s5,$a2); # once we load b[7], no use for $a2 + +($t_1,$t_2,$c_1,$c_2,$c_3)=($t8,$t9,$v0,$v1,$a3); + +$code.=<<___; + +.align 5 +.globl bn_mul_comba8 +.ent bn_mul_comba8 +bn_mul_comba8: + .set noreorder +___ +$code.=<<___ if ($flavour =~ /nubi/i); + .frame $sp,12*$SZREG,$ra + .mask 0x803ff008,-$SZREG + $PTR_SUB $sp,12*$SZREG + $REG_S $ra,11*$SZREG($sp) + $REG_S $s5,10*$SZREG($sp) + $REG_S $s4,9*$SZREG($sp) + $REG_S $s3,8*$SZREG($sp) + $REG_S $s2,7*$SZREG($sp) + $REG_S $s1,6*$SZREG($sp) + $REG_S $s0,5*$SZREG($sp) + $REG_S $t3,4*$SZREG($sp) + $REG_S $t2,3*$SZREG($sp) + $REG_S $t1,2*$SZREG($sp) + $REG_S $t0,1*$SZREG($sp) + $REG_S $gp,0*$SZREG($sp) +___ +$code.=<<___ if ($flavour !~ /nubi/i); + .frame $sp,6*$SZREG,$ra + .mask 0x003f0000,-$SZREG + $PTR_SUB $sp,6*$SZREG + $REG_S $s5,5*$SZREG($sp) + $REG_S $s4,4*$SZREG($sp) + $REG_S $s3,3*$SZREG($sp) + $REG_S $s2,2*$SZREG($sp) + $REG_S $s1,1*$SZREG($sp) + $REG_S $s0,0*$SZREG($sp) +___ +$code.=<<___; + + .set reorder + $LD $a_0,0($a1) # If compiled with -mips3 option on + # R5000 box assembler barks on this + # 1ine with "should not have mult/div + # as last instruction in bb (R10K + # bug)" warning. If anybody out there + # has a clue about how to circumvent + # this do send me a note. + # + + $LD $b_0,0($a2) + $LD $a_1,$BNSZ($a1) + $LD $a_2,2*$BNSZ($a1) + $MULTU ($a_0,$b_0) # mul_add_c(a[0],b[0],c1,c2,c3); + $LD $a_3,3*$BNSZ($a1) + $LD $b_1,$BNSZ($a2) + $LD $b_2,2*$BNSZ($a2) + $LD $b_3,3*$BNSZ($a2) + mflo ($c_1,$a_0,$b_0) + mfhi ($c_2,$a_0,$b_0) + + $LD $a_4,4*$BNSZ($a1) + $LD $a_5,5*$BNSZ($a1) + $MULTU ($a_0,$b_1) # mul_add_c(a[0],b[1],c2,c3,c1); + $LD $a_6,6*$BNSZ($a1) + $LD $a_7,7*$BNSZ($a1) + $LD $b_4,4*$BNSZ($a2) + $LD $b_5,5*$BNSZ($a2) + mflo ($t_1,$a_0,$b_1) + mfhi ($t_2,$a_0,$b_1) + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_1,$b_0) # mul_add_c(a[1],b[0],c2,c3,c1); + $ADDU $c_3,$t_2,$at + $LD $b_6,6*$BNSZ($a2) + $LD $b_7,7*$BNSZ($a2) + $ST $c_1,0($a0) # r[0]=c1; + mflo ($t_1,$a_1,$b_0) + mfhi ($t_2,$a_1,$b_0) + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_2,$b_0) # mul_add_c(a[2],b[0],c3,c1,c2); + $ADDU $t_2,$at + $ADDU $c_3,$t_2 + sltu $c_1,$c_3,$t_2 + $ST $c_2,$BNSZ($a0) # r[1]=c2; + + mflo ($t_1,$a_2,$b_0) + mfhi ($t_2,$a_2,$b_0) + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $MULTU ($a_1,$b_1) # mul_add_c(a[1],b[1],c3,c1,c2); + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + mflo ($t_1,$a_1,$b_1) + mfhi ($t_2,$a_1,$b_1) + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $MULTU ($a_0,$b_2) # mul_add_c(a[0],b[2],c3,c1,c2); + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + sltu $c_2,$c_1,$t_2 + mflo ($t_1,$a_0,$b_2) + mfhi ($t_2,$a_0,$b_2) + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $MULTU ($a_0,$b_3) # mul_add_c(a[0],b[3],c1,c2,c3); + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + sltu $at,$c_1,$t_2 + $ADDU $c_2,$at + $ST $c_3,2*$BNSZ($a0) # r[2]=c3; + + mflo ($t_1,$a_0,$b_3) + mfhi ($t_2,$a_0,$b_3) + $ADDU $c_1,$t_1 + sltu $at,$c_1,$t_1 + $MULTU ($a_1,$b_2) # mul_add_c(a[1],b[2],c1,c2,c3); + $ADDU $t_2,$at + $ADDU $c_2,$t_2 + sltu $c_3,$c_2,$t_2 + mflo ($t_1,$a_1,$b_2) + mfhi ($t_2,$a_1,$b_2) + $ADDU $c_1,$t_1 + sltu $at,$c_1,$t_1 + $MULTU ($a_2,$b_1) # mul_add_c(a[2],b[1],c1,c2,c3); + $ADDU $t_2,$at + $ADDU $c_2,$t_2 + sltu $at,$c_2,$t_2 + $ADDU $c_3,$at + mflo ($t_1,$a_2,$b_1) + mfhi ($t_2,$a_2,$b_1) + $ADDU $c_1,$t_1 + sltu $at,$c_1,$t_1 + $MULTU ($a_3,$b_0) # mul_add_c(a[3],b[0],c1,c2,c3); + $ADDU $t_2,$at + $ADDU $c_2,$t_2 + sltu $at,$c_2,$t_2 + $ADDU $c_3,$at + mflo ($t_1,$a_3,$b_0) + mfhi ($t_2,$a_3,$b_0) + $ADDU $c_1,$t_1 + sltu $at,$c_1,$t_1 + $MULTU ($a_4,$b_0) # mul_add_c(a[4],b[0],c2,c3,c1); + $ADDU $t_2,$at + $ADDU $c_2,$t_2 + sltu $at,$c_2,$t_2 + $ADDU $c_3,$at + $ST $c_1,3*$BNSZ($a0) # r[3]=c1; + + mflo ($t_1,$a_4,$b_0) + mfhi ($t_2,$a_4,$b_0) + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_3,$b_1) # mul_add_c(a[3],b[1],c2,c3,c1); + $ADDU $t_2,$at + $ADDU $c_3,$t_2 + sltu $c_1,$c_3,$t_2 + mflo ($t_1,$a_3,$b_1) + mfhi ($t_2,$a_3,$b_1) + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_2,$b_2) # mul_add_c(a[2],b[2],c2,c3,c1); + $ADDU $t_2,$at + $ADDU $c_3,$t_2 + sltu $at,$c_3,$t_2 + $ADDU $c_1,$at + mflo ($t_1,$a_2,$b_2) + mfhi ($t_2,$a_2,$b_2) + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_1,$b_3) # mul_add_c(a[1],b[3],c2,c3,c1); + $ADDU $t_2,$at + $ADDU $c_3,$t_2 + sltu $at,$c_3,$t_2 + $ADDU $c_1,$at + mflo ($t_1,$a_1,$b_3) + mfhi ($t_2,$a_1,$b_3) + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_0,$b_4) # mul_add_c(a[0],b[4],c2,c3,c1); + $ADDU $t_2,$at + $ADDU $c_3,$t_2 + sltu $at,$c_3,$t_2 + $ADDU $c_1,$at + mflo ($t_1,$a_0,$b_4) + mfhi ($t_2,$a_0,$b_4) + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_0,$b_5) # mul_add_c(a[0],b[5],c3,c1,c2); + $ADDU $t_2,$at + $ADDU $c_3,$t_2 + sltu $at,$c_3,$t_2 + $ADDU $c_1,$at + $ST $c_2,4*$BNSZ($a0) # r[4]=c2; + + mflo ($t_1,$a_0,$b_5) + mfhi ($t_2,$a_0,$b_5) + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $MULTU ($a_1,$b_4) # mul_add_c(a[1],b[4],c3,c1,c2); + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + sltu $c_2,$c_1,$t_2 + mflo ($t_1,$a_1,$b_4) + mfhi ($t_2,$a_1,$b_4) + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $MULTU ($a_2,$b_3) # mul_add_c(a[2],b[3],c3,c1,c2); + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + sltu $at,$c_1,$t_2 + $ADDU $c_2,$at + mflo ($t_1,$a_2,$b_3) + mfhi ($t_2,$a_2,$b_3) + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $MULTU ($a_3,$b_2) # mul_add_c(a[3],b[2],c3,c1,c2); + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + sltu $at,$c_1,$t_2 + $ADDU $c_2,$at + mflo ($t_1,$a_3,$b_2) + mfhi ($t_2,$a_3,$b_2) + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $MULTU ($a_4,$b_1) # mul_add_c(a[4],b[1],c3,c1,c2); + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + sltu $at,$c_1,$t_2 + $ADDU $c_2,$at + mflo ($t_1,$a_4,$b_1) + mfhi ($t_2,$a_4,$b_1) + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $MULTU ($a_5,$b_0) # mul_add_c(a[5],b[0],c3,c1,c2); + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + sltu $at,$c_1,$t_2 + $ADDU $c_2,$at + mflo ($t_1,$a_5,$b_0) + mfhi ($t_2,$a_5,$b_0) + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $MULTU ($a_6,$b_0) # mul_add_c(a[6],b[0],c1,c2,c3); + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + sltu $at,$c_1,$t_2 + $ADDU $c_2,$at + $ST $c_3,5*$BNSZ($a0) # r[5]=c3; + + mflo ($t_1,$a_6,$b_0) + mfhi ($t_2,$a_6,$b_0) + $ADDU $c_1,$t_1 + sltu $at,$c_1,$t_1 + $MULTU ($a_5,$b_1) # mul_add_c(a[5],b[1],c1,c2,c3); + $ADDU $t_2,$at + $ADDU $c_2,$t_2 + sltu $c_3,$c_2,$t_2 + mflo ($t_1,$a_5,$b_1) + mfhi ($t_2,$a_5,$b_1) + $ADDU $c_1,$t_1 + sltu $at,$c_1,$t_1 + $MULTU ($a_4,$b_2) # mul_add_c(a[4],b[2],c1,c2,c3); + $ADDU $t_2,$at + $ADDU $c_2,$t_2 + sltu $at,$c_2,$t_2 + $ADDU $c_3,$at + mflo ($t_1,$a_4,$b_2) + mfhi ($t_2,$a_4,$b_2) + $ADDU $c_1,$t_1 + sltu $at,$c_1,$t_1 + $MULTU ($a_3,$b_3) # mul_add_c(a[3],b[3],c1,c2,c3); + $ADDU $t_2,$at + $ADDU $c_2,$t_2 + sltu $at,$c_2,$t_2 + $ADDU $c_3,$at + mflo ($t_1,$a_3,$b_3) + mfhi ($t_2,$a_3,$b_3) + $ADDU $c_1,$t_1 + sltu $at,$c_1,$t_1 + $MULTU ($a_2,$b_4) # mul_add_c(a[2],b[4],c1,c2,c3); + $ADDU $t_2,$at + $ADDU $c_2,$t_2 + sltu $at,$c_2,$t_2 + $ADDU $c_3,$at + mflo ($t_1,$a_2,$b_4) + mfhi ($t_2,$a_2,$b_4) + $ADDU $c_1,$t_1 + sltu $at,$c_1,$t_1 + $MULTU ($a_1,$b_5) # mul_add_c(a[1],b[5],c1,c2,c3); + $ADDU $t_2,$at + $ADDU $c_2,$t_2 + sltu $at,$c_2,$t_2 + $ADDU $c_3,$at + mflo ($t_1,$a_1,$b_5) + mfhi ($t_2,$a_1,$b_5) + $ADDU $c_1,$t_1 + sltu $at,$c_1,$t_1 + $MULTU ($a_0,$b_6) # mul_add_c(a[0],b[6],c1,c2,c3); + $ADDU $t_2,$at + $ADDU $c_2,$t_2 + sltu $at,$c_2,$t_2 + $ADDU $c_3,$at + mflo ($t_1,$a_0,$b_6) + mfhi ($t_2,$a_0,$b_6) + $ADDU $c_1,$t_1 + sltu $at,$c_1,$t_1 + $MULTU ($a_0,$b_7) # mul_add_c(a[0],b[7],c2,c3,c1); + $ADDU $t_2,$at + $ADDU $c_2,$t_2 + sltu $at,$c_2,$t_2 + $ADDU $c_3,$at + $ST $c_1,6*$BNSZ($a0) # r[6]=c1; + + mflo ($t_1,$a_0,$b_7) + mfhi ($t_2,$a_0,$b_7) + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_1,$b_6) # mul_add_c(a[1],b[6],c2,c3,c1); + $ADDU $t_2,$at + $ADDU $c_3,$t_2 + sltu $c_1,$c_3,$t_2 + mflo ($t_1,$a_1,$b_6) + mfhi ($t_2,$a_1,$b_6) + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_2,$b_5) # mul_add_c(a[2],b[5],c2,c3,c1); + $ADDU $t_2,$at + $ADDU $c_3,$t_2 + sltu $at,$c_3,$t_2 + $ADDU $c_1,$at + mflo ($t_1,$a_2,$b_5) + mfhi ($t_2,$a_2,$b_5) + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_3,$b_4) # mul_add_c(a[3],b[4],c2,c3,c1); + $ADDU $t_2,$at + $ADDU $c_3,$t_2 + sltu $at,$c_3,$t_2 + $ADDU $c_1,$at + mflo ($t_1,$a_3,$b_4) + mfhi ($t_2,$a_3,$b_4) + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_4,$b_3) # mul_add_c(a[4],b[3],c2,c3,c1); + $ADDU $t_2,$at + $ADDU $c_3,$t_2 + sltu $at,$c_3,$t_2 + $ADDU $c_1,$at + mflo ($t_1,$a_4,$b_3) + mfhi ($t_2,$a_4,$b_3) + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_5,$b_2) # mul_add_c(a[5],b[2],c2,c3,c1); + $ADDU $t_2,$at + $ADDU $c_3,$t_2 + sltu $at,$c_3,$t_2 + $ADDU $c_1,$at + mflo ($t_1,$a_5,$b_2) + mfhi ($t_2,$a_5,$b_2) + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_6,$b_1) # mul_add_c(a[6],b[1],c2,c3,c1); + $ADDU $t_2,$at + $ADDU $c_3,$t_2 + sltu $at,$c_3,$t_2 + $ADDU $c_1,$at + mflo ($t_1,$a_6,$b_1) + mfhi ($t_2,$a_6,$b_1) + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_7,$b_0) # mul_add_c(a[7],b[0],c2,c3,c1); + $ADDU $t_2,$at + $ADDU $c_3,$t_2 + sltu $at,$c_3,$t_2 + $ADDU $c_1,$at + mflo ($t_1,$a_7,$b_0) + mfhi ($t_2,$a_7,$b_0) + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_7,$b_1) # mul_add_c(a[7],b[1],c3,c1,c2); + $ADDU $t_2,$at + $ADDU $c_3,$t_2 + sltu $at,$c_3,$t_2 + $ADDU $c_1,$at + $ST $c_2,7*$BNSZ($a0) # r[7]=c2; + + mflo ($t_1,$a_7,$b_1) + mfhi ($t_2,$a_7,$b_1) + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $MULTU ($a_6,$b_2) # mul_add_c(a[6],b[2],c3,c1,c2); + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + sltu $c_2,$c_1,$t_2 + mflo ($t_1,$a_6,$b_2) + mfhi ($t_2,$a_6,$b_2) + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $MULTU ($a_5,$b_3) # mul_add_c(a[5],b[3],c3,c1,c2); + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + sltu $at,$c_1,$t_2 + $ADDU $c_2,$at + mflo ($t_1,$a_5,$b_3) + mfhi ($t_2,$a_5,$b_3) + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $MULTU ($a_4,$b_4) # mul_add_c(a[4],b[4],c3,c1,c2); + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + sltu $at,$c_1,$t_2 + $ADDU $c_2,$at + mflo ($t_1,$a_4,$b_4) + mfhi ($t_2,$a_4,$b_4) + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $MULTU ($a_3,$b_5) # mul_add_c(a[3],b[5],c3,c1,c2); + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + sltu $at,$c_1,$t_2 + $ADDU $c_2,$at + mflo ($t_1,$a_3,$b_5) + mfhi ($t_2,$a_3,$b_5) + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $MULTU ($a_2,$b_6) # mul_add_c(a[2],b[6],c3,c1,c2); + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + sltu $at,$c_1,$t_2 + $ADDU $c_2,$at + mflo ($t_1,$a_2,$b_6) + mfhi ($t_2,$a_2,$b_6) + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $MULTU ($a_1,$b_7) # mul_add_c(a[1],b[7],c3,c1,c2); + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + sltu $at,$c_1,$t_2 + $ADDU $c_2,$at + mflo ($t_1,$a_1,$b_7) + mfhi ($t_2,$a_1,$b_7) + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $MULTU ($a_2,$b_7) # mul_add_c(a[2],b[7],c1,c2,c3); + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + sltu $at,$c_1,$t_2 + $ADDU $c_2,$at + $ST $c_3,8*$BNSZ($a0) # r[8]=c3; + + mflo ($t_1,$a_2,$b_7) + mfhi ($t_2,$a_2,$b_7) + $ADDU $c_1,$t_1 + sltu $at,$c_1,$t_1 + $MULTU ($a_3,$b_6) # mul_add_c(a[3],b[6],c1,c2,c3); + $ADDU $t_2,$at + $ADDU $c_2,$t_2 + sltu $c_3,$c_2,$t_2 + mflo ($t_1,$a_3,$b_6) + mfhi ($t_2,$a_3,$b_6) + $ADDU $c_1,$t_1 + sltu $at,$c_1,$t_1 + $MULTU ($a_4,$b_5) # mul_add_c(a[4],b[5],c1,c2,c3); + $ADDU $t_2,$at + $ADDU $c_2,$t_2 + sltu $at,$c_2,$t_2 + $ADDU $c_3,$at + mflo ($t_1,$a_4,$b_5) + mfhi ($t_2,$a_4,$b_5) + $ADDU $c_1,$t_1 + sltu $at,$c_1,$t_1 + $MULTU ($a_5,$b_4) # mul_add_c(a[5],b[4],c1,c2,c3); + $ADDU $t_2,$at + $ADDU $c_2,$t_2 + sltu $at,$c_2,$t_2 + $ADDU $c_3,$at + mflo ($t_1,$a_5,$b_4) + mfhi ($t_2,$a_5,$b_4) + $ADDU $c_1,$t_1 + sltu $at,$c_1,$t_1 + $MULTU ($a_6,$b_3) # mul_add_c(a[6],b[3],c1,c2,c3); + $ADDU $t_2,$at + $ADDU $c_2,$t_2 + sltu $at,$c_2,$t_2 + $ADDU $c_3,$at + mflo ($t_1,$a_6,$b_3) + mfhi ($t_2,$a_6,$b_3) + $ADDU $c_1,$t_1 + sltu $at,$c_1,$t_1 + $MULTU ($a_7,$b_2) # mul_add_c(a[7],b[2],c1,c2,c3); + $ADDU $t_2,$at + $ADDU $c_2,$t_2 + sltu $at,$c_2,$t_2 + $ADDU $c_3,$at + mflo ($t_1,$a_7,$b_2) + mfhi ($t_2,$a_7,$b_2) + $ADDU $c_1,$t_1 + sltu $at,$c_1,$t_1 + $MULTU ($a_7,$b_3) # mul_add_c(a[7],b[3],c2,c3,c1); + $ADDU $t_2,$at + $ADDU $c_2,$t_2 + sltu $at,$c_2,$t_2 + $ADDU $c_3,$at + $ST $c_1,9*$BNSZ($a0) # r[9]=c1; + + mflo ($t_1,$a_7,$b_3) + mfhi ($t_2,$a_7,$b_3) + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_6,$b_4) # mul_add_c(a[6],b[4],c2,c3,c1); + $ADDU $t_2,$at + $ADDU $c_3,$t_2 + sltu $c_1,$c_3,$t_2 + mflo ($t_1,$a_6,$b_4) + mfhi ($t_2,$a_6,$b_4) + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_5,$b_5) # mul_add_c(a[5],b[5],c2,c3,c1); + $ADDU $t_2,$at + $ADDU $c_3,$t_2 + sltu $at,$c_3,$t_2 + $ADDU $c_1,$at + mflo ($t_1,$a_5,$b_5) + mfhi ($t_2,$a_5,$b_5) + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_4,$b_6) # mul_add_c(a[4],b[6],c2,c3,c1); + $ADDU $t_2,$at + $ADDU $c_3,$t_2 + sltu $at,$c_3,$t_2 + $ADDU $c_1,$at + mflo ($t_1,$a_4,$b_6) + mfhi ($t_2,$a_4,$b_6) + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_3,$b_7) # mul_add_c(a[3],b[7],c2,c3,c1); + $ADDU $t_2,$at + $ADDU $c_3,$t_2 + sltu $at,$c_3,$t_2 + $ADDU $c_1,$at + mflo ($t_1,$a_3,$b_7) + mfhi ($t_2,$a_3,$b_7) + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_4,$b_7) # mul_add_c(a[4],b[7],c3,c1,c2); + $ADDU $t_2,$at + $ADDU $c_3,$t_2 + sltu $at,$c_3,$t_2 + $ADDU $c_1,$at + $ST $c_2,10*$BNSZ($a0) # r[10]=c2; + + mflo ($t_1,$a_4,$b_7) + mfhi ($t_2,$a_4,$b_7) + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $MULTU ($a_5,$b_6) # mul_add_c(a[5],b[6],c3,c1,c2); + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + sltu $c_2,$c_1,$t_2 + mflo ($t_1,$a_5,$b_6) + mfhi ($t_2,$a_5,$b_6) + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $MULTU ($a_6,$b_5) # mul_add_c(a[6],b[5],c3,c1,c2); + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + sltu $at,$c_1,$t_2 + $ADDU $c_2,$at + mflo ($t_1,$a_6,$b_5) + mfhi ($t_2,$a_6,$b_5) + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $MULTU ($a_7,$b_4) # mul_add_c(a[7],b[4],c3,c1,c2); + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + sltu $at,$c_1,$t_2 + $ADDU $c_2,$at + mflo ($t_1,$a_7,$b_4) + mfhi ($t_2,$a_7,$b_4) + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $MULTU ($a_7,$b_5) # mul_add_c(a[7],b[5],c1,c2,c3); + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + sltu $at,$c_1,$t_2 + $ADDU $c_2,$at + $ST $c_3,11*$BNSZ($a0) # r[11]=c3; + + mflo ($t_1,$a_7,$b_5) + mfhi ($t_2,$a_7,$b_5) + $ADDU $c_1,$t_1 + sltu $at,$c_1,$t_1 + $MULTU ($a_6,$b_6) # mul_add_c(a[6],b[6],c1,c2,c3); + $ADDU $t_2,$at + $ADDU $c_2,$t_2 + sltu $c_3,$c_2,$t_2 + mflo ($t_1,$a_6,$b_6) + mfhi ($t_2,$a_6,$b_6) + $ADDU $c_1,$t_1 + sltu $at,$c_1,$t_1 + $MULTU ($a_5,$b_7) # mul_add_c(a[5],b[7],c1,c2,c3); + $ADDU $t_2,$at + $ADDU $c_2,$t_2 + sltu $at,$c_2,$t_2 + $ADDU $c_3,$at + mflo ($t_1,$a_5,$b_7) + mfhi ($t_2,$a_5,$b_7) + $ADDU $c_1,$t_1 + sltu $at,$c_1,$t_1 + $MULTU ($a_6,$b_7) # mul_add_c(a[6],b[7],c2,c3,c1); + $ADDU $t_2,$at + $ADDU $c_2,$t_2 + sltu $at,$c_2,$t_2 + $ADDU $c_3,$at + $ST $c_1,12*$BNSZ($a0) # r[12]=c1; + + mflo ($t_1,$a_6,$b_7) + mfhi ($t_2,$a_6,$b_7) + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_7,$b_6) # mul_add_c(a[7],b[6],c2,c3,c1); + $ADDU $t_2,$at + $ADDU $c_3,$t_2 + sltu $c_1,$c_3,$t_2 + mflo ($t_1,$a_7,$b_6) + mfhi ($t_2,$a_7,$b_6) + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_7,$b_7) # mul_add_c(a[7],b[7],c3,c1,c2); + $ADDU $t_2,$at + $ADDU $c_3,$t_2 + sltu $at,$c_3,$t_2 + $ADDU $c_1,$at + $ST $c_2,13*$BNSZ($a0) # r[13]=c2; + + mflo ($t_1,$a_7,$b_7) + mfhi ($t_2,$a_7,$b_7) + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + $ST $c_3,14*$BNSZ($a0) # r[14]=c3; + $ST $c_1,15*$BNSZ($a0) # r[15]=c1; + + .set noreorder +___ +$code.=<<___ if ($flavour =~ /nubi/i); + $REG_L $s5,10*$SZREG($sp) + $REG_L $s4,9*$SZREG($sp) + $REG_L $s3,8*$SZREG($sp) + $REG_L $s2,7*$SZREG($sp) + $REG_L $s1,6*$SZREG($sp) + $REG_L $s0,5*$SZREG($sp) + $REG_L $t3,4*$SZREG($sp) + $REG_L $t2,3*$SZREG($sp) + $REG_L $t1,2*$SZREG($sp) + $REG_L $t0,1*$SZREG($sp) + $REG_L $gp,0*$SZREG($sp) + jr $ra + $PTR_ADD $sp,12*$SZREG +___ +$code.=<<___ if ($flavour !~ /nubi/i); + $REG_L $s5,5*$SZREG($sp) + $REG_L $s4,4*$SZREG($sp) + $REG_L $s3,3*$SZREG($sp) + $REG_L $s2,2*$SZREG($sp) + $REG_L $s1,1*$SZREG($sp) + $REG_L $s0,0*$SZREG($sp) + jr $ra + $PTR_ADD $sp,6*$SZREG +___ +$code.=<<___; +.end bn_mul_comba8 + +.align 5 +.globl bn_mul_comba4 +.ent bn_mul_comba4 +bn_mul_comba4: +___ +$code.=<<___ if ($flavour =~ /nubi/i); + .frame $sp,6*$SZREG,$ra + .mask 0x8000f008,-$SZREG + .set noreorder + $PTR_SUB $sp,6*$SZREG + $REG_S $ra,5*$SZREG($sp) + $REG_S $t3,4*$SZREG($sp) + $REG_S $t2,3*$SZREG($sp) + $REG_S $t1,2*$SZREG($sp) + $REG_S $t0,1*$SZREG($sp) + $REG_S $gp,0*$SZREG($sp) +___ +$code.=<<___; + .set reorder + $LD $a_0,0($a1) + $LD $b_0,0($a2) + $LD $a_1,$BNSZ($a1) + $LD $a_2,2*$BNSZ($a1) + $MULTU ($a_0,$b_0) # mul_add_c(a[0],b[0],c1,c2,c3); + $LD $a_3,3*$BNSZ($a1) + $LD $b_1,$BNSZ($a2) + $LD $b_2,2*$BNSZ($a2) + $LD $b_3,3*$BNSZ($a2) + mflo ($c_1,$a_0,$b_0) + mfhi ($c_2,$a_0,$b_0) + $ST $c_1,0($a0) + + $MULTU ($a_0,$b_1) # mul_add_c(a[0],b[1],c2,c3,c1); + mflo ($t_1,$a_0,$b_1) + mfhi ($t_2,$a_0,$b_1) + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_1,$b_0) # mul_add_c(a[1],b[0],c2,c3,c1); + $ADDU $c_3,$t_2,$at + mflo ($t_1,$a_1,$b_0) + mfhi ($t_2,$a_1,$b_0) + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_2,$b_0) # mul_add_c(a[2],b[0],c3,c1,c2); + $ADDU $t_2,$at + $ADDU $c_3,$t_2 + sltu $c_1,$c_3,$t_2 + $ST $c_2,$BNSZ($a0) + + mflo ($t_1,$a_2,$b_0) + mfhi ($t_2,$a_2,$b_0) + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $MULTU ($a_1,$b_1) # mul_add_c(a[1],b[1],c3,c1,c2); + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + mflo ($t_1,$a_1,$b_1) + mfhi ($t_2,$a_1,$b_1) + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $MULTU ($a_0,$b_2) # mul_add_c(a[0],b[2],c3,c1,c2); + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + sltu $c_2,$c_1,$t_2 + mflo ($t_1,$a_0,$b_2) + mfhi ($t_2,$a_0,$b_2) + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $MULTU ($a_0,$b_3) # mul_add_c(a[0],b[3],c1,c2,c3); + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + sltu $at,$c_1,$t_2 + $ADDU $c_2,$at + $ST $c_3,2*$BNSZ($a0) + + mflo ($t_1,$a_0,$b_3) + mfhi ($t_2,$a_0,$b_3) + $ADDU $c_1,$t_1 + sltu $at,$c_1,$t_1 + $MULTU ($a_1,$b_2) # mul_add_c(a[1],b[2],c1,c2,c3); + $ADDU $t_2,$at + $ADDU $c_2,$t_2 + sltu $c_3,$c_2,$t_2 + mflo ($t_1,$a_1,$b_2) + mfhi ($t_2,$a_1,$b_2) + $ADDU $c_1,$t_1 + sltu $at,$c_1,$t_1 + $MULTU ($a_2,$b_1) # mul_add_c(a[2],b[1],c1,c2,c3); + $ADDU $t_2,$at + $ADDU $c_2,$t_2 + sltu $at,$c_2,$t_2 + $ADDU $c_3,$at + mflo ($t_1,$a_2,$b_1) + mfhi ($t_2,$a_2,$b_1) + $ADDU $c_1,$t_1 + sltu $at,$c_1,$t_1 + $MULTU ($a_3,$b_0) # mul_add_c(a[3],b[0],c1,c2,c3); + $ADDU $t_2,$at + $ADDU $c_2,$t_2 + sltu $at,$c_2,$t_2 + $ADDU $c_3,$at + mflo ($t_1,$a_3,$b_0) + mfhi ($t_2,$a_3,$b_0) + $ADDU $c_1,$t_1 + sltu $at,$c_1,$t_1 + $MULTU ($a_3,$b_1) # mul_add_c(a[3],b[1],c2,c3,c1); + $ADDU $t_2,$at + $ADDU $c_2,$t_2 + sltu $at,$c_2,$t_2 + $ADDU $c_3,$at + $ST $c_1,3*$BNSZ($a0) + + mflo ($t_1,$a_3,$b_1) + mfhi ($t_2,$a_3,$b_1) + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_2,$b_2) # mul_add_c(a[2],b[2],c2,c3,c1); + $ADDU $t_2,$at + $ADDU $c_3,$t_2 + sltu $c_1,$c_3,$t_2 + mflo ($t_1,$a_2,$b_2) + mfhi ($t_2,$a_2,$b_2) + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_1,$b_3) # mul_add_c(a[1],b[3],c2,c3,c1); + $ADDU $t_2,$at + $ADDU $c_3,$t_2 + sltu $at,$c_3,$t_2 + $ADDU $c_1,$at + mflo ($t_1,$a_1,$b_3) + mfhi ($t_2,$a_1,$b_3) + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_2,$b_3) # mul_add_c(a[2],b[3],c3,c1,c2); + $ADDU $t_2,$at + $ADDU $c_3,$t_2 + sltu $at,$c_3,$t_2 + $ADDU $c_1,$at + $ST $c_2,4*$BNSZ($a0) + + mflo ($t_1,$a_2,$b_3) + mfhi ($t_2,$a_2,$b_3) + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $MULTU ($a_3,$b_2) # mul_add_c(a[3],b[2],c3,c1,c2); + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + sltu $c_2,$c_1,$t_2 + mflo ($t_1,$a_3,$b_2) + mfhi ($t_2,$a_3,$b_2) + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $MULTU ($a_3,$b_3) # mul_add_c(a[3],b[3],c1,c2,c3); + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + sltu $at,$c_1,$t_2 + $ADDU $c_2,$at + $ST $c_3,5*$BNSZ($a0) + + mflo ($t_1,$a_3,$b_3) + mfhi ($t_2,$a_3,$b_3) + $ADDU $c_1,$t_1 + sltu $at,$c_1,$t_1 + $ADDU $t_2,$at + $ADDU $c_2,$t_2 + $ST $c_1,6*$BNSZ($a0) + $ST $c_2,7*$BNSZ($a0) + + .set noreorder +___ +$code.=<<___ if ($flavour =~ /nubi/i); + $REG_L $t3,4*$SZREG($sp) + $REG_L $t2,3*$SZREG($sp) + $REG_L $t1,2*$SZREG($sp) + $REG_L $t0,1*$SZREG($sp) + $REG_L $gp,0*$SZREG($sp) + $PTR_ADD $sp,6*$SZREG +___ +$code.=<<___; + jr $ra + nop +.end bn_mul_comba4 +___ + +($a_4,$a_5,$a_6,$a_7)=($b_0,$b_1,$b_2,$b_3); + +sub add_c2 () { +my ($hi,$lo,$c0,$c1,$c2, + $warm, # !$warm denotes first call with specific sequence of + # $c_[XYZ] when there is no Z-carry to accumulate yet; + $an,$bn # these two are arguments for multiplication which + # result is used in *next* step [which is why it's + # commented as "forward multiplication" below]; + )=@_; +$code.=<<___; + $ADDU $c0,$lo + sltu $at,$c0,$lo + $MULTU ($an,$bn) # forward multiplication + $ADDU $c0,$lo + $ADDU $at,$hi + sltu $lo,$c0,$lo + $ADDU $c1,$at + $ADDU $hi,$lo +___ +$code.=<<___ if (!$warm); + sltu $c2,$c1,$at + $ADDU $c1,$hi +___ +$code.=<<___ if ($warm); + sltu $at,$c1,$at + $ADDU $c1,$hi + $ADDU $c2,$at +___ +$code.=<<___; + sltu $hi,$c1,$hi + $ADDU $c2,$hi + mflo ($lo,$an,$bn) + mfhi ($hi,$an,$bn) +___ +} + +$code.=<<___; + +.align 5 +.globl bn_sqr_comba8 +.ent bn_sqr_comba8 +bn_sqr_comba8: +___ +$code.=<<___ if ($flavour =~ /nubi/i); + .frame $sp,6*$SZREG,$ra + .mask 0x8000f008,-$SZREG + .set noreorder + $PTR_SUB $sp,6*$SZREG + $REG_S $ra,5*$SZREG($sp) + $REG_S $t3,4*$SZREG($sp) + $REG_S $t2,3*$SZREG($sp) + $REG_S $t1,2*$SZREG($sp) + $REG_S $t0,1*$SZREG($sp) + $REG_S $gp,0*$SZREG($sp) +___ +$code.=<<___; + .set reorder + $LD $a_0,0($a1) + $LD $a_1,$BNSZ($a1) + $LD $a_2,2*$BNSZ($a1) + $LD $a_3,3*$BNSZ($a1) + + $MULTU ($a_0,$a_0) # mul_add_c(a[0],b[0],c1,c2,c3); + $LD $a_4,4*$BNSZ($a1) + $LD $a_5,5*$BNSZ($a1) + $LD $a_6,6*$BNSZ($a1) + $LD $a_7,7*$BNSZ($a1) + mflo ($c_1,$a_0,$a_0) + mfhi ($c_2,$a_0,$a_0) + $ST $c_1,0($a0) + + $MULTU ($a_0,$a_1) # mul_add_c2(a[0],b[1],c2,c3,c1); + mflo ($t_1,$a_0,$a_1) + mfhi ($t_2,$a_0,$a_1) + slt $c_1,$t_2,$zero + $SLL $t_2,1 + $MULTU ($a_2,$a_0) # mul_add_c2(a[2],b[0],c3,c1,c2); + slt $a2,$t_1,$zero + $ADDU $t_2,$a2 + $SLL $t_1,1 + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $ADDU $c_3,$t_2,$at + $ST $c_2,$BNSZ($a0) + mflo ($t_1,$a_2,$a_0) + mfhi ($t_2,$a_2,$a_0) +___ + &add_c2($t_2,$t_1,$c_3,$c_1,$c_2,0, + $a_1,$a_1); # mul_add_c(a[1],b[1],c3,c1,c2); +$code.=<<___; + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $MULTU ($a_0,$a_3) # mul_add_c2(a[0],b[3],c1,c2,c3); + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + sltu $at,$c_1,$t_2 + $ADDU $c_2,$at + $ST $c_3,2*$BNSZ($a0) + mflo ($t_1,$a_0,$a_3) + mfhi ($t_2,$a_0,$a_3) +___ + &add_c2($t_2,$t_1,$c_1,$c_2,$c_3,0, + $a_1,$a_2); # mul_add_c2(a[1],b[2],c1,c2,c3); + &add_c2($t_2,$t_1,$c_1,$c_2,$c_3,1, + $a_4,$a_0); # mul_add_c2(a[4],b[0],c2,c3,c1); +$code.=<<___; + $ST $c_1,3*$BNSZ($a0) +___ + &add_c2($t_2,$t_1,$c_2,$c_3,$c_1,0, + $a_3,$a_1); # mul_add_c2(a[3],b[1],c2,c3,c1); + &add_c2($t_2,$t_1,$c_2,$c_3,$c_1,1, + $a_2,$a_2); # mul_add_c(a[2],b[2],c2,c3,c1); +$code.=<<___; + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_0,$a_5) # mul_add_c2(a[0],b[5],c3,c1,c2); + $ADDU $t_2,$at + $ADDU $c_3,$t_2 + sltu $at,$c_3,$t_2 + $ADDU $c_1,$at + $ST $c_2,4*$BNSZ($a0) + mflo ($t_1,$a_0,$a_5) + mfhi ($t_2,$a_0,$a_5) +___ + &add_c2($t_2,$t_1,$c_3,$c_1,$c_2,0, + $a_1,$a_4); # mul_add_c2(a[1],b[4],c3,c1,c2); + &add_c2($t_2,$t_1,$c_3,$c_1,$c_2,1, + $a_2,$a_3); # mul_add_c2(a[2],b[3],c3,c1,c2); + &add_c2($t_2,$t_1,$c_3,$c_1,$c_2,1, + $a_6,$a_0); # mul_add_c2(a[6],b[0],c1,c2,c3); +$code.=<<___; + $ST $c_3,5*$BNSZ($a0) +___ + &add_c2($t_2,$t_1,$c_1,$c_2,$c_3,0, + $a_5,$a_1); # mul_add_c2(a[5],b[1],c1,c2,c3); + &add_c2($t_2,$t_1,$c_1,$c_2,$c_3,1, + $a_4,$a_2); # mul_add_c2(a[4],b[2],c1,c2,c3); + &add_c2($t_2,$t_1,$c_1,$c_2,$c_3,1, + $a_3,$a_3); # mul_add_c(a[3],b[3],c1,c2,c3); +$code.=<<___; + $ADDU $c_1,$t_1 + sltu $at,$c_1,$t_1 + $MULTU ($a_0,$a_7) # mul_add_c2(a[0],b[7],c2,c3,c1); + $ADDU $t_2,$at + $ADDU $c_2,$t_2 + sltu $at,$c_2,$t_2 + $ADDU $c_3,$at + $ST $c_1,6*$BNSZ($a0) + mflo ($t_1,$a_0,$a_7) + mfhi ($t_2,$a_0,$a_7) +___ + &add_c2($t_2,$t_1,$c_2,$c_3,$c_1,0, + $a_1,$a_6); # mul_add_c2(a[1],b[6],c2,c3,c1); + &add_c2($t_2,$t_1,$c_2,$c_3,$c_1,1, + $a_2,$a_5); # mul_add_c2(a[2],b[5],c2,c3,c1); + &add_c2($t_2,$t_1,$c_2,$c_3,$c_1,1, + $a_3,$a_4); # mul_add_c2(a[3],b[4],c2,c3,c1); + &add_c2($t_2,$t_1,$c_2,$c_3,$c_1,1, + $a_7,$a_1); # mul_add_c2(a[7],b[1],c3,c1,c2); +$code.=<<___; + $ST $c_2,7*$BNSZ($a0) +___ + &add_c2($t_2,$t_1,$c_3,$c_1,$c_2,0, + $a_6,$a_2); # mul_add_c2(a[6],b[2],c3,c1,c2); + &add_c2($t_2,$t_1,$c_3,$c_1,$c_2,1, + $a_5,$a_3); # mul_add_c2(a[5],b[3],c3,c1,c2); + &add_c2($t_2,$t_1,$c_3,$c_1,$c_2,1, + $a_4,$a_4); # mul_add_c(a[4],b[4],c3,c1,c2); +$code.=<<___; + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $MULTU ($a_2,$a_7) # mul_add_c2(a[2],b[7],c1,c2,c3); + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + sltu $at,$c_1,$t_2 + $ADDU $c_2,$at + $ST $c_3,8*$BNSZ($a0) + mflo ($t_1,$a_2,$a_7) + mfhi ($t_2,$a_2,$a_7) +___ + &add_c2($t_2,$t_1,$c_1,$c_2,$c_3,0, + $a_3,$a_6); # mul_add_c2(a[3],b[6],c1,c2,c3); + &add_c2($t_2,$t_1,$c_1,$c_2,$c_3,1, + $a_4,$a_5); # mul_add_c2(a[4],b[5],c1,c2,c3); + &add_c2($t_2,$t_1,$c_1,$c_2,$c_3,1, + $a_7,$a_3); # mul_add_c2(a[7],b[3],c2,c3,c1); +$code.=<<___; + $ST $c_1,9*$BNSZ($a0) +___ + &add_c2($t_2,$t_1,$c_2,$c_3,$c_1,0, + $a_6,$a_4); # mul_add_c2(a[6],b[4],c2,c3,c1); + &add_c2($t_2,$t_1,$c_2,$c_3,$c_1,1, + $a_5,$a_5); # mul_add_c(a[5],b[5],c2,c3,c1); +$code.=<<___; + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_4,$a_7) # mul_add_c2(a[4],b[7],c3,c1,c2); + $ADDU $t_2,$at + $ADDU $c_3,$t_2 + sltu $at,$c_3,$t_2 + $ADDU $c_1,$at + $ST $c_2,10*$BNSZ($a0) + mflo ($t_1,$a_4,$a_7) + mfhi ($t_2,$a_4,$a_7) +___ + &add_c2($t_2,$t_1,$c_3,$c_1,$c_2,0, + $a_5,$a_6); # mul_add_c2(a[5],b[6],c3,c1,c2); + &add_c2($t_2,$t_1,$c_3,$c_1,$c_2,1, + $a_7,$a_5); # mul_add_c2(a[7],b[5],c1,c2,c3); +$code.=<<___; + $ST $c_3,11*$BNSZ($a0) +___ + &add_c2($t_2,$t_1,$c_1,$c_2,$c_3,0, + $a_6,$a_6); # mul_add_c(a[6],b[6],c1,c2,c3); +$code.=<<___; + $ADDU $c_1,$t_1 + sltu $at,$c_1,$t_1 + $MULTU ($a_6,$a_7) # mul_add_c2(a[6],b[7],c2,c3,c1); + $ADDU $t_2,$at + $ADDU $c_2,$t_2 + sltu $at,$c_2,$t_2 + $ADDU $c_3,$at + $ST $c_1,12*$BNSZ($a0) + mflo ($t_1,$a_6,$a_7) + mfhi ($t_2,$a_6,$a_7) +___ + &add_c2($t_2,$t_1,$c_2,$c_3,$c_1,0, + $a_7,$a_7); # mul_add_c(a[7],b[7],c3,c1,c2); +$code.=<<___; + $ST $c_2,13*$BNSZ($a0) + + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + $ST $c_3,14*$BNSZ($a0) + $ST $c_1,15*$BNSZ($a0) + + .set noreorder +___ +$code.=<<___ if ($flavour =~ /nubi/i); + $REG_L $t3,4*$SZREG($sp) + $REG_L $t2,3*$SZREG($sp) + $REG_L $t1,2*$SZREG($sp) + $REG_L $t0,1*$SZREG($sp) + $REG_L $gp,0*$SZREG($sp) + $PTR_ADD $sp,6*$SZREG +___ +$code.=<<___; + jr $ra + nop +.end bn_sqr_comba8 + +.align 5 +.globl bn_sqr_comba4 +.ent bn_sqr_comba4 +bn_sqr_comba4: +___ +$code.=<<___ if ($flavour =~ /nubi/i); + .frame $sp,6*$SZREG,$ra + .mask 0x8000f008,-$SZREG + .set noreorder + $PTR_SUB $sp,6*$SZREG + $REG_S $ra,5*$SZREG($sp) + $REG_S $t3,4*$SZREG($sp) + $REG_S $t2,3*$SZREG($sp) + $REG_S $t1,2*$SZREG($sp) + $REG_S $t0,1*$SZREG($sp) + $REG_S $gp,0*$SZREG($sp) +___ +$code.=<<___; + .set reorder + $LD $a_0,0($a1) + $LD $a_1,$BNSZ($a1) + $MULTU ($a_0,$a_0) # mul_add_c(a[0],b[0],c1,c2,c3); + $LD $a_2,2*$BNSZ($a1) + $LD $a_3,3*$BNSZ($a1) + mflo ($c_1,$a_0,$a_0) + mfhi ($c_2,$a_0,$a_0) + $ST $c_1,0($a0) + + $MULTU ($a_0,$a_1) # mul_add_c2(a[0],b[1],c2,c3,c1); + mflo ($t_1,$a_0,$a_1) + mfhi ($t_2,$a_0,$a_1) + slt $c_1,$t_2,$zero + $SLL $t_2,1 + $MULTU ($a_2,$a_0) # mul_add_c2(a[2],b[0],c3,c1,c2); + slt $a2,$t_1,$zero + $ADDU $t_2,$a2 + $SLL $t_1,1 + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $ADDU $c_3,$t_2,$at + $ST $c_2,$BNSZ($a0) + mflo ($t_1,$a_2,$a_0) + mfhi ($t_2,$a_2,$a_0) +___ + &add_c2($t_2,$t_1,$c_3,$c_1,$c_2,0, + $a_1,$a_1); # mul_add_c(a[1],b[1],c3,c1,c2); +$code.=<<___; + $ADDU $c_3,$t_1 + sltu $at,$c_3,$t_1 + $MULTU ($a_0,$a_3) # mul_add_c2(a[0],b[3],c1,c2,c3); + $ADDU $t_2,$at + $ADDU $c_1,$t_2 + sltu $at,$c_1,$t_2 + $ADDU $c_2,$at + $ST $c_3,2*$BNSZ($a0) + mflo ($t_1,$a_0,$a_3) + mfhi ($t_2,$a_0,$a_3) +___ + &add_c2($t_2,$t_1,$c_1,$c_2,$c_3,0, + $a_1,$a_2); # mul_add_c2(a2[1],b[2],c1,c2,c3); + &add_c2($t_2,$t_1,$c_1,$c_2,$c_3,1, + $a_3,$a_1); # mul_add_c2(a[3],b[1],c2,c3,c1); +$code.=<<___; + $ST $c_1,3*$BNSZ($a0) +___ + &add_c2($t_2,$t_1,$c_2,$c_3,$c_1,0, + $a_2,$a_2); # mul_add_c(a[2],b[2],c2,c3,c1); +$code.=<<___; + $ADDU $c_2,$t_1 + sltu $at,$c_2,$t_1 + $MULTU ($a_2,$a_3) # mul_add_c2(a[2],b[3],c3,c1,c2); + $ADDU $t_2,$at + $ADDU $c_3,$t_2 + sltu $at,$c_3,$t_2 + $ADDU $c_1,$at + $ST $c_2,4*$BNSZ($a0) + mflo ($t_1,$a_2,$a_3) + mfhi ($t_2,$a_2,$a_3) +___ + &add_c2($t_2,$t_1,$c_3,$c_1,$c_2,0, + $a_3,$a_3); # mul_add_c(a[3],b[3],c1,c2,c3); +$code.=<<___; + $ST $c_3,5*$BNSZ($a0) + + $ADDU $c_1,$t_1 + sltu $at,$c_1,$t_1 + $ADDU $t_2,$at + $ADDU $c_2,$t_2 + $ST $c_1,6*$BNSZ($a0) + $ST $c_2,7*$BNSZ($a0) + + .set noreorder +___ +$code.=<<___ if ($flavour =~ /nubi/i); + $REG_L $t3,4*$SZREG($sp) + $REG_L $t2,3*$SZREG($sp) + $REG_L $t1,2*$SZREG($sp) + $REG_L $t0,1*$SZREG($sp) + $REG_L $gp,0*$SZREG($sp) + $PTR_ADD $sp,6*$SZREG +___ +$code.=<<___; + jr $ra + nop +.end bn_sqr_comba4 +___ +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/parisc-mont.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/parisc-mont.pl new file mode 100644 index 000000000..aa9f626ed --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/parisc-mont.pl @@ -0,0 +1,1006 @@ +#! /usr/bin/env perl +# Copyright 2009-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# On PA-7100LC this module performs ~90-50% better, less for longer +# keys, than code generated by gcc 3.2 for PA-RISC 1.1. Latter means +# that compiler utilized xmpyu instruction to perform 32x32=64-bit +# multiplication, which in turn means that "baseline" performance was +# optimal in respect to instruction set capabilities. Fair comparison +# with vendor compiler is problematic, because OpenSSL doesn't define +# BN_LLONG [presumably] for historical reasons, which drives compiler +# toward 4 times 16x16=32-bit multiplications [plus complementary +# shifts and additions] instead. This means that you should observe +# several times improvement over code generated by vendor compiler +# for PA-RISC 1.1, but the "baseline" is far from optimal. The actual +# improvement coefficient was never collected on PA-7100LC, or any +# other 1.1 CPU, because I don't have access to such machine with +# vendor compiler. But to give you a taste, PA-RISC 1.1 code path +# reportedly outperformed code generated by cc +DA1.1 +O3 by factor +# of ~5x on PA-8600. +# +# On PA-RISC 2.0 it has to compete with pa-risc2[W].s, which is +# reportedly ~2x faster than vendor compiler generated code [according +# to comment in pa-risc2[W].s]. Here comes a catch. Execution core of +# this implementation is actually 32-bit one, in the sense that it +# operates on 32-bit values. But pa-risc2[W].s operates on arrays of +# 64-bit BN_LONGs... How do they interoperate then? No problem. This +# module picks halves of 64-bit values in reverse order and pretends +# they were 32-bit BN_LONGs. But can 32-bit core compete with "pure" +# 64-bit code such as pa-risc2[W].s then? Well, the thing is that +# 32x32=64-bit multiplication is the best even PA-RISC 2.0 can do, +# i.e. there is no "wider" multiplication like on most other 64-bit +# platforms. This means that even being effectively 32-bit, this +# implementation performs "64-bit" computational task in same amount +# of arithmetic operations, most notably multiplications. It requires +# more memory references, most notably to tp[num], but this doesn't +# seem to exhaust memory port capacity. And indeed, dedicated PA-RISC +# 2.0 code path provides virtually same performance as pa-risc2[W].s: +# it's ~10% better for shortest key length and ~10% worse for longest +# one. +# +# In case it wasn't clear. The module has two distinct code paths: +# PA-RISC 1.1 and PA-RISC 2.0 ones. Latter features carry-free 64-bit +# additions and 64-bit integer loads, not to mention specific +# instruction scheduling. In 64-bit build naturally only 2.0 code path +# is assembled. In 32-bit application context both code paths are +# assembled, PA-RISC 2.0 CPU is detected at run-time and proper path +# is taken automatically. Also, in 32-bit build the module imposes +# couple of limitations: vector lengths has to be even and vector +# addresses has to be 64-bit aligned. Normally neither is a problem: +# most common key lengths are even and vectors are commonly malloc-ed, +# which ensures alignment. +# +# Special thanks to polarhome.com for providing HP-UX account on +# PA-RISC 1.1 machine, and to correspondent who chose to remain +# anonymous for testing the code on PA-RISC 2.0 machine. + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + +$flavour = shift; +$output = shift; + +open STDOUT,">$output"; + +if ($flavour =~ /64/) { + $LEVEL ="2.0W"; + $SIZE_T =8; + $FRAME_MARKER =80; + $SAVED_RP =16; + $PUSH ="std"; + $PUSHMA ="std,ma"; + $POP ="ldd"; + $POPMB ="ldd,mb"; + $BN_SZ =$SIZE_T; +} else { + $LEVEL ="1.1"; #$LEVEL.="\n\t.ALLOW\t2.0"; + $SIZE_T =4; + $FRAME_MARKER =48; + $SAVED_RP =20; + $PUSH ="stw"; + $PUSHMA ="stwm"; + $POP ="ldw"; + $POPMB ="ldwm"; + $BN_SZ =$SIZE_T; + if (open CONF,"<${dir}../../opensslconf.h") { + while() { + if (m/#\s*define\s+SIXTY_FOUR_BIT/) { + $BN_SZ=8; + $LEVEL="2.0"; + last; + } + } + close CONF; + } +} + +$FRAME=8*$SIZE_T+$FRAME_MARKER; # 8 saved regs + frame marker + # [+ argument transfer] +$LOCALS=$FRAME-$FRAME_MARKER; +$FRAME+=32; # local variables + +$tp="%r31"; +$ti1="%r29"; +$ti0="%r28"; + +$rp="%r26"; +$ap="%r25"; +$bp="%r24"; +$np="%r23"; +$n0="%r22"; # passed through stack in 32-bit +$num="%r21"; # passed through stack in 32-bit +$idx="%r20"; +$arrsz="%r19"; + +$nm1="%r7"; +$nm0="%r6"; +$ab1="%r5"; +$ab0="%r4"; + +$fp="%r3"; +$hi1="%r2"; +$hi0="%r1"; + +$xfer=$n0; # accommodates [-16..15] offset in fld[dw]s + +$fm0="%fr4"; $fti=$fm0; +$fbi="%fr5L"; +$fn0="%fr5R"; +$fai="%fr6"; $fab0="%fr7"; $fab1="%fr8"; +$fni="%fr9"; $fnm0="%fr10"; $fnm1="%fr11"; + +$code=<<___; + .LEVEL $LEVEL + .SPACE \$TEXT\$ + .SUBSPA \$CODE\$,QUAD=0,ALIGN=8,ACCESS=0x2C,CODE_ONLY + + .EXPORT bn_mul_mont,ENTRY,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR + .ALIGN 64 +bn_mul_mont + .PROC + .CALLINFO FRAME=`$FRAME-8*$SIZE_T`,NO_CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=6 + .ENTRY + $PUSH %r2,-$SAVED_RP(%sp) ; standard prologue + $PUSHMA %r3,$FRAME(%sp) + $PUSH %r4,`-$FRAME+1*$SIZE_T`(%sp) + $PUSH %r5,`-$FRAME+2*$SIZE_T`(%sp) + $PUSH %r6,`-$FRAME+3*$SIZE_T`(%sp) + $PUSH %r7,`-$FRAME+4*$SIZE_T`(%sp) + $PUSH %r8,`-$FRAME+5*$SIZE_T`(%sp) + $PUSH %r9,`-$FRAME+6*$SIZE_T`(%sp) + $PUSH %r10,`-$FRAME+7*$SIZE_T`(%sp) + ldo -$FRAME(%sp),$fp +___ +$code.=<<___ if ($SIZE_T==4); + ldw `-$FRAME_MARKER-4`($fp),$n0 + ldw `-$FRAME_MARKER-8`($fp),$num + nop + nop ; alignment +___ +$code.=<<___ if ($BN_SZ==4); + comiclr,<= 6,$num,%r0 ; are vectors long enough? + b L\$abort + ldi 0,%r28 ; signal "unhandled" + add,ev %r0,$num,$num ; is $num even? + b L\$abort + nop + or $ap,$np,$ti1 + extru,= $ti1,31,3,%r0 ; are ap and np 64-bit aligned? + b L\$abort + nop + nop ; alignment + nop + + fldws 0($n0),${fn0} + fldws,ma 4($bp),${fbi} ; bp[0] +___ +$code.=<<___ if ($BN_SZ==8); + comib,> 3,$num,L\$abort ; are vectors long enough? + ldi 0,%r28 ; signal "unhandled" + addl $num,$num,$num ; I operate on 32-bit values + + fldws 4($n0),${fn0} ; only low part of n0 + fldws 4($bp),${fbi} ; bp[0] in flipped word order +___ +$code.=<<___; + fldds 0($ap),${fai} ; ap[0,1] + fldds 0($np),${fni} ; np[0,1] + + sh2addl $num,%r0,$arrsz + ldi 31,$hi0 + ldo 36($arrsz),$hi1 ; space for tp[num+1] + andcm $hi1,$hi0,$hi1 ; align + addl $hi1,%sp,%sp + $PUSH $fp,-$SIZE_T(%sp) + + ldo `$LOCALS+16`($fp),$xfer + ldo `$LOCALS+32+4`($fp),$tp + + xmpyu ${fai}L,${fbi},${fab0} ; ap[0]*bp[0] + xmpyu ${fai}R,${fbi},${fab1} ; ap[1]*bp[0] + xmpyu ${fn0},${fab0}R,${fm0} + + addl $arrsz,$ap,$ap ; point at the end + addl $arrsz,$np,$np + subi 0,$arrsz,$idx ; j=0 + ldo 8($idx),$idx ; j++++ + + xmpyu ${fni}L,${fm0}R,${fnm0} ; np[0]*m + xmpyu ${fni}R,${fm0}R,${fnm1} ; np[1]*m + fstds ${fab0},-16($xfer) + fstds ${fnm0},-8($xfer) + fstds ${fab1},0($xfer) + fstds ${fnm1},8($xfer) + flddx $idx($ap),${fai} ; ap[2,3] + flddx $idx($np),${fni} ; np[2,3] +___ +$code.=<<___ if ($BN_SZ==4); + mtctl $hi0,%cr11 ; $hi0 still holds 31 + extrd,u,*= $hi0,%sar,1,$hi0 ; executes on PA-RISC 1.0 + b L\$parisc11 + nop +___ +$code.=<<___; # PA-RISC 2.0 code-path + xmpyu ${fai}L,${fbi},${fab0} ; ap[j]*bp[0] + xmpyu ${fni}L,${fm0}R,${fnm0} ; np[j]*m + ldd -16($xfer),$ab0 + fstds ${fab0},-16($xfer) + + extrd,u $ab0,31,32,$hi0 + extrd,u $ab0,63,32,$ab0 + ldd -8($xfer),$nm0 + fstds ${fnm0},-8($xfer) + ldo 8($idx),$idx ; j++++ + addl $ab0,$nm0,$nm0 ; low part is discarded + extrd,u $nm0,31,32,$hi1 + +L\$1st + xmpyu ${fai}R,${fbi},${fab1} ; ap[j+1]*bp[0] + xmpyu ${fni}R,${fm0}R,${fnm1} ; np[j+1]*m + ldd 0($xfer),$ab1 + fstds ${fab1},0($xfer) + addl $hi0,$ab1,$ab1 + extrd,u $ab1,31,32,$hi0 + ldd 8($xfer),$nm1 + fstds ${fnm1},8($xfer) + extrd,u $ab1,63,32,$ab1 + addl $hi1,$nm1,$nm1 + flddx $idx($ap),${fai} ; ap[j,j+1] + flddx $idx($np),${fni} ; np[j,j+1] + addl $ab1,$nm1,$nm1 + extrd,u $nm1,31,32,$hi1 + + xmpyu ${fai}L,${fbi},${fab0} ; ap[j]*bp[0] + xmpyu ${fni}L,${fm0}R,${fnm0} ; np[j]*m + ldd -16($xfer),$ab0 + fstds ${fab0},-16($xfer) + addl $hi0,$ab0,$ab0 + extrd,u $ab0,31,32,$hi0 + ldd -8($xfer),$nm0 + fstds ${fnm0},-8($xfer) + extrd,u $ab0,63,32,$ab0 + addl $hi1,$nm0,$nm0 + stw $nm1,-4($tp) ; tp[j-1] + addl $ab0,$nm0,$nm0 + stw,ma $nm0,8($tp) ; tp[j-1] + addib,<> 8,$idx,L\$1st ; j++++ + extrd,u $nm0,31,32,$hi1 + + xmpyu ${fai}R,${fbi},${fab1} ; ap[j]*bp[0] + xmpyu ${fni}R,${fm0}R,${fnm1} ; np[j]*m + ldd 0($xfer),$ab1 + fstds ${fab1},0($xfer) + addl $hi0,$ab1,$ab1 + extrd,u $ab1,31,32,$hi0 + ldd 8($xfer),$nm1 + fstds ${fnm1},8($xfer) + extrd,u $ab1,63,32,$ab1 + addl $hi1,$nm1,$nm1 + ldd -16($xfer),$ab0 + addl $ab1,$nm1,$nm1 + ldd -8($xfer),$nm0 + extrd,u $nm1,31,32,$hi1 + + addl $hi0,$ab0,$ab0 + extrd,u $ab0,31,32,$hi0 + stw $nm1,-4($tp) ; tp[j-1] + extrd,u $ab0,63,32,$ab0 + addl $hi1,$nm0,$nm0 + ldd 0($xfer),$ab1 + addl $ab0,$nm0,$nm0 + ldd,mb 8($xfer),$nm1 + extrd,u $nm0,31,32,$hi1 + stw,ma $nm0,8($tp) ; tp[j-1] + + ldo -1($num),$num ; i-- + subi 0,$arrsz,$idx ; j=0 +___ +$code.=<<___ if ($BN_SZ==4); + fldws,ma 4($bp),${fbi} ; bp[1] +___ +$code.=<<___ if ($BN_SZ==8); + fldws 0($bp),${fbi} ; bp[1] in flipped word order +___ +$code.=<<___; + flddx $idx($ap),${fai} ; ap[0,1] + flddx $idx($np),${fni} ; np[0,1] + fldws 8($xfer),${fti}R ; tp[0] + addl $hi0,$ab1,$ab1 + extrd,u $ab1,31,32,$hi0 + extrd,u $ab1,63,32,$ab1 + ldo 8($idx),$idx ; j++++ + xmpyu ${fai}L,${fbi},${fab0} ; ap[0]*bp[1] + xmpyu ${fai}R,${fbi},${fab1} ; ap[1]*bp[1] + addl $hi1,$nm1,$nm1 + addl $ab1,$nm1,$nm1 + extrd,u $nm1,31,32,$hi1 + fstws,mb ${fab0}L,-8($xfer) ; save high part + stw $nm1,-4($tp) ; tp[j-1] + + fcpy,sgl %fr0,${fti}L ; zero high part + fcpy,sgl %fr0,${fab0}L + addl $hi1,$hi0,$hi0 + extrd,u $hi0,31,32,$hi1 + fcnvxf,dbl,dbl ${fti},${fti} ; 32-bit unsigned int -> double + fcnvxf,dbl,dbl ${fab0},${fab0} + stw $hi0,0($tp) + stw $hi1,4($tp) + + fadd,dbl ${fti},${fab0},${fab0} ; add tp[0] + fcnvfx,dbl,dbl ${fab0},${fab0} ; double -> 33-bit unsigned int + xmpyu ${fn0},${fab0}R,${fm0} + ldo `$LOCALS+32+4`($fp),$tp +L\$outer + xmpyu ${fni}L,${fm0}R,${fnm0} ; np[0]*m + xmpyu ${fni}R,${fm0}R,${fnm1} ; np[1]*m + fstds ${fab0},-16($xfer) ; 33-bit value + fstds ${fnm0},-8($xfer) + flddx $idx($ap),${fai} ; ap[2] + flddx $idx($np),${fni} ; np[2] + ldo 8($idx),$idx ; j++++ + ldd -16($xfer),$ab0 ; 33-bit value + ldd -8($xfer),$nm0 + ldw 0($xfer),$hi0 ; high part + + xmpyu ${fai}L,${fbi},${fab0} ; ap[j]*bp[i] + xmpyu ${fni}L,${fm0}R,${fnm0} ; np[j]*m + extrd,u $ab0,31,32,$ti0 ; carry bit + extrd,u $ab0,63,32,$ab0 + fstds ${fab1},0($xfer) + addl $ti0,$hi0,$hi0 ; account carry bit + fstds ${fnm1},8($xfer) + addl $ab0,$nm0,$nm0 ; low part is discarded + ldw 0($tp),$ti1 ; tp[1] + extrd,u $nm0,31,32,$hi1 + fstds ${fab0},-16($xfer) + fstds ${fnm0},-8($xfer) + +L\$inner + xmpyu ${fai}R,${fbi},${fab1} ; ap[j+1]*bp[i] + xmpyu ${fni}R,${fm0}R,${fnm1} ; np[j+1]*m + ldd 0($xfer),$ab1 + fstds ${fab1},0($xfer) + addl $hi0,$ti1,$ti1 + addl $ti1,$ab1,$ab1 + ldd 8($xfer),$nm1 + fstds ${fnm1},8($xfer) + extrd,u $ab1,31,32,$hi0 + extrd,u $ab1,63,32,$ab1 + flddx $idx($ap),${fai} ; ap[j,j+1] + flddx $idx($np),${fni} ; np[j,j+1] + addl $hi1,$nm1,$nm1 + addl $ab1,$nm1,$nm1 + ldw 4($tp),$ti0 ; tp[j] + stw $nm1,-4($tp) ; tp[j-1] + + xmpyu ${fai}L,${fbi},${fab0} ; ap[j]*bp[i] + xmpyu ${fni}L,${fm0}R,${fnm0} ; np[j]*m + ldd -16($xfer),$ab0 + fstds ${fab0},-16($xfer) + addl $hi0,$ti0,$ti0 + addl $ti0,$ab0,$ab0 + ldd -8($xfer),$nm0 + fstds ${fnm0},-8($xfer) + extrd,u $ab0,31,32,$hi0 + extrd,u $nm1,31,32,$hi1 + ldw 8($tp),$ti1 ; tp[j] + extrd,u $ab0,63,32,$ab0 + addl $hi1,$nm0,$nm0 + addl $ab0,$nm0,$nm0 + stw,ma $nm0,8($tp) ; tp[j-1] + addib,<> 8,$idx,L\$inner ; j++++ + extrd,u $nm0,31,32,$hi1 + + xmpyu ${fai}R,${fbi},${fab1} ; ap[j]*bp[i] + xmpyu ${fni}R,${fm0}R,${fnm1} ; np[j]*m + ldd 0($xfer),$ab1 + fstds ${fab1},0($xfer) + addl $hi0,$ti1,$ti1 + addl $ti1,$ab1,$ab1 + ldd 8($xfer),$nm1 + fstds ${fnm1},8($xfer) + extrd,u $ab1,31,32,$hi0 + extrd,u $ab1,63,32,$ab1 + ldw 4($tp),$ti0 ; tp[j] + addl $hi1,$nm1,$nm1 + addl $ab1,$nm1,$nm1 + ldd -16($xfer),$ab0 + ldd -8($xfer),$nm0 + extrd,u $nm1,31,32,$hi1 + + addl $hi0,$ab0,$ab0 + addl $ti0,$ab0,$ab0 + stw $nm1,-4($tp) ; tp[j-1] + extrd,u $ab0,31,32,$hi0 + ldw 8($tp),$ti1 ; tp[j] + extrd,u $ab0,63,32,$ab0 + addl $hi1,$nm0,$nm0 + ldd 0($xfer),$ab1 + addl $ab0,$nm0,$nm0 + ldd,mb 8($xfer),$nm1 + extrd,u $nm0,31,32,$hi1 + stw,ma $nm0,8($tp) ; tp[j-1] + + addib,= -1,$num,L\$outerdone ; i-- + subi 0,$arrsz,$idx ; j=0 +___ +$code.=<<___ if ($BN_SZ==4); + fldws,ma 4($bp),${fbi} ; bp[i] +___ +$code.=<<___ if ($BN_SZ==8); + ldi 12,$ti0 ; bp[i] in flipped word order + addl,ev %r0,$num,$num + ldi -4,$ti0 + addl $ti0,$bp,$bp + fldws 0($bp),${fbi} +___ +$code.=<<___; + flddx $idx($ap),${fai} ; ap[0] + addl $hi0,$ab1,$ab1 + flddx $idx($np),${fni} ; np[0] + fldws 8($xfer),${fti}R ; tp[0] + addl $ti1,$ab1,$ab1 + extrd,u $ab1,31,32,$hi0 + extrd,u $ab1,63,32,$ab1 + + ldo 8($idx),$idx ; j++++ + xmpyu ${fai}L,${fbi},${fab0} ; ap[0]*bp[i] + xmpyu ${fai}R,${fbi},${fab1} ; ap[1]*bp[i] + ldw 4($tp),$ti0 ; tp[j] + + addl $hi1,$nm1,$nm1 + fstws,mb ${fab0}L,-8($xfer) ; save high part + addl $ab1,$nm1,$nm1 + extrd,u $nm1,31,32,$hi1 + fcpy,sgl %fr0,${fti}L ; zero high part + fcpy,sgl %fr0,${fab0}L + stw $nm1,-4($tp) ; tp[j-1] + + fcnvxf,dbl,dbl ${fti},${fti} ; 32-bit unsigned int -> double + fcnvxf,dbl,dbl ${fab0},${fab0} + addl $hi1,$hi0,$hi0 + fadd,dbl ${fti},${fab0},${fab0} ; add tp[0] + addl $ti0,$hi0,$hi0 + extrd,u $hi0,31,32,$hi1 + fcnvfx,dbl,dbl ${fab0},${fab0} ; double -> 33-bit unsigned int + stw $hi0,0($tp) + stw $hi1,4($tp) + xmpyu ${fn0},${fab0}R,${fm0} + + b L\$outer + ldo `$LOCALS+32+4`($fp),$tp + +L\$outerdone + addl $hi0,$ab1,$ab1 + addl $ti1,$ab1,$ab1 + extrd,u $ab1,31,32,$hi0 + extrd,u $ab1,63,32,$ab1 + + ldw 4($tp),$ti0 ; tp[j] + + addl $hi1,$nm1,$nm1 + addl $ab1,$nm1,$nm1 + extrd,u $nm1,31,32,$hi1 + stw $nm1,-4($tp) ; tp[j-1] + + addl $hi1,$hi0,$hi0 + addl $ti0,$hi0,$hi0 + extrd,u $hi0,31,32,$hi1 + stw $hi0,0($tp) + stw $hi1,4($tp) + + ldo `$LOCALS+32`($fp),$tp + sub %r0,%r0,%r0 ; clear borrow +___ +$code.=<<___ if ($BN_SZ==4); + ldws,ma 4($tp),$ti0 + extru,= $rp,31,3,%r0 ; is rp 64-bit aligned? + b L\$sub_pa11 + addl $tp,$arrsz,$tp +L\$sub + ldwx $idx($np),$hi0 + subb $ti0,$hi0,$hi1 + ldwx $idx($tp),$ti0 + addib,<> 4,$idx,L\$sub + stws,ma $hi1,4($rp) + + subb $ti0,%r0,$hi1 +___ +$code.=<<___ if ($BN_SZ==8); + ldd,ma 8($tp),$ti0 +L\$sub + ldd $idx($np),$hi0 + shrpd $ti0,$ti0,32,$ti0 ; flip word order + std $ti0,-8($tp) ; save flipped value + sub,db $ti0,$hi0,$hi1 + ldd,ma 8($tp),$ti0 + addib,<> 8,$idx,L\$sub + std,ma $hi1,8($rp) + + extrd,u $ti0,31,32,$ti0 ; carry in flipped word order + sub,db $ti0,%r0,$hi1 +___ +$code.=<<___; + ldo `$LOCALS+32`($fp),$tp + sub $rp,$arrsz,$rp ; rewind rp + subi 0,$arrsz,$idx +L\$copy + ldd 0($tp),$ti0 + ldd 0($rp),$hi0 + std,ma %r0,8($tp) + comiclr,= 0,$hi1,%r0 + copy $ti0,$hi0 + addib,<> 8,$idx,L\$copy + std,ma $hi0,8($rp) +___ + +if ($BN_SZ==4) { # PA-RISC 1.1 code-path +$ablo=$ab0; +$abhi=$ab1; +$nmlo0=$nm0; +$nmhi0=$nm1; +$nmlo1="%r9"; +$nmhi1="%r8"; + +$code.=<<___; + b L\$done + nop + + .ALIGN 8 +L\$parisc11 + xmpyu ${fai}L,${fbi},${fab0} ; ap[j]*bp[0] + xmpyu ${fni}L,${fm0}R,${fnm0} ; np[j]*m + ldw -12($xfer),$ablo + ldw -16($xfer),$hi0 + ldw -4($xfer),$nmlo0 + ldw -8($xfer),$nmhi0 + fstds ${fab0},-16($xfer) + fstds ${fnm0},-8($xfer) + + ldo 8($idx),$idx ; j++++ + add $ablo,$nmlo0,$nmlo0 ; discarded + addc %r0,$nmhi0,$hi1 + ldw 4($xfer),$ablo + ldw 0($xfer),$abhi + nop + +L\$1st_pa11 + xmpyu ${fai}R,${fbi},${fab1} ; ap[j+1]*bp[0] + flddx $idx($ap),${fai} ; ap[j,j+1] + xmpyu ${fni}R,${fm0}R,${fnm1} ; np[j+1]*m + flddx $idx($np),${fni} ; np[j,j+1] + add $hi0,$ablo,$ablo + ldw 12($xfer),$nmlo1 + addc %r0,$abhi,$hi0 + ldw 8($xfer),$nmhi1 + add $ablo,$nmlo1,$nmlo1 + fstds ${fab1},0($xfer) + addc %r0,$nmhi1,$nmhi1 + fstds ${fnm1},8($xfer) + add $hi1,$nmlo1,$nmlo1 + ldw -12($xfer),$ablo + addc %r0,$nmhi1,$hi1 + ldw -16($xfer),$abhi + + xmpyu ${fai}L,${fbi},${fab0} ; ap[j]*bp[0] + ldw -4($xfer),$nmlo0 + xmpyu ${fni}L,${fm0}R,${fnm0} ; np[j]*m + ldw -8($xfer),$nmhi0 + add $hi0,$ablo,$ablo + stw $nmlo1,-4($tp) ; tp[j-1] + addc %r0,$abhi,$hi0 + fstds ${fab0},-16($xfer) + add $ablo,$nmlo0,$nmlo0 + fstds ${fnm0},-8($xfer) + addc %r0,$nmhi0,$nmhi0 + ldw 0($xfer),$abhi + add $hi1,$nmlo0,$nmlo0 + ldw 4($xfer),$ablo + stws,ma $nmlo0,8($tp) ; tp[j-1] + addib,<> 8,$idx,L\$1st_pa11 ; j++++ + addc %r0,$nmhi0,$hi1 + + ldw 8($xfer),$nmhi1 + ldw 12($xfer),$nmlo1 + xmpyu ${fai}R,${fbi},${fab1} ; ap[j]*bp[0] + xmpyu ${fni}R,${fm0}R,${fnm1} ; np[j]*m + add $hi0,$ablo,$ablo + fstds ${fab1},0($xfer) + addc %r0,$abhi,$hi0 + fstds ${fnm1},8($xfer) + add $ablo,$nmlo1,$nmlo1 + ldw -16($xfer),$abhi + addc %r0,$nmhi1,$nmhi1 + ldw -12($xfer),$ablo + add $hi1,$nmlo1,$nmlo1 + ldw -8($xfer),$nmhi0 + addc %r0,$nmhi1,$hi1 + ldw -4($xfer),$nmlo0 + + add $hi0,$ablo,$ablo + stw $nmlo1,-4($tp) ; tp[j-1] + addc %r0,$abhi,$hi0 + ldw 0($xfer),$abhi + add $ablo,$nmlo0,$nmlo0 + ldw 4($xfer),$ablo + addc %r0,$nmhi0,$nmhi0 + ldws,mb 8($xfer),$nmhi1 + add $hi1,$nmlo0,$nmlo0 + ldw 4($xfer),$nmlo1 + addc %r0,$nmhi0,$hi1 + stws,ma $nmlo0,8($tp) ; tp[j-1] + + ldo -1($num),$num ; i-- + subi 0,$arrsz,$idx ; j=0 + + fldws,ma 4($bp),${fbi} ; bp[1] + flddx $idx($ap),${fai} ; ap[0,1] + flddx $idx($np),${fni} ; np[0,1] + fldws 8($xfer),${fti}R ; tp[0] + add $hi0,$ablo,$ablo + addc %r0,$abhi,$hi0 + ldo 8($idx),$idx ; j++++ + xmpyu ${fai}L,${fbi},${fab0} ; ap[0]*bp[1] + xmpyu ${fai}R,${fbi},${fab1} ; ap[1]*bp[1] + add $hi1,$nmlo1,$nmlo1 + addc %r0,$nmhi1,$nmhi1 + add $ablo,$nmlo1,$nmlo1 + addc %r0,$nmhi1,$hi1 + fstws,mb ${fab0}L,-8($xfer) ; save high part + stw $nmlo1,-4($tp) ; tp[j-1] + + fcpy,sgl %fr0,${fti}L ; zero high part + fcpy,sgl %fr0,${fab0}L + add $hi1,$hi0,$hi0 + addc %r0,%r0,$hi1 + fcnvxf,dbl,dbl ${fti},${fti} ; 32-bit unsigned int -> double + fcnvxf,dbl,dbl ${fab0},${fab0} + stw $hi0,0($tp) + stw $hi1,4($tp) + + fadd,dbl ${fti},${fab0},${fab0} ; add tp[0] + fcnvfx,dbl,dbl ${fab0},${fab0} ; double -> 33-bit unsigned int + xmpyu ${fn0},${fab0}R,${fm0} + ldo `$LOCALS+32+4`($fp),$tp +L\$outer_pa11 + xmpyu ${fni}L,${fm0}R,${fnm0} ; np[0]*m + xmpyu ${fni}R,${fm0}R,${fnm1} ; np[1]*m + fstds ${fab0},-16($xfer) ; 33-bit value + fstds ${fnm0},-8($xfer) + flddx $idx($ap),${fai} ; ap[2,3] + flddx $idx($np),${fni} ; np[2,3] + ldw -16($xfer),$abhi ; carry bit actually + ldo 8($idx),$idx ; j++++ + ldw -12($xfer),$ablo + ldw -8($xfer),$nmhi0 + ldw -4($xfer),$nmlo0 + ldw 0($xfer),$hi0 ; high part + + xmpyu ${fai}L,${fbi},${fab0} ; ap[j]*bp[i] + xmpyu ${fni}L,${fm0}R,${fnm0} ; np[j]*m + fstds ${fab1},0($xfer) + addl $abhi,$hi0,$hi0 ; account carry bit + fstds ${fnm1},8($xfer) + add $ablo,$nmlo0,$nmlo0 ; discarded + ldw 0($tp),$ti1 ; tp[1] + addc %r0,$nmhi0,$hi1 + fstds ${fab0},-16($xfer) + fstds ${fnm0},-8($xfer) + ldw 4($xfer),$ablo + ldw 0($xfer),$abhi + +L\$inner_pa11 + xmpyu ${fai}R,${fbi},${fab1} ; ap[j+1]*bp[i] + flddx $idx($ap),${fai} ; ap[j,j+1] + xmpyu ${fni}R,${fm0}R,${fnm1} ; np[j+1]*m + flddx $idx($np),${fni} ; np[j,j+1] + add $hi0,$ablo,$ablo + ldw 4($tp),$ti0 ; tp[j] + addc %r0,$abhi,$abhi + ldw 12($xfer),$nmlo1 + add $ti1,$ablo,$ablo + ldw 8($xfer),$nmhi1 + addc %r0,$abhi,$hi0 + fstds ${fab1},0($xfer) + add $ablo,$nmlo1,$nmlo1 + fstds ${fnm1},8($xfer) + addc %r0,$nmhi1,$nmhi1 + ldw -12($xfer),$ablo + add $hi1,$nmlo1,$nmlo1 + ldw -16($xfer),$abhi + addc %r0,$nmhi1,$hi1 + + xmpyu ${fai}L,${fbi},${fab0} ; ap[j]*bp[i] + ldw 8($tp),$ti1 ; tp[j] + xmpyu ${fni}L,${fm0}R,${fnm0} ; np[j]*m + ldw -4($xfer),$nmlo0 + add $hi0,$ablo,$ablo + ldw -8($xfer),$nmhi0 + addc %r0,$abhi,$abhi + stw $nmlo1,-4($tp) ; tp[j-1] + add $ti0,$ablo,$ablo + fstds ${fab0},-16($xfer) + addc %r0,$abhi,$hi0 + fstds ${fnm0},-8($xfer) + add $ablo,$nmlo0,$nmlo0 + ldw 4($xfer),$ablo + addc %r0,$nmhi0,$nmhi0 + ldw 0($xfer),$abhi + add $hi1,$nmlo0,$nmlo0 + stws,ma $nmlo0,8($tp) ; tp[j-1] + addib,<> 8,$idx,L\$inner_pa11 ; j++++ + addc %r0,$nmhi0,$hi1 + + xmpyu ${fai}R,${fbi},${fab1} ; ap[j]*bp[i] + ldw 12($xfer),$nmlo1 + xmpyu ${fni}R,${fm0}R,${fnm1} ; np[j]*m + ldw 8($xfer),$nmhi1 + add $hi0,$ablo,$ablo + ldw 4($tp),$ti0 ; tp[j] + addc %r0,$abhi,$abhi + fstds ${fab1},0($xfer) + add $ti1,$ablo,$ablo + fstds ${fnm1},8($xfer) + addc %r0,$abhi,$hi0 + ldw -16($xfer),$abhi + add $ablo,$nmlo1,$nmlo1 + ldw -12($xfer),$ablo + addc %r0,$nmhi1,$nmhi1 + ldw -8($xfer),$nmhi0 + add $hi1,$nmlo1,$nmlo1 + ldw -4($xfer),$nmlo0 + addc %r0,$nmhi1,$hi1 + + add $hi0,$ablo,$ablo + stw $nmlo1,-4($tp) ; tp[j-1] + addc %r0,$abhi,$abhi + add $ti0,$ablo,$ablo + ldw 8($tp),$ti1 ; tp[j] + addc %r0,$abhi,$hi0 + ldw 0($xfer),$abhi + add $ablo,$nmlo0,$nmlo0 + ldw 4($xfer),$ablo + addc %r0,$nmhi0,$nmhi0 + ldws,mb 8($xfer),$nmhi1 + add $hi1,$nmlo0,$nmlo0 + ldw 4($xfer),$nmlo1 + addc %r0,$nmhi0,$hi1 + stws,ma $nmlo0,8($tp) ; tp[j-1] + + addib,= -1,$num,L\$outerdone_pa11; i-- + subi 0,$arrsz,$idx ; j=0 + + fldws,ma 4($bp),${fbi} ; bp[i] + flddx $idx($ap),${fai} ; ap[0] + add $hi0,$ablo,$ablo + addc %r0,$abhi,$abhi + flddx $idx($np),${fni} ; np[0] + fldws 8($xfer),${fti}R ; tp[0] + add $ti1,$ablo,$ablo + addc %r0,$abhi,$hi0 + + ldo 8($idx),$idx ; j++++ + xmpyu ${fai}L,${fbi},${fab0} ; ap[0]*bp[i] + xmpyu ${fai}R,${fbi},${fab1} ; ap[1]*bp[i] + ldw 4($tp),$ti0 ; tp[j] + + add $hi1,$nmlo1,$nmlo1 + addc %r0,$nmhi1,$nmhi1 + fstws,mb ${fab0}L,-8($xfer) ; save high part + add $ablo,$nmlo1,$nmlo1 + addc %r0,$nmhi1,$hi1 + fcpy,sgl %fr0,${fti}L ; zero high part + fcpy,sgl %fr0,${fab0}L + stw $nmlo1,-4($tp) ; tp[j-1] + + fcnvxf,dbl,dbl ${fti},${fti} ; 32-bit unsigned int -> double + fcnvxf,dbl,dbl ${fab0},${fab0} + add $hi1,$hi0,$hi0 + addc %r0,%r0,$hi1 + fadd,dbl ${fti},${fab0},${fab0} ; add tp[0] + add $ti0,$hi0,$hi0 + addc %r0,$hi1,$hi1 + fcnvfx,dbl,dbl ${fab0},${fab0} ; double -> 33-bit unsigned int + stw $hi0,0($tp) + stw $hi1,4($tp) + xmpyu ${fn0},${fab0}R,${fm0} + + b L\$outer_pa11 + ldo `$LOCALS+32+4`($fp),$tp + +L\$outerdone_pa11 + add $hi0,$ablo,$ablo + addc %r0,$abhi,$abhi + add $ti1,$ablo,$ablo + addc %r0,$abhi,$hi0 + + ldw 4($tp),$ti0 ; tp[j] + + add $hi1,$nmlo1,$nmlo1 + addc %r0,$nmhi1,$nmhi1 + add $ablo,$nmlo1,$nmlo1 + addc %r0,$nmhi1,$hi1 + stw $nmlo1,-4($tp) ; tp[j-1] + + add $hi1,$hi0,$hi0 + addc %r0,%r0,$hi1 + add $ti0,$hi0,$hi0 + addc %r0,$hi1,$hi1 + stw $hi0,0($tp) + stw $hi1,4($tp) + + ldo `$LOCALS+32+4`($fp),$tp + sub %r0,%r0,%r0 ; clear borrow + ldw -4($tp),$ti0 + addl $tp,$arrsz,$tp +L\$sub_pa11 + ldwx $idx($np),$hi0 + subb $ti0,$hi0,$hi1 + ldwx $idx($tp),$ti0 + addib,<> 4,$idx,L\$sub_pa11 + stws,ma $hi1,4($rp) + + subb $ti0,%r0,$hi1 + + ldo `$LOCALS+32`($fp),$tp + sub $rp,$arrsz,$rp ; rewind rp + subi 0,$arrsz,$idx +L\$copy_pa11 + ldw 0($tp),$ti0 + ldw 0($rp),$hi0 + stws,ma %r0,4($tp) + comiclr,= 0,$hi1,%r0 + copy $ti0,$hi0 + addib,<> 4,$idx,L\$copy_pa11 + stws,ma $hi0,4($rp) + + nop ; alignment +L\$done +___ +} + +$code.=<<___; + ldi 1,%r28 ; signal "handled" + ldo $FRAME($fp),%sp ; destroy tp[num+1] + + $POP `-$FRAME-$SAVED_RP`(%sp),%r2 ; standard epilogue + $POP `-$FRAME+1*$SIZE_T`(%sp),%r4 + $POP `-$FRAME+2*$SIZE_T`(%sp),%r5 + $POP `-$FRAME+3*$SIZE_T`(%sp),%r6 + $POP `-$FRAME+4*$SIZE_T`(%sp),%r7 + $POP `-$FRAME+5*$SIZE_T`(%sp),%r8 + $POP `-$FRAME+6*$SIZE_T`(%sp),%r9 + $POP `-$FRAME+7*$SIZE_T`(%sp),%r10 +L\$abort + bv (%r2) + .EXIT + $POPMB -$FRAME(%sp),%r3 + .PROCEND + .STRINGZ "Montgomery Multiplication for PA-RISC, CRYPTOGAMS by " +___ + +# Explicitly encode PA-RISC 2.0 instructions used in this module, so +# that it can be compiled with .LEVEL 1.0. It should be noted that I +# wouldn't have to do this, if GNU assembler understood .ALLOW 2.0 +# directive... + +my $ldd = sub { + my ($mod,$args) = @_; + my $orig = "ldd$mod\t$args"; + + if ($args =~ /%r([0-9]+)\(%r([0-9]+)\),%r([0-9]+)/) # format 4 + { my $opcode=(0x03<<26)|($2<<21)|($1<<16)|(3<<6)|$3; + sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig; + } + elsif ($args =~ /(\-?[0-9]+)\(%r([0-9]+)\),%r([0-9]+)/) # format 5 + { my $opcode=(0x03<<26)|($2<<21)|(1<<12)|(3<<6)|$3; + $opcode|=(($1&0xF)<<17)|(($1&0x10)<<12); # encode offset + $opcode|=(1<<5) if ($mod =~ /^,m/); + $opcode|=(1<<13) if ($mod =~ /^,mb/); + sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig; + } + else { "\t".$orig; } +}; + +my $std = sub { + my ($mod,$args) = @_; + my $orig = "std$mod\t$args"; + + if ($args =~ /%r([0-9]+),(\-?[0-9]+)\(%r([0-9]+)\)/) # format 6 + { my $opcode=(0x03<<26)|($3<<21)|($1<<16)|(1<<12)|(0xB<<6); + $opcode|=(($2&0xF)<<1)|(($2&0x10)>>4); # encode offset + $opcode|=(1<<5) if ($mod =~ /^,m/); + $opcode|=(1<<13) if ($mod =~ /^,mb/); + sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig; + } + else { "\t".$orig; } +}; + +my $extrd = sub { + my ($mod,$args) = @_; + my $orig = "extrd$mod\t$args"; + + # I only have ",u" completer, it's implicitly encoded... + if ($args =~ /%r([0-9]+),([0-9]+),([0-9]+),%r([0-9]+)/) # format 15 + { my $opcode=(0x36<<26)|($1<<21)|($4<<16); + my $len=32-$3; + $opcode |= (($2&0x20)<<6)|(($2&0x1f)<<5); # encode pos + $opcode |= (($len&0x20)<<7)|($len&0x1f); # encode len + sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig; + } + elsif ($args =~ /%r([0-9]+),%sar,([0-9]+),%r([0-9]+)/) # format 12 + { my $opcode=(0x34<<26)|($1<<21)|($3<<16)|(2<<11)|(1<<9); + my $len=32-$2; + $opcode |= (($len&0x20)<<3)|($len&0x1f); # encode len + $opcode |= (1<<13) if ($mod =~ /,\**=/); + sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig; + } + else { "\t".$orig; } +}; + +my $shrpd = sub { + my ($mod,$args) = @_; + my $orig = "shrpd$mod\t$args"; + + if ($args =~ /%r([0-9]+),%r([0-9]+),([0-9]+),%r([0-9]+)/) # format 14 + { my $opcode=(0x34<<26)|($2<<21)|($1<<16)|(1<<10)|$4; + my $cpos=63-$3; + $opcode |= (($cpos&0x20)<<6)|(($cpos&0x1f)<<5); # encode sa + sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig; + } + else { "\t".$orig; } +}; + +my $sub = sub { + my ($mod,$args) = @_; + my $orig = "sub$mod\t$args"; + + if ($mod eq ",db" && $args =~ /%r([0-9]+),%r([0-9]+),%r([0-9]+)/) { + my $opcode=(0x02<<26)|($2<<21)|($1<<16)|$3; + $opcode|=(1<<10); # e1 + $opcode|=(1<<8); # e2 + $opcode|=(1<<5); # d + sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig + } + else { "\t".$orig; } +}; + +sub assemble { + my ($mnemonic,$mod,$args)=@_; + my $opcode = eval("\$$mnemonic"); + + ref($opcode) eq 'CODE' ? &$opcode($mod,$args) : "\t$mnemonic$mod\t$args"; +} + +if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler/) { + $gnuas = 1; +} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/ge; + # flip word order in 64-bit mode... + s/(xmpyu\s+)($fai|$fni)([LR])/$1.$2.($3 eq "L"?"R":"L")/e if ($BN_SZ==8); + # assemble 2.0 instructions in 32-bit mode... + s/^\s+([a-z]+)([\S]*)\s+([\S]*)/&assemble($1,$2,$3)/e if ($BN_SZ==4); + + s/(\.LEVEL\s+2\.0)W/$1w/ if ($gnuas && $SIZE_T==8); + s/\.SPACE\s+\$TEXT\$/.text/ if ($gnuas && $SIZE_T==8); + s/\.SUBSPA.*// if ($gnuas && $SIZE_T==8); + s/\bbv\b/bve/ if ($SIZE_T==8); + + print $_,"\n"; +} +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/ppc-mont.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/ppc-mont.pl new file mode 100644 index 000000000..ec7e019a4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/ppc-mont.pl @@ -0,0 +1,1990 @@ +#! /usr/bin/env perl +# Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# April 2006 + +# "Teaser" Montgomery multiplication module for PowerPC. It's possible +# to gain a bit more by modulo-scheduling outer loop, then dedicated +# squaring procedure should give further 20% and code can be adapted +# for 32-bit application running on 64-bit CPU. As for the latter. +# It won't be able to achieve "native" 64-bit performance, because in +# 32-bit application context every addc instruction will have to be +# expanded as addc, twice right shift by 32 and finally adde, etc. +# So far RSA *sign* performance improvement over pre-bn_mul_mont asm +# for 64-bit application running on PPC970/G5 is: +# +# 512-bit +65% +# 1024-bit +35% +# 2048-bit +18% +# 4096-bit +4% + +# September 2016 +# +# Add multiplication procedure operating on lengths divisible by 4 +# and squaring procedure operating on lengths divisible by 8. Length +# is expressed in number of limbs. RSA private key operations are +# ~35-50% faster (more for longer keys) on contemporary high-end POWER +# processors in 64-bit builds, [mysteriously enough] more in 32-bit +# builds. On low-end 32-bit processors performance improvement turned +# to be marginal... + +$flavour = shift; + +if ($flavour =~ /32/) { + $BITS= 32; + $BNSZ= $BITS/8; + $SIZE_T=4; + $RZONE= 224; + + $LD= "lwz"; # load + $LDU= "lwzu"; # load and update + $LDX= "lwzx"; # load indexed + $ST= "stw"; # store + $STU= "stwu"; # store and update + $STX= "stwx"; # store indexed + $STUX= "stwux"; # store indexed and update + $UMULL= "mullw"; # unsigned multiply low + $UMULH= "mulhwu"; # unsigned multiply high + $UCMP= "cmplw"; # unsigned compare + $SHRI= "srwi"; # unsigned shift right by immediate + $SHLI= "slwi"; # unsigned shift left by immediate + $PUSH= $ST; + $POP= $LD; +} elsif ($flavour =~ /64/) { + $BITS= 64; + $BNSZ= $BITS/8; + $SIZE_T=8; + $RZONE= 288; + + # same as above, but 64-bit mnemonics... + $LD= "ld"; # load + $LDU= "ldu"; # load and update + $LDX= "ldx"; # load indexed + $ST= "std"; # store + $STU= "stdu"; # store and update + $STX= "stdx"; # store indexed + $STUX= "stdux"; # store indexed and update + $UMULL= "mulld"; # unsigned multiply low + $UMULH= "mulhdu"; # unsigned multiply high + $UCMP= "cmpld"; # unsigned compare + $SHRI= "srdi"; # unsigned shift right by immediate + $SHLI= "sldi"; # unsigned shift left by immediate + $PUSH= $ST; + $POP= $LD; +} else { die "nonsense $flavour"; } + +$FRAME=8*$SIZE_T+$RZONE; +$LOCALS=8*$SIZE_T; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or +die "can't locate ppc-xlate.pl"; + +open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!"; + +$sp="r1"; +$toc="r2"; +$rp="r3"; +$ap="r4"; +$bp="r5"; +$np="r6"; +$n0="r7"; +$num="r8"; + +{ +my $ovf=$rp; +my $rp="r9"; # $rp is reassigned +my $aj="r10"; +my $nj="r11"; +my $tj="r12"; +# non-volatile registers +my $i="r20"; +my $j="r21"; +my $tp="r22"; +my $m0="r23"; +my $m1="r24"; +my $lo0="r25"; +my $hi0="r26"; +my $lo1="r27"; +my $hi1="r28"; +my $alo="r29"; +my $ahi="r30"; +my $nlo="r31"; +# +my $nhi="r0"; + +$code=<<___; +.machine "any" +.text + +.globl .bn_mul_mont_int +.align 5 +.bn_mul_mont_int: + mr $rp,r3 ; $rp is reassigned + li r3,0 +___ +$code.=<<___ if ($BNSZ==4); + cmpwi $num,32 ; longer key performance is not better + bgelr +___ +$code.=<<___; + slwi $num,$num,`log($BNSZ)/log(2)` + li $tj,-4096 + addi $ovf,$num,$FRAME + subf $ovf,$ovf,$sp ; $sp-$ovf + and $ovf,$ovf,$tj ; minimize TLB usage + subf $ovf,$sp,$ovf ; $ovf-$sp + mr $tj,$sp + srwi $num,$num,`log($BNSZ)/log(2)` + $STUX $sp,$sp,$ovf + + $PUSH r20,`-12*$SIZE_T`($tj) + $PUSH r21,`-11*$SIZE_T`($tj) + $PUSH r22,`-10*$SIZE_T`($tj) + $PUSH r23,`-9*$SIZE_T`($tj) + $PUSH r24,`-8*$SIZE_T`($tj) + $PUSH r25,`-7*$SIZE_T`($tj) + $PUSH r26,`-6*$SIZE_T`($tj) + $PUSH r27,`-5*$SIZE_T`($tj) + $PUSH r28,`-4*$SIZE_T`($tj) + $PUSH r29,`-3*$SIZE_T`($tj) + $PUSH r30,`-2*$SIZE_T`($tj) + $PUSH r31,`-1*$SIZE_T`($tj) + + $LD $n0,0($n0) ; pull n0[0] value + addi $num,$num,-2 ; adjust $num for counter register + + $LD $m0,0($bp) ; m0=bp[0] + $LD $aj,0($ap) ; ap[0] + addi $tp,$sp,$LOCALS + $UMULL $lo0,$aj,$m0 ; ap[0]*bp[0] + $UMULH $hi0,$aj,$m0 + + $LD $aj,$BNSZ($ap) ; ap[1] + $LD $nj,0($np) ; np[0] + + $UMULL $m1,$lo0,$n0 ; "tp[0]"*n0 + + $UMULL $alo,$aj,$m0 ; ap[1]*bp[0] + $UMULH $ahi,$aj,$m0 + + $UMULL $lo1,$nj,$m1 ; np[0]*m1 + $UMULH $hi1,$nj,$m1 + $LD $nj,$BNSZ($np) ; np[1] + addc $lo1,$lo1,$lo0 + addze $hi1,$hi1 + + $UMULL $nlo,$nj,$m1 ; np[1]*m1 + $UMULH $nhi,$nj,$m1 + + mtctr $num + li $j,`2*$BNSZ` +.align 4 +L1st: + $LDX $aj,$ap,$j ; ap[j] + addc $lo0,$alo,$hi0 + $LDX $nj,$np,$j ; np[j] + addze $hi0,$ahi + $UMULL $alo,$aj,$m0 ; ap[j]*bp[0] + addc $lo1,$nlo,$hi1 + $UMULH $ahi,$aj,$m0 + addze $hi1,$nhi + $UMULL $nlo,$nj,$m1 ; np[j]*m1 + addc $lo1,$lo1,$lo0 ; np[j]*m1+ap[j]*bp[0] + $UMULH $nhi,$nj,$m1 + addze $hi1,$hi1 + $ST $lo1,0($tp) ; tp[j-1] + + addi $j,$j,$BNSZ ; j++ + addi $tp,$tp,$BNSZ ; tp++ + bdnz L1st +;L1st + addc $lo0,$alo,$hi0 + addze $hi0,$ahi + + addc $lo1,$nlo,$hi1 + addze $hi1,$nhi + addc $lo1,$lo1,$lo0 ; np[j]*m1+ap[j]*bp[0] + addze $hi1,$hi1 + $ST $lo1,0($tp) ; tp[j-1] + + li $ovf,0 + addc $hi1,$hi1,$hi0 + addze $ovf,$ovf ; upmost overflow bit + $ST $hi1,$BNSZ($tp) + + li $i,$BNSZ +.align 4 +Louter: + $LDX $m0,$bp,$i ; m0=bp[i] + $LD $aj,0($ap) ; ap[0] + addi $tp,$sp,$LOCALS + $LD $tj,$LOCALS($sp); tp[0] + $UMULL $lo0,$aj,$m0 ; ap[0]*bp[i] + $UMULH $hi0,$aj,$m0 + $LD $aj,$BNSZ($ap) ; ap[1] + $LD $nj,0($np) ; np[0] + addc $lo0,$lo0,$tj ; ap[0]*bp[i]+tp[0] + $UMULL $alo,$aj,$m0 ; ap[j]*bp[i] + addze $hi0,$hi0 + $UMULL $m1,$lo0,$n0 ; tp[0]*n0 + $UMULH $ahi,$aj,$m0 + $UMULL $lo1,$nj,$m1 ; np[0]*m1 + $UMULH $hi1,$nj,$m1 + $LD $nj,$BNSZ($np) ; np[1] + addc $lo1,$lo1,$lo0 + $UMULL $nlo,$nj,$m1 ; np[1]*m1 + addze $hi1,$hi1 + $UMULH $nhi,$nj,$m1 + + mtctr $num + li $j,`2*$BNSZ` +.align 4 +Linner: + $LDX $aj,$ap,$j ; ap[j] + addc $lo0,$alo,$hi0 + $LD $tj,$BNSZ($tp) ; tp[j] + addze $hi0,$ahi + $LDX $nj,$np,$j ; np[j] + addc $lo1,$nlo,$hi1 + $UMULL $alo,$aj,$m0 ; ap[j]*bp[i] + addze $hi1,$nhi + $UMULH $ahi,$aj,$m0 + addc $lo0,$lo0,$tj ; ap[j]*bp[i]+tp[j] + $UMULL $nlo,$nj,$m1 ; np[j]*m1 + addze $hi0,$hi0 + $UMULH $nhi,$nj,$m1 + addc $lo1,$lo1,$lo0 ; np[j]*m1+ap[j]*bp[i]+tp[j] + addi $j,$j,$BNSZ ; j++ + addze $hi1,$hi1 + $ST $lo1,0($tp) ; tp[j-1] + addi $tp,$tp,$BNSZ ; tp++ + bdnz Linner +;Linner + $LD $tj,$BNSZ($tp) ; tp[j] + addc $lo0,$alo,$hi0 + addze $hi0,$ahi + addc $lo0,$lo0,$tj ; ap[j]*bp[i]+tp[j] + addze $hi0,$hi0 + + addc $lo1,$nlo,$hi1 + addze $hi1,$nhi + addc $lo1,$lo1,$lo0 ; np[j]*m1+ap[j]*bp[i]+tp[j] + addze $hi1,$hi1 + $ST $lo1,0($tp) ; tp[j-1] + + addic $ovf,$ovf,-1 ; move upmost overflow to XER[CA] + li $ovf,0 + adde $hi1,$hi1,$hi0 + addze $ovf,$ovf + $ST $hi1,$BNSZ($tp) +; + slwi $tj,$num,`log($BNSZ)/log(2)` + $UCMP $i,$tj + addi $i,$i,$BNSZ + ble Louter + + addi $num,$num,2 ; restore $num + subfc $j,$j,$j ; j=0 and "clear" XER[CA] + addi $tp,$sp,$LOCALS + mtctr $num + +.align 4 +Lsub: $LDX $tj,$tp,$j + $LDX $nj,$np,$j + subfe $aj,$nj,$tj ; tp[j]-np[j] + $STX $aj,$rp,$j + addi $j,$j,$BNSZ + bdnz Lsub + + li $j,0 + mtctr $num + subfe $ovf,$j,$ovf ; handle upmost overflow bit + +.align 4 +Lcopy: ; conditional copy + $LDX $tj,$tp,$j + $LDX $aj,$rp,$j + and $tj,$tj,$ovf + andc $aj,$aj,$ovf + $STX $j,$tp,$j ; zap at once + or $aj,$aj,$tj + $STX $aj,$rp,$j + addi $j,$j,$BNSZ + bdnz Lcopy + + $POP $tj,0($sp) + li r3,1 + $POP r20,`-12*$SIZE_T`($tj) + $POP r21,`-11*$SIZE_T`($tj) + $POP r22,`-10*$SIZE_T`($tj) + $POP r23,`-9*$SIZE_T`($tj) + $POP r24,`-8*$SIZE_T`($tj) + $POP r25,`-7*$SIZE_T`($tj) + $POP r26,`-6*$SIZE_T`($tj) + $POP r27,`-5*$SIZE_T`($tj) + $POP r28,`-4*$SIZE_T`($tj) + $POP r29,`-3*$SIZE_T`($tj) + $POP r30,`-2*$SIZE_T`($tj) + $POP r31,`-1*$SIZE_T`($tj) + mr $sp,$tj + blr + .long 0 + .byte 0,12,4,0,0x80,12,6,0 + .long 0 +.size .bn_mul_mont_int,.-.bn_mul_mont_int +___ +} +if (1) { +my ($a0,$a1,$a2,$a3, + $t0,$t1,$t2,$t3, + $m0,$m1,$m2,$m3, + $acc0,$acc1,$acc2,$acc3,$acc4, + $bi,$mi,$tp,$ap_end,$cnt) = map("r$_",(9..12,14..31)); +my ($carry,$zero) = ($rp,"r0"); + +# sp----------->+-------------------------------+ +# | saved sp | +# +-------------------------------+ +# . . +# +8*size_t +-------------------------------+ +# | 4 "n0*t0" | +# . . +# . . +# +12*size_t +-------------------------------+ +# | size_t tmp[num] | +# . . +# . . +# . . +# +-------------------------------+ +# | topmost carry | +# . . +# -18*size_t +-------------------------------+ +# | 18 saved gpr, r14-r31 | +# . . +# . . +# +-------------------------------+ +$code.=<<___; +.globl .bn_mul4x_mont_int +.align 5 +.bn_mul4x_mont_int: + andi. r0,$num,7 + bne .Lmul4x_do + $UCMP $ap,$bp + bne .Lmul4x_do + b .Lsqr8x_do +.Lmul4x_do: + slwi $num,$num,`log($SIZE_T)/log(2)` + mr $a0,$sp + li $a1,-32*$SIZE_T + sub $a1,$a1,$num + $STUX $sp,$sp,$a1 # alloca + + $PUSH r14,-$SIZE_T*18($a0) + $PUSH r15,-$SIZE_T*17($a0) + $PUSH r16,-$SIZE_T*16($a0) + $PUSH r17,-$SIZE_T*15($a0) + $PUSH r18,-$SIZE_T*14($a0) + $PUSH r19,-$SIZE_T*13($a0) + $PUSH r20,-$SIZE_T*12($a0) + $PUSH r21,-$SIZE_T*11($a0) + $PUSH r22,-$SIZE_T*10($a0) + $PUSH r23,-$SIZE_T*9($a0) + $PUSH r24,-$SIZE_T*8($a0) + $PUSH r25,-$SIZE_T*7($a0) + $PUSH r26,-$SIZE_T*6($a0) + $PUSH r27,-$SIZE_T*5($a0) + $PUSH r28,-$SIZE_T*4($a0) + $PUSH r29,-$SIZE_T*3($a0) + $PUSH r30,-$SIZE_T*2($a0) + $PUSH r31,-$SIZE_T*1($a0) + + subi $ap,$ap,$SIZE_T # bias by -1 + subi $np,$np,$SIZE_T # bias by -1 + subi $rp,$rp,$SIZE_T # bias by -1 + $LD $n0,0($n0) # *n0 + + add $t0,$bp,$num + add $ap_end,$ap,$num + subi $t0,$t0,$SIZE_T*4 # &b[num-4] + + $LD $bi,$SIZE_T*0($bp) # b[0] + li $acc0,0 + $LD $a0,$SIZE_T*1($ap) # a[0..3] + li $acc1,0 + $LD $a1,$SIZE_T*2($ap) + li $acc2,0 + $LD $a2,$SIZE_T*3($ap) + li $acc3,0 + $LDU $a3,$SIZE_T*4($ap) + $LD $m0,$SIZE_T*1($np) # n[0..3] + $LD $m1,$SIZE_T*2($np) + $LD $m2,$SIZE_T*3($np) + $LDU $m3,$SIZE_T*4($np) + + $PUSH $rp,$SIZE_T*6($sp) # offload rp and &b[num-4] + $PUSH $t0,$SIZE_T*7($sp) + li $carry,0 + addic $tp,$sp,$SIZE_T*7 # &t[-1], clear carry bit + li $cnt,0 + li $zero,0 + b .Loop_mul4x_1st_reduction + +.align 5 +.Loop_mul4x_1st_reduction: + $UMULL $t0,$a0,$bi # lo(a[0..3]*b[0]) + addze $carry,$carry # modulo-scheduled + $UMULL $t1,$a1,$bi + addi $cnt,$cnt,$SIZE_T + $UMULL $t2,$a2,$bi + andi. $cnt,$cnt,$SIZE_T*4-1 + $UMULL $t3,$a3,$bi + addc $acc0,$acc0,$t0 + $UMULH $t0,$a0,$bi # hi(a[0..3]*b[0]) + adde $acc1,$acc1,$t1 + $UMULH $t1,$a1,$bi + adde $acc2,$acc2,$t2 + $UMULL $mi,$acc0,$n0 # t[0]*n0 + adde $acc3,$acc3,$t3 + $UMULH $t2,$a2,$bi + addze $acc4,$zero + $UMULH $t3,$a3,$bi + $LDX $bi,$bp,$cnt # next b[i] (or b[0]) + addc $acc1,$acc1,$t0 + # (*) mul $t0,$m0,$mi # lo(n[0..3]*t[0]*n0) + $STU $mi,$SIZE_T($tp) # put aside t[0]*n0 for tail processing + adde $acc2,$acc2,$t1 + $UMULL $t1,$m1,$mi + adde $acc3,$acc3,$t2 + $UMULL $t2,$m2,$mi + adde $acc4,$acc4,$t3 # can't overflow + $UMULL $t3,$m3,$mi + # (*) addc $acc0,$acc0,$t0 + # (*) As for removal of first multiplication and addition + # instructions. The outcome of first addition is + # guaranteed to be zero, which leaves two computationally + # significant outcomes: it either carries or not. Then + # question is when does it carry? Is there alternative + # way to deduce it? If you follow operations, you can + # observe that condition for carry is quite simple: + # $acc0 being non-zero. So that carry can be calculated + # by adding -1 to $acc0. That's what next instruction does. + addic $acc0,$acc0,-1 # (*), discarded + $UMULH $t0,$m0,$mi # hi(n[0..3]*t[0]*n0) + adde $acc0,$acc1,$t1 + $UMULH $t1,$m1,$mi + adde $acc1,$acc2,$t2 + $UMULH $t2,$m2,$mi + adde $acc2,$acc3,$t3 + $UMULH $t3,$m3,$mi + adde $acc3,$acc4,$carry + addze $carry,$zero + addc $acc0,$acc0,$t0 + adde $acc1,$acc1,$t1 + adde $acc2,$acc2,$t2 + adde $acc3,$acc3,$t3 + #addze $carry,$carry + bne .Loop_mul4x_1st_reduction + + $UCMP $ap_end,$ap + beq .Lmul4x4_post_condition + + $LD $a0,$SIZE_T*1($ap) # a[4..7] + $LD $a1,$SIZE_T*2($ap) + $LD $a2,$SIZE_T*3($ap) + $LDU $a3,$SIZE_T*4($ap) + $LD $mi,$SIZE_T*8($sp) # a[0]*n0 + $LD $m0,$SIZE_T*1($np) # n[4..7] + $LD $m1,$SIZE_T*2($np) + $LD $m2,$SIZE_T*3($np) + $LDU $m3,$SIZE_T*4($np) + b .Loop_mul4x_1st_tail + +.align 5 +.Loop_mul4x_1st_tail: + $UMULL $t0,$a0,$bi # lo(a[4..7]*b[i]) + addze $carry,$carry # modulo-scheduled + $UMULL $t1,$a1,$bi + addi $cnt,$cnt,$SIZE_T + $UMULL $t2,$a2,$bi + andi. $cnt,$cnt,$SIZE_T*4-1 + $UMULL $t3,$a3,$bi + addc $acc0,$acc0,$t0 + $UMULH $t0,$a0,$bi # hi(a[4..7]*b[i]) + adde $acc1,$acc1,$t1 + $UMULH $t1,$a1,$bi + adde $acc2,$acc2,$t2 + $UMULH $t2,$a2,$bi + adde $acc3,$acc3,$t3 + $UMULH $t3,$a3,$bi + addze $acc4,$zero + $LDX $bi,$bp,$cnt # next b[i] (or b[0]) + addc $acc1,$acc1,$t0 + $UMULL $t0,$m0,$mi # lo(n[4..7]*a[0]*n0) + adde $acc2,$acc2,$t1 + $UMULL $t1,$m1,$mi + adde $acc3,$acc3,$t2 + $UMULL $t2,$m2,$mi + adde $acc4,$acc4,$t3 # can't overflow + $UMULL $t3,$m3,$mi + addc $acc0,$acc0,$t0 + $UMULH $t0,$m0,$mi # hi(n[4..7]*a[0]*n0) + adde $acc1,$acc1,$t1 + $UMULH $t1,$m1,$mi + adde $acc2,$acc2,$t2 + $UMULH $t2,$m2,$mi + adde $acc3,$acc3,$t3 + adde $acc4,$acc4,$carry + $UMULH $t3,$m3,$mi + addze $carry,$zero + addi $mi,$sp,$SIZE_T*8 + $LDX $mi,$mi,$cnt # next t[0]*n0 + $STU $acc0,$SIZE_T($tp) # word of result + addc $acc0,$acc1,$t0 + adde $acc1,$acc2,$t1 + adde $acc2,$acc3,$t2 + adde $acc3,$acc4,$t3 + #addze $carry,$carry + bne .Loop_mul4x_1st_tail + + sub $t1,$ap_end,$num # rewinded $ap + $UCMP $ap_end,$ap # done yet? + beq .Lmul4x_proceed + + $LD $a0,$SIZE_T*1($ap) + $LD $a1,$SIZE_T*2($ap) + $LD $a2,$SIZE_T*3($ap) + $LDU $a3,$SIZE_T*4($ap) + $LD $m0,$SIZE_T*1($np) + $LD $m1,$SIZE_T*2($np) + $LD $m2,$SIZE_T*3($np) + $LDU $m3,$SIZE_T*4($np) + b .Loop_mul4x_1st_tail + +.align 5 +.Lmul4x_proceed: + $LDU $bi,$SIZE_T*4($bp) # *++b + addze $carry,$carry # topmost carry + $LD $a0,$SIZE_T*1($t1) + $LD $a1,$SIZE_T*2($t1) + $LD $a2,$SIZE_T*3($t1) + $LD $a3,$SIZE_T*4($t1) + addi $ap,$t1,$SIZE_T*4 + sub $np,$np,$num # rewind np + + $ST $acc0,$SIZE_T*1($tp) # result + $ST $acc1,$SIZE_T*2($tp) + $ST $acc2,$SIZE_T*3($tp) + $ST $acc3,$SIZE_T*4($tp) + $ST $carry,$SIZE_T*5($tp) # save topmost carry + $LD $acc0,$SIZE_T*12($sp) # t[0..3] + $LD $acc1,$SIZE_T*13($sp) + $LD $acc2,$SIZE_T*14($sp) + $LD $acc3,$SIZE_T*15($sp) + + $LD $m0,$SIZE_T*1($np) # n[0..3] + $LD $m1,$SIZE_T*2($np) + $LD $m2,$SIZE_T*3($np) + $LDU $m3,$SIZE_T*4($np) + addic $tp,$sp,$SIZE_T*7 # &t[-1], clear carry bit + li $carry,0 + b .Loop_mul4x_reduction + +.align 5 +.Loop_mul4x_reduction: + $UMULL $t0,$a0,$bi # lo(a[0..3]*b[4]) + addze $carry,$carry # modulo-scheduled + $UMULL $t1,$a1,$bi + addi $cnt,$cnt,$SIZE_T + $UMULL $t2,$a2,$bi + andi. $cnt,$cnt,$SIZE_T*4-1 + $UMULL $t3,$a3,$bi + addc $acc0,$acc0,$t0 + $UMULH $t0,$a0,$bi # hi(a[0..3]*b[4]) + adde $acc1,$acc1,$t1 + $UMULH $t1,$a1,$bi + adde $acc2,$acc2,$t2 + $UMULL $mi,$acc0,$n0 # t[0]*n0 + adde $acc3,$acc3,$t3 + $UMULH $t2,$a2,$bi + addze $acc4,$zero + $UMULH $t3,$a3,$bi + $LDX $bi,$bp,$cnt # next b[i] + addc $acc1,$acc1,$t0 + # (*) mul $t0,$m0,$mi + $STU $mi,$SIZE_T($tp) # put aside t[0]*n0 for tail processing + adde $acc2,$acc2,$t1 + $UMULL $t1,$m1,$mi # lo(n[0..3]*t[0]*n0 + adde $acc3,$acc3,$t2 + $UMULL $t2,$m2,$mi + adde $acc4,$acc4,$t3 # can't overflow + $UMULL $t3,$m3,$mi + # (*) addc $acc0,$acc0,$t0 + addic $acc0,$acc0,-1 # (*), discarded + $UMULH $t0,$m0,$mi # hi(n[0..3]*t[0]*n0 + adde $acc0,$acc1,$t1 + $UMULH $t1,$m1,$mi + adde $acc1,$acc2,$t2 + $UMULH $t2,$m2,$mi + adde $acc2,$acc3,$t3 + $UMULH $t3,$m3,$mi + adde $acc3,$acc4,$carry + addze $carry,$zero + addc $acc0,$acc0,$t0 + adde $acc1,$acc1,$t1 + adde $acc2,$acc2,$t2 + adde $acc3,$acc3,$t3 + #addze $carry,$carry + bne .Loop_mul4x_reduction + + $LD $t0,$SIZE_T*5($tp) # t[4..7] + addze $carry,$carry + $LD $t1,$SIZE_T*6($tp) + $LD $t2,$SIZE_T*7($tp) + $LD $t3,$SIZE_T*8($tp) + $LD $a0,$SIZE_T*1($ap) # a[4..7] + $LD $a1,$SIZE_T*2($ap) + $LD $a2,$SIZE_T*3($ap) + $LDU $a3,$SIZE_T*4($ap) + addc $acc0,$acc0,$t0 + adde $acc1,$acc1,$t1 + adde $acc2,$acc2,$t2 + adde $acc3,$acc3,$t3 + #addze $carry,$carry + + $LD $mi,$SIZE_T*8($sp) # t[0]*n0 + $LD $m0,$SIZE_T*1($np) # n[4..7] + $LD $m1,$SIZE_T*2($np) + $LD $m2,$SIZE_T*3($np) + $LDU $m3,$SIZE_T*4($np) + b .Loop_mul4x_tail + +.align 5 +.Loop_mul4x_tail: + $UMULL $t0,$a0,$bi # lo(a[4..7]*b[4]) + addze $carry,$carry # modulo-scheduled + $UMULL $t1,$a1,$bi + addi $cnt,$cnt,$SIZE_T + $UMULL $t2,$a2,$bi + andi. $cnt,$cnt,$SIZE_T*4-1 + $UMULL $t3,$a3,$bi + addc $acc0,$acc0,$t0 + $UMULH $t0,$a0,$bi # hi(a[4..7]*b[4]) + adde $acc1,$acc1,$t1 + $UMULH $t1,$a1,$bi + adde $acc2,$acc2,$t2 + $UMULH $t2,$a2,$bi + adde $acc3,$acc3,$t3 + $UMULH $t3,$a3,$bi + addze $acc4,$zero + $LDX $bi,$bp,$cnt # next b[i] + addc $acc1,$acc1,$t0 + $UMULL $t0,$m0,$mi # lo(n[4..7]*t[0]*n0) + adde $acc2,$acc2,$t1 + $UMULL $t1,$m1,$mi + adde $acc3,$acc3,$t2 + $UMULL $t2,$m2,$mi + adde $acc4,$acc4,$t3 # can't overflow + $UMULL $t3,$m3,$mi + addc $acc0,$acc0,$t0 + $UMULH $t0,$m0,$mi # hi(n[4..7]*t[0]*n0) + adde $acc1,$acc1,$t1 + $UMULH $t1,$m1,$mi + adde $acc2,$acc2,$t2 + $UMULH $t2,$m2,$mi + adde $acc3,$acc3,$t3 + $UMULH $t3,$m3,$mi + adde $acc4,$acc4,$carry + addi $mi,$sp,$SIZE_T*8 + $LDX $mi,$mi,$cnt # next a[0]*n0 + addze $carry,$zero + $STU $acc0,$SIZE_T($tp) # word of result + addc $acc0,$acc1,$t0 + adde $acc1,$acc2,$t1 + adde $acc2,$acc3,$t2 + adde $acc3,$acc4,$t3 + #addze $carry,$carry + bne .Loop_mul4x_tail + + $LD $t0,$SIZE_T*5($tp) # next t[i] or topmost carry + sub $t1,$np,$num # rewinded np? + addze $carry,$carry + $UCMP $ap_end,$ap # done yet? + beq .Loop_mul4x_break + + $LD $t1,$SIZE_T*6($tp) + $LD $t2,$SIZE_T*7($tp) + $LD $t3,$SIZE_T*8($tp) + $LD $a0,$SIZE_T*1($ap) + $LD $a1,$SIZE_T*2($ap) + $LD $a2,$SIZE_T*3($ap) + $LDU $a3,$SIZE_T*4($ap) + addc $acc0,$acc0,$t0 + adde $acc1,$acc1,$t1 + adde $acc2,$acc2,$t2 + adde $acc3,$acc3,$t3 + #addze $carry,$carry + + $LD $m0,$SIZE_T*1($np) # n[4..7] + $LD $m1,$SIZE_T*2($np) + $LD $m2,$SIZE_T*3($np) + $LDU $m3,$SIZE_T*4($np) + b .Loop_mul4x_tail + +.align 5 +.Loop_mul4x_break: + $POP $t2,$SIZE_T*6($sp) # pull rp and &b[num-4] + $POP $t3,$SIZE_T*7($sp) + addc $a0,$acc0,$t0 # accumulate topmost carry + $LD $acc0,$SIZE_T*12($sp) # t[0..3] + addze $a1,$acc1 + $LD $acc1,$SIZE_T*13($sp) + addze $a2,$acc2 + $LD $acc2,$SIZE_T*14($sp) + addze $a3,$acc3 + $LD $acc3,$SIZE_T*15($sp) + addze $carry,$carry # topmost carry + $ST $a0,$SIZE_T*1($tp) # result + sub $ap,$ap_end,$num # rewind ap + $ST $a1,$SIZE_T*2($tp) + $ST $a2,$SIZE_T*3($tp) + $ST $a3,$SIZE_T*4($tp) + $ST $carry,$SIZE_T*5($tp) # store topmost carry + + $LD $m0,$SIZE_T*1($t1) # n[0..3] + $LD $m1,$SIZE_T*2($t1) + $LD $m2,$SIZE_T*3($t1) + $LD $m3,$SIZE_T*4($t1) + addi $np,$t1,$SIZE_T*4 + $UCMP $bp,$t3 # done yet? + beq .Lmul4x_post + + $LDU $bi,$SIZE_T*4($bp) + $LD $a0,$SIZE_T*1($ap) # a[0..3] + $LD $a1,$SIZE_T*2($ap) + $LD $a2,$SIZE_T*3($ap) + $LDU $a3,$SIZE_T*4($ap) + li $carry,0 + addic $tp,$sp,$SIZE_T*7 # &t[-1], clear carry bit + b .Loop_mul4x_reduction + +.align 5 +.Lmul4x_post: + # Final step. We see if result is larger than modulus, and + # if it is, subtract the modulus. But comparison implies + # subtraction. So we subtract modulus, see if it borrowed, + # and conditionally copy original value. + srwi $cnt,$num,`log($SIZE_T)/log(2)+2` + mr $bp,$t2 # &rp[-1] + subi $cnt,$cnt,1 + mr $ap_end,$t2 # &rp[-1] copy + subfc $t0,$m0,$acc0 + addi $tp,$sp,$SIZE_T*15 + subfe $t1,$m1,$acc1 + + mtctr $cnt +.Lmul4x_sub: + $LD $m0,$SIZE_T*1($np) + $LD $acc0,$SIZE_T*1($tp) + subfe $t2,$m2,$acc2 + $LD $m1,$SIZE_T*2($np) + $LD $acc1,$SIZE_T*2($tp) + subfe $t3,$m3,$acc3 + $LD $m2,$SIZE_T*3($np) + $LD $acc2,$SIZE_T*3($tp) + $LDU $m3,$SIZE_T*4($np) + $LDU $acc3,$SIZE_T*4($tp) + $ST $t0,$SIZE_T*1($bp) + $ST $t1,$SIZE_T*2($bp) + subfe $t0,$m0,$acc0 + $ST $t2,$SIZE_T*3($bp) + $STU $t3,$SIZE_T*4($bp) + subfe $t1,$m1,$acc1 + bdnz .Lmul4x_sub + + $LD $a0,$SIZE_T*1($ap_end) + $ST $t0,$SIZE_T*1($bp) + $LD $t0,$SIZE_T*12($sp) + subfe $t2,$m2,$acc2 + $LD $a1,$SIZE_T*2($ap_end) + $ST $t1,$SIZE_T*2($bp) + $LD $t1,$SIZE_T*13($sp) + subfe $t3,$m3,$acc3 + subfe $carry,$zero,$carry # did it borrow? + addi $tp,$sp,$SIZE_T*12 + $LD $a2,$SIZE_T*3($ap_end) + $ST $t2,$SIZE_T*3($bp) + $LD $t2,$SIZE_T*14($sp) + $LD $a3,$SIZE_T*4($ap_end) + $ST $t3,$SIZE_T*4($bp) + $LD $t3,$SIZE_T*15($sp) + + mtctr $cnt +.Lmul4x_cond_copy: + and $t0,$t0,$carry + andc $a0,$a0,$carry + $ST $zero,$SIZE_T*0($tp) # wipe stack clean + and $t1,$t1,$carry + andc $a1,$a1,$carry + $ST $zero,$SIZE_T*1($tp) + and $t2,$t2,$carry + andc $a2,$a2,$carry + $ST $zero,$SIZE_T*2($tp) + and $t3,$t3,$carry + andc $a3,$a3,$carry + $ST $zero,$SIZE_T*3($tp) + or $acc0,$t0,$a0 + $LD $a0,$SIZE_T*5($ap_end) + $LD $t0,$SIZE_T*4($tp) + or $acc1,$t1,$a1 + $LD $a1,$SIZE_T*6($ap_end) + $LD $t1,$SIZE_T*5($tp) + or $acc2,$t2,$a2 + $LD $a2,$SIZE_T*7($ap_end) + $LD $t2,$SIZE_T*6($tp) + or $acc3,$t3,$a3 + $LD $a3,$SIZE_T*8($ap_end) + $LD $t3,$SIZE_T*7($tp) + addi $tp,$tp,$SIZE_T*4 + $ST $acc0,$SIZE_T*1($ap_end) + $ST $acc1,$SIZE_T*2($ap_end) + $ST $acc2,$SIZE_T*3($ap_end) + $STU $acc3,$SIZE_T*4($ap_end) + bdnz .Lmul4x_cond_copy + + $POP $bp,0($sp) # pull saved sp + and $t0,$t0,$carry + andc $a0,$a0,$carry + $ST $zero,$SIZE_T*0($tp) + and $t1,$t1,$carry + andc $a1,$a1,$carry + $ST $zero,$SIZE_T*1($tp) + and $t2,$t2,$carry + andc $a2,$a2,$carry + $ST $zero,$SIZE_T*2($tp) + and $t3,$t3,$carry + andc $a3,$a3,$carry + $ST $zero,$SIZE_T*3($tp) + or $acc0,$t0,$a0 + or $acc1,$t1,$a1 + $ST $zero,$SIZE_T*4($tp) + or $acc2,$t2,$a2 + or $acc3,$t3,$a3 + $ST $acc0,$SIZE_T*1($ap_end) + $ST $acc1,$SIZE_T*2($ap_end) + $ST $acc2,$SIZE_T*3($ap_end) + $ST $acc3,$SIZE_T*4($ap_end) + + b .Lmul4x_done + +.align 4 +.Lmul4x4_post_condition: + $POP $ap,$SIZE_T*6($sp) # pull &rp[-1] + $POP $bp,0($sp) # pull saved sp + addze $carry,$carry # modulo-scheduled + # $acc0-3,$carry hold result, $m0-3 hold modulus + subfc $a0,$m0,$acc0 + subfe $a1,$m1,$acc1 + subfe $a2,$m2,$acc2 + subfe $a3,$m3,$acc3 + subfe $carry,$zero,$carry # did it borrow? + + and $m0,$m0,$carry + and $m1,$m1,$carry + addc $a0,$a0,$m0 + and $m2,$m2,$carry + adde $a1,$a1,$m1 + and $m3,$m3,$carry + adde $a2,$a2,$m2 + adde $a3,$a3,$m3 + + $ST $a0,$SIZE_T*1($ap) # write result + $ST $a1,$SIZE_T*2($ap) + $ST $a2,$SIZE_T*3($ap) + $ST $a3,$SIZE_T*4($ap) + +.Lmul4x_done: + $ST $zero,$SIZE_T*8($sp) # wipe stack clean + $ST $zero,$SIZE_T*9($sp) + $ST $zero,$SIZE_T*10($sp) + $ST $zero,$SIZE_T*11($sp) + li r3,1 # signal "done" + $POP r14,-$SIZE_T*18($bp) + $POP r15,-$SIZE_T*17($bp) + $POP r16,-$SIZE_T*16($bp) + $POP r17,-$SIZE_T*15($bp) + $POP r18,-$SIZE_T*14($bp) + $POP r19,-$SIZE_T*13($bp) + $POP r20,-$SIZE_T*12($bp) + $POP r21,-$SIZE_T*11($bp) + $POP r22,-$SIZE_T*10($bp) + $POP r23,-$SIZE_T*9($bp) + $POP r24,-$SIZE_T*8($bp) + $POP r25,-$SIZE_T*7($bp) + $POP r26,-$SIZE_T*6($bp) + $POP r27,-$SIZE_T*5($bp) + $POP r28,-$SIZE_T*4($bp) + $POP r29,-$SIZE_T*3($bp) + $POP r30,-$SIZE_T*2($bp) + $POP r31,-$SIZE_T*1($bp) + mr $sp,$bp + blr + .long 0 + .byte 0,12,4,0x20,0x80,18,6,0 + .long 0 +.size .bn_mul4x_mont_int,.-.bn_mul4x_mont_int +___ +} + +if (1) { +######################################################################## +# Following is PPC adaptation of sqrx8x_mont from x86_64-mont5 module. + +my ($a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7)=map("r$_",(9..12,14..17)); +my ($t0,$t1,$t2,$t3)=map("r$_",(18..21)); +my ($acc0,$acc1,$acc2,$acc3,$acc4,$acc5,$acc6,$acc7)=map("r$_",(22..29)); +my ($cnt,$carry,$zero)=("r30","r31","r0"); +my ($tp,$ap_end,$na0)=($bp,$np,$carry); + +# sp----------->+-------------------------------+ +# | saved sp | +# +-------------------------------+ +# . . +# +12*size_t +-------------------------------+ +# | size_t tmp[2*num] | +# . . +# . . +# . . +# +-------------------------------+ +# . . +# -18*size_t +-------------------------------+ +# | 18 saved gpr, r14-r31 | +# . . +# . . +# +-------------------------------+ +$code.=<<___; +.align 5 +__bn_sqr8x_mont: +.Lsqr8x_do: + mr $a0,$sp + slwi $a1,$num,`log($SIZE_T)/log(2)+1` + li $a2,-32*$SIZE_T + sub $a1,$a2,$a1 + slwi $num,$num,`log($SIZE_T)/log(2)` + $STUX $sp,$sp,$a1 # alloca + + $PUSH r14,-$SIZE_T*18($a0) + $PUSH r15,-$SIZE_T*17($a0) + $PUSH r16,-$SIZE_T*16($a0) + $PUSH r17,-$SIZE_T*15($a0) + $PUSH r18,-$SIZE_T*14($a0) + $PUSH r19,-$SIZE_T*13($a0) + $PUSH r20,-$SIZE_T*12($a0) + $PUSH r21,-$SIZE_T*11($a0) + $PUSH r22,-$SIZE_T*10($a0) + $PUSH r23,-$SIZE_T*9($a0) + $PUSH r24,-$SIZE_T*8($a0) + $PUSH r25,-$SIZE_T*7($a0) + $PUSH r26,-$SIZE_T*6($a0) + $PUSH r27,-$SIZE_T*5($a0) + $PUSH r28,-$SIZE_T*4($a0) + $PUSH r29,-$SIZE_T*3($a0) + $PUSH r30,-$SIZE_T*2($a0) + $PUSH r31,-$SIZE_T*1($a0) + + subi $ap,$ap,$SIZE_T # bias by -1 + subi $t0,$np,$SIZE_T # bias by -1 + subi $rp,$rp,$SIZE_T # bias by -1 + $LD $n0,0($n0) # *n0 + li $zero,0 + + add $ap_end,$ap,$num + $LD $a0,$SIZE_T*1($ap) + #li $acc0,0 + $LD $a1,$SIZE_T*2($ap) + li $acc1,0 + $LD $a2,$SIZE_T*3($ap) + li $acc2,0 + $LD $a3,$SIZE_T*4($ap) + li $acc3,0 + $LD $a4,$SIZE_T*5($ap) + li $acc4,0 + $LD $a5,$SIZE_T*6($ap) + li $acc5,0 + $LD $a6,$SIZE_T*7($ap) + li $acc6,0 + $LDU $a7,$SIZE_T*8($ap) + li $acc7,0 + + addi $tp,$sp,$SIZE_T*11 # &tp[-1] + subic. $cnt,$num,$SIZE_T*8 + b .Lsqr8x_zero_start + +.align 5 +.Lsqr8x_zero: + subic. $cnt,$cnt,$SIZE_T*8 + $ST $zero,$SIZE_T*1($tp) + $ST $zero,$SIZE_T*2($tp) + $ST $zero,$SIZE_T*3($tp) + $ST $zero,$SIZE_T*4($tp) + $ST $zero,$SIZE_T*5($tp) + $ST $zero,$SIZE_T*6($tp) + $ST $zero,$SIZE_T*7($tp) + $ST $zero,$SIZE_T*8($tp) +.Lsqr8x_zero_start: + $ST $zero,$SIZE_T*9($tp) + $ST $zero,$SIZE_T*10($tp) + $ST $zero,$SIZE_T*11($tp) + $ST $zero,$SIZE_T*12($tp) + $ST $zero,$SIZE_T*13($tp) + $ST $zero,$SIZE_T*14($tp) + $ST $zero,$SIZE_T*15($tp) + $STU $zero,$SIZE_T*16($tp) + bne .Lsqr8x_zero + + $PUSH $rp,$SIZE_T*6($sp) # offload &rp[-1] + $PUSH $t0,$SIZE_T*7($sp) # offload &np[-1] + $PUSH $n0,$SIZE_T*8($sp) # offload n0 + $PUSH $tp,$SIZE_T*9($sp) # &tp[2*num-1] + $PUSH $zero,$SIZE_T*10($sp) # initial top-most carry + addi $tp,$sp,$SIZE_T*11 # &tp[-1] + + # Multiply everything but a[i]*a[i] +.align 5 +.Lsqr8x_outer_loop: + # a[1]a[0] (i) + # a[2]a[0] + # a[3]a[0] + # a[4]a[0] + # a[5]a[0] + # a[6]a[0] + # a[7]a[0] + # a[2]a[1] (ii) + # a[3]a[1] + # a[4]a[1] + # a[5]a[1] + # a[6]a[1] + # a[7]a[1] + # a[3]a[2] (iii) + # a[4]a[2] + # a[5]a[2] + # a[6]a[2] + # a[7]a[2] + # a[4]a[3] (iv) + # a[5]a[3] + # a[6]a[3] + # a[7]a[3] + # a[5]a[4] (v) + # a[6]a[4] + # a[7]a[4] + # a[6]a[5] (vi) + # a[7]a[5] + # a[7]a[6] (vii) + + $UMULL $t0,$a1,$a0 # lo(a[1..7]*a[0]) (i) + $UMULL $t1,$a2,$a0 + $UMULL $t2,$a3,$a0 + $UMULL $t3,$a4,$a0 + addc $acc1,$acc1,$t0 # t[1]+lo(a[1]*a[0]) + $UMULL $t0,$a5,$a0 + adde $acc2,$acc2,$t1 + $UMULL $t1,$a6,$a0 + adde $acc3,$acc3,$t2 + $UMULL $t2,$a7,$a0 + adde $acc4,$acc4,$t3 + $UMULH $t3,$a1,$a0 # hi(a[1..7]*a[0]) + adde $acc5,$acc5,$t0 + $UMULH $t0,$a2,$a0 + adde $acc6,$acc6,$t1 + $UMULH $t1,$a3,$a0 + adde $acc7,$acc7,$t2 + $UMULH $t2,$a4,$a0 + $ST $acc0,$SIZE_T*1($tp) # t[0] + addze $acc0,$zero # t[8] + $ST $acc1,$SIZE_T*2($tp) # t[1] + addc $acc2,$acc2,$t3 # t[2]+lo(a[1]*a[0]) + $UMULH $t3,$a5,$a0 + adde $acc3,$acc3,$t0 + $UMULH $t0,$a6,$a0 + adde $acc4,$acc4,$t1 + $UMULH $t1,$a7,$a0 + adde $acc5,$acc5,$t2 + $UMULL $t2,$a2,$a1 # lo(a[2..7]*a[1]) (ii) + adde $acc6,$acc6,$t3 + $UMULL $t3,$a3,$a1 + adde $acc7,$acc7,$t0 + $UMULL $t0,$a4,$a1 + adde $acc0,$acc0,$t1 + + $UMULL $t1,$a5,$a1 + addc $acc3,$acc3,$t2 + $UMULL $t2,$a6,$a1 + adde $acc4,$acc4,$t3 + $UMULL $t3,$a7,$a1 + adde $acc5,$acc5,$t0 + $UMULH $t0,$a2,$a1 # hi(a[2..7]*a[1]) + adde $acc6,$acc6,$t1 + $UMULH $t1,$a3,$a1 + adde $acc7,$acc7,$t2 + $UMULH $t2,$a4,$a1 + adde $acc0,$acc0,$t3 + $UMULH $t3,$a5,$a1 + $ST $acc2,$SIZE_T*3($tp) # t[2] + addze $acc1,$zero # t[9] + $ST $acc3,$SIZE_T*4($tp) # t[3] + addc $acc4,$acc4,$t0 + $UMULH $t0,$a6,$a1 + adde $acc5,$acc5,$t1 + $UMULH $t1,$a7,$a1 + adde $acc6,$acc6,$t2 + $UMULL $t2,$a3,$a2 # lo(a[3..7]*a[2]) (iii) + adde $acc7,$acc7,$t3 + $UMULL $t3,$a4,$a2 + adde $acc0,$acc0,$t0 + $UMULL $t0,$a5,$a2 + adde $acc1,$acc1,$t1 + + $UMULL $t1,$a6,$a2 + addc $acc5,$acc5,$t2 + $UMULL $t2,$a7,$a2 + adde $acc6,$acc6,$t3 + $UMULH $t3,$a3,$a2 # hi(a[3..7]*a[2]) + adde $acc7,$acc7,$t0 + $UMULH $t0,$a4,$a2 + adde $acc0,$acc0,$t1 + $UMULH $t1,$a5,$a2 + adde $acc1,$acc1,$t2 + $UMULH $t2,$a6,$a2 + $ST $acc4,$SIZE_T*5($tp) # t[4] + addze $acc2,$zero # t[10] + $ST $acc5,$SIZE_T*6($tp) # t[5] + addc $acc6,$acc6,$t3 + $UMULH $t3,$a7,$a2 + adde $acc7,$acc7,$t0 + $UMULL $t0,$a4,$a3 # lo(a[4..7]*a[3]) (iv) + adde $acc0,$acc0,$t1 + $UMULL $t1,$a5,$a3 + adde $acc1,$acc1,$t2 + $UMULL $t2,$a6,$a3 + adde $acc2,$acc2,$t3 + + $UMULL $t3,$a7,$a3 + addc $acc7,$acc7,$t0 + $UMULH $t0,$a4,$a3 # hi(a[4..7]*a[3]) + adde $acc0,$acc0,$t1 + $UMULH $t1,$a5,$a3 + adde $acc1,$acc1,$t2 + $UMULH $t2,$a6,$a3 + adde $acc2,$acc2,$t3 + $UMULH $t3,$a7,$a3 + $ST $acc6,$SIZE_T*7($tp) # t[6] + addze $acc3,$zero # t[11] + $STU $acc7,$SIZE_T*8($tp) # t[7] + addc $acc0,$acc0,$t0 + $UMULL $t0,$a5,$a4 # lo(a[5..7]*a[4]) (v) + adde $acc1,$acc1,$t1 + $UMULL $t1,$a6,$a4 + adde $acc2,$acc2,$t2 + $UMULL $t2,$a7,$a4 + adde $acc3,$acc3,$t3 + + $UMULH $t3,$a5,$a4 # hi(a[5..7]*a[4]) + addc $acc1,$acc1,$t0 + $UMULH $t0,$a6,$a4 + adde $acc2,$acc2,$t1 + $UMULH $t1,$a7,$a4 + adde $acc3,$acc3,$t2 + $UMULL $t2,$a6,$a5 # lo(a[6..7]*a[5]) (vi) + addze $acc4,$zero # t[12] + addc $acc2,$acc2,$t3 + $UMULL $t3,$a7,$a5 + adde $acc3,$acc3,$t0 + $UMULH $t0,$a6,$a5 # hi(a[6..7]*a[5]) + adde $acc4,$acc4,$t1 + + $UMULH $t1,$a7,$a5 + addc $acc3,$acc3,$t2 + $UMULL $t2,$a7,$a6 # lo(a[7]*a[6]) (vii) + adde $acc4,$acc4,$t3 + $UMULH $t3,$a7,$a6 # hi(a[7]*a[6]) + addze $acc5,$zero # t[13] + addc $acc4,$acc4,$t0 + $UCMP $ap_end,$ap # done yet? + adde $acc5,$acc5,$t1 + + addc $acc5,$acc5,$t2 + sub $t0,$ap_end,$num # rewinded ap + addze $acc6,$zero # t[14] + add $acc6,$acc6,$t3 + + beq .Lsqr8x_outer_break + + mr $n0,$a0 + $LD $a0,$SIZE_T*1($tp) + $LD $a1,$SIZE_T*2($tp) + $LD $a2,$SIZE_T*3($tp) + $LD $a3,$SIZE_T*4($tp) + $LD $a4,$SIZE_T*5($tp) + $LD $a5,$SIZE_T*6($tp) + $LD $a6,$SIZE_T*7($tp) + $LD $a7,$SIZE_T*8($tp) + addc $acc0,$acc0,$a0 + $LD $a0,$SIZE_T*1($ap) + adde $acc1,$acc1,$a1 + $LD $a1,$SIZE_T*2($ap) + adde $acc2,$acc2,$a2 + $LD $a2,$SIZE_T*3($ap) + adde $acc3,$acc3,$a3 + $LD $a3,$SIZE_T*4($ap) + adde $acc4,$acc4,$a4 + $LD $a4,$SIZE_T*5($ap) + adde $acc5,$acc5,$a5 + $LD $a5,$SIZE_T*6($ap) + adde $acc6,$acc6,$a6 + $LD $a6,$SIZE_T*7($ap) + subi $rp,$ap,$SIZE_T*7 + addze $acc7,$a7 + $LDU $a7,$SIZE_T*8($ap) + #addze $carry,$zero # moved below + li $cnt,0 + b .Lsqr8x_mul + + # a[8]a[0] + # a[9]a[0] + # a[a]a[0] + # a[b]a[0] + # a[c]a[0] + # a[d]a[0] + # a[e]a[0] + # a[f]a[0] + # a[8]a[1] + # a[f]a[1]........................ + # a[8]a[2] + # a[f]a[2]........................ + # a[8]a[3] + # a[f]a[3]........................ + # a[8]a[4] + # a[f]a[4]........................ + # a[8]a[5] + # a[f]a[5]........................ + # a[8]a[6] + # a[f]a[6]........................ + # a[8]a[7] + # a[f]a[7]........................ +.align 5 +.Lsqr8x_mul: + $UMULL $t0,$a0,$n0 + addze $carry,$zero # carry bit, modulo-scheduled + $UMULL $t1,$a1,$n0 + addi $cnt,$cnt,$SIZE_T + $UMULL $t2,$a2,$n0 + andi. $cnt,$cnt,$SIZE_T*8-1 + $UMULL $t3,$a3,$n0 + addc $acc0,$acc0,$t0 + $UMULL $t0,$a4,$n0 + adde $acc1,$acc1,$t1 + $UMULL $t1,$a5,$n0 + adde $acc2,$acc2,$t2 + $UMULL $t2,$a6,$n0 + adde $acc3,$acc3,$t3 + $UMULL $t3,$a7,$n0 + adde $acc4,$acc4,$t0 + $UMULH $t0,$a0,$n0 + adde $acc5,$acc5,$t1 + $UMULH $t1,$a1,$n0 + adde $acc6,$acc6,$t2 + $UMULH $t2,$a2,$n0 + adde $acc7,$acc7,$t3 + $UMULH $t3,$a3,$n0 + addze $carry,$carry + $STU $acc0,$SIZE_T($tp) + addc $acc0,$acc1,$t0 + $UMULH $t0,$a4,$n0 + adde $acc1,$acc2,$t1 + $UMULH $t1,$a5,$n0 + adde $acc2,$acc3,$t2 + $UMULH $t2,$a6,$n0 + adde $acc3,$acc4,$t3 + $UMULH $t3,$a7,$n0 + $LDX $n0,$rp,$cnt + adde $acc4,$acc5,$t0 + adde $acc5,$acc6,$t1 + adde $acc6,$acc7,$t2 + adde $acc7,$carry,$t3 + #addze $carry,$zero # moved above + bne .Lsqr8x_mul + # note that carry flag is guaranteed + # to be zero at this point + $UCMP $ap,$ap_end # done yet? + beq .Lsqr8x_break + + $LD $a0,$SIZE_T*1($tp) + $LD $a1,$SIZE_T*2($tp) + $LD $a2,$SIZE_T*3($tp) + $LD $a3,$SIZE_T*4($tp) + $LD $a4,$SIZE_T*5($tp) + $LD $a5,$SIZE_T*6($tp) + $LD $a6,$SIZE_T*7($tp) + $LD $a7,$SIZE_T*8($tp) + addc $acc0,$acc0,$a0 + $LD $a0,$SIZE_T*1($ap) + adde $acc1,$acc1,$a1 + $LD $a1,$SIZE_T*2($ap) + adde $acc2,$acc2,$a2 + $LD $a2,$SIZE_T*3($ap) + adde $acc3,$acc3,$a3 + $LD $a3,$SIZE_T*4($ap) + adde $acc4,$acc4,$a4 + $LD $a4,$SIZE_T*5($ap) + adde $acc5,$acc5,$a5 + $LD $a5,$SIZE_T*6($ap) + adde $acc6,$acc6,$a6 + $LD $a6,$SIZE_T*7($ap) + adde $acc7,$acc7,$a7 + $LDU $a7,$SIZE_T*8($ap) + #addze $carry,$zero # moved above + b .Lsqr8x_mul + +.align 5 +.Lsqr8x_break: + $LD $a0,$SIZE_T*8($rp) + addi $ap,$rp,$SIZE_T*15 + $LD $a1,$SIZE_T*9($rp) + sub. $t0,$ap_end,$ap # is it last iteration? + $LD $a2,$SIZE_T*10($rp) + sub $t1,$tp,$t0 + $LD $a3,$SIZE_T*11($rp) + $LD $a4,$SIZE_T*12($rp) + $LD $a5,$SIZE_T*13($rp) + $LD $a6,$SIZE_T*14($rp) + $LD $a7,$SIZE_T*15($rp) + beq .Lsqr8x_outer_loop + + $ST $acc0,$SIZE_T*1($tp) + $LD $acc0,$SIZE_T*1($t1) + $ST $acc1,$SIZE_T*2($tp) + $LD $acc1,$SIZE_T*2($t1) + $ST $acc2,$SIZE_T*3($tp) + $LD $acc2,$SIZE_T*3($t1) + $ST $acc3,$SIZE_T*4($tp) + $LD $acc3,$SIZE_T*4($t1) + $ST $acc4,$SIZE_T*5($tp) + $LD $acc4,$SIZE_T*5($t1) + $ST $acc5,$SIZE_T*6($tp) + $LD $acc5,$SIZE_T*6($t1) + $ST $acc6,$SIZE_T*7($tp) + $LD $acc6,$SIZE_T*7($t1) + $ST $acc7,$SIZE_T*8($tp) + $LD $acc7,$SIZE_T*8($t1) + mr $tp,$t1 + b .Lsqr8x_outer_loop + +.align 5 +.Lsqr8x_outer_break: + #################################################################### + # Now multiply above result by 2 and add a[n-1]*a[n-1]|...|a[0]*a[0] + $LD $a1,$SIZE_T*1($t0) # recall that $t0 is &a[-1] + $LD $a3,$SIZE_T*2($t0) + $LD $a5,$SIZE_T*3($t0) + $LD $a7,$SIZE_T*4($t0) + addi $ap,$t0,$SIZE_T*4 + # "tp[x]" comments are for num==8 case + $LD $t1,$SIZE_T*13($sp) # =tp[1], t[0] is not interesting + $LD $t2,$SIZE_T*14($sp) + $LD $t3,$SIZE_T*15($sp) + $LD $t0,$SIZE_T*16($sp) + + $ST $acc0,$SIZE_T*1($tp) # tp[8]= + srwi $cnt,$num,`log($SIZE_T)/log(2)+2` + $ST $acc1,$SIZE_T*2($tp) + subi $cnt,$cnt,1 + $ST $acc2,$SIZE_T*3($tp) + $ST $acc3,$SIZE_T*4($tp) + $ST $acc4,$SIZE_T*5($tp) + $ST $acc5,$SIZE_T*6($tp) + $ST $acc6,$SIZE_T*7($tp) + #$ST $acc7,$SIZE_T*8($tp) # tp[15] is not interesting + addi $tp,$sp,$SIZE_T*11 # &tp[-1] + $UMULL $acc0,$a1,$a1 + $UMULH $a1,$a1,$a1 + add $acc1,$t1,$t1 # <<1 + $SHRI $t1,$t1,$BITS-1 + $UMULL $a2,$a3,$a3 + $UMULH $a3,$a3,$a3 + addc $acc1,$acc1,$a1 + add $acc2,$t2,$t2 + $SHRI $t2,$t2,$BITS-1 + add $acc3,$t3,$t3 + $SHRI $t3,$t3,$BITS-1 + or $acc2,$acc2,$t1 + + mtctr $cnt +.Lsqr4x_shift_n_add: + $UMULL $a4,$a5,$a5 + $UMULH $a5,$a5,$a5 + $LD $t1,$SIZE_T*6($tp) # =tp[5] + $LD $a1,$SIZE_T*1($ap) + adde $acc2,$acc2,$a2 + add $acc4,$t0,$t0 + $SHRI $t0,$t0,$BITS-1 + or $acc3,$acc3,$t2 + $LD $t2,$SIZE_T*7($tp) # =tp[6] + adde $acc3,$acc3,$a3 + $LD $a3,$SIZE_T*2($ap) + add $acc5,$t1,$t1 + $SHRI $t1,$t1,$BITS-1 + or $acc4,$acc4,$t3 + $LD $t3,$SIZE_T*8($tp) # =tp[7] + $UMULL $a6,$a7,$a7 + $UMULH $a7,$a7,$a7 + adde $acc4,$acc4,$a4 + add $acc6,$t2,$t2 + $SHRI $t2,$t2,$BITS-1 + or $acc5,$acc5,$t0 + $LD $t0,$SIZE_T*9($tp) # =tp[8] + adde $acc5,$acc5,$a5 + $LD $a5,$SIZE_T*3($ap) + add $acc7,$t3,$t3 + $SHRI $t3,$t3,$BITS-1 + or $acc6,$acc6,$t1 + $LD $t1,$SIZE_T*10($tp) # =tp[9] + $UMULL $a0,$a1,$a1 + $UMULH $a1,$a1,$a1 + adde $acc6,$acc6,$a6 + $ST $acc0,$SIZE_T*1($tp) # tp[0]= + add $acc0,$t0,$t0 + $SHRI $t0,$t0,$BITS-1 + or $acc7,$acc7,$t2 + $LD $t2,$SIZE_T*11($tp) # =tp[10] + adde $acc7,$acc7,$a7 + $LDU $a7,$SIZE_T*4($ap) + $ST $acc1,$SIZE_T*2($tp) # tp[1]= + add $acc1,$t1,$t1 + $SHRI $t1,$t1,$BITS-1 + or $acc0,$acc0,$t3 + $LD $t3,$SIZE_T*12($tp) # =tp[11] + $UMULL $a2,$a3,$a3 + $UMULH $a3,$a3,$a3 + adde $acc0,$acc0,$a0 + $ST $acc2,$SIZE_T*3($tp) # tp[2]= + add $acc2,$t2,$t2 + $SHRI $t2,$t2,$BITS-1 + or $acc1,$acc1,$t0 + $LD $t0,$SIZE_T*13($tp) # =tp[12] + adde $acc1,$acc1,$a1 + $ST $acc3,$SIZE_T*4($tp) # tp[3]= + $ST $acc4,$SIZE_T*5($tp) # tp[4]= + $ST $acc5,$SIZE_T*6($tp) # tp[5]= + $ST $acc6,$SIZE_T*7($tp) # tp[6]= + $STU $acc7,$SIZE_T*8($tp) # tp[7]= + add $acc3,$t3,$t3 + $SHRI $t3,$t3,$BITS-1 + or $acc2,$acc2,$t1 + bdnz .Lsqr4x_shift_n_add +___ +my ($np,$np_end)=($ap,$ap_end); +$code.=<<___; + $POP $np,$SIZE_T*7($sp) # pull &np[-1] and n0 + $POP $n0,$SIZE_T*8($sp) + + $UMULL $a4,$a5,$a5 + $UMULH $a5,$a5,$a5 + $ST $acc0,$SIZE_T*1($tp) # tp[8]= + $LD $acc0,$SIZE_T*12($sp) # =tp[0] + $LD $t1,$SIZE_T*6($tp) # =tp[13] + adde $acc2,$acc2,$a2 + add $acc4,$t0,$t0 + $SHRI $t0,$t0,$BITS-1 + or $acc3,$acc3,$t2 + $LD $t2,$SIZE_T*7($tp) # =tp[14] + adde $acc3,$acc3,$a3 + add $acc5,$t1,$t1 + $SHRI $t1,$t1,$BITS-1 + or $acc4,$acc4,$t3 + $UMULL $a6,$a7,$a7 + $UMULH $a7,$a7,$a7 + adde $acc4,$acc4,$a4 + add $acc6,$t2,$t2 + $SHRI $t2,$t2,$BITS-1 + or $acc5,$acc5,$t0 + $ST $acc1,$SIZE_T*2($tp) # tp[9]= + $LD $acc1,$SIZE_T*13($sp) # =tp[1] + adde $acc5,$acc5,$a5 + or $acc6,$acc6,$t1 + $LD $a0,$SIZE_T*1($np) + $LD $a1,$SIZE_T*2($np) + adde $acc6,$acc6,$a6 + $LD $a2,$SIZE_T*3($np) + $LD $a3,$SIZE_T*4($np) + adde $acc7,$a7,$t2 + $LD $a4,$SIZE_T*5($np) + $LD $a5,$SIZE_T*6($np) + + ################################################################ + # Reduce by 8 limbs per iteration + $UMULL $na0,$n0,$acc0 # t[0]*n0 + li $cnt,8 + $LD $a6,$SIZE_T*7($np) + add $np_end,$np,$num + $LDU $a7,$SIZE_T*8($np) + $ST $acc2,$SIZE_T*3($tp) # tp[10]= + $LD $acc2,$SIZE_T*14($sp) + $ST $acc3,$SIZE_T*4($tp) # tp[11]= + $LD $acc3,$SIZE_T*15($sp) + $ST $acc4,$SIZE_T*5($tp) # tp[12]= + $LD $acc4,$SIZE_T*16($sp) + $ST $acc5,$SIZE_T*6($tp) # tp[13]= + $LD $acc5,$SIZE_T*17($sp) + $ST $acc6,$SIZE_T*7($tp) # tp[14]= + $LD $acc6,$SIZE_T*18($sp) + $ST $acc7,$SIZE_T*8($tp) # tp[15]= + $LD $acc7,$SIZE_T*19($sp) + addi $tp,$sp,$SIZE_T*11 # &tp[-1] + mtctr $cnt + b .Lsqr8x_reduction + +.align 5 +.Lsqr8x_reduction: + # (*) $UMULL $t0,$a0,$na0 # lo(n[0-7])*lo(t[0]*n0) + $UMULL $t1,$a1,$na0 + $UMULL $t2,$a2,$na0 + $STU $na0,$SIZE_T($tp) # put aside t[0]*n0 for tail processing + $UMULL $t3,$a3,$na0 + # (*) addc $acc0,$acc0,$t0 + addic $acc0,$acc0,-1 # (*) + $UMULL $t0,$a4,$na0 + adde $acc0,$acc1,$t1 + $UMULL $t1,$a5,$na0 + adde $acc1,$acc2,$t2 + $UMULL $t2,$a6,$na0 + adde $acc2,$acc3,$t3 + $UMULL $t3,$a7,$na0 + adde $acc3,$acc4,$t0 + $UMULH $t0,$a0,$na0 # hi(n[0-7])*lo(t[0]*n0) + adde $acc4,$acc5,$t1 + $UMULH $t1,$a1,$na0 + adde $acc5,$acc6,$t2 + $UMULH $t2,$a2,$na0 + adde $acc6,$acc7,$t3 + $UMULH $t3,$a3,$na0 + addze $acc7,$zero + addc $acc0,$acc0,$t0 + $UMULH $t0,$a4,$na0 + adde $acc1,$acc1,$t1 + $UMULH $t1,$a5,$na0 + adde $acc2,$acc2,$t2 + $UMULH $t2,$a6,$na0 + adde $acc3,$acc3,$t3 + $UMULH $t3,$a7,$na0 + $UMULL $na0,$n0,$acc0 # next t[0]*n0 + adde $acc4,$acc4,$t0 + adde $acc5,$acc5,$t1 + adde $acc6,$acc6,$t2 + adde $acc7,$acc7,$t3 + bdnz .Lsqr8x_reduction + + $LD $t0,$SIZE_T*1($tp) + $LD $t1,$SIZE_T*2($tp) + $LD $t2,$SIZE_T*3($tp) + $LD $t3,$SIZE_T*4($tp) + subi $rp,$tp,$SIZE_T*7 + $UCMP $np_end,$np # done yet? + addc $acc0,$acc0,$t0 + $LD $t0,$SIZE_T*5($tp) + adde $acc1,$acc1,$t1 + $LD $t1,$SIZE_T*6($tp) + adde $acc2,$acc2,$t2 + $LD $t2,$SIZE_T*7($tp) + adde $acc3,$acc3,$t3 + $LD $t3,$SIZE_T*8($tp) + adde $acc4,$acc4,$t0 + adde $acc5,$acc5,$t1 + adde $acc6,$acc6,$t2 + adde $acc7,$acc7,$t3 + #addze $carry,$zero # moved below + beq .Lsqr8x8_post_condition + + $LD $n0,$SIZE_T*0($rp) + $LD $a0,$SIZE_T*1($np) + $LD $a1,$SIZE_T*2($np) + $LD $a2,$SIZE_T*3($np) + $LD $a3,$SIZE_T*4($np) + $LD $a4,$SIZE_T*5($np) + $LD $a5,$SIZE_T*6($np) + $LD $a6,$SIZE_T*7($np) + $LDU $a7,$SIZE_T*8($np) + li $cnt,0 + +.align 5 +.Lsqr8x_tail: + $UMULL $t0,$a0,$n0 + addze $carry,$zero # carry bit, modulo-scheduled + $UMULL $t1,$a1,$n0 + addi $cnt,$cnt,$SIZE_T + $UMULL $t2,$a2,$n0 + andi. $cnt,$cnt,$SIZE_T*8-1 + $UMULL $t3,$a3,$n0 + addc $acc0,$acc0,$t0 + $UMULL $t0,$a4,$n0 + adde $acc1,$acc1,$t1 + $UMULL $t1,$a5,$n0 + adde $acc2,$acc2,$t2 + $UMULL $t2,$a6,$n0 + adde $acc3,$acc3,$t3 + $UMULL $t3,$a7,$n0 + adde $acc4,$acc4,$t0 + $UMULH $t0,$a0,$n0 + adde $acc5,$acc5,$t1 + $UMULH $t1,$a1,$n0 + adde $acc6,$acc6,$t2 + $UMULH $t2,$a2,$n0 + adde $acc7,$acc7,$t3 + $UMULH $t3,$a3,$n0 + addze $carry,$carry + $STU $acc0,$SIZE_T($tp) + addc $acc0,$acc1,$t0 + $UMULH $t0,$a4,$n0 + adde $acc1,$acc2,$t1 + $UMULH $t1,$a5,$n0 + adde $acc2,$acc3,$t2 + $UMULH $t2,$a6,$n0 + adde $acc3,$acc4,$t3 + $UMULH $t3,$a7,$n0 + $LDX $n0,$rp,$cnt + adde $acc4,$acc5,$t0 + adde $acc5,$acc6,$t1 + adde $acc6,$acc7,$t2 + adde $acc7,$carry,$t3 + #addze $carry,$zero # moved above + bne .Lsqr8x_tail + # note that carry flag is guaranteed + # to be zero at this point + $LD $a0,$SIZE_T*1($tp) + $POP $carry,$SIZE_T*10($sp) # pull top-most carry in case we break + $UCMP $np_end,$np # done yet? + $LD $a1,$SIZE_T*2($tp) + sub $t2,$np_end,$num # rewinded np + $LD $a2,$SIZE_T*3($tp) + $LD $a3,$SIZE_T*4($tp) + $LD $a4,$SIZE_T*5($tp) + $LD $a5,$SIZE_T*6($tp) + $LD $a6,$SIZE_T*7($tp) + $LD $a7,$SIZE_T*8($tp) + beq .Lsqr8x_tail_break + + addc $acc0,$acc0,$a0 + $LD $a0,$SIZE_T*1($np) + adde $acc1,$acc1,$a1 + $LD $a1,$SIZE_T*2($np) + adde $acc2,$acc2,$a2 + $LD $a2,$SIZE_T*3($np) + adde $acc3,$acc3,$a3 + $LD $a3,$SIZE_T*4($np) + adde $acc4,$acc4,$a4 + $LD $a4,$SIZE_T*5($np) + adde $acc5,$acc5,$a5 + $LD $a5,$SIZE_T*6($np) + adde $acc6,$acc6,$a6 + $LD $a6,$SIZE_T*7($np) + adde $acc7,$acc7,$a7 + $LDU $a7,$SIZE_T*8($np) + #addze $carry,$zero # moved above + b .Lsqr8x_tail + +.align 5 +.Lsqr8x_tail_break: + $POP $n0,$SIZE_T*8($sp) # pull n0 + $POP $t3,$SIZE_T*9($sp) # &tp[2*num-1] + addi $cnt,$tp,$SIZE_T*8 # end of current t[num] window + + addic $carry,$carry,-1 # "move" top-most carry to carry bit + adde $t0,$acc0,$a0 + $LD $acc0,$SIZE_T*8($rp) + $LD $a0,$SIZE_T*1($t2) # recall that $t2 is &n[-1] + adde $t1,$acc1,$a1 + $LD $acc1,$SIZE_T*9($rp) + $LD $a1,$SIZE_T*2($t2) + adde $acc2,$acc2,$a2 + $LD $a2,$SIZE_T*3($t2) + adde $acc3,$acc3,$a3 + $LD $a3,$SIZE_T*4($t2) + adde $acc4,$acc4,$a4 + $LD $a4,$SIZE_T*5($t2) + adde $acc5,$acc5,$a5 + $LD $a5,$SIZE_T*6($t2) + adde $acc6,$acc6,$a6 + $LD $a6,$SIZE_T*7($t2) + adde $acc7,$acc7,$a7 + $LD $a7,$SIZE_T*8($t2) + addi $np,$t2,$SIZE_T*8 + addze $t2,$zero # top-most carry + $UMULL $na0,$n0,$acc0 + $ST $t0,$SIZE_T*1($tp) + $UCMP $cnt,$t3 # did we hit the bottom? + $ST $t1,$SIZE_T*2($tp) + li $cnt,8 + $ST $acc2,$SIZE_T*3($tp) + $LD $acc2,$SIZE_T*10($rp) + $ST $acc3,$SIZE_T*4($tp) + $LD $acc3,$SIZE_T*11($rp) + $ST $acc4,$SIZE_T*5($tp) + $LD $acc4,$SIZE_T*12($rp) + $ST $acc5,$SIZE_T*6($tp) + $LD $acc5,$SIZE_T*13($rp) + $ST $acc6,$SIZE_T*7($tp) + $LD $acc6,$SIZE_T*14($rp) + $ST $acc7,$SIZE_T*8($tp) + $LD $acc7,$SIZE_T*15($rp) + $PUSH $t2,$SIZE_T*10($sp) # off-load top-most carry + addi $tp,$rp,$SIZE_T*7 # slide the window + mtctr $cnt + bne .Lsqr8x_reduction + + ################################################################ + # Final step. We see if result is larger than modulus, and + # if it is, subtract the modulus. But comparison implies + # subtraction. So we subtract modulus, see if it borrowed, + # and conditionally copy original value. + $POP $rp,$SIZE_T*6($sp) # pull &rp[-1] + srwi $cnt,$num,`log($SIZE_T)/log(2)+3` + mr $n0,$tp # put tp aside + addi $tp,$tp,$SIZE_T*8 + subi $cnt,$cnt,1 + subfc $t0,$a0,$acc0 + subfe $t1,$a1,$acc1 + mr $carry,$t2 + mr $ap_end,$rp # $rp copy + + mtctr $cnt + b .Lsqr8x_sub + +.align 5 +.Lsqr8x_sub: + $LD $a0,$SIZE_T*1($np) + $LD $acc0,$SIZE_T*1($tp) + $LD $a1,$SIZE_T*2($np) + $LD $acc1,$SIZE_T*2($tp) + subfe $t2,$a2,$acc2 + $LD $a2,$SIZE_T*3($np) + $LD $acc2,$SIZE_T*3($tp) + subfe $t3,$a3,$acc3 + $LD $a3,$SIZE_T*4($np) + $LD $acc3,$SIZE_T*4($tp) + $ST $t0,$SIZE_T*1($rp) + subfe $t0,$a4,$acc4 + $LD $a4,$SIZE_T*5($np) + $LD $acc4,$SIZE_T*5($tp) + $ST $t1,$SIZE_T*2($rp) + subfe $t1,$a5,$acc5 + $LD $a5,$SIZE_T*6($np) + $LD $acc5,$SIZE_T*6($tp) + $ST $t2,$SIZE_T*3($rp) + subfe $t2,$a6,$acc6 + $LD $a6,$SIZE_T*7($np) + $LD $acc6,$SIZE_T*7($tp) + $ST $t3,$SIZE_T*4($rp) + subfe $t3,$a7,$acc7 + $LDU $a7,$SIZE_T*8($np) + $LDU $acc7,$SIZE_T*8($tp) + $ST $t0,$SIZE_T*5($rp) + subfe $t0,$a0,$acc0 + $ST $t1,$SIZE_T*6($rp) + subfe $t1,$a1,$acc1 + $ST $t2,$SIZE_T*7($rp) + $STU $t3,$SIZE_T*8($rp) + bdnz .Lsqr8x_sub + + srwi $cnt,$num,`log($SIZE_T)/log(2)+2` + $LD $a0,$SIZE_T*1($ap_end) # original $rp + $LD $acc0,$SIZE_T*1($n0) # original $tp + subi $cnt,$cnt,1 + $LD $a1,$SIZE_T*2($ap_end) + $LD $acc1,$SIZE_T*2($n0) + subfe $t2,$a2,$acc2 + $LD $a2,$SIZE_T*3($ap_end) + $LD $acc2,$SIZE_T*3($n0) + subfe $t3,$a3,$acc3 + $LD $a3,$SIZE_T*4($ap_end) + $LDU $acc3,$SIZE_T*4($n0) + $ST $t0,$SIZE_T*1($rp) + subfe $t0,$a4,$acc4 + $ST $t1,$SIZE_T*2($rp) + subfe $t1,$a5,$acc5 + $ST $t2,$SIZE_T*3($rp) + subfe $t2,$a6,$acc6 + $ST $t3,$SIZE_T*4($rp) + subfe $t3,$a7,$acc7 + $ST $t0,$SIZE_T*5($rp) + subfe $carry,$zero,$carry # did it borrow? + $ST $t1,$SIZE_T*6($rp) + $ST $t2,$SIZE_T*7($rp) + $ST $t3,$SIZE_T*8($rp) + + addi $tp,$sp,$SIZE_T*11 + mtctr $cnt + +.Lsqr4x_cond_copy: + andc $a0,$a0,$carry + $ST $zero,-$SIZE_T*3($n0) # wipe stack clean + and $acc0,$acc0,$carry + $ST $zero,-$SIZE_T*2($n0) + andc $a1,$a1,$carry + $ST $zero,-$SIZE_T*1($n0) + and $acc1,$acc1,$carry + $ST $zero,-$SIZE_T*0($n0) + andc $a2,$a2,$carry + $ST $zero,$SIZE_T*1($tp) + and $acc2,$acc2,$carry + $ST $zero,$SIZE_T*2($tp) + andc $a3,$a3,$carry + $ST $zero,$SIZE_T*3($tp) + and $acc3,$acc3,$carry + $STU $zero,$SIZE_T*4($tp) + or $t0,$a0,$acc0 + $LD $a0,$SIZE_T*5($ap_end) + $LD $acc0,$SIZE_T*1($n0) + or $t1,$a1,$acc1 + $LD $a1,$SIZE_T*6($ap_end) + $LD $acc1,$SIZE_T*2($n0) + or $t2,$a2,$acc2 + $LD $a2,$SIZE_T*7($ap_end) + $LD $acc2,$SIZE_T*3($n0) + or $t3,$a3,$acc3 + $LD $a3,$SIZE_T*8($ap_end) + $LDU $acc3,$SIZE_T*4($n0) + $ST $t0,$SIZE_T*1($ap_end) + $ST $t1,$SIZE_T*2($ap_end) + $ST $t2,$SIZE_T*3($ap_end) + $STU $t3,$SIZE_T*4($ap_end) + bdnz .Lsqr4x_cond_copy + + $POP $ap,0($sp) # pull saved sp + andc $a0,$a0,$carry + and $acc0,$acc0,$carry + andc $a1,$a1,$carry + and $acc1,$acc1,$carry + andc $a2,$a2,$carry + and $acc2,$acc2,$carry + andc $a3,$a3,$carry + and $acc3,$acc3,$carry + or $t0,$a0,$acc0 + or $t1,$a1,$acc1 + or $t2,$a2,$acc2 + or $t3,$a3,$acc3 + $ST $t0,$SIZE_T*1($ap_end) + $ST $t1,$SIZE_T*2($ap_end) + $ST $t2,$SIZE_T*3($ap_end) + $ST $t3,$SIZE_T*4($ap_end) + + b .Lsqr8x_done + +.align 5 +.Lsqr8x8_post_condition: + $POP $rp,$SIZE_T*6($sp) # pull rp + $POP $ap,0($sp) # pull saved sp + addze $carry,$zero + + # $acc0-7,$carry hold result, $a0-7 hold modulus + subfc $acc0,$a0,$acc0 + subfe $acc1,$a1,$acc1 + $ST $zero,$SIZE_T*12($sp) # wipe stack clean + $ST $zero,$SIZE_T*13($sp) + subfe $acc2,$a2,$acc2 + $ST $zero,$SIZE_T*14($sp) + $ST $zero,$SIZE_T*15($sp) + subfe $acc3,$a3,$acc3 + $ST $zero,$SIZE_T*16($sp) + $ST $zero,$SIZE_T*17($sp) + subfe $acc4,$a4,$acc4 + $ST $zero,$SIZE_T*18($sp) + $ST $zero,$SIZE_T*19($sp) + subfe $acc5,$a5,$acc5 + $ST $zero,$SIZE_T*20($sp) + $ST $zero,$SIZE_T*21($sp) + subfe $acc6,$a6,$acc6 + $ST $zero,$SIZE_T*22($sp) + $ST $zero,$SIZE_T*23($sp) + subfe $acc7,$a7,$acc7 + $ST $zero,$SIZE_T*24($sp) + $ST $zero,$SIZE_T*25($sp) + subfe $carry,$zero,$carry # did it borrow? + $ST $zero,$SIZE_T*26($sp) + $ST $zero,$SIZE_T*27($sp) + + and $a0,$a0,$carry + and $a1,$a1,$carry + addc $acc0,$acc0,$a0 # add modulus back if borrowed + and $a2,$a2,$carry + adde $acc1,$acc1,$a1 + and $a3,$a3,$carry + adde $acc2,$acc2,$a2 + and $a4,$a4,$carry + adde $acc3,$acc3,$a3 + and $a5,$a5,$carry + adde $acc4,$acc4,$a4 + and $a6,$a6,$carry + adde $acc5,$acc5,$a5 + and $a7,$a7,$carry + adde $acc6,$acc6,$a6 + adde $acc7,$acc7,$a7 + $ST $acc0,$SIZE_T*1($rp) + $ST $acc1,$SIZE_T*2($rp) + $ST $acc2,$SIZE_T*3($rp) + $ST $acc3,$SIZE_T*4($rp) + $ST $acc4,$SIZE_T*5($rp) + $ST $acc5,$SIZE_T*6($rp) + $ST $acc6,$SIZE_T*7($rp) + $ST $acc7,$SIZE_T*8($rp) + +.Lsqr8x_done: + $PUSH $zero,$SIZE_T*8($sp) + $PUSH $zero,$SIZE_T*10($sp) + + $POP r14,-$SIZE_T*18($ap) + li r3,1 # signal "done" + $POP r15,-$SIZE_T*17($ap) + $POP r16,-$SIZE_T*16($ap) + $POP r17,-$SIZE_T*15($ap) + $POP r18,-$SIZE_T*14($ap) + $POP r19,-$SIZE_T*13($ap) + $POP r20,-$SIZE_T*12($ap) + $POP r21,-$SIZE_T*11($ap) + $POP r22,-$SIZE_T*10($ap) + $POP r23,-$SIZE_T*9($ap) + $POP r24,-$SIZE_T*8($ap) + $POP r25,-$SIZE_T*7($ap) + $POP r26,-$SIZE_T*6($ap) + $POP r27,-$SIZE_T*5($ap) + $POP r28,-$SIZE_T*4($ap) + $POP r29,-$SIZE_T*3($ap) + $POP r30,-$SIZE_T*2($ap) + $POP r31,-$SIZE_T*1($ap) + mr $sp,$ap + blr + .long 0 + .byte 0,12,4,0x20,0x80,18,6,0 + .long 0 +.size __bn_sqr8x_mont,.-__bn_sqr8x_mont +___ +} +$code.=<<___; +.asciz "Montgomery Multiplication for PPC, CRYPTOGAMS by " +___ + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/ppc.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/ppc.pl new file mode 100644 index 000000000..e37068192 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/ppc.pl @@ -0,0 +1,2011 @@ +#! /usr/bin/env perl +# Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# Implemented as a Perl wrapper as we want to support several different +# architectures with single file. We pick up the target based on the +# file name we are asked to generate. +# +# It should be noted though that this perl code is nothing like +# /crypto/perlasm/x86*. In this case perl is used pretty much +# as pre-processor to cover for platform differences in name decoration, +# linker tables, 32-/64-bit instruction sets... +# +# As you might know there're several PowerPC ABI in use. Most notably +# Linux and AIX use different 32-bit ABIs. Good news are that these ABIs +# are similar enough to implement leaf(!) functions, which would be ABI +# neutral. And that's what you find here: ABI neutral leaf functions. +# In case you wonder what that is... +# +# AIX performance +# +# MEASUREMENTS WITH cc ON a 200 MhZ PowerPC 604e. +# +# The following is the performance of 32-bit compiler +# generated code: +# +# OpenSSL 0.9.6c 21 dec 2001 +# built on: Tue Jun 11 11:06:51 EDT 2002 +# options:bn(64,32) ... +#compiler: cc -DTHREADS -DAIX -DB_ENDIAN -DBN_LLONG -O3 +# sign verify sign/s verify/s +#rsa 512 bits 0.0098s 0.0009s 102.0 1170.6 +#rsa 1024 bits 0.0507s 0.0026s 19.7 387.5 +#rsa 2048 bits 0.3036s 0.0085s 3.3 117.1 +#rsa 4096 bits 2.0040s 0.0299s 0.5 33.4 +#dsa 512 bits 0.0087s 0.0106s 114.3 94.5 +#dsa 1024 bits 0.0256s 0.0313s 39.0 32.0 +# +# Same benchmark with this assembler code: +# +#rsa 512 bits 0.0056s 0.0005s 178.6 2049.2 +#rsa 1024 bits 0.0283s 0.0015s 35.3 674.1 +#rsa 2048 bits 0.1744s 0.0050s 5.7 201.2 +#rsa 4096 bits 1.1644s 0.0179s 0.9 55.7 +#dsa 512 bits 0.0052s 0.0062s 191.6 162.0 +#dsa 1024 bits 0.0149s 0.0180s 67.0 55.5 +# +# Number of operations increases by at almost 75% +# +# Here are performance numbers for 64-bit compiler +# generated code: +# +# OpenSSL 0.9.6g [engine] 9 Aug 2002 +# built on: Fri Apr 18 16:59:20 EDT 2003 +# options:bn(64,64) ... +# compiler: cc -DTHREADS -D_REENTRANT -q64 -DB_ENDIAN -O3 +# sign verify sign/s verify/s +#rsa 512 bits 0.0028s 0.0003s 357.1 3844.4 +#rsa 1024 bits 0.0148s 0.0008s 67.5 1239.7 +#rsa 2048 bits 0.0963s 0.0028s 10.4 353.0 +#rsa 4096 bits 0.6538s 0.0102s 1.5 98.1 +#dsa 512 bits 0.0026s 0.0032s 382.5 313.7 +#dsa 1024 bits 0.0081s 0.0099s 122.8 100.6 +# +# Same benchmark with this assembler code: +# +#rsa 512 bits 0.0020s 0.0002s 510.4 6273.7 +#rsa 1024 bits 0.0088s 0.0005s 114.1 2128.3 +#rsa 2048 bits 0.0540s 0.0016s 18.5 622.5 +#rsa 4096 bits 0.3700s 0.0058s 2.7 171.0 +#dsa 512 bits 0.0016s 0.0020s 610.7 507.1 +#dsa 1024 bits 0.0047s 0.0058s 212.5 173.2 +# +# Again, performance increases by at about 75% +# +# Mac OS X, Apple G5 1.8GHz (Note this is 32 bit code) +# OpenSSL 0.9.7c 30 Sep 2003 +# +# Original code. +# +#rsa 512 bits 0.0011s 0.0001s 906.1 11012.5 +#rsa 1024 bits 0.0060s 0.0003s 166.6 3363.1 +#rsa 2048 bits 0.0370s 0.0010s 27.1 982.4 +#rsa 4096 bits 0.2426s 0.0036s 4.1 280.4 +#dsa 512 bits 0.0010s 0.0012s 1038.1 841.5 +#dsa 1024 bits 0.0030s 0.0037s 329.6 269.7 +#dsa 2048 bits 0.0101s 0.0127s 98.9 78.6 +# +# Same benchmark with this assembler code: +# +#rsa 512 bits 0.0007s 0.0001s 1416.2 16645.9 +#rsa 1024 bits 0.0036s 0.0002s 274.4 5380.6 +#rsa 2048 bits 0.0222s 0.0006s 45.1 1589.5 +#rsa 4096 bits 0.1469s 0.0022s 6.8 449.6 +#dsa 512 bits 0.0006s 0.0007s 1664.2 1376.2 +#dsa 1024 bits 0.0018s 0.0023s 545.0 442.2 +#dsa 2048 bits 0.0061s 0.0075s 163.5 132.8 +# +# Performance increase of ~60% +# Based on submission from Suresh N. Chari of IBM + +$flavour = shift; + +if ($flavour =~ /32/) { + $BITS= 32; + $BNSZ= $BITS/8; + $ISA= "\"ppc\""; + + $LD= "lwz"; # load + $LDU= "lwzu"; # load and update + $ST= "stw"; # store + $STU= "stwu"; # store and update + $UMULL= "mullw"; # unsigned multiply low + $UMULH= "mulhwu"; # unsigned multiply high + $UDIV= "divwu"; # unsigned divide + $UCMPI= "cmplwi"; # unsigned compare with immediate + $UCMP= "cmplw"; # unsigned compare + $CNTLZ= "cntlzw"; # count leading zeros + $SHL= "slw"; # shift left + $SHR= "srw"; # unsigned shift right + $SHRI= "srwi"; # unsigned shift right by immediate + $SHLI= "slwi"; # shift left by immediate + $CLRU= "clrlwi"; # clear upper bits + $INSR= "insrwi"; # insert right + $ROTL= "rotlwi"; # rotate left by immediate + $TR= "tw"; # conditional trap +} elsif ($flavour =~ /64/) { + $BITS= 64; + $BNSZ= $BITS/8; + $ISA= "\"ppc64\""; + + # same as above, but 64-bit mnemonics... + $LD= "ld"; # load + $LDU= "ldu"; # load and update + $ST= "std"; # store + $STU= "stdu"; # store and update + $UMULL= "mulld"; # unsigned multiply low + $UMULH= "mulhdu"; # unsigned multiply high + $UDIV= "divdu"; # unsigned divide + $UCMPI= "cmpldi"; # unsigned compare with immediate + $UCMP= "cmpld"; # unsigned compare + $CNTLZ= "cntlzd"; # count leading zeros + $SHL= "sld"; # shift left + $SHR= "srd"; # unsigned shift right + $SHRI= "srdi"; # unsigned shift right by immediate + $SHLI= "sldi"; # shift left by immediate + $CLRU= "clrldi"; # clear upper bits + $INSR= "insrdi"; # insert right + $ROTL= "rotldi"; # rotate left by immediate + $TR= "td"; # conditional trap +} else { die "nonsense $flavour"; } + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or +die "can't locate ppc-xlate.pl"; + +open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!"; + +$data=< 0 then result !=0 + # In either case carry bit is set. + beq Lppcasm_sub_adios + addi r4,r4,-$BNSZ + addi r3,r3,-$BNSZ + addi r5,r5,-$BNSZ + mtctr r6 +Lppcasm_sub_mainloop: + $LDU r7,$BNSZ(r4) + $LDU r8,$BNSZ(r5) + subfe r6,r8,r7 # r6 = r7+carry bit + onescomplement(r8) + # if carry = 1 this is r7-r8. Else it + # is r7-r8 -1 as we need. + $STU r6,$BNSZ(r3) + bdnz Lppcasm_sub_mainloop +Lppcasm_sub_adios: + subfze r3,r0 # if carry bit is set then r3 = 0 else -1 + andi. r3,r3,1 # keep only last bit. + blr + .long 0 + .byte 0,12,0x14,0,0,0,4,0 + .long 0 +.size .bn_sub_words,.-.bn_sub_words + +# +# NOTE: The following label name should be changed to +# "bn_add_words" i.e. remove the first dot +# for the gcc compiler. This should be automatically +# done in the build +# + +.align 4 +.bn_add_words: +# +# Handcoded version of bn_add_words +# +#BN_ULONG bn_add_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) +# +# r3 = r +# r4 = a +# r5 = b +# r6 = n +# +# Note: No loop unrolling done since this is not a performance +# critical loop. + + xor r0,r0,r0 +# +# check for r6 = 0. Is this needed? +# + addic. r6,r6,0 #test r6 and clear carry bit. + beq Lppcasm_add_adios + addi r4,r4,-$BNSZ + addi r3,r3,-$BNSZ + addi r5,r5,-$BNSZ + mtctr r6 +Lppcasm_add_mainloop: + $LDU r7,$BNSZ(r4) + $LDU r8,$BNSZ(r5) + adde r8,r7,r8 + $STU r8,$BNSZ(r3) + bdnz Lppcasm_add_mainloop +Lppcasm_add_adios: + addze r3,r0 #return carry bit. + blr + .long 0 + .byte 0,12,0x14,0,0,0,4,0 + .long 0 +.size .bn_add_words,.-.bn_add_words + +# +# NOTE: The following label name should be changed to +# "bn_div_words" i.e. remove the first dot +# for the gcc compiler. This should be automatically +# done in the build +# + +.align 4 +.bn_div_words: +# +# This is a cleaned up version of code generated by +# the AIX compiler. The only optimization is to use +# the PPC instruction to count leading zeros instead +# of call to num_bits_word. Since this was compiled +# only at level -O2 we can possibly squeeze it more? +# +# r3 = h +# r4 = l +# r5 = d + + $UCMPI 0,r5,0 # compare r5 and 0 + bne Lppcasm_div1 # proceed if d!=0 + li r3,-1 # d=0 return -1 + blr +Lppcasm_div1: + xor r0,r0,r0 #r0=0 + li r8,$BITS + $CNTLZ. r7,r5 #r7 = num leading 0s in d. + beq Lppcasm_div2 #proceed if no leading zeros + subf r8,r7,r8 #r8 = BN_num_bits_word(d) + $SHR. r9,r3,r8 #are there any bits above r8'th? + $TR 16,r9,r0 #if there're, signal to dump core... +Lppcasm_div2: + $UCMP 0,r3,r5 #h>=d? + blt Lppcasm_div3 #goto Lppcasm_div3 if not + subf r3,r5,r3 #h-=d ; +Lppcasm_div3: #r7 = BN_BITS2-i. so r7=i + cmpi 0,0,r7,0 # is (i == 0)? + beq Lppcasm_div4 + $SHL r3,r3,r7 # h = (h<< i) + $SHR r8,r4,r8 # r8 = (l >> BN_BITS2 -i) + $SHL r5,r5,r7 # d<<=i + or r3,r3,r8 # h = (h<>(BN_BITS2-i)) + $SHL r4,r4,r7 # l <<=i +Lppcasm_div4: + $SHRI r9,r5,`$BITS/2` # r9 = dh + # dl will be computed when needed + # as it saves registers. + li r6,2 #r6=2 + mtctr r6 #counter will be in count. +Lppcasm_divouterloop: + $SHRI r8,r3,`$BITS/2` #r8 = (h>>BN_BITS4) + $SHRI r11,r4,`$BITS/2` #r11= (l&BN_MASK2h)>>BN_BITS4 + # compute here for innerloop. + $UCMP 0,r8,r9 # is (h>>BN_BITS4)==dh + bne Lppcasm_div5 # goto Lppcasm_div5 if not + + li r8,-1 + $CLRU r8,r8,`$BITS/2` #q = BN_MASK2l + b Lppcasm_div6 +Lppcasm_div5: + $UDIV r8,r3,r9 #q = h/dh +Lppcasm_div6: + $UMULL r12,r9,r8 #th = q*dh + $CLRU r10,r5,`$BITS/2` #r10=dl + $UMULL r6,r8,r10 #tl = q*dl + +Lppcasm_divinnerloop: + subf r10,r12,r3 #t = h -th + $SHRI r7,r10,`$BITS/2` #r7= (t &BN_MASK2H), sort of... + addic. r7,r7,0 #test if r7 == 0. used below. + # now want to compute + # r7 = (t<>BN_BITS4) + # the following 2 instructions do that + $SHLI r7,r10,`$BITS/2` # r7 = (t<>BN_BITS4) + $UCMP cr1,r6,r7 # compare (tl <= r7) + bne Lppcasm_divinnerexit + ble cr1,Lppcasm_divinnerexit + addi r8,r8,-1 #q-- + subf r12,r9,r12 #th -=dh + $CLRU r10,r5,`$BITS/2` #r10=dl. t is no longer needed in loop. + subf r6,r10,r6 #tl -=dl + b Lppcasm_divinnerloop +Lppcasm_divinnerexit: + $SHRI r10,r6,`$BITS/2` #t=(tl>>BN_BITS4) + $SHLI r11,r6,`$BITS/2` #tl=(tl<=tl) goto Lppcasm_div7 + addi r12,r12,1 # th++ +Lppcasm_div7: + subf r11,r11,r4 #r11=l-tl + $UCMP cr1,r3,r12 #compare h and th + bge cr1,Lppcasm_div8 #if (h>=th) goto Lppcasm_div8 + addi r8,r8,-1 # q-- + add r3,r5,r3 # h+=d +Lppcasm_div8: + subf r12,r12,r3 #r12 = h-th + $SHLI r4,r11,`$BITS/2` #l=(l&BN_MASK2l)<>BN_BITS4))&BN_MASK2 + # the following 2 instructions will do this. + $INSR r11,r12,`$BITS/2`,`$BITS/2` # r11 is the value we want rotated $BITS/2. + $ROTL r3,r11,`$BITS/2` # rotate by $BITS/2 and store in r3 + bdz Lppcasm_div9 #if (count==0) break ; + $SHLI r0,r8,`$BITS/2` #ret =q<> 2 + beq Lppcasm_mw_REM + mtctr r7 +Lppcasm_mw_LOOP: + #mul(rp[0],ap[0],w,c1); + $LD r8,`0*$BNSZ`(r4) + $UMULL r9,r6,r8 + $UMULH r10,r6,r8 + addc r9,r9,r12 + #addze r10,r10 #carry is NOT ignored. + #will be taken care of + #in second spin below + #using adde. + $ST r9,`0*$BNSZ`(r3) + #mul(rp[1],ap[1],w,c1); + $LD r8,`1*$BNSZ`(r4) + $UMULL r11,r6,r8 + $UMULH r12,r6,r8 + adde r11,r11,r10 + #addze r12,r12 + $ST r11,`1*$BNSZ`(r3) + #mul(rp[2],ap[2],w,c1); + $LD r8,`2*$BNSZ`(r4) + $UMULL r9,r6,r8 + $UMULH r10,r6,r8 + adde r9,r9,r12 + #addze r10,r10 + $ST r9,`2*$BNSZ`(r3) + #mul_add(rp[3],ap[3],w,c1); + $LD r8,`3*$BNSZ`(r4) + $UMULL r11,r6,r8 + $UMULH r12,r6,r8 + adde r11,r11,r10 + addze r12,r12 #this spin we collect carry into + #r12 + $ST r11,`3*$BNSZ`(r3) + + addi r3,r3,`4*$BNSZ` + addi r4,r4,`4*$BNSZ` + bdnz Lppcasm_mw_LOOP + +Lppcasm_mw_REM: + andi. r5,r5,0x3 + beq Lppcasm_mw_OVER + #mul(rp[0],ap[0],w,c1); + $LD r8,`0*$BNSZ`(r4) + $UMULL r9,r6,r8 + $UMULH r10,r6,r8 + addc r9,r9,r12 + addze r10,r10 + $ST r9,`0*$BNSZ`(r3) + addi r12,r10,0 + + addi r5,r5,-1 + cmpli 0,0,r5,0 + beq Lppcasm_mw_OVER + + + #mul(rp[1],ap[1],w,c1); + $LD r8,`1*$BNSZ`(r4) + $UMULL r9,r6,r8 + $UMULH r10,r6,r8 + addc r9,r9,r12 + addze r10,r10 + $ST r9,`1*$BNSZ`(r3) + addi r12,r10,0 + + addi r5,r5,-1 + cmpli 0,0,r5,0 + beq Lppcasm_mw_OVER + + #mul_add(rp[2],ap[2],w,c1); + $LD r8,`2*$BNSZ`(r4) + $UMULL r9,r6,r8 + $UMULH r10,r6,r8 + addc r9,r9,r12 + addze r10,r10 + $ST r9,`2*$BNSZ`(r3) + addi r12,r10,0 + +Lppcasm_mw_OVER: + addi r3,r12,0 + blr + .long 0 + .byte 0,12,0x14,0,0,0,4,0 + .long 0 +.size .bn_mul_words,.-.bn_mul_words + +# +# NOTE: The following label name should be changed to +# "bn_mul_add_words" i.e. remove the first dot +# for the gcc compiler. This should be automatically +# done in the build +# + +.align 4 +.bn_mul_add_words: +# +# BN_ULONG bn_mul_add_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w) +# +# r3 = rp +# r4 = ap +# r5 = num +# r6 = w +# +# empirical evidence suggests that unrolled version performs best!! +# + xor r0,r0,r0 #r0 = 0 + xor r12,r12,r12 #r12 = 0 . used for carry + rlwinm. r7,r5,30,2,31 # num >> 2 + beq Lppcasm_maw_leftover # if (num < 4) go LPPCASM_maw_leftover + mtctr r7 +Lppcasm_maw_mainloop: + #mul_add(rp[0],ap[0],w,c1); + $LD r8,`0*$BNSZ`(r4) + $LD r11,`0*$BNSZ`(r3) + $UMULL r9,r6,r8 + $UMULH r10,r6,r8 + addc r9,r9,r12 #r12 is carry. + addze r10,r10 + addc r9,r9,r11 + #addze r10,r10 + #the above instruction addze + #is NOT needed. Carry will NOT + #be ignored. It's not affected + #by multiply and will be collected + #in the next spin + $ST r9,`0*$BNSZ`(r3) + + #mul_add(rp[1],ap[1],w,c1); + $LD r8,`1*$BNSZ`(r4) + $LD r9,`1*$BNSZ`(r3) + $UMULL r11,r6,r8 + $UMULH r12,r6,r8 + adde r11,r11,r10 #r10 is carry. + addze r12,r12 + addc r11,r11,r9 + #addze r12,r12 + $ST r11,`1*$BNSZ`(r3) + + #mul_add(rp[2],ap[2],w,c1); + $LD r8,`2*$BNSZ`(r4) + $UMULL r9,r6,r8 + $LD r11,`2*$BNSZ`(r3) + $UMULH r10,r6,r8 + adde r9,r9,r12 + addze r10,r10 + addc r9,r9,r11 + #addze r10,r10 + $ST r9,`2*$BNSZ`(r3) + + #mul_add(rp[3],ap[3],w,c1); + $LD r8,`3*$BNSZ`(r4) + $UMULL r11,r6,r8 + $LD r9,`3*$BNSZ`(r3) + $UMULH r12,r6,r8 + adde r11,r11,r10 + addze r12,r12 + addc r11,r11,r9 + addze r12,r12 + $ST r11,`3*$BNSZ`(r3) + addi r3,r3,`4*$BNSZ` + addi r4,r4,`4*$BNSZ` + bdnz Lppcasm_maw_mainloop + +Lppcasm_maw_leftover: + andi. r5,r5,0x3 + beq Lppcasm_maw_adios + addi r3,r3,-$BNSZ + addi r4,r4,-$BNSZ + #mul_add(rp[0],ap[0],w,c1); + mtctr r5 + $LDU r8,$BNSZ(r4) + $UMULL r9,r6,r8 + $UMULH r10,r6,r8 + $LDU r11,$BNSZ(r3) + addc r9,r9,r11 + addze r10,r10 + addc r9,r9,r12 + addze r12,r10 + $ST r9,0(r3) + + bdz Lppcasm_maw_adios + #mul_add(rp[1],ap[1],w,c1); + $LDU r8,$BNSZ(r4) + $UMULL r9,r6,r8 + $UMULH r10,r6,r8 + $LDU r11,$BNSZ(r3) + addc r9,r9,r11 + addze r10,r10 + addc r9,r9,r12 + addze r12,r10 + $ST r9,0(r3) + + bdz Lppcasm_maw_adios + #mul_add(rp[2],ap[2],w,c1); + $LDU r8,$BNSZ(r4) + $UMULL r9,r6,r8 + $UMULH r10,r6,r8 + $LDU r11,$BNSZ(r3) + addc r9,r9,r11 + addze r10,r10 + addc r9,r9,r12 + addze r12,r10 + $ST r9,0(r3) + +Lppcasm_maw_adios: + addi r3,r12,0 + blr + .long 0 + .byte 0,12,0x14,0,0,0,4,0 + .long 0 +.size .bn_mul_add_words,.-.bn_mul_add_words + .align 4 +EOF +$data =~ s/\`([^\`]*)\`/eval $1/gem; +print $data; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/ppc64-mont.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/ppc64-mont.pl new file mode 100644 index 000000000..c41b620bc --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/ppc64-mont.pl @@ -0,0 +1,1652 @@ +#! /usr/bin/env perl +# Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# December 2007 + +# The reason for undertaken effort is basically following. Even though +# Power 6 CPU operates at incredible 4.7GHz clock frequency, its PKI +# performance was observed to be less than impressive, essentially as +# fast as 1.8GHz PPC970, or 2.6 times(!) slower than one would hope. +# Well, it's not surprising that IBM had to make some sacrifices to +# boost the clock frequency that much, but no overall improvement? +# Having observed how much difference did switching to FPU make on +# UltraSPARC, playing same stunt on Power 6 appeared appropriate... +# Unfortunately the resulting performance improvement is not as +# impressive, ~30%, and in absolute terms is still very far from what +# one would expect from 4.7GHz CPU. There is a chance that I'm doing +# something wrong, but in the lack of assembler level micro-profiling +# data or at least decent platform guide I can't tell... Or better +# results might be achieved with VMX... Anyway, this module provides +# *worse* performance on other PowerPC implementations, ~40-15% slower +# on PPC970 depending on key length and ~40% slower on Power 5 for all +# key lengths. As it's obviously inappropriate as "best all-round" +# alternative, it has to be complemented with run-time CPU family +# detection. Oh! It should also be noted that unlike other PowerPC +# implementation IALU ppc-mont.pl module performs *suboptimally* on +# >=1024-bit key lengths on Power 6. It should also be noted that +# *everything* said so far applies to 64-bit builds! As far as 32-bit +# application executed on 64-bit CPU goes, this module is likely to +# become preferred choice, because it's easy to adapt it for such +# case and *is* faster than 32-bit ppc-mont.pl on *all* processors. + +# February 2008 + +# Micro-profiling assisted optimization results in ~15% improvement +# over original ppc64-mont.pl version, or overall ~50% improvement +# over ppc.pl module on Power 6. If compared to ppc-mont.pl on same +# Power 6 CPU, this module is 5-150% faster depending on key length, +# [hereafter] more for longer keys. But if compared to ppc-mont.pl +# on 1.8GHz PPC970, it's only 5-55% faster. Still far from impressive +# in absolute terms, but it's apparently the way Power 6 is... + +# December 2009 + +# Adapted for 32-bit build this module delivers 25-120%, yes, more +# than *twice* for longer keys, performance improvement over 32-bit +# ppc-mont.pl on 1.8GHz PPC970. However! This implementation utilizes +# even 64-bit integer operations and the trouble is that most PPC +# operating systems don't preserve upper halves of general purpose +# registers upon 32-bit signal delivery. They do preserve them upon +# context switch, but not signalling:-( This means that asynchronous +# signals have to be blocked upon entry to this subroutine. Signal +# masking (and of course complementary unmasking) has quite an impact +# on performance, naturally larger for shorter keys. It's so severe +# that 512-bit key performance can be as low as 1/3 of expected one. +# This is why this routine can be engaged for longer key operations +# only on these OSes, see crypto/ppccap.c for further details. MacOS X +# is an exception from this and doesn't require signal masking, and +# that's where above improvement coefficients were collected. For +# others alternative would be to break dependence on upper halves of +# GPRs by sticking to 32-bit integer operations... + +# December 2012 + +# Remove above mentioned dependence on GPRs' upper halves in 32-bit +# build. No signal masking overhead, but integer instructions are +# *more* numerous... It's still "universally" faster than 32-bit +# ppc-mont.pl, but improvement coefficient is not as impressive +# for longer keys... + +$flavour = shift; + +if ($flavour =~ /32/) { + $SIZE_T=4; + $RZONE= 224; + $fname= "bn_mul_mont_fpu64"; + + $STUX= "stwux"; # store indexed and update + $PUSH= "stw"; + $POP= "lwz"; +} elsif ($flavour =~ /64/) { + $SIZE_T=8; + $RZONE= 288; + $fname= "bn_mul_mont_fpu64"; + + # same as above, but 64-bit mnemonics... + $STUX= "stdux"; # store indexed and update + $PUSH= "std"; + $POP= "ld"; +} else { die "nonsense $flavour"; } + +$LITTLE_ENDIAN = ($flavour=~/le$/) ? 4 : 0; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or +die "can't locate ppc-xlate.pl"; + +open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!"; + +$FRAME=64; # padded frame header +$TRANSFER=16*8; + +$carry="r0"; +$sp="r1"; +$toc="r2"; +$rp="r3"; $ovf="r3"; +$ap="r4"; +$bp="r5"; +$np="r6"; +$n0="r7"; +$num="r8"; +$rp="r9"; # $rp is reassigned +$tp="r10"; +$j="r11"; +$i="r12"; +# non-volatile registers +$c1="r19"; +$n1="r20"; +$a1="r21"; +$nap_d="r22"; # interleaved ap and np in double format +$a0="r23"; # ap[0] +$t0="r24"; # temporary registers +$t1="r25"; +$t2="r26"; +$t3="r27"; +$t4="r28"; +$t5="r29"; +$t6="r30"; +$t7="r31"; + +# PPC offers enough register bank capacity to unroll inner loops twice +# +# ..A3A2A1A0 +# dcba +# ----------- +# A0a +# A0b +# A0c +# A0d +# A1a +# A1b +# A1c +# A1d +# A2a +# A2b +# A2c +# A2d +# A3a +# A3b +# A3c +# A3d +# ..a +# ..b +# +$ba="f0"; $bb="f1"; $bc="f2"; $bd="f3"; +$na="f4"; $nb="f5"; $nc="f6"; $nd="f7"; +$dota="f8"; $dotb="f9"; +$A0="f10"; $A1="f11"; $A2="f12"; $A3="f13"; +$N0="f20"; $N1="f21"; $N2="f22"; $N3="f23"; +$T0a="f24"; $T0b="f25"; +$T1a="f26"; $T1b="f27"; +$T2a="f28"; $T2b="f29"; +$T3a="f30"; $T3b="f31"; + +# sp----------->+-------------------------------+ +# | saved sp | +# +-------------------------------+ +# . . +# +64 +-------------------------------+ +# | 16 gpr<->fpr transfer zone | +# . . +# . . +# +16*8 +-------------------------------+ +# | __int64 tmp[-1] | +# +-------------------------------+ +# | __int64 tmp[num] | +# . . +# . . +# . . +# +(num+1)*8 +-------------------------------+ +# | padding to 64 byte boundary | +# . . +# +X +-------------------------------+ +# | double nap_d[4*num] | +# . . +# . . +# . . +# +-------------------------------+ +# . . +# -13*size_t +-------------------------------+ +# | 13 saved gpr, r19-r31 | +# . . +# . . +# -12*8 +-------------------------------+ +# | 12 saved fpr, f20-f31 | +# . . +# . . +# +-------------------------------+ + +$code=<<___; +.machine "any" +.text + +.globl .$fname +.align 5 +.$fname: + cmpwi $num,`3*8/$SIZE_T` + mr $rp,r3 ; $rp is reassigned + li r3,0 ; possible "not handled" return code + bltlr- + andi. r0,$num,`16/$SIZE_T-1` ; $num has to be "even" + bnelr- + + slwi $num,$num,`log($SIZE_T)/log(2)` ; num*=sizeof(BN_LONG) + li $i,-4096 + slwi $tp,$num,2 ; place for {an}p_{lh}[num], i.e. 4*num + add $tp,$tp,$num ; place for tp[num+1] + addi $tp,$tp,`$FRAME+$TRANSFER+8+64+$RZONE` + subf $tp,$tp,$sp ; $sp-$tp + and $tp,$tp,$i ; minimize TLB usage + subf $tp,$sp,$tp ; $tp-$sp + mr $i,$sp + $STUX $sp,$sp,$tp ; alloca + + $PUSH r19,`-12*8-13*$SIZE_T`($i) + $PUSH r20,`-12*8-12*$SIZE_T`($i) + $PUSH r21,`-12*8-11*$SIZE_T`($i) + $PUSH r22,`-12*8-10*$SIZE_T`($i) + $PUSH r23,`-12*8-9*$SIZE_T`($i) + $PUSH r24,`-12*8-8*$SIZE_T`($i) + $PUSH r25,`-12*8-7*$SIZE_T`($i) + $PUSH r26,`-12*8-6*$SIZE_T`($i) + $PUSH r27,`-12*8-5*$SIZE_T`($i) + $PUSH r28,`-12*8-4*$SIZE_T`($i) + $PUSH r29,`-12*8-3*$SIZE_T`($i) + $PUSH r30,`-12*8-2*$SIZE_T`($i) + $PUSH r31,`-12*8-1*$SIZE_T`($i) + stfd f20,`-12*8`($i) + stfd f21,`-11*8`($i) + stfd f22,`-10*8`($i) + stfd f23,`-9*8`($i) + stfd f24,`-8*8`($i) + stfd f25,`-7*8`($i) + stfd f26,`-6*8`($i) + stfd f27,`-5*8`($i) + stfd f28,`-4*8`($i) + stfd f29,`-3*8`($i) + stfd f30,`-2*8`($i) + stfd f31,`-1*8`($i) + + addi $tp,$sp,`$FRAME+$TRANSFER+8+64` + li $i,-64 + add $nap_d,$tp,$num + and $nap_d,$nap_d,$i ; align to 64 bytes + ; nap_d is off by 1, because it's used with stfdu/lfdu + addi $nap_d,$nap_d,-8 + srwi $j,$num,`3+1` ; counter register, num/2 + addi $j,$j,-1 + addi $tp,$sp,`$FRAME+$TRANSFER-8` + li $carry,0 + mtctr $j +___ + +$code.=<<___ if ($SIZE_T==8); + ld $a0,0($ap) ; pull ap[0] value + ld $t3,0($bp) ; bp[0] + ld $n0,0($n0) ; pull n0[0] value + + mulld $t7,$a0,$t3 ; ap[0]*bp[0] + ; transfer bp[0] to FPU as 4x16-bit values + extrdi $t0,$t3,16,48 + extrdi $t1,$t3,16,32 + extrdi $t2,$t3,16,16 + extrdi $t3,$t3,16,0 + std $t0,`$FRAME+0`($sp) + std $t1,`$FRAME+8`($sp) + std $t2,`$FRAME+16`($sp) + std $t3,`$FRAME+24`($sp) + + mulld $t7,$t7,$n0 ; tp[0]*n0 + ; transfer (ap[0]*bp[0])*n0 to FPU as 4x16-bit values + extrdi $t4,$t7,16,48 + extrdi $t5,$t7,16,32 + extrdi $t6,$t7,16,16 + extrdi $t7,$t7,16,0 + std $t4,`$FRAME+32`($sp) + std $t5,`$FRAME+40`($sp) + std $t6,`$FRAME+48`($sp) + std $t7,`$FRAME+56`($sp) + + extrdi $t0,$a0,32,32 ; lwz $t0,4($ap) + extrdi $t1,$a0,32,0 ; lwz $t1,0($ap) + lwz $t2,`12^$LITTLE_ENDIAN`($ap) ; load a[1] as 32-bit word pair + lwz $t3,`8^$LITTLE_ENDIAN`($ap) + lwz $t4,`4^$LITTLE_ENDIAN`($np) ; load n[0] as 32-bit word pair + lwz $t5,`0^$LITTLE_ENDIAN`($np) + lwz $t6,`12^$LITTLE_ENDIAN`($np) ; load n[1] as 32-bit word pair + lwz $t7,`8^$LITTLE_ENDIAN`($np) +___ +$code.=<<___ if ($SIZE_T==4); + lwz $a0,0($ap) ; pull ap[0,1] value + mr $n1,$n0 + lwz $a1,4($ap) + li $c1,0 + lwz $t1,0($bp) ; bp[0,1] + lwz $t3,4($bp) + lwz $n0,0($n1) ; pull n0[0,1] value + lwz $n1,4($n1) + + mullw $t4,$a0,$t1 ; mulld ap[0]*bp[0] + mulhwu $t5,$a0,$t1 + mullw $t6,$a1,$t1 + mullw $t7,$a0,$t3 + add $t5,$t5,$t6 + add $t5,$t5,$t7 + ; transfer bp[0] to FPU as 4x16-bit values + extrwi $t0,$t1,16,16 + extrwi $t1,$t1,16,0 + extrwi $t2,$t3,16,16 + extrwi $t3,$t3,16,0 + std $t0,`$FRAME+0`($sp) ; yes, std in 32-bit build + std $t1,`$FRAME+8`($sp) + std $t2,`$FRAME+16`($sp) + std $t3,`$FRAME+24`($sp) + + mullw $t0,$t4,$n0 ; mulld tp[0]*n0 + mulhwu $t1,$t4,$n0 + mullw $t2,$t5,$n0 + mullw $t3,$t4,$n1 + add $t1,$t1,$t2 + add $t1,$t1,$t3 + ; transfer (ap[0]*bp[0])*n0 to FPU as 4x16-bit values + extrwi $t4,$t0,16,16 + extrwi $t5,$t0,16,0 + extrwi $t6,$t1,16,16 + extrwi $t7,$t1,16,0 + std $t4,`$FRAME+32`($sp) ; yes, std in 32-bit build + std $t5,`$FRAME+40`($sp) + std $t6,`$FRAME+48`($sp) + std $t7,`$FRAME+56`($sp) + + mr $t0,$a0 ; lwz $t0,0($ap) + mr $t1,$a1 ; lwz $t1,4($ap) + lwz $t2,8($ap) ; load a[j..j+3] as 32-bit word pairs + lwz $t3,12($ap) + lwz $t4,0($np) ; load n[j..j+3] as 32-bit word pairs + lwz $t5,4($np) + lwz $t6,8($np) + lwz $t7,12($np) +___ +$code.=<<___; + lfd $ba,`$FRAME+0`($sp) + lfd $bb,`$FRAME+8`($sp) + lfd $bc,`$FRAME+16`($sp) + lfd $bd,`$FRAME+24`($sp) + lfd $na,`$FRAME+32`($sp) + lfd $nb,`$FRAME+40`($sp) + lfd $nc,`$FRAME+48`($sp) + lfd $nd,`$FRAME+56`($sp) + std $t0,`$FRAME+64`($sp) ; yes, std even in 32-bit build + std $t1,`$FRAME+72`($sp) + std $t2,`$FRAME+80`($sp) + std $t3,`$FRAME+88`($sp) + std $t4,`$FRAME+96`($sp) + std $t5,`$FRAME+104`($sp) + std $t6,`$FRAME+112`($sp) + std $t7,`$FRAME+120`($sp) + fcfid $ba,$ba + fcfid $bb,$bb + fcfid $bc,$bc + fcfid $bd,$bd + fcfid $na,$na + fcfid $nb,$nb + fcfid $nc,$nc + fcfid $nd,$nd + + lfd $A0,`$FRAME+64`($sp) + lfd $A1,`$FRAME+72`($sp) + lfd $A2,`$FRAME+80`($sp) + lfd $A3,`$FRAME+88`($sp) + lfd $N0,`$FRAME+96`($sp) + lfd $N1,`$FRAME+104`($sp) + lfd $N2,`$FRAME+112`($sp) + lfd $N3,`$FRAME+120`($sp) + fcfid $A0,$A0 + fcfid $A1,$A1 + fcfid $A2,$A2 + fcfid $A3,$A3 + fcfid $N0,$N0 + fcfid $N1,$N1 + fcfid $N2,$N2 + fcfid $N3,$N3 + addi $ap,$ap,16 + addi $np,$np,16 + + fmul $T1a,$A1,$ba + fmul $T1b,$A1,$bb + stfd $A0,8($nap_d) ; save a[j] in double format + stfd $A1,16($nap_d) + fmul $T2a,$A2,$ba + fmul $T2b,$A2,$bb + stfd $A2,24($nap_d) ; save a[j+1] in double format + stfd $A3,32($nap_d) + fmul $T3a,$A3,$ba + fmul $T3b,$A3,$bb + stfd $N0,40($nap_d) ; save n[j] in double format + stfd $N1,48($nap_d) + fmul $T0a,$A0,$ba + fmul $T0b,$A0,$bb + stfd $N2,56($nap_d) ; save n[j+1] in double format + stfdu $N3,64($nap_d) + + fmadd $T1a,$A0,$bc,$T1a + fmadd $T1b,$A0,$bd,$T1b + fmadd $T2a,$A1,$bc,$T2a + fmadd $T2b,$A1,$bd,$T2b + fmadd $T3a,$A2,$bc,$T3a + fmadd $T3b,$A2,$bd,$T3b + fmul $dota,$A3,$bc + fmul $dotb,$A3,$bd + + fmadd $T1a,$N1,$na,$T1a + fmadd $T1b,$N1,$nb,$T1b + fmadd $T2a,$N2,$na,$T2a + fmadd $T2b,$N2,$nb,$T2b + fmadd $T3a,$N3,$na,$T3a + fmadd $T3b,$N3,$nb,$T3b + fmadd $T0a,$N0,$na,$T0a + fmadd $T0b,$N0,$nb,$T0b + + fmadd $T1a,$N0,$nc,$T1a + fmadd $T1b,$N0,$nd,$T1b + fmadd $T2a,$N1,$nc,$T2a + fmadd $T2b,$N1,$nd,$T2b + fmadd $T3a,$N2,$nc,$T3a + fmadd $T3b,$N2,$nd,$T3b + fmadd $dota,$N3,$nc,$dota + fmadd $dotb,$N3,$nd,$dotb + + fctid $T0a,$T0a + fctid $T0b,$T0b + fctid $T1a,$T1a + fctid $T1b,$T1b + fctid $T2a,$T2a + fctid $T2b,$T2b + fctid $T3a,$T3a + fctid $T3b,$T3b + + stfd $T0a,`$FRAME+0`($sp) + stfd $T0b,`$FRAME+8`($sp) + stfd $T1a,`$FRAME+16`($sp) + stfd $T1b,`$FRAME+24`($sp) + stfd $T2a,`$FRAME+32`($sp) + stfd $T2b,`$FRAME+40`($sp) + stfd $T3a,`$FRAME+48`($sp) + stfd $T3b,`$FRAME+56`($sp) + +.align 5 +L1st: +___ +$code.=<<___ if ($SIZE_T==8); + lwz $t0,`4^$LITTLE_ENDIAN`($ap) ; load a[j] as 32-bit word pair + lwz $t1,`0^$LITTLE_ENDIAN`($ap) + lwz $t2,`12^$LITTLE_ENDIAN`($ap) ; load a[j+1] as 32-bit word pair + lwz $t3,`8^$LITTLE_ENDIAN`($ap) + lwz $t4,`4^$LITTLE_ENDIAN`($np) ; load n[j] as 32-bit word pair + lwz $t5,`0^$LITTLE_ENDIAN`($np) + lwz $t6,`12^$LITTLE_ENDIAN`($np) ; load n[j+1] as 32-bit word pair + lwz $t7,`8^$LITTLE_ENDIAN`($np) +___ +$code.=<<___ if ($SIZE_T==4); + lwz $t0,0($ap) ; load a[j..j+3] as 32-bit word pairs + lwz $t1,4($ap) + lwz $t2,8($ap) + lwz $t3,12($ap) + lwz $t4,0($np) ; load n[j..j+3] as 32-bit word pairs + lwz $t5,4($np) + lwz $t6,8($np) + lwz $t7,12($np) +___ +$code.=<<___; + std $t0,`$FRAME+64`($sp) ; yes, std even in 32-bit build + std $t1,`$FRAME+72`($sp) + std $t2,`$FRAME+80`($sp) + std $t3,`$FRAME+88`($sp) + std $t4,`$FRAME+96`($sp) + std $t5,`$FRAME+104`($sp) + std $t6,`$FRAME+112`($sp) + std $t7,`$FRAME+120`($sp) +___ +if ($SIZE_T==8 or $flavour =~ /osx/) { +$code.=<<___; + ld $t0,`$FRAME+0`($sp) + ld $t1,`$FRAME+8`($sp) + ld $t2,`$FRAME+16`($sp) + ld $t3,`$FRAME+24`($sp) + ld $t4,`$FRAME+32`($sp) + ld $t5,`$FRAME+40`($sp) + ld $t6,`$FRAME+48`($sp) + ld $t7,`$FRAME+56`($sp) +___ +} else { +$code.=<<___; + lwz $t1,`$FRAME+0^$LITTLE_ENDIAN`($sp) + lwz $t0,`$FRAME+4^$LITTLE_ENDIAN`($sp) + lwz $t3,`$FRAME+8^$LITTLE_ENDIAN`($sp) + lwz $t2,`$FRAME+12^$LITTLE_ENDIAN`($sp) + lwz $t5,`$FRAME+16^$LITTLE_ENDIAN`($sp) + lwz $t4,`$FRAME+20^$LITTLE_ENDIAN`($sp) + lwz $t7,`$FRAME+24^$LITTLE_ENDIAN`($sp) + lwz $t6,`$FRAME+28^$LITTLE_ENDIAN`($sp) +___ +} +$code.=<<___; + lfd $A0,`$FRAME+64`($sp) + lfd $A1,`$FRAME+72`($sp) + lfd $A2,`$FRAME+80`($sp) + lfd $A3,`$FRAME+88`($sp) + lfd $N0,`$FRAME+96`($sp) + lfd $N1,`$FRAME+104`($sp) + lfd $N2,`$FRAME+112`($sp) + lfd $N3,`$FRAME+120`($sp) + fcfid $A0,$A0 + fcfid $A1,$A1 + fcfid $A2,$A2 + fcfid $A3,$A3 + fcfid $N0,$N0 + fcfid $N1,$N1 + fcfid $N2,$N2 + fcfid $N3,$N3 + addi $ap,$ap,16 + addi $np,$np,16 + + fmul $T1a,$A1,$ba + fmul $T1b,$A1,$bb + fmul $T2a,$A2,$ba + fmul $T2b,$A2,$bb + stfd $A0,8($nap_d) ; save a[j] in double format + stfd $A1,16($nap_d) + fmul $T3a,$A3,$ba + fmul $T3b,$A3,$bb + fmadd $T0a,$A0,$ba,$dota + fmadd $T0b,$A0,$bb,$dotb + stfd $A2,24($nap_d) ; save a[j+1] in double format + stfd $A3,32($nap_d) +___ +if ($SIZE_T==8 or $flavour =~ /osx/) { +$code.=<<___; + fmadd $T1a,$A0,$bc,$T1a + fmadd $T1b,$A0,$bd,$T1b + fmadd $T2a,$A1,$bc,$T2a + fmadd $T2b,$A1,$bd,$T2b + stfd $N0,40($nap_d) ; save n[j] in double format + stfd $N1,48($nap_d) + fmadd $T3a,$A2,$bc,$T3a + fmadd $T3b,$A2,$bd,$T3b + add $t0,$t0,$carry ; can not overflow + fmul $dota,$A3,$bc + fmul $dotb,$A3,$bd + stfd $N2,56($nap_d) ; save n[j+1] in double format + stfdu $N3,64($nap_d) + srdi $carry,$t0,16 + add $t1,$t1,$carry + srdi $carry,$t1,16 + + fmadd $T1a,$N1,$na,$T1a + fmadd $T1b,$N1,$nb,$T1b + insrdi $t0,$t1,16,32 + fmadd $T2a,$N2,$na,$T2a + fmadd $T2b,$N2,$nb,$T2b + add $t2,$t2,$carry + fmadd $T3a,$N3,$na,$T3a + fmadd $T3b,$N3,$nb,$T3b + srdi $carry,$t2,16 + fmadd $T0a,$N0,$na,$T0a + fmadd $T0b,$N0,$nb,$T0b + insrdi $t0,$t2,16,16 + add $t3,$t3,$carry + srdi $carry,$t3,16 + + fmadd $T1a,$N0,$nc,$T1a + fmadd $T1b,$N0,$nd,$T1b + insrdi $t0,$t3,16,0 ; 0..63 bits + fmadd $T2a,$N1,$nc,$T2a + fmadd $T2b,$N1,$nd,$T2b + add $t4,$t4,$carry + fmadd $T3a,$N2,$nc,$T3a + fmadd $T3b,$N2,$nd,$T3b + srdi $carry,$t4,16 + fmadd $dota,$N3,$nc,$dota + fmadd $dotb,$N3,$nd,$dotb + add $t5,$t5,$carry + srdi $carry,$t5,16 + insrdi $t4,$t5,16,32 + + fctid $T0a,$T0a + fctid $T0b,$T0b + add $t6,$t6,$carry + fctid $T1a,$T1a + fctid $T1b,$T1b + srdi $carry,$t6,16 + fctid $T2a,$T2a + fctid $T2b,$T2b + insrdi $t4,$t6,16,16 + fctid $T3a,$T3a + fctid $T3b,$T3b + add $t7,$t7,$carry + insrdi $t4,$t7,16,0 ; 64..127 bits + srdi $carry,$t7,16 ; upper 33 bits + + stfd $T0a,`$FRAME+0`($sp) + stfd $T0b,`$FRAME+8`($sp) + stfd $T1a,`$FRAME+16`($sp) + stfd $T1b,`$FRAME+24`($sp) + stfd $T2a,`$FRAME+32`($sp) + stfd $T2b,`$FRAME+40`($sp) + stfd $T3a,`$FRAME+48`($sp) + stfd $T3b,`$FRAME+56`($sp) + std $t0,8($tp) ; tp[j-1] + stdu $t4,16($tp) ; tp[j] +___ +} else { +$code.=<<___; + fmadd $T1a,$A0,$bc,$T1a + fmadd $T1b,$A0,$bd,$T1b + addc $t0,$t0,$carry + adde $t1,$t1,$c1 + srwi $carry,$t0,16 + fmadd $T2a,$A1,$bc,$T2a + fmadd $T2b,$A1,$bd,$T2b + stfd $N0,40($nap_d) ; save n[j] in double format + stfd $N1,48($nap_d) + srwi $c1,$t1,16 + insrwi $carry,$t1,16,0 + fmadd $T3a,$A2,$bc,$T3a + fmadd $T3b,$A2,$bd,$T3b + addc $t2,$t2,$carry + adde $t3,$t3,$c1 + srwi $carry,$t2,16 + fmul $dota,$A3,$bc + fmul $dotb,$A3,$bd + stfd $N2,56($nap_d) ; save n[j+1] in double format + stfdu $N3,64($nap_d) + insrwi $t0,$t2,16,0 ; 0..31 bits + srwi $c1,$t3,16 + insrwi $carry,$t3,16,0 + + fmadd $T1a,$N1,$na,$T1a + fmadd $T1b,$N1,$nb,$T1b + lwz $t3,`$FRAME+32^$LITTLE_ENDIAN`($sp) ; permuted $t1 + lwz $t2,`$FRAME+36^$LITTLE_ENDIAN`($sp) ; permuted $t0 + addc $t4,$t4,$carry + adde $t5,$t5,$c1 + srwi $carry,$t4,16 + fmadd $T2a,$N2,$na,$T2a + fmadd $T2b,$N2,$nb,$T2b + srwi $c1,$t5,16 + insrwi $carry,$t5,16,0 + fmadd $T3a,$N3,$na,$T3a + fmadd $T3b,$N3,$nb,$T3b + addc $t6,$t6,$carry + adde $t7,$t7,$c1 + srwi $carry,$t6,16 + fmadd $T0a,$N0,$na,$T0a + fmadd $T0b,$N0,$nb,$T0b + insrwi $t4,$t6,16,0 ; 32..63 bits + srwi $c1,$t7,16 + insrwi $carry,$t7,16,0 + + fmadd $T1a,$N0,$nc,$T1a + fmadd $T1b,$N0,$nd,$T1b + lwz $t7,`$FRAME+40^$LITTLE_ENDIAN`($sp) ; permuted $t3 + lwz $t6,`$FRAME+44^$LITTLE_ENDIAN`($sp) ; permuted $t2 + addc $t2,$t2,$carry + adde $t3,$t3,$c1 + srwi $carry,$t2,16 + fmadd $T2a,$N1,$nc,$T2a + fmadd $T2b,$N1,$nd,$T2b + stw $t0,12($tp) ; tp[j-1] + stw $t4,8($tp) + srwi $c1,$t3,16 + insrwi $carry,$t3,16,0 + fmadd $T3a,$N2,$nc,$T3a + fmadd $T3b,$N2,$nd,$T3b + lwz $t1,`$FRAME+48^$LITTLE_ENDIAN`($sp) ; permuted $t5 + lwz $t0,`$FRAME+52^$LITTLE_ENDIAN`($sp) ; permuted $t4 + addc $t6,$t6,$carry + adde $t7,$t7,$c1 + srwi $carry,$t6,16 + fmadd $dota,$N3,$nc,$dota + fmadd $dotb,$N3,$nd,$dotb + insrwi $t2,$t6,16,0 ; 64..95 bits + srwi $c1,$t7,16 + insrwi $carry,$t7,16,0 + + fctid $T0a,$T0a + fctid $T0b,$T0b + lwz $t5,`$FRAME+56^$LITTLE_ENDIAN`($sp) ; permuted $t7 + lwz $t4,`$FRAME+60^$LITTLE_ENDIAN`($sp) ; permuted $t6 + addc $t0,$t0,$carry + adde $t1,$t1,$c1 + srwi $carry,$t0,16 + fctid $T1a,$T1a + fctid $T1b,$T1b + srwi $c1,$t1,16 + insrwi $carry,$t1,16,0 + fctid $T2a,$T2a + fctid $T2b,$T2b + addc $t4,$t4,$carry + adde $t5,$t5,$c1 + srwi $carry,$t4,16 + fctid $T3a,$T3a + fctid $T3b,$T3b + insrwi $t0,$t4,16,0 ; 96..127 bits + srwi $c1,$t5,16 + insrwi $carry,$t5,16,0 + + stfd $T0a,`$FRAME+0`($sp) + stfd $T0b,`$FRAME+8`($sp) + stfd $T1a,`$FRAME+16`($sp) + stfd $T1b,`$FRAME+24`($sp) + stfd $T2a,`$FRAME+32`($sp) + stfd $T2b,`$FRAME+40`($sp) + stfd $T3a,`$FRAME+48`($sp) + stfd $T3b,`$FRAME+56`($sp) + stw $t2,20($tp) ; tp[j] + stwu $t0,16($tp) +___ +} +$code.=<<___; + bdnz L1st + + fctid $dota,$dota + fctid $dotb,$dotb +___ +if ($SIZE_T==8 or $flavour =~ /osx/) { +$code.=<<___; + ld $t0,`$FRAME+0`($sp) + ld $t1,`$FRAME+8`($sp) + ld $t2,`$FRAME+16`($sp) + ld $t3,`$FRAME+24`($sp) + ld $t4,`$FRAME+32`($sp) + ld $t5,`$FRAME+40`($sp) + ld $t6,`$FRAME+48`($sp) + ld $t7,`$FRAME+56`($sp) + stfd $dota,`$FRAME+64`($sp) + stfd $dotb,`$FRAME+72`($sp) + + add $t0,$t0,$carry ; can not overflow + srdi $carry,$t0,16 + add $t1,$t1,$carry + srdi $carry,$t1,16 + insrdi $t0,$t1,16,32 + add $t2,$t2,$carry + srdi $carry,$t2,16 + insrdi $t0,$t2,16,16 + add $t3,$t3,$carry + srdi $carry,$t3,16 + insrdi $t0,$t3,16,0 ; 0..63 bits + add $t4,$t4,$carry + srdi $carry,$t4,16 + add $t5,$t5,$carry + srdi $carry,$t5,16 + insrdi $t4,$t5,16,32 + add $t6,$t6,$carry + srdi $carry,$t6,16 + insrdi $t4,$t6,16,16 + add $t7,$t7,$carry + insrdi $t4,$t7,16,0 ; 64..127 bits + srdi $carry,$t7,16 ; upper 33 bits + ld $t6,`$FRAME+64`($sp) + ld $t7,`$FRAME+72`($sp) + + std $t0,8($tp) ; tp[j-1] + stdu $t4,16($tp) ; tp[j] + + add $t6,$t6,$carry ; can not overflow + srdi $carry,$t6,16 + add $t7,$t7,$carry + insrdi $t6,$t7,48,0 + srdi $ovf,$t7,48 + std $t6,8($tp) ; tp[num-1] +___ +} else { +$code.=<<___; + lwz $t1,`$FRAME+0^$LITTLE_ENDIAN`($sp) + lwz $t0,`$FRAME+4^$LITTLE_ENDIAN`($sp) + lwz $t3,`$FRAME+8^$LITTLE_ENDIAN`($sp) + lwz $t2,`$FRAME+12^$LITTLE_ENDIAN`($sp) + lwz $t5,`$FRAME+16^$LITTLE_ENDIAN`($sp) + lwz $t4,`$FRAME+20^$LITTLE_ENDIAN`($sp) + lwz $t7,`$FRAME+24^$LITTLE_ENDIAN`($sp) + lwz $t6,`$FRAME+28^$LITTLE_ENDIAN`($sp) + stfd $dota,`$FRAME+64`($sp) + stfd $dotb,`$FRAME+72`($sp) + + addc $t0,$t0,$carry + adde $t1,$t1,$c1 + srwi $carry,$t0,16 + insrwi $carry,$t1,16,0 + srwi $c1,$t1,16 + addc $t2,$t2,$carry + adde $t3,$t3,$c1 + srwi $carry,$t2,16 + insrwi $t0,$t2,16,0 ; 0..31 bits + insrwi $carry,$t3,16,0 + srwi $c1,$t3,16 + addc $t4,$t4,$carry + adde $t5,$t5,$c1 + srwi $carry,$t4,16 + insrwi $carry,$t5,16,0 + srwi $c1,$t5,16 + addc $t6,$t6,$carry + adde $t7,$t7,$c1 + srwi $carry,$t6,16 + insrwi $t4,$t6,16,0 ; 32..63 bits + insrwi $carry,$t7,16,0 + srwi $c1,$t7,16 + stw $t0,12($tp) ; tp[j-1] + stw $t4,8($tp) + + lwz $t3,`$FRAME+32^$LITTLE_ENDIAN`($sp) ; permuted $t1 + lwz $t2,`$FRAME+36^$LITTLE_ENDIAN`($sp) ; permuted $t0 + lwz $t7,`$FRAME+40^$LITTLE_ENDIAN`($sp) ; permuted $t3 + lwz $t6,`$FRAME+44^$LITTLE_ENDIAN`($sp) ; permuted $t2 + lwz $t1,`$FRAME+48^$LITTLE_ENDIAN`($sp) ; permuted $t5 + lwz $t0,`$FRAME+52^$LITTLE_ENDIAN`($sp) ; permuted $t4 + lwz $t5,`$FRAME+56^$LITTLE_ENDIAN`($sp) ; permuted $t7 + lwz $t4,`$FRAME+60^$LITTLE_ENDIAN`($sp) ; permuted $t6 + + addc $t2,$t2,$carry + adde $t3,$t3,$c1 + srwi $carry,$t2,16 + insrwi $carry,$t3,16,0 + srwi $c1,$t3,16 + addc $t6,$t6,$carry + adde $t7,$t7,$c1 + srwi $carry,$t6,16 + insrwi $t2,$t6,16,0 ; 64..95 bits + insrwi $carry,$t7,16,0 + srwi $c1,$t7,16 + addc $t0,$t0,$carry + adde $t1,$t1,$c1 + srwi $carry,$t0,16 + insrwi $carry,$t1,16,0 + srwi $c1,$t1,16 + addc $t4,$t4,$carry + adde $t5,$t5,$c1 + srwi $carry,$t4,16 + insrwi $t0,$t4,16,0 ; 96..127 bits + insrwi $carry,$t5,16,0 + srwi $c1,$t5,16 + stw $t2,20($tp) ; tp[j] + stwu $t0,16($tp) + + lwz $t7,`$FRAME+64^$LITTLE_ENDIAN`($sp) + lwz $t6,`$FRAME+68^$LITTLE_ENDIAN`($sp) + lwz $t5,`$FRAME+72^$LITTLE_ENDIAN`($sp) + lwz $t4,`$FRAME+76^$LITTLE_ENDIAN`($sp) + + addc $t6,$t6,$carry + adde $t7,$t7,$c1 + srwi $carry,$t6,16 + insrwi $carry,$t7,16,0 + srwi $c1,$t7,16 + addc $t4,$t4,$carry + adde $t5,$t5,$c1 + + insrwi $t6,$t4,16,0 + srwi $t4,$t4,16 + insrwi $t4,$t5,16,0 + srwi $ovf,$t5,16 + stw $t6,12($tp) ; tp[num-1] + stw $t4,8($tp) +___ +} +$code.=<<___; + slwi $t7,$num,2 + subf $nap_d,$t7,$nap_d ; rewind pointer + + li $i,8 ; i=1 +.align 5 +Louter: + addi $tp,$sp,`$FRAME+$TRANSFER` + li $carry,0 + mtctr $j +___ +$code.=<<___ if ($SIZE_T==8); + ldx $t3,$bp,$i ; bp[i] + + ld $t6,`$FRAME+$TRANSFER+8`($sp) ; tp[0] + mulld $t7,$a0,$t3 ; ap[0]*bp[i] + add $t7,$t7,$t6 ; ap[0]*bp[i]+tp[0] + ; transfer bp[i] to FPU as 4x16-bit values + extrdi $t0,$t3,16,48 + extrdi $t1,$t3,16,32 + extrdi $t2,$t3,16,16 + extrdi $t3,$t3,16,0 + std $t0,`$FRAME+0`($sp) + std $t1,`$FRAME+8`($sp) + std $t2,`$FRAME+16`($sp) + std $t3,`$FRAME+24`($sp) + + mulld $t7,$t7,$n0 ; tp[0]*n0 + ; transfer (ap[0]*bp[i]+tp[0])*n0 to FPU as 4x16-bit values + extrdi $t4,$t7,16,48 + extrdi $t5,$t7,16,32 + extrdi $t6,$t7,16,16 + extrdi $t7,$t7,16,0 + std $t4,`$FRAME+32`($sp) + std $t5,`$FRAME+40`($sp) + std $t6,`$FRAME+48`($sp) + std $t7,`$FRAME+56`($sp) +___ +$code.=<<___ if ($SIZE_T==4); + add $t0,$bp,$i + li $c1,0 + lwz $t1,0($t0) ; bp[i,i+1] + lwz $t3,4($t0) + + mullw $t4,$a0,$t1 ; ap[0]*bp[i] + lwz $t0,`$FRAME+$TRANSFER+8+4`($sp) ; tp[0] + mulhwu $t5,$a0,$t1 + lwz $t2,`$FRAME+$TRANSFER+8`($sp) ; tp[0] + mullw $t6,$a1,$t1 + mullw $t7,$a0,$t3 + add $t5,$t5,$t6 + add $t5,$t5,$t7 + addc $t4,$t4,$t0 ; ap[0]*bp[i]+tp[0] + adde $t5,$t5,$t2 + ; transfer bp[i] to FPU as 4x16-bit values + extrwi $t0,$t1,16,16 + extrwi $t1,$t1,16,0 + extrwi $t2,$t3,16,16 + extrwi $t3,$t3,16,0 + std $t0,`$FRAME+0`($sp) ; yes, std in 32-bit build + std $t1,`$FRAME+8`($sp) + std $t2,`$FRAME+16`($sp) + std $t3,`$FRAME+24`($sp) + + mullw $t0,$t4,$n0 ; mulld tp[0]*n0 + mulhwu $t1,$t4,$n0 + mullw $t2,$t5,$n0 + mullw $t3,$t4,$n1 + add $t1,$t1,$t2 + add $t1,$t1,$t3 + ; transfer (ap[0]*bp[i]+tp[0])*n0 to FPU as 4x16-bit values + extrwi $t4,$t0,16,16 + extrwi $t5,$t0,16,0 + extrwi $t6,$t1,16,16 + extrwi $t7,$t1,16,0 + std $t4,`$FRAME+32`($sp) ; yes, std in 32-bit build + std $t5,`$FRAME+40`($sp) + std $t6,`$FRAME+48`($sp) + std $t7,`$FRAME+56`($sp) +___ +$code.=<<___; + lfd $A0,8($nap_d) ; load a[j] in double format + lfd $A1,16($nap_d) + lfd $A2,24($nap_d) ; load a[j+1] in double format + lfd $A3,32($nap_d) + lfd $N0,40($nap_d) ; load n[j] in double format + lfd $N1,48($nap_d) + lfd $N2,56($nap_d) ; load n[j+1] in double format + lfdu $N3,64($nap_d) + + lfd $ba,`$FRAME+0`($sp) + lfd $bb,`$FRAME+8`($sp) + lfd $bc,`$FRAME+16`($sp) + lfd $bd,`$FRAME+24`($sp) + lfd $na,`$FRAME+32`($sp) + lfd $nb,`$FRAME+40`($sp) + lfd $nc,`$FRAME+48`($sp) + lfd $nd,`$FRAME+56`($sp) + + fcfid $ba,$ba + fcfid $bb,$bb + fcfid $bc,$bc + fcfid $bd,$bd + fcfid $na,$na + fcfid $nb,$nb + fcfid $nc,$nc + fcfid $nd,$nd + + fmul $T1a,$A1,$ba + fmul $T1b,$A1,$bb + fmul $T2a,$A2,$ba + fmul $T2b,$A2,$bb + fmul $T3a,$A3,$ba + fmul $T3b,$A3,$bb + fmul $T0a,$A0,$ba + fmul $T0b,$A0,$bb + + fmadd $T1a,$A0,$bc,$T1a + fmadd $T1b,$A0,$bd,$T1b + fmadd $T2a,$A1,$bc,$T2a + fmadd $T2b,$A1,$bd,$T2b + fmadd $T3a,$A2,$bc,$T3a + fmadd $T3b,$A2,$bd,$T3b + fmul $dota,$A3,$bc + fmul $dotb,$A3,$bd + + fmadd $T1a,$N1,$na,$T1a + fmadd $T1b,$N1,$nb,$T1b + lfd $A0,8($nap_d) ; load a[j] in double format + lfd $A1,16($nap_d) + fmadd $T2a,$N2,$na,$T2a + fmadd $T2b,$N2,$nb,$T2b + lfd $A2,24($nap_d) ; load a[j+1] in double format + lfd $A3,32($nap_d) + fmadd $T3a,$N3,$na,$T3a + fmadd $T3b,$N3,$nb,$T3b + fmadd $T0a,$N0,$na,$T0a + fmadd $T0b,$N0,$nb,$T0b + + fmadd $T1a,$N0,$nc,$T1a + fmadd $T1b,$N0,$nd,$T1b + fmadd $T2a,$N1,$nc,$T2a + fmadd $T2b,$N1,$nd,$T2b + fmadd $T3a,$N2,$nc,$T3a + fmadd $T3b,$N2,$nd,$T3b + fmadd $dota,$N3,$nc,$dota + fmadd $dotb,$N3,$nd,$dotb + + fctid $T0a,$T0a + fctid $T0b,$T0b + fctid $T1a,$T1a + fctid $T1b,$T1b + fctid $T2a,$T2a + fctid $T2b,$T2b + fctid $T3a,$T3a + fctid $T3b,$T3b + + stfd $T0a,`$FRAME+0`($sp) + stfd $T0b,`$FRAME+8`($sp) + stfd $T1a,`$FRAME+16`($sp) + stfd $T1b,`$FRAME+24`($sp) + stfd $T2a,`$FRAME+32`($sp) + stfd $T2b,`$FRAME+40`($sp) + stfd $T3a,`$FRAME+48`($sp) + stfd $T3b,`$FRAME+56`($sp) + +.align 5 +Linner: + fmul $T1a,$A1,$ba + fmul $T1b,$A1,$bb + fmul $T2a,$A2,$ba + fmul $T2b,$A2,$bb + lfd $N0,40($nap_d) ; load n[j] in double format + lfd $N1,48($nap_d) + fmul $T3a,$A3,$ba + fmul $T3b,$A3,$bb + fmadd $T0a,$A0,$ba,$dota + fmadd $T0b,$A0,$bb,$dotb + lfd $N2,56($nap_d) ; load n[j+1] in double format + lfdu $N3,64($nap_d) + + fmadd $T1a,$A0,$bc,$T1a + fmadd $T1b,$A0,$bd,$T1b + fmadd $T2a,$A1,$bc,$T2a + fmadd $T2b,$A1,$bd,$T2b + lfd $A0,8($nap_d) ; load a[j] in double format + lfd $A1,16($nap_d) + fmadd $T3a,$A2,$bc,$T3a + fmadd $T3b,$A2,$bd,$T3b + fmul $dota,$A3,$bc + fmul $dotb,$A3,$bd + lfd $A2,24($nap_d) ; load a[j+1] in double format + lfd $A3,32($nap_d) +___ +if ($SIZE_T==8 or $flavour =~ /osx/) { +$code.=<<___; + fmadd $T1a,$N1,$na,$T1a + fmadd $T1b,$N1,$nb,$T1b + ld $t0,`$FRAME+0`($sp) + ld $t1,`$FRAME+8`($sp) + fmadd $T2a,$N2,$na,$T2a + fmadd $T2b,$N2,$nb,$T2b + ld $t2,`$FRAME+16`($sp) + ld $t3,`$FRAME+24`($sp) + fmadd $T3a,$N3,$na,$T3a + fmadd $T3b,$N3,$nb,$T3b + add $t0,$t0,$carry ; can not overflow + ld $t4,`$FRAME+32`($sp) + ld $t5,`$FRAME+40`($sp) + fmadd $T0a,$N0,$na,$T0a + fmadd $T0b,$N0,$nb,$T0b + srdi $carry,$t0,16 + add $t1,$t1,$carry + srdi $carry,$t1,16 + ld $t6,`$FRAME+48`($sp) + ld $t7,`$FRAME+56`($sp) + + fmadd $T1a,$N0,$nc,$T1a + fmadd $T1b,$N0,$nd,$T1b + insrdi $t0,$t1,16,32 + ld $t1,8($tp) ; tp[j] + fmadd $T2a,$N1,$nc,$T2a + fmadd $T2b,$N1,$nd,$T2b + add $t2,$t2,$carry + fmadd $T3a,$N2,$nc,$T3a + fmadd $T3b,$N2,$nd,$T3b + srdi $carry,$t2,16 + insrdi $t0,$t2,16,16 + fmadd $dota,$N3,$nc,$dota + fmadd $dotb,$N3,$nd,$dotb + add $t3,$t3,$carry + ldu $t2,16($tp) ; tp[j+1] + srdi $carry,$t3,16 + insrdi $t0,$t3,16,0 ; 0..63 bits + add $t4,$t4,$carry + + fctid $T0a,$T0a + fctid $T0b,$T0b + srdi $carry,$t4,16 + fctid $T1a,$T1a + fctid $T1b,$T1b + add $t5,$t5,$carry + fctid $T2a,$T2a + fctid $T2b,$T2b + srdi $carry,$t5,16 + insrdi $t4,$t5,16,32 + fctid $T3a,$T3a + fctid $T3b,$T3b + add $t6,$t6,$carry + srdi $carry,$t6,16 + insrdi $t4,$t6,16,16 + + stfd $T0a,`$FRAME+0`($sp) + stfd $T0b,`$FRAME+8`($sp) + add $t7,$t7,$carry + addc $t3,$t0,$t1 +___ +$code.=<<___ if ($SIZE_T==4); # adjust XER[CA] + extrdi $t0,$t0,32,0 + extrdi $t1,$t1,32,0 + adde $t0,$t0,$t1 +___ +$code.=<<___; + stfd $T1a,`$FRAME+16`($sp) + stfd $T1b,`$FRAME+24`($sp) + insrdi $t4,$t7,16,0 ; 64..127 bits + srdi $carry,$t7,16 ; upper 33 bits + stfd $T2a,`$FRAME+32`($sp) + stfd $T2b,`$FRAME+40`($sp) + adde $t5,$t4,$t2 +___ +$code.=<<___ if ($SIZE_T==4); # adjust XER[CA] + extrdi $t4,$t4,32,0 + extrdi $t2,$t2,32,0 + adde $t4,$t4,$t2 +___ +$code.=<<___; + stfd $T3a,`$FRAME+48`($sp) + stfd $T3b,`$FRAME+56`($sp) + addze $carry,$carry + std $t3,-16($tp) ; tp[j-1] + std $t5,-8($tp) ; tp[j] +___ +} else { +$code.=<<___; + fmadd $T1a,$N1,$na,$T1a + fmadd $T1b,$N1,$nb,$T1b + lwz $t1,`$FRAME+0^$LITTLE_ENDIAN`($sp) + lwz $t0,`$FRAME+4^$LITTLE_ENDIAN`($sp) + fmadd $T2a,$N2,$na,$T2a + fmadd $T2b,$N2,$nb,$T2b + lwz $t3,`$FRAME+8^$LITTLE_ENDIAN`($sp) + lwz $t2,`$FRAME+12^$LITTLE_ENDIAN`($sp) + fmadd $T3a,$N3,$na,$T3a + fmadd $T3b,$N3,$nb,$T3b + lwz $t5,`$FRAME+16^$LITTLE_ENDIAN`($sp) + lwz $t4,`$FRAME+20^$LITTLE_ENDIAN`($sp) + addc $t0,$t0,$carry + adde $t1,$t1,$c1 + srwi $carry,$t0,16 + fmadd $T0a,$N0,$na,$T0a + fmadd $T0b,$N0,$nb,$T0b + lwz $t7,`$FRAME+24^$LITTLE_ENDIAN`($sp) + lwz $t6,`$FRAME+28^$LITTLE_ENDIAN`($sp) + srwi $c1,$t1,16 + insrwi $carry,$t1,16,0 + + fmadd $T1a,$N0,$nc,$T1a + fmadd $T1b,$N0,$nd,$T1b + addc $t2,$t2,$carry + adde $t3,$t3,$c1 + srwi $carry,$t2,16 + fmadd $T2a,$N1,$nc,$T2a + fmadd $T2b,$N1,$nd,$T2b + insrwi $t0,$t2,16,0 ; 0..31 bits + srwi $c1,$t3,16 + insrwi $carry,$t3,16,0 + fmadd $T3a,$N2,$nc,$T3a + fmadd $T3b,$N2,$nd,$T3b + lwz $t2,12($tp) ; tp[j] + lwz $t3,8($tp) + addc $t4,$t4,$carry + adde $t5,$t5,$c1 + srwi $carry,$t4,16 + fmadd $dota,$N3,$nc,$dota + fmadd $dotb,$N3,$nd,$dotb + srwi $c1,$t5,16 + insrwi $carry,$t5,16,0 + + fctid $T0a,$T0a + addc $t6,$t6,$carry + adde $t7,$t7,$c1 + srwi $carry,$t6,16 + fctid $T0b,$T0b + insrwi $t4,$t6,16,0 ; 32..63 bits + srwi $c1,$t7,16 + insrwi $carry,$t7,16,0 + fctid $T1a,$T1a + addc $t0,$t0,$t2 + adde $t4,$t4,$t3 + lwz $t3,`$FRAME+32^$LITTLE_ENDIAN`($sp) ; permuted $t1 + lwz $t2,`$FRAME+36^$LITTLE_ENDIAN`($sp) ; permuted $t0 + fctid $T1b,$T1b + addze $carry,$carry + addze $c1,$c1 + stw $t0,4($tp) ; tp[j-1] + stw $t4,0($tp) + fctid $T2a,$T2a + addc $t2,$t2,$carry + adde $t3,$t3,$c1 + srwi $carry,$t2,16 + lwz $t7,`$FRAME+40^$LITTLE_ENDIAN`($sp) ; permuted $t3 + lwz $t6,`$FRAME+44^$LITTLE_ENDIAN`($sp) ; permuted $t2 + fctid $T2b,$T2b + srwi $c1,$t3,16 + insrwi $carry,$t3,16,0 + lwz $t1,`$FRAME+48^$LITTLE_ENDIAN`($sp) ; permuted $t5 + lwz $t0,`$FRAME+52^$LITTLE_ENDIAN`($sp) ; permuted $t4 + fctid $T3a,$T3a + addc $t6,$t6,$carry + adde $t7,$t7,$c1 + srwi $carry,$t6,16 + lwz $t5,`$FRAME+56^$LITTLE_ENDIAN`($sp) ; permuted $t7 + lwz $t4,`$FRAME+60^$LITTLE_ENDIAN`($sp) ; permuted $t6 + fctid $T3b,$T3b + + insrwi $t2,$t6,16,0 ; 64..95 bits + insrwi $carry,$t7,16,0 + srwi $c1,$t7,16 + lwz $t6,20($tp) + lwzu $t7,16($tp) + addc $t0,$t0,$carry + stfd $T0a,`$FRAME+0`($sp) + adde $t1,$t1,$c1 + srwi $carry,$t0,16 + stfd $T0b,`$FRAME+8`($sp) + insrwi $carry,$t1,16,0 + srwi $c1,$t1,16 + addc $t4,$t4,$carry + stfd $T1a,`$FRAME+16`($sp) + adde $t5,$t5,$c1 + srwi $carry,$t4,16 + insrwi $t0,$t4,16,0 ; 96..127 bits + stfd $T1b,`$FRAME+24`($sp) + insrwi $carry,$t5,16,0 + srwi $c1,$t5,16 + + addc $t2,$t2,$t6 + stfd $T2a,`$FRAME+32`($sp) + adde $t0,$t0,$t7 + stfd $T2b,`$FRAME+40`($sp) + addze $carry,$carry + stfd $T3a,`$FRAME+48`($sp) + addze $c1,$c1 + stfd $T3b,`$FRAME+56`($sp) + stw $t2,-4($tp) ; tp[j] + stw $t0,-8($tp) +___ +} +$code.=<<___; + bdnz Linner + + fctid $dota,$dota + fctid $dotb,$dotb +___ +if ($SIZE_T==8 or $flavour =~ /osx/) { +$code.=<<___; + ld $t0,`$FRAME+0`($sp) + ld $t1,`$FRAME+8`($sp) + ld $t2,`$FRAME+16`($sp) + ld $t3,`$FRAME+24`($sp) + ld $t4,`$FRAME+32`($sp) + ld $t5,`$FRAME+40`($sp) + ld $t6,`$FRAME+48`($sp) + ld $t7,`$FRAME+56`($sp) + stfd $dota,`$FRAME+64`($sp) + stfd $dotb,`$FRAME+72`($sp) + + add $t0,$t0,$carry ; can not overflow + srdi $carry,$t0,16 + add $t1,$t1,$carry + srdi $carry,$t1,16 + insrdi $t0,$t1,16,32 + add $t2,$t2,$carry + ld $t1,8($tp) ; tp[j] + srdi $carry,$t2,16 + insrdi $t0,$t2,16,16 + add $t3,$t3,$carry + ldu $t2,16($tp) ; tp[j+1] + srdi $carry,$t3,16 + insrdi $t0,$t3,16,0 ; 0..63 bits + add $t4,$t4,$carry + srdi $carry,$t4,16 + add $t5,$t5,$carry + srdi $carry,$t5,16 + insrdi $t4,$t5,16,32 + add $t6,$t6,$carry + srdi $carry,$t6,16 + insrdi $t4,$t6,16,16 + add $t7,$t7,$carry + insrdi $t4,$t7,16,0 ; 64..127 bits + srdi $carry,$t7,16 ; upper 33 bits + ld $t6,`$FRAME+64`($sp) + ld $t7,`$FRAME+72`($sp) + + addc $t3,$t0,$t1 +___ +$code.=<<___ if ($SIZE_T==4); # adjust XER[CA] + extrdi $t0,$t0,32,0 + extrdi $t1,$t1,32,0 + adde $t0,$t0,$t1 +___ +$code.=<<___; + adde $t5,$t4,$t2 +___ +$code.=<<___ if ($SIZE_T==4); # adjust XER[CA] + extrdi $t4,$t4,32,0 + extrdi $t2,$t2,32,0 + adde $t4,$t4,$t2 +___ +$code.=<<___; + addze $carry,$carry + + std $t3,-16($tp) ; tp[j-1] + std $t5,-8($tp) ; tp[j] + + add $carry,$carry,$ovf ; consume upmost overflow + add $t6,$t6,$carry ; can not overflow + srdi $carry,$t6,16 + add $t7,$t7,$carry + insrdi $t6,$t7,48,0 + srdi $ovf,$t7,48 + std $t6,0($tp) ; tp[num-1] +___ +} else { +$code.=<<___; + lwz $t1,`$FRAME+0^$LITTLE_ENDIAN`($sp) + lwz $t0,`$FRAME+4^$LITTLE_ENDIAN`($sp) + lwz $t3,`$FRAME+8^$LITTLE_ENDIAN`($sp) + lwz $t2,`$FRAME+12^$LITTLE_ENDIAN`($sp) + lwz $t5,`$FRAME+16^$LITTLE_ENDIAN`($sp) + lwz $t4,`$FRAME+20^$LITTLE_ENDIAN`($sp) + lwz $t7,`$FRAME+24^$LITTLE_ENDIAN`($sp) + lwz $t6,`$FRAME+28^$LITTLE_ENDIAN`($sp) + stfd $dota,`$FRAME+64`($sp) + stfd $dotb,`$FRAME+72`($sp) + + addc $t0,$t0,$carry + adde $t1,$t1,$c1 + srwi $carry,$t0,16 + insrwi $carry,$t1,16,0 + srwi $c1,$t1,16 + addc $t2,$t2,$carry + adde $t3,$t3,$c1 + srwi $carry,$t2,16 + insrwi $t0,$t2,16,0 ; 0..31 bits + lwz $t2,12($tp) ; tp[j] + insrwi $carry,$t3,16,0 + srwi $c1,$t3,16 + lwz $t3,8($tp) + addc $t4,$t4,$carry + adde $t5,$t5,$c1 + srwi $carry,$t4,16 + insrwi $carry,$t5,16,0 + srwi $c1,$t5,16 + addc $t6,$t6,$carry + adde $t7,$t7,$c1 + srwi $carry,$t6,16 + insrwi $t4,$t6,16,0 ; 32..63 bits + insrwi $carry,$t7,16,0 + srwi $c1,$t7,16 + + addc $t0,$t0,$t2 + adde $t4,$t4,$t3 + addze $carry,$carry + addze $c1,$c1 + stw $t0,4($tp) ; tp[j-1] + stw $t4,0($tp) + + lwz $t3,`$FRAME+32^$LITTLE_ENDIAN`($sp) ; permuted $t1 + lwz $t2,`$FRAME+36^$LITTLE_ENDIAN`($sp) ; permuted $t0 + lwz $t7,`$FRAME+40^$LITTLE_ENDIAN`($sp) ; permuted $t3 + lwz $t6,`$FRAME+44^$LITTLE_ENDIAN`($sp) ; permuted $t2 + lwz $t1,`$FRAME+48^$LITTLE_ENDIAN`($sp) ; permuted $t5 + lwz $t0,`$FRAME+52^$LITTLE_ENDIAN`($sp) ; permuted $t4 + lwz $t5,`$FRAME+56^$LITTLE_ENDIAN`($sp) ; permuted $t7 + lwz $t4,`$FRAME+60^$LITTLE_ENDIAN`($sp) ; permuted $t6 + + addc $t2,$t2,$carry + adde $t3,$t3,$c1 + srwi $carry,$t2,16 + insrwi $carry,$t3,16,0 + srwi $c1,$t3,16 + addc $t6,$t6,$carry + adde $t7,$t7,$c1 + srwi $carry,$t6,16 + insrwi $t2,$t6,16,0 ; 64..95 bits + lwz $t6,20($tp) + insrwi $carry,$t7,16,0 + srwi $c1,$t7,16 + lwzu $t7,16($tp) + addc $t0,$t0,$carry + adde $t1,$t1,$c1 + srwi $carry,$t0,16 + insrwi $carry,$t1,16,0 + srwi $c1,$t1,16 + addc $t4,$t4,$carry + adde $t5,$t5,$c1 + srwi $carry,$t4,16 + insrwi $t0,$t4,16,0 ; 96..127 bits + insrwi $carry,$t5,16,0 + srwi $c1,$t5,16 + + addc $t2,$t2,$t6 + adde $t0,$t0,$t7 + lwz $t7,`$FRAME+64^$LITTLE_ENDIAN`($sp) + lwz $t6,`$FRAME+68^$LITTLE_ENDIAN`($sp) + addze $carry,$carry + addze $c1,$c1 + lwz $t5,`$FRAME+72^$LITTLE_ENDIAN`($sp) + lwz $t4,`$FRAME+76^$LITTLE_ENDIAN`($sp) + + addc $t6,$t6,$carry + adde $t7,$t7,$c1 + stw $t2,-4($tp) ; tp[j] + stw $t0,-8($tp) + addc $t6,$t6,$ovf + addze $t7,$t7 + srwi $carry,$t6,16 + insrwi $carry,$t7,16,0 + srwi $c1,$t7,16 + addc $t4,$t4,$carry + adde $t5,$t5,$c1 + + insrwi $t6,$t4,16,0 + srwi $t4,$t4,16 + insrwi $t4,$t5,16,0 + srwi $ovf,$t5,16 + stw $t6,4($tp) ; tp[num-1] + stw $t4,0($tp) +___ +} +$code.=<<___; + slwi $t7,$num,2 + addi $i,$i,8 + subf $nap_d,$t7,$nap_d ; rewind pointer + cmpw $i,$num + blt- Louter +___ + +$code.=<<___ if ($SIZE_T==8); + subf $np,$num,$np ; rewind np + addi $j,$j,1 ; restore counter + subfc $i,$i,$i ; j=0 and "clear" XER[CA] + addi $tp,$sp,`$FRAME+$TRANSFER+8` + addi $t4,$sp,`$FRAME+$TRANSFER+16` + addi $t5,$np,8 + addi $t6,$rp,8 + mtctr $j + +.align 4 +Lsub: ldx $t0,$tp,$i + ldx $t1,$np,$i + ldx $t2,$t4,$i + ldx $t3,$t5,$i + subfe $t0,$t1,$t0 ; tp[j]-np[j] + subfe $t2,$t3,$t2 ; tp[j+1]-np[j+1] + stdx $t0,$rp,$i + stdx $t2,$t6,$i + addi $i,$i,16 + bdnz Lsub + + li $i,0 + subfe $ovf,$i,$ovf ; handle upmost overflow bit + mtctr $j + +.align 4 +Lcopy: ; conditional copy + ldx $t0,$tp,$i + ldx $t1,$t4,$i + ldx $t2,$rp,$i + ldx $t3,$t6,$i + std $i,8($nap_d) ; zap nap_d + std $i,16($nap_d) + std $i,24($nap_d) + std $i,32($nap_d) + std $i,40($nap_d) + std $i,48($nap_d) + std $i,56($nap_d) + stdu $i,64($nap_d) + and $t0,$t0,$ovf + and $t1,$t1,$ovf + andc $t2,$t2,$ovf + andc $t3,$t3,$ovf + or $t0,$t0,$t2 + or $t1,$t1,$t3 + stdx $t0,$rp,$i + stdx $t1,$t6,$i + stdx $i,$tp,$i ; zap tp at once + stdx $i,$t4,$i + addi $i,$i,16 + bdnz Lcopy +___ +$code.=<<___ if ($SIZE_T==4); + subf $np,$num,$np ; rewind np + addi $j,$j,1 ; restore counter + subfc $i,$i,$i ; j=0 and "clear" XER[CA] + addi $tp,$sp,`$FRAME+$TRANSFER` + addi $np,$np,-4 + addi $rp,$rp,-4 + addi $ap,$sp,`$FRAME+$TRANSFER+4` + mtctr $j + +.align 4 +Lsub: lwz $t0,12($tp) ; load tp[j..j+3] in 64-bit word order + lwz $t1,8($tp) + lwz $t2,20($tp) + lwzu $t3,16($tp) + lwz $t4,4($np) ; load np[j..j+3] in 32-bit word order + lwz $t5,8($np) + lwz $t6,12($np) + lwzu $t7,16($np) + subfe $t4,$t4,$t0 ; tp[j]-np[j] + stw $t0,4($ap) ; save tp[j..j+3] in 32-bit word order + subfe $t5,$t5,$t1 ; tp[j+1]-np[j+1] + stw $t1,8($ap) + subfe $t6,$t6,$t2 ; tp[j+2]-np[j+2] + stw $t2,12($ap) + subfe $t7,$t7,$t3 ; tp[j+3]-np[j+3] + stwu $t3,16($ap) + stw $t4,4($rp) + stw $t5,8($rp) + stw $t6,12($rp) + stwu $t7,16($rp) + bdnz Lsub + + li $i,0 + subfe $ovf,$i,$ovf ; handle upmost overflow bit + addi $ap,$sp,`$FRAME+$TRANSFER+4` + subf $rp,$num,$rp ; rewind rp + addi $tp,$sp,`$FRAME+$TRANSFER` + mtctr $j + +.align 4 +Lcopy: ; conditional copy + lwz $t0,4($ap) + lwz $t1,8($ap) + lwz $t2,12($ap) + lwzu $t3,16($ap) + lwz $t4,4($rp) + lwz $t5,8($rp) + lwz $t6,12($rp) + lwz $t7,16($rp) + std $i,8($nap_d) ; zap nap_d + std $i,16($nap_d) + std $i,24($nap_d) + std $i,32($nap_d) + std $i,40($nap_d) + std $i,48($nap_d) + std $i,56($nap_d) + stdu $i,64($nap_d) + and $t0,$t0,$ovf + and $t1,$t1,$ovf + and $t2,$t2,$ovf + and $t3,$t3,$ovf + andc $t4,$t4,$ovf + andc $t5,$t5,$ovf + andc $t6,$t6,$ovf + andc $t7,$t7,$ovf + or $t0,$t0,$t4 + or $t1,$t1,$t5 + or $t2,$t2,$t6 + or $t3,$t3,$t7 + stw $t0,4($rp) + stw $t1,8($rp) + stw $t2,12($rp) + stwu $t3,16($rp) + std $i,8($tp) ; zap tp at once + stdu $i,16($tp) + bdnz Lcopy +___ + +$code.=<<___; + $POP $i,0($sp) + li r3,1 ; signal "handled" + $POP r19,`-12*8-13*$SIZE_T`($i) + $POP r20,`-12*8-12*$SIZE_T`($i) + $POP r21,`-12*8-11*$SIZE_T`($i) + $POP r22,`-12*8-10*$SIZE_T`($i) + $POP r23,`-12*8-9*$SIZE_T`($i) + $POP r24,`-12*8-8*$SIZE_T`($i) + $POP r25,`-12*8-7*$SIZE_T`($i) + $POP r26,`-12*8-6*$SIZE_T`($i) + $POP r27,`-12*8-5*$SIZE_T`($i) + $POP r28,`-12*8-4*$SIZE_T`($i) + $POP r29,`-12*8-3*$SIZE_T`($i) + $POP r30,`-12*8-2*$SIZE_T`($i) + $POP r31,`-12*8-1*$SIZE_T`($i) + lfd f20,`-12*8`($i) + lfd f21,`-11*8`($i) + lfd f22,`-10*8`($i) + lfd f23,`-9*8`($i) + lfd f24,`-8*8`($i) + lfd f25,`-7*8`($i) + lfd f26,`-6*8`($i) + lfd f27,`-5*8`($i) + lfd f28,`-4*8`($i) + lfd f29,`-3*8`($i) + lfd f30,`-2*8`($i) + lfd f31,`-1*8`($i) + mr $sp,$i + blr + .long 0 + .byte 0,12,4,0,0x8c,13,6,0 + .long 0 +.size .$fname,.-.$fname + +.asciz "Montgomery Multiplication for PPC64, CRYPTOGAMS by " +___ + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/rsaz-avx2.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/rsaz-avx2.pl new file mode 100755 index 000000000..85cd73c66 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/rsaz-avx2.pl @@ -0,0 +1,1982 @@ +#! /usr/bin/env perl +# Copyright 2013-2019 The OpenSSL Project Authors. All Rights Reserved. +# Copyright (c) 2012, Intel Corporation. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html +# +# Originally written by Shay Gueron (1, 2), and Vlad Krasnov (1) +# (1) Intel Corporation, Israel Development Center, Haifa, Israel +# (2) University of Haifa, Israel +# +# References: +# [1] S. Gueron, V. Krasnov: "Software Implementation of Modular +# Exponentiation, Using Advanced Vector Instructions Architectures", +# F. Ozbudak and F. Rodriguez-Henriquez (Eds.): WAIFI 2012, LNCS 7369, +# pp. 119?135, 2012. Springer-Verlag Berlin Heidelberg 2012 +# [2] S. Gueron: "Efficient Software Implementations of Modular +# Exponentiation", Journal of Cryptographic Engineering 2:31-43 (2012). +# [3] S. Gueron, V. Krasnov: "Speeding up Big-numbers Squaring",IEEE +# Proceedings of 9th International Conference on Information Technology: +# New Generations (ITNG 2012), pp.821-823 (2012) +# [4] S. Gueron, V. Krasnov: "[PATCH] Efficient and side channel analysis +# resistant 1024-bit modular exponentiation, for optimizing RSA2048 +# on AVX2 capable x86_64 platforms", +# http://rt.openssl.org/Ticket/Display.html?id=2850&user=guest&pass=guest +# +# +13% improvement over original submission by +# +# rsa2048 sign/sec OpenSSL 1.0.1 scalar(*) this +# 2.3GHz Haswell 621 765/+23% 1113/+79% +# 2.3GHz Broadwell(**) 688 1200(***)/+74% 1120/+63% +# +# (*) if system doesn't support AVX2, for reference purposes; +# (**) scaled to 2.3GHz to simplify comparison; +# (***) scalar AD*X code is faster than AVX2 and is preferred code +# path for Broadwell; + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler version ([2-9]\.[0-9]+)/) { + $avx = ($1>=2.19) + ($1>=2.22); + $addx = ($1>=2.23); +} + +if (!$avx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) && + `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) { + $avx = ($1>=2.09) + ($1>=2.10); + $addx = ($1>=2.10); +} + +if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && + `ml64 2>&1` =~ /Version ([0-9]+)\./) { + $avx = ($1>=10) + ($1>=11); + $addx = ($1>=11); +} + +if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9])\.([0-9]+)/) { + my $ver = $2 + $3/100.0; # 3.1->3.01, 3.10->3.10 + $avx = ($ver>=3.0) + ($ver>=3.01); + $addx = ($ver>=3.03); +} + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +*STDOUT = *OUT; + +if ($avx>1) {{{ +{ # void AMS_WW( +my $rp="%rdi"; # BN_ULONG *rp, +my $ap="%rsi"; # const BN_ULONG *ap, +my $np="%rdx"; # const BN_ULONG *np, +my $n0="%ecx"; # const BN_ULONG n0, +my $rep="%r8d"; # int repeat); + +# The registers that hold the accumulated redundant result +# The AMM works on 1024 bit operands, and redundant word size is 29 +# Therefore: ceil(1024/29)/4 = 9 +my $ACC0="%ymm0"; +my $ACC1="%ymm1"; +my $ACC2="%ymm2"; +my $ACC3="%ymm3"; +my $ACC4="%ymm4"; +my $ACC5="%ymm5"; +my $ACC6="%ymm6"; +my $ACC7="%ymm7"; +my $ACC8="%ymm8"; +my $ACC9="%ymm9"; +# Registers that hold the broadcasted words of bp, currently used +my $B1="%ymm10"; +my $B2="%ymm11"; +# Registers that hold the broadcasted words of Y, currently used +my $Y1="%ymm12"; +my $Y2="%ymm13"; +# Helper registers +my $TEMP1="%ymm14"; +my $AND_MASK="%ymm15"; +# alu registers that hold the first words of the ACC +my $r0="%r9"; +my $r1="%r10"; +my $r2="%r11"; +my $r3="%r12"; + +my $i="%r14d"; # loop counter +my $tmp = "%r15"; + +my $FrameSize=32*18+32*8; # place for A^2 and 2*A + +my $aap=$r0; +my $tp0="%rbx"; +my $tp1=$r3; +my $tpa=$tmp; + +$np="%r13"; # reassigned argument + +$code.=<<___; +.text + +.globl rsaz_1024_sqr_avx2 +.type rsaz_1024_sqr_avx2,\@function,5 +.align 64 +rsaz_1024_sqr_avx2: # 702 cycles, 14% faster than rsaz_1024_mul_avx2 +.cfi_startproc + lea (%rsp), %rax +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + vzeroupper +___ +$code.=<<___ if ($win64); + lea -0xa8(%rsp),%rsp + vmovaps %xmm6,-0xd8(%rax) + vmovaps %xmm7,-0xc8(%rax) + vmovaps %xmm8,-0xb8(%rax) + vmovaps %xmm9,-0xa8(%rax) + vmovaps %xmm10,-0x98(%rax) + vmovaps %xmm11,-0x88(%rax) + vmovaps %xmm12,-0x78(%rax) + vmovaps %xmm13,-0x68(%rax) + vmovaps %xmm14,-0x58(%rax) + vmovaps %xmm15,-0x48(%rax) +.Lsqr_1024_body: +___ +$code.=<<___; + mov %rax,%rbp +.cfi_def_cfa_register %rbp + mov %rdx, $np # reassigned argument + sub \$$FrameSize, %rsp + mov $np, $tmp + sub \$-128, $rp # size optimization + sub \$-128, $ap + sub \$-128, $np + + and \$4095, $tmp # see if $np crosses page + add \$32*10, $tmp + shr \$12, $tmp + vpxor $ACC9,$ACC9,$ACC9 + jz .Lsqr_1024_no_n_copy + + # unaligned 256-bit load that crosses page boundary can + # cause >2x performance degradation here, so if $np does + # cross page boundary, copy it to stack and make sure stack + # frame doesn't... + sub \$32*10,%rsp + vmovdqu 32*0-128($np), $ACC0 + and \$-2048, %rsp + vmovdqu 32*1-128($np), $ACC1 + vmovdqu 32*2-128($np), $ACC2 + vmovdqu 32*3-128($np), $ACC3 + vmovdqu 32*4-128($np), $ACC4 + vmovdqu 32*5-128($np), $ACC5 + vmovdqu 32*6-128($np), $ACC6 + vmovdqu 32*7-128($np), $ACC7 + vmovdqu 32*8-128($np), $ACC8 + lea $FrameSize+128(%rsp),$np + vmovdqu $ACC0, 32*0-128($np) + vmovdqu $ACC1, 32*1-128($np) + vmovdqu $ACC2, 32*2-128($np) + vmovdqu $ACC3, 32*3-128($np) + vmovdqu $ACC4, 32*4-128($np) + vmovdqu $ACC5, 32*5-128($np) + vmovdqu $ACC6, 32*6-128($np) + vmovdqu $ACC7, 32*7-128($np) + vmovdqu $ACC8, 32*8-128($np) + vmovdqu $ACC9, 32*9-128($np) # $ACC9 is zero + +.Lsqr_1024_no_n_copy: + and \$-1024, %rsp + + vmovdqu 32*1-128($ap), $ACC1 + vmovdqu 32*2-128($ap), $ACC2 + vmovdqu 32*3-128($ap), $ACC3 + vmovdqu 32*4-128($ap), $ACC4 + vmovdqu 32*5-128($ap), $ACC5 + vmovdqu 32*6-128($ap), $ACC6 + vmovdqu 32*7-128($ap), $ACC7 + vmovdqu 32*8-128($ap), $ACC8 + + lea 192(%rsp), $tp0 # 64+128=192 + vmovdqu .Land_mask(%rip), $AND_MASK + jmp .LOOP_GRANDE_SQR_1024 + +.align 32 +.LOOP_GRANDE_SQR_1024: + lea 32*18+128(%rsp), $aap # size optimization + lea 448(%rsp), $tp1 # 64+128+256=448 + + # the squaring is performed as described in Variant B of + # "Speeding up Big-Number Squaring", so start by calculating + # the A*2=A+A vector + vpaddq $ACC1, $ACC1, $ACC1 + vpbroadcastq 32*0-128($ap), $B1 + vpaddq $ACC2, $ACC2, $ACC2 + vmovdqa $ACC1, 32*0-128($aap) + vpaddq $ACC3, $ACC3, $ACC3 + vmovdqa $ACC2, 32*1-128($aap) + vpaddq $ACC4, $ACC4, $ACC4 + vmovdqa $ACC3, 32*2-128($aap) + vpaddq $ACC5, $ACC5, $ACC5 + vmovdqa $ACC4, 32*3-128($aap) + vpaddq $ACC6, $ACC6, $ACC6 + vmovdqa $ACC5, 32*4-128($aap) + vpaddq $ACC7, $ACC7, $ACC7 + vmovdqa $ACC6, 32*5-128($aap) + vpaddq $ACC8, $ACC8, $ACC8 + vmovdqa $ACC7, 32*6-128($aap) + vpxor $ACC9, $ACC9, $ACC9 + vmovdqa $ACC8, 32*7-128($aap) + + vpmuludq 32*0-128($ap), $B1, $ACC0 + vpbroadcastq 32*1-128($ap), $B2 + vmovdqu $ACC9, 32*9-192($tp0) # zero upper half + vpmuludq $B1, $ACC1, $ACC1 + vmovdqu $ACC9, 32*10-448($tp1) + vpmuludq $B1, $ACC2, $ACC2 + vmovdqu $ACC9, 32*11-448($tp1) + vpmuludq $B1, $ACC3, $ACC3 + vmovdqu $ACC9, 32*12-448($tp1) + vpmuludq $B1, $ACC4, $ACC4 + vmovdqu $ACC9, 32*13-448($tp1) + vpmuludq $B1, $ACC5, $ACC5 + vmovdqu $ACC9, 32*14-448($tp1) + vpmuludq $B1, $ACC6, $ACC6 + vmovdqu $ACC9, 32*15-448($tp1) + vpmuludq $B1, $ACC7, $ACC7 + vmovdqu $ACC9, 32*16-448($tp1) + vpmuludq $B1, $ACC8, $ACC8 + vpbroadcastq 32*2-128($ap), $B1 + vmovdqu $ACC9, 32*17-448($tp1) + + mov $ap, $tpa + mov \$4, $i + jmp .Lsqr_entry_1024 +___ +$TEMP0=$Y1; +$TEMP2=$Y2; +$code.=<<___; +.align 32 +.LOOP_SQR_1024: + vpbroadcastq 32*1-128($tpa), $B2 + vpmuludq 32*0-128($ap), $B1, $ACC0 + vpaddq 32*0-192($tp0), $ACC0, $ACC0 + vpmuludq 32*0-128($aap), $B1, $ACC1 + vpaddq 32*1-192($tp0), $ACC1, $ACC1 + vpmuludq 32*1-128($aap), $B1, $ACC2 + vpaddq 32*2-192($tp0), $ACC2, $ACC2 + vpmuludq 32*2-128($aap), $B1, $ACC3 + vpaddq 32*3-192($tp0), $ACC3, $ACC3 + vpmuludq 32*3-128($aap), $B1, $ACC4 + vpaddq 32*4-192($tp0), $ACC4, $ACC4 + vpmuludq 32*4-128($aap), $B1, $ACC5 + vpaddq 32*5-192($tp0), $ACC5, $ACC5 + vpmuludq 32*5-128($aap), $B1, $ACC6 + vpaddq 32*6-192($tp0), $ACC6, $ACC6 + vpmuludq 32*6-128($aap), $B1, $ACC7 + vpaddq 32*7-192($tp0), $ACC7, $ACC7 + vpmuludq 32*7-128($aap), $B1, $ACC8 + vpbroadcastq 32*2-128($tpa), $B1 + vpaddq 32*8-192($tp0), $ACC8, $ACC8 +.Lsqr_entry_1024: + vmovdqu $ACC0, 32*0-192($tp0) + vmovdqu $ACC1, 32*1-192($tp0) + + vpmuludq 32*1-128($ap), $B2, $TEMP0 + vpaddq $TEMP0, $ACC2, $ACC2 + vpmuludq 32*1-128($aap), $B2, $TEMP1 + vpaddq $TEMP1, $ACC3, $ACC3 + vpmuludq 32*2-128($aap), $B2, $TEMP2 + vpaddq $TEMP2, $ACC4, $ACC4 + vpmuludq 32*3-128($aap), $B2, $TEMP0 + vpaddq $TEMP0, $ACC5, $ACC5 + vpmuludq 32*4-128($aap), $B2, $TEMP1 + vpaddq $TEMP1, $ACC6, $ACC6 + vpmuludq 32*5-128($aap), $B2, $TEMP2 + vpaddq $TEMP2, $ACC7, $ACC7 + vpmuludq 32*6-128($aap), $B2, $TEMP0 + vpaddq $TEMP0, $ACC8, $ACC8 + vpmuludq 32*7-128($aap), $B2, $ACC0 + vpbroadcastq 32*3-128($tpa), $B2 + vpaddq 32*9-192($tp0), $ACC0, $ACC0 + + vmovdqu $ACC2, 32*2-192($tp0) + vmovdqu $ACC3, 32*3-192($tp0) + + vpmuludq 32*2-128($ap), $B1, $TEMP2 + vpaddq $TEMP2, $ACC4, $ACC4 + vpmuludq 32*2-128($aap), $B1, $TEMP0 + vpaddq $TEMP0, $ACC5, $ACC5 + vpmuludq 32*3-128($aap), $B1, $TEMP1 + vpaddq $TEMP1, $ACC6, $ACC6 + vpmuludq 32*4-128($aap), $B1, $TEMP2 + vpaddq $TEMP2, $ACC7, $ACC7 + vpmuludq 32*5-128($aap), $B1, $TEMP0 + vpaddq $TEMP0, $ACC8, $ACC8 + vpmuludq 32*6-128($aap), $B1, $TEMP1 + vpaddq $TEMP1, $ACC0, $ACC0 + vpmuludq 32*7-128($aap), $B1, $ACC1 + vpbroadcastq 32*4-128($tpa), $B1 + vpaddq 32*10-448($tp1), $ACC1, $ACC1 + + vmovdqu $ACC4, 32*4-192($tp0) + vmovdqu $ACC5, 32*5-192($tp0) + + vpmuludq 32*3-128($ap), $B2, $TEMP0 + vpaddq $TEMP0, $ACC6, $ACC6 + vpmuludq 32*3-128($aap), $B2, $TEMP1 + vpaddq $TEMP1, $ACC7, $ACC7 + vpmuludq 32*4-128($aap), $B2, $TEMP2 + vpaddq $TEMP2, $ACC8, $ACC8 + vpmuludq 32*5-128($aap), $B2, $TEMP0 + vpaddq $TEMP0, $ACC0, $ACC0 + vpmuludq 32*6-128($aap), $B2, $TEMP1 + vpaddq $TEMP1, $ACC1, $ACC1 + vpmuludq 32*7-128($aap), $B2, $ACC2 + vpbroadcastq 32*5-128($tpa), $B2 + vpaddq 32*11-448($tp1), $ACC2, $ACC2 + + vmovdqu $ACC6, 32*6-192($tp0) + vmovdqu $ACC7, 32*7-192($tp0) + + vpmuludq 32*4-128($ap), $B1, $TEMP0 + vpaddq $TEMP0, $ACC8, $ACC8 + vpmuludq 32*4-128($aap), $B1, $TEMP1 + vpaddq $TEMP1, $ACC0, $ACC0 + vpmuludq 32*5-128($aap), $B1, $TEMP2 + vpaddq $TEMP2, $ACC1, $ACC1 + vpmuludq 32*6-128($aap), $B1, $TEMP0 + vpaddq $TEMP0, $ACC2, $ACC2 + vpmuludq 32*7-128($aap), $B1, $ACC3 + vpbroadcastq 32*6-128($tpa), $B1 + vpaddq 32*12-448($tp1), $ACC3, $ACC3 + + vmovdqu $ACC8, 32*8-192($tp0) + vmovdqu $ACC0, 32*9-192($tp0) + lea 8($tp0), $tp0 + + vpmuludq 32*5-128($ap), $B2, $TEMP2 + vpaddq $TEMP2, $ACC1, $ACC1 + vpmuludq 32*5-128($aap), $B2, $TEMP0 + vpaddq $TEMP0, $ACC2, $ACC2 + vpmuludq 32*6-128($aap), $B2, $TEMP1 + vpaddq $TEMP1, $ACC3, $ACC3 + vpmuludq 32*7-128($aap), $B2, $ACC4 + vpbroadcastq 32*7-128($tpa), $B2 + vpaddq 32*13-448($tp1), $ACC4, $ACC4 + + vmovdqu $ACC1, 32*10-448($tp1) + vmovdqu $ACC2, 32*11-448($tp1) + + vpmuludq 32*6-128($ap), $B1, $TEMP0 + vpaddq $TEMP0, $ACC3, $ACC3 + vpmuludq 32*6-128($aap), $B1, $TEMP1 + vpbroadcastq 32*8-128($tpa), $ACC0 # borrow $ACC0 for $B1 + vpaddq $TEMP1, $ACC4, $ACC4 + vpmuludq 32*7-128($aap), $B1, $ACC5 + vpbroadcastq 32*0+8-128($tpa), $B1 # for next iteration + vpaddq 32*14-448($tp1), $ACC5, $ACC5 + + vmovdqu $ACC3, 32*12-448($tp1) + vmovdqu $ACC4, 32*13-448($tp1) + lea 8($tpa), $tpa + + vpmuludq 32*7-128($ap), $B2, $TEMP0 + vpaddq $TEMP0, $ACC5, $ACC5 + vpmuludq 32*7-128($aap), $B2, $ACC6 + vpaddq 32*15-448($tp1), $ACC6, $ACC6 + + vpmuludq 32*8-128($ap), $ACC0, $ACC7 + vmovdqu $ACC5, 32*14-448($tp1) + vpaddq 32*16-448($tp1), $ACC7, $ACC7 + vmovdqu $ACC6, 32*15-448($tp1) + vmovdqu $ACC7, 32*16-448($tp1) + lea 8($tp1), $tp1 + + dec $i + jnz .LOOP_SQR_1024 +___ +$ZERO = $ACC9; +$TEMP0 = $B1; +$TEMP2 = $B2; +$TEMP3 = $Y1; +$TEMP4 = $Y2; +$code.=<<___; + # we need to fix indices 32-39 to avoid overflow + vmovdqu 32*8(%rsp), $ACC8 # 32*8-192($tp0), + vmovdqu 32*9(%rsp), $ACC1 # 32*9-192($tp0) + vmovdqu 32*10(%rsp), $ACC2 # 32*10-192($tp0) + lea 192(%rsp), $tp0 # 64+128=192 + + vpsrlq \$29, $ACC8, $TEMP1 + vpand $AND_MASK, $ACC8, $ACC8 + vpsrlq \$29, $ACC1, $TEMP2 + vpand $AND_MASK, $ACC1, $ACC1 + + vpermq \$0x93, $TEMP1, $TEMP1 + vpxor $ZERO, $ZERO, $ZERO + vpermq \$0x93, $TEMP2, $TEMP2 + + vpblendd \$3, $ZERO, $TEMP1, $TEMP0 + vpblendd \$3, $TEMP1, $TEMP2, $TEMP1 + vpaddq $TEMP0, $ACC8, $ACC8 + vpblendd \$3, $TEMP2, $ZERO, $TEMP2 + vpaddq $TEMP1, $ACC1, $ACC1 + vpaddq $TEMP2, $ACC2, $ACC2 + vmovdqu $ACC1, 32*9-192($tp0) + vmovdqu $ACC2, 32*10-192($tp0) + + mov (%rsp), %rax + mov 8(%rsp), $r1 + mov 16(%rsp), $r2 + mov 24(%rsp), $r3 + vmovdqu 32*1(%rsp), $ACC1 + vmovdqu 32*2-192($tp0), $ACC2 + vmovdqu 32*3-192($tp0), $ACC3 + vmovdqu 32*4-192($tp0), $ACC4 + vmovdqu 32*5-192($tp0), $ACC5 + vmovdqu 32*6-192($tp0), $ACC6 + vmovdqu 32*7-192($tp0), $ACC7 + + mov %rax, $r0 + imull $n0, %eax + and \$0x1fffffff, %eax + vmovd %eax, $Y1 + + mov %rax, %rdx + imulq -128($np), %rax + vpbroadcastq $Y1, $Y1 + add %rax, $r0 + mov %rdx, %rax + imulq 8-128($np), %rax + shr \$29, $r0 + add %rax, $r1 + mov %rdx, %rax + imulq 16-128($np), %rax + add $r0, $r1 + add %rax, $r2 + imulq 24-128($np), %rdx + add %rdx, $r3 + + mov $r1, %rax + imull $n0, %eax + and \$0x1fffffff, %eax + + mov \$9, $i + jmp .LOOP_REDUCE_1024 + +.align 32 +.LOOP_REDUCE_1024: + vmovd %eax, $Y2 + vpbroadcastq $Y2, $Y2 + + vpmuludq 32*1-128($np), $Y1, $TEMP0 + mov %rax, %rdx + imulq -128($np), %rax + vpaddq $TEMP0, $ACC1, $ACC1 + add %rax, $r1 + vpmuludq 32*2-128($np), $Y1, $TEMP1 + mov %rdx, %rax + imulq 8-128($np), %rax + vpaddq $TEMP1, $ACC2, $ACC2 + vpmuludq 32*3-128($np), $Y1, $TEMP2 + .byte 0x67 + add %rax, $r2 + .byte 0x67 + mov %rdx, %rax + imulq 16-128($np), %rax + shr \$29, $r1 + vpaddq $TEMP2, $ACC3, $ACC3 + vpmuludq 32*4-128($np), $Y1, $TEMP0 + add %rax, $r3 + add $r1, $r2 + vpaddq $TEMP0, $ACC4, $ACC4 + vpmuludq 32*5-128($np), $Y1, $TEMP1 + mov $r2, %rax + imull $n0, %eax + vpaddq $TEMP1, $ACC5, $ACC5 + vpmuludq 32*6-128($np), $Y1, $TEMP2 + and \$0x1fffffff, %eax + vpaddq $TEMP2, $ACC6, $ACC6 + vpmuludq 32*7-128($np), $Y1, $TEMP0 + vpaddq $TEMP0, $ACC7, $ACC7 + vpmuludq 32*8-128($np), $Y1, $TEMP1 + vmovd %eax, $Y1 + #vmovdqu 32*1-8-128($np), $TEMP2 # moved below + vpaddq $TEMP1, $ACC8, $ACC8 + #vmovdqu 32*2-8-128($np), $TEMP0 # moved below + vpbroadcastq $Y1, $Y1 + + vpmuludq 32*1-8-128($np), $Y2, $TEMP2 # see above + vmovdqu 32*3-8-128($np), $TEMP1 + mov %rax, %rdx + imulq -128($np), %rax + vpaddq $TEMP2, $ACC1, $ACC1 + vpmuludq 32*2-8-128($np), $Y2, $TEMP0 # see above + vmovdqu 32*4-8-128($np), $TEMP2 + add %rax, $r2 + mov %rdx, %rax + imulq 8-128($np), %rax + vpaddq $TEMP0, $ACC2, $ACC2 + add $r3, %rax + shr \$29, $r2 + vpmuludq $Y2, $TEMP1, $TEMP1 + vmovdqu 32*5-8-128($np), $TEMP0 + add $r2, %rax + vpaddq $TEMP1, $ACC3, $ACC3 + vpmuludq $Y2, $TEMP2, $TEMP2 + vmovdqu 32*6-8-128($np), $TEMP1 + .byte 0x67 + mov %rax, $r3 + imull $n0, %eax + vpaddq $TEMP2, $ACC4, $ACC4 + vpmuludq $Y2, $TEMP0, $TEMP0 + .byte 0xc4,0x41,0x7e,0x6f,0x9d,0x58,0x00,0x00,0x00 # vmovdqu 32*7-8-128($np), $TEMP2 + and \$0x1fffffff, %eax + vpaddq $TEMP0, $ACC5, $ACC5 + vpmuludq $Y2, $TEMP1, $TEMP1 + vmovdqu 32*8-8-128($np), $TEMP0 + vpaddq $TEMP1, $ACC6, $ACC6 + vpmuludq $Y2, $TEMP2, $TEMP2 + vmovdqu 32*9-8-128($np), $ACC9 + vmovd %eax, $ACC0 # borrow ACC0 for Y2 + imulq -128($np), %rax + vpaddq $TEMP2, $ACC7, $ACC7 + vpmuludq $Y2, $TEMP0, $TEMP0 + vmovdqu 32*1-16-128($np), $TEMP1 + vpbroadcastq $ACC0, $ACC0 + vpaddq $TEMP0, $ACC8, $ACC8 + vpmuludq $Y2, $ACC9, $ACC9 + vmovdqu 32*2-16-128($np), $TEMP2 + add %rax, $r3 + +___ +($ACC0,$Y2)=($Y2,$ACC0); +$code.=<<___; + vmovdqu 32*1-24-128($np), $ACC0 + vpmuludq $Y1, $TEMP1, $TEMP1 + vmovdqu 32*3-16-128($np), $TEMP0 + vpaddq $TEMP1, $ACC1, $ACC1 + vpmuludq $Y2, $ACC0, $ACC0 + vpmuludq $Y1, $TEMP2, $TEMP2 + .byte 0xc4,0x41,0x7e,0x6f,0xb5,0xf0,0xff,0xff,0xff # vmovdqu 32*4-16-128($np), $TEMP1 + vpaddq $ACC1, $ACC0, $ACC0 + vpaddq $TEMP2, $ACC2, $ACC2 + vpmuludq $Y1, $TEMP0, $TEMP0 + vmovdqu 32*5-16-128($np), $TEMP2 + .byte 0x67 + vmovq $ACC0, %rax + vmovdqu $ACC0, (%rsp) # transfer $r0-$r3 + vpaddq $TEMP0, $ACC3, $ACC3 + vpmuludq $Y1, $TEMP1, $TEMP1 + vmovdqu 32*6-16-128($np), $TEMP0 + vpaddq $TEMP1, $ACC4, $ACC4 + vpmuludq $Y1, $TEMP2, $TEMP2 + vmovdqu 32*7-16-128($np), $TEMP1 + vpaddq $TEMP2, $ACC5, $ACC5 + vpmuludq $Y1, $TEMP0, $TEMP0 + vmovdqu 32*8-16-128($np), $TEMP2 + vpaddq $TEMP0, $ACC6, $ACC6 + vpmuludq $Y1, $TEMP1, $TEMP1 + shr \$29, $r3 + vmovdqu 32*9-16-128($np), $TEMP0 + add $r3, %rax + vpaddq $TEMP1, $ACC7, $ACC7 + vpmuludq $Y1, $TEMP2, $TEMP2 + #vmovdqu 32*2-24-128($np), $TEMP1 # moved below + mov %rax, $r0 + imull $n0, %eax + vpaddq $TEMP2, $ACC8, $ACC8 + vpmuludq $Y1, $TEMP0, $TEMP0 + and \$0x1fffffff, %eax + vmovd %eax, $Y1 + vmovdqu 32*3-24-128($np), $TEMP2 + .byte 0x67 + vpaddq $TEMP0, $ACC9, $ACC9 + vpbroadcastq $Y1, $Y1 + + vpmuludq 32*2-24-128($np), $Y2, $TEMP1 # see above + vmovdqu 32*4-24-128($np), $TEMP0 + mov %rax, %rdx + imulq -128($np), %rax + mov 8(%rsp), $r1 + vpaddq $TEMP1, $ACC2, $ACC1 + vpmuludq $Y2, $TEMP2, $TEMP2 + vmovdqu 32*5-24-128($np), $TEMP1 + add %rax, $r0 + mov %rdx, %rax + imulq 8-128($np), %rax + .byte 0x67 + shr \$29, $r0 + mov 16(%rsp), $r2 + vpaddq $TEMP2, $ACC3, $ACC2 + vpmuludq $Y2, $TEMP0, $TEMP0 + vmovdqu 32*6-24-128($np), $TEMP2 + add %rax, $r1 + mov %rdx, %rax + imulq 16-128($np), %rax + vpaddq $TEMP0, $ACC4, $ACC3 + vpmuludq $Y2, $TEMP1, $TEMP1 + vmovdqu 32*7-24-128($np), $TEMP0 + imulq 24-128($np), %rdx # future $r3 + add %rax, $r2 + lea ($r0,$r1), %rax + vpaddq $TEMP1, $ACC5, $ACC4 + vpmuludq $Y2, $TEMP2, $TEMP2 + vmovdqu 32*8-24-128($np), $TEMP1 + mov %rax, $r1 + imull $n0, %eax + vpmuludq $Y2, $TEMP0, $TEMP0 + vpaddq $TEMP2, $ACC6, $ACC5 + vmovdqu 32*9-24-128($np), $TEMP2 + and \$0x1fffffff, %eax + vpaddq $TEMP0, $ACC7, $ACC6 + vpmuludq $Y2, $TEMP1, $TEMP1 + add 24(%rsp), %rdx + vpaddq $TEMP1, $ACC8, $ACC7 + vpmuludq $Y2, $TEMP2, $TEMP2 + vpaddq $TEMP2, $ACC9, $ACC8 + vmovq $r3, $ACC9 + mov %rdx, $r3 + + dec $i + jnz .LOOP_REDUCE_1024 +___ +($ACC0,$Y2)=($Y2,$ACC0); +$code.=<<___; + lea 448(%rsp), $tp1 # size optimization + vpaddq $ACC9, $Y2, $ACC0 + vpxor $ZERO, $ZERO, $ZERO + + vpaddq 32*9-192($tp0), $ACC0, $ACC0 + vpaddq 32*10-448($tp1), $ACC1, $ACC1 + vpaddq 32*11-448($tp1), $ACC2, $ACC2 + vpaddq 32*12-448($tp1), $ACC3, $ACC3 + vpaddq 32*13-448($tp1), $ACC4, $ACC4 + vpaddq 32*14-448($tp1), $ACC5, $ACC5 + vpaddq 32*15-448($tp1), $ACC6, $ACC6 + vpaddq 32*16-448($tp1), $ACC7, $ACC7 + vpaddq 32*17-448($tp1), $ACC8, $ACC8 + + vpsrlq \$29, $ACC0, $TEMP1 + vpand $AND_MASK, $ACC0, $ACC0 + vpsrlq \$29, $ACC1, $TEMP2 + vpand $AND_MASK, $ACC1, $ACC1 + vpsrlq \$29, $ACC2, $TEMP3 + vpermq \$0x93, $TEMP1, $TEMP1 + vpand $AND_MASK, $ACC2, $ACC2 + vpsrlq \$29, $ACC3, $TEMP4 + vpermq \$0x93, $TEMP2, $TEMP2 + vpand $AND_MASK, $ACC3, $ACC3 + vpermq \$0x93, $TEMP3, $TEMP3 + + vpblendd \$3, $ZERO, $TEMP1, $TEMP0 + vpermq \$0x93, $TEMP4, $TEMP4 + vpblendd \$3, $TEMP1, $TEMP2, $TEMP1 + vpaddq $TEMP0, $ACC0, $ACC0 + vpblendd \$3, $TEMP2, $TEMP3, $TEMP2 + vpaddq $TEMP1, $ACC1, $ACC1 + vpblendd \$3, $TEMP3, $TEMP4, $TEMP3 + vpaddq $TEMP2, $ACC2, $ACC2 + vpblendd \$3, $TEMP4, $ZERO, $TEMP4 + vpaddq $TEMP3, $ACC3, $ACC3 + vpaddq $TEMP4, $ACC4, $ACC4 + + vpsrlq \$29, $ACC0, $TEMP1 + vpand $AND_MASK, $ACC0, $ACC0 + vpsrlq \$29, $ACC1, $TEMP2 + vpand $AND_MASK, $ACC1, $ACC1 + vpsrlq \$29, $ACC2, $TEMP3 + vpermq \$0x93, $TEMP1, $TEMP1 + vpand $AND_MASK, $ACC2, $ACC2 + vpsrlq \$29, $ACC3, $TEMP4 + vpermq \$0x93, $TEMP2, $TEMP2 + vpand $AND_MASK, $ACC3, $ACC3 + vpermq \$0x93, $TEMP3, $TEMP3 + + vpblendd \$3, $ZERO, $TEMP1, $TEMP0 + vpermq \$0x93, $TEMP4, $TEMP4 + vpblendd \$3, $TEMP1, $TEMP2, $TEMP1 + vpaddq $TEMP0, $ACC0, $ACC0 + vpblendd \$3, $TEMP2, $TEMP3, $TEMP2 + vpaddq $TEMP1, $ACC1, $ACC1 + vmovdqu $ACC0, 32*0-128($rp) + vpblendd \$3, $TEMP3, $TEMP4, $TEMP3 + vpaddq $TEMP2, $ACC2, $ACC2 + vmovdqu $ACC1, 32*1-128($rp) + vpblendd \$3, $TEMP4, $ZERO, $TEMP4 + vpaddq $TEMP3, $ACC3, $ACC3 + vmovdqu $ACC2, 32*2-128($rp) + vpaddq $TEMP4, $ACC4, $ACC4 + vmovdqu $ACC3, 32*3-128($rp) +___ +$TEMP5=$ACC0; +$code.=<<___; + vpsrlq \$29, $ACC4, $TEMP1 + vpand $AND_MASK, $ACC4, $ACC4 + vpsrlq \$29, $ACC5, $TEMP2 + vpand $AND_MASK, $ACC5, $ACC5 + vpsrlq \$29, $ACC6, $TEMP3 + vpermq \$0x93, $TEMP1, $TEMP1 + vpand $AND_MASK, $ACC6, $ACC6 + vpsrlq \$29, $ACC7, $TEMP4 + vpermq \$0x93, $TEMP2, $TEMP2 + vpand $AND_MASK, $ACC7, $ACC7 + vpsrlq \$29, $ACC8, $TEMP5 + vpermq \$0x93, $TEMP3, $TEMP3 + vpand $AND_MASK, $ACC8, $ACC8 + vpermq \$0x93, $TEMP4, $TEMP4 + + vpblendd \$3, $ZERO, $TEMP1, $TEMP0 + vpermq \$0x93, $TEMP5, $TEMP5 + vpblendd \$3, $TEMP1, $TEMP2, $TEMP1 + vpaddq $TEMP0, $ACC4, $ACC4 + vpblendd \$3, $TEMP2, $TEMP3, $TEMP2 + vpaddq $TEMP1, $ACC5, $ACC5 + vpblendd \$3, $TEMP3, $TEMP4, $TEMP3 + vpaddq $TEMP2, $ACC6, $ACC6 + vpblendd \$3, $TEMP4, $TEMP5, $TEMP4 + vpaddq $TEMP3, $ACC7, $ACC7 + vpaddq $TEMP4, $ACC8, $ACC8 + + vpsrlq \$29, $ACC4, $TEMP1 + vpand $AND_MASK, $ACC4, $ACC4 + vpsrlq \$29, $ACC5, $TEMP2 + vpand $AND_MASK, $ACC5, $ACC5 + vpsrlq \$29, $ACC6, $TEMP3 + vpermq \$0x93, $TEMP1, $TEMP1 + vpand $AND_MASK, $ACC6, $ACC6 + vpsrlq \$29, $ACC7, $TEMP4 + vpermq \$0x93, $TEMP2, $TEMP2 + vpand $AND_MASK, $ACC7, $ACC7 + vpsrlq \$29, $ACC8, $TEMP5 + vpermq \$0x93, $TEMP3, $TEMP3 + vpand $AND_MASK, $ACC8, $ACC8 + vpermq \$0x93, $TEMP4, $TEMP4 + + vpblendd \$3, $ZERO, $TEMP1, $TEMP0 + vpermq \$0x93, $TEMP5, $TEMP5 + vpblendd \$3, $TEMP1, $TEMP2, $TEMP1 + vpaddq $TEMP0, $ACC4, $ACC4 + vpblendd \$3, $TEMP2, $TEMP3, $TEMP2 + vpaddq $TEMP1, $ACC5, $ACC5 + vmovdqu $ACC4, 32*4-128($rp) + vpblendd \$3, $TEMP3, $TEMP4, $TEMP3 + vpaddq $TEMP2, $ACC6, $ACC6 + vmovdqu $ACC5, 32*5-128($rp) + vpblendd \$3, $TEMP4, $TEMP5, $TEMP4 + vpaddq $TEMP3, $ACC7, $ACC7 + vmovdqu $ACC6, 32*6-128($rp) + vpaddq $TEMP4, $ACC8, $ACC8 + vmovdqu $ACC7, 32*7-128($rp) + vmovdqu $ACC8, 32*8-128($rp) + + mov $rp, $ap + dec $rep + jne .LOOP_GRANDE_SQR_1024 + + vzeroall + mov %rbp, %rax +.cfi_def_cfa_register %rax +___ +$code.=<<___ if ($win64); +.Lsqr_1024_in_tail: + movaps -0xd8(%rax),%xmm6 + movaps -0xc8(%rax),%xmm7 + movaps -0xb8(%rax),%xmm8 + movaps -0xa8(%rax),%xmm9 + movaps -0x98(%rax),%xmm10 + movaps -0x88(%rax),%xmm11 + movaps -0x78(%rax),%xmm12 + movaps -0x68(%rax),%xmm13 + movaps -0x58(%rax),%xmm14 + movaps -0x48(%rax),%xmm15 +___ +$code.=<<___; + mov -48(%rax),%r15 +.cfi_restore %r15 + mov -40(%rax),%r14 +.cfi_restore %r14 + mov -32(%rax),%r13 +.cfi_restore %r13 + mov -24(%rax),%r12 +.cfi_restore %r12 + mov -16(%rax),%rbp +.cfi_restore %rbp + mov -8(%rax),%rbx +.cfi_restore %rbx + lea (%rax),%rsp # restore %rsp +.cfi_def_cfa_register %rsp +.Lsqr_1024_epilogue: + ret +.cfi_endproc +.size rsaz_1024_sqr_avx2,.-rsaz_1024_sqr_avx2 +___ +} + +{ # void AMM_WW( +my $rp="%rdi"; # BN_ULONG *rp, +my $ap="%rsi"; # const BN_ULONG *ap, +my $bp="%rdx"; # const BN_ULONG *bp, +my $np="%rcx"; # const BN_ULONG *np, +my $n0="%r8d"; # unsigned int n0); + +# The registers that hold the accumulated redundant result +# The AMM works on 1024 bit operands, and redundant word size is 29 +# Therefore: ceil(1024/29)/4 = 9 +my $ACC0="%ymm0"; +my $ACC1="%ymm1"; +my $ACC2="%ymm2"; +my $ACC3="%ymm3"; +my $ACC4="%ymm4"; +my $ACC5="%ymm5"; +my $ACC6="%ymm6"; +my $ACC7="%ymm7"; +my $ACC8="%ymm8"; +my $ACC9="%ymm9"; + +# Registers that hold the broadcasted words of multiplier, currently used +my $Bi="%ymm10"; +my $Yi="%ymm11"; + +# Helper registers +my $TEMP0=$ACC0; +my $TEMP1="%ymm12"; +my $TEMP2="%ymm13"; +my $ZERO="%ymm14"; +my $AND_MASK="%ymm15"; + +# alu registers that hold the first words of the ACC +my $r0="%r9"; +my $r1="%r10"; +my $r2="%r11"; +my $r3="%r12"; + +my $i="%r14d"; +my $tmp="%r15"; + +$bp="%r13"; # reassigned argument + +$code.=<<___; +.globl rsaz_1024_mul_avx2 +.type rsaz_1024_mul_avx2,\@function,5 +.align 64 +rsaz_1024_mul_avx2: +.cfi_startproc + lea (%rsp), %rax +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +___ +$code.=<<___ if ($win64); + vzeroupper + lea -0xa8(%rsp),%rsp + vmovaps %xmm6,-0xd8(%rax) + vmovaps %xmm7,-0xc8(%rax) + vmovaps %xmm8,-0xb8(%rax) + vmovaps %xmm9,-0xa8(%rax) + vmovaps %xmm10,-0x98(%rax) + vmovaps %xmm11,-0x88(%rax) + vmovaps %xmm12,-0x78(%rax) + vmovaps %xmm13,-0x68(%rax) + vmovaps %xmm14,-0x58(%rax) + vmovaps %xmm15,-0x48(%rax) +.Lmul_1024_body: +___ +$code.=<<___; + mov %rax,%rbp +.cfi_def_cfa_register %rbp + vzeroall + mov %rdx, $bp # reassigned argument + sub \$64,%rsp + + # unaligned 256-bit load that crosses page boundary can + # cause severe performance degradation here, so if $ap does + # cross page boundary, swap it with $bp [meaning that caller + # is advised to lay down $ap and $bp next to each other, so + # that only one can cross page boundary]. + .byte 0x67,0x67 + mov $ap, $tmp + and \$4095, $tmp + add \$32*10, $tmp + shr \$12, $tmp + mov $ap, $tmp + cmovnz $bp, $ap + cmovnz $tmp, $bp + + mov $np, $tmp + sub \$-128,$ap # size optimization + sub \$-128,$np + sub \$-128,$rp + + and \$4095, $tmp # see if $np crosses page + add \$32*10, $tmp + .byte 0x67,0x67 + shr \$12, $tmp + jz .Lmul_1024_no_n_copy + + # unaligned 256-bit load that crosses page boundary can + # cause severe performance degradation here, so if $np does + # cross page boundary, copy it to stack and make sure stack + # frame doesn't... + sub \$32*10,%rsp + vmovdqu 32*0-128($np), $ACC0 + and \$-512, %rsp + vmovdqu 32*1-128($np), $ACC1 + vmovdqu 32*2-128($np), $ACC2 + vmovdqu 32*3-128($np), $ACC3 + vmovdqu 32*4-128($np), $ACC4 + vmovdqu 32*5-128($np), $ACC5 + vmovdqu 32*6-128($np), $ACC6 + vmovdqu 32*7-128($np), $ACC7 + vmovdqu 32*8-128($np), $ACC8 + lea 64+128(%rsp),$np + vmovdqu $ACC0, 32*0-128($np) + vpxor $ACC0, $ACC0, $ACC0 + vmovdqu $ACC1, 32*1-128($np) + vpxor $ACC1, $ACC1, $ACC1 + vmovdqu $ACC2, 32*2-128($np) + vpxor $ACC2, $ACC2, $ACC2 + vmovdqu $ACC3, 32*3-128($np) + vpxor $ACC3, $ACC3, $ACC3 + vmovdqu $ACC4, 32*4-128($np) + vpxor $ACC4, $ACC4, $ACC4 + vmovdqu $ACC5, 32*5-128($np) + vpxor $ACC5, $ACC5, $ACC5 + vmovdqu $ACC6, 32*6-128($np) + vpxor $ACC6, $ACC6, $ACC6 + vmovdqu $ACC7, 32*7-128($np) + vpxor $ACC7, $ACC7, $ACC7 + vmovdqu $ACC8, 32*8-128($np) + vmovdqa $ACC0, $ACC8 + vmovdqu $ACC9, 32*9-128($np) # $ACC9 is zero after vzeroall +.Lmul_1024_no_n_copy: + and \$-64,%rsp + + mov ($bp), %rbx + vpbroadcastq ($bp), $Bi + vmovdqu $ACC0, (%rsp) # clear top of stack + xor $r0, $r0 + .byte 0x67 + xor $r1, $r1 + xor $r2, $r2 + xor $r3, $r3 + + vmovdqu .Land_mask(%rip), $AND_MASK + mov \$9, $i + vmovdqu $ACC9, 32*9-128($rp) # $ACC9 is zero after vzeroall + jmp .Loop_mul_1024 + +.align 32 +.Loop_mul_1024: + vpsrlq \$29, $ACC3, $ACC9 # correct $ACC3(*) + mov %rbx, %rax + imulq -128($ap), %rax + add $r0, %rax + mov %rbx, $r1 + imulq 8-128($ap), $r1 + add 8(%rsp), $r1 + + mov %rax, $r0 + imull $n0, %eax + and \$0x1fffffff, %eax + + mov %rbx, $r2 + imulq 16-128($ap), $r2 + add 16(%rsp), $r2 + + mov %rbx, $r3 + imulq 24-128($ap), $r3 + add 24(%rsp), $r3 + vpmuludq 32*1-128($ap),$Bi,$TEMP0 + vmovd %eax, $Yi + vpaddq $TEMP0,$ACC1,$ACC1 + vpmuludq 32*2-128($ap),$Bi,$TEMP1 + vpbroadcastq $Yi, $Yi + vpaddq $TEMP1,$ACC2,$ACC2 + vpmuludq 32*3-128($ap),$Bi,$TEMP2 + vpand $AND_MASK, $ACC3, $ACC3 # correct $ACC3 + vpaddq $TEMP2,$ACC3,$ACC3 + vpmuludq 32*4-128($ap),$Bi,$TEMP0 + vpaddq $TEMP0,$ACC4,$ACC4 + vpmuludq 32*5-128($ap),$Bi,$TEMP1 + vpaddq $TEMP1,$ACC5,$ACC5 + vpmuludq 32*6-128($ap),$Bi,$TEMP2 + vpaddq $TEMP2,$ACC6,$ACC6 + vpmuludq 32*7-128($ap),$Bi,$TEMP0 + vpermq \$0x93, $ACC9, $ACC9 # correct $ACC3 + vpaddq $TEMP0,$ACC7,$ACC7 + vpmuludq 32*8-128($ap),$Bi,$TEMP1 + vpbroadcastq 8($bp), $Bi + vpaddq $TEMP1,$ACC8,$ACC8 + + mov %rax,%rdx + imulq -128($np),%rax + add %rax,$r0 + mov %rdx,%rax + imulq 8-128($np),%rax + add %rax,$r1 + mov %rdx,%rax + imulq 16-128($np),%rax + add %rax,$r2 + shr \$29, $r0 + imulq 24-128($np),%rdx + add %rdx,$r3 + add $r0, $r1 + + vpmuludq 32*1-128($np),$Yi,$TEMP2 + vmovq $Bi, %rbx + vpaddq $TEMP2,$ACC1,$ACC1 + vpmuludq 32*2-128($np),$Yi,$TEMP0 + vpaddq $TEMP0,$ACC2,$ACC2 + vpmuludq 32*3-128($np),$Yi,$TEMP1 + vpaddq $TEMP1,$ACC3,$ACC3 + vpmuludq 32*4-128($np),$Yi,$TEMP2 + vpaddq $TEMP2,$ACC4,$ACC4 + vpmuludq 32*5-128($np),$Yi,$TEMP0 + vpaddq $TEMP0,$ACC5,$ACC5 + vpmuludq 32*6-128($np),$Yi,$TEMP1 + vpaddq $TEMP1,$ACC6,$ACC6 + vpmuludq 32*7-128($np),$Yi,$TEMP2 + vpblendd \$3, $ZERO, $ACC9, $TEMP1 # correct $ACC3 + vpaddq $TEMP2,$ACC7,$ACC7 + vpmuludq 32*8-128($np),$Yi,$TEMP0 + vpaddq $TEMP1, $ACC3, $ACC3 # correct $ACC3 + vpaddq $TEMP0,$ACC8,$ACC8 + + mov %rbx, %rax + imulq -128($ap),%rax + add %rax,$r1 + vmovdqu -8+32*1-128($ap),$TEMP1 + mov %rbx, %rax + imulq 8-128($ap),%rax + add %rax,$r2 + vmovdqu -8+32*2-128($ap),$TEMP2 + + mov $r1, %rax + vpblendd \$0xfc, $ZERO, $ACC9, $ACC9 # correct $ACC3 + imull $n0, %eax + vpaddq $ACC9,$ACC4,$ACC4 # correct $ACC3 + and \$0x1fffffff, %eax + + imulq 16-128($ap),%rbx + add %rbx,$r3 + vpmuludq $Bi,$TEMP1,$TEMP1 + vmovd %eax, $Yi + vmovdqu -8+32*3-128($ap),$TEMP0 + vpaddq $TEMP1,$ACC1,$ACC1 + vpmuludq $Bi,$TEMP2,$TEMP2 + vpbroadcastq $Yi, $Yi + vmovdqu -8+32*4-128($ap),$TEMP1 + vpaddq $TEMP2,$ACC2,$ACC2 + vpmuludq $Bi,$TEMP0,$TEMP0 + vmovdqu -8+32*5-128($ap),$TEMP2 + vpaddq $TEMP0,$ACC3,$ACC3 + vpmuludq $Bi,$TEMP1,$TEMP1 + vmovdqu -8+32*6-128($ap),$TEMP0 + vpaddq $TEMP1,$ACC4,$ACC4 + vpmuludq $Bi,$TEMP2,$TEMP2 + vmovdqu -8+32*7-128($ap),$TEMP1 + vpaddq $TEMP2,$ACC5,$ACC5 + vpmuludq $Bi,$TEMP0,$TEMP0 + vmovdqu -8+32*8-128($ap),$TEMP2 + vpaddq $TEMP0,$ACC6,$ACC6 + vpmuludq $Bi,$TEMP1,$TEMP1 + vmovdqu -8+32*9-128($ap),$ACC9 + vpaddq $TEMP1,$ACC7,$ACC7 + vpmuludq $Bi,$TEMP2,$TEMP2 + vpaddq $TEMP2,$ACC8,$ACC8 + vpmuludq $Bi,$ACC9,$ACC9 + vpbroadcastq 16($bp), $Bi + + mov %rax,%rdx + imulq -128($np),%rax + add %rax,$r1 + vmovdqu -8+32*1-128($np),$TEMP0 + mov %rdx,%rax + imulq 8-128($np),%rax + add %rax,$r2 + vmovdqu -8+32*2-128($np),$TEMP1 + shr \$29, $r1 + imulq 16-128($np),%rdx + add %rdx,$r3 + add $r1, $r2 + + vpmuludq $Yi,$TEMP0,$TEMP0 + vmovq $Bi, %rbx + vmovdqu -8+32*3-128($np),$TEMP2 + vpaddq $TEMP0,$ACC1,$ACC1 + vpmuludq $Yi,$TEMP1,$TEMP1 + vmovdqu -8+32*4-128($np),$TEMP0 + vpaddq $TEMP1,$ACC2,$ACC2 + vpmuludq $Yi,$TEMP2,$TEMP2 + vmovdqu -8+32*5-128($np),$TEMP1 + vpaddq $TEMP2,$ACC3,$ACC3 + vpmuludq $Yi,$TEMP0,$TEMP0 + vmovdqu -8+32*6-128($np),$TEMP2 + vpaddq $TEMP0,$ACC4,$ACC4 + vpmuludq $Yi,$TEMP1,$TEMP1 + vmovdqu -8+32*7-128($np),$TEMP0 + vpaddq $TEMP1,$ACC5,$ACC5 + vpmuludq $Yi,$TEMP2,$TEMP2 + vmovdqu -8+32*8-128($np),$TEMP1 + vpaddq $TEMP2,$ACC6,$ACC6 + vpmuludq $Yi,$TEMP0,$TEMP0 + vmovdqu -8+32*9-128($np),$TEMP2 + vpaddq $TEMP0,$ACC7,$ACC7 + vpmuludq $Yi,$TEMP1,$TEMP1 + vpaddq $TEMP1,$ACC8,$ACC8 + vpmuludq $Yi,$TEMP2,$TEMP2 + vpaddq $TEMP2,$ACC9,$ACC9 + + vmovdqu -16+32*1-128($ap),$TEMP0 + mov %rbx,%rax + imulq -128($ap),%rax + add $r2,%rax + + vmovdqu -16+32*2-128($ap),$TEMP1 + mov %rax,$r2 + imull $n0, %eax + and \$0x1fffffff, %eax + + imulq 8-128($ap),%rbx + add %rbx,$r3 + vpmuludq $Bi,$TEMP0,$TEMP0 + vmovd %eax, $Yi + vmovdqu -16+32*3-128($ap),$TEMP2 + vpaddq $TEMP0,$ACC1,$ACC1 + vpmuludq $Bi,$TEMP1,$TEMP1 + vpbroadcastq $Yi, $Yi + vmovdqu -16+32*4-128($ap),$TEMP0 + vpaddq $TEMP1,$ACC2,$ACC2 + vpmuludq $Bi,$TEMP2,$TEMP2 + vmovdqu -16+32*5-128($ap),$TEMP1 + vpaddq $TEMP2,$ACC3,$ACC3 + vpmuludq $Bi,$TEMP0,$TEMP0 + vmovdqu -16+32*6-128($ap),$TEMP2 + vpaddq $TEMP0,$ACC4,$ACC4 + vpmuludq $Bi,$TEMP1,$TEMP1 + vmovdqu -16+32*7-128($ap),$TEMP0 + vpaddq $TEMP1,$ACC5,$ACC5 + vpmuludq $Bi,$TEMP2,$TEMP2 + vmovdqu -16+32*8-128($ap),$TEMP1 + vpaddq $TEMP2,$ACC6,$ACC6 + vpmuludq $Bi,$TEMP0,$TEMP0 + vmovdqu -16+32*9-128($ap),$TEMP2 + vpaddq $TEMP0,$ACC7,$ACC7 + vpmuludq $Bi,$TEMP1,$TEMP1 + vpaddq $TEMP1,$ACC8,$ACC8 + vpmuludq $Bi,$TEMP2,$TEMP2 + vpbroadcastq 24($bp), $Bi + vpaddq $TEMP2,$ACC9,$ACC9 + + vmovdqu -16+32*1-128($np),$TEMP0 + mov %rax,%rdx + imulq -128($np),%rax + add %rax,$r2 + vmovdqu -16+32*2-128($np),$TEMP1 + imulq 8-128($np),%rdx + add %rdx,$r3 + shr \$29, $r2 + + vpmuludq $Yi,$TEMP0,$TEMP0 + vmovq $Bi, %rbx + vmovdqu -16+32*3-128($np),$TEMP2 + vpaddq $TEMP0,$ACC1,$ACC1 + vpmuludq $Yi,$TEMP1,$TEMP1 + vmovdqu -16+32*4-128($np),$TEMP0 + vpaddq $TEMP1,$ACC2,$ACC2 + vpmuludq $Yi,$TEMP2,$TEMP2 + vmovdqu -16+32*5-128($np),$TEMP1 + vpaddq $TEMP2,$ACC3,$ACC3 + vpmuludq $Yi,$TEMP0,$TEMP0 + vmovdqu -16+32*6-128($np),$TEMP2 + vpaddq $TEMP0,$ACC4,$ACC4 + vpmuludq $Yi,$TEMP1,$TEMP1 + vmovdqu -16+32*7-128($np),$TEMP0 + vpaddq $TEMP1,$ACC5,$ACC5 + vpmuludq $Yi,$TEMP2,$TEMP2 + vmovdqu -16+32*8-128($np),$TEMP1 + vpaddq $TEMP2,$ACC6,$ACC6 + vpmuludq $Yi,$TEMP0,$TEMP0 + vmovdqu -16+32*9-128($np),$TEMP2 + vpaddq $TEMP0,$ACC7,$ACC7 + vpmuludq $Yi,$TEMP1,$TEMP1 + vmovdqu -24+32*1-128($ap),$TEMP0 + vpaddq $TEMP1,$ACC8,$ACC8 + vpmuludq $Yi,$TEMP2,$TEMP2 + vmovdqu -24+32*2-128($ap),$TEMP1 + vpaddq $TEMP2,$ACC9,$ACC9 + + add $r2, $r3 + imulq -128($ap),%rbx + add %rbx,$r3 + + mov $r3, %rax + imull $n0, %eax + and \$0x1fffffff, %eax + + vpmuludq $Bi,$TEMP0,$TEMP0 + vmovd %eax, $Yi + vmovdqu -24+32*3-128($ap),$TEMP2 + vpaddq $TEMP0,$ACC1,$ACC1 + vpmuludq $Bi,$TEMP1,$TEMP1 + vpbroadcastq $Yi, $Yi + vmovdqu -24+32*4-128($ap),$TEMP0 + vpaddq $TEMP1,$ACC2,$ACC2 + vpmuludq $Bi,$TEMP2,$TEMP2 + vmovdqu -24+32*5-128($ap),$TEMP1 + vpaddq $TEMP2,$ACC3,$ACC3 + vpmuludq $Bi,$TEMP0,$TEMP0 + vmovdqu -24+32*6-128($ap),$TEMP2 + vpaddq $TEMP0,$ACC4,$ACC4 + vpmuludq $Bi,$TEMP1,$TEMP1 + vmovdqu -24+32*7-128($ap),$TEMP0 + vpaddq $TEMP1,$ACC5,$ACC5 + vpmuludq $Bi,$TEMP2,$TEMP2 + vmovdqu -24+32*8-128($ap),$TEMP1 + vpaddq $TEMP2,$ACC6,$ACC6 + vpmuludq $Bi,$TEMP0,$TEMP0 + vmovdqu -24+32*9-128($ap),$TEMP2 + vpaddq $TEMP0,$ACC7,$ACC7 + vpmuludq $Bi,$TEMP1,$TEMP1 + vpaddq $TEMP1,$ACC8,$ACC8 + vpmuludq $Bi,$TEMP2,$TEMP2 + vpbroadcastq 32($bp), $Bi + vpaddq $TEMP2,$ACC9,$ACC9 + add \$32, $bp # $bp++ + + vmovdqu -24+32*1-128($np),$TEMP0 + imulq -128($np),%rax + add %rax,$r3 + shr \$29, $r3 + + vmovdqu -24+32*2-128($np),$TEMP1 + vpmuludq $Yi,$TEMP0,$TEMP0 + vmovq $Bi, %rbx + vmovdqu -24+32*3-128($np),$TEMP2 + vpaddq $TEMP0,$ACC1,$ACC0 # $ACC0==$TEMP0 + vpmuludq $Yi,$TEMP1,$TEMP1 + vmovdqu $ACC0, (%rsp) # transfer $r0-$r3 + vpaddq $TEMP1,$ACC2,$ACC1 + vmovdqu -24+32*4-128($np),$TEMP0 + vpmuludq $Yi,$TEMP2,$TEMP2 + vmovdqu -24+32*5-128($np),$TEMP1 + vpaddq $TEMP2,$ACC3,$ACC2 + vpmuludq $Yi,$TEMP0,$TEMP0 + vmovdqu -24+32*6-128($np),$TEMP2 + vpaddq $TEMP0,$ACC4,$ACC3 + vpmuludq $Yi,$TEMP1,$TEMP1 + vmovdqu -24+32*7-128($np),$TEMP0 + vpaddq $TEMP1,$ACC5,$ACC4 + vpmuludq $Yi,$TEMP2,$TEMP2 + vmovdqu -24+32*8-128($np),$TEMP1 + vpaddq $TEMP2,$ACC6,$ACC5 + vpmuludq $Yi,$TEMP0,$TEMP0 + vmovdqu -24+32*9-128($np),$TEMP2 + mov $r3, $r0 + vpaddq $TEMP0,$ACC7,$ACC6 + vpmuludq $Yi,$TEMP1,$TEMP1 + add (%rsp), $r0 + vpaddq $TEMP1,$ACC8,$ACC7 + vpmuludq $Yi,$TEMP2,$TEMP2 + vmovq $r3, $TEMP1 + vpaddq $TEMP2,$ACC9,$ACC8 + + dec $i + jnz .Loop_mul_1024 +___ + +# (*) Original implementation was correcting ACC1-ACC3 for overflow +# after 7 loop runs, or after 28 iterations, or 56 additions. +# But as we underutilize resources, it's possible to correct in +# each iteration with marginal performance loss. But then, as +# we do it in each iteration, we can correct less digits, and +# avoid performance penalties completely. + +$TEMP0 = $ACC9; +$TEMP3 = $Bi; +$TEMP4 = $Yi; +$code.=<<___; + vpaddq (%rsp), $TEMP1, $ACC0 + + vpsrlq \$29, $ACC0, $TEMP1 + vpand $AND_MASK, $ACC0, $ACC0 + vpsrlq \$29, $ACC1, $TEMP2 + vpand $AND_MASK, $ACC1, $ACC1 + vpsrlq \$29, $ACC2, $TEMP3 + vpermq \$0x93, $TEMP1, $TEMP1 + vpand $AND_MASK, $ACC2, $ACC2 + vpsrlq \$29, $ACC3, $TEMP4 + vpermq \$0x93, $TEMP2, $TEMP2 + vpand $AND_MASK, $ACC3, $ACC3 + + vpblendd \$3, $ZERO, $TEMP1, $TEMP0 + vpermq \$0x93, $TEMP3, $TEMP3 + vpblendd \$3, $TEMP1, $TEMP2, $TEMP1 + vpermq \$0x93, $TEMP4, $TEMP4 + vpaddq $TEMP0, $ACC0, $ACC0 + vpblendd \$3, $TEMP2, $TEMP3, $TEMP2 + vpaddq $TEMP1, $ACC1, $ACC1 + vpblendd \$3, $TEMP3, $TEMP4, $TEMP3 + vpaddq $TEMP2, $ACC2, $ACC2 + vpblendd \$3, $TEMP4, $ZERO, $TEMP4 + vpaddq $TEMP3, $ACC3, $ACC3 + vpaddq $TEMP4, $ACC4, $ACC4 + + vpsrlq \$29, $ACC0, $TEMP1 + vpand $AND_MASK, $ACC0, $ACC0 + vpsrlq \$29, $ACC1, $TEMP2 + vpand $AND_MASK, $ACC1, $ACC1 + vpsrlq \$29, $ACC2, $TEMP3 + vpermq \$0x93, $TEMP1, $TEMP1 + vpand $AND_MASK, $ACC2, $ACC2 + vpsrlq \$29, $ACC3, $TEMP4 + vpermq \$0x93, $TEMP2, $TEMP2 + vpand $AND_MASK, $ACC3, $ACC3 + vpermq \$0x93, $TEMP3, $TEMP3 + + vpblendd \$3, $ZERO, $TEMP1, $TEMP0 + vpermq \$0x93, $TEMP4, $TEMP4 + vpblendd \$3, $TEMP1, $TEMP2, $TEMP1 + vpaddq $TEMP0, $ACC0, $ACC0 + vpblendd \$3, $TEMP2, $TEMP3, $TEMP2 + vpaddq $TEMP1, $ACC1, $ACC1 + vpblendd \$3, $TEMP3, $TEMP4, $TEMP3 + vpaddq $TEMP2, $ACC2, $ACC2 + vpblendd \$3, $TEMP4, $ZERO, $TEMP4 + vpaddq $TEMP3, $ACC3, $ACC3 + vpaddq $TEMP4, $ACC4, $ACC4 + + vmovdqu $ACC0, 0-128($rp) + vmovdqu $ACC1, 32-128($rp) + vmovdqu $ACC2, 64-128($rp) + vmovdqu $ACC3, 96-128($rp) +___ + +$TEMP5=$ACC0; +$code.=<<___; + vpsrlq \$29, $ACC4, $TEMP1 + vpand $AND_MASK, $ACC4, $ACC4 + vpsrlq \$29, $ACC5, $TEMP2 + vpand $AND_MASK, $ACC5, $ACC5 + vpsrlq \$29, $ACC6, $TEMP3 + vpermq \$0x93, $TEMP1, $TEMP1 + vpand $AND_MASK, $ACC6, $ACC6 + vpsrlq \$29, $ACC7, $TEMP4 + vpermq \$0x93, $TEMP2, $TEMP2 + vpand $AND_MASK, $ACC7, $ACC7 + vpsrlq \$29, $ACC8, $TEMP5 + vpermq \$0x93, $TEMP3, $TEMP3 + vpand $AND_MASK, $ACC8, $ACC8 + vpermq \$0x93, $TEMP4, $TEMP4 + + vpblendd \$3, $ZERO, $TEMP1, $TEMP0 + vpermq \$0x93, $TEMP5, $TEMP5 + vpblendd \$3, $TEMP1, $TEMP2, $TEMP1 + vpaddq $TEMP0, $ACC4, $ACC4 + vpblendd \$3, $TEMP2, $TEMP3, $TEMP2 + vpaddq $TEMP1, $ACC5, $ACC5 + vpblendd \$3, $TEMP3, $TEMP4, $TEMP3 + vpaddq $TEMP2, $ACC6, $ACC6 + vpblendd \$3, $TEMP4, $TEMP5, $TEMP4 + vpaddq $TEMP3, $ACC7, $ACC7 + vpaddq $TEMP4, $ACC8, $ACC8 + + vpsrlq \$29, $ACC4, $TEMP1 + vpand $AND_MASK, $ACC4, $ACC4 + vpsrlq \$29, $ACC5, $TEMP2 + vpand $AND_MASK, $ACC5, $ACC5 + vpsrlq \$29, $ACC6, $TEMP3 + vpermq \$0x93, $TEMP1, $TEMP1 + vpand $AND_MASK, $ACC6, $ACC6 + vpsrlq \$29, $ACC7, $TEMP4 + vpermq \$0x93, $TEMP2, $TEMP2 + vpand $AND_MASK, $ACC7, $ACC7 + vpsrlq \$29, $ACC8, $TEMP5 + vpermq \$0x93, $TEMP3, $TEMP3 + vpand $AND_MASK, $ACC8, $ACC8 + vpermq \$0x93, $TEMP4, $TEMP4 + + vpblendd \$3, $ZERO, $TEMP1, $TEMP0 + vpermq \$0x93, $TEMP5, $TEMP5 + vpblendd \$3, $TEMP1, $TEMP2, $TEMP1 + vpaddq $TEMP0, $ACC4, $ACC4 + vpblendd \$3, $TEMP2, $TEMP3, $TEMP2 + vpaddq $TEMP1, $ACC5, $ACC5 + vpblendd \$3, $TEMP3, $TEMP4, $TEMP3 + vpaddq $TEMP2, $ACC6, $ACC6 + vpblendd \$3, $TEMP4, $TEMP5, $TEMP4 + vpaddq $TEMP3, $ACC7, $ACC7 + vpaddq $TEMP4, $ACC8, $ACC8 + + vmovdqu $ACC4, 128-128($rp) + vmovdqu $ACC5, 160-128($rp) + vmovdqu $ACC6, 192-128($rp) + vmovdqu $ACC7, 224-128($rp) + vmovdqu $ACC8, 256-128($rp) + vzeroupper + + mov %rbp, %rax +.cfi_def_cfa_register %rax +___ +$code.=<<___ if ($win64); +.Lmul_1024_in_tail: + movaps -0xd8(%rax),%xmm6 + movaps -0xc8(%rax),%xmm7 + movaps -0xb8(%rax),%xmm8 + movaps -0xa8(%rax),%xmm9 + movaps -0x98(%rax),%xmm10 + movaps -0x88(%rax),%xmm11 + movaps -0x78(%rax),%xmm12 + movaps -0x68(%rax),%xmm13 + movaps -0x58(%rax),%xmm14 + movaps -0x48(%rax),%xmm15 +___ +$code.=<<___; + mov -48(%rax),%r15 +.cfi_restore %r15 + mov -40(%rax),%r14 +.cfi_restore %r14 + mov -32(%rax),%r13 +.cfi_restore %r13 + mov -24(%rax),%r12 +.cfi_restore %r12 + mov -16(%rax),%rbp +.cfi_restore %rbp + mov -8(%rax),%rbx +.cfi_restore %rbx + lea (%rax),%rsp # restore %rsp +.cfi_def_cfa_register %rsp +.Lmul_1024_epilogue: + ret +.cfi_endproc +.size rsaz_1024_mul_avx2,.-rsaz_1024_mul_avx2 +___ +} +{ +my ($out,$inp) = $win64 ? ("%rcx","%rdx") : ("%rdi","%rsi"); +my @T = map("%r$_",(8..11)); + +$code.=<<___; +.globl rsaz_1024_red2norm_avx2 +.type rsaz_1024_red2norm_avx2,\@abi-omnipotent +.align 32 +rsaz_1024_red2norm_avx2: +.cfi_startproc + sub \$-128,$inp # size optimization + xor %rax,%rax +___ + +for ($j=0,$i=0; $i<16; $i++) { + my $k=0; + while (29*$j<64*($i+1)) { # load data till boundary + $code.=" mov `8*$j-128`($inp), @T[0]\n"; + $j++; $k++; push(@T,shift(@T)); + } + $l=$k; + while ($k>1) { # shift loaded data but last value + $code.=" shl \$`29*($j-$k)`,@T[-$k]\n"; + $k--; + } + $code.=<<___; # shift last value + mov @T[-1], @T[0] + shl \$`29*($j-1)`, @T[-1] + shr \$`-29*($j-1)`, @T[0] +___ + while ($l) { # accumulate all values + $code.=" add @T[-$l], %rax\n"; + $l--; + } + $code.=<<___; + adc \$0, @T[0] # consume eventual carry + mov %rax, 8*$i($out) + mov @T[0], %rax +___ + push(@T,shift(@T)); +} +$code.=<<___; + ret +.cfi_endproc +.size rsaz_1024_red2norm_avx2,.-rsaz_1024_red2norm_avx2 + +.globl rsaz_1024_norm2red_avx2 +.type rsaz_1024_norm2red_avx2,\@abi-omnipotent +.align 32 +rsaz_1024_norm2red_avx2: +.cfi_startproc + sub \$-128,$out # size optimization + mov ($inp),@T[0] + mov \$0x1fffffff,%eax +___ +for ($j=0,$i=0; $i<16; $i++) { + $code.=" mov `8*($i+1)`($inp),@T[1]\n" if ($i<15); + $code.=" xor @T[1],@T[1]\n" if ($i==15); + my $k=1; + while (29*($j+1)<64*($i+1)) { + $code.=<<___; + mov @T[0],@T[-$k] + shr \$`29*$j`,@T[-$k] + and %rax,@T[-$k] # &0x1fffffff + mov @T[-$k],`8*$j-128`($out) +___ + $j++; $k++; + } + $code.=<<___; + shrd \$`29*$j`,@T[1],@T[0] + and %rax,@T[0] + mov @T[0],`8*$j-128`($out) +___ + $j++; + push(@T,shift(@T)); +} +$code.=<<___; + mov @T[0],`8*$j-128`($out) # zero + mov @T[0],`8*($j+1)-128`($out) + mov @T[0],`8*($j+2)-128`($out) + mov @T[0],`8*($j+3)-128`($out) + ret +.cfi_endproc +.size rsaz_1024_norm2red_avx2,.-rsaz_1024_norm2red_avx2 +___ +} +{ +my ($out,$inp,$power) = $win64 ? ("%rcx","%rdx","%r8d") : ("%rdi","%rsi","%edx"); + +$code.=<<___; +.globl rsaz_1024_scatter5_avx2 +.type rsaz_1024_scatter5_avx2,\@abi-omnipotent +.align 32 +rsaz_1024_scatter5_avx2: +.cfi_startproc + vzeroupper + vmovdqu .Lscatter_permd(%rip),%ymm5 + shl \$4,$power + lea ($out,$power),$out + mov \$9,%eax + jmp .Loop_scatter_1024 + +.align 32 +.Loop_scatter_1024: + vmovdqu ($inp),%ymm0 + lea 32($inp),$inp + vpermd %ymm0,%ymm5,%ymm0 + vmovdqu %xmm0,($out) + lea 16*32($out),$out + dec %eax + jnz .Loop_scatter_1024 + + vzeroupper + ret +.cfi_endproc +.size rsaz_1024_scatter5_avx2,.-rsaz_1024_scatter5_avx2 + +.globl rsaz_1024_gather5_avx2 +.type rsaz_1024_gather5_avx2,\@abi-omnipotent +.align 32 +rsaz_1024_gather5_avx2: +.cfi_startproc + vzeroupper + mov %rsp,%r11 +.cfi_def_cfa_register %r11 +___ +$code.=<<___ if ($win64); + lea -0x88(%rsp),%rax +.LSEH_begin_rsaz_1024_gather5: + # I can't trust assembler to use specific encoding:-( + .byte 0x48,0x8d,0x60,0xe0 # lea -0x20(%rax),%rsp + .byte 0xc5,0xf8,0x29,0x70,0xe0 # vmovaps %xmm6,-0x20(%rax) + .byte 0xc5,0xf8,0x29,0x78,0xf0 # vmovaps %xmm7,-0x10(%rax) + .byte 0xc5,0x78,0x29,0x40,0x00 # vmovaps %xmm8,0(%rax) + .byte 0xc5,0x78,0x29,0x48,0x10 # vmovaps %xmm9,0x10(%rax) + .byte 0xc5,0x78,0x29,0x50,0x20 # vmovaps %xmm10,0x20(%rax) + .byte 0xc5,0x78,0x29,0x58,0x30 # vmovaps %xmm11,0x30(%rax) + .byte 0xc5,0x78,0x29,0x60,0x40 # vmovaps %xmm12,0x40(%rax) + .byte 0xc5,0x78,0x29,0x68,0x50 # vmovaps %xmm13,0x50(%rax) + .byte 0xc5,0x78,0x29,0x70,0x60 # vmovaps %xmm14,0x60(%rax) + .byte 0xc5,0x78,0x29,0x78,0x70 # vmovaps %xmm15,0x70(%rax) +___ +$code.=<<___; + lea -0x100(%rsp),%rsp + and \$-32, %rsp + lea .Linc(%rip), %r10 + lea -128(%rsp),%rax # control u-op density + + vmovd $power, %xmm4 + vmovdqa (%r10),%ymm0 + vmovdqa 32(%r10),%ymm1 + vmovdqa 64(%r10),%ymm5 + vpbroadcastd %xmm4,%ymm4 + + vpaddd %ymm5, %ymm0, %ymm2 + vpcmpeqd %ymm4, %ymm0, %ymm0 + vpaddd %ymm5, %ymm1, %ymm3 + vpcmpeqd %ymm4, %ymm1, %ymm1 + vmovdqa %ymm0, 32*0+128(%rax) + vpaddd %ymm5, %ymm2, %ymm0 + vpcmpeqd %ymm4, %ymm2, %ymm2 + vmovdqa %ymm1, 32*1+128(%rax) + vpaddd %ymm5, %ymm3, %ymm1 + vpcmpeqd %ymm4, %ymm3, %ymm3 + vmovdqa %ymm2, 32*2+128(%rax) + vpaddd %ymm5, %ymm0, %ymm2 + vpcmpeqd %ymm4, %ymm0, %ymm0 + vmovdqa %ymm3, 32*3+128(%rax) + vpaddd %ymm5, %ymm1, %ymm3 + vpcmpeqd %ymm4, %ymm1, %ymm1 + vmovdqa %ymm0, 32*4+128(%rax) + vpaddd %ymm5, %ymm2, %ymm8 + vpcmpeqd %ymm4, %ymm2, %ymm2 + vmovdqa %ymm1, 32*5+128(%rax) + vpaddd %ymm5, %ymm3, %ymm9 + vpcmpeqd %ymm4, %ymm3, %ymm3 + vmovdqa %ymm2, 32*6+128(%rax) + vpaddd %ymm5, %ymm8, %ymm10 + vpcmpeqd %ymm4, %ymm8, %ymm8 + vmovdqa %ymm3, 32*7+128(%rax) + vpaddd %ymm5, %ymm9, %ymm11 + vpcmpeqd %ymm4, %ymm9, %ymm9 + vpaddd %ymm5, %ymm10, %ymm12 + vpcmpeqd %ymm4, %ymm10, %ymm10 + vpaddd %ymm5, %ymm11, %ymm13 + vpcmpeqd %ymm4, %ymm11, %ymm11 + vpaddd %ymm5, %ymm12, %ymm14 + vpcmpeqd %ymm4, %ymm12, %ymm12 + vpaddd %ymm5, %ymm13, %ymm15 + vpcmpeqd %ymm4, %ymm13, %ymm13 + vpcmpeqd %ymm4, %ymm14, %ymm14 + vpcmpeqd %ymm4, %ymm15, %ymm15 + + vmovdqa -32(%r10),%ymm7 # .Lgather_permd + lea 128($inp), $inp + mov \$9,$power + +.Loop_gather_1024: + vmovdqa 32*0-128($inp), %ymm0 + vmovdqa 32*1-128($inp), %ymm1 + vmovdqa 32*2-128($inp), %ymm2 + vmovdqa 32*3-128($inp), %ymm3 + vpand 32*0+128(%rax), %ymm0, %ymm0 + vpand 32*1+128(%rax), %ymm1, %ymm1 + vpand 32*2+128(%rax), %ymm2, %ymm2 + vpor %ymm0, %ymm1, %ymm4 + vpand 32*3+128(%rax), %ymm3, %ymm3 + vmovdqa 32*4-128($inp), %ymm0 + vmovdqa 32*5-128($inp), %ymm1 + vpor %ymm2, %ymm3, %ymm5 + vmovdqa 32*6-128($inp), %ymm2 + vmovdqa 32*7-128($inp), %ymm3 + vpand 32*4+128(%rax), %ymm0, %ymm0 + vpand 32*5+128(%rax), %ymm1, %ymm1 + vpand 32*6+128(%rax), %ymm2, %ymm2 + vpor %ymm0, %ymm4, %ymm4 + vpand 32*7+128(%rax), %ymm3, %ymm3 + vpand 32*8-128($inp), %ymm8, %ymm0 + vpor %ymm1, %ymm5, %ymm5 + vpand 32*9-128($inp), %ymm9, %ymm1 + vpor %ymm2, %ymm4, %ymm4 + vpand 32*10-128($inp),%ymm10, %ymm2 + vpor %ymm3, %ymm5, %ymm5 + vpand 32*11-128($inp),%ymm11, %ymm3 + vpor %ymm0, %ymm4, %ymm4 + vpand 32*12-128($inp),%ymm12, %ymm0 + vpor %ymm1, %ymm5, %ymm5 + vpand 32*13-128($inp),%ymm13, %ymm1 + vpor %ymm2, %ymm4, %ymm4 + vpand 32*14-128($inp),%ymm14, %ymm2 + vpor %ymm3, %ymm5, %ymm5 + vpand 32*15-128($inp),%ymm15, %ymm3 + lea 32*16($inp), $inp + vpor %ymm0, %ymm4, %ymm4 + vpor %ymm1, %ymm5, %ymm5 + vpor %ymm2, %ymm4, %ymm4 + vpor %ymm3, %ymm5, %ymm5 + + vpor %ymm5, %ymm4, %ymm4 + vextracti128 \$1, %ymm4, %xmm5 # upper half is cleared + vpor %xmm4, %xmm5, %xmm5 + vpermd %ymm5,%ymm7,%ymm5 + vmovdqu %ymm5,($out) + lea 32($out),$out + dec $power + jnz .Loop_gather_1024 + + vpxor %ymm0,%ymm0,%ymm0 + vmovdqu %ymm0,($out) + vzeroupper +___ +$code.=<<___ if ($win64); + movaps -0xa8(%r11),%xmm6 + movaps -0x98(%r11),%xmm7 + movaps -0x88(%r11),%xmm8 + movaps -0x78(%r11),%xmm9 + movaps -0x68(%r11),%xmm10 + movaps -0x58(%r11),%xmm11 + movaps -0x48(%r11),%xmm12 + movaps -0x38(%r11),%xmm13 + movaps -0x28(%r11),%xmm14 + movaps -0x18(%r11),%xmm15 +___ +$code.=<<___; + lea (%r11),%rsp +.cfi_def_cfa_register %rsp + ret +.cfi_endproc +.LSEH_end_rsaz_1024_gather5: +.size rsaz_1024_gather5_avx2,.-rsaz_1024_gather5_avx2 +___ +} + +$code.=<<___; +.extern OPENSSL_ia32cap_P +.globl rsaz_avx2_eligible +.type rsaz_avx2_eligible,\@abi-omnipotent +.align 32 +rsaz_avx2_eligible: + mov OPENSSL_ia32cap_P+8(%rip),%eax +___ +$code.=<<___ if ($addx); + mov \$`1<<8|1<<19`,%ecx + mov \$0,%edx + and %eax,%ecx + cmp \$`1<<8|1<<19`,%ecx # check for BMI2+AD*X + cmove %edx,%eax +___ +$code.=<<___; + and \$`1<<5`,%eax + shr \$5,%eax + ret +.size rsaz_avx2_eligible,.-rsaz_avx2_eligible + +.align 64 +.Land_mask: + .quad 0x1fffffff,0x1fffffff,0x1fffffff,0x1fffffff +.Lscatter_permd: + .long 0,2,4,6,7,7,7,7 +.Lgather_permd: + .long 0,7,1,7,2,7,3,7 +.Linc: + .long 0,0,0,0, 1,1,1,1 + .long 2,2,2,2, 3,3,3,3 + .long 4,4,4,4, 4,4,4,4 +.align 64 +___ + +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___ +.extern __imp_RtlVirtualUnwind +.type rsaz_se_handler,\@abi-omnipotent +.align 16 +rsaz_se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->RipRip>=epilogue label + jae .Lcommon_seh_tail + + mov 160($context),%rbp # pull context->Rbp + + mov 8(%r11),%r10d # HandlerData[2] + lea (%rsi,%r10),%r10 # "in tail" label + cmp %r10,%rbx # context->Rip>="in tail" label + cmovc %rbp,%rax + + mov -48(%rax),%r15 + mov -40(%rax),%r14 + mov -32(%rax),%r13 + mov -24(%rax),%r12 + mov -16(%rax),%rbp + mov -8(%rax),%rbx + mov %r15,240($context) + mov %r14,232($context) + mov %r13,224($context) + mov %r12,216($context) + mov %rbp,160($context) + mov %rbx,144($context) + + lea -0xd8(%rax),%rsi # %xmm save area + lea 512($context),%rdi # & context.Xmm6 + mov \$20,%ecx # 10*sizeof(%xmm0)/sizeof(%rax) + .long 0xa548f3fc # cld; rep movsq + +.Lcommon_seh_tail: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size rsaz_se_handler,.-rsaz_se_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_rsaz_1024_sqr_avx2 + .rva .LSEH_end_rsaz_1024_sqr_avx2 + .rva .LSEH_info_rsaz_1024_sqr_avx2 + + .rva .LSEH_begin_rsaz_1024_mul_avx2 + .rva .LSEH_end_rsaz_1024_mul_avx2 + .rva .LSEH_info_rsaz_1024_mul_avx2 + + .rva .LSEH_begin_rsaz_1024_gather5 + .rva .LSEH_end_rsaz_1024_gather5 + .rva .LSEH_info_rsaz_1024_gather5 +.section .xdata +.align 8 +.LSEH_info_rsaz_1024_sqr_avx2: + .byte 9,0,0,0 + .rva rsaz_se_handler + .rva .Lsqr_1024_body,.Lsqr_1024_epilogue,.Lsqr_1024_in_tail + .long 0 +.LSEH_info_rsaz_1024_mul_avx2: + .byte 9,0,0,0 + .rva rsaz_se_handler + .rva .Lmul_1024_body,.Lmul_1024_epilogue,.Lmul_1024_in_tail + .long 0 +.LSEH_info_rsaz_1024_gather5: + .byte 0x01,0x36,0x17,0x0b + .byte 0x36,0xf8,0x09,0x00 # vmovaps 0x90(rsp),xmm15 + .byte 0x31,0xe8,0x08,0x00 # vmovaps 0x80(rsp),xmm14 + .byte 0x2c,0xd8,0x07,0x00 # vmovaps 0x70(rsp),xmm13 + .byte 0x27,0xc8,0x06,0x00 # vmovaps 0x60(rsp),xmm12 + .byte 0x22,0xb8,0x05,0x00 # vmovaps 0x50(rsp),xmm11 + .byte 0x1d,0xa8,0x04,0x00 # vmovaps 0x40(rsp),xmm10 + .byte 0x18,0x98,0x03,0x00 # vmovaps 0x30(rsp),xmm9 + .byte 0x13,0x88,0x02,0x00 # vmovaps 0x20(rsp),xmm8 + .byte 0x0e,0x78,0x01,0x00 # vmovaps 0x10(rsp),xmm7 + .byte 0x09,0x68,0x00,0x00 # vmovaps 0x00(rsp),xmm6 + .byte 0x04,0x01,0x15,0x00 # sub rsp,0xa8 + .byte 0x00,0xb3,0x00,0x00 # set_frame r11 +___ +} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval($1)/ge; + + s/\b(sh[rl]d?\s+\$)(-?[0-9]+)/$1.$2%64/ge or + + s/\b(vmov[dq])\b(.+)%ymm([0-9]+)/$1$2%xmm$3/go or + s/\b(vmovdqu)\b(.+)%x%ymm([0-9]+)/$1$2%xmm$3/go or + s/\b(vpinsr[qd])\b(.+)%ymm([0-9]+)/$1$2%xmm$3/go or + s/\b(vpextr[qd])\b(.+)%ymm([0-9]+)/$1$2%xmm$3/go or + s/\b(vpbroadcast[qd]\s+)%ymm([0-9]+)/$1%xmm$2/go; + print $_,"\n"; +} + +}}} else {{{ +print <<___; # assembler is too old +.text + +.globl rsaz_avx2_eligible +.type rsaz_avx2_eligible,\@abi-omnipotent +rsaz_avx2_eligible: + xor %eax,%eax + ret +.size rsaz_avx2_eligible,.-rsaz_avx2_eligible + +.globl rsaz_1024_sqr_avx2 +.globl rsaz_1024_mul_avx2 +.globl rsaz_1024_norm2red_avx2 +.globl rsaz_1024_red2norm_avx2 +.globl rsaz_1024_scatter5_avx2 +.globl rsaz_1024_gather5_avx2 +.type rsaz_1024_sqr_avx2,\@abi-omnipotent +rsaz_1024_sqr_avx2: +rsaz_1024_mul_avx2: +rsaz_1024_norm2red_avx2: +rsaz_1024_red2norm_avx2: +rsaz_1024_scatter5_avx2: +rsaz_1024_gather5_avx2: + .byte 0x0f,0x0b # ud2 + ret +.size rsaz_1024_sqr_avx2,.-rsaz_1024_sqr_avx2 +___ +}}} + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/rsaz-x86_64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/rsaz-x86_64.pl new file mode 100755 index 000000000..b1797b649 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/rsaz-x86_64.pl @@ -0,0 +1,2404 @@ +#! /usr/bin/env perl +# Copyright 2013-2016 The OpenSSL Project Authors. All Rights Reserved. +# Copyright (c) 2012, Intel Corporation. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html +# +# Originally written by Shay Gueron (1, 2), and Vlad Krasnov (1) +# (1) Intel Corporation, Israel Development Center, Haifa, Israel +# (2) University of Haifa, Israel +# +# References: +# [1] S. Gueron, "Efficient Software Implementations of Modular +# Exponentiation", http://eprint.iacr.org/2011/239 +# [2] S. Gueron, V. Krasnov. "Speeding up Big-Numbers Squaring". +# IEEE Proceedings of 9th International Conference on Information +# Technology: New Generations (ITNG 2012), 821-823 (2012). +# [3] S. Gueron, Efficient Software Implementations of Modular Exponentiation +# Journal of Cryptographic Engineering 2:31-43 (2012). +# [4] S. Gueron, V. Krasnov: "[PATCH] Efficient and side channel analysis +# resistant 512-bit and 1024-bit modular exponentiation for optimizing +# RSA1024 and RSA2048 on x86_64 platforms", +# http://rt.openssl.org/Ticket/Display.html?id=2582&user=guest&pass=guest +# +# While original submission covers 512- and 1024-bit exponentiation, +# this module is limited to 512-bit version only (and as such +# accelerates RSA1024 sign). This is because improvement for longer +# keys is not high enough to justify the effort, highest measured +# was ~5% on Westmere. [This is relative to OpenSSL 1.0.2, upcoming +# for the moment of this writing!] Nor does this module implement +# "monolithic" complete exponentiation jumbo-subroutine, but adheres +# to more modular mixture of C and assembly. And it's optimized even +# for processors other than Intel Core family (see table below for +# improvement coefficients). +# +# +# RSA1024 sign/sec this/original |this/rsax(*) this/fips(*) +# ----------------+--------------------------- +# Opteron +13% |+5% +20% +# Bulldozer -0% |-1% +10% +# P4 +11% |+7% +8% +# Westmere +5% |+14% +17% +# Sandy Bridge +2% |+12% +29% +# Ivy Bridge +1% |+11% +35% +# Haswell(**) -0% |+12% +39% +# Atom +13% |+11% +4% +# VIA Nano +70% |+9% +25% +# +# (*) rsax engine and fips numbers are presented for reference +# purposes; +# (**) MULX was attempted, but found to give only marginal improvement; + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +*STDOUT=*OUT; + +if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler version ([2-9]\.[0-9]+)/) { + $addx = ($1>=2.23); +} + +if (!$addx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) && + `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) { + $addx = ($1>=2.10); +} + +if (!$addx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && + `ml64 2>&1` =~ /Version ([0-9]+)\./) { + $addx = ($1>=12); +} + +if (!$addx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9])\.([0-9]+)/) { + my $ver = $2 + $3/100.0; # 3.1->3.01, 3.10->3.10 + $addx = ($ver>=3.03); +} + +($out, $inp, $mod) = ("%rdi", "%rsi", "%rbp"); # common internal API +{ +my ($out,$inp,$mod,$n0,$times) = ("%rdi","%rsi","%rdx","%rcx","%r8d"); + +$code.=<<___; +.text + +.extern OPENSSL_ia32cap_P + +.globl rsaz_512_sqr +.type rsaz_512_sqr,\@function,5 +.align 32 +rsaz_512_sqr: # 25-29% faster than rsaz_512_mul +.cfi_startproc + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + + subq \$128+24, %rsp +.cfi_adjust_cfa_offset 128+24 +.Lsqr_body: + movq $mod, %rbp # common argument + movq ($inp), %rdx + movq 8($inp), %rax + movq $n0, 128(%rsp) +___ +$code.=<<___ if ($addx); + movl \$0x80100,%r11d + andl OPENSSL_ia32cap_P+8(%rip),%r11d + cmpl \$0x80100,%r11d # check for MULX and ADO/CX + je .Loop_sqrx +___ +$code.=<<___; + jmp .Loop_sqr + +.align 32 +.Loop_sqr: + movl $times,128+8(%rsp) +#first iteration + movq %rdx, %rbx + mulq %rdx + movq %rax, %r8 + movq 16($inp), %rax + movq %rdx, %r9 + + mulq %rbx + addq %rax, %r9 + movq 24($inp), %rax + movq %rdx, %r10 + adcq \$0, %r10 + + mulq %rbx + addq %rax, %r10 + movq 32($inp), %rax + movq %rdx, %r11 + adcq \$0, %r11 + + mulq %rbx + addq %rax, %r11 + movq 40($inp), %rax + movq %rdx, %r12 + adcq \$0, %r12 + + mulq %rbx + addq %rax, %r12 + movq 48($inp), %rax + movq %rdx, %r13 + adcq \$0, %r13 + + mulq %rbx + addq %rax, %r13 + movq 56($inp), %rax + movq %rdx, %r14 + adcq \$0, %r14 + + mulq %rbx + addq %rax, %r14 + movq %rbx, %rax + movq %rdx, %r15 + adcq \$0, %r15 + + addq %r8, %r8 #shlq \$1, %r8 + movq %r9, %rcx + adcq %r9, %r9 #shld \$1, %r8, %r9 + + mulq %rax + movq %rax, (%rsp) + addq %rdx, %r8 + adcq \$0, %r9 + + movq %r8, 8(%rsp) + shrq \$63, %rcx + +#second iteration + movq 8($inp), %r8 + movq 16($inp), %rax + mulq %r8 + addq %rax, %r10 + movq 24($inp), %rax + movq %rdx, %rbx + adcq \$0, %rbx + + mulq %r8 + addq %rax, %r11 + movq 32($inp), %rax + adcq \$0, %rdx + addq %rbx, %r11 + movq %rdx, %rbx + adcq \$0, %rbx + + mulq %r8 + addq %rax, %r12 + movq 40($inp), %rax + adcq \$0, %rdx + addq %rbx, %r12 + movq %rdx, %rbx + adcq \$0, %rbx + + mulq %r8 + addq %rax, %r13 + movq 48($inp), %rax + adcq \$0, %rdx + addq %rbx, %r13 + movq %rdx, %rbx + adcq \$0, %rbx + + mulq %r8 + addq %rax, %r14 + movq 56($inp), %rax + adcq \$0, %rdx + addq %rbx, %r14 + movq %rdx, %rbx + adcq \$0, %rbx + + mulq %r8 + addq %rax, %r15 + movq %r8, %rax + adcq \$0, %rdx + addq %rbx, %r15 + movq %rdx, %r8 + movq %r10, %rdx + adcq \$0, %r8 + + add %rdx, %rdx + lea (%rcx,%r10,2), %r10 #shld \$1, %rcx, %r10 + movq %r11, %rbx + adcq %r11, %r11 #shld \$1, %r10, %r11 + + mulq %rax + addq %rax, %r9 + adcq %rdx, %r10 + adcq \$0, %r11 + + movq %r9, 16(%rsp) + movq %r10, 24(%rsp) + shrq \$63, %rbx + +#third iteration + movq 16($inp), %r9 + movq 24($inp), %rax + mulq %r9 + addq %rax, %r12 + movq 32($inp), %rax + movq %rdx, %rcx + adcq \$0, %rcx + + mulq %r9 + addq %rax, %r13 + movq 40($inp), %rax + adcq \$0, %rdx + addq %rcx, %r13 + movq %rdx, %rcx + adcq \$0, %rcx + + mulq %r9 + addq %rax, %r14 + movq 48($inp), %rax + adcq \$0, %rdx + addq %rcx, %r14 + movq %rdx, %rcx + adcq \$0, %rcx + + mulq %r9 + movq %r12, %r10 + lea (%rbx,%r12,2), %r12 #shld \$1, %rbx, %r12 + addq %rax, %r15 + movq 56($inp), %rax + adcq \$0, %rdx + addq %rcx, %r15 + movq %rdx, %rcx + adcq \$0, %rcx + + mulq %r9 + shrq \$63, %r10 + addq %rax, %r8 + movq %r9, %rax + adcq \$0, %rdx + addq %rcx, %r8 + movq %rdx, %r9 + adcq \$0, %r9 + + movq %r13, %rcx + leaq (%r10,%r13,2), %r13 #shld \$1, %r12, %r13 + + mulq %rax + addq %rax, %r11 + adcq %rdx, %r12 + adcq \$0, %r13 + + movq %r11, 32(%rsp) + movq %r12, 40(%rsp) + shrq \$63, %rcx + +#fourth iteration + movq 24($inp), %r10 + movq 32($inp), %rax + mulq %r10 + addq %rax, %r14 + movq 40($inp), %rax + movq %rdx, %rbx + adcq \$0, %rbx + + mulq %r10 + addq %rax, %r15 + movq 48($inp), %rax + adcq \$0, %rdx + addq %rbx, %r15 + movq %rdx, %rbx + adcq \$0, %rbx + + mulq %r10 + movq %r14, %r12 + leaq (%rcx,%r14,2), %r14 #shld \$1, %rcx, %r14 + addq %rax, %r8 + movq 56($inp), %rax + adcq \$0, %rdx + addq %rbx, %r8 + movq %rdx, %rbx + adcq \$0, %rbx + + mulq %r10 + shrq \$63, %r12 + addq %rax, %r9 + movq %r10, %rax + adcq \$0, %rdx + addq %rbx, %r9 + movq %rdx, %r10 + adcq \$0, %r10 + + movq %r15, %rbx + leaq (%r12,%r15,2),%r15 #shld \$1, %r14, %r15 + + mulq %rax + addq %rax, %r13 + adcq %rdx, %r14 + adcq \$0, %r15 + + movq %r13, 48(%rsp) + movq %r14, 56(%rsp) + shrq \$63, %rbx + +#fifth iteration + movq 32($inp), %r11 + movq 40($inp), %rax + mulq %r11 + addq %rax, %r8 + movq 48($inp), %rax + movq %rdx, %rcx + adcq \$0, %rcx + + mulq %r11 + addq %rax, %r9 + movq 56($inp), %rax + adcq \$0, %rdx + movq %r8, %r12 + leaq (%rbx,%r8,2), %r8 #shld \$1, %rbx, %r8 + addq %rcx, %r9 + movq %rdx, %rcx + adcq \$0, %rcx + + mulq %r11 + shrq \$63, %r12 + addq %rax, %r10 + movq %r11, %rax + adcq \$0, %rdx + addq %rcx, %r10 + movq %rdx, %r11 + adcq \$0, %r11 + + movq %r9, %rcx + leaq (%r12,%r9,2), %r9 #shld \$1, %r8, %r9 + + mulq %rax + addq %rax, %r15 + adcq %rdx, %r8 + adcq \$0, %r9 + + movq %r15, 64(%rsp) + movq %r8, 72(%rsp) + shrq \$63, %rcx + +#sixth iteration + movq 40($inp), %r12 + movq 48($inp), %rax + mulq %r12 + addq %rax, %r10 + movq 56($inp), %rax + movq %rdx, %rbx + adcq \$0, %rbx + + mulq %r12 + addq %rax, %r11 + movq %r12, %rax + movq %r10, %r15 + leaq (%rcx,%r10,2), %r10 #shld \$1, %rcx, %r10 + adcq \$0, %rdx + shrq \$63, %r15 + addq %rbx, %r11 + movq %rdx, %r12 + adcq \$0, %r12 + + movq %r11, %rbx + leaq (%r15,%r11,2), %r11 #shld \$1, %r10, %r11 + + mulq %rax + addq %rax, %r9 + adcq %rdx, %r10 + adcq \$0, %r11 + + movq %r9, 80(%rsp) + movq %r10, 88(%rsp) + +#seventh iteration + movq 48($inp), %r13 + movq 56($inp), %rax + mulq %r13 + addq %rax, %r12 + movq %r13, %rax + movq %rdx, %r13 + adcq \$0, %r13 + + xorq %r14, %r14 + shlq \$1, %rbx + adcq %r12, %r12 #shld \$1, %rbx, %r12 + adcq %r13, %r13 #shld \$1, %r12, %r13 + adcq %r14, %r14 #shld \$1, %r13, %r14 + + mulq %rax + addq %rax, %r11 + adcq %rdx, %r12 + adcq \$0, %r13 + + movq %r11, 96(%rsp) + movq %r12, 104(%rsp) + +#eighth iteration + movq 56($inp), %rax + mulq %rax + addq %rax, %r13 + adcq \$0, %rdx + + addq %rdx, %r14 + + movq %r13, 112(%rsp) + movq %r14, 120(%rsp) + + movq (%rsp), %r8 + movq 8(%rsp), %r9 + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + movq 32(%rsp), %r12 + movq 40(%rsp), %r13 + movq 48(%rsp), %r14 + movq 56(%rsp), %r15 + + call __rsaz_512_reduce + + addq 64(%rsp), %r8 + adcq 72(%rsp), %r9 + adcq 80(%rsp), %r10 + adcq 88(%rsp), %r11 + adcq 96(%rsp), %r12 + adcq 104(%rsp), %r13 + adcq 112(%rsp), %r14 + adcq 120(%rsp), %r15 + sbbq %rcx, %rcx + + call __rsaz_512_subtract + + movq %r8, %rdx + movq %r9, %rax + movl 128+8(%rsp), $times + movq $out, $inp + + decl $times + jnz .Loop_sqr +___ +if ($addx) { +$code.=<<___; + jmp .Lsqr_tail + +.align 32 +.Loop_sqrx: + movl $times,128+8(%rsp) + movq $out, %xmm0 # off-load + movq %rbp, %xmm1 # off-load +#first iteration + mulx %rax, %r8, %r9 + + mulx 16($inp), %rcx, %r10 + xor %rbp, %rbp # cf=0, of=0 + + mulx 24($inp), %rax, %r11 + adcx %rcx, %r9 + + mulx 32($inp), %rcx, %r12 + adcx %rax, %r10 + + mulx 40($inp), %rax, %r13 + adcx %rcx, %r11 + + .byte 0xc4,0x62,0xf3,0xf6,0xb6,0x30,0x00,0x00,0x00 # mulx 48($inp), %rcx, %r14 + adcx %rax, %r12 + adcx %rcx, %r13 + + .byte 0xc4,0x62,0xfb,0xf6,0xbe,0x38,0x00,0x00,0x00 # mulx 56($inp), %rax, %r15 + adcx %rax, %r14 + adcx %rbp, %r15 # %rbp is 0 + + mov %r9, %rcx + shld \$1, %r8, %r9 + shl \$1, %r8 + + xor %ebp, %ebp + mulx %rdx, %rax, %rdx + adcx %rdx, %r8 + mov 8($inp), %rdx + adcx %rbp, %r9 + + mov %rax, (%rsp) + mov %r8, 8(%rsp) + +#second iteration + mulx 16($inp), %rax, %rbx + adox %rax, %r10 + adcx %rbx, %r11 + + .byte 0xc4,0x62,0xc3,0xf6,0x86,0x18,0x00,0x00,0x00 # mulx 24($inp), $out, %r8 + adox $out, %r11 + adcx %r8, %r12 + + mulx 32($inp), %rax, %rbx + adox %rax, %r12 + adcx %rbx, %r13 + + mulx 40($inp), $out, %r8 + adox $out, %r13 + adcx %r8, %r14 + + .byte 0xc4,0xe2,0xfb,0xf6,0x9e,0x30,0x00,0x00,0x00 # mulx 48($inp), %rax, %rbx + adox %rax, %r14 + adcx %rbx, %r15 + + .byte 0xc4,0x62,0xc3,0xf6,0x86,0x38,0x00,0x00,0x00 # mulx 56($inp), $out, %r8 + adox $out, %r15 + adcx %rbp, %r8 + adox %rbp, %r8 + + mov %r11, %rbx + shld \$1, %r10, %r11 + shld \$1, %rcx, %r10 + + xor %ebp,%ebp + mulx %rdx, %rax, %rcx + mov 16($inp), %rdx + adcx %rax, %r9 + adcx %rcx, %r10 + adcx %rbp, %r11 + + mov %r9, 16(%rsp) + .byte 0x4c,0x89,0x94,0x24,0x18,0x00,0x00,0x00 # mov %r10, 24(%rsp) + +#third iteration + .byte 0xc4,0x62,0xc3,0xf6,0x8e,0x18,0x00,0x00,0x00 # mulx 24($inp), $out, %r9 + adox $out, %r12 + adcx %r9, %r13 + + mulx 32($inp), %rax, %rcx + adox %rax, %r13 + adcx %rcx, %r14 + + mulx 40($inp), $out, %r9 + adox $out, %r14 + adcx %r9, %r15 + + .byte 0xc4,0xe2,0xfb,0xf6,0x8e,0x30,0x00,0x00,0x00 # mulx 48($inp), %rax, %rcx + adox %rax, %r15 + adcx %rcx, %r8 + + .byte 0xc4,0x62,0xc3,0xf6,0x8e,0x38,0x00,0x00,0x00 # mulx 56($inp), $out, %r9 + adox $out, %r8 + adcx %rbp, %r9 + adox %rbp, %r9 + + mov %r13, %rcx + shld \$1, %r12, %r13 + shld \$1, %rbx, %r12 + + xor %ebp, %ebp + mulx %rdx, %rax, %rdx + adcx %rax, %r11 + adcx %rdx, %r12 + mov 24($inp), %rdx + adcx %rbp, %r13 + + mov %r11, 32(%rsp) + .byte 0x4c,0x89,0xa4,0x24,0x28,0x00,0x00,0x00 # mov %r12, 40(%rsp) + +#fourth iteration + .byte 0xc4,0xe2,0xfb,0xf6,0x9e,0x20,0x00,0x00,0x00 # mulx 32($inp), %rax, %rbx + adox %rax, %r14 + adcx %rbx, %r15 + + mulx 40($inp), $out, %r10 + adox $out, %r15 + adcx %r10, %r8 + + mulx 48($inp), %rax, %rbx + adox %rax, %r8 + adcx %rbx, %r9 + + mulx 56($inp), $out, %r10 + adox $out, %r9 + adcx %rbp, %r10 + adox %rbp, %r10 + + .byte 0x66 + mov %r15, %rbx + shld \$1, %r14, %r15 + shld \$1, %rcx, %r14 + + xor %ebp, %ebp + mulx %rdx, %rax, %rdx + adcx %rax, %r13 + adcx %rdx, %r14 + mov 32($inp), %rdx + adcx %rbp, %r15 + + mov %r13, 48(%rsp) + mov %r14, 56(%rsp) + +#fifth iteration + .byte 0xc4,0x62,0xc3,0xf6,0x9e,0x28,0x00,0x00,0x00 # mulx 40($inp), $out, %r11 + adox $out, %r8 + adcx %r11, %r9 + + mulx 48($inp), %rax, %rcx + adox %rax, %r9 + adcx %rcx, %r10 + + mulx 56($inp), $out, %r11 + adox $out, %r10 + adcx %rbp, %r11 + adox %rbp, %r11 + + mov %r9, %rcx + shld \$1, %r8, %r9 + shld \$1, %rbx, %r8 + + xor %ebp, %ebp + mulx %rdx, %rax, %rdx + adcx %rax, %r15 + adcx %rdx, %r8 + mov 40($inp), %rdx + adcx %rbp, %r9 + + mov %r15, 64(%rsp) + mov %r8, 72(%rsp) + +#sixth iteration + .byte 0xc4,0xe2,0xfb,0xf6,0x9e,0x30,0x00,0x00,0x00 # mulx 48($inp), %rax, %rbx + adox %rax, %r10 + adcx %rbx, %r11 + + .byte 0xc4,0x62,0xc3,0xf6,0xa6,0x38,0x00,0x00,0x00 # mulx 56($inp), $out, %r12 + adox $out, %r11 + adcx %rbp, %r12 + adox %rbp, %r12 + + mov %r11, %rbx + shld \$1, %r10, %r11 + shld \$1, %rcx, %r10 + + xor %ebp, %ebp + mulx %rdx, %rax, %rdx + adcx %rax, %r9 + adcx %rdx, %r10 + mov 48($inp), %rdx + adcx %rbp, %r11 + + mov %r9, 80(%rsp) + mov %r10, 88(%rsp) + +#seventh iteration + .byte 0xc4,0x62,0xfb,0xf6,0xae,0x38,0x00,0x00,0x00 # mulx 56($inp), %rax, %r13 + adox %rax, %r12 + adox %rbp, %r13 + + xor %r14, %r14 + shld \$1, %r13, %r14 + shld \$1, %r12, %r13 + shld \$1, %rbx, %r12 + + xor %ebp, %ebp + mulx %rdx, %rax, %rdx + adcx %rax, %r11 + adcx %rdx, %r12 + mov 56($inp), %rdx + adcx %rbp, %r13 + + .byte 0x4c,0x89,0x9c,0x24,0x60,0x00,0x00,0x00 # mov %r11, 96(%rsp) + .byte 0x4c,0x89,0xa4,0x24,0x68,0x00,0x00,0x00 # mov %r12, 104(%rsp) + +#eighth iteration + mulx %rdx, %rax, %rdx + adox %rax, %r13 + adox %rbp, %rdx + + .byte 0x66 + add %rdx, %r14 + + movq %r13, 112(%rsp) + movq %r14, 120(%rsp) + movq %xmm0, $out + movq %xmm1, %rbp + + movq 128(%rsp), %rdx # pull $n0 + movq (%rsp), %r8 + movq 8(%rsp), %r9 + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + movq 32(%rsp), %r12 + movq 40(%rsp), %r13 + movq 48(%rsp), %r14 + movq 56(%rsp), %r15 + + call __rsaz_512_reducex + + addq 64(%rsp), %r8 + adcq 72(%rsp), %r9 + adcq 80(%rsp), %r10 + adcq 88(%rsp), %r11 + adcq 96(%rsp), %r12 + adcq 104(%rsp), %r13 + adcq 112(%rsp), %r14 + adcq 120(%rsp), %r15 + sbbq %rcx, %rcx + + call __rsaz_512_subtract + + movq %r8, %rdx + movq %r9, %rax + movl 128+8(%rsp), $times + movq $out, $inp + + decl $times + jnz .Loop_sqrx + +.Lsqr_tail: +___ +} +$code.=<<___; + + leaq 128+24+48(%rsp), %rax +.cfi_def_cfa %rax,8 + movq -48(%rax), %r15 +.cfi_restore %r15 + movq -40(%rax), %r14 +.cfi_restore %r14 + movq -32(%rax), %r13 +.cfi_restore %r13 + movq -24(%rax), %r12 +.cfi_restore %r12 + movq -16(%rax), %rbp +.cfi_restore %rbp + movq -8(%rax), %rbx +.cfi_restore %rbx + leaq (%rax), %rsp +.cfi_def_cfa_register %rsp +.Lsqr_epilogue: + ret +.cfi_endproc +.size rsaz_512_sqr,.-rsaz_512_sqr +___ +} +{ +my ($out,$ap,$bp,$mod,$n0) = ("%rdi","%rsi","%rdx","%rcx","%r8"); +$code.=<<___; +.globl rsaz_512_mul +.type rsaz_512_mul,\@function,5 +.align 32 +rsaz_512_mul: +.cfi_startproc + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + + subq \$128+24, %rsp +.cfi_adjust_cfa_offset 128+24 +.Lmul_body: + movq $out, %xmm0 # off-load arguments + movq $mod, %xmm1 + movq $n0, 128(%rsp) +___ +$code.=<<___ if ($addx); + movl \$0x80100,%r11d + andl OPENSSL_ia32cap_P+8(%rip),%r11d + cmpl \$0x80100,%r11d # check for MULX and ADO/CX + je .Lmulx +___ +$code.=<<___; + movq ($bp), %rbx # pass b[0] + movq $bp, %rbp # pass argument + call __rsaz_512_mul + + movq %xmm0, $out + movq %xmm1, %rbp + + movq (%rsp), %r8 + movq 8(%rsp), %r9 + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + movq 32(%rsp), %r12 + movq 40(%rsp), %r13 + movq 48(%rsp), %r14 + movq 56(%rsp), %r15 + + call __rsaz_512_reduce +___ +$code.=<<___ if ($addx); + jmp .Lmul_tail + +.align 32 +.Lmulx: + movq $bp, %rbp # pass argument + movq ($bp), %rdx # pass b[0] + call __rsaz_512_mulx + + movq %xmm0, $out + movq %xmm1, %rbp + + movq 128(%rsp), %rdx # pull $n0 + movq (%rsp), %r8 + movq 8(%rsp), %r9 + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + movq 32(%rsp), %r12 + movq 40(%rsp), %r13 + movq 48(%rsp), %r14 + movq 56(%rsp), %r15 + + call __rsaz_512_reducex +.Lmul_tail: +___ +$code.=<<___; + addq 64(%rsp), %r8 + adcq 72(%rsp), %r9 + adcq 80(%rsp), %r10 + adcq 88(%rsp), %r11 + adcq 96(%rsp), %r12 + adcq 104(%rsp), %r13 + adcq 112(%rsp), %r14 + adcq 120(%rsp), %r15 + sbbq %rcx, %rcx + + call __rsaz_512_subtract + + leaq 128+24+48(%rsp), %rax +.cfi_def_cfa %rax,8 + movq -48(%rax), %r15 +.cfi_restore %r15 + movq -40(%rax), %r14 +.cfi_restore %r14 + movq -32(%rax), %r13 +.cfi_restore %r13 + movq -24(%rax), %r12 +.cfi_restore %r12 + movq -16(%rax), %rbp +.cfi_restore %rbp + movq -8(%rax), %rbx +.cfi_restore %rbx + leaq (%rax), %rsp +.cfi_def_cfa_register %rsp +.Lmul_epilogue: + ret +.cfi_endproc +.size rsaz_512_mul,.-rsaz_512_mul +___ +} +{ +my ($out,$ap,$bp,$mod,$n0,$pwr) = ("%rdi","%rsi","%rdx","%rcx","%r8","%r9d"); +$code.=<<___; +.globl rsaz_512_mul_gather4 +.type rsaz_512_mul_gather4,\@function,6 +.align 32 +rsaz_512_mul_gather4: +.cfi_startproc + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + + subq \$`128+24+($win64?0xb0:0)`, %rsp +.cfi_adjust_cfa_offset `128+24+($win64?0xb0:0)` +___ +$code.=<<___ if ($win64); + movaps %xmm6,0xa0(%rsp) + movaps %xmm7,0xb0(%rsp) + movaps %xmm8,0xc0(%rsp) + movaps %xmm9,0xd0(%rsp) + movaps %xmm10,0xe0(%rsp) + movaps %xmm11,0xf0(%rsp) + movaps %xmm12,0x100(%rsp) + movaps %xmm13,0x110(%rsp) + movaps %xmm14,0x120(%rsp) + movaps %xmm15,0x130(%rsp) +___ +$code.=<<___; +.Lmul_gather4_body: + movd $pwr,%xmm8 + movdqa .Linc+16(%rip),%xmm1 # 00000002000000020000000200000002 + movdqa .Linc(%rip),%xmm0 # 00000001000000010000000000000000 + + pshufd \$0,%xmm8,%xmm8 # broadcast $power + movdqa %xmm1,%xmm7 + movdqa %xmm1,%xmm2 +___ +######################################################################## +# calculate mask by comparing 0..15 to $power +# +for($i=0;$i<4;$i++) { +$code.=<<___; + paddd %xmm`$i`,%xmm`$i+1` + pcmpeqd %xmm8,%xmm`$i` + movdqa %xmm7,%xmm`$i+3` +___ +} +for(;$i<7;$i++) { +$code.=<<___; + paddd %xmm`$i`,%xmm`$i+1` + pcmpeqd %xmm8,%xmm`$i` +___ +} +$code.=<<___; + pcmpeqd %xmm8,%xmm7 + + movdqa 16*0($bp),%xmm8 + movdqa 16*1($bp),%xmm9 + movdqa 16*2($bp),%xmm10 + movdqa 16*3($bp),%xmm11 + pand %xmm0,%xmm8 + movdqa 16*4($bp),%xmm12 + pand %xmm1,%xmm9 + movdqa 16*5($bp),%xmm13 + pand %xmm2,%xmm10 + movdqa 16*6($bp),%xmm14 + pand %xmm3,%xmm11 + movdqa 16*7($bp),%xmm15 + leaq 128($bp), %rbp + pand %xmm4,%xmm12 + pand %xmm5,%xmm13 + pand %xmm6,%xmm14 + pand %xmm7,%xmm15 + por %xmm10,%xmm8 + por %xmm11,%xmm9 + por %xmm12,%xmm8 + por %xmm13,%xmm9 + por %xmm14,%xmm8 + por %xmm15,%xmm9 + + por %xmm9,%xmm8 + pshufd \$0x4e,%xmm8,%xmm9 + por %xmm9,%xmm8 +___ +$code.=<<___ if ($addx); + movl \$0x80100,%r11d + andl OPENSSL_ia32cap_P+8(%rip),%r11d + cmpl \$0x80100,%r11d # check for MULX and ADO/CX + je .Lmulx_gather +___ +$code.=<<___; + movq %xmm8,%rbx + + movq $n0, 128(%rsp) # off-load arguments + movq $out, 128+8(%rsp) + movq $mod, 128+16(%rsp) + + movq ($ap), %rax + movq 8($ap), %rcx + mulq %rbx # 0 iteration + movq %rax, (%rsp) + movq %rcx, %rax + movq %rdx, %r8 + + mulq %rbx + addq %rax, %r8 + movq 16($ap), %rax + movq %rdx, %r9 + adcq \$0, %r9 + + mulq %rbx + addq %rax, %r9 + movq 24($ap), %rax + movq %rdx, %r10 + adcq \$0, %r10 + + mulq %rbx + addq %rax, %r10 + movq 32($ap), %rax + movq %rdx, %r11 + adcq \$0, %r11 + + mulq %rbx + addq %rax, %r11 + movq 40($ap), %rax + movq %rdx, %r12 + adcq \$0, %r12 + + mulq %rbx + addq %rax, %r12 + movq 48($ap), %rax + movq %rdx, %r13 + adcq \$0, %r13 + + mulq %rbx + addq %rax, %r13 + movq 56($ap), %rax + movq %rdx, %r14 + adcq \$0, %r14 + + mulq %rbx + addq %rax, %r14 + movq ($ap), %rax + movq %rdx, %r15 + adcq \$0, %r15 + + leaq 8(%rsp), %rdi + movl \$7, %ecx + jmp .Loop_mul_gather + +.align 32 +.Loop_mul_gather: + movdqa 16*0(%rbp),%xmm8 + movdqa 16*1(%rbp),%xmm9 + movdqa 16*2(%rbp),%xmm10 + movdqa 16*3(%rbp),%xmm11 + pand %xmm0,%xmm8 + movdqa 16*4(%rbp),%xmm12 + pand %xmm1,%xmm9 + movdqa 16*5(%rbp),%xmm13 + pand %xmm2,%xmm10 + movdqa 16*6(%rbp),%xmm14 + pand %xmm3,%xmm11 + movdqa 16*7(%rbp),%xmm15 + leaq 128(%rbp), %rbp + pand %xmm4,%xmm12 + pand %xmm5,%xmm13 + pand %xmm6,%xmm14 + pand %xmm7,%xmm15 + por %xmm10,%xmm8 + por %xmm11,%xmm9 + por %xmm12,%xmm8 + por %xmm13,%xmm9 + por %xmm14,%xmm8 + por %xmm15,%xmm9 + + por %xmm9,%xmm8 + pshufd \$0x4e,%xmm8,%xmm9 + por %xmm9,%xmm8 + movq %xmm8,%rbx + + mulq %rbx + addq %rax, %r8 + movq 8($ap), %rax + movq %r8, (%rdi) + movq %rdx, %r8 + adcq \$0, %r8 + + mulq %rbx + addq %rax, %r9 + movq 16($ap), %rax + adcq \$0, %rdx + addq %r9, %r8 + movq %rdx, %r9 + adcq \$0, %r9 + + mulq %rbx + addq %rax, %r10 + movq 24($ap), %rax + adcq \$0, %rdx + addq %r10, %r9 + movq %rdx, %r10 + adcq \$0, %r10 + + mulq %rbx + addq %rax, %r11 + movq 32($ap), %rax + adcq \$0, %rdx + addq %r11, %r10 + movq %rdx, %r11 + adcq \$0, %r11 + + mulq %rbx + addq %rax, %r12 + movq 40($ap), %rax + adcq \$0, %rdx + addq %r12, %r11 + movq %rdx, %r12 + adcq \$0, %r12 + + mulq %rbx + addq %rax, %r13 + movq 48($ap), %rax + adcq \$0, %rdx + addq %r13, %r12 + movq %rdx, %r13 + adcq \$0, %r13 + + mulq %rbx + addq %rax, %r14 + movq 56($ap), %rax + adcq \$0, %rdx + addq %r14, %r13 + movq %rdx, %r14 + adcq \$0, %r14 + + mulq %rbx + addq %rax, %r15 + movq ($ap), %rax + adcq \$0, %rdx + addq %r15, %r14 + movq %rdx, %r15 + adcq \$0, %r15 + + leaq 8(%rdi), %rdi + + decl %ecx + jnz .Loop_mul_gather + + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, 32(%rdi) + movq %r13, 40(%rdi) + movq %r14, 48(%rdi) + movq %r15, 56(%rdi) + + movq 128+8(%rsp), $out + movq 128+16(%rsp), %rbp + + movq (%rsp), %r8 + movq 8(%rsp), %r9 + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + movq 32(%rsp), %r12 + movq 40(%rsp), %r13 + movq 48(%rsp), %r14 + movq 56(%rsp), %r15 + + call __rsaz_512_reduce +___ +$code.=<<___ if ($addx); + jmp .Lmul_gather_tail + +.align 32 +.Lmulx_gather: + movq %xmm8,%rdx + + mov $n0, 128(%rsp) # off-load arguments + mov $out, 128+8(%rsp) + mov $mod, 128+16(%rsp) + + mulx ($ap), %rbx, %r8 # 0 iteration + mov %rbx, (%rsp) + xor %edi, %edi # cf=0, of=0 + + mulx 8($ap), %rax, %r9 + + mulx 16($ap), %rbx, %r10 + adcx %rax, %r8 + + mulx 24($ap), %rax, %r11 + adcx %rbx, %r9 + + mulx 32($ap), %rbx, %r12 + adcx %rax, %r10 + + mulx 40($ap), %rax, %r13 + adcx %rbx, %r11 + + mulx 48($ap), %rbx, %r14 + adcx %rax, %r12 + + mulx 56($ap), %rax, %r15 + adcx %rbx, %r13 + adcx %rax, %r14 + .byte 0x67 + mov %r8, %rbx + adcx %rdi, %r15 # %rdi is 0 + + mov \$-7, %rcx + jmp .Loop_mulx_gather + +.align 32 +.Loop_mulx_gather: + movdqa 16*0(%rbp),%xmm8 + movdqa 16*1(%rbp),%xmm9 + movdqa 16*2(%rbp),%xmm10 + movdqa 16*3(%rbp),%xmm11 + pand %xmm0,%xmm8 + movdqa 16*4(%rbp),%xmm12 + pand %xmm1,%xmm9 + movdqa 16*5(%rbp),%xmm13 + pand %xmm2,%xmm10 + movdqa 16*6(%rbp),%xmm14 + pand %xmm3,%xmm11 + movdqa 16*7(%rbp),%xmm15 + leaq 128(%rbp), %rbp + pand %xmm4,%xmm12 + pand %xmm5,%xmm13 + pand %xmm6,%xmm14 + pand %xmm7,%xmm15 + por %xmm10,%xmm8 + por %xmm11,%xmm9 + por %xmm12,%xmm8 + por %xmm13,%xmm9 + por %xmm14,%xmm8 + por %xmm15,%xmm9 + + por %xmm9,%xmm8 + pshufd \$0x4e,%xmm8,%xmm9 + por %xmm9,%xmm8 + movq %xmm8,%rdx + + .byte 0xc4,0x62,0xfb,0xf6,0x86,0x00,0x00,0x00,0x00 # mulx ($ap), %rax, %r8 + adcx %rax, %rbx + adox %r9, %r8 + + mulx 8($ap), %rax, %r9 + adcx %rax, %r8 + adox %r10, %r9 + + mulx 16($ap), %rax, %r10 + adcx %rax, %r9 + adox %r11, %r10 + + .byte 0xc4,0x62,0xfb,0xf6,0x9e,0x18,0x00,0x00,0x00 # mulx 24($ap), %rax, %r11 + adcx %rax, %r10 + adox %r12, %r11 + + mulx 32($ap), %rax, %r12 + adcx %rax, %r11 + adox %r13, %r12 + + mulx 40($ap), %rax, %r13 + adcx %rax, %r12 + adox %r14, %r13 + + .byte 0xc4,0x62,0xfb,0xf6,0xb6,0x30,0x00,0x00,0x00 # mulx 48($ap), %rax, %r14 + adcx %rax, %r13 + .byte 0x67 + adox %r15, %r14 + + mulx 56($ap), %rax, %r15 + mov %rbx, 64(%rsp,%rcx,8) + adcx %rax, %r14 + adox %rdi, %r15 + mov %r8, %rbx + adcx %rdi, %r15 # cf=0 + + inc %rcx # of=0 + jnz .Loop_mulx_gather + + mov %r8, 64(%rsp) + mov %r9, 64+8(%rsp) + mov %r10, 64+16(%rsp) + mov %r11, 64+24(%rsp) + mov %r12, 64+32(%rsp) + mov %r13, 64+40(%rsp) + mov %r14, 64+48(%rsp) + mov %r15, 64+56(%rsp) + + mov 128(%rsp), %rdx # pull arguments + mov 128+8(%rsp), $out + mov 128+16(%rsp), %rbp + + mov (%rsp), %r8 + mov 8(%rsp), %r9 + mov 16(%rsp), %r10 + mov 24(%rsp), %r11 + mov 32(%rsp), %r12 + mov 40(%rsp), %r13 + mov 48(%rsp), %r14 + mov 56(%rsp), %r15 + + call __rsaz_512_reducex + +.Lmul_gather_tail: +___ +$code.=<<___; + addq 64(%rsp), %r8 + adcq 72(%rsp), %r9 + adcq 80(%rsp), %r10 + adcq 88(%rsp), %r11 + adcq 96(%rsp), %r12 + adcq 104(%rsp), %r13 + adcq 112(%rsp), %r14 + adcq 120(%rsp), %r15 + sbbq %rcx, %rcx + + call __rsaz_512_subtract + + leaq 128+24+48(%rsp), %rax +___ +$code.=<<___ if ($win64); + movaps 0xa0-0xc8(%rax),%xmm6 + movaps 0xb0-0xc8(%rax),%xmm7 + movaps 0xc0-0xc8(%rax),%xmm8 + movaps 0xd0-0xc8(%rax),%xmm9 + movaps 0xe0-0xc8(%rax),%xmm10 + movaps 0xf0-0xc8(%rax),%xmm11 + movaps 0x100-0xc8(%rax),%xmm12 + movaps 0x110-0xc8(%rax),%xmm13 + movaps 0x120-0xc8(%rax),%xmm14 + movaps 0x130-0xc8(%rax),%xmm15 + lea 0xb0(%rax),%rax +___ +$code.=<<___; +.cfi_def_cfa %rax,8 + movq -48(%rax), %r15 +.cfi_restore %r15 + movq -40(%rax), %r14 +.cfi_restore %r14 + movq -32(%rax), %r13 +.cfi_restore %r13 + movq -24(%rax), %r12 +.cfi_restore %r12 + movq -16(%rax), %rbp +.cfi_restore %rbp + movq -8(%rax), %rbx +.cfi_restore %rbx + leaq (%rax), %rsp +.cfi_def_cfa_register %rsp +.Lmul_gather4_epilogue: + ret +.cfi_endproc +.size rsaz_512_mul_gather4,.-rsaz_512_mul_gather4 +___ +} +{ +my ($out,$ap,$mod,$n0,$tbl,$pwr) = ("%rdi","%rsi","%rdx","%rcx","%r8","%r9d"); +$code.=<<___; +.globl rsaz_512_mul_scatter4 +.type rsaz_512_mul_scatter4,\@function,6 +.align 32 +rsaz_512_mul_scatter4: +.cfi_startproc + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + + mov $pwr, $pwr + subq \$128+24, %rsp +.cfi_adjust_cfa_offset 128+24 +.Lmul_scatter4_body: + leaq ($tbl,$pwr,8), $tbl + movq $out, %xmm0 # off-load arguments + movq $mod, %xmm1 + movq $tbl, %xmm2 + movq $n0, 128(%rsp) + + movq $out, %rbp +___ +$code.=<<___ if ($addx); + movl \$0x80100,%r11d + andl OPENSSL_ia32cap_P+8(%rip),%r11d + cmpl \$0x80100,%r11d # check for MULX and ADO/CX + je .Lmulx_scatter +___ +$code.=<<___; + movq ($out),%rbx # pass b[0] + call __rsaz_512_mul + + movq %xmm0, $out + movq %xmm1, %rbp + + movq (%rsp), %r8 + movq 8(%rsp), %r9 + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + movq 32(%rsp), %r12 + movq 40(%rsp), %r13 + movq 48(%rsp), %r14 + movq 56(%rsp), %r15 + + call __rsaz_512_reduce +___ +$code.=<<___ if ($addx); + jmp .Lmul_scatter_tail + +.align 32 +.Lmulx_scatter: + movq ($out), %rdx # pass b[0] + call __rsaz_512_mulx + + movq %xmm0, $out + movq %xmm1, %rbp + + movq 128(%rsp), %rdx # pull $n0 + movq (%rsp), %r8 + movq 8(%rsp), %r9 + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + movq 32(%rsp), %r12 + movq 40(%rsp), %r13 + movq 48(%rsp), %r14 + movq 56(%rsp), %r15 + + call __rsaz_512_reducex + +.Lmul_scatter_tail: +___ +$code.=<<___; + addq 64(%rsp), %r8 + adcq 72(%rsp), %r9 + adcq 80(%rsp), %r10 + adcq 88(%rsp), %r11 + adcq 96(%rsp), %r12 + adcq 104(%rsp), %r13 + adcq 112(%rsp), %r14 + adcq 120(%rsp), %r15 + movq %xmm2, $inp + sbbq %rcx, %rcx + + call __rsaz_512_subtract + + movq %r8, 128*0($inp) # scatter + movq %r9, 128*1($inp) + movq %r10, 128*2($inp) + movq %r11, 128*3($inp) + movq %r12, 128*4($inp) + movq %r13, 128*5($inp) + movq %r14, 128*6($inp) + movq %r15, 128*7($inp) + + leaq 128+24+48(%rsp), %rax +.cfi_def_cfa %rax,8 + movq -48(%rax), %r15 +.cfi_restore %r15 + movq -40(%rax), %r14 +.cfi_restore %r14 + movq -32(%rax), %r13 +.cfi_restore %r13 + movq -24(%rax), %r12 +.cfi_restore %r12 + movq -16(%rax), %rbp +.cfi_restore %rbp + movq -8(%rax), %rbx +.cfi_restore %rbx + leaq (%rax), %rsp +.cfi_def_cfa_register %rsp +.Lmul_scatter4_epilogue: + ret +.cfi_endproc +.size rsaz_512_mul_scatter4,.-rsaz_512_mul_scatter4 +___ +} +{ +my ($out,$inp,$mod,$n0) = ("%rdi","%rsi","%rdx","%rcx"); +$code.=<<___; +.globl rsaz_512_mul_by_one +.type rsaz_512_mul_by_one,\@function,4 +.align 32 +rsaz_512_mul_by_one: +.cfi_startproc + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + + subq \$128+24, %rsp +.cfi_adjust_cfa_offset 128+24 +.Lmul_by_one_body: +___ +$code.=<<___ if ($addx); + movl OPENSSL_ia32cap_P+8(%rip),%eax +___ +$code.=<<___; + movq $mod, %rbp # reassign argument + movq $n0, 128(%rsp) + + movq ($inp), %r8 + pxor %xmm0, %xmm0 + movq 8($inp), %r9 + movq 16($inp), %r10 + movq 24($inp), %r11 + movq 32($inp), %r12 + movq 40($inp), %r13 + movq 48($inp), %r14 + movq 56($inp), %r15 + + movdqa %xmm0, (%rsp) + movdqa %xmm0, 16(%rsp) + movdqa %xmm0, 32(%rsp) + movdqa %xmm0, 48(%rsp) + movdqa %xmm0, 64(%rsp) + movdqa %xmm0, 80(%rsp) + movdqa %xmm0, 96(%rsp) +___ +$code.=<<___ if ($addx); + andl \$0x80100,%eax + cmpl \$0x80100,%eax # check for MULX and ADO/CX + je .Lby_one_callx +___ +$code.=<<___; + call __rsaz_512_reduce +___ +$code.=<<___ if ($addx); + jmp .Lby_one_tail +.align 32 +.Lby_one_callx: + movq 128(%rsp), %rdx # pull $n0 + call __rsaz_512_reducex +.Lby_one_tail: +___ +$code.=<<___; + movq %r8, ($out) + movq %r9, 8($out) + movq %r10, 16($out) + movq %r11, 24($out) + movq %r12, 32($out) + movq %r13, 40($out) + movq %r14, 48($out) + movq %r15, 56($out) + + leaq 128+24+48(%rsp), %rax +.cfi_def_cfa %rax,8 + movq -48(%rax), %r15 +.cfi_restore %r15 + movq -40(%rax), %r14 +.cfi_restore %r14 + movq -32(%rax), %r13 +.cfi_restore %r13 + movq -24(%rax), %r12 +.cfi_restore %r12 + movq -16(%rax), %rbp +.cfi_restore %rbp + movq -8(%rax), %rbx +.cfi_restore %rbx + leaq (%rax), %rsp +.cfi_def_cfa_register %rsp +.Lmul_by_one_epilogue: + ret +.cfi_endproc +.size rsaz_512_mul_by_one,.-rsaz_512_mul_by_one +___ +} +{ # __rsaz_512_reduce + # + # input: %r8-%r15, %rbp - mod, 128(%rsp) - n0 + # output: %r8-%r15 + # clobbers: everything except %rbp and %rdi +$code.=<<___; +.type __rsaz_512_reduce,\@abi-omnipotent +.align 32 +__rsaz_512_reduce: + movq %r8, %rbx + imulq 128+8(%rsp), %rbx + movq 0(%rbp), %rax + movl \$8, %ecx + jmp .Lreduction_loop + +.align 32 +.Lreduction_loop: + mulq %rbx + movq 8(%rbp), %rax + negq %r8 + movq %rdx, %r8 + adcq \$0, %r8 + + mulq %rbx + addq %rax, %r9 + movq 16(%rbp), %rax + adcq \$0, %rdx + addq %r9, %r8 + movq %rdx, %r9 + adcq \$0, %r9 + + mulq %rbx + addq %rax, %r10 + movq 24(%rbp), %rax + adcq \$0, %rdx + addq %r10, %r9 + movq %rdx, %r10 + adcq \$0, %r10 + + mulq %rbx + addq %rax, %r11 + movq 32(%rbp), %rax + adcq \$0, %rdx + addq %r11, %r10 + movq 128+8(%rsp), %rsi + #movq %rdx, %r11 + #adcq \$0, %r11 + adcq \$0, %rdx + movq %rdx, %r11 + + mulq %rbx + addq %rax, %r12 + movq 40(%rbp), %rax + adcq \$0, %rdx + imulq %r8, %rsi + addq %r12, %r11 + movq %rdx, %r12 + adcq \$0, %r12 + + mulq %rbx + addq %rax, %r13 + movq 48(%rbp), %rax + adcq \$0, %rdx + addq %r13, %r12 + movq %rdx, %r13 + adcq \$0, %r13 + + mulq %rbx + addq %rax, %r14 + movq 56(%rbp), %rax + adcq \$0, %rdx + addq %r14, %r13 + movq %rdx, %r14 + adcq \$0, %r14 + + mulq %rbx + movq %rsi, %rbx + addq %rax, %r15 + movq 0(%rbp), %rax + adcq \$0, %rdx + addq %r15, %r14 + movq %rdx, %r15 + adcq \$0, %r15 + + decl %ecx + jne .Lreduction_loop + + ret +.size __rsaz_512_reduce,.-__rsaz_512_reduce +___ +} +if ($addx) { + # __rsaz_512_reducex + # + # input: %r8-%r15, %rbp - mod, 128(%rsp) - n0 + # output: %r8-%r15 + # clobbers: everything except %rbp and %rdi +$code.=<<___; +.type __rsaz_512_reducex,\@abi-omnipotent +.align 32 +__rsaz_512_reducex: + #movq 128+8(%rsp), %rdx # pull $n0 + imulq %r8, %rdx + xorq %rsi, %rsi # cf=0,of=0 + movl \$8, %ecx + jmp .Lreduction_loopx + +.align 32 +.Lreduction_loopx: + mov %r8, %rbx + mulx 0(%rbp), %rax, %r8 + adcx %rbx, %rax + adox %r9, %r8 + + mulx 8(%rbp), %rax, %r9 + adcx %rax, %r8 + adox %r10, %r9 + + mulx 16(%rbp), %rbx, %r10 + adcx %rbx, %r9 + adox %r11, %r10 + + mulx 24(%rbp), %rbx, %r11 + adcx %rbx, %r10 + adox %r12, %r11 + + .byte 0xc4,0x62,0xe3,0xf6,0xa5,0x20,0x00,0x00,0x00 # mulx 32(%rbp), %rbx, %r12 + mov %rdx, %rax + mov %r8, %rdx + adcx %rbx, %r11 + adox %r13, %r12 + + mulx 128+8(%rsp), %rbx, %rdx + mov %rax, %rdx + + mulx 40(%rbp), %rax, %r13 + adcx %rax, %r12 + adox %r14, %r13 + + .byte 0xc4,0x62,0xfb,0xf6,0xb5,0x30,0x00,0x00,0x00 # mulx 48(%rbp), %rax, %r14 + adcx %rax, %r13 + adox %r15, %r14 + + mulx 56(%rbp), %rax, %r15 + mov %rbx, %rdx + adcx %rax, %r14 + adox %rsi, %r15 # %rsi is 0 + adcx %rsi, %r15 # cf=0 + + decl %ecx # of=0 + jne .Lreduction_loopx + + ret +.size __rsaz_512_reducex,.-__rsaz_512_reducex +___ +} +{ # __rsaz_512_subtract + # input: %r8-%r15, %rdi - $out, %rbp - $mod, %rcx - mask + # output: + # clobbers: everything but %rdi, %rsi and %rbp +$code.=<<___; +.type __rsaz_512_subtract,\@abi-omnipotent +.align 32 +__rsaz_512_subtract: + movq %r8, ($out) + movq %r9, 8($out) + movq %r10, 16($out) + movq %r11, 24($out) + movq %r12, 32($out) + movq %r13, 40($out) + movq %r14, 48($out) + movq %r15, 56($out) + + movq 0($mod), %r8 + movq 8($mod), %r9 + negq %r8 + notq %r9 + andq %rcx, %r8 + movq 16($mod), %r10 + andq %rcx, %r9 + notq %r10 + movq 24($mod), %r11 + andq %rcx, %r10 + notq %r11 + movq 32($mod), %r12 + andq %rcx, %r11 + notq %r12 + movq 40($mod), %r13 + andq %rcx, %r12 + notq %r13 + movq 48($mod), %r14 + andq %rcx, %r13 + notq %r14 + movq 56($mod), %r15 + andq %rcx, %r14 + notq %r15 + andq %rcx, %r15 + + addq ($out), %r8 + adcq 8($out), %r9 + adcq 16($out), %r10 + adcq 24($out), %r11 + adcq 32($out), %r12 + adcq 40($out), %r13 + adcq 48($out), %r14 + adcq 56($out), %r15 + + movq %r8, ($out) + movq %r9, 8($out) + movq %r10, 16($out) + movq %r11, 24($out) + movq %r12, 32($out) + movq %r13, 40($out) + movq %r14, 48($out) + movq %r15, 56($out) + + ret +.size __rsaz_512_subtract,.-__rsaz_512_subtract +___ +} +{ # __rsaz_512_mul + # + # input: %rsi - ap, %rbp - bp + # output: + # clobbers: everything +my ($ap,$bp) = ("%rsi","%rbp"); +$code.=<<___; +.type __rsaz_512_mul,\@abi-omnipotent +.align 32 +__rsaz_512_mul: + leaq 8(%rsp), %rdi + + movq ($ap), %rax + mulq %rbx + movq %rax, (%rdi) + movq 8($ap), %rax + movq %rdx, %r8 + + mulq %rbx + addq %rax, %r8 + movq 16($ap), %rax + movq %rdx, %r9 + adcq \$0, %r9 + + mulq %rbx + addq %rax, %r9 + movq 24($ap), %rax + movq %rdx, %r10 + adcq \$0, %r10 + + mulq %rbx + addq %rax, %r10 + movq 32($ap), %rax + movq %rdx, %r11 + adcq \$0, %r11 + + mulq %rbx + addq %rax, %r11 + movq 40($ap), %rax + movq %rdx, %r12 + adcq \$0, %r12 + + mulq %rbx + addq %rax, %r12 + movq 48($ap), %rax + movq %rdx, %r13 + adcq \$0, %r13 + + mulq %rbx + addq %rax, %r13 + movq 56($ap), %rax + movq %rdx, %r14 + adcq \$0, %r14 + + mulq %rbx + addq %rax, %r14 + movq ($ap), %rax + movq %rdx, %r15 + adcq \$0, %r15 + + leaq 8($bp), $bp + leaq 8(%rdi), %rdi + + movl \$7, %ecx + jmp .Loop_mul + +.align 32 +.Loop_mul: + movq ($bp), %rbx + mulq %rbx + addq %rax, %r8 + movq 8($ap), %rax + movq %r8, (%rdi) + movq %rdx, %r8 + adcq \$0, %r8 + + mulq %rbx + addq %rax, %r9 + movq 16($ap), %rax + adcq \$0, %rdx + addq %r9, %r8 + movq %rdx, %r9 + adcq \$0, %r9 + + mulq %rbx + addq %rax, %r10 + movq 24($ap), %rax + adcq \$0, %rdx + addq %r10, %r9 + movq %rdx, %r10 + adcq \$0, %r10 + + mulq %rbx + addq %rax, %r11 + movq 32($ap), %rax + adcq \$0, %rdx + addq %r11, %r10 + movq %rdx, %r11 + adcq \$0, %r11 + + mulq %rbx + addq %rax, %r12 + movq 40($ap), %rax + adcq \$0, %rdx + addq %r12, %r11 + movq %rdx, %r12 + adcq \$0, %r12 + + mulq %rbx + addq %rax, %r13 + movq 48($ap), %rax + adcq \$0, %rdx + addq %r13, %r12 + movq %rdx, %r13 + adcq \$0, %r13 + + mulq %rbx + addq %rax, %r14 + movq 56($ap), %rax + adcq \$0, %rdx + addq %r14, %r13 + movq %rdx, %r14 + leaq 8($bp), $bp + adcq \$0, %r14 + + mulq %rbx + addq %rax, %r15 + movq ($ap), %rax + adcq \$0, %rdx + addq %r15, %r14 + movq %rdx, %r15 + adcq \$0, %r15 + + leaq 8(%rdi), %rdi + + decl %ecx + jnz .Loop_mul + + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, 32(%rdi) + movq %r13, 40(%rdi) + movq %r14, 48(%rdi) + movq %r15, 56(%rdi) + + ret +.size __rsaz_512_mul,.-__rsaz_512_mul +___ +} +if ($addx) { + # __rsaz_512_mulx + # + # input: %rsi - ap, %rbp - bp + # output: + # clobbers: everything +my ($ap,$bp,$zero) = ("%rsi","%rbp","%rdi"); +$code.=<<___; +.type __rsaz_512_mulx,\@abi-omnipotent +.align 32 +__rsaz_512_mulx: + mulx ($ap), %rbx, %r8 # initial %rdx preloaded by caller + mov \$-6, %rcx + + mulx 8($ap), %rax, %r9 + movq %rbx, 8(%rsp) + + mulx 16($ap), %rbx, %r10 + adc %rax, %r8 + + mulx 24($ap), %rax, %r11 + adc %rbx, %r9 + + mulx 32($ap), %rbx, %r12 + adc %rax, %r10 + + mulx 40($ap), %rax, %r13 + adc %rbx, %r11 + + mulx 48($ap), %rbx, %r14 + adc %rax, %r12 + + mulx 56($ap), %rax, %r15 + mov 8($bp), %rdx + adc %rbx, %r13 + adc %rax, %r14 + adc \$0, %r15 + + xor $zero, $zero # cf=0,of=0 + jmp .Loop_mulx + +.align 32 +.Loop_mulx: + movq %r8, %rbx + mulx ($ap), %rax, %r8 + adcx %rax, %rbx + adox %r9, %r8 + + mulx 8($ap), %rax, %r9 + adcx %rax, %r8 + adox %r10, %r9 + + mulx 16($ap), %rax, %r10 + adcx %rax, %r9 + adox %r11, %r10 + + mulx 24($ap), %rax, %r11 + adcx %rax, %r10 + adox %r12, %r11 + + .byte 0x3e,0xc4,0x62,0xfb,0xf6,0xa6,0x20,0x00,0x00,0x00 # mulx 32($ap), %rax, %r12 + adcx %rax, %r11 + adox %r13, %r12 + + mulx 40($ap), %rax, %r13 + adcx %rax, %r12 + adox %r14, %r13 + + mulx 48($ap), %rax, %r14 + adcx %rax, %r13 + adox %r15, %r14 + + mulx 56($ap), %rax, %r15 + movq 64($bp,%rcx,8), %rdx + movq %rbx, 8+64-8(%rsp,%rcx,8) + adcx %rax, %r14 + adox $zero, %r15 + adcx $zero, %r15 # cf=0 + + inc %rcx # of=0 + jnz .Loop_mulx + + movq %r8, %rbx + mulx ($ap), %rax, %r8 + adcx %rax, %rbx + adox %r9, %r8 + + .byte 0xc4,0x62,0xfb,0xf6,0x8e,0x08,0x00,0x00,0x00 # mulx 8($ap), %rax, %r9 + adcx %rax, %r8 + adox %r10, %r9 + + .byte 0xc4,0x62,0xfb,0xf6,0x96,0x10,0x00,0x00,0x00 # mulx 16($ap), %rax, %r10 + adcx %rax, %r9 + adox %r11, %r10 + + mulx 24($ap), %rax, %r11 + adcx %rax, %r10 + adox %r12, %r11 + + mulx 32($ap), %rax, %r12 + adcx %rax, %r11 + adox %r13, %r12 + + mulx 40($ap), %rax, %r13 + adcx %rax, %r12 + adox %r14, %r13 + + .byte 0xc4,0x62,0xfb,0xf6,0xb6,0x30,0x00,0x00,0x00 # mulx 48($ap), %rax, %r14 + adcx %rax, %r13 + adox %r15, %r14 + + .byte 0xc4,0x62,0xfb,0xf6,0xbe,0x38,0x00,0x00,0x00 # mulx 56($ap), %rax, %r15 + adcx %rax, %r14 + adox $zero, %r15 + adcx $zero, %r15 + + mov %rbx, 8+64-8(%rsp) + mov %r8, 8+64(%rsp) + mov %r9, 8+64+8(%rsp) + mov %r10, 8+64+16(%rsp) + mov %r11, 8+64+24(%rsp) + mov %r12, 8+64+32(%rsp) + mov %r13, 8+64+40(%rsp) + mov %r14, 8+64+48(%rsp) + mov %r15, 8+64+56(%rsp) + + ret +.size __rsaz_512_mulx,.-__rsaz_512_mulx +___ +} +{ +my ($out,$inp,$power)= $win64 ? ("%rcx","%rdx","%r8d") : ("%rdi","%rsi","%edx"); +$code.=<<___; +.globl rsaz_512_scatter4 +.type rsaz_512_scatter4,\@abi-omnipotent +.align 16 +rsaz_512_scatter4: + leaq ($out,$power,8), $out + movl \$8, %r9d + jmp .Loop_scatter +.align 16 +.Loop_scatter: + movq ($inp), %rax + leaq 8($inp), $inp + movq %rax, ($out) + leaq 128($out), $out + decl %r9d + jnz .Loop_scatter + ret +.size rsaz_512_scatter4,.-rsaz_512_scatter4 + +.globl rsaz_512_gather4 +.type rsaz_512_gather4,\@abi-omnipotent +.align 16 +rsaz_512_gather4: +___ +$code.=<<___ if ($win64); +.LSEH_begin_rsaz_512_gather4: + .byte 0x48,0x81,0xec,0xa8,0x00,0x00,0x00 # sub $0xa8,%rsp + .byte 0x0f,0x29,0x34,0x24 # movaps %xmm6,(%rsp) + .byte 0x0f,0x29,0x7c,0x24,0x10 # movaps %xmm7,0x10(%rsp) + .byte 0x44,0x0f,0x29,0x44,0x24,0x20 # movaps %xmm8,0x20(%rsp) + .byte 0x44,0x0f,0x29,0x4c,0x24,0x30 # movaps %xmm9,0x30(%rsp) + .byte 0x44,0x0f,0x29,0x54,0x24,0x40 # movaps %xmm10,0x40(%rsp) + .byte 0x44,0x0f,0x29,0x5c,0x24,0x50 # movaps %xmm11,0x50(%rsp) + .byte 0x44,0x0f,0x29,0x64,0x24,0x60 # movaps %xmm12,0x60(%rsp) + .byte 0x44,0x0f,0x29,0x6c,0x24,0x70 # movaps %xmm13,0x70(%rsp) + .byte 0x44,0x0f,0x29,0xb4,0x24,0x80,0,0,0 # movaps %xmm14,0x80(%rsp) + .byte 0x44,0x0f,0x29,0xbc,0x24,0x90,0,0,0 # movaps %xmm15,0x90(%rsp) +___ +$code.=<<___; + movd $power,%xmm8 + movdqa .Linc+16(%rip),%xmm1 # 00000002000000020000000200000002 + movdqa .Linc(%rip),%xmm0 # 00000001000000010000000000000000 + + pshufd \$0,%xmm8,%xmm8 # broadcast $power + movdqa %xmm1,%xmm7 + movdqa %xmm1,%xmm2 +___ +######################################################################## +# calculate mask by comparing 0..15 to $power +# +for($i=0;$i<4;$i++) { +$code.=<<___; + paddd %xmm`$i`,%xmm`$i+1` + pcmpeqd %xmm8,%xmm`$i` + movdqa %xmm7,%xmm`$i+3` +___ +} +for(;$i<7;$i++) { +$code.=<<___; + paddd %xmm`$i`,%xmm`$i+1` + pcmpeqd %xmm8,%xmm`$i` +___ +} +$code.=<<___; + pcmpeqd %xmm8,%xmm7 + movl \$8, %r9d + jmp .Loop_gather +.align 16 +.Loop_gather: + movdqa 16*0($inp),%xmm8 + movdqa 16*1($inp),%xmm9 + movdqa 16*2($inp),%xmm10 + movdqa 16*3($inp),%xmm11 + pand %xmm0,%xmm8 + movdqa 16*4($inp),%xmm12 + pand %xmm1,%xmm9 + movdqa 16*5($inp),%xmm13 + pand %xmm2,%xmm10 + movdqa 16*6($inp),%xmm14 + pand %xmm3,%xmm11 + movdqa 16*7($inp),%xmm15 + leaq 128($inp), $inp + pand %xmm4,%xmm12 + pand %xmm5,%xmm13 + pand %xmm6,%xmm14 + pand %xmm7,%xmm15 + por %xmm10,%xmm8 + por %xmm11,%xmm9 + por %xmm12,%xmm8 + por %xmm13,%xmm9 + por %xmm14,%xmm8 + por %xmm15,%xmm9 + + por %xmm9,%xmm8 + pshufd \$0x4e,%xmm8,%xmm9 + por %xmm9,%xmm8 + movq %xmm8,($out) + leaq 8($out), $out + decl %r9d + jnz .Loop_gather +___ +$code.=<<___ if ($win64); + movaps 0x00(%rsp),%xmm6 + movaps 0x10(%rsp),%xmm7 + movaps 0x20(%rsp),%xmm8 + movaps 0x30(%rsp),%xmm9 + movaps 0x40(%rsp),%xmm10 + movaps 0x50(%rsp),%xmm11 + movaps 0x60(%rsp),%xmm12 + movaps 0x70(%rsp),%xmm13 + movaps 0x80(%rsp),%xmm14 + movaps 0x90(%rsp),%xmm15 + add \$0xa8,%rsp +___ +$code.=<<___; + ret +.LSEH_end_rsaz_512_gather4: +.size rsaz_512_gather4,.-rsaz_512_gather4 + +.align 64 +.Linc: + .long 0,0, 1,1 + .long 2,2, 2,2 +___ +} + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type se_handler,\@abi-omnipotent +.align 16 +se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # end of prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lcommon_seh_tail + + lea 128+24+48(%rax),%rax + + lea .Lmul_gather4_epilogue(%rip),%rbx + cmp %r10,%rbx + jne .Lse_not_in_mul_gather4 + + lea 0xb0(%rax),%rax + + lea -48-0xa8(%rax),%rsi + lea 512($context),%rdi + mov \$20,%ecx + .long 0xa548f3fc # cld; rep movsq + +.Lse_not_in_mul_gather4: + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov -48(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + +.Lcommon_seh_tail: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size se_handler,.-se_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_rsaz_512_sqr + .rva .LSEH_end_rsaz_512_sqr + .rva .LSEH_info_rsaz_512_sqr + + .rva .LSEH_begin_rsaz_512_mul + .rva .LSEH_end_rsaz_512_mul + .rva .LSEH_info_rsaz_512_mul + + .rva .LSEH_begin_rsaz_512_mul_gather4 + .rva .LSEH_end_rsaz_512_mul_gather4 + .rva .LSEH_info_rsaz_512_mul_gather4 + + .rva .LSEH_begin_rsaz_512_mul_scatter4 + .rva .LSEH_end_rsaz_512_mul_scatter4 + .rva .LSEH_info_rsaz_512_mul_scatter4 + + .rva .LSEH_begin_rsaz_512_mul_by_one + .rva .LSEH_end_rsaz_512_mul_by_one + .rva .LSEH_info_rsaz_512_mul_by_one + + .rva .LSEH_begin_rsaz_512_gather4 + .rva .LSEH_end_rsaz_512_gather4 + .rva .LSEH_info_rsaz_512_gather4 + +.section .xdata +.align 8 +.LSEH_info_rsaz_512_sqr: + .byte 9,0,0,0 + .rva se_handler + .rva .Lsqr_body,.Lsqr_epilogue # HandlerData[] +.LSEH_info_rsaz_512_mul: + .byte 9,0,0,0 + .rva se_handler + .rva .Lmul_body,.Lmul_epilogue # HandlerData[] +.LSEH_info_rsaz_512_mul_gather4: + .byte 9,0,0,0 + .rva se_handler + .rva .Lmul_gather4_body,.Lmul_gather4_epilogue # HandlerData[] +.LSEH_info_rsaz_512_mul_scatter4: + .byte 9,0,0,0 + .rva se_handler + .rva .Lmul_scatter4_body,.Lmul_scatter4_epilogue # HandlerData[] +.LSEH_info_rsaz_512_mul_by_one: + .byte 9,0,0,0 + .rva se_handler + .rva .Lmul_by_one_body,.Lmul_by_one_epilogue # HandlerData[] +.LSEH_info_rsaz_512_gather4: + .byte 0x01,0x46,0x16,0x00 + .byte 0x46,0xf8,0x09,0x00 # vmovaps 0x90(rsp),xmm15 + .byte 0x3d,0xe8,0x08,0x00 # vmovaps 0x80(rsp),xmm14 + .byte 0x34,0xd8,0x07,0x00 # vmovaps 0x70(rsp),xmm13 + .byte 0x2e,0xc8,0x06,0x00 # vmovaps 0x60(rsp),xmm12 + .byte 0x28,0xb8,0x05,0x00 # vmovaps 0x50(rsp),xmm11 + .byte 0x22,0xa8,0x04,0x00 # vmovaps 0x40(rsp),xmm10 + .byte 0x1c,0x98,0x03,0x00 # vmovaps 0x30(rsp),xmm9 + .byte 0x16,0x88,0x02,0x00 # vmovaps 0x20(rsp),xmm8 + .byte 0x10,0x78,0x01,0x00 # vmovaps 0x10(rsp),xmm7 + .byte 0x0b,0x68,0x00,0x00 # vmovaps 0x00(rsp),xmm6 + .byte 0x07,0x01,0x15,0x00 # sub rsp,0xa8 +___ +} + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/s390x-gf2m.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/s390x-gf2m.pl new file mode 100644 index 000000000..06181bf9b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/s390x-gf2m.pl @@ -0,0 +1,228 @@ +#! /usr/bin/env perl +# Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# May 2011 +# +# The module implements bn_GF2m_mul_2x2 polynomial multiplication used +# in bn_gf2m.c. It's kind of low-hanging mechanical port from C for +# the time being... gcc 4.3 appeared to generate poor code, therefore +# the effort. And indeed, the module delivers 55%-90%(*) improvement +# on heaviest ECDSA verify and ECDH benchmarks for 163- and 571-bit +# key lengths on z990, 30%-55%(*) - on z10, and 70%-110%(*) - on z196. +# This is for 64-bit build. In 32-bit "highgprs" case improvement is +# even higher, for example on z990 it was measured 80%-150%. ECDSA +# sign is modest 9%-12% faster. Keep in mind that these coefficients +# are not ones for bn_GF2m_mul_2x2 itself, as not all CPU time is +# burnt in it... +# +# (*) gcc 4.1 was observed to deliver better results than gcc 4.3, +# so that improvement coefficients can vary from one specific +# setup to another. + +$flavour = shift; + +if ($flavour =~ /3[12]/) { + $SIZE_T=4; + $g=""; +} else { + $SIZE_T=8; + $g="g"; +} + +while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} +open STDOUT,">$output"; + +$stdframe=16*$SIZE_T+4*8; + +$rp="%r2"; +$a1="%r3"; +$a0="%r4"; +$b1="%r5"; +$b0="%r6"; + +$ra="%r14"; +$sp="%r15"; + +@T=("%r0","%r1"); +@i=("%r12","%r13"); + +($a1,$a2,$a4,$a8,$a12,$a48)=map("%r$_",(6..11)); +($lo,$hi,$b)=map("%r$_",(3..5)); $a=$lo; $mask=$a8; + +$code.=<<___; +.text + +.type _mul_1x1,\@function +.align 16 +_mul_1x1: + lgr $a1,$a + sllg $a2,$a,1 + sllg $a4,$a,2 + sllg $a8,$a,3 + + srag $lo,$a1,63 # broadcast 63rd bit + nihh $a1,0x1fff + srag @i[0],$a2,63 # broadcast 62nd bit + nihh $a2,0x3fff + srag @i[1],$a4,63 # broadcast 61st bit + nihh $a4,0x7fff + ngr $lo,$b + ngr @i[0],$b + ngr @i[1],$b + + lghi @T[0],0 + lgr $a12,$a1 + stg @T[0],`$stdframe+0*8`($sp) # tab[0]=0 + xgr $a12,$a2 + stg $a1,`$stdframe+1*8`($sp) # tab[1]=a1 + lgr $a48,$a4 + stg $a2,`$stdframe+2*8`($sp) # tab[2]=a2 + xgr $a48,$a8 + stg $a12,`$stdframe+3*8`($sp) # tab[3]=a1^a2 + xgr $a1,$a4 + + stg $a4,`$stdframe+4*8`($sp) # tab[4]=a4 + xgr $a2,$a4 + stg $a1,`$stdframe+5*8`($sp) # tab[5]=a1^a4 + xgr $a12,$a4 + stg $a2,`$stdframe+6*8`($sp) # tab[6]=a2^a4 + xgr $a1,$a48 + stg $a12,`$stdframe+7*8`($sp) # tab[7]=a1^a2^a4 + xgr $a2,$a48 + + stg $a8,`$stdframe+8*8`($sp) # tab[8]=a8 + xgr $a12,$a48 + stg $a1,`$stdframe+9*8`($sp) # tab[9]=a1^a8 + xgr $a1,$a4 + stg $a2,`$stdframe+10*8`($sp) # tab[10]=a2^a8 + xgr $a2,$a4 + stg $a12,`$stdframe+11*8`($sp) # tab[11]=a1^a2^a8 + + xgr $a12,$a4 + stg $a48,`$stdframe+12*8`($sp) # tab[12]=a4^a8 + srlg $hi,$lo,1 + stg $a1,`$stdframe+13*8`($sp) # tab[13]=a1^a4^a8 + sllg $lo,$lo,63 + stg $a2,`$stdframe+14*8`($sp) # tab[14]=a2^a4^a8 + srlg @T[0],@i[0],2 + stg $a12,`$stdframe+15*8`($sp) # tab[15]=a1^a2^a4^a8 + + lghi $mask,`0xf<<3` + sllg $a1,@i[0],62 + sllg @i[0],$b,3 + srlg @T[1],@i[1],3 + ngr @i[0],$mask + sllg $a2,@i[1],61 + srlg @i[1],$b,4-3 + xgr $hi,@T[0] + ngr @i[1],$mask + xgr $lo,$a1 + xgr $hi,@T[1] + xgr $lo,$a2 + + xg $lo,$stdframe(@i[0],$sp) + srlg @i[0],$b,8-3 + ngr @i[0],$mask +___ +for($n=1;$n<14;$n++) { +$code.=<<___; + lg @T[1],$stdframe(@i[1],$sp) + srlg @i[1],$b,`($n+2)*4`-3 + sllg @T[0],@T[1],`$n*4` + ngr @i[1],$mask + srlg @T[1],@T[1],`64-$n*4` + xgr $lo,@T[0] + xgr $hi,@T[1] +___ + push(@i,shift(@i)); push(@T,shift(@T)); +} +$code.=<<___; + lg @T[1],$stdframe(@i[1],$sp) + sllg @T[0],@T[1],`$n*4` + srlg @T[1],@T[1],`64-$n*4` + xgr $lo,@T[0] + xgr $hi,@T[1] + + lg @T[0],$stdframe(@i[0],$sp) + sllg @T[1],@T[0],`($n+1)*4` + srlg @T[0],@T[0],`64-($n+1)*4` + xgr $lo,@T[1] + xgr $hi,@T[0] + + br $ra +.size _mul_1x1,.-_mul_1x1 + +.globl bn_GF2m_mul_2x2 +.type bn_GF2m_mul_2x2,\@function +.align 16 +bn_GF2m_mul_2x2: + stm${g} %r3,%r15,3*$SIZE_T($sp) + + lghi %r1,-$stdframe-128 + la %r0,0($sp) + la $sp,0(%r1,$sp) # alloca + st${g} %r0,0($sp) # back chain +___ +if ($SIZE_T==8) { +my @r=map("%r$_",(6..9)); +$code.=<<___; + bras $ra,_mul_1x1 # a1·b1 + stmg $lo,$hi,16($rp) + + lg $a,`$stdframe+128+4*$SIZE_T`($sp) + lg $b,`$stdframe+128+6*$SIZE_T`($sp) + bras $ra,_mul_1x1 # a0·b0 + stmg $lo,$hi,0($rp) + + lg $a,`$stdframe+128+3*$SIZE_T`($sp) + lg $b,`$stdframe+128+5*$SIZE_T`($sp) + xg $a,`$stdframe+128+4*$SIZE_T`($sp) + xg $b,`$stdframe+128+6*$SIZE_T`($sp) + bras $ra,_mul_1x1 # (a0+a1)·(b0+b1) + lmg @r[0],@r[3],0($rp) + + xgr $lo,$hi + xgr $hi,@r[1] + xgr $lo,@r[0] + xgr $hi,@r[2] + xgr $lo,@r[3] + xgr $hi,@r[3] + xgr $lo,$hi + stg $hi,16($rp) + stg $lo,8($rp) +___ +} else { +$code.=<<___; + sllg %r3,%r3,32 + sllg %r5,%r5,32 + or %r3,%r4 + or %r5,%r6 + bras $ra,_mul_1x1 + rllg $lo,$lo,32 + rllg $hi,$hi,32 + stmg $lo,$hi,0($rp) +___ +} +$code.=<<___; + lm${g} %r6,%r15,`$stdframe+128+6*$SIZE_T`($sp) + br $ra +.size bn_GF2m_mul_2x2,.-bn_GF2m_mul_2x2 +.string "GF(2^m) Multiplication for s390x, CRYPTOGAMS by " +___ + +$code =~ s/\`([^\`]*)\`/eval($1)/gem; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/s390x-mont.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/s390x-mont.pl new file mode 100644 index 000000000..c2fc5adff --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/s390x-mont.pl @@ -0,0 +1,284 @@ +#! /usr/bin/env perl +# Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# April 2007. +# +# Performance improvement over vanilla C code varies from 85% to 45% +# depending on key length and benchmark. Unfortunately in this context +# these are not very impressive results [for code that utilizes "wide" +# 64x64=128-bit multiplication, which is not commonly available to C +# programmers], at least hand-coded bn_asm.c replacement is known to +# provide 30-40% better results for longest keys. Well, on a second +# thought it's not very surprising, because z-CPUs are single-issue +# and _strictly_ in-order execution, while bn_mul_mont is more or less +# dependent on CPU ability to pipe-line instructions and have several +# of them "in-flight" at the same time. I mean while other methods, +# for example Karatsuba, aim to minimize amount of multiplications at +# the cost of other operations increase, bn_mul_mont aim to neatly +# "overlap" multiplications and the other operations [and on most +# platforms even minimize the amount of the other operations, in +# particular references to memory]. But it's possible to improve this +# module performance by implementing dedicated squaring code-path and +# possibly by unrolling loops... + +# January 2009. +# +# Reschedule to minimize/avoid Address Generation Interlock hazard, +# make inner loops counter-based. + +# November 2010. +# +# Adapt for -m31 build. If kernel supports what's called "highgprs" +# feature on Linux [see /proc/cpuinfo], it's possible to use 64-bit +# instructions and achieve "64-bit" performance even in 31-bit legacy +# application context. The feature is not specific to any particular +# processor, as long as it's "z-CPU". Latter implies that the code +# remains z/Architecture specific. Compatibility with 32-bit BN_ULONG +# is achieved by swapping words after 64-bit loads, follow _dswap-s. +# On z990 it was measured to perform 2.6-2.2 times better than +# compiler-generated code, less for longer keys... + +$flavour = shift; + +if ($flavour =~ /3[12]/) { + $SIZE_T=4; + $g=""; +} else { + $SIZE_T=8; + $g="g"; +} + +while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} +open STDOUT,">$output"; + +$stdframe=16*$SIZE_T+4*8; + +$mn0="%r0"; +$num="%r1"; + +# int bn_mul_mont( +$rp="%r2"; # BN_ULONG *rp, +$ap="%r3"; # const BN_ULONG *ap, +$bp="%r4"; # const BN_ULONG *bp, +$np="%r5"; # const BN_ULONG *np, +$n0="%r6"; # const BN_ULONG *n0, +#$num="160(%r15)" # int num); + +$bi="%r2"; # zaps rp +$j="%r7"; + +$ahi="%r8"; +$alo="%r9"; +$nhi="%r10"; +$nlo="%r11"; +$AHI="%r12"; +$NHI="%r13"; +$count="%r14"; +$sp="%r15"; + +$code.=<<___; +.text +.globl bn_mul_mont +.type bn_mul_mont,\@function +bn_mul_mont: + lgf $num,`$stdframe+$SIZE_T-4`($sp) # pull $num + sla $num,`log($SIZE_T)/log(2)` # $num to enumerate bytes + la $bp,0($num,$bp) + + st${g} %r2,2*$SIZE_T($sp) + + cghi $num,16 # + lghi %r2,0 # + blr %r14 # if($num<16) return 0; +___ +$code.=<<___ if ($flavour =~ /3[12]/); + tmll $num,4 + bnzr %r14 # if ($num&1) return 0; +___ +$code.=<<___ if ($flavour !~ /3[12]/); + cghi $num,96 # + bhr %r14 # if($num>96) return 0; +___ +$code.=<<___; + stm${g} %r3,%r15,3*$SIZE_T($sp) + + lghi $rp,-$stdframe-8 # leave room for carry bit + lcgr $j,$num # -$num + lgr %r0,$sp + la $rp,0($rp,$sp) + la $sp,0($j,$rp) # alloca + st${g} %r0,0($sp) # back chain + + sra $num,3 # restore $num + la $bp,0($j,$bp) # restore $bp + ahi $num,-1 # adjust $num for inner loop + lg $n0,0($n0) # pull n0 + _dswap $n0 + + lg $bi,0($bp) + _dswap $bi + lg $alo,0($ap) + _dswap $alo + mlgr $ahi,$bi # ap[0]*bp[0] + lgr $AHI,$ahi + + lgr $mn0,$alo # "tp[0]"*n0 + msgr $mn0,$n0 + + lg $nlo,0($np) # + _dswap $nlo + mlgr $nhi,$mn0 # np[0]*m1 + algr $nlo,$alo # +="tp[0]" + lghi $NHI,0 + alcgr $NHI,$nhi + + la $j,8(%r0) # j=1 + lr $count,$num + +.align 16 +.L1st: + lg $alo,0($j,$ap) + _dswap $alo + mlgr $ahi,$bi # ap[j]*bp[0] + algr $alo,$AHI + lghi $AHI,0 + alcgr $AHI,$ahi + + lg $nlo,0($j,$np) + _dswap $nlo + mlgr $nhi,$mn0 # np[j]*m1 + algr $nlo,$NHI + lghi $NHI,0 + alcgr $nhi,$NHI # +="tp[j]" + algr $nlo,$alo + alcgr $NHI,$nhi + + stg $nlo,$stdframe-8($j,$sp) # tp[j-1]= + la $j,8($j) # j++ + brct $count,.L1st + + algr $NHI,$AHI + lghi $AHI,0 + alcgr $AHI,$AHI # upmost overflow bit + stg $NHI,$stdframe-8($j,$sp) + stg $AHI,$stdframe($j,$sp) + la $bp,8($bp) # bp++ + +.Louter: + lg $bi,0($bp) # bp[i] + _dswap $bi + lg $alo,0($ap) + _dswap $alo + mlgr $ahi,$bi # ap[0]*bp[i] + alg $alo,$stdframe($sp) # +=tp[0] + lghi $AHI,0 + alcgr $AHI,$ahi + + lgr $mn0,$alo + msgr $mn0,$n0 # tp[0]*n0 + + lg $nlo,0($np) # np[0] + _dswap $nlo + mlgr $nhi,$mn0 # np[0]*m1 + algr $nlo,$alo # +="tp[0]" + lghi $NHI,0 + alcgr $NHI,$nhi + + la $j,8(%r0) # j=1 + lr $count,$num + +.align 16 +.Linner: + lg $alo,0($j,$ap) + _dswap $alo + mlgr $ahi,$bi # ap[j]*bp[i] + algr $alo,$AHI + lghi $AHI,0 + alcgr $ahi,$AHI + alg $alo,$stdframe($j,$sp)# +=tp[j] + alcgr $AHI,$ahi + + lg $nlo,0($j,$np) + _dswap $nlo + mlgr $nhi,$mn0 # np[j]*m1 + algr $nlo,$NHI + lghi $NHI,0 + alcgr $nhi,$NHI + algr $nlo,$alo # +="tp[j]" + alcgr $NHI,$nhi + + stg $nlo,$stdframe-8($j,$sp) # tp[j-1]= + la $j,8($j) # j++ + brct $count,.Linner + + algr $NHI,$AHI + lghi $AHI,0 + alcgr $AHI,$AHI + alg $NHI,$stdframe($j,$sp)# accumulate previous upmost overflow bit + lghi $ahi,0 + alcgr $AHI,$ahi # new upmost overflow bit + stg $NHI,$stdframe-8($j,$sp) + stg $AHI,$stdframe($j,$sp) + + la $bp,8($bp) # bp++ + cl${g} $bp,`$stdframe+8+4*$SIZE_T`($j,$sp) # compare to &bp[num] + jne .Louter + + l${g} $rp,`$stdframe+8+2*$SIZE_T`($j,$sp) # reincarnate rp + la $ap,$stdframe($sp) + ahi $num,1 # restore $num, incidentally clears "borrow" + + la $j,0(%r0) + lr $count,$num +.Lsub: lg $alo,0($j,$ap) + lg $nlo,0($j,$np) + _dswap $nlo + slbgr $alo,$nlo + stg $alo,0($j,$rp) + la $j,8($j) + brct $count,.Lsub + lghi $ahi,0 + slbgr $AHI,$ahi # handle upmost carry + lghi $NHI,-1 + xgr $NHI,$AHI + + la $j,0(%r0) + lgr $count,$num +.Lcopy: lg $ahi,$stdframe($j,$sp) # conditional copy + lg $alo,0($j,$rp) + ngr $ahi,$AHI + ngr $alo,$NHI + ogr $alo,$ahi + _dswap $alo + stg $j,$stdframe($j,$sp) # zap tp + stg $alo,0($j,$rp) + la $j,8($j) + brct $count,.Lcopy + + la %r1,`$stdframe+8+6*$SIZE_T`($j,$sp) + lm${g} %r6,%r15,0(%r1) + lghi %r2,1 # signal "processed" + br %r14 +.size bn_mul_mont,.-bn_mul_mont +.string "Montgomery Multiplication for s390x, CRYPTOGAMS by " +___ + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/ge; + s/_dswap\s+(%r[0-9]+)/sprintf("rllg\t%s,%s,32",$1,$1) if($SIZE_T==4)/e; + print $_,"\n"; +} +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/s390x.S b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/s390x.S new file mode 100644 index 000000000..292a7a999 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/s390x.S @@ -0,0 +1,713 @@ +.ident "s390x.S, version 1.1" +// ==================================================================== +// Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved. +// +// Licensed under the OpenSSL license (the "License"). You may not use +// this file except in compliance with the License. You can obtain a copy +// in the file LICENSE in the source distribution or at +// https://www.openssl.org/source/license.html +// ==================================================================== + +.text + +#define zero %r0 + +// BN_ULONG bn_mul_add_words(BN_ULONG *r2,BN_ULONG *r3,int r4,BN_ULONG r5); +.globl bn_mul_add_words +.type bn_mul_add_words,@function +.align 4 +bn_mul_add_words: + lghi zero,0 // zero = 0 + la %r1,0(%r2) // put rp aside [to give way to] + lghi %r2,0 // return value + ltgfr %r4,%r4 + bler %r14 // if (len<=0) return 0; + + stmg %r6,%r13,48(%r15) + lghi %r2,3 + lghi %r12,0 // carry = 0 + slgr %r1,%r3 // rp-=ap + nr %r2,%r4 // len%4 + sra %r4,2 // cnt=len/4 + jz .Loop1_madd // carry is incidentally cleared if branch taken + algr zero,zero // clear carry + + lg %r7,0(%r3) // ap[0] + lg %r9,8(%r3) // ap[1] + mlgr %r6,%r5 // *=w + brct %r4,.Loop4_madd + j .Loop4_madd_tail + +.Loop4_madd: + mlgr %r8,%r5 + lg %r11,16(%r3) // ap[i+2] + alcgr %r7,%r12 // +=carry + alcgr %r6,zero + alg %r7,0(%r3,%r1) // +=rp[i] + stg %r7,0(%r3,%r1) // rp[i]= + + mlgr %r10,%r5 + lg %r13,24(%r3) + alcgr %r9,%r6 + alcgr %r8,zero + alg %r9,8(%r3,%r1) + stg %r9,8(%r3,%r1) + + mlgr %r12,%r5 + lg %r7,32(%r3) + alcgr %r11,%r8 + alcgr %r10,zero + alg %r11,16(%r3,%r1) + stg %r11,16(%r3,%r1) + + mlgr %r6,%r5 + lg %r9,40(%r3) + alcgr %r13,%r10 + alcgr %r12,zero + alg %r13,24(%r3,%r1) + stg %r13,24(%r3,%r1) + + la %r3,32(%r3) // i+=4 + brct %r4,.Loop4_madd + +.Loop4_madd_tail: + mlgr %r8,%r5 + lg %r11,16(%r3) + alcgr %r7,%r12 // +=carry + alcgr %r6,zero + alg %r7,0(%r3,%r1) // +=rp[i] + stg %r7,0(%r3,%r1) // rp[i]= + + mlgr %r10,%r5 + lg %r13,24(%r3) + alcgr %r9,%r6 + alcgr %r8,zero + alg %r9,8(%r3,%r1) + stg %r9,8(%r3,%r1) + + mlgr %r12,%r5 + alcgr %r11,%r8 + alcgr %r10,zero + alg %r11,16(%r3,%r1) + stg %r11,16(%r3,%r1) + + alcgr %r13,%r10 + alcgr %r12,zero + alg %r13,24(%r3,%r1) + stg %r13,24(%r3,%r1) + + la %r3,32(%r3) // i+=4 + + la %r2,1(%r2) // see if len%4 is zero ... + brct %r2,.Loop1_madd // without touching condition code:-) + +.Lend_madd: + lgr %r2,zero // return value + alcgr %r2,%r12 // collect even carry bit + lmg %r6,%r13,48(%r15) + br %r14 + +.Loop1_madd: + lg %r7,0(%r3) // ap[i] + mlgr %r6,%r5 // *=w + alcgr %r7,%r12 // +=carry + alcgr %r6,zero + alg %r7,0(%r3,%r1) // +=rp[i] + stg %r7,0(%r3,%r1) // rp[i]= + + lgr %r12,%r6 + la %r3,8(%r3) // i++ + brct %r2,.Loop1_madd + + j .Lend_madd +.size bn_mul_add_words,.-bn_mul_add_words + +// BN_ULONG bn_mul_words(BN_ULONG *r2,BN_ULONG *r3,int r4,BN_ULONG r5); +.globl bn_mul_words +.type bn_mul_words,@function +.align 4 +bn_mul_words: + lghi zero,0 // zero = 0 + la %r1,0(%r2) // put rp aside + lghi %r2,0 // i=0; + ltgfr %r4,%r4 + bler %r14 // if (len<=0) return 0; + + stmg %r6,%r10,48(%r15) + lghi %r10,3 + lghi %r8,0 // carry = 0 + nr %r10,%r4 // len%4 + sra %r4,2 // cnt=len/4 + jz .Loop1_mul // carry is incidentally cleared if branch taken + algr zero,zero // clear carry + +.Loop4_mul: + lg %r7,0(%r2,%r3) // ap[i] + mlgr %r6,%r5 // *=w + alcgr %r7,%r8 // +=carry + stg %r7,0(%r2,%r1) // rp[i]= + + lg %r9,8(%r2,%r3) + mlgr %r8,%r5 + alcgr %r9,%r6 + stg %r9,8(%r2,%r1) + + lg %r7,16(%r2,%r3) + mlgr %r6,%r5 + alcgr %r7,%r8 + stg %r7,16(%r2,%r1) + + lg %r9,24(%r2,%r3) + mlgr %r8,%r5 + alcgr %r9,%r6 + stg %r9,24(%r2,%r1) + + la %r2,32(%r2) // i+=4 + brct %r4,.Loop4_mul + + la %r10,1(%r10) // see if len%4 is zero ... + brct %r10,.Loop1_mul // without touching condition code:-) + +.Lend_mul: + alcgr %r8,zero // collect carry bit + lgr %r2,%r8 + lmg %r6,%r10,48(%r15) + br %r14 + +.Loop1_mul: + lg %r7,0(%r2,%r3) // ap[i] + mlgr %r6,%r5 // *=w + alcgr %r7,%r8 // +=carry + stg %r7,0(%r2,%r1) // rp[i]= + + lgr %r8,%r6 + la %r2,8(%r2) // i++ + brct %r10,.Loop1_mul + + j .Lend_mul +.size bn_mul_words,.-bn_mul_words + +// void bn_sqr_words(BN_ULONG *r2,BN_ULONG *r2,int r4) +.globl bn_sqr_words +.type bn_sqr_words,@function +.align 4 +bn_sqr_words: + ltgfr %r4,%r4 + bler %r14 + + stmg %r6,%r7,48(%r15) + srag %r1,%r4,2 // cnt=len/4 + jz .Loop1_sqr + +.Loop4_sqr: + lg %r7,0(%r3) + mlgr %r6,%r7 + stg %r7,0(%r2) + stg %r6,8(%r2) + + lg %r7,8(%r3) + mlgr %r6,%r7 + stg %r7,16(%r2) + stg %r6,24(%r2) + + lg %r7,16(%r3) + mlgr %r6,%r7 + stg %r7,32(%r2) + stg %r6,40(%r2) + + lg %r7,24(%r3) + mlgr %r6,%r7 + stg %r7,48(%r2) + stg %r6,56(%r2) + + la %r3,32(%r3) + la %r2,64(%r2) + brct %r1,.Loop4_sqr + + lghi %r1,3 + nr %r4,%r1 // cnt=len%4 + jz .Lend_sqr + +.Loop1_sqr: + lg %r7,0(%r3) + mlgr %r6,%r7 + stg %r7,0(%r2) + stg %r6,8(%r2) + + la %r3,8(%r3) + la %r2,16(%r2) + brct %r4,.Loop1_sqr + +.Lend_sqr: + lmg %r6,%r7,48(%r15) + br %r14 +.size bn_sqr_words,.-bn_sqr_words + +// BN_ULONG bn_div_words(BN_ULONG h,BN_ULONG l,BN_ULONG d); +.globl bn_div_words +.type bn_div_words,@function +.align 4 +bn_div_words: + dlgr %r2,%r4 + lgr %r2,%r3 + br %r14 +.size bn_div_words,.-bn_div_words + +// BN_ULONG bn_add_words(BN_ULONG *r2,BN_ULONG *r3,BN_ULONG *r4,int r5); +.globl bn_add_words +.type bn_add_words,@function +.align 4 +bn_add_words: + la %r1,0(%r2) // put rp aside + lghi %r2,0 // i=0 + ltgfr %r5,%r5 + bler %r14 // if (len<=0) return 0; + + stg %r6,48(%r15) + lghi %r6,3 + nr %r6,%r5 // len%4 + sra %r5,2 // len/4, use sra because it sets condition code + jz .Loop1_add // carry is incidentally cleared if branch taken + algr %r2,%r2 // clear carry + +.Loop4_add: + lg %r0,0(%r2,%r3) + alcg %r0,0(%r2,%r4) + stg %r0,0(%r2,%r1) + lg %r0,8(%r2,%r3) + alcg %r0,8(%r2,%r4) + stg %r0,8(%r2,%r1) + lg %r0,16(%r2,%r3) + alcg %r0,16(%r2,%r4) + stg %r0,16(%r2,%r1) + lg %r0,24(%r2,%r3) + alcg %r0,24(%r2,%r4) + stg %r0,24(%r2,%r1) + + la %r2,32(%r2) // i+=4 + brct %r5,.Loop4_add + + la %r6,1(%r6) // see if len%4 is zero ... + brct %r6,.Loop1_add // without touching condition code:-) + +.Lexit_add: + lghi %r2,0 + alcgr %r2,%r2 + lg %r6,48(%r15) + br %r14 + +.Loop1_add: + lg %r0,0(%r2,%r3) + alcg %r0,0(%r2,%r4) + stg %r0,0(%r2,%r1) + + la %r2,8(%r2) // i++ + brct %r6,.Loop1_add + + j .Lexit_add +.size bn_add_words,.-bn_add_words + +// BN_ULONG bn_sub_words(BN_ULONG *r2,BN_ULONG *r3,BN_ULONG *r4,int r5); +.globl bn_sub_words +.type bn_sub_words,@function +.align 4 +bn_sub_words: + la %r1,0(%r2) // put rp aside + lghi %r2,0 // i=0 + ltgfr %r5,%r5 + bler %r14 // if (len<=0) return 0; + + stg %r6,48(%r15) + lghi %r6,3 + nr %r6,%r5 // len%4 + sra %r5,2 // len/4, use sra because it sets condition code + jnz .Loop4_sub // borrow is incidentally cleared if branch taken + slgr %r2,%r2 // clear borrow + +.Loop1_sub: + lg %r0,0(%r2,%r3) + slbg %r0,0(%r2,%r4) + stg %r0,0(%r2,%r1) + + la %r2,8(%r2) // i++ + brct %r6,.Loop1_sub + j .Lexit_sub + +.Loop4_sub: + lg %r0,0(%r2,%r3) + slbg %r0,0(%r2,%r4) + stg %r0,0(%r2,%r1) + lg %r0,8(%r2,%r3) + slbg %r0,8(%r2,%r4) + stg %r0,8(%r2,%r1) + lg %r0,16(%r2,%r3) + slbg %r0,16(%r2,%r4) + stg %r0,16(%r2,%r1) + lg %r0,24(%r2,%r3) + slbg %r0,24(%r2,%r4) + stg %r0,24(%r2,%r1) + + la %r2,32(%r2) // i+=4 + brct %r5,.Loop4_sub + + la %r6,1(%r6) // see if len%4 is zero ... + brct %r6,.Loop1_sub // without touching condition code:-) + +.Lexit_sub: + lghi %r2,0 + slbgr %r2,%r2 + lcgr %r2,%r2 + lg %r6,48(%r15) + br %r14 +.size bn_sub_words,.-bn_sub_words + +#define c1 %r1 +#define c2 %r5 +#define c3 %r8 + +#define mul_add_c(ai,bi,c1,c2,c3) \ + lg %r7,ai*8(%r3); \ + mlg %r6,bi*8(%r4); \ + algr c1,%r7; \ + alcgr c2,%r6; \ + alcgr c3,zero + +// void bn_mul_comba8(BN_ULONG *r2,BN_ULONG *r3,BN_ULONG *r4); +.globl bn_mul_comba8 +.type bn_mul_comba8,@function +.align 4 +bn_mul_comba8: + stmg %r6,%r8,48(%r15) + + lghi c1,0 + lghi c2,0 + lghi c3,0 + lghi zero,0 + + mul_add_c(0,0,c1,c2,c3); + stg c1,0*8(%r2) + lghi c1,0 + + mul_add_c(0,1,c2,c3,c1); + mul_add_c(1,0,c2,c3,c1); + stg c2,1*8(%r2) + lghi c2,0 + + mul_add_c(2,0,c3,c1,c2); + mul_add_c(1,1,c3,c1,c2); + mul_add_c(0,2,c3,c1,c2); + stg c3,2*8(%r2) + lghi c3,0 + + mul_add_c(0,3,c1,c2,c3); + mul_add_c(1,2,c1,c2,c3); + mul_add_c(2,1,c1,c2,c3); + mul_add_c(3,0,c1,c2,c3); + stg c1,3*8(%r2) + lghi c1,0 + + mul_add_c(4,0,c2,c3,c1); + mul_add_c(3,1,c2,c3,c1); + mul_add_c(2,2,c2,c3,c1); + mul_add_c(1,3,c2,c3,c1); + mul_add_c(0,4,c2,c3,c1); + stg c2,4*8(%r2) + lghi c2,0 + + mul_add_c(0,5,c3,c1,c2); + mul_add_c(1,4,c3,c1,c2); + mul_add_c(2,3,c3,c1,c2); + mul_add_c(3,2,c3,c1,c2); + mul_add_c(4,1,c3,c1,c2); + mul_add_c(5,0,c3,c1,c2); + stg c3,5*8(%r2) + lghi c3,0 + + mul_add_c(6,0,c1,c2,c3); + mul_add_c(5,1,c1,c2,c3); + mul_add_c(4,2,c1,c2,c3); + mul_add_c(3,3,c1,c2,c3); + mul_add_c(2,4,c1,c2,c3); + mul_add_c(1,5,c1,c2,c3); + mul_add_c(0,6,c1,c2,c3); + stg c1,6*8(%r2) + lghi c1,0 + + mul_add_c(0,7,c2,c3,c1); + mul_add_c(1,6,c2,c3,c1); + mul_add_c(2,5,c2,c3,c1); + mul_add_c(3,4,c2,c3,c1); + mul_add_c(4,3,c2,c3,c1); + mul_add_c(5,2,c2,c3,c1); + mul_add_c(6,1,c2,c3,c1); + mul_add_c(7,0,c2,c3,c1); + stg c2,7*8(%r2) + lghi c2,0 + + mul_add_c(7,1,c3,c1,c2); + mul_add_c(6,2,c3,c1,c2); + mul_add_c(5,3,c3,c1,c2); + mul_add_c(4,4,c3,c1,c2); + mul_add_c(3,5,c3,c1,c2); + mul_add_c(2,6,c3,c1,c2); + mul_add_c(1,7,c3,c1,c2); + stg c3,8*8(%r2) + lghi c3,0 + + mul_add_c(2,7,c1,c2,c3); + mul_add_c(3,6,c1,c2,c3); + mul_add_c(4,5,c1,c2,c3); + mul_add_c(5,4,c1,c2,c3); + mul_add_c(6,3,c1,c2,c3); + mul_add_c(7,2,c1,c2,c3); + stg c1,9*8(%r2) + lghi c1,0 + + mul_add_c(7,3,c2,c3,c1); + mul_add_c(6,4,c2,c3,c1); + mul_add_c(5,5,c2,c3,c1); + mul_add_c(4,6,c2,c3,c1); + mul_add_c(3,7,c2,c3,c1); + stg c2,10*8(%r2) + lghi c2,0 + + mul_add_c(4,7,c3,c1,c2); + mul_add_c(5,6,c3,c1,c2); + mul_add_c(6,5,c3,c1,c2); + mul_add_c(7,4,c3,c1,c2); + stg c3,11*8(%r2) + lghi c3,0 + + mul_add_c(7,5,c1,c2,c3); + mul_add_c(6,6,c1,c2,c3); + mul_add_c(5,7,c1,c2,c3); + stg c1,12*8(%r2) + lghi c1,0 + + + mul_add_c(6,7,c2,c3,c1); + mul_add_c(7,6,c2,c3,c1); + stg c2,13*8(%r2) + lghi c2,0 + + mul_add_c(7,7,c3,c1,c2); + stg c3,14*8(%r2) + stg c1,15*8(%r2) + + lmg %r6,%r8,48(%r15) + br %r14 +.size bn_mul_comba8,.-bn_mul_comba8 + +// void bn_mul_comba4(BN_ULONG *r2,BN_ULONG *r3,BN_ULONG *r4); +.globl bn_mul_comba4 +.type bn_mul_comba4,@function +.align 4 +bn_mul_comba4: + stmg %r6,%r8,48(%r15) + + lghi c1,0 + lghi c2,0 + lghi c3,0 + lghi zero,0 + + mul_add_c(0,0,c1,c2,c3); + stg c1,0*8(%r3) + lghi c1,0 + + mul_add_c(0,1,c2,c3,c1); + mul_add_c(1,0,c2,c3,c1); + stg c2,1*8(%r2) + lghi c2,0 + + mul_add_c(2,0,c3,c1,c2); + mul_add_c(1,1,c3,c1,c2); + mul_add_c(0,2,c3,c1,c2); + stg c3,2*8(%r2) + lghi c3,0 + + mul_add_c(0,3,c1,c2,c3); + mul_add_c(1,2,c1,c2,c3); + mul_add_c(2,1,c1,c2,c3); + mul_add_c(3,0,c1,c2,c3); + stg c1,3*8(%r2) + lghi c1,0 + + mul_add_c(3,1,c2,c3,c1); + mul_add_c(2,2,c2,c3,c1); + mul_add_c(1,3,c2,c3,c1); + stg c2,4*8(%r2) + lghi c2,0 + + mul_add_c(2,3,c3,c1,c2); + mul_add_c(3,2,c3,c1,c2); + stg c3,5*8(%r2) + lghi c3,0 + + mul_add_c(3,3,c1,c2,c3); + stg c1,6*8(%r2) + stg c2,7*8(%r2) + + stmg %r6,%r8,48(%r15) + br %r14 +.size bn_mul_comba4,.-bn_mul_comba4 + +#define sqr_add_c(ai,c1,c2,c3) \ + lg %r7,ai*8(%r3); \ + mlgr %r6,%r7; \ + algr c1,%r7; \ + alcgr c2,%r6; \ + alcgr c3,zero + +#define sqr_add_c2(ai,aj,c1,c2,c3) \ + lg %r7,ai*8(%r3); \ + mlg %r6,aj*8(%r3); \ + algr c1,%r7; \ + alcgr c2,%r6; \ + alcgr c3,zero; \ + algr c1,%r7; \ + alcgr c2,%r6; \ + alcgr c3,zero + +// void bn_sqr_comba8(BN_ULONG *r2,BN_ULONG *r3); +.globl bn_sqr_comba8 +.type bn_sqr_comba8,@function +.align 4 +bn_sqr_comba8: + stmg %r6,%r8,48(%r15) + + lghi c1,0 + lghi c2,0 + lghi c3,0 + lghi zero,0 + + sqr_add_c(0,c1,c2,c3); + stg c1,0*8(%r2) + lghi c1,0 + + sqr_add_c2(1,0,c2,c3,c1); + stg c2,1*8(%r2) + lghi c2,0 + + sqr_add_c(1,c3,c1,c2); + sqr_add_c2(2,0,c3,c1,c2); + stg c3,2*8(%r2) + lghi c3,0 + + sqr_add_c2(3,0,c1,c2,c3); + sqr_add_c2(2,1,c1,c2,c3); + stg c1,3*8(%r2) + lghi c1,0 + + sqr_add_c(2,c2,c3,c1); + sqr_add_c2(3,1,c2,c3,c1); + sqr_add_c2(4,0,c2,c3,c1); + stg c2,4*8(%r2) + lghi c2,0 + + sqr_add_c2(5,0,c3,c1,c2); + sqr_add_c2(4,1,c3,c1,c2); + sqr_add_c2(3,2,c3,c1,c2); + stg c3,5*8(%r2) + lghi c3,0 + + sqr_add_c(3,c1,c2,c3); + sqr_add_c2(4,2,c1,c2,c3); + sqr_add_c2(5,1,c1,c2,c3); + sqr_add_c2(6,0,c1,c2,c3); + stg c1,6*8(%r2) + lghi c1,0 + + sqr_add_c2(7,0,c2,c3,c1); + sqr_add_c2(6,1,c2,c3,c1); + sqr_add_c2(5,2,c2,c3,c1); + sqr_add_c2(4,3,c2,c3,c1); + stg c2,7*8(%r2) + lghi c2,0 + + sqr_add_c(4,c3,c1,c2); + sqr_add_c2(5,3,c3,c1,c2); + sqr_add_c2(6,2,c3,c1,c2); + sqr_add_c2(7,1,c3,c1,c2); + stg c3,8*8(%r2) + lghi c3,0 + + sqr_add_c2(7,2,c1,c2,c3); + sqr_add_c2(6,3,c1,c2,c3); + sqr_add_c2(5,4,c1,c2,c3); + stg c1,9*8(%r2) + lghi c1,0 + + sqr_add_c(5,c2,c3,c1); + sqr_add_c2(6,4,c2,c3,c1); + sqr_add_c2(7,3,c2,c3,c1); + stg c2,10*8(%r2) + lghi c2,0 + + sqr_add_c2(7,4,c3,c1,c2); + sqr_add_c2(6,5,c3,c1,c2); + stg c3,11*8(%r2) + lghi c3,0 + + sqr_add_c(6,c1,c2,c3); + sqr_add_c2(7,5,c1,c2,c3); + stg c1,12*8(%r2) + lghi c1,0 + + sqr_add_c2(7,6,c2,c3,c1); + stg c2,13*8(%r2) + lghi c2,0 + + sqr_add_c(7,c3,c1,c2); + stg c3,14*8(%r2) + stg c1,15*8(%r2) + + lmg %r6,%r8,48(%r15) + br %r14 +.size bn_sqr_comba8,.-bn_sqr_comba8 + +// void bn_sqr_comba4(BN_ULONG *r2,BN_ULONG *r3); +.globl bn_sqr_comba4 +.type bn_sqr_comba4,@function +.align 4 +bn_sqr_comba4: + stmg %r6,%r8,48(%r15) + + lghi c1,0 + lghi c2,0 + lghi c3,0 + lghi zero,0 + + sqr_add_c(0,c1,c2,c3); + stg c1,0*8(%r2) + lghi c1,0 + + sqr_add_c2(1,0,c2,c3,c1); + stg c2,1*8(%r2) + lghi c2,0 + + sqr_add_c(1,c3,c1,c2); + sqr_add_c2(2,0,c3,c1,c2); + stg c3,2*8(%r2) + lghi c3,0 + + sqr_add_c2(3,0,c1,c2,c3); + sqr_add_c2(2,1,c1,c2,c3); + stg c1,3*8(%r2) + lghi c1,0 + + sqr_add_c(2,c2,c3,c1); + sqr_add_c2(3,1,c2,c3,c1); + stg c2,4*8(%r2) + lghi c2,0 + + sqr_add_c2(3,2,c3,c1,c2); + stg c3,5*8(%r2) + lghi c3,0 + + sqr_add_c(3,c1,c2,c3); + stg c1,6*8(%r2) + stg c2,7*8(%r2) + + lmg %r6,%r8,48(%r15) + br %r14 +.size bn_sqr_comba4,.-bn_sqr_comba4 diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/sparct4-mont.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/sparct4-mont.pl new file mode 100755 index 000000000..fcae9cfc5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/sparct4-mont.pl @@ -0,0 +1,1228 @@ +#! /usr/bin/env perl +# Copyright 2012-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by David S. Miller and Andy Polyakov +# The module is licensed under 2-clause BSD license. +# November 2012. All rights reserved. +# ==================================================================== + +###################################################################### +# Montgomery squaring-n-multiplication module for SPARC T4. +# +# The module consists of three parts: +# +# 1) collection of "single-op" subroutines that perform single +# operation, Montgomery squaring or multiplication, on 512-, +# 1024-, 1536- and 2048-bit operands; +# 2) collection of "multi-op" subroutines that perform 5 squaring and +# 1 multiplication operations on operands of above lengths; +# 3) fall-back and helper VIS3 subroutines. +# +# RSA sign is dominated by multi-op subroutine, while RSA verify and +# DSA - by single-op. Special note about 4096-bit RSA verify result. +# Operands are too long for dedicated hardware and it's handled by +# VIS3 code, which is why you don't see any improvement. It's surely +# possible to improve it [by deploying 'mpmul' instruction], maybe in +# the future... +# +# Performance improvement. +# +# 64-bit process, VIS3: +# sign verify sign/s verify/s +# rsa 1024 bits 0.000628s 0.000028s 1592.4 35434.4 +# rsa 2048 bits 0.003282s 0.000106s 304.7 9438.3 +# rsa 4096 bits 0.025866s 0.000340s 38.7 2940.9 +# dsa 1024 bits 0.000301s 0.000332s 3323.7 3013.9 +# dsa 2048 bits 0.001056s 0.001233s 946.9 810.8 +# +# 64-bit process, this module: +# sign verify sign/s verify/s +# rsa 1024 bits 0.000256s 0.000016s 3904.4 61411.9 +# rsa 2048 bits 0.000946s 0.000029s 1056.8 34292.7 +# rsa 4096 bits 0.005061s 0.000340s 197.6 2940.5 +# dsa 1024 bits 0.000176s 0.000195s 5674.7 5130.5 +# dsa 2048 bits 0.000296s 0.000354s 3383.2 2827.6 +# +###################################################################### +# 32-bit process, VIS3: +# sign verify sign/s verify/s +# rsa 1024 bits 0.000665s 0.000028s 1504.8 35233.3 +# rsa 2048 bits 0.003349s 0.000106s 298.6 9433.4 +# rsa 4096 bits 0.025959s 0.000341s 38.5 2934.8 +# dsa 1024 bits 0.000320s 0.000341s 3123.3 2929.6 +# dsa 2048 bits 0.001101s 0.001260s 908.2 793.4 +# +# 32-bit process, this module: +# sign verify sign/s verify/s +# rsa 1024 bits 0.000301s 0.000017s 3317.1 60240.0 +# rsa 2048 bits 0.001034s 0.000030s 966.9 33812.7 +# rsa 4096 bits 0.005244s 0.000341s 190.7 2935.4 +# dsa 1024 bits 0.000201s 0.000205s 4976.1 4879.2 +# dsa 2048 bits 0.000328s 0.000360s 3051.1 2774.2 +# +# 32-bit code is prone to performance degradation as interrupt rate +# dispatched to CPU executing the code grows. This is because in +# standard process of handling interrupt in 32-bit process context +# upper halves of most integer registers used as input or output are +# zeroed. This renders result invalid, and operation has to be re-run. +# If CPU is "bothered" with timer interrupts only, the penalty is +# hardly measurable. But in order to mitigate this problem for higher +# interrupt rates contemporary Linux kernel recognizes biased stack +# even in 32-bit process context and preserves full register contents. +# See http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=517ffce4e1a03aea979fe3a18a3dd1761a24fafb +# for details. + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "sparcv9_modes.pl"; + +$output = pop; +open STDOUT,">$output"; + +$code.=<<___; +#include "sparc_arch.h" + +#ifdef __arch64__ +.register %g2,#scratch +.register %g3,#scratch +#endif + +.section ".text",#alloc,#execinstr + +#ifdef __PIC__ +SPARC_PIC_THUNK(%g1) +#endif +___ + +######################################################################## +# Register layout for mont[mul|sqr] instructions. +# For details see "Oracle SPARC Architecture 2011" manual at +# http://www.oracle.com/technetwork/server-storage/sun-sparc-enterprise/documentation/. +# +my @R=map("%f".2*$_,(0..11,30,31,12..29)); +my @N=(map("%l$_",(0..7)),map("%o$_",(0..5))); @N=(@N,@N,@N[0..3]); +my @A=(@N[0..13],@R[14..31]); +my @B=(map("%i$_",(0..5)),map("%l$_",(0..7))); @B=(@B,@B,map("%o$_",(0..3))); + +######################################################################## +# int bn_mul_mont_t4_$NUM(u64 *rp,const u64 *ap,const u64 *bp, +# const u64 *np,const BN_ULONG *n0); +# +sub generate_bn_mul_mont_t4() { +my $NUM=shift; +my ($rp,$ap,$bp,$np,$sentinel)=map("%g$_",(1..5)); + +$code.=<<___; +.globl bn_mul_mont_t4_$NUM +.align 32 +bn_mul_mont_t4_$NUM: +#ifdef __arch64__ + mov 0,$sentinel + mov -128,%g4 +#elif defined(SPARCV9_64BIT_STACK) + SPARC_LOAD_ADDRESS_LEAF(OPENSSL_sparcv9cap_P,%g1,%g5) + ld [%g1+0],%g1 ! OPENSSL_sparcv9_P[0] + mov -2047,%g4 + and %g1,SPARCV9_64BIT_STACK,%g1 + movrz %g1,0,%g4 + mov -1,$sentinel + add %g4,-128,%g4 +#else + mov -1,$sentinel + mov -128,%g4 +#endif + sllx $sentinel,32,$sentinel + save %sp,%g4,%sp +#ifndef __arch64__ + save %sp,-128,%sp ! warm it up + save %sp,-128,%sp + save %sp,-128,%sp + save %sp,-128,%sp + save %sp,-128,%sp + save %sp,-128,%sp + restore + restore + restore + restore + restore + restore +#endif + and %sp,1,%g4 + or $sentinel,%fp,%fp + or %g4,$sentinel,$sentinel + + ! copy arguments to global registers + mov %i0,$rp + mov %i1,$ap + mov %i2,$bp + mov %i3,$np + ld [%i4+0],%f1 ! load *n0 + ld [%i4+4],%f0 + fsrc2 %f0,%f60 +___ + +# load ap[$NUM] ######################################################## +$code.=<<___; + save %sp,-128,%sp; or $sentinel,%fp,%fp +___ +for($i=0; $i<14 && $i<$NUM; $i++) { +my $lo=$i<13?@A[$i+1]:"%o7"; +$code.=<<___; + ld [$ap+$i*8+0],$lo + ld [$ap+$i*8+4],@A[$i] + sllx @A[$i],32,@A[$i] + or $lo,@A[$i],@A[$i] +___ +} +for(; $i<$NUM; $i++) { +my ($hi,$lo)=("%f".2*($i%4),"%f".(2*($i%4)+1)); +$code.=<<___; + ld [$ap+$i*8+0],$lo + ld [$ap+$i*8+4],$hi + fsrc2 $hi,@A[$i] +___ +} +# load np[$NUM] ######################################################## +$code.=<<___; + save %sp,-128,%sp; or $sentinel,%fp,%fp +___ +for($i=0; $i<14 && $i<$NUM; $i++) { +my $lo=$i<13?@N[$i+1]:"%o7"; +$code.=<<___; + ld [$np+$i*8+0],$lo + ld [$np+$i*8+4],@N[$i] + sllx @N[$i],32,@N[$i] + or $lo,@N[$i],@N[$i] +___ +} +$code.=<<___; + save %sp,-128,%sp; or $sentinel,%fp,%fp +___ +for(; $i<28 && $i<$NUM; $i++) { +my $lo=$i<27?@N[$i+1]:"%o7"; +$code.=<<___; + ld [$np+$i*8+0],$lo + ld [$np+$i*8+4],@N[$i] + sllx @N[$i],32,@N[$i] + or $lo,@N[$i],@N[$i] +___ +} +$code.=<<___; + save %sp,-128,%sp; or $sentinel,%fp,%fp +___ +for(; $i<$NUM; $i++) { +my $lo=($i<$NUM-1)?@N[$i+1]:"%o7"; +$code.=<<___; + ld [$np+$i*8+0],$lo + ld [$np+$i*8+4],@N[$i] + sllx @N[$i],32,@N[$i] + or $lo,@N[$i],@N[$i] +___ +} +$code.=<<___; + cmp $ap,$bp + be SIZE_T_CC,.Lmsquare_$NUM + nop +___ + +# load bp[$NUM] ######################################################## +$code.=<<___; + save %sp,-128,%sp; or $sentinel,%fp,%fp +___ +for($i=0; $i<14 && $i<$NUM; $i++) { +my $lo=$i<13?@B[$i+1]:"%o7"; +$code.=<<___; + ld [$bp+$i*8+0],$lo + ld [$bp+$i*8+4],@B[$i] + sllx @B[$i],32,@B[$i] + or $lo,@B[$i],@B[$i] +___ +} +$code.=<<___; + save %sp,-128,%sp; or $sentinel,%fp,%fp +___ +for(; $i<$NUM; $i++) { +my $lo=($i<$NUM-1)?@B[$i+1]:"%o7"; +$code.=<<___; + ld [$bp+$i*8+0],$lo + ld [$bp+$i*8+4],@B[$i] + sllx @B[$i],32,@B[$i] + or $lo,@B[$i],@B[$i] +___ +} +# magic ################################################################ +$code.=<<___; + .word 0x81b02920+$NUM-1 ! montmul $NUM-1 +.Lmresume_$NUM: + fbu,pn %fcc3,.Lmabort_$NUM +#ifndef __arch64__ + and %fp,$sentinel,$sentinel + brz,pn $sentinel,.Lmabort_$NUM +#endif + nop +#ifdef __arch64__ + restore + restore + restore + restore + restore +#else + restore; and %fp,$sentinel,$sentinel + restore; and %fp,$sentinel,$sentinel + restore; and %fp,$sentinel,$sentinel + restore; and %fp,$sentinel,$sentinel + brz,pn $sentinel,.Lmabort1_$NUM + restore +#endif +___ + +# save tp[$NUM] ######################################################## +for($i=0; $i<14 && $i<$NUM; $i++) { +$code.=<<___; + movxtod @A[$i],@R[$i] +___ +} +$code.=<<___; +#ifdef __arch64__ + restore +#else + and %fp,$sentinel,$sentinel + restore + and $sentinel,1,%o7 + and %fp,$sentinel,$sentinel + srl %fp,0,%fp ! just in case? + or %o7,$sentinel,$sentinel + brz,a,pn $sentinel,.Lmdone_$NUM + mov 0,%i0 ! return failure +#endif +___ +for($i=0; $i<12 && $i<$NUM; $i++) { +@R[$i] =~ /%f([0-9]+)/; +my $lo = "%f".($1+1); +$code.=<<___; + st $lo,[$rp+$i*8+0] + st @R[$i],[$rp+$i*8+4] +___ +} +for(; $i<$NUM; $i++) { +my ($hi,$lo)=("%f".2*($i%4),"%f".(2*($i%4)+1)); +$code.=<<___; + fsrc2 @R[$i],$hi + st $lo,[$rp+$i*8+0] + st $hi,[$rp+$i*8+4] +___ +} +$code.=<<___; + mov 1,%i0 ! return success +.Lmdone_$NUM: + ret + restore + +.Lmabort_$NUM: + restore + restore + restore + restore + restore +.Lmabort1_$NUM: + restore + + mov 0,%i0 ! return failure + ret + restore + +.align 32 +.Lmsquare_$NUM: + save %sp,-128,%sp; or $sentinel,%fp,%fp + save %sp,-128,%sp; or $sentinel,%fp,%fp + .word 0x81b02940+$NUM-1 ! montsqr $NUM-1 + ba .Lmresume_$NUM + nop +.type bn_mul_mont_t4_$NUM, #function +.size bn_mul_mont_t4_$NUM, .-bn_mul_mont_t4_$NUM +___ +} + +for ($i=8;$i<=32;$i+=8) { + &generate_bn_mul_mont_t4($i); +} + +######################################################################## +# +sub load_ccr { +my ($ptbl,$pwr,$ccr,$skip_wr)=@_; +$code.=<<___; + srl $pwr, 2, %o4 + and $pwr, 3, %o5 + and %o4, 7, %o4 + sll %o5, 3, %o5 ! offset within first cache line + add %o5, $ptbl, $ptbl ! of the pwrtbl + or %g0, 1, %o5 + sll %o5, %o4, $ccr +___ +$code.=<<___ if (!$skip_wr); + wr $ccr, %g0, %ccr +___ +} +sub load_b_pair { +my ($pwrtbl,$B0,$B1)=@_; + +$code.=<<___; + ldx [$pwrtbl+0*32], $B0 + ldx [$pwrtbl+8*32], $B1 + ldx [$pwrtbl+1*32], %o4 + ldx [$pwrtbl+9*32], %o5 + movvs %icc, %o4, $B0 + ldx [$pwrtbl+2*32], %o4 + movvs %icc, %o5, $B1 + ldx [$pwrtbl+10*32],%o5 + move %icc, %o4, $B0 + ldx [$pwrtbl+3*32], %o4 + move %icc, %o5, $B1 + ldx [$pwrtbl+11*32],%o5 + movneg %icc, %o4, $B0 + ldx [$pwrtbl+4*32], %o4 + movneg %icc, %o5, $B1 + ldx [$pwrtbl+12*32],%o5 + movcs %xcc, %o4, $B0 + ldx [$pwrtbl+5*32],%o4 + movcs %xcc, %o5, $B1 + ldx [$pwrtbl+13*32],%o5 + movvs %xcc, %o4, $B0 + ldx [$pwrtbl+6*32], %o4 + movvs %xcc, %o5, $B1 + ldx [$pwrtbl+14*32],%o5 + move %xcc, %o4, $B0 + ldx [$pwrtbl+7*32], %o4 + move %xcc, %o5, $B1 + ldx [$pwrtbl+15*32],%o5 + movneg %xcc, %o4, $B0 + add $pwrtbl,16*32, $pwrtbl + movneg %xcc, %o5, $B1 +___ +} +sub load_b { +my ($pwrtbl,$Bi)=@_; + +$code.=<<___; + ldx [$pwrtbl+0*32], $Bi + ldx [$pwrtbl+1*32], %o4 + ldx [$pwrtbl+2*32], %o5 + movvs %icc, %o4, $Bi + ldx [$pwrtbl+3*32], %o4 + move %icc, %o5, $Bi + ldx [$pwrtbl+4*32], %o5 + movneg %icc, %o4, $Bi + ldx [$pwrtbl+5*32], %o4 + movcs %xcc, %o5, $Bi + ldx [$pwrtbl+6*32], %o5 + movvs %xcc, %o4, $Bi + ldx [$pwrtbl+7*32], %o4 + move %xcc, %o5, $Bi + add $pwrtbl,8*32, $pwrtbl + movneg %xcc, %o4, $Bi +___ +} + +######################################################################## +# int bn_pwr5_mont_t4_$NUM(u64 *tp,const u64 *np,const BN_ULONG *n0, +# const u64 *pwrtbl,int pwr,int stride); +# +sub generate_bn_pwr5_mont_t4() { +my $NUM=shift; +my ($tp,$np,$pwrtbl,$pwr,$sentinel)=map("%g$_",(1..5)); + +$code.=<<___; +.globl bn_pwr5_mont_t4_$NUM +.align 32 +bn_pwr5_mont_t4_$NUM: +#ifdef __arch64__ + mov 0,$sentinel + mov -128,%g4 +#elif defined(SPARCV9_64BIT_STACK) + SPARC_LOAD_ADDRESS_LEAF(OPENSSL_sparcv9cap_P,%g1,%g5) + ld [%g1+0],%g1 ! OPENSSL_sparcv9_P[0] + mov -2047,%g4 + and %g1,SPARCV9_64BIT_STACK,%g1 + movrz %g1,0,%g4 + mov -1,$sentinel + add %g4,-128,%g4 +#else + mov -1,$sentinel + mov -128,%g4 +#endif + sllx $sentinel,32,$sentinel + save %sp,%g4,%sp +#ifndef __arch64__ + save %sp,-128,%sp ! warm it up + save %sp,-128,%sp + save %sp,-128,%sp + save %sp,-128,%sp + save %sp,-128,%sp + save %sp,-128,%sp + restore + restore + restore + restore + restore + restore +#endif + and %sp,1,%g4 + or $sentinel,%fp,%fp + or %g4,$sentinel,$sentinel + + ! copy arguments to global registers + mov %i0,$tp + mov %i1,$np + ld [%i2+0],%f1 ! load *n0 + ld [%i2+4],%f0 + mov %i3,$pwrtbl + srl %i4,%g0,%i4 ! pack last arguments + sllx %i5,32,$pwr + or %i4,$pwr,$pwr + fsrc2 %f0,%f60 +___ + +# load tp[$NUM] ######################################################## +$code.=<<___; + save %sp,-128,%sp; or $sentinel,%fp,%fp +___ +for($i=0; $i<14 && $i<$NUM; $i++) { +$code.=<<___; + ldx [$tp+$i*8],@A[$i] +___ +} +for(; $i<$NUM; $i++) { +$code.=<<___; + ldd [$tp+$i*8],@A[$i] +___ +} +# load np[$NUM] ######################################################## +$code.=<<___; + save %sp,-128,%sp; or $sentinel,%fp,%fp +___ +for($i=0; $i<14 && $i<$NUM; $i++) { +$code.=<<___; + ldx [$np+$i*8],@N[$i] +___ +} +$code.=<<___; + save %sp,-128,%sp; or $sentinel,%fp,%fp +___ +for(; $i<28 && $i<$NUM; $i++) { +$code.=<<___; + ldx [$np+$i*8],@N[$i] +___ +} +$code.=<<___; + save %sp,-128,%sp; or $sentinel,%fp,%fp +___ +for(; $i<$NUM; $i++) { +$code.=<<___; + ldx [$np+$i*8],@N[$i] +___ +} +# load pwrtbl[pwr] ######################################################## +$code.=<<___; + save %sp,-128,%sp; or $sentinel,%fp,%fp + + srlx $pwr, 32, %o4 ! unpack $pwr + srl $pwr, %g0, %o5 + sub %o4, 5, %o4 + mov $pwrtbl, %o7 + sllx %o4, 32, $pwr ! re-pack $pwr + or %o5, $pwr, $pwr + srl %o5, %o4, %o5 +___ + &load_ccr("%o7","%o5","%o4"); +$code.=<<___; + b .Lstride_$NUM + nop +.align 16 +.Lstride_$NUM: +___ +for($i=0; $i<14 && $i<$NUM; $i+=2) { + &load_b_pair("%o7",@B[$i],@B[$i+1]); +} +$code.=<<___; + save %sp,-128,%sp; or $sentinel,%fp,%fp +___ +for(; $i<$NUM; $i+=2) { + &load_b_pair("%i7",@B[$i],@B[$i+1]); +} +$code.=<<___; + srax $pwr, 32, %o4 ! unpack $pwr + srl $pwr, %g0, %o5 + sub %o4, 5, %o4 + mov $pwrtbl, %i7 + sllx %o4, 32, $pwr ! re-pack $pwr + or %o5, $pwr, $pwr + srl %o5, %o4, %o5 +___ + &load_ccr("%i7","%o5","%o4",1); + +# magic ################################################################ +for($i=0; $i<5; $i++) { +$code.=<<___; + .word 0x81b02940+$NUM-1 ! montsqr $NUM-1 + fbu,pn %fcc3,.Labort_$NUM +#ifndef __arch64__ + and %fp,$sentinel,$sentinel + brz,pn $sentinel,.Labort_$NUM +#endif + nop +___ +} +$code.=<<___; + wr %o4, %g0, %ccr + .word 0x81b02920+$NUM-1 ! montmul $NUM-1 + fbu,pn %fcc3,.Labort_$NUM +#ifndef __arch64__ + and %fp,$sentinel,$sentinel + brz,pn $sentinel,.Labort_$NUM +#endif + + srax $pwr, 32, %o4 +#ifdef __arch64__ + brgez %o4,.Lstride_$NUM + restore + restore + restore + restore + restore +#else + brgez %o4,.Lstride_$NUM + restore; and %fp,$sentinel,$sentinel + restore; and %fp,$sentinel,$sentinel + restore; and %fp,$sentinel,$sentinel + restore; and %fp,$sentinel,$sentinel + brz,pn $sentinel,.Labort1_$NUM + restore +#endif +___ + +# save tp[$NUM] ######################################################## +for($i=0; $i<14 && $i<$NUM; $i++) { +$code.=<<___; + movxtod @A[$i],@R[$i] +___ +} +$code.=<<___; +#ifdef __arch64__ + restore +#else + and %fp,$sentinel,$sentinel + restore + and $sentinel,1,%o7 + and %fp,$sentinel,$sentinel + srl %fp,0,%fp ! just in case? + or %o7,$sentinel,$sentinel + brz,a,pn $sentinel,.Ldone_$NUM + mov 0,%i0 ! return failure +#endif +___ +for($i=0; $i<$NUM; $i++) { +$code.=<<___; + std @R[$i],[$tp+$i*8] +___ +} +$code.=<<___; + mov 1,%i0 ! return success +.Ldone_$NUM: + ret + restore + +.Labort_$NUM: + restore + restore + restore + restore + restore +.Labort1_$NUM: + restore + + mov 0,%i0 ! return failure + ret + restore +.type bn_pwr5_mont_t4_$NUM, #function +.size bn_pwr5_mont_t4_$NUM, .-bn_pwr5_mont_t4_$NUM +___ +} + +for ($i=8;$i<=32;$i+=8) { + &generate_bn_pwr5_mont_t4($i); +} + +{ +######################################################################## +# Fall-back subroutines +# +# copy of bn_mul_mont_vis3 adjusted for vectors of 64-bit values +# +($n0,$m0,$m1,$lo0,$hi0, $lo1,$hi1,$aj,$alo,$nj,$nlo,$tj)= + (map("%g$_",(1..5)),map("%o$_",(0..5,7))); + +# int bn_mul_mont( +$rp="%o0"; # u64 *rp, +$ap="%o1"; # const u64 *ap, +$bp="%o2"; # const u64 *bp, +$np="%o3"; # const u64 *np, +$n0p="%o4"; # const BN_ULONG *n0, +$num="%o5"; # int num); # caller ensures that num is >=3 +$code.=<<___; +.globl bn_mul_mont_t4 +.align 32 +bn_mul_mont_t4: + add %sp, STACK_BIAS, %g4 ! real top of stack + sll $num, 3, $num ! size in bytes + add $num, 63, %g1 + andn %g1, 63, %g1 ! buffer size rounded up to 64 bytes + sub %g4, %g1, %g1 + andn %g1, 63, %g1 ! align at 64 byte + sub %g1, STACK_FRAME, %g1 ! new top of stack + sub %g1, %g4, %g1 + + save %sp, %g1, %sp +___ +# +-------------------------------+<----- %sp +# . . +# +-------------------------------+<----- aligned at 64 bytes +# | __int64 tmp[0] | +# +-------------------------------+ +# . . +# . . +# +-------------------------------+<----- aligned at 64 bytes +# . . +($rp,$ap,$bp,$np,$n0p,$num)=map("%i$_",(0..5)); +($t0,$t1,$t2,$t3,$cnt,$tp,$bufsz)=map("%l$_",(0..7)); +($ovf,$i)=($t0,$t1); +$code.=<<___; + ld [$n0p+0], $t0 ! pull n0[0..1] value + ld [$n0p+4], $t1 + add %sp, STACK_BIAS+STACK_FRAME, $tp + ldx [$bp+0], $m0 ! m0=bp[0] + sllx $t1, 32, $n0 + add $bp, 8, $bp + or $t0, $n0, $n0 + + ldx [$ap+0], $aj ! ap[0] + + mulx $aj, $m0, $lo0 ! ap[0]*bp[0] + umulxhi $aj, $m0, $hi0 + + ldx [$ap+8], $aj ! ap[1] + add $ap, 16, $ap + ldx [$np+0], $nj ! np[0] + + mulx $lo0, $n0, $m1 ! "tp[0]"*n0 + + mulx $aj, $m0, $alo ! ap[1]*bp[0] + umulxhi $aj, $m0, $aj ! ahi=aj + + mulx $nj, $m1, $lo1 ! np[0]*m1 + umulxhi $nj, $m1, $hi1 + + ldx [$np+8], $nj ! np[1] + + addcc $lo0, $lo1, $lo1 + add $np, 16, $np + addxc %g0, $hi1, $hi1 + + mulx $nj, $m1, $nlo ! np[1]*m1 + umulxhi $nj, $m1, $nj ! nhi=nj + + ba .L1st + sub $num, 24, $cnt ! cnt=num-3 + +.align 16 +.L1st: + addcc $alo, $hi0, $lo0 + addxc $aj, %g0, $hi0 + + ldx [$ap+0], $aj ! ap[j] + addcc $nlo, $hi1, $lo1 + add $ap, 8, $ap + addxc $nj, %g0, $hi1 ! nhi=nj + + ldx [$np+0], $nj ! np[j] + mulx $aj, $m0, $alo ! ap[j]*bp[0] + add $np, 8, $np + umulxhi $aj, $m0, $aj ! ahi=aj + + mulx $nj, $m1, $nlo ! np[j]*m1 + addcc $lo0, $lo1, $lo1 ! np[j]*m1+ap[j]*bp[0] + umulxhi $nj, $m1, $nj ! nhi=nj + addxc %g0, $hi1, $hi1 + stxa $lo1, [$tp]0xe2 ! tp[j-1] + add $tp, 8, $tp ! tp++ + + brnz,pt $cnt, .L1st + sub $cnt, 8, $cnt ! j-- +!.L1st + addcc $alo, $hi0, $lo0 + addxc $aj, %g0, $hi0 ! ahi=aj + + addcc $nlo, $hi1, $lo1 + addxc $nj, %g0, $hi1 + addcc $lo0, $lo1, $lo1 ! np[j]*m1+ap[j]*bp[0] + addxc %g0, $hi1, $hi1 + stxa $lo1, [$tp]0xe2 ! tp[j-1] + add $tp, 8, $tp + + addcc $hi0, $hi1, $hi1 + addxc %g0, %g0, $ovf ! upmost overflow bit + stxa $hi1, [$tp]0xe2 + add $tp, 8, $tp + + ba .Louter + sub $num, 16, $i ! i=num-2 + +.align 16 +.Louter: + ldx [$bp+0], $m0 ! m0=bp[i] + add $bp, 8, $bp + + sub $ap, $num, $ap ! rewind + sub $np, $num, $np + sub $tp, $num, $tp + + ldx [$ap+0], $aj ! ap[0] + ldx [$np+0], $nj ! np[0] + + mulx $aj, $m0, $lo0 ! ap[0]*bp[i] + ldx [$tp], $tj ! tp[0] + umulxhi $aj, $m0, $hi0 + ldx [$ap+8], $aj ! ap[1] + addcc $lo0, $tj, $lo0 ! ap[0]*bp[i]+tp[0] + mulx $aj, $m0, $alo ! ap[1]*bp[i] + addxc %g0, $hi0, $hi0 + mulx $lo0, $n0, $m1 ! tp[0]*n0 + umulxhi $aj, $m0, $aj ! ahi=aj + mulx $nj, $m1, $lo1 ! np[0]*m1 + add $ap, 16, $ap + umulxhi $nj, $m1, $hi1 + ldx [$np+8], $nj ! np[1] + add $np, 16, $np + addcc $lo1, $lo0, $lo1 + mulx $nj, $m1, $nlo ! np[1]*m1 + addxc %g0, $hi1, $hi1 + umulxhi $nj, $m1, $nj ! nhi=nj + + ba .Linner + sub $num, 24, $cnt ! cnt=num-3 +.align 16 +.Linner: + addcc $alo, $hi0, $lo0 + ldx [$tp+8], $tj ! tp[j] + addxc $aj, %g0, $hi0 ! ahi=aj + ldx [$ap+0], $aj ! ap[j] + add $ap, 8, $ap + addcc $nlo, $hi1, $lo1 + mulx $aj, $m0, $alo ! ap[j]*bp[i] + addxc $nj, %g0, $hi1 ! nhi=nj + ldx [$np+0], $nj ! np[j] + add $np, 8, $np + umulxhi $aj, $m0, $aj ! ahi=aj + addcc $lo0, $tj, $lo0 ! ap[j]*bp[i]+tp[j] + mulx $nj, $m1, $nlo ! np[j]*m1 + addxc %g0, $hi0, $hi0 + umulxhi $nj, $m1, $nj ! nhi=nj + addcc $lo1, $lo0, $lo1 ! np[j]*m1+ap[j]*bp[i]+tp[j] + addxc %g0, $hi1, $hi1 + stx $lo1, [$tp] ! tp[j-1] + add $tp, 8, $tp + brnz,pt $cnt, .Linner + sub $cnt, 8, $cnt +!.Linner + ldx [$tp+8], $tj ! tp[j] + addcc $alo, $hi0, $lo0 + addxc $aj, %g0, $hi0 ! ahi=aj + addcc $lo0, $tj, $lo0 ! ap[j]*bp[i]+tp[j] + addxc %g0, $hi0, $hi0 + + addcc $nlo, $hi1, $lo1 + addxc $nj, %g0, $hi1 ! nhi=nj + addcc $lo1, $lo0, $lo1 ! np[j]*m1+ap[j]*bp[i]+tp[j] + addxc %g0, $hi1, $hi1 + stx $lo1, [$tp] ! tp[j-1] + + subcc %g0, $ovf, %g0 ! move upmost overflow to CCR.xcc + addxccc $hi1, $hi0, $hi1 + addxc %g0, %g0, $ovf + stx $hi1, [$tp+8] + add $tp, 16, $tp + + brnz,pt $i, .Louter + sub $i, 8, $i + + sub $ap, $num, $ap ! rewind + sub $np, $num, $np + sub $tp, $num, $tp + ba .Lsub + subcc $num, 8, $cnt ! cnt=num-1 and clear CCR.xcc + +.align 16 +.Lsub: + ldx [$tp], $tj + add $tp, 8, $tp + ldx [$np+0], $nj + add $np, 8, $np + subccc $tj, $nj, $t2 ! tp[j]-np[j] + srlx $tj, 32, $tj + srlx $nj, 32, $nj + subccc $tj, $nj, $t3 + add $rp, 8, $rp + st $t2, [$rp-4] ! reverse order + st $t3, [$rp-8] + brnz,pt $cnt, .Lsub + sub $cnt, 8, $cnt + + sub $np, $num, $np ! rewind + sub $tp, $num, $tp + sub $rp, $num, $rp + + subccc $ovf, %g0, $ovf ! handle upmost overflow bit + ba .Lcopy + sub $num, 8, $cnt + +.align 16 +.Lcopy: ! conditional copy + ldx [$tp], $tj + ldx [$rp+0], $t2 + stx %g0, [$tp] ! zap + add $tp, 8, $tp + movcs %icc, $tj, $t2 + stx $t2, [$rp+0] + add $rp, 8, $rp + brnz $cnt, .Lcopy + sub $cnt, 8, $cnt + + mov 1, %o0 + ret + restore +.type bn_mul_mont_t4, #function +.size bn_mul_mont_t4, .-bn_mul_mont_t4 +___ + +# int bn_mul_mont_gather5( +$rp="%o0"; # u64 *rp, +$ap="%o1"; # const u64 *ap, +$bp="%o2"; # const u64 *pwrtbl, +$np="%o3"; # const u64 *np, +$n0p="%o4"; # const BN_ULONG *n0, +$num="%o5"; # int num, # caller ensures that num is >=3 + # int power); +$code.=<<___; +.globl bn_mul_mont_gather5_t4 +.align 32 +bn_mul_mont_gather5_t4: + add %sp, STACK_BIAS, %g4 ! real top of stack + sll $num, 3, $num ! size in bytes + add $num, 63, %g1 + andn %g1, 63, %g1 ! buffer size rounded up to 64 bytes + sub %g4, %g1, %g1 + andn %g1, 63, %g1 ! align at 64 byte + sub %g1, STACK_FRAME, %g1 ! new top of stack + sub %g1, %g4, %g1 + LDPTR [%sp+STACK_7thARG], %g4 ! load power, 7th argument + + save %sp, %g1, %sp +___ +# +-------------------------------+<----- %sp +# . . +# +-------------------------------+<----- aligned at 64 bytes +# | __int64 tmp[0] | +# +-------------------------------+ +# . . +# . . +# +-------------------------------+<----- aligned at 64 bytes +# . . +($rp,$ap,$bp,$np,$n0p,$num)=map("%i$_",(0..5)); +($t0,$t1,$t2,$t3,$cnt,$tp,$bufsz,$ccr)=map("%l$_",(0..7)); +($ovf,$i)=($t0,$t1); + &load_ccr($bp,"%g4",$ccr); + &load_b($bp,$m0,"%o7"); # m0=bp[0] + +$code.=<<___; + ld [$n0p+0], $t0 ! pull n0[0..1] value + ld [$n0p+4], $t1 + add %sp, STACK_BIAS+STACK_FRAME, $tp + sllx $t1, 32, $n0 + or $t0, $n0, $n0 + + ldx [$ap+0], $aj ! ap[0] + + mulx $aj, $m0, $lo0 ! ap[0]*bp[0] + umulxhi $aj, $m0, $hi0 + + ldx [$ap+8], $aj ! ap[1] + add $ap, 16, $ap + ldx [$np+0], $nj ! np[0] + + mulx $lo0, $n0, $m1 ! "tp[0]"*n0 + + mulx $aj, $m0, $alo ! ap[1]*bp[0] + umulxhi $aj, $m0, $aj ! ahi=aj + + mulx $nj, $m1, $lo1 ! np[0]*m1 + umulxhi $nj, $m1, $hi1 + + ldx [$np+8], $nj ! np[1] + + addcc $lo0, $lo1, $lo1 + add $np, 16, $np + addxc %g0, $hi1, $hi1 + + mulx $nj, $m1, $nlo ! np[1]*m1 + umulxhi $nj, $m1, $nj ! nhi=nj + + ba .L1st_g5 + sub $num, 24, $cnt ! cnt=num-3 + +.align 16 +.L1st_g5: + addcc $alo, $hi0, $lo0 + addxc $aj, %g0, $hi0 + + ldx [$ap+0], $aj ! ap[j] + addcc $nlo, $hi1, $lo1 + add $ap, 8, $ap + addxc $nj, %g0, $hi1 ! nhi=nj + + ldx [$np+0], $nj ! np[j] + mulx $aj, $m0, $alo ! ap[j]*bp[0] + add $np, 8, $np + umulxhi $aj, $m0, $aj ! ahi=aj + + mulx $nj, $m1, $nlo ! np[j]*m1 + addcc $lo0, $lo1, $lo1 ! np[j]*m1+ap[j]*bp[0] + umulxhi $nj, $m1, $nj ! nhi=nj + addxc %g0, $hi1, $hi1 + stxa $lo1, [$tp]0xe2 ! tp[j-1] + add $tp, 8, $tp ! tp++ + + brnz,pt $cnt, .L1st_g5 + sub $cnt, 8, $cnt ! j-- +!.L1st_g5 + addcc $alo, $hi0, $lo0 + addxc $aj, %g0, $hi0 ! ahi=aj + + addcc $nlo, $hi1, $lo1 + addxc $nj, %g0, $hi1 + addcc $lo0, $lo1, $lo1 ! np[j]*m1+ap[j]*bp[0] + addxc %g0, $hi1, $hi1 + stxa $lo1, [$tp]0xe2 ! tp[j-1] + add $tp, 8, $tp + + addcc $hi0, $hi1, $hi1 + addxc %g0, %g0, $ovf ! upmost overflow bit + stxa $hi1, [$tp]0xe2 + add $tp, 8, $tp + + ba .Louter_g5 + sub $num, 16, $i ! i=num-2 + +.align 16 +.Louter_g5: + wr $ccr, %g0, %ccr +___ + &load_b($bp,$m0); # m0=bp[i] +$code.=<<___; + sub $ap, $num, $ap ! rewind + sub $np, $num, $np + sub $tp, $num, $tp + + ldx [$ap+0], $aj ! ap[0] + ldx [$np+0], $nj ! np[0] + + mulx $aj, $m0, $lo0 ! ap[0]*bp[i] + ldx [$tp], $tj ! tp[0] + umulxhi $aj, $m0, $hi0 + ldx [$ap+8], $aj ! ap[1] + addcc $lo0, $tj, $lo0 ! ap[0]*bp[i]+tp[0] + mulx $aj, $m0, $alo ! ap[1]*bp[i] + addxc %g0, $hi0, $hi0 + mulx $lo0, $n0, $m1 ! tp[0]*n0 + umulxhi $aj, $m0, $aj ! ahi=aj + mulx $nj, $m1, $lo1 ! np[0]*m1 + add $ap, 16, $ap + umulxhi $nj, $m1, $hi1 + ldx [$np+8], $nj ! np[1] + add $np, 16, $np + addcc $lo1, $lo0, $lo1 + mulx $nj, $m1, $nlo ! np[1]*m1 + addxc %g0, $hi1, $hi1 + umulxhi $nj, $m1, $nj ! nhi=nj + + ba .Linner_g5 + sub $num, 24, $cnt ! cnt=num-3 +.align 16 +.Linner_g5: + addcc $alo, $hi0, $lo0 + ldx [$tp+8], $tj ! tp[j] + addxc $aj, %g0, $hi0 ! ahi=aj + ldx [$ap+0], $aj ! ap[j] + add $ap, 8, $ap + addcc $nlo, $hi1, $lo1 + mulx $aj, $m0, $alo ! ap[j]*bp[i] + addxc $nj, %g0, $hi1 ! nhi=nj + ldx [$np+0], $nj ! np[j] + add $np, 8, $np + umulxhi $aj, $m0, $aj ! ahi=aj + addcc $lo0, $tj, $lo0 ! ap[j]*bp[i]+tp[j] + mulx $nj, $m1, $nlo ! np[j]*m1 + addxc %g0, $hi0, $hi0 + umulxhi $nj, $m1, $nj ! nhi=nj + addcc $lo1, $lo0, $lo1 ! np[j]*m1+ap[j]*bp[i]+tp[j] + addxc %g0, $hi1, $hi1 + stx $lo1, [$tp] ! tp[j-1] + add $tp, 8, $tp + brnz,pt $cnt, .Linner_g5 + sub $cnt, 8, $cnt +!.Linner_g5 + ldx [$tp+8], $tj ! tp[j] + addcc $alo, $hi0, $lo0 + addxc $aj, %g0, $hi0 ! ahi=aj + addcc $lo0, $tj, $lo0 ! ap[j]*bp[i]+tp[j] + addxc %g0, $hi0, $hi0 + + addcc $nlo, $hi1, $lo1 + addxc $nj, %g0, $hi1 ! nhi=nj + addcc $lo1, $lo0, $lo1 ! np[j]*m1+ap[j]*bp[i]+tp[j] + addxc %g0, $hi1, $hi1 + stx $lo1, [$tp] ! tp[j-1] + + subcc %g0, $ovf, %g0 ! move upmost overflow to CCR.xcc + addxccc $hi1, $hi0, $hi1 + addxc %g0, %g0, $ovf + stx $hi1, [$tp+8] + add $tp, 16, $tp + + brnz,pt $i, .Louter_g5 + sub $i, 8, $i + + sub $ap, $num, $ap ! rewind + sub $np, $num, $np + sub $tp, $num, $tp + ba .Lsub_g5 + subcc $num, 8, $cnt ! cnt=num-1 and clear CCR.xcc + +.align 16 +.Lsub_g5: + ldx [$tp], $tj + add $tp, 8, $tp + ldx [$np+0], $nj + add $np, 8, $np + subccc $tj, $nj, $t2 ! tp[j]-np[j] + srlx $tj, 32, $tj + srlx $nj, 32, $nj + subccc $tj, $nj, $t3 + add $rp, 8, $rp + st $t2, [$rp-4] ! reverse order + st $t3, [$rp-8] + brnz,pt $cnt, .Lsub_g5 + sub $cnt, 8, $cnt + + sub $np, $num, $np ! rewind + sub $tp, $num, $tp + sub $rp, $num, $rp + + subccc $ovf, %g0, $ovf ! handle upmost overflow bit + ba .Lcopy_g5 + sub $num, 8, $cnt + +.align 16 +.Lcopy_g5: ! conditional copy + ldx [$tp], $tj + ldx [$rp+0], $t2 + stx %g0, [$tp] ! zap + add $tp, 8, $tp + movcs %icc, $tj, $t2 + stx $t2, [$rp+0] + add $rp, 8, $rp + brnz $cnt, .Lcopy_g5 + sub $cnt, 8, $cnt + + mov 1, %o0 + ret + restore +.type bn_mul_mont_gather5_t4, #function +.size bn_mul_mont_gather5_t4, .-bn_mul_mont_gather5_t4 +___ +} + +$code.=<<___; +.globl bn_flip_t4 +.align 32 +bn_flip_t4: +.Loop_flip: + ld [%o1+0], %o4 + sub %o2, 1, %o2 + ld [%o1+4], %o5 + add %o1, 8, %o1 + st %o5, [%o0+0] + st %o4, [%o0+4] + brnz %o2, .Loop_flip + add %o0, 8, %o0 + retl + nop +.type bn_flip_t4, #function +.size bn_flip_t4, .-bn_flip_t4 + +.globl bn_flip_n_scatter5_t4 +.align 32 +bn_flip_n_scatter5_t4: + sll %o3, 3, %o3 + srl %o1, 1, %o1 + add %o3, %o2, %o2 ! &pwrtbl[pwr] + sub %o1, 1, %o1 +.Loop_flip_n_scatter5: + ld [%o0+0], %o4 ! inp[i] + ld [%o0+4], %o5 + add %o0, 8, %o0 + sllx %o5, 32, %o5 + or %o4, %o5, %o5 + stx %o5, [%o2] + add %o2, 32*8, %o2 + brnz %o1, .Loop_flip_n_scatter5 + sub %o1, 1, %o1 + retl + nop +.type bn_flip_n_scatter5_t4, #function +.size bn_flip_n_scatter5_t4, .-bn_flip_n_scatter5_t4 + +.globl bn_gather5_t4 +.align 32 +bn_gather5_t4: +___ + &load_ccr("%o2","%o3","%g1"); +$code.=<<___; + sub %o1, 1, %o1 +.Loop_gather5: +___ + &load_b("%o2","%g1"); +$code.=<<___; + stx %g1, [%o0] + add %o0, 8, %o0 + brnz %o1, .Loop_gather5 + sub %o1, 1, %o1 + + retl + nop +.type bn_gather5_t4, #function +.size bn_gather5_t4, .-bn_gather5_t4 + +.asciz "Montgomery Multiplication for SPARC T4, David S. Miller, Andy Polyakov" +.align 4 +___ + +&emit_assembler(); + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/sparcv8.S b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/sparcv8.S new file mode 100644 index 000000000..75d72eb92 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/sparcv8.S @@ -0,0 +1,1458 @@ +.ident "sparcv8.s, Version 1.4" +.ident "SPARC v8 ISA artwork by Andy Polyakov " + +/* + * ==================================================================== + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + * ==================================================================== + */ + +/* + * This is my modest contribution to OpenSSL project (see + * http://www.openssl.org/ for more information about it) and is + * a drop-in SuperSPARC ISA replacement for crypto/bn/bn_asm.c + * module. For updates see http://fy.chalmers.se/~appro/hpe/. + * + * See bn_asm.sparc.v8plus.S for more details. + */ + +/* + * Revision history. + * + * 1.1 - new loop unrolling model(*); + * 1.2 - made gas friendly; + * 1.3 - fixed problem with /usr/ccs/lib/cpp; + * 1.4 - some retunes; + * + * (*) see bn_asm.sparc.v8plus.S for details + */ + +.section ".text",#alloc,#execinstr +.file "bn_asm.sparc.v8.S" + +.align 32 + +.global bn_mul_add_words +/* + * BN_ULONG bn_mul_add_words(rp,ap,num,w) + * BN_ULONG *rp,*ap; + * int num; + * BN_ULONG w; + */ +bn_mul_add_words: + cmp %o2,0 + bg,a .L_bn_mul_add_words_proceed + ld [%o1],%g2 + retl + clr %o0 + +.L_bn_mul_add_words_proceed: + andcc %o2,-4,%g0 + bz .L_bn_mul_add_words_tail + clr %o5 + +.L_bn_mul_add_words_loop: + ld [%o0],%o4 + ld [%o1+4],%g3 + umul %o3,%g2,%g2 + rd %y,%g1 + addcc %o4,%o5,%o4 + addx %g1,0,%g1 + addcc %o4,%g2,%o4 + st %o4,[%o0] + addx %g1,0,%o5 + + ld [%o0+4],%o4 + ld [%o1+8],%g2 + umul %o3,%g3,%g3 + dec 4,%o2 + rd %y,%g1 + addcc %o4,%o5,%o4 + addx %g1,0,%g1 + addcc %o4,%g3,%o4 + st %o4,[%o0+4] + addx %g1,0,%o5 + + ld [%o0+8],%o4 + ld [%o1+12],%g3 + umul %o3,%g2,%g2 + inc 16,%o1 + rd %y,%g1 + addcc %o4,%o5,%o4 + addx %g1,0,%g1 + addcc %o4,%g2,%o4 + st %o4,[%o0+8] + addx %g1,0,%o5 + + ld [%o0+12],%o4 + umul %o3,%g3,%g3 + inc 16,%o0 + rd %y,%g1 + addcc %o4,%o5,%o4 + addx %g1,0,%g1 + addcc %o4,%g3,%o4 + st %o4,[%o0-4] + addx %g1,0,%o5 + andcc %o2,-4,%g0 + bnz,a .L_bn_mul_add_words_loop + ld [%o1],%g2 + + tst %o2 + bnz,a .L_bn_mul_add_words_tail + ld [%o1],%g2 +.L_bn_mul_add_words_return: + retl + mov %o5,%o0 + nop + +.L_bn_mul_add_words_tail: + ld [%o0],%o4 + umul %o3,%g2,%g2 + addcc %o4,%o5,%o4 + rd %y,%g1 + addx %g1,0,%g1 + addcc %o4,%g2,%o4 + addx %g1,0,%o5 + deccc %o2 + bz .L_bn_mul_add_words_return + st %o4,[%o0] + + ld [%o1+4],%g2 + ld [%o0+4],%o4 + umul %o3,%g2,%g2 + rd %y,%g1 + addcc %o4,%o5,%o4 + addx %g1,0,%g1 + addcc %o4,%g2,%o4 + addx %g1,0,%o5 + deccc %o2 + bz .L_bn_mul_add_words_return + st %o4,[%o0+4] + + ld [%o1+8],%g2 + ld [%o0+8],%o4 + umul %o3,%g2,%g2 + rd %y,%g1 + addcc %o4,%o5,%o4 + addx %g1,0,%g1 + addcc %o4,%g2,%o4 + st %o4,[%o0+8] + retl + addx %g1,0,%o0 + +.type bn_mul_add_words,#function +.size bn_mul_add_words,(.-bn_mul_add_words) + +.align 32 + +.global bn_mul_words +/* + * BN_ULONG bn_mul_words(rp,ap,num,w) + * BN_ULONG *rp,*ap; + * int num; + * BN_ULONG w; + */ +bn_mul_words: + cmp %o2,0 + bg,a .L_bn_mul_words_proceed + ld [%o1],%g2 + retl + clr %o0 + +.L_bn_mul_words_proceed: + andcc %o2,-4,%g0 + bz .L_bn_mul_words_tail + clr %o5 + +.L_bn_mul_words_loop: + ld [%o1+4],%g3 + umul %o3,%g2,%g2 + addcc %g2,%o5,%g2 + rd %y,%g1 + addx %g1,0,%o5 + st %g2,[%o0] + + ld [%o1+8],%g2 + umul %o3,%g3,%g3 + addcc %g3,%o5,%g3 + rd %y,%g1 + dec 4,%o2 + addx %g1,0,%o5 + st %g3,[%o0+4] + + ld [%o1+12],%g3 + umul %o3,%g2,%g2 + addcc %g2,%o5,%g2 + rd %y,%g1 + inc 16,%o1 + st %g2,[%o0+8] + addx %g1,0,%o5 + + umul %o3,%g3,%g3 + addcc %g3,%o5,%g3 + rd %y,%g1 + inc 16,%o0 + addx %g1,0,%o5 + st %g3,[%o0-4] + andcc %o2,-4,%g0 + nop + bnz,a .L_bn_mul_words_loop + ld [%o1],%g2 + + tst %o2 + bnz,a .L_bn_mul_words_tail + ld [%o1],%g2 +.L_bn_mul_words_return: + retl + mov %o5,%o0 + nop + +.L_bn_mul_words_tail: + umul %o3,%g2,%g2 + addcc %g2,%o5,%g2 + rd %y,%g1 + addx %g1,0,%o5 + deccc %o2 + bz .L_bn_mul_words_return + st %g2,[%o0] + nop + + ld [%o1+4],%g2 + umul %o3,%g2,%g2 + addcc %g2,%o5,%g2 + rd %y,%g1 + addx %g1,0,%o5 + deccc %o2 + bz .L_bn_mul_words_return + st %g2,[%o0+4] + + ld [%o1+8],%g2 + umul %o3,%g2,%g2 + addcc %g2,%o5,%g2 + rd %y,%g1 + st %g2,[%o0+8] + retl + addx %g1,0,%o0 + +.type bn_mul_words,#function +.size bn_mul_words,(.-bn_mul_words) + +.align 32 +.global bn_sqr_words +/* + * void bn_sqr_words(r,a,n) + * BN_ULONG *r,*a; + * int n; + */ +bn_sqr_words: + cmp %o2,0 + bg,a .L_bn_sqr_words_proceed + ld [%o1],%g2 + retl + clr %o0 + +.L_bn_sqr_words_proceed: + andcc %o2,-4,%g0 + bz .L_bn_sqr_words_tail + clr %o5 + +.L_bn_sqr_words_loop: + ld [%o1+4],%g3 + umul %g2,%g2,%o4 + st %o4,[%o0] + rd %y,%o5 + st %o5,[%o0+4] + + ld [%o1+8],%g2 + umul %g3,%g3,%o4 + dec 4,%o2 + st %o4,[%o0+8] + rd %y,%o5 + st %o5,[%o0+12] + nop + + ld [%o1+12],%g3 + umul %g2,%g2,%o4 + st %o4,[%o0+16] + rd %y,%o5 + inc 16,%o1 + st %o5,[%o0+20] + + umul %g3,%g3,%o4 + inc 32,%o0 + st %o4,[%o0-8] + rd %y,%o5 + st %o5,[%o0-4] + andcc %o2,-4,%g2 + bnz,a .L_bn_sqr_words_loop + ld [%o1],%g2 + + tst %o2 + nop + bnz,a .L_bn_sqr_words_tail + ld [%o1],%g2 +.L_bn_sqr_words_return: + retl + clr %o0 + +.L_bn_sqr_words_tail: + umul %g2,%g2,%o4 + st %o4,[%o0] + deccc %o2 + rd %y,%o5 + bz .L_bn_sqr_words_return + st %o5,[%o0+4] + + ld [%o1+4],%g2 + umul %g2,%g2,%o4 + st %o4,[%o0+8] + deccc %o2 + rd %y,%o5 + nop + bz .L_bn_sqr_words_return + st %o5,[%o0+12] + + ld [%o1+8],%g2 + umul %g2,%g2,%o4 + st %o4,[%o0+16] + rd %y,%o5 + st %o5,[%o0+20] + retl + clr %o0 + +.type bn_sqr_words,#function +.size bn_sqr_words,(.-bn_sqr_words) + +.align 32 + +.global bn_div_words +/* + * BN_ULONG bn_div_words(h,l,d) + * BN_ULONG h,l,d; + */ +bn_div_words: + wr %o0,%y + udiv %o1,%o2,%o0 + retl + nop + +.type bn_div_words,#function +.size bn_div_words,(.-bn_div_words) + +.align 32 + +.global bn_add_words +/* + * BN_ULONG bn_add_words(rp,ap,bp,n) + * BN_ULONG *rp,*ap,*bp; + * int n; + */ +bn_add_words: + cmp %o3,0 + bg,a .L_bn_add_words_proceed + ld [%o1],%o4 + retl + clr %o0 + +.L_bn_add_words_proceed: + andcc %o3,-4,%g0 + bz .L_bn_add_words_tail + clr %g1 + ba .L_bn_add_words_warn_loop + addcc %g0,0,%g0 ! clear carry flag + +.L_bn_add_words_loop: + ld [%o1],%o4 +.L_bn_add_words_warn_loop: + ld [%o2],%o5 + ld [%o1+4],%g3 + ld [%o2+4],%g4 + dec 4,%o3 + addxcc %o5,%o4,%o5 + st %o5,[%o0] + + ld [%o1+8],%o4 + ld [%o2+8],%o5 + inc 16,%o1 + addxcc %g3,%g4,%g3 + st %g3,[%o0+4] + + ld [%o1-4],%g3 + ld [%o2+12],%g4 + inc 16,%o2 + addxcc %o5,%o4,%o5 + st %o5,[%o0+8] + + inc 16,%o0 + addxcc %g3,%g4,%g3 + st %g3,[%o0-4] + addx %g0,0,%g1 + andcc %o3,-4,%g0 + bnz,a .L_bn_add_words_loop + addcc %g1,-1,%g0 + + tst %o3 + bnz,a .L_bn_add_words_tail + ld [%o1],%o4 +.L_bn_add_words_return: + retl + mov %g1,%o0 + +.L_bn_add_words_tail: + addcc %g1,-1,%g0 + ld [%o2],%o5 + addxcc %o5,%o4,%o5 + addx %g0,0,%g1 + deccc %o3 + bz .L_bn_add_words_return + st %o5,[%o0] + + ld [%o1+4],%o4 + addcc %g1,-1,%g0 + ld [%o2+4],%o5 + addxcc %o5,%o4,%o5 + addx %g0,0,%g1 + deccc %o3 + bz .L_bn_add_words_return + st %o5,[%o0+4] + + ld [%o1+8],%o4 + addcc %g1,-1,%g0 + ld [%o2+8],%o5 + addxcc %o5,%o4,%o5 + st %o5,[%o0+8] + retl + addx %g0,0,%o0 + +.type bn_add_words,#function +.size bn_add_words,(.-bn_add_words) + +.align 32 + +.global bn_sub_words +/* + * BN_ULONG bn_sub_words(rp,ap,bp,n) + * BN_ULONG *rp,*ap,*bp; + * int n; + */ +bn_sub_words: + cmp %o3,0 + bg,a .L_bn_sub_words_proceed + ld [%o1],%o4 + retl + clr %o0 + +.L_bn_sub_words_proceed: + andcc %o3,-4,%g0 + bz .L_bn_sub_words_tail + clr %g1 + ba .L_bn_sub_words_warm_loop + addcc %g0,0,%g0 ! clear carry flag + +.L_bn_sub_words_loop: + ld [%o1],%o4 +.L_bn_sub_words_warm_loop: + ld [%o2],%o5 + ld [%o1+4],%g3 + ld [%o2+4],%g4 + dec 4,%o3 + subxcc %o4,%o5,%o5 + st %o5,[%o0] + + ld [%o1+8],%o4 + ld [%o2+8],%o5 + inc 16,%o1 + subxcc %g3,%g4,%g4 + st %g4,[%o0+4] + + ld [%o1-4],%g3 + ld [%o2+12],%g4 + inc 16,%o2 + subxcc %o4,%o5,%o5 + st %o5,[%o0+8] + + inc 16,%o0 + subxcc %g3,%g4,%g4 + st %g4,[%o0-4] + addx %g0,0,%g1 + andcc %o3,-4,%g0 + bnz,a .L_bn_sub_words_loop + addcc %g1,-1,%g0 + + tst %o3 + nop + bnz,a .L_bn_sub_words_tail + ld [%o1],%o4 +.L_bn_sub_words_return: + retl + mov %g1,%o0 + +.L_bn_sub_words_tail: + addcc %g1,-1,%g0 + ld [%o2],%o5 + subxcc %o4,%o5,%o5 + addx %g0,0,%g1 + deccc %o3 + bz .L_bn_sub_words_return + st %o5,[%o0] + nop + + ld [%o1+4],%o4 + addcc %g1,-1,%g0 + ld [%o2+4],%o5 + subxcc %o4,%o5,%o5 + addx %g0,0,%g1 + deccc %o3 + bz .L_bn_sub_words_return + st %o5,[%o0+4] + + ld [%o1+8],%o4 + addcc %g1,-1,%g0 + ld [%o2+8],%o5 + subxcc %o4,%o5,%o5 + st %o5,[%o0+8] + retl + addx %g0,0,%o0 + +.type bn_sub_words,#function +.size bn_sub_words,(.-bn_sub_words) + +#define FRAME_SIZE -96 + +/* + * Here is register usage map for *all* routines below. + */ +#define t_1 %o0 +#define t_2 %o1 +#define c_1 %o2 +#define c_2 %o3 +#define c_3 %o4 + +#define ap(I) [%i1+4*I] +#define bp(I) [%i2+4*I] +#define rp(I) [%i0+4*I] + +#define a_0 %l0 +#define a_1 %l1 +#define a_2 %l2 +#define a_3 %l3 +#define a_4 %l4 +#define a_5 %l5 +#define a_6 %l6 +#define a_7 %l7 + +#define b_0 %i3 +#define b_1 %i4 +#define b_2 %i5 +#define b_3 %o5 +#define b_4 %g1 +#define b_5 %g2 +#define b_6 %g3 +#define b_7 %g4 + +.align 32 +.global bn_mul_comba8 +/* + * void bn_mul_comba8(r,a,b) + * BN_ULONG *r,*a,*b; + */ +bn_mul_comba8: + save %sp,FRAME_SIZE,%sp + ld ap(0),a_0 + ld bp(0),b_0 + umul a_0,b_0,c_1 !=!mul_add_c(a[0],b[0],c1,c2,c3); + ld bp(1),b_1 + rd %y,c_2 + st c_1,rp(0) !r[0]=c1; + + umul a_0,b_1,t_1 !=!mul_add_c(a[0],b[1],c2,c3,c1); + ld ap(1),a_1 + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc %g0,t_2,c_3 != + addx %g0,%g0,c_1 + ld ap(2),a_2 + umul a_1,b_0,t_1 !mul_add_c(a[1],b[0],c2,c3,c1); + addcc c_2,t_1,c_2 != + rd %y,t_2 + addxcc c_3,t_2,c_3 + st c_2,rp(1) !r[1]=c2; + addx c_1,%g0,c_1 != + + umul a_2,b_0,t_1 !mul_add_c(a[2],b[0],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 != + addx %g0,%g0,c_2 + ld bp(2),b_2 + umul a_1,b_1,t_1 !mul_add_c(a[1],b[1],c3,c1,c2); + addcc c_3,t_1,c_3 != + rd %y,t_2 + addxcc c_1,t_2,c_1 + ld bp(3),b_3 + addx c_2,%g0,c_2 != + umul a_0,b_2,t_1 !mul_add_c(a[0],b[2],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 != + addx c_2,%g0,c_2 + st c_3,rp(2) !r[2]=c3; + + umul a_0,b_3,t_1 !mul_add_c(a[0],b[3],c1,c2,c3); + addcc c_1,t_1,c_1 != + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx %g0,%g0,c_3 + umul a_1,b_2,t_1 !=!mul_add_c(a[1],b[2],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 != + ld ap(3),a_3 + umul a_2,b_1,t_1 !mul_add_c(a[2],b[1],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 != + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 + ld ap(4),a_4 + umul a_3,b_0,t_1 !mul_add_c(a[3],b[0],c1,c2,c3);!= + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 != + st c_1,rp(3) !r[3]=c1; + + umul a_4,b_0,t_1 !mul_add_c(a[4],b[0],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx %g0,%g0,c_1 + umul a_3,b_1,t_1 !mul_add_c(a[3],b[1],c2,c3,c1); + addcc c_2,t_1,c_2 != + rd %y,t_2 + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + umul a_2,b_2,t_1 !=!mul_add_c(a[2],b[2],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 != + ld bp(4),b_4 + umul a_1,b_3,t_1 !mul_add_c(a[1],b[3],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + ld bp(5),b_5 + umul a_0,b_4,t_1 !=!mul_add_c(a[0],b[4],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 != + st c_2,rp(4) !r[4]=c2; + + umul a_0,b_5,t_1 !mul_add_c(a[0],b[5],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 != + addxcc c_1,t_2,c_1 + addx %g0,%g0,c_2 + umul a_1,b_4,t_1 !mul_add_c(a[1],b[4],c3,c1,c2); + addcc c_3,t_1,c_3 != + rd %y,t_2 + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 + umul a_2,b_3,t_1 !=!mul_add_c(a[2],b[3],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 != + umul a_3,b_2,t_1 !mul_add_c(a[3],b[2],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 != + addx c_2,%g0,c_2 + ld ap(5),a_5 + umul a_4,b_1,t_1 !mul_add_c(a[4],b[1],c3,c1,c2); + addcc c_3,t_1,c_3 != + rd %y,t_2 + addxcc c_1,t_2,c_1 + ld ap(6),a_6 + addx c_2,%g0,c_2 != + umul a_5,b_0,t_1 !mul_add_c(a[5],b[0],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 != + addx c_2,%g0,c_2 + st c_3,rp(5) !r[5]=c3; + + umul a_6,b_0,t_1 !mul_add_c(a[6],b[0],c1,c2,c3); + addcc c_1,t_1,c_1 != + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx %g0,%g0,c_3 + umul a_5,b_1,t_1 !=!mul_add_c(a[5],b[1],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 != + umul a_4,b_2,t_1 !mul_add_c(a[4],b[2],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + addx c_3,%g0,c_3 + umul a_3,b_3,t_1 !mul_add_c(a[3],b[3],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 != + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 + umul a_2,b_4,t_1 !mul_add_c(a[2],b[4],c1,c2,c3); + addcc c_1,t_1,c_1 != + rd %y,t_2 + addxcc c_2,t_2,c_2 + ld bp(6),b_6 + addx c_3,%g0,c_3 != + umul a_1,b_5,t_1 !mul_add_c(a[1],b[5],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + addx c_3,%g0,c_3 + ld bp(7),b_7 + umul a_0,b_6,t_1 !mul_add_c(a[0],b[6],c1,c2,c3); + addcc c_1,t_1,c_1 != + rd %y,t_2 + addxcc c_2,t_2,c_2 + st c_1,rp(6) !r[6]=c1; + addx c_3,%g0,c_3 != + + umul a_0,b_7,t_1 !mul_add_c(a[0],b[7],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc c_3,t_2,c_3 != + addx %g0,%g0,c_1 + umul a_1,b_6,t_1 !mul_add_c(a[1],b[6],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + umul a_2,b_5,t_1 !mul_add_c(a[2],b[5],c2,c3,c1); + addcc c_2,t_1,c_2 != + rd %y,t_2 + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + umul a_3,b_4,t_1 !=!mul_add_c(a[3],b[4],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 != + umul a_4,b_3,t_1 !mul_add_c(a[4],b[3],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc c_3,t_2,c_3 != + addx c_1,%g0,c_1 + umul a_5,b_2,t_1 !mul_add_c(a[5],b[2],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + ld ap(7),a_7 + umul a_6,b_1,t_1 !=!mul_add_c(a[6],b[1],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 != + umul a_7,b_0,t_1 !mul_add_c(a[7],b[0],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc c_3,t_2,c_3 != + addx c_1,%g0,c_1 + st c_2,rp(7) !r[7]=c2; + + umul a_7,b_1,t_1 !mul_add_c(a[7],b[1],c3,c1,c2); + addcc c_3,t_1,c_3 != + rd %y,t_2 + addxcc c_1,t_2,c_1 + addx %g0,%g0,c_2 + umul a_6,b_2,t_1 !=!mul_add_c(a[6],b[2],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 != + umul a_5,b_3,t_1 !mul_add_c(a[5],b[3],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 != + addx c_2,%g0,c_2 + umul a_4,b_4,t_1 !mul_add_c(a[4],b[4],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 != + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 + umul a_3,b_5,t_1 !mul_add_c(a[3],b[5],c3,c1,c2); + addcc c_3,t_1,c_3 != + rd %y,t_2 + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 + umul a_2,b_6,t_1 !=!mul_add_c(a[2],b[6],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 != + umul a_1,b_7,t_1 !mul_add_c(a[1],b[7],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 ! + addx c_2,%g0,c_2 + st c_3,rp(8) !r[8]=c3; + + umul a_2,b_7,t_1 !mul_add_c(a[2],b[7],c1,c2,c3); + addcc c_1,t_1,c_1 != + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx %g0,%g0,c_3 + umul a_3,b_6,t_1 !=!mul_add_c(a[3],b[6],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 != + umul a_4,b_5,t_1 !mul_add_c(a[4],b[5],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + addx c_3,%g0,c_3 + umul a_5,b_4,t_1 !mul_add_c(a[5],b[4],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 != + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 + umul a_6,b_3,t_1 !mul_add_c(a[6],b[3],c1,c2,c3); + addcc c_1,t_1,c_1 != + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 + umul a_7,b_2,t_1 !=!mul_add_c(a[7],b[2],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 != + st c_1,rp(9) !r[9]=c1; + + umul a_7,b_3,t_1 !mul_add_c(a[7],b[3],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx %g0,%g0,c_1 + umul a_6,b_4,t_1 !mul_add_c(a[6],b[4],c2,c3,c1); + addcc c_2,t_1,c_2 != + rd %y,t_2 + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + umul a_5,b_5,t_1 !=!mul_add_c(a[5],b[5],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 != + umul a_4,b_6,t_1 !mul_add_c(a[4],b[6],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc c_3,t_2,c_3 != + addx c_1,%g0,c_1 + umul a_3,b_7,t_1 !mul_add_c(a[3],b[7],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + st c_2,rp(10) !r[10]=c2; + + umul a_4,b_7,t_1 !=!mul_add_c(a[4],b[7],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 + addx %g0,%g0,c_2 != + umul a_5,b_6,t_1 !mul_add_c(a[5],b[6],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 != + addx c_2,%g0,c_2 + umul a_6,b_5,t_1 !mul_add_c(a[6],b[5],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 != + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 + umul a_7,b_4,t_1 !mul_add_c(a[7],b[4],c3,c1,c2); + addcc c_3,t_1,c_3 != + rd %y,t_2 + addxcc c_1,t_2,c_1 + st c_3,rp(11) !r[11]=c3; + addx c_2,%g0,c_2 != + + umul a_7,b_5,t_1 !mul_add_c(a[7],b[5],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + addx %g0,%g0,c_3 + umul a_6,b_6,t_1 !mul_add_c(a[6],b[6],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 != + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 + umul a_5,b_7,t_1 !mul_add_c(a[5],b[7],c1,c2,c3); + addcc c_1,t_1,c_1 != + rd %y,t_2 + addxcc c_2,t_2,c_2 + st c_1,rp(12) !r[12]=c1; + addx c_3,%g0,c_3 != + + umul a_6,b_7,t_1 !mul_add_c(a[6],b[7],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc c_3,t_2,c_3 != + addx %g0,%g0,c_1 + umul a_7,b_6,t_1 !mul_add_c(a[7],b[6],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + st c_2,rp(13) !r[13]=c2; + + umul a_7,b_7,t_1 !=!mul_add_c(a[7],b[7],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 + nop != + st c_3,rp(14) !r[14]=c3; + st c_1,rp(15) !r[15]=c1; + + ret + restore %g0,%g0,%o0 + +.type bn_mul_comba8,#function +.size bn_mul_comba8,(.-bn_mul_comba8) + +.align 32 + +.global bn_mul_comba4 +/* + * void bn_mul_comba4(r,a,b) + * BN_ULONG *r,*a,*b; + */ +bn_mul_comba4: + save %sp,FRAME_SIZE,%sp + ld ap(0),a_0 + ld bp(0),b_0 + umul a_0,b_0,c_1 !=!mul_add_c(a[0],b[0],c1,c2,c3); + ld bp(1),b_1 + rd %y,c_2 + st c_1,rp(0) !r[0]=c1; + + umul a_0,b_1,t_1 !=!mul_add_c(a[0],b[1],c2,c3,c1); + ld ap(1),a_1 + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc %g0,t_2,c_3 + addx %g0,%g0,c_1 + ld ap(2),a_2 + umul a_1,b_0,t_1 !=!mul_add_c(a[1],b[0],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 != + st c_2,rp(1) !r[1]=c2; + + umul a_2,b_0,t_1 !mul_add_c(a[2],b[0],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 != + addxcc c_1,t_2,c_1 + addx %g0,%g0,c_2 + ld bp(2),b_2 + umul a_1,b_1,t_1 !=!mul_add_c(a[1],b[1],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 != + ld bp(3),b_3 + umul a_0,b_2,t_1 !mul_add_c(a[0],b[2],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 != + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 + st c_3,rp(2) !r[2]=c3; + + umul a_0,b_3,t_1 !=!mul_add_c(a[0],b[3],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx %g0,%g0,c_3 != + umul a_1,b_2,t_1 !mul_add_c(a[1],b[2],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + addx c_3,%g0,c_3 + ld ap(3),a_3 + umul a_2,b_1,t_1 !mul_add_c(a[2],b[1],c1,c2,c3); + addcc c_1,t_1,c_1 != + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 + umul a_3,b_0,t_1 !=!mul_add_c(a[3],b[0],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 != + st c_1,rp(3) !r[3]=c1; + + umul a_3,b_1,t_1 !mul_add_c(a[3],b[1],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx %g0,%g0,c_1 + umul a_2,b_2,t_1 !mul_add_c(a[2],b[2],c2,c3,c1); + addcc c_2,t_1,c_2 != + rd %y,t_2 + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + umul a_1,b_3,t_1 !=!mul_add_c(a[1],b[3],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 != + st c_2,rp(4) !r[4]=c2; + + umul a_2,b_3,t_1 !mul_add_c(a[2],b[3],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 != + addxcc c_1,t_2,c_1 + addx %g0,%g0,c_2 + umul a_3,b_2,t_1 !mul_add_c(a[3],b[2],c3,c1,c2); + addcc c_3,t_1,c_3 != + rd %y,t_2 + addxcc c_1,t_2,c_1 + st c_3,rp(5) !r[5]=c3; + addx c_2,%g0,c_2 != + + umul a_3,b_3,t_1 !mul_add_c(a[3],b[3],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + st c_1,rp(6) !r[6]=c1; + st c_2,rp(7) !r[7]=c2; + + ret + restore %g0,%g0,%o0 + +.type bn_mul_comba4,#function +.size bn_mul_comba4,(.-bn_mul_comba4) + +.align 32 + +.global bn_sqr_comba8 +bn_sqr_comba8: + save %sp,FRAME_SIZE,%sp + ld ap(0),a_0 + ld ap(1),a_1 + umul a_0,a_0,c_1 !=!sqr_add_c(a,0,c1,c2,c3); + rd %y,c_2 + st c_1,rp(0) !r[0]=c1; + + ld ap(2),a_2 + umul a_0,a_1,t_1 !=!sqr_add_c2(a,1,0,c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc %g0,t_2,c_3 + addx %g0,%g0,c_1 != + addcc c_2,t_1,c_2 + addxcc c_3,t_2,c_3 + st c_2,rp(1) !r[1]=c2; + addx c_1,%g0,c_1 != + + umul a_2,a_0,t_1 !sqr_add_c2(a,2,0,c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 != + addx %g0,%g0,c_2 + addcc c_3,t_1,c_3 + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 != + ld ap(3),a_3 + umul a_1,a_1,t_1 !sqr_add_c(a,1,c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 != + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 + st c_3,rp(2) !r[2]=c3; + + umul a_0,a_3,t_1 !=!sqr_add_c2(a,3,0,c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx %g0,%g0,c_3 != + addcc c_1,t_1,c_1 + addxcc c_2,t_2,c_2 + ld ap(4),a_4 + addx c_3,%g0,c_3 != + umul a_1,a_2,t_1 !sqr_add_c2(a,2,1,c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + addx c_3,%g0,c_3 + addcc c_1,t_1,c_1 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 != + st c_1,rp(3) !r[3]=c1; + + umul a_4,a_0,t_1 !sqr_add_c2(a,4,0,c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx %g0,%g0,c_1 + addcc c_2,t_1,c_2 + addxcc c_3,t_2,c_3 != + addx c_1,%g0,c_1 + umul a_3,a_1,t_1 !sqr_add_c2(a,3,1,c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + addcc c_2,t_1,c_2 + addxcc c_3,t_2,c_3 != + addx c_1,%g0,c_1 + ld ap(5),a_5 + umul a_2,a_2,t_1 !sqr_add_c(a,2,c2,c3,c1); + addcc c_2,t_1,c_2 != + rd %y,t_2 + addxcc c_3,t_2,c_3 + st c_2,rp(4) !r[4]=c2; + addx c_1,%g0,c_1 != + + umul a_0,a_5,t_1 !sqr_add_c2(a,5,0,c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 != + addx %g0,%g0,c_2 + addcc c_3,t_1,c_3 + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 != + umul a_1,a_4,t_1 !sqr_add_c2(a,4,1,c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 != + addx c_2,%g0,c_2 + addcc c_3,t_1,c_3 + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 != + ld ap(6),a_6 + umul a_2,a_3,t_1 !sqr_add_c2(a,3,2,c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 != + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 + addcc c_3,t_1,c_3 + addxcc c_1,t_2,c_1 != + addx c_2,%g0,c_2 + st c_3,rp(5) !r[5]=c3; + + umul a_6,a_0,t_1 !sqr_add_c2(a,6,0,c1,c2,c3); + addcc c_1,t_1,c_1 != + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx %g0,%g0,c_3 + addcc c_1,t_1,c_1 != + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 + umul a_5,a_1,t_1 !sqr_add_c2(a,5,1,c1,c2,c3); + addcc c_1,t_1,c_1 != + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 + addcc c_1,t_1,c_1 != + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 + umul a_4,a_2,t_1 !sqr_add_c2(a,4,2,c1,c2,c3); + addcc c_1,t_1,c_1 != + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 + addcc c_1,t_1,c_1 != + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 + ld ap(7),a_7 + umul a_3,a_3,t_1 !=!sqr_add_c(a,3,c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 != + st c_1,rp(6) !r[6]=c1; + + umul a_0,a_7,t_1 !sqr_add_c2(a,7,0,c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx %g0,%g0,c_1 + addcc c_2,t_1,c_2 + addxcc c_3,t_2,c_3 != + addx c_1,%g0,c_1 + umul a_1,a_6,t_1 !sqr_add_c2(a,6,1,c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + addcc c_2,t_1,c_2 + addxcc c_3,t_2,c_3 != + addx c_1,%g0,c_1 + umul a_2,a_5,t_1 !sqr_add_c2(a,5,2,c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + addcc c_2,t_1,c_2 + addxcc c_3,t_2,c_3 != + addx c_1,%g0,c_1 + umul a_3,a_4,t_1 !sqr_add_c2(a,4,3,c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + addcc c_2,t_1,c_2 + addxcc c_3,t_2,c_3 != + addx c_1,%g0,c_1 + st c_2,rp(7) !r[7]=c2; + + umul a_7,a_1,t_1 !sqr_add_c2(a,7,1,c3,c1,c2); + addcc c_3,t_1,c_3 != + rd %y,t_2 + addxcc c_1,t_2,c_1 + addx %g0,%g0,c_2 + addcc c_3,t_1,c_3 != + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 + umul a_6,a_2,t_1 !sqr_add_c2(a,6,2,c3,c1,c2); + addcc c_3,t_1,c_3 != + rd %y,t_2 + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 + addcc c_3,t_1,c_3 != + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 + umul a_5,a_3,t_1 !sqr_add_c2(a,5,3,c3,c1,c2); + addcc c_3,t_1,c_3 != + rd %y,t_2 + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 + addcc c_3,t_1,c_3 != + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 + umul a_4,a_4,t_1 !sqr_add_c(a,4,c3,c1,c2); + addcc c_3,t_1,c_3 != + rd %y,t_2 + addxcc c_1,t_2,c_1 + st c_3,rp(8) !r[8]=c3; + addx c_2,%g0,c_2 != + + umul a_2,a_7,t_1 !sqr_add_c2(a,7,2,c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + addx %g0,%g0,c_3 + addcc c_1,t_1,c_1 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 != + umul a_3,a_6,t_1 !sqr_add_c2(a,6,3,c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + addx c_3,%g0,c_3 + addcc c_1,t_1,c_1 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 != + umul a_4,a_5,t_1 !sqr_add_c2(a,5,4,c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + addx c_3,%g0,c_3 + addcc c_1,t_1,c_1 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 != + st c_1,rp(9) !r[9]=c1; + + umul a_7,a_3,t_1 !sqr_add_c2(a,7,3,c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx %g0,%g0,c_1 + addcc c_2,t_1,c_2 + addxcc c_3,t_2,c_3 != + addx c_1,%g0,c_1 + umul a_6,a_4,t_1 !sqr_add_c2(a,6,4,c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + addcc c_2,t_1,c_2 + addxcc c_3,t_2,c_3 != + addx c_1,%g0,c_1 + umul a_5,a_5,t_1 !sqr_add_c(a,5,c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + st c_2,rp(10) !r[10]=c2; + + umul a_4,a_7,t_1 !=!sqr_add_c2(a,7,4,c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 + addx %g0,%g0,c_2 != + addcc c_3,t_1,c_3 + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 + umul a_5,a_6,t_1 !=!sqr_add_c2(a,6,5,c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 != + addcc c_3,t_1,c_3 + addxcc c_1,t_2,c_1 + st c_3,rp(11) !r[11]=c3; + addx c_2,%g0,c_2 != + + umul a_7,a_5,t_1 !sqr_add_c2(a,7,5,c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + addx %g0,%g0,c_3 + addcc c_1,t_1,c_1 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 != + umul a_6,a_6,t_1 !sqr_add_c(a,6,c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + addx c_3,%g0,c_3 + st c_1,rp(12) !r[12]=c1; + + umul a_6,a_7,t_1 !sqr_add_c2(a,7,6,c2,c3,c1); + addcc c_2,t_1,c_2 != + rd %y,t_2 + addxcc c_3,t_2,c_3 + addx %g0,%g0,c_1 + addcc c_2,t_1,c_2 != + addxcc c_3,t_2,c_3 + st c_2,rp(13) !r[13]=c2; + addx c_1,%g0,c_1 != + + umul a_7,a_7,t_1 !sqr_add_c(a,7,c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 != + st c_3,rp(14) !r[14]=c3; + st c_1,rp(15) !r[15]=c1; + + ret + restore %g0,%g0,%o0 + +.type bn_sqr_comba8,#function +.size bn_sqr_comba8,(.-bn_sqr_comba8) + +.align 32 + +.global bn_sqr_comba4 +/* + * void bn_sqr_comba4(r,a) + * BN_ULONG *r,*a; + */ +bn_sqr_comba4: + save %sp,FRAME_SIZE,%sp + ld ap(0),a_0 + umul a_0,a_0,c_1 !sqr_add_c(a,0,c1,c2,c3); + ld ap(1),a_1 != + rd %y,c_2 + st c_1,rp(0) !r[0]=c1; + + ld ap(2),a_2 + umul a_0,a_1,t_1 !=!sqr_add_c2(a,1,0,c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc %g0,t_2,c_3 + addx %g0,%g0,c_1 != + addcc c_2,t_1,c_2 + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 != + st c_2,rp(1) !r[1]=c2; + + umul a_2,a_0,t_1 !sqr_add_c2(a,2,0,c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 != + addxcc c_1,t_2,c_1 + addx %g0,%g0,c_2 + addcc c_3,t_1,c_3 + addxcc c_1,t_2,c_1 != + addx c_2,%g0,c_2 + ld ap(3),a_3 + umul a_1,a_1,t_1 !sqr_add_c(a,1,c3,c1,c2); + addcc c_3,t_1,c_3 != + rd %y,t_2 + addxcc c_1,t_2,c_1 + st c_3,rp(2) !r[2]=c3; + addx c_2,%g0,c_2 != + + umul a_0,a_3,t_1 !sqr_add_c2(a,3,0,c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + addx %g0,%g0,c_3 + addcc c_1,t_1,c_1 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 != + umul a_1,a_2,t_1 !sqr_add_c2(a,2,1,c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + addx c_3,%g0,c_3 + addcc c_1,t_1,c_1 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 != + st c_1,rp(3) !r[3]=c1; + + umul a_3,a_1,t_1 !sqr_add_c2(a,3,1,c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx %g0,%g0,c_1 + addcc c_2,t_1,c_2 + addxcc c_3,t_2,c_3 != + addx c_1,%g0,c_1 + umul a_2,a_2,t_1 !sqr_add_c(a,2,c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + st c_2,rp(4) !r[4]=c2; + + umul a_2,a_3,t_1 !=!sqr_add_c2(a,3,2,c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 + addx %g0,%g0,c_2 != + addcc c_3,t_1,c_3 + addxcc c_1,t_2,c_1 + st c_3,rp(5) !r[5]=c3; + addx c_2,%g0,c_2 != + + umul a_3,a_3,t_1 !sqr_add_c(a,3,c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + st c_1,rp(6) !r[6]=c1; + st c_2,rp(7) !r[7]=c2; + + ret + restore %g0,%g0,%o0 + +.type bn_sqr_comba4,#function +.size bn_sqr_comba4,(.-bn_sqr_comba4) + +.align 32 diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/sparcv8plus.S b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/sparcv8plus.S new file mode 100644 index 000000000..d520ffa7c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/sparcv8plus.S @@ -0,0 +1,1558 @@ +.ident "sparcv8plus.s, Version 1.4" +.ident "SPARC v9 ISA artwork by Andy Polyakov " + +/* + * ==================================================================== + * Copyright 1999-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + * ==================================================================== + */ + +/* + * This is my modest contribution to OpenSSL project (see + * http://www.openssl.org/ for more information about it) and is + * a drop-in UltraSPARC ISA replacement for crypto/bn/bn_asm.c + * module. For updates see http://fy.chalmers.se/~appro/hpe/. + * + * Questions-n-answers. + * + * Q. How to compile? + * A. With SC4.x/SC5.x: + * + * cc -xarch=v8plus -c bn_asm.sparc.v8plus.S -o bn_asm.o + * + * and with gcc: + * + * gcc -mcpu=ultrasparc -c bn_asm.sparc.v8plus.S -o bn_asm.o + * + * or if above fails (it does if you have gas installed): + * + * gcc -E bn_asm.sparc.v8plus.S | as -xarch=v8plus /dev/fd/0 -o bn_asm.o + * + * Quick-n-dirty way to fuse the module into the library. + * Provided that the library is already configured and built + * (in 0.9.2 case with no-asm option): + * + * # cd crypto/bn + * # cp /some/place/bn_asm.sparc.v8plus.S . + * # cc -xarch=v8plus -c bn_asm.sparc.v8plus.S -o bn_asm.o + * # make + * # cd ../.. + * # make; make test + * + * Quick-n-dirty way to get rid of it: + * + * # cd crypto/bn + * # touch bn_asm.c + * # make + * # cd ../.. + * # make; make test + * + * Q. V8plus architecture? What kind of beast is that? + * A. Well, it's rather a programming model than an architecture... + * It's actually v9-compliant, i.e. *any* UltraSPARC, CPU under + * special conditions, namely when kernel doesn't preserve upper + * 32 bits of otherwise 64-bit registers during a context switch. + * + * Q. Why just UltraSPARC? What about SuperSPARC? + * A. Original release did target UltraSPARC only. Now SuperSPARC + * version is provided along. Both version share bn_*comba[48] + * implementations (see comment later in code for explanation). + * But what's so special about this UltraSPARC implementation? + * Why didn't I let compiler do the job? Trouble is that most of + * available compilers (well, SC5.0 is the only exception) don't + * attempt to take advantage of UltraSPARC's 64-bitness under + * 32-bit kernels even though it's perfectly possible (see next + * question). + * + * Q. 64-bit registers under 32-bit kernels? Didn't you just say it + * doesn't work? + * A. You can't address *all* registers as 64-bit wide:-( The catch is + * that you actually may rely upon %o0-%o5 and %g1-%g4 being fully + * preserved if you're in a leaf function, i.e. such never calling + * any other functions. All functions in this module are leaf and + * 10 registers is a handful. And as a matter of fact none-"comba" + * routines don't require even that much and I could even afford to + * not allocate own stack frame for 'em:-) + * + * Q. What about 64-bit kernels? + * A. What about 'em? Just kidding:-) Pure 64-bit version is currently + * under evaluation and development... + * + * Q. What about shared libraries? + * A. What about 'em? Kidding again:-) Code does *not* contain any + * code position dependencies and it's safe to include it into + * shared library as is. + * + * Q. How much faster does it go? + * A. Do you have a good benchmark? In either case below is what I + * experience with crypto/bn/expspeed.c test program: + * + * v8plus module on U10/300MHz against bn_asm.c compiled with: + * + * cc-5.0 -xarch=v8plus -xO5 -xdepend +7-12% + * cc-4.2 -xarch=v8plus -xO5 -xdepend +25-35% + * egcs-1.1.2 -mcpu=ultrasparc -O3 +35-45% + * + * v8 module on SS10/60MHz against bn_asm.c compiled with: + * + * cc-5.0 -xarch=v8 -xO5 -xdepend +7-10% + * cc-4.2 -xarch=v8 -xO5 -xdepend +10% + * egcs-1.1.2 -mv8 -O3 +35-45% + * + * As you can see it's damn hard to beat the new Sun C compiler + * and it's in first place GNU C users who will appreciate this + * assembler implementation:-) + */ + +/* + * Revision history. + * + * 1.0 - initial release; + * 1.1 - new loop unrolling model(*); + * - some more fine tuning; + * 1.2 - made gas friendly; + * - updates to documentation concerning v9; + * - new performance comparison matrix; + * 1.3 - fixed problem with /usr/ccs/lib/cpp; + * 1.4 - native V9 bn_*_comba[48] implementation (15% more efficient) + * resulting in slight overall performance kick; + * - some retunes; + * - support for GNU as added; + * + * (*) Originally unrolled loop looked like this: + * for (;;) { + * op(p+0); if (--n==0) break; + * op(p+1); if (--n==0) break; + * op(p+2); if (--n==0) break; + * op(p+3); if (--n==0) break; + * p+=4; + * } + * I unroll according to following: + * while (n&~3) { + * op(p+0); op(p+1); op(p+2); op(p+3); + * p+=4; n=-4; + * } + * if (n) { + * op(p+0); if (--n==0) return; + * op(p+2); if (--n==0) return; + * op(p+3); return; + * } + */ + +#if defined(__SUNPRO_C) && defined(__sparcv9) + /* They've said -xarch=v9 at command line */ + .register %g2,#scratch + .register %g3,#scratch +# define FRAME_SIZE -192 +#elif defined(__GNUC__) && defined(__arch64__) + /* They've said -m64 at command line */ + .register %g2,#scratch + .register %g3,#scratch +# define FRAME_SIZE -192 +#else +# define FRAME_SIZE -96 +#endif +/* + * GNU assembler can't stand stuw:-( + */ +#define stuw st + +.section ".text",#alloc,#execinstr +.file "bn_asm.sparc.v8plus.S" + +.align 32 + +.global bn_mul_add_words +/* + * BN_ULONG bn_mul_add_words(rp,ap,num,w) + * BN_ULONG *rp,*ap; + * int num; + * BN_ULONG w; + */ +bn_mul_add_words: + sra %o2,%g0,%o2 ! signx %o2 + brgz,a %o2,.L_bn_mul_add_words_proceed + lduw [%o1],%g2 + retl + clr %o0 + nop + nop + nop + +.L_bn_mul_add_words_proceed: + srl %o3,%g0,%o3 ! clruw %o3 + andcc %o2,-4,%g0 + bz,pn %icc,.L_bn_mul_add_words_tail + clr %o5 + +.L_bn_mul_add_words_loop: ! wow! 32 aligned! + lduw [%o0],%g1 + lduw [%o1+4],%g3 + mulx %o3,%g2,%g2 + add %g1,%o5,%o4 + nop + add %o4,%g2,%o4 + stuw %o4,[%o0] + srlx %o4,32,%o5 + + lduw [%o0+4],%g1 + lduw [%o1+8],%g2 + mulx %o3,%g3,%g3 + add %g1,%o5,%o4 + dec 4,%o2 + add %o4,%g3,%o4 + stuw %o4,[%o0+4] + srlx %o4,32,%o5 + + lduw [%o0+8],%g1 + lduw [%o1+12],%g3 + mulx %o3,%g2,%g2 + add %g1,%o5,%o4 + inc 16,%o1 + add %o4,%g2,%o4 + stuw %o4,[%o0+8] + srlx %o4,32,%o5 + + lduw [%o0+12],%g1 + mulx %o3,%g3,%g3 + add %g1,%o5,%o4 + inc 16,%o0 + add %o4,%g3,%o4 + andcc %o2,-4,%g0 + stuw %o4,[%o0-4] + srlx %o4,32,%o5 + bnz,a,pt %icc,.L_bn_mul_add_words_loop + lduw [%o1],%g2 + + brnz,a,pn %o2,.L_bn_mul_add_words_tail + lduw [%o1],%g2 +.L_bn_mul_add_words_return: + retl + mov %o5,%o0 + +.L_bn_mul_add_words_tail: + lduw [%o0],%g1 + mulx %o3,%g2,%g2 + add %g1,%o5,%o4 + dec %o2 + add %o4,%g2,%o4 + srlx %o4,32,%o5 + brz,pt %o2,.L_bn_mul_add_words_return + stuw %o4,[%o0] + + lduw [%o1+4],%g2 + lduw [%o0+4],%g1 + mulx %o3,%g2,%g2 + add %g1,%o5,%o4 + dec %o2 + add %o4,%g2,%o4 + srlx %o4,32,%o5 + brz,pt %o2,.L_bn_mul_add_words_return + stuw %o4,[%o0+4] + + lduw [%o1+8],%g2 + lduw [%o0+8],%g1 + mulx %o3,%g2,%g2 + add %g1,%o5,%o4 + add %o4,%g2,%o4 + stuw %o4,[%o0+8] + retl + srlx %o4,32,%o0 + +.type bn_mul_add_words,#function +.size bn_mul_add_words,(.-bn_mul_add_words) + +.align 32 + +.global bn_mul_words +/* + * BN_ULONG bn_mul_words(rp,ap,num,w) + * BN_ULONG *rp,*ap; + * int num; + * BN_ULONG w; + */ +bn_mul_words: + sra %o2,%g0,%o2 ! signx %o2 + brgz,a %o2,.L_bn_mul_words_proceed + lduw [%o1],%g2 + retl + clr %o0 + nop + nop + nop + +.L_bn_mul_words_proceed: + srl %o3,%g0,%o3 ! clruw %o3 + andcc %o2,-4,%g0 + bz,pn %icc,.L_bn_mul_words_tail + clr %o5 + +.L_bn_mul_words_loop: ! wow! 32 aligned! + lduw [%o1+4],%g3 + mulx %o3,%g2,%g2 + add %g2,%o5,%o4 + nop + stuw %o4,[%o0] + srlx %o4,32,%o5 + + lduw [%o1+8],%g2 + mulx %o3,%g3,%g3 + add %g3,%o5,%o4 + dec 4,%o2 + stuw %o4,[%o0+4] + srlx %o4,32,%o5 + + lduw [%o1+12],%g3 + mulx %o3,%g2,%g2 + add %g2,%o5,%o4 + inc 16,%o1 + stuw %o4,[%o0+8] + srlx %o4,32,%o5 + + mulx %o3,%g3,%g3 + add %g3,%o5,%o4 + inc 16,%o0 + stuw %o4,[%o0-4] + srlx %o4,32,%o5 + andcc %o2,-4,%g0 + bnz,a,pt %icc,.L_bn_mul_words_loop + lduw [%o1],%g2 + nop + nop + + brnz,a,pn %o2,.L_bn_mul_words_tail + lduw [%o1],%g2 +.L_bn_mul_words_return: + retl + mov %o5,%o0 + +.L_bn_mul_words_tail: + mulx %o3,%g2,%g2 + add %g2,%o5,%o4 + dec %o2 + srlx %o4,32,%o5 + brz,pt %o2,.L_bn_mul_words_return + stuw %o4,[%o0] + + lduw [%o1+4],%g2 + mulx %o3,%g2,%g2 + add %g2,%o5,%o4 + dec %o2 + srlx %o4,32,%o5 + brz,pt %o2,.L_bn_mul_words_return + stuw %o4,[%o0+4] + + lduw [%o1+8],%g2 + mulx %o3,%g2,%g2 + add %g2,%o5,%o4 + stuw %o4,[%o0+8] + retl + srlx %o4,32,%o0 + +.type bn_mul_words,#function +.size bn_mul_words,(.-bn_mul_words) + +.align 32 +.global bn_sqr_words +/* + * void bn_sqr_words(r,a,n) + * BN_ULONG *r,*a; + * int n; + */ +bn_sqr_words: + sra %o2,%g0,%o2 ! signx %o2 + brgz,a %o2,.L_bn_sqr_words_proceed + lduw [%o1],%g2 + retl + clr %o0 + nop + nop + nop + +.L_bn_sqr_words_proceed: + andcc %o2,-4,%g0 + nop + bz,pn %icc,.L_bn_sqr_words_tail + nop + +.L_bn_sqr_words_loop: ! wow! 32 aligned! + lduw [%o1+4],%g3 + mulx %g2,%g2,%o4 + stuw %o4,[%o0] + srlx %o4,32,%o5 + stuw %o5,[%o0+4] + nop + + lduw [%o1+8],%g2 + mulx %g3,%g3,%o4 + dec 4,%o2 + stuw %o4,[%o0+8] + srlx %o4,32,%o5 + stuw %o5,[%o0+12] + + lduw [%o1+12],%g3 + mulx %g2,%g2,%o4 + srlx %o4,32,%o5 + stuw %o4,[%o0+16] + inc 16,%o1 + stuw %o5,[%o0+20] + + mulx %g3,%g3,%o4 + inc 32,%o0 + stuw %o4,[%o0-8] + srlx %o4,32,%o5 + andcc %o2,-4,%g2 + stuw %o5,[%o0-4] + bnz,a,pt %icc,.L_bn_sqr_words_loop + lduw [%o1],%g2 + nop + + brnz,a,pn %o2,.L_bn_sqr_words_tail + lduw [%o1],%g2 +.L_bn_sqr_words_return: + retl + clr %o0 + +.L_bn_sqr_words_tail: + mulx %g2,%g2,%o4 + dec %o2 + stuw %o4,[%o0] + srlx %o4,32,%o5 + brz,pt %o2,.L_bn_sqr_words_return + stuw %o5,[%o0+4] + + lduw [%o1+4],%g2 + mulx %g2,%g2,%o4 + dec %o2 + stuw %o4,[%o0+8] + srlx %o4,32,%o5 + brz,pt %o2,.L_bn_sqr_words_return + stuw %o5,[%o0+12] + + lduw [%o1+8],%g2 + mulx %g2,%g2,%o4 + srlx %o4,32,%o5 + stuw %o4,[%o0+16] + stuw %o5,[%o0+20] + retl + clr %o0 + +.type bn_sqr_words,#function +.size bn_sqr_words,(.-bn_sqr_words) + +.align 32 +.global bn_div_words +/* + * BN_ULONG bn_div_words(h,l,d) + * BN_ULONG h,l,d; + */ +bn_div_words: + sllx %o0,32,%o0 + or %o0,%o1,%o0 + udivx %o0,%o2,%o0 + retl + srl %o0,%g0,%o0 ! clruw %o0 + +.type bn_div_words,#function +.size bn_div_words,(.-bn_div_words) + +.align 32 + +.global bn_add_words +/* + * BN_ULONG bn_add_words(rp,ap,bp,n) + * BN_ULONG *rp,*ap,*bp; + * int n; + */ +bn_add_words: + sra %o3,%g0,%o3 ! signx %o3 + brgz,a %o3,.L_bn_add_words_proceed + lduw [%o1],%o4 + retl + clr %o0 + +.L_bn_add_words_proceed: + andcc %o3,-4,%g0 + bz,pn %icc,.L_bn_add_words_tail + addcc %g0,0,%g0 ! clear carry flag + +.L_bn_add_words_loop: ! wow! 32 aligned! + dec 4,%o3 + lduw [%o2],%o5 + lduw [%o1+4],%g1 + lduw [%o2+4],%g2 + lduw [%o1+8],%g3 + lduw [%o2+8],%g4 + addccc %o5,%o4,%o5 + stuw %o5,[%o0] + + lduw [%o1+12],%o4 + lduw [%o2+12],%o5 + inc 16,%o1 + addccc %g1,%g2,%g1 + stuw %g1,[%o0+4] + + inc 16,%o2 + addccc %g3,%g4,%g3 + stuw %g3,[%o0+8] + + inc 16,%o0 + addccc %o5,%o4,%o5 + stuw %o5,[%o0-4] + and %o3,-4,%g1 + brnz,a,pt %g1,.L_bn_add_words_loop + lduw [%o1],%o4 + + brnz,a,pn %o3,.L_bn_add_words_tail + lduw [%o1],%o4 +.L_bn_add_words_return: + clr %o0 + retl + movcs %icc,1,%o0 + nop + +.L_bn_add_words_tail: + lduw [%o2],%o5 + dec %o3 + addccc %o5,%o4,%o5 + brz,pt %o3,.L_bn_add_words_return + stuw %o5,[%o0] + + lduw [%o1+4],%o4 + lduw [%o2+4],%o5 + dec %o3 + addccc %o5,%o4,%o5 + brz,pt %o3,.L_bn_add_words_return + stuw %o5,[%o0+4] + + lduw [%o1+8],%o4 + lduw [%o2+8],%o5 + addccc %o5,%o4,%o5 + stuw %o5,[%o0+8] + clr %o0 + retl + movcs %icc,1,%o0 + +.type bn_add_words,#function +.size bn_add_words,(.-bn_add_words) + +.global bn_sub_words +/* + * BN_ULONG bn_sub_words(rp,ap,bp,n) + * BN_ULONG *rp,*ap,*bp; + * int n; + */ +bn_sub_words: + sra %o3,%g0,%o3 ! signx %o3 + brgz,a %o3,.L_bn_sub_words_proceed + lduw [%o1],%o4 + retl + clr %o0 + +.L_bn_sub_words_proceed: + andcc %o3,-4,%g0 + bz,pn %icc,.L_bn_sub_words_tail + addcc %g0,0,%g0 ! clear carry flag + +.L_bn_sub_words_loop: ! wow! 32 aligned! + dec 4,%o3 + lduw [%o2],%o5 + lduw [%o1+4],%g1 + lduw [%o2+4],%g2 + lduw [%o1+8],%g3 + lduw [%o2+8],%g4 + subccc %o4,%o5,%o5 + stuw %o5,[%o0] + + lduw [%o1+12],%o4 + lduw [%o2+12],%o5 + inc 16,%o1 + subccc %g1,%g2,%g2 + stuw %g2,[%o0+4] + + inc 16,%o2 + subccc %g3,%g4,%g4 + stuw %g4,[%o0+8] + + inc 16,%o0 + subccc %o4,%o5,%o5 + stuw %o5,[%o0-4] + and %o3,-4,%g1 + brnz,a,pt %g1,.L_bn_sub_words_loop + lduw [%o1],%o4 + + brnz,a,pn %o3,.L_bn_sub_words_tail + lduw [%o1],%o4 +.L_bn_sub_words_return: + clr %o0 + retl + movcs %icc,1,%o0 + nop + +.L_bn_sub_words_tail: ! wow! 32 aligned! + lduw [%o2],%o5 + dec %o3 + subccc %o4,%o5,%o5 + brz,pt %o3,.L_bn_sub_words_return + stuw %o5,[%o0] + + lduw [%o1+4],%o4 + lduw [%o2+4],%o5 + dec %o3 + subccc %o4,%o5,%o5 + brz,pt %o3,.L_bn_sub_words_return + stuw %o5,[%o0+4] + + lduw [%o1+8],%o4 + lduw [%o2+8],%o5 + subccc %o4,%o5,%o5 + stuw %o5,[%o0+8] + clr %o0 + retl + movcs %icc,1,%o0 + +.type bn_sub_words,#function +.size bn_sub_words,(.-bn_sub_words) + +/* + * Code below depends on the fact that upper parts of the %l0-%l7 + * and %i0-%i7 are zeroed by kernel after context switch. In + * previous versions this comment stated that "the trouble is that + * it's not feasible to implement the mumbo-jumbo in less V9 + * instructions:-(" which apparently isn't true thanks to + * 'bcs,a %xcc,.+8; inc %rd' pair. But the performance improvement + * results not from the shorter code, but from elimination of + * multicycle none-pairable 'rd %y,%rd' instructions. + * + * Andy. + */ + +/* + * Here is register usage map for *all* routines below. + */ +#define t_1 %o0 +#define t_2 %o1 +#define c_12 %o2 +#define c_3 %o3 + +#define ap(I) [%i1+4*I] +#define bp(I) [%i2+4*I] +#define rp(I) [%i0+4*I] + +#define a_0 %l0 +#define a_1 %l1 +#define a_2 %l2 +#define a_3 %l3 +#define a_4 %l4 +#define a_5 %l5 +#define a_6 %l6 +#define a_7 %l7 + +#define b_0 %i3 +#define b_1 %i4 +#define b_2 %i5 +#define b_3 %o4 +#define b_4 %o5 +#define b_5 %o7 +#define b_6 %g1 +#define b_7 %g4 + +.align 32 +.global bn_mul_comba8 +/* + * void bn_mul_comba8(r,a,b) + * BN_ULONG *r,*a,*b; + */ +bn_mul_comba8: + save %sp,FRAME_SIZE,%sp + mov 1,t_2 + lduw ap(0),a_0 + sllx t_2,32,t_2 + lduw bp(0),b_0 != + lduw bp(1),b_1 + mulx a_0,b_0,t_1 !mul_add_c(a[0],b[0],c1,c2,c3); + srlx t_1,32,c_12 + stuw t_1,rp(0) !=!r[0]=c1; + + lduw ap(1),a_1 + mulx a_0,b_1,t_1 !mul_add_c(a[0],b[1],c2,c3,c1); + addcc c_12,t_1,c_12 + clr c_3 != + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + lduw ap(2),a_2 + mulx a_1,b_0,t_1 !=!mul_add_c(a[1],b[0],c2,c3,c1); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 != + stuw t_1,rp(1) !r[1]=c2; + or c_12,c_3,c_12 + + mulx a_2,b_0,t_1 !mul_add_c(a[2],b[0],c3,c1,c2); + addcc c_12,t_1,c_12 != + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + lduw bp(2),b_2 != + mulx a_1,b_1,t_1 !mul_add_c(a[1],b[1],c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 != + lduw bp(3),b_3 + mulx a_0,b_2,t_1 !mul_add_c(a[0],b[2],c3,c1,c2); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(2) !r[2]=c3; + or c_12,c_3,c_12 != + + mulx a_0,b_3,t_1 !mul_add_c(a[0],b[3],c1,c2,c3); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_1,b_2,t_1 !=!mul_add_c(a[1],b[2],c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + lduw ap(3),a_3 + mulx a_2,b_1,t_1 !mul_add_c(a[2],b[1],c1,c2,c3); + addcc c_12,t_1,c_12 != + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + lduw ap(4),a_4 + mulx a_3,b_0,t_1 !=!mul_add_c(a[3],b[0],c1,c2,c3);!= + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 != + stuw t_1,rp(3) !r[3]=c1; + or c_12,c_3,c_12 + + mulx a_4,b_0,t_1 !mul_add_c(a[4],b[0],c2,c3,c1); + addcc c_12,t_1,c_12 != + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_3,b_1,t_1 !=!mul_add_c(a[3],b[1],c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_2,b_2,t_1 !=!mul_add_c(a[2],b[2],c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + lduw bp(4),b_4 != + mulx a_1,b_3,t_1 !mul_add_c(a[1],b[3],c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 != + lduw bp(5),b_5 + mulx a_0,b_4,t_1 !mul_add_c(a[0],b[4],c2,c3,c1); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(4) !r[4]=c2; + or c_12,c_3,c_12 != + + mulx a_0,b_5,t_1 !mul_add_c(a[0],b[5],c3,c1,c2); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_1,b_4,t_1 !mul_add_c(a[1],b[4],c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_2,b_3,t_1 !mul_add_c(a[2],b[3],c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_3,b_2,t_1 !mul_add_c(a[3],b[2],c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + lduw ap(5),a_5 + mulx a_4,b_1,t_1 !mul_add_c(a[4],b[1],c3,c1,c2); + addcc c_12,t_1,c_12 != + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + lduw ap(6),a_6 + mulx a_5,b_0,t_1 !=!mul_add_c(a[5],b[0],c3,c1,c2); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 != + stuw t_1,rp(5) !r[5]=c3; + or c_12,c_3,c_12 + + mulx a_6,b_0,t_1 !mul_add_c(a[6],b[0],c1,c2,c3); + addcc c_12,t_1,c_12 != + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_5,b_1,t_1 !=!mul_add_c(a[5],b[1],c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_4,b_2,t_1 !=!mul_add_c(a[4],b[2],c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_3,b_3,t_1 !=!mul_add_c(a[3],b[3],c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_2,b_4,t_1 !=!mul_add_c(a[2],b[4],c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + lduw bp(6),b_6 != + mulx a_1,b_5,t_1 !mul_add_c(a[1],b[5],c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 != + lduw bp(7),b_7 + mulx a_0,b_6,t_1 !mul_add_c(a[0],b[6],c1,c2,c3); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(6) !r[6]=c1; + or c_12,c_3,c_12 != + + mulx a_0,b_7,t_1 !mul_add_c(a[0],b[7],c2,c3,c1); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_1,b_6,t_1 !mul_add_c(a[1],b[6],c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_2,b_5,t_1 !mul_add_c(a[2],b[5],c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_3,b_4,t_1 !mul_add_c(a[3],b[4],c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_4,b_3,t_1 !mul_add_c(a[4],b[3],c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_5,b_2,t_1 !mul_add_c(a[5],b[2],c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + lduw ap(7),a_7 + mulx a_6,b_1,t_1 !=!mul_add_c(a[6],b[1],c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_7,b_0,t_1 !=!mul_add_c(a[7],b[0],c2,c3,c1); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 != + stuw t_1,rp(7) !r[7]=c2; + or c_12,c_3,c_12 + + mulx a_7,b_1,t_1 !=!mul_add_c(a[7],b[1],c3,c1,c2); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 != + mulx a_6,b_2,t_1 !mul_add_c(a[6],b[2],c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 != + mulx a_5,b_3,t_1 !mul_add_c(a[5],b[3],c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 != + mulx a_4,b_4,t_1 !mul_add_c(a[4],b[4],c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 != + mulx a_3,b_5,t_1 !mul_add_c(a[3],b[5],c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 != + mulx a_2,b_6,t_1 !mul_add_c(a[2],b[6],c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 != + mulx a_1,b_7,t_1 !mul_add_c(a[1],b[7],c3,c1,c2); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 != + srlx t_1,32,c_12 + stuw t_1,rp(8) !r[8]=c3; + or c_12,c_3,c_12 + + mulx a_2,b_7,t_1 !=!mul_add_c(a[2],b[7],c1,c2,c3); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 != + mulx a_3,b_6,t_1 !mul_add_c(a[3],b[6],c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_4,b_5,t_1 !mul_add_c(a[4],b[5],c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_5,b_4,t_1 !mul_add_c(a[5],b[4],c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_6,b_3,t_1 !mul_add_c(a[6],b[3],c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_7,b_2,t_1 !mul_add_c(a[7],b[2],c1,c2,c3); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(9) !r[9]=c1; + or c_12,c_3,c_12 != + + mulx a_7,b_3,t_1 !mul_add_c(a[7],b[3],c2,c3,c1); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_6,b_4,t_1 !mul_add_c(a[6],b[4],c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_5,b_5,t_1 !mul_add_c(a[5],b[5],c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_4,b_6,t_1 !mul_add_c(a[4],b[6],c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_3,b_7,t_1 !mul_add_c(a[3],b[7],c2,c3,c1); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(10) !r[10]=c2; + or c_12,c_3,c_12 != + + mulx a_4,b_7,t_1 !mul_add_c(a[4],b[7],c3,c1,c2); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_5,b_6,t_1 !mul_add_c(a[5],b[6],c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_6,b_5,t_1 !mul_add_c(a[6],b[5],c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_7,b_4,t_1 !mul_add_c(a[7],b[4],c3,c1,c2); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(11) !r[11]=c3; + or c_12,c_3,c_12 != + + mulx a_7,b_5,t_1 !mul_add_c(a[7],b[5],c1,c2,c3); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_6,b_6,t_1 !mul_add_c(a[6],b[6],c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_5,b_7,t_1 !mul_add_c(a[5],b[7],c1,c2,c3); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(12) !r[12]=c1; + or c_12,c_3,c_12 != + + mulx a_6,b_7,t_1 !mul_add_c(a[6],b[7],c2,c3,c1); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_7,b_6,t_1 !mul_add_c(a[7],b[6],c2,c3,c1); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + srlx t_1,32,c_12 + st t_1,rp(13) !r[13]=c2; + or c_12,c_3,c_12 != + + mulx a_7,b_7,t_1 !mul_add_c(a[7],b[7],c3,c1,c2); + addcc c_12,t_1,t_1 + srlx t_1,32,c_12 != + stuw t_1,rp(14) !r[14]=c3; + stuw c_12,rp(15) !r[15]=c1; + + ret + restore %g0,%g0,%o0 != + +.type bn_mul_comba8,#function +.size bn_mul_comba8,(.-bn_mul_comba8) + +.align 32 + +.global bn_mul_comba4 +/* + * void bn_mul_comba4(r,a,b) + * BN_ULONG *r,*a,*b; + */ +bn_mul_comba4: + save %sp,FRAME_SIZE,%sp + lduw ap(0),a_0 + mov 1,t_2 + lduw bp(0),b_0 + sllx t_2,32,t_2 != + lduw bp(1),b_1 + mulx a_0,b_0,t_1 !mul_add_c(a[0],b[0],c1,c2,c3); + srlx t_1,32,c_12 + stuw t_1,rp(0) !=!r[0]=c1; + + lduw ap(1),a_1 + mulx a_0,b_1,t_1 !mul_add_c(a[0],b[1],c2,c3,c1); + addcc c_12,t_1,c_12 + clr c_3 != + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + lduw ap(2),a_2 + mulx a_1,b_0,t_1 !=!mul_add_c(a[1],b[0],c2,c3,c1); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 != + stuw t_1,rp(1) !r[1]=c2; + or c_12,c_3,c_12 + + mulx a_2,b_0,t_1 !mul_add_c(a[2],b[0],c3,c1,c2); + addcc c_12,t_1,c_12 != + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + lduw bp(2),b_2 != + mulx a_1,b_1,t_1 !mul_add_c(a[1],b[1],c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 != + lduw bp(3),b_3 + mulx a_0,b_2,t_1 !mul_add_c(a[0],b[2],c3,c1,c2); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(2) !r[2]=c3; + or c_12,c_3,c_12 != + + mulx a_0,b_3,t_1 !mul_add_c(a[0],b[3],c1,c2,c3); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_1,b_2,t_1 !mul_add_c(a[1],b[2],c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + lduw ap(3),a_3 + mulx a_2,b_1,t_1 !mul_add_c(a[2],b[1],c1,c2,c3); + addcc c_12,t_1,c_12 != + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_3,b_0,t_1 !mul_add_c(a[3],b[0],c1,c2,c3);!= + addcc c_12,t_1,t_1 != + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(3) !=!r[3]=c1; + or c_12,c_3,c_12 + + mulx a_3,b_1,t_1 !mul_add_c(a[3],b[1],c2,c3,c1); + addcc c_12,t_1,c_12 + clr c_3 != + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_2,b_2,t_1 !mul_add_c(a[2],b[2],c2,c3,c1); + addcc c_12,t_1,c_12 != + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_1,b_3,t_1 !mul_add_c(a[1],b[3],c2,c3,c1); + addcc c_12,t_1,t_1 != + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(4) !=!r[4]=c2; + or c_12,c_3,c_12 + + mulx a_2,b_3,t_1 !mul_add_c(a[2],b[3],c3,c1,c2); + addcc c_12,t_1,c_12 + clr c_3 != + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_3,b_2,t_1 !mul_add_c(a[3],b[2],c3,c1,c2); + addcc c_12,t_1,t_1 != + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(5) !=!r[5]=c3; + or c_12,c_3,c_12 + + mulx a_3,b_3,t_1 !mul_add_c(a[3],b[3],c1,c2,c3); + addcc c_12,t_1,t_1 + srlx t_1,32,c_12 != + stuw t_1,rp(6) !r[6]=c1; + stuw c_12,rp(7) !r[7]=c2; + + ret + restore %g0,%g0,%o0 + +.type bn_mul_comba4,#function +.size bn_mul_comba4,(.-bn_mul_comba4) + +.align 32 + +.global bn_sqr_comba8 +bn_sqr_comba8: + save %sp,FRAME_SIZE,%sp + mov 1,t_2 + lduw ap(0),a_0 + sllx t_2,32,t_2 + lduw ap(1),a_1 + mulx a_0,a_0,t_1 !sqr_add_c(a,0,c1,c2,c3); + srlx t_1,32,c_12 + stuw t_1,rp(0) !r[0]=c1; + + lduw ap(2),a_2 + mulx a_0,a_1,t_1 !=!sqr_add_c2(a,1,0,c2,c3,c1); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(1) !r[1]=c2; + or c_12,c_3,c_12 + + mulx a_2,a_0,t_1 !sqr_add_c2(a,2,0,c3,c1,c2); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + lduw ap(3),a_3 + mulx a_1,a_1,t_1 !sqr_add_c(a,1,c3,c1,c2); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(2) !r[2]=c3; + or c_12,c_3,c_12 + + mulx a_0,a_3,t_1 !sqr_add_c2(a,3,0,c1,c2,c3); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + lduw ap(4),a_4 + mulx a_1,a_2,t_1 !sqr_add_c2(a,2,1,c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + st t_1,rp(3) !r[3]=c1; + or c_12,c_3,c_12 + + mulx a_4,a_0,t_1 !sqr_add_c2(a,4,0,c2,c3,c1); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_3,a_1,t_1 !sqr_add_c2(a,3,1,c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + lduw ap(5),a_5 + mulx a_2,a_2,t_1 !sqr_add_c(a,2,c2,c3,c1); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(4) !r[4]=c2; + or c_12,c_3,c_12 + + mulx a_0,a_5,t_1 !sqr_add_c2(a,5,0,c3,c1,c2); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_1,a_4,t_1 !sqr_add_c2(a,4,1,c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + lduw ap(6),a_6 + mulx a_2,a_3,t_1 !sqr_add_c2(a,3,2,c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(5) !r[5]=c3; + or c_12,c_3,c_12 + + mulx a_6,a_0,t_1 !sqr_add_c2(a,6,0,c1,c2,c3); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_5,a_1,t_1 !sqr_add_c2(a,5,1,c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_4,a_2,t_1 !sqr_add_c2(a,4,2,c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + lduw ap(7),a_7 + mulx a_3,a_3,t_1 !=!sqr_add_c(a,3,c1,c2,c3); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(6) !r[6]=c1; + or c_12,c_3,c_12 + + mulx a_0,a_7,t_1 !sqr_add_c2(a,7,0,c2,c3,c1); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_1,a_6,t_1 !sqr_add_c2(a,6,1,c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_2,a_5,t_1 !sqr_add_c2(a,5,2,c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_3,a_4,t_1 !sqr_add_c2(a,4,3,c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(7) !r[7]=c2; + or c_12,c_3,c_12 + + mulx a_7,a_1,t_1 !sqr_add_c2(a,7,1,c3,c1,c2); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_6,a_2,t_1 !sqr_add_c2(a,6,2,c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_5,a_3,t_1 !sqr_add_c2(a,5,3,c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_4,a_4,t_1 !sqr_add_c(a,4,c3,c1,c2); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(8) !r[8]=c3; + or c_12,c_3,c_12 + + mulx a_2,a_7,t_1 !sqr_add_c2(a,7,2,c1,c2,c3); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_3,a_6,t_1 !sqr_add_c2(a,6,3,c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_4,a_5,t_1 !sqr_add_c2(a,5,4,c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(9) !r[9]=c1; + or c_12,c_3,c_12 + + mulx a_7,a_3,t_1 !sqr_add_c2(a,7,3,c2,c3,c1); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_6,a_4,t_1 !sqr_add_c2(a,6,4,c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_5,a_5,t_1 !sqr_add_c(a,5,c2,c3,c1); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(10) !r[10]=c2; + or c_12,c_3,c_12 + + mulx a_4,a_7,t_1 !sqr_add_c2(a,7,4,c3,c1,c2); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_5,a_6,t_1 !sqr_add_c2(a,6,5,c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(11) !r[11]=c3; + or c_12,c_3,c_12 + + mulx a_7,a_5,t_1 !sqr_add_c2(a,7,5,c1,c2,c3); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_6,a_6,t_1 !sqr_add_c(a,6,c1,c2,c3); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(12) !r[12]=c1; + or c_12,c_3,c_12 + + mulx a_6,a_7,t_1 !sqr_add_c2(a,7,6,c2,c3,c1); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(13) !r[13]=c2; + or c_12,c_3,c_12 + + mulx a_7,a_7,t_1 !sqr_add_c(a,7,c3,c1,c2); + addcc c_12,t_1,t_1 + srlx t_1,32,c_12 + stuw t_1,rp(14) !r[14]=c3; + stuw c_12,rp(15) !r[15]=c1; + + ret + restore %g0,%g0,%o0 + +.type bn_sqr_comba8,#function +.size bn_sqr_comba8,(.-bn_sqr_comba8) + +.align 32 + +.global bn_sqr_comba4 +/* + * void bn_sqr_comba4(r,a) + * BN_ULONG *r,*a; + */ +bn_sqr_comba4: + save %sp,FRAME_SIZE,%sp + mov 1,t_2 + lduw ap(0),a_0 + sllx t_2,32,t_2 + lduw ap(1),a_1 + mulx a_0,a_0,t_1 !sqr_add_c(a,0,c1,c2,c3); + srlx t_1,32,c_12 + stuw t_1,rp(0) !r[0]=c1; + + lduw ap(2),a_2 + mulx a_0,a_1,t_1 !sqr_add_c2(a,1,0,c2,c3,c1); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(1) !r[1]=c2; + or c_12,c_3,c_12 + + mulx a_2,a_0,t_1 !sqr_add_c2(a,2,0,c3,c1,c2); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + lduw ap(3),a_3 + mulx a_1,a_1,t_1 !sqr_add_c(a,1,c3,c1,c2); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(2) !r[2]=c3; + or c_12,c_3,c_12 + + mulx a_0,a_3,t_1 !sqr_add_c2(a,3,0,c1,c2,c3); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_1,a_2,t_1 !sqr_add_c2(a,2,1,c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(3) !r[3]=c1; + or c_12,c_3,c_12 + + mulx a_3,a_1,t_1 !sqr_add_c2(a,3,1,c2,c3,c1); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_2,a_2,t_1 !sqr_add_c(a,2,c2,c3,c1); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(4) !r[4]=c2; + or c_12,c_3,c_12 + + mulx a_2,a_3,t_1 !sqr_add_c2(a,3,2,c3,c1,c2); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(5) !r[5]=c3; + or c_12,c_3,c_12 + + mulx a_3,a_3,t_1 !sqr_add_c(a,3,c1,c2,c3); + addcc c_12,t_1,t_1 + srlx t_1,32,c_12 + stuw t_1,rp(6) !r[6]=c1; + stuw c_12,rp(7) !r[7]=c2; + + ret + restore %g0,%g0,%o0 + +.type bn_sqr_comba4,#function +.size bn_sqr_comba4,(.-bn_sqr_comba4) + +.align 32 diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/sparcv9-gf2m.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/sparcv9-gf2m.pl new file mode 100644 index 000000000..dcf11a87a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/sparcv9-gf2m.pl @@ -0,0 +1,200 @@ +#! /usr/bin/env perl +# Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# October 2012 +# +# The module implements bn_GF2m_mul_2x2 polynomial multiplication used +# in bn_gf2m.c. It's kind of low-hanging mechanical port from C for +# the time being... Except that it has two code paths: one suitable +# for all SPARCv9 processors and one for VIS3-capable ones. Former +# delivers ~25-45% more, more for longer keys, heaviest DH and DSA +# verify operations on venerable UltraSPARC II. On T4 VIS3 code is +# ~100-230% faster than gcc-generated code and ~35-90% faster than +# the pure SPARCv9 code path. + +$output = pop; +open STDOUT,">$output"; + +$locals=16*8; + +$tab="%l0"; + +@T=("%g2","%g3"); +@i=("%g4","%g5"); + +($a1,$a2,$a4,$a8,$a12,$a48)=map("%o$_",(0..5)); +($lo,$hi,$b)=("%g1",$a8,"%o7"); $a=$lo; + +$code.=<<___; +#include + +#ifdef __arch64__ +.register %g2,#scratch +.register %g3,#scratch +#endif + +#ifdef __PIC__ +SPARC_PIC_THUNK(%g1) +#endif + +.globl bn_GF2m_mul_2x2 +.align 16 +bn_GF2m_mul_2x2: + SPARC_LOAD_ADDRESS_LEAF(OPENSSL_sparcv9cap_P,%g1,%g5) + ld [%g1+0],%g1 ! OPENSSL_sparcv9cap_P[0] + + andcc %g1, SPARCV9_VIS3, %g0 + bz,pn %icc,.Lsoftware + nop + + sllx %o1, 32, %o1 + sllx %o3, 32, %o3 + or %o2, %o1, %o1 + or %o4, %o3, %o3 + .word 0x95b262ab ! xmulx %o1, %o3, %o2 + .word 0x99b262cb ! xmulxhi %o1, %o3, %o4 + srlx %o2, 32, %o1 ! 13 cycles later + st %o2, [%o0+0] + st %o1, [%o0+4] + srlx %o4, 32, %o3 + st %o4, [%o0+8] + retl + st %o3, [%o0+12] + +.align 16 +.Lsoftware: + save %sp,-STACK_FRAME-$locals,%sp + + sllx %i1,32,$a + mov -1,$a12 + sllx %i3,32,$b + or %i2,$a,$a + srlx $a12,1,$a48 ! 0x7fff... + or %i4,$b,$b + srlx $a12,2,$a12 ! 0x3fff... + add %sp,STACK_BIAS+STACK_FRAME,$tab + + sllx $a,2,$a4 + mov $a,$a1 + sllx $a,1,$a2 + + srax $a4,63,@i[1] ! broadcast 61st bit + and $a48,$a4,$a4 ! (a<<2)&0x7fff... + srlx $a48,2,$a48 + srax $a2,63,@i[0] ! broadcast 62nd bit + and $a12,$a2,$a2 ! (a<<1)&0x3fff... + srax $a1,63,$lo ! broadcast 63rd bit + and $a48,$a1,$a1 ! (a<<0)&0x1fff... + + sllx $a1,3,$a8 + and $b,$lo,$lo + and $b,@i[0],@i[0] + and $b,@i[1],@i[1] + + stx %g0,[$tab+0*8] ! tab[0]=0 + xor $a1,$a2,$a12 + stx $a1,[$tab+1*8] ! tab[1]=a1 + stx $a2,[$tab+2*8] ! tab[2]=a2 + xor $a4,$a8,$a48 + stx $a12,[$tab+3*8] ! tab[3]=a1^a2 + xor $a4,$a1,$a1 + + stx $a4,[$tab+4*8] ! tab[4]=a4 + xor $a4,$a2,$a2 + stx $a1,[$tab+5*8] ! tab[5]=a1^a4 + xor $a4,$a12,$a12 + stx $a2,[$tab+6*8] ! tab[6]=a2^a4 + xor $a48,$a1,$a1 + stx $a12,[$tab+7*8] ! tab[7]=a1^a2^a4 + xor $a48,$a2,$a2 + + stx $a8,[$tab+8*8] ! tab[8]=a8 + xor $a48,$a12,$a12 + stx $a1,[$tab+9*8] ! tab[9]=a1^a8 + xor $a4,$a1,$a1 + stx $a2,[$tab+10*8] ! tab[10]=a2^a8 + xor $a4,$a2,$a2 + stx $a12,[$tab+11*8] ! tab[11]=a1^a2^a8 + + xor $a4,$a12,$a12 + stx $a48,[$tab+12*8] ! tab[12]=a4^a8 + srlx $lo,1,$hi + stx $a1,[$tab+13*8] ! tab[13]=a1^a4^a8 + sllx $lo,63,$lo + stx $a2,[$tab+14*8] ! tab[14]=a2^a4^a8 + srlx @i[0],2,@T[0] + stx $a12,[$tab+15*8] ! tab[15]=a1^a2^a4^a8 + + sllx @i[0],62,$a1 + sllx $b,3,@i[0] + srlx @i[1],3,@T[1] + and @i[0],`0xf<<3`,@i[0] + sllx @i[1],61,$a2 + ldx [$tab+@i[0]],@i[0] + srlx $b,4-3,@i[1] + xor @T[0],$hi,$hi + and @i[1],`0xf<<3`,@i[1] + xor $a1,$lo,$lo + ldx [$tab+@i[1]],@i[1] + xor @T[1],$hi,$hi + + xor @i[0],$lo,$lo + srlx $b,8-3,@i[0] + xor $a2,$lo,$lo + and @i[0],`0xf<<3`,@i[0] +___ +for($n=1;$n<14;$n++) { +$code.=<<___; + sllx @i[1],`$n*4`,@T[0] + ldx [$tab+@i[0]],@i[0] + srlx @i[1],`64-$n*4`,@T[1] + xor @T[0],$lo,$lo + srlx $b,`($n+2)*4`-3,@i[1] + xor @T[1],$hi,$hi + and @i[1],`0xf<<3`,@i[1] +___ + push(@i,shift(@i)); push(@T,shift(@T)); +} +$code.=<<___; + sllx @i[1],`$n*4`,@T[0] + ldx [$tab+@i[0]],@i[0] + srlx @i[1],`64-$n*4`,@T[1] + xor @T[0],$lo,$lo + + sllx @i[0],`($n+1)*4`,@T[0] + xor @T[1],$hi,$hi + srlx @i[0],`64-($n+1)*4`,@T[1] + xor @T[0],$lo,$lo + xor @T[1],$hi,$hi + + srlx $lo,32,%i1 + st $lo,[%i0+0] + st %i1,[%i0+4] + srlx $hi,32,%i2 + st $hi,[%i0+8] + st %i2,[%i0+12] + + ret + restore +.type bn_GF2m_mul_2x2,#function +.size bn_GF2m_mul_2x2,.-bn_GF2m_mul_2x2 +.asciz "GF(2^m) Multiplication for SPARCv9, CRYPTOGAMS by " +.align 4 +___ + +$code =~ s/\`([^\`]*)\`/eval($1)/gem; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/sparcv9-mont.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/sparcv9-mont.pl new file mode 100644 index 000000000..b41903af9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/sparcv9-mont.pl @@ -0,0 +1,620 @@ +#! /usr/bin/env perl +# Copyright 2005-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# December 2005 +# +# Pure SPARCv9/8+ and IALU-only bn_mul_mont implementation. The reasons +# for undertaken effort are multiple. First of all, UltraSPARC is not +# the whole SPARCv9 universe and other VIS-free implementations deserve +# optimized code as much. Secondly, newly introduced UltraSPARC T1, +# a.k.a. Niagara, has shared FPU and concurrent FPU-intensive paths, +# such as sparcv9a-mont, will simply sink it. Yes, T1 is equipped with +# several integrated RSA/DSA accelerator circuits accessible through +# kernel driver [only(*)], but having decent user-land software +# implementation is important too. Finally, reasons like desire to +# experiment with dedicated squaring procedure. Yes, this module +# implements one, because it was easiest to draft it in SPARCv9 +# instructions... + +# (*) Engine accessing the driver in question is on my TODO list. +# For reference, accelerator is estimated to give 6 to 10 times +# improvement on single-threaded RSA sign. It should be noted +# that 6-10x improvement coefficient does not actually mean +# something extraordinary in terms of absolute [single-threaded] +# performance, as SPARCv9 instruction set is by all means least +# suitable for high performance crypto among other 64 bit +# platforms. 6-10x factor simply places T1 in same performance +# domain as say AMD64 and IA-64. Improvement of RSA verify don't +# appear impressive at all, but it's the sign operation which is +# far more critical/interesting. + +# You might notice that inner loops are modulo-scheduled:-) This has +# essentially negligible impact on UltraSPARC performance, it's +# Fujitsu SPARC64 V users who should notice and hopefully appreciate +# the advantage... Currently this module surpasses sparcv9a-mont.pl +# by ~20% on UltraSPARC-III and later cores, but recall that sparcv9a +# module still have hidden potential [see TODO list there], which is +# estimated to be larger than 20%... + +$output = pop; +open STDOUT,">$output"; + +# int bn_mul_mont( +$rp="%i0"; # BN_ULONG *rp, +$ap="%i1"; # const BN_ULONG *ap, +$bp="%i2"; # const BN_ULONG *bp, +$np="%i3"; # const BN_ULONG *np, +$n0="%i4"; # const BN_ULONG *n0, +$num="%i5"; # int num); + +$frame="STACK_FRAME"; +$bias="STACK_BIAS"; + +$car0="%o0"; +$car1="%o1"; +$car2="%o2"; # 1 bit +$acc0="%o3"; +$acc1="%o4"; +$mask="%g1"; # 32 bits, what a waste... +$tmp0="%g4"; +$tmp1="%g5"; + +$i="%l0"; +$j="%l1"; +$mul0="%l2"; +$mul1="%l3"; +$tp="%l4"; +$apj="%l5"; +$npj="%l6"; +$tpj="%l7"; + +$fname="bn_mul_mont_int"; + +$code=<<___; +#include "sparc_arch.h" + +.section ".text",#alloc,#execinstr + +.global $fname +.align 32 +$fname: + cmp %o5,4 ! 128 bits minimum + bge,pt %icc,.Lenter + sethi %hi(0xffffffff),$mask + retl + clr %o0 +.align 32 +.Lenter: + save %sp,-$frame,%sp + sll $num,2,$num ! num*=4 + or $mask,%lo(0xffffffff),$mask + ld [$n0],$n0 + cmp $ap,$bp + and $num,$mask,$num + ld [$bp],$mul0 ! bp[0] + nop + + add %sp,$bias,%o7 ! real top of stack + ld [$ap],$car0 ! ap[0] ! redundant in squaring context + sub %o7,$num,%o7 + ld [$ap+4],$apj ! ap[1] + and %o7,-1024,%o7 + ld [$np],$car1 ! np[0] + sub %o7,$bias,%sp ! alloca + ld [$np+4],$npj ! np[1] + be,pt SIZE_T_CC,.Lbn_sqr_mont + mov 12,$j + + mulx $car0,$mul0,$car0 ! ap[0]*bp[0] + mulx $apj,$mul0,$tmp0 !prologue! ap[1]*bp[0] + and $car0,$mask,$acc0 + add %sp,$bias+$frame,$tp + ld [$ap+8],$apj !prologue! + + mulx $n0,$acc0,$mul1 ! "t[0]"*n0 + and $mul1,$mask,$mul1 + + mulx $car1,$mul1,$car1 ! np[0]*"t[0]"*n0 + mulx $npj,$mul1,$acc1 !prologue! np[1]*"t[0]"*n0 + srlx $car0,32,$car0 + add $acc0,$car1,$car1 + ld [$np+8],$npj !prologue! + srlx $car1,32,$car1 + mov $tmp0,$acc0 !prologue! + +.L1st: + mulx $apj,$mul0,$tmp0 + mulx $npj,$mul1,$tmp1 + add $acc0,$car0,$car0 + ld [$ap+$j],$apj ! ap[j] + and $car0,$mask,$acc0 + add $acc1,$car1,$car1 + ld [$np+$j],$npj ! np[j] + srlx $car0,32,$car0 + add $acc0,$car1,$car1 + add $j,4,$j ! j++ + mov $tmp0,$acc0 + st $car1,[$tp] + cmp $j,$num + mov $tmp1,$acc1 + srlx $car1,32,$car1 + bl %icc,.L1st + add $tp,4,$tp ! tp++ +!.L1st + + mulx $apj,$mul0,$tmp0 !epilogue! + mulx $npj,$mul1,$tmp1 + add $acc0,$car0,$car0 + and $car0,$mask,$acc0 + add $acc1,$car1,$car1 + srlx $car0,32,$car0 + add $acc0,$car1,$car1 + st $car1,[$tp] + srlx $car1,32,$car1 + + add $tmp0,$car0,$car0 + and $car0,$mask,$acc0 + add $tmp1,$car1,$car1 + srlx $car0,32,$car0 + add $acc0,$car1,$car1 + st $car1,[$tp+4] + srlx $car1,32,$car1 + + add $car0,$car1,$car1 + st $car1,[$tp+8] + srlx $car1,32,$car2 + + mov 4,$i ! i++ + ld [$bp+4],$mul0 ! bp[1] +.Louter: + add %sp,$bias+$frame,$tp + ld [$ap],$car0 ! ap[0] + ld [$ap+4],$apj ! ap[1] + ld [$np],$car1 ! np[0] + ld [$np+4],$npj ! np[1] + ld [$tp],$tmp1 ! tp[0] + ld [$tp+4],$tpj ! tp[1] + mov 12,$j + + mulx $car0,$mul0,$car0 + mulx $apj,$mul0,$tmp0 !prologue! + add $tmp1,$car0,$car0 + ld [$ap+8],$apj !prologue! + and $car0,$mask,$acc0 + + mulx $n0,$acc0,$mul1 + and $mul1,$mask,$mul1 + + mulx $car1,$mul1,$car1 + mulx $npj,$mul1,$acc1 !prologue! + srlx $car0,32,$car0 + add $acc0,$car1,$car1 + ld [$np+8],$npj !prologue! + srlx $car1,32,$car1 + mov $tmp0,$acc0 !prologue! + +.Linner: + mulx $apj,$mul0,$tmp0 + mulx $npj,$mul1,$tmp1 + add $tpj,$car0,$car0 + ld [$ap+$j],$apj ! ap[j] + add $acc0,$car0,$car0 + add $acc1,$car1,$car1 + ld [$np+$j],$npj ! np[j] + and $car0,$mask,$acc0 + ld [$tp+8],$tpj ! tp[j] + srlx $car0,32,$car0 + add $acc0,$car1,$car1 + add $j,4,$j ! j++ + mov $tmp0,$acc0 + st $car1,[$tp] ! tp[j-1] + srlx $car1,32,$car1 + mov $tmp1,$acc1 + cmp $j,$num + bl %icc,.Linner + add $tp,4,$tp ! tp++ +!.Linner + + mulx $apj,$mul0,$tmp0 !epilogue! + mulx $npj,$mul1,$tmp1 + add $tpj,$car0,$car0 + add $acc0,$car0,$car0 + ld [$tp+8],$tpj ! tp[j] + and $car0,$mask,$acc0 + add $acc1,$car1,$car1 + srlx $car0,32,$car0 + add $acc0,$car1,$car1 + st $car1,[$tp] ! tp[j-1] + srlx $car1,32,$car1 + + add $tpj,$car0,$car0 + add $tmp0,$car0,$car0 + and $car0,$mask,$acc0 + add $tmp1,$car1,$car1 + add $acc0,$car1,$car1 + st $car1,[$tp+4] ! tp[j-1] + srlx $car0,32,$car0 + add $i,4,$i ! i++ + srlx $car1,32,$car1 + + add $car0,$car1,$car1 + cmp $i,$num + add $car2,$car1,$car1 + st $car1,[$tp+8] + + srlx $car1,32,$car2 + bl,a %icc,.Louter + ld [$bp+$i],$mul0 ! bp[i] +!.Louter + + add $tp,12,$tp + +.Ltail: + add $np,$num,$np + add $rp,$num,$rp + sub %g0,$num,%o7 ! k=-num + ba .Lsub + subcc %g0,%g0,%g0 ! clear %icc.c +.align 16 +.Lsub: + ld [$tp+%o7],%o0 + ld [$np+%o7],%o1 + subccc %o0,%o1,%o1 ! tp[j]-np[j] + add $rp,%o7,$i + add %o7,4,%o7 + brnz %o7,.Lsub + st %o1,[$i] + subccc $car2,0,$car2 ! handle upmost overflow bit + sub %g0,$num,%o7 + +.Lcopy: + ld [$tp+%o7],%o1 ! conditional copy + ld [$rp+%o7],%o0 + st %g0,[$tp+%o7] ! zap tp + movcs %icc,%o1,%o0 + st %o0,[$rp+%o7] + add %o7,4,%o7 + brnz %o7,.Lcopy + nop + mov 1,%i0 + ret + restore +___ + +######## +######## .Lbn_sqr_mont gives up to 20% *overall* improvement over +######## code without following dedicated squaring procedure. +######## +$sbit="%o5"; + +$code.=<<___; +.align 32 +.Lbn_sqr_mont: + mulx $mul0,$mul0,$car0 ! ap[0]*ap[0] + mulx $apj,$mul0,$tmp0 !prologue! + and $car0,$mask,$acc0 + add %sp,$bias+$frame,$tp + ld [$ap+8],$apj !prologue! + + mulx $n0,$acc0,$mul1 ! "t[0]"*n0 + srlx $car0,32,$car0 + and $mul1,$mask,$mul1 + + mulx $car1,$mul1,$car1 ! np[0]*"t[0]"*n0 + mulx $npj,$mul1,$acc1 !prologue! + and $car0,1,$sbit + ld [$np+8],$npj !prologue! + srlx $car0,1,$car0 + add $acc0,$car1,$car1 + srlx $car1,32,$car1 + mov $tmp0,$acc0 !prologue! + +.Lsqr_1st: + mulx $apj,$mul0,$tmp0 + mulx $npj,$mul1,$tmp1 + add $acc0,$car0,$car0 ! ap[j]*a0+c0 + add $acc1,$car1,$car1 + ld [$ap+$j],$apj ! ap[j] + and $car0,$mask,$acc0 + ld [$np+$j],$npj ! np[j] + srlx $car0,32,$car0 + add $acc0,$acc0,$acc0 + or $sbit,$acc0,$acc0 + mov $tmp1,$acc1 + srlx $acc0,32,$sbit + add $j,4,$j ! j++ + and $acc0,$mask,$acc0 + cmp $j,$num + add $acc0,$car1,$car1 + st $car1,[$tp] + mov $tmp0,$acc0 + srlx $car1,32,$car1 + bl %icc,.Lsqr_1st + add $tp,4,$tp ! tp++ +!.Lsqr_1st + + mulx $apj,$mul0,$tmp0 ! epilogue + mulx $npj,$mul1,$tmp1 + add $acc0,$car0,$car0 ! ap[j]*a0+c0 + add $acc1,$car1,$car1 + and $car0,$mask,$acc0 + srlx $car0,32,$car0 + add $acc0,$acc0,$acc0 + or $sbit,$acc0,$acc0 + srlx $acc0,32,$sbit + and $acc0,$mask,$acc0 + add $acc0,$car1,$car1 + st $car1,[$tp] + srlx $car1,32,$car1 + + add $tmp0,$car0,$car0 ! ap[j]*a0+c0 + add $tmp1,$car1,$car1 + and $car0,$mask,$acc0 + srlx $car0,32,$car0 + add $acc0,$acc0,$acc0 + or $sbit,$acc0,$acc0 + srlx $acc0,32,$sbit + and $acc0,$mask,$acc0 + add $acc0,$car1,$car1 + st $car1,[$tp+4] + srlx $car1,32,$car1 + + add $car0,$car0,$car0 + or $sbit,$car0,$car0 + add $car0,$car1,$car1 + st $car1,[$tp+8] + srlx $car1,32,$car2 + + ld [%sp+$bias+$frame],$tmp0 ! tp[0] + ld [%sp+$bias+$frame+4],$tmp1 ! tp[1] + ld [%sp+$bias+$frame+8],$tpj ! tp[2] + ld [$ap+4],$mul0 ! ap[1] + ld [$ap+8],$apj ! ap[2] + ld [$np],$car1 ! np[0] + ld [$np+4],$npj ! np[1] + mulx $n0,$tmp0,$mul1 + + mulx $mul0,$mul0,$car0 + and $mul1,$mask,$mul1 + + mulx $car1,$mul1,$car1 + mulx $npj,$mul1,$acc1 + add $tmp0,$car1,$car1 + and $car0,$mask,$acc0 + ld [$np+8],$npj ! np[2] + srlx $car1,32,$car1 + add $tmp1,$car1,$car1 + srlx $car0,32,$car0 + add $acc0,$car1,$car1 + and $car0,1,$sbit + add $acc1,$car1,$car1 + srlx $car0,1,$car0 + mov 12,$j + st $car1,[%sp+$bias+$frame] ! tp[0]= + srlx $car1,32,$car1 + add %sp,$bias+$frame+4,$tp + +.Lsqr_2nd: + mulx $apj,$mul0,$acc0 + mulx $npj,$mul1,$acc1 + add $acc0,$car0,$car0 + add $tpj,$sbit,$sbit + ld [$ap+$j],$apj ! ap[j] + and $car0,$mask,$acc0 + ld [$np+$j],$npj ! np[j] + srlx $car0,32,$car0 + add $acc1,$car1,$car1 + ld [$tp+8],$tpj ! tp[j] + add $acc0,$acc0,$acc0 + add $j,4,$j ! j++ + add $sbit,$acc0,$acc0 + srlx $acc0,32,$sbit + and $acc0,$mask,$acc0 + cmp $j,$num + add $acc0,$car1,$car1 + st $car1,[$tp] ! tp[j-1] + srlx $car1,32,$car1 + bl %icc,.Lsqr_2nd + add $tp,4,$tp ! tp++ +!.Lsqr_2nd + + mulx $apj,$mul0,$acc0 + mulx $npj,$mul1,$acc1 + add $acc0,$car0,$car0 + add $tpj,$sbit,$sbit + and $car0,$mask,$acc0 + srlx $car0,32,$car0 + add $acc1,$car1,$car1 + add $acc0,$acc0,$acc0 + add $sbit,$acc0,$acc0 + srlx $acc0,32,$sbit + and $acc0,$mask,$acc0 + add $acc0,$car1,$car1 + st $car1,[$tp] ! tp[j-1] + srlx $car1,32,$car1 + + add $car0,$car0,$car0 + add $sbit,$car0,$car0 + add $car0,$car1,$car1 + add $car2,$car1,$car1 + st $car1,[$tp+4] + srlx $car1,32,$car2 + + ld [%sp+$bias+$frame],$tmp1 ! tp[0] + ld [%sp+$bias+$frame+4],$tpj ! tp[1] + ld [$ap+8],$mul0 ! ap[2] + ld [$np],$car1 ! np[0] + ld [$np+4],$npj ! np[1] + mulx $n0,$tmp1,$mul1 + and $mul1,$mask,$mul1 + mov 8,$i + + mulx $mul0,$mul0,$car0 + mulx $car1,$mul1,$car1 + and $car0,$mask,$acc0 + add $tmp1,$car1,$car1 + srlx $car0,32,$car0 + add %sp,$bias+$frame,$tp + srlx $car1,32,$car1 + and $car0,1,$sbit + srlx $car0,1,$car0 + mov 4,$j + +.Lsqr_outer: +.Lsqr_inner1: + mulx $npj,$mul1,$acc1 + add $tpj,$car1,$car1 + add $j,4,$j + ld [$tp+8],$tpj + cmp $j,$i + add $acc1,$car1,$car1 + ld [$np+$j],$npj + st $car1,[$tp] + srlx $car1,32,$car1 + bl %icc,.Lsqr_inner1 + add $tp,4,$tp +!.Lsqr_inner1 + + add $j,4,$j + ld [$ap+$j],$apj ! ap[j] + mulx $npj,$mul1,$acc1 + add $tpj,$car1,$car1 + ld [$np+$j],$npj ! np[j] + srlx $car1,32,$tmp0 + and $car1,$mask,$car1 + add $tmp0,$sbit,$sbit + add $acc0,$car1,$car1 + ld [$tp+8],$tpj ! tp[j] + add $acc1,$car1,$car1 + st $car1,[$tp] + srlx $car1,32,$car1 + + add $j,4,$j + cmp $j,$num + be,pn %icc,.Lsqr_no_inner2 + add $tp,4,$tp + +.Lsqr_inner2: + mulx $apj,$mul0,$acc0 + mulx $npj,$mul1,$acc1 + add $tpj,$sbit,$sbit + add $acc0,$car0,$car0 + ld [$ap+$j],$apj ! ap[j] + and $car0,$mask,$acc0 + ld [$np+$j],$npj ! np[j] + srlx $car0,32,$car0 + add $acc0,$acc0,$acc0 + ld [$tp+8],$tpj ! tp[j] + add $sbit,$acc0,$acc0 + add $j,4,$j ! j++ + srlx $acc0,32,$sbit + and $acc0,$mask,$acc0 + cmp $j,$num + add $acc0,$car1,$car1 + add $acc1,$car1,$car1 + st $car1,[$tp] ! tp[j-1] + srlx $car1,32,$car1 + bl %icc,.Lsqr_inner2 + add $tp,4,$tp ! tp++ + +.Lsqr_no_inner2: + mulx $apj,$mul0,$acc0 + mulx $npj,$mul1,$acc1 + add $tpj,$sbit,$sbit + add $acc0,$car0,$car0 + and $car0,$mask,$acc0 + srlx $car0,32,$car0 + add $acc0,$acc0,$acc0 + add $sbit,$acc0,$acc0 + srlx $acc0,32,$sbit + and $acc0,$mask,$acc0 + add $acc0,$car1,$car1 + add $acc1,$car1,$car1 + st $car1,[$tp] ! tp[j-1] + srlx $car1,32,$car1 + + add $car0,$car0,$car0 + add $sbit,$car0,$car0 + add $car0,$car1,$car1 + add $car2,$car1,$car1 + st $car1,[$tp+4] + srlx $car1,32,$car2 + + add $i,4,$i ! i++ + ld [%sp+$bias+$frame],$tmp1 ! tp[0] + ld [%sp+$bias+$frame+4],$tpj ! tp[1] + ld [$ap+$i],$mul0 ! ap[j] + ld [$np],$car1 ! np[0] + ld [$np+4],$npj ! np[1] + mulx $n0,$tmp1,$mul1 + and $mul1,$mask,$mul1 + add $i,4,$tmp0 + + mulx $mul0,$mul0,$car0 + mulx $car1,$mul1,$car1 + and $car0,$mask,$acc0 + add $tmp1,$car1,$car1 + srlx $car0,32,$car0 + add %sp,$bias+$frame,$tp + srlx $car1,32,$car1 + and $car0,1,$sbit + srlx $car0,1,$car0 + + cmp $tmp0,$num ! i" +.align 32 +___ +$code =~ s/\`([^\`]*)\`/eval($1)/gem; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/sparcv9a-mont.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/sparcv9a-mont.pl new file mode 100755 index 000000000..c8f759df9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/sparcv9a-mont.pl @@ -0,0 +1,887 @@ +#! /usr/bin/env perl +# Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# October 2005 +# +# "Teaser" Montgomery multiplication module for UltraSPARC. Why FPU? +# Because unlike integer multiplier, which simply stalls whole CPU, +# FPU is fully pipelined and can effectively emit 48 bit partial +# product every cycle. Why not blended SPARC v9? One can argue that +# making this module dependent on UltraSPARC VIS extension limits its +# binary compatibility. Well yes, it does exclude SPARC64 prior-V(!) +# implementations from compatibility matrix. But the rest, whole Sun +# UltraSPARC family and brand new Fujitsu's SPARC64 V, all support +# VIS extension instructions used in this module. This is considered +# good enough to not care about HAL SPARC64 users [if any] who have +# integer-only pure SPARCv9 module to "fall down" to. + +# USI&II cores currently exhibit uniform 2x improvement [over pre- +# bn_mul_mont codebase] for all key lengths and benchmarks. On USIII +# performance improves few percents for shorter keys and worsens few +# percents for longer keys. This is because USIII integer multiplier +# is >3x faster than USI&II one, which is harder to match [but see +# TODO list below]. It should also be noted that SPARC64 V features +# out-of-order execution, which *might* mean that integer multiplier +# is pipelined, which in turn *might* be impossible to match... On +# additional note, SPARC64 V implements FP Multiply-Add instruction, +# which is perfectly usable in this context... In other words, as far +# as Fujitsu SPARC64 V goes, talk to the author:-) + +# The implementation implies following "non-natural" limitations on +# input arguments: +# - num may not be less than 4; +# - num has to be even; +# Failure to meet either condition has no fatal effects, simply +# doesn't give any performance gain. + +# TODO: +# - modulo-schedule inner loop for better performance (on in-order +# execution core such as UltraSPARC this shall result in further +# noticeable(!) improvement); +# - dedicated squaring procedure[?]; + +###################################################################### +# November 2006 +# +# Modulo-scheduled inner loops allow to interleave floating point and +# integer instructions and minimize Read-After-Write penalties. This +# results in *further* 20-50% performance improvement [depending on +# key length, more for longer keys] on USI&II cores and 30-80% - on +# USIII&IV. + +$output = pop; +open STDOUT,">$output"; + +$fname="bn_mul_mont_fpu"; + +$frame="STACK_FRAME"; +$bias="STACK_BIAS"; +$locals=64; + +# In order to provide for 32-/64-bit ABI duality, I keep integers wider +# than 32 bit in %g1-%g4 and %o0-%o5. %l0-%l7 and %i0-%i5 are used +# exclusively for pointers, indexes and other small values... +# int bn_mul_mont( +$rp="%i0"; # BN_ULONG *rp, +$ap="%i1"; # const BN_ULONG *ap, +$bp="%i2"; # const BN_ULONG *bp, +$np="%i3"; # const BN_ULONG *np, +$n0="%i4"; # const BN_ULONG *n0, +$num="%i5"; # int num); + +$tp="%l0"; # t[num] +$ap_l="%l1"; # a[num],n[num] are smashed to 32-bit words and saved +$ap_h="%l2"; # to these four vectors as double-precision FP values. +$np_l="%l3"; # This way a bunch of fxtods are eliminated in second +$np_h="%l4"; # loop and L1-cache aliasing is minimized... +$i="%l5"; +$j="%l6"; +$mask="%l7"; # 16-bit mask, 0xffff + +$n0="%g4"; # reassigned(!) to "64-bit" register +$carry="%i4"; # %i4 reused(!) for a carry bit + +# FP register naming chart +# +# ..HILO +# dcba +# -------- +# LOa +# LOb +# LOc +# LOd +# HIa +# HIb +# HIc +# HId +# ..a +# ..b +$ba="%f0"; $bb="%f2"; $bc="%f4"; $bd="%f6"; +$na="%f8"; $nb="%f10"; $nc="%f12"; $nd="%f14"; +$alo="%f16"; $alo_="%f17"; $ahi="%f18"; $ahi_="%f19"; +$nlo="%f20"; $nlo_="%f21"; $nhi="%f22"; $nhi_="%f23"; + +$dota="%f24"; $dotb="%f26"; + +$aloa="%f32"; $alob="%f34"; $aloc="%f36"; $alod="%f38"; +$ahia="%f40"; $ahib="%f42"; $ahic="%f44"; $ahid="%f46"; +$nloa="%f48"; $nlob="%f50"; $nloc="%f52"; $nlod="%f54"; +$nhia="%f56"; $nhib="%f58"; $nhic="%f60"; $nhid="%f62"; + +$ASI_FL16_P=0xD2; # magic ASI value to engage 16-bit FP load + +$code=<<___; +#include "sparc_arch.h" + +.section ".text",#alloc,#execinstr + +.global $fname +.align 32 +$fname: + save %sp,-$frame-$locals,%sp + + cmp $num,4 + bl,a,pn %icc,.Lret + clr %i0 + andcc $num,1,%g0 ! $num has to be even... + bnz,a,pn %icc,.Lret + clr %i0 ! signal "unsupported input value" + + srl $num,1,$num + sethi %hi(0xffff),$mask + ld [%i4+0],$n0 ! $n0 reassigned, remember? + or $mask,%lo(0xffff),$mask + ld [%i4+4],%o0 + sllx %o0,32,%o0 + or %o0,$n0,$n0 ! $n0=n0[1].n0[0] + + sll $num,3,$num ! num*=8 + + add %sp,$bias,%o0 ! real top of stack + sll $num,2,%o1 + add %o1,$num,%o1 ! %o1=num*5 + sub %o0,%o1,%o0 + and %o0,-2048,%o0 ! optimize TLB utilization + sub %o0,$bias,%sp ! alloca(5*num*8) + + rd %asi,%o7 ! save %asi + add %sp,$bias+$frame+$locals,$tp + add $tp,$num,$ap_l + add $ap_l,$num,$ap_l ! [an]p_[lh] point at the vectors' ends ! + add $ap_l,$num,$ap_h + add $ap_h,$num,$np_l + add $np_l,$num,$np_h + + wr %g0,$ASI_FL16_P,%asi ! setup %asi for 16-bit FP loads + + add $rp,$num,$rp ! readjust input pointers to point + add $ap,$num,$ap ! at the ends too... + add $bp,$num,$bp + add $np,$num,$np + + stx %o7,[%sp+$bias+$frame+48] ! save %asi + + sub %g0,$num,$i ! i=-num + sub %g0,$num,$j ! j=-num + + add $ap,$j,%o3 + add $bp,$i,%o4 + + ld [%o3+4],%g1 ! bp[0] + ld [%o3+0],%o0 + ld [%o4+4],%g5 ! ap[0] + sllx %g1,32,%g1 + ld [%o4+0],%o1 + sllx %g5,32,%g5 + or %g1,%o0,%o0 + or %g5,%o1,%o1 + + add $np,$j,%o5 + + mulx %o1,%o0,%o0 ! ap[0]*bp[0] + mulx $n0,%o0,%o0 ! ap[0]*bp[0]*n0 + stx %o0,[%sp+$bias+$frame+0] + + ld [%o3+0],$alo_ ! load a[j] as pair of 32-bit words + fzeros $alo + ld [%o3+4],$ahi_ + fzeros $ahi + ld [%o5+0],$nlo_ ! load n[j] as pair of 32-bit words + fzeros $nlo + ld [%o5+4],$nhi_ + fzeros $nhi + + ! transfer b[i] to FPU as 4x16-bit values + ldda [%o4+2]%asi,$ba + fxtod $alo,$alo + ldda [%o4+0]%asi,$bb + fxtod $ahi,$ahi + ldda [%o4+6]%asi,$bc + fxtod $nlo,$nlo + ldda [%o4+4]%asi,$bd + fxtod $nhi,$nhi + + ! transfer ap[0]*b[0]*n0 to FPU as 4x16-bit values + ldda [%sp+$bias+$frame+6]%asi,$na + fxtod $ba,$ba + ldda [%sp+$bias+$frame+4]%asi,$nb + fxtod $bb,$bb + ldda [%sp+$bias+$frame+2]%asi,$nc + fxtod $bc,$bc + ldda [%sp+$bias+$frame+0]%asi,$nd + fxtod $bd,$bd + + std $alo,[$ap_l+$j] ! save smashed ap[j] in double format + fxtod $na,$na + std $ahi,[$ap_h+$j] + fxtod $nb,$nb + std $nlo,[$np_l+$j] ! save smashed np[j] in double format + fxtod $nc,$nc + std $nhi,[$np_h+$j] + fxtod $nd,$nd + + fmuld $alo,$ba,$aloa + fmuld $nlo,$na,$nloa + fmuld $alo,$bb,$alob + fmuld $nlo,$nb,$nlob + fmuld $alo,$bc,$aloc + faddd $aloa,$nloa,$nloa + fmuld $nlo,$nc,$nloc + fmuld $alo,$bd,$alod + faddd $alob,$nlob,$nlob + fmuld $nlo,$nd,$nlod + fmuld $ahi,$ba,$ahia + faddd $aloc,$nloc,$nloc + fmuld $nhi,$na,$nhia + fmuld $ahi,$bb,$ahib + faddd $alod,$nlod,$nlod + fmuld $nhi,$nb,$nhib + fmuld $ahi,$bc,$ahic + faddd $ahia,$nhia,$nhia + fmuld $nhi,$nc,$nhic + fmuld $ahi,$bd,$ahid + faddd $ahib,$nhib,$nhib + fmuld $nhi,$nd,$nhid + + faddd $ahic,$nhic,$dota ! $nhic + faddd $ahid,$nhid,$dotb ! $nhid + + faddd $nloc,$nhia,$nloc + faddd $nlod,$nhib,$nlod + + fdtox $nloa,$nloa + fdtox $nlob,$nlob + fdtox $nloc,$nloc + fdtox $nlod,$nlod + + std $nloa,[%sp+$bias+$frame+0] + add $j,8,$j + std $nlob,[%sp+$bias+$frame+8] + add $ap,$j,%o4 + std $nloc,[%sp+$bias+$frame+16] + add $np,$j,%o5 + std $nlod,[%sp+$bias+$frame+24] + + ld [%o4+0],$alo_ ! load a[j] as pair of 32-bit words + fzeros $alo + ld [%o4+4],$ahi_ + fzeros $ahi + ld [%o5+0],$nlo_ ! load n[j] as pair of 32-bit words + fzeros $nlo + ld [%o5+4],$nhi_ + fzeros $nhi + + fxtod $alo,$alo + fxtod $ahi,$ahi + fxtod $nlo,$nlo + fxtod $nhi,$nhi + + ldx [%sp+$bias+$frame+0],%o0 + fmuld $alo,$ba,$aloa + ldx [%sp+$bias+$frame+8],%o1 + fmuld $nlo,$na,$nloa + ldx [%sp+$bias+$frame+16],%o2 + fmuld $alo,$bb,$alob + ldx [%sp+$bias+$frame+24],%o3 + fmuld $nlo,$nb,$nlob + + srlx %o0,16,%o7 + std $alo,[$ap_l+$j] ! save smashed ap[j] in double format + fmuld $alo,$bc,$aloc + add %o7,%o1,%o1 + std $ahi,[$ap_h+$j] + faddd $aloa,$nloa,$nloa + fmuld $nlo,$nc,$nloc + srlx %o1,16,%o7 + std $nlo,[$np_l+$j] ! save smashed np[j] in double format + fmuld $alo,$bd,$alod + add %o7,%o2,%o2 + std $nhi,[$np_h+$j] + faddd $alob,$nlob,$nlob + fmuld $nlo,$nd,$nlod + srlx %o2,16,%o7 + fmuld $ahi,$ba,$ahia + add %o7,%o3,%o3 ! %o3.%o2[0..15].%o1[0..15].%o0[0..15] + faddd $aloc,$nloc,$nloc + fmuld $nhi,$na,$nhia + !and %o0,$mask,%o0 + !and %o1,$mask,%o1 + !and %o2,$mask,%o2 + !sllx %o1,16,%o1 + !sllx %o2,32,%o2 + !sllx %o3,48,%o7 + !or %o1,%o0,%o0 + !or %o2,%o0,%o0 + !or %o7,%o0,%o0 ! 64-bit result + srlx %o3,16,%g1 ! 34-bit carry + fmuld $ahi,$bb,$ahib + + faddd $alod,$nlod,$nlod + fmuld $nhi,$nb,$nhib + fmuld $ahi,$bc,$ahic + faddd $ahia,$nhia,$nhia + fmuld $nhi,$nc,$nhic + fmuld $ahi,$bd,$ahid + faddd $ahib,$nhib,$nhib + fmuld $nhi,$nd,$nhid + + faddd $dota,$nloa,$nloa + faddd $dotb,$nlob,$nlob + faddd $ahic,$nhic,$dota ! $nhic + faddd $ahid,$nhid,$dotb ! $nhid + + faddd $nloc,$nhia,$nloc + faddd $nlod,$nhib,$nlod + + fdtox $nloa,$nloa + fdtox $nlob,$nlob + fdtox $nloc,$nloc + fdtox $nlod,$nlod + + std $nloa,[%sp+$bias+$frame+0] + std $nlob,[%sp+$bias+$frame+8] + addcc $j,8,$j + std $nloc,[%sp+$bias+$frame+16] + bz,pn %icc,.L1stskip + std $nlod,[%sp+$bias+$frame+24] + +.align 32 ! incidentally already aligned ! +.L1st: + add $ap,$j,%o4 + add $np,$j,%o5 + ld [%o4+0],$alo_ ! load a[j] as pair of 32-bit words + fzeros $alo + ld [%o4+4],$ahi_ + fzeros $ahi + ld [%o5+0],$nlo_ ! load n[j] as pair of 32-bit words + fzeros $nlo + ld [%o5+4],$nhi_ + fzeros $nhi + + fxtod $alo,$alo + fxtod $ahi,$ahi + fxtod $nlo,$nlo + fxtod $nhi,$nhi + + ldx [%sp+$bias+$frame+0],%o0 + fmuld $alo,$ba,$aloa + ldx [%sp+$bias+$frame+8],%o1 + fmuld $nlo,$na,$nloa + ldx [%sp+$bias+$frame+16],%o2 + fmuld $alo,$bb,$alob + ldx [%sp+$bias+$frame+24],%o3 + fmuld $nlo,$nb,$nlob + + srlx %o0,16,%o7 + std $alo,[$ap_l+$j] ! save smashed ap[j] in double format + fmuld $alo,$bc,$aloc + add %o7,%o1,%o1 + std $ahi,[$ap_h+$j] + faddd $aloa,$nloa,$nloa + fmuld $nlo,$nc,$nloc + srlx %o1,16,%o7 + std $nlo,[$np_l+$j] ! save smashed np[j] in double format + fmuld $alo,$bd,$alod + add %o7,%o2,%o2 + std $nhi,[$np_h+$j] + faddd $alob,$nlob,$nlob + fmuld $nlo,$nd,$nlod + srlx %o2,16,%o7 + fmuld $ahi,$ba,$ahia + add %o7,%o3,%o3 ! %o3.%o2[0..15].%o1[0..15].%o0[0..15] + and %o0,$mask,%o0 + faddd $aloc,$nloc,$nloc + fmuld $nhi,$na,$nhia + and %o1,$mask,%o1 + and %o2,$mask,%o2 + fmuld $ahi,$bb,$ahib + sllx %o1,16,%o1 + faddd $alod,$nlod,$nlod + fmuld $nhi,$nb,$nhib + sllx %o2,32,%o2 + fmuld $ahi,$bc,$ahic + sllx %o3,48,%o7 + or %o1,%o0,%o0 + faddd $ahia,$nhia,$nhia + fmuld $nhi,$nc,$nhic + or %o2,%o0,%o0 + fmuld $ahi,$bd,$ahid + or %o7,%o0,%o0 ! 64-bit result + faddd $ahib,$nhib,$nhib + fmuld $nhi,$nd,$nhid + addcc %g1,%o0,%o0 + faddd $dota,$nloa,$nloa + srlx %o3,16,%g1 ! 34-bit carry + faddd $dotb,$nlob,$nlob + bcs,a %xcc,.+8 + add %g1,1,%g1 + + stx %o0,[$tp] ! tp[j-1]= + + faddd $ahic,$nhic,$dota ! $nhic + faddd $ahid,$nhid,$dotb ! $nhid + + faddd $nloc,$nhia,$nloc + faddd $nlod,$nhib,$nlod + + fdtox $nloa,$nloa + fdtox $nlob,$nlob + fdtox $nloc,$nloc + fdtox $nlod,$nlod + + std $nloa,[%sp+$bias+$frame+0] + std $nlob,[%sp+$bias+$frame+8] + std $nloc,[%sp+$bias+$frame+16] + std $nlod,[%sp+$bias+$frame+24] + + addcc $j,8,$j + bnz,pt %icc,.L1st + add $tp,8,$tp + +.L1stskip: + fdtox $dota,$dota + fdtox $dotb,$dotb + + ldx [%sp+$bias+$frame+0],%o0 + ldx [%sp+$bias+$frame+8],%o1 + ldx [%sp+$bias+$frame+16],%o2 + ldx [%sp+$bias+$frame+24],%o3 + + srlx %o0,16,%o7 + std $dota,[%sp+$bias+$frame+32] + add %o7,%o1,%o1 + std $dotb,[%sp+$bias+$frame+40] + srlx %o1,16,%o7 + add %o7,%o2,%o2 + srlx %o2,16,%o7 + add %o7,%o3,%o3 ! %o3.%o2[0..15].%o1[0..15].%o0[0..15] + and %o0,$mask,%o0 + and %o1,$mask,%o1 + and %o2,$mask,%o2 + sllx %o1,16,%o1 + sllx %o2,32,%o2 + sllx %o3,48,%o7 + or %o1,%o0,%o0 + or %o2,%o0,%o0 + or %o7,%o0,%o0 ! 64-bit result + ldx [%sp+$bias+$frame+32],%o4 + addcc %g1,%o0,%o0 + ldx [%sp+$bias+$frame+40],%o5 + srlx %o3,16,%g1 ! 34-bit carry + bcs,a %xcc,.+8 + add %g1,1,%g1 + + stx %o0,[$tp] ! tp[j-1]= + add $tp,8,$tp + + srlx %o4,16,%o7 + add %o7,%o5,%o5 + and %o4,$mask,%o4 + sllx %o5,16,%o7 + or %o7,%o4,%o4 + addcc %g1,%o4,%o4 + srlx %o5,48,%g1 + bcs,a %xcc,.+8 + add %g1,1,%g1 + + mov %g1,$carry + stx %o4,[$tp] ! tp[num-1]= + + ba .Louter + add $i,8,$i +.align 32 +.Louter: + sub %g0,$num,$j ! j=-num + add %sp,$bias+$frame+$locals,$tp + + add $ap,$j,%o3 + add $bp,$i,%o4 + + ld [%o3+4],%g1 ! bp[i] + ld [%o3+0],%o0 + ld [%o4+4],%g5 ! ap[0] + sllx %g1,32,%g1 + ld [%o4+0],%o1 + sllx %g5,32,%g5 + or %g1,%o0,%o0 + or %g5,%o1,%o1 + + ldx [$tp],%o2 ! tp[0] + mulx %o1,%o0,%o0 + addcc %o2,%o0,%o0 + mulx $n0,%o0,%o0 ! (ap[0]*bp[i]+t[0])*n0 + stx %o0,[%sp+$bias+$frame+0] + + ! transfer b[i] to FPU as 4x16-bit values + ldda [%o4+2]%asi,$ba + ldda [%o4+0]%asi,$bb + ldda [%o4+6]%asi,$bc + ldda [%o4+4]%asi,$bd + + ! transfer (ap[0]*b[i]+t[0])*n0 to FPU as 4x16-bit values + ldda [%sp+$bias+$frame+6]%asi,$na + fxtod $ba,$ba + ldda [%sp+$bias+$frame+4]%asi,$nb + fxtod $bb,$bb + ldda [%sp+$bias+$frame+2]%asi,$nc + fxtod $bc,$bc + ldda [%sp+$bias+$frame+0]%asi,$nd + fxtod $bd,$bd + ldd [$ap_l+$j],$alo ! load a[j] in double format + fxtod $na,$na + ldd [$ap_h+$j],$ahi + fxtod $nb,$nb + ldd [$np_l+$j],$nlo ! load n[j] in double format + fxtod $nc,$nc + ldd [$np_h+$j],$nhi + fxtod $nd,$nd + + fmuld $alo,$ba,$aloa + fmuld $nlo,$na,$nloa + fmuld $alo,$bb,$alob + fmuld $nlo,$nb,$nlob + fmuld $alo,$bc,$aloc + faddd $aloa,$nloa,$nloa + fmuld $nlo,$nc,$nloc + fmuld $alo,$bd,$alod + faddd $alob,$nlob,$nlob + fmuld $nlo,$nd,$nlod + fmuld $ahi,$ba,$ahia + faddd $aloc,$nloc,$nloc + fmuld $nhi,$na,$nhia + fmuld $ahi,$bb,$ahib + faddd $alod,$nlod,$nlod + fmuld $nhi,$nb,$nhib + fmuld $ahi,$bc,$ahic + faddd $ahia,$nhia,$nhia + fmuld $nhi,$nc,$nhic + fmuld $ahi,$bd,$ahid + faddd $ahib,$nhib,$nhib + fmuld $nhi,$nd,$nhid + + faddd $ahic,$nhic,$dota ! $nhic + faddd $ahid,$nhid,$dotb ! $nhid + + faddd $nloc,$nhia,$nloc + faddd $nlod,$nhib,$nlod + + fdtox $nloa,$nloa + fdtox $nlob,$nlob + fdtox $nloc,$nloc + fdtox $nlod,$nlod + + std $nloa,[%sp+$bias+$frame+0] + std $nlob,[%sp+$bias+$frame+8] + std $nloc,[%sp+$bias+$frame+16] + add $j,8,$j + std $nlod,[%sp+$bias+$frame+24] + + ldd [$ap_l+$j],$alo ! load a[j] in double format + ldd [$ap_h+$j],$ahi + ldd [$np_l+$j],$nlo ! load n[j] in double format + ldd [$np_h+$j],$nhi + + fmuld $alo,$ba,$aloa + fmuld $nlo,$na,$nloa + fmuld $alo,$bb,$alob + fmuld $nlo,$nb,$nlob + fmuld $alo,$bc,$aloc + ldx [%sp+$bias+$frame+0],%o0 + faddd $aloa,$nloa,$nloa + fmuld $nlo,$nc,$nloc + ldx [%sp+$bias+$frame+8],%o1 + fmuld $alo,$bd,$alod + ldx [%sp+$bias+$frame+16],%o2 + faddd $alob,$nlob,$nlob + fmuld $nlo,$nd,$nlod + ldx [%sp+$bias+$frame+24],%o3 + fmuld $ahi,$ba,$ahia + + srlx %o0,16,%o7 + faddd $aloc,$nloc,$nloc + fmuld $nhi,$na,$nhia + add %o7,%o1,%o1 + fmuld $ahi,$bb,$ahib + srlx %o1,16,%o7 + faddd $alod,$nlod,$nlod + fmuld $nhi,$nb,$nhib + add %o7,%o2,%o2 + fmuld $ahi,$bc,$ahic + srlx %o2,16,%o7 + faddd $ahia,$nhia,$nhia + fmuld $nhi,$nc,$nhic + add %o7,%o3,%o3 ! %o3.%o2[0..15].%o1[0..15].%o0[0..15] + ! why? + and %o0,$mask,%o0 + fmuld $ahi,$bd,$ahid + and %o1,$mask,%o1 + and %o2,$mask,%o2 + faddd $ahib,$nhib,$nhib + fmuld $nhi,$nd,$nhid + sllx %o1,16,%o1 + faddd $dota,$nloa,$nloa + sllx %o2,32,%o2 + faddd $dotb,$nlob,$nlob + sllx %o3,48,%o7 + or %o1,%o0,%o0 + faddd $ahic,$nhic,$dota ! $nhic + or %o2,%o0,%o0 + faddd $ahid,$nhid,$dotb ! $nhid + or %o7,%o0,%o0 ! 64-bit result + ldx [$tp],%o7 + faddd $nloc,$nhia,$nloc + addcc %o7,%o0,%o0 + ! end-of-why? + faddd $nlod,$nhib,$nlod + srlx %o3,16,%g1 ! 34-bit carry + fdtox $nloa,$nloa + bcs,a %xcc,.+8 + add %g1,1,%g1 + + fdtox $nlob,$nlob + fdtox $nloc,$nloc + fdtox $nlod,$nlod + + std $nloa,[%sp+$bias+$frame+0] + std $nlob,[%sp+$bias+$frame+8] + addcc $j,8,$j + std $nloc,[%sp+$bias+$frame+16] + bz,pn %icc,.Linnerskip + std $nlod,[%sp+$bias+$frame+24] + + ba .Linner + nop +.align 32 +.Linner: + ldd [$ap_l+$j],$alo ! load a[j] in double format + ldd [$ap_h+$j],$ahi + ldd [$np_l+$j],$nlo ! load n[j] in double format + ldd [$np_h+$j],$nhi + + fmuld $alo,$ba,$aloa + fmuld $nlo,$na,$nloa + fmuld $alo,$bb,$alob + fmuld $nlo,$nb,$nlob + fmuld $alo,$bc,$aloc + ldx [%sp+$bias+$frame+0],%o0 + faddd $aloa,$nloa,$nloa + fmuld $nlo,$nc,$nloc + ldx [%sp+$bias+$frame+8],%o1 + fmuld $alo,$bd,$alod + ldx [%sp+$bias+$frame+16],%o2 + faddd $alob,$nlob,$nlob + fmuld $nlo,$nd,$nlod + ldx [%sp+$bias+$frame+24],%o3 + fmuld $ahi,$ba,$ahia + + srlx %o0,16,%o7 + faddd $aloc,$nloc,$nloc + fmuld $nhi,$na,$nhia + add %o7,%o1,%o1 + fmuld $ahi,$bb,$ahib + srlx %o1,16,%o7 + faddd $alod,$nlod,$nlod + fmuld $nhi,$nb,$nhib + add %o7,%o2,%o2 + fmuld $ahi,$bc,$ahic + srlx %o2,16,%o7 + faddd $ahia,$nhia,$nhia + fmuld $nhi,$nc,$nhic + add %o7,%o3,%o3 ! %o3.%o2[0..15].%o1[0..15].%o0[0..15] + and %o0,$mask,%o0 + fmuld $ahi,$bd,$ahid + and %o1,$mask,%o1 + and %o2,$mask,%o2 + faddd $ahib,$nhib,$nhib + fmuld $nhi,$nd,$nhid + sllx %o1,16,%o1 + faddd $dota,$nloa,$nloa + sllx %o2,32,%o2 + faddd $dotb,$nlob,$nlob + sllx %o3,48,%o7 + or %o1,%o0,%o0 + faddd $ahic,$nhic,$dota ! $nhic + or %o2,%o0,%o0 + faddd $ahid,$nhid,$dotb ! $nhid + or %o7,%o0,%o0 ! 64-bit result + faddd $nloc,$nhia,$nloc + addcc %g1,%o0,%o0 + ldx [$tp+8],%o7 ! tp[j] + faddd $nlod,$nhib,$nlod + srlx %o3,16,%g1 ! 34-bit carry + fdtox $nloa,$nloa + bcs,a %xcc,.+8 + add %g1,1,%g1 + fdtox $nlob,$nlob + addcc %o7,%o0,%o0 + fdtox $nloc,$nloc + bcs,a %xcc,.+8 + add %g1,1,%g1 + + stx %o0,[$tp] ! tp[j-1] + fdtox $nlod,$nlod + + std $nloa,[%sp+$bias+$frame+0] + std $nlob,[%sp+$bias+$frame+8] + std $nloc,[%sp+$bias+$frame+16] + addcc $j,8,$j + std $nlod,[%sp+$bias+$frame+24] + bnz,pt %icc,.Linner + add $tp,8,$tp + +.Linnerskip: + fdtox $dota,$dota + fdtox $dotb,$dotb + + ldx [%sp+$bias+$frame+0],%o0 + ldx [%sp+$bias+$frame+8],%o1 + ldx [%sp+$bias+$frame+16],%o2 + ldx [%sp+$bias+$frame+24],%o3 + + srlx %o0,16,%o7 + std $dota,[%sp+$bias+$frame+32] + add %o7,%o1,%o1 + std $dotb,[%sp+$bias+$frame+40] + srlx %o1,16,%o7 + add %o7,%o2,%o2 + srlx %o2,16,%o7 + add %o7,%o3,%o3 ! %o3.%o2[0..15].%o1[0..15].%o0[0..15] + and %o0,$mask,%o0 + and %o1,$mask,%o1 + and %o2,$mask,%o2 + sllx %o1,16,%o1 + sllx %o2,32,%o2 + sllx %o3,48,%o7 + or %o1,%o0,%o0 + or %o2,%o0,%o0 + ldx [%sp+$bias+$frame+32],%o4 + or %o7,%o0,%o0 ! 64-bit result + ldx [%sp+$bias+$frame+40],%o5 + addcc %g1,%o0,%o0 + ldx [$tp+8],%o7 ! tp[j] + srlx %o3,16,%g1 ! 34-bit carry + bcs,a %xcc,.+8 + add %g1,1,%g1 + + addcc %o7,%o0,%o0 + bcs,a %xcc,.+8 + add %g1,1,%g1 + + stx %o0,[$tp] ! tp[j-1] + add $tp,8,$tp + + srlx %o4,16,%o7 + add %o7,%o5,%o5 + and %o4,$mask,%o4 + sllx %o5,16,%o7 + or %o7,%o4,%o4 + addcc %g1,%o4,%o4 + srlx %o5,48,%g1 + bcs,a %xcc,.+8 + add %g1,1,%g1 + + addcc $carry,%o4,%o4 + stx %o4,[$tp] ! tp[num-1] + mov %g1,$carry + bcs,a %xcc,.+8 + add $carry,1,$carry + + addcc $i,8,$i + bnz %icc,.Louter + nop + + add $tp,8,$tp ! adjust tp to point at the end + orn %g0,%g0,%g4 + sub %g0,$num,%o7 ! n=-num + ba .Lsub + subcc %g0,%g0,%g0 ! clear %icc.c + +.align 32 +.Lsub: + ldx [$tp+%o7],%o0 + add $np,%o7,%g1 + ld [%g1+0],%o2 + ld [%g1+4],%o3 + srlx %o0,32,%o1 + subccc %o0,%o2,%o2 + add $rp,%o7,%g1 + subccc %o1,%o3,%o3 + st %o2,[%g1+0] + add %o7,8,%o7 + brnz,pt %o7,.Lsub + st %o3,[%g1+4] + subc $carry,0,%g4 + sub %g0,$num,%o7 ! n=-num + ba .Lcopy + nop + +.align 32 +.Lcopy: + ldx [$tp+%o7],%o0 + add $rp,%o7,%g1 + ld [%g1+0],%o2 + ld [%g1+4],%o3 + stx %g0,[$tp+%o7] + and %o0,%g4,%o0 + srlx %o0,32,%o1 + andn %o2,%g4,%o2 + andn %o3,%g4,%o3 + or %o2,%o0,%o0 + or %o3,%o1,%o1 + st %o0,[%g1+0] + add %o7,8,%o7 + brnz,pt %o7,.Lcopy + st %o1,[%g1+4] + sub %g0,$num,%o7 ! n=-num + +.Lzap: + stx %g0,[$ap_l+%o7] + stx %g0,[$ap_h+%o7] + stx %g0,[$np_l+%o7] + stx %g0,[$np_h+%o7] + add %o7,8,%o7 + brnz,pt %o7,.Lzap + nop + + ldx [%sp+$bias+$frame+48],%o7 + wr %g0,%o7,%asi ! restore %asi + + mov 1,%i0 +.Lret: + ret + restore +.type $fname,#function +.size $fname,(.-$fname) +.asciz "Montgomery Multiplication for UltraSPARC, CRYPTOGAMS by " +.align 32 +___ + +$code =~ s/\`([^\`]*)\`/eval($1)/gem; + +# Below substitution makes it possible to compile without demanding +# VIS extensions on command line, e.g. -xarch=v9 vs. -xarch=v9a. I +# dare to do this, because VIS capability is detected at run-time now +# and this routine is not called on CPU not capable to execute it. Do +# note that fzeros is not the only VIS dependency! Another dependency +# is implicit and is just _a_ numerical value loaded to %asi register, +# which assembler can't recognize as VIS specific... +$code =~ s/fzeros\s+%f([0-9]+)/ + sprintf(".word\t0x%x\t! fzeros %%f%d",0x81b00c20|($1<<25),$1) + /gem; + +print $code; +# flush +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/via-mont.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/via-mont.pl new file mode 100644 index 000000000..9cf717e84 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/via-mont.pl @@ -0,0 +1,251 @@ +#! /usr/bin/env perl +# Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# Wrapper around 'rep montmul', VIA-specific instruction accessing +# PadLock Montgomery Multiplier. The wrapper is designed as drop-in +# replacement for OpenSSL bn_mul_mont [first implemented in 0.9.9]. +# +# Below are interleaved outputs from 'openssl speed rsa dsa' for 4 +# different software configurations on 1.5GHz VIA Esther processor. +# Lines marked with "software integer" denote performance of hand- +# coded integer-only assembler found in OpenSSL 0.9.7. "Software SSE2" +# refers to hand-coded SSE2 Montgomery multiplication procedure found +# OpenSSL 0.9.9. "Hardware VIA SDK" refers to padlock_pmm routine from +# Padlock SDK 2.0.1 available for download from VIA, which naturally +# utilizes the magic 'repz montmul' instruction. And finally "hardware +# this" refers to *this* implementation which also uses 'repz montmul' +# +# sign verify sign/s verify/s +# rsa 512 bits 0.001720s 0.000140s 581.4 7149.7 software integer +# rsa 512 bits 0.000690s 0.000086s 1450.3 11606.0 software SSE2 +# rsa 512 bits 0.006136s 0.000201s 163.0 4974.5 hardware VIA SDK +# rsa 512 bits 0.000712s 0.000050s 1404.9 19858.5 hardware this +# +# rsa 1024 bits 0.008518s 0.000413s 117.4 2420.8 software integer +# rsa 1024 bits 0.004275s 0.000277s 233.9 3609.7 software SSE2 +# rsa 1024 bits 0.012136s 0.000260s 82.4 3844.5 hardware VIA SDK +# rsa 1024 bits 0.002522s 0.000116s 396.5 8650.9 hardware this +# +# rsa 2048 bits 0.050101s 0.001371s 20.0 729.6 software integer +# rsa 2048 bits 0.030273s 0.001008s 33.0 991.9 software SSE2 +# rsa 2048 bits 0.030833s 0.000976s 32.4 1025.1 hardware VIA SDK +# rsa 2048 bits 0.011879s 0.000342s 84.2 2921.7 hardware this +# +# rsa 4096 bits 0.327097s 0.004859s 3.1 205.8 software integer +# rsa 4096 bits 0.229318s 0.003859s 4.4 259.2 software SSE2 +# rsa 4096 bits 0.233953s 0.003274s 4.3 305.4 hardware VIA SDK +# rsa 4096 bits 0.070493s 0.001166s 14.2 857.6 hardware this +# +# dsa 512 bits 0.001342s 0.001651s 745.2 605.7 software integer +# dsa 512 bits 0.000844s 0.000987s 1185.3 1013.1 software SSE2 +# dsa 512 bits 0.001902s 0.002247s 525.6 444.9 hardware VIA SDK +# dsa 512 bits 0.000458s 0.000524s 2182.2 1909.1 hardware this +# +# dsa 1024 bits 0.003964s 0.004926s 252.3 203.0 software integer +# dsa 1024 bits 0.002686s 0.003166s 372.3 315.8 software SSE2 +# dsa 1024 bits 0.002397s 0.002823s 417.1 354.3 hardware VIA SDK +# dsa 1024 bits 0.000978s 0.001170s 1022.2 855.0 hardware this +# +# dsa 2048 bits 0.013280s 0.016518s 75.3 60.5 software integer +# dsa 2048 bits 0.009911s 0.011522s 100.9 86.8 software SSE2 +# dsa 2048 bits 0.009542s 0.011763s 104.8 85.0 hardware VIA SDK +# dsa 2048 bits 0.002884s 0.003352s 346.8 298.3 hardware this +# +# To give you some other reference point here is output for 2.4GHz P4 +# running hand-coded SSE2 bn_mul_mont found in 0.9.9, i.e. "software +# SSE2" in above terms. +# +# rsa 512 bits 0.000407s 0.000047s 2454.2 21137.0 +# rsa 1024 bits 0.002426s 0.000141s 412.1 7100.0 +# rsa 2048 bits 0.015046s 0.000491s 66.5 2034.9 +# rsa 4096 bits 0.109770s 0.002379s 9.1 420.3 +# dsa 512 bits 0.000438s 0.000525s 2281.1 1904.1 +# dsa 1024 bits 0.001346s 0.001595s 742.7 627.0 +# dsa 2048 bits 0.004745s 0.005582s 210.7 179.1 +# +# Conclusions: +# - VIA SDK leaves a *lot* of room for improvement (which this +# implementation successfully fills:-); +# - 'rep montmul' gives up to >3x performance improvement depending on +# key length; +# - in terms of absolute performance it delivers approximately as much +# as modern out-of-order 32-bit cores [again, for longer keys]. + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +$output = pop; +open STDOUT,">$output"; + +&asm_init($ARGV[0]); + +# int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, const BN_ULONG *np,const BN_ULONG *n0, int num); +$func="bn_mul_mont_padlock"; + +$pad=16*1; # amount of reserved bytes on top of every vector + +# stack layout +$mZeroPrime=&DWP(0,"esp"); # these are specified by VIA +$A=&DWP(4,"esp"); +$B=&DWP(8,"esp"); +$T=&DWP(12,"esp"); +$M=&DWP(16,"esp"); +$scratch=&DWP(20,"esp"); +$rp=&DWP(24,"esp"); # these are mine +$sp=&DWP(28,"esp"); +# &DWP(32,"esp") # 32 byte scratch area +# &DWP(64+(4*$num+$pad)*0,"esp") # padded tp[num] +# &DWP(64+(4*$num+$pad)*1,"esp") # padded copy of ap[num] +# &DWP(64+(4*$num+$pad)*2,"esp") # padded copy of bp[num] +# &DWP(64+(4*$num+$pad)*3,"esp") # padded copy of np[num] +# Note that SDK suggests to unconditionally allocate 2K per vector. This +# has quite an impact on performance. It naturally depends on key length, +# but to give an example 1024 bit private RSA key operations suffer >30% +# penalty. I allocate only as much as actually required... + +&function_begin($func); + &xor ("eax","eax"); + &mov ("ecx",&wparam(5)); # num + # meet VIA's limitations for num [note that the specification + # expresses them in bits, while we work with amount of 32-bit words] + &test ("ecx",3); + &jnz (&label("leave")); # num % 4 != 0 + &cmp ("ecx",8); + &jb (&label("leave")); # num < 8 + &cmp ("ecx",1024); + &ja (&label("leave")); # num > 1024 + + &pushf (); + &cld (); + + &mov ("edi",&wparam(0)); # rp + &mov ("eax",&wparam(1)); # ap + &mov ("ebx",&wparam(2)); # bp + &mov ("edx",&wparam(3)); # np + &mov ("esi",&wparam(4)); # n0 + &mov ("esi",&DWP(0,"esi")); # *n0 + + &lea ("ecx",&DWP($pad,"","ecx",4)); # ecx becomes vector size in bytes + &lea ("ebp",&DWP(64,"","ecx",4)); # allocate 4 vectors + 64 bytes + &neg ("ebp"); + &add ("ebp","esp"); + &and ("ebp",-64); # align to cache-line + &xchg ("ebp","esp"); # alloca + + &mov ($rp,"edi"); # save rp + &mov ($sp,"ebp"); # save esp + + &mov ($mZeroPrime,"esi"); + &lea ("esi",&DWP(64,"esp")); # tp + &mov ($T,"esi"); + &lea ("edi",&DWP(32,"esp")); # scratch area + &mov ($scratch,"edi"); + &mov ("esi","eax"); + + &lea ("ebp",&DWP(-$pad,"ecx")); + &shr ("ebp",2); # restore original num value in ebp + + &xor ("eax","eax"); + + &mov ("ecx","ebp"); + &lea ("ecx",&DWP((32+$pad)/4,"ecx"));# padded tp + scratch + &data_byte(0xf3,0xab); # rep stosl, bzero + + &mov ("ecx","ebp"); + &lea ("edi",&DWP(64+$pad,"esp","ecx",4));# pointer to ap copy + &mov ($A,"edi"); + &data_byte(0xf3,0xa5); # rep movsl, memcpy + &mov ("ecx",$pad/4); + &data_byte(0xf3,0xab); # rep stosl, bzero pad + # edi points at the end of padded ap copy... + + &mov ("ecx","ebp"); + &mov ("esi","ebx"); + &mov ($B,"edi"); + &data_byte(0xf3,0xa5); # rep movsl, memcpy + &mov ("ecx",$pad/4); + &data_byte(0xf3,0xab); # rep stosl, bzero pad + # edi points at the end of padded bp copy... + + &mov ("ecx","ebp"); + &mov ("esi","edx"); + &mov ($M,"edi"); + &data_byte(0xf3,0xa5); # rep movsl, memcpy + &mov ("ecx",$pad/4); + &data_byte(0xf3,0xab); # rep stosl, bzero pad + # edi points at the end of padded np copy... + + # let magic happen... + &mov ("ecx","ebp"); + &mov ("esi","esp"); + &shl ("ecx",5); # convert word counter to bit counter + &align (4); + &data_byte(0xf3,0x0f,0xa6,0xc0);# rep montmul + + &mov ("ecx","ebp"); + &lea ("esi",&DWP(64,"esp")); # tp + # edi still points at the end of padded np copy... + &neg ("ebp"); + &lea ("ebp",&DWP(-$pad,"edi","ebp",4)); # so just "rewind" + &mov ("edi",$rp); # restore rp + &xor ("edx","edx"); # i=0 and clear CF + +&set_label("sub",8); + &mov ("eax",&DWP(0,"esi","edx",4)); + &sbb ("eax",&DWP(0,"ebp","edx",4)); + &mov (&DWP(0,"edi","edx",4),"eax"); # rp[i]=tp[i]-np[i] + &lea ("edx",&DWP(1,"edx")); # i++ + &loop (&label("sub")); # doesn't affect CF! + + &mov ("eax",&DWP(0,"esi","edx",4)); # upmost overflow bit + &sbb ("eax",0); + + &mov ("ecx","edx"); # num + &mov ("edx",0); # i=0 + +&set_label("copy",8); + &mov ("ebx",&DWP(0,"esi","edx",4)); + &mov ("eax",&DWP(0,"edi","edx",4)); + &mov (&DWP(0,"esi","edx",4),"ecx"); # zap tp + &cmovc ("eax","ebx"); + &mov (&DWP(0,"edi","edx",4),"eax"); + &lea ("edx",&DWP(1,"edx")); # i++ + &loop (&label("copy")); + + &mov ("ebp",$sp); + &xor ("eax","eax"); + + &mov ("ecx",64/4); + &mov ("edi","esp"); # zap frame including scratch area + &data_byte(0xf3,0xab); # rep stosl, bzero + + # zap copies of ap, bp and np + &lea ("edi",&DWP(64+$pad,"esp","edx",4));# pointer to ap + &lea ("ecx",&DWP(3*$pad/4,"edx","edx",2)); + &data_byte(0xf3,0xab); # rep stosl, bzero + + &mov ("esp","ebp"); + &inc ("eax"); # signal "done" + &popf (); +&set_label("leave"); +&function_end($func); + +&asciz("Padlock Montgomery Multiplication, CRYPTOGAMS by "); + +&asm_finish(); + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/vis3-mont.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/vis3-mont.pl new file mode 100644 index 000000000..04833a0c8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/vis3-mont.pl @@ -0,0 +1,384 @@ +#! /usr/bin/env perl +# Copyright 2012-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# October 2012. +# +# SPARCv9 VIS3 Montgomery multiplication procedure suitable for T3 and +# onward. There are three new instructions used here: umulxhi, +# addxc[cc] and initializing store. On T3 RSA private key operations +# are 1.54/1.87/2.11/2.26 times faster for 512/1024/2048/4096-bit key +# lengths. This is without dedicated squaring procedure. On T4 +# corresponding coefficients are 1.47/2.10/2.80/2.90x, which is mostly +# for reference purposes, because T4 has dedicated Montgomery +# multiplication and squaring *instructions* that deliver even more. + +$output = pop; +open STDOUT,">$output"; + +$frame = "STACK_FRAME"; +$bias = "STACK_BIAS"; + +$code.=<<___; +#include "sparc_arch.h" + +#ifdef __arch64__ +.register %g2,#scratch +.register %g3,#scratch +#endif + +.section ".text",#alloc,#execinstr +___ + +($n0,$m0,$m1,$lo0,$hi0, $lo1,$hi1,$aj,$alo,$nj,$nlo,$tj)= + (map("%g$_",(1..5)),map("%o$_",(0..5,7))); + +# int bn_mul_mont( +$rp="%o0"; # BN_ULONG *rp, +$ap="%o1"; # const BN_ULONG *ap, +$bp="%o2"; # const BN_ULONG *bp, +$np="%o3"; # const BN_ULONG *np, +$n0p="%o4"; # const BN_ULONG *n0, +$num="%o5"; # int num); # caller ensures that num is even + # and >=6 +$code.=<<___; +.globl bn_mul_mont_vis3 +.align 32 +bn_mul_mont_vis3: + add %sp, $bias, %g4 ! real top of stack + sll $num, 2, $num ! size in bytes + add $num, 63, %g5 + andn %g5, 63, %g5 ! buffer size rounded up to 64 bytes + add %g5, %g5, %g1 + add %g5, %g1, %g1 ! 3*buffer size + sub %g4, %g1, %g1 + andn %g1, 63, %g1 ! align at 64 byte + sub %g1, $frame, %g1 ! new top of stack + sub %g1, %g4, %g1 + + save %sp, %g1, %sp +___ + +# +-------------------------------+<----- %sp +# . . +# +-------------------------------+<----- aligned at 64 bytes +# | __int64 tmp[0] | +# +-------------------------------+ +# . . +# . . +# +-------------------------------+<----- aligned at 64 bytes +# | __int64 ap[1..0] | converted ap[] +# +-------------------------------+ +# | __int64 np[1..0] | converted np[] +# +-------------------------------+ +# | __int64 ap[3..2] | +# . . +# . . +# +-------------------------------+ +($rp,$ap,$bp,$np,$n0p,$num)=map("%i$_",(0..5)); +($t0,$t1,$t2,$t3,$cnt,$tp,$bufsz,$anp)=map("%l$_",(0..7)); +($ovf,$i)=($t0,$t1); +$code.=<<___; + ld [$n0p+0], $t0 ! pull n0[0..1] value + add %sp, $bias+$frame, $tp + ld [$n0p+4], $t1 + add $tp, %g5, $anp + ld [$bp+0], $t2 ! m0=bp[0] + sllx $t1, 32, $n0 + ld [$bp+4], $t3 + or $t0, $n0, $n0 + add $bp, 8, $bp + + ld [$ap+0], $t0 ! ap[0] + sllx $t3, 32, $m0 + ld [$ap+4], $t1 + or $t2, $m0, $m0 + + ld [$ap+8], $t2 ! ap[1] + sllx $t1, 32, $aj + ld [$ap+12], $t3 + or $t0, $aj, $aj + add $ap, 16, $ap + stx $aj, [$anp] ! converted ap[0] + + mulx $aj, $m0, $lo0 ! ap[0]*bp[0] + umulxhi $aj, $m0, $hi0 + + ld [$np+0], $t0 ! np[0] + sllx $t3, 32, $aj + ld [$np+4], $t1 + or $t2, $aj, $aj + + ld [$np+8], $t2 ! np[1] + sllx $t1, 32, $nj + ld [$np+12], $t3 + or $t0, $nj, $nj + add $np, 16, $np + stx $nj, [$anp+8] ! converted np[0] + + mulx $lo0, $n0, $m1 ! "tp[0]"*n0 + stx $aj, [$anp+16] ! converted ap[1] + + mulx $aj, $m0, $alo ! ap[1]*bp[0] + umulxhi $aj, $m0, $aj ! ahi=aj + + mulx $nj, $m1, $lo1 ! np[0]*m1 + umulxhi $nj, $m1, $hi1 + + sllx $t3, 32, $nj + or $t2, $nj, $nj + stx $nj, [$anp+24] ! converted np[1] + add $anp, 32, $anp + + addcc $lo0, $lo1, $lo1 + addxc %g0, $hi1, $hi1 + + mulx $nj, $m1, $nlo ! np[1]*m1 + umulxhi $nj, $m1, $nj ! nhi=nj + + ba .L1st + sub $num, 24, $cnt ! cnt=num-3 + +.align 16 +.L1st: + ld [$ap+0], $t0 ! ap[j] + addcc $alo, $hi0, $lo0 + ld [$ap+4], $t1 + addxc $aj, %g0, $hi0 + + sllx $t1, 32, $aj + add $ap, 8, $ap + or $t0, $aj, $aj + stx $aj, [$anp] ! converted ap[j] + + ld [$np+0], $t2 ! np[j] + addcc $nlo, $hi1, $lo1 + ld [$np+4], $t3 + addxc $nj, %g0, $hi1 ! nhi=nj + + sllx $t3, 32, $nj + add $np, 8, $np + mulx $aj, $m0, $alo ! ap[j]*bp[0] + or $t2, $nj, $nj + umulxhi $aj, $m0, $aj ! ahi=aj + stx $nj, [$anp+8] ! converted np[j] + add $anp, 16, $anp ! anp++ + + mulx $nj, $m1, $nlo ! np[j]*m1 + addcc $lo0, $lo1, $lo1 ! np[j]*m1+ap[j]*bp[0] + umulxhi $nj, $m1, $nj ! nhi=nj + addxc %g0, $hi1, $hi1 + stx $lo1, [$tp] ! tp[j-1] + add $tp, 8, $tp ! tp++ + + brnz,pt $cnt, .L1st + sub $cnt, 8, $cnt ! j-- +!.L1st + addcc $alo, $hi0, $lo0 + addxc $aj, %g0, $hi0 ! ahi=aj + + addcc $nlo, $hi1, $lo1 + addxc $nj, %g0, $hi1 + addcc $lo0, $lo1, $lo1 ! np[j]*m1+ap[j]*bp[0] + addxc %g0, $hi1, $hi1 + stx $lo1, [$tp] ! tp[j-1] + add $tp, 8, $tp + + addcc $hi0, $hi1, $hi1 + addxc %g0, %g0, $ovf ! upmost overflow bit + stx $hi1, [$tp] + add $tp, 8, $tp + + ba .Louter + sub $num, 16, $i ! i=num-2 + +.align 16 +.Louter: + ld [$bp+0], $t2 ! m0=bp[i] + ld [$bp+4], $t3 + + sub $anp, $num, $anp ! rewind + sub $tp, $num, $tp + sub $anp, $num, $anp + + add $bp, 8, $bp + sllx $t3, 32, $m0 + ldx [$anp+0], $aj ! ap[0] + or $t2, $m0, $m0 + ldx [$anp+8], $nj ! np[0] + + mulx $aj, $m0, $lo0 ! ap[0]*bp[i] + ldx [$tp], $tj ! tp[0] + umulxhi $aj, $m0, $hi0 + ldx [$anp+16], $aj ! ap[1] + addcc $lo0, $tj, $lo0 ! ap[0]*bp[i]+tp[0] + mulx $aj, $m0, $alo ! ap[1]*bp[i] + addxc %g0, $hi0, $hi0 + mulx $lo0, $n0, $m1 ! tp[0]*n0 + umulxhi $aj, $m0, $aj ! ahi=aj + mulx $nj, $m1, $lo1 ! np[0]*m1 + umulxhi $nj, $m1, $hi1 + ldx [$anp+24], $nj ! np[1] + add $anp, 32, $anp + addcc $lo1, $lo0, $lo1 + mulx $nj, $m1, $nlo ! np[1]*m1 + addxc %g0, $hi1, $hi1 + umulxhi $nj, $m1, $nj ! nhi=nj + + ba .Linner + sub $num, 24, $cnt ! cnt=num-3 +.align 16 +.Linner: + addcc $alo, $hi0, $lo0 + ldx [$tp+8], $tj ! tp[j] + addxc $aj, %g0, $hi0 ! ahi=aj + ldx [$anp+0], $aj ! ap[j] + addcc $nlo, $hi1, $lo1 + mulx $aj, $m0, $alo ! ap[j]*bp[i] + addxc $nj, %g0, $hi1 ! nhi=nj + ldx [$anp+8], $nj ! np[j] + add $anp, 16, $anp + umulxhi $aj, $m0, $aj ! ahi=aj + addcc $lo0, $tj, $lo0 ! ap[j]*bp[i]+tp[j] + mulx $nj, $m1, $nlo ! np[j]*m1 + addxc %g0, $hi0, $hi0 + umulxhi $nj, $m1, $nj ! nhi=nj + addcc $lo1, $lo0, $lo1 ! np[j]*m1+ap[j]*bp[i]+tp[j] + addxc %g0, $hi1, $hi1 + stx $lo1, [$tp] ! tp[j-1] + add $tp, 8, $tp + brnz,pt $cnt, .Linner + sub $cnt, 8, $cnt +!.Linner + ldx [$tp+8], $tj ! tp[j] + addcc $alo, $hi0, $lo0 + addxc $aj, %g0, $hi0 ! ahi=aj + addcc $lo0, $tj, $lo0 ! ap[j]*bp[i]+tp[j] + addxc %g0, $hi0, $hi0 + + addcc $nlo, $hi1, $lo1 + addxc $nj, %g0, $hi1 ! nhi=nj + addcc $lo1, $lo0, $lo1 ! np[j]*m1+ap[j]*bp[i]+tp[j] + addxc %g0, $hi1, $hi1 + stx $lo1, [$tp] ! tp[j-1] + + subcc %g0, $ovf, %g0 ! move upmost overflow to CCR.xcc + addxccc $hi1, $hi0, $hi1 + addxc %g0, %g0, $ovf + stx $hi1, [$tp+8] + add $tp, 16, $tp + + brnz,pt $i, .Louter + sub $i, 8, $i + + sub $anp, $num, $anp ! rewind + sub $tp, $num, $tp + sub $anp, $num, $anp + ba .Lsub + subcc $num, 8, $cnt ! cnt=num-1 and clear CCR.xcc + +.align 16 +.Lsub: + ldx [$tp], $tj + add $tp, 8, $tp + ldx [$anp+8], $nj + add $anp, 16, $anp + subccc $tj, $nj, $t2 ! tp[j]-np[j] + srlx $tj, 32, $tj + srlx $nj, 32, $nj + subccc $tj, $nj, $t3 + add $rp, 8, $rp + st $t2, [$rp-4] ! reverse order + st $t3, [$rp-8] + brnz,pt $cnt, .Lsub + sub $cnt, 8, $cnt + + sub $anp, $num, $anp ! rewind + sub $tp, $num, $tp + sub $anp, $num, $anp + sub $rp, $num, $rp + + subccc $ovf, %g0, $ovf ! handle upmost overflow bit + ba .Lcopy + sub $num, 8, $cnt + +.align 16 +.Lcopy: ! conditional copy + ld [$tp+0], $t0 + ld [$tp+4], $t1 + ld [$rp+0], $t2 + ld [$rp+4], $t3 + stx %g0, [$tp] ! zap + add $tp, 8, $tp + stx %g0, [$anp] ! zap + stx %g0, [$anp+8] + add $anp, 16, $anp + movcs %icc, $t0, $t2 + movcs %icc, $t1, $t3 + st $t3, [$rp+0] ! flip order + st $t2, [$rp+4] + add $rp, 8, $rp + brnz $cnt, .Lcopy + sub $cnt, 8, $cnt + + mov 1, %o0 + ret + restore +.type bn_mul_mont_vis3, #function +.size bn_mul_mont_vis3, .-bn_mul_mont_vis3 +.asciz "Montgomery Multiplication for SPARCv9 VIS3, CRYPTOGAMS by " +.align 4 +___ + +# Purpose of these subroutines is to explicitly encode VIS instructions, +# so that one can compile the module without having to specify VIS +# extensions on compiler command line, e.g. -xarch=v9 vs. -xarch=v9a. +# Idea is to reserve for option to produce "universal" binary and let +# programmer detect if current CPU is VIS capable at run-time. +sub unvis3 { +my ($mnemonic,$rs1,$rs2,$rd)=@_; +my %bias = ( "g" => 0, "o" => 8, "l" => 16, "i" => 24 ); +my ($ref,$opf); +my %visopf = ( "addxc" => 0x011, + "addxccc" => 0x013, + "umulxhi" => 0x016 ); + + $ref = "$mnemonic\t$rs1,$rs2,$rd"; + + if ($opf=$visopf{$mnemonic}) { + foreach ($rs1,$rs2,$rd) { + return $ref if (!/%([goli])([0-9])/); + $_=$bias{$1}+$2; + } + + return sprintf ".word\t0x%08x !%s", + 0x81b00000|$rd<<25|$rs1<<14|$opf<<5|$rs2, + $ref; + } else { + return $ref; + } +} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/ge; + + s/\b(umulxhi|addxc[c]{0,2})\s+(%[goli][0-7]),\s*(%[goli][0-7]),\s*(%[goli][0-7])/ + &unvis3($1,$2,$3,$4) + /ge; + + print $_,"\n"; +} + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/x86-gf2m.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/x86-gf2m.pl new file mode 100644 index 000000000..d03efcc75 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/x86-gf2m.pl @@ -0,0 +1,325 @@ +#! /usr/bin/env perl +# Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# May 2011 +# +# The module implements bn_GF2m_mul_2x2 polynomial multiplication used +# in bn_gf2m.c. It's kind of low-hanging mechanical port from C for +# the time being... Except that it has three code paths: pure integer +# code suitable for any x86 CPU, MMX code suitable for PIII and later +# and PCLMULQDQ suitable for Westmere and later. Improvement varies +# from one benchmark and µ-arch to another. Below are interval values +# for 163- and 571-bit ECDH benchmarks relative to compiler-generated +# code: +# +# PIII 16%-30% +# P4 12%-12% +# Opteron 18%-40% +# Core2 19%-44% +# Atom 38%-64% +# Westmere 53%-121%(PCLMULQDQ)/20%-32%(MMX) +# Sandy Bridge 72%-127%(PCLMULQDQ)/27%-23%(MMX) +# +# Note that above improvement coefficients are not coefficients for +# bn_GF2m_mul_2x2 itself. For example 120% ECDH improvement is result +# of bn_GF2m_mul_2x2 being >4x faster. As it gets faster, benchmark +# is more and more dominated by other subroutines, most notably by +# BN_GF2m_mod[_mul]_arr... + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +$output = pop; +open STDOUT,">$output"; + +&asm_init($ARGV[0],$x86only = $ARGV[$#ARGV] eq "386"); + +$sse2=0; +for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); } + +&external_label("OPENSSL_ia32cap_P") if ($sse2); + +$a="eax"; +$b="ebx"; +($a1,$a2,$a4)=("ecx","edx","ebp"); + +$R="mm0"; +@T=("mm1","mm2"); +($A,$B,$B30,$B31)=("mm2","mm3","mm4","mm5"); +@i=("esi","edi"); + + if (!$x86only) { +&function_begin_B("_mul_1x1_mmx"); + &sub ("esp",32+4); + &mov ($a1,$a); + &lea ($a2,&DWP(0,$a,$a)); + &and ($a1,0x3fffffff); + &lea ($a4,&DWP(0,$a2,$a2)); + &mov (&DWP(0*4,"esp"),0); + &and ($a2,0x7fffffff); + &movd ($A,$a); + &movd ($B,$b); + &mov (&DWP(1*4,"esp"),$a1); # a1 + &xor ($a1,$a2); # a1^a2 + &pxor ($B31,$B31); + &pxor ($B30,$B30); + &mov (&DWP(2*4,"esp"),$a2); # a2 + &xor ($a2,$a4); # a2^a4 + &mov (&DWP(3*4,"esp"),$a1); # a1^a2 + &pcmpgtd($B31,$A); # broadcast 31st bit + &paddd ($A,$A); # $A<<=1 + &xor ($a1,$a2); # a1^a4=a1^a2^a2^a4 + &mov (&DWP(4*4,"esp"),$a4); # a4 + &xor ($a4,$a2); # a2=a4^a2^a4 + &pand ($B31,$B); + &pcmpgtd($B30,$A); # broadcast 30th bit + &mov (&DWP(5*4,"esp"),$a1); # a1^a4 + &xor ($a4,$a1); # a1^a2^a4 + &psllq ($B31,31); + &pand ($B30,$B); + &mov (&DWP(6*4,"esp"),$a2); # a2^a4 + &mov (@i[0],0x7); + &mov (&DWP(7*4,"esp"),$a4); # a1^a2^a4 + &mov ($a4,@i[0]); + &and (@i[0],$b); + &shr ($b,3); + &mov (@i[1],$a4); + &psllq ($B30,30); + &and (@i[1],$b); + &shr ($b,3); + &movd ($R,&DWP(0,"esp",@i[0],4)); + &mov (@i[0],$a4); + &and (@i[0],$b); + &shr ($b,3); + for($n=1;$n<9;$n++) { + &movd (@T[1],&DWP(0,"esp",@i[1],4)); + &mov (@i[1],$a4); + &psllq (@T[1],3*$n); + &and (@i[1],$b); + &shr ($b,3); + &pxor ($R,@T[1]); + + push(@i,shift(@i)); push(@T,shift(@T)); + } + &movd (@T[1],&DWP(0,"esp",@i[1],4)); + &pxor ($R,$B30); + &psllq (@T[1],3*$n++); + &pxor ($R,@T[1]); + + &movd (@T[0],&DWP(0,"esp",@i[0],4)); + &pxor ($R,$B31); + &psllq (@T[0],3*$n); + &add ("esp",32+4); + &pxor ($R,@T[0]); + &ret (); +&function_end_B("_mul_1x1_mmx"); + } + +($lo,$hi)=("eax","edx"); +@T=("ecx","ebp"); + +&function_begin_B("_mul_1x1_ialu"); + &sub ("esp",32+4); + &mov ($a1,$a); + &lea ($a2,&DWP(0,$a,$a)); + &lea ($a4,&DWP(0,"",$a,4)); + &and ($a1,0x3fffffff); + &lea (@i[1],&DWP(0,$lo,$lo)); + &sar ($lo,31); # broadcast 31st bit + &mov (&DWP(0*4,"esp"),0); + &and ($a2,0x7fffffff); + &mov (&DWP(1*4,"esp"),$a1); # a1 + &xor ($a1,$a2); # a1^a2 + &mov (&DWP(2*4,"esp"),$a2); # a2 + &xor ($a2,$a4); # a2^a4 + &mov (&DWP(3*4,"esp"),$a1); # a1^a2 + &xor ($a1,$a2); # a1^a4=a1^a2^a2^a4 + &mov (&DWP(4*4,"esp"),$a4); # a4 + &xor ($a4,$a2); # a2=a4^a2^a4 + &mov (&DWP(5*4,"esp"),$a1); # a1^a4 + &xor ($a4,$a1); # a1^a2^a4 + &sar (@i[1],31); # broadcast 30th bit + &and ($lo,$b); + &mov (&DWP(6*4,"esp"),$a2); # a2^a4 + &and (@i[1],$b); + &mov (&DWP(7*4,"esp"),$a4); # a1^a2^a4 + &mov ($hi,$lo); + &shl ($lo,31); + &mov (@T[0],@i[1]); + &shr ($hi,1); + + &mov (@i[0],0x7); + &shl (@i[1],30); + &and (@i[0],$b); + &shr (@T[0],2); + &xor ($lo,@i[1]); + + &shr ($b,3); + &mov (@i[1],0x7); # 5-byte instruction!? + &and (@i[1],$b); + &shr ($b,3); + &xor ($hi,@T[0]); + &xor ($lo,&DWP(0,"esp",@i[0],4)); + &mov (@i[0],0x7); + &and (@i[0],$b); + &shr ($b,3); + for($n=1;$n<9;$n++) { + &mov (@T[1],&DWP(0,"esp",@i[1],4)); + &mov (@i[1],0x7); + &mov (@T[0],@T[1]); + &shl (@T[1],3*$n); + &and (@i[1],$b); + &shr (@T[0],32-3*$n); + &xor ($lo,@T[1]); + &shr ($b,3); + &xor ($hi,@T[0]); + + push(@i,shift(@i)); push(@T,shift(@T)); + } + &mov (@T[1],&DWP(0,"esp",@i[1],4)); + &mov (@T[0],@T[1]); + &shl (@T[1],3*$n); + &mov (@i[1],&DWP(0,"esp",@i[0],4)); + &shr (@T[0],32-3*$n); $n++; + &mov (@i[0],@i[1]); + &xor ($lo,@T[1]); + &shl (@i[1],3*$n); + &xor ($hi,@T[0]); + &shr (@i[0],32-3*$n); + &xor ($lo,@i[1]); + &xor ($hi,@i[0]); + + &add ("esp",32+4); + &ret (); +&function_end_B("_mul_1x1_ialu"); + +# void bn_GF2m_mul_2x2(BN_ULONG *r, BN_ULONG a1, BN_ULONG a0, BN_ULONG b1, BN_ULONG b0); +&function_begin_B("bn_GF2m_mul_2x2"); +if (!$x86only) { + &picmeup("edx","OPENSSL_ia32cap_P"); + &mov ("eax",&DWP(0,"edx")); + &mov ("edx",&DWP(4,"edx")); + &test ("eax",1<<23); # check MMX bit + &jz (&label("ialu")); +if ($sse2) { + &test ("eax",1<<24); # check FXSR bit + &jz (&label("mmx")); + &test ("edx",1<<1); # check PCLMULQDQ bit + &jz (&label("mmx")); + + &movups ("xmm0",&QWP(8,"esp")); + &shufps ("xmm0","xmm0",0b10110001); + &pclmulqdq ("xmm0","xmm0",1); + &mov ("eax",&DWP(4,"esp")); + &movups (&QWP(0,"eax"),"xmm0"); + &ret (); + +&set_label("mmx",16); +} + &push ("ebp"); + &push ("ebx"); + &push ("esi"); + &push ("edi"); + &mov ($a,&wparam(1)); + &mov ($b,&wparam(3)); + &call ("_mul_1x1_mmx"); # a1·b1 + &movq ("mm7",$R); + + &mov ($a,&wparam(2)); + &mov ($b,&wparam(4)); + &call ("_mul_1x1_mmx"); # a0·b0 + &movq ("mm6",$R); + + &mov ($a,&wparam(1)); + &mov ($b,&wparam(3)); + &xor ($a,&wparam(2)); + &xor ($b,&wparam(4)); + &call ("_mul_1x1_mmx"); # (a0+a1)·(b0+b1) + &pxor ($R,"mm7"); + &mov ($a,&wparam(0)); + &pxor ($R,"mm6"); # (a0+a1)·(b0+b1)-a1·b1-a0·b0 + + &movq ($A,$R); + &psllq ($R,32); + &pop ("edi"); + &psrlq ($A,32); + &pop ("esi"); + &pxor ($R,"mm6"); + &pop ("ebx"); + &pxor ($A,"mm7"); + &movq (&QWP(0,$a),$R); + &pop ("ebp"); + &movq (&QWP(8,$a),$A); + &emms (); + &ret (); +&set_label("ialu",16); +} + &push ("ebp"); + &push ("ebx"); + &push ("esi"); + &push ("edi"); + &stack_push(4+1); + + &mov ($a,&wparam(1)); + &mov ($b,&wparam(3)); + &call ("_mul_1x1_ialu"); # a1·b1 + &mov (&DWP(8,"esp"),$lo); + &mov (&DWP(12,"esp"),$hi); + + &mov ($a,&wparam(2)); + &mov ($b,&wparam(4)); + &call ("_mul_1x1_ialu"); # a0·b0 + &mov (&DWP(0,"esp"),$lo); + &mov (&DWP(4,"esp"),$hi); + + &mov ($a,&wparam(1)); + &mov ($b,&wparam(3)); + &xor ($a,&wparam(2)); + &xor ($b,&wparam(4)); + &call ("_mul_1x1_ialu"); # (a0+a1)·(b0+b1) + + &mov ("ebp",&wparam(0)); + @r=("ebx","ecx","edi","esi"); + &mov (@r[0],&DWP(0,"esp")); + &mov (@r[1],&DWP(4,"esp")); + &mov (@r[2],&DWP(8,"esp")); + &mov (@r[3],&DWP(12,"esp")); + + &xor ($lo,$hi); + &xor ($hi,@r[1]); + &xor ($lo,@r[0]); + &mov (&DWP(0,"ebp"),@r[0]); + &xor ($hi,@r[2]); + &mov (&DWP(12,"ebp"),@r[3]); + &xor ($lo,@r[3]); + &stack_pop(4+1); + &xor ($hi,@r[3]); + &pop ("edi"); + &xor ($lo,$hi); + &pop ("esi"); + &mov (&DWP(8,"ebp"),$hi); + &pop ("ebx"); + &mov (&DWP(4,"ebp"),$lo); + &pop ("ebp"); + &ret (); +&function_end_B("bn_GF2m_mul_2x2"); + +&asciz ("GF(2^m) Multiplication for x86, CRYPTOGAMS by "); + +&asm_finish(); + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/x86-mont.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/x86-mont.pl new file mode 100755 index 000000000..7ba2133ac --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/x86-mont.pl @@ -0,0 +1,631 @@ +#! /usr/bin/env perl +# Copyright 2005-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# October 2005 +# +# This is a "teaser" code, as it can be improved in several ways... +# First of all non-SSE2 path should be implemented (yes, for now it +# performs Montgomery multiplication/convolution only on SSE2-capable +# CPUs such as P4, others fall down to original code). Then inner loop +# can be unrolled and modulo-scheduled to improve ILP and possibly +# moved to 128-bit XMM register bank (though it would require input +# rearrangement and/or increase bus bandwidth utilization). Dedicated +# squaring procedure should give further performance improvement... +# Yet, for being draft, the code improves rsa512 *sign* benchmark by +# 110%(!), rsa1024 one - by 70% and rsa4096 - by 20%:-) + +# December 2006 +# +# Modulo-scheduling SSE2 loops results in further 15-20% improvement. +# Integer-only code [being equipped with dedicated squaring procedure] +# gives ~40% on rsa512 sign benchmark... + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +$output = pop; +open STDOUT,">$output"; + +&asm_init($ARGV[0]); + +$sse2=0; +for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); } + +&external_label("OPENSSL_ia32cap_P") if ($sse2); + +&function_begin("bn_mul_mont"); + +$i="edx"; +$j="ecx"; +$ap="esi"; $tp="esi"; # overlapping variables!!! +$rp="edi"; $bp="edi"; # overlapping variables!!! +$np="ebp"; +$num="ebx"; + +$_num=&DWP(4*0,"esp"); # stack top layout +$_rp=&DWP(4*1,"esp"); +$_ap=&DWP(4*2,"esp"); +$_bp=&DWP(4*3,"esp"); +$_np=&DWP(4*4,"esp"); +$_n0=&DWP(4*5,"esp"); $_n0q=&QWP(4*5,"esp"); +$_sp=&DWP(4*6,"esp"); +$_bpend=&DWP(4*7,"esp"); +$frame=32; # size of above frame rounded up to 16n + + &xor ("eax","eax"); + &mov ("edi",&wparam(5)); # int num + &cmp ("edi",4); + &jl (&label("just_leave")); + + &lea ("esi",&wparam(0)); # put aside pointer to argument block + &lea ("edx",&wparam(1)); # load ap + &add ("edi",2); # extra two words on top of tp + &neg ("edi"); + &lea ("ebp",&DWP(-$frame,"esp","edi",4)); # future alloca($frame+4*(num+2)) + &neg ("edi"); + + # minimize cache contention by arranging 2K window between stack + # pointer and ap argument [np is also position sensitive vector, + # but it's assumed to be near ap, as it's allocated at ~same + # time]. + &mov ("eax","ebp"); + &sub ("eax","edx"); + &and ("eax",2047); + &sub ("ebp","eax"); # this aligns sp and ap modulo 2048 + + &xor ("edx","ebp"); + &and ("edx",2048); + &xor ("edx",2048); + &sub ("ebp","edx"); # this splits them apart modulo 4096 + + &and ("ebp",-64); # align to cache line + + # An OS-agnostic version of __chkstk. + # + # Some OSes (Windows) insist on stack being "wired" to + # physical memory in strictly sequential manner, i.e. if stack + # allocation spans two pages, then reference to farmost one can + # be punishable by SEGV. But page walking can do good even on + # other OSes, because it guarantees that villain thread hits + # the guard page before it can make damage to innocent one... + &mov ("eax","esp"); + &sub ("eax","ebp"); + &and ("eax",-4096); + &mov ("edx","esp"); # saved stack pointer! + &lea ("esp",&DWP(0,"ebp","eax")); + &mov ("eax",&DWP(0,"esp")); + &cmp ("esp","ebp"); + &ja (&label("page_walk")); + &jmp (&label("page_walk_done")); + +&set_label("page_walk",16); + &lea ("esp",&DWP(-4096,"esp")); + &mov ("eax",&DWP(0,"esp")); + &cmp ("esp","ebp"); + &ja (&label("page_walk")); +&set_label("page_walk_done"); + + ################################# load argument block... + &mov ("eax",&DWP(0*4,"esi"));# BN_ULONG *rp + &mov ("ebx",&DWP(1*4,"esi"));# const BN_ULONG *ap + &mov ("ecx",&DWP(2*4,"esi"));# const BN_ULONG *bp + &mov ("ebp",&DWP(3*4,"esi"));# const BN_ULONG *np + &mov ("esi",&DWP(4*4,"esi"));# const BN_ULONG *n0 + #&mov ("edi",&DWP(5*4,"esi"));# int num + + &mov ("esi",&DWP(0,"esi")); # pull n0[0] + &mov ($_rp,"eax"); # ... save a copy of argument block + &mov ($_ap,"ebx"); + &mov ($_bp,"ecx"); + &mov ($_np,"ebp"); + &mov ($_n0,"esi"); + &lea ($num,&DWP(-3,"edi")); # num=num-1 to assist modulo-scheduling + #&mov ($_num,$num); # redundant as $num is not reused + &mov ($_sp,"edx"); # saved stack pointer! + +if($sse2) { +$acc0="mm0"; # mmx register bank layout +$acc1="mm1"; +$car0="mm2"; +$car1="mm3"; +$mul0="mm4"; +$mul1="mm5"; +$temp="mm6"; +$mask="mm7"; + + &picmeup("eax","OPENSSL_ia32cap_P"); + &bt (&DWP(0,"eax"),26); + &jnc (&label("non_sse2")); + + &mov ("eax",-1); + &movd ($mask,"eax"); # mask 32 lower bits + + &mov ($ap,$_ap); # load input pointers + &mov ($bp,$_bp); + &mov ($np,$_np); + + &xor ($i,$i); # i=0 + &xor ($j,$j); # j=0 + + &movd ($mul0,&DWP(0,$bp)); # bp[0] + &movd ($mul1,&DWP(0,$ap)); # ap[0] + &movd ($car1,&DWP(0,$np)); # np[0] + + &pmuludq($mul1,$mul0); # ap[0]*bp[0] + &movq ($car0,$mul1); + &movq ($acc0,$mul1); # I wish movd worked for + &pand ($acc0,$mask); # inter-register transfers + + &pmuludq($mul1,$_n0q); # *=n0 + + &pmuludq($car1,$mul1); # "t[0]"*np[0]*n0 + &paddq ($car1,$acc0); + + &movd ($acc1,&DWP(4,$np)); # np[1] + &movd ($acc0,&DWP(4,$ap)); # ap[1] + + &psrlq ($car0,32); + &psrlq ($car1,32); + + &inc ($j); # j++ +&set_label("1st",16); + &pmuludq($acc0,$mul0); # ap[j]*bp[0] + &pmuludq($acc1,$mul1); # np[j]*m1 + &paddq ($car0,$acc0); # +=c0 + &paddq ($car1,$acc1); # +=c1 + + &movq ($acc0,$car0); + &pand ($acc0,$mask); + &movd ($acc1,&DWP(4,$np,$j,4)); # np[j+1] + &paddq ($car1,$acc0); # +=ap[j]*bp[0]; + &movd ($acc0,&DWP(4,$ap,$j,4)); # ap[j+1] + &psrlq ($car0,32); + &movd (&DWP($frame-4,"esp",$j,4),$car1); # tp[j-1]= + &psrlq ($car1,32); + + &lea ($j,&DWP(1,$j)); + &cmp ($j,$num); + &jl (&label("1st")); + + &pmuludq($acc0,$mul0); # ap[num-1]*bp[0] + &pmuludq($acc1,$mul1); # np[num-1]*m1 + &paddq ($car0,$acc0); # +=c0 + &paddq ($car1,$acc1); # +=c1 + + &movq ($acc0,$car0); + &pand ($acc0,$mask); + &paddq ($car1,$acc0); # +=ap[num-1]*bp[0]; + &movd (&DWP($frame-4,"esp",$j,4),$car1); # tp[num-2]= + + &psrlq ($car0,32); + &psrlq ($car1,32); + + &paddq ($car1,$car0); + &movq (&QWP($frame,"esp",$num,4),$car1); # tp[num].tp[num-1] + + &inc ($i); # i++ +&set_label("outer"); + &xor ($j,$j); # j=0 + + &movd ($mul0,&DWP(0,$bp,$i,4)); # bp[i] + &movd ($mul1,&DWP(0,$ap)); # ap[0] + &movd ($temp,&DWP($frame,"esp")); # tp[0] + &movd ($car1,&DWP(0,$np)); # np[0] + &pmuludq($mul1,$mul0); # ap[0]*bp[i] + + &paddq ($mul1,$temp); # +=tp[0] + &movq ($acc0,$mul1); + &movq ($car0,$mul1); + &pand ($acc0,$mask); + + &pmuludq($mul1,$_n0q); # *=n0 + + &pmuludq($car1,$mul1); + &paddq ($car1,$acc0); + + &movd ($temp,&DWP($frame+4,"esp")); # tp[1] + &movd ($acc1,&DWP(4,$np)); # np[1] + &movd ($acc0,&DWP(4,$ap)); # ap[1] + + &psrlq ($car0,32); + &psrlq ($car1,32); + &paddq ($car0,$temp); # +=tp[1] + + &inc ($j); # j++ + &dec ($num); +&set_label("inner"); + &pmuludq($acc0,$mul0); # ap[j]*bp[i] + &pmuludq($acc1,$mul1); # np[j]*m1 + &paddq ($car0,$acc0); # +=c0 + &paddq ($car1,$acc1); # +=c1 + + &movq ($acc0,$car0); + &movd ($temp,&DWP($frame+4,"esp",$j,4));# tp[j+1] + &pand ($acc0,$mask); + &movd ($acc1,&DWP(4,$np,$j,4)); # np[j+1] + &paddq ($car1,$acc0); # +=ap[j]*bp[i]+tp[j] + &movd ($acc0,&DWP(4,$ap,$j,4)); # ap[j+1] + &psrlq ($car0,32); + &movd (&DWP($frame-4,"esp",$j,4),$car1);# tp[j-1]= + &psrlq ($car1,32); + &paddq ($car0,$temp); # +=tp[j+1] + + &dec ($num); + &lea ($j,&DWP(1,$j)); # j++ + &jnz (&label("inner")); + + &mov ($num,$j); + &pmuludq($acc0,$mul0); # ap[num-1]*bp[i] + &pmuludq($acc1,$mul1); # np[num-1]*m1 + &paddq ($car0,$acc0); # +=c0 + &paddq ($car1,$acc1); # +=c1 + + &movq ($acc0,$car0); + &pand ($acc0,$mask); + &paddq ($car1,$acc0); # +=ap[num-1]*bp[i]+tp[num-1] + &movd (&DWP($frame-4,"esp",$j,4),$car1); # tp[num-2]= + &psrlq ($car0,32); + &psrlq ($car1,32); + + &movd ($temp,&DWP($frame+4,"esp",$num,4)); # += tp[num] + &paddq ($car1,$car0); + &paddq ($car1,$temp); + &movq (&QWP($frame,"esp",$num,4),$car1); # tp[num].tp[num-1] + + &lea ($i,&DWP(1,$i)); # i++ + &cmp ($i,$num); + &jle (&label("outer")); + + &emms (); # done with mmx bank + &jmp (&label("common_tail")); + +&set_label("non_sse2",16); +} + +if (0) { + &mov ("esp",$_sp); + &xor ("eax","eax"); # signal "not fast enough [yet]" + &jmp (&label("just_leave")); + # While the below code provides competitive performance for + # all key lengths on modern Intel cores, it's still more + # than 10% slower for 4096-bit key elsewhere:-( "Competitive" + # means compared to the original integer-only assembler. + # 512-bit RSA sign is better by ~40%, but that's about all + # one can say about all CPUs... +} else { +$inp="esi"; # integer path uses these registers differently +$word="edi"; +$carry="ebp"; + + &mov ($inp,$_ap); + &lea ($carry,&DWP(1,$num)); + &mov ($word,$_bp); + &xor ($j,$j); # j=0 + &mov ("edx",$inp); + &and ($carry,1); # see if num is even + &sub ("edx",$word); # see if ap==bp + &lea ("eax",&DWP(4,$word,$num,4)); # &bp[num] + &or ($carry,"edx"); + &mov ($word,&DWP(0,$word)); # bp[0] + &jz (&label("bn_sqr_mont")); + &mov ($_bpend,"eax"); + &mov ("eax",&DWP(0,$inp)); + &xor ("edx","edx"); + +&set_label("mull",16); + &mov ($carry,"edx"); + &mul ($word); # ap[j]*bp[0] + &add ($carry,"eax"); + &lea ($j,&DWP(1,$j)); + &adc ("edx",0); + &mov ("eax",&DWP(0,$inp,$j,4)); # ap[j+1] + &cmp ($j,$num); + &mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j]= + &jl (&label("mull")); + + &mov ($carry,"edx"); + &mul ($word); # ap[num-1]*bp[0] + &mov ($word,$_n0); + &add ("eax",$carry); + &mov ($inp,$_np); + &adc ("edx",0); + &imul ($word,&DWP($frame,"esp")); # n0*tp[0] + + &mov (&DWP($frame,"esp",$num,4),"eax"); # tp[num-1]= + &xor ($j,$j); + &mov (&DWP($frame+4,"esp",$num,4),"edx"); # tp[num]= + &mov (&DWP($frame+8,"esp",$num,4),$j); # tp[num+1]= + + &mov ("eax",&DWP(0,$inp)); # np[0] + &mul ($word); # np[0]*m + &add ("eax",&DWP($frame,"esp")); # +=tp[0] + &mov ("eax",&DWP(4,$inp)); # np[1] + &adc ("edx",0); + &inc ($j); + + &jmp (&label("2ndmadd")); + +&set_label("1stmadd",16); + &mov ($carry,"edx"); + &mul ($word); # ap[j]*bp[i] + &add ($carry,&DWP($frame,"esp",$j,4)); # +=tp[j] + &lea ($j,&DWP(1,$j)); + &adc ("edx",0); + &add ($carry,"eax"); + &mov ("eax",&DWP(0,$inp,$j,4)); # ap[j+1] + &adc ("edx",0); + &cmp ($j,$num); + &mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j]= + &jl (&label("1stmadd")); + + &mov ($carry,"edx"); + &mul ($word); # ap[num-1]*bp[i] + &add ("eax",&DWP($frame,"esp",$num,4)); # +=tp[num-1] + &mov ($word,$_n0); + &adc ("edx",0); + &mov ($inp,$_np); + &add ($carry,"eax"); + &adc ("edx",0); + &imul ($word,&DWP($frame,"esp")); # n0*tp[0] + + &xor ($j,$j); + &add ("edx",&DWP($frame+4,"esp",$num,4)); # carry+=tp[num] + &mov (&DWP($frame,"esp",$num,4),$carry); # tp[num-1]= + &adc ($j,0); + &mov ("eax",&DWP(0,$inp)); # np[0] + &mov (&DWP($frame+4,"esp",$num,4),"edx"); # tp[num]= + &mov (&DWP($frame+8,"esp",$num,4),$j); # tp[num+1]= + + &mul ($word); # np[0]*m + &add ("eax",&DWP($frame,"esp")); # +=tp[0] + &mov ("eax",&DWP(4,$inp)); # np[1] + &adc ("edx",0); + &mov ($j,1); + +&set_label("2ndmadd",16); + &mov ($carry,"edx"); + &mul ($word); # np[j]*m + &add ($carry,&DWP($frame,"esp",$j,4)); # +=tp[j] + &lea ($j,&DWP(1,$j)); + &adc ("edx",0); + &add ($carry,"eax"); + &mov ("eax",&DWP(0,$inp,$j,4)); # np[j+1] + &adc ("edx",0); + &cmp ($j,$num); + &mov (&DWP($frame-8,"esp",$j,4),$carry); # tp[j-1]= + &jl (&label("2ndmadd")); + + &mov ($carry,"edx"); + &mul ($word); # np[j]*m + &add ($carry,&DWP($frame,"esp",$num,4)); # +=tp[num-1] + &adc ("edx",0); + &add ($carry,"eax"); + &adc ("edx",0); + &mov (&DWP($frame-4,"esp",$num,4),$carry); # tp[num-2]= + + &xor ("eax","eax"); + &mov ($j,$_bp); # &bp[i] + &add ("edx",&DWP($frame+4,"esp",$num,4)); # carry+=tp[num] + &adc ("eax",&DWP($frame+8,"esp",$num,4)); # +=tp[num+1] + &lea ($j,&DWP(4,$j)); + &mov (&DWP($frame,"esp",$num,4),"edx"); # tp[num-1]= + &cmp ($j,$_bpend); + &mov (&DWP($frame+4,"esp",$num,4),"eax"); # tp[num]= + &je (&label("common_tail")); + + &mov ($word,&DWP(0,$j)); # bp[i+1] + &mov ($inp,$_ap); + &mov ($_bp,$j); # &bp[++i] + &xor ($j,$j); + &xor ("edx","edx"); + &mov ("eax",&DWP(0,$inp)); + &jmp (&label("1stmadd")); + +&set_label("bn_sqr_mont",16); +$sbit=$num; + &mov ($_num,$num); + &mov ($_bp,$j); # i=0 + + &mov ("eax",$word); # ap[0] + &mul ($word); # ap[0]*ap[0] + &mov (&DWP($frame,"esp"),"eax"); # tp[0]= + &mov ($sbit,"edx"); + &shr ("edx",1); + &and ($sbit,1); + &inc ($j); +&set_label("sqr",16); + &mov ("eax",&DWP(0,$inp,$j,4)); # ap[j] + &mov ($carry,"edx"); + &mul ($word); # ap[j]*ap[0] + &add ("eax",$carry); + &lea ($j,&DWP(1,$j)); + &adc ("edx",0); + &lea ($carry,&DWP(0,$sbit,"eax",2)); + &shr ("eax",31); + &cmp ($j,$_num); + &mov ($sbit,"eax"); + &mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j]= + &jl (&label("sqr")); + + &mov ("eax",&DWP(0,$inp,$j,4)); # ap[num-1] + &mov ($carry,"edx"); + &mul ($word); # ap[num-1]*ap[0] + &add ("eax",$carry); + &mov ($word,$_n0); + &adc ("edx",0); + &mov ($inp,$_np); + &lea ($carry,&DWP(0,$sbit,"eax",2)); + &imul ($word,&DWP($frame,"esp")); # n0*tp[0] + &shr ("eax",31); + &mov (&DWP($frame,"esp",$j,4),$carry); # tp[num-1]= + + &lea ($carry,&DWP(0,"eax","edx",2)); + &mov ("eax",&DWP(0,$inp)); # np[0] + &shr ("edx",31); + &mov (&DWP($frame+4,"esp",$j,4),$carry); # tp[num]= + &mov (&DWP($frame+8,"esp",$j,4),"edx"); # tp[num+1]= + + &mul ($word); # np[0]*m + &add ("eax",&DWP($frame,"esp")); # +=tp[0] + &mov ($num,$j); + &adc ("edx",0); + &mov ("eax",&DWP(4,$inp)); # np[1] + &mov ($j,1); + +&set_label("3rdmadd",16); + &mov ($carry,"edx"); + &mul ($word); # np[j]*m + &add ($carry,&DWP($frame,"esp",$j,4)); # +=tp[j] + &adc ("edx",0); + &add ($carry,"eax"); + &mov ("eax",&DWP(4,$inp,$j,4)); # np[j+1] + &adc ("edx",0); + &mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j-1]= + + &mov ($carry,"edx"); + &mul ($word); # np[j+1]*m + &add ($carry,&DWP($frame+4,"esp",$j,4)); # +=tp[j+1] + &lea ($j,&DWP(2,$j)); + &adc ("edx",0); + &add ($carry,"eax"); + &mov ("eax",&DWP(0,$inp,$j,4)); # np[j+2] + &adc ("edx",0); + &cmp ($j,$num); + &mov (&DWP($frame-8,"esp",$j,4),$carry); # tp[j]= + &jl (&label("3rdmadd")); + + &mov ($carry,"edx"); + &mul ($word); # np[j]*m + &add ($carry,&DWP($frame,"esp",$num,4)); # +=tp[num-1] + &adc ("edx",0); + &add ($carry,"eax"); + &adc ("edx",0); + &mov (&DWP($frame-4,"esp",$num,4),$carry); # tp[num-2]= + + &mov ($j,$_bp); # i + &xor ("eax","eax"); + &mov ($inp,$_ap); + &add ("edx",&DWP($frame+4,"esp",$num,4)); # carry+=tp[num] + &adc ("eax",&DWP($frame+8,"esp",$num,4)); # +=tp[num+1] + &mov (&DWP($frame,"esp",$num,4),"edx"); # tp[num-1]= + &cmp ($j,$num); + &mov (&DWP($frame+4,"esp",$num,4),"eax"); # tp[num]= + &je (&label("common_tail")); + + &mov ($word,&DWP(4,$inp,$j,4)); # ap[i] + &lea ($j,&DWP(1,$j)); + &mov ("eax",$word); + &mov ($_bp,$j); # ++i + &mul ($word); # ap[i]*ap[i] + &add ("eax",&DWP($frame,"esp",$j,4)); # +=tp[i] + &adc ("edx",0); + &mov (&DWP($frame,"esp",$j,4),"eax"); # tp[i]= + &xor ($carry,$carry); + &cmp ($j,$num); + &lea ($j,&DWP(1,$j)); + &je (&label("sqrlast")); + + &mov ($sbit,"edx"); # zaps $num + &shr ("edx",1); + &and ($sbit,1); +&set_label("sqradd",16); + &mov ("eax",&DWP(0,$inp,$j,4)); # ap[j] + &mov ($carry,"edx"); + &mul ($word); # ap[j]*ap[i] + &add ("eax",$carry); + &lea ($carry,&DWP(0,"eax","eax")); + &adc ("edx",0); + &shr ("eax",31); + &add ($carry,&DWP($frame,"esp",$j,4)); # +=tp[j] + &lea ($j,&DWP(1,$j)); + &adc ("eax",0); + &add ($carry,$sbit); + &adc ("eax",0); + &cmp ($j,$_num); + &mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j]= + &mov ($sbit,"eax"); + &jle (&label("sqradd")); + + &mov ($carry,"edx"); + &add ("edx","edx"); + &shr ($carry,31); + &add ("edx",$sbit); + &adc ($carry,0); +&set_label("sqrlast"); + &mov ($word,$_n0); + &mov ($inp,$_np); + &imul ($word,&DWP($frame,"esp")); # n0*tp[0] + + &add ("edx",&DWP($frame,"esp",$j,4)); # +=tp[num] + &mov ("eax",&DWP(0,$inp)); # np[0] + &adc ($carry,0); + &mov (&DWP($frame,"esp",$j,4),"edx"); # tp[num]= + &mov (&DWP($frame+4,"esp",$j,4),$carry); # tp[num+1]= + + &mul ($word); # np[0]*m + &add ("eax",&DWP($frame,"esp")); # +=tp[0] + &lea ($num,&DWP(-1,$j)); + &adc ("edx",0); + &mov ($j,1); + &mov ("eax",&DWP(4,$inp)); # np[1] + + &jmp (&label("3rdmadd")); +} + +&set_label("common_tail",16); + &mov ($np,$_np); # load modulus pointer + &mov ($rp,$_rp); # load result pointer + &lea ($tp,&DWP($frame,"esp")); # [$ap and $bp are zapped] + + &mov ("eax",&DWP(0,$tp)); # tp[0] + &mov ($j,$num); # j=num-1 + &xor ($i,$i); # i=0 and clear CF! + +&set_label("sub",16); + &sbb ("eax",&DWP(0,$np,$i,4)); + &mov (&DWP(0,$rp,$i,4),"eax"); # rp[i]=tp[i]-np[i] + &dec ($j); # doesn't affect CF! + &mov ("eax",&DWP(4,$tp,$i,4)); # tp[i+1] + &lea ($i,&DWP(1,$i)); # i++ + &jge (&label("sub")); + + &sbb ("eax",0); # handle upmost overflow bit + &mov ("edx",-1); + &xor ("edx","eax"); + &jmp (&label("copy")); + +&set_label("copy",16); # conditional copy + &mov ($tp,&DWP($frame,"esp",$num,4)); + &mov ($np,&DWP(0,$rp,$num,4)); + &mov (&DWP($frame,"esp",$num,4),$j); # zap temporary vector + &and ($tp,"eax"); + &and ($np,"edx"); + &or ($np,$tp); + &mov (&DWP(0,$rp,$num,4),$np); + &dec ($num); + &jge (&label("copy")); + + &mov ("esp",$_sp); # pull saved stack pointer + &mov ("eax",1); +&set_label("just_leave"); +&function_end("bn_mul_mont"); + +&asciz("Montgomery Multiplication for x86, CRYPTOGAMS by "); + +&asm_finish(); + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/x86_64-gcc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/x86_64-gcc.c new file mode 100644 index 000000000..31839ba06 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/x86_64-gcc.c @@ -0,0 +1,643 @@ +/* + * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "../bn_lcl.h" +#if !(defined(__GNUC__) && __GNUC__>=2) +# include "../bn_asm.c" /* kind of dirty hack for Sun Studio */ +#else +/*- + * x86_64 BIGNUM accelerator version 0.1, December 2002. + * + * Implemented by Andy Polyakov for the OpenSSL + * project. + * + * Rights for redistribution and usage in source and binary forms are + * granted according to the OpenSSL license. Warranty of any kind is + * disclaimed. + * + * Q. Version 0.1? It doesn't sound like Andy, he used to assign real + * versions, like 1.0... + * A. Well, that's because this code is basically a quick-n-dirty + * proof-of-concept hack. As you can see it's implemented with + * inline assembler, which means that you're bound to GCC and that + * there might be enough room for further improvement. + * + * Q. Why inline assembler? + * A. x86_64 features own ABI which I'm not familiar with. This is + * why I decided to let the compiler take care of subroutine + * prologue/epilogue as well as register allocation. For reference. + * Win64 implements different ABI for AMD64, different from Linux. + * + * Q. How much faster does it get? + * A. 'apps/openssl speed rsa dsa' output with no-asm: + * + * sign verify sign/s verify/s + * rsa 512 bits 0.0006s 0.0001s 1683.8 18456.2 + * rsa 1024 bits 0.0028s 0.0002s 356.0 6407.0 + * rsa 2048 bits 0.0172s 0.0005s 58.0 1957.8 + * rsa 4096 bits 0.1155s 0.0018s 8.7 555.6 + * sign verify sign/s verify/s + * dsa 512 bits 0.0005s 0.0006s 2100.8 1768.3 + * dsa 1024 bits 0.0014s 0.0018s 692.3 559.2 + * dsa 2048 bits 0.0049s 0.0061s 204.7 165.0 + * + * 'apps/openssl speed rsa dsa' output with this module: + * + * sign verify sign/s verify/s + * rsa 512 bits 0.0004s 0.0000s 2767.1 33297.9 + * rsa 1024 bits 0.0012s 0.0001s 867.4 14674.7 + * rsa 2048 bits 0.0061s 0.0002s 164.0 5270.0 + * rsa 4096 bits 0.0384s 0.0006s 26.1 1650.8 + * sign verify sign/s verify/s + * dsa 512 bits 0.0002s 0.0003s 4442.2 3786.3 + * dsa 1024 bits 0.0005s 0.0007s 1835.1 1497.4 + * dsa 2048 bits 0.0016s 0.0020s 620.4 504.6 + * + * For the reference. IA-32 assembler implementation performs + * very much like 64-bit code compiled with no-asm on the same + * machine. + */ + +# undef mul +# undef mul_add + +/*- + * "m"(a), "+m"(r) is the way to favor DirectPath µ-code; + * "g"(0) let the compiler to decide where does it + * want to keep the value of zero; + */ +# define mul_add(r,a,word,carry) do { \ + register BN_ULONG high,low; \ + asm ("mulq %3" \ + : "=a"(low),"=d"(high) \ + : "a"(word),"m"(a) \ + : "cc"); \ + asm ("addq %2,%0; adcq %3,%1" \ + : "+r"(carry),"+d"(high)\ + : "a"(low),"g"(0) \ + : "cc"); \ + asm ("addq %2,%0; adcq %3,%1" \ + : "+m"(r),"+d"(high) \ + : "r"(carry),"g"(0) \ + : "cc"); \ + carry=high; \ + } while (0) + +# define mul(r,a,word,carry) do { \ + register BN_ULONG high,low; \ + asm ("mulq %3" \ + : "=a"(low),"=d"(high) \ + : "a"(word),"g"(a) \ + : "cc"); \ + asm ("addq %2,%0; adcq %3,%1" \ + : "+r"(carry),"+d"(high)\ + : "a"(low),"g"(0) \ + : "cc"); \ + (r)=carry, carry=high; \ + } while (0) +# undef sqr +# define sqr(r0,r1,a) \ + asm ("mulq %2" \ + : "=a"(r0),"=d"(r1) \ + : "a"(a) \ + : "cc"); + +BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, + BN_ULONG w) +{ + BN_ULONG c1 = 0; + + if (num <= 0) + return c1; + + while (num & ~3) { + mul_add(rp[0], ap[0], w, c1); + mul_add(rp[1], ap[1], w, c1); + mul_add(rp[2], ap[2], w, c1); + mul_add(rp[3], ap[3], w, c1); + ap += 4; + rp += 4; + num -= 4; + } + if (num) { + mul_add(rp[0], ap[0], w, c1); + if (--num == 0) + return c1; + mul_add(rp[1], ap[1], w, c1); + if (--num == 0) + return c1; + mul_add(rp[2], ap[2], w, c1); + return c1; + } + + return c1; +} + +BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) +{ + BN_ULONG c1 = 0; + + if (num <= 0) + return c1; + + while (num & ~3) { + mul(rp[0], ap[0], w, c1); + mul(rp[1], ap[1], w, c1); + mul(rp[2], ap[2], w, c1); + mul(rp[3], ap[3], w, c1); + ap += 4; + rp += 4; + num -= 4; + } + if (num) { + mul(rp[0], ap[0], w, c1); + if (--num == 0) + return c1; + mul(rp[1], ap[1], w, c1); + if (--num == 0) + return c1; + mul(rp[2], ap[2], w, c1); + } + return c1; +} + +void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) +{ + if (n <= 0) + return; + + while (n & ~3) { + sqr(r[0], r[1], a[0]); + sqr(r[2], r[3], a[1]); + sqr(r[4], r[5], a[2]); + sqr(r[6], r[7], a[3]); + a += 4; + r += 8; + n -= 4; + } + if (n) { + sqr(r[0], r[1], a[0]); + if (--n == 0) + return; + sqr(r[2], r[3], a[1]); + if (--n == 0) + return; + sqr(r[4], r[5], a[2]); + } +} + +BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) +{ + BN_ULONG ret, waste; + + asm("divq %4":"=a"(ret), "=d"(waste) + : "a"(l), "d"(h), "r"(d) + : "cc"); + + return ret; +} + +BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + int n) +{ + BN_ULONG ret; + size_t i = 0; + + if (n <= 0) + return 0; + + asm volatile (" subq %0,%0 \n" /* clear carry */ + " jmp 1f \n" + ".p2align 4 \n" + "1: movq (%4,%2,8),%0 \n" + " adcq (%5,%2,8),%0 \n" + " movq %0,(%3,%2,8) \n" + " lea 1(%2),%2 \n" + " dec %1 \n" + " jnz 1b \n" + " sbbq %0,%0 \n" + :"=&r" (ret), "+c"(n), "+r"(i) + :"r"(rp), "r"(ap), "r"(bp) + :"cc", "memory"); + + return ret & 1; +} + +# ifndef SIMICS +BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + int n) +{ + BN_ULONG ret; + size_t i = 0; + + if (n <= 0) + return 0; + + asm volatile (" subq %0,%0 \n" /* clear borrow */ + " jmp 1f \n" + ".p2align 4 \n" + "1: movq (%4,%2,8),%0 \n" + " sbbq (%5,%2,8),%0 \n" + " movq %0,(%3,%2,8) \n" + " lea 1(%2),%2 \n" + " dec %1 \n" + " jnz 1b \n" + " sbbq %0,%0 \n" + :"=&r" (ret), "+c"(n), "+r"(i) + :"r"(rp), "r"(ap), "r"(bp) + :"cc", "memory"); + + return ret & 1; +} +# else +/* Simics 1.4<7 has buggy sbbq:-( */ +# define BN_MASK2 0xffffffffffffffffL +BN_ULONG bn_sub_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) +{ + BN_ULONG t1, t2; + int c = 0; + + if (n <= 0) + return (BN_ULONG)0; + + for (;;) { + t1 = a[0]; + t2 = b[0]; + r[0] = (t1 - t2 - c) & BN_MASK2; + if (t1 != t2) + c = (t1 < t2); + if (--n <= 0) + break; + + t1 = a[1]; + t2 = b[1]; + r[1] = (t1 - t2 - c) & BN_MASK2; + if (t1 != t2) + c = (t1 < t2); + if (--n <= 0) + break; + + t1 = a[2]; + t2 = b[2]; + r[2] = (t1 - t2 - c) & BN_MASK2; + if (t1 != t2) + c = (t1 < t2); + if (--n <= 0) + break; + + t1 = a[3]; + t2 = b[3]; + r[3] = (t1 - t2 - c) & BN_MASK2; + if (t1 != t2) + c = (t1 < t2); + if (--n <= 0) + break; + + a += 4; + b += 4; + r += 4; + } + return c; +} +# endif + +/* mul_add_c(a,b,c0,c1,c2) -- c+=a*b for three word number c=(c2,c1,c0) */ +/* mul_add_c2(a,b,c0,c1,c2) -- c+=2*a*b for three word number c=(c2,c1,c0) */ +/* sqr_add_c(a,i,c0,c1,c2) -- c+=a[i]^2 for three word number c=(c2,c1,c0) */ +/* + * sqr_add_c2(a,i,c0,c1,c2) -- c+=2*a[i]*a[j] for three word number + * c=(c2,c1,c0) + */ + +/* + * Keep in mind that carrying into high part of multiplication result + * can not overflow, because it cannot be all-ones. + */ +# if 0 +/* original macros are kept for reference purposes */ +# define mul_add_c(a,b,c0,c1,c2) do { \ + BN_ULONG ta = (a), tb = (b); \ + BN_ULONG lo, hi; \ + BN_UMULT_LOHI(lo,hi,ta,tb); \ + c0 += lo; hi += (c0 for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# May 2011 +# +# The module implements bn_GF2m_mul_2x2 polynomial multiplication used +# in bn_gf2m.c. It's kind of low-hanging mechanical port from C for +# the time being... Except that it has two code paths: code suitable +# for any x86_64 CPU and PCLMULQDQ one suitable for Westmere and +# later. Improvement varies from one benchmark and µ-arch to another. +# Vanilla code path is at most 20% faster than compiler-generated code +# [not very impressive], while PCLMULQDQ - whole 85%-160% better on +# 163- and 571-bit ECDH benchmarks on Intel CPUs. Keep in mind that +# these coefficients are not ones for bn_GF2m_mul_2x2 itself, as not +# all CPU time is burnt in it... + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +*STDOUT=*OUT; + +($lo,$hi)=("%rax","%rdx"); $a=$lo; +($i0,$i1)=("%rsi","%rdi"); +($t0,$t1)=("%rbx","%rcx"); +($b,$mask)=("%rbp","%r8"); +($a1,$a2,$a4,$a8,$a12,$a48)=map("%r$_",(9..15)); +($R,$Tx)=("%xmm0","%xmm1"); + +$code.=<<___; +.text + +.type _mul_1x1,\@abi-omnipotent +.align 16 +_mul_1x1: +.cfi_startproc + sub \$128+8,%rsp +.cfi_adjust_cfa_offset 128+8 + mov \$-1,$a1 + lea ($a,$a),$i0 + shr \$3,$a1 + lea (,$a,4),$i1 + and $a,$a1 # a1=a&0x1fffffffffffffff + lea (,$a,8),$a8 + sar \$63,$a # broadcast 63rd bit + lea ($a1,$a1),$a2 + sar \$63,$i0 # broadcast 62nd bit + lea (,$a1,4),$a4 + and $b,$a + sar \$63,$i1 # broadcast 61st bit + mov $a,$hi # $a is $lo + shl \$63,$lo + and $b,$i0 + shr \$1,$hi + mov $i0,$t1 + shl \$62,$i0 + and $b,$i1 + shr \$2,$t1 + xor $i0,$lo + mov $i1,$t0 + shl \$61,$i1 + xor $t1,$hi + shr \$3,$t0 + xor $i1,$lo + xor $t0,$hi + + mov $a1,$a12 + movq \$0,0(%rsp) # tab[0]=0 + xor $a2,$a12 # a1^a2 + mov $a1,8(%rsp) # tab[1]=a1 + mov $a4,$a48 + mov $a2,16(%rsp) # tab[2]=a2 + xor $a8,$a48 # a4^a8 + mov $a12,24(%rsp) # tab[3]=a1^a2 + + xor $a4,$a1 + mov $a4,32(%rsp) # tab[4]=a4 + xor $a4,$a2 + mov $a1,40(%rsp) # tab[5]=a1^a4 + xor $a4,$a12 + mov $a2,48(%rsp) # tab[6]=a2^a4 + xor $a48,$a1 # a1^a4^a4^a8=a1^a8 + mov $a12,56(%rsp) # tab[7]=a1^a2^a4 + xor $a48,$a2 # a2^a4^a4^a8=a1^a8 + + mov $a8,64(%rsp) # tab[8]=a8 + xor $a48,$a12 # a1^a2^a4^a4^a8=a1^a2^a8 + mov $a1,72(%rsp) # tab[9]=a1^a8 + xor $a4,$a1 # a1^a8^a4 + mov $a2,80(%rsp) # tab[10]=a2^a8 + xor $a4,$a2 # a2^a8^a4 + mov $a12,88(%rsp) # tab[11]=a1^a2^a8 + + xor $a4,$a12 # a1^a2^a8^a4 + mov $a48,96(%rsp) # tab[12]=a4^a8 + mov $mask,$i0 + mov $a1,104(%rsp) # tab[13]=a1^a4^a8 + and $b,$i0 + mov $a2,112(%rsp) # tab[14]=a2^a4^a8 + shr \$4,$b + mov $a12,120(%rsp) # tab[15]=a1^a2^a4^a8 + mov $mask,$i1 + and $b,$i1 + shr \$4,$b + + movq (%rsp,$i0,8),$R # half of calculations is done in SSE2 + mov $mask,$i0 + and $b,$i0 + shr \$4,$b +___ + for ($n=1;$n<8;$n++) { + $code.=<<___; + mov (%rsp,$i1,8),$t1 + mov $mask,$i1 + mov $t1,$t0 + shl \$`8*$n-4`,$t1 + and $b,$i1 + movq (%rsp,$i0,8),$Tx + shr \$`64-(8*$n-4)`,$t0 + xor $t1,$lo + pslldq \$$n,$Tx + mov $mask,$i0 + shr \$4,$b + xor $t0,$hi + and $b,$i0 + shr \$4,$b + pxor $Tx,$R +___ + } +$code.=<<___; + mov (%rsp,$i1,8),$t1 + mov $t1,$t0 + shl \$`8*$n-4`,$t1 + movq $R,$i0 + shr \$`64-(8*$n-4)`,$t0 + xor $t1,$lo + psrldq \$8,$R + xor $t0,$hi + movq $R,$i1 + xor $i0,$lo + xor $i1,$hi + + add \$128+8,%rsp +.cfi_adjust_cfa_offset -128-8 + ret +.Lend_mul_1x1: +.cfi_endproc +.size _mul_1x1,.-_mul_1x1 +___ + +($rp,$a1,$a0,$b1,$b0) = $win64? ("%rcx","%rdx","%r8", "%r9","%r10") : # Win64 order + ("%rdi","%rsi","%rdx","%rcx","%r8"); # Unix order + +$code.=<<___; +.extern OPENSSL_ia32cap_P +.globl bn_GF2m_mul_2x2 +.type bn_GF2m_mul_2x2,\@abi-omnipotent +.align 16 +bn_GF2m_mul_2x2: +.cfi_startproc + mov %rsp,%rax + mov OPENSSL_ia32cap_P(%rip),%r10 + bt \$33,%r10 + jnc .Lvanilla_mul_2x2 + + movq $a1,%xmm0 + movq $b1,%xmm1 + movq $a0,%xmm2 +___ +$code.=<<___ if ($win64); + movq 40(%rsp),%xmm3 +___ +$code.=<<___ if (!$win64); + movq $b0,%xmm3 +___ +$code.=<<___; + movdqa %xmm0,%xmm4 + movdqa %xmm1,%xmm5 + pclmulqdq \$0,%xmm1,%xmm0 # a1·b1 + pxor %xmm2,%xmm4 + pxor %xmm3,%xmm5 + pclmulqdq \$0,%xmm3,%xmm2 # a0·b0 + pclmulqdq \$0,%xmm5,%xmm4 # (a0+a1)·(b0+b1) + xorps %xmm0,%xmm4 + xorps %xmm2,%xmm4 # (a0+a1)·(b0+b1)-a0·b0-a1·b1 + movdqa %xmm4,%xmm5 + pslldq \$8,%xmm4 + psrldq \$8,%xmm5 + pxor %xmm4,%xmm2 + pxor %xmm5,%xmm0 + movdqu %xmm2,0($rp) + movdqu %xmm0,16($rp) + ret + +.align 16 +.Lvanilla_mul_2x2: + lea -8*17(%rsp),%rsp +.cfi_adjust_cfa_offset 8*17 +___ +$code.=<<___ if ($win64); + mov `8*17+40`(%rsp),$b0 + mov %rdi,8*15(%rsp) + mov %rsi,8*16(%rsp) +___ +$code.=<<___; + mov %r14,8*10(%rsp) +.cfi_rel_offset %r14,8*10 + mov %r13,8*11(%rsp) +.cfi_rel_offset %r13,8*11 + mov %r12,8*12(%rsp) +.cfi_rel_offset %r12,8*12 + mov %rbp,8*13(%rsp) +.cfi_rel_offset %rbp,8*13 + mov %rbx,8*14(%rsp) +.cfi_rel_offset %rbx,8*14 +.Lbody_mul_2x2: + mov $rp,32(%rsp) # save the arguments + mov $a1,40(%rsp) + mov $a0,48(%rsp) + mov $b1,56(%rsp) + mov $b0,64(%rsp) + + mov \$0xf,$mask + mov $a1,$a + mov $b1,$b + call _mul_1x1 # a1·b1 + mov $lo,16(%rsp) + mov $hi,24(%rsp) + + mov 48(%rsp),$a + mov 64(%rsp),$b + call _mul_1x1 # a0·b0 + mov $lo,0(%rsp) + mov $hi,8(%rsp) + + mov 40(%rsp),$a + mov 56(%rsp),$b + xor 48(%rsp),$a + xor 64(%rsp),$b + call _mul_1x1 # (a0+a1)·(b0+b1) +___ + @r=("%rbx","%rcx","%rdi","%rsi"); +$code.=<<___; + mov 0(%rsp),@r[0] + mov 8(%rsp),@r[1] + mov 16(%rsp),@r[2] + mov 24(%rsp),@r[3] + mov 32(%rsp),%rbp + + xor $hi,$lo + xor @r[1],$hi + xor @r[0],$lo + mov @r[0],0(%rbp) + xor @r[2],$hi + mov @r[3],24(%rbp) + xor @r[3],$lo + xor @r[3],$hi + xor $hi,$lo + mov $hi,16(%rbp) + mov $lo,8(%rbp) + + mov 8*10(%rsp),%r14 +.cfi_restore %r14 + mov 8*11(%rsp),%r13 +.cfi_restore %r13 + mov 8*12(%rsp),%r12 +.cfi_restore %r12 + mov 8*13(%rsp),%rbp +.cfi_restore %rbp + mov 8*14(%rsp),%rbx +.cfi_restore %rbx +___ +$code.=<<___ if ($win64); + mov 8*15(%rsp),%rdi + mov 8*16(%rsp),%rsi +___ +$code.=<<___; + lea 8*17(%rsp),%rsp +.cfi_adjust_cfa_offset -8*17 +.Lepilogue_mul_2x2: + ret +.Lend_mul_2x2: +.cfi_endproc +.size bn_GF2m_mul_2x2,.-bn_GF2m_mul_2x2 +.asciz "GF(2^m) Multiplication for x86_64, CRYPTOGAMS by " +.align 16 +___ + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind + +.type se_handler,\@abi-omnipotent +.align 16 +se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + lea .Lbody_mul_2x2(%rip),%r10 + cmp %r10,%rbx # context->Rip<"prologue" label + jb .Lin_prologue + + mov 152($context),%rax # pull context->Rsp + + lea .Lepilogue_mul_2x2(%rip),%r10 + cmp %r10,%rbx # context->Rip>="epilogue" label + jae .Lin_prologue + + mov 8*10(%rax),%r14 # mimic epilogue + mov 8*11(%rax),%r13 + mov 8*12(%rax),%r12 + mov 8*13(%rax),%rbp + mov 8*14(%rax),%rbx + mov 8*15(%rax),%rdi + mov 8*16(%rax),%rsi + + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + + lea 8*17(%rax),%rax + +.Lin_prologue: + mov %rax,152($context) # restore context->Rsp + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size se_handler,.-se_handler + +.section .pdata +.align 4 + .rva _mul_1x1 + .rva .Lend_mul_1x1 + .rva .LSEH_info_1x1 + + .rva .Lvanilla_mul_2x2 + .rva .Lend_mul_2x2 + .rva .LSEH_info_2x2 +.section .xdata +.align 8 +.LSEH_info_1x1: + .byte 0x01,0x07,0x02,0x00 + .byte 0x07,0x01,0x11,0x00 # sub rsp,128+8 +.LSEH_info_2x2: + .byte 9,0,0,0 + .rva se_handler +___ +} + +$code =~ s/\`([^\`]*)\`/eval($1)/gem; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/x86_64-mont.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/x86_64-mont.pl new file mode 100755 index 000000000..c051135e3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/x86_64-mont.pl @@ -0,0 +1,1592 @@ +#! /usr/bin/env perl +# Copyright 2005-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# October 2005. +# +# Montgomery multiplication routine for x86_64. While it gives modest +# 9% improvement of rsa4096 sign on Opteron, rsa512 sign runs more +# than twice, >2x, as fast. Most common rsa1024 sign is improved by +# respectful 50%. It remains to be seen if loop unrolling and +# dedicated squaring routine can provide further improvement... + +# July 2011. +# +# Add dedicated squaring procedure. Performance improvement varies +# from platform to platform, but in average it's ~5%/15%/25%/33% +# for 512-/1024-/2048-/4096-bit RSA *sign* benchmarks respectively. + +# August 2011. +# +# Unroll and modulo-schedule inner loops in such manner that they +# are "fallen through" for input lengths of 8, which is critical for +# 1024-bit RSA *sign*. Average performance improvement in comparison +# to *initial* version of this module from 2005 is ~0%/30%/40%/45% +# for 512-/1024-/2048-/4096-bit RSA *sign* benchmarks respectively. + +# June 2013. +# +# Optimize reduction in squaring procedure and improve 1024+-bit RSA +# sign performance by 10-16% on Intel Sandy Bridge and later +# (virtually same on non-Intel processors). + +# August 2013. +# +# Add MULX/ADOX/ADCX code path. + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +*STDOUT=*OUT; + +if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler version ([2-9]\.[0-9]+)/) { + $addx = ($1>=2.23); +} + +if (!$addx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) && + `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) { + $addx = ($1>=2.10); +} + +if (!$addx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && + `ml64 2>&1` =~ /Version ([0-9]+)\./) { + $addx = ($1>=12); +} + +if (!$addx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9])\.([0-9]+)/) { + my $ver = $2 + $3/100.0; # 3.1->3.01, 3.10->3.10 + $addx = ($ver>=3.03); +} + +# int bn_mul_mont( +$rp="%rdi"; # BN_ULONG *rp, +$ap="%rsi"; # const BN_ULONG *ap, +$bp="%rdx"; # const BN_ULONG *bp, +$np="%rcx"; # const BN_ULONG *np, +$n0="%r8"; # const BN_ULONG *n0, +$num="%r9"; # int num); +$lo0="%r10"; +$hi0="%r11"; +$hi1="%r13"; +$i="%r14"; +$j="%r15"; +$m0="%rbx"; +$m1="%rbp"; + +$code=<<___; +.text + +.extern OPENSSL_ia32cap_P + +.globl bn_mul_mont +.type bn_mul_mont,\@function,6 +.align 16 +bn_mul_mont: +.cfi_startproc + mov ${num}d,${num}d + mov %rsp,%rax +.cfi_def_cfa_register %rax + test \$3,${num}d + jnz .Lmul_enter + cmp \$8,${num}d + jb .Lmul_enter +___ +$code.=<<___ if ($addx); + mov OPENSSL_ia32cap_P+8(%rip),%r11d +___ +$code.=<<___; + cmp $ap,$bp + jne .Lmul4x_enter + test \$7,${num}d + jz .Lsqr8x_enter + jmp .Lmul4x_enter + +.align 16 +.Lmul_enter: + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + + neg $num + mov %rsp,%r11 + lea -16(%rsp,$num,8),%r10 # future alloca(8*(num+2)) + neg $num # restore $num + and \$-1024,%r10 # minimize TLB usage + + # An OS-agnostic version of __chkstk. + # + # Some OSes (Windows) insist on stack being "wired" to + # physical memory in strictly sequential manner, i.e. if stack + # allocation spans two pages, then reference to farmost one can + # be punishable by SEGV. But page walking can do good even on + # other OSes, because it guarantees that villain thread hits + # the guard page before it can make damage to innocent one... + sub %r10,%r11 + and \$-4096,%r11 + lea (%r10,%r11),%rsp + mov (%rsp),%r11 + cmp %r10,%rsp + ja .Lmul_page_walk + jmp .Lmul_page_walk_done + +.align 16 +.Lmul_page_walk: + lea -4096(%rsp),%rsp + mov (%rsp),%r11 + cmp %r10,%rsp + ja .Lmul_page_walk +.Lmul_page_walk_done: + + mov %rax,8(%rsp,$num,8) # tp[num+1]=%rsp +.cfi_cfa_expression %rsp+8,$num,8,mul,plus,deref,+8 +.Lmul_body: + mov $bp,%r12 # reassign $bp +___ + $bp="%r12"; +$code.=<<___; + mov ($n0),$n0 # pull n0[0] value + mov ($bp),$m0 # m0=bp[0] + mov ($ap),%rax + + xor $i,$i # i=0 + xor $j,$j # j=0 + + mov $n0,$m1 + mulq $m0 # ap[0]*bp[0] + mov %rax,$lo0 + mov ($np),%rax + + imulq $lo0,$m1 # "tp[0]"*n0 + mov %rdx,$hi0 + + mulq $m1 # np[0]*m1 + add %rax,$lo0 # discarded + mov 8($ap),%rax + adc \$0,%rdx + mov %rdx,$hi1 + + lea 1($j),$j # j++ + jmp .L1st_enter + +.align 16 +.L1st: + add %rax,$hi1 + mov ($ap,$j,8),%rax + adc \$0,%rdx + add $hi0,$hi1 # np[j]*m1+ap[j]*bp[0] + mov $lo0,$hi0 + adc \$0,%rdx + mov $hi1,-16(%rsp,$j,8) # tp[j-1] + mov %rdx,$hi1 + +.L1st_enter: + mulq $m0 # ap[j]*bp[0] + add %rax,$hi0 + mov ($np,$j,8),%rax + adc \$0,%rdx + lea 1($j),$j # j++ + mov %rdx,$lo0 + + mulq $m1 # np[j]*m1 + cmp $num,$j + jne .L1st + + add %rax,$hi1 + mov ($ap),%rax # ap[0] + adc \$0,%rdx + add $hi0,$hi1 # np[j]*m1+ap[j]*bp[0] + adc \$0,%rdx + mov $hi1,-16(%rsp,$j,8) # tp[j-1] + mov %rdx,$hi1 + mov $lo0,$hi0 + + xor %rdx,%rdx + add $hi0,$hi1 + adc \$0,%rdx + mov $hi1,-8(%rsp,$num,8) + mov %rdx,(%rsp,$num,8) # store upmost overflow bit + + lea 1($i),$i # i++ + jmp .Louter +.align 16 +.Louter: + mov ($bp,$i,8),$m0 # m0=bp[i] + xor $j,$j # j=0 + mov $n0,$m1 + mov (%rsp),$lo0 + mulq $m0 # ap[0]*bp[i] + add %rax,$lo0 # ap[0]*bp[i]+tp[0] + mov ($np),%rax + adc \$0,%rdx + + imulq $lo0,$m1 # tp[0]*n0 + mov %rdx,$hi0 + + mulq $m1 # np[0]*m1 + add %rax,$lo0 # discarded + mov 8($ap),%rax + adc \$0,%rdx + mov 8(%rsp),$lo0 # tp[1] + mov %rdx,$hi1 + + lea 1($j),$j # j++ + jmp .Linner_enter + +.align 16 +.Linner: + add %rax,$hi1 + mov ($ap,$j,8),%rax + adc \$0,%rdx + add $lo0,$hi1 # np[j]*m1+ap[j]*bp[i]+tp[j] + mov (%rsp,$j,8),$lo0 + adc \$0,%rdx + mov $hi1,-16(%rsp,$j,8) # tp[j-1] + mov %rdx,$hi1 + +.Linner_enter: + mulq $m0 # ap[j]*bp[i] + add %rax,$hi0 + mov ($np,$j,8),%rax + adc \$0,%rdx + add $hi0,$lo0 # ap[j]*bp[i]+tp[j] + mov %rdx,$hi0 + adc \$0,$hi0 + lea 1($j),$j # j++ + + mulq $m1 # np[j]*m1 + cmp $num,$j + jne .Linner + + add %rax,$hi1 + mov ($ap),%rax # ap[0] + adc \$0,%rdx + add $lo0,$hi1 # np[j]*m1+ap[j]*bp[i]+tp[j] + mov (%rsp,$j,8),$lo0 + adc \$0,%rdx + mov $hi1,-16(%rsp,$j,8) # tp[j-1] + mov %rdx,$hi1 + + xor %rdx,%rdx + add $hi0,$hi1 + adc \$0,%rdx + add $lo0,$hi1 # pull upmost overflow bit + adc \$0,%rdx + mov $hi1,-8(%rsp,$num,8) + mov %rdx,(%rsp,$num,8) # store upmost overflow bit + + lea 1($i),$i # i++ + cmp $num,$i + jb .Louter + + xor $i,$i # i=0 and clear CF! + mov (%rsp),%rax # tp[0] + mov $num,$j # j=num + +.align 16 +.Lsub: sbb ($np,$i,8),%rax + mov %rax,($rp,$i,8) # rp[i]=tp[i]-np[i] + mov 8(%rsp,$i,8),%rax # tp[i+1] + lea 1($i),$i # i++ + dec $j # doesn't affect CF! + jnz .Lsub + + sbb \$0,%rax # handle upmost overflow bit + mov \$-1,%rbx + xor %rax,%rbx # not %rax + xor $i,$i + mov $num,$j # j=num + +.Lcopy: # conditional copy + mov ($rp,$i,8),%rcx + mov (%rsp,$i,8),%rdx + and %rbx,%rcx + and %rax,%rdx + mov $num,(%rsp,$i,8) # zap temporary vector + or %rcx,%rdx + mov %rdx,($rp,$i,8) # rp[i]=tp[i] + lea 1($i),$i + sub \$1,$j + jnz .Lcopy + + mov 8(%rsp,$num,8),%rsi # restore %rsp +.cfi_def_cfa %rsi,8 + mov \$1,%rax + mov -48(%rsi),%r15 +.cfi_restore %r15 + mov -40(%rsi),%r14 +.cfi_restore %r14 + mov -32(%rsi),%r13 +.cfi_restore %r13 + mov -24(%rsi),%r12 +.cfi_restore %r12 + mov -16(%rsi),%rbp +.cfi_restore %rbp + mov -8(%rsi),%rbx +.cfi_restore %rbx + lea (%rsi),%rsp +.cfi_def_cfa_register %rsp +.Lmul_epilogue: + ret +.cfi_endproc +.size bn_mul_mont,.-bn_mul_mont +___ +{{{ +my @A=("%r10","%r11"); +my @N=("%r13","%rdi"); +$code.=<<___; +.type bn_mul4x_mont,\@function,6 +.align 16 +bn_mul4x_mont: +.cfi_startproc + mov ${num}d,${num}d + mov %rsp,%rax +.cfi_def_cfa_register %rax +.Lmul4x_enter: +___ +$code.=<<___ if ($addx); + and \$0x80100,%r11d + cmp \$0x80100,%r11d + je .Lmulx4x_enter +___ +$code.=<<___; + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + + neg $num + mov %rsp,%r11 + lea -32(%rsp,$num,8),%r10 # future alloca(8*(num+4)) + neg $num # restore + and \$-1024,%r10 # minimize TLB usage + + sub %r10,%r11 + and \$-4096,%r11 + lea (%r10,%r11),%rsp + mov (%rsp),%r11 + cmp %r10,%rsp + ja .Lmul4x_page_walk + jmp .Lmul4x_page_walk_done + +.Lmul4x_page_walk: + lea -4096(%rsp),%rsp + mov (%rsp),%r11 + cmp %r10,%rsp + ja .Lmul4x_page_walk +.Lmul4x_page_walk_done: + + mov %rax,8(%rsp,$num,8) # tp[num+1]=%rsp +.cfi_cfa_expression %rsp+8,$num,8,mul,plus,deref,+8 +.Lmul4x_body: + mov $rp,16(%rsp,$num,8) # tp[num+2]=$rp + mov %rdx,%r12 # reassign $bp +___ + $bp="%r12"; +$code.=<<___; + mov ($n0),$n0 # pull n0[0] value + mov ($bp),$m0 # m0=bp[0] + mov ($ap),%rax + + xor $i,$i # i=0 + xor $j,$j # j=0 + + mov $n0,$m1 + mulq $m0 # ap[0]*bp[0] + mov %rax,$A[0] + mov ($np),%rax + + imulq $A[0],$m1 # "tp[0]"*n0 + mov %rdx,$A[1] + + mulq $m1 # np[0]*m1 + add %rax,$A[0] # discarded + mov 8($ap),%rax + adc \$0,%rdx + mov %rdx,$N[1] + + mulq $m0 + add %rax,$A[1] + mov 8($np),%rax + adc \$0,%rdx + mov %rdx,$A[0] + + mulq $m1 + add %rax,$N[1] + mov 16($ap),%rax + adc \$0,%rdx + add $A[1],$N[1] + lea 4($j),$j # j++ + adc \$0,%rdx + mov $N[1],(%rsp) + mov %rdx,$N[0] + jmp .L1st4x +.align 16 +.L1st4x: + mulq $m0 # ap[j]*bp[0] + add %rax,$A[0] + mov -16($np,$j,8),%rax + adc \$0,%rdx + mov %rdx,$A[1] + + mulq $m1 # np[j]*m1 + add %rax,$N[0] + mov -8($ap,$j,8),%rax + adc \$0,%rdx + add $A[0],$N[0] # np[j]*m1+ap[j]*bp[0] + adc \$0,%rdx + mov $N[0],-24(%rsp,$j,8) # tp[j-1] + mov %rdx,$N[1] + + mulq $m0 # ap[j]*bp[0] + add %rax,$A[1] + mov -8($np,$j,8),%rax + adc \$0,%rdx + mov %rdx,$A[0] + + mulq $m1 # np[j]*m1 + add %rax,$N[1] + mov ($ap,$j,8),%rax + adc \$0,%rdx + add $A[1],$N[1] # np[j]*m1+ap[j]*bp[0] + adc \$0,%rdx + mov $N[1],-16(%rsp,$j,8) # tp[j-1] + mov %rdx,$N[0] + + mulq $m0 # ap[j]*bp[0] + add %rax,$A[0] + mov ($np,$j,8),%rax + adc \$0,%rdx + mov %rdx,$A[1] + + mulq $m1 # np[j]*m1 + add %rax,$N[0] + mov 8($ap,$j,8),%rax + adc \$0,%rdx + add $A[0],$N[0] # np[j]*m1+ap[j]*bp[0] + adc \$0,%rdx + mov $N[0],-8(%rsp,$j,8) # tp[j-1] + mov %rdx,$N[1] + + mulq $m0 # ap[j]*bp[0] + add %rax,$A[1] + mov 8($np,$j,8),%rax + adc \$0,%rdx + lea 4($j),$j # j++ + mov %rdx,$A[0] + + mulq $m1 # np[j]*m1 + add %rax,$N[1] + mov -16($ap,$j,8),%rax + adc \$0,%rdx + add $A[1],$N[1] # np[j]*m1+ap[j]*bp[0] + adc \$0,%rdx + mov $N[1],-32(%rsp,$j,8) # tp[j-1] + mov %rdx,$N[0] + cmp $num,$j + jb .L1st4x + + mulq $m0 # ap[j]*bp[0] + add %rax,$A[0] + mov -16($np,$j,8),%rax + adc \$0,%rdx + mov %rdx,$A[1] + + mulq $m1 # np[j]*m1 + add %rax,$N[0] + mov -8($ap,$j,8),%rax + adc \$0,%rdx + add $A[0],$N[0] # np[j]*m1+ap[j]*bp[0] + adc \$0,%rdx + mov $N[0],-24(%rsp,$j,8) # tp[j-1] + mov %rdx,$N[1] + + mulq $m0 # ap[j]*bp[0] + add %rax,$A[1] + mov -8($np,$j,8),%rax + adc \$0,%rdx + mov %rdx,$A[0] + + mulq $m1 # np[j]*m1 + add %rax,$N[1] + mov ($ap),%rax # ap[0] + adc \$0,%rdx + add $A[1],$N[1] # np[j]*m1+ap[j]*bp[0] + adc \$0,%rdx + mov $N[1],-16(%rsp,$j,8) # tp[j-1] + mov %rdx,$N[0] + + xor $N[1],$N[1] + add $A[0],$N[0] + adc \$0,$N[1] + mov $N[0],-8(%rsp,$j,8) + mov $N[1],(%rsp,$j,8) # store upmost overflow bit + + lea 1($i),$i # i++ +.align 4 +.Louter4x: + mov ($bp,$i,8),$m0 # m0=bp[i] + xor $j,$j # j=0 + mov (%rsp),$A[0] + mov $n0,$m1 + mulq $m0 # ap[0]*bp[i] + add %rax,$A[0] # ap[0]*bp[i]+tp[0] + mov ($np),%rax + adc \$0,%rdx + + imulq $A[0],$m1 # tp[0]*n0 + mov %rdx,$A[1] + + mulq $m1 # np[0]*m1 + add %rax,$A[0] # "$N[0]", discarded + mov 8($ap),%rax + adc \$0,%rdx + mov %rdx,$N[1] + + mulq $m0 # ap[j]*bp[i] + add %rax,$A[1] + mov 8($np),%rax + adc \$0,%rdx + add 8(%rsp),$A[1] # +tp[1] + adc \$0,%rdx + mov %rdx,$A[0] + + mulq $m1 # np[j]*m1 + add %rax,$N[1] + mov 16($ap),%rax + adc \$0,%rdx + add $A[1],$N[1] # np[j]*m1+ap[j]*bp[i]+tp[j] + lea 4($j),$j # j+=2 + adc \$0,%rdx + mov $N[1],(%rsp) # tp[j-1] + mov %rdx,$N[0] + jmp .Linner4x +.align 16 +.Linner4x: + mulq $m0 # ap[j]*bp[i] + add %rax,$A[0] + mov -16($np,$j,8),%rax + adc \$0,%rdx + add -16(%rsp,$j,8),$A[0] # ap[j]*bp[i]+tp[j] + adc \$0,%rdx + mov %rdx,$A[1] + + mulq $m1 # np[j]*m1 + add %rax,$N[0] + mov -8($ap,$j,8),%rax + adc \$0,%rdx + add $A[0],$N[0] + adc \$0,%rdx + mov $N[0],-24(%rsp,$j,8) # tp[j-1] + mov %rdx,$N[1] + + mulq $m0 # ap[j]*bp[i] + add %rax,$A[1] + mov -8($np,$j,8),%rax + adc \$0,%rdx + add -8(%rsp,$j,8),$A[1] + adc \$0,%rdx + mov %rdx,$A[0] + + mulq $m1 # np[j]*m1 + add %rax,$N[1] + mov ($ap,$j,8),%rax + adc \$0,%rdx + add $A[1],$N[1] + adc \$0,%rdx + mov $N[1],-16(%rsp,$j,8) # tp[j-1] + mov %rdx,$N[0] + + mulq $m0 # ap[j]*bp[i] + add %rax,$A[0] + mov ($np,$j,8),%rax + adc \$0,%rdx + add (%rsp,$j,8),$A[0] # ap[j]*bp[i]+tp[j] + adc \$0,%rdx + mov %rdx,$A[1] + + mulq $m1 # np[j]*m1 + add %rax,$N[0] + mov 8($ap,$j,8),%rax + adc \$0,%rdx + add $A[0],$N[0] + adc \$0,%rdx + mov $N[0],-8(%rsp,$j,8) # tp[j-1] + mov %rdx,$N[1] + + mulq $m0 # ap[j]*bp[i] + add %rax,$A[1] + mov 8($np,$j,8),%rax + adc \$0,%rdx + add 8(%rsp,$j,8),$A[1] + adc \$0,%rdx + lea 4($j),$j # j++ + mov %rdx,$A[0] + + mulq $m1 # np[j]*m1 + add %rax,$N[1] + mov -16($ap,$j,8),%rax + adc \$0,%rdx + add $A[1],$N[1] + adc \$0,%rdx + mov $N[1],-32(%rsp,$j,8) # tp[j-1] + mov %rdx,$N[0] + cmp $num,$j + jb .Linner4x + + mulq $m0 # ap[j]*bp[i] + add %rax,$A[0] + mov -16($np,$j,8),%rax + adc \$0,%rdx + add -16(%rsp,$j,8),$A[0] # ap[j]*bp[i]+tp[j] + adc \$0,%rdx + mov %rdx,$A[1] + + mulq $m1 # np[j]*m1 + add %rax,$N[0] + mov -8($ap,$j,8),%rax + adc \$0,%rdx + add $A[0],$N[0] + adc \$0,%rdx + mov $N[0],-24(%rsp,$j,8) # tp[j-1] + mov %rdx,$N[1] + + mulq $m0 # ap[j]*bp[i] + add %rax,$A[1] + mov -8($np,$j,8),%rax + adc \$0,%rdx + add -8(%rsp,$j,8),$A[1] + adc \$0,%rdx + lea 1($i),$i # i++ + mov %rdx,$A[0] + + mulq $m1 # np[j]*m1 + add %rax,$N[1] + mov ($ap),%rax # ap[0] + adc \$0,%rdx + add $A[1],$N[1] + adc \$0,%rdx + mov $N[1],-16(%rsp,$j,8) # tp[j-1] + mov %rdx,$N[0] + + xor $N[1],$N[1] + add $A[0],$N[0] + adc \$0,$N[1] + add (%rsp,$num,8),$N[0] # pull upmost overflow bit + adc \$0,$N[1] + mov $N[0],-8(%rsp,$j,8) + mov $N[1],(%rsp,$j,8) # store upmost overflow bit + + cmp $num,$i + jb .Louter4x +___ +{ +my @ri=("%rax","%rdx",$m0,$m1); +$code.=<<___; + mov 16(%rsp,$num,8),$rp # restore $rp + lea -4($num),$j + mov 0(%rsp),@ri[0] # tp[0] + mov 8(%rsp),@ri[1] # tp[1] + shr \$2,$j # j=num/4-1 + lea (%rsp),$ap # borrow ap for tp + xor $i,$i # i=0 and clear CF! + + sub 0($np),@ri[0] + mov 16($ap),@ri[2] # tp[2] + mov 24($ap),@ri[3] # tp[3] + sbb 8($np),@ri[1] + +.Lsub4x: + mov @ri[0],0($rp,$i,8) # rp[i]=tp[i]-np[i] + mov @ri[1],8($rp,$i,8) # rp[i]=tp[i]-np[i] + sbb 16($np,$i,8),@ri[2] + mov 32($ap,$i,8),@ri[0] # tp[i+1] + mov 40($ap,$i,8),@ri[1] + sbb 24($np,$i,8),@ri[3] + mov @ri[2],16($rp,$i,8) # rp[i]=tp[i]-np[i] + mov @ri[3],24($rp,$i,8) # rp[i]=tp[i]-np[i] + sbb 32($np,$i,8),@ri[0] + mov 48($ap,$i,8),@ri[2] + mov 56($ap,$i,8),@ri[3] + sbb 40($np,$i,8),@ri[1] + lea 4($i),$i # i++ + dec $j # doesn't affect CF! + jnz .Lsub4x + + mov @ri[0],0($rp,$i,8) # rp[i]=tp[i]-np[i] + mov 32($ap,$i,8),@ri[0] # load overflow bit + sbb 16($np,$i,8),@ri[2] + mov @ri[1],8($rp,$i,8) # rp[i]=tp[i]-np[i] + sbb 24($np,$i,8),@ri[3] + mov @ri[2],16($rp,$i,8) # rp[i]=tp[i]-np[i] + + sbb \$0,@ri[0] # handle upmost overflow bit + mov @ri[3],24($rp,$i,8) # rp[i]=tp[i]-np[i] + pxor %xmm0,%xmm0 + movq @ri[0],%xmm4 + pcmpeqd %xmm5,%xmm5 + pshufd \$0,%xmm4,%xmm4 + mov $num,$j + pxor %xmm4,%xmm5 + shr \$2,$j # j=num/4 + xor %eax,%eax # i=0 + + jmp .Lcopy4x +.align 16 +.Lcopy4x: # conditional copy + movdqa (%rsp,%rax),%xmm1 + movdqu ($rp,%rax),%xmm2 + pand %xmm4,%xmm1 + pand %xmm5,%xmm2 + movdqa 16(%rsp,%rax),%xmm3 + movdqa %xmm0,(%rsp,%rax) + por %xmm2,%xmm1 + movdqu 16($rp,%rax),%xmm2 + movdqu %xmm1,($rp,%rax) + pand %xmm4,%xmm3 + pand %xmm5,%xmm2 + movdqa %xmm0,16(%rsp,%rax) + por %xmm2,%xmm3 + movdqu %xmm3,16($rp,%rax) + lea 32(%rax),%rax + dec $j + jnz .Lcopy4x +___ +} +$code.=<<___; + mov 8(%rsp,$num,8),%rsi # restore %rsp +.cfi_def_cfa %rsi, 8 + mov \$1,%rax + mov -48(%rsi),%r15 +.cfi_restore %r15 + mov -40(%rsi),%r14 +.cfi_restore %r14 + mov -32(%rsi),%r13 +.cfi_restore %r13 + mov -24(%rsi),%r12 +.cfi_restore %r12 + mov -16(%rsi),%rbp +.cfi_restore %rbp + mov -8(%rsi),%rbx +.cfi_restore %rbx + lea (%rsi),%rsp +.cfi_def_cfa_register %rsp +.Lmul4x_epilogue: + ret +.cfi_endproc +.size bn_mul4x_mont,.-bn_mul4x_mont +___ +}}} + {{{ +###################################################################### +# void bn_sqr8x_mont( +my $rptr="%rdi"; # const BN_ULONG *rptr, +my $aptr="%rsi"; # const BN_ULONG *aptr, +my $bptr="%rdx"; # not used +my $nptr="%rcx"; # const BN_ULONG *nptr, +my $n0 ="%r8"; # const BN_ULONG *n0); +my $num ="%r9"; # int num, has to be divisible by 8 + +my ($i,$j,$tptr)=("%rbp","%rcx",$rptr); +my @A0=("%r10","%r11"); +my @A1=("%r12","%r13"); +my ($a0,$a1,$ai)=("%r14","%r15","%rbx"); + +$code.=<<___ if ($addx); +.extern bn_sqrx8x_internal # see x86_64-mont5 module +___ +$code.=<<___; +.extern bn_sqr8x_internal # see x86_64-mont5 module + +.type bn_sqr8x_mont,\@function,6 +.align 32 +bn_sqr8x_mont: +.cfi_startproc + mov %rsp,%rax +.cfi_def_cfa_register %rax +.Lsqr8x_enter: + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +.Lsqr8x_prologue: + + mov ${num}d,%r10d + shl \$3,${num}d # convert $num to bytes + shl \$3+2,%r10 # 4*$num + neg $num + + ############################################################## + # ensure that stack frame doesn't alias with $aptr modulo + # 4096. this is done to allow memory disambiguation logic + # do its job. + # + lea -64(%rsp,$num,2),%r11 + mov %rsp,%rbp + mov ($n0),$n0 # *n0 + sub $aptr,%r11 + and \$4095,%r11 + cmp %r11,%r10 + jb .Lsqr8x_sp_alt + sub %r11,%rbp # align with $aptr + lea -64(%rbp,$num,2),%rbp # future alloca(frame+2*$num) + jmp .Lsqr8x_sp_done + +.align 32 +.Lsqr8x_sp_alt: + lea 4096-64(,$num,2),%r10 # 4096-frame-2*$num + lea -64(%rbp,$num,2),%rbp # future alloca(frame+2*$num) + sub %r10,%r11 + mov \$0,%r10 + cmovc %r10,%r11 + sub %r11,%rbp +.Lsqr8x_sp_done: + and \$-64,%rbp + mov %rsp,%r11 + sub %rbp,%r11 + and \$-4096,%r11 + lea (%rbp,%r11),%rsp + mov (%rsp),%r10 + cmp %rbp,%rsp + ja .Lsqr8x_page_walk + jmp .Lsqr8x_page_walk_done + +.align 16 +.Lsqr8x_page_walk: + lea -4096(%rsp),%rsp + mov (%rsp),%r10 + cmp %rbp,%rsp + ja .Lsqr8x_page_walk +.Lsqr8x_page_walk_done: + + mov $num,%r10 + neg $num + + mov $n0, 32(%rsp) + mov %rax, 40(%rsp) # save original %rsp +.cfi_cfa_expression %rsp+40,deref,+8 +.Lsqr8x_body: + + movq $nptr, %xmm2 # save pointer to modulus + pxor %xmm0,%xmm0 + movq $rptr,%xmm1 # save $rptr + movq %r10, %xmm3 # -$num +___ +$code.=<<___ if ($addx); + mov OPENSSL_ia32cap_P+8(%rip),%eax + and \$0x80100,%eax + cmp \$0x80100,%eax + jne .Lsqr8x_nox + + call bn_sqrx8x_internal # see x86_64-mont5 module + # %rax top-most carry + # %rbp nptr + # %rcx -8*num + # %r8 end of tp[2*num] + lea (%r8,%rcx),%rbx + mov %rcx,$num + mov %rcx,%rdx + movq %xmm1,$rptr + sar \$3+2,%rcx # %cf=0 + jmp .Lsqr8x_sub + +.align 32 +.Lsqr8x_nox: +___ +$code.=<<___; + call bn_sqr8x_internal # see x86_64-mont5 module + # %rax top-most carry + # %rbp nptr + # %r8 -8*num + # %rdi end of tp[2*num] + lea (%rdi,$num),%rbx + mov $num,%rcx + mov $num,%rdx + movq %xmm1,$rptr + sar \$3+2,%rcx # %cf=0 + jmp .Lsqr8x_sub + +.align 32 +.Lsqr8x_sub: + mov 8*0(%rbx),%r12 + mov 8*1(%rbx),%r13 + mov 8*2(%rbx),%r14 + mov 8*3(%rbx),%r15 + lea 8*4(%rbx),%rbx + sbb 8*0(%rbp),%r12 + sbb 8*1(%rbp),%r13 + sbb 8*2(%rbp),%r14 + sbb 8*3(%rbp),%r15 + lea 8*4(%rbp),%rbp + mov %r12,8*0($rptr) + mov %r13,8*1($rptr) + mov %r14,8*2($rptr) + mov %r15,8*3($rptr) + lea 8*4($rptr),$rptr + inc %rcx # preserves %cf + jnz .Lsqr8x_sub + + sbb \$0,%rax # top-most carry + lea (%rbx,$num),%rbx # rewind + lea ($rptr,$num),$rptr # rewind + + movq %rax,%xmm1 + pxor %xmm0,%xmm0 + pshufd \$0,%xmm1,%xmm1 + mov 40(%rsp),%rsi # restore %rsp +.cfi_def_cfa %rsi,8 + jmp .Lsqr8x_cond_copy + +.align 32 +.Lsqr8x_cond_copy: + movdqa 16*0(%rbx),%xmm2 + movdqa 16*1(%rbx),%xmm3 + lea 16*2(%rbx),%rbx + movdqu 16*0($rptr),%xmm4 + movdqu 16*1($rptr),%xmm5 + lea 16*2($rptr),$rptr + movdqa %xmm0,-16*2(%rbx) # zero tp + movdqa %xmm0,-16*1(%rbx) + movdqa %xmm0,-16*2(%rbx,%rdx) + movdqa %xmm0,-16*1(%rbx,%rdx) + pcmpeqd %xmm1,%xmm0 + pand %xmm1,%xmm2 + pand %xmm1,%xmm3 + pand %xmm0,%xmm4 + pand %xmm0,%xmm5 + pxor %xmm0,%xmm0 + por %xmm2,%xmm4 + por %xmm3,%xmm5 + movdqu %xmm4,-16*2($rptr) + movdqu %xmm5,-16*1($rptr) + add \$32,$num + jnz .Lsqr8x_cond_copy + + mov \$1,%rax + mov -48(%rsi),%r15 +.cfi_restore %r15 + mov -40(%rsi),%r14 +.cfi_restore %r14 + mov -32(%rsi),%r13 +.cfi_restore %r13 + mov -24(%rsi),%r12 +.cfi_restore %r12 + mov -16(%rsi),%rbp +.cfi_restore %rbp + mov -8(%rsi),%rbx +.cfi_restore %rbx + lea (%rsi),%rsp +.cfi_def_cfa_register %rsp +.Lsqr8x_epilogue: + ret +.cfi_endproc +.size bn_sqr8x_mont,.-bn_sqr8x_mont +___ +}}} + +if ($addx) {{{ +my $bp="%rdx"; # original value + +$code.=<<___; +.type bn_mulx4x_mont,\@function,6 +.align 32 +bn_mulx4x_mont: +.cfi_startproc + mov %rsp,%rax +.cfi_def_cfa_register %rax +.Lmulx4x_enter: + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +.Lmulx4x_prologue: + + shl \$3,${num}d # convert $num to bytes + xor %r10,%r10 + sub $num,%r10 # -$num + mov ($n0),$n0 # *n0 + lea -72(%rsp,%r10),%rbp # future alloca(frame+$num+8) + and \$-128,%rbp + mov %rsp,%r11 + sub %rbp,%r11 + and \$-4096,%r11 + lea (%rbp,%r11),%rsp + mov (%rsp),%r10 + cmp %rbp,%rsp + ja .Lmulx4x_page_walk + jmp .Lmulx4x_page_walk_done + +.align 16 +.Lmulx4x_page_walk: + lea -4096(%rsp),%rsp + mov (%rsp),%r10 + cmp %rbp,%rsp + ja .Lmulx4x_page_walk +.Lmulx4x_page_walk_done: + + lea ($bp,$num),%r10 + ############################################################## + # Stack layout + # +0 num + # +8 off-loaded &b[i] + # +16 end of b[num] + # +24 saved n0 + # +32 saved rp + # +40 saved %rsp + # +48 inner counter + # +56 + # +64 tmp[num+1] + # + mov $num,0(%rsp) # save $num + shr \$5,$num + mov %r10,16(%rsp) # end of b[num] + sub \$1,$num + mov $n0, 24(%rsp) # save *n0 + mov $rp, 32(%rsp) # save $rp + mov %rax,40(%rsp) # save original %rsp +.cfi_cfa_expression %rsp+40,deref,+8 + mov $num,48(%rsp) # inner counter + jmp .Lmulx4x_body + +.align 32 +.Lmulx4x_body: +___ +my ($aptr, $bptr, $nptr, $tptr, $mi, $bi, $zero, $num)= + ("%rsi","%rdi","%rcx","%rbx","%r8","%r9","%rbp","%rax"); +my $rptr=$bptr; +$code.=<<___; + lea 8($bp),$bptr + mov ($bp),%rdx # b[0], $bp==%rdx actually + lea 64+32(%rsp),$tptr + mov %rdx,$bi + + mulx 0*8($aptr),$mi,%rax # a[0]*b[0] + mulx 1*8($aptr),%r11,%r14 # a[1]*b[0] + add %rax,%r11 + mov $bptr,8(%rsp) # off-load &b[i] + mulx 2*8($aptr),%r12,%r13 # ... + adc %r14,%r12 + adc \$0,%r13 + + mov $mi,$bptr # borrow $bptr + imulq 24(%rsp),$mi # "t[0]"*n0 + xor $zero,$zero # cf=0, of=0 + + mulx 3*8($aptr),%rax,%r14 + mov $mi,%rdx + lea 4*8($aptr),$aptr + adcx %rax,%r13 + adcx $zero,%r14 # cf=0 + + mulx 0*8($nptr),%rax,%r10 + adcx %rax,$bptr # discarded + adox %r11,%r10 + mulx 1*8($nptr),%rax,%r11 + adcx %rax,%r10 + adox %r12,%r11 + .byte 0xc4,0x62,0xfb,0xf6,0xa1,0x10,0x00,0x00,0x00 # mulx 2*8($nptr),%rax,%r12 + mov 48(%rsp),$bptr # counter value + mov %r10,-4*8($tptr) + adcx %rax,%r11 + adox %r13,%r12 + mulx 3*8($nptr),%rax,%r15 + mov $bi,%rdx + mov %r11,-3*8($tptr) + adcx %rax,%r12 + adox $zero,%r15 # of=0 + lea 4*8($nptr),$nptr + mov %r12,-2*8($tptr) + + jmp .Lmulx4x_1st + +.align 32 +.Lmulx4x_1st: + adcx $zero,%r15 # cf=0, modulo-scheduled + mulx 0*8($aptr),%r10,%rax # a[4]*b[0] + adcx %r14,%r10 + mulx 1*8($aptr),%r11,%r14 # a[5]*b[0] + adcx %rax,%r11 + mulx 2*8($aptr),%r12,%rax # ... + adcx %r14,%r12 + mulx 3*8($aptr),%r13,%r14 + .byte 0x67,0x67 + mov $mi,%rdx + adcx %rax,%r13 + adcx $zero,%r14 # cf=0 + lea 4*8($aptr),$aptr + lea 4*8($tptr),$tptr + + adox %r15,%r10 + mulx 0*8($nptr),%rax,%r15 + adcx %rax,%r10 + adox %r15,%r11 + mulx 1*8($nptr),%rax,%r15 + adcx %rax,%r11 + adox %r15,%r12 + mulx 2*8($nptr),%rax,%r15 + mov %r10,-5*8($tptr) + adcx %rax,%r12 + mov %r11,-4*8($tptr) + adox %r15,%r13 + mulx 3*8($nptr),%rax,%r15 + mov $bi,%rdx + mov %r12,-3*8($tptr) + adcx %rax,%r13 + adox $zero,%r15 + lea 4*8($nptr),$nptr + mov %r13,-2*8($tptr) + + dec $bptr # of=0, pass cf + jnz .Lmulx4x_1st + + mov 0(%rsp),$num # load num + mov 8(%rsp),$bptr # re-load &b[i] + adc $zero,%r15 # modulo-scheduled + add %r15,%r14 + sbb %r15,%r15 # top-most carry + mov %r14,-1*8($tptr) + jmp .Lmulx4x_outer + +.align 32 +.Lmulx4x_outer: + mov ($bptr),%rdx # b[i] + lea 8($bptr),$bptr # b++ + sub $num,$aptr # rewind $aptr + mov %r15,($tptr) # save top-most carry + lea 64+4*8(%rsp),$tptr + sub $num,$nptr # rewind $nptr + + mulx 0*8($aptr),$mi,%r11 # a[0]*b[i] + xor %ebp,%ebp # xor $zero,$zero # cf=0, of=0 + mov %rdx,$bi + mulx 1*8($aptr),%r14,%r12 # a[1]*b[i] + adox -4*8($tptr),$mi + adcx %r14,%r11 + mulx 2*8($aptr),%r15,%r13 # ... + adox -3*8($tptr),%r11 + adcx %r15,%r12 + adox -2*8($tptr),%r12 + adcx $zero,%r13 + adox $zero,%r13 + + mov $bptr,8(%rsp) # off-load &b[i] + mov $mi,%r15 + imulq 24(%rsp),$mi # "t[0]"*n0 + xor %ebp,%ebp # xor $zero,$zero # cf=0, of=0 + + mulx 3*8($aptr),%rax,%r14 + mov $mi,%rdx + adcx %rax,%r13 + adox -1*8($tptr),%r13 + adcx $zero,%r14 + lea 4*8($aptr),$aptr + adox $zero,%r14 + + mulx 0*8($nptr),%rax,%r10 + adcx %rax,%r15 # discarded + adox %r11,%r10 + mulx 1*8($nptr),%rax,%r11 + adcx %rax,%r10 + adox %r12,%r11 + mulx 2*8($nptr),%rax,%r12 + mov %r10,-4*8($tptr) + adcx %rax,%r11 + adox %r13,%r12 + mulx 3*8($nptr),%rax,%r15 + mov $bi,%rdx + mov %r11,-3*8($tptr) + lea 4*8($nptr),$nptr + adcx %rax,%r12 + adox $zero,%r15 # of=0 + mov 48(%rsp),$bptr # counter value + mov %r12,-2*8($tptr) + + jmp .Lmulx4x_inner + +.align 32 +.Lmulx4x_inner: + mulx 0*8($aptr),%r10,%rax # a[4]*b[i] + adcx $zero,%r15 # cf=0, modulo-scheduled + adox %r14,%r10 + mulx 1*8($aptr),%r11,%r14 # a[5]*b[i] + adcx 0*8($tptr),%r10 + adox %rax,%r11 + mulx 2*8($aptr),%r12,%rax # ... + adcx 1*8($tptr),%r11 + adox %r14,%r12 + mulx 3*8($aptr),%r13,%r14 + mov $mi,%rdx + adcx 2*8($tptr),%r12 + adox %rax,%r13 + adcx 3*8($tptr),%r13 + adox $zero,%r14 # of=0 + lea 4*8($aptr),$aptr + lea 4*8($tptr),$tptr + adcx $zero,%r14 # cf=0 + + adox %r15,%r10 + mulx 0*8($nptr),%rax,%r15 + adcx %rax,%r10 + adox %r15,%r11 + mulx 1*8($nptr),%rax,%r15 + adcx %rax,%r11 + adox %r15,%r12 + mulx 2*8($nptr),%rax,%r15 + mov %r10,-5*8($tptr) + adcx %rax,%r12 + adox %r15,%r13 + mulx 3*8($nptr),%rax,%r15 + mov $bi,%rdx + mov %r11,-4*8($tptr) + mov %r12,-3*8($tptr) + adcx %rax,%r13 + adox $zero,%r15 + lea 4*8($nptr),$nptr + mov %r13,-2*8($tptr) + + dec $bptr # of=0, pass cf + jnz .Lmulx4x_inner + + mov 0(%rsp),$num # load num + mov 8(%rsp),$bptr # re-load &b[i] + adc $zero,%r15 # modulo-scheduled + sub 0*8($tptr),$zero # pull top-most carry + adc %r15,%r14 + sbb %r15,%r15 # top-most carry + mov %r14,-1*8($tptr) + + cmp 16(%rsp),$bptr + jne .Lmulx4x_outer + + lea 64(%rsp),$tptr + sub $num,$nptr # rewind $nptr + neg %r15 + mov $num,%rdx + shr \$3+2,$num # %cf=0 + mov 32(%rsp),$rptr # restore rp + jmp .Lmulx4x_sub + +.align 32 +.Lmulx4x_sub: + mov 8*0($tptr),%r11 + mov 8*1($tptr),%r12 + mov 8*2($tptr),%r13 + mov 8*3($tptr),%r14 + lea 8*4($tptr),$tptr + sbb 8*0($nptr),%r11 + sbb 8*1($nptr),%r12 + sbb 8*2($nptr),%r13 + sbb 8*3($nptr),%r14 + lea 8*4($nptr),$nptr + mov %r11,8*0($rptr) + mov %r12,8*1($rptr) + mov %r13,8*2($rptr) + mov %r14,8*3($rptr) + lea 8*4($rptr),$rptr + dec $num # preserves %cf + jnz .Lmulx4x_sub + + sbb \$0,%r15 # top-most carry + lea 64(%rsp),$tptr + sub %rdx,$rptr # rewind + + movq %r15,%xmm1 + pxor %xmm0,%xmm0 + pshufd \$0,%xmm1,%xmm1 + mov 40(%rsp),%rsi # restore %rsp +.cfi_def_cfa %rsi,8 + jmp .Lmulx4x_cond_copy + +.align 32 +.Lmulx4x_cond_copy: + movdqa 16*0($tptr),%xmm2 + movdqa 16*1($tptr),%xmm3 + lea 16*2($tptr),$tptr + movdqu 16*0($rptr),%xmm4 + movdqu 16*1($rptr),%xmm5 + lea 16*2($rptr),$rptr + movdqa %xmm0,-16*2($tptr) # zero tp + movdqa %xmm0,-16*1($tptr) + pcmpeqd %xmm1,%xmm0 + pand %xmm1,%xmm2 + pand %xmm1,%xmm3 + pand %xmm0,%xmm4 + pand %xmm0,%xmm5 + pxor %xmm0,%xmm0 + por %xmm2,%xmm4 + por %xmm3,%xmm5 + movdqu %xmm4,-16*2($rptr) + movdqu %xmm5,-16*1($rptr) + sub \$32,%rdx + jnz .Lmulx4x_cond_copy + + mov %rdx,($tptr) + + mov \$1,%rax + mov -48(%rsi),%r15 +.cfi_restore %r15 + mov -40(%rsi),%r14 +.cfi_restore %r14 + mov -32(%rsi),%r13 +.cfi_restore %r13 + mov -24(%rsi),%r12 +.cfi_restore %r12 + mov -16(%rsi),%rbp +.cfi_restore %rbp + mov -8(%rsi),%rbx +.cfi_restore %rbx + lea (%rsi),%rsp +.cfi_def_cfa_register %rsp +.Lmulx4x_epilogue: + ret +.cfi_endproc +.size bn_mulx4x_mont,.-bn_mulx4x_mont +___ +}}} +$code.=<<___; +.asciz "Montgomery Multiplication for x86_64, CRYPTOGAMS by " +.align 16 +___ + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type mul_handler,\@abi-omnipotent +.align 16 +mul_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # end of prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lcommon_seh_tail + + mov 192($context),%r10 # pull $num + mov 8(%rax,%r10,8),%rax # pull saved stack pointer + + jmp .Lcommon_pop_regs +.size mul_handler,.-mul_handler + +.type sqr_handler,\@abi-omnipotent +.align 16 +sqr_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # end of prologue label + cmp %r10,%rbx # context->Rip<.Lsqr_prologue + jb .Lcommon_seh_tail + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # body label + cmp %r10,%rbx # context->Rip<.Lsqr_body + jb .Lcommon_pop_regs + + mov 152($context),%rax # pull context->Rsp + + mov 8(%r11),%r10d # HandlerData[2] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=.Lsqr_epilogue + jae .Lcommon_seh_tail + + mov 40(%rax),%rax # pull saved stack pointer + +.Lcommon_pop_regs: + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov -48(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + +.Lcommon_seh_tail: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size sqr_handler,.-sqr_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_bn_mul_mont + .rva .LSEH_end_bn_mul_mont + .rva .LSEH_info_bn_mul_mont + + .rva .LSEH_begin_bn_mul4x_mont + .rva .LSEH_end_bn_mul4x_mont + .rva .LSEH_info_bn_mul4x_mont + + .rva .LSEH_begin_bn_sqr8x_mont + .rva .LSEH_end_bn_sqr8x_mont + .rva .LSEH_info_bn_sqr8x_mont +___ +$code.=<<___ if ($addx); + .rva .LSEH_begin_bn_mulx4x_mont + .rva .LSEH_end_bn_mulx4x_mont + .rva .LSEH_info_bn_mulx4x_mont +___ +$code.=<<___; +.section .xdata +.align 8 +.LSEH_info_bn_mul_mont: + .byte 9,0,0,0 + .rva mul_handler + .rva .Lmul_body,.Lmul_epilogue # HandlerData[] +.LSEH_info_bn_mul4x_mont: + .byte 9,0,0,0 + .rva mul_handler + .rva .Lmul4x_body,.Lmul4x_epilogue # HandlerData[] +.LSEH_info_bn_sqr8x_mont: + .byte 9,0,0,0 + .rva sqr_handler + .rva .Lsqr8x_prologue,.Lsqr8x_body,.Lsqr8x_epilogue # HandlerData[] +.align 8 +___ +$code.=<<___ if ($addx); +.LSEH_info_bn_mulx4x_mont: + .byte 9,0,0,0 + .rva sqr_handler + .rva .Lmulx4x_prologue,.Lmulx4x_body,.Lmulx4x_epilogue # HandlerData[] +.align 8 +___ +} + +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/x86_64-mont5.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/x86_64-mont5.pl new file mode 100755 index 000000000..f43e13d11 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/asm/x86_64-mont5.pl @@ -0,0 +1,3945 @@ +#! /usr/bin/env perl +# Copyright 2011-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# August 2011. +# +# Companion to x86_64-mont.pl that optimizes cache-timing attack +# countermeasures. The subroutines are produced by replacing bp[i] +# references in their x86_64-mont.pl counterparts with cache-neutral +# references to powers table computed in BN_mod_exp_mont_consttime. +# In addition subroutine that scatters elements of the powers table +# is implemented, so that scatter-/gathering can be tuned without +# bn_exp.c modifications. + +# August 2013. +# +# Add MULX/AD*X code paths and additional interfaces to optimize for +# branch prediction unit. For input lengths that are multiples of 8 +# the np argument is not just modulus value, but one interleaved +# with 0. This is to optimize post-condition... + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +*STDOUT=*OUT; + +if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler version ([2-9]\.[0-9]+)/) { + $addx = ($1>=2.23); +} + +if (!$addx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) && + `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) { + $addx = ($1>=2.10); +} + +if (!$addx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && + `ml64 2>&1` =~ /Version ([0-9]+)\./) { + $addx = ($1>=12); +} + +if (!$addx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9])\.([0-9]+)/) { + my $ver = $2 + $3/100.0; # 3.1->3.01, 3.10->3.10 + $addx = ($ver>=3.03); +} + +# int bn_mul_mont_gather5( +$rp="%rdi"; # BN_ULONG *rp, +$ap="%rsi"; # const BN_ULONG *ap, +$bp="%rdx"; # const BN_ULONG *bp, +$np="%rcx"; # const BN_ULONG *np, +$n0="%r8"; # const BN_ULONG *n0, +$num="%r9"; # int num, + # int idx); # 0 to 2^5-1, "index" in $bp holding + # pre-computed powers of a', interlaced + # in such manner that b[0] is $bp[idx], + # b[1] is [2^5+idx], etc. +$lo0="%r10"; +$hi0="%r11"; +$hi1="%r13"; +$i="%r14"; +$j="%r15"; +$m0="%rbx"; +$m1="%rbp"; + +$code=<<___; +.text + +.extern OPENSSL_ia32cap_P + +.globl bn_mul_mont_gather5 +.type bn_mul_mont_gather5,\@function,6 +.align 64 +bn_mul_mont_gather5: +.cfi_startproc + mov ${num}d,${num}d + mov %rsp,%rax +.cfi_def_cfa_register %rax + test \$7,${num}d + jnz .Lmul_enter +___ +$code.=<<___ if ($addx); + mov OPENSSL_ia32cap_P+8(%rip),%r11d +___ +$code.=<<___; + jmp .Lmul4x_enter + +.align 16 +.Lmul_enter: + movd `($win64?56:8)`(%rsp),%xmm5 # load 7th argument + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + + neg $num + mov %rsp,%r11 + lea -280(%rsp,$num,8),%r10 # future alloca(8*(num+2)+256+8) + neg $num # restore $num + and \$-1024,%r10 # minimize TLB usage + + # An OS-agnostic version of __chkstk. + # + # Some OSes (Windows) insist on stack being "wired" to + # physical memory in strictly sequential manner, i.e. if stack + # allocation spans two pages, then reference to farmost one can + # be punishable by SEGV. But page walking can do good even on + # other OSes, because it guarantees that villain thread hits + # the guard page before it can make damage to innocent one... + sub %r10,%r11 + and \$-4096,%r11 + lea (%r10,%r11),%rsp + mov (%rsp),%r11 + cmp %r10,%rsp + ja .Lmul_page_walk + jmp .Lmul_page_walk_done + +.Lmul_page_walk: + lea -4096(%rsp),%rsp + mov (%rsp),%r11 + cmp %r10,%rsp + ja .Lmul_page_walk +.Lmul_page_walk_done: + + lea .Linc(%rip),%r10 + mov %rax,8(%rsp,$num,8) # tp[num+1]=%rsp +.cfi_cfa_expression %rsp+8,$num,8,mul,plus,deref,+8 +.Lmul_body: + + lea 128($bp),%r12 # reassign $bp (+size optimization) +___ + $bp="%r12"; + $STRIDE=2**5*8; # 5 is "window size" + $N=$STRIDE/4; # should match cache line size +$code.=<<___; + movdqa 0(%r10),%xmm0 # 00000001000000010000000000000000 + movdqa 16(%r10),%xmm1 # 00000002000000020000000200000002 + lea 24-112(%rsp,$num,8),%r10# place the mask after tp[num+3] (+ICache optimization) + and \$-16,%r10 + + pshufd \$0,%xmm5,%xmm5 # broadcast index + movdqa %xmm1,%xmm4 + movdqa %xmm1,%xmm2 +___ +######################################################################## +# calculate mask by comparing 0..31 to index and save result to stack +# +$code.=<<___; + paddd %xmm0,%xmm1 + pcmpeqd %xmm5,%xmm0 # compare to 1,0 + .byte 0x67 + movdqa %xmm4,%xmm3 +___ +for($k=0;$k<$STRIDE/16-4;$k+=4) { +$code.=<<___; + paddd %xmm1,%xmm2 + pcmpeqd %xmm5,%xmm1 # compare to 3,2 + movdqa %xmm0,`16*($k+0)+112`(%r10) + movdqa %xmm4,%xmm0 + + paddd %xmm2,%xmm3 + pcmpeqd %xmm5,%xmm2 # compare to 5,4 + movdqa %xmm1,`16*($k+1)+112`(%r10) + movdqa %xmm4,%xmm1 + + paddd %xmm3,%xmm0 + pcmpeqd %xmm5,%xmm3 # compare to 7,6 + movdqa %xmm2,`16*($k+2)+112`(%r10) + movdqa %xmm4,%xmm2 + + paddd %xmm0,%xmm1 + pcmpeqd %xmm5,%xmm0 + movdqa %xmm3,`16*($k+3)+112`(%r10) + movdqa %xmm4,%xmm3 +___ +} +$code.=<<___; # last iteration can be optimized + paddd %xmm1,%xmm2 + pcmpeqd %xmm5,%xmm1 + movdqa %xmm0,`16*($k+0)+112`(%r10) + + paddd %xmm2,%xmm3 + .byte 0x67 + pcmpeqd %xmm5,%xmm2 + movdqa %xmm1,`16*($k+1)+112`(%r10) + + pcmpeqd %xmm5,%xmm3 + movdqa %xmm2,`16*($k+2)+112`(%r10) + pand `16*($k+0)-128`($bp),%xmm0 # while it's still in register + + pand `16*($k+1)-128`($bp),%xmm1 + pand `16*($k+2)-128`($bp),%xmm2 + movdqa %xmm3,`16*($k+3)+112`(%r10) + pand `16*($k+3)-128`($bp),%xmm3 + por %xmm2,%xmm0 + por %xmm3,%xmm1 +___ +for($k=0;$k<$STRIDE/16-4;$k+=4) { +$code.=<<___; + movdqa `16*($k+0)-128`($bp),%xmm4 + movdqa `16*($k+1)-128`($bp),%xmm5 + movdqa `16*($k+2)-128`($bp),%xmm2 + pand `16*($k+0)+112`(%r10),%xmm4 + movdqa `16*($k+3)-128`($bp),%xmm3 + pand `16*($k+1)+112`(%r10),%xmm5 + por %xmm4,%xmm0 + pand `16*($k+2)+112`(%r10),%xmm2 + por %xmm5,%xmm1 + pand `16*($k+3)+112`(%r10),%xmm3 + por %xmm2,%xmm0 + por %xmm3,%xmm1 +___ +} +$code.=<<___; + por %xmm1,%xmm0 + pshufd \$0x4e,%xmm0,%xmm1 + por %xmm1,%xmm0 + lea $STRIDE($bp),$bp + movq %xmm0,$m0 # m0=bp[0] + + mov ($n0),$n0 # pull n0[0] value + mov ($ap),%rax + + xor $i,$i # i=0 + xor $j,$j # j=0 + + mov $n0,$m1 + mulq $m0 # ap[0]*bp[0] + mov %rax,$lo0 + mov ($np),%rax + + imulq $lo0,$m1 # "tp[0]"*n0 + mov %rdx,$hi0 + + mulq $m1 # np[0]*m1 + add %rax,$lo0 # discarded + mov 8($ap),%rax + adc \$0,%rdx + mov %rdx,$hi1 + + lea 1($j),$j # j++ + jmp .L1st_enter + +.align 16 +.L1st: + add %rax,$hi1 + mov ($ap,$j,8),%rax + adc \$0,%rdx + add $hi0,$hi1 # np[j]*m1+ap[j]*bp[0] + mov $lo0,$hi0 + adc \$0,%rdx + mov $hi1,-16(%rsp,$j,8) # tp[j-1] + mov %rdx,$hi1 + +.L1st_enter: + mulq $m0 # ap[j]*bp[0] + add %rax,$hi0 + mov ($np,$j,8),%rax + adc \$0,%rdx + lea 1($j),$j # j++ + mov %rdx,$lo0 + + mulq $m1 # np[j]*m1 + cmp $num,$j + jne .L1st # note that upon exit $j==$num, so + # they can be used interchangeably + + add %rax,$hi1 + adc \$0,%rdx + add $hi0,$hi1 # np[j]*m1+ap[j]*bp[0] + adc \$0,%rdx + mov $hi1,-16(%rsp,$num,8) # tp[num-1] + mov %rdx,$hi1 + mov $lo0,$hi0 + + xor %rdx,%rdx + add $hi0,$hi1 + adc \$0,%rdx + mov $hi1,-8(%rsp,$num,8) + mov %rdx,(%rsp,$num,8) # store upmost overflow bit + + lea 1($i),$i # i++ + jmp .Louter +.align 16 +.Louter: + lea 24+128(%rsp,$num,8),%rdx # where 256-byte mask is (+size optimization) + and \$-16,%rdx + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 +___ +for($k=0;$k<$STRIDE/16;$k+=4) { +$code.=<<___; + movdqa `16*($k+0)-128`($bp),%xmm0 + movdqa `16*($k+1)-128`($bp),%xmm1 + movdqa `16*($k+2)-128`($bp),%xmm2 + movdqa `16*($k+3)-128`($bp),%xmm3 + pand `16*($k+0)-128`(%rdx),%xmm0 + pand `16*($k+1)-128`(%rdx),%xmm1 + por %xmm0,%xmm4 + pand `16*($k+2)-128`(%rdx),%xmm2 + por %xmm1,%xmm5 + pand `16*($k+3)-128`(%rdx),%xmm3 + por %xmm2,%xmm4 + por %xmm3,%xmm5 +___ +} +$code.=<<___; + por %xmm5,%xmm4 + pshufd \$0x4e,%xmm4,%xmm0 + por %xmm4,%xmm0 + lea $STRIDE($bp),$bp + + mov ($ap),%rax # ap[0] + movq %xmm0,$m0 # m0=bp[i] + + xor $j,$j # j=0 + mov $n0,$m1 + mov (%rsp),$lo0 + + mulq $m0 # ap[0]*bp[i] + add %rax,$lo0 # ap[0]*bp[i]+tp[0] + mov ($np),%rax + adc \$0,%rdx + + imulq $lo0,$m1 # tp[0]*n0 + mov %rdx,$hi0 + + mulq $m1 # np[0]*m1 + add %rax,$lo0 # discarded + mov 8($ap),%rax + adc \$0,%rdx + mov 8(%rsp),$lo0 # tp[1] + mov %rdx,$hi1 + + lea 1($j),$j # j++ + jmp .Linner_enter + +.align 16 +.Linner: + add %rax,$hi1 + mov ($ap,$j,8),%rax + adc \$0,%rdx + add $lo0,$hi1 # np[j]*m1+ap[j]*bp[i]+tp[j] + mov (%rsp,$j,8),$lo0 + adc \$0,%rdx + mov $hi1,-16(%rsp,$j,8) # tp[j-1] + mov %rdx,$hi1 + +.Linner_enter: + mulq $m0 # ap[j]*bp[i] + add %rax,$hi0 + mov ($np,$j,8),%rax + adc \$0,%rdx + add $hi0,$lo0 # ap[j]*bp[i]+tp[j] + mov %rdx,$hi0 + adc \$0,$hi0 + lea 1($j),$j # j++ + + mulq $m1 # np[j]*m1 + cmp $num,$j + jne .Linner # note that upon exit $j==$num, so + # they can be used interchangeably + add %rax,$hi1 + adc \$0,%rdx + add $lo0,$hi1 # np[j]*m1+ap[j]*bp[i]+tp[j] + mov (%rsp,$num,8),$lo0 + adc \$0,%rdx + mov $hi1,-16(%rsp,$num,8) # tp[num-1] + mov %rdx,$hi1 + + xor %rdx,%rdx + add $hi0,$hi1 + adc \$0,%rdx + add $lo0,$hi1 # pull upmost overflow bit + adc \$0,%rdx + mov $hi1,-8(%rsp,$num,8) + mov %rdx,(%rsp,$num,8) # store upmost overflow bit + + lea 1($i),$i # i++ + cmp $num,$i + jb .Louter + + xor $i,$i # i=0 and clear CF! + mov (%rsp),%rax # tp[0] + lea (%rsp),$ap # borrow ap for tp + mov $num,$j # j=num + jmp .Lsub +.align 16 +.Lsub: sbb ($np,$i,8),%rax + mov %rax,($rp,$i,8) # rp[i]=tp[i]-np[i] + mov 8($ap,$i,8),%rax # tp[i+1] + lea 1($i),$i # i++ + dec $j # doesn't affect CF! + jnz .Lsub + + sbb \$0,%rax # handle upmost overflow bit + mov \$-1,%rbx + xor %rax,%rbx + xor $i,$i + mov $num,$j # j=num + +.Lcopy: # conditional copy + mov ($rp,$i,8),%rcx + mov (%rsp,$i,8),%rdx + and %rbx,%rcx + and %rax,%rdx + mov $i,(%rsp,$i,8) # zap temporary vector + or %rcx,%rdx + mov %rdx,($rp,$i,8) # rp[i]=tp[i] + lea 1($i),$i + sub \$1,$j + jnz .Lcopy + + mov 8(%rsp,$num,8),%rsi # restore %rsp +.cfi_def_cfa %rsi,8 + mov \$1,%rax + + mov -48(%rsi),%r15 +.cfi_restore %r15 + mov -40(%rsi),%r14 +.cfi_restore %r14 + mov -32(%rsi),%r13 +.cfi_restore %r13 + mov -24(%rsi),%r12 +.cfi_restore %r12 + mov -16(%rsi),%rbp +.cfi_restore %rbp + mov -8(%rsi),%rbx +.cfi_restore %rbx + lea (%rsi),%rsp +.cfi_def_cfa_register %rsp +.Lmul_epilogue: + ret +.cfi_endproc +.size bn_mul_mont_gather5,.-bn_mul_mont_gather5 +___ +{{{ +my @A=("%r10","%r11"); +my @N=("%r13","%rdi"); +$code.=<<___; +.type bn_mul4x_mont_gather5,\@function,6 +.align 32 +bn_mul4x_mont_gather5: +.cfi_startproc + .byte 0x67 + mov %rsp,%rax +.cfi_def_cfa_register %rax +.Lmul4x_enter: +___ +$code.=<<___ if ($addx); + and \$0x80108,%r11d + cmp \$0x80108,%r11d # check for AD*X+BMI2+BMI1 + je .Lmulx4x_enter +___ +$code.=<<___; + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +.Lmul4x_prologue: + + .byte 0x67 + shl \$3,${num}d # convert $num to bytes + lea ($num,$num,2),%r10 # 3*$num in bytes + neg $num # -$num + + ############################################################## + # Ensure that stack frame doesn't alias with $rptr+3*$num + # modulo 4096, which covers ret[num], am[num] and n[num] + # (see bn_exp.c). This is done to allow memory disambiguation + # logic do its magic. [Extra [num] is allocated in order + # to align with bn_power5's frame, which is cleansed after + # completing exponentiation. Extra 256 bytes is for power mask + # calculated from 7th argument, the index.] + # + lea -320(%rsp,$num,2),%r11 + mov %rsp,%rbp + sub $rp,%r11 + and \$4095,%r11 + cmp %r11,%r10 + jb .Lmul4xsp_alt + sub %r11,%rbp # align with $rp + lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*num*8+256) + jmp .Lmul4xsp_done + +.align 32 +.Lmul4xsp_alt: + lea 4096-320(,$num,2),%r10 + lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*num*8+256) + sub %r10,%r11 + mov \$0,%r10 + cmovc %r10,%r11 + sub %r11,%rbp +.Lmul4xsp_done: + and \$-64,%rbp + mov %rsp,%r11 + sub %rbp,%r11 + and \$-4096,%r11 + lea (%rbp,%r11),%rsp + mov (%rsp),%r10 + cmp %rbp,%rsp + ja .Lmul4x_page_walk + jmp .Lmul4x_page_walk_done + +.Lmul4x_page_walk: + lea -4096(%rsp),%rsp + mov (%rsp),%r10 + cmp %rbp,%rsp + ja .Lmul4x_page_walk +.Lmul4x_page_walk_done: + + neg $num + + mov %rax,40(%rsp) +.cfi_cfa_expression %rsp+40,deref,+8 +.Lmul4x_body: + + call mul4x_internal + + mov 40(%rsp),%rsi # restore %rsp +.cfi_def_cfa %rsi,8 + mov \$1,%rax + + mov -48(%rsi),%r15 +.cfi_restore %r15 + mov -40(%rsi),%r14 +.cfi_restore %r14 + mov -32(%rsi),%r13 +.cfi_restore %r13 + mov -24(%rsi),%r12 +.cfi_restore %r12 + mov -16(%rsi),%rbp +.cfi_restore %rbp + mov -8(%rsi),%rbx +.cfi_restore %rbx + lea (%rsi),%rsp +.cfi_def_cfa_register %rsp +.Lmul4x_epilogue: + ret +.cfi_endproc +.size bn_mul4x_mont_gather5,.-bn_mul4x_mont_gather5 + +.type mul4x_internal,\@abi-omnipotent +.align 32 +mul4x_internal: + shl \$5,$num # $num was in bytes + movd `($win64?56:8)`(%rax),%xmm5 # load 7th argument, index + lea .Linc(%rip),%rax + lea 128(%rdx,$num),%r13 # end of powers table (+size optimization) + shr \$5,$num # restore $num +___ + $bp="%r12"; + $STRIDE=2**5*8; # 5 is "window size" + $N=$STRIDE/4; # should match cache line size + $tp=$i; +$code.=<<___; + movdqa 0(%rax),%xmm0 # 00000001000000010000000000000000 + movdqa 16(%rax),%xmm1 # 00000002000000020000000200000002 + lea 88-112(%rsp,$num),%r10 # place the mask after tp[num+1] (+ICache optimization) + lea 128(%rdx),$bp # size optimization + + pshufd \$0,%xmm5,%xmm5 # broadcast index + movdqa %xmm1,%xmm4 + .byte 0x67,0x67 + movdqa %xmm1,%xmm2 +___ +######################################################################## +# calculate mask by comparing 0..31 to index and save result to stack +# +$code.=<<___; + paddd %xmm0,%xmm1 + pcmpeqd %xmm5,%xmm0 # compare to 1,0 + .byte 0x67 + movdqa %xmm4,%xmm3 +___ +for($i=0;$i<$STRIDE/16-4;$i+=4) { +$code.=<<___; + paddd %xmm1,%xmm2 + pcmpeqd %xmm5,%xmm1 # compare to 3,2 + movdqa %xmm0,`16*($i+0)+112`(%r10) + movdqa %xmm4,%xmm0 + + paddd %xmm2,%xmm3 + pcmpeqd %xmm5,%xmm2 # compare to 5,4 + movdqa %xmm1,`16*($i+1)+112`(%r10) + movdqa %xmm4,%xmm1 + + paddd %xmm3,%xmm0 + pcmpeqd %xmm5,%xmm3 # compare to 7,6 + movdqa %xmm2,`16*($i+2)+112`(%r10) + movdqa %xmm4,%xmm2 + + paddd %xmm0,%xmm1 + pcmpeqd %xmm5,%xmm0 + movdqa %xmm3,`16*($i+3)+112`(%r10) + movdqa %xmm4,%xmm3 +___ +} +$code.=<<___; # last iteration can be optimized + paddd %xmm1,%xmm2 + pcmpeqd %xmm5,%xmm1 + movdqa %xmm0,`16*($i+0)+112`(%r10) + + paddd %xmm2,%xmm3 + .byte 0x67 + pcmpeqd %xmm5,%xmm2 + movdqa %xmm1,`16*($i+1)+112`(%r10) + + pcmpeqd %xmm5,%xmm3 + movdqa %xmm2,`16*($i+2)+112`(%r10) + pand `16*($i+0)-128`($bp),%xmm0 # while it's still in register + + pand `16*($i+1)-128`($bp),%xmm1 + pand `16*($i+2)-128`($bp),%xmm2 + movdqa %xmm3,`16*($i+3)+112`(%r10) + pand `16*($i+3)-128`($bp),%xmm3 + por %xmm2,%xmm0 + por %xmm3,%xmm1 +___ +for($i=0;$i<$STRIDE/16-4;$i+=4) { +$code.=<<___; + movdqa `16*($i+0)-128`($bp),%xmm4 + movdqa `16*($i+1)-128`($bp),%xmm5 + movdqa `16*($i+2)-128`($bp),%xmm2 + pand `16*($i+0)+112`(%r10),%xmm4 + movdqa `16*($i+3)-128`($bp),%xmm3 + pand `16*($i+1)+112`(%r10),%xmm5 + por %xmm4,%xmm0 + pand `16*($i+2)+112`(%r10),%xmm2 + por %xmm5,%xmm1 + pand `16*($i+3)+112`(%r10),%xmm3 + por %xmm2,%xmm0 + por %xmm3,%xmm1 +___ +} +$code.=<<___; + por %xmm1,%xmm0 + pshufd \$0x4e,%xmm0,%xmm1 + por %xmm1,%xmm0 + lea $STRIDE($bp),$bp + movq %xmm0,$m0 # m0=bp[0] + + mov %r13,16+8(%rsp) # save end of b[num] + mov $rp, 56+8(%rsp) # save $rp + + mov ($n0),$n0 # pull n0[0] value + mov ($ap),%rax + lea ($ap,$num),$ap # end of a[num] + neg $num + + mov $n0,$m1 + mulq $m0 # ap[0]*bp[0] + mov %rax,$A[0] + mov ($np),%rax + + imulq $A[0],$m1 # "tp[0]"*n0 + lea 64+8(%rsp),$tp + mov %rdx,$A[1] + + mulq $m1 # np[0]*m1 + add %rax,$A[0] # discarded + mov 8($ap,$num),%rax + adc \$0,%rdx + mov %rdx,$N[1] + + mulq $m0 + add %rax,$A[1] + mov 8*1($np),%rax + adc \$0,%rdx + mov %rdx,$A[0] + + mulq $m1 + add %rax,$N[1] + mov 16($ap,$num),%rax + adc \$0,%rdx + add $A[1],$N[1] + lea 4*8($num),$j # j=4 + lea 8*4($np),$np + adc \$0,%rdx + mov $N[1],($tp) + mov %rdx,$N[0] + jmp .L1st4x + +.align 32 +.L1st4x: + mulq $m0 # ap[j]*bp[0] + add %rax,$A[0] + mov -8*2($np),%rax + lea 32($tp),$tp + adc \$0,%rdx + mov %rdx,$A[1] + + mulq $m1 # np[j]*m1 + add %rax,$N[0] + mov -8($ap,$j),%rax + adc \$0,%rdx + add $A[0],$N[0] # np[j]*m1+ap[j]*bp[0] + adc \$0,%rdx + mov $N[0],-24($tp) # tp[j-1] + mov %rdx,$N[1] + + mulq $m0 # ap[j]*bp[0] + add %rax,$A[1] + mov -8*1($np),%rax + adc \$0,%rdx + mov %rdx,$A[0] + + mulq $m1 # np[j]*m1 + add %rax,$N[1] + mov ($ap,$j),%rax + adc \$0,%rdx + add $A[1],$N[1] # np[j]*m1+ap[j]*bp[0] + adc \$0,%rdx + mov $N[1],-16($tp) # tp[j-1] + mov %rdx,$N[0] + + mulq $m0 # ap[j]*bp[0] + add %rax,$A[0] + mov 8*0($np),%rax + adc \$0,%rdx + mov %rdx,$A[1] + + mulq $m1 # np[j]*m1 + add %rax,$N[0] + mov 8($ap,$j),%rax + adc \$0,%rdx + add $A[0],$N[0] # np[j]*m1+ap[j]*bp[0] + adc \$0,%rdx + mov $N[0],-8($tp) # tp[j-1] + mov %rdx,$N[1] + + mulq $m0 # ap[j]*bp[0] + add %rax,$A[1] + mov 8*1($np),%rax + adc \$0,%rdx + mov %rdx,$A[0] + + mulq $m1 # np[j]*m1 + add %rax,$N[1] + mov 16($ap,$j),%rax + adc \$0,%rdx + add $A[1],$N[1] # np[j]*m1+ap[j]*bp[0] + lea 8*4($np),$np + adc \$0,%rdx + mov $N[1],($tp) # tp[j-1] + mov %rdx,$N[0] + + add \$32,$j # j+=4 + jnz .L1st4x + + mulq $m0 # ap[j]*bp[0] + add %rax,$A[0] + mov -8*2($np),%rax + lea 32($tp),$tp + adc \$0,%rdx + mov %rdx,$A[1] + + mulq $m1 # np[j]*m1 + add %rax,$N[0] + mov -8($ap),%rax + adc \$0,%rdx + add $A[0],$N[0] # np[j]*m1+ap[j]*bp[0] + adc \$0,%rdx + mov $N[0],-24($tp) # tp[j-1] + mov %rdx,$N[1] + + mulq $m0 # ap[j]*bp[0] + add %rax,$A[1] + mov -8*1($np),%rax + adc \$0,%rdx + mov %rdx,$A[0] + + mulq $m1 # np[j]*m1 + add %rax,$N[1] + mov ($ap,$num),%rax # ap[0] + adc \$0,%rdx + add $A[1],$N[1] # np[j]*m1+ap[j]*bp[0] + adc \$0,%rdx + mov $N[1],-16($tp) # tp[j-1] + mov %rdx,$N[0] + + lea ($np,$num),$np # rewind $np + + xor $N[1],$N[1] + add $A[0],$N[0] + adc \$0,$N[1] + mov $N[0],-8($tp) + + jmp .Louter4x + +.align 32 +.Louter4x: + lea 16+128($tp),%rdx # where 256-byte mask is (+size optimization) + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 +___ +for($i=0;$i<$STRIDE/16;$i+=4) { +$code.=<<___; + movdqa `16*($i+0)-128`($bp),%xmm0 + movdqa `16*($i+1)-128`($bp),%xmm1 + movdqa `16*($i+2)-128`($bp),%xmm2 + movdqa `16*($i+3)-128`($bp),%xmm3 + pand `16*($i+0)-128`(%rdx),%xmm0 + pand `16*($i+1)-128`(%rdx),%xmm1 + por %xmm0,%xmm4 + pand `16*($i+2)-128`(%rdx),%xmm2 + por %xmm1,%xmm5 + pand `16*($i+3)-128`(%rdx),%xmm3 + por %xmm2,%xmm4 + por %xmm3,%xmm5 +___ +} +$code.=<<___; + por %xmm5,%xmm4 + pshufd \$0x4e,%xmm4,%xmm0 + por %xmm4,%xmm0 + lea $STRIDE($bp),$bp + movq %xmm0,$m0 # m0=bp[i] + + mov ($tp,$num),$A[0] + mov $n0,$m1 + mulq $m0 # ap[0]*bp[i] + add %rax,$A[0] # ap[0]*bp[i]+tp[0] + mov ($np),%rax + adc \$0,%rdx + + imulq $A[0],$m1 # tp[0]*n0 + mov %rdx,$A[1] + mov $N[1],($tp) # store upmost overflow bit + + lea ($tp,$num),$tp # rewind $tp + + mulq $m1 # np[0]*m1 + add %rax,$A[0] # "$N[0]", discarded + mov 8($ap,$num),%rax + adc \$0,%rdx + mov %rdx,$N[1] + + mulq $m0 # ap[j]*bp[i] + add %rax,$A[1] + mov 8*1($np),%rax + adc \$0,%rdx + add 8($tp),$A[1] # +tp[1] + adc \$0,%rdx + mov %rdx,$A[0] + + mulq $m1 # np[j]*m1 + add %rax,$N[1] + mov 16($ap,$num),%rax + adc \$0,%rdx + add $A[1],$N[1] # np[j]*m1+ap[j]*bp[i]+tp[j] + lea 4*8($num),$j # j=4 + lea 8*4($np),$np + adc \$0,%rdx + mov %rdx,$N[0] + jmp .Linner4x + +.align 32 +.Linner4x: + mulq $m0 # ap[j]*bp[i] + add %rax,$A[0] + mov -8*2($np),%rax + adc \$0,%rdx + add 16($tp),$A[0] # ap[j]*bp[i]+tp[j] + lea 32($tp),$tp + adc \$0,%rdx + mov %rdx,$A[1] + + mulq $m1 # np[j]*m1 + add %rax,$N[0] + mov -8($ap,$j),%rax + adc \$0,%rdx + add $A[0],$N[0] + adc \$0,%rdx + mov $N[1],-32($tp) # tp[j-1] + mov %rdx,$N[1] + + mulq $m0 # ap[j]*bp[i] + add %rax,$A[1] + mov -8*1($np),%rax + adc \$0,%rdx + add -8($tp),$A[1] + adc \$0,%rdx + mov %rdx,$A[0] + + mulq $m1 # np[j]*m1 + add %rax,$N[1] + mov ($ap,$j),%rax + adc \$0,%rdx + add $A[1],$N[1] + adc \$0,%rdx + mov $N[0],-24($tp) # tp[j-1] + mov %rdx,$N[0] + + mulq $m0 # ap[j]*bp[i] + add %rax,$A[0] + mov 8*0($np),%rax + adc \$0,%rdx + add ($tp),$A[0] # ap[j]*bp[i]+tp[j] + adc \$0,%rdx + mov %rdx,$A[1] + + mulq $m1 # np[j]*m1 + add %rax,$N[0] + mov 8($ap,$j),%rax + adc \$0,%rdx + add $A[0],$N[0] + adc \$0,%rdx + mov $N[1],-16($tp) # tp[j-1] + mov %rdx,$N[1] + + mulq $m0 # ap[j]*bp[i] + add %rax,$A[1] + mov 8*1($np),%rax + adc \$0,%rdx + add 8($tp),$A[1] + adc \$0,%rdx + mov %rdx,$A[0] + + mulq $m1 # np[j]*m1 + add %rax,$N[1] + mov 16($ap,$j),%rax + adc \$0,%rdx + add $A[1],$N[1] + lea 8*4($np),$np + adc \$0,%rdx + mov $N[0],-8($tp) # tp[j-1] + mov %rdx,$N[0] + + add \$32,$j # j+=4 + jnz .Linner4x + + mulq $m0 # ap[j]*bp[i] + add %rax,$A[0] + mov -8*2($np),%rax + adc \$0,%rdx + add 16($tp),$A[0] # ap[j]*bp[i]+tp[j] + lea 32($tp),$tp + adc \$0,%rdx + mov %rdx,$A[1] + + mulq $m1 # np[j]*m1 + add %rax,$N[0] + mov -8($ap),%rax + adc \$0,%rdx + add $A[0],$N[0] + adc \$0,%rdx + mov $N[1],-32($tp) # tp[j-1] + mov %rdx,$N[1] + + mulq $m0 # ap[j]*bp[i] + add %rax,$A[1] + mov $m1,%rax + mov -8*1($np),$m1 + adc \$0,%rdx + add -8($tp),$A[1] + adc \$0,%rdx + mov %rdx,$A[0] + + mulq $m1 # np[j]*m1 + add %rax,$N[1] + mov ($ap,$num),%rax # ap[0] + adc \$0,%rdx + add $A[1],$N[1] + adc \$0,%rdx + mov $N[0],-24($tp) # tp[j-1] + mov %rdx,$N[0] + + mov $N[1],-16($tp) # tp[j-1] + lea ($np,$num),$np # rewind $np + + xor $N[1],$N[1] + add $A[0],$N[0] + adc \$0,$N[1] + add ($tp),$N[0] # pull upmost overflow bit + adc \$0,$N[1] # upmost overflow bit + mov $N[0],-8($tp) + + cmp 16+8(%rsp),$bp + jb .Louter4x +___ +if (1) { +$code.=<<___; + xor %rax,%rax + sub $N[0],$m1 # compare top-most words + adc $j,$j # $j is zero + or $j,$N[1] + sub $N[1],%rax # %rax=-$N[1] + lea ($tp,$num),%rbx # tptr in .sqr4x_sub + mov ($np),%r12 + lea ($np),%rbp # nptr in .sqr4x_sub + mov %r9,%rcx + sar \$3+2,%rcx + mov 56+8(%rsp),%rdi # rptr in .sqr4x_sub + dec %r12 # so that after 'not' we get -n[0] + xor %r10,%r10 + mov 8*1(%rbp),%r13 + mov 8*2(%rbp),%r14 + mov 8*3(%rbp),%r15 + jmp .Lsqr4x_sub_entry +___ +} else { +my @ri=("%rax",$bp,$m0,$m1); +my $rp="%rdx"; +$code.=<<___ + xor \$1,$N[1] + lea ($tp,$num),$tp # rewind $tp + sar \$5,$num # cf=0 + lea ($np,$N[1],8),$np + mov 56+8(%rsp),$rp # restore $rp + jmp .Lsub4x + +.align 32 +.Lsub4x: + .byte 0x66 + mov 8*0($tp),@ri[0] + mov 8*1($tp),@ri[1] + .byte 0x66 + sbb 16*0($np),@ri[0] + mov 8*2($tp),@ri[2] + sbb 16*1($np),@ri[1] + mov 3*8($tp),@ri[3] + lea 4*8($tp),$tp + sbb 16*2($np),@ri[2] + mov @ri[0],8*0($rp) + sbb 16*3($np),@ri[3] + lea 16*4($np),$np + mov @ri[1],8*1($rp) + mov @ri[2],8*2($rp) + mov @ri[3],8*3($rp) + lea 8*4($rp),$rp + + inc $num + jnz .Lsub4x + + ret +___ +} +$code.=<<___; +.size mul4x_internal,.-mul4x_internal +___ +}}} + {{{ +###################################################################### +# void bn_power5( +my $rptr="%rdi"; # BN_ULONG *rptr, +my $aptr="%rsi"; # const BN_ULONG *aptr, +my $bptr="%rdx"; # const void *table, +my $nptr="%rcx"; # const BN_ULONG *nptr, +my $n0 ="%r8"; # const BN_ULONG *n0); +my $num ="%r9"; # int num, has to be divisible by 8 + # int pwr + +my ($i,$j,$tptr)=("%rbp","%rcx",$rptr); +my @A0=("%r10","%r11"); +my @A1=("%r12","%r13"); +my ($a0,$a1,$ai)=("%r14","%r15","%rbx"); + +$code.=<<___; +.globl bn_power5 +.type bn_power5,\@function,6 +.align 32 +bn_power5: +.cfi_startproc + mov %rsp,%rax +.cfi_def_cfa_register %rax +___ +$code.=<<___ if ($addx); + mov OPENSSL_ia32cap_P+8(%rip),%r11d + and \$0x80108,%r11d + cmp \$0x80108,%r11d # check for AD*X+BMI2+BMI1 + je .Lpowerx5_enter +___ +$code.=<<___; + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +.Lpower5_prologue: + + shl \$3,${num}d # convert $num to bytes + lea ($num,$num,2),%r10d # 3*$num + neg $num + mov ($n0),$n0 # *n0 + + ############################################################## + # Ensure that stack frame doesn't alias with $rptr+3*$num + # modulo 4096, which covers ret[num], am[num] and n[num] + # (see bn_exp.c). This is done to allow memory disambiguation + # logic do its magic. [Extra 256 bytes is for power mask + # calculated from 7th argument, the index.] + # + lea -320(%rsp,$num,2),%r11 + mov %rsp,%rbp + sub $rptr,%r11 + and \$4095,%r11 + cmp %r11,%r10 + jb .Lpwr_sp_alt + sub %r11,%rbp # align with $aptr + lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*num*8+256) + jmp .Lpwr_sp_done + +.align 32 +.Lpwr_sp_alt: + lea 4096-320(,$num,2),%r10 + lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*num*8+256) + sub %r10,%r11 + mov \$0,%r10 + cmovc %r10,%r11 + sub %r11,%rbp +.Lpwr_sp_done: + and \$-64,%rbp + mov %rsp,%r11 + sub %rbp,%r11 + and \$-4096,%r11 + lea (%rbp,%r11),%rsp + mov (%rsp),%r10 + cmp %rbp,%rsp + ja .Lpwr_page_walk + jmp .Lpwr_page_walk_done + +.Lpwr_page_walk: + lea -4096(%rsp),%rsp + mov (%rsp),%r10 + cmp %rbp,%rsp + ja .Lpwr_page_walk +.Lpwr_page_walk_done: + + mov $num,%r10 + neg $num + + ############################################################## + # Stack layout + # + # +0 saved $num, used in reduction section + # +8 &t[2*$num], used in reduction section + # +32 saved *n0 + # +40 saved %rsp + # +48 t[2*$num] + # + mov $n0, 32(%rsp) + mov %rax, 40(%rsp) # save original %rsp +.cfi_cfa_expression %rsp+40,deref,+8 +.Lpower5_body: + movq $rptr,%xmm1 # save $rptr, used in sqr8x + movq $nptr,%xmm2 # save $nptr + movq %r10, %xmm3 # -$num, used in sqr8x + movq $bptr,%xmm4 + + call __bn_sqr8x_internal + call __bn_post4x_internal + call __bn_sqr8x_internal + call __bn_post4x_internal + call __bn_sqr8x_internal + call __bn_post4x_internal + call __bn_sqr8x_internal + call __bn_post4x_internal + call __bn_sqr8x_internal + call __bn_post4x_internal + + movq %xmm2,$nptr + movq %xmm4,$bptr + mov $aptr,$rptr + mov 40(%rsp),%rax + lea 32(%rsp),$n0 + + call mul4x_internal + + mov 40(%rsp),%rsi # restore %rsp +.cfi_def_cfa %rsi,8 + mov \$1,%rax + mov -48(%rsi),%r15 +.cfi_restore %r15 + mov -40(%rsi),%r14 +.cfi_restore %r14 + mov -32(%rsi),%r13 +.cfi_restore %r13 + mov -24(%rsi),%r12 +.cfi_restore %r12 + mov -16(%rsi),%rbp +.cfi_restore %rbp + mov -8(%rsi),%rbx +.cfi_restore %rbx + lea (%rsi),%rsp +.cfi_def_cfa_register %rsp +.Lpower5_epilogue: + ret +.cfi_endproc +.size bn_power5,.-bn_power5 + +.globl bn_sqr8x_internal +.hidden bn_sqr8x_internal +.type bn_sqr8x_internal,\@abi-omnipotent +.align 32 +bn_sqr8x_internal: +__bn_sqr8x_internal: + ############################################################## + # Squaring part: + # + # a) multiply-n-add everything but a[i]*a[i]; + # b) shift result of a) by 1 to the left and accumulate + # a[i]*a[i] products; + # + ############################################################## + # a[1]a[0] + # a[2]a[0] + # a[3]a[0] + # a[2]a[1] + # a[4]a[0] + # a[3]a[1] + # a[5]a[0] + # a[4]a[1] + # a[3]a[2] + # a[6]a[0] + # a[5]a[1] + # a[4]a[2] + # a[7]a[0] + # a[6]a[1] + # a[5]a[2] + # a[4]a[3] + # a[7]a[1] + # a[6]a[2] + # a[5]a[3] + # a[7]a[2] + # a[6]a[3] + # a[5]a[4] + # a[7]a[3] + # a[6]a[4] + # a[7]a[4] + # a[6]a[5] + # a[7]a[5] + # a[7]a[6] + # a[1]a[0] + # a[2]a[0] + # a[3]a[0] + # a[4]a[0] + # a[5]a[0] + # a[6]a[0] + # a[7]a[0] + # a[2]a[1] + # a[3]a[1] + # a[4]a[1] + # a[5]a[1] + # a[6]a[1] + # a[7]a[1] + # a[3]a[2] + # a[4]a[2] + # a[5]a[2] + # a[6]a[2] + # a[7]a[2] + # a[4]a[3] + # a[5]a[3] + # a[6]a[3] + # a[7]a[3] + # a[5]a[4] + # a[6]a[4] + # a[7]a[4] + # a[6]a[5] + # a[7]a[5] + # a[7]a[6] + # a[0]a[0] + # a[1]a[1] + # a[2]a[2] + # a[3]a[3] + # a[4]a[4] + # a[5]a[5] + # a[6]a[6] + # a[7]a[7] + + lea 32(%r10),$i # $i=-($num-32) + lea ($aptr,$num),$aptr # end of a[] buffer, ($aptr,$i)=&ap[2] + + mov $num,$j # $j=$num + + # comments apply to $num==8 case + mov -32($aptr,$i),$a0 # a[0] + lea 48+8(%rsp,$num,2),$tptr # end of tp[] buffer, &tp[2*$num] + mov -24($aptr,$i),%rax # a[1] + lea -32($tptr,$i),$tptr # end of tp[] window, &tp[2*$num-"$i"] + mov -16($aptr,$i),$ai # a[2] + mov %rax,$a1 + + mul $a0 # a[1]*a[0] + mov %rax,$A0[0] # a[1]*a[0] + mov $ai,%rax # a[2] + mov %rdx,$A0[1] + mov $A0[0],-24($tptr,$i) # t[1] + + mul $a0 # a[2]*a[0] + add %rax,$A0[1] + mov $ai,%rax + adc \$0,%rdx + mov $A0[1],-16($tptr,$i) # t[2] + mov %rdx,$A0[0] + + + mov -8($aptr,$i),$ai # a[3] + mul $a1 # a[2]*a[1] + mov %rax,$A1[0] # a[2]*a[1]+t[3] + mov $ai,%rax + mov %rdx,$A1[1] + + lea ($i),$j + mul $a0 # a[3]*a[0] + add %rax,$A0[0] # a[3]*a[0]+a[2]*a[1]+t[3] + mov $ai,%rax + mov %rdx,$A0[1] + adc \$0,$A0[1] + add $A1[0],$A0[0] + adc \$0,$A0[1] + mov $A0[0],-8($tptr,$j) # t[3] + jmp .Lsqr4x_1st + +.align 32 +.Lsqr4x_1st: + mov ($aptr,$j),$ai # a[4] + mul $a1 # a[3]*a[1] + add %rax,$A1[1] # a[3]*a[1]+t[4] + mov $ai,%rax + mov %rdx,$A1[0] + adc \$0,$A1[0] + + mul $a0 # a[4]*a[0] + add %rax,$A0[1] # a[4]*a[0]+a[3]*a[1]+t[4] + mov $ai,%rax # a[3] + mov 8($aptr,$j),$ai # a[5] + mov %rdx,$A0[0] + adc \$0,$A0[0] + add $A1[1],$A0[1] + adc \$0,$A0[0] + + + mul $a1 # a[4]*a[3] + add %rax,$A1[0] # a[4]*a[3]+t[5] + mov $ai,%rax + mov $A0[1],($tptr,$j) # t[4] + mov %rdx,$A1[1] + adc \$0,$A1[1] + + mul $a0 # a[5]*a[2] + add %rax,$A0[0] # a[5]*a[2]+a[4]*a[3]+t[5] + mov $ai,%rax + mov 16($aptr,$j),$ai # a[6] + mov %rdx,$A0[1] + adc \$0,$A0[1] + add $A1[0],$A0[0] + adc \$0,$A0[1] + + mul $a1 # a[5]*a[3] + add %rax,$A1[1] # a[5]*a[3]+t[6] + mov $ai,%rax + mov $A0[0],8($tptr,$j) # t[5] + mov %rdx,$A1[0] + adc \$0,$A1[0] + + mul $a0 # a[6]*a[2] + add %rax,$A0[1] # a[6]*a[2]+a[5]*a[3]+t[6] + mov $ai,%rax # a[3] + mov 24($aptr,$j),$ai # a[7] + mov %rdx,$A0[0] + adc \$0,$A0[0] + add $A1[1],$A0[1] + adc \$0,$A0[0] + + + mul $a1 # a[6]*a[5] + add %rax,$A1[0] # a[6]*a[5]+t[7] + mov $ai,%rax + mov $A0[1],16($tptr,$j) # t[6] + mov %rdx,$A1[1] + adc \$0,$A1[1] + lea 32($j),$j + + mul $a0 # a[7]*a[4] + add %rax,$A0[0] # a[7]*a[4]+a[6]*a[5]+t[6] + mov $ai,%rax + mov %rdx,$A0[1] + adc \$0,$A0[1] + add $A1[0],$A0[0] + adc \$0,$A0[1] + mov $A0[0],-8($tptr,$j) # t[7] + + cmp \$0,$j + jne .Lsqr4x_1st + + mul $a1 # a[7]*a[5] + add %rax,$A1[1] + lea 16($i),$i + adc \$0,%rdx + add $A0[1],$A1[1] + adc \$0,%rdx + + mov $A1[1],($tptr) # t[8] + mov %rdx,$A1[0] + mov %rdx,8($tptr) # t[9] + jmp .Lsqr4x_outer + +.align 32 +.Lsqr4x_outer: # comments apply to $num==6 case + mov -32($aptr,$i),$a0 # a[0] + lea 48+8(%rsp,$num,2),$tptr # end of tp[] buffer, &tp[2*$num] + mov -24($aptr,$i),%rax # a[1] + lea -32($tptr,$i),$tptr # end of tp[] window, &tp[2*$num-"$i"] + mov -16($aptr,$i),$ai # a[2] + mov %rax,$a1 + + mul $a0 # a[1]*a[0] + mov -24($tptr,$i),$A0[0] # t[1] + add %rax,$A0[0] # a[1]*a[0]+t[1] + mov $ai,%rax # a[2] + adc \$0,%rdx + mov $A0[0],-24($tptr,$i) # t[1] + mov %rdx,$A0[1] + + mul $a0 # a[2]*a[0] + add %rax,$A0[1] + mov $ai,%rax + adc \$0,%rdx + add -16($tptr,$i),$A0[1] # a[2]*a[0]+t[2] + mov %rdx,$A0[0] + adc \$0,$A0[0] + mov $A0[1],-16($tptr,$i) # t[2] + + xor $A1[0],$A1[0] + + mov -8($aptr,$i),$ai # a[3] + mul $a1 # a[2]*a[1] + add %rax,$A1[0] # a[2]*a[1]+t[3] + mov $ai,%rax + adc \$0,%rdx + add -8($tptr,$i),$A1[0] + mov %rdx,$A1[1] + adc \$0,$A1[1] + + mul $a0 # a[3]*a[0] + add %rax,$A0[0] # a[3]*a[0]+a[2]*a[1]+t[3] + mov $ai,%rax + adc \$0,%rdx + add $A1[0],$A0[0] + mov %rdx,$A0[1] + adc \$0,$A0[1] + mov $A0[0],-8($tptr,$i) # t[3] + + lea ($i),$j + jmp .Lsqr4x_inner + +.align 32 +.Lsqr4x_inner: + mov ($aptr,$j),$ai # a[4] + mul $a1 # a[3]*a[1] + add %rax,$A1[1] # a[3]*a[1]+t[4] + mov $ai,%rax + mov %rdx,$A1[0] + adc \$0,$A1[0] + add ($tptr,$j),$A1[1] + adc \$0,$A1[0] + + .byte 0x67 + mul $a0 # a[4]*a[0] + add %rax,$A0[1] # a[4]*a[0]+a[3]*a[1]+t[4] + mov $ai,%rax # a[3] + mov 8($aptr,$j),$ai # a[5] + mov %rdx,$A0[0] + adc \$0,$A0[0] + add $A1[1],$A0[1] + adc \$0,$A0[0] + + mul $a1 # a[4]*a[3] + add %rax,$A1[0] # a[4]*a[3]+t[5] + mov $A0[1],($tptr,$j) # t[4] + mov $ai,%rax + mov %rdx,$A1[1] + adc \$0,$A1[1] + add 8($tptr,$j),$A1[0] + lea 16($j),$j # j++ + adc \$0,$A1[1] + + mul $a0 # a[5]*a[2] + add %rax,$A0[0] # a[5]*a[2]+a[4]*a[3]+t[5] + mov $ai,%rax + adc \$0,%rdx + add $A1[0],$A0[0] + mov %rdx,$A0[1] + adc \$0,$A0[1] + mov $A0[0],-8($tptr,$j) # t[5], "preloaded t[1]" below + + cmp \$0,$j + jne .Lsqr4x_inner + + .byte 0x67 + mul $a1 # a[5]*a[3] + add %rax,$A1[1] + adc \$0,%rdx + add $A0[1],$A1[1] + adc \$0,%rdx + + mov $A1[1],($tptr) # t[6], "preloaded t[2]" below + mov %rdx,$A1[0] + mov %rdx,8($tptr) # t[7], "preloaded t[3]" below + + add \$16,$i + jnz .Lsqr4x_outer + + # comments apply to $num==4 case + mov -32($aptr),$a0 # a[0] + lea 48+8(%rsp,$num,2),$tptr # end of tp[] buffer, &tp[2*$num] + mov -24($aptr),%rax # a[1] + lea -32($tptr,$i),$tptr # end of tp[] window, &tp[2*$num-"$i"] + mov -16($aptr),$ai # a[2] + mov %rax,$a1 + + mul $a0 # a[1]*a[0] + add %rax,$A0[0] # a[1]*a[0]+t[1], preloaded t[1] + mov $ai,%rax # a[2] + mov %rdx,$A0[1] + adc \$0,$A0[1] + + mul $a0 # a[2]*a[0] + add %rax,$A0[1] + mov $ai,%rax + mov $A0[0],-24($tptr) # t[1] + mov %rdx,$A0[0] + adc \$0,$A0[0] + add $A1[1],$A0[1] # a[2]*a[0]+t[2], preloaded t[2] + mov -8($aptr),$ai # a[3] + adc \$0,$A0[0] + + mul $a1 # a[2]*a[1] + add %rax,$A1[0] # a[2]*a[1]+t[3], preloaded t[3] + mov $ai,%rax + mov $A0[1],-16($tptr) # t[2] + mov %rdx,$A1[1] + adc \$0,$A1[1] + + mul $a0 # a[3]*a[0] + add %rax,$A0[0] # a[3]*a[0]+a[2]*a[1]+t[3] + mov $ai,%rax + mov %rdx,$A0[1] + adc \$0,$A0[1] + add $A1[0],$A0[0] + adc \$0,$A0[1] + mov $A0[0],-8($tptr) # t[3] + + mul $a1 # a[3]*a[1] + add %rax,$A1[1] + mov -16($aptr),%rax # a[2] + adc \$0,%rdx + add $A0[1],$A1[1] + adc \$0,%rdx + + mov $A1[1],($tptr) # t[4] + mov %rdx,$A1[0] + mov %rdx,8($tptr) # t[5] + + mul $ai # a[2]*a[3] +___ +{ +my ($shift,$carry)=($a0,$a1); +my @S=(@A1,$ai,$n0); +$code.=<<___; + add \$16,$i + xor $shift,$shift + sub $num,$i # $i=16-$num + xor $carry,$carry + + add $A1[0],%rax # t[5] + adc \$0,%rdx + mov %rax,8($tptr) # t[5] + mov %rdx,16($tptr) # t[6] + mov $carry,24($tptr) # t[7] + + mov -16($aptr,$i),%rax # a[0] + lea 48+8(%rsp),$tptr + xor $A0[0],$A0[0] # t[0] + mov 8($tptr),$A0[1] # t[1] + + lea ($shift,$A0[0],2),$S[0] # t[2*i]<<1 | shift + shr \$63,$A0[0] + lea ($j,$A0[1],2),$S[1] # t[2*i+1]<<1 | + shr \$63,$A0[1] + or $A0[0],$S[1] # | t[2*i]>>63 + mov 16($tptr),$A0[0] # t[2*i+2] # prefetch + mov $A0[1],$shift # shift=t[2*i+1]>>63 + mul %rax # a[i]*a[i] + neg $carry # mov $carry,cf + mov 24($tptr),$A0[1] # t[2*i+2+1] # prefetch + adc %rax,$S[0] + mov -8($aptr,$i),%rax # a[i+1] # prefetch + mov $S[0],($tptr) + adc %rdx,$S[1] + + lea ($shift,$A0[0],2),$S[2] # t[2*i]<<1 | shift + mov $S[1],8($tptr) + sbb $carry,$carry # mov cf,$carry + shr \$63,$A0[0] + lea ($j,$A0[1],2),$S[3] # t[2*i+1]<<1 | + shr \$63,$A0[1] + or $A0[0],$S[3] # | t[2*i]>>63 + mov 32($tptr),$A0[0] # t[2*i+2] # prefetch + mov $A0[1],$shift # shift=t[2*i+1]>>63 + mul %rax # a[i]*a[i] + neg $carry # mov $carry,cf + mov 40($tptr),$A0[1] # t[2*i+2+1] # prefetch + adc %rax,$S[2] + mov 0($aptr,$i),%rax # a[i+1] # prefetch + mov $S[2],16($tptr) + adc %rdx,$S[3] + lea 16($i),$i + mov $S[3],24($tptr) + sbb $carry,$carry # mov cf,$carry + lea 64($tptr),$tptr + jmp .Lsqr4x_shift_n_add + +.align 32 +.Lsqr4x_shift_n_add: + lea ($shift,$A0[0],2),$S[0] # t[2*i]<<1 | shift + shr \$63,$A0[0] + lea ($j,$A0[1],2),$S[1] # t[2*i+1]<<1 | + shr \$63,$A0[1] + or $A0[0],$S[1] # | t[2*i]>>63 + mov -16($tptr),$A0[0] # t[2*i+2] # prefetch + mov $A0[1],$shift # shift=t[2*i+1]>>63 + mul %rax # a[i]*a[i] + neg $carry # mov $carry,cf + mov -8($tptr),$A0[1] # t[2*i+2+1] # prefetch + adc %rax,$S[0] + mov -8($aptr,$i),%rax # a[i+1] # prefetch + mov $S[0],-32($tptr) + adc %rdx,$S[1] + + lea ($shift,$A0[0],2),$S[2] # t[2*i]<<1 | shift + mov $S[1],-24($tptr) + sbb $carry,$carry # mov cf,$carry + shr \$63,$A0[0] + lea ($j,$A0[1],2),$S[3] # t[2*i+1]<<1 | + shr \$63,$A0[1] + or $A0[0],$S[3] # | t[2*i]>>63 + mov 0($tptr),$A0[0] # t[2*i+2] # prefetch + mov $A0[1],$shift # shift=t[2*i+1]>>63 + mul %rax # a[i]*a[i] + neg $carry # mov $carry,cf + mov 8($tptr),$A0[1] # t[2*i+2+1] # prefetch + adc %rax,$S[2] + mov 0($aptr,$i),%rax # a[i+1] # prefetch + mov $S[2],-16($tptr) + adc %rdx,$S[3] + + lea ($shift,$A0[0],2),$S[0] # t[2*i]<<1 | shift + mov $S[3],-8($tptr) + sbb $carry,$carry # mov cf,$carry + shr \$63,$A0[0] + lea ($j,$A0[1],2),$S[1] # t[2*i+1]<<1 | + shr \$63,$A0[1] + or $A0[0],$S[1] # | t[2*i]>>63 + mov 16($tptr),$A0[0] # t[2*i+2] # prefetch + mov $A0[1],$shift # shift=t[2*i+1]>>63 + mul %rax # a[i]*a[i] + neg $carry # mov $carry,cf + mov 24($tptr),$A0[1] # t[2*i+2+1] # prefetch + adc %rax,$S[0] + mov 8($aptr,$i),%rax # a[i+1] # prefetch + mov $S[0],0($tptr) + adc %rdx,$S[1] + + lea ($shift,$A0[0],2),$S[2] # t[2*i]<<1 | shift + mov $S[1],8($tptr) + sbb $carry,$carry # mov cf,$carry + shr \$63,$A0[0] + lea ($j,$A0[1],2),$S[3] # t[2*i+1]<<1 | + shr \$63,$A0[1] + or $A0[0],$S[3] # | t[2*i]>>63 + mov 32($tptr),$A0[0] # t[2*i+2] # prefetch + mov $A0[1],$shift # shift=t[2*i+1]>>63 + mul %rax # a[i]*a[i] + neg $carry # mov $carry,cf + mov 40($tptr),$A0[1] # t[2*i+2+1] # prefetch + adc %rax,$S[2] + mov 16($aptr,$i),%rax # a[i+1] # prefetch + mov $S[2],16($tptr) + adc %rdx,$S[3] + mov $S[3],24($tptr) + sbb $carry,$carry # mov cf,$carry + lea 64($tptr),$tptr + add \$32,$i + jnz .Lsqr4x_shift_n_add + + lea ($shift,$A0[0],2),$S[0] # t[2*i]<<1 | shift + .byte 0x67 + shr \$63,$A0[0] + lea ($j,$A0[1],2),$S[1] # t[2*i+1]<<1 | + shr \$63,$A0[1] + or $A0[0],$S[1] # | t[2*i]>>63 + mov -16($tptr),$A0[0] # t[2*i+2] # prefetch + mov $A0[1],$shift # shift=t[2*i+1]>>63 + mul %rax # a[i]*a[i] + neg $carry # mov $carry,cf + mov -8($tptr),$A0[1] # t[2*i+2+1] # prefetch + adc %rax,$S[0] + mov -8($aptr),%rax # a[i+1] # prefetch + mov $S[0],-32($tptr) + adc %rdx,$S[1] + + lea ($shift,$A0[0],2),$S[2] # t[2*i]<<1|shift + mov $S[1],-24($tptr) + sbb $carry,$carry # mov cf,$carry + shr \$63,$A0[0] + lea ($j,$A0[1],2),$S[3] # t[2*i+1]<<1 | + shr \$63,$A0[1] + or $A0[0],$S[3] # | t[2*i]>>63 + mul %rax # a[i]*a[i] + neg $carry # mov $carry,cf + adc %rax,$S[2] + adc %rdx,$S[3] + mov $S[2],-16($tptr) + mov $S[3],-8($tptr) +___ +} +###################################################################### +# Montgomery reduction part, "word-by-word" algorithm. +# +# This new path is inspired by multiple submissions from Intel, by +# Shay Gueron, Vlad Krasnov, Erdinc Ozturk, James Guilford, +# Vinodh Gopal... +{ +my ($nptr,$tptr,$carry,$m0)=("%rbp","%rdi","%rsi","%rbx"); + +$code.=<<___; + movq %xmm2,$nptr +__bn_sqr8x_reduction: + xor %rax,%rax + lea ($nptr,$num),%rcx # end of n[] + lea 48+8(%rsp,$num,2),%rdx # end of t[] buffer + mov %rcx,0+8(%rsp) + lea 48+8(%rsp,$num),$tptr # end of initial t[] window + mov %rdx,8+8(%rsp) + neg $num + jmp .L8x_reduction_loop + +.align 32 +.L8x_reduction_loop: + lea ($tptr,$num),$tptr # start of current t[] window + .byte 0x66 + mov 8*0($tptr),$m0 + mov 8*1($tptr),%r9 + mov 8*2($tptr),%r10 + mov 8*3($tptr),%r11 + mov 8*4($tptr),%r12 + mov 8*5($tptr),%r13 + mov 8*6($tptr),%r14 + mov 8*7($tptr),%r15 + mov %rax,(%rdx) # store top-most carry bit + lea 8*8($tptr),$tptr + + .byte 0x67 + mov $m0,%r8 + imulq 32+8(%rsp),$m0 # n0*a[0] + mov 8*0($nptr),%rax # n[0] + mov \$8,%ecx + jmp .L8x_reduce + +.align 32 +.L8x_reduce: + mulq $m0 + mov 8*1($nptr),%rax # n[1] + neg %r8 + mov %rdx,%r8 + adc \$0,%r8 + + mulq $m0 + add %rax,%r9 + mov 8*2($nptr),%rax + adc \$0,%rdx + add %r9,%r8 + mov $m0,48-8+8(%rsp,%rcx,8) # put aside n0*a[i] + mov %rdx,%r9 + adc \$0,%r9 + + mulq $m0 + add %rax,%r10 + mov 8*3($nptr),%rax + adc \$0,%rdx + add %r10,%r9 + mov 32+8(%rsp),$carry # pull n0, borrow $carry + mov %rdx,%r10 + adc \$0,%r10 + + mulq $m0 + add %rax,%r11 + mov 8*4($nptr),%rax + adc \$0,%rdx + imulq %r8,$carry # modulo-scheduled + add %r11,%r10 + mov %rdx,%r11 + adc \$0,%r11 + + mulq $m0 + add %rax,%r12 + mov 8*5($nptr),%rax + adc \$0,%rdx + add %r12,%r11 + mov %rdx,%r12 + adc \$0,%r12 + + mulq $m0 + add %rax,%r13 + mov 8*6($nptr),%rax + adc \$0,%rdx + add %r13,%r12 + mov %rdx,%r13 + adc \$0,%r13 + + mulq $m0 + add %rax,%r14 + mov 8*7($nptr),%rax + adc \$0,%rdx + add %r14,%r13 + mov %rdx,%r14 + adc \$0,%r14 + + mulq $m0 + mov $carry,$m0 # n0*a[i] + add %rax,%r15 + mov 8*0($nptr),%rax # n[0] + adc \$0,%rdx + add %r15,%r14 + mov %rdx,%r15 + adc \$0,%r15 + + dec %ecx + jnz .L8x_reduce + + lea 8*8($nptr),$nptr + xor %rax,%rax + mov 8+8(%rsp),%rdx # pull end of t[] + cmp 0+8(%rsp),$nptr # end of n[]? + jae .L8x_no_tail + + .byte 0x66 + add 8*0($tptr),%r8 + adc 8*1($tptr),%r9 + adc 8*2($tptr),%r10 + adc 8*3($tptr),%r11 + adc 8*4($tptr),%r12 + adc 8*5($tptr),%r13 + adc 8*6($tptr),%r14 + adc 8*7($tptr),%r15 + sbb $carry,$carry # top carry + + mov 48+56+8(%rsp),$m0 # pull n0*a[0] + mov \$8,%ecx + mov 8*0($nptr),%rax + jmp .L8x_tail + +.align 32 +.L8x_tail: + mulq $m0 + add %rax,%r8 + mov 8*1($nptr),%rax + mov %r8,($tptr) # save result + mov %rdx,%r8 + adc \$0,%r8 + + mulq $m0 + add %rax,%r9 + mov 8*2($nptr),%rax + adc \$0,%rdx + add %r9,%r8 + lea 8($tptr),$tptr # $tptr++ + mov %rdx,%r9 + adc \$0,%r9 + + mulq $m0 + add %rax,%r10 + mov 8*3($nptr),%rax + adc \$0,%rdx + add %r10,%r9 + mov %rdx,%r10 + adc \$0,%r10 + + mulq $m0 + add %rax,%r11 + mov 8*4($nptr),%rax + adc \$0,%rdx + add %r11,%r10 + mov %rdx,%r11 + adc \$0,%r11 + + mulq $m0 + add %rax,%r12 + mov 8*5($nptr),%rax + adc \$0,%rdx + add %r12,%r11 + mov %rdx,%r12 + adc \$0,%r12 + + mulq $m0 + add %rax,%r13 + mov 8*6($nptr),%rax + adc \$0,%rdx + add %r13,%r12 + mov %rdx,%r13 + adc \$0,%r13 + + mulq $m0 + add %rax,%r14 + mov 8*7($nptr),%rax + adc \$0,%rdx + add %r14,%r13 + mov %rdx,%r14 + adc \$0,%r14 + + mulq $m0 + mov 48-16+8(%rsp,%rcx,8),$m0# pull n0*a[i] + add %rax,%r15 + adc \$0,%rdx + add %r15,%r14 + mov 8*0($nptr),%rax # pull n[0] + mov %rdx,%r15 + adc \$0,%r15 + + dec %ecx + jnz .L8x_tail + + lea 8*8($nptr),$nptr + mov 8+8(%rsp),%rdx # pull end of t[] + cmp 0+8(%rsp),$nptr # end of n[]? + jae .L8x_tail_done # break out of loop + + mov 48+56+8(%rsp),$m0 # pull n0*a[0] + neg $carry + mov 8*0($nptr),%rax # pull n[0] + adc 8*0($tptr),%r8 + adc 8*1($tptr),%r9 + adc 8*2($tptr),%r10 + adc 8*3($tptr),%r11 + adc 8*4($tptr),%r12 + adc 8*5($tptr),%r13 + adc 8*6($tptr),%r14 + adc 8*7($tptr),%r15 + sbb $carry,$carry # top carry + + mov \$8,%ecx + jmp .L8x_tail + +.align 32 +.L8x_tail_done: + xor %rax,%rax + add (%rdx),%r8 # can this overflow? + adc \$0,%r9 + adc \$0,%r10 + adc \$0,%r11 + adc \$0,%r12 + adc \$0,%r13 + adc \$0,%r14 + adc \$0,%r15 + adc \$0,%rax + + neg $carry +.L8x_no_tail: + adc 8*0($tptr),%r8 + adc 8*1($tptr),%r9 + adc 8*2($tptr),%r10 + adc 8*3($tptr),%r11 + adc 8*4($tptr),%r12 + adc 8*5($tptr),%r13 + adc 8*6($tptr),%r14 + adc 8*7($tptr),%r15 + adc \$0,%rax # top-most carry + mov -8($nptr),%rcx # np[num-1] + xor $carry,$carry + + movq %xmm2,$nptr # restore $nptr + + mov %r8,8*0($tptr) # store top 512 bits + mov %r9,8*1($tptr) + movq %xmm3,$num # $num is %r9, can't be moved upwards + mov %r10,8*2($tptr) + mov %r11,8*3($tptr) + mov %r12,8*4($tptr) + mov %r13,8*5($tptr) + mov %r14,8*6($tptr) + mov %r15,8*7($tptr) + lea 8*8($tptr),$tptr + + cmp %rdx,$tptr # end of t[]? + jb .L8x_reduction_loop + ret +.size bn_sqr8x_internal,.-bn_sqr8x_internal +___ +} +############################################################## +# Post-condition, 4x unrolled +# +{ +my ($tptr,$nptr)=("%rbx","%rbp"); +$code.=<<___; +.type __bn_post4x_internal,\@abi-omnipotent +.align 32 +__bn_post4x_internal: + mov 8*0($nptr),%r12 + lea (%rdi,$num),$tptr # %rdi was $tptr above + mov $num,%rcx + movq %xmm1,$rptr # restore $rptr + neg %rax + movq %xmm1,$aptr # prepare for back-to-back call + sar \$3+2,%rcx + dec %r12 # so that after 'not' we get -n[0] + xor %r10,%r10 + mov 8*1($nptr),%r13 + mov 8*2($nptr),%r14 + mov 8*3($nptr),%r15 + jmp .Lsqr4x_sub_entry + +.align 16 +.Lsqr4x_sub: + mov 8*0($nptr),%r12 + mov 8*1($nptr),%r13 + mov 8*2($nptr),%r14 + mov 8*3($nptr),%r15 +.Lsqr4x_sub_entry: + lea 8*4($nptr),$nptr + not %r12 + not %r13 + not %r14 + not %r15 + and %rax,%r12 + and %rax,%r13 + and %rax,%r14 + and %rax,%r15 + + neg %r10 # mov %r10,%cf + adc 8*0($tptr),%r12 + adc 8*1($tptr),%r13 + adc 8*2($tptr),%r14 + adc 8*3($tptr),%r15 + mov %r12,8*0($rptr) + lea 8*4($tptr),$tptr + mov %r13,8*1($rptr) + sbb %r10,%r10 # mov %cf,%r10 + mov %r14,8*2($rptr) + mov %r15,8*3($rptr) + lea 8*4($rptr),$rptr + + inc %rcx # pass %cf + jnz .Lsqr4x_sub + + mov $num,%r10 # prepare for back-to-back call + neg $num # restore $num + ret +.size __bn_post4x_internal,.-__bn_post4x_internal +___ +} +{ +$code.=<<___; +.globl bn_from_montgomery +.type bn_from_montgomery,\@abi-omnipotent +.align 32 +bn_from_montgomery: + testl \$7,`($win64?"48(%rsp)":"%r9d")` + jz bn_from_mont8x + xor %eax,%eax + ret +.size bn_from_montgomery,.-bn_from_montgomery + +.type bn_from_mont8x,\@function,6 +.align 32 +bn_from_mont8x: +.cfi_startproc + .byte 0x67 + mov %rsp,%rax +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +.Lfrom_prologue: + + shl \$3,${num}d # convert $num to bytes + lea ($num,$num,2),%r10 # 3*$num in bytes + neg $num + mov ($n0),$n0 # *n0 + + ############################################################## + # Ensure that stack frame doesn't alias with $rptr+3*$num + # modulo 4096, which covers ret[num], am[num] and n[num] + # (see bn_exp.c). The stack is allocated to aligned with + # bn_power5's frame, and as bn_from_montgomery happens to be + # last operation, we use the opportunity to cleanse it. + # + lea -320(%rsp,$num,2),%r11 + mov %rsp,%rbp + sub $rptr,%r11 + and \$4095,%r11 + cmp %r11,%r10 + jb .Lfrom_sp_alt + sub %r11,%rbp # align with $aptr + lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*$num*8+256) + jmp .Lfrom_sp_done + +.align 32 +.Lfrom_sp_alt: + lea 4096-320(,$num,2),%r10 + lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*$num*8+256) + sub %r10,%r11 + mov \$0,%r10 + cmovc %r10,%r11 + sub %r11,%rbp +.Lfrom_sp_done: + and \$-64,%rbp + mov %rsp,%r11 + sub %rbp,%r11 + and \$-4096,%r11 + lea (%rbp,%r11),%rsp + mov (%rsp),%r10 + cmp %rbp,%rsp + ja .Lfrom_page_walk + jmp .Lfrom_page_walk_done + +.Lfrom_page_walk: + lea -4096(%rsp),%rsp + mov (%rsp),%r10 + cmp %rbp,%rsp + ja .Lfrom_page_walk +.Lfrom_page_walk_done: + + mov $num,%r10 + neg $num + + ############################################################## + # Stack layout + # + # +0 saved $num, used in reduction section + # +8 &t[2*$num], used in reduction section + # +32 saved *n0 + # +40 saved %rsp + # +48 t[2*$num] + # + mov $n0, 32(%rsp) + mov %rax, 40(%rsp) # save original %rsp +.cfi_cfa_expression %rsp+40,deref,+8 +.Lfrom_body: + mov $num,%r11 + lea 48(%rsp),%rax + pxor %xmm0,%xmm0 + jmp .Lmul_by_1 + +.align 32 +.Lmul_by_1: + movdqu ($aptr),%xmm1 + movdqu 16($aptr),%xmm2 + movdqu 32($aptr),%xmm3 + movdqa %xmm0,(%rax,$num) + movdqu 48($aptr),%xmm4 + movdqa %xmm0,16(%rax,$num) + .byte 0x48,0x8d,0xb6,0x40,0x00,0x00,0x00 # lea 64($aptr),$aptr + movdqa %xmm1,(%rax) + movdqa %xmm0,32(%rax,$num) + movdqa %xmm2,16(%rax) + movdqa %xmm0,48(%rax,$num) + movdqa %xmm3,32(%rax) + movdqa %xmm4,48(%rax) + lea 64(%rax),%rax + sub \$64,%r11 + jnz .Lmul_by_1 + + movq $rptr,%xmm1 + movq $nptr,%xmm2 + .byte 0x67 + mov $nptr,%rbp + movq %r10, %xmm3 # -num +___ +$code.=<<___ if ($addx); + mov OPENSSL_ia32cap_P+8(%rip),%r11d + and \$0x80108,%r11d + cmp \$0x80108,%r11d # check for AD*X+BMI2+BMI1 + jne .Lfrom_mont_nox + + lea (%rax,$num),$rptr + call __bn_sqrx8x_reduction + call __bn_postx4x_internal + + pxor %xmm0,%xmm0 + lea 48(%rsp),%rax + jmp .Lfrom_mont_zero + +.align 32 +.Lfrom_mont_nox: +___ +$code.=<<___; + call __bn_sqr8x_reduction + call __bn_post4x_internal + + pxor %xmm0,%xmm0 + lea 48(%rsp),%rax + jmp .Lfrom_mont_zero + +.align 32 +.Lfrom_mont_zero: + mov 40(%rsp),%rsi # restore %rsp +.cfi_def_cfa %rsi,8 + movdqa %xmm0,16*0(%rax) + movdqa %xmm0,16*1(%rax) + movdqa %xmm0,16*2(%rax) + movdqa %xmm0,16*3(%rax) + lea 16*4(%rax),%rax + sub \$32,$num + jnz .Lfrom_mont_zero + + mov \$1,%rax + mov -48(%rsi),%r15 +.cfi_restore %r15 + mov -40(%rsi),%r14 +.cfi_restore %r14 + mov -32(%rsi),%r13 +.cfi_restore %r13 + mov -24(%rsi),%r12 +.cfi_restore %r12 + mov -16(%rsi),%rbp +.cfi_restore %rbp + mov -8(%rsi),%rbx +.cfi_restore %rbx + lea (%rsi),%rsp +.cfi_def_cfa_register %rsp +.Lfrom_epilogue: + ret +.cfi_endproc +.size bn_from_mont8x,.-bn_from_mont8x +___ +} +}}} + +if ($addx) {{{ +my $bp="%rdx"; # restore original value + +$code.=<<___; +.type bn_mulx4x_mont_gather5,\@function,6 +.align 32 +bn_mulx4x_mont_gather5: +.cfi_startproc + mov %rsp,%rax +.cfi_def_cfa_register %rax +.Lmulx4x_enter: + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +.Lmulx4x_prologue: + + shl \$3,${num}d # convert $num to bytes + lea ($num,$num,2),%r10 # 3*$num in bytes + neg $num # -$num + mov ($n0),$n0 # *n0 + + ############################################################## + # Ensure that stack frame doesn't alias with $rptr+3*$num + # modulo 4096, which covers ret[num], am[num] and n[num] + # (see bn_exp.c). This is done to allow memory disambiguation + # logic do its magic. [Extra [num] is allocated in order + # to align with bn_power5's frame, which is cleansed after + # completing exponentiation. Extra 256 bytes is for power mask + # calculated from 7th argument, the index.] + # + lea -320(%rsp,$num,2),%r11 + mov %rsp,%rbp + sub $rp,%r11 + and \$4095,%r11 + cmp %r11,%r10 + jb .Lmulx4xsp_alt + sub %r11,%rbp # align with $aptr + lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*$num*8+256) + jmp .Lmulx4xsp_done + +.Lmulx4xsp_alt: + lea 4096-320(,$num,2),%r10 + lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*$num*8+256) + sub %r10,%r11 + mov \$0,%r10 + cmovc %r10,%r11 + sub %r11,%rbp +.Lmulx4xsp_done: + and \$-64,%rbp # ensure alignment + mov %rsp,%r11 + sub %rbp,%r11 + and \$-4096,%r11 + lea (%rbp,%r11),%rsp + mov (%rsp),%r10 + cmp %rbp,%rsp + ja .Lmulx4x_page_walk + jmp .Lmulx4x_page_walk_done + +.Lmulx4x_page_walk: + lea -4096(%rsp),%rsp + mov (%rsp),%r10 + cmp %rbp,%rsp + ja .Lmulx4x_page_walk +.Lmulx4x_page_walk_done: + + ############################################################## + # Stack layout + # +0 -num + # +8 off-loaded &b[i] + # +16 end of b[num] + # +24 inner counter + # +32 saved n0 + # +40 saved %rsp + # +48 + # +56 saved rp + # +64 tmp[num+1] + # + mov $n0, 32(%rsp) # save *n0 + mov %rax,40(%rsp) # save original %rsp +.cfi_cfa_expression %rsp+40,deref,+8 +.Lmulx4x_body: + call mulx4x_internal + + mov 40(%rsp),%rsi # restore %rsp +.cfi_def_cfa %rsi,8 + mov \$1,%rax + + mov -48(%rsi),%r15 +.cfi_restore %r15 + mov -40(%rsi),%r14 +.cfi_restore %r14 + mov -32(%rsi),%r13 +.cfi_restore %r13 + mov -24(%rsi),%r12 +.cfi_restore %r12 + mov -16(%rsi),%rbp +.cfi_restore %rbp + mov -8(%rsi),%rbx +.cfi_restore %rbx + lea (%rsi),%rsp +.cfi_def_cfa_register %rsp +.Lmulx4x_epilogue: + ret +.cfi_endproc +.size bn_mulx4x_mont_gather5,.-bn_mulx4x_mont_gather5 + +.type mulx4x_internal,\@abi-omnipotent +.align 32 +mulx4x_internal: + mov $num,8(%rsp) # save -$num (it was in bytes) + mov $num,%r10 + neg $num # restore $num + shl \$5,$num + neg %r10 # restore $num + lea 128($bp,$num),%r13 # end of powers table (+size optimization) + shr \$5+5,$num + movd `($win64?56:8)`(%rax),%xmm5 # load 7th argument + sub \$1,$num + lea .Linc(%rip),%rax + mov %r13,16+8(%rsp) # end of b[num] + mov $num,24+8(%rsp) # inner counter + mov $rp, 56+8(%rsp) # save $rp +___ +my ($aptr, $bptr, $nptr, $tptr, $mi, $bi, $zero, $num)= + ("%rsi","%rdi","%rcx","%rbx","%r8","%r9","%rbp","%rax"); +my $rptr=$bptr; +my $STRIDE=2**5*8; # 5 is "window size" +my $N=$STRIDE/4; # should match cache line size +$code.=<<___; + movdqa 0(%rax),%xmm0 # 00000001000000010000000000000000 + movdqa 16(%rax),%xmm1 # 00000002000000020000000200000002 + lea 88-112(%rsp,%r10),%r10 # place the mask after tp[num+1] (+ICache optimization) + lea 128($bp),$bptr # size optimization + + pshufd \$0,%xmm5,%xmm5 # broadcast index + movdqa %xmm1,%xmm4 + .byte 0x67 + movdqa %xmm1,%xmm2 +___ +######################################################################## +# calculate mask by comparing 0..31 to index and save result to stack +# +$code.=<<___; + .byte 0x67 + paddd %xmm0,%xmm1 + pcmpeqd %xmm5,%xmm0 # compare to 1,0 + movdqa %xmm4,%xmm3 +___ +for($i=0;$i<$STRIDE/16-4;$i+=4) { +$code.=<<___; + paddd %xmm1,%xmm2 + pcmpeqd %xmm5,%xmm1 # compare to 3,2 + movdqa %xmm0,`16*($i+0)+112`(%r10) + movdqa %xmm4,%xmm0 + + paddd %xmm2,%xmm3 + pcmpeqd %xmm5,%xmm2 # compare to 5,4 + movdqa %xmm1,`16*($i+1)+112`(%r10) + movdqa %xmm4,%xmm1 + + paddd %xmm3,%xmm0 + pcmpeqd %xmm5,%xmm3 # compare to 7,6 + movdqa %xmm2,`16*($i+2)+112`(%r10) + movdqa %xmm4,%xmm2 + + paddd %xmm0,%xmm1 + pcmpeqd %xmm5,%xmm0 + movdqa %xmm3,`16*($i+3)+112`(%r10) + movdqa %xmm4,%xmm3 +___ +} +$code.=<<___; # last iteration can be optimized + .byte 0x67 + paddd %xmm1,%xmm2 + pcmpeqd %xmm5,%xmm1 + movdqa %xmm0,`16*($i+0)+112`(%r10) + + paddd %xmm2,%xmm3 + pcmpeqd %xmm5,%xmm2 + movdqa %xmm1,`16*($i+1)+112`(%r10) + + pcmpeqd %xmm5,%xmm3 + movdqa %xmm2,`16*($i+2)+112`(%r10) + + pand `16*($i+0)-128`($bptr),%xmm0 # while it's still in register + pand `16*($i+1)-128`($bptr),%xmm1 + pand `16*($i+2)-128`($bptr),%xmm2 + movdqa %xmm3,`16*($i+3)+112`(%r10) + pand `16*($i+3)-128`($bptr),%xmm3 + por %xmm2,%xmm0 + por %xmm3,%xmm1 +___ +for($i=0;$i<$STRIDE/16-4;$i+=4) { +$code.=<<___; + movdqa `16*($i+0)-128`($bptr),%xmm4 + movdqa `16*($i+1)-128`($bptr),%xmm5 + movdqa `16*($i+2)-128`($bptr),%xmm2 + pand `16*($i+0)+112`(%r10),%xmm4 + movdqa `16*($i+3)-128`($bptr),%xmm3 + pand `16*($i+1)+112`(%r10),%xmm5 + por %xmm4,%xmm0 + pand `16*($i+2)+112`(%r10),%xmm2 + por %xmm5,%xmm1 + pand `16*($i+3)+112`(%r10),%xmm3 + por %xmm2,%xmm0 + por %xmm3,%xmm1 +___ +} +$code.=<<___; + pxor %xmm1,%xmm0 + pshufd \$0x4e,%xmm0,%xmm1 + por %xmm1,%xmm0 + lea $STRIDE($bptr),$bptr + movq %xmm0,%rdx # bp[0] + lea 64+8*4+8(%rsp),$tptr + + mov %rdx,$bi + mulx 0*8($aptr),$mi,%rax # a[0]*b[0] + mulx 1*8($aptr),%r11,%r12 # a[1]*b[0] + add %rax,%r11 + mulx 2*8($aptr),%rax,%r13 # ... + adc %rax,%r12 + adc \$0,%r13 + mulx 3*8($aptr),%rax,%r14 + + mov $mi,%r15 + imulq 32+8(%rsp),$mi # "t[0]"*n0 + xor $zero,$zero # cf=0, of=0 + mov $mi,%rdx + + mov $bptr,8+8(%rsp) # off-load &b[i] + + lea 4*8($aptr),$aptr + adcx %rax,%r13 + adcx $zero,%r14 # cf=0 + + mulx 0*8($nptr),%rax,%r10 + adcx %rax,%r15 # discarded + adox %r11,%r10 + mulx 1*8($nptr),%rax,%r11 + adcx %rax,%r10 + adox %r12,%r11 + mulx 2*8($nptr),%rax,%r12 + mov 24+8(%rsp),$bptr # counter value + mov %r10,-8*4($tptr) + adcx %rax,%r11 + adox %r13,%r12 + mulx 3*8($nptr),%rax,%r15 + mov $bi,%rdx + mov %r11,-8*3($tptr) + adcx %rax,%r12 + adox $zero,%r15 # of=0 + lea 4*8($nptr),$nptr + mov %r12,-8*2($tptr) + jmp .Lmulx4x_1st + +.align 32 +.Lmulx4x_1st: + adcx $zero,%r15 # cf=0, modulo-scheduled + mulx 0*8($aptr),%r10,%rax # a[4]*b[0] + adcx %r14,%r10 + mulx 1*8($aptr),%r11,%r14 # a[5]*b[0] + adcx %rax,%r11 + mulx 2*8($aptr),%r12,%rax # ... + adcx %r14,%r12 + mulx 3*8($aptr),%r13,%r14 + .byte 0x67,0x67 + mov $mi,%rdx + adcx %rax,%r13 + adcx $zero,%r14 # cf=0 + lea 4*8($aptr),$aptr + lea 4*8($tptr),$tptr + + adox %r15,%r10 + mulx 0*8($nptr),%rax,%r15 + adcx %rax,%r10 + adox %r15,%r11 + mulx 1*8($nptr),%rax,%r15 + adcx %rax,%r11 + adox %r15,%r12 + mulx 2*8($nptr),%rax,%r15 + mov %r10,-5*8($tptr) + adcx %rax,%r12 + mov %r11,-4*8($tptr) + adox %r15,%r13 + mulx 3*8($nptr),%rax,%r15 + mov $bi,%rdx + mov %r12,-3*8($tptr) + adcx %rax,%r13 + adox $zero,%r15 + lea 4*8($nptr),$nptr + mov %r13,-2*8($tptr) + + dec $bptr # of=0, pass cf + jnz .Lmulx4x_1st + + mov 8(%rsp),$num # load -num + adc $zero,%r15 # modulo-scheduled + lea ($aptr,$num),$aptr # rewind $aptr + add %r15,%r14 + mov 8+8(%rsp),$bptr # re-load &b[i] + adc $zero,$zero # top-most carry + mov %r14,-1*8($tptr) + jmp .Lmulx4x_outer + +.align 32 +.Lmulx4x_outer: + lea 16-256($tptr),%r10 # where 256-byte mask is (+density control) + pxor %xmm4,%xmm4 + .byte 0x67,0x67 + pxor %xmm5,%xmm5 +___ +for($i=0;$i<$STRIDE/16;$i+=4) { +$code.=<<___; + movdqa `16*($i+0)-128`($bptr),%xmm0 + movdqa `16*($i+1)-128`($bptr),%xmm1 + movdqa `16*($i+2)-128`($bptr),%xmm2 + pand `16*($i+0)+256`(%r10),%xmm0 + movdqa `16*($i+3)-128`($bptr),%xmm3 + pand `16*($i+1)+256`(%r10),%xmm1 + por %xmm0,%xmm4 + pand `16*($i+2)+256`(%r10),%xmm2 + por %xmm1,%xmm5 + pand `16*($i+3)+256`(%r10),%xmm3 + por %xmm2,%xmm4 + por %xmm3,%xmm5 +___ +} +$code.=<<___; + por %xmm5,%xmm4 + pshufd \$0x4e,%xmm4,%xmm0 + por %xmm4,%xmm0 + lea $STRIDE($bptr),$bptr + movq %xmm0,%rdx # m0=bp[i] + + mov $zero,($tptr) # save top-most carry + lea 4*8($tptr,$num),$tptr # rewind $tptr + mulx 0*8($aptr),$mi,%r11 # a[0]*b[i] + xor $zero,$zero # cf=0, of=0 + mov %rdx,$bi + mulx 1*8($aptr),%r14,%r12 # a[1]*b[i] + adox -4*8($tptr),$mi # +t[0] + adcx %r14,%r11 + mulx 2*8($aptr),%r15,%r13 # ... + adox -3*8($tptr),%r11 + adcx %r15,%r12 + mulx 3*8($aptr),%rdx,%r14 + adox -2*8($tptr),%r12 + adcx %rdx,%r13 + lea ($nptr,$num),$nptr # rewind $nptr + lea 4*8($aptr),$aptr + adox -1*8($tptr),%r13 + adcx $zero,%r14 + adox $zero,%r14 + + mov $mi,%r15 + imulq 32+8(%rsp),$mi # "t[0]"*n0 + + mov $mi,%rdx + xor $zero,$zero # cf=0, of=0 + mov $bptr,8+8(%rsp) # off-load &b[i] + + mulx 0*8($nptr),%rax,%r10 + adcx %rax,%r15 # discarded + adox %r11,%r10 + mulx 1*8($nptr),%rax,%r11 + adcx %rax,%r10 + adox %r12,%r11 + mulx 2*8($nptr),%rax,%r12 + adcx %rax,%r11 + adox %r13,%r12 + mulx 3*8($nptr),%rax,%r15 + mov $bi,%rdx + mov 24+8(%rsp),$bptr # counter value + mov %r10,-8*4($tptr) + adcx %rax,%r12 + mov %r11,-8*3($tptr) + adox $zero,%r15 # of=0 + mov %r12,-8*2($tptr) + lea 4*8($nptr),$nptr + jmp .Lmulx4x_inner + +.align 32 +.Lmulx4x_inner: + mulx 0*8($aptr),%r10,%rax # a[4]*b[i] + adcx $zero,%r15 # cf=0, modulo-scheduled + adox %r14,%r10 + mulx 1*8($aptr),%r11,%r14 # a[5]*b[i] + adcx 0*8($tptr),%r10 + adox %rax,%r11 + mulx 2*8($aptr),%r12,%rax # ... + adcx 1*8($tptr),%r11 + adox %r14,%r12 + mulx 3*8($aptr),%r13,%r14 + mov $mi,%rdx + adcx 2*8($tptr),%r12 + adox %rax,%r13 + adcx 3*8($tptr),%r13 + adox $zero,%r14 # of=0 + lea 4*8($aptr),$aptr + lea 4*8($tptr),$tptr + adcx $zero,%r14 # cf=0 + + adox %r15,%r10 + mulx 0*8($nptr),%rax,%r15 + adcx %rax,%r10 + adox %r15,%r11 + mulx 1*8($nptr),%rax,%r15 + adcx %rax,%r11 + adox %r15,%r12 + mulx 2*8($nptr),%rax,%r15 + mov %r10,-5*8($tptr) + adcx %rax,%r12 + adox %r15,%r13 + mov %r11,-4*8($tptr) + mulx 3*8($nptr),%rax,%r15 + mov $bi,%rdx + lea 4*8($nptr),$nptr + mov %r12,-3*8($tptr) + adcx %rax,%r13 + adox $zero,%r15 + mov %r13,-2*8($tptr) + + dec $bptr # of=0, pass cf + jnz .Lmulx4x_inner + + mov 0+8(%rsp),$num # load -num + adc $zero,%r15 # modulo-scheduled + sub 0*8($tptr),$bptr # pull top-most carry to %cf + mov 8+8(%rsp),$bptr # re-load &b[i] + mov 16+8(%rsp),%r10 + adc %r15,%r14 + lea ($aptr,$num),$aptr # rewind $aptr + adc $zero,$zero # top-most carry + mov %r14,-1*8($tptr) + + cmp %r10,$bptr + jb .Lmulx4x_outer + + mov -8($nptr),%r10 + mov $zero,%r8 + mov ($nptr,$num),%r12 + lea ($nptr,$num),%rbp # rewind $nptr + mov $num,%rcx + lea ($tptr,$num),%rdi # rewind $tptr + xor %eax,%eax + xor %r15,%r15 + sub %r14,%r10 # compare top-most words + adc %r15,%r15 + or %r15,%r8 + sar \$3+2,%rcx + sub %r8,%rax # %rax=-%r8 + mov 56+8(%rsp),%rdx # restore rp + dec %r12 # so that after 'not' we get -n[0] + mov 8*1(%rbp),%r13 + xor %r8,%r8 + mov 8*2(%rbp),%r14 + mov 8*3(%rbp),%r15 + jmp .Lsqrx4x_sub_entry # common post-condition +.size mulx4x_internal,.-mulx4x_internal +___ +} { +###################################################################### +# void bn_power5( +my $rptr="%rdi"; # BN_ULONG *rptr, +my $aptr="%rsi"; # const BN_ULONG *aptr, +my $bptr="%rdx"; # const void *table, +my $nptr="%rcx"; # const BN_ULONG *nptr, +my $n0 ="%r8"; # const BN_ULONG *n0); +my $num ="%r9"; # int num, has to be divisible by 8 + # int pwr); + +my ($i,$j,$tptr)=("%rbp","%rcx",$rptr); +my @A0=("%r10","%r11"); +my @A1=("%r12","%r13"); +my ($a0,$a1,$ai)=("%r14","%r15","%rbx"); + +$code.=<<___; +.type bn_powerx5,\@function,6 +.align 32 +bn_powerx5: +.cfi_startproc + mov %rsp,%rax +.cfi_def_cfa_register %rax +.Lpowerx5_enter: + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +.Lpowerx5_prologue: + + shl \$3,${num}d # convert $num to bytes + lea ($num,$num,2),%r10 # 3*$num in bytes + neg $num + mov ($n0),$n0 # *n0 + + ############################################################## + # Ensure that stack frame doesn't alias with $rptr+3*$num + # modulo 4096, which covers ret[num], am[num] and n[num] + # (see bn_exp.c). This is done to allow memory disambiguation + # logic do its magic. [Extra 256 bytes is for power mask + # calculated from 7th argument, the index.] + # + lea -320(%rsp,$num,2),%r11 + mov %rsp,%rbp + sub $rptr,%r11 + and \$4095,%r11 + cmp %r11,%r10 + jb .Lpwrx_sp_alt + sub %r11,%rbp # align with $aptr + lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*$num*8+256) + jmp .Lpwrx_sp_done + +.align 32 +.Lpwrx_sp_alt: + lea 4096-320(,$num,2),%r10 + lea -320(%rbp,$num,2),%rbp # alloca(frame+2*$num*8+256) + sub %r10,%r11 + mov \$0,%r10 + cmovc %r10,%r11 + sub %r11,%rbp +.Lpwrx_sp_done: + and \$-64,%rbp + mov %rsp,%r11 + sub %rbp,%r11 + and \$-4096,%r11 + lea (%rbp,%r11),%rsp + mov (%rsp),%r10 + cmp %rbp,%rsp + ja .Lpwrx_page_walk + jmp .Lpwrx_page_walk_done + +.Lpwrx_page_walk: + lea -4096(%rsp),%rsp + mov (%rsp),%r10 + cmp %rbp,%rsp + ja .Lpwrx_page_walk +.Lpwrx_page_walk_done: + + mov $num,%r10 + neg $num + + ############################################################## + # Stack layout + # + # +0 saved $num, used in reduction section + # +8 &t[2*$num], used in reduction section + # +16 intermediate carry bit + # +24 top-most carry bit, used in reduction section + # +32 saved *n0 + # +40 saved %rsp + # +48 t[2*$num] + # + pxor %xmm0,%xmm0 + movq $rptr,%xmm1 # save $rptr + movq $nptr,%xmm2 # save $nptr + movq %r10, %xmm3 # -$num + movq $bptr,%xmm4 + mov $n0, 32(%rsp) + mov %rax, 40(%rsp) # save original %rsp +.cfi_cfa_expression %rsp+40,deref,+8 +.Lpowerx5_body: + + call __bn_sqrx8x_internal + call __bn_postx4x_internal + call __bn_sqrx8x_internal + call __bn_postx4x_internal + call __bn_sqrx8x_internal + call __bn_postx4x_internal + call __bn_sqrx8x_internal + call __bn_postx4x_internal + call __bn_sqrx8x_internal + call __bn_postx4x_internal + + mov %r10,$num # -num + mov $aptr,$rptr + movq %xmm2,$nptr + movq %xmm4,$bptr + mov 40(%rsp),%rax + + call mulx4x_internal + + mov 40(%rsp),%rsi # restore %rsp +.cfi_def_cfa %rsi,8 + mov \$1,%rax + + mov -48(%rsi),%r15 +.cfi_restore %r15 + mov -40(%rsi),%r14 +.cfi_restore %r14 + mov -32(%rsi),%r13 +.cfi_restore %r13 + mov -24(%rsi),%r12 +.cfi_restore %r12 + mov -16(%rsi),%rbp +.cfi_restore %rbp + mov -8(%rsi),%rbx +.cfi_restore %rbx + lea (%rsi),%rsp +.cfi_def_cfa_register %rsp +.Lpowerx5_epilogue: + ret +.cfi_endproc +.size bn_powerx5,.-bn_powerx5 + +.globl bn_sqrx8x_internal +.hidden bn_sqrx8x_internal +.type bn_sqrx8x_internal,\@abi-omnipotent +.align 32 +bn_sqrx8x_internal: +__bn_sqrx8x_internal: +.cfi_startproc + ################################################################## + # Squaring part: + # + # a) multiply-n-add everything but a[i]*a[i]; + # b) shift result of a) by 1 to the left and accumulate + # a[i]*a[i] products; + # + ################################################################## + # a[7]a[7]a[6]a[6]a[5]a[5]a[4]a[4]a[3]a[3]a[2]a[2]a[1]a[1]a[0]a[0] + # a[1]a[0] + # a[2]a[0] + # a[3]a[0] + # a[2]a[1] + # a[3]a[1] + # a[3]a[2] + # + # a[4]a[0] + # a[5]a[0] + # a[6]a[0] + # a[7]a[0] + # a[4]a[1] + # a[5]a[1] + # a[6]a[1] + # a[7]a[1] + # a[4]a[2] + # a[5]a[2] + # a[6]a[2] + # a[7]a[2] + # a[4]a[3] + # a[5]a[3] + # a[6]a[3] + # a[7]a[3] + # + # a[5]a[4] + # a[6]a[4] + # a[7]a[4] + # a[6]a[5] + # a[7]a[5] + # a[7]a[6] + # a[7]a[7]a[6]a[6]a[5]a[5]a[4]a[4]a[3]a[3]a[2]a[2]a[1]a[1]a[0]a[0] +___ +{ +my ($zero,$carry)=("%rbp","%rcx"); +my $aaptr=$zero; +$code.=<<___; + lea 48+8(%rsp),$tptr + lea ($aptr,$num),$aaptr + mov $num,0+8(%rsp) # save $num + mov $aaptr,8+8(%rsp) # save end of $aptr + jmp .Lsqr8x_zero_start + +.align 32 +.byte 0x66,0x66,0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00 +.Lsqrx8x_zero: + .byte 0x3e + movdqa %xmm0,0*8($tptr) + movdqa %xmm0,2*8($tptr) + movdqa %xmm0,4*8($tptr) + movdqa %xmm0,6*8($tptr) +.Lsqr8x_zero_start: # aligned at 32 + movdqa %xmm0,8*8($tptr) + movdqa %xmm0,10*8($tptr) + movdqa %xmm0,12*8($tptr) + movdqa %xmm0,14*8($tptr) + lea 16*8($tptr),$tptr + sub \$64,$num + jnz .Lsqrx8x_zero + + mov 0*8($aptr),%rdx # a[0], modulo-scheduled + #xor %r9,%r9 # t[1], ex-$num, zero already + xor %r10,%r10 + xor %r11,%r11 + xor %r12,%r12 + xor %r13,%r13 + xor %r14,%r14 + xor %r15,%r15 + lea 48+8(%rsp),$tptr + xor $zero,$zero # cf=0, cf=0 + jmp .Lsqrx8x_outer_loop + +.align 32 +.Lsqrx8x_outer_loop: + mulx 1*8($aptr),%r8,%rax # a[1]*a[0] + adcx %r9,%r8 # a[1]*a[0]+=t[1] + adox %rax,%r10 + mulx 2*8($aptr),%r9,%rax # a[2]*a[0] + adcx %r10,%r9 + adox %rax,%r11 + .byte 0xc4,0xe2,0xab,0xf6,0x86,0x18,0x00,0x00,0x00 # mulx 3*8($aptr),%r10,%rax # ... + adcx %r11,%r10 + adox %rax,%r12 + .byte 0xc4,0xe2,0xa3,0xf6,0x86,0x20,0x00,0x00,0x00 # mulx 4*8($aptr),%r11,%rax + adcx %r12,%r11 + adox %rax,%r13 + mulx 5*8($aptr),%r12,%rax + adcx %r13,%r12 + adox %rax,%r14 + mulx 6*8($aptr),%r13,%rax + adcx %r14,%r13 + adox %r15,%rax + mulx 7*8($aptr),%r14,%r15 + mov 1*8($aptr),%rdx # a[1] + adcx %rax,%r14 + adox $zero,%r15 + adc 8*8($tptr),%r15 + mov %r8,1*8($tptr) # t[1] + mov %r9,2*8($tptr) # t[2] + sbb $carry,$carry # mov %cf,$carry + xor $zero,$zero # cf=0, of=0 + + + mulx 2*8($aptr),%r8,%rbx # a[2]*a[1] + mulx 3*8($aptr),%r9,%rax # a[3]*a[1] + adcx %r10,%r8 + adox %rbx,%r9 + mulx 4*8($aptr),%r10,%rbx # ... + adcx %r11,%r9 + adox %rax,%r10 + .byte 0xc4,0xe2,0xa3,0xf6,0x86,0x28,0x00,0x00,0x00 # mulx 5*8($aptr),%r11,%rax + adcx %r12,%r10 + adox %rbx,%r11 + .byte 0xc4,0xe2,0x9b,0xf6,0x9e,0x30,0x00,0x00,0x00 # mulx 6*8($aptr),%r12,%rbx + adcx %r13,%r11 + adox %r14,%r12 + .byte 0xc4,0x62,0x93,0xf6,0xb6,0x38,0x00,0x00,0x00 # mulx 7*8($aptr),%r13,%r14 + mov 2*8($aptr),%rdx # a[2] + adcx %rax,%r12 + adox %rbx,%r13 + adcx %r15,%r13 + adox $zero,%r14 # of=0 + adcx $zero,%r14 # cf=0 + + mov %r8,3*8($tptr) # t[3] + mov %r9,4*8($tptr) # t[4] + + mulx 3*8($aptr),%r8,%rbx # a[3]*a[2] + mulx 4*8($aptr),%r9,%rax # a[4]*a[2] + adcx %r10,%r8 + adox %rbx,%r9 + mulx 5*8($aptr),%r10,%rbx # ... + adcx %r11,%r9 + adox %rax,%r10 + .byte 0xc4,0xe2,0xa3,0xf6,0x86,0x30,0x00,0x00,0x00 # mulx 6*8($aptr),%r11,%rax + adcx %r12,%r10 + adox %r13,%r11 + .byte 0xc4,0x62,0x9b,0xf6,0xae,0x38,0x00,0x00,0x00 # mulx 7*8($aptr),%r12,%r13 + .byte 0x3e + mov 3*8($aptr),%rdx # a[3] + adcx %rbx,%r11 + adox %rax,%r12 + adcx %r14,%r12 + mov %r8,5*8($tptr) # t[5] + mov %r9,6*8($tptr) # t[6] + mulx 4*8($aptr),%r8,%rax # a[4]*a[3] + adox $zero,%r13 # of=0 + adcx $zero,%r13 # cf=0 + + mulx 5*8($aptr),%r9,%rbx # a[5]*a[3] + adcx %r10,%r8 + adox %rax,%r9 + mulx 6*8($aptr),%r10,%rax # ... + adcx %r11,%r9 + adox %r12,%r10 + mulx 7*8($aptr),%r11,%r12 + mov 4*8($aptr),%rdx # a[4] + mov 5*8($aptr),%r14 # a[5] + adcx %rbx,%r10 + adox %rax,%r11 + mov 6*8($aptr),%r15 # a[6] + adcx %r13,%r11 + adox $zero,%r12 # of=0 + adcx $zero,%r12 # cf=0 + + mov %r8,7*8($tptr) # t[7] + mov %r9,8*8($tptr) # t[8] + + mulx %r14,%r9,%rax # a[5]*a[4] + mov 7*8($aptr),%r8 # a[7] + adcx %r10,%r9 + mulx %r15,%r10,%rbx # a[6]*a[4] + adox %rax,%r10 + adcx %r11,%r10 + mulx %r8,%r11,%rax # a[7]*a[4] + mov %r14,%rdx # a[5] + adox %rbx,%r11 + adcx %r12,%r11 + #adox $zero,%rax # of=0 + adcx $zero,%rax # cf=0 + + mulx %r15,%r14,%rbx # a[6]*a[5] + mulx %r8,%r12,%r13 # a[7]*a[5] + mov %r15,%rdx # a[6] + lea 8*8($aptr),$aptr + adcx %r14,%r11 + adox %rbx,%r12 + adcx %rax,%r12 + adox $zero,%r13 + + .byte 0x67,0x67 + mulx %r8,%r8,%r14 # a[7]*a[6] + adcx %r8,%r13 + adcx $zero,%r14 + + cmp 8+8(%rsp),$aptr + je .Lsqrx8x_outer_break + + neg $carry # mov $carry,%cf + mov \$-8,%rcx + mov $zero,%r15 + mov 8*8($tptr),%r8 + adcx 9*8($tptr),%r9 # +=t[9] + adcx 10*8($tptr),%r10 # ... + adcx 11*8($tptr),%r11 + adc 12*8($tptr),%r12 + adc 13*8($tptr),%r13 + adc 14*8($tptr),%r14 + adc 15*8($tptr),%r15 + lea ($aptr),$aaptr + lea 2*64($tptr),$tptr + sbb %rax,%rax # mov %cf,$carry + + mov -64($aptr),%rdx # a[0] + mov %rax,16+8(%rsp) # offload $carry + mov $tptr,24+8(%rsp) + + #lea 8*8($tptr),$tptr # see 2*8*8($tptr) above + xor %eax,%eax # cf=0, of=0 + jmp .Lsqrx8x_loop + +.align 32 +.Lsqrx8x_loop: + mov %r8,%rbx + mulx 0*8($aaptr),%rax,%r8 # a[8]*a[i] + adcx %rax,%rbx # +=t[8] + adox %r9,%r8 + + mulx 1*8($aaptr),%rax,%r9 # ... + adcx %rax,%r8 + adox %r10,%r9 + + mulx 2*8($aaptr),%rax,%r10 + adcx %rax,%r9 + adox %r11,%r10 + + mulx 3*8($aaptr),%rax,%r11 + adcx %rax,%r10 + adox %r12,%r11 + + .byte 0xc4,0x62,0xfb,0xf6,0xa5,0x20,0x00,0x00,0x00 # mulx 4*8($aaptr),%rax,%r12 + adcx %rax,%r11 + adox %r13,%r12 + + mulx 5*8($aaptr),%rax,%r13 + adcx %rax,%r12 + adox %r14,%r13 + + mulx 6*8($aaptr),%rax,%r14 + mov %rbx,($tptr,%rcx,8) # store t[8+i] + mov \$0,%ebx + adcx %rax,%r13 + adox %r15,%r14 + + .byte 0xc4,0x62,0xfb,0xf6,0xbd,0x38,0x00,0x00,0x00 # mulx 7*8($aaptr),%rax,%r15 + mov 8($aptr,%rcx,8),%rdx # a[i] + adcx %rax,%r14 + adox %rbx,%r15 # %rbx is 0, of=0 + adcx %rbx,%r15 # cf=0 + + .byte 0x67 + inc %rcx # of=0 + jnz .Lsqrx8x_loop + + lea 8*8($aaptr),$aaptr + mov \$-8,%rcx + cmp 8+8(%rsp),$aaptr # done? + je .Lsqrx8x_break + + sub 16+8(%rsp),%rbx # mov 16(%rsp),%cf + .byte 0x66 + mov -64($aptr),%rdx + adcx 0*8($tptr),%r8 + adcx 1*8($tptr),%r9 + adc 2*8($tptr),%r10 + adc 3*8($tptr),%r11 + adc 4*8($tptr),%r12 + adc 5*8($tptr),%r13 + adc 6*8($tptr),%r14 + adc 7*8($tptr),%r15 + lea 8*8($tptr),$tptr + .byte 0x67 + sbb %rax,%rax # mov %cf,%rax + xor %ebx,%ebx # cf=0, of=0 + mov %rax,16+8(%rsp) # offload carry + jmp .Lsqrx8x_loop + +.align 32 +.Lsqrx8x_break: + xor $zero,$zero + sub 16+8(%rsp),%rbx # mov 16(%rsp),%cf + adcx $zero,%r8 + mov 24+8(%rsp),$carry # initial $tptr, borrow $carry + adcx $zero,%r9 + mov 0*8($aptr),%rdx # a[8], modulo-scheduled + adc \$0,%r10 + mov %r8,0*8($tptr) + adc \$0,%r11 + adc \$0,%r12 + adc \$0,%r13 + adc \$0,%r14 + adc \$0,%r15 + cmp $carry,$tptr # cf=0, of=0 + je .Lsqrx8x_outer_loop + + mov %r9,1*8($tptr) + mov 1*8($carry),%r9 + mov %r10,2*8($tptr) + mov 2*8($carry),%r10 + mov %r11,3*8($tptr) + mov 3*8($carry),%r11 + mov %r12,4*8($tptr) + mov 4*8($carry),%r12 + mov %r13,5*8($tptr) + mov 5*8($carry),%r13 + mov %r14,6*8($tptr) + mov 6*8($carry),%r14 + mov %r15,7*8($tptr) + mov 7*8($carry),%r15 + mov $carry,$tptr + jmp .Lsqrx8x_outer_loop + +.align 32 +.Lsqrx8x_outer_break: + mov %r9,9*8($tptr) # t[9] + movq %xmm3,%rcx # -$num + mov %r10,10*8($tptr) # ... + mov %r11,11*8($tptr) + mov %r12,12*8($tptr) + mov %r13,13*8($tptr) + mov %r14,14*8($tptr) +___ +} { +my $i="%rcx"; +$code.=<<___; + lea 48+8(%rsp),$tptr + mov ($aptr,$i),%rdx # a[0] + + mov 8($tptr),$A0[1] # t[1] + xor $A0[0],$A0[0] # t[0], of=0, cf=0 + mov 0+8(%rsp),$num # restore $num + adox $A0[1],$A0[1] + mov 16($tptr),$A1[0] # t[2] # prefetch + mov 24($tptr),$A1[1] # t[3] # prefetch + #jmp .Lsqrx4x_shift_n_add # happens to be aligned + +.align 32 +.Lsqrx4x_shift_n_add: + mulx %rdx,%rax,%rbx + adox $A1[0],$A1[0] + adcx $A0[0],%rax + .byte 0x48,0x8b,0x94,0x0e,0x08,0x00,0x00,0x00 # mov 8($aptr,$i),%rdx # a[i+1] # prefetch + .byte 0x4c,0x8b,0x97,0x20,0x00,0x00,0x00 # mov 32($tptr),$A0[0] # t[2*i+4] # prefetch + adox $A1[1],$A1[1] + adcx $A0[1],%rbx + mov 40($tptr),$A0[1] # t[2*i+4+1] # prefetch + mov %rax,0($tptr) + mov %rbx,8($tptr) + + mulx %rdx,%rax,%rbx + adox $A0[0],$A0[0] + adcx $A1[0],%rax + mov 16($aptr,$i),%rdx # a[i+2] # prefetch + mov 48($tptr),$A1[0] # t[2*i+6] # prefetch + adox $A0[1],$A0[1] + adcx $A1[1],%rbx + mov 56($tptr),$A1[1] # t[2*i+6+1] # prefetch + mov %rax,16($tptr) + mov %rbx,24($tptr) + + mulx %rdx,%rax,%rbx + adox $A1[0],$A1[0] + adcx $A0[0],%rax + mov 24($aptr,$i),%rdx # a[i+3] # prefetch + lea 32($i),$i + mov 64($tptr),$A0[0] # t[2*i+8] # prefetch + adox $A1[1],$A1[1] + adcx $A0[1],%rbx + mov 72($tptr),$A0[1] # t[2*i+8+1] # prefetch + mov %rax,32($tptr) + mov %rbx,40($tptr) + + mulx %rdx,%rax,%rbx + adox $A0[0],$A0[0] + adcx $A1[0],%rax + jrcxz .Lsqrx4x_shift_n_add_break + .byte 0x48,0x8b,0x94,0x0e,0x00,0x00,0x00,0x00 # mov 0($aptr,$i),%rdx # a[i+4] # prefetch + adox $A0[1],$A0[1] + adcx $A1[1],%rbx + mov 80($tptr),$A1[0] # t[2*i+10] # prefetch + mov 88($tptr),$A1[1] # t[2*i+10+1] # prefetch + mov %rax,48($tptr) + mov %rbx,56($tptr) + lea 64($tptr),$tptr + nop + jmp .Lsqrx4x_shift_n_add + +.align 32 +.Lsqrx4x_shift_n_add_break: + adcx $A1[1],%rbx + mov %rax,48($tptr) + mov %rbx,56($tptr) + lea 64($tptr),$tptr # end of t[] buffer +___ +} +###################################################################### +# Montgomery reduction part, "word-by-word" algorithm. +# +# This new path is inspired by multiple submissions from Intel, by +# Shay Gueron, Vlad Krasnov, Erdinc Ozturk, James Guilford, +# Vinodh Gopal... +{ +my ($nptr,$carry,$m0)=("%rbp","%rsi","%rdx"); + +$code.=<<___; + movq %xmm2,$nptr +__bn_sqrx8x_reduction: + xor %eax,%eax # initial top-most carry bit + mov 32+8(%rsp),%rbx # n0 + mov 48+8(%rsp),%rdx # "%r8", 8*0($tptr) + lea -8*8($nptr,$num),%rcx # end of n[] + #lea 48+8(%rsp,$num,2),$tptr # end of t[] buffer + mov %rcx, 0+8(%rsp) # save end of n[] + mov $tptr,8+8(%rsp) # save end of t[] + + lea 48+8(%rsp),$tptr # initial t[] window + jmp .Lsqrx8x_reduction_loop + +.align 32 +.Lsqrx8x_reduction_loop: + mov 8*1($tptr),%r9 + mov 8*2($tptr),%r10 + mov 8*3($tptr),%r11 + mov 8*4($tptr),%r12 + mov %rdx,%r8 + imulq %rbx,%rdx # n0*a[i] + mov 8*5($tptr),%r13 + mov 8*6($tptr),%r14 + mov 8*7($tptr),%r15 + mov %rax,24+8(%rsp) # store top-most carry bit + + lea 8*8($tptr),$tptr + xor $carry,$carry # cf=0,of=0 + mov \$-8,%rcx + jmp .Lsqrx8x_reduce + +.align 32 +.Lsqrx8x_reduce: + mov %r8, %rbx + mulx 8*0($nptr),%rax,%r8 # n[0] + adcx %rbx,%rax # discarded + adox %r9,%r8 + + mulx 8*1($nptr),%rbx,%r9 # n[1] + adcx %rbx,%r8 + adox %r10,%r9 + + mulx 8*2($nptr),%rbx,%r10 + adcx %rbx,%r9 + adox %r11,%r10 + + mulx 8*3($nptr),%rbx,%r11 + adcx %rbx,%r10 + adox %r12,%r11 + + .byte 0xc4,0x62,0xe3,0xf6,0xa5,0x20,0x00,0x00,0x00 # mulx 8*4($nptr),%rbx,%r12 + mov %rdx,%rax + mov %r8,%rdx + adcx %rbx,%r11 + adox %r13,%r12 + + mulx 32+8(%rsp),%rbx,%rdx # %rdx discarded + mov %rax,%rdx + mov %rax,64+48+8(%rsp,%rcx,8) # put aside n0*a[i] + + mulx 8*5($nptr),%rax,%r13 + adcx %rax,%r12 + adox %r14,%r13 + + mulx 8*6($nptr),%rax,%r14 + adcx %rax,%r13 + adox %r15,%r14 + + mulx 8*7($nptr),%rax,%r15 + mov %rbx,%rdx + adcx %rax,%r14 + adox $carry,%r15 # $carry is 0 + adcx $carry,%r15 # cf=0 + + .byte 0x67,0x67,0x67 + inc %rcx # of=0 + jnz .Lsqrx8x_reduce + + mov $carry,%rax # xor %rax,%rax + cmp 0+8(%rsp),$nptr # end of n[]? + jae .Lsqrx8x_no_tail + + mov 48+8(%rsp),%rdx # pull n0*a[0] + add 8*0($tptr),%r8 + lea 8*8($nptr),$nptr + mov \$-8,%rcx + adcx 8*1($tptr),%r9 + adcx 8*2($tptr),%r10 + adc 8*3($tptr),%r11 + adc 8*4($tptr),%r12 + adc 8*5($tptr),%r13 + adc 8*6($tptr),%r14 + adc 8*7($tptr),%r15 + lea 8*8($tptr),$tptr + sbb %rax,%rax # top carry + + xor $carry,$carry # of=0, cf=0 + mov %rax,16+8(%rsp) + jmp .Lsqrx8x_tail + +.align 32 +.Lsqrx8x_tail: + mov %r8,%rbx + mulx 8*0($nptr),%rax,%r8 + adcx %rax,%rbx + adox %r9,%r8 + + mulx 8*1($nptr),%rax,%r9 + adcx %rax,%r8 + adox %r10,%r9 + + mulx 8*2($nptr),%rax,%r10 + adcx %rax,%r9 + adox %r11,%r10 + + mulx 8*3($nptr),%rax,%r11 + adcx %rax,%r10 + adox %r12,%r11 + + .byte 0xc4,0x62,0xfb,0xf6,0xa5,0x20,0x00,0x00,0x00 # mulx 8*4($nptr),%rax,%r12 + adcx %rax,%r11 + adox %r13,%r12 + + mulx 8*5($nptr),%rax,%r13 + adcx %rax,%r12 + adox %r14,%r13 + + mulx 8*6($nptr),%rax,%r14 + adcx %rax,%r13 + adox %r15,%r14 + + mulx 8*7($nptr),%rax,%r15 + mov 72+48+8(%rsp,%rcx,8),%rdx # pull n0*a[i] + adcx %rax,%r14 + adox $carry,%r15 + mov %rbx,($tptr,%rcx,8) # save result + mov %r8,%rbx + adcx $carry,%r15 # cf=0 + + inc %rcx # of=0 + jnz .Lsqrx8x_tail + + cmp 0+8(%rsp),$nptr # end of n[]? + jae .Lsqrx8x_tail_done # break out of loop + + sub 16+8(%rsp),$carry # mov 16(%rsp),%cf + mov 48+8(%rsp),%rdx # pull n0*a[0] + lea 8*8($nptr),$nptr + adc 8*0($tptr),%r8 + adc 8*1($tptr),%r9 + adc 8*2($tptr),%r10 + adc 8*3($tptr),%r11 + adc 8*4($tptr),%r12 + adc 8*5($tptr),%r13 + adc 8*6($tptr),%r14 + adc 8*7($tptr),%r15 + lea 8*8($tptr),$tptr + sbb %rax,%rax + sub \$8,%rcx # mov \$-8,%rcx + + xor $carry,$carry # of=0, cf=0 + mov %rax,16+8(%rsp) + jmp .Lsqrx8x_tail + +.align 32 +.Lsqrx8x_tail_done: + xor %rax,%rax + add 24+8(%rsp),%r8 # can this overflow? + adc \$0,%r9 + adc \$0,%r10 + adc \$0,%r11 + adc \$0,%r12 + adc \$0,%r13 + adc \$0,%r14 + adc \$0,%r15 + adc \$0,%rax + + sub 16+8(%rsp),$carry # mov 16(%rsp),%cf +.Lsqrx8x_no_tail: # %cf is 0 if jumped here + adc 8*0($tptr),%r8 + movq %xmm3,%rcx + adc 8*1($tptr),%r9 + mov 8*7($nptr),$carry + movq %xmm2,$nptr # restore $nptr + adc 8*2($tptr),%r10 + adc 8*3($tptr),%r11 + adc 8*4($tptr),%r12 + adc 8*5($tptr),%r13 + adc 8*6($tptr),%r14 + adc 8*7($tptr),%r15 + adc \$0,%rax # top-most carry + + mov 32+8(%rsp),%rbx # n0 + mov 8*8($tptr,%rcx),%rdx # modulo-scheduled "%r8" + + mov %r8,8*0($tptr) # store top 512 bits + lea 8*8($tptr),%r8 # borrow %r8 + mov %r9,8*1($tptr) + mov %r10,8*2($tptr) + mov %r11,8*3($tptr) + mov %r12,8*4($tptr) + mov %r13,8*5($tptr) + mov %r14,8*6($tptr) + mov %r15,8*7($tptr) + + lea 8*8($tptr,%rcx),$tptr # start of current t[] window + cmp 8+8(%rsp),%r8 # end of t[]? + jb .Lsqrx8x_reduction_loop + ret +.cfi_endproc +.size bn_sqrx8x_internal,.-bn_sqrx8x_internal +___ +} +############################################################## +# Post-condition, 4x unrolled +# +{ +my ($rptr,$nptr)=("%rdx","%rbp"); +$code.=<<___; +.align 32 +__bn_postx4x_internal: + mov 8*0($nptr),%r12 + mov %rcx,%r10 # -$num + mov %rcx,%r9 # -$num + neg %rax + sar \$3+2,%rcx + #lea 48+8(%rsp,%r9),$tptr + movq %xmm1,$rptr # restore $rptr + movq %xmm1,$aptr # prepare for back-to-back call + dec %r12 # so that after 'not' we get -n[0] + mov 8*1($nptr),%r13 + xor %r8,%r8 + mov 8*2($nptr),%r14 + mov 8*3($nptr),%r15 + jmp .Lsqrx4x_sub_entry + +.align 16 +.Lsqrx4x_sub: + mov 8*0($nptr),%r12 + mov 8*1($nptr),%r13 + mov 8*2($nptr),%r14 + mov 8*3($nptr),%r15 +.Lsqrx4x_sub_entry: + andn %rax,%r12,%r12 + lea 8*4($nptr),$nptr + andn %rax,%r13,%r13 + andn %rax,%r14,%r14 + andn %rax,%r15,%r15 + + neg %r8 # mov %r8,%cf + adc 8*0($tptr),%r12 + adc 8*1($tptr),%r13 + adc 8*2($tptr),%r14 + adc 8*3($tptr),%r15 + mov %r12,8*0($rptr) + lea 8*4($tptr),$tptr + mov %r13,8*1($rptr) + sbb %r8,%r8 # mov %cf,%r8 + mov %r14,8*2($rptr) + mov %r15,8*3($rptr) + lea 8*4($rptr),$rptr + + inc %rcx + jnz .Lsqrx4x_sub + + neg %r9 # restore $num + + ret +.size __bn_postx4x_internal,.-__bn_postx4x_internal +___ +} +}}} +{ +my ($inp,$num,$tbl,$idx)=$win64?("%rcx","%edx","%r8", "%r9d") : # Win64 order + ("%rdi","%esi","%rdx","%ecx"); # Unix order +my $out=$inp; +my $STRIDE=2**5*8; +my $N=$STRIDE/4; + +$code.=<<___; +.globl bn_get_bits5 +.type bn_get_bits5,\@abi-omnipotent +.align 16 +bn_get_bits5: + lea 0($inp),%r10 + lea 1($inp),%r11 + mov $num,%ecx + shr \$4,$num + and \$15,%ecx + lea -8(%ecx),%eax + cmp \$11,%ecx + cmova %r11,%r10 + cmova %eax,%ecx + movzw (%r10,$num,2),%eax + shrl %cl,%eax + and \$31,%eax + ret +.size bn_get_bits5,.-bn_get_bits5 + +.globl bn_scatter5 +.type bn_scatter5,\@abi-omnipotent +.align 16 +bn_scatter5: + cmp \$0, $num + jz .Lscatter_epilogue + lea ($tbl,$idx,8),$tbl +.Lscatter: + mov ($inp),%rax + lea 8($inp),$inp + mov %rax,($tbl) + lea 32*8($tbl),$tbl + sub \$1,$num + jnz .Lscatter +.Lscatter_epilogue: + ret +.size bn_scatter5,.-bn_scatter5 + +.globl bn_gather5 +.type bn_gather5,\@abi-omnipotent +.align 32 +bn_gather5: +.LSEH_begin_bn_gather5: # Win64 thing, but harmless in other cases + # I can't trust assembler to use specific encoding:-( + .byte 0x4c,0x8d,0x14,0x24 #lea (%rsp),%r10 + .byte 0x48,0x81,0xec,0x08,0x01,0x00,0x00 #sub $0x108,%rsp + lea .Linc(%rip),%rax + and \$-16,%rsp # shouldn't be formally required + + movd $idx,%xmm5 + movdqa 0(%rax),%xmm0 # 00000001000000010000000000000000 + movdqa 16(%rax),%xmm1 # 00000002000000020000000200000002 + lea 128($tbl),%r11 # size optimization + lea 128(%rsp),%rax # size optimization + + pshufd \$0,%xmm5,%xmm5 # broadcast $idx + movdqa %xmm1,%xmm4 + movdqa %xmm1,%xmm2 +___ +######################################################################## +# calculate mask by comparing 0..31 to $idx and save result to stack +# +for($i=0;$i<$STRIDE/16;$i+=4) { +$code.=<<___; + paddd %xmm0,%xmm1 + pcmpeqd %xmm5,%xmm0 # compare to 1,0 +___ +$code.=<<___ if ($i); + movdqa %xmm3,`16*($i-1)-128`(%rax) +___ +$code.=<<___; + movdqa %xmm4,%xmm3 + + paddd %xmm1,%xmm2 + pcmpeqd %xmm5,%xmm1 # compare to 3,2 + movdqa %xmm0,`16*($i+0)-128`(%rax) + movdqa %xmm4,%xmm0 + + paddd %xmm2,%xmm3 + pcmpeqd %xmm5,%xmm2 # compare to 5,4 + movdqa %xmm1,`16*($i+1)-128`(%rax) + movdqa %xmm4,%xmm1 + + paddd %xmm3,%xmm0 + pcmpeqd %xmm5,%xmm3 # compare to 7,6 + movdqa %xmm2,`16*($i+2)-128`(%rax) + movdqa %xmm4,%xmm2 +___ +} +$code.=<<___; + movdqa %xmm3,`16*($i-1)-128`(%rax) + jmp .Lgather + +.align 32 +.Lgather: + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 +___ +for($i=0;$i<$STRIDE/16;$i+=4) { +$code.=<<___; + movdqa `16*($i+0)-128`(%r11),%xmm0 + movdqa `16*($i+1)-128`(%r11),%xmm1 + movdqa `16*($i+2)-128`(%r11),%xmm2 + pand `16*($i+0)-128`(%rax),%xmm0 + movdqa `16*($i+3)-128`(%r11),%xmm3 + pand `16*($i+1)-128`(%rax),%xmm1 + por %xmm0,%xmm4 + pand `16*($i+2)-128`(%rax),%xmm2 + por %xmm1,%xmm5 + pand `16*($i+3)-128`(%rax),%xmm3 + por %xmm2,%xmm4 + por %xmm3,%xmm5 +___ +} +$code.=<<___; + por %xmm5,%xmm4 + lea $STRIDE(%r11),%r11 + pshufd \$0x4e,%xmm4,%xmm0 + por %xmm4,%xmm0 + movq %xmm0,($out) # m0=bp[0] + lea 8($out),$out + sub \$1,$num + jnz .Lgather + + lea (%r10),%rsp + ret +.LSEH_end_bn_gather5: +.size bn_gather5,.-bn_gather5 +___ +} +$code.=<<___; +.align 64 +.Linc: + .long 0,0, 1,1 + .long 2,2, 2,2 +.asciz "Montgomery Multiplication with scatter/gather for x86_64, CRYPTOGAMS by " +___ + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type mul_handler,\@abi-omnipotent +.align 16 +mul_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # end of prologue label + cmp %r10,%rbx # context->RipRipRsp + + mov 8(%r11),%r10d # HandlerData[2] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lcommon_seh_tail + + lea .Lmul_epilogue(%rip),%r10 + cmp %r10,%rbx + ja .Lbody_40 + + mov 192($context),%r10 # pull $num + mov 8(%rax,%r10,8),%rax # pull saved stack pointer + + jmp .Lcommon_pop_regs + +.Lbody_40: + mov 40(%rax),%rax # pull saved stack pointer +.Lcommon_pop_regs: + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov -48(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + +.Lcommon_seh_tail: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size mul_handler,.-mul_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_bn_mul_mont_gather5 + .rva .LSEH_end_bn_mul_mont_gather5 + .rva .LSEH_info_bn_mul_mont_gather5 + + .rva .LSEH_begin_bn_mul4x_mont_gather5 + .rva .LSEH_end_bn_mul4x_mont_gather5 + .rva .LSEH_info_bn_mul4x_mont_gather5 + + .rva .LSEH_begin_bn_power5 + .rva .LSEH_end_bn_power5 + .rva .LSEH_info_bn_power5 + + .rva .LSEH_begin_bn_from_mont8x + .rva .LSEH_end_bn_from_mont8x + .rva .LSEH_info_bn_from_mont8x +___ +$code.=<<___ if ($addx); + .rva .LSEH_begin_bn_mulx4x_mont_gather5 + .rva .LSEH_end_bn_mulx4x_mont_gather5 + .rva .LSEH_info_bn_mulx4x_mont_gather5 + + .rva .LSEH_begin_bn_powerx5 + .rva .LSEH_end_bn_powerx5 + .rva .LSEH_info_bn_powerx5 +___ +$code.=<<___; + .rva .LSEH_begin_bn_gather5 + .rva .LSEH_end_bn_gather5 + .rva .LSEH_info_bn_gather5 + +.section .xdata +.align 8 +.LSEH_info_bn_mul_mont_gather5: + .byte 9,0,0,0 + .rva mul_handler + .rva .Lmul_body,.Lmul_body,.Lmul_epilogue # HandlerData[] +.align 8 +.LSEH_info_bn_mul4x_mont_gather5: + .byte 9,0,0,0 + .rva mul_handler + .rva .Lmul4x_prologue,.Lmul4x_body,.Lmul4x_epilogue # HandlerData[] +.align 8 +.LSEH_info_bn_power5: + .byte 9,0,0,0 + .rva mul_handler + .rva .Lpower5_prologue,.Lpower5_body,.Lpower5_epilogue # HandlerData[] +.align 8 +.LSEH_info_bn_from_mont8x: + .byte 9,0,0,0 + .rva mul_handler + .rva .Lfrom_prologue,.Lfrom_body,.Lfrom_epilogue # HandlerData[] +___ +$code.=<<___ if ($addx); +.align 8 +.LSEH_info_bn_mulx4x_mont_gather5: + .byte 9,0,0,0 + .rva mul_handler + .rva .Lmulx4x_prologue,.Lmulx4x_body,.Lmulx4x_epilogue # HandlerData[] +.align 8 +.LSEH_info_bn_powerx5: + .byte 9,0,0,0 + .rva mul_handler + .rva .Lpowerx5_prologue,.Lpowerx5_body,.Lpowerx5_epilogue # HandlerData[] +___ +$code.=<<___; +.align 8 +.LSEH_info_bn_gather5: + .byte 0x01,0x0b,0x03,0x0a + .byte 0x0b,0x01,0x21,0x00 # sub rsp,0x108 + .byte 0x04,0xa3,0x00,0x00 # lea r10,(rsp) +.align 8 +___ +} + +$code =~ s/\`([^\`]*)\`/eval($1)/gem; + +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_add.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_add.c new file mode 100644 index 000000000..f2736b8f6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_add.c @@ -0,0 +1,171 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include "bn_lcl.h" + +/* signed add of b to a. */ +int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) +{ + int ret, r_neg, cmp_res; + + bn_check_top(a); + bn_check_top(b); + + if (a->neg == b->neg) { + r_neg = a->neg; + ret = BN_uadd(r, a, b); + } else { + cmp_res = BN_ucmp(a, b); + if (cmp_res > 0) { + r_neg = a->neg; + ret = BN_usub(r, a, b); + } else if (cmp_res < 0) { + r_neg = b->neg; + ret = BN_usub(r, b, a); + } else { + r_neg = 0; + BN_zero(r); + ret = 1; + } + } + + r->neg = r_neg; + bn_check_top(r); + return ret; +} + +/* signed sub of b from a. */ +int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) +{ + int ret, r_neg, cmp_res; + + bn_check_top(a); + bn_check_top(b); + + if (a->neg != b->neg) { + r_neg = a->neg; + ret = BN_uadd(r, a, b); + } else { + cmp_res = BN_ucmp(a, b); + if (cmp_res > 0) { + r_neg = a->neg; + ret = BN_usub(r, a, b); + } else if (cmp_res < 0) { + r_neg = !b->neg; + ret = BN_usub(r, b, a); + } else { + r_neg = 0; + BN_zero(r); + ret = 1; + } + } + + r->neg = r_neg; + bn_check_top(r); + return ret; +} + +/* unsigned add of b to a, r can be equal to a or b. */ +int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) +{ + int max, min, dif; + const BN_ULONG *ap, *bp; + BN_ULONG *rp, carry, t1, t2; + + bn_check_top(a); + bn_check_top(b); + + if (a->top < b->top) { + const BIGNUM *tmp; + + tmp = a; + a = b; + b = tmp; + } + max = a->top; + min = b->top; + dif = max - min; + + if (bn_wexpand(r, max + 1) == NULL) + return 0; + + r->top = max; + + ap = a->d; + bp = b->d; + rp = r->d; + + carry = bn_add_words(rp, ap, bp, min); + rp += min; + ap += min; + + while (dif) { + dif--; + t1 = *(ap++); + t2 = (t1 + carry) & BN_MASK2; + *(rp++) = t2; + carry &= (t2 == 0); + } + *rp = carry; + r->top += carry; + + r->neg = 0; + bn_check_top(r); + return 1; +} + +/* unsigned subtraction of b from a, a must be larger than b. */ +int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) +{ + int max, min, dif; + BN_ULONG t1, t2, borrow, *rp; + const BN_ULONG *ap, *bp; + + bn_check_top(a); + bn_check_top(b); + + max = a->top; + min = b->top; + dif = max - min; + + if (dif < 0) { /* hmm... should not be happening */ + BNerr(BN_F_BN_USUB, BN_R_ARG2_LT_ARG3); + return 0; + } + + if (bn_wexpand(r, max) == NULL) + return 0; + + ap = a->d; + bp = b->d; + rp = r->d; + + borrow = bn_sub_words(rp, ap, bp, min); + ap += min; + rp += min; + + while (dif) { + dif--; + t1 = *(ap++); + t2 = (t1 - borrow) & BN_MASK2; + *(rp++) = t2; + borrow &= (t1 == 0); + } + + while (max && *--rp == 0) + max--; + + r->top = max; + r->neg = 0; + bn_pollute(r); + + return 1; +} + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_asm.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_asm.c new file mode 100644 index 000000000..729b2480a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_asm.c @@ -0,0 +1,1039 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include "bn_lcl.h" + +#if defined(BN_LLONG) || defined(BN_UMULT_HIGH) + +BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, + BN_ULONG w) +{ + BN_ULONG c1 = 0; + + assert(num >= 0); + if (num <= 0) + return c1; + +# ifndef OPENSSL_SMALL_FOOTPRINT + while (num & ~3) { + mul_add(rp[0], ap[0], w, c1); + mul_add(rp[1], ap[1], w, c1); + mul_add(rp[2], ap[2], w, c1); + mul_add(rp[3], ap[3], w, c1); + ap += 4; + rp += 4; + num -= 4; + } +# endif + while (num) { + mul_add(rp[0], ap[0], w, c1); + ap++; + rp++; + num--; + } + + return c1; +} + +BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) +{ + BN_ULONG c1 = 0; + + assert(num >= 0); + if (num <= 0) + return c1; + +# ifndef OPENSSL_SMALL_FOOTPRINT + while (num & ~3) { + mul(rp[0], ap[0], w, c1); + mul(rp[1], ap[1], w, c1); + mul(rp[2], ap[2], w, c1); + mul(rp[3], ap[3], w, c1); + ap += 4; + rp += 4; + num -= 4; + } +# endif + while (num) { + mul(rp[0], ap[0], w, c1); + ap++; + rp++; + num--; + } + return c1; +} + +void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) +{ + assert(n >= 0); + if (n <= 0) + return; + +# ifndef OPENSSL_SMALL_FOOTPRINT + while (n & ~3) { + sqr(r[0], r[1], a[0]); + sqr(r[2], r[3], a[1]); + sqr(r[4], r[5], a[2]); + sqr(r[6], r[7], a[3]); + a += 4; + r += 8; + n -= 4; + } +# endif + while (n) { + sqr(r[0], r[1], a[0]); + a++; + r += 2; + n--; + } +} + +#else /* !(defined(BN_LLONG) || + * defined(BN_UMULT_HIGH)) */ + +BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, + BN_ULONG w) +{ + BN_ULONG c = 0; + BN_ULONG bl, bh; + + assert(num >= 0); + if (num <= 0) + return (BN_ULONG)0; + + bl = LBITS(w); + bh = HBITS(w); + +# ifndef OPENSSL_SMALL_FOOTPRINT + while (num & ~3) { + mul_add(rp[0], ap[0], bl, bh, c); + mul_add(rp[1], ap[1], bl, bh, c); + mul_add(rp[2], ap[2], bl, bh, c); + mul_add(rp[3], ap[3], bl, bh, c); + ap += 4; + rp += 4; + num -= 4; + } +# endif + while (num) { + mul_add(rp[0], ap[0], bl, bh, c); + ap++; + rp++; + num--; + } + return c; +} + +BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) +{ + BN_ULONG carry = 0; + BN_ULONG bl, bh; + + assert(num >= 0); + if (num <= 0) + return (BN_ULONG)0; + + bl = LBITS(w); + bh = HBITS(w); + +# ifndef OPENSSL_SMALL_FOOTPRINT + while (num & ~3) { + mul(rp[0], ap[0], bl, bh, carry); + mul(rp[1], ap[1], bl, bh, carry); + mul(rp[2], ap[2], bl, bh, carry); + mul(rp[3], ap[3], bl, bh, carry); + ap += 4; + rp += 4; + num -= 4; + } +# endif + while (num) { + mul(rp[0], ap[0], bl, bh, carry); + ap++; + rp++; + num--; + } + return carry; +} + +void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) +{ + assert(n >= 0); + if (n <= 0) + return; + +# ifndef OPENSSL_SMALL_FOOTPRINT + while (n & ~3) { + sqr64(r[0], r[1], a[0]); + sqr64(r[2], r[3], a[1]); + sqr64(r[4], r[5], a[2]); + sqr64(r[6], r[7], a[3]); + a += 4; + r += 8; + n -= 4; + } +# endif + while (n) { + sqr64(r[0], r[1], a[0]); + a++; + r += 2; + n--; + } +} + +#endif /* !(defined(BN_LLONG) || + * defined(BN_UMULT_HIGH)) */ + +#if defined(BN_LLONG) && defined(BN_DIV2W) + +BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) +{ + return ((BN_ULONG)(((((BN_ULLONG) h) << BN_BITS2) | l) / (BN_ULLONG) d)); +} + +#else + +/* Divide h,l by d and return the result. */ +/* I need to test this some more :-( */ +BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) +{ + BN_ULONG dh, dl, q, ret = 0, th, tl, t; + int i, count = 2; + + if (d == 0) + return BN_MASK2; + + i = BN_num_bits_word(d); + assert((i == BN_BITS2) || (h <= (BN_ULONG)1 << i)); + + i = BN_BITS2 - i; + if (h >= d) + h -= d; + + if (i) { + d <<= i; + h = (h << i) | (l >> (BN_BITS2 - i)); + l <<= i; + } + dh = (d & BN_MASK2h) >> BN_BITS4; + dl = (d & BN_MASK2l); + for (;;) { + if ((h >> BN_BITS4) == dh) + q = BN_MASK2l; + else + q = h / dh; + + th = q * dh; + tl = dl * q; + for (;;) { + t = h - th; + if ((t & BN_MASK2h) || + ((tl) <= ((t << BN_BITS4) | ((l & BN_MASK2h) >> BN_BITS4)))) + break; + q--; + th -= dh; + tl -= dl; + } + t = (tl >> BN_BITS4); + tl = (tl << BN_BITS4) & BN_MASK2h; + th += t; + + if (l < tl) + th++; + l -= tl; + if (h < th) { + h += d; + q--; + } + h -= th; + + if (--count == 0) + break; + + ret = q << BN_BITS4; + h = ((h << BN_BITS4) | (l >> BN_BITS4)) & BN_MASK2; + l = (l & BN_MASK2l) << BN_BITS4; + } + ret |= q; + return ret; +} +#endif /* !defined(BN_LLONG) && defined(BN_DIV2W) */ + +#ifdef BN_LLONG +BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, + int n) +{ + BN_ULLONG ll = 0; + + assert(n >= 0); + if (n <= 0) + return (BN_ULONG)0; + +# ifndef OPENSSL_SMALL_FOOTPRINT + while (n & ~3) { + ll += (BN_ULLONG) a[0] + b[0]; + r[0] = (BN_ULONG)ll & BN_MASK2; + ll >>= BN_BITS2; + ll += (BN_ULLONG) a[1] + b[1]; + r[1] = (BN_ULONG)ll & BN_MASK2; + ll >>= BN_BITS2; + ll += (BN_ULLONG) a[2] + b[2]; + r[2] = (BN_ULONG)ll & BN_MASK2; + ll >>= BN_BITS2; + ll += (BN_ULLONG) a[3] + b[3]; + r[3] = (BN_ULONG)ll & BN_MASK2; + ll >>= BN_BITS2; + a += 4; + b += 4; + r += 4; + n -= 4; + } +# endif + while (n) { + ll += (BN_ULLONG) a[0] + b[0]; + r[0] = (BN_ULONG)ll & BN_MASK2; + ll >>= BN_BITS2; + a++; + b++; + r++; + n--; + } + return (BN_ULONG)ll; +} +#else /* !BN_LLONG */ +BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, + int n) +{ + BN_ULONG c, l, t; + + assert(n >= 0); + if (n <= 0) + return (BN_ULONG)0; + + c = 0; +# ifndef OPENSSL_SMALL_FOOTPRINT + while (n & ~3) { + t = a[0]; + t = (t + c) & BN_MASK2; + c = (t < c); + l = (t + b[0]) & BN_MASK2; + c += (l < t); + r[0] = l; + t = a[1]; + t = (t + c) & BN_MASK2; + c = (t < c); + l = (t + b[1]) & BN_MASK2; + c += (l < t); + r[1] = l; + t = a[2]; + t = (t + c) & BN_MASK2; + c = (t < c); + l = (t + b[2]) & BN_MASK2; + c += (l < t); + r[2] = l; + t = a[3]; + t = (t + c) & BN_MASK2; + c = (t < c); + l = (t + b[3]) & BN_MASK2; + c += (l < t); + r[3] = l; + a += 4; + b += 4; + r += 4; + n -= 4; + } +# endif + while (n) { + t = a[0]; + t = (t + c) & BN_MASK2; + c = (t < c); + l = (t + b[0]) & BN_MASK2; + c += (l < t); + r[0] = l; + a++; + b++; + r++; + n--; + } + return (BN_ULONG)c; +} +#endif /* !BN_LLONG */ + +BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, + int n) +{ + BN_ULONG t1, t2; + int c = 0; + + assert(n >= 0); + if (n <= 0) + return (BN_ULONG)0; + +#ifndef OPENSSL_SMALL_FOOTPRINT + while (n & ~3) { + t1 = a[0]; + t2 = b[0]; + r[0] = (t1 - t2 - c) & BN_MASK2; + if (t1 != t2) + c = (t1 < t2); + t1 = a[1]; + t2 = b[1]; + r[1] = (t1 - t2 - c) & BN_MASK2; + if (t1 != t2) + c = (t1 < t2); + t1 = a[2]; + t2 = b[2]; + r[2] = (t1 - t2 - c) & BN_MASK2; + if (t1 != t2) + c = (t1 < t2); + t1 = a[3]; + t2 = b[3]; + r[3] = (t1 - t2 - c) & BN_MASK2; + if (t1 != t2) + c = (t1 < t2); + a += 4; + b += 4; + r += 4; + n -= 4; + } +#endif + while (n) { + t1 = a[0]; + t2 = b[0]; + r[0] = (t1 - t2 - c) & BN_MASK2; + if (t1 != t2) + c = (t1 < t2); + a++; + b++; + r++; + n--; + } + return c; +} + +#if defined(BN_MUL_COMBA) && !defined(OPENSSL_SMALL_FOOTPRINT) + +# undef bn_mul_comba8 +# undef bn_mul_comba4 +# undef bn_sqr_comba8 +# undef bn_sqr_comba4 + +/* mul_add_c(a,b,c0,c1,c2) -- c+=a*b for three word number c=(c2,c1,c0) */ +/* mul_add_c2(a,b,c0,c1,c2) -- c+=2*a*b for three word number c=(c2,c1,c0) */ +/* sqr_add_c(a,i,c0,c1,c2) -- c+=a[i]^2 for three word number c=(c2,c1,c0) */ +/* + * sqr_add_c2(a,i,c0,c1,c2) -- c+=2*a[i]*a[j] for three word number + * c=(c2,c1,c0) + */ + +# ifdef BN_LLONG +/* + * Keep in mind that additions to multiplication result can not + * overflow, because its high half cannot be all-ones. + */ +# define mul_add_c(a,b,c0,c1,c2) do { \ + BN_ULONG hi; \ + BN_ULLONG t = (BN_ULLONG)(a)*(b); \ + t += c0; /* no carry */ \ + c0 = (BN_ULONG)Lw(t); \ + hi = (BN_ULONG)Hw(t); \ + c1 = (c1+hi)&BN_MASK2; if (c1 +/* + * This is essentially reference implementation, which may or may not + * result in performance improvement. E.g. on IA-32 this routine was + * observed to give 40% faster rsa1024 private key operations and 10% + * faster rsa4096 ones, while on AMD64 it improves rsa1024 sign only + * by 10% and *worsens* rsa4096 sign by 15%. Once again, it's a + * reference implementation, one to be used as starting point for + * platform-specific assembler. Mentioned numbers apply to compiler + * generated code compiled with and without -DOPENSSL_BN_ASM_MONT and + * can vary not only from platform to platform, but even for compiler + * versions. Assembler vs. assembler improvement coefficients can + * [and are known to] differ and are to be documented elsewhere. + */ +int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + const BN_ULONG *np, const BN_ULONG *n0p, int num) +{ + BN_ULONG c0, c1, ml, *tp, n0; +# ifdef mul64 + BN_ULONG mh; +# endif + volatile BN_ULONG *vp; + int i = 0, j; + +# if 0 /* template for platform-specific + * implementation */ + if (ap == bp) + return bn_sqr_mont(rp, ap, np, n0p, num); +# endif + vp = tp = alloca((num + 2) * sizeof(BN_ULONG)); + + n0 = *n0p; + + c0 = 0; + ml = bp[0]; +# ifdef mul64 + mh = HBITS(ml); + ml = LBITS(ml); + for (j = 0; j < num; ++j) + mul(tp[j], ap[j], ml, mh, c0); +# else + for (j = 0; j < num; ++j) + mul(tp[j], ap[j], ml, c0); +# endif + + tp[num] = c0; + tp[num + 1] = 0; + goto enter; + + for (i = 0; i < num; i++) { + c0 = 0; + ml = bp[i]; +# ifdef mul64 + mh = HBITS(ml); + ml = LBITS(ml); + for (j = 0; j < num; ++j) + mul_add(tp[j], ap[j], ml, mh, c0); +# else + for (j = 0; j < num; ++j) + mul_add(tp[j], ap[j], ml, c0); +# endif + c1 = (tp[num] + c0) & BN_MASK2; + tp[num] = c1; + tp[num + 1] = (c1 < c0 ? 1 : 0); + enter: + c1 = tp[0]; + ml = (c1 * n0) & BN_MASK2; + c0 = 0; +# ifdef mul64 + mh = HBITS(ml); + ml = LBITS(ml); + mul_add(c1, np[0], ml, mh, c0); +# else + mul_add(c1, ml, np[0], c0); +# endif + for (j = 1; j < num; j++) { + c1 = tp[j]; +# ifdef mul64 + mul_add(c1, np[j], ml, mh, c0); +# else + mul_add(c1, ml, np[j], c0); +# endif + tp[j - 1] = c1 & BN_MASK2; + } + c1 = (tp[num] + c0) & BN_MASK2; + tp[num - 1] = c1; + tp[num] = tp[num + 1] + (c1 < c0 ? 1 : 0); + } + + if (tp[num] != 0 || tp[num - 1] >= np[num - 1]) { + c0 = bn_sub_words(rp, tp, np, num); + if (tp[num] != 0 || c0 == 0) { + for (i = 0; i < num + 2; i++) + vp[i] = 0; + return 1; + } + } + for (i = 0; i < num; i++) + rp[i] = tp[i], vp[i] = 0; + vp[num] = 0; + vp[num + 1] = 0; + return 1; +} +# else +/* + * Return value of 0 indicates that multiplication/convolution was not + * performed to signal the caller to fall down to alternative/original + * code-path. + */ +int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + const BN_ULONG *np, const BN_ULONG *n0, int num) +{ + return 0; +} +# endif /* OPENSSL_BN_ASM_MONT */ +# endif + +#else /* !BN_MUL_COMBA */ + +/* hmm... is it faster just to do a multiply? */ +# undef bn_sqr_comba4 +# undef bn_sqr_comba8 +void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a) +{ + BN_ULONG t[8]; + bn_sqr_normal(r, a, 4, t); +} + +void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a) +{ + BN_ULONG t[16]; + bn_sqr_normal(r, a, 8, t); +} + +void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) +{ + r[4] = bn_mul_words(&(r[0]), a, 4, b[0]); + r[5] = bn_mul_add_words(&(r[1]), a, 4, b[1]); + r[6] = bn_mul_add_words(&(r[2]), a, 4, b[2]); + r[7] = bn_mul_add_words(&(r[3]), a, 4, b[3]); +} + +void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) +{ + r[8] = bn_mul_words(&(r[0]), a, 8, b[0]); + r[9] = bn_mul_add_words(&(r[1]), a, 8, b[1]); + r[10] = bn_mul_add_words(&(r[2]), a, 8, b[2]); + r[11] = bn_mul_add_words(&(r[3]), a, 8, b[3]); + r[12] = bn_mul_add_words(&(r[4]), a, 8, b[4]); + r[13] = bn_mul_add_words(&(r[5]), a, 8, b[5]); + r[14] = bn_mul_add_words(&(r[6]), a, 8, b[6]); + r[15] = bn_mul_add_words(&(r[7]), a, 8, b[7]); +} + +# ifdef OPENSSL_NO_ASM +# ifdef OPENSSL_BN_ASM_MONT +# include +int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + const BN_ULONG *np, const BN_ULONG *n0p, int num) +{ + BN_ULONG c0, c1, *tp, n0 = *n0p; + volatile BN_ULONG *vp; + int i = 0, j; + + vp = tp = alloca((num + 2) * sizeof(BN_ULONG)); + + for (i = 0; i <= num; i++) + tp[i] = 0; + + for (i = 0; i < num; i++) { + c0 = bn_mul_add_words(tp, ap, num, bp[i]); + c1 = (tp[num] + c0) & BN_MASK2; + tp[num] = c1; + tp[num + 1] = (c1 < c0 ? 1 : 0); + + c0 = bn_mul_add_words(tp, np, num, tp[0] * n0); + c1 = (tp[num] + c0) & BN_MASK2; + tp[num] = c1; + tp[num + 1] += (c1 < c0 ? 1 : 0); + for (j = 0; j <= num; j++) + tp[j] = tp[j + 1]; + } + + if (tp[num] != 0 || tp[num - 1] >= np[num - 1]) { + c0 = bn_sub_words(rp, tp, np, num); + if (tp[num] != 0 || c0 == 0) { + for (i = 0; i < num + 2; i++) + vp[i] = 0; + return 1; + } + } + for (i = 0; i < num; i++) + rp[i] = tp[i], vp[i] = 0; + vp[num] = 0; + vp[num + 1] = 0; + return 1; +} +# else +int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + const BN_ULONG *np, const BN_ULONG *n0, int num) +{ + return 0; +} +# endif /* OPENSSL_BN_ASM_MONT */ +# endif + +#endif /* !BN_MUL_COMBA */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_blind.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_blind.c new file mode 100644 index 000000000..450cdfb34 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_blind.c @@ -0,0 +1,312 @@ +/* + * Copyright 1998-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include "bn_lcl.h" + +#define BN_BLINDING_COUNTER 32 + +struct bn_blinding_st { + BIGNUM *A; + BIGNUM *Ai; + BIGNUM *e; + BIGNUM *mod; /* just a reference */ + CRYPTO_THREAD_ID tid; + int counter; + unsigned long flags; + BN_MONT_CTX *m_ctx; + int (*bn_mod_exp) (BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); + CRYPTO_RWLOCK *lock; +}; + +BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod) +{ + BN_BLINDING *ret = NULL; + + bn_check_top(mod); + + if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) { + BNerr(BN_F_BN_BLINDING_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) { + BNerr(BN_F_BN_BLINDING_NEW, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ret); + return NULL; + } + + BN_BLINDING_set_current_thread(ret); + + if (A != NULL) { + if ((ret->A = BN_dup(A)) == NULL) + goto err; + } + + if (Ai != NULL) { + if ((ret->Ai = BN_dup(Ai)) == NULL) + goto err; + } + + /* save a copy of mod in the BN_BLINDING structure */ + if ((ret->mod = BN_dup(mod)) == NULL) + goto err; + + if (BN_get_flags(mod, BN_FLG_CONSTTIME) != 0) + BN_set_flags(ret->mod, BN_FLG_CONSTTIME); + + /* + * Set the counter to the special value -1 to indicate that this is + * never-used fresh blinding that does not need updating before first + * use. + */ + ret->counter = -1; + + return ret; + + err: + BN_BLINDING_free(ret); + return NULL; +} + +void BN_BLINDING_free(BN_BLINDING *r) +{ + if (r == NULL) + return; + BN_free(r->A); + BN_free(r->Ai); + BN_free(r->e); + BN_free(r->mod); + CRYPTO_THREAD_lock_free(r->lock); + OPENSSL_free(r); +} + +int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx) +{ + int ret = 0; + + if ((b->A == NULL) || (b->Ai == NULL)) { + BNerr(BN_F_BN_BLINDING_UPDATE, BN_R_NOT_INITIALIZED); + goto err; + } + + if (b->counter == -1) + b->counter = 0; + + if (++b->counter == BN_BLINDING_COUNTER && b->e != NULL && + !(b->flags & BN_BLINDING_NO_RECREATE)) { + /* re-create blinding parameters */ + if (!BN_BLINDING_create_param(b, NULL, NULL, ctx, NULL, NULL)) + goto err; + } else if (!(b->flags & BN_BLINDING_NO_UPDATE)) { + if (b->m_ctx != NULL) { + if (!bn_mul_mont_fixed_top(b->Ai, b->Ai, b->Ai, b->m_ctx, ctx) + || !bn_mul_mont_fixed_top(b->A, b->A, b->A, b->m_ctx, ctx)) + goto err; + } else { + if (!BN_mod_mul(b->Ai, b->Ai, b->Ai, b->mod, ctx) + || !BN_mod_mul(b->A, b->A, b->A, b->mod, ctx)) + goto err; + } + } + + ret = 1; + err: + if (b->counter == BN_BLINDING_COUNTER) + b->counter = 0; + return ret; +} + +int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx) +{ + return BN_BLINDING_convert_ex(n, NULL, b, ctx); +} + +int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *ctx) +{ + int ret = 1; + + bn_check_top(n); + + if ((b->A == NULL) || (b->Ai == NULL)) { + BNerr(BN_F_BN_BLINDING_CONVERT_EX, BN_R_NOT_INITIALIZED); + return 0; + } + + if (b->counter == -1) + /* Fresh blinding, doesn't need updating. */ + b->counter = 0; + else if (!BN_BLINDING_update(b, ctx)) + return 0; + + if (r != NULL && (BN_copy(r, b->Ai) == NULL)) + return 0; + + if (b->m_ctx != NULL) + ret = BN_mod_mul_montgomery(n, n, b->A, b->m_ctx, ctx); + else + ret = BN_mod_mul(n, n, b->A, b->mod, ctx); + + return ret; +} + +int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx) +{ + return BN_BLINDING_invert_ex(n, NULL, b, ctx); +} + +int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b, + BN_CTX *ctx) +{ + int ret; + + bn_check_top(n); + + if (r == NULL && (r = b->Ai) == NULL) { + BNerr(BN_F_BN_BLINDING_INVERT_EX, BN_R_NOT_INITIALIZED); + return 0; + } + + if (b->m_ctx != NULL) { + /* ensure that BN_mod_mul_montgomery takes pre-defined path */ + if (n->dmax >= r->top) { + size_t i, rtop = r->top, ntop = n->top; + BN_ULONG mask; + + for (i = 0; i < rtop; i++) { + mask = (BN_ULONG)0 - ((i - ntop) >> (8 * sizeof(i) - 1)); + n->d[i] &= mask; + } + mask = (BN_ULONG)0 - ((rtop - ntop) >> (8 * sizeof(ntop) - 1)); + /* always true, if (rtop >= ntop) n->top = r->top; */ + n->top = (int)(rtop & ~mask) | (ntop & mask); + n->flags |= (BN_FLG_FIXED_TOP & ~mask); + } + ret = BN_mod_mul_montgomery(n, n, r, b->m_ctx, ctx); + } else { + ret = BN_mod_mul(n, n, r, b->mod, ctx); + } + + bn_check_top(n); + return ret; +} + +int BN_BLINDING_is_current_thread(BN_BLINDING *b) +{ + return CRYPTO_THREAD_compare_id(CRYPTO_THREAD_get_current_id(), b->tid); +} + +void BN_BLINDING_set_current_thread(BN_BLINDING *b) +{ + b->tid = CRYPTO_THREAD_get_current_id(); +} + +int BN_BLINDING_lock(BN_BLINDING *b) +{ + return CRYPTO_THREAD_write_lock(b->lock); +} + +int BN_BLINDING_unlock(BN_BLINDING *b) +{ + return CRYPTO_THREAD_unlock(b->lock); +} + +unsigned long BN_BLINDING_get_flags(const BN_BLINDING *b) +{ + return b->flags; +} + +void BN_BLINDING_set_flags(BN_BLINDING *b, unsigned long flags) +{ + b->flags = flags; +} + +BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b, + const BIGNUM *e, BIGNUM *m, BN_CTX *ctx, + int (*bn_mod_exp) (BIGNUM *r, + const BIGNUM *a, + const BIGNUM *p, + const BIGNUM *m, + BN_CTX *ctx, + BN_MONT_CTX *m_ctx), + BN_MONT_CTX *m_ctx) +{ + int retry_counter = 32; + BN_BLINDING *ret = NULL; + + if (b == NULL) + ret = BN_BLINDING_new(NULL, NULL, m); + else + ret = b; + + if (ret == NULL) + goto err; + + if (ret->A == NULL && (ret->A = BN_new()) == NULL) + goto err; + if (ret->Ai == NULL && (ret->Ai = BN_new()) == NULL) + goto err; + + if (e != NULL) { + BN_free(ret->e); + ret->e = BN_dup(e); + } + if (ret->e == NULL) + goto err; + + if (bn_mod_exp != NULL) + ret->bn_mod_exp = bn_mod_exp; + if (m_ctx != NULL) + ret->m_ctx = m_ctx; + + do { + int rv; + if (!BN_priv_rand_range(ret->A, ret->mod)) + goto err; + if (int_bn_mod_inverse(ret->Ai, ret->A, ret->mod, ctx, &rv)) + break; + + /* + * this should almost never happen for good RSA keys + */ + if (!rv) + goto err; + + if (retry_counter-- == 0) { + BNerr(BN_F_BN_BLINDING_CREATE_PARAM, BN_R_TOO_MANY_ITERATIONS); + goto err; + } + } while (1); + + if (ret->bn_mod_exp != NULL && ret->m_ctx != NULL) { + if (!ret->bn_mod_exp(ret->A, ret->A, ret->e, ret->mod, ctx, ret->m_ctx)) + goto err; + } else { + if (!BN_mod_exp(ret->A, ret->A, ret->e, ret->mod, ctx)) + goto err; + } + + if (ret->m_ctx != NULL) { + if (!bn_to_mont_fixed_top(ret->Ai, ret->Ai, ret->m_ctx, ctx) + || !bn_to_mont_fixed_top(ret->A, ret->A, ret->m_ctx, ctx)) + goto err; + } + + return ret; + err: + if (b == NULL) { + BN_BLINDING_free(ret); + ret = NULL; + } + + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_const.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_const.c new file mode 100644 index 000000000..39dd61202 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_const.c @@ -0,0 +1,553 @@ +/* + * Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +/*- + * "First Oakley Default Group" from RFC2409, section 6.1. + * + * The prime is: 2^768 - 2 ^704 - 1 + 2^64 * { [2^638 pi] + 149686 } + * + * RFC2409 specifies a generator of 2. + * RFC2412 specifies a generator of of 22. + */ + +BIGNUM *BN_get_rfc2409_prime_768(BIGNUM *bn) +{ + static const unsigned char RFC2409_PRIME_768[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x3A, 0x36, 0x20, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + }; + return BN_bin2bn(RFC2409_PRIME_768, sizeof(RFC2409_PRIME_768), bn); +} + +/*- + * "Second Oakley Default Group" from RFC2409, section 6.2. + * + * The prime is: 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 }. + * + * RFC2409 specifies a generator of 2. + * RFC2412 specifies a generator of 22. + */ + +BIGNUM *BN_get_rfc2409_prime_1024(BIGNUM *bn) +{ + static const unsigned char RFC2409_PRIME_1024[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + }; + return BN_bin2bn(RFC2409_PRIME_1024, sizeof(RFC2409_PRIME_1024), bn); +} + +/*- + * "1536-bit MODP Group" from RFC3526, Section 2. + * + * The prime is: 2^1536 - 2^1472 - 1 + 2^64 * { [2^1406 pi] + 741804 } + * + * RFC3526 specifies a generator of 2. + * RFC2312 specifies a generator of 22. + */ + +BIGNUM *BN_get_rfc3526_prime_1536(BIGNUM *bn) +{ + static const unsigned char RFC3526_PRIME_1536[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x23, 0x73, 0x27, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + }; + return BN_bin2bn(RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536), bn); +} + +/*- + * "2048-bit MODP Group" from RFC3526, Section 3. + * + * The prime is: 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 } + * + * RFC3526 specifies a generator of 2. + */ + +BIGNUM *BN_get_rfc3526_prime_2048(BIGNUM *bn) +{ + static const unsigned char RFC3526_PRIME_2048[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + }; + return BN_bin2bn(RFC3526_PRIME_2048, sizeof(RFC3526_PRIME_2048), bn); +} + +/*- + * "3072-bit MODP Group" from RFC3526, Section 4. + * + * The prime is: 2^3072 - 2^3008 - 1 + 2^64 * { [2^2942 pi] + 1690314 } + * + * RFC3526 specifies a generator of 2. + */ + +BIGNUM *BN_get_rfc3526_prime_3072(BIGNUM *bn) +{ + static const unsigned char RFC3526_PRIME_3072[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, + 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, + 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, + 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, + 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, + 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, + 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, + 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, + 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, + 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, + 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, + 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + }; + return BN_bin2bn(RFC3526_PRIME_3072, sizeof(RFC3526_PRIME_3072), bn); +} + +/*- + * "4096-bit MODP Group" from RFC3526, Section 5. + * + * The prime is: 2^4096 - 2^4032 - 1 + 2^64 * { [2^3966 pi] + 240904 } + * + * RFC3526 specifies a generator of 2. + */ + +BIGNUM *BN_get_rfc3526_prime_4096(BIGNUM *bn) +{ + static const unsigned char RFC3526_PRIME_4096[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, + 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, + 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, + 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, + 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, + 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, + 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, + 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, + 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, + 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, + 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, + 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, + 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, + 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, + 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, + 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, + 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, + 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, + 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, + 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, + 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, + 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, + 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, + 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, + 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, + 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, + 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, + 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + }; + return BN_bin2bn(RFC3526_PRIME_4096, sizeof(RFC3526_PRIME_4096), bn); +} + +/*- + * "6144-bit MODP Group" from RFC3526, Section 6. + * + * The prime is: 2^6144 - 2^6080 - 1 + 2^64 * { [2^6014 pi] + 929484 } + * + * RFC3526 specifies a generator of 2. + */ + +BIGNUM *BN_get_rfc3526_prime_6144(BIGNUM *bn) +{ + static const unsigned char RFC3526_PRIME_6144[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, + 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, + 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, + 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, + 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, + 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, + 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, + 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, + 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, + 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, + 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, + 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, + 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, + 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, + 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, + 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, + 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, + 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, + 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, + 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, + 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, + 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, + 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, + 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, + 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, + 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, + 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, + 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92, + 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, + 0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE, + 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD, + 0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, + 0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE, + 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31, + 0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, + 0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED, + 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B, + 0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, + 0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42, + 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF, + 0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, + 0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03, + 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6, + 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, + 0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E, + 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3, + 0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, + 0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5, + 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA, + 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, + 0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0, + 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28, + 0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, + 0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0, + 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C, + 0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, + 0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68, + 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE, + 0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, + 0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xCC, 0x40, 0x24, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + }; + return BN_bin2bn(RFC3526_PRIME_6144, sizeof(RFC3526_PRIME_6144), bn); +} + +/*- + * "8192-bit MODP Group" from RFC3526, Section 7. + * + * The prime is: 2^8192 - 2^8128 - 1 + 2^64 * { [2^8062 pi] + 4743158 } + * + * RFC3526 specifies a generator of 2. + */ + +BIGNUM *BN_get_rfc3526_prime_8192(BIGNUM *bn) +{ + static const unsigned char RFC3526_PRIME_8192[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, + 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, + 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, + 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, + 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, + 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, + 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, + 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, + 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, + 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, + 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, + 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, + 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, + 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, + 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, + 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, + 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, + 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, + 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, + 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, + 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, + 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, + 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, + 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, + 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, + 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, + 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, + 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92, + 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, + 0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE, + 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD, + 0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, + 0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE, + 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31, + 0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, + 0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED, + 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B, + 0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, + 0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42, + 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF, + 0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, + 0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03, + 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6, + 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, + 0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E, + 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3, + 0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, + 0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5, + 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA, + 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, + 0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0, + 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28, + 0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, + 0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0, + 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C, + 0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, + 0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68, + 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE, + 0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, + 0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xBE, 0x11, 0x59, + 0x74, 0xA3, 0x92, 0x6F, 0x12, 0xFE, 0xE5, 0xE4, + 0x38, 0x77, 0x7C, 0xB6, 0xA9, 0x32, 0xDF, 0x8C, + 0xD8, 0xBE, 0xC4, 0xD0, 0x73, 0xB9, 0x31, 0xBA, + 0x3B, 0xC8, 0x32, 0xB6, 0x8D, 0x9D, 0xD3, 0x00, + 0x74, 0x1F, 0xA7, 0xBF, 0x8A, 0xFC, 0x47, 0xED, + 0x25, 0x76, 0xF6, 0x93, 0x6B, 0xA4, 0x24, 0x66, + 0x3A, 0xAB, 0x63, 0x9C, 0x5A, 0xE4, 0xF5, 0x68, + 0x34, 0x23, 0xB4, 0x74, 0x2B, 0xF1, 0xC9, 0x78, + 0x23, 0x8F, 0x16, 0xCB, 0xE3, 0x9D, 0x65, 0x2D, + 0xE3, 0xFD, 0xB8, 0xBE, 0xFC, 0x84, 0x8A, 0xD9, + 0x22, 0x22, 0x2E, 0x04, 0xA4, 0x03, 0x7C, 0x07, + 0x13, 0xEB, 0x57, 0xA8, 0x1A, 0x23, 0xF0, 0xC7, + 0x34, 0x73, 0xFC, 0x64, 0x6C, 0xEA, 0x30, 0x6B, + 0x4B, 0xCB, 0xC8, 0x86, 0x2F, 0x83, 0x85, 0xDD, + 0xFA, 0x9D, 0x4B, 0x7F, 0xA2, 0xC0, 0x87, 0xE8, + 0x79, 0x68, 0x33, 0x03, 0xED, 0x5B, 0xDD, 0x3A, + 0x06, 0x2B, 0x3C, 0xF5, 0xB3, 0xA2, 0x78, 0xA6, + 0x6D, 0x2A, 0x13, 0xF8, 0x3F, 0x44, 0xF8, 0x2D, + 0xDF, 0x31, 0x0E, 0xE0, 0x74, 0xAB, 0x6A, 0x36, + 0x45, 0x97, 0xE8, 0x99, 0xA0, 0x25, 0x5D, 0xC1, + 0x64, 0xF3, 0x1C, 0xC5, 0x08, 0x46, 0x85, 0x1D, + 0xF9, 0xAB, 0x48, 0x19, 0x5D, 0xED, 0x7E, 0xA1, + 0xB1, 0xD5, 0x10, 0xBD, 0x7E, 0xE7, 0x4D, 0x73, + 0xFA, 0xF3, 0x6B, 0xC3, 0x1E, 0xCF, 0xA2, 0x68, + 0x35, 0x90, 0x46, 0xF4, 0xEB, 0x87, 0x9F, 0x92, + 0x40, 0x09, 0x43, 0x8B, 0x48, 0x1C, 0x6C, 0xD7, + 0x88, 0x9A, 0x00, 0x2E, 0xD5, 0xEE, 0x38, 0x2B, + 0xC9, 0x19, 0x0D, 0xA6, 0xFC, 0x02, 0x6E, 0x47, + 0x95, 0x58, 0xE4, 0x47, 0x56, 0x77, 0xE9, 0xAA, + 0x9E, 0x30, 0x50, 0xE2, 0x76, 0x56, 0x94, 0xDF, + 0xC8, 0x1F, 0x56, 0xE8, 0x80, 0xB9, 0x6E, 0x71, + 0x60, 0xC9, 0x80, 0xDD, 0x98, 0xED, 0xD3, 0xDF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + }; + return BN_bin2bn(RFC3526_PRIME_8192, sizeof(RFC3526_PRIME_8192), bn); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_ctx.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_ctx.c new file mode 100644 index 000000000..54b799961 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_ctx.c @@ -0,0 +1,361 @@ +/* + * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include "bn_lcl.h" + +/*- + * TODO list + * + * 1. Check a bunch of "(words+1)" type hacks in various bignum functions and + * check they can be safely removed. + * - Check +1 and other ugliness in BN_from_montgomery() + * + * 2. Consider allowing a BN_new_ex() that, at least, lets you specify an + * appropriate 'block' size that will be honoured by bn_expand_internal() to + * prevent piddly little reallocations. OTOH, profiling bignum expansions in + * BN_CTX doesn't show this to be a big issue. + */ + +/* How many bignums are in each "pool item"; */ +#define BN_CTX_POOL_SIZE 16 +/* The stack frame info is resizing, set a first-time expansion size; */ +#define BN_CTX_START_FRAMES 32 + +/***********/ +/* BN_POOL */ +/***********/ + +/* A bundle of bignums that can be linked with other bundles */ +typedef struct bignum_pool_item { + /* The bignum values */ + BIGNUM vals[BN_CTX_POOL_SIZE]; + /* Linked-list admin */ + struct bignum_pool_item *prev, *next; +} BN_POOL_ITEM; +/* A linked-list of bignums grouped in bundles */ +typedef struct bignum_pool { + /* Linked-list admin */ + BN_POOL_ITEM *head, *current, *tail; + /* Stack depth and allocation size */ + unsigned used, size; +} BN_POOL; +static void BN_POOL_init(BN_POOL *); +static void BN_POOL_finish(BN_POOL *); +static BIGNUM *BN_POOL_get(BN_POOL *, int); +static void BN_POOL_release(BN_POOL *, unsigned int); + +/************/ +/* BN_STACK */ +/************/ + +/* A wrapper to manage the "stack frames" */ +typedef struct bignum_ctx_stack { + /* Array of indexes into the bignum stack */ + unsigned int *indexes; + /* Number of stack frames, and the size of the allocated array */ + unsigned int depth, size; +} BN_STACK; +static void BN_STACK_init(BN_STACK *); +static void BN_STACK_finish(BN_STACK *); +static int BN_STACK_push(BN_STACK *, unsigned int); +static unsigned int BN_STACK_pop(BN_STACK *); + +/**********/ +/* BN_CTX */ +/**********/ + +/* The opaque BN_CTX type */ +struct bignum_ctx { + /* The bignum bundles */ + BN_POOL pool; + /* The "stack frames", if you will */ + BN_STACK stack; + /* The number of bignums currently assigned */ + unsigned int used; + /* Depth of stack overflow */ + int err_stack; + /* Block "gets" until an "end" (compatibility behaviour) */ + int too_many; + /* Flags. */ + int flags; +}; + +/* Enable this to find BN_CTX bugs */ +#ifdef BN_CTX_DEBUG +static const char *ctxdbg_cur = NULL; +static void ctxdbg(BN_CTX *ctx) +{ + unsigned int bnidx = 0, fpidx = 0; + BN_POOL_ITEM *item = ctx->pool.head; + BN_STACK *stack = &ctx->stack; + fprintf(stderr, "(%16p): ", ctx); + while (bnidx < ctx->used) { + fprintf(stderr, "%03x ", item->vals[bnidx++ % BN_CTX_POOL_SIZE].dmax); + if (!(bnidx % BN_CTX_POOL_SIZE)) + item = item->next; + } + fprintf(stderr, "\n"); + bnidx = 0; + fprintf(stderr, " : "); + while (fpidx < stack->depth) { + while (bnidx++ < stack->indexes[fpidx]) + fprintf(stderr, " "); + fprintf(stderr, "^^^ "); + bnidx++; + fpidx++; + } + fprintf(stderr, "\n"); +} + +# define CTXDBG_ENTRY(str, ctx) do { \ + ctxdbg_cur = (str); \ + fprintf(stderr,"Starting %s\n", ctxdbg_cur); \ + ctxdbg(ctx); \ + } while(0) +# define CTXDBG_EXIT(ctx) do { \ + fprintf(stderr,"Ending %s\n", ctxdbg_cur); \ + ctxdbg(ctx); \ + } while(0) +# define CTXDBG_RET(ctx,ret) +#else +# define CTXDBG_ENTRY(str, ctx) +# define CTXDBG_EXIT(ctx) +# define CTXDBG_RET(ctx,ret) +#endif + + +BN_CTX *BN_CTX_new(void) +{ + BN_CTX *ret; + + if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) { + BNerr(BN_F_BN_CTX_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + /* Initialise the structure */ + BN_POOL_init(&ret->pool); + BN_STACK_init(&ret->stack); + return ret; +} + +BN_CTX *BN_CTX_secure_new(void) +{ + BN_CTX *ret = BN_CTX_new(); + + if (ret != NULL) + ret->flags = BN_FLG_SECURE; + return ret; +} + +void BN_CTX_free(BN_CTX *ctx) +{ + if (ctx == NULL) + return; +#ifdef BN_CTX_DEBUG + { + BN_POOL_ITEM *pool = ctx->pool.head; + fprintf(stderr, "BN_CTX_free, stack-size=%d, pool-bignums=%d\n", + ctx->stack.size, ctx->pool.size); + fprintf(stderr, "dmaxs: "); + while (pool) { + unsigned loop = 0; + while (loop < BN_CTX_POOL_SIZE) + fprintf(stderr, "%02x ", pool->vals[loop++].dmax); + pool = pool->next; + } + fprintf(stderr, "\n"); + } +#endif + BN_STACK_finish(&ctx->stack); + BN_POOL_finish(&ctx->pool); + OPENSSL_free(ctx); +} + +void BN_CTX_start(BN_CTX *ctx) +{ + CTXDBG_ENTRY("BN_CTX_start", ctx); + /* If we're already overflowing ... */ + if (ctx->err_stack || ctx->too_many) + ctx->err_stack++; + /* (Try to) get a new frame pointer */ + else if (!BN_STACK_push(&ctx->stack, ctx->used)) { + BNerr(BN_F_BN_CTX_START, BN_R_TOO_MANY_TEMPORARY_VARIABLES); + ctx->err_stack++; + } + CTXDBG_EXIT(ctx); +} + +void BN_CTX_end(BN_CTX *ctx) +{ + CTXDBG_ENTRY("BN_CTX_end", ctx); + if (ctx->err_stack) + ctx->err_stack--; + else { + unsigned int fp = BN_STACK_pop(&ctx->stack); + /* Does this stack frame have anything to release? */ + if (fp < ctx->used) + BN_POOL_release(&ctx->pool, ctx->used - fp); + ctx->used = fp; + /* Unjam "too_many" in case "get" had failed */ + ctx->too_many = 0; + } + CTXDBG_EXIT(ctx); +} + +BIGNUM *BN_CTX_get(BN_CTX *ctx) +{ + BIGNUM *ret; + + CTXDBG_ENTRY("BN_CTX_get", ctx); + if (ctx->err_stack || ctx->too_many) + return NULL; + if ((ret = BN_POOL_get(&ctx->pool, ctx->flags)) == NULL) { + /* + * Setting too_many prevents repeated "get" attempts from cluttering + * the error stack. + */ + ctx->too_many = 1; + BNerr(BN_F_BN_CTX_GET, BN_R_TOO_MANY_TEMPORARY_VARIABLES); + return NULL; + } + /* OK, make sure the returned bignum is "zero" */ + BN_zero(ret); + /* clear BN_FLG_CONSTTIME if leaked from previous frames */ + ret->flags &= (~BN_FLG_CONSTTIME); + ctx->used++; + CTXDBG_RET(ctx, ret); + return ret; +} + +/************/ +/* BN_STACK */ +/************/ + +static void BN_STACK_init(BN_STACK *st) +{ + st->indexes = NULL; + st->depth = st->size = 0; +} + +static void BN_STACK_finish(BN_STACK *st) +{ + OPENSSL_free(st->indexes); + st->indexes = NULL; +} + + +static int BN_STACK_push(BN_STACK *st, unsigned int idx) +{ + if (st->depth == st->size) { + /* Need to expand */ + unsigned int newsize = + st->size ? (st->size * 3 / 2) : BN_CTX_START_FRAMES; + unsigned int *newitems; + + if ((newitems = OPENSSL_malloc(sizeof(*newitems) * newsize)) == NULL) { + BNerr(BN_F_BN_STACK_PUSH, ERR_R_MALLOC_FAILURE); + return 0; + } + if (st->depth) + memcpy(newitems, st->indexes, sizeof(*newitems) * st->depth); + OPENSSL_free(st->indexes); + st->indexes = newitems; + st->size = newsize; + } + st->indexes[(st->depth)++] = idx; + return 1; +} + +static unsigned int BN_STACK_pop(BN_STACK *st) +{ + return st->indexes[--(st->depth)]; +} + +/***********/ +/* BN_POOL */ +/***********/ + +static void BN_POOL_init(BN_POOL *p) +{ + p->head = p->current = p->tail = NULL; + p->used = p->size = 0; +} + +static void BN_POOL_finish(BN_POOL *p) +{ + unsigned int loop; + BIGNUM *bn; + + while (p->head) { + for (loop = 0, bn = p->head->vals; loop++ < BN_CTX_POOL_SIZE; bn++) + if (bn->d) + BN_clear_free(bn); + p->current = p->head->next; + OPENSSL_free(p->head); + p->head = p->current; + } +} + + +static BIGNUM *BN_POOL_get(BN_POOL *p, int flag) +{ + BIGNUM *bn; + unsigned int loop; + + /* Full; allocate a new pool item and link it in. */ + if (p->used == p->size) { + BN_POOL_ITEM *item; + + if ((item = OPENSSL_malloc(sizeof(*item))) == NULL) { + BNerr(BN_F_BN_POOL_GET, ERR_R_MALLOC_FAILURE); + return NULL; + } + for (loop = 0, bn = item->vals; loop++ < BN_CTX_POOL_SIZE; bn++) { + bn_init(bn); + if ((flag & BN_FLG_SECURE) != 0) + BN_set_flags(bn, BN_FLG_SECURE); + } + item->prev = p->tail; + item->next = NULL; + + if (p->head == NULL) + p->head = p->current = p->tail = item; + else { + p->tail->next = item; + p->tail = item; + p->current = item; + } + p->size += BN_CTX_POOL_SIZE; + p->used++; + /* Return the first bignum from the new pool */ + return item->vals; + } + + if (!p->used) + p->current = p->head; + else if ((p->used % BN_CTX_POOL_SIZE) == 0) + p->current = p->current->next; + return p->current->vals + ((p->used++) % BN_CTX_POOL_SIZE); +} + +static void BN_POOL_release(BN_POOL *p, unsigned int num) +{ + unsigned int offset = (p->used - 1) % BN_CTX_POOL_SIZE; + + p->used -= num; + while (num--) { + bn_check_top(p->current->vals + offset); + if (offset == 0) { + offset = BN_CTX_POOL_SIZE - 1; + p->current = p->current->prev; + } else + offset--; + } +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_depr.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_depr.c new file mode 100644 index 000000000..58bcf197a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_depr.c @@ -0,0 +1,68 @@ +/* + * Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Support for deprecated functions goes here - static linkage will only + * slurp this code if applications are using them directly. + */ + +#include +#if OPENSSL_API_COMPAT >= 0x00908000L +NON_EMPTY_TRANSLATION_UNIT +#else + +# include +# include +# include "internal/cryptlib.h" +# include "bn_lcl.h" + +BIGNUM *BN_generate_prime(BIGNUM *ret, int bits, int safe, + const BIGNUM *add, const BIGNUM *rem, + void (*callback) (int, int, void *), void *cb_arg) +{ + BN_GENCB cb; + BIGNUM *rnd = NULL; + + BN_GENCB_set_old(&cb, callback, cb_arg); + + if (ret == NULL) { + if ((rnd = BN_new()) == NULL) + goto err; + } else + rnd = ret; + if (!BN_generate_prime_ex(rnd, bits, safe, add, rem, &cb)) + goto err; + + /* we have a prime :-) */ + return rnd; + err: + BN_free(rnd); + return NULL; +} + +int BN_is_prime(const BIGNUM *a, int checks, + void (*callback) (int, int, void *), BN_CTX *ctx_passed, + void *cb_arg) +{ + BN_GENCB cb; + BN_GENCB_set_old(&cb, callback, cb_arg); + return BN_is_prime_ex(a, checks, ctx_passed, &cb); +} + +int BN_is_prime_fasttest(const BIGNUM *a, int checks, + void (*callback) (int, int, void *), + BN_CTX *ctx_passed, void *cb_arg, + int do_trial_division) +{ + BN_GENCB cb; + BN_GENCB_set_old(&cb, callback, cb_arg); + return BN_is_prime_fasttest_ex(a, checks, ctx_passed, + do_trial_division, &cb); +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_dh.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_dh.c new file mode 100644 index 000000000..38acdee23 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_dh.c @@ -0,0 +1,512 @@ +/* + * Copyright 2014-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "bn_lcl.h" +#include "internal/nelem.h" + +#ifndef OPENSSL_NO_DH +#include +#include "internal/bn_dh.h" +/* DH parameters from RFC5114 */ + +# if BN_BITS2 == 64 +static const BN_ULONG dh1024_160_p[] = { + 0xDF1FB2BC2E4A4371ULL, 0xE68CFDA76D4DA708ULL, 0x45BF37DF365C1A65ULL, + 0xA151AF5F0DC8B4BDULL, 0xFAA31A4FF55BCCC0ULL, 0x4EFFD6FAE5644738ULL, + 0x98488E9C219A7372ULL, 0xACCBDD7D90C4BD70ULL, 0x24975C3CD49B83BFULL, + 0x13ECB4AEA9061123ULL, 0x9838EF1E2EE652C0ULL, 0x6073E28675A23D18ULL, + 0x9A6A9DCA52D23B61ULL, 0x52C99FBCFB06A3C6ULL, 0xDE92DE5EAE5D54ECULL, + 0xB10B8F96A080E01DULL +}; + +static const BN_ULONG dh1024_160_g[] = { + 0x855E6EEB22B3B2E5ULL, 0x858F4DCEF97C2A24ULL, 0x2D779D5918D08BC8ULL, + 0xD662A4D18E73AFA3ULL, 0x1DBF0A0169B6A28AULL, 0xA6A24C087A091F53ULL, + 0x909D0D2263F80A76ULL, 0xD7FBD7D3B9A92EE1ULL, 0x5E91547F9E2749F4ULL, + 0x160217B4B01B886AULL, 0x777E690F5504F213ULL, 0x266FEA1E5C41564BULL, + 0xD6406CFF14266D31ULL, 0xF8104DD258AC507FULL, 0x6765A442EFB99905ULL, + 0xA4D1CBD5C3FD3412ULL +}; + +static const BN_ULONG dh1024_160_q[] = { + 0x64B7CB9D49462353ULL, 0x81A8DF278ABA4E7DULL, 0x00000000F518AA87ULL +}; + +static const BN_ULONG dh2048_224_p[] = { + 0x0AC4DFFE0C10E64FULL, 0xCF9DE5384E71B81CULL, 0x7EF363E2FFA31F71ULL, + 0xE3FB73C16B8E75B9ULL, 0xC9B53DCF4BA80A29ULL, 0x23F10B0E16E79763ULL, + 0xC52172E413042E9BULL, 0xBE60E69CC928B2B9ULL, 0x80CD86A1B9E587E8ULL, + 0x315D75E198C641A4ULL, 0xCDF93ACC44328387ULL, 0x15987D9ADC0A486DULL, + 0x7310F7121FD5A074ULL, 0x278273C7DE31EFDCULL, 0x1602E714415D9330ULL, + 0x81286130BC8985DBULL, 0xB3BF8A3170918836ULL, 0x6A00E0A0B9C49708ULL, + 0xC6BA0B2C8BBC27BEULL, 0xC9F98D11ED34DBF6ULL, 0x7AD5B7D0B6C12207ULL, + 0xD91E8FEF55B7394BULL, 0x9037C9EDEFDA4DF8ULL, 0x6D3F8152AD6AC212ULL, + 0x1DE6B85A1274A0A6ULL, 0xEB3D688A309C180EULL, 0xAF9A3C407BA1DF15ULL, + 0xE6FA141DF95A56DBULL, 0xB54B1597B61D0A75ULL, 0xA20D64E5683B9FD1ULL, + 0xD660FAA79559C51FULL, 0xAD107E1E9123A9D0ULL +}; + +static const BN_ULONG dh2048_224_g[] = { + 0x84B890D3191F2BFAULL, 0x81BC087F2A7065B3ULL, 0x19C418E1F6EC0179ULL, + 0x7B5A0F1C71CFFF4CULL, 0xEDFE72FE9B6AA4BDULL, 0x81E1BCFE94B30269ULL, + 0x566AFBB48D6C0191ULL, 0xB539CCE3409D13CDULL, 0x6AA21E7F5F2FF381ULL, + 0xD9E263E4770589EFULL, 0x10E183EDD19963DDULL, 0xB70A8137150B8EEBULL, + 0x051AE3D428C8F8ACULL, 0xBB77A86F0C1AB15BULL, 0x6E3025E316A330EFULL, + 0x19529A45D6F83456ULL, 0xF180EB34118E98D1ULL, 0xB5F6C6B250717CBEULL, + 0x09939D54DA7460CDULL, 0xE247150422EA1ED4ULL, 0xB8A762D0521BC98AULL, + 0xF4D027275AC1348BULL, 0xC17669101999024AULL, 0xBE5E9001A8D66AD7ULL, + 0xC57DB17C620A8652ULL, 0xAB739D7700C29F52ULL, 0xDD921F01A70C4AFAULL, + 0xA6824A4E10B9A6F0ULL, 0x74866A08CFE4FFE3ULL, 0x6CDEBE7B89998CAFULL, + 0x9DF30B5C8FFDAC50ULL, 0xAC4032EF4F2D9AE3ULL +}; + +static const BN_ULONG dh2048_224_q[] = { + 0xBF389A99B36371EBULL, 0x1F80535A4738CEBCULL, 0xC58D93FE99717710ULL, + 0x00000000801C0D34ULL +}; + +static const BN_ULONG dh2048_256_p[] = { + 0xDB094AE91E1A1597ULL, 0x693877FAD7EF09CAULL, 0x6116D2276E11715FULL, + 0xA4B54330C198AF12ULL, 0x75F26375D7014103ULL, 0xC3A3960A54E710C3ULL, + 0xDED4010ABD0BE621ULL, 0xC0B857F689962856ULL, 0xB3CA3F7971506026ULL, + 0x1CCACB83E6B486F6ULL, 0x67E144E514056425ULL, 0xF6A167B5A41825D9ULL, + 0x3AD8347796524D8EULL, 0xF13C6D9A51BFA4ABULL, 0x2D52526735488A0EULL, + 0xB63ACAE1CAA6B790ULL, 0x4FDB70C581B23F76ULL, 0xBC39A0BF12307F5CULL, + 0xB941F54EB1E59BB8ULL, 0x6C5BFC11D45F9088ULL, 0x22E0B1EF4275BF7BULL, + 0x91F9E6725B4758C0ULL, 0x5A8A9D306BCF67EDULL, 0x209E0C6497517ABDULL, + 0x3BF4296D830E9A7CULL, 0x16C3D91134096FAAULL, 0xFAF7DF4561B2AA30ULL, + 0xE00DF8F1D61957D4ULL, 0x5D2CEED4435E3B00ULL, 0x8CEEF608660DD0F2ULL, + 0xFFBBD19C65195999ULL, 0x87A8E61DB4B6663CULL +}; + +static const BN_ULONG dh2048_256_g[] = { + 0x664B4C0F6CC41659ULL, 0x5E2327CFEF98C582ULL, 0xD647D148D4795451ULL, + 0x2F63078490F00EF8ULL, 0x184B523D1DB246C3ULL, 0xC7891428CDC67EB6ULL, + 0x7FD028370DF92B52ULL, 0xB3353BBB64E0EC37ULL, 0xECD06E1557CD0915ULL, + 0xB7D2BBD2DF016199ULL, 0xC8484B1E052588B9ULL, 0xDB2A3B7313D3FE14ULL, + 0xD052B985D182EA0AULL, 0xA4BD1BFFE83B9C80ULL, 0xDFC967C1FB3F2E55ULL, + 0xB5045AF2767164E1ULL, 0x1D14348F6F2F9193ULL, 0x64E67982428EBC83ULL, + 0x8AC376D282D6ED38ULL, 0x777DE62AAAB8A862ULL, 0xDDF463E5E9EC144BULL, + 0x0196F931C77A57F2ULL, 0xA55AE31341000A65ULL, 0x901228F8C28CBB18ULL, + 0xBC3773BF7E8C6F62ULL, 0xBE3A6C1B0C6B47B1ULL, 0xFF4FED4AAC0BB555ULL, + 0x10DBC15077BE463FULL, 0x07F4793A1A0BA125ULL, 0x4CA7B18F21EF2054ULL, + 0x2E77506660EDBD48ULL, 0x3FB32C9B73134D0BULL +}; + +static const BN_ULONG dh2048_256_q[] = { + 0xA308B0FE64F5FBD3ULL, 0x99B1A47D1EB3750BULL, 0xB447997640129DA2ULL, + 0x8CF83642A709A097ULL +}; + +/* Primes from RFC 7919 */ +static const BN_ULONG ffdhe2048_p[] = { + 0xFFFFFFFFFFFFFFFFULL, 0x886B423861285C97ULL, 0xC6F34A26C1B2EFFAULL, + 0xC58EF1837D1683B2ULL, 0x3BB5FCBC2EC22005ULL, 0xC3FE3B1B4C6FAD73ULL, + 0x8E4F1232EEF28183ULL, 0x9172FE9CE98583FFULL, 0xC03404CD28342F61ULL, + 0x9E02FCE1CDF7E2ECULL, 0x0B07A7C8EE0A6D70ULL, 0xAE56EDE76372BB19ULL, + 0x1D4F42A3DE394DF4ULL, 0xB96ADAB760D7F468ULL, 0xD108A94BB2C8E3FBULL, + 0xBC0AB182B324FB61ULL, 0x30ACCA4F483A797AULL, 0x1DF158A136ADE735ULL, + 0xE2A689DAF3EFE872ULL, 0x984F0C70E0E68B77ULL, 0xB557135E7F57C935ULL, + 0x856365553DED1AF3ULL, 0x2433F51F5F066ED0ULL, 0xD3DF1ED5D5FD6561ULL, + 0xF681B202AEC4617AULL, 0x7D2FE363630C75D8ULL, 0xCC939DCE249B3EF9ULL, + 0xA9E13641146433FBULL, 0xD8B9C583CE2D3695ULL, 0xAFDC5620273D3CF1ULL, + 0xADF85458A2BB4A9AULL, 0xFFFFFFFFFFFFFFFFULL +}; + +static const BN_ULONG ffdhe3072_p[] = { + 0xFFFFFFFFFFFFFFFFULL, 0x25E41D2B66C62E37ULL, 0x3C1B20EE3FD59D7CULL, + 0x0ABCD06BFA53DDEFULL, 0x1DBF9A42D5C4484EULL, 0xABC521979B0DEADAULL, + 0xE86D2BC522363A0DULL, 0x5CAE82AB9C9DF69EULL, 0x64F2E21E71F54BFFULL, + 0xF4FD4452E2D74DD3ULL, 0xB4130C93BC437944ULL, 0xAEFE130985139270ULL, + 0x598CB0FAC186D91CULL, 0x7AD91D2691F7F7EEULL, 0x61B46FC9D6E6C907ULL, + 0xBC34F4DEF99C0238ULL, 0xDE355B3B6519035BULL, 0x886B4238611FCFDCULL, + 0xC6F34A26C1B2EFFAULL, 0xC58EF1837D1683B2ULL, 0x3BB5FCBC2EC22005ULL, + 0xC3FE3B1B4C6FAD73ULL, 0x8E4F1232EEF28183ULL, 0x9172FE9CE98583FFULL, + 0xC03404CD28342F61ULL, 0x9E02FCE1CDF7E2ECULL, 0x0B07A7C8EE0A6D70ULL, + 0xAE56EDE76372BB19ULL, 0x1D4F42A3DE394DF4ULL, 0xB96ADAB760D7F468ULL, + 0xD108A94BB2C8E3FBULL, 0xBC0AB182B324FB61ULL, 0x30ACCA4F483A797AULL, + 0x1DF158A136ADE735ULL, 0xE2A689DAF3EFE872ULL, 0x984F0C70E0E68B77ULL, + 0xB557135E7F57C935ULL, 0x856365553DED1AF3ULL, 0x2433F51F5F066ED0ULL, + 0xD3DF1ED5D5FD6561ULL, 0xF681B202AEC4617AULL, 0x7D2FE363630C75D8ULL, + 0xCC939DCE249B3EF9ULL, 0xA9E13641146433FBULL, 0xD8B9C583CE2D3695ULL, + 0xAFDC5620273D3CF1ULL, 0xADF85458A2BB4A9AULL, 0xFFFFFFFFFFFFFFFFULL +}; + +static const BN_ULONG ffdhe4096_p[] = { + 0xFFFFFFFFFFFFFFFFULL, 0xC68A007E5E655F6AULL, 0x4DB5A851F44182E1ULL, + 0x8EC9B55A7F88A46BULL, 0x0A8291CDCEC97DCFULL, 0x2A4ECEA9F98D0ACCULL, + 0x1A1DB93D7140003CULL, 0x092999A333CB8B7AULL, 0x6DC778F971AD0038ULL, + 0xA907600A918130C4ULL, 0xED6A1E012D9E6832ULL, 0x7135C886EFB4318AULL, + 0x87F55BA57E31CC7AULL, 0x7763CF1D55034004ULL, 0xAC7D5F42D69F6D18ULL, + 0x7930E9E4E58857B6ULL, 0x6E6F52C3164DF4FBULL, 0x25E41D2B669E1EF1ULL, + 0x3C1B20EE3FD59D7CULL, 0x0ABCD06BFA53DDEFULL, 0x1DBF9A42D5C4484EULL, + 0xABC521979B0DEADAULL, 0xE86D2BC522363A0DULL, 0x5CAE82AB9C9DF69EULL, + 0x64F2E21E71F54BFFULL, 0xF4FD4452E2D74DD3ULL, 0xB4130C93BC437944ULL, + 0xAEFE130985139270ULL, 0x598CB0FAC186D91CULL, 0x7AD91D2691F7F7EEULL, + 0x61B46FC9D6E6C907ULL, 0xBC34F4DEF99C0238ULL, 0xDE355B3B6519035BULL, + 0x886B4238611FCFDCULL, 0xC6F34A26C1B2EFFAULL, 0xC58EF1837D1683B2ULL, + 0x3BB5FCBC2EC22005ULL, 0xC3FE3B1B4C6FAD73ULL, 0x8E4F1232EEF28183ULL, + 0x9172FE9CE98583FFULL, 0xC03404CD28342F61ULL, 0x9E02FCE1CDF7E2ECULL, + 0x0B07A7C8EE0A6D70ULL, 0xAE56EDE76372BB19ULL, 0x1D4F42A3DE394DF4ULL, + 0xB96ADAB760D7F468ULL, 0xD108A94BB2C8E3FBULL, 0xBC0AB182B324FB61ULL, + 0x30ACCA4F483A797AULL, 0x1DF158A136ADE735ULL, 0xE2A689DAF3EFE872ULL, + 0x984F0C70E0E68B77ULL, 0xB557135E7F57C935ULL, 0x856365553DED1AF3ULL, + 0x2433F51F5F066ED0ULL, 0xD3DF1ED5D5FD6561ULL, 0xF681B202AEC4617AULL, + 0x7D2FE363630C75D8ULL, 0xCC939DCE249B3EF9ULL, 0xA9E13641146433FBULL, + 0xD8B9C583CE2D3695ULL, 0xAFDC5620273D3CF1ULL, 0xADF85458A2BB4A9AULL, + 0xFFFFFFFFFFFFFFFFULL +}; + +static const BN_ULONG ffdhe6144_p[] = { + 0xFFFFFFFFFFFFFFFFULL, 0xA40E329CD0E40E65ULL, 0xA41D570D7938DAD4ULL, + 0x62A69526D43161C1ULL, 0x3FDD4A8E9ADB1E69ULL, 0x5B3B71F9DC6B80D6ULL, + 0xEC9D1810C6272B04ULL, 0x8CCF2DD5CACEF403ULL, 0xE49F5235C95B9117ULL, + 0x505DC82DB854338AULL, 0x62292C311562A846ULL, 0xD72B03746AE77F5EULL, + 0xF9C9091B462D538CULL, 0x0AE8DB5847A67CBEULL, 0xB3A739C122611682ULL, + 0xEEAAC0232A281BF6ULL, 0x94C6651E77CAF992ULL, 0x763E4E4B94B2BBC1ULL, + 0x587E38DA0077D9B4ULL, 0x7FB29F8C183023C3ULL, 0x0ABEC1FFF9E3A26EULL, + 0xA00EF092350511E3ULL, 0xB855322EDB6340D8ULL, 0xA52471F7A9A96910ULL, + 0x388147FB4CFDB477ULL, 0x9B1F5C3E4E46041FULL, 0xCDAD0657FCCFEC71ULL, + 0xB38E8C334C701C3AULL, 0x917BDD64B1C0FD4CULL, 0x3BB454329B7624C8ULL, + 0x23BA4442CAF53EA6ULL, 0x4E677D2C38532A3AULL, 0x0BFD64B645036C7AULL, + 0xC68A007E5E0DD902ULL, 0x4DB5A851F44182E1ULL, 0x8EC9B55A7F88A46BULL, + 0x0A8291CDCEC97DCFULL, 0x2A4ECEA9F98D0ACCULL, 0x1A1DB93D7140003CULL, + 0x092999A333CB8B7AULL, 0x6DC778F971AD0038ULL, 0xA907600A918130C4ULL, + 0xED6A1E012D9E6832ULL, 0x7135C886EFB4318AULL, 0x87F55BA57E31CC7AULL, + 0x7763CF1D55034004ULL, 0xAC7D5F42D69F6D18ULL, 0x7930E9E4E58857B6ULL, + 0x6E6F52C3164DF4FBULL, 0x25E41D2B669E1EF1ULL, 0x3C1B20EE3FD59D7CULL, + 0x0ABCD06BFA53DDEFULL, 0x1DBF9A42D5C4484EULL, 0xABC521979B0DEADAULL, + 0xE86D2BC522363A0DULL, 0x5CAE82AB9C9DF69EULL, 0x64F2E21E71F54BFFULL, + 0xF4FD4452E2D74DD3ULL, 0xB4130C93BC437944ULL, 0xAEFE130985139270ULL, + 0x598CB0FAC186D91CULL, 0x7AD91D2691F7F7EEULL, 0x61B46FC9D6E6C907ULL, + 0xBC34F4DEF99C0238ULL, 0xDE355B3B6519035BULL, 0x886B4238611FCFDCULL, + 0xC6F34A26C1B2EFFAULL, 0xC58EF1837D1683B2ULL, 0x3BB5FCBC2EC22005ULL, + 0xC3FE3B1B4C6FAD73ULL, 0x8E4F1232EEF28183ULL, 0x9172FE9CE98583FFULL, + 0xC03404CD28342F61ULL, 0x9E02FCE1CDF7E2ECULL, 0x0B07A7C8EE0A6D70ULL, + 0xAE56EDE76372BB19ULL, 0x1D4F42A3DE394DF4ULL, 0xB96ADAB760D7F468ULL, + 0xD108A94BB2C8E3FBULL, 0xBC0AB182B324FB61ULL, 0x30ACCA4F483A797AULL, + 0x1DF158A136ADE735ULL, 0xE2A689DAF3EFE872ULL, 0x984F0C70E0E68B77ULL, + 0xB557135E7F57C935ULL, 0x856365553DED1AF3ULL, 0x2433F51F5F066ED0ULL, + 0xD3DF1ED5D5FD6561ULL, 0xF681B202AEC4617AULL, 0x7D2FE363630C75D8ULL, + 0xCC939DCE249B3EF9ULL, 0xA9E13641146433FBULL, 0xD8B9C583CE2D3695ULL, + 0xAFDC5620273D3CF1ULL, 0xADF85458A2BB4A9AULL, 0xFFFFFFFFFFFFFFFFULL +}; + +static const BN_ULONG ffdhe8192_p[] = { + 0xFFFFFFFFFFFFFFFFULL, 0xD68C8BB7C5C6424CULL, 0x011E2A94838FF88CULL, + 0x0822E506A9F4614EULL, 0x97D11D49F7A8443DULL, 0xA6BBFDE530677F0DULL, + 0x2F741EF8C1FE86FEULL, 0xFAFABE1C5D71A87EULL, 0xDED2FBABFBE58A30ULL, + 0xB6855DFE72B0A66EULL, 0x1EFC8CE0BA8A4FE8ULL, 0x83F81D4A3F2FA457ULL, + 0xA1FE3075A577E231ULL, 0xD5B8019488D9C0A0ULL, 0x624816CDAD9A95F9ULL, + 0x99E9E31650C1217BULL, 0x51AA691E0E423CFCULL, 0x1C217E6C3826E52CULL, + 0x51A8A93109703FEEULL, 0xBB7099876A460E74ULL, 0x541FC68C9C86B022ULL, + 0x59160CC046FD8251ULL, 0x2846C0BA35C35F5CULL, 0x54504AC78B758282ULL, + 0x29388839D2AF05E4ULL, 0xCB2C0F1CC01BD702ULL, 0x555B2F747C932665ULL, + 0x86B63142A3AB8829ULL, 0x0B8CC3BDF64B10EFULL, 0x687FEB69EDD1CC5EULL, + 0xFDB23FCEC9509D43ULL, 0x1E425A31D951AE64ULL, 0x36AD004CF600C838ULL, + 0xA40E329CCFF46AAAULL, 0xA41D570D7938DAD4ULL, 0x62A69526D43161C1ULL, + 0x3FDD4A8E9ADB1E69ULL, 0x5B3B71F9DC6B80D6ULL, 0xEC9D1810C6272B04ULL, + 0x8CCF2DD5CACEF403ULL, 0xE49F5235C95B9117ULL, 0x505DC82DB854338AULL, + 0x62292C311562A846ULL, 0xD72B03746AE77F5EULL, 0xF9C9091B462D538CULL, + 0x0AE8DB5847A67CBEULL, 0xB3A739C122611682ULL, 0xEEAAC0232A281BF6ULL, + 0x94C6651E77CAF992ULL, 0x763E4E4B94B2BBC1ULL, 0x587E38DA0077D9B4ULL, + 0x7FB29F8C183023C3ULL, 0x0ABEC1FFF9E3A26EULL, 0xA00EF092350511E3ULL, + 0xB855322EDB6340D8ULL, 0xA52471F7A9A96910ULL, 0x388147FB4CFDB477ULL, + 0x9B1F5C3E4E46041FULL, 0xCDAD0657FCCFEC71ULL, 0xB38E8C334C701C3AULL, + 0x917BDD64B1C0FD4CULL, 0x3BB454329B7624C8ULL, 0x23BA4442CAF53EA6ULL, + 0x4E677D2C38532A3AULL, 0x0BFD64B645036C7AULL, 0xC68A007E5E0DD902ULL, + 0x4DB5A851F44182E1ULL, 0x8EC9B55A7F88A46BULL, 0x0A8291CDCEC97DCFULL, + 0x2A4ECEA9F98D0ACCULL, 0x1A1DB93D7140003CULL, 0x092999A333CB8B7AULL, + 0x6DC778F971AD0038ULL, 0xA907600A918130C4ULL, 0xED6A1E012D9E6832ULL, + 0x7135C886EFB4318AULL, 0x87F55BA57E31CC7AULL, 0x7763CF1D55034004ULL, + 0xAC7D5F42D69F6D18ULL, 0x7930E9E4E58857B6ULL, 0x6E6F52C3164DF4FBULL, + 0x25E41D2B669E1EF1ULL, 0x3C1B20EE3FD59D7CULL, 0x0ABCD06BFA53DDEFULL, + 0x1DBF9A42D5C4484EULL, 0xABC521979B0DEADAULL, 0xE86D2BC522363A0DULL, + 0x5CAE82AB9C9DF69EULL, 0x64F2E21E71F54BFFULL, 0xF4FD4452E2D74DD3ULL, + 0xB4130C93BC437944ULL, 0xAEFE130985139270ULL, 0x598CB0FAC186D91CULL, + 0x7AD91D2691F7F7EEULL, 0x61B46FC9D6E6C907ULL, 0xBC34F4DEF99C0238ULL, + 0xDE355B3B6519035BULL, 0x886B4238611FCFDCULL, 0xC6F34A26C1B2EFFAULL, + 0xC58EF1837D1683B2ULL, 0x3BB5FCBC2EC22005ULL, 0xC3FE3B1B4C6FAD73ULL, + 0x8E4F1232EEF28183ULL, 0x9172FE9CE98583FFULL, 0xC03404CD28342F61ULL, + 0x9E02FCE1CDF7E2ECULL, 0x0B07A7C8EE0A6D70ULL, 0xAE56EDE76372BB19ULL, + 0x1D4F42A3DE394DF4ULL, 0xB96ADAB760D7F468ULL, 0xD108A94BB2C8E3FBULL, + 0xBC0AB182B324FB61ULL, 0x30ACCA4F483A797AULL, 0x1DF158A136ADE735ULL, + 0xE2A689DAF3EFE872ULL, 0x984F0C70E0E68B77ULL, 0xB557135E7F57C935ULL, + 0x856365553DED1AF3ULL, 0x2433F51F5F066ED0ULL, 0xD3DF1ED5D5FD6561ULL, + 0xF681B202AEC4617AULL, 0x7D2FE363630C75D8ULL, 0xCC939DCE249B3EF9ULL, + 0xA9E13641146433FBULL, 0xD8B9C583CE2D3695ULL, 0xAFDC5620273D3CF1ULL, + 0xADF85458A2BB4A9AULL, 0xFFFFFFFFFFFFFFFFULL +}; + +# elif BN_BITS2 == 32 + +static const BN_ULONG dh1024_160_p[] = { + 0x2E4A4371, 0xDF1FB2BC, 0x6D4DA708, 0xE68CFDA7, 0x365C1A65, 0x45BF37DF, + 0x0DC8B4BD, 0xA151AF5F, 0xF55BCCC0, 0xFAA31A4F, 0xE5644738, 0x4EFFD6FA, + 0x219A7372, 0x98488E9C, 0x90C4BD70, 0xACCBDD7D, 0xD49B83BF, 0x24975C3C, + 0xA9061123, 0x13ECB4AE, 0x2EE652C0, 0x9838EF1E, 0x75A23D18, 0x6073E286, + 0x52D23B61, 0x9A6A9DCA, 0xFB06A3C6, 0x52C99FBC, 0xAE5D54EC, 0xDE92DE5E, + 0xA080E01D, 0xB10B8F96 +}; + +static const BN_ULONG dh1024_160_g[] = { + 0x22B3B2E5, 0x855E6EEB, 0xF97C2A24, 0x858F4DCE, 0x18D08BC8, 0x2D779D59, + 0x8E73AFA3, 0xD662A4D1, 0x69B6A28A, 0x1DBF0A01, 0x7A091F53, 0xA6A24C08, + 0x63F80A76, 0x909D0D22, 0xB9A92EE1, 0xD7FBD7D3, 0x9E2749F4, 0x5E91547F, + 0xB01B886A, 0x160217B4, 0x5504F213, 0x777E690F, 0x5C41564B, 0x266FEA1E, + 0x14266D31, 0xD6406CFF, 0x58AC507F, 0xF8104DD2, 0xEFB99905, 0x6765A442, + 0xC3FD3412, 0xA4D1CBD5 +}; + +static const BN_ULONG dh1024_160_q[] = { + 0x49462353, 0x64B7CB9D, 0x8ABA4E7D, 0x81A8DF27, 0xF518AA87 +}; + +static const BN_ULONG dh2048_224_p[] = { + 0x0C10E64F, 0x0AC4DFFE, 0x4E71B81C, 0xCF9DE538, 0xFFA31F71, 0x7EF363E2, + 0x6B8E75B9, 0xE3FB73C1, 0x4BA80A29, 0xC9B53DCF, 0x16E79763, 0x23F10B0E, + 0x13042E9B, 0xC52172E4, 0xC928B2B9, 0xBE60E69C, 0xB9E587E8, 0x80CD86A1, + 0x98C641A4, 0x315D75E1, 0x44328387, 0xCDF93ACC, 0xDC0A486D, 0x15987D9A, + 0x1FD5A074, 0x7310F712, 0xDE31EFDC, 0x278273C7, 0x415D9330, 0x1602E714, + 0xBC8985DB, 0x81286130, 0x70918836, 0xB3BF8A31, 0xB9C49708, 0x6A00E0A0, + 0x8BBC27BE, 0xC6BA0B2C, 0xED34DBF6, 0xC9F98D11, 0xB6C12207, 0x7AD5B7D0, + 0x55B7394B, 0xD91E8FEF, 0xEFDA4DF8, 0x9037C9ED, 0xAD6AC212, 0x6D3F8152, + 0x1274A0A6, 0x1DE6B85A, 0x309C180E, 0xEB3D688A, 0x7BA1DF15, 0xAF9A3C40, + 0xF95A56DB, 0xE6FA141D, 0xB61D0A75, 0xB54B1597, 0x683B9FD1, 0xA20D64E5, + 0x9559C51F, 0xD660FAA7, 0x9123A9D0, 0xAD107E1E +}; + +static const BN_ULONG dh2048_224_g[] = { + 0x191F2BFA, 0x84B890D3, 0x2A7065B3, 0x81BC087F, 0xF6EC0179, 0x19C418E1, + 0x71CFFF4C, 0x7B5A0F1C, 0x9B6AA4BD, 0xEDFE72FE, 0x94B30269, 0x81E1BCFE, + 0x8D6C0191, 0x566AFBB4, 0x409D13CD, 0xB539CCE3, 0x5F2FF381, 0x6AA21E7F, + 0x770589EF, 0xD9E263E4, 0xD19963DD, 0x10E183ED, 0x150B8EEB, 0xB70A8137, + 0x28C8F8AC, 0x051AE3D4, 0x0C1AB15B, 0xBB77A86F, 0x16A330EF, 0x6E3025E3, + 0xD6F83456, 0x19529A45, 0x118E98D1, 0xF180EB34, 0x50717CBE, 0xB5F6C6B2, + 0xDA7460CD, 0x09939D54, 0x22EA1ED4, 0xE2471504, 0x521BC98A, 0xB8A762D0, + 0x5AC1348B, 0xF4D02727, 0x1999024A, 0xC1766910, 0xA8D66AD7, 0xBE5E9001, + 0x620A8652, 0xC57DB17C, 0x00C29F52, 0xAB739D77, 0xA70C4AFA, 0xDD921F01, + 0x10B9A6F0, 0xA6824A4E, 0xCFE4FFE3, 0x74866A08, 0x89998CAF, 0x6CDEBE7B, + 0x8FFDAC50, 0x9DF30B5C, 0x4F2D9AE3, 0xAC4032EF +}; + +static const BN_ULONG dh2048_224_q[] = { + 0xB36371EB, 0xBF389A99, 0x4738CEBC, 0x1F80535A, 0x99717710, 0xC58D93FE, + 0x801C0D34 +}; + +static const BN_ULONG dh2048_256_p[] = { + 0x1E1A1597, 0xDB094AE9, 0xD7EF09CA, 0x693877FA, 0x6E11715F, 0x6116D227, + 0xC198AF12, 0xA4B54330, 0xD7014103, 0x75F26375, 0x54E710C3, 0xC3A3960A, + 0xBD0BE621, 0xDED4010A, 0x89962856, 0xC0B857F6, 0x71506026, 0xB3CA3F79, + 0xE6B486F6, 0x1CCACB83, 0x14056425, 0x67E144E5, 0xA41825D9, 0xF6A167B5, + 0x96524D8E, 0x3AD83477, 0x51BFA4AB, 0xF13C6D9A, 0x35488A0E, 0x2D525267, + 0xCAA6B790, 0xB63ACAE1, 0x81B23F76, 0x4FDB70C5, 0x12307F5C, 0xBC39A0BF, + 0xB1E59BB8, 0xB941F54E, 0xD45F9088, 0x6C5BFC11, 0x4275BF7B, 0x22E0B1EF, + 0x5B4758C0, 0x91F9E672, 0x6BCF67ED, 0x5A8A9D30, 0x97517ABD, 0x209E0C64, + 0x830E9A7C, 0x3BF4296D, 0x34096FAA, 0x16C3D911, 0x61B2AA30, 0xFAF7DF45, + 0xD61957D4, 0xE00DF8F1, 0x435E3B00, 0x5D2CEED4, 0x660DD0F2, 0x8CEEF608, + 0x65195999, 0xFFBBD19C, 0xB4B6663C, 0x87A8E61D +}; + +static const BN_ULONG dh2048_256_g[] = { + 0x6CC41659, 0x664B4C0F, 0xEF98C582, 0x5E2327CF, 0xD4795451, 0xD647D148, + 0x90F00EF8, 0x2F630784, 0x1DB246C3, 0x184B523D, 0xCDC67EB6, 0xC7891428, + 0x0DF92B52, 0x7FD02837, 0x64E0EC37, 0xB3353BBB, 0x57CD0915, 0xECD06E15, + 0xDF016199, 0xB7D2BBD2, 0x052588B9, 0xC8484B1E, 0x13D3FE14, 0xDB2A3B73, + 0xD182EA0A, 0xD052B985, 0xE83B9C80, 0xA4BD1BFF, 0xFB3F2E55, 0xDFC967C1, + 0x767164E1, 0xB5045AF2, 0x6F2F9193, 0x1D14348F, 0x428EBC83, 0x64E67982, + 0x82D6ED38, 0x8AC376D2, 0xAAB8A862, 0x777DE62A, 0xE9EC144B, 0xDDF463E5, + 0xC77A57F2, 0x0196F931, 0x41000A65, 0xA55AE313, 0xC28CBB18, 0x901228F8, + 0x7E8C6F62, 0xBC3773BF, 0x0C6B47B1, 0xBE3A6C1B, 0xAC0BB555, 0xFF4FED4A, + 0x77BE463F, 0x10DBC150, 0x1A0BA125, 0x07F4793A, 0x21EF2054, 0x4CA7B18F, + 0x60EDBD48, 0x2E775066, 0x73134D0B, 0x3FB32C9B +}; + +static const BN_ULONG dh2048_256_q[] = { + 0x64F5FBD3, 0xA308B0FE, 0x1EB3750B, 0x99B1A47D, 0x40129DA2, 0xB4479976, + 0xA709A097, 0x8CF83642 +}; + +/* Primes from RFC 7919 */ + +static const BN_ULONG ffdhe2048_p[] = { + 0xFFFFFFFF, 0xFFFFFFFF, 0x61285C97, 0x886B4238, 0xC1B2EFFA, 0xC6F34A26, + 0x7D1683B2, 0xC58EF183, 0x2EC22005, 0x3BB5FCBC, 0x4C6FAD73, 0xC3FE3B1B, + 0xEEF28183, 0x8E4F1232, 0xE98583FF, 0x9172FE9C, 0x28342F61, 0xC03404CD, + 0xCDF7E2EC, 0x9E02FCE1, 0xEE0A6D70, 0x0B07A7C8, 0x6372BB19, 0xAE56EDE7, + 0xDE394DF4, 0x1D4F42A3, 0x60D7F468, 0xB96ADAB7, 0xB2C8E3FB, 0xD108A94B, + 0xB324FB61, 0xBC0AB182, 0x483A797A, 0x30ACCA4F, 0x36ADE735, 0x1DF158A1, + 0xF3EFE872, 0xE2A689DA, 0xE0E68B77, 0x984F0C70, 0x7F57C935, 0xB557135E, + 0x3DED1AF3, 0x85636555, 0x5F066ED0, 0x2433F51F, 0xD5FD6561, 0xD3DF1ED5, + 0xAEC4617A, 0xF681B202, 0x630C75D8, 0x7D2FE363, 0x249B3EF9, 0xCC939DCE, + 0x146433FB, 0xA9E13641, 0xCE2D3695, 0xD8B9C583, 0x273D3CF1, 0xAFDC5620, + 0xA2BB4A9A, 0xADF85458, 0xFFFFFFFF, 0xFFFFFFFF +}; + +static const BN_ULONG ffdhe3072_p[] = { + 0xFFFFFFFF, 0xFFFFFFFF, 0x66C62E37, 0x25E41D2B, 0x3FD59D7C, 0x3C1B20EE, + 0xFA53DDEF, 0x0ABCD06B, 0xD5C4484E, 0x1DBF9A42, 0x9B0DEADA, 0xABC52197, + 0x22363A0D, 0xE86D2BC5, 0x9C9DF69E, 0x5CAE82AB, 0x71F54BFF, 0x64F2E21E, + 0xE2D74DD3, 0xF4FD4452, 0xBC437944, 0xB4130C93, 0x85139270, 0xAEFE1309, + 0xC186D91C, 0x598CB0FA, 0x91F7F7EE, 0x7AD91D26, 0xD6E6C907, 0x61B46FC9, + 0xF99C0238, 0xBC34F4DE, 0x6519035B, 0xDE355B3B, 0x611FCFDC, 0x886B4238, + 0xC1B2EFFA, 0xC6F34A26, 0x7D1683B2, 0xC58EF183, 0x2EC22005, 0x3BB5FCBC, + 0x4C6FAD73, 0xC3FE3B1B, 0xEEF28183, 0x8E4F1232, 0xE98583FF, 0x9172FE9C, + 0x28342F61, 0xC03404CD, 0xCDF7E2EC, 0x9E02FCE1, 0xEE0A6D70, 0x0B07A7C8, + 0x6372BB19, 0xAE56EDE7, 0xDE394DF4, 0x1D4F42A3, 0x60D7F468, 0xB96ADAB7, + 0xB2C8E3FB, 0xD108A94B, 0xB324FB61, 0xBC0AB182, 0x483A797A, 0x30ACCA4F, + 0x36ADE735, 0x1DF158A1, 0xF3EFE872, 0xE2A689DA, 0xE0E68B77, 0x984F0C70, + 0x7F57C935, 0xB557135E, 0x3DED1AF3, 0x85636555, 0x5F066ED0, 0x2433F51F, + 0xD5FD6561, 0xD3DF1ED5, 0xAEC4617A, 0xF681B202, 0x630C75D8, 0x7D2FE363, + 0x249B3EF9, 0xCC939DCE, 0x146433FB, 0xA9E13641, 0xCE2D3695, 0xD8B9C583, + 0x273D3CF1, 0xAFDC5620, 0xA2BB4A9A, 0xADF85458, 0xFFFFFFFF, 0xFFFFFFFF +}; + +static const BN_ULONG ffdhe4096_p[] = { + 0xFFFFFFFF, 0xFFFFFFFF, 0x5E655F6A, 0xC68A007E, 0xF44182E1, 0x4DB5A851, + 0x7F88A46B, 0x8EC9B55A, 0xCEC97DCF, 0x0A8291CD, 0xF98D0ACC, 0x2A4ECEA9, + 0x7140003C, 0x1A1DB93D, 0x33CB8B7A, 0x092999A3, 0x71AD0038, 0x6DC778F9, + 0x918130C4, 0xA907600A, 0x2D9E6832, 0xED6A1E01, 0xEFB4318A, 0x7135C886, + 0x7E31CC7A, 0x87F55BA5, 0x55034004, 0x7763CF1D, 0xD69F6D18, 0xAC7D5F42, + 0xE58857B6, 0x7930E9E4, 0x164DF4FB, 0x6E6F52C3, 0x669E1EF1, 0x25E41D2B, + 0x3FD59D7C, 0x3C1B20EE, 0xFA53DDEF, 0x0ABCD06B, 0xD5C4484E, 0x1DBF9A42, + 0x9B0DEADA, 0xABC52197, 0x22363A0D, 0xE86D2BC5, 0x9C9DF69E, 0x5CAE82AB, + 0x71F54BFF, 0x64F2E21E, 0xE2D74DD3, 0xF4FD4452, 0xBC437944, 0xB4130C93, + 0x85139270, 0xAEFE1309, 0xC186D91C, 0x598CB0FA, 0x91F7F7EE, 0x7AD91D26, + 0xD6E6C907, 0x61B46FC9, 0xF99C0238, 0xBC34F4DE, 0x6519035B, 0xDE355B3B, + 0x611FCFDC, 0x886B4238, 0xC1B2EFFA, 0xC6F34A26, 0x7D1683B2, 0xC58EF183, + 0x2EC22005, 0x3BB5FCBC, 0x4C6FAD73, 0xC3FE3B1B, 0xEEF28183, 0x8E4F1232, + 0xE98583FF, 0x9172FE9C, 0x28342F61, 0xC03404CD, 0xCDF7E2EC, 0x9E02FCE1, + 0xEE0A6D70, 0x0B07A7C8, 0x6372BB19, 0xAE56EDE7, 0xDE394DF4, 0x1D4F42A3, + 0x60D7F468, 0xB96ADAB7, 0xB2C8E3FB, 0xD108A94B, 0xB324FB61, 0xBC0AB182, + 0x483A797A, 0x30ACCA4F, 0x36ADE735, 0x1DF158A1, 0xF3EFE872, 0xE2A689DA, + 0xE0E68B77, 0x984F0C70, 0x7F57C935, 0xB557135E, 0x3DED1AF3, 0x85636555, + 0x5F066ED0, 0x2433F51F, 0xD5FD6561, 0xD3DF1ED5, 0xAEC4617A, 0xF681B202, + 0x630C75D8, 0x7D2FE363, 0x249B3EF9, 0xCC939DCE, 0x146433FB, 0xA9E13641, + 0xCE2D3695, 0xD8B9C583, 0x273D3CF1, 0xAFDC5620, 0xA2BB4A9A, 0xADF85458, + 0xFFFFFFFF, 0xFFFFFFFF +}; + +static const BN_ULONG ffdhe6144_p[] = { + 0xFFFFFFFF, 0xFFFFFFFF, 0xD0E40E65, 0xA40E329C, 0x7938DAD4, 0xA41D570D, + 0xD43161C1, 0x62A69526, 0x9ADB1E69, 0x3FDD4A8E, 0xDC6B80D6, 0x5B3B71F9, + 0xC6272B04, 0xEC9D1810, 0xCACEF403, 0x8CCF2DD5, 0xC95B9117, 0xE49F5235, + 0xB854338A, 0x505DC82D, 0x1562A846, 0x62292C31, 0x6AE77F5E, 0xD72B0374, + 0x462D538C, 0xF9C9091B, 0x47A67CBE, 0x0AE8DB58, 0x22611682, 0xB3A739C1, + 0x2A281BF6, 0xEEAAC023, 0x77CAF992, 0x94C6651E, 0x94B2BBC1, 0x763E4E4B, + 0x0077D9B4, 0x587E38DA, 0x183023C3, 0x7FB29F8C, 0xF9E3A26E, 0x0ABEC1FF, + 0x350511E3, 0xA00EF092, 0xDB6340D8, 0xB855322E, 0xA9A96910, 0xA52471F7, + 0x4CFDB477, 0x388147FB, 0x4E46041F, 0x9B1F5C3E, 0xFCCFEC71, 0xCDAD0657, + 0x4C701C3A, 0xB38E8C33, 0xB1C0FD4C, 0x917BDD64, 0x9B7624C8, 0x3BB45432, + 0xCAF53EA6, 0x23BA4442, 0x38532A3A, 0x4E677D2C, 0x45036C7A, 0x0BFD64B6, + 0x5E0DD902, 0xC68A007E, 0xF44182E1, 0x4DB5A851, 0x7F88A46B, 0x8EC9B55A, + 0xCEC97DCF, 0x0A8291CD, 0xF98D0ACC, 0x2A4ECEA9, 0x7140003C, 0x1A1DB93D, + 0x33CB8B7A, 0x092999A3, 0x71AD0038, 0x6DC778F9, 0x918130C4, 0xA907600A, + 0x2D9E6832, 0xED6A1E01, 0xEFB4318A, 0x7135C886, 0x7E31CC7A, 0x87F55BA5, + 0x55034004, 0x7763CF1D, 0xD69F6D18, 0xAC7D5F42, 0xE58857B6, 0x7930E9E4, + 0x164DF4FB, 0x6E6F52C3, 0x669E1EF1, 0x25E41D2B, 0x3FD59D7C, 0x3C1B20EE, + 0xFA53DDEF, 0x0ABCD06B, 0xD5C4484E, 0x1DBF9A42, 0x9B0DEADA, 0xABC52197, + 0x22363A0D, 0xE86D2BC5, 0x9C9DF69E, 0x5CAE82AB, 0x71F54BFF, 0x64F2E21E, + 0xE2D74DD3, 0xF4FD4452, 0xBC437944, 0xB4130C93, 0x85139270, 0xAEFE1309, + 0xC186D91C, 0x598CB0FA, 0x91F7F7EE, 0x7AD91D26, 0xD6E6C907, 0x61B46FC9, + 0xF99C0238, 0xBC34F4DE, 0x6519035B, 0xDE355B3B, 0x611FCFDC, 0x886B4238, + 0xC1B2EFFA, 0xC6F34A26, 0x7D1683B2, 0xC58EF183, 0x2EC22005, 0x3BB5FCBC, + 0x4C6FAD73, 0xC3FE3B1B, 0xEEF28183, 0x8E4F1232, 0xE98583FF, 0x9172FE9C, + 0x28342F61, 0xC03404CD, 0xCDF7E2EC, 0x9E02FCE1, 0xEE0A6D70, 0x0B07A7C8, + 0x6372BB19, 0xAE56EDE7, 0xDE394DF4, 0x1D4F42A3, 0x60D7F468, 0xB96ADAB7, + 0xB2C8E3FB, 0xD108A94B, 0xB324FB61, 0xBC0AB182, 0x483A797A, 0x30ACCA4F, + 0x36ADE735, 0x1DF158A1, 0xF3EFE872, 0xE2A689DA, 0xE0E68B77, 0x984F0C70, + 0x7F57C935, 0xB557135E, 0x3DED1AF3, 0x85636555, 0x5F066ED0, 0x2433F51F, + 0xD5FD6561, 0xD3DF1ED5, 0xAEC4617A, 0xF681B202, 0x630C75D8, 0x7D2FE363, + 0x249B3EF9, 0xCC939DCE, 0x146433FB, 0xA9E13641, 0xCE2D3695, 0xD8B9C583, + 0x273D3CF1, 0xAFDC5620, 0xA2BB4A9A, 0xADF85458, 0xFFFFFFFF, 0xFFFFFFFF +}; + +static const BN_ULONG ffdhe8192_p[] = { + 0xFFFFFFFF, 0xFFFFFFFF, 0xC5C6424C, 0xD68C8BB7, 0x838FF88C, 0x011E2A94, + 0xA9F4614E, 0x0822E506, 0xF7A8443D, 0x97D11D49, 0x30677F0D, 0xA6BBFDE5, + 0xC1FE86FE, 0x2F741EF8, 0x5D71A87E, 0xFAFABE1C, 0xFBE58A30, 0xDED2FBAB, + 0x72B0A66E, 0xB6855DFE, 0xBA8A4FE8, 0x1EFC8CE0, 0x3F2FA457, 0x83F81D4A, + 0xA577E231, 0xA1FE3075, 0x88D9C0A0, 0xD5B80194, 0xAD9A95F9, 0x624816CD, + 0x50C1217B, 0x99E9E316, 0x0E423CFC, 0x51AA691E, 0x3826E52C, 0x1C217E6C, + 0x09703FEE, 0x51A8A931, 0x6A460E74, 0xBB709987, 0x9C86B022, 0x541FC68C, + 0x46FD8251, 0x59160CC0, 0x35C35F5C, 0x2846C0BA, 0x8B758282, 0x54504AC7, + 0xD2AF05E4, 0x29388839, 0xC01BD702, 0xCB2C0F1C, 0x7C932665, 0x555B2F74, + 0xA3AB8829, 0x86B63142, 0xF64B10EF, 0x0B8CC3BD, 0xEDD1CC5E, 0x687FEB69, + 0xC9509D43, 0xFDB23FCE, 0xD951AE64, 0x1E425A31, 0xF600C838, 0x36AD004C, + 0xCFF46AAA, 0xA40E329C, 0x7938DAD4, 0xA41D570D, 0xD43161C1, 0x62A69526, + 0x9ADB1E69, 0x3FDD4A8E, 0xDC6B80D6, 0x5B3B71F9, 0xC6272B04, 0xEC9D1810, + 0xCACEF403, 0x8CCF2DD5, 0xC95B9117, 0xE49F5235, 0xB854338A, 0x505DC82D, + 0x1562A846, 0x62292C31, 0x6AE77F5E, 0xD72B0374, 0x462D538C, 0xF9C9091B, + 0x47A67CBE, 0x0AE8DB58, 0x22611682, 0xB3A739C1, 0x2A281BF6, 0xEEAAC023, + 0x77CAF992, 0x94C6651E, 0x94B2BBC1, 0x763E4E4B, 0x0077D9B4, 0x587E38DA, + 0x183023C3, 0x7FB29F8C, 0xF9E3A26E, 0x0ABEC1FF, 0x350511E3, 0xA00EF092, + 0xDB6340D8, 0xB855322E, 0xA9A96910, 0xA52471F7, 0x4CFDB477, 0x388147FB, + 0x4E46041F, 0x9B1F5C3E, 0xFCCFEC71, 0xCDAD0657, 0x4C701C3A, 0xB38E8C33, + 0xB1C0FD4C, 0x917BDD64, 0x9B7624C8, 0x3BB45432, 0xCAF53EA6, 0x23BA4442, + 0x38532A3A, 0x4E677D2C, 0x45036C7A, 0x0BFD64B6, 0x5E0DD902, 0xC68A007E, + 0xF44182E1, 0x4DB5A851, 0x7F88A46B, 0x8EC9B55A, 0xCEC97DCF, 0x0A8291CD, + 0xF98D0ACC, 0x2A4ECEA9, 0x7140003C, 0x1A1DB93D, 0x33CB8B7A, 0x092999A3, + 0x71AD0038, 0x6DC778F9, 0x918130C4, 0xA907600A, 0x2D9E6832, 0xED6A1E01, + 0xEFB4318A, 0x7135C886, 0x7E31CC7A, 0x87F55BA5, 0x55034004, 0x7763CF1D, + 0xD69F6D18, 0xAC7D5F42, 0xE58857B6, 0x7930E9E4, 0x164DF4FB, 0x6E6F52C3, + 0x669E1EF1, 0x25E41D2B, 0x3FD59D7C, 0x3C1B20EE, 0xFA53DDEF, 0x0ABCD06B, + 0xD5C4484E, 0x1DBF9A42, 0x9B0DEADA, 0xABC52197, 0x22363A0D, 0xE86D2BC5, + 0x9C9DF69E, 0x5CAE82AB, 0x71F54BFF, 0x64F2E21E, 0xE2D74DD3, 0xF4FD4452, + 0xBC437944, 0xB4130C93, 0x85139270, 0xAEFE1309, 0xC186D91C, 0x598CB0FA, + 0x91F7F7EE, 0x7AD91D26, 0xD6E6C907, 0x61B46FC9, 0xF99C0238, 0xBC34F4DE, + 0x6519035B, 0xDE355B3B, 0x611FCFDC, 0x886B4238, 0xC1B2EFFA, 0xC6F34A26, + 0x7D1683B2, 0xC58EF183, 0x2EC22005, 0x3BB5FCBC, 0x4C6FAD73, 0xC3FE3B1B, + 0xEEF28183, 0x8E4F1232, 0xE98583FF, 0x9172FE9C, 0x28342F61, 0xC03404CD, + 0xCDF7E2EC, 0x9E02FCE1, 0xEE0A6D70, 0x0B07A7C8, 0x6372BB19, 0xAE56EDE7, + 0xDE394DF4, 0x1D4F42A3, 0x60D7F468, 0xB96ADAB7, 0xB2C8E3FB, 0xD108A94B, + 0xB324FB61, 0xBC0AB182, 0x483A797A, 0x30ACCA4F, 0x36ADE735, 0x1DF158A1, + 0xF3EFE872, 0xE2A689DA, 0xE0E68B77, 0x984F0C70, 0x7F57C935, 0xB557135E, + 0x3DED1AF3, 0x85636555, 0x5F066ED0, 0x2433F51F, 0xD5FD6561, 0xD3DF1ED5, + 0xAEC4617A, 0xF681B202, 0x630C75D8, 0x7D2FE363, 0x249B3EF9, 0xCC939DCE, + 0x146433FB, 0xA9E13641, 0xCE2D3695, 0xD8B9C583, 0x273D3CF1, 0xAFDC5620, + 0xA2BB4A9A, 0xADF85458, 0xFFFFFFFF, 0xFFFFFFFF +}; + +# else +# error "unsupported BN_BITS2" +# endif + +/* Macro to make a BIGNUM from static data */ + +# define make_dh_bn(x) extern const BIGNUM _bignum_##x; \ + const BIGNUM _bignum_##x = { (BN_ULONG *) x, \ + OSSL_NELEM(x),\ + OSSL_NELEM(x),\ + 0, BN_FLG_STATIC_DATA }; + +static const BN_ULONG value_2 = 2; + +const BIGNUM _bignum_const_2 = + { (BN_ULONG *)&value_2, 1, 1, 0, BN_FLG_STATIC_DATA }; + +make_dh_bn(dh1024_160_p) +make_dh_bn(dh1024_160_g) +make_dh_bn(dh1024_160_q) +make_dh_bn(dh2048_224_p) +make_dh_bn(dh2048_224_g) +make_dh_bn(dh2048_224_q) +make_dh_bn(dh2048_256_p) +make_dh_bn(dh2048_256_g) +make_dh_bn(dh2048_256_q) + +make_dh_bn(ffdhe2048_p) +make_dh_bn(ffdhe3072_p) +make_dh_bn(ffdhe4096_p) +make_dh_bn(ffdhe6144_p) +make_dh_bn(ffdhe8192_p) + + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_div.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_div.c new file mode 100644 index 000000000..3a6fa0a1b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_div.c @@ -0,0 +1,457 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include "bn_lcl.h" + +/* The old slow way */ +#if 0 +int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, + BN_CTX *ctx) +{ + int i, nm, nd; + int ret = 0; + BIGNUM *D; + + bn_check_top(m); + bn_check_top(d); + if (BN_is_zero(d)) { + BNerr(BN_F_BN_DIV, BN_R_DIV_BY_ZERO); + return 0; + } + + if (BN_ucmp(m, d) < 0) { + if (rem != NULL) { + if (BN_copy(rem, m) == NULL) + return 0; + } + if (dv != NULL) + BN_zero(dv); + return 1; + } + + BN_CTX_start(ctx); + D = BN_CTX_get(ctx); + if (dv == NULL) + dv = BN_CTX_get(ctx); + if (rem == NULL) + rem = BN_CTX_get(ctx); + if (D == NULL || dv == NULL || rem == NULL) + goto end; + + nd = BN_num_bits(d); + nm = BN_num_bits(m); + if (BN_copy(D, d) == NULL) + goto end; + if (BN_copy(rem, m) == NULL) + goto end; + + /* + * The next 2 are needed so we can do a dv->d[0]|=1 later since + * BN_lshift1 will only work once there is a value :-) + */ + BN_zero(dv); + if (bn_wexpand(dv, 1) == NULL) + goto end; + dv->top = 1; + + if (!BN_lshift(D, D, nm - nd)) + goto end; + for (i = nm - nd; i >= 0; i--) { + if (!BN_lshift1(dv, dv)) + goto end; + if (BN_ucmp(rem, D) >= 0) { + dv->d[0] |= 1; + if (!BN_usub(rem, rem, D)) + goto end; + } +/* CAN IMPROVE (and have now :=) */ + if (!BN_rshift1(D, D)) + goto end; + } + rem->neg = BN_is_zero(rem) ? 0 : m->neg; + dv->neg = m->neg ^ d->neg; + ret = 1; + end: + BN_CTX_end(ctx); + return ret; +} + +#else + +# if defined(BN_DIV3W) +BN_ULONG bn_div_3_words(const BN_ULONG *m, BN_ULONG d1, BN_ULONG d0); +# elif 0 +/* + * This is #if-ed away, because it's a reference for assembly implementations, + * where it can and should be made constant-time. But if you want to test it, + * just replace 0 with 1. + */ +# if BN_BITS2 == 64 && defined(__SIZEOF_INT128__) && __SIZEOF_INT128__==16 +# undef BN_ULLONG +# define BN_ULLONG __uint128_t +# define BN_LLONG +# endif + +# ifdef BN_LLONG +# define BN_DIV3W +/* + * Interface is somewhat quirky, |m| is pointer to most significant limb, + * and less significant limb is referred at |m[-1]|. This means that caller + * is responsible for ensuring that |m[-1]| is valid. Second condition that + * has to be met is that |d0|'s most significant bit has to be set. Or in + * other words divisor has to be "bit-aligned to the left." bn_div_fixed_top + * does all this. The subroutine considers four limbs, two of which are + * "overlapping," hence the name... + */ +static BN_ULONG bn_div_3_words(const BN_ULONG *m, BN_ULONG d1, BN_ULONG d0) +{ + BN_ULLONG R = ((BN_ULLONG)m[0] << BN_BITS2) | m[-1]; + BN_ULLONG D = ((BN_ULLONG)d0 << BN_BITS2) | d1; + BN_ULONG Q = 0, mask; + int i; + + for (i = 0; i < BN_BITS2; i++) { + Q <<= 1; + if (R >= D) { + Q |= 1; + R -= D; + } + D >>= 1; + } + + mask = 0 - (Q >> (BN_BITS2 - 1)); /* does it overflow? */ + + Q <<= 1; + Q |= (R >= D); + + return (Q | mask) & BN_MASK2; +} +# endif +# endif + +static int bn_left_align(BIGNUM *num) +{ + BN_ULONG *d = num->d, n, m, rmask; + int top = num->top; + int rshift = BN_num_bits_word(d[top - 1]), lshift, i; + + lshift = BN_BITS2 - rshift; + rshift %= BN_BITS2; /* say no to undefined behaviour */ + rmask = (BN_ULONG)0 - rshift; /* rmask = 0 - (rshift != 0) */ + rmask |= rmask >> 8; + + for (i = 0, m = 0; i < top; i++) { + n = d[i]; + d[i] = ((n << lshift) | m) & BN_MASK2; + m = (n >> rshift) & rmask; + } + + return lshift; +} + +# if !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) \ + && !defined(PEDANTIC) && !defined(BN_DIV3W) +# if defined(__GNUC__) && __GNUC__>=2 +# if defined(__i386) || defined (__i386__) + /*- + * There were two reasons for implementing this template: + * - GNU C generates a call to a function (__udivdi3 to be exact) + * in reply to ((((BN_ULLONG)n0)< */ +# endif /* __GNUC__ */ +# endif /* OPENSSL_NO_ASM */ + +/*- + * BN_div computes dv := num / divisor, rounding towards + * zero, and sets up rm such that dv*divisor + rm = num holds. + * Thus: + * dv->neg == num->neg ^ divisor->neg (unless the result is zero) + * rm->neg == num->neg (unless the remainder is zero) + * If 'dv' or 'rm' is NULL, the respective value is not returned. + */ +int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor, + BN_CTX *ctx) +{ + int ret; + + if (BN_is_zero(divisor)) { + BNerr(BN_F_BN_DIV, BN_R_DIV_BY_ZERO); + return 0; + } + + /* + * Invalid zero-padding would have particularly bad consequences so don't + * just rely on bn_check_top() here (bn_check_top() works only for + * BN_DEBUG builds) + */ + if (divisor->d[divisor->top - 1] == 0) { + BNerr(BN_F_BN_DIV, BN_R_NOT_INITIALIZED); + return 0; + } + + ret = bn_div_fixed_top(dv, rm, num, divisor, ctx); + + if (ret) { + if (dv != NULL) + bn_correct_top(dv); + if (rm != NULL) + bn_correct_top(rm); + } + + return ret; +} + +/* + * It's argued that *length* of *significant* part of divisor is public. + * Even if it's private modulus that is. Again, *length* is assumed + * public, but not *value*. Former is likely to be pre-defined by + * algorithm with bit granularity, though below subroutine is invariant + * of limb length. Thanks to this assumption we can require that |divisor| + * may not be zero-padded, yet claim this subroutine "constant-time"(*). + * This is because zero-padded dividend, |num|, is tolerated, so that + * caller can pass dividend of public length(*), but with smaller amount + * of significant limbs. This naturally means that quotient, |dv|, would + * contain correspongly less significant limbs as well, and will be zero- + * padded accordingly. Returned remainder, |rm|, will have same bit length + * as divisor, also zero-padded if needed. These actually leave sign bits + * in ambiguous state. In sense that we try to avoid negative zeros, while + * zero-padded zeros would retain sign. + * + * (*) "Constant-time-ness" has two pre-conditions: + * + * - availability of constant-time bn_div_3_words; + * - dividend is at least as "wide" as divisor, limb-wise, zero-padded + * if so requied, which shouldn't be a privacy problem, because + * divisor's length is considered public; + */ +int bn_div_fixed_top(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, + const BIGNUM *divisor, BN_CTX *ctx) +{ + int norm_shift, i, j, loop; + BIGNUM *tmp, *snum, *sdiv, *res; + BN_ULONG *resp, *wnum, *wnumtop; + BN_ULONG d0, d1; + int num_n, div_n; + + assert(divisor->top > 0 && divisor->d[divisor->top - 1] != 0); + + bn_check_top(num); + bn_check_top(divisor); + bn_check_top(dv); + bn_check_top(rm); + + BN_CTX_start(ctx); + res = (dv == NULL) ? BN_CTX_get(ctx) : dv; + tmp = BN_CTX_get(ctx); + snum = BN_CTX_get(ctx); + sdiv = BN_CTX_get(ctx); + if (sdiv == NULL) + goto err; + + /* First we normalise the numbers */ + if (!BN_copy(sdiv, divisor)) + goto err; + norm_shift = bn_left_align(sdiv); + sdiv->neg = 0; + /* + * Note that bn_lshift_fixed_top's output is always one limb longer + * than input, even when norm_shift is zero. This means that amount of + * inner loop iterations is invariant of dividend value, and that one + * doesn't need to compare dividend and divisor if they were originally + * of the same bit length. + */ + if (!(bn_lshift_fixed_top(snum, num, norm_shift))) + goto err; + + div_n = sdiv->top; + num_n = snum->top; + + if (num_n <= div_n) { + /* caller didn't pad dividend -> no constant-time guarantee... */ + if (bn_wexpand(snum, div_n + 1) == NULL) + goto err; + memset(&(snum->d[num_n]), 0, (div_n - num_n + 1) * sizeof(BN_ULONG)); + snum->top = num_n = div_n + 1; + } + + loop = num_n - div_n; + /* + * Lets setup a 'window' into snum This is the part that corresponds to + * the current 'area' being divided + */ + wnum = &(snum->d[loop]); + wnumtop = &(snum->d[num_n - 1]); + + /* Get the top 2 words of sdiv */ + d0 = sdiv->d[div_n - 1]; + d1 = (div_n == 1) ? 0 : sdiv->d[div_n - 2]; + + /* Setup quotient */ + if (!bn_wexpand(res, loop)) + goto err; + res->neg = (num->neg ^ divisor->neg); + res->top = loop; + res->flags |= BN_FLG_FIXED_TOP; + resp = &(res->d[loop]); + + /* space for temp */ + if (!bn_wexpand(tmp, (div_n + 1))) + goto err; + + for (i = 0; i < loop; i++, wnumtop--) { + BN_ULONG q, l0; + /* + * the first part of the loop uses the top two words of snum and sdiv + * to calculate a BN_ULONG q such that | wnum - sdiv * q | < sdiv + */ +# if defined(BN_DIV3W) + q = bn_div_3_words(wnumtop, d1, d0); +# else + BN_ULONG n0, n1, rem = 0; + + n0 = wnumtop[0]; + n1 = wnumtop[-1]; + if (n0 == d0) + q = BN_MASK2; + else { /* n0 < d0 */ + BN_ULONG n2 = (wnumtop == wnum) ? 0 : wnumtop[-2]; +# ifdef BN_LLONG + BN_ULLONG t2; + +# if defined(BN_LLONG) && defined(BN_DIV2W) && !defined(bn_div_words) + q = (BN_ULONG)(((((BN_ULLONG) n0) << BN_BITS2) | n1) / d0); +# else + q = bn_div_words(n0, n1, d0); +# endif + +# ifndef REMAINDER_IS_ALREADY_CALCULATED + /* + * rem doesn't have to be BN_ULLONG. The least we + * know it's less that d0, isn't it? + */ + rem = (n1 - q * d0) & BN_MASK2; +# endif + t2 = (BN_ULLONG) d1 *q; + + for (;;) { + if (t2 <= ((((BN_ULLONG) rem) << BN_BITS2) | n2)) + break; + q--; + rem += d0; + if (rem < d0) + break; /* don't let rem overflow */ + t2 -= d1; + } +# else /* !BN_LLONG */ + BN_ULONG t2l, t2h; + + q = bn_div_words(n0, n1, d0); +# ifndef REMAINDER_IS_ALREADY_CALCULATED + rem = (n1 - q * d0) & BN_MASK2; +# endif + +# if defined(BN_UMULT_LOHI) + BN_UMULT_LOHI(t2l, t2h, d1, q); +# elif defined(BN_UMULT_HIGH) + t2l = d1 * q; + t2h = BN_UMULT_HIGH(d1, q); +# else + { + BN_ULONG ql, qh; + t2l = LBITS(d1); + t2h = HBITS(d1); + ql = LBITS(q); + qh = HBITS(q); + mul64(t2l, t2h, ql, qh); /* t2=(BN_ULLONG)d1*q; */ + } +# endif + + for (;;) { + if ((t2h < rem) || ((t2h == rem) && (t2l <= n2))) + break; + q--; + rem += d0; + if (rem < d0) + break; /* don't let rem overflow */ + if (t2l < d1) + t2h--; + t2l -= d1; + } +# endif /* !BN_LLONG */ + } +# endif /* !BN_DIV3W */ + + l0 = bn_mul_words(tmp->d, sdiv->d, div_n, q); + tmp->d[div_n] = l0; + wnum--; + /* + * ignore top values of the bignums just sub the two BN_ULONG arrays + * with bn_sub_words + */ + l0 = bn_sub_words(wnum, wnum, tmp->d, div_n + 1); + q -= l0; + /* + * Note: As we have considered only the leading two BN_ULONGs in + * the calculation of q, sdiv * q might be greater than wnum (but + * then (q-1) * sdiv is less or equal than wnum) + */ + for (l0 = 0 - l0, j = 0; j < div_n; j++) + tmp->d[j] = sdiv->d[j] & l0; + l0 = bn_add_words(wnum, wnum, tmp->d, div_n); + (*wnumtop) += l0; + assert((*wnumtop) == 0); + + /* store part of the result */ + *--resp = q; + } + /* snum holds remainder, it's as wide as divisor */ + snum->neg = num->neg; + snum->top = div_n; + snum->flags |= BN_FLG_FIXED_TOP; + if (rm != NULL) + bn_rshift_fixed_top(rm, snum, norm_shift); + BN_CTX_end(ctx); + return 1; + err: + bn_check_top(rm); + BN_CTX_end(ctx); + return 0; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_err.c new file mode 100644 index 000000000..dd87c152c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_err.c @@ -0,0 +1,118 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA BN_str_functs[] = { + {ERR_PACK(ERR_LIB_BN, BN_F_BNRAND, 0), "bnrand"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BNRAND_RANGE, 0), "bnrand_range"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_BLINDING_CONVERT_EX, 0), + "BN_BLINDING_convert_ex"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_BLINDING_CREATE_PARAM, 0), + "BN_BLINDING_create_param"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_BLINDING_INVERT_EX, 0), + "BN_BLINDING_invert_ex"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_BLINDING_NEW, 0), "BN_BLINDING_new"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_BLINDING_UPDATE, 0), "BN_BLINDING_update"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_BN2DEC, 0), "BN_bn2dec"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_BN2HEX, 0), "BN_bn2hex"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_COMPUTE_WNAF, 0), "bn_compute_wNAF"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_CTX_GET, 0), "BN_CTX_get"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_CTX_NEW, 0), "BN_CTX_new"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_CTX_START, 0), "BN_CTX_start"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_DIV, 0), "BN_div"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_DIV_RECP, 0), "BN_div_recp"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_EXP, 0), "BN_exp"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_EXPAND_INTERNAL, 0), "bn_expand_internal"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_GENCB_NEW, 0), "BN_GENCB_new"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_GENERATE_DSA_NONCE, 0), + "BN_generate_dsa_nonce"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_GENERATE_PRIME_EX, 0), + "BN_generate_prime_ex"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_GF2M_MOD, 0), "BN_GF2m_mod"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_GF2M_MOD_EXP, 0), "BN_GF2m_mod_exp"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_GF2M_MOD_MUL, 0), "BN_GF2m_mod_mul"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_GF2M_MOD_SOLVE_QUAD, 0), + "BN_GF2m_mod_solve_quad"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR, 0), + "BN_GF2m_mod_solve_quad_arr"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_GF2M_MOD_SQR, 0), "BN_GF2m_mod_sqr"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_GF2M_MOD_SQRT, 0), "BN_GF2m_mod_sqrt"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_LSHIFT, 0), "BN_lshift"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_EXP2_MONT, 0), "BN_mod_exp2_mont"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_EXP_MONT, 0), "BN_mod_exp_mont"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_EXP_MONT_CONSTTIME, 0), + "BN_mod_exp_mont_consttime"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_EXP_MONT_WORD, 0), + "BN_mod_exp_mont_word"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_EXP_RECP, 0), "BN_mod_exp_recp"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_EXP_SIMPLE, 0), "BN_mod_exp_simple"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_INVERSE, 0), "BN_mod_inverse"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_INVERSE_NO_BRANCH, 0), + "BN_mod_inverse_no_branch"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_LSHIFT_QUICK, 0), "BN_mod_lshift_quick"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_SQRT, 0), "BN_mod_sqrt"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_MONT_CTX_NEW, 0), "BN_MONT_CTX_new"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_MPI2BN, 0), "BN_mpi2bn"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_NEW, 0), "BN_new"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_POOL_GET, 0), "BN_POOL_get"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_RAND, 0), "BN_rand"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_RAND_RANGE, 0), "BN_rand_range"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_RECP_CTX_NEW, 0), "BN_RECP_CTX_new"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_RSHIFT, 0), "BN_rshift"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_SET_WORDS, 0), "bn_set_words"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_STACK_PUSH, 0), "BN_STACK_push"}, + {ERR_PACK(ERR_LIB_BN, BN_F_BN_USUB, 0), "BN_usub"}, + {0, NULL} +}; + +static const ERR_STRING_DATA BN_str_reasons[] = { + {ERR_PACK(ERR_LIB_BN, 0, BN_R_ARG2_LT_ARG3), "arg2 lt arg3"}, + {ERR_PACK(ERR_LIB_BN, 0, BN_R_BAD_RECIPROCAL), "bad reciprocal"}, + {ERR_PACK(ERR_LIB_BN, 0, BN_R_BIGNUM_TOO_LONG), "bignum too long"}, + {ERR_PACK(ERR_LIB_BN, 0, BN_R_BITS_TOO_SMALL), "bits too small"}, + {ERR_PACK(ERR_LIB_BN, 0, BN_R_CALLED_WITH_EVEN_MODULUS), + "called with even modulus"}, + {ERR_PACK(ERR_LIB_BN, 0, BN_R_DIV_BY_ZERO), "div by zero"}, + {ERR_PACK(ERR_LIB_BN, 0, BN_R_ENCODING_ERROR), "encoding error"}, + {ERR_PACK(ERR_LIB_BN, 0, BN_R_EXPAND_ON_STATIC_BIGNUM_DATA), + "expand on static bignum data"}, + {ERR_PACK(ERR_LIB_BN, 0, BN_R_INPUT_NOT_REDUCED), "input not reduced"}, + {ERR_PACK(ERR_LIB_BN, 0, BN_R_INVALID_LENGTH), "invalid length"}, + {ERR_PACK(ERR_LIB_BN, 0, BN_R_INVALID_RANGE), "invalid range"}, + {ERR_PACK(ERR_LIB_BN, 0, BN_R_INVALID_SHIFT), "invalid shift"}, + {ERR_PACK(ERR_LIB_BN, 0, BN_R_NOT_A_SQUARE), "not a square"}, + {ERR_PACK(ERR_LIB_BN, 0, BN_R_NOT_INITIALIZED), "not initialized"}, + {ERR_PACK(ERR_LIB_BN, 0, BN_R_NO_INVERSE), "no inverse"}, + {ERR_PACK(ERR_LIB_BN, 0, BN_R_NO_SOLUTION), "no solution"}, + {ERR_PACK(ERR_LIB_BN, 0, BN_R_PRIVATE_KEY_TOO_LARGE), + "private key too large"}, + {ERR_PACK(ERR_LIB_BN, 0, BN_R_P_IS_NOT_PRIME), "p is not prime"}, + {ERR_PACK(ERR_LIB_BN, 0, BN_R_TOO_MANY_ITERATIONS), "too many iterations"}, + {ERR_PACK(ERR_LIB_BN, 0, BN_R_TOO_MANY_TEMPORARY_VARIABLES), + "too many temporary variables"}, + {0, NULL} +}; + +#endif + +int ERR_load_BN_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(BN_str_functs[0].error) == NULL) { + ERR_load_strings_const(BN_str_functs); + ERR_load_strings_const(BN_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_exp.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_exp.c new file mode 100644 index 000000000..88f2baf0e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_exp.c @@ -0,0 +1,1395 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include "internal/constant_time_locl.h" +#include "bn_lcl.h" + +#include +#ifdef _WIN32 +# include +# ifndef alloca +# define alloca _alloca +# endif +#elif defined(__GNUC__) +# ifndef alloca +# define alloca(s) __builtin_alloca((s)) +# endif +#elif defined(__sun) +# include +#endif + +#include "rsaz_exp.h" + +#undef SPARC_T4_MONT +#if defined(OPENSSL_BN_ASM_MONT) && (defined(__sparc__) || defined(__sparc)) +# include "sparc_arch.h" +extern unsigned int OPENSSL_sparcv9cap_P[]; +# define SPARC_T4_MONT +#endif + +/* maximum precomputation table size for *variable* sliding windows */ +#define TABLE_SIZE 32 + +/* this one works - simple but works */ +int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) +{ + int i, bits, ret = 0; + BIGNUM *v, *rr; + + if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0 + || BN_get_flags(a, BN_FLG_CONSTTIME) != 0) { + /* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */ + BNerr(BN_F_BN_EXP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + BN_CTX_start(ctx); + rr = ((r == a) || (r == p)) ? BN_CTX_get(ctx) : r; + v = BN_CTX_get(ctx); + if (rr == NULL || v == NULL) + goto err; + + if (BN_copy(v, a) == NULL) + goto err; + bits = BN_num_bits(p); + + if (BN_is_odd(p)) { + if (BN_copy(rr, a) == NULL) + goto err; + } else { + if (!BN_one(rr)) + goto err; + } + + for (i = 1; i < bits; i++) { + if (!BN_sqr(v, v, ctx)) + goto err; + if (BN_is_bit_set(p, i)) { + if (!BN_mul(rr, rr, v, ctx)) + goto err; + } + } + if (r != rr && BN_copy(r, rr) == NULL) + goto err; + + ret = 1; + err: + BN_CTX_end(ctx); + bn_check_top(r); + return ret; +} + +int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, + BN_CTX *ctx) +{ + int ret; + + bn_check_top(a); + bn_check_top(p); + bn_check_top(m); + + /*- + * For even modulus m = 2^k*m_odd, it might make sense to compute + * a^p mod m_odd and a^p mod 2^k separately (with Montgomery + * exponentiation for the odd part), using appropriate exponent + * reductions, and combine the results using the CRT. + * + * For now, we use Montgomery only if the modulus is odd; otherwise, + * exponentiation using the reciprocal-based quick remaindering + * algorithm is used. + * + * (Timing obtained with expspeed.c [computations a^p mod m + * where a, p, m are of the same length: 256, 512, 1024, 2048, + * 4096, 8192 bits], compared to the running time of the + * standard algorithm: + * + * BN_mod_exp_mont 33 .. 40 % [AMD K6-2, Linux, debug configuration] + * 55 .. 77 % [UltraSparc processor, but + * debug-solaris-sparcv8-gcc conf.] + * + * BN_mod_exp_recp 50 .. 70 % [AMD K6-2, Linux, debug configuration] + * 62 .. 118 % [UltraSparc, debug-solaris-sparcv8-gcc] + * + * On the Sparc, BN_mod_exp_recp was faster than BN_mod_exp_mont + * at 2048 and more bits, but at 512 and 1024 bits, it was + * slower even than the standard algorithm! + * + * "Real" timings [linux-elf, solaris-sparcv9-gcc configurations] + * should be obtained when the new Montgomery reduction code + * has been integrated into OpenSSL.) + */ + +#define MONT_MUL_MOD +#define MONT_EXP_WORD +#define RECP_MUL_MOD + +#ifdef MONT_MUL_MOD + if (BN_is_odd(m)) { +# ifdef MONT_EXP_WORD + if (a->top == 1 && !a->neg + && (BN_get_flags(p, BN_FLG_CONSTTIME) == 0) + && (BN_get_flags(a, BN_FLG_CONSTTIME) == 0) + && (BN_get_flags(m, BN_FLG_CONSTTIME) == 0)) { + BN_ULONG A = a->d[0]; + ret = BN_mod_exp_mont_word(r, A, p, m, ctx, NULL); + } else +# endif + ret = BN_mod_exp_mont(r, a, p, m, ctx, NULL); + } else +#endif +#ifdef RECP_MUL_MOD + { + ret = BN_mod_exp_recp(r, a, p, m, ctx); + } +#else + { + ret = BN_mod_exp_simple(r, a, p, m, ctx); + } +#endif + + bn_check_top(r); + return ret; +} + +int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx) +{ + int i, j, bits, ret = 0, wstart, wend, window, wvalue; + int start = 1; + BIGNUM *aa; + /* Table of variables obtained from 'ctx' */ + BIGNUM *val[TABLE_SIZE]; + BN_RECP_CTX recp; + + if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0 + || BN_get_flags(a, BN_FLG_CONSTTIME) != 0 + || BN_get_flags(m, BN_FLG_CONSTTIME) != 0) { + /* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */ + BNerr(BN_F_BN_MOD_EXP_RECP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + bits = BN_num_bits(p); + if (bits == 0) { + /* x**0 mod 1, or x**0 mod -1 is still zero. */ + if (BN_abs_is_word(m, 1)) { + ret = 1; + BN_zero(r); + } else { + ret = BN_one(r); + } + return ret; + } + + BN_CTX_start(ctx); + aa = BN_CTX_get(ctx); + val[0] = BN_CTX_get(ctx); + if (val[0] == NULL) + goto err; + + BN_RECP_CTX_init(&recp); + if (m->neg) { + /* ignore sign of 'm' */ + if (!BN_copy(aa, m)) + goto err; + aa->neg = 0; + if (BN_RECP_CTX_set(&recp, aa, ctx) <= 0) + goto err; + } else { + if (BN_RECP_CTX_set(&recp, m, ctx) <= 0) + goto err; + } + + if (!BN_nnmod(val[0], a, m, ctx)) + goto err; /* 1 */ + if (BN_is_zero(val[0])) { + BN_zero(r); + ret = 1; + goto err; + } + + window = BN_window_bits_for_exponent_size(bits); + if (window > 1) { + if (!BN_mod_mul_reciprocal(aa, val[0], val[0], &recp, ctx)) + goto err; /* 2 */ + j = 1 << (window - 1); + for (i = 1; i < j; i++) { + if (((val[i] = BN_CTX_get(ctx)) == NULL) || + !BN_mod_mul_reciprocal(val[i], val[i - 1], aa, &recp, ctx)) + goto err; + } + } + + start = 1; /* This is used to avoid multiplication etc + * when there is only the value '1' in the + * buffer. */ + wvalue = 0; /* The 'value' of the window */ + wstart = bits - 1; /* The top bit of the window */ + wend = 0; /* The bottom bit of the window */ + + if (!BN_one(r)) + goto err; + + for (;;) { + if (BN_is_bit_set(p, wstart) == 0) { + if (!start) + if (!BN_mod_mul_reciprocal(r, r, r, &recp, ctx)) + goto err; + if (wstart == 0) + break; + wstart--; + continue; + } + /* + * We now have wstart on a 'set' bit, we now need to work out how bit + * a window to do. To do this we need to scan forward until the last + * set bit before the end of the window + */ + j = wstart; + wvalue = 1; + wend = 0; + for (i = 1; i < window; i++) { + if (wstart - i < 0) + break; + if (BN_is_bit_set(p, wstart - i)) { + wvalue <<= (i - wend); + wvalue |= 1; + wend = i; + } + } + + /* wend is the size of the current window */ + j = wend + 1; + /* add the 'bytes above' */ + if (!start) + for (i = 0; i < j; i++) { + if (!BN_mod_mul_reciprocal(r, r, r, &recp, ctx)) + goto err; + } + + /* wvalue will be an odd number < 2^window */ + if (!BN_mod_mul_reciprocal(r, r, val[wvalue >> 1], &recp, ctx)) + goto err; + + /* move the 'window' down further */ + wstart -= wend + 1; + wvalue = 0; + start = 0; + if (wstart < 0) + break; + } + ret = 1; + err: + BN_CTX_end(ctx); + BN_RECP_CTX_free(&recp); + bn_check_top(r); + return ret; +} + +int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont) +{ + int i, j, bits, ret = 0, wstart, wend, window, wvalue; + int start = 1; + BIGNUM *d, *r; + const BIGNUM *aa; + /* Table of variables obtained from 'ctx' */ + BIGNUM *val[TABLE_SIZE]; + BN_MONT_CTX *mont = NULL; + + if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0 + || BN_get_flags(a, BN_FLG_CONSTTIME) != 0 + || BN_get_flags(m, BN_FLG_CONSTTIME) != 0) { + return BN_mod_exp_mont_consttime(rr, a, p, m, ctx, in_mont); + } + + bn_check_top(a); + bn_check_top(p); + bn_check_top(m); + + if (!BN_is_odd(m)) { + BNerr(BN_F_BN_MOD_EXP_MONT, BN_R_CALLED_WITH_EVEN_MODULUS); + return 0; + } + bits = BN_num_bits(p); + if (bits == 0) { + /* x**0 mod 1, or x**0 mod -1 is still zero. */ + if (BN_abs_is_word(m, 1)) { + ret = 1; + BN_zero(rr); + } else { + ret = BN_one(rr); + } + return ret; + } + + BN_CTX_start(ctx); + d = BN_CTX_get(ctx); + r = BN_CTX_get(ctx); + val[0] = BN_CTX_get(ctx); + if (val[0] == NULL) + goto err; + + /* + * If this is not done, things will break in the montgomery part + */ + + if (in_mont != NULL) + mont = in_mont; + else { + if ((mont = BN_MONT_CTX_new()) == NULL) + goto err; + if (!BN_MONT_CTX_set(mont, m, ctx)) + goto err; + } + + if (a->neg || BN_ucmp(a, m) >= 0) { + if (!BN_nnmod(val[0], a, m, ctx)) + goto err; + aa = val[0]; + } else + aa = a; + if (!bn_to_mont_fixed_top(val[0], aa, mont, ctx)) + goto err; /* 1 */ + + window = BN_window_bits_for_exponent_size(bits); + if (window > 1) { + if (!bn_mul_mont_fixed_top(d, val[0], val[0], mont, ctx)) + goto err; /* 2 */ + j = 1 << (window - 1); + for (i = 1; i < j; i++) { + if (((val[i] = BN_CTX_get(ctx)) == NULL) || + !bn_mul_mont_fixed_top(val[i], val[i - 1], d, mont, ctx)) + goto err; + } + } + + start = 1; /* This is used to avoid multiplication etc + * when there is only the value '1' in the + * buffer. */ + wvalue = 0; /* The 'value' of the window */ + wstart = bits - 1; /* The top bit of the window */ + wend = 0; /* The bottom bit of the window */ + +#if 1 /* by Shay Gueron's suggestion */ + j = m->top; /* borrow j */ + if (m->d[j - 1] & (((BN_ULONG)1) << (BN_BITS2 - 1))) { + if (bn_wexpand(r, j) == NULL) + goto err; + /* 2^(top*BN_BITS2) - m */ + r->d[0] = (0 - m->d[0]) & BN_MASK2; + for (i = 1; i < j; i++) + r->d[i] = (~m->d[i]) & BN_MASK2; + r->top = j; + r->flags |= BN_FLG_FIXED_TOP; + } else +#endif + if (!bn_to_mont_fixed_top(r, BN_value_one(), mont, ctx)) + goto err; + for (;;) { + if (BN_is_bit_set(p, wstart) == 0) { + if (!start) { + if (!bn_mul_mont_fixed_top(r, r, r, mont, ctx)) + goto err; + } + if (wstart == 0) + break; + wstart--; + continue; + } + /* + * We now have wstart on a 'set' bit, we now need to work out how bit + * a window to do. To do this we need to scan forward until the last + * set bit before the end of the window + */ + j = wstart; + wvalue = 1; + wend = 0; + for (i = 1; i < window; i++) { + if (wstart - i < 0) + break; + if (BN_is_bit_set(p, wstart - i)) { + wvalue <<= (i - wend); + wvalue |= 1; + wend = i; + } + } + + /* wend is the size of the current window */ + j = wend + 1; + /* add the 'bytes above' */ + if (!start) + for (i = 0; i < j; i++) { + if (!bn_mul_mont_fixed_top(r, r, r, mont, ctx)) + goto err; + } + + /* wvalue will be an odd number < 2^window */ + if (!bn_mul_mont_fixed_top(r, r, val[wvalue >> 1], mont, ctx)) + goto err; + + /* move the 'window' down further */ + wstart -= wend + 1; + wvalue = 0; + start = 0; + if (wstart < 0) + break; + } + /* + * Done with zero-padded intermediate BIGNUMs. Final BN_from_montgomery + * removes padding [if any] and makes return value suitable for public + * API consumer. + */ +#if defined(SPARC_T4_MONT) + if (OPENSSL_sparcv9cap_P[0] & (SPARCV9_VIS3 | SPARCV9_PREFER_FPU)) { + j = mont->N.top; /* borrow j */ + val[0]->d[0] = 1; /* borrow val[0] */ + for (i = 1; i < j; i++) + val[0]->d[i] = 0; + val[0]->top = j; + if (!BN_mod_mul_montgomery(rr, r, val[0], mont, ctx)) + goto err; + } else +#endif + if (!BN_from_montgomery(rr, r, mont, ctx)) + goto err; + ret = 1; + err: + if (in_mont == NULL) + BN_MONT_CTX_free(mont); + BN_CTX_end(ctx); + bn_check_top(rr); + return ret; +} + +static BN_ULONG bn_get_bits(const BIGNUM *a, int bitpos) +{ + BN_ULONG ret = 0; + int wordpos; + + wordpos = bitpos / BN_BITS2; + bitpos %= BN_BITS2; + if (wordpos >= 0 && wordpos < a->top) { + ret = a->d[wordpos] & BN_MASK2; + if (bitpos) { + ret >>= bitpos; + if (++wordpos < a->top) + ret |= a->d[wordpos] << (BN_BITS2 - bitpos); + } + } + + return ret & BN_MASK2; +} + +/* + * BN_mod_exp_mont_consttime() stores the precomputed powers in a specific + * layout so that accessing any of these table values shows the same access + * pattern as far as cache lines are concerned. The following functions are + * used to transfer a BIGNUM from/to that table. + */ + +static int MOD_EXP_CTIME_COPY_TO_PREBUF(const BIGNUM *b, int top, + unsigned char *buf, int idx, + int window) +{ + int i, j; + int width = 1 << window; + BN_ULONG *table = (BN_ULONG *)buf; + + if (top > b->top) + top = b->top; /* this works because 'buf' is explicitly + * zeroed */ + for (i = 0, j = idx; i < top; i++, j += width) { + table[j] = b->d[i]; + } + + return 1; +} + +static int MOD_EXP_CTIME_COPY_FROM_PREBUF(BIGNUM *b, int top, + unsigned char *buf, int idx, + int window) +{ + int i, j; + int width = 1 << window; + /* + * We declare table 'volatile' in order to discourage compiler + * from reordering loads from the table. Concern is that if + * reordered in specific manner loads might give away the + * information we are trying to conceal. Some would argue that + * compiler can reorder them anyway, but it can as well be + * argued that doing so would be violation of standard... + */ + volatile BN_ULONG *table = (volatile BN_ULONG *)buf; + + if (bn_wexpand(b, top) == NULL) + return 0; + + if (window <= 3) { + for (i = 0; i < top; i++, table += width) { + BN_ULONG acc = 0; + + for (j = 0; j < width; j++) { + acc |= table[j] & + ((BN_ULONG)0 - (constant_time_eq_int(j,idx)&1)); + } + + b->d[i] = acc; + } + } else { + int xstride = 1 << (window - 2); + BN_ULONG y0, y1, y2, y3; + + i = idx >> (window - 2); /* equivalent of idx / xstride */ + idx &= xstride - 1; /* equivalent of idx % xstride */ + + y0 = (BN_ULONG)0 - (constant_time_eq_int(i,0)&1); + y1 = (BN_ULONG)0 - (constant_time_eq_int(i,1)&1); + y2 = (BN_ULONG)0 - (constant_time_eq_int(i,2)&1); + y3 = (BN_ULONG)0 - (constant_time_eq_int(i,3)&1); + + for (i = 0; i < top; i++, table += width) { + BN_ULONG acc = 0; + + for (j = 0; j < xstride; j++) { + acc |= ( (table[j + 0 * xstride] & y0) | + (table[j + 1 * xstride] & y1) | + (table[j + 2 * xstride] & y2) | + (table[j + 3 * xstride] & y3) ) + & ((BN_ULONG)0 - (constant_time_eq_int(j,idx)&1)); + } + + b->d[i] = acc; + } + } + + b->top = top; + b->flags |= BN_FLG_FIXED_TOP; + return 1; +} + +/* + * Given a pointer value, compute the next address that is a cache line + * multiple. + */ +#define MOD_EXP_CTIME_ALIGN(x_) \ + ((unsigned char*)(x_) + (MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH - (((size_t)(x_)) & (MOD_EXP_CTIME_MIN_CACHE_LINE_MASK)))) + +/* + * This variant of BN_mod_exp_mont() uses fixed windows and the special + * precomputation memory layout to limit data-dependency to a minimum to + * protect secret exponents (cf. the hyper-threading timing attacks pointed + * out by Colin Percival, + * http://www.daemonology.net/hyperthreading-considered-harmful/) + */ +int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *in_mont) +{ + int i, bits, ret = 0, window, wvalue, wmask, window0; + int top; + BN_MONT_CTX *mont = NULL; + + int numPowers; + unsigned char *powerbufFree = NULL; + int powerbufLen = 0; + unsigned char *powerbuf = NULL; + BIGNUM tmp, am; +#if defined(SPARC_T4_MONT) + unsigned int t4 = 0; +#endif + + bn_check_top(a); + bn_check_top(p); + bn_check_top(m); + + if (!BN_is_odd(m)) { + BNerr(BN_F_BN_MOD_EXP_MONT_CONSTTIME, BN_R_CALLED_WITH_EVEN_MODULUS); + return 0; + } + + top = m->top; + + /* + * Use all bits stored in |p|, rather than |BN_num_bits|, so we do not leak + * whether the top bits are zero. + */ + bits = p->top * BN_BITS2; + if (bits == 0) { + /* x**0 mod 1, or x**0 mod -1 is still zero. */ + if (BN_abs_is_word(m, 1)) { + ret = 1; + BN_zero(rr); + } else { + ret = BN_one(rr); + } + return ret; + } + + BN_CTX_start(ctx); + + /* + * Allocate a montgomery context if it was not supplied by the caller. If + * this is not done, things will break in the montgomery part. + */ + if (in_mont != NULL) + mont = in_mont; + else { + if ((mont = BN_MONT_CTX_new()) == NULL) + goto err; + if (!BN_MONT_CTX_set(mont, m, ctx)) + goto err; + } + + if (a->neg || BN_ucmp(a, m) >= 0) { + BIGNUM *reduced = BN_CTX_get(ctx); + if (reduced == NULL + || !BN_nnmod(reduced, a, m, ctx)) { + goto err; + } + a = reduced; + } + +#ifdef RSAZ_ENABLED + /* + * If the size of the operands allow it, perform the optimized + * RSAZ exponentiation. For further information see + * crypto/bn/rsaz_exp.c and accompanying assembly modules. + */ + if ((16 == a->top) && (16 == p->top) && (BN_num_bits(m) == 1024) + && rsaz_avx2_eligible()) { + if (NULL == bn_wexpand(rr, 16)) + goto err; + RSAZ_1024_mod_exp_avx2(rr->d, a->d, p->d, m->d, mont->RR.d, + mont->n0[0]); + rr->top = 16; + rr->neg = 0; + bn_correct_top(rr); + ret = 1; + goto err; + } else if ((8 == a->top) && (8 == p->top) && (BN_num_bits(m) == 512)) { + if (NULL == bn_wexpand(rr, 8)) + goto err; + RSAZ_512_mod_exp(rr->d, a->d, p->d, m->d, mont->n0[0], mont->RR.d); + rr->top = 8; + rr->neg = 0; + bn_correct_top(rr); + ret = 1; + goto err; + } +#endif + + /* Get the window size to use with size of p. */ + window = BN_window_bits_for_ctime_exponent_size(bits); +#if defined(SPARC_T4_MONT) + if (window >= 5 && (top & 15) == 0 && top <= 64 && + (OPENSSL_sparcv9cap_P[1] & (CFR_MONTMUL | CFR_MONTSQR)) == + (CFR_MONTMUL | CFR_MONTSQR) && (t4 = OPENSSL_sparcv9cap_P[0])) + window = 5; + else +#endif +#if defined(OPENSSL_BN_ASM_MONT5) + if (window >= 5) { + window = 5; /* ~5% improvement for RSA2048 sign, and even + * for RSA4096 */ + /* reserve space for mont->N.d[] copy */ + powerbufLen += top * sizeof(mont->N.d[0]); + } +#endif + (void)0; + + /* + * Allocate a buffer large enough to hold all of the pre-computed powers + * of am, am itself and tmp. + */ + numPowers = 1 << window; + powerbufLen += sizeof(m->d[0]) * (top * numPowers + + ((2 * top) > + numPowers ? (2 * top) : numPowers)); +#ifdef alloca + if (powerbufLen < 3072) + powerbufFree = + alloca(powerbufLen + MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH); + else +#endif + if ((powerbufFree = + OPENSSL_malloc(powerbufLen + MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH)) + == NULL) + goto err; + + powerbuf = MOD_EXP_CTIME_ALIGN(powerbufFree); + memset(powerbuf, 0, powerbufLen); + +#ifdef alloca + if (powerbufLen < 3072) + powerbufFree = NULL; +#endif + + /* lay down tmp and am right after powers table */ + tmp.d = (BN_ULONG *)(powerbuf + sizeof(m->d[0]) * top * numPowers); + am.d = tmp.d + top; + tmp.top = am.top = 0; + tmp.dmax = am.dmax = top; + tmp.neg = am.neg = 0; + tmp.flags = am.flags = BN_FLG_STATIC_DATA; + + /* prepare a^0 in Montgomery domain */ +#if 1 /* by Shay Gueron's suggestion */ + if (m->d[top - 1] & (((BN_ULONG)1) << (BN_BITS2 - 1))) { + /* 2^(top*BN_BITS2) - m */ + tmp.d[0] = (0 - m->d[0]) & BN_MASK2; + for (i = 1; i < top; i++) + tmp.d[i] = (~m->d[i]) & BN_MASK2; + tmp.top = top; + } else +#endif + if (!bn_to_mont_fixed_top(&tmp, BN_value_one(), mont, ctx)) + goto err; + + /* prepare a^1 in Montgomery domain */ + if (!bn_to_mont_fixed_top(&am, a, mont, ctx)) + goto err; + +#if defined(SPARC_T4_MONT) + if (t4) { + typedef int (*bn_pwr5_mont_f) (BN_ULONG *tp, const BN_ULONG *np, + const BN_ULONG *n0, const void *table, + int power, int bits); + int bn_pwr5_mont_t4_8(BN_ULONG *tp, const BN_ULONG *np, + const BN_ULONG *n0, const void *table, + int power, int bits); + int bn_pwr5_mont_t4_16(BN_ULONG *tp, const BN_ULONG *np, + const BN_ULONG *n0, const void *table, + int power, int bits); + int bn_pwr5_mont_t4_24(BN_ULONG *tp, const BN_ULONG *np, + const BN_ULONG *n0, const void *table, + int power, int bits); + int bn_pwr5_mont_t4_32(BN_ULONG *tp, const BN_ULONG *np, + const BN_ULONG *n0, const void *table, + int power, int bits); + static const bn_pwr5_mont_f pwr5_funcs[4] = { + bn_pwr5_mont_t4_8, bn_pwr5_mont_t4_16, + bn_pwr5_mont_t4_24, bn_pwr5_mont_t4_32 + }; + bn_pwr5_mont_f pwr5_worker = pwr5_funcs[top / 16 - 1]; + + typedef int (*bn_mul_mont_f) (BN_ULONG *rp, const BN_ULONG *ap, + const void *bp, const BN_ULONG *np, + const BN_ULONG *n0); + int bn_mul_mont_t4_8(BN_ULONG *rp, const BN_ULONG *ap, const void *bp, + const BN_ULONG *np, const BN_ULONG *n0); + int bn_mul_mont_t4_16(BN_ULONG *rp, const BN_ULONG *ap, + const void *bp, const BN_ULONG *np, + const BN_ULONG *n0); + int bn_mul_mont_t4_24(BN_ULONG *rp, const BN_ULONG *ap, + const void *bp, const BN_ULONG *np, + const BN_ULONG *n0); + int bn_mul_mont_t4_32(BN_ULONG *rp, const BN_ULONG *ap, + const void *bp, const BN_ULONG *np, + const BN_ULONG *n0); + static const bn_mul_mont_f mul_funcs[4] = { + bn_mul_mont_t4_8, bn_mul_mont_t4_16, + bn_mul_mont_t4_24, bn_mul_mont_t4_32 + }; + bn_mul_mont_f mul_worker = mul_funcs[top / 16 - 1]; + + void bn_mul_mont_vis3(BN_ULONG *rp, const BN_ULONG *ap, + const void *bp, const BN_ULONG *np, + const BN_ULONG *n0, int num); + void bn_mul_mont_t4(BN_ULONG *rp, const BN_ULONG *ap, + const void *bp, const BN_ULONG *np, + const BN_ULONG *n0, int num); + void bn_mul_mont_gather5_t4(BN_ULONG *rp, const BN_ULONG *ap, + const void *table, const BN_ULONG *np, + const BN_ULONG *n0, int num, int power); + void bn_flip_n_scatter5_t4(const BN_ULONG *inp, size_t num, + void *table, size_t power); + void bn_gather5_t4(BN_ULONG *out, size_t num, + void *table, size_t power); + void bn_flip_t4(BN_ULONG *dst, BN_ULONG *src, size_t num); + + BN_ULONG *np = mont->N.d, *n0 = mont->n0; + int stride = 5 * (6 - (top / 16 - 1)); /* multiple of 5, but less + * than 32 */ + + /* + * BN_to_montgomery can contaminate words above .top [in + * BN_DEBUG[_DEBUG] build]... + */ + for (i = am.top; i < top; i++) + am.d[i] = 0; + for (i = tmp.top; i < top; i++) + tmp.d[i] = 0; + + bn_flip_n_scatter5_t4(tmp.d, top, powerbuf, 0); + bn_flip_n_scatter5_t4(am.d, top, powerbuf, 1); + if (!(*mul_worker) (tmp.d, am.d, am.d, np, n0) && + !(*mul_worker) (tmp.d, am.d, am.d, np, n0)) + bn_mul_mont_vis3(tmp.d, am.d, am.d, np, n0, top); + bn_flip_n_scatter5_t4(tmp.d, top, powerbuf, 2); + + for (i = 3; i < 32; i++) { + /* Calculate a^i = a^(i-1) * a */ + if (!(*mul_worker) (tmp.d, tmp.d, am.d, np, n0) && + !(*mul_worker) (tmp.d, tmp.d, am.d, np, n0)) + bn_mul_mont_vis3(tmp.d, tmp.d, am.d, np, n0, top); + bn_flip_n_scatter5_t4(tmp.d, top, powerbuf, i); + } + + /* switch to 64-bit domain */ + np = alloca(top * sizeof(BN_ULONG)); + top /= 2; + bn_flip_t4(np, mont->N.d, top); + + /* + * The exponent may not have a whole number of fixed-size windows. + * To simplify the main loop, the initial window has between 1 and + * full-window-size bits such that what remains is always a whole + * number of windows + */ + window0 = (bits - 1) % 5 + 1; + wmask = (1 << window0) - 1; + bits -= window0; + wvalue = bn_get_bits(p, bits) & wmask; + bn_gather5_t4(tmp.d, top, powerbuf, wvalue); + + /* + * Scan the exponent one window at a time starting from the most + * significant bits. + */ + while (bits > 0) { + if (bits < stride) + stride = bits; + bits -= stride; + wvalue = bn_get_bits(p, bits); + + if ((*pwr5_worker) (tmp.d, np, n0, powerbuf, wvalue, stride)) + continue; + /* retry once and fall back */ + if ((*pwr5_worker) (tmp.d, np, n0, powerbuf, wvalue, stride)) + continue; + + bits += stride - 5; + wvalue >>= stride - 5; + wvalue &= 31; + bn_mul_mont_t4(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont_t4(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont_t4(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont_t4(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont_t4(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont_gather5_t4(tmp.d, tmp.d, powerbuf, np, n0, top, + wvalue); + } + + bn_flip_t4(tmp.d, tmp.d, top); + top *= 2; + /* back to 32-bit domain */ + tmp.top = top; + bn_correct_top(&tmp); + OPENSSL_cleanse(np, top * sizeof(BN_ULONG)); + } else +#endif +#if defined(OPENSSL_BN_ASM_MONT5) + if (window == 5 && top > 1) { + /* + * This optimization uses ideas from http://eprint.iacr.org/2011/239, + * specifically optimization of cache-timing attack countermeasures + * and pre-computation optimization. + */ + + /* + * Dedicated window==4 case improves 512-bit RSA sign by ~15%, but as + * 512-bit RSA is hardly relevant, we omit it to spare size... + */ + void bn_mul_mont_gather5(BN_ULONG *rp, const BN_ULONG *ap, + const void *table, const BN_ULONG *np, + const BN_ULONG *n0, int num, int power); + void bn_scatter5(const BN_ULONG *inp, size_t num, + void *table, size_t power); + void bn_gather5(BN_ULONG *out, size_t num, void *table, size_t power); + void bn_power5(BN_ULONG *rp, const BN_ULONG *ap, + const void *table, const BN_ULONG *np, + const BN_ULONG *n0, int num, int power); + int bn_get_bits5(const BN_ULONG *ap, int off); + int bn_from_montgomery(BN_ULONG *rp, const BN_ULONG *ap, + const BN_ULONG *not_used, const BN_ULONG *np, + const BN_ULONG *n0, int num); + + BN_ULONG *n0 = mont->n0, *np; + + /* + * BN_to_montgomery can contaminate words above .top [in + * BN_DEBUG[_DEBUG] build]... + */ + for (i = am.top; i < top; i++) + am.d[i] = 0; + for (i = tmp.top; i < top; i++) + tmp.d[i] = 0; + + /* + * copy mont->N.d[] to improve cache locality + */ + for (np = am.d + top, i = 0; i < top; i++) + np[i] = mont->N.d[i]; + + bn_scatter5(tmp.d, top, powerbuf, 0); + bn_scatter5(am.d, am.top, powerbuf, 1); + bn_mul_mont(tmp.d, am.d, am.d, np, n0, top); + bn_scatter5(tmp.d, top, powerbuf, 2); + +# if 0 + for (i = 3; i < 32; i++) { + /* Calculate a^i = a^(i-1) * a */ + bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1); + bn_scatter5(tmp.d, top, powerbuf, i); + } +# else + /* same as above, but uses squaring for 1/2 of operations */ + for (i = 4; i < 32; i *= 2) { + bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_scatter5(tmp.d, top, powerbuf, i); + } + for (i = 3; i < 8; i += 2) { + int j; + bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1); + bn_scatter5(tmp.d, top, powerbuf, i); + for (j = 2 * i; j < 32; j *= 2) { + bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_scatter5(tmp.d, top, powerbuf, j); + } + } + for (; i < 16; i += 2) { + bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1); + bn_scatter5(tmp.d, top, powerbuf, i); + bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_scatter5(tmp.d, top, powerbuf, 2 * i); + } + for (; i < 32; i += 2) { + bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1); + bn_scatter5(tmp.d, top, powerbuf, i); + } +# endif + /* + * The exponent may not have a whole number of fixed-size windows. + * To simplify the main loop, the initial window has between 1 and + * full-window-size bits such that what remains is always a whole + * number of windows + */ + window0 = (bits - 1) % 5 + 1; + wmask = (1 << window0) - 1; + bits -= window0; + wvalue = bn_get_bits(p, bits) & wmask; + bn_gather5(tmp.d, top, powerbuf, wvalue); + + /* + * Scan the exponent one window at a time starting from the most + * significant bits. + */ + if (top & 7) { + while (bits > 0) { + bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont_gather5(tmp.d, tmp.d, powerbuf, np, n0, top, + bn_get_bits5(p->d, bits -= 5)); + } + } else { + while (bits > 0) { + bn_power5(tmp.d, tmp.d, powerbuf, np, n0, top, + bn_get_bits5(p->d, bits -= 5)); + } + } + + ret = bn_from_montgomery(tmp.d, tmp.d, NULL, np, n0, top); + tmp.top = top; + bn_correct_top(&tmp); + if (ret) { + if (!BN_copy(rr, &tmp)) + ret = 0; + goto err; /* non-zero ret means it's not error */ + } + } else +#endif + { + if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, 0, window)) + goto err; + if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&am, top, powerbuf, 1, window)) + goto err; + + /* + * If the window size is greater than 1, then calculate + * val[i=2..2^winsize-1]. Powers are computed as a*a^(i-1) (even + * powers could instead be computed as (a^(i/2))^2 to use the slight + * performance advantage of sqr over mul). + */ + if (window > 1) { + if (!bn_mul_mont_fixed_top(&tmp, &am, &am, mont, ctx)) + goto err; + if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, 2, + window)) + goto err; + for (i = 3; i < numPowers; i++) { + /* Calculate a^i = a^(i-1) * a */ + if (!bn_mul_mont_fixed_top(&tmp, &am, &tmp, mont, ctx)) + goto err; + if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, i, + window)) + goto err; + } + } + + /* + * The exponent may not have a whole number of fixed-size windows. + * To simplify the main loop, the initial window has between 1 and + * full-window-size bits such that what remains is always a whole + * number of windows + */ + window0 = (bits - 1) % window + 1; + wmask = (1 << window0) - 1; + bits -= window0; + wvalue = bn_get_bits(p, bits) & wmask; + if (!MOD_EXP_CTIME_COPY_FROM_PREBUF(&tmp, top, powerbuf, wvalue, + window)) + goto err; + + wmask = (1 << window) - 1; + /* + * Scan the exponent one window at a time starting from the most + * significant bits. + */ + while (bits > 0) { + + /* Square the result window-size times */ + for (i = 0; i < window; i++) + if (!bn_mul_mont_fixed_top(&tmp, &tmp, &tmp, mont, ctx)) + goto err; + + /* + * Get a window's worth of bits from the exponent + * This avoids calling BN_is_bit_set for each bit, which + * is not only slower but also makes each bit vulnerable to + * EM (and likely other) side-channel attacks like One&Done + * (for details see "One&Done: A Single-Decryption EM-Based + * Attack on OpenSSL's Constant-Time Blinded RSA" by M. Alam, + * H. Khan, M. Dey, N. Sinha, R. Callan, A. Zajic, and + * M. Prvulovic, in USENIX Security'18) + */ + bits -= window; + wvalue = bn_get_bits(p, bits) & wmask; + /* + * Fetch the appropriate pre-computed value from the pre-buf + */ + if (!MOD_EXP_CTIME_COPY_FROM_PREBUF(&am, top, powerbuf, wvalue, + window)) + goto err; + + /* Multiply the result into the intermediate result */ + if (!bn_mul_mont_fixed_top(&tmp, &tmp, &am, mont, ctx)) + goto err; + } + } + + /* + * Done with zero-padded intermediate BIGNUMs. Final BN_from_montgomery + * removes padding [if any] and makes return value suitable for public + * API consumer. + */ +#if defined(SPARC_T4_MONT) + if (OPENSSL_sparcv9cap_P[0] & (SPARCV9_VIS3 | SPARCV9_PREFER_FPU)) { + am.d[0] = 1; /* borrow am */ + for (i = 1; i < top; i++) + am.d[i] = 0; + if (!BN_mod_mul_montgomery(rr, &tmp, &am, mont, ctx)) + goto err; + } else +#endif + if (!BN_from_montgomery(rr, &tmp, mont, ctx)) + goto err; + ret = 1; + err: + if (in_mont == NULL) + BN_MONT_CTX_free(mont); + if (powerbuf != NULL) { + OPENSSL_cleanse(powerbuf, powerbufLen); + OPENSSL_free(powerbufFree); + } + BN_CTX_end(ctx); + return ret; +} + +int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont) +{ + BN_MONT_CTX *mont = NULL; + int b, bits, ret = 0; + int r_is_one; + BN_ULONG w, next_w; + BIGNUM *r, *t; + BIGNUM *swap_tmp; +#define BN_MOD_MUL_WORD(r, w, m) \ + (BN_mul_word(r, (w)) && \ + (/* BN_ucmp(r, (m)) < 0 ? 1 :*/ \ + (BN_mod(t, r, m, ctx) && (swap_tmp = r, r = t, t = swap_tmp, 1)))) + /* + * BN_MOD_MUL_WORD is only used with 'w' large, so the BN_ucmp test is + * probably more overhead than always using BN_mod (which uses BN_copy if + * a similar test returns true). + */ + /* + * We can use BN_mod and do not need BN_nnmod because our accumulator is + * never negative (the result of BN_mod does not depend on the sign of + * the modulus). + */ +#define BN_TO_MONTGOMERY_WORD(r, w, mont) \ + (BN_set_word(r, (w)) && BN_to_montgomery(r, r, (mont), ctx)) + + if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0 + || BN_get_flags(m, BN_FLG_CONSTTIME) != 0) { + /* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */ + BNerr(BN_F_BN_MOD_EXP_MONT_WORD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + bn_check_top(p); + bn_check_top(m); + + if (!BN_is_odd(m)) { + BNerr(BN_F_BN_MOD_EXP_MONT_WORD, BN_R_CALLED_WITH_EVEN_MODULUS); + return 0; + } + if (m->top == 1) + a %= m->d[0]; /* make sure that 'a' is reduced */ + + bits = BN_num_bits(p); + if (bits == 0) { + /* x**0 mod 1, or x**0 mod -1 is still zero. */ + if (BN_abs_is_word(m, 1)) { + ret = 1; + BN_zero(rr); + } else { + ret = BN_one(rr); + } + return ret; + } + if (a == 0) { + BN_zero(rr); + ret = 1; + return ret; + } + + BN_CTX_start(ctx); + r = BN_CTX_get(ctx); + t = BN_CTX_get(ctx); + if (t == NULL) + goto err; + + if (in_mont != NULL) + mont = in_mont; + else { + if ((mont = BN_MONT_CTX_new()) == NULL) + goto err; + if (!BN_MONT_CTX_set(mont, m, ctx)) + goto err; + } + + r_is_one = 1; /* except for Montgomery factor */ + + /* bits-1 >= 0 */ + + /* The result is accumulated in the product r*w. */ + w = a; /* bit 'bits-1' of 'p' is always set */ + for (b = bits - 2; b >= 0; b--) { + /* First, square r*w. */ + next_w = w * w; + if ((next_w / w) != w) { /* overflow */ + if (r_is_one) { + if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) + goto err; + r_is_one = 0; + } else { + if (!BN_MOD_MUL_WORD(r, w, m)) + goto err; + } + next_w = 1; + } + w = next_w; + if (!r_is_one) { + if (!BN_mod_mul_montgomery(r, r, r, mont, ctx)) + goto err; + } + + /* Second, multiply r*w by 'a' if exponent bit is set. */ + if (BN_is_bit_set(p, b)) { + next_w = w * a; + if ((next_w / a) != w) { /* overflow */ + if (r_is_one) { + if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) + goto err; + r_is_one = 0; + } else { + if (!BN_MOD_MUL_WORD(r, w, m)) + goto err; + } + next_w = a; + } + w = next_w; + } + } + + /* Finally, set r:=r*w. */ + if (w != 1) { + if (r_is_one) { + if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) + goto err; + r_is_one = 0; + } else { + if (!BN_MOD_MUL_WORD(r, w, m)) + goto err; + } + } + + if (r_is_one) { /* can happen only if a == 1 */ + if (!BN_one(rr)) + goto err; + } else { + if (!BN_from_montgomery(rr, r, mont, ctx)) + goto err; + } + ret = 1; + err: + if (in_mont == NULL) + BN_MONT_CTX_free(mont); + BN_CTX_end(ctx); + bn_check_top(rr); + return ret; +} + +/* The old fallback, simple version :-) */ +int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx) +{ + int i, j, bits, ret = 0, wstart, wend, window, wvalue; + int start = 1; + BIGNUM *d; + /* Table of variables obtained from 'ctx' */ + BIGNUM *val[TABLE_SIZE]; + + if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0 + || BN_get_flags(a, BN_FLG_CONSTTIME) != 0 + || BN_get_flags(m, BN_FLG_CONSTTIME) != 0) { + /* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */ + BNerr(BN_F_BN_MOD_EXP_SIMPLE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + bits = BN_num_bits(p); + if (bits == 0) { + /* x**0 mod 1, or x**0 mod -1 is still zero. */ + if (BN_abs_is_word(m, 1)) { + ret = 1; + BN_zero(r); + } else { + ret = BN_one(r); + } + return ret; + } + + BN_CTX_start(ctx); + d = BN_CTX_get(ctx); + val[0] = BN_CTX_get(ctx); + if (val[0] == NULL) + goto err; + + if (!BN_nnmod(val[0], a, m, ctx)) + goto err; /* 1 */ + if (BN_is_zero(val[0])) { + BN_zero(r); + ret = 1; + goto err; + } + + window = BN_window_bits_for_exponent_size(bits); + if (window > 1) { + if (!BN_mod_mul(d, val[0], val[0], m, ctx)) + goto err; /* 2 */ + j = 1 << (window - 1); + for (i = 1; i < j; i++) { + if (((val[i] = BN_CTX_get(ctx)) == NULL) || + !BN_mod_mul(val[i], val[i - 1], d, m, ctx)) + goto err; + } + } + + start = 1; /* This is used to avoid multiplication etc + * when there is only the value '1' in the + * buffer. */ + wvalue = 0; /* The 'value' of the window */ + wstart = bits - 1; /* The top bit of the window */ + wend = 0; /* The bottom bit of the window */ + + if (!BN_one(r)) + goto err; + + for (;;) { + if (BN_is_bit_set(p, wstart) == 0) { + if (!start) + if (!BN_mod_mul(r, r, r, m, ctx)) + goto err; + if (wstart == 0) + break; + wstart--; + continue; + } + /* + * We now have wstart on a 'set' bit, we now need to work out how bit + * a window to do. To do this we need to scan forward until the last + * set bit before the end of the window + */ + j = wstart; + wvalue = 1; + wend = 0; + for (i = 1; i < window; i++) { + if (wstart - i < 0) + break; + if (BN_is_bit_set(p, wstart - i)) { + wvalue <<= (i - wend); + wvalue |= 1; + wend = i; + } + } + + /* wend is the size of the current window */ + j = wend + 1; + /* add the 'bytes above' */ + if (!start) + for (i = 0; i < j; i++) { + if (!BN_mod_mul(r, r, r, m, ctx)) + goto err; + } + + /* wvalue will be an odd number < 2^window */ + if (!BN_mod_mul(r, r, val[wvalue >> 1], m, ctx)) + goto err; + + /* move the 'window' down further */ + wstart -= wend + 1; + wvalue = 0; + start = 0; + if (wstart < 0) + break; + } + ret = 1; + err: + BN_CTX_end(ctx); + bn_check_top(r); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_exp2.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_exp2.c new file mode 100644 index 000000000..082c9286a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_exp2.c @@ -0,0 +1,201 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include "bn_lcl.h" + +#define TABLE_SIZE 32 + +int BN_mod_exp2_mont(BIGNUM *rr, const BIGNUM *a1, const BIGNUM *p1, + const BIGNUM *a2, const BIGNUM *p2, const BIGNUM *m, + BN_CTX *ctx, BN_MONT_CTX *in_mont) +{ + int i, j, bits, b, bits1, bits2, ret = + 0, wpos1, wpos2, window1, window2, wvalue1, wvalue2; + int r_is_one = 1; + BIGNUM *d, *r; + const BIGNUM *a_mod_m; + /* Tables of variables obtained from 'ctx' */ + BIGNUM *val1[TABLE_SIZE], *val2[TABLE_SIZE]; + BN_MONT_CTX *mont = NULL; + + bn_check_top(a1); + bn_check_top(p1); + bn_check_top(a2); + bn_check_top(p2); + bn_check_top(m); + + if (!(m->d[0] & 1)) { + BNerr(BN_F_BN_MOD_EXP2_MONT, BN_R_CALLED_WITH_EVEN_MODULUS); + return 0; + } + bits1 = BN_num_bits(p1); + bits2 = BN_num_bits(p2); + if ((bits1 == 0) && (bits2 == 0)) { + ret = BN_one(rr); + return ret; + } + + bits = (bits1 > bits2) ? bits1 : bits2; + + BN_CTX_start(ctx); + d = BN_CTX_get(ctx); + r = BN_CTX_get(ctx); + val1[0] = BN_CTX_get(ctx); + val2[0] = BN_CTX_get(ctx); + if (val2[0] == NULL) + goto err; + + if (in_mont != NULL) + mont = in_mont; + else { + if ((mont = BN_MONT_CTX_new()) == NULL) + goto err; + if (!BN_MONT_CTX_set(mont, m, ctx)) + goto err; + } + + window1 = BN_window_bits_for_exponent_size(bits1); + window2 = BN_window_bits_for_exponent_size(bits2); + + /* + * Build table for a1: val1[i] := a1^(2*i + 1) mod m for i = 0 .. 2^(window1-1) + */ + if (a1->neg || BN_ucmp(a1, m) >= 0) { + if (!BN_mod(val1[0], a1, m, ctx)) + goto err; + a_mod_m = val1[0]; + } else + a_mod_m = a1; + if (BN_is_zero(a_mod_m)) { + BN_zero(rr); + ret = 1; + goto err; + } + + if (!BN_to_montgomery(val1[0], a_mod_m, mont, ctx)) + goto err; + if (window1 > 1) { + if (!BN_mod_mul_montgomery(d, val1[0], val1[0], mont, ctx)) + goto err; + + j = 1 << (window1 - 1); + for (i = 1; i < j; i++) { + if (((val1[i] = BN_CTX_get(ctx)) == NULL) || + !BN_mod_mul_montgomery(val1[i], val1[i - 1], d, mont, ctx)) + goto err; + } + } + + /* + * Build table for a2: val2[i] := a2^(2*i + 1) mod m for i = 0 .. 2^(window2-1) + */ + if (a2->neg || BN_ucmp(a2, m) >= 0) { + if (!BN_mod(val2[0], a2, m, ctx)) + goto err; + a_mod_m = val2[0]; + } else + a_mod_m = a2; + if (BN_is_zero(a_mod_m)) { + BN_zero(rr); + ret = 1; + goto err; + } + if (!BN_to_montgomery(val2[0], a_mod_m, mont, ctx)) + goto err; + if (window2 > 1) { + if (!BN_mod_mul_montgomery(d, val2[0], val2[0], mont, ctx)) + goto err; + + j = 1 << (window2 - 1); + for (i = 1; i < j; i++) { + if (((val2[i] = BN_CTX_get(ctx)) == NULL) || + !BN_mod_mul_montgomery(val2[i], val2[i - 1], d, mont, ctx)) + goto err; + } + } + + /* Now compute the power product, using independent windows. */ + r_is_one = 1; + wvalue1 = 0; /* The 'value' of the first window */ + wvalue2 = 0; /* The 'value' of the second window */ + wpos1 = 0; /* If wvalue1 > 0, the bottom bit of the + * first window */ + wpos2 = 0; /* If wvalue2 > 0, the bottom bit of the + * second window */ + + if (!BN_to_montgomery(r, BN_value_one(), mont, ctx)) + goto err; + for (b = bits - 1; b >= 0; b--) { + if (!r_is_one) { + if (!BN_mod_mul_montgomery(r, r, r, mont, ctx)) + goto err; + } + + if (!wvalue1) + if (BN_is_bit_set(p1, b)) { + /* + * consider bits b-window1+1 .. b for this window + */ + i = b - window1 + 1; + while (!BN_is_bit_set(p1, i)) /* works for i<0 */ + i++; + wpos1 = i; + wvalue1 = 1; + for (i = b - 1; i >= wpos1; i--) { + wvalue1 <<= 1; + if (BN_is_bit_set(p1, i)) + wvalue1++; + } + } + + if (!wvalue2) + if (BN_is_bit_set(p2, b)) { + /* + * consider bits b-window2+1 .. b for this window + */ + i = b - window2 + 1; + while (!BN_is_bit_set(p2, i)) + i++; + wpos2 = i; + wvalue2 = 1; + for (i = b - 1; i >= wpos2; i--) { + wvalue2 <<= 1; + if (BN_is_bit_set(p2, i)) + wvalue2++; + } + } + + if (wvalue1 && b == wpos1) { + /* wvalue1 is odd and < 2^window1 */ + if (!BN_mod_mul_montgomery(r, r, val1[wvalue1 >> 1], mont, ctx)) + goto err; + wvalue1 = 0; + r_is_one = 0; + } + + if (wvalue2 && b == wpos2) { + /* wvalue2 is odd and < 2^window2 */ + if (!BN_mod_mul_montgomery(r, r, val2[wvalue2 >> 1], mont, ctx)) + goto err; + wvalue2 = 0; + r_is_one = 0; + } + } + if (!BN_from_montgomery(rr, r, mont, ctx)) + goto err; + ret = 1; + err: + if (in_mont == NULL) + BN_MONT_CTX_free(mont); + BN_CTX_end(ctx); + bn_check_top(rr); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_gcd.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_gcd.c new file mode 100644 index 000000000..0091ea4e0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_gcd.c @@ -0,0 +1,623 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include "bn_lcl.h" + +static BIGNUM *euclid(BIGNUM *a, BIGNUM *b); + +int BN_gcd(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx) +{ + BIGNUM *a, *b, *t; + int ret = 0; + + bn_check_top(in_a); + bn_check_top(in_b); + + BN_CTX_start(ctx); + a = BN_CTX_get(ctx); + b = BN_CTX_get(ctx); + if (b == NULL) + goto err; + + if (BN_copy(a, in_a) == NULL) + goto err; + if (BN_copy(b, in_b) == NULL) + goto err; + a->neg = 0; + b->neg = 0; + + if (BN_cmp(a, b) < 0) { + t = a; + a = b; + b = t; + } + t = euclid(a, b); + if (t == NULL) + goto err; + + if (BN_copy(r, t) == NULL) + goto err; + ret = 1; + err: + BN_CTX_end(ctx); + bn_check_top(r); + return ret; +} + +static BIGNUM *euclid(BIGNUM *a, BIGNUM *b) +{ + BIGNUM *t; + int shifts = 0; + + bn_check_top(a); + bn_check_top(b); + + /* 0 <= b <= a */ + while (!BN_is_zero(b)) { + /* 0 < b <= a */ + + if (BN_is_odd(a)) { + if (BN_is_odd(b)) { + if (!BN_sub(a, a, b)) + goto err; + if (!BN_rshift1(a, a)) + goto err; + if (BN_cmp(a, b) < 0) { + t = a; + a = b; + b = t; + } + } else { /* a odd - b even */ + + if (!BN_rshift1(b, b)) + goto err; + if (BN_cmp(a, b) < 0) { + t = a; + a = b; + b = t; + } + } + } else { /* a is even */ + + if (BN_is_odd(b)) { + if (!BN_rshift1(a, a)) + goto err; + if (BN_cmp(a, b) < 0) { + t = a; + a = b; + b = t; + } + } else { /* a even - b even */ + + if (!BN_rshift1(a, a)) + goto err; + if (!BN_rshift1(b, b)) + goto err; + shifts++; + } + } + /* 0 <= b <= a */ + } + + if (shifts) { + if (!BN_lshift(a, a, shifts)) + goto err; + } + bn_check_top(a); + return a; + err: + return NULL; +} + +/* solves ax == 1 (mod n) */ +static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *in, + const BIGNUM *a, const BIGNUM *n, + BN_CTX *ctx); + +BIGNUM *BN_mod_inverse(BIGNUM *in, + const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx) +{ + BIGNUM *rv; + int noinv; + rv = int_bn_mod_inverse(in, a, n, ctx, &noinv); + if (noinv) + BNerr(BN_F_BN_MOD_INVERSE, BN_R_NO_INVERSE); + return rv; +} + +BIGNUM *int_bn_mod_inverse(BIGNUM *in, + const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx, + int *pnoinv) +{ + BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL; + BIGNUM *ret = NULL; + int sign; + + /* This is invalid input so we don't worry about constant time here */ + if (BN_abs_is_word(n, 1) || BN_is_zero(n)) { + if (pnoinv != NULL) + *pnoinv = 1; + return NULL; + } + + if (pnoinv != NULL) + *pnoinv = 0; + + if ((BN_get_flags(a, BN_FLG_CONSTTIME) != 0) + || (BN_get_flags(n, BN_FLG_CONSTTIME) != 0)) { + return BN_mod_inverse_no_branch(in, a, n, ctx); + } + + bn_check_top(a); + bn_check_top(n); + + BN_CTX_start(ctx); + A = BN_CTX_get(ctx); + B = BN_CTX_get(ctx); + X = BN_CTX_get(ctx); + D = BN_CTX_get(ctx); + M = BN_CTX_get(ctx); + Y = BN_CTX_get(ctx); + T = BN_CTX_get(ctx); + if (T == NULL) + goto err; + + if (in == NULL) + R = BN_new(); + else + R = in; + if (R == NULL) + goto err; + + BN_one(X); + BN_zero(Y); + if (BN_copy(B, a) == NULL) + goto err; + if (BN_copy(A, n) == NULL) + goto err; + A->neg = 0; + if (B->neg || (BN_ucmp(B, A) >= 0)) { + if (!BN_nnmod(B, B, A, ctx)) + goto err; + } + sign = -1; + /*- + * From B = a mod |n|, A = |n| it follows that + * + * 0 <= B < A, + * -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|). + */ + + if (BN_is_odd(n) && (BN_num_bits(n) <= 2048)) { + /* + * Binary inversion algorithm; requires odd modulus. This is faster + * than the general algorithm if the modulus is sufficiently small + * (about 400 .. 500 bits on 32-bit systems, but much more on 64-bit + * systems) + */ + int shift; + + while (!BN_is_zero(B)) { + /*- + * 0 < B < |n|, + * 0 < A <= |n|, + * (1) -sign*X*a == B (mod |n|), + * (2) sign*Y*a == A (mod |n|) + */ + + /* + * Now divide B by the maximum possible power of two in the + * integers, and divide X by the same value mod |n|. When we're + * done, (1) still holds. + */ + shift = 0; + while (!BN_is_bit_set(B, shift)) { /* note that 0 < B */ + shift++; + + if (BN_is_odd(X)) { + if (!BN_uadd(X, X, n)) + goto err; + } + /* + * now X is even, so we can easily divide it by two + */ + if (!BN_rshift1(X, X)) + goto err; + } + if (shift > 0) { + if (!BN_rshift(B, B, shift)) + goto err; + } + + /* + * Same for A and Y. Afterwards, (2) still holds. + */ + shift = 0; + while (!BN_is_bit_set(A, shift)) { /* note that 0 < A */ + shift++; + + if (BN_is_odd(Y)) { + if (!BN_uadd(Y, Y, n)) + goto err; + } + /* now Y is even */ + if (!BN_rshift1(Y, Y)) + goto err; + } + if (shift > 0) { + if (!BN_rshift(A, A, shift)) + goto err; + } + + /*- + * We still have (1) and (2). + * Both A and B are odd. + * The following computations ensure that + * + * 0 <= B < |n|, + * 0 < A < |n|, + * (1) -sign*X*a == B (mod |n|), + * (2) sign*Y*a == A (mod |n|), + * + * and that either A or B is even in the next iteration. + */ + if (BN_ucmp(B, A) >= 0) { + /* -sign*(X + Y)*a == B - A (mod |n|) */ + if (!BN_uadd(X, X, Y)) + goto err; + /* + * NB: we could use BN_mod_add_quick(X, X, Y, n), but that + * actually makes the algorithm slower + */ + if (!BN_usub(B, B, A)) + goto err; + } else { + /* sign*(X + Y)*a == A - B (mod |n|) */ + if (!BN_uadd(Y, Y, X)) + goto err; + /* + * as above, BN_mod_add_quick(Y, Y, X, n) would slow things down + */ + if (!BN_usub(A, A, B)) + goto err; + } + } + } else { + /* general inversion algorithm */ + + while (!BN_is_zero(B)) { + BIGNUM *tmp; + + /*- + * 0 < B < A, + * (*) -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|) + */ + + /* (D, M) := (A/B, A%B) ... */ + if (BN_num_bits(A) == BN_num_bits(B)) { + if (!BN_one(D)) + goto err; + if (!BN_sub(M, A, B)) + goto err; + } else if (BN_num_bits(A) == BN_num_bits(B) + 1) { + /* A/B is 1, 2, or 3 */ + if (!BN_lshift1(T, B)) + goto err; + if (BN_ucmp(A, T) < 0) { + /* A < 2*B, so D=1 */ + if (!BN_one(D)) + goto err; + if (!BN_sub(M, A, B)) + goto err; + } else { + /* A >= 2*B, so D=2 or D=3 */ + if (!BN_sub(M, A, T)) + goto err; + if (!BN_add(D, T, B)) + goto err; /* use D (:= 3*B) as temp */ + if (BN_ucmp(A, D) < 0) { + /* A < 3*B, so D=2 */ + if (!BN_set_word(D, 2)) + goto err; + /* + * M (= A - 2*B) already has the correct value + */ + } else { + /* only D=3 remains */ + if (!BN_set_word(D, 3)) + goto err; + /* + * currently M = A - 2*B, but we need M = A - 3*B + */ + if (!BN_sub(M, M, B)) + goto err; + } + } + } else { + if (!BN_div(D, M, A, B, ctx)) + goto err; + } + + /*- + * Now + * A = D*B + M; + * thus we have + * (**) sign*Y*a == D*B + M (mod |n|). + */ + + tmp = A; /* keep the BIGNUM object, the value does not matter */ + + /* (A, B) := (B, A mod B) ... */ + A = B; + B = M; + /* ... so we have 0 <= B < A again */ + + /*- + * Since the former M is now B and the former B is now A, + * (**) translates into + * sign*Y*a == D*A + B (mod |n|), + * i.e. + * sign*Y*a - D*A == B (mod |n|). + * Similarly, (*) translates into + * -sign*X*a == A (mod |n|). + * + * Thus, + * sign*Y*a + D*sign*X*a == B (mod |n|), + * i.e. + * sign*(Y + D*X)*a == B (mod |n|). + * + * So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at + * -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|). + * Note that X and Y stay non-negative all the time. + */ + + /* + * most of the time D is very small, so we can optimize tmp := D*X+Y + */ + if (BN_is_one(D)) { + if (!BN_add(tmp, X, Y)) + goto err; + } else { + if (BN_is_word(D, 2)) { + if (!BN_lshift1(tmp, X)) + goto err; + } else if (BN_is_word(D, 4)) { + if (!BN_lshift(tmp, X, 2)) + goto err; + } else if (D->top == 1) { + if (!BN_copy(tmp, X)) + goto err; + if (!BN_mul_word(tmp, D->d[0])) + goto err; + } else { + if (!BN_mul(tmp, D, X, ctx)) + goto err; + } + if (!BN_add(tmp, tmp, Y)) + goto err; + } + + M = Y; /* keep the BIGNUM object, the value does not matter */ + Y = X; + X = tmp; + sign = -sign; + } + } + + /*- + * The while loop (Euclid's algorithm) ends when + * A == gcd(a,n); + * we have + * sign*Y*a == A (mod |n|), + * where Y is non-negative. + */ + + if (sign < 0) { + if (!BN_sub(Y, n, Y)) + goto err; + } + /* Now Y*a == A (mod |n|). */ + + if (BN_is_one(A)) { + /* Y*a == 1 (mod |n|) */ + if (!Y->neg && BN_ucmp(Y, n) < 0) { + if (!BN_copy(R, Y)) + goto err; + } else { + if (!BN_nnmod(R, Y, n, ctx)) + goto err; + } + } else { + if (pnoinv) + *pnoinv = 1; + goto err; + } + ret = R; + err: + if ((ret == NULL) && (in == NULL)) + BN_free(R); + BN_CTX_end(ctx); + bn_check_top(ret); + return ret; +} + +/* + * BN_mod_inverse_no_branch is a special version of BN_mod_inverse. It does + * not contain branches that may leak sensitive information. + */ +static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *in, + const BIGNUM *a, const BIGNUM *n, + BN_CTX *ctx) +{ + BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL; + BIGNUM *ret = NULL; + int sign; + + bn_check_top(a); + bn_check_top(n); + + BN_CTX_start(ctx); + A = BN_CTX_get(ctx); + B = BN_CTX_get(ctx); + X = BN_CTX_get(ctx); + D = BN_CTX_get(ctx); + M = BN_CTX_get(ctx); + Y = BN_CTX_get(ctx); + T = BN_CTX_get(ctx); + if (T == NULL) + goto err; + + if (in == NULL) + R = BN_new(); + else + R = in; + if (R == NULL) + goto err; + + BN_one(X); + BN_zero(Y); + if (BN_copy(B, a) == NULL) + goto err; + if (BN_copy(A, n) == NULL) + goto err; + A->neg = 0; + + if (B->neg || (BN_ucmp(B, A) >= 0)) { + /* + * Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, + * BN_div_no_branch will be called eventually. + */ + { + BIGNUM local_B; + bn_init(&local_B); + BN_with_flags(&local_B, B, BN_FLG_CONSTTIME); + if (!BN_nnmod(B, &local_B, A, ctx)) + goto err; + /* Ensure local_B goes out of scope before any further use of B */ + } + } + sign = -1; + /*- + * From B = a mod |n|, A = |n| it follows that + * + * 0 <= B < A, + * -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|). + */ + + while (!BN_is_zero(B)) { + BIGNUM *tmp; + + /*- + * 0 < B < A, + * (*) -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|) + */ + + /* + * Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, + * BN_div_no_branch will be called eventually. + */ + { + BIGNUM local_A; + bn_init(&local_A); + BN_with_flags(&local_A, A, BN_FLG_CONSTTIME); + + /* (D, M) := (A/B, A%B) ... */ + if (!BN_div(D, M, &local_A, B, ctx)) + goto err; + /* Ensure local_A goes out of scope before any further use of A */ + } + + /*- + * Now + * A = D*B + M; + * thus we have + * (**) sign*Y*a == D*B + M (mod |n|). + */ + + tmp = A; /* keep the BIGNUM object, the value does not + * matter */ + + /* (A, B) := (B, A mod B) ... */ + A = B; + B = M; + /* ... so we have 0 <= B < A again */ + + /*- + * Since the former M is now B and the former B is now A, + * (**) translates into + * sign*Y*a == D*A + B (mod |n|), + * i.e. + * sign*Y*a - D*A == B (mod |n|). + * Similarly, (*) translates into + * -sign*X*a == A (mod |n|). + * + * Thus, + * sign*Y*a + D*sign*X*a == B (mod |n|), + * i.e. + * sign*(Y + D*X)*a == B (mod |n|). + * + * So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at + * -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|). + * Note that X and Y stay non-negative all the time. + */ + + if (!BN_mul(tmp, D, X, ctx)) + goto err; + if (!BN_add(tmp, tmp, Y)) + goto err; + + M = Y; /* keep the BIGNUM object, the value does not + * matter */ + Y = X; + X = tmp; + sign = -sign; + } + + /*- + * The while loop (Euclid's algorithm) ends when + * A == gcd(a,n); + * we have + * sign*Y*a == A (mod |n|), + * where Y is non-negative. + */ + + if (sign < 0) { + if (!BN_sub(Y, n, Y)) + goto err; + } + /* Now Y*a == A (mod |n|). */ + + if (BN_is_one(A)) { + /* Y*a == 1 (mod |n|) */ + if (!Y->neg && BN_ucmp(Y, n) < 0) { + if (!BN_copy(R, Y)) + goto err; + } else { + if (!BN_nnmod(R, Y, n, ctx)) + goto err; + } + } else { + BNerr(BN_F_BN_MOD_INVERSE_NO_BRANCH, BN_R_NO_INVERSE); + goto err; + } + ret = R; + err: + if ((ret == NULL) && (in == NULL)) + BN_free(R); + BN_CTX_end(ctx); + bn_check_top(ret); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_gf2m.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_gf2m.c new file mode 100644 index 000000000..34d8b69c1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_gf2m.c @@ -0,0 +1,1166 @@ +/* + * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "internal/cryptlib.h" +#include "bn_lcl.h" + +#ifndef OPENSSL_NO_EC2M + +/* + * Maximum number of iterations before BN_GF2m_mod_solve_quad_arr should + * fail. + */ +# define MAX_ITERATIONS 50 + +# define SQR_nibble(w) ((((w) & 8) << 3) \ + | (((w) & 4) << 2) \ + | (((w) & 2) << 1) \ + | ((w) & 1)) + + +/* Platform-specific macros to accelerate squaring. */ +# if defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG) +# define SQR1(w) \ + SQR_nibble((w) >> 60) << 56 | SQR_nibble((w) >> 56) << 48 | \ + SQR_nibble((w) >> 52) << 40 | SQR_nibble((w) >> 48) << 32 | \ + SQR_nibble((w) >> 44) << 24 | SQR_nibble((w) >> 40) << 16 | \ + SQR_nibble((w) >> 36) << 8 | SQR_nibble((w) >> 32) +# define SQR0(w) \ + SQR_nibble((w) >> 28) << 56 | SQR_nibble((w) >> 24) << 48 | \ + SQR_nibble((w) >> 20) << 40 | SQR_nibble((w) >> 16) << 32 | \ + SQR_nibble((w) >> 12) << 24 | SQR_nibble((w) >> 8) << 16 | \ + SQR_nibble((w) >> 4) << 8 | SQR_nibble((w) ) +# endif +# ifdef THIRTY_TWO_BIT +# define SQR1(w) \ + SQR_nibble((w) >> 28) << 24 | SQR_nibble((w) >> 24) << 16 | \ + SQR_nibble((w) >> 20) << 8 | SQR_nibble((w) >> 16) +# define SQR0(w) \ + SQR_nibble((w) >> 12) << 24 | SQR_nibble((w) >> 8) << 16 | \ + SQR_nibble((w) >> 4) << 8 | SQR_nibble((w) ) +# endif + +# if !defined(OPENSSL_BN_ASM_GF2m) +/* + * Product of two polynomials a, b each with degree < BN_BITS2 - 1, result is + * a polynomial r with degree < 2 * BN_BITS - 1 The caller MUST ensure that + * the variables have the right amount of space allocated. + */ +# ifdef THIRTY_TWO_BIT +static void bn_GF2m_mul_1x1(BN_ULONG *r1, BN_ULONG *r0, const BN_ULONG a, + const BN_ULONG b) +{ + register BN_ULONG h, l, s; + BN_ULONG tab[8], top2b = a >> 30; + register BN_ULONG a1, a2, a4; + + a1 = a & (0x3FFFFFFF); + a2 = a1 << 1; + a4 = a2 << 1; + + tab[0] = 0; + tab[1] = a1; + tab[2] = a2; + tab[3] = a1 ^ a2; + tab[4] = a4; + tab[5] = a1 ^ a4; + tab[6] = a2 ^ a4; + tab[7] = a1 ^ a2 ^ a4; + + s = tab[b & 0x7]; + l = s; + s = tab[b >> 3 & 0x7]; + l ^= s << 3; + h = s >> 29; + s = tab[b >> 6 & 0x7]; + l ^= s << 6; + h ^= s >> 26; + s = tab[b >> 9 & 0x7]; + l ^= s << 9; + h ^= s >> 23; + s = tab[b >> 12 & 0x7]; + l ^= s << 12; + h ^= s >> 20; + s = tab[b >> 15 & 0x7]; + l ^= s << 15; + h ^= s >> 17; + s = tab[b >> 18 & 0x7]; + l ^= s << 18; + h ^= s >> 14; + s = tab[b >> 21 & 0x7]; + l ^= s << 21; + h ^= s >> 11; + s = tab[b >> 24 & 0x7]; + l ^= s << 24; + h ^= s >> 8; + s = tab[b >> 27 & 0x7]; + l ^= s << 27; + h ^= s >> 5; + s = tab[b >> 30]; + l ^= s << 30; + h ^= s >> 2; + + /* compensate for the top two bits of a */ + + if (top2b & 01) { + l ^= b << 30; + h ^= b >> 2; + } + if (top2b & 02) { + l ^= b << 31; + h ^= b >> 1; + } + + *r1 = h; + *r0 = l; +} +# endif +# if defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG) +static void bn_GF2m_mul_1x1(BN_ULONG *r1, BN_ULONG *r0, const BN_ULONG a, + const BN_ULONG b) +{ + register BN_ULONG h, l, s; + BN_ULONG tab[16], top3b = a >> 61; + register BN_ULONG a1, a2, a4, a8; + + a1 = a & (0x1FFFFFFFFFFFFFFFULL); + a2 = a1 << 1; + a4 = a2 << 1; + a8 = a4 << 1; + + tab[0] = 0; + tab[1] = a1; + tab[2] = a2; + tab[3] = a1 ^ a2; + tab[4] = a4; + tab[5] = a1 ^ a4; + tab[6] = a2 ^ a4; + tab[7] = a1 ^ a2 ^ a4; + tab[8] = a8; + tab[9] = a1 ^ a8; + tab[10] = a2 ^ a8; + tab[11] = a1 ^ a2 ^ a8; + tab[12] = a4 ^ a8; + tab[13] = a1 ^ a4 ^ a8; + tab[14] = a2 ^ a4 ^ a8; + tab[15] = a1 ^ a2 ^ a4 ^ a8; + + s = tab[b & 0xF]; + l = s; + s = tab[b >> 4 & 0xF]; + l ^= s << 4; + h = s >> 60; + s = tab[b >> 8 & 0xF]; + l ^= s << 8; + h ^= s >> 56; + s = tab[b >> 12 & 0xF]; + l ^= s << 12; + h ^= s >> 52; + s = tab[b >> 16 & 0xF]; + l ^= s << 16; + h ^= s >> 48; + s = tab[b >> 20 & 0xF]; + l ^= s << 20; + h ^= s >> 44; + s = tab[b >> 24 & 0xF]; + l ^= s << 24; + h ^= s >> 40; + s = tab[b >> 28 & 0xF]; + l ^= s << 28; + h ^= s >> 36; + s = tab[b >> 32 & 0xF]; + l ^= s << 32; + h ^= s >> 32; + s = tab[b >> 36 & 0xF]; + l ^= s << 36; + h ^= s >> 28; + s = tab[b >> 40 & 0xF]; + l ^= s << 40; + h ^= s >> 24; + s = tab[b >> 44 & 0xF]; + l ^= s << 44; + h ^= s >> 20; + s = tab[b >> 48 & 0xF]; + l ^= s << 48; + h ^= s >> 16; + s = tab[b >> 52 & 0xF]; + l ^= s << 52; + h ^= s >> 12; + s = tab[b >> 56 & 0xF]; + l ^= s << 56; + h ^= s >> 8; + s = tab[b >> 60]; + l ^= s << 60; + h ^= s >> 4; + + /* compensate for the top three bits of a */ + + if (top3b & 01) { + l ^= b << 61; + h ^= b >> 3; + } + if (top3b & 02) { + l ^= b << 62; + h ^= b >> 2; + } + if (top3b & 04) { + l ^= b << 63; + h ^= b >> 1; + } + + *r1 = h; + *r0 = l; +} +# endif + +/* + * Product of two polynomials a, b each with degree < 2 * BN_BITS2 - 1, + * result is a polynomial r with degree < 4 * BN_BITS2 - 1 The caller MUST + * ensure that the variables have the right amount of space allocated. + */ +static void bn_GF2m_mul_2x2(BN_ULONG *r, const BN_ULONG a1, const BN_ULONG a0, + const BN_ULONG b1, const BN_ULONG b0) +{ + BN_ULONG m1, m0; + /* r[3] = h1, r[2] = h0; r[1] = l1; r[0] = l0 */ + bn_GF2m_mul_1x1(r + 3, r + 2, a1, b1); + bn_GF2m_mul_1x1(r + 1, r, a0, b0); + bn_GF2m_mul_1x1(&m1, &m0, a0 ^ a1, b0 ^ b1); + /* Correction on m1 ^= l1 ^ h1; m0 ^= l0 ^ h0; */ + r[2] ^= m1 ^ r[1] ^ r[3]; /* h0 ^= m1 ^ l1 ^ h1; */ + r[1] = r[3] ^ r[2] ^ r[0] ^ m1 ^ m0; /* l1 ^= l0 ^ h0 ^ m0; */ +} +# else +void bn_GF2m_mul_2x2(BN_ULONG *r, BN_ULONG a1, BN_ULONG a0, BN_ULONG b1, + BN_ULONG b0); +# endif + +/* + * Add polynomials a and b and store result in r; r could be a or b, a and b + * could be equal; r is the bitwise XOR of a and b. + */ +int BN_GF2m_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) +{ + int i; + const BIGNUM *at, *bt; + + bn_check_top(a); + bn_check_top(b); + + if (a->top < b->top) { + at = b; + bt = a; + } else { + at = a; + bt = b; + } + + if (bn_wexpand(r, at->top) == NULL) + return 0; + + for (i = 0; i < bt->top; i++) { + r->d[i] = at->d[i] ^ bt->d[i]; + } + for (; i < at->top; i++) { + r->d[i] = at->d[i]; + } + + r->top = at->top; + bn_correct_top(r); + + return 1; +} + +/*- + * Some functions allow for representation of the irreducible polynomials + * as an int[], say p. The irreducible f(t) is then of the form: + * t^p[0] + t^p[1] + ... + t^p[k] + * where m = p[0] > p[1] > ... > p[k] = 0. + */ + +/* Performs modular reduction of a and store result in r. r could be a. */ +int BN_GF2m_mod_arr(BIGNUM *r, const BIGNUM *a, const int p[]) +{ + int j, k; + int n, dN, d0, d1; + BN_ULONG zz, *z; + + bn_check_top(a); + + if (!p[0]) { + /* reduction mod 1 => return 0 */ + BN_zero(r); + return 1; + } + + /* + * Since the algorithm does reduction in the r value, if a != r, copy the + * contents of a into r so we can do reduction in r. + */ + if (a != r) { + if (!bn_wexpand(r, a->top)) + return 0; + for (j = 0; j < a->top; j++) { + r->d[j] = a->d[j]; + } + r->top = a->top; + } + z = r->d; + + /* start reduction */ + dN = p[0] / BN_BITS2; + for (j = r->top - 1; j > dN;) { + zz = z[j]; + if (z[j] == 0) { + j--; + continue; + } + z[j] = 0; + + for (k = 1; p[k] != 0; k++) { + /* reducing component t^p[k] */ + n = p[0] - p[k]; + d0 = n % BN_BITS2; + d1 = BN_BITS2 - d0; + n /= BN_BITS2; + z[j - n] ^= (zz >> d0); + if (d0) + z[j - n - 1] ^= (zz << d1); + } + + /* reducing component t^0 */ + n = dN; + d0 = p[0] % BN_BITS2; + d1 = BN_BITS2 - d0; + z[j - n] ^= (zz >> d0); + if (d0) + z[j - n - 1] ^= (zz << d1); + } + + /* final round of reduction */ + while (j == dN) { + + d0 = p[0] % BN_BITS2; + zz = z[dN] >> d0; + if (zz == 0) + break; + d1 = BN_BITS2 - d0; + + /* clear up the top d1 bits */ + if (d0) + z[dN] = (z[dN] << d1) >> d1; + else + z[dN] = 0; + z[0] ^= zz; /* reduction t^0 component */ + + for (k = 1; p[k] != 0; k++) { + BN_ULONG tmp_ulong; + + /* reducing component t^p[k] */ + n = p[k] / BN_BITS2; + d0 = p[k] % BN_BITS2; + d1 = BN_BITS2 - d0; + z[n] ^= (zz << d0); + if (d0 && (tmp_ulong = zz >> d1)) + z[n + 1] ^= tmp_ulong; + } + + } + + bn_correct_top(r); + return 1; +} + +/* + * Performs modular reduction of a by p and store result in r. r could be a. + * This function calls down to the BN_GF2m_mod_arr implementation; this wrapper + * function is only provided for convenience; for best performance, use the + * BN_GF2m_mod_arr function. + */ +int BN_GF2m_mod(BIGNUM *r, const BIGNUM *a, const BIGNUM *p) +{ + int ret = 0; + int arr[6]; + bn_check_top(a); + bn_check_top(p); + ret = BN_GF2m_poly2arr(p, arr, OSSL_NELEM(arr)); + if (!ret || ret > (int)OSSL_NELEM(arr)) { + BNerr(BN_F_BN_GF2M_MOD, BN_R_INVALID_LENGTH); + return 0; + } + ret = BN_GF2m_mod_arr(r, a, arr); + bn_check_top(r); + return ret; +} + +/* + * Compute the product of two polynomials a and b, reduce modulo p, and store + * the result in r. r could be a or b; a could be b. + */ +int BN_GF2m_mod_mul_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const int p[], BN_CTX *ctx) +{ + int zlen, i, j, k, ret = 0; + BIGNUM *s; + BN_ULONG x1, x0, y1, y0, zz[4]; + + bn_check_top(a); + bn_check_top(b); + + if (a == b) { + return BN_GF2m_mod_sqr_arr(r, a, p, ctx); + } + + BN_CTX_start(ctx); + if ((s = BN_CTX_get(ctx)) == NULL) + goto err; + + zlen = a->top + b->top + 4; + if (!bn_wexpand(s, zlen)) + goto err; + s->top = zlen; + + for (i = 0; i < zlen; i++) + s->d[i] = 0; + + for (j = 0; j < b->top; j += 2) { + y0 = b->d[j]; + y1 = ((j + 1) == b->top) ? 0 : b->d[j + 1]; + for (i = 0; i < a->top; i += 2) { + x0 = a->d[i]; + x1 = ((i + 1) == a->top) ? 0 : a->d[i + 1]; + bn_GF2m_mul_2x2(zz, x1, x0, y1, y0); + for (k = 0; k < 4; k++) + s->d[i + j + k] ^= zz[k]; + } + } + + bn_correct_top(s); + if (BN_GF2m_mod_arr(r, s, p)) + ret = 1; + bn_check_top(r); + + err: + BN_CTX_end(ctx); + return ret; +} + +/* + * Compute the product of two polynomials a and b, reduce modulo p, and store + * the result in r. r could be a or b; a could equal b. This function calls + * down to the BN_GF2m_mod_mul_arr implementation; this wrapper function is + * only provided for convenience; for best performance, use the + * BN_GF2m_mod_mul_arr function. + */ +int BN_GF2m_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *p, BN_CTX *ctx) +{ + int ret = 0; + const int max = BN_num_bits(p) + 1; + int *arr = NULL; + bn_check_top(a); + bn_check_top(b); + bn_check_top(p); + if ((arr = OPENSSL_malloc(sizeof(*arr) * max)) == NULL) + goto err; + ret = BN_GF2m_poly2arr(p, arr, max); + if (!ret || ret > max) { + BNerr(BN_F_BN_GF2M_MOD_MUL, BN_R_INVALID_LENGTH); + goto err; + } + ret = BN_GF2m_mod_mul_arr(r, a, b, arr, ctx); + bn_check_top(r); + err: + OPENSSL_free(arr); + return ret; +} + +/* Square a, reduce the result mod p, and store it in a. r could be a. */ +int BN_GF2m_mod_sqr_arr(BIGNUM *r, const BIGNUM *a, const int p[], + BN_CTX *ctx) +{ + int i, ret = 0; + BIGNUM *s; + + bn_check_top(a); + BN_CTX_start(ctx); + if ((s = BN_CTX_get(ctx)) == NULL) + goto err; + if (!bn_wexpand(s, 2 * a->top)) + goto err; + + for (i = a->top - 1; i >= 0; i--) { + s->d[2 * i + 1] = SQR1(a->d[i]); + s->d[2 * i] = SQR0(a->d[i]); + } + + s->top = 2 * a->top; + bn_correct_top(s); + if (!BN_GF2m_mod_arr(r, s, p)) + goto err; + bn_check_top(r); + ret = 1; + err: + BN_CTX_end(ctx); + return ret; +} + +/* + * Square a, reduce the result mod p, and store it in a. r could be a. This + * function calls down to the BN_GF2m_mod_sqr_arr implementation; this + * wrapper function is only provided for convenience; for best performance, + * use the BN_GF2m_mod_sqr_arr function. + */ +int BN_GF2m_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) +{ + int ret = 0; + const int max = BN_num_bits(p) + 1; + int *arr = NULL; + + bn_check_top(a); + bn_check_top(p); + if ((arr = OPENSSL_malloc(sizeof(*arr) * max)) == NULL) + goto err; + ret = BN_GF2m_poly2arr(p, arr, max); + if (!ret || ret > max) { + BNerr(BN_F_BN_GF2M_MOD_SQR, BN_R_INVALID_LENGTH); + goto err; + } + ret = BN_GF2m_mod_sqr_arr(r, a, arr, ctx); + bn_check_top(r); + err: + OPENSSL_free(arr); + return ret; +} + +/* + * Invert a, reduce modulo p, and store the result in r. r could be a. Uses + * Modified Almost Inverse Algorithm (Algorithm 10) from Hankerson, D., + * Hernandez, J.L., and Menezes, A. "Software Implementation of Elliptic + * Curve Cryptography Over Binary Fields". + */ +static int BN_GF2m_mod_inv_vartime(BIGNUM *r, const BIGNUM *a, + const BIGNUM *p, BN_CTX *ctx) +{ + BIGNUM *b, *c = NULL, *u = NULL, *v = NULL, *tmp; + int ret = 0; + + bn_check_top(a); + bn_check_top(p); + + BN_CTX_start(ctx); + + b = BN_CTX_get(ctx); + c = BN_CTX_get(ctx); + u = BN_CTX_get(ctx); + v = BN_CTX_get(ctx); + if (v == NULL) + goto err; + + if (!BN_GF2m_mod(u, a, p)) + goto err; + if (BN_is_zero(u)) + goto err; + + if (!BN_copy(v, p)) + goto err; +# if 0 + if (!BN_one(b)) + goto err; + + while (1) { + while (!BN_is_odd(u)) { + if (BN_is_zero(u)) + goto err; + if (!BN_rshift1(u, u)) + goto err; + if (BN_is_odd(b)) { + if (!BN_GF2m_add(b, b, p)) + goto err; + } + if (!BN_rshift1(b, b)) + goto err; + } + + if (BN_abs_is_word(u, 1)) + break; + + if (BN_num_bits(u) < BN_num_bits(v)) { + tmp = u; + u = v; + v = tmp; + tmp = b; + b = c; + c = tmp; + } + + if (!BN_GF2m_add(u, u, v)) + goto err; + if (!BN_GF2m_add(b, b, c)) + goto err; + } +# else + { + int i; + int ubits = BN_num_bits(u); + int vbits = BN_num_bits(v); /* v is copy of p */ + int top = p->top; + BN_ULONG *udp, *bdp, *vdp, *cdp; + + if (!bn_wexpand(u, top)) + goto err; + udp = u->d; + for (i = u->top; i < top; i++) + udp[i] = 0; + u->top = top; + if (!bn_wexpand(b, top)) + goto err; + bdp = b->d; + bdp[0] = 1; + for (i = 1; i < top; i++) + bdp[i] = 0; + b->top = top; + if (!bn_wexpand(c, top)) + goto err; + cdp = c->d; + for (i = 0; i < top; i++) + cdp[i] = 0; + c->top = top; + vdp = v->d; /* It pays off to "cache" *->d pointers, + * because it allows optimizer to be more + * aggressive. But we don't have to "cache" + * p->d, because *p is declared 'const'... */ + while (1) { + while (ubits && !(udp[0] & 1)) { + BN_ULONG u0, u1, b0, b1, mask; + + u0 = udp[0]; + b0 = bdp[0]; + mask = (BN_ULONG)0 - (b0 & 1); + b0 ^= p->d[0] & mask; + for (i = 0; i < top - 1; i++) { + u1 = udp[i + 1]; + udp[i] = ((u0 >> 1) | (u1 << (BN_BITS2 - 1))) & BN_MASK2; + u0 = u1; + b1 = bdp[i + 1] ^ (p->d[i + 1] & mask); + bdp[i] = ((b0 >> 1) | (b1 << (BN_BITS2 - 1))) & BN_MASK2; + b0 = b1; + } + udp[i] = u0 >> 1; + bdp[i] = b0 >> 1; + ubits--; + } + + if (ubits <= BN_BITS2) { + if (udp[0] == 0) /* poly was reducible */ + goto err; + if (udp[0] == 1) + break; + } + + if (ubits < vbits) { + i = ubits; + ubits = vbits; + vbits = i; + tmp = u; + u = v; + v = tmp; + tmp = b; + b = c; + c = tmp; + udp = vdp; + vdp = v->d; + bdp = cdp; + cdp = c->d; + } + for (i = 0; i < top; i++) { + udp[i] ^= vdp[i]; + bdp[i] ^= cdp[i]; + } + if (ubits == vbits) { + BN_ULONG ul; + int utop = (ubits - 1) / BN_BITS2; + + while ((ul = udp[utop]) == 0 && utop) + utop--; + ubits = utop * BN_BITS2 + BN_num_bits_word(ul); + } + } + bn_correct_top(b); + } +# endif + + if (!BN_copy(r, b)) + goto err; + bn_check_top(r); + ret = 1; + + err: +# ifdef BN_DEBUG /* BN_CTX_end would complain about the + * expanded form */ + bn_correct_top(c); + bn_correct_top(u); + bn_correct_top(v); +# endif + BN_CTX_end(ctx); + return ret; +} + +/*- + * Wrapper for BN_GF2m_mod_inv_vartime that blinds the input before calling. + * This is not constant time. + * But it does eliminate first order deduction on the input. + */ +int BN_GF2m_mod_inv(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) +{ + BIGNUM *b = NULL; + int ret = 0; + + BN_CTX_start(ctx); + if ((b = BN_CTX_get(ctx)) == NULL) + goto err; + + /* generate blinding value */ + do { + if (!BN_priv_rand(b, BN_num_bits(p) - 1, + BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) + goto err; + } while (BN_is_zero(b)); + + /* r := a * b */ + if (!BN_GF2m_mod_mul(r, a, b, p, ctx)) + goto err; + + /* r := 1/(a * b) */ + if (!BN_GF2m_mod_inv_vartime(r, r, p, ctx)) + goto err; + + /* r := b/(a * b) = 1/a */ + if (!BN_GF2m_mod_mul(r, r, b, p, ctx)) + goto err; + + ret = 1; + + err: + BN_CTX_end(ctx); + return ret; +} + +/* + * Invert xx, reduce modulo p, and store the result in r. r could be xx. + * This function calls down to the BN_GF2m_mod_inv implementation; this + * wrapper function is only provided for convenience; for best performance, + * use the BN_GF2m_mod_inv function. + */ +int BN_GF2m_mod_inv_arr(BIGNUM *r, const BIGNUM *xx, const int p[], + BN_CTX *ctx) +{ + BIGNUM *field; + int ret = 0; + + bn_check_top(xx); + BN_CTX_start(ctx); + if ((field = BN_CTX_get(ctx)) == NULL) + goto err; + if (!BN_GF2m_arr2poly(p, field)) + goto err; + + ret = BN_GF2m_mod_inv(r, xx, field, ctx); + bn_check_top(r); + + err: + BN_CTX_end(ctx); + return ret; +} + +/* + * Divide y by x, reduce modulo p, and store the result in r. r could be x + * or y, x could equal y. + */ +int BN_GF2m_mod_div(BIGNUM *r, const BIGNUM *y, const BIGNUM *x, + const BIGNUM *p, BN_CTX *ctx) +{ + BIGNUM *xinv = NULL; + int ret = 0; + + bn_check_top(y); + bn_check_top(x); + bn_check_top(p); + + BN_CTX_start(ctx); + xinv = BN_CTX_get(ctx); + if (xinv == NULL) + goto err; + + if (!BN_GF2m_mod_inv(xinv, x, p, ctx)) + goto err; + if (!BN_GF2m_mod_mul(r, y, xinv, p, ctx)) + goto err; + bn_check_top(r); + ret = 1; + + err: + BN_CTX_end(ctx); + return ret; +} + +/* + * Divide yy by xx, reduce modulo p, and store the result in r. r could be xx + * * or yy, xx could equal yy. This function calls down to the + * BN_GF2m_mod_div implementation; this wrapper function is only provided for + * convenience; for best performance, use the BN_GF2m_mod_div function. + */ +int BN_GF2m_mod_div_arr(BIGNUM *r, const BIGNUM *yy, const BIGNUM *xx, + const int p[], BN_CTX *ctx) +{ + BIGNUM *field; + int ret = 0; + + bn_check_top(yy); + bn_check_top(xx); + + BN_CTX_start(ctx); + if ((field = BN_CTX_get(ctx)) == NULL) + goto err; + if (!BN_GF2m_arr2poly(p, field)) + goto err; + + ret = BN_GF2m_mod_div(r, yy, xx, field, ctx); + bn_check_top(r); + + err: + BN_CTX_end(ctx); + return ret; +} + +/* + * Compute the bth power of a, reduce modulo p, and store the result in r. r + * could be a. Uses simple square-and-multiply algorithm A.5.1 from IEEE + * P1363. + */ +int BN_GF2m_mod_exp_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const int p[], BN_CTX *ctx) +{ + int ret = 0, i, n; + BIGNUM *u; + + bn_check_top(a); + bn_check_top(b); + + if (BN_is_zero(b)) + return BN_one(r); + + if (BN_abs_is_word(b, 1)) + return (BN_copy(r, a) != NULL); + + BN_CTX_start(ctx); + if ((u = BN_CTX_get(ctx)) == NULL) + goto err; + + if (!BN_GF2m_mod_arr(u, a, p)) + goto err; + + n = BN_num_bits(b) - 1; + for (i = n - 1; i >= 0; i--) { + if (!BN_GF2m_mod_sqr_arr(u, u, p, ctx)) + goto err; + if (BN_is_bit_set(b, i)) { + if (!BN_GF2m_mod_mul_arr(u, u, a, p, ctx)) + goto err; + } + } + if (!BN_copy(r, u)) + goto err; + bn_check_top(r); + ret = 1; + err: + BN_CTX_end(ctx); + return ret; +} + +/* + * Compute the bth power of a, reduce modulo p, and store the result in r. r + * could be a. This function calls down to the BN_GF2m_mod_exp_arr + * implementation; this wrapper function is only provided for convenience; + * for best performance, use the BN_GF2m_mod_exp_arr function. + */ +int BN_GF2m_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *p, BN_CTX *ctx) +{ + int ret = 0; + const int max = BN_num_bits(p) + 1; + int *arr = NULL; + bn_check_top(a); + bn_check_top(b); + bn_check_top(p); + if ((arr = OPENSSL_malloc(sizeof(*arr) * max)) == NULL) + goto err; + ret = BN_GF2m_poly2arr(p, arr, max); + if (!ret || ret > max) { + BNerr(BN_F_BN_GF2M_MOD_EXP, BN_R_INVALID_LENGTH); + goto err; + } + ret = BN_GF2m_mod_exp_arr(r, a, b, arr, ctx); + bn_check_top(r); + err: + OPENSSL_free(arr); + return ret; +} + +/* + * Compute the square root of a, reduce modulo p, and store the result in r. + * r could be a. Uses exponentiation as in algorithm A.4.1 from IEEE P1363. + */ +int BN_GF2m_mod_sqrt_arr(BIGNUM *r, const BIGNUM *a, const int p[], + BN_CTX *ctx) +{ + int ret = 0; + BIGNUM *u; + + bn_check_top(a); + + if (!p[0]) { + /* reduction mod 1 => return 0 */ + BN_zero(r); + return 1; + } + + BN_CTX_start(ctx); + if ((u = BN_CTX_get(ctx)) == NULL) + goto err; + + if (!BN_set_bit(u, p[0] - 1)) + goto err; + ret = BN_GF2m_mod_exp_arr(r, a, u, p, ctx); + bn_check_top(r); + + err: + BN_CTX_end(ctx); + return ret; +} + +/* + * Compute the square root of a, reduce modulo p, and store the result in r. + * r could be a. This function calls down to the BN_GF2m_mod_sqrt_arr + * implementation; this wrapper function is only provided for convenience; + * for best performance, use the BN_GF2m_mod_sqrt_arr function. + */ +int BN_GF2m_mod_sqrt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) +{ + int ret = 0; + const int max = BN_num_bits(p) + 1; + int *arr = NULL; + bn_check_top(a); + bn_check_top(p); + if ((arr = OPENSSL_malloc(sizeof(*arr) * max)) == NULL) + goto err; + ret = BN_GF2m_poly2arr(p, arr, max); + if (!ret || ret > max) { + BNerr(BN_F_BN_GF2M_MOD_SQRT, BN_R_INVALID_LENGTH); + goto err; + } + ret = BN_GF2m_mod_sqrt_arr(r, a, arr, ctx); + bn_check_top(r); + err: + OPENSSL_free(arr); + return ret; +} + +/* + * Find r such that r^2 + r = a mod p. r could be a. If no r exists returns + * 0. Uses algorithms A.4.7 and A.4.6 from IEEE P1363. + */ +int BN_GF2m_mod_solve_quad_arr(BIGNUM *r, const BIGNUM *a_, const int p[], + BN_CTX *ctx) +{ + int ret = 0, count = 0, j; + BIGNUM *a, *z, *rho, *w, *w2, *tmp; + + bn_check_top(a_); + + if (!p[0]) { + /* reduction mod 1 => return 0 */ + BN_zero(r); + return 1; + } + + BN_CTX_start(ctx); + a = BN_CTX_get(ctx); + z = BN_CTX_get(ctx); + w = BN_CTX_get(ctx); + if (w == NULL) + goto err; + + if (!BN_GF2m_mod_arr(a, a_, p)) + goto err; + + if (BN_is_zero(a)) { + BN_zero(r); + ret = 1; + goto err; + } + + if (p[0] & 0x1) { /* m is odd */ + /* compute half-trace of a */ + if (!BN_copy(z, a)) + goto err; + for (j = 1; j <= (p[0] - 1) / 2; j++) { + if (!BN_GF2m_mod_sqr_arr(z, z, p, ctx)) + goto err; + if (!BN_GF2m_mod_sqr_arr(z, z, p, ctx)) + goto err; + if (!BN_GF2m_add(z, z, a)) + goto err; + } + + } else { /* m is even */ + + rho = BN_CTX_get(ctx); + w2 = BN_CTX_get(ctx); + tmp = BN_CTX_get(ctx); + if (tmp == NULL) + goto err; + do { + if (!BN_priv_rand(rho, p[0], BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) + goto err; + if (!BN_GF2m_mod_arr(rho, rho, p)) + goto err; + BN_zero(z); + if (!BN_copy(w, rho)) + goto err; + for (j = 1; j <= p[0] - 1; j++) { + if (!BN_GF2m_mod_sqr_arr(z, z, p, ctx)) + goto err; + if (!BN_GF2m_mod_sqr_arr(w2, w, p, ctx)) + goto err; + if (!BN_GF2m_mod_mul_arr(tmp, w2, a, p, ctx)) + goto err; + if (!BN_GF2m_add(z, z, tmp)) + goto err; + if (!BN_GF2m_add(w, w2, rho)) + goto err; + } + count++; + } while (BN_is_zero(w) && (count < MAX_ITERATIONS)); + if (BN_is_zero(w)) { + BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR, BN_R_TOO_MANY_ITERATIONS); + goto err; + } + } + + if (!BN_GF2m_mod_sqr_arr(w, z, p, ctx)) + goto err; + if (!BN_GF2m_add(w, z, w)) + goto err; + if (BN_GF2m_cmp(w, a)) { + BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR, BN_R_NO_SOLUTION); + goto err; + } + + if (!BN_copy(r, z)) + goto err; + bn_check_top(r); + + ret = 1; + + err: + BN_CTX_end(ctx); + return ret; +} + +/* + * Find r such that r^2 + r = a mod p. r could be a. If no r exists returns + * 0. This function calls down to the BN_GF2m_mod_solve_quad_arr + * implementation; this wrapper function is only provided for convenience; + * for best performance, use the BN_GF2m_mod_solve_quad_arr function. + */ +int BN_GF2m_mod_solve_quad(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + BN_CTX *ctx) +{ + int ret = 0; + const int max = BN_num_bits(p) + 1; + int *arr = NULL; + bn_check_top(a); + bn_check_top(p); + if ((arr = OPENSSL_malloc(sizeof(*arr) * max)) == NULL) + goto err; + ret = BN_GF2m_poly2arr(p, arr, max); + if (!ret || ret > max) { + BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD, BN_R_INVALID_LENGTH); + goto err; + } + ret = BN_GF2m_mod_solve_quad_arr(r, a, arr, ctx); + bn_check_top(r); + err: + OPENSSL_free(arr); + return ret; +} + +/* + * Convert the bit-string representation of a polynomial ( \sum_{i=0}^n a_i * + * x^i) into an array of integers corresponding to the bits with non-zero + * coefficient. Array is terminated with -1. Up to max elements of the array + * will be filled. Return value is total number of array elements that would + * be filled if array was large enough. + */ +int BN_GF2m_poly2arr(const BIGNUM *a, int p[], int max) +{ + int i, j, k = 0; + BN_ULONG mask; + + if (BN_is_zero(a)) + return 0; + + for (i = a->top - 1; i >= 0; i--) { + if (!a->d[i]) + /* skip word if a->d[i] == 0 */ + continue; + mask = BN_TBIT; + for (j = BN_BITS2 - 1; j >= 0; j--) { + if (a->d[i] & mask) { + if (k < max) + p[k] = BN_BITS2 * i + j; + k++; + } + mask >>= 1; + } + } + + if (k < max) { + p[k] = -1; + k++; + } + + return k; +} + +/* + * Convert the coefficient array representation of a polynomial to a + * bit-string. The array must be terminated by -1. + */ +int BN_GF2m_arr2poly(const int p[], BIGNUM *a) +{ + int i; + + bn_check_top(a); + BN_zero(a); + for (i = 0; p[i] != -1; i++) { + if (BN_set_bit(a, p[i]) == 0) + return 0; + } + bn_check_top(a); + + return 1; +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_intern.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_intern.c new file mode 100644 index 000000000..46bc97575 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_intern.c @@ -0,0 +1,199 @@ +/* + * Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include "bn_lcl.h" + +/* + * Determine the modified width-(w+1) Non-Adjacent Form (wNAF) of 'scalar'. + * This is an array r[] of values that are either zero or odd with an + * absolute value less than 2^w satisfying + * scalar = \sum_j r[j]*2^j + * where at most one of any w+1 consecutive digits is non-zero + * with the exception that the most significant digit may be only + * w-1 zeros away from that next non-zero digit. + */ +signed char *bn_compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len) +{ + int window_val; + signed char *r = NULL; + int sign = 1; + int bit, next_bit, mask; + size_t len = 0, j; + + if (BN_is_zero(scalar)) { + r = OPENSSL_malloc(1); + if (r == NULL) { + BNerr(BN_F_BN_COMPUTE_WNAF, ERR_R_MALLOC_FAILURE); + goto err; + } + r[0] = 0; + *ret_len = 1; + return r; + } + + if (w <= 0 || w > 7) { /* 'signed char' can represent integers with + * absolute values less than 2^7 */ + BNerr(BN_F_BN_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); + goto err; + } + bit = 1 << w; /* at most 128 */ + next_bit = bit << 1; /* at most 256 */ + mask = next_bit - 1; /* at most 255 */ + + if (BN_is_negative(scalar)) { + sign = -1; + } + + if (scalar->d == NULL || scalar->top == 0) { + BNerr(BN_F_BN_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); + goto err; + } + + len = BN_num_bits(scalar); + r = OPENSSL_malloc(len + 1); /* + * Modified wNAF may be one digit longer than binary representation + * (*ret_len will be set to the actual length, i.e. at most + * BN_num_bits(scalar) + 1) + */ + if (r == NULL) { + BNerr(BN_F_BN_COMPUTE_WNAF, ERR_R_MALLOC_FAILURE); + goto err; + } + window_val = scalar->d[0] & mask; + j = 0; + while ((window_val != 0) || (j + w + 1 < len)) { /* if j+w+1 >= len, + * window_val will not + * increase */ + int digit = 0; + + /* 0 <= window_val <= 2^(w+1) */ + + if (window_val & 1) { + /* 0 < window_val < 2^(w+1) */ + + if (window_val & bit) { + digit = window_val - next_bit; /* -2^w < digit < 0 */ + +#if 1 /* modified wNAF */ + if (j + w + 1 >= len) { + /* + * Special case for generating modified wNAFs: + * no new bits will be added into window_val, + * so using a positive digit here will decrease + * the total length of the representation + */ + + digit = window_val & (mask >> 1); /* 0 < digit < 2^w */ + } +#endif + } else { + digit = window_val; /* 0 < digit < 2^w */ + } + + if (digit <= -bit || digit >= bit || !(digit & 1)) { + BNerr(BN_F_BN_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); + goto err; + } + + window_val -= digit; + + /* + * now window_val is 0 or 2^(w+1) in standard wNAF generation; + * for modified window NAFs, it may also be 2^w + */ + if (window_val != 0 && window_val != next_bit + && window_val != bit) { + BNerr(BN_F_BN_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); + goto err; + } + } + + r[j++] = sign * digit; + + window_val >>= 1; + window_val += bit * BN_is_bit_set(scalar, j + w); + + if (window_val > next_bit) { + BNerr(BN_F_BN_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); + goto err; + } + } + + if (j > len + 1) { + BNerr(BN_F_BN_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); + goto err; + } + *ret_len = j; + return r; + + err: + OPENSSL_free(r); + return NULL; +} + +int bn_get_top(const BIGNUM *a) +{ + return a->top; +} + +int bn_get_dmax(const BIGNUM *a) +{ + return a->dmax; +} + +void bn_set_all_zero(BIGNUM *a) +{ + int i; + + for (i = a->top; i < a->dmax; i++) + a->d[i] = 0; +} + +int bn_copy_words(BN_ULONG *out, const BIGNUM *in, int size) +{ + if (in->top > size) + return 0; + + memset(out, 0, sizeof(*out) * size); + if (in->d != NULL) + memcpy(out, in->d, sizeof(*out) * in->top); + return 1; +} + +BN_ULONG *bn_get_words(const BIGNUM *a) +{ + return a->d; +} + +void bn_set_static_words(BIGNUM *a, const BN_ULONG *words, int size) +{ + /* + * |const| qualifier omission is compensated by BN_FLG_STATIC_DATA + * flag, which effectively means "read-only data". + */ + a->d = (BN_ULONG *)words; + a->dmax = a->top = size; + a->neg = 0; + a->flags |= BN_FLG_STATIC_DATA; + bn_correct_top(a); +} + +int bn_set_words(BIGNUM *a, const BN_ULONG *words, int num_words) +{ + if (bn_wexpand(a, num_words) == NULL) { + BNerr(BN_F_BN_SET_WORDS, ERR_R_MALLOC_FAILURE); + return 0; + } + + memcpy(a->d, words, sizeof(BN_ULONG) * num_words); + a->top = num_words; + bn_correct_top(a); + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_kron.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_kron.c new file mode 100644 index 000000000..b9bc6cca2 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_kron.c @@ -0,0 +1,140 @@ +/* + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include "bn_lcl.h" + +/* least significant word */ +#define BN_lsw(n) (((n)->top == 0) ? (BN_ULONG) 0 : (n)->d[0]) + +/* Returns -2 for errors because both -1 and 0 are valid results. */ +int BN_kronecker(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) +{ + int i; + int ret = -2; /* avoid 'uninitialized' warning */ + int err = 0; + BIGNUM *A, *B, *tmp; + /*- + * In 'tab', only odd-indexed entries are relevant: + * For any odd BIGNUM n, + * tab[BN_lsw(n) & 7] + * is $(-1)^{(n^2-1)/8}$ (using TeX notation). + * Note that the sign of n does not matter. + */ + static const int tab[8] = { 0, 1, 0, -1, 0, -1, 0, 1 }; + + bn_check_top(a); + bn_check_top(b); + + BN_CTX_start(ctx); + A = BN_CTX_get(ctx); + B = BN_CTX_get(ctx); + if (B == NULL) + goto end; + + err = !BN_copy(A, a); + if (err) + goto end; + err = !BN_copy(B, b); + if (err) + goto end; + + /* + * Kronecker symbol, implemented according to Henri Cohen, + * "A Course in Computational Algebraic Number Theory" + * (algorithm 1.4.10). + */ + + /* Cohen's step 1: */ + + if (BN_is_zero(B)) { + ret = BN_abs_is_word(A, 1); + goto end; + } + + /* Cohen's step 2: */ + + if (!BN_is_odd(A) && !BN_is_odd(B)) { + ret = 0; + goto end; + } + + /* now B is non-zero */ + i = 0; + while (!BN_is_bit_set(B, i)) + i++; + err = !BN_rshift(B, B, i); + if (err) + goto end; + if (i & 1) { + /* i is odd */ + /* (thus B was even, thus A must be odd!) */ + + /* set 'ret' to $(-1)^{(A^2-1)/8}$ */ + ret = tab[BN_lsw(A) & 7]; + } else { + /* i is even */ + ret = 1; + } + + if (B->neg) { + B->neg = 0; + if (A->neg) + ret = -ret; + } + + /* + * now B is positive and odd, so what remains to be done is to compute + * the Jacobi symbol (A/B) and multiply it by 'ret' + */ + + while (1) { + /* Cohen's step 3: */ + + /* B is positive and odd */ + + if (BN_is_zero(A)) { + ret = BN_is_one(B) ? ret : 0; + goto end; + } + + /* now A is non-zero */ + i = 0; + while (!BN_is_bit_set(A, i)) + i++; + err = !BN_rshift(A, A, i); + if (err) + goto end; + if (i & 1) { + /* i is odd */ + /* multiply 'ret' by $(-1)^{(B^2-1)/8}$ */ + ret = ret * tab[BN_lsw(B) & 7]; + } + + /* Cohen's step 4: */ + /* multiply 'ret' by $(-1)^{(A-1)(B-1)/4}$ */ + if ((A->neg ? ~BN_lsw(A) : BN_lsw(A)) & BN_lsw(B) & 2) + ret = -ret; + + /* (A, B) := (B mod |A|, |A|) */ + err = !BN_nnmod(B, B, A, ctx); + if (err) + goto end; + tmp = A; + A = B; + B = tmp; + tmp->neg = 0; + } + end: + BN_CTX_end(ctx); + if (err) + return -2; + else + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_lcl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_lcl.h new file mode 100644 index 000000000..8a36db2e8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_lcl.h @@ -0,0 +1,671 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_BN_LCL_H +# define HEADER_BN_LCL_H + +/* + * The EDK2 build doesn't use bn_conf.h; it sets THIRTY_TWO_BIT or + * SIXTY_FOUR_BIT in its own environment since it doesn't re-run our + * Configure script and needs to support both 32-bit and 64-bit. + */ +# include + +# if !defined(OPENSSL_SYS_UEFI) +# include "internal/bn_conf.h" +# endif + +# include "internal/bn_int.h" + +/* + * These preprocessor symbols control various aspects of the bignum headers + * and library code. They're not defined by any "normal" configuration, as + * they are intended for development and testing purposes. NB: defining all + * three can be useful for debugging application code as well as openssl + * itself. BN_DEBUG - turn on various debugging alterations to the bignum + * code BN_DEBUG_RAND - uses random poisoning of unused words to trip up + * mismanagement of bignum internals. You must also define BN_DEBUG. + */ +/* #define BN_DEBUG */ +/* #define BN_DEBUG_RAND */ + +# ifndef OPENSSL_SMALL_FOOTPRINT +# define BN_MUL_COMBA +# define BN_SQR_COMBA +# define BN_RECURSION +# endif + +/* + * This next option uses the C libraries (2 word)/(1 word) function. If it is + * not defined, I use my C version (which is slower). The reason for this + * flag is that when the particular C compiler library routine is used, and + * the library is linked with a different compiler, the library is missing. + * This mostly happens when the library is built with gcc and then linked + * using normal cc. This would be a common occurrence because gcc normally + * produces code that is 2 times faster than system compilers for the big + * number stuff. For machines with only one compiler (or shared libraries), + * this should be on. Again this in only really a problem on machines using + * "long long's", are 32bit, and are not using my assembler code. + */ +# if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WINDOWS) || \ + defined(OPENSSL_SYS_WIN32) || defined(linux) +# define BN_DIV2W +# endif + +/* + * 64-bit processor with LP64 ABI + */ +# ifdef SIXTY_FOUR_BIT_LONG +# define BN_ULLONG unsigned long long +# define BN_BITS4 32 +# define BN_MASK2 (0xffffffffffffffffL) +# define BN_MASK2l (0xffffffffL) +# define BN_MASK2h (0xffffffff00000000L) +# define BN_MASK2h1 (0xffffffff80000000L) +# define BN_DEC_CONV (10000000000000000000UL) +# define BN_DEC_NUM 19 +# define BN_DEC_FMT1 "%lu" +# define BN_DEC_FMT2 "%019lu" +# endif + +/* + * 64-bit processor other than LP64 ABI + */ +# ifdef SIXTY_FOUR_BIT +# undef BN_LLONG +# undef BN_ULLONG +# define BN_BITS4 32 +# define BN_MASK2 (0xffffffffffffffffLL) +# define BN_MASK2l (0xffffffffL) +# define BN_MASK2h (0xffffffff00000000LL) +# define BN_MASK2h1 (0xffffffff80000000LL) +# define BN_DEC_CONV (10000000000000000000ULL) +# define BN_DEC_NUM 19 +# define BN_DEC_FMT1 "%llu" +# define BN_DEC_FMT2 "%019llu" +# endif + +# ifdef THIRTY_TWO_BIT +# ifdef BN_LLONG +# if defined(_WIN32) && !defined(__GNUC__) +# define BN_ULLONG unsigned __int64 +# else +# define BN_ULLONG unsigned long long +# endif +# endif +# define BN_BITS4 16 +# define BN_MASK2 (0xffffffffL) +# define BN_MASK2l (0xffff) +# define BN_MASK2h1 (0xffff8000L) +# define BN_MASK2h (0xffff0000L) +# define BN_DEC_CONV (1000000000L) +# define BN_DEC_NUM 9 +# define BN_DEC_FMT1 "%u" +# define BN_DEC_FMT2 "%09u" +# endif + + +/*- + * Bignum consistency macros + * There is one "API" macro, bn_fix_top(), for stripping leading zeroes from + * bignum data after direct manipulations on the data. There is also an + * "internal" macro, bn_check_top(), for verifying that there are no leading + * zeroes. Unfortunately, some auditing is required due to the fact that + * bn_fix_top() has become an overabused duct-tape because bignum data is + * occasionally passed around in an inconsistent state. So the following + * changes have been made to sort this out; + * - bn_fix_top()s implementation has been moved to bn_correct_top() + * - if BN_DEBUG isn't defined, bn_fix_top() maps to bn_correct_top(), and + * bn_check_top() is as before. + * - if BN_DEBUG *is* defined; + * - bn_check_top() tries to pollute unused words even if the bignum 'top' is + * consistent. (ed: only if BN_DEBUG_RAND is defined) + * - bn_fix_top() maps to bn_check_top() rather than "fixing" anything. + * The idea is to have debug builds flag up inconsistent bignums when they + * occur. If that occurs in a bn_fix_top(), we examine the code in question; if + * the use of bn_fix_top() was appropriate (ie. it follows directly after code + * that manipulates the bignum) it is converted to bn_correct_top(), and if it + * was not appropriate, we convert it permanently to bn_check_top() and track + * down the cause of the bug. Eventually, no internal code should be using the + * bn_fix_top() macro. External applications and libraries should try this with + * their own code too, both in terms of building against the openssl headers + * with BN_DEBUG defined *and* linking with a version of OpenSSL built with it + * defined. This not only improves external code, it provides more test + * coverage for openssl's own code. + */ + +# ifdef BN_DEBUG +/* + * The new BN_FLG_FIXED_TOP flag marks vectors that were not treated with + * bn_correct_top, in other words such vectors are permitted to have zeros + * in most significant limbs. Such vectors are used internally to achieve + * execution time invariance for critical operations with private keys. + * It's BN_DEBUG-only flag, because user application is not supposed to + * observe it anyway. Moreover, optimizing compiler would actually remove + * all operations manipulating the bit in question in non-BN_DEBUG build. + */ +# define BN_FLG_FIXED_TOP 0x10000 +# ifdef BN_DEBUG_RAND +# define bn_pollute(a) \ + do { \ + const BIGNUM *_bnum1 = (a); \ + if (_bnum1->top < _bnum1->dmax) { \ + unsigned char _tmp_char; \ + /* We cast away const without the compiler knowing, any \ + * *genuinely* constant variables that aren't mutable \ + * wouldn't be constructed with top!=dmax. */ \ + BN_ULONG *_not_const; \ + memcpy(&_not_const, &_bnum1->d, sizeof(_not_const)); \ + RAND_bytes(&_tmp_char, 1); /* Debug only - safe to ignore error return */\ + memset(_not_const + _bnum1->top, _tmp_char, \ + sizeof(*_not_const) * (_bnum1->dmax - _bnum1->top)); \ + } \ + } while(0) +# else +# define bn_pollute(a) +# endif +# define bn_check_top(a) \ + do { \ + const BIGNUM *_bnum2 = (a); \ + if (_bnum2 != NULL) { \ + int _top = _bnum2->top; \ + (void)ossl_assert((_top == 0 && !_bnum2->neg) || \ + (_top && ((_bnum2->flags & BN_FLG_FIXED_TOP) \ + || _bnum2->d[_top - 1] != 0))); \ + bn_pollute(_bnum2); \ + } \ + } while(0) + +# define bn_fix_top(a) bn_check_top(a) + +# define bn_check_size(bn, bits) bn_wcheck_size(bn, ((bits+BN_BITS2-1))/BN_BITS2) +# define bn_wcheck_size(bn, words) \ + do { \ + const BIGNUM *_bnum2 = (bn); \ + assert((words) <= (_bnum2)->dmax && \ + (words) >= (_bnum2)->top); \ + /* avoid unused variable warning with NDEBUG */ \ + (void)(_bnum2); \ + } while(0) + +# else /* !BN_DEBUG */ + +# define BN_FLG_FIXED_TOP 0 +# define bn_pollute(a) +# define bn_check_top(a) +# define bn_fix_top(a) bn_correct_top(a) +# define bn_check_size(bn, bits) +# define bn_wcheck_size(bn, words) + +# endif + +BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, + BN_ULONG w); +BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w); +void bn_sqr_words(BN_ULONG *rp, const BN_ULONG *ap, int num); +BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d); +BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + int num); +BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + int num); + +struct bignum_st { + BN_ULONG *d; /* Pointer to an array of 'BN_BITS2' bit + * chunks. */ + int top; /* Index of last used d +1. */ + /* The next are internal book keeping for bn_expand. */ + int dmax; /* Size of the d array. */ + int neg; /* one if the number is negative */ + int flags; +}; + +/* Used for montgomery multiplication */ +struct bn_mont_ctx_st { + int ri; /* number of bits in R */ + BIGNUM RR; /* used to convert to montgomery form, + possibly zero-padded */ + BIGNUM N; /* The modulus */ + BIGNUM Ni; /* R*(1/R mod N) - N*Ni = 1 (Ni is only + * stored for bignum algorithm) */ + BN_ULONG n0[2]; /* least significant word(s) of Ni; (type + * changed with 0.9.9, was "BN_ULONG n0;" + * before) */ + int flags; +}; + +/* + * Used for reciprocal division/mod functions It cannot be shared between + * threads + */ +struct bn_recp_ctx_st { + BIGNUM N; /* the divisor */ + BIGNUM Nr; /* the reciprocal */ + int num_bits; + int shift; + int flags; +}; + +/* Used for slow "generation" functions. */ +struct bn_gencb_st { + unsigned int ver; /* To handle binary (in)compatibility */ + void *arg; /* callback-specific data */ + union { + /* if (ver==1) - handles old style callbacks */ + void (*cb_1) (int, int, void *); + /* if (ver==2) - new callback style */ + int (*cb_2) (int, int, BN_GENCB *); + } cb; +}; + +/*- + * BN_window_bits_for_exponent_size -- macro for sliding window mod_exp functions + * + * + * For window size 'w' (w >= 2) and a random 'b' bits exponent, + * the number of multiplications is a constant plus on average + * + * 2^(w-1) + (b-w)/(w+1); + * + * here 2^(w-1) is for precomputing the table (we actually need + * entries only for windows that have the lowest bit set), and + * (b-w)/(w+1) is an approximation for the expected number of + * w-bit windows, not counting the first one. + * + * Thus we should use + * + * w >= 6 if b > 671 + * w = 5 if 671 > b > 239 + * w = 4 if 239 > b > 79 + * w = 3 if 79 > b > 23 + * w <= 2 if 23 > b + * + * (with draws in between). Very small exponents are often selected + * with low Hamming weight, so we use w = 1 for b <= 23. + */ +# define BN_window_bits_for_exponent_size(b) \ + ((b) > 671 ? 6 : \ + (b) > 239 ? 5 : \ + (b) > 79 ? 4 : \ + (b) > 23 ? 3 : 1) + +/* + * BN_mod_exp_mont_conttime is based on the assumption that the L1 data cache + * line width of the target processor is at least the following value. + */ +# define MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH ( 64 ) +# define MOD_EXP_CTIME_MIN_CACHE_LINE_MASK (MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH - 1) + +/* + * Window sizes optimized for fixed window size modular exponentiation + * algorithm (BN_mod_exp_mont_consttime). To achieve the security goals of + * BN_mode_exp_mont_consttime, the maximum size of the window must not exceed + * log_2(MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH). Window size thresholds are + * defined for cache line sizes of 32 and 64, cache line sizes where + * log_2(32)=5 and log_2(64)=6 respectively. A window size of 7 should only be + * used on processors that have a 128 byte or greater cache line size. + */ +# if MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH == 64 + +# define BN_window_bits_for_ctime_exponent_size(b) \ + ((b) > 937 ? 6 : \ + (b) > 306 ? 5 : \ + (b) > 89 ? 4 : \ + (b) > 22 ? 3 : 1) +# define BN_MAX_WINDOW_BITS_FOR_CTIME_EXPONENT_SIZE (6) + +# elif MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH == 32 + +# define BN_window_bits_for_ctime_exponent_size(b) \ + ((b) > 306 ? 5 : \ + (b) > 89 ? 4 : \ + (b) > 22 ? 3 : 1) +# define BN_MAX_WINDOW_BITS_FOR_CTIME_EXPONENT_SIZE (5) + +# endif + +/* Pentium pro 16,16,16,32,64 */ +/* Alpha 16,16,16,16.64 */ +# define BN_MULL_SIZE_NORMAL (16)/* 32 */ +# define BN_MUL_RECURSIVE_SIZE_NORMAL (16)/* 32 less than */ +# define BN_SQR_RECURSIVE_SIZE_NORMAL (16)/* 32 */ +# define BN_MUL_LOW_RECURSIVE_SIZE_NORMAL (32)/* 32 */ +# define BN_MONT_CTX_SET_SIZE_WORD (64)/* 32 */ + +/* + * 2011-02-22 SMS. In various places, a size_t variable or a type cast to + * size_t was used to perform integer-only operations on pointers. This + * failed on VMS with 64-bit pointers (CC /POINTER_SIZE = 64) because size_t + * is still only 32 bits. What's needed in these cases is an integer type + * with the same size as a pointer, which size_t is not certain to be. The + * only fix here is VMS-specific. + */ +# if defined(OPENSSL_SYS_VMS) +# if __INITIAL_POINTER_SIZE == 64 +# define PTR_SIZE_INT long long +# else /* __INITIAL_POINTER_SIZE == 64 */ +# define PTR_SIZE_INT int +# endif /* __INITIAL_POINTER_SIZE == 64 [else] */ +# elif !defined(PTR_SIZE_INT) /* defined(OPENSSL_SYS_VMS) */ +# define PTR_SIZE_INT size_t +# endif /* defined(OPENSSL_SYS_VMS) [else] */ + +# if !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) && !defined(PEDANTIC) +/* + * BN_UMULT_HIGH section. + * If the compiler doesn't support 2*N integer type, then you have to + * replace every N*N multiplication with 4 (N/2)*(N/2) accompanied by some + * shifts and additions which unavoidably results in severe performance + * penalties. Of course provided that the hardware is capable of producing + * 2*N result... That's when you normally start considering assembler + * implementation. However! It should be pointed out that some CPUs (e.g., + * PowerPC, Alpha, and IA-64) provide *separate* instruction calculating + * the upper half of the product placing the result into a general + * purpose register. Now *if* the compiler supports inline assembler, + * then it's not impossible to implement the "bignum" routines (and have + * the compiler optimize 'em) exhibiting "native" performance in C. That's + * what BN_UMULT_HIGH macro is about:-) Note that more recent compilers do + * support 2*64 integer type, which is also used here. + */ +# if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__==16 && \ + (defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG)) +# define BN_UMULT_HIGH(a,b) (((__uint128_t)(a)*(b))>>64) +# define BN_UMULT_LOHI(low,high,a,b) ({ \ + __uint128_t ret=(__uint128_t)(a)*(b); \ + (high)=ret>>64; (low)=ret; }) +# elif defined(__alpha) && (defined(SIXTY_FOUR_BIT_LONG) || defined(SIXTY_FOUR_BIT)) +# if defined(__DECC) +# include +# define BN_UMULT_HIGH(a,b) (BN_ULONG)asm("umulh %a0,%a1,%v0",(a),(b)) +# elif defined(__GNUC__) && __GNUC__>=2 +# define BN_UMULT_HIGH(a,b) ({ \ + register BN_ULONG ret; \ + asm ("umulh %1,%2,%0" \ + : "=r"(ret) \ + : "r"(a), "r"(b)); \ + ret; }) +# endif /* compiler */ +# elif defined(_ARCH_PPC64) && defined(SIXTY_FOUR_BIT_LONG) +# if defined(__GNUC__) && __GNUC__>=2 +# define BN_UMULT_HIGH(a,b) ({ \ + register BN_ULONG ret; \ + asm ("mulhdu %0,%1,%2" \ + : "=r"(ret) \ + : "r"(a), "r"(b)); \ + ret; }) +# endif /* compiler */ +# elif (defined(__x86_64) || defined(__x86_64__)) && \ + (defined(SIXTY_FOUR_BIT_LONG) || defined(SIXTY_FOUR_BIT)) +# if defined(__GNUC__) && __GNUC__>=2 +# define BN_UMULT_HIGH(a,b) ({ \ + register BN_ULONG ret,discard; \ + asm ("mulq %3" \ + : "=a"(discard),"=d"(ret) \ + : "a"(a), "g"(b) \ + : "cc"); \ + ret; }) +# define BN_UMULT_LOHI(low,high,a,b) \ + asm ("mulq %3" \ + : "=a"(low),"=d"(high) \ + : "a"(a),"g"(b) \ + : "cc"); +# endif +# elif (defined(_M_AMD64) || defined(_M_X64)) && defined(SIXTY_FOUR_BIT) +# if defined(_MSC_VER) && _MSC_VER>=1400 +unsigned __int64 __umulh(unsigned __int64 a, unsigned __int64 b); +unsigned __int64 _umul128(unsigned __int64 a, unsigned __int64 b, + unsigned __int64 *h); +# pragma intrinsic(__umulh,_umul128) +# define BN_UMULT_HIGH(a,b) __umulh((a),(b)) +# define BN_UMULT_LOHI(low,high,a,b) ((low)=_umul128((a),(b),&(high))) +# endif +# elif defined(__mips) && (defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG)) +# if defined(__GNUC__) && __GNUC__>=2 +# define BN_UMULT_HIGH(a,b) ({ \ + register BN_ULONG ret; \ + asm ("dmultu %1,%2" \ + : "=h"(ret) \ + : "r"(a), "r"(b) : "l"); \ + ret; }) +# define BN_UMULT_LOHI(low,high,a,b) \ + asm ("dmultu %2,%3" \ + : "=l"(low),"=h"(high) \ + : "r"(a), "r"(b)); +# endif +# elif defined(__aarch64__) && defined(SIXTY_FOUR_BIT_LONG) +# if defined(__GNUC__) && __GNUC__>=2 +# define BN_UMULT_HIGH(a,b) ({ \ + register BN_ULONG ret; \ + asm ("umulh %0,%1,%2" \ + : "=r"(ret) \ + : "r"(a), "r"(b)); \ + ret; }) +# endif +# endif /* cpu */ +# endif /* OPENSSL_NO_ASM */ + +# ifdef BN_DEBUG_RAND +# define bn_clear_top2max(a) \ + { \ + int ind = (a)->dmax - (a)->top; \ + BN_ULONG *ftl = &(a)->d[(a)->top-1]; \ + for (; ind != 0; ind--) \ + *(++ftl) = 0x0; \ + } +# else +# define bn_clear_top2max(a) +# endif + +# ifdef BN_LLONG +/******************************************************************* + * Using the long long type, has to be twice as wide as BN_ULONG... + */ +# define Lw(t) (((BN_ULONG)(t))&BN_MASK2) +# define Hw(t) (((BN_ULONG)((t)>>BN_BITS2))&BN_MASK2) + +# define mul_add(r,a,w,c) { \ + BN_ULLONG t; \ + t=(BN_ULLONG)w * (a) + (r) + (c); \ + (r)= Lw(t); \ + (c)= Hw(t); \ + } + +# define mul(r,a,w,c) { \ + BN_ULLONG t; \ + t=(BN_ULLONG)w * (a) + (c); \ + (r)= Lw(t); \ + (c)= Hw(t); \ + } + +# define sqr(r0,r1,a) { \ + BN_ULLONG t; \ + t=(BN_ULLONG)(a)*(a); \ + (r0)=Lw(t); \ + (r1)=Hw(t); \ + } + +# elif defined(BN_UMULT_LOHI) +# define mul_add(r,a,w,c) { \ + BN_ULONG high,low,ret,tmp=(a); \ + ret = (r); \ + BN_UMULT_LOHI(low,high,w,tmp); \ + ret += (c); \ + (c) = (ret<(c))?1:0; \ + (c) += high; \ + ret += low; \ + (c) += (ret>BN_BITS4)&BN_MASK2l) +# define L2HBITS(a) (((a)<>BN_BITS2)&BN_MASKl) +# define LL2HBITS(a) ((BN_ULLONG)((a)&BN_MASKl)<>(BN_BITS4-1); \ + m =(m&BN_MASK2l)<<(BN_BITS4+1); \ + l=(l+m)&BN_MASK2; if (l < m) h++; \ + (lo)=l; \ + (ho)=h; \ + } + +# define mul_add(r,a,bl,bh,c) { \ + BN_ULONG l,h; \ + \ + h= (a); \ + l=LBITS(h); \ + h=HBITS(h); \ + mul64(l,h,(bl),(bh)); \ + \ + /* non-multiply part */ \ + l=(l+(c))&BN_MASK2; if (l < (c)) h++; \ + (c)=(r); \ + l=(l+(c))&BN_MASK2; if (l < (c)) h++; \ + (c)=h&BN_MASK2; \ + (r)=l; \ + } + +# define mul(r,a,bl,bh,c) { \ + BN_ULONG l,h; \ + \ + h= (a); \ + l=LBITS(h); \ + h=HBITS(h); \ + mul64(l,h,(bl),(bh)); \ + \ + /* non-multiply part */ \ + l+=(c); if ((l&BN_MASK2) < (c)) h++; \ + (c)=h&BN_MASK2; \ + (r)=l&BN_MASK2; \ + } +# endif /* !BN_LLONG */ + +void BN_RECP_CTX_init(BN_RECP_CTX *recp); +void BN_MONT_CTX_init(BN_MONT_CTX *ctx); + +void bn_init(BIGNUM *a); +void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb); +void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b); +void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b); +void bn_sqr_normal(BN_ULONG *r, const BN_ULONG *a, int n, BN_ULONG *tmp); +void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a); +void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a); +int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n); +int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl); +void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2, + int dna, int dnb, BN_ULONG *t); +void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, + int n, int tna, int tnb, BN_ULONG *t); +void bn_sqr_recursive(BN_ULONG *r, const BN_ULONG *a, int n2, BN_ULONG *t); +void bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n); +void bn_mul_low_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2, + BN_ULONG *t); +BN_ULONG bn_sub_part_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, + int cl, int dl); +int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + const BN_ULONG *np, const BN_ULONG *n0, int num); + +BIGNUM *int_bn_mod_inverse(BIGNUM *in, + const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx, + int *noinv); + +int bn_probable_prime_dh(BIGNUM *rnd, int bits, + const BIGNUM *add, const BIGNUM *rem, BN_CTX *ctx); + +static ossl_inline BIGNUM *bn_expand(BIGNUM *a, int bits) +{ + if (bits > (INT_MAX - BN_BITS2 + 1)) + return NULL; + + if (((bits+BN_BITS2-1)/BN_BITS2) <= (a)->dmax) + return a; + + return bn_expand2((a),(bits+BN_BITS2-1)/BN_BITS2); +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_lib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_lib.c new file mode 100644 index 000000000..8286b3855 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_lib.c @@ -0,0 +1,964 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include "bn_lcl.h" +#include +#include "internal/constant_time_locl.h" + +/* This stuff appears to be completely unused, so is deprecated */ +#if OPENSSL_API_COMPAT < 0x00908000L +/*- + * For a 32 bit machine + * 2 - 4 == 128 + * 3 - 8 == 256 + * 4 - 16 == 512 + * 5 - 32 == 1024 + * 6 - 64 == 2048 + * 7 - 128 == 4096 + * 8 - 256 == 8192 + */ +static int bn_limit_bits = 0; +static int bn_limit_num = 8; /* (1<= 0) { + if (mult > (int)(sizeof(int) * 8) - 1) + mult = sizeof(int) * 8 - 1; + bn_limit_bits = mult; + bn_limit_num = 1 << mult; + } + if (high >= 0) { + if (high > (int)(sizeof(int) * 8) - 1) + high = sizeof(int) * 8 - 1; + bn_limit_bits_high = high; + bn_limit_num_high = 1 << high; + } + if (low >= 0) { + if (low > (int)(sizeof(int) * 8) - 1) + low = sizeof(int) * 8 - 1; + bn_limit_bits_low = low; + bn_limit_num_low = 1 << low; + } + if (mont >= 0) { + if (mont > (int)(sizeof(int) * 8) - 1) + mont = sizeof(int) * 8 - 1; + bn_limit_bits_mont = mont; + bn_limit_num_mont = 1 << mont; + } +} + +int BN_get_params(int which) +{ + if (which == 0) + return bn_limit_bits; + else if (which == 1) + return bn_limit_bits_high; + else if (which == 2) + return bn_limit_bits_low; + else if (which == 3) + return bn_limit_bits_mont; + else + return 0; +} +#endif + +const BIGNUM *BN_value_one(void) +{ + static const BN_ULONG data_one = 1L; + static const BIGNUM const_one = + { (BN_ULONG *)&data_one, 1, 1, 0, BN_FLG_STATIC_DATA }; + + return &const_one; +} + +int BN_num_bits_word(BN_ULONG l) +{ + BN_ULONG x, mask; + int bits = (l != 0); + +#if BN_BITS2 > 32 + x = l >> 32; + mask = (0 - x) & BN_MASK2; + mask = (0 - (mask >> (BN_BITS2 - 1))); + bits += 32 & mask; + l ^= (x ^ l) & mask; +#endif + + x = l >> 16; + mask = (0 - x) & BN_MASK2; + mask = (0 - (mask >> (BN_BITS2 - 1))); + bits += 16 & mask; + l ^= (x ^ l) & mask; + + x = l >> 8; + mask = (0 - x) & BN_MASK2; + mask = (0 - (mask >> (BN_BITS2 - 1))); + bits += 8 & mask; + l ^= (x ^ l) & mask; + + x = l >> 4; + mask = (0 - x) & BN_MASK2; + mask = (0 - (mask >> (BN_BITS2 - 1))); + bits += 4 & mask; + l ^= (x ^ l) & mask; + + x = l >> 2; + mask = (0 - x) & BN_MASK2; + mask = (0 - (mask >> (BN_BITS2 - 1))); + bits += 2 & mask; + l ^= (x ^ l) & mask; + + x = l >> 1; + mask = (0 - x) & BN_MASK2; + mask = (0 - (mask >> (BN_BITS2 - 1))); + bits += 1 & mask; + + return bits; +} + +int BN_num_bits(const BIGNUM *a) +{ + int i = a->top - 1; + bn_check_top(a); + + if (BN_is_zero(a)) + return 0; + return ((i * BN_BITS2) + BN_num_bits_word(a->d[i])); +} + +static void bn_free_d(BIGNUM *a) +{ + if (BN_get_flags(a, BN_FLG_SECURE)) + OPENSSL_secure_free(a->d); + else + OPENSSL_free(a->d); +} + + +void BN_clear_free(BIGNUM *a) +{ + if (a == NULL) + return; + if (a->d != NULL && !BN_get_flags(a, BN_FLG_STATIC_DATA)) { + OPENSSL_cleanse(a->d, a->dmax * sizeof(a->d[0])); + bn_free_d(a); + } + if (BN_get_flags(a, BN_FLG_MALLOCED)) { + OPENSSL_cleanse(a, sizeof(*a)); + OPENSSL_free(a); + } +} + +void BN_free(BIGNUM *a) +{ + if (a == NULL) + return; + if (!BN_get_flags(a, BN_FLG_STATIC_DATA)) + bn_free_d(a); + if (a->flags & BN_FLG_MALLOCED) + OPENSSL_free(a); +} + +void bn_init(BIGNUM *a) +{ + static BIGNUM nilbn; + + *a = nilbn; + bn_check_top(a); +} + +BIGNUM *BN_new(void) +{ + BIGNUM *ret; + + if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) { + BNerr(BN_F_BN_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + ret->flags = BN_FLG_MALLOCED; + bn_check_top(ret); + return ret; +} + + BIGNUM *BN_secure_new(void) + { + BIGNUM *ret = BN_new(); + if (ret != NULL) + ret->flags |= BN_FLG_SECURE; + return ret; + } + +/* This is used by bn_expand2() */ +/* The caller MUST check that words > b->dmax before calling this */ +static BN_ULONG *bn_expand_internal(const BIGNUM *b, int words) +{ + BN_ULONG *a = NULL; + + if (words > (INT_MAX / (4 * BN_BITS2))) { + BNerr(BN_F_BN_EXPAND_INTERNAL, BN_R_BIGNUM_TOO_LONG); + return NULL; + } + if (BN_get_flags(b, BN_FLG_STATIC_DATA)) { + BNerr(BN_F_BN_EXPAND_INTERNAL, BN_R_EXPAND_ON_STATIC_BIGNUM_DATA); + return NULL; + } + if (BN_get_flags(b, BN_FLG_SECURE)) + a = OPENSSL_secure_zalloc(words * sizeof(*a)); + else + a = OPENSSL_zalloc(words * sizeof(*a)); + if (a == NULL) { + BNerr(BN_F_BN_EXPAND_INTERNAL, ERR_R_MALLOC_FAILURE); + return NULL; + } + + assert(b->top <= words); + if (b->top > 0) + memcpy(a, b->d, sizeof(*a) * b->top); + + return a; +} + +/* + * This is an internal function that should not be used in applications. It + * ensures that 'b' has enough room for a 'words' word number and initialises + * any unused part of b->d with leading zeros. It is mostly used by the + * various BIGNUM routines. If there is an error, NULL is returned. If not, + * 'b' is returned. + */ + +BIGNUM *bn_expand2(BIGNUM *b, int words) +{ + if (words > b->dmax) { + BN_ULONG *a = bn_expand_internal(b, words); + if (!a) + return NULL; + if (b->d) { + OPENSSL_cleanse(b->d, b->dmax * sizeof(b->d[0])); + bn_free_d(b); + } + b->d = a; + b->dmax = words; + } + + return b; +} + +BIGNUM *BN_dup(const BIGNUM *a) +{ + BIGNUM *t; + + if (a == NULL) + return NULL; + bn_check_top(a); + + t = BN_get_flags(a, BN_FLG_SECURE) ? BN_secure_new() : BN_new(); + if (t == NULL) + return NULL; + if (!BN_copy(t, a)) { + BN_free(t); + return NULL; + } + bn_check_top(t); + return t; +} + +BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b) +{ + bn_check_top(b); + + if (a == b) + return a; + if (bn_wexpand(a, b->top) == NULL) + return NULL; + + if (b->top > 0) + memcpy(a->d, b->d, sizeof(b->d[0]) * b->top); + + a->neg = b->neg; + a->top = b->top; + a->flags |= b->flags & BN_FLG_FIXED_TOP; + bn_check_top(a); + return a; +} + +#define FLAGS_DATA(flags) ((flags) & (BN_FLG_STATIC_DATA \ + | BN_FLG_CONSTTIME \ + | BN_FLG_SECURE \ + | BN_FLG_FIXED_TOP)) +#define FLAGS_STRUCT(flags) ((flags) & (BN_FLG_MALLOCED)) + +void BN_swap(BIGNUM *a, BIGNUM *b) +{ + int flags_old_a, flags_old_b; + BN_ULONG *tmp_d; + int tmp_top, tmp_dmax, tmp_neg; + + bn_check_top(a); + bn_check_top(b); + + flags_old_a = a->flags; + flags_old_b = b->flags; + + tmp_d = a->d; + tmp_top = a->top; + tmp_dmax = a->dmax; + tmp_neg = a->neg; + + a->d = b->d; + a->top = b->top; + a->dmax = b->dmax; + a->neg = b->neg; + + b->d = tmp_d; + b->top = tmp_top; + b->dmax = tmp_dmax; + b->neg = tmp_neg; + + a->flags = FLAGS_STRUCT(flags_old_a) | FLAGS_DATA(flags_old_b); + b->flags = FLAGS_STRUCT(flags_old_b) | FLAGS_DATA(flags_old_a); + bn_check_top(a); + bn_check_top(b); +} + +void BN_clear(BIGNUM *a) +{ + bn_check_top(a); + if (a->d != NULL) + OPENSSL_cleanse(a->d, sizeof(*a->d) * a->dmax); + a->neg = 0; + a->top = 0; + a->flags &= ~BN_FLG_FIXED_TOP; +} + +BN_ULONG BN_get_word(const BIGNUM *a) +{ + if (a->top > 1) + return BN_MASK2; + else if (a->top == 1) + return a->d[0]; + /* a->top == 0 */ + return 0; +} + +int BN_set_word(BIGNUM *a, BN_ULONG w) +{ + bn_check_top(a); + if (bn_expand(a, (int)sizeof(BN_ULONG) * 8) == NULL) + return 0; + a->neg = 0; + a->d[0] = w; + a->top = (w ? 1 : 0); + a->flags &= ~BN_FLG_FIXED_TOP; + bn_check_top(a); + return 1; +} + +BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret) +{ + unsigned int i, m; + unsigned int n; + BN_ULONG l; + BIGNUM *bn = NULL; + + if (ret == NULL) + ret = bn = BN_new(); + if (ret == NULL) + return NULL; + bn_check_top(ret); + /* Skip leading zero's. */ + for ( ; len > 0 && *s == 0; s++, len--) + continue; + n = len; + if (n == 0) { + ret->top = 0; + return ret; + } + i = ((n - 1) / BN_BYTES) + 1; + m = ((n - 1) % (BN_BYTES)); + if (bn_wexpand(ret, (int)i) == NULL) { + BN_free(bn); + return NULL; + } + ret->top = i; + ret->neg = 0; + l = 0; + while (n--) { + l = (l << 8L) | *(s++); + if (m-- == 0) { + ret->d[--i] = l; + l = 0; + m = BN_BYTES - 1; + } + } + /* + * need to call this due to clear byte at top if avoiding having the top + * bit set (-ve number) + */ + bn_correct_top(ret); + return ret; +} + +/* ignore negative */ +static int bn2binpad(const BIGNUM *a, unsigned char *to, int tolen) +{ + int n; + size_t i, lasti, j, atop, mask; + BN_ULONG l; + + /* + * In case |a| is fixed-top, BN_num_bytes can return bogus length, + * but it's assumed that fixed-top inputs ought to be "nominated" + * even for padded output, so it works out... + */ + n = BN_num_bytes(a); + if (tolen == -1) { + tolen = n; + } else if (tolen < n) { /* uncommon/unlike case */ + BIGNUM temp = *a; + + bn_correct_top(&temp); + n = BN_num_bytes(&temp); + if (tolen < n) + return -1; + } + + /* Swipe through whole available data and don't give away padded zero. */ + atop = a->dmax * BN_BYTES; + if (atop == 0) { + OPENSSL_cleanse(to, tolen); + return tolen; + } + + lasti = atop - 1; + atop = a->top * BN_BYTES; + for (i = 0, j = 0, to += tolen; j < (size_t)tolen; j++) { + l = a->d[i / BN_BYTES]; + mask = 0 - ((j - atop) >> (8 * sizeof(i) - 1)); + *--to = (unsigned char)(l >> (8 * (i % BN_BYTES)) & mask); + i += (i - lasti) >> (8 * sizeof(i) - 1); /* stay on last limb */ + } + + return tolen; +} + +int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen) +{ + if (tolen < 0) + return -1; + return bn2binpad(a, to, tolen); +} + +int BN_bn2bin(const BIGNUM *a, unsigned char *to) +{ + return bn2binpad(a, to, -1); +} + +BIGNUM *BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret) +{ + unsigned int i, m; + unsigned int n; + BN_ULONG l; + BIGNUM *bn = NULL; + + if (ret == NULL) + ret = bn = BN_new(); + if (ret == NULL) + return NULL; + bn_check_top(ret); + s += len; + /* Skip trailing zeroes. */ + for ( ; len > 0 && s[-1] == 0; s--, len--) + continue; + n = len; + if (n == 0) { + ret->top = 0; + return ret; + } + i = ((n - 1) / BN_BYTES) + 1; + m = ((n - 1) % (BN_BYTES)); + if (bn_wexpand(ret, (int)i) == NULL) { + BN_free(bn); + return NULL; + } + ret->top = i; + ret->neg = 0; + l = 0; + while (n--) { + s--; + l = (l << 8L) | *s; + if (m-- == 0) { + ret->d[--i] = l; + l = 0; + m = BN_BYTES - 1; + } + } + /* + * need to call this due to clear byte at top if avoiding having the top + * bit set (-ve number) + */ + bn_correct_top(ret); + return ret; +} + +int BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen) +{ + int i; + BN_ULONG l; + bn_check_top(a); + i = BN_num_bytes(a); + if (tolen < i) + return -1; + /* Add trailing zeroes if necessary */ + if (tolen > i) + memset(to + i, 0, tolen - i); + to += i; + while (i--) { + l = a->d[i / BN_BYTES]; + to--; + *to = (unsigned char)(l >> (8 * (i % BN_BYTES))) & 0xff; + } + return tolen; +} + +int BN_ucmp(const BIGNUM *a, const BIGNUM *b) +{ + int i; + BN_ULONG t1, t2, *ap, *bp; + + bn_check_top(a); + bn_check_top(b); + + i = a->top - b->top; + if (i != 0) + return i; + ap = a->d; + bp = b->d; + for (i = a->top - 1; i >= 0; i--) { + t1 = ap[i]; + t2 = bp[i]; + if (t1 != t2) + return ((t1 > t2) ? 1 : -1); + } + return 0; +} + +int BN_cmp(const BIGNUM *a, const BIGNUM *b) +{ + int i; + int gt, lt; + BN_ULONG t1, t2; + + if ((a == NULL) || (b == NULL)) { + if (a != NULL) + return -1; + else if (b != NULL) + return 1; + else + return 0; + } + + bn_check_top(a); + bn_check_top(b); + + if (a->neg != b->neg) { + if (a->neg) + return -1; + else + return 1; + } + if (a->neg == 0) { + gt = 1; + lt = -1; + } else { + gt = -1; + lt = 1; + } + + if (a->top > b->top) + return gt; + if (a->top < b->top) + return lt; + for (i = a->top - 1; i >= 0; i--) { + t1 = a->d[i]; + t2 = b->d[i]; + if (t1 > t2) + return gt; + if (t1 < t2) + return lt; + } + return 0; +} + +int BN_set_bit(BIGNUM *a, int n) +{ + int i, j, k; + + if (n < 0) + return 0; + + i = n / BN_BITS2; + j = n % BN_BITS2; + if (a->top <= i) { + if (bn_wexpand(a, i + 1) == NULL) + return 0; + for (k = a->top; k < i + 1; k++) + a->d[k] = 0; + a->top = i + 1; + a->flags &= ~BN_FLG_FIXED_TOP; + } + + a->d[i] |= (((BN_ULONG)1) << j); + bn_check_top(a); + return 1; +} + +int BN_clear_bit(BIGNUM *a, int n) +{ + int i, j; + + bn_check_top(a); + if (n < 0) + return 0; + + i = n / BN_BITS2; + j = n % BN_BITS2; + if (a->top <= i) + return 0; + + a->d[i] &= (~(((BN_ULONG)1) << j)); + bn_correct_top(a); + return 1; +} + +int BN_is_bit_set(const BIGNUM *a, int n) +{ + int i, j; + + bn_check_top(a); + if (n < 0) + return 0; + i = n / BN_BITS2; + j = n % BN_BITS2; + if (a->top <= i) + return 0; + return (int)(((a->d[i]) >> j) & ((BN_ULONG)1)); +} + +int BN_mask_bits(BIGNUM *a, int n) +{ + int b, w; + + bn_check_top(a); + if (n < 0) + return 0; + + w = n / BN_BITS2; + b = n % BN_BITS2; + if (w >= a->top) + return 0; + if (b == 0) + a->top = w; + else { + a->top = w + 1; + a->d[w] &= ~(BN_MASK2 << b); + } + bn_correct_top(a); + return 1; +} + +void BN_set_negative(BIGNUM *a, int b) +{ + if (b && !BN_is_zero(a)) + a->neg = 1; + else + a->neg = 0; +} + +int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n) +{ + int i; + BN_ULONG aa, bb; + + if (n == 0) + return 0; + + aa = a[n - 1]; + bb = b[n - 1]; + if (aa != bb) + return ((aa > bb) ? 1 : -1); + for (i = n - 2; i >= 0; i--) { + aa = a[i]; + bb = b[i]; + if (aa != bb) + return ((aa > bb) ? 1 : -1); + } + return 0; +} + +/* + * Here follows a specialised variants of bn_cmp_words(). It has the + * capability of performing the operation on arrays of different sizes. The + * sizes of those arrays is expressed through cl, which is the common length + * ( basically, min(len(a),len(b)) ), and dl, which is the delta between the + * two lengths, calculated as len(a)-len(b). All lengths are the number of + * BN_ULONGs... + */ + +int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl) +{ + int n, i; + n = cl - 1; + + if (dl < 0) { + for (i = dl; i < 0; i++) { + if (b[n - i] != 0) + return -1; /* a < b */ + } + } + if (dl > 0) { + for (i = dl; i > 0; i--) { + if (a[n + i] != 0) + return 1; /* a > b */ + } + } + return bn_cmp_words(a, b, cl); +} + +/*- + * Constant-time conditional swap of a and b. + * a and b are swapped if condition is not 0. + * nwords is the number of words to swap. + * Assumes that at least nwords are allocated in both a and b. + * Assumes that no more than nwords are used by either a or b. + */ +void BN_consttime_swap(BN_ULONG condition, BIGNUM *a, BIGNUM *b, int nwords) +{ + BN_ULONG t; + int i; + + if (a == b) + return; + + bn_wcheck_size(a, nwords); + bn_wcheck_size(b, nwords); + + condition = ((~condition & ((condition - 1))) >> (BN_BITS2 - 1)) - 1; + + t = (a->top ^ b->top) & condition; + a->top ^= t; + b->top ^= t; + + t = (a->neg ^ b->neg) & condition; + a->neg ^= t; + b->neg ^= t; + + /*- + * BN_FLG_STATIC_DATA: indicates that data may not be written to. Intention + * is actually to treat it as it's read-only data, and some (if not most) + * of it does reside in read-only segment. In other words observation of + * BN_FLG_STATIC_DATA in BN_consttime_swap should be treated as fatal + * condition. It would either cause SEGV or effectively cause data + * corruption. + * + * BN_FLG_MALLOCED: refers to BN structure itself, and hence must be + * preserved. + * + * BN_FLG_SECURE: must be preserved, because it determines how x->d was + * allocated and hence how to free it. + * + * BN_FLG_CONSTTIME: sufficient to mask and swap + * + * BN_FLG_FIXED_TOP: indicates that we haven't called bn_correct_top() on + * the data, so the d array may be padded with additional 0 values (i.e. + * top could be greater than the minimal value that it could be). We should + * be swapping it + */ + +#define BN_CONSTTIME_SWAP_FLAGS (BN_FLG_CONSTTIME | BN_FLG_FIXED_TOP) + + t = ((a->flags ^ b->flags) & BN_CONSTTIME_SWAP_FLAGS) & condition; + a->flags ^= t; + b->flags ^= t; + + /* conditionally swap the data */ + for (i = 0; i < nwords; i++) { + t = (a->d[i] ^ b->d[i]) & condition; + a->d[i] ^= t; + b->d[i] ^= t; + } +} + +#undef BN_CONSTTIME_SWAP_FLAGS + +/* Bits of security, see SP800-57 */ + +int BN_security_bits(int L, int N) +{ + int secbits, bits; + if (L >= 15360) + secbits = 256; + else if (L >= 7680) + secbits = 192; + else if (L >= 3072) + secbits = 128; + else if (L >= 2048) + secbits = 112; + else if (L >= 1024) + secbits = 80; + else + return 0; + if (N == -1) + return secbits; + bits = N / 2; + if (bits < 80) + return 0; + return bits >= secbits ? secbits : bits; +} + +void BN_zero_ex(BIGNUM *a) +{ + a->neg = 0; + a->top = 0; + a->flags &= ~BN_FLG_FIXED_TOP; +} + +int BN_abs_is_word(const BIGNUM *a, const BN_ULONG w) +{ + return ((a->top == 1) && (a->d[0] == w)) || ((w == 0) && (a->top == 0)); +} + +int BN_is_zero(const BIGNUM *a) +{ + return a->top == 0; +} + +int BN_is_one(const BIGNUM *a) +{ + return BN_abs_is_word(a, 1) && !a->neg; +} + +int BN_is_word(const BIGNUM *a, const BN_ULONG w) +{ + return BN_abs_is_word(a, w) && (!w || !a->neg); +} + +int BN_is_odd(const BIGNUM *a) +{ + return (a->top > 0) && (a->d[0] & 1); +} + +int BN_is_negative(const BIGNUM *a) +{ + return (a->neg != 0); +} + +int BN_to_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont, + BN_CTX *ctx) +{ + return BN_mod_mul_montgomery(r, a, &(mont->RR), mont, ctx); +} + +void BN_with_flags(BIGNUM *dest, const BIGNUM *b, int flags) +{ + dest->d = b->d; + dest->top = b->top; + dest->dmax = b->dmax; + dest->neg = b->neg; + dest->flags = ((dest->flags & BN_FLG_MALLOCED) + | (b->flags & ~BN_FLG_MALLOCED) + | BN_FLG_STATIC_DATA | flags); +} + +BN_GENCB *BN_GENCB_new(void) +{ + BN_GENCB *ret; + + if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) { + BNerr(BN_F_BN_GENCB_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + return ret; +} + +void BN_GENCB_free(BN_GENCB *cb) +{ + if (cb == NULL) + return; + OPENSSL_free(cb); +} + +void BN_set_flags(BIGNUM *b, int n) +{ + b->flags |= n; +} + +int BN_get_flags(const BIGNUM *b, int n) +{ + return b->flags & n; +} + +/* Populate a BN_GENCB structure with an "old"-style callback */ +void BN_GENCB_set_old(BN_GENCB *gencb, void (*callback) (int, int, void *), + void *cb_arg) +{ + BN_GENCB *tmp_gencb = gencb; + tmp_gencb->ver = 1; + tmp_gencb->arg = cb_arg; + tmp_gencb->cb.cb_1 = callback; +} + +/* Populate a BN_GENCB structure with a "new"-style callback */ +void BN_GENCB_set(BN_GENCB *gencb, int (*callback) (int, int, BN_GENCB *), + void *cb_arg) +{ + BN_GENCB *tmp_gencb = gencb; + tmp_gencb->ver = 2; + tmp_gencb->arg = cb_arg; + tmp_gencb->cb.cb_2 = callback; +} + +void *BN_GENCB_get_arg(BN_GENCB *cb) +{ + return cb->arg; +} + +BIGNUM *bn_wexpand(BIGNUM *a, int words) +{ + return (words <= a->dmax) ? a : bn_expand2(a, words); +} + +void bn_correct_top(BIGNUM *a) +{ + BN_ULONG *ftl; + int tmp_top = a->top; + + if (tmp_top > 0) { + for (ftl = &(a->d[tmp_top]); tmp_top > 0; tmp_top--) { + ftl--; + if (*ftl != 0) + break; + } + a->top = tmp_top; + } + if (a->top == 0) + a->neg = 0; + a->flags &= ~BN_FLG_FIXED_TOP; + bn_pollute(a); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_mod.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_mod.c new file mode 100644 index 000000000..712fc8ac1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_mod.c @@ -0,0 +1,321 @@ +/* + * Copyright 1998-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include "bn_lcl.h" + +int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx) +{ + /* + * like BN_mod, but returns non-negative remainder (i.e., 0 <= r < |d| + * always holds) + */ + + if (!(BN_mod(r, m, d, ctx))) + return 0; + if (!r->neg) + return 1; + /* now -|d| < r < 0, so we have to set r := r + |d| */ + return (d->neg ? BN_sub : BN_add) (r, r, d); +} + +int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, + BN_CTX *ctx) +{ + if (!BN_add(r, a, b)) + return 0; + return BN_nnmod(r, r, m, ctx); +} + +/* + * BN_mod_add variant that may be used if both a and b are non-negative and + * less than m. The original algorithm was + * + * if (!BN_uadd(r, a, b)) + * return 0; + * if (BN_ucmp(r, m) >= 0) + * return BN_usub(r, r, m); + * + * which is replaced with addition, subtracting modulus, and conditional + * move depending on whether or not subtraction borrowed. + */ +int bn_mod_add_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m) +{ + size_t i, ai, bi, mtop = m->top; + BN_ULONG storage[1024 / BN_BITS2]; + BN_ULONG carry, temp, mask, *rp, *tp = storage; + const BN_ULONG *ap, *bp; + + if (bn_wexpand(r, mtop) == NULL) + return 0; + + if (mtop > sizeof(storage) / sizeof(storage[0]) + && (tp = OPENSSL_malloc(mtop * sizeof(BN_ULONG))) == NULL) + return 0; + + ap = a->d != NULL ? a->d : tp; + bp = b->d != NULL ? b->d : tp; + + for (i = 0, ai = 0, bi = 0, carry = 0; i < mtop;) { + mask = (BN_ULONG)0 - ((i - a->top) >> (8 * sizeof(i) - 1)); + temp = ((ap[ai] & mask) + carry) & BN_MASK2; + carry = (temp < carry); + + mask = (BN_ULONG)0 - ((i - b->top) >> (8 * sizeof(i) - 1)); + tp[i] = ((bp[bi] & mask) + temp) & BN_MASK2; + carry += (tp[i] < temp); + + i++; + ai += (i - a->dmax) >> (8 * sizeof(i) - 1); + bi += (i - b->dmax) >> (8 * sizeof(i) - 1); + } + rp = r->d; + carry -= bn_sub_words(rp, tp, m->d, mtop); + for (i = 0; i < mtop; i++) { + rp[i] = (carry & tp[i]) | (~carry & rp[i]); + ((volatile BN_ULONG *)tp)[i] = 0; + } + r->top = mtop; + r->flags |= BN_FLG_FIXED_TOP; + r->neg = 0; + + if (tp != storage) + OPENSSL_free(tp); + + return 1; +} + +int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m) +{ + int ret = bn_mod_add_fixed_top(r, a, b, m); + + if (ret) + bn_correct_top(r); + + return ret; +} + +int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, + BN_CTX *ctx) +{ + if (!BN_sub(r, a, b)) + return 0; + return BN_nnmod(r, r, m, ctx); +} + +/* + * BN_mod_sub variant that may be used if both a and b are non-negative, + * a is less than m, while b is of same bit width as m. It's implemented + * as subtraction followed by two conditional additions. + * + * 0 <= a < m + * 0 <= b < 2^w < 2*m + * + * after subtraction + * + * -2*m < r = a - b < m + * + * Thus it takes up to two conditional additions to make |r| positive. + */ +int bn_mod_sub_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m) +{ + size_t i, ai, bi, mtop = m->top; + BN_ULONG borrow, carry, ta, tb, mask, *rp; + const BN_ULONG *ap, *bp; + + if (bn_wexpand(r, mtop) == NULL) + return 0; + + rp = r->d; + ap = a->d != NULL ? a->d : rp; + bp = b->d != NULL ? b->d : rp; + + for (i = 0, ai = 0, bi = 0, borrow = 0; i < mtop;) { + mask = (BN_ULONG)0 - ((i - a->top) >> (8 * sizeof(i) - 1)); + ta = ap[ai] & mask; + + mask = (BN_ULONG)0 - ((i - b->top) >> (8 * sizeof(i) - 1)); + tb = bp[bi] & mask; + rp[i] = ta - tb - borrow; + if (ta != tb) + borrow = (ta < tb); + + i++; + ai += (i - a->dmax) >> (8 * sizeof(i) - 1); + bi += (i - b->dmax) >> (8 * sizeof(i) - 1); + } + ap = m->d; + for (i = 0, mask = 0 - borrow, carry = 0; i < mtop; i++) { + ta = ((ap[i] & mask) + carry) & BN_MASK2; + carry = (ta < carry); + rp[i] = (rp[i] + ta) & BN_MASK2; + carry += (rp[i] < ta); + } + borrow -= carry; + for (i = 0, mask = 0 - borrow, carry = 0; i < mtop; i++) { + ta = ((ap[i] & mask) + carry) & BN_MASK2; + carry = (ta < carry); + rp[i] = (rp[i] + ta) & BN_MASK2; + carry += (rp[i] < ta); + } + + r->top = mtop; + r->flags |= BN_FLG_FIXED_TOP; + r->neg = 0; + + return 1; +} + +/* + * BN_mod_sub variant that may be used if both a and b are non-negative and + * less than m + */ +int BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m) +{ + if (!BN_sub(r, a, b)) + return 0; + if (r->neg) + return BN_add(r, r, m); + return 1; +} + +/* slow but works */ +int BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, + BN_CTX *ctx) +{ + BIGNUM *t; + int ret = 0; + + bn_check_top(a); + bn_check_top(b); + bn_check_top(m); + + BN_CTX_start(ctx); + if ((t = BN_CTX_get(ctx)) == NULL) + goto err; + if (a == b) { + if (!BN_sqr(t, a, ctx)) + goto err; + } else { + if (!BN_mul(t, a, b, ctx)) + goto err; + } + if (!BN_nnmod(r, t, m, ctx)) + goto err; + bn_check_top(r); + ret = 1; + err: + BN_CTX_end(ctx); + return ret; +} + +int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx) +{ + if (!BN_sqr(r, a, ctx)) + return 0; + /* r->neg == 0, thus we don't need BN_nnmod */ + return BN_mod(r, r, m, ctx); +} + +int BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx) +{ + if (!BN_lshift1(r, a)) + return 0; + bn_check_top(r); + return BN_nnmod(r, r, m, ctx); +} + +/* + * BN_mod_lshift1 variant that may be used if a is non-negative and less than + * m + */ +int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m) +{ + if (!BN_lshift1(r, a)) + return 0; + bn_check_top(r); + if (BN_cmp(r, m) >= 0) + return BN_sub(r, r, m); + return 1; +} + +int BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m, + BN_CTX *ctx) +{ + BIGNUM *abs_m = NULL; + int ret; + + if (!BN_nnmod(r, a, m, ctx)) + return 0; + + if (m->neg) { + abs_m = BN_dup(m); + if (abs_m == NULL) + return 0; + abs_m->neg = 0; + } + + ret = BN_mod_lshift_quick(r, r, n, (abs_m ? abs_m : m)); + bn_check_top(r); + + BN_free(abs_m); + return ret; +} + +/* + * BN_mod_lshift variant that may be used if a is non-negative and less than + * m + */ +int BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m) +{ + if (r != a) { + if (BN_copy(r, a) == NULL) + return 0; + } + + while (n > 0) { + int max_shift; + + /* 0 < r < m */ + max_shift = BN_num_bits(m) - BN_num_bits(r); + /* max_shift >= 0 */ + + if (max_shift < 0) { + BNerr(BN_F_BN_MOD_LSHIFT_QUICK, BN_R_INPUT_NOT_REDUCED); + return 0; + } + + if (max_shift > n) + max_shift = n; + + if (max_shift) { + if (!BN_lshift(r, r, max_shift)) + return 0; + n -= max_shift; + } else { + if (!BN_lshift1(r, r)) + return 0; + --n; + } + + /* BN_num_bits(r) <= BN_num_bits(m) */ + + if (BN_cmp(r, m) >= 0) { + if (!BN_sub(r, r, m)) + return 0; + } + } + bn_check_top(r); + + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_mont.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_mont.c new file mode 100644 index 000000000..393d27c39 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_mont.c @@ -0,0 +1,464 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Details about Montgomery multiplication algorithms can be found at + * http://security.ece.orst.edu/publications.html, e.g. + * http://security.ece.orst.edu/koc/papers/j37acmon.pdf and + * sections 3.8 and 4.2 in http://security.ece.orst.edu/koc/papers/r01rsasw.pdf + */ + +#include "internal/cryptlib.h" +#include "bn_lcl.h" + +#define MONT_WORD /* use the faster word-based algorithm */ + +#ifdef MONT_WORD +static int bn_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont); +#endif + +int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + BN_MONT_CTX *mont, BN_CTX *ctx) +{ + int ret = bn_mul_mont_fixed_top(r, a, b, mont, ctx); + + bn_correct_top(r); + bn_check_top(r); + + return ret; +} + +int bn_mul_mont_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + BN_MONT_CTX *mont, BN_CTX *ctx) +{ + BIGNUM *tmp; + int ret = 0; + int num = mont->N.top; + +#if defined(OPENSSL_BN_ASM_MONT) && defined(MONT_WORD) + if (num > 1 && a->top == num && b->top == num) { + if (bn_wexpand(r, num) == NULL) + return 0; + if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) { + r->neg = a->neg ^ b->neg; + r->top = num; + r->flags |= BN_FLG_FIXED_TOP; + return 1; + } + } +#endif + + if ((a->top + b->top) > 2 * num) + return 0; + + BN_CTX_start(ctx); + tmp = BN_CTX_get(ctx); + if (tmp == NULL) + goto err; + + bn_check_top(tmp); + if (a == b) { + if (!bn_sqr_fixed_top(tmp, a, ctx)) + goto err; + } else { + if (!bn_mul_fixed_top(tmp, a, b, ctx)) + goto err; + } + /* reduce from aRR to aR */ +#ifdef MONT_WORD + if (!bn_from_montgomery_word(r, tmp, mont)) + goto err; +#else + if (!BN_from_montgomery(r, tmp, mont, ctx)) + goto err; +#endif + ret = 1; + err: + BN_CTX_end(ctx); + return ret; +} + +#ifdef MONT_WORD +static int bn_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont) +{ + BIGNUM *n; + BN_ULONG *ap, *np, *rp, n0, v, carry; + int nl, max, i; + unsigned int rtop; + + n = &(mont->N); + nl = n->top; + if (nl == 0) { + ret->top = 0; + return 1; + } + + max = (2 * nl); /* carry is stored separately */ + if (bn_wexpand(r, max) == NULL) + return 0; + + r->neg ^= n->neg; + np = n->d; + rp = r->d; + + /* clear the top words of T */ + for (rtop = r->top, i = 0; i < max; i++) { + v = (BN_ULONG)0 - ((i - rtop) >> (8 * sizeof(rtop) - 1)); + rp[i] &= v; + } + + r->top = max; + r->flags |= BN_FLG_FIXED_TOP; + n0 = mont->n0[0]; + + /* + * Add multiples of |n| to |r| until R = 2^(nl * BN_BITS2) divides it. On + * input, we had |r| < |n| * R, so now |r| < 2 * |n| * R. Note that |r| + * includes |carry| which is stored separately. + */ + for (carry = 0, i = 0; i < nl; i++, rp++) { + v = bn_mul_add_words(rp, np, nl, (rp[0] * n0) & BN_MASK2); + v = (v + carry + rp[nl]) & BN_MASK2; + carry |= (v != rp[nl]); + carry &= (v <= rp[nl]); + rp[nl] = v; + } + + if (bn_wexpand(ret, nl) == NULL) + return 0; + ret->top = nl; + ret->flags |= BN_FLG_FIXED_TOP; + ret->neg = r->neg; + + rp = ret->d; + + /* + * Shift |nl| words to divide by R. We have |ap| < 2 * |n|. Note that |ap| + * includes |carry| which is stored separately. + */ + ap = &(r->d[nl]); + + carry -= bn_sub_words(rp, ap, np, nl); + /* + * |carry| is -1 if |ap| - |np| underflowed or zero if it did not. Note + * |carry| cannot be 1. That would imply the subtraction did not fit in + * |nl| words, and we know at most one subtraction is needed. + */ + for (i = 0; i < nl; i++) { + rp[i] = (carry & ap[i]) | (~carry & rp[i]); + ap[i] = 0; + } + + return 1; +} +#endif /* MONT_WORD */ + +int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont, + BN_CTX *ctx) +{ + int retn; + + retn = bn_from_mont_fixed_top(ret, a, mont, ctx); + bn_correct_top(ret); + bn_check_top(ret); + + return retn; +} + +int bn_from_mont_fixed_top(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont, + BN_CTX *ctx) +{ + int retn = 0; +#ifdef MONT_WORD + BIGNUM *t; + + BN_CTX_start(ctx); + if ((t = BN_CTX_get(ctx)) && BN_copy(t, a)) { + retn = bn_from_montgomery_word(ret, t, mont); + } + BN_CTX_end(ctx); +#else /* !MONT_WORD */ + BIGNUM *t1, *t2; + + BN_CTX_start(ctx); + t1 = BN_CTX_get(ctx); + t2 = BN_CTX_get(ctx); + if (t2 == NULL) + goto err; + + if (!BN_copy(t1, a)) + goto err; + BN_mask_bits(t1, mont->ri); + + if (!BN_mul(t2, t1, &mont->Ni, ctx)) + goto err; + BN_mask_bits(t2, mont->ri); + + if (!BN_mul(t1, t2, &mont->N, ctx)) + goto err; + if (!BN_add(t2, a, t1)) + goto err; + if (!BN_rshift(ret, t2, mont->ri)) + goto err; + + if (BN_ucmp(ret, &(mont->N)) >= 0) { + if (!BN_usub(ret, ret, &(mont->N))) + goto err; + } + retn = 1; + bn_check_top(ret); + err: + BN_CTX_end(ctx); +#endif /* MONT_WORD */ + return retn; +} + +int bn_to_mont_fixed_top(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont, + BN_CTX *ctx) +{ + return bn_mul_mont_fixed_top(r, a, &(mont->RR), mont, ctx); +} + +BN_MONT_CTX *BN_MONT_CTX_new(void) +{ + BN_MONT_CTX *ret; + + if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) { + BNerr(BN_F_BN_MONT_CTX_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + BN_MONT_CTX_init(ret); + ret->flags = BN_FLG_MALLOCED; + return ret; +} + +void BN_MONT_CTX_init(BN_MONT_CTX *ctx) +{ + ctx->ri = 0; + bn_init(&ctx->RR); + bn_init(&ctx->N); + bn_init(&ctx->Ni); + ctx->n0[0] = ctx->n0[1] = 0; + ctx->flags = 0; +} + +void BN_MONT_CTX_free(BN_MONT_CTX *mont) +{ + if (mont == NULL) + return; + BN_clear_free(&mont->RR); + BN_clear_free(&mont->N); + BN_clear_free(&mont->Ni); + if (mont->flags & BN_FLG_MALLOCED) + OPENSSL_free(mont); +} + +int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) +{ + int i, ret = 0; + BIGNUM *Ri, *R; + + if (BN_is_zero(mod)) + return 0; + + BN_CTX_start(ctx); + if ((Ri = BN_CTX_get(ctx)) == NULL) + goto err; + R = &(mont->RR); /* grab RR as a temp */ + if (!BN_copy(&(mont->N), mod)) + goto err; /* Set N */ + if (BN_get_flags(mod, BN_FLG_CONSTTIME) != 0) + BN_set_flags(&(mont->N), BN_FLG_CONSTTIME); + mont->N.neg = 0; + +#ifdef MONT_WORD + { + BIGNUM tmod; + BN_ULONG buf[2]; + + bn_init(&tmod); + tmod.d = buf; + tmod.dmax = 2; + tmod.neg = 0; + + if (BN_get_flags(mod, BN_FLG_CONSTTIME) != 0) + BN_set_flags(&tmod, BN_FLG_CONSTTIME); + + mont->ri = (BN_num_bits(mod) + (BN_BITS2 - 1)) / BN_BITS2 * BN_BITS2; + +# if defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2<=32) + /* + * Only certain BN_BITS2<=32 platforms actually make use of n0[1], + * and we could use the #else case (with a shorter R value) for the + * others. However, currently only the assembler files do know which + * is which. + */ + + BN_zero(R); + if (!(BN_set_bit(R, 2 * BN_BITS2))) + goto err; + + tmod.top = 0; + if ((buf[0] = mod->d[0])) + tmod.top = 1; + if ((buf[1] = mod->top > 1 ? mod->d[1] : 0)) + tmod.top = 2; + + if (BN_is_one(&tmod)) + BN_zero(Ri); + else if ((BN_mod_inverse(Ri, R, &tmod, ctx)) == NULL) + goto err; + if (!BN_lshift(Ri, Ri, 2 * BN_BITS2)) + goto err; /* R*Ri */ + if (!BN_is_zero(Ri)) { + if (!BN_sub_word(Ri, 1)) + goto err; + } else { /* if N mod word size == 1 */ + + if (bn_expand(Ri, (int)sizeof(BN_ULONG) * 2) == NULL) + goto err; + /* Ri-- (mod double word size) */ + Ri->neg = 0; + Ri->d[0] = BN_MASK2; + Ri->d[1] = BN_MASK2; + Ri->top = 2; + } + if (!BN_div(Ri, NULL, Ri, &tmod, ctx)) + goto err; + /* + * Ni = (R*Ri-1)/N, keep only couple of least significant words: + */ + mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0; + mont->n0[1] = (Ri->top > 1) ? Ri->d[1] : 0; +# else + BN_zero(R); + if (!(BN_set_bit(R, BN_BITS2))) + goto err; /* R */ + + buf[0] = mod->d[0]; /* tmod = N mod word size */ + buf[1] = 0; + tmod.top = buf[0] != 0 ? 1 : 0; + /* Ri = R^-1 mod N */ + if (BN_is_one(&tmod)) + BN_zero(Ri); + else if ((BN_mod_inverse(Ri, R, &tmod, ctx)) == NULL) + goto err; + if (!BN_lshift(Ri, Ri, BN_BITS2)) + goto err; /* R*Ri */ + if (!BN_is_zero(Ri)) { + if (!BN_sub_word(Ri, 1)) + goto err; + } else { /* if N mod word size == 1 */ + + if (!BN_set_word(Ri, BN_MASK2)) + goto err; /* Ri-- (mod word size) */ + } + if (!BN_div(Ri, NULL, Ri, &tmod, ctx)) + goto err; + /* + * Ni = (R*Ri-1)/N, keep only least significant word: + */ + mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0; + mont->n0[1] = 0; +# endif + } +#else /* !MONT_WORD */ + { /* bignum version */ + mont->ri = BN_num_bits(&mont->N); + BN_zero(R); + if (!BN_set_bit(R, mont->ri)) + goto err; /* R = 2^ri */ + /* Ri = R^-1 mod N */ + if ((BN_mod_inverse(Ri, R, &mont->N, ctx)) == NULL) + goto err; + if (!BN_lshift(Ri, Ri, mont->ri)) + goto err; /* R*Ri */ + if (!BN_sub_word(Ri, 1)) + goto err; + /* + * Ni = (R*Ri-1) / N + */ + if (!BN_div(&(mont->Ni), NULL, Ri, &mont->N, ctx)) + goto err; + } +#endif + + /* setup RR for conversions */ + BN_zero(&(mont->RR)); + if (!BN_set_bit(&(mont->RR), mont->ri * 2)) + goto err; + if (!BN_mod(&(mont->RR), &(mont->RR), &(mont->N), ctx)) + goto err; + + for (i = mont->RR.top, ret = mont->N.top; i < ret; i++) + mont->RR.d[i] = 0; + mont->RR.top = ret; + mont->RR.flags |= BN_FLG_FIXED_TOP; + + ret = 1; + err: + BN_CTX_end(ctx); + return ret; +} + +BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, BN_MONT_CTX *from) +{ + if (to == from) + return to; + + if (!BN_copy(&(to->RR), &(from->RR))) + return NULL; + if (!BN_copy(&(to->N), &(from->N))) + return NULL; + if (!BN_copy(&(to->Ni), &(from->Ni))) + return NULL; + to->ri = from->ri; + to->n0[0] = from->n0[0]; + to->n0[1] = from->n0[1]; + return to; +} + +BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_RWLOCK *lock, + const BIGNUM *mod, BN_CTX *ctx) +{ + BN_MONT_CTX *ret; + + CRYPTO_THREAD_read_lock(lock); + ret = *pmont; + CRYPTO_THREAD_unlock(lock); + if (ret) + return ret; + + /* + * We don't want to serialise globally while doing our lazy-init math in + * BN_MONT_CTX_set. That punishes threads that are doing independent + * things. Instead, punish the case where more than one thread tries to + * lazy-init the same 'pmont', by having each do the lazy-init math work + * independently and only use the one from the thread that wins the race + * (the losers throw away the work they've done). + */ + ret = BN_MONT_CTX_new(); + if (ret == NULL) + return NULL; + if (!BN_MONT_CTX_set(ret, mod, ctx)) { + BN_MONT_CTX_free(ret); + return NULL; + } + + /* The locked compare-and-set, after the local work is done. */ + CRYPTO_THREAD_write_lock(lock); + if (*pmont) { + BN_MONT_CTX_free(ret); + ret = *pmont; + } else + *pmont = ret; + CRYPTO_THREAD_unlock(lock); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_mpi.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_mpi.c new file mode 100644 index 000000000..043e21d26 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_mpi.c @@ -0,0 +1,86 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include "bn_lcl.h" + +int BN_bn2mpi(const BIGNUM *a, unsigned char *d) +{ + int bits; + int num = 0; + int ext = 0; + long l; + + bits = BN_num_bits(a); + num = (bits + 7) / 8; + if (bits > 0) { + ext = ((bits & 0x07) == 0); + } + if (d == NULL) + return (num + 4 + ext); + + l = num + ext; + d[0] = (unsigned char)(l >> 24) & 0xff; + d[1] = (unsigned char)(l >> 16) & 0xff; + d[2] = (unsigned char)(l >> 8) & 0xff; + d[3] = (unsigned char)(l) & 0xff; + if (ext) + d[4] = 0; + num = BN_bn2bin(a, &(d[4 + ext])); + if (a->neg) + d[4] |= 0x80; + return (num + 4 + ext); +} + +BIGNUM *BN_mpi2bn(const unsigned char *d, int n, BIGNUM *ain) +{ + long len; + int neg = 0; + BIGNUM *a = NULL; + + if (n < 4) { + BNerr(BN_F_BN_MPI2BN, BN_R_INVALID_LENGTH); + return NULL; + } + len = ((long)d[0] << 24) | ((long)d[1] << 16) | ((int)d[2] << 8) | (int) + d[3]; + if ((len + 4) != n) { + BNerr(BN_F_BN_MPI2BN, BN_R_ENCODING_ERROR); + return NULL; + } + + if (ain == NULL) + a = BN_new(); + else + a = ain; + + if (a == NULL) + return NULL; + + if (len == 0) { + a->neg = 0; + a->top = 0; + return a; + } + d += 4; + if ((*d) & 0x80) + neg = 1; + if (BN_bin2bn(d, (int)len, a) == NULL) { + if (ain == NULL) + BN_free(a); + return NULL; + } + a->neg = neg; + if (neg) { + BN_clear_bit(a, BN_num_bits(a) - 1); + } + bn_check_top(a); + return a; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_mul.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_mul.c new file mode 100644 index 000000000..5eda65cfb --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_mul.c @@ -0,0 +1,684 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include "bn_lcl.h" + +#if defined(OPENSSL_NO_ASM) || !defined(OPENSSL_BN_ASM_PART_WORDS) +/* + * Here follows specialised variants of bn_add_words() and bn_sub_words(). + * They have the property performing operations on arrays of different sizes. + * The sizes of those arrays is expressed through cl, which is the common + * length ( basically, min(len(a),len(b)) ), and dl, which is the delta + * between the two lengths, calculated as len(a)-len(b). All lengths are the + * number of BN_ULONGs... For the operations that require a result array as + * parameter, it must have the length cl+abs(dl). These functions should + * probably end up in bn_asm.c as soon as there are assembler counterparts + * for the systems that use assembler files. + */ + +BN_ULONG bn_sub_part_words(BN_ULONG *r, + const BN_ULONG *a, const BN_ULONG *b, + int cl, int dl) +{ + BN_ULONG c, t; + + assert(cl >= 0); + c = bn_sub_words(r, a, b, cl); + + if (dl == 0) + return c; + + r += cl; + a += cl; + b += cl; + + if (dl < 0) { + for (;;) { + t = b[0]; + r[0] = (0 - t - c) & BN_MASK2; + if (t != 0) + c = 1; + if (++dl >= 0) + break; + + t = b[1]; + r[1] = (0 - t - c) & BN_MASK2; + if (t != 0) + c = 1; + if (++dl >= 0) + break; + + t = b[2]; + r[2] = (0 - t - c) & BN_MASK2; + if (t != 0) + c = 1; + if (++dl >= 0) + break; + + t = b[3]; + r[3] = (0 - t - c) & BN_MASK2; + if (t != 0) + c = 1; + if (++dl >= 0) + break; + + b += 4; + r += 4; + } + } else { + int save_dl = dl; + while (c) { + t = a[0]; + r[0] = (t - c) & BN_MASK2; + if (t != 0) + c = 0; + if (--dl <= 0) + break; + + t = a[1]; + r[1] = (t - c) & BN_MASK2; + if (t != 0) + c = 0; + if (--dl <= 0) + break; + + t = a[2]; + r[2] = (t - c) & BN_MASK2; + if (t != 0) + c = 0; + if (--dl <= 0) + break; + + t = a[3]; + r[3] = (t - c) & BN_MASK2; + if (t != 0) + c = 0; + if (--dl <= 0) + break; + + save_dl = dl; + a += 4; + r += 4; + } + if (dl > 0) { + if (save_dl > dl) { + switch (save_dl - dl) { + case 1: + r[1] = a[1]; + if (--dl <= 0) + break; + /* fall thru */ + case 2: + r[2] = a[2]; + if (--dl <= 0) + break; + /* fall thru */ + case 3: + r[3] = a[3]; + if (--dl <= 0) + break; + } + a += 4; + r += 4; + } + } + if (dl > 0) { + for (;;) { + r[0] = a[0]; + if (--dl <= 0) + break; + r[1] = a[1]; + if (--dl <= 0) + break; + r[2] = a[2]; + if (--dl <= 0) + break; + r[3] = a[3]; + if (--dl <= 0) + break; + + a += 4; + r += 4; + } + } + } + return c; +} +#endif + +#ifdef BN_RECURSION +/* + * Karatsuba recursive multiplication algorithm (cf. Knuth, The Art of + * Computer Programming, Vol. 2) + */ + +/*- + * r is 2*n2 words in size, + * a and b are both n2 words in size. + * n2 must be a power of 2. + * We multiply and return the result. + * t must be 2*n2 words in size + * We calculate + * a[0]*b[0] + * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0]) + * a[1]*b[1] + */ +/* dnX may not be positive, but n2/2+dnX has to be */ +void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2, + int dna, int dnb, BN_ULONG *t) +{ + int n = n2 / 2, c1, c2; + int tna = n + dna, tnb = n + dnb; + unsigned int neg, zero; + BN_ULONG ln, lo, *p; + +# ifdef BN_MUL_COMBA +# if 0 + if (n2 == 4) { + bn_mul_comba4(r, a, b); + return; + } +# endif + /* + * Only call bn_mul_comba 8 if n2 == 8 and the two arrays are complete + * [steve] + */ + if (n2 == 8 && dna == 0 && dnb == 0) { + bn_mul_comba8(r, a, b); + return; + } +# endif /* BN_MUL_COMBA */ + /* Else do normal multiply */ + if (n2 < BN_MUL_RECURSIVE_SIZE_NORMAL) { + bn_mul_normal(r, a, n2 + dna, b, n2 + dnb); + if ((dna + dnb) < 0) + memset(&r[2 * n2 + dna + dnb], 0, + sizeof(BN_ULONG) * -(dna + dnb)); + return; + } + /* r=(a[0]-a[1])*(b[1]-b[0]) */ + c1 = bn_cmp_part_words(a, &(a[n]), tna, n - tna); + c2 = bn_cmp_part_words(&(b[n]), b, tnb, tnb - n); + zero = neg = 0; + switch (c1 * 3 + c2) { + case -4: + bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */ + bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */ + break; + case -3: + zero = 1; + break; + case -2: + bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */ + bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); /* + */ + neg = 1; + break; + case -1: + case 0: + case 1: + zero = 1; + break; + case 2: + bn_sub_part_words(t, a, &(a[n]), tna, n - tna); /* + */ + bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */ + neg = 1; + break; + case 3: + zero = 1; + break; + case 4: + bn_sub_part_words(t, a, &(a[n]), tna, n - tna); + bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); + break; + } + +# ifdef BN_MUL_COMBA + if (n == 4 && dna == 0 && dnb == 0) { /* XXX: bn_mul_comba4 could take + * extra args to do this well */ + if (!zero) + bn_mul_comba4(&(t[n2]), t, &(t[n])); + else + memset(&t[n2], 0, sizeof(*t) * 8); + + bn_mul_comba4(r, a, b); + bn_mul_comba4(&(r[n2]), &(a[n]), &(b[n])); + } else if (n == 8 && dna == 0 && dnb == 0) { /* XXX: bn_mul_comba8 could + * take extra args to do + * this well */ + if (!zero) + bn_mul_comba8(&(t[n2]), t, &(t[n])); + else + memset(&t[n2], 0, sizeof(*t) * 16); + + bn_mul_comba8(r, a, b); + bn_mul_comba8(&(r[n2]), &(a[n]), &(b[n])); + } else +# endif /* BN_MUL_COMBA */ + { + p = &(t[n2 * 2]); + if (!zero) + bn_mul_recursive(&(t[n2]), t, &(t[n]), n, 0, 0, p); + else + memset(&t[n2], 0, sizeof(*t) * n2); + bn_mul_recursive(r, a, b, n, 0, 0, p); + bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]), n, dna, dnb, p); + } + + /*- + * t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + */ + + c1 = (int)(bn_add_words(t, r, &(r[n2]), n2)); + + if (neg) { /* if t[32] is negative */ + c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2)); + } else { + /* Might have a carry */ + c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), t, n2)); + } + + /*- + * t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1]) + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + * c1 holds the carry bits + */ + c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2)); + if (c1) { + p = &(r[n + n2]); + lo = *p; + ln = (lo + c1) & BN_MASK2; + *p = ln; + + /* + * The overflow will stop before we over write words we should not + * overwrite + */ + if (ln < (BN_ULONG)c1) { + do { + p++; + lo = *p; + ln = (lo + 1) & BN_MASK2; + *p = ln; + } while (ln == 0); + } + } +} + +/* + * n+tn is the word length t needs to be n*4 is size, as does r + */ +/* tnX may not be negative but less than n */ +void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n, + int tna, int tnb, BN_ULONG *t) +{ + int i, j, n2 = n * 2; + int c1, c2, neg; + BN_ULONG ln, lo, *p; + + if (n < 8) { + bn_mul_normal(r, a, n + tna, b, n + tnb); + return; + } + + /* r=(a[0]-a[1])*(b[1]-b[0]) */ + c1 = bn_cmp_part_words(a, &(a[n]), tna, n - tna); + c2 = bn_cmp_part_words(&(b[n]), b, tnb, tnb - n); + neg = 0; + switch (c1 * 3 + c2) { + case -4: + bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */ + bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */ + break; + case -3: + case -2: + bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */ + bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); /* + */ + neg = 1; + break; + case -1: + case 0: + case 1: + case 2: + bn_sub_part_words(t, a, &(a[n]), tna, n - tna); /* + */ + bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */ + neg = 1; + break; + case 3: + case 4: + bn_sub_part_words(t, a, &(a[n]), tna, n - tna); + bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); + break; + } + /* + * The zero case isn't yet implemented here. The speedup would probably + * be negligible. + */ +# if 0 + if (n == 4) { + bn_mul_comba4(&(t[n2]), t, &(t[n])); + bn_mul_comba4(r, a, b); + bn_mul_normal(&(r[n2]), &(a[n]), tn, &(b[n]), tn); + memset(&r[n2 + tn * 2], 0, sizeof(*r) * (n2 - tn * 2)); + } else +# endif + if (n == 8) { + bn_mul_comba8(&(t[n2]), t, &(t[n])); + bn_mul_comba8(r, a, b); + bn_mul_normal(&(r[n2]), &(a[n]), tna, &(b[n]), tnb); + memset(&r[n2 + tna + tnb], 0, sizeof(*r) * (n2 - tna - tnb)); + } else { + p = &(t[n2 * 2]); + bn_mul_recursive(&(t[n2]), t, &(t[n]), n, 0, 0, p); + bn_mul_recursive(r, a, b, n, 0, 0, p); + i = n / 2; + /* + * If there is only a bottom half to the number, just do it + */ + if (tna > tnb) + j = tna - i; + else + j = tnb - i; + if (j == 0) { + bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]), + i, tna - i, tnb - i, p); + memset(&r[n2 + i * 2], 0, sizeof(*r) * (n2 - i * 2)); + } else if (j > 0) { /* eg, n == 16, i == 8 and tn == 11 */ + bn_mul_part_recursive(&(r[n2]), &(a[n]), &(b[n]), + i, tna - i, tnb - i, p); + memset(&(r[n2 + tna + tnb]), 0, + sizeof(BN_ULONG) * (n2 - tna - tnb)); + } else { /* (j < 0) eg, n == 16, i == 8 and tn == 5 */ + + memset(&r[n2], 0, sizeof(*r) * n2); + if (tna < BN_MUL_RECURSIVE_SIZE_NORMAL + && tnb < BN_MUL_RECURSIVE_SIZE_NORMAL) { + bn_mul_normal(&(r[n2]), &(a[n]), tna, &(b[n]), tnb); + } else { + for (;;) { + i /= 2; + /* + * these simplified conditions work exclusively because + * difference between tna and tnb is 1 or 0 + */ + if (i < tna || i < tnb) { + bn_mul_part_recursive(&(r[n2]), + &(a[n]), &(b[n]), + i, tna - i, tnb - i, p); + break; + } else if (i == tna || i == tnb) { + bn_mul_recursive(&(r[n2]), + &(a[n]), &(b[n]), + i, tna - i, tnb - i, p); + break; + } + } + } + } + } + + /*- + * t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + */ + + c1 = (int)(bn_add_words(t, r, &(r[n2]), n2)); + + if (neg) { /* if t[32] is negative */ + c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2)); + } else { + /* Might have a carry */ + c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), t, n2)); + } + + /*- + * t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1]) + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + * c1 holds the carry bits + */ + c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2)); + if (c1) { + p = &(r[n + n2]); + lo = *p; + ln = (lo + c1) & BN_MASK2; + *p = ln; + + /* + * The overflow will stop before we over write words we should not + * overwrite + */ + if (ln < (BN_ULONG)c1) { + do { + p++; + lo = *p; + ln = (lo + 1) & BN_MASK2; + *p = ln; + } while (ln == 0); + } + } +} + +/*- + * a and b must be the same size, which is n2. + * r needs to be n2 words and t needs to be n2*2 + */ +void bn_mul_low_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2, + BN_ULONG *t) +{ + int n = n2 / 2; + + bn_mul_recursive(r, a, b, n, 0, 0, &(t[0])); + if (n >= BN_MUL_LOW_RECURSIVE_SIZE_NORMAL) { + bn_mul_low_recursive(&(t[0]), &(a[0]), &(b[n]), n, &(t[n2])); + bn_add_words(&(r[n]), &(r[n]), &(t[0]), n); + bn_mul_low_recursive(&(t[0]), &(a[n]), &(b[0]), n, &(t[n2])); + bn_add_words(&(r[n]), &(r[n]), &(t[0]), n); + } else { + bn_mul_low_normal(&(t[0]), &(a[0]), &(b[n]), n); + bn_mul_low_normal(&(t[n]), &(a[n]), &(b[0]), n); + bn_add_words(&(r[n]), &(r[n]), &(t[0]), n); + bn_add_words(&(r[n]), &(r[n]), &(t[n]), n); + } +} +#endif /* BN_RECURSION */ + +int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) +{ + int ret = bn_mul_fixed_top(r, a, b, ctx); + + bn_correct_top(r); + bn_check_top(r); + + return ret; +} + +int bn_mul_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) +{ + int ret = 0; + int top, al, bl; + BIGNUM *rr; +#if defined(BN_MUL_COMBA) || defined(BN_RECURSION) + int i; +#endif +#ifdef BN_RECURSION + BIGNUM *t = NULL; + int j = 0, k; +#endif + + bn_check_top(a); + bn_check_top(b); + bn_check_top(r); + + al = a->top; + bl = b->top; + + if ((al == 0) || (bl == 0)) { + BN_zero(r); + return 1; + } + top = al + bl; + + BN_CTX_start(ctx); + if ((r == a) || (r == b)) { + if ((rr = BN_CTX_get(ctx)) == NULL) + goto err; + } else + rr = r; + +#if defined(BN_MUL_COMBA) || defined(BN_RECURSION) + i = al - bl; +#endif +#ifdef BN_MUL_COMBA + if (i == 0) { +# if 0 + if (al == 4) { + if (bn_wexpand(rr, 8) == NULL) + goto err; + rr->top = 8; + bn_mul_comba4(rr->d, a->d, b->d); + goto end; + } +# endif + if (al == 8) { + if (bn_wexpand(rr, 16) == NULL) + goto err; + rr->top = 16; + bn_mul_comba8(rr->d, a->d, b->d); + goto end; + } + } +#endif /* BN_MUL_COMBA */ +#ifdef BN_RECURSION + if ((al >= BN_MULL_SIZE_NORMAL) && (bl >= BN_MULL_SIZE_NORMAL)) { + if (i >= -1 && i <= 1) { + /* + * Find out the power of two lower or equal to the longest of the + * two numbers + */ + if (i >= 0) { + j = BN_num_bits_word((BN_ULONG)al); + } + if (i == -1) { + j = BN_num_bits_word((BN_ULONG)bl); + } + j = 1 << (j - 1); + assert(j <= al || j <= bl); + k = j + j; + t = BN_CTX_get(ctx); + if (t == NULL) + goto err; + if (al > j || bl > j) { + if (bn_wexpand(t, k * 4) == NULL) + goto err; + if (bn_wexpand(rr, k * 4) == NULL) + goto err; + bn_mul_part_recursive(rr->d, a->d, b->d, + j, al - j, bl - j, t->d); + } else { /* al <= j || bl <= j */ + + if (bn_wexpand(t, k * 2) == NULL) + goto err; + if (bn_wexpand(rr, k * 2) == NULL) + goto err; + bn_mul_recursive(rr->d, a->d, b->d, j, al - j, bl - j, t->d); + } + rr->top = top; + goto end; + } + } +#endif /* BN_RECURSION */ + if (bn_wexpand(rr, top) == NULL) + goto err; + rr->top = top; + bn_mul_normal(rr->d, a->d, al, b->d, bl); + +#if defined(BN_MUL_COMBA) || defined(BN_RECURSION) + end: +#endif + rr->neg = a->neg ^ b->neg; + rr->flags |= BN_FLG_FIXED_TOP; + if (r != rr && BN_copy(r, rr) == NULL) + goto err; + + ret = 1; + err: + bn_check_top(r); + BN_CTX_end(ctx); + return ret; +} + +void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb) +{ + BN_ULONG *rr; + + if (na < nb) { + int itmp; + BN_ULONG *ltmp; + + itmp = na; + na = nb; + nb = itmp; + ltmp = a; + a = b; + b = ltmp; + + } + rr = &(r[na]); + if (nb <= 0) { + (void)bn_mul_words(r, a, na, 0); + return; + } else + rr[0] = bn_mul_words(r, a, na, b[0]); + + for (;;) { + if (--nb <= 0) + return; + rr[1] = bn_mul_add_words(&(r[1]), a, na, b[1]); + if (--nb <= 0) + return; + rr[2] = bn_mul_add_words(&(r[2]), a, na, b[2]); + if (--nb <= 0) + return; + rr[3] = bn_mul_add_words(&(r[3]), a, na, b[3]); + if (--nb <= 0) + return; + rr[4] = bn_mul_add_words(&(r[4]), a, na, b[4]); + rr += 4; + r += 4; + b += 4; + } +} + +void bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) +{ + bn_mul_words(r, a, n, b[0]); + + for (;;) { + if (--n <= 0) + return; + bn_mul_add_words(&(r[1]), a, n, b[1]); + if (--n <= 0) + return; + bn_mul_add_words(&(r[2]), a, n, b[2]); + if (--n <= 0) + return; + bn_mul_add_words(&(r[3]), a, n, b[3]); + if (--n <= 0) + return; + bn_mul_add_words(&(r[4]), a, n, b[4]); + r += 4; + b += 4; + } +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_nist.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_nist.c new file mode 100644 index 000000000..dcdd321c6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_nist.c @@ -0,0 +1,1239 @@ +/* + * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "bn_lcl.h" +#include "internal/cryptlib.h" + +#define BN_NIST_192_TOP (192+BN_BITS2-1)/BN_BITS2 +#define BN_NIST_224_TOP (224+BN_BITS2-1)/BN_BITS2 +#define BN_NIST_256_TOP (256+BN_BITS2-1)/BN_BITS2 +#define BN_NIST_384_TOP (384+BN_BITS2-1)/BN_BITS2 +#define BN_NIST_521_TOP (521+BN_BITS2-1)/BN_BITS2 + +/* pre-computed tables are "carry-less" values of modulus*(i+1) */ +#if BN_BITS2 == 64 +static const BN_ULONG _nist_p_192[][BN_NIST_192_TOP] = { + {0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFEULL, 0xFFFFFFFFFFFFFFFFULL}, + {0xFFFFFFFFFFFFFFFEULL, 0xFFFFFFFFFFFFFFFDULL, 0xFFFFFFFFFFFFFFFFULL}, + {0xFFFFFFFFFFFFFFFDULL, 0xFFFFFFFFFFFFFFFCULL, 0xFFFFFFFFFFFFFFFFULL} +}; + +static const BN_ULONG _nist_p_192_sqr[] = { + 0x0000000000000001ULL, 0x0000000000000002ULL, 0x0000000000000001ULL, + 0xFFFFFFFFFFFFFFFEULL, 0xFFFFFFFFFFFFFFFDULL, 0xFFFFFFFFFFFFFFFFULL +}; + +static const BN_ULONG _nist_p_224[][BN_NIST_224_TOP] = { + {0x0000000000000001ULL, 0xFFFFFFFF00000000ULL, + 0xFFFFFFFFFFFFFFFFULL, 0x00000000FFFFFFFFULL}, + {0x0000000000000002ULL, 0xFFFFFFFE00000000ULL, + 0xFFFFFFFFFFFFFFFFULL, 0x00000001FFFFFFFFULL} /* this one is + * "carry-full" */ +}; + +static const BN_ULONG _nist_p_224_sqr[] = { + 0x0000000000000001ULL, 0xFFFFFFFE00000000ULL, + 0xFFFFFFFFFFFFFFFFULL, 0x0000000200000000ULL, + 0x0000000000000000ULL, 0xFFFFFFFFFFFFFFFEULL, + 0xFFFFFFFFFFFFFFFFULL +}; + +static const BN_ULONG _nist_p_256[][BN_NIST_256_TOP] = { + {0xFFFFFFFFFFFFFFFFULL, 0x00000000FFFFFFFFULL, + 0x0000000000000000ULL, 0xFFFFFFFF00000001ULL}, + {0xFFFFFFFFFFFFFFFEULL, 0x00000001FFFFFFFFULL, + 0x0000000000000000ULL, 0xFFFFFFFE00000002ULL}, + {0xFFFFFFFFFFFFFFFDULL, 0x00000002FFFFFFFFULL, + 0x0000000000000000ULL, 0xFFFFFFFD00000003ULL}, + {0xFFFFFFFFFFFFFFFCULL, 0x00000003FFFFFFFFULL, + 0x0000000000000000ULL, 0xFFFFFFFC00000004ULL}, + {0xFFFFFFFFFFFFFFFBULL, 0x00000004FFFFFFFFULL, + 0x0000000000000000ULL, 0xFFFFFFFB00000005ULL}, +}; + +static const BN_ULONG _nist_p_256_sqr[] = { + 0x0000000000000001ULL, 0xFFFFFFFE00000000ULL, + 0xFFFFFFFFFFFFFFFFULL, 0x00000001FFFFFFFEULL, + 0x00000001FFFFFFFEULL, 0x00000001FFFFFFFEULL, + 0xFFFFFFFE00000001ULL, 0xFFFFFFFE00000002ULL +}; + +static const BN_ULONG _nist_p_384[][BN_NIST_384_TOP] = { + {0x00000000FFFFFFFFULL, 0xFFFFFFFF00000000ULL, 0xFFFFFFFFFFFFFFFEULL, + 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL}, + {0x00000001FFFFFFFEULL, 0xFFFFFFFE00000000ULL, 0xFFFFFFFFFFFFFFFDULL, + 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL}, + {0x00000002FFFFFFFDULL, 0xFFFFFFFD00000000ULL, 0xFFFFFFFFFFFFFFFCULL, + 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL}, + {0x00000003FFFFFFFCULL, 0xFFFFFFFC00000000ULL, 0xFFFFFFFFFFFFFFFBULL, + 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL}, + {0x00000004FFFFFFFBULL, 0xFFFFFFFB00000000ULL, 0xFFFFFFFFFFFFFFFAULL, + 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL}, +}; + +static const BN_ULONG _nist_p_384_sqr[] = { + 0xFFFFFFFE00000001ULL, 0x0000000200000000ULL, 0xFFFFFFFE00000000ULL, + 0x0000000200000000ULL, 0x0000000000000001ULL, 0x0000000000000000ULL, + 0x00000001FFFFFFFEULL, 0xFFFFFFFE00000000ULL, 0xFFFFFFFFFFFFFFFDULL, + 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL +}; + +static const BN_ULONG _nist_p_521[] = + { 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, + 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, + 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, + 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, + 0x00000000000001FFULL +}; + +static const BN_ULONG _nist_p_521_sqr[] = { + 0x0000000000000001ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, + 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, + 0x0000000000000000ULL, 0x0000000000000000ULL, 0xFFFFFFFFFFFFFC00ULL, + 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, + 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, + 0xFFFFFFFFFFFFFFFFULL, 0x000000000003FFFFULL +}; +#elif BN_BITS2 == 32 +static const BN_ULONG _nist_p_192[][BN_NIST_192_TOP] = { + {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, + {0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, + {0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF} +}; + +static const BN_ULONG _nist_p_192_sqr[] = { + 0x00000001, 0x00000000, 0x00000002, 0x00000000, 0x00000001, 0x00000000, + 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF +}; + +static const BN_ULONG _nist_p_224[][BN_NIST_224_TOP] = { + {0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, + {0x00000002, 0x00000000, 0x00000000, 0xFFFFFFFE, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF} +}; + +static const BN_ULONG _nist_p_224_sqr[] = { + 0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFE, + 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000002, + 0x00000000, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF +}; + +static const BN_ULONG _nist_p_256[][BN_NIST_256_TOP] = { + {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, + 0x00000000, 0x00000000, 0x00000001, 0xFFFFFFFF}, + {0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000001, + 0x00000000, 0x00000000, 0x00000002, 0xFFFFFFFE}, + {0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000002, + 0x00000000, 0x00000000, 0x00000003, 0xFFFFFFFD}, + {0xFFFFFFFC, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000003, + 0x00000000, 0x00000000, 0x00000004, 0xFFFFFFFC}, + {0xFFFFFFFB, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000004, + 0x00000000, 0x00000000, 0x00000005, 0xFFFFFFFB}, +}; + +static const BN_ULONG _nist_p_256_sqr[] = { + 0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFE, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0x00000001, + 0xFFFFFFFE, 0x00000001, 0xFFFFFFFE, 0x00000001, + 0x00000001, 0xFFFFFFFE, 0x00000002, 0xFFFFFFFE +}; + +static const BN_ULONG _nist_p_384[][BN_NIST_384_TOP] = { + {0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, + {0xFFFFFFFE, 0x00000001, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFD, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, + {0xFFFFFFFD, 0x00000002, 0x00000000, 0xFFFFFFFD, 0xFFFFFFFC, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, + {0xFFFFFFFC, 0x00000003, 0x00000000, 0xFFFFFFFC, 0xFFFFFFFB, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, + {0xFFFFFFFB, 0x00000004, 0x00000000, 0xFFFFFFFB, 0xFFFFFFFA, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, +}; + +static const BN_ULONG _nist_p_384_sqr[] = { + 0x00000001, 0xFFFFFFFE, 0x00000000, 0x00000002, 0x00000000, 0xFFFFFFFE, + 0x00000000, 0x00000002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, + 0xFFFFFFFE, 0x00000001, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFD, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF +}; + +static const BN_ULONG _nist_p_521[] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0x000001FF +}; + +static const BN_ULONG _nist_p_521_sqr[] = { + 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFC00, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0x0003FFFF +}; +#else +# error "unsupported BN_BITS2" +#endif + +static const BIGNUM _bignum_nist_p_192 = { + (BN_ULONG *)_nist_p_192[0], + BN_NIST_192_TOP, + BN_NIST_192_TOP, + 0, + BN_FLG_STATIC_DATA +}; + +static const BIGNUM _bignum_nist_p_224 = { + (BN_ULONG *)_nist_p_224[0], + BN_NIST_224_TOP, + BN_NIST_224_TOP, + 0, + BN_FLG_STATIC_DATA +}; + +static const BIGNUM _bignum_nist_p_256 = { + (BN_ULONG *)_nist_p_256[0], + BN_NIST_256_TOP, + BN_NIST_256_TOP, + 0, + BN_FLG_STATIC_DATA +}; + +static const BIGNUM _bignum_nist_p_384 = { + (BN_ULONG *)_nist_p_384[0], + BN_NIST_384_TOP, + BN_NIST_384_TOP, + 0, + BN_FLG_STATIC_DATA +}; + +static const BIGNUM _bignum_nist_p_521 = { + (BN_ULONG *)_nist_p_521, + BN_NIST_521_TOP, + BN_NIST_521_TOP, + 0, + BN_FLG_STATIC_DATA +}; + +const BIGNUM *BN_get0_nist_prime_192(void) +{ + return &_bignum_nist_p_192; +} + +const BIGNUM *BN_get0_nist_prime_224(void) +{ + return &_bignum_nist_p_224; +} + +const BIGNUM *BN_get0_nist_prime_256(void) +{ + return &_bignum_nist_p_256; +} + +const BIGNUM *BN_get0_nist_prime_384(void) +{ + return &_bignum_nist_p_384; +} + +const BIGNUM *BN_get0_nist_prime_521(void) +{ + return &_bignum_nist_p_521; +} + +static void nist_cp_bn_0(BN_ULONG *dst, const BN_ULONG *src, int top, int max) +{ + int i; + +#ifdef BN_DEBUG + (void)ossl_assert(top <= max); +#endif + for (i = 0; i < top; i++) + dst[i] = src[i]; + for (; i < max; i++) + dst[i] = 0; +} + +static void nist_cp_bn(BN_ULONG *dst, const BN_ULONG *src, int top) +{ + int i; + + for (i = 0; i < top; i++) + dst[i] = src[i]; +} + +#if BN_BITS2 == 64 +# define bn_cp_64(to, n, from, m) (to)[n] = (m>=0)?((from)[m]):0; +# define bn_64_set_0(to, n) (to)[n] = (BN_ULONG)0; +/* + * two following macros are implemented under assumption that they + * are called in a sequence with *ascending* n, i.e. as they are... + */ +# define bn_cp_32_naked(to, n, from, m) (((n)&1)?(to[(n)/2]|=((m)&1)?(from[(m)/2]&BN_MASK2h):(from[(m)/2]<<32))\ + :(to[(n)/2] =((m)&1)?(from[(m)/2]>>32):(from[(m)/2]&BN_MASK2l))) +# define bn_32_set_0(to, n) (((n)&1)?(to[(n)/2]&=BN_MASK2l):(to[(n)/2]=0)); +# define bn_cp_32(to,n,from,m) ((m)>=0)?bn_cp_32_naked(to,n,from,m):bn_32_set_0(to,n) +# if defined(L_ENDIAN) +# if defined(__arch64__) +# define NIST_INT64 long +# else +# define NIST_INT64 long long +# endif +# endif +#else +# define bn_cp_64(to, n, from, m) \ + { \ + bn_cp_32(to, (n)*2, from, (m)*2); \ + bn_cp_32(to, (n)*2+1, from, (m)*2+1); \ + } +# define bn_64_set_0(to, n) \ + { \ + bn_32_set_0(to, (n)*2); \ + bn_32_set_0(to, (n)*2+1); \ + } +# define bn_cp_32(to, n, from, m) (to)[n] = (m>=0)?((from)[m]):0; +# define bn_32_set_0(to, n) (to)[n] = (BN_ULONG)0; +# if defined(_WIN32) && !defined(__GNUC__) +# define NIST_INT64 __int64 +# elif defined(BN_LLONG) +# define NIST_INT64 long long +# endif +#endif /* BN_BITS2 != 64 */ + +#define nist_set_192(to, from, a1, a2, a3) \ + { \ + bn_cp_64(to, 0, from, (a3) - 3) \ + bn_cp_64(to, 1, from, (a2) - 3) \ + bn_cp_64(to, 2, from, (a1) - 3) \ + } + +int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, + BN_CTX *ctx) +{ + int top = a->top, i; + int carry; + register BN_ULONG *r_d, *a_d = a->d; + union { + BN_ULONG bn[BN_NIST_192_TOP]; + unsigned int ui[BN_NIST_192_TOP * sizeof(BN_ULONG) / + sizeof(unsigned int)]; + } buf; + BN_ULONG c_d[BN_NIST_192_TOP], *res; + PTR_SIZE_INT mask; + static const BIGNUM _bignum_nist_p_192_sqr = { + (BN_ULONG *)_nist_p_192_sqr, + OSSL_NELEM(_nist_p_192_sqr), + OSSL_NELEM(_nist_p_192_sqr), + 0, BN_FLG_STATIC_DATA + }; + + field = &_bignum_nist_p_192; /* just to make sure */ + + if (BN_is_negative(a) || BN_ucmp(a, &_bignum_nist_p_192_sqr) >= 0) + return BN_nnmod(r, a, field, ctx); + + i = BN_ucmp(field, a); + if (i == 0) { + BN_zero(r); + return 1; + } else if (i > 0) + return (r == a) ? 1 : (BN_copy(r, a) != NULL); + + if (r != a) { + if (!bn_wexpand(r, BN_NIST_192_TOP)) + return 0; + r_d = r->d; + nist_cp_bn(r_d, a_d, BN_NIST_192_TOP); + } else + r_d = a_d; + + nist_cp_bn_0(buf.bn, a_d + BN_NIST_192_TOP, top - BN_NIST_192_TOP, + BN_NIST_192_TOP); + +#if defined(NIST_INT64) + { + NIST_INT64 acc; /* accumulator */ + unsigned int *rp = (unsigned int *)r_d; + const unsigned int *bp = (const unsigned int *)buf.ui; + + acc = rp[0]; + acc += bp[3 * 2 - 6]; + acc += bp[5 * 2 - 6]; + rp[0] = (unsigned int)acc; + acc >>= 32; + + acc += rp[1]; + acc += bp[3 * 2 - 5]; + acc += bp[5 * 2 - 5]; + rp[1] = (unsigned int)acc; + acc >>= 32; + + acc += rp[2]; + acc += bp[3 * 2 - 6]; + acc += bp[4 * 2 - 6]; + acc += bp[5 * 2 - 6]; + rp[2] = (unsigned int)acc; + acc >>= 32; + + acc += rp[3]; + acc += bp[3 * 2 - 5]; + acc += bp[4 * 2 - 5]; + acc += bp[5 * 2 - 5]; + rp[3] = (unsigned int)acc; + acc >>= 32; + + acc += rp[4]; + acc += bp[4 * 2 - 6]; + acc += bp[5 * 2 - 6]; + rp[4] = (unsigned int)acc; + acc >>= 32; + + acc += rp[5]; + acc += bp[4 * 2 - 5]; + acc += bp[5 * 2 - 5]; + rp[5] = (unsigned int)acc; + + carry = (int)(acc >> 32); + } +#else + { + BN_ULONG t_d[BN_NIST_192_TOP]; + + nist_set_192(t_d, buf.bn, 0, 3, 3); + carry = (int)bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP); + nist_set_192(t_d, buf.bn, 4, 4, 0); + carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP); + nist_set_192(t_d, buf.bn, 5, 5, 5) + carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP); + } +#endif + if (carry > 0) + carry = + (int)bn_sub_words(r_d, r_d, _nist_p_192[carry - 1], + BN_NIST_192_TOP); + else + carry = 1; + + /* + * we need 'if (carry==0 || result>=modulus) result-=modulus;' + * as comparison implies subtraction, we can write + * 'tmp=result-modulus; if (!carry || !borrow) result=tmp;' + * this is what happens below, but without explicit if:-) a. + */ + mask = + 0 - (PTR_SIZE_INT) bn_sub_words(c_d, r_d, _nist_p_192[0], + BN_NIST_192_TOP); + mask &= 0 - (PTR_SIZE_INT) carry; + res = c_d; + res = (BN_ULONG *) + (((PTR_SIZE_INT) res & ~mask) | ((PTR_SIZE_INT) r_d & mask)); + nist_cp_bn(r_d, res, BN_NIST_192_TOP); + r->top = BN_NIST_192_TOP; + bn_correct_top(r); + + return 1; +} + +typedef BN_ULONG (*bn_addsub_f) (BN_ULONG *, const BN_ULONG *, + const BN_ULONG *, int); + +#define nist_set_224(to, from, a1, a2, a3, a4, a5, a6, a7) \ + { \ + bn_cp_32(to, 0, from, (a7) - 7) \ + bn_cp_32(to, 1, from, (a6) - 7) \ + bn_cp_32(to, 2, from, (a5) - 7) \ + bn_cp_32(to, 3, from, (a4) - 7) \ + bn_cp_32(to, 4, from, (a3) - 7) \ + bn_cp_32(to, 5, from, (a2) - 7) \ + bn_cp_32(to, 6, from, (a1) - 7) \ + } + +int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, + BN_CTX *ctx) +{ + int top = a->top, i; + int carry; + BN_ULONG *r_d, *a_d = a->d; + union { + BN_ULONG bn[BN_NIST_224_TOP]; + unsigned int ui[BN_NIST_224_TOP * sizeof(BN_ULONG) / + sizeof(unsigned int)]; + } buf; + BN_ULONG c_d[BN_NIST_224_TOP], *res; + PTR_SIZE_INT mask; + union { + bn_addsub_f f; + PTR_SIZE_INT p; + } u; + static const BIGNUM _bignum_nist_p_224_sqr = { + (BN_ULONG *)_nist_p_224_sqr, + OSSL_NELEM(_nist_p_224_sqr), + OSSL_NELEM(_nist_p_224_sqr), + 0, BN_FLG_STATIC_DATA + }; + + field = &_bignum_nist_p_224; /* just to make sure */ + + if (BN_is_negative(a) || BN_ucmp(a, &_bignum_nist_p_224_sqr) >= 0) + return BN_nnmod(r, a, field, ctx); + + i = BN_ucmp(field, a); + if (i == 0) { + BN_zero(r); + return 1; + } else if (i > 0) + return (r == a) ? 1 : (BN_copy(r, a) != NULL); + + if (r != a) { + if (!bn_wexpand(r, BN_NIST_224_TOP)) + return 0; + r_d = r->d; + nist_cp_bn(r_d, a_d, BN_NIST_224_TOP); + } else + r_d = a_d; + +#if BN_BITS2==64 + /* copy upper 256 bits of 448 bit number ... */ + nist_cp_bn_0(c_d, a_d + (BN_NIST_224_TOP - 1), + top - (BN_NIST_224_TOP - 1), BN_NIST_224_TOP); + /* ... and right shift by 32 to obtain upper 224 bits */ + nist_set_224(buf.bn, c_d, 14, 13, 12, 11, 10, 9, 8); + /* truncate lower part to 224 bits too */ + r_d[BN_NIST_224_TOP - 1] &= BN_MASK2l; +#else + nist_cp_bn_0(buf.bn, a_d + BN_NIST_224_TOP, top - BN_NIST_224_TOP, + BN_NIST_224_TOP); +#endif + +#if defined(NIST_INT64) && BN_BITS2!=64 + { + NIST_INT64 acc; /* accumulator */ + unsigned int *rp = (unsigned int *)r_d; + const unsigned int *bp = (const unsigned int *)buf.ui; + + acc = rp[0]; + acc -= bp[7 - 7]; + acc -= bp[11 - 7]; + rp[0] = (unsigned int)acc; + acc >>= 32; + + acc += rp[1]; + acc -= bp[8 - 7]; + acc -= bp[12 - 7]; + rp[1] = (unsigned int)acc; + acc >>= 32; + + acc += rp[2]; + acc -= bp[9 - 7]; + acc -= bp[13 - 7]; + rp[2] = (unsigned int)acc; + acc >>= 32; + + acc += rp[3]; + acc += bp[7 - 7]; + acc += bp[11 - 7]; + acc -= bp[10 - 7]; + rp[3] = (unsigned int)acc; + acc >>= 32; + + acc += rp[4]; + acc += bp[8 - 7]; + acc += bp[12 - 7]; + acc -= bp[11 - 7]; + rp[4] = (unsigned int)acc; + acc >>= 32; + + acc += rp[5]; + acc += bp[9 - 7]; + acc += bp[13 - 7]; + acc -= bp[12 - 7]; + rp[5] = (unsigned int)acc; + acc >>= 32; + + acc += rp[6]; + acc += bp[10 - 7]; + acc -= bp[13 - 7]; + rp[6] = (unsigned int)acc; + + carry = (int)(acc >> 32); +# if BN_BITS2==64 + rp[7] = carry; +# endif + } +#else + { + BN_ULONG t_d[BN_NIST_224_TOP]; + + nist_set_224(t_d, buf.bn, 10, 9, 8, 7, 0, 0, 0); + carry = (int)bn_add_words(r_d, r_d, t_d, BN_NIST_224_TOP); + nist_set_224(t_d, buf.bn, 0, 13, 12, 11, 0, 0, 0); + carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_224_TOP); + nist_set_224(t_d, buf.bn, 13, 12, 11, 10, 9, 8, 7); + carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_224_TOP); + nist_set_224(t_d, buf.bn, 0, 0, 0, 0, 13, 12, 11); + carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_224_TOP); + +# if BN_BITS2==64 + carry = (int)(r_d[BN_NIST_224_TOP - 1] >> 32); +# endif + } +#endif + u.f = bn_sub_words; + if (carry > 0) { + carry = + (int)bn_sub_words(r_d, r_d, _nist_p_224[carry - 1], + BN_NIST_224_TOP); +#if BN_BITS2==64 + carry = (int)(~(r_d[BN_NIST_224_TOP - 1] >> 32)) & 1; +#endif + } else if (carry < 0) { + /* + * it's a bit more complicated logic in this case. if bn_add_words + * yields no carry, then result has to be adjusted by unconditionally + * *adding* the modulus. but if it does, then result has to be + * compared to the modulus and conditionally adjusted by + * *subtracting* the latter. + */ + carry = + (int)bn_add_words(r_d, r_d, _nist_p_224[-carry - 1], + BN_NIST_224_TOP); + mask = 0 - (PTR_SIZE_INT) carry; + u.p = ((PTR_SIZE_INT) bn_sub_words & mask) | + ((PTR_SIZE_INT) bn_add_words & ~mask); + } else + carry = 1; + + /* otherwise it's effectively same as in BN_nist_mod_192... */ + mask = + 0 - (PTR_SIZE_INT) (*u.f) (c_d, r_d, _nist_p_224[0], BN_NIST_224_TOP); + mask &= 0 - (PTR_SIZE_INT) carry; + res = c_d; + res = (BN_ULONG *)(((PTR_SIZE_INT) res & ~mask) | + ((PTR_SIZE_INT) r_d & mask)); + nist_cp_bn(r_d, res, BN_NIST_224_TOP); + r->top = BN_NIST_224_TOP; + bn_correct_top(r); + + return 1; +} + +#define nist_set_256(to, from, a1, a2, a3, a4, a5, a6, a7, a8) \ + { \ + bn_cp_32(to, 0, from, (a8) - 8) \ + bn_cp_32(to, 1, from, (a7) - 8) \ + bn_cp_32(to, 2, from, (a6) - 8) \ + bn_cp_32(to, 3, from, (a5) - 8) \ + bn_cp_32(to, 4, from, (a4) - 8) \ + bn_cp_32(to, 5, from, (a3) - 8) \ + bn_cp_32(to, 6, from, (a2) - 8) \ + bn_cp_32(to, 7, from, (a1) - 8) \ + } + +int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, + BN_CTX *ctx) +{ + int i, top = a->top; + int carry = 0; + register BN_ULONG *a_d = a->d, *r_d; + union { + BN_ULONG bn[BN_NIST_256_TOP]; + unsigned int ui[BN_NIST_256_TOP * sizeof(BN_ULONG) / + sizeof(unsigned int)]; + } buf; + BN_ULONG c_d[BN_NIST_256_TOP], *res; + PTR_SIZE_INT mask; + union { + bn_addsub_f f; + PTR_SIZE_INT p; + } u; + static const BIGNUM _bignum_nist_p_256_sqr = { + (BN_ULONG *)_nist_p_256_sqr, + OSSL_NELEM(_nist_p_256_sqr), + OSSL_NELEM(_nist_p_256_sqr), + 0, BN_FLG_STATIC_DATA + }; + + field = &_bignum_nist_p_256; /* just to make sure */ + + if (BN_is_negative(a) || BN_ucmp(a, &_bignum_nist_p_256_sqr) >= 0) + return BN_nnmod(r, a, field, ctx); + + i = BN_ucmp(field, a); + if (i == 0) { + BN_zero(r); + return 1; + } else if (i > 0) + return (r == a) ? 1 : (BN_copy(r, a) != NULL); + + if (r != a) { + if (!bn_wexpand(r, BN_NIST_256_TOP)) + return 0; + r_d = r->d; + nist_cp_bn(r_d, a_d, BN_NIST_256_TOP); + } else + r_d = a_d; + + nist_cp_bn_0(buf.bn, a_d + BN_NIST_256_TOP, top - BN_NIST_256_TOP, + BN_NIST_256_TOP); + +#if defined(NIST_INT64) + { + NIST_INT64 acc; /* accumulator */ + unsigned int *rp = (unsigned int *)r_d; + const unsigned int *bp = (const unsigned int *)buf.ui; + + acc = rp[0]; + acc += bp[8 - 8]; + acc += bp[9 - 8]; + acc -= bp[11 - 8]; + acc -= bp[12 - 8]; + acc -= bp[13 - 8]; + acc -= bp[14 - 8]; + rp[0] = (unsigned int)acc; + acc >>= 32; + + acc += rp[1]; + acc += bp[9 - 8]; + acc += bp[10 - 8]; + acc -= bp[12 - 8]; + acc -= bp[13 - 8]; + acc -= bp[14 - 8]; + acc -= bp[15 - 8]; + rp[1] = (unsigned int)acc; + acc >>= 32; + + acc += rp[2]; + acc += bp[10 - 8]; + acc += bp[11 - 8]; + acc -= bp[13 - 8]; + acc -= bp[14 - 8]; + acc -= bp[15 - 8]; + rp[2] = (unsigned int)acc; + acc >>= 32; + + acc += rp[3]; + acc += bp[11 - 8]; + acc += bp[11 - 8]; + acc += bp[12 - 8]; + acc += bp[12 - 8]; + acc += bp[13 - 8]; + acc -= bp[15 - 8]; + acc -= bp[8 - 8]; + acc -= bp[9 - 8]; + rp[3] = (unsigned int)acc; + acc >>= 32; + + acc += rp[4]; + acc += bp[12 - 8]; + acc += bp[12 - 8]; + acc += bp[13 - 8]; + acc += bp[13 - 8]; + acc += bp[14 - 8]; + acc -= bp[9 - 8]; + acc -= bp[10 - 8]; + rp[4] = (unsigned int)acc; + acc >>= 32; + + acc += rp[5]; + acc += bp[13 - 8]; + acc += bp[13 - 8]; + acc += bp[14 - 8]; + acc += bp[14 - 8]; + acc += bp[15 - 8]; + acc -= bp[10 - 8]; + acc -= bp[11 - 8]; + rp[5] = (unsigned int)acc; + acc >>= 32; + + acc += rp[6]; + acc += bp[14 - 8]; + acc += bp[14 - 8]; + acc += bp[15 - 8]; + acc += bp[15 - 8]; + acc += bp[14 - 8]; + acc += bp[13 - 8]; + acc -= bp[8 - 8]; + acc -= bp[9 - 8]; + rp[6] = (unsigned int)acc; + acc >>= 32; + + acc += rp[7]; + acc += bp[15 - 8]; + acc += bp[15 - 8]; + acc += bp[15 - 8]; + acc += bp[8 - 8]; + acc -= bp[10 - 8]; + acc -= bp[11 - 8]; + acc -= bp[12 - 8]; + acc -= bp[13 - 8]; + rp[7] = (unsigned int)acc; + + carry = (int)(acc >> 32); + } +#else + { + BN_ULONG t_d[BN_NIST_256_TOP]; + + /* + * S1 + */ + nist_set_256(t_d, buf.bn, 15, 14, 13, 12, 11, 0, 0, 0); + /* + * S2 + */ + nist_set_256(c_d, buf.bn, 0, 15, 14, 13, 12, 0, 0, 0); + carry = (int)bn_add_words(t_d, t_d, c_d, BN_NIST_256_TOP); + /* left shift */ + { + register BN_ULONG *ap, t, c; + ap = t_d; + c = 0; + for (i = BN_NIST_256_TOP; i != 0; --i) { + t = *ap; + *(ap++) = ((t << 1) | c) & BN_MASK2; + c = (t & BN_TBIT) ? 1 : 0; + } + carry <<= 1; + carry |= c; + } + carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP); + /* + * S3 + */ + nist_set_256(t_d, buf.bn, 15, 14, 0, 0, 0, 10, 9, 8); + carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP); + /* + * S4 + */ + nist_set_256(t_d, buf.bn, 8, 13, 15, 14, 13, 11, 10, 9); + carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP); + /* + * D1 + */ + nist_set_256(t_d, buf.bn, 10, 8, 0, 0, 0, 13, 12, 11); + carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP); + /* + * D2 + */ + nist_set_256(t_d, buf.bn, 11, 9, 0, 0, 15, 14, 13, 12); + carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP); + /* + * D3 + */ + nist_set_256(t_d, buf.bn, 12, 0, 10, 9, 8, 15, 14, 13); + carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP); + /* + * D4 + */ + nist_set_256(t_d, buf.bn, 13, 0, 11, 10, 9, 0, 15, 14); + carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP); + + } +#endif + /* see BN_nist_mod_224 for explanation */ + u.f = bn_sub_words; + if (carry > 0) + carry = + (int)bn_sub_words(r_d, r_d, _nist_p_256[carry - 1], + BN_NIST_256_TOP); + else if (carry < 0) { + carry = + (int)bn_add_words(r_d, r_d, _nist_p_256[-carry - 1], + BN_NIST_256_TOP); + mask = 0 - (PTR_SIZE_INT) carry; + u.p = ((PTR_SIZE_INT) bn_sub_words & mask) | + ((PTR_SIZE_INT) bn_add_words & ~mask); + } else + carry = 1; + + mask = + 0 - (PTR_SIZE_INT) (*u.f) (c_d, r_d, _nist_p_256[0], BN_NIST_256_TOP); + mask &= 0 - (PTR_SIZE_INT) carry; + res = c_d; + res = (BN_ULONG *)(((PTR_SIZE_INT) res & ~mask) | + ((PTR_SIZE_INT) r_d & mask)); + nist_cp_bn(r_d, res, BN_NIST_256_TOP); + r->top = BN_NIST_256_TOP; + bn_correct_top(r); + + return 1; +} + +#define nist_set_384(to,from,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12) \ + { \ + bn_cp_32(to, 0, from, (a12) - 12) \ + bn_cp_32(to, 1, from, (a11) - 12) \ + bn_cp_32(to, 2, from, (a10) - 12) \ + bn_cp_32(to, 3, from, (a9) - 12) \ + bn_cp_32(to, 4, from, (a8) - 12) \ + bn_cp_32(to, 5, from, (a7) - 12) \ + bn_cp_32(to, 6, from, (a6) - 12) \ + bn_cp_32(to, 7, from, (a5) - 12) \ + bn_cp_32(to, 8, from, (a4) - 12) \ + bn_cp_32(to, 9, from, (a3) - 12) \ + bn_cp_32(to, 10, from, (a2) - 12) \ + bn_cp_32(to, 11, from, (a1) - 12) \ + } + +int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, + BN_CTX *ctx) +{ + int i, top = a->top; + int carry = 0; + register BN_ULONG *r_d, *a_d = a->d; + union { + BN_ULONG bn[BN_NIST_384_TOP]; + unsigned int ui[BN_NIST_384_TOP * sizeof(BN_ULONG) / + sizeof(unsigned int)]; + } buf; + BN_ULONG c_d[BN_NIST_384_TOP], *res; + PTR_SIZE_INT mask; + union { + bn_addsub_f f; + PTR_SIZE_INT p; + } u; + static const BIGNUM _bignum_nist_p_384_sqr = { + (BN_ULONG *)_nist_p_384_sqr, + OSSL_NELEM(_nist_p_384_sqr), + OSSL_NELEM(_nist_p_384_sqr), + 0, BN_FLG_STATIC_DATA + }; + + field = &_bignum_nist_p_384; /* just to make sure */ + + if (BN_is_negative(a) || BN_ucmp(a, &_bignum_nist_p_384_sqr) >= 0) + return BN_nnmod(r, a, field, ctx); + + i = BN_ucmp(field, a); + if (i == 0) { + BN_zero(r); + return 1; + } else if (i > 0) + return (r == a) ? 1 : (BN_copy(r, a) != NULL); + + if (r != a) { + if (!bn_wexpand(r, BN_NIST_384_TOP)) + return 0; + r_d = r->d; + nist_cp_bn(r_d, a_d, BN_NIST_384_TOP); + } else + r_d = a_d; + + nist_cp_bn_0(buf.bn, a_d + BN_NIST_384_TOP, top - BN_NIST_384_TOP, + BN_NIST_384_TOP); + +#if defined(NIST_INT64) + { + NIST_INT64 acc; /* accumulator */ + unsigned int *rp = (unsigned int *)r_d; + const unsigned int *bp = (const unsigned int *)buf.ui; + + acc = rp[0]; + acc += bp[12 - 12]; + acc += bp[21 - 12]; + acc += bp[20 - 12]; + acc -= bp[23 - 12]; + rp[0] = (unsigned int)acc; + acc >>= 32; + + acc += rp[1]; + acc += bp[13 - 12]; + acc += bp[22 - 12]; + acc += bp[23 - 12]; + acc -= bp[12 - 12]; + acc -= bp[20 - 12]; + rp[1] = (unsigned int)acc; + acc >>= 32; + + acc += rp[2]; + acc += bp[14 - 12]; + acc += bp[23 - 12]; + acc -= bp[13 - 12]; + acc -= bp[21 - 12]; + rp[2] = (unsigned int)acc; + acc >>= 32; + + acc += rp[3]; + acc += bp[15 - 12]; + acc += bp[12 - 12]; + acc += bp[20 - 12]; + acc += bp[21 - 12]; + acc -= bp[14 - 12]; + acc -= bp[22 - 12]; + acc -= bp[23 - 12]; + rp[3] = (unsigned int)acc; + acc >>= 32; + + acc += rp[4]; + acc += bp[21 - 12]; + acc += bp[21 - 12]; + acc += bp[16 - 12]; + acc += bp[13 - 12]; + acc += bp[12 - 12]; + acc += bp[20 - 12]; + acc += bp[22 - 12]; + acc -= bp[15 - 12]; + acc -= bp[23 - 12]; + acc -= bp[23 - 12]; + rp[4] = (unsigned int)acc; + acc >>= 32; + + acc += rp[5]; + acc += bp[22 - 12]; + acc += bp[22 - 12]; + acc += bp[17 - 12]; + acc += bp[14 - 12]; + acc += bp[13 - 12]; + acc += bp[21 - 12]; + acc += bp[23 - 12]; + acc -= bp[16 - 12]; + rp[5] = (unsigned int)acc; + acc >>= 32; + + acc += rp[6]; + acc += bp[23 - 12]; + acc += bp[23 - 12]; + acc += bp[18 - 12]; + acc += bp[15 - 12]; + acc += bp[14 - 12]; + acc += bp[22 - 12]; + acc -= bp[17 - 12]; + rp[6] = (unsigned int)acc; + acc >>= 32; + + acc += rp[7]; + acc += bp[19 - 12]; + acc += bp[16 - 12]; + acc += bp[15 - 12]; + acc += bp[23 - 12]; + acc -= bp[18 - 12]; + rp[7] = (unsigned int)acc; + acc >>= 32; + + acc += rp[8]; + acc += bp[20 - 12]; + acc += bp[17 - 12]; + acc += bp[16 - 12]; + acc -= bp[19 - 12]; + rp[8] = (unsigned int)acc; + acc >>= 32; + + acc += rp[9]; + acc += bp[21 - 12]; + acc += bp[18 - 12]; + acc += bp[17 - 12]; + acc -= bp[20 - 12]; + rp[9] = (unsigned int)acc; + acc >>= 32; + + acc += rp[10]; + acc += bp[22 - 12]; + acc += bp[19 - 12]; + acc += bp[18 - 12]; + acc -= bp[21 - 12]; + rp[10] = (unsigned int)acc; + acc >>= 32; + + acc += rp[11]; + acc += bp[23 - 12]; + acc += bp[20 - 12]; + acc += bp[19 - 12]; + acc -= bp[22 - 12]; + rp[11] = (unsigned int)acc; + + carry = (int)(acc >> 32); + } +#else + { + BN_ULONG t_d[BN_NIST_384_TOP]; + + /* + * S1 + */ + nist_set_256(t_d, buf.bn, 0, 0, 0, 0, 0, 23 - 4, 22 - 4, 21 - 4); + /* left shift */ + { + register BN_ULONG *ap, t, c; + ap = t_d; + c = 0; + for (i = 3; i != 0; --i) { + t = *ap; + *(ap++) = ((t << 1) | c) & BN_MASK2; + c = (t & BN_TBIT) ? 1 : 0; + } + *ap = c; + } + carry = + (int)bn_add_words(r_d + (128 / BN_BITS2), r_d + (128 / BN_BITS2), + t_d, BN_NIST_256_TOP); + /* + * S2 + */ + carry += (int)bn_add_words(r_d, r_d, buf.bn, BN_NIST_384_TOP); + /* + * S3 + */ + nist_set_384(t_d, buf.bn, 20, 19, 18, 17, 16, 15, 14, 13, 12, 23, 22, + 21); + carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP); + /* + * S4 + */ + nist_set_384(t_d, buf.bn, 19, 18, 17, 16, 15, 14, 13, 12, 20, 0, 23, + 0); + carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP); + /* + * S5 + */ + nist_set_384(t_d, buf.bn, 0, 0, 0, 0, 23, 22, 21, 20, 0, 0, 0, 0); + carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP); + /* + * S6 + */ + nist_set_384(t_d, buf.bn, 0, 0, 0, 0, 0, 0, 23, 22, 21, 0, 0, 20); + carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP); + /* + * D1 + */ + nist_set_384(t_d, buf.bn, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, + 23); + carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP); + /* + * D2 + */ + nist_set_384(t_d, buf.bn, 0, 0, 0, 0, 0, 0, 0, 23, 22, 21, 20, 0); + carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP); + /* + * D3 + */ + nist_set_384(t_d, buf.bn, 0, 0, 0, 0, 0, 0, 0, 23, 23, 0, 0, 0); + carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP); + + } +#endif + /* see BN_nist_mod_224 for explanation */ + u.f = bn_sub_words; + if (carry > 0) + carry = + (int)bn_sub_words(r_d, r_d, _nist_p_384[carry - 1], + BN_NIST_384_TOP); + else if (carry < 0) { + carry = + (int)bn_add_words(r_d, r_d, _nist_p_384[-carry - 1], + BN_NIST_384_TOP); + mask = 0 - (PTR_SIZE_INT) carry; + u.p = ((PTR_SIZE_INT) bn_sub_words & mask) | + ((PTR_SIZE_INT) bn_add_words & ~mask); + } else + carry = 1; + + mask = + 0 - (PTR_SIZE_INT) (*u.f) (c_d, r_d, _nist_p_384[0], BN_NIST_384_TOP); + mask &= 0 - (PTR_SIZE_INT) carry; + res = c_d; + res = (BN_ULONG *)(((PTR_SIZE_INT) res & ~mask) | + ((PTR_SIZE_INT) r_d & mask)); + nist_cp_bn(r_d, res, BN_NIST_384_TOP); + r->top = BN_NIST_384_TOP; + bn_correct_top(r); + + return 1; +} + +#define BN_NIST_521_RSHIFT (521%BN_BITS2) +#define BN_NIST_521_LSHIFT (BN_BITS2-BN_NIST_521_RSHIFT) +#define BN_NIST_521_TOP_MASK ((BN_ULONG)BN_MASK2>>BN_NIST_521_LSHIFT) + +int BN_nist_mod_521(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, + BN_CTX *ctx) +{ + int top = a->top, i; + BN_ULONG *r_d, *a_d = a->d, t_d[BN_NIST_521_TOP], val, tmp, *res; + PTR_SIZE_INT mask; + static const BIGNUM _bignum_nist_p_521_sqr = { + (BN_ULONG *)_nist_p_521_sqr, + OSSL_NELEM(_nist_p_521_sqr), + OSSL_NELEM(_nist_p_521_sqr), + 0, BN_FLG_STATIC_DATA + }; + + field = &_bignum_nist_p_521; /* just to make sure */ + + if (BN_is_negative(a) || BN_ucmp(a, &_bignum_nist_p_521_sqr) >= 0) + return BN_nnmod(r, a, field, ctx); + + i = BN_ucmp(field, a); + if (i == 0) { + BN_zero(r); + return 1; + } else if (i > 0) + return (r == a) ? 1 : (BN_copy(r, a) != NULL); + + if (r != a) { + if (!bn_wexpand(r, BN_NIST_521_TOP)) + return 0; + r_d = r->d; + nist_cp_bn(r_d, a_d, BN_NIST_521_TOP); + } else + r_d = a_d; + + /* upper 521 bits, copy ... */ + nist_cp_bn_0(t_d, a_d + (BN_NIST_521_TOP - 1), + top - (BN_NIST_521_TOP - 1), BN_NIST_521_TOP); + /* ... and right shift */ + for (val = t_d[0], i = 0; i < BN_NIST_521_TOP - 1; i++) { +#if 0 + /* + * MSC ARM compiler [version 2013, presumably even earlier, + * much earlier] miscompiles this code, but not one in + * #else section. See RT#3541. + */ + tmp = val >> BN_NIST_521_RSHIFT; + val = t_d[i + 1]; + t_d[i] = (tmp | val << BN_NIST_521_LSHIFT) & BN_MASK2; +#else + t_d[i] = (val >> BN_NIST_521_RSHIFT | + (tmp = t_d[i + 1]) << BN_NIST_521_LSHIFT) & BN_MASK2; + val = tmp; +#endif + } + t_d[i] = val >> BN_NIST_521_RSHIFT; + /* lower 521 bits */ + r_d[i] &= BN_NIST_521_TOP_MASK; + + bn_add_words(r_d, r_d, t_d, BN_NIST_521_TOP); + mask = + 0 - (PTR_SIZE_INT) bn_sub_words(t_d, r_d, _nist_p_521, + BN_NIST_521_TOP); + res = t_d; + res = (BN_ULONG *)(((PTR_SIZE_INT) res & ~mask) | + ((PTR_SIZE_INT) r_d & mask)); + nist_cp_bn(r_d, res, BN_NIST_521_TOP); + r->top = BN_NIST_521_TOP; + bn_correct_top(r); + + return 1; +} + +int (*BN_nist_mod_func(const BIGNUM *p)) (BIGNUM *r, const BIGNUM *a, + const BIGNUM *field, BN_CTX *ctx) { + if (BN_ucmp(&_bignum_nist_p_192, p) == 0) + return BN_nist_mod_192; + if (BN_ucmp(&_bignum_nist_p_224, p) == 0) + return BN_nist_mod_224; + if (BN_ucmp(&_bignum_nist_p_256, p) == 0) + return BN_nist_mod_256; + if (BN_ucmp(&_bignum_nist_p_384, p) == 0) + return BN_nist_mod_384; + if (BN_ucmp(&_bignum_nist_p_521, p) == 0) + return BN_nist_mod_521; + return 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_prime.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_prime.c new file mode 100644 index 000000000..b91b31b1f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_prime.c @@ -0,0 +1,469 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include "bn_lcl.h" + +/* + * The quick sieve algorithm approach to weeding out primes is Philip + * Zimmermann's, as implemented in PGP. I have had a read of his comments + * and implemented my own version. + */ +#include "bn_prime.h" + +static int witness(BIGNUM *w, const BIGNUM *a, const BIGNUM *a1, + const BIGNUM *a1_odd, int k, BN_CTX *ctx, + BN_MONT_CTX *mont); +static int probable_prime(BIGNUM *rnd, int bits, prime_t *mods); +static int probable_prime_dh_safe(BIGNUM *rnd, int bits, + const BIGNUM *add, const BIGNUM *rem, + BN_CTX *ctx); + +int BN_GENCB_call(BN_GENCB *cb, int a, int b) +{ + /* No callback means continue */ + if (!cb) + return 1; + switch (cb->ver) { + case 1: + /* Deprecated-style callbacks */ + if (!cb->cb.cb_1) + return 1; + cb->cb.cb_1(a, b, cb->arg); + return 1; + case 2: + /* New-style callbacks */ + return cb->cb.cb_2(a, b, cb); + default: + break; + } + /* Unrecognised callback type */ + return 0; +} + +int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe, + const BIGNUM *add, const BIGNUM *rem, BN_GENCB *cb) +{ + BIGNUM *t; + int found = 0; + int i, j, c1 = 0; + BN_CTX *ctx = NULL; + prime_t *mods = NULL; + int checks = BN_prime_checks_for_size(bits); + + if (bits < 2) { + /* There are no prime numbers this small. */ + BNerr(BN_F_BN_GENERATE_PRIME_EX, BN_R_BITS_TOO_SMALL); + return 0; + } else if (bits == 2 && safe) { + /* The smallest safe prime (7) is three bits. */ + BNerr(BN_F_BN_GENERATE_PRIME_EX, BN_R_BITS_TOO_SMALL); + return 0; + } + + mods = OPENSSL_zalloc(sizeof(*mods) * NUMPRIMES); + if (mods == NULL) + goto err; + + ctx = BN_CTX_new(); + if (ctx == NULL) + goto err; + BN_CTX_start(ctx); + t = BN_CTX_get(ctx); + if (t == NULL) + goto err; + loop: + /* make a random number and set the top and bottom bits */ + if (add == NULL) { + if (!probable_prime(ret, bits, mods)) + goto err; + } else { + if (safe) { + if (!probable_prime_dh_safe(ret, bits, add, rem, ctx)) + goto err; + } else { + if (!bn_probable_prime_dh(ret, bits, add, rem, ctx)) + goto err; + } + } + + if (!BN_GENCB_call(cb, 0, c1++)) + /* aborted */ + goto err; + + if (!safe) { + i = BN_is_prime_fasttest_ex(ret, checks, ctx, 0, cb); + if (i == -1) + goto err; + if (i == 0) + goto loop; + } else { + /* + * for "safe prime" generation, check that (p-1)/2 is prime. Since a + * prime is odd, We just need to divide by 2 + */ + if (!BN_rshift1(t, ret)) + goto err; + + for (i = 0; i < checks; i++) { + j = BN_is_prime_fasttest_ex(ret, 1, ctx, 0, cb); + if (j == -1) + goto err; + if (j == 0) + goto loop; + + j = BN_is_prime_fasttest_ex(t, 1, ctx, 0, cb); + if (j == -1) + goto err; + if (j == 0) + goto loop; + + if (!BN_GENCB_call(cb, 2, c1 - 1)) + goto err; + /* We have a safe prime test pass */ + } + } + /* we have a prime :-) */ + found = 1; + err: + OPENSSL_free(mods); + if (ctx != NULL) + BN_CTX_end(ctx); + BN_CTX_free(ctx); + bn_check_top(ret); + return found; +} + +int BN_is_prime_ex(const BIGNUM *a, int checks, BN_CTX *ctx_passed, + BN_GENCB *cb) +{ + return BN_is_prime_fasttest_ex(a, checks, ctx_passed, 0, cb); +} + +int BN_is_prime_fasttest_ex(const BIGNUM *a, int checks, BN_CTX *ctx_passed, + int do_trial_division, BN_GENCB *cb) +{ + int i, j, ret = -1; + int k; + BN_CTX *ctx = NULL; + BIGNUM *A1, *A1_odd, *A3, *check; /* taken from ctx */ + BN_MONT_CTX *mont = NULL; + + /* Take care of the really small primes 2 & 3 */ + if (BN_is_word(a, 2) || BN_is_word(a, 3)) + return 1; + + /* Check odd and bigger than 1 */ + if (!BN_is_odd(a) || BN_cmp(a, BN_value_one()) <= 0) + return 0; + + if (checks == BN_prime_checks) + checks = BN_prime_checks_for_size(BN_num_bits(a)); + + /* first look for small factors */ + if (do_trial_division) { + for (i = 1; i < NUMPRIMES; i++) { + BN_ULONG mod = BN_mod_word(a, primes[i]); + if (mod == (BN_ULONG)-1) + goto err; + if (mod == 0) + return BN_is_word(a, primes[i]); + } + if (!BN_GENCB_call(cb, 1, -1)) + goto err; + } + + if (ctx_passed != NULL) + ctx = ctx_passed; + else if ((ctx = BN_CTX_new()) == NULL) + goto err; + BN_CTX_start(ctx); + + A1 = BN_CTX_get(ctx); + A3 = BN_CTX_get(ctx); + A1_odd = BN_CTX_get(ctx); + check = BN_CTX_get(ctx); + if (check == NULL) + goto err; + + /* compute A1 := a - 1 */ + if (!BN_copy(A1, a) || !BN_sub_word(A1, 1)) + goto err; + /* compute A3 := a - 3 */ + if (!BN_copy(A3, a) || !BN_sub_word(A3, 3)) + goto err; + + /* write A1 as A1_odd * 2^k */ + k = 1; + while (!BN_is_bit_set(A1, k)) + k++; + if (!BN_rshift(A1_odd, A1, k)) + goto err; + + /* Montgomery setup for computations mod a */ + mont = BN_MONT_CTX_new(); + if (mont == NULL) + goto err; + if (!BN_MONT_CTX_set(mont, a, ctx)) + goto err; + + for (i = 0; i < checks; i++) { + /* 1 < check < a-1 */ + if (!BN_priv_rand_range(check, A3) || !BN_add_word(check, 2)) + goto err; + + j = witness(check, a, A1, A1_odd, k, ctx, mont); + if (j == -1) + goto err; + if (j) { + ret = 0; + goto err; + } + if (!BN_GENCB_call(cb, 1, i)) + goto err; + } + ret = 1; + err: + if (ctx != NULL) { + BN_CTX_end(ctx); + if (ctx_passed == NULL) + BN_CTX_free(ctx); + } + BN_MONT_CTX_free(mont); + + return ret; +} + +static int witness(BIGNUM *w, const BIGNUM *a, const BIGNUM *a1, + const BIGNUM *a1_odd, int k, BN_CTX *ctx, + BN_MONT_CTX *mont) +{ + if (!BN_mod_exp_mont(w, w, a1_odd, a, ctx, mont)) /* w := w^a1_odd mod a */ + return -1; + if (BN_is_one(w)) + return 0; /* probably prime */ + if (BN_cmp(w, a1) == 0) + return 0; /* w == -1 (mod a), 'a' is probably prime */ + while (--k) { + if (!BN_mod_mul(w, w, w, a, ctx)) /* w := w^2 mod a */ + return -1; + if (BN_is_one(w)) + return 1; /* 'a' is composite, otherwise a previous 'w' + * would have been == -1 (mod 'a') */ + if (BN_cmp(w, a1) == 0) + return 0; /* w == -1 (mod a), 'a' is probably prime */ + } + /* + * If we get here, 'w' is the (a-1)/2-th power of the original 'w', and + * it is neither -1 nor +1 -- so 'a' cannot be prime + */ + bn_check_top(w); + return 1; +} + +static int probable_prime(BIGNUM *rnd, int bits, prime_t *mods) +{ + int i; + BN_ULONG delta; + BN_ULONG maxdelta = BN_MASK2 - primes[NUMPRIMES - 1]; + char is_single_word = bits <= BN_BITS2; + + again: + /* TODO: Not all primes are private */ + if (!BN_priv_rand(rnd, bits, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ODD)) + return 0; + /* we now have a random number 'rnd' to test. */ + for (i = 1; i < NUMPRIMES; i++) { + BN_ULONG mod = BN_mod_word(rnd, (BN_ULONG)primes[i]); + if (mod == (BN_ULONG)-1) + return 0; + mods[i] = (prime_t) mod; + } + /* + * If bits is so small that it fits into a single word then we + * additionally don't want to exceed that many bits. + */ + if (is_single_word) { + BN_ULONG size_limit; + + if (bits == BN_BITS2) { + /* + * Shifting by this much has undefined behaviour so we do it a + * different way + */ + size_limit = ~((BN_ULONG)0) - BN_get_word(rnd); + } else { + size_limit = (((BN_ULONG)1) << bits) - BN_get_word(rnd) - 1; + } + if (size_limit < maxdelta) + maxdelta = size_limit; + } + delta = 0; + loop: + if (is_single_word) { + BN_ULONG rnd_word = BN_get_word(rnd); + + /*- + * In the case that the candidate prime is a single word then + * we check that: + * 1) It's greater than primes[i] because we shouldn't reject + * 3 as being a prime number because it's a multiple of + * three. + * 2) That it's not a multiple of a known prime. We don't + * check that rnd-1 is also coprime to all the known + * primes because there aren't many small primes where + * that's true. + */ + for (i = 1; i < NUMPRIMES && primes[i] < rnd_word; i++) { + if ((mods[i] + delta) % primes[i] == 0) { + delta += 2; + if (delta > maxdelta) + goto again; + goto loop; + } + } + } else { + for (i = 1; i < NUMPRIMES; i++) { + /* + * check that rnd is not a prime and also that gcd(rnd-1,primes) + * == 1 (except for 2) + */ + if (((mods[i] + delta) % primes[i]) <= 1) { + delta += 2; + if (delta > maxdelta) + goto again; + goto loop; + } + } + } + if (!BN_add_word(rnd, delta)) + return 0; + if (BN_num_bits(rnd) != bits) + goto again; + bn_check_top(rnd); + return 1; +} + +int bn_probable_prime_dh(BIGNUM *rnd, int bits, + const BIGNUM *add, const BIGNUM *rem, BN_CTX *ctx) +{ + int i, ret = 0; + BIGNUM *t1; + + BN_CTX_start(ctx); + if ((t1 = BN_CTX_get(ctx)) == NULL) + goto err; + + if (!BN_rand(rnd, bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ODD)) + goto err; + + /* we need ((rnd-rem) % add) == 0 */ + + if (!BN_mod(t1, rnd, add, ctx)) + goto err; + if (!BN_sub(rnd, rnd, t1)) + goto err; + if (rem == NULL) { + if (!BN_add_word(rnd, 1)) + goto err; + } else { + if (!BN_add(rnd, rnd, rem)) + goto err; + } + + /* we now have a random number 'rand' to test. */ + + loop: + for (i = 1; i < NUMPRIMES; i++) { + /* check that rnd is a prime */ + BN_ULONG mod = BN_mod_word(rnd, (BN_ULONG)primes[i]); + if (mod == (BN_ULONG)-1) + goto err; + if (mod <= 1) { + if (!BN_add(rnd, rnd, add)) + goto err; + goto loop; + } + } + ret = 1; + + err: + BN_CTX_end(ctx); + bn_check_top(rnd); + return ret; +} + +static int probable_prime_dh_safe(BIGNUM *p, int bits, const BIGNUM *padd, + const BIGNUM *rem, BN_CTX *ctx) +{ + int i, ret = 0; + BIGNUM *t1, *qadd, *q; + + bits--; + BN_CTX_start(ctx); + t1 = BN_CTX_get(ctx); + q = BN_CTX_get(ctx); + qadd = BN_CTX_get(ctx); + if (qadd == NULL) + goto err; + + if (!BN_rshift1(qadd, padd)) + goto err; + + if (!BN_rand(q, bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ODD)) + goto err; + + /* we need ((rnd-rem) % add) == 0 */ + if (!BN_mod(t1, q, qadd, ctx)) + goto err; + if (!BN_sub(q, q, t1)) + goto err; + if (rem == NULL) { + if (!BN_add_word(q, 1)) + goto err; + } else { + if (!BN_rshift1(t1, rem)) + goto err; + if (!BN_add(q, q, t1)) + goto err; + } + + /* we now have a random number 'rand' to test. */ + if (!BN_lshift1(p, q)) + goto err; + if (!BN_add_word(p, 1)) + goto err; + + loop: + for (i = 1; i < NUMPRIMES; i++) { + /* check that p and q are prime */ + /* + * check that for p and q gcd(p-1,primes) == 1 (except for 2) + */ + BN_ULONG pmod = BN_mod_word(p, (BN_ULONG)primes[i]); + BN_ULONG qmod = BN_mod_word(q, (BN_ULONG)primes[i]); + if (pmod == (BN_ULONG)-1 || qmod == (BN_ULONG)-1) + goto err; + if (pmod == 0 || qmod == 0) { + if (!BN_add(p, p, padd)) + goto err; + if (!BN_add(q, q, qadd)) + goto err; + goto loop; + } + } + ret = 1; + + err: + BN_CTX_end(ctx); + bn_check_top(p); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_prime.h b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_prime.h new file mode 100644 index 000000000..2eb7b52f7 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_prime.h @@ -0,0 +1,273 @@ +/* + * WARNING: do not edit! + * Generated by crypto/bn/bn_prime.pl + * + * Copyright 1998-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +typedef unsigned short prime_t; +# define NUMPRIMES 2048 + +static const prime_t primes[2048] = { + 2, 3, 5, 7, 11, 13, 17, 19, + 23, 29, 31, 37, 41, 43, 47, 53, + 59, 61, 67, 71, 73, 79, 83, 89, + 97, 101, 103, 107, 109, 113, 127, 131, + 137, 139, 149, 151, 157, 163, 167, 173, + 179, 181, 191, 193, 197, 199, 211, 223, + 227, 229, 233, 239, 241, 251, 257, 263, + 269, 271, 277, 281, 283, 293, 307, 311, + 313, 317, 331, 337, 347, 349, 353, 359, + 367, 373, 379, 383, 389, 397, 401, 409, + 419, 421, 431, 433, 439, 443, 449, 457, + 461, 463, 467, 479, 487, 491, 499, 503, + 509, 521, 523, 541, 547, 557, 563, 569, + 571, 577, 587, 593, 599, 601, 607, 613, + 617, 619, 631, 641, 643, 647, 653, 659, + 661, 673, 677, 683, 691, 701, 709, 719, + 727, 733, 739, 743, 751, 757, 761, 769, + 773, 787, 797, 809, 811, 821, 823, 827, + 829, 839, 853, 857, 859, 863, 877, 881, + 883, 887, 907, 911, 919, 929, 937, 941, + 947, 953, 967, 971, 977, 983, 991, 997, + 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, + 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, + 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, + 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, + 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, + 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, + 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, + 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, + 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, + 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, + 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, + 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, + 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, + 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, + 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, + 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, + 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, + 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, + 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, + 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, + 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, + 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, + 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, + 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, + 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, + 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, + 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, + 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, + 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, + 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, + 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, + 2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939, + 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, + 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, + 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, + 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, + 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, + 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, + 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, + 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, + 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541, + 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, + 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, + 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, + 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, + 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, + 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, + 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, + 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, + 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, + 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, + 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, + 4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, + 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, + 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, + 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, + 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, + 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, + 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, + 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, + 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, + 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, + 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, + 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, + 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, + 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, + 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, + 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, + 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, + 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, + 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, + 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, + 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, + 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, + 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, + 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, + 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, + 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, + 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, + 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, + 6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271, + 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, + 6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379, + 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, + 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, + 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, + 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, + 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, + 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, + 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, + 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, + 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, + 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, + 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, + 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, + 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, + 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, + 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, + 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, + 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, + 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, + 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757, + 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, + 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, + 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, + 8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, + 8089, 8093, 8101, 8111, 8117, 8123, 8147, 8161, + 8167, 8171, 8179, 8191, 8209, 8219, 8221, 8231, + 8233, 8237, 8243, 8263, 8269, 8273, 8287, 8291, + 8293, 8297, 8311, 8317, 8329, 8353, 8363, 8369, + 8377, 8387, 8389, 8419, 8423, 8429, 8431, 8443, + 8447, 8461, 8467, 8501, 8513, 8521, 8527, 8537, + 8539, 8543, 8563, 8573, 8581, 8597, 8599, 8609, + 8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677, + 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, + 8737, 8741, 8747, 8753, 8761, 8779, 8783, 8803, + 8807, 8819, 8821, 8831, 8837, 8839, 8849, 8861, + 8863, 8867, 8887, 8893, 8923, 8929, 8933, 8941, + 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011, + 9013, 9029, 9041, 9043, 9049, 9059, 9067, 9091, + 9103, 9109, 9127, 9133, 9137, 9151, 9157, 9161, + 9173, 9181, 9187, 9199, 9203, 9209, 9221, 9227, + 9239, 9241, 9257, 9277, 9281, 9283, 9293, 9311, + 9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377, + 9391, 9397, 9403, 9413, 9419, 9421, 9431, 9433, + 9437, 9439, 9461, 9463, 9467, 9473, 9479, 9491, + 9497, 9511, 9521, 9533, 9539, 9547, 9551, 9587, + 9601, 9613, 9619, 9623, 9629, 9631, 9643, 9649, + 9661, 9677, 9679, 9689, 9697, 9719, 9721, 9733, + 9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791, + 9803, 9811, 9817, 9829, 9833, 9839, 9851, 9857, + 9859, 9871, 9883, 9887, 9901, 9907, 9923, 9929, + 9931, 9941, 9949, 9967, 9973, 10007, 10009, 10037, + 10039, 10061, 10067, 10069, 10079, 10091, 10093, 10099, + 10103, 10111, 10133, 10139, 10141, 10151, 10159, 10163, + 10169, 10177, 10181, 10193, 10211, 10223, 10243, 10247, + 10253, 10259, 10267, 10271, 10273, 10289, 10301, 10303, + 10313, 10321, 10331, 10333, 10337, 10343, 10357, 10369, + 10391, 10399, 10427, 10429, 10433, 10453, 10457, 10459, + 10463, 10477, 10487, 10499, 10501, 10513, 10529, 10531, + 10559, 10567, 10589, 10597, 10601, 10607, 10613, 10627, + 10631, 10639, 10651, 10657, 10663, 10667, 10687, 10691, + 10709, 10711, 10723, 10729, 10733, 10739, 10753, 10771, + 10781, 10789, 10799, 10831, 10837, 10847, 10853, 10859, + 10861, 10867, 10883, 10889, 10891, 10903, 10909, 10937, + 10939, 10949, 10957, 10973, 10979, 10987, 10993, 11003, + 11027, 11047, 11057, 11059, 11069, 11071, 11083, 11087, + 11093, 11113, 11117, 11119, 11131, 11149, 11159, 11161, + 11171, 11173, 11177, 11197, 11213, 11239, 11243, 11251, + 11257, 11261, 11273, 11279, 11287, 11299, 11311, 11317, + 11321, 11329, 11351, 11353, 11369, 11383, 11393, 11399, + 11411, 11423, 11437, 11443, 11447, 11467, 11471, 11483, + 11489, 11491, 11497, 11503, 11519, 11527, 11549, 11551, + 11579, 11587, 11593, 11597, 11617, 11621, 11633, 11657, + 11677, 11681, 11689, 11699, 11701, 11717, 11719, 11731, + 11743, 11777, 11779, 11783, 11789, 11801, 11807, 11813, + 11821, 11827, 11831, 11833, 11839, 11863, 11867, 11887, + 11897, 11903, 11909, 11923, 11927, 11933, 11939, 11941, + 11953, 11959, 11969, 11971, 11981, 11987, 12007, 12011, + 12037, 12041, 12043, 12049, 12071, 12073, 12097, 12101, + 12107, 12109, 12113, 12119, 12143, 12149, 12157, 12161, + 12163, 12197, 12203, 12211, 12227, 12239, 12241, 12251, + 12253, 12263, 12269, 12277, 12281, 12289, 12301, 12323, + 12329, 12343, 12347, 12373, 12377, 12379, 12391, 12401, + 12409, 12413, 12421, 12433, 12437, 12451, 12457, 12473, + 12479, 12487, 12491, 12497, 12503, 12511, 12517, 12527, + 12539, 12541, 12547, 12553, 12569, 12577, 12583, 12589, + 12601, 12611, 12613, 12619, 12637, 12641, 12647, 12653, + 12659, 12671, 12689, 12697, 12703, 12713, 12721, 12739, + 12743, 12757, 12763, 12781, 12791, 12799, 12809, 12821, + 12823, 12829, 12841, 12853, 12889, 12893, 12899, 12907, + 12911, 12917, 12919, 12923, 12941, 12953, 12959, 12967, + 12973, 12979, 12983, 13001, 13003, 13007, 13009, 13033, + 13037, 13043, 13049, 13063, 13093, 13099, 13103, 13109, + 13121, 13127, 13147, 13151, 13159, 13163, 13171, 13177, + 13183, 13187, 13217, 13219, 13229, 13241, 13249, 13259, + 13267, 13291, 13297, 13309, 13313, 13327, 13331, 13337, + 13339, 13367, 13381, 13397, 13399, 13411, 13417, 13421, + 13441, 13451, 13457, 13463, 13469, 13477, 13487, 13499, + 13513, 13523, 13537, 13553, 13567, 13577, 13591, 13597, + 13613, 13619, 13627, 13633, 13649, 13669, 13679, 13681, + 13687, 13691, 13693, 13697, 13709, 13711, 13721, 13723, + 13729, 13751, 13757, 13759, 13763, 13781, 13789, 13799, + 13807, 13829, 13831, 13841, 13859, 13873, 13877, 13879, + 13883, 13901, 13903, 13907, 13913, 13921, 13931, 13933, + 13963, 13967, 13997, 13999, 14009, 14011, 14029, 14033, + 14051, 14057, 14071, 14081, 14083, 14087, 14107, 14143, + 14149, 14153, 14159, 14173, 14177, 14197, 14207, 14221, + 14243, 14249, 14251, 14281, 14293, 14303, 14321, 14323, + 14327, 14341, 14347, 14369, 14387, 14389, 14401, 14407, + 14411, 14419, 14423, 14431, 14437, 14447, 14449, 14461, + 14479, 14489, 14503, 14519, 14533, 14537, 14543, 14549, + 14551, 14557, 14561, 14563, 14591, 14593, 14621, 14627, + 14629, 14633, 14639, 14653, 14657, 14669, 14683, 14699, + 14713, 14717, 14723, 14731, 14737, 14741, 14747, 14753, + 14759, 14767, 14771, 14779, 14783, 14797, 14813, 14821, + 14827, 14831, 14843, 14851, 14867, 14869, 14879, 14887, + 14891, 14897, 14923, 14929, 14939, 14947, 14951, 14957, + 14969, 14983, 15013, 15017, 15031, 15053, 15061, 15073, + 15077, 15083, 15091, 15101, 15107, 15121, 15131, 15137, + 15139, 15149, 15161, 15173, 15187, 15193, 15199, 15217, + 15227, 15233, 15241, 15259, 15263, 15269, 15271, 15277, + 15287, 15289, 15299, 15307, 15313, 15319, 15329, 15331, + 15349, 15359, 15361, 15373, 15377, 15383, 15391, 15401, + 15413, 15427, 15439, 15443, 15451, 15461, 15467, 15473, + 15493, 15497, 15511, 15527, 15541, 15551, 15559, 15569, + 15581, 15583, 15601, 15607, 15619, 15629, 15641, 15643, + 15647, 15649, 15661, 15667, 15671, 15679, 15683, 15727, + 15731, 15733, 15737, 15739, 15749, 15761, 15767, 15773, + 15787, 15791, 15797, 15803, 15809, 15817, 15823, 15859, + 15877, 15881, 15887, 15889, 15901, 15907, 15913, 15919, + 15923, 15937, 15959, 15971, 15973, 15991, 16001, 16007, + 16033, 16057, 16061, 16063, 16067, 16069, 16073, 16087, + 16091, 16097, 16103, 16111, 16127, 16139, 16141, 16183, + 16187, 16189, 16193, 16217, 16223, 16229, 16231, 16249, + 16253, 16267, 16273, 16301, 16319, 16333, 16339, 16349, + 16361, 16363, 16369, 16381, 16411, 16417, 16421, 16427, + 16433, 16447, 16451, 16453, 16477, 16481, 16487, 16493, + 16519, 16529, 16547, 16553, 16561, 16567, 16573, 16603, + 16607, 16619, 16631, 16633, 16649, 16651, 16657, 16661, + 16673, 16691, 16693, 16699, 16703, 16729, 16741, 16747, + 16759, 16763, 16787, 16811, 16823, 16829, 16831, 16843, + 16871, 16879, 16883, 16889, 16901, 16903, 16921, 16927, + 16931, 16937, 16943, 16963, 16979, 16981, 16987, 16993, + 17011, 17021, 17027, 17029, 17033, 17041, 17047, 17053, + 17077, 17093, 17099, 17107, 17117, 17123, 17137, 17159, + 17167, 17183, 17189, 17191, 17203, 17207, 17209, 17231, + 17239, 17257, 17291, 17293, 17299, 17317, 17321, 17327, + 17333, 17341, 17351, 17359, 17377, 17383, 17387, 17389, + 17393, 17401, 17417, 17419, 17431, 17443, 17449, 17467, + 17471, 17477, 17483, 17489, 17491, 17497, 17509, 17519, + 17539, 17551, 17569, 17573, 17579, 17581, 17597, 17599, + 17609, 17623, 17627, 17657, 17659, 17669, 17681, 17683, + 17707, 17713, 17729, 17737, 17747, 17749, 17761, 17783, + 17789, 17791, 17807, 17827, 17837, 17839, 17851, 17863, +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_prime.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_prime.pl new file mode 100644 index 000000000..b0b160874 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_prime.pl @@ -0,0 +1,48 @@ +#! /usr/bin/env perl +# Copyright 1998-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# Output year depends on the year of the script. +my $YEAR = [localtime([stat($0)]->[9])]->[5] + 1900; +print <<"EOF"; +/* + * WARNING: do not edit! + * Generated by crypto/bn/bn_prime.pl + * + * Copyright 1998-$YEAR The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +EOF + + +my $num = shift || 2048; +my @primes = ( 2 ); +my $p = 1; +loop: while ($#primes < $num-1) { + $p += 2; + my $s = int(sqrt($p)); + + for (my $i = 0; defined($primes[$i]) && $primes[$i] <= $s; $i++) { + next loop if ($p % $primes[$i]) == 0; + } + push(@primes, $p); +} + +print "typedef unsigned short prime_t;\n"; +printf "# define NUMPRIMES %d\n\n", $num; + +printf "static const prime_t primes[%d] = {", $num; +for (my $i = 0; $i <= $#primes; $i++) { + printf "\n " if ($i % 8) == 0; + printf " %5d,", $primes[$i]; +} +print "\n};\n"; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_print.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_print.c new file mode 100644 index 000000000..1853269d9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_print.c @@ -0,0 +1,345 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/ctype.h" +#include +#include "internal/cryptlib.h" +#include +#include "bn_lcl.h" + +static const char Hex[] = "0123456789ABCDEF"; + +/* Must 'OPENSSL_free' the returned data */ +char *BN_bn2hex(const BIGNUM *a) +{ + int i, j, v, z = 0; + char *buf; + char *p; + + if (BN_is_zero(a)) + return OPENSSL_strdup("0"); + buf = OPENSSL_malloc(a->top * BN_BYTES * 2 + 2); + if (buf == NULL) { + BNerr(BN_F_BN_BN2HEX, ERR_R_MALLOC_FAILURE); + goto err; + } + p = buf; + if (a->neg) + *p++ = '-'; + for (i = a->top - 1; i >= 0; i--) { + for (j = BN_BITS2 - 8; j >= 0; j -= 8) { + /* strip leading zeros */ + v = (int)((a->d[i] >> j) & 0xff); + if (z || v != 0) { + *p++ = Hex[v >> 4]; + *p++ = Hex[v & 0x0f]; + z = 1; + } + } + } + *p = '\0'; + err: + return buf; +} + +/* Must 'OPENSSL_free' the returned data */ +char *BN_bn2dec(const BIGNUM *a) +{ + int i = 0, num, ok = 0, n, tbytes; + char *buf = NULL; + char *p; + BIGNUM *t = NULL; + BN_ULONG *bn_data = NULL, *lp; + int bn_data_num; + + /*- + * get an upper bound for the length of the decimal integer + * num <= (BN_num_bits(a) + 1) * log(2) + * <= 3 * BN_num_bits(a) * 0.101 + log(2) + 1 (rounding error) + * <= 3 * BN_num_bits(a) / 10 + 3 * BN_num_bits / 1000 + 1 + 1 + */ + i = BN_num_bits(a) * 3; + num = (i / 10 + i / 1000 + 1) + 1; + tbytes = num + 3; /* negative and terminator and one spare? */ + bn_data_num = num / BN_DEC_NUM + 1; + bn_data = OPENSSL_malloc(bn_data_num * sizeof(BN_ULONG)); + buf = OPENSSL_malloc(tbytes); + if (buf == NULL || bn_data == NULL) { + BNerr(BN_F_BN_BN2DEC, ERR_R_MALLOC_FAILURE); + goto err; + } + if ((t = BN_dup(a)) == NULL) + goto err; + + p = buf; + lp = bn_data; + if (BN_is_zero(t)) { + *p++ = '0'; + *p++ = '\0'; + } else { + if (BN_is_negative(t)) + *p++ = '-'; + + while (!BN_is_zero(t)) { + if (lp - bn_data >= bn_data_num) + goto err; + *lp = BN_div_word(t, BN_DEC_CONV); + if (*lp == (BN_ULONG)-1) + goto err; + lp++; + } + lp--; + /* + * We now have a series of blocks, BN_DEC_NUM chars in length, where + * the last one needs truncation. The blocks need to be reversed in + * order. + */ + n = BIO_snprintf(p, tbytes - (size_t)(p - buf), BN_DEC_FMT1, *lp); + if (n < 0) + goto err; + p += n; + while (lp != bn_data) { + lp--; + n = BIO_snprintf(p, tbytes - (size_t)(p - buf), BN_DEC_FMT2, *lp); + if (n < 0) + goto err; + p += n; + } + } + ok = 1; + err: + OPENSSL_free(bn_data); + BN_free(t); + if (ok) + return buf; + OPENSSL_free(buf); + return NULL; +} + +int BN_hex2bn(BIGNUM **bn, const char *a) +{ + BIGNUM *ret = NULL; + BN_ULONG l = 0; + int neg = 0, h, m, i, j, k, c; + int num; + + if (a == NULL || *a == '\0') + return 0; + + if (*a == '-') { + neg = 1; + a++; + } + + for (i = 0; i <= INT_MAX / 4 && ossl_isxdigit(a[i]); i++) + continue; + + if (i == 0 || i > INT_MAX / 4) + goto err; + + num = i + neg; + if (bn == NULL) + return num; + + /* a is the start of the hex digits, and it is 'i' long */ + if (*bn == NULL) { + if ((ret = BN_new()) == NULL) + return 0; + } else { + ret = *bn; + BN_zero(ret); + } + + /* i is the number of hex digits */ + if (bn_expand(ret, i * 4) == NULL) + goto err; + + j = i; /* least significant 'hex' */ + m = 0; + h = 0; + while (j > 0) { + m = (BN_BYTES * 2 <= j) ? BN_BYTES * 2 : j; + l = 0; + for (;;) { + c = a[j - m]; + k = OPENSSL_hexchar2int(c); + if (k < 0) + k = 0; /* paranoia */ + l = (l << 4) | k; + + if (--m <= 0) { + ret->d[h++] = l; + break; + } + } + j -= BN_BYTES * 2; + } + ret->top = h; + bn_correct_top(ret); + + *bn = ret; + bn_check_top(ret); + /* Don't set the negative flag if it's zero. */ + if (ret->top != 0) + ret->neg = neg; + return num; + err: + if (*bn == NULL) + BN_free(ret); + return 0; +} + +int BN_dec2bn(BIGNUM **bn, const char *a) +{ + BIGNUM *ret = NULL; + BN_ULONG l = 0; + int neg = 0, i, j; + int num; + + if (a == NULL || *a == '\0') + return 0; + if (*a == '-') { + neg = 1; + a++; + } + + for (i = 0; i <= INT_MAX / 4 && ossl_isdigit(a[i]); i++) + continue; + + if (i == 0 || i > INT_MAX / 4) + goto err; + + num = i + neg; + if (bn == NULL) + return num; + + /* + * a is the start of the digits, and it is 'i' long. We chop it into + * BN_DEC_NUM digits at a time + */ + if (*bn == NULL) { + if ((ret = BN_new()) == NULL) + return 0; + } else { + ret = *bn; + BN_zero(ret); + } + + /* i is the number of digits, a bit of an over expand */ + if (bn_expand(ret, i * 4) == NULL) + goto err; + + j = BN_DEC_NUM - i % BN_DEC_NUM; + if (j == BN_DEC_NUM) + j = 0; + l = 0; + while (--i >= 0) { + l *= 10; + l += *a - '0'; + a++; + if (++j == BN_DEC_NUM) { + if (!BN_mul_word(ret, BN_DEC_CONV) + || !BN_add_word(ret, l)) + goto err; + l = 0; + j = 0; + } + } + + bn_correct_top(ret); + *bn = ret; + bn_check_top(ret); + /* Don't set the negative flag if it's zero. */ + if (ret->top != 0) + ret->neg = neg; + return num; + err: + if (*bn == NULL) + BN_free(ret); + return 0; +} + +int BN_asc2bn(BIGNUM **bn, const char *a) +{ + const char *p = a; + + if (*p == '-') + p++; + + if (p[0] == '0' && (p[1] == 'X' || p[1] == 'x')) { + if (!BN_hex2bn(bn, p + 2)) + return 0; + } else { + if (!BN_dec2bn(bn, p)) + return 0; + } + /* Don't set the negative flag if it's zero. */ + if (*a == '-' && (*bn)->top != 0) + (*bn)->neg = 1; + return 1; +} + +# ifndef OPENSSL_NO_STDIO +int BN_print_fp(FILE *fp, const BIGNUM *a) +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) + return 0; + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = BN_print(b, a); + BIO_free(b); + return ret; +} +# endif + +int BN_print(BIO *bp, const BIGNUM *a) +{ + int i, j, v, z = 0; + int ret = 0; + + if ((a->neg) && BIO_write(bp, "-", 1) != 1) + goto end; + if (BN_is_zero(a) && BIO_write(bp, "0", 1) != 1) + goto end; + for (i = a->top - 1; i >= 0; i--) { + for (j = BN_BITS2 - 4; j >= 0; j -= 4) { + /* strip leading zeros */ + v = (int)((a->d[i] >> j) & 0x0f); + if (z || v != 0) { + if (BIO_write(bp, &Hex[v], 1) != 1) + goto end; + z = 1; + } + } + } + ret = 1; + end: + return ret; +} + +char *BN_options(void) +{ + static int init = 0; + static char data[16]; + + if (!init) { + init++; +#ifdef BN_LLONG + BIO_snprintf(data, sizeof(data), "bn(%zu,%zu)", + sizeof(BN_ULLONG) * 8, sizeof(BN_ULONG) * 8); +#else + BIO_snprintf(data, sizeof(data), "bn(%zu,%zu)", + sizeof(BN_ULONG) * 8, sizeof(BN_ULONG) * 8); +#endif + } + return data; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_rand.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_rand.c new file mode 100644 index 000000000..c0d1a3229 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_rand.c @@ -0,0 +1,268 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include "bn_lcl.h" +#include +#include + +typedef enum bnrand_flag_e { + NORMAL, TESTING, PRIVATE +} BNRAND_FLAG; + +static int bnrand(BNRAND_FLAG flag, BIGNUM *rnd, int bits, int top, int bottom) +{ + unsigned char *buf = NULL; + int b, ret = 0, bit, bytes, mask; + + if (bits == 0) { + if (top != BN_RAND_TOP_ANY || bottom != BN_RAND_BOTTOM_ANY) + goto toosmall; + BN_zero(rnd); + return 1; + } + if (bits < 0 || (bits == 1 && top > 0)) + goto toosmall; + + bytes = (bits + 7) / 8; + bit = (bits - 1) % 8; + mask = 0xff << (bit + 1); + + buf = OPENSSL_malloc(bytes); + if (buf == NULL) { + BNerr(BN_F_BNRAND, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* make a random number and set the top and bottom bits */ + b = flag == NORMAL ? RAND_bytes(buf, bytes) : RAND_priv_bytes(buf, bytes); + if (b <= 0) + goto err; + + if (flag == TESTING) { + /* + * generate patterns that are more likely to trigger BN library bugs + */ + int i; + unsigned char c; + + for (i = 0; i < bytes; i++) { + if (RAND_bytes(&c, 1) <= 0) + goto err; + if (c >= 128 && i > 0) + buf[i] = buf[i - 1]; + else if (c < 42) + buf[i] = 0; + else if (c < 84) + buf[i] = 255; + } + } + + if (top >= 0) { + if (top) { + if (bit == 0) { + buf[0] = 1; + buf[1] |= 0x80; + } else { + buf[0] |= (3 << (bit - 1)); + } + } else { + buf[0] |= (1 << bit); + } + } + buf[0] &= ~mask; + if (bottom) /* set bottom bit if requested */ + buf[bytes - 1] |= 1; + if (!BN_bin2bn(buf, bytes, rnd)) + goto err; + ret = 1; + err: + OPENSSL_clear_free(buf, bytes); + bn_check_top(rnd); + return ret; + +toosmall: + BNerr(BN_F_BNRAND, BN_R_BITS_TOO_SMALL); + return 0; +} + +int BN_rand(BIGNUM *rnd, int bits, int top, int bottom) +{ + return bnrand(NORMAL, rnd, bits, top, bottom); +} + +int BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom) +{ + return bnrand(TESTING, rnd, bits, top, bottom); +} + +int BN_priv_rand(BIGNUM *rnd, int bits, int top, int bottom) +{ + return bnrand(PRIVATE, rnd, bits, top, bottom); +} + +/* random number r: 0 <= r < range */ +static int bnrand_range(BNRAND_FLAG flag, BIGNUM *r, const BIGNUM *range) +{ + int n; + int count = 100; + + if (range->neg || BN_is_zero(range)) { + BNerr(BN_F_BNRAND_RANGE, BN_R_INVALID_RANGE); + return 0; + } + + n = BN_num_bits(range); /* n > 0 */ + + /* BN_is_bit_set(range, n - 1) always holds */ + + if (n == 1) + BN_zero(r); + else if (!BN_is_bit_set(range, n - 2) && !BN_is_bit_set(range, n - 3)) { + /* + * range = 100..._2, so 3*range (= 11..._2) is exactly one bit longer + * than range + */ + do { + if (!bnrand(flag, r, n + 1, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) + return 0; + + /* + * If r < 3*range, use r := r MOD range (which is either r, r - + * range, or r - 2*range). Otherwise, iterate once more. Since + * 3*range = 11..._2, each iteration succeeds with probability >= + * .75. + */ + if (BN_cmp(r, range) >= 0) { + if (!BN_sub(r, r, range)) + return 0; + if (BN_cmp(r, range) >= 0) + if (!BN_sub(r, r, range)) + return 0; + } + + if (!--count) { + BNerr(BN_F_BNRAND_RANGE, BN_R_TOO_MANY_ITERATIONS); + return 0; + } + + } + while (BN_cmp(r, range) >= 0); + } else { + do { + /* range = 11..._2 or range = 101..._2 */ + if (!bnrand(flag, r, n, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) + return 0; + + if (!--count) { + BNerr(BN_F_BNRAND_RANGE, BN_R_TOO_MANY_ITERATIONS); + return 0; + } + } + while (BN_cmp(r, range) >= 0); + } + + bn_check_top(r); + return 1; +} + +int BN_rand_range(BIGNUM *r, const BIGNUM *range) +{ + return bnrand_range(NORMAL, r, range); +} + +int BN_priv_rand_range(BIGNUM *r, const BIGNUM *range) +{ + return bnrand_range(PRIVATE, r, range); +} + +int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom) +{ + return BN_rand(rnd, bits, top, bottom); +} + +int BN_pseudo_rand_range(BIGNUM *r, const BIGNUM *range) +{ + return BN_rand_range(r, range); +} + +/* + * BN_generate_dsa_nonce generates a random number 0 <= out < range. Unlike + * BN_rand_range, it also includes the contents of |priv| and |message| in + * the generation so that an RNG failure isn't fatal as long as |priv| + * remains secret. This is intended for use in DSA and ECDSA where an RNG + * weakness leads directly to private key exposure unless this function is + * used. + */ +int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range, + const BIGNUM *priv, const unsigned char *message, + size_t message_len, BN_CTX *ctx) +{ + SHA512_CTX sha; + /* + * We use 512 bits of random data per iteration to ensure that we have at + * least |range| bits of randomness. + */ + unsigned char random_bytes[64]; + unsigned char digest[SHA512_DIGEST_LENGTH]; + unsigned done, todo; + /* We generate |range|+8 bytes of random output. */ + const unsigned num_k_bytes = BN_num_bytes(range) + 8; + unsigned char private_bytes[96]; + unsigned char *k_bytes; + int ret = 0; + + k_bytes = OPENSSL_malloc(num_k_bytes); + if (k_bytes == NULL) + goto err; + + /* We copy |priv| into a local buffer to avoid exposing its length. */ + todo = sizeof(priv->d[0]) * priv->top; + if (todo > sizeof(private_bytes)) { + /* + * No reasonable DSA or ECDSA key should have a private key this + * large and we don't handle this case in order to avoid leaking the + * length of the private key. + */ + BNerr(BN_F_BN_GENERATE_DSA_NONCE, BN_R_PRIVATE_KEY_TOO_LARGE); + goto err; + } + memcpy(private_bytes, priv->d, todo); + memset(private_bytes + todo, 0, sizeof(private_bytes) - todo); + + for (done = 0; done < num_k_bytes;) { + if (RAND_priv_bytes(random_bytes, sizeof(random_bytes)) != 1) + goto err; + SHA512_Init(&sha); + SHA512_Update(&sha, &done, sizeof(done)); + SHA512_Update(&sha, private_bytes, sizeof(private_bytes)); + SHA512_Update(&sha, message, message_len); + SHA512_Update(&sha, random_bytes, sizeof(random_bytes)); + SHA512_Final(digest, &sha); + + todo = num_k_bytes - done; + if (todo > SHA512_DIGEST_LENGTH) + todo = SHA512_DIGEST_LENGTH; + memcpy(k_bytes + done, digest, todo); + done += todo; + } + + if (!BN_bin2bn(k_bytes, num_k_bytes, out)) + goto err; + if (BN_mod(out, out, range, ctx) != 1) + goto err; + ret = 1; + + err: + OPENSSL_free(k_bytes); + OPENSSL_cleanse(private_bytes, sizeof(private_bytes)); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_recp.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_recp.c new file mode 100644 index 000000000..9ab767f42 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_recp.c @@ -0,0 +1,194 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include "bn_lcl.h" + +void BN_RECP_CTX_init(BN_RECP_CTX *recp) +{ + memset(recp, 0, sizeof(*recp)); + bn_init(&(recp->N)); + bn_init(&(recp->Nr)); +} + +BN_RECP_CTX *BN_RECP_CTX_new(void) +{ + BN_RECP_CTX *ret; + + if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) { + BNerr(BN_F_BN_RECP_CTX_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + bn_init(&(ret->N)); + bn_init(&(ret->Nr)); + ret->flags = BN_FLG_MALLOCED; + return ret; +} + +void BN_RECP_CTX_free(BN_RECP_CTX *recp) +{ + if (recp == NULL) + return; + BN_free(&recp->N); + BN_free(&recp->Nr); + if (recp->flags & BN_FLG_MALLOCED) + OPENSSL_free(recp); +} + +int BN_RECP_CTX_set(BN_RECP_CTX *recp, const BIGNUM *d, BN_CTX *ctx) +{ + if (!BN_copy(&(recp->N), d)) + return 0; + BN_zero(&(recp->Nr)); + recp->num_bits = BN_num_bits(d); + recp->shift = 0; + return 1; +} + +int BN_mod_mul_reciprocal(BIGNUM *r, const BIGNUM *x, const BIGNUM *y, + BN_RECP_CTX *recp, BN_CTX *ctx) +{ + int ret = 0; + BIGNUM *a; + const BIGNUM *ca; + + BN_CTX_start(ctx); + if ((a = BN_CTX_get(ctx)) == NULL) + goto err; + if (y != NULL) { + if (x == y) { + if (!BN_sqr(a, x, ctx)) + goto err; + } else { + if (!BN_mul(a, x, y, ctx)) + goto err; + } + ca = a; + } else + ca = x; /* Just do the mod */ + + ret = BN_div_recp(NULL, r, ca, recp, ctx); + err: + BN_CTX_end(ctx); + bn_check_top(r); + return ret; +} + +int BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, + BN_RECP_CTX *recp, BN_CTX *ctx) +{ + int i, j, ret = 0; + BIGNUM *a, *b, *d, *r; + + BN_CTX_start(ctx); + d = (dv != NULL) ? dv : BN_CTX_get(ctx); + r = (rem != NULL) ? rem : BN_CTX_get(ctx); + a = BN_CTX_get(ctx); + b = BN_CTX_get(ctx); + if (b == NULL) + goto err; + + if (BN_ucmp(m, &(recp->N)) < 0) { + BN_zero(d); + if (!BN_copy(r, m)) { + BN_CTX_end(ctx); + return 0; + } + BN_CTX_end(ctx); + return 1; + } + + /* + * We want the remainder Given input of ABCDEF / ab we need multiply + * ABCDEF by 3 digests of the reciprocal of ab + */ + + /* i := max(BN_num_bits(m), 2*BN_num_bits(N)) */ + i = BN_num_bits(m); + j = recp->num_bits << 1; + if (j > i) + i = j; + + /* Nr := round(2^i / N) */ + if (i != recp->shift) + recp->shift = BN_reciprocal(&(recp->Nr), &(recp->N), i, ctx); + /* BN_reciprocal could have returned -1 for an error */ + if (recp->shift == -1) + goto err; + + /*- + * d := |round(round(m / 2^BN_num_bits(N)) * recp->Nr / 2^(i - BN_num_bits(N)))| + * = |round(round(m / 2^BN_num_bits(N)) * round(2^i / N) / 2^(i - BN_num_bits(N)))| + * <= |(m / 2^BN_num_bits(N)) * (2^i / N) * (2^BN_num_bits(N) / 2^i)| + * = |m/N| + */ + if (!BN_rshift(a, m, recp->num_bits)) + goto err; + if (!BN_mul(b, a, &(recp->Nr), ctx)) + goto err; + if (!BN_rshift(d, b, i - recp->num_bits)) + goto err; + d->neg = 0; + + if (!BN_mul(b, &(recp->N), d, ctx)) + goto err; + if (!BN_usub(r, m, b)) + goto err; + r->neg = 0; + + j = 0; + while (BN_ucmp(r, &(recp->N)) >= 0) { + if (j++ > 2) { + BNerr(BN_F_BN_DIV_RECP, BN_R_BAD_RECIPROCAL); + goto err; + } + if (!BN_usub(r, r, &(recp->N))) + goto err; + if (!BN_add_word(d, 1)) + goto err; + } + + r->neg = BN_is_zero(r) ? 0 : m->neg; + d->neg = m->neg ^ recp->N.neg; + ret = 1; + err: + BN_CTX_end(ctx); + bn_check_top(dv); + bn_check_top(rem); + return ret; +} + +/* + * len is the expected size of the result We actually calculate with an extra + * word of precision, so we can do faster division if the remainder is not + * required. + */ +/* r := 2^len / m */ +int BN_reciprocal(BIGNUM *r, const BIGNUM *m, int len, BN_CTX *ctx) +{ + int ret = -1; + BIGNUM *t; + + BN_CTX_start(ctx); + if ((t = BN_CTX_get(ctx)) == NULL) + goto err; + + if (!BN_set_bit(t, len)) + goto err; + + if (!BN_div(r, NULL, t, m, ctx)) + goto err; + + ret = len; + err: + bn_check_top(r); + BN_CTX_end(ctx); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_shift.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_shift.c new file mode 100644 index 000000000..b7a1e0ff9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_shift.c @@ -0,0 +1,257 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include "bn_lcl.h" + +int BN_lshift1(BIGNUM *r, const BIGNUM *a) +{ + register BN_ULONG *ap, *rp, t, c; + int i; + + bn_check_top(r); + bn_check_top(a); + + if (r != a) { + r->neg = a->neg; + if (bn_wexpand(r, a->top + 1) == NULL) + return 0; + r->top = a->top; + } else { + if (bn_wexpand(r, a->top + 1) == NULL) + return 0; + } + ap = a->d; + rp = r->d; + c = 0; + for (i = 0; i < a->top; i++) { + t = *(ap++); + *(rp++) = ((t << 1) | c) & BN_MASK2; + c = (t & BN_TBIT) ? 1 : 0; + } + if (c) { + *rp = 1; + r->top++; + } + bn_check_top(r); + return 1; +} + +int BN_rshift1(BIGNUM *r, const BIGNUM *a) +{ + BN_ULONG *ap, *rp, t, c; + int i, j; + + bn_check_top(r); + bn_check_top(a); + + if (BN_is_zero(a)) { + BN_zero(r); + return 1; + } + i = a->top; + ap = a->d; + j = i - (ap[i - 1] == 1); + if (a != r) { + if (bn_wexpand(r, j) == NULL) + return 0; + r->neg = a->neg; + } + rp = r->d; + t = ap[--i]; + c = (t & 1) ? BN_TBIT : 0; + if (t >>= 1) + rp[i] = t; + while (i > 0) { + t = ap[--i]; + rp[i] = ((t >> 1) & BN_MASK2) | c; + c = (t & 1) ? BN_TBIT : 0; + } + r->top = j; + if (!r->top) + r->neg = 0; /* don't allow negative zero */ + bn_check_top(r); + return 1; +} + +int BN_lshift(BIGNUM *r, const BIGNUM *a, int n) +{ + int ret; + + if (n < 0) { + BNerr(BN_F_BN_LSHIFT, BN_R_INVALID_SHIFT); + return 0; + } + + ret = bn_lshift_fixed_top(r, a, n); + + bn_correct_top(r); + bn_check_top(r); + + return ret; +} + +/* + * In respect to shift factor the execution time is invariant of + * |n % BN_BITS2|, but not |n / BN_BITS2|. Or in other words pre-condition + * for constant-time-ness is |n < BN_BITS2| or |n / BN_BITS2| being + * non-secret. + */ +int bn_lshift_fixed_top(BIGNUM *r, const BIGNUM *a, int n) +{ + int i, nw; + unsigned int lb, rb; + BN_ULONG *t, *f; + BN_ULONG l, m, rmask = 0; + + assert(n >= 0); + + bn_check_top(r); + bn_check_top(a); + + nw = n / BN_BITS2; + if (bn_wexpand(r, a->top + nw + 1) == NULL) + return 0; + + if (a->top != 0) { + lb = (unsigned int)n % BN_BITS2; + rb = BN_BITS2 - lb; + rb %= BN_BITS2; /* say no to undefined behaviour */ + rmask = (BN_ULONG)0 - rb; /* rmask = 0 - (rb != 0) */ + rmask |= rmask >> 8; + f = &(a->d[0]); + t = &(r->d[nw]); + l = f[a->top - 1]; + t[a->top] = (l >> rb) & rmask; + for (i = a->top - 1; i > 0; i--) { + m = l << lb; + l = f[i - 1]; + t[i] = (m | ((l >> rb) & rmask)) & BN_MASK2; + } + t[0] = (l << lb) & BN_MASK2; + } else { + /* shouldn't happen, but formally required */ + r->d[nw] = 0; + } + if (nw != 0) + memset(r->d, 0, sizeof(*t) * nw); + + r->neg = a->neg; + r->top = a->top + nw + 1; + r->flags |= BN_FLG_FIXED_TOP; + + return 1; +} + +int BN_rshift(BIGNUM *r, const BIGNUM *a, int n) +{ + int i, j, nw, lb, rb; + BN_ULONG *t, *f; + BN_ULONG l, tmp; + + bn_check_top(r); + bn_check_top(a); + + if (n < 0) { + BNerr(BN_F_BN_RSHIFT, BN_R_INVALID_SHIFT); + return 0; + } + + nw = n / BN_BITS2; + rb = n % BN_BITS2; + lb = BN_BITS2 - rb; + if (nw >= a->top || a->top == 0) { + BN_zero(r); + return 1; + } + i = (BN_num_bits(a) - n + (BN_BITS2 - 1)) / BN_BITS2; + if (r != a) { + if (bn_wexpand(r, i) == NULL) + return 0; + r->neg = a->neg; + } else { + if (n == 0) + return 1; /* or the copying loop will go berserk */ + } + + f = &(a->d[nw]); + t = r->d; + j = a->top - nw; + r->top = i; + + if (rb == 0) { + for (i = j; i != 0; i--) + *(t++) = *(f++); + } else { + l = *(f++); + for (i = j - 1; i != 0; i--) { + tmp = (l >> rb) & BN_MASK2; + l = *(f++); + *(t++) = (tmp | (l << lb)) & BN_MASK2; + } + if ((l = (l >> rb) & BN_MASK2)) + *(t) = l; + } + if (!r->top) + r->neg = 0; /* don't allow negative zero */ + bn_check_top(r); + return 1; +} + +/* + * In respect to shift factor the execution time is invariant of + * |n % BN_BITS2|, but not |n / BN_BITS2|. Or in other words pre-condition + * for constant-time-ness for sufficiently[!] zero-padded inputs is + * |n < BN_BITS2| or |n / BN_BITS2| being non-secret. + */ +int bn_rshift_fixed_top(BIGNUM *r, const BIGNUM *a, int n) +{ + int i, top, nw; + unsigned int lb, rb; + BN_ULONG *t, *f; + BN_ULONG l, m, mask; + + bn_check_top(r); + bn_check_top(a); + + assert(n >= 0); + + nw = n / BN_BITS2; + if (nw >= a->top) { + /* shouldn't happen, but formally required */ + BN_zero(r); + return 1; + } + + rb = (unsigned int)n % BN_BITS2; + lb = BN_BITS2 - rb; + lb %= BN_BITS2; /* say no to undefined behaviour */ + mask = (BN_ULONG)0 - lb; /* mask = 0 - (lb != 0) */ + mask |= mask >> 8; + top = a->top - nw; + if (r != a && bn_wexpand(r, top) == NULL) + return 0; + + t = &(r->d[0]); + f = &(a->d[nw]); + l = f[0]; + for (i = 0; i < top - 1; i++) { + m = f[i + 1]; + t[i] = (l >> rb) | ((m << lb) & mask); + l = m; + } + t[i] = l >> rb; + + r->neg = a->neg; + r->top = top; + r->flags |= BN_FLG_FIXED_TOP; + + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_sqr.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_sqr.c new file mode 100644 index 000000000..0c0a590f0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_sqr.c @@ -0,0 +1,239 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include "bn_lcl.h" + +/* r must not be a */ +/* + * I've just gone over this and it is now %20 faster on x86 - eay - 27 Jun 96 + */ +int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) +{ + int ret = bn_sqr_fixed_top(r, a, ctx); + + bn_correct_top(r); + bn_check_top(r); + + return ret; +} + +int bn_sqr_fixed_top(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) +{ + int max, al; + int ret = 0; + BIGNUM *tmp, *rr; + + bn_check_top(a); + + al = a->top; + if (al <= 0) { + r->top = 0; + r->neg = 0; + return 1; + } + + BN_CTX_start(ctx); + rr = (a != r) ? r : BN_CTX_get(ctx); + tmp = BN_CTX_get(ctx); + if (rr == NULL || tmp == NULL) + goto err; + + max = 2 * al; /* Non-zero (from above) */ + if (bn_wexpand(rr, max) == NULL) + goto err; + + if (al == 4) { +#ifndef BN_SQR_COMBA + BN_ULONG t[8]; + bn_sqr_normal(rr->d, a->d, 4, t); +#else + bn_sqr_comba4(rr->d, a->d); +#endif + } else if (al == 8) { +#ifndef BN_SQR_COMBA + BN_ULONG t[16]; + bn_sqr_normal(rr->d, a->d, 8, t); +#else + bn_sqr_comba8(rr->d, a->d); +#endif + } else { +#if defined(BN_RECURSION) + if (al < BN_SQR_RECURSIVE_SIZE_NORMAL) { + BN_ULONG t[BN_SQR_RECURSIVE_SIZE_NORMAL * 2]; + bn_sqr_normal(rr->d, a->d, al, t); + } else { + int j, k; + + j = BN_num_bits_word((BN_ULONG)al); + j = 1 << (j - 1); + k = j + j; + if (al == j) { + if (bn_wexpand(tmp, k * 2) == NULL) + goto err; + bn_sqr_recursive(rr->d, a->d, al, tmp->d); + } else { + if (bn_wexpand(tmp, max) == NULL) + goto err; + bn_sqr_normal(rr->d, a->d, al, tmp->d); + } + } +#else + if (bn_wexpand(tmp, max) == NULL) + goto err; + bn_sqr_normal(rr->d, a->d, al, tmp->d); +#endif + } + + rr->neg = 0; + rr->top = max; + rr->flags |= BN_FLG_FIXED_TOP; + if (r != rr && BN_copy(r, rr) == NULL) + goto err; + + ret = 1; + err: + bn_check_top(rr); + bn_check_top(tmp); + BN_CTX_end(ctx); + return ret; +} + +/* tmp must have 2*n words */ +void bn_sqr_normal(BN_ULONG *r, const BN_ULONG *a, int n, BN_ULONG *tmp) +{ + int i, j, max; + const BN_ULONG *ap; + BN_ULONG *rp; + + max = n * 2; + ap = a; + rp = r; + rp[0] = rp[max - 1] = 0; + rp++; + j = n; + + if (--j > 0) { + ap++; + rp[j] = bn_mul_words(rp, ap, j, ap[-1]); + rp += 2; + } + + for (i = n - 2; i > 0; i--) { + j--; + ap++; + rp[j] = bn_mul_add_words(rp, ap, j, ap[-1]); + rp += 2; + } + + bn_add_words(r, r, r, max); + + /* There will not be a carry */ + + bn_sqr_words(tmp, a, n); + + bn_add_words(r, r, tmp, max); +} + +#ifdef BN_RECURSION +/*- + * r is 2*n words in size, + * a and b are both n words in size. (There's not actually a 'b' here ...) + * n must be a power of 2. + * We multiply and return the result. + * t must be 2*n words in size + * We calculate + * a[0]*b[0] + * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0]) + * a[1]*b[1] + */ +void bn_sqr_recursive(BN_ULONG *r, const BN_ULONG *a, int n2, BN_ULONG *t) +{ + int n = n2 / 2; + int zero, c1; + BN_ULONG ln, lo, *p; + + if (n2 == 4) { +# ifndef BN_SQR_COMBA + bn_sqr_normal(r, a, 4, t); +# else + bn_sqr_comba4(r, a); +# endif + return; + } else if (n2 == 8) { +# ifndef BN_SQR_COMBA + bn_sqr_normal(r, a, 8, t); +# else + bn_sqr_comba8(r, a); +# endif + return; + } + if (n2 < BN_SQR_RECURSIVE_SIZE_NORMAL) { + bn_sqr_normal(r, a, n2, t); + return; + } + /* r=(a[0]-a[1])*(a[1]-a[0]) */ + c1 = bn_cmp_words(a, &(a[n]), n); + zero = 0; + if (c1 > 0) + bn_sub_words(t, a, &(a[n]), n); + else if (c1 < 0) + bn_sub_words(t, &(a[n]), a, n); + else + zero = 1; + + /* The result will always be negative unless it is zero */ + p = &(t[n2 * 2]); + + if (!zero) + bn_sqr_recursive(&(t[n2]), t, n, p); + else + memset(&t[n2], 0, sizeof(*t) * n2); + bn_sqr_recursive(r, a, n, p); + bn_sqr_recursive(&(r[n2]), &(a[n]), n, p); + + /*- + * t[32] holds (a[0]-a[1])*(a[1]-a[0]), it is negative or zero + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + */ + + c1 = (int)(bn_add_words(t, r, &(r[n2]), n2)); + + /* t[32] is negative */ + c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2)); + + /*- + * t[32] holds (a[0]-a[1])*(a[1]-a[0])+(a[0]*a[0])+(a[1]*a[1]) + * r[10] holds (a[0]*a[0]) + * r[32] holds (a[1]*a[1]) + * c1 holds the carry bits + */ + c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2)); + if (c1) { + p = &(r[n + n2]); + lo = *p; + ln = (lo + c1) & BN_MASK2; + *p = ln; + + /* + * The overflow will stop before we over write words we should not + * overwrite + */ + if (ln < (BN_ULONG)c1) { + do { + p++; + lo = *p; + ln = (lo + 1) & BN_MASK2; + *p = ln; + } while (ln == 0); + } + } +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_sqrt.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_sqrt.c new file mode 100644 index 000000000..b97d8ca43 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_sqrt.c @@ -0,0 +1,358 @@ +/* + * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include "bn_lcl.h" + +BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) +/* + * Returns 'ret' such that ret^2 == a (mod p), using the Tonelli/Shanks + * algorithm (cf. Henri Cohen, "A Course in Algebraic Computational Number + * Theory", algorithm 1.5.1). 'p' must be prime! + */ +{ + BIGNUM *ret = in; + int err = 1; + int r; + BIGNUM *A, *b, *q, *t, *x, *y; + int e, i, j; + + if (!BN_is_odd(p) || BN_abs_is_word(p, 1)) { + if (BN_abs_is_word(p, 2)) { + if (ret == NULL) + ret = BN_new(); + if (ret == NULL) + goto end; + if (!BN_set_word(ret, BN_is_bit_set(a, 0))) { + if (ret != in) + BN_free(ret); + return NULL; + } + bn_check_top(ret); + return ret; + } + + BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME); + return NULL; + } + + if (BN_is_zero(a) || BN_is_one(a)) { + if (ret == NULL) + ret = BN_new(); + if (ret == NULL) + goto end; + if (!BN_set_word(ret, BN_is_one(a))) { + if (ret != in) + BN_free(ret); + return NULL; + } + bn_check_top(ret); + return ret; + } + + BN_CTX_start(ctx); + A = BN_CTX_get(ctx); + b = BN_CTX_get(ctx); + q = BN_CTX_get(ctx); + t = BN_CTX_get(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (y == NULL) + goto end; + + if (ret == NULL) + ret = BN_new(); + if (ret == NULL) + goto end; + + /* A = a mod p */ + if (!BN_nnmod(A, a, p, ctx)) + goto end; + + /* now write |p| - 1 as 2^e*q where q is odd */ + e = 1; + while (!BN_is_bit_set(p, e)) + e++; + /* we'll set q later (if needed) */ + + if (e == 1) { + /*- + * The easy case: (|p|-1)/2 is odd, so 2 has an inverse + * modulo (|p|-1)/2, and square roots can be computed + * directly by modular exponentiation. + * We have + * 2 * (|p|+1)/4 == 1 (mod (|p|-1)/2), + * so we can use exponent (|p|+1)/4, i.e. (|p|-3)/4 + 1. + */ + if (!BN_rshift(q, p, 2)) + goto end; + q->neg = 0; + if (!BN_add_word(q, 1)) + goto end; + if (!BN_mod_exp(ret, A, q, p, ctx)) + goto end; + err = 0; + goto vrfy; + } + + if (e == 2) { + /*- + * |p| == 5 (mod 8) + * + * In this case 2 is always a non-square since + * Legendre(2,p) = (-1)^((p^2-1)/8) for any odd prime. + * So if a really is a square, then 2*a is a non-square. + * Thus for + * b := (2*a)^((|p|-5)/8), + * i := (2*a)*b^2 + * we have + * i^2 = (2*a)^((1 + (|p|-5)/4)*2) + * = (2*a)^((p-1)/2) + * = -1; + * so if we set + * x := a*b*(i-1), + * then + * x^2 = a^2 * b^2 * (i^2 - 2*i + 1) + * = a^2 * b^2 * (-2*i) + * = a*(-i)*(2*a*b^2) + * = a*(-i)*i + * = a. + * + * (This is due to A.O.L. Atkin, + * , + * November 1992.) + */ + + /* t := 2*a */ + if (!BN_mod_lshift1_quick(t, A, p)) + goto end; + + /* b := (2*a)^((|p|-5)/8) */ + if (!BN_rshift(q, p, 3)) + goto end; + q->neg = 0; + if (!BN_mod_exp(b, t, q, p, ctx)) + goto end; + + /* y := b^2 */ + if (!BN_mod_sqr(y, b, p, ctx)) + goto end; + + /* t := (2*a)*b^2 - 1 */ + if (!BN_mod_mul(t, t, y, p, ctx)) + goto end; + if (!BN_sub_word(t, 1)) + goto end; + + /* x = a*b*t */ + if (!BN_mod_mul(x, A, b, p, ctx)) + goto end; + if (!BN_mod_mul(x, x, t, p, ctx)) + goto end; + + if (!BN_copy(ret, x)) + goto end; + err = 0; + goto vrfy; + } + + /* + * e > 2, so we really have to use the Tonelli/Shanks algorithm. First, + * find some y that is not a square. + */ + if (!BN_copy(q, p)) + goto end; /* use 'q' as temp */ + q->neg = 0; + i = 2; + do { + /* + * For efficiency, try small numbers first; if this fails, try random + * numbers. + */ + if (i < 22) { + if (!BN_set_word(y, i)) + goto end; + } else { + if (!BN_priv_rand(y, BN_num_bits(p), 0, 0)) + goto end; + if (BN_ucmp(y, p) >= 0) { + if (!(p->neg ? BN_add : BN_sub) (y, y, p)) + goto end; + } + /* now 0 <= y < |p| */ + if (BN_is_zero(y)) + if (!BN_set_word(y, i)) + goto end; + } + + r = BN_kronecker(y, q, ctx); /* here 'q' is |p| */ + if (r < -1) + goto end; + if (r == 0) { + /* m divides p */ + BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME); + goto end; + } + } + while (r == 1 && ++i < 82); + + if (r != -1) { + /* + * Many rounds and still no non-square -- this is more likely a bug + * than just bad luck. Even if p is not prime, we should have found + * some y such that r == -1. + */ + BNerr(BN_F_BN_MOD_SQRT, BN_R_TOO_MANY_ITERATIONS); + goto end; + } + + /* Here's our actual 'q': */ + if (!BN_rshift(q, q, e)) + goto end; + + /* + * Now that we have some non-square, we can find an element of order 2^e + * by computing its q'th power. + */ + if (!BN_mod_exp(y, y, q, p, ctx)) + goto end; + if (BN_is_one(y)) { + BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME); + goto end; + } + + /*- + * Now we know that (if p is indeed prime) there is an integer + * k, 0 <= k < 2^e, such that + * + * a^q * y^k == 1 (mod p). + * + * As a^q is a square and y is not, k must be even. + * q+1 is even, too, so there is an element + * + * X := a^((q+1)/2) * y^(k/2), + * + * and it satisfies + * + * X^2 = a^q * a * y^k + * = a, + * + * so it is the square root that we are looking for. + */ + + /* t := (q-1)/2 (note that q is odd) */ + if (!BN_rshift1(t, q)) + goto end; + + /* x := a^((q-1)/2) */ + if (BN_is_zero(t)) { /* special case: p = 2^e + 1 */ + if (!BN_nnmod(t, A, p, ctx)) + goto end; + if (BN_is_zero(t)) { + /* special case: a == 0 (mod p) */ + BN_zero(ret); + err = 0; + goto end; + } else if (!BN_one(x)) + goto end; + } else { + if (!BN_mod_exp(x, A, t, p, ctx)) + goto end; + if (BN_is_zero(x)) { + /* special case: a == 0 (mod p) */ + BN_zero(ret); + err = 0; + goto end; + } + } + + /* b := a*x^2 (= a^q) */ + if (!BN_mod_sqr(b, x, p, ctx)) + goto end; + if (!BN_mod_mul(b, b, A, p, ctx)) + goto end; + + /* x := a*x (= a^((q+1)/2)) */ + if (!BN_mod_mul(x, x, A, p, ctx)) + goto end; + + while (1) { + /*- + * Now b is a^q * y^k for some even k (0 <= k < 2^E + * where E refers to the original value of e, which we + * don't keep in a variable), and x is a^((q+1)/2) * y^(k/2). + * + * We have a*b = x^2, + * y^2^(e-1) = -1, + * b^2^(e-1) = 1. + */ + + if (BN_is_one(b)) { + if (!BN_copy(ret, x)) + goto end; + err = 0; + goto vrfy; + } + + /* find smallest i such that b^(2^i) = 1 */ + i = 1; + if (!BN_mod_sqr(t, b, p, ctx)) + goto end; + while (!BN_is_one(t)) { + i++; + if (i == e) { + BNerr(BN_F_BN_MOD_SQRT, BN_R_NOT_A_SQUARE); + goto end; + } + if (!BN_mod_mul(t, t, t, p, ctx)) + goto end; + } + + /* t := y^2^(e - i - 1) */ + if (!BN_copy(t, y)) + goto end; + for (j = e - i - 1; j > 0; j--) { + if (!BN_mod_sqr(t, t, p, ctx)) + goto end; + } + if (!BN_mod_mul(y, t, t, p, ctx)) + goto end; + if (!BN_mod_mul(x, x, t, p, ctx)) + goto end; + if (!BN_mod_mul(b, b, y, p, ctx)) + goto end; + e = i; + } + + vrfy: + if (!err) { + /* + * verify the result -- the input might have been not a square (test + * added in 0.9.8) + */ + + if (!BN_mod_sqr(x, ret, p, ctx)) + err = 1; + + if (!err && 0 != BN_cmp(x, A)) { + BNerr(BN_F_BN_MOD_SQRT, BN_R_NOT_A_SQUARE); + err = 1; + } + } + + end: + if (err) { + if (ret != in) + BN_clear_free(ret); + ret = NULL; + } + BN_CTX_end(ctx); + bn_check_top(ret); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_srp.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_srp.c new file mode 100644 index 000000000..27b6ebe51 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_srp.c @@ -0,0 +1,545 @@ +/* + * Copyright 2014-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "bn_lcl.h" +#include "internal/nelem.h" + +#ifndef OPENSSL_NO_SRP + +#include +#include "internal/bn_srp.h" + +# if (BN_BYTES == 8) +# if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__) +# define bn_pack4(a1,a2,a3,a4) ((a1##UI64<<48)|(a2##UI64<<32)|(a3##UI64<<16)|a4##UI64) +# elif defined(__arch64__) +# define bn_pack4(a1,a2,a3,a4) ((a1##UL<<48)|(a2##UL<<32)|(a3##UL<<16)|a4##UL) +# else +# define bn_pack4(a1,a2,a3,a4) ((a1##ULL<<48)|(a2##ULL<<32)|(a3##ULL<<16)|a4##ULL) +# endif +# elif (BN_BYTES == 4) +# define bn_pack4(a1,a2,a3,a4) ((a3##UL<<16)|a4##UL), ((a1##UL<<16)|a2##UL) +# else +# error "unsupported BN_BYTES" +# endif + +static const BN_ULONG bn_group_1024_value[] = { + bn_pack4(0x9FC6, 0x1D2F, 0xC0EB, 0x06E3), + bn_pack4(0xFD51, 0x38FE, 0x8376, 0x435B), + bn_pack4(0x2FD4, 0xCBF4, 0x976E, 0xAA9A), + bn_pack4(0x68ED, 0xBC3C, 0x0572, 0x6CC0), + bn_pack4(0xC529, 0xF566, 0x660E, 0x57EC), + bn_pack4(0x8255, 0x9B29, 0x7BCF, 0x1885), + bn_pack4(0xCE8E, 0xF4AD, 0x69B1, 0x5D49), + bn_pack4(0x5DC7, 0xD7B4, 0x6154, 0xD6B6), + bn_pack4(0x8E49, 0x5C1D, 0x6089, 0xDAD1), + bn_pack4(0xE0D5, 0xD8E2, 0x50B9, 0x8BE4), + bn_pack4(0x383B, 0x4813, 0xD692, 0xC6E0), + bn_pack4(0xD674, 0xDF74, 0x96EA, 0x81D3), + bn_pack4(0x9EA2, 0x314C, 0x9C25, 0x6576), + bn_pack4(0x6072, 0x6187, 0x75FF, 0x3C0B), + bn_pack4(0x9C33, 0xF80A, 0xFA8F, 0xC5E8), + bn_pack4(0xEEAF, 0x0AB9, 0xADB3, 0x8DD6) +}; + +const BIGNUM bn_group_1024 = { + (BN_ULONG *)bn_group_1024_value, + OSSL_NELEM(bn_group_1024_value), + OSSL_NELEM(bn_group_1024_value), + 0, + BN_FLG_STATIC_DATA +}; + +static const BN_ULONG bn_group_1536_value[] = { + bn_pack4(0xCF76, 0xE3FE, 0xD135, 0xF9BB), + bn_pack4(0x1518, 0x0F93, 0x499A, 0x234D), + bn_pack4(0x8CE7, 0xA28C, 0x2442, 0xC6F3), + bn_pack4(0x5A02, 0x1FFF, 0x5E91, 0x479E), + bn_pack4(0x7F8A, 0x2FE9, 0xB8B5, 0x292E), + bn_pack4(0x837C, 0x264A, 0xE3A9, 0xBEB8), + bn_pack4(0xE442, 0x734A, 0xF7CC, 0xB7AE), + bn_pack4(0x6577, 0x2E43, 0x7D6C, 0x7F8C), + bn_pack4(0xDB2F, 0xD53D, 0x24B7, 0xC486), + bn_pack4(0x6EDF, 0x0195, 0x3934, 0x9627), + bn_pack4(0x158B, 0xFD3E, 0x2B9C, 0x8CF5), + bn_pack4(0x764E, 0x3F4B, 0x53DD, 0x9DA1), + bn_pack4(0x4754, 0x8381, 0xDBC5, 0xB1FC), + bn_pack4(0x9B60, 0x9E0B, 0xE3BA, 0xB63D), + bn_pack4(0x8134, 0xB1C8, 0xB979, 0x8914), + bn_pack4(0xDF02, 0x8A7C, 0xEC67, 0xF0D0), + bn_pack4(0x80B6, 0x55BB, 0x9A22, 0xE8DC), + bn_pack4(0x1558, 0x903B, 0xA0D0, 0xF843), + bn_pack4(0x51C6, 0xA94B, 0xE460, 0x7A29), + bn_pack4(0x5F4F, 0x5F55, 0x6E27, 0xCBDE), + bn_pack4(0xBEEE, 0xA961, 0x4B19, 0xCC4D), + bn_pack4(0xDBA5, 0x1DF4, 0x99AC, 0x4C80), + bn_pack4(0xB1F1, 0x2A86, 0x17A4, 0x7BBB), + bn_pack4(0x9DEF, 0x3CAF, 0xB939, 0x277A) +}; + +const BIGNUM bn_group_1536 = { + (BN_ULONG *)bn_group_1536_value, + OSSL_NELEM(bn_group_1536_value), + OSSL_NELEM(bn_group_1536_value), + 0, + BN_FLG_STATIC_DATA +}; + +static const BN_ULONG bn_group_2048_value[] = { + bn_pack4(0x0FA7, 0x111F, 0x9E4A, 0xFF73), + bn_pack4(0x9B65, 0xE372, 0xFCD6, 0x8EF2), + bn_pack4(0x35DE, 0x236D, 0x525F, 0x5475), + bn_pack4(0x94B5, 0xC803, 0xD89F, 0x7AE4), + bn_pack4(0x71AE, 0x35F8, 0xE9DB, 0xFBB6), + bn_pack4(0x2A56, 0x98F3, 0xA8D0, 0xC382), + bn_pack4(0x9CCC, 0x041C, 0x7BC3, 0x08D8), + bn_pack4(0xAF87, 0x4E73, 0x03CE, 0x5329), + bn_pack4(0x6160, 0x2790, 0x04E5, 0x7AE6), + bn_pack4(0x032C, 0xFBDB, 0xF52F, 0xB378), + bn_pack4(0x5EA7, 0x7A27, 0x75D2, 0xECFA), + bn_pack4(0x5445, 0x23B5, 0x24B0, 0xD57D), + bn_pack4(0x5B9D, 0x32E6, 0x88F8, 0x7748), + bn_pack4(0xF1D2, 0xB907, 0x8717, 0x461A), + bn_pack4(0x76BD, 0x207A, 0x436C, 0x6481), + bn_pack4(0xCA97, 0xB43A, 0x23FB, 0x8016), + bn_pack4(0x1D28, 0x1E44, 0x6B14, 0x773B), + bn_pack4(0x7359, 0xD041, 0xD5C3, 0x3EA7), + bn_pack4(0xA80D, 0x740A, 0xDBF4, 0xFF74), + bn_pack4(0x55F9, 0x7993, 0xEC97, 0x5EEA), + bn_pack4(0x2918, 0xA996, 0x2F0B, 0x93B8), + bn_pack4(0x661A, 0x05FB, 0xD5FA, 0xAAE8), + bn_pack4(0xCF60, 0x9517, 0x9A16, 0x3AB3), + bn_pack4(0xE808, 0x3969, 0xEDB7, 0x67B0), + bn_pack4(0xCD7F, 0x48A9, 0xDA04, 0xFD50), + bn_pack4(0xD523, 0x12AB, 0x4B03, 0x310D), + bn_pack4(0x8193, 0xE075, 0x7767, 0xA13D), + bn_pack4(0xA373, 0x29CB, 0xB4A0, 0x99ED), + bn_pack4(0xFC31, 0x9294, 0x3DB5, 0x6050), + bn_pack4(0xAF72, 0xB665, 0x1987, 0xEE07), + bn_pack4(0xF166, 0xDE5E, 0x1389, 0x582F), + bn_pack4(0xAC6B, 0xDB41, 0x324A, 0x9A9B) +}; + +const BIGNUM bn_group_2048 = { + (BN_ULONG *)bn_group_2048_value, + OSSL_NELEM(bn_group_2048_value), + OSSL_NELEM(bn_group_2048_value), + 0, + BN_FLG_STATIC_DATA +}; + +static const BN_ULONG bn_group_3072_value[] = { + bn_pack4(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF), + bn_pack4(0x4B82, 0xD120, 0xA93A, 0xD2CA), + bn_pack4(0x43DB, 0x5BFC, 0xE0FD, 0x108E), + bn_pack4(0x08E2, 0x4FA0, 0x74E5, 0xAB31), + bn_pack4(0x7709, 0x88C0, 0xBAD9, 0x46E2), + bn_pack4(0xBBE1, 0x1757, 0x7A61, 0x5D6C), + bn_pack4(0x521F, 0x2B18, 0x177B, 0x200C), + bn_pack4(0xD876, 0x0273, 0x3EC8, 0x6A64), + bn_pack4(0xF12F, 0xFA06, 0xD98A, 0x0864), + bn_pack4(0xCEE3, 0xD226, 0x1AD2, 0xEE6B), + bn_pack4(0x1E8C, 0x94E0, 0x4A25, 0x619D), + bn_pack4(0xABF5, 0xAE8C, 0xDB09, 0x33D7), + bn_pack4(0xB397, 0x0F85, 0xA6E1, 0xE4C7), + bn_pack4(0x8AEA, 0x7157, 0x5D06, 0x0C7D), + bn_pack4(0xECFB, 0x8504, 0x58DB, 0xEF0A), + bn_pack4(0xA855, 0x21AB, 0xDF1C, 0xBA64), + bn_pack4(0xAD33, 0x170D, 0x0450, 0x7A33), + bn_pack4(0x1572, 0x8E5A, 0x8AAA, 0xC42D), + bn_pack4(0x15D2, 0x2618, 0x98FA, 0x0510), + bn_pack4(0x3995, 0x497C, 0xEA95, 0x6AE5), + bn_pack4(0xDE2B, 0xCBF6, 0x9558, 0x1718), + bn_pack4(0xB5C5, 0x5DF0, 0x6F4C, 0x52C9), + bn_pack4(0x9B27, 0x83A2, 0xEC07, 0xA28F), + bn_pack4(0xE39E, 0x772C, 0x180E, 0x8603), + bn_pack4(0x3290, 0x5E46, 0x2E36, 0xCE3B), + bn_pack4(0xF174, 0x6C08, 0xCA18, 0x217C), + bn_pack4(0x670C, 0x354E, 0x4ABC, 0x9804), + bn_pack4(0x9ED5, 0x2907, 0x7096, 0x966D), + bn_pack4(0x1C62, 0xF356, 0x2085, 0x52BB), + bn_pack4(0x8365, 0x5D23, 0xDCA3, 0xAD96), + bn_pack4(0x6916, 0x3FA8, 0xFD24, 0xCF5F), + bn_pack4(0x98DA, 0x4836, 0x1C55, 0xD39A), + bn_pack4(0xC200, 0x7CB8, 0xA163, 0xBF05), + bn_pack4(0x4928, 0x6651, 0xECE4, 0x5B3D), + bn_pack4(0xAE9F, 0x2411, 0x7C4B, 0x1FE6), + bn_pack4(0xEE38, 0x6BFB, 0x5A89, 0x9FA5), + bn_pack4(0x0BFF, 0x5CB6, 0xF406, 0xB7ED), + bn_pack4(0xF44C, 0x42E9, 0xA637, 0xED6B), + bn_pack4(0xE485, 0xB576, 0x625E, 0x7EC6), + bn_pack4(0x4FE1, 0x356D, 0x6D51, 0xC245), + bn_pack4(0x302B, 0x0A6D, 0xF25F, 0x1437), + bn_pack4(0xEF95, 0x19B3, 0xCD3A, 0x431B), + bn_pack4(0x514A, 0x0879, 0x8E34, 0x04DD), + bn_pack4(0x020B, 0xBEA6, 0x3B13, 0x9B22), + bn_pack4(0x2902, 0x4E08, 0x8A67, 0xCC74), + bn_pack4(0xC4C6, 0x628B, 0x80DC, 0x1CD1), + bn_pack4(0xC90F, 0xDAA2, 0x2168, 0xC234), + bn_pack4(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF) +}; + +const BIGNUM bn_group_3072 = { + (BN_ULONG *)bn_group_3072_value, + OSSL_NELEM(bn_group_3072_value), + OSSL_NELEM(bn_group_3072_value), + 0, + BN_FLG_STATIC_DATA +}; + +static const BN_ULONG bn_group_4096_value[] = { + bn_pack4(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF), + bn_pack4(0x4DF4, 0x35C9, 0x3406, 0x3199), + bn_pack4(0x86FF, 0xB7DC, 0x90A6, 0xC08F), + bn_pack4(0x93B4, 0xEA98, 0x8D8F, 0xDDC1), + bn_pack4(0xD006, 0x9127, 0xD5B0, 0x5AA9), + bn_pack4(0xB81B, 0xDD76, 0x2170, 0x481C), + bn_pack4(0x1F61, 0x2970, 0xCEE2, 0xD7AF), + bn_pack4(0x233B, 0xA186, 0x515B, 0xE7ED), + bn_pack4(0x99B2, 0x964F, 0xA090, 0xC3A2), + bn_pack4(0x287C, 0x5947, 0x4E6B, 0xC05D), + bn_pack4(0x2E8E, 0xFC14, 0x1FBE, 0xCAA6), + bn_pack4(0xDBBB, 0xC2DB, 0x04DE, 0x8EF9), + bn_pack4(0x2583, 0xE9CA, 0x2AD4, 0x4CE8), + bn_pack4(0x1A94, 0x6834, 0xB615, 0x0BDA), + bn_pack4(0x99C3, 0x2718, 0x6AF4, 0xE23C), + bn_pack4(0x8871, 0x9A10, 0xBDBA, 0x5B26), + bn_pack4(0x1A72, 0x3C12, 0xA787, 0xE6D7), + bn_pack4(0x4B82, 0xD120, 0xA921, 0x0801), + bn_pack4(0x43DB, 0x5BFC, 0xE0FD, 0x108E), + bn_pack4(0x08E2, 0x4FA0, 0x74E5, 0xAB31), + bn_pack4(0x7709, 0x88C0, 0xBAD9, 0x46E2), + bn_pack4(0xBBE1, 0x1757, 0x7A61, 0x5D6C), + bn_pack4(0x521F, 0x2B18, 0x177B, 0x200C), + bn_pack4(0xD876, 0x0273, 0x3EC8, 0x6A64), + bn_pack4(0xF12F, 0xFA06, 0xD98A, 0x0864), + bn_pack4(0xCEE3, 0xD226, 0x1AD2, 0xEE6B), + bn_pack4(0x1E8C, 0x94E0, 0x4A25, 0x619D), + bn_pack4(0xABF5, 0xAE8C, 0xDB09, 0x33D7), + bn_pack4(0xB397, 0x0F85, 0xA6E1, 0xE4C7), + bn_pack4(0x8AEA, 0x7157, 0x5D06, 0x0C7D), + bn_pack4(0xECFB, 0x8504, 0x58DB, 0xEF0A), + bn_pack4(0xA855, 0x21AB, 0xDF1C, 0xBA64), + bn_pack4(0xAD33, 0x170D, 0x0450, 0x7A33), + bn_pack4(0x1572, 0x8E5A, 0x8AAA, 0xC42D), + bn_pack4(0x15D2, 0x2618, 0x98FA, 0x0510), + bn_pack4(0x3995, 0x497C, 0xEA95, 0x6AE5), + bn_pack4(0xDE2B, 0xCBF6, 0x9558, 0x1718), + bn_pack4(0xB5C5, 0x5DF0, 0x6F4C, 0x52C9), + bn_pack4(0x9B27, 0x83A2, 0xEC07, 0xA28F), + bn_pack4(0xE39E, 0x772C, 0x180E, 0x8603), + bn_pack4(0x3290, 0x5E46, 0x2E36, 0xCE3B), + bn_pack4(0xF174, 0x6C08, 0xCA18, 0x217C), + bn_pack4(0x670C, 0x354E, 0x4ABC, 0x9804), + bn_pack4(0x9ED5, 0x2907, 0x7096, 0x966D), + bn_pack4(0x1C62, 0xF356, 0x2085, 0x52BB), + bn_pack4(0x8365, 0x5D23, 0xDCA3, 0xAD96), + bn_pack4(0x6916, 0x3FA8, 0xFD24, 0xCF5F), + bn_pack4(0x98DA, 0x4836, 0x1C55, 0xD39A), + bn_pack4(0xC200, 0x7CB8, 0xA163, 0xBF05), + bn_pack4(0x4928, 0x6651, 0xECE4, 0x5B3D), + bn_pack4(0xAE9F, 0x2411, 0x7C4B, 0x1FE6), + bn_pack4(0xEE38, 0x6BFB, 0x5A89, 0x9FA5), + bn_pack4(0x0BFF, 0x5CB6, 0xF406, 0xB7ED), + bn_pack4(0xF44C, 0x42E9, 0xA637, 0xED6B), + bn_pack4(0xE485, 0xB576, 0x625E, 0x7EC6), + bn_pack4(0x4FE1, 0x356D, 0x6D51, 0xC245), + bn_pack4(0x302B, 0x0A6D, 0xF25F, 0x1437), + bn_pack4(0xEF95, 0x19B3, 0xCD3A, 0x431B), + bn_pack4(0x514A, 0x0879, 0x8E34, 0x04DD), + bn_pack4(0x020B, 0xBEA6, 0x3B13, 0x9B22), + bn_pack4(0x2902, 0x4E08, 0x8A67, 0xCC74), + bn_pack4(0xC4C6, 0x628B, 0x80DC, 0x1CD1), + bn_pack4(0xC90F, 0xDAA2, 0x2168, 0xC234), + bn_pack4(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF) +}; + +const BIGNUM bn_group_4096 = { + (BN_ULONG *)bn_group_4096_value, + OSSL_NELEM(bn_group_4096_value), + OSSL_NELEM(bn_group_4096_value), + 0, + BN_FLG_STATIC_DATA +}; + +static const BN_ULONG bn_group_6144_value[] = { + bn_pack4(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF), + bn_pack4(0xE694, 0xF91E, 0x6DCC, 0x4024), + bn_pack4(0x12BF, 0x2D5B, 0x0B74, 0x74D6), + bn_pack4(0x043E, 0x8F66, 0x3F48, 0x60EE), + bn_pack4(0x387F, 0xE8D7, 0x6E3C, 0x0468), + bn_pack4(0xDA56, 0xC9EC, 0x2EF2, 0x9632), + bn_pack4(0xEB19, 0xCCB1, 0xA313, 0xD55C), + bn_pack4(0xF550, 0xAA3D, 0x8A1F, 0xBFF0), + bn_pack4(0x06A1, 0xD58B, 0xB7C5, 0xDA76), + bn_pack4(0xA797, 0x15EE, 0xF29B, 0xE328), + bn_pack4(0x14CC, 0x5ED2, 0x0F80, 0x37E0), + bn_pack4(0xCC8F, 0x6D7E, 0xBF48, 0xE1D8), + bn_pack4(0x4BD4, 0x07B2, 0x2B41, 0x54AA), + bn_pack4(0x0F1D, 0x45B7, 0xFF58, 0x5AC5), + bn_pack4(0x23A9, 0x7A7E, 0x36CC, 0x88BE), + bn_pack4(0x59E7, 0xC97F, 0xBEC7, 0xE8F3), + bn_pack4(0xB5A8, 0x4031, 0x900B, 0x1C9E), + bn_pack4(0xD55E, 0x702F, 0x4698, 0x0C82), + bn_pack4(0xF482, 0xD7CE, 0x6E74, 0xFEF6), + bn_pack4(0xF032, 0xEA15, 0xD172, 0x1D03), + bn_pack4(0x5983, 0xCA01, 0xC64B, 0x92EC), + bn_pack4(0x6FB8, 0xF401, 0x378C, 0xD2BF), + bn_pack4(0x3320, 0x5151, 0x2BD7, 0xAF42), + bn_pack4(0xDB7F, 0x1447, 0xE6CC, 0x254B), + bn_pack4(0x44CE, 0x6CBA, 0xCED4, 0xBB1B), + bn_pack4(0xDA3E, 0xDBEB, 0xCF9B, 0x14ED), + bn_pack4(0x1797, 0x27B0, 0x865A, 0x8918), + bn_pack4(0xB06A, 0x53ED, 0x9027, 0xD831), + bn_pack4(0xE5DB, 0x382F, 0x4130, 0x01AE), + bn_pack4(0xF8FF, 0x9406, 0xAD9E, 0x530E), + bn_pack4(0xC975, 0x1E76, 0x3DBA, 0x37BD), + bn_pack4(0xC1D4, 0xDCB2, 0x6026, 0x46DE), + bn_pack4(0x36C3, 0xFAB4, 0xD27C, 0x7026), + bn_pack4(0x4DF4, 0x35C9, 0x3402, 0x8492), + bn_pack4(0x86FF, 0xB7DC, 0x90A6, 0xC08F), + bn_pack4(0x93B4, 0xEA98, 0x8D8F, 0xDDC1), + bn_pack4(0xD006, 0x9127, 0xD5B0, 0x5AA9), + bn_pack4(0xB81B, 0xDD76, 0x2170, 0x481C), + bn_pack4(0x1F61, 0x2970, 0xCEE2, 0xD7AF), + bn_pack4(0x233B, 0xA186, 0x515B, 0xE7ED), + bn_pack4(0x99B2, 0x964F, 0xA090, 0xC3A2), + bn_pack4(0x287C, 0x5947, 0x4E6B, 0xC05D), + bn_pack4(0x2E8E, 0xFC14, 0x1FBE, 0xCAA6), + bn_pack4(0xDBBB, 0xC2DB, 0x04DE, 0x8EF9), + bn_pack4(0x2583, 0xE9CA, 0x2AD4, 0x4CE8), + bn_pack4(0x1A94, 0x6834, 0xB615, 0x0BDA), + bn_pack4(0x99C3, 0x2718, 0x6AF4, 0xE23C), + bn_pack4(0x8871, 0x9A10, 0xBDBA, 0x5B26), + bn_pack4(0x1A72, 0x3C12, 0xA787, 0xE6D7), + bn_pack4(0x4B82, 0xD120, 0xA921, 0x0801), + bn_pack4(0x43DB, 0x5BFC, 0xE0FD, 0x108E), + bn_pack4(0x08E2, 0x4FA0, 0x74E5, 0xAB31), + bn_pack4(0x7709, 0x88C0, 0xBAD9, 0x46E2), + bn_pack4(0xBBE1, 0x1757, 0x7A61, 0x5D6C), + bn_pack4(0x521F, 0x2B18, 0x177B, 0x200C), + bn_pack4(0xD876, 0x0273, 0x3EC8, 0x6A64), + bn_pack4(0xF12F, 0xFA06, 0xD98A, 0x0864), + bn_pack4(0xCEE3, 0xD226, 0x1AD2, 0xEE6B), + bn_pack4(0x1E8C, 0x94E0, 0x4A25, 0x619D), + bn_pack4(0xABF5, 0xAE8C, 0xDB09, 0x33D7), + bn_pack4(0xB397, 0x0F85, 0xA6E1, 0xE4C7), + bn_pack4(0x8AEA, 0x7157, 0x5D06, 0x0C7D), + bn_pack4(0xECFB, 0x8504, 0x58DB, 0xEF0A), + bn_pack4(0xA855, 0x21AB, 0xDF1C, 0xBA64), + bn_pack4(0xAD33, 0x170D, 0x0450, 0x7A33), + bn_pack4(0x1572, 0x8E5A, 0x8AAA, 0xC42D), + bn_pack4(0x15D2, 0x2618, 0x98FA, 0x0510), + bn_pack4(0x3995, 0x497C, 0xEA95, 0x6AE5), + bn_pack4(0xDE2B, 0xCBF6, 0x9558, 0x1718), + bn_pack4(0xB5C5, 0x5DF0, 0x6F4C, 0x52C9), + bn_pack4(0x9B27, 0x83A2, 0xEC07, 0xA28F), + bn_pack4(0xE39E, 0x772C, 0x180E, 0x8603), + bn_pack4(0x3290, 0x5E46, 0x2E36, 0xCE3B), + bn_pack4(0xF174, 0x6C08, 0xCA18, 0x217C), + bn_pack4(0x670C, 0x354E, 0x4ABC, 0x9804), + bn_pack4(0x9ED5, 0x2907, 0x7096, 0x966D), + bn_pack4(0x1C62, 0xF356, 0x2085, 0x52BB), + bn_pack4(0x8365, 0x5D23, 0xDCA3, 0xAD96), + bn_pack4(0x6916, 0x3FA8, 0xFD24, 0xCF5F), + bn_pack4(0x98DA, 0x4836, 0x1C55, 0xD39A), + bn_pack4(0xC200, 0x7CB8, 0xA163, 0xBF05), + bn_pack4(0x4928, 0x6651, 0xECE4, 0x5B3D), + bn_pack4(0xAE9F, 0x2411, 0x7C4B, 0x1FE6), + bn_pack4(0xEE38, 0x6BFB, 0x5A89, 0x9FA5), + bn_pack4(0x0BFF, 0x5CB6, 0xF406, 0xB7ED), + bn_pack4(0xF44C, 0x42E9, 0xA637, 0xED6B), + bn_pack4(0xE485, 0xB576, 0x625E, 0x7EC6), + bn_pack4(0x4FE1, 0x356D, 0x6D51, 0xC245), + bn_pack4(0x302B, 0x0A6D, 0xF25F, 0x1437), + bn_pack4(0xEF95, 0x19B3, 0xCD3A, 0x431B), + bn_pack4(0x514A, 0x0879, 0x8E34, 0x04DD), + bn_pack4(0x020B, 0xBEA6, 0x3B13, 0x9B22), + bn_pack4(0x2902, 0x4E08, 0x8A67, 0xCC74), + bn_pack4(0xC4C6, 0x628B, 0x80DC, 0x1CD1), + bn_pack4(0xC90F, 0xDAA2, 0x2168, 0xC234), + bn_pack4(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF) +}; + +const BIGNUM bn_group_6144 = { + (BN_ULONG *)bn_group_6144_value, + OSSL_NELEM(bn_group_6144_value), + OSSL_NELEM(bn_group_6144_value), + 0, + BN_FLG_STATIC_DATA +}; + +static const BN_ULONG bn_group_8192_value[] = { + bn_pack4(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF), + bn_pack4(0x60C9, 0x80DD, 0x98ED, 0xD3DF), + bn_pack4(0xC81F, 0x56E8, 0x80B9, 0x6E71), + bn_pack4(0x9E30, 0x50E2, 0x7656, 0x94DF), + bn_pack4(0x9558, 0xE447, 0x5677, 0xE9AA), + bn_pack4(0xC919, 0x0DA6, 0xFC02, 0x6E47), + bn_pack4(0x889A, 0x002E, 0xD5EE, 0x382B), + bn_pack4(0x4009, 0x438B, 0x481C, 0x6CD7), + bn_pack4(0x3590, 0x46F4, 0xEB87, 0x9F92), + bn_pack4(0xFAF3, 0x6BC3, 0x1ECF, 0xA268), + bn_pack4(0xB1D5, 0x10BD, 0x7EE7, 0x4D73), + bn_pack4(0xF9AB, 0x4819, 0x5DED, 0x7EA1), + bn_pack4(0x64F3, 0x1CC5, 0x0846, 0x851D), + bn_pack4(0x4597, 0xE899, 0xA025, 0x5DC1), + bn_pack4(0xDF31, 0x0EE0, 0x74AB, 0x6A36), + bn_pack4(0x6D2A, 0x13F8, 0x3F44, 0xF82D), + bn_pack4(0x062B, 0x3CF5, 0xB3A2, 0x78A6), + bn_pack4(0x7968, 0x3303, 0xED5B, 0xDD3A), + bn_pack4(0xFA9D, 0x4B7F, 0xA2C0, 0x87E8), + bn_pack4(0x4BCB, 0xC886, 0x2F83, 0x85DD), + bn_pack4(0x3473, 0xFC64, 0x6CEA, 0x306B), + bn_pack4(0x13EB, 0x57A8, 0x1A23, 0xF0C7), + bn_pack4(0x2222, 0x2E04, 0xA403, 0x7C07), + bn_pack4(0xE3FD, 0xB8BE, 0xFC84, 0x8AD9), + bn_pack4(0x238F, 0x16CB, 0xE39D, 0x652D), + bn_pack4(0x3423, 0xB474, 0x2BF1, 0xC978), + bn_pack4(0x3AAB, 0x639C, 0x5AE4, 0xF568), + bn_pack4(0x2576, 0xF693, 0x6BA4, 0x2466), + bn_pack4(0x741F, 0xA7BF, 0x8AFC, 0x47ED), + bn_pack4(0x3BC8, 0x32B6, 0x8D9D, 0xD300), + bn_pack4(0xD8BE, 0xC4D0, 0x73B9, 0x31BA), + bn_pack4(0x3877, 0x7CB6, 0xA932, 0xDF8C), + bn_pack4(0x74A3, 0x926F, 0x12FE, 0xE5E4), + bn_pack4(0xE694, 0xF91E, 0x6DBE, 0x1159), + bn_pack4(0x12BF, 0x2D5B, 0x0B74, 0x74D6), + bn_pack4(0x043E, 0x8F66, 0x3F48, 0x60EE), + bn_pack4(0x387F, 0xE8D7, 0x6E3C, 0x0468), + bn_pack4(0xDA56, 0xC9EC, 0x2EF2, 0x9632), + bn_pack4(0xEB19, 0xCCB1, 0xA313, 0xD55C), + bn_pack4(0xF550, 0xAA3D, 0x8A1F, 0xBFF0), + bn_pack4(0x06A1, 0xD58B, 0xB7C5, 0xDA76), + bn_pack4(0xA797, 0x15EE, 0xF29B, 0xE328), + bn_pack4(0x14CC, 0x5ED2, 0x0F80, 0x37E0), + bn_pack4(0xCC8F, 0x6D7E, 0xBF48, 0xE1D8), + bn_pack4(0x4BD4, 0x07B2, 0x2B41, 0x54AA), + bn_pack4(0x0F1D, 0x45B7, 0xFF58, 0x5AC5), + bn_pack4(0x23A9, 0x7A7E, 0x36CC, 0x88BE), + bn_pack4(0x59E7, 0xC97F, 0xBEC7, 0xE8F3), + bn_pack4(0xB5A8, 0x4031, 0x900B, 0x1C9E), + bn_pack4(0xD55E, 0x702F, 0x4698, 0x0C82), + bn_pack4(0xF482, 0xD7CE, 0x6E74, 0xFEF6), + bn_pack4(0xF032, 0xEA15, 0xD172, 0x1D03), + bn_pack4(0x5983, 0xCA01, 0xC64B, 0x92EC), + bn_pack4(0x6FB8, 0xF401, 0x378C, 0xD2BF), + bn_pack4(0x3320, 0x5151, 0x2BD7, 0xAF42), + bn_pack4(0xDB7F, 0x1447, 0xE6CC, 0x254B), + bn_pack4(0x44CE, 0x6CBA, 0xCED4, 0xBB1B), + bn_pack4(0xDA3E, 0xDBEB, 0xCF9B, 0x14ED), + bn_pack4(0x1797, 0x27B0, 0x865A, 0x8918), + bn_pack4(0xB06A, 0x53ED, 0x9027, 0xD831), + bn_pack4(0xE5DB, 0x382F, 0x4130, 0x01AE), + bn_pack4(0xF8FF, 0x9406, 0xAD9E, 0x530E), + bn_pack4(0xC975, 0x1E76, 0x3DBA, 0x37BD), + bn_pack4(0xC1D4, 0xDCB2, 0x6026, 0x46DE), + bn_pack4(0x36C3, 0xFAB4, 0xD27C, 0x7026), + bn_pack4(0x4DF4, 0x35C9, 0x3402, 0x8492), + bn_pack4(0x86FF, 0xB7DC, 0x90A6, 0xC08F), + bn_pack4(0x93B4, 0xEA98, 0x8D8F, 0xDDC1), + bn_pack4(0xD006, 0x9127, 0xD5B0, 0x5AA9), + bn_pack4(0xB81B, 0xDD76, 0x2170, 0x481C), + bn_pack4(0x1F61, 0x2970, 0xCEE2, 0xD7AF), + bn_pack4(0x233B, 0xA186, 0x515B, 0xE7ED), + bn_pack4(0x99B2, 0x964F, 0xA090, 0xC3A2), + bn_pack4(0x287C, 0x5947, 0x4E6B, 0xC05D), + bn_pack4(0x2E8E, 0xFC14, 0x1FBE, 0xCAA6), + bn_pack4(0xDBBB, 0xC2DB, 0x04DE, 0x8EF9), + bn_pack4(0x2583, 0xE9CA, 0x2AD4, 0x4CE8), + bn_pack4(0x1A94, 0x6834, 0xB615, 0x0BDA), + bn_pack4(0x99C3, 0x2718, 0x6AF4, 0xE23C), + bn_pack4(0x8871, 0x9A10, 0xBDBA, 0x5B26), + bn_pack4(0x1A72, 0x3C12, 0xA787, 0xE6D7), + bn_pack4(0x4B82, 0xD120, 0xA921, 0x0801), + bn_pack4(0x43DB, 0x5BFC, 0xE0FD, 0x108E), + bn_pack4(0x08E2, 0x4FA0, 0x74E5, 0xAB31), + bn_pack4(0x7709, 0x88C0, 0xBAD9, 0x46E2), + bn_pack4(0xBBE1, 0x1757, 0x7A61, 0x5D6C), + bn_pack4(0x521F, 0x2B18, 0x177B, 0x200C), + bn_pack4(0xD876, 0x0273, 0x3EC8, 0x6A64), + bn_pack4(0xF12F, 0xFA06, 0xD98A, 0x0864), + bn_pack4(0xCEE3, 0xD226, 0x1AD2, 0xEE6B), + bn_pack4(0x1E8C, 0x94E0, 0x4A25, 0x619D), + bn_pack4(0xABF5, 0xAE8C, 0xDB09, 0x33D7), + bn_pack4(0xB397, 0x0F85, 0xA6E1, 0xE4C7), + bn_pack4(0x8AEA, 0x7157, 0x5D06, 0x0C7D), + bn_pack4(0xECFB, 0x8504, 0x58DB, 0xEF0A), + bn_pack4(0xA855, 0x21AB, 0xDF1C, 0xBA64), + bn_pack4(0xAD33, 0x170D, 0x0450, 0x7A33), + bn_pack4(0x1572, 0x8E5A, 0x8AAA, 0xC42D), + bn_pack4(0x15D2, 0x2618, 0x98FA, 0x0510), + bn_pack4(0x3995, 0x497C, 0xEA95, 0x6AE5), + bn_pack4(0xDE2B, 0xCBF6, 0x9558, 0x1718), + bn_pack4(0xB5C5, 0x5DF0, 0x6F4C, 0x52C9), + bn_pack4(0x9B27, 0x83A2, 0xEC07, 0xA28F), + bn_pack4(0xE39E, 0x772C, 0x180E, 0x8603), + bn_pack4(0x3290, 0x5E46, 0x2E36, 0xCE3B), + bn_pack4(0xF174, 0x6C08, 0xCA18, 0x217C), + bn_pack4(0x670C, 0x354E, 0x4ABC, 0x9804), + bn_pack4(0x9ED5, 0x2907, 0x7096, 0x966D), + bn_pack4(0x1C62, 0xF356, 0x2085, 0x52BB), + bn_pack4(0x8365, 0x5D23, 0xDCA3, 0xAD96), + bn_pack4(0x6916, 0x3FA8, 0xFD24, 0xCF5F), + bn_pack4(0x98DA, 0x4836, 0x1C55, 0xD39A), + bn_pack4(0xC200, 0x7CB8, 0xA163, 0xBF05), + bn_pack4(0x4928, 0x6651, 0xECE4, 0x5B3D), + bn_pack4(0xAE9F, 0x2411, 0x7C4B, 0x1FE6), + bn_pack4(0xEE38, 0x6BFB, 0x5A89, 0x9FA5), + bn_pack4(0x0BFF, 0x5CB6, 0xF406, 0xB7ED), + bn_pack4(0xF44C, 0x42E9, 0xA637, 0xED6B), + bn_pack4(0xE485, 0xB576, 0x625E, 0x7EC6), + bn_pack4(0x4FE1, 0x356D, 0x6D51, 0xC245), + bn_pack4(0x302B, 0x0A6D, 0xF25F, 0x1437), + bn_pack4(0xEF95, 0x19B3, 0xCD3A, 0x431B), + bn_pack4(0x514A, 0x0879, 0x8E34, 0x04DD), + bn_pack4(0x020B, 0xBEA6, 0x3B13, 0x9B22), + bn_pack4(0x2902, 0x4E08, 0x8A67, 0xCC74), + bn_pack4(0xC4C6, 0x628B, 0x80DC, 0x1CD1), + bn_pack4(0xC90F, 0xDAA2, 0x2168, 0xC234), + bn_pack4(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF) +}; + +const BIGNUM bn_group_8192 = { + (BN_ULONG *)bn_group_8192_value, + OSSL_NELEM(bn_group_8192_value), + OSSL_NELEM(bn_group_8192_value), + 0, + BN_FLG_STATIC_DATA +}; + +static const BN_ULONG bn_generator_19_value[] = { 19 }; + +const BIGNUM bn_generator_19 = { + (BN_ULONG *)bn_generator_19_value, + 1, + 1, + 0, + BN_FLG_STATIC_DATA +}; +static const BN_ULONG bn_generator_5_value[] = { 5 }; + +const BIGNUM bn_generator_5 = { + (BN_ULONG *)bn_generator_5_value, + 1, + 1, + 0, + BN_FLG_STATIC_DATA +}; +static const BN_ULONG bn_generator_2_value[] = { 2 }; + +const BIGNUM bn_generator_2 = { + (BN_ULONG *)bn_generator_2_value, + 1, + 1, + 0, + BN_FLG_STATIC_DATA +}; + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_word.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_word.c new file mode 100644 index 000000000..262d7668f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_word.c @@ -0,0 +1,201 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include "bn_lcl.h" + +BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w) +{ +#ifndef BN_LLONG + BN_ULONG ret = 0; +#else + BN_ULLONG ret = 0; +#endif + int i; + + if (w == 0) + return (BN_ULONG)-1; + +#ifndef BN_LLONG + /* + * If |w| is too long and we don't have BN_ULLONG then we need to fall + * back to using BN_div_word + */ + if (w > ((BN_ULONG)1 << BN_BITS4)) { + BIGNUM *tmp = BN_dup(a); + if (tmp == NULL) + return (BN_ULONG)-1; + + ret = BN_div_word(tmp, w); + BN_free(tmp); + + return ret; + } +#endif + + bn_check_top(a); + w &= BN_MASK2; + for (i = a->top - 1; i >= 0; i--) { +#ifndef BN_LLONG + /* + * We can assume here that | w <= ((BN_ULONG)1 << BN_BITS4) | and so + * | ret < ((BN_ULONG)1 << BN_BITS4) | and therefore the shifts here are + * safe and will not overflow + */ + ret = ((ret << BN_BITS4) | ((a->d[i] >> BN_BITS4) & BN_MASK2l)) % w; + ret = ((ret << BN_BITS4) | (a->d[i] & BN_MASK2l)) % w; +#else + ret = (BN_ULLONG) (((ret << (BN_ULLONG) BN_BITS2) | a->d[i]) % + (BN_ULLONG) w); +#endif + } + return (BN_ULONG)ret; +} + +BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w) +{ + BN_ULONG ret = 0; + int i, j; + + bn_check_top(a); + w &= BN_MASK2; + + if (!w) + /* actually this an error (division by zero) */ + return (BN_ULONG)-1; + if (a->top == 0) + return 0; + + /* normalize input (so bn_div_words doesn't complain) */ + j = BN_BITS2 - BN_num_bits_word(w); + w <<= j; + if (!BN_lshift(a, a, j)) + return (BN_ULONG)-1; + + for (i = a->top - 1; i >= 0; i--) { + BN_ULONG l, d; + + l = a->d[i]; + d = bn_div_words(ret, l, w); + ret = (l - ((d * w) & BN_MASK2)) & BN_MASK2; + a->d[i] = d; + } + if ((a->top > 0) && (a->d[a->top - 1] == 0)) + a->top--; + ret >>= j; + if (!a->top) + a->neg = 0; /* don't allow negative zero */ + bn_check_top(a); + return ret; +} + +int BN_add_word(BIGNUM *a, BN_ULONG w) +{ + BN_ULONG l; + int i; + + bn_check_top(a); + w &= BN_MASK2; + + /* degenerate case: w is zero */ + if (!w) + return 1; + /* degenerate case: a is zero */ + if (BN_is_zero(a)) + return BN_set_word(a, w); + /* handle 'a' when negative */ + if (a->neg) { + a->neg = 0; + i = BN_sub_word(a, w); + if (!BN_is_zero(a)) + a->neg = !(a->neg); + return i; + } + for (i = 0; w != 0 && i < a->top; i++) { + a->d[i] = l = (a->d[i] + w) & BN_MASK2; + w = (w > l) ? 1 : 0; + } + if (w && i == a->top) { + if (bn_wexpand(a, a->top + 1) == NULL) + return 0; + a->top++; + a->d[i] = w; + } + bn_check_top(a); + return 1; +} + +int BN_sub_word(BIGNUM *a, BN_ULONG w) +{ + int i; + + bn_check_top(a); + w &= BN_MASK2; + + /* degenerate case: w is zero */ + if (!w) + return 1; + /* degenerate case: a is zero */ + if (BN_is_zero(a)) { + i = BN_set_word(a, w); + if (i != 0) + BN_set_negative(a, 1); + return i; + } + /* handle 'a' when negative */ + if (a->neg) { + a->neg = 0; + i = BN_add_word(a, w); + a->neg = 1; + return i; + } + + if ((a->top == 1) && (a->d[0] < w)) { + a->d[0] = w - a->d[0]; + a->neg = 1; + return 1; + } + i = 0; + for (;;) { + if (a->d[i] >= w) { + a->d[i] -= w; + break; + } else { + a->d[i] = (a->d[i] - w) & BN_MASK2; + i++; + w = 1; + } + } + if ((a->d[i] == 0) && (i == (a->top - 1))) + a->top--; + bn_check_top(a); + return 1; +} + +int BN_mul_word(BIGNUM *a, BN_ULONG w) +{ + BN_ULONG ll; + + bn_check_top(a); + w &= BN_MASK2; + if (a->top) { + if (w == 0) + BN_zero(a); + else { + ll = bn_mul_words(a->d, a->d, a->top, w); + if (ll) { + if (bn_wexpand(a, a->top + 1) == NULL) + return 0; + a->d[a->top++] = ll; + } + } + } + bn_check_top(a); + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_x931p.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_x931p.c new file mode 100644 index 000000000..9eb8384fd --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/bn_x931p.c @@ -0,0 +1,244 @@ +/* + * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "bn_lcl.h" + +/* X9.31 routines for prime derivation */ + +/* + * X9.31 prime derivation. This is used to generate the primes pi (p1, p2, + * q1, q2) from a parameter Xpi by checking successive odd integers. + */ + +static int bn_x931_derive_pi(BIGNUM *pi, const BIGNUM *Xpi, BN_CTX *ctx, + BN_GENCB *cb) +{ + int i = 0, is_prime; + if (!BN_copy(pi, Xpi)) + return 0; + if (!BN_is_odd(pi) && !BN_add_word(pi, 1)) + return 0; + for (;;) { + i++; + BN_GENCB_call(cb, 0, i); + /* NB 27 MR is specified in X9.31 */ + is_prime = BN_is_prime_fasttest_ex(pi, 27, ctx, 1, cb); + if (is_prime < 0) + return 0; + if (is_prime) + break; + if (!BN_add_word(pi, 2)) + return 0; + } + BN_GENCB_call(cb, 2, i); + return 1; +} + +/* + * This is the main X9.31 prime derivation function. From parameters Xp1, Xp2 + * and Xp derive the prime p. If the parameters p1 or p2 are not NULL they + * will be returned too: this is needed for testing. + */ + +int BN_X931_derive_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2, + const BIGNUM *Xp, const BIGNUM *Xp1, + const BIGNUM *Xp2, const BIGNUM *e, BN_CTX *ctx, + BN_GENCB *cb) +{ + int ret = 0; + + BIGNUM *t, *p1p2, *pm1; + + /* Only even e supported */ + if (!BN_is_odd(e)) + return 0; + + BN_CTX_start(ctx); + if (p1 == NULL) + p1 = BN_CTX_get(ctx); + + if (p2 == NULL) + p2 = BN_CTX_get(ctx); + + t = BN_CTX_get(ctx); + + p1p2 = BN_CTX_get(ctx); + + pm1 = BN_CTX_get(ctx); + + if (pm1 == NULL) + goto err; + + if (!bn_x931_derive_pi(p1, Xp1, ctx, cb)) + goto err; + + if (!bn_x931_derive_pi(p2, Xp2, ctx, cb)) + goto err; + + if (!BN_mul(p1p2, p1, p2, ctx)) + goto err; + + /* First set p to value of Rp */ + + if (!BN_mod_inverse(p, p2, p1, ctx)) + goto err; + + if (!BN_mul(p, p, p2, ctx)) + goto err; + + if (!BN_mod_inverse(t, p1, p2, ctx)) + goto err; + + if (!BN_mul(t, t, p1, ctx)) + goto err; + + if (!BN_sub(p, p, t)) + goto err; + + if (p->neg && !BN_add(p, p, p1p2)) + goto err; + + /* p now equals Rp */ + + if (!BN_mod_sub(p, p, Xp, p1p2, ctx)) + goto err; + + if (!BN_add(p, p, Xp)) + goto err; + + /* p now equals Yp0 */ + + for (;;) { + int i = 1; + BN_GENCB_call(cb, 0, i++); + if (!BN_copy(pm1, p)) + goto err; + if (!BN_sub_word(pm1, 1)) + goto err; + if (!BN_gcd(t, pm1, e, ctx)) + goto err; + if (BN_is_one(t)) { + /* + * X9.31 specifies 8 MR and 1 Lucas test or any prime test + * offering similar or better guarantees 50 MR is considerably + * better. + */ + int r = BN_is_prime_fasttest_ex(p, 50, ctx, 1, cb); + if (r < 0) + goto err; + if (r) + break; + } + if (!BN_add(p, p, p1p2)) + goto err; + } + + BN_GENCB_call(cb, 3, 0); + + ret = 1; + + err: + + BN_CTX_end(ctx); + + return ret; +} + +/* + * Generate pair of parameters Xp, Xq for X9.31 prime generation. Note: nbits + * parameter is sum of number of bits in both. + */ + +int BN_X931_generate_Xpq(BIGNUM *Xp, BIGNUM *Xq, int nbits, BN_CTX *ctx) +{ + BIGNUM *t; + int i; + /* + * Number of bits for each prime is of the form 512+128s for s = 0, 1, + * ... + */ + if ((nbits < 1024) || (nbits & 0xff)) + return 0; + nbits >>= 1; + /* + * The random value Xp must be between sqrt(2) * 2^(nbits-1) and 2^nbits + * - 1. By setting the top two bits we ensure that the lower bound is + * exceeded. + */ + if (!BN_priv_rand(Xp, nbits, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ANY)) + goto err; + + BN_CTX_start(ctx); + t = BN_CTX_get(ctx); + if (t == NULL) + goto err; + + for (i = 0; i < 1000; i++) { + if (!BN_priv_rand(Xq, nbits, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ANY)) + goto err; + + /* Check that |Xp - Xq| > 2^(nbits - 100) */ + if (!BN_sub(t, Xp, Xq)) + goto err; + if (BN_num_bits(t) > (nbits - 100)) + break; + } + + BN_CTX_end(ctx); + + if (i < 1000) + return 1; + + return 0; + + err: + BN_CTX_end(ctx); + return 0; +} + +/* + * Generate primes using X9.31 algorithm. Of the values p, p1, p2, Xp1 and + * Xp2 only 'p' needs to be non-NULL. If any of the others are not NULL the + * relevant parameter will be stored in it. Due to the fact that |Xp - Xq| > + * 2^(nbits - 100) must be satisfied Xp and Xq are generated using the + * previous function and supplied as input. + */ + +int BN_X931_generate_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2, + BIGNUM *Xp1, BIGNUM *Xp2, + const BIGNUM *Xp, + const BIGNUM *e, BN_CTX *ctx, BN_GENCB *cb) +{ + int ret = 0; + + BN_CTX_start(ctx); + if (Xp1 == NULL) + Xp1 = BN_CTX_get(ctx); + if (Xp2 == NULL) + Xp2 = BN_CTX_get(ctx); + if (Xp1 == NULL || Xp2 == NULL) + goto error; + + if (!BN_priv_rand(Xp1, 101, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) + goto error; + if (!BN_priv_rand(Xp2, 101, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) + goto error; + if (!BN_X931_derive_prime_ex(p, p1, p2, Xp, Xp1, Xp2, e, ctx, cb)) + goto error; + + ret = 1; + + error: + BN_CTX_end(ctx); + + return ret; + +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/build.info new file mode 100644 index 000000000..a463eddab --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/build.info @@ -0,0 +1,67 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + bn_add.c bn_div.c bn_exp.c bn_lib.c bn_ctx.c bn_mul.c bn_mod.c \ + bn_print.c bn_rand.c bn_shift.c bn_word.c bn_blind.c \ + bn_kron.c bn_sqrt.c bn_gcd.c bn_prime.c bn_err.c bn_sqr.c \ + {- $target{bn_asm_src} -} \ + bn_recp.c bn_mont.c bn_mpi.c bn_exp2.c bn_gf2m.c bn_nist.c \ + bn_depr.c bn_const.c bn_x931p.c bn_intern.c bn_dh.c bn_srp.c +INCLUDE[../../libcrypto]=../../crypto/include + +INCLUDE[bn_exp.o]=.. + +GENERATE[bn-586.s]=asm/bn-586.pl \ + $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) +DEPEND[bn-586.s]=../perlasm/x86asm.pl +GENERATE[co-586.s]=asm/co-586.pl \ + $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) +DEPEND[co-586.s]=../perlasm/x86asm.pl +GENERATE[x86-mont.s]=asm/x86-mont.pl \ + $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) +DEPEND[x86-mont.s]=../perlasm/x86asm.pl +GENERATE[x86-gf2m.s]=asm/x86-gf2m.pl \ + $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) +DEPEND[x86-gf2m.s]=../perlasm/x86asm.pl + +GENERATE[sparcv9a-mont.S]=asm/sparcv9a-mont.pl $(PERLASM_SCHEME) +INCLUDE[sparcv9a-mont.o]=.. +GENERATE[sparcv9-mont.S]=asm/sparcv9-mont.pl $(PERLASM_SCHEME) +INCLUDE[sparcv9-mont.o]=.. +GENERATE[vis3-mont.S]=asm/vis3-mont.pl $(PERLASM_SCHEME) +INCLUDE[vis3-mont.o]=.. +GENERATE[sparct4-mont.S]=asm/sparct4-mont.pl $(PERLASM_SCHEME) +INCLUDE[sparct4-mont.o]=.. +GENERATE[sparcv9-gf2m.S]=asm/sparcv9-gf2m.pl $(PERLASM_SCHEME) +INCLUDE[sparcv9-gf2m.o]=.. + +GENERATE[bn-mips.S]=asm/mips.pl $(PERLASM_SCHEME) +INCLUDE[bn-mips.o]=.. +GENERATE[mips-mont.S]=asm/mips-mont.pl $(PERLASM_SCHEME) +INCLUDE[mips-mont.o]=.. + +GENERATE[s390x-mont.S]=asm/s390x-mont.pl $(PERLASM_SCHEME) +GENERATE[s390x-gf2m.s]=asm/s390x-gf2m.pl $(PERLASM_SCHEME) + +GENERATE[x86_64-mont.s]=asm/x86_64-mont.pl $(PERLASM_SCHEME) +GENERATE[x86_64-mont5.s]=asm/x86_64-mont5.pl $(PERLASM_SCHEME) +GENERATE[x86_64-gf2m.s]=asm/x86_64-gf2m.pl $(PERLASM_SCHEME) +GENERATE[rsaz-x86_64.s]=asm/rsaz-x86_64.pl $(PERLASM_SCHEME) +GENERATE[rsaz-avx2.s]=asm/rsaz-avx2.pl $(PERLASM_SCHEME) + +GENERATE[bn-ia64.s]=asm/ia64.S +GENERATE[ia64-mont.s]=asm/ia64-mont.pl $(LIB_CFLAGS) $(LIB_CPPFLAGS) + +GENERATE[parisc-mont.s]=asm/parisc-mont.pl $(PERLASM_SCHEME) + +# ppc - AIX, Linux, MacOS X... +GENERATE[bn-ppc.s]=asm/ppc.pl $(PERLASM_SCHEME) +GENERATE[ppc-mont.s]=asm/ppc-mont.pl $(PERLASM_SCHEME) +GENERATE[ppc64-mont.s]=asm/ppc64-mont.pl $(PERLASM_SCHEME) + +GENERATE[alpha-mont.S]=asm/alpha-mont.pl $(PERLASM_SCHEME) + +GENERATE[armv4-mont.S]=asm/armv4-mont.pl $(PERLASM_SCHEME) +INCLUDE[armv4-mont.o]=.. +GENERATE[armv4-gf2m.S]=asm/armv4-gf2m.pl $(PERLASM_SCHEME) +INCLUDE[armv4-gf2m.o]=.. +GENERATE[armv8-mont.S]=asm/armv8-mont.pl $(PERLASM_SCHEME) diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/rsaz_exp.c b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/rsaz_exp.c new file mode 100644 index 000000000..22455b8a6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/rsaz_exp.c @@ -0,0 +1,315 @@ +/* + * Copyright 2013-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2012, Intel Corporation. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + * + * Originally written by Shay Gueron (1, 2), and Vlad Krasnov (1) + * (1) Intel Corporation, Israel Development Center, Haifa, Israel + * (2) University of Haifa, Israel + */ + +#include +#include "rsaz_exp.h" + +#ifndef RSAZ_ENABLED +NON_EMPTY_TRANSLATION_UNIT +#else + +/* + * See crypto/bn/asm/rsaz-avx2.pl for further details. + */ +void rsaz_1024_norm2red_avx2(void *red, const void *norm); +void rsaz_1024_mul_avx2(void *ret, const void *a, const void *b, + const void *n, BN_ULONG k); +void rsaz_1024_sqr_avx2(void *ret, const void *a, const void *n, BN_ULONG k, + int cnt); +void rsaz_1024_scatter5_avx2(void *tbl, const void *val, int i); +void rsaz_1024_gather5_avx2(void *val, const void *tbl, int i); +void rsaz_1024_red2norm_avx2(void *norm, const void *red); + +#if defined(__GNUC__) +# define ALIGN64 __attribute__((aligned(64))) +#elif defined(_MSC_VER) +# define ALIGN64 __declspec(align(64)) +#elif defined(__SUNPRO_C) +# define ALIGN64 +# pragma align 64(one,two80) +#else +/* not fatal, might hurt performance a little */ +# define ALIGN64 +#endif + +ALIGN64 static const BN_ULONG one[40] = { + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +ALIGN64 static const BN_ULONG two80[40] = { + 0, 0, 1 << 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +void RSAZ_1024_mod_exp_avx2(BN_ULONG result_norm[16], + const BN_ULONG base_norm[16], + const BN_ULONG exponent[16], + const BN_ULONG m_norm[16], const BN_ULONG RR[16], + BN_ULONG k0) +{ + unsigned char storage[320 * 3 + 32 * 9 * 16 + 64]; /* 5.5KB */ + unsigned char *p_str = storage + (64 - ((size_t)storage % 64)); + unsigned char *a_inv, *m, *result; + unsigned char *table_s = p_str + 320 * 3; + unsigned char *R2 = table_s; /* borrow */ + int index; + int wvalue; + + if ((((size_t)p_str & 4095) + 320) >> 12) { + result = p_str; + a_inv = p_str + 320; + m = p_str + 320 * 2; /* should not cross page */ + } else { + m = p_str; /* should not cross page */ + result = p_str + 320; + a_inv = p_str + 320 * 2; + } + + rsaz_1024_norm2red_avx2(m, m_norm); + rsaz_1024_norm2red_avx2(a_inv, base_norm); + rsaz_1024_norm2red_avx2(R2, RR); + + rsaz_1024_mul_avx2(R2, R2, R2, m, k0); + rsaz_1024_mul_avx2(R2, R2, two80, m, k0); + + /* table[0] = 1 */ + rsaz_1024_mul_avx2(result, R2, one, m, k0); + /* table[1] = a_inv^1 */ + rsaz_1024_mul_avx2(a_inv, a_inv, R2, m, k0); + + rsaz_1024_scatter5_avx2(table_s, result, 0); + rsaz_1024_scatter5_avx2(table_s, a_inv, 1); + + /* table[2] = a_inv^2 */ + rsaz_1024_sqr_avx2(result, a_inv, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 2); +#if 0 + /* this is almost 2x smaller and less than 1% slower */ + for (index = 3; index < 32; index++) { + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, index); + } +#else + /* table[4] = a_inv^4 */ + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 4); + /* table[8] = a_inv^8 */ + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 8); + /* table[16] = a_inv^16 */ + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 16); + /* table[17] = a_inv^17 */ + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 17); + + /* table[3] */ + rsaz_1024_gather5_avx2(result, table_s, 2); + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 3); + /* table[6] */ + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 6); + /* table[12] */ + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 12); + /* table[24] */ + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 24); + /* table[25] */ + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 25); + + /* table[5] */ + rsaz_1024_gather5_avx2(result, table_s, 4); + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 5); + /* table[10] */ + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 10); + /* table[20] */ + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 20); + /* table[21] */ + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 21); + + /* table[7] */ + rsaz_1024_gather5_avx2(result, table_s, 6); + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 7); + /* table[14] */ + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 14); + /* table[28] */ + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 28); + /* table[29] */ + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 29); + + /* table[9] */ + rsaz_1024_gather5_avx2(result, table_s, 8); + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 9); + /* table[18] */ + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 18); + /* table[19] */ + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 19); + + /* table[11] */ + rsaz_1024_gather5_avx2(result, table_s, 10); + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 11); + /* table[22] */ + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 22); + /* table[23] */ + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 23); + + /* table[13] */ + rsaz_1024_gather5_avx2(result, table_s, 12); + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 13); + /* table[26] */ + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 26); + /* table[27] */ + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 27); + + /* table[15] */ + rsaz_1024_gather5_avx2(result, table_s, 14); + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 15); + /* table[30] */ + rsaz_1024_sqr_avx2(result, result, m, k0, 1); + rsaz_1024_scatter5_avx2(table_s, result, 30); + /* table[31] */ + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + rsaz_1024_scatter5_avx2(table_s, result, 31); +#endif + + /* load first window */ + p_str = (unsigned char *)exponent; + wvalue = p_str[127] >> 3; + rsaz_1024_gather5_avx2(result, table_s, wvalue); + + index = 1014; + + while (index > -1) { /* loop for the remaining 127 windows */ + + rsaz_1024_sqr_avx2(result, result, m, k0, 5); + + wvalue = (p_str[(index / 8) + 1] << 8) | p_str[index / 8]; + wvalue = (wvalue >> (index % 8)) & 31; + index -= 5; + + rsaz_1024_gather5_avx2(a_inv, table_s, wvalue); /* borrow a_inv */ + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + } + + /* square four times */ + rsaz_1024_sqr_avx2(result, result, m, k0, 4); + + wvalue = p_str[0] & 15; + + rsaz_1024_gather5_avx2(a_inv, table_s, wvalue); /* borrow a_inv */ + rsaz_1024_mul_avx2(result, result, a_inv, m, k0); + + /* from Montgomery */ + rsaz_1024_mul_avx2(result, result, one, m, k0); + + rsaz_1024_red2norm_avx2(result_norm, result); + + OPENSSL_cleanse(storage, sizeof(storage)); +} + +/* + * See crypto/bn/rsaz-x86_64.pl for further details. + */ +void rsaz_512_mul(void *ret, const void *a, const void *b, const void *n, + BN_ULONG k); +void rsaz_512_mul_scatter4(void *ret, const void *a, const void *n, + BN_ULONG k, const void *tbl, unsigned int power); +void rsaz_512_mul_gather4(void *ret, const void *a, const void *tbl, + const void *n, BN_ULONG k, unsigned int power); +void rsaz_512_mul_by_one(void *ret, const void *a, const void *n, BN_ULONG k); +void rsaz_512_sqr(void *ret, const void *a, const void *n, BN_ULONG k, + int cnt); +void rsaz_512_scatter4(void *tbl, const BN_ULONG *val, int power); +void rsaz_512_gather4(BN_ULONG *val, const void *tbl, int power); + +void RSAZ_512_mod_exp(BN_ULONG result[8], + const BN_ULONG base[8], const BN_ULONG exponent[8], + const BN_ULONG m[8], BN_ULONG k0, const BN_ULONG RR[8]) +{ + unsigned char storage[16 * 8 * 8 + 64 * 2 + 64]; /* 1.2KB */ + unsigned char *table = storage + (64 - ((size_t)storage % 64)); + BN_ULONG *a_inv = (BN_ULONG *)(table + 16 * 8 * 8); + BN_ULONG *temp = (BN_ULONG *)(table + 16 * 8 * 8 + 8 * 8); + unsigned char *p_str = (unsigned char *)exponent; + int index; + unsigned int wvalue; + + /* table[0] = 1_inv */ + temp[0] = 0 - m[0]; + temp[1] = ~m[1]; + temp[2] = ~m[2]; + temp[3] = ~m[3]; + temp[4] = ~m[4]; + temp[5] = ~m[5]; + temp[6] = ~m[6]; + temp[7] = ~m[7]; + rsaz_512_scatter4(table, temp, 0); + + /* table [1] = a_inv^1 */ + rsaz_512_mul(a_inv, base, RR, m, k0); + rsaz_512_scatter4(table, a_inv, 1); + + /* table [2] = a_inv^2 */ + rsaz_512_sqr(temp, a_inv, m, k0, 1); + rsaz_512_scatter4(table, temp, 2); + + for (index = 3; index < 16; index++) + rsaz_512_mul_scatter4(temp, a_inv, m, k0, table, index); + + /* load first window */ + wvalue = p_str[63]; + + rsaz_512_gather4(temp, table, wvalue >> 4); + rsaz_512_sqr(temp, temp, m, k0, 4); + rsaz_512_mul_gather4(temp, temp, table, m, k0, wvalue & 0xf); + + for (index = 62; index >= 0; index--) { + wvalue = p_str[index]; + + rsaz_512_sqr(temp, temp, m, k0, 4); + rsaz_512_mul_gather4(temp, temp, table, m, k0, wvalue >> 4); + + rsaz_512_sqr(temp, temp, m, k0, 4); + rsaz_512_mul_gather4(temp, temp, table, m, k0, wvalue & 0x0f); + } + + /* from Montgomery */ + rsaz_512_mul_by_one(result, temp, m, k0); + + OPENSSL_cleanse(storage, sizeof(storage)); +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/bn/rsaz_exp.h b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/rsaz_exp.h new file mode 100644 index 000000000..c5864f8aa --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/bn/rsaz_exp.h @@ -0,0 +1,40 @@ +/* + * Copyright 2013-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2012, Intel Corporation. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + * + * Originally written by Shay Gueron (1, 2), and Vlad Krasnov (1) + * (1) Intel Corporation, Israel Development Center, Haifa, Israel + * (2) University of Haifa, Israel + */ + +#ifndef RSAZ_EXP_H +# define RSAZ_EXP_H + +# undef RSAZ_ENABLED +# if defined(OPENSSL_BN_ASM_MONT) && \ + (defined(__x86_64) || defined(__x86_64__) || \ + defined(_M_AMD64) || defined(_M_X64)) +# define RSAZ_ENABLED + +# include + +void RSAZ_1024_mod_exp_avx2(BN_ULONG result[16], + const BN_ULONG base_norm[16], + const BN_ULONG exponent[16], + const BN_ULONG m_norm[16], const BN_ULONG RR[16], + BN_ULONG k0); +int rsaz_avx2_eligible(void); + +void RSAZ_512_mod_exp(BN_ULONG result[8], + const BN_ULONG base_norm[8], const BN_ULONG exponent[8], + const BN_ULONG m_norm[8], BN_ULONG k0, + const BN_ULONG RR[8]); + +# endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/buffer/buf_err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/buffer/buf_err.c new file mode 100644 index 000000000..7e6e53226 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/buffer/buf_err.c @@ -0,0 +1,38 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA BUF_str_functs[] = { + {ERR_PACK(ERR_LIB_BUF, BUF_F_BUF_MEM_GROW, 0), "BUF_MEM_grow"}, + {ERR_PACK(ERR_LIB_BUF, BUF_F_BUF_MEM_GROW_CLEAN, 0), "BUF_MEM_grow_clean"}, + {ERR_PACK(ERR_LIB_BUF, BUF_F_BUF_MEM_NEW, 0), "BUF_MEM_new"}, + {0, NULL} +}; + +static const ERR_STRING_DATA BUF_str_reasons[] = { + {0, NULL} +}; + +#endif + +int ERR_load_BUF_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(BUF_str_functs[0].error) == NULL) { + ERR_load_strings_const(BUF_str_functs); + ERR_load_strings_const(BUF_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/buffer/buffer.c b/trunk/3rdparty/openssl-1.1-fit/crypto/buffer/buffer.c new file mode 100644 index 000000000..72258abb9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/buffer/buffer.c @@ -0,0 +1,165 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include + +/* + * LIMIT_BEFORE_EXPANSION is the maximum n such that (n+3)/3*4 < 2**31. That + * function is applied in several functions in this file and this limit + * ensures that the result fits in an int. + */ +#define LIMIT_BEFORE_EXPANSION 0x5ffffffc + +BUF_MEM *BUF_MEM_new_ex(unsigned long flags) +{ + BUF_MEM *ret; + + ret = BUF_MEM_new(); + if (ret != NULL) + ret->flags = flags; + return ret; +} + +BUF_MEM *BUF_MEM_new(void) +{ + BUF_MEM *ret; + + ret = OPENSSL_zalloc(sizeof(*ret)); + if (ret == NULL) { + BUFerr(BUF_F_BUF_MEM_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + return ret; +} + +void BUF_MEM_free(BUF_MEM *a) +{ + if (a == NULL) + return; + if (a->data != NULL) { + if (a->flags & BUF_MEM_FLAG_SECURE) + OPENSSL_secure_clear_free(a->data, a->max); + else + OPENSSL_clear_free(a->data, a->max); + } + OPENSSL_free(a); +} + +/* Allocate a block of secure memory; copy over old data if there + * was any, and then free it. */ +static char *sec_alloc_realloc(BUF_MEM *str, size_t len) +{ + char *ret; + + ret = OPENSSL_secure_malloc(len); + if (str->data != NULL) { + if (ret != NULL) { + memcpy(ret, str->data, str->length); + OPENSSL_secure_clear_free(str->data, str->length); + str->data = NULL; + } + } + return ret; +} + +size_t BUF_MEM_grow(BUF_MEM *str, size_t len) +{ + char *ret; + size_t n; + + if (str->length >= len) { + str->length = len; + return len; + } + if (str->max >= len) { + if (str->data != NULL) + memset(&str->data[str->length], 0, len - str->length); + str->length = len; + return len; + } + /* This limit is sufficient to ensure (len+3)/3*4 < 2**31 */ + if (len > LIMIT_BEFORE_EXPANSION) { + BUFerr(BUF_F_BUF_MEM_GROW, ERR_R_MALLOC_FAILURE); + return 0; + } + n = (len + 3) / 3 * 4; + if ((str->flags & BUF_MEM_FLAG_SECURE)) + ret = sec_alloc_realloc(str, n); + else + ret = OPENSSL_realloc(str->data, n); + if (ret == NULL) { + BUFerr(BUF_F_BUF_MEM_GROW, ERR_R_MALLOC_FAILURE); + len = 0; + } else { + str->data = ret; + str->max = n; + memset(&str->data[str->length], 0, len - str->length); + str->length = len; + } + return len; +} + +size_t BUF_MEM_grow_clean(BUF_MEM *str, size_t len) +{ + char *ret; + size_t n; + + if (str->length >= len) { + if (str->data != NULL) + memset(&str->data[len], 0, str->length - len); + str->length = len; + return len; + } + if (str->max >= len) { + memset(&str->data[str->length], 0, len - str->length); + str->length = len; + return len; + } + /* This limit is sufficient to ensure (len+3)/3*4 < 2**31 */ + if (len > LIMIT_BEFORE_EXPANSION) { + BUFerr(BUF_F_BUF_MEM_GROW_CLEAN, ERR_R_MALLOC_FAILURE); + return 0; + } + n = (len + 3) / 3 * 4; + if ((str->flags & BUF_MEM_FLAG_SECURE)) + ret = sec_alloc_realloc(str, n); + else + ret = OPENSSL_clear_realloc(str->data, str->max, n); + if (ret == NULL) { + BUFerr(BUF_F_BUF_MEM_GROW_CLEAN, ERR_R_MALLOC_FAILURE); + len = 0; + } else { + str->data = ret; + str->max = n; + memset(&str->data[str->length], 0, len - str->length); + str->length = len; + } + return len; +} + +void BUF_reverse(unsigned char *out, const unsigned char *in, size_t size) +{ + size_t i; + if (in) { + out += size - 1; + for (i = 0; i < size; i++) + *out-- = *in++; + } else { + unsigned char *q; + char c; + q = out + size - 1; + for (i = 0; i < size / 2; i++) { + c = *q; + *q-- = *out; + *out++ = c; + } + } +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/buffer/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/buffer/build.info new file mode 100644 index 000000000..54da1f92a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/buffer/build.info @@ -0,0 +1,2 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=buffer.c buf_err.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/build.info new file mode 100644 index 000000000..2c619c62e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/build.info @@ -0,0 +1,39 @@ +LIBS=../libcrypto +SOURCE[../libcrypto]=\ + cryptlib.c mem.c mem_dbg.c cversion.c ex_data.c cpt_err.c \ + ebcdic.c uid.c o_time.c o_str.c o_dir.c o_fopen.c ctype.c \ + threads_pthread.c threads_win.c threads_none.c getenv.c \ + o_init.c o_fips.c mem_sec.c init.c {- $target{cpuid_asm_src} -} \ + {- $target{uplink_aux_src} -} +EXTRA= ../ms/uplink-x86.pl ../ms/uplink.c ../ms/applink.c \ + x86cpuid.pl x86_64cpuid.pl ia64cpuid.S \ + ppccpuid.pl pariscid.pl alphacpuid.pl arm64cpuid.pl armv4cpuid.pl + +DEPEND[cversion.o]=buildinf.h +GENERATE[buildinf.h]=../util/mkbuildinf.pl "$(CC) $(LIB_CFLAGS) $(CPPFLAGS_Q)" "$(PLATFORM)" +DEPEND[buildinf.h]=../configdata.pm + +GENERATE[uplink-x86.s]=../ms/uplink-x86.pl $(PERLASM_SCHEME) +GENERATE[uplink-x86_64.s]=../ms/uplink-x86_64.pl $(PERLASM_SCHEME) +GENERATE[uplink-ia64.s]=../ms/uplink-ia64.pl $(PERLASM_SCHEME) + +GENERATE[x86cpuid.s]=x86cpuid.pl \ + $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) +DEPEND[x86cpuid.s]=perlasm/x86asm.pl + +GENERATE[x86_64cpuid.s]=x86_64cpuid.pl $(PERLASM_SCHEME) + +GENERATE[ia64cpuid.s]=ia64cpuid.S +GENERATE[ppccpuid.s]=ppccpuid.pl $(PERLASM_SCHEME) +GENERATE[pariscid.s]=pariscid.pl $(PERLASM_SCHEME) +GENERATE[alphacpuid.s]=alphacpuid.pl +GENERATE[arm64cpuid.S]=arm64cpuid.pl $(PERLASM_SCHEME) +INCLUDE[arm64cpuid.o]=. +GENERATE[armv4cpuid.S]=armv4cpuid.pl $(PERLASM_SCHEME) +INCLUDE[armv4cpuid.o]=. +GENERATE[s390xcpuid.S]=s390xcpuid.pl $(PERLASM_SCHEME) +INCLUDE[s390xcpuid.o]=. + +IF[{- $config{target} =~ /^(?:Cygwin|mingw|VC-)/ -}] + SHARED_SOURCE[../libcrypto]=dllmain.c +ENDIF diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/c64xpluscpuid.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/c64xpluscpuid.pl new file mode 100644 index 000000000..b7b11d503 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/c64xpluscpuid.pl @@ -0,0 +1,287 @@ +#! /usr/bin/env perl +# Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} +open STDOUT,">$output"; + +$code.=<<___; + .text + + .if .ASSEMBLER_VERSION<7000000 + .asg 0,__TI_EABI__ + .endif + .if __TI_EABI__ + .asg OPENSSL_rdtsc,_OPENSSL_rdtsc + .asg OPENSSL_cleanse,_OPENSSL_cleanse + .asg CRYPTO_memcmp,_CRYPTO_memcmp + .asg OPENSSL_atomic_add,_OPENSSL_atomic_add + .asg OPENSSL_wipe_cpu,_OPENSSL_wipe_cpu + .asg OPENSSL_instrument_bus,_OPENSSL_instrument_bus + .asg OPENSSL_instrument_bus2,_OPENSSL_instrument_bus2 + .endif + + .asg B3,RA + + .global _OPENSSL_rdtsc +_OPENSSL_rdtsc: + .asmfunc + B RA + MVC TSCL,B0 + MVC TSCH,B1 + [!B0] MVC B0,TSCL ; start TSC + MV B0,A4 + MV B1,A5 + .endasmfunc + + .global _OPENSSL_cleanse +_OPENSSL_cleanse: + .asmfunc + ZERO A3:A2 +|| ZERO B2 +|| SHRU B4,3,B0 ; is length >= 8 +|| ADD 1,A4,B6 + [!B0] BNOP RA +|| ZERO A1 +|| ZERO B1 + [B0] MVC B0,ILC +||[!B0] CMPLT 0,B4,A1 +||[!B0] CMPLT 1,B4,B1 + [A1] STB A2,*A4++[2] +|| [B1] STB B2,*B6++[2] +||[!B0] CMPLT 2,B4,A1 +||[!B0] CMPLT 3,B4,B1 + [A1] STB A2,*A4++[2] +|| [B1] STB B2,*B6++[2] +||[!B0] CMPLT 4,B4,A1 +||[!B0] CMPLT 5,B4,B1 + [A1] STB A2,*A4++[2] +|| [B1] STB B2,*B6++[2] +||[!B0] CMPLT 6,B4,A1 + [A1] STB A2,*A4++[2] + + SPLOOP 1 + STNDW A3:A2,*A4++ +|| SUB B4,8,B4 + SPKERNEL + + MV B4,B0 ; remaining bytes +|| ADD 1,A4,B6 +|| BNOP RA + [B0] CMPLT 0,B0,A1 +|| [B0] CMPLT 1,B0,B1 + [A1] STB A2,*A4++[2] +|| [B1] STB B2,*B6++[2] +|| [B0] CMPLT 2,B0,A1 +|| [B0] CMPLT 3,B0,B1 + [A1] STB A2,*A4++[2] +|| [B1] STB B2,*B6++[2] +|| [B0] CMPLT 4,B0,A1 +|| [B0] CMPLT 5,B0,B1 + [A1] STB A2,*A4++[2] +|| [B1] STB B2,*B6++[2] +|| [B0] CMPLT 6,B0,A1 + [A1] STB A2,*A4++[2] + .endasmfunc + + .global _CRYPTO_memcmp +_CRYPTO_memcmp: + .asmfunc + MV A6,B0 + [!B0] BNOP RA +||[!B0] ZERO A4 + [B0] MVC B0,ILC +|| [B0] ZERO A0 + NOP 4 + + SPLOOP 1 + LDBU *A4++,A1 +|| LDBU *B4++,B1 + NOP 4 + XOR.L B1,A1,A2 + SPKERNEL 1,0 +|| OR.S A2,A0,A0 + + BNOP RA,3 + ZERO.L A4 + [A0] MVK 1,A4 + .endasmfunc + + .global _OPENSSL_atomic_add +_OPENSSL_atomic_add: + .asmfunc + MV A4,B0 +atomic_add?: + LL *B0,B5 + NOP 4 + ADD B4,B5,B5 + SL B5,*B0 + CMTL *B0,B1 + NOP 4 + [!B1] B atomic_add? + [B1] BNOP RA,4 + MV B5,A4 + .endasmfunc + + .global _OPENSSL_wipe_cpu +_OPENSSL_wipe_cpu: + .asmfunc + ZERO A0 +|| ZERO B0 +|| ZERO A1 +|| ZERO B1 + ZERO A3:A2 +|| MVD B0,B2 +|| ZERO A4 +|| ZERO B4 +|| ZERO A5 +|| ZERO B5 +|| BNOP RA + ZERO A7:A6 +|| ZERO B7:B6 +|| ZERO A8 +|| ZERO B8 +|| ZERO A9 +|| ZERO B9 + ZERO A17:A16 +|| ZERO B17:B16 +|| ZERO A18 +|| ZERO B18 +|| ZERO A19 +|| ZERO B19 + ZERO A21:A20 +|| ZERO B21:B20 +|| ZERO A22 +|| ZERO B22 +|| ZERO A23 +|| ZERO B23 + ZERO A25:A24 +|| ZERO B25:B24 +|| ZERO A26 +|| ZERO B26 +|| ZERO A27 +|| ZERO B27 + ZERO A29:A28 +|| ZERO B29:B28 +|| ZERO A30 +|| ZERO B30 +|| ZERO A31 +|| ZERO B31 + .endasmfunc + +CLFLUSH .macro CONTROL,ADDR,LEN + B passthrough? +|| STW ADDR,*CONTROL[0] + STW LEN,*CONTROL[1] +spinlock?: + LDW *CONTROL[1],A0 + NOP 3 +passthrough?: + NOP + [A0] BNOP spinlock?,5 + .endm + + .global _OPENSSL_instrument_bus +_OPENSSL_instrument_bus: + .asmfunc + MV B4,B0 ; reassign sizeof(output) +|| MV A4,B4 ; reassign output +|| MVK 0x00004030,A3 + MV B0,A4 ; return value +|| MVK 1,A1 +|| MVKH 0x01840000,A3 ; L1DWIBAR + MVC TSCL,B8 ; collect 1st tick +|| MVK 0x00004010,A5 + MV B8,B9 ; lasttick = tick +|| MVK 0,B7 ; lastdiff = 0 +|| MVKH 0x01840000,A5 ; L2WIBAR + CLFLUSH A3,B4,A1 ; write-back and invalidate L1D line + CLFLUSH A5,B4,A1 ; write-back and invalidate L2 line + LL *B4,B5 + NOP 4 + ADD B7,B5,B5 + SL B5,*B4 + CMTL *B4,B1 + NOP 4 + STW B5,*B4 +bus_loop1?: + MVC TSCL,B8 +|| [B0] SUB B0,1,B0 + SUB B8,B9,B7 ; lastdiff = tick - lasttick +|| MV B8,B9 ; lasttick = tick + CLFLUSH A3,B4,A1 ; write-back and invalidate L1D line + CLFLUSH A5,B4,A1 ; write-back and invalidate L2 line + LL *B4,B5 + NOP 4 + ADD B7,B5,B5 + SL B5,*B4 + CMTL *B4,B1 + STW B5,*B4 ; [!B1] is removed to flatten samples +|| ADDK 4,B4 +|| [B0] BNOP bus_loop1?,5 + + BNOP RA,5 + .endasmfunc + + .global _OPENSSL_instrument_bus2 +_OPENSSL_instrument_bus2: + .asmfunc + MV A6,B0 ; reassign max +|| MV B4,A6 ; reassign sizeof(output) +|| MVK 0x00004030,A3 + MV A4,B4 ; reassign output +|| MVK 0,A4 ; return value +|| MVK 1,A1 +|| MVKH 0x01840000,A3 ; L1DWIBAR + + MVC TSCL,B8 ; collect 1st tick +|| MVK 0x00004010,A5 + MV B8,B9 ; lasttick = tick +|| MVK 0,B7 ; lastdiff = 0 +|| MVKH 0x01840000,A5 ; L2WIBAR + CLFLUSH A3,B4,A1 ; write-back and invalidate L1D line + CLFLUSH A5,B4,A1 ; write-back and invalidate L2 line + LL *B4,B5 + NOP 4 + ADD B7,B5,B5 + SL B5,*B4 + CMTL *B4,B1 + NOP 4 + STW B5,*B4 + + MVC TSCL,B8 ; collect 1st diff + SUB B8,B9,B7 ; lastdiff = tick - lasttick +|| MV B8,B9 ; lasttick = tick +|| SUB B0,1,B0 +bus_loop2?: + CLFLUSH A3,B4,A1 ; write-back and invalidate L1D line + CLFLUSH A5,B4,A1 ; write-back and invalidate L2 line + LL *B4,B5 + NOP 4 + ADD B7,B5,B5 + SL B5,*B4 + CMTL *B4,B1 + STW B5,*B4 ; [!B1] is removed to flatten samples +||[!B0] BNOP bus_loop2_done?,2 +|| SUB B0,1,B0 + MVC TSCL,B8 + SUB B8,B9,B8 +|| MV B8,B9 + CMPEQ B8,B7,B2 +|| MV B8,B7 + [!B2] ADDAW B4,1,B4 +||[!B2] ADDK 1,A4 + CMPEQ A4,A6,A2 + [!A2] BNOP bus_loop2?,5 + +bus_loop2_done?: + BNOP RA,5 + .endasmfunc +___ + +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/asm/cmll-x86.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/asm/cmll-x86.pl new file mode 100644 index 000000000..55af9b4e3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/asm/cmll-x86.pl @@ -0,0 +1,1150 @@ +#! /usr/bin/env perl +# Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Copyright (c) 2008 Andy Polyakov +# +# This module may be used under the terms of either the GNU General +# Public License version 2 or later, the GNU Lesser General Public +# License version 2.1 or later, the Mozilla Public License version +# 1.1 or the BSD License. The exact terms of either license are +# distributed along with this module. For further details see +# http://www.openssl.org/~appro/camellia/. +# ==================================================================== + +# Performance in cycles per processed byte (less is better) in +# 'openssl speed ...' benchmark: +# +# AMD K8 Core2 PIII P4 +# -evp camellia-128-ecb 21.5 22.8 27.0 28.9 +# + over gcc 3.4.6 +90/11% +70/10% +53/4% +160/64% +# + over icc 8.0 +48/19% +21/15% +21/17% +55/37% +# +# camellia-128-cbc 17.3 21.1 23.9 25.9 +# +# 128-bit key setup 196 280 256 240 cycles/key +# + over gcc 3.4.6 +30/0% +17/11% +11/0% +63/40% +# + over icc 8.0 +18/3% +10/0% +10/3% +21/10% +# +# Pairs of numbers in "+" rows represent performance improvement over +# compiler generated position-independent code, PIC, and non-PIC +# respectively. PIC results are of greater relevance, as this module +# is position-independent, i.e. suitable for a shared library or PIE. +# Position independence "costs" one register, which is why compilers +# are so close with non-PIC results, they have an extra register to +# spare. CBC results are better than ECB ones thanks to "zero-copy" +# private _x86_* interface, and are ~30-40% better than with compiler +# generated cmll_cbc.o, and reach ~80-90% of x86_64 performance on +# same CPU (where applicable). + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +$OPENSSL=1; + +$output = pop; +open STDOUT,">$output"; + +&asm_init($ARGV[0],$ARGV[$#ARGV] eq "386"); + +@T=("eax","ebx","ecx","edx"); +$idx="esi"; +$key="edi"; +$Tbl="ebp"; + +# stack frame layout in _x86_Camellia_* routines, frame is allocated +# by caller +$__ra=&DWP(0,"esp"); # return address +$__s0=&DWP(4,"esp"); # s0 backing store +$__s1=&DWP(8,"esp"); # s1 backing store +$__s2=&DWP(12,"esp"); # s2 backing store +$__s3=&DWP(16,"esp"); # s3 backing store +$__end=&DWP(20,"esp"); # pointer to end/start of key schedule + +# stack frame layout in Camellia_[en|crypt] routines, which differs from +# above by 4 and overlaps by pointer to end/start of key schedule +$_end=&DWP(16,"esp"); +$_esp=&DWP(20,"esp"); + +# const unsigned int Camellia_SBOX[4][256]; +# Well, sort of... Camellia_SBOX[0][] is interleaved with [1][], +# and [2][] - with [3][]. This is done to optimize code size. +$SBOX1_1110=0; # Camellia_SBOX[0] +$SBOX4_4404=4; # Camellia_SBOX[1] +$SBOX2_0222=2048; # Camellia_SBOX[2] +$SBOX3_3033=2052; # Camellia_SBOX[3] +&static_label("Camellia_SIGMA"); +&static_label("Camellia_SBOX"); + +sub Camellia_Feistel { +my $i=@_[0]; +my $seed=defined(@_[1])?@_[1]:0; +my $scale=$seed<0?-8:8; +my $frame=defined(@_[2])?@_[2]:0; +my $j=($i&1)*2; +my $t0=@T[($j)%4],$t1=@T[($j+1)%4],$t2=@T[($j+2)%4],$t3=@T[($j+3)%4]; + + &xor ($t0,$idx); # t0^=key[0] + &xor ($t1,&DWP($seed+$i*$scale+4,$key)); # t1^=key[1] + &movz ($idx,&HB($t0)); # (t0>>8)&0xff + &mov ($t3,&DWP($SBOX3_3033,$Tbl,$idx,8)); # t3=SBOX3_3033[0] + &movz ($idx,&LB($t0)); # (t0>>0)&0xff + &xor ($t3,&DWP($SBOX4_4404,$Tbl,$idx,8)); # t3^=SBOX4_4404[0] + &shr ($t0,16); + &movz ($idx,&LB($t1)); # (t1>>0)&0xff + &mov ($t2,&DWP($SBOX1_1110,$Tbl,$idx,8)); # t2=SBOX1_1110[1] + &movz ($idx,&HB($t0)); # (t0>>24)&0xff + &xor ($t3,&DWP($SBOX1_1110,$Tbl,$idx,8)); # t3^=SBOX1_1110[0] + &movz ($idx,&HB($t1)); # (t1>>8)&0xff + &xor ($t2,&DWP($SBOX4_4404,$Tbl,$idx,8)); # t2^=SBOX4_4404[1] + &shr ($t1,16); + &movz ($t0,&LB($t0)); # (t0>>16)&0xff + &xor ($t3,&DWP($SBOX2_0222,$Tbl,$t0,8)); # t3^=SBOX2_0222[0] + &movz ($idx,&HB($t1)); # (t1>>24)&0xff + &mov ($t0,&DWP($frame+4*(($j+3)%4),"esp")); # prefetch "s3" + &xor ($t2,$t3); # t2^=t3 + &rotr ($t3,8); # t3=RightRotate(t3,8) + &xor ($t2,&DWP($SBOX2_0222,$Tbl,$idx,8)); # t2^=SBOX2_0222[1] + &movz ($idx,&LB($t1)); # (t1>>16)&0xff + &mov ($t1,&DWP($frame+4*(($j+2)%4),"esp")); # prefetch "s2" + &xor ($t3,$t0); # t3^=s3 + &xor ($t2,&DWP($SBOX3_3033,$Tbl,$idx,8)); # t2^=SBOX3_3033[1] + &mov ($idx,&DWP($seed+($i+1)*$scale,$key)); # prefetch key[i+1] + &xor ($t3,$t2); # t3^=t2 + &mov (&DWP($frame+4*(($j+3)%4),"esp"),$t3); # s3=t3 + &xor ($t2,$t1); # t2^=s2 + &mov (&DWP($frame+4*(($j+2)%4),"esp"),$t2); # s2=t2 +} + +# void Camellia_EncryptBlock_Rounds( +# int grandRounds, +# const Byte plaintext[], +# const KEY_TABLE_TYPE keyTable, +# Byte ciphertext[]) +&function_begin("Camellia_EncryptBlock_Rounds"); + &mov ("eax",&wparam(0)); # load grandRounds + &mov ($idx,&wparam(1)); # load plaintext pointer + &mov ($key,&wparam(2)); # load key schedule pointer + + &mov ("ebx","esp"); + &sub ("esp",7*4); # place for s[0-3],keyEnd,esp and ra + &and ("esp",-64); + + # place stack frame just "above mod 1024" the key schedule + # this ensures that cache associativity of 2 suffices + &lea ("ecx",&DWP(-64-63,$key)); + &sub ("ecx","esp"); + &neg ("ecx"); + &and ("ecx",0x3C0); # modulo 1024, but aligned to cache-line + &sub ("esp","ecx"); + &add ("esp",4); # 4 is reserved for callee's return address + + &shl ("eax",6); + &lea ("eax",&DWP(0,$key,"eax")); + &mov ($_esp,"ebx"); # save %esp + &mov ($_end,"eax"); # save keyEnd + + &call (&label("pic_point")); + &set_label("pic_point"); + &blindpop($Tbl); + &lea ($Tbl,&DWP(&label("Camellia_SBOX")."-".&label("pic_point"),$Tbl)); + + &mov (@T[0],&DWP(0,$idx)); # load plaintext + &mov (@T[1],&DWP(4,$idx)); + &mov (@T[2],&DWP(8,$idx)); + &bswap (@T[0]); + &mov (@T[3],&DWP(12,$idx)); + &bswap (@T[1]); + &bswap (@T[2]); + &bswap (@T[3]); + + &call ("_x86_Camellia_encrypt"); + + &mov ("esp",$_esp); + &bswap (@T[0]); + &mov ($idx,&wparam(3)); # load ciphertext pointer + &bswap (@T[1]); + &bswap (@T[2]); + &bswap (@T[3]); + &mov (&DWP(0,$idx),@T[0]); # write ciphertext + &mov (&DWP(4,$idx),@T[1]); + &mov (&DWP(8,$idx),@T[2]); + &mov (&DWP(12,$idx),@T[3]); +&function_end("Camellia_EncryptBlock_Rounds"); +# V1.x API +&function_begin_B("Camellia_EncryptBlock"); + &mov ("eax",128); + &sub ("eax",&wparam(0)); # load keyBitLength + &mov ("eax",3); + &adc ("eax",0); # keyBitLength==128?3:4 + &mov (&wparam(0),"eax"); + &jmp (&label("Camellia_EncryptBlock_Rounds")); +&function_end_B("Camellia_EncryptBlock"); + +if ($OPENSSL) { +# void Camellia_encrypt( +# const unsigned char *in, +# unsigned char *out, +# const CAMELLIA_KEY *key) +&function_begin("Camellia_encrypt"); + &mov ($idx,&wparam(0)); # load plaintext pointer + &mov ($key,&wparam(2)); # load key schedule pointer + + &mov ("ebx","esp"); + &sub ("esp",7*4); # place for s[0-3],keyEnd,esp and ra + &and ("esp",-64); + &mov ("eax",&DWP(272,$key)); # load grandRounds counter + + # place stack frame just "above mod 1024" the key schedule + # this ensures that cache associativity of 2 suffices + &lea ("ecx",&DWP(-64-63,$key)); + &sub ("ecx","esp"); + &neg ("ecx"); + &and ("ecx",0x3C0); # modulo 1024, but aligned to cache-line + &sub ("esp","ecx"); + &add ("esp",4); # 4 is reserved for callee's return address + + &shl ("eax",6); + &lea ("eax",&DWP(0,$key,"eax")); + &mov ($_esp,"ebx"); # save %esp + &mov ($_end,"eax"); # save keyEnd + + &call (&label("pic_point")); + &set_label("pic_point"); + &blindpop($Tbl); + &lea ($Tbl,&DWP(&label("Camellia_SBOX")."-".&label("pic_point"),$Tbl)); + + &mov (@T[0],&DWP(0,$idx)); # load plaintext + &mov (@T[1],&DWP(4,$idx)); + &mov (@T[2],&DWP(8,$idx)); + &bswap (@T[0]); + &mov (@T[3],&DWP(12,$idx)); + &bswap (@T[1]); + &bswap (@T[2]); + &bswap (@T[3]); + + &call ("_x86_Camellia_encrypt"); + + &mov ("esp",$_esp); + &bswap (@T[0]); + &mov ($idx,&wparam(1)); # load ciphertext pointer + &bswap (@T[1]); + &bswap (@T[2]); + &bswap (@T[3]); + &mov (&DWP(0,$idx),@T[0]); # write ciphertext + &mov (&DWP(4,$idx),@T[1]); + &mov (&DWP(8,$idx),@T[2]); + &mov (&DWP(12,$idx),@T[3]); +&function_end("Camellia_encrypt"); +} + +&function_begin_B("_x86_Camellia_encrypt"); + &xor (@T[0],&DWP(0,$key)); # ^=key[0-3] + &xor (@T[1],&DWP(4,$key)); + &xor (@T[2],&DWP(8,$key)); + &xor (@T[3],&DWP(12,$key)); + &mov ($idx,&DWP(16,$key)); # prefetch key[4] + + &mov ($__s0,@T[0]); # save s[0-3] + &mov ($__s1,@T[1]); + &mov ($__s2,@T[2]); + &mov ($__s3,@T[3]); + +&set_label("loop",16); + for ($i=0;$i<6;$i++) { Camellia_Feistel($i,16,4); } + + &add ($key,16*4); + &cmp ($key,$__end); + &je (&label("done")); + + # @T[0-1] are preloaded, $idx is preloaded with key[0] + &and ($idx,@T[0]); + &mov (@T[3],$__s3); + &rotl ($idx,1); + &mov (@T[2],@T[3]); + &xor (@T[1],$idx); + &or (@T[2],&DWP(12,$key)); + &mov ($__s1,@T[1]); # s1^=LeftRotate(s0&key[0],1); + &xor (@T[2],$__s2); + + &mov ($idx,&DWP(4,$key)); + &mov ($__s2,@T[2]); # s2^=s3|key[3]; + &or ($idx,@T[1]); + &and (@T[2],&DWP(8,$key)); + &xor (@T[0],$idx); + &rotl (@T[2],1); + &mov ($__s0,@T[0]); # s0^=s1|key[1]; + &xor (@T[3],@T[2]); + &mov ($idx,&DWP(16,$key)); # prefetch key[4] + &mov ($__s3,@T[3]); # s3^=LeftRotate(s2&key[2],1); + &jmp (&label("loop")); + +&set_label("done",8); + &mov (@T[2],@T[0]); # SwapHalf + &mov (@T[3],@T[1]); + &mov (@T[0],$__s2); + &mov (@T[1],$__s3); + &xor (@T[0],$idx); # $idx is preloaded with key[0] + &xor (@T[1],&DWP(4,$key)); + &xor (@T[2],&DWP(8,$key)); + &xor (@T[3],&DWP(12,$key)); + &ret (); +&function_end_B("_x86_Camellia_encrypt"); + +# void Camellia_DecryptBlock_Rounds( +# int grandRounds, +# const Byte ciphertext[], +# const KEY_TABLE_TYPE keyTable, +# Byte plaintext[]) +&function_begin("Camellia_DecryptBlock_Rounds"); + &mov ("eax",&wparam(0)); # load grandRounds + &mov ($idx,&wparam(1)); # load ciphertext pointer + &mov ($key,&wparam(2)); # load key schedule pointer + + &mov ("ebx","esp"); + &sub ("esp",7*4); # place for s[0-3],keyEnd,esp and ra + &and ("esp",-64); + + # place stack frame just "above mod 1024" the key schedule + # this ensures that cache associativity of 2 suffices + &lea ("ecx",&DWP(-64-63,$key)); + &sub ("ecx","esp"); + &neg ("ecx"); + &and ("ecx",0x3C0); # modulo 1024, but aligned to cache-line + &sub ("esp","ecx"); + &add ("esp",4); # 4 is reserved for callee's return address + + &shl ("eax",6); + &mov (&DWP(4*4,"esp"),$key); # save keyStart + &lea ($key,&DWP(0,$key,"eax")); + &mov (&DWP(5*4,"esp"),"ebx");# save %esp + + &call (&label("pic_point")); + &set_label("pic_point"); + &blindpop($Tbl); + &lea ($Tbl,&DWP(&label("Camellia_SBOX")."-".&label("pic_point"),$Tbl)); + + &mov (@T[0],&DWP(0,$idx)); # load ciphertext + &mov (@T[1],&DWP(4,$idx)); + &mov (@T[2],&DWP(8,$idx)); + &bswap (@T[0]); + &mov (@T[3],&DWP(12,$idx)); + &bswap (@T[1]); + &bswap (@T[2]); + &bswap (@T[3]); + + &call ("_x86_Camellia_decrypt"); + + &mov ("esp",&DWP(5*4,"esp")); + &bswap (@T[0]); + &mov ($idx,&wparam(3)); # load plaintext pointer + &bswap (@T[1]); + &bswap (@T[2]); + &bswap (@T[3]); + &mov (&DWP(0,$idx),@T[0]); # write plaintext + &mov (&DWP(4,$idx),@T[1]); + &mov (&DWP(8,$idx),@T[2]); + &mov (&DWP(12,$idx),@T[3]); +&function_end("Camellia_DecryptBlock_Rounds"); +# V1.x API +&function_begin_B("Camellia_DecryptBlock"); + &mov ("eax",128); + &sub ("eax",&wparam(0)); # load keyBitLength + &mov ("eax",3); + &adc ("eax",0); # keyBitLength==128?3:4 + &mov (&wparam(0),"eax"); + &jmp (&label("Camellia_DecryptBlock_Rounds")); +&function_end_B("Camellia_DecryptBlock"); + +if ($OPENSSL) { +# void Camellia_decrypt( +# const unsigned char *in, +# unsigned char *out, +# const CAMELLIA_KEY *key) +&function_begin("Camellia_decrypt"); + &mov ($idx,&wparam(0)); # load ciphertext pointer + &mov ($key,&wparam(2)); # load key schedule pointer + + &mov ("ebx","esp"); + &sub ("esp",7*4); # place for s[0-3],keyEnd,esp and ra + &and ("esp",-64); + &mov ("eax",&DWP(272,$key)); # load grandRounds counter + + # place stack frame just "above mod 1024" the key schedule + # this ensures that cache associativity of 2 suffices + &lea ("ecx",&DWP(-64-63,$key)); + &sub ("ecx","esp"); + &neg ("ecx"); + &and ("ecx",0x3C0); # modulo 1024, but aligned to cache-line + &sub ("esp","ecx"); + &add ("esp",4); # 4 is reserved for callee's return address + + &shl ("eax",6); + &mov (&DWP(4*4,"esp"),$key); # save keyStart + &lea ($key,&DWP(0,$key,"eax")); + &mov (&DWP(5*4,"esp"),"ebx");# save %esp + + &call (&label("pic_point")); + &set_label("pic_point"); + &blindpop($Tbl); + &lea ($Tbl,&DWP(&label("Camellia_SBOX")."-".&label("pic_point"),$Tbl)); + + &mov (@T[0],&DWP(0,$idx)); # load ciphertext + &mov (@T[1],&DWP(4,$idx)); + &mov (@T[2],&DWP(8,$idx)); + &bswap (@T[0]); + &mov (@T[3],&DWP(12,$idx)); + &bswap (@T[1]); + &bswap (@T[2]); + &bswap (@T[3]); + + &call ("_x86_Camellia_decrypt"); + + &mov ("esp",&DWP(5*4,"esp")); + &bswap (@T[0]); + &mov ($idx,&wparam(1)); # load plaintext pointer + &bswap (@T[1]); + &bswap (@T[2]); + &bswap (@T[3]); + &mov (&DWP(0,$idx),@T[0]); # write plaintext + &mov (&DWP(4,$idx),@T[1]); + &mov (&DWP(8,$idx),@T[2]); + &mov (&DWP(12,$idx),@T[3]); +&function_end("Camellia_decrypt"); +} + +&function_begin_B("_x86_Camellia_decrypt"); + &xor (@T[0],&DWP(0,$key)); # ^=key[0-3] + &xor (@T[1],&DWP(4,$key)); + &xor (@T[2],&DWP(8,$key)); + &xor (@T[3],&DWP(12,$key)); + &mov ($idx,&DWP(-8,$key)); # prefetch key[-2] + + &mov ($__s0,@T[0]); # save s[0-3] + &mov ($__s1,@T[1]); + &mov ($__s2,@T[2]); + &mov ($__s3,@T[3]); + +&set_label("loop",16); + for ($i=0;$i<6;$i++) { Camellia_Feistel($i,-8,4); } + + &sub ($key,16*4); + &cmp ($key,$__end); + &je (&label("done")); + + # @T[0-1] are preloaded, $idx is preloaded with key[2] + &and ($idx,@T[0]); + &mov (@T[3],$__s3); + &rotl ($idx,1); + &mov (@T[2],@T[3]); + &xor (@T[1],$idx); + &or (@T[2],&DWP(4,$key)); + &mov ($__s1,@T[1]); # s1^=LeftRotate(s0&key[0],1); + &xor (@T[2],$__s2); + + &mov ($idx,&DWP(12,$key)); + &mov ($__s2,@T[2]); # s2^=s3|key[3]; + &or ($idx,@T[1]); + &and (@T[2],&DWP(0,$key)); + &xor (@T[0],$idx); + &rotl (@T[2],1); + &mov ($__s0,@T[0]); # s0^=s1|key[1]; + &xor (@T[3],@T[2]); + &mov ($idx,&DWP(-8,$key)); # prefetch key[4] + &mov ($__s3,@T[3]); # s3^=LeftRotate(s2&key[2],1); + &jmp (&label("loop")); + +&set_label("done",8); + &mov (@T[2],@T[0]); # SwapHalf + &mov (@T[3],@T[1]); + &mov (@T[0],$__s2); + &mov (@T[1],$__s3); + &xor (@T[2],$idx); # $idx is preloaded with key[2] + &xor (@T[3],&DWP(12,$key)); + &xor (@T[0],&DWP(0,$key)); + &xor (@T[1],&DWP(4,$key)); + &ret (); +&function_end_B("_x86_Camellia_decrypt"); + +# shld is very slow on Intel P4 family. Even on AMD it limits +# instruction decode rate [because it's VectorPath] and consequently +# performance. PIII, PM and Core[2] seem to be the only ones which +# execute this code ~7% faster... +sub __rotl128 { + my ($i0,$i1,$i2,$i3,$rot,$rnd,@T)=@_; + + $rnd *= 2; + if ($rot) { + &mov ($idx,$i0); + &shld ($i0,$i1,$rot); + &shld ($i1,$i2,$rot); + &shld ($i2,$i3,$rot); + &shld ($i3,$idx,$rot); + } + &mov (&DWP(-128+4*$rnd++,$key),shift(@T)) if ($i0 eq @T[0]); + &mov (&DWP(-128+4*$rnd++,$key),shift(@T)) if ($i1 eq @T[0]); + &mov (&DWP(-128+4*$rnd++,$key),shift(@T)) if ($i2 eq @T[0]); + &mov (&DWP(-128+4*$rnd++,$key),shift(@T)) if ($i3 eq @T[0]); +} + +# ... Implementing 128-bit rotate without shld gives >3x performance +# improvement on P4, only ~7% degradation on other Intel CPUs and +# not worse performance on AMD. This is therefore preferred. +sub _rotl128 { + my ($i0,$i1,$i2,$i3,$rot,$rnd,@T)=@_; + + $rnd *= 2; + if ($rot) { + &mov ($Tbl,$i0); + &shl ($i0,$rot); + &mov ($idx,$i1); + &shr ($idx,32-$rot); + &shl ($i1,$rot); + &or ($i0,$idx); + &mov ($idx,$i2); + &shl ($i2,$rot); + &mov (&DWP(-128+4*$rnd++,$key),shift(@T)) if ($i0 eq @T[0]); + &shr ($idx,32-$rot); + &or ($i1,$idx); + &shr ($Tbl,32-$rot); + &mov ($idx,$i3); + &shr ($idx,32-$rot); + &mov (&DWP(-128+4*$rnd++,$key),shift(@T)) if ($i1 eq @T[0]); + &shl ($i3,$rot); + &or ($i2,$idx); + &or ($i3,$Tbl); + &mov (&DWP(-128+4*$rnd++,$key),shift(@T)) if ($i2 eq @T[0]); + &mov (&DWP(-128+4*$rnd++,$key),shift(@T)) if ($i3 eq @T[0]); + } else { + &mov (&DWP(-128+4*$rnd++,$key),shift(@T)) if ($i0 eq @T[0]); + &mov (&DWP(-128+4*$rnd++,$key),shift(@T)) if ($i1 eq @T[0]); + &mov (&DWP(-128+4*$rnd++,$key),shift(@T)) if ($i2 eq @T[0]); + &mov (&DWP(-128+4*$rnd++,$key),shift(@T)) if ($i3 eq @T[0]); + } +} + +sub _saveround { +my ($rnd,$key,@T)=@_; +my $bias=int(@T[0])?shift(@T):0; + + &mov (&DWP($bias+$rnd*8+0,$key),@T[0]); + &mov (&DWP($bias+$rnd*8+4,$key),@T[1]) if ($#T>=1); + &mov (&DWP($bias+$rnd*8+8,$key),@T[2]) if ($#T>=2); + &mov (&DWP($bias+$rnd*8+12,$key),@T[3]) if ($#T>=3); +} + +sub _loadround { +my ($rnd,$key,@T)=@_; +my $bias=int(@T[0])?shift(@T):0; + + &mov (@T[0],&DWP($bias+$rnd*8+0,$key)); + &mov (@T[1],&DWP($bias+$rnd*8+4,$key)) if ($#T>=1); + &mov (@T[2],&DWP($bias+$rnd*8+8,$key)) if ($#T>=2); + &mov (@T[3],&DWP($bias+$rnd*8+12,$key)) if ($#T>=3); +} + +# void Camellia_Ekeygen( +# const int keyBitLength, +# const Byte *rawKey, +# KEY_TABLE_TYPE keyTable) +&function_begin("Camellia_Ekeygen"); +{ my $step=0; + + &stack_push(4); # place for s[0-3] + + &mov ($Tbl,&wparam(0)); # load arguments + &mov ($idx,&wparam(1)); + &mov ($key,&wparam(2)); + + &mov (@T[0],&DWP(0,$idx)); # load 0-127 bits + &mov (@T[1],&DWP(4,$idx)); + &mov (@T[2],&DWP(8,$idx)); + &mov (@T[3],&DWP(12,$idx)); + + &bswap (@T[0]); + &bswap (@T[1]); + &bswap (@T[2]); + &bswap (@T[3]); + + &_saveround (0,$key,@T); # KL<<<0 + + &cmp ($Tbl,128); + &je (&label("1st128")); + + &mov (@T[0],&DWP(16,$idx)); # load 128-191 bits + &mov (@T[1],&DWP(20,$idx)); + &cmp ($Tbl,192); + &je (&label("1st192")); + &mov (@T[2],&DWP(24,$idx)); # load 192-255 bits + &mov (@T[3],&DWP(28,$idx)); + &jmp (&label("1st256")); +&set_label("1st192",4); + &mov (@T[2],@T[0]); + &mov (@T[3],@T[1]); + ¬ (@T[2]); + ¬ (@T[3]); +&set_label("1st256",4); + &bswap (@T[0]); + &bswap (@T[1]); + &bswap (@T[2]); + &bswap (@T[3]); + + &_saveround (4,$key,@T); # temporary storage for KR! + + &xor (@T[0],&DWP(0*8+0,$key)); # KR^KL + &xor (@T[1],&DWP(0*8+4,$key)); + &xor (@T[2],&DWP(1*8+0,$key)); + &xor (@T[3],&DWP(1*8+4,$key)); + +&set_label("1st128",4); + &call (&label("pic_point")); + &set_label("pic_point"); + &blindpop($Tbl); + &lea ($Tbl,&DWP(&label("Camellia_SBOX")."-".&label("pic_point"),$Tbl)); + &lea ($key,&DWP(&label("Camellia_SIGMA")."-".&label("Camellia_SBOX"),$Tbl)); + + &mov ($idx,&DWP($step*8,$key)); # prefetch SIGMA[0] + &mov (&swtmp(0),@T[0]); # save s[0-3] + &mov (&swtmp(1),@T[1]); + &mov (&swtmp(2),@T[2]); + &mov (&swtmp(3),@T[3]); + &Camellia_Feistel($step++); + &Camellia_Feistel($step++); + &mov (@T[2],&swtmp(2)); + &mov (@T[3],&swtmp(3)); + + &mov ($idx,&wparam(2)); + &xor (@T[0],&DWP(0*8+0,$idx)); # ^KL + &xor (@T[1],&DWP(0*8+4,$idx)); + &xor (@T[2],&DWP(1*8+0,$idx)); + &xor (@T[3],&DWP(1*8+4,$idx)); + + &mov ($idx,&DWP($step*8,$key)); # prefetch SIGMA[4] + &mov (&swtmp(0),@T[0]); # save s[0-3] + &mov (&swtmp(1),@T[1]); + &mov (&swtmp(2),@T[2]); + &mov (&swtmp(3),@T[3]); + &Camellia_Feistel($step++); + &Camellia_Feistel($step++); + &mov (@T[2],&swtmp(2)); + &mov (@T[3],&swtmp(3)); + + &mov ($idx,&wparam(0)); + &cmp ($idx,128); + &jne (&label("2nd256")); + + &mov ($key,&wparam(2)); + &lea ($key,&DWP(128,$key)); # size optimization + + ####### process KA + &_saveround (2,$key,-128,@T); # KA<<<0 + &_rotl128 (@T,15,6,@T); # KA<<<15 + &_rotl128 (@T,15,8,@T); # KA<<<(15+15=30) + &_rotl128 (@T,15,12,@T[0],@T[1]); # KA<<<(30+15=45) + &_rotl128 (@T,15,14,@T); # KA<<<(45+15=60) + push (@T,shift(@T)); # rotl128(@T,32); + &_rotl128 (@T,2,20,@T); # KA<<<(60+32+2=94) + &_rotl128 (@T,17,24,@T); # KA<<<(94+17=111) + + ####### process KL + &_loadround (0,$key,-128,@T); # load KL + &_rotl128 (@T,15,4,@T); # KL<<<15 + &_rotl128 (@T,30,10,@T); # KL<<<(15+30=45) + &_rotl128 (@T,15,13,@T[2],@T[3]); # KL<<<(45+15=60) + &_rotl128 (@T,17,16,@T); # KL<<<(60+17=77) + &_rotl128 (@T,17,18,@T); # KL<<<(77+17=94) + &_rotl128 (@T,17,22,@T); # KL<<<(94+17=111) + + while (@T[0] ne "eax") # restore order + { unshift (@T,pop(@T)); } + + &mov ("eax",3); # 3 grandRounds + &jmp (&label("done")); + +&set_label("2nd256",16); + &mov ($idx,&wparam(2)); + &_saveround (6,$idx,@T); # temporary storage for KA! + + &xor (@T[0],&DWP(4*8+0,$idx)); # KA^KR + &xor (@T[1],&DWP(4*8+4,$idx)); + &xor (@T[2],&DWP(5*8+0,$idx)); + &xor (@T[3],&DWP(5*8+4,$idx)); + + &mov ($idx,&DWP($step*8,$key)); # prefetch SIGMA[8] + &mov (&swtmp(0),@T[0]); # save s[0-3] + &mov (&swtmp(1),@T[1]); + &mov (&swtmp(2),@T[2]); + &mov (&swtmp(3),@T[3]); + &Camellia_Feistel($step++); + &Camellia_Feistel($step++); + &mov (@T[2],&swtmp(2)); + &mov (@T[3],&swtmp(3)); + + &mov ($key,&wparam(2)); + &lea ($key,&DWP(128,$key)); # size optimization + + ####### process KB + &_saveround (2,$key,-128,@T); # KB<<<0 + &_rotl128 (@T,30,10,@T); # KB<<<30 + &_rotl128 (@T,30,20,@T); # KB<<<(30+30=60) + push (@T,shift(@T)); # rotl128(@T,32); + &_rotl128 (@T,19,32,@T); # KB<<<(60+32+19=111) + + ####### process KR + &_loadround (4,$key,-128,@T); # load KR + &_rotl128 (@T,15,4,@T); # KR<<<15 + &_rotl128 (@T,15,8,@T); # KR<<<(15+15=30) + &_rotl128 (@T,30,18,@T); # KR<<<(30+30=60) + push (@T,shift(@T)); # rotl128(@T,32); + &_rotl128 (@T,2,26,@T); # KR<<<(60+32+2=94) + + ####### process KA + &_loadround (6,$key,-128,@T); # load KA + &_rotl128 (@T,15,6,@T); # KA<<<15 + &_rotl128 (@T,30,14,@T); # KA<<<(15+30=45) + push (@T,shift(@T)); # rotl128(@T,32); + &_rotl128 (@T,0,24,@T); # KA<<<(45+32+0=77) + &_rotl128 (@T,17,28,@T); # KA<<<(77+17=94) + + ####### process KL + &_loadround (0,$key,-128,@T); # load KL + push (@T,shift(@T)); # rotl128(@T,32); + &_rotl128 (@T,13,12,@T); # KL<<<(32+13=45) + &_rotl128 (@T,15,16,@T); # KL<<<(45+15=60) + &_rotl128 (@T,17,22,@T); # KL<<<(60+17=77) + push (@T,shift(@T)); # rotl128(@T,32); + &_rotl128 (@T,2,30,@T); # KL<<<(77+32+2=111) + + while (@T[0] ne "eax") # restore order + { unshift (@T,pop(@T)); } + + &mov ("eax",4); # 4 grandRounds +&set_label("done"); + &lea ("edx",&DWP(272-128,$key)); # end of key schedule + &stack_pop(4); +} +&function_end("Camellia_Ekeygen"); + +if ($OPENSSL) { +# int Camellia_set_key ( +# const unsigned char *userKey, +# int bits, +# CAMELLIA_KEY *key) +&function_begin_B("Camellia_set_key"); + &push ("ebx"); + &mov ("ecx",&wparam(0)); # pull arguments + &mov ("ebx",&wparam(1)); + &mov ("edx",&wparam(2)); + + &mov ("eax",-1); + &test ("ecx","ecx"); + &jz (&label("done")); # userKey==NULL? + &test ("edx","edx"); + &jz (&label("done")); # key==NULL? + + &mov ("eax",-2); + &cmp ("ebx",256); + &je (&label("arg_ok")); # bits==256? + &cmp ("ebx",192); + &je (&label("arg_ok")); # bits==192? + &cmp ("ebx",128); + &jne (&label("done")); # bits!=128? +&set_label("arg_ok",4); + + &push ("edx"); # push arguments + &push ("ecx"); + &push ("ebx"); + &call ("Camellia_Ekeygen"); + &stack_pop(3); + + # eax holds grandRounds and edx points at where to put it + &mov (&DWP(0,"edx"),"eax"); + &xor ("eax","eax"); +&set_label("done",4); + &pop ("ebx"); + &ret (); +&function_end_B("Camellia_set_key"); +} + +@SBOX=( +112,130, 44,236,179, 39,192,229,228,133, 87, 53,234, 12,174, 65, + 35,239,107,147, 69, 25,165, 33,237, 14, 79, 78, 29,101,146,189, +134,184,175,143,124,235, 31,206, 62, 48,220, 95, 94,197, 11, 26, +166,225, 57,202,213, 71, 93, 61,217, 1, 90,214, 81, 86,108, 77, +139, 13,154,102,251,204,176, 45,116, 18, 43, 32,240,177,132,153, +223, 76,203,194, 52,126,118, 5,109,183,169, 49,209, 23, 4,215, + 20, 88, 58, 97,222, 27, 17, 28, 50, 15,156, 22, 83, 24,242, 34, +254, 68,207,178,195,181,122,145, 36, 8,232,168, 96,252,105, 80, +170,208,160,125,161,137, 98,151, 84, 91, 30,149,224,255,100,210, + 16,196, 0, 72,163,247,117,219,138, 3,230,218, 9, 63,221,148, +135, 92,131, 2,205, 74,144, 51,115,103,246,243,157,127,191,226, + 82,155,216, 38,200, 55,198, 59,129,150,111, 75, 19,190, 99, 46, +233,121,167,140,159,110,188,142, 41,245,249,182, 47,253,180, 89, +120,152, 6,106,231, 70,113,186,212, 37,171, 66,136,162,141,250, +114, 7,185, 85,248,238,172, 10, 54, 73, 42,104, 60, 56,241,164, + 64, 40,211,123,187,201, 67,193, 21,227,173,244,119,199,128,158); + +sub S1110 { my $i=shift; $i=@SBOX[$i]; return $i<<24|$i<<16|$i<<8; } +sub S4404 { my $i=shift; $i=($i<<1|$i>>7)&0xff; $i=@SBOX[$i]; return $i<<24|$i<<16|$i; } +sub S0222 { my $i=shift; $i=@SBOX[$i]; $i=($i<<1|$i>>7)&0xff; return $i<<16|$i<<8|$i; } +sub S3033 { my $i=shift; $i=@SBOX[$i]; $i=($i>>1|$i<<7)&0xff; return $i<<24|$i<<8|$i; } + +&set_label("Camellia_SIGMA",64); +&data_word( + 0xa09e667f, 0x3bcc908b, 0xb67ae858, 0x4caa73b2, + 0xc6ef372f, 0xe94f82be, 0x54ff53a5, 0xf1d36f1c, + 0x10e527fa, 0xde682d1d, 0xb05688c2, 0xb3e6c1fd, + 0, 0, 0, 0); +&set_label("Camellia_SBOX",64); +# tables are interleaved, remember? +for ($i=0;$i<256;$i++) { &data_word(&S1110($i),&S4404($i)); } +for ($i=0;$i<256;$i++) { &data_word(&S0222($i),&S3033($i)); } + +# void Camellia_cbc_encrypt (const void char *inp, unsigned char *out, +# size_t length, const CAMELLIA_KEY *key, +# unsigned char *ivp,const int enc); +{ +# stack frame layout +# -4(%esp) # return address 0(%esp) +# 0(%esp) # s0 4(%esp) +# 4(%esp) # s1 8(%esp) +# 8(%esp) # s2 12(%esp) +# 12(%esp) # s3 16(%esp) +# 16(%esp) # end of key schedule 20(%esp) +# 20(%esp) # %esp backup +my $_inp=&DWP(24,"esp"); #copy of wparam(0) +my $_out=&DWP(28,"esp"); #copy of wparam(1) +my $_len=&DWP(32,"esp"); #copy of wparam(2) +my $_key=&DWP(36,"esp"); #copy of wparam(3) +my $_ivp=&DWP(40,"esp"); #copy of wparam(4) +my $ivec=&DWP(44,"esp"); #ivec[16] +my $_tmp=&DWP(44,"esp"); #volatile variable [yes, aliases with ivec] +my ($s0,$s1,$s2,$s3) = @T; + +&function_begin("Camellia_cbc_encrypt"); + &mov ($s2 eq "ecx"? $s2 : "",&wparam(2)); # load len + &cmp ($s2,0); + &je (&label("enc_out")); + + &pushf (); + &cld (); + + &mov ($s0,&wparam(0)); # load inp + &mov ($s1,&wparam(1)); # load out + #&mov ($s2,&wparam(2)); # load len + &mov ($s3,&wparam(3)); # load key + &mov ($Tbl,&wparam(4)); # load ivp + + # allocate aligned stack frame... + &lea ($idx,&DWP(-64,"esp")); + &and ($idx,-64); + + # place stack frame just "above mod 1024" the key schedule + # this ensures that cache associativity of 2 suffices + &lea ($key,&DWP(-64-63,$s3)); + &sub ($key,$idx); + &neg ($key); + &and ($key,0x3C0); # modulo 1024, but aligned to cache-line + &sub ($idx,$key); + + &mov ($key,&wparam(5)); # load enc + + &exch ("esp",$idx); + &add ("esp",4); # reserve for return address! + &mov ($_esp,$idx); # save %esp + + &mov ($_inp,$s0); # save copy of inp + &mov ($_out,$s1); # save copy of out + &mov ($_len,$s2); # save copy of len + &mov ($_key,$s3); # save copy of key + &mov ($_ivp,$Tbl); # save copy of ivp + + &call (&label("pic_point")); # make it PIC! + &set_label("pic_point"); + &blindpop($Tbl); + &lea ($Tbl,&DWP(&label("Camellia_SBOX")."-".&label("pic_point"),$Tbl)); + + &mov ($idx,32); + &set_label("prefetch_sbox",4); + &mov ($s0,&DWP(0,$Tbl)); + &mov ($s1,&DWP(32,$Tbl)); + &mov ($s2,&DWP(64,$Tbl)); + &mov ($s3,&DWP(96,$Tbl)); + &lea ($Tbl,&DWP(128,$Tbl)); + &dec ($idx); + &jnz (&label("prefetch_sbox")); + &mov ($s0,$_key); + &sub ($Tbl,4096); + &mov ($idx,$_inp); + &mov ($s3,&DWP(272,$s0)); # load grandRounds + + &cmp ($key,0); + &je (&label("DECRYPT")); + + &mov ($s2,$_len); + &mov ($key,$_ivp); + &shl ($s3,6); + &lea ($s3,&DWP(0,$s0,$s3)); + &mov ($_end,$s3); + + &test ($s2,0xFFFFFFF0); + &jz (&label("enc_tail")); # short input... + + &mov ($s0,&DWP(0,$key)); # load iv + &mov ($s1,&DWP(4,$key)); + + &set_label("enc_loop",4); + &mov ($s2,&DWP(8,$key)); + &mov ($s3,&DWP(12,$key)); + + &xor ($s0,&DWP(0,$idx)); # xor input data + &xor ($s1,&DWP(4,$idx)); + &xor ($s2,&DWP(8,$idx)); + &bswap ($s0); + &xor ($s3,&DWP(12,$idx)); + &bswap ($s1); + &mov ($key,$_key); # load key + &bswap ($s2); + &bswap ($s3); + + &call ("_x86_Camellia_encrypt"); + + &mov ($idx,$_inp); # load inp + &mov ($key,$_out); # load out + + &bswap ($s0); + &bswap ($s1); + &bswap ($s2); + &mov (&DWP(0,$key),$s0); # save output data + &bswap ($s3); + &mov (&DWP(4,$key),$s1); + &mov (&DWP(8,$key),$s2); + &mov (&DWP(12,$key),$s3); + + &mov ($s2,$_len); # load len + + &lea ($idx,&DWP(16,$idx)); + &mov ($_inp,$idx); # save inp + + &lea ($s3,&DWP(16,$key)); + &mov ($_out,$s3); # save out + + &sub ($s2,16); + &test ($s2,0xFFFFFFF0); + &mov ($_len,$s2); # save len + &jnz (&label("enc_loop")); + &test ($s2,15); + &jnz (&label("enc_tail")); + &mov ($idx,$_ivp); # load ivp + &mov ($s2,&DWP(8,$key)); # restore last dwords + &mov ($s3,&DWP(12,$key)); + &mov (&DWP(0,$idx),$s0); # save ivec + &mov (&DWP(4,$idx),$s1); + &mov (&DWP(8,$idx),$s2); + &mov (&DWP(12,$idx),$s3); + + &mov ("esp",$_esp); + &popf (); + &set_label("enc_out"); + &function_end_A(); + &pushf (); # kludge, never executed + + &set_label("enc_tail",4); + &mov ($s0,$key eq "edi" ? $key : ""); + &mov ($key,$_out); # load out + &push ($s0); # push ivp + &mov ($s1,16); + &sub ($s1,$s2); + &cmp ($key,$idx); # compare with inp + &je (&label("enc_in_place")); + &align (4); + &data_word(0xA4F3F689); # rep movsb # copy input + &jmp (&label("enc_skip_in_place")); + &set_label("enc_in_place"); + &lea ($key,&DWP(0,$key,$s2)); + &set_label("enc_skip_in_place"); + &mov ($s2,$s1); + &xor ($s0,$s0); + &align (4); + &data_word(0xAAF3F689); # rep stosb # zero tail + &pop ($key); # pop ivp + + &mov ($idx,$_out); # output as input + &mov ($s0,&DWP(0,$key)); + &mov ($s1,&DWP(4,$key)); + &mov ($_len,16); # len=16 + &jmp (&label("enc_loop")); # one more spin... + +#----------------------------- DECRYPT -----------------------------# +&set_label("DECRYPT",16); + &shl ($s3,6); + &lea ($s3,&DWP(0,$s0,$s3)); + &mov ($_end,$s0); + &mov ($_key,$s3); + + &cmp ($idx,$_out); + &je (&label("dec_in_place")); # in-place processing... + + &mov ($key,$_ivp); # load ivp + &mov ($_tmp,$key); + + &set_label("dec_loop",4); + &mov ($s0,&DWP(0,$idx)); # read input + &mov ($s1,&DWP(4,$idx)); + &mov ($s2,&DWP(8,$idx)); + &bswap ($s0); + &mov ($s3,&DWP(12,$idx)); + &bswap ($s1); + &mov ($key,$_key); # load key + &bswap ($s2); + &bswap ($s3); + + &call ("_x86_Camellia_decrypt"); + + &mov ($key,$_tmp); # load ivp + &mov ($idx,$_len); # load len + + &bswap ($s0); + &bswap ($s1); + &bswap ($s2); + &xor ($s0,&DWP(0,$key)); # xor iv + &bswap ($s3); + &xor ($s1,&DWP(4,$key)); + &xor ($s2,&DWP(8,$key)); + &xor ($s3,&DWP(12,$key)); + + &sub ($idx,16); + &jc (&label("dec_partial")); + &mov ($_len,$idx); # save len + &mov ($idx,$_inp); # load inp + &mov ($key,$_out); # load out + + &mov (&DWP(0,$key),$s0); # write output + &mov (&DWP(4,$key),$s1); + &mov (&DWP(8,$key),$s2); + &mov (&DWP(12,$key),$s3); + + &mov ($_tmp,$idx); # save ivp + &lea ($idx,&DWP(16,$idx)); + &mov ($_inp,$idx); # save inp + + &lea ($key,&DWP(16,$key)); + &mov ($_out,$key); # save out + + &jnz (&label("dec_loop")); + &mov ($key,$_tmp); # load temp ivp + &set_label("dec_end"); + &mov ($idx,$_ivp); # load user ivp + &mov ($s0,&DWP(0,$key)); # load iv + &mov ($s1,&DWP(4,$key)); + &mov ($s2,&DWP(8,$key)); + &mov ($s3,&DWP(12,$key)); + &mov (&DWP(0,$idx),$s0); # copy back to user + &mov (&DWP(4,$idx),$s1); + &mov (&DWP(8,$idx),$s2); + &mov (&DWP(12,$idx),$s3); + &jmp (&label("dec_out")); + + &set_label("dec_partial",4); + &lea ($key,$ivec); + &mov (&DWP(0,$key),$s0); # dump output to stack + &mov (&DWP(4,$key),$s1); + &mov (&DWP(8,$key),$s2); + &mov (&DWP(12,$key),$s3); + &lea ($s2 eq "ecx" ? $s2 : "",&DWP(16,$idx)); + &mov ($idx eq "esi" ? $idx : "",$key); + &mov ($key eq "edi" ? $key : "",$_out); # load out + &data_word(0xA4F3F689); # rep movsb # copy output + &mov ($key,$_inp); # use inp as temp ivp + &jmp (&label("dec_end")); + + &set_label("dec_in_place",4); + &set_label("dec_in_place_loop"); + &lea ($key,$ivec); + &mov ($s0,&DWP(0,$idx)); # read input + &mov ($s1,&DWP(4,$idx)); + &mov ($s2,&DWP(8,$idx)); + &mov ($s3,&DWP(12,$idx)); + + &mov (&DWP(0,$key),$s0); # copy to temp + &mov (&DWP(4,$key),$s1); + &mov (&DWP(8,$key),$s2); + &bswap ($s0); + &mov (&DWP(12,$key),$s3); + &bswap ($s1); + &mov ($key,$_key); # load key + &bswap ($s2); + &bswap ($s3); + + &call ("_x86_Camellia_decrypt"); + + &mov ($key,$_ivp); # load ivp + &mov ($idx,$_out); # load out + + &bswap ($s0); + &bswap ($s1); + &bswap ($s2); + &xor ($s0,&DWP(0,$key)); # xor iv + &bswap ($s3); + &xor ($s1,&DWP(4,$key)); + &xor ($s2,&DWP(8,$key)); + &xor ($s3,&DWP(12,$key)); + + &mov (&DWP(0,$idx),$s0); # write output + &mov (&DWP(4,$idx),$s1); + &mov (&DWP(8,$idx),$s2); + &mov (&DWP(12,$idx),$s3); + + &lea ($idx,&DWP(16,$idx)); + &mov ($_out,$idx); # save out + + &lea ($idx,$ivec); + &mov ($s0,&DWP(0,$idx)); # read temp + &mov ($s1,&DWP(4,$idx)); + &mov ($s2,&DWP(8,$idx)); + &mov ($s3,&DWP(12,$idx)); + + &mov (&DWP(0,$key),$s0); # copy iv + &mov (&DWP(4,$key),$s1); + &mov (&DWP(8,$key),$s2); + &mov (&DWP(12,$key),$s3); + + &mov ($idx,$_inp); # load inp + + &lea ($idx,&DWP(16,$idx)); + &mov ($_inp,$idx); # save inp + + &mov ($s2,$_len); # load len + &sub ($s2,16); + &jc (&label("dec_in_place_partial")); + &mov ($_len,$s2); # save len + &jnz (&label("dec_in_place_loop")); + &jmp (&label("dec_out")); + + &set_label("dec_in_place_partial",4); + # one can argue if this is actually required... + &mov ($key eq "edi" ? $key : "",$_out); + &lea ($idx eq "esi" ? $idx : "",$ivec); + &lea ($key,&DWP(0,$key,$s2)); + &lea ($idx,&DWP(16,$idx,$s2)); + &neg ($s2 eq "ecx" ? $s2 : ""); + &data_word(0xA4F3F689); # rep movsb # restore tail + + &set_label("dec_out",4); + &mov ("esp",$_esp); + &popf (); +&function_end("Camellia_cbc_encrypt"); +} + +&asciz("Camellia for x86 by "); + +&asm_finish(); + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/asm/cmll-x86_64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/asm/cmll-x86_64.pl new file mode 100644 index 000000000..02c52c3ef --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/asm/cmll-x86_64.pl @@ -0,0 +1,1145 @@ +#! /usr/bin/env perl +# Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Copyright (c) 2008 Andy Polyakov +# +# This module may be used under the terms of either the GNU General +# Public License version 2 or later, the GNU Lesser General Public +# License version 2.1 or later, the Mozilla Public License version +# 1.1 or the BSD License. The exact terms of either license are +# distributed along with this module. For further details see +# http://www.openssl.org/~appro/camellia/. +# ==================================================================== + +# Performance in cycles per processed byte (less is better) in +# 'openssl speed ...' benchmark: +# +# AMD64 Core2 EM64T +# -evp camellia-128-ecb 16.7 21.0 22.7 +# + over gcc 3.4.6 +25% +5% 0% +# +# camellia-128-cbc 15.7 20.4 21.1 +# +# 128-bit key setup 128 216 205 cycles/key +# + over gcc 3.4.6 +54% +39% +15% +# +# Numbers in "+" rows represent performance improvement over compiler +# generated code. Key setup timings are impressive on AMD and Core2 +# thanks to 64-bit operations being covertly deployed. Improvement on +# EM64T, pre-Core2 Intel x86_64 CPU, is not as impressive, because it +# apparently emulates some of 64-bit operations in [32-bit] microcode. + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +*STDOUT=*OUT; + +sub hi() { my $r=shift; $r =~ s/%[er]([a-d])x/%\1h/; $r; } +sub lo() { my $r=shift; $r =~ s/%[er]([a-d])x/%\1l/; + $r =~ s/%[er]([sd]i)/%\1l/; + $r =~ s/%(r[0-9]+)[d]?/%\1b/; $r; } + +$t0="%eax";$t1="%ebx";$t2="%ecx";$t3="%edx"; +@S=("%r8d","%r9d","%r10d","%r11d"); +$i0="%esi"; +$i1="%edi"; +$Tbl="%rbp"; # size optimization +$inp="%r12"; +$out="%r13"; +$key="%r14"; +$keyend="%r15"; +$arg0d=$win64?"%ecx":"%edi"; + +# const unsigned int Camellia_SBOX[4][256]; +# Well, sort of... Camellia_SBOX[0][] is interleaved with [1][], +# and [2][] - with [3][]. This is done to minimize code size. +$SBOX1_1110=0; # Camellia_SBOX[0] +$SBOX4_4404=4; # Camellia_SBOX[1] +$SBOX2_0222=2048; # Camellia_SBOX[2] +$SBOX3_3033=2052; # Camellia_SBOX[3] + +sub Camellia_Feistel { +my $i=@_[0]; +my $seed=defined(@_[1])?@_[1]:0; +my $scale=$seed<0?-8:8; +my $j=($i&1)*2; +my ($s0,$s1,$s2,$s3)=(@S[($j)%4],@S[($j+1)%4],@S[($j+2)%4],@S[($j+3)%4]); + +$code.=<<___; + xor $s0,$t0 # t0^=key[0] + xor $s1,$t1 # t1^=key[1] + movz `&hi("$t0")`,$i0 # (t0>>8)&0xff + movz `&lo("$t1")`,$i1 # (t1>>0)&0xff + mov $SBOX3_3033($Tbl,$i0,8),$t3 # t3=SBOX3_3033[0] + mov $SBOX1_1110($Tbl,$i1,8),$t2 # t2=SBOX1_1110[1] + movz `&lo("$t0")`,$i0 # (t0>>0)&0xff + shr \$16,$t0 + movz `&hi("$t1")`,$i1 # (t1>>8)&0xff + xor $SBOX4_4404($Tbl,$i0,8),$t3 # t3^=SBOX4_4404[0] + shr \$16,$t1 + xor $SBOX4_4404($Tbl,$i1,8),$t2 # t2^=SBOX4_4404[1] + movz `&hi("$t0")`,$i0 # (t0>>24)&0xff + movz `&lo("$t1")`,$i1 # (t1>>16)&0xff + xor $SBOX1_1110($Tbl,$i0,8),$t3 # t3^=SBOX1_1110[0] + xor $SBOX3_3033($Tbl,$i1,8),$t2 # t2^=SBOX3_3033[1] + movz `&lo("$t0")`,$i0 # (t0>>16)&0xff + movz `&hi("$t1")`,$i1 # (t1>>24)&0xff + xor $SBOX2_0222($Tbl,$i0,8),$t3 # t3^=SBOX2_0222[0] + xor $SBOX2_0222($Tbl,$i1,8),$t2 # t2^=SBOX2_0222[1] + mov `$seed+($i+1)*$scale`($key),$t1 # prefetch key[i+1] + mov `$seed+($i+1)*$scale+4`($key),$t0 + xor $t3,$t2 # t2^=t3 + ror \$8,$t3 # t3=RightRotate(t3,8) + xor $t2,$s2 + xor $t2,$s3 + xor $t3,$s3 +___ +} + +# void Camellia_EncryptBlock_Rounds( +# int grandRounds, +# const Byte plaintext[], +# const KEY_TABLE_TYPE keyTable, +# Byte ciphertext[]) +$code=<<___; +.text + +# V1.x API +.globl Camellia_EncryptBlock +.type Camellia_EncryptBlock,\@abi-omnipotent +.align 16 +Camellia_EncryptBlock: + movl \$128,%eax + subl $arg0d,%eax + movl \$3,$arg0d + adcl \$0,$arg0d # keyBitLength==128?3:4 + jmp .Lenc_rounds +.size Camellia_EncryptBlock,.-Camellia_EncryptBlock +# V2 +.globl Camellia_EncryptBlock_Rounds +.type Camellia_EncryptBlock_Rounds,\@function,4 +.align 16 +.Lenc_rounds: +Camellia_EncryptBlock_Rounds: +.cfi_startproc + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +.Lenc_prologue: + + #mov %rsi,$inp # put away arguments + mov %rcx,$out + mov %rdx,$key + + shl \$6,%edi # process grandRounds + lea .LCamellia_SBOX(%rip),$Tbl + lea ($key,%rdi),$keyend + + mov 0(%rsi),@S[0] # load plaintext + mov 4(%rsi),@S[1] + mov 8(%rsi),@S[2] + bswap @S[0] + mov 12(%rsi),@S[3] + bswap @S[1] + bswap @S[2] + bswap @S[3] + + call _x86_64_Camellia_encrypt + + bswap @S[0] + bswap @S[1] + bswap @S[2] + mov @S[0],0($out) + bswap @S[3] + mov @S[1],4($out) + mov @S[2],8($out) + mov @S[3],12($out) + + mov 0(%rsp),%r15 +.cfi_restore %r15 + mov 8(%rsp),%r14 +.cfi_restore %r14 + mov 16(%rsp),%r13 +.cfi_restore %r13 + mov 24(%rsp),%rbp +.cfi_restore %rbp + mov 32(%rsp),%rbx +.cfi_restore %rbx + lea 40(%rsp),%rsp +.cfi_adjust_cfa_offset -40 +.Lenc_epilogue: + ret +.cfi_endproc +.size Camellia_EncryptBlock_Rounds,.-Camellia_EncryptBlock_Rounds + +.type _x86_64_Camellia_encrypt,\@abi-omnipotent +.align 16 +_x86_64_Camellia_encrypt: + xor 0($key),@S[1] + xor 4($key),@S[0] # ^=key[0-3] + xor 8($key),@S[3] + xor 12($key),@S[2] +.align 16 +.Leloop: + mov 16($key),$t1 # prefetch key[4-5] + mov 20($key),$t0 + +___ + for ($i=0;$i<6;$i++) { Camellia_Feistel($i,16); } +$code.=<<___; + lea 16*4($key),$key + cmp $keyend,$key + mov 8($key),$t3 # prefetch key[2-3] + mov 12($key),$t2 + je .Ledone + + and @S[0],$t0 + or @S[3],$t3 + rol \$1,$t0 + xor $t3,@S[2] # s2^=s3|key[3]; + xor $t0,@S[1] # s1^=LeftRotate(s0&key[0],1); + and @S[2],$t2 + or @S[1],$t1 + rol \$1,$t2 + xor $t1,@S[0] # s0^=s1|key[1]; + xor $t2,@S[3] # s3^=LeftRotate(s2&key[2],1); + jmp .Leloop + +.align 16 +.Ledone: + xor @S[2],$t0 # SwapHalf + xor @S[3],$t1 + xor @S[0],$t2 + xor @S[1],$t3 + + mov $t0,@S[0] + mov $t1,@S[1] + mov $t2,@S[2] + mov $t3,@S[3] + + .byte 0xf3,0xc3 # rep ret +.size _x86_64_Camellia_encrypt,.-_x86_64_Camellia_encrypt + +# V1.x API +.globl Camellia_DecryptBlock +.type Camellia_DecryptBlock,\@abi-omnipotent +.align 16 +Camellia_DecryptBlock: + movl \$128,%eax + subl $arg0d,%eax + movl \$3,$arg0d + adcl \$0,$arg0d # keyBitLength==128?3:4 + jmp .Ldec_rounds +.size Camellia_DecryptBlock,.-Camellia_DecryptBlock +# V2 +.globl Camellia_DecryptBlock_Rounds +.type Camellia_DecryptBlock_Rounds,\@function,4 +.align 16 +.Ldec_rounds: +Camellia_DecryptBlock_Rounds: +.cfi_startproc + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +.Ldec_prologue: + + #mov %rsi,$inp # put away arguments + mov %rcx,$out + mov %rdx,$keyend + + shl \$6,%edi # process grandRounds + lea .LCamellia_SBOX(%rip),$Tbl + lea ($keyend,%rdi),$key + + mov 0(%rsi),@S[0] # load plaintext + mov 4(%rsi),@S[1] + mov 8(%rsi),@S[2] + bswap @S[0] + mov 12(%rsi),@S[3] + bswap @S[1] + bswap @S[2] + bswap @S[3] + + call _x86_64_Camellia_decrypt + + bswap @S[0] + bswap @S[1] + bswap @S[2] + mov @S[0],0($out) + bswap @S[3] + mov @S[1],4($out) + mov @S[2],8($out) + mov @S[3],12($out) + + mov 0(%rsp),%r15 +.cfi_restore %r15 + mov 8(%rsp),%r14 +.cfi_restore %r14 + mov 16(%rsp),%r13 +.cfi_restore %r13 + mov 24(%rsp),%rbp +.cfi_restore %rbp + mov 32(%rsp),%rbx +.cfi_restore %rbx + lea 40(%rsp),%rsp +.cfi_adjust_cfa_offset -40 +.Ldec_epilogue: + ret +.cfi_endproc +.size Camellia_DecryptBlock_Rounds,.-Camellia_DecryptBlock_Rounds + +.type _x86_64_Camellia_decrypt,\@abi-omnipotent +.align 16 +_x86_64_Camellia_decrypt: + xor 0($key),@S[1] + xor 4($key),@S[0] # ^=key[0-3] + xor 8($key),@S[3] + xor 12($key),@S[2] +.align 16 +.Ldloop: + mov -8($key),$t1 # prefetch key[4-5] + mov -4($key),$t0 + +___ + for ($i=0;$i<6;$i++) { Camellia_Feistel($i,-8); } +$code.=<<___; + lea -16*4($key),$key + cmp $keyend,$key + mov 0($key),$t3 # prefetch key[2-3] + mov 4($key),$t2 + je .Lddone + + and @S[0],$t0 + or @S[3],$t3 + rol \$1,$t0 + xor $t3,@S[2] # s2^=s3|key[3]; + xor $t0,@S[1] # s1^=LeftRotate(s0&key[0],1); + and @S[2],$t2 + or @S[1],$t1 + rol \$1,$t2 + xor $t1,@S[0] # s0^=s1|key[1]; + xor $t2,@S[3] # s3^=LeftRotate(s2&key[2],1); + + jmp .Ldloop + +.align 16 +.Lddone: + xor @S[2],$t2 + xor @S[3],$t3 + xor @S[0],$t0 + xor @S[1],$t1 + + mov $t2,@S[0] # SwapHalf + mov $t3,@S[1] + mov $t0,@S[2] + mov $t1,@S[3] + + .byte 0xf3,0xc3 # rep ret +.size _x86_64_Camellia_decrypt,.-_x86_64_Camellia_decrypt +___ + +sub _saveround { +my ($rnd,$key,@T)=@_; +my $bias=int(@T[0])?shift(@T):0; + + if ($#T==3) { + $code.=<<___; + mov @T[1],`$bias+$rnd*8+0`($key) + mov @T[0],`$bias+$rnd*8+4`($key) + mov @T[3],`$bias+$rnd*8+8`($key) + mov @T[2],`$bias+$rnd*8+12`($key) +___ + } else { + $code.=" mov @T[0],`$bias+$rnd*8+0`($key)\n"; + $code.=" mov @T[1],`$bias+$rnd*8+8`($key)\n" if ($#T>=1); + } +} + +sub _loadround { +my ($rnd,$key,@T)=@_; +my $bias=int(@T[0])?shift(@T):0; + +$code.=" mov `$bias+$rnd*8+0`($key),@T[0]\n"; +$code.=" mov `$bias+$rnd*8+8`($key),@T[1]\n" if ($#T>=1); +} + +# shld is very slow on Intel EM64T family. Even on AMD it limits +# instruction decode rate [because it's VectorPath] and consequently +# performance... +sub __rotl128 { +my ($i0,$i1,$rot)=@_; + + if ($rot) { + $code.=<<___; + mov $i0,%r11 + shld \$$rot,$i1,$i0 + shld \$$rot,%r11,$i1 +___ + } +} + +# ... Implementing 128-bit rotate without shld gives 80% better +# performance EM64T, +15% on AMD64 and only ~7% degradation on +# Core2. This is therefore preferred. +sub _rotl128 { +my ($i0,$i1,$rot)=@_; + + if ($rot) { + $code.=<<___; + mov $i0,%r11 + shl \$$rot,$i0 + mov $i1,%r9 + shr \$`64-$rot`,%r9 + shr \$`64-$rot`,%r11 + or %r9,$i0 + shl \$$rot,$i1 + or %r11,$i1 +___ + } +} + +{ my $step=0; + +$code.=<<___; +.globl Camellia_Ekeygen +.type Camellia_Ekeygen,\@function,3 +.align 16 +Camellia_Ekeygen: +.cfi_startproc + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +.Lkey_prologue: + + mov %edi,${keyend}d # put away arguments, keyBitLength + mov %rdx,$out # keyTable + + mov 0(%rsi),@S[0] # load 0-127 bits + mov 4(%rsi),@S[1] + mov 8(%rsi),@S[2] + mov 12(%rsi),@S[3] + + bswap @S[0] + bswap @S[1] + bswap @S[2] + bswap @S[3] +___ + &_saveround (0,$out,@S); # KL<<<0 +$code.=<<___; + cmp \$128,$keyend # check keyBitLength + je .L1st128 + + mov 16(%rsi),@S[0] # load 128-191 bits + mov 20(%rsi),@S[1] + cmp \$192,$keyend + je .L1st192 + mov 24(%rsi),@S[2] # load 192-255 bits + mov 28(%rsi),@S[3] + jmp .L1st256 +.L1st192: + mov @S[0],@S[2] + mov @S[1],@S[3] + not @S[2] + not @S[3] +.L1st256: + bswap @S[0] + bswap @S[1] + bswap @S[2] + bswap @S[3] +___ + &_saveround (4,$out,@S); # temp storage for KR! +$code.=<<___; + xor 0($out),@S[1] # KR^KL + xor 4($out),@S[0] + xor 8($out),@S[3] + xor 12($out),@S[2] + +.L1st128: + lea .LCamellia_SIGMA(%rip),$key + lea .LCamellia_SBOX(%rip),$Tbl + + mov 0($key),$t1 + mov 4($key),$t0 +___ + &Camellia_Feistel($step++); + &Camellia_Feistel($step++); +$code.=<<___; + xor 0($out),@S[1] # ^KL + xor 4($out),@S[0] + xor 8($out),@S[3] + xor 12($out),@S[2] +___ + &Camellia_Feistel($step++); + &Camellia_Feistel($step++); +$code.=<<___; + cmp \$128,$keyend + jne .L2nd256 + + lea 128($out),$out # size optimization + shl \$32,%r8 # @S[0]|| + shl \$32,%r10 # @S[2]|| + or %r9,%r8 # ||@S[1] + or %r11,%r10 # ||@S[3] +___ + &_loadround (0,$out,-128,"%rax","%rbx"); # KL + &_saveround (2,$out,-128,"%r8","%r10"); # KA<<<0 + &_rotl128 ("%rax","%rbx",15); + &_saveround (4,$out,-128,"%rax","%rbx"); # KL<<<15 + &_rotl128 ("%r8","%r10",15); + &_saveround (6,$out,-128,"%r8","%r10"); # KA<<<15 + &_rotl128 ("%r8","%r10",15); # 15+15=30 + &_saveround (8,$out,-128,"%r8","%r10"); # KA<<<30 + &_rotl128 ("%rax","%rbx",30); # 15+30=45 + &_saveround (10,$out,-128,"%rax","%rbx"); # KL<<<45 + &_rotl128 ("%r8","%r10",15); # 30+15=45 + &_saveround (12,$out,-128,"%r8"); # KA<<<45 + &_rotl128 ("%rax","%rbx",15); # 45+15=60 + &_saveround (13,$out,-128,"%rbx"); # KL<<<60 + &_rotl128 ("%r8","%r10",15); # 45+15=60 + &_saveround (14,$out,-128,"%r8","%r10"); # KA<<<60 + &_rotl128 ("%rax","%rbx",17); # 60+17=77 + &_saveround (16,$out,-128,"%rax","%rbx"); # KL<<<77 + &_rotl128 ("%rax","%rbx",17); # 77+17=94 + &_saveround (18,$out,-128,"%rax","%rbx"); # KL<<<94 + &_rotl128 ("%r8","%r10",34); # 60+34=94 + &_saveround (20,$out,-128,"%r8","%r10"); # KA<<<94 + &_rotl128 ("%rax","%rbx",17); # 94+17=111 + &_saveround (22,$out,-128,"%rax","%rbx"); # KL<<<111 + &_rotl128 ("%r8","%r10",17); # 94+17=111 + &_saveround (24,$out,-128,"%r8","%r10"); # KA<<<111 +$code.=<<___; + mov \$3,%eax + jmp .Ldone +.align 16 +.L2nd256: +___ + &_saveround (6,$out,@S); # temp storage for KA! +$code.=<<___; + xor `4*8+0`($out),@S[1] # KA^KR + xor `4*8+4`($out),@S[0] + xor `5*8+0`($out),@S[3] + xor `5*8+4`($out),@S[2] +___ + &Camellia_Feistel($step++); + &Camellia_Feistel($step++); + + &_loadround (0,$out,"%rax","%rbx"); # KL + &_loadround (4,$out,"%rcx","%rdx"); # KR + &_loadround (6,$out,"%r14","%r15"); # KA +$code.=<<___; + lea 128($out),$out # size optimization + shl \$32,%r8 # @S[0]|| + shl \$32,%r10 # @S[2]|| + or %r9,%r8 # ||@S[1] + or %r11,%r10 # ||@S[3] +___ + &_saveround (2,$out,-128,"%r8","%r10"); # KB<<<0 + &_rotl128 ("%rcx","%rdx",15); + &_saveround (4,$out,-128,"%rcx","%rdx"); # KR<<<15 + &_rotl128 ("%r14","%r15",15); + &_saveround (6,$out,-128,"%r14","%r15"); # KA<<<15 + &_rotl128 ("%rcx","%rdx",15); # 15+15=30 + &_saveround (8,$out,-128,"%rcx","%rdx"); # KR<<<30 + &_rotl128 ("%r8","%r10",30); + &_saveround (10,$out,-128,"%r8","%r10"); # KB<<<30 + &_rotl128 ("%rax","%rbx",45); + &_saveround (12,$out,-128,"%rax","%rbx"); # KL<<<45 + &_rotl128 ("%r14","%r15",30); # 15+30=45 + &_saveround (14,$out,-128,"%r14","%r15"); # KA<<<45 + &_rotl128 ("%rax","%rbx",15); # 45+15=60 + &_saveround (16,$out,-128,"%rax","%rbx"); # KL<<<60 + &_rotl128 ("%rcx","%rdx",30); # 30+30=60 + &_saveround (18,$out,-128,"%rcx","%rdx"); # KR<<<60 + &_rotl128 ("%r8","%r10",30); # 30+30=60 + &_saveround (20,$out,-128,"%r8","%r10"); # KB<<<60 + &_rotl128 ("%rax","%rbx",17); # 60+17=77 + &_saveround (22,$out,-128,"%rax","%rbx"); # KL<<<77 + &_rotl128 ("%r14","%r15",32); # 45+32=77 + &_saveround (24,$out,-128,"%r14","%r15"); # KA<<<77 + &_rotl128 ("%rcx","%rdx",34); # 60+34=94 + &_saveround (26,$out,-128,"%rcx","%rdx"); # KR<<<94 + &_rotl128 ("%r14","%r15",17); # 77+17=94 + &_saveround (28,$out,-128,"%r14","%r15"); # KA<<<77 + &_rotl128 ("%rax","%rbx",34); # 77+34=111 + &_saveround (30,$out,-128,"%rax","%rbx"); # KL<<<111 + &_rotl128 ("%r8","%r10",51); # 60+51=111 + &_saveround (32,$out,-128,"%r8","%r10"); # KB<<<111 +$code.=<<___; + mov \$4,%eax +.Ldone: + mov 0(%rsp),%r15 +.cfi_restore %r15 + mov 8(%rsp),%r14 +.cfi_restore %r14 + mov 16(%rsp),%r13 +.cfi_restore %r13 + mov 24(%rsp),%rbp +.cfi_restore %rbp + mov 32(%rsp),%rbx +.cfi_restore %rbx + lea 40(%rsp),%rsp +.cfi_adjust_cfa_offset -40 +.Lkey_epilogue: + ret +.cfi_endproc +.size Camellia_Ekeygen,.-Camellia_Ekeygen +___ +} + +@SBOX=( +112,130, 44,236,179, 39,192,229,228,133, 87, 53,234, 12,174, 65, + 35,239,107,147, 69, 25,165, 33,237, 14, 79, 78, 29,101,146,189, +134,184,175,143,124,235, 31,206, 62, 48,220, 95, 94,197, 11, 26, +166,225, 57,202,213, 71, 93, 61,217, 1, 90,214, 81, 86,108, 77, +139, 13,154,102,251,204,176, 45,116, 18, 43, 32,240,177,132,153, +223, 76,203,194, 52,126,118, 5,109,183,169, 49,209, 23, 4,215, + 20, 88, 58, 97,222, 27, 17, 28, 50, 15,156, 22, 83, 24,242, 34, +254, 68,207,178,195,181,122,145, 36, 8,232,168, 96,252,105, 80, +170,208,160,125,161,137, 98,151, 84, 91, 30,149,224,255,100,210, + 16,196, 0, 72,163,247,117,219,138, 3,230,218, 9, 63,221,148, +135, 92,131, 2,205, 74,144, 51,115,103,246,243,157,127,191,226, + 82,155,216, 38,200, 55,198, 59,129,150,111, 75, 19,190, 99, 46, +233,121,167,140,159,110,188,142, 41,245,249,182, 47,253,180, 89, +120,152, 6,106,231, 70,113,186,212, 37,171, 66,136,162,141,250, +114, 7,185, 85,248,238,172, 10, 54, 73, 42,104, 60, 56,241,164, + 64, 40,211,123,187,201, 67,193, 21,227,173,244,119,199,128,158); + +sub S1110 { my $i=shift; $i=@SBOX[$i]; $i=$i<<24|$i<<16|$i<<8; sprintf("0x%08x",$i); } +sub S4404 { my $i=shift; $i=($i<<1|$i>>7)&0xff; $i=@SBOX[$i]; $i=$i<<24|$i<<16|$i; sprintf("0x%08x",$i); } +sub S0222 { my $i=shift; $i=@SBOX[$i]; $i=($i<<1|$i>>7)&0xff; $i=$i<<16|$i<<8|$i; sprintf("0x%08x",$i); } +sub S3033 { my $i=shift; $i=@SBOX[$i]; $i=($i>>1|$i<<7)&0xff; $i=$i<<24|$i<<8|$i; sprintf("0x%08x",$i); } + +$code.=<<___; +.align 64 +.LCamellia_SIGMA: +.long 0x3bcc908b, 0xa09e667f, 0x4caa73b2, 0xb67ae858 +.long 0xe94f82be, 0xc6ef372f, 0xf1d36f1c, 0x54ff53a5 +.long 0xde682d1d, 0x10e527fa, 0xb3e6c1fd, 0xb05688c2 +.long 0, 0, 0, 0 +.LCamellia_SBOX: +___ +# tables are interleaved, remember? +sub data_word { $code.=".long\t".join(',',@_)."\n"; } +for ($i=0;$i<256;$i++) { &data_word(&S1110($i),&S4404($i)); } +for ($i=0;$i<256;$i++) { &data_word(&S0222($i),&S3033($i)); } + +# void Camellia_cbc_encrypt (const void char *inp, unsigned char *out, +# size_t length, const CAMELLIA_KEY *key, +# unsigned char *ivp,const int enc); +{ +$_key="0(%rsp)"; +$_end="8(%rsp)"; # inp+len&~15 +$_res="16(%rsp)"; # len&15 +$ivec="24(%rsp)"; +$_ivp="40(%rsp)"; +$_rsp="48(%rsp)"; + +$code.=<<___; +.globl Camellia_cbc_encrypt +.type Camellia_cbc_encrypt,\@function,6 +.align 16 +Camellia_cbc_encrypt: +.cfi_startproc + cmp \$0,%rdx + je .Lcbc_abort + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +.Lcbc_prologue: + + mov %rsp,%rbp +.cfi_def_cfa_register %rbp + sub \$64,%rsp + and \$-64,%rsp + + # place stack frame just "above mod 1024" the key schedule, + # this ensures that cache associativity suffices + lea -64-63(%rcx),%r10 + sub %rsp,%r10 + neg %r10 + and \$0x3C0,%r10 + sub %r10,%rsp + #add \$8,%rsp # 8 is reserved for callee's ra + + mov %rdi,$inp # inp argument + mov %rsi,$out # out argument + mov %r8,%rbx # ivp argument + mov %rcx,$key # key argument + mov 272(%rcx),${keyend}d # grandRounds + + mov %r8,$_ivp + mov %rbp,$_rsp +.cfi_cfa_expression $_rsp,deref,+56 + +.Lcbc_body: + lea .LCamellia_SBOX(%rip),$Tbl + + mov \$32,%ecx +.align 4 +.Lcbc_prefetch_sbox: + mov 0($Tbl),%rax + mov 32($Tbl),%rsi + mov 64($Tbl),%rdi + mov 96($Tbl),%r11 + lea 128($Tbl),$Tbl + loop .Lcbc_prefetch_sbox + sub \$4096,$Tbl + shl \$6,$keyend + mov %rdx,%rcx # len argument + lea ($key,$keyend),$keyend + + cmp \$0,%r9d # enc argument + je .LCBC_DECRYPT + + and \$-16,%rdx + and \$15,%rcx # length residue + lea ($inp,%rdx),%rdx + mov $key,$_key + mov %rdx,$_end + mov %rcx,$_res + + cmp $inp,%rdx + mov 0(%rbx),@S[0] # load IV + mov 4(%rbx),@S[1] + mov 8(%rbx),@S[2] + mov 12(%rbx),@S[3] + je .Lcbc_enc_tail + jmp .Lcbc_eloop + +.align 16 +.Lcbc_eloop: + xor 0($inp),@S[0] + xor 4($inp),@S[1] + xor 8($inp),@S[2] + bswap @S[0] + xor 12($inp),@S[3] + bswap @S[1] + bswap @S[2] + bswap @S[3] + + call _x86_64_Camellia_encrypt + + mov $_key,$key # "rewind" the key + bswap @S[0] + mov $_end,%rdx + bswap @S[1] + mov $_res,%rcx + bswap @S[2] + mov @S[0],0($out) + bswap @S[3] + mov @S[1],4($out) + mov @S[2],8($out) + lea 16($inp),$inp + mov @S[3],12($out) + cmp %rdx,$inp + lea 16($out),$out + jne .Lcbc_eloop + + cmp \$0,%rcx + jne .Lcbc_enc_tail + + mov $_ivp,$out + mov @S[0],0($out) # write out IV residue + mov @S[1],4($out) + mov @S[2],8($out) + mov @S[3],12($out) + jmp .Lcbc_done + +.align 16 +.Lcbc_enc_tail: + xor %rax,%rax + mov %rax,0+$ivec + mov %rax,8+$ivec + mov %rax,$_res + +.Lcbc_enc_pushf: + pushfq + cld + mov $inp,%rsi + lea 8+$ivec,%rdi + .long 0x9066A4F3 # rep movsb + popfq +.Lcbc_enc_popf: + + lea $ivec,$inp + lea 16+$ivec,%rax + mov %rax,$_end + jmp .Lcbc_eloop # one more time + +.align 16 +.LCBC_DECRYPT: + xchg $key,$keyend + add \$15,%rdx + and \$15,%rcx # length residue + and \$-16,%rdx + mov $key,$_key + lea ($inp,%rdx),%rdx + mov %rdx,$_end + mov %rcx,$_res + + mov (%rbx),%rax # load IV + mov 8(%rbx),%rbx + jmp .Lcbc_dloop +.align 16 +.Lcbc_dloop: + mov 0($inp),@S[0] + mov 4($inp),@S[1] + mov 8($inp),@S[2] + bswap @S[0] + mov 12($inp),@S[3] + bswap @S[1] + mov %rax,0+$ivec # save IV to temporary storage + bswap @S[2] + mov %rbx,8+$ivec + bswap @S[3] + + call _x86_64_Camellia_decrypt + + mov $_key,$key # "rewind" the key + mov $_end,%rdx + mov $_res,%rcx + + bswap @S[0] + mov ($inp),%rax # load IV for next iteration + bswap @S[1] + mov 8($inp),%rbx + bswap @S[2] + xor 0+$ivec,@S[0] + bswap @S[3] + xor 4+$ivec,@S[1] + xor 8+$ivec,@S[2] + lea 16($inp),$inp + xor 12+$ivec,@S[3] + cmp %rdx,$inp + je .Lcbc_ddone + + mov @S[0],0($out) + mov @S[1],4($out) + mov @S[2],8($out) + mov @S[3],12($out) + + lea 16($out),$out + jmp .Lcbc_dloop + +.align 16 +.Lcbc_ddone: + mov $_ivp,%rdx + cmp \$0,%rcx + jne .Lcbc_dec_tail + + mov @S[0],0($out) + mov @S[1],4($out) + mov @S[2],8($out) + mov @S[3],12($out) + + mov %rax,(%rdx) # write out IV residue + mov %rbx,8(%rdx) + jmp .Lcbc_done +.align 16 +.Lcbc_dec_tail: + mov @S[0],0+$ivec + mov @S[1],4+$ivec + mov @S[2],8+$ivec + mov @S[3],12+$ivec + +.Lcbc_dec_pushf: + pushfq + cld + lea 8+$ivec,%rsi + lea ($out),%rdi + .long 0x9066A4F3 # rep movsb + popfq +.Lcbc_dec_popf: + + mov %rax,(%rdx) # write out IV residue + mov %rbx,8(%rdx) + jmp .Lcbc_done + +.align 16 +.Lcbc_done: + mov $_rsp,%rcx +.cfi_def_cfa %rcx,56 + mov 0(%rcx),%r15 +.cfi_restore %r15 + mov 8(%rcx),%r14 +.cfi_restore %r14 + mov 16(%rcx),%r13 +.cfi_restore %r13 + mov 24(%rcx),%r12 +.cfi_restore %r12 + mov 32(%rcx),%rbp +.cfi_restore %rbp + mov 40(%rcx),%rbx +.cfi_restore %rbx + lea 48(%rcx),%rsp +.cfi_def_cfa %rsp,8 +.Lcbc_abort: + ret +.cfi_endproc +.size Camellia_cbc_encrypt,.-Camellia_cbc_encrypt + +.asciz "Camellia for x86_64 by " +___ +} + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type common_se_handler,\@abi-omnipotent +.align 16 +common_se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + lea -64(%rsp),%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lin_prologue + + lea 40(%rax),%rax + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r13 + mov -32(%rax),%r14 + mov -40(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + +.Lin_prologue: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + jmp .Lcommon_seh_exit +.size common_se_handler,.-common_se_handler + +.type cbc_se_handler,\@abi-omnipotent +.align 16 +cbc_se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + lea -64(%rsp),%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + lea .Lcbc_prologue(%rip),%r10 + cmp %r10,%rbx # context->Rip<.Lcbc_prologue + jb .Lin_cbc_prologue + + lea .Lcbc_body(%rip),%r10 + cmp %r10,%rbx # context->Rip<.Lcbc_body + jb .Lin_cbc_frame_setup + + mov 152($context),%rax # pull context->Rsp + + lea .Lcbc_abort(%rip),%r10 + cmp %r10,%rbx # context->Rip>=.Lcbc_abort + jae .Lin_cbc_prologue + + # handle pushf/popf in Camellia_cbc_encrypt + lea .Lcbc_enc_pushf(%rip),%r10 + cmp %r10,%rbx # context->Rip<=.Lcbc_enc_pushf + jbe .Lin_cbc_no_flag + lea 8(%rax),%rax + lea .Lcbc_enc_popf(%rip),%r10 + cmp %r10,%rbx # context->Rip<.Lcbc_enc_popf + jb .Lin_cbc_no_flag + lea -8(%rax),%rax + lea .Lcbc_dec_pushf(%rip),%r10 + cmp %r10,%rbx # context->Rip<=.Lcbc_dec_pushf + jbe .Lin_cbc_no_flag + lea 8(%rax),%rax + lea .Lcbc_dec_popf(%rip),%r10 + cmp %r10,%rbx # context->Rip<.Lcbc_dec_popf + jb .Lin_cbc_no_flag + lea -8(%rax),%rax + +.Lin_cbc_no_flag: + mov 48(%rax),%rax # $_rsp + lea 48(%rax),%rax + +.Lin_cbc_frame_setup: + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov -48(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + +.Lin_cbc_prologue: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + +.align 4 +.Lcommon_seh_exit: + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$`1232/8`,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + lea 64(%rsp),%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size cbc_se_handler,.-cbc_se_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_Camellia_EncryptBlock_Rounds + .rva .LSEH_end_Camellia_EncryptBlock_Rounds + .rva .LSEH_info_Camellia_EncryptBlock_Rounds + + .rva .LSEH_begin_Camellia_DecryptBlock_Rounds + .rva .LSEH_end_Camellia_DecryptBlock_Rounds + .rva .LSEH_info_Camellia_DecryptBlock_Rounds + + .rva .LSEH_begin_Camellia_Ekeygen + .rva .LSEH_end_Camellia_Ekeygen + .rva .LSEH_info_Camellia_Ekeygen + + .rva .LSEH_begin_Camellia_cbc_encrypt + .rva .LSEH_end_Camellia_cbc_encrypt + .rva .LSEH_info_Camellia_cbc_encrypt + +.section .xdata +.align 8 +.LSEH_info_Camellia_EncryptBlock_Rounds: + .byte 9,0,0,0 + .rva common_se_handler + .rva .Lenc_prologue,.Lenc_epilogue # HandlerData[] +.LSEH_info_Camellia_DecryptBlock_Rounds: + .byte 9,0,0,0 + .rva common_se_handler + .rva .Ldec_prologue,.Ldec_epilogue # HandlerData[] +.LSEH_info_Camellia_Ekeygen: + .byte 9,0,0,0 + .rva common_se_handler + .rva .Lkey_prologue,.Lkey_epilogue # HandlerData[] +.LSEH_info_Camellia_cbc_encrypt: + .byte 9,0,0,0 + .rva cbc_se_handler +___ +} + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/asm/cmllt4-sparcv9.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/asm/cmllt4-sparcv9.pl new file mode 100644 index 000000000..6396679a5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/asm/cmllt4-sparcv9.pl @@ -0,0 +1,939 @@ +#! /usr/bin/env perl +# Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by David S. Miller and Andy Polyakov. +# The module is licensed under 2-clause BSD +# license. October 2012. All rights reserved. +# ==================================================================== + +###################################################################### +# Camellia for SPARC T4. +# +# As with AES below results [for aligned data] are virtually identical +# to critical path lengths for 3-cycle instruction latency: +# +# 128-bit key 192/256- +# CBC encrypt 4.14/4.21(*) 5.46/5.52 +# (*) numbers after slash are for +# misaligned data. +# +# As with Intel AES-NI, question is if it's possible to improve +# performance of parallelizable modes by interleaving round +# instructions. In Camellia every instruction is dependent on +# previous, which means that there is place for 2 additional ones +# in between two dependent. Can we expect 3x performance improvement? +# At least one can argue that it should be possible to break 2x +# barrier... For some reason not even 2x appears to be possible: +# +# 128-bit key 192/256- +# CBC decrypt 2.21/2.74 2.99/3.40 +# CTR 2.15/2.68(*) 2.93/3.34 +# (*) numbers after slash are for +# misaligned data. +# +# This is for 2x interleave. But compared to 1x interleave CBC decrypt +# improved by ... 0% for 128-bit key, and 11% for 192/256-bit one. +# So that out-of-order execution logic can take non-interleaved code +# to 1.87x, but can't take 2x interleaved one any further. There +# surely is some explanation... As result 3x interleave was not even +# attempted. Instead an effort was made to share specific modes +# implementations with AES module (therefore sparct4_modes.pl). +# +# To anchor to something else, software C implementation processes +# one byte in 38 cycles with 128-bit key on same processor. + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "sparcv9_modes.pl"; + +$output = pop; +open STDOUT,">$output"; + +$::evp=1; # if $evp is set to 0, script generates module with +# Camellia_[en|de]crypt, Camellia_set_key and Camellia_cbc_encrypt +# entry points. These are fully compatible with openssl/camellia.h. + +###################################################################### +# single-round subroutines +# +{ +my ($inp,$out,$key,$rounds,$tmp,$mask)=map("%o$_",(0..5)); + +$code=<<___; +#include "sparc_arch.h" + +.text + +.globl cmll_t4_encrypt +.align 32 +cmll_t4_encrypt: + andcc $inp, 7, %g1 ! is input aligned? + andn $inp, 7, $inp + + ldx [$key + 0], %g4 + ldx [$key + 8], %g5 + + ldx [$inp + 0], %o4 + bz,pt %icc, 1f + ldx [$inp + 8], %o5 + ldx [$inp + 16], $inp + sll %g1, 3, %g1 + sub %g0, %g1, %o3 + sllx %o4, %g1, %o4 + sllx %o5, %g1, %g1 + srlx %o5, %o3, %o5 + srlx $inp, %o3, %o3 + or %o5, %o4, %o4 + or %o3, %g1, %o5 +1: + ld [$key + 272], $rounds ! grandRounds, 3 or 4 + ldd [$key + 16], %f12 + ldd [$key + 24], %f14 + xor %g4, %o4, %o4 + xor %g5, %o5, %o5 + ldd [$key + 32], %f16 + ldd [$key + 40], %f18 + movxtod %o4, %f0 + movxtod %o5, %f2 + ldd [$key + 48], %f20 + ldd [$key + 56], %f22 + sub $rounds, 1, $rounds + ldd [$key + 64], %f24 + ldd [$key + 72], %f26 + add $key, 80, $key + +.Lenc: + camellia_f %f12, %f2, %f0, %f2 + ldd [$key + 0], %f12 + sub $rounds,1,$rounds + camellia_f %f14, %f0, %f2, %f0 + ldd [$key + 8], %f14 + camellia_f %f16, %f2, %f0, %f2 + ldd [$key + 16], %f16 + camellia_f %f18, %f0, %f2, %f0 + ldd [$key + 24], %f18 + camellia_f %f20, %f2, %f0, %f2 + ldd [$key + 32], %f20 + camellia_f %f22, %f0, %f2, %f0 + ldd [$key + 40], %f22 + camellia_fl %f24, %f0, %f0 + ldd [$key + 48], %f24 + camellia_fli %f26, %f2, %f2 + ldd [$key + 56], %f26 + brnz,pt $rounds, .Lenc + add $key, 64, $key + + andcc $out, 7, $tmp ! is output aligned? + camellia_f %f12, %f2, %f0, %f2 + camellia_f %f14, %f0, %f2, %f0 + camellia_f %f16, %f2, %f0, %f2 + camellia_f %f18, %f0, %f2, %f0 + camellia_f %f20, %f2, %f0, %f4 + camellia_f %f22, %f0, %f4, %f2 + fxor %f24, %f4, %f0 + fxor %f26, %f2, %f2 + + bnz,pn %icc, 2f + nop + + std %f0, [$out + 0] + retl + std %f2, [$out + 8] + +2: alignaddrl $out, %g0, $out + mov 0xff, $mask + srl $mask, $tmp, $mask + + faligndata %f0, %f0, %f4 + faligndata %f0, %f2, %f6 + faligndata %f2, %f2, %f8 + + stda %f4, [$out + $mask]0xc0 ! partial store + std %f6, [$out + 8] + add $out, 16, $out + orn %g0, $mask, $mask + retl + stda %f8, [$out + $mask]0xc0 ! partial store +.type cmll_t4_encrypt,#function +.size cmll_t4_encrypt,.-cmll_t4_encrypt + +.globl cmll_t4_decrypt +.align 32 +cmll_t4_decrypt: + ld [$key + 272], $rounds ! grandRounds, 3 or 4 + andcc $inp, 7, %g1 ! is input aligned? + andn $inp, 7, $inp + + sll $rounds, 6, $rounds + add $rounds, $key, $key + + ldx [$inp + 0], %o4 + bz,pt %icc, 1f + ldx [$inp + 8], %o5 + ldx [$inp + 16], $inp + sll %g1, 3, %g1 + sub %g0, %g1, %g4 + sllx %o4, %g1, %o4 + sllx %o5, %g1, %g1 + srlx %o5, %g4, %o5 + srlx $inp, %g4, %g4 + or %o5, %o4, %o4 + or %g4, %g1, %o5 +1: + ldx [$key + 0], %g4 + ldx [$key + 8], %g5 + ldd [$key - 8], %f12 + ldd [$key - 16], %f14 + xor %g4, %o4, %o4 + xor %g5, %o5, %o5 + ldd [$key - 24], %f16 + ldd [$key - 32], %f18 + movxtod %o4, %f0 + movxtod %o5, %f2 + ldd [$key - 40], %f20 + ldd [$key - 48], %f22 + sub $rounds, 64, $rounds + ldd [$key - 56], %f24 + ldd [$key - 64], %f26 + sub $key, 64, $key + +.Ldec: + camellia_f %f12, %f2, %f0, %f2 + ldd [$key - 8], %f12 + sub $rounds, 64, $rounds + camellia_f %f14, %f0, %f2, %f0 + ldd [$key - 16], %f14 + camellia_f %f16, %f2, %f0, %f2 + ldd [$key - 24], %f16 + camellia_f %f18, %f0, %f2, %f0 + ldd [$key - 32], %f18 + camellia_f %f20, %f2, %f0, %f2 + ldd [$key - 40], %f20 + camellia_f %f22, %f0, %f2, %f0 + ldd [$key - 48], %f22 + camellia_fl %f24, %f0, %f0 + ldd [$key - 56], %f24 + camellia_fli %f26, %f2, %f2 + ldd [$key - 64], %f26 + brnz,pt $rounds, .Ldec + sub $key, 64, $key + + andcc $out, 7, $tmp ! is output aligned? + camellia_f %f12, %f2, %f0, %f2 + camellia_f %f14, %f0, %f2, %f0 + camellia_f %f16, %f2, %f0, %f2 + camellia_f %f18, %f0, %f2, %f0 + camellia_f %f20, %f2, %f0, %f4 + camellia_f %f22, %f0, %f4, %f2 + fxor %f26, %f4, %f0 + fxor %f24, %f2, %f2 + + bnz,pn %icc, 2f + nop + + std %f0, [$out + 0] + retl + std %f2, [$out + 8] + +2: alignaddrl $out, %g0, $out + mov 0xff, $mask + srl $mask, $tmp, $mask + + faligndata %f0, %f0, %f4 + faligndata %f0, %f2, %f6 + faligndata %f2, %f2, %f8 + + stda %f4, [$out + $mask]0xc0 ! partial store + std %f6, [$out + 8] + add $out, 16, $out + orn %g0, $mask, $mask + retl + stda %f8, [$out + $mask]0xc0 ! partial store +.type cmll_t4_decrypt,#function +.size cmll_t4_decrypt,.-cmll_t4_decrypt +___ +} + +###################################################################### +# key setup subroutines +# +{ +sub ROTL128 { + my $rot = shift; + + "srlx %o4, 64-$rot, %g4\n\t". + "sllx %o4, $rot, %o4\n\t". + "srlx %o5, 64-$rot, %g5\n\t". + "sllx %o5, $rot, %o5\n\t". + "or %o4, %g5, %o4\n\t". + "or %o5, %g4, %o5"; +} + +my ($inp,$bits,$out,$tmp)=map("%o$_",(0..5)); +$code.=<<___; +.globl cmll_t4_set_key +.align 32 +cmll_t4_set_key: + and $inp, 7, $tmp + alignaddr $inp, %g0, $inp + cmp $bits, 192 + ldd [$inp + 0], %f0 + bl,pt %icc,.L128 + ldd [$inp + 8], %f2 + + be,pt %icc,.L192 + ldd [$inp + 16], %f4 + + brz,pt $tmp, .L256aligned + ldd [$inp + 24], %f6 + + ldd [$inp + 32], %f8 + faligndata %f0, %f2, %f0 + faligndata %f2, %f4, %f2 + faligndata %f4, %f6, %f4 + b .L256aligned + faligndata %f6, %f8, %f6 + +.align 16 +.L192: + brz,a,pt $tmp, .L256aligned + fnot2 %f4, %f6 + + ldd [$inp + 24], %f6 + nop + faligndata %f0, %f2, %f0 + faligndata %f2, %f4, %f2 + faligndata %f4, %f6, %f4 + fnot2 %f4, %f6 + +.L256aligned: + std %f0, [$out + 0] ! k[0, 1] + fsrc2 %f0, %f28 + std %f2, [$out + 8] ! k[2, 3] + fsrc2 %f2, %f30 + fxor %f4, %f0, %f0 + b .L128key + fxor %f6, %f2, %f2 + +.align 16 +.L128: + brz,pt $tmp, .L128aligned + nop + + ldd [$inp + 16], %f4 + nop + faligndata %f0, %f2, %f0 + faligndata %f2, %f4, %f2 + +.L128aligned: + std %f0, [$out + 0] ! k[0, 1] + fsrc2 %f0, %f28 + std %f2, [$out + 8] ! k[2, 3] + fsrc2 %f2, %f30 + +.L128key: + mov %o7, %o5 +1: call .+8 + add %o7, SIGMA-1b, %o4 + mov %o5, %o7 + + ldd [%o4 + 0], %f16 + ldd [%o4 + 8], %f18 + ldd [%o4 + 16], %f20 + ldd [%o4 + 24], %f22 + + camellia_f %f16, %f2, %f0, %f2 + camellia_f %f18, %f0, %f2, %f0 + fxor %f28, %f0, %f0 + fxor %f30, %f2, %f2 + camellia_f %f20, %f2, %f0, %f2 + camellia_f %f22, %f0, %f2, %f0 + + bge,pn %icc, .L256key + nop + std %f0, [$out + 0x10] ! k[ 4, 5] + std %f2, [$out + 0x18] ! k[ 6, 7] + + movdtox %f0, %o4 + movdtox %f2, %o5 + `&ROTL128(15)` + stx %o4, [$out + 0x30] ! k[12, 13] + stx %o5, [$out + 0x38] ! k[14, 15] + `&ROTL128(15)` + stx %o4, [$out + 0x40] ! k[16, 17] + stx %o5, [$out + 0x48] ! k[18, 19] + `&ROTL128(15)` + stx %o4, [$out + 0x60] ! k[24, 25] + `&ROTL128(15)` + stx %o4, [$out + 0x70] ! k[28, 29] + stx %o5, [$out + 0x78] ! k[30, 31] + `&ROTL128(34)` + stx %o4, [$out + 0xa0] ! k[40, 41] + stx %o5, [$out + 0xa8] ! k[42, 43] + `&ROTL128(17)` + stx %o4, [$out + 0xc0] ! k[48, 49] + stx %o5, [$out + 0xc8] ! k[50, 51] + + movdtox %f28, %o4 ! k[ 0, 1] + movdtox %f30, %o5 ! k[ 2, 3] + `&ROTL128(15)` + stx %o4, [$out + 0x20] ! k[ 8, 9] + stx %o5, [$out + 0x28] ! k[10, 11] + `&ROTL128(30)` + stx %o4, [$out + 0x50] ! k[20, 21] + stx %o5, [$out + 0x58] ! k[22, 23] + `&ROTL128(15)` + stx %o5, [$out + 0x68] ! k[26, 27] + `&ROTL128(17)` + stx %o4, [$out + 0x80] ! k[32, 33] + stx %o5, [$out + 0x88] ! k[34, 35] + `&ROTL128(17)` + stx %o4, [$out + 0x90] ! k[36, 37] + stx %o5, [$out + 0x98] ! k[38, 39] + `&ROTL128(17)` + stx %o4, [$out + 0xb0] ! k[44, 45] + stx %o5, [$out + 0xb8] ! k[46, 47] + + mov 3, $tmp + st $tmp, [$out + 0x110] + retl + xor %o0, %o0, %o0 + +.align 16 +.L256key: + ldd [%o4 + 32], %f24 + ldd [%o4 + 40], %f26 + + std %f0, [$out + 0x30] ! k[12, 13] + std %f2, [$out + 0x38] ! k[14, 15] + + fxor %f4, %f0, %f0 + fxor %f6, %f2, %f2 + camellia_f %f24, %f2, %f0, %f2 + camellia_f %f26, %f0, %f2, %f0 + + std %f0, [$out + 0x10] ! k[ 4, 5] + std %f2, [$out + 0x18] ! k[ 6, 7] + + movdtox %f0, %o4 + movdtox %f2, %o5 + `&ROTL128(30)` + stx %o4, [$out + 0x50] ! k[20, 21] + stx %o5, [$out + 0x58] ! k[22, 23] + `&ROTL128(30)` + stx %o4, [$out + 0xa0] ! k[40, 41] + stx %o5, [$out + 0xa8] ! k[42, 43] + `&ROTL128(51)` + stx %o4, [$out + 0x100] ! k[64, 65] + stx %o5, [$out + 0x108] ! k[66, 67] + + movdtox %f4, %o4 ! k[ 8, 9] + movdtox %f6, %o5 ! k[10, 11] + `&ROTL128(15)` + stx %o4, [$out + 0x20] ! k[ 8, 9] + stx %o5, [$out + 0x28] ! k[10, 11] + `&ROTL128(15)` + stx %o4, [$out + 0x40] ! k[16, 17] + stx %o5, [$out + 0x48] ! k[18, 19] + `&ROTL128(30)` + stx %o4, [$out + 0x90] ! k[36, 37] + stx %o5, [$out + 0x98] ! k[38, 39] + `&ROTL128(34)` + stx %o4, [$out + 0xd0] ! k[52, 53] + stx %o5, [$out + 0xd8] ! k[54, 55] + ldx [$out + 0x30], %o4 ! k[12, 13] + ldx [$out + 0x38], %o5 ! k[14, 15] + `&ROTL128(15)` + stx %o4, [$out + 0x30] ! k[12, 13] + stx %o5, [$out + 0x38] ! k[14, 15] + `&ROTL128(30)` + stx %o4, [$out + 0x70] ! k[28, 29] + stx %o5, [$out + 0x78] ! k[30, 31] + srlx %o4, 32, %g4 + srlx %o5, 32, %g5 + st %o4, [$out + 0xc0] ! k[48] + st %g5, [$out + 0xc4] ! k[49] + st %o5, [$out + 0xc8] ! k[50] + st %g4, [$out + 0xcc] ! k[51] + `&ROTL128(49)` + stx %o4, [$out + 0xe0] ! k[56, 57] + stx %o5, [$out + 0xe8] ! k[58, 59] + + movdtox %f28, %o4 ! k[ 0, 1] + movdtox %f30, %o5 ! k[ 2, 3] + `&ROTL128(45)` + stx %o4, [$out + 0x60] ! k[24, 25] + stx %o5, [$out + 0x68] ! k[26, 27] + `&ROTL128(15)` + stx %o4, [$out + 0x80] ! k[32, 33] + stx %o5, [$out + 0x88] ! k[34, 35] + `&ROTL128(17)` + stx %o4, [$out + 0xb0] ! k[44, 45] + stx %o5, [$out + 0xb8] ! k[46, 47] + `&ROTL128(34)` + stx %o4, [$out + 0xf0] ! k[60, 61] + stx %o5, [$out + 0xf8] ! k[62, 63] + + mov 4, $tmp + st $tmp, [$out + 0x110] + retl + xor %o0, %o0, %o0 +.type cmll_t4_set_key,#function +.size cmll_t4_set_key,.-cmll_t4_set_key +.align 32 +SIGMA: + .long 0xa09e667f, 0x3bcc908b, 0xb67ae858, 0x4caa73b2 + .long 0xc6ef372f, 0xe94f82be, 0x54ff53a5, 0xf1d36f1c + .long 0x10e527fa, 0xde682d1d, 0xb05688c2, 0xb3e6c1fd +.type SIGMA,#object +.size SIGMA,.-SIGMA +.asciz "Camellia for SPARC T4, David S. Miller, Andy Polyakov" +___ +} + +{{{ +my ($inp,$out,$len,$key,$ivec,$enc)=map("%i$_",(0..5)); +my ($ileft,$iright,$ooff,$omask,$ivoff)=map("%l$_",(1..7)); + +$code.=<<___; +.align 32 +_cmll128_load_enckey: + ldx [$key + 0], %g4 + ldx [$key + 8], %g5 +___ +for ($i=2; $i<26;$i++) { # load key schedule + $code.=<<___; + ldd [$key + `8*$i`], %f`12+2*$i` +___ +} +$code.=<<___; + retl + nop +.type _cmll128_load_enckey,#function +.size _cmll128_load_enckey,.-_cmll128_load_enckey +_cmll256_load_enckey=_cmll128_load_enckey + +.align 32 +_cmll256_load_deckey: + ldd [$key + 64], %f62 + ldd [$key + 72], %f60 + b .Load_deckey + add $key, 64, $key +_cmll128_load_deckey: + ldd [$key + 0], %f60 + ldd [$key + 8], %f62 +.Load_deckey: +___ +for ($i=2; $i<24;$i++) { # load key schedule + $code.=<<___; + ldd [$key + `8*$i`], %f`62-2*$i` +___ +} +$code.=<<___; + ldx [$key + 192], %g4 + retl + ldx [$key + 200], %g5 +.type _cmll256_load_deckey,#function +.size _cmll256_load_deckey,.-_cmll256_load_deckey + +.align 32 +_cmll128_encrypt_1x: +___ +for ($i=0; $i<3; $i++) { + $code.=<<___; + camellia_f %f`16+16*$i+0`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+2`, %f0, %f2, %f0 + camellia_f %f`16+16*$i+4`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+6`, %f0, %f2, %f0 +___ +$code.=<<___ if ($i<2); + camellia_f %f`16+16*$i+8`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+10`, %f0, %f2, %f0 + camellia_fl %f`16+16*$i+12`, %f0, %f0 + camellia_fli %f`16+16*$i+14`, %f2, %f2 +___ +} +$code.=<<___; + camellia_f %f56, %f2, %f0, %f4 + camellia_f %f58, %f0, %f4, %f2 + fxor %f60, %f4, %f0 + retl + fxor %f62, %f2, %f2 +.type _cmll128_encrypt_1x,#function +.size _cmll128_encrypt_1x,.-_cmll128_encrypt_1x +_cmll128_decrypt_1x=_cmll128_encrypt_1x + +.align 32 +_cmll128_encrypt_2x: +___ +for ($i=0; $i<3; $i++) { + $code.=<<___; + camellia_f %f`16+16*$i+0`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+0`, %f6, %f4, %f6 + camellia_f %f`16+16*$i+2`, %f0, %f2, %f0 + camellia_f %f`16+16*$i+2`, %f4, %f6, %f4 + camellia_f %f`16+16*$i+4`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+4`, %f6, %f4, %f6 + camellia_f %f`16+16*$i+6`, %f0, %f2, %f0 + camellia_f %f`16+16*$i+6`, %f4, %f6, %f4 +___ +$code.=<<___ if ($i<2); + camellia_f %f`16+16*$i+8`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+8`, %f6, %f4, %f6 + camellia_f %f`16+16*$i+10`, %f0, %f2, %f0 + camellia_f %f`16+16*$i+10`, %f4, %f6, %f4 + camellia_fl %f`16+16*$i+12`, %f0, %f0 + camellia_fl %f`16+16*$i+12`, %f4, %f4 + camellia_fli %f`16+16*$i+14`, %f2, %f2 + camellia_fli %f`16+16*$i+14`, %f6, %f6 +___ +} +$code.=<<___; + camellia_f %f56, %f2, %f0, %f8 + camellia_f %f56, %f6, %f4, %f10 + camellia_f %f58, %f0, %f8, %f2 + camellia_f %f58, %f4, %f10, %f6 + fxor %f60, %f8, %f0 + fxor %f60, %f10, %f4 + fxor %f62, %f2, %f2 + retl + fxor %f62, %f6, %f6 +.type _cmll128_encrypt_2x,#function +.size _cmll128_encrypt_2x,.-_cmll128_encrypt_2x +_cmll128_decrypt_2x=_cmll128_encrypt_2x + +.align 32 +_cmll256_encrypt_1x: + camellia_f %f16, %f2, %f0, %f2 + camellia_f %f18, %f0, %f2, %f0 + ldd [$key + 208], %f16 + ldd [$key + 216], %f18 + camellia_f %f20, %f2, %f0, %f2 + camellia_f %f22, %f0, %f2, %f0 + ldd [$key + 224], %f20 + ldd [$key + 232], %f22 + camellia_f %f24, %f2, %f0, %f2 + camellia_f %f26, %f0, %f2, %f0 + ldd [$key + 240], %f24 + ldd [$key + 248], %f26 + camellia_fl %f28, %f0, %f0 + camellia_fli %f30, %f2, %f2 + ldd [$key + 256], %f28 + ldd [$key + 264], %f30 +___ +for ($i=1; $i<3; $i++) { + $code.=<<___; + camellia_f %f`16+16*$i+0`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+2`, %f0, %f2, %f0 + camellia_f %f`16+16*$i+4`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+6`, %f0, %f2, %f0 + camellia_f %f`16+16*$i+8`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+10`, %f0, %f2, %f0 + camellia_fl %f`16+16*$i+12`, %f0, %f0 + camellia_fli %f`16+16*$i+14`, %f2, %f2 +___ +} +$code.=<<___; + camellia_f %f16, %f2, %f0, %f2 + camellia_f %f18, %f0, %f2, %f0 + ldd [$key + 16], %f16 + ldd [$key + 24], %f18 + camellia_f %f20, %f2, %f0, %f2 + camellia_f %f22, %f0, %f2, %f0 + ldd [$key + 32], %f20 + ldd [$key + 40], %f22 + camellia_f %f24, %f2, %f0, %f4 + camellia_f %f26, %f0, %f4, %f2 + ldd [$key + 48], %f24 + ldd [$key + 56], %f26 + fxor %f28, %f4, %f0 + fxor %f30, %f2, %f2 + ldd [$key + 64], %f28 + retl + ldd [$key + 72], %f30 +.type _cmll256_encrypt_1x,#function +.size _cmll256_encrypt_1x,.-_cmll256_encrypt_1x + +.align 32 +_cmll256_encrypt_2x: + camellia_f %f16, %f2, %f0, %f2 + camellia_f %f16, %f6, %f4, %f6 + camellia_f %f18, %f0, %f2, %f0 + camellia_f %f18, %f4, %f6, %f4 + ldd [$key + 208], %f16 + ldd [$key + 216], %f18 + camellia_f %f20, %f2, %f0, %f2 + camellia_f %f20, %f6, %f4, %f6 + camellia_f %f22, %f0, %f2, %f0 + camellia_f %f22, %f4, %f6, %f4 + ldd [$key + 224], %f20 + ldd [$key + 232], %f22 + camellia_f %f24, %f2, %f0, %f2 + camellia_f %f24, %f6, %f4, %f6 + camellia_f %f26, %f0, %f2, %f0 + camellia_f %f26, %f4, %f6, %f4 + ldd [$key + 240], %f24 + ldd [$key + 248], %f26 + camellia_fl %f28, %f0, %f0 + camellia_fl %f28, %f4, %f4 + camellia_fli %f30, %f2, %f2 + camellia_fli %f30, %f6, %f6 + ldd [$key + 256], %f28 + ldd [$key + 264], %f30 +___ +for ($i=1; $i<3; $i++) { + $code.=<<___; + camellia_f %f`16+16*$i+0`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+0`, %f6, %f4, %f6 + camellia_f %f`16+16*$i+2`, %f0, %f2, %f0 + camellia_f %f`16+16*$i+2`, %f4, %f6, %f4 + camellia_f %f`16+16*$i+4`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+4`, %f6, %f4, %f6 + camellia_f %f`16+16*$i+6`, %f0, %f2, %f0 + camellia_f %f`16+16*$i+6`, %f4, %f6, %f4 + camellia_f %f`16+16*$i+8`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+8`, %f6, %f4, %f6 + camellia_f %f`16+16*$i+10`, %f0, %f2, %f0 + camellia_f %f`16+16*$i+10`, %f4, %f6, %f4 + camellia_fl %f`16+16*$i+12`, %f0, %f0 + camellia_fl %f`16+16*$i+12`, %f4, %f4 + camellia_fli %f`16+16*$i+14`, %f2, %f2 + camellia_fli %f`16+16*$i+14`, %f6, %f6 +___ +} +$code.=<<___; + camellia_f %f16, %f2, %f0, %f2 + camellia_f %f16, %f6, %f4, %f6 + camellia_f %f18, %f0, %f2, %f0 + camellia_f %f18, %f4, %f6, %f4 + ldd [$key + 16], %f16 + ldd [$key + 24], %f18 + camellia_f %f20, %f2, %f0, %f2 + camellia_f %f20, %f6, %f4, %f6 + camellia_f %f22, %f0, %f2, %f0 + camellia_f %f22, %f4, %f6, %f4 + ldd [$key + 32], %f20 + ldd [$key + 40], %f22 + camellia_f %f24, %f2, %f0, %f8 + camellia_f %f24, %f6, %f4, %f10 + camellia_f %f26, %f0, %f8, %f2 + camellia_f %f26, %f4, %f10, %f6 + ldd [$key + 48], %f24 + ldd [$key + 56], %f26 + fxor %f28, %f8, %f0 + fxor %f28, %f10, %f4 + fxor %f30, %f2, %f2 + fxor %f30, %f6, %f6 + ldd [$key + 64], %f28 + retl + ldd [$key + 72], %f30 +.type _cmll256_encrypt_2x,#function +.size _cmll256_encrypt_2x,.-_cmll256_encrypt_2x + +.align 32 +_cmll256_decrypt_1x: + camellia_f %f16, %f2, %f0, %f2 + camellia_f %f18, %f0, %f2, %f0 + ldd [$key - 8], %f16 + ldd [$key - 16], %f18 + camellia_f %f20, %f2, %f0, %f2 + camellia_f %f22, %f0, %f2, %f0 + ldd [$key - 24], %f20 + ldd [$key - 32], %f22 + camellia_f %f24, %f2, %f0, %f2 + camellia_f %f26, %f0, %f2, %f0 + ldd [$key - 40], %f24 + ldd [$key - 48], %f26 + camellia_fl %f28, %f0, %f0 + camellia_fli %f30, %f2, %f2 + ldd [$key - 56], %f28 + ldd [$key - 64], %f30 +___ +for ($i=1; $i<3; $i++) { + $code.=<<___; + camellia_f %f`16+16*$i+0`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+2`, %f0, %f2, %f0 + camellia_f %f`16+16*$i+4`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+6`, %f0, %f2, %f0 + camellia_f %f`16+16*$i+8`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+10`, %f0, %f2, %f0 + camellia_fl %f`16+16*$i+12`, %f0, %f0 + camellia_fli %f`16+16*$i+14`, %f2, %f2 +___ +} +$code.=<<___; + camellia_f %f16, %f2, %f0, %f2 + camellia_f %f18, %f0, %f2, %f0 + ldd [$key + 184], %f16 + ldd [$key + 176], %f18 + camellia_f %f20, %f2, %f0, %f2 + camellia_f %f22, %f0, %f2, %f0 + ldd [$key + 168], %f20 + ldd [$key + 160], %f22 + camellia_f %f24, %f2, %f0, %f4 + camellia_f %f26, %f0, %f4, %f2 + ldd [$key + 152], %f24 + ldd [$key + 144], %f26 + fxor %f30, %f4, %f0 + fxor %f28, %f2, %f2 + ldd [$key + 136], %f28 + retl + ldd [$key + 128], %f30 +.type _cmll256_decrypt_1x,#function +.size _cmll256_decrypt_1x,.-_cmll256_decrypt_1x + +.align 32 +_cmll256_decrypt_2x: + camellia_f %f16, %f2, %f0, %f2 + camellia_f %f16, %f6, %f4, %f6 + camellia_f %f18, %f0, %f2, %f0 + camellia_f %f18, %f4, %f6, %f4 + ldd [$key - 8], %f16 + ldd [$key - 16], %f18 + camellia_f %f20, %f2, %f0, %f2 + camellia_f %f20, %f6, %f4, %f6 + camellia_f %f22, %f0, %f2, %f0 + camellia_f %f22, %f4, %f6, %f4 + ldd [$key - 24], %f20 + ldd [$key - 32], %f22 + camellia_f %f24, %f2, %f0, %f2 + camellia_f %f24, %f6, %f4, %f6 + camellia_f %f26, %f0, %f2, %f0 + camellia_f %f26, %f4, %f6, %f4 + ldd [$key - 40], %f24 + ldd [$key - 48], %f26 + camellia_fl %f28, %f0, %f0 + camellia_fl %f28, %f4, %f4 + camellia_fli %f30, %f2, %f2 + camellia_fli %f30, %f6, %f6 + ldd [$key - 56], %f28 + ldd [$key - 64], %f30 +___ +for ($i=1; $i<3; $i++) { + $code.=<<___; + camellia_f %f`16+16*$i+0`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+0`, %f6, %f4, %f6 + camellia_f %f`16+16*$i+2`, %f0, %f2, %f0 + camellia_f %f`16+16*$i+2`, %f4, %f6, %f4 + camellia_f %f`16+16*$i+4`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+4`, %f6, %f4, %f6 + camellia_f %f`16+16*$i+6`, %f0, %f2, %f0 + camellia_f %f`16+16*$i+6`, %f4, %f6, %f4 + camellia_f %f`16+16*$i+8`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+8`, %f6, %f4, %f6 + camellia_f %f`16+16*$i+10`, %f0, %f2, %f0 + camellia_f %f`16+16*$i+10`, %f4, %f6, %f4 + camellia_fl %f`16+16*$i+12`, %f0, %f0 + camellia_fl %f`16+16*$i+12`, %f4, %f4 + camellia_fli %f`16+16*$i+14`, %f2, %f2 + camellia_fli %f`16+16*$i+14`, %f6, %f6 +___ +} +$code.=<<___; + camellia_f %f16, %f2, %f0, %f2 + camellia_f %f16, %f6, %f4, %f6 + camellia_f %f18, %f0, %f2, %f0 + camellia_f %f18, %f4, %f6, %f4 + ldd [$key + 184], %f16 + ldd [$key + 176], %f18 + camellia_f %f20, %f2, %f0, %f2 + camellia_f %f20, %f6, %f4, %f6 + camellia_f %f22, %f0, %f2, %f0 + camellia_f %f22, %f4, %f6, %f4 + ldd [$key + 168], %f20 + ldd [$key + 160], %f22 + camellia_f %f24, %f2, %f0, %f8 + camellia_f %f24, %f6, %f4, %f10 + camellia_f %f26, %f0, %f8, %f2 + camellia_f %f26, %f4, %f10, %f6 + ldd [$key + 152], %f24 + ldd [$key + 144], %f26 + fxor %f30, %f8, %f0 + fxor %f30, %f10, %f4 + fxor %f28, %f2, %f2 + fxor %f28, %f6, %f6 + ldd [$key + 136], %f28 + retl + ldd [$key + 128], %f30 +.type _cmll256_decrypt_2x,#function +.size _cmll256_decrypt_2x,.-_cmll256_decrypt_2x +___ + +&alg_cbc_encrypt_implement("cmll",128); +&alg_cbc_encrypt_implement("cmll",256); + +&alg_cbc_decrypt_implement("cmll",128); +&alg_cbc_decrypt_implement("cmll",256); + +if ($::evp) { + &alg_ctr32_implement("cmll",128); + &alg_ctr32_implement("cmll",256); +} +}}} + +if (!$::evp) { +$code.=<<___; +.global Camellia_encrypt +Camellia_encrypt=cmll_t4_encrypt +.global Camellia_decrypt +Camellia_decrypt=cmll_t4_decrypt +.global Camellia_set_key +.align 32 +Camellia_set_key: + andcc %o2, 7, %g0 ! double-check alignment + bnz,a,pn %icc, 1f + mov -1, %o0 + brz,a,pn %o0, 1f + mov -1, %o0 + brz,a,pn %o2, 1f + mov -1, %o0 + andncc %o1, 0x1c0, %g0 + bnz,a,pn %icc, 1f + mov -2, %o0 + cmp %o1, 128 + bl,a,pn %icc, 1f + mov -2, %o0 + b cmll_t4_set_key + nop +1: retl + nop +.type Camellia_set_key,#function +.size Camellia_set_key,.-Camellia_set_key +___ + +my ($inp,$out,$len,$key,$ivec,$enc)=map("%o$_",(0..5)); + +$code.=<<___; +.globl Camellia_cbc_encrypt +.align 32 +Camellia_cbc_encrypt: + ld [$key + 272], %g1 + nop + brz $enc, .Lcbc_decrypt + cmp %g1, 3 + + be,pt %icc, cmll128_t4_cbc_encrypt + nop + ba cmll256_t4_cbc_encrypt + nop + +.Lcbc_decrypt: + be,pt %icc, cmll128_t4_cbc_decrypt + nop + ba cmll256_t4_cbc_decrypt + nop +.type Camellia_cbc_encrypt,#function +.size Camellia_cbc_encrypt,.-Camellia_cbc_encrypt +___ +} + +&emit_assembler(); + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/build.info new file mode 100644 index 000000000..e36a19bd4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/build.info @@ -0,0 +1,13 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + cmll_ecb.c cmll_ofb.c cmll_cfb.c cmll_ctr.c \ + {- $target{cmll_asm_src} -} + +GENERATE[cmll-x86.s]=asm/cmll-x86.pl \ + $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) \ + $(PROCESSOR) +DEPEND[cmll-x86.s]=../perlasm/x86asm.pl +GENERATE[cmll-x86_64.s]=asm/cmll-x86_64.pl $(PERLASM_SCHEME) +GENERATE[cmllt4-sparcv9.S]=asm/cmllt4-sparcv9.pl $(PERLASM_SCHEME) +INCLUDE[cmllt4-sparcv9.o]=.. +DEPEND[cmllt4-sparcv9.S]=../perlasm/sparcv9_modes.pl diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/camellia.c b/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/camellia.c new file mode 100644 index 000000000..c200b8230 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/camellia.c @@ -0,0 +1,501 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* ==================================================================== + * Copyright 2006 NTT (Nippon Telegraph and Telephone Corporation) . + * ALL RIGHTS RESERVED. + * + * Intellectual Property information for Camellia: + * http://info.isl.ntt.co.jp/crypt/eng/info/chiteki.html + * + * News Release for Announcement of Camellia open source: + * http://www.ntt.co.jp/news/news06e/0604/060413a.html + * + * The Camellia Code included herein is developed by + * NTT (Nippon Telegraph and Telephone Corporation), and is contributed + * to the OpenSSL project. + */ + +/* + * Algorithm Specification + * http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html + */ + +/* + * This release balances code size and performance. In particular key + * schedule setup is fully unrolled, because doing so *significantly* + * reduces amount of instructions per setup round and code increase is + * justifiable. In block functions on the other hand only inner loops + * are unrolled, as full unroll gives only nominal performance boost, + * while code size grows 4 or 7 times. Also, unlike previous versions + * this one "encourages" compiler to keep intermediate variables in + * registers, which should give better "all round" results, in other + * words reasonable performance even with not so modern compilers. + */ + +#include +#include "cmll_locl.h" +#include +#include + +#define RightRotate(x, s) ( ((x) >> (s)) + ((x) << (32 - s)) ) +#define LeftRotate(x, s) ( ((x) << (s)) + ((x) >> (32 - s)) ) + +#define GETU32(p) (((u32)(p)[0] << 24) ^ ((u32)(p)[1] << 16) ^ ((u32)(p)[2] << 8) ^ ((u32)(p)[3])) +#define PUTU32(p,v) ((p)[0] = (u8)((v) >> 24), (p)[1] = (u8)((v) >> 16), (p)[2] = (u8)((v) >> 8), (p)[3] = (u8)(v)) + +/* S-box data */ +#define SBOX1_1110 Camellia_SBOX[0] +#define SBOX4_4404 Camellia_SBOX[1] +#define SBOX2_0222 Camellia_SBOX[2] +#define SBOX3_3033 Camellia_SBOX[3] +static const u32 Camellia_SBOX[][256] = { + {0x70707000, 0x82828200, 0x2c2c2c00, 0xececec00, 0xb3b3b300, 0x27272700, + 0xc0c0c000, 0xe5e5e500, 0xe4e4e400, 0x85858500, 0x57575700, 0x35353500, + 0xeaeaea00, 0x0c0c0c00, 0xaeaeae00, 0x41414100, 0x23232300, 0xefefef00, + 0x6b6b6b00, 0x93939300, 0x45454500, 0x19191900, 0xa5a5a500, 0x21212100, + 0xededed00, 0x0e0e0e00, 0x4f4f4f00, 0x4e4e4e00, 0x1d1d1d00, 0x65656500, + 0x92929200, 0xbdbdbd00, 0x86868600, 0xb8b8b800, 0xafafaf00, 0x8f8f8f00, + 0x7c7c7c00, 0xebebeb00, 0x1f1f1f00, 0xcecece00, 0x3e3e3e00, 0x30303000, + 0xdcdcdc00, 0x5f5f5f00, 0x5e5e5e00, 0xc5c5c500, 0x0b0b0b00, 0x1a1a1a00, + 0xa6a6a600, 0xe1e1e100, 0x39393900, 0xcacaca00, 0xd5d5d500, 0x47474700, + 0x5d5d5d00, 0x3d3d3d00, 0xd9d9d900, 0x01010100, 0x5a5a5a00, 0xd6d6d600, + 0x51515100, 0x56565600, 0x6c6c6c00, 0x4d4d4d00, 0x8b8b8b00, 0x0d0d0d00, + 0x9a9a9a00, 0x66666600, 0xfbfbfb00, 0xcccccc00, 0xb0b0b000, 0x2d2d2d00, + 0x74747400, 0x12121200, 0x2b2b2b00, 0x20202000, 0xf0f0f000, 0xb1b1b100, + 0x84848400, 0x99999900, 0xdfdfdf00, 0x4c4c4c00, 0xcbcbcb00, 0xc2c2c200, + 0x34343400, 0x7e7e7e00, 0x76767600, 0x05050500, 0x6d6d6d00, 0xb7b7b700, + 0xa9a9a900, 0x31313100, 0xd1d1d100, 0x17171700, 0x04040400, 0xd7d7d700, + 0x14141400, 0x58585800, 0x3a3a3a00, 0x61616100, 0xdedede00, 0x1b1b1b00, + 0x11111100, 0x1c1c1c00, 0x32323200, 0x0f0f0f00, 0x9c9c9c00, 0x16161600, + 0x53535300, 0x18181800, 0xf2f2f200, 0x22222200, 0xfefefe00, 0x44444400, + 0xcfcfcf00, 0xb2b2b200, 0xc3c3c300, 0xb5b5b500, 0x7a7a7a00, 0x91919100, + 0x24242400, 0x08080800, 0xe8e8e800, 0xa8a8a800, 0x60606000, 0xfcfcfc00, + 0x69696900, 0x50505000, 0xaaaaaa00, 0xd0d0d000, 0xa0a0a000, 0x7d7d7d00, + 0xa1a1a100, 0x89898900, 0x62626200, 0x97979700, 0x54545400, 0x5b5b5b00, + 0x1e1e1e00, 0x95959500, 0xe0e0e000, 0xffffff00, 0x64646400, 0xd2d2d200, + 0x10101000, 0xc4c4c400, 0x00000000, 0x48484800, 0xa3a3a300, 0xf7f7f700, + 0x75757500, 0xdbdbdb00, 0x8a8a8a00, 0x03030300, 0xe6e6e600, 0xdadada00, + 0x09090900, 0x3f3f3f00, 0xdddddd00, 0x94949400, 0x87878700, 0x5c5c5c00, + 0x83838300, 0x02020200, 0xcdcdcd00, 0x4a4a4a00, 0x90909000, 0x33333300, + 0x73737300, 0x67676700, 0xf6f6f600, 0xf3f3f300, 0x9d9d9d00, 0x7f7f7f00, + 0xbfbfbf00, 0xe2e2e200, 0x52525200, 0x9b9b9b00, 0xd8d8d800, 0x26262600, + 0xc8c8c800, 0x37373700, 0xc6c6c600, 0x3b3b3b00, 0x81818100, 0x96969600, + 0x6f6f6f00, 0x4b4b4b00, 0x13131300, 0xbebebe00, 0x63636300, 0x2e2e2e00, + 0xe9e9e900, 0x79797900, 0xa7a7a700, 0x8c8c8c00, 0x9f9f9f00, 0x6e6e6e00, + 0xbcbcbc00, 0x8e8e8e00, 0x29292900, 0xf5f5f500, 0xf9f9f900, 0xb6b6b600, + 0x2f2f2f00, 0xfdfdfd00, 0xb4b4b400, 0x59595900, 0x78787800, 0x98989800, + 0x06060600, 0x6a6a6a00, 0xe7e7e700, 0x46464600, 0x71717100, 0xbababa00, + 0xd4d4d400, 0x25252500, 0xababab00, 0x42424200, 0x88888800, 0xa2a2a200, + 0x8d8d8d00, 0xfafafa00, 0x72727200, 0x07070700, 0xb9b9b900, 0x55555500, + 0xf8f8f800, 0xeeeeee00, 0xacacac00, 0x0a0a0a00, 0x36363600, 0x49494900, + 0x2a2a2a00, 0x68686800, 0x3c3c3c00, 0x38383800, 0xf1f1f100, 0xa4a4a400, + 0x40404000, 0x28282800, 0xd3d3d300, 0x7b7b7b00, 0xbbbbbb00, 0xc9c9c900, + 0x43434300, 0xc1c1c100, 0x15151500, 0xe3e3e300, 0xadadad00, 0xf4f4f400, + 0x77777700, 0xc7c7c700, 0x80808000, 0x9e9e9e00}, + {0x70700070, 0x2c2c002c, 0xb3b300b3, 0xc0c000c0, 0xe4e400e4, 0x57570057, + 0xeaea00ea, 0xaeae00ae, 0x23230023, 0x6b6b006b, 0x45450045, 0xa5a500a5, + 0xeded00ed, 0x4f4f004f, 0x1d1d001d, 0x92920092, 0x86860086, 0xafaf00af, + 0x7c7c007c, 0x1f1f001f, 0x3e3e003e, 0xdcdc00dc, 0x5e5e005e, 0x0b0b000b, + 0xa6a600a6, 0x39390039, 0xd5d500d5, 0x5d5d005d, 0xd9d900d9, 0x5a5a005a, + 0x51510051, 0x6c6c006c, 0x8b8b008b, 0x9a9a009a, 0xfbfb00fb, 0xb0b000b0, + 0x74740074, 0x2b2b002b, 0xf0f000f0, 0x84840084, 0xdfdf00df, 0xcbcb00cb, + 0x34340034, 0x76760076, 0x6d6d006d, 0xa9a900a9, 0xd1d100d1, 0x04040004, + 0x14140014, 0x3a3a003a, 0xdede00de, 0x11110011, 0x32320032, 0x9c9c009c, + 0x53530053, 0xf2f200f2, 0xfefe00fe, 0xcfcf00cf, 0xc3c300c3, 0x7a7a007a, + 0x24240024, 0xe8e800e8, 0x60600060, 0x69690069, 0xaaaa00aa, 0xa0a000a0, + 0xa1a100a1, 0x62620062, 0x54540054, 0x1e1e001e, 0xe0e000e0, 0x64640064, + 0x10100010, 0x00000000, 0xa3a300a3, 0x75750075, 0x8a8a008a, 0xe6e600e6, + 0x09090009, 0xdddd00dd, 0x87870087, 0x83830083, 0xcdcd00cd, 0x90900090, + 0x73730073, 0xf6f600f6, 0x9d9d009d, 0xbfbf00bf, 0x52520052, 0xd8d800d8, + 0xc8c800c8, 0xc6c600c6, 0x81810081, 0x6f6f006f, 0x13130013, 0x63630063, + 0xe9e900e9, 0xa7a700a7, 0x9f9f009f, 0xbcbc00bc, 0x29290029, 0xf9f900f9, + 0x2f2f002f, 0xb4b400b4, 0x78780078, 0x06060006, 0xe7e700e7, 0x71710071, + 0xd4d400d4, 0xabab00ab, 0x88880088, 0x8d8d008d, 0x72720072, 0xb9b900b9, + 0xf8f800f8, 0xacac00ac, 0x36360036, 0x2a2a002a, 0x3c3c003c, 0xf1f100f1, + 0x40400040, 0xd3d300d3, 0xbbbb00bb, 0x43430043, 0x15150015, 0xadad00ad, + 0x77770077, 0x80800080, 0x82820082, 0xecec00ec, 0x27270027, 0xe5e500e5, + 0x85850085, 0x35350035, 0x0c0c000c, 0x41410041, 0xefef00ef, 0x93930093, + 0x19190019, 0x21210021, 0x0e0e000e, 0x4e4e004e, 0x65650065, 0xbdbd00bd, + 0xb8b800b8, 0x8f8f008f, 0xebeb00eb, 0xcece00ce, 0x30300030, 0x5f5f005f, + 0xc5c500c5, 0x1a1a001a, 0xe1e100e1, 0xcaca00ca, 0x47470047, 0x3d3d003d, + 0x01010001, 0xd6d600d6, 0x56560056, 0x4d4d004d, 0x0d0d000d, 0x66660066, + 0xcccc00cc, 0x2d2d002d, 0x12120012, 0x20200020, 0xb1b100b1, 0x99990099, + 0x4c4c004c, 0xc2c200c2, 0x7e7e007e, 0x05050005, 0xb7b700b7, 0x31310031, + 0x17170017, 0xd7d700d7, 0x58580058, 0x61610061, 0x1b1b001b, 0x1c1c001c, + 0x0f0f000f, 0x16160016, 0x18180018, 0x22220022, 0x44440044, 0xb2b200b2, + 0xb5b500b5, 0x91910091, 0x08080008, 0xa8a800a8, 0xfcfc00fc, 0x50500050, + 0xd0d000d0, 0x7d7d007d, 0x89890089, 0x97970097, 0x5b5b005b, 0x95950095, + 0xffff00ff, 0xd2d200d2, 0xc4c400c4, 0x48480048, 0xf7f700f7, 0xdbdb00db, + 0x03030003, 0xdada00da, 0x3f3f003f, 0x94940094, 0x5c5c005c, 0x02020002, + 0x4a4a004a, 0x33330033, 0x67670067, 0xf3f300f3, 0x7f7f007f, 0xe2e200e2, + 0x9b9b009b, 0x26260026, 0x37370037, 0x3b3b003b, 0x96960096, 0x4b4b004b, + 0xbebe00be, 0x2e2e002e, 0x79790079, 0x8c8c008c, 0x6e6e006e, 0x8e8e008e, + 0xf5f500f5, 0xb6b600b6, 0xfdfd00fd, 0x59590059, 0x98980098, 0x6a6a006a, + 0x46460046, 0xbaba00ba, 0x25250025, 0x42420042, 0xa2a200a2, 0xfafa00fa, + 0x07070007, 0x55550055, 0xeeee00ee, 0x0a0a000a, 0x49490049, 0x68680068, + 0x38380038, 0xa4a400a4, 0x28280028, 0x7b7b007b, 0xc9c900c9, 0xc1c100c1, + 0xe3e300e3, 0xf4f400f4, 0xc7c700c7, 0x9e9e009e}, + {0x00e0e0e0, 0x00050505, 0x00585858, 0x00d9d9d9, 0x00676767, 0x004e4e4e, + 0x00818181, 0x00cbcbcb, 0x00c9c9c9, 0x000b0b0b, 0x00aeaeae, 0x006a6a6a, + 0x00d5d5d5, 0x00181818, 0x005d5d5d, 0x00828282, 0x00464646, 0x00dfdfdf, + 0x00d6d6d6, 0x00272727, 0x008a8a8a, 0x00323232, 0x004b4b4b, 0x00424242, + 0x00dbdbdb, 0x001c1c1c, 0x009e9e9e, 0x009c9c9c, 0x003a3a3a, 0x00cacaca, + 0x00252525, 0x007b7b7b, 0x000d0d0d, 0x00717171, 0x005f5f5f, 0x001f1f1f, + 0x00f8f8f8, 0x00d7d7d7, 0x003e3e3e, 0x009d9d9d, 0x007c7c7c, 0x00606060, + 0x00b9b9b9, 0x00bebebe, 0x00bcbcbc, 0x008b8b8b, 0x00161616, 0x00343434, + 0x004d4d4d, 0x00c3c3c3, 0x00727272, 0x00959595, 0x00ababab, 0x008e8e8e, + 0x00bababa, 0x007a7a7a, 0x00b3b3b3, 0x00020202, 0x00b4b4b4, 0x00adadad, + 0x00a2a2a2, 0x00acacac, 0x00d8d8d8, 0x009a9a9a, 0x00171717, 0x001a1a1a, + 0x00353535, 0x00cccccc, 0x00f7f7f7, 0x00999999, 0x00616161, 0x005a5a5a, + 0x00e8e8e8, 0x00242424, 0x00565656, 0x00404040, 0x00e1e1e1, 0x00636363, + 0x00090909, 0x00333333, 0x00bfbfbf, 0x00989898, 0x00979797, 0x00858585, + 0x00686868, 0x00fcfcfc, 0x00ececec, 0x000a0a0a, 0x00dadada, 0x006f6f6f, + 0x00535353, 0x00626262, 0x00a3a3a3, 0x002e2e2e, 0x00080808, 0x00afafaf, + 0x00282828, 0x00b0b0b0, 0x00747474, 0x00c2c2c2, 0x00bdbdbd, 0x00363636, + 0x00222222, 0x00383838, 0x00646464, 0x001e1e1e, 0x00393939, 0x002c2c2c, + 0x00a6a6a6, 0x00303030, 0x00e5e5e5, 0x00444444, 0x00fdfdfd, 0x00888888, + 0x009f9f9f, 0x00656565, 0x00878787, 0x006b6b6b, 0x00f4f4f4, 0x00232323, + 0x00484848, 0x00101010, 0x00d1d1d1, 0x00515151, 0x00c0c0c0, 0x00f9f9f9, + 0x00d2d2d2, 0x00a0a0a0, 0x00555555, 0x00a1a1a1, 0x00414141, 0x00fafafa, + 0x00434343, 0x00131313, 0x00c4c4c4, 0x002f2f2f, 0x00a8a8a8, 0x00b6b6b6, + 0x003c3c3c, 0x002b2b2b, 0x00c1c1c1, 0x00ffffff, 0x00c8c8c8, 0x00a5a5a5, + 0x00202020, 0x00898989, 0x00000000, 0x00909090, 0x00474747, 0x00efefef, + 0x00eaeaea, 0x00b7b7b7, 0x00151515, 0x00060606, 0x00cdcdcd, 0x00b5b5b5, + 0x00121212, 0x007e7e7e, 0x00bbbbbb, 0x00292929, 0x000f0f0f, 0x00b8b8b8, + 0x00070707, 0x00040404, 0x009b9b9b, 0x00949494, 0x00212121, 0x00666666, + 0x00e6e6e6, 0x00cecece, 0x00ededed, 0x00e7e7e7, 0x003b3b3b, 0x00fefefe, + 0x007f7f7f, 0x00c5c5c5, 0x00a4a4a4, 0x00373737, 0x00b1b1b1, 0x004c4c4c, + 0x00919191, 0x006e6e6e, 0x008d8d8d, 0x00767676, 0x00030303, 0x002d2d2d, + 0x00dedede, 0x00969696, 0x00262626, 0x007d7d7d, 0x00c6c6c6, 0x005c5c5c, + 0x00d3d3d3, 0x00f2f2f2, 0x004f4f4f, 0x00191919, 0x003f3f3f, 0x00dcdcdc, + 0x00797979, 0x001d1d1d, 0x00525252, 0x00ebebeb, 0x00f3f3f3, 0x006d6d6d, + 0x005e5e5e, 0x00fbfbfb, 0x00696969, 0x00b2b2b2, 0x00f0f0f0, 0x00313131, + 0x000c0c0c, 0x00d4d4d4, 0x00cfcfcf, 0x008c8c8c, 0x00e2e2e2, 0x00757575, + 0x00a9a9a9, 0x004a4a4a, 0x00575757, 0x00848484, 0x00111111, 0x00454545, + 0x001b1b1b, 0x00f5f5f5, 0x00e4e4e4, 0x000e0e0e, 0x00737373, 0x00aaaaaa, + 0x00f1f1f1, 0x00dddddd, 0x00595959, 0x00141414, 0x006c6c6c, 0x00929292, + 0x00545454, 0x00d0d0d0, 0x00787878, 0x00707070, 0x00e3e3e3, 0x00494949, + 0x00808080, 0x00505050, 0x00a7a7a7, 0x00f6f6f6, 0x00777777, 0x00939393, + 0x00868686, 0x00838383, 0x002a2a2a, 0x00c7c7c7, 0x005b5b5b, 0x00e9e9e9, + 0x00eeeeee, 0x008f8f8f, 0x00010101, 0x003d3d3d}, + {0x38003838, 0x41004141, 0x16001616, 0x76007676, 0xd900d9d9, 0x93009393, + 0x60006060, 0xf200f2f2, 0x72007272, 0xc200c2c2, 0xab00abab, 0x9a009a9a, + 0x75007575, 0x06000606, 0x57005757, 0xa000a0a0, 0x91009191, 0xf700f7f7, + 0xb500b5b5, 0xc900c9c9, 0xa200a2a2, 0x8c008c8c, 0xd200d2d2, 0x90009090, + 0xf600f6f6, 0x07000707, 0xa700a7a7, 0x27002727, 0x8e008e8e, 0xb200b2b2, + 0x49004949, 0xde00dede, 0x43004343, 0x5c005c5c, 0xd700d7d7, 0xc700c7c7, + 0x3e003e3e, 0xf500f5f5, 0x8f008f8f, 0x67006767, 0x1f001f1f, 0x18001818, + 0x6e006e6e, 0xaf00afaf, 0x2f002f2f, 0xe200e2e2, 0x85008585, 0x0d000d0d, + 0x53005353, 0xf000f0f0, 0x9c009c9c, 0x65006565, 0xea00eaea, 0xa300a3a3, + 0xae00aeae, 0x9e009e9e, 0xec00ecec, 0x80008080, 0x2d002d2d, 0x6b006b6b, + 0xa800a8a8, 0x2b002b2b, 0x36003636, 0xa600a6a6, 0xc500c5c5, 0x86008686, + 0x4d004d4d, 0x33003333, 0xfd00fdfd, 0x66006666, 0x58005858, 0x96009696, + 0x3a003a3a, 0x09000909, 0x95009595, 0x10001010, 0x78007878, 0xd800d8d8, + 0x42004242, 0xcc00cccc, 0xef00efef, 0x26002626, 0xe500e5e5, 0x61006161, + 0x1a001a1a, 0x3f003f3f, 0x3b003b3b, 0x82008282, 0xb600b6b6, 0xdb00dbdb, + 0xd400d4d4, 0x98009898, 0xe800e8e8, 0x8b008b8b, 0x02000202, 0xeb00ebeb, + 0x0a000a0a, 0x2c002c2c, 0x1d001d1d, 0xb000b0b0, 0x6f006f6f, 0x8d008d8d, + 0x88008888, 0x0e000e0e, 0x19001919, 0x87008787, 0x4e004e4e, 0x0b000b0b, + 0xa900a9a9, 0x0c000c0c, 0x79007979, 0x11001111, 0x7f007f7f, 0x22002222, + 0xe700e7e7, 0x59005959, 0xe100e1e1, 0xda00dada, 0x3d003d3d, 0xc800c8c8, + 0x12001212, 0x04000404, 0x74007474, 0x54005454, 0x30003030, 0x7e007e7e, + 0xb400b4b4, 0x28002828, 0x55005555, 0x68006868, 0x50005050, 0xbe00bebe, + 0xd000d0d0, 0xc400c4c4, 0x31003131, 0xcb00cbcb, 0x2a002a2a, 0xad00adad, + 0x0f000f0f, 0xca00caca, 0x70007070, 0xff00ffff, 0x32003232, 0x69006969, + 0x08000808, 0x62006262, 0x00000000, 0x24002424, 0xd100d1d1, 0xfb00fbfb, + 0xba00baba, 0xed00eded, 0x45004545, 0x81008181, 0x73007373, 0x6d006d6d, + 0x84008484, 0x9f009f9f, 0xee00eeee, 0x4a004a4a, 0xc300c3c3, 0x2e002e2e, + 0xc100c1c1, 0x01000101, 0xe600e6e6, 0x25002525, 0x48004848, 0x99009999, + 0xb900b9b9, 0xb300b3b3, 0x7b007b7b, 0xf900f9f9, 0xce00cece, 0xbf00bfbf, + 0xdf00dfdf, 0x71007171, 0x29002929, 0xcd00cdcd, 0x6c006c6c, 0x13001313, + 0x64006464, 0x9b009b9b, 0x63006363, 0x9d009d9d, 0xc000c0c0, 0x4b004b4b, + 0xb700b7b7, 0xa500a5a5, 0x89008989, 0x5f005f5f, 0xb100b1b1, 0x17001717, + 0xf400f4f4, 0xbc00bcbc, 0xd300d3d3, 0x46004646, 0xcf00cfcf, 0x37003737, + 0x5e005e5e, 0x47004747, 0x94009494, 0xfa00fafa, 0xfc00fcfc, 0x5b005b5b, + 0x97009797, 0xfe00fefe, 0x5a005a5a, 0xac00acac, 0x3c003c3c, 0x4c004c4c, + 0x03000303, 0x35003535, 0xf300f3f3, 0x23002323, 0xb800b8b8, 0x5d005d5d, + 0x6a006a6a, 0x92009292, 0xd500d5d5, 0x21002121, 0x44004444, 0x51005151, + 0xc600c6c6, 0x7d007d7d, 0x39003939, 0x83008383, 0xdc00dcdc, 0xaa00aaaa, + 0x7c007c7c, 0x77007777, 0x56005656, 0x05000505, 0x1b001b1b, 0xa400a4a4, + 0x15001515, 0x34003434, 0x1e001e1e, 0x1c001c1c, 0xf800f8f8, 0x52005252, + 0x20002020, 0x14001414, 0xe900e9e9, 0xbd00bdbd, 0xdd00dddd, 0xe400e4e4, + 0xa100a1a1, 0xe000e0e0, 0x8a008a8a, 0xf100f1f1, 0xd600d6d6, 0x7a007a7a, + 0xbb00bbbb, 0xe300e3e3, 0x40004040, 0x4f004f4f} +}; + +/* Key generation constants */ +static const u32 SIGMA[] = { + 0xa09e667f, 0x3bcc908b, 0xb67ae858, 0x4caa73b2, 0xc6ef372f, 0xe94f82be, + 0x54ff53a5, 0xf1d36f1c, 0x10e527fa, 0xde682d1d, 0xb05688c2, 0xb3e6c1fd +}; + +/* The phi algorithm given in C.2.7 of the Camellia spec document. */ +/* + * This version does not attempt to minimize amount of temporary + * variables, but instead explicitly exposes algorithm's parallelism. + * It is therefore most appropriate for platforms with not less than + * ~16 registers. For platforms with less registers [well, x86 to be + * specific] assembler version should be/is provided anyway... + */ +#define Camellia_Feistel(_s0,_s1,_s2,_s3,_key) do {\ + register u32 _t0,_t1,_t2,_t3;\ +\ + _t0 = _s0 ^ (_key)[0];\ + _t3 = SBOX4_4404[_t0&0xff];\ + _t1 = _s1 ^ (_key)[1];\ + _t3 ^= SBOX3_3033[(_t0 >> 8)&0xff];\ + _t2 = SBOX1_1110[_t1&0xff];\ + _t3 ^= SBOX2_0222[(_t0 >> 16)&0xff];\ + _t2 ^= SBOX4_4404[(_t1 >> 8)&0xff];\ + _t3 ^= SBOX1_1110[(_t0 >> 24)];\ + _t2 ^= _t3;\ + _t3 = RightRotate(_t3,8);\ + _t2 ^= SBOX3_3033[(_t1 >> 16)&0xff];\ + _s3 ^= _t3;\ + _t2 ^= SBOX2_0222[(_t1 >> 24)];\ + _s2 ^= _t2; \ + _s3 ^= _t2;\ +} while(0) + +/* + * Note that n has to be less than 32. Rotations for larger amount + * of bits are achieved by "rotating" order of s-elements and + * adjusting n accordingly, e.g. RotLeft128(s1,s2,s3,s0,n-32). + */ +#define RotLeft128(_s0,_s1,_s2,_s3,_n) do {\ + u32 _t0=_s0>>(32-_n);\ + _s0 = (_s0<<_n) | (_s1>>(32-_n));\ + _s1 = (_s1<<_n) | (_s2>>(32-_n));\ + _s2 = (_s2<<_n) | (_s3>>(32-_n));\ + _s3 = (_s3<<_n) | _t0;\ +} while (0) + +int Camellia_Ekeygen(int keyBitLength, const u8 *rawKey, KEY_TABLE_TYPE k) +{ + register u32 s0, s1, s2, s3; + + k[0] = s0 = GETU32(rawKey); + k[1] = s1 = GETU32(rawKey + 4); + k[2] = s2 = GETU32(rawKey + 8); + k[3] = s3 = GETU32(rawKey + 12); + + if (keyBitLength != 128) { + k[8] = s0 = GETU32(rawKey + 16); + k[9] = s1 = GETU32(rawKey + 20); + if (keyBitLength == 192) { + k[10] = s2 = ~s0; + k[11] = s3 = ~s1; + } else { + k[10] = s2 = GETU32(rawKey + 24); + k[11] = s3 = GETU32(rawKey + 28); + } + s0 ^= k[0], s1 ^= k[1], s2 ^= k[2], s3 ^= k[3]; + } + + /* Use the Feistel routine to scramble the key material */ + Camellia_Feistel(s0, s1, s2, s3, SIGMA + 0); + Camellia_Feistel(s2, s3, s0, s1, SIGMA + 2); + + s0 ^= k[0], s1 ^= k[1], s2 ^= k[2], s3 ^= k[3]; + Camellia_Feistel(s0, s1, s2, s3, SIGMA + 4); + Camellia_Feistel(s2, s3, s0, s1, SIGMA + 6); + + /* Fill the keyTable. Requires many block rotations. */ + if (keyBitLength == 128) { + k[4] = s0, k[5] = s1, k[6] = s2, k[7] = s3; + RotLeft128(s0, s1, s2, s3, 15); /* KA <<< 15 */ + k[12] = s0, k[13] = s1, k[14] = s2, k[15] = s3; + RotLeft128(s0, s1, s2, s3, 15); /* KA <<< 30 */ + k[16] = s0, k[17] = s1, k[18] = s2, k[19] = s3; + RotLeft128(s0, s1, s2, s3, 15); /* KA <<< 45 */ + k[24] = s0, k[25] = s1; + RotLeft128(s0, s1, s2, s3, 15); /* KA <<< 60 */ + k[28] = s0, k[29] = s1, k[30] = s2, k[31] = s3; + RotLeft128(s1, s2, s3, s0, 2); /* KA <<< 94 */ + k[40] = s1, k[41] = s2, k[42] = s3, k[43] = s0; + RotLeft128(s1, s2, s3, s0, 17); /* KA <<<111 */ + k[48] = s1, k[49] = s2, k[50] = s3, k[51] = s0; + + s0 = k[0], s1 = k[1], s2 = k[2], s3 = k[3]; + RotLeft128(s0, s1, s2, s3, 15); /* KL <<< 15 */ + k[8] = s0, k[9] = s1, k[10] = s2, k[11] = s3; + RotLeft128(s0, s1, s2, s3, 30); /* KL <<< 45 */ + k[20] = s0, k[21] = s1, k[22] = s2, k[23] = s3; + RotLeft128(s0, s1, s2, s3, 15); /* KL <<< 60 */ + k[26] = s2, k[27] = s3; + RotLeft128(s0, s1, s2, s3, 17); /* KL <<< 77 */ + k[32] = s0, k[33] = s1, k[34] = s2, k[35] = s3; + RotLeft128(s0, s1, s2, s3, 17); /* KL <<< 94 */ + k[36] = s0, k[37] = s1, k[38] = s2, k[39] = s3; + RotLeft128(s0, s1, s2, s3, 17); /* KL <<<111 */ + k[44] = s0, k[45] = s1, k[46] = s2, k[47] = s3; + + return 3; /* grand rounds */ + } else { + k[12] = s0, k[13] = s1, k[14] = s2, k[15] = s3; + s0 ^= k[8], s1 ^= k[9], s2 ^= k[10], s3 ^= k[11]; + Camellia_Feistel(s0, s1, s2, s3, (SIGMA + 8)); + Camellia_Feistel(s2, s3, s0, s1, (SIGMA + 10)); + + k[4] = s0, k[5] = s1, k[6] = s2, k[7] = s3; + RotLeft128(s0, s1, s2, s3, 30); /* KB <<< 30 */ + k[20] = s0, k[21] = s1, k[22] = s2, k[23] = s3; + RotLeft128(s0, s1, s2, s3, 30); /* KB <<< 60 */ + k[40] = s0, k[41] = s1, k[42] = s2, k[43] = s3; + RotLeft128(s1, s2, s3, s0, 19); /* KB <<<111 */ + k[64] = s1, k[65] = s2, k[66] = s3, k[67] = s0; + + s0 = k[8], s1 = k[9], s2 = k[10], s3 = k[11]; + RotLeft128(s0, s1, s2, s3, 15); /* KR <<< 15 */ + k[8] = s0, k[9] = s1, k[10] = s2, k[11] = s3; + RotLeft128(s0, s1, s2, s3, 15); /* KR <<< 30 */ + k[16] = s0, k[17] = s1, k[18] = s2, k[19] = s3; + RotLeft128(s0, s1, s2, s3, 30); /* KR <<< 60 */ + k[36] = s0, k[37] = s1, k[38] = s2, k[39] = s3; + RotLeft128(s1, s2, s3, s0, 2); /* KR <<< 94 */ + k[52] = s1, k[53] = s2, k[54] = s3, k[55] = s0; + + s0 = k[12], s1 = k[13], s2 = k[14], s3 = k[15]; + RotLeft128(s0, s1, s2, s3, 15); /* KA <<< 15 */ + k[12] = s0, k[13] = s1, k[14] = s2, k[15] = s3; + RotLeft128(s0, s1, s2, s3, 30); /* KA <<< 45 */ + k[28] = s0, k[29] = s1, k[30] = s2, k[31] = s3; + /* KA <<< 77 */ + k[48] = s1, k[49] = s2, k[50] = s3, k[51] = s0; + RotLeft128(s1, s2, s3, s0, 17); /* KA <<< 94 */ + k[56] = s1, k[57] = s2, k[58] = s3, k[59] = s0; + + s0 = k[0], s1 = k[1], s2 = k[2], s3 = k[3]; + RotLeft128(s1, s2, s3, s0, 13); /* KL <<< 45 */ + k[24] = s1, k[25] = s2, k[26] = s3, k[27] = s0; + RotLeft128(s1, s2, s3, s0, 15); /* KL <<< 60 */ + k[32] = s1, k[33] = s2, k[34] = s3, k[35] = s0; + RotLeft128(s1, s2, s3, s0, 17); /* KL <<< 77 */ + k[44] = s1, k[45] = s2, k[46] = s3, k[47] = s0; + RotLeft128(s2, s3, s0, s1, 2); /* KL <<<111 */ + k[60] = s2, k[61] = s3, k[62] = s0, k[63] = s1; + + return 4; /* grand rounds */ + } + /* + * It is possible to perform certain precalculations, which + * would spare few cycles in block procedure. It's not done, + * because it upsets the performance balance between key + * setup and block procedures, negatively affecting overall + * throughput in applications operating on short messages + * and volatile keys. + */ +} + +void Camellia_EncryptBlock_Rounds(int grandRounds, const u8 plaintext[], + const KEY_TABLE_TYPE keyTable, + u8 ciphertext[]) +{ + register u32 s0, s1, s2, s3; + const u32 *k = keyTable, *kend = keyTable + grandRounds * 16; + + s0 = GETU32(plaintext) ^ k[0]; + s1 = GETU32(plaintext + 4) ^ k[1]; + s2 = GETU32(plaintext + 8) ^ k[2]; + s3 = GETU32(plaintext + 12) ^ k[3]; + k += 4; + + while (1) { + /* Camellia makes 6 Feistel rounds */ + Camellia_Feistel(s0, s1, s2, s3, k + 0); + Camellia_Feistel(s2, s3, s0, s1, k + 2); + Camellia_Feistel(s0, s1, s2, s3, k + 4); + Camellia_Feistel(s2, s3, s0, s1, k + 6); + Camellia_Feistel(s0, s1, s2, s3, k + 8); + Camellia_Feistel(s2, s3, s0, s1, k + 10); + k += 12; + + if (k == kend) + break; + + /* + * This is the same function as the diffusion function D of the + * accompanying documentation. See section 3.2 for properties of the + * FLlayer function. + */ + s1 ^= LeftRotate(s0 & k[0], 1); + s2 ^= s3 | k[3]; + s0 ^= s1 | k[1]; + s3 ^= LeftRotate(s2 & k[2], 1); + k += 4; + } + + s2 ^= k[0], s3 ^= k[1], s0 ^= k[2], s1 ^= k[3]; + + PUTU32(ciphertext, s2); + PUTU32(ciphertext + 4, s3); + PUTU32(ciphertext + 8, s0); + PUTU32(ciphertext + 12, s1); +} + +void Camellia_EncryptBlock(int keyBitLength, const u8 plaintext[], + const KEY_TABLE_TYPE keyTable, u8 ciphertext[]) +{ + Camellia_EncryptBlock_Rounds(keyBitLength == 128 ? 3 : 4, + plaintext, keyTable, ciphertext); +} + +void Camellia_DecryptBlock_Rounds(int grandRounds, const u8 ciphertext[], + const KEY_TABLE_TYPE keyTable, + u8 plaintext[]) +{ + u32 s0, s1, s2, s3; + const u32 *k = keyTable + grandRounds * 16, *kend = keyTable + 4; + + s0 = GETU32(ciphertext) ^ k[0]; + s1 = GETU32(ciphertext + 4) ^ k[1]; + s2 = GETU32(ciphertext + 8) ^ k[2]; + s3 = GETU32(ciphertext + 12) ^ k[3]; + + while (1) { + /* Camellia makes 6 Feistel rounds */ + k -= 12; + Camellia_Feistel(s0, s1, s2, s3, k + 10); + Camellia_Feistel(s2, s3, s0, s1, k + 8); + Camellia_Feistel(s0, s1, s2, s3, k + 6); + Camellia_Feistel(s2, s3, s0, s1, k + 4); + Camellia_Feistel(s0, s1, s2, s3, k + 2); + Camellia_Feistel(s2, s3, s0, s1, k + 0); + + if (k == kend) + break; + + /* + * This is the same function as the diffusion function D of the + * accompanying documentation. See section 3.2 for properties of the + * FLlayer function. + */ + k -= 4; + s1 ^= LeftRotate(s0 & k[2], 1); + s2 ^= s3 | k[1]; + s0 ^= s1 | k[3]; + s3 ^= LeftRotate(s2 & k[0], 1); + } + + k -= 4; + s2 ^= k[0], s3 ^= k[1], s0 ^= k[2], s1 ^= k[3]; + + PUTU32(plaintext, s2); + PUTU32(plaintext + 4, s3); + PUTU32(plaintext + 8, s0); + PUTU32(plaintext + 12, s1); +} + +void Camellia_DecryptBlock(int keyBitLength, const u8 plaintext[], + const KEY_TABLE_TYPE keyTable, u8 ciphertext[]) +{ + Camellia_DecryptBlock_Rounds(keyBitLength == 128 ? 3 : 4, + plaintext, keyTable, ciphertext); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/cmll_cbc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/cmll_cbc.c new file mode 100644 index 000000000..b19171ded --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/cmll_cbc.c @@ -0,0 +1,24 @@ +/* + * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +void Camellia_cbc_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const CAMELLIA_KEY *key, + unsigned char *ivec, const int enc) +{ + + if (enc) + CRYPTO_cbc128_encrypt(in, out, len, key, ivec, + (block128_f) Camellia_encrypt); + else + CRYPTO_cbc128_decrypt(in, out, len, key, ivec, + (block128_f) Camellia_decrypt); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/cmll_cfb.c b/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/cmll_cfb.c new file mode 100644 index 000000000..4f49eaded --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/cmll_cfb.c @@ -0,0 +1,43 @@ +/* + * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +/* + * The input and output encrypted as though 128bit cfb mode is being used. + * The extra state information to record how much of the 128bit block we have + * used is contained in *num; + */ + +void Camellia_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char *ivec, int *num, const int enc) +{ + + CRYPTO_cfb128_encrypt(in, out, length, key, ivec, num, enc, + (block128_f) Camellia_encrypt); +} + +/* N.B. This expects the input to be packed, MS bit first */ +void Camellia_cfb1_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char *ivec, int *num, const int enc) +{ + CRYPTO_cfb128_1_encrypt(in, out, length, key, ivec, num, enc, + (block128_f) Camellia_encrypt); +} + +void Camellia_cfb8_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char *ivec, int *num, const int enc) +{ + CRYPTO_cfb128_8_encrypt(in, out, length, key, ivec, num, enc, + (block128_f) Camellia_encrypt); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/cmll_ctr.c b/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/cmll_ctr.c new file mode 100644 index 000000000..161d1e18c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/cmll_ctr.c @@ -0,0 +1,22 @@ +/* + * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +void Camellia_ctr128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char ivec[CAMELLIA_BLOCK_SIZE], + unsigned char ecount_buf[CAMELLIA_BLOCK_SIZE], + unsigned int *num) +{ + + CRYPTO_ctr128_encrypt(in, out, length, key, ivec, ecount_buf, num, + (block128_f) Camellia_encrypt); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/cmll_ecb.c b/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/cmll_ecb.c new file mode 100644 index 000000000..d932f1b37 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/cmll_ecb.c @@ -0,0 +1,20 @@ +/* + * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "cmll_locl.h" + +void Camellia_ecb_encrypt(const unsigned char *in, unsigned char *out, + const CAMELLIA_KEY *key, const int enc) +{ + if (CAMELLIA_ENCRYPT == enc) + Camellia_encrypt(in, out, key); + else + Camellia_decrypt(in, out, key); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/cmll_locl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/cmll_locl.h new file mode 100644 index 000000000..6403b390d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/cmll_locl.h @@ -0,0 +1,43 @@ +/* + * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* ==================================================================== + * Copyright 2006 NTT (Nippon Telegraph and Telephone Corporation) . + * ALL RIGHTS RESERVED. + * + * Intellectual Property information for Camellia: + * http://info.isl.ntt.co.jp/crypt/eng/info/chiteki.html + * + * News Release for Announcement of Camellia open source: + * http://www.ntt.co.jp/news/news06e/0604/060413a.html + * + * The Camellia Code included herein is developed by + * NTT (Nippon Telegraph and Telephone Corporation), and is contributed + * to the OpenSSL project. + */ + +#ifndef HEADER_CAMELLIA_LOCL_H +# define HEADER_CAMELLIA_LOCL_H + +typedef unsigned int u32; +typedef unsigned char u8; + +int Camellia_Ekeygen(int keyBitLength, const u8 *rawKey, + KEY_TABLE_TYPE keyTable); +void Camellia_EncryptBlock_Rounds(int grandRounds, const u8 plaintext[], + const KEY_TABLE_TYPE keyTable, + u8 ciphertext[]); +void Camellia_DecryptBlock_Rounds(int grandRounds, const u8 ciphertext[], + const KEY_TABLE_TYPE keyTable, + u8 plaintext[]); +void Camellia_EncryptBlock(int keyBitLength, const u8 plaintext[], + const KEY_TABLE_TYPE keyTable, u8 ciphertext[]); +void Camellia_DecryptBlock(int keyBitLength, const u8 ciphertext[], + const KEY_TABLE_TYPE keyTable, u8 plaintext[]); +#endif /* #ifndef HEADER_CAMELLIA_LOCL_H */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/cmll_misc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/cmll_misc.c new file mode 100644 index 000000000..e5f014b79 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/cmll_misc.c @@ -0,0 +1,35 @@ +/* + * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "cmll_locl.h" + +int Camellia_set_key(const unsigned char *userKey, const int bits, + CAMELLIA_KEY *key) +{ + if (!userKey || !key) + return -1; + if (bits != 128 && bits != 192 && bits != 256) + return -2; + key->grand_rounds = Camellia_Ekeygen(bits, userKey, key->u.rd_key); + return 0; +} + +void Camellia_encrypt(const unsigned char *in, unsigned char *out, + const CAMELLIA_KEY *key) +{ + Camellia_EncryptBlock_Rounds(key->grand_rounds, in, key->u.rd_key, out); +} + +void Camellia_decrypt(const unsigned char *in, unsigned char *out, + const CAMELLIA_KEY *key) +{ + Camellia_DecryptBlock_Rounds(key->grand_rounds, in, key->u.rd_key, out); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/cmll_ofb.c b/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/cmll_ofb.c new file mode 100644 index 000000000..b43c685c7 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/camellia/cmll_ofb.c @@ -0,0 +1,24 @@ +/* + * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +/* + * The input and output encrypted as though 128bit ofb mode is being used. + * The extra state information to record how much of the 128bit block we have + * used is contained in *num; + */ +void Camellia_ofb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char *ivec, int *num) +{ + CRYPTO_ofb128_encrypt(in, out, length, key, ivec, num, + (block128_f) Camellia_encrypt); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cast/asm/cast-586.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/cast/asm/cast-586.pl new file mode 100644 index 000000000..d5d38965c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cast/asm/cast-586.pl @@ -0,0 +1,192 @@ +#! /usr/bin/env perl +# Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# This flag makes the inner loop one cycle longer, but generates +# code that runs %30 faster on the pentium pro/II, 44% faster +# of PIII, while only %7 slower on the pentium. +# By default, this flag is on. +$ppro=1; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; +require "cbc.pl"; + +$output=pop; +open STDOUT,">$output"; + +&asm_init($ARGV[0],$ARGV[$#ARGV] eq "386"); + +$CAST_ROUNDS=16; +$L="edi"; +$R="esi"; +$K="ebp"; +$tmp1="ecx"; +$tmp2="ebx"; +$tmp3="eax"; +$tmp4="edx"; +$S1="CAST_S_table0"; +$S2="CAST_S_table1"; +$S3="CAST_S_table2"; +$S4="CAST_S_table3"; + +@F1=("add","xor","sub"); +@F2=("xor","sub","add"); +@F3=("sub","add","xor"); + +&CAST_encrypt("CAST_encrypt",1); +&CAST_encrypt("CAST_decrypt",0); +&cbc("CAST_cbc_encrypt","CAST_encrypt","CAST_decrypt",1,4,5,3,-1,-1); + +&asm_finish(); + +close STDOUT; + +sub CAST_encrypt { + local($name,$enc)=@_; + + local($win_ex)=<<"EOF"; +EXTERN _CAST_S_table0:DWORD +EXTERN _CAST_S_table1:DWORD +EXTERN _CAST_S_table2:DWORD +EXTERN _CAST_S_table3:DWORD +EOF + &main::external_label( + "CAST_S_table0", + "CAST_S_table1", + "CAST_S_table2", + "CAST_S_table3", + ); + + &function_begin_B($name,$win_ex); + + &comment(""); + + &push("ebp"); + &push("ebx"); + &mov($tmp2,&wparam(0)); + &mov($K,&wparam(1)); + &push("esi"); + &push("edi"); + + &comment("Load the 2 words"); + &mov($L,&DWP(0,$tmp2,"",0)); + &mov($R,&DWP(4,$tmp2,"",0)); + + &comment('Get short key flag'); + &mov($tmp3,&DWP(128,$K,"",0)); + if($enc) { + &push($tmp3); + } else { + &or($tmp3,$tmp3); + &jnz(&label('cast_dec_skip')); + } + + &xor($tmp3, $tmp3); + + # encrypting part + + if ($enc) { + &E_CAST( 0,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 1,$S,$R,$L,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 2,$S,$L,$R,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 3,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 4,$S,$L,$R,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 5,$S,$R,$L,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 6,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 7,$S,$R,$L,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 8,$S,$L,$R,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 9,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST(10,$S,$L,$R,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST(11,$S,$R,$L,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); + &comment('test short key flag'); + &pop($tmp4); + &or($tmp4,$tmp4); + &jnz(&label('cast_enc_done')); + &E_CAST(12,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST(13,$S,$R,$L,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST(14,$S,$L,$R,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST(15,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); + } else { + &E_CAST(15,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST(14,$S,$R,$L,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST(13,$S,$L,$R,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST(12,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); + &set_label('cast_dec_skip'); + &E_CAST(11,$S,$L,$R,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST(10,$S,$R,$L,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 9,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 8,$S,$R,$L,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 7,$S,$L,$R,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 6,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 5,$S,$L,$R,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 4,$S,$R,$L,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 3,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 2,$S,$R,$L,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 1,$S,$L,$R,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 0,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); + } + + &set_label('cast_enc_done') if $enc; +# Why the nop? - Ben 17/1/99 + &nop(); + &mov($tmp3,&wparam(0)); + &mov(&DWP(4,$tmp3,"",0),$L); + &mov(&DWP(0,$tmp3,"",0),$R); + &function_end($name); +} + +sub E_CAST { + local($i,$S,$L,$R,$K,$OP1,$OP2,$OP3,$tmp1,$tmp2,$tmp3,$tmp4)=@_; + # Ri needs to have 16 pre added. + + &comment("round $i"); + &mov( $tmp4, &DWP($i*8,$K,"",1)); + + &mov( $tmp1, &DWP($i*8+4,$K,"",1)); + &$OP1( $tmp4, $R); + + &rotl( $tmp4, &LB($tmp1)); + + if ($ppro) { + &xor( $tmp1, $tmp1); + &mov( $tmp2, 0xff); + + &movb( &LB($tmp1), &HB($tmp4)); # A + &and( $tmp2, $tmp4); + + &shr( $tmp4, 16); # + &xor( $tmp3, $tmp3); + } else { + &mov( $tmp2, $tmp4); # B + &movb( &LB($tmp1), &HB($tmp4)); # A # BAD BAD BAD + + &shr( $tmp4, 16); # + &and( $tmp2, 0xff); + } + + &movb( &LB($tmp3), &HB($tmp4)); # C # BAD BAD BAD + &and( $tmp4, 0xff); # D + + &mov( $tmp1, &DWP($S1,"",$tmp1,4)); + &mov( $tmp2, &DWP($S2,"",$tmp2,4)); + + &$OP2( $tmp1, $tmp2); + &mov( $tmp2, &DWP($S3,"",$tmp3,4)); + + &$OP3( $tmp1, $tmp2); + &mov( $tmp2, &DWP($S4,"",$tmp4,4)); + + &$OP1( $tmp1, $tmp2); + # XXX + + &xor( $L, $tmp1); + # XXX +} + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cast/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/cast/build.info new file mode 100644 index 000000000..b0f59f380 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cast/build.info @@ -0,0 +1,7 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + c_skey.c c_ecb.c {- $target{cast_asm_src} -} c_cfb64.c c_ofb64.c + +GENERATE[cast-586.s]=asm/cast-586.pl \ + $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) +DEPEND[cast-586.s]=../perlasm/x86asm.pl ../perlasm/cbc.pl diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cast/c_cfb64.c b/trunk/3rdparty/openssl-1.1-fit/crypto/cast/c_cfb64.c new file mode 100644 index 000000000..bd7cb2f46 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cast/c_cfb64.c @@ -0,0 +1,74 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "cast_lcl.h" + +/* + * The input and output encrypted as though 64bit cfb mode is being used. + * The extra state information to record how much of the 64bit block we have + * used is contained in *num; + */ + +void CAST_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, const CAST_KEY *schedule, + unsigned char *ivec, int *num, int enc) +{ + register CAST_LONG v0, v1, t; + register int n = *num; + register long l = length; + CAST_LONG ti[2]; + unsigned char *iv, c, cc; + + iv = ivec; + if (enc) { + while (l--) { + if (n == 0) { + n2l(iv, v0); + ti[0] = v0; + n2l(iv, v1); + ti[1] = v1; + CAST_encrypt((CAST_LONG *)ti, schedule); + iv = ivec; + t = ti[0]; + l2n(t, iv); + t = ti[1]; + l2n(t, iv); + iv = ivec; + } + c = *(in++) ^ iv[n]; + *(out++) = c; + iv[n] = c; + n = (n + 1) & 0x07; + } + } else { + while (l--) { + if (n == 0) { + n2l(iv, v0); + ti[0] = v0; + n2l(iv, v1); + ti[1] = v1; + CAST_encrypt((CAST_LONG *)ti, schedule); + iv = ivec; + t = ti[0]; + l2n(t, iv); + t = ti[1]; + l2n(t, iv); + iv = ivec; + } + cc = *(in++); + c = iv[n]; + iv[n] = cc; + *(out++) = c ^ cc; + n = (n + 1) & 0x07; + } + } + v0 = v1 = ti[0] = ti[1] = t = c = cc = 0; + *num = n; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cast/c_ecb.c b/trunk/3rdparty/openssl-1.1-fit/crypto/cast/c_ecb.c new file mode 100644 index 000000000..da4179438 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cast/c_ecb.c @@ -0,0 +1,32 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "cast_lcl.h" +#include + +void CAST_ecb_encrypt(const unsigned char *in, unsigned char *out, + const CAST_KEY *ks, int enc) +{ + CAST_LONG l, d[2]; + + n2l(in, l); + d[0] = l; + n2l(in, l); + d[1] = l; + if (enc) + CAST_encrypt(d, ks); + else + CAST_decrypt(d, ks); + l = d[0]; + l2n(l, out); + l = d[1]; + l2n(l, out); + l = d[0] = d[1] = 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cast/c_enc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/cast/c_enc.c new file mode 100644 index 000000000..700b6d162 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cast/c_enc.c @@ -0,0 +1,151 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "cast_lcl.h" + +void CAST_encrypt(CAST_LONG *data, const CAST_KEY *key) +{ + CAST_LONG l, r, t; + const CAST_LONG *k; + + k = &(key->data[0]); + l = data[0]; + r = data[1]; + + E_CAST(0, k, l, r, +, ^, -); + E_CAST(1, k, r, l, ^, -, +); + E_CAST(2, k, l, r, -, +, ^); + E_CAST(3, k, r, l, +, ^, -); + E_CAST(4, k, l, r, ^, -, +); + E_CAST(5, k, r, l, -, +, ^); + E_CAST(6, k, l, r, +, ^, -); + E_CAST(7, k, r, l, ^, -, +); + E_CAST(8, k, l, r, -, +, ^); + E_CAST(9, k, r, l, +, ^, -); + E_CAST(10, k, l, r, ^, -, +); + E_CAST(11, k, r, l, -, +, ^); + if (!key->short_key) { + E_CAST(12, k, l, r, +, ^, -); + E_CAST(13, k, r, l, ^, -, +); + E_CAST(14, k, l, r, -, +, ^); + E_CAST(15, k, r, l, +, ^, -); + } + + data[1] = l & 0xffffffffL; + data[0] = r & 0xffffffffL; +} + +void CAST_decrypt(CAST_LONG *data, const CAST_KEY *key) +{ + CAST_LONG l, r, t; + const CAST_LONG *k; + + k = &(key->data[0]); + l = data[0]; + r = data[1]; + + if (!key->short_key) { + E_CAST(15, k, l, r, +, ^, -); + E_CAST(14, k, r, l, -, +, ^); + E_CAST(13, k, l, r, ^, -, +); + E_CAST(12, k, r, l, +, ^, -); + } + E_CAST(11, k, l, r, -, +, ^); + E_CAST(10, k, r, l, ^, -, +); + E_CAST(9, k, l, r, +, ^, -); + E_CAST(8, k, r, l, -, +, ^); + E_CAST(7, k, l, r, ^, -, +); + E_CAST(6, k, r, l, +, ^, -); + E_CAST(5, k, l, r, -, +, ^); + E_CAST(4, k, r, l, ^, -, +); + E_CAST(3, k, l, r, +, ^, -); + E_CAST(2, k, r, l, -, +, ^); + E_CAST(1, k, l, r, ^, -, +); + E_CAST(0, k, r, l, +, ^, -); + + data[1] = l & 0xffffffffL; + data[0] = r & 0xffffffffL; +} + +void CAST_cbc_encrypt(const unsigned char *in, unsigned char *out, + long length, const CAST_KEY *ks, unsigned char *iv, + int enc) +{ + register CAST_LONG tin0, tin1; + register CAST_LONG tout0, tout1, xor0, xor1; + register long l = length; + CAST_LONG tin[2]; + + if (enc) { + n2l(iv, tout0); + n2l(iv, tout1); + iv -= 8; + for (l -= 8; l >= 0; l -= 8) { + n2l(in, tin0); + n2l(in, tin1); + tin0 ^= tout0; + tin1 ^= tout1; + tin[0] = tin0; + tin[1] = tin1; + CAST_encrypt(tin, ks); + tout0 = tin[0]; + tout1 = tin[1]; + l2n(tout0, out); + l2n(tout1, out); + } + if (l != -8) { + n2ln(in, tin0, tin1, l + 8); + tin0 ^= tout0; + tin1 ^= tout1; + tin[0] = tin0; + tin[1] = tin1; + CAST_encrypt(tin, ks); + tout0 = tin[0]; + tout1 = tin[1]; + l2n(tout0, out); + l2n(tout1, out); + } + l2n(tout0, iv); + l2n(tout1, iv); + } else { + n2l(iv, xor0); + n2l(iv, xor1); + iv -= 8; + for (l -= 8; l >= 0; l -= 8) { + n2l(in, tin0); + n2l(in, tin1); + tin[0] = tin0; + tin[1] = tin1; + CAST_decrypt(tin, ks); + tout0 = tin[0] ^ xor0; + tout1 = tin[1] ^ xor1; + l2n(tout0, out); + l2n(tout1, out); + xor0 = tin0; + xor1 = tin1; + } + if (l != -8) { + n2l(in, tin0); + n2l(in, tin1); + tin[0] = tin0; + tin[1] = tin1; + CAST_decrypt(tin, ks); + tout0 = tin[0] ^ xor0; + tout1 = tin[1] ^ xor1; + l2nn(tout0, tout1, out, l + 8); + xor0 = tin0; + xor1 = tin1; + } + l2n(xor0, iv); + l2n(xor1, iv); + } + tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0; + tin[0] = tin[1] = 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cast/c_ofb64.c b/trunk/3rdparty/openssl-1.1-fit/crypto/cast/c_ofb64.c new file mode 100644 index 000000000..dffb07476 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cast/c_ofb64.c @@ -0,0 +1,61 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "cast_lcl.h" + +/* + * The input and output encrypted as though 64bit ofb mode is being used. + * The extra state information to record how much of the 64bit block we have + * used is contained in *num; + */ +void CAST_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, const CAST_KEY *schedule, + unsigned char *ivec, int *num) +{ + register CAST_LONG v0, v1, t; + register int n = *num; + register long l = length; + unsigned char d[8]; + register char *dp; + CAST_LONG ti[2]; + unsigned char *iv; + int save = 0; + + iv = ivec; + n2l(iv, v0); + n2l(iv, v1); + ti[0] = v0; + ti[1] = v1; + dp = (char *)d; + l2n(v0, dp); + l2n(v1, dp); + while (l--) { + if (n == 0) { + CAST_encrypt((CAST_LONG *)ti, schedule); + dp = (char *)d; + t = ti[0]; + l2n(t, dp); + t = ti[1]; + l2n(t, dp); + save++; + } + *(out++) = *(in++) ^ d[n]; + n = (n + 1) & 0x07; + } + if (save) { + v0 = ti[0]; + v1 = ti[1]; + iv = ivec; + l2n(v0, iv); + l2n(v1, iv); + } + t = v0 = v1 = ti[0] = ti[1] = 0; + *num = n; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cast/c_skey.c b/trunk/3rdparty/openssl-1.1-fit/crypto/cast/c_skey.c new file mode 100644 index 000000000..962d2a60b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cast/c_skey.c @@ -0,0 +1,118 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "cast_lcl.h" +#include "cast_s.h" + +#define CAST_exp(l,A,a,n) \ + A[n/4]=l; \ + a[n+3]=(l )&0xff; \ + a[n+2]=(l>> 8)&0xff; \ + a[n+1]=(l>>16)&0xff; \ + a[n+0]=(l>>24)&0xff; + +#define S4 CAST_S_table4 +#define S5 CAST_S_table5 +#define S6 CAST_S_table6 +#define S7 CAST_S_table7 + +void CAST_set_key(CAST_KEY *key, int len, const unsigned char *data) +{ + CAST_LONG x[16]; + CAST_LONG z[16]; + CAST_LONG k[32]; + CAST_LONG X[4], Z[4]; + CAST_LONG l, *K; + int i; + + for (i = 0; i < 16; i++) + x[i] = 0; + if (len > 16) + len = 16; + for (i = 0; i < len; i++) + x[i] = data[i]; + if (len <= 10) + key->short_key = 1; + else + key->short_key = 0; + + K = &k[0]; + X[0] = ((x[0] << 24) | (x[1] << 16) | (x[2] << 8) | x[3]) & 0xffffffffL; + X[1] = ((x[4] << 24) | (x[5] << 16) | (x[6] << 8) | x[7]) & 0xffffffffL; + X[2] = ((x[8] << 24) | (x[9] << 16) | (x[10] << 8) | x[11]) & 0xffffffffL; + X[3] = + ((x[12] << 24) | (x[13] << 16) | (x[14] << 8) | x[15]) & 0xffffffffL; + + for (;;) { + l = X[0] ^ S4[x[13]] ^ S5[x[15]] ^ S6[x[12]] ^ S7[x[14]] ^ S6[x[8]]; + CAST_exp(l, Z, z, 0); + l = X[2] ^ S4[z[0]] ^ S5[z[2]] ^ S6[z[1]] ^ S7[z[3]] ^ S7[x[10]]; + CAST_exp(l, Z, z, 4); + l = X[3] ^ S4[z[7]] ^ S5[z[6]] ^ S6[z[5]] ^ S7[z[4]] ^ S4[x[9]]; + CAST_exp(l, Z, z, 8); + l = X[1] ^ S4[z[10]] ^ S5[z[9]] ^ S6[z[11]] ^ S7[z[8]] ^ S5[x[11]]; + CAST_exp(l, Z, z, 12); + + K[0] = S4[z[8]] ^ S5[z[9]] ^ S6[z[7]] ^ S7[z[6]] ^ S4[z[2]]; + K[1] = S4[z[10]] ^ S5[z[11]] ^ S6[z[5]] ^ S7[z[4]] ^ S5[z[6]]; + K[2] = S4[z[12]] ^ S5[z[13]] ^ S6[z[3]] ^ S7[z[2]] ^ S6[z[9]]; + K[3] = S4[z[14]] ^ S5[z[15]] ^ S6[z[1]] ^ S7[z[0]] ^ S7[z[12]]; + + l = Z[2] ^ S4[z[5]] ^ S5[z[7]] ^ S6[z[4]] ^ S7[z[6]] ^ S6[z[0]]; + CAST_exp(l, X, x, 0); + l = Z[0] ^ S4[x[0]] ^ S5[x[2]] ^ S6[x[1]] ^ S7[x[3]] ^ S7[z[2]]; + CAST_exp(l, X, x, 4); + l = Z[1] ^ S4[x[7]] ^ S5[x[6]] ^ S6[x[5]] ^ S7[x[4]] ^ S4[z[1]]; + CAST_exp(l, X, x, 8); + l = Z[3] ^ S4[x[10]] ^ S5[x[9]] ^ S6[x[11]] ^ S7[x[8]] ^ S5[z[3]]; + CAST_exp(l, X, x, 12); + + K[4] = S4[x[3]] ^ S5[x[2]] ^ S6[x[12]] ^ S7[x[13]] ^ S4[x[8]]; + K[5] = S4[x[1]] ^ S5[x[0]] ^ S6[x[14]] ^ S7[x[15]] ^ S5[x[13]]; + K[6] = S4[x[7]] ^ S5[x[6]] ^ S6[x[8]] ^ S7[x[9]] ^ S6[x[3]]; + K[7] = S4[x[5]] ^ S5[x[4]] ^ S6[x[10]] ^ S7[x[11]] ^ S7[x[7]]; + + l = X[0] ^ S4[x[13]] ^ S5[x[15]] ^ S6[x[12]] ^ S7[x[14]] ^ S6[x[8]]; + CAST_exp(l, Z, z, 0); + l = X[2] ^ S4[z[0]] ^ S5[z[2]] ^ S6[z[1]] ^ S7[z[3]] ^ S7[x[10]]; + CAST_exp(l, Z, z, 4); + l = X[3] ^ S4[z[7]] ^ S5[z[6]] ^ S6[z[5]] ^ S7[z[4]] ^ S4[x[9]]; + CAST_exp(l, Z, z, 8); + l = X[1] ^ S4[z[10]] ^ S5[z[9]] ^ S6[z[11]] ^ S7[z[8]] ^ S5[x[11]]; + CAST_exp(l, Z, z, 12); + + K[8] = S4[z[3]] ^ S5[z[2]] ^ S6[z[12]] ^ S7[z[13]] ^ S4[z[9]]; + K[9] = S4[z[1]] ^ S5[z[0]] ^ S6[z[14]] ^ S7[z[15]] ^ S5[z[12]]; + K[10] = S4[z[7]] ^ S5[z[6]] ^ S6[z[8]] ^ S7[z[9]] ^ S6[z[2]]; + K[11] = S4[z[5]] ^ S5[z[4]] ^ S6[z[10]] ^ S7[z[11]] ^ S7[z[6]]; + + l = Z[2] ^ S4[z[5]] ^ S5[z[7]] ^ S6[z[4]] ^ S7[z[6]] ^ S6[z[0]]; + CAST_exp(l, X, x, 0); + l = Z[0] ^ S4[x[0]] ^ S5[x[2]] ^ S6[x[1]] ^ S7[x[3]] ^ S7[z[2]]; + CAST_exp(l, X, x, 4); + l = Z[1] ^ S4[x[7]] ^ S5[x[6]] ^ S6[x[5]] ^ S7[x[4]] ^ S4[z[1]]; + CAST_exp(l, X, x, 8); + l = Z[3] ^ S4[x[10]] ^ S5[x[9]] ^ S6[x[11]] ^ S7[x[8]] ^ S5[z[3]]; + CAST_exp(l, X, x, 12); + + K[12] = S4[x[8]] ^ S5[x[9]] ^ S6[x[7]] ^ S7[x[6]] ^ S4[x[3]]; + K[13] = S4[x[10]] ^ S5[x[11]] ^ S6[x[5]] ^ S7[x[4]] ^ S5[x[7]]; + K[14] = S4[x[12]] ^ S5[x[13]] ^ S6[x[3]] ^ S7[x[2]] ^ S6[x[8]]; + K[15] = S4[x[14]] ^ S5[x[15]] ^ S6[x[1]] ^ S7[x[0]] ^ S7[x[13]]; + if (K != k) + break; + K += 16; + } + + for (i = 0; i < 16; i++) { + key->data[i * 2] = k[i]; + key->data[i * 2 + 1] = ((k[i + 16]) + 16) & 0x1f; + } +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cast/cast_lcl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/cast/cast_lcl.h new file mode 100644 index 000000000..35e89930a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cast/cast_lcl.h @@ -0,0 +1,188 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifdef OPENSSL_SYS_WIN32 +# include +#endif + +#undef c2l +#define c2l(c,l) (l =((unsigned long)(*((c)++))) , \ + l|=((unsigned long)(*((c)++)))<< 8L, \ + l|=((unsigned long)(*((c)++)))<<16L, \ + l|=((unsigned long)(*((c)++)))<<24L) + +/* NOTE - c is not incremented as per c2l */ +#undef c2ln +#define c2ln(c,l1,l2,n) { \ + c+=n; \ + l1=l2=0; \ + switch (n) { \ + case 8: l2 =((unsigned long)(*(--(c))))<<24L; \ + case 7: l2|=((unsigned long)(*(--(c))))<<16L; \ + case 6: l2|=((unsigned long)(*(--(c))))<< 8L; \ + case 5: l2|=((unsigned long)(*(--(c)))); \ + case 4: l1 =((unsigned long)(*(--(c))))<<24L; \ + case 3: l1|=((unsigned long)(*(--(c))))<<16L; \ + case 2: l1|=((unsigned long)(*(--(c))))<< 8L; \ + case 1: l1|=((unsigned long)(*(--(c)))); \ + } \ + } + +#undef l2c +#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24L)&0xff)) + +/* NOTE - c is not incremented as per l2c */ +#undef l2cn +#define l2cn(l1,l2,c,n) { \ + c+=n; \ + switch (n) { \ + case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \ + case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \ + case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \ + case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ + case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \ + case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \ + case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \ + case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ + } \ + } + +/* NOTE - c is not incremented as per n2l */ +#define n2ln(c,l1,l2,n) { \ + c+=n; \ + l1=l2=0; \ + switch (n) { \ + case 8: l2 =((unsigned long)(*(--(c)))) ; \ + /* fall thru */ \ + case 7: l2|=((unsigned long)(*(--(c))))<< 8; \ + /* fall thru */ \ + case 6: l2|=((unsigned long)(*(--(c))))<<16; \ + /* fall thru */ \ + case 5: l2|=((unsigned long)(*(--(c))))<<24; \ + /* fall thru */ \ + case 4: l1 =((unsigned long)(*(--(c)))) ; \ + /* fall thru */ \ + case 3: l1|=((unsigned long)(*(--(c))))<< 8; \ + /* fall thru */ \ + case 2: l1|=((unsigned long)(*(--(c))))<<16; \ + /* fall thru */ \ + case 1: l1|=((unsigned long)(*(--(c))))<<24; \ + } \ + } + +/* NOTE - c is not incremented as per l2n */ +#define l2nn(l1,l2,c,n) { \ + c+=n; \ + switch (n) { \ + case 8: *(--(c))=(unsigned char)(((l2) )&0xff); \ + /* fall thru */ \ + case 7: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \ + /* fall thru */ \ + case 6: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \ + /* fall thru */ \ + case 5: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \ + /* fall thru */ \ + case 4: *(--(c))=(unsigned char)(((l1) )&0xff); \ + /* fall thru */ \ + case 3: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \ + /* fall thru */ \ + case 2: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \ + /* fall thru */ \ + case 1: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \ + } \ + } + +#undef n2l +#define n2l(c,l) (l =((unsigned long)(*((c)++)))<<24L, \ + l|=((unsigned long)(*((c)++)))<<16L, \ + l|=((unsigned long)(*((c)++)))<< 8L, \ + l|=((unsigned long)(*((c)++)))) + +#undef l2n +#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +#if defined(OPENSSL_SYS_WIN32) && defined(_MSC_VER) +# define ROTL(a,n) (_lrotl(a,n)) +#else +# define ROTL(a,n) ((((a)<<(n))&0xffffffffL)|((a)>>((32-(n))&31))) +#endif + +#define C_M 0x3fc +#define C_0 22L +#define C_1 14L +#define C_2 6L +#define C_3 2L /* left shift */ + +/* The rotate has an extra 16 added to it to help the x86 asm */ +#if defined(CAST_PTR) +# define E_CAST(n,key,L,R,OP1,OP2,OP3) \ + { \ + int i; \ + t=(key[n*2] OP1 R)&0xffffffffL; \ + i=key[n*2+1]; \ + t=ROTL(t,i); \ + L^= (((((*(CAST_LONG *)((unsigned char *) \ + CAST_S_table0+((t>>C_2)&C_M)) OP2 \ + *(CAST_LONG *)((unsigned char *) \ + CAST_S_table1+((t<>C_0)&C_M)))&0xffffffffL) OP1 \ + *(CAST_LONG *)((unsigned char *) \ + CAST_S_table3+((t>>C_1)&C_M)))&0xffffffffL; \ + } +#elif defined(CAST_PTR2) +# define E_CAST(n,key,L,R,OP1,OP2,OP3) \ + { \ + int i; \ + CAST_LONG u,v,w; \ + w=(key[n*2] OP1 R)&0xffffffffL; \ + i=key[n*2+1]; \ + w=ROTL(w,i); \ + u=w>>C_2; \ + v=w<>C_0; \ + t=(t OP2 *(CAST_LONG *)((unsigned char *)CAST_S_table1+v))&0xffffffffL;\ + v=w>>C_1; \ + u&=C_M; \ + v&=C_M; \ + t=(t OP3 *(CAST_LONG *)((unsigned char *)CAST_S_table2+u)&0xffffffffL);\ + t=(t OP1 *(CAST_LONG *)((unsigned char *)CAST_S_table3+v)&0xffffffffL);\ + L^=(t&0xffffffff); \ + } +#else +# define E_CAST(n,key,L,R,OP1,OP2,OP3) \ + { \ + CAST_LONG a,b,c,d; \ + t=(key[n*2] OP1 R)&0xffffffff; \ + t=ROTL(t,(key[n*2+1])); \ + a=CAST_S_table0[(t>> 8)&0xff]; \ + b=CAST_S_table1[(t )&0xff]; \ + c=CAST_S_table2[(t>>24)&0xff]; \ + d=CAST_S_table3[(t>>16)&0xff]; \ + L^=(((((a OP2 b)&0xffffffffL) OP3 c)&0xffffffffL) OP1 d)&0xffffffffL; \ + } +#endif + +extern const CAST_LONG CAST_S_table0[256]; +extern const CAST_LONG CAST_S_table1[256]; +extern const CAST_LONG CAST_S_table2[256]; +extern const CAST_LONG CAST_S_table3[256]; +extern const CAST_LONG CAST_S_table4[256]; +extern const CAST_LONG CAST_S_table5[256]; +extern const CAST_LONG CAST_S_table6[256]; +extern const CAST_LONG CAST_S_table7[256]; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cast/cast_s.h b/trunk/3rdparty/openssl-1.1-fit/crypto/cast/cast_s.h new file mode 100644 index 000000000..b27415b96 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cast/cast_s.h @@ -0,0 +1,544 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +const CAST_LONG CAST_S_table0[256] = { + 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, + 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949, + 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, + 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, + 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, + 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, + 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, + 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0, + 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, + 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, + 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, + 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, + 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, + 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d, + 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, + 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, + 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, + 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, + 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, + 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, + 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, + 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, + 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, + 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, + 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, + 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, + 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, + 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, + 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, + 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, + 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, + 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d, + 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, + 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, + 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, + 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, + 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, + 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, + 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, + 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, + 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, + 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, + 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, + 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96, + 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, + 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, + 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, + 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, + 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, + 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, + 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, + 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, + 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, + 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, + 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, + 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, + 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, + 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, + 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, + 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, + 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, + 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9, + 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, + 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf, +}; + +const CAST_LONG CAST_S_table1[256] = { + 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, + 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651, + 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, + 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, + 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, + 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, + 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, + 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, + 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, + 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, + 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, + 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, + 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, + 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b, + 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, + 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, + 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, + 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, + 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, + 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, + 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, + 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, + 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, + 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, + 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, + 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, + 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, + 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, + 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, + 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, + 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, + 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, + 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, + 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, + 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, + 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, + 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, + 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f, + 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, + 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, + 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, + 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, + 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, + 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58, + 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, + 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, + 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, + 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, + 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, + 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, + 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, + 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, + 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, + 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, + 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, + 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, + 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, + 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, + 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, + 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, + 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, + 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9, + 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, + 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1, +}; + +const CAST_LONG CAST_S_table2[256] = { + 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, + 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90, + 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, + 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, + 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, + 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, + 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, + 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240, + 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, + 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, + 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, + 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, + 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, + 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71, + 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, + 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, + 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, + 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, + 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, + 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, + 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, + 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, + 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, + 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, + 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, + 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, + 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, + 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, + 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, + 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, + 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, + 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e, + 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, + 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, + 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, + 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, + 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, + 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a, + 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, + 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, + 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, + 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, + 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, + 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, + 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, + 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, + 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, + 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, + 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, + 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, + 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, + 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, + 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, + 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, + 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, + 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, + 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, + 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, + 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, + 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, + 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, + 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a, + 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, + 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783, +}; + +const CAST_LONG CAST_S_table3[256] = { + 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, + 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1, + 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, + 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, + 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, + 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, + 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, + 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121, + 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, + 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, + 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, + 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, + 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, + 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb, + 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, + 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, + 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, + 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, + 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, + 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, + 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, + 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, + 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, + 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, + 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, + 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, + 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, + 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, + 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, + 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, + 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, + 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a, + 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, + 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, + 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, + 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, + 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, + 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, + 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, + 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, + 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, + 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, + 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, + 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, + 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, + 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, + 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, + 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, + 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, + 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, + 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, + 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, + 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, + 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, + 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, + 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, + 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, + 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, + 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, + 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, + 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, + 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282, + 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, + 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2, +}; + +const CAST_LONG CAST_S_table4[256] = { + 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, + 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f, + 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, + 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, + 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, + 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, + 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, + 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02, + 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, + 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, + 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, + 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, + 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, + 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9, + 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, + 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, + 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, + 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, + 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, + 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, + 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, + 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, + 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, + 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, + 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, + 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, + 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, + 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, + 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, + 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, + 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, + 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f, + 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, + 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, + 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, + 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, + 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, + 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3, + 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, + 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, + 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, + 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, + 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, + 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2, + 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, + 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, + 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, + 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, + 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, + 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, + 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, + 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, + 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, + 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, + 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, + 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, + 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, + 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, + 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, + 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, + 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, + 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8, + 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, + 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4, +}; + +const CAST_LONG CAST_S_table5[256] = { + 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, + 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac, + 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, + 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, + 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, + 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, + 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, + 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98, + 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, + 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, + 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, + 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, + 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, + 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd, + 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, + 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, + 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, + 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, + 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, + 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, + 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, + 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, + 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, + 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, + 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, + 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, + 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, + 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, + 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, + 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, + 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, + 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289, + 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, + 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, + 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, + 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, + 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, + 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b, + 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, + 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, + 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, + 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, + 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, + 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976, + 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, + 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, + 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, + 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, + 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, + 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, + 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, + 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, + 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, + 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, + 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, + 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, + 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, + 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, + 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, + 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, + 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, + 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd, + 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, + 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f, +}; + +const CAST_LONG CAST_S_table6[256] = { + 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, + 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f, + 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, + 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, + 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, + 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, + 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, + 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19, + 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, + 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, + 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, + 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, + 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, + 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88, + 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, + 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, + 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, + 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, + 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, + 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, + 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, + 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, + 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, + 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, + 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, + 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, + 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, + 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, + 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, + 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, + 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, + 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, + 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, + 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, + 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, + 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, + 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, + 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566, + 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, + 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, + 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, + 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, + 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, + 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e, + 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, + 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, + 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, + 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, + 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, + 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, + 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, + 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, + 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, + 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, + 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, + 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, + 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, + 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, + 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, + 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, + 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, + 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c, + 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, + 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3, +}; + +const CAST_LONG CAST_S_table7[256] = { + 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, + 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5, + 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, + 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, + 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, + 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, + 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, + 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d, + 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, + 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, + 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, + 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, + 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, + 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc, + 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, + 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, + 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, + 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, + 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, + 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, + 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, + 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, + 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, + 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, + 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, + 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, + 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, + 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, + 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, + 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, + 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, + 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c, + 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, + 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, + 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, + 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, + 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, + 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70, + 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, + 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, + 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, + 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, + 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, + 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3, + 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, + 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, + 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, + 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, + 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, + 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, + 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, + 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, + 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, + 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, + 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, + 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, + 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, + 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, + 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, + 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, + 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, + 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82, + 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, + 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e, +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/chacha/asm/chacha-armv4.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/chacha/asm/chacha-armv4.pl new file mode 100755 index 000000000..d3fadcc63 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/chacha/asm/chacha-armv4.pl @@ -0,0 +1,1160 @@ +#! /usr/bin/env perl +# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# December 2014 +# +# ChaCha20 for ARMv4. +# +# Performance in cycles per byte out of large buffer. +# +# IALU/gcc-4.4 1xNEON 3xNEON+1xIALU +# +# Cortex-A5 19.3(*)/+95% 21.8 14.1 +# Cortex-A8 10.5(*)/+160% 13.9 6.35 +# Cortex-A9 12.9(**)/+110% 14.3 6.50 +# Cortex-A15 11.0/+40% 16.0 5.00 +# Snapdragon S4 11.5/+125% 13.6 4.90 +# +# (*) most "favourable" result for aligned data on little-endian +# processor, result for misaligned data is 10-15% lower; +# (**) this result is a trade-off: it can be improved by 20%, +# but then Snapdragon S4 and Cortex-A8 results get +# 20-25% worse; + +$flavour = shift; +if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + open STDOUT,">$output"; +} + +sub AUTOLOAD() # thunk [simplified] x86-style perlasm +{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; $opcode =~ s/_/\./; + my $arg = pop; + $arg = "#$arg" if ($arg*1 eq $arg); + $code .= "\t$opcode\t".join(',',@_,$arg)."\n"; +} + +my @x=map("r$_",(0..7,"x","x","x","x",12,"x",14,"x")); +my @t=map("r$_",(8..11)); + +sub ROUND { +my ($a0,$b0,$c0,$d0)=@_; +my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0)); +my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1)); +my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2)); +my $odd = $d0&1; +my ($xc,$xc_) = (@t[0..1]); +my ($xd,$xd_) = $odd ? (@t[2],@x[$d1]) : (@x[$d0],@t[2]); +my @ret; + + # Consider order in which variables are addressed by their + # index: + # + # a b c d + # + # 0 4 8 12 < even round + # 1 5 9 13 + # 2 6 10 14 + # 3 7 11 15 + # 0 5 10 15 < odd round + # 1 6 11 12 + # 2 7 8 13 + # 3 4 9 14 + # + # 'a', 'b' are permanently allocated in registers, @x[0..7], + # while 'c's and pair of 'd's are maintained in memory. If + # you observe 'c' column, you'll notice that pair of 'c's is + # invariant between rounds. This means that we have to reload + # them once per round, in the middle. This is why you'll see + # bunch of 'c' stores and loads in the middle, but none in + # the beginning or end. If you observe 'd' column, you'll + # notice that 15 and 13 are reused in next pair of rounds. + # This is why these two are chosen for offloading to memory, + # to make loads count more. + push @ret,( + "&add (@x[$a0],@x[$a0],@x[$b0])", + "&mov ($xd,$xd,'ror#16')", + "&add (@x[$a1],@x[$a1],@x[$b1])", + "&mov ($xd_,$xd_,'ror#16')", + "&eor ($xd,$xd,@x[$a0],'ror#16')", + "&eor ($xd_,$xd_,@x[$a1],'ror#16')", + + "&add ($xc,$xc,$xd)", + "&mov (@x[$b0],@x[$b0],'ror#20')", + "&add ($xc_,$xc_,$xd_)", + "&mov (@x[$b1],@x[$b1],'ror#20')", + "&eor (@x[$b0],@x[$b0],$xc,'ror#20')", + "&eor (@x[$b1],@x[$b1],$xc_,'ror#20')", + + "&add (@x[$a0],@x[$a0],@x[$b0])", + "&mov ($xd,$xd,'ror#24')", + "&add (@x[$a1],@x[$a1],@x[$b1])", + "&mov ($xd_,$xd_,'ror#24')", + "&eor ($xd,$xd,@x[$a0],'ror#24')", + "&eor ($xd_,$xd_,@x[$a1],'ror#24')", + + "&add ($xc,$xc,$xd)", + "&mov (@x[$b0],@x[$b0],'ror#25')" ); + push @ret,( + "&str ($xd,'[sp,#4*(16+$d0)]')", + "&ldr ($xd,'[sp,#4*(16+$d2)]')" ) if ($odd); + push @ret,( + "&add ($xc_,$xc_,$xd_)", + "&mov (@x[$b1],@x[$b1],'ror#25')" ); + push @ret,( + "&str ($xd_,'[sp,#4*(16+$d1)]')", + "&ldr ($xd_,'[sp,#4*(16+$d3)]')" ) if (!$odd); + push @ret,( + "&eor (@x[$b0],@x[$b0],$xc,'ror#25')", + "&eor (@x[$b1],@x[$b1],$xc_,'ror#25')" ); + + $xd=@x[$d2] if (!$odd); + $xd_=@x[$d3] if ($odd); + push @ret,( + "&str ($xc,'[sp,#4*(16+$c0)]')", + "&ldr ($xc,'[sp,#4*(16+$c2)]')", + "&add (@x[$a2],@x[$a2],@x[$b2])", + "&mov ($xd,$xd,'ror#16')", + "&str ($xc_,'[sp,#4*(16+$c1)]')", + "&ldr ($xc_,'[sp,#4*(16+$c3)]')", + "&add (@x[$a3],@x[$a3],@x[$b3])", + "&mov ($xd_,$xd_,'ror#16')", + "&eor ($xd,$xd,@x[$a2],'ror#16')", + "&eor ($xd_,$xd_,@x[$a3],'ror#16')", + + "&add ($xc,$xc,$xd)", + "&mov (@x[$b2],@x[$b2],'ror#20')", + "&add ($xc_,$xc_,$xd_)", + "&mov (@x[$b3],@x[$b3],'ror#20')", + "&eor (@x[$b2],@x[$b2],$xc,'ror#20')", + "&eor (@x[$b3],@x[$b3],$xc_,'ror#20')", + + "&add (@x[$a2],@x[$a2],@x[$b2])", + "&mov ($xd,$xd,'ror#24')", + "&add (@x[$a3],@x[$a3],@x[$b3])", + "&mov ($xd_,$xd_,'ror#24')", + "&eor ($xd,$xd,@x[$a2],'ror#24')", + "&eor ($xd_,$xd_,@x[$a3],'ror#24')", + + "&add ($xc,$xc,$xd)", + "&mov (@x[$b2],@x[$b2],'ror#25')", + "&add ($xc_,$xc_,$xd_)", + "&mov (@x[$b3],@x[$b3],'ror#25')", + "&eor (@x[$b2],@x[$b2],$xc,'ror#25')", + "&eor (@x[$b3],@x[$b3],$xc_,'ror#25')" ); + + @ret; +} + +$code.=<<___; +#include "arm_arch.h" + +.text +#if defined(__thumb2__) || defined(__clang__) +.syntax unified +#endif +#if defined(__thumb2__) +.thumb +#else +.code 32 +#endif + +#if defined(__thumb2__) || defined(__clang__) +#define ldrhsb ldrbhs +#endif + +.align 5 +.Lsigma: +.long 0x61707865,0x3320646e,0x79622d32,0x6b206574 @ endian-neutral +.Lone: +.long 1,0,0,0 +#if __ARM_MAX_ARCH__>=7 +.LOPENSSL_armcap: +.word OPENSSL_armcap_P-.LChaCha20_ctr32 +#else +.word -1 +#endif + +.globl ChaCha20_ctr32 +.type ChaCha20_ctr32,%function +.align 5 +ChaCha20_ctr32: +.LChaCha20_ctr32: + ldr r12,[sp,#0] @ pull pointer to counter and nonce + stmdb sp!,{r0-r2,r4-r11,lr} +#if __ARM_ARCH__<7 && !defined(__thumb2__) + sub r14,pc,#16 @ ChaCha20_ctr32 +#else + adr r14,.LChaCha20_ctr32 +#endif + cmp r2,#0 @ len==0? +#ifdef __thumb2__ + itt eq +#endif + addeq sp,sp,#4*3 + beq .Lno_data +#if __ARM_MAX_ARCH__>=7 + cmp r2,#192 @ test len + bls .Lshort + ldr r4,[r14,#-32] + ldr r4,[r14,r4] +# ifdef __APPLE__ + ldr r4,[r4] +# endif + tst r4,#ARMV7_NEON + bne .LChaCha20_neon +.Lshort: +#endif + ldmia r12,{r4-r7} @ load counter and nonce + sub sp,sp,#4*(16) @ off-load area + sub r14,r14,#64 @ .Lsigma + stmdb sp!,{r4-r7} @ copy counter and nonce + ldmia r3,{r4-r11} @ load key + ldmia r14,{r0-r3} @ load sigma + stmdb sp!,{r4-r11} @ copy key + stmdb sp!,{r0-r3} @ copy sigma + str r10,[sp,#4*(16+10)] @ off-load "@x[10]" + str r11,[sp,#4*(16+11)] @ off-load "@x[11]" + b .Loop_outer_enter + +.align 4 +.Loop_outer: + ldmia sp,{r0-r9} @ load key material + str @t[3],[sp,#4*(32+2)] @ save len + str r12, [sp,#4*(32+1)] @ save inp + str r14, [sp,#4*(32+0)] @ save out +.Loop_outer_enter: + ldr @t[3], [sp,#4*(15)] + ldr @x[12],[sp,#4*(12)] @ modulo-scheduled load + ldr @t[2], [sp,#4*(13)] + ldr @x[14],[sp,#4*(14)] + str @t[3], [sp,#4*(16+15)] + mov @t[3],#10 + b .Loop + +.align 4 +.Loop: + subs @t[3],@t[3],#1 +___ + foreach (&ROUND(0, 4, 8,12)) { eval; } + foreach (&ROUND(0, 5,10,15)) { eval; } +$code.=<<___; + bne .Loop + + ldr @t[3],[sp,#4*(32+2)] @ load len + + str @t[0], [sp,#4*(16+8)] @ modulo-scheduled store + str @t[1], [sp,#4*(16+9)] + str @x[12],[sp,#4*(16+12)] + str @t[2], [sp,#4*(16+13)] + str @x[14],[sp,#4*(16+14)] + + @ at this point we have first half of 512-bit result in + @ @x[0-7] and second half at sp+4*(16+8) + + cmp @t[3],#64 @ done yet? +#ifdef __thumb2__ + itete lo +#endif + addlo r12,sp,#4*(0) @ shortcut or ... + ldrhs r12,[sp,#4*(32+1)] @ ... load inp + addlo r14,sp,#4*(0) @ shortcut or ... + ldrhs r14,[sp,#4*(32+0)] @ ... load out + + ldr @t[0],[sp,#4*(0)] @ load key material + ldr @t[1],[sp,#4*(1)] + +#if __ARM_ARCH__>=6 || !defined(__ARMEB__) +# if __ARM_ARCH__<7 + orr @t[2],r12,r14 + tst @t[2],#3 @ are input and output aligned? + ldr @t[2],[sp,#4*(2)] + bne .Lunaligned + cmp @t[3],#64 @ restore flags +# else + ldr @t[2],[sp,#4*(2)] +# endif + ldr @t[3],[sp,#4*(3)] + + add @x[0],@x[0],@t[0] @ accumulate key material + add @x[1],@x[1],@t[1] +# ifdef __thumb2__ + itt hs +# endif + ldrhs @t[0],[r12],#16 @ load input + ldrhs @t[1],[r12,#-12] + + add @x[2],@x[2],@t[2] + add @x[3],@x[3],@t[3] +# ifdef __thumb2__ + itt hs +# endif + ldrhs @t[2],[r12,#-8] + ldrhs @t[3],[r12,#-4] +# if __ARM_ARCH__>=6 && defined(__ARMEB__) + rev @x[0],@x[0] + rev @x[1],@x[1] + rev @x[2],@x[2] + rev @x[3],@x[3] +# endif +# ifdef __thumb2__ + itt hs +# endif + eorhs @x[0],@x[0],@t[0] @ xor with input + eorhs @x[1],@x[1],@t[1] + add @t[0],sp,#4*(4) + str @x[0],[r14],#16 @ store output +# ifdef __thumb2__ + itt hs +# endif + eorhs @x[2],@x[2],@t[2] + eorhs @x[3],@x[3],@t[3] + ldmia @t[0],{@t[0]-@t[3]} @ load key material + str @x[1],[r14,#-12] + str @x[2],[r14,#-8] + str @x[3],[r14,#-4] + + add @x[4],@x[4],@t[0] @ accumulate key material + add @x[5],@x[5],@t[1] +# ifdef __thumb2__ + itt hs +# endif + ldrhs @t[0],[r12],#16 @ load input + ldrhs @t[1],[r12,#-12] + add @x[6],@x[6],@t[2] + add @x[7],@x[7],@t[3] +# ifdef __thumb2__ + itt hs +# endif + ldrhs @t[2],[r12,#-8] + ldrhs @t[3],[r12,#-4] +# if __ARM_ARCH__>=6 && defined(__ARMEB__) + rev @x[4],@x[4] + rev @x[5],@x[5] + rev @x[6],@x[6] + rev @x[7],@x[7] +# endif +# ifdef __thumb2__ + itt hs +# endif + eorhs @x[4],@x[4],@t[0] + eorhs @x[5],@x[5],@t[1] + add @t[0],sp,#4*(8) + str @x[4],[r14],#16 @ store output +# ifdef __thumb2__ + itt hs +# endif + eorhs @x[6],@x[6],@t[2] + eorhs @x[7],@x[7],@t[3] + str @x[5],[r14,#-12] + ldmia @t[0],{@t[0]-@t[3]} @ load key material + str @x[6],[r14,#-8] + add @x[0],sp,#4*(16+8) + str @x[7],[r14,#-4] + + ldmia @x[0],{@x[0]-@x[7]} @ load second half + + add @x[0],@x[0],@t[0] @ accumulate key material + add @x[1],@x[1],@t[1] +# ifdef __thumb2__ + itt hs +# endif + ldrhs @t[0],[r12],#16 @ load input + ldrhs @t[1],[r12,#-12] +# ifdef __thumb2__ + itt hi +# endif + strhi @t[2],[sp,#4*(16+10)] @ copy "@x[10]" while at it + strhi @t[3],[sp,#4*(16+11)] @ copy "@x[11]" while at it + add @x[2],@x[2],@t[2] + add @x[3],@x[3],@t[3] +# ifdef __thumb2__ + itt hs +# endif + ldrhs @t[2],[r12,#-8] + ldrhs @t[3],[r12,#-4] +# if __ARM_ARCH__>=6 && defined(__ARMEB__) + rev @x[0],@x[0] + rev @x[1],@x[1] + rev @x[2],@x[2] + rev @x[3],@x[3] +# endif +# ifdef __thumb2__ + itt hs +# endif + eorhs @x[0],@x[0],@t[0] + eorhs @x[1],@x[1],@t[1] + add @t[0],sp,#4*(12) + str @x[0],[r14],#16 @ store output +# ifdef __thumb2__ + itt hs +# endif + eorhs @x[2],@x[2],@t[2] + eorhs @x[3],@x[3],@t[3] + str @x[1],[r14,#-12] + ldmia @t[0],{@t[0]-@t[3]} @ load key material + str @x[2],[r14,#-8] + str @x[3],[r14,#-4] + + add @x[4],@x[4],@t[0] @ accumulate key material + add @x[5],@x[5],@t[1] +# ifdef __thumb2__ + itt hi +# endif + addhi @t[0],@t[0],#1 @ next counter value + strhi @t[0],[sp,#4*(12)] @ save next counter value +# ifdef __thumb2__ + itt hs +# endif + ldrhs @t[0],[r12],#16 @ load input + ldrhs @t[1],[r12,#-12] + add @x[6],@x[6],@t[2] + add @x[7],@x[7],@t[3] +# ifdef __thumb2__ + itt hs +# endif + ldrhs @t[2],[r12,#-8] + ldrhs @t[3],[r12,#-4] +# if __ARM_ARCH__>=6 && defined(__ARMEB__) + rev @x[4],@x[4] + rev @x[5],@x[5] + rev @x[6],@x[6] + rev @x[7],@x[7] +# endif +# ifdef __thumb2__ + itt hs +# endif + eorhs @x[4],@x[4],@t[0] + eorhs @x[5],@x[5],@t[1] +# ifdef __thumb2__ + it ne +# endif + ldrne @t[0],[sp,#4*(32+2)] @ re-load len +# ifdef __thumb2__ + itt hs +# endif + eorhs @x[6],@x[6],@t[2] + eorhs @x[7],@x[7],@t[3] + str @x[4],[r14],#16 @ store output + str @x[5],[r14,#-12] +# ifdef __thumb2__ + it hs +# endif + subhs @t[3],@t[0],#64 @ len-=64 + str @x[6],[r14,#-8] + str @x[7],[r14,#-4] + bhi .Loop_outer + + beq .Ldone +# if __ARM_ARCH__<7 + b .Ltail + +.align 4 +.Lunaligned: @ unaligned endian-neutral path + cmp @t[3],#64 @ restore flags +# endif +#endif +#if __ARM_ARCH__<7 + ldr @t[3],[sp,#4*(3)] +___ +for ($i=0;$i<16;$i+=4) { +my $j=$i&0x7; + +$code.=<<___ if ($i==4); + add @x[0],sp,#4*(16+8) +___ +$code.=<<___ if ($i==8); + ldmia @x[0],{@x[0]-@x[7]} @ load second half +# ifdef __thumb2__ + itt hi +# endif + strhi @t[2],[sp,#4*(16+10)] @ copy "@x[10]" + strhi @t[3],[sp,#4*(16+11)] @ copy "@x[11]" +___ +$code.=<<___; + add @x[$j+0],@x[$j+0],@t[0] @ accumulate key material +___ +$code.=<<___ if ($i==12); +# ifdef __thumb2__ + itt hi +# endif + addhi @t[0],@t[0],#1 @ next counter value + strhi @t[0],[sp,#4*(12)] @ save next counter value +___ +$code.=<<___; + add @x[$j+1],@x[$j+1],@t[1] + add @x[$j+2],@x[$j+2],@t[2] +# ifdef __thumb2__ + itete lo +# endif + eorlo @t[0],@t[0],@t[0] @ zero or ... + ldrhsb @t[0],[r12],#16 @ ... load input + eorlo @t[1],@t[1],@t[1] + ldrhsb @t[1],[r12,#-12] + + add @x[$j+3],@x[$j+3],@t[3] +# ifdef __thumb2__ + itete lo +# endif + eorlo @t[2],@t[2],@t[2] + ldrhsb @t[2],[r12,#-8] + eorlo @t[3],@t[3],@t[3] + ldrhsb @t[3],[r12,#-4] + + eor @x[$j+0],@t[0],@x[$j+0] @ xor with input (or zero) + eor @x[$j+1],@t[1],@x[$j+1] +# ifdef __thumb2__ + itt hs +# endif + ldrhsb @t[0],[r12,#-15] @ load more input + ldrhsb @t[1],[r12,#-11] + eor @x[$j+2],@t[2],@x[$j+2] + strb @x[$j+0],[r14],#16 @ store output + eor @x[$j+3],@t[3],@x[$j+3] +# ifdef __thumb2__ + itt hs +# endif + ldrhsb @t[2],[r12,#-7] + ldrhsb @t[3],[r12,#-3] + strb @x[$j+1],[r14,#-12] + eor @x[$j+0],@t[0],@x[$j+0],lsr#8 + strb @x[$j+2],[r14,#-8] + eor @x[$j+1],@t[1],@x[$j+1],lsr#8 +# ifdef __thumb2__ + itt hs +# endif + ldrhsb @t[0],[r12,#-14] @ load more input + ldrhsb @t[1],[r12,#-10] + strb @x[$j+3],[r14,#-4] + eor @x[$j+2],@t[2],@x[$j+2],lsr#8 + strb @x[$j+0],[r14,#-15] + eor @x[$j+3],@t[3],@x[$j+3],lsr#8 +# ifdef __thumb2__ + itt hs +# endif + ldrhsb @t[2],[r12,#-6] + ldrhsb @t[3],[r12,#-2] + strb @x[$j+1],[r14,#-11] + eor @x[$j+0],@t[0],@x[$j+0],lsr#8 + strb @x[$j+2],[r14,#-7] + eor @x[$j+1],@t[1],@x[$j+1],lsr#8 +# ifdef __thumb2__ + itt hs +# endif + ldrhsb @t[0],[r12,#-13] @ load more input + ldrhsb @t[1],[r12,#-9] + strb @x[$j+3],[r14,#-3] + eor @x[$j+2],@t[2],@x[$j+2],lsr#8 + strb @x[$j+0],[r14,#-14] + eor @x[$j+3],@t[3],@x[$j+3],lsr#8 +# ifdef __thumb2__ + itt hs +# endif + ldrhsb @t[2],[r12,#-5] + ldrhsb @t[3],[r12,#-1] + strb @x[$j+1],[r14,#-10] + strb @x[$j+2],[r14,#-6] + eor @x[$j+0],@t[0],@x[$j+0],lsr#8 + strb @x[$j+3],[r14,#-2] + eor @x[$j+1],@t[1],@x[$j+1],lsr#8 + strb @x[$j+0],[r14,#-13] + eor @x[$j+2],@t[2],@x[$j+2],lsr#8 + strb @x[$j+1],[r14,#-9] + eor @x[$j+3],@t[3],@x[$j+3],lsr#8 + strb @x[$j+2],[r14,#-5] + strb @x[$j+3],[r14,#-1] +___ +$code.=<<___ if ($i<12); + add @t[0],sp,#4*(4+$i) + ldmia @t[0],{@t[0]-@t[3]} @ load key material +___ +} +$code.=<<___; +# ifdef __thumb2__ + it ne +# endif + ldrne @t[0],[sp,#4*(32+2)] @ re-load len +# ifdef __thumb2__ + it hs +# endif + subhs @t[3],@t[0],#64 @ len-=64 + bhi .Loop_outer + + beq .Ldone +#endif + +.Ltail: + ldr r12,[sp,#4*(32+1)] @ load inp + add @t[1],sp,#4*(0) + ldr r14,[sp,#4*(32+0)] @ load out + +.Loop_tail: + ldrb @t[2],[@t[1]],#1 @ read buffer on stack + ldrb @t[3],[r12],#1 @ read input + subs @t[0],@t[0],#1 + eor @t[3],@t[3],@t[2] + strb @t[3],[r14],#1 @ store output + bne .Loop_tail + +.Ldone: + add sp,sp,#4*(32+3) +.Lno_data: + ldmia sp!,{r4-r11,pc} +.size ChaCha20_ctr32,.-ChaCha20_ctr32 +___ + +{{{ +my ($a0,$b0,$c0,$d0,$a1,$b1,$c1,$d1,$a2,$b2,$c2,$d2,$t0,$t1,$t2,$t3) = + map("q$_",(0..15)); + +sub NEONROUND { +my $odd = pop; +my ($a,$b,$c,$d,$t)=@_; + + ( + "&vadd_i32 ($a,$a,$b)", + "&veor ($d,$d,$a)", + "&vrev32_16 ($d,$d)", # vrot ($d,16) + + "&vadd_i32 ($c,$c,$d)", + "&veor ($t,$b,$c)", + "&vshr_u32 ($b,$t,20)", + "&vsli_32 ($b,$t,12)", + + "&vadd_i32 ($a,$a,$b)", + "&veor ($t,$d,$a)", + "&vshr_u32 ($d,$t,24)", + "&vsli_32 ($d,$t,8)", + + "&vadd_i32 ($c,$c,$d)", + "&veor ($t,$b,$c)", + "&vshr_u32 ($b,$t,25)", + "&vsli_32 ($b,$t,7)", + + "&vext_8 ($c,$c,$c,8)", + "&vext_8 ($b,$b,$b,$odd?12:4)", + "&vext_8 ($d,$d,$d,$odd?4:12)" + ); +} + +$code.=<<___; +#if __ARM_MAX_ARCH__>=7 +.arch armv7-a +.fpu neon + +.type ChaCha20_neon,%function +.align 5 +ChaCha20_neon: + ldr r12,[sp,#0] @ pull pointer to counter and nonce + stmdb sp!,{r0-r2,r4-r11,lr} +.LChaCha20_neon: + adr r14,.Lsigma + vstmdb sp!,{d8-d15} @ ABI spec says so + stmdb sp!,{r0-r3} + + vld1.32 {$b0-$c0},[r3] @ load key + ldmia r3,{r4-r11} @ load key + + sub sp,sp,#4*(16+16) + vld1.32 {$d0},[r12] @ load counter and nonce + add r12,sp,#4*8 + ldmia r14,{r0-r3} @ load sigma + vld1.32 {$a0},[r14]! @ load sigma + vld1.32 {$t0},[r14] @ one + vst1.32 {$c0-$d0},[r12] @ copy 1/2key|counter|nonce + vst1.32 {$a0-$b0},[sp] @ copy sigma|1/2key + + str r10,[sp,#4*(16+10)] @ off-load "@x[10]" + str r11,[sp,#4*(16+11)] @ off-load "@x[11]" + vshl.i32 $t1#lo,$t0#lo,#1 @ two + vstr $t0#lo,[sp,#4*(16+0)] + vshl.i32 $t2#lo,$t0#lo,#2 @ four + vstr $t1#lo,[sp,#4*(16+2)] + vmov $a1,$a0 + vstr $t2#lo,[sp,#4*(16+4)] + vmov $a2,$a0 + vmov $b1,$b0 + vmov $b2,$b0 + b .Loop_neon_enter + +.align 4 +.Loop_neon_outer: + ldmia sp,{r0-r9} @ load key material + cmp @t[3],#64*2 @ if len<=64*2 + bls .Lbreak_neon @ switch to integer-only + vmov $a1,$a0 + str @t[3],[sp,#4*(32+2)] @ save len + vmov $a2,$a0 + str r12, [sp,#4*(32+1)] @ save inp + vmov $b1,$b0 + str r14, [sp,#4*(32+0)] @ save out + vmov $b2,$b0 +.Loop_neon_enter: + ldr @t[3], [sp,#4*(15)] + vadd.i32 $d1,$d0,$t0 @ counter+1 + ldr @x[12],[sp,#4*(12)] @ modulo-scheduled load + vmov $c1,$c0 + ldr @t[2], [sp,#4*(13)] + vmov $c2,$c0 + ldr @x[14],[sp,#4*(14)] + vadd.i32 $d2,$d1,$t0 @ counter+2 + str @t[3], [sp,#4*(16+15)] + mov @t[3],#10 + add @x[12],@x[12],#3 @ counter+3 + b .Loop_neon + +.align 4 +.Loop_neon: + subs @t[3],@t[3],#1 +___ + my @thread0=&NEONROUND($a0,$b0,$c0,$d0,$t0,0); + my @thread1=&NEONROUND($a1,$b1,$c1,$d1,$t1,0); + my @thread2=&NEONROUND($a2,$b2,$c2,$d2,$t2,0); + my @thread3=&ROUND(0,4,8,12); + + foreach (@thread0) { + eval; eval(shift(@thread3)); + eval(shift(@thread1)); eval(shift(@thread3)); + eval(shift(@thread2)); eval(shift(@thread3)); + } + + @thread0=&NEONROUND($a0,$b0,$c0,$d0,$t0,1); + @thread1=&NEONROUND($a1,$b1,$c1,$d1,$t1,1); + @thread2=&NEONROUND($a2,$b2,$c2,$d2,$t2,1); + @thread3=&ROUND(0,5,10,15); + + foreach (@thread0) { + eval; eval(shift(@thread3)); + eval(shift(@thread1)); eval(shift(@thread3)); + eval(shift(@thread2)); eval(shift(@thread3)); + } +$code.=<<___; + bne .Loop_neon + + add @t[3],sp,#32 + vld1.32 {$t0-$t1},[sp] @ load key material + vld1.32 {$t2-$t3},[@t[3]] + + ldr @t[3],[sp,#4*(32+2)] @ load len + + str @t[0], [sp,#4*(16+8)] @ modulo-scheduled store + str @t[1], [sp,#4*(16+9)] + str @x[12],[sp,#4*(16+12)] + str @t[2], [sp,#4*(16+13)] + str @x[14],[sp,#4*(16+14)] + + @ at this point we have first half of 512-bit result in + @ @x[0-7] and second half at sp+4*(16+8) + + ldr r12,[sp,#4*(32+1)] @ load inp + ldr r14,[sp,#4*(32+0)] @ load out + + vadd.i32 $a0,$a0,$t0 @ accumulate key material + vadd.i32 $a1,$a1,$t0 + vadd.i32 $a2,$a2,$t0 + vldr $t0#lo,[sp,#4*(16+0)] @ one + + vadd.i32 $b0,$b0,$t1 + vadd.i32 $b1,$b1,$t1 + vadd.i32 $b2,$b2,$t1 + vldr $t1#lo,[sp,#4*(16+2)] @ two + + vadd.i32 $c0,$c0,$t2 + vadd.i32 $c1,$c1,$t2 + vadd.i32 $c2,$c2,$t2 + vadd.i32 $d1#lo,$d1#lo,$t0#lo @ counter+1 + vadd.i32 $d2#lo,$d2#lo,$t1#lo @ counter+2 + + vadd.i32 $d0,$d0,$t3 + vadd.i32 $d1,$d1,$t3 + vadd.i32 $d2,$d2,$t3 + + cmp @t[3],#64*4 + blo .Ltail_neon + + vld1.8 {$t0-$t1},[r12]! @ load input + mov @t[3],sp + vld1.8 {$t2-$t3},[r12]! + veor $a0,$a0,$t0 @ xor with input + veor $b0,$b0,$t1 + vld1.8 {$t0-$t1},[r12]! + veor $c0,$c0,$t2 + veor $d0,$d0,$t3 + vld1.8 {$t2-$t3},[r12]! + + veor $a1,$a1,$t0 + vst1.8 {$a0-$b0},[r14]! @ store output + veor $b1,$b1,$t1 + vld1.8 {$t0-$t1},[r12]! + veor $c1,$c1,$t2 + vst1.8 {$c0-$d0},[r14]! + veor $d1,$d1,$t3 + vld1.8 {$t2-$t3},[r12]! + + veor $a2,$a2,$t0 + vld1.32 {$a0-$b0},[@t[3]]! @ load for next iteration + veor $t0#hi,$t0#hi,$t0#hi + vldr $t0#lo,[sp,#4*(16+4)] @ four + veor $b2,$b2,$t1 + vld1.32 {$c0-$d0},[@t[3]] + veor $c2,$c2,$t2 + vst1.8 {$a1-$b1},[r14]! + veor $d2,$d2,$t3 + vst1.8 {$c1-$d1},[r14]! + + vadd.i32 $d0#lo,$d0#lo,$t0#lo @ next counter value + vldr $t0#lo,[sp,#4*(16+0)] @ one + + ldmia sp,{@t[0]-@t[3]} @ load key material + add @x[0],@x[0],@t[0] @ accumulate key material + ldr @t[0],[r12],#16 @ load input + vst1.8 {$a2-$b2},[r14]! + add @x[1],@x[1],@t[1] + ldr @t[1],[r12,#-12] + vst1.8 {$c2-$d2},[r14]! + add @x[2],@x[2],@t[2] + ldr @t[2],[r12,#-8] + add @x[3],@x[3],@t[3] + ldr @t[3],[r12,#-4] +# ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[1],@x[1] + rev @x[2],@x[2] + rev @x[3],@x[3] +# endif + eor @x[0],@x[0],@t[0] @ xor with input + add @t[0],sp,#4*(4) + eor @x[1],@x[1],@t[1] + str @x[0],[r14],#16 @ store output + eor @x[2],@x[2],@t[2] + str @x[1],[r14,#-12] + eor @x[3],@x[3],@t[3] + ldmia @t[0],{@t[0]-@t[3]} @ load key material + str @x[2],[r14,#-8] + str @x[3],[r14,#-4] + + add @x[4],@x[4],@t[0] @ accumulate key material + ldr @t[0],[r12],#16 @ load input + add @x[5],@x[5],@t[1] + ldr @t[1],[r12,#-12] + add @x[6],@x[6],@t[2] + ldr @t[2],[r12,#-8] + add @x[7],@x[7],@t[3] + ldr @t[3],[r12,#-4] +# ifdef __ARMEB__ + rev @x[4],@x[4] + rev @x[5],@x[5] + rev @x[6],@x[6] + rev @x[7],@x[7] +# endif + eor @x[4],@x[4],@t[0] + add @t[0],sp,#4*(8) + eor @x[5],@x[5],@t[1] + str @x[4],[r14],#16 @ store output + eor @x[6],@x[6],@t[2] + str @x[5],[r14,#-12] + eor @x[7],@x[7],@t[3] + ldmia @t[0],{@t[0]-@t[3]} @ load key material + str @x[6],[r14,#-8] + add @x[0],sp,#4*(16+8) + str @x[7],[r14,#-4] + + ldmia @x[0],{@x[0]-@x[7]} @ load second half + + add @x[0],@x[0],@t[0] @ accumulate key material + ldr @t[0],[r12],#16 @ load input + add @x[1],@x[1],@t[1] + ldr @t[1],[r12,#-12] +# ifdef __thumb2__ + it hi +# endif + strhi @t[2],[sp,#4*(16+10)] @ copy "@x[10]" while at it + add @x[2],@x[2],@t[2] + ldr @t[2],[r12,#-8] +# ifdef __thumb2__ + it hi +# endif + strhi @t[3],[sp,#4*(16+11)] @ copy "@x[11]" while at it + add @x[3],@x[3],@t[3] + ldr @t[3],[r12,#-4] +# ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[1],@x[1] + rev @x[2],@x[2] + rev @x[3],@x[3] +# endif + eor @x[0],@x[0],@t[0] + add @t[0],sp,#4*(12) + eor @x[1],@x[1],@t[1] + str @x[0],[r14],#16 @ store output + eor @x[2],@x[2],@t[2] + str @x[1],[r14,#-12] + eor @x[3],@x[3],@t[3] + ldmia @t[0],{@t[0]-@t[3]} @ load key material + str @x[2],[r14,#-8] + str @x[3],[r14,#-4] + + add @x[4],@x[4],@t[0] @ accumulate key material + add @t[0],@t[0],#4 @ next counter value + add @x[5],@x[5],@t[1] + str @t[0],[sp,#4*(12)] @ save next counter value + ldr @t[0],[r12],#16 @ load input + add @x[6],@x[6],@t[2] + add @x[4],@x[4],#3 @ counter+3 + ldr @t[1],[r12,#-12] + add @x[7],@x[7],@t[3] + ldr @t[2],[r12,#-8] + ldr @t[3],[r12,#-4] +# ifdef __ARMEB__ + rev @x[4],@x[4] + rev @x[5],@x[5] + rev @x[6],@x[6] + rev @x[7],@x[7] +# endif + eor @x[4],@x[4],@t[0] +# ifdef __thumb2__ + it hi +# endif + ldrhi @t[0],[sp,#4*(32+2)] @ re-load len + eor @x[5],@x[5],@t[1] + eor @x[6],@x[6],@t[2] + str @x[4],[r14],#16 @ store output + eor @x[7],@x[7],@t[3] + str @x[5],[r14,#-12] + sub @t[3],@t[0],#64*4 @ len-=64*4 + str @x[6],[r14,#-8] + str @x[7],[r14,#-4] + bhi .Loop_neon_outer + + b .Ldone_neon + +.align 4 +.Lbreak_neon: + @ harmonize NEON and integer-only stack frames: load data + @ from NEON frame, but save to integer-only one; distance + @ between the two is 4*(32+4+16-32)=4*(20). + + str @t[3], [sp,#4*(20+32+2)] @ save len + add @t[3],sp,#4*(32+4) + str r12, [sp,#4*(20+32+1)] @ save inp + str r14, [sp,#4*(20+32+0)] @ save out + + ldr @x[12],[sp,#4*(16+10)] + ldr @x[14],[sp,#4*(16+11)] + vldmia @t[3],{d8-d15} @ fulfill ABI requirement + str @x[12],[sp,#4*(20+16+10)] @ copy "@x[10]" + str @x[14],[sp,#4*(20+16+11)] @ copy "@x[11]" + + ldr @t[3], [sp,#4*(15)] + ldr @x[12],[sp,#4*(12)] @ modulo-scheduled load + ldr @t[2], [sp,#4*(13)] + ldr @x[14],[sp,#4*(14)] + str @t[3], [sp,#4*(20+16+15)] + add @t[3],sp,#4*(20) + vst1.32 {$a0-$b0},[@t[3]]! @ copy key + add sp,sp,#4*(20) @ switch frame + vst1.32 {$c0-$d0},[@t[3]] + mov @t[3],#10 + b .Loop @ go integer-only + +.align 4 +.Ltail_neon: + cmp @t[3],#64*3 + bhs .L192_or_more_neon + cmp @t[3],#64*2 + bhs .L128_or_more_neon + cmp @t[3],#64*1 + bhs .L64_or_more_neon + + add @t[0],sp,#4*(8) + vst1.8 {$a0-$b0},[sp] + add @t[2],sp,#4*(0) + vst1.8 {$c0-$d0},[@t[0]] + b .Loop_tail_neon + +.align 4 +.L64_or_more_neon: + vld1.8 {$t0-$t1},[r12]! + vld1.8 {$t2-$t3},[r12]! + veor $a0,$a0,$t0 + veor $b0,$b0,$t1 + veor $c0,$c0,$t2 + veor $d0,$d0,$t3 + vst1.8 {$a0-$b0},[r14]! + vst1.8 {$c0-$d0},[r14]! + + beq .Ldone_neon + + add @t[0],sp,#4*(8) + vst1.8 {$a1-$b1},[sp] + add @t[2],sp,#4*(0) + vst1.8 {$c1-$d1},[@t[0]] + sub @t[3],@t[3],#64*1 @ len-=64*1 + b .Loop_tail_neon + +.align 4 +.L128_or_more_neon: + vld1.8 {$t0-$t1},[r12]! + vld1.8 {$t2-$t3},[r12]! + veor $a0,$a0,$t0 + veor $b0,$b0,$t1 + vld1.8 {$t0-$t1},[r12]! + veor $c0,$c0,$t2 + veor $d0,$d0,$t3 + vld1.8 {$t2-$t3},[r12]! + + veor $a1,$a1,$t0 + veor $b1,$b1,$t1 + vst1.8 {$a0-$b0},[r14]! + veor $c1,$c1,$t2 + vst1.8 {$c0-$d0},[r14]! + veor $d1,$d1,$t3 + vst1.8 {$a1-$b1},[r14]! + vst1.8 {$c1-$d1},[r14]! + + beq .Ldone_neon + + add @t[0],sp,#4*(8) + vst1.8 {$a2-$b2},[sp] + add @t[2],sp,#4*(0) + vst1.8 {$c2-$d2},[@t[0]] + sub @t[3],@t[3],#64*2 @ len-=64*2 + b .Loop_tail_neon + +.align 4 +.L192_or_more_neon: + vld1.8 {$t0-$t1},[r12]! + vld1.8 {$t2-$t3},[r12]! + veor $a0,$a0,$t0 + veor $b0,$b0,$t1 + vld1.8 {$t0-$t1},[r12]! + veor $c0,$c0,$t2 + veor $d0,$d0,$t3 + vld1.8 {$t2-$t3},[r12]! + + veor $a1,$a1,$t0 + veor $b1,$b1,$t1 + vld1.8 {$t0-$t1},[r12]! + veor $c1,$c1,$t2 + vst1.8 {$a0-$b0},[r14]! + veor $d1,$d1,$t3 + vld1.8 {$t2-$t3},[r12]! + + veor $a2,$a2,$t0 + vst1.8 {$c0-$d0},[r14]! + veor $b2,$b2,$t1 + vst1.8 {$a1-$b1},[r14]! + veor $c2,$c2,$t2 + vst1.8 {$c1-$d1},[r14]! + veor $d2,$d2,$t3 + vst1.8 {$a2-$b2},[r14]! + vst1.8 {$c2-$d2},[r14]! + + beq .Ldone_neon + + ldmia sp,{@t[0]-@t[3]} @ load key material + add @x[0],@x[0],@t[0] @ accumulate key material + add @t[0],sp,#4*(4) + add @x[1],@x[1],@t[1] + add @x[2],@x[2],@t[2] + add @x[3],@x[3],@t[3] + ldmia @t[0],{@t[0]-@t[3]} @ load key material + + add @x[4],@x[4],@t[0] @ accumulate key material + add @t[0],sp,#4*(8) + add @x[5],@x[5],@t[1] + add @x[6],@x[6],@t[2] + add @x[7],@x[7],@t[3] + ldmia @t[0],{@t[0]-@t[3]} @ load key material +# ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[1],@x[1] + rev @x[2],@x[2] + rev @x[3],@x[3] + rev @x[4],@x[4] + rev @x[5],@x[5] + rev @x[6],@x[6] + rev @x[7],@x[7] +# endif + stmia sp,{@x[0]-@x[7]} + add @x[0],sp,#4*(16+8) + + ldmia @x[0],{@x[0]-@x[7]} @ load second half + + add @x[0],@x[0],@t[0] @ accumulate key material + add @t[0],sp,#4*(12) + add @x[1],@x[1],@t[1] + add @x[2],@x[2],@t[2] + add @x[3],@x[3],@t[3] + ldmia @t[0],{@t[0]-@t[3]} @ load key material + + add @x[4],@x[4],@t[0] @ accumulate key material + add @t[0],sp,#4*(8) + add @x[5],@x[5],@t[1] + add @x[4],@x[4],#3 @ counter+3 + add @x[6],@x[6],@t[2] + add @x[7],@x[7],@t[3] + ldr @t[3],[sp,#4*(32+2)] @ re-load len +# ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[1],@x[1] + rev @x[2],@x[2] + rev @x[3],@x[3] + rev @x[4],@x[4] + rev @x[5],@x[5] + rev @x[6],@x[6] + rev @x[7],@x[7] +# endif + stmia @t[0],{@x[0]-@x[7]} + add @t[2],sp,#4*(0) + sub @t[3],@t[3],#64*3 @ len-=64*3 + +.Loop_tail_neon: + ldrb @t[0],[@t[2]],#1 @ read buffer on stack + ldrb @t[1],[r12],#1 @ read input + subs @t[3],@t[3],#1 + eor @t[0],@t[0],@t[1] + strb @t[0],[r14],#1 @ store output + bne .Loop_tail_neon + +.Ldone_neon: + add sp,sp,#4*(32+4) + vldmia sp,{d8-d15} + add sp,sp,#4*(16+3) + ldmia sp!,{r4-r11,pc} +.size ChaCha20_neon,.-ChaCha20_neon +.comm OPENSSL_armcap_P,4,4 +#endif +___ +}}} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/geo; + + s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo; + + print $_,"\n"; +} +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/chacha/asm/chacha-armv8.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/chacha/asm/chacha-armv8.pl new file mode 100755 index 000000000..e90be6d0e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/chacha/asm/chacha-armv8.pl @@ -0,0 +1,1144 @@ +#! /usr/bin/env perl +# Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# June 2015 +# +# ChaCha20 for ARMv8. +# +# Performance in cycles per byte out of large buffer. +# +# IALU/gcc-4.9 3xNEON+1xIALU 6xNEON+2xIALU +# +# Apple A7 5.50/+49% 3.33 1.70 +# Cortex-A53 8.40/+80% 4.72 4.72(*) +# Cortex-A57 8.06/+43% 4.90 4.43(**) +# Denver 4.50/+82% 2.63 2.67(*) +# X-Gene 9.50/+46% 8.82 8.89(*) +# Mongoose 8.00/+44% 3.64 3.25 +# Kryo 8.17/+50% 4.83 4.65 +# +# (*) it's expected that doubling interleave factor doesn't help +# all processors, only those with higher NEON latency and +# higher instruction issue rate; +# (**) expected improvement was actually higher; + +$flavour=shift; +$output=shift; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or +die "can't locate arm-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +sub AUTOLOAD() # thunk [simplified] x86-style perlasm +{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; $opcode =~ s/_/\./; + my $arg = pop; + $arg = "#$arg" if ($arg*1 eq $arg); + $code .= "\t$opcode\t".join(',',@_,$arg)."\n"; +} + +my ($out,$inp,$len,$key,$ctr) = map("x$_",(0..4)); + +my @x=map("x$_",(5..17,19..21)); +my @d=map("x$_",(22..28,30)); + +sub ROUND { +my ($a0,$b0,$c0,$d0)=@_; +my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0)); +my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1)); +my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2)); + + ( + "&add_32 (@x[$a0],@x[$a0],@x[$b0])", + "&add_32 (@x[$a1],@x[$a1],@x[$b1])", + "&add_32 (@x[$a2],@x[$a2],@x[$b2])", + "&add_32 (@x[$a3],@x[$a3],@x[$b3])", + "&eor_32 (@x[$d0],@x[$d0],@x[$a0])", + "&eor_32 (@x[$d1],@x[$d1],@x[$a1])", + "&eor_32 (@x[$d2],@x[$d2],@x[$a2])", + "&eor_32 (@x[$d3],@x[$d3],@x[$a3])", + "&ror_32 (@x[$d0],@x[$d0],16)", + "&ror_32 (@x[$d1],@x[$d1],16)", + "&ror_32 (@x[$d2],@x[$d2],16)", + "&ror_32 (@x[$d3],@x[$d3],16)", + + "&add_32 (@x[$c0],@x[$c0],@x[$d0])", + "&add_32 (@x[$c1],@x[$c1],@x[$d1])", + "&add_32 (@x[$c2],@x[$c2],@x[$d2])", + "&add_32 (@x[$c3],@x[$c3],@x[$d3])", + "&eor_32 (@x[$b0],@x[$b0],@x[$c0])", + "&eor_32 (@x[$b1],@x[$b1],@x[$c1])", + "&eor_32 (@x[$b2],@x[$b2],@x[$c2])", + "&eor_32 (@x[$b3],@x[$b3],@x[$c3])", + "&ror_32 (@x[$b0],@x[$b0],20)", + "&ror_32 (@x[$b1],@x[$b1],20)", + "&ror_32 (@x[$b2],@x[$b2],20)", + "&ror_32 (@x[$b3],@x[$b3],20)", + + "&add_32 (@x[$a0],@x[$a0],@x[$b0])", + "&add_32 (@x[$a1],@x[$a1],@x[$b1])", + "&add_32 (@x[$a2],@x[$a2],@x[$b2])", + "&add_32 (@x[$a3],@x[$a3],@x[$b3])", + "&eor_32 (@x[$d0],@x[$d0],@x[$a0])", + "&eor_32 (@x[$d1],@x[$d1],@x[$a1])", + "&eor_32 (@x[$d2],@x[$d2],@x[$a2])", + "&eor_32 (@x[$d3],@x[$d3],@x[$a3])", + "&ror_32 (@x[$d0],@x[$d0],24)", + "&ror_32 (@x[$d1],@x[$d1],24)", + "&ror_32 (@x[$d2],@x[$d2],24)", + "&ror_32 (@x[$d3],@x[$d3],24)", + + "&add_32 (@x[$c0],@x[$c0],@x[$d0])", + "&add_32 (@x[$c1],@x[$c1],@x[$d1])", + "&add_32 (@x[$c2],@x[$c2],@x[$d2])", + "&add_32 (@x[$c3],@x[$c3],@x[$d3])", + "&eor_32 (@x[$b0],@x[$b0],@x[$c0])", + "&eor_32 (@x[$b1],@x[$b1],@x[$c1])", + "&eor_32 (@x[$b2],@x[$b2],@x[$c2])", + "&eor_32 (@x[$b3],@x[$b3],@x[$c3])", + "&ror_32 (@x[$b0],@x[$b0],25)", + "&ror_32 (@x[$b1],@x[$b1],25)", + "&ror_32 (@x[$b2],@x[$b2],25)", + "&ror_32 (@x[$b3],@x[$b3],25)" + ); +} + +$code.=<<___; +#include "arm_arch.h" + +.text + +.extern OPENSSL_armcap_P + +.align 5 +.Lsigma: +.quad 0x3320646e61707865,0x6b20657479622d32 // endian-neutral +.Lone: +.long 1,0,0,0 +.LOPENSSL_armcap_P: +#ifdef __ILP32__ +.long OPENSSL_armcap_P-. +#else +.quad OPENSSL_armcap_P-. +#endif +.asciz "ChaCha20 for ARMv8, CRYPTOGAMS by " + +.globl ChaCha20_ctr32 +.type ChaCha20_ctr32,%function +.align 5 +ChaCha20_ctr32: + cbz $len,.Labort + adr @x[0],.LOPENSSL_armcap_P + cmp $len,#192 + b.lo .Lshort +#ifdef __ILP32__ + ldrsw @x[1],[@x[0]] +#else + ldr @x[1],[@x[0]] +#endif + ldr w17,[@x[1],@x[0]] + tst w17,#ARMV7_NEON + b.ne ChaCha20_neon + +.Lshort: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-96]! + add x29,sp,#0 + + adr @x[0],.Lsigma + stp x19,x20,[sp,#16] + stp x21,x22,[sp,#32] + stp x23,x24,[sp,#48] + stp x25,x26,[sp,#64] + stp x27,x28,[sp,#80] + sub sp,sp,#64 + + ldp @d[0],@d[1],[@x[0]] // load sigma + ldp @d[2],@d[3],[$key] // load key + ldp @d[4],@d[5],[$key,#16] + ldp @d[6],@d[7],[$ctr] // load counter +#ifdef __ARMEB__ + ror @d[2],@d[2],#32 + ror @d[3],@d[3],#32 + ror @d[4],@d[4],#32 + ror @d[5],@d[5],#32 + ror @d[6],@d[6],#32 + ror @d[7],@d[7],#32 +#endif + +.Loop_outer: + mov.32 @x[0],@d[0] // unpack key block + lsr @x[1],@d[0],#32 + mov.32 @x[2],@d[1] + lsr @x[3],@d[1],#32 + mov.32 @x[4],@d[2] + lsr @x[5],@d[2],#32 + mov.32 @x[6],@d[3] + lsr @x[7],@d[3],#32 + mov.32 @x[8],@d[4] + lsr @x[9],@d[4],#32 + mov.32 @x[10],@d[5] + lsr @x[11],@d[5],#32 + mov.32 @x[12],@d[6] + lsr @x[13],@d[6],#32 + mov.32 @x[14],@d[7] + lsr @x[15],@d[7],#32 + + mov $ctr,#10 + subs $len,$len,#64 +.Loop: + sub $ctr,$ctr,#1 +___ + foreach (&ROUND(0, 4, 8,12)) { eval; } + foreach (&ROUND(0, 5,10,15)) { eval; } +$code.=<<___; + cbnz $ctr,.Loop + + add.32 @x[0],@x[0],@d[0] // accumulate key block + add @x[1],@x[1],@d[0],lsr#32 + add.32 @x[2],@x[2],@d[1] + add @x[3],@x[3],@d[1],lsr#32 + add.32 @x[4],@x[4],@d[2] + add @x[5],@x[5],@d[2],lsr#32 + add.32 @x[6],@x[6],@d[3] + add @x[7],@x[7],@d[3],lsr#32 + add.32 @x[8],@x[8],@d[4] + add @x[9],@x[9],@d[4],lsr#32 + add.32 @x[10],@x[10],@d[5] + add @x[11],@x[11],@d[5],lsr#32 + add.32 @x[12],@x[12],@d[6] + add @x[13],@x[13],@d[6],lsr#32 + add.32 @x[14],@x[14],@d[7] + add @x[15],@x[15],@d[7],lsr#32 + + b.lo .Ltail + + add @x[0],@x[0],@x[1],lsl#32 // pack + add @x[2],@x[2],@x[3],lsl#32 + ldp @x[1],@x[3],[$inp,#0] // load input + add @x[4],@x[4],@x[5],lsl#32 + add @x[6],@x[6],@x[7],lsl#32 + ldp @x[5],@x[7],[$inp,#16] + add @x[8],@x[8],@x[9],lsl#32 + add @x[10],@x[10],@x[11],lsl#32 + ldp @x[9],@x[11],[$inp,#32] + add @x[12],@x[12],@x[13],lsl#32 + add @x[14],@x[14],@x[15],lsl#32 + ldp @x[13],@x[15],[$inp,#48] + add $inp,$inp,#64 +#ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[2],@x[2] + rev @x[4],@x[4] + rev @x[6],@x[6] + rev @x[8],@x[8] + rev @x[10],@x[10] + rev @x[12],@x[12] + rev @x[14],@x[14] +#endif + eor @x[0],@x[0],@x[1] + eor @x[2],@x[2],@x[3] + eor @x[4],@x[4],@x[5] + eor @x[6],@x[6],@x[7] + eor @x[8],@x[8],@x[9] + eor @x[10],@x[10],@x[11] + eor @x[12],@x[12],@x[13] + eor @x[14],@x[14],@x[15] + + stp @x[0],@x[2],[$out,#0] // store output + add @d[6],@d[6],#1 // increment counter + stp @x[4],@x[6],[$out,#16] + stp @x[8],@x[10],[$out,#32] + stp @x[12],@x[14],[$out,#48] + add $out,$out,#64 + + b.hi .Loop_outer + + ldp x19,x20,[x29,#16] + add sp,sp,#64 + ldp x21,x22,[x29,#32] + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x27,x28,[x29,#80] + ldp x29,x30,[sp],#96 + .inst 0xd50323bf // autiasp +.Labort: + ret + +.align 4 +.Ltail: + add $len,$len,#64 +.Less_than_64: + sub $out,$out,#1 + add $inp,$inp,$len + add $out,$out,$len + add $ctr,sp,$len + neg $len,$len + + add @x[0],@x[0],@x[1],lsl#32 // pack + add @x[2],@x[2],@x[3],lsl#32 + add @x[4],@x[4],@x[5],lsl#32 + add @x[6],@x[6],@x[7],lsl#32 + add @x[8],@x[8],@x[9],lsl#32 + add @x[10],@x[10],@x[11],lsl#32 + add @x[12],@x[12],@x[13],lsl#32 + add @x[14],@x[14],@x[15],lsl#32 +#ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[2],@x[2] + rev @x[4],@x[4] + rev @x[6],@x[6] + rev @x[8],@x[8] + rev @x[10],@x[10] + rev @x[12],@x[12] + rev @x[14],@x[14] +#endif + stp @x[0],@x[2],[sp,#0] + stp @x[4],@x[6],[sp,#16] + stp @x[8],@x[10],[sp,#32] + stp @x[12],@x[14],[sp,#48] + +.Loop_tail: + ldrb w10,[$inp,$len] + ldrb w11,[$ctr,$len] + add $len,$len,#1 + eor w10,w10,w11 + strb w10,[$out,$len] + cbnz $len,.Loop_tail + + stp xzr,xzr,[sp,#0] + stp xzr,xzr,[sp,#16] + stp xzr,xzr,[sp,#32] + stp xzr,xzr,[sp,#48] + + ldp x19,x20,[x29,#16] + add sp,sp,#64 + ldp x21,x22,[x29,#32] + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x27,x28,[x29,#80] + ldp x29,x30,[sp],#96 + .inst 0xd50323bf // autiasp + ret +.size ChaCha20_ctr32,.-ChaCha20_ctr32 +___ + +{{{ +my ($A0,$B0,$C0,$D0,$A1,$B1,$C1,$D1,$A2,$B2,$C2,$D2,$T0,$T1,$T2,$T3) = + map("v$_.4s",(0..7,16..23)); +my (@K)=map("v$_.4s",(24..30)); +my $ONE="v31.4s"; + +sub NEONROUND { +my $odd = pop; +my ($a,$b,$c,$d,$t)=@_; + + ( + "&add ('$a','$a','$b')", + "&eor ('$d','$d','$a')", + "&rev32_16 ('$d','$d')", # vrot ($d,16) + + "&add ('$c','$c','$d')", + "&eor ('$t','$b','$c')", + "&ushr ('$b','$t',20)", + "&sli ('$b','$t',12)", + + "&add ('$a','$a','$b')", + "&eor ('$t','$d','$a')", + "&ushr ('$d','$t',24)", + "&sli ('$d','$t',8)", + + "&add ('$c','$c','$d')", + "&eor ('$t','$b','$c')", + "&ushr ('$b','$t',25)", + "&sli ('$b','$t',7)", + + "&ext ('$c','$c','$c',8)", + "&ext ('$d','$d','$d',$odd?4:12)", + "&ext ('$b','$b','$b',$odd?12:4)" + ); +} + +$code.=<<___; + +.type ChaCha20_neon,%function +.align 5 +ChaCha20_neon: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-96]! + add x29,sp,#0 + + adr @x[0],.Lsigma + stp x19,x20,[sp,#16] + stp x21,x22,[sp,#32] + stp x23,x24,[sp,#48] + stp x25,x26,[sp,#64] + stp x27,x28,[sp,#80] + cmp $len,#512 + b.hs .L512_or_more_neon + + sub sp,sp,#64 + + ldp @d[0],@d[1],[@x[0]] // load sigma + ld1 {@K[0]},[@x[0]],#16 + ldp @d[2],@d[3],[$key] // load key + ldp @d[4],@d[5],[$key,#16] + ld1 {@K[1],@K[2]},[$key] + ldp @d[6],@d[7],[$ctr] // load counter + ld1 {@K[3]},[$ctr] + ld1 {$ONE},[@x[0]] +#ifdef __ARMEB__ + rev64 @K[0],@K[0] + ror @d[2],@d[2],#32 + ror @d[3],@d[3],#32 + ror @d[4],@d[4],#32 + ror @d[5],@d[5],#32 + ror @d[6],@d[6],#32 + ror @d[7],@d[7],#32 +#endif + add @K[3],@K[3],$ONE // += 1 + add @K[4],@K[3],$ONE + add @K[5],@K[4],$ONE + shl $ONE,$ONE,#2 // 1 -> 4 + +.Loop_outer_neon: + mov.32 @x[0],@d[0] // unpack key block + lsr @x[1],@d[0],#32 + mov $A0,@K[0] + mov.32 @x[2],@d[1] + lsr @x[3],@d[1],#32 + mov $A1,@K[0] + mov.32 @x[4],@d[2] + lsr @x[5],@d[2],#32 + mov $A2,@K[0] + mov.32 @x[6],@d[3] + mov $B0,@K[1] + lsr @x[7],@d[3],#32 + mov $B1,@K[1] + mov.32 @x[8],@d[4] + mov $B2,@K[1] + lsr @x[9],@d[4],#32 + mov $D0,@K[3] + mov.32 @x[10],@d[5] + mov $D1,@K[4] + lsr @x[11],@d[5],#32 + mov $D2,@K[5] + mov.32 @x[12],@d[6] + mov $C0,@K[2] + lsr @x[13],@d[6],#32 + mov $C1,@K[2] + mov.32 @x[14],@d[7] + mov $C2,@K[2] + lsr @x[15],@d[7],#32 + + mov $ctr,#10 + subs $len,$len,#256 +.Loop_neon: + sub $ctr,$ctr,#1 +___ + my @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,0); + my @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,0); + my @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,0); + my @thread3=&ROUND(0,4,8,12); + + foreach (@thread0) { + eval; eval(shift(@thread3)); + eval(shift(@thread1)); eval(shift(@thread3)); + eval(shift(@thread2)); eval(shift(@thread3)); + } + + @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,1); + @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,1); + @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,1); + @thread3=&ROUND(0,5,10,15); + + foreach (@thread0) { + eval; eval(shift(@thread3)); + eval(shift(@thread1)); eval(shift(@thread3)); + eval(shift(@thread2)); eval(shift(@thread3)); + } +$code.=<<___; + cbnz $ctr,.Loop_neon + + add.32 @x[0],@x[0],@d[0] // accumulate key block + add $A0,$A0,@K[0] + add @x[1],@x[1],@d[0],lsr#32 + add $A1,$A1,@K[0] + add.32 @x[2],@x[2],@d[1] + add $A2,$A2,@K[0] + add @x[3],@x[3],@d[1],lsr#32 + add $C0,$C0,@K[2] + add.32 @x[4],@x[4],@d[2] + add $C1,$C1,@K[2] + add @x[5],@x[5],@d[2],lsr#32 + add $C2,$C2,@K[2] + add.32 @x[6],@x[6],@d[3] + add $D0,$D0,@K[3] + add @x[7],@x[7],@d[3],lsr#32 + add.32 @x[8],@x[8],@d[4] + add $D1,$D1,@K[4] + add @x[9],@x[9],@d[4],lsr#32 + add.32 @x[10],@x[10],@d[5] + add $D2,$D2,@K[5] + add @x[11],@x[11],@d[5],lsr#32 + add.32 @x[12],@x[12],@d[6] + add $B0,$B0,@K[1] + add @x[13],@x[13],@d[6],lsr#32 + add.32 @x[14],@x[14],@d[7] + add $B1,$B1,@K[1] + add @x[15],@x[15],@d[7],lsr#32 + add $B2,$B2,@K[1] + + b.lo .Ltail_neon + + add @x[0],@x[0],@x[1],lsl#32 // pack + add @x[2],@x[2],@x[3],lsl#32 + ldp @x[1],@x[3],[$inp,#0] // load input + add @x[4],@x[4],@x[5],lsl#32 + add @x[6],@x[6],@x[7],lsl#32 + ldp @x[5],@x[7],[$inp,#16] + add @x[8],@x[8],@x[9],lsl#32 + add @x[10],@x[10],@x[11],lsl#32 + ldp @x[9],@x[11],[$inp,#32] + add @x[12],@x[12],@x[13],lsl#32 + add @x[14],@x[14],@x[15],lsl#32 + ldp @x[13],@x[15],[$inp,#48] + add $inp,$inp,#64 +#ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[2],@x[2] + rev @x[4],@x[4] + rev @x[6],@x[6] + rev @x[8],@x[8] + rev @x[10],@x[10] + rev @x[12],@x[12] + rev @x[14],@x[14] +#endif + ld1.8 {$T0-$T3},[$inp],#64 + eor @x[0],@x[0],@x[1] + eor @x[2],@x[2],@x[3] + eor @x[4],@x[4],@x[5] + eor @x[6],@x[6],@x[7] + eor @x[8],@x[8],@x[9] + eor $A0,$A0,$T0 + eor @x[10],@x[10],@x[11] + eor $B0,$B0,$T1 + eor @x[12],@x[12],@x[13] + eor $C0,$C0,$T2 + eor @x[14],@x[14],@x[15] + eor $D0,$D0,$T3 + ld1.8 {$T0-$T3},[$inp],#64 + + stp @x[0],@x[2],[$out,#0] // store output + add @d[6],@d[6],#4 // increment counter + stp @x[4],@x[6],[$out,#16] + add @K[3],@K[3],$ONE // += 4 + stp @x[8],@x[10],[$out,#32] + add @K[4],@K[4],$ONE + stp @x[12],@x[14],[$out,#48] + add @K[5],@K[5],$ONE + add $out,$out,#64 + + st1.8 {$A0-$D0},[$out],#64 + ld1.8 {$A0-$D0},[$inp],#64 + + eor $A1,$A1,$T0 + eor $B1,$B1,$T1 + eor $C1,$C1,$T2 + eor $D1,$D1,$T3 + st1.8 {$A1-$D1},[$out],#64 + + eor $A2,$A2,$A0 + eor $B2,$B2,$B0 + eor $C2,$C2,$C0 + eor $D2,$D2,$D0 + st1.8 {$A2-$D2},[$out],#64 + + b.hi .Loop_outer_neon + + ldp x19,x20,[x29,#16] + add sp,sp,#64 + ldp x21,x22,[x29,#32] + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x27,x28,[x29,#80] + ldp x29,x30,[sp],#96 + .inst 0xd50323bf // autiasp + ret + +.Ltail_neon: + add $len,$len,#256 + cmp $len,#64 + b.lo .Less_than_64 + + add @x[0],@x[0],@x[1],lsl#32 // pack + add @x[2],@x[2],@x[3],lsl#32 + ldp @x[1],@x[3],[$inp,#0] // load input + add @x[4],@x[4],@x[5],lsl#32 + add @x[6],@x[6],@x[7],lsl#32 + ldp @x[5],@x[7],[$inp,#16] + add @x[8],@x[8],@x[9],lsl#32 + add @x[10],@x[10],@x[11],lsl#32 + ldp @x[9],@x[11],[$inp,#32] + add @x[12],@x[12],@x[13],lsl#32 + add @x[14],@x[14],@x[15],lsl#32 + ldp @x[13],@x[15],[$inp,#48] + add $inp,$inp,#64 +#ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[2],@x[2] + rev @x[4],@x[4] + rev @x[6],@x[6] + rev @x[8],@x[8] + rev @x[10],@x[10] + rev @x[12],@x[12] + rev @x[14],@x[14] +#endif + eor @x[0],@x[0],@x[1] + eor @x[2],@x[2],@x[3] + eor @x[4],@x[4],@x[5] + eor @x[6],@x[6],@x[7] + eor @x[8],@x[8],@x[9] + eor @x[10],@x[10],@x[11] + eor @x[12],@x[12],@x[13] + eor @x[14],@x[14],@x[15] + + stp @x[0],@x[2],[$out,#0] // store output + add @d[6],@d[6],#4 // increment counter + stp @x[4],@x[6],[$out,#16] + stp @x[8],@x[10],[$out,#32] + stp @x[12],@x[14],[$out,#48] + add $out,$out,#64 + b.eq .Ldone_neon + sub $len,$len,#64 + cmp $len,#64 + b.lo .Less_than_128 + + ld1.8 {$T0-$T3},[$inp],#64 + eor $A0,$A0,$T0 + eor $B0,$B0,$T1 + eor $C0,$C0,$T2 + eor $D0,$D0,$T3 + st1.8 {$A0-$D0},[$out],#64 + b.eq .Ldone_neon + sub $len,$len,#64 + cmp $len,#64 + b.lo .Less_than_192 + + ld1.8 {$T0-$T3},[$inp],#64 + eor $A1,$A1,$T0 + eor $B1,$B1,$T1 + eor $C1,$C1,$T2 + eor $D1,$D1,$T3 + st1.8 {$A1-$D1},[$out],#64 + b.eq .Ldone_neon + sub $len,$len,#64 + + st1.8 {$A2-$D2},[sp] + b .Last_neon + +.Less_than_128: + st1.8 {$A0-$D0},[sp] + b .Last_neon +.Less_than_192: + st1.8 {$A1-$D1},[sp] + b .Last_neon + +.align 4 +.Last_neon: + sub $out,$out,#1 + add $inp,$inp,$len + add $out,$out,$len + add $ctr,sp,$len + neg $len,$len + +.Loop_tail_neon: + ldrb w10,[$inp,$len] + ldrb w11,[$ctr,$len] + add $len,$len,#1 + eor w10,w10,w11 + strb w10,[$out,$len] + cbnz $len,.Loop_tail_neon + + stp xzr,xzr,[sp,#0] + stp xzr,xzr,[sp,#16] + stp xzr,xzr,[sp,#32] + stp xzr,xzr,[sp,#48] + +.Ldone_neon: + ldp x19,x20,[x29,#16] + add sp,sp,#64 + ldp x21,x22,[x29,#32] + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x27,x28,[x29,#80] + ldp x29,x30,[sp],#96 + .inst 0xd50323bf // autiasp + ret +.size ChaCha20_neon,.-ChaCha20_neon +___ +{ +my ($T0,$T1,$T2,$T3,$T4,$T5)=@K; +my ($A0,$B0,$C0,$D0,$A1,$B1,$C1,$D1,$A2,$B2,$C2,$D2, + $A3,$B3,$C3,$D3,$A4,$B4,$C4,$D4,$A5,$B5,$C5,$D5) = map("v$_.4s",(0..23)); + +$code.=<<___; +.type ChaCha20_512_neon,%function +.align 5 +ChaCha20_512_neon: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-96]! + add x29,sp,#0 + + adr @x[0],.Lsigma + stp x19,x20,[sp,#16] + stp x21,x22,[sp,#32] + stp x23,x24,[sp,#48] + stp x25,x26,[sp,#64] + stp x27,x28,[sp,#80] + +.L512_or_more_neon: + sub sp,sp,#128+64 + + ldp @d[0],@d[1],[@x[0]] // load sigma + ld1 {@K[0]},[@x[0]],#16 + ldp @d[2],@d[3],[$key] // load key + ldp @d[4],@d[5],[$key,#16] + ld1 {@K[1],@K[2]},[$key] + ldp @d[6],@d[7],[$ctr] // load counter + ld1 {@K[3]},[$ctr] + ld1 {$ONE},[@x[0]] +#ifdef __ARMEB__ + rev64 @K[0],@K[0] + ror @d[2],@d[2],#32 + ror @d[3],@d[3],#32 + ror @d[4],@d[4],#32 + ror @d[5],@d[5],#32 + ror @d[6],@d[6],#32 + ror @d[7],@d[7],#32 +#endif + add @K[3],@K[3],$ONE // += 1 + stp @K[0],@K[1],[sp,#0] // off-load key block, invariant part + add @K[3],@K[3],$ONE // not typo + str @K[2],[sp,#32] + add @K[4],@K[3],$ONE + add @K[5],@K[4],$ONE + add @K[6],@K[5],$ONE + shl $ONE,$ONE,#2 // 1 -> 4 + + stp d8,d9,[sp,#128+0] // meet ABI requirements + stp d10,d11,[sp,#128+16] + stp d12,d13,[sp,#128+32] + stp d14,d15,[sp,#128+48] + + sub $len,$len,#512 // not typo + +.Loop_outer_512_neon: + mov $A0,@K[0] + mov $A1,@K[0] + mov $A2,@K[0] + mov $A3,@K[0] + mov $A4,@K[0] + mov $A5,@K[0] + mov $B0,@K[1] + mov.32 @x[0],@d[0] // unpack key block + mov $B1,@K[1] + lsr @x[1],@d[0],#32 + mov $B2,@K[1] + mov.32 @x[2],@d[1] + mov $B3,@K[1] + lsr @x[3],@d[1],#32 + mov $B4,@K[1] + mov.32 @x[4],@d[2] + mov $B5,@K[1] + lsr @x[5],@d[2],#32 + mov $D0,@K[3] + mov.32 @x[6],@d[3] + mov $D1,@K[4] + lsr @x[7],@d[3],#32 + mov $D2,@K[5] + mov.32 @x[8],@d[4] + mov $D3,@K[6] + lsr @x[9],@d[4],#32 + mov $C0,@K[2] + mov.32 @x[10],@d[5] + mov $C1,@K[2] + lsr @x[11],@d[5],#32 + add $D4,$D0,$ONE // +4 + mov.32 @x[12],@d[6] + add $D5,$D1,$ONE // +4 + lsr @x[13],@d[6],#32 + mov $C2,@K[2] + mov.32 @x[14],@d[7] + mov $C3,@K[2] + lsr @x[15],@d[7],#32 + mov $C4,@K[2] + stp @K[3],@K[4],[sp,#48] // off-load key block, variable part + mov $C5,@K[2] + str @K[5],[sp,#80] + + mov $ctr,#5 + subs $len,$len,#512 +.Loop_upper_neon: + sub $ctr,$ctr,#1 +___ + my @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,0); + my @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,0); + my @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,0); + my @thread3=&NEONROUND($A3,$B3,$C3,$D3,$T3,0); + my @thread4=&NEONROUND($A4,$B4,$C4,$D4,$T4,0); + my @thread5=&NEONROUND($A5,$B5,$C5,$D5,$T5,0); + my @thread67=(&ROUND(0,4,8,12),&ROUND(0,5,10,15)); + my $diff = ($#thread0+1)*6 - $#thread67 - 1; + my $i = 0; + + foreach (@thread0) { + eval; eval(shift(@thread67)); + eval(shift(@thread1)); eval(shift(@thread67)); + eval(shift(@thread2)); eval(shift(@thread67)); + eval(shift(@thread3)); eval(shift(@thread67)); + eval(shift(@thread4)); eval(shift(@thread67)); + eval(shift(@thread5)); eval(shift(@thread67)); + } + + @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,1); + @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,1); + @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,1); + @thread3=&NEONROUND($A3,$B3,$C3,$D3,$T3,1); + @thread4=&NEONROUND($A4,$B4,$C4,$D4,$T4,1); + @thread5=&NEONROUND($A5,$B5,$C5,$D5,$T5,1); + @thread67=(&ROUND(0,4,8,12),&ROUND(0,5,10,15)); + + foreach (@thread0) { + eval; eval(shift(@thread67)); + eval(shift(@thread1)); eval(shift(@thread67)); + eval(shift(@thread2)); eval(shift(@thread67)); + eval(shift(@thread3)); eval(shift(@thread67)); + eval(shift(@thread4)); eval(shift(@thread67)); + eval(shift(@thread5)); eval(shift(@thread67)); + } +$code.=<<___; + cbnz $ctr,.Loop_upper_neon + + add.32 @x[0],@x[0],@d[0] // accumulate key block + add @x[1],@x[1],@d[0],lsr#32 + add.32 @x[2],@x[2],@d[1] + add @x[3],@x[3],@d[1],lsr#32 + add.32 @x[4],@x[4],@d[2] + add @x[5],@x[5],@d[2],lsr#32 + add.32 @x[6],@x[6],@d[3] + add @x[7],@x[7],@d[3],lsr#32 + add.32 @x[8],@x[8],@d[4] + add @x[9],@x[9],@d[4],lsr#32 + add.32 @x[10],@x[10],@d[5] + add @x[11],@x[11],@d[5],lsr#32 + add.32 @x[12],@x[12],@d[6] + add @x[13],@x[13],@d[6],lsr#32 + add.32 @x[14],@x[14],@d[7] + add @x[15],@x[15],@d[7],lsr#32 + + add @x[0],@x[0],@x[1],lsl#32 // pack + add @x[2],@x[2],@x[3],lsl#32 + ldp @x[1],@x[3],[$inp,#0] // load input + add @x[4],@x[4],@x[5],lsl#32 + add @x[6],@x[6],@x[7],lsl#32 + ldp @x[5],@x[7],[$inp,#16] + add @x[8],@x[8],@x[9],lsl#32 + add @x[10],@x[10],@x[11],lsl#32 + ldp @x[9],@x[11],[$inp,#32] + add @x[12],@x[12],@x[13],lsl#32 + add @x[14],@x[14],@x[15],lsl#32 + ldp @x[13],@x[15],[$inp,#48] + add $inp,$inp,#64 +#ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[2],@x[2] + rev @x[4],@x[4] + rev @x[6],@x[6] + rev @x[8],@x[8] + rev @x[10],@x[10] + rev @x[12],@x[12] + rev @x[14],@x[14] +#endif + eor @x[0],@x[0],@x[1] + eor @x[2],@x[2],@x[3] + eor @x[4],@x[4],@x[5] + eor @x[6],@x[6],@x[7] + eor @x[8],@x[8],@x[9] + eor @x[10],@x[10],@x[11] + eor @x[12],@x[12],@x[13] + eor @x[14],@x[14],@x[15] + + stp @x[0],@x[2],[$out,#0] // store output + add @d[6],@d[6],#1 // increment counter + mov.32 @x[0],@d[0] // unpack key block + lsr @x[1],@d[0],#32 + stp @x[4],@x[6],[$out,#16] + mov.32 @x[2],@d[1] + lsr @x[3],@d[1],#32 + stp @x[8],@x[10],[$out,#32] + mov.32 @x[4],@d[2] + lsr @x[5],@d[2],#32 + stp @x[12],@x[14],[$out,#48] + add $out,$out,#64 + mov.32 @x[6],@d[3] + lsr @x[7],@d[3],#32 + mov.32 @x[8],@d[4] + lsr @x[9],@d[4],#32 + mov.32 @x[10],@d[5] + lsr @x[11],@d[5],#32 + mov.32 @x[12],@d[6] + lsr @x[13],@d[6],#32 + mov.32 @x[14],@d[7] + lsr @x[15],@d[7],#32 + + mov $ctr,#5 +.Loop_lower_neon: + sub $ctr,$ctr,#1 +___ + @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,0); + @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,0); + @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,0); + @thread3=&NEONROUND($A3,$B3,$C3,$D3,$T3,0); + @thread4=&NEONROUND($A4,$B4,$C4,$D4,$T4,0); + @thread5=&NEONROUND($A5,$B5,$C5,$D5,$T5,0); + @thread67=(&ROUND(0,4,8,12),&ROUND(0,5,10,15)); + + foreach (@thread0) { + eval; eval(shift(@thread67)); + eval(shift(@thread1)); eval(shift(@thread67)); + eval(shift(@thread2)); eval(shift(@thread67)); + eval(shift(@thread3)); eval(shift(@thread67)); + eval(shift(@thread4)); eval(shift(@thread67)); + eval(shift(@thread5)); eval(shift(@thread67)); + } + + @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,1); + @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,1); + @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,1); + @thread3=&NEONROUND($A3,$B3,$C3,$D3,$T3,1); + @thread4=&NEONROUND($A4,$B4,$C4,$D4,$T4,1); + @thread5=&NEONROUND($A5,$B5,$C5,$D5,$T5,1); + @thread67=(&ROUND(0,4,8,12),&ROUND(0,5,10,15)); + + foreach (@thread0) { + eval; eval(shift(@thread67)); + eval(shift(@thread1)); eval(shift(@thread67)); + eval(shift(@thread2)); eval(shift(@thread67)); + eval(shift(@thread3)); eval(shift(@thread67)); + eval(shift(@thread4)); eval(shift(@thread67)); + eval(shift(@thread5)); eval(shift(@thread67)); + } +$code.=<<___; + cbnz $ctr,.Loop_lower_neon + + add.32 @x[0],@x[0],@d[0] // accumulate key block + ldp @K[0],@K[1],[sp,#0] + add @x[1],@x[1],@d[0],lsr#32 + ldp @K[2],@K[3],[sp,#32] + add.32 @x[2],@x[2],@d[1] + ldp @K[4],@K[5],[sp,#64] + add @x[3],@x[3],@d[1],lsr#32 + add $A0,$A0,@K[0] + add.32 @x[4],@x[4],@d[2] + add $A1,$A1,@K[0] + add @x[5],@x[5],@d[2],lsr#32 + add $A2,$A2,@K[0] + add.32 @x[6],@x[6],@d[3] + add $A3,$A3,@K[0] + add @x[7],@x[7],@d[3],lsr#32 + add $A4,$A4,@K[0] + add.32 @x[8],@x[8],@d[4] + add $A5,$A5,@K[0] + add @x[9],@x[9],@d[4],lsr#32 + add $C0,$C0,@K[2] + add.32 @x[10],@x[10],@d[5] + add $C1,$C1,@K[2] + add @x[11],@x[11],@d[5],lsr#32 + add $C2,$C2,@K[2] + add.32 @x[12],@x[12],@d[6] + add $C3,$C3,@K[2] + add @x[13],@x[13],@d[6],lsr#32 + add $C4,$C4,@K[2] + add.32 @x[14],@x[14],@d[7] + add $C5,$C5,@K[2] + add @x[15],@x[15],@d[7],lsr#32 + add $D4,$D4,$ONE // +4 + add @x[0],@x[0],@x[1],lsl#32 // pack + add $D5,$D5,$ONE // +4 + add @x[2],@x[2],@x[3],lsl#32 + add $D0,$D0,@K[3] + ldp @x[1],@x[3],[$inp,#0] // load input + add $D1,$D1,@K[4] + add @x[4],@x[4],@x[5],lsl#32 + add $D2,$D2,@K[5] + add @x[6],@x[6],@x[7],lsl#32 + add $D3,$D3,@K[6] + ldp @x[5],@x[7],[$inp,#16] + add $D4,$D4,@K[3] + add @x[8],@x[8],@x[9],lsl#32 + add $D5,$D5,@K[4] + add @x[10],@x[10],@x[11],lsl#32 + add $B0,$B0,@K[1] + ldp @x[9],@x[11],[$inp,#32] + add $B1,$B1,@K[1] + add @x[12],@x[12],@x[13],lsl#32 + add $B2,$B2,@K[1] + add @x[14],@x[14],@x[15],lsl#32 + add $B3,$B3,@K[1] + ldp @x[13],@x[15],[$inp,#48] + add $B4,$B4,@K[1] + add $inp,$inp,#64 + add $B5,$B5,@K[1] + +#ifdef __ARMEB__ + rev @x[0],@x[0] + rev @x[2],@x[2] + rev @x[4],@x[4] + rev @x[6],@x[6] + rev @x[8],@x[8] + rev @x[10],@x[10] + rev @x[12],@x[12] + rev @x[14],@x[14] +#endif + ld1.8 {$T0-$T3},[$inp],#64 + eor @x[0],@x[0],@x[1] + eor @x[2],@x[2],@x[3] + eor @x[4],@x[4],@x[5] + eor @x[6],@x[6],@x[7] + eor @x[8],@x[8],@x[9] + eor $A0,$A0,$T0 + eor @x[10],@x[10],@x[11] + eor $B0,$B0,$T1 + eor @x[12],@x[12],@x[13] + eor $C0,$C0,$T2 + eor @x[14],@x[14],@x[15] + eor $D0,$D0,$T3 + ld1.8 {$T0-$T3},[$inp],#64 + + stp @x[0],@x[2],[$out,#0] // store output + add @d[6],@d[6],#7 // increment counter + stp @x[4],@x[6],[$out,#16] + stp @x[8],@x[10],[$out,#32] + stp @x[12],@x[14],[$out,#48] + add $out,$out,#64 + st1.8 {$A0-$D0},[$out],#64 + + ld1.8 {$A0-$D0},[$inp],#64 + eor $A1,$A1,$T0 + eor $B1,$B1,$T1 + eor $C1,$C1,$T2 + eor $D1,$D1,$T3 + st1.8 {$A1-$D1},[$out],#64 + + ld1.8 {$A1-$D1},[$inp],#64 + eor $A2,$A2,$A0 + ldp @K[0],@K[1],[sp,#0] + eor $B2,$B2,$B0 + ldp @K[2],@K[3],[sp,#32] + eor $C2,$C2,$C0 + eor $D2,$D2,$D0 + st1.8 {$A2-$D2},[$out],#64 + + ld1.8 {$A2-$D2},[$inp],#64 + eor $A3,$A3,$A1 + eor $B3,$B3,$B1 + eor $C3,$C3,$C1 + eor $D3,$D3,$D1 + st1.8 {$A3-$D3},[$out],#64 + + ld1.8 {$A3-$D3},[$inp],#64 + eor $A4,$A4,$A2 + eor $B4,$B4,$B2 + eor $C4,$C4,$C2 + eor $D4,$D4,$D2 + st1.8 {$A4-$D4},[$out],#64 + + shl $A0,$ONE,#1 // 4 -> 8 + eor $A5,$A5,$A3 + eor $B5,$B5,$B3 + eor $C5,$C5,$C3 + eor $D5,$D5,$D3 + st1.8 {$A5-$D5},[$out],#64 + + add @K[3],@K[3],$A0 // += 8 + add @K[4],@K[4],$A0 + add @K[5],@K[5],$A0 + add @K[6],@K[6],$A0 + + b.hs .Loop_outer_512_neon + + adds $len,$len,#512 + ushr $A0,$ONE,#2 // 4 -> 1 + + ldp d8,d9,[sp,#128+0] // meet ABI requirements + ldp d10,d11,[sp,#128+16] + ldp d12,d13,[sp,#128+32] + ldp d14,d15,[sp,#128+48] + + stp @K[0],$ONE,[sp,#0] // wipe off-load area + stp @K[0],$ONE,[sp,#32] + stp @K[0],$ONE,[sp,#64] + + b.eq .Ldone_512_neon + + cmp $len,#192 + sub @K[3],@K[3],$A0 // -= 1 + sub @K[4],@K[4],$A0 + sub @K[5],@K[5],$A0 + add sp,sp,#128 + b.hs .Loop_outer_neon + + eor @K[1],@K[1],@K[1] + eor @K[2],@K[2],@K[2] + eor @K[3],@K[3],@K[3] + eor @K[4],@K[4],@K[4] + eor @K[5],@K[5],@K[5] + eor @K[6],@K[6],@K[6] + b .Loop_outer + +.Ldone_512_neon: + ldp x19,x20,[x29,#16] + add sp,sp,#128+64 + ldp x21,x22,[x29,#32] + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x27,x28,[x29,#80] + ldp x29,x30,[sp],#96 + .inst 0xd50323bf // autiasp + ret +.size ChaCha20_512_neon,.-ChaCha20_512_neon +___ +} +}}} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/geo; + + (s/\b([a-z]+)\.32\b/$1/ and (s/x([0-9]+)/w$1/g or 1)) or + (m/\b(eor|ext|mov)\b/ and (s/\.4s/\.16b/g or 1)) or + (s/\b((?:ld|st)1)\.8\b/$1/ and (s/\.4s/\.16b/g or 1)) or + (m/\b(ld|st)[rp]\b/ and (s/v([0-9]+)\.4s/q$1/g or 1)) or + (s/\brev32\.16\b/rev32/ and (s/\.4s/\.8h/g or 1)); + + #s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo; + + print $_,"\n"; +} +close STDOUT; # flush diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/chacha/asm/chacha-c64xplus.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/chacha/asm/chacha-c64xplus.pl new file mode 100755 index 000000000..266401eb1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/chacha/asm/chacha-c64xplus.pl @@ -0,0 +1,926 @@ +#! /usr/bin/env perl +# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# ChaCha20 for C64x+. +# +# October 2015 +# +# Performance is 3.54 cycles per processed byte, which is ~4.3 times +# faster than code generated by TI compiler. Compiler also disables +# interrupts for some reason, thus making interrupt response time +# dependent on input length. This module on the other hand is free +# from such limitation. + +$output=pop; +open STDOUT,">$output"; + +($OUT,$INP,$LEN,$KEYB,$COUNTERA)=("A4","B4","A6","B6","A8"); +($KEYA,$COUNTERB,$STEP)=("A7","B7","A3"); + +@X= ("A16","B16","A17","B17","A18","B18","A19","B19", + "A20","B20","A21","B21","A22","B22","A23","B23"); +@Y= ("A24","B24","A25","B25","A26","B26","A27","B27", + "A28","B28","A29","B29","A30","B30","A31","B31"); +@DAT=("A6", "A7", "B6", "B7", "A8", "A9", "B8", "B9", + "A10","A11","B10","B11","A12","A13","B12","B13"); + +# yes, overlaps with @DAT, used only in 2x interleave code path... +@K2x=("A6", "B6", "A7", "B7", "A8", "B8", "A9", "B9", + "A10","B10","A11","B11","A2", "B2", "A13","B13"); + +$code.=<<___; + .text + + .if .ASSEMBLER_VERSION<7000000 + .asg 0,__TI_EABI__ + .endif + .if __TI_EABI__ + .asg ChaCha20_ctr32,_ChaCha20_ctr32 + .endif + + .asg B3,RA + .asg A15,FP + .asg B15,SP + + .global _ChaCha20_ctr32 + .align 32 +_ChaCha20_ctr32: + .asmfunc stack_usage(40+64) + MV $LEN,A0 ; reassign + [!A0] BNOP RA ; no data +|| [A0] STW FP,*SP--(40+64) ; save frame pointer and alloca(40+64) +|| [A0] MV SP,FP + [A0] STDW B13:B12,*SP[4+8] ; ABI says so +|| [A0] MV $KEYB,$KEYA +|| [A0] MV $COUNTERA,$COUNTERB + [A0] STDW B11:B10,*SP[3+8] +|| [A0] STDW A13:A12,*FP[-3] + [A0] STDW A11:A10,*FP[-4] +|| [A0] MVK 128,$STEP ; 2 * input block size + + [A0] LDW *${KEYA}[0],@Y[4] ; load key +|| [A0] LDW *${KEYB}[1],@Y[5] +|| [A0] MVK 0x00007865,@Y[0] ; synthesize sigma +|| [A0] MVK 0x0000646e,@Y[1] + [A0] LDW *${KEYA}[2],@Y[6] +|| [A0] LDW *${KEYB}[3],@Y[7] +|| [A0] MVKH 0x61700000,@Y[0] +|| [A0] MVKH 0x33200000,@Y[1] + LDW *${KEYA}[4],@Y[8] +|| LDW *${KEYB}[5],@Y[9] +|| MVK 0x00002d32,@Y[2] +|| MVK 0x00006574,@Y[3] + LDW *${KEYA}[6],@Y[10] +|| LDW *${KEYB}[7],@Y[11] +|| MVKH 0x79620000,@Y[2] +|| MVKH 0x6b200000,@Y[3] + LDW *${COUNTERA}[0],@Y[12] ; load counter||nonce +|| LDW *${COUNTERB}[1],@Y[13] +|| CMPLTU A0,$STEP,A1 ; is length < 2*blocks? + LDW *${COUNTERA}[2],@Y[14] +|| LDW *${COUNTERB}[3],@Y[15] +|| [A1] BNOP top1x? + [A1] MVK 64,$STEP ; input block size +|| MVK 10,B0 ; inner loop counter + + DMV @Y[2],@Y[0],@X[2]:@X[0] ; copy block +|| DMV @Y[3],@Y[1],@X[3]:@X[1] +||[!A1] STDW @Y[2]:@Y[0],*FP[-12] ; offload key material to stack +||[!A1] STDW @Y[3]:@Y[1],*SP[2] + DMV @Y[6],@Y[4],@X[6]:@X[4] +|| DMV @Y[7],@Y[5],@X[7]:@X[5] +||[!A1] STDW @Y[6]:@Y[4],*FP[-10] +||[!A1] STDW @Y[7]:@Y[5],*SP[4] + DMV @Y[10],@Y[8],@X[10]:@X[8] +|| DMV @Y[11],@Y[9],@X[11]:@X[9] +||[!A1] STDW @Y[10]:@Y[8],*FP[-8] +||[!A1] STDW @Y[11]:@Y[9],*SP[6] + DMV @Y[14],@Y[12],@X[14]:@X[12] +|| DMV @Y[15],@Y[13],@X[15]:@X[13] +||[!A1] MV @Y[12],@K2x[12] ; counter +||[!A1] MV @Y[13],@K2x[13] +||[!A1] STW @Y[14],*FP[-6*2] +||[!A1] STW @Y[15],*SP[8*2] +___ +{ ################################################################ + # 2x interleave gives 50% performance improvement + # +my ($a0,$a1,$a2,$a3) = (0..3); +my ($b0,$b1,$b2,$b3) = (4..7); +my ($c0,$c1,$c2,$c3) = (8..11); +my ($d0,$d1,$d2,$d3) = (12..15); + +$code.=<<___; +outer2x?: + ADD @X[$b1],@X[$a1],@X[$a1] +|| ADD @X[$b2],@X[$a2],@X[$a2] +|| ADD @X[$b0],@X[$a0],@X[$a0] +|| ADD @X[$b3],@X[$a3],@X[$a3] +|| DMV @Y[2],@Y[0],@K2x[2]:@K2x[0] +|| DMV @Y[3],@Y[1],@K2x[3]:@K2x[1] + XOR @X[$a1],@X[$d1],@X[$d1] +|| XOR @X[$a2],@X[$d2],@X[$d2] +|| XOR @X[$a0],@X[$d0],@X[$d0] +|| XOR @X[$a3],@X[$d3],@X[$d3] +|| DMV @Y[6],@Y[4],@K2x[6]:@K2x[4] +|| DMV @Y[7],@Y[5],@K2x[7]:@K2x[5] + SWAP2 @X[$d1],@X[$d1] ; rotate by 16 +|| SWAP2 @X[$d2],@X[$d2] +|| SWAP2 @X[$d0],@X[$d0] +|| SWAP2 @X[$d3],@X[$d3] + + ADD @X[$d1],@X[$c1],@X[$c1] +|| ADD @X[$d2],@X[$c2],@X[$c2] +|| ADD @X[$d0],@X[$c0],@X[$c0] +|| ADD @X[$d3],@X[$c3],@X[$c3] +|| DMV @Y[10],@Y[8],@K2x[10]:@K2x[8] +|| DMV @Y[11],@Y[9],@K2x[11]:@K2x[9] + XOR @X[$c1],@X[$b1],@X[$b1] +|| XOR @X[$c2],@X[$b2],@X[$b2] +|| XOR @X[$c0],@X[$b0],@X[$b0] +|| XOR @X[$c3],@X[$b3],@X[$b3] +|| ADD 1,@Y[12],@Y[12] ; adjust counter for 2nd block + ROTL @X[$b1],12,@X[$b1] +|| ROTL @X[$b2],12,@X[$b2] +|| MV @Y[14],@K2x[14] +|| MV @Y[15],@K2x[15] +top2x?: + ROTL @X[$b0],12,@X[$b0] +|| ROTL @X[$b3],12,@X[$b3] +|| ADD @Y[$b1],@Y[$a1],@Y[$a1] +|| ADD @Y[$b2],@Y[$a2],@Y[$a2] + ADD @Y[$b0],@Y[$a0],@Y[$a0] +|| ADD @Y[$b3],@Y[$a3],@Y[$a3] + +|| ADD @X[$b1],@X[$a1],@X[$a1] +|| ADD @X[$b2],@X[$a2],@X[$a2] +|| XOR @Y[$a1],@Y[$d1],@Y[$d1] +|| XOR @Y[$a2],@Y[$d2],@Y[$d2] + XOR @Y[$a0],@Y[$d0],@Y[$d0] +|| XOR @Y[$a3],@Y[$d3],@Y[$d3] +|| ADD @X[$b0],@X[$a0],@X[$a0] +|| ADD @X[$b3],@X[$a3],@X[$a3] +|| XOR @X[$a1],@X[$d1],@X[$d1] +|| XOR @X[$a2],@X[$d2],@X[$d2] + XOR @X[$a0],@X[$d0],@X[$d0] +|| XOR @X[$a3],@X[$d3],@X[$d3] +|| ROTL @X[$d1],8,@X[$d1] +|| ROTL @X[$d2],8,@X[$d2] +|| SWAP2 @Y[$d1],@Y[$d1] ; rotate by 16 +|| SWAP2 @Y[$d2],@Y[$d2] +|| SWAP2 @Y[$d0],@Y[$d0] +|| SWAP2 @Y[$d3],@Y[$d3] + ROTL @X[$d0],8,@X[$d0] +|| ROTL @X[$d3],8,@X[$d3] +|| ADD @Y[$d1],@Y[$c1],@Y[$c1] +|| ADD @Y[$d2],@Y[$c2],@Y[$c2] +|| ADD @Y[$d0],@Y[$c0],@Y[$c0] +|| ADD @Y[$d3],@Y[$c3],@Y[$c3] +|| BNOP middle2x1? ; protect from interrupt + + ADD @X[$d1],@X[$c1],@X[$c1] +|| ADD @X[$d2],@X[$c2],@X[$c2] +|| XOR @Y[$c1],@Y[$b1],@Y[$b1] +|| XOR @Y[$c2],@Y[$b2],@Y[$b2] +|| XOR @Y[$c0],@Y[$b0],@Y[$b0] +|| XOR @Y[$c3],@Y[$b3],@Y[$b3] + ADD @X[$d0],@X[$c0],@X[$c0] +|| ADD @X[$d3],@X[$c3],@X[$c3] +|| XOR @X[$c1],@X[$b1],@X[$b1] +|| XOR @X[$c2],@X[$b2],@X[$b2] +|| ROTL @X[$d1],0,@X[$d2] ; moved to avoid cross-path stall +|| ROTL @X[$d2],0,@X[$d3] + XOR @X[$c0],@X[$b0],@X[$b0] +|| XOR @X[$c3],@X[$b3],@X[$b3] +|| MV @X[$d0],@X[$d1] +|| MV @X[$d3],@X[$d0] +|| ROTL @Y[$b1],12,@Y[$b1] +|| ROTL @Y[$b2],12,@Y[$b2] + ROTL @X[$b1],7,@X[$b0] ; avoided cross-path stall +|| ROTL @X[$b2],7,@X[$b1] + ROTL @X[$b0],7,@X[$b3] +|| ROTL @X[$b3],7,@X[$b2] +middle2x1?: + + ROTL @Y[$b0],12,@Y[$b0] +|| ROTL @Y[$b3],12,@Y[$b3] +|| ADD @X[$b0],@X[$a0],@X[$a0] +|| ADD @X[$b1],@X[$a1],@X[$a1] + ADD @X[$b2],@X[$a2],@X[$a2] +|| ADD @X[$b3],@X[$a3],@X[$a3] + +|| ADD @Y[$b1],@Y[$a1],@Y[$a1] +|| ADD @Y[$b2],@Y[$a2],@Y[$a2] +|| XOR @X[$a0],@X[$d0],@X[$d0] +|| XOR @X[$a1],@X[$d1],@X[$d1] + XOR @X[$a2],@X[$d2],@X[$d2] +|| XOR @X[$a3],@X[$d3],@X[$d3] +|| ADD @Y[$b0],@Y[$a0],@Y[$a0] +|| ADD @Y[$b3],@Y[$a3],@Y[$a3] +|| XOR @Y[$a1],@Y[$d1],@Y[$d1] +|| XOR @Y[$a2],@Y[$d2],@Y[$d2] + XOR @Y[$a0],@Y[$d0],@Y[$d0] +|| XOR @Y[$a3],@Y[$d3],@Y[$d3] +|| ROTL @Y[$d1],8,@Y[$d1] +|| ROTL @Y[$d2],8,@Y[$d2] +|| SWAP2 @X[$d0],@X[$d0] ; rotate by 16 +|| SWAP2 @X[$d1],@X[$d1] +|| SWAP2 @X[$d2],@X[$d2] +|| SWAP2 @X[$d3],@X[$d3] + ROTL @Y[$d0],8,@Y[$d0] +|| ROTL @Y[$d3],8,@Y[$d3] +|| ADD @X[$d0],@X[$c2],@X[$c2] +|| ADD @X[$d1],@X[$c3],@X[$c3] +|| ADD @X[$d2],@X[$c0],@X[$c0] +|| ADD @X[$d3],@X[$c1],@X[$c1] +|| BNOP middle2x2? ; protect from interrupt + + ADD @Y[$d1],@Y[$c1],@Y[$c1] +|| ADD @Y[$d2],@Y[$c2],@Y[$c2] +|| XOR @X[$c2],@X[$b0],@X[$b0] +|| XOR @X[$c3],@X[$b1],@X[$b1] +|| XOR @X[$c0],@X[$b2],@X[$b2] +|| XOR @X[$c1],@X[$b3],@X[$b3] + ADD @Y[$d0],@Y[$c0],@Y[$c0] +|| ADD @Y[$d3],@Y[$c3],@Y[$c3] +|| XOR @Y[$c1],@Y[$b1],@Y[$b1] +|| XOR @Y[$c2],@Y[$b2],@Y[$b2] +|| ROTL @Y[$d1],0,@Y[$d2] ; moved to avoid cross-path stall +|| ROTL @Y[$d2],0,@Y[$d3] + XOR @Y[$c0],@Y[$b0],@Y[$b0] +|| XOR @Y[$c3],@Y[$b3],@Y[$b3] +|| MV @Y[$d0],@Y[$d1] +|| MV @Y[$d3],@Y[$d0] +|| ROTL @X[$b0],12,@X[$b0] +|| ROTL @X[$b1],12,@X[$b1] + ROTL @Y[$b1],7,@Y[$b0] ; avoided cross-path stall +|| ROTL @Y[$b2],7,@Y[$b1] + ROTL @Y[$b0],7,@Y[$b3] +|| ROTL @Y[$b3],7,@Y[$b2] +middle2x2?: + + ROTL @X[$b2],12,@X[$b2] +|| ROTL @X[$b3],12,@X[$b3] +|| ADD @Y[$b0],@Y[$a0],@Y[$a0] +|| ADD @Y[$b1],@Y[$a1],@Y[$a1] + ADD @Y[$b2],@Y[$a2],@Y[$a2] +|| ADD @Y[$b3],@Y[$a3],@Y[$a3] + +|| ADD @X[$b0],@X[$a0],@X[$a0] +|| ADD @X[$b1],@X[$a1],@X[$a1] +|| XOR @Y[$a0],@Y[$d0],@Y[$d0] +|| XOR @Y[$a1],@Y[$d1],@Y[$d1] + XOR @Y[$a2],@Y[$d2],@Y[$d2] +|| XOR @Y[$a3],@Y[$d3],@Y[$d3] +|| ADD @X[$b2],@X[$a2],@X[$a2] +|| ADD @X[$b3],@X[$a3],@X[$a3] +|| XOR @X[$a0],@X[$d0],@X[$d0] +|| XOR @X[$a1],@X[$d1],@X[$d1] + XOR @X[$a2],@X[$d2],@X[$d2] +|| XOR @X[$a3],@X[$d3],@X[$d3] +|| ROTL @X[$d0],8,@X[$d0] +|| ROTL @X[$d1],8,@X[$d1] +|| SWAP2 @Y[$d0],@Y[$d0] ; rotate by 16 +|| SWAP2 @Y[$d1],@Y[$d1] +|| SWAP2 @Y[$d2],@Y[$d2] +|| SWAP2 @Y[$d3],@Y[$d3] + ROTL @X[$d2],8,@X[$d2] +|| ROTL @X[$d3],8,@X[$d3] +|| ADD @Y[$d0],@Y[$c2],@Y[$c2] +|| ADD @Y[$d1],@Y[$c3],@Y[$c3] +|| ADD @Y[$d2],@Y[$c0],@Y[$c0] +|| ADD @Y[$d3],@Y[$c1],@Y[$c1] +|| BNOP bottom2x1? ; protect from interrupt + + ADD @X[$d0],@X[$c2],@X[$c2] +|| ADD @X[$d1],@X[$c3],@X[$c3] +|| XOR @Y[$c2],@Y[$b0],@Y[$b0] +|| XOR @Y[$c3],@Y[$b1],@Y[$b1] +|| XOR @Y[$c0],@Y[$b2],@Y[$b2] +|| XOR @Y[$c1],@Y[$b3],@Y[$b3] + ADD @X[$d2],@X[$c0],@X[$c0] +|| ADD @X[$d3],@X[$c1],@X[$c1] +|| XOR @X[$c2],@X[$b0],@X[$b0] +|| XOR @X[$c3],@X[$b1],@X[$b1] +|| ROTL @X[$d0],0,@X[$d3] ; moved to avoid cross-path stall +|| ROTL @X[$d1],0,@X[$d0] + XOR @X[$c0],@X[$b2],@X[$b2] +|| XOR @X[$c1],@X[$b3],@X[$b3] +|| MV @X[$d2],@X[$d1] +|| MV @X[$d3],@X[$d2] +|| ROTL @Y[$b0],12,@Y[$b0] +|| ROTL @Y[$b1],12,@Y[$b1] + ROTL @X[$b0],7,@X[$b1] ; avoided cross-path stall +|| ROTL @X[$b1],7,@X[$b2] + ROTL @X[$b2],7,@X[$b3] +|| ROTL @X[$b3],7,@X[$b0] +|| [B0] SUB B0,1,B0 ; decrement inner loop counter +bottom2x1?: + + ROTL @Y[$b2],12,@Y[$b2] +|| ROTL @Y[$b3],12,@Y[$b3] +|| [B0] ADD @X[$b1],@X[$a1],@X[$a1] ; modulo-scheduled +|| [B0] ADD @X[$b2],@X[$a2],@X[$a2] + [B0] ADD @X[$b0],@X[$a0],@X[$a0] +|| [B0] ADD @X[$b3],@X[$a3],@X[$a3] + +|| ADD @Y[$b0],@Y[$a0],@Y[$a0] +|| ADD @Y[$b1],@Y[$a1],@Y[$a1] +|| [B0] XOR @X[$a1],@X[$d1],@X[$d1] +|| [B0] XOR @X[$a2],@X[$d2],@X[$d2] + [B0] XOR @X[$a0],@X[$d0],@X[$d0] +|| [B0] XOR @X[$a3],@X[$d3],@X[$d3] +|| ADD @Y[$b2],@Y[$a2],@Y[$a2] +|| ADD @Y[$b3],@Y[$a3],@Y[$a3] +|| XOR @Y[$a0],@Y[$d0],@Y[$d0] +|| XOR @Y[$a1],@Y[$d1],@Y[$d1] + XOR @Y[$a2],@Y[$d2],@Y[$d2] +|| XOR @Y[$a3],@Y[$d3],@Y[$d3] +|| ROTL @Y[$d0],8,@Y[$d0] +|| ROTL @Y[$d1],8,@Y[$d1] +|| [B0] SWAP2 @X[$d1],@X[$d1] ; rotate by 16 +|| [B0] SWAP2 @X[$d2],@X[$d2] +|| [B0] SWAP2 @X[$d0],@X[$d0] +|| [B0] SWAP2 @X[$d3],@X[$d3] + ROTL @Y[$d2],8,@Y[$d2] +|| ROTL @Y[$d3],8,@Y[$d3] +|| [B0] ADD @X[$d1],@X[$c1],@X[$c1] +|| [B0] ADD @X[$d2],@X[$c2],@X[$c2] +|| [B0] ADD @X[$d0],@X[$c0],@X[$c0] +|| [B0] ADD @X[$d3],@X[$c3],@X[$c3] +|| [B0] BNOP top2x? ; even protects from interrupt + + ADD @Y[$d0],@Y[$c2],@Y[$c2] +|| ADD @Y[$d1],@Y[$c3],@Y[$c3] +|| [B0] XOR @X[$c1],@X[$b1],@X[$b1] +|| [B0] XOR @X[$c2],@X[$b2],@X[$b2] +|| [B0] XOR @X[$c0],@X[$b0],@X[$b0] +|| [B0] XOR @X[$c3],@X[$b3],@X[$b3] + ADD @Y[$d2],@Y[$c0],@Y[$c0] +|| ADD @Y[$d3],@Y[$c1],@Y[$c1] +|| XOR @Y[$c2],@Y[$b0],@Y[$b0] +|| XOR @Y[$c3],@Y[$b1],@Y[$b1] +|| ROTL @Y[$d0],0,@Y[$d3] ; moved to avoid cross-path stall +|| ROTL @Y[$d1],0,@Y[$d0] + XOR @Y[$c0],@Y[$b2],@Y[$b2] +|| XOR @Y[$c1],@Y[$b3],@Y[$b3] +|| MV @Y[$d2],@Y[$d1] +|| MV @Y[$d3],@Y[$d2] +|| [B0] ROTL @X[$b1],12,@X[$b1] +|| [B0] ROTL @X[$b2],12,@X[$b2] + ROTL @Y[$b0],7,@Y[$b1] ; avoided cross-path stall +|| ROTL @Y[$b1],7,@Y[$b2] + ROTL @Y[$b2],7,@Y[$b3] +|| ROTL @Y[$b3],7,@Y[$b0] +bottom2x2?: +___ +} + +$code.=<<___; + ADD @K2x[0],@X[0],@X[0] ; accumulate key material +|| ADD @K2x[1],@X[1],@X[1] +|| ADD @K2x[2],@X[2],@X[2] +|| ADD @K2x[3],@X[3],@X[3] + ADD @K2x[0],@Y[0],@Y[0] +|| ADD @K2x[1],@Y[1],@Y[1] +|| ADD @K2x[2],@Y[2],@Y[2] +|| ADD @K2x[3],@Y[3],@Y[3] +|| LDNDW *${INP}++[8],@DAT[1]:@DAT[0] + ADD @K2x[4],@X[4],@X[4] +|| ADD @K2x[5],@X[5],@X[5] +|| ADD @K2x[6],@X[6],@X[6] +|| ADD @K2x[7],@X[7],@X[7] +|| LDNDW *${INP}[-7],@DAT[3]:@DAT[2] + ADD @K2x[4],@Y[4],@Y[4] +|| ADD @K2x[5],@Y[5],@Y[5] +|| ADD @K2x[6],@Y[6],@Y[6] +|| ADD @K2x[7],@Y[7],@Y[7] +|| LDNDW *${INP}[-6],@DAT[5]:@DAT[4] + ADD @K2x[8],@X[8],@X[8] +|| ADD @K2x[9],@X[9],@X[9] +|| ADD @K2x[10],@X[10],@X[10] +|| ADD @K2x[11],@X[11],@X[11] +|| LDNDW *${INP}[-5],@DAT[7]:@DAT[6] + ADD @K2x[8],@Y[8],@Y[8] +|| ADD @K2x[9],@Y[9],@Y[9] +|| ADD @K2x[10],@Y[10],@Y[10] +|| ADD @K2x[11],@Y[11],@Y[11] +|| LDNDW *${INP}[-4],@DAT[9]:@DAT[8] + ADD @K2x[12],@X[12],@X[12] +|| ADD @K2x[13],@X[13],@X[13] +|| ADD @K2x[14],@X[14],@X[14] +|| ADD @K2x[15],@X[15],@X[15] +|| LDNDW *${INP}[-3],@DAT[11]:@DAT[10] + ADD @K2x[12],@Y[12],@Y[12] +|| ADD @K2x[13],@Y[13],@Y[13] +|| ADD @K2x[14],@Y[14],@Y[14] +|| ADD @K2x[15],@Y[15],@Y[15] +|| LDNDW *${INP}[-2],@DAT[13]:@DAT[12] + ADD 1,@Y[12],@Y[12] ; adjust counter for 2nd block +|| ADD 2,@K2x[12],@K2x[12] ; increment counter +|| LDNDW *${INP}[-1],@DAT[15]:@DAT[14] + + .if .BIG_ENDIAN + SWAP2 @X[0],@X[0] +|| SWAP2 @X[1],@X[1] +|| SWAP2 @X[2],@X[2] +|| SWAP2 @X[3],@X[3] + SWAP2 @X[4],@X[4] +|| SWAP2 @X[5],@X[5] +|| SWAP2 @X[6],@X[6] +|| SWAP2 @X[7],@X[7] + SWAP2 @X[8],@X[8] +|| SWAP2 @X[9],@X[9] +|| SWAP4 @X[0],@X[1] +|| SWAP4 @X[1],@X[0] + SWAP2 @X[10],@X[10] +|| SWAP2 @X[11],@X[11] +|| SWAP4 @X[2],@X[3] +|| SWAP4 @X[3],@X[2] + SWAP2 @X[12],@X[12] +|| SWAP2 @X[13],@X[13] +|| SWAP4 @X[4],@X[5] +|| SWAP4 @X[5],@X[4] + SWAP2 @X[14],@X[14] +|| SWAP2 @X[15],@X[15] +|| SWAP4 @X[6],@X[7] +|| SWAP4 @X[7],@X[6] + SWAP4 @X[8],@X[9] +|| SWAP4 @X[9],@X[8] +|| SWAP2 @Y[0],@Y[0] +|| SWAP2 @Y[1],@Y[1] + SWAP4 @X[10],@X[11] +|| SWAP4 @X[11],@X[10] +|| SWAP2 @Y[2],@Y[2] +|| SWAP2 @Y[3],@Y[3] + SWAP4 @X[12],@X[13] +|| SWAP4 @X[13],@X[12] +|| SWAP2 @Y[4],@Y[4] +|| SWAP2 @Y[5],@Y[5] + SWAP4 @X[14],@X[15] +|| SWAP4 @X[15],@X[14] +|| SWAP2 @Y[6],@Y[6] +|| SWAP2 @Y[7],@Y[7] + SWAP2 @Y[8],@Y[8] +|| SWAP2 @Y[9],@Y[9] +|| SWAP4 @Y[0],@Y[1] +|| SWAP4 @Y[1],@Y[0] + SWAP2 @Y[10],@Y[10] +|| SWAP2 @Y[11],@Y[11] +|| SWAP4 @Y[2],@Y[3] +|| SWAP4 @Y[3],@Y[2] + SWAP2 @Y[12],@Y[12] +|| SWAP2 @Y[13],@Y[13] +|| SWAP4 @Y[4],@Y[5] +|| SWAP4 @Y[5],@Y[4] + SWAP2 @Y[14],@Y[14] +|| SWAP2 @Y[15],@Y[15] +|| SWAP4 @Y[6],@Y[7] +|| SWAP4 @Y[7],@Y[6] + SWAP4 @Y[8],@Y[9] +|| SWAP4 @Y[9],@Y[8] + SWAP4 @Y[10],@Y[11] +|| SWAP4 @Y[11],@Y[10] + SWAP4 @Y[12],@Y[13] +|| SWAP4 @Y[13],@Y[12] + SWAP4 @Y[14],@Y[15] +|| SWAP4 @Y[15],@Y[14] + .endif + + XOR @DAT[0],@X[0],@X[0] ; xor 1st block +|| XOR @DAT[3],@X[3],@X[3] +|| XOR @DAT[2],@X[2],@X[1] +|| XOR @DAT[1],@X[1],@X[2] +|| LDNDW *${INP}++[8],@DAT[1]:@DAT[0] + XOR @DAT[4],@X[4],@X[4] +|| XOR @DAT[7],@X[7],@X[7] +|| LDNDW *${INP}[-7],@DAT[3]:@DAT[2] + XOR @DAT[6],@X[6],@X[5] +|| XOR @DAT[5],@X[5],@X[6] +|| LDNDW *${INP}[-6],@DAT[5]:@DAT[4] + XOR @DAT[8],@X[8],@X[8] +|| XOR @DAT[11],@X[11],@X[11] +|| LDNDW *${INP}[-5],@DAT[7]:@DAT[6] + XOR @DAT[10],@X[10],@X[9] +|| XOR @DAT[9],@X[9],@X[10] +|| LDNDW *${INP}[-4],@DAT[9]:@DAT[8] + XOR @DAT[12],@X[12],@X[12] +|| XOR @DAT[15],@X[15],@X[15] +|| LDNDW *${INP}[-3],@DAT[11]:@DAT[10] + XOR @DAT[14],@X[14],@X[13] +|| XOR @DAT[13],@X[13],@X[14] +|| LDNDW *${INP}[-2],@DAT[13]:@DAT[12] + [A0] SUB A0,$STEP,A0 ; SUB A0,128,A0 +|| LDNDW *${INP}[-1],@DAT[15]:@DAT[14] + + XOR @Y[0],@DAT[0],@DAT[0] ; xor 2nd block +|| XOR @Y[1],@DAT[1],@DAT[1] +|| STNDW @X[2]:@X[0],*${OUT}++[8] + XOR @Y[2],@DAT[2],@DAT[2] +|| XOR @Y[3],@DAT[3],@DAT[3] +|| STNDW @X[3]:@X[1],*${OUT}[-7] + XOR @Y[4],@DAT[4],@DAT[4] +|| [A0] LDDW *FP[-12],@X[2]:@X[0] ; re-load key material from stack +|| [A0] LDDW *SP[2], @X[3]:@X[1] + XOR @Y[5],@DAT[5],@DAT[5] +|| STNDW @X[6]:@X[4],*${OUT}[-6] + XOR @Y[6],@DAT[6],@DAT[6] +|| XOR @Y[7],@DAT[7],@DAT[7] +|| STNDW @X[7]:@X[5],*${OUT}[-5] + XOR @Y[8],@DAT[8],@DAT[8] +|| [A0] LDDW *FP[-10],@X[6]:@X[4] +|| [A0] LDDW *SP[4], @X[7]:@X[5] + XOR @Y[9],@DAT[9],@DAT[9] +|| STNDW @X[10]:@X[8],*${OUT}[-4] + XOR @Y[10],@DAT[10],@DAT[10] +|| XOR @Y[11],@DAT[11],@DAT[11] +|| STNDW @X[11]:@X[9],*${OUT}[-3] + XOR @Y[12],@DAT[12],@DAT[12] +|| [A0] LDDW *FP[-8], @X[10]:@X[8] +|| [A0] LDDW *SP[6], @X[11]:@X[9] + XOR @Y[13],@DAT[13],@DAT[13] +|| STNDW @X[14]:@X[12],*${OUT}[-2] + XOR @Y[14],@DAT[14],@DAT[14] +|| XOR @Y[15],@DAT[15],@DAT[15] +|| STNDW @X[15]:@X[13],*${OUT}[-1] + + [A0] MV @K2x[12],@X[12] +|| [A0] MV @K2x[13],@X[13] +|| [A0] LDW *FP[-6*2], @X[14] +|| [A0] LDW *SP[8*2], @X[15] + + [A0] DMV @X[2],@X[0],@Y[2]:@Y[0] ; duplicate key material +|| STNDW @DAT[1]:@DAT[0],*${OUT}++[8] + [A0] DMV @X[3],@X[1],@Y[3]:@Y[1] +|| STNDW @DAT[3]:@DAT[2],*${OUT}[-7] + [A0] DMV @X[6],@X[4],@Y[6]:@Y[4] +|| STNDW @DAT[5]:@DAT[4],*${OUT}[-6] +|| CMPLTU A0,$STEP,A1 ; is remaining length < 2*blocks? +||[!A0] BNOP epilogue? + [A0] DMV @X[7],@X[5],@Y[7]:@Y[5] +|| STNDW @DAT[7]:@DAT[6],*${OUT}[-5] +||[!A1] BNOP outer2x? + [A0] DMV @X[10],@X[8],@Y[10]:@Y[8] +|| STNDW @DAT[9]:@DAT[8],*${OUT}[-4] + [A0] DMV @X[11],@X[9],@Y[11]:@Y[9] +|| STNDW @DAT[11]:@DAT[10],*${OUT}[-3] + [A0] DMV @X[14],@X[12],@Y[14]:@Y[12] +|| STNDW @DAT[13]:@DAT[12],*${OUT}[-2] + [A0] DMV @X[15],@X[13],@Y[15]:@Y[13] +|| STNDW @DAT[15]:@DAT[14],*${OUT}[-1] +;;===== branch to epilogue? is taken here + [A1] MVK 64,$STEP +|| [A0] MVK 10,B0 ; inner loop counter +;;===== branch to outer2x? is taken here +___ +{ +my ($a0,$a1,$a2,$a3) = (0..3); +my ($b0,$b1,$b2,$b3) = (4..7); +my ($c0,$c1,$c2,$c3) = (8..11); +my ($d0,$d1,$d2,$d3) = (12..15); + +$code.=<<___; +top1x?: + ADD @X[$b1],@X[$a1],@X[$a1] +|| ADD @X[$b2],@X[$a2],@X[$a2] + ADD @X[$b0],@X[$a0],@X[$a0] +|| ADD @X[$b3],@X[$a3],@X[$a3] +|| XOR @X[$a1],@X[$d1],@X[$d1] +|| XOR @X[$a2],@X[$d2],@X[$d2] + XOR @X[$a0],@X[$d0],@X[$d0] +|| XOR @X[$a3],@X[$d3],@X[$d3] +|| SWAP2 @X[$d1],@X[$d1] ; rotate by 16 +|| SWAP2 @X[$d2],@X[$d2] + SWAP2 @X[$d0],@X[$d0] +|| SWAP2 @X[$d3],@X[$d3] + +|| ADD @X[$d1],@X[$c1],@X[$c1] +|| ADD @X[$d2],@X[$c2],@X[$c2] + ADD @X[$d0],@X[$c0],@X[$c0] +|| ADD @X[$d3],@X[$c3],@X[$c3] +|| XOR @X[$c1],@X[$b1],@X[$b1] +|| XOR @X[$c2],@X[$b2],@X[$b2] + XOR @X[$c0],@X[$b0],@X[$b0] +|| XOR @X[$c3],@X[$b3],@X[$b3] +|| ROTL @X[$b1],12,@X[$b1] +|| ROTL @X[$b2],12,@X[$b2] + ROTL @X[$b0],12,@X[$b0] +|| ROTL @X[$b3],12,@X[$b3] + + ADD @X[$b1],@X[$a1],@X[$a1] +|| ADD @X[$b2],@X[$a2],@X[$a2] + ADD @X[$b0],@X[$a0],@X[$a0] +|| ADD @X[$b3],@X[$a3],@X[$a3] +|| XOR @X[$a1],@X[$d1],@X[$d1] +|| XOR @X[$a2],@X[$d2],@X[$d2] + XOR @X[$a0],@X[$d0],@X[$d0] +|| XOR @X[$a3],@X[$d3],@X[$d3] +|| ROTL @X[$d1],8,@X[$d1] +|| ROTL @X[$d2],8,@X[$d2] + ROTL @X[$d0],8,@X[$d0] +|| ROTL @X[$d3],8,@X[$d3] +|| BNOP middle1x? ; protect from interrupt + + ADD @X[$d1],@X[$c1],@X[$c1] +|| ADD @X[$d2],@X[$c2],@X[$c2] + ADD @X[$d0],@X[$c0],@X[$c0] +|| ADD @X[$d3],@X[$c3],@X[$c3] +|| XOR @X[$c1],@X[$b1],@X[$b1] +|| XOR @X[$c2],@X[$b2],@X[$b2] +|| ROTL @X[$d1],0,@X[$d2] ; moved to avoid cross-path stall +|| ROTL @X[$d2],0,@X[$d3] + XOR @X[$c0],@X[$b0],@X[$b0] +|| XOR @X[$c3],@X[$b3],@X[$b3] +|| ROTL @X[$d0],0,@X[$d1] +|| ROTL @X[$d3],0,@X[$d0] + ROTL @X[$b1],7,@X[$b0] ; avoided cross-path stall +|| ROTL @X[$b2],7,@X[$b1] + ROTL @X[$b0],7,@X[$b3] +|| ROTL @X[$b3],7,@X[$b2] +middle1x?: + + ADD @X[$b0],@X[$a0],@X[$a0] +|| ADD @X[$b1],@X[$a1],@X[$a1] + ADD @X[$b2],@X[$a2],@X[$a2] +|| ADD @X[$b3],@X[$a3],@X[$a3] +|| XOR @X[$a0],@X[$d0],@X[$d0] +|| XOR @X[$a1],@X[$d1],@X[$d1] + XOR @X[$a2],@X[$d2],@X[$d2] +|| XOR @X[$a3],@X[$d3],@X[$d3] +|| SWAP2 @X[$d0],@X[$d0] ; rotate by 16 +|| SWAP2 @X[$d1],@X[$d1] + SWAP2 @X[$d2],@X[$d2] +|| SWAP2 @X[$d3],@X[$d3] + +|| ADD @X[$d0],@X[$c2],@X[$c2] +|| ADD @X[$d1],@X[$c3],@X[$c3] + ADD @X[$d2],@X[$c0],@X[$c0] +|| ADD @X[$d3],@X[$c1],@X[$c1] +|| XOR @X[$c2],@X[$b0],@X[$b0] +|| XOR @X[$c3],@X[$b1],@X[$b1] + XOR @X[$c0],@X[$b2],@X[$b2] +|| XOR @X[$c1],@X[$b3],@X[$b3] +|| ROTL @X[$b0],12,@X[$b0] +|| ROTL @X[$b1],12,@X[$b1] + ROTL @X[$b2],12,@X[$b2] +|| ROTL @X[$b3],12,@X[$b3] + + ADD @X[$b0],@X[$a0],@X[$a0] +|| ADD @X[$b1],@X[$a1],@X[$a1] +|| [B0] SUB B0,1,B0 ; decrement inner loop counter + ADD @X[$b2],@X[$a2],@X[$a2] +|| ADD @X[$b3],@X[$a3],@X[$a3] +|| XOR @X[$a0],@X[$d0],@X[$d0] +|| XOR @X[$a1],@X[$d1],@X[$d1] + XOR @X[$a2],@X[$d2],@X[$d2] +|| XOR @X[$a3],@X[$d3],@X[$d3] +|| ROTL @X[$d0],8,@X[$d0] +|| ROTL @X[$d1],8,@X[$d1] + ROTL @X[$d2],8,@X[$d2] +|| ROTL @X[$d3],8,@X[$d3] +|| [B0] BNOP top1x? ; even protects from interrupt + + ADD @X[$d0],@X[$c2],@X[$c2] +|| ADD @X[$d1],@X[$c3],@X[$c3] + ADD @X[$d2],@X[$c0],@X[$c0] +|| ADD @X[$d3],@X[$c1],@X[$c1] +|| XOR @X[$c2],@X[$b0],@X[$b0] +|| XOR @X[$c3],@X[$b1],@X[$b1] +|| ROTL @X[$d0],0,@X[$d3] ; moved to avoid cross-path stall +|| ROTL @X[$d1],0,@X[$d0] + XOR @X[$c0],@X[$b2],@X[$b2] +|| XOR @X[$c1],@X[$b3],@X[$b3] +|| ROTL @X[$d2],0,@X[$d1] +|| ROTL @X[$d3],0,@X[$d2] + ROTL @X[$b0],7,@X[$b1] ; avoided cross-path stall +|| ROTL @X[$b1],7,@X[$b2] + ROTL @X[$b2],7,@X[$b3] +|| ROTL @X[$b3],7,@X[$b0] +||[!B0] CMPLTU A0,$STEP,A1 ; less than 64 bytes left? +bottom1x?: +___ +} + +$code.=<<___; + ADD @Y[0],@X[0],@X[0] ; accumulate key material +|| ADD @Y[1],@X[1],@X[1] +|| ADD @Y[2],@X[2],@X[2] +|| ADD @Y[3],@X[3],@X[3] +||[!A1] LDNDW *${INP}++[8],@DAT[1]:@DAT[0] +|| [A1] BNOP tail? + ADD @Y[4],@X[4],@X[4] +|| ADD @Y[5],@X[5],@X[5] +|| ADD @Y[6],@X[6],@X[6] +|| ADD @Y[7],@X[7],@X[7] +||[!A1] LDNDW *${INP}[-7],@DAT[3]:@DAT[2] + ADD @Y[8],@X[8],@X[8] +|| ADD @Y[9],@X[9],@X[9] +|| ADD @Y[10],@X[10],@X[10] +|| ADD @Y[11],@X[11],@X[11] +||[!A1] LDNDW *${INP}[-6],@DAT[5]:@DAT[4] + ADD @Y[12],@X[12],@X[12] +|| ADD @Y[13],@X[13],@X[13] +|| ADD @Y[14],@X[14],@X[14] +|| ADD @Y[15],@X[15],@X[15] +||[!A1] LDNDW *${INP}[-5],@DAT[7]:@DAT[6] + [!A1] LDNDW *${INP}[-4],@DAT[9]:@DAT[8] + [!A1] LDNDW *${INP}[-3],@DAT[11]:@DAT[10] + LDNDW *${INP}[-2],@DAT[13]:@DAT[12] + LDNDW *${INP}[-1],@DAT[15]:@DAT[14] + + .if .BIG_ENDIAN + SWAP2 @X[0],@X[0] +|| SWAP2 @X[1],@X[1] +|| SWAP2 @X[2],@X[2] +|| SWAP2 @X[3],@X[3] + SWAP2 @X[4],@X[4] +|| SWAP2 @X[5],@X[5] +|| SWAP2 @X[6],@X[6] +|| SWAP2 @X[7],@X[7] + SWAP2 @X[8],@X[8] +|| SWAP2 @X[9],@X[9] +|| SWAP4 @X[0],@X[1] +|| SWAP4 @X[1],@X[0] + SWAP2 @X[10],@X[10] +|| SWAP2 @X[11],@X[11] +|| SWAP4 @X[2],@X[3] +|| SWAP4 @X[3],@X[2] + SWAP2 @X[12],@X[12] +|| SWAP2 @X[13],@X[13] +|| SWAP4 @X[4],@X[5] +|| SWAP4 @X[5],@X[4] + SWAP2 @X[14],@X[14] +|| SWAP2 @X[15],@X[15] +|| SWAP4 @X[6],@X[7] +|| SWAP4 @X[7],@X[6] + SWAP4 @X[8],@X[9] +|| SWAP4 @X[9],@X[8] + SWAP4 @X[10],@X[11] +|| SWAP4 @X[11],@X[10] + SWAP4 @X[12],@X[13] +|| SWAP4 @X[13],@X[12] + SWAP4 @X[14],@X[15] +|| SWAP4 @X[15],@X[14] + .else + NOP 1 + .endif + + XOR @X[0],@DAT[0],@DAT[0] ; xor with input +|| XOR @X[1],@DAT[1],@DAT[1] +|| XOR @X[2],@DAT[2],@DAT[2] +|| XOR @X[3],@DAT[3],@DAT[3] +|| [A0] SUB A0,$STEP,A0 ; SUB A0,64,A0 + XOR @X[4],@DAT[4],@DAT[4] +|| XOR @X[5],@DAT[5],@DAT[5] +|| XOR @X[6],@DAT[6],@DAT[6] +|| XOR @X[7],@DAT[7],@DAT[7] +|| STNDW @DAT[1]:@DAT[0],*${OUT}++[8] + XOR @X[8],@DAT[8],@DAT[8] +|| XOR @X[9],@DAT[9],@DAT[9] +|| XOR @X[10],@DAT[10],@DAT[10] +|| XOR @X[11],@DAT[11],@DAT[11] +|| STNDW @DAT[3]:@DAT[2],*${OUT}[-7] + XOR @X[12],@DAT[12],@DAT[12] +|| XOR @X[13],@DAT[13],@DAT[13] +|| XOR @X[14],@DAT[14],@DAT[14] +|| XOR @X[15],@DAT[15],@DAT[15] +|| STNDW @DAT[5]:@DAT[4],*${OUT}[-6] +|| [A0] BNOP top1x? + [A0] DMV @Y[2],@Y[0],@X[2]:@X[0] ; duplicate key material +|| [A0] DMV @Y[3],@Y[1],@X[3]:@X[1] +|| STNDW @DAT[7]:@DAT[6],*${OUT}[-5] + [A0] DMV @Y[6],@Y[4],@X[6]:@X[4] +|| [A0] DMV @Y[7],@Y[5],@X[7]:@X[5] +|| STNDW @DAT[9]:@DAT[8],*${OUT}[-4] + [A0] DMV @Y[10],@Y[8],@X[10]:@X[8] +|| [A0] DMV @Y[11],@Y[9],@X[11]:@X[9] +|| [A0] ADD 1,@Y[12],@Y[12] ; increment counter +|| STNDW @DAT[11]:@DAT[10],*${OUT}[-3] + [A0] DMV @Y[14],@Y[12],@X[14]:@X[12] +|| [A0] DMV @Y[15],@Y[13],@X[15]:@X[13] +|| STNDW @DAT[13]:@DAT[12],*${OUT}[-2] + [A0] MVK 10,B0 ; inner loop counter +|| STNDW @DAT[15]:@DAT[14],*${OUT}[-1] +;;===== branch to top1x? is taken here + +epilogue?: + LDDW *FP[-4],A11:A10 ; ABI says so + LDDW *FP[-3],A13:A12 +|| LDDW *SP[3+8],B11:B10 + LDDW *SP[4+8],B13:B12 +|| BNOP RA + LDW *++SP(40+64),FP ; restore frame pointer + NOP 4 + +tail?: + LDBU *${INP}++[1],B24 ; load byte by byte +|| SUB A0,1,A0 +|| SUB A0,1,B1 + [!B1] BNOP epilogue? ; interrupts are disabled for whole time +|| [A0] LDBU *${INP}++[1],B24 +|| [A0] SUB A0,1,A0 +|| SUB B1,1,B1 + [!B1] BNOP epilogue? +|| [A0] LDBU *${INP}++[1],B24 +|| [A0] SUB A0,1,A0 +|| SUB B1,1,B1 + [!B1] BNOP epilogue? +|| ROTL @X[0],0,A24 +|| [A0] LDBU *${INP}++[1],B24 +|| [A0] SUB A0,1,A0 +|| SUB B1,1,B1 + [!B1] BNOP epilogue? +|| ROTL @X[0],24,A24 +|| [A0] LDBU *${INP}++[1],A24 +|| [A0] SUB A0,1,A0 +|| SUB B1,1,B1 + [!B1] BNOP epilogue? +|| ROTL @X[0],16,A24 +|| [A0] LDBU *${INP}++[1],A24 +|| [A0] SUB A0,1,A0 +|| SUB B1,1,B1 +|| XOR A24,B24,B25 + STB B25,*${OUT}++[1] ; store byte by byte +||[!B1] BNOP epilogue? +|| ROTL @X[0],8,A24 +|| [A0] LDBU *${INP}++[1],A24 +|| [A0] SUB A0,1,A0 +|| SUB B1,1,B1 +|| XOR A24,B24,B25 + STB B25,*${OUT}++[1] +___ +sub TAIL_STEP { +my $Xi= shift; +my $T = ($Xi=~/^B/?"B24":"A24"); # match @X[i] to avoid cross path +my $D = $T; $D=~tr/AB/BA/; +my $O = $D; $O=~s/24/25/; + +$code.=<<___; +||[!B1] BNOP epilogue? +|| ROTL $Xi,0,$T +|| [A0] LDBU *${INP}++[1],$D +|| [A0] SUB A0,1,A0 +|| SUB B1,1,B1 +|| XOR A24,B24,$O + STB $O,*${OUT}++[1] +||[!B1] BNOP epilogue? +|| ROTL $Xi,24,$T +|| [A0] LDBU *${INP}++[1],$T +|| [A0] SUB A0,1,A0 +|| SUB B1,1,B1 +|| XOR A24,B24,$O + STB $O,*${OUT}++[1] +||[!B1] BNOP epilogue? +|| ROTL $Xi,16,$T +|| [A0] LDBU *${INP}++[1],$T +|| [A0] SUB A0,1,A0 +|| SUB B1,1,B1 +|| XOR A24,B24,$O + STB $O,*${OUT}++[1] +||[!B1] BNOP epilogue? +|| ROTL $Xi,8,$T +|| [A0] LDBU *${INP}++[1],$T +|| [A0] SUB A0,1,A0 +|| SUB B1,1,B1 +|| XOR A24,B24,$O + STB $O,*${OUT}++[1] +___ +} + foreach (1..14) { TAIL_STEP(@X[$_]); } +$code.=<<___; +||[!B1] BNOP epilogue? +|| ROTL @X[15],0,B24 +|| XOR A24,B24,A25 + STB A25,*${OUT}++[1] +|| ROTL @X[15],24,B24 +|| XOR A24,B24,A25 + STB A25,*${OUT}++[1] +|| ROTL @X[15],16,B24 +|| XOR A24,B24,A25 + STB A25,*${OUT}++[1] +|| XOR A24,B24,A25 + STB A25,*${OUT}++[1] +|| XOR A24,B24,B25 + STB B25,*${OUT}++[1] + .endasmfunc + + .sect .const + .cstring "ChaCha20 for C64x+, CRYPTOGAMS by " + .align 4 +___ + +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/chacha/asm/chacha-ppc.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/chacha/asm/chacha-ppc.pl new file mode 100755 index 000000000..f4f8610bf --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/chacha/asm/chacha-ppc.pl @@ -0,0 +1,1348 @@ +#! /usr/bin/env perl +# Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# October 2015 +# +# ChaCha20 for PowerPC/AltiVec. +# +# June 2018 +# +# Add VSX 2.07 code path. Original 3xAltiVec+1xIALU is well-suited for +# processors that can't issue more than one vector instruction per +# cycle. But POWER8 (and POWER9) can issue a pair, and vector-only 4x +# interleave would perform better. Incidentally PowerISA 2.07 (first +# implemented by POWER8) defined new usable instructions, hence 4xVSX +# code path... +# +# Performance in cycles per byte out of large buffer. +# +# IALU/gcc-4.x 3xAltiVec+1xIALU 4xVSX +# +# Freescale e300 13.6/+115% - - +# PPC74x0/G4e 6.81/+310% 3.81 - +# PPC970/G5 9.29/+160% ? - +# POWER7 8.62/+61% 3.35 - +# POWER8 8.70/+51% 2.91 2.09 +# POWER9 8.80/+29% 4.44(*) 2.45(**) +# +# (*) this is trade-off result, it's possible to improve it, but +# then it would negatively affect all others; +# (**) POWER9 seems to be "allergic" to mixing vector and integer +# instructions, which is why switch to vector-only code pays +# off that much; + +$flavour = shift; + +if ($flavour =~ /64/) { + $SIZE_T =8; + $LRSAVE =2*$SIZE_T; + $STU ="stdu"; + $POP ="ld"; + $PUSH ="std"; + $UCMP ="cmpld"; +} elsif ($flavour =~ /32/) { + $SIZE_T =4; + $LRSAVE =$SIZE_T; + $STU ="stwu"; + $POP ="lwz"; + $PUSH ="stw"; + $UCMP ="cmplw"; +} else { die "nonsense $flavour"; } + +$LITTLE_ENDIAN = ($flavour=~/le$/) ? 1 : 0; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or +die "can't locate ppc-xlate.pl"; + +open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!"; + +$LOCALS=6*$SIZE_T; +$FRAME=$LOCALS+64+18*$SIZE_T; # 64 is for local variables + +sub AUTOLOAD() # thunk [simplified] x86-style perlasm +{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; $opcode =~ s/_/\./; + $code .= "\t$opcode\t".join(',',@_)."\n"; +} + +my $sp = "r1"; + +my ($out,$inp,$len,$key,$ctr) = map("r$_",(3..7)); + +my @x=map("r$_",(16..31)); +my @d=map("r$_",(11,12,14,15)); +my @t=map("r$_",(7..10)); + +sub ROUND { +my ($a0,$b0,$c0,$d0)=@_; +my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0)); +my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1)); +my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2)); + + ( + "&add (@x[$a0],@x[$a0],@x[$b0])", + "&add (@x[$a1],@x[$a1],@x[$b1])", + "&add (@x[$a2],@x[$a2],@x[$b2])", + "&add (@x[$a3],@x[$a3],@x[$b3])", + "&xor (@x[$d0],@x[$d0],@x[$a0])", + "&xor (@x[$d1],@x[$d1],@x[$a1])", + "&xor (@x[$d2],@x[$d2],@x[$a2])", + "&xor (@x[$d3],@x[$d3],@x[$a3])", + "&rotlwi (@x[$d0],@x[$d0],16)", + "&rotlwi (@x[$d1],@x[$d1],16)", + "&rotlwi (@x[$d2],@x[$d2],16)", + "&rotlwi (@x[$d3],@x[$d3],16)", + + "&add (@x[$c0],@x[$c0],@x[$d0])", + "&add (@x[$c1],@x[$c1],@x[$d1])", + "&add (@x[$c2],@x[$c2],@x[$d2])", + "&add (@x[$c3],@x[$c3],@x[$d3])", + "&xor (@x[$b0],@x[$b0],@x[$c0])", + "&xor (@x[$b1],@x[$b1],@x[$c1])", + "&xor (@x[$b2],@x[$b2],@x[$c2])", + "&xor (@x[$b3],@x[$b3],@x[$c3])", + "&rotlwi (@x[$b0],@x[$b0],12)", + "&rotlwi (@x[$b1],@x[$b1],12)", + "&rotlwi (@x[$b2],@x[$b2],12)", + "&rotlwi (@x[$b3],@x[$b3],12)", + + "&add (@x[$a0],@x[$a0],@x[$b0])", + "&add (@x[$a1],@x[$a1],@x[$b1])", + "&add (@x[$a2],@x[$a2],@x[$b2])", + "&add (@x[$a3],@x[$a3],@x[$b3])", + "&xor (@x[$d0],@x[$d0],@x[$a0])", + "&xor (@x[$d1],@x[$d1],@x[$a1])", + "&xor (@x[$d2],@x[$d2],@x[$a2])", + "&xor (@x[$d3],@x[$d3],@x[$a3])", + "&rotlwi (@x[$d0],@x[$d0],8)", + "&rotlwi (@x[$d1],@x[$d1],8)", + "&rotlwi (@x[$d2],@x[$d2],8)", + "&rotlwi (@x[$d3],@x[$d3],8)", + + "&add (@x[$c0],@x[$c0],@x[$d0])", + "&add (@x[$c1],@x[$c1],@x[$d1])", + "&add (@x[$c2],@x[$c2],@x[$d2])", + "&add (@x[$c3],@x[$c3],@x[$d3])", + "&xor (@x[$b0],@x[$b0],@x[$c0])", + "&xor (@x[$b1],@x[$b1],@x[$c1])", + "&xor (@x[$b2],@x[$b2],@x[$c2])", + "&xor (@x[$b3],@x[$b3],@x[$c3])", + "&rotlwi (@x[$b0],@x[$b0],7)", + "&rotlwi (@x[$b1],@x[$b1],7)", + "&rotlwi (@x[$b2],@x[$b2],7)", + "&rotlwi (@x[$b3],@x[$b3],7)" + ); +} + +$code.=<<___; +.machine "any" +.text + +.globl .ChaCha20_ctr32_int +.align 5 +.ChaCha20_ctr32_int: +__ChaCha20_ctr32_int: + ${UCMP}i $len,0 + beqlr- + + $STU $sp,-$FRAME($sp) + mflr r0 + + $PUSH r14,`$FRAME-$SIZE_T*18`($sp) + $PUSH r15,`$FRAME-$SIZE_T*17`($sp) + $PUSH r16,`$FRAME-$SIZE_T*16`($sp) + $PUSH r17,`$FRAME-$SIZE_T*15`($sp) + $PUSH r18,`$FRAME-$SIZE_T*14`($sp) + $PUSH r19,`$FRAME-$SIZE_T*13`($sp) + $PUSH r20,`$FRAME-$SIZE_T*12`($sp) + $PUSH r21,`$FRAME-$SIZE_T*11`($sp) + $PUSH r22,`$FRAME-$SIZE_T*10`($sp) + $PUSH r23,`$FRAME-$SIZE_T*9`($sp) + $PUSH r24,`$FRAME-$SIZE_T*8`($sp) + $PUSH r25,`$FRAME-$SIZE_T*7`($sp) + $PUSH r26,`$FRAME-$SIZE_T*6`($sp) + $PUSH r27,`$FRAME-$SIZE_T*5`($sp) + $PUSH r28,`$FRAME-$SIZE_T*4`($sp) + $PUSH r29,`$FRAME-$SIZE_T*3`($sp) + $PUSH r30,`$FRAME-$SIZE_T*2`($sp) + $PUSH r31,`$FRAME-$SIZE_T*1`($sp) + $PUSH r0,`$FRAME+$LRSAVE`($sp) + + lwz @d[0],0($ctr) # load counter + lwz @d[1],4($ctr) + lwz @d[2],8($ctr) + lwz @d[3],12($ctr) + + bl __ChaCha20_1x + + $POP r0,`$FRAME+$LRSAVE`($sp) + $POP r14,`$FRAME-$SIZE_T*18`($sp) + $POP r15,`$FRAME-$SIZE_T*17`($sp) + $POP r16,`$FRAME-$SIZE_T*16`($sp) + $POP r17,`$FRAME-$SIZE_T*15`($sp) + $POP r18,`$FRAME-$SIZE_T*14`($sp) + $POP r19,`$FRAME-$SIZE_T*13`($sp) + $POP r20,`$FRAME-$SIZE_T*12`($sp) + $POP r21,`$FRAME-$SIZE_T*11`($sp) + $POP r22,`$FRAME-$SIZE_T*10`($sp) + $POP r23,`$FRAME-$SIZE_T*9`($sp) + $POP r24,`$FRAME-$SIZE_T*8`($sp) + $POP r25,`$FRAME-$SIZE_T*7`($sp) + $POP r26,`$FRAME-$SIZE_T*6`($sp) + $POP r27,`$FRAME-$SIZE_T*5`($sp) + $POP r28,`$FRAME-$SIZE_T*4`($sp) + $POP r29,`$FRAME-$SIZE_T*3`($sp) + $POP r30,`$FRAME-$SIZE_T*2`($sp) + $POP r31,`$FRAME-$SIZE_T*1`($sp) + mtlr r0 + addi $sp,$sp,$FRAME + blr + .long 0 + .byte 0,12,4,1,0x80,18,5,0 + .long 0 +.size .ChaCha20_ctr32_int,.-.ChaCha20_ctr32_int + +.align 5 +__ChaCha20_1x: +Loop_outer: + lis @x[0],0x6170 # synthesize sigma + lis @x[1],0x3320 + lis @x[2],0x7962 + lis @x[3],0x6b20 + ori @x[0],@x[0],0x7865 + ori @x[1],@x[1],0x646e + ori @x[2],@x[2],0x2d32 + ori @x[3],@x[3],0x6574 + + li r0,10 # inner loop counter + lwz @x[4],0($key) # load key + lwz @x[5],4($key) + lwz @x[6],8($key) + lwz @x[7],12($key) + lwz @x[8],16($key) + mr @x[12],@d[0] # copy counter + lwz @x[9],20($key) + mr @x[13],@d[1] + lwz @x[10],24($key) + mr @x[14],@d[2] + lwz @x[11],28($key) + mr @x[15],@d[3] + + mr @t[0],@x[4] + mr @t[1],@x[5] + mr @t[2],@x[6] + mr @t[3],@x[7] + + mtctr r0 +Loop: +___ + foreach (&ROUND(0, 4, 8,12)) { eval; } + foreach (&ROUND(0, 5,10,15)) { eval; } +$code.=<<___; + bdnz Loop + + subic $len,$len,64 # $len-=64 + addi @x[0],@x[0],0x7865 # accumulate key block + addi @x[1],@x[1],0x646e + addi @x[2],@x[2],0x2d32 + addi @x[3],@x[3],0x6574 + addis @x[0],@x[0],0x6170 + addis @x[1],@x[1],0x3320 + addis @x[2],@x[2],0x7962 + addis @x[3],@x[3],0x6b20 + + subfe. r0,r0,r0 # borrow?-1:0 + add @x[4],@x[4],@t[0] + lwz @t[0],16($key) + add @x[5],@x[5],@t[1] + lwz @t[1],20($key) + add @x[6],@x[6],@t[2] + lwz @t[2],24($key) + add @x[7],@x[7],@t[3] + lwz @t[3],28($key) + add @x[8],@x[8],@t[0] + add @x[9],@x[9],@t[1] + add @x[10],@x[10],@t[2] + add @x[11],@x[11],@t[3] + + add @x[12],@x[12],@d[0] + add @x[13],@x[13],@d[1] + add @x[14],@x[14],@d[2] + add @x[15],@x[15],@d[3] + addi @d[0],@d[0],1 # increment counter +___ +if (!$LITTLE_ENDIAN) { for($i=0;$i<16;$i++) { # flip byte order +$code.=<<___; + mr @t[$i&3],@x[$i] + rotlwi @x[$i],@x[$i],8 + rlwimi @x[$i],@t[$i&3],24,0,7 + rlwimi @x[$i],@t[$i&3],24,16,23 +___ +} } +$code.=<<___; + bne Ltail # $len-=64 borrowed + + lwz @t[0],0($inp) # load input, aligned or not + lwz @t[1],4($inp) + ${UCMP}i $len,0 # done already? + lwz @t[2],8($inp) + lwz @t[3],12($inp) + xor @x[0],@x[0],@t[0] # xor with input + lwz @t[0],16($inp) + xor @x[1],@x[1],@t[1] + lwz @t[1],20($inp) + xor @x[2],@x[2],@t[2] + lwz @t[2],24($inp) + xor @x[3],@x[3],@t[3] + lwz @t[3],28($inp) + xor @x[4],@x[4],@t[0] + lwz @t[0],32($inp) + xor @x[5],@x[5],@t[1] + lwz @t[1],36($inp) + xor @x[6],@x[6],@t[2] + lwz @t[2],40($inp) + xor @x[7],@x[7],@t[3] + lwz @t[3],44($inp) + xor @x[8],@x[8],@t[0] + lwz @t[0],48($inp) + xor @x[9],@x[9],@t[1] + lwz @t[1],52($inp) + xor @x[10],@x[10],@t[2] + lwz @t[2],56($inp) + xor @x[11],@x[11],@t[3] + lwz @t[3],60($inp) + xor @x[12],@x[12],@t[0] + stw @x[0],0($out) # store output, aligned or not + xor @x[13],@x[13],@t[1] + stw @x[1],4($out) + xor @x[14],@x[14],@t[2] + stw @x[2],8($out) + xor @x[15],@x[15],@t[3] + stw @x[3],12($out) + stw @x[4],16($out) + stw @x[5],20($out) + stw @x[6],24($out) + stw @x[7],28($out) + stw @x[8],32($out) + stw @x[9],36($out) + stw @x[10],40($out) + stw @x[11],44($out) + stw @x[12],48($out) + stw @x[13],52($out) + stw @x[14],56($out) + addi $inp,$inp,64 + stw @x[15],60($out) + addi $out,$out,64 + + bne Loop_outer + + blr + +.align 4 +Ltail: + addi $len,$len,64 # restore tail length + subi $inp,$inp,1 # prepare for *++ptr + subi $out,$out,1 + addi @t[0],$sp,$LOCALS-1 + mtctr $len + + stw @x[0],`$LOCALS+0`($sp) # save whole block to stack + stw @x[1],`$LOCALS+4`($sp) + stw @x[2],`$LOCALS+8`($sp) + stw @x[3],`$LOCALS+12`($sp) + stw @x[4],`$LOCALS+16`($sp) + stw @x[5],`$LOCALS+20`($sp) + stw @x[6],`$LOCALS+24`($sp) + stw @x[7],`$LOCALS+28`($sp) + stw @x[8],`$LOCALS+32`($sp) + stw @x[9],`$LOCALS+36`($sp) + stw @x[10],`$LOCALS+40`($sp) + stw @x[11],`$LOCALS+44`($sp) + stw @x[12],`$LOCALS+48`($sp) + stw @x[13],`$LOCALS+52`($sp) + stw @x[14],`$LOCALS+56`($sp) + stw @x[15],`$LOCALS+60`($sp) + +Loop_tail: # byte-by-byte loop + lbzu @d[0],1($inp) + lbzu @x[0],1(@t[0]) + xor @d[1],@d[0],@x[0] + stbu @d[1],1($out) + bdnz Loop_tail + + stw $sp,`$LOCALS+0`($sp) # wipe block on stack + stw $sp,`$LOCALS+4`($sp) + stw $sp,`$LOCALS+8`($sp) + stw $sp,`$LOCALS+12`($sp) + stw $sp,`$LOCALS+16`($sp) + stw $sp,`$LOCALS+20`($sp) + stw $sp,`$LOCALS+24`($sp) + stw $sp,`$LOCALS+28`($sp) + stw $sp,`$LOCALS+32`($sp) + stw $sp,`$LOCALS+36`($sp) + stw $sp,`$LOCALS+40`($sp) + stw $sp,`$LOCALS+44`($sp) + stw $sp,`$LOCALS+48`($sp) + stw $sp,`$LOCALS+52`($sp) + stw $sp,`$LOCALS+56`($sp) + stw $sp,`$LOCALS+60`($sp) + + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 +___ + +{{{ +my ($A0,$B0,$C0,$D0,$A1,$B1,$C1,$D1,$A2,$B2,$C2,$D2) + = map("v$_",(0..11)); +my @K = map("v$_",(12..17)); +my ($FOUR,$sixteen,$twenty4) = map("v$_",(18..19,23)); +my ($inpperm,$outperm,$outmask) = map("v$_",(24..26)); +my @D = map("v$_",(27..31)); +my ($twelve,$seven,$T0,$T1) = @D; + +my $FRAME=$LOCALS+64+10*16+18*$SIZE_T; # 10*16 is for v23-v31 offload + +sub VMXROUND { +my $odd = pop; +my ($a,$b,$c,$d)=@_; + + ( + "&vadduwm ('$a','$a','$b')", + "&vxor ('$d','$d','$a')", + "&vperm ('$d','$d','$d','$sixteen')", + + "&vadduwm ('$c','$c','$d')", + "&vxor ('$b','$b','$c')", + "&vrlw ('$b','$b','$twelve')", + + "&vadduwm ('$a','$a','$b')", + "&vxor ('$d','$d','$a')", + "&vperm ('$d','$d','$d','$twenty4')", + + "&vadduwm ('$c','$c','$d')", + "&vxor ('$b','$b','$c')", + "&vrlw ('$b','$b','$seven')", + + "&vrldoi ('$c','$c',8)", + "&vrldoi ('$b','$b',$odd?4:12)", + "&vrldoi ('$d','$d',$odd?12:4)" + ); +} + +$code.=<<___; + +.globl .ChaCha20_ctr32_vmx +.align 5 +.ChaCha20_ctr32_vmx: + ${UCMP}i $len,256 + blt __ChaCha20_ctr32_int + + $STU $sp,-$FRAME($sp) + mflr r0 + li r10,`15+$LOCALS+64` + li r11,`31+$LOCALS+64` + mfspr r12,256 + stvx v23,r10,$sp + addi r10,r10,32 + stvx v24,r11,$sp + addi r11,r11,32 + stvx v25,r10,$sp + addi r10,r10,32 + stvx v26,r11,$sp + addi r11,r11,32 + stvx v27,r10,$sp + addi r10,r10,32 + stvx v28,r11,$sp + addi r11,r11,32 + stvx v29,r10,$sp + addi r10,r10,32 + stvx v30,r11,$sp + stvx v31,r10,$sp + stw r12,`$FRAME-$SIZE_T*18-4`($sp) # save vrsave + $PUSH r14,`$FRAME-$SIZE_T*18`($sp) + $PUSH r15,`$FRAME-$SIZE_T*17`($sp) + $PUSH r16,`$FRAME-$SIZE_T*16`($sp) + $PUSH r17,`$FRAME-$SIZE_T*15`($sp) + $PUSH r18,`$FRAME-$SIZE_T*14`($sp) + $PUSH r19,`$FRAME-$SIZE_T*13`($sp) + $PUSH r20,`$FRAME-$SIZE_T*12`($sp) + $PUSH r21,`$FRAME-$SIZE_T*11`($sp) + $PUSH r22,`$FRAME-$SIZE_T*10`($sp) + $PUSH r23,`$FRAME-$SIZE_T*9`($sp) + $PUSH r24,`$FRAME-$SIZE_T*8`($sp) + $PUSH r25,`$FRAME-$SIZE_T*7`($sp) + $PUSH r26,`$FRAME-$SIZE_T*6`($sp) + $PUSH r27,`$FRAME-$SIZE_T*5`($sp) + $PUSH r28,`$FRAME-$SIZE_T*4`($sp) + $PUSH r29,`$FRAME-$SIZE_T*3`($sp) + $PUSH r30,`$FRAME-$SIZE_T*2`($sp) + $PUSH r31,`$FRAME-$SIZE_T*1`($sp) + li r12,-4096+511 + $PUSH r0, `$FRAME+$LRSAVE`($sp) + mtspr 256,r12 # preserve 29 AltiVec registers + + bl Lconsts # returns pointer Lsigma in r12 + li @x[0],16 + li @x[1],32 + li @x[2],48 + li @x[3],64 + li @x[4],31 # 31 is not a typo + li @x[5],15 # nor is 15 + + lvx @K[1],0,$key # load key + ?lvsr $T0,0,$key # prepare unaligned load + lvx @K[2],@x[0],$key + lvx @D[0],@x[4],$key + + lvx @K[3],0,$ctr # load counter + ?lvsr $T1,0,$ctr # prepare unaligned load + lvx @D[1],@x[5],$ctr + + lvx @K[0],0,r12 # load constants + lvx @K[5],@x[0],r12 # one + lvx $FOUR,@x[1],r12 + lvx $sixteen,@x[2],r12 + lvx $twenty4,@x[3],r12 + + ?vperm @K[1],@K[2],@K[1],$T0 # align key + ?vperm @K[2],@D[0],@K[2],$T0 + ?vperm @K[3],@D[1],@K[3],$T1 # align counter + + lwz @d[0],0($ctr) # load counter to GPR + lwz @d[1],4($ctr) + vadduwm @K[3],@K[3],@K[5] # adjust AltiVec counter + lwz @d[2],8($ctr) + vadduwm @K[4],@K[3],@K[5] + lwz @d[3],12($ctr) + vadduwm @K[5],@K[4],@K[5] + + vxor $T0,$T0,$T0 # 0x00..00 + vspltisw $outmask,-1 # 0xff..ff + ?lvsr $inpperm,0,$inp # prepare for unaligned load + ?lvsl $outperm,0,$out # prepare for unaligned store + ?vperm $outmask,$outmask,$T0,$outperm + + be?lvsl $T0,0,@x[0] # 0x00..0f + be?vspltisb $T1,3 # 0x03..03 + be?vxor $T0,$T0,$T1 # swap bytes within words + be?vxor $outperm,$outperm,$T1 + be?vperm $inpperm,$inpperm,$inpperm,$T0 + + li r0,10 # inner loop counter + b Loop_outer_vmx + +.align 4 +Loop_outer_vmx: + lis @x[0],0x6170 # synthesize sigma + lis @x[1],0x3320 + vmr $A0,@K[0] + lis @x[2],0x7962 + lis @x[3],0x6b20 + vmr $A1,@K[0] + ori @x[0],@x[0],0x7865 + ori @x[1],@x[1],0x646e + vmr $A2,@K[0] + ori @x[2],@x[2],0x2d32 + ori @x[3],@x[3],0x6574 + vmr $B0,@K[1] + + lwz @x[4],0($key) # load key to GPR + vmr $B1,@K[1] + lwz @x[5],4($key) + vmr $B2,@K[1] + lwz @x[6],8($key) + vmr $C0,@K[2] + lwz @x[7],12($key) + vmr $C1,@K[2] + lwz @x[8],16($key) + vmr $C2,@K[2] + mr @x[12],@d[0] # copy GPR counter + lwz @x[9],20($key) + vmr $D0,@K[3] + mr @x[13],@d[1] + lwz @x[10],24($key) + vmr $D1,@K[4] + mr @x[14],@d[2] + lwz @x[11],28($key) + vmr $D2,@K[5] + mr @x[15],@d[3] + + mr @t[0],@x[4] + mr @t[1],@x[5] + mr @t[2],@x[6] + mr @t[3],@x[7] + + vspltisw $twelve,12 # synthesize constants + vspltisw $seven,7 + + mtctr r0 + nop +Loop_vmx: +___ + my @thread0=&VMXROUND($A0,$B0,$C0,$D0,0); + my @thread1=&VMXROUND($A1,$B1,$C1,$D1,0); + my @thread2=&VMXROUND($A2,$B2,$C2,$D2,0); + my @thread3=&ROUND(0,4,8,12); + + foreach (@thread0) { + eval; + eval(shift(@thread1)); + eval(shift(@thread2)); + + eval(shift(@thread3)); + eval(shift(@thread3)); + eval(shift(@thread3)); + } + foreach (@thread3) { eval; } + + @thread0=&VMXROUND($A0,$B0,$C0,$D0,1); + @thread1=&VMXROUND($A1,$B1,$C1,$D1,1); + @thread2=&VMXROUND($A2,$B2,$C2,$D2,1); + @thread3=&ROUND(0,5,10,15); + + foreach (@thread0) { + eval; + eval(shift(@thread1)); + eval(shift(@thread2)); + + eval(shift(@thread3)); + eval(shift(@thread3)); + eval(shift(@thread3)); + } + foreach (@thread3) { eval; } +$code.=<<___; + bdnz Loop_vmx + + subi $len,$len,256 # $len-=256 + addi @x[0],@x[0],0x7865 # accumulate key block + addi @x[1],@x[1],0x646e + addi @x[2],@x[2],0x2d32 + addi @x[3],@x[3],0x6574 + addis @x[0],@x[0],0x6170 + addis @x[1],@x[1],0x3320 + addis @x[2],@x[2],0x7962 + addis @x[3],@x[3],0x6b20 + add @x[4],@x[4],@t[0] + lwz @t[0],16($key) + add @x[5],@x[5],@t[1] + lwz @t[1],20($key) + add @x[6],@x[6],@t[2] + lwz @t[2],24($key) + add @x[7],@x[7],@t[3] + lwz @t[3],28($key) + add @x[8],@x[8],@t[0] + add @x[9],@x[9],@t[1] + add @x[10],@x[10],@t[2] + add @x[11],@x[11],@t[3] + add @x[12],@x[12],@d[0] + add @x[13],@x[13],@d[1] + add @x[14],@x[14],@d[2] + add @x[15],@x[15],@d[3] + + vadduwm $A0,$A0,@K[0] # accumulate key block + vadduwm $A1,$A1,@K[0] + vadduwm $A2,$A2,@K[0] + vadduwm $B0,$B0,@K[1] + vadduwm $B1,$B1,@K[1] + vadduwm $B2,$B2,@K[1] + vadduwm $C0,$C0,@K[2] + vadduwm $C1,$C1,@K[2] + vadduwm $C2,$C2,@K[2] + vadduwm $D0,$D0,@K[3] + vadduwm $D1,$D1,@K[4] + vadduwm $D2,$D2,@K[5] + + addi @d[0],@d[0],4 # increment counter + vadduwm @K[3],@K[3],$FOUR + vadduwm @K[4],@K[4],$FOUR + vadduwm @K[5],@K[5],$FOUR + +___ +if (!$LITTLE_ENDIAN) { for($i=0;$i<16;$i++) { # flip byte order +$code.=<<___; + mr @t[$i&3],@x[$i] + rotlwi @x[$i],@x[$i],8 + rlwimi @x[$i],@t[$i&3],24,0,7 + rlwimi @x[$i],@t[$i&3],24,16,23 +___ +} } +$code.=<<___; + lwz @t[0],0($inp) # load input, aligned or not + lwz @t[1],4($inp) + lwz @t[2],8($inp) + lwz @t[3],12($inp) + xor @x[0],@x[0],@t[0] # xor with input + lwz @t[0],16($inp) + xor @x[1],@x[1],@t[1] + lwz @t[1],20($inp) + xor @x[2],@x[2],@t[2] + lwz @t[2],24($inp) + xor @x[3],@x[3],@t[3] + lwz @t[3],28($inp) + xor @x[4],@x[4],@t[0] + lwz @t[0],32($inp) + xor @x[5],@x[5],@t[1] + lwz @t[1],36($inp) + xor @x[6],@x[6],@t[2] + lwz @t[2],40($inp) + xor @x[7],@x[7],@t[3] + lwz @t[3],44($inp) + xor @x[8],@x[8],@t[0] + lwz @t[0],48($inp) + xor @x[9],@x[9],@t[1] + lwz @t[1],52($inp) + xor @x[10],@x[10],@t[2] + lwz @t[2],56($inp) + xor @x[11],@x[11],@t[3] + lwz @t[3],60($inp) + xor @x[12],@x[12],@t[0] + stw @x[0],0($out) # store output, aligned or not + xor @x[13],@x[13],@t[1] + stw @x[1],4($out) + xor @x[14],@x[14],@t[2] + stw @x[2],8($out) + xor @x[15],@x[15],@t[3] + stw @x[3],12($out) + addi $inp,$inp,64 + stw @x[4],16($out) + li @t[0],16 + stw @x[5],20($out) + li @t[1],32 + stw @x[6],24($out) + li @t[2],48 + stw @x[7],28($out) + li @t[3],64 + stw @x[8],32($out) + stw @x[9],36($out) + stw @x[10],40($out) + stw @x[11],44($out) + stw @x[12],48($out) + stw @x[13],52($out) + stw @x[14],56($out) + stw @x[15],60($out) + addi $out,$out,64 + + lvx @D[0],0,$inp # load input + lvx @D[1],@t[0],$inp + lvx @D[2],@t[1],$inp + lvx @D[3],@t[2],$inp + lvx @D[4],@t[3],$inp + addi $inp,$inp,64 + + ?vperm @D[0],@D[1],@D[0],$inpperm # align input + ?vperm @D[1],@D[2],@D[1],$inpperm + ?vperm @D[2],@D[3],@D[2],$inpperm + ?vperm @D[3],@D[4],@D[3],$inpperm + vxor $A0,$A0,@D[0] # xor with input + vxor $B0,$B0,@D[1] + lvx @D[1],@t[0],$inp # keep loading input + vxor $C0,$C0,@D[2] + lvx @D[2],@t[1],$inp + vxor $D0,$D0,@D[3] + lvx @D[3],@t[2],$inp + lvx @D[0],@t[3],$inp + addi $inp,$inp,64 + li @t[3],63 # 63 is not a typo + vperm $A0,$A0,$A0,$outperm # pre-misalign output + vperm $B0,$B0,$B0,$outperm + vperm $C0,$C0,$C0,$outperm + vperm $D0,$D0,$D0,$outperm + + ?vperm @D[4],@D[1],@D[4],$inpperm # align input + ?vperm @D[1],@D[2],@D[1],$inpperm + ?vperm @D[2],@D[3],@D[2],$inpperm + ?vperm @D[3],@D[0],@D[3],$inpperm + vxor $A1,$A1,@D[4] + vxor $B1,$B1,@D[1] + lvx @D[1],@t[0],$inp # keep loading input + vxor $C1,$C1,@D[2] + lvx @D[2],@t[1],$inp + vxor $D1,$D1,@D[3] + lvx @D[3],@t[2],$inp + lvx @D[4],@t[3],$inp # redundant in aligned case + addi $inp,$inp,64 + vperm $A1,$A1,$A1,$outperm # pre-misalign output + vperm $B1,$B1,$B1,$outperm + vperm $C1,$C1,$C1,$outperm + vperm $D1,$D1,$D1,$outperm + + ?vperm @D[0],@D[1],@D[0],$inpperm # align input + ?vperm @D[1],@D[2],@D[1],$inpperm + ?vperm @D[2],@D[3],@D[2],$inpperm + ?vperm @D[3],@D[4],@D[3],$inpperm + vxor $A2,$A2,@D[0] + vxor $B2,$B2,@D[1] + vxor $C2,$C2,@D[2] + vxor $D2,$D2,@D[3] + vperm $A2,$A2,$A2,$outperm # pre-misalign output + vperm $B2,$B2,$B2,$outperm + vperm $C2,$C2,$C2,$outperm + vperm $D2,$D2,$D2,$outperm + + andi. @x[1],$out,15 # is $out aligned? + mr @x[0],$out + + vsel @D[0],$A0,$B0,$outmask # collect pre-misaligned output + vsel @D[1],$B0,$C0,$outmask + vsel @D[2],$C0,$D0,$outmask + vsel @D[3],$D0,$A1,$outmask + vsel $B0,$A1,$B1,$outmask + vsel $C0,$B1,$C1,$outmask + vsel $D0,$C1,$D1,$outmask + vsel $A1,$D1,$A2,$outmask + vsel $B1,$A2,$B2,$outmask + vsel $C1,$B2,$C2,$outmask + vsel $D1,$C2,$D2,$outmask + + #stvx $A0,0,$out # take it easy on the edges + stvx @D[0],@t[0],$out # store output + stvx @D[1],@t[1],$out + stvx @D[2],@t[2],$out + addi $out,$out,64 + stvx @D[3],0,$out + stvx $B0,@t[0],$out + stvx $C0,@t[1],$out + stvx $D0,@t[2],$out + addi $out,$out,64 + stvx $A1,0,$out + stvx $B1,@t[0],$out + stvx $C1,@t[1],$out + stvx $D1,@t[2],$out + addi $out,$out,64 + + beq Laligned_vmx + + sub @x[2],$out,@x[1] # in misaligned case edges + li @x[3],0 # are written byte-by-byte +Lunaligned_tail_vmx: + stvebx $D2,@x[3],@x[2] + addi @x[3],@x[3],1 + cmpw @x[3],@x[1] + bne Lunaligned_tail_vmx + + sub @x[2],@x[0],@x[1] +Lunaligned_head_vmx: + stvebx $A0,@x[1],@x[2] + cmpwi @x[1],15 + addi @x[1],@x[1],1 + bne Lunaligned_head_vmx + + ${UCMP}i $len,255 # done with 256-byte blocks yet? + bgt Loop_outer_vmx + + b Ldone_vmx + +.align 4 +Laligned_vmx: + stvx $A0,0,@x[0] # head hexaword was not stored + + ${UCMP}i $len,255 # done with 256-byte blocks yet? + bgt Loop_outer_vmx + nop + +Ldone_vmx: + ${UCMP}i $len,0 # done yet? + bnel __ChaCha20_1x + + lwz r12,`$FRAME-$SIZE_T*18-4`($sp) # pull vrsave + li r10,`15+$LOCALS+64` + li r11,`31+$LOCALS+64` + mtspr 256,r12 # restore vrsave + lvx v23,r10,$sp + addi r10,r10,32 + lvx v24,r11,$sp + addi r11,r11,32 + lvx v25,r10,$sp + addi r10,r10,32 + lvx v26,r11,$sp + addi r11,r11,32 + lvx v27,r10,$sp + addi r10,r10,32 + lvx v28,r11,$sp + addi r11,r11,32 + lvx v29,r10,$sp + addi r10,r10,32 + lvx v30,r11,$sp + lvx v31,r10,$sp + $POP r0, `$FRAME+$LRSAVE`($sp) + $POP r14,`$FRAME-$SIZE_T*18`($sp) + $POP r15,`$FRAME-$SIZE_T*17`($sp) + $POP r16,`$FRAME-$SIZE_T*16`($sp) + $POP r17,`$FRAME-$SIZE_T*15`($sp) + $POP r18,`$FRAME-$SIZE_T*14`($sp) + $POP r19,`$FRAME-$SIZE_T*13`($sp) + $POP r20,`$FRAME-$SIZE_T*12`($sp) + $POP r21,`$FRAME-$SIZE_T*11`($sp) + $POP r22,`$FRAME-$SIZE_T*10`($sp) + $POP r23,`$FRAME-$SIZE_T*9`($sp) + $POP r24,`$FRAME-$SIZE_T*8`($sp) + $POP r25,`$FRAME-$SIZE_T*7`($sp) + $POP r26,`$FRAME-$SIZE_T*6`($sp) + $POP r27,`$FRAME-$SIZE_T*5`($sp) + $POP r28,`$FRAME-$SIZE_T*4`($sp) + $POP r29,`$FRAME-$SIZE_T*3`($sp) + $POP r30,`$FRAME-$SIZE_T*2`($sp) + $POP r31,`$FRAME-$SIZE_T*1`($sp) + mtlr r0 + addi $sp,$sp,$FRAME + blr + .long 0 + .byte 0,12,0x04,1,0x80,18,5,0 + .long 0 +.size .ChaCha20_ctr32_vmx,.-.ChaCha20_ctr32_vmx +___ +}}} +{{{ +my ($xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3, + $xc0,$xc1,$xc2,$xc3, $xd0,$xd1,$xd2,$xd3) = map("v$_",(0..15)); +my @K = map("v$_",(16..19)); +my $CTR = "v26"; +my ($xt0,$xt1,$xt2,$xt3) = map("v$_",(27..30)); +my ($sixteen,$twelve,$eight,$seven) = ($xt0,$xt1,$xt2,$xt3); +my $beperm = "v31"; + +my ($x00,$x10,$x20,$x30) = (0, map("r$_",(8..10))); + +my $FRAME=$LOCALS+64+7*16; # 7*16 is for v26-v31 offload + +sub VSX_lane_ROUND { +my ($a0,$b0,$c0,$d0)=@_; +my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0)); +my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1)); +my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2)); +my @x=map("\"v$_\"",(0..15)); + + ( + "&vadduwm (@x[$a0],@x[$a0],@x[$b0])", # Q1 + "&vadduwm (@x[$a1],@x[$a1],@x[$b1])", # Q2 + "&vadduwm (@x[$a2],@x[$a2],@x[$b2])", # Q3 + "&vadduwm (@x[$a3],@x[$a3],@x[$b3])", # Q4 + "&vxor (@x[$d0],@x[$d0],@x[$a0])", + "&vxor (@x[$d1],@x[$d1],@x[$a1])", + "&vxor (@x[$d2],@x[$d2],@x[$a2])", + "&vxor (@x[$d3],@x[$d3],@x[$a3])", + "&vrlw (@x[$d0],@x[$d0],'$sixteen')", + "&vrlw (@x[$d1],@x[$d1],'$sixteen')", + "&vrlw (@x[$d2],@x[$d2],'$sixteen')", + "&vrlw (@x[$d3],@x[$d3],'$sixteen')", + + "&vadduwm (@x[$c0],@x[$c0],@x[$d0])", + "&vadduwm (@x[$c1],@x[$c1],@x[$d1])", + "&vadduwm (@x[$c2],@x[$c2],@x[$d2])", + "&vadduwm (@x[$c3],@x[$c3],@x[$d3])", + "&vxor (@x[$b0],@x[$b0],@x[$c0])", + "&vxor (@x[$b1],@x[$b1],@x[$c1])", + "&vxor (@x[$b2],@x[$b2],@x[$c2])", + "&vxor (@x[$b3],@x[$b3],@x[$c3])", + "&vrlw (@x[$b0],@x[$b0],'$twelve')", + "&vrlw (@x[$b1],@x[$b1],'$twelve')", + "&vrlw (@x[$b2],@x[$b2],'$twelve')", + "&vrlw (@x[$b3],@x[$b3],'$twelve')", + + "&vadduwm (@x[$a0],@x[$a0],@x[$b0])", + "&vadduwm (@x[$a1],@x[$a1],@x[$b1])", + "&vadduwm (@x[$a2],@x[$a2],@x[$b2])", + "&vadduwm (@x[$a3],@x[$a3],@x[$b3])", + "&vxor (@x[$d0],@x[$d0],@x[$a0])", + "&vxor (@x[$d1],@x[$d1],@x[$a1])", + "&vxor (@x[$d2],@x[$d2],@x[$a2])", + "&vxor (@x[$d3],@x[$d3],@x[$a3])", + "&vrlw (@x[$d0],@x[$d0],'$eight')", + "&vrlw (@x[$d1],@x[$d1],'$eight')", + "&vrlw (@x[$d2],@x[$d2],'$eight')", + "&vrlw (@x[$d3],@x[$d3],'$eight')", + + "&vadduwm (@x[$c0],@x[$c0],@x[$d0])", + "&vadduwm (@x[$c1],@x[$c1],@x[$d1])", + "&vadduwm (@x[$c2],@x[$c2],@x[$d2])", + "&vadduwm (@x[$c3],@x[$c3],@x[$d3])", + "&vxor (@x[$b0],@x[$b0],@x[$c0])", + "&vxor (@x[$b1],@x[$b1],@x[$c1])", + "&vxor (@x[$b2],@x[$b2],@x[$c2])", + "&vxor (@x[$b3],@x[$b3],@x[$c3])", + "&vrlw (@x[$b0],@x[$b0],'$seven')", + "&vrlw (@x[$b1],@x[$b1],'$seven')", + "&vrlw (@x[$b2],@x[$b2],'$seven')", + "&vrlw (@x[$b3],@x[$b3],'$seven')" + ); +} + +$code.=<<___; + +.globl .ChaCha20_ctr32_vsx +.align 5 +.ChaCha20_ctr32_vsx: + $STU $sp,-$FRAME($sp) + mflr r0 + li r10,`15+$LOCALS+64` + li r11,`31+$LOCALS+64` + mfspr r12,256 + stvx v26,r10,$sp + addi r10,r10,32 + stvx v27,r11,$sp + addi r11,r11,32 + stvx v28,r10,$sp + addi r10,r10,32 + stvx v29,r11,$sp + addi r11,r11,32 + stvx v30,r10,$sp + stvx v31,r11,$sp + stw r12,`$FRAME-4`($sp) # save vrsave + li r12,-4096+63 + $PUSH r0, `$FRAME+$LRSAVE`($sp) + mtspr 256,r12 # preserve 29 AltiVec registers + + bl Lconsts # returns pointer Lsigma in r12 + lvx_4w @K[0],0,r12 # load sigma + addi r12,r12,0x50 + li $x10,16 + li $x20,32 + li $x30,48 + li r11,64 + + lvx_4w @K[1],0,$key # load key + lvx_4w @K[2],$x10,$key + lvx_4w @K[3],0,$ctr # load counter + + vxor $xt0,$xt0,$xt0 + lvx_4w $xt1,r11,r12 + vspltw $CTR,@K[3],0 + vsldoi @K[3],@K[3],$xt0,4 + vsldoi @K[3],$xt0,@K[3],12 # clear @K[3].word[0] + vadduwm $CTR,$CTR,$xt1 + + be?lvsl $beperm,0,$x10 # 0x00..0f + be?vspltisb $xt0,3 # 0x03..03 + be?vxor $beperm,$beperm,$xt0 # swap bytes within words + + li r0,10 # inner loop counter + mtctr r0 + b Loop_outer_vsx + +.align 5 +Loop_outer_vsx: + lvx $xa0,$x00,r12 # load [smashed] sigma + lvx $xa1,$x10,r12 + lvx $xa2,$x20,r12 + lvx $xa3,$x30,r12 + + vspltw $xb0,@K[1],0 # smash the key + vspltw $xb1,@K[1],1 + vspltw $xb2,@K[1],2 + vspltw $xb3,@K[1],3 + + vspltw $xc0,@K[2],0 + vspltw $xc1,@K[2],1 + vspltw $xc2,@K[2],2 + vspltw $xc3,@K[2],3 + + vmr $xd0,$CTR # smash the counter + vspltw $xd1,@K[3],1 + vspltw $xd2,@K[3],2 + vspltw $xd3,@K[3],3 + + vspltisw $sixteen,-16 # synthesize constants + vspltisw $twelve,12 + vspltisw $eight,8 + vspltisw $seven,7 + +Loop_vsx: +___ + foreach (&VSX_lane_ROUND(0, 4, 8,12)) { eval; } + foreach (&VSX_lane_ROUND(0, 5,10,15)) { eval; } +$code.=<<___; + bdnz Loop_vsx + + vadduwm $xd0,$xd0,$CTR + + vmrgew $xt0,$xa0,$xa1 # transpose data + vmrgew $xt1,$xa2,$xa3 + vmrgow $xa0,$xa0,$xa1 + vmrgow $xa2,$xa2,$xa3 + vmrgew $xt2,$xb0,$xb1 + vmrgew $xt3,$xb2,$xb3 + vpermdi $xa1,$xa0,$xa2,0b00 + vpermdi $xa3,$xa0,$xa2,0b11 + vpermdi $xa0,$xt0,$xt1,0b00 + vpermdi $xa2,$xt0,$xt1,0b11 + + vmrgow $xb0,$xb0,$xb1 + vmrgow $xb2,$xb2,$xb3 + vmrgew $xt0,$xc0,$xc1 + vmrgew $xt1,$xc2,$xc3 + vpermdi $xb1,$xb0,$xb2,0b00 + vpermdi $xb3,$xb0,$xb2,0b11 + vpermdi $xb0,$xt2,$xt3,0b00 + vpermdi $xb2,$xt2,$xt3,0b11 + + vmrgow $xc0,$xc0,$xc1 + vmrgow $xc2,$xc2,$xc3 + vmrgew $xt2,$xd0,$xd1 + vmrgew $xt3,$xd2,$xd3 + vpermdi $xc1,$xc0,$xc2,0b00 + vpermdi $xc3,$xc0,$xc2,0b11 + vpermdi $xc0,$xt0,$xt1,0b00 + vpermdi $xc2,$xt0,$xt1,0b11 + + vmrgow $xd0,$xd0,$xd1 + vmrgow $xd2,$xd2,$xd3 + vspltisw $xt0,4 + vadduwm $CTR,$CTR,$xt0 # next counter value + vpermdi $xd1,$xd0,$xd2,0b00 + vpermdi $xd3,$xd0,$xd2,0b11 + vpermdi $xd0,$xt2,$xt3,0b00 + vpermdi $xd2,$xt2,$xt3,0b11 + + vadduwm $xa0,$xa0,@K[0] + vadduwm $xb0,$xb0,@K[1] + vadduwm $xc0,$xc0,@K[2] + vadduwm $xd0,$xd0,@K[3] + + be?vperm $xa0,$xa0,$xa0,$beperm + be?vperm $xb0,$xb0,$xb0,$beperm + be?vperm $xc0,$xc0,$xc0,$beperm + be?vperm $xd0,$xd0,$xd0,$beperm + + ${UCMP}i $len,0x40 + blt Ltail_vsx + + lvx_4w $xt0,$x00,$inp + lvx_4w $xt1,$x10,$inp + lvx_4w $xt2,$x20,$inp + lvx_4w $xt3,$x30,$inp + + vxor $xt0,$xt0,$xa0 + vxor $xt1,$xt1,$xb0 + vxor $xt2,$xt2,$xc0 + vxor $xt3,$xt3,$xd0 + + stvx_4w $xt0,$x00,$out + stvx_4w $xt1,$x10,$out + addi $inp,$inp,0x40 + stvx_4w $xt2,$x20,$out + subi $len,$len,0x40 + stvx_4w $xt3,$x30,$out + addi $out,$out,0x40 + beq Ldone_vsx + + vadduwm $xa0,$xa1,@K[0] + vadduwm $xb0,$xb1,@K[1] + vadduwm $xc0,$xc1,@K[2] + vadduwm $xd0,$xd1,@K[3] + + be?vperm $xa0,$xa0,$xa0,$beperm + be?vperm $xb0,$xb0,$xb0,$beperm + be?vperm $xc0,$xc0,$xc0,$beperm + be?vperm $xd0,$xd0,$xd0,$beperm + + ${UCMP}i $len,0x40 + blt Ltail_vsx + + lvx_4w $xt0,$x00,$inp + lvx_4w $xt1,$x10,$inp + lvx_4w $xt2,$x20,$inp + lvx_4w $xt3,$x30,$inp + + vxor $xt0,$xt0,$xa0 + vxor $xt1,$xt1,$xb0 + vxor $xt2,$xt2,$xc0 + vxor $xt3,$xt3,$xd0 + + stvx_4w $xt0,$x00,$out + stvx_4w $xt1,$x10,$out + addi $inp,$inp,0x40 + stvx_4w $xt2,$x20,$out + subi $len,$len,0x40 + stvx_4w $xt3,$x30,$out + addi $out,$out,0x40 + beq Ldone_vsx + + vadduwm $xa0,$xa2,@K[0] + vadduwm $xb0,$xb2,@K[1] + vadduwm $xc0,$xc2,@K[2] + vadduwm $xd0,$xd2,@K[3] + + be?vperm $xa0,$xa0,$xa0,$beperm + be?vperm $xb0,$xb0,$xb0,$beperm + be?vperm $xc0,$xc0,$xc0,$beperm + be?vperm $xd0,$xd0,$xd0,$beperm + + ${UCMP}i $len,0x40 + blt Ltail_vsx + + lvx_4w $xt0,$x00,$inp + lvx_4w $xt1,$x10,$inp + lvx_4w $xt2,$x20,$inp + lvx_4w $xt3,$x30,$inp + + vxor $xt0,$xt0,$xa0 + vxor $xt1,$xt1,$xb0 + vxor $xt2,$xt2,$xc0 + vxor $xt3,$xt3,$xd0 + + stvx_4w $xt0,$x00,$out + stvx_4w $xt1,$x10,$out + addi $inp,$inp,0x40 + stvx_4w $xt2,$x20,$out + subi $len,$len,0x40 + stvx_4w $xt3,$x30,$out + addi $out,$out,0x40 + beq Ldone_vsx + + vadduwm $xa0,$xa3,@K[0] + vadduwm $xb0,$xb3,@K[1] + vadduwm $xc0,$xc3,@K[2] + vadduwm $xd0,$xd3,@K[3] + + be?vperm $xa0,$xa0,$xa0,$beperm + be?vperm $xb0,$xb0,$xb0,$beperm + be?vperm $xc0,$xc0,$xc0,$beperm + be?vperm $xd0,$xd0,$xd0,$beperm + + ${UCMP}i $len,0x40 + blt Ltail_vsx + + lvx_4w $xt0,$x00,$inp + lvx_4w $xt1,$x10,$inp + lvx_4w $xt2,$x20,$inp + lvx_4w $xt3,$x30,$inp + + vxor $xt0,$xt0,$xa0 + vxor $xt1,$xt1,$xb0 + vxor $xt2,$xt2,$xc0 + vxor $xt3,$xt3,$xd0 + + stvx_4w $xt0,$x00,$out + stvx_4w $xt1,$x10,$out + addi $inp,$inp,0x40 + stvx_4w $xt2,$x20,$out + subi $len,$len,0x40 + stvx_4w $xt3,$x30,$out + addi $out,$out,0x40 + mtctr r0 + bne Loop_outer_vsx + +Ldone_vsx: + lwz r12,`$FRAME-4`($sp) # pull vrsave + li r10,`15+$LOCALS+64` + li r11,`31+$LOCALS+64` + $POP r0, `$FRAME+$LRSAVE`($sp) + mtspr 256,r12 # restore vrsave + lvx v26,r10,$sp + addi r10,r10,32 + lvx v27,r11,$sp + addi r11,r11,32 + lvx v28,r10,$sp + addi r10,r10,32 + lvx v29,r11,$sp + addi r11,r11,32 + lvx v30,r10,$sp + lvx v31,r11,$sp + mtlr r0 + addi $sp,$sp,$FRAME + blr + +.align 4 +Ltail_vsx: + addi r11,$sp,$LOCALS + mtctr $len + stvx_4w $xa0,$x00,r11 # offload block to stack + stvx_4w $xb0,$x10,r11 + stvx_4w $xc0,$x20,r11 + stvx_4w $xd0,$x30,r11 + subi r12,r11,1 # prepare for *++ptr + subi $inp,$inp,1 + subi $out,$out,1 + +Loop_tail_vsx: + lbzu r6,1(r12) + lbzu r7,1($inp) + xor r6,r6,r7 + stbu r6,1($out) + bdnz Loop_tail_vsx + + stvx_4w $K[0],$x00,r11 # wipe copy of the block + stvx_4w $K[0],$x10,r11 + stvx_4w $K[0],$x20,r11 + stvx_4w $K[0],$x30,r11 + + b Ldone_vsx + .long 0 + .byte 0,12,0x04,1,0x80,0,5,0 + .long 0 +.size .ChaCha20_ctr32_vsx,.-.ChaCha20_ctr32_vsx +___ +}}} +$code.=<<___; +.align 5 +Lconsts: + mflr r0 + bcl 20,31,\$+4 + mflr r12 #vvvvv "distance between . and Lsigma + addi r12,r12,`64-8` + mtlr r0 + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 + .space `64-9*4` +Lsigma: + .long 0x61707865,0x3320646e,0x79622d32,0x6b206574 + .long 1,0,0,0 + .long 4,0,0,0 +___ +$code.=<<___ if ($LITTLE_ENDIAN); + .long 0x0e0f0c0d,0x0a0b0809,0x06070405,0x02030001 + .long 0x0d0e0f0c,0x090a0b08,0x05060704,0x01020300 +___ +$code.=<<___ if (!$LITTLE_ENDIAN); # flipped words + .long 0x02030001,0x06070405,0x0a0b0809,0x0e0f0c0d + .long 0x01020300,0x05060704,0x090a0b08,0x0d0e0f0c +___ +$code.=<<___; + .long 0x61707865,0x61707865,0x61707865,0x61707865 + .long 0x3320646e,0x3320646e,0x3320646e,0x3320646e + .long 0x79622d32,0x79622d32,0x79622d32,0x79622d32 + .long 0x6b206574,0x6b206574,0x6b206574,0x6b206574 + .long 0,1,2,3 +.asciz "ChaCha20 for PowerPC/AltiVec, CRYPTOGAMS by " +.align 2 +___ + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/ge; + + # instructions prefixed with '?' are endian-specific and need + # to be adjusted accordingly... + if ($flavour !~ /le$/) { # big-endian + s/be\?// or + s/le\?/#le#/ or + s/\?lvsr/lvsl/ or + s/\?lvsl/lvsr/ or + s/\?(vperm\s+v[0-9]+,\s*)(v[0-9]+,\s*)(v[0-9]+,\s*)(v[0-9]+)/$1$3$2$4/ or + s/vrldoi(\s+v[0-9]+,\s*)(v[0-9]+,)\s*([0-9]+)/vsldoi$1$2$2 16-$3/; + } else { # little-endian + s/le\?// or + s/be\?/#be#/ or + s/\?([a-z]+)/$1/ or + s/vrldoi(\s+v[0-9]+,\s*)(v[0-9]+,)\s*([0-9]+)/vsldoi$1$2$2 $3/; + } + + print $_,"\n"; +} + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/chacha/asm/chacha-s390x.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/chacha/asm/chacha-s390x.pl new file mode 100755 index 000000000..c31526473 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/chacha/asm/chacha-s390x.pl @@ -0,0 +1,326 @@ +#! /usr/bin/env perl +# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# December 2015 +# +# ChaCha20 for s390x. +# +# 3 times faster than compiler-generated code. + +$flavour = shift; + +if ($flavour =~ /3[12]/) { + $SIZE_T=4; + $g=""; +} else { + $SIZE_T=8; + $g="g"; +} + +while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} +open STDOUT,">$output"; + +sub AUTOLOAD() # thunk [simplified] x86-style perlasm +{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; + $code .= "\t$opcode\t".join(',',@_)."\n"; +} + +my $sp="%r15"; + +my $stdframe=16*$SIZE_T+4*8; +my $frame=$stdframe+4*20; + +my ($out,$inp,$len,$key,$counter)=map("%r$_",(2..6)); + +my @x=map("%r$_",(0..7,"x","x","x","x",(10..13))); +my @t=map("%r$_",(8,9)); + +sub ROUND { +my ($a0,$b0,$c0,$d0)=@_; +my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0)); +my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1)); +my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2)); +my ($xc,$xc_)=map("\"$_\"",@t); +my @x=map("\"$_\"",@x); + + # Consider order in which variables are addressed by their + # index: + # + # a b c d + # + # 0 4 8 12 < even round + # 1 5 9 13 + # 2 6 10 14 + # 3 7 11 15 + # 0 5 10 15 < odd round + # 1 6 11 12 + # 2 7 8 13 + # 3 4 9 14 + # + # 'a', 'b' and 'd's are permanently allocated in registers, + # @x[0..7,12..15], while 'c's are maintained in memory. If + # you observe 'c' column, you'll notice that pair of 'c's is + # invariant between rounds. This means that we have to reload + # them once per round, in the middle. This is why you'll see + # 'c' stores and loads in the middle, but none in the beginning + # or end. + + ( + "&alr (@x[$a0],@x[$b0])", # Q1 + "&alr (@x[$a1],@x[$b1])", # Q2 + "&xr (@x[$d0],@x[$a0])", + "&xr (@x[$d1],@x[$a1])", + "&rll (@x[$d0],@x[$d0],16)", + "&rll (@x[$d1],@x[$d1],16)", + + "&alr ($xc,@x[$d0])", + "&alr ($xc_,@x[$d1])", + "&xr (@x[$b0],$xc)", + "&xr (@x[$b1],$xc_)", + "&rll (@x[$b0],@x[$b0],12)", + "&rll (@x[$b1],@x[$b1],12)", + + "&alr (@x[$a0],@x[$b0])", + "&alr (@x[$a1],@x[$b1])", + "&xr (@x[$d0],@x[$a0])", + "&xr (@x[$d1],@x[$a1])", + "&rll (@x[$d0],@x[$d0],8)", + "&rll (@x[$d1],@x[$d1],8)", + + "&alr ($xc,@x[$d0])", + "&alr ($xc_,@x[$d1])", + "&xr (@x[$b0],$xc)", + "&xr (@x[$b1],$xc_)", + "&rll (@x[$b0],@x[$b0],7)", + "&rll (@x[$b1],@x[$b1],7)", + + "&stm ($xc,$xc_,'$stdframe+4*8+4*$c0($sp)')", # reload pair of 'c's + "&lm ($xc,$xc_,'$stdframe+4*8+4*$c2($sp)')", + + "&alr (@x[$a2],@x[$b2])", # Q3 + "&alr (@x[$a3],@x[$b3])", # Q4 + "&xr (@x[$d2],@x[$a2])", + "&xr (@x[$d3],@x[$a3])", + "&rll (@x[$d2],@x[$d2],16)", + "&rll (@x[$d3],@x[$d3],16)", + + "&alr ($xc,@x[$d2])", + "&alr ($xc_,@x[$d3])", + "&xr (@x[$b2],$xc)", + "&xr (@x[$b3],$xc_)", + "&rll (@x[$b2],@x[$b2],12)", + "&rll (@x[$b3],@x[$b3],12)", + + "&alr (@x[$a2],@x[$b2])", + "&alr (@x[$a3],@x[$b3])", + "&xr (@x[$d2],@x[$a2])", + "&xr (@x[$d3],@x[$a3])", + "&rll (@x[$d2],@x[$d2],8)", + "&rll (@x[$d3],@x[$d3],8)", + + "&alr ($xc,@x[$d2])", + "&alr ($xc_,@x[$d3])", + "&xr (@x[$b2],$xc)", + "&xr (@x[$b3],$xc_)", + "&rll (@x[$b2],@x[$b2],7)", + "&rll (@x[$b3],@x[$b3],7)" + ); +} + +$code.=<<___; +.text + +.globl ChaCha20_ctr32 +.type ChaCha20_ctr32,\@function +.align 32 +ChaCha20_ctr32: + lt${g}r $len,$len # $len==0? + bzr %r14 + a${g}hi $len,-64 + l${g}hi %r1,-$frame + stm${g} %r6,%r15,`6*$SIZE_T`($sp) + sl${g}r $out,$inp # difference + la $len,0($inp,$len) # end of input minus 64 + larl %r7,.Lsigma + lgr %r0,$sp + la $sp,0(%r1,$sp) + st${g} %r0,0($sp) + + lmg %r8,%r11,0($key) # load key + lmg %r12,%r13,0($counter) # load counter + lmg %r6,%r7,0(%r7) # load sigma constant + + la %r14,0($inp) + st${g} $out,$frame+3*$SIZE_T($sp) + st${g} $len,$frame+4*$SIZE_T($sp) + stmg %r6,%r13,$stdframe($sp) # copy key schedule to stack + srlg @x[12],%r12,32 # 32-bit counter value + j .Loop_outer + +.align 16 +.Loop_outer: + lm @x[0],@x[7],$stdframe+4*0($sp) # load x[0]-x[7] + lm @t[0],@t[1],$stdframe+4*10($sp) # load x[10]-x[11] + lm @x[13],@x[15],$stdframe+4*13($sp) # load x[13]-x[15] + stm @t[0],@t[1],$stdframe+4*8+4*10($sp) # offload x[10]-x[11] + lm @t[0],@t[1],$stdframe+4*8($sp) # load x[8]-x[9] + st @x[12],$stdframe+4*12($sp) # save counter + st${g} %r14,$frame+2*$SIZE_T($sp) # save input pointer + lhi %r14,10 + j .Loop + +.align 4 +.Loop: +___ + foreach (&ROUND(0, 4, 8,12)) { eval; } + foreach (&ROUND(0, 5,10,15)) { eval; } +$code.=<<___; + brct %r14,.Loop + + l${g} %r14,$frame+2*$SIZE_T($sp) # pull input pointer + stm @t[0],@t[1],$stdframe+4*8+4*8($sp) # offload x[8]-x[9] + lm${g} @t[0],@t[1],$frame+3*$SIZE_T($sp) + + al @x[0],$stdframe+4*0($sp) # accumulate key schedule + al @x[1],$stdframe+4*1($sp) + al @x[2],$stdframe+4*2($sp) + al @x[3],$stdframe+4*3($sp) + al @x[4],$stdframe+4*4($sp) + al @x[5],$stdframe+4*5($sp) + al @x[6],$stdframe+4*6($sp) + al @x[7],$stdframe+4*7($sp) + lrvr @x[0],@x[0] + lrvr @x[1],@x[1] + lrvr @x[2],@x[2] + lrvr @x[3],@x[3] + lrvr @x[4],@x[4] + lrvr @x[5],@x[5] + lrvr @x[6],@x[6] + lrvr @x[7],@x[7] + al @x[12],$stdframe+4*12($sp) + al @x[13],$stdframe+4*13($sp) + al @x[14],$stdframe+4*14($sp) + al @x[15],$stdframe+4*15($sp) + lrvr @x[12],@x[12] + lrvr @x[13],@x[13] + lrvr @x[14],@x[14] + lrvr @x[15],@x[15] + + la @t[0],0(@t[0],%r14) # reconstruct output pointer + cl${g}r %r14,@t[1] + jh .Ltail + + x @x[0],4*0(%r14) # xor with input + x @x[1],4*1(%r14) + st @x[0],4*0(@t[0]) # store output + x @x[2],4*2(%r14) + st @x[1],4*1(@t[0]) + x @x[3],4*3(%r14) + st @x[2],4*2(@t[0]) + x @x[4],4*4(%r14) + st @x[3],4*3(@t[0]) + lm @x[0],@x[3],$stdframe+4*8+4*8($sp) # load x[8]-x[11] + x @x[5],4*5(%r14) + st @x[4],4*4(@t[0]) + x @x[6],4*6(%r14) + al @x[0],$stdframe+4*8($sp) + st @x[5],4*5(@t[0]) + x @x[7],4*7(%r14) + al @x[1],$stdframe+4*9($sp) + st @x[6],4*6(@t[0]) + x @x[12],4*12(%r14) + al @x[2],$stdframe+4*10($sp) + st @x[7],4*7(@t[0]) + x @x[13],4*13(%r14) + al @x[3],$stdframe+4*11($sp) + st @x[12],4*12(@t[0]) + x @x[14],4*14(%r14) + st @x[13],4*13(@t[0]) + x @x[15],4*15(%r14) + st @x[14],4*14(@t[0]) + lrvr @x[0],@x[0] + st @x[15],4*15(@t[0]) + lrvr @x[1],@x[1] + lrvr @x[2],@x[2] + lrvr @x[3],@x[3] + lhi @x[12],1 + x @x[0],4*8(%r14) + al @x[12],$stdframe+4*12($sp) # increment counter + x @x[1],4*9(%r14) + st @x[0],4*8(@t[0]) + x @x[2],4*10(%r14) + st @x[1],4*9(@t[0]) + x @x[3],4*11(%r14) + st @x[2],4*10(@t[0]) + st @x[3],4*11(@t[0]) + + cl${g}r %r14,@t[1] # done yet? + la %r14,64(%r14) + jl .Loop_outer + +.Ldone: + xgr %r0,%r0 + xgr %r1,%r1 + xgr %r2,%r2 + xgr %r3,%r3 + stmg %r0,%r3,$stdframe+4*4($sp) # wipe key copy + stmg %r0,%r3,$stdframe+4*12($sp) + + lm${g} %r6,%r15,`$frame+6*$SIZE_T`($sp) + br %r14 + +.align 16 +.Ltail: + la @t[1],64($t[1]) + stm @x[0],@x[7],$stdframe+4*0($sp) + sl${g}r @t[1],%r14 + lm @x[0],@x[3],$stdframe+4*8+4*8($sp) + l${g}hi @x[6],0 + stm @x[12],@x[15],$stdframe+4*12($sp) + al @x[0],$stdframe+4*8($sp) + al @x[1],$stdframe+4*9($sp) + al @x[2],$stdframe+4*10($sp) + al @x[3],$stdframe+4*11($sp) + lrvr @x[0],@x[0] + lrvr @x[1],@x[1] + lrvr @x[2],@x[2] + lrvr @x[3],@x[3] + stm @x[0],@x[3],$stdframe+4*8($sp) + +.Loop_tail: + llgc @x[4],0(@x[6],%r14) + llgc @x[5],$stdframe(@x[6],$sp) + xr @x[5],@x[4] + stc @x[5],0(@x[6],@t[0]) + la @x[6],1(@x[6]) + brct @t[1],.Loop_tail + + j .Ldone +.size ChaCha20_ctr32,.-ChaCha20_ctr32 + +.align 32 +.Lsigma: +.long 0x61707865,0x3320646e,0x79622d32,0x6b206574 # endian-neutral +.asciz "ChaCha20 for s390x, CRYPTOGAMS by " +.align 4 +___ + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/ge; + + print $_,"\n"; +} +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/chacha/asm/chacha-x86.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/chacha/asm/chacha-x86.pl new file mode 100755 index 000000000..13c217dcf --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/chacha/asm/chacha-x86.pl @@ -0,0 +1,1155 @@ +#! /usr/bin/env perl +# Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# January 2015 +# +# ChaCha20 for x86. +# +# Performance in cycles per byte out of large buffer. +# +# 1xIALU/gcc 4xSSSE3 +# Pentium 17.5/+80% +# PIII 14.2/+60% +# P4 18.6/+84% +# Core2 9.56/+89% 4.83 +# Westmere 9.50/+45% 3.35 +# Sandy Bridge 10.5/+47% 3.20 +# Haswell 8.15/+50% 2.83 +# Skylake 7.53/+22% 2.75 +# Silvermont 17.4/+36% 8.35 +# Goldmont 13.4/+40% 4.36 +# Sledgehammer 10.2/+54% +# Bulldozer 13.4/+50% 4.38(*) +# +# (*) Bulldozer actually executes 4xXOP code path that delivers 3.55; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +$output=pop; +open STDOUT,">$output"; + +&asm_init($ARGV[0],$ARGV[$#ARGV] eq "386"); + +$xmm=$ymm=0; +for (@ARGV) { $xmm=1 if (/-DOPENSSL_IA32_SSE2/); } + +$ymm=1 if ($xmm && + `$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler version ([2-9]\.[0-9]+)/ && + ($gasver=$1)>=2.19); # first version supporting AVX + +$ymm=1 if ($xmm && !$ymm && $ARGV[0] eq "win32n" && + `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/ && + $1>=2.03); # first version supporting AVX + +$ymm=1 if ($xmm && !$ymm && $ARGV[0] eq "win32" && + `ml 2>&1` =~ /Version ([0-9]+)\./ && + $1>=10); # first version supporting AVX + +$ymm=1 if ($xmm && !$ymm && + `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9]\.[0-9]+)/ && + $2>=3.0); # first version supporting AVX + +$a="eax"; +($b,$b_)=("ebx","ebp"); +($c,$c_)=("ecx","esi"); +($d,$d_)=("edx","edi"); + +sub QUARTERROUND { +my ($ai,$bi,$ci,$di,$i)=@_; +my ($an,$bn,$cn,$dn)=map(($_&~3)+(($_+1)&3),($ai,$bi,$ci,$di)); # next +my ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-1)&3),($ai,$bi,$ci,$di)); # previous + + # a b c d + # + # 0 4 8 12 < even round + # 1 5 9 13 + # 2 6 10 14 + # 3 7 11 15 + # 0 5 10 15 < odd round + # 1 6 11 12 + # 2 7 8 13 + # 3 4 9 14 + + if ($i==0) { + my $j=4; + ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-$j--)&3),($ap,$bp,$cp,$dp)); + } elsif ($i==3) { + my $j=0; + ($an,$bn,$cn,$dn)=map(($_&~3)+(($_+$j++)&3),($an,$bn,$cn,$dn)); + } elsif ($i==4) { + my $j=4; + ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_+$j--)&3),($ap,$bp,$cp,$dp)); + } elsif ($i==7) { + my $j=0; + ($an,$bn,$cn,$dn)=map(($_&~3)+(($_-$j++)&3),($an,$bn,$cn,$dn)); + } + + #&add ($a,$b); # see elsewhere + &xor ($d,$a); + &mov (&DWP(4*$cp,"esp"),$c_) if ($ai>0 && $ai<3); + &rol ($d,16); + &mov (&DWP(4*$bp,"esp"),$b_) if ($i!=0); + &add ($c,$d); + &mov ($c_,&DWP(4*$cn,"esp")) if ($ai>0 && $ai<3); + &xor ($b,$c); + &mov ($d_,&DWP(4*$dn,"esp")) if ($di!=$dn); + &rol ($b,12); + &mov ($b_,&DWP(4*$bn,"esp")) if ($i<7); + &mov ($b_,&DWP(128,"esp")) if ($i==7); # loop counter + &add ($a,$b); + &xor ($d,$a); + &mov (&DWP(4*$ai,"esp"),$a); + &rol ($d,8); + &mov ($a,&DWP(4*$an,"esp")); + &add ($c,$d); + &mov (&DWP(4*$di,"esp"),$d) if ($di!=$dn); + &mov ($d_,$d) if ($di==$dn); + &xor ($b,$c); + &add ($a,$b_) if ($i<7); # elsewhere + &rol ($b,7); + + ($b,$b_)=($b_,$b); + ($c,$c_)=($c_,$c); + ($d,$d_)=($d_,$d); +} + +&static_label("ssse3_shortcut"); +&static_label("xop_shortcut"); +&static_label("ssse3_data"); +&static_label("pic_point"); + +&function_begin("ChaCha20_ctr32"); + &xor ("eax","eax"); + &cmp ("eax",&wparam(2)); # len==0? + &je (&label("no_data")); +if ($xmm) { + &call (&label("pic_point")); +&set_label("pic_point"); + &blindpop("eax"); + &picmeup("ebp","OPENSSL_ia32cap_P","eax",&label("pic_point")); + &test (&DWP(0,"ebp"),1<<24); # test FXSR bit + &jz (&label("x86")); + &test (&DWP(4,"ebp"),1<<9); # test SSSE3 bit + &jz (&label("x86")); + &jmp (&label("ssse3_shortcut")); +&set_label("x86"); +} + &mov ("esi",&wparam(3)); # key + &mov ("edi",&wparam(4)); # counter and nonce + + &stack_push(33); + + &mov ("eax",&DWP(4*0,"esi")); # copy key + &mov ("ebx",&DWP(4*1,"esi")); + &mov ("ecx",&DWP(4*2,"esi")); + &mov ("edx",&DWP(4*3,"esi")); + &mov (&DWP(64+4*4,"esp"),"eax"); + &mov (&DWP(64+4*5,"esp"),"ebx"); + &mov (&DWP(64+4*6,"esp"),"ecx"); + &mov (&DWP(64+4*7,"esp"),"edx"); + &mov ("eax",&DWP(4*4,"esi")); + &mov ("ebx",&DWP(4*5,"esi")); + &mov ("ecx",&DWP(4*6,"esi")); + &mov ("edx",&DWP(4*7,"esi")); + &mov (&DWP(64+4*8,"esp"),"eax"); + &mov (&DWP(64+4*9,"esp"),"ebx"); + &mov (&DWP(64+4*10,"esp"),"ecx"); + &mov (&DWP(64+4*11,"esp"),"edx"); + &mov ("eax",&DWP(4*0,"edi")); # copy counter and nonce + &mov ("ebx",&DWP(4*1,"edi")); + &mov ("ecx",&DWP(4*2,"edi")); + &mov ("edx",&DWP(4*3,"edi")); + &sub ("eax",1); + &mov (&DWP(64+4*12,"esp"),"eax"); + &mov (&DWP(64+4*13,"esp"),"ebx"); + &mov (&DWP(64+4*14,"esp"),"ecx"); + &mov (&DWP(64+4*15,"esp"),"edx"); + &jmp (&label("entry")); + +&set_label("outer_loop",16); + &mov (&wparam(1),$b); # save input + &mov (&wparam(0),$a); # save output + &mov (&wparam(2),$c); # save len +&set_label("entry"); + &mov ($a,0x61707865); + &mov (&DWP(4*1,"esp"),0x3320646e); + &mov (&DWP(4*2,"esp"),0x79622d32); + &mov (&DWP(4*3,"esp"),0x6b206574); + + &mov ($b, &DWP(64+4*5,"esp")); # copy key material + &mov ($b_,&DWP(64+4*6,"esp")); + &mov ($c, &DWP(64+4*10,"esp")); + &mov ($c_,&DWP(64+4*11,"esp")); + &mov ($d, &DWP(64+4*13,"esp")); + &mov ($d_,&DWP(64+4*14,"esp")); + &mov (&DWP(4*5,"esp"),$b); + &mov (&DWP(4*6,"esp"),$b_); + &mov (&DWP(4*10,"esp"),$c); + &mov (&DWP(4*11,"esp"),$c_); + &mov (&DWP(4*13,"esp"),$d); + &mov (&DWP(4*14,"esp"),$d_); + + &mov ($b, &DWP(64+4*7,"esp")); + &mov ($d_,&DWP(64+4*15,"esp")); + &mov ($d, &DWP(64+4*12,"esp")); + &mov ($b_,&DWP(64+4*4,"esp")); + &mov ($c, &DWP(64+4*8,"esp")); + &mov ($c_,&DWP(64+4*9,"esp")); + &add ($d,1); # counter value + &mov (&DWP(4*7,"esp"),$b); + &mov (&DWP(4*15,"esp"),$d_); + &mov (&DWP(64+4*12,"esp"),$d); # save counter value + + &mov ($b,10); # loop counter + &jmp (&label("loop")); + +&set_label("loop",16); + &add ($a,$b_); # elsewhere + &mov (&DWP(128,"esp"),$b); # save loop counter + &mov ($b,$b_); + &QUARTERROUND(0, 4, 8, 12, 0); + &QUARTERROUND(1, 5, 9, 13, 1); + &QUARTERROUND(2, 6,10, 14, 2); + &QUARTERROUND(3, 7,11, 15, 3); + &QUARTERROUND(0, 5,10, 15, 4); + &QUARTERROUND(1, 6,11, 12, 5); + &QUARTERROUND(2, 7, 8, 13, 6); + &QUARTERROUND(3, 4, 9, 14, 7); + &dec ($b); + &jnz (&label("loop")); + + &mov ($b,&wparam(2)); # load len + + &add ($a,0x61707865); # accumulate key material + &add ($b_,&DWP(64+4*4,"esp")); + &add ($c, &DWP(64+4*8,"esp")); + &add ($c_,&DWP(64+4*9,"esp")); + + &cmp ($b,64); + &jb (&label("tail")); + + &mov ($b,&wparam(1)); # load input pointer + &add ($d, &DWP(64+4*12,"esp")); + &add ($d_,&DWP(64+4*14,"esp")); + + &xor ($a, &DWP(4*0,$b)); # xor with input + &xor ($b_,&DWP(4*4,$b)); + &mov (&DWP(4*0,"esp"),$a); + &mov ($a,&wparam(0)); # load output pointer + &xor ($c, &DWP(4*8,$b)); + &xor ($c_,&DWP(4*9,$b)); + &xor ($d, &DWP(4*12,$b)); + &xor ($d_,&DWP(4*14,$b)); + &mov (&DWP(4*4,$a),$b_); # write output + &mov (&DWP(4*8,$a),$c); + &mov (&DWP(4*9,$a),$c_); + &mov (&DWP(4*12,$a),$d); + &mov (&DWP(4*14,$a),$d_); + + &mov ($b_,&DWP(4*1,"esp")); + &mov ($c, &DWP(4*2,"esp")); + &mov ($c_,&DWP(4*3,"esp")); + &mov ($d, &DWP(4*5,"esp")); + &mov ($d_,&DWP(4*6,"esp")); + &add ($b_,0x3320646e); # accumulate key material + &add ($c, 0x79622d32); + &add ($c_,0x6b206574); + &add ($d, &DWP(64+4*5,"esp")); + &add ($d_,&DWP(64+4*6,"esp")); + &xor ($b_,&DWP(4*1,$b)); + &xor ($c, &DWP(4*2,$b)); + &xor ($c_,&DWP(4*3,$b)); + &xor ($d, &DWP(4*5,$b)); + &xor ($d_,&DWP(4*6,$b)); + &mov (&DWP(4*1,$a),$b_); + &mov (&DWP(4*2,$a),$c); + &mov (&DWP(4*3,$a),$c_); + &mov (&DWP(4*5,$a),$d); + &mov (&DWP(4*6,$a),$d_); + + &mov ($b_,&DWP(4*7,"esp")); + &mov ($c, &DWP(4*10,"esp")); + &mov ($c_,&DWP(4*11,"esp")); + &mov ($d, &DWP(4*13,"esp")); + &mov ($d_,&DWP(4*15,"esp")); + &add ($b_,&DWP(64+4*7,"esp")); + &add ($c, &DWP(64+4*10,"esp")); + &add ($c_,&DWP(64+4*11,"esp")); + &add ($d, &DWP(64+4*13,"esp")); + &add ($d_,&DWP(64+4*15,"esp")); + &xor ($b_,&DWP(4*7,$b)); + &xor ($c, &DWP(4*10,$b)); + &xor ($c_,&DWP(4*11,$b)); + &xor ($d, &DWP(4*13,$b)); + &xor ($d_,&DWP(4*15,$b)); + &lea ($b,&DWP(4*16,$b)); + &mov (&DWP(4*7,$a),$b_); + &mov ($b_,&DWP(4*0,"esp")); + &mov (&DWP(4*10,$a),$c); + &mov ($c,&wparam(2)); # len + &mov (&DWP(4*11,$a),$c_); + &mov (&DWP(4*13,$a),$d); + &mov (&DWP(4*15,$a),$d_); + &mov (&DWP(4*0,$a),$b_); + &lea ($a,&DWP(4*16,$a)); + &sub ($c,64); + &jnz (&label("outer_loop")); + + &jmp (&label("done")); + +&set_label("tail"); + &add ($d, &DWP(64+4*12,"esp")); + &add ($d_,&DWP(64+4*14,"esp")); + &mov (&DWP(4*0,"esp"),$a); + &mov (&DWP(4*4,"esp"),$b_); + &mov (&DWP(4*8,"esp"),$c); + &mov (&DWP(4*9,"esp"),$c_); + &mov (&DWP(4*12,"esp"),$d); + &mov (&DWP(4*14,"esp"),$d_); + + &mov ($b_,&DWP(4*1,"esp")); + &mov ($c, &DWP(4*2,"esp")); + &mov ($c_,&DWP(4*3,"esp")); + &mov ($d, &DWP(4*5,"esp")); + &mov ($d_,&DWP(4*6,"esp")); + &add ($b_,0x3320646e); # accumulate key material + &add ($c, 0x79622d32); + &add ($c_,0x6b206574); + &add ($d, &DWP(64+4*5,"esp")); + &add ($d_,&DWP(64+4*6,"esp")); + &mov (&DWP(4*1,"esp"),$b_); + &mov (&DWP(4*2,"esp"),$c); + &mov (&DWP(4*3,"esp"),$c_); + &mov (&DWP(4*5,"esp"),$d); + &mov (&DWP(4*6,"esp"),$d_); + + &mov ($b_,&DWP(4*7,"esp")); + &mov ($c, &DWP(4*10,"esp")); + &mov ($c_,&DWP(4*11,"esp")); + &mov ($d, &DWP(4*13,"esp")); + &mov ($d_,&DWP(4*15,"esp")); + &add ($b_,&DWP(64+4*7,"esp")); + &add ($c, &DWP(64+4*10,"esp")); + &add ($c_,&DWP(64+4*11,"esp")); + &add ($d, &DWP(64+4*13,"esp")); + &add ($d_,&DWP(64+4*15,"esp")); + &mov (&DWP(4*7,"esp"),$b_); + &mov ($b_,&wparam(1)); # load input + &mov (&DWP(4*10,"esp"),$c); + &mov ($c,&wparam(0)); # load output + &mov (&DWP(4*11,"esp"),$c_); + &xor ($c_,$c_); + &mov (&DWP(4*13,"esp"),$d); + &mov (&DWP(4*15,"esp"),$d_); + + &xor ("eax","eax"); + &xor ("edx","edx"); +&set_label("tail_loop"); + &movb ("al",&BP(0,$c_,$b_)); + &movb ("dl",&BP(0,"esp",$c_)); + &lea ($c_,&DWP(1,$c_)); + &xor ("al","dl"); + &mov (&BP(-1,$c,$c_),"al"); + &dec ($b); + &jnz (&label("tail_loop")); + +&set_label("done"); + &stack_pop(33); +&set_label("no_data"); +&function_end("ChaCha20_ctr32"); + +if ($xmm) { +my ($xa,$xa_,$xb,$xb_,$xc,$xc_,$xd,$xd_)=map("xmm$_",(0..7)); +my ($out,$inp,$len)=("edi","esi","ecx"); + +sub QUARTERROUND_SSSE3 { +my ($ai,$bi,$ci,$di,$i)=@_; +my ($an,$bn,$cn,$dn)=map(($_&~3)+(($_+1)&3),($ai,$bi,$ci,$di)); # next +my ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-1)&3),($ai,$bi,$ci,$di)); # previous + + # a b c d + # + # 0 4 8 12 < even round + # 1 5 9 13 + # 2 6 10 14 + # 3 7 11 15 + # 0 5 10 15 < odd round + # 1 6 11 12 + # 2 7 8 13 + # 3 4 9 14 + + if ($i==0) { + my $j=4; + ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-$j--)&3),($ap,$bp,$cp,$dp)); + } elsif ($i==3) { + my $j=0; + ($an,$bn,$cn,$dn)=map(($_&~3)+(($_+$j++)&3),($an,$bn,$cn,$dn)); + } elsif ($i==4) { + my $j=4; + ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_+$j--)&3),($ap,$bp,$cp,$dp)); + } elsif ($i==7) { + my $j=0; + ($an,$bn,$cn,$dn)=map(($_&~3)+(($_-$j++)&3),($an,$bn,$cn,$dn)); + } + + #&paddd ($xa,$xb); # see elsewhere + #&pxor ($xd,$xa); # see elsewhere + &movdqa(&QWP(16*$cp-128,"ebx"),$xc_) if ($ai>0 && $ai<3); + &pshufb ($xd,&QWP(0,"eax")); # rot16 + &movdqa(&QWP(16*$bp-128,"ebx"),$xb_) if ($i!=0); + &paddd ($xc,$xd); + &movdqa($xc_,&QWP(16*$cn-128,"ebx")) if ($ai>0 && $ai<3); + &pxor ($xb,$xc); + &movdqa($xb_,&QWP(16*$bn-128,"ebx")) if ($i<7); + &movdqa ($xa_,$xb); # borrow as temporary + &pslld ($xb,12); + &psrld ($xa_,20); + &por ($xb,$xa_); + &movdqa($xa_,&QWP(16*$an-128,"ebx")); + &paddd ($xa,$xb); + &movdqa($xd_,&QWP(16*$dn-128,"ebx")) if ($di!=$dn); + &pxor ($xd,$xa); + &movdqa (&QWP(16*$ai-128,"ebx"),$xa); + &pshufb ($xd,&QWP(16,"eax")); # rot8 + &paddd ($xc,$xd); + &movdqa (&QWP(16*$di-128,"ebx"),$xd) if ($di!=$dn); + &movdqa ($xd_,$xd) if ($di==$dn); + &pxor ($xb,$xc); + &paddd ($xa_,$xb_) if ($i<7); # elsewhere + &movdqa ($xa,$xb); # borrow as temporary + &pslld ($xb,7); + &psrld ($xa,25); + &pxor ($xd_,$xa_) if ($i<7); # elsewhere + &por ($xb,$xa); + + ($xa,$xa_)=($xa_,$xa); + ($xb,$xb_)=($xb_,$xb); + ($xc,$xc_)=($xc_,$xc); + ($xd,$xd_)=($xd_,$xd); +} + +&function_begin("ChaCha20_ssse3"); +&set_label("ssse3_shortcut"); +if ($ymm) { + &test (&DWP(4,"ebp"),1<<11); # test XOP bit + &jnz (&label("xop_shortcut")); +} + + &mov ($out,&wparam(0)); + &mov ($inp,&wparam(1)); + &mov ($len,&wparam(2)); + &mov ("edx",&wparam(3)); # key + &mov ("ebx",&wparam(4)); # counter and nonce + + &mov ("ebp","esp"); + &stack_push (131); + &and ("esp",-64); + &mov (&DWP(512,"esp"),"ebp"); + + &lea ("eax",&DWP(&label("ssse3_data")."-". + &label("pic_point"),"eax")); + &movdqu ("xmm3",&QWP(0,"ebx")); # counter and nonce + +if (defined($gasver) && $gasver>=2.17) { # even though we encode + # pshufb manually, we + # handle only register + # operands, while this + # segment uses memory + # operand... + &cmp ($len,64*4); + &jb (&label("1x")); + + &mov (&DWP(512+4,"esp"),"edx"); # offload pointers + &mov (&DWP(512+8,"esp"),"ebx"); + &sub ($len,64*4); # bias len + &lea ("ebp",&DWP(256+128,"esp")); # size optimization + + &movdqu ("xmm7",&QWP(0,"edx")); # key + &pshufd ("xmm0","xmm3",0x00); + &pshufd ("xmm1","xmm3",0x55); + &pshufd ("xmm2","xmm3",0xaa); + &pshufd ("xmm3","xmm3",0xff); + &paddd ("xmm0",&QWP(16*3,"eax")); # fix counters + &pshufd ("xmm4","xmm7",0x00); + &pshufd ("xmm5","xmm7",0x55); + &psubd ("xmm0",&QWP(16*4,"eax")); + &pshufd ("xmm6","xmm7",0xaa); + &pshufd ("xmm7","xmm7",0xff); + &movdqa (&QWP(16*12-128,"ebp"),"xmm0"); + &movdqa (&QWP(16*13-128,"ebp"),"xmm1"); + &movdqa (&QWP(16*14-128,"ebp"),"xmm2"); + &movdqa (&QWP(16*15-128,"ebp"),"xmm3"); + &movdqu ("xmm3",&QWP(16,"edx")); # key + &movdqa (&QWP(16*4-128,"ebp"),"xmm4"); + &movdqa (&QWP(16*5-128,"ebp"),"xmm5"); + &movdqa (&QWP(16*6-128,"ebp"),"xmm6"); + &movdqa (&QWP(16*7-128,"ebp"),"xmm7"); + &movdqa ("xmm7",&QWP(16*2,"eax")); # sigma + &lea ("ebx",&DWP(128,"esp")); # size optimization + + &pshufd ("xmm0","xmm3",0x00); + &pshufd ("xmm1","xmm3",0x55); + &pshufd ("xmm2","xmm3",0xaa); + &pshufd ("xmm3","xmm3",0xff); + &pshufd ("xmm4","xmm7",0x00); + &pshufd ("xmm5","xmm7",0x55); + &pshufd ("xmm6","xmm7",0xaa); + &pshufd ("xmm7","xmm7",0xff); + &movdqa (&QWP(16*8-128,"ebp"),"xmm0"); + &movdqa (&QWP(16*9-128,"ebp"),"xmm1"); + &movdqa (&QWP(16*10-128,"ebp"),"xmm2"); + &movdqa (&QWP(16*11-128,"ebp"),"xmm3"); + &movdqa (&QWP(16*0-128,"ebp"),"xmm4"); + &movdqa (&QWP(16*1-128,"ebp"),"xmm5"); + &movdqa (&QWP(16*2-128,"ebp"),"xmm6"); + &movdqa (&QWP(16*3-128,"ebp"),"xmm7"); + + &lea ($inp,&DWP(128,$inp)); # size optimization + &lea ($out,&DWP(128,$out)); # size optimization + &jmp (&label("outer_loop")); + +&set_label("outer_loop",16); + #&movdqa ("xmm0",&QWP(16*0-128,"ebp")); # copy key material + &movdqa ("xmm1",&QWP(16*1-128,"ebp")); + &movdqa ("xmm2",&QWP(16*2-128,"ebp")); + &movdqa ("xmm3",&QWP(16*3-128,"ebp")); + #&movdqa ("xmm4",&QWP(16*4-128,"ebp")); + &movdqa ("xmm5",&QWP(16*5-128,"ebp")); + &movdqa ("xmm6",&QWP(16*6-128,"ebp")); + &movdqa ("xmm7",&QWP(16*7-128,"ebp")); + #&movdqa (&QWP(16*0-128,"ebx"),"xmm0"); + &movdqa (&QWP(16*1-128,"ebx"),"xmm1"); + &movdqa (&QWP(16*2-128,"ebx"),"xmm2"); + &movdqa (&QWP(16*3-128,"ebx"),"xmm3"); + #&movdqa (&QWP(16*4-128,"ebx"),"xmm4"); + &movdqa (&QWP(16*5-128,"ebx"),"xmm5"); + &movdqa (&QWP(16*6-128,"ebx"),"xmm6"); + &movdqa (&QWP(16*7-128,"ebx"),"xmm7"); + #&movdqa ("xmm0",&QWP(16*8-128,"ebp")); + #&movdqa ("xmm1",&QWP(16*9-128,"ebp")); + &movdqa ("xmm2",&QWP(16*10-128,"ebp")); + &movdqa ("xmm3",&QWP(16*11-128,"ebp")); + &movdqa ("xmm4",&QWP(16*12-128,"ebp")); + &movdqa ("xmm5",&QWP(16*13-128,"ebp")); + &movdqa ("xmm6",&QWP(16*14-128,"ebp")); + &movdqa ("xmm7",&QWP(16*15-128,"ebp")); + &paddd ("xmm4",&QWP(16*4,"eax")); # counter value + #&movdqa (&QWP(16*8-128,"ebx"),"xmm0"); + #&movdqa (&QWP(16*9-128,"ebx"),"xmm1"); + &movdqa (&QWP(16*10-128,"ebx"),"xmm2"); + &movdqa (&QWP(16*11-128,"ebx"),"xmm3"); + &movdqa (&QWP(16*12-128,"ebx"),"xmm4"); + &movdqa (&QWP(16*13-128,"ebx"),"xmm5"); + &movdqa (&QWP(16*14-128,"ebx"),"xmm6"); + &movdqa (&QWP(16*15-128,"ebx"),"xmm7"); + &movdqa (&QWP(16*12-128,"ebp"),"xmm4"); # save counter value + + &movdqa ($xa, &QWP(16*0-128,"ebp")); + &movdqa ($xd, "xmm4"); + &movdqa ($xb_,&QWP(16*4-128,"ebp")); + &movdqa ($xc, &QWP(16*8-128,"ebp")); + &movdqa ($xc_,&QWP(16*9-128,"ebp")); + + &mov ("edx",10); # loop counter + &nop (); + +&set_label("loop",16); + &paddd ($xa,$xb_); # elsewhere + &movdqa ($xb,$xb_); + &pxor ($xd,$xa); # elsewhere + &QUARTERROUND_SSSE3(0, 4, 8, 12, 0); + &QUARTERROUND_SSSE3(1, 5, 9, 13, 1); + &QUARTERROUND_SSSE3(2, 6,10, 14, 2); + &QUARTERROUND_SSSE3(3, 7,11, 15, 3); + &QUARTERROUND_SSSE3(0, 5,10, 15, 4); + &QUARTERROUND_SSSE3(1, 6,11, 12, 5); + &QUARTERROUND_SSSE3(2, 7, 8, 13, 6); + &QUARTERROUND_SSSE3(3, 4, 9, 14, 7); + &dec ("edx"); + &jnz (&label("loop")); + + &movdqa (&QWP(16*4-128,"ebx"),$xb_); + &movdqa (&QWP(16*8-128,"ebx"),$xc); + &movdqa (&QWP(16*9-128,"ebx"),$xc_); + &movdqa (&QWP(16*12-128,"ebx"),$xd); + &movdqa (&QWP(16*14-128,"ebx"),$xd_); + + my ($xa0,$xa1,$xa2,$xa3,$xt0,$xt1,$xt2,$xt3)=map("xmm$_",(0..7)); + + #&movdqa ($xa0,&QWP(16*0-128,"ebx")); # it's there + &movdqa ($xa1,&QWP(16*1-128,"ebx")); + &movdqa ($xa2,&QWP(16*2-128,"ebx")); + &movdqa ($xa3,&QWP(16*3-128,"ebx")); + + for($i=0;$i<256;$i+=64) { + &paddd ($xa0,&QWP($i+16*0-128,"ebp")); # accumulate key material + &paddd ($xa1,&QWP($i+16*1-128,"ebp")); + &paddd ($xa2,&QWP($i+16*2-128,"ebp")); + &paddd ($xa3,&QWP($i+16*3-128,"ebp")); + + &movdqa ($xt2,$xa0); # "de-interlace" data + &punpckldq ($xa0,$xa1); + &movdqa ($xt3,$xa2); + &punpckldq ($xa2,$xa3); + &punpckhdq ($xt2,$xa1); + &punpckhdq ($xt3,$xa3); + &movdqa ($xa1,$xa0); + &punpcklqdq ($xa0,$xa2); # "a0" + &movdqa ($xa3,$xt2); + &punpcklqdq ($xt2,$xt3); # "a2" + &punpckhqdq ($xa1,$xa2); # "a1" + &punpckhqdq ($xa3,$xt3); # "a3" + + #($xa2,$xt2)=($xt2,$xa2); + + &movdqu ($xt0,&QWP(64*0-128,$inp)); # load input + &movdqu ($xt1,&QWP(64*1-128,$inp)); + &movdqu ($xa2,&QWP(64*2-128,$inp)); + &movdqu ($xt3,&QWP(64*3-128,$inp)); + &lea ($inp,&QWP($i<192?16:(64*4-16*3),$inp)); + &pxor ($xt0,$xa0); + &movdqa ($xa0,&QWP($i+16*4-128,"ebx")) if ($i<192); + &pxor ($xt1,$xa1); + &movdqa ($xa1,&QWP($i+16*5-128,"ebx")) if ($i<192); + &pxor ($xt2,$xa2); + &movdqa ($xa2,&QWP($i+16*6-128,"ebx")) if ($i<192); + &pxor ($xt3,$xa3); + &movdqa ($xa3,&QWP($i+16*7-128,"ebx")) if ($i<192); + &movdqu (&QWP(64*0-128,$out),$xt0); # store output + &movdqu (&QWP(64*1-128,$out),$xt1); + &movdqu (&QWP(64*2-128,$out),$xt2); + &movdqu (&QWP(64*3-128,$out),$xt3); + &lea ($out,&QWP($i<192?16:(64*4-16*3),$out)); + } + &sub ($len,64*4); + &jnc (&label("outer_loop")); + + &add ($len,64*4); + &jz (&label("done")); + + &mov ("ebx",&DWP(512+8,"esp")); # restore pointers + &lea ($inp,&DWP(-128,$inp)); + &mov ("edx",&DWP(512+4,"esp")); + &lea ($out,&DWP(-128,$out)); + + &movd ("xmm2",&DWP(16*12-128,"ebp")); # counter value + &movdqu ("xmm3",&QWP(0,"ebx")); + &paddd ("xmm2",&QWP(16*6,"eax")); # +four + &pand ("xmm3",&QWP(16*7,"eax")); + &por ("xmm3","xmm2"); # counter value +} +{ +my ($a,$b,$c,$d,$t,$t1,$rot16,$rot24)=map("xmm$_",(0..7)); + +sub SSSE3ROUND { # critical path is 20 "SIMD ticks" per round + &paddd ($a,$b); + &pxor ($d,$a); + &pshufb ($d,$rot16); + + &paddd ($c,$d); + &pxor ($b,$c); + &movdqa ($t,$b); + &psrld ($b,20); + &pslld ($t,12); + &por ($b,$t); + + &paddd ($a,$b); + &pxor ($d,$a); + &pshufb ($d,$rot24); + + &paddd ($c,$d); + &pxor ($b,$c); + &movdqa ($t,$b); + &psrld ($b,25); + &pslld ($t,7); + &por ($b,$t); +} + +&set_label("1x"); + &movdqa ($a,&QWP(16*2,"eax")); # sigma + &movdqu ($b,&QWP(0,"edx")); + &movdqu ($c,&QWP(16,"edx")); + #&movdqu ($d,&QWP(0,"ebx")); # already loaded + &movdqa ($rot16,&QWP(0,"eax")); + &movdqa ($rot24,&QWP(16,"eax")); + &mov (&DWP(16*3,"esp"),"ebp"); + + &movdqa (&QWP(16*0,"esp"),$a); + &movdqa (&QWP(16*1,"esp"),$b); + &movdqa (&QWP(16*2,"esp"),$c); + &movdqa (&QWP(16*3,"esp"),$d); + &mov ("edx",10); + &jmp (&label("loop1x")); + +&set_label("outer1x",16); + &movdqa ($d,&QWP(16*5,"eax")); # one + &movdqa ($a,&QWP(16*0,"esp")); + &movdqa ($b,&QWP(16*1,"esp")); + &movdqa ($c,&QWP(16*2,"esp")); + &paddd ($d,&QWP(16*3,"esp")); + &mov ("edx",10); + &movdqa (&QWP(16*3,"esp"),$d); + &jmp (&label("loop1x")); + +&set_label("loop1x",16); + &SSSE3ROUND(); + &pshufd ($c,$c,0b01001110); + &pshufd ($b,$b,0b00111001); + &pshufd ($d,$d,0b10010011); + &nop (); + + &SSSE3ROUND(); + &pshufd ($c,$c,0b01001110); + &pshufd ($b,$b,0b10010011); + &pshufd ($d,$d,0b00111001); + + &dec ("edx"); + &jnz (&label("loop1x")); + + &paddd ($a,&QWP(16*0,"esp")); + &paddd ($b,&QWP(16*1,"esp")); + &paddd ($c,&QWP(16*2,"esp")); + &paddd ($d,&QWP(16*3,"esp")); + + &cmp ($len,64); + &jb (&label("tail")); + + &movdqu ($t,&QWP(16*0,$inp)); + &movdqu ($t1,&QWP(16*1,$inp)); + &pxor ($a,$t); # xor with input + &movdqu ($t,&QWP(16*2,$inp)); + &pxor ($b,$t1); + &movdqu ($t1,&QWP(16*3,$inp)); + &pxor ($c,$t); + &pxor ($d,$t1); + &lea ($inp,&DWP(16*4,$inp)); # inp+=64 + + &movdqu (&QWP(16*0,$out),$a); # write output + &movdqu (&QWP(16*1,$out),$b); + &movdqu (&QWP(16*2,$out),$c); + &movdqu (&QWP(16*3,$out),$d); + &lea ($out,&DWP(16*4,$out)); # inp+=64 + + &sub ($len,64); + &jnz (&label("outer1x")); + + &jmp (&label("done")); + +&set_label("tail"); + &movdqa (&QWP(16*0,"esp"),$a); + &movdqa (&QWP(16*1,"esp"),$b); + &movdqa (&QWP(16*2,"esp"),$c); + &movdqa (&QWP(16*3,"esp"),$d); + + &xor ("eax","eax"); + &xor ("edx","edx"); + &xor ("ebp","ebp"); + +&set_label("tail_loop"); + &movb ("al",&BP(0,"esp","ebp")); + &movb ("dl",&BP(0,$inp,"ebp")); + &lea ("ebp",&DWP(1,"ebp")); + &xor ("al","dl"); + &movb (&BP(-1,$out,"ebp"),"al"); + &dec ($len); + &jnz (&label("tail_loop")); +} +&set_label("done"); + &mov ("esp",&DWP(512,"esp")); +&function_end("ChaCha20_ssse3"); + +&align (64); +&set_label("ssse3_data"); +&data_byte(0x2,0x3,0x0,0x1, 0x6,0x7,0x4,0x5, 0xa,0xb,0x8,0x9, 0xe,0xf,0xc,0xd); +&data_byte(0x3,0x0,0x1,0x2, 0x7,0x4,0x5,0x6, 0xb,0x8,0x9,0xa, 0xf,0xc,0xd,0xe); +&data_word(0x61707865,0x3320646e,0x79622d32,0x6b206574); +&data_word(0,1,2,3); +&data_word(4,4,4,4); +&data_word(1,0,0,0); +&data_word(4,0,0,0); +&data_word(0,-1,-1,-1); +&align (64); +} +&asciz ("ChaCha20 for x86, CRYPTOGAMS by "); + +if ($ymm) { +my ($xa,$xa_,$xb,$xb_,$xc,$xc_,$xd,$xd_)=map("xmm$_",(0..7)); +my ($out,$inp,$len)=("edi","esi","ecx"); + +sub QUARTERROUND_XOP { +my ($ai,$bi,$ci,$di,$i)=@_; +my ($an,$bn,$cn,$dn)=map(($_&~3)+(($_+1)&3),($ai,$bi,$ci,$di)); # next +my ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-1)&3),($ai,$bi,$ci,$di)); # previous + + # a b c d + # + # 0 4 8 12 < even round + # 1 5 9 13 + # 2 6 10 14 + # 3 7 11 15 + # 0 5 10 15 < odd round + # 1 6 11 12 + # 2 7 8 13 + # 3 4 9 14 + + if ($i==0) { + my $j=4; + ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-$j--)&3),($ap,$bp,$cp,$dp)); + } elsif ($i==3) { + my $j=0; + ($an,$bn,$cn,$dn)=map(($_&~3)+(($_+$j++)&3),($an,$bn,$cn,$dn)); + } elsif ($i==4) { + my $j=4; + ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_+$j--)&3),($ap,$bp,$cp,$dp)); + } elsif ($i==7) { + my $j=0; + ($an,$bn,$cn,$dn)=map(($_&~3)+(($_-$j++)&3),($an,$bn,$cn,$dn)); + } + + #&vpaddd ($xa,$xa,$xb); # see elsewhere + #&vpxor ($xd,$xd,$xa); # see elsewhere + &vmovdqa (&QWP(16*$cp-128,"ebx"),$xc_) if ($ai>0 && $ai<3); + &vprotd ($xd,$xd,16); + &vmovdqa (&QWP(16*$bp-128,"ebx"),$xb_) if ($i!=0); + &vpaddd ($xc,$xc,$xd); + &vmovdqa ($xc_,&QWP(16*$cn-128,"ebx")) if ($ai>0 && $ai<3); + &vpxor ($xb,$i!=0?$xb:$xb_,$xc); + &vmovdqa ($xa_,&QWP(16*$an-128,"ebx")); + &vprotd ($xb,$xb,12); + &vmovdqa ($xb_,&QWP(16*$bn-128,"ebx")) if ($i<7); + &vpaddd ($xa,$xa,$xb); + &vmovdqa ($xd_,&QWP(16*$dn-128,"ebx")) if ($di!=$dn); + &vpxor ($xd,$xd,$xa); + &vpaddd ($xa_,$xa_,$xb_) if ($i<7); # elsewhere + &vprotd ($xd,$xd,8); + &vmovdqa (&QWP(16*$ai-128,"ebx"),$xa); + &vpaddd ($xc,$xc,$xd); + &vmovdqa (&QWP(16*$di-128,"ebx"),$xd) if ($di!=$dn); + &vpxor ($xb,$xb,$xc); + &vpxor ($xd_,$di==$dn?$xd:$xd_,$xa_) if ($i<7); # elsewhere + &vprotd ($xb,$xb,7); + + ($xa,$xa_)=($xa_,$xa); + ($xb,$xb_)=($xb_,$xb); + ($xc,$xc_)=($xc_,$xc); + ($xd,$xd_)=($xd_,$xd); +} + +&function_begin("ChaCha20_xop"); +&set_label("xop_shortcut"); + &mov ($out,&wparam(0)); + &mov ($inp,&wparam(1)); + &mov ($len,&wparam(2)); + &mov ("edx",&wparam(3)); # key + &mov ("ebx",&wparam(4)); # counter and nonce + &vzeroupper (); + + &mov ("ebp","esp"); + &stack_push (131); + &and ("esp",-64); + &mov (&DWP(512,"esp"),"ebp"); + + &lea ("eax",&DWP(&label("ssse3_data")."-". + &label("pic_point"),"eax")); + &vmovdqu ("xmm3",&QWP(0,"ebx")); # counter and nonce + + &cmp ($len,64*4); + &jb (&label("1x")); + + &mov (&DWP(512+4,"esp"),"edx"); # offload pointers + &mov (&DWP(512+8,"esp"),"ebx"); + &sub ($len,64*4); # bias len + &lea ("ebp",&DWP(256+128,"esp")); # size optimization + + &vmovdqu ("xmm7",&QWP(0,"edx")); # key + &vpshufd ("xmm0","xmm3",0x00); + &vpshufd ("xmm1","xmm3",0x55); + &vpshufd ("xmm2","xmm3",0xaa); + &vpshufd ("xmm3","xmm3",0xff); + &vpaddd ("xmm0","xmm0",&QWP(16*3,"eax")); # fix counters + &vpshufd ("xmm4","xmm7",0x00); + &vpshufd ("xmm5","xmm7",0x55); + &vpsubd ("xmm0","xmm0",&QWP(16*4,"eax")); + &vpshufd ("xmm6","xmm7",0xaa); + &vpshufd ("xmm7","xmm7",0xff); + &vmovdqa (&QWP(16*12-128,"ebp"),"xmm0"); + &vmovdqa (&QWP(16*13-128,"ebp"),"xmm1"); + &vmovdqa (&QWP(16*14-128,"ebp"),"xmm2"); + &vmovdqa (&QWP(16*15-128,"ebp"),"xmm3"); + &vmovdqu ("xmm3",&QWP(16,"edx")); # key + &vmovdqa (&QWP(16*4-128,"ebp"),"xmm4"); + &vmovdqa (&QWP(16*5-128,"ebp"),"xmm5"); + &vmovdqa (&QWP(16*6-128,"ebp"),"xmm6"); + &vmovdqa (&QWP(16*7-128,"ebp"),"xmm7"); + &vmovdqa ("xmm7",&QWP(16*2,"eax")); # sigma + &lea ("ebx",&DWP(128,"esp")); # size optimization + + &vpshufd ("xmm0","xmm3",0x00); + &vpshufd ("xmm1","xmm3",0x55); + &vpshufd ("xmm2","xmm3",0xaa); + &vpshufd ("xmm3","xmm3",0xff); + &vpshufd ("xmm4","xmm7",0x00); + &vpshufd ("xmm5","xmm7",0x55); + &vpshufd ("xmm6","xmm7",0xaa); + &vpshufd ("xmm7","xmm7",0xff); + &vmovdqa (&QWP(16*8-128,"ebp"),"xmm0"); + &vmovdqa (&QWP(16*9-128,"ebp"),"xmm1"); + &vmovdqa (&QWP(16*10-128,"ebp"),"xmm2"); + &vmovdqa (&QWP(16*11-128,"ebp"),"xmm3"); + &vmovdqa (&QWP(16*0-128,"ebp"),"xmm4"); + &vmovdqa (&QWP(16*1-128,"ebp"),"xmm5"); + &vmovdqa (&QWP(16*2-128,"ebp"),"xmm6"); + &vmovdqa (&QWP(16*3-128,"ebp"),"xmm7"); + + &lea ($inp,&DWP(128,$inp)); # size optimization + &lea ($out,&DWP(128,$out)); # size optimization + &jmp (&label("outer_loop")); + +&set_label("outer_loop",32); + #&vmovdqa ("xmm0",&QWP(16*0-128,"ebp")); # copy key material + &vmovdqa ("xmm1",&QWP(16*1-128,"ebp")); + &vmovdqa ("xmm2",&QWP(16*2-128,"ebp")); + &vmovdqa ("xmm3",&QWP(16*3-128,"ebp")); + #&vmovdqa ("xmm4",&QWP(16*4-128,"ebp")); + &vmovdqa ("xmm5",&QWP(16*5-128,"ebp")); + &vmovdqa ("xmm6",&QWP(16*6-128,"ebp")); + &vmovdqa ("xmm7",&QWP(16*7-128,"ebp")); + #&vmovdqa (&QWP(16*0-128,"ebx"),"xmm0"); + &vmovdqa (&QWP(16*1-128,"ebx"),"xmm1"); + &vmovdqa (&QWP(16*2-128,"ebx"),"xmm2"); + &vmovdqa (&QWP(16*3-128,"ebx"),"xmm3"); + #&vmovdqa (&QWP(16*4-128,"ebx"),"xmm4"); + &vmovdqa (&QWP(16*5-128,"ebx"),"xmm5"); + &vmovdqa (&QWP(16*6-128,"ebx"),"xmm6"); + &vmovdqa (&QWP(16*7-128,"ebx"),"xmm7"); + #&vmovdqa ("xmm0",&QWP(16*8-128,"ebp")); + #&vmovdqa ("xmm1",&QWP(16*9-128,"ebp")); + &vmovdqa ("xmm2",&QWP(16*10-128,"ebp")); + &vmovdqa ("xmm3",&QWP(16*11-128,"ebp")); + &vmovdqa ("xmm4",&QWP(16*12-128,"ebp")); + &vmovdqa ("xmm5",&QWP(16*13-128,"ebp")); + &vmovdqa ("xmm6",&QWP(16*14-128,"ebp")); + &vmovdqa ("xmm7",&QWP(16*15-128,"ebp")); + &vpaddd ("xmm4","xmm4",&QWP(16*4,"eax")); # counter value + #&vmovdqa (&QWP(16*8-128,"ebx"),"xmm0"); + #&vmovdqa (&QWP(16*9-128,"ebx"),"xmm1"); + &vmovdqa (&QWP(16*10-128,"ebx"),"xmm2"); + &vmovdqa (&QWP(16*11-128,"ebx"),"xmm3"); + &vmovdqa (&QWP(16*12-128,"ebx"),"xmm4"); + &vmovdqa (&QWP(16*13-128,"ebx"),"xmm5"); + &vmovdqa (&QWP(16*14-128,"ebx"),"xmm6"); + &vmovdqa (&QWP(16*15-128,"ebx"),"xmm7"); + &vmovdqa (&QWP(16*12-128,"ebp"),"xmm4"); # save counter value + + &vmovdqa ($xa, &QWP(16*0-128,"ebp")); + &vmovdqa ($xd, "xmm4"); + &vmovdqa ($xb_,&QWP(16*4-128,"ebp")); + &vmovdqa ($xc, &QWP(16*8-128,"ebp")); + &vmovdqa ($xc_,&QWP(16*9-128,"ebp")); + + &mov ("edx",10); # loop counter + &nop (); + +&set_label("loop",32); + &vpaddd ($xa,$xa,$xb_); # elsewhere + &vpxor ($xd,$xd,$xa); # elsewhere + &QUARTERROUND_XOP(0, 4, 8, 12, 0); + &QUARTERROUND_XOP(1, 5, 9, 13, 1); + &QUARTERROUND_XOP(2, 6,10, 14, 2); + &QUARTERROUND_XOP(3, 7,11, 15, 3); + &QUARTERROUND_XOP(0, 5,10, 15, 4); + &QUARTERROUND_XOP(1, 6,11, 12, 5); + &QUARTERROUND_XOP(2, 7, 8, 13, 6); + &QUARTERROUND_XOP(3, 4, 9, 14, 7); + &dec ("edx"); + &jnz (&label("loop")); + + &vmovdqa (&QWP(16*4-128,"ebx"),$xb_); + &vmovdqa (&QWP(16*8-128,"ebx"),$xc); + &vmovdqa (&QWP(16*9-128,"ebx"),$xc_); + &vmovdqa (&QWP(16*12-128,"ebx"),$xd); + &vmovdqa (&QWP(16*14-128,"ebx"),$xd_); + + my ($xa0,$xa1,$xa2,$xa3,$xt0,$xt1,$xt2,$xt3)=map("xmm$_",(0..7)); + + #&vmovdqa ($xa0,&QWP(16*0-128,"ebx")); # it's there + &vmovdqa ($xa1,&QWP(16*1-128,"ebx")); + &vmovdqa ($xa2,&QWP(16*2-128,"ebx")); + &vmovdqa ($xa3,&QWP(16*3-128,"ebx")); + + for($i=0;$i<256;$i+=64) { + &vpaddd ($xa0,$xa0,&QWP($i+16*0-128,"ebp")); # accumulate key material + &vpaddd ($xa1,$xa1,&QWP($i+16*1-128,"ebp")); + &vpaddd ($xa2,$xa2,&QWP($i+16*2-128,"ebp")); + &vpaddd ($xa3,$xa3,&QWP($i+16*3-128,"ebp")); + + &vpunpckldq ($xt2,$xa0,$xa1); # "de-interlace" data + &vpunpckldq ($xt3,$xa2,$xa3); + &vpunpckhdq ($xa0,$xa0,$xa1); + &vpunpckhdq ($xa2,$xa2,$xa3); + &vpunpcklqdq ($xa1,$xt2,$xt3); # "a0" + &vpunpckhqdq ($xt2,$xt2,$xt3); # "a1" + &vpunpcklqdq ($xt3,$xa0,$xa2); # "a2" + &vpunpckhqdq ($xa3,$xa0,$xa2); # "a3" + + &vpxor ($xt0,$xa1,&QWP(64*0-128,$inp)); + &vpxor ($xt1,$xt2,&QWP(64*1-128,$inp)); + &vpxor ($xt2,$xt3,&QWP(64*2-128,$inp)); + &vpxor ($xt3,$xa3,&QWP(64*3-128,$inp)); + &lea ($inp,&QWP($i<192?16:(64*4-16*3),$inp)); + &vmovdqa ($xa0,&QWP($i+16*4-128,"ebx")) if ($i<192); + &vmovdqa ($xa1,&QWP($i+16*5-128,"ebx")) if ($i<192); + &vmovdqa ($xa2,&QWP($i+16*6-128,"ebx")) if ($i<192); + &vmovdqa ($xa3,&QWP($i+16*7-128,"ebx")) if ($i<192); + &vmovdqu (&QWP(64*0-128,$out),$xt0); # store output + &vmovdqu (&QWP(64*1-128,$out),$xt1); + &vmovdqu (&QWP(64*2-128,$out),$xt2); + &vmovdqu (&QWP(64*3-128,$out),$xt3); + &lea ($out,&QWP($i<192?16:(64*4-16*3),$out)); + } + &sub ($len,64*4); + &jnc (&label("outer_loop")); + + &add ($len,64*4); + &jz (&label("done")); + + &mov ("ebx",&DWP(512+8,"esp")); # restore pointers + &lea ($inp,&DWP(-128,$inp)); + &mov ("edx",&DWP(512+4,"esp")); + &lea ($out,&DWP(-128,$out)); + + &vmovd ("xmm2",&DWP(16*12-128,"ebp")); # counter value + &vmovdqu ("xmm3",&QWP(0,"ebx")); + &vpaddd ("xmm2","xmm2",&QWP(16*6,"eax"));# +four + &vpand ("xmm3","xmm3",&QWP(16*7,"eax")); + &vpor ("xmm3","xmm3","xmm2"); # counter value +{ +my ($a,$b,$c,$d,$t,$t1,$rot16,$rot24)=map("xmm$_",(0..7)); + +sub XOPROUND { + &vpaddd ($a,$a,$b); + &vpxor ($d,$d,$a); + &vprotd ($d,$d,16); + + &vpaddd ($c,$c,$d); + &vpxor ($b,$b,$c); + &vprotd ($b,$b,12); + + &vpaddd ($a,$a,$b); + &vpxor ($d,$d,$a); + &vprotd ($d,$d,8); + + &vpaddd ($c,$c,$d); + &vpxor ($b,$b,$c); + &vprotd ($b,$b,7); +} + +&set_label("1x"); + &vmovdqa ($a,&QWP(16*2,"eax")); # sigma + &vmovdqu ($b,&QWP(0,"edx")); + &vmovdqu ($c,&QWP(16,"edx")); + #&vmovdqu ($d,&QWP(0,"ebx")); # already loaded + &vmovdqa ($rot16,&QWP(0,"eax")); + &vmovdqa ($rot24,&QWP(16,"eax")); + &mov (&DWP(16*3,"esp"),"ebp"); + + &vmovdqa (&QWP(16*0,"esp"),$a); + &vmovdqa (&QWP(16*1,"esp"),$b); + &vmovdqa (&QWP(16*2,"esp"),$c); + &vmovdqa (&QWP(16*3,"esp"),$d); + &mov ("edx",10); + &jmp (&label("loop1x")); + +&set_label("outer1x",16); + &vmovdqa ($d,&QWP(16*5,"eax")); # one + &vmovdqa ($a,&QWP(16*0,"esp")); + &vmovdqa ($b,&QWP(16*1,"esp")); + &vmovdqa ($c,&QWP(16*2,"esp")); + &vpaddd ($d,$d,&QWP(16*3,"esp")); + &mov ("edx",10); + &vmovdqa (&QWP(16*3,"esp"),$d); + &jmp (&label("loop1x")); + +&set_label("loop1x",16); + &XOPROUND(); + &vpshufd ($c,$c,0b01001110); + &vpshufd ($b,$b,0b00111001); + &vpshufd ($d,$d,0b10010011); + + &XOPROUND(); + &vpshufd ($c,$c,0b01001110); + &vpshufd ($b,$b,0b10010011); + &vpshufd ($d,$d,0b00111001); + + &dec ("edx"); + &jnz (&label("loop1x")); + + &vpaddd ($a,$a,&QWP(16*0,"esp")); + &vpaddd ($b,$b,&QWP(16*1,"esp")); + &vpaddd ($c,$c,&QWP(16*2,"esp")); + &vpaddd ($d,$d,&QWP(16*3,"esp")); + + &cmp ($len,64); + &jb (&label("tail")); + + &vpxor ($a,$a,&QWP(16*0,$inp)); # xor with input + &vpxor ($b,$b,&QWP(16*1,$inp)); + &vpxor ($c,$c,&QWP(16*2,$inp)); + &vpxor ($d,$d,&QWP(16*3,$inp)); + &lea ($inp,&DWP(16*4,$inp)); # inp+=64 + + &vmovdqu (&QWP(16*0,$out),$a); # write output + &vmovdqu (&QWP(16*1,$out),$b); + &vmovdqu (&QWP(16*2,$out),$c); + &vmovdqu (&QWP(16*3,$out),$d); + &lea ($out,&DWP(16*4,$out)); # inp+=64 + + &sub ($len,64); + &jnz (&label("outer1x")); + + &jmp (&label("done")); + +&set_label("tail"); + &vmovdqa (&QWP(16*0,"esp"),$a); + &vmovdqa (&QWP(16*1,"esp"),$b); + &vmovdqa (&QWP(16*2,"esp"),$c); + &vmovdqa (&QWP(16*3,"esp"),$d); + + &xor ("eax","eax"); + &xor ("edx","edx"); + &xor ("ebp","ebp"); + +&set_label("tail_loop"); + &movb ("al",&BP(0,"esp","ebp")); + &movb ("dl",&BP(0,$inp,"ebp")); + &lea ("ebp",&DWP(1,"ebp")); + &xor ("al","dl"); + &movb (&BP(-1,$out,"ebp"),"al"); + &dec ($len); + &jnz (&label("tail_loop")); +} +&set_label("done"); + &vzeroupper (); + &mov ("esp",&DWP(512,"esp")); +&function_end("ChaCha20_xop"); +} + +&asm_finish(); + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/chacha/asm/chacha-x86_64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/chacha/asm/chacha-x86_64.pl new file mode 100755 index 000000000..b54f3b152 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/chacha/asm/chacha-x86_64.pl @@ -0,0 +1,4005 @@ +#! /usr/bin/env perl +# Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# November 2014 +# +# ChaCha20 for x86_64. +# +# December 2016 +# +# Add AVX512F code path. +# +# December 2017 +# +# Add AVX512VL code path. +# +# Performance in cycles per byte out of large buffer. +# +# IALU/gcc 4.8(i) 1x/2xSSSE3(ii) 4xSSSE3 NxAVX(v) +# +# P4 9.48/+99% - - +# Core2 7.83/+55% 7.90/5.76 4.35 +# Westmere 7.19/+50% 5.60/4.50 3.00 +# Sandy Bridge 8.31/+42% 5.45/4.00 2.72 +# Ivy Bridge 6.71/+46% 5.40/? 2.41 +# Haswell 5.92/+43% 5.20/3.45 2.42 1.23 +# Skylake[-X] 5.87/+39% 4.70/3.22 2.31 1.19[0.80(vi)] +# Silvermont 12.0/+33% 7.75/6.90 7.03(iii) +# Knights L 11.7/- ? 9.60(iii) 0.80 +# Goldmont 10.6/+17% 5.10/3.52 3.28 +# Sledgehammer 7.28/+52% - - +# Bulldozer 9.66/+28% 9.85/5.35(iv) 3.06(iv) +# Ryzen 5.96/+50% 5.19/3.00 2.40 2.09 +# VIA Nano 10.5/+46% 6.72/6.88 6.05 +# +# (i) compared to older gcc 3.x one can observe >2x improvement on +# most platforms; +# (ii) 2xSSSE3 is code path optimized specifically for 128 bytes used +# by chacha20_poly1305_tls_cipher, results are EVP-free; +# (iii) this is not optimal result for Atom because of MSROM +# limitations, SSE2 can do better, but gain is considered too +# low to justify the [maintenance] effort; +# (iv) Bulldozer actually executes 4xXOP code path that delivers 2.20 +# and 4.85 for 128-byte inputs; +# (v) 8xAVX2, 8xAVX512VL or 16xAVX512F, whichever best applicable; +# (vi) even though Skylake-X can execute AVX512F code and deliver 0.57 +# cpb in single thread, the corresponding capability is suppressed; + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler version ([2-9]\.[0-9]+)/) { + $avx = ($1>=2.19) + ($1>=2.22) + ($1>=2.25); +} + +if (!$avx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) && + `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)(?:\.([0-9]+))?/) { + $avx = ($1>=2.09) + ($1>=2.10) + ($1>=2.12); + $avx += 1 if ($1==2.11 && $2>=8); +} + +if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && + `ml64 2>&1` =~ /Version ([0-9]+)\./) { + $avx = ($1>=10) + ($1>=11); +} + +if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9]\.[0-9]+)/) { + $avx = ($2>=3.0) + ($2>3.0); +} + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +*STDOUT=*OUT; + +# input parameter block +($out,$inp,$len,$key,$counter)=("%rdi","%rsi","%rdx","%rcx","%r8"); + +$code.=<<___; +.text + +.extern OPENSSL_ia32cap_P + +.align 64 +.Lzero: +.long 0,0,0,0 +.Lone: +.long 1,0,0,0 +.Linc: +.long 0,1,2,3 +.Lfour: +.long 4,4,4,4 +.Lincy: +.long 0,2,4,6,1,3,5,7 +.Leight: +.long 8,8,8,8,8,8,8,8 +.Lrot16: +.byte 0x2,0x3,0x0,0x1, 0x6,0x7,0x4,0x5, 0xa,0xb,0x8,0x9, 0xe,0xf,0xc,0xd +.Lrot24: +.byte 0x3,0x0,0x1,0x2, 0x7,0x4,0x5,0x6, 0xb,0x8,0x9,0xa, 0xf,0xc,0xd,0xe +.Ltwoy: +.long 2,0,0,0, 2,0,0,0 +.align 64 +.Lzeroz: +.long 0,0,0,0, 1,0,0,0, 2,0,0,0, 3,0,0,0 +.Lfourz: +.long 4,0,0,0, 4,0,0,0, 4,0,0,0, 4,0,0,0 +.Lincz: +.long 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 +.Lsixteen: +.long 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16 +.Lsigma: +.asciz "expand 32-byte k" +.asciz "ChaCha20 for x86_64, CRYPTOGAMS by " +___ + +sub AUTOLOAD() # thunk [simplified] 32-bit style perlasm +{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; + my $arg = pop; + $arg = "\$$arg" if ($arg*1 eq $arg); + $code .= "\t$opcode\t".join(',',$arg,reverse @_)."\n"; +} + +@x=("%eax","%ebx","%ecx","%edx",map("%r${_}d",(8..11)), + "%nox","%nox","%nox","%nox",map("%r${_}d",(12..15))); +@t=("%esi","%edi"); + +sub ROUND { # critical path is 24 cycles per round +my ($a0,$b0,$c0,$d0)=@_; +my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0)); +my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1)); +my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2)); +my ($xc,$xc_)=map("\"$_\"",@t); +my @x=map("\"$_\"",@x); + + # Consider order in which variables are addressed by their + # index: + # + # a b c d + # + # 0 4 8 12 < even round + # 1 5 9 13 + # 2 6 10 14 + # 3 7 11 15 + # 0 5 10 15 < odd round + # 1 6 11 12 + # 2 7 8 13 + # 3 4 9 14 + # + # 'a', 'b' and 'd's are permanently allocated in registers, + # @x[0..7,12..15], while 'c's are maintained in memory. If + # you observe 'c' column, you'll notice that pair of 'c's is + # invariant between rounds. This means that we have to reload + # them once per round, in the middle. This is why you'll see + # bunch of 'c' stores and loads in the middle, but none in + # the beginning or end. + + # Normally instructions would be interleaved to favour in-order + # execution. Generally out-of-order cores manage it gracefully, + # but not this time for some reason. As in-order execution + # cores are dying breed, old Atom is the only one around, + # instructions are left uninterleaved. Besides, Atom is better + # off executing 1xSSSE3 code anyway... + + ( + "&add (@x[$a0],@x[$b0])", # Q1 + "&xor (@x[$d0],@x[$a0])", + "&rol (@x[$d0],16)", + "&add (@x[$a1],@x[$b1])", # Q2 + "&xor (@x[$d1],@x[$a1])", + "&rol (@x[$d1],16)", + + "&add ($xc,@x[$d0])", + "&xor (@x[$b0],$xc)", + "&rol (@x[$b0],12)", + "&add ($xc_,@x[$d1])", + "&xor (@x[$b1],$xc_)", + "&rol (@x[$b1],12)", + + "&add (@x[$a0],@x[$b0])", + "&xor (@x[$d0],@x[$a0])", + "&rol (@x[$d0],8)", + "&add (@x[$a1],@x[$b1])", + "&xor (@x[$d1],@x[$a1])", + "&rol (@x[$d1],8)", + + "&add ($xc,@x[$d0])", + "&xor (@x[$b0],$xc)", + "&rol (@x[$b0],7)", + "&add ($xc_,@x[$d1])", + "&xor (@x[$b1],$xc_)", + "&rol (@x[$b1],7)", + + "&mov (\"4*$c0(%rsp)\",$xc)", # reload pair of 'c's + "&mov (\"4*$c1(%rsp)\",$xc_)", + "&mov ($xc,\"4*$c2(%rsp)\")", + "&mov ($xc_,\"4*$c3(%rsp)\")", + + "&add (@x[$a2],@x[$b2])", # Q3 + "&xor (@x[$d2],@x[$a2])", + "&rol (@x[$d2],16)", + "&add (@x[$a3],@x[$b3])", # Q4 + "&xor (@x[$d3],@x[$a3])", + "&rol (@x[$d3],16)", + + "&add ($xc,@x[$d2])", + "&xor (@x[$b2],$xc)", + "&rol (@x[$b2],12)", + "&add ($xc_,@x[$d3])", + "&xor (@x[$b3],$xc_)", + "&rol (@x[$b3],12)", + + "&add (@x[$a2],@x[$b2])", + "&xor (@x[$d2],@x[$a2])", + "&rol (@x[$d2],8)", + "&add (@x[$a3],@x[$b3])", + "&xor (@x[$d3],@x[$a3])", + "&rol (@x[$d3],8)", + + "&add ($xc,@x[$d2])", + "&xor (@x[$b2],$xc)", + "&rol (@x[$b2],7)", + "&add ($xc_,@x[$d3])", + "&xor (@x[$b3],$xc_)", + "&rol (@x[$b3],7)" + ); +} + +######################################################################## +# Generic code path that handles all lengths on pre-SSSE3 processors. +$code.=<<___; +.globl ChaCha20_ctr32 +.type ChaCha20_ctr32,\@function,5 +.align 64 +ChaCha20_ctr32: +.cfi_startproc + cmp \$0,$len + je .Lno_data + mov OPENSSL_ia32cap_P+4(%rip),%r10 +___ +$code.=<<___ if ($avx>2); + bt \$48,%r10 # check for AVX512F + jc .LChaCha20_avx512 + test %r10,%r10 # check for AVX512VL + js .LChaCha20_avx512vl +___ +$code.=<<___; + test \$`1<<(41-32)`,%r10d + jnz .LChaCha20_ssse3 + + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + sub \$64+24,%rsp +.cfi_adjust_cfa_offset 64+24 +.Lctr32_body: + + #movdqa .Lsigma(%rip),%xmm0 + movdqu ($key),%xmm1 + movdqu 16($key),%xmm2 + movdqu ($counter),%xmm3 + movdqa .Lone(%rip),%xmm4 + + #movdqa %xmm0,4*0(%rsp) # key[0] + movdqa %xmm1,4*4(%rsp) # key[1] + movdqa %xmm2,4*8(%rsp) # key[2] + movdqa %xmm3,4*12(%rsp) # key[3] + mov $len,%rbp # reassign $len + jmp .Loop_outer + +.align 32 +.Loop_outer: + mov \$0x61707865,@x[0] # 'expa' + mov \$0x3320646e,@x[1] # 'nd 3' + mov \$0x79622d32,@x[2] # '2-by' + mov \$0x6b206574,@x[3] # 'te k' + mov 4*4(%rsp),@x[4] + mov 4*5(%rsp),@x[5] + mov 4*6(%rsp),@x[6] + mov 4*7(%rsp),@x[7] + movd %xmm3,@x[12] + mov 4*13(%rsp),@x[13] + mov 4*14(%rsp),@x[14] + mov 4*15(%rsp),@x[15] + + mov %rbp,64+0(%rsp) # save len + mov \$10,%ebp + mov $inp,64+8(%rsp) # save inp + movq %xmm2,%rsi # "@x[8]" + mov $out,64+16(%rsp) # save out + mov %rsi,%rdi + shr \$32,%rdi # "@x[9]" + jmp .Loop + +.align 32 +.Loop: +___ + foreach (&ROUND (0, 4, 8,12)) { eval; } + foreach (&ROUND (0, 5,10,15)) { eval; } + &dec ("%ebp"); + &jnz (".Loop"); + +$code.=<<___; + mov @t[1],4*9(%rsp) # modulo-scheduled + mov @t[0],4*8(%rsp) + mov 64(%rsp),%rbp # load len + movdqa %xmm2,%xmm1 + mov 64+8(%rsp),$inp # load inp + paddd %xmm4,%xmm3 # increment counter + mov 64+16(%rsp),$out # load out + + add \$0x61707865,@x[0] # 'expa' + add \$0x3320646e,@x[1] # 'nd 3' + add \$0x79622d32,@x[2] # '2-by' + add \$0x6b206574,@x[3] # 'te k' + add 4*4(%rsp),@x[4] + add 4*5(%rsp),@x[5] + add 4*6(%rsp),@x[6] + add 4*7(%rsp),@x[7] + add 4*12(%rsp),@x[12] + add 4*13(%rsp),@x[13] + add 4*14(%rsp),@x[14] + add 4*15(%rsp),@x[15] + paddd 4*8(%rsp),%xmm1 + + cmp \$64,%rbp + jb .Ltail + + xor 4*0($inp),@x[0] # xor with input + xor 4*1($inp),@x[1] + xor 4*2($inp),@x[2] + xor 4*3($inp),@x[3] + xor 4*4($inp),@x[4] + xor 4*5($inp),@x[5] + xor 4*6($inp),@x[6] + xor 4*7($inp),@x[7] + movdqu 4*8($inp),%xmm0 + xor 4*12($inp),@x[12] + xor 4*13($inp),@x[13] + xor 4*14($inp),@x[14] + xor 4*15($inp),@x[15] + lea 4*16($inp),$inp # inp+=64 + pxor %xmm1,%xmm0 + + movdqa %xmm2,4*8(%rsp) + movd %xmm3,4*12(%rsp) + + mov @x[0],4*0($out) # write output + mov @x[1],4*1($out) + mov @x[2],4*2($out) + mov @x[3],4*3($out) + mov @x[4],4*4($out) + mov @x[5],4*5($out) + mov @x[6],4*6($out) + mov @x[7],4*7($out) + movdqu %xmm0,4*8($out) + mov @x[12],4*12($out) + mov @x[13],4*13($out) + mov @x[14],4*14($out) + mov @x[15],4*15($out) + lea 4*16($out),$out # out+=64 + + sub \$64,%rbp + jnz .Loop_outer + + jmp .Ldone + +.align 16 +.Ltail: + mov @x[0],4*0(%rsp) + mov @x[1],4*1(%rsp) + xor %rbx,%rbx + mov @x[2],4*2(%rsp) + mov @x[3],4*3(%rsp) + mov @x[4],4*4(%rsp) + mov @x[5],4*5(%rsp) + mov @x[6],4*6(%rsp) + mov @x[7],4*7(%rsp) + movdqa %xmm1,4*8(%rsp) + mov @x[12],4*12(%rsp) + mov @x[13],4*13(%rsp) + mov @x[14],4*14(%rsp) + mov @x[15],4*15(%rsp) + +.Loop_tail: + movzb ($inp,%rbx),%eax + movzb (%rsp,%rbx),%edx + lea 1(%rbx),%rbx + xor %edx,%eax + mov %al,-1($out,%rbx) + dec %rbp + jnz .Loop_tail + +.Ldone: + lea 64+24+48(%rsp),%rsi +.cfi_def_cfa %rsi,8 + mov -48(%rsi),%r15 +.cfi_restore %r15 + mov -40(%rsi),%r14 +.cfi_restore %r14 + mov -32(%rsi),%r13 +.cfi_restore %r13 + mov -24(%rsi),%r12 +.cfi_restore %r12 + mov -16(%rsi),%rbp +.cfi_restore %rbp + mov -8(%rsi),%rbx +.cfi_restore %rbx + lea (%rsi),%rsp +.cfi_def_cfa_register %rsp +.Lno_data: + ret +.cfi_endproc +.size ChaCha20_ctr32,.-ChaCha20_ctr32 +___ + +######################################################################## +# SSSE3 code path that handles shorter lengths +{ +my ($a,$b,$c,$d,$t,$t1,$rot16,$rot24)=map("%xmm$_",(0..7)); + +sub SSSE3ROUND { # critical path is 20 "SIMD ticks" per round + &paddd ($a,$b); + &pxor ($d,$a); + &pshufb ($d,$rot16); + + &paddd ($c,$d); + &pxor ($b,$c); + &movdqa ($t,$b); + &psrld ($b,20); + &pslld ($t,12); + &por ($b,$t); + + &paddd ($a,$b); + &pxor ($d,$a); + &pshufb ($d,$rot24); + + &paddd ($c,$d); + &pxor ($b,$c); + &movdqa ($t,$b); + &psrld ($b,25); + &pslld ($t,7); + &por ($b,$t); +} + +my $xframe = $win64 ? 32+8 : 8; + +$code.=<<___; +.type ChaCha20_ssse3,\@function,5 +.align 32 +ChaCha20_ssse3: +.cfi_startproc +.LChaCha20_ssse3: + mov %rsp,%r9 # frame pointer +.cfi_def_cfa_register %r9 +___ +$code.=<<___ if ($avx); + test \$`1<<(43-32)`,%r10d + jnz .LChaCha20_4xop # XOP is fastest even if we use 1/4 +___ +$code.=<<___; + cmp \$128,$len # we might throw away some data, + je .LChaCha20_128 + ja .LChaCha20_4x # but overall it won't be slower + +.Ldo_sse3_after_all: + sub \$64+$xframe,%rsp +___ +$code.=<<___ if ($win64); + movaps %xmm6,-0x28(%r9) + movaps %xmm7,-0x18(%r9) +.Lssse3_body: +___ +$code.=<<___; + movdqa .Lsigma(%rip),$a + movdqu ($key),$b + movdqu 16($key),$c + movdqu ($counter),$d + movdqa .Lrot16(%rip),$rot16 + movdqa .Lrot24(%rip),$rot24 + + movdqa $a,0x00(%rsp) + movdqa $b,0x10(%rsp) + movdqa $c,0x20(%rsp) + movdqa $d,0x30(%rsp) + mov \$10,$counter # reuse $counter + jmp .Loop_ssse3 + +.align 32 +.Loop_outer_ssse3: + movdqa .Lone(%rip),$d + movdqa 0x00(%rsp),$a + movdqa 0x10(%rsp),$b + movdqa 0x20(%rsp),$c + paddd 0x30(%rsp),$d + mov \$10,$counter + movdqa $d,0x30(%rsp) + jmp .Loop_ssse3 + +.align 32 +.Loop_ssse3: +___ + &SSSE3ROUND(); + &pshufd ($c,$c,0b01001110); + &pshufd ($b,$b,0b00111001); + &pshufd ($d,$d,0b10010011); + &nop (); + + &SSSE3ROUND(); + &pshufd ($c,$c,0b01001110); + &pshufd ($b,$b,0b10010011); + &pshufd ($d,$d,0b00111001); + + &dec ($counter); + &jnz (".Loop_ssse3"); + +$code.=<<___; + paddd 0x00(%rsp),$a + paddd 0x10(%rsp),$b + paddd 0x20(%rsp),$c + paddd 0x30(%rsp),$d + + cmp \$64,$len + jb .Ltail_ssse3 + + movdqu 0x00($inp),$t + movdqu 0x10($inp),$t1 + pxor $t,$a # xor with input + movdqu 0x20($inp),$t + pxor $t1,$b + movdqu 0x30($inp),$t1 + lea 0x40($inp),$inp # inp+=64 + pxor $t,$c + pxor $t1,$d + + movdqu $a,0x00($out) # write output + movdqu $b,0x10($out) + movdqu $c,0x20($out) + movdqu $d,0x30($out) + lea 0x40($out),$out # out+=64 + + sub \$64,$len + jnz .Loop_outer_ssse3 + + jmp .Ldone_ssse3 + +.align 16 +.Ltail_ssse3: + movdqa $a,0x00(%rsp) + movdqa $b,0x10(%rsp) + movdqa $c,0x20(%rsp) + movdqa $d,0x30(%rsp) + xor $counter,$counter + +.Loop_tail_ssse3: + movzb ($inp,$counter),%eax + movzb (%rsp,$counter),%ecx + lea 1($counter),$counter + xor %ecx,%eax + mov %al,-1($out,$counter) + dec $len + jnz .Loop_tail_ssse3 + +.Ldone_ssse3: +___ +$code.=<<___ if ($win64); + movaps -0x28(%r9),%xmm6 + movaps -0x18(%r9),%xmm7 +___ +$code.=<<___; + lea (%r9),%rsp +.cfi_def_cfa_register %rsp +.Lssse3_epilogue: + ret +.cfi_endproc +.size ChaCha20_ssse3,.-ChaCha20_ssse3 +___ +} + +######################################################################## +# SSSE3 code path that handles 128-byte inputs +{ +my ($a,$b,$c,$d,$t,$t1,$rot16,$rot24)=map("%xmm$_",(8,9,2..7)); +my ($a1,$b1,$c1,$d1)=map("%xmm$_",(10,11,0,1)); + +sub SSSE3ROUND_2x { + &paddd ($a,$b); + &pxor ($d,$a); + &paddd ($a1,$b1); + &pxor ($d1,$a1); + &pshufb ($d,$rot16); + &pshufb($d1,$rot16); + + &paddd ($c,$d); + &paddd ($c1,$d1); + &pxor ($b,$c); + &pxor ($b1,$c1); + &movdqa ($t,$b); + &psrld ($b,20); + &movdqa($t1,$b1); + &pslld ($t,12); + &psrld ($b1,20); + &por ($b,$t); + &pslld ($t1,12); + &por ($b1,$t1); + + &paddd ($a,$b); + &pxor ($d,$a); + &paddd ($a1,$b1); + &pxor ($d1,$a1); + &pshufb ($d,$rot24); + &pshufb($d1,$rot24); + + &paddd ($c,$d); + &paddd ($c1,$d1); + &pxor ($b,$c); + &pxor ($b1,$c1); + &movdqa ($t,$b); + &psrld ($b,25); + &movdqa($t1,$b1); + &pslld ($t,7); + &psrld ($b1,25); + &por ($b,$t); + &pslld ($t1,7); + &por ($b1,$t1); +} + +my $xframe = $win64 ? 0x68 : 8; + +$code.=<<___; +.type ChaCha20_128,\@function,5 +.align 32 +ChaCha20_128: +.cfi_startproc +.LChaCha20_128: + mov %rsp,%r9 # frame pointer +.cfi_def_cfa_register %r9 + sub \$64+$xframe,%rsp +___ +$code.=<<___ if ($win64); + movaps %xmm6,-0x68(%r9) + movaps %xmm7,-0x58(%r9) + movaps %xmm8,-0x48(%r9) + movaps %xmm9,-0x38(%r9) + movaps %xmm10,-0x28(%r9) + movaps %xmm11,-0x18(%r9) +.L128_body: +___ +$code.=<<___; + movdqa .Lsigma(%rip),$a + movdqu ($key),$b + movdqu 16($key),$c + movdqu ($counter),$d + movdqa .Lone(%rip),$d1 + movdqa .Lrot16(%rip),$rot16 + movdqa .Lrot24(%rip),$rot24 + + movdqa $a,$a1 + movdqa $a,0x00(%rsp) + movdqa $b,$b1 + movdqa $b,0x10(%rsp) + movdqa $c,$c1 + movdqa $c,0x20(%rsp) + paddd $d,$d1 + movdqa $d,0x30(%rsp) + mov \$10,$counter # reuse $counter + jmp .Loop_128 + +.align 32 +.Loop_128: +___ + &SSSE3ROUND_2x(); + &pshufd ($c,$c,0b01001110); + &pshufd ($b,$b,0b00111001); + &pshufd ($d,$d,0b10010011); + &pshufd ($c1,$c1,0b01001110); + &pshufd ($b1,$b1,0b00111001); + &pshufd ($d1,$d1,0b10010011); + + &SSSE3ROUND_2x(); + &pshufd ($c,$c,0b01001110); + &pshufd ($b,$b,0b10010011); + &pshufd ($d,$d,0b00111001); + &pshufd ($c1,$c1,0b01001110); + &pshufd ($b1,$b1,0b10010011); + &pshufd ($d1,$d1,0b00111001); + + &dec ($counter); + &jnz (".Loop_128"); + +$code.=<<___; + paddd 0x00(%rsp),$a + paddd 0x10(%rsp),$b + paddd 0x20(%rsp),$c + paddd 0x30(%rsp),$d + paddd .Lone(%rip),$d1 + paddd 0x00(%rsp),$a1 + paddd 0x10(%rsp),$b1 + paddd 0x20(%rsp),$c1 + paddd 0x30(%rsp),$d1 + + movdqu 0x00($inp),$t + movdqu 0x10($inp),$t1 + pxor $t,$a # xor with input + movdqu 0x20($inp),$t + pxor $t1,$b + movdqu 0x30($inp),$t1 + pxor $t,$c + movdqu 0x40($inp),$t + pxor $t1,$d + movdqu 0x50($inp),$t1 + pxor $t,$a1 + movdqu 0x60($inp),$t + pxor $t1,$b1 + movdqu 0x70($inp),$t1 + pxor $t,$c1 + pxor $t1,$d1 + + movdqu $a,0x00($out) # write output + movdqu $b,0x10($out) + movdqu $c,0x20($out) + movdqu $d,0x30($out) + movdqu $a1,0x40($out) + movdqu $b1,0x50($out) + movdqu $c1,0x60($out) + movdqu $d1,0x70($out) +___ +$code.=<<___ if ($win64); + movaps -0x68(%r9),%xmm6 + movaps -0x58(%r9),%xmm7 + movaps -0x48(%r9),%xmm8 + movaps -0x38(%r9),%xmm9 + movaps -0x28(%r9),%xmm10 + movaps -0x18(%r9),%xmm11 +___ +$code.=<<___; + lea (%r9),%rsp +.cfi_def_cfa_register %rsp +.L128_epilogue: + ret +.cfi_endproc +.size ChaCha20_128,.-ChaCha20_128 +___ +} + +######################################################################## +# SSSE3 code path that handles longer messages. +{ +# assign variables to favor Atom front-end +my ($xd0,$xd1,$xd2,$xd3, $xt0,$xt1,$xt2,$xt3, + $xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3)=map("%xmm$_",(0..15)); +my @xx=($xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3, + "%nox","%nox","%nox","%nox", $xd0,$xd1,$xd2,$xd3); + +sub SSSE3_lane_ROUND { +my ($a0,$b0,$c0,$d0)=@_; +my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0)); +my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1)); +my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2)); +my ($xc,$xc_,$t0,$t1)=map("\"$_\"",$xt0,$xt1,$xt2,$xt3); +my @x=map("\"$_\"",@xx); + + # Consider order in which variables are addressed by their + # index: + # + # a b c d + # + # 0 4 8 12 < even round + # 1 5 9 13 + # 2 6 10 14 + # 3 7 11 15 + # 0 5 10 15 < odd round + # 1 6 11 12 + # 2 7 8 13 + # 3 4 9 14 + # + # 'a', 'b' and 'd's are permanently allocated in registers, + # @x[0..7,12..15], while 'c's are maintained in memory. If + # you observe 'c' column, you'll notice that pair of 'c's is + # invariant between rounds. This means that we have to reload + # them once per round, in the middle. This is why you'll see + # bunch of 'c' stores and loads in the middle, but none in + # the beginning or end. + + ( + "&paddd (@x[$a0],@x[$b0])", # Q1 + "&paddd (@x[$a1],@x[$b1])", # Q2 + "&pxor (@x[$d0],@x[$a0])", + "&pxor (@x[$d1],@x[$a1])", + "&pshufb (@x[$d0],$t1)", + "&pshufb (@x[$d1],$t1)", + + "&paddd ($xc,@x[$d0])", + "&paddd ($xc_,@x[$d1])", + "&pxor (@x[$b0],$xc)", + "&pxor (@x[$b1],$xc_)", + "&movdqa ($t0,@x[$b0])", + "&pslld (@x[$b0],12)", + "&psrld ($t0,20)", + "&movdqa ($t1,@x[$b1])", + "&pslld (@x[$b1],12)", + "&por (@x[$b0],$t0)", + "&psrld ($t1,20)", + "&movdqa ($t0,'(%r11)')", # .Lrot24(%rip) + "&por (@x[$b1],$t1)", + + "&paddd (@x[$a0],@x[$b0])", + "&paddd (@x[$a1],@x[$b1])", + "&pxor (@x[$d0],@x[$a0])", + "&pxor (@x[$d1],@x[$a1])", + "&pshufb (@x[$d0],$t0)", + "&pshufb (@x[$d1],$t0)", + + "&paddd ($xc,@x[$d0])", + "&paddd ($xc_,@x[$d1])", + "&pxor (@x[$b0],$xc)", + "&pxor (@x[$b1],$xc_)", + "&movdqa ($t1,@x[$b0])", + "&pslld (@x[$b0],7)", + "&psrld ($t1,25)", + "&movdqa ($t0,@x[$b1])", + "&pslld (@x[$b1],7)", + "&por (@x[$b0],$t1)", + "&psrld ($t0,25)", + "&movdqa ($t1,'(%r10)')", # .Lrot16(%rip) + "&por (@x[$b1],$t0)", + + "&movdqa (\"`16*($c0-8)`(%rsp)\",$xc)", # reload pair of 'c's + "&movdqa (\"`16*($c1-8)`(%rsp)\",$xc_)", + "&movdqa ($xc,\"`16*($c2-8)`(%rsp)\")", + "&movdqa ($xc_,\"`16*($c3-8)`(%rsp)\")", + + "&paddd (@x[$a2],@x[$b2])", # Q3 + "&paddd (@x[$a3],@x[$b3])", # Q4 + "&pxor (@x[$d2],@x[$a2])", + "&pxor (@x[$d3],@x[$a3])", + "&pshufb (@x[$d2],$t1)", + "&pshufb (@x[$d3],$t1)", + + "&paddd ($xc,@x[$d2])", + "&paddd ($xc_,@x[$d3])", + "&pxor (@x[$b2],$xc)", + "&pxor (@x[$b3],$xc_)", + "&movdqa ($t0,@x[$b2])", + "&pslld (@x[$b2],12)", + "&psrld ($t0,20)", + "&movdqa ($t1,@x[$b3])", + "&pslld (@x[$b3],12)", + "&por (@x[$b2],$t0)", + "&psrld ($t1,20)", + "&movdqa ($t0,'(%r11)')", # .Lrot24(%rip) + "&por (@x[$b3],$t1)", + + "&paddd (@x[$a2],@x[$b2])", + "&paddd (@x[$a3],@x[$b3])", + "&pxor (@x[$d2],@x[$a2])", + "&pxor (@x[$d3],@x[$a3])", + "&pshufb (@x[$d2],$t0)", + "&pshufb (@x[$d3],$t0)", + + "&paddd ($xc,@x[$d2])", + "&paddd ($xc_,@x[$d3])", + "&pxor (@x[$b2],$xc)", + "&pxor (@x[$b3],$xc_)", + "&movdqa ($t1,@x[$b2])", + "&pslld (@x[$b2],7)", + "&psrld ($t1,25)", + "&movdqa ($t0,@x[$b3])", + "&pslld (@x[$b3],7)", + "&por (@x[$b2],$t1)", + "&psrld ($t0,25)", + "&movdqa ($t1,'(%r10)')", # .Lrot16(%rip) + "&por (@x[$b3],$t0)" + ); +} + +my $xframe = $win64 ? 0xa8 : 8; + +$code.=<<___; +.type ChaCha20_4x,\@function,5 +.align 32 +ChaCha20_4x: +.cfi_startproc +.LChaCha20_4x: + mov %rsp,%r9 # frame pointer +.cfi_def_cfa_register %r9 + mov %r10,%r11 +___ +$code.=<<___ if ($avx>1); + shr \$32,%r10 # OPENSSL_ia32cap_P+8 + test \$`1<<5`,%r10 # test AVX2 + jnz .LChaCha20_8x +___ +$code.=<<___; + cmp \$192,$len + ja .Lproceed4x + + and \$`1<<26|1<<22`,%r11 # isolate XSAVE+MOVBE + cmp \$`1<<22`,%r11 # check for MOVBE without XSAVE + je .Ldo_sse3_after_all # to detect Atom + +.Lproceed4x: + sub \$0x140+$xframe,%rsp +___ + ################ stack layout + # +0x00 SIMD equivalent of @x[8-12] + # ... + # +0x40 constant copy of key[0-2] smashed by lanes + # ... + # +0x100 SIMD counters (with nonce smashed by lanes) + # ... + # +0x140 +$code.=<<___ if ($win64); + movaps %xmm6,-0xa8(%r9) + movaps %xmm7,-0x98(%r9) + movaps %xmm8,-0x88(%r9) + movaps %xmm9,-0x78(%r9) + movaps %xmm10,-0x68(%r9) + movaps %xmm11,-0x58(%r9) + movaps %xmm12,-0x48(%r9) + movaps %xmm13,-0x38(%r9) + movaps %xmm14,-0x28(%r9) + movaps %xmm15,-0x18(%r9) +.L4x_body: +___ +$code.=<<___; + movdqa .Lsigma(%rip),$xa3 # key[0] + movdqu ($key),$xb3 # key[1] + movdqu 16($key),$xt3 # key[2] + movdqu ($counter),$xd3 # key[3] + lea 0x100(%rsp),%rcx # size optimization + lea .Lrot16(%rip),%r10 + lea .Lrot24(%rip),%r11 + + pshufd \$0x00,$xa3,$xa0 # smash key by lanes... + pshufd \$0x55,$xa3,$xa1 + movdqa $xa0,0x40(%rsp) # ... and offload + pshufd \$0xaa,$xa3,$xa2 + movdqa $xa1,0x50(%rsp) + pshufd \$0xff,$xa3,$xa3 + movdqa $xa2,0x60(%rsp) + movdqa $xa3,0x70(%rsp) + + pshufd \$0x00,$xb3,$xb0 + pshufd \$0x55,$xb3,$xb1 + movdqa $xb0,0x80-0x100(%rcx) + pshufd \$0xaa,$xb3,$xb2 + movdqa $xb1,0x90-0x100(%rcx) + pshufd \$0xff,$xb3,$xb3 + movdqa $xb2,0xa0-0x100(%rcx) + movdqa $xb3,0xb0-0x100(%rcx) + + pshufd \$0x00,$xt3,$xt0 # "$xc0" + pshufd \$0x55,$xt3,$xt1 # "$xc1" + movdqa $xt0,0xc0-0x100(%rcx) + pshufd \$0xaa,$xt3,$xt2 # "$xc2" + movdqa $xt1,0xd0-0x100(%rcx) + pshufd \$0xff,$xt3,$xt3 # "$xc3" + movdqa $xt2,0xe0-0x100(%rcx) + movdqa $xt3,0xf0-0x100(%rcx) + + pshufd \$0x00,$xd3,$xd0 + pshufd \$0x55,$xd3,$xd1 + paddd .Linc(%rip),$xd0 # don't save counters yet + pshufd \$0xaa,$xd3,$xd2 + movdqa $xd1,0x110-0x100(%rcx) + pshufd \$0xff,$xd3,$xd3 + movdqa $xd2,0x120-0x100(%rcx) + movdqa $xd3,0x130-0x100(%rcx) + + jmp .Loop_enter4x + +.align 32 +.Loop_outer4x: + movdqa 0x40(%rsp),$xa0 # re-load smashed key + movdqa 0x50(%rsp),$xa1 + movdqa 0x60(%rsp),$xa2 + movdqa 0x70(%rsp),$xa3 + movdqa 0x80-0x100(%rcx),$xb0 + movdqa 0x90-0x100(%rcx),$xb1 + movdqa 0xa0-0x100(%rcx),$xb2 + movdqa 0xb0-0x100(%rcx),$xb3 + movdqa 0xc0-0x100(%rcx),$xt0 # "$xc0" + movdqa 0xd0-0x100(%rcx),$xt1 # "$xc1" + movdqa 0xe0-0x100(%rcx),$xt2 # "$xc2" + movdqa 0xf0-0x100(%rcx),$xt3 # "$xc3" + movdqa 0x100-0x100(%rcx),$xd0 + movdqa 0x110-0x100(%rcx),$xd1 + movdqa 0x120-0x100(%rcx),$xd2 + movdqa 0x130-0x100(%rcx),$xd3 + paddd .Lfour(%rip),$xd0 # next SIMD counters + +.Loop_enter4x: + movdqa $xt2,0x20(%rsp) # SIMD equivalent of "@x[10]" + movdqa $xt3,0x30(%rsp) # SIMD equivalent of "@x[11]" + movdqa (%r10),$xt3 # .Lrot16(%rip) + mov \$10,%eax + movdqa $xd0,0x100-0x100(%rcx) # save SIMD counters + jmp .Loop4x + +.align 32 +.Loop4x: +___ + foreach (&SSSE3_lane_ROUND(0, 4, 8,12)) { eval; } + foreach (&SSSE3_lane_ROUND(0, 5,10,15)) { eval; } +$code.=<<___; + dec %eax + jnz .Loop4x + + paddd 0x40(%rsp),$xa0 # accumulate key material + paddd 0x50(%rsp),$xa1 + paddd 0x60(%rsp),$xa2 + paddd 0x70(%rsp),$xa3 + + movdqa $xa0,$xt2 # "de-interlace" data + punpckldq $xa1,$xa0 + movdqa $xa2,$xt3 + punpckldq $xa3,$xa2 + punpckhdq $xa1,$xt2 + punpckhdq $xa3,$xt3 + movdqa $xa0,$xa1 + punpcklqdq $xa2,$xa0 # "a0" + movdqa $xt2,$xa3 + punpcklqdq $xt3,$xt2 # "a2" + punpckhqdq $xa2,$xa1 # "a1" + punpckhqdq $xt3,$xa3 # "a3" +___ + ($xa2,$xt2)=($xt2,$xa2); +$code.=<<___; + paddd 0x80-0x100(%rcx),$xb0 + paddd 0x90-0x100(%rcx),$xb1 + paddd 0xa0-0x100(%rcx),$xb2 + paddd 0xb0-0x100(%rcx),$xb3 + + movdqa $xa0,0x00(%rsp) # offload $xaN + movdqa $xa1,0x10(%rsp) + movdqa 0x20(%rsp),$xa0 # "xc2" + movdqa 0x30(%rsp),$xa1 # "xc3" + + movdqa $xb0,$xt2 + punpckldq $xb1,$xb0 + movdqa $xb2,$xt3 + punpckldq $xb3,$xb2 + punpckhdq $xb1,$xt2 + punpckhdq $xb3,$xt3 + movdqa $xb0,$xb1 + punpcklqdq $xb2,$xb0 # "b0" + movdqa $xt2,$xb3 + punpcklqdq $xt3,$xt2 # "b2" + punpckhqdq $xb2,$xb1 # "b1" + punpckhqdq $xt3,$xb3 # "b3" +___ + ($xb2,$xt2)=($xt2,$xb2); + my ($xc0,$xc1,$xc2,$xc3)=($xt0,$xt1,$xa0,$xa1); +$code.=<<___; + paddd 0xc0-0x100(%rcx),$xc0 + paddd 0xd0-0x100(%rcx),$xc1 + paddd 0xe0-0x100(%rcx),$xc2 + paddd 0xf0-0x100(%rcx),$xc3 + + movdqa $xa2,0x20(%rsp) # keep offloading $xaN + movdqa $xa3,0x30(%rsp) + + movdqa $xc0,$xt2 + punpckldq $xc1,$xc0 + movdqa $xc2,$xt3 + punpckldq $xc3,$xc2 + punpckhdq $xc1,$xt2 + punpckhdq $xc3,$xt3 + movdqa $xc0,$xc1 + punpcklqdq $xc2,$xc0 # "c0" + movdqa $xt2,$xc3 + punpcklqdq $xt3,$xt2 # "c2" + punpckhqdq $xc2,$xc1 # "c1" + punpckhqdq $xt3,$xc3 # "c3" +___ + ($xc2,$xt2)=($xt2,$xc2); + ($xt0,$xt1)=($xa2,$xa3); # use $xaN as temporary +$code.=<<___; + paddd 0x100-0x100(%rcx),$xd0 + paddd 0x110-0x100(%rcx),$xd1 + paddd 0x120-0x100(%rcx),$xd2 + paddd 0x130-0x100(%rcx),$xd3 + + movdqa $xd0,$xt2 + punpckldq $xd1,$xd0 + movdqa $xd2,$xt3 + punpckldq $xd3,$xd2 + punpckhdq $xd1,$xt2 + punpckhdq $xd3,$xt3 + movdqa $xd0,$xd1 + punpcklqdq $xd2,$xd0 # "d0" + movdqa $xt2,$xd3 + punpcklqdq $xt3,$xt2 # "d2" + punpckhqdq $xd2,$xd1 # "d1" + punpckhqdq $xt3,$xd3 # "d3" +___ + ($xd2,$xt2)=($xt2,$xd2); +$code.=<<___; + cmp \$64*4,$len + jb .Ltail4x + + movdqu 0x00($inp),$xt0 # xor with input + movdqu 0x10($inp),$xt1 + movdqu 0x20($inp),$xt2 + movdqu 0x30($inp),$xt3 + pxor 0x00(%rsp),$xt0 # $xaN is offloaded, remember? + pxor $xb0,$xt1 + pxor $xc0,$xt2 + pxor $xd0,$xt3 + + movdqu $xt0,0x00($out) + movdqu 0x40($inp),$xt0 + movdqu $xt1,0x10($out) + movdqu 0x50($inp),$xt1 + movdqu $xt2,0x20($out) + movdqu 0x60($inp),$xt2 + movdqu $xt3,0x30($out) + movdqu 0x70($inp),$xt3 + lea 0x80($inp),$inp # size optimization + pxor 0x10(%rsp),$xt0 + pxor $xb1,$xt1 + pxor $xc1,$xt2 + pxor $xd1,$xt3 + + movdqu $xt0,0x40($out) + movdqu 0x00($inp),$xt0 + movdqu $xt1,0x50($out) + movdqu 0x10($inp),$xt1 + movdqu $xt2,0x60($out) + movdqu 0x20($inp),$xt2 + movdqu $xt3,0x70($out) + lea 0x80($out),$out # size optimization + movdqu 0x30($inp),$xt3 + pxor 0x20(%rsp),$xt0 + pxor $xb2,$xt1 + pxor $xc2,$xt2 + pxor $xd2,$xt3 + + movdqu $xt0,0x00($out) + movdqu 0x40($inp),$xt0 + movdqu $xt1,0x10($out) + movdqu 0x50($inp),$xt1 + movdqu $xt2,0x20($out) + movdqu 0x60($inp),$xt2 + movdqu $xt3,0x30($out) + movdqu 0x70($inp),$xt3 + lea 0x80($inp),$inp # inp+=64*4 + pxor 0x30(%rsp),$xt0 + pxor $xb3,$xt1 + pxor $xc3,$xt2 + pxor $xd3,$xt3 + movdqu $xt0,0x40($out) + movdqu $xt1,0x50($out) + movdqu $xt2,0x60($out) + movdqu $xt3,0x70($out) + lea 0x80($out),$out # out+=64*4 + + sub \$64*4,$len + jnz .Loop_outer4x + + jmp .Ldone4x + +.Ltail4x: + cmp \$192,$len + jae .L192_or_more4x + cmp \$128,$len + jae .L128_or_more4x + cmp \$64,$len + jae .L64_or_more4x + + #movdqa 0x00(%rsp),$xt0 # $xaN is offloaded, remember? + xor %r10,%r10 + #movdqa $xt0,0x00(%rsp) + movdqa $xb0,0x10(%rsp) + movdqa $xc0,0x20(%rsp) + movdqa $xd0,0x30(%rsp) + jmp .Loop_tail4x + +.align 32 +.L64_or_more4x: + movdqu 0x00($inp),$xt0 # xor with input + movdqu 0x10($inp),$xt1 + movdqu 0x20($inp),$xt2 + movdqu 0x30($inp),$xt3 + pxor 0x00(%rsp),$xt0 # $xaxN is offloaded, remember? + pxor $xb0,$xt1 + pxor $xc0,$xt2 + pxor $xd0,$xt3 + movdqu $xt0,0x00($out) + movdqu $xt1,0x10($out) + movdqu $xt2,0x20($out) + movdqu $xt3,0x30($out) + je .Ldone4x + + movdqa 0x10(%rsp),$xt0 # $xaN is offloaded, remember? + lea 0x40($inp),$inp # inp+=64*1 + xor %r10,%r10 + movdqa $xt0,0x00(%rsp) + movdqa $xb1,0x10(%rsp) + lea 0x40($out),$out # out+=64*1 + movdqa $xc1,0x20(%rsp) + sub \$64,$len # len-=64*1 + movdqa $xd1,0x30(%rsp) + jmp .Loop_tail4x + +.align 32 +.L128_or_more4x: + movdqu 0x00($inp),$xt0 # xor with input + movdqu 0x10($inp),$xt1 + movdqu 0x20($inp),$xt2 + movdqu 0x30($inp),$xt3 + pxor 0x00(%rsp),$xt0 # $xaN is offloaded, remember? + pxor $xb0,$xt1 + pxor $xc0,$xt2 + pxor $xd0,$xt3 + + movdqu $xt0,0x00($out) + movdqu 0x40($inp),$xt0 + movdqu $xt1,0x10($out) + movdqu 0x50($inp),$xt1 + movdqu $xt2,0x20($out) + movdqu 0x60($inp),$xt2 + movdqu $xt3,0x30($out) + movdqu 0x70($inp),$xt3 + pxor 0x10(%rsp),$xt0 + pxor $xb1,$xt1 + pxor $xc1,$xt2 + pxor $xd1,$xt3 + movdqu $xt0,0x40($out) + movdqu $xt1,0x50($out) + movdqu $xt2,0x60($out) + movdqu $xt3,0x70($out) + je .Ldone4x + + movdqa 0x20(%rsp),$xt0 # $xaN is offloaded, remember? + lea 0x80($inp),$inp # inp+=64*2 + xor %r10,%r10 + movdqa $xt0,0x00(%rsp) + movdqa $xb2,0x10(%rsp) + lea 0x80($out),$out # out+=64*2 + movdqa $xc2,0x20(%rsp) + sub \$128,$len # len-=64*2 + movdqa $xd2,0x30(%rsp) + jmp .Loop_tail4x + +.align 32 +.L192_or_more4x: + movdqu 0x00($inp),$xt0 # xor with input + movdqu 0x10($inp),$xt1 + movdqu 0x20($inp),$xt2 + movdqu 0x30($inp),$xt3 + pxor 0x00(%rsp),$xt0 # $xaN is offloaded, remember? + pxor $xb0,$xt1 + pxor $xc0,$xt2 + pxor $xd0,$xt3 + + movdqu $xt0,0x00($out) + movdqu 0x40($inp),$xt0 + movdqu $xt1,0x10($out) + movdqu 0x50($inp),$xt1 + movdqu $xt2,0x20($out) + movdqu 0x60($inp),$xt2 + movdqu $xt3,0x30($out) + movdqu 0x70($inp),$xt3 + lea 0x80($inp),$inp # size optimization + pxor 0x10(%rsp),$xt0 + pxor $xb1,$xt1 + pxor $xc1,$xt2 + pxor $xd1,$xt3 + + movdqu $xt0,0x40($out) + movdqu 0x00($inp),$xt0 + movdqu $xt1,0x50($out) + movdqu 0x10($inp),$xt1 + movdqu $xt2,0x60($out) + movdqu 0x20($inp),$xt2 + movdqu $xt3,0x70($out) + lea 0x80($out),$out # size optimization + movdqu 0x30($inp),$xt3 + pxor 0x20(%rsp),$xt0 + pxor $xb2,$xt1 + pxor $xc2,$xt2 + pxor $xd2,$xt3 + movdqu $xt0,0x00($out) + movdqu $xt1,0x10($out) + movdqu $xt2,0x20($out) + movdqu $xt3,0x30($out) + je .Ldone4x + + movdqa 0x30(%rsp),$xt0 # $xaN is offloaded, remember? + lea 0x40($inp),$inp # inp+=64*3 + xor %r10,%r10 + movdqa $xt0,0x00(%rsp) + movdqa $xb3,0x10(%rsp) + lea 0x40($out),$out # out+=64*3 + movdqa $xc3,0x20(%rsp) + sub \$192,$len # len-=64*3 + movdqa $xd3,0x30(%rsp) + +.Loop_tail4x: + movzb ($inp,%r10),%eax + movzb (%rsp,%r10),%ecx + lea 1(%r10),%r10 + xor %ecx,%eax + mov %al,-1($out,%r10) + dec $len + jnz .Loop_tail4x + +.Ldone4x: +___ +$code.=<<___ if ($win64); + movaps -0xa8(%r9),%xmm6 + movaps -0x98(%r9),%xmm7 + movaps -0x88(%r9),%xmm8 + movaps -0x78(%r9),%xmm9 + movaps -0x68(%r9),%xmm10 + movaps -0x58(%r9),%xmm11 + movaps -0x48(%r9),%xmm12 + movaps -0x38(%r9),%xmm13 + movaps -0x28(%r9),%xmm14 + movaps -0x18(%r9),%xmm15 +___ +$code.=<<___; + lea (%r9),%rsp +.cfi_def_cfa_register %rsp +.L4x_epilogue: + ret +.cfi_endproc +.size ChaCha20_4x,.-ChaCha20_4x +___ +} + +######################################################################## +# XOP code path that handles all lengths. +if ($avx) { +# There is some "anomaly" observed depending on instructions' size or +# alignment. If you look closely at below code you'll notice that +# sometimes argument order varies. The order affects instruction +# encoding by making it larger, and such fiddling gives 5% performance +# improvement. This is on FX-4100... + +my ($xb0,$xb1,$xb2,$xb3, $xd0,$xd1,$xd2,$xd3, + $xa0,$xa1,$xa2,$xa3, $xt0,$xt1,$xt2,$xt3)=map("%xmm$_",(0..15)); +my @xx=($xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3, + $xt0,$xt1,$xt2,$xt3, $xd0,$xd1,$xd2,$xd3); + +sub XOP_lane_ROUND { +my ($a0,$b0,$c0,$d0)=@_; +my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0)); +my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1)); +my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2)); +my @x=map("\"$_\"",@xx); + + ( + "&vpaddd (@x[$a0],@x[$a0],@x[$b0])", # Q1 + "&vpaddd (@x[$a1],@x[$a1],@x[$b1])", # Q2 + "&vpaddd (@x[$a2],@x[$a2],@x[$b2])", # Q3 + "&vpaddd (@x[$a3],@x[$a3],@x[$b3])", # Q4 + "&vpxor (@x[$d0],@x[$a0],@x[$d0])", + "&vpxor (@x[$d1],@x[$a1],@x[$d1])", + "&vpxor (@x[$d2],@x[$a2],@x[$d2])", + "&vpxor (@x[$d3],@x[$a3],@x[$d3])", + "&vprotd (@x[$d0],@x[$d0],16)", + "&vprotd (@x[$d1],@x[$d1],16)", + "&vprotd (@x[$d2],@x[$d2],16)", + "&vprotd (@x[$d3],@x[$d3],16)", + + "&vpaddd (@x[$c0],@x[$c0],@x[$d0])", + "&vpaddd (@x[$c1],@x[$c1],@x[$d1])", + "&vpaddd (@x[$c2],@x[$c2],@x[$d2])", + "&vpaddd (@x[$c3],@x[$c3],@x[$d3])", + "&vpxor (@x[$b0],@x[$c0],@x[$b0])", + "&vpxor (@x[$b1],@x[$c1],@x[$b1])", + "&vpxor (@x[$b2],@x[$b2],@x[$c2])", # flip + "&vpxor (@x[$b3],@x[$b3],@x[$c3])", # flip + "&vprotd (@x[$b0],@x[$b0],12)", + "&vprotd (@x[$b1],@x[$b1],12)", + "&vprotd (@x[$b2],@x[$b2],12)", + "&vprotd (@x[$b3],@x[$b3],12)", + + "&vpaddd (@x[$a0],@x[$b0],@x[$a0])", # flip + "&vpaddd (@x[$a1],@x[$b1],@x[$a1])", # flip + "&vpaddd (@x[$a2],@x[$a2],@x[$b2])", + "&vpaddd (@x[$a3],@x[$a3],@x[$b3])", + "&vpxor (@x[$d0],@x[$a0],@x[$d0])", + "&vpxor (@x[$d1],@x[$a1],@x[$d1])", + "&vpxor (@x[$d2],@x[$a2],@x[$d2])", + "&vpxor (@x[$d3],@x[$a3],@x[$d3])", + "&vprotd (@x[$d0],@x[$d0],8)", + "&vprotd (@x[$d1],@x[$d1],8)", + "&vprotd (@x[$d2],@x[$d2],8)", + "&vprotd (@x[$d3],@x[$d3],8)", + + "&vpaddd (@x[$c0],@x[$c0],@x[$d0])", + "&vpaddd (@x[$c1],@x[$c1],@x[$d1])", + "&vpaddd (@x[$c2],@x[$c2],@x[$d2])", + "&vpaddd (@x[$c3],@x[$c3],@x[$d3])", + "&vpxor (@x[$b0],@x[$c0],@x[$b0])", + "&vpxor (@x[$b1],@x[$c1],@x[$b1])", + "&vpxor (@x[$b2],@x[$b2],@x[$c2])", # flip + "&vpxor (@x[$b3],@x[$b3],@x[$c3])", # flip + "&vprotd (@x[$b0],@x[$b0],7)", + "&vprotd (@x[$b1],@x[$b1],7)", + "&vprotd (@x[$b2],@x[$b2],7)", + "&vprotd (@x[$b3],@x[$b3],7)" + ); +} + +my $xframe = $win64 ? 0xa8 : 8; + +$code.=<<___; +.type ChaCha20_4xop,\@function,5 +.align 32 +ChaCha20_4xop: +.cfi_startproc +.LChaCha20_4xop: + mov %rsp,%r9 # frame pointer +.cfi_def_cfa_register %r9 + sub \$0x140+$xframe,%rsp +___ + ################ stack layout + # +0x00 SIMD equivalent of @x[8-12] + # ... + # +0x40 constant copy of key[0-2] smashed by lanes + # ... + # +0x100 SIMD counters (with nonce smashed by lanes) + # ... + # +0x140 +$code.=<<___ if ($win64); + movaps %xmm6,-0xa8(%r9) + movaps %xmm7,-0x98(%r9) + movaps %xmm8,-0x88(%r9) + movaps %xmm9,-0x78(%r9) + movaps %xmm10,-0x68(%r9) + movaps %xmm11,-0x58(%r9) + movaps %xmm12,-0x48(%r9) + movaps %xmm13,-0x38(%r9) + movaps %xmm14,-0x28(%r9) + movaps %xmm15,-0x18(%r9) +.L4xop_body: +___ +$code.=<<___; + vzeroupper + + vmovdqa .Lsigma(%rip),$xa3 # key[0] + vmovdqu ($key),$xb3 # key[1] + vmovdqu 16($key),$xt3 # key[2] + vmovdqu ($counter),$xd3 # key[3] + lea 0x100(%rsp),%rcx # size optimization + + vpshufd \$0x00,$xa3,$xa0 # smash key by lanes... + vpshufd \$0x55,$xa3,$xa1 + vmovdqa $xa0,0x40(%rsp) # ... and offload + vpshufd \$0xaa,$xa3,$xa2 + vmovdqa $xa1,0x50(%rsp) + vpshufd \$0xff,$xa3,$xa3 + vmovdqa $xa2,0x60(%rsp) + vmovdqa $xa3,0x70(%rsp) + + vpshufd \$0x00,$xb3,$xb0 + vpshufd \$0x55,$xb3,$xb1 + vmovdqa $xb0,0x80-0x100(%rcx) + vpshufd \$0xaa,$xb3,$xb2 + vmovdqa $xb1,0x90-0x100(%rcx) + vpshufd \$0xff,$xb3,$xb3 + vmovdqa $xb2,0xa0-0x100(%rcx) + vmovdqa $xb3,0xb0-0x100(%rcx) + + vpshufd \$0x00,$xt3,$xt0 # "$xc0" + vpshufd \$0x55,$xt3,$xt1 # "$xc1" + vmovdqa $xt0,0xc0-0x100(%rcx) + vpshufd \$0xaa,$xt3,$xt2 # "$xc2" + vmovdqa $xt1,0xd0-0x100(%rcx) + vpshufd \$0xff,$xt3,$xt3 # "$xc3" + vmovdqa $xt2,0xe0-0x100(%rcx) + vmovdqa $xt3,0xf0-0x100(%rcx) + + vpshufd \$0x00,$xd3,$xd0 + vpshufd \$0x55,$xd3,$xd1 + vpaddd .Linc(%rip),$xd0,$xd0 # don't save counters yet + vpshufd \$0xaa,$xd3,$xd2 + vmovdqa $xd1,0x110-0x100(%rcx) + vpshufd \$0xff,$xd3,$xd3 + vmovdqa $xd2,0x120-0x100(%rcx) + vmovdqa $xd3,0x130-0x100(%rcx) + + jmp .Loop_enter4xop + +.align 32 +.Loop_outer4xop: + vmovdqa 0x40(%rsp),$xa0 # re-load smashed key + vmovdqa 0x50(%rsp),$xa1 + vmovdqa 0x60(%rsp),$xa2 + vmovdqa 0x70(%rsp),$xa3 + vmovdqa 0x80-0x100(%rcx),$xb0 + vmovdqa 0x90-0x100(%rcx),$xb1 + vmovdqa 0xa0-0x100(%rcx),$xb2 + vmovdqa 0xb0-0x100(%rcx),$xb3 + vmovdqa 0xc0-0x100(%rcx),$xt0 # "$xc0" + vmovdqa 0xd0-0x100(%rcx),$xt1 # "$xc1" + vmovdqa 0xe0-0x100(%rcx),$xt2 # "$xc2" + vmovdqa 0xf0-0x100(%rcx),$xt3 # "$xc3" + vmovdqa 0x100-0x100(%rcx),$xd0 + vmovdqa 0x110-0x100(%rcx),$xd1 + vmovdqa 0x120-0x100(%rcx),$xd2 + vmovdqa 0x130-0x100(%rcx),$xd3 + vpaddd .Lfour(%rip),$xd0,$xd0 # next SIMD counters + +.Loop_enter4xop: + mov \$10,%eax + vmovdqa $xd0,0x100-0x100(%rcx) # save SIMD counters + jmp .Loop4xop + +.align 32 +.Loop4xop: +___ + foreach (&XOP_lane_ROUND(0, 4, 8,12)) { eval; } + foreach (&XOP_lane_ROUND(0, 5,10,15)) { eval; } +$code.=<<___; + dec %eax + jnz .Loop4xop + + vpaddd 0x40(%rsp),$xa0,$xa0 # accumulate key material + vpaddd 0x50(%rsp),$xa1,$xa1 + vpaddd 0x60(%rsp),$xa2,$xa2 + vpaddd 0x70(%rsp),$xa3,$xa3 + + vmovdqa $xt2,0x20(%rsp) # offload $xc2,3 + vmovdqa $xt3,0x30(%rsp) + + vpunpckldq $xa1,$xa0,$xt2 # "de-interlace" data + vpunpckldq $xa3,$xa2,$xt3 + vpunpckhdq $xa1,$xa0,$xa0 + vpunpckhdq $xa3,$xa2,$xa2 + vpunpcklqdq $xt3,$xt2,$xa1 # "a0" + vpunpckhqdq $xt3,$xt2,$xt2 # "a1" + vpunpcklqdq $xa2,$xa0,$xa3 # "a2" + vpunpckhqdq $xa2,$xa0,$xa0 # "a3" +___ + ($xa0,$xa1,$xa2,$xa3,$xt2)=($xa1,$xt2,$xa3,$xa0,$xa2); +$code.=<<___; + vpaddd 0x80-0x100(%rcx),$xb0,$xb0 + vpaddd 0x90-0x100(%rcx),$xb1,$xb1 + vpaddd 0xa0-0x100(%rcx),$xb2,$xb2 + vpaddd 0xb0-0x100(%rcx),$xb3,$xb3 + + vmovdqa $xa0,0x00(%rsp) # offload $xa0,1 + vmovdqa $xa1,0x10(%rsp) + vmovdqa 0x20(%rsp),$xa0 # "xc2" + vmovdqa 0x30(%rsp),$xa1 # "xc3" + + vpunpckldq $xb1,$xb0,$xt2 + vpunpckldq $xb3,$xb2,$xt3 + vpunpckhdq $xb1,$xb0,$xb0 + vpunpckhdq $xb3,$xb2,$xb2 + vpunpcklqdq $xt3,$xt2,$xb1 # "b0" + vpunpckhqdq $xt3,$xt2,$xt2 # "b1" + vpunpcklqdq $xb2,$xb0,$xb3 # "b2" + vpunpckhqdq $xb2,$xb0,$xb0 # "b3" +___ + ($xb0,$xb1,$xb2,$xb3,$xt2)=($xb1,$xt2,$xb3,$xb0,$xb2); + my ($xc0,$xc1,$xc2,$xc3)=($xt0,$xt1,$xa0,$xa1); +$code.=<<___; + vpaddd 0xc0-0x100(%rcx),$xc0,$xc0 + vpaddd 0xd0-0x100(%rcx),$xc1,$xc1 + vpaddd 0xe0-0x100(%rcx),$xc2,$xc2 + vpaddd 0xf0-0x100(%rcx),$xc3,$xc3 + + vpunpckldq $xc1,$xc0,$xt2 + vpunpckldq $xc3,$xc2,$xt3 + vpunpckhdq $xc1,$xc0,$xc0 + vpunpckhdq $xc3,$xc2,$xc2 + vpunpcklqdq $xt3,$xt2,$xc1 # "c0" + vpunpckhqdq $xt3,$xt2,$xt2 # "c1" + vpunpcklqdq $xc2,$xc0,$xc3 # "c2" + vpunpckhqdq $xc2,$xc0,$xc0 # "c3" +___ + ($xc0,$xc1,$xc2,$xc3,$xt2)=($xc1,$xt2,$xc3,$xc0,$xc2); +$code.=<<___; + vpaddd 0x100-0x100(%rcx),$xd0,$xd0 + vpaddd 0x110-0x100(%rcx),$xd1,$xd1 + vpaddd 0x120-0x100(%rcx),$xd2,$xd2 + vpaddd 0x130-0x100(%rcx),$xd3,$xd3 + + vpunpckldq $xd1,$xd0,$xt2 + vpunpckldq $xd3,$xd2,$xt3 + vpunpckhdq $xd1,$xd0,$xd0 + vpunpckhdq $xd3,$xd2,$xd2 + vpunpcklqdq $xt3,$xt2,$xd1 # "d0" + vpunpckhqdq $xt3,$xt2,$xt2 # "d1" + vpunpcklqdq $xd2,$xd0,$xd3 # "d2" + vpunpckhqdq $xd2,$xd0,$xd0 # "d3" +___ + ($xd0,$xd1,$xd2,$xd3,$xt2)=($xd1,$xt2,$xd3,$xd0,$xd2); + ($xa0,$xa1)=($xt2,$xt3); +$code.=<<___; + vmovdqa 0x00(%rsp),$xa0 # restore $xa0,1 + vmovdqa 0x10(%rsp),$xa1 + + cmp \$64*4,$len + jb .Ltail4xop + + vpxor 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x10($inp),$xb0,$xb0 + vpxor 0x20($inp),$xc0,$xc0 + vpxor 0x30($inp),$xd0,$xd0 + vpxor 0x40($inp),$xa1,$xa1 + vpxor 0x50($inp),$xb1,$xb1 + vpxor 0x60($inp),$xc1,$xc1 + vpxor 0x70($inp),$xd1,$xd1 + lea 0x80($inp),$inp # size optimization + vpxor 0x00($inp),$xa2,$xa2 + vpxor 0x10($inp),$xb2,$xb2 + vpxor 0x20($inp),$xc2,$xc2 + vpxor 0x30($inp),$xd2,$xd2 + vpxor 0x40($inp),$xa3,$xa3 + vpxor 0x50($inp),$xb3,$xb3 + vpxor 0x60($inp),$xc3,$xc3 + vpxor 0x70($inp),$xd3,$xd3 + lea 0x80($inp),$inp # inp+=64*4 + + vmovdqu $xa0,0x00($out) + vmovdqu $xb0,0x10($out) + vmovdqu $xc0,0x20($out) + vmovdqu $xd0,0x30($out) + vmovdqu $xa1,0x40($out) + vmovdqu $xb1,0x50($out) + vmovdqu $xc1,0x60($out) + vmovdqu $xd1,0x70($out) + lea 0x80($out),$out # size optimization + vmovdqu $xa2,0x00($out) + vmovdqu $xb2,0x10($out) + vmovdqu $xc2,0x20($out) + vmovdqu $xd2,0x30($out) + vmovdqu $xa3,0x40($out) + vmovdqu $xb3,0x50($out) + vmovdqu $xc3,0x60($out) + vmovdqu $xd3,0x70($out) + lea 0x80($out),$out # out+=64*4 + + sub \$64*4,$len + jnz .Loop_outer4xop + + jmp .Ldone4xop + +.align 32 +.Ltail4xop: + cmp \$192,$len + jae .L192_or_more4xop + cmp \$128,$len + jae .L128_or_more4xop + cmp \$64,$len + jae .L64_or_more4xop + + xor %r10,%r10 + vmovdqa $xa0,0x00(%rsp) + vmovdqa $xb0,0x10(%rsp) + vmovdqa $xc0,0x20(%rsp) + vmovdqa $xd0,0x30(%rsp) + jmp .Loop_tail4xop + +.align 32 +.L64_or_more4xop: + vpxor 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x10($inp),$xb0,$xb0 + vpxor 0x20($inp),$xc0,$xc0 + vpxor 0x30($inp),$xd0,$xd0 + vmovdqu $xa0,0x00($out) + vmovdqu $xb0,0x10($out) + vmovdqu $xc0,0x20($out) + vmovdqu $xd0,0x30($out) + je .Ldone4xop + + lea 0x40($inp),$inp # inp+=64*1 + vmovdqa $xa1,0x00(%rsp) + xor %r10,%r10 + vmovdqa $xb1,0x10(%rsp) + lea 0x40($out),$out # out+=64*1 + vmovdqa $xc1,0x20(%rsp) + sub \$64,$len # len-=64*1 + vmovdqa $xd1,0x30(%rsp) + jmp .Loop_tail4xop + +.align 32 +.L128_or_more4xop: + vpxor 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x10($inp),$xb0,$xb0 + vpxor 0x20($inp),$xc0,$xc0 + vpxor 0x30($inp),$xd0,$xd0 + vpxor 0x40($inp),$xa1,$xa1 + vpxor 0x50($inp),$xb1,$xb1 + vpxor 0x60($inp),$xc1,$xc1 + vpxor 0x70($inp),$xd1,$xd1 + + vmovdqu $xa0,0x00($out) + vmovdqu $xb0,0x10($out) + vmovdqu $xc0,0x20($out) + vmovdqu $xd0,0x30($out) + vmovdqu $xa1,0x40($out) + vmovdqu $xb1,0x50($out) + vmovdqu $xc1,0x60($out) + vmovdqu $xd1,0x70($out) + je .Ldone4xop + + lea 0x80($inp),$inp # inp+=64*2 + vmovdqa $xa2,0x00(%rsp) + xor %r10,%r10 + vmovdqa $xb2,0x10(%rsp) + lea 0x80($out),$out # out+=64*2 + vmovdqa $xc2,0x20(%rsp) + sub \$128,$len # len-=64*2 + vmovdqa $xd2,0x30(%rsp) + jmp .Loop_tail4xop + +.align 32 +.L192_or_more4xop: + vpxor 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x10($inp),$xb0,$xb0 + vpxor 0x20($inp),$xc0,$xc0 + vpxor 0x30($inp),$xd0,$xd0 + vpxor 0x40($inp),$xa1,$xa1 + vpxor 0x50($inp),$xb1,$xb1 + vpxor 0x60($inp),$xc1,$xc1 + vpxor 0x70($inp),$xd1,$xd1 + lea 0x80($inp),$inp # size optimization + vpxor 0x00($inp),$xa2,$xa2 + vpxor 0x10($inp),$xb2,$xb2 + vpxor 0x20($inp),$xc2,$xc2 + vpxor 0x30($inp),$xd2,$xd2 + + vmovdqu $xa0,0x00($out) + vmovdqu $xb0,0x10($out) + vmovdqu $xc0,0x20($out) + vmovdqu $xd0,0x30($out) + vmovdqu $xa1,0x40($out) + vmovdqu $xb1,0x50($out) + vmovdqu $xc1,0x60($out) + vmovdqu $xd1,0x70($out) + lea 0x80($out),$out # size optimization + vmovdqu $xa2,0x00($out) + vmovdqu $xb2,0x10($out) + vmovdqu $xc2,0x20($out) + vmovdqu $xd2,0x30($out) + je .Ldone4xop + + lea 0x40($inp),$inp # inp+=64*3 + vmovdqa $xa3,0x00(%rsp) + xor %r10,%r10 + vmovdqa $xb3,0x10(%rsp) + lea 0x40($out),$out # out+=64*3 + vmovdqa $xc3,0x20(%rsp) + sub \$192,$len # len-=64*3 + vmovdqa $xd3,0x30(%rsp) + +.Loop_tail4xop: + movzb ($inp,%r10),%eax + movzb (%rsp,%r10),%ecx + lea 1(%r10),%r10 + xor %ecx,%eax + mov %al,-1($out,%r10) + dec $len + jnz .Loop_tail4xop + +.Ldone4xop: + vzeroupper +___ +$code.=<<___ if ($win64); + movaps -0xa8(%r9),%xmm6 + movaps -0x98(%r9),%xmm7 + movaps -0x88(%r9),%xmm8 + movaps -0x78(%r9),%xmm9 + movaps -0x68(%r9),%xmm10 + movaps -0x58(%r9),%xmm11 + movaps -0x48(%r9),%xmm12 + movaps -0x38(%r9),%xmm13 + movaps -0x28(%r9),%xmm14 + movaps -0x18(%r9),%xmm15 +___ +$code.=<<___; + lea (%r9),%rsp +.cfi_def_cfa_register %rsp +.L4xop_epilogue: + ret +.cfi_endproc +.size ChaCha20_4xop,.-ChaCha20_4xop +___ +} + +######################################################################## +# AVX2 code path +if ($avx>1) { +my ($xb0,$xb1,$xb2,$xb3, $xd0,$xd1,$xd2,$xd3, + $xa0,$xa1,$xa2,$xa3, $xt0,$xt1,$xt2,$xt3)=map("%ymm$_",(0..15)); +my @xx=($xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3, + "%nox","%nox","%nox","%nox", $xd0,$xd1,$xd2,$xd3); + +sub AVX2_lane_ROUND { +my ($a0,$b0,$c0,$d0)=@_; +my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0)); +my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1)); +my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2)); +my ($xc,$xc_,$t0,$t1)=map("\"$_\"",$xt0,$xt1,$xt2,$xt3); +my @x=map("\"$_\"",@xx); + + # Consider order in which variables are addressed by their + # index: + # + # a b c d + # + # 0 4 8 12 < even round + # 1 5 9 13 + # 2 6 10 14 + # 3 7 11 15 + # 0 5 10 15 < odd round + # 1 6 11 12 + # 2 7 8 13 + # 3 4 9 14 + # + # 'a', 'b' and 'd's are permanently allocated in registers, + # @x[0..7,12..15], while 'c's are maintained in memory. If + # you observe 'c' column, you'll notice that pair of 'c's is + # invariant between rounds. This means that we have to reload + # them once per round, in the middle. This is why you'll see + # bunch of 'c' stores and loads in the middle, but none in + # the beginning or end. + + ( + "&vpaddd (@x[$a0],@x[$a0],@x[$b0])", # Q1 + "&vpxor (@x[$d0],@x[$a0],@x[$d0])", + "&vpshufb (@x[$d0],@x[$d0],$t1)", + "&vpaddd (@x[$a1],@x[$a1],@x[$b1])", # Q2 + "&vpxor (@x[$d1],@x[$a1],@x[$d1])", + "&vpshufb (@x[$d1],@x[$d1],$t1)", + + "&vpaddd ($xc,$xc,@x[$d0])", + "&vpxor (@x[$b0],$xc,@x[$b0])", + "&vpslld ($t0,@x[$b0],12)", + "&vpsrld (@x[$b0],@x[$b0],20)", + "&vpor (@x[$b0],$t0,@x[$b0])", + "&vbroadcasti128($t0,'(%r11)')", # .Lrot24(%rip) + "&vpaddd ($xc_,$xc_,@x[$d1])", + "&vpxor (@x[$b1],$xc_,@x[$b1])", + "&vpslld ($t1,@x[$b1],12)", + "&vpsrld (@x[$b1],@x[$b1],20)", + "&vpor (@x[$b1],$t1,@x[$b1])", + + "&vpaddd (@x[$a0],@x[$a0],@x[$b0])", + "&vpxor (@x[$d0],@x[$a0],@x[$d0])", + "&vpshufb (@x[$d0],@x[$d0],$t0)", + "&vpaddd (@x[$a1],@x[$a1],@x[$b1])", + "&vpxor (@x[$d1],@x[$a1],@x[$d1])", + "&vpshufb (@x[$d1],@x[$d1],$t0)", + + "&vpaddd ($xc,$xc,@x[$d0])", + "&vpxor (@x[$b0],$xc,@x[$b0])", + "&vpslld ($t1,@x[$b0],7)", + "&vpsrld (@x[$b0],@x[$b0],25)", + "&vpor (@x[$b0],$t1,@x[$b0])", + "&vbroadcasti128($t1,'(%r10)')", # .Lrot16(%rip) + "&vpaddd ($xc_,$xc_,@x[$d1])", + "&vpxor (@x[$b1],$xc_,@x[$b1])", + "&vpslld ($t0,@x[$b1],7)", + "&vpsrld (@x[$b1],@x[$b1],25)", + "&vpor (@x[$b1],$t0,@x[$b1])", + + "&vmovdqa (\"`32*($c0-8)`(%rsp)\",$xc)", # reload pair of 'c's + "&vmovdqa (\"`32*($c1-8)`(%rsp)\",$xc_)", + "&vmovdqa ($xc,\"`32*($c2-8)`(%rsp)\")", + "&vmovdqa ($xc_,\"`32*($c3-8)`(%rsp)\")", + + "&vpaddd (@x[$a2],@x[$a2],@x[$b2])", # Q3 + "&vpxor (@x[$d2],@x[$a2],@x[$d2])", + "&vpshufb (@x[$d2],@x[$d2],$t1)", + "&vpaddd (@x[$a3],@x[$a3],@x[$b3])", # Q4 + "&vpxor (@x[$d3],@x[$a3],@x[$d3])", + "&vpshufb (@x[$d3],@x[$d3],$t1)", + + "&vpaddd ($xc,$xc,@x[$d2])", + "&vpxor (@x[$b2],$xc,@x[$b2])", + "&vpslld ($t0,@x[$b2],12)", + "&vpsrld (@x[$b2],@x[$b2],20)", + "&vpor (@x[$b2],$t0,@x[$b2])", + "&vbroadcasti128($t0,'(%r11)')", # .Lrot24(%rip) + "&vpaddd ($xc_,$xc_,@x[$d3])", + "&vpxor (@x[$b3],$xc_,@x[$b3])", + "&vpslld ($t1,@x[$b3],12)", + "&vpsrld (@x[$b3],@x[$b3],20)", + "&vpor (@x[$b3],$t1,@x[$b3])", + + "&vpaddd (@x[$a2],@x[$a2],@x[$b2])", + "&vpxor (@x[$d2],@x[$a2],@x[$d2])", + "&vpshufb (@x[$d2],@x[$d2],$t0)", + "&vpaddd (@x[$a3],@x[$a3],@x[$b3])", + "&vpxor (@x[$d3],@x[$a3],@x[$d3])", + "&vpshufb (@x[$d3],@x[$d3],$t0)", + + "&vpaddd ($xc,$xc,@x[$d2])", + "&vpxor (@x[$b2],$xc,@x[$b2])", + "&vpslld ($t1,@x[$b2],7)", + "&vpsrld (@x[$b2],@x[$b2],25)", + "&vpor (@x[$b2],$t1,@x[$b2])", + "&vbroadcasti128($t1,'(%r10)')", # .Lrot16(%rip) + "&vpaddd ($xc_,$xc_,@x[$d3])", + "&vpxor (@x[$b3],$xc_,@x[$b3])", + "&vpslld ($t0,@x[$b3],7)", + "&vpsrld (@x[$b3],@x[$b3],25)", + "&vpor (@x[$b3],$t0,@x[$b3])" + ); +} + +my $xframe = $win64 ? 0xa8 : 8; + +$code.=<<___; +.type ChaCha20_8x,\@function,5 +.align 32 +ChaCha20_8x: +.cfi_startproc +.LChaCha20_8x: + mov %rsp,%r9 # frame register +.cfi_def_cfa_register %r9 + sub \$0x280+$xframe,%rsp + and \$-32,%rsp +___ +$code.=<<___ if ($win64); + movaps %xmm6,-0xa8(%r9) + movaps %xmm7,-0x98(%r9) + movaps %xmm8,-0x88(%r9) + movaps %xmm9,-0x78(%r9) + movaps %xmm10,-0x68(%r9) + movaps %xmm11,-0x58(%r9) + movaps %xmm12,-0x48(%r9) + movaps %xmm13,-0x38(%r9) + movaps %xmm14,-0x28(%r9) + movaps %xmm15,-0x18(%r9) +.L8x_body: +___ +$code.=<<___; + vzeroupper + + ################ stack layout + # +0x00 SIMD equivalent of @x[8-12] + # ... + # +0x80 constant copy of key[0-2] smashed by lanes + # ... + # +0x200 SIMD counters (with nonce smashed by lanes) + # ... + # +0x280 + + vbroadcasti128 .Lsigma(%rip),$xa3 # key[0] + vbroadcasti128 ($key),$xb3 # key[1] + vbroadcasti128 16($key),$xt3 # key[2] + vbroadcasti128 ($counter),$xd3 # key[3] + lea 0x100(%rsp),%rcx # size optimization + lea 0x200(%rsp),%rax # size optimization + lea .Lrot16(%rip),%r10 + lea .Lrot24(%rip),%r11 + + vpshufd \$0x00,$xa3,$xa0 # smash key by lanes... + vpshufd \$0x55,$xa3,$xa1 + vmovdqa $xa0,0x80-0x100(%rcx) # ... and offload + vpshufd \$0xaa,$xa3,$xa2 + vmovdqa $xa1,0xa0-0x100(%rcx) + vpshufd \$0xff,$xa3,$xa3 + vmovdqa $xa2,0xc0-0x100(%rcx) + vmovdqa $xa3,0xe0-0x100(%rcx) + + vpshufd \$0x00,$xb3,$xb0 + vpshufd \$0x55,$xb3,$xb1 + vmovdqa $xb0,0x100-0x100(%rcx) + vpshufd \$0xaa,$xb3,$xb2 + vmovdqa $xb1,0x120-0x100(%rcx) + vpshufd \$0xff,$xb3,$xb3 + vmovdqa $xb2,0x140-0x100(%rcx) + vmovdqa $xb3,0x160-0x100(%rcx) + + vpshufd \$0x00,$xt3,$xt0 # "xc0" + vpshufd \$0x55,$xt3,$xt1 # "xc1" + vmovdqa $xt0,0x180-0x200(%rax) + vpshufd \$0xaa,$xt3,$xt2 # "xc2" + vmovdqa $xt1,0x1a0-0x200(%rax) + vpshufd \$0xff,$xt3,$xt3 # "xc3" + vmovdqa $xt2,0x1c0-0x200(%rax) + vmovdqa $xt3,0x1e0-0x200(%rax) + + vpshufd \$0x00,$xd3,$xd0 + vpshufd \$0x55,$xd3,$xd1 + vpaddd .Lincy(%rip),$xd0,$xd0 # don't save counters yet + vpshufd \$0xaa,$xd3,$xd2 + vmovdqa $xd1,0x220-0x200(%rax) + vpshufd \$0xff,$xd3,$xd3 + vmovdqa $xd2,0x240-0x200(%rax) + vmovdqa $xd3,0x260-0x200(%rax) + + jmp .Loop_enter8x + +.align 32 +.Loop_outer8x: + vmovdqa 0x80-0x100(%rcx),$xa0 # re-load smashed key + vmovdqa 0xa0-0x100(%rcx),$xa1 + vmovdqa 0xc0-0x100(%rcx),$xa2 + vmovdqa 0xe0-0x100(%rcx),$xa3 + vmovdqa 0x100-0x100(%rcx),$xb0 + vmovdqa 0x120-0x100(%rcx),$xb1 + vmovdqa 0x140-0x100(%rcx),$xb2 + vmovdqa 0x160-0x100(%rcx),$xb3 + vmovdqa 0x180-0x200(%rax),$xt0 # "xc0" + vmovdqa 0x1a0-0x200(%rax),$xt1 # "xc1" + vmovdqa 0x1c0-0x200(%rax),$xt2 # "xc2" + vmovdqa 0x1e0-0x200(%rax),$xt3 # "xc3" + vmovdqa 0x200-0x200(%rax),$xd0 + vmovdqa 0x220-0x200(%rax),$xd1 + vmovdqa 0x240-0x200(%rax),$xd2 + vmovdqa 0x260-0x200(%rax),$xd3 + vpaddd .Leight(%rip),$xd0,$xd0 # next SIMD counters + +.Loop_enter8x: + vmovdqa $xt2,0x40(%rsp) # SIMD equivalent of "@x[10]" + vmovdqa $xt3,0x60(%rsp) # SIMD equivalent of "@x[11]" + vbroadcasti128 (%r10),$xt3 + vmovdqa $xd0,0x200-0x200(%rax) # save SIMD counters + mov \$10,%eax + jmp .Loop8x + +.align 32 +.Loop8x: +___ + foreach (&AVX2_lane_ROUND(0, 4, 8,12)) { eval; } + foreach (&AVX2_lane_ROUND(0, 5,10,15)) { eval; } +$code.=<<___; + dec %eax + jnz .Loop8x + + lea 0x200(%rsp),%rax # size optimization + vpaddd 0x80-0x100(%rcx),$xa0,$xa0 # accumulate key + vpaddd 0xa0-0x100(%rcx),$xa1,$xa1 + vpaddd 0xc0-0x100(%rcx),$xa2,$xa2 + vpaddd 0xe0-0x100(%rcx),$xa3,$xa3 + + vpunpckldq $xa1,$xa0,$xt2 # "de-interlace" data + vpunpckldq $xa3,$xa2,$xt3 + vpunpckhdq $xa1,$xa0,$xa0 + vpunpckhdq $xa3,$xa2,$xa2 + vpunpcklqdq $xt3,$xt2,$xa1 # "a0" + vpunpckhqdq $xt3,$xt2,$xt2 # "a1" + vpunpcklqdq $xa2,$xa0,$xa3 # "a2" + vpunpckhqdq $xa2,$xa0,$xa0 # "a3" +___ + ($xa0,$xa1,$xa2,$xa3,$xt2)=($xa1,$xt2,$xa3,$xa0,$xa2); +$code.=<<___; + vpaddd 0x100-0x100(%rcx),$xb0,$xb0 + vpaddd 0x120-0x100(%rcx),$xb1,$xb1 + vpaddd 0x140-0x100(%rcx),$xb2,$xb2 + vpaddd 0x160-0x100(%rcx),$xb3,$xb3 + + vpunpckldq $xb1,$xb0,$xt2 + vpunpckldq $xb3,$xb2,$xt3 + vpunpckhdq $xb1,$xb0,$xb0 + vpunpckhdq $xb3,$xb2,$xb2 + vpunpcklqdq $xt3,$xt2,$xb1 # "b0" + vpunpckhqdq $xt3,$xt2,$xt2 # "b1" + vpunpcklqdq $xb2,$xb0,$xb3 # "b2" + vpunpckhqdq $xb2,$xb0,$xb0 # "b3" +___ + ($xb0,$xb1,$xb2,$xb3,$xt2)=($xb1,$xt2,$xb3,$xb0,$xb2); +$code.=<<___; + vperm2i128 \$0x20,$xb0,$xa0,$xt3 # "de-interlace" further + vperm2i128 \$0x31,$xb0,$xa0,$xb0 + vperm2i128 \$0x20,$xb1,$xa1,$xa0 + vperm2i128 \$0x31,$xb1,$xa1,$xb1 + vperm2i128 \$0x20,$xb2,$xa2,$xa1 + vperm2i128 \$0x31,$xb2,$xa2,$xb2 + vperm2i128 \$0x20,$xb3,$xa3,$xa2 + vperm2i128 \$0x31,$xb3,$xa3,$xb3 +___ + ($xa0,$xa1,$xa2,$xa3,$xt3)=($xt3,$xa0,$xa1,$xa2,$xa3); + my ($xc0,$xc1,$xc2,$xc3)=($xt0,$xt1,$xa0,$xa1); +$code.=<<___; + vmovdqa $xa0,0x00(%rsp) # offload $xaN + vmovdqa $xa1,0x20(%rsp) + vmovdqa 0x40(%rsp),$xc2 # $xa0 + vmovdqa 0x60(%rsp),$xc3 # $xa1 + + vpaddd 0x180-0x200(%rax),$xc0,$xc0 + vpaddd 0x1a0-0x200(%rax),$xc1,$xc1 + vpaddd 0x1c0-0x200(%rax),$xc2,$xc2 + vpaddd 0x1e0-0x200(%rax),$xc3,$xc3 + + vpunpckldq $xc1,$xc0,$xt2 + vpunpckldq $xc3,$xc2,$xt3 + vpunpckhdq $xc1,$xc0,$xc0 + vpunpckhdq $xc3,$xc2,$xc2 + vpunpcklqdq $xt3,$xt2,$xc1 # "c0" + vpunpckhqdq $xt3,$xt2,$xt2 # "c1" + vpunpcklqdq $xc2,$xc0,$xc3 # "c2" + vpunpckhqdq $xc2,$xc0,$xc0 # "c3" +___ + ($xc0,$xc1,$xc2,$xc3,$xt2)=($xc1,$xt2,$xc3,$xc0,$xc2); +$code.=<<___; + vpaddd 0x200-0x200(%rax),$xd0,$xd0 + vpaddd 0x220-0x200(%rax),$xd1,$xd1 + vpaddd 0x240-0x200(%rax),$xd2,$xd2 + vpaddd 0x260-0x200(%rax),$xd3,$xd3 + + vpunpckldq $xd1,$xd0,$xt2 + vpunpckldq $xd3,$xd2,$xt3 + vpunpckhdq $xd1,$xd0,$xd0 + vpunpckhdq $xd3,$xd2,$xd2 + vpunpcklqdq $xt3,$xt2,$xd1 # "d0" + vpunpckhqdq $xt3,$xt2,$xt2 # "d1" + vpunpcklqdq $xd2,$xd0,$xd3 # "d2" + vpunpckhqdq $xd2,$xd0,$xd0 # "d3" +___ + ($xd0,$xd1,$xd2,$xd3,$xt2)=($xd1,$xt2,$xd3,$xd0,$xd2); +$code.=<<___; + vperm2i128 \$0x20,$xd0,$xc0,$xt3 # "de-interlace" further + vperm2i128 \$0x31,$xd0,$xc0,$xd0 + vperm2i128 \$0x20,$xd1,$xc1,$xc0 + vperm2i128 \$0x31,$xd1,$xc1,$xd1 + vperm2i128 \$0x20,$xd2,$xc2,$xc1 + vperm2i128 \$0x31,$xd2,$xc2,$xd2 + vperm2i128 \$0x20,$xd3,$xc3,$xc2 + vperm2i128 \$0x31,$xd3,$xc3,$xd3 +___ + ($xc0,$xc1,$xc2,$xc3,$xt3)=($xt3,$xc0,$xc1,$xc2,$xc3); + ($xb0,$xb1,$xb2,$xb3,$xc0,$xc1,$xc2,$xc3)= + ($xc0,$xc1,$xc2,$xc3,$xb0,$xb1,$xb2,$xb3); + ($xa0,$xa1)=($xt2,$xt3); +$code.=<<___; + vmovdqa 0x00(%rsp),$xa0 # $xaN was offloaded, remember? + vmovdqa 0x20(%rsp),$xa1 + + cmp \$64*8,$len + jb .Ltail8x + + vpxor 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x20($inp),$xb0,$xb0 + vpxor 0x40($inp),$xc0,$xc0 + vpxor 0x60($inp),$xd0,$xd0 + lea 0x80($inp),$inp # size optimization + vmovdqu $xa0,0x00($out) + vmovdqu $xb0,0x20($out) + vmovdqu $xc0,0x40($out) + vmovdqu $xd0,0x60($out) + lea 0x80($out),$out # size optimization + + vpxor 0x00($inp),$xa1,$xa1 + vpxor 0x20($inp),$xb1,$xb1 + vpxor 0x40($inp),$xc1,$xc1 + vpxor 0x60($inp),$xd1,$xd1 + lea 0x80($inp),$inp # size optimization + vmovdqu $xa1,0x00($out) + vmovdqu $xb1,0x20($out) + vmovdqu $xc1,0x40($out) + vmovdqu $xd1,0x60($out) + lea 0x80($out),$out # size optimization + + vpxor 0x00($inp),$xa2,$xa2 + vpxor 0x20($inp),$xb2,$xb2 + vpxor 0x40($inp),$xc2,$xc2 + vpxor 0x60($inp),$xd2,$xd2 + lea 0x80($inp),$inp # size optimization + vmovdqu $xa2,0x00($out) + vmovdqu $xb2,0x20($out) + vmovdqu $xc2,0x40($out) + vmovdqu $xd2,0x60($out) + lea 0x80($out),$out # size optimization + + vpxor 0x00($inp),$xa3,$xa3 + vpxor 0x20($inp),$xb3,$xb3 + vpxor 0x40($inp),$xc3,$xc3 + vpxor 0x60($inp),$xd3,$xd3 + lea 0x80($inp),$inp # size optimization + vmovdqu $xa3,0x00($out) + vmovdqu $xb3,0x20($out) + vmovdqu $xc3,0x40($out) + vmovdqu $xd3,0x60($out) + lea 0x80($out),$out # size optimization + + sub \$64*8,$len + jnz .Loop_outer8x + + jmp .Ldone8x + +.Ltail8x: + cmp \$448,$len + jae .L448_or_more8x + cmp \$384,$len + jae .L384_or_more8x + cmp \$320,$len + jae .L320_or_more8x + cmp \$256,$len + jae .L256_or_more8x + cmp \$192,$len + jae .L192_or_more8x + cmp \$128,$len + jae .L128_or_more8x + cmp \$64,$len + jae .L64_or_more8x + + xor %r10,%r10 + vmovdqa $xa0,0x00(%rsp) + vmovdqa $xb0,0x20(%rsp) + jmp .Loop_tail8x + +.align 32 +.L64_or_more8x: + vpxor 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x20($inp),$xb0,$xb0 + vmovdqu $xa0,0x00($out) + vmovdqu $xb0,0x20($out) + je .Ldone8x + + lea 0x40($inp),$inp # inp+=64*1 + xor %r10,%r10 + vmovdqa $xc0,0x00(%rsp) + lea 0x40($out),$out # out+=64*1 + sub \$64,$len # len-=64*1 + vmovdqa $xd0,0x20(%rsp) + jmp .Loop_tail8x + +.align 32 +.L128_or_more8x: + vpxor 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x20($inp),$xb0,$xb0 + vpxor 0x40($inp),$xc0,$xc0 + vpxor 0x60($inp),$xd0,$xd0 + vmovdqu $xa0,0x00($out) + vmovdqu $xb0,0x20($out) + vmovdqu $xc0,0x40($out) + vmovdqu $xd0,0x60($out) + je .Ldone8x + + lea 0x80($inp),$inp # inp+=64*2 + xor %r10,%r10 + vmovdqa $xa1,0x00(%rsp) + lea 0x80($out),$out # out+=64*2 + sub \$128,$len # len-=64*2 + vmovdqa $xb1,0x20(%rsp) + jmp .Loop_tail8x + +.align 32 +.L192_or_more8x: + vpxor 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x20($inp),$xb0,$xb0 + vpxor 0x40($inp),$xc0,$xc0 + vpxor 0x60($inp),$xd0,$xd0 + vpxor 0x80($inp),$xa1,$xa1 + vpxor 0xa0($inp),$xb1,$xb1 + vmovdqu $xa0,0x00($out) + vmovdqu $xb0,0x20($out) + vmovdqu $xc0,0x40($out) + vmovdqu $xd0,0x60($out) + vmovdqu $xa1,0x80($out) + vmovdqu $xb1,0xa0($out) + je .Ldone8x + + lea 0xc0($inp),$inp # inp+=64*3 + xor %r10,%r10 + vmovdqa $xc1,0x00(%rsp) + lea 0xc0($out),$out # out+=64*3 + sub \$192,$len # len-=64*3 + vmovdqa $xd1,0x20(%rsp) + jmp .Loop_tail8x + +.align 32 +.L256_or_more8x: + vpxor 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x20($inp),$xb0,$xb0 + vpxor 0x40($inp),$xc0,$xc0 + vpxor 0x60($inp),$xd0,$xd0 + vpxor 0x80($inp),$xa1,$xa1 + vpxor 0xa0($inp),$xb1,$xb1 + vpxor 0xc0($inp),$xc1,$xc1 + vpxor 0xe0($inp),$xd1,$xd1 + vmovdqu $xa0,0x00($out) + vmovdqu $xb0,0x20($out) + vmovdqu $xc0,0x40($out) + vmovdqu $xd0,0x60($out) + vmovdqu $xa1,0x80($out) + vmovdqu $xb1,0xa0($out) + vmovdqu $xc1,0xc0($out) + vmovdqu $xd1,0xe0($out) + je .Ldone8x + + lea 0x100($inp),$inp # inp+=64*4 + xor %r10,%r10 + vmovdqa $xa2,0x00(%rsp) + lea 0x100($out),$out # out+=64*4 + sub \$256,$len # len-=64*4 + vmovdqa $xb2,0x20(%rsp) + jmp .Loop_tail8x + +.align 32 +.L320_or_more8x: + vpxor 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x20($inp),$xb0,$xb0 + vpxor 0x40($inp),$xc0,$xc0 + vpxor 0x60($inp),$xd0,$xd0 + vpxor 0x80($inp),$xa1,$xa1 + vpxor 0xa0($inp),$xb1,$xb1 + vpxor 0xc0($inp),$xc1,$xc1 + vpxor 0xe0($inp),$xd1,$xd1 + vpxor 0x100($inp),$xa2,$xa2 + vpxor 0x120($inp),$xb2,$xb2 + vmovdqu $xa0,0x00($out) + vmovdqu $xb0,0x20($out) + vmovdqu $xc0,0x40($out) + vmovdqu $xd0,0x60($out) + vmovdqu $xa1,0x80($out) + vmovdqu $xb1,0xa0($out) + vmovdqu $xc1,0xc0($out) + vmovdqu $xd1,0xe0($out) + vmovdqu $xa2,0x100($out) + vmovdqu $xb2,0x120($out) + je .Ldone8x + + lea 0x140($inp),$inp # inp+=64*5 + xor %r10,%r10 + vmovdqa $xc2,0x00(%rsp) + lea 0x140($out),$out # out+=64*5 + sub \$320,$len # len-=64*5 + vmovdqa $xd2,0x20(%rsp) + jmp .Loop_tail8x + +.align 32 +.L384_or_more8x: + vpxor 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x20($inp),$xb0,$xb0 + vpxor 0x40($inp),$xc0,$xc0 + vpxor 0x60($inp),$xd0,$xd0 + vpxor 0x80($inp),$xa1,$xa1 + vpxor 0xa0($inp),$xb1,$xb1 + vpxor 0xc0($inp),$xc1,$xc1 + vpxor 0xe0($inp),$xd1,$xd1 + vpxor 0x100($inp),$xa2,$xa2 + vpxor 0x120($inp),$xb2,$xb2 + vpxor 0x140($inp),$xc2,$xc2 + vpxor 0x160($inp),$xd2,$xd2 + vmovdqu $xa0,0x00($out) + vmovdqu $xb0,0x20($out) + vmovdqu $xc0,0x40($out) + vmovdqu $xd0,0x60($out) + vmovdqu $xa1,0x80($out) + vmovdqu $xb1,0xa0($out) + vmovdqu $xc1,0xc0($out) + vmovdqu $xd1,0xe0($out) + vmovdqu $xa2,0x100($out) + vmovdqu $xb2,0x120($out) + vmovdqu $xc2,0x140($out) + vmovdqu $xd2,0x160($out) + je .Ldone8x + + lea 0x180($inp),$inp # inp+=64*6 + xor %r10,%r10 + vmovdqa $xa3,0x00(%rsp) + lea 0x180($out),$out # out+=64*6 + sub \$384,$len # len-=64*6 + vmovdqa $xb3,0x20(%rsp) + jmp .Loop_tail8x + +.align 32 +.L448_or_more8x: + vpxor 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x20($inp),$xb0,$xb0 + vpxor 0x40($inp),$xc0,$xc0 + vpxor 0x60($inp),$xd0,$xd0 + vpxor 0x80($inp),$xa1,$xa1 + vpxor 0xa0($inp),$xb1,$xb1 + vpxor 0xc0($inp),$xc1,$xc1 + vpxor 0xe0($inp),$xd1,$xd1 + vpxor 0x100($inp),$xa2,$xa2 + vpxor 0x120($inp),$xb2,$xb2 + vpxor 0x140($inp),$xc2,$xc2 + vpxor 0x160($inp),$xd2,$xd2 + vpxor 0x180($inp),$xa3,$xa3 + vpxor 0x1a0($inp),$xb3,$xb3 + vmovdqu $xa0,0x00($out) + vmovdqu $xb0,0x20($out) + vmovdqu $xc0,0x40($out) + vmovdqu $xd0,0x60($out) + vmovdqu $xa1,0x80($out) + vmovdqu $xb1,0xa0($out) + vmovdqu $xc1,0xc0($out) + vmovdqu $xd1,0xe0($out) + vmovdqu $xa2,0x100($out) + vmovdqu $xb2,0x120($out) + vmovdqu $xc2,0x140($out) + vmovdqu $xd2,0x160($out) + vmovdqu $xa3,0x180($out) + vmovdqu $xb3,0x1a0($out) + je .Ldone8x + + lea 0x1c0($inp),$inp # inp+=64*7 + xor %r10,%r10 + vmovdqa $xc3,0x00(%rsp) + lea 0x1c0($out),$out # out+=64*7 + sub \$448,$len # len-=64*7 + vmovdqa $xd3,0x20(%rsp) + +.Loop_tail8x: + movzb ($inp,%r10),%eax + movzb (%rsp,%r10),%ecx + lea 1(%r10),%r10 + xor %ecx,%eax + mov %al,-1($out,%r10) + dec $len + jnz .Loop_tail8x + +.Ldone8x: + vzeroall +___ +$code.=<<___ if ($win64); + movaps -0xa8(%r9),%xmm6 + movaps -0x98(%r9),%xmm7 + movaps -0x88(%r9),%xmm8 + movaps -0x78(%r9),%xmm9 + movaps -0x68(%r9),%xmm10 + movaps -0x58(%r9),%xmm11 + movaps -0x48(%r9),%xmm12 + movaps -0x38(%r9),%xmm13 + movaps -0x28(%r9),%xmm14 + movaps -0x18(%r9),%xmm15 +___ +$code.=<<___; + lea (%r9),%rsp +.cfi_def_cfa_register %rsp +.L8x_epilogue: + ret +.cfi_endproc +.size ChaCha20_8x,.-ChaCha20_8x +___ +} + +######################################################################## +# AVX512 code paths +if ($avx>2) { +# This one handles shorter inputs... + +my ($a,$b,$c,$d, $a_,$b_,$c_,$d_,$fourz) = map("%zmm$_",(0..3,16..20)); +my ($t0,$t1,$t2,$t3) = map("%xmm$_",(4..7)); + +sub vpxord() # size optimization +{ my $opcode = "vpxor"; # adhere to vpxor when possible + + foreach (@_) { + if (/%([zy])mm([0-9]+)/ && ($1 eq "z" || $2>=16)) { + $opcode = "vpxord"; + last; + } + } + + $code .= "\t$opcode\t".join(',',reverse @_)."\n"; +} + +sub AVX512ROUND { # critical path is 14 "SIMD ticks" per round + &vpaddd ($a,$a,$b); + &vpxord ($d,$d,$a); + &vprold ($d,$d,16); + + &vpaddd ($c,$c,$d); + &vpxord ($b,$b,$c); + &vprold ($b,$b,12); + + &vpaddd ($a,$a,$b); + &vpxord ($d,$d,$a); + &vprold ($d,$d,8); + + &vpaddd ($c,$c,$d); + &vpxord ($b,$b,$c); + &vprold ($b,$b,7); +} + +my $xframe = $win64 ? 32+8 : 8; + +$code.=<<___; +.type ChaCha20_avx512,\@function,5 +.align 32 +ChaCha20_avx512: +.cfi_startproc +.LChaCha20_avx512: + mov %rsp,%r9 # frame pointer +.cfi_def_cfa_register %r9 + cmp \$512,$len + ja .LChaCha20_16x + + sub \$64+$xframe,%rsp +___ +$code.=<<___ if ($win64); + movaps %xmm6,-0x28(%r9) + movaps %xmm7,-0x18(%r9) +.Lavx512_body: +___ +$code.=<<___; + vbroadcasti32x4 .Lsigma(%rip),$a + vbroadcasti32x4 ($key),$b + vbroadcasti32x4 16($key),$c + vbroadcasti32x4 ($counter),$d + + vmovdqa32 $a,$a_ + vmovdqa32 $b,$b_ + vmovdqa32 $c,$c_ + vpaddd .Lzeroz(%rip),$d,$d + vmovdqa32 .Lfourz(%rip),$fourz + mov \$10,$counter # reuse $counter + vmovdqa32 $d,$d_ + jmp .Loop_avx512 + +.align 16 +.Loop_outer_avx512: + vmovdqa32 $a_,$a + vmovdqa32 $b_,$b + vmovdqa32 $c_,$c + vpaddd $fourz,$d_,$d + mov \$10,$counter + vmovdqa32 $d,$d_ + jmp .Loop_avx512 + +.align 32 +.Loop_avx512: +___ + &AVX512ROUND(); + &vpshufd ($c,$c,0b01001110); + &vpshufd ($b,$b,0b00111001); + &vpshufd ($d,$d,0b10010011); + + &AVX512ROUND(); + &vpshufd ($c,$c,0b01001110); + &vpshufd ($b,$b,0b10010011); + &vpshufd ($d,$d,0b00111001); + + &dec ($counter); + &jnz (".Loop_avx512"); + +$code.=<<___; + vpaddd $a_,$a,$a + vpaddd $b_,$b,$b + vpaddd $c_,$c,$c + vpaddd $d_,$d,$d + + sub \$64,$len + jb .Ltail64_avx512 + + vpxor 0x00($inp),%x#$a,$t0 # xor with input + vpxor 0x10($inp),%x#$b,$t1 + vpxor 0x20($inp),%x#$c,$t2 + vpxor 0x30($inp),%x#$d,$t3 + lea 0x40($inp),$inp # inp+=64 + + vmovdqu $t0,0x00($out) # write output + vmovdqu $t1,0x10($out) + vmovdqu $t2,0x20($out) + vmovdqu $t3,0x30($out) + lea 0x40($out),$out # out+=64 + + jz .Ldone_avx512 + + vextracti32x4 \$1,$a,$t0 + vextracti32x4 \$1,$b,$t1 + vextracti32x4 \$1,$c,$t2 + vextracti32x4 \$1,$d,$t3 + + sub \$64,$len + jb .Ltail_avx512 + + vpxor 0x00($inp),$t0,$t0 # xor with input + vpxor 0x10($inp),$t1,$t1 + vpxor 0x20($inp),$t2,$t2 + vpxor 0x30($inp),$t3,$t3 + lea 0x40($inp),$inp # inp+=64 + + vmovdqu $t0,0x00($out) # write output + vmovdqu $t1,0x10($out) + vmovdqu $t2,0x20($out) + vmovdqu $t3,0x30($out) + lea 0x40($out),$out # out+=64 + + jz .Ldone_avx512 + + vextracti32x4 \$2,$a,$t0 + vextracti32x4 \$2,$b,$t1 + vextracti32x4 \$2,$c,$t2 + vextracti32x4 \$2,$d,$t3 + + sub \$64,$len + jb .Ltail_avx512 + + vpxor 0x00($inp),$t0,$t0 # xor with input + vpxor 0x10($inp),$t1,$t1 + vpxor 0x20($inp),$t2,$t2 + vpxor 0x30($inp),$t3,$t3 + lea 0x40($inp),$inp # inp+=64 + + vmovdqu $t0,0x00($out) # write output + vmovdqu $t1,0x10($out) + vmovdqu $t2,0x20($out) + vmovdqu $t3,0x30($out) + lea 0x40($out),$out # out+=64 + + jz .Ldone_avx512 + + vextracti32x4 \$3,$a,$t0 + vextracti32x4 \$3,$b,$t1 + vextracti32x4 \$3,$c,$t2 + vextracti32x4 \$3,$d,$t3 + + sub \$64,$len + jb .Ltail_avx512 + + vpxor 0x00($inp),$t0,$t0 # xor with input + vpxor 0x10($inp),$t1,$t1 + vpxor 0x20($inp),$t2,$t2 + vpxor 0x30($inp),$t3,$t3 + lea 0x40($inp),$inp # inp+=64 + + vmovdqu $t0,0x00($out) # write output + vmovdqu $t1,0x10($out) + vmovdqu $t2,0x20($out) + vmovdqu $t3,0x30($out) + lea 0x40($out),$out # out+=64 + + jnz .Loop_outer_avx512 + + jmp .Ldone_avx512 + +.align 16 +.Ltail64_avx512: + vmovdqa %x#$a,0x00(%rsp) + vmovdqa %x#$b,0x10(%rsp) + vmovdqa %x#$c,0x20(%rsp) + vmovdqa %x#$d,0x30(%rsp) + add \$64,$len + jmp .Loop_tail_avx512 + +.align 16 +.Ltail_avx512: + vmovdqa $t0,0x00(%rsp) + vmovdqa $t1,0x10(%rsp) + vmovdqa $t2,0x20(%rsp) + vmovdqa $t3,0x30(%rsp) + add \$64,$len + +.Loop_tail_avx512: + movzb ($inp,$counter),%eax + movzb (%rsp,$counter),%ecx + lea 1($counter),$counter + xor %ecx,%eax + mov %al,-1($out,$counter) + dec $len + jnz .Loop_tail_avx512 + + vmovdqu32 $a_,0x00(%rsp) + +.Ldone_avx512: + vzeroall +___ +$code.=<<___ if ($win64); + movaps -0x28(%r9),%xmm6 + movaps -0x18(%r9),%xmm7 +___ +$code.=<<___; + lea (%r9),%rsp +.cfi_def_cfa_register %rsp +.Lavx512_epilogue: + ret +.cfi_endproc +.size ChaCha20_avx512,.-ChaCha20_avx512 +___ + +map(s/%z/%y/, $a,$b,$c,$d, $a_,$b_,$c_,$d_,$fourz); + +$code.=<<___; +.type ChaCha20_avx512vl,\@function,5 +.align 32 +ChaCha20_avx512vl: +.cfi_startproc +.LChaCha20_avx512vl: + mov %rsp,%r9 # frame pointer +.cfi_def_cfa_register %r9 + cmp \$128,$len + ja .LChaCha20_8xvl + + sub \$64+$xframe,%rsp +___ +$code.=<<___ if ($win64); + movaps %xmm6,-0x28(%r9) + movaps %xmm7,-0x18(%r9) +.Lavx512vl_body: +___ +$code.=<<___; + vbroadcasti128 .Lsigma(%rip),$a + vbroadcasti128 ($key),$b + vbroadcasti128 16($key),$c + vbroadcasti128 ($counter),$d + + vmovdqa32 $a,$a_ + vmovdqa32 $b,$b_ + vmovdqa32 $c,$c_ + vpaddd .Lzeroz(%rip),$d,$d + vmovdqa32 .Ltwoy(%rip),$fourz + mov \$10,$counter # reuse $counter + vmovdqa32 $d,$d_ + jmp .Loop_avx512vl + +.align 16 +.Loop_outer_avx512vl: + vmovdqa32 $c_,$c + vpaddd $fourz,$d_,$d + mov \$10,$counter + vmovdqa32 $d,$d_ + jmp .Loop_avx512vl + +.align 32 +.Loop_avx512vl: +___ + &AVX512ROUND(); + &vpshufd ($c,$c,0b01001110); + &vpshufd ($b,$b,0b00111001); + &vpshufd ($d,$d,0b10010011); + + &AVX512ROUND(); + &vpshufd ($c,$c,0b01001110); + &vpshufd ($b,$b,0b10010011); + &vpshufd ($d,$d,0b00111001); + + &dec ($counter); + &jnz (".Loop_avx512vl"); + +$code.=<<___; + vpaddd $a_,$a,$a + vpaddd $b_,$b,$b + vpaddd $c_,$c,$c + vpaddd $d_,$d,$d + + sub \$64,$len + jb .Ltail64_avx512vl + + vpxor 0x00($inp),%x#$a,$t0 # xor with input + vpxor 0x10($inp),%x#$b,$t1 + vpxor 0x20($inp),%x#$c,$t2 + vpxor 0x30($inp),%x#$d,$t3 + lea 0x40($inp),$inp # inp+=64 + + vmovdqu $t0,0x00($out) # write output + vmovdqu $t1,0x10($out) + vmovdqu $t2,0x20($out) + vmovdqu $t3,0x30($out) + lea 0x40($out),$out # out+=64 + + jz .Ldone_avx512vl + + vextracti128 \$1,$a,$t0 + vextracti128 \$1,$b,$t1 + vextracti128 \$1,$c,$t2 + vextracti128 \$1,$d,$t3 + + sub \$64,$len + jb .Ltail_avx512vl + + vpxor 0x00($inp),$t0,$t0 # xor with input + vpxor 0x10($inp),$t1,$t1 + vpxor 0x20($inp),$t2,$t2 + vpxor 0x30($inp),$t3,$t3 + lea 0x40($inp),$inp # inp+=64 + + vmovdqu $t0,0x00($out) # write output + vmovdqu $t1,0x10($out) + vmovdqu $t2,0x20($out) + vmovdqu $t3,0x30($out) + lea 0x40($out),$out # out+=64 + + vmovdqa32 $a_,$a + vmovdqa32 $b_,$b + jnz .Loop_outer_avx512vl + + jmp .Ldone_avx512vl + +.align 16 +.Ltail64_avx512vl: + vmovdqa %x#$a,0x00(%rsp) + vmovdqa %x#$b,0x10(%rsp) + vmovdqa %x#$c,0x20(%rsp) + vmovdqa %x#$d,0x30(%rsp) + add \$64,$len + jmp .Loop_tail_avx512vl + +.align 16 +.Ltail_avx512vl: + vmovdqa $t0,0x00(%rsp) + vmovdqa $t1,0x10(%rsp) + vmovdqa $t2,0x20(%rsp) + vmovdqa $t3,0x30(%rsp) + add \$64,$len + +.Loop_tail_avx512vl: + movzb ($inp,$counter),%eax + movzb (%rsp,$counter),%ecx + lea 1($counter),$counter + xor %ecx,%eax + mov %al,-1($out,$counter) + dec $len + jnz .Loop_tail_avx512vl + + vmovdqu32 $a_,0x00(%rsp) + vmovdqu32 $a_,0x20(%rsp) + +.Ldone_avx512vl: + vzeroall +___ +$code.=<<___ if ($win64); + movaps -0x28(%r9),%xmm6 + movaps -0x18(%r9),%xmm7 +___ +$code.=<<___; + lea (%r9),%rsp +.cfi_def_cfa_register %rsp +.Lavx512vl_epilogue: + ret +.cfi_endproc +.size ChaCha20_avx512vl,.-ChaCha20_avx512vl +___ +} +if ($avx>2) { +# This one handles longer inputs... + +my ($xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3, + $xc0,$xc1,$xc2,$xc3, $xd0,$xd1,$xd2,$xd3)=map("%zmm$_",(0..15)); +my @xx=($xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3, + $xc0,$xc1,$xc2,$xc3, $xd0,$xd1,$xd2,$xd3); +my @key=map("%zmm$_",(16..31)); +my ($xt0,$xt1,$xt2,$xt3)=@key[0..3]; + +sub AVX512_lane_ROUND { +my ($a0,$b0,$c0,$d0)=@_; +my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0)); +my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1)); +my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2)); +my @x=map("\"$_\"",@xx); + + ( + "&vpaddd (@x[$a0],@x[$a0],@x[$b0])", # Q1 + "&vpaddd (@x[$a1],@x[$a1],@x[$b1])", # Q2 + "&vpaddd (@x[$a2],@x[$a2],@x[$b2])", # Q3 + "&vpaddd (@x[$a3],@x[$a3],@x[$b3])", # Q4 + "&vpxord (@x[$d0],@x[$d0],@x[$a0])", + "&vpxord (@x[$d1],@x[$d1],@x[$a1])", + "&vpxord (@x[$d2],@x[$d2],@x[$a2])", + "&vpxord (@x[$d3],@x[$d3],@x[$a3])", + "&vprold (@x[$d0],@x[$d0],16)", + "&vprold (@x[$d1],@x[$d1],16)", + "&vprold (@x[$d2],@x[$d2],16)", + "&vprold (@x[$d3],@x[$d3],16)", + + "&vpaddd (@x[$c0],@x[$c0],@x[$d0])", + "&vpaddd (@x[$c1],@x[$c1],@x[$d1])", + "&vpaddd (@x[$c2],@x[$c2],@x[$d2])", + "&vpaddd (@x[$c3],@x[$c3],@x[$d3])", + "&vpxord (@x[$b0],@x[$b0],@x[$c0])", + "&vpxord (@x[$b1],@x[$b1],@x[$c1])", + "&vpxord (@x[$b2],@x[$b2],@x[$c2])", + "&vpxord (@x[$b3],@x[$b3],@x[$c3])", + "&vprold (@x[$b0],@x[$b0],12)", + "&vprold (@x[$b1],@x[$b1],12)", + "&vprold (@x[$b2],@x[$b2],12)", + "&vprold (@x[$b3],@x[$b3],12)", + + "&vpaddd (@x[$a0],@x[$a0],@x[$b0])", + "&vpaddd (@x[$a1],@x[$a1],@x[$b1])", + "&vpaddd (@x[$a2],@x[$a2],@x[$b2])", + "&vpaddd (@x[$a3],@x[$a3],@x[$b3])", + "&vpxord (@x[$d0],@x[$d0],@x[$a0])", + "&vpxord (@x[$d1],@x[$d1],@x[$a1])", + "&vpxord (@x[$d2],@x[$d2],@x[$a2])", + "&vpxord (@x[$d3],@x[$d3],@x[$a3])", + "&vprold (@x[$d0],@x[$d0],8)", + "&vprold (@x[$d1],@x[$d1],8)", + "&vprold (@x[$d2],@x[$d2],8)", + "&vprold (@x[$d3],@x[$d3],8)", + + "&vpaddd (@x[$c0],@x[$c0],@x[$d0])", + "&vpaddd (@x[$c1],@x[$c1],@x[$d1])", + "&vpaddd (@x[$c2],@x[$c2],@x[$d2])", + "&vpaddd (@x[$c3],@x[$c3],@x[$d3])", + "&vpxord (@x[$b0],@x[$b0],@x[$c0])", + "&vpxord (@x[$b1],@x[$b1],@x[$c1])", + "&vpxord (@x[$b2],@x[$b2],@x[$c2])", + "&vpxord (@x[$b3],@x[$b3],@x[$c3])", + "&vprold (@x[$b0],@x[$b0],7)", + "&vprold (@x[$b1],@x[$b1],7)", + "&vprold (@x[$b2],@x[$b2],7)", + "&vprold (@x[$b3],@x[$b3],7)" + ); +} + +my $xframe = $win64 ? 0xa8 : 8; + +$code.=<<___; +.type ChaCha20_16x,\@function,5 +.align 32 +ChaCha20_16x: +.cfi_startproc +.LChaCha20_16x: + mov %rsp,%r9 # frame register +.cfi_def_cfa_register %r9 + sub \$64+$xframe,%rsp + and \$-64,%rsp +___ +$code.=<<___ if ($win64); + movaps %xmm6,-0xa8(%r9) + movaps %xmm7,-0x98(%r9) + movaps %xmm8,-0x88(%r9) + movaps %xmm9,-0x78(%r9) + movaps %xmm10,-0x68(%r9) + movaps %xmm11,-0x58(%r9) + movaps %xmm12,-0x48(%r9) + movaps %xmm13,-0x38(%r9) + movaps %xmm14,-0x28(%r9) + movaps %xmm15,-0x18(%r9) +.L16x_body: +___ +$code.=<<___; + vzeroupper + + lea .Lsigma(%rip),%r10 + vbroadcasti32x4 (%r10),$xa3 # key[0] + vbroadcasti32x4 ($key),$xb3 # key[1] + vbroadcasti32x4 16($key),$xc3 # key[2] + vbroadcasti32x4 ($counter),$xd3 # key[3] + + vpshufd \$0x00,$xa3,$xa0 # smash key by lanes... + vpshufd \$0x55,$xa3,$xa1 + vpshufd \$0xaa,$xa3,$xa2 + vpshufd \$0xff,$xa3,$xa3 + vmovdqa64 $xa0,@key[0] + vmovdqa64 $xa1,@key[1] + vmovdqa64 $xa2,@key[2] + vmovdqa64 $xa3,@key[3] + + vpshufd \$0x00,$xb3,$xb0 + vpshufd \$0x55,$xb3,$xb1 + vpshufd \$0xaa,$xb3,$xb2 + vpshufd \$0xff,$xb3,$xb3 + vmovdqa64 $xb0,@key[4] + vmovdqa64 $xb1,@key[5] + vmovdqa64 $xb2,@key[6] + vmovdqa64 $xb3,@key[7] + + vpshufd \$0x00,$xc3,$xc0 + vpshufd \$0x55,$xc3,$xc1 + vpshufd \$0xaa,$xc3,$xc2 + vpshufd \$0xff,$xc3,$xc3 + vmovdqa64 $xc0,@key[8] + vmovdqa64 $xc1,@key[9] + vmovdqa64 $xc2,@key[10] + vmovdqa64 $xc3,@key[11] + + vpshufd \$0x00,$xd3,$xd0 + vpshufd \$0x55,$xd3,$xd1 + vpshufd \$0xaa,$xd3,$xd2 + vpshufd \$0xff,$xd3,$xd3 + vpaddd .Lincz(%rip),$xd0,$xd0 # don't save counters yet + vmovdqa64 $xd0,@key[12] + vmovdqa64 $xd1,@key[13] + vmovdqa64 $xd2,@key[14] + vmovdqa64 $xd3,@key[15] + + mov \$10,%eax + jmp .Loop16x + +.align 32 +.Loop_outer16x: + vpbroadcastd 0(%r10),$xa0 # reload key + vpbroadcastd 4(%r10),$xa1 + vpbroadcastd 8(%r10),$xa2 + vpbroadcastd 12(%r10),$xa3 + vpaddd .Lsixteen(%rip),@key[12],@key[12] # next SIMD counters + vmovdqa64 @key[4],$xb0 + vmovdqa64 @key[5],$xb1 + vmovdqa64 @key[6],$xb2 + vmovdqa64 @key[7],$xb3 + vmovdqa64 @key[8],$xc0 + vmovdqa64 @key[9],$xc1 + vmovdqa64 @key[10],$xc2 + vmovdqa64 @key[11],$xc3 + vmovdqa64 @key[12],$xd0 + vmovdqa64 @key[13],$xd1 + vmovdqa64 @key[14],$xd2 + vmovdqa64 @key[15],$xd3 + + vmovdqa64 $xa0,@key[0] + vmovdqa64 $xa1,@key[1] + vmovdqa64 $xa2,@key[2] + vmovdqa64 $xa3,@key[3] + + mov \$10,%eax + jmp .Loop16x + +.align 32 +.Loop16x: +___ + foreach (&AVX512_lane_ROUND(0, 4, 8,12)) { eval; } + foreach (&AVX512_lane_ROUND(0, 5,10,15)) { eval; } +$code.=<<___; + dec %eax + jnz .Loop16x + + vpaddd @key[0],$xa0,$xa0 # accumulate key + vpaddd @key[1],$xa1,$xa1 + vpaddd @key[2],$xa2,$xa2 + vpaddd @key[3],$xa3,$xa3 + + vpunpckldq $xa1,$xa0,$xt2 # "de-interlace" data + vpunpckldq $xa3,$xa2,$xt3 + vpunpckhdq $xa1,$xa0,$xa0 + vpunpckhdq $xa3,$xa2,$xa2 + vpunpcklqdq $xt3,$xt2,$xa1 # "a0" + vpunpckhqdq $xt3,$xt2,$xt2 # "a1" + vpunpcklqdq $xa2,$xa0,$xa3 # "a2" + vpunpckhqdq $xa2,$xa0,$xa0 # "a3" +___ + ($xa0,$xa1,$xa2,$xa3,$xt2)=($xa1,$xt2,$xa3,$xa0,$xa2); +$code.=<<___; + vpaddd @key[4],$xb0,$xb0 + vpaddd @key[5],$xb1,$xb1 + vpaddd @key[6],$xb2,$xb2 + vpaddd @key[7],$xb3,$xb3 + + vpunpckldq $xb1,$xb0,$xt2 + vpunpckldq $xb3,$xb2,$xt3 + vpunpckhdq $xb1,$xb0,$xb0 + vpunpckhdq $xb3,$xb2,$xb2 + vpunpcklqdq $xt3,$xt2,$xb1 # "b0" + vpunpckhqdq $xt3,$xt2,$xt2 # "b1" + vpunpcklqdq $xb2,$xb0,$xb3 # "b2" + vpunpckhqdq $xb2,$xb0,$xb0 # "b3" +___ + ($xb0,$xb1,$xb2,$xb3,$xt2)=($xb1,$xt2,$xb3,$xb0,$xb2); +$code.=<<___; + vshufi32x4 \$0x44,$xb0,$xa0,$xt3 # "de-interlace" further + vshufi32x4 \$0xee,$xb0,$xa0,$xb0 + vshufi32x4 \$0x44,$xb1,$xa1,$xa0 + vshufi32x4 \$0xee,$xb1,$xa1,$xb1 + vshufi32x4 \$0x44,$xb2,$xa2,$xa1 + vshufi32x4 \$0xee,$xb2,$xa2,$xb2 + vshufi32x4 \$0x44,$xb3,$xa3,$xa2 + vshufi32x4 \$0xee,$xb3,$xa3,$xb3 +___ + ($xa0,$xa1,$xa2,$xa3,$xt3)=($xt3,$xa0,$xa1,$xa2,$xa3); +$code.=<<___; + vpaddd @key[8],$xc0,$xc0 + vpaddd @key[9],$xc1,$xc1 + vpaddd @key[10],$xc2,$xc2 + vpaddd @key[11],$xc3,$xc3 + + vpunpckldq $xc1,$xc0,$xt2 + vpunpckldq $xc3,$xc2,$xt3 + vpunpckhdq $xc1,$xc0,$xc0 + vpunpckhdq $xc3,$xc2,$xc2 + vpunpcklqdq $xt3,$xt2,$xc1 # "c0" + vpunpckhqdq $xt3,$xt2,$xt2 # "c1" + vpunpcklqdq $xc2,$xc0,$xc3 # "c2" + vpunpckhqdq $xc2,$xc0,$xc0 # "c3" +___ + ($xc0,$xc1,$xc2,$xc3,$xt2)=($xc1,$xt2,$xc3,$xc0,$xc2); +$code.=<<___; + vpaddd @key[12],$xd0,$xd0 + vpaddd @key[13],$xd1,$xd1 + vpaddd @key[14],$xd2,$xd2 + vpaddd @key[15],$xd3,$xd3 + + vpunpckldq $xd1,$xd0,$xt2 + vpunpckldq $xd3,$xd2,$xt3 + vpunpckhdq $xd1,$xd0,$xd0 + vpunpckhdq $xd3,$xd2,$xd2 + vpunpcklqdq $xt3,$xt2,$xd1 # "d0" + vpunpckhqdq $xt3,$xt2,$xt2 # "d1" + vpunpcklqdq $xd2,$xd0,$xd3 # "d2" + vpunpckhqdq $xd2,$xd0,$xd0 # "d3" +___ + ($xd0,$xd1,$xd2,$xd3,$xt2)=($xd1,$xt2,$xd3,$xd0,$xd2); +$code.=<<___; + vshufi32x4 \$0x44,$xd0,$xc0,$xt3 # "de-interlace" further + vshufi32x4 \$0xee,$xd0,$xc0,$xd0 + vshufi32x4 \$0x44,$xd1,$xc1,$xc0 + vshufi32x4 \$0xee,$xd1,$xc1,$xd1 + vshufi32x4 \$0x44,$xd2,$xc2,$xc1 + vshufi32x4 \$0xee,$xd2,$xc2,$xd2 + vshufi32x4 \$0x44,$xd3,$xc3,$xc2 + vshufi32x4 \$0xee,$xd3,$xc3,$xd3 +___ + ($xc0,$xc1,$xc2,$xc3,$xt3)=($xt3,$xc0,$xc1,$xc2,$xc3); +$code.=<<___; + vshufi32x4 \$0x88,$xc0,$xa0,$xt0 # "de-interlace" further + vshufi32x4 \$0xdd,$xc0,$xa0,$xa0 + vshufi32x4 \$0x88,$xd0,$xb0,$xc0 + vshufi32x4 \$0xdd,$xd0,$xb0,$xd0 + vshufi32x4 \$0x88,$xc1,$xa1,$xt1 + vshufi32x4 \$0xdd,$xc1,$xa1,$xa1 + vshufi32x4 \$0x88,$xd1,$xb1,$xc1 + vshufi32x4 \$0xdd,$xd1,$xb1,$xd1 + vshufi32x4 \$0x88,$xc2,$xa2,$xt2 + vshufi32x4 \$0xdd,$xc2,$xa2,$xa2 + vshufi32x4 \$0x88,$xd2,$xb2,$xc2 + vshufi32x4 \$0xdd,$xd2,$xb2,$xd2 + vshufi32x4 \$0x88,$xc3,$xa3,$xt3 + vshufi32x4 \$0xdd,$xc3,$xa3,$xa3 + vshufi32x4 \$0x88,$xd3,$xb3,$xc3 + vshufi32x4 \$0xdd,$xd3,$xb3,$xd3 +___ + ($xa0,$xa1,$xa2,$xa3,$xb0,$xb1,$xb2,$xb3)= + ($xt0,$xt1,$xt2,$xt3,$xa0,$xa1,$xa2,$xa3); + + ($xa0,$xb0,$xc0,$xd0, $xa1,$xb1,$xc1,$xd1, + $xa2,$xb2,$xc2,$xd2, $xa3,$xb3,$xc3,$xd3) = + ($xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3, + $xc0,$xc1,$xc2,$xc3, $xd0,$xd1,$xd2,$xd3); +$code.=<<___; + cmp \$64*16,$len + jb .Ltail16x + + vpxord 0x00($inp),$xa0,$xa0 # xor with input + vpxord 0x40($inp),$xb0,$xb0 + vpxord 0x80($inp),$xc0,$xc0 + vpxord 0xc0($inp),$xd0,$xd0 + vmovdqu32 $xa0,0x00($out) + vmovdqu32 $xb0,0x40($out) + vmovdqu32 $xc0,0x80($out) + vmovdqu32 $xd0,0xc0($out) + + vpxord 0x100($inp),$xa1,$xa1 + vpxord 0x140($inp),$xb1,$xb1 + vpxord 0x180($inp),$xc1,$xc1 + vpxord 0x1c0($inp),$xd1,$xd1 + vmovdqu32 $xa1,0x100($out) + vmovdqu32 $xb1,0x140($out) + vmovdqu32 $xc1,0x180($out) + vmovdqu32 $xd1,0x1c0($out) + + vpxord 0x200($inp),$xa2,$xa2 + vpxord 0x240($inp),$xb2,$xb2 + vpxord 0x280($inp),$xc2,$xc2 + vpxord 0x2c0($inp),$xd2,$xd2 + vmovdqu32 $xa2,0x200($out) + vmovdqu32 $xb2,0x240($out) + vmovdqu32 $xc2,0x280($out) + vmovdqu32 $xd2,0x2c0($out) + + vpxord 0x300($inp),$xa3,$xa3 + vpxord 0x340($inp),$xb3,$xb3 + vpxord 0x380($inp),$xc3,$xc3 + vpxord 0x3c0($inp),$xd3,$xd3 + lea 0x400($inp),$inp + vmovdqu32 $xa3,0x300($out) + vmovdqu32 $xb3,0x340($out) + vmovdqu32 $xc3,0x380($out) + vmovdqu32 $xd3,0x3c0($out) + lea 0x400($out),$out + + sub \$64*16,$len + jnz .Loop_outer16x + + jmp .Ldone16x + +.align 32 +.Ltail16x: + xor %r10,%r10 + sub $inp,$out + cmp \$64*1,$len + jb .Less_than_64_16x + vpxord ($inp),$xa0,$xa0 # xor with input + vmovdqu32 $xa0,($out,$inp) + je .Ldone16x + vmovdqa32 $xb0,$xa0 + lea 64($inp),$inp + + cmp \$64*2,$len + jb .Less_than_64_16x + vpxord ($inp),$xb0,$xb0 + vmovdqu32 $xb0,($out,$inp) + je .Ldone16x + vmovdqa32 $xc0,$xa0 + lea 64($inp),$inp + + cmp \$64*3,$len + jb .Less_than_64_16x + vpxord ($inp),$xc0,$xc0 + vmovdqu32 $xc0,($out,$inp) + je .Ldone16x + vmovdqa32 $xd0,$xa0 + lea 64($inp),$inp + + cmp \$64*4,$len + jb .Less_than_64_16x + vpxord ($inp),$xd0,$xd0 + vmovdqu32 $xd0,($out,$inp) + je .Ldone16x + vmovdqa32 $xa1,$xa0 + lea 64($inp),$inp + + cmp \$64*5,$len + jb .Less_than_64_16x + vpxord ($inp),$xa1,$xa1 + vmovdqu32 $xa1,($out,$inp) + je .Ldone16x + vmovdqa32 $xb1,$xa0 + lea 64($inp),$inp + + cmp \$64*6,$len + jb .Less_than_64_16x + vpxord ($inp),$xb1,$xb1 + vmovdqu32 $xb1,($out,$inp) + je .Ldone16x + vmovdqa32 $xc1,$xa0 + lea 64($inp),$inp + + cmp \$64*7,$len + jb .Less_than_64_16x + vpxord ($inp),$xc1,$xc1 + vmovdqu32 $xc1,($out,$inp) + je .Ldone16x + vmovdqa32 $xd1,$xa0 + lea 64($inp),$inp + + cmp \$64*8,$len + jb .Less_than_64_16x + vpxord ($inp),$xd1,$xd1 + vmovdqu32 $xd1,($out,$inp) + je .Ldone16x + vmovdqa32 $xa2,$xa0 + lea 64($inp),$inp + + cmp \$64*9,$len + jb .Less_than_64_16x + vpxord ($inp),$xa2,$xa2 + vmovdqu32 $xa2,($out,$inp) + je .Ldone16x + vmovdqa32 $xb2,$xa0 + lea 64($inp),$inp + + cmp \$64*10,$len + jb .Less_than_64_16x + vpxord ($inp),$xb2,$xb2 + vmovdqu32 $xb2,($out,$inp) + je .Ldone16x + vmovdqa32 $xc2,$xa0 + lea 64($inp),$inp + + cmp \$64*11,$len + jb .Less_than_64_16x + vpxord ($inp),$xc2,$xc2 + vmovdqu32 $xc2,($out,$inp) + je .Ldone16x + vmovdqa32 $xd2,$xa0 + lea 64($inp),$inp + + cmp \$64*12,$len + jb .Less_than_64_16x + vpxord ($inp),$xd2,$xd2 + vmovdqu32 $xd2,($out,$inp) + je .Ldone16x + vmovdqa32 $xa3,$xa0 + lea 64($inp),$inp + + cmp \$64*13,$len + jb .Less_than_64_16x + vpxord ($inp),$xa3,$xa3 + vmovdqu32 $xa3,($out,$inp) + je .Ldone16x + vmovdqa32 $xb3,$xa0 + lea 64($inp),$inp + + cmp \$64*14,$len + jb .Less_than_64_16x + vpxord ($inp),$xb3,$xb3 + vmovdqu32 $xb3,($out,$inp) + je .Ldone16x + vmovdqa32 $xc3,$xa0 + lea 64($inp),$inp + + cmp \$64*15,$len + jb .Less_than_64_16x + vpxord ($inp),$xc3,$xc3 + vmovdqu32 $xc3,($out,$inp) + je .Ldone16x + vmovdqa32 $xd3,$xa0 + lea 64($inp),$inp + +.Less_than_64_16x: + vmovdqa32 $xa0,0x00(%rsp) + lea ($out,$inp),$out + and \$63,$len + +.Loop_tail16x: + movzb ($inp,%r10),%eax + movzb (%rsp,%r10),%ecx + lea 1(%r10),%r10 + xor %ecx,%eax + mov %al,-1($out,%r10) + dec $len + jnz .Loop_tail16x + + vpxord $xa0,$xa0,$xa0 + vmovdqa32 $xa0,0(%rsp) + +.Ldone16x: + vzeroall +___ +$code.=<<___ if ($win64); + movaps -0xa8(%r9),%xmm6 + movaps -0x98(%r9),%xmm7 + movaps -0x88(%r9),%xmm8 + movaps -0x78(%r9),%xmm9 + movaps -0x68(%r9),%xmm10 + movaps -0x58(%r9),%xmm11 + movaps -0x48(%r9),%xmm12 + movaps -0x38(%r9),%xmm13 + movaps -0x28(%r9),%xmm14 + movaps -0x18(%r9),%xmm15 +___ +$code.=<<___; + lea (%r9),%rsp +.cfi_def_cfa_register %rsp +.L16x_epilogue: + ret +.cfi_endproc +.size ChaCha20_16x,.-ChaCha20_16x +___ + +# switch to %ymm domain +($xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3, + $xc0,$xc1,$xc2,$xc3, $xd0,$xd1,$xd2,$xd3)=map("%ymm$_",(0..15)); +@xx=($xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3, + $xc0,$xc1,$xc2,$xc3, $xd0,$xd1,$xd2,$xd3); +@key=map("%ymm$_",(16..31)); +($xt0,$xt1,$xt2,$xt3)=@key[0..3]; + +$code.=<<___; +.type ChaCha20_8xvl,\@function,5 +.align 32 +ChaCha20_8xvl: +.cfi_startproc +.LChaCha20_8xvl: + mov %rsp,%r9 # frame register +.cfi_def_cfa_register %r9 + sub \$64+$xframe,%rsp + and \$-64,%rsp +___ +$code.=<<___ if ($win64); + movaps %xmm6,-0xa8(%r9) + movaps %xmm7,-0x98(%r9) + movaps %xmm8,-0x88(%r9) + movaps %xmm9,-0x78(%r9) + movaps %xmm10,-0x68(%r9) + movaps %xmm11,-0x58(%r9) + movaps %xmm12,-0x48(%r9) + movaps %xmm13,-0x38(%r9) + movaps %xmm14,-0x28(%r9) + movaps %xmm15,-0x18(%r9) +.L8xvl_body: +___ +$code.=<<___; + vzeroupper + + lea .Lsigma(%rip),%r10 + vbroadcasti128 (%r10),$xa3 # key[0] + vbroadcasti128 ($key),$xb3 # key[1] + vbroadcasti128 16($key),$xc3 # key[2] + vbroadcasti128 ($counter),$xd3 # key[3] + + vpshufd \$0x00,$xa3,$xa0 # smash key by lanes... + vpshufd \$0x55,$xa3,$xa1 + vpshufd \$0xaa,$xa3,$xa2 + vpshufd \$0xff,$xa3,$xa3 + vmovdqa64 $xa0,@key[0] + vmovdqa64 $xa1,@key[1] + vmovdqa64 $xa2,@key[2] + vmovdqa64 $xa3,@key[3] + + vpshufd \$0x00,$xb3,$xb0 + vpshufd \$0x55,$xb3,$xb1 + vpshufd \$0xaa,$xb3,$xb2 + vpshufd \$0xff,$xb3,$xb3 + vmovdqa64 $xb0,@key[4] + vmovdqa64 $xb1,@key[5] + vmovdqa64 $xb2,@key[6] + vmovdqa64 $xb3,@key[7] + + vpshufd \$0x00,$xc3,$xc0 + vpshufd \$0x55,$xc3,$xc1 + vpshufd \$0xaa,$xc3,$xc2 + vpshufd \$0xff,$xc3,$xc3 + vmovdqa64 $xc0,@key[8] + vmovdqa64 $xc1,@key[9] + vmovdqa64 $xc2,@key[10] + vmovdqa64 $xc3,@key[11] + + vpshufd \$0x00,$xd3,$xd0 + vpshufd \$0x55,$xd3,$xd1 + vpshufd \$0xaa,$xd3,$xd2 + vpshufd \$0xff,$xd3,$xd3 + vpaddd .Lincy(%rip),$xd0,$xd0 # don't save counters yet + vmovdqa64 $xd0,@key[12] + vmovdqa64 $xd1,@key[13] + vmovdqa64 $xd2,@key[14] + vmovdqa64 $xd3,@key[15] + + mov \$10,%eax + jmp .Loop8xvl + +.align 32 +.Loop_outer8xvl: + #vpbroadcastd 0(%r10),$xa0 # reload key + #vpbroadcastd 4(%r10),$xa1 + vpbroadcastd 8(%r10),$xa2 + vpbroadcastd 12(%r10),$xa3 + vpaddd .Leight(%rip),@key[12],@key[12] # next SIMD counters + vmovdqa64 @key[4],$xb0 + vmovdqa64 @key[5],$xb1 + vmovdqa64 @key[6],$xb2 + vmovdqa64 @key[7],$xb3 + vmovdqa64 @key[8],$xc0 + vmovdqa64 @key[9],$xc1 + vmovdqa64 @key[10],$xc2 + vmovdqa64 @key[11],$xc3 + vmovdqa64 @key[12],$xd0 + vmovdqa64 @key[13],$xd1 + vmovdqa64 @key[14],$xd2 + vmovdqa64 @key[15],$xd3 + + vmovdqa64 $xa0,@key[0] + vmovdqa64 $xa1,@key[1] + vmovdqa64 $xa2,@key[2] + vmovdqa64 $xa3,@key[3] + + mov \$10,%eax + jmp .Loop8xvl + +.align 32 +.Loop8xvl: +___ + foreach (&AVX512_lane_ROUND(0, 4, 8,12)) { eval; } + foreach (&AVX512_lane_ROUND(0, 5,10,15)) { eval; } +$code.=<<___; + dec %eax + jnz .Loop8xvl + + vpaddd @key[0],$xa0,$xa0 # accumulate key + vpaddd @key[1],$xa1,$xa1 + vpaddd @key[2],$xa2,$xa2 + vpaddd @key[3],$xa3,$xa3 + + vpunpckldq $xa1,$xa0,$xt2 # "de-interlace" data + vpunpckldq $xa3,$xa2,$xt3 + vpunpckhdq $xa1,$xa0,$xa0 + vpunpckhdq $xa3,$xa2,$xa2 + vpunpcklqdq $xt3,$xt2,$xa1 # "a0" + vpunpckhqdq $xt3,$xt2,$xt2 # "a1" + vpunpcklqdq $xa2,$xa0,$xa3 # "a2" + vpunpckhqdq $xa2,$xa0,$xa0 # "a3" +___ + ($xa0,$xa1,$xa2,$xa3,$xt2)=($xa1,$xt2,$xa3,$xa0,$xa2); +$code.=<<___; + vpaddd @key[4],$xb0,$xb0 + vpaddd @key[5],$xb1,$xb1 + vpaddd @key[6],$xb2,$xb2 + vpaddd @key[7],$xb3,$xb3 + + vpunpckldq $xb1,$xb0,$xt2 + vpunpckldq $xb3,$xb2,$xt3 + vpunpckhdq $xb1,$xb0,$xb0 + vpunpckhdq $xb3,$xb2,$xb2 + vpunpcklqdq $xt3,$xt2,$xb1 # "b0" + vpunpckhqdq $xt3,$xt2,$xt2 # "b1" + vpunpcklqdq $xb2,$xb0,$xb3 # "b2" + vpunpckhqdq $xb2,$xb0,$xb0 # "b3" +___ + ($xb0,$xb1,$xb2,$xb3,$xt2)=($xb1,$xt2,$xb3,$xb0,$xb2); +$code.=<<___; + vshufi32x4 \$0,$xb0,$xa0,$xt3 # "de-interlace" further + vshufi32x4 \$3,$xb0,$xa0,$xb0 + vshufi32x4 \$0,$xb1,$xa1,$xa0 + vshufi32x4 \$3,$xb1,$xa1,$xb1 + vshufi32x4 \$0,$xb2,$xa2,$xa1 + vshufi32x4 \$3,$xb2,$xa2,$xb2 + vshufi32x4 \$0,$xb3,$xa3,$xa2 + vshufi32x4 \$3,$xb3,$xa3,$xb3 +___ + ($xa0,$xa1,$xa2,$xa3,$xt3)=($xt3,$xa0,$xa1,$xa2,$xa3); +$code.=<<___; + vpaddd @key[8],$xc0,$xc0 + vpaddd @key[9],$xc1,$xc1 + vpaddd @key[10],$xc2,$xc2 + vpaddd @key[11],$xc3,$xc3 + + vpunpckldq $xc1,$xc0,$xt2 + vpunpckldq $xc3,$xc2,$xt3 + vpunpckhdq $xc1,$xc0,$xc0 + vpunpckhdq $xc3,$xc2,$xc2 + vpunpcklqdq $xt3,$xt2,$xc1 # "c0" + vpunpckhqdq $xt3,$xt2,$xt2 # "c1" + vpunpcklqdq $xc2,$xc0,$xc3 # "c2" + vpunpckhqdq $xc2,$xc0,$xc0 # "c3" +___ + ($xc0,$xc1,$xc2,$xc3,$xt2)=($xc1,$xt2,$xc3,$xc0,$xc2); +$code.=<<___; + vpaddd @key[12],$xd0,$xd0 + vpaddd @key[13],$xd1,$xd1 + vpaddd @key[14],$xd2,$xd2 + vpaddd @key[15],$xd3,$xd3 + + vpunpckldq $xd1,$xd0,$xt2 + vpunpckldq $xd3,$xd2,$xt3 + vpunpckhdq $xd1,$xd0,$xd0 + vpunpckhdq $xd3,$xd2,$xd2 + vpunpcklqdq $xt3,$xt2,$xd1 # "d0" + vpunpckhqdq $xt3,$xt2,$xt2 # "d1" + vpunpcklqdq $xd2,$xd0,$xd3 # "d2" + vpunpckhqdq $xd2,$xd0,$xd0 # "d3" +___ + ($xd0,$xd1,$xd2,$xd3,$xt2)=($xd1,$xt2,$xd3,$xd0,$xd2); +$code.=<<___; + vperm2i128 \$0x20,$xd0,$xc0,$xt3 # "de-interlace" further + vperm2i128 \$0x31,$xd0,$xc0,$xd0 + vperm2i128 \$0x20,$xd1,$xc1,$xc0 + vperm2i128 \$0x31,$xd1,$xc1,$xd1 + vperm2i128 \$0x20,$xd2,$xc2,$xc1 + vperm2i128 \$0x31,$xd2,$xc2,$xd2 + vperm2i128 \$0x20,$xd3,$xc3,$xc2 + vperm2i128 \$0x31,$xd3,$xc3,$xd3 +___ + ($xc0,$xc1,$xc2,$xc3,$xt3)=($xt3,$xc0,$xc1,$xc2,$xc3); + ($xb0,$xb1,$xb2,$xb3,$xc0,$xc1,$xc2,$xc3)= + ($xc0,$xc1,$xc2,$xc3,$xb0,$xb1,$xb2,$xb3); +$code.=<<___; + cmp \$64*8,$len + jb .Ltail8xvl + + mov \$0x80,%eax # size optimization + vpxord 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x20($inp),$xb0,$xb0 + vpxor 0x40($inp),$xc0,$xc0 + vpxor 0x60($inp),$xd0,$xd0 + lea ($inp,%rax),$inp # size optimization + vmovdqu32 $xa0,0x00($out) + vmovdqu $xb0,0x20($out) + vmovdqu $xc0,0x40($out) + vmovdqu $xd0,0x60($out) + lea ($out,%rax),$out # size optimization + + vpxor 0x00($inp),$xa1,$xa1 + vpxor 0x20($inp),$xb1,$xb1 + vpxor 0x40($inp),$xc1,$xc1 + vpxor 0x60($inp),$xd1,$xd1 + lea ($inp,%rax),$inp # size optimization + vmovdqu $xa1,0x00($out) + vmovdqu $xb1,0x20($out) + vmovdqu $xc1,0x40($out) + vmovdqu $xd1,0x60($out) + lea ($out,%rax),$out # size optimization + + vpxord 0x00($inp),$xa2,$xa2 + vpxor 0x20($inp),$xb2,$xb2 + vpxor 0x40($inp),$xc2,$xc2 + vpxor 0x60($inp),$xd2,$xd2 + lea ($inp,%rax),$inp # size optimization + vmovdqu32 $xa2,0x00($out) + vmovdqu $xb2,0x20($out) + vmovdqu $xc2,0x40($out) + vmovdqu $xd2,0x60($out) + lea ($out,%rax),$out # size optimization + + vpxor 0x00($inp),$xa3,$xa3 + vpxor 0x20($inp),$xb3,$xb3 + vpxor 0x40($inp),$xc3,$xc3 + vpxor 0x60($inp),$xd3,$xd3 + lea ($inp,%rax),$inp # size optimization + vmovdqu $xa3,0x00($out) + vmovdqu $xb3,0x20($out) + vmovdqu $xc3,0x40($out) + vmovdqu $xd3,0x60($out) + lea ($out,%rax),$out # size optimization + + vpbroadcastd 0(%r10),%ymm0 # reload key + vpbroadcastd 4(%r10),%ymm1 + + sub \$64*8,$len + jnz .Loop_outer8xvl + + jmp .Ldone8xvl + +.align 32 +.Ltail8xvl: + vmovdqa64 $xa0,%ymm8 # size optimization +___ +$xa0 = "%ymm8"; +$code.=<<___; + xor %r10,%r10 + sub $inp,$out + cmp \$64*1,$len + jb .Less_than_64_8xvl + vpxor 0x00($inp),$xa0,$xa0 # xor with input + vpxor 0x20($inp),$xb0,$xb0 + vmovdqu $xa0,0x00($out,$inp) + vmovdqu $xb0,0x20($out,$inp) + je .Ldone8xvl + vmovdqa $xc0,$xa0 + vmovdqa $xd0,$xb0 + lea 64($inp),$inp + + cmp \$64*2,$len + jb .Less_than_64_8xvl + vpxor 0x00($inp),$xc0,$xc0 + vpxor 0x20($inp),$xd0,$xd0 + vmovdqu $xc0,0x00($out,$inp) + vmovdqu $xd0,0x20($out,$inp) + je .Ldone8xvl + vmovdqa $xa1,$xa0 + vmovdqa $xb1,$xb0 + lea 64($inp),$inp + + cmp \$64*3,$len + jb .Less_than_64_8xvl + vpxor 0x00($inp),$xa1,$xa1 + vpxor 0x20($inp),$xb1,$xb1 + vmovdqu $xa1,0x00($out,$inp) + vmovdqu $xb1,0x20($out,$inp) + je .Ldone8xvl + vmovdqa $xc1,$xa0 + vmovdqa $xd1,$xb0 + lea 64($inp),$inp + + cmp \$64*4,$len + jb .Less_than_64_8xvl + vpxor 0x00($inp),$xc1,$xc1 + vpxor 0x20($inp),$xd1,$xd1 + vmovdqu $xc1,0x00($out,$inp) + vmovdqu $xd1,0x20($out,$inp) + je .Ldone8xvl + vmovdqa32 $xa2,$xa0 + vmovdqa $xb2,$xb0 + lea 64($inp),$inp + + cmp \$64*5,$len + jb .Less_than_64_8xvl + vpxord 0x00($inp),$xa2,$xa2 + vpxor 0x20($inp),$xb2,$xb2 + vmovdqu32 $xa2,0x00($out,$inp) + vmovdqu $xb2,0x20($out,$inp) + je .Ldone8xvl + vmovdqa $xc2,$xa0 + vmovdqa $xd2,$xb0 + lea 64($inp),$inp + + cmp \$64*6,$len + jb .Less_than_64_8xvl + vpxor 0x00($inp),$xc2,$xc2 + vpxor 0x20($inp),$xd2,$xd2 + vmovdqu $xc2,0x00($out,$inp) + vmovdqu $xd2,0x20($out,$inp) + je .Ldone8xvl + vmovdqa $xa3,$xa0 + vmovdqa $xb3,$xb0 + lea 64($inp),$inp + + cmp \$64*7,$len + jb .Less_than_64_8xvl + vpxor 0x00($inp),$xa3,$xa3 + vpxor 0x20($inp),$xb3,$xb3 + vmovdqu $xa3,0x00($out,$inp) + vmovdqu $xb3,0x20($out,$inp) + je .Ldone8xvl + vmovdqa $xc3,$xa0 + vmovdqa $xd3,$xb0 + lea 64($inp),$inp + +.Less_than_64_8xvl: + vmovdqa $xa0,0x00(%rsp) + vmovdqa $xb0,0x20(%rsp) + lea ($out,$inp),$out + and \$63,$len + +.Loop_tail8xvl: + movzb ($inp,%r10),%eax + movzb (%rsp,%r10),%ecx + lea 1(%r10),%r10 + xor %ecx,%eax + mov %al,-1($out,%r10) + dec $len + jnz .Loop_tail8xvl + + vpxor $xa0,$xa0,$xa0 + vmovdqa $xa0,0x00(%rsp) + vmovdqa $xa0,0x20(%rsp) + +.Ldone8xvl: + vzeroall +___ +$code.=<<___ if ($win64); + movaps -0xa8(%r9),%xmm6 + movaps -0x98(%r9),%xmm7 + movaps -0x88(%r9),%xmm8 + movaps -0x78(%r9),%xmm9 + movaps -0x68(%r9),%xmm10 + movaps -0x58(%r9),%xmm11 + movaps -0x48(%r9),%xmm12 + movaps -0x38(%r9),%xmm13 + movaps -0x28(%r9),%xmm14 + movaps -0x18(%r9),%xmm15 +___ +$code.=<<___; + lea (%r9),%rsp +.cfi_def_cfa_register %rsp +.L8xvl_epilogue: + ret +.cfi_endproc +.size ChaCha20_8xvl,.-ChaCha20_8xvl +___ +} + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type se_handler,\@abi-omnipotent +.align 16 +se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + lea .Lctr32_body(%rip),%r10 + cmp %r10,%rbx # context->Rip<.Lprologue + jb .Lcommon_seh_tail + + mov 152($context),%rax # pull context->Rsp + + lea .Lno_data(%rip),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=.Lepilogue + jae .Lcommon_seh_tail + + lea 64+24+48(%rax),%rax + + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov -48(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R14 + +.Lcommon_seh_tail: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size se_handler,.-se_handler + +.type simd_handler,\@abi-omnipotent +.align 16 +simd_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->RipR9 + + mov 4(%r11),%r10d # HandlerData[1] + mov 8(%r11),%ecx # HandlerData[2] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lcommon_seh_tail + + neg %rcx + lea -8(%rax,%rcx),%rsi + lea 512($context),%rdi # &context.Xmm6 + neg %ecx + shr \$3,%ecx + .long 0xa548f3fc # cld; rep movsq + + jmp .Lcommon_seh_tail +.size simd_handler,.-simd_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_ChaCha20_ctr32 + .rva .LSEH_end_ChaCha20_ctr32 + .rva .LSEH_info_ChaCha20_ctr32 + + .rva .LSEH_begin_ChaCha20_ssse3 + .rva .LSEH_end_ChaCha20_ssse3 + .rva .LSEH_info_ChaCha20_ssse3 + + .rva .LSEH_begin_ChaCha20_128 + .rva .LSEH_end_ChaCha20_128 + .rva .LSEH_info_ChaCha20_128 + + .rva .LSEH_begin_ChaCha20_4x + .rva .LSEH_end_ChaCha20_4x + .rva .LSEH_info_ChaCha20_4x +___ +$code.=<<___ if ($avx); + .rva .LSEH_begin_ChaCha20_4xop + .rva .LSEH_end_ChaCha20_4xop + .rva .LSEH_info_ChaCha20_4xop +___ +$code.=<<___ if ($avx>1); + .rva .LSEH_begin_ChaCha20_8x + .rva .LSEH_end_ChaCha20_8x + .rva .LSEH_info_ChaCha20_8x +___ +$code.=<<___ if ($avx>2); + .rva .LSEH_begin_ChaCha20_avx512 + .rva .LSEH_end_ChaCha20_avx512 + .rva .LSEH_info_ChaCha20_avx512 + + .rva .LSEH_begin_ChaCha20_avx512vl + .rva .LSEH_end_ChaCha20_avx512vl + .rva .LSEH_info_ChaCha20_avx512vl + + .rva .LSEH_begin_ChaCha20_16x + .rva .LSEH_end_ChaCha20_16x + .rva .LSEH_info_ChaCha20_16x + + .rva .LSEH_begin_ChaCha20_8xvl + .rva .LSEH_end_ChaCha20_8xvl + .rva .LSEH_info_ChaCha20_8xvl +___ +$code.=<<___; +.section .xdata +.align 8 +.LSEH_info_ChaCha20_ctr32: + .byte 9,0,0,0 + .rva se_handler + +.LSEH_info_ChaCha20_ssse3: + .byte 9,0,0,0 + .rva simd_handler + .rva .Lssse3_body,.Lssse3_epilogue + .long 0x20,0 + +.LSEH_info_ChaCha20_128: + .byte 9,0,0,0 + .rva simd_handler + .rva .L128_body,.L128_epilogue + .long 0x60,0 + +.LSEH_info_ChaCha20_4x: + .byte 9,0,0,0 + .rva simd_handler + .rva .L4x_body,.L4x_epilogue + .long 0xa0,0 +___ +$code.=<<___ if ($avx); +.LSEH_info_ChaCha20_4xop: + .byte 9,0,0,0 + .rva simd_handler + .rva .L4xop_body,.L4xop_epilogue # HandlerData[] + .long 0xa0,0 +___ +$code.=<<___ if ($avx>1); +.LSEH_info_ChaCha20_8x: + .byte 9,0,0,0 + .rva simd_handler + .rva .L8x_body,.L8x_epilogue # HandlerData[] + .long 0xa0,0 +___ +$code.=<<___ if ($avx>2); +.LSEH_info_ChaCha20_avx512: + .byte 9,0,0,0 + .rva simd_handler + .rva .Lavx512_body,.Lavx512_epilogue # HandlerData[] + .long 0x20,0 + +.LSEH_info_ChaCha20_avx512vl: + .byte 9,0,0,0 + .rva simd_handler + .rva .Lavx512vl_body,.Lavx512vl_epilogue # HandlerData[] + .long 0x20,0 + +.LSEH_info_ChaCha20_16x: + .byte 9,0,0,0 + .rva simd_handler + .rva .L16x_body,.L16x_epilogue # HandlerData[] + .long 0xa0,0 + +.LSEH_info_ChaCha20_8xvl: + .byte 9,0,0,0 + .rva simd_handler + .rva .L8xvl_body,.L8xvl_epilogue # HandlerData[] + .long 0xa0,0 +___ +} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/ge; + + s/%x#%[yz]/%x/g; # "down-shift" + + print $_,"\n"; +} + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/chacha/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/chacha/build.info new file mode 100644 index 000000000..02f8e518a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/chacha/build.info @@ -0,0 +1,18 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]={- $target{chacha_asm_src} -} + +GENERATE[chacha-x86.s]=asm/chacha-x86.pl \ + $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) +GENERATE[chacha-x86_64.s]=asm/chacha-x86_64.pl $(PERLASM_SCHEME) +GENERATE[chacha-ppc.s]=asm/chacha-ppc.pl $(PERLASM_SCHEME) +GENERATE[chacha-armv4.S]=asm/chacha-armv4.pl $(PERLASM_SCHEME) +INCLUDE[chacha-armv4.o]=.. +GENERATE[chacha-armv8.S]=asm/chacha-armv8.pl $(PERLASM_SCHEME) +INCLUDE[chacha-armv8.o]=.. + +BEGINRAW[Makefile(unix)] +##### CHACHA assembler implementations + +{- $builddir -}/chacha-%.S: {- $sourcedir -}/asm/chacha-%.pl + CC="$(CC)" $(PERL) $< $(PERLASM_SCHEME) $@ +ENDRAW[Makefile(unix)] diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/chacha/chacha_enc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/chacha/chacha_enc.c new file mode 100644 index 000000000..239f68ab8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/chacha/chacha_enc.c @@ -0,0 +1,121 @@ +/* + * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Adapted from the public domain code by D. Bernstein from SUPERCOP. */ + +#include + +#include "internal/chacha.h" + +typedef unsigned int u32; +typedef unsigned char u8; +typedef union { + u32 u[16]; + u8 c[64]; +} chacha_buf; + +# define ROTATE(v, n) (((v) << (n)) | ((v) >> (32 - (n)))) + +# define U32TO8_LITTLE(p, v) do { \ + (p)[0] = (u8)(v >> 0); \ + (p)[1] = (u8)(v >> 8); \ + (p)[2] = (u8)(v >> 16); \ + (p)[3] = (u8)(v >> 24); \ + } while(0) + +/* QUARTERROUND updates a, b, c, d with a ChaCha "quarter" round. */ +# define QUARTERROUND(a,b,c,d) ( \ + x[a] += x[b], x[d] = ROTATE((x[d] ^ x[a]),16), \ + x[c] += x[d], x[b] = ROTATE((x[b] ^ x[c]),12), \ + x[a] += x[b], x[d] = ROTATE((x[d] ^ x[a]), 8), \ + x[c] += x[d], x[b] = ROTATE((x[b] ^ x[c]), 7) ) + +/* chacha_core performs 20 rounds of ChaCha on the input words in + * |input| and writes the 64 output bytes to |output|. */ +static void chacha20_core(chacha_buf *output, const u32 input[16]) +{ + u32 x[16]; + int i; + const union { + long one; + char little; + } is_endian = { 1 }; + + memcpy(x, input, sizeof(x)); + + for (i = 20; i > 0; i -= 2) { + QUARTERROUND(0, 4, 8, 12); + QUARTERROUND(1, 5, 9, 13); + QUARTERROUND(2, 6, 10, 14); + QUARTERROUND(3, 7, 11, 15); + QUARTERROUND(0, 5, 10, 15); + QUARTERROUND(1, 6, 11, 12); + QUARTERROUND(2, 7, 8, 13); + QUARTERROUND(3, 4, 9, 14); + } + + if (is_endian.little) { + for (i = 0; i < 16; ++i) + output->u[i] = x[i] + input[i]; + } else { + for (i = 0; i < 16; ++i) + U32TO8_LITTLE(output->c + 4 * i, (x[i] + input[i])); + } +} + +void ChaCha20_ctr32(unsigned char *out, const unsigned char *inp, + size_t len, const unsigned int key[8], + const unsigned int counter[4]) +{ + u32 input[16]; + chacha_buf buf; + size_t todo, i; + + /* sigma constant "expand 32-byte k" in little-endian encoding */ + input[0] = ((u32)'e') | ((u32)'x'<<8) | ((u32)'p'<<16) | ((u32)'a'<<24); + input[1] = ((u32)'n') | ((u32)'d'<<8) | ((u32)' '<<16) | ((u32)'3'<<24); + input[2] = ((u32)'2') | ((u32)'-'<<8) | ((u32)'b'<<16) | ((u32)'y'<<24); + input[3] = ((u32)'t') | ((u32)'e'<<8) | ((u32)' '<<16) | ((u32)'k'<<24); + + input[4] = key[0]; + input[5] = key[1]; + input[6] = key[2]; + input[7] = key[3]; + input[8] = key[4]; + input[9] = key[5]; + input[10] = key[6]; + input[11] = key[7]; + + input[12] = counter[0]; + input[13] = counter[1]; + input[14] = counter[2]; + input[15] = counter[3]; + + while (len > 0) { + todo = sizeof(buf); + if (len < todo) + todo = len; + + chacha20_core(&buf, input); + + for (i = 0; i < todo; i++) + out[i] = inp[i] ^ buf.c[i]; + out += todo; + inp += todo; + len -= todo; + + /* + * Advance 32-bit counter. Note that as subroutine is so to + * say nonce-agnostic, this limited counter width doesn't + * prevent caller from implementing wider counter. It would + * simply take two calls split on counter overflow... + */ + input[12]++; + } +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cmac/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/cmac/build.info new file mode 100644 index 000000000..c8a4949a0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cmac/build.info @@ -0,0 +1,2 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=cmac.c cm_ameth.c cm_pmeth.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cmac/cm_ameth.c b/trunk/3rdparty/openssl-1.1-fit/crypto/cmac/cm_ameth.c new file mode 100644 index 000000000..a58454a08 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cmac/cm_ameth.c @@ -0,0 +1,51 @@ +/* + * Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include "internal/asn1_int.h" + +/* + * CMAC "ASN1" method. This is just here to indicate the maximum CMAC output + * length and to free up a CMAC key. + */ + +static int cmac_size(const EVP_PKEY *pkey) +{ + return EVP_MAX_BLOCK_LENGTH; +} + +static void cmac_key_free(EVP_PKEY *pkey) +{ + CMAC_CTX *cmctx = EVP_PKEY_get0(pkey); + CMAC_CTX_free(cmctx); +} + +const EVP_PKEY_ASN1_METHOD cmac_asn1_meth = { + EVP_PKEY_CMAC, + EVP_PKEY_CMAC, + 0, + + "CMAC", + "OpenSSL CMAC method", + + 0, 0, 0, 0, + + 0, 0, 0, + + cmac_size, + 0, 0, + 0, 0, 0, 0, 0, 0, 0, + + cmac_key_free, + 0, + 0, 0 +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cmac/cm_pmeth.c b/trunk/3rdparty/openssl-1.1-fit/crypto/cmac/cm_pmeth.c new file mode 100644 index 000000000..10748f148 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cmac/cm_pmeth.c @@ -0,0 +1,161 @@ +/* + * Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "internal/evp_int.h" + +/* The context structure and "key" is simply a CMAC_CTX */ + +static int pkey_cmac_init(EVP_PKEY_CTX *ctx) +{ + ctx->data = CMAC_CTX_new(); + if (ctx->data == NULL) + return 0; + ctx->keygen_info_count = 0; + return 1; +} + +static int pkey_cmac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) +{ + if (!pkey_cmac_init(dst)) + return 0; + if (!CMAC_CTX_copy(dst->data, src->data)) + return 0; + return 1; +} + +static void pkey_cmac_cleanup(EVP_PKEY_CTX *ctx) +{ + CMAC_CTX_free(ctx->data); +} + +static int pkey_cmac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) +{ + CMAC_CTX *cmkey = CMAC_CTX_new(); + CMAC_CTX *cmctx = ctx->data; + if (cmkey == NULL) + return 0; + if (!CMAC_CTX_copy(cmkey, cmctx)) { + CMAC_CTX_free(cmkey); + return 0; + } + EVP_PKEY_assign(pkey, EVP_PKEY_CMAC, cmkey); + + return 1; +} + +static int int_update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ + if (!CMAC_Update(EVP_MD_CTX_pkey_ctx(ctx)->data, data, count)) + return 0; + return 1; +} + +static int cmac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx) +{ + EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT); + EVP_MD_CTX_set_update_fn(mctx, int_update); + return 1; +} + +static int cmac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, + EVP_MD_CTX *mctx) +{ + return CMAC_Final(ctx->data, sig, siglen); +} + +static int pkey_cmac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) +{ + CMAC_CTX *cmctx = ctx->data; + switch (type) { + + case EVP_PKEY_CTRL_SET_MAC_KEY: + if (!p2 || p1 < 0) + return 0; + if (!CMAC_Init(cmctx, p2, p1, NULL, NULL)) + return 0; + break; + + case EVP_PKEY_CTRL_CIPHER: + if (!CMAC_Init(cmctx, NULL, 0, p2, ctx->engine)) + return 0; + break; + + case EVP_PKEY_CTRL_MD: + if (ctx->pkey && !CMAC_CTX_copy(ctx->data, + (CMAC_CTX *)ctx->pkey->pkey.ptr)) + return 0; + if (!CMAC_Init(cmctx, NULL, 0, NULL, NULL)) + return 0; + break; + + default: + return -2; + + } + return 1; +} + +static int pkey_cmac_ctrl_str(EVP_PKEY_CTX *ctx, + const char *type, const char *value) +{ + if (!value) { + return 0; + } + if (strcmp(type, "cipher") == 0) { + const EVP_CIPHER *c; + c = EVP_get_cipherbyname(value); + if (!c) + return 0; + return pkey_cmac_ctrl(ctx, EVP_PKEY_CTRL_CIPHER, -1, (void *)c); + } + if (strcmp(type, "key") == 0) + return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value); + if (strcmp(type, "hexkey") == 0) + return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value); + return -2; +} + +const EVP_PKEY_METHOD cmac_pkey_meth = { + EVP_PKEY_CMAC, + EVP_PKEY_FLAG_SIGCTX_CUSTOM, + pkey_cmac_init, + pkey_cmac_copy, + pkey_cmac_cleanup, + + 0, 0, + + 0, + pkey_cmac_keygen, + + 0, 0, + + 0, 0, + + 0, 0, + + cmac_signctx_init, + cmac_signctx, + + 0, 0, + + 0, 0, + + 0, 0, + + 0, 0, + + pkey_cmac_ctrl, + pkey_cmac_ctrl_str +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cmac/cmac.c b/trunk/3rdparty/openssl-1.1-fit/crypto/cmac/cmac.c new file mode 100644 index 000000000..6989c32d0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cmac/cmac.c @@ -0,0 +1,226 @@ +/* + * Copyright 2010-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "internal/cryptlib.h" +#include +#include + +struct CMAC_CTX_st { + /* Cipher context to use */ + EVP_CIPHER_CTX *cctx; + /* Keys k1 and k2 */ + unsigned char k1[EVP_MAX_BLOCK_LENGTH]; + unsigned char k2[EVP_MAX_BLOCK_LENGTH]; + /* Temporary block */ + unsigned char tbl[EVP_MAX_BLOCK_LENGTH]; + /* Last (possibly partial) block */ + unsigned char last_block[EVP_MAX_BLOCK_LENGTH]; + /* Number of bytes in last block: -1 means context not initialised */ + int nlast_block; +}; + +/* Make temporary keys K1 and K2 */ + +static void make_kn(unsigned char *k1, const unsigned char *l, int bl) +{ + int i; + unsigned char c = l[0], carry = c >> 7, cnext; + + /* Shift block to left, including carry */ + for (i = 0; i < bl - 1; i++, c = cnext) + k1[i] = (c << 1) | ((cnext = l[i + 1]) >> 7); + + /* If MSB set fixup with R */ + k1[i] = (c << 1) ^ ((0 - carry) & (bl == 16 ? 0x87 : 0x1b)); +} + +CMAC_CTX *CMAC_CTX_new(void) +{ + CMAC_CTX *ctx; + + if ((ctx = OPENSSL_malloc(sizeof(*ctx))) == NULL) { + CRYPTOerr(CRYPTO_F_CMAC_CTX_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + ctx->cctx = EVP_CIPHER_CTX_new(); + if (ctx->cctx == NULL) { + OPENSSL_free(ctx); + return NULL; + } + ctx->nlast_block = -1; + return ctx; +} + +void CMAC_CTX_cleanup(CMAC_CTX *ctx) +{ + EVP_CIPHER_CTX_reset(ctx->cctx); + OPENSSL_cleanse(ctx->tbl, EVP_MAX_BLOCK_LENGTH); + OPENSSL_cleanse(ctx->k1, EVP_MAX_BLOCK_LENGTH); + OPENSSL_cleanse(ctx->k2, EVP_MAX_BLOCK_LENGTH); + OPENSSL_cleanse(ctx->last_block, EVP_MAX_BLOCK_LENGTH); + ctx->nlast_block = -1; +} + +EVP_CIPHER_CTX *CMAC_CTX_get0_cipher_ctx(CMAC_CTX *ctx) +{ + return ctx->cctx; +} + +void CMAC_CTX_free(CMAC_CTX *ctx) +{ + if (!ctx) + return; + CMAC_CTX_cleanup(ctx); + EVP_CIPHER_CTX_free(ctx->cctx); + OPENSSL_free(ctx); +} + +int CMAC_CTX_copy(CMAC_CTX *out, const CMAC_CTX *in) +{ + int bl; + if (in->nlast_block == -1) + return 0; + if (!EVP_CIPHER_CTX_copy(out->cctx, in->cctx)) + return 0; + bl = EVP_CIPHER_CTX_block_size(in->cctx); + memcpy(out->k1, in->k1, bl); + memcpy(out->k2, in->k2, bl); + memcpy(out->tbl, in->tbl, bl); + memcpy(out->last_block, in->last_block, bl); + out->nlast_block = in->nlast_block; + return 1; +} + +int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen, + const EVP_CIPHER *cipher, ENGINE *impl) +{ + static const unsigned char zero_iv[EVP_MAX_BLOCK_LENGTH] = { 0 }; + /* All zeros means restart */ + if (!key && !cipher && !impl && keylen == 0) { + /* Not initialised */ + if (ctx->nlast_block == -1) + return 0; + if (!EVP_EncryptInit_ex(ctx->cctx, NULL, NULL, NULL, zero_iv)) + return 0; + memset(ctx->tbl, 0, EVP_CIPHER_CTX_block_size(ctx->cctx)); + ctx->nlast_block = 0; + return 1; + } + /* Initialise context */ + if (cipher && !EVP_EncryptInit_ex(ctx->cctx, cipher, impl, NULL, NULL)) + return 0; + /* Non-NULL key means initialisation complete */ + if (key) { + int bl; + if (!EVP_CIPHER_CTX_cipher(ctx->cctx)) + return 0; + if (!EVP_CIPHER_CTX_set_key_length(ctx->cctx, keylen)) + return 0; + if (!EVP_EncryptInit_ex(ctx->cctx, NULL, NULL, key, zero_iv)) + return 0; + bl = EVP_CIPHER_CTX_block_size(ctx->cctx); + if (!EVP_Cipher(ctx->cctx, ctx->tbl, zero_iv, bl)) + return 0; + make_kn(ctx->k1, ctx->tbl, bl); + make_kn(ctx->k2, ctx->k1, bl); + OPENSSL_cleanse(ctx->tbl, bl); + /* Reset context again ready for first data block */ + if (!EVP_EncryptInit_ex(ctx->cctx, NULL, NULL, NULL, zero_iv)) + return 0; + /* Zero tbl so resume works */ + memset(ctx->tbl, 0, bl); + ctx->nlast_block = 0; + } + return 1; +} + +int CMAC_Update(CMAC_CTX *ctx, const void *in, size_t dlen) +{ + const unsigned char *data = in; + size_t bl; + if (ctx->nlast_block == -1) + return 0; + if (dlen == 0) + return 1; + bl = EVP_CIPHER_CTX_block_size(ctx->cctx); + /* Copy into partial block if we need to */ + if (ctx->nlast_block > 0) { + size_t nleft; + nleft = bl - ctx->nlast_block; + if (dlen < nleft) + nleft = dlen; + memcpy(ctx->last_block + ctx->nlast_block, data, nleft); + dlen -= nleft; + ctx->nlast_block += nleft; + /* If no more to process return */ + if (dlen == 0) + return 1; + data += nleft; + /* Else not final block so encrypt it */ + if (!EVP_Cipher(ctx->cctx, ctx->tbl, ctx->last_block, bl)) + return 0; + } + /* Encrypt all but one of the complete blocks left */ + while (dlen > bl) { + if (!EVP_Cipher(ctx->cctx, ctx->tbl, data, bl)) + return 0; + dlen -= bl; + data += bl; + } + /* Copy any data left to last block buffer */ + memcpy(ctx->last_block, data, dlen); + ctx->nlast_block = dlen; + return 1; + +} + +int CMAC_Final(CMAC_CTX *ctx, unsigned char *out, size_t *poutlen) +{ + int i, bl, lb; + if (ctx->nlast_block == -1) + return 0; + bl = EVP_CIPHER_CTX_block_size(ctx->cctx); + *poutlen = (size_t)bl; + if (!out) + return 1; + lb = ctx->nlast_block; + /* Is last block complete? */ + if (lb == bl) { + for (i = 0; i < bl; i++) + out[i] = ctx->last_block[i] ^ ctx->k1[i]; + } else { + ctx->last_block[lb] = 0x80; + if (bl - lb > 1) + memset(ctx->last_block + lb + 1, 0, bl - lb - 1); + for (i = 0; i < bl; i++) + out[i] = ctx->last_block[i] ^ ctx->k2[i]; + } + if (!EVP_Cipher(ctx->cctx, out, out, bl)) { + OPENSSL_cleanse(out, bl); + return 0; + } + return 1; +} + +int CMAC_resume(CMAC_CTX *ctx) +{ + if (ctx->nlast_block == -1) + return 0; + /* + * The buffer "tbl" contains the last fully encrypted block which is the + * last IV (or all zeroes if no last encrypted block). The last block has + * not been modified since CMAC_final(). So reinitialising using the last + * decrypted block will allow CMAC to continue after calling + * CMAC_Final(). + */ + return EVP_EncryptInit_ex(ctx->cctx, NULL, NULL, NULL, ctx->tbl); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cms/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/build.info new file mode 100644 index 000000000..cb675436e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/build.info @@ -0,0 +1,5 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]= \ + cms_lib.c cms_asn1.c cms_att.c cms_io.c cms_smime.c cms_err.c \ + cms_sd.c cms_dd.c cms_cd.c cms_env.c cms_enc.c cms_ess.c \ + cms_pwri.c cms_kari.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_asn1.c b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_asn1.c new file mode 100644 index 000000000..993ea6b21 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_asn1.c @@ -0,0 +1,403 @@ +/* + * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include "cms_lcl.h" + + +ASN1_SEQUENCE(CMS_IssuerAndSerialNumber) = { + ASN1_SIMPLE(CMS_IssuerAndSerialNumber, issuer, X509_NAME), + ASN1_SIMPLE(CMS_IssuerAndSerialNumber, serialNumber, ASN1_INTEGER) +} ASN1_SEQUENCE_END(CMS_IssuerAndSerialNumber) + +ASN1_SEQUENCE(CMS_OtherCertificateFormat) = { + ASN1_SIMPLE(CMS_OtherCertificateFormat, otherCertFormat, ASN1_OBJECT), + ASN1_OPT(CMS_OtherCertificateFormat, otherCert, ASN1_ANY) +} static_ASN1_SEQUENCE_END(CMS_OtherCertificateFormat) + +ASN1_CHOICE(CMS_CertificateChoices) = { + ASN1_SIMPLE(CMS_CertificateChoices, d.certificate, X509), + ASN1_IMP(CMS_CertificateChoices, d.extendedCertificate, ASN1_SEQUENCE, 0), + ASN1_IMP(CMS_CertificateChoices, d.v1AttrCert, ASN1_SEQUENCE, 1), + ASN1_IMP(CMS_CertificateChoices, d.v2AttrCert, ASN1_SEQUENCE, 2), + ASN1_IMP(CMS_CertificateChoices, d.other, CMS_OtherCertificateFormat, 3) +} ASN1_CHOICE_END(CMS_CertificateChoices) + +ASN1_CHOICE(CMS_SignerIdentifier) = { + ASN1_SIMPLE(CMS_SignerIdentifier, d.issuerAndSerialNumber, CMS_IssuerAndSerialNumber), + ASN1_IMP(CMS_SignerIdentifier, d.subjectKeyIdentifier, ASN1_OCTET_STRING, 0) +} static_ASN1_CHOICE_END(CMS_SignerIdentifier) + +ASN1_NDEF_SEQUENCE(CMS_EncapsulatedContentInfo) = { + ASN1_SIMPLE(CMS_EncapsulatedContentInfo, eContentType, ASN1_OBJECT), + ASN1_NDEF_EXP_OPT(CMS_EncapsulatedContentInfo, eContent, ASN1_OCTET_STRING_NDEF, 0) +} static_ASN1_NDEF_SEQUENCE_END(CMS_EncapsulatedContentInfo) + +/* Minor tweak to operation: free up signer key, cert */ +static int cms_si_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + if (operation == ASN1_OP_FREE_POST) { + CMS_SignerInfo *si = (CMS_SignerInfo *)*pval; + EVP_PKEY_free(si->pkey); + X509_free(si->signer); + EVP_MD_CTX_free(si->mctx); + } + return 1; +} + +ASN1_SEQUENCE_cb(CMS_SignerInfo, cms_si_cb) = { + ASN1_EMBED(CMS_SignerInfo, version, INT32), + ASN1_SIMPLE(CMS_SignerInfo, sid, CMS_SignerIdentifier), + ASN1_SIMPLE(CMS_SignerInfo, digestAlgorithm, X509_ALGOR), + ASN1_IMP_SET_OF_OPT(CMS_SignerInfo, signedAttrs, X509_ATTRIBUTE, 0), + ASN1_SIMPLE(CMS_SignerInfo, signatureAlgorithm, X509_ALGOR), + ASN1_SIMPLE(CMS_SignerInfo, signature, ASN1_OCTET_STRING), + ASN1_IMP_SET_OF_OPT(CMS_SignerInfo, unsignedAttrs, X509_ATTRIBUTE, 1) +} ASN1_SEQUENCE_END_cb(CMS_SignerInfo, CMS_SignerInfo) + +ASN1_SEQUENCE(CMS_OtherRevocationInfoFormat) = { + ASN1_SIMPLE(CMS_OtherRevocationInfoFormat, otherRevInfoFormat, ASN1_OBJECT), + ASN1_OPT(CMS_OtherRevocationInfoFormat, otherRevInfo, ASN1_ANY) +} static_ASN1_SEQUENCE_END(CMS_OtherRevocationInfoFormat) + +ASN1_CHOICE(CMS_RevocationInfoChoice) = { + ASN1_SIMPLE(CMS_RevocationInfoChoice, d.crl, X509_CRL), + ASN1_IMP(CMS_RevocationInfoChoice, d.other, CMS_OtherRevocationInfoFormat, 1) +} ASN1_CHOICE_END(CMS_RevocationInfoChoice) + +ASN1_NDEF_SEQUENCE(CMS_SignedData) = { + ASN1_EMBED(CMS_SignedData, version, INT32), + ASN1_SET_OF(CMS_SignedData, digestAlgorithms, X509_ALGOR), + ASN1_SIMPLE(CMS_SignedData, encapContentInfo, CMS_EncapsulatedContentInfo), + ASN1_IMP_SET_OF_OPT(CMS_SignedData, certificates, CMS_CertificateChoices, 0), + ASN1_IMP_SET_OF_OPT(CMS_SignedData, crls, CMS_RevocationInfoChoice, 1), + ASN1_SET_OF(CMS_SignedData, signerInfos, CMS_SignerInfo) +} ASN1_NDEF_SEQUENCE_END(CMS_SignedData) + +ASN1_SEQUENCE(CMS_OriginatorInfo) = { + ASN1_IMP_SET_OF_OPT(CMS_OriginatorInfo, certificates, CMS_CertificateChoices, 0), + ASN1_IMP_SET_OF_OPT(CMS_OriginatorInfo, crls, CMS_RevocationInfoChoice, 1) +} static_ASN1_SEQUENCE_END(CMS_OriginatorInfo) + +ASN1_NDEF_SEQUENCE(CMS_EncryptedContentInfo) = { + ASN1_SIMPLE(CMS_EncryptedContentInfo, contentType, ASN1_OBJECT), + ASN1_SIMPLE(CMS_EncryptedContentInfo, contentEncryptionAlgorithm, X509_ALGOR), + ASN1_IMP_OPT(CMS_EncryptedContentInfo, encryptedContent, ASN1_OCTET_STRING_NDEF, 0) +} static_ASN1_NDEF_SEQUENCE_END(CMS_EncryptedContentInfo) + +ASN1_SEQUENCE(CMS_KeyTransRecipientInfo) = { + ASN1_EMBED(CMS_KeyTransRecipientInfo, version, INT32), + ASN1_SIMPLE(CMS_KeyTransRecipientInfo, rid, CMS_SignerIdentifier), + ASN1_SIMPLE(CMS_KeyTransRecipientInfo, keyEncryptionAlgorithm, X509_ALGOR), + ASN1_SIMPLE(CMS_KeyTransRecipientInfo, encryptedKey, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(CMS_KeyTransRecipientInfo) + +ASN1_SEQUENCE(CMS_OtherKeyAttribute) = { + ASN1_SIMPLE(CMS_OtherKeyAttribute, keyAttrId, ASN1_OBJECT), + ASN1_OPT(CMS_OtherKeyAttribute, keyAttr, ASN1_ANY) +} ASN1_SEQUENCE_END(CMS_OtherKeyAttribute) + +ASN1_SEQUENCE(CMS_RecipientKeyIdentifier) = { + ASN1_SIMPLE(CMS_RecipientKeyIdentifier, subjectKeyIdentifier, ASN1_OCTET_STRING), + ASN1_OPT(CMS_RecipientKeyIdentifier, date, ASN1_GENERALIZEDTIME), + ASN1_OPT(CMS_RecipientKeyIdentifier, other, CMS_OtherKeyAttribute) +} ASN1_SEQUENCE_END(CMS_RecipientKeyIdentifier) + +ASN1_CHOICE(CMS_KeyAgreeRecipientIdentifier) = { + ASN1_SIMPLE(CMS_KeyAgreeRecipientIdentifier, d.issuerAndSerialNumber, CMS_IssuerAndSerialNumber), + ASN1_IMP(CMS_KeyAgreeRecipientIdentifier, d.rKeyId, CMS_RecipientKeyIdentifier, 0) +} static_ASN1_CHOICE_END(CMS_KeyAgreeRecipientIdentifier) + +static int cms_rek_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + CMS_RecipientEncryptedKey *rek = (CMS_RecipientEncryptedKey *)*pval; + if (operation == ASN1_OP_FREE_POST) { + EVP_PKEY_free(rek->pkey); + } + return 1; +} + +ASN1_SEQUENCE_cb(CMS_RecipientEncryptedKey, cms_rek_cb) = { + ASN1_SIMPLE(CMS_RecipientEncryptedKey, rid, CMS_KeyAgreeRecipientIdentifier), + ASN1_SIMPLE(CMS_RecipientEncryptedKey, encryptedKey, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END_cb(CMS_RecipientEncryptedKey, CMS_RecipientEncryptedKey) + +ASN1_SEQUENCE(CMS_OriginatorPublicKey) = { + ASN1_SIMPLE(CMS_OriginatorPublicKey, algorithm, X509_ALGOR), + ASN1_SIMPLE(CMS_OriginatorPublicKey, publicKey, ASN1_BIT_STRING) +} ASN1_SEQUENCE_END(CMS_OriginatorPublicKey) + +ASN1_CHOICE(CMS_OriginatorIdentifierOrKey) = { + ASN1_SIMPLE(CMS_OriginatorIdentifierOrKey, d.issuerAndSerialNumber, CMS_IssuerAndSerialNumber), + ASN1_IMP(CMS_OriginatorIdentifierOrKey, d.subjectKeyIdentifier, ASN1_OCTET_STRING, 0), + ASN1_IMP(CMS_OriginatorIdentifierOrKey, d.originatorKey, CMS_OriginatorPublicKey, 1) +} static_ASN1_CHOICE_END(CMS_OriginatorIdentifierOrKey) + +static int cms_kari_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + CMS_KeyAgreeRecipientInfo *kari = (CMS_KeyAgreeRecipientInfo *)*pval; + if (operation == ASN1_OP_NEW_POST) { + kari->ctx = EVP_CIPHER_CTX_new(); + if (kari->ctx == NULL) + return 0; + EVP_CIPHER_CTX_set_flags(kari->ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW); + kari->pctx = NULL; + } else if (operation == ASN1_OP_FREE_POST) { + EVP_PKEY_CTX_free(kari->pctx); + EVP_CIPHER_CTX_free(kari->ctx); + } + return 1; +} + +ASN1_SEQUENCE_cb(CMS_KeyAgreeRecipientInfo, cms_kari_cb) = { + ASN1_EMBED(CMS_KeyAgreeRecipientInfo, version, INT32), + ASN1_EXP(CMS_KeyAgreeRecipientInfo, originator, CMS_OriginatorIdentifierOrKey, 0), + ASN1_EXP_OPT(CMS_KeyAgreeRecipientInfo, ukm, ASN1_OCTET_STRING, 1), + ASN1_SIMPLE(CMS_KeyAgreeRecipientInfo, keyEncryptionAlgorithm, X509_ALGOR), + ASN1_SEQUENCE_OF(CMS_KeyAgreeRecipientInfo, recipientEncryptedKeys, CMS_RecipientEncryptedKey) +} ASN1_SEQUENCE_END_cb(CMS_KeyAgreeRecipientInfo, CMS_KeyAgreeRecipientInfo) + +ASN1_SEQUENCE(CMS_KEKIdentifier) = { + ASN1_SIMPLE(CMS_KEKIdentifier, keyIdentifier, ASN1_OCTET_STRING), + ASN1_OPT(CMS_KEKIdentifier, date, ASN1_GENERALIZEDTIME), + ASN1_OPT(CMS_KEKIdentifier, other, CMS_OtherKeyAttribute) +} static_ASN1_SEQUENCE_END(CMS_KEKIdentifier) + +ASN1_SEQUENCE(CMS_KEKRecipientInfo) = { + ASN1_EMBED(CMS_KEKRecipientInfo, version, INT32), + ASN1_SIMPLE(CMS_KEKRecipientInfo, kekid, CMS_KEKIdentifier), + ASN1_SIMPLE(CMS_KEKRecipientInfo, keyEncryptionAlgorithm, X509_ALGOR), + ASN1_SIMPLE(CMS_KEKRecipientInfo, encryptedKey, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(CMS_KEKRecipientInfo) + +ASN1_SEQUENCE(CMS_PasswordRecipientInfo) = { + ASN1_EMBED(CMS_PasswordRecipientInfo, version, INT32), + ASN1_IMP_OPT(CMS_PasswordRecipientInfo, keyDerivationAlgorithm, X509_ALGOR, 0), + ASN1_SIMPLE(CMS_PasswordRecipientInfo, keyEncryptionAlgorithm, X509_ALGOR), + ASN1_SIMPLE(CMS_PasswordRecipientInfo, encryptedKey, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(CMS_PasswordRecipientInfo) + +ASN1_SEQUENCE(CMS_OtherRecipientInfo) = { + ASN1_SIMPLE(CMS_OtherRecipientInfo, oriType, ASN1_OBJECT), + ASN1_OPT(CMS_OtherRecipientInfo, oriValue, ASN1_ANY) +} static_ASN1_SEQUENCE_END(CMS_OtherRecipientInfo) + +/* Free up RecipientInfo additional data */ +static int cms_ri_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + if (operation == ASN1_OP_FREE_PRE) { + CMS_RecipientInfo *ri = (CMS_RecipientInfo *)*pval; + if (ri->type == CMS_RECIPINFO_TRANS) { + CMS_KeyTransRecipientInfo *ktri = ri->d.ktri; + EVP_PKEY_free(ktri->pkey); + X509_free(ktri->recip); + EVP_PKEY_CTX_free(ktri->pctx); + } else if (ri->type == CMS_RECIPINFO_KEK) { + CMS_KEKRecipientInfo *kekri = ri->d.kekri; + OPENSSL_clear_free(kekri->key, kekri->keylen); + } else if (ri->type == CMS_RECIPINFO_PASS) { + CMS_PasswordRecipientInfo *pwri = ri->d.pwri; + OPENSSL_clear_free(pwri->pass, pwri->passlen); + } + } + return 1; +} + +ASN1_CHOICE_cb(CMS_RecipientInfo, cms_ri_cb) = { + ASN1_SIMPLE(CMS_RecipientInfo, d.ktri, CMS_KeyTransRecipientInfo), + ASN1_IMP(CMS_RecipientInfo, d.kari, CMS_KeyAgreeRecipientInfo, 1), + ASN1_IMP(CMS_RecipientInfo, d.kekri, CMS_KEKRecipientInfo, 2), + ASN1_IMP(CMS_RecipientInfo, d.pwri, CMS_PasswordRecipientInfo, 3), + ASN1_IMP(CMS_RecipientInfo, d.ori, CMS_OtherRecipientInfo, 4) +} ASN1_CHOICE_END_cb(CMS_RecipientInfo, CMS_RecipientInfo, type) + +ASN1_NDEF_SEQUENCE(CMS_EnvelopedData) = { + ASN1_EMBED(CMS_EnvelopedData, version, INT32), + ASN1_IMP_OPT(CMS_EnvelopedData, originatorInfo, CMS_OriginatorInfo, 0), + ASN1_SET_OF(CMS_EnvelopedData, recipientInfos, CMS_RecipientInfo), + ASN1_SIMPLE(CMS_EnvelopedData, encryptedContentInfo, CMS_EncryptedContentInfo), + ASN1_IMP_SET_OF_OPT(CMS_EnvelopedData, unprotectedAttrs, X509_ATTRIBUTE, 1) +} ASN1_NDEF_SEQUENCE_END(CMS_EnvelopedData) + +ASN1_NDEF_SEQUENCE(CMS_DigestedData) = { + ASN1_EMBED(CMS_DigestedData, version, INT32), + ASN1_SIMPLE(CMS_DigestedData, digestAlgorithm, X509_ALGOR), + ASN1_SIMPLE(CMS_DigestedData, encapContentInfo, CMS_EncapsulatedContentInfo), + ASN1_SIMPLE(CMS_DigestedData, digest, ASN1_OCTET_STRING) +} ASN1_NDEF_SEQUENCE_END(CMS_DigestedData) + +ASN1_NDEF_SEQUENCE(CMS_EncryptedData) = { + ASN1_EMBED(CMS_EncryptedData, version, INT32), + ASN1_SIMPLE(CMS_EncryptedData, encryptedContentInfo, CMS_EncryptedContentInfo), + ASN1_IMP_SET_OF_OPT(CMS_EncryptedData, unprotectedAttrs, X509_ATTRIBUTE, 1) +} ASN1_NDEF_SEQUENCE_END(CMS_EncryptedData) + +ASN1_NDEF_SEQUENCE(CMS_AuthenticatedData) = { + ASN1_EMBED(CMS_AuthenticatedData, version, INT32), + ASN1_IMP_OPT(CMS_AuthenticatedData, originatorInfo, CMS_OriginatorInfo, 0), + ASN1_SET_OF(CMS_AuthenticatedData, recipientInfos, CMS_RecipientInfo), + ASN1_SIMPLE(CMS_AuthenticatedData, macAlgorithm, X509_ALGOR), + ASN1_IMP(CMS_AuthenticatedData, digestAlgorithm, X509_ALGOR, 1), + ASN1_SIMPLE(CMS_AuthenticatedData, encapContentInfo, CMS_EncapsulatedContentInfo), + ASN1_IMP_SET_OF_OPT(CMS_AuthenticatedData, authAttrs, X509_ALGOR, 2), + ASN1_SIMPLE(CMS_AuthenticatedData, mac, ASN1_OCTET_STRING), + ASN1_IMP_SET_OF_OPT(CMS_AuthenticatedData, unauthAttrs, X509_ALGOR, 3) +} static_ASN1_NDEF_SEQUENCE_END(CMS_AuthenticatedData) + +ASN1_NDEF_SEQUENCE(CMS_CompressedData) = { + ASN1_EMBED(CMS_CompressedData, version, INT32), + ASN1_SIMPLE(CMS_CompressedData, compressionAlgorithm, X509_ALGOR), + ASN1_SIMPLE(CMS_CompressedData, encapContentInfo, CMS_EncapsulatedContentInfo), +} ASN1_NDEF_SEQUENCE_END(CMS_CompressedData) + +/* This is the ANY DEFINED BY table for the top level ContentInfo structure */ + +ASN1_ADB_TEMPLATE(cms_default) = ASN1_EXP(CMS_ContentInfo, d.other, ASN1_ANY, 0); + +ASN1_ADB(CMS_ContentInfo) = { + ADB_ENTRY(NID_pkcs7_data, ASN1_NDEF_EXP(CMS_ContentInfo, d.data, ASN1_OCTET_STRING_NDEF, 0)), + ADB_ENTRY(NID_pkcs7_signed, ASN1_NDEF_EXP(CMS_ContentInfo, d.signedData, CMS_SignedData, 0)), + ADB_ENTRY(NID_pkcs7_enveloped, ASN1_NDEF_EXP(CMS_ContentInfo, d.envelopedData, CMS_EnvelopedData, 0)), + ADB_ENTRY(NID_pkcs7_digest, ASN1_NDEF_EXP(CMS_ContentInfo, d.digestedData, CMS_DigestedData, 0)), + ADB_ENTRY(NID_pkcs7_encrypted, ASN1_NDEF_EXP(CMS_ContentInfo, d.encryptedData, CMS_EncryptedData, 0)), + ADB_ENTRY(NID_id_smime_ct_authData, ASN1_NDEF_EXP(CMS_ContentInfo, d.authenticatedData, CMS_AuthenticatedData, 0)), + ADB_ENTRY(NID_id_smime_ct_compressedData, ASN1_NDEF_EXP(CMS_ContentInfo, d.compressedData, CMS_CompressedData, 0)), +} ASN1_ADB_END(CMS_ContentInfo, 0, contentType, 0, &cms_default_tt, NULL); + +/* CMS streaming support */ +static int cms_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + ASN1_STREAM_ARG *sarg = exarg; + CMS_ContentInfo *cms = NULL; + if (pval) + cms = (CMS_ContentInfo *)*pval; + else + return 1; + switch (operation) { + + case ASN1_OP_STREAM_PRE: + if (CMS_stream(&sarg->boundary, cms) <= 0) + return 0; + /* fall thru */ + case ASN1_OP_DETACHED_PRE: + sarg->ndef_bio = CMS_dataInit(cms, sarg->out); + if (!sarg->ndef_bio) + return 0; + break; + + case ASN1_OP_STREAM_POST: + case ASN1_OP_DETACHED_POST: + if (CMS_dataFinal(cms, sarg->ndef_bio) <= 0) + return 0; + break; + + } + return 1; +} + +ASN1_NDEF_SEQUENCE_cb(CMS_ContentInfo, cms_cb) = { + ASN1_SIMPLE(CMS_ContentInfo, contentType, ASN1_OBJECT), + ASN1_ADB_OBJECT(CMS_ContentInfo) +} ASN1_NDEF_SEQUENCE_END_cb(CMS_ContentInfo, CMS_ContentInfo) + +/* Specials for signed attributes */ + +/* + * When signing attributes we want to reorder them to match the sorted + * encoding. + */ + +ASN1_ITEM_TEMPLATE(CMS_Attributes_Sign) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_ORDER, 0, CMS_ATTRIBUTES, X509_ATTRIBUTE) +ASN1_ITEM_TEMPLATE_END(CMS_Attributes_Sign) + +/* + * When verifying attributes we need to use the received order. So we use + * SEQUENCE OF and tag it to SET OF + */ + +ASN1_ITEM_TEMPLATE(CMS_Attributes_Verify) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_IMPTAG | ASN1_TFLG_UNIVERSAL, + V_ASN1_SET, CMS_ATTRIBUTES, X509_ATTRIBUTE) +ASN1_ITEM_TEMPLATE_END(CMS_Attributes_Verify) + + + +ASN1_CHOICE(CMS_ReceiptsFrom) = { + ASN1_IMP_EMBED(CMS_ReceiptsFrom, d.allOrFirstTier, INT32, 0), + ASN1_IMP_SEQUENCE_OF(CMS_ReceiptsFrom, d.receiptList, GENERAL_NAMES, 1) +} static_ASN1_CHOICE_END(CMS_ReceiptsFrom) + +ASN1_SEQUENCE(CMS_ReceiptRequest) = { + ASN1_SIMPLE(CMS_ReceiptRequest, signedContentIdentifier, ASN1_OCTET_STRING), + ASN1_SIMPLE(CMS_ReceiptRequest, receiptsFrom, CMS_ReceiptsFrom), + ASN1_SEQUENCE_OF(CMS_ReceiptRequest, receiptsTo, GENERAL_NAMES) +} ASN1_SEQUENCE_END(CMS_ReceiptRequest) + +ASN1_SEQUENCE(CMS_Receipt) = { + ASN1_EMBED(CMS_Receipt, version, INT32), + ASN1_SIMPLE(CMS_Receipt, contentType, ASN1_OBJECT), + ASN1_SIMPLE(CMS_Receipt, signedContentIdentifier, ASN1_OCTET_STRING), + ASN1_SIMPLE(CMS_Receipt, originatorSignatureValue, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(CMS_Receipt) + +/* + * Utilities to encode the CMS_SharedInfo structure used during key + * derivation. + */ + +typedef struct { + X509_ALGOR *keyInfo; + ASN1_OCTET_STRING *entityUInfo; + ASN1_OCTET_STRING *suppPubInfo; +} CMS_SharedInfo; + +ASN1_SEQUENCE(CMS_SharedInfo) = { + ASN1_SIMPLE(CMS_SharedInfo, keyInfo, X509_ALGOR), + ASN1_EXP_OPT(CMS_SharedInfo, entityUInfo, ASN1_OCTET_STRING, 0), + ASN1_EXP_OPT(CMS_SharedInfo, suppPubInfo, ASN1_OCTET_STRING, 2), +} static_ASN1_SEQUENCE_END(CMS_SharedInfo) + +int CMS_SharedInfo_encode(unsigned char **pder, X509_ALGOR *kekalg, + ASN1_OCTET_STRING *ukm, int keylen) +{ + union { + CMS_SharedInfo *pecsi; + ASN1_VALUE *a; + } intsi = { + NULL + }; + + ASN1_OCTET_STRING oklen; + unsigned char kl[4]; + CMS_SharedInfo ecsi; + + keylen <<= 3; + kl[0] = (keylen >> 24) & 0xff; + kl[1] = (keylen >> 16) & 0xff; + kl[2] = (keylen >> 8) & 0xff; + kl[3] = keylen & 0xff; + oklen.length = 4; + oklen.data = kl; + oklen.type = V_ASN1_OCTET_STRING; + oklen.flags = 0; + ecsi.keyInfo = kekalg; + ecsi.entityUInfo = ukm; + ecsi.suppPubInfo = &oklen; + intsi.pecsi = &ecsi; + return ASN1_item_i2d(intsi.a, pder, ASN1_ITEM_rptr(CMS_SharedInfo)); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_att.c b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_att.c new file mode 100644 index 000000000..664e64971 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_att.c @@ -0,0 +1,152 @@ +/* + * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include "cms_lcl.h" + +/* CMS SignedData Attribute utilities */ + +int CMS_signed_get_attr_count(const CMS_SignerInfo *si) +{ + return X509at_get_attr_count(si->signedAttrs); +} + +int CMS_signed_get_attr_by_NID(const CMS_SignerInfo *si, int nid, int lastpos) +{ + return X509at_get_attr_by_NID(si->signedAttrs, nid, lastpos); +} + +int CMS_signed_get_attr_by_OBJ(const CMS_SignerInfo *si, const ASN1_OBJECT *obj, + int lastpos) +{ + return X509at_get_attr_by_OBJ(si->signedAttrs, obj, lastpos); +} + +X509_ATTRIBUTE *CMS_signed_get_attr(const CMS_SignerInfo *si, int loc) +{ + return X509at_get_attr(si->signedAttrs, loc); +} + +X509_ATTRIBUTE *CMS_signed_delete_attr(CMS_SignerInfo *si, int loc) +{ + return X509at_delete_attr(si->signedAttrs, loc); +} + +int CMS_signed_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr) +{ + if (X509at_add1_attr(&si->signedAttrs, attr)) + return 1; + return 0; +} + +int CMS_signed_add1_attr_by_OBJ(CMS_SignerInfo *si, + const ASN1_OBJECT *obj, int type, + const void *bytes, int len) +{ + if (X509at_add1_attr_by_OBJ(&si->signedAttrs, obj, type, bytes, len)) + return 1; + return 0; +} + +int CMS_signed_add1_attr_by_NID(CMS_SignerInfo *si, + int nid, int type, const void *bytes, int len) +{ + if (X509at_add1_attr_by_NID(&si->signedAttrs, nid, type, bytes, len)) + return 1; + return 0; +} + +int CMS_signed_add1_attr_by_txt(CMS_SignerInfo *si, + const char *attrname, int type, + const void *bytes, int len) +{ + if (X509at_add1_attr_by_txt(&si->signedAttrs, attrname, type, bytes, len)) + return 1; + return 0; +} + +void *CMS_signed_get0_data_by_OBJ(CMS_SignerInfo *si, const ASN1_OBJECT *oid, + int lastpos, int type) +{ + return X509at_get0_data_by_OBJ(si->signedAttrs, oid, lastpos, type); +} + +int CMS_unsigned_get_attr_count(const CMS_SignerInfo *si) +{ + return X509at_get_attr_count(si->unsignedAttrs); +} + +int CMS_unsigned_get_attr_by_NID(const CMS_SignerInfo *si, int nid, + int lastpos) +{ + return X509at_get_attr_by_NID(si->unsignedAttrs, nid, lastpos); +} + +int CMS_unsigned_get_attr_by_OBJ(const CMS_SignerInfo *si, + const ASN1_OBJECT *obj, int lastpos) +{ + return X509at_get_attr_by_OBJ(si->unsignedAttrs, obj, lastpos); +} + +X509_ATTRIBUTE *CMS_unsigned_get_attr(const CMS_SignerInfo *si, int loc) +{ + return X509at_get_attr(si->unsignedAttrs, loc); +} + +X509_ATTRIBUTE *CMS_unsigned_delete_attr(CMS_SignerInfo *si, int loc) +{ + return X509at_delete_attr(si->unsignedAttrs, loc); +} + +int CMS_unsigned_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr) +{ + if (X509at_add1_attr(&si->unsignedAttrs, attr)) + return 1; + return 0; +} + +int CMS_unsigned_add1_attr_by_OBJ(CMS_SignerInfo *si, + const ASN1_OBJECT *obj, int type, + const void *bytes, int len) +{ + if (X509at_add1_attr_by_OBJ(&si->unsignedAttrs, obj, type, bytes, len)) + return 1; + return 0; +} + +int CMS_unsigned_add1_attr_by_NID(CMS_SignerInfo *si, + int nid, int type, + const void *bytes, int len) +{ + if (X509at_add1_attr_by_NID(&si->unsignedAttrs, nid, type, bytes, len)) + return 1; + return 0; +} + +int CMS_unsigned_add1_attr_by_txt(CMS_SignerInfo *si, + const char *attrname, int type, + const void *bytes, int len) +{ + if (X509at_add1_attr_by_txt(&si->unsignedAttrs, attrname, + type, bytes, len)) + return 1; + return 0; +} + +void *CMS_unsigned_get0_data_by_OBJ(CMS_SignerInfo *si, ASN1_OBJECT *oid, + int lastpos, int type) +{ + return X509at_get0_data_by_OBJ(si->unsignedAttrs, oid, lastpos, type); +} + +/* Specific attribute cases */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_cd.c b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_cd.c new file mode 100644 index 000000000..f05e30841 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_cd.c @@ -0,0 +1,82 @@ +/* + * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include +#include +#include "cms_lcl.h" + +#ifdef ZLIB + +/* CMS CompressedData Utilities */ + +CMS_ContentInfo *cms_CompressedData_create(int comp_nid) +{ + CMS_ContentInfo *cms; + CMS_CompressedData *cd; + /* + * Will need something cleverer if there is ever more than one + * compression algorithm or parameters have some meaning... + */ + if (comp_nid != NID_zlib_compression) { + CMSerr(CMS_F_CMS_COMPRESSEDDATA_CREATE, + CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM); + return NULL; + } + cms = CMS_ContentInfo_new(); + if (cms == NULL) + return NULL; + + cd = M_ASN1_new_of(CMS_CompressedData); + + if (cd == NULL) + goto err; + + cms->contentType = OBJ_nid2obj(NID_id_smime_ct_compressedData); + cms->d.compressedData = cd; + + cd->version = 0; + + X509_ALGOR_set0(cd->compressionAlgorithm, + OBJ_nid2obj(NID_zlib_compression), V_ASN1_UNDEF, NULL); + + cd->encapContentInfo->eContentType = OBJ_nid2obj(NID_pkcs7_data); + + return cms; + + err: + CMS_ContentInfo_free(cms); + return NULL; +} + +BIO *cms_CompressedData_init_bio(CMS_ContentInfo *cms) +{ + CMS_CompressedData *cd; + const ASN1_OBJECT *compoid; + if (OBJ_obj2nid(cms->contentType) != NID_id_smime_ct_compressedData) { + CMSerr(CMS_F_CMS_COMPRESSEDDATA_INIT_BIO, + CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA); + return NULL; + } + cd = cms->d.compressedData; + X509_ALGOR_get0(&compoid, NULL, NULL, cd->compressionAlgorithm); + if (OBJ_obj2nid(compoid) != NID_zlib_compression) { + CMSerr(CMS_F_CMS_COMPRESSEDDATA_INIT_BIO, + CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM); + return NULL; + } + return BIO_new(BIO_f_zlib()); +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_dd.c b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_dd.c new file mode 100644 index 000000000..5da6802fc --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_dd.c @@ -0,0 +1,99 @@ +/* + * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include "cms_lcl.h" + +/* CMS DigestedData Utilities */ + +CMS_ContentInfo *cms_DigestedData_create(const EVP_MD *md) +{ + CMS_ContentInfo *cms; + CMS_DigestedData *dd; + cms = CMS_ContentInfo_new(); + if (cms == NULL) + return NULL; + + dd = M_ASN1_new_of(CMS_DigestedData); + + if (dd == NULL) + goto err; + + cms->contentType = OBJ_nid2obj(NID_pkcs7_digest); + cms->d.digestedData = dd; + + dd->version = 0; + dd->encapContentInfo->eContentType = OBJ_nid2obj(NID_pkcs7_data); + + X509_ALGOR_set_md(dd->digestAlgorithm, md); + + return cms; + + err: + CMS_ContentInfo_free(cms); + return NULL; +} + +BIO *cms_DigestedData_init_bio(CMS_ContentInfo *cms) +{ + CMS_DigestedData *dd; + dd = cms->d.digestedData; + return cms_DigestAlgorithm_init_bio(dd->digestAlgorithm); +} + +int cms_DigestedData_do_final(CMS_ContentInfo *cms, BIO *chain, int verify) +{ + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); + unsigned char md[EVP_MAX_MD_SIZE]; + unsigned int mdlen; + int r = 0; + CMS_DigestedData *dd; + + if (mctx == NULL) { + CMSerr(CMS_F_CMS_DIGESTEDDATA_DO_FINAL, ERR_R_MALLOC_FAILURE); + goto err; + } + + dd = cms->d.digestedData; + + if (!cms_DigestAlgorithm_find_ctx(mctx, chain, dd->digestAlgorithm)) + goto err; + + if (EVP_DigestFinal_ex(mctx, md, &mdlen) <= 0) + goto err; + + if (verify) { + if (mdlen != (unsigned int)dd->digest->length) { + CMSerr(CMS_F_CMS_DIGESTEDDATA_DO_FINAL, + CMS_R_MESSAGEDIGEST_WRONG_LENGTH); + goto err; + } + + if (memcmp(md, dd->digest->data, mdlen)) + CMSerr(CMS_F_CMS_DIGESTEDDATA_DO_FINAL, + CMS_R_VERIFICATION_FAILURE); + else + r = 1; + } else { + if (!ASN1_STRING_set(dd->digest, md, mdlen)) + goto err; + r = 1; + } + + err: + EVP_MD_CTX_free(mctx); + + return r; + +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_enc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_enc.c new file mode 100644 index 000000000..a1719830e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_enc.c @@ -0,0 +1,213 @@ +/* + * Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include +#include "cms_lcl.h" + +/* CMS EncryptedData Utilities */ + +/* Return BIO based on EncryptedContentInfo and key */ + +BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec) +{ + BIO *b; + EVP_CIPHER_CTX *ctx; + const EVP_CIPHER *ciph; + X509_ALGOR *calg = ec->contentEncryptionAlgorithm; + unsigned char iv[EVP_MAX_IV_LENGTH], *piv = NULL; + unsigned char *tkey = NULL; + size_t tkeylen = 0; + + int ok = 0; + + int enc, keep_key = 0; + + enc = ec->cipher ? 1 : 0; + + b = BIO_new(BIO_f_cipher()); + if (b == NULL) { + CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE); + return NULL; + } + + BIO_get_cipher_ctx(b, &ctx); + + if (enc) { + ciph = ec->cipher; + /* + * If not keeping key set cipher to NULL so subsequent calls decrypt. + */ + if (ec->key) + ec->cipher = NULL; + } else { + ciph = EVP_get_cipherbyobj(calg->algorithm); + + if (!ciph) { + CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, CMS_R_UNKNOWN_CIPHER); + goto err; + } + } + + if (EVP_CipherInit_ex(ctx, ciph, NULL, NULL, NULL, enc) <= 0) { + CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, + CMS_R_CIPHER_INITIALISATION_ERROR); + goto err; + } + + if (enc) { + int ivlen; + calg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(ctx)); + /* Generate a random IV if we need one */ + ivlen = EVP_CIPHER_CTX_iv_length(ctx); + if (ivlen > 0) { + if (RAND_bytes(iv, ivlen) <= 0) + goto err; + piv = iv; + } + } else if (EVP_CIPHER_asn1_to_param(ctx, calg->parameter) <= 0) { + CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, + CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); + goto err; + } + tkeylen = EVP_CIPHER_CTX_key_length(ctx); + /* Generate random session key */ + if (!enc || !ec->key) { + tkey = OPENSSL_malloc(tkeylen); + if (tkey == NULL) { + CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE); + goto err; + } + if (EVP_CIPHER_CTX_rand_key(ctx, tkey) <= 0) + goto err; + } + + if (!ec->key) { + ec->key = tkey; + ec->keylen = tkeylen; + tkey = NULL; + if (enc) + keep_key = 1; + else + ERR_clear_error(); + + } + + if (ec->keylen != tkeylen) { + /* If necessary set key length */ + if (EVP_CIPHER_CTX_set_key_length(ctx, ec->keylen) <= 0) { + /* + * Only reveal failure if debugging so we don't leak information + * which may be useful in MMA. + */ + if (enc || ec->debug) { + CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, + CMS_R_INVALID_KEY_LENGTH); + goto err; + } else { + /* Use random key */ + OPENSSL_clear_free(ec->key, ec->keylen); + ec->key = tkey; + ec->keylen = tkeylen; + tkey = NULL; + ERR_clear_error(); + } + } + } + + if (EVP_CipherInit_ex(ctx, NULL, NULL, ec->key, piv, enc) <= 0) { + CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, + CMS_R_CIPHER_INITIALISATION_ERROR); + goto err; + } + if (enc) { + calg->parameter = ASN1_TYPE_new(); + if (calg->parameter == NULL) { + CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE); + goto err; + } + if (EVP_CIPHER_param_to_asn1(ctx, calg->parameter) <= 0) { + CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, + CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); + goto err; + } + /* If parameter type not set omit parameter */ + if (calg->parameter->type == V_ASN1_UNDEF) { + ASN1_TYPE_free(calg->parameter); + calg->parameter = NULL; + } + } + ok = 1; + + err: + if (!keep_key || !ok) { + OPENSSL_clear_free(ec->key, ec->keylen); + ec->key = NULL; + } + OPENSSL_clear_free(tkey, tkeylen); + if (ok) + return b; + BIO_free(b); + return NULL; +} + +int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec, + const EVP_CIPHER *cipher, + const unsigned char *key, size_t keylen) +{ + ec->cipher = cipher; + if (key) { + if ((ec->key = OPENSSL_malloc(keylen)) == NULL) { + CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT, ERR_R_MALLOC_FAILURE); + return 0; + } + memcpy(ec->key, key, keylen); + } + ec->keylen = keylen; + if (cipher) + ec->contentType = OBJ_nid2obj(NID_pkcs7_data); + return 1; +} + +int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph, + const unsigned char *key, size_t keylen) +{ + CMS_EncryptedContentInfo *ec; + if (!key || !keylen) { + CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, CMS_R_NO_KEY); + return 0; + } + if (ciph) { + cms->d.encryptedData = M_ASN1_new_of(CMS_EncryptedData); + if (!cms->d.encryptedData) { + CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, ERR_R_MALLOC_FAILURE); + return 0; + } + cms->contentType = OBJ_nid2obj(NID_pkcs7_encrypted); + cms->d.encryptedData->version = 0; + } else if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_encrypted) { + CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, CMS_R_NOT_ENCRYPTED_DATA); + return 0; + } + ec = cms->d.encryptedData->encryptedContentInfo; + return cms_EncryptedContent_init(ec, ciph, key, keylen); +} + +BIO *cms_EncryptedData_init_bio(CMS_ContentInfo *cms) +{ + CMS_EncryptedData *enc = cms->d.encryptedData; + if (enc->encryptedContentInfo->cipher && enc->unprotectedAttrs) + enc->version = 2; + return cms_EncryptedContent_init_bio(enc->encryptedContentInfo); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_env.c b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_env.c new file mode 100644 index 000000000..bb95af75e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_env.c @@ -0,0 +1,903 @@ +/* + * Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include +#include "cms_lcl.h" +#include "internal/asn1_int.h" +#include "internal/evp_int.h" + +/* CMS EnvelopedData Utilities */ + +CMS_EnvelopedData *cms_get0_enveloped(CMS_ContentInfo *cms) +{ + if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_enveloped) { + CMSerr(CMS_F_CMS_GET0_ENVELOPED, + CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA); + return NULL; + } + return cms->d.envelopedData; +} + +static CMS_EnvelopedData *cms_enveloped_data_init(CMS_ContentInfo *cms) +{ + if (cms->d.other == NULL) { + cms->d.envelopedData = M_ASN1_new_of(CMS_EnvelopedData); + if (!cms->d.envelopedData) { + CMSerr(CMS_F_CMS_ENVELOPED_DATA_INIT, ERR_R_MALLOC_FAILURE); + return NULL; + } + cms->d.envelopedData->version = 0; + cms->d.envelopedData->encryptedContentInfo->contentType = + OBJ_nid2obj(NID_pkcs7_data); + ASN1_OBJECT_free(cms->contentType); + cms->contentType = OBJ_nid2obj(NID_pkcs7_enveloped); + return cms->d.envelopedData; + } + return cms_get0_enveloped(cms); +} + +int cms_env_asn1_ctrl(CMS_RecipientInfo *ri, int cmd) +{ + EVP_PKEY *pkey; + int i; + if (ri->type == CMS_RECIPINFO_TRANS) + pkey = ri->d.ktri->pkey; + else if (ri->type == CMS_RECIPINFO_AGREE) { + EVP_PKEY_CTX *pctx = ri->d.kari->pctx; + if (!pctx) + return 0; + pkey = EVP_PKEY_CTX_get0_pkey(pctx); + if (!pkey) + return 0; + } else + return 0; + if (!pkey->ameth || !pkey->ameth->pkey_ctrl) + return 1; + i = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_CMS_ENVELOPE, cmd, ri); + if (i == -2) { + CMSerr(CMS_F_CMS_ENV_ASN1_CTRL, + CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); + return 0; + } + if (i <= 0) { + CMSerr(CMS_F_CMS_ENV_ASN1_CTRL, CMS_R_CTRL_FAILURE); + return 0; + } + return 1; +} + +STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms) +{ + CMS_EnvelopedData *env; + env = cms_get0_enveloped(cms); + if (!env) + return NULL; + return env->recipientInfos; +} + +int CMS_RecipientInfo_type(CMS_RecipientInfo *ri) +{ + return ri->type; +} + +EVP_PKEY_CTX *CMS_RecipientInfo_get0_pkey_ctx(CMS_RecipientInfo *ri) +{ + if (ri->type == CMS_RECIPINFO_TRANS) + return ri->d.ktri->pctx; + else if (ri->type == CMS_RECIPINFO_AGREE) + return ri->d.kari->pctx; + return NULL; +} + +CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher) +{ + CMS_ContentInfo *cms; + CMS_EnvelopedData *env; + cms = CMS_ContentInfo_new(); + if (cms == NULL) + goto merr; + env = cms_enveloped_data_init(cms); + if (env == NULL) + goto merr; + if (!cms_EncryptedContent_init(env->encryptedContentInfo, + cipher, NULL, 0)) + goto merr; + return cms; + merr: + CMS_ContentInfo_free(cms); + CMSerr(CMS_F_CMS_ENVELOPEDDATA_CREATE, ERR_R_MALLOC_FAILURE); + return NULL; +} + +/* Key Transport Recipient Info (KTRI) routines */ + +/* Initialise a ktri based on passed certificate and key */ + +static int cms_RecipientInfo_ktri_init(CMS_RecipientInfo *ri, X509 *recip, + EVP_PKEY *pk, unsigned int flags) +{ + CMS_KeyTransRecipientInfo *ktri; + int idtype; + + ri->d.ktri = M_ASN1_new_of(CMS_KeyTransRecipientInfo); + if (!ri->d.ktri) + return 0; + ri->type = CMS_RECIPINFO_TRANS; + + ktri = ri->d.ktri; + + if (flags & CMS_USE_KEYID) { + ktri->version = 2; + idtype = CMS_RECIPINFO_KEYIDENTIFIER; + } else { + ktri->version = 0; + idtype = CMS_RECIPINFO_ISSUER_SERIAL; + } + + /* + * Not a typo: RecipientIdentifier and SignerIdentifier are the same + * structure. + */ + + if (!cms_set1_SignerIdentifier(ktri->rid, recip, idtype)) + return 0; + + X509_up_ref(recip); + EVP_PKEY_up_ref(pk); + + ktri->pkey = pk; + ktri->recip = recip; + + if (flags & CMS_KEY_PARAM) { + ktri->pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL); + if (ktri->pctx == NULL) + return 0; + if (EVP_PKEY_encrypt_init(ktri->pctx) <= 0) + return 0; + } else if (!cms_env_asn1_ctrl(ri, 0)) + return 0; + return 1; +} + +/* + * Add a recipient certificate using appropriate type of RecipientInfo + */ + +CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms, + X509 *recip, unsigned int flags) +{ + CMS_RecipientInfo *ri = NULL; + CMS_EnvelopedData *env; + EVP_PKEY *pk = NULL; + env = cms_get0_enveloped(cms); + if (!env) + goto err; + + /* Initialize recipient info */ + ri = M_ASN1_new_of(CMS_RecipientInfo); + if (!ri) + goto merr; + + pk = X509_get0_pubkey(recip); + if (!pk) { + CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, CMS_R_ERROR_GETTING_PUBLIC_KEY); + goto err; + } + + switch (cms_pkey_get_ri_type(pk)) { + + case CMS_RECIPINFO_TRANS: + if (!cms_RecipientInfo_ktri_init(ri, recip, pk, flags)) + goto err; + break; + + case CMS_RECIPINFO_AGREE: + if (!cms_RecipientInfo_kari_init(ri, recip, pk, flags)) + goto err; + break; + + default: + CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, + CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); + goto err; + + } + + if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri)) + goto merr; + + return ri; + + merr: + CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, ERR_R_MALLOC_FAILURE); + err: + M_ASN1_free_of(ri, CMS_RecipientInfo); + return NULL; + +} + +int CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri, + EVP_PKEY **pk, X509 **recip, + X509_ALGOR **palg) +{ + CMS_KeyTransRecipientInfo *ktri; + if (ri->type != CMS_RECIPINFO_TRANS) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS, + CMS_R_NOT_KEY_TRANSPORT); + return 0; + } + + ktri = ri->d.ktri; + + if (pk) + *pk = ktri->pkey; + if (recip) + *recip = ktri->recip; + if (palg) + *palg = ktri->keyEncryptionAlgorithm; + return 1; +} + +int CMS_RecipientInfo_ktri_get0_signer_id(CMS_RecipientInfo *ri, + ASN1_OCTET_STRING **keyid, + X509_NAME **issuer, + ASN1_INTEGER **sno) +{ + CMS_KeyTransRecipientInfo *ktri; + if (ri->type != CMS_RECIPINFO_TRANS) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID, + CMS_R_NOT_KEY_TRANSPORT); + return 0; + } + ktri = ri->d.ktri; + + return cms_SignerIdentifier_get0_signer_id(ktri->rid, keyid, issuer, sno); +} + +int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert) +{ + if (ri->type != CMS_RECIPINFO_TRANS) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP, + CMS_R_NOT_KEY_TRANSPORT); + return -2; + } + return cms_SignerIdentifier_cert_cmp(ri->d.ktri->rid, cert); +} + +int CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey) +{ + if (ri->type != CMS_RECIPINFO_TRANS) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_PKEY, CMS_R_NOT_KEY_TRANSPORT); + return 0; + } + EVP_PKEY_free(ri->d.ktri->pkey); + ri->d.ktri->pkey = pkey; + return 1; +} + +/* Encrypt content key in key transport recipient info */ + +static int cms_RecipientInfo_ktri_encrypt(CMS_ContentInfo *cms, + CMS_RecipientInfo *ri) +{ + CMS_KeyTransRecipientInfo *ktri; + CMS_EncryptedContentInfo *ec; + EVP_PKEY_CTX *pctx; + unsigned char *ek = NULL; + size_t eklen; + + int ret = 0; + + if (ri->type != CMS_RECIPINFO_TRANS) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, CMS_R_NOT_KEY_TRANSPORT); + return 0; + } + ktri = ri->d.ktri; + ec = cms->d.envelopedData->encryptedContentInfo; + + pctx = ktri->pctx; + + if (pctx) { + if (!cms_env_asn1_ctrl(ri, 0)) + goto err; + } else { + pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL); + if (pctx == NULL) + return 0; + + if (EVP_PKEY_encrypt_init(pctx) <= 0) + goto err; + } + + if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT, + EVP_PKEY_CTRL_CMS_ENCRYPT, 0, ri) <= 0) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, CMS_R_CTRL_ERROR); + goto err; + } + + if (EVP_PKEY_encrypt(pctx, NULL, &eklen, ec->key, ec->keylen) <= 0) + goto err; + + ek = OPENSSL_malloc(eklen); + + if (ek == NULL) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (EVP_PKEY_encrypt(pctx, ek, &eklen, ec->key, ec->keylen) <= 0) + goto err; + + ASN1_STRING_set0(ktri->encryptedKey, ek, eklen); + ek = NULL; + + ret = 1; + + err: + EVP_PKEY_CTX_free(pctx); + ktri->pctx = NULL; + OPENSSL_free(ek); + return ret; + +} + +/* Decrypt content key from KTRI */ + +static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms, + CMS_RecipientInfo *ri) +{ + CMS_KeyTransRecipientInfo *ktri = ri->d.ktri; + EVP_PKEY *pkey = ktri->pkey; + unsigned char *ek = NULL; + size_t eklen; + int ret = 0; + CMS_EncryptedContentInfo *ec; + ec = cms->d.envelopedData->encryptedContentInfo; + + if (ktri->pkey == NULL) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_NO_PRIVATE_KEY); + return 0; + } + + ktri->pctx = EVP_PKEY_CTX_new(pkey, NULL); + if (ktri->pctx == NULL) + return 0; + + if (EVP_PKEY_decrypt_init(ktri->pctx) <= 0) + goto err; + + if (!cms_env_asn1_ctrl(ri, 1)) + goto err; + + if (EVP_PKEY_CTX_ctrl(ktri->pctx, -1, EVP_PKEY_OP_DECRYPT, + EVP_PKEY_CTRL_CMS_DECRYPT, 0, ri) <= 0) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CTRL_ERROR); + goto err; + } + + if (EVP_PKEY_decrypt(ktri->pctx, NULL, &eklen, + ktri->encryptedKey->data, + ktri->encryptedKey->length) <= 0) + goto err; + + ek = OPENSSL_malloc(eklen); + + if (ek == NULL) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (EVP_PKEY_decrypt(ktri->pctx, ek, &eklen, + ktri->encryptedKey->data, + ktri->encryptedKey->length) <= 0) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CMS_LIB); + goto err; + } + + ret = 1; + + OPENSSL_clear_free(ec->key, ec->keylen); + ec->key = ek; + ec->keylen = eklen; + + err: + EVP_PKEY_CTX_free(ktri->pctx); + ktri->pctx = NULL; + if (!ret) + OPENSSL_free(ek); + + return ret; +} + +/* Key Encrypted Key (KEK) RecipientInfo routines */ + +int CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri, + const unsigned char *id, size_t idlen) +{ + ASN1_OCTET_STRING tmp_os; + CMS_KEKRecipientInfo *kekri; + if (ri->type != CMS_RECIPINFO_KEK) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP, CMS_R_NOT_KEK); + return -2; + } + kekri = ri->d.kekri; + tmp_os.type = V_ASN1_OCTET_STRING; + tmp_os.flags = 0; + tmp_os.data = (unsigned char *)id; + tmp_os.length = (int)idlen; + return ASN1_OCTET_STRING_cmp(&tmp_os, kekri->kekid->keyIdentifier); +} + +/* For now hard code AES key wrap info */ + +static size_t aes_wrap_keylen(int nid) +{ + switch (nid) { + case NID_id_aes128_wrap: + return 16; + + case NID_id_aes192_wrap: + return 24; + + case NID_id_aes256_wrap: + return 32; + + default: + return 0; + } +} + +CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid, + unsigned char *key, size_t keylen, + unsigned char *id, size_t idlen, + ASN1_GENERALIZEDTIME *date, + ASN1_OBJECT *otherTypeId, + ASN1_TYPE *otherType) +{ + CMS_RecipientInfo *ri = NULL; + CMS_EnvelopedData *env; + CMS_KEKRecipientInfo *kekri; + env = cms_get0_enveloped(cms); + if (!env) + goto err; + + if (nid == NID_undef) { + switch (keylen) { + case 16: + nid = NID_id_aes128_wrap; + break; + + case 24: + nid = NID_id_aes192_wrap; + break; + + case 32: + nid = NID_id_aes256_wrap; + break; + + default: + CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, CMS_R_INVALID_KEY_LENGTH); + goto err; + } + + } else { + + size_t exp_keylen = aes_wrap_keylen(nid); + + if (!exp_keylen) { + CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, + CMS_R_UNSUPPORTED_KEK_ALGORITHM); + goto err; + } + + if (keylen != exp_keylen) { + CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, CMS_R_INVALID_KEY_LENGTH); + goto err; + } + + } + + /* Initialize recipient info */ + ri = M_ASN1_new_of(CMS_RecipientInfo); + if (!ri) + goto merr; + + ri->d.kekri = M_ASN1_new_of(CMS_KEKRecipientInfo); + if (!ri->d.kekri) + goto merr; + ri->type = CMS_RECIPINFO_KEK; + + kekri = ri->d.kekri; + + if (otherTypeId) { + kekri->kekid->other = M_ASN1_new_of(CMS_OtherKeyAttribute); + if (kekri->kekid->other == NULL) + goto merr; + } + + if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri)) + goto merr; + + /* After this point no calls can fail */ + + kekri->version = 4; + + kekri->key = key; + kekri->keylen = keylen; + + ASN1_STRING_set0(kekri->kekid->keyIdentifier, id, idlen); + + kekri->kekid->date = date; + + if (kekri->kekid->other) { + kekri->kekid->other->keyAttrId = otherTypeId; + kekri->kekid->other->keyAttr = otherType; + } + + X509_ALGOR_set0(kekri->keyEncryptionAlgorithm, + OBJ_nid2obj(nid), V_ASN1_UNDEF, NULL); + + return ri; + + merr: + CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, ERR_R_MALLOC_FAILURE); + err: + M_ASN1_free_of(ri, CMS_RecipientInfo); + return NULL; + +} + +int CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri, + X509_ALGOR **palg, + ASN1_OCTET_STRING **pid, + ASN1_GENERALIZEDTIME **pdate, + ASN1_OBJECT **potherid, + ASN1_TYPE **pothertype) +{ + CMS_KEKIdentifier *rkid; + if (ri->type != CMS_RECIPINFO_KEK) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID, CMS_R_NOT_KEK); + return 0; + } + rkid = ri->d.kekri->kekid; + if (palg) + *palg = ri->d.kekri->keyEncryptionAlgorithm; + if (pid) + *pid = rkid->keyIdentifier; + if (pdate) + *pdate = rkid->date; + if (potherid) { + if (rkid->other) + *potherid = rkid->other->keyAttrId; + else + *potherid = NULL; + } + if (pothertype) { + if (rkid->other) + *pothertype = rkid->other->keyAttr; + else + *pothertype = NULL; + } + return 1; +} + +int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri, + unsigned char *key, size_t keylen) +{ + CMS_KEKRecipientInfo *kekri; + if (ri->type != CMS_RECIPINFO_KEK) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_KEY, CMS_R_NOT_KEK); + return 0; + } + + kekri = ri->d.kekri; + kekri->key = key; + kekri->keylen = keylen; + return 1; +} + +/* Encrypt content key in KEK recipient info */ + +static int cms_RecipientInfo_kekri_encrypt(CMS_ContentInfo *cms, + CMS_RecipientInfo *ri) +{ + CMS_EncryptedContentInfo *ec; + CMS_KEKRecipientInfo *kekri; + AES_KEY actx; + unsigned char *wkey = NULL; + int wkeylen; + int r = 0; + + ec = cms->d.envelopedData->encryptedContentInfo; + + kekri = ri->d.kekri; + + if (!kekri->key) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_NO_KEY); + return 0; + } + + if (AES_set_encrypt_key(kekri->key, kekri->keylen << 3, &actx)) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, + CMS_R_ERROR_SETTING_KEY); + goto err; + } + + wkey = OPENSSL_malloc(ec->keylen + 8); + + if (wkey == NULL) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto err; + } + + wkeylen = AES_wrap_key(&actx, NULL, wkey, ec->key, ec->keylen); + + if (wkeylen <= 0) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_WRAP_ERROR); + goto err; + } + + ASN1_STRING_set0(kekri->encryptedKey, wkey, wkeylen); + + r = 1; + + err: + + if (!r) + OPENSSL_free(wkey); + OPENSSL_cleanse(&actx, sizeof(actx)); + + return r; + +} + +/* Decrypt content key in KEK recipient info */ + +static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms, + CMS_RecipientInfo *ri) +{ + CMS_EncryptedContentInfo *ec; + CMS_KEKRecipientInfo *kekri; + AES_KEY actx; + unsigned char *ukey = NULL; + int ukeylen; + int r = 0, wrap_nid; + + ec = cms->d.envelopedData->encryptedContentInfo; + + kekri = ri->d.kekri; + + if (!kekri->key) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, CMS_R_NO_KEY); + return 0; + } + + wrap_nid = OBJ_obj2nid(kekri->keyEncryptionAlgorithm->algorithm); + if (aes_wrap_keylen(wrap_nid) != kekri->keylen) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, + CMS_R_INVALID_KEY_LENGTH); + return 0; + } + + /* If encrypted key length is invalid don't bother */ + + if (kekri->encryptedKey->length < 16) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, + CMS_R_INVALID_ENCRYPTED_KEY_LENGTH); + goto err; + } + + if (AES_set_decrypt_key(kekri->key, kekri->keylen << 3, &actx)) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, + CMS_R_ERROR_SETTING_KEY); + goto err; + } + + ukey = OPENSSL_malloc(kekri->encryptedKey->length - 8); + + if (ukey == NULL) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, ERR_R_MALLOC_FAILURE); + goto err; + } + + ukeylen = AES_unwrap_key(&actx, NULL, ukey, + kekri->encryptedKey->data, + kekri->encryptedKey->length); + + if (ukeylen <= 0) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, CMS_R_UNWRAP_ERROR); + goto err; + } + + ec->key = ukey; + ec->keylen = ukeylen; + + r = 1; + + err: + + if (!r) + OPENSSL_free(ukey); + OPENSSL_cleanse(&actx, sizeof(actx)); + + return r; + +} + +int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri) +{ + switch (ri->type) { + case CMS_RECIPINFO_TRANS: + return cms_RecipientInfo_ktri_decrypt(cms, ri); + + case CMS_RECIPINFO_KEK: + return cms_RecipientInfo_kekri_decrypt(cms, ri); + + case CMS_RECIPINFO_PASS: + return cms_RecipientInfo_pwri_crypt(cms, ri, 0); + + default: + CMSerr(CMS_F_CMS_RECIPIENTINFO_DECRYPT, + CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE); + return 0; + } +} + +int CMS_RecipientInfo_encrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri) +{ + switch (ri->type) { + case CMS_RECIPINFO_TRANS: + return cms_RecipientInfo_ktri_encrypt(cms, ri); + + case CMS_RECIPINFO_AGREE: + return cms_RecipientInfo_kari_encrypt(cms, ri); + + case CMS_RECIPINFO_KEK: + return cms_RecipientInfo_kekri_encrypt(cms, ri); + + case CMS_RECIPINFO_PASS: + return cms_RecipientInfo_pwri_crypt(cms, ri, 1); + + default: + CMSerr(CMS_F_CMS_RECIPIENTINFO_ENCRYPT, + CMS_R_UNSUPPORTED_RECIPIENT_TYPE); + return 0; + } +} + +/* Check structures and fixup version numbers (if necessary) */ + +static void cms_env_set_originfo_version(CMS_EnvelopedData *env) +{ + CMS_OriginatorInfo *org = env->originatorInfo; + int i; + if (org == NULL) + return; + for (i = 0; i < sk_CMS_CertificateChoices_num(org->certificates); i++) { + CMS_CertificateChoices *cch; + cch = sk_CMS_CertificateChoices_value(org->certificates, i); + if (cch->type == CMS_CERTCHOICE_OTHER) { + env->version = 4; + return; + } else if (cch->type == CMS_CERTCHOICE_V2ACERT) { + if (env->version < 3) + env->version = 3; + } + } + + for (i = 0; i < sk_CMS_RevocationInfoChoice_num(org->crls); i++) { + CMS_RevocationInfoChoice *rch; + rch = sk_CMS_RevocationInfoChoice_value(org->crls, i); + if (rch->type == CMS_REVCHOICE_OTHER) { + env->version = 4; + return; + } + } +} + +static void cms_env_set_version(CMS_EnvelopedData *env) +{ + int i; + CMS_RecipientInfo *ri; + + /* + * Can't set version higher than 4 so if 4 or more already nothing to do. + */ + if (env->version >= 4) + return; + + cms_env_set_originfo_version(env); + + if (env->version >= 3) + return; + + for (i = 0; i < sk_CMS_RecipientInfo_num(env->recipientInfos); i++) { + ri = sk_CMS_RecipientInfo_value(env->recipientInfos, i); + if (ri->type == CMS_RECIPINFO_PASS || ri->type == CMS_RECIPINFO_OTHER) { + env->version = 3; + return; + } else if (ri->type != CMS_RECIPINFO_TRANS + || ri->d.ktri->version != 0) { + env->version = 2; + } + } + if (env->originatorInfo || env->unprotectedAttrs) + env->version = 2; + if (env->version == 2) + return; + env->version = 0; +} + +BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms) +{ + CMS_EncryptedContentInfo *ec; + STACK_OF(CMS_RecipientInfo) *rinfos; + CMS_RecipientInfo *ri; + int i, ok = 0; + BIO *ret; + + /* Get BIO first to set up key */ + + ec = cms->d.envelopedData->encryptedContentInfo; + ret = cms_EncryptedContent_init_bio(ec); + + /* If error or no cipher end of processing */ + + if (!ret || !ec->cipher) + return ret; + + /* Now encrypt content key according to each RecipientInfo type */ + + rinfos = cms->d.envelopedData->recipientInfos; + + for (i = 0; i < sk_CMS_RecipientInfo_num(rinfos); i++) { + ri = sk_CMS_RecipientInfo_value(rinfos, i); + if (CMS_RecipientInfo_encrypt(cms, ri) <= 0) { + CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO, + CMS_R_ERROR_SETTING_RECIPIENTINFO); + goto err; + } + } + cms_env_set_version(cms->d.envelopedData); + + ok = 1; + + err: + ec->cipher = NULL; + OPENSSL_clear_free(ec->key, ec->keylen); + ec->key = NULL; + ec->keylen = 0; + if (ok) + return ret; + BIO_free(ret); + return NULL; + +} + +/* + * Get RecipientInfo type (if any) supported by a key (public or private). To + * retain compatibility with previous behaviour if the ctrl value isn't + * supported we assume key transport. + */ +int cms_pkey_get_ri_type(EVP_PKEY *pk) +{ + if (pk->ameth && pk->ameth->pkey_ctrl) { + int i, r; + i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_RI_TYPE, 0, &r); + if (i > 0) + return r; + } + return CMS_RECIPINFO_TRANS; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_err.c new file mode 100644 index 000000000..4432b471e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_err.c @@ -0,0 +1,294 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA CMS_str_functs[] = { + {ERR_PACK(ERR_LIB_CMS, CMS_F_CHECK_CONTENT, 0), "check_content"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ADD0_CERT, 0), "CMS_add0_cert"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ADD0_RECIPIENT_KEY, 0), + "CMS_add0_recipient_key"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, 0), + "CMS_add0_recipient_password"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ADD1_RECEIPTREQUEST, 0), + "CMS_add1_ReceiptRequest"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ADD1_RECIPIENT_CERT, 0), + "CMS_add1_recipient_cert"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ADD1_SIGNER, 0), "CMS_add1_signer"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ADD1_SIGNINGTIME, 0), + "cms_add1_signingTime"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_COMPRESS, 0), "CMS_compress"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_COMPRESSEDDATA_CREATE, 0), + "cms_CompressedData_create"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_COMPRESSEDDATA_INIT_BIO, 0), + "cms_CompressedData_init_bio"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_COPY_CONTENT, 0), "cms_copy_content"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_COPY_MESSAGEDIGEST, 0), + "cms_copy_messageDigest"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_DATA, 0), "CMS_data"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_DATAFINAL, 0), "CMS_dataFinal"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_DATAINIT, 0), "CMS_dataInit"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_DECRYPT, 0), "CMS_decrypt"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_DECRYPT_SET1_KEY, 0), + "CMS_decrypt_set1_key"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_DECRYPT_SET1_PASSWORD, 0), + "CMS_decrypt_set1_password"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_DECRYPT_SET1_PKEY, 0), + "CMS_decrypt_set1_pkey"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_DIGESTALGORITHM_FIND_CTX, 0), + "cms_DigestAlgorithm_find_ctx"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_DIGESTALGORITHM_INIT_BIO, 0), + "cms_DigestAlgorithm_init_bio"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_DIGESTEDDATA_DO_FINAL, 0), + "cms_DigestedData_do_final"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_DIGEST_VERIFY, 0), "CMS_digest_verify"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ENCODE_RECEIPT, 0), "cms_encode_Receipt"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ENCRYPT, 0), "CMS_encrypt"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ENCRYPTEDCONTENT_INIT, 0), + "cms_EncryptedContent_init"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, 0), + "cms_EncryptedContent_init_bio"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ENCRYPTEDDATA_DECRYPT, 0), + "CMS_EncryptedData_decrypt"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT, 0), + "CMS_EncryptedData_encrypt"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, 0), + "CMS_EncryptedData_set1_key"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ENVELOPEDDATA_CREATE, 0), + "CMS_EnvelopedData_create"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ENVELOPEDDATA_INIT_BIO, 0), + "cms_EnvelopedData_init_bio"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ENVELOPED_DATA_INIT, 0), + "cms_enveloped_data_init"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ENV_ASN1_CTRL, 0), "cms_env_asn1_ctrl"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_FINAL, 0), "CMS_final"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_GET0_CERTIFICATE_CHOICES, 0), + "cms_get0_certificate_choices"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_GET0_CONTENT, 0), "CMS_get0_content"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_GET0_ECONTENT_TYPE, 0), + "cms_get0_econtent_type"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_GET0_ENVELOPED, 0), "cms_get0_enveloped"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_GET0_REVOCATION_CHOICES, 0), + "cms_get0_revocation_choices"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_GET0_SIGNED, 0), "cms_get0_signed"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_MSGSIGDIGEST_ADD1, 0), + "cms_msgSigDigest_add1"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECEIPTREQUEST_CREATE0, 0), + "CMS_ReceiptRequest_create0"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECEIPT_VERIFY, 0), "cms_Receipt_verify"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_DECRYPT, 0), + "CMS_RecipientInfo_decrypt"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_ENCRYPT, 0), + "CMS_RecipientInfo_encrypt"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT, 0), + "cms_RecipientInfo_kari_encrypt"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ALG, 0), + "CMS_RecipientInfo_kari_get0_alg"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ORIG_ID, 0), + "CMS_RecipientInfo_kari_get0_orig_id"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_KARI_GET0_REKS, 0), + "CMS_RecipientInfo_kari_get0_reks"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_KARI_ORIG_ID_CMP, 0), + "CMS_RecipientInfo_kari_orig_id_cmp"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, 0), + "cms_RecipientInfo_kekri_decrypt"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, 0), + "cms_RecipientInfo_kekri_encrypt"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID, 0), + "CMS_RecipientInfo_kekri_get0_id"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP, 0), + "CMS_RecipientInfo_kekri_id_cmp"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP, 0), + "CMS_RecipientInfo_ktri_cert_cmp"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, 0), + "cms_RecipientInfo_ktri_decrypt"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, 0), + "cms_RecipientInfo_ktri_encrypt"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS, 0), + "CMS_RecipientInfo_ktri_get0_algs"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID, 0), + "CMS_RecipientInfo_ktri_get0_signer_id"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, 0), + "cms_RecipientInfo_pwri_crypt"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_SET0_KEY, 0), + "CMS_RecipientInfo_set0_key"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD, 0), + "CMS_RecipientInfo_set0_password"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_RECIPIENTINFO_SET0_PKEY, 0), + "CMS_RecipientInfo_set0_pkey"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_SD_ASN1_CTRL, 0), "cms_sd_asn1_ctrl"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_SET1_IAS, 0), "cms_set1_ias"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_SET1_KEYID, 0), "cms_set1_keyid"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_SET1_SIGNERIDENTIFIER, 0), + "cms_set1_SignerIdentifier"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_SET_DETACHED, 0), "CMS_set_detached"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_SIGN, 0), "CMS_sign"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_SIGNED_DATA_INIT, 0), + "cms_signed_data_init"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, 0), + "cms_SignerInfo_content_sign"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_SIGNERINFO_SIGN, 0), + "CMS_SignerInfo_sign"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_SIGNERINFO_VERIFY, 0), + "CMS_SignerInfo_verify"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_SIGNERINFO_VERIFY_CERT, 0), + "cms_signerinfo_verify_cert"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT, 0), + "CMS_SignerInfo_verify_content"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_SIGN_RECEIPT, 0), "CMS_sign_receipt"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_STREAM, 0), "CMS_stream"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_UNCOMPRESS, 0), "CMS_uncompress"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_VERIFY, 0), "CMS_verify"}, + {ERR_PACK(ERR_LIB_CMS, CMS_F_KEK_UNWRAP_KEY, 0), "kek_unwrap_key"}, + {0, NULL} +}; + +static const ERR_STRING_DATA CMS_str_reasons[] = { + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ADD_SIGNER_ERROR), "add signer error"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CERTIFICATE_ALREADY_PRESENT), + "certificate already present"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CERTIFICATE_HAS_NO_KEYID), + "certificate has no keyid"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CERTIFICATE_VERIFY_ERROR), + "certificate verify error"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CIPHER_INITIALISATION_ERROR), + "cipher initialisation error"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR), + "cipher parameter initialisation error"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CMS_DATAFINAL_ERROR), + "cms datafinal error"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CMS_LIB), "cms lib"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CONTENTIDENTIFIER_MISMATCH), + "contentidentifier mismatch"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CONTENT_NOT_FOUND), "content not found"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CONTENT_TYPE_MISMATCH), + "content type mismatch"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA), + "content type not compressed data"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA), + "content type not enveloped data"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA), + "content type not signed data"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CONTENT_VERIFY_ERROR), + "content verify error"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CTRL_ERROR), "ctrl error"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CTRL_FAILURE), "ctrl failure"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_DECRYPT_ERROR), "decrypt error"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ERROR_GETTING_PUBLIC_KEY), + "error getting public key"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE), + "error reading messagedigest attribute"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ERROR_SETTING_KEY), "error setting key"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ERROR_SETTING_RECIPIENTINFO), + "error setting recipientinfo"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_INVALID_ENCRYPTED_KEY_LENGTH), + "invalid encrypted key length"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER), + "invalid key encryption parameter"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_INVALID_KEY_LENGTH), "invalid key length"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_MD_BIO_INIT_ERROR), "md bio init error"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH), + "messagedigest attribute wrong length"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_MESSAGEDIGEST_WRONG_LENGTH), + "messagedigest wrong length"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_MSGSIGDIGEST_ERROR), "msgsigdigest error"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE), + "msgsigdigest verification failure"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_MSGSIGDIGEST_WRONG_LENGTH), + "msgsigdigest wrong length"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NEED_ONE_SIGNER), "need one signer"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NOT_A_SIGNED_RECEIPT), + "not a signed receipt"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NOT_ENCRYPTED_DATA), "not encrypted data"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NOT_KEK), "not kek"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NOT_KEY_AGREEMENT), "not key agreement"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NOT_KEY_TRANSPORT), "not key transport"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NOT_PWRI), "not pwri"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE), + "not supported for this key type"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_CIPHER), "no cipher"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_CONTENT), "no content"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_CONTENT_TYPE), "no content type"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_DEFAULT_DIGEST), "no default digest"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_DIGEST_SET), "no digest set"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_KEY), "no key"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_KEY_OR_CERT), "no key or cert"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_MATCHING_DIGEST), "no matching digest"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_MATCHING_RECIPIENT), + "no matching recipient"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_MATCHING_SIGNATURE), + "no matching signature"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_MSGSIGDIGEST), "no msgsigdigest"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_PASSWORD), "no password"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_PRIVATE_KEY), "no private key"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_PUBLIC_KEY), "no public key"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_RECEIPT_REQUEST), "no receipt request"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_SIGNERS), "no signers"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE), + "private key does not match certificate"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_RECEIPT_DECODE_ERROR), + "receipt decode error"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_RECIPIENT_ERROR), "recipient error"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_SIGNER_CERTIFICATE_NOT_FOUND), + "signer certificate not found"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_SIGNFINAL_ERROR), "signfinal error"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_SMIME_TEXT_ERROR), "smime text error"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_STORE_INIT_ERROR), "store init error"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_TYPE_NOT_COMPRESSED_DATA), + "type not compressed data"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_TYPE_NOT_DATA), "type not data"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_TYPE_NOT_DIGESTED_DATA), + "type not digested data"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_TYPE_NOT_ENCRYPTED_DATA), + "type not encrypted data"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_TYPE_NOT_ENVELOPED_DATA), + "type not enveloped data"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNABLE_TO_FINALIZE_CONTEXT), + "unable to finalize context"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNKNOWN_CIPHER), "unknown cipher"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNKNOWN_DIGEST_ALGORITHM), + "unknown digest algorithm"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNKNOWN_ID), "unknown id"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM), + "unsupported compression algorithm"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_CONTENT_TYPE), + "unsupported content type"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_KEK_ALGORITHM), + "unsupported kek algorithm"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM), + "unsupported key encryption algorithm"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE), + "unsupported recipientinfo type"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_RECIPIENT_TYPE), + "unsupported recipient type"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_TYPE), "unsupported type"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNWRAP_ERROR), "unwrap error"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNWRAP_FAILURE), "unwrap failure"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_VERIFICATION_FAILURE), + "verification failure"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_WRAP_ERROR), "wrap error"}, + {0, NULL} +}; + +#endif + +int ERR_load_CMS_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(CMS_str_functs[0].error) == NULL) { + ERR_load_strings_const(CMS_str_functs); + ERR_load_strings_const(CMS_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_ess.c b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_ess.c new file mode 100644 index 000000000..4780231c2 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_ess.c @@ -0,0 +1,337 @@ +/* + * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include +#include "cms_lcl.h" + +IMPLEMENT_ASN1_FUNCTIONS(CMS_ReceiptRequest) + +/* ESS services: for now just Signed Receipt related */ + +int CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr) +{ + ASN1_STRING *str; + CMS_ReceiptRequest *rr = NULL; + if (prr) + *prr = NULL; + str = CMS_signed_get0_data_by_OBJ(si, + OBJ_nid2obj + (NID_id_smime_aa_receiptRequest), -3, + V_ASN1_SEQUENCE); + if (!str) + return 0; + + rr = ASN1_item_unpack(str, ASN1_ITEM_rptr(CMS_ReceiptRequest)); + if (!rr) + return -1; + if (prr) + *prr = rr; + else + CMS_ReceiptRequest_free(rr); + return 1; +} + +CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen, + int allorfirst, + STACK_OF(GENERAL_NAMES) + *receiptList, STACK_OF(GENERAL_NAMES) + *receiptsTo) +{ + CMS_ReceiptRequest *rr = NULL; + + rr = CMS_ReceiptRequest_new(); + if (rr == NULL) + goto merr; + if (id) + ASN1_STRING_set0(rr->signedContentIdentifier, id, idlen); + else { + if (!ASN1_STRING_set(rr->signedContentIdentifier, NULL, 32)) + goto merr; + if (RAND_bytes(rr->signedContentIdentifier->data, 32) <= 0) + goto err; + } + + sk_GENERAL_NAMES_pop_free(rr->receiptsTo, GENERAL_NAMES_free); + rr->receiptsTo = receiptsTo; + + if (receiptList) { + rr->receiptsFrom->type = 1; + rr->receiptsFrom->d.receiptList = receiptList; + } else { + rr->receiptsFrom->type = 0; + rr->receiptsFrom->d.allOrFirstTier = allorfirst; + } + + return rr; + + merr: + CMSerr(CMS_F_CMS_RECEIPTREQUEST_CREATE0, ERR_R_MALLOC_FAILURE); + + err: + CMS_ReceiptRequest_free(rr); + return NULL; + +} + +int CMS_add1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest *rr) +{ + unsigned char *rrder = NULL; + int rrderlen, r = 0; + + rrderlen = i2d_CMS_ReceiptRequest(rr, &rrder); + if (rrderlen < 0) + goto merr; + + if (!CMS_signed_add1_attr_by_NID(si, NID_id_smime_aa_receiptRequest, + V_ASN1_SEQUENCE, rrder, rrderlen)) + goto merr; + + r = 1; + + merr: + if (!r) + CMSerr(CMS_F_CMS_ADD1_RECEIPTREQUEST, ERR_R_MALLOC_FAILURE); + + OPENSSL_free(rrder); + + return r; + +} + +void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr, + ASN1_STRING **pcid, + int *pallorfirst, + STACK_OF(GENERAL_NAMES) **plist, + STACK_OF(GENERAL_NAMES) **prto) +{ + if (pcid) + *pcid = rr->signedContentIdentifier; + if (rr->receiptsFrom->type == 0) { + if (pallorfirst) + *pallorfirst = (int)rr->receiptsFrom->d.allOrFirstTier; + if (plist) + *plist = NULL; + } else { + if (pallorfirst) + *pallorfirst = -1; + if (plist) + *plist = rr->receiptsFrom->d.receiptList; + } + if (prto) + *prto = rr->receiptsTo; +} + +/* Digest a SignerInfo structure for msgSigDigest attribute processing */ + +static int cms_msgSigDigest(CMS_SignerInfo *si, + unsigned char *dig, unsigned int *diglen) +{ + const EVP_MD *md; + md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm); + if (md == NULL) + return 0; + if (!ASN1_item_digest(ASN1_ITEM_rptr(CMS_Attributes_Verify), md, + si->signedAttrs, dig, diglen)) + return 0; + return 1; +} + +/* Add a msgSigDigest attribute to a SignerInfo */ + +int cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src) +{ + unsigned char dig[EVP_MAX_MD_SIZE]; + unsigned int diglen; + if (!cms_msgSigDigest(src, dig, &diglen)) { + CMSerr(CMS_F_CMS_MSGSIGDIGEST_ADD1, CMS_R_MSGSIGDIGEST_ERROR); + return 0; + } + if (!CMS_signed_add1_attr_by_NID(dest, NID_id_smime_aa_msgSigDigest, + V_ASN1_OCTET_STRING, dig, diglen)) { + CMSerr(CMS_F_CMS_MSGSIGDIGEST_ADD1, ERR_R_MALLOC_FAILURE); + return 0; + } + return 1; +} + +/* Verify signed receipt after it has already passed normal CMS verify */ + +int cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms) +{ + int r = 0, i; + CMS_ReceiptRequest *rr = NULL; + CMS_Receipt *rct = NULL; + STACK_OF(CMS_SignerInfo) *sis, *osis; + CMS_SignerInfo *si, *osi = NULL; + ASN1_OCTET_STRING *msig, **pcont; + ASN1_OBJECT *octype; + unsigned char dig[EVP_MAX_MD_SIZE]; + unsigned int diglen; + + /* Get SignerInfos, also checks SignedData content type */ + osis = CMS_get0_SignerInfos(req_cms); + sis = CMS_get0_SignerInfos(cms); + if (!osis || !sis) + goto err; + + if (sk_CMS_SignerInfo_num(sis) != 1) { + CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NEED_ONE_SIGNER); + goto err; + } + + /* Check receipt content type */ + if (OBJ_obj2nid(CMS_get0_eContentType(cms)) != NID_id_smime_ct_receipt) { + CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NOT_A_SIGNED_RECEIPT); + goto err; + } + + /* Extract and decode receipt content */ + pcont = CMS_get0_content(cms); + if (!pcont || !*pcont) { + CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_CONTENT); + goto err; + } + + rct = ASN1_item_unpack(*pcont, ASN1_ITEM_rptr(CMS_Receipt)); + + if (!rct) { + CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_RECEIPT_DECODE_ERROR); + goto err; + } + + /* Locate original request */ + + for (i = 0; i < sk_CMS_SignerInfo_num(osis); i++) { + osi = sk_CMS_SignerInfo_value(osis, i); + if (!ASN1_STRING_cmp(osi->signature, rct->originatorSignatureValue)) + break; + } + + if (i == sk_CMS_SignerInfo_num(osis)) { + CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_MATCHING_SIGNATURE); + goto err; + } + + si = sk_CMS_SignerInfo_value(sis, 0); + + /* Get msgSigDigest value and compare */ + + msig = CMS_signed_get0_data_by_OBJ(si, + OBJ_nid2obj + (NID_id_smime_aa_msgSigDigest), -3, + V_ASN1_OCTET_STRING); + + if (!msig) { + CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_MSGSIGDIGEST); + goto err; + } + + if (!cms_msgSigDigest(osi, dig, &diglen)) { + CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_MSGSIGDIGEST_ERROR); + goto err; + } + + if (diglen != (unsigned int)msig->length) { + CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_MSGSIGDIGEST_WRONG_LENGTH); + goto err; + } + + if (memcmp(dig, msig->data, diglen)) { + CMSerr(CMS_F_CMS_RECEIPT_VERIFY, + CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE); + goto err; + } + + /* Compare content types */ + + octype = CMS_signed_get0_data_by_OBJ(osi, + OBJ_nid2obj(NID_pkcs9_contentType), + -3, V_ASN1_OBJECT); + if (!octype) { + CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_CONTENT_TYPE); + goto err; + } + + /* Compare details in receipt request */ + + if (OBJ_cmp(octype, rct->contentType)) { + CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_CONTENT_TYPE_MISMATCH); + goto err; + } + + /* Get original receipt request details */ + + if (CMS_get1_ReceiptRequest(osi, &rr) <= 0) { + CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_NO_RECEIPT_REQUEST); + goto err; + } + + if (ASN1_STRING_cmp(rr->signedContentIdentifier, + rct->signedContentIdentifier)) { + CMSerr(CMS_F_CMS_RECEIPT_VERIFY, CMS_R_CONTENTIDENTIFIER_MISMATCH); + goto err; + } + + r = 1; + + err: + CMS_ReceiptRequest_free(rr); + M_ASN1_free_of(rct, CMS_Receipt); + return r; + +} + +/* + * Encode a Receipt into an OCTET STRING read for including into content of a + * SignedData ContentInfo. + */ + +ASN1_OCTET_STRING *cms_encode_Receipt(CMS_SignerInfo *si) +{ + CMS_Receipt rct; + CMS_ReceiptRequest *rr = NULL; + ASN1_OBJECT *ctype; + ASN1_OCTET_STRING *os = NULL; + + /* Get original receipt request */ + + /* Get original receipt request details */ + + if (CMS_get1_ReceiptRequest(si, &rr) <= 0) { + CMSerr(CMS_F_CMS_ENCODE_RECEIPT, CMS_R_NO_RECEIPT_REQUEST); + goto err; + } + + /* Get original content type */ + + ctype = CMS_signed_get0_data_by_OBJ(si, + OBJ_nid2obj(NID_pkcs9_contentType), + -3, V_ASN1_OBJECT); + if (!ctype) { + CMSerr(CMS_F_CMS_ENCODE_RECEIPT, CMS_R_NO_CONTENT_TYPE); + goto err; + } + + rct.version = 1; + rct.contentType = ctype; + rct.signedContentIdentifier = rr->signedContentIdentifier; + rct.originatorSignatureValue = si->signature; + + os = ASN1_item_pack(&rct, ASN1_ITEM_rptr(CMS_Receipt), NULL); + + err: + CMS_ReceiptRequest_free(rr); + return os; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_io.c b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_io.c new file mode 100644 index 000000000..d18f980a9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_io.c @@ -0,0 +1,88 @@ +/* + * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include "cms_lcl.h" + +int CMS_stream(unsigned char ***boundary, CMS_ContentInfo *cms) +{ + ASN1_OCTET_STRING **pos; + pos = CMS_get0_content(cms); + if (pos == NULL) + return 0; + if (*pos == NULL) + *pos = ASN1_OCTET_STRING_new(); + if (*pos != NULL) { + (*pos)->flags |= ASN1_STRING_FLAG_NDEF; + (*pos)->flags &= ~ASN1_STRING_FLAG_CONT; + *boundary = &(*pos)->data; + return 1; + } + CMSerr(CMS_F_CMS_STREAM, ERR_R_MALLOC_FAILURE); + return 0; +} + +CMS_ContentInfo *d2i_CMS_bio(BIO *bp, CMS_ContentInfo **cms) +{ + return ASN1_item_d2i_bio(ASN1_ITEM_rptr(CMS_ContentInfo), bp, cms); +} + +int i2d_CMS_bio(BIO *bp, CMS_ContentInfo *cms) +{ + return ASN1_item_i2d_bio(ASN1_ITEM_rptr(CMS_ContentInfo), bp, cms); +} + +IMPLEMENT_PEM_rw_const(CMS, CMS_ContentInfo, PEM_STRING_CMS, CMS_ContentInfo) + +BIO *BIO_new_CMS(BIO *out, CMS_ContentInfo *cms) +{ + return BIO_new_NDEF(out, (ASN1_VALUE *)cms, + ASN1_ITEM_rptr(CMS_ContentInfo)); +} + +/* CMS wrappers round generalised stream and MIME routines */ + +int i2d_CMS_bio_stream(BIO *out, CMS_ContentInfo *cms, BIO *in, int flags) +{ + return i2d_ASN1_bio_stream(out, (ASN1_VALUE *)cms, in, flags, + ASN1_ITEM_rptr(CMS_ContentInfo)); +} + +int PEM_write_bio_CMS_stream(BIO *out, CMS_ContentInfo *cms, BIO *in, + int flags) +{ + return PEM_write_bio_ASN1_stream(out, (ASN1_VALUE *)cms, in, flags, + "CMS", ASN1_ITEM_rptr(CMS_ContentInfo)); +} + +int SMIME_write_CMS(BIO *bio, CMS_ContentInfo *cms, BIO *data, int flags) +{ + STACK_OF(X509_ALGOR) *mdalgs; + int ctype_nid = OBJ_obj2nid(cms->contentType); + int econt_nid = OBJ_obj2nid(CMS_get0_eContentType(cms)); + if (ctype_nid == NID_pkcs7_signed) + mdalgs = cms->d.signedData->digestAlgorithms; + else + mdalgs = NULL; + + return SMIME_write_ASN1(bio, (ASN1_VALUE *)cms, data, flags, + ctype_nid, econt_nid, mdalgs, + ASN1_ITEM_rptr(CMS_ContentInfo)); +} + +CMS_ContentInfo *SMIME_read_CMS(BIO *bio, BIO **bcont) +{ + return (CMS_ContentInfo *)SMIME_read_ASN1(bio, bcont, + ASN1_ITEM_rptr + (CMS_ContentInfo)); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_kari.c b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_kari.c new file mode 100644 index 000000000..5e83814d0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_kari.c @@ -0,0 +1,414 @@ +/* + * Copyright 2013-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include +#include "cms_lcl.h" +#include "internal/asn1_int.h" + +/* Key Agreement Recipient Info (KARI) routines */ + +int CMS_RecipientInfo_kari_get0_alg(CMS_RecipientInfo *ri, + X509_ALGOR **palg, + ASN1_OCTET_STRING **pukm) +{ + if (ri->type != CMS_RECIPINFO_AGREE) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ALG, + CMS_R_NOT_KEY_AGREEMENT); + return 0; + } + if (palg) + *palg = ri->d.kari->keyEncryptionAlgorithm; + if (pukm) + *pukm = ri->d.kari->ukm; + return 1; +} + +/* Retrieve recipient encrypted keys from a kari */ + +STACK_OF(CMS_RecipientEncryptedKey) +*CMS_RecipientInfo_kari_get0_reks(CMS_RecipientInfo *ri) +{ + if (ri->type != CMS_RECIPINFO_AGREE) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_GET0_REKS, + CMS_R_NOT_KEY_AGREEMENT); + return NULL; + } + return ri->d.kari->recipientEncryptedKeys; +} + +int CMS_RecipientInfo_kari_get0_orig_id(CMS_RecipientInfo *ri, + X509_ALGOR **pubalg, + ASN1_BIT_STRING **pubkey, + ASN1_OCTET_STRING **keyid, + X509_NAME **issuer, + ASN1_INTEGER **sno) +{ + CMS_OriginatorIdentifierOrKey *oik; + if (ri->type != CMS_RECIPINFO_AGREE) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ORIG_ID, + CMS_R_NOT_KEY_AGREEMENT); + return 0; + } + oik = ri->d.kari->originator; + if (issuer) + *issuer = NULL; + if (sno) + *sno = NULL; + if (keyid) + *keyid = NULL; + if (pubalg) + *pubalg = NULL; + if (pubkey) + *pubkey = NULL; + if (oik->type == CMS_OIK_ISSUER_SERIAL) { + if (issuer) + *issuer = oik->d.issuerAndSerialNumber->issuer; + if (sno) + *sno = oik->d.issuerAndSerialNumber->serialNumber; + } else if (oik->type == CMS_OIK_KEYIDENTIFIER) { + if (keyid) + *keyid = oik->d.subjectKeyIdentifier; + } else if (oik->type == CMS_OIK_PUBKEY) { + if (pubalg) + *pubalg = oik->d.originatorKey->algorithm; + if (pubkey) + *pubkey = oik->d.originatorKey->publicKey; + } else + return 0; + return 1; +} + +int CMS_RecipientInfo_kari_orig_id_cmp(CMS_RecipientInfo *ri, X509 *cert) +{ + CMS_OriginatorIdentifierOrKey *oik; + if (ri->type != CMS_RECIPINFO_AGREE) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_ORIG_ID_CMP, + CMS_R_NOT_KEY_AGREEMENT); + return -2; + } + oik = ri->d.kari->originator; + if (oik->type == CMS_OIK_ISSUER_SERIAL) + return cms_ias_cert_cmp(oik->d.issuerAndSerialNumber, cert); + else if (oik->type == CMS_OIK_KEYIDENTIFIER) + return cms_keyid_cert_cmp(oik->d.subjectKeyIdentifier, cert); + return -1; +} + +int CMS_RecipientEncryptedKey_get0_id(CMS_RecipientEncryptedKey *rek, + ASN1_OCTET_STRING **keyid, + ASN1_GENERALIZEDTIME **tm, + CMS_OtherKeyAttribute **other, + X509_NAME **issuer, ASN1_INTEGER **sno) +{ + CMS_KeyAgreeRecipientIdentifier *rid = rek->rid; + if (rid->type == CMS_REK_ISSUER_SERIAL) { + if (issuer) + *issuer = rid->d.issuerAndSerialNumber->issuer; + if (sno) + *sno = rid->d.issuerAndSerialNumber->serialNumber; + if (keyid) + *keyid = NULL; + if (tm) + *tm = NULL; + if (other) + *other = NULL; + } else if (rid->type == CMS_REK_KEYIDENTIFIER) { + if (keyid) + *keyid = rid->d.rKeyId->subjectKeyIdentifier; + if (tm) + *tm = rid->d.rKeyId->date; + if (other) + *other = rid->d.rKeyId->other; + if (issuer) + *issuer = NULL; + if (sno) + *sno = NULL; + } else + return 0; + return 1; +} + +int CMS_RecipientEncryptedKey_cert_cmp(CMS_RecipientEncryptedKey *rek, + X509 *cert) +{ + CMS_KeyAgreeRecipientIdentifier *rid = rek->rid; + if (rid->type == CMS_REK_ISSUER_SERIAL) + return cms_ias_cert_cmp(rid->d.issuerAndSerialNumber, cert); + else if (rid->type == CMS_REK_KEYIDENTIFIER) + return cms_keyid_cert_cmp(rid->d.rKeyId->subjectKeyIdentifier, cert); + else + return -1; +} + +int CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk) +{ + EVP_PKEY_CTX *pctx; + CMS_KeyAgreeRecipientInfo *kari = ri->d.kari; + + EVP_PKEY_CTX_free(kari->pctx); + kari->pctx = NULL; + if (!pk) + return 1; + pctx = EVP_PKEY_CTX_new(pk, NULL); + if (!pctx || !EVP_PKEY_derive_init(pctx)) + goto err; + kari->pctx = pctx; + return 1; + err: + EVP_PKEY_CTX_free(pctx); + return 0; +} + +EVP_CIPHER_CTX *CMS_RecipientInfo_kari_get0_ctx(CMS_RecipientInfo *ri) +{ + if (ri->type == CMS_RECIPINFO_AGREE) + return ri->d.kari->ctx; + return NULL; +} + +/* + * Derive KEK and decrypt/encrypt with it to produce either the original CEK + * or the encrypted CEK. + */ + +static int cms_kek_cipher(unsigned char **pout, size_t *poutlen, + const unsigned char *in, size_t inlen, + CMS_KeyAgreeRecipientInfo *kari, int enc) +{ + /* Key encryption key */ + unsigned char kek[EVP_MAX_KEY_LENGTH]; + size_t keklen; + int rv = 0; + unsigned char *out = NULL; + int outlen; + keklen = EVP_CIPHER_CTX_key_length(kari->ctx); + if (keklen > EVP_MAX_KEY_LENGTH) + return 0; + /* Derive KEK */ + if (EVP_PKEY_derive(kari->pctx, kek, &keklen) <= 0) + goto err; + /* Set KEK in context */ + if (!EVP_CipherInit_ex(kari->ctx, NULL, NULL, kek, NULL, enc)) + goto err; + /* obtain output length of ciphered key */ + if (!EVP_CipherUpdate(kari->ctx, NULL, &outlen, in, inlen)) + goto err; + out = OPENSSL_malloc(outlen); + if (out == NULL) + goto err; + if (!EVP_CipherUpdate(kari->ctx, out, &outlen, in, inlen)) + goto err; + *pout = out; + *poutlen = (size_t)outlen; + rv = 1; + + err: + OPENSSL_cleanse(kek, keklen); + if (!rv) + OPENSSL_free(out); + EVP_CIPHER_CTX_reset(kari->ctx); + /* FIXME: WHY IS kari->pctx freed here? /RL */ + EVP_PKEY_CTX_free(kari->pctx); + kari->pctx = NULL; + return rv; +} + +int CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo *cms, + CMS_RecipientInfo *ri, + CMS_RecipientEncryptedKey *rek) +{ + int rv = 0; + unsigned char *enckey = NULL, *cek = NULL; + size_t enckeylen; + size_t ceklen; + CMS_EncryptedContentInfo *ec; + enckeylen = rek->encryptedKey->length; + enckey = rek->encryptedKey->data; + /* Setup all parameters to derive KEK */ + if (!cms_env_asn1_ctrl(ri, 1)) + goto err; + /* Attempt to decrypt CEK */ + if (!cms_kek_cipher(&cek, &ceklen, enckey, enckeylen, ri->d.kari, 0)) + goto err; + ec = cms->d.envelopedData->encryptedContentInfo; + OPENSSL_clear_free(ec->key, ec->keylen); + ec->key = cek; + ec->keylen = ceklen; + cek = NULL; + rv = 1; + err: + OPENSSL_free(cek); + return rv; +} + +/* Create ephemeral key and initialise context based on it */ +static int cms_kari_create_ephemeral_key(CMS_KeyAgreeRecipientInfo *kari, + EVP_PKEY *pk) +{ + EVP_PKEY_CTX *pctx = NULL; + EVP_PKEY *ekey = NULL; + int rv = 0; + pctx = EVP_PKEY_CTX_new(pk, NULL); + if (!pctx) + goto err; + if (EVP_PKEY_keygen_init(pctx) <= 0) + goto err; + if (EVP_PKEY_keygen(pctx, &ekey) <= 0) + goto err; + EVP_PKEY_CTX_free(pctx); + pctx = EVP_PKEY_CTX_new(ekey, NULL); + if (!pctx) + goto err; + if (EVP_PKEY_derive_init(pctx) <= 0) + goto err; + kari->pctx = pctx; + rv = 1; + err: + if (!rv) + EVP_PKEY_CTX_free(pctx); + EVP_PKEY_free(ekey); + return rv; +} + +/* Initialise a kari based on passed certificate and key */ + +int cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip, + EVP_PKEY *pk, unsigned int flags) +{ + CMS_KeyAgreeRecipientInfo *kari; + CMS_RecipientEncryptedKey *rek = NULL; + + ri->d.kari = M_ASN1_new_of(CMS_KeyAgreeRecipientInfo); + if (!ri->d.kari) + return 0; + ri->type = CMS_RECIPINFO_AGREE; + + kari = ri->d.kari; + kari->version = 3; + + rek = M_ASN1_new_of(CMS_RecipientEncryptedKey); + if (rek == NULL) + return 0; + + if (!sk_CMS_RecipientEncryptedKey_push(kari->recipientEncryptedKeys, rek)) { + M_ASN1_free_of(rek, CMS_RecipientEncryptedKey); + return 0; + } + + if (flags & CMS_USE_KEYID) { + rek->rid->type = CMS_REK_KEYIDENTIFIER; + rek->rid->d.rKeyId = M_ASN1_new_of(CMS_RecipientKeyIdentifier); + if (rek->rid->d.rKeyId == NULL) + return 0; + if (!cms_set1_keyid(&rek->rid->d.rKeyId->subjectKeyIdentifier, recip)) + return 0; + } else { + rek->rid->type = CMS_REK_ISSUER_SERIAL; + if (!cms_set1_ias(&rek->rid->d.issuerAndSerialNumber, recip)) + return 0; + } + + /* Create ephemeral key */ + if (!cms_kari_create_ephemeral_key(kari, pk)) + return 0; + + EVP_PKEY_up_ref(pk); + rek->pkey = pk; + return 1; +} + +static int cms_wrap_init(CMS_KeyAgreeRecipientInfo *kari, + const EVP_CIPHER *cipher) +{ + EVP_CIPHER_CTX *ctx = kari->ctx; + const EVP_CIPHER *kekcipher; + int keylen = EVP_CIPHER_key_length(cipher); + /* If a suitable wrap algorithm is already set nothing to do */ + kekcipher = EVP_CIPHER_CTX_cipher(ctx); + + if (kekcipher) { + if (EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_WRAP_MODE) + return 0; + return 1; + } + /* + * Pick a cipher based on content encryption cipher. If it is DES3 use + * DES3 wrap otherwise use AES wrap similar to key size. + */ +#ifndef OPENSSL_NO_DES + if (EVP_CIPHER_type(cipher) == NID_des_ede3_cbc) + kekcipher = EVP_des_ede3_wrap(); + else +#endif + if (keylen <= 16) + kekcipher = EVP_aes_128_wrap(); + else if (keylen <= 24) + kekcipher = EVP_aes_192_wrap(); + else + kekcipher = EVP_aes_256_wrap(); + return EVP_EncryptInit_ex(ctx, kekcipher, NULL, NULL, NULL); +} + +/* Encrypt content key in key agreement recipient info */ + +int cms_RecipientInfo_kari_encrypt(CMS_ContentInfo *cms, + CMS_RecipientInfo *ri) +{ + CMS_KeyAgreeRecipientInfo *kari; + CMS_EncryptedContentInfo *ec; + CMS_RecipientEncryptedKey *rek; + STACK_OF(CMS_RecipientEncryptedKey) *reks; + int i; + + if (ri->type != CMS_RECIPINFO_AGREE) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT, CMS_R_NOT_KEY_AGREEMENT); + return 0; + } + kari = ri->d.kari; + reks = kari->recipientEncryptedKeys; + ec = cms->d.envelopedData->encryptedContentInfo; + /* Initialise wrap algorithm parameters */ + if (!cms_wrap_init(kari, ec->cipher)) + return 0; + /* + * If no originator key set up initialise for ephemeral key the public key + * ASN1 structure will set the actual public key value. + */ + if (kari->originator->type == -1) { + CMS_OriginatorIdentifierOrKey *oik = kari->originator; + oik->type = CMS_OIK_PUBKEY; + oik->d.originatorKey = M_ASN1_new_of(CMS_OriginatorPublicKey); + if (!oik->d.originatorKey) + return 0; + } + /* Initialise KDF algorithm */ + if (!cms_env_asn1_ctrl(ri, 0)) + return 0; + /* For each rek, derive KEK, encrypt CEK */ + for (i = 0; i < sk_CMS_RecipientEncryptedKey_num(reks); i++) { + unsigned char *enckey; + size_t enckeylen; + rek = sk_CMS_RecipientEncryptedKey_value(reks, i); + if (EVP_PKEY_derive_set_peer(kari->pctx, rek->pkey) <= 0) + return 0; + if (!cms_kek_cipher(&enckey, &enckeylen, ec->key, ec->keylen, + kari, 1)) + return 0; + ASN1_STRING_set0(rek->encryptedKey, enckey, enckeylen); + } + + return 1; + +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_lcl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_lcl.h new file mode 100644 index 000000000..916fcbfbe --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_lcl.h @@ -0,0 +1,437 @@ +/* + * Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_CMS_LCL_H +# define HEADER_CMS_LCL_H + +# include + +/* + * Cryptographic message syntax (CMS) structures: taken from RFC3852 + */ + +/* Forward references */ + +typedef struct CMS_IssuerAndSerialNumber_st CMS_IssuerAndSerialNumber; +typedef struct CMS_EncapsulatedContentInfo_st CMS_EncapsulatedContentInfo; +typedef struct CMS_SignerIdentifier_st CMS_SignerIdentifier; +typedef struct CMS_SignedData_st CMS_SignedData; +typedef struct CMS_OtherRevocationInfoFormat_st CMS_OtherRevocationInfoFormat; +typedef struct CMS_OriginatorInfo_st CMS_OriginatorInfo; +typedef struct CMS_EncryptedContentInfo_st CMS_EncryptedContentInfo; +typedef struct CMS_EnvelopedData_st CMS_EnvelopedData; +typedef struct CMS_DigestedData_st CMS_DigestedData; +typedef struct CMS_EncryptedData_st CMS_EncryptedData; +typedef struct CMS_AuthenticatedData_st CMS_AuthenticatedData; +typedef struct CMS_CompressedData_st CMS_CompressedData; +typedef struct CMS_OtherCertificateFormat_st CMS_OtherCertificateFormat; +typedef struct CMS_KeyTransRecipientInfo_st CMS_KeyTransRecipientInfo; +typedef struct CMS_OriginatorPublicKey_st CMS_OriginatorPublicKey; +typedef struct CMS_OriginatorIdentifierOrKey_st CMS_OriginatorIdentifierOrKey; +typedef struct CMS_KeyAgreeRecipientInfo_st CMS_KeyAgreeRecipientInfo; +typedef struct CMS_RecipientKeyIdentifier_st CMS_RecipientKeyIdentifier; +typedef struct CMS_KeyAgreeRecipientIdentifier_st + CMS_KeyAgreeRecipientIdentifier; +typedef struct CMS_KEKIdentifier_st CMS_KEKIdentifier; +typedef struct CMS_KEKRecipientInfo_st CMS_KEKRecipientInfo; +typedef struct CMS_PasswordRecipientInfo_st CMS_PasswordRecipientInfo; +typedef struct CMS_OtherRecipientInfo_st CMS_OtherRecipientInfo; +typedef struct CMS_ReceiptsFrom_st CMS_ReceiptsFrom; + +struct CMS_ContentInfo_st { + ASN1_OBJECT *contentType; + union { + ASN1_OCTET_STRING *data; + CMS_SignedData *signedData; + CMS_EnvelopedData *envelopedData; + CMS_DigestedData *digestedData; + CMS_EncryptedData *encryptedData; + CMS_AuthenticatedData *authenticatedData; + CMS_CompressedData *compressedData; + ASN1_TYPE *other; + /* Other types ... */ + void *otherData; + } d; +}; + +DEFINE_STACK_OF(CMS_CertificateChoices) + +struct CMS_SignedData_st { + int32_t version; + STACK_OF(X509_ALGOR) *digestAlgorithms; + CMS_EncapsulatedContentInfo *encapContentInfo; + STACK_OF(CMS_CertificateChoices) *certificates; + STACK_OF(CMS_RevocationInfoChoice) *crls; + STACK_OF(CMS_SignerInfo) *signerInfos; +}; + +struct CMS_EncapsulatedContentInfo_st { + ASN1_OBJECT *eContentType; + ASN1_OCTET_STRING *eContent; + /* Set to 1 if incomplete structure only part set up */ + int partial; +}; + +struct CMS_SignerInfo_st { + int32_t version; + CMS_SignerIdentifier *sid; + X509_ALGOR *digestAlgorithm; + STACK_OF(X509_ATTRIBUTE) *signedAttrs; + X509_ALGOR *signatureAlgorithm; + ASN1_OCTET_STRING *signature; + STACK_OF(X509_ATTRIBUTE) *unsignedAttrs; + /* Signing certificate and key */ + X509 *signer; + EVP_PKEY *pkey; + /* Digest and public key context for alternative parameters */ + EVP_MD_CTX *mctx; + EVP_PKEY_CTX *pctx; +}; + +struct CMS_SignerIdentifier_st { + int type; + union { + CMS_IssuerAndSerialNumber *issuerAndSerialNumber; + ASN1_OCTET_STRING *subjectKeyIdentifier; + } d; +}; + +struct CMS_EnvelopedData_st { + int32_t version; + CMS_OriginatorInfo *originatorInfo; + STACK_OF(CMS_RecipientInfo) *recipientInfos; + CMS_EncryptedContentInfo *encryptedContentInfo; + STACK_OF(X509_ATTRIBUTE) *unprotectedAttrs; +}; + +struct CMS_OriginatorInfo_st { + STACK_OF(CMS_CertificateChoices) *certificates; + STACK_OF(CMS_RevocationInfoChoice) *crls; +}; + +struct CMS_EncryptedContentInfo_st { + ASN1_OBJECT *contentType; + X509_ALGOR *contentEncryptionAlgorithm; + ASN1_OCTET_STRING *encryptedContent; + /* Content encryption algorithm and key */ + const EVP_CIPHER *cipher; + unsigned char *key; + size_t keylen; + /* Set to 1 if we are debugging decrypt and don't fake keys for MMA */ + int debug; +}; + +struct CMS_RecipientInfo_st { + int type; + union { + CMS_KeyTransRecipientInfo *ktri; + CMS_KeyAgreeRecipientInfo *kari; + CMS_KEKRecipientInfo *kekri; + CMS_PasswordRecipientInfo *pwri; + CMS_OtherRecipientInfo *ori; + } d; +}; + +typedef CMS_SignerIdentifier CMS_RecipientIdentifier; + +struct CMS_KeyTransRecipientInfo_st { + int32_t version; + CMS_RecipientIdentifier *rid; + X509_ALGOR *keyEncryptionAlgorithm; + ASN1_OCTET_STRING *encryptedKey; + /* Recipient Key and cert */ + X509 *recip; + EVP_PKEY *pkey; + /* Public key context for this operation */ + EVP_PKEY_CTX *pctx; +}; + +struct CMS_KeyAgreeRecipientInfo_st { + int32_t version; + CMS_OriginatorIdentifierOrKey *originator; + ASN1_OCTET_STRING *ukm; + X509_ALGOR *keyEncryptionAlgorithm; + STACK_OF(CMS_RecipientEncryptedKey) *recipientEncryptedKeys; + /* Public key context associated with current operation */ + EVP_PKEY_CTX *pctx; + /* Cipher context for CEK wrapping */ + EVP_CIPHER_CTX *ctx; +}; + +struct CMS_OriginatorIdentifierOrKey_st { + int type; + union { + CMS_IssuerAndSerialNumber *issuerAndSerialNumber; + ASN1_OCTET_STRING *subjectKeyIdentifier; + CMS_OriginatorPublicKey *originatorKey; + } d; +}; + +struct CMS_OriginatorPublicKey_st { + X509_ALGOR *algorithm; + ASN1_BIT_STRING *publicKey; +}; + +struct CMS_RecipientEncryptedKey_st { + CMS_KeyAgreeRecipientIdentifier *rid; + ASN1_OCTET_STRING *encryptedKey; + /* Public key associated with this recipient */ + EVP_PKEY *pkey; +}; + +struct CMS_KeyAgreeRecipientIdentifier_st { + int type; + union { + CMS_IssuerAndSerialNumber *issuerAndSerialNumber; + CMS_RecipientKeyIdentifier *rKeyId; + } d; +}; + +struct CMS_RecipientKeyIdentifier_st { + ASN1_OCTET_STRING *subjectKeyIdentifier; + ASN1_GENERALIZEDTIME *date; + CMS_OtherKeyAttribute *other; +}; + +struct CMS_KEKRecipientInfo_st { + int32_t version; + CMS_KEKIdentifier *kekid; + X509_ALGOR *keyEncryptionAlgorithm; + ASN1_OCTET_STRING *encryptedKey; + /* Extra info: symmetric key to use */ + unsigned char *key; + size_t keylen; +}; + +struct CMS_KEKIdentifier_st { + ASN1_OCTET_STRING *keyIdentifier; + ASN1_GENERALIZEDTIME *date; + CMS_OtherKeyAttribute *other; +}; + +struct CMS_PasswordRecipientInfo_st { + int32_t version; + X509_ALGOR *keyDerivationAlgorithm; + X509_ALGOR *keyEncryptionAlgorithm; + ASN1_OCTET_STRING *encryptedKey; + /* Extra info: password to use */ + unsigned char *pass; + size_t passlen; +}; + +struct CMS_OtherRecipientInfo_st { + ASN1_OBJECT *oriType; + ASN1_TYPE *oriValue; +}; + +struct CMS_DigestedData_st { + int32_t version; + X509_ALGOR *digestAlgorithm; + CMS_EncapsulatedContentInfo *encapContentInfo; + ASN1_OCTET_STRING *digest; +}; + +struct CMS_EncryptedData_st { + int32_t version; + CMS_EncryptedContentInfo *encryptedContentInfo; + STACK_OF(X509_ATTRIBUTE) *unprotectedAttrs; +}; + +struct CMS_AuthenticatedData_st { + int32_t version; + CMS_OriginatorInfo *originatorInfo; + STACK_OF(CMS_RecipientInfo) *recipientInfos; + X509_ALGOR *macAlgorithm; + X509_ALGOR *digestAlgorithm; + CMS_EncapsulatedContentInfo *encapContentInfo; + STACK_OF(X509_ATTRIBUTE) *authAttrs; + ASN1_OCTET_STRING *mac; + STACK_OF(X509_ATTRIBUTE) *unauthAttrs; +}; + +struct CMS_CompressedData_st { + int32_t version; + X509_ALGOR *compressionAlgorithm; + STACK_OF(CMS_RecipientInfo) *recipientInfos; + CMS_EncapsulatedContentInfo *encapContentInfo; +}; + +struct CMS_RevocationInfoChoice_st { + int type; + union { + X509_CRL *crl; + CMS_OtherRevocationInfoFormat *other; + } d; +}; + +# define CMS_REVCHOICE_CRL 0 +# define CMS_REVCHOICE_OTHER 1 + +struct CMS_OtherRevocationInfoFormat_st { + ASN1_OBJECT *otherRevInfoFormat; + ASN1_TYPE *otherRevInfo; +}; + +struct CMS_CertificateChoices { + int type; + union { + X509 *certificate; + ASN1_STRING *extendedCertificate; /* Obsolete */ + ASN1_STRING *v1AttrCert; /* Left encoded for now */ + ASN1_STRING *v2AttrCert; /* Left encoded for now */ + CMS_OtherCertificateFormat *other; + } d; +}; + +# define CMS_CERTCHOICE_CERT 0 +# define CMS_CERTCHOICE_EXCERT 1 +# define CMS_CERTCHOICE_V1ACERT 2 +# define CMS_CERTCHOICE_V2ACERT 3 +# define CMS_CERTCHOICE_OTHER 4 + +struct CMS_OtherCertificateFormat_st { + ASN1_OBJECT *otherCertFormat; + ASN1_TYPE *otherCert; +}; + +/* + * This is also defined in pkcs7.h but we duplicate it to allow the CMS code + * to be independent of PKCS#7 + */ + +struct CMS_IssuerAndSerialNumber_st { + X509_NAME *issuer; + ASN1_INTEGER *serialNumber; +}; + +struct CMS_OtherKeyAttribute_st { + ASN1_OBJECT *keyAttrId; + ASN1_TYPE *keyAttr; +}; + +/* ESS structures */ + +# ifdef HEADER_X509V3_H + +struct CMS_ReceiptRequest_st { + ASN1_OCTET_STRING *signedContentIdentifier; + CMS_ReceiptsFrom *receiptsFrom; + STACK_OF(GENERAL_NAMES) *receiptsTo; +}; + +struct CMS_ReceiptsFrom_st { + int type; + union { + int32_t allOrFirstTier; + STACK_OF(GENERAL_NAMES) *receiptList; + } d; +}; +# endif + +struct CMS_Receipt_st { + int32_t version; + ASN1_OBJECT *contentType; + ASN1_OCTET_STRING *signedContentIdentifier; + ASN1_OCTET_STRING *originatorSignatureValue; +}; + +DECLARE_ASN1_FUNCTIONS(CMS_ContentInfo) +DECLARE_ASN1_ITEM(CMS_SignerInfo) +DECLARE_ASN1_ITEM(CMS_IssuerAndSerialNumber) +DECLARE_ASN1_ITEM(CMS_Attributes_Sign) +DECLARE_ASN1_ITEM(CMS_Attributes_Verify) +DECLARE_ASN1_ITEM(CMS_RecipientInfo) +DECLARE_ASN1_ITEM(CMS_PasswordRecipientInfo) +DECLARE_ASN1_ALLOC_FUNCTIONS(CMS_IssuerAndSerialNumber) + +# define CMS_SIGNERINFO_ISSUER_SERIAL 0 +# define CMS_SIGNERINFO_KEYIDENTIFIER 1 + +# define CMS_RECIPINFO_ISSUER_SERIAL 0 +# define CMS_RECIPINFO_KEYIDENTIFIER 1 + +# define CMS_REK_ISSUER_SERIAL 0 +# define CMS_REK_KEYIDENTIFIER 1 + +# define CMS_OIK_ISSUER_SERIAL 0 +# define CMS_OIK_KEYIDENTIFIER 1 +# define CMS_OIK_PUBKEY 2 + +BIO *cms_content_bio(CMS_ContentInfo *cms); + +CMS_ContentInfo *cms_Data_create(void); + +CMS_ContentInfo *cms_DigestedData_create(const EVP_MD *md); +BIO *cms_DigestedData_init_bio(CMS_ContentInfo *cms); +int cms_DigestedData_do_final(CMS_ContentInfo *cms, BIO *chain, int verify); + +BIO *cms_SignedData_init_bio(CMS_ContentInfo *cms); +int cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain); +int cms_set1_SignerIdentifier(CMS_SignerIdentifier *sid, X509 *cert, + int type); +int cms_SignerIdentifier_get0_signer_id(CMS_SignerIdentifier *sid, + ASN1_OCTET_STRING **keyid, + X509_NAME **issuer, + ASN1_INTEGER **sno); +int cms_SignerIdentifier_cert_cmp(CMS_SignerIdentifier *sid, X509 *cert); + +CMS_ContentInfo *cms_CompressedData_create(int comp_nid); +BIO *cms_CompressedData_init_bio(CMS_ContentInfo *cms); + +BIO *cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm); +int cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain, + X509_ALGOR *mdalg); + +int cms_ias_cert_cmp(CMS_IssuerAndSerialNumber *ias, X509 *cert); +int cms_keyid_cert_cmp(ASN1_OCTET_STRING *keyid, X509 *cert); +int cms_set1_ias(CMS_IssuerAndSerialNumber **pias, X509 *cert); +int cms_set1_keyid(ASN1_OCTET_STRING **pkeyid, X509 *cert); + +BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec); +BIO *cms_EncryptedData_init_bio(CMS_ContentInfo *cms); +int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec, + const EVP_CIPHER *cipher, + const unsigned char *key, size_t keylen); + +int cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms); +int cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src); +ASN1_OCTET_STRING *cms_encode_Receipt(CMS_SignerInfo *si); + +BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms); +CMS_EnvelopedData *cms_get0_enveloped(CMS_ContentInfo *cms); +int cms_env_asn1_ctrl(CMS_RecipientInfo *ri, int cmd); +int cms_pkey_get_ri_type(EVP_PKEY *pk); +/* KARI routines */ +int cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip, + EVP_PKEY *pk, unsigned int flags); +int cms_RecipientInfo_kari_encrypt(CMS_ContentInfo *cms, + CMS_RecipientInfo *ri); + +/* PWRI routines */ +int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri, + int en_de); + +DECLARE_ASN1_ITEM(CMS_CertificateChoices) +DECLARE_ASN1_ITEM(CMS_DigestedData) +DECLARE_ASN1_ITEM(CMS_EncryptedData) +DECLARE_ASN1_ITEM(CMS_EnvelopedData) +DECLARE_ASN1_ITEM(CMS_KEKRecipientInfo) +DECLARE_ASN1_ITEM(CMS_KeyAgreeRecipientInfo) +DECLARE_ASN1_ITEM(CMS_KeyTransRecipientInfo) +DECLARE_ASN1_ITEM(CMS_OriginatorPublicKey) +DECLARE_ASN1_ITEM(CMS_OtherKeyAttribute) +DECLARE_ASN1_ITEM(CMS_Receipt) +DECLARE_ASN1_ITEM(CMS_ReceiptRequest) +DECLARE_ASN1_ITEM(CMS_RecipientEncryptedKey) +DECLARE_ASN1_ITEM(CMS_RecipientKeyIdentifier) +DECLARE_ASN1_ITEM(CMS_RevocationInfoChoice) +DECLARE_ASN1_ITEM(CMS_SignedData) +DECLARE_ASN1_ITEM(CMS_CompressedData) + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_lib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_lib.c new file mode 100644 index 000000000..c2cac2601 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_lib.c @@ -0,0 +1,587 @@ +/* + * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include "cms_lcl.h" + +IMPLEMENT_ASN1_FUNCTIONS(CMS_ContentInfo) +IMPLEMENT_ASN1_PRINT_FUNCTION(CMS_ContentInfo) + +const ASN1_OBJECT *CMS_get0_type(const CMS_ContentInfo *cms) +{ + return cms->contentType; +} + +CMS_ContentInfo *cms_Data_create(void) +{ + CMS_ContentInfo *cms; + cms = CMS_ContentInfo_new(); + if (cms != NULL) { + cms->contentType = OBJ_nid2obj(NID_pkcs7_data); + /* Never detached */ + CMS_set_detached(cms, 0); + } + return cms; +} + +BIO *cms_content_bio(CMS_ContentInfo *cms) +{ + ASN1_OCTET_STRING **pos = CMS_get0_content(cms); + if (!pos) + return NULL; + /* If content detached data goes nowhere: create NULL BIO */ + if (!*pos) + return BIO_new(BIO_s_null()); + /* + * If content not detached and created return memory BIO + */ + if (!*pos || ((*pos)->flags == ASN1_STRING_FLAG_CONT)) + return BIO_new(BIO_s_mem()); + /* Else content was read in: return read only BIO for it */ + return BIO_new_mem_buf((*pos)->data, (*pos)->length); +} + +BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont) +{ + BIO *cmsbio, *cont; + if (icont) + cont = icont; + else + cont = cms_content_bio(cms); + if (!cont) { + CMSerr(CMS_F_CMS_DATAINIT, CMS_R_NO_CONTENT); + return NULL; + } + switch (OBJ_obj2nid(cms->contentType)) { + + case NID_pkcs7_data: + return cont; + + case NID_pkcs7_signed: + cmsbio = cms_SignedData_init_bio(cms); + break; + + case NID_pkcs7_digest: + cmsbio = cms_DigestedData_init_bio(cms); + break; +#ifdef ZLIB + case NID_id_smime_ct_compressedData: + cmsbio = cms_CompressedData_init_bio(cms); + break; +#endif + + case NID_pkcs7_encrypted: + cmsbio = cms_EncryptedData_init_bio(cms); + break; + + case NID_pkcs7_enveloped: + cmsbio = cms_EnvelopedData_init_bio(cms); + break; + + default: + CMSerr(CMS_F_CMS_DATAINIT, CMS_R_UNSUPPORTED_TYPE); + return NULL; + } + + if (cmsbio) + return BIO_push(cmsbio, cont); + + if (!icont) + BIO_free(cont); + return NULL; + +} + +int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio) +{ + ASN1_OCTET_STRING **pos = CMS_get0_content(cms); + if (!pos) + return 0; + /* If embedded content find memory BIO and set content */ + if (*pos && ((*pos)->flags & ASN1_STRING_FLAG_CONT)) { + BIO *mbio; + unsigned char *cont; + long contlen; + mbio = BIO_find_type(cmsbio, BIO_TYPE_MEM); + if (!mbio) { + CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_CONTENT_NOT_FOUND); + return 0; + } + contlen = BIO_get_mem_data(mbio, &cont); + /* Set bio as read only so its content can't be clobbered */ + BIO_set_flags(mbio, BIO_FLAGS_MEM_RDONLY); + BIO_set_mem_eof_return(mbio, 0); + ASN1_STRING_set0(*pos, cont, contlen); + (*pos)->flags &= ~ASN1_STRING_FLAG_CONT; + } + + switch (OBJ_obj2nid(cms->contentType)) { + + case NID_pkcs7_data: + case NID_pkcs7_enveloped: + case NID_pkcs7_encrypted: + case NID_id_smime_ct_compressedData: + /* Nothing to do */ + return 1; + + case NID_pkcs7_signed: + return cms_SignedData_final(cms, cmsbio); + + case NID_pkcs7_digest: + return cms_DigestedData_do_final(cms, cmsbio, 0); + + default: + CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_UNSUPPORTED_TYPE); + return 0; + } +} + +/* + * Return an OCTET STRING pointer to content. This allows it to be accessed + * or set later. + */ + +ASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms) +{ + switch (OBJ_obj2nid(cms->contentType)) { + + case NID_pkcs7_data: + return &cms->d.data; + + case NID_pkcs7_signed: + return &cms->d.signedData->encapContentInfo->eContent; + + case NID_pkcs7_enveloped: + return &cms->d.envelopedData->encryptedContentInfo->encryptedContent; + + case NID_pkcs7_digest: + return &cms->d.digestedData->encapContentInfo->eContent; + + case NID_pkcs7_encrypted: + return &cms->d.encryptedData->encryptedContentInfo->encryptedContent; + + case NID_id_smime_ct_authData: + return &cms->d.authenticatedData->encapContentInfo->eContent; + + case NID_id_smime_ct_compressedData: + return &cms->d.compressedData->encapContentInfo->eContent; + + default: + if (cms->d.other->type == V_ASN1_OCTET_STRING) + return &cms->d.other->value.octet_string; + CMSerr(CMS_F_CMS_GET0_CONTENT, CMS_R_UNSUPPORTED_CONTENT_TYPE); + return NULL; + + } +} + +/* + * Return an ASN1_OBJECT pointer to content type. This allows it to be + * accessed or set later. + */ + +static ASN1_OBJECT **cms_get0_econtent_type(CMS_ContentInfo *cms) +{ + switch (OBJ_obj2nid(cms->contentType)) { + + case NID_pkcs7_signed: + return &cms->d.signedData->encapContentInfo->eContentType; + + case NID_pkcs7_enveloped: + return &cms->d.envelopedData->encryptedContentInfo->contentType; + + case NID_pkcs7_digest: + return &cms->d.digestedData->encapContentInfo->eContentType; + + case NID_pkcs7_encrypted: + return &cms->d.encryptedData->encryptedContentInfo->contentType; + + case NID_id_smime_ct_authData: + return &cms->d.authenticatedData->encapContentInfo->eContentType; + + case NID_id_smime_ct_compressedData: + return &cms->d.compressedData->encapContentInfo->eContentType; + + default: + CMSerr(CMS_F_CMS_GET0_ECONTENT_TYPE, CMS_R_UNSUPPORTED_CONTENT_TYPE); + return NULL; + + } +} + +const ASN1_OBJECT *CMS_get0_eContentType(CMS_ContentInfo *cms) +{ + ASN1_OBJECT **petype; + petype = cms_get0_econtent_type(cms); + if (petype) + return *petype; + return NULL; +} + +int CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid) +{ + ASN1_OBJECT **petype, *etype; + petype = cms_get0_econtent_type(cms); + if (!petype) + return 0; + if (!oid) + return 1; + etype = OBJ_dup(oid); + if (!etype) + return 0; + ASN1_OBJECT_free(*petype); + *petype = etype; + return 1; +} + +int CMS_is_detached(CMS_ContentInfo *cms) +{ + ASN1_OCTET_STRING **pos; + pos = CMS_get0_content(cms); + if (!pos) + return -1; + if (*pos) + return 0; + return 1; +} + +int CMS_set_detached(CMS_ContentInfo *cms, int detached) +{ + ASN1_OCTET_STRING **pos; + pos = CMS_get0_content(cms); + if (!pos) + return 0; + if (detached) { + ASN1_OCTET_STRING_free(*pos); + *pos = NULL; + return 1; + } + if (*pos == NULL) + *pos = ASN1_OCTET_STRING_new(); + if (*pos != NULL) { + /* + * NB: special flag to show content is created and not read in. + */ + (*pos)->flags |= ASN1_STRING_FLAG_CONT; + return 1; + } + CMSerr(CMS_F_CMS_SET_DETACHED, ERR_R_MALLOC_FAILURE); + return 0; +} + +/* Create a digest BIO from an X509_ALGOR structure */ + +BIO *cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm) +{ + BIO *mdbio = NULL; + const ASN1_OBJECT *digestoid; + const EVP_MD *digest; + X509_ALGOR_get0(&digestoid, NULL, NULL, digestAlgorithm); + digest = EVP_get_digestbyobj(digestoid); + if (!digest) { + CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO, + CMS_R_UNKNOWN_DIGEST_ALGORITHM); + goto err; + } + mdbio = BIO_new(BIO_f_md()); + if (mdbio == NULL || !BIO_set_md(mdbio, digest)) { + CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO, CMS_R_MD_BIO_INIT_ERROR); + goto err; + } + return mdbio; + err: + BIO_free(mdbio); + return NULL; +} + +/* Locate a message digest content from a BIO chain based on SignerInfo */ + +int cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain, + X509_ALGOR *mdalg) +{ + int nid; + const ASN1_OBJECT *mdoid; + X509_ALGOR_get0(&mdoid, NULL, NULL, mdalg); + nid = OBJ_obj2nid(mdoid); + /* Look for digest type to match signature */ + for (;;) { + EVP_MD_CTX *mtmp; + chain = BIO_find_type(chain, BIO_TYPE_MD); + if (chain == NULL) { + CMSerr(CMS_F_CMS_DIGESTALGORITHM_FIND_CTX, + CMS_R_NO_MATCHING_DIGEST); + return 0; + } + BIO_get_md_ctx(chain, &mtmp); + if (EVP_MD_CTX_type(mtmp) == nid + /* + * Workaround for broken implementations that use signature + * algorithm OID instead of digest. + */ + || EVP_MD_pkey_type(EVP_MD_CTX_md(mtmp)) == nid) + return EVP_MD_CTX_copy_ex(mctx, mtmp); + chain = BIO_next(chain); + } +} + +static STACK_OF(CMS_CertificateChoices) +**cms_get0_certificate_choices(CMS_ContentInfo *cms) +{ + switch (OBJ_obj2nid(cms->contentType)) { + + case NID_pkcs7_signed: + return &cms->d.signedData->certificates; + + case NID_pkcs7_enveloped: + if (cms->d.envelopedData->originatorInfo == NULL) + return NULL; + return &cms->d.envelopedData->originatorInfo->certificates; + + default: + CMSerr(CMS_F_CMS_GET0_CERTIFICATE_CHOICES, + CMS_R_UNSUPPORTED_CONTENT_TYPE); + return NULL; + + } +} + +CMS_CertificateChoices *CMS_add0_CertificateChoices(CMS_ContentInfo *cms) +{ + STACK_OF(CMS_CertificateChoices) **pcerts; + CMS_CertificateChoices *cch; + pcerts = cms_get0_certificate_choices(cms); + if (!pcerts) + return NULL; + if (!*pcerts) + *pcerts = sk_CMS_CertificateChoices_new_null(); + if (!*pcerts) + return NULL; + cch = M_ASN1_new_of(CMS_CertificateChoices); + if (!cch) + return NULL; + if (!sk_CMS_CertificateChoices_push(*pcerts, cch)) { + M_ASN1_free_of(cch, CMS_CertificateChoices); + return NULL; + } + return cch; +} + +int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert) +{ + CMS_CertificateChoices *cch; + STACK_OF(CMS_CertificateChoices) **pcerts; + int i; + pcerts = cms_get0_certificate_choices(cms); + if (!pcerts) + return 0; + for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) { + cch = sk_CMS_CertificateChoices_value(*pcerts, i); + if (cch->type == CMS_CERTCHOICE_CERT) { + if (!X509_cmp(cch->d.certificate, cert)) { + CMSerr(CMS_F_CMS_ADD0_CERT, + CMS_R_CERTIFICATE_ALREADY_PRESENT); + return 0; + } + } + } + cch = CMS_add0_CertificateChoices(cms); + if (!cch) + return 0; + cch->type = CMS_CERTCHOICE_CERT; + cch->d.certificate = cert; + return 1; +} + +int CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert) +{ + int r; + r = CMS_add0_cert(cms, cert); + if (r > 0) + X509_up_ref(cert); + return r; +} + +static STACK_OF(CMS_RevocationInfoChoice) +**cms_get0_revocation_choices(CMS_ContentInfo *cms) +{ + switch (OBJ_obj2nid(cms->contentType)) { + + case NID_pkcs7_signed: + return &cms->d.signedData->crls; + + case NID_pkcs7_enveloped: + if (cms->d.envelopedData->originatorInfo == NULL) + return NULL; + return &cms->d.envelopedData->originatorInfo->crls; + + default: + CMSerr(CMS_F_CMS_GET0_REVOCATION_CHOICES, + CMS_R_UNSUPPORTED_CONTENT_TYPE); + return NULL; + + } +} + +CMS_RevocationInfoChoice *CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms) +{ + STACK_OF(CMS_RevocationInfoChoice) **pcrls; + CMS_RevocationInfoChoice *rch; + pcrls = cms_get0_revocation_choices(cms); + if (!pcrls) + return NULL; + if (!*pcrls) + *pcrls = sk_CMS_RevocationInfoChoice_new_null(); + if (!*pcrls) + return NULL; + rch = M_ASN1_new_of(CMS_RevocationInfoChoice); + if (!rch) + return NULL; + if (!sk_CMS_RevocationInfoChoice_push(*pcrls, rch)) { + M_ASN1_free_of(rch, CMS_RevocationInfoChoice); + return NULL; + } + return rch; +} + +int CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl) +{ + CMS_RevocationInfoChoice *rch; + rch = CMS_add0_RevocationInfoChoice(cms); + if (!rch) + return 0; + rch->type = CMS_REVCHOICE_CRL; + rch->d.crl = crl; + return 1; +} + +int CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl) +{ + int r; + r = CMS_add0_crl(cms, crl); + if (r > 0) + X509_CRL_up_ref(crl); + return r; +} + +STACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms) +{ + STACK_OF(X509) *certs = NULL; + CMS_CertificateChoices *cch; + STACK_OF(CMS_CertificateChoices) **pcerts; + int i; + pcerts = cms_get0_certificate_choices(cms); + if (!pcerts) + return NULL; + for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) { + cch = sk_CMS_CertificateChoices_value(*pcerts, i); + if (cch->type == 0) { + if (!certs) { + certs = sk_X509_new_null(); + if (!certs) + return NULL; + } + if (!sk_X509_push(certs, cch->d.certificate)) { + sk_X509_pop_free(certs, X509_free); + return NULL; + } + X509_up_ref(cch->d.certificate); + } + } + return certs; + +} + +STACK_OF(X509_CRL) *CMS_get1_crls(CMS_ContentInfo *cms) +{ + STACK_OF(X509_CRL) *crls = NULL; + STACK_OF(CMS_RevocationInfoChoice) **pcrls; + CMS_RevocationInfoChoice *rch; + int i; + pcrls = cms_get0_revocation_choices(cms); + if (!pcrls) + return NULL; + for (i = 0; i < sk_CMS_RevocationInfoChoice_num(*pcrls); i++) { + rch = sk_CMS_RevocationInfoChoice_value(*pcrls, i); + if (rch->type == 0) { + if (!crls) { + crls = sk_X509_CRL_new_null(); + if (!crls) + return NULL; + } + if (!sk_X509_CRL_push(crls, rch->d.crl)) { + sk_X509_CRL_pop_free(crls, X509_CRL_free); + return NULL; + } + X509_CRL_up_ref(rch->d.crl); + } + } + return crls; +} + +int cms_ias_cert_cmp(CMS_IssuerAndSerialNumber *ias, X509 *cert) +{ + int ret; + ret = X509_NAME_cmp(ias->issuer, X509_get_issuer_name(cert)); + if (ret) + return ret; + return ASN1_INTEGER_cmp(ias->serialNumber, X509_get_serialNumber(cert)); +} + +int cms_keyid_cert_cmp(ASN1_OCTET_STRING *keyid, X509 *cert) +{ + const ASN1_OCTET_STRING *cert_keyid = X509_get0_subject_key_id(cert); + + if (cert_keyid == NULL) + return -1; + return ASN1_OCTET_STRING_cmp(keyid, cert_keyid); +} + +int cms_set1_ias(CMS_IssuerAndSerialNumber **pias, X509 *cert) +{ + CMS_IssuerAndSerialNumber *ias; + ias = M_ASN1_new_of(CMS_IssuerAndSerialNumber); + if (!ias) + goto err; + if (!X509_NAME_set(&ias->issuer, X509_get_issuer_name(cert))) + goto err; + if (!ASN1_STRING_copy(ias->serialNumber, X509_get_serialNumber(cert))) + goto err; + M_ASN1_free_of(*pias, CMS_IssuerAndSerialNumber); + *pias = ias; + return 1; + err: + M_ASN1_free_of(ias, CMS_IssuerAndSerialNumber); + CMSerr(CMS_F_CMS_SET1_IAS, ERR_R_MALLOC_FAILURE); + return 0; +} + +int cms_set1_keyid(ASN1_OCTET_STRING **pkeyid, X509 *cert) +{ + ASN1_OCTET_STRING *keyid = NULL; + const ASN1_OCTET_STRING *cert_keyid; + cert_keyid = X509_get0_subject_key_id(cert); + if (cert_keyid == NULL) { + CMSerr(CMS_F_CMS_SET1_KEYID, CMS_R_CERTIFICATE_HAS_NO_KEYID); + return 0; + } + keyid = ASN1_STRING_dup(cert_keyid); + if (!keyid) { + CMSerr(CMS_F_CMS_SET1_KEYID, ERR_R_MALLOC_FAILURE); + return 0; + } + ASN1_OCTET_STRING_free(*pkeyid); + *pkeyid = keyid; + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_pwri.c b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_pwri.c new file mode 100644 index 000000000..26e3bdcf9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_pwri.c @@ -0,0 +1,394 @@ +/* + * Copyright 2009-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include +#include +#include "cms_lcl.h" +#include "internal/asn1_int.h" + +int CMS_RecipientInfo_set0_password(CMS_RecipientInfo *ri, + unsigned char *pass, ossl_ssize_t passlen) +{ + CMS_PasswordRecipientInfo *pwri; + if (ri->type != CMS_RECIPINFO_PASS) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD, CMS_R_NOT_PWRI); + return 0; + } + + pwri = ri->d.pwri; + pwri->pass = pass; + if (pass && passlen < 0) + passlen = strlen((char *)pass); + pwri->passlen = passlen; + return 1; +} + +CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms, + int iter, int wrap_nid, + int pbe_nid, + unsigned char *pass, + ossl_ssize_t passlen, + const EVP_CIPHER *kekciph) +{ + CMS_RecipientInfo *ri = NULL; + CMS_EnvelopedData *env; + CMS_PasswordRecipientInfo *pwri; + EVP_CIPHER_CTX *ctx = NULL; + X509_ALGOR *encalg = NULL; + unsigned char iv[EVP_MAX_IV_LENGTH]; + int ivlen; + + env = cms_get0_enveloped(cms); + if (!env) + return NULL; + + if (wrap_nid <= 0) + wrap_nid = NID_id_alg_PWRI_KEK; + + if (pbe_nid <= 0) + pbe_nid = NID_id_pbkdf2; + + /* Get from enveloped data */ + if (kekciph == NULL) + kekciph = env->encryptedContentInfo->cipher; + + if (kekciph == NULL) { + CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, CMS_R_NO_CIPHER); + return NULL; + } + if (wrap_nid != NID_id_alg_PWRI_KEK) { + CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, + CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM); + return NULL; + } + + /* Setup algorithm identifier for cipher */ + encalg = X509_ALGOR_new(); + if (encalg == NULL) { + goto merr; + } + ctx = EVP_CIPHER_CTX_new(); + + if (EVP_EncryptInit_ex(ctx, kekciph, NULL, NULL, NULL) <= 0) { + CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_EVP_LIB); + goto err; + } + + ivlen = EVP_CIPHER_CTX_iv_length(ctx); + + if (ivlen > 0) { + if (RAND_bytes(iv, ivlen) <= 0) + goto err; + if (EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv) <= 0) { + CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_EVP_LIB); + goto err; + } + encalg->parameter = ASN1_TYPE_new(); + if (!encalg->parameter) { + CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_MALLOC_FAILURE); + goto err; + } + if (EVP_CIPHER_param_to_asn1(ctx, encalg->parameter) <= 0) { + CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, + CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); + goto err; + } + } + + encalg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(ctx)); + + EVP_CIPHER_CTX_free(ctx); + ctx = NULL; + + /* Initialize recipient info */ + ri = M_ASN1_new_of(CMS_RecipientInfo); + if (ri == NULL) + goto merr; + + ri->d.pwri = M_ASN1_new_of(CMS_PasswordRecipientInfo); + if (ri->d.pwri == NULL) + goto merr; + ri->type = CMS_RECIPINFO_PASS; + + pwri = ri->d.pwri; + /* Since this is overwritten, free up empty structure already there */ + X509_ALGOR_free(pwri->keyEncryptionAlgorithm); + pwri->keyEncryptionAlgorithm = X509_ALGOR_new(); + if (pwri->keyEncryptionAlgorithm == NULL) + goto merr; + pwri->keyEncryptionAlgorithm->algorithm = OBJ_nid2obj(wrap_nid); + pwri->keyEncryptionAlgorithm->parameter = ASN1_TYPE_new(); + if (pwri->keyEncryptionAlgorithm->parameter == NULL) + goto merr; + + if (!ASN1_item_pack(encalg, ASN1_ITEM_rptr(X509_ALGOR), + &pwri->keyEncryptionAlgorithm->parameter-> + value.sequence)) + goto merr; + pwri->keyEncryptionAlgorithm->parameter->type = V_ASN1_SEQUENCE; + + X509_ALGOR_free(encalg); + encalg = NULL; + + /* Setup PBE algorithm */ + + pwri->keyDerivationAlgorithm = PKCS5_pbkdf2_set(iter, NULL, 0, -1, -1); + + if (!pwri->keyDerivationAlgorithm) + goto err; + + CMS_RecipientInfo_set0_password(ri, pass, passlen); + pwri->version = 0; + + if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri)) + goto merr; + + return ri; + + merr: + CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_MALLOC_FAILURE); + err: + EVP_CIPHER_CTX_free(ctx); + if (ri) + M_ASN1_free_of(ri, CMS_RecipientInfo); + X509_ALGOR_free(encalg); + return NULL; + +} + +/* + * This is an implementation of the key wrapping mechanism in RFC3211, at + * some point this should go into EVP. + */ + +static int kek_unwrap_key(unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen, + EVP_CIPHER_CTX *ctx) +{ + size_t blocklen = EVP_CIPHER_CTX_block_size(ctx); + unsigned char *tmp; + int outl, rv = 0; + if (inlen < 2 * blocklen) { + /* too small */ + return 0; + } + if (inlen % blocklen) { + /* Invalid size */ + return 0; + } + if ((tmp = OPENSSL_malloc(inlen)) == NULL) { + CMSerr(CMS_F_KEK_UNWRAP_KEY, ERR_R_MALLOC_FAILURE); + return 0; + } + /* setup IV by decrypting last two blocks */ + if (!EVP_DecryptUpdate(ctx, tmp + inlen - 2 * blocklen, &outl, + in + inlen - 2 * blocklen, blocklen * 2) + /* + * Do a decrypt of last decrypted block to set IV to correct value + * output it to start of buffer so we don't corrupt decrypted block + * this works because buffer is at least two block lengths long. + */ + || !EVP_DecryptUpdate(ctx, tmp, &outl, + tmp + inlen - blocklen, blocklen) + /* Can now decrypt first n - 1 blocks */ + || !EVP_DecryptUpdate(ctx, tmp, &outl, in, inlen - blocklen) + + /* Reset IV to original value */ + || !EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, NULL) + /* Decrypt again */ + || !EVP_DecryptUpdate(ctx, tmp, &outl, tmp, inlen)) + goto err; + /* Check check bytes */ + if (((tmp[1] ^ tmp[4]) & (tmp[2] ^ tmp[5]) & (tmp[3] ^ tmp[6])) != 0xff) { + /* Check byte failure */ + goto err; + } + if (inlen < (size_t)(tmp[0] - 4)) { + /* Invalid length value */ + goto err; + } + *outlen = (size_t)tmp[0]; + memcpy(out, tmp + 4, *outlen); + rv = 1; + err: + OPENSSL_clear_free(tmp, inlen); + return rv; + +} + +static int kek_wrap_key(unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen, + EVP_CIPHER_CTX *ctx) +{ + size_t blocklen = EVP_CIPHER_CTX_block_size(ctx); + size_t olen; + int dummy; + /* + * First decide length of output buffer: need header and round up to + * multiple of block length. + */ + olen = (inlen + 4 + blocklen - 1) / blocklen; + olen *= blocklen; + if (olen < 2 * blocklen) { + /* Key too small */ + return 0; + } + if (inlen > 0xFF) { + /* Key too large */ + return 0; + } + if (out) { + /* Set header */ + out[0] = (unsigned char)inlen; + out[1] = in[0] ^ 0xFF; + out[2] = in[1] ^ 0xFF; + out[3] = in[2] ^ 0xFF; + memcpy(out + 4, in, inlen); + /* Add random padding to end */ + if (olen > inlen + 4 + && RAND_bytes(out + 4 + inlen, olen - 4 - inlen) <= 0) + return 0; + /* Encrypt twice */ + if (!EVP_EncryptUpdate(ctx, out, &dummy, out, olen) + || !EVP_EncryptUpdate(ctx, out, &dummy, out, olen)) + return 0; + } + + *outlen = olen; + + return 1; +} + +/* Encrypt/Decrypt content key in PWRI recipient info */ + +int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri, + int en_de) +{ + CMS_EncryptedContentInfo *ec; + CMS_PasswordRecipientInfo *pwri; + int r = 0; + X509_ALGOR *algtmp, *kekalg = NULL; + EVP_CIPHER_CTX *kekctx = NULL; + const EVP_CIPHER *kekcipher; + unsigned char *key = NULL; + size_t keylen; + + ec = cms->d.envelopedData->encryptedContentInfo; + + pwri = ri->d.pwri; + + if (!pwri->pass) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_NO_PASSWORD); + return 0; + } + algtmp = pwri->keyEncryptionAlgorithm; + + if (!algtmp || OBJ_obj2nid(algtmp->algorithm) != NID_id_alg_PWRI_KEK) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, + CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM); + return 0; + } + + kekalg = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(X509_ALGOR), + algtmp->parameter); + + if (kekalg == NULL) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, + CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER); + return 0; + } + + kekcipher = EVP_get_cipherbyobj(kekalg->algorithm); + + if (!kekcipher) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_UNKNOWN_CIPHER); + return 0; + } + + kekctx = EVP_CIPHER_CTX_new(); + if (kekctx == NULL) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, ERR_R_MALLOC_FAILURE); + return 0; + } + /* Fixup cipher based on AlgorithmIdentifier to set IV etc */ + if (!EVP_CipherInit_ex(kekctx, kekcipher, NULL, NULL, NULL, en_de)) + goto err; + EVP_CIPHER_CTX_set_padding(kekctx, 0); + if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, + CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); + goto err; + } + + algtmp = pwri->keyDerivationAlgorithm; + + /* Finish password based key derivation to setup key in "ctx" */ + + if (EVP_PBE_CipherInit(algtmp->algorithm, + (char *)pwri->pass, pwri->passlen, + algtmp->parameter, kekctx, en_de) < 0) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, ERR_R_EVP_LIB); + goto err; + } + + /* Finally wrap/unwrap the key */ + + if (en_de) { + + if (!kek_wrap_key(NULL, &keylen, ec->key, ec->keylen, kekctx)) + goto err; + + key = OPENSSL_malloc(keylen); + + if (key == NULL) + goto err; + + if (!kek_wrap_key(key, &keylen, ec->key, ec->keylen, kekctx)) + goto err; + pwri->encryptedKey->data = key; + pwri->encryptedKey->length = keylen; + } else { + key = OPENSSL_malloc(pwri->encryptedKey->length); + + if (key == NULL) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!kek_unwrap_key(key, &keylen, + pwri->encryptedKey->data, + pwri->encryptedKey->length, kekctx)) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_UNWRAP_FAILURE); + goto err; + } + + OPENSSL_clear_free(ec->key, ec->keylen); + ec->key = key; + ec->keylen = keylen; + + } + + r = 1; + + err: + + EVP_CIPHER_CTX_free(kekctx); + + if (!r) + OPENSSL_free(key); + X509_ALGOR_free(kekalg); + + return r; + +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_sd.c b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_sd.c new file mode 100644 index 000000000..ff2d540b6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_sd.c @@ -0,0 +1,926 @@ +/* + * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include +#include "cms_lcl.h" +#include "internal/asn1_int.h" +#include "internal/evp_int.h" + +/* CMS SignedData Utilities */ + +static CMS_SignedData *cms_get0_signed(CMS_ContentInfo *cms) +{ + if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_signed) { + CMSerr(CMS_F_CMS_GET0_SIGNED, CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA); + return NULL; + } + return cms->d.signedData; +} + +static CMS_SignedData *cms_signed_data_init(CMS_ContentInfo *cms) +{ + if (cms->d.other == NULL) { + cms->d.signedData = M_ASN1_new_of(CMS_SignedData); + if (!cms->d.signedData) { + CMSerr(CMS_F_CMS_SIGNED_DATA_INIT, ERR_R_MALLOC_FAILURE); + return NULL; + } + cms->d.signedData->version = 1; + cms->d.signedData->encapContentInfo->eContentType = + OBJ_nid2obj(NID_pkcs7_data); + cms->d.signedData->encapContentInfo->partial = 1; + ASN1_OBJECT_free(cms->contentType); + cms->contentType = OBJ_nid2obj(NID_pkcs7_signed); + return cms->d.signedData; + } + return cms_get0_signed(cms); +} + +/* Just initialise SignedData e.g. for certs only structure */ + +int CMS_SignedData_init(CMS_ContentInfo *cms) +{ + if (cms_signed_data_init(cms)) + return 1; + else + return 0; +} + +/* Check structures and fixup version numbers (if necessary) */ + +static void cms_sd_set_version(CMS_SignedData *sd) +{ + int i; + CMS_CertificateChoices *cch; + CMS_RevocationInfoChoice *rch; + CMS_SignerInfo *si; + + for (i = 0; i < sk_CMS_CertificateChoices_num(sd->certificates); i++) { + cch = sk_CMS_CertificateChoices_value(sd->certificates, i); + if (cch->type == CMS_CERTCHOICE_OTHER) { + if (sd->version < 5) + sd->version = 5; + } else if (cch->type == CMS_CERTCHOICE_V2ACERT) { + if (sd->version < 4) + sd->version = 4; + } else if (cch->type == CMS_CERTCHOICE_V1ACERT) { + if (sd->version < 3) + sd->version = 3; + } + } + + for (i = 0; i < sk_CMS_RevocationInfoChoice_num(sd->crls); i++) { + rch = sk_CMS_RevocationInfoChoice_value(sd->crls, i); + if (rch->type == CMS_REVCHOICE_OTHER) { + if (sd->version < 5) + sd->version = 5; + } + } + + if ((OBJ_obj2nid(sd->encapContentInfo->eContentType) != NID_pkcs7_data) + && (sd->version < 3)) + sd->version = 3; + + for (i = 0; i < sk_CMS_SignerInfo_num(sd->signerInfos); i++) { + si = sk_CMS_SignerInfo_value(sd->signerInfos, i); + if (si->sid->type == CMS_SIGNERINFO_KEYIDENTIFIER) { + if (si->version < 3) + si->version = 3; + if (sd->version < 3) + sd->version = 3; + } else if (si->version < 1) + si->version = 1; + } + + if (sd->version < 1) + sd->version = 1; + +} + +/* Copy an existing messageDigest value */ + +static int cms_copy_messageDigest(CMS_ContentInfo *cms, CMS_SignerInfo *si) +{ + STACK_OF(CMS_SignerInfo) *sinfos; + CMS_SignerInfo *sitmp; + int i; + sinfos = CMS_get0_SignerInfos(cms); + for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) { + ASN1_OCTET_STRING *messageDigest; + sitmp = sk_CMS_SignerInfo_value(sinfos, i); + if (sitmp == si) + continue; + if (CMS_signed_get_attr_count(sitmp) < 0) + continue; + if (OBJ_cmp(si->digestAlgorithm->algorithm, + sitmp->digestAlgorithm->algorithm)) + continue; + messageDigest = CMS_signed_get0_data_by_OBJ(sitmp, + OBJ_nid2obj + (NID_pkcs9_messageDigest), + -3, V_ASN1_OCTET_STRING); + if (!messageDigest) { + CMSerr(CMS_F_CMS_COPY_MESSAGEDIGEST, + CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE); + return 0; + } + + if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest, + V_ASN1_OCTET_STRING, + messageDigest, -1)) + return 1; + else + return 0; + } + CMSerr(CMS_F_CMS_COPY_MESSAGEDIGEST, CMS_R_NO_MATCHING_DIGEST); + return 0; +} + +int cms_set1_SignerIdentifier(CMS_SignerIdentifier *sid, X509 *cert, int type) +{ + switch (type) { + case CMS_SIGNERINFO_ISSUER_SERIAL: + if (!cms_set1_ias(&sid->d.issuerAndSerialNumber, cert)) + return 0; + break; + + case CMS_SIGNERINFO_KEYIDENTIFIER: + if (!cms_set1_keyid(&sid->d.subjectKeyIdentifier, cert)) + return 0; + break; + + default: + CMSerr(CMS_F_CMS_SET1_SIGNERIDENTIFIER, CMS_R_UNKNOWN_ID); + return 0; + } + + sid->type = type; + + return 1; +} + +int cms_SignerIdentifier_get0_signer_id(CMS_SignerIdentifier *sid, + ASN1_OCTET_STRING **keyid, + X509_NAME **issuer, + ASN1_INTEGER **sno) +{ + if (sid->type == CMS_SIGNERINFO_ISSUER_SERIAL) { + if (issuer) + *issuer = sid->d.issuerAndSerialNumber->issuer; + if (sno) + *sno = sid->d.issuerAndSerialNumber->serialNumber; + } else if (sid->type == CMS_SIGNERINFO_KEYIDENTIFIER) { + if (keyid) + *keyid = sid->d.subjectKeyIdentifier; + } else + return 0; + return 1; +} + +int cms_SignerIdentifier_cert_cmp(CMS_SignerIdentifier *sid, X509 *cert) +{ + if (sid->type == CMS_SIGNERINFO_ISSUER_SERIAL) + return cms_ias_cert_cmp(sid->d.issuerAndSerialNumber, cert); + else if (sid->type == CMS_SIGNERINFO_KEYIDENTIFIER) + return cms_keyid_cert_cmp(sid->d.subjectKeyIdentifier, cert); + else + return -1; +} + +static int cms_sd_asn1_ctrl(CMS_SignerInfo *si, int cmd) +{ + EVP_PKEY *pkey = si->pkey; + int i; + if (!pkey->ameth || !pkey->ameth->pkey_ctrl) + return 1; + i = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_CMS_SIGN, cmd, si); + if (i == -2) { + CMSerr(CMS_F_CMS_SD_ASN1_CTRL, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); + return 0; + } + if (i <= 0) { + CMSerr(CMS_F_CMS_SD_ASN1_CTRL, CMS_R_CTRL_FAILURE); + return 0; + } + return 1; +} + +CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, + X509 *signer, EVP_PKEY *pk, const EVP_MD *md, + unsigned int flags) +{ + CMS_SignedData *sd; + CMS_SignerInfo *si = NULL; + X509_ALGOR *alg; + int i, type; + if (!X509_check_private_key(signer, pk)) { + CMSerr(CMS_F_CMS_ADD1_SIGNER, + CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); + return NULL; + } + sd = cms_signed_data_init(cms); + if (!sd) + goto err; + si = M_ASN1_new_of(CMS_SignerInfo); + if (!si) + goto merr; + /* Call for side-effect of computing hash and caching extensions */ + X509_check_purpose(signer, -1, -1); + + X509_up_ref(signer); + EVP_PKEY_up_ref(pk); + + si->pkey = pk; + si->signer = signer; + si->mctx = EVP_MD_CTX_new(); + si->pctx = NULL; + + if (si->mctx == NULL) { + CMSerr(CMS_F_CMS_ADD1_SIGNER, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (flags & CMS_USE_KEYID) { + si->version = 3; + if (sd->version < 3) + sd->version = 3; + type = CMS_SIGNERINFO_KEYIDENTIFIER; + } else { + type = CMS_SIGNERINFO_ISSUER_SERIAL; + si->version = 1; + } + + if (!cms_set1_SignerIdentifier(si->sid, signer, type)) + goto err; + + if (md == NULL) { + int def_nid; + if (EVP_PKEY_get_default_digest_nid(pk, &def_nid) <= 0) + goto err; + md = EVP_get_digestbynid(def_nid); + if (md == NULL) { + CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DEFAULT_DIGEST); + goto err; + } + } + + if (!md) { + CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DIGEST_SET); + goto err; + } + + X509_ALGOR_set_md(si->digestAlgorithm, md); + + /* See if digest is present in digestAlgorithms */ + for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) { + const ASN1_OBJECT *aoid; + alg = sk_X509_ALGOR_value(sd->digestAlgorithms, i); + X509_ALGOR_get0(&aoid, NULL, NULL, alg); + if (OBJ_obj2nid(aoid) == EVP_MD_type(md)) + break; + } + + if (i == sk_X509_ALGOR_num(sd->digestAlgorithms)) { + alg = X509_ALGOR_new(); + if (alg == NULL) + goto merr; + X509_ALGOR_set_md(alg, md); + if (!sk_X509_ALGOR_push(sd->digestAlgorithms, alg)) { + X509_ALGOR_free(alg); + goto merr; + } + } + + if (!(flags & CMS_KEY_PARAM) && !cms_sd_asn1_ctrl(si, 0)) + goto err; + if (!(flags & CMS_NOATTR)) { + /* + * Initialize signed attributes structure so other attributes + * such as signing time etc are added later even if we add none here. + */ + if (!si->signedAttrs) { + si->signedAttrs = sk_X509_ATTRIBUTE_new_null(); + if (!si->signedAttrs) + goto merr; + } + + if (!(flags & CMS_NOSMIMECAP)) { + STACK_OF(X509_ALGOR) *smcap = NULL; + i = CMS_add_standard_smimecap(&smcap); + if (i) + i = CMS_add_smimecap(si, smcap); + sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free); + if (!i) + goto merr; + } + if (flags & CMS_REUSE_DIGEST) { + if (!cms_copy_messageDigest(cms, si)) + goto err; + if (!(flags & (CMS_PARTIAL | CMS_KEY_PARAM)) && + !CMS_SignerInfo_sign(si)) + goto err; + } + } + + if (!(flags & CMS_NOCERTS)) { + /* NB ignore -1 return for duplicate cert */ + if (!CMS_add1_cert(cms, signer)) + goto merr; + } + + if (flags & CMS_KEY_PARAM) { + if (flags & CMS_NOATTR) { + si->pctx = EVP_PKEY_CTX_new(si->pkey, NULL); + if (si->pctx == NULL) + goto err; + if (EVP_PKEY_sign_init(si->pctx) <= 0) + goto err; + if (EVP_PKEY_CTX_set_signature_md(si->pctx, md) <= 0) + goto err; + } else if (EVP_DigestSignInit(si->mctx, &si->pctx, md, NULL, pk) <= + 0) + goto err; + } + + if (!sd->signerInfos) + sd->signerInfos = sk_CMS_SignerInfo_new_null(); + if (!sd->signerInfos || !sk_CMS_SignerInfo_push(sd->signerInfos, si)) + goto merr; + + return si; + + merr: + CMSerr(CMS_F_CMS_ADD1_SIGNER, ERR_R_MALLOC_FAILURE); + err: + M_ASN1_free_of(si, CMS_SignerInfo); + return NULL; + +} + +static int cms_add1_signingTime(CMS_SignerInfo *si, ASN1_TIME *t) +{ + ASN1_TIME *tt; + int r = 0; + if (t) + tt = t; + else + tt = X509_gmtime_adj(NULL, 0); + + if (!tt) + goto merr; + + if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_signingTime, + tt->type, tt, -1) <= 0) + goto merr; + + r = 1; + + merr: + + if (!t) + ASN1_TIME_free(tt); + + if (!r) + CMSerr(CMS_F_CMS_ADD1_SIGNINGTIME, ERR_R_MALLOC_FAILURE); + + return r; + +} + +EVP_PKEY_CTX *CMS_SignerInfo_get0_pkey_ctx(CMS_SignerInfo *si) +{ + return si->pctx; +} + +EVP_MD_CTX *CMS_SignerInfo_get0_md_ctx(CMS_SignerInfo *si) +{ + return si->mctx; +} + +STACK_OF(CMS_SignerInfo) *CMS_get0_SignerInfos(CMS_ContentInfo *cms) +{ + CMS_SignedData *sd; + sd = cms_get0_signed(cms); + if (!sd) + return NULL; + return sd->signerInfos; +} + +STACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms) +{ + STACK_OF(X509) *signers = NULL; + STACK_OF(CMS_SignerInfo) *sinfos; + CMS_SignerInfo *si; + int i; + sinfos = CMS_get0_SignerInfos(cms); + for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) { + si = sk_CMS_SignerInfo_value(sinfos, i); + if (si->signer) { + if (!signers) { + signers = sk_X509_new_null(); + if (!signers) + return NULL; + } + if (!sk_X509_push(signers, si->signer)) { + sk_X509_free(signers); + return NULL; + } + } + } + return signers; +} + +void CMS_SignerInfo_set1_signer_cert(CMS_SignerInfo *si, X509 *signer) +{ + if (signer) { + X509_up_ref(signer); + EVP_PKEY_free(si->pkey); + si->pkey = X509_get_pubkey(signer); + } + X509_free(si->signer); + si->signer = signer; +} + +int CMS_SignerInfo_get0_signer_id(CMS_SignerInfo *si, + ASN1_OCTET_STRING **keyid, + X509_NAME **issuer, ASN1_INTEGER **sno) +{ + return cms_SignerIdentifier_get0_signer_id(si->sid, keyid, issuer, sno); +} + +int CMS_SignerInfo_cert_cmp(CMS_SignerInfo *si, X509 *cert) +{ + return cms_SignerIdentifier_cert_cmp(si->sid, cert); +} + +int CMS_set1_signers_certs(CMS_ContentInfo *cms, STACK_OF(X509) *scerts, + unsigned int flags) +{ + CMS_SignedData *sd; + CMS_SignerInfo *si; + CMS_CertificateChoices *cch; + STACK_OF(CMS_CertificateChoices) *certs; + X509 *x; + int i, j; + int ret = 0; + sd = cms_get0_signed(cms); + if (!sd) + return -1; + certs = sd->certificates; + for (i = 0; i < sk_CMS_SignerInfo_num(sd->signerInfos); i++) { + si = sk_CMS_SignerInfo_value(sd->signerInfos, i); + if (si->signer) + continue; + + for (j = 0; j < sk_X509_num(scerts); j++) { + x = sk_X509_value(scerts, j); + if (CMS_SignerInfo_cert_cmp(si, x) == 0) { + CMS_SignerInfo_set1_signer_cert(si, x); + ret++; + break; + } + } + + if (si->signer || (flags & CMS_NOINTERN)) + continue; + + for (j = 0; j < sk_CMS_CertificateChoices_num(certs); j++) { + cch = sk_CMS_CertificateChoices_value(certs, j); + if (cch->type != 0) + continue; + x = cch->d.certificate; + if (CMS_SignerInfo_cert_cmp(si, x) == 0) { + CMS_SignerInfo_set1_signer_cert(si, x); + ret++; + break; + } + } + } + return ret; +} + +void CMS_SignerInfo_get0_algs(CMS_SignerInfo *si, EVP_PKEY **pk, + X509 **signer, X509_ALGOR **pdig, + X509_ALGOR **psig) +{ + if (pk) + *pk = si->pkey; + if (signer) + *signer = si->signer; + if (pdig) + *pdig = si->digestAlgorithm; + if (psig) + *psig = si->signatureAlgorithm; +} + +ASN1_OCTET_STRING *CMS_SignerInfo_get0_signature(CMS_SignerInfo *si) +{ + return si->signature; +} + +static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms, + CMS_SignerInfo *si, BIO *chain) +{ + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); + int r = 0; + EVP_PKEY_CTX *pctx = NULL; + + if (mctx == NULL) { + CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (!si->pkey) { + CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, CMS_R_NO_PRIVATE_KEY); + goto err; + } + + if (!cms_DigestAlgorithm_find_ctx(mctx, chain, si->digestAlgorithm)) + goto err; + /* Set SignerInfo algorithm details if we used custom parameter */ + if (si->pctx && !cms_sd_asn1_ctrl(si, 0)) + goto err; + + /* + * If any signed attributes calculate and add messageDigest attribute + */ + + if (CMS_signed_get_attr_count(si) >= 0) { + ASN1_OBJECT *ctype = + cms->d.signedData->encapContentInfo->eContentType; + unsigned char md[EVP_MAX_MD_SIZE]; + unsigned int mdlen; + if (!EVP_DigestFinal_ex(mctx, md, &mdlen)) + goto err; + if (!CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest, + V_ASN1_OCTET_STRING, md, mdlen)) + goto err; + /* Copy content type across */ + if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_contentType, + V_ASN1_OBJECT, ctype, -1) <= 0) + goto err; + if (!CMS_SignerInfo_sign(si)) + goto err; + } else if (si->pctx) { + unsigned char *sig; + size_t siglen; + unsigned char md[EVP_MAX_MD_SIZE]; + unsigned int mdlen; + pctx = si->pctx; + if (!EVP_DigestFinal_ex(mctx, md, &mdlen)) + goto err; + siglen = EVP_PKEY_size(si->pkey); + sig = OPENSSL_malloc(siglen); + if (sig == NULL) { + CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, ERR_R_MALLOC_FAILURE); + goto err; + } + if (EVP_PKEY_sign(pctx, sig, &siglen, md, mdlen) <= 0) { + OPENSSL_free(sig); + goto err; + } + ASN1_STRING_set0(si->signature, sig, siglen); + } else { + unsigned char *sig; + unsigned int siglen; + sig = OPENSSL_malloc(EVP_PKEY_size(si->pkey)); + if (sig == NULL) { + CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!EVP_SignFinal(mctx, sig, &siglen, si->pkey)) { + CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, CMS_R_SIGNFINAL_ERROR); + OPENSSL_free(sig); + goto err; + } + ASN1_STRING_set0(si->signature, sig, siglen); + } + + r = 1; + + err: + EVP_MD_CTX_free(mctx); + EVP_PKEY_CTX_free(pctx); + return r; + +} + +int cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain) +{ + STACK_OF(CMS_SignerInfo) *sinfos; + CMS_SignerInfo *si; + int i; + sinfos = CMS_get0_SignerInfos(cms); + for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) { + si = sk_CMS_SignerInfo_value(sinfos, i); + if (!cms_SignerInfo_content_sign(cms, si, chain)) + return 0; + } + cms->d.signedData->encapContentInfo->partial = 0; + return 1; +} + +int CMS_SignerInfo_sign(CMS_SignerInfo *si) +{ + EVP_MD_CTX *mctx = si->mctx; + EVP_PKEY_CTX *pctx = NULL; + unsigned char *abuf = NULL; + int alen; + size_t siglen; + const EVP_MD *md = NULL; + + md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm); + if (md == NULL) + return 0; + + if (CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1) < 0) { + if (!cms_add1_signingTime(si, NULL)) + goto err; + } + + if (si->pctx) + pctx = si->pctx; + else { + EVP_MD_CTX_reset(mctx); + if (EVP_DigestSignInit(mctx, &pctx, md, NULL, si->pkey) <= 0) + goto err; + si->pctx = pctx; + } + + if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, + EVP_PKEY_CTRL_CMS_SIGN, 0, si) <= 0) { + CMSerr(CMS_F_CMS_SIGNERINFO_SIGN, CMS_R_CTRL_ERROR); + goto err; + } + + alen = ASN1_item_i2d((ASN1_VALUE *)si->signedAttrs, &abuf, + ASN1_ITEM_rptr(CMS_Attributes_Sign)); + if (!abuf) + goto err; + if (EVP_DigestSignUpdate(mctx, abuf, alen) <= 0) + goto err; + if (EVP_DigestSignFinal(mctx, NULL, &siglen) <= 0) + goto err; + OPENSSL_free(abuf); + abuf = OPENSSL_malloc(siglen); + if (abuf == NULL) + goto err; + if (EVP_DigestSignFinal(mctx, abuf, &siglen) <= 0) + goto err; + + if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, + EVP_PKEY_CTRL_CMS_SIGN, 1, si) <= 0) { + CMSerr(CMS_F_CMS_SIGNERINFO_SIGN, CMS_R_CTRL_ERROR); + goto err; + } + + EVP_MD_CTX_reset(mctx); + + ASN1_STRING_set0(si->signature, abuf, siglen); + + return 1; + + err: + OPENSSL_free(abuf); + EVP_MD_CTX_reset(mctx); + return 0; + +} + +int CMS_SignerInfo_verify(CMS_SignerInfo *si) +{ + EVP_MD_CTX *mctx = NULL; + unsigned char *abuf = NULL; + int alen, r = -1; + const EVP_MD *md = NULL; + + if (!si->pkey) { + CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY, CMS_R_NO_PUBLIC_KEY); + return -1; + } + + md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm); + if (md == NULL) + return -1; + if (si->mctx == NULL && (si->mctx = EVP_MD_CTX_new()) == NULL) { + CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY, ERR_R_MALLOC_FAILURE); + return -1; + } + mctx = si->mctx; + if (EVP_DigestVerifyInit(mctx, &si->pctx, md, NULL, si->pkey) <= 0) + goto err; + + if (!cms_sd_asn1_ctrl(si, 1)) + goto err; + + alen = ASN1_item_i2d((ASN1_VALUE *)si->signedAttrs, &abuf, + ASN1_ITEM_rptr(CMS_Attributes_Verify)); + if (!abuf) + goto err; + r = EVP_DigestVerifyUpdate(mctx, abuf, alen); + OPENSSL_free(abuf); + if (r <= 0) { + r = -1; + goto err; + } + r = EVP_DigestVerifyFinal(mctx, + si->signature->data, si->signature->length); + if (r <= 0) + CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY, CMS_R_VERIFICATION_FAILURE); + err: + EVP_MD_CTX_reset(mctx); + return r; +} + +/* Create a chain of digest BIOs from a CMS ContentInfo */ + +BIO *cms_SignedData_init_bio(CMS_ContentInfo *cms) +{ + int i; + CMS_SignedData *sd; + BIO *chain = NULL; + sd = cms_get0_signed(cms); + if (!sd) + return NULL; + if (cms->d.signedData->encapContentInfo->partial) + cms_sd_set_version(sd); + for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) { + X509_ALGOR *digestAlgorithm; + BIO *mdbio; + digestAlgorithm = sk_X509_ALGOR_value(sd->digestAlgorithms, i); + mdbio = cms_DigestAlgorithm_init_bio(digestAlgorithm); + if (!mdbio) + goto err; + if (chain) + BIO_push(chain, mdbio); + else + chain = mdbio; + } + return chain; + err: + BIO_free_all(chain); + return NULL; +} + +int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain) +{ + ASN1_OCTET_STRING *os = NULL; + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); + EVP_PKEY_CTX *pkctx = NULL; + int r = -1; + unsigned char mval[EVP_MAX_MD_SIZE]; + unsigned int mlen; + + if (mctx == NULL) { + CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT, ERR_R_MALLOC_FAILURE); + goto err; + } + /* If we have any signed attributes look for messageDigest value */ + if (CMS_signed_get_attr_count(si) >= 0) { + os = CMS_signed_get0_data_by_OBJ(si, + OBJ_nid2obj(NID_pkcs9_messageDigest), + -3, V_ASN1_OCTET_STRING); + if (!os) { + CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT, + CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE); + goto err; + } + } + + if (!cms_DigestAlgorithm_find_ctx(mctx, chain, si->digestAlgorithm)) + goto err; + + if (EVP_DigestFinal_ex(mctx, mval, &mlen) <= 0) { + CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT, + CMS_R_UNABLE_TO_FINALIZE_CONTEXT); + goto err; + } + + /* If messageDigest found compare it */ + + if (os) { + if (mlen != (unsigned int)os->length) { + CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT, + CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH); + goto err; + } + + if (memcmp(mval, os->data, mlen)) { + CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT, + CMS_R_VERIFICATION_FAILURE); + r = 0; + } else + r = 1; + } else { + const EVP_MD *md = EVP_MD_CTX_md(mctx); + pkctx = EVP_PKEY_CTX_new(si->pkey, NULL); + if (pkctx == NULL) + goto err; + if (EVP_PKEY_verify_init(pkctx) <= 0) + goto err; + if (EVP_PKEY_CTX_set_signature_md(pkctx, md) <= 0) + goto err; + si->pctx = pkctx; + if (!cms_sd_asn1_ctrl(si, 1)) + goto err; + r = EVP_PKEY_verify(pkctx, si->signature->data, + si->signature->length, mval, mlen); + if (r <= 0) { + CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT, + CMS_R_VERIFICATION_FAILURE); + r = 0; + } + } + + err: + EVP_PKEY_CTX_free(pkctx); + EVP_MD_CTX_free(mctx); + return r; + +} + +int CMS_add_smimecap(CMS_SignerInfo *si, STACK_OF(X509_ALGOR) *algs) +{ + unsigned char *smder = NULL; + int smderlen, r; + smderlen = i2d_X509_ALGORS(algs, &smder); + if (smderlen <= 0) + return 0; + r = CMS_signed_add1_attr_by_NID(si, NID_SMIMECapabilities, + V_ASN1_SEQUENCE, smder, smderlen); + OPENSSL_free(smder); + return r; +} + +int CMS_add_simple_smimecap(STACK_OF(X509_ALGOR) **algs, + int algnid, int keysize) +{ + X509_ALGOR *alg; + ASN1_INTEGER *key = NULL; + if (keysize > 0) { + key = ASN1_INTEGER_new(); + if (key == NULL || !ASN1_INTEGER_set(key, keysize)) + return 0; + } + alg = X509_ALGOR_new(); + if (alg == NULL) { + ASN1_INTEGER_free(key); + return 0; + } + + X509_ALGOR_set0(alg, OBJ_nid2obj(algnid), + key ? V_ASN1_INTEGER : V_ASN1_UNDEF, key); + if (*algs == NULL) + *algs = sk_X509_ALGOR_new_null(); + if (*algs == NULL || !sk_X509_ALGOR_push(*algs, alg)) { + X509_ALGOR_free(alg); + return 0; + } + return 1; +} + +/* Check to see if a cipher exists and if so add S/MIME capabilities */ + +static int cms_add_cipher_smcap(STACK_OF(X509_ALGOR) **sk, int nid, int arg) +{ + if (EVP_get_cipherbynid(nid)) + return CMS_add_simple_smimecap(sk, nid, arg); + return 1; +} + +static int cms_add_digest_smcap(STACK_OF(X509_ALGOR) **sk, int nid, int arg) +{ + if (EVP_get_digestbynid(nid)) + return CMS_add_simple_smimecap(sk, nid, arg); + return 1; +} + +int CMS_add_standard_smimecap(STACK_OF(X509_ALGOR) **smcap) +{ + if (!cms_add_cipher_smcap(smcap, NID_aes_256_cbc, -1) + || !cms_add_digest_smcap(smcap, NID_id_GostR3411_2012_256, -1) + || !cms_add_digest_smcap(smcap, NID_id_GostR3411_2012_512, -1) + || !cms_add_digest_smcap(smcap, NID_id_GostR3411_94, -1) + || !cms_add_cipher_smcap(smcap, NID_id_Gost28147_89, -1) + || !cms_add_cipher_smcap(smcap, NID_aes_192_cbc, -1) + || !cms_add_cipher_smcap(smcap, NID_aes_128_cbc, -1) + || !cms_add_cipher_smcap(smcap, NID_des_ede3_cbc, -1) + || !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 128) + || !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 64) + || !cms_add_cipher_smcap(smcap, NID_des_cbc, -1) + || !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 40)) + return 0; + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_smime.c b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_smime.c new file mode 100644 index 000000000..5dcf803f4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cms/cms_smime.c @@ -0,0 +1,843 @@ +/* + * Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include "cms_lcl.h" +#include "internal/asn1_int.h" + +static BIO *cms_get_text_bio(BIO *out, unsigned int flags) +{ + BIO *rbio; + if (out == NULL) + rbio = BIO_new(BIO_s_null()); + else if (flags & CMS_TEXT) { + rbio = BIO_new(BIO_s_mem()); + BIO_set_mem_eof_return(rbio, 0); + } else + rbio = out; + return rbio; +} + +static int cms_copy_content(BIO *out, BIO *in, unsigned int flags) +{ + unsigned char buf[4096]; + int r = 0, i; + BIO *tmpout; + + tmpout = cms_get_text_bio(out, flags); + + if (tmpout == NULL) { + CMSerr(CMS_F_CMS_COPY_CONTENT, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* Read all content through chain to process digest, decrypt etc */ + for (;;) { + i = BIO_read(in, buf, sizeof(buf)); + if (i <= 0) { + if (BIO_method_type(in) == BIO_TYPE_CIPHER) { + if (!BIO_get_cipher_status(in)) + goto err; + } + if (i < 0) + goto err; + break; + } + + if (tmpout && (BIO_write(tmpout, buf, i) != i)) + goto err; + } + + if (flags & CMS_TEXT) { + if (!SMIME_text(tmpout, out)) { + CMSerr(CMS_F_CMS_COPY_CONTENT, CMS_R_SMIME_TEXT_ERROR); + goto err; + } + } + + r = 1; + + err: + if (tmpout != out) + BIO_free(tmpout); + return r; + +} + +static int check_content(CMS_ContentInfo *cms) +{ + ASN1_OCTET_STRING **pos = CMS_get0_content(cms); + if (!pos || !*pos) { + CMSerr(CMS_F_CHECK_CONTENT, CMS_R_NO_CONTENT); + return 0; + } + return 1; +} + +static void do_free_upto(BIO *f, BIO *upto) +{ + if (upto) { + BIO *tbio; + do { + tbio = BIO_pop(f); + BIO_free(f); + f = tbio; + } + while (f && f != upto); + } else + BIO_free_all(f); +} + +int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags) +{ + BIO *cont; + int r; + if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_data) { + CMSerr(CMS_F_CMS_DATA, CMS_R_TYPE_NOT_DATA); + return 0; + } + cont = CMS_dataInit(cms, NULL); + if (!cont) + return 0; + r = cms_copy_content(out, cont, flags); + BIO_free_all(cont); + return r; +} + +CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags) +{ + CMS_ContentInfo *cms; + cms = cms_Data_create(); + if (!cms) + return NULL; + + if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags)) + return cms; + + CMS_ContentInfo_free(cms); + + return NULL; +} + +int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out, + unsigned int flags) +{ + BIO *cont; + int r; + if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_digest) { + CMSerr(CMS_F_CMS_DIGEST_VERIFY, CMS_R_TYPE_NOT_DIGESTED_DATA); + return 0; + } + + if (!dcont && !check_content(cms)) + return 0; + + cont = CMS_dataInit(cms, dcont); + if (!cont) + return 0; + r = cms_copy_content(out, cont, flags); + if (r) + r = cms_DigestedData_do_final(cms, cont, 1); + do_free_upto(cont, dcont); + return r; +} + +CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md, + unsigned int flags) +{ + CMS_ContentInfo *cms; + if (!md) + md = EVP_sha1(); + cms = cms_DigestedData_create(md); + if (!cms) + return NULL; + + if (!(flags & CMS_DETACHED)) + CMS_set_detached(cms, 0); + + if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags)) + return cms; + + CMS_ContentInfo_free(cms); + return NULL; +} + +int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms, + const unsigned char *key, size_t keylen, + BIO *dcont, BIO *out, unsigned int flags) +{ + BIO *cont; + int r; + if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_encrypted) { + CMSerr(CMS_F_CMS_ENCRYPTEDDATA_DECRYPT, + CMS_R_TYPE_NOT_ENCRYPTED_DATA); + return 0; + } + + if (!dcont && !check_content(cms)) + return 0; + + if (CMS_EncryptedData_set1_key(cms, NULL, key, keylen) <= 0) + return 0; + cont = CMS_dataInit(cms, dcont); + if (!cont) + return 0; + r = cms_copy_content(out, cont, flags); + do_free_upto(cont, dcont); + return r; +} + +CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher, + const unsigned char *key, + size_t keylen, unsigned int flags) +{ + CMS_ContentInfo *cms; + if (!cipher) { + CMSerr(CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT, CMS_R_NO_CIPHER); + return NULL; + } + cms = CMS_ContentInfo_new(); + if (cms == NULL) + return NULL; + if (!CMS_EncryptedData_set1_key(cms, cipher, key, keylen)) + return NULL; + + if (!(flags & CMS_DETACHED)) + CMS_set_detached(cms, 0); + + if ((flags & (CMS_STREAM | CMS_PARTIAL)) + || CMS_final(cms, in, NULL, flags)) + return cms; + + CMS_ContentInfo_free(cms); + return NULL; +} + +static int cms_signerinfo_verify_cert(CMS_SignerInfo *si, + X509_STORE *store, + STACK_OF(X509) *certs, + STACK_OF(X509_CRL) *crls) +{ + X509_STORE_CTX *ctx = X509_STORE_CTX_new(); + X509 *signer; + int i, j, r = 0; + + if (ctx == NULL) { + CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT, ERR_R_MALLOC_FAILURE); + goto err; + } + CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL); + if (!X509_STORE_CTX_init(ctx, store, signer, certs)) { + CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT, CMS_R_STORE_INIT_ERROR); + goto err; + } + X509_STORE_CTX_set_default(ctx, "smime_sign"); + if (crls) + X509_STORE_CTX_set0_crls(ctx, crls); + + i = X509_verify_cert(ctx); + if (i <= 0) { + j = X509_STORE_CTX_get_error(ctx); + CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT, + CMS_R_CERTIFICATE_VERIFY_ERROR); + ERR_add_error_data(2, "Verify error:", + X509_verify_cert_error_string(j)); + goto err; + } + r = 1; + err: + X509_STORE_CTX_free(ctx); + return r; + +} + +int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs, + X509_STORE *store, BIO *dcont, BIO *out, unsigned int flags) +{ + CMS_SignerInfo *si; + STACK_OF(CMS_SignerInfo) *sinfos; + STACK_OF(X509) *cms_certs = NULL; + STACK_OF(X509_CRL) *crls = NULL; + X509 *signer; + int i, scount = 0, ret = 0; + BIO *cmsbio = NULL, *tmpin = NULL, *tmpout = NULL; + + if (!dcont && !check_content(cms)) + return 0; + if (dcont && !(flags & CMS_BINARY)) { + const ASN1_OBJECT *coid = CMS_get0_eContentType(cms); + if (OBJ_obj2nid(coid) == NID_id_ct_asciiTextWithCRLF) + flags |= CMS_ASCIICRLF; + } + + /* Attempt to find all signer certificates */ + + sinfos = CMS_get0_SignerInfos(cms); + + if (sk_CMS_SignerInfo_num(sinfos) <= 0) { + CMSerr(CMS_F_CMS_VERIFY, CMS_R_NO_SIGNERS); + goto err; + } + + for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) { + si = sk_CMS_SignerInfo_value(sinfos, i); + CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL); + if (signer) + scount++; + } + + if (scount != sk_CMS_SignerInfo_num(sinfos)) + scount += CMS_set1_signers_certs(cms, certs, flags); + + if (scount != sk_CMS_SignerInfo_num(sinfos)) { + CMSerr(CMS_F_CMS_VERIFY, CMS_R_SIGNER_CERTIFICATE_NOT_FOUND); + goto err; + } + + /* Attempt to verify all signers certs */ + + if (!(flags & CMS_NO_SIGNER_CERT_VERIFY)) { + cms_certs = CMS_get1_certs(cms); + if (!(flags & CMS_NOCRL)) + crls = CMS_get1_crls(cms); + for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) { + si = sk_CMS_SignerInfo_value(sinfos, i); + if (!cms_signerinfo_verify_cert(si, store, cms_certs, crls)) + goto err; + } + } + + /* Attempt to verify all SignerInfo signed attribute signatures */ + + if (!(flags & CMS_NO_ATTR_VERIFY)) { + for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) { + si = sk_CMS_SignerInfo_value(sinfos, i); + if (CMS_signed_get_attr_count(si) < 0) + continue; + if (CMS_SignerInfo_verify(si) <= 0) + goto err; + } + } + + /* + * Performance optimization: if the content is a memory BIO then store + * its contents in a temporary read only memory BIO. This avoids + * potentially large numbers of slow copies of data which will occur when + * reading from a read write memory BIO when signatures are calculated. + */ + + if (dcont && (BIO_method_type(dcont) == BIO_TYPE_MEM)) { + char *ptr; + long len; + len = BIO_get_mem_data(dcont, &ptr); + tmpin = BIO_new_mem_buf(ptr, len); + if (tmpin == NULL) { + CMSerr(CMS_F_CMS_VERIFY, ERR_R_MALLOC_FAILURE); + goto err2; + } + } else + tmpin = dcont; + /* + * If not binary mode and detached generate digests by *writing* through + * the BIO. That makes it possible to canonicalise the input. + */ + if (!(flags & SMIME_BINARY) && dcont) { + /* + * Create output BIO so we can either handle text or to ensure + * included content doesn't override detached content. + */ + tmpout = cms_get_text_bio(out, flags); + if (!tmpout) { + CMSerr(CMS_F_CMS_VERIFY, ERR_R_MALLOC_FAILURE); + goto err; + } + cmsbio = CMS_dataInit(cms, tmpout); + if (!cmsbio) + goto err; + /* + * Don't use SMIME_TEXT for verify: it adds headers and we want to + * remove them. + */ + SMIME_crlf_copy(dcont, cmsbio, flags & ~SMIME_TEXT); + + if (flags & CMS_TEXT) { + if (!SMIME_text(tmpout, out)) { + CMSerr(CMS_F_CMS_VERIFY, CMS_R_SMIME_TEXT_ERROR); + goto err; + } + } + } else { + cmsbio = CMS_dataInit(cms, tmpin); + if (!cmsbio) + goto err; + + if (!cms_copy_content(out, cmsbio, flags)) + goto err; + + } + if (!(flags & CMS_NO_CONTENT_VERIFY)) { + for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) { + si = sk_CMS_SignerInfo_value(sinfos, i); + if (CMS_SignerInfo_verify_content(si, cmsbio) <= 0) { + CMSerr(CMS_F_CMS_VERIFY, CMS_R_CONTENT_VERIFY_ERROR); + goto err; + } + } + } + + ret = 1; + + err: + if (!(flags & SMIME_BINARY) && dcont) { + do_free_upto(cmsbio, tmpout); + if (tmpin != dcont) + BIO_free(tmpin); + } else { + if (dcont && (tmpin == dcont)) + do_free_upto(cmsbio, dcont); + else + BIO_free_all(cmsbio); + } + + if (out != tmpout) + BIO_free_all(tmpout); + + err2: + sk_X509_pop_free(cms_certs, X509_free); + sk_X509_CRL_pop_free(crls, X509_CRL_free); + + return ret; +} + +int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms, + STACK_OF(X509) *certs, + X509_STORE *store, unsigned int flags) +{ + int r; + flags &= ~(CMS_DETACHED | CMS_TEXT); + r = CMS_verify(rcms, certs, store, NULL, NULL, flags); + if (r <= 0) + return r; + return cms_Receipt_verify(rcms, ocms); +} + +CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, + STACK_OF(X509) *certs, BIO *data, + unsigned int flags) +{ + CMS_ContentInfo *cms; + int i; + + cms = CMS_ContentInfo_new(); + if (cms == NULL || !CMS_SignedData_init(cms)) + goto merr; + if (flags & CMS_ASCIICRLF + && !CMS_set1_eContentType(cms, + OBJ_nid2obj(NID_id_ct_asciiTextWithCRLF))) + goto err; + + if (pkey && !CMS_add1_signer(cms, signcert, pkey, NULL, flags)) { + CMSerr(CMS_F_CMS_SIGN, CMS_R_ADD_SIGNER_ERROR); + goto err; + } + + for (i = 0; i < sk_X509_num(certs); i++) { + X509 *x = sk_X509_value(certs, i); + if (!CMS_add1_cert(cms, x)) + goto merr; + } + + if (!(flags & CMS_DETACHED)) + CMS_set_detached(cms, 0); + + if ((flags & (CMS_STREAM | CMS_PARTIAL)) + || CMS_final(cms, data, NULL, flags)) + return cms; + else + goto err; + + merr: + CMSerr(CMS_F_CMS_SIGN, ERR_R_MALLOC_FAILURE); + + err: + CMS_ContentInfo_free(cms); + return NULL; +} + +CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si, + X509 *signcert, EVP_PKEY *pkey, + STACK_OF(X509) *certs, unsigned int flags) +{ + CMS_SignerInfo *rct_si; + CMS_ContentInfo *cms = NULL; + ASN1_OCTET_STRING **pos, *os; + BIO *rct_cont = NULL; + int r = 0; + + flags &= ~(CMS_STREAM | CMS_TEXT); + /* Not really detached but avoids content being allocated */ + flags |= CMS_PARTIAL | CMS_BINARY | CMS_DETACHED; + if (!pkey || !signcert) { + CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_NO_KEY_OR_CERT); + return NULL; + } + + /* Initialize signed data */ + + cms = CMS_sign(NULL, NULL, certs, NULL, flags); + if (!cms) + goto err; + + /* Set inner content type to signed receipt */ + if (!CMS_set1_eContentType(cms, OBJ_nid2obj(NID_id_smime_ct_receipt))) + goto err; + + rct_si = CMS_add1_signer(cms, signcert, pkey, NULL, flags); + if (!rct_si) { + CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_ADD_SIGNER_ERROR); + goto err; + } + + os = cms_encode_Receipt(si); + + if (!os) + goto err; + + /* Set content to digest */ + rct_cont = BIO_new_mem_buf(os->data, os->length); + if (!rct_cont) + goto err; + + /* Add msgSigDigest attribute */ + + if (!cms_msgSigDigest_add1(rct_si, si)) + goto err; + + /* Finalize structure */ + if (!CMS_final(cms, rct_cont, NULL, flags)) + goto err; + + /* Set embedded content */ + pos = CMS_get0_content(cms); + *pos = os; + + r = 1; + + err: + BIO_free(rct_cont); + if (r) + return cms; + CMS_ContentInfo_free(cms); + return NULL; + +} + +CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *data, + const EVP_CIPHER *cipher, unsigned int flags) +{ + CMS_ContentInfo *cms; + int i; + X509 *recip; + cms = CMS_EnvelopedData_create(cipher); + if (!cms) + goto merr; + for (i = 0; i < sk_X509_num(certs); i++) { + recip = sk_X509_value(certs, i); + if (!CMS_add1_recipient_cert(cms, recip, flags)) { + CMSerr(CMS_F_CMS_ENCRYPT, CMS_R_RECIPIENT_ERROR); + goto err; + } + } + + if (!(flags & CMS_DETACHED)) + CMS_set_detached(cms, 0); + + if ((flags & (CMS_STREAM | CMS_PARTIAL)) + || CMS_final(cms, data, NULL, flags)) + return cms; + else + goto err; + + merr: + CMSerr(CMS_F_CMS_ENCRYPT, ERR_R_MALLOC_FAILURE); + err: + CMS_ContentInfo_free(cms); + return NULL; +} + +static int cms_kari_set1_pkey(CMS_ContentInfo *cms, CMS_RecipientInfo *ri, + EVP_PKEY *pk, X509 *cert) +{ + int i; + STACK_OF(CMS_RecipientEncryptedKey) *reks; + CMS_RecipientEncryptedKey *rek; + reks = CMS_RecipientInfo_kari_get0_reks(ri); + for (i = 0; i < sk_CMS_RecipientEncryptedKey_num(reks); i++) { + int rv; + rek = sk_CMS_RecipientEncryptedKey_value(reks, i); + if (cert != NULL && CMS_RecipientEncryptedKey_cert_cmp(rek, cert)) + continue; + CMS_RecipientInfo_kari_set0_pkey(ri, pk); + rv = CMS_RecipientInfo_kari_decrypt(cms, ri, rek); + CMS_RecipientInfo_kari_set0_pkey(ri, NULL); + if (rv > 0) + return 1; + return cert == NULL ? 0 : -1; + } + return 0; +} + +int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert) +{ + STACK_OF(CMS_RecipientInfo) *ris; + CMS_RecipientInfo *ri; + int i, r, ri_type; + int debug = 0, match_ri = 0; + ris = CMS_get0_RecipientInfos(cms); + if (ris) + debug = cms->d.envelopedData->encryptedContentInfo->debug; + ri_type = cms_pkey_get_ri_type(pk); + if (ri_type == CMS_RECIPINFO_NONE) { + CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, + CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); + return 0; + } + + for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) { + ri = sk_CMS_RecipientInfo_value(ris, i); + if (CMS_RecipientInfo_type(ri) != ri_type) + continue; + match_ri = 1; + if (ri_type == CMS_RECIPINFO_AGREE) { + r = cms_kari_set1_pkey(cms, ri, pk, cert); + if (r > 0) + return 1; + if (r < 0) + return 0; + } + /* + * If we have a cert try matching RecipientInfo otherwise try them + * all. + */ + else if (!cert || !CMS_RecipientInfo_ktri_cert_cmp(ri, cert)) { + EVP_PKEY_up_ref(pk); + CMS_RecipientInfo_set0_pkey(ri, pk); + r = CMS_RecipientInfo_decrypt(cms, ri); + CMS_RecipientInfo_set0_pkey(ri, NULL); + if (cert) { + /* + * If not debugging clear any error and return success to + * avoid leaking of information useful to MMA + */ + if (!debug) { + ERR_clear_error(); + return 1; + } + if (r > 0) + return 1; + CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_DECRYPT_ERROR); + return 0; + } + /* + * If no cert and not debugging don't leave loop after first + * successful decrypt. Always attempt to decrypt all recipients + * to avoid leaking timing of a successful decrypt. + */ + else if (r > 0 && debug) + return 1; + } + } + /* If no cert, key transport and not debugging always return success */ + if (cert == NULL && ri_type == CMS_RECIPINFO_TRANS && match_ri && !debug) { + ERR_clear_error(); + return 1; + } + + CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_NO_MATCHING_RECIPIENT); + return 0; + +} + +int CMS_decrypt_set1_key(CMS_ContentInfo *cms, + unsigned char *key, size_t keylen, + const unsigned char *id, size_t idlen) +{ + STACK_OF(CMS_RecipientInfo) *ris; + CMS_RecipientInfo *ri; + int i, r; + ris = CMS_get0_RecipientInfos(cms); + for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) { + ri = sk_CMS_RecipientInfo_value(ris, i); + if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_KEK) + continue; + + /* + * If we have an id try matching RecipientInfo otherwise try them + * all. + */ + if (!id || (CMS_RecipientInfo_kekri_id_cmp(ri, id, idlen) == 0)) { + CMS_RecipientInfo_set0_key(ri, key, keylen); + r = CMS_RecipientInfo_decrypt(cms, ri); + CMS_RecipientInfo_set0_key(ri, NULL, 0); + if (r > 0) + return 1; + if (id) { + CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY, CMS_R_DECRYPT_ERROR); + return 0; + } + ERR_clear_error(); + } + } + + CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY, CMS_R_NO_MATCHING_RECIPIENT); + return 0; + +} + +int CMS_decrypt_set1_password(CMS_ContentInfo *cms, + unsigned char *pass, ossl_ssize_t passlen) +{ + STACK_OF(CMS_RecipientInfo) *ris; + CMS_RecipientInfo *ri; + int i, r; + ris = CMS_get0_RecipientInfos(cms); + for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) { + ri = sk_CMS_RecipientInfo_value(ris, i); + if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_PASS) + continue; + CMS_RecipientInfo_set0_password(ri, pass, passlen); + r = CMS_RecipientInfo_decrypt(cms, ri); + CMS_RecipientInfo_set0_password(ri, NULL, 0); + if (r > 0) + return 1; + } + + CMSerr(CMS_F_CMS_DECRYPT_SET1_PASSWORD, CMS_R_NO_MATCHING_RECIPIENT); + return 0; + +} + +int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert, + BIO *dcont, BIO *out, unsigned int flags) +{ + int r; + BIO *cont; + if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_enveloped) { + CMSerr(CMS_F_CMS_DECRYPT, CMS_R_TYPE_NOT_ENVELOPED_DATA); + return 0; + } + if (!dcont && !check_content(cms)) + return 0; + if (flags & CMS_DEBUG_DECRYPT) + cms->d.envelopedData->encryptedContentInfo->debug = 1; + else + cms->d.envelopedData->encryptedContentInfo->debug = 0; + if (!pk && !cert && !dcont && !out) + return 1; + if (pk && !CMS_decrypt_set1_pkey(cms, pk, cert)) + return 0; + cont = CMS_dataInit(cms, dcont); + if (!cont) + return 0; + r = cms_copy_content(out, cont, flags); + do_free_upto(cont, dcont); + return r; +} + +int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, unsigned int flags) +{ + BIO *cmsbio; + int ret = 0; + + if ((cmsbio = CMS_dataInit(cms, dcont)) == NULL) { + CMSerr(CMS_F_CMS_FINAL, CMS_R_CMS_LIB); + return 0; + } + + SMIME_crlf_copy(data, cmsbio, flags); + + (void)BIO_flush(cmsbio); + + if (!CMS_dataFinal(cms, cmsbio)) { + CMSerr(CMS_F_CMS_FINAL, CMS_R_CMS_DATAFINAL_ERROR); + goto err; + } + + ret = 1; + + err: + do_free_upto(cmsbio, dcont); + + return ret; + +} + +#ifdef ZLIB + +int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out, + unsigned int flags) +{ + BIO *cont; + int r; + if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_id_smime_ct_compressedData) { + CMSerr(CMS_F_CMS_UNCOMPRESS, CMS_R_TYPE_NOT_COMPRESSED_DATA); + return 0; + } + + if (!dcont && !check_content(cms)) + return 0; + + cont = CMS_dataInit(cms, dcont); + if (!cont) + return 0; + r = cms_copy_content(out, cont, flags); + do_free_upto(cont, dcont); + return r; +} + +CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags) +{ + CMS_ContentInfo *cms; + if (comp_nid <= 0) + comp_nid = NID_zlib_compression; + cms = cms_CompressedData_create(comp_nid); + if (!cms) + return NULL; + + if (!(flags & CMS_DETACHED)) + CMS_set_detached(cms, 0); + + if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags)) + return cms; + + CMS_ContentInfo_free(cms); + return NULL; +} + +#else + +int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out, + unsigned int flags) +{ + CMSerr(CMS_F_CMS_UNCOMPRESS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM); + return 0; +} + +CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags) +{ + CMSerr(CMS_F_CMS_COMPRESS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM); + return NULL; +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/comp/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/comp/build.info new file mode 100644 index 000000000..65df46a17 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/comp/build.info @@ -0,0 +1,4 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]= \ + comp_lib.c comp_err.c \ + c_zlib.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/comp/c_zlib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/comp/c_zlib.c new file mode 100644 index 000000000..d688deee5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/comp/c_zlib.c @@ -0,0 +1,618 @@ +/* + * Copyright 1998-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include "internal/comp.h" +#include +#include "internal/cryptlib_int.h" +#include "internal/bio.h" +#include "comp_lcl.h" + +COMP_METHOD *COMP_zlib(void); + +static COMP_METHOD zlib_method_nozlib = { + NID_undef, + "(undef)", + NULL, + NULL, + NULL, + NULL, +}; + +#ifndef ZLIB +# undef ZLIB_SHARED +#else + +# include + +static int zlib_stateful_init(COMP_CTX *ctx); +static void zlib_stateful_finish(COMP_CTX *ctx); +static int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out, + unsigned int olen, unsigned char *in, + unsigned int ilen); +static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out, + unsigned int olen, unsigned char *in, + unsigned int ilen); + +/* memory allocations functions for zlib initialisation */ +static void *zlib_zalloc(void *opaque, unsigned int no, unsigned int size) +{ + void *p; + + p = OPENSSL_zalloc(no * size); + return p; +} + +static void zlib_zfree(void *opaque, void *address) +{ + OPENSSL_free(address); +} + + +static COMP_METHOD zlib_stateful_method = { + NID_zlib_compression, + LN_zlib_compression, + zlib_stateful_init, + zlib_stateful_finish, + zlib_stateful_compress_block, + zlib_stateful_expand_block +}; + +/* + * When OpenSSL is built on Windows, we do not want to require that + * the ZLIB.DLL be available in order for the OpenSSL DLLs to + * work. Therefore, all ZLIB routines are loaded at run time + * and we do not link to a .LIB file when ZLIB_SHARED is set. + */ +# if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) +# include +# endif /* !(OPENSSL_SYS_WINDOWS || + * OPENSSL_SYS_WIN32) */ + +# ifdef ZLIB_SHARED +# include "internal/dso.h" + +/* Function pointers */ +typedef int (*compress_ft) (Bytef *dest, uLongf * destLen, + const Bytef *source, uLong sourceLen); +typedef int (*inflateEnd_ft) (z_streamp strm); +typedef int (*inflate_ft) (z_streamp strm, int flush); +typedef int (*inflateInit__ft) (z_streamp strm, + const char *version, int stream_size); +typedef int (*deflateEnd_ft) (z_streamp strm); +typedef int (*deflate_ft) (z_streamp strm, int flush); +typedef int (*deflateInit__ft) (z_streamp strm, int level, + const char *version, int stream_size); +typedef const char *(*zError__ft) (int err); +static compress_ft p_compress = NULL; +static inflateEnd_ft p_inflateEnd = NULL; +static inflate_ft p_inflate = NULL; +static inflateInit__ft p_inflateInit_ = NULL; +static deflateEnd_ft p_deflateEnd = NULL; +static deflate_ft p_deflate = NULL; +static deflateInit__ft p_deflateInit_ = NULL; +static zError__ft p_zError = NULL; + +static int zlib_loaded = 0; /* only attempt to init func pts once */ +static DSO *zlib_dso = NULL; + +# define compress p_compress +# define inflateEnd p_inflateEnd +# define inflate p_inflate +# define inflateInit_ p_inflateInit_ +# define deflateEnd p_deflateEnd +# define deflate p_deflate +# define deflateInit_ p_deflateInit_ +# define zError p_zError +# endif /* ZLIB_SHARED */ + +struct zlib_state { + z_stream istream; + z_stream ostream; +}; + +static int zlib_stateful_init(COMP_CTX *ctx) +{ + int err; + struct zlib_state *state = OPENSSL_zalloc(sizeof(*state)); + + if (state == NULL) + goto err; + + state->istream.zalloc = zlib_zalloc; + state->istream.zfree = zlib_zfree; + state->istream.opaque = Z_NULL; + state->istream.next_in = Z_NULL; + state->istream.next_out = Z_NULL; + err = inflateInit_(&state->istream, ZLIB_VERSION, sizeof(z_stream)); + if (err != Z_OK) + goto err; + + state->ostream.zalloc = zlib_zalloc; + state->ostream.zfree = zlib_zfree; + state->ostream.opaque = Z_NULL; + state->ostream.next_in = Z_NULL; + state->ostream.next_out = Z_NULL; + err = deflateInit_(&state->ostream, Z_DEFAULT_COMPRESSION, + ZLIB_VERSION, sizeof(z_stream)); + if (err != Z_OK) + goto err; + + ctx->data = state; + return 1; + err: + OPENSSL_free(state); + return 0; +} + +static void zlib_stateful_finish(COMP_CTX *ctx) +{ + struct zlib_state *state = ctx->data; + inflateEnd(&state->istream); + deflateEnd(&state->ostream); + OPENSSL_free(state); +} + +static int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out, + unsigned int olen, unsigned char *in, + unsigned int ilen) +{ + int err = Z_OK; + struct zlib_state *state = ctx->data; + + if (state == NULL) + return -1; + + state->ostream.next_in = in; + state->ostream.avail_in = ilen; + state->ostream.next_out = out; + state->ostream.avail_out = olen; + if (ilen > 0) + err = deflate(&state->ostream, Z_SYNC_FLUSH); + if (err != Z_OK) + return -1; + return olen - state->ostream.avail_out; +} + +static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out, + unsigned int olen, unsigned char *in, + unsigned int ilen) +{ + int err = Z_OK; + struct zlib_state *state = ctx->data; + + if (state == NULL) + return 0; + + state->istream.next_in = in; + state->istream.avail_in = ilen; + state->istream.next_out = out; + state->istream.avail_out = olen; + if (ilen > 0) + err = inflate(&state->istream, Z_SYNC_FLUSH); + if (err != Z_OK) + return -1; + return olen - state->istream.avail_out; +} + +#endif + +COMP_METHOD *COMP_zlib(void) +{ + COMP_METHOD *meth = &zlib_method_nozlib; + +#ifdef ZLIB_SHARED + /* LIBZ may be externally defined, and we should respect that value */ +# ifndef LIBZ +# if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) +# define LIBZ "ZLIB1" +# elif defined(OPENSSL_SYS_VMS) +# define LIBZ "LIBZ" +# else +# define LIBZ "z" +# endif +# endif + + if (!zlib_loaded) { + zlib_dso = DSO_load(NULL, LIBZ, NULL, 0); + if (zlib_dso != NULL) { + p_compress = (compress_ft) DSO_bind_func(zlib_dso, "compress"); + p_inflateEnd + = (inflateEnd_ft) DSO_bind_func(zlib_dso, "inflateEnd"); + p_inflate = (inflate_ft) DSO_bind_func(zlib_dso, "inflate"); + p_inflateInit_ + = (inflateInit__ft) DSO_bind_func(zlib_dso, "inflateInit_"); + p_deflateEnd + = (deflateEnd_ft) DSO_bind_func(zlib_dso, "deflateEnd"); + p_deflate = (deflate_ft) DSO_bind_func(zlib_dso, "deflate"); + p_deflateInit_ + = (deflateInit__ft) DSO_bind_func(zlib_dso, "deflateInit_"); + p_zError = (zError__ft) DSO_bind_func(zlib_dso, "zError"); + + if (p_compress && p_inflateEnd && p_inflate + && p_inflateInit_ && p_deflateEnd + && p_deflate && p_deflateInit_ && p_zError) + zlib_loaded++; + + if (!OPENSSL_init_crypto(OPENSSL_INIT_ZLIB, NULL)) { + comp_zlib_cleanup_int(); + return meth; + } + if (zlib_loaded) + meth = &zlib_stateful_method; + } + } +#endif +#if defined(ZLIB) + meth = &zlib_stateful_method; +#endif + + return meth; +} + +void comp_zlib_cleanup_int(void) +{ +#ifdef ZLIB_SHARED + DSO_free(zlib_dso); + zlib_dso = NULL; +#endif +} + +#ifdef ZLIB + +/* Zlib based compression/decompression filter BIO */ + +typedef struct { + unsigned char *ibuf; /* Input buffer */ + int ibufsize; /* Buffer size */ + z_stream zin; /* Input decompress context */ + unsigned char *obuf; /* Output buffer */ + int obufsize; /* Output buffer size */ + unsigned char *optr; /* Position in output buffer */ + int ocount; /* Amount of data in output buffer */ + int odone; /* deflate EOF */ + int comp_level; /* Compression level to use */ + z_stream zout; /* Output compression context */ +} BIO_ZLIB_CTX; + +# define ZLIB_DEFAULT_BUFSIZE 1024 + +static int bio_zlib_new(BIO *bi); +static int bio_zlib_free(BIO *bi); +static int bio_zlib_read(BIO *b, char *out, int outl); +static int bio_zlib_write(BIO *b, const char *in, int inl); +static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr); +static long bio_zlib_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp); + +static const BIO_METHOD bio_meth_zlib = { + BIO_TYPE_COMP, + "zlib", + /* TODO: Convert to new style write function */ + bwrite_conv, + bio_zlib_write, + /* TODO: Convert to new style read function */ + bread_conv, + bio_zlib_read, + NULL, /* bio_zlib_puts, */ + NULL, /* bio_zlib_gets, */ + bio_zlib_ctrl, + bio_zlib_new, + bio_zlib_free, + bio_zlib_callback_ctrl +}; + +const BIO_METHOD *BIO_f_zlib(void) +{ + return &bio_meth_zlib; +} + +static int bio_zlib_new(BIO *bi) +{ + BIO_ZLIB_CTX *ctx; +# ifdef ZLIB_SHARED + (void)COMP_zlib(); + if (!zlib_loaded) { + COMPerr(COMP_F_BIO_ZLIB_NEW, COMP_R_ZLIB_NOT_SUPPORTED); + return 0; + } +# endif + ctx = OPENSSL_zalloc(sizeof(*ctx)); + if (ctx == NULL) { + COMPerr(COMP_F_BIO_ZLIB_NEW, ERR_R_MALLOC_FAILURE); + return 0; + } + ctx->ibufsize = ZLIB_DEFAULT_BUFSIZE; + ctx->obufsize = ZLIB_DEFAULT_BUFSIZE; + ctx->zin.zalloc = Z_NULL; + ctx->zin.zfree = Z_NULL; + ctx->zout.zalloc = Z_NULL; + ctx->zout.zfree = Z_NULL; + ctx->comp_level = Z_DEFAULT_COMPRESSION; + BIO_set_init(bi, 1); + BIO_set_data(bi, ctx); + + return 1; +} + +static int bio_zlib_free(BIO *bi) +{ + BIO_ZLIB_CTX *ctx; + if (!bi) + return 0; + ctx = BIO_get_data(bi); + if (ctx->ibuf) { + /* Destroy decompress context */ + inflateEnd(&ctx->zin); + OPENSSL_free(ctx->ibuf); + } + if (ctx->obuf) { + /* Destroy compress context */ + deflateEnd(&ctx->zout); + OPENSSL_free(ctx->obuf); + } + OPENSSL_free(ctx); + BIO_set_data(bi, NULL); + BIO_set_init(bi, 0); + + return 1; +} + +static int bio_zlib_read(BIO *b, char *out, int outl) +{ + BIO_ZLIB_CTX *ctx; + int ret; + z_stream *zin; + BIO *next = BIO_next(b); + + if (!out || !outl) + return 0; + ctx = BIO_get_data(b); + zin = &ctx->zin; + BIO_clear_retry_flags(b); + if (!ctx->ibuf) { + ctx->ibuf = OPENSSL_malloc(ctx->ibufsize); + if (ctx->ibuf == NULL) { + COMPerr(COMP_F_BIO_ZLIB_READ, ERR_R_MALLOC_FAILURE); + return 0; + } + inflateInit(zin); + zin->next_in = ctx->ibuf; + zin->avail_in = 0; + } + + /* Copy output data directly to supplied buffer */ + zin->next_out = (unsigned char *)out; + zin->avail_out = (unsigned int)outl; + for (;;) { + /* Decompress while data available */ + while (zin->avail_in) { + ret = inflate(zin, 0); + if ((ret != Z_OK) && (ret != Z_STREAM_END)) { + COMPerr(COMP_F_BIO_ZLIB_READ, COMP_R_ZLIB_INFLATE_ERROR); + ERR_add_error_data(2, "zlib error:", zError(ret)); + return 0; + } + /* If EOF or we've read everything then return */ + if ((ret == Z_STREAM_END) || !zin->avail_out) + return outl - zin->avail_out; + } + + /* + * No data in input buffer try to read some in, if an error then + * return the total data read. + */ + ret = BIO_read(next, ctx->ibuf, ctx->ibufsize); + if (ret <= 0) { + /* Total data read */ + int tot = outl - zin->avail_out; + BIO_copy_next_retry(b); + if (ret < 0) + return (tot > 0) ? tot : ret; + return tot; + } + zin->avail_in = ret; + zin->next_in = ctx->ibuf; + } +} + +static int bio_zlib_write(BIO *b, const char *in, int inl) +{ + BIO_ZLIB_CTX *ctx; + int ret; + z_stream *zout; + BIO *next = BIO_next(b); + + if (!in || !inl) + return 0; + ctx = BIO_get_data(b); + if (ctx->odone) + return 0; + zout = &ctx->zout; + BIO_clear_retry_flags(b); + if (!ctx->obuf) { + ctx->obuf = OPENSSL_malloc(ctx->obufsize); + /* Need error here */ + if (ctx->obuf == NULL) { + COMPerr(COMP_F_BIO_ZLIB_WRITE, ERR_R_MALLOC_FAILURE); + return 0; + } + ctx->optr = ctx->obuf; + ctx->ocount = 0; + deflateInit(zout, ctx->comp_level); + zout->next_out = ctx->obuf; + zout->avail_out = ctx->obufsize; + } + /* Obtain input data directly from supplied buffer */ + zout->next_in = (void *)in; + zout->avail_in = inl; + for (;;) { + /* If data in output buffer write it first */ + while (ctx->ocount) { + ret = BIO_write(next, ctx->optr, ctx->ocount); + if (ret <= 0) { + /* Total data written */ + int tot = inl - zout->avail_in; + BIO_copy_next_retry(b); + if (ret < 0) + return (tot > 0) ? tot : ret; + return tot; + } + ctx->optr += ret; + ctx->ocount -= ret; + } + + /* Have we consumed all supplied data? */ + if (!zout->avail_in) + return inl; + + /* Compress some more */ + + /* Reset buffer */ + ctx->optr = ctx->obuf; + zout->next_out = ctx->obuf; + zout->avail_out = ctx->obufsize; + /* Compress some more */ + ret = deflate(zout, 0); + if (ret != Z_OK) { + COMPerr(COMP_F_BIO_ZLIB_WRITE, COMP_R_ZLIB_DEFLATE_ERROR); + ERR_add_error_data(2, "zlib error:", zError(ret)); + return 0; + } + ctx->ocount = ctx->obufsize - zout->avail_out; + } +} + +static int bio_zlib_flush(BIO *b) +{ + BIO_ZLIB_CTX *ctx; + int ret; + z_stream *zout; + BIO *next = BIO_next(b); + + ctx = BIO_get_data(b); + /* If no data written or already flush show success */ + if (!ctx->obuf || (ctx->odone && !ctx->ocount)) + return 1; + zout = &ctx->zout; + BIO_clear_retry_flags(b); + /* No more input data */ + zout->next_in = NULL; + zout->avail_in = 0; + for (;;) { + /* If data in output buffer write it first */ + while (ctx->ocount) { + ret = BIO_write(next, ctx->optr, ctx->ocount); + if (ret <= 0) { + BIO_copy_next_retry(b); + return ret; + } + ctx->optr += ret; + ctx->ocount -= ret; + } + if (ctx->odone) + return 1; + + /* Compress some more */ + + /* Reset buffer */ + ctx->optr = ctx->obuf; + zout->next_out = ctx->obuf; + zout->avail_out = ctx->obufsize; + /* Compress some more */ + ret = deflate(zout, Z_FINISH); + if (ret == Z_STREAM_END) + ctx->odone = 1; + else if (ret != Z_OK) { + COMPerr(COMP_F_BIO_ZLIB_FLUSH, COMP_R_ZLIB_DEFLATE_ERROR); + ERR_add_error_data(2, "zlib error:", zError(ret)); + return 0; + } + ctx->ocount = ctx->obufsize - zout->avail_out; + } +} + +static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + BIO_ZLIB_CTX *ctx; + int ret, *ip; + int ibs, obs; + BIO *next = BIO_next(b); + + if (next == NULL) + return 0; + ctx = BIO_get_data(b); + switch (cmd) { + + case BIO_CTRL_RESET: + ctx->ocount = 0; + ctx->odone = 0; + ret = 1; + break; + + case BIO_CTRL_FLUSH: + ret = bio_zlib_flush(b); + if (ret > 0) + ret = BIO_flush(next); + break; + + case BIO_C_SET_BUFF_SIZE: + ibs = -1; + obs = -1; + if (ptr != NULL) { + ip = ptr; + if (*ip == 0) + ibs = (int)num; + else + obs = (int)num; + } else { + ibs = (int)num; + obs = ibs; + } + + if (ibs != -1) { + OPENSSL_free(ctx->ibuf); + ctx->ibuf = NULL; + ctx->ibufsize = ibs; + } + + if (obs != -1) { + OPENSSL_free(ctx->obuf); + ctx->obuf = NULL; + ctx->obufsize = obs; + } + ret = 1; + break; + + case BIO_C_DO_STATE_MACHINE: + BIO_clear_retry_flags(b); + ret = BIO_ctrl(next, cmd, num, ptr); + BIO_copy_next_retry(b); + break; + + default: + ret = BIO_ctrl(next, cmd, num, ptr); + break; + + } + + return ret; +} + +static long bio_zlib_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) +{ + BIO *next = BIO_next(b); + if (next == NULL) + return 0; + return BIO_callback_ctrl(next, cmd, fp); +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/comp/comp_err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/comp/comp_err.c new file mode 100644 index 000000000..2dca315cf --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/comp/comp_err.c @@ -0,0 +1,46 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA COMP_str_functs[] = { + {ERR_PACK(ERR_LIB_COMP, COMP_F_BIO_ZLIB_FLUSH, 0), "bio_zlib_flush"}, + {ERR_PACK(ERR_LIB_COMP, COMP_F_BIO_ZLIB_NEW, 0), "bio_zlib_new"}, + {ERR_PACK(ERR_LIB_COMP, COMP_F_BIO_ZLIB_READ, 0), "bio_zlib_read"}, + {ERR_PACK(ERR_LIB_COMP, COMP_F_BIO_ZLIB_WRITE, 0), "bio_zlib_write"}, + {ERR_PACK(ERR_LIB_COMP, COMP_F_COMP_CTX_NEW, 0), "COMP_CTX_new"}, + {0, NULL} +}; + +static const ERR_STRING_DATA COMP_str_reasons[] = { + {ERR_PACK(ERR_LIB_COMP, 0, COMP_R_ZLIB_DEFLATE_ERROR), + "zlib deflate error"}, + {ERR_PACK(ERR_LIB_COMP, 0, COMP_R_ZLIB_INFLATE_ERROR), + "zlib inflate error"}, + {ERR_PACK(ERR_LIB_COMP, 0, COMP_R_ZLIB_NOT_SUPPORTED), + "zlib not supported"}, + {0, NULL} +}; + +#endif + +int ERR_load_COMP_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(COMP_str_functs[0].error) == NULL) { + ERR_load_strings_const(COMP_str_functs); + ERR_load_strings_const(COMP_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/comp/comp_lcl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/comp/comp_lcl.h new file mode 100644 index 000000000..aa45fca23 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/comp/comp_lcl.h @@ -0,0 +1,30 @@ +/* + * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +struct comp_method_st { + int type; /* NID for compression library */ + const char *name; /* A text string to identify the library */ + int (*init) (COMP_CTX *ctx); + void (*finish) (COMP_CTX *ctx); + int (*compress) (COMP_CTX *ctx, + unsigned char *out, unsigned int olen, + unsigned char *in, unsigned int ilen); + int (*expand) (COMP_CTX *ctx, + unsigned char *out, unsigned int olen, + unsigned char *in, unsigned int ilen); +}; + +struct comp_ctx_st { + struct comp_method_st *meth; + unsigned long compress_in; + unsigned long compress_out; + unsigned long expand_in; + unsigned long expand_out; + void* data; +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/comp/comp_lib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/comp/comp_lib.c new file mode 100644 index 000000000..6ae211449 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/comp/comp_lib.c @@ -0,0 +1,93 @@ +/* + * Copyright 1998-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include +#include "comp_lcl.h" + +COMP_CTX *COMP_CTX_new(COMP_METHOD *meth) +{ + COMP_CTX *ret; + + if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) { + COMPerr(COMP_F_COMP_CTX_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + ret->meth = meth; + if ((ret->meth->init != NULL) && !ret->meth->init(ret)) { + OPENSSL_free(ret); + ret = NULL; + } + return ret; +} + +const COMP_METHOD *COMP_CTX_get_method(const COMP_CTX *ctx) +{ + return ctx->meth; +} + +int COMP_get_type(const COMP_METHOD *meth) +{ + return meth->type; +} + +const char *COMP_get_name(const COMP_METHOD *meth) +{ + return meth->name; +} + +void COMP_CTX_free(COMP_CTX *ctx) +{ + if (ctx == NULL) + return; + if (ctx->meth->finish != NULL) + ctx->meth->finish(ctx); + + OPENSSL_free(ctx); +} + +int COMP_compress_block(COMP_CTX *ctx, unsigned char *out, int olen, + unsigned char *in, int ilen) +{ + int ret; + if (ctx->meth->compress == NULL) { + return -1; + } + ret = ctx->meth->compress(ctx, out, olen, in, ilen); + if (ret > 0) { + ctx->compress_in += ilen; + ctx->compress_out += ret; + } + return ret; +} + +int COMP_expand_block(COMP_CTX *ctx, unsigned char *out, int olen, + unsigned char *in, int ilen) +{ + int ret; + + if (ctx->meth->expand == NULL) { + return -1; + } + ret = ctx->meth->expand(ctx, out, olen, in, ilen); + if (ret > 0) { + ctx->expand_in += ilen; + ctx->expand_out += ret; + } + return ret; +} + +int COMP_CTX_get_type(const COMP_CTX* comp) +{ + return comp->meth ? comp->meth->type : NID_undef; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/conf/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/conf/build.info new file mode 100644 index 000000000..ff367994e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/conf/build.info @@ -0,0 +1,4 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]= \ + conf_err.c conf_lib.c conf_api.c conf_def.c conf_mod.c \ + conf_mall.c conf_sap.c conf_ssl.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_api.c b/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_api.c new file mode 100644 index 000000000..5e57d749c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_api.c @@ -0,0 +1,218 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Part of the code in here was originally in conf.c, which is now removed */ + +#include "e_os.h" +#include "internal/cryptlib.h" +#include +#include +#include +#include + +static void value_free_hash(const CONF_VALUE *a, LHASH_OF(CONF_VALUE) *conf); +static void value_free_stack_doall(CONF_VALUE *a); + +/* Up until OpenSSL 0.9.5a, this was get_section */ +CONF_VALUE *_CONF_get_section(const CONF *conf, const char *section) +{ + CONF_VALUE *v, vv; + + if ((conf == NULL) || (section == NULL)) + return NULL; + vv.name = NULL; + vv.section = (char *)section; + v = lh_CONF_VALUE_retrieve(conf->data, &vv); + return v; +} + +/* Up until OpenSSL 0.9.5a, this was CONF_get_section */ +STACK_OF(CONF_VALUE) *_CONF_get_section_values(const CONF *conf, + const char *section) +{ + CONF_VALUE *v; + + v = _CONF_get_section(conf, section); + if (v != NULL) + return ((STACK_OF(CONF_VALUE) *)v->value); + else + return NULL; +} + +int _CONF_add_string(CONF *conf, CONF_VALUE *section, CONF_VALUE *value) +{ + CONF_VALUE *v = NULL; + STACK_OF(CONF_VALUE) *ts; + + ts = (STACK_OF(CONF_VALUE) *)section->value; + + value->section = section->section; + if (!sk_CONF_VALUE_push(ts, value)) { + return 0; + } + + v = lh_CONF_VALUE_insert(conf->data, value); + if (v != NULL) { + (void)sk_CONF_VALUE_delete_ptr(ts, v); + OPENSSL_free(v->name); + OPENSSL_free(v->value); + OPENSSL_free(v); + } + return 1; +} + +char *_CONF_get_string(const CONF *conf, const char *section, + const char *name) +{ + CONF_VALUE *v, vv; + char *p; + + if (name == NULL) + return NULL; + if (conf != NULL) { + if (section != NULL) { + vv.name = (char *)name; + vv.section = (char *)section; + v = lh_CONF_VALUE_retrieve(conf->data, &vv); + if (v != NULL) + return v->value; + if (strcmp(section, "ENV") == 0) { + p = ossl_safe_getenv(name); + if (p != NULL) + return p; + } + } + vv.section = "default"; + vv.name = (char *)name; + v = lh_CONF_VALUE_retrieve(conf->data, &vv); + if (v != NULL) + return v->value; + else + return NULL; + } else + return ossl_safe_getenv(name); +} + +static unsigned long conf_value_hash(const CONF_VALUE *v) +{ + return (OPENSSL_LH_strhash(v->section) << 2) ^ OPENSSL_LH_strhash(v->name); +} + +static int conf_value_cmp(const CONF_VALUE *a, const CONF_VALUE *b) +{ + int i; + + if (a->section != b->section) { + i = strcmp(a->section, b->section); + if (i) + return i; + } + + if ((a->name != NULL) && (b->name != NULL)) { + i = strcmp(a->name, b->name); + return i; + } else if (a->name == b->name) + return 0; + else + return ((a->name == NULL) ? -1 : 1); +} + +int _CONF_new_data(CONF *conf) +{ + if (conf == NULL) { + return 0; + } + if (conf->data == NULL) { + conf->data = lh_CONF_VALUE_new(conf_value_hash, conf_value_cmp); + if (conf->data == NULL) + return 0; + } + return 1; +} + +typedef LHASH_OF(CONF_VALUE) LH_CONF_VALUE; + +IMPLEMENT_LHASH_DOALL_ARG_CONST(CONF_VALUE, LH_CONF_VALUE); + +void _CONF_free_data(CONF *conf) +{ + if (conf == NULL || conf->data == NULL) + return; + + /* evil thing to make sure the 'OPENSSL_free()' works as expected */ + lh_CONF_VALUE_set_down_load(conf->data, 0); + lh_CONF_VALUE_doall_LH_CONF_VALUE(conf->data, value_free_hash, conf->data); + + /* + * We now have only 'section' entries in the hash table. Due to problems + * with + */ + + lh_CONF_VALUE_doall(conf->data, value_free_stack_doall); + lh_CONF_VALUE_free(conf->data); +} + +static void value_free_hash(const CONF_VALUE *a, LHASH_OF(CONF_VALUE) *conf) +{ + if (a->name != NULL) + (void)lh_CONF_VALUE_delete(conf, a); +} + +static void value_free_stack_doall(CONF_VALUE *a) +{ + CONF_VALUE *vv; + STACK_OF(CONF_VALUE) *sk; + int i; + + if (a->name != NULL) + return; + + sk = (STACK_OF(CONF_VALUE) *)a->value; + for (i = sk_CONF_VALUE_num(sk) - 1; i >= 0; i--) { + vv = sk_CONF_VALUE_value(sk, i); + OPENSSL_free(vv->value); + OPENSSL_free(vv->name); + OPENSSL_free(vv); + } + sk_CONF_VALUE_free(sk); + OPENSSL_free(a->section); + OPENSSL_free(a); +} + +/* Up until OpenSSL 0.9.5a, this was new_section */ +CONF_VALUE *_CONF_new_section(CONF *conf, const char *section) +{ + STACK_OF(CONF_VALUE) *sk = NULL; + int i; + CONF_VALUE *v = NULL, *vv; + + if ((sk = sk_CONF_VALUE_new_null()) == NULL) + goto err; + if ((v = OPENSSL_malloc(sizeof(*v))) == NULL) + goto err; + i = strlen(section) + 1; + if ((v->section = OPENSSL_malloc(i)) == NULL) + goto err; + + memcpy(v->section, section, i); + v->name = NULL; + v->value = (char *)sk; + + vv = lh_CONF_VALUE_insert(conf->data, v); + if (vv != NULL || lh_CONF_VALUE_error(conf->data) > 0) + goto err; + return v; + + err: + sk_CONF_VALUE_free(sk); + if (v != NULL) + OPENSSL_free(v->section); + OPENSSL_free(v); + return NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_def.c b/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_def.c new file mode 100644 index 000000000..8e3f42a0c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_def.c @@ -0,0 +1,878 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Part of the code in here was originally in conf.c, which is now removed */ + +#include +#include +#include "internal/cryptlib.h" +#include "internal/o_dir.h" +#include +#include +#include +#include "conf_def.h" +#include +#include +#ifndef OPENSSL_NO_POSIX_IO +# include +# ifdef _WIN32 +# define stat _stat +# define strcasecmp _stricmp +# endif +#endif + +#ifndef S_ISDIR +# define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR) +#endif + +/* + * The maximum length we can grow a value to after variable expansion. 64k + * should be more than enough for all reasonable uses. + */ +#define MAX_CONF_VALUE_LENGTH 65536 + +static int is_keytype(const CONF *conf, char c, unsigned short type); +static char *eat_ws(CONF *conf, char *p); +static void trim_ws(CONF *conf, char *start); +static char *eat_alpha_numeric(CONF *conf, char *p); +static void clear_comments(CONF *conf, char *p); +static int str_copy(CONF *conf, char *section, char **to, char *from); +static char *scan_quote(CONF *conf, char *p); +static char *scan_dquote(CONF *conf, char *p); +#define scan_esc(conf,p) (((IS_EOF((conf),(p)[1]))?((p)+1):((p)+2))) +#ifndef OPENSSL_NO_POSIX_IO +static BIO *process_include(char *include, OPENSSL_DIR_CTX **dirctx, + char **dirpath); +static BIO *get_next_file(const char *path, OPENSSL_DIR_CTX **dirctx); +#endif + +static CONF *def_create(CONF_METHOD *meth); +static int def_init_default(CONF *conf); +static int def_init_WIN32(CONF *conf); +static int def_destroy(CONF *conf); +static int def_destroy_data(CONF *conf); +static int def_load(CONF *conf, const char *name, long *eline); +static int def_load_bio(CONF *conf, BIO *bp, long *eline); +static int def_dump(const CONF *conf, BIO *bp); +static int def_is_number(const CONF *conf, char c); +static int def_to_int(const CONF *conf, char c); + +static CONF_METHOD default_method = { + "OpenSSL default", + def_create, + def_init_default, + def_destroy, + def_destroy_data, + def_load_bio, + def_dump, + def_is_number, + def_to_int, + def_load +}; + +static CONF_METHOD WIN32_method = { + "WIN32", + def_create, + def_init_WIN32, + def_destroy, + def_destroy_data, + def_load_bio, + def_dump, + def_is_number, + def_to_int, + def_load +}; + +CONF_METHOD *NCONF_default(void) +{ + return &default_method; +} + +CONF_METHOD *NCONF_WIN32(void) +{ + return &WIN32_method; +} + +static CONF *def_create(CONF_METHOD *meth) +{ + CONF *ret; + + ret = OPENSSL_malloc(sizeof(*ret)); + if (ret != NULL) + if (meth->init(ret) == 0) { + OPENSSL_free(ret); + ret = NULL; + } + return ret; +} + +static int def_init_default(CONF *conf) +{ + if (conf == NULL) + return 0; + + conf->meth = &default_method; + conf->meth_data = (void *)CONF_type_default; + conf->data = NULL; + + return 1; +} + +static int def_init_WIN32(CONF *conf) +{ + if (conf == NULL) + return 0; + + conf->meth = &WIN32_method; + conf->meth_data = (void *)CONF_type_win32; + conf->data = NULL; + + return 1; +} + +static int def_destroy(CONF *conf) +{ + if (def_destroy_data(conf)) { + OPENSSL_free(conf); + return 1; + } + return 0; +} + +static int def_destroy_data(CONF *conf) +{ + if (conf == NULL) + return 0; + _CONF_free_data(conf); + return 1; +} + +static int def_load(CONF *conf, const char *name, long *line) +{ + int ret; + BIO *in = NULL; + +#ifdef OPENSSL_SYS_VMS + in = BIO_new_file(name, "r"); +#else + in = BIO_new_file(name, "rb"); +#endif + if (in == NULL) { + if (ERR_GET_REASON(ERR_peek_last_error()) == BIO_R_NO_SUCH_FILE) + CONFerr(CONF_F_DEF_LOAD, CONF_R_NO_SUCH_FILE); + else + CONFerr(CONF_F_DEF_LOAD, ERR_R_SYS_LIB); + return 0; + } + + ret = def_load_bio(conf, in, line); + BIO_free(in); + + return ret; +} + +static int def_load_bio(CONF *conf, BIO *in, long *line) +{ +/* The macro BUFSIZE conflicts with a system macro in VxWorks */ +#define CONFBUFSIZE 512 + int bufnum = 0, i, ii; + BUF_MEM *buff = NULL; + char *s, *p, *end; + int again; + long eline = 0; + char btmp[DECIMAL_SIZE(eline) + 1]; + CONF_VALUE *v = NULL, *tv; + CONF_VALUE *sv = NULL; + char *section = NULL, *buf; + char *start, *psection, *pname; + void *h = (void *)(conf->data); + STACK_OF(BIO) *biosk = NULL; +#ifndef OPENSSL_NO_POSIX_IO + char *dirpath = NULL; + OPENSSL_DIR_CTX *dirctx = NULL; +#endif + + if ((buff = BUF_MEM_new()) == NULL) { + CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_BUF_LIB); + goto err; + } + + section = OPENSSL_strdup("default"); + if (section == NULL) { + CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (_CONF_new_data(conf) == 0) { + CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); + goto err; + } + + sv = _CONF_new_section(conf, section); + if (sv == NULL) { + CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_UNABLE_TO_CREATE_NEW_SECTION); + goto err; + } + + bufnum = 0; + again = 0; + for (;;) { + if (!BUF_MEM_grow(buff, bufnum + CONFBUFSIZE)) { + CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_BUF_LIB); + goto err; + } + p = &(buff->data[bufnum]); + *p = '\0'; + read_retry: + BIO_gets(in, p, CONFBUFSIZE - 1); + p[CONFBUFSIZE - 1] = '\0'; + ii = i = strlen(p); + if (i == 0 && !again) { + /* the currently processed BIO is at EOF */ + BIO *parent; + +#ifndef OPENSSL_NO_POSIX_IO + /* continue processing with the next file from directory */ + if (dirctx != NULL) { + BIO *next; + + if ((next = get_next_file(dirpath, &dirctx)) != NULL) { + BIO_vfree(in); + in = next; + goto read_retry; + } else { + OPENSSL_free(dirpath); + dirpath = NULL; + } + } +#endif + /* no more files in directory, continue with processing parent */ + if ((parent = sk_BIO_pop(biosk)) == NULL) { + /* everything processed get out of the loop */ + break; + } else { + BIO_vfree(in); + in = parent; + goto read_retry; + } + } + again = 0; + while (i > 0) { + if ((p[i - 1] != '\r') && (p[i - 1] != '\n')) + break; + else + i--; + } + /* + * we removed some trailing stuff so there is a new line on the end. + */ + if (ii && i == ii) + again = 1; /* long line */ + else { + p[i] = '\0'; + eline++; /* another input line */ + } + + /* we now have a line with trailing \r\n removed */ + + /* i is the number of bytes */ + bufnum += i; + + v = NULL; + /* check for line continuation */ + if (bufnum >= 1) { + /* + * If we have bytes and the last char '\\' and second last char + * is not '\\' + */ + p = &(buff->data[bufnum - 1]); + if (IS_ESC(conf, p[0]) && ((bufnum <= 1) || !IS_ESC(conf, p[-1]))) { + bufnum--; + again = 1; + } + } + if (again) + continue; + bufnum = 0; + buf = buff->data; + + clear_comments(conf, buf); + s = eat_ws(conf, buf); + if (IS_EOF(conf, *s)) + continue; /* blank line */ + if (*s == '[') { + char *ss; + + s++; + start = eat_ws(conf, s); + ss = start; + again: + end = eat_alpha_numeric(conf, ss); + p = eat_ws(conf, end); + if (*p != ']') { + if (*p != '\0' && ss != p) { + ss = p; + goto again; + } + CONFerr(CONF_F_DEF_LOAD_BIO, + CONF_R_MISSING_CLOSE_SQUARE_BRACKET); + goto err; + } + *end = '\0'; + if (!str_copy(conf, NULL, §ion, start)) + goto err; + if ((sv = _CONF_get_section(conf, section)) == NULL) + sv = _CONF_new_section(conf, section); + if (sv == NULL) { + CONFerr(CONF_F_DEF_LOAD_BIO, + CONF_R_UNABLE_TO_CREATE_NEW_SECTION); + goto err; + } + continue; + } else { + pname = s; + end = eat_alpha_numeric(conf, s); + if ((end[0] == ':') && (end[1] == ':')) { + *end = '\0'; + end += 2; + psection = pname; + pname = end; + end = eat_alpha_numeric(conf, end); + } else { + psection = section; + } + p = eat_ws(conf, end); + if (strncmp(pname, ".include", 8) == 0 + && (p != pname + 8 || *p == '=')) { + char *include = NULL; + BIO *next; + + if (*p == '=') { + p++; + p = eat_ws(conf, p); + } + trim_ws(conf, p); + if (!str_copy(conf, psection, &include, p)) + goto err; + /* get the BIO of the included file */ +#ifndef OPENSSL_NO_POSIX_IO + next = process_include(include, &dirctx, &dirpath); + if (include != dirpath) { + /* dirpath will contain include in case of a directory */ + OPENSSL_free(include); + } +#else + next = BIO_new_file(include, "r"); + OPENSSL_free(include); +#endif + if (next != NULL) { + /* push the currently processing BIO onto stack */ + if (biosk == NULL) { + if ((biosk = sk_BIO_new_null()) == NULL) { + CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); + goto err; + } + } + if (!sk_BIO_push(biosk, in)) { + CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); + goto err; + } + /* continue with reading from the included BIO */ + in = next; + } + continue; + } else if (*p != '=') { + CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_MISSING_EQUAL_SIGN); + goto err; + } + *end = '\0'; + p++; + start = eat_ws(conf, p); + trim_ws(conf, start); + + if ((v = OPENSSL_malloc(sizeof(*v))) == NULL) { + CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); + goto err; + } + v->name = OPENSSL_strdup(pname); + v->value = NULL; + if (v->name == NULL) { + CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!str_copy(conf, psection, &(v->value), start)) + goto err; + + if (strcmp(psection, section) != 0) { + if ((tv = _CONF_get_section(conf, psection)) + == NULL) + tv = _CONF_new_section(conf, psection); + if (tv == NULL) { + CONFerr(CONF_F_DEF_LOAD_BIO, + CONF_R_UNABLE_TO_CREATE_NEW_SECTION); + goto err; + } + } else + tv = sv; + if (_CONF_add_string(conf, tv, v) == 0) { + CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); + goto err; + } + v = NULL; + } + } + BUF_MEM_free(buff); + OPENSSL_free(section); + /* + * No need to pop, since we only get here if the stack is empty. + * If this causes a BIO leak, THE ISSUE IS SOMEWHERE ELSE! + */ + sk_BIO_free(biosk); + return 1; + err: + BUF_MEM_free(buff); + OPENSSL_free(section); + /* + * Since |in| is the first element of the stack and should NOT be freed + * here, we cannot use sk_BIO_pop_free(). Instead, we pop and free one + * BIO at a time, making sure that the last one popped isn't. + */ + while (sk_BIO_num(biosk) > 0) { + BIO *popped = sk_BIO_pop(biosk); + BIO_vfree(in); + in = popped; + } + sk_BIO_free(biosk); +#ifndef OPENSSL_NO_POSIX_IO + OPENSSL_free(dirpath); + if (dirctx != NULL) + OPENSSL_DIR_end(&dirctx); +#endif + if (line != NULL) + *line = eline; + BIO_snprintf(btmp, sizeof(btmp), "%ld", eline); + ERR_add_error_data(2, "line ", btmp); + if (h != conf->data) { + CONF_free(conf->data); + conf->data = NULL; + } + if (v != NULL) { + OPENSSL_free(v->name); + OPENSSL_free(v->value); + OPENSSL_free(v); + } + return 0; +} + +static void clear_comments(CONF *conf, char *p) +{ + for (;;) { + if (IS_FCOMMENT(conf, *p)) { + *p = '\0'; + return; + } + if (!IS_WS(conf, *p)) { + break; + } + p++; + } + + for (;;) { + if (IS_COMMENT(conf, *p)) { + *p = '\0'; + return; + } + if (IS_DQUOTE(conf, *p)) { + p = scan_dquote(conf, p); + continue; + } + if (IS_QUOTE(conf, *p)) { + p = scan_quote(conf, p); + continue; + } + if (IS_ESC(conf, *p)) { + p = scan_esc(conf, p); + continue; + } + if (IS_EOF(conf, *p)) + return; + else + p++; + } +} + +static int str_copy(CONF *conf, char *section, char **pto, char *from) +{ + int q, r, rr = 0, to = 0, len = 0; + char *s, *e, *rp, *p, *rrp, *np, *cp, v; + BUF_MEM *buf; + + if ((buf = BUF_MEM_new()) == NULL) + return 0; + + len = strlen(from) + 1; + if (!BUF_MEM_grow(buf, len)) + goto err; + + for (;;) { + if (IS_QUOTE(conf, *from)) { + q = *from; + from++; + while (!IS_EOF(conf, *from) && (*from != q)) { + if (IS_ESC(conf, *from)) { + from++; + if (IS_EOF(conf, *from)) + break; + } + buf->data[to++] = *(from++); + } + if (*from == q) + from++; + } else if (IS_DQUOTE(conf, *from)) { + q = *from; + from++; + while (!IS_EOF(conf, *from)) { + if (*from == q) { + if (*(from + 1) == q) { + from++; + } else { + break; + } + } + buf->data[to++] = *(from++); + } + if (*from == q) + from++; + } else if (IS_ESC(conf, *from)) { + from++; + v = *(from++); + if (IS_EOF(conf, v)) + break; + else if (v == 'r') + v = '\r'; + else if (v == 'n') + v = '\n'; + else if (v == 'b') + v = '\b'; + else if (v == 't') + v = '\t'; + buf->data[to++] = v; + } else if (IS_EOF(conf, *from)) + break; + else if (*from == '$') { + size_t newsize; + + /* try to expand it */ + rrp = NULL; + s = &(from[1]); + if (*s == '{') + q = '}'; + else if (*s == '(') + q = ')'; + else + q = 0; + + if (q) + s++; + cp = section; + e = np = s; + while (IS_ALNUM(conf, *e)) + e++; + if ((e[0] == ':') && (e[1] == ':')) { + cp = np; + rrp = e; + rr = *e; + *rrp = '\0'; + e += 2; + np = e; + while (IS_ALNUM(conf, *e)) + e++; + } + r = *e; + *e = '\0'; + rp = e; + if (q) { + if (r != q) { + CONFerr(CONF_F_STR_COPY, CONF_R_NO_CLOSE_BRACE); + goto err; + } + e++; + } + /*- + * So at this point we have + * np which is the start of the name string which is + * '\0' terminated. + * cp which is the start of the section string which is + * '\0' terminated. + * e is the 'next point after'. + * r and rr are the chars replaced by the '\0' + * rp and rrp is where 'r' and 'rr' came from. + */ + p = _CONF_get_string(conf, cp, np); + if (rrp != NULL) + *rrp = rr; + *rp = r; + if (p == NULL) { + CONFerr(CONF_F_STR_COPY, CONF_R_VARIABLE_HAS_NO_VALUE); + goto err; + } + newsize = strlen(p) + buf->length - (e - from); + if (newsize > MAX_CONF_VALUE_LENGTH) { + CONFerr(CONF_F_STR_COPY, CONF_R_VARIABLE_EXPANSION_TOO_LONG); + goto err; + } + if (!BUF_MEM_grow_clean(buf, newsize)) { + CONFerr(CONF_F_STR_COPY, ERR_R_MALLOC_FAILURE); + goto err; + } + while (*p) + buf->data[to++] = *(p++); + + /* + * Since we change the pointer 'from', we also have to change the + * perceived length of the string it points at. /RL + */ + len -= e - from; + from = e; + + /* + * In case there were no braces or parenthesis around the + * variable reference, we have to put back the character that was + * replaced with a '\0'. /RL + */ + *rp = r; + } else + buf->data[to++] = *(from++); + } + buf->data[to] = '\0'; + OPENSSL_free(*pto); + *pto = buf->data; + OPENSSL_free(buf); + return 1; + err: + BUF_MEM_free(buf); + return 0; +} + +#ifndef OPENSSL_NO_POSIX_IO +/* + * Check whether included path is a directory. + * Returns next BIO to process and in case of a directory + * also an opened directory context and the include path. + */ +static BIO *process_include(char *include, OPENSSL_DIR_CTX **dirctx, + char **dirpath) +{ + struct stat st = { 0 }; + BIO *next; + + if (stat(include, &st) < 0) { + SYSerr(SYS_F_STAT, errno); + ERR_add_error_data(1, include); + /* missing include file is not fatal error */ + return NULL; + } + + if (S_ISDIR(st.st_mode)) { + if (*dirctx != NULL) { + CONFerr(CONF_F_PROCESS_INCLUDE, + CONF_R_RECURSIVE_DIRECTORY_INCLUDE); + ERR_add_error_data(1, include); + return NULL; + } + /* a directory, load its contents */ + if ((next = get_next_file(include, dirctx)) != NULL) + *dirpath = include; + return next; + } + + next = BIO_new_file(include, "r"); + return next; +} + +/* + * Get next file from the directory path. + * Returns BIO of the next file to read and updates dirctx. + */ +static BIO *get_next_file(const char *path, OPENSSL_DIR_CTX **dirctx) +{ + const char *filename; + + while ((filename = OPENSSL_DIR_read(dirctx, path)) != NULL) { + size_t namelen; + + namelen = strlen(filename); + + + if ((namelen > 5 && strcasecmp(filename + namelen - 5, ".conf") == 0) + || (namelen > 4 && strcasecmp(filename + namelen - 4, ".cnf") == 0)) { + size_t newlen; + char *newpath; + BIO *bio; + + newlen = strlen(path) + namelen + 2; + newpath = OPENSSL_zalloc(newlen); + if (newpath == NULL) { + CONFerr(CONF_F_GET_NEXT_FILE, ERR_R_MALLOC_FAILURE); + break; + } +#ifdef OPENSSL_SYS_VMS + /* + * If the given path isn't clear VMS syntax, + * we treat it as on Unix. + */ + { + size_t pathlen = strlen(path); + + if (path[pathlen - 1] == ']' || path[pathlen - 1] == '>' + || path[pathlen - 1] == ':') { + /* Clear VMS directory syntax, just copy as is */ + OPENSSL_strlcpy(newpath, path, newlen); + } + } +#endif + if (newpath[0] == '\0') { + OPENSSL_strlcpy(newpath, path, newlen); + OPENSSL_strlcat(newpath, "/", newlen); + } + OPENSSL_strlcat(newpath, filename, newlen); + + bio = BIO_new_file(newpath, "r"); + OPENSSL_free(newpath); + /* Errors when opening files are non-fatal. */ + if (bio != NULL) + return bio; + } + } + OPENSSL_DIR_end(dirctx); + *dirctx = NULL; + return NULL; +} +#endif + +static int is_keytype(const CONF *conf, char c, unsigned short type) +{ + const unsigned short * keytypes = (const unsigned short *) conf->meth_data; + unsigned char key = (unsigned char)c; + +#ifdef CHARSET_EBCDIC +# if CHAR_BIT > 8 + if (key > 255) { + /* key is out of range for os_toascii table */ + return 0; + } +# endif + /* convert key from ebcdic to ascii */ + key = os_toascii[key]; +#endif + + if (key > 127) { + /* key is not a seven bit ascii character */ + return 0; + } + + return (keytypes[key] & type) ? 1 : 0; +} + +static char *eat_ws(CONF *conf, char *p) +{ + while (IS_WS(conf, *p) && (!IS_EOF(conf, *p))) + p++; + return p; +} + +static void trim_ws(CONF *conf, char *start) +{ + char *p = start; + + while (!IS_EOF(conf, *p)) + p++; + p--; + while ((p >= start) && IS_WS(conf, *p)) + p--; + p++; + *p = '\0'; +} + +static char *eat_alpha_numeric(CONF *conf, char *p) +{ + for (;;) { + if (IS_ESC(conf, *p)) { + p = scan_esc(conf, p); + continue; + } + if (!IS_ALNUM_PUNCT(conf, *p)) + return p; + p++; + } +} + +static char *scan_quote(CONF *conf, char *p) +{ + int q = *p; + + p++; + while (!(IS_EOF(conf, *p)) && (*p != q)) { + if (IS_ESC(conf, *p)) { + p++; + if (IS_EOF(conf, *p)) + return p; + } + p++; + } + if (*p == q) + p++; + return p; +} + +static char *scan_dquote(CONF *conf, char *p) +{ + int q = *p; + + p++; + while (!(IS_EOF(conf, *p))) { + if (*p == q) { + if (*(p + 1) == q) { + p++; + } else { + break; + } + } + p++; + } + if (*p == q) + p++; + return p; +} + +static void dump_value_doall_arg(const CONF_VALUE *a, BIO *out) +{ + if (a->name) + BIO_printf(out, "[%s] %s=%s\n", a->section, a->name, a->value); + else + BIO_printf(out, "[[%s]]\n", a->section); +} + +IMPLEMENT_LHASH_DOALL_ARG_CONST(CONF_VALUE, BIO); + +static int def_dump(const CONF *conf, BIO *out) +{ + lh_CONF_VALUE_doall_BIO(conf->data, dump_value_doall_arg, out); + return 1; +} + +static int def_is_number(const CONF *conf, char c) +{ + return IS_NUMBER(conf, c); +} + +static int def_to_int(const CONF *conf, char c) +{ + return c - '0'; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_def.h b/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_def.h new file mode 100644 index 000000000..2016d31b8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_def.h @@ -0,0 +1,76 @@ +/* + * WARNING: do not edit! + * Generated by crypto/conf/keysets.pl + * + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#define CONF_NUMBER 1 +#define CONF_UPPER 2 +#define CONF_LOWER 4 +#define CONF_UNDER 256 +#define CONF_PUNCT 512 +#define CONF_WS 16 +#define CONF_ESC 32 +#define CONF_QUOTE 64 +#define CONF_DQUOTE 1024 +#define CONF_COMMENT 128 +#define CONF_FCOMMENT 2048 +#define CONF_EOF 8 +#define CONF_ALPHA (CONF_UPPER|CONF_LOWER) +#define CONF_ALNUM (CONF_ALPHA|CONF_NUMBER|CONF_UNDER) +#define CONF_ALNUM_PUNCT (CONF_ALPHA|CONF_NUMBER|CONF_UNDER|CONF_PUNCT) + + +#define IS_COMMENT(conf,c) is_keytype(conf, c, CONF_COMMENT) +#define IS_FCOMMENT(conf,c) is_keytype(conf, c, CONF_FCOMMENT) +#define IS_EOF(conf,c) is_keytype(conf, c, CONF_EOF) +#define IS_ESC(conf,c) is_keytype(conf, c, CONF_ESC) +#define IS_NUMBER(conf,c) is_keytype(conf, c, CONF_NUMBER) +#define IS_WS(conf,c) is_keytype(conf, c, CONF_WS) +#define IS_ALNUM(conf,c) is_keytype(conf, c, CONF_ALNUM) +#define IS_ALNUM_PUNCT(conf,c) is_keytype(conf, c, CONF_ALNUM_PUNCT) +#define IS_QUOTE(conf,c) is_keytype(conf, c, CONF_QUOTE) +#define IS_DQUOTE(conf,c) is_keytype(conf, c, CONF_DQUOTE) + +static const unsigned short CONF_type_default[128] = { + 0x0008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0010, 0x0010, 0x0000, 0x0000, 0x0010, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0010, 0x0200, 0x0040, 0x0080, 0x0000, 0x0200, 0x0200, 0x0040, + 0x0000, 0x0000, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0000, 0x0200, 0x0000, 0x0000, 0x0000, 0x0200, + 0x0200, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, + 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, + 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, + 0x0002, 0x0002, 0x0002, 0x0000, 0x0020, 0x0000, 0x0200, 0x0100, + 0x0040, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0000, 0x0200, 0x0000, 0x0200, 0x0000, +}; + +static const unsigned short CONF_type_win32[128] = { + 0x0008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0010, 0x0010, 0x0000, 0x0000, 0x0010, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0010, 0x0200, 0x0400, 0x0000, 0x0000, 0x0200, 0x0200, 0x0000, + 0x0000, 0x0000, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0000, 0x0A00, 0x0000, 0x0000, 0x0000, 0x0200, + 0x0200, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, + 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, + 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, + 0x0002, 0x0002, 0x0002, 0x0000, 0x0000, 0x0000, 0x0200, 0x0100, + 0x0000, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0000, 0x0200, 0x0000, 0x0200, 0x0000, +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_err.c new file mode 100644 index 000000000..f7613584e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_err.c @@ -0,0 +1,95 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA CONF_str_functs[] = { + {ERR_PACK(ERR_LIB_CONF, CONF_F_CONF_DUMP_FP, 0), "CONF_dump_fp"}, + {ERR_PACK(ERR_LIB_CONF, CONF_F_CONF_LOAD, 0), "CONF_load"}, + {ERR_PACK(ERR_LIB_CONF, CONF_F_CONF_LOAD_FP, 0), "CONF_load_fp"}, + {ERR_PACK(ERR_LIB_CONF, CONF_F_CONF_PARSE_LIST, 0), "CONF_parse_list"}, + {ERR_PACK(ERR_LIB_CONF, CONF_F_DEF_LOAD, 0), "def_load"}, + {ERR_PACK(ERR_LIB_CONF, CONF_F_DEF_LOAD_BIO, 0), "def_load_bio"}, + {ERR_PACK(ERR_LIB_CONF, CONF_F_GET_NEXT_FILE, 0), "get_next_file"}, + {ERR_PACK(ERR_LIB_CONF, CONF_F_MODULE_ADD, 0), "module_add"}, + {ERR_PACK(ERR_LIB_CONF, CONF_F_MODULE_INIT, 0), "module_init"}, + {ERR_PACK(ERR_LIB_CONF, CONF_F_MODULE_LOAD_DSO, 0), "module_load_dso"}, + {ERR_PACK(ERR_LIB_CONF, CONF_F_MODULE_RUN, 0), "module_run"}, + {ERR_PACK(ERR_LIB_CONF, CONF_F_NCONF_DUMP_BIO, 0), "NCONF_dump_bio"}, + {ERR_PACK(ERR_LIB_CONF, CONF_F_NCONF_DUMP_FP, 0), "NCONF_dump_fp"}, + {ERR_PACK(ERR_LIB_CONF, CONF_F_NCONF_GET_NUMBER_E, 0), + "NCONF_get_number_e"}, + {ERR_PACK(ERR_LIB_CONF, CONF_F_NCONF_GET_SECTION, 0), "NCONF_get_section"}, + {ERR_PACK(ERR_LIB_CONF, CONF_F_NCONF_GET_STRING, 0), "NCONF_get_string"}, + {ERR_PACK(ERR_LIB_CONF, CONF_F_NCONF_LOAD, 0), "NCONF_load"}, + {ERR_PACK(ERR_LIB_CONF, CONF_F_NCONF_LOAD_BIO, 0), "NCONF_load_bio"}, + {ERR_PACK(ERR_LIB_CONF, CONF_F_NCONF_LOAD_FP, 0), "NCONF_load_fp"}, + {ERR_PACK(ERR_LIB_CONF, CONF_F_NCONF_NEW, 0), "NCONF_new"}, + {ERR_PACK(ERR_LIB_CONF, CONF_F_PROCESS_INCLUDE, 0), "process_include"}, + {ERR_PACK(ERR_LIB_CONF, CONF_F_SSL_MODULE_INIT, 0), "ssl_module_init"}, + {ERR_PACK(ERR_LIB_CONF, CONF_F_STR_COPY, 0), "str_copy"}, + {0, NULL} +}; + +static const ERR_STRING_DATA CONF_str_reasons[] = { + {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_ERROR_LOADING_DSO), "error loading dso"}, + {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_LIST_CANNOT_BE_NULL), + "list cannot be null"}, + {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_MISSING_CLOSE_SQUARE_BRACKET), + "missing close square bracket"}, + {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_MISSING_EQUAL_SIGN), + "missing equal sign"}, + {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_MISSING_INIT_FUNCTION), + "missing init function"}, + {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_MODULE_INITIALIZATION_ERROR), + "module initialization error"}, + {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_NO_CLOSE_BRACE), "no close brace"}, + {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_NO_CONF), "no conf"}, + {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_NO_CONF_OR_ENVIRONMENT_VARIABLE), + "no conf or environment variable"}, + {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_NO_SECTION), "no section"}, + {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_NO_SUCH_FILE), "no such file"}, + {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_NO_VALUE), "no value"}, + {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_NUMBER_TOO_LARGE), "number too large"}, + {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_RECURSIVE_DIRECTORY_INCLUDE), + "recursive directory include"}, + {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_SSL_COMMAND_SECTION_EMPTY), + "ssl command section empty"}, + {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_SSL_COMMAND_SECTION_NOT_FOUND), + "ssl command section not found"}, + {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_SSL_SECTION_EMPTY), "ssl section empty"}, + {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_SSL_SECTION_NOT_FOUND), + "ssl section not found"}, + {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_UNABLE_TO_CREATE_NEW_SECTION), + "unable to create new section"}, + {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_UNKNOWN_MODULE_NAME), + "unknown module name"}, + {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_VARIABLE_EXPANSION_TOO_LONG), + "variable expansion too long"}, + {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_VARIABLE_HAS_NO_VALUE), + "variable has no value"}, + {0, NULL} +}; + +#endif + +int ERR_load_CONF_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(CONF_str_functs[0].error) == NULL) { + ERR_load_strings_const(CONF_str_functs); + ERR_load_strings_const(CONF_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_lcl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_lcl.h new file mode 100644 index 000000000..6e1f7fe00 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_lcl.h @@ -0,0 +1,11 @@ +/* + * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +void conf_add_ssl_module(void); + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_lib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_lib.c new file mode 100644 index 000000000..2d40ac97e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_lib.c @@ -0,0 +1,414 @@ +/* + * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "e_os.h" +#include +#include +#include "internal/conf.h" +#include "internal/ctype.h" +#include +#include +#include +#include +#include + +static CONF_METHOD *default_CONF_method = NULL; + +/* Init a 'CONF' structure from an old LHASH */ + +void CONF_set_nconf(CONF *conf, LHASH_OF(CONF_VALUE) *hash) +{ + if (default_CONF_method == NULL) + default_CONF_method = NCONF_default(); + + default_CONF_method->init(conf); + conf->data = hash; +} + +/* + * The following section contains the "CONF classic" functions, rewritten in + * terms of the new CONF interface. + */ + +int CONF_set_default_method(CONF_METHOD *meth) +{ + default_CONF_method = meth; + return 1; +} + +LHASH_OF(CONF_VALUE) *CONF_load(LHASH_OF(CONF_VALUE) *conf, const char *file, + long *eline) +{ + LHASH_OF(CONF_VALUE) *ltmp; + BIO *in = NULL; + +#ifdef OPENSSL_SYS_VMS + in = BIO_new_file(file, "r"); +#else + in = BIO_new_file(file, "rb"); +#endif + if (in == NULL) { + CONFerr(CONF_F_CONF_LOAD, ERR_R_SYS_LIB); + return NULL; + } + + ltmp = CONF_load_bio(conf, in, eline); + BIO_free(in); + + return ltmp; +} + +#ifndef OPENSSL_NO_STDIO +LHASH_OF(CONF_VALUE) *CONF_load_fp(LHASH_OF(CONF_VALUE) *conf, FILE *fp, + long *eline) +{ + BIO *btmp; + LHASH_OF(CONF_VALUE) *ltmp; + if ((btmp = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) { + CONFerr(CONF_F_CONF_LOAD_FP, ERR_R_BUF_LIB); + return NULL; + } + ltmp = CONF_load_bio(conf, btmp, eline); + BIO_free(btmp); + return ltmp; +} +#endif + +LHASH_OF(CONF_VALUE) *CONF_load_bio(LHASH_OF(CONF_VALUE) *conf, BIO *bp, + long *eline) +{ + CONF ctmp; + int ret; + + CONF_set_nconf(&ctmp, conf); + + ret = NCONF_load_bio(&ctmp, bp, eline); + if (ret) + return ctmp.data; + return NULL; +} + +STACK_OF(CONF_VALUE) *CONF_get_section(LHASH_OF(CONF_VALUE) *conf, + const char *section) +{ + if (conf == NULL) { + return NULL; + } else { + CONF ctmp; + CONF_set_nconf(&ctmp, conf); + return NCONF_get_section(&ctmp, section); + } +} + +char *CONF_get_string(LHASH_OF(CONF_VALUE) *conf, const char *group, + const char *name) +{ + if (conf == NULL) { + return NCONF_get_string(NULL, group, name); + } else { + CONF ctmp; + CONF_set_nconf(&ctmp, conf); + return NCONF_get_string(&ctmp, group, name); + } +} + +long CONF_get_number(LHASH_OF(CONF_VALUE) *conf, const char *group, + const char *name) +{ + int status; + long result = 0; + + ERR_set_mark(); + if (conf == NULL) { + status = NCONF_get_number_e(NULL, group, name, &result); + } else { + CONF ctmp; + CONF_set_nconf(&ctmp, conf); + status = NCONF_get_number_e(&ctmp, group, name, &result); + } + ERR_pop_to_mark(); + return status == 0 ? 0L : result; +} + +void CONF_free(LHASH_OF(CONF_VALUE) *conf) +{ + CONF ctmp; + CONF_set_nconf(&ctmp, conf); + NCONF_free_data(&ctmp); +} + +#ifndef OPENSSL_NO_STDIO +int CONF_dump_fp(LHASH_OF(CONF_VALUE) *conf, FILE *out) +{ + BIO *btmp; + int ret; + + if ((btmp = BIO_new_fp(out, BIO_NOCLOSE)) == NULL) { + CONFerr(CONF_F_CONF_DUMP_FP, ERR_R_BUF_LIB); + return 0; + } + ret = CONF_dump_bio(conf, btmp); + BIO_free(btmp); + return ret; +} +#endif + +int CONF_dump_bio(LHASH_OF(CONF_VALUE) *conf, BIO *out) +{ + CONF ctmp; + CONF_set_nconf(&ctmp, conf); + return NCONF_dump_bio(&ctmp, out); +} + +/* + * The following section contains the "New CONF" functions. They are + * completely centralised around a new CONF structure that may contain + * basically anything, but at least a method pointer and a table of data. + * These functions are also written in terms of the bridge functions used by + * the "CONF classic" functions, for consistency. + */ + +CONF *NCONF_new(CONF_METHOD *meth) +{ + CONF *ret; + + if (meth == NULL) + meth = NCONF_default(); + + ret = meth->create(meth); + if (ret == NULL) { + CONFerr(CONF_F_NCONF_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + return ret; +} + +void NCONF_free(CONF *conf) +{ + if (conf == NULL) + return; + conf->meth->destroy(conf); +} + +void NCONF_free_data(CONF *conf) +{ + if (conf == NULL) + return; + conf->meth->destroy_data(conf); +} + +int NCONF_load(CONF *conf, const char *file, long *eline) +{ + if (conf == NULL) { + CONFerr(CONF_F_NCONF_LOAD, CONF_R_NO_CONF); + return 0; + } + + return conf->meth->load(conf, file, eline); +} + +#ifndef OPENSSL_NO_STDIO +int NCONF_load_fp(CONF *conf, FILE *fp, long *eline) +{ + BIO *btmp; + int ret; + if ((btmp = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) { + CONFerr(CONF_F_NCONF_LOAD_FP, ERR_R_BUF_LIB); + return 0; + } + ret = NCONF_load_bio(conf, btmp, eline); + BIO_free(btmp); + return ret; +} +#endif + +int NCONF_load_bio(CONF *conf, BIO *bp, long *eline) +{ + if (conf == NULL) { + CONFerr(CONF_F_NCONF_LOAD_BIO, CONF_R_NO_CONF); + return 0; + } + + return conf->meth->load_bio(conf, bp, eline); +} + +STACK_OF(CONF_VALUE) *NCONF_get_section(const CONF *conf, const char *section) +{ + if (conf == NULL) { + CONFerr(CONF_F_NCONF_GET_SECTION, CONF_R_NO_CONF); + return NULL; + } + + if (section == NULL) { + CONFerr(CONF_F_NCONF_GET_SECTION, CONF_R_NO_SECTION); + return NULL; + } + + return _CONF_get_section_values(conf, section); +} + +char *NCONF_get_string(const CONF *conf, const char *group, const char *name) +{ + char *s = _CONF_get_string(conf, group, name); + + /* + * Since we may get a value from an environment variable even if conf is + * NULL, let's check the value first + */ + if (s) + return s; + + if (conf == NULL) { + CONFerr(CONF_F_NCONF_GET_STRING, + CONF_R_NO_CONF_OR_ENVIRONMENT_VARIABLE); + return NULL; + } + CONFerr(CONF_F_NCONF_GET_STRING, CONF_R_NO_VALUE); + ERR_add_error_data(4, "group=", group, " name=", name); + return NULL; +} + +static int default_is_number(const CONF *conf, char c) +{ + return ossl_isdigit(c); +} + +static int default_to_int(const CONF *conf, char c) +{ + return (int)(c - '0'); +} + +int NCONF_get_number_e(const CONF *conf, const char *group, const char *name, + long *result) +{ + char *str; + long res; + int (*is_number)(const CONF *, char) = &default_is_number; + int (*to_int)(const CONF *, char) = &default_to_int; + + if (result == NULL) { + CONFerr(CONF_F_NCONF_GET_NUMBER_E, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + str = NCONF_get_string(conf, group, name); + + if (str == NULL) + return 0; + + if (conf != NULL) { + if (conf->meth->is_number != NULL) + is_number = conf->meth->is_number; + if (conf->meth->to_int != NULL) + to_int = conf->meth->to_int; + } + for (res = 0; is_number(conf, *str); str++) { + const int d = to_int(conf, *str); + + if (res > (LONG_MAX - d) / 10L) { + CONFerr(CONF_F_NCONF_GET_NUMBER_E, CONF_R_NUMBER_TOO_LARGE); + return 0; + } + res = res * 10 + d; + } + + *result = res; + return 1; +} + +#ifndef OPENSSL_NO_STDIO +int NCONF_dump_fp(const CONF *conf, FILE *out) +{ + BIO *btmp; + int ret; + if ((btmp = BIO_new_fp(out, BIO_NOCLOSE)) == NULL) { + CONFerr(CONF_F_NCONF_DUMP_FP, ERR_R_BUF_LIB); + return 0; + } + ret = NCONF_dump_bio(conf, btmp); + BIO_free(btmp); + return ret; +} +#endif + +int NCONF_dump_bio(const CONF *conf, BIO *out) +{ + if (conf == NULL) { + CONFerr(CONF_F_NCONF_DUMP_BIO, CONF_R_NO_CONF); + return 0; + } + + return conf->meth->dump(conf, out); +} + +/* + * These routines call the C malloc/free, to avoid intermixing with + * OpenSSL function pointers before the library is initialized. + */ +OPENSSL_INIT_SETTINGS *OPENSSL_INIT_new(void) +{ + OPENSSL_INIT_SETTINGS *ret = malloc(sizeof(*ret)); + + if (ret != NULL) + memset(ret, 0, sizeof(*ret)); + ret->flags = DEFAULT_CONF_MFLAGS; + + return ret; +} + + +#ifndef OPENSSL_NO_STDIO +int OPENSSL_INIT_set_config_filename(OPENSSL_INIT_SETTINGS *settings, + const char *filename) +{ + char *newfilename = NULL; + + if (filename != NULL) { + newfilename = strdup(filename); + if (newfilename == NULL) + return 0; + } + + free(settings->filename); + settings->filename = newfilename; + + return 1; +} + +void OPENSSL_INIT_set_config_file_flags(OPENSSL_INIT_SETTINGS *settings, + unsigned long flags) +{ + settings->flags = flags; +} + +int OPENSSL_INIT_set_config_appname(OPENSSL_INIT_SETTINGS *settings, + const char *appname) +{ + char *newappname = NULL; + + if (appname != NULL) { + newappname = strdup(appname); + if (newappname == NULL) + return 0; + } + + free(settings->appname); + settings->appname = newappname; + + return 1; +} +#endif + +void OPENSSL_INIT_free(OPENSSL_INIT_SETTINGS *settings) +{ + free(settings->filename); + free(settings->appname); + free(settings); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_mall.c b/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_mall.c new file mode 100644 index 000000000..7e86948e8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_mall.c @@ -0,0 +1,31 @@ +/* + * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "conf_lcl.h" + +/* Load all OpenSSL builtin modules */ + +void OPENSSL_load_builtin_modules(void) +{ + /* Add builtin modules here */ + ASN1_add_oid_module(); + ASN1_add_stable_module(); +#ifndef OPENSSL_NO_ENGINE + ENGINE_add_conf_module(); +#endif + EVP_add_alg_module(); + conf_add_ssl_module(); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_mod.c b/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_mod.c new file mode 100644 index 000000000..e703d97f5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_mod.c @@ -0,0 +1,551 @@ +/* + * Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include +#include +#include +#include "internal/conf.h" +#include "internal/dso.h" +#include + +#define DSO_mod_init_name "OPENSSL_init" +#define DSO_mod_finish_name "OPENSSL_finish" + +/* + * This structure contains a data about supported modules. entries in this + * table correspond to either dynamic or static modules. + */ + +struct conf_module_st { + /* DSO of this module or NULL if static */ + DSO *dso; + /* Name of the module */ + char *name; + /* Init function */ + conf_init_func *init; + /* Finish function */ + conf_finish_func *finish; + /* Number of successfully initialized modules */ + int links; + void *usr_data; +}; + +/* + * This structure contains information about modules that have been + * successfully initialized. There may be more than one entry for a given + * module. + */ + +struct conf_imodule_st { + CONF_MODULE *pmod; + char *name; + char *value; + unsigned long flags; + void *usr_data; +}; + +static STACK_OF(CONF_MODULE) *supported_modules = NULL; +static STACK_OF(CONF_IMODULE) *initialized_modules = NULL; + +static void module_free(CONF_MODULE *md); +static void module_finish(CONF_IMODULE *imod); +static int module_run(const CONF *cnf, const char *name, const char *value, + unsigned long flags); +static CONF_MODULE *module_add(DSO *dso, const char *name, + conf_init_func *ifunc, + conf_finish_func *ffunc); +static CONF_MODULE *module_find(const char *name); +static int module_init(CONF_MODULE *pmod, const char *name, const char *value, + const CONF *cnf); +static CONF_MODULE *module_load_dso(const CONF *cnf, const char *name, + const char *value); + +/* Main function: load modules from a CONF structure */ + +int CONF_modules_load(const CONF *cnf, const char *appname, + unsigned long flags) +{ + STACK_OF(CONF_VALUE) *values; + CONF_VALUE *vl; + char *vsection = NULL; + + int ret, i; + + if (!cnf) + return 1; + + if (appname) + vsection = NCONF_get_string(cnf, NULL, appname); + + if (!appname || (!vsection && (flags & CONF_MFLAGS_DEFAULT_SECTION))) + vsection = NCONF_get_string(cnf, NULL, "openssl_conf"); + + if (!vsection) { + ERR_clear_error(); + return 1; + } + + values = NCONF_get_section(cnf, vsection); + + if (!values) + return 0; + + for (i = 0; i < sk_CONF_VALUE_num(values); i++) { + vl = sk_CONF_VALUE_value(values, i); + ret = module_run(cnf, vl->name, vl->value, flags); + if (ret <= 0) + if (!(flags & CONF_MFLAGS_IGNORE_ERRORS)) + return ret; + } + + return 1; + +} + +int CONF_modules_load_file(const char *filename, const char *appname, + unsigned long flags) +{ + char *file = NULL; + CONF *conf = NULL; + int ret = 0; + conf = NCONF_new(NULL); + if (conf == NULL) + goto err; + + if (filename == NULL) { + file = CONF_get1_default_config_file(); + if (!file) + goto err; + } else + file = (char *)filename; + + if (NCONF_load(conf, file, NULL) <= 0) { + if ((flags & CONF_MFLAGS_IGNORE_MISSING_FILE) && + (ERR_GET_REASON(ERR_peek_last_error()) == CONF_R_NO_SUCH_FILE)) { + ERR_clear_error(); + ret = 1; + } + goto err; + } + + ret = CONF_modules_load(conf, appname, flags); + + err: + if (filename == NULL) + OPENSSL_free(file); + NCONF_free(conf); + + if (flags & CONF_MFLAGS_IGNORE_RETURN_CODES) + return 1; + + return ret; +} + +static int module_run(const CONF *cnf, const char *name, const char *value, + unsigned long flags) +{ + CONF_MODULE *md; + int ret; + + md = module_find(name); + + /* Module not found: try to load DSO */ + if (!md && !(flags & CONF_MFLAGS_NO_DSO)) + md = module_load_dso(cnf, name, value); + + if (!md) { + if (!(flags & CONF_MFLAGS_SILENT)) { + CONFerr(CONF_F_MODULE_RUN, CONF_R_UNKNOWN_MODULE_NAME); + ERR_add_error_data(2, "module=", name); + } + return -1; + } + + ret = module_init(md, name, value, cnf); + + if (ret <= 0) { + if (!(flags & CONF_MFLAGS_SILENT)) { + char rcode[DECIMAL_SIZE(ret) + 1]; + + CONFerr(CONF_F_MODULE_RUN, CONF_R_MODULE_INITIALIZATION_ERROR); + BIO_snprintf(rcode, sizeof(rcode), "%-8d", ret); + ERR_add_error_data(6, "module=", name, ", value=", value, + ", retcode=", rcode); + } + } + + return ret; +} + +/* Load a module from a DSO */ +static CONF_MODULE *module_load_dso(const CONF *cnf, + const char *name, const char *value) +{ + DSO *dso = NULL; + conf_init_func *ifunc; + conf_finish_func *ffunc; + const char *path = NULL; + int errcode = 0; + CONF_MODULE *md; + /* Look for alternative path in module section */ + path = NCONF_get_string(cnf, value, "path"); + if (!path) { + ERR_clear_error(); + path = name; + } + dso = DSO_load(NULL, path, NULL, 0); + if (!dso) { + errcode = CONF_R_ERROR_LOADING_DSO; + goto err; + } + ifunc = (conf_init_func *)DSO_bind_func(dso, DSO_mod_init_name); + if (!ifunc) { + errcode = CONF_R_MISSING_INIT_FUNCTION; + goto err; + } + ffunc = (conf_finish_func *)DSO_bind_func(dso, DSO_mod_finish_name); + /* All OK, add module */ + md = module_add(dso, name, ifunc, ffunc); + + if (!md) + goto err; + + return md; + + err: + DSO_free(dso); + CONFerr(CONF_F_MODULE_LOAD_DSO, errcode); + ERR_add_error_data(4, "module=", name, ", path=", path); + return NULL; +} + +/* add module to list */ +static CONF_MODULE *module_add(DSO *dso, const char *name, + conf_init_func *ifunc, conf_finish_func *ffunc) +{ + CONF_MODULE *tmod = NULL; + if (supported_modules == NULL) + supported_modules = sk_CONF_MODULE_new_null(); + if (supported_modules == NULL) + return NULL; + if ((tmod = OPENSSL_zalloc(sizeof(*tmod))) == NULL) { + CONFerr(CONF_F_MODULE_ADD, ERR_R_MALLOC_FAILURE); + return NULL; + } + + tmod->dso = dso; + tmod->name = OPENSSL_strdup(name); + tmod->init = ifunc; + tmod->finish = ffunc; + if (tmod->name == NULL) { + OPENSSL_free(tmod); + return NULL; + } + + if (!sk_CONF_MODULE_push(supported_modules, tmod)) { + OPENSSL_free(tmod->name); + OPENSSL_free(tmod); + return NULL; + } + + return tmod; +} + +/* + * Find a module from the list. We allow module names of the form + * modname.XXXX to just search for modname to allow the same module to be + * initialized more than once. + */ + +static CONF_MODULE *module_find(const char *name) +{ + CONF_MODULE *tmod; + int i, nchar; + char *p; + p = strrchr(name, '.'); + + if (p) + nchar = p - name; + else + nchar = strlen(name); + + for (i = 0; i < sk_CONF_MODULE_num(supported_modules); i++) { + tmod = sk_CONF_MODULE_value(supported_modules, i); + if (strncmp(tmod->name, name, nchar) == 0) + return tmod; + } + + return NULL; + +} + +/* initialize a module */ +static int module_init(CONF_MODULE *pmod, const char *name, const char *value, + const CONF *cnf) +{ + int ret = 1; + int init_called = 0; + CONF_IMODULE *imod = NULL; + + /* Otherwise add initialized module to list */ + imod = OPENSSL_malloc(sizeof(*imod)); + if (imod == NULL) + goto err; + + imod->pmod = pmod; + imod->name = OPENSSL_strdup(name); + imod->value = OPENSSL_strdup(value); + imod->usr_data = NULL; + + if (!imod->name || !imod->value) + goto memerr; + + /* Try to initialize module */ + if (pmod->init) { + ret = pmod->init(imod, cnf); + init_called = 1; + /* Error occurred, exit */ + if (ret <= 0) + goto err; + } + + if (initialized_modules == NULL) { + initialized_modules = sk_CONF_IMODULE_new_null(); + if (!initialized_modules) { + CONFerr(CONF_F_MODULE_INIT, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + if (!sk_CONF_IMODULE_push(initialized_modules, imod)) { + CONFerr(CONF_F_MODULE_INIT, ERR_R_MALLOC_FAILURE); + goto err; + } + + pmod->links++; + + return ret; + + err: + + /* We've started the module so we'd better finish it */ + if (pmod->finish && init_called) + pmod->finish(imod); + + memerr: + if (imod) { + OPENSSL_free(imod->name); + OPENSSL_free(imod->value); + OPENSSL_free(imod); + } + + return -1; + +} + +/* + * Unload any dynamic modules that have a link count of zero: i.e. have no + * active initialized modules. If 'all' is set then all modules are unloaded + * including static ones. + */ + +void CONF_modules_unload(int all) +{ + int i; + CONF_MODULE *md; + CONF_modules_finish(); + /* unload modules in reverse order */ + for (i = sk_CONF_MODULE_num(supported_modules) - 1; i >= 0; i--) { + md = sk_CONF_MODULE_value(supported_modules, i); + /* If static or in use and 'all' not set ignore it */ + if (((md->links > 0) || !md->dso) && !all) + continue; + /* Since we're working in reverse this is OK */ + (void)sk_CONF_MODULE_delete(supported_modules, i); + module_free(md); + } + if (sk_CONF_MODULE_num(supported_modules) == 0) { + sk_CONF_MODULE_free(supported_modules); + supported_modules = NULL; + } +} + +/* unload a single module */ +static void module_free(CONF_MODULE *md) +{ + DSO_free(md->dso); + OPENSSL_free(md->name); + OPENSSL_free(md); +} + +/* finish and free up all modules instances */ + +void CONF_modules_finish(void) +{ + CONF_IMODULE *imod; + while (sk_CONF_IMODULE_num(initialized_modules) > 0) { + imod = sk_CONF_IMODULE_pop(initialized_modules); + module_finish(imod); + } + sk_CONF_IMODULE_free(initialized_modules); + initialized_modules = NULL; +} + +/* finish a module instance */ + +static void module_finish(CONF_IMODULE *imod) +{ + if (!imod) + return; + if (imod->pmod->finish) + imod->pmod->finish(imod); + imod->pmod->links--; + OPENSSL_free(imod->name); + OPENSSL_free(imod->value); + OPENSSL_free(imod); +} + +/* Add a static module to OpenSSL */ + +int CONF_module_add(const char *name, conf_init_func *ifunc, + conf_finish_func *ffunc) +{ + if (module_add(NULL, name, ifunc, ffunc)) + return 1; + else + return 0; +} + +void conf_modules_free_int(void) +{ + CONF_modules_finish(); + CONF_modules_unload(1); +} + +/* Utility functions */ + +const char *CONF_imodule_get_name(const CONF_IMODULE *md) +{ + return md->name; +} + +const char *CONF_imodule_get_value(const CONF_IMODULE *md) +{ + return md->value; +} + +void *CONF_imodule_get_usr_data(const CONF_IMODULE *md) +{ + return md->usr_data; +} + +void CONF_imodule_set_usr_data(CONF_IMODULE *md, void *usr_data) +{ + md->usr_data = usr_data; +} + +CONF_MODULE *CONF_imodule_get_module(const CONF_IMODULE *md) +{ + return md->pmod; +} + +unsigned long CONF_imodule_get_flags(const CONF_IMODULE *md) +{ + return md->flags; +} + +void CONF_imodule_set_flags(CONF_IMODULE *md, unsigned long flags) +{ + md->flags = flags; +} + +void *CONF_module_get_usr_data(CONF_MODULE *pmod) +{ + return pmod->usr_data; +} + +void CONF_module_set_usr_data(CONF_MODULE *pmod, void *usr_data) +{ + pmod->usr_data = usr_data; +} + +/* Return default config file name */ + +char *CONF_get1_default_config_file(void) +{ + char *file, *sep = ""; + int len; + + if ((file = ossl_safe_getenv("OPENSSL_CONF")) != NULL) + return OPENSSL_strdup(file); + + len = strlen(X509_get_default_cert_area()); +#ifndef OPENSSL_SYS_VMS + len++; + sep = "/"; +#endif + len += strlen(OPENSSL_CONF); + + file = OPENSSL_malloc(len + 1); + + if (file == NULL) + return NULL; + BIO_snprintf(file, len + 1, "%s%s%s", X509_get_default_cert_area(), + sep, OPENSSL_CONF); + + return file; +} + +/* + * This function takes a list separated by 'sep' and calls the callback + * function giving the start and length of each member optionally stripping + * leading and trailing whitespace. This can be used to parse comma separated + * lists for example. + */ + +int CONF_parse_list(const char *list_, int sep, int nospc, + int (*list_cb) (const char *elem, int len, void *usr), + void *arg) +{ + int ret; + const char *lstart, *tmpend, *p; + + if (list_ == NULL) { + CONFerr(CONF_F_CONF_PARSE_LIST, CONF_R_LIST_CANNOT_BE_NULL); + return 0; + } + + lstart = list_; + for (;;) { + if (nospc) { + while (*lstart && isspace((unsigned char)*lstart)) + lstart++; + } + p = strchr(lstart, sep); + if (p == lstart || !*lstart) + ret = list_cb(NULL, 0, arg); + else { + if (p) + tmpend = p - 1; + else + tmpend = lstart + strlen(lstart) - 1; + if (nospc) { + while (isspace((unsigned char)*tmpend)) + tmpend--; + } + ret = list_cb(lstart, tmpend - lstart + 1, arg); + } + if (ret <= 0) + return ret; + if (p == NULL) + return 1; + lstart = p + 1; + } +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_sap.c b/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_sap.c new file mode 100644 index 000000000..2ce42f0c6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_sap.c @@ -0,0 +1,77 @@ +/* + * Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include "internal/conf.h" +#include +#include +#include + +#ifdef _WIN32 +# define strdup _strdup +#endif + +/* + * This is the automatic configuration loader: it is called automatically by + * OpenSSL when any of a number of standard initialisation functions are + * called, unless this is overridden by calling OPENSSL_no_config() + */ + +static int openssl_configured = 0; + +#if OPENSSL_API_COMPAT < 0x10100000L +void OPENSSL_config(const char *appname) +{ + OPENSSL_INIT_SETTINGS settings; + + memset(&settings, 0, sizeof(settings)); + if (appname != NULL) + settings.appname = strdup(appname); + OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, &settings); +} +#endif + +int openssl_config_int(const OPENSSL_INIT_SETTINGS *settings) +{ + int ret; + const char *filename; + const char *appname; + unsigned long flags; + + if (openssl_configured) + return 1; + + filename = settings ? settings->filename : NULL; + appname = settings ? settings->appname : NULL; + flags = settings ? settings->flags : DEFAULT_CONF_MFLAGS; + +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: openssl_config_int(%s, %s, %lu)\n", + filename, appname, flags); +#endif + + OPENSSL_load_builtin_modules(); +#ifndef OPENSSL_NO_ENGINE + /* Need to load ENGINEs */ + ENGINE_load_builtin_engines(); +#endif + ERR_clear_error(); +#ifndef OPENSSL_SYS_UEFI + ret = CONF_modules_load_file(filename, appname, flags); +#endif + openssl_configured = 1; + return ret; +} + +void openssl_no_config_int(void) +{ + openssl_configured = 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_ssl.c b/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_ssl.c new file mode 100644 index 000000000..387f2cf46 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/conf/conf_ssl.c @@ -0,0 +1,181 @@ +/* + * Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include "internal/sslconf.h" +#include "conf_lcl.h" + +/* + * SSL library configuration module placeholder. We load it here but defer + * all decisions about its contents to libssl. + */ + +struct ssl_conf_name_st { + /* Name of this set of commands */ + char *name; + /* List of commands */ + SSL_CONF_CMD *cmds; + /* Number of commands */ + size_t cmd_count; +}; + +struct ssl_conf_cmd_st { + /* Command */ + char *cmd; + /* Argument */ + char *arg; +}; + +static struct ssl_conf_name_st *ssl_names; +static size_t ssl_names_count; + +static void ssl_module_free(CONF_IMODULE *md) +{ + size_t i, j; + if (ssl_names == NULL) + return; + for (i = 0; i < ssl_names_count; i++) { + struct ssl_conf_name_st *tname = ssl_names + i; + + OPENSSL_free(tname->name); + for (j = 0; j < tname->cmd_count; j++) { + OPENSSL_free(tname->cmds[j].cmd); + OPENSSL_free(tname->cmds[j].arg); + } + OPENSSL_free(tname->cmds); + } + OPENSSL_free(ssl_names); + ssl_names = NULL; + ssl_names_count = 0; +} + +static int ssl_module_init(CONF_IMODULE *md, const CONF *cnf) +{ + size_t i, j, cnt; + int rv = 0; + const char *ssl_conf_section; + STACK_OF(CONF_VALUE) *cmd_lists; + + ssl_conf_section = CONF_imodule_get_value(md); + cmd_lists = NCONF_get_section(cnf, ssl_conf_section); + if (sk_CONF_VALUE_num(cmd_lists) <= 0) { + if (cmd_lists == NULL) + CONFerr(CONF_F_SSL_MODULE_INIT, CONF_R_SSL_SECTION_NOT_FOUND); + else + CONFerr(CONF_F_SSL_MODULE_INIT, CONF_R_SSL_SECTION_EMPTY); + ERR_add_error_data(2, "section=", ssl_conf_section); + goto err; + } + cnt = sk_CONF_VALUE_num(cmd_lists); + ssl_module_free(md); + ssl_names = OPENSSL_zalloc(sizeof(*ssl_names) * cnt); + if (ssl_names == NULL) + goto err; + ssl_names_count = cnt; + for (i = 0; i < ssl_names_count; i++) { + struct ssl_conf_name_st *ssl_name = ssl_names + i; + CONF_VALUE *sect = sk_CONF_VALUE_value(cmd_lists, (int)i); + STACK_OF(CONF_VALUE) *cmds = NCONF_get_section(cnf, sect->value); + + if (sk_CONF_VALUE_num(cmds) <= 0) { + if (cmds == NULL) + CONFerr(CONF_F_SSL_MODULE_INIT, + CONF_R_SSL_COMMAND_SECTION_NOT_FOUND); + else + CONFerr(CONF_F_SSL_MODULE_INIT, + CONF_R_SSL_COMMAND_SECTION_EMPTY); + ERR_add_error_data(4, "name=", sect->name, ", value=", sect->value); + goto err; + } + ssl_name->name = OPENSSL_strdup(sect->name); + if (ssl_name->name == NULL) + goto err; + cnt = sk_CONF_VALUE_num(cmds); + ssl_name->cmds = OPENSSL_zalloc(cnt * sizeof(struct ssl_conf_cmd_st)); + if (ssl_name->cmds == NULL) + goto err; + ssl_name->cmd_count = cnt; + for (j = 0; j < cnt; j++) { + const char *name; + CONF_VALUE *cmd_conf = sk_CONF_VALUE_value(cmds, (int)j); + struct ssl_conf_cmd_st *cmd = ssl_name->cmds + j; + + /* Skip any initial dot in name */ + name = strchr(cmd_conf->name, '.'); + if (name != NULL) + name++; + else + name = cmd_conf->name; + cmd->cmd = OPENSSL_strdup(name); + cmd->arg = OPENSSL_strdup(cmd_conf->value); + if (cmd->cmd == NULL || cmd->arg == NULL) + goto err; + } + + } + rv = 1; + err: + if (rv == 0) + ssl_module_free(md); + return rv; +} + +/* + * Returns the set of commands with index |idx| previously searched for via + * conf_ssl_name_find. Also stores the name of the set of commands in |*name| + * and the number of commands in the set in |*cnt|. + */ +const SSL_CONF_CMD *conf_ssl_get(size_t idx, const char **name, size_t *cnt) +{ + *name = ssl_names[idx].name; + *cnt = ssl_names[idx].cmd_count; + return ssl_names[idx].cmds; +} + +/* + * Search for the named set of commands given in |name|. On success return the + * index for the command set in |*idx|. + * Returns 1 on success or 0 on failure. + */ +int conf_ssl_name_find(const char *name, size_t *idx) +{ + size_t i; + const struct ssl_conf_name_st *nm; + + if (name == NULL) + return 0; + for (i = 0, nm = ssl_names; i < ssl_names_count; i++, nm++) { + if (strcmp(nm->name, name) == 0) { + *idx = i; + return 1; + } + } + return 0; +} + +/* + * Given a command set |cmd|, return details on the command at index |idx| which + * must be less than the number of commands in the set (as returned by + * conf_ssl_get). The name of the command will be returned in |*cmdstr| and the + * argument is returned in |*arg|. + */ +void conf_ssl_get_cmd(const SSL_CONF_CMD *cmd, size_t idx, char **cmdstr, + char **arg) +{ + *cmdstr = cmd[idx].cmd; + *arg = cmd[idx].arg; +} + +void conf_add_ssl_module(void) +{ + CONF_module_add("ssl_conf", ssl_module_init, ssl_module_free); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/conf/keysets.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/conf/keysets.pl new file mode 100644 index 000000000..27a7214cc --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/conf/keysets.pl @@ -0,0 +1,116 @@ +#! /usr/bin/env perl +# Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use strict; +use warnings; + +my $NUMBER = 0x0001; +my $UPPER = 0x0002; +my $LOWER = 0x0004; +my $UNDER = 0x0100; +my $PUNCTUATION = 0x0200; +my $WS = 0x0010; +my $ESC = 0x0020; +my $QUOTE = 0x0040; +my $DQUOTE = 0x0400; +my $COMMENT = 0x0080; +my $FCOMMENT = 0x0800; +my $EOF = 0x0008; +my @V_def; +my @V_w32; + +my $v; +my $c; +foreach (0 .. 127) { + $c = sprintf("%c", $_); + $v = 0; + $v |= $NUMBER if $c =~ /[0-9]/; + $v |= $UPPER if $c =~ /[A-Z]/; + $v |= $LOWER if $c =~ /[a-z]/; + $v |= $UNDER if $c =~ /_/; + $v |= $PUNCTUATION if $c =~ /[!\.%&\*\+,\/;\?\@\^\~\|-]/; + $v |= $WS if $c =~ /[ \t\r\n]/; + $v |= $ESC if $c =~ /\\/; + $v |= $QUOTE if $c =~ /['`"]/; # for emacs: "`' + $v |= $COMMENT if $c =~ /\#/; + $v |= $EOF if $c =~ /\0/; + push(@V_def, $v); + + $v = 0; + $v |= $NUMBER if $c =~ /[0-9]/; + $v |= $UPPER if $c =~ /[A-Z]/; + $v |= $LOWER if $c =~ /[a-z]/; + $v |= $UNDER if $c =~ /_/; + $v |= $PUNCTUATION if $c =~ /[!\.%&\*\+,\/;\?\@\^\~\|-]/; + $v |= $WS if $c =~ /[ \t\r\n]/; + $v |= $DQUOTE if $c =~ /["]/; # for emacs: " + $v |= $FCOMMENT if $c =~ /;/; + $v |= $EOF if $c =~ /\0/; + push(@V_w32, $v); +} + +# Output year depends on the year of the script. +my $YEAR = [localtime([stat($0)]->[9])]->[5] + 1900; + +print <<"EOF"; +/* + * WARNING: do not edit! + * Generated by crypto/conf/keysets.pl + * + * Copyright 1995-$YEAR The OpenSSL Project Authors. All Rights Reserved. + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#define CONF_NUMBER $NUMBER +#define CONF_UPPER $UPPER +#define CONF_LOWER $LOWER +#define CONF_UNDER $UNDER +#define CONF_PUNCT $PUNCTUATION +#define CONF_WS $WS +#define CONF_ESC $ESC +#define CONF_QUOTE $QUOTE +#define CONF_DQUOTE $DQUOTE +#define CONF_COMMENT $COMMENT +#define CONF_FCOMMENT $FCOMMENT +#define CONF_EOF $EOF +#define CONF_ALPHA (CONF_UPPER|CONF_LOWER) +#define CONF_ALNUM (CONF_ALPHA|CONF_NUMBER|CONF_UNDER) +#define CONF_ALNUM_PUNCT (CONF_ALPHA|CONF_NUMBER|CONF_UNDER|CONF_PUNCT) + + +#define IS_COMMENT(conf,c) is_keytype(conf, c, CONF_COMMENT) +#define IS_FCOMMENT(conf,c) is_keytype(conf, c, CONF_FCOMMENT) +#define IS_EOF(conf,c) is_keytype(conf, c, CONF_EOF) +#define IS_ESC(conf,c) is_keytype(conf, c, CONF_ESC) +#define IS_NUMBER(conf,c) is_keytype(conf, c, CONF_NUMBER) +#define IS_WS(conf,c) is_keytype(conf, c, CONF_WS) +#define IS_ALNUM(conf,c) is_keytype(conf, c, CONF_ALNUM) +#define IS_ALNUM_PUNCT(conf,c) is_keytype(conf, c, CONF_ALNUM_PUNCT) +#define IS_QUOTE(conf,c) is_keytype(conf, c, CONF_QUOTE) +#define IS_DQUOTE(conf,c) is_keytype(conf, c, CONF_DQUOTE) + +EOF + +my $i; + +print "static const unsigned short CONF_type_default[128] = {"; +for ($i = 0; $i < 128; $i++) { + print "\n " if ($i % 8) == 0; + printf " 0x%04X,", $V_def[$i]; +} +print "\n};\n\n"; + +print "static const unsigned short CONF_type_win32[128] = {"; +for ($i = 0; $i < 128; $i++) { + print "\n " if ($i % 8) == 0; + printf " 0x%04X,", $V_w32[$i]; +} +print "\n};\n"; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cpt_err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/cpt_err.c new file mode 100644 index 000000000..4147b1cb9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cpt_err.c @@ -0,0 +1,77 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA CRYPTO_str_functs[] = { + {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CMAC_CTX_NEW, 0), "CMAC_CTX_new"}, + {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_DUP_EX_DATA, 0), + "CRYPTO_dup_ex_data"}, + {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_FREE_EX_DATA, 0), + "CRYPTO_free_ex_data"}, + {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX, 0), + "CRYPTO_get_ex_new_index"}, + {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_MEMDUP, 0), "CRYPTO_memdup"}, + {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_NEW_EX_DATA, 0), + "CRYPTO_new_ex_data"}, + {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_OCB128_COPY_CTX, 0), + "CRYPTO_ocb128_copy_ctx"}, + {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_OCB128_INIT, 0), + "CRYPTO_ocb128_init"}, + {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_SET_EX_DATA, 0), + "CRYPTO_set_ex_data"}, + {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_FIPS_MODE_SET, 0), "FIPS_mode_set"}, + {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_GET_AND_LOCK, 0), "get_and_lock"}, + {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OPENSSL_ATEXIT, 0), "OPENSSL_atexit"}, + {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OPENSSL_BUF2HEXSTR, 0), + "OPENSSL_buf2hexstr"}, + {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OPENSSL_FOPEN, 0), "openssl_fopen"}, + {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OPENSSL_HEXSTR2BUF, 0), + "OPENSSL_hexstr2buf"}, + {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OPENSSL_INIT_CRYPTO, 0), + "OPENSSL_init_crypto"}, + {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OPENSSL_LH_NEW, 0), "OPENSSL_LH_new"}, + {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OPENSSL_SK_DEEP_COPY, 0), + "OPENSSL_sk_deep_copy"}, + {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OPENSSL_SK_DUP, 0), "OPENSSL_sk_dup"}, + {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_PKEY_HMAC_INIT, 0), "pkey_hmac_init"}, + {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_PKEY_POLY1305_INIT, 0), + "pkey_poly1305_init"}, + {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_PKEY_SIPHASH_INIT, 0), + "pkey_siphash_init"}, + {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_SK_RESERVE, 0), "sk_reserve"}, + {0, NULL} +}; + +static const ERR_STRING_DATA CRYPTO_str_reasons[] = { + {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_FIPS_MODE_NOT_SUPPORTED), + "fips mode not supported"}, + {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_ILLEGAL_HEX_DIGIT), + "illegal hex digit"}, + {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_ODD_NUMBER_OF_DIGITS), + "odd number of digits"}, + {0, NULL} +}; + +#endif + +int ERR_load_CRYPTO_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(CRYPTO_str_functs[0].error) == NULL) { + ERR_load_strings_const(CRYPTO_str_functs); + ERR_load_strings_const(CRYPTO_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cryptlib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/cryptlib.c new file mode 100644 index 000000000..7b761a3ad --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cryptlib.c @@ -0,0 +1,473 @@ +/* + * Copyright 1998-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "e_os.h" +#include "internal/cryptlib_int.h" +#include + +#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ + defined(__x86_64) || defined(__x86_64__) || \ + defined(_M_AMD64) || defined(_M_X64) + +extern unsigned int OPENSSL_ia32cap_P[4]; + +# if defined(OPENSSL_CPUID_OBJ) && !defined(OPENSSL_NO_ASM) && !defined(I386_ONLY) + +/* + * Purpose of these minimalistic and character-type-agnostic subroutines + * is to break dependency on MSVCRT (on Windows) and locale. This makes + * OPENSSL_cpuid_setup safe to use as "constructor". "Character-type- + * agnostic" means that they work with either wide or 8-bit characters, + * exploiting the fact that first 127 characters can be simply casted + * between the sets, while the rest would be simply rejected by ossl_is* + * subroutines. + */ +# ifdef _WIN32 +typedef WCHAR variant_char; + +static variant_char *ossl_getenv(const char *name) +{ + /* + * Since we pull only one environment variable, it's simpler to + * to just ignore |name| and use equivalent wide-char L-literal. + * As well as to ignore excessively long values... + */ + static WCHAR value[48]; + DWORD len = GetEnvironmentVariableW(L"OPENSSL_ia32cap", value, 48); + + return (len > 0 && len < 48) ? value : NULL; +} +# else +typedef char variant_char; +# define ossl_getenv getenv +# endif + +# include "internal/ctype.h" + +static int todigit(variant_char c) +{ + if (ossl_isdigit(c)) + return c - '0'; + else if (ossl_isxdigit(c)) + return ossl_tolower(c) - 'a' + 10; + + /* return largest base value to make caller terminate the loop */ + return 16; +} + +static uint64_t ossl_strtouint64(const variant_char *str) +{ + uint64_t ret = 0; + unsigned int digit, base = 10; + + if (*str == '0') { + base = 8, str++; + if (ossl_tolower(*str) == 'x') + base = 16, str++; + } + + while((digit = todigit(*str++)) < base) + ret = ret * base + digit; + + return ret; +} + +static variant_char *ossl_strchr(const variant_char *str, char srch) +{ variant_char c; + + while((c = *str)) { + if (c == srch) + return (variant_char *)str; + str++; + } + + return NULL; +} + +# define OPENSSL_CPUID_SETUP +typedef uint64_t IA32CAP; + +void OPENSSL_cpuid_setup(void) +{ + static int trigger = 0; + IA32CAP OPENSSL_ia32_cpuid(unsigned int *); + IA32CAP vec; + const variant_char *env; + + if (trigger) + return; + + trigger = 1; + if ((env = ossl_getenv("OPENSSL_ia32cap")) != NULL) { + int off = (env[0] == '~') ? 1 : 0; + + vec = ossl_strtouint64(env + off); + + if (off) { + IA32CAP mask = vec; + vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P) & ~mask; + if (mask & (1<<24)) { + /* + * User disables FXSR bit, mask even other capabilities + * that operate exclusively on XMM, so we don't have to + * double-check all the time. We mask PCLMULQDQ, AMD XOP, + * AES-NI and AVX. Formally speaking we don't have to + * do it in x86_64 case, but we can safely assume that + * x86_64 users won't actually flip this flag. + */ + vec &= ~((IA32CAP)(1<<1|1<<11|1<<25|1<<28) << 32); + } + } else if (env[0] == ':') { + vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P); + } + + if ((env = ossl_strchr(env, ':')) != NULL) { + IA32CAP vecx; + + env++; + off = (env[0] == '~') ? 1 : 0; + vecx = ossl_strtouint64(env + off); + if (off) { + OPENSSL_ia32cap_P[2] &= ~(unsigned int)vecx; + OPENSSL_ia32cap_P[3] &= ~(unsigned int)(vecx >> 32); + } else { + OPENSSL_ia32cap_P[2] = (unsigned int)vecx; + OPENSSL_ia32cap_P[3] = (unsigned int)(vecx >> 32); + } + } else { + OPENSSL_ia32cap_P[2] = 0; + OPENSSL_ia32cap_P[3] = 0; + } + } else { + vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P); + } + + /* + * |(1<<10) sets a reserved bit to signal that variable + * was initialized already... This is to avoid interference + * with cpuid snippets in ELF .init segment. + */ + OPENSSL_ia32cap_P[0] = (unsigned int)vec | (1 << 10); + OPENSSL_ia32cap_P[1] = (unsigned int)(vec >> 32); +} +# else +unsigned int OPENSSL_ia32cap_P[4]; +# endif +#endif +#if !defined(OPENSSL_CPUID_SETUP) && !defined(OPENSSL_CPUID_OBJ) +void OPENSSL_cpuid_setup(void) +{ +} +#endif + +#if defined(_WIN32) +# include +# include +# ifdef __WATCOMC__ +# if defined(_UNICODE) || defined(__UNICODE__) +# define _vsntprintf _vsnwprintf +# else +# define _vsntprintf _vsnprintf +# endif +# endif +# ifdef _MSC_VER +# define alloca _alloca +# endif + +# if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333 +# ifdef OPENSSL_SYS_WIN_CORE + +int OPENSSL_isservice(void) +{ + /* OneCore API cannot interact with GUI */ + return 1; +} +# else +int OPENSSL_isservice(void) +{ + HWINSTA h; + DWORD len; + WCHAR *name; + static union { + void *p; + FARPROC f; + } _OPENSSL_isservice = { + NULL + }; + + if (_OPENSSL_isservice.p == NULL) { + HANDLE mod = GetModuleHandle(NULL); + FARPROC f = NULL; + + if (mod != NULL) + f = GetProcAddress(mod, "_OPENSSL_isservice"); + if (f == NULL) + _OPENSSL_isservice.p = (void *)-1; + else + _OPENSSL_isservice.f = f; + } + + if (_OPENSSL_isservice.p != (void *)-1) + return (*_OPENSSL_isservice.f) (); + + h = GetProcessWindowStation(); + if (h == NULL) + return -1; + + if (GetUserObjectInformationW(h, UOI_NAME, NULL, 0, &len) || + GetLastError() != ERROR_INSUFFICIENT_BUFFER) + return -1; + + if (len > 512) + return -1; /* paranoia */ + len++, len &= ~1; /* paranoia */ + name = (WCHAR *)alloca(len + sizeof(WCHAR)); + if (!GetUserObjectInformationW(h, UOI_NAME, name, len, &len)) + return -1; + + len++, len &= ~1; /* paranoia */ + name[len / sizeof(WCHAR)] = L'\0'; /* paranoia */ +# if 1 + /* + * This doesn't cover "interactive" services [working with real + * WinSta0's] nor programs started non-interactively by Task Scheduler + * [those are working with SAWinSta]. + */ + if (wcsstr(name, L"Service-0x")) + return 1; +# else + /* This covers all non-interactive programs such as services. */ + if (!wcsstr(name, L"WinSta0")) + return 1; +# endif + else + return 0; +} +# endif +# else +int OPENSSL_isservice(void) +{ + return 0; +} +# endif + +void OPENSSL_showfatal(const char *fmta, ...) +{ + va_list ap; + TCHAR buf[256]; + const TCHAR *fmt; + /* + * First check if it's a console application, in which case the + * error message would be printed to standard error. + * Windows CE does not have a concept of a console application, + * so we need to guard the check. + */ +# ifdef STD_ERROR_HANDLE + HANDLE h; + + if ((h = GetStdHandle(STD_ERROR_HANDLE)) != NULL && + GetFileType(h) != FILE_TYPE_UNKNOWN) { + /* must be console application */ + int len; + DWORD out; + + va_start(ap, fmta); + len = _vsnprintf((char *)buf, sizeof(buf), fmta, ap); + WriteFile(h, buf, len < 0 ? sizeof(buf) : (DWORD) len, &out, NULL); + va_end(ap); + return; + } +# endif + + if (sizeof(TCHAR) == sizeof(char)) + fmt = (const TCHAR *)fmta; + else + do { + int keepgoing; + size_t len_0 = strlen(fmta) + 1, i; + WCHAR *fmtw; + + fmtw = (WCHAR *)alloca(len_0 * sizeof(WCHAR)); + if (fmtw == NULL) { + fmt = (const TCHAR *)L"no stack?"; + break; + } + if (!MultiByteToWideChar(CP_ACP, 0, fmta, len_0, fmtw, len_0)) + for (i = 0; i < len_0; i++) + fmtw[i] = (WCHAR)fmta[i]; + for (i = 0; i < len_0; i++) { + if (fmtw[i] == L'%') + do { + keepgoing = 0; + switch (fmtw[i + 1]) { + case L'0': + case L'1': + case L'2': + case L'3': + case L'4': + case L'5': + case L'6': + case L'7': + case L'8': + case L'9': + case L'.': + case L'*': + case L'-': + i++; + keepgoing = 1; + break; + case L's': + fmtw[i + 1] = L'S'; + break; + case L'S': + fmtw[i + 1] = L's'; + break; + case L'c': + fmtw[i + 1] = L'C'; + break; + case L'C': + fmtw[i + 1] = L'c'; + break; + } + } while (keepgoing); + } + fmt = (const TCHAR *)fmtw; + } while (0); + + va_start(ap, fmta); + _vsntprintf(buf, OSSL_NELEM(buf) - 1, fmt, ap); + buf[OSSL_NELEM(buf) - 1] = _T('\0'); + va_end(ap); + +# if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333 +# ifdef OPENSSL_SYS_WIN_CORE + /* ONECORE is always NONGUI and NT >= 0x0601 */ + + /* + * TODO: (For non GUI and no std error cases) + * Add event logging feature here. + */ + +# if !defined(NDEBUG) + /* + * We are in a situation where we tried to report a critical + * error and this failed for some reason. As a last resort, + * in debug builds, send output to the debugger or any other + * tool like DebugView which can monitor the output. + */ + OutputDebugString(buf); +# endif +# else + /* this -------------v--- guards NT-specific calls */ + if (check_winnt() && OPENSSL_isservice() > 0) { + HANDLE hEventLog = RegisterEventSource(NULL, _T("OpenSSL")); + + if (hEventLog != NULL) { + const TCHAR *pmsg = buf; + + if (!ReportEvent(hEventLog, EVENTLOG_ERROR_TYPE, 0, 0, NULL, + 1, 0, &pmsg, NULL)) { +# if !defined(NDEBUG) + /* + * We are in a situation where we tried to report a critical + * error and this failed for some reason. As a last resort, + * in debug builds, send output to the debugger or any other + * tool like DebugView which can monitor the output. + */ + OutputDebugString(pmsg); +# endif + } + + (void)DeregisterEventSource(hEventLog); + } + } else { + MessageBox(NULL, buf, _T("OpenSSL: FATAL"), MB_OK | MB_ICONERROR); + } +# endif +# else + MessageBox(NULL, buf, _T("OpenSSL: FATAL"), MB_OK | MB_ICONERROR); +# endif +} +#else +void OPENSSL_showfatal(const char *fmta, ...) +{ +#ifndef OPENSSL_NO_STDIO + va_list ap; + + va_start(ap, fmta); + vfprintf(stderr, fmta, ap); + va_end(ap); +#endif +} + +int OPENSSL_isservice(void) +{ + return 0; +} +#endif + +void OPENSSL_die(const char *message, const char *file, int line) +{ + OPENSSL_showfatal("%s:%d: OpenSSL internal error: %s\n", + file, line, message); +#if !defined(_WIN32) + abort(); +#else + /* + * Win32 abort() customarily shows a dialog, but we just did that... + */ +# if !defined(_WIN32_WCE) + raise(SIGABRT); +# endif + _exit(3); +#endif +} + +#if !defined(OPENSSL_CPUID_OBJ) +/* + * The volatile is used to to ensure that the compiler generates code that reads + * all values from the array and doesn't try to optimize this away. The standard + * doesn't actually require this behavior if the original data pointed to is + * not volatile, but compilers do this in practice anyway. + * + * There are also assembler versions of this function. + */ +# undef CRYPTO_memcmp +int CRYPTO_memcmp(const void * in_a, const void * in_b, size_t len) +{ + size_t i; + const volatile unsigned char *a = in_a; + const volatile unsigned char *b = in_b; + unsigned char x = 0; + + for (i = 0; i < len; i++) + x |= a[i] ^ b[i]; + + return x; +} + +/* + * For systems that don't provide an instruction counter register or equivalent. + */ +uint32_t OPENSSL_rdtsc(void) +{ + return 0; +} + +size_t OPENSSL_instrument_bus(unsigned int *out, size_t cnt) +{ + return 0; +} + +size_t OPENSSL_instrument_bus2(unsigned int *out, size_t cnt, size_t max) +{ + return 0; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ct/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/ct/build.info new file mode 100644 index 000000000..3ca0e3160 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ct/build.info @@ -0,0 +1,3 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]= ct_b64.c ct_err.c ct_log.c ct_oct.c ct_policy.c \ + ct_prn.c ct_sct.c ct_sct_ctx.c ct_vfy.c ct_x509v3.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_b64.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_b64.c new file mode 100644 index 000000000..109ffcdcf --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_b64.c @@ -0,0 +1,168 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#include +#include +#include + +#include "ct_locl.h" + +/* + * Decodes the base64 string |in| into |out|. + * A new string will be malloc'd and assigned to |out|. This will be owned by + * the caller. Do not provide a pre-allocated string in |out|. + */ +static int ct_base64_decode(const char *in, unsigned char **out) +{ + size_t inlen = strlen(in); + int outlen, i; + unsigned char *outbuf = NULL; + + if (inlen == 0) { + *out = NULL; + return 0; + } + + outlen = (inlen / 4) * 3; + outbuf = OPENSSL_malloc(outlen); + if (outbuf == NULL) { + CTerr(CT_F_CT_BASE64_DECODE, ERR_R_MALLOC_FAILURE); + goto err; + } + + outlen = EVP_DecodeBlock(outbuf, (unsigned char *)in, inlen); + if (outlen < 0) { + CTerr(CT_F_CT_BASE64_DECODE, CT_R_BASE64_DECODE_ERROR); + goto err; + } + + /* Subtract padding bytes from |outlen|. Any more than 2 is malformed. */ + i = 0; + while (in[--inlen] == '=') { + --outlen; + if (++i > 2) + goto err; + } + + *out = outbuf; + return outlen; +err: + OPENSSL_free(outbuf); + return -1; +} + +SCT *SCT_new_from_base64(unsigned char version, const char *logid_base64, + ct_log_entry_type_t entry_type, uint64_t timestamp, + const char *extensions_base64, + const char *signature_base64) +{ + SCT *sct = SCT_new(); + unsigned char *dec = NULL; + const unsigned char* p = NULL; + int declen; + + if (sct == NULL) { + CTerr(CT_F_SCT_NEW_FROM_BASE64, ERR_R_MALLOC_FAILURE); + return NULL; + } + + /* + * RFC6962 section 4.1 says we "MUST NOT expect this to be 0", but we + * can only construct SCT versions that have been defined. + */ + if (!SCT_set_version(sct, version)) { + CTerr(CT_F_SCT_NEW_FROM_BASE64, CT_R_SCT_UNSUPPORTED_VERSION); + goto err; + } + + declen = ct_base64_decode(logid_base64, &dec); + if (declen < 0) { + CTerr(CT_F_SCT_NEW_FROM_BASE64, X509_R_BASE64_DECODE_ERROR); + goto err; + } + if (!SCT_set0_log_id(sct, dec, declen)) + goto err; + dec = NULL; + + declen = ct_base64_decode(extensions_base64, &dec); + if (declen < 0) { + CTerr(CT_F_SCT_NEW_FROM_BASE64, X509_R_BASE64_DECODE_ERROR); + goto err; + } + SCT_set0_extensions(sct, dec, declen); + dec = NULL; + + declen = ct_base64_decode(signature_base64, &dec); + if (declen < 0) { + CTerr(CT_F_SCT_NEW_FROM_BASE64, X509_R_BASE64_DECODE_ERROR); + goto err; + } + + p = dec; + if (o2i_SCT_signature(sct, &p, declen) <= 0) + goto err; + OPENSSL_free(dec); + dec = NULL; + + SCT_set_timestamp(sct, timestamp); + + if (!SCT_set_log_entry_type(sct, entry_type)) + goto err; + + return sct; + + err: + OPENSSL_free(dec); + SCT_free(sct); + return NULL; +} + +/* + * Allocate, build and returns a new |ct_log| from input |pkey_base64| + * It returns 1 on success, + * 0 on decoding failure, or invalid parameter if any + * -1 on internal (malloc) failure + */ +int CTLOG_new_from_base64(CTLOG **ct_log, const char *pkey_base64, const char *name) +{ + unsigned char *pkey_der = NULL; + int pkey_der_len; + const unsigned char *p; + EVP_PKEY *pkey = NULL; + + if (ct_log == NULL) { + CTerr(CT_F_CTLOG_NEW_FROM_BASE64, ERR_R_PASSED_INVALID_ARGUMENT); + return 0; + } + + pkey_der_len = ct_base64_decode(pkey_base64, &pkey_der); + if (pkey_der_len < 0) { + CTerr(CT_F_CTLOG_NEW_FROM_BASE64, CT_R_LOG_CONF_INVALID_KEY); + return 0; + } + + p = pkey_der; + pkey = d2i_PUBKEY(NULL, &p, pkey_der_len); + OPENSSL_free(pkey_der); + if (pkey == NULL) { + CTerr(CT_F_CTLOG_NEW_FROM_BASE64, CT_R_LOG_CONF_INVALID_KEY); + return 0; + } + + *ct_log = CTLOG_new(pkey, name); + if (*ct_log == NULL) { + EVP_PKEY_free(pkey); + return 0; + } + + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_err.c new file mode 100644 index 000000000..c0c62fee6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_err.c @@ -0,0 +1,96 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA CT_str_functs[] = { + {ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_NEW, 0), "CTLOG_new"}, + {ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_NEW_FROM_BASE64, 0), + "CTLOG_new_from_base64"}, + {ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_NEW_FROM_CONF, 0), "ctlog_new_from_conf"}, + {ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_STORE_LOAD_CTX_NEW, 0), + "ctlog_store_load_ctx_new"}, + {ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_STORE_LOAD_FILE, 0), + "CTLOG_STORE_load_file"}, + {ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_STORE_LOAD_LOG, 0), + "ctlog_store_load_log"}, + {ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_STORE_NEW, 0), "CTLOG_STORE_new"}, + {ERR_PACK(ERR_LIB_CT, CT_F_CT_BASE64_DECODE, 0), "ct_base64_decode"}, + {ERR_PACK(ERR_LIB_CT, CT_F_CT_POLICY_EVAL_CTX_NEW, 0), + "CT_POLICY_EVAL_CTX_new"}, + {ERR_PACK(ERR_LIB_CT, CT_F_CT_V1_LOG_ID_FROM_PKEY, 0), + "ct_v1_log_id_from_pkey"}, + {ERR_PACK(ERR_LIB_CT, CT_F_I2O_SCT, 0), "i2o_SCT"}, + {ERR_PACK(ERR_LIB_CT, CT_F_I2O_SCT_LIST, 0), "i2o_SCT_LIST"}, + {ERR_PACK(ERR_LIB_CT, CT_F_I2O_SCT_SIGNATURE, 0), "i2o_SCT_signature"}, + {ERR_PACK(ERR_LIB_CT, CT_F_O2I_SCT, 0), "o2i_SCT"}, + {ERR_PACK(ERR_LIB_CT, CT_F_O2I_SCT_LIST, 0), "o2i_SCT_LIST"}, + {ERR_PACK(ERR_LIB_CT, CT_F_O2I_SCT_SIGNATURE, 0), "o2i_SCT_signature"}, + {ERR_PACK(ERR_LIB_CT, CT_F_SCT_CTX_NEW, 0), "SCT_CTX_new"}, + {ERR_PACK(ERR_LIB_CT, CT_F_SCT_CTX_VERIFY, 0), "SCT_CTX_verify"}, + {ERR_PACK(ERR_LIB_CT, CT_F_SCT_NEW, 0), "SCT_new"}, + {ERR_PACK(ERR_LIB_CT, CT_F_SCT_NEW_FROM_BASE64, 0), "SCT_new_from_base64"}, + {ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET0_LOG_ID, 0), "SCT_set0_log_id"}, + {ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET1_EXTENSIONS, 0), "SCT_set1_extensions"}, + {ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET1_LOG_ID, 0), "SCT_set1_log_id"}, + {ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET1_SIGNATURE, 0), "SCT_set1_signature"}, + {ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET_LOG_ENTRY_TYPE, 0), + "SCT_set_log_entry_type"}, + {ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET_SIGNATURE_NID, 0), + "SCT_set_signature_nid"}, + {ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET_VERSION, 0), "SCT_set_version"}, + {0, NULL} +}; + +static const ERR_STRING_DATA CT_str_reasons[] = { + {ERR_PACK(ERR_LIB_CT, 0, CT_R_BASE64_DECODE_ERROR), "base64 decode error"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_INVALID_LOG_ID_LENGTH), + "invalid log id length"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_LOG_CONF_INVALID), "log conf invalid"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_LOG_CONF_INVALID_KEY), + "log conf invalid key"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_LOG_CONF_MISSING_DESCRIPTION), + "log conf missing description"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_LOG_CONF_MISSING_KEY), + "log conf missing key"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_LOG_KEY_INVALID), "log key invalid"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_FUTURE_TIMESTAMP), + "sct future timestamp"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_INVALID), "sct invalid"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_INVALID_SIGNATURE), + "sct invalid signature"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_LIST_INVALID), "sct list invalid"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_LOG_ID_MISMATCH), "sct log id mismatch"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_NOT_SET), "sct not set"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_UNSUPPORTED_VERSION), + "sct unsupported version"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_UNRECOGNIZED_SIGNATURE_NID), + "unrecognized signature nid"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_UNSUPPORTED_ENTRY_TYPE), + "unsupported entry type"}, + {ERR_PACK(ERR_LIB_CT, 0, CT_R_UNSUPPORTED_VERSION), "unsupported version"}, + {0, NULL} +}; + +#endif + +int ERR_load_CT_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(CT_str_functs[0].error) == NULL) { + ERR_load_strings_const(CT_str_functs); + ERR_load_strings_const(CT_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_locl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_locl.h new file mode 100644 index 000000000..9f983c91b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_locl.h @@ -0,0 +1,216 @@ +/* + * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include + +/* + * From RFC6962: opaque SerializedSCT<1..2^16-1>; struct { SerializedSCT + * sct_list <1..2^16-1>; } SignedCertificateTimestampList; + */ +# define MAX_SCT_SIZE 65535 +# define MAX_SCT_LIST_SIZE MAX_SCT_SIZE + +/* + * Macros to read and write integers in network-byte order. + */ + +#define n2s(c,s) ((s=(((unsigned int)((c)[0]))<< 8)| \ + (((unsigned int)((c)[1])) )),c+=2) + +#define s2n(s,c) ((c[0]=(unsigned char)(((s)>> 8)&0xff), \ + c[1]=(unsigned char)(((s) )&0xff)),c+=2) + +#define l2n3(l,c) ((c[0]=(unsigned char)(((l)>>16)&0xff), \ + c[1]=(unsigned char)(((l)>> 8)&0xff), \ + c[2]=(unsigned char)(((l) )&0xff)),c+=3) + +#define n2l8(c,l) (l =((uint64_t)(*((c)++)))<<56, \ + l|=((uint64_t)(*((c)++)))<<48, \ + l|=((uint64_t)(*((c)++)))<<40, \ + l|=((uint64_t)(*((c)++)))<<32, \ + l|=((uint64_t)(*((c)++)))<<24, \ + l|=((uint64_t)(*((c)++)))<<16, \ + l|=((uint64_t)(*((c)++)))<< 8, \ + l|=((uint64_t)(*((c)++)))) + +#define l2n8(l,c) (*((c)++)=(unsigned char)(((l)>>56)&0xff), \ + *((c)++)=(unsigned char)(((l)>>48)&0xff), \ + *((c)++)=(unsigned char)(((l)>>40)&0xff), \ + *((c)++)=(unsigned char)(((l)>>32)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +/* Signed Certificate Timestamp */ +struct sct_st { + sct_version_t version; + /* If version is not SCT_VERSION_V1, this contains the encoded SCT */ + unsigned char *sct; + size_t sct_len; + /* If version is SCT_VERSION_V1, fields below contain components of the SCT */ + unsigned char *log_id; + size_t log_id_len; + /* + * Note, we cannot distinguish between an unset timestamp, and one + * that is set to 0. However since CT didn't exist in 1970, no real + * SCT should ever be set as such. + */ + uint64_t timestamp; + unsigned char *ext; + size_t ext_len; + unsigned char hash_alg; + unsigned char sig_alg; + unsigned char *sig; + size_t sig_len; + /* Log entry type */ + ct_log_entry_type_t entry_type; + /* Where this SCT was found, e.g. certificate, OCSP response, etc. */ + sct_source_t source; + /* The result of the last attempt to validate this SCT. */ + sct_validation_status_t validation_status; +}; + +/* Miscellaneous data that is useful when verifying an SCT */ +struct sct_ctx_st { + /* Public key */ + EVP_PKEY *pkey; + /* Hash of public key */ + unsigned char *pkeyhash; + size_t pkeyhashlen; + /* For pre-certificate: issuer public key hash */ + unsigned char *ihash; + size_t ihashlen; + /* certificate encoding */ + unsigned char *certder; + size_t certderlen; + /* pre-certificate encoding */ + unsigned char *preder; + size_t prederlen; + /* milliseconds since epoch (to check that the SCT isn't from the future) */ + uint64_t epoch_time_in_ms; +}; + +/* Context when evaluating whether a Certificate Transparency policy is met */ +struct ct_policy_eval_ctx_st { + X509 *cert; + X509 *issuer; + CTLOG_STORE *log_store; + /* milliseconds since epoch (to check that SCTs aren't from the future) */ + uint64_t epoch_time_in_ms; +}; + +/* + * Creates a new context for verifying an SCT. + */ +SCT_CTX *SCT_CTX_new(void); +/* + * Deletes an SCT verification context. + */ +void SCT_CTX_free(SCT_CTX *sctx); + +/* + * Sets the certificate that the SCT was created for. + * If *cert does not have a poison extension, presigner must be NULL. + * If *cert does not have a poison extension, it may have a single SCT + * (NID_ct_precert_scts) extension. + * If either *cert or *presigner have an AKID (NID_authority_key_identifier) + * extension, both must have one. + * Returns 1 on success, 0 on failure. + */ +__owur int SCT_CTX_set1_cert(SCT_CTX *sctx, X509 *cert, X509 *presigner); + +/* + * Sets the issuer of the certificate that the SCT was created for. + * This is just a convenience method to save extracting the public key and + * calling SCT_CTX_set1_issuer_pubkey(). + * Issuer must not be NULL. + * Returns 1 on success, 0 on failure. + */ +__owur int SCT_CTX_set1_issuer(SCT_CTX *sctx, const X509 *issuer); + +/* + * Sets the public key of the issuer of the certificate that the SCT was created + * for. + * The public key must not be NULL. + * Returns 1 on success, 0 on failure. + */ +__owur int SCT_CTX_set1_issuer_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey); + +/* + * Sets the public key of the CT log that the SCT is from. + * Returns 1 on success, 0 on failure. + */ +__owur int SCT_CTX_set1_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey); + +/* + * Sets the time to evaluate the SCT against, in milliseconds since the Unix + * epoch. If the SCT's timestamp is after this time, it will be interpreted as + * having been issued in the future. RFC6962 states that "TLS clients MUST + * reject SCTs whose timestamp is in the future", so an SCT will not validate + * in this case. + */ +void SCT_CTX_set_time(SCT_CTX *sctx, uint64_t time_in_ms); + +/* + * Verifies an SCT with the given context. + * Returns 1 if the SCT verifies successfully; any other value indicates + * failure. See EVP_DigestVerifyFinal() for the meaning of those values. + */ +__owur int SCT_CTX_verify(const SCT_CTX *sctx, const SCT *sct); + +/* + * Does this SCT have the minimum fields populated to be usable? + * Returns 1 if so, 0 otherwise. + */ +__owur int SCT_is_complete(const SCT *sct); + +/* + * Does this SCT have the signature-related fields populated? + * Returns 1 if so, 0 otherwise. + * This checks that the signature and hash algorithms are set to supported + * values and that the signature field is set. + */ +__owur int SCT_signature_is_complete(const SCT *sct); + +/* + * TODO(RJPercival): Create an SCT_signature struct and make i2o_SCT_signature + * and o2i_SCT_signature conform to the i2d/d2i conventions. + */ + +/* +* Serialize (to TLS format) an |sct| signature and write it to |out|. +* If |out| is null, no signature will be output but the length will be returned. +* If |out| points to a null pointer, a string will be allocated to hold the +* TLS-format signature. It is the responsibility of the caller to free it. +* If |out| points to an allocated string, the signature will be written to it. +* The length of the signature in TLS format will be returned. +*/ +__owur int i2o_SCT_signature(const SCT *sct, unsigned char **out); + +/* +* Parses an SCT signature in TLS format and populates the |sct| with it. +* |in| should be a pointer to a string containing the TLS-format signature. +* |in| will be advanced to the end of the signature if parsing succeeds. +* |len| should be the length of the signature in |in|. +* Returns the number of bytes parsed, or a negative integer if an error occurs. +* If an error occurs, the SCT's signature NID may be updated whilst the +* signature field itself remains unset. +*/ +__owur int o2i_SCT_signature(SCT *sct, const unsigned char **in, size_t len); + +/* + * Handlers for Certificate Transparency X509v3/OCSP extensions + */ +extern const X509V3_EXT_METHOD v3_ct_scts[3]; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_log.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_log.c new file mode 100644 index 000000000..c1bca3e14 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_log.c @@ -0,0 +1,306 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "internal/cryptlib.h" + +/* + * Information about a CT log server. + */ +struct ctlog_st { + char *name; + uint8_t log_id[CT_V1_HASHLEN]; + EVP_PKEY *public_key; +}; + +/* + * A store for multiple CTLOG instances. + * It takes ownership of any CTLOG instances added to it. + */ +struct ctlog_store_st { + STACK_OF(CTLOG) *logs; +}; + +/* The context when loading a CT log list from a CONF file. */ +typedef struct ctlog_store_load_ctx_st { + CTLOG_STORE *log_store; + CONF *conf; + size_t invalid_log_entries; +} CTLOG_STORE_LOAD_CTX; + +/* + * Creates an empty context for loading a CT log store. + * It should be populated before use. + */ +static CTLOG_STORE_LOAD_CTX *ctlog_store_load_ctx_new(void); + +/* + * Deletes a CT log store load context. + * Does not delete any of the fields. + */ +static void ctlog_store_load_ctx_free(CTLOG_STORE_LOAD_CTX* ctx); + +static CTLOG_STORE_LOAD_CTX *ctlog_store_load_ctx_new(void) +{ + CTLOG_STORE_LOAD_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); + + if (ctx == NULL) + CTerr(CT_F_CTLOG_STORE_LOAD_CTX_NEW, ERR_R_MALLOC_FAILURE); + + return ctx; +} + +static void ctlog_store_load_ctx_free(CTLOG_STORE_LOAD_CTX* ctx) +{ + OPENSSL_free(ctx); +} + +/* Converts a log's public key into a SHA256 log ID */ +static int ct_v1_log_id_from_pkey(EVP_PKEY *pkey, + unsigned char log_id[CT_V1_HASHLEN]) +{ + int ret = 0; + unsigned char *pkey_der = NULL; + int pkey_der_len = i2d_PUBKEY(pkey, &pkey_der); + + if (pkey_der_len <= 0) { + CTerr(CT_F_CT_V1_LOG_ID_FROM_PKEY, CT_R_LOG_KEY_INVALID); + goto err; + } + + SHA256(pkey_der, pkey_der_len, log_id); + ret = 1; +err: + OPENSSL_free(pkey_der); + return ret; +} + +CTLOG_STORE *CTLOG_STORE_new(void) +{ + CTLOG_STORE *ret = OPENSSL_zalloc(sizeof(*ret)); + + if (ret == NULL) { + CTerr(CT_F_CTLOG_STORE_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + ret->logs = sk_CTLOG_new_null(); + if (ret->logs == NULL) + goto err; + + return ret; +err: + OPENSSL_free(ret); + return NULL; +} + +void CTLOG_STORE_free(CTLOG_STORE *store) +{ + if (store != NULL) { + sk_CTLOG_pop_free(store->logs, CTLOG_free); + OPENSSL_free(store); + } +} + +static int ctlog_new_from_conf(CTLOG **ct_log, const CONF *conf, const char *section) +{ + const char *description = NCONF_get_string(conf, section, "description"); + char *pkey_base64; + + if (description == NULL) { + CTerr(CT_F_CTLOG_NEW_FROM_CONF, CT_R_LOG_CONF_MISSING_DESCRIPTION); + return 0; + } + + pkey_base64 = NCONF_get_string(conf, section, "key"); + if (pkey_base64 == NULL) { + CTerr(CT_F_CTLOG_NEW_FROM_CONF, CT_R_LOG_CONF_MISSING_KEY); + return 0; + } + + return CTLOG_new_from_base64(ct_log, pkey_base64, description); +} + +int CTLOG_STORE_load_default_file(CTLOG_STORE *store) +{ + const char *fpath = ossl_safe_getenv(CTLOG_FILE_EVP); + + if (fpath == NULL) + fpath = CTLOG_FILE; + + return CTLOG_STORE_load_file(store, fpath); +} + +/* + * Called by CONF_parse_list, which stops if this returns <= 0, + * Otherwise, one bad log entry would stop loading of any of + * the following log entries. + * It may stop parsing and returns -1 on any internal (malloc) error. + */ +static int ctlog_store_load_log(const char *log_name, int log_name_len, + void *arg) +{ + CTLOG_STORE_LOAD_CTX *load_ctx = arg; + CTLOG *ct_log = NULL; + /* log_name may not be null-terminated, so fix that before using it */ + char *tmp; + int ret = 0; + + /* log_name will be NULL for empty list entries */ + if (log_name == NULL) + return 1; + + tmp = OPENSSL_strndup(log_name, log_name_len); + if (tmp == NULL) + goto mem_err; + + ret = ctlog_new_from_conf(&ct_log, load_ctx->conf, tmp); + OPENSSL_free(tmp); + + if (ret < 0) { + /* Propagate any internal error */ + return ret; + } + if (ret == 0) { + /* If we can't load this log, record that fact and skip it */ + ++load_ctx->invalid_log_entries; + return 1; + } + + if (!sk_CTLOG_push(load_ctx->log_store->logs, ct_log)) { + goto mem_err; + } + return 1; + +mem_err: + CTLOG_free(ct_log); + CTerr(CT_F_CTLOG_STORE_LOAD_LOG, ERR_R_MALLOC_FAILURE); + return -1; +} + +int CTLOG_STORE_load_file(CTLOG_STORE *store, const char *file) +{ + int ret = 0; + char *enabled_logs; + CTLOG_STORE_LOAD_CTX* load_ctx = ctlog_store_load_ctx_new(); + + if (load_ctx == NULL) + return 0; + load_ctx->log_store = store; + load_ctx->conf = NCONF_new(NULL); + if (load_ctx->conf == NULL) + goto end; + + if (NCONF_load(load_ctx->conf, file, NULL) <= 0) { + CTerr(CT_F_CTLOG_STORE_LOAD_FILE, CT_R_LOG_CONF_INVALID); + goto end; + } + + enabled_logs = NCONF_get_string(load_ctx->conf, NULL, "enabled_logs"); + if (enabled_logs == NULL) { + CTerr(CT_F_CTLOG_STORE_LOAD_FILE, CT_R_LOG_CONF_INVALID); + goto end; + } + + if (!CONF_parse_list(enabled_logs, ',', 1, ctlog_store_load_log, load_ctx) || + load_ctx->invalid_log_entries > 0) { + CTerr(CT_F_CTLOG_STORE_LOAD_FILE, CT_R_LOG_CONF_INVALID); + goto end; + } + + ret = 1; +end: + NCONF_free(load_ctx->conf); + ctlog_store_load_ctx_free(load_ctx); + return ret; +} + +/* + * Initialize a new CTLOG object. + * Takes ownership of the public key. + * Copies the name. + */ +CTLOG *CTLOG_new(EVP_PKEY *public_key, const char *name) +{ + CTLOG *ret = OPENSSL_zalloc(sizeof(*ret)); + + if (ret == NULL) { + CTerr(CT_F_CTLOG_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + ret->name = OPENSSL_strdup(name); + if (ret->name == NULL) { + CTerr(CT_F_CTLOG_NEW, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (ct_v1_log_id_from_pkey(public_key, ret->log_id) != 1) + goto err; + + ret->public_key = public_key; + return ret; +err: + CTLOG_free(ret); + return NULL; +} + +/* Frees CT log and associated structures */ +void CTLOG_free(CTLOG *log) +{ + if (log != NULL) { + OPENSSL_free(log->name); + EVP_PKEY_free(log->public_key); + OPENSSL_free(log); + } +} + +const char *CTLOG_get0_name(const CTLOG *log) +{ + return log->name; +} + +void CTLOG_get0_log_id(const CTLOG *log, const uint8_t **log_id, + size_t *log_id_len) +{ + *log_id = log->log_id; + *log_id_len = CT_V1_HASHLEN; +} + +EVP_PKEY *CTLOG_get0_public_key(const CTLOG *log) +{ + return log->public_key; +} + +/* + * Given a log ID, finds the matching log. + * Returns NULL if no match found. + */ +const CTLOG *CTLOG_STORE_get0_log_by_id(const CTLOG_STORE *store, + const uint8_t *log_id, + size_t log_id_len) +{ + int i; + + for (i = 0; i < sk_CTLOG_num(store->logs); ++i) { + const CTLOG *log = sk_CTLOG_value(store->logs, i); + if (memcmp(log->log_id, log_id, log_id_len) == 0) + return log; + } + + return NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_oct.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_oct.c new file mode 100644 index 000000000..0dd691c0f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_oct.c @@ -0,0 +1,407 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifdef OPENSSL_NO_CT +# error "CT is disabled" +#endif + +#include +#include + +#include +#include +#include +#include + +#include "ct_locl.h" + +int o2i_SCT_signature(SCT *sct, const unsigned char **in, size_t len) +{ + size_t siglen; + size_t len_remaining = len; + const unsigned char *p; + + if (sct->version != SCT_VERSION_V1) { + CTerr(CT_F_O2I_SCT_SIGNATURE, CT_R_UNSUPPORTED_VERSION); + return -1; + } + /* + * digitally-signed struct header: (1 byte) Hash algorithm (1 byte) + * Signature algorithm (2 bytes + ?) Signature + * + * This explicitly rejects empty signatures: they're invalid for + * all supported algorithms. + */ + if (len <= 4) { + CTerr(CT_F_O2I_SCT_SIGNATURE, CT_R_SCT_INVALID_SIGNATURE); + return -1; + } + + p = *in; + /* Get hash and signature algorithm */ + sct->hash_alg = *p++; + sct->sig_alg = *p++; + if (SCT_get_signature_nid(sct) == NID_undef) { + CTerr(CT_F_O2I_SCT_SIGNATURE, CT_R_SCT_INVALID_SIGNATURE); + return -1; + } + /* Retrieve signature and check it is consistent with the buffer length */ + n2s(p, siglen); + len_remaining -= (p - *in); + if (siglen > len_remaining) { + CTerr(CT_F_O2I_SCT_SIGNATURE, CT_R_SCT_INVALID_SIGNATURE); + return -1; + } + + if (SCT_set1_signature(sct, p, siglen) != 1) + return -1; + len_remaining -= siglen; + *in = p + siglen; + + return len - len_remaining; +} + +SCT *o2i_SCT(SCT **psct, const unsigned char **in, size_t len) +{ + SCT *sct = NULL; + const unsigned char *p; + + if (len == 0 || len > MAX_SCT_SIZE) { + CTerr(CT_F_O2I_SCT, CT_R_SCT_INVALID); + goto err; + } + + if ((sct = SCT_new()) == NULL) + goto err; + + p = *in; + + sct->version = *p; + if (sct->version == SCT_VERSION_V1) { + int sig_len; + size_t len2; + /*- + * Fixed-length header: + * struct { + * Version sct_version; (1 byte) + * log_id id; (32 bytes) + * uint64 timestamp; (8 bytes) + * CtExtensions extensions; (2 bytes + ?) + * } + */ + if (len < 43) { + CTerr(CT_F_O2I_SCT, CT_R_SCT_INVALID); + goto err; + } + len -= 43; + p++; + sct->log_id = BUF_memdup(p, CT_V1_HASHLEN); + if (sct->log_id == NULL) + goto err; + sct->log_id_len = CT_V1_HASHLEN; + p += CT_V1_HASHLEN; + + n2l8(p, sct->timestamp); + + n2s(p, len2); + if (len < len2) { + CTerr(CT_F_O2I_SCT, CT_R_SCT_INVALID); + goto err; + } + if (len2 > 0) { + sct->ext = BUF_memdup(p, len2); + if (sct->ext == NULL) + goto err; + } + sct->ext_len = len2; + p += len2; + len -= len2; + + sig_len = o2i_SCT_signature(sct, &p, len); + if (sig_len <= 0) { + CTerr(CT_F_O2I_SCT, CT_R_SCT_INVALID); + goto err; + } + len -= sig_len; + *in = p + len; + } else { + /* If not V1 just cache encoding */ + sct->sct = BUF_memdup(p, len); + if (sct->sct == NULL) + goto err; + sct->sct_len = len; + *in = p + len; + } + + if (psct != NULL) { + SCT_free(*psct); + *psct = sct; + } + + return sct; +err: + SCT_free(sct); + return NULL; +} + +int i2o_SCT_signature(const SCT *sct, unsigned char **out) +{ + size_t len; + unsigned char *p = NULL, *pstart = NULL; + + if (!SCT_signature_is_complete(sct)) { + CTerr(CT_F_I2O_SCT_SIGNATURE, CT_R_SCT_INVALID_SIGNATURE); + goto err; + } + + if (sct->version != SCT_VERSION_V1) { + CTerr(CT_F_I2O_SCT_SIGNATURE, CT_R_UNSUPPORTED_VERSION); + goto err; + } + + /* + * (1 byte) Hash algorithm + * (1 byte) Signature algorithm + * (2 bytes + ?) Signature + */ + len = 4 + sct->sig_len; + + if (out != NULL) { + if (*out != NULL) { + p = *out; + *out += len; + } else { + pstart = p = OPENSSL_malloc(len); + if (p == NULL) { + CTerr(CT_F_I2O_SCT_SIGNATURE, ERR_R_MALLOC_FAILURE); + goto err; + } + *out = p; + } + + *p++ = sct->hash_alg; + *p++ = sct->sig_alg; + s2n(sct->sig_len, p); + memcpy(p, sct->sig, sct->sig_len); + } + + return len; +err: + OPENSSL_free(pstart); + return -1; +} + +int i2o_SCT(const SCT *sct, unsigned char **out) +{ + size_t len; + unsigned char *p = NULL, *pstart = NULL; + + if (!SCT_is_complete(sct)) { + CTerr(CT_F_I2O_SCT, CT_R_SCT_NOT_SET); + goto err; + } + /* + * Fixed-length header: struct { (1 byte) Version sct_version; (32 bytes) + * log_id id; (8 bytes) uint64 timestamp; (2 bytes + ?) CtExtensions + * extensions; (1 byte) Hash algorithm (1 byte) Signature algorithm (2 + * bytes + ?) Signature + */ + if (sct->version == SCT_VERSION_V1) + len = 43 + sct->ext_len + 4 + sct->sig_len; + else + len = sct->sct_len; + + if (out == NULL) + return len; + + if (*out != NULL) { + p = *out; + *out += len; + } else { + pstart = p = OPENSSL_malloc(len); + if (p == NULL) { + CTerr(CT_F_I2O_SCT, ERR_R_MALLOC_FAILURE); + goto err; + } + *out = p; + } + + if (sct->version == SCT_VERSION_V1) { + *p++ = sct->version; + memcpy(p, sct->log_id, CT_V1_HASHLEN); + p += CT_V1_HASHLEN; + l2n8(sct->timestamp, p); + s2n(sct->ext_len, p); + if (sct->ext_len > 0) { + memcpy(p, sct->ext, sct->ext_len); + p += sct->ext_len; + } + if (i2o_SCT_signature(sct, &p) <= 0) + goto err; + } else { + memcpy(p, sct->sct, len); + } + + return len; +err: + OPENSSL_free(pstart); + return -1; +} + +STACK_OF(SCT) *o2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp, + size_t len) +{ + STACK_OF(SCT) *sk = NULL; + size_t list_len, sct_len; + + if (len < 2 || len > MAX_SCT_LIST_SIZE) { + CTerr(CT_F_O2I_SCT_LIST, CT_R_SCT_LIST_INVALID); + return NULL; + } + + n2s(*pp, list_len); + if (list_len != len - 2) { + CTerr(CT_F_O2I_SCT_LIST, CT_R_SCT_LIST_INVALID); + return NULL; + } + + if (a == NULL || *a == NULL) { + sk = sk_SCT_new_null(); + if (sk == NULL) + return NULL; + } else { + SCT *sct; + + /* Use the given stack, but empty it first. */ + sk = *a; + while ((sct = sk_SCT_pop(sk)) != NULL) + SCT_free(sct); + } + + while (list_len > 0) { + SCT *sct; + + if (list_len < 2) { + CTerr(CT_F_O2I_SCT_LIST, CT_R_SCT_LIST_INVALID); + goto err; + } + n2s(*pp, sct_len); + list_len -= 2; + + if (sct_len == 0 || sct_len > list_len) { + CTerr(CT_F_O2I_SCT_LIST, CT_R_SCT_LIST_INVALID); + goto err; + } + list_len -= sct_len; + + if ((sct = o2i_SCT(NULL, pp, sct_len)) == NULL) + goto err; + if (!sk_SCT_push(sk, sct)) { + SCT_free(sct); + goto err; + } + } + + if (a != NULL && *a == NULL) + *a = sk; + return sk; + + err: + if (a == NULL || *a == NULL) + SCT_LIST_free(sk); + return NULL; +} + +int i2o_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **pp) +{ + int len, sct_len, i, is_pp_new = 0; + size_t len2; + unsigned char *p = NULL, *p2; + + if (pp != NULL) { + if (*pp == NULL) { + if ((len = i2o_SCT_LIST(a, NULL)) == -1) { + CTerr(CT_F_I2O_SCT_LIST, CT_R_SCT_LIST_INVALID); + return -1; + } + if ((*pp = OPENSSL_malloc(len)) == NULL) { + CTerr(CT_F_I2O_SCT_LIST, ERR_R_MALLOC_FAILURE); + return -1; + } + is_pp_new = 1; + } + p = *pp + 2; + } + + len2 = 2; + for (i = 0; i < sk_SCT_num(a); i++) { + if (pp != NULL) { + p2 = p; + p += 2; + if ((sct_len = i2o_SCT(sk_SCT_value(a, i), &p)) == -1) + goto err; + s2n(sct_len, p2); + } else { + if ((sct_len = i2o_SCT(sk_SCT_value(a, i), NULL)) == -1) + goto err; + } + len2 += 2 + sct_len; + } + + if (len2 > MAX_SCT_LIST_SIZE) + goto err; + + if (pp != NULL) { + p = *pp; + s2n(len2 - 2, p); + if (!is_pp_new) + *pp += len2; + } + return len2; + + err: + if (is_pp_new) { + OPENSSL_free(*pp); + *pp = NULL; + } + return -1; +} + +STACK_OF(SCT) *d2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp, + long len) +{ + ASN1_OCTET_STRING *oct = NULL; + STACK_OF(SCT) *sk = NULL; + const unsigned char *p; + + p = *pp; + if (d2i_ASN1_OCTET_STRING(&oct, &p, len) == NULL) + return NULL; + + p = oct->data; + if ((sk = o2i_SCT_LIST(a, &p, oct->length)) != NULL) + *pp += len; + + ASN1_OCTET_STRING_free(oct); + return sk; +} + +int i2d_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **out) +{ + ASN1_OCTET_STRING oct; + int len; + + oct.data = NULL; + if ((oct.length = i2o_SCT_LIST(a, &oct.data)) == -1) + return -1; + + len = i2d_ASN1_OCTET_STRING(&oct, out); + OPENSSL_free(oct.data); + return len; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_policy.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_policy.c new file mode 100644 index 000000000..0d7b34638 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_policy.c @@ -0,0 +1,98 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifdef OPENSSL_NO_CT +# error "CT is disabled" +#endif + +#include +#include +#include + +#include "ct_locl.h" + +/* + * Number of seconds in the future that an SCT timestamp can be, by default, + * without being considered invalid. This is added to time() when setting a + * default value for CT_POLICY_EVAL_CTX.epoch_time_in_ms. + * It can be overridden by calling CT_POLICY_EVAL_CTX_set_time(). + */ +static const time_t SCT_CLOCK_DRIFT_TOLERANCE = 300; + +CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new(void) +{ + CT_POLICY_EVAL_CTX *ctx = OPENSSL_zalloc(sizeof(CT_POLICY_EVAL_CTX)); + + if (ctx == NULL) { + CTerr(CT_F_CT_POLICY_EVAL_CTX_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + /* time(NULL) shouldn't ever fail, so don't bother checking for -1. */ + ctx->epoch_time_in_ms = (uint64_t)(time(NULL) + SCT_CLOCK_DRIFT_TOLERANCE) * + 1000; + + return ctx; +} + +void CT_POLICY_EVAL_CTX_free(CT_POLICY_EVAL_CTX *ctx) +{ + if (ctx == NULL) + return; + X509_free(ctx->cert); + X509_free(ctx->issuer); + OPENSSL_free(ctx); +} + +int CT_POLICY_EVAL_CTX_set1_cert(CT_POLICY_EVAL_CTX *ctx, X509 *cert) +{ + if (!X509_up_ref(cert)) + return 0; + ctx->cert = cert; + return 1; +} + +int CT_POLICY_EVAL_CTX_set1_issuer(CT_POLICY_EVAL_CTX *ctx, X509 *issuer) +{ + if (!X509_up_ref(issuer)) + return 0; + ctx->issuer = issuer; + return 1; +} + +void CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE(CT_POLICY_EVAL_CTX *ctx, + CTLOG_STORE *log_store) +{ + ctx->log_store = log_store; +} + +void CT_POLICY_EVAL_CTX_set_time(CT_POLICY_EVAL_CTX *ctx, uint64_t time_in_ms) +{ + ctx->epoch_time_in_ms = time_in_ms; +} + +X509* CT_POLICY_EVAL_CTX_get0_cert(const CT_POLICY_EVAL_CTX *ctx) +{ + return ctx->cert; +} + +X509* CT_POLICY_EVAL_CTX_get0_issuer(const CT_POLICY_EVAL_CTX *ctx) +{ + return ctx->issuer; +} + +const CTLOG_STORE *CT_POLICY_EVAL_CTX_get0_log_store(const CT_POLICY_EVAL_CTX *ctx) +{ + return ctx->log_store; +} + +uint64_t CT_POLICY_EVAL_CTX_get_time(const CT_POLICY_EVAL_CTX *ctx) +{ + return ctx->epoch_time_in_ms; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_prn.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_prn.c new file mode 100644 index 000000000..376e04523 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_prn.c @@ -0,0 +1,127 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifdef OPENSSL_NO_CT +# error "CT is disabled" +#endif + +#include +#include + +#include "ct_locl.h" + +static void SCT_signature_algorithms_print(const SCT *sct, BIO *out) +{ + int nid = SCT_get_signature_nid(sct); + + if (nid == NID_undef) + BIO_printf(out, "%02X%02X", sct->hash_alg, sct->sig_alg); + else + BIO_printf(out, "%s", OBJ_nid2ln(nid)); +} + +static void timestamp_print(uint64_t timestamp, BIO *out) +{ + ASN1_GENERALIZEDTIME *gen = ASN1_GENERALIZEDTIME_new(); + char genstr[20]; + + if (gen == NULL) + return; + ASN1_GENERALIZEDTIME_adj(gen, (time_t)0, + (int)(timestamp / 86400000), + (timestamp % 86400000) / 1000); + /* + * Note GeneralizedTime from ASN1_GENERALIZETIME_adj is always 15 + * characters long with a final Z. Update it with fractional seconds. + */ + BIO_snprintf(genstr, sizeof(genstr), "%.14s.%03dZ", + ASN1_STRING_get0_data(gen), (unsigned int)(timestamp % 1000)); + if (ASN1_GENERALIZEDTIME_set_string(gen, genstr)) + ASN1_GENERALIZEDTIME_print(out, gen); + ASN1_GENERALIZEDTIME_free(gen); +} + +const char *SCT_validation_status_string(const SCT *sct) +{ + + switch (SCT_get_validation_status(sct)) { + case SCT_VALIDATION_STATUS_NOT_SET: + return "not set"; + case SCT_VALIDATION_STATUS_UNKNOWN_VERSION: + return "unknown version"; + case SCT_VALIDATION_STATUS_UNKNOWN_LOG: + return "unknown log"; + case SCT_VALIDATION_STATUS_UNVERIFIED: + return "unverified"; + case SCT_VALIDATION_STATUS_INVALID: + return "invalid"; + case SCT_VALIDATION_STATUS_VALID: + return "valid"; + } + return "unknown status"; +} + +void SCT_print(const SCT *sct, BIO *out, int indent, + const CTLOG_STORE *log_store) +{ + const CTLOG *log = NULL; + + if (log_store != NULL) { + log = CTLOG_STORE_get0_log_by_id(log_store, sct->log_id, + sct->log_id_len); + } + + BIO_printf(out, "%*sSigned Certificate Timestamp:", indent, ""); + BIO_printf(out, "\n%*sVersion : ", indent + 4, ""); + + if (sct->version != SCT_VERSION_V1) { + BIO_printf(out, "unknown\n%*s", indent + 16, ""); + BIO_hex_string(out, indent + 16, 16, sct->sct, sct->sct_len); + return; + } + + BIO_printf(out, "v1 (0x0)"); + + if (log != NULL) { + BIO_printf(out, "\n%*sLog : %s", indent + 4, "", + CTLOG_get0_name(log)); + } + + BIO_printf(out, "\n%*sLog ID : ", indent + 4, ""); + BIO_hex_string(out, indent + 16, 16, sct->log_id, sct->log_id_len); + + BIO_printf(out, "\n%*sTimestamp : ", indent + 4, ""); + timestamp_print(sct->timestamp, out); + + BIO_printf(out, "\n%*sExtensions: ", indent + 4, ""); + if (sct->ext_len == 0) + BIO_printf(out, "none"); + else + BIO_hex_string(out, indent + 16, 16, sct->ext, sct->ext_len); + + BIO_printf(out, "\n%*sSignature : ", indent + 4, ""); + SCT_signature_algorithms_print(sct, out); + BIO_printf(out, "\n%*s ", indent + 4, ""); + BIO_hex_string(out, indent + 16, 16, sct->sig, sct->sig_len); +} + +void SCT_LIST_print(const STACK_OF(SCT) *sct_list, BIO *out, int indent, + const char *separator, const CTLOG_STORE *log_store) +{ + int sct_count = sk_SCT_num(sct_list); + int i; + + for (i = 0; i < sct_count; ++i) { + SCT *sct = sk_SCT_value(sct_list, i); + + SCT_print(sct, out, indent, log_store); + if (i < sk_SCT_num(sct_list) - 1) + BIO_printf(out, "%s", separator); + } +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_sct.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_sct.c new file mode 100644 index 000000000..1dc16857b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_sct.c @@ -0,0 +1,396 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifdef OPENSSL_NO_CT +# error "CT disabled" +#endif + +#include +#include +#include +#include +#include + +#include "ct_locl.h" + +SCT *SCT_new(void) +{ + SCT *sct = OPENSSL_zalloc(sizeof(*sct)); + + if (sct == NULL) { + CTerr(CT_F_SCT_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + sct->entry_type = CT_LOG_ENTRY_TYPE_NOT_SET; + sct->version = SCT_VERSION_NOT_SET; + return sct; +} + +void SCT_free(SCT *sct) +{ + if (sct == NULL) + return; + + OPENSSL_free(sct->log_id); + OPENSSL_free(sct->ext); + OPENSSL_free(sct->sig); + OPENSSL_free(sct->sct); + OPENSSL_free(sct); +} + +void SCT_LIST_free(STACK_OF(SCT) *a) +{ + sk_SCT_pop_free(a, SCT_free); +} + +int SCT_set_version(SCT *sct, sct_version_t version) +{ + if (version != SCT_VERSION_V1) { + CTerr(CT_F_SCT_SET_VERSION, CT_R_UNSUPPORTED_VERSION); + return 0; + } + sct->version = version; + sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; + return 1; +} + +int SCT_set_log_entry_type(SCT *sct, ct_log_entry_type_t entry_type) +{ + sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; + + switch (entry_type) { + case CT_LOG_ENTRY_TYPE_X509: + case CT_LOG_ENTRY_TYPE_PRECERT: + sct->entry_type = entry_type; + return 1; + case CT_LOG_ENTRY_TYPE_NOT_SET: + break; + } + CTerr(CT_F_SCT_SET_LOG_ENTRY_TYPE, CT_R_UNSUPPORTED_ENTRY_TYPE); + return 0; +} + +int SCT_set0_log_id(SCT *sct, unsigned char *log_id, size_t log_id_len) +{ + if (sct->version == SCT_VERSION_V1 && log_id_len != CT_V1_HASHLEN) { + CTerr(CT_F_SCT_SET0_LOG_ID, CT_R_INVALID_LOG_ID_LENGTH); + return 0; + } + + OPENSSL_free(sct->log_id); + sct->log_id = log_id; + sct->log_id_len = log_id_len; + sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; + return 1; +} + +int SCT_set1_log_id(SCT *sct, const unsigned char *log_id, size_t log_id_len) +{ + if (sct->version == SCT_VERSION_V1 && log_id_len != CT_V1_HASHLEN) { + CTerr(CT_F_SCT_SET1_LOG_ID, CT_R_INVALID_LOG_ID_LENGTH); + return 0; + } + + OPENSSL_free(sct->log_id); + sct->log_id = NULL; + sct->log_id_len = 0; + sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; + + if (log_id != NULL && log_id_len > 0) { + sct->log_id = OPENSSL_memdup(log_id, log_id_len); + if (sct->log_id == NULL) { + CTerr(CT_F_SCT_SET1_LOG_ID, ERR_R_MALLOC_FAILURE); + return 0; + } + sct->log_id_len = log_id_len; + } + return 1; +} + + +void SCT_set_timestamp(SCT *sct, uint64_t timestamp) +{ + sct->timestamp = timestamp; + sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; +} + +int SCT_set_signature_nid(SCT *sct, int nid) +{ + switch (nid) { + case NID_sha256WithRSAEncryption: + sct->hash_alg = TLSEXT_hash_sha256; + sct->sig_alg = TLSEXT_signature_rsa; + sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; + return 1; + case NID_ecdsa_with_SHA256: + sct->hash_alg = TLSEXT_hash_sha256; + sct->sig_alg = TLSEXT_signature_ecdsa; + sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; + return 1; + default: + CTerr(CT_F_SCT_SET_SIGNATURE_NID, CT_R_UNRECOGNIZED_SIGNATURE_NID); + return 0; + } +} + +void SCT_set0_extensions(SCT *sct, unsigned char *ext, size_t ext_len) +{ + OPENSSL_free(sct->ext); + sct->ext = ext; + sct->ext_len = ext_len; + sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; +} + +int SCT_set1_extensions(SCT *sct, const unsigned char *ext, size_t ext_len) +{ + OPENSSL_free(sct->ext); + sct->ext = NULL; + sct->ext_len = 0; + sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; + + if (ext != NULL && ext_len > 0) { + sct->ext = OPENSSL_memdup(ext, ext_len); + if (sct->ext == NULL) { + CTerr(CT_F_SCT_SET1_EXTENSIONS, ERR_R_MALLOC_FAILURE); + return 0; + } + sct->ext_len = ext_len; + } + return 1; +} + +void SCT_set0_signature(SCT *sct, unsigned char *sig, size_t sig_len) +{ + OPENSSL_free(sct->sig); + sct->sig = sig; + sct->sig_len = sig_len; + sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; +} + +int SCT_set1_signature(SCT *sct, const unsigned char *sig, size_t sig_len) +{ + OPENSSL_free(sct->sig); + sct->sig = NULL; + sct->sig_len = 0; + sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; + + if (sig != NULL && sig_len > 0) { + sct->sig = OPENSSL_memdup(sig, sig_len); + if (sct->sig == NULL) { + CTerr(CT_F_SCT_SET1_SIGNATURE, ERR_R_MALLOC_FAILURE); + return 0; + } + sct->sig_len = sig_len; + } + return 1; +} + +sct_version_t SCT_get_version(const SCT *sct) +{ + return sct->version; +} + +ct_log_entry_type_t SCT_get_log_entry_type(const SCT *sct) +{ + return sct->entry_type; +} + +size_t SCT_get0_log_id(const SCT *sct, unsigned char **log_id) +{ + *log_id = sct->log_id; + return sct->log_id_len; +} + +uint64_t SCT_get_timestamp(const SCT *sct) +{ + return sct->timestamp; +} + +int SCT_get_signature_nid(const SCT *sct) +{ + if (sct->version == SCT_VERSION_V1) { + if (sct->hash_alg == TLSEXT_hash_sha256) { + switch (sct->sig_alg) { + case TLSEXT_signature_ecdsa: + return NID_ecdsa_with_SHA256; + case TLSEXT_signature_rsa: + return NID_sha256WithRSAEncryption; + default: + return NID_undef; + } + } + } + return NID_undef; +} + +size_t SCT_get0_extensions(const SCT *sct, unsigned char **ext) +{ + *ext = sct->ext; + return sct->ext_len; +} + +size_t SCT_get0_signature(const SCT *sct, unsigned char **sig) +{ + *sig = sct->sig; + return sct->sig_len; +} + +int SCT_is_complete(const SCT *sct) +{ + switch (sct->version) { + case SCT_VERSION_NOT_SET: + return 0; + case SCT_VERSION_V1: + return sct->log_id != NULL && SCT_signature_is_complete(sct); + default: + return sct->sct != NULL; /* Just need cached encoding */ + } +} + +int SCT_signature_is_complete(const SCT *sct) +{ + return SCT_get_signature_nid(sct) != NID_undef && + sct->sig != NULL && sct->sig_len > 0; +} + +sct_source_t SCT_get_source(const SCT *sct) +{ + return sct->source; +} + +int SCT_set_source(SCT *sct, sct_source_t source) +{ + sct->source = source; + sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; + switch (source) { + case SCT_SOURCE_TLS_EXTENSION: + case SCT_SOURCE_OCSP_STAPLED_RESPONSE: + return SCT_set_log_entry_type(sct, CT_LOG_ENTRY_TYPE_X509); + case SCT_SOURCE_X509V3_EXTENSION: + return SCT_set_log_entry_type(sct, CT_LOG_ENTRY_TYPE_PRECERT); + case SCT_SOURCE_UNKNOWN: + break; + } + /* if we aren't sure, leave the log entry type alone */ + return 1; +} + +sct_validation_status_t SCT_get_validation_status(const SCT *sct) +{ + return sct->validation_status; +} + +int SCT_validate(SCT *sct, const CT_POLICY_EVAL_CTX *ctx) +{ + int is_sct_valid = -1; + SCT_CTX *sctx = NULL; + X509_PUBKEY *pub = NULL, *log_pkey = NULL; + const CTLOG *log; + + /* + * With an unrecognized SCT version we don't know what such an SCT means, + * let alone validate one. So we return validation failure (0). + */ + if (sct->version != SCT_VERSION_V1) { + sct->validation_status = SCT_VALIDATION_STATUS_UNKNOWN_VERSION; + return 0; + } + + log = CTLOG_STORE_get0_log_by_id(ctx->log_store, + sct->log_id, sct->log_id_len); + + /* Similarly, an SCT from an unknown log also cannot be validated. */ + if (log == NULL) { + sct->validation_status = SCT_VALIDATION_STATUS_UNKNOWN_LOG; + return 0; + } + + sctx = SCT_CTX_new(); + if (sctx == NULL) + goto err; + + if (X509_PUBKEY_set(&log_pkey, CTLOG_get0_public_key(log)) != 1) + goto err; + if (SCT_CTX_set1_pubkey(sctx, log_pkey) != 1) + goto err; + + if (SCT_get_log_entry_type(sct) == CT_LOG_ENTRY_TYPE_PRECERT) { + EVP_PKEY *issuer_pkey; + + if (ctx->issuer == NULL) { + sct->validation_status = SCT_VALIDATION_STATUS_UNVERIFIED; + goto end; + } + + issuer_pkey = X509_get0_pubkey(ctx->issuer); + + if (X509_PUBKEY_set(&pub, issuer_pkey) != 1) + goto err; + if (SCT_CTX_set1_issuer_pubkey(sctx, pub) != 1) + goto err; + } + + SCT_CTX_set_time(sctx, ctx->epoch_time_in_ms); + + /* + * XXX: Potential for optimization. This repeats some idempotent heavy + * lifting on the certificate for each candidate SCT, and appears to not + * use any information in the SCT itself, only the certificate is + * processed. So it may make more sense to to do this just once, perhaps + * associated with the shared (by all SCTs) policy eval ctx. + * + * XXX: Failure here is global (SCT independent) and represents either an + * issue with the certificate (e.g. duplicate extensions) or an out of + * memory condition. When the certificate is incompatible with CT, we just + * mark the SCTs invalid, rather than report a failure to determine the + * validation status. That way, callbacks that want to do "soft" SCT + * processing will not abort handshakes with false positive internal + * errors. Since the function does not distinguish between certificate + * issues (peer's fault) and internal problems (out fault) the safe thing + * to do is to report a validation failure and let the callback or + * application decide what to do. + */ + if (SCT_CTX_set1_cert(sctx, ctx->cert, NULL) != 1) + sct->validation_status = SCT_VALIDATION_STATUS_UNVERIFIED; + else + sct->validation_status = SCT_CTX_verify(sctx, sct) == 1 ? + SCT_VALIDATION_STATUS_VALID : SCT_VALIDATION_STATUS_INVALID; + +end: + is_sct_valid = sct->validation_status == SCT_VALIDATION_STATUS_VALID; +err: + X509_PUBKEY_free(pub); + X509_PUBKEY_free(log_pkey); + SCT_CTX_free(sctx); + + return is_sct_valid; +} + +int SCT_LIST_validate(const STACK_OF(SCT) *scts, CT_POLICY_EVAL_CTX *ctx) +{ + int are_scts_valid = 1; + int sct_count = scts != NULL ? sk_SCT_num(scts) : 0; + int i; + + for (i = 0; i < sct_count; ++i) { + int is_sct_valid = -1; + SCT *sct = sk_SCT_value(scts, i); + + if (sct == NULL) + continue; + + is_sct_valid = SCT_validate(sct, ctx); + if (is_sct_valid < 0) + return is_sct_valid; + are_scts_valid &= is_sct_valid; + } + + return are_scts_valid; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_sct_ctx.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_sct_ctx.c new file mode 100644 index 000000000..75a5027df --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_sct_ctx.c @@ -0,0 +1,263 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifdef OPENSSL_NO_CT +# error "CT is disabled" +#endif + +#include +#include + +#include +#include +#include + +#include "ct_locl.h" + +SCT_CTX *SCT_CTX_new(void) +{ + SCT_CTX *sctx = OPENSSL_zalloc(sizeof(*sctx)); + + if (sctx == NULL) + CTerr(CT_F_SCT_CTX_NEW, ERR_R_MALLOC_FAILURE); + + return sctx; +} + +void SCT_CTX_free(SCT_CTX *sctx) +{ + if (sctx == NULL) + return; + EVP_PKEY_free(sctx->pkey); + OPENSSL_free(sctx->pkeyhash); + OPENSSL_free(sctx->ihash); + OPENSSL_free(sctx->certder); + OPENSSL_free(sctx->preder); + OPENSSL_free(sctx); +} + +/* + * Finds the index of the first extension with the given NID in cert. + * If there is more than one extension with that NID, *is_duplicated is set to + * 1, otherwise 0 (unless it is NULL). + */ +static int ct_x509_get_ext(X509 *cert, int nid, int *is_duplicated) +{ + int ret = X509_get_ext_by_NID(cert, nid, -1); + + if (is_duplicated != NULL) + *is_duplicated = ret >= 0 && X509_get_ext_by_NID(cert, nid, ret) >= 0; + + return ret; +} + +/* + * Modifies a certificate by deleting extensions and copying the issuer and + * AKID from the presigner certificate, if necessary. + * Returns 1 on success, 0 otherwise. + */ +__owur static int ct_x509_cert_fixup(X509 *cert, X509 *presigner) +{ + int preidx, certidx; + int pre_akid_ext_is_dup, cert_akid_ext_is_dup; + + if (presigner == NULL) + return 1; + + preidx = ct_x509_get_ext(presigner, NID_authority_key_identifier, + &pre_akid_ext_is_dup); + certidx = ct_x509_get_ext(cert, NID_authority_key_identifier, + &cert_akid_ext_is_dup); + + /* An error occurred whilst searching for the extension */ + if (preidx < -1 || certidx < -1) + return 0; + /* Invalid certificate if they contain duplicate extensions */ + if (pre_akid_ext_is_dup || cert_akid_ext_is_dup) + return 0; + /* AKID must be present in both certificate or absent in both */ + if (preidx >= 0 && certidx == -1) + return 0; + if (preidx == -1 && certidx >= 0) + return 0; + /* Copy issuer name */ + if (!X509_set_issuer_name(cert, X509_get_issuer_name(presigner))) + return 0; + if (preidx != -1) { + /* Retrieve and copy AKID encoding */ + X509_EXTENSION *preext = X509_get_ext(presigner, preidx); + X509_EXTENSION *certext = X509_get_ext(cert, certidx); + ASN1_OCTET_STRING *preextdata; + + /* Should never happen */ + if (preext == NULL || certext == NULL) + return 0; + preextdata = X509_EXTENSION_get_data(preext); + if (preextdata == NULL || + !X509_EXTENSION_set_data(certext, preextdata)) + return 0; + } + return 1; +} + +int SCT_CTX_set1_cert(SCT_CTX *sctx, X509 *cert, X509 *presigner) +{ + unsigned char *certder = NULL, *preder = NULL; + X509 *pretmp = NULL; + int certderlen = 0, prederlen = 0; + int idx = -1; + int poison_ext_is_dup, sct_ext_is_dup; + int poison_idx = ct_x509_get_ext(cert, NID_ct_precert_poison, &poison_ext_is_dup); + + /* Duplicate poison extensions are present - error */ + if (poison_ext_is_dup) + goto err; + + /* If *cert doesn't have a poison extension, it isn't a precert */ + if (poison_idx == -1) { + /* cert isn't a precert, so we shouldn't have a presigner */ + if (presigner != NULL) + goto err; + + certderlen = i2d_X509(cert, &certder); + if (certderlen < 0) + goto err; + } + + /* See if cert has a precert SCTs extension */ + idx = ct_x509_get_ext(cert, NID_ct_precert_scts, &sct_ext_is_dup); + /* Duplicate SCT extensions are present - error */ + if (sct_ext_is_dup) + goto err; + + if (idx >= 0 && poison_idx >= 0) { + /* + * cert can't both contain SCTs (i.e. have an SCT extension) and be a + * precert (i.e. have a poison extension). + */ + goto err; + } + + if (idx == -1) { + idx = poison_idx; + } + + /* + * If either a poison or SCT extension is present, remove it before encoding + * cert. This, along with ct_x509_cert_fixup(), gets a TBSCertificate (see + * RFC5280) from cert, which is what the CT log signed when it produced the + * SCT. + */ + if (idx >= 0) { + X509_EXTENSION *ext; + + /* Take a copy of certificate so we don't modify passed version */ + pretmp = X509_dup(cert); + if (pretmp == NULL) + goto err; + + ext = X509_delete_ext(pretmp, idx); + X509_EXTENSION_free(ext); + + if (!ct_x509_cert_fixup(pretmp, presigner)) + goto err; + + prederlen = i2d_re_X509_tbs(pretmp, &preder); + if (prederlen <= 0) + goto err; + } + + X509_free(pretmp); + + OPENSSL_free(sctx->certder); + sctx->certder = certder; + sctx->certderlen = certderlen; + + OPENSSL_free(sctx->preder); + sctx->preder = preder; + sctx->prederlen = prederlen; + + return 1; +err: + OPENSSL_free(certder); + OPENSSL_free(preder); + X509_free(pretmp); + return 0; +} + +__owur static int ct_public_key_hash(X509_PUBKEY *pkey, unsigned char **hash, + size_t *hash_len) +{ + int ret = 0; + unsigned char *md = NULL, *der = NULL; + int der_len; + unsigned int md_len; + + /* Reuse buffer if possible */ + if (*hash != NULL && *hash_len >= SHA256_DIGEST_LENGTH) { + md = *hash; + } else { + md = OPENSSL_malloc(SHA256_DIGEST_LENGTH); + if (md == NULL) + goto err; + } + + /* Calculate key hash */ + der_len = i2d_X509_PUBKEY(pkey, &der); + if (der_len <= 0) + goto err; + + if (!EVP_Digest(der, der_len, md, &md_len, EVP_sha256(), NULL)) + goto err; + + if (md != *hash) { + OPENSSL_free(*hash); + *hash = md; + *hash_len = SHA256_DIGEST_LENGTH; + } + + md = NULL; + ret = 1; + err: + OPENSSL_free(md); + OPENSSL_free(der); + return ret; +} + +int SCT_CTX_set1_issuer(SCT_CTX *sctx, const X509 *issuer) +{ + return SCT_CTX_set1_issuer_pubkey(sctx, X509_get_X509_PUBKEY(issuer)); +} + +int SCT_CTX_set1_issuer_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey) +{ + return ct_public_key_hash(pubkey, &sctx->ihash, &sctx->ihashlen); +} + +int SCT_CTX_set1_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey) +{ + EVP_PKEY *pkey = X509_PUBKEY_get(pubkey); + + if (pkey == NULL) + return 0; + + if (!ct_public_key_hash(pubkey, &sctx->pkeyhash, &sctx->pkeyhashlen)) { + EVP_PKEY_free(pkey); + return 0; + } + + EVP_PKEY_free(sctx->pkey); + sctx->pkey = pkey; + return 1; +} + +void SCT_CTX_set_time(SCT_CTX *sctx, uint64_t time_in_ms) +{ + sctx->epoch_time_in_ms = time_in_ms; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_vfy.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_vfy.c new file mode 100644 index 000000000..cabcf5782 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_vfy.c @@ -0,0 +1,140 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#include +#include +#include +#include + +#include "ct_locl.h" + +typedef enum sct_signature_type_t { + SIGNATURE_TYPE_NOT_SET = -1, + SIGNATURE_TYPE_CERT_TIMESTAMP, + SIGNATURE_TYPE_TREE_HASH +} SCT_SIGNATURE_TYPE; + +/* + * Update encoding for SCT signature verification/generation to supplied + * EVP_MD_CTX. + */ +static int sct_ctx_update(EVP_MD_CTX *ctx, const SCT_CTX *sctx, const SCT *sct) +{ + unsigned char tmpbuf[12]; + unsigned char *p, *der; + size_t derlen; + /*+ + * digitally-signed struct { + * (1 byte) Version sct_version; + * (1 byte) SignatureType signature_type = certificate_timestamp; + * (8 bytes) uint64 timestamp; + * (2 bytes) LogEntryType entry_type; + * (? bytes) select(entry_type) { + * case x509_entry: ASN.1Cert; + * case precert_entry: PreCert; + * } signed_entry; + * (2 bytes + sct->ext_len) CtExtensions extensions; + * } + */ + if (sct->entry_type == CT_LOG_ENTRY_TYPE_NOT_SET) + return 0; + if (sct->entry_type == CT_LOG_ENTRY_TYPE_PRECERT && sctx->ihash == NULL) + return 0; + + p = tmpbuf; + *p++ = sct->version; + *p++ = SIGNATURE_TYPE_CERT_TIMESTAMP; + l2n8(sct->timestamp, p); + s2n(sct->entry_type, p); + + if (!EVP_DigestUpdate(ctx, tmpbuf, p - tmpbuf)) + return 0; + + if (sct->entry_type == CT_LOG_ENTRY_TYPE_X509) { + der = sctx->certder; + derlen = sctx->certderlen; + } else { + if (!EVP_DigestUpdate(ctx, sctx->ihash, sctx->ihashlen)) + return 0; + der = sctx->preder; + derlen = sctx->prederlen; + } + + /* If no encoding available, fatal error */ + if (der == NULL) + return 0; + + /* Include length first */ + p = tmpbuf; + l2n3(derlen, p); + + if (!EVP_DigestUpdate(ctx, tmpbuf, 3)) + return 0; + if (!EVP_DigestUpdate(ctx, der, derlen)) + return 0; + + /* Add any extensions */ + p = tmpbuf; + s2n(sct->ext_len, p); + if (!EVP_DigestUpdate(ctx, tmpbuf, 2)) + return 0; + + if (sct->ext_len && !EVP_DigestUpdate(ctx, sct->ext, sct->ext_len)) + return 0; + + return 1; +} + +int SCT_CTX_verify(const SCT_CTX *sctx, const SCT *sct) +{ + EVP_MD_CTX *ctx = NULL; + int ret = 0; + + if (!SCT_is_complete(sct) || sctx->pkey == NULL || + sct->entry_type == CT_LOG_ENTRY_TYPE_NOT_SET || + (sct->entry_type == CT_LOG_ENTRY_TYPE_PRECERT && sctx->ihash == NULL)) { + CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_NOT_SET); + return 0; + } + if (sct->version != SCT_VERSION_V1) { + CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_UNSUPPORTED_VERSION); + return 0; + } + if (sct->log_id_len != sctx->pkeyhashlen || + memcmp(sct->log_id, sctx->pkeyhash, sctx->pkeyhashlen) != 0) { + CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_LOG_ID_MISMATCH); + return 0; + } + if (sct->timestamp > sctx->epoch_time_in_ms) { + CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_FUTURE_TIMESTAMP); + return 0; + } + + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) + goto end; + + if (!EVP_DigestVerifyInit(ctx, NULL, EVP_sha256(), NULL, sctx->pkey)) + goto end; + + if (!sct_ctx_update(ctx, sctx, sct)) + goto end; + + /* Verify signature */ + ret = EVP_DigestVerifyFinal(ctx, sct->sig, sct->sig_len); + /* If ret < 0 some other error: fall through without setting error */ + if (ret == 0) + CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_INVALID_SIGNATURE); + +end: + EVP_MD_CTX_free(ctx); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_x509v3.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_x509v3.c new file mode 100644 index 000000000..ec186d1f5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ct/ct_x509v3.c @@ -0,0 +1,104 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifdef OPENSSL_NO_CT +# error "CT is disabled" +#endif + +#include "ct_locl.h" + +static char *i2s_poison(const X509V3_EXT_METHOD *method, void *val) +{ + return OPENSSL_strdup("NULL"); +} + +static void *s2i_poison(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, const char *str) +{ + return ASN1_NULL_new(); +} + +static int i2r_SCT_LIST(X509V3_EXT_METHOD *method, STACK_OF(SCT) *sct_list, + BIO *out, int indent) +{ + SCT_LIST_print(sct_list, out, indent, "\n", NULL); + return 1; +} + +static int set_sct_list_source(STACK_OF(SCT) *s, sct_source_t source) +{ + if (s != NULL) { + int i; + + for (i = 0; i < sk_SCT_num(s); i++) { + int res = SCT_set_source(sk_SCT_value(s, i), source); + + if (res != 1) { + return 0; + } + } + } + return 1; +} + +static STACK_OF(SCT) *x509_ext_d2i_SCT_LIST(STACK_OF(SCT) **a, + const unsigned char **pp, + long len) +{ + STACK_OF(SCT) *s = d2i_SCT_LIST(a, pp, len); + + if (set_sct_list_source(s, SCT_SOURCE_X509V3_EXTENSION) != 1) { + SCT_LIST_free(s); + *a = NULL; + return NULL; + } + return s; +} + +static STACK_OF(SCT) *ocsp_ext_d2i_SCT_LIST(STACK_OF(SCT) **a, + const unsigned char **pp, + long len) +{ + STACK_OF(SCT) *s = d2i_SCT_LIST(a, pp, len); + + if (set_sct_list_source(s, SCT_SOURCE_OCSP_STAPLED_RESPONSE) != 1) { + SCT_LIST_free(s); + *a = NULL; + return NULL; + } + return s; +} + +/* Handlers for X509v3/OCSP Certificate Transparency extensions */ +const X509V3_EXT_METHOD v3_ct_scts[3] = { + /* X509v3 extension in certificates that contains SCTs */ + { NID_ct_precert_scts, 0, NULL, + NULL, (X509V3_EXT_FREE)SCT_LIST_free, + (X509V3_EXT_D2I)x509_ext_d2i_SCT_LIST, (X509V3_EXT_I2D)i2d_SCT_LIST, + NULL, NULL, + NULL, NULL, + (X509V3_EXT_I2R)i2r_SCT_LIST, NULL, + NULL }, + + /* X509v3 extension to mark a certificate as a pre-certificate */ + { NID_ct_precert_poison, 0, ASN1_ITEM_ref(ASN1_NULL), + NULL, NULL, NULL, NULL, + i2s_poison, s2i_poison, + NULL, NULL, + NULL, NULL, + NULL }, + + /* OCSP extension that contains SCTs */ + { NID_ct_cert_scts, 0, NULL, + 0, (X509V3_EXT_FREE)SCT_LIST_free, + (X509V3_EXT_D2I)ocsp_ext_d2i_SCT_LIST, (X509V3_EXT_I2D)i2d_SCT_LIST, + NULL, NULL, + NULL, NULL, + (X509V3_EXT_I2R)i2r_SCT_LIST, NULL, + NULL }, +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ctype.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ctype.c new file mode 100644 index 000000000..813be25a0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ctype.c @@ -0,0 +1,274 @@ +/* + * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/ctype.h" +#include "openssl/ebcdic.h" + +/* + * Define the character classes for each character in the seven bit ASCII + * character set. This is independent of the host's character set, characters + * are converted to ASCII before being used as an index in to this table. + * Characters outside of the seven bit ASCII range are detected before indexing. + */ +static const unsigned short ctype_char_map[128] = { + /* 00 nul */ CTYPE_MASK_cntrl, + /* 01 soh */ CTYPE_MASK_cntrl, + /* 02 stx */ CTYPE_MASK_cntrl, + /* 03 etx */ CTYPE_MASK_cntrl, + /* 04 eot */ CTYPE_MASK_cntrl, + /* 05 enq */ CTYPE_MASK_cntrl, + /* 06 ack */ CTYPE_MASK_cntrl, + /* 07 \a */ CTYPE_MASK_cntrl, + /* 08 \b */ CTYPE_MASK_cntrl, + /* 09 \t */ CTYPE_MASK_blank | CTYPE_MASK_cntrl | CTYPE_MASK_space, + /* 0A \n */ CTYPE_MASK_cntrl | CTYPE_MASK_space, + /* 0B \v */ CTYPE_MASK_cntrl | CTYPE_MASK_space, + /* 0C \f */ CTYPE_MASK_cntrl | CTYPE_MASK_space, + /* 0D \r */ CTYPE_MASK_cntrl | CTYPE_MASK_space, + /* 0E so */ CTYPE_MASK_cntrl, + /* 0F si */ CTYPE_MASK_cntrl, + /* 10 dle */ CTYPE_MASK_cntrl, + /* 11 dc1 */ CTYPE_MASK_cntrl, + /* 12 dc2 */ CTYPE_MASK_cntrl, + /* 13 dc3 */ CTYPE_MASK_cntrl, + /* 14 dc4 */ CTYPE_MASK_cntrl, + /* 15 nak */ CTYPE_MASK_cntrl, + /* 16 syn */ CTYPE_MASK_cntrl, + /* 17 etb */ CTYPE_MASK_cntrl, + /* 18 can */ CTYPE_MASK_cntrl, + /* 19 em */ CTYPE_MASK_cntrl, + /* 1A sub */ CTYPE_MASK_cntrl, + /* 1B esc */ CTYPE_MASK_cntrl, + /* 1C fs */ CTYPE_MASK_cntrl, + /* 1D gs */ CTYPE_MASK_cntrl, + /* 1E rs */ CTYPE_MASK_cntrl, + /* 1F us */ CTYPE_MASK_cntrl, + /* 20 */ CTYPE_MASK_blank | CTYPE_MASK_print | CTYPE_MASK_space + | CTYPE_MASK_asn1print, + /* 21 ! */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct, + /* 22 " */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct, + /* 23 # */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct, + /* 24 $ */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct, + /* 25 % */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct, + /* 26 & */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct, + /* 27 ' */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct + | CTYPE_MASK_asn1print, + /* 28 ( */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct + | CTYPE_MASK_asn1print, + /* 29 ) */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct + | CTYPE_MASK_asn1print, + /* 2A * */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct, + /* 2B + */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 2C , */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct + | CTYPE_MASK_asn1print, + /* 2D - */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct + | CTYPE_MASK_asn1print, + /* 2E . */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct + | CTYPE_MASK_asn1print, + /* 2F / */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 30 0 */ CTYPE_MASK_digit | CTYPE_MASK_graph | CTYPE_MASK_print + | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 31 1 */ CTYPE_MASK_digit | CTYPE_MASK_graph | CTYPE_MASK_print + | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 32 2 */ CTYPE_MASK_digit | CTYPE_MASK_graph | CTYPE_MASK_print + | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 33 3 */ CTYPE_MASK_digit | CTYPE_MASK_graph | CTYPE_MASK_print + | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 34 4 */ CTYPE_MASK_digit | CTYPE_MASK_graph | CTYPE_MASK_print + | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 35 5 */ CTYPE_MASK_digit | CTYPE_MASK_graph | CTYPE_MASK_print + | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 36 6 */ CTYPE_MASK_digit | CTYPE_MASK_graph | CTYPE_MASK_print + | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 37 7 */ CTYPE_MASK_digit | CTYPE_MASK_graph | CTYPE_MASK_print + | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 38 8 */ CTYPE_MASK_digit | CTYPE_MASK_graph | CTYPE_MASK_print + | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 39 9 */ CTYPE_MASK_digit | CTYPE_MASK_graph | CTYPE_MASK_print + | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 3A : */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct + | CTYPE_MASK_asn1print, + /* 3B ; */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct, + /* 3C < */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct, + /* 3D = */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 3E > */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct, + /* 3F ? */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct + | CTYPE_MASK_asn1print, + /* 40 @ */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct, + /* 41 A */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper + | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 42 B */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper + | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 43 C */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper + | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 44 D */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper + | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 45 E */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper + | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 46 F */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper + | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 47 G */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 48 H */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 49 I */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 4A J */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 4B K */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 4C L */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 4D M */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 4E N */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 4F O */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 50 P */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 51 Q */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 52 R */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 53 S */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 54 T */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 55 U */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 56 V */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 57 W */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 58 X */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 59 Y */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 5A Z */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 5B [ */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct, + /* 5C \ */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct, + /* 5D ] */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct, + /* 5E ^ */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct, + /* 5F _ */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct, + /* 60 ` */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct, + /* 61 a */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print + | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 62 b */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print + | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 63 c */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print + | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 64 d */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print + | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 65 e */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print + | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 66 f */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print + | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 67 g */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 68 h */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 69 i */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 6A j */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 6B k */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 6C l */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 6D m */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 6E n */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 6F o */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 70 p */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 71 q */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 72 r */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 73 s */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 74 t */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 75 u */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 76 v */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 77 w */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 78 x */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 79 y */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 7A z */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print + | CTYPE_MASK_base64 | CTYPE_MASK_asn1print, + /* 7B { */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct, + /* 7C | */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct, + /* 7D } */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct, + /* 7E ~ */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct, + /* 7F del */ CTYPE_MASK_cntrl +}; + +#ifdef CHARSET_EBCDIC +int ossl_toascii(int c) +{ + if (c < -128 || c > 256 || c == EOF) + return c; + /* + * Adjust negatively signed characters. + * This is not required for ASCII because any character that sign extends + * is not seven bit and all of the checks are on the seven bit characters. + * I.e. any check must fail on sign extension. + */ + if (c < 0) + c += 256; + return os_toascii[c]; +} + +int ossl_fromascii(int c) +{ + if (c < -128 || c > 256 || c == EOF) + return c; + if (c < 0) + c += 256; + return os_toebcdic[c]; +} +#endif + +int ossl_ctype_check(int c, unsigned int mask) +{ + const int max = sizeof(ctype_char_map) / sizeof(*ctype_char_map); + const int a = ossl_toascii(c); + + return a >= 0 && a < max && (ctype_char_map[a] & mask) != 0; +} + +#if defined(CHARSET_EBCDIC) && !defined(CHARSET_EBCDIC_TEST) +static const int case_change = 0x40; +#else +static const int case_change = 0x20; +#endif + +int ossl_tolower(int c) +{ + return ossl_isupper(c) ? c ^ case_change : c; +} + +int ossl_toupper(int c) +{ + return ossl_islower(c) ? c ^ case_change : c; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/cversion.c b/trunk/3rdparty/openssl-1.1-fit/crypto/cversion.c new file mode 100644 index 000000000..534e7eba5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/cversion.c @@ -0,0 +1,44 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" + +#include "buildinf.h" + +unsigned long OpenSSL_version_num(void) +{ + return OPENSSL_VERSION_NUMBER; +} + +const char *OpenSSL_version(int t) +{ + switch (t) { + case OPENSSL_VERSION: + return OPENSSL_VERSION_TEXT; + case OPENSSL_BUILT_ON: + return DATE; + case OPENSSL_CFLAGS: + return compiler_flags; + case OPENSSL_PLATFORM: + return PLATFORM; + case OPENSSL_DIR: +#ifdef OPENSSLDIR + return "OPENSSLDIR: \"" OPENSSLDIR "\""; +#else + return "OPENSSLDIR: N/A"; +#endif + case OPENSSL_ENGINES_DIR: +#ifdef ENGINESDIR + return "ENGINESDIR: \"" ENGINESDIR "\""; +#else + return "ENGINESDIR: N/A"; +#endif + } + return "not available"; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/des/asm/crypt586.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/des/asm/crypt586.pl new file mode 100644 index 000000000..a02d18063 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/des/asm/crypt586.pl @@ -0,0 +1,217 @@ +#! /usr/bin/env perl +# Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# The inner loop instruction sequence and the IP/FP modifications are from +# Svend Olaf Mikkelsen + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +$output=pop; +open STDOUT,">$output"; + +&asm_init($ARGV[0]); + +$L="edi"; +$R="esi"; + +&external_label("DES_SPtrans"); +&fcrypt_body("fcrypt_body"); +&asm_finish(); + +close STDOUT; + +sub fcrypt_body + { + local($name,$do_ip)=@_; + + &function_begin($name); + + &comment(""); + &comment("Load the 2 words"); + $trans="ebp"; + + &xor( $L, $L); + &xor( $R, $R); + + # PIC-ification:-) + &picmeup("edx","DES_SPtrans"); + #if ($cpp) { &picmeup("edx","DES_SPtrans"); } + #else { &lea("edx",&DWP("DES_SPtrans")); } + &push("edx"); # becomes &swtmp(1) + # + &mov($trans,&wparam(1)); # reloaded with DES_SPtrans in D_ENCRYPT + + &push(&DWC(25)); # add a variable + + &set_label("start"); + for ($i=0; $i<16; $i+=2) + { + &comment(""); + &comment("Round $i"); + &D_ENCRYPT($i,$L,$R,$i*2,$trans,"eax","ebx","ecx","edx"); + + &comment(""); + &comment("Round ".sprintf("%d",$i+1)); + &D_ENCRYPT($i+1,$R,$L,($i+1)*2,$trans,"eax","ebx","ecx","edx"); + } + &mov("ebx", &swtmp(0)); + &mov("eax", $L); + &dec("ebx"); + &mov($L, $R); + &mov($R, "eax"); + &mov(&swtmp(0), "ebx"); + &jnz(&label("start")); + + &comment(""); + &comment("FP"); + &mov("edx",&wparam(0)); + + &FP_new($R,$L,"eax",3); + &mov(&DWP(0,"edx","",0),"eax"); + &mov(&DWP(4,"edx","",0),$L); + + &add("esp",8); # remove variables + + &function_end($name); + } + +sub D_ENCRYPT + { + local($r,$L,$R,$S,$trans,$u,$tmp1,$tmp2,$t)=@_; + + &mov( $u, &wparam(2)); # 2 + &mov( $t, $R); + &shr( $t, 16); # 1 + &mov( $tmp2, &wparam(3)); # 2 + &xor( $t, $R); # 1 + + &and( $u, $t); # 2 + &and( $t, $tmp2); # 2 + + &mov( $tmp1, $u); + &shl( $tmp1, 16); # 1 + &mov( $tmp2, $t); + &shl( $tmp2, 16); # 1 + &xor( $u, $tmp1); # 2 + &xor( $t, $tmp2); # 2 + &mov( $tmp1, &DWP(&n2a($S*4),$trans,"",0)); # 2 + &xor( $u, $tmp1); + &mov( $tmp2, &DWP(&n2a(($S+1)*4),$trans,"",0)); # 2 + &xor( $u, $R); + &xor( $t, $R); + &xor( $t, $tmp2); + + &and( $u, "0xfcfcfcfc" ); # 2 + &xor( $tmp1, $tmp1); # 1 + &and( $t, "0xcfcfcfcf" ); # 2 + &xor( $tmp2, $tmp2); + &movb( &LB($tmp1), &LB($u) ); + &movb( &LB($tmp2), &HB($u) ); + &rotr( $t, 4 ); + &mov( $trans, &swtmp(1)); + &xor( $L, &DWP(" ",$trans,$tmp1,0)); + &movb( &LB($tmp1), &LB($t) ); + &xor( $L, &DWP("0x200",$trans,$tmp2,0)); + &movb( &LB($tmp2), &HB($t) ); + &shr( $u, 16); + &xor( $L, &DWP("0x100",$trans,$tmp1,0)); + &movb( &LB($tmp1), &HB($u) ); + &shr( $t, 16); + &xor( $L, &DWP("0x300",$trans,$tmp2,0)); + &movb( &LB($tmp2), &HB($t) ); + &and( $u, "0xff" ); + &and( $t, "0xff" ); + &mov( $tmp1, &DWP("0x600",$trans,$tmp1,0)); + &xor( $L, $tmp1); + &mov( $tmp1, &DWP("0x700",$trans,$tmp2,0)); + &xor( $L, $tmp1); + &mov( $tmp1, &DWP("0x400",$trans,$u,0)); + &xor( $L, $tmp1); + &mov( $tmp1, &DWP("0x500",$trans,$t,0)); + &xor( $L, $tmp1); + &mov( $trans, &wparam(1)); + } + +sub n2a + { + sprintf("%d",$_[0]); + } + +# now has a side affect of rotating $a by $shift +sub R_PERM_OP + { + local($a,$b,$tt,$shift,$mask,$last)=@_; + + &rotl( $a, $shift ) if ($shift != 0); + &mov( $tt, $a ); + &xor( $a, $b ); + &and( $a, $mask ); + if ($notlast eq $b) + { + &xor( $b, $a ); + &xor( $tt, $a ); + } + else + { + &xor( $tt, $a ); + &xor( $b, $a ); + } + &comment(""); + } + +sub IP_new + { + local($l,$r,$tt,$lr)=@_; + + &R_PERM_OP($l,$r,$tt, 4,"0xf0f0f0f0",$l); + &R_PERM_OP($r,$tt,$l,20,"0xfff0000f",$l); + &R_PERM_OP($l,$tt,$r,14,"0x33333333",$r); + &R_PERM_OP($tt,$r,$l,22,"0x03fc03fc",$r); + &R_PERM_OP($l,$r,$tt, 9,"0xaaaaaaaa",$r); + + if ($lr != 3) + { + if (($lr-3) < 0) + { &rotr($tt, 3-$lr); } + else { &rotl($tt, $lr-3); } + } + if ($lr != 2) + { + if (($lr-2) < 0) + { &rotr($r, 2-$lr); } + else { &rotl($r, $lr-2); } + } + } + +sub FP_new + { + local($l,$r,$tt,$lr)=@_; + + if ($lr != 2) + { + if (($lr-2) < 0) + { &rotl($r, 2-$lr); } + else { &rotr($r, $lr-2); } + } + if ($lr != 3) + { + if (($lr-3) < 0) + { &rotl($l, 3-$lr); } + else { &rotr($l, $lr-3); } + } + + &R_PERM_OP($l,$r,$tt, 0,"0xaaaaaaaa",$r); + &R_PERM_OP($tt,$r,$l,23,"0x03fc03fc",$r); + &R_PERM_OP($l,$r,$tt,10,"0x33333333",$l); + &R_PERM_OP($r,$tt,$l,18,"0xfff0000f",$l); + &R_PERM_OP($l,$tt,$r,12,"0xf0f0f0f0",$r); + &rotr($tt , 4); + } + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/des/asm/des-586.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/des/asm/des-586.pl new file mode 100644 index 000000000..2bcc54ef2 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/des/asm/des-586.pl @@ -0,0 +1,465 @@ +#! /usr/bin/env perl +# Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# The inner loop instruction sequence and the IP/FP modifications are from +# Svend Olaf Mikkelsen. + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; +require "cbc.pl"; +require "desboth.pl"; + +# base code is in Microsoft +# op dest, source +# format. +# + +$output=pop; +open STDOUT,">$output"; + +&asm_init($ARGV[0]); + +$L="edi"; +$R="esi"; +$trans="ebp"; +$small_footprint=1 if (grep(/\-DOPENSSL_SMALL_FOOTPRINT/,@ARGV)); +# one can discuss setting this variable to 1 unconditionally, as +# the folded loop is only 3% slower than unrolled, but >7 times smaller + +&public_label("DES_SPtrans"); +&static_label("des_sptrans"); + +&DES_encrypt_internal(); +&DES_decrypt_internal(); +&DES_encrypt("DES_encrypt1",1); +&DES_encrypt("DES_encrypt2",0); +&DES_encrypt3("DES_encrypt3",1); +&DES_encrypt3("DES_decrypt3",0); +&cbc("DES_ncbc_encrypt","DES_encrypt1","DES_encrypt1",0,4,5,3,5,-1); +&cbc("DES_ede3_cbc_encrypt","DES_encrypt3","DES_decrypt3",0,6,7,3,4,5); +&DES_SPtrans(); + +&asm_finish(); + +close STDOUT; + +sub DES_encrypt_internal() + { + &function_begin_B("_x86_DES_encrypt"); + + if ($small_footprint) + { + &lea("edx",&DWP(128,"ecx")); + &push("edx"); + &push("ecx"); + &set_label("eloop"); + &D_ENCRYPT(0,$L,$R,0,$trans,"eax","ebx","ecx","edx",&swtmp(0)); + &comment(""); + &D_ENCRYPT(1,$R,$L,2,$trans,"eax","ebx","ecx","edx",&swtmp(0)); + &comment(""); + &add("ecx",16); + &cmp("ecx",&swtmp(1)); + &mov(&swtmp(0),"ecx"); + &jb(&label("eloop")); + &add("esp",8); + } + else + { + &push("ecx"); + for ($i=0; $i<16; $i+=2) + { + &comment("Round $i"); + &D_ENCRYPT($i,$L,$R,$i*2,$trans,"eax","ebx","ecx","edx",&swtmp(0)); + &comment("Round ".sprintf("%d",$i+1)); + &D_ENCRYPT($i+1,$R,$L,($i+1)*2,$trans,"eax","ebx","ecx","edx",&swtmp(0)); + } + &add("esp",4); + } + &ret(); + + &function_end_B("_x86_DES_encrypt"); + } + +sub DES_decrypt_internal() + { + &function_begin_B("_x86_DES_decrypt"); + + if ($small_footprint) + { + &push("ecx"); + &lea("ecx",&DWP(128,"ecx")); + &push("ecx"); + &set_label("dloop"); + &D_ENCRYPT(0,$L,$R,-2,$trans,"eax","ebx","ecx","edx",&swtmp(0)); + &comment(""); + &D_ENCRYPT(1,$R,$L,-4,$trans,"eax","ebx","ecx","edx",&swtmp(0)); + &comment(""); + &sub("ecx",16); + &cmp("ecx",&swtmp(1)); + &mov(&swtmp(0),"ecx"); + &ja(&label("dloop")); + &add("esp",8); + } + else + { + &push("ecx"); + for ($i=15; $i>0; $i-=2) + { + &comment("Round $i"); + &D_ENCRYPT(15-$i,$L,$R,$i*2,$trans,"eax","ebx","ecx","edx",&swtmp(0)); + &comment("Round ".sprintf("%d",$i-1)); + &D_ENCRYPT(15-$i+1,$R,$L,($i-1)*2,$trans,"eax","ebx","ecx","edx",&swtmp(0)); + } + &add("esp",4); + } + &ret(); + + &function_end_B("_x86_DES_decrypt"); + } + +sub DES_encrypt + { + local($name,$do_ip)=@_; + + &function_begin_B($name); + + &push("esi"); + &push("edi"); + + &comment(""); + &comment("Load the 2 words"); + + if ($do_ip) + { + &mov($R,&wparam(0)); + &xor( "ecx", "ecx" ); + + &push("ebx"); + &push("ebp"); + + &mov("eax",&DWP(0,$R,"",0)); + &mov("ebx",&wparam(2)); # get encrypt flag + &mov($L,&DWP(4,$R,"",0)); + &comment(""); + &comment("IP"); + &IP_new("eax",$L,$R,3); + } + else + { + &mov("eax",&wparam(0)); + &xor( "ecx", "ecx" ); + + &push("ebx"); + &push("ebp"); + + &mov($R,&DWP(0,"eax","",0)); + &mov("ebx",&wparam(2)); # get encrypt flag + &rotl($R,3); + &mov($L,&DWP(4,"eax","",0)); + &rotl($L,3); + } + + # PIC-ification:-) + &call (&label("pic_point")); + &set_label("pic_point"); + &blindpop($trans); + &lea ($trans,&DWP(&label("des_sptrans")."-".&label("pic_point"),$trans)); + + &mov( "ecx", &wparam(1) ); + + &cmp("ebx","0"); + &je(&label("decrypt")); + &call("_x86_DES_encrypt"); + &jmp(&label("done")); + &set_label("decrypt"); + &call("_x86_DES_decrypt"); + &set_label("done"); + + if ($do_ip) + { + &comment(""); + &comment("FP"); + &mov("edx",&wparam(0)); + &FP_new($L,$R,"eax",3); + + &mov(&DWP(0,"edx","",0),"eax"); + &mov(&DWP(4,"edx","",0),$R); + } + else + { + &comment(""); + &comment("Fixup"); + &rotr($L,3); # r + &mov("eax",&wparam(0)); + &rotr($R,3); # l + &mov(&DWP(0,"eax","",0),$L); + &mov(&DWP(4,"eax","",0),$R); + } + + &pop("ebp"); + &pop("ebx"); + &pop("edi"); + &pop("esi"); + &ret(); + + &function_end_B($name); + } + +sub D_ENCRYPT + { + local($r,$L,$R,$S,$trans,$u,$tmp1,$tmp2,$t,$wp1)=@_; + + &mov( $u, &DWP(&n2a($S*4),$tmp2,"",0)); + &xor( $tmp1, $tmp1); + &mov( $t, &DWP(&n2a(($S+1)*4),$tmp2,"",0)); + &xor( $u, $R); + &xor( $tmp2, $tmp2); + &xor( $t, $R); + &and( $u, "0xfcfcfcfc" ); + &and( $t, "0xcfcfcfcf" ); + &movb( &LB($tmp1), &LB($u) ); + &movb( &LB($tmp2), &HB($u) ); + &rotr( $t, 4 ); + &xor( $L, &DWP(" ",$trans,$tmp1,0)); + &movb( &LB($tmp1), &LB($t) ); + &xor( $L, &DWP("0x200",$trans,$tmp2,0)); + &movb( &LB($tmp2), &HB($t) ); + &shr( $u, 16); + &xor( $L, &DWP("0x100",$trans,$tmp1,0)); + &movb( &LB($tmp1), &HB($u) ); + &shr( $t, 16); + &xor( $L, &DWP("0x300",$trans,$tmp2,0)); + &movb( &LB($tmp2), &HB($t) ); + &and( $u, "0xff" ); + &and( $t, "0xff" ); + &xor( $L, &DWP("0x600",$trans,$tmp1,0)); + &xor( $L, &DWP("0x700",$trans,$tmp2,0)); + &mov( $tmp2, $wp1 ); + &xor( $L, &DWP("0x400",$trans,$u,0)); + &xor( $L, &DWP("0x500",$trans,$t,0)); + } + +sub n2a + { + sprintf("%d",$_[0]); + } + +# now has a side affect of rotating $a by $shift +sub R_PERM_OP + { + local($a,$b,$tt,$shift,$mask,$last)=@_; + + &rotl( $a, $shift ) if ($shift != 0); + &mov( $tt, $a ); + &xor( $a, $b ); + &and( $a, $mask ); + # This can never succeed, and besides it is difficult to see what the + # idea was - Ben 13 Feb 99 + if (!$last eq $b) + { + &xor( $b, $a ); + &xor( $tt, $a ); + } + else + { + &xor( $tt, $a ); + &xor( $b, $a ); + } + &comment(""); + } + +sub IP_new + { + local($l,$r,$tt,$lr)=@_; + + &R_PERM_OP($l,$r,$tt, 4,"0xf0f0f0f0",$l); + &R_PERM_OP($r,$tt,$l,20,"0xfff0000f",$l); + &R_PERM_OP($l,$tt,$r,14,"0x33333333",$r); + &R_PERM_OP($tt,$r,$l,22,"0x03fc03fc",$r); + &R_PERM_OP($l,$r,$tt, 9,"0xaaaaaaaa",$r); + + if ($lr != 3) + { + if (($lr-3) < 0) + { &rotr($tt, 3-$lr); } + else { &rotl($tt, $lr-3); } + } + if ($lr != 2) + { + if (($lr-2) < 0) + { &rotr($r, 2-$lr); } + else { &rotl($r, $lr-2); } + } + } + +sub FP_new + { + local($l,$r,$tt,$lr)=@_; + + if ($lr != 2) + { + if (($lr-2) < 0) + { &rotl($r, 2-$lr); } + else { &rotr($r, $lr-2); } + } + if ($lr != 3) + { + if (($lr-3) < 0) + { &rotl($l, 3-$lr); } + else { &rotr($l, $lr-3); } + } + + &R_PERM_OP($l,$r,$tt, 0,"0xaaaaaaaa",$r); + &R_PERM_OP($tt,$r,$l,23,"0x03fc03fc",$r); + &R_PERM_OP($l,$r,$tt,10,"0x33333333",$l); + &R_PERM_OP($r,$tt,$l,18,"0xfff0000f",$l); + &R_PERM_OP($l,$tt,$r,12,"0xf0f0f0f0",$r); + &rotr($tt , 4); + } + +sub DES_SPtrans + { + &set_label("DES_SPtrans",64); + &set_label("des_sptrans"); + &data_word(0x02080800, 0x00080000, 0x02000002, 0x02080802); + &data_word(0x02000000, 0x00080802, 0x00080002, 0x02000002); + &data_word(0x00080802, 0x02080800, 0x02080000, 0x00000802); + &data_word(0x02000802, 0x02000000, 0x00000000, 0x00080002); + &data_word(0x00080000, 0x00000002, 0x02000800, 0x00080800); + &data_word(0x02080802, 0x02080000, 0x00000802, 0x02000800); + &data_word(0x00000002, 0x00000800, 0x00080800, 0x02080002); + &data_word(0x00000800, 0x02000802, 0x02080002, 0x00000000); + &data_word(0x00000000, 0x02080802, 0x02000800, 0x00080002); + &data_word(0x02080800, 0x00080000, 0x00000802, 0x02000800); + &data_word(0x02080002, 0x00000800, 0x00080800, 0x02000002); + &data_word(0x00080802, 0x00000002, 0x02000002, 0x02080000); + &data_word(0x02080802, 0x00080800, 0x02080000, 0x02000802); + &data_word(0x02000000, 0x00000802, 0x00080002, 0x00000000); + &data_word(0x00080000, 0x02000000, 0x02000802, 0x02080800); + &data_word(0x00000002, 0x02080002, 0x00000800, 0x00080802); + # nibble 1 + &data_word(0x40108010, 0x00000000, 0x00108000, 0x40100000); + &data_word(0x40000010, 0x00008010, 0x40008000, 0x00108000); + &data_word(0x00008000, 0x40100010, 0x00000010, 0x40008000); + &data_word(0x00100010, 0x40108000, 0x40100000, 0x00000010); + &data_word(0x00100000, 0x40008010, 0x40100010, 0x00008000); + &data_word(0x00108010, 0x40000000, 0x00000000, 0x00100010); + &data_word(0x40008010, 0x00108010, 0x40108000, 0x40000010); + &data_word(0x40000000, 0x00100000, 0x00008010, 0x40108010); + &data_word(0x00100010, 0x40108000, 0x40008000, 0x00108010); + &data_word(0x40108010, 0x00100010, 0x40000010, 0x00000000); + &data_word(0x40000000, 0x00008010, 0x00100000, 0x40100010); + &data_word(0x00008000, 0x40000000, 0x00108010, 0x40008010); + &data_word(0x40108000, 0x00008000, 0x00000000, 0x40000010); + &data_word(0x00000010, 0x40108010, 0x00108000, 0x40100000); + &data_word(0x40100010, 0x00100000, 0x00008010, 0x40008000); + &data_word(0x40008010, 0x00000010, 0x40100000, 0x00108000); + # nibble 2 + &data_word(0x04000001, 0x04040100, 0x00000100, 0x04000101); + &data_word(0x00040001, 0x04000000, 0x04000101, 0x00040100); + &data_word(0x04000100, 0x00040000, 0x04040000, 0x00000001); + &data_word(0x04040101, 0x00000101, 0x00000001, 0x04040001); + &data_word(0x00000000, 0x00040001, 0x04040100, 0x00000100); + &data_word(0x00000101, 0x04040101, 0x00040000, 0x04000001); + &data_word(0x04040001, 0x04000100, 0x00040101, 0x04040000); + &data_word(0x00040100, 0x00000000, 0x04000000, 0x00040101); + &data_word(0x04040100, 0x00000100, 0x00000001, 0x00040000); + &data_word(0x00000101, 0x00040001, 0x04040000, 0x04000101); + &data_word(0x00000000, 0x04040100, 0x00040100, 0x04040001); + &data_word(0x00040001, 0x04000000, 0x04040101, 0x00000001); + &data_word(0x00040101, 0x04000001, 0x04000000, 0x04040101); + &data_word(0x00040000, 0x04000100, 0x04000101, 0x00040100); + &data_word(0x04000100, 0x00000000, 0x04040001, 0x00000101); + &data_word(0x04000001, 0x00040101, 0x00000100, 0x04040000); + # nibble 3 + &data_word(0x00401008, 0x10001000, 0x00000008, 0x10401008); + &data_word(0x00000000, 0x10400000, 0x10001008, 0x00400008); + &data_word(0x10401000, 0x10000008, 0x10000000, 0x00001008); + &data_word(0x10000008, 0x00401008, 0x00400000, 0x10000000); + &data_word(0x10400008, 0x00401000, 0x00001000, 0x00000008); + &data_word(0x00401000, 0x10001008, 0x10400000, 0x00001000); + &data_word(0x00001008, 0x00000000, 0x00400008, 0x10401000); + &data_word(0x10001000, 0x10400008, 0x10401008, 0x00400000); + &data_word(0x10400008, 0x00001008, 0x00400000, 0x10000008); + &data_word(0x00401000, 0x10001000, 0x00000008, 0x10400000); + &data_word(0x10001008, 0x00000000, 0x00001000, 0x00400008); + &data_word(0x00000000, 0x10400008, 0x10401000, 0x00001000); + &data_word(0x10000000, 0x10401008, 0x00401008, 0x00400000); + &data_word(0x10401008, 0x00000008, 0x10001000, 0x00401008); + &data_word(0x00400008, 0x00401000, 0x10400000, 0x10001008); + &data_word(0x00001008, 0x10000000, 0x10000008, 0x10401000); + # nibble 4 + &data_word(0x08000000, 0x00010000, 0x00000400, 0x08010420); + &data_word(0x08010020, 0x08000400, 0x00010420, 0x08010000); + &data_word(0x00010000, 0x00000020, 0x08000020, 0x00010400); + &data_word(0x08000420, 0x08010020, 0x08010400, 0x00000000); + &data_word(0x00010400, 0x08000000, 0x00010020, 0x00000420); + &data_word(0x08000400, 0x00010420, 0x00000000, 0x08000020); + &data_word(0x00000020, 0x08000420, 0x08010420, 0x00010020); + &data_word(0x08010000, 0x00000400, 0x00000420, 0x08010400); + &data_word(0x08010400, 0x08000420, 0x00010020, 0x08010000); + &data_word(0x00010000, 0x00000020, 0x08000020, 0x08000400); + &data_word(0x08000000, 0x00010400, 0x08010420, 0x00000000); + &data_word(0x00010420, 0x08000000, 0x00000400, 0x00010020); + &data_word(0x08000420, 0x00000400, 0x00000000, 0x08010420); + &data_word(0x08010020, 0x08010400, 0x00000420, 0x00010000); + &data_word(0x00010400, 0x08010020, 0x08000400, 0x00000420); + &data_word(0x00000020, 0x00010420, 0x08010000, 0x08000020); + # nibble 5 + &data_word(0x80000040, 0x00200040, 0x00000000, 0x80202000); + &data_word(0x00200040, 0x00002000, 0x80002040, 0x00200000); + &data_word(0x00002040, 0x80202040, 0x00202000, 0x80000000); + &data_word(0x80002000, 0x80000040, 0x80200000, 0x00202040); + &data_word(0x00200000, 0x80002040, 0x80200040, 0x00000000); + &data_word(0x00002000, 0x00000040, 0x80202000, 0x80200040); + &data_word(0x80202040, 0x80200000, 0x80000000, 0x00002040); + &data_word(0x00000040, 0x00202000, 0x00202040, 0x80002000); + &data_word(0x00002040, 0x80000000, 0x80002000, 0x00202040); + &data_word(0x80202000, 0x00200040, 0x00000000, 0x80002000); + &data_word(0x80000000, 0x00002000, 0x80200040, 0x00200000); + &data_word(0x00200040, 0x80202040, 0x00202000, 0x00000040); + &data_word(0x80202040, 0x00202000, 0x00200000, 0x80002040); + &data_word(0x80000040, 0x80200000, 0x00202040, 0x00000000); + &data_word(0x00002000, 0x80000040, 0x80002040, 0x80202000); + &data_word(0x80200000, 0x00002040, 0x00000040, 0x80200040); + # nibble 6 + &data_word(0x00004000, 0x00000200, 0x01000200, 0x01000004); + &data_word(0x01004204, 0x00004004, 0x00004200, 0x00000000); + &data_word(0x01000000, 0x01000204, 0x00000204, 0x01004000); + &data_word(0x00000004, 0x01004200, 0x01004000, 0x00000204); + &data_word(0x01000204, 0x00004000, 0x00004004, 0x01004204); + &data_word(0x00000000, 0x01000200, 0x01000004, 0x00004200); + &data_word(0x01004004, 0x00004204, 0x01004200, 0x00000004); + &data_word(0x00004204, 0x01004004, 0x00000200, 0x01000000); + &data_word(0x00004204, 0x01004000, 0x01004004, 0x00000204); + &data_word(0x00004000, 0x00000200, 0x01000000, 0x01004004); + &data_word(0x01000204, 0x00004204, 0x00004200, 0x00000000); + &data_word(0x00000200, 0x01000004, 0x00000004, 0x01000200); + &data_word(0x00000000, 0x01000204, 0x01000200, 0x00004200); + &data_word(0x00000204, 0x00004000, 0x01004204, 0x01000000); + &data_word(0x01004200, 0x00000004, 0x00004004, 0x01004204); + &data_word(0x01000004, 0x01004200, 0x01004000, 0x00004004); + # nibble 7 + &data_word(0x20800080, 0x20820000, 0x00020080, 0x00000000); + &data_word(0x20020000, 0x00800080, 0x20800000, 0x20820080); + &data_word(0x00000080, 0x20000000, 0x00820000, 0x00020080); + &data_word(0x00820080, 0x20020080, 0x20000080, 0x20800000); + &data_word(0x00020000, 0x00820080, 0x00800080, 0x20020000); + &data_word(0x20820080, 0x20000080, 0x00000000, 0x00820000); + &data_word(0x20000000, 0x00800000, 0x20020080, 0x20800080); + &data_word(0x00800000, 0x00020000, 0x20820000, 0x00000080); + &data_word(0x00800000, 0x00020000, 0x20000080, 0x20820080); + &data_word(0x00020080, 0x20000000, 0x00000000, 0x00820000); + &data_word(0x20800080, 0x20020080, 0x20020000, 0x00800080); + &data_word(0x20820000, 0x00000080, 0x00800080, 0x20020000); + &data_word(0x20820080, 0x00800000, 0x20800000, 0x20000080); + &data_word(0x00820000, 0x00020080, 0x20020080, 0x20800000); + &data_word(0x00000080, 0x20820000, 0x00820080, 0x00000000); + &data_word(0x20000000, 0x20800080, 0x00020000, 0x00820080); + } diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/des/asm/des_enc.m4 b/trunk/3rdparty/openssl-1.1-fit/crypto/des/asm/des_enc.m4 new file mode 100644 index 000000000..4ada97b17 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/des/asm/des_enc.m4 @@ -0,0 +1,1968 @@ +! Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved. +! +! Licensed under the OpenSSL license (the "License"). You may not use +! this file except in compliance with the License. You can obtain a copy +! in the file LICENSE in the source distribution or at +! https://www.openssl.org/source/license.html +! +! To expand the m4 macros: m4 -B 8192 des_enc.m4 > des_enc.S +! +! Global registers 1 to 5 are used. This is the same as done by the +! cc compiler. The UltraSPARC load/store little endian feature is used. +! +! Instruction grouping often refers to one CPU cycle. +! +! Assemble through gcc: gcc -c -mcpu=ultrasparc -o des_enc.o des_enc.S +! +! Assemble through cc: cc -c -xarch=v8plusa -o des_enc.o des_enc.S +! +! Performance improvement according to './apps/openssl speed des' +! +! 32-bit build: +! 23% faster than cc-5.2 -xarch=v8plus -xO5 +! 115% faster than gcc-3.2.1 -m32 -mcpu=ultrasparc -O5 +! 64-bit build: +! 50% faster than cc-5.2 -xarch=v9 -xO5 +! 100% faster than gcc-3.2.1 -m64 -mcpu=ultrasparc -O5 +! + +.ident "des_enc.m4 2.1" +.file "des_enc-sparc.S" + +#include + +#if defined(__SUNPRO_C) && defined(__sparcv9) +# define ABI64 /* They've said -xarch=v9 at command line */ +#elif defined(__GNUC__) && defined(__arch64__) +# define ABI64 /* They've said -m64 at command line */ +#endif + +#ifdef ABI64 + .register %g2,#scratch + .register %g3,#scratch +# define FRAME -192 +# define BIAS 2047 +# define LDPTR ldx +# define STPTR stx +# define ARG0 128 +# define ARGSZ 8 +#else +# define FRAME -96 +# define BIAS 0 +# define LDPTR ld +# define STPTR st +# define ARG0 68 +# define ARGSZ 4 +#endif + +#define LOOPS 7 + +#define global0 %g0 +#define global1 %g1 +#define global2 %g2 +#define global3 %g3 +#define global4 %g4 +#define global5 %g5 + +#define local0 %l0 +#define local1 %l1 +#define local2 %l2 +#define local3 %l3 +#define local4 %l4 +#define local5 %l5 +#define local7 %l6 +#define local6 %l7 + +#define in0 %i0 +#define in1 %i1 +#define in2 %i2 +#define in3 %i3 +#define in4 %i4 +#define in5 %i5 +#define in6 %i6 +#define in7 %i7 + +#define out0 %o0 +#define out1 %o1 +#define out2 %o2 +#define out3 %o3 +#define out4 %o4 +#define out5 %o5 +#define out6 %o6 +#define out7 %o7 + +#define stub stb + +changequote({,}) + + +! Macro definitions: + + +! {ip_macro} +! +! The logic used in initial and final permutations is the same as in +! the C code. The permutations are done with a clever shift, xor, and +! technique. +! +! The macro also loads address sbox 1 to 5 to global 1 to 5, address +! sbox 6 to local6, and addres sbox 8 to out3. +! +! Rotates the halfs 3 left to bring the sbox bits in convenient positions. +! +! Loads key first round from address in parameter 5 to out0, out1. +! +! After the original LibDES initial permutation, the resulting left +! is in the variable initially used for right and vice versa. The macro +! implements the possibility to keep the halfs in the original registers. +! +! parameter 1 left +! parameter 2 right +! parameter 3 result left (modify in first round) +! parameter 4 result right (use in first round) +! parameter 5 key address +! parameter 6 1/2 for include encryption/decryption +! parameter 7 1 for move in1 to in3 +! parameter 8 1 for move in3 to in4, 2 for move in4 to in3 +! parameter 9 1 for load ks3 and ks2 to in4 and in3 + +define(ip_macro, { + +! {ip_macro} +! $1 $2 $4 $3 $5 $6 $7 $8 $9 + + ld [out2+256], local1 + srl $2, 4, local4 + + xor local4, $1, local4 + ifelse($7,1,{mov in1, in3},{nop}) + + ld [out2+260], local2 + and local4, local1, local4 + ifelse($8,1,{mov in3, in4},{}) + ifelse($8,2,{mov in4, in3},{}) + + ld [out2+280], out4 ! loop counter + sll local4, 4, local1 + xor $1, local4, $1 + + ld [out2+264], local3 + srl $1, 16, local4 + xor $2, local1, $2 + + ifelse($9,1,{LDPTR KS3, in4},{}) + xor local4, $2, local4 + nop !sethi %hi(DES_SPtrans), global1 ! sbox addr + + ifelse($9,1,{LDPTR KS2, in3},{}) + and local4, local2, local4 + nop !or global1, %lo(DES_SPtrans), global1 ! sbox addr + + sll local4, 16, local1 + xor $2, local4, $2 + + srl $2, 2, local4 + xor $1, local1, $1 + + sethi %hi(16711680), local5 + xor local4, $1, local4 + + and local4, local3, local4 + or local5, 255, local5 + + sll local4, 2, local2 + xor $1, local4, $1 + + srl $1, 8, local4 + xor $2, local2, $2 + + xor local4, $2, local4 + add global1, 768, global4 + + and local4, local5, local4 + add global1, 1024, global5 + + ld [out2+272], local7 + sll local4, 8, local1 + xor $2, local4, $2 + + srl $2, 1, local4 + xor $1, local1, $1 + + ld [$5], out0 ! key 7531 + xor local4, $1, local4 + add global1, 256, global2 + + ld [$5+4], out1 ! key 8642 + and local4, local7, local4 + add global1, 512, global3 + + sll local4, 1, local1 + xor $1, local4, $1 + + sll $1, 3, local3 + xor $2, local1, $2 + + sll $2, 3, local2 + add global1, 1280, local6 ! address sbox 8 + + srl $1, 29, local4 + add global1, 1792, out3 ! address sbox 8 + + srl $2, 29, local1 + or local4, local3, $4 + + or local2, local1, $3 + + ifelse($6, 1, { + + ld [out2+284], local5 ! 0x0000FC00 used in the rounds + or local2, local1, $3 + xor $4, out0, local1 + + call .des_enc.1 + and local1, 252, local1 + + },{}) + + ifelse($6, 2, { + + ld [out2+284], local5 ! 0x0000FC00 used in the rounds + or local2, local1, $3 + xor $4, out0, local1 + + call .des_dec.1 + and local1, 252, local1 + + },{}) +}) + + +! {rounds_macro} +! +! The logic used in the DES rounds is the same as in the C code, +! except that calculations for sbox 1 and sbox 5 begin before +! the previous round is finished. +! +! In each round one half (work) is modified based on key and the +! other half (use). +! +! In this version we do two rounds in a loop repeated 7 times +! and two rounds separately. +! +! One half has the bits for the sboxes in the following positions: +! +! 777777xx555555xx333333xx111111xx +! +! 88xx666666xx444444xx222222xx8888 +! +! The bits for each sbox are xor-ed with the key bits for that box. +! The above xx bits are cleared, and the result used for lookup in +! the sbox table. Each sbox entry contains the 4 output bits permuted +! into 32 bits according to the P permutation. +! +! In the description of DES, left and right are switched after +! each round, except after last round. In this code the original +! left and right are kept in the same register in all rounds, meaning +! that after the 16 rounds the result for right is in the register +! originally used for left. +! +! parameter 1 first work (left in first round) +! parameter 2 first use (right in first round) +! parameter 3 enc/dec 1/-1 +! parameter 4 loop label +! parameter 5 key address register +! parameter 6 optional address for key next encryption/decryption +! parameter 7 not empty for include retl +! +! also compares in2 to 8 + +define(rounds_macro, { + +! {rounds_macro} +! $1 $2 $3 $4 $5 $6 $7 $8 $9 + + xor $2, out0, local1 + + ld [out2+284], local5 ! 0x0000FC00 + ba $4 + and local1, 252, local1 + + .align 32 + +$4: + ! local6 is address sbox 6 + ! out3 is address sbox 8 + ! out4 is loop counter + + ld [global1+local1], local1 + xor $2, out1, out1 ! 8642 + xor $2, out0, out0 ! 7531 + ! fmovs %f0, %f0 ! fxor used for alignment + + srl out1, 4, local0 ! rotate 4 right + and out0, local5, local3 ! 3 + ! fmovs %f0, %f0 + + ld [$5+$3*8], local7 ! key 7531 next round + srl local3, 8, local3 ! 3 + and local0, 252, local2 ! 2 + ! fmovs %f0, %f0 + + ld [global3+local3],local3 ! 3 + sll out1, 28, out1 ! rotate + xor $1, local1, $1 ! 1 finished, local1 now sbox 7 + + ld [global2+local2], local2 ! 2 + srl out0, 24, local1 ! 7 + or out1, local0, out1 ! rotate + + ldub [out2+local1], local1 ! 7 (and 0xFC) + srl out1, 24, local0 ! 8 + and out1, local5, local4 ! 4 + + ldub [out2+local0], local0 ! 8 (and 0xFC) + srl local4, 8, local4 ! 4 + xor $1, local2, $1 ! 2 finished local2 now sbox 6 + + ld [global4+local4],local4 ! 4 + srl out1, 16, local2 ! 6 + xor $1, local3, $1 ! 3 finished local3 now sbox 5 + + ld [out3+local0],local0 ! 8 + and local2, 252, local2 ! 6 + add global1, 1536, local5 ! address sbox 7 + + ld [local6+local2], local2 ! 6 + srl out0, 16, local3 ! 5 + xor $1, local4, $1 ! 4 finished + + ld [local5+local1],local1 ! 7 + and local3, 252, local3 ! 5 + xor $1, local0, $1 ! 8 finished + + ld [global5+local3],local3 ! 5 + xor $1, local2, $1 ! 6 finished + subcc out4, 1, out4 + + ld [$5+$3*8+4], out0 ! key 8642 next round + xor $1, local7, local2 ! sbox 5 next round + xor $1, local1, $1 ! 7 finished + + srl local2, 16, local2 ! sbox 5 next round + xor $1, local3, $1 ! 5 finished + + ld [$5+$3*16+4], out1 ! key 8642 next round again + and local2, 252, local2 ! sbox5 next round +! next round + xor $1, local7, local7 ! 7531 + + ld [global5+local2], local2 ! 5 + srl local7, 24, local3 ! 7 + xor $1, out0, out0 ! 8642 + + ldub [out2+local3], local3 ! 7 (and 0xFC) + srl out0, 4, local0 ! rotate 4 right + and local7, 252, local1 ! 1 + + sll out0, 28, out0 ! rotate + xor $2, local2, $2 ! 5 finished local2 used + + srl local0, 8, local4 ! 4 + and local0, 252, local2 ! 2 + ld [local5+local3], local3 ! 7 + + srl local0, 16, local5 ! 6 + or out0, local0, out0 ! rotate + ld [global2+local2], local2 ! 2 + + srl out0, 24, local0 + ld [$5+$3*16], out0 ! key 7531 next round + and local4, 252, local4 ! 4 + + and local5, 252, local5 ! 6 + ld [global4+local4], local4 ! 4 + xor $2, local3, $2 ! 7 finished local3 used + + and local0, 252, local0 ! 8 + ld [local6+local5], local5 ! 6 + xor $2, local2, $2 ! 2 finished local2 now sbox 3 + + srl local7, 8, local2 ! 3 start + ld [out3+local0], local0 ! 8 + xor $2, local4, $2 ! 4 finished + + and local2, 252, local2 ! 3 + ld [global1+local1], local1 ! 1 + xor $2, local5, $2 ! 6 finished local5 used + + ld [global3+local2], local2 ! 3 + xor $2, local0, $2 ! 8 finished + add $5, $3*16, $5 ! enc add 8, dec add -8 to key pointer + + ld [out2+284], local5 ! 0x0000FC00 + xor $2, out0, local4 ! sbox 1 next round + xor $2, local1, $2 ! 1 finished + + xor $2, local2, $2 ! 3 finished + bne $4 + and local4, 252, local1 ! sbox 1 next round + +! two rounds more: + + ld [global1+local1], local1 + xor $2, out1, out1 + xor $2, out0, out0 + + srl out1, 4, local0 ! rotate + and out0, local5, local3 + + ld [$5+$3*8], local7 ! key 7531 + srl local3, 8, local3 + and local0, 252, local2 + + ld [global3+local3],local3 + sll out1, 28, out1 ! rotate + xor $1, local1, $1 ! 1 finished, local1 now sbox 7 + + ld [global2+local2], local2 + srl out0, 24, local1 + or out1, local0, out1 ! rotate + + ldub [out2+local1], local1 + srl out1, 24, local0 + and out1, local5, local4 + + ldub [out2+local0], local0 + srl local4, 8, local4 + xor $1, local2, $1 ! 2 finished local2 now sbox 6 + + ld [global4+local4],local4 + srl out1, 16, local2 + xor $1, local3, $1 ! 3 finished local3 now sbox 5 + + ld [out3+local0],local0 + and local2, 252, local2 + add global1, 1536, local5 ! address sbox 7 + + ld [local6+local2], local2 + srl out0, 16, local3 + xor $1, local4, $1 ! 4 finished + + ld [local5+local1],local1 + and local3, 252, local3 + xor $1, local0, $1 + + ld [global5+local3],local3 + xor $1, local2, $1 ! 6 finished + cmp in2, 8 + + ifelse($6,{}, {}, {ld [out2+280], out4}) ! loop counter + xor $1, local7, local2 ! sbox 5 next round + xor $1, local1, $1 ! 7 finished + + ld [$5+$3*8+4], out0 + srl local2, 16, local2 ! sbox 5 next round + xor $1, local3, $1 ! 5 finished + + and local2, 252, local2 +! next round (two rounds more) + xor $1, local7, local7 ! 7531 + + ld [global5+local2], local2 + srl local7, 24, local3 + xor $1, out0, out0 ! 8642 + + ldub [out2+local3], local3 + srl out0, 4, local0 ! rotate + and local7, 252, local1 + + sll out0, 28, out0 ! rotate + xor $2, local2, $2 ! 5 finished local2 used + + srl local0, 8, local4 + and local0, 252, local2 + ld [local5+local3], local3 + + srl local0, 16, local5 + or out0, local0, out0 ! rotate + ld [global2+local2], local2 + + srl out0, 24, local0 + ifelse($6,{}, {}, {ld [$6], out0}) ! key next encryption/decryption + and local4, 252, local4 + + and local5, 252, local5 + ld [global4+local4], local4 + xor $2, local3, $2 ! 7 finished local3 used + + and local0, 252, local0 + ld [local6+local5], local5 + xor $2, local2, $2 ! 2 finished local2 now sbox 3 + + srl local7, 8, local2 ! 3 start + ld [out3+local0], local0 + xor $2, local4, $2 + + and local2, 252, local2 + ld [global1+local1], local1 + xor $2, local5, $2 ! 6 finished local5 used + + ld [global3+local2], local2 + srl $1, 3, local3 + xor $2, local0, $2 + + ifelse($6,{}, {}, {ld [$6+4], out1}) ! key next encryption/decryption + sll $1, 29, local4 + xor $2, local1, $2 + + ifelse($7,{}, {}, {retl}) + xor $2, local2, $2 +}) + + +! {fp_macro} +! +! parameter 1 right (original left) +! parameter 2 left (original right) +! parameter 3 1 for optional store to [in0] +! parameter 4 1 for load input/output address to local5/7 +! +! The final permutation logic switches the halves, meaning that +! left and right ends up the registers originally used. + +define(fp_macro, { + +! {fp_macro} +! $1 $2 $3 $4 $5 $6 $7 $8 $9 + + ! initially undo the rotate 3 left done after initial permutation + ! original left is received shifted 3 right and 29 left in local3/4 + + sll $2, 29, local1 + or local3, local4, $1 + + srl $2, 3, $2 + sethi %hi(0x55555555), local2 + + or $2, local1, $2 + or local2, %lo(0x55555555), local2 + + srl $2, 1, local3 + sethi %hi(0x00ff00ff), local1 + xor local3, $1, local3 + or local1, %lo(0x00ff00ff), local1 + and local3, local2, local3 + sethi %hi(0x33333333), local4 + sll local3, 1, local2 + + xor $1, local3, $1 + + srl $1, 8, local3 + xor $2, local2, $2 + xor local3, $2, local3 + or local4, %lo(0x33333333), local4 + and local3, local1, local3 + sethi %hi(0x0000ffff), local1 + sll local3, 8, local2 + + xor $2, local3, $2 + + srl $2, 2, local3 + xor $1, local2, $1 + xor local3, $1, local3 + or local1, %lo(0x0000ffff), local1 + and local3, local4, local3 + sethi %hi(0x0f0f0f0f), local4 + sll local3, 2, local2 + + ifelse($4,1, {LDPTR INPUT, local5}) + xor $1, local3, $1 + + ifelse($4,1, {LDPTR OUTPUT, local7}) + srl $1, 16, local3 + xor $2, local2, $2 + xor local3, $2, local3 + or local4, %lo(0x0f0f0f0f), local4 + and local3, local1, local3 + sll local3, 16, local2 + + xor $2, local3, local1 + + srl local1, 4, local3 + xor $1, local2, $1 + xor local3, $1, local3 + and local3, local4, local3 + sll local3, 4, local2 + + xor $1, local3, $1 + + ! optional store: + + ifelse($3,1, {st $1, [in0]}) + + xor local1, local2, $2 + + ifelse($3,1, {st $2, [in0+4]}) + +}) + + +! {fp_ip_macro} +! +! Does initial permutation for next block mixed with +! final permutation for current block. +! +! parameter 1 original left +! parameter 2 original right +! parameter 3 left ip +! parameter 4 right ip +! parameter 5 1: load ks1/ks2 to in3/in4, add 120 to in4 +! 2: mov in4 to in3 +! +! also adds -8 to length in2 and loads loop counter to out4 + +define(fp_ip_macro, { + +! {fp_ip_macro} +! $1 $2 $3 $4 $5 $6 $7 $8 $9 + + define({temp1},{out4}) + define({temp2},{local3}) + + define({ip1},{local1}) + define({ip2},{local2}) + define({ip4},{local4}) + define({ip5},{local5}) + + ! $1 in local3, local4 + + ld [out2+256], ip1 + sll out5, 29, temp1 + or local3, local4, $1 + + srl out5, 3, $2 + ifelse($5,2,{mov in4, in3}) + + ld [out2+272], ip5 + srl $4, 4, local0 + or $2, temp1, $2 + + srl $2, 1, temp1 + xor temp1, $1, temp1 + + and temp1, ip5, temp1 + xor local0, $3, local0 + + sll temp1, 1, temp2 + xor $1, temp1, $1 + + and local0, ip1, local0 + add in2, -8, in2 + + sll local0, 4, local7 + xor $3, local0, $3 + + ld [out2+268], ip4 + srl $1, 8, temp1 + xor $2, temp2, $2 + ld [out2+260], ip2 + srl $3, 16, local0 + xor $4, local7, $4 + xor temp1, $2, temp1 + xor local0, $4, local0 + and temp1, ip4, temp1 + and local0, ip2, local0 + sll temp1, 8, temp2 + xor $2, temp1, $2 + sll local0, 16, local7 + xor $4, local0, $4 + + srl $2, 2, temp1 + xor $1, temp2, $1 + + ld [out2+264], temp2 ! ip3 + srl $4, 2, local0 + xor $3, local7, $3 + xor temp1, $1, temp1 + xor local0, $3, local0 + and temp1, temp2, temp1 + and local0, temp2, local0 + sll temp1, 2, temp2 + xor $1, temp1, $1 + sll local0, 2, local7 + xor $3, local0, $3 + + srl $1, 16, temp1 + xor $2, temp2, $2 + srl $3, 8, local0 + xor $4, local7, $4 + xor temp1, $2, temp1 + xor local0, $4, local0 + and temp1, ip2, temp1 + and local0, ip4, local0 + sll temp1, 16, temp2 + xor $2, temp1, local4 + sll local0, 8, local7 + xor $4, local0, $4 + + srl $4, 1, local0 + xor $3, local7, $3 + + srl local4, 4, temp1 + xor local0, $3, local0 + + xor $1, temp2, $1 + and local0, ip5, local0 + + sll local0, 1, local7 + xor temp1, $1, temp1 + + xor $3, local0, $3 + xor $4, local7, $4 + + sll $3, 3, local5 + and temp1, ip1, temp1 + + sll temp1, 4, temp2 + xor $1, temp1, $1 + + ifelse($5,1,{LDPTR KS2, in4}) + sll $4, 3, local2 + xor local4, temp2, $2 + + ! reload since used as temporary: + + ld [out2+280], out4 ! loop counter + + srl $3, 29, local0 + ifelse($5,1,{add in4, 120, in4}) + + ifelse($5,1,{LDPTR KS1, in3}) + srl $4, 29, local7 + + or local0, local5, $4 + or local2, local7, $3 + +}) + + + +! {load_little_endian} +! +! parameter 1 address +! parameter 2 destination left +! parameter 3 destination right +! parameter 4 temporary +! parameter 5 label + +define(load_little_endian, { + +! {load_little_endian} +! $1 $2 $3 $4 $5 $6 $7 $8 $9 + + ! first in memory to rightmost in register + +$5: + ldub [$1+3], $2 + + ldub [$1+2], $4 + sll $2, 8, $2 + or $2, $4, $2 + + ldub [$1+1], $4 + sll $2, 8, $2 + or $2, $4, $2 + + ldub [$1+0], $4 + sll $2, 8, $2 + or $2, $4, $2 + + + ldub [$1+3+4], $3 + + ldub [$1+2+4], $4 + sll $3, 8, $3 + or $3, $4, $3 + + ldub [$1+1+4], $4 + sll $3, 8, $3 + or $3, $4, $3 + + ldub [$1+0+4], $4 + sll $3, 8, $3 + or $3, $4, $3 +$5a: + +}) + + +! {load_little_endian_inc} +! +! parameter 1 address +! parameter 2 destination left +! parameter 3 destination right +! parameter 4 temporary +! parameter 4 label +! +! adds 8 to address + +define(load_little_endian_inc, { + +! {load_little_endian_inc} +! $1 $2 $3 $4 $5 $6 $7 $8 $9 + + ! first in memory to rightmost in register + +$5: + ldub [$1+3], $2 + + ldub [$1+2], $4 + sll $2, 8, $2 + or $2, $4, $2 + + ldub [$1+1], $4 + sll $2, 8, $2 + or $2, $4, $2 + + ldub [$1+0], $4 + sll $2, 8, $2 + or $2, $4, $2 + + ldub [$1+3+4], $3 + add $1, 8, $1 + + ldub [$1+2+4-8], $4 + sll $3, 8, $3 + or $3, $4, $3 + + ldub [$1+1+4-8], $4 + sll $3, 8, $3 + or $3, $4, $3 + + ldub [$1+0+4-8], $4 + sll $3, 8, $3 + or $3, $4, $3 +$5a: + +}) + + +! {load_n_bytes} +! +! Loads 1 to 7 bytes little endian +! Remaining bytes are zeroed. +! +! parameter 1 address +! parameter 2 length +! parameter 3 destination register left +! parameter 4 destination register right +! parameter 5 temp +! parameter 6 temp2 +! parameter 7 label +! parameter 8 return label + +define(load_n_bytes, { + +! {load_n_bytes} +! $1 $2 $5 $6 $7 $8 $7 $8 $9 + +$7.0: call .+8 + sll $2, 2, $6 + + add %o7,$7.jmp.table-$7.0,$5 + + add $5, $6, $5 + mov 0, $4 + + ld [$5], $5 + + jmp %o7+$5 + mov 0, $3 + +$7.7: + ldub [$1+6], $5 + sll $5, 16, $5 + or $3, $5, $3 +$7.6: + ldub [$1+5], $5 + sll $5, 8, $5 + or $3, $5, $3 +$7.5: + ldub [$1+4], $5 + or $3, $5, $3 +$7.4: + ldub [$1+3], $5 + sll $5, 24, $5 + or $4, $5, $4 +$7.3: + ldub [$1+2], $5 + sll $5, 16, $5 + or $4, $5, $4 +$7.2: + ldub [$1+1], $5 + sll $5, 8, $5 + or $4, $5, $4 +$7.1: + ldub [$1+0], $5 + ba $8 + or $4, $5, $4 + + .align 4 + +$7.jmp.table: + .word 0 + .word $7.1-$7.0 + .word $7.2-$7.0 + .word $7.3-$7.0 + .word $7.4-$7.0 + .word $7.5-$7.0 + .word $7.6-$7.0 + .word $7.7-$7.0 +}) + + +! {store_little_endian} +! +! parameter 1 address +! parameter 2 source left +! parameter 3 source right +! parameter 4 temporary + +define(store_little_endian, { + +! {store_little_endian} +! $1 $2 $3 $4 $5 $6 $7 $8 $9 + + ! rightmost in register to first in memory + +$5: + and $2, 255, $4 + stub $4, [$1+0] + + srl $2, 8, $4 + and $4, 255, $4 + stub $4, [$1+1] + + srl $2, 16, $4 + and $4, 255, $4 + stub $4, [$1+2] + + srl $2, 24, $4 + stub $4, [$1+3] + + + and $3, 255, $4 + stub $4, [$1+0+4] + + srl $3, 8, $4 + and $4, 255, $4 + stub $4, [$1+1+4] + + srl $3, 16, $4 + and $4, 255, $4 + stub $4, [$1+2+4] + + srl $3, 24, $4 + stub $4, [$1+3+4] + +$5a: + +}) + + +! {store_n_bytes} +! +! Stores 1 to 7 bytes little endian +! +! parameter 1 address +! parameter 2 length +! parameter 3 source register left +! parameter 4 source register right +! parameter 5 temp +! parameter 6 temp2 +! parameter 7 label +! parameter 8 return label + +define(store_n_bytes, { + +! {store_n_bytes} +! $1 $2 $5 $6 $7 $8 $7 $8 $9 + +$7.0: call .+8 + sll $2, 2, $6 + + add %o7,$7.jmp.table-$7.0,$5 + + add $5, $6, $5 + + ld [$5], $5 + + jmp %o7+$5 + nop + +$7.7: + srl $3, 16, $5 + and $5, 0xff, $5 + stub $5, [$1+6] +$7.6: + srl $3, 8, $5 + and $5, 0xff, $5 + stub $5, [$1+5] +$7.5: + and $3, 0xff, $5 + stub $5, [$1+4] +$7.4: + srl $4, 24, $5 + stub $5, [$1+3] +$7.3: + srl $4, 16, $5 + and $5, 0xff, $5 + stub $5, [$1+2] +$7.2: + srl $4, 8, $5 + and $5, 0xff, $5 + stub $5, [$1+1] +$7.1: + and $4, 0xff, $5 + + + ba $8 + stub $5, [$1] + + .align 4 + +$7.jmp.table: + + .word 0 + .word $7.1-$7.0 + .word $7.2-$7.0 + .word $7.3-$7.0 + .word $7.4-$7.0 + .word $7.5-$7.0 + .word $7.6-$7.0 + .word $7.7-$7.0 +}) + + +define(testvalue,{1}) + +define(register_init, { + +! For test purposes: + + sethi %hi(testvalue), local0 + or local0, %lo(testvalue), local0 + + ifelse($1,{},{}, {mov local0, $1}) + ifelse($2,{},{}, {mov local0, $2}) + ifelse($3,{},{}, {mov local0, $3}) + ifelse($4,{},{}, {mov local0, $4}) + ifelse($5,{},{}, {mov local0, $5}) + ifelse($6,{},{}, {mov local0, $6}) + ifelse($7,{},{}, {mov local0, $7}) + ifelse($8,{},{}, {mov local0, $8}) + + mov local0, local1 + mov local0, local2 + mov local0, local3 + mov local0, local4 + mov local0, local5 + mov local0, local7 + mov local0, local6 + mov local0, out0 + mov local0, out1 + mov local0, out2 + mov local0, out3 + mov local0, out4 + mov local0, out5 + mov local0, global1 + mov local0, global2 + mov local0, global3 + mov local0, global4 + mov local0, global5 + +}) + +.section ".text" + + .align 32 + +.des_enc: + + ! key address in3 + ! loads key next encryption/decryption first round from [in4] + + rounds_macro(in5, out5, 1, .des_enc.1, in3, in4, retl) + + + .align 32 + +.des_dec: + + ! implemented with out5 as first parameter to avoid + ! register exchange in ede modes + + ! key address in4 + ! loads key next encryption/decryption first round from [in3] + + rounds_macro(out5, in5, -1, .des_dec.1, in4, in3, retl) + + + +! void DES_encrypt1(data, ks, enc) +! ******************************* + + .align 32 + .global DES_encrypt1 + .type DES_encrypt1,#function + +DES_encrypt1: + + save %sp, FRAME, %sp + + sethi %hi(.PIC.DES_SPtrans-1f),global1 + or global1,%lo(.PIC.DES_SPtrans-1f),global1 +1: call .+8 + add %o7,global1,global1 + sub global1,.PIC.DES_SPtrans-.des_and,out2 + + ld [in0], in5 ! left + cmp in2, 0 ! enc + + be .encrypt.dec + ld [in0+4], out5 ! right + + ! parameter 6 1/2 for include encryption/decryption + ! parameter 7 1 for move in1 to in3 + ! parameter 8 1 for move in3 to in4, 2 for move in4 to in3 + + ip_macro(in5, out5, in5, out5, in3, 0, 1, 1) + + rounds_macro(in5, out5, 1, .des_encrypt1.1, in3, in4) ! in4 not used + + fp_macro(in5, out5, 1) ! 1 for store to [in0] + + ret + restore + +.encrypt.dec: + + add in1, 120, in3 ! use last subkey for first round + + ! parameter 6 1/2 for include encryption/decryption + ! parameter 7 1 for move in1 to in3 + ! parameter 8 1 for move in3 to in4, 2 for move in4 to in3 + + ip_macro(in5, out5, out5, in5, in4, 2, 0, 1) ! include dec, ks in4 + + fp_macro(out5, in5, 1) ! 1 for store to [in0] + + ret + restore + +.DES_encrypt1.end: + .size DES_encrypt1,.DES_encrypt1.end-DES_encrypt1 + + +! void DES_encrypt2(data, ks, enc) +!********************************* + + ! encrypts/decrypts without initial/final permutation + + .align 32 + .global DES_encrypt2 + .type DES_encrypt2,#function + +DES_encrypt2: + + save %sp, FRAME, %sp + + sethi %hi(.PIC.DES_SPtrans-1f),global1 + or global1,%lo(.PIC.DES_SPtrans-1f),global1 +1: call .+8 + add %o7,global1,global1 + sub global1,.PIC.DES_SPtrans-.des_and,out2 + + ! Set sbox address 1 to 6 and rotate halfs 3 left + ! Errors caught by destest? Yes. Still? *NO* + + !sethi %hi(DES_SPtrans), global1 ! address sbox 1 + + !or global1, %lo(DES_SPtrans), global1 ! sbox 1 + + add global1, 256, global2 ! sbox 2 + add global1, 512, global3 ! sbox 3 + + ld [in0], out5 ! right + add global1, 768, global4 ! sbox 4 + add global1, 1024, global5 ! sbox 5 + + ld [in0+4], in5 ! left + add global1, 1280, local6 ! sbox 6 + add global1, 1792, out3 ! sbox 8 + + ! rotate + + sll in5, 3, local5 + mov in1, in3 ! key address to in3 + + sll out5, 3, local7 + srl in5, 29, in5 + + srl out5, 29, out5 + add in5, local5, in5 + + add out5, local7, out5 + cmp in2, 0 + + ! we use our own stackframe + + be .encrypt2.dec + STPTR in0, [%sp+BIAS+ARG0+0*ARGSZ] + + ld [in3], out0 ! key 7531 first round + mov LOOPS, out4 ! loop counter + + ld [in3+4], out1 ! key 8642 first round + sethi %hi(0x0000FC00), local5 + + call .des_enc + mov in3, in4 + + ! rotate + sll in5, 29, in0 + srl in5, 3, in5 + sll out5, 29, in1 + add in5, in0, in5 + srl out5, 3, out5 + LDPTR [%sp+BIAS+ARG0+0*ARGSZ], in0 + add out5, in1, out5 + st in5, [in0] + st out5, [in0+4] + + ret + restore + + +.encrypt2.dec: + + add in3, 120, in4 + + ld [in4], out0 ! key 7531 first round + mov LOOPS, out4 ! loop counter + + ld [in4+4], out1 ! key 8642 first round + sethi %hi(0x0000FC00), local5 + + mov in5, local1 ! left expected in out5 + mov out5, in5 + + call .des_dec + mov local1, out5 + +.encrypt2.finish: + + ! rotate + sll in5, 29, in0 + srl in5, 3, in5 + sll out5, 29, in1 + add in5, in0, in5 + srl out5, 3, out5 + LDPTR [%sp+BIAS+ARG0+0*ARGSZ], in0 + add out5, in1, out5 + st out5, [in0] + st in5, [in0+4] + + ret + restore + +.DES_encrypt2.end: + .size DES_encrypt2, .DES_encrypt2.end-DES_encrypt2 + + +! void DES_encrypt3(data, ks1, ks2, ks3) +! ************************************** + + .align 32 + .global DES_encrypt3 + .type DES_encrypt3,#function + +DES_encrypt3: + + save %sp, FRAME, %sp + + sethi %hi(.PIC.DES_SPtrans-1f),global1 + or global1,%lo(.PIC.DES_SPtrans-1f),global1 +1: call .+8 + add %o7,global1,global1 + sub global1,.PIC.DES_SPtrans-.des_and,out2 + + ld [in0], in5 ! left + add in2, 120, in4 ! ks2 + + ld [in0+4], out5 ! right + mov in3, in2 ! save ks3 + + ! parameter 6 1/2 for include encryption/decryption + ! parameter 7 1 for mov in1 to in3 + ! parameter 8 1 for mov in3 to in4 + ! parameter 9 1 for load ks3 and ks2 to in4 and in3 + + ip_macro(in5, out5, in5, out5, in3, 1, 1, 0, 0) + + call .des_dec + mov in2, in3 ! preload ks3 + + call .des_enc + nop + + fp_macro(in5, out5, 1) + + ret + restore + +.DES_encrypt3.end: + .size DES_encrypt3,.DES_encrypt3.end-DES_encrypt3 + + +! void DES_decrypt3(data, ks1, ks2, ks3) +! ************************************** + + .align 32 + .global DES_decrypt3 + .type DES_decrypt3,#function + +DES_decrypt3: + + save %sp, FRAME, %sp + + sethi %hi(.PIC.DES_SPtrans-1f),global1 + or global1,%lo(.PIC.DES_SPtrans-1f),global1 +1: call .+8 + add %o7,global1,global1 + sub global1,.PIC.DES_SPtrans-.des_and,out2 + + ld [in0], in5 ! left + add in3, 120, in4 ! ks3 + + ld [in0+4], out5 ! right + mov in2, in3 ! ks2 + + ! parameter 6 1/2 for include encryption/decryption + ! parameter 7 1 for mov in1 to in3 + ! parameter 8 1 for mov in3 to in4 + ! parameter 9 1 for load ks3 and ks2 to in4 and in3 + + ip_macro(in5, out5, out5, in5, in4, 2, 0, 0, 0) + + call .des_enc + add in1, 120, in4 ! preload ks1 + + call .des_dec + nop + + fp_macro(out5, in5, 1) + + ret + restore + +.DES_decrypt3.end: + .size DES_decrypt3,.DES_decrypt3.end-DES_decrypt3 + +! void DES_ncbc_encrypt(input, output, length, schedule, ivec, enc) +! ***************************************************************** + + + .align 32 + .global DES_ncbc_encrypt + .type DES_ncbc_encrypt,#function + +DES_ncbc_encrypt: + + save %sp, FRAME, %sp + + define({INPUT}, { [%sp+BIAS+ARG0+0*ARGSZ] }) + define({OUTPUT}, { [%sp+BIAS+ARG0+1*ARGSZ] }) + define({IVEC}, { [%sp+BIAS+ARG0+4*ARGSZ] }) + + sethi %hi(.PIC.DES_SPtrans-1f),global1 + or global1,%lo(.PIC.DES_SPtrans-1f),global1 +1: call .+8 + add %o7,global1,global1 + sub global1,.PIC.DES_SPtrans-.des_and,out2 + + cmp in5, 0 ! enc + + be .ncbc.dec + STPTR in4, IVEC + + ! addr left right temp label + load_little_endian(in4, in5, out5, local3, .LLE1) ! iv + + addcc in2, -8, in2 ! bytes missing when first block done + + bl .ncbc.enc.seven.or.less + mov in3, in4 ! schedule + +.ncbc.enc.next.block: + + load_little_endian(in0, out4, global4, local3, .LLE2) ! block + +.ncbc.enc.next.block_1: + + xor in5, out4, in5 ! iv xor + xor out5, global4, out5 ! iv xor + + ! parameter 8 1 for move in3 to in4, 2 for move in4 to in3 + ip_macro(in5, out5, in5, out5, in3, 0, 0, 2) + +.ncbc.enc.next.block_2: + +!// call .des_enc ! compares in2 to 8 +! rounds inlined for alignment purposes + + add global1, 768, global4 ! address sbox 4 since register used below + + rounds_macro(in5, out5, 1, .ncbc.enc.1, in3, in4) ! include encryption ks in3 + + bl .ncbc.enc.next.block_fp + add in0, 8, in0 ! input address + + ! If 8 or more bytes are to be encrypted after this block, + ! we combine final permutation for this block with initial + ! permutation for next block. Load next block: + + load_little_endian(in0, global3, global4, local5, .LLE12) + + ! parameter 1 original left + ! parameter 2 original right + ! parameter 3 left ip + ! parameter 4 right ip + ! parameter 5 1: load ks1/ks2 to in3/in4, add 120 to in4 + ! 2: mov in4 to in3 + ! + ! also adds -8 to length in2 and loads loop counter to out4 + + fp_ip_macro(out0, out1, global3, global4, 2) + + store_little_endian(in1, out0, out1, local3, .SLE10) ! block + + ld [in3], out0 ! key 7531 first round next block + mov in5, local1 + xor global3, out5, in5 ! iv xor next block + + ld [in3+4], out1 ! key 8642 + add global1, 512, global3 ! address sbox 3 since register used + xor global4, local1, out5 ! iv xor next block + + ba .ncbc.enc.next.block_2 + add in1, 8, in1 ! output address + +.ncbc.enc.next.block_fp: + + fp_macro(in5, out5) + + store_little_endian(in1, in5, out5, local3, .SLE1) ! block + + addcc in2, -8, in2 ! bytes missing when next block done + + bpos .ncbc.enc.next.block + add in1, 8, in1 + +.ncbc.enc.seven.or.less: + + cmp in2, -8 + + ble .ncbc.enc.finish + nop + + add in2, 8, local1 ! bytes to load + + ! addr, length, dest left, dest right, temp, temp2, label, ret label + load_n_bytes(in0, local1, global4, out4, local2, local3, .LNB1, .ncbc.enc.next.block_1) + + ! Loads 1 to 7 bytes little endian to global4, out4 + + +.ncbc.enc.finish: + + LDPTR IVEC, local4 + store_little_endian(local4, in5, out5, local5, .SLE2) ! ivec + + ret + restore + + +.ncbc.dec: + + STPTR in0, INPUT + cmp in2, 0 ! length + add in3, 120, in3 + + LDPTR IVEC, local7 ! ivec + ble .ncbc.dec.finish + mov in3, in4 ! schedule + + STPTR in1, OUTPUT + mov in0, local5 ! input + + load_little_endian(local7, in0, in1, local3, .LLE3) ! ivec + +.ncbc.dec.next.block: + + load_little_endian(local5, in5, out5, local3, .LLE4) ! block + + ! parameter 6 1/2 for include encryption/decryption + ! parameter 7 1 for mov in1 to in3 + ! parameter 8 1 for mov in3 to in4 + + ip_macro(in5, out5, out5, in5, in4, 2, 0, 1) ! include decryption ks in4 + + fp_macro(out5, in5, 0, 1) ! 1 for input and output address to local5/7 + + ! in2 is bytes left to be stored + ! in2 is compared to 8 in the rounds + + xor out5, in0, out4 ! iv xor + bl .ncbc.dec.seven.or.less + xor in5, in1, global4 ! iv xor + + ! Load ivec next block now, since input and output address might be the same. + + load_little_endian_inc(local5, in0, in1, local3, .LLE5) ! iv + + store_little_endian(local7, out4, global4, local3, .SLE3) + + STPTR local5, INPUT + add local7, 8, local7 + addcc in2, -8, in2 + + bg .ncbc.dec.next.block + STPTR local7, OUTPUT + + +.ncbc.dec.store.iv: + + LDPTR IVEC, local4 ! ivec + store_little_endian(local4, in0, in1, local5, .SLE4) + +.ncbc.dec.finish: + + ret + restore + +.ncbc.dec.seven.or.less: + + load_little_endian_inc(local5, in0, in1, local3, .LLE13) ! ivec + + store_n_bytes(local7, in2, global4, out4, local3, local4, .SNB1, .ncbc.dec.store.iv) + + +.DES_ncbc_encrypt.end: + .size DES_ncbc_encrypt, .DES_ncbc_encrypt.end-DES_ncbc_encrypt + + +! void DES_ede3_cbc_encrypt(input, output, length, ks1, ks2, ks3, ivec, enc) +! ************************************************************************** + + + .align 32 + .global DES_ede3_cbc_encrypt + .type DES_ede3_cbc_encrypt,#function + +DES_ede3_cbc_encrypt: + + save %sp, FRAME, %sp + + define({KS1}, { [%sp+BIAS+ARG0+3*ARGSZ] }) + define({KS2}, { [%sp+BIAS+ARG0+4*ARGSZ] }) + define({KS3}, { [%sp+BIAS+ARG0+5*ARGSZ] }) + + sethi %hi(.PIC.DES_SPtrans-1f),global1 + or global1,%lo(.PIC.DES_SPtrans-1f),global1 +1: call .+8 + add %o7,global1,global1 + sub global1,.PIC.DES_SPtrans-.des_and,out2 + + LDPTR [%fp+BIAS+ARG0+7*ARGSZ], local3 ! enc + LDPTR [%fp+BIAS+ARG0+6*ARGSZ], local4 ! ivec + cmp local3, 0 ! enc + + be .ede3.dec + STPTR in4, KS2 + + STPTR in5, KS3 + + load_little_endian(local4, in5, out5, local3, .LLE6) ! ivec + + addcc in2, -8, in2 ! bytes missing after next block + + bl .ede3.enc.seven.or.less + STPTR in3, KS1 + +.ede3.enc.next.block: + + load_little_endian(in0, out4, global4, local3, .LLE7) + +.ede3.enc.next.block_1: + + LDPTR KS2, in4 + xor in5, out4, in5 ! iv xor + xor out5, global4, out5 ! iv xor + + LDPTR KS1, in3 + add in4, 120, in4 ! for decryption we use last subkey first + nop + + ip_macro(in5, out5, in5, out5, in3) + +.ede3.enc.next.block_2: + + call .des_enc ! ks1 in3 + nop + + call .des_dec ! ks2 in4 + LDPTR KS3, in3 + + call .des_enc ! ks3 in3 compares in2 to 8 + nop + + bl .ede3.enc.next.block_fp + add in0, 8, in0 + + ! If 8 or more bytes are to be encrypted after this block, + ! we combine final permutation for this block with initial + ! permutation for next block. Load next block: + + load_little_endian(in0, global3, global4, local5, .LLE11) + + ! parameter 1 original left + ! parameter 2 original right + ! parameter 3 left ip + ! parameter 4 right ip + ! parameter 5 1: load ks1/ks2 to in3/in4, add 120 to in4 + ! 2: mov in4 to in3 + ! + ! also adds -8 to length in2 and loads loop counter to out4 + + fp_ip_macro(out0, out1, global3, global4, 1) + + store_little_endian(in1, out0, out1, local3, .SLE9) ! block + + mov in5, local1 + xor global3, out5, in5 ! iv xor next block + + ld [in3], out0 ! key 7531 + add global1, 512, global3 ! address sbox 3 + xor global4, local1, out5 ! iv xor next block + + ld [in3+4], out1 ! key 8642 + add global1, 768, global4 ! address sbox 4 + ba .ede3.enc.next.block_2 + add in1, 8, in1 + +.ede3.enc.next.block_fp: + + fp_macro(in5, out5) + + store_little_endian(in1, in5, out5, local3, .SLE5) ! block + + addcc in2, -8, in2 ! bytes missing when next block done + + bpos .ede3.enc.next.block + add in1, 8, in1 + +.ede3.enc.seven.or.less: + + cmp in2, -8 + + ble .ede3.enc.finish + nop + + add in2, 8, local1 ! bytes to load + + ! addr, length, dest left, dest right, temp, temp2, label, ret label + load_n_bytes(in0, local1, global4, out4, local2, local3, .LNB2, .ede3.enc.next.block_1) + +.ede3.enc.finish: + + LDPTR [%fp+BIAS+ARG0+6*ARGSZ], local4 ! ivec + store_little_endian(local4, in5, out5, local5, .SLE6) ! ivec + + ret + restore + +.ede3.dec: + + STPTR in0, INPUT + add in5, 120, in5 + + STPTR in1, OUTPUT + mov in0, local5 + add in3, 120, in3 + + STPTR in3, KS1 + cmp in2, 0 + + ble .ede3.dec.finish + STPTR in5, KS3 + + LDPTR [%fp+BIAS+ARG0+6*ARGSZ], local7 ! iv + load_little_endian(local7, in0, in1, local3, .LLE8) + +.ede3.dec.next.block: + + load_little_endian(local5, in5, out5, local3, .LLE9) + + ! parameter 6 1/2 for include encryption/decryption + ! parameter 7 1 for mov in1 to in3 + ! parameter 8 1 for mov in3 to in4 + ! parameter 9 1 for load ks3 and ks2 to in4 and in3 + + ip_macro(in5, out5, out5, in5, in4, 2, 0, 0, 1) ! inc .des_dec ks3 in4 + + call .des_enc ! ks2 in3 + LDPTR KS1, in4 + + call .des_dec ! ks1 in4 + nop + + fp_macro(out5, in5, 0, 1) ! 1 for input and output address local5/7 + + ! in2 is bytes left to be stored + ! in2 is compared to 8 in the rounds + + xor out5, in0, out4 + bl .ede3.dec.seven.or.less + xor in5, in1, global4 + + load_little_endian_inc(local5, in0, in1, local3, .LLE10) ! iv next block + + store_little_endian(local7, out4, global4, local3, .SLE7) ! block + + STPTR local5, INPUT + addcc in2, -8, in2 + add local7, 8, local7 + + bg .ede3.dec.next.block + STPTR local7, OUTPUT + +.ede3.dec.store.iv: + + LDPTR [%fp+BIAS+ARG0+6*ARGSZ], local4 ! ivec + store_little_endian(local4, in0, in1, local5, .SLE8) ! ivec + +.ede3.dec.finish: + + ret + restore + +.ede3.dec.seven.or.less: + + load_little_endian_inc(local5, in0, in1, local3, .LLE14) ! iv + + store_n_bytes(local7, in2, global4, out4, local3, local4, .SNB2, .ede3.dec.store.iv) + + +.DES_ede3_cbc_encrypt.end: + .size DES_ede3_cbc_encrypt,.DES_ede3_cbc_encrypt.end-DES_ede3_cbc_encrypt + + .align 256 + .type .des_and,#object + .size .des_and,284 + +.des_and: + +! This table is used for AND 0xFC when it is known that register +! bits 8-31 are zero. Makes it possible to do three arithmetic +! operations in one cycle. + + .byte 0, 0, 0, 0, 4, 4, 4, 4 + .byte 8, 8, 8, 8, 12, 12, 12, 12 + .byte 16, 16, 16, 16, 20, 20, 20, 20 + .byte 24, 24, 24, 24, 28, 28, 28, 28 + .byte 32, 32, 32, 32, 36, 36, 36, 36 + .byte 40, 40, 40, 40, 44, 44, 44, 44 + .byte 48, 48, 48, 48, 52, 52, 52, 52 + .byte 56, 56, 56, 56, 60, 60, 60, 60 + .byte 64, 64, 64, 64, 68, 68, 68, 68 + .byte 72, 72, 72, 72, 76, 76, 76, 76 + .byte 80, 80, 80, 80, 84, 84, 84, 84 + .byte 88, 88, 88, 88, 92, 92, 92, 92 + .byte 96, 96, 96, 96, 100, 100, 100, 100 + .byte 104, 104, 104, 104, 108, 108, 108, 108 + .byte 112, 112, 112, 112, 116, 116, 116, 116 + .byte 120, 120, 120, 120, 124, 124, 124, 124 + .byte 128, 128, 128, 128, 132, 132, 132, 132 + .byte 136, 136, 136, 136, 140, 140, 140, 140 + .byte 144, 144, 144, 144, 148, 148, 148, 148 + .byte 152, 152, 152, 152, 156, 156, 156, 156 + .byte 160, 160, 160, 160, 164, 164, 164, 164 + .byte 168, 168, 168, 168, 172, 172, 172, 172 + .byte 176, 176, 176, 176, 180, 180, 180, 180 + .byte 184, 184, 184, 184, 188, 188, 188, 188 + .byte 192, 192, 192, 192, 196, 196, 196, 196 + .byte 200, 200, 200, 200, 204, 204, 204, 204 + .byte 208, 208, 208, 208, 212, 212, 212, 212 + .byte 216, 216, 216, 216, 220, 220, 220, 220 + .byte 224, 224, 224, 224, 228, 228, 228, 228 + .byte 232, 232, 232, 232, 236, 236, 236, 236 + .byte 240, 240, 240, 240, 244, 244, 244, 244 + .byte 248, 248, 248, 248, 252, 252, 252, 252 + + ! 5 numbers for initial/final permutation + + .word 0x0f0f0f0f ! offset 256 + .word 0x0000ffff ! 260 + .word 0x33333333 ! 264 + .word 0x00ff00ff ! 268 + .word 0x55555555 ! 272 + + .word 0 ! 276 + .word LOOPS ! 280 + .word 0x0000FC00 ! 284 + + .global DES_SPtrans + .type DES_SPtrans,#object + .size DES_SPtrans,2048 +.align 64 +DES_SPtrans: +.PIC.DES_SPtrans: + ! nibble 0 + .word 0x02080800, 0x00080000, 0x02000002, 0x02080802 + .word 0x02000000, 0x00080802, 0x00080002, 0x02000002 + .word 0x00080802, 0x02080800, 0x02080000, 0x00000802 + .word 0x02000802, 0x02000000, 0x00000000, 0x00080002 + .word 0x00080000, 0x00000002, 0x02000800, 0x00080800 + .word 0x02080802, 0x02080000, 0x00000802, 0x02000800 + .word 0x00000002, 0x00000800, 0x00080800, 0x02080002 + .word 0x00000800, 0x02000802, 0x02080002, 0x00000000 + .word 0x00000000, 0x02080802, 0x02000800, 0x00080002 + .word 0x02080800, 0x00080000, 0x00000802, 0x02000800 + .word 0x02080002, 0x00000800, 0x00080800, 0x02000002 + .word 0x00080802, 0x00000002, 0x02000002, 0x02080000 + .word 0x02080802, 0x00080800, 0x02080000, 0x02000802 + .word 0x02000000, 0x00000802, 0x00080002, 0x00000000 + .word 0x00080000, 0x02000000, 0x02000802, 0x02080800 + .word 0x00000002, 0x02080002, 0x00000800, 0x00080802 + ! nibble 1 + .word 0x40108010, 0x00000000, 0x00108000, 0x40100000 + .word 0x40000010, 0x00008010, 0x40008000, 0x00108000 + .word 0x00008000, 0x40100010, 0x00000010, 0x40008000 + .word 0x00100010, 0x40108000, 0x40100000, 0x00000010 + .word 0x00100000, 0x40008010, 0x40100010, 0x00008000 + .word 0x00108010, 0x40000000, 0x00000000, 0x00100010 + .word 0x40008010, 0x00108010, 0x40108000, 0x40000010 + .word 0x40000000, 0x00100000, 0x00008010, 0x40108010 + .word 0x00100010, 0x40108000, 0x40008000, 0x00108010 + .word 0x40108010, 0x00100010, 0x40000010, 0x00000000 + .word 0x40000000, 0x00008010, 0x00100000, 0x40100010 + .word 0x00008000, 0x40000000, 0x00108010, 0x40008010 + .word 0x40108000, 0x00008000, 0x00000000, 0x40000010 + .word 0x00000010, 0x40108010, 0x00108000, 0x40100000 + .word 0x40100010, 0x00100000, 0x00008010, 0x40008000 + .word 0x40008010, 0x00000010, 0x40100000, 0x00108000 + ! nibble 2 + .word 0x04000001, 0x04040100, 0x00000100, 0x04000101 + .word 0x00040001, 0x04000000, 0x04000101, 0x00040100 + .word 0x04000100, 0x00040000, 0x04040000, 0x00000001 + .word 0x04040101, 0x00000101, 0x00000001, 0x04040001 + .word 0x00000000, 0x00040001, 0x04040100, 0x00000100 + .word 0x00000101, 0x04040101, 0x00040000, 0x04000001 + .word 0x04040001, 0x04000100, 0x00040101, 0x04040000 + .word 0x00040100, 0x00000000, 0x04000000, 0x00040101 + .word 0x04040100, 0x00000100, 0x00000001, 0x00040000 + .word 0x00000101, 0x00040001, 0x04040000, 0x04000101 + .word 0x00000000, 0x04040100, 0x00040100, 0x04040001 + .word 0x00040001, 0x04000000, 0x04040101, 0x00000001 + .word 0x00040101, 0x04000001, 0x04000000, 0x04040101 + .word 0x00040000, 0x04000100, 0x04000101, 0x00040100 + .word 0x04000100, 0x00000000, 0x04040001, 0x00000101 + .word 0x04000001, 0x00040101, 0x00000100, 0x04040000 + ! nibble 3 + .word 0x00401008, 0x10001000, 0x00000008, 0x10401008 + .word 0x00000000, 0x10400000, 0x10001008, 0x00400008 + .word 0x10401000, 0x10000008, 0x10000000, 0x00001008 + .word 0x10000008, 0x00401008, 0x00400000, 0x10000000 + .word 0x10400008, 0x00401000, 0x00001000, 0x00000008 + .word 0x00401000, 0x10001008, 0x10400000, 0x00001000 + .word 0x00001008, 0x00000000, 0x00400008, 0x10401000 + .word 0x10001000, 0x10400008, 0x10401008, 0x00400000 + .word 0x10400008, 0x00001008, 0x00400000, 0x10000008 + .word 0x00401000, 0x10001000, 0x00000008, 0x10400000 + .word 0x10001008, 0x00000000, 0x00001000, 0x00400008 + .word 0x00000000, 0x10400008, 0x10401000, 0x00001000 + .word 0x10000000, 0x10401008, 0x00401008, 0x00400000 + .word 0x10401008, 0x00000008, 0x10001000, 0x00401008 + .word 0x00400008, 0x00401000, 0x10400000, 0x10001008 + .word 0x00001008, 0x10000000, 0x10000008, 0x10401000 + ! nibble 4 + .word 0x08000000, 0x00010000, 0x00000400, 0x08010420 + .word 0x08010020, 0x08000400, 0x00010420, 0x08010000 + .word 0x00010000, 0x00000020, 0x08000020, 0x00010400 + .word 0x08000420, 0x08010020, 0x08010400, 0x00000000 + .word 0x00010400, 0x08000000, 0x00010020, 0x00000420 + .word 0x08000400, 0x00010420, 0x00000000, 0x08000020 + .word 0x00000020, 0x08000420, 0x08010420, 0x00010020 + .word 0x08010000, 0x00000400, 0x00000420, 0x08010400 + .word 0x08010400, 0x08000420, 0x00010020, 0x08010000 + .word 0x00010000, 0x00000020, 0x08000020, 0x08000400 + .word 0x08000000, 0x00010400, 0x08010420, 0x00000000 + .word 0x00010420, 0x08000000, 0x00000400, 0x00010020 + .word 0x08000420, 0x00000400, 0x00000000, 0x08010420 + .word 0x08010020, 0x08010400, 0x00000420, 0x00010000 + .word 0x00010400, 0x08010020, 0x08000400, 0x00000420 + .word 0x00000020, 0x00010420, 0x08010000, 0x08000020 + ! nibble 5 + .word 0x80000040, 0x00200040, 0x00000000, 0x80202000 + .word 0x00200040, 0x00002000, 0x80002040, 0x00200000 + .word 0x00002040, 0x80202040, 0x00202000, 0x80000000 + .word 0x80002000, 0x80000040, 0x80200000, 0x00202040 + .word 0x00200000, 0x80002040, 0x80200040, 0x00000000 + .word 0x00002000, 0x00000040, 0x80202000, 0x80200040 + .word 0x80202040, 0x80200000, 0x80000000, 0x00002040 + .word 0x00000040, 0x00202000, 0x00202040, 0x80002000 + .word 0x00002040, 0x80000000, 0x80002000, 0x00202040 + .word 0x80202000, 0x00200040, 0x00000000, 0x80002000 + .word 0x80000000, 0x00002000, 0x80200040, 0x00200000 + .word 0x00200040, 0x80202040, 0x00202000, 0x00000040 + .word 0x80202040, 0x00202000, 0x00200000, 0x80002040 + .word 0x80000040, 0x80200000, 0x00202040, 0x00000000 + .word 0x00002000, 0x80000040, 0x80002040, 0x80202000 + .word 0x80200000, 0x00002040, 0x00000040, 0x80200040 + ! nibble 6 + .word 0x00004000, 0x00000200, 0x01000200, 0x01000004 + .word 0x01004204, 0x00004004, 0x00004200, 0x00000000 + .word 0x01000000, 0x01000204, 0x00000204, 0x01004000 + .word 0x00000004, 0x01004200, 0x01004000, 0x00000204 + .word 0x01000204, 0x00004000, 0x00004004, 0x01004204 + .word 0x00000000, 0x01000200, 0x01000004, 0x00004200 + .word 0x01004004, 0x00004204, 0x01004200, 0x00000004 + .word 0x00004204, 0x01004004, 0x00000200, 0x01000000 + .word 0x00004204, 0x01004000, 0x01004004, 0x00000204 + .word 0x00004000, 0x00000200, 0x01000000, 0x01004004 + .word 0x01000204, 0x00004204, 0x00004200, 0x00000000 + .word 0x00000200, 0x01000004, 0x00000004, 0x01000200 + .word 0x00000000, 0x01000204, 0x01000200, 0x00004200 + .word 0x00000204, 0x00004000, 0x01004204, 0x01000000 + .word 0x01004200, 0x00000004, 0x00004004, 0x01004204 + .word 0x01000004, 0x01004200, 0x01004000, 0x00004004 + ! nibble 7 + .word 0x20800080, 0x20820000, 0x00020080, 0x00000000 + .word 0x20020000, 0x00800080, 0x20800000, 0x20820080 + .word 0x00000080, 0x20000000, 0x00820000, 0x00020080 + .word 0x00820080, 0x20020080, 0x20000080, 0x20800000 + .word 0x00020000, 0x00820080, 0x00800080, 0x20020000 + .word 0x20820080, 0x20000080, 0x00000000, 0x00820000 + .word 0x20000000, 0x00800000, 0x20020080, 0x20800080 + .word 0x00800000, 0x00020000, 0x20820000, 0x00000080 + .word 0x00800000, 0x00020000, 0x20000080, 0x20820080 + .word 0x00020080, 0x20000000, 0x00000000, 0x00820000 + .word 0x20800080, 0x20020080, 0x20020000, 0x00800080 + .word 0x20820000, 0x00000080, 0x00800080, 0x20020000 + .word 0x20820080, 0x00800000, 0x20800000, 0x20000080 + .word 0x00820000, 0x00020080, 0x20020080, 0x20800000 + .word 0x00000080, 0x20820000, 0x00820080, 0x00000000 + .word 0x20000000, 0x20800080, 0x00020000, 0x00820080 + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/des/asm/desboth.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/des/asm/desboth.pl new file mode 100644 index 000000000..ef7054e27 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/des/asm/desboth.pl @@ -0,0 +1,86 @@ +#! /usr/bin/env perl +# Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +$L="edi"; +$R="esi"; + +sub DES_encrypt3 + { + local($name,$enc)=@_; + + &function_begin_B($name,""); + &push("ebx"); + &mov("ebx",&wparam(0)); + + &push("ebp"); + &push("esi"); + + &push("edi"); + + &comment(""); + &comment("Load the data words"); + &mov($L,&DWP(0,"ebx","",0)); + &mov($R,&DWP(4,"ebx","",0)); + &stack_push(3); + + &comment(""); + &comment("IP"); + &IP_new($L,$R,"edx",0); + + # put them back + + if ($enc) + { + &mov(&DWP(4,"ebx","",0),$R); + &mov("eax",&wparam(1)); + &mov(&DWP(0,"ebx","",0),"edx"); + &mov("edi",&wparam(2)); + &mov("esi",&wparam(3)); + } + else + { + &mov(&DWP(4,"ebx","",0),$R); + &mov("esi",&wparam(1)); + &mov(&DWP(0,"ebx","",0),"edx"); + &mov("edi",&wparam(2)); + &mov("eax",&wparam(3)); + } + &mov(&swtmp(2), (DWC(($enc)?"1":"0"))); + &mov(&swtmp(1), "eax"); + &mov(&swtmp(0), "ebx"); + &call("DES_encrypt2"); + &mov(&swtmp(2), (DWC(($enc)?"0":"1"))); + &mov(&swtmp(1), "edi"); + &mov(&swtmp(0), "ebx"); + &call("DES_encrypt2"); + &mov(&swtmp(2), (DWC(($enc)?"1":"0"))); + &mov(&swtmp(1), "esi"); + &mov(&swtmp(0), "ebx"); + &call("DES_encrypt2"); + + &stack_pop(3); + &mov($L,&DWP(0,"ebx","",0)); + &mov($R,&DWP(4,"ebx","",0)); + + &comment(""); + &comment("FP"); + &FP_new($L,$R,"eax",0); + + &mov(&DWP(0,"ebx","",0),"eax"); + &mov(&DWP(4,"ebx","",0),$R); + + &pop("edi"); + &pop("esi"); + &pop("ebp"); + &pop("ebx"); + &ret(); + &function_end_B($name); + } + + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/des/asm/dest4-sparcv9.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/des/asm/dest4-sparcv9.pl new file mode 100644 index 000000000..fe1fdc702 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/des/asm/dest4-sparcv9.pl @@ -0,0 +1,627 @@ +#! /usr/bin/env perl +# Copyright 2013-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by David S. Miller and Andy Polyakov. +# The module is licensed under 2-clause BSD +# license. March 2013. All rights reserved. +# ==================================================================== + +###################################################################### +# DES for SPARC T4. +# +# As with other hardware-assisted ciphers CBC encrypt results [for +# aligned data] are virtually identical to critical path lengths: +# +# DES Triple-DES +# CBC encrypt 4.14/4.15(*) 11.7/11.7 +# CBC decrypt 1.77/4.11(**) 6.42/7.47 +# +# (*) numbers after slash are for +# misaligned data; +# (**) this is result for largest +# block size, unlike all other +# cases smaller blocks results +# are better[?]; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "sparcv9_modes.pl"; + +$output=pop; +open STDOUT,">$output"; + +$code.=<<___; +#include "sparc_arch.h" + +#ifdef __arch64__ +.register %g2,#scratch +.register %g3,#scratch +#endif + +.text +___ + +{ my ($inp,$out)=("%o0","%o1"); + +$code.=<<___; +.align 32 +.globl des_t4_key_expand +.type des_t4_key_expand,#function +des_t4_key_expand: + andcc $inp, 0x7, %g0 + alignaddr $inp, %g0, $inp + bz,pt %icc, 1f + ldd [$inp + 0x00], %f0 + ldd [$inp + 0x08], %f2 + faligndata %f0, %f2, %f0 +1: des_kexpand %f0, 0, %f0 + des_kexpand %f0, 1, %f2 + std %f0, [$out + 0x00] + des_kexpand %f2, 3, %f6 + std %f2, [$out + 0x08] + des_kexpand %f2, 2, %f4 + des_kexpand %f6, 3, %f10 + std %f6, [$out + 0x18] + des_kexpand %f6, 2, %f8 + std %f4, [$out + 0x10] + des_kexpand %f10, 3, %f14 + std %f10, [$out + 0x28] + des_kexpand %f10, 2, %f12 + std %f8, [$out + 0x20] + des_kexpand %f14, 1, %f16 + std %f14, [$out + 0x38] + des_kexpand %f16, 3, %f20 + std %f12, [$out + 0x30] + des_kexpand %f16, 2, %f18 + std %f16, [$out + 0x40] + des_kexpand %f20, 3, %f24 + std %f20, [$out + 0x50] + des_kexpand %f20, 2, %f22 + std %f18, [$out + 0x48] + des_kexpand %f24, 3, %f28 + std %f24, [$out + 0x60] + des_kexpand %f24, 2, %f26 + std %f22, [$out + 0x58] + des_kexpand %f28, 1, %f30 + std %f28, [$out + 0x70] + std %f26, [$out + 0x68] + retl + std %f30, [$out + 0x78] +.size des_t4_key_expand,.-des_t4_key_expand +___ +} +{ my ($inp,$out,$len,$key,$ivec) = map("%o$_",(0..4)); + my ($ileft,$iright,$omask) = map("%g$_",(1..3)); + +$code.=<<___; +.globl des_t4_cbc_encrypt +.align 32 +des_t4_cbc_encrypt: + cmp $len, 0 + be,pn $::size_t_cc, .Lcbc_abort + srln $len, 0, $len ! needed on v8+, "nop" on v9 + ld [$ivec + 0], %f0 ! load ivec + ld [$ivec + 4], %f1 + + and $inp, 7, $ileft + andn $inp, 7, $inp + sll $ileft, 3, $ileft + mov 0xff, $omask + prefetch [$inp], 20 + prefetch [$inp + 63], 20 + sub %g0, $ileft, $iright + and $out, 7, %g4 + alignaddrl $out, %g0, $out + srl $omask, %g4, $omask + srlx $len, 3, $len + movrz %g4, 0, $omask + prefetch [$out], 22 + + ldd [$key + 0x00], %f4 ! load key schedule + ldd [$key + 0x08], %f6 + ldd [$key + 0x10], %f8 + ldd [$key + 0x18], %f10 + ldd [$key + 0x20], %f12 + ldd [$key + 0x28], %f14 + ldd [$key + 0x30], %f16 + ldd [$key + 0x38], %f18 + ldd [$key + 0x40], %f20 + ldd [$key + 0x48], %f22 + ldd [$key + 0x50], %f24 + ldd [$key + 0x58], %f26 + ldd [$key + 0x60], %f28 + ldd [$key + 0x68], %f30 + ldd [$key + 0x70], %f32 + ldd [$key + 0x78], %f34 + +.Ldes_cbc_enc_loop: + ldx [$inp + 0], %g4 + brz,pt $ileft, 4f + nop + + ldx [$inp + 8], %g5 + sllx %g4, $ileft, %g4 + srlx %g5, $iright, %g5 + or %g5, %g4, %g4 +4: + movxtod %g4, %f2 + prefetch [$inp + 8+63], 20 + add $inp, 8, $inp + fxor %f2, %f0, %f0 ! ^= ivec + prefetch [$out + 63], 22 + + des_ip %f0, %f0 + des_round %f4, %f6, %f0, %f0 + des_round %f8, %f10, %f0, %f0 + des_round %f12, %f14, %f0, %f0 + des_round %f16, %f18, %f0, %f0 + des_round %f20, %f22, %f0, %f0 + des_round %f24, %f26, %f0, %f0 + des_round %f28, %f30, %f0, %f0 + des_round %f32, %f34, %f0, %f0 + des_iip %f0, %f0 + + brnz,pn $omask, 2f + sub $len, 1, $len + + std %f0, [$out + 0] + brnz,pt $len, .Ldes_cbc_enc_loop + add $out, 8, $out + + st %f0, [$ivec + 0] ! write out ivec + retl + st %f1, [$ivec + 4] +.Lcbc_abort: + retl + nop + +.align 16 +2: ldxa [$inp]0x82, %g4 ! avoid read-after-write hazard + ! and ~4x deterioration + ! in inp==out case + faligndata %f0, %f0, %f2 ! handle unaligned output + + stda %f2, [$out + $omask]0xc0 ! partial store + add $out, 8, $out + orn %g0, $omask, $omask + stda %f2, [$out + $omask]0xc0 ! partial store + + brnz,pt $len, .Ldes_cbc_enc_loop+4 + orn %g0, $omask, $omask + + st %f0, [$ivec + 0] ! write out ivec + retl + st %f1, [$ivec + 4] +.type des_t4_cbc_encrypt,#function +.size des_t4_cbc_encrypt,.-des_t4_cbc_encrypt + +.globl des_t4_cbc_decrypt +.align 32 +des_t4_cbc_decrypt: + cmp $len, 0 + be,pn $::size_t_cc, .Lcbc_abort + srln $len, 0, $len ! needed on v8+, "nop" on v9 + ld [$ivec + 0], %f2 ! load ivec + ld [$ivec + 4], %f3 + + and $inp, 7, $ileft + andn $inp, 7, $inp + sll $ileft, 3, $ileft + mov 0xff, $omask + prefetch [$inp], 20 + prefetch [$inp + 63], 20 + sub %g0, $ileft, $iright + and $out, 7, %g4 + alignaddrl $out, %g0, $out + srl $omask, %g4, $omask + srlx $len, 3, $len + movrz %g4, 0, $omask + prefetch [$out], 22 + + ldd [$key + 0x78], %f4 ! load key schedule + ldd [$key + 0x70], %f6 + ldd [$key + 0x68], %f8 + ldd [$key + 0x60], %f10 + ldd [$key + 0x58], %f12 + ldd [$key + 0x50], %f14 + ldd [$key + 0x48], %f16 + ldd [$key + 0x40], %f18 + ldd [$key + 0x38], %f20 + ldd [$key + 0x30], %f22 + ldd [$key + 0x28], %f24 + ldd [$key + 0x20], %f26 + ldd [$key + 0x18], %f28 + ldd [$key + 0x10], %f30 + ldd [$key + 0x08], %f32 + ldd [$key + 0x00], %f34 + +.Ldes_cbc_dec_loop: + ldx [$inp + 0], %g4 + brz,pt $ileft, 4f + nop + + ldx [$inp + 8], %g5 + sllx %g4, $ileft, %g4 + srlx %g5, $iright, %g5 + or %g5, %g4, %g4 +4: + movxtod %g4, %f0 + prefetch [$inp + 8+63], 20 + add $inp, 8, $inp + prefetch [$out + 63], 22 + + des_ip %f0, %f0 + des_round %f4, %f6, %f0, %f0 + des_round %f8, %f10, %f0, %f0 + des_round %f12, %f14, %f0, %f0 + des_round %f16, %f18, %f0, %f0 + des_round %f20, %f22, %f0, %f0 + des_round %f24, %f26, %f0, %f0 + des_round %f28, %f30, %f0, %f0 + des_round %f32, %f34, %f0, %f0 + des_iip %f0, %f0 + + fxor %f2, %f0, %f0 ! ^= ivec + movxtod %g4, %f2 + + brnz,pn $omask, 2f + sub $len, 1, $len + + std %f0, [$out + 0] + brnz,pt $len, .Ldes_cbc_dec_loop + add $out, 8, $out + + st %f2, [$ivec + 0] ! write out ivec + retl + st %f3, [$ivec + 4] + +.align 16 +2: ldxa [$inp]0x82, %g4 ! avoid read-after-write hazard + ! and ~4x deterioration + ! in inp==out case + faligndata %f0, %f0, %f0 ! handle unaligned output + + stda %f0, [$out + $omask]0xc0 ! partial store + add $out, 8, $out + orn %g0, $omask, $omask + stda %f0, [$out + $omask]0xc0 ! partial store + + brnz,pt $len, .Ldes_cbc_dec_loop+4 + orn %g0, $omask, $omask + + st %f2, [$ivec + 0] ! write out ivec + retl + st %f3, [$ivec + 4] +.type des_t4_cbc_decrypt,#function +.size des_t4_cbc_decrypt,.-des_t4_cbc_decrypt +___ + +# One might wonder why does one have back-to-back des_iip/des_ip +# pairs between EDE passes. Indeed, aren't they inverse of each other? +# They almost are. Outcome of the pair is 32-bit words being swapped +# in target register. Consider pair of des_iip/des_ip as a way to +# perform the due swap, it's actually fastest way in this case. + +$code.=<<___; +.globl des_t4_ede3_cbc_encrypt +.align 32 +des_t4_ede3_cbc_encrypt: + cmp $len, 0 + be,pn $::size_t_cc, .Lcbc_abort + srln $len, 0, $len ! needed on v8+, "nop" on v9 + ld [$ivec + 0], %f0 ! load ivec + ld [$ivec + 4], %f1 + + and $inp, 7, $ileft + andn $inp, 7, $inp + sll $ileft, 3, $ileft + mov 0xff, $omask + prefetch [$inp], 20 + prefetch [$inp + 63], 20 + sub %g0, $ileft, $iright + and $out, 7, %g4 + alignaddrl $out, %g0, $out + srl $omask, %g4, $omask + srlx $len, 3, $len + movrz %g4, 0, $omask + prefetch [$out], 22 + + ldd [$key + 0x00], %f4 ! load key schedule + ldd [$key + 0x08], %f6 + ldd [$key + 0x10], %f8 + ldd [$key + 0x18], %f10 + ldd [$key + 0x20], %f12 + ldd [$key + 0x28], %f14 + ldd [$key + 0x30], %f16 + ldd [$key + 0x38], %f18 + ldd [$key + 0x40], %f20 + ldd [$key + 0x48], %f22 + ldd [$key + 0x50], %f24 + ldd [$key + 0x58], %f26 + ldd [$key + 0x60], %f28 + ldd [$key + 0x68], %f30 + ldd [$key + 0x70], %f32 + ldd [$key + 0x78], %f34 + +.Ldes_ede3_cbc_enc_loop: + ldx [$inp + 0], %g4 + brz,pt $ileft, 4f + nop + + ldx [$inp + 8], %g5 + sllx %g4, $ileft, %g4 + srlx %g5, $iright, %g5 + or %g5, %g4, %g4 +4: + movxtod %g4, %f2 + prefetch [$inp + 8+63], 20 + add $inp, 8, $inp + fxor %f2, %f0, %f0 ! ^= ivec + prefetch [$out + 63], 22 + + des_ip %f0, %f0 + des_round %f4, %f6, %f0, %f0 + des_round %f8, %f10, %f0, %f0 + des_round %f12, %f14, %f0, %f0 + des_round %f16, %f18, %f0, %f0 + ldd [$key + 0x100-0x08], %f36 + ldd [$key + 0x100-0x10], %f38 + des_round %f20, %f22, %f0, %f0 + ldd [$key + 0x100-0x18], %f40 + ldd [$key + 0x100-0x20], %f42 + des_round %f24, %f26, %f0, %f0 + ldd [$key + 0x100-0x28], %f44 + ldd [$key + 0x100-0x30], %f46 + des_round %f28, %f30, %f0, %f0 + ldd [$key + 0x100-0x38], %f48 + ldd [$key + 0x100-0x40], %f50 + des_round %f32, %f34, %f0, %f0 + ldd [$key + 0x100-0x48], %f52 + ldd [$key + 0x100-0x50], %f54 + des_iip %f0, %f0 + + ldd [$key + 0x100-0x58], %f56 + ldd [$key + 0x100-0x60], %f58 + des_ip %f0, %f0 + ldd [$key + 0x100-0x68], %f60 + ldd [$key + 0x100-0x70], %f62 + des_round %f36, %f38, %f0, %f0 + ldd [$key + 0x100-0x78], %f36 + ldd [$key + 0x100-0x80], %f38 + des_round %f40, %f42, %f0, %f0 + des_round %f44, %f46, %f0, %f0 + des_round %f48, %f50, %f0, %f0 + ldd [$key + 0x100+0x00], %f40 + ldd [$key + 0x100+0x08], %f42 + des_round %f52, %f54, %f0, %f0 + ldd [$key + 0x100+0x10], %f44 + ldd [$key + 0x100+0x18], %f46 + des_round %f56, %f58, %f0, %f0 + ldd [$key + 0x100+0x20], %f48 + ldd [$key + 0x100+0x28], %f50 + des_round %f60, %f62, %f0, %f0 + ldd [$key + 0x100+0x30], %f52 + ldd [$key + 0x100+0x38], %f54 + des_round %f36, %f38, %f0, %f0 + ldd [$key + 0x100+0x40], %f56 + ldd [$key + 0x100+0x48], %f58 + des_iip %f0, %f0 + + ldd [$key + 0x100+0x50], %f60 + ldd [$key + 0x100+0x58], %f62 + des_ip %f0, %f0 + ldd [$key + 0x100+0x60], %f36 + ldd [$key + 0x100+0x68], %f38 + des_round %f40, %f42, %f0, %f0 + ldd [$key + 0x100+0x70], %f40 + ldd [$key + 0x100+0x78], %f42 + des_round %f44, %f46, %f0, %f0 + des_round %f48, %f50, %f0, %f0 + des_round %f52, %f54, %f0, %f0 + des_round %f56, %f58, %f0, %f0 + des_round %f60, %f62, %f0, %f0 + des_round %f36, %f38, %f0, %f0 + des_round %f40, %f42, %f0, %f0 + des_iip %f0, %f0 + + brnz,pn $omask, 2f + sub $len, 1, $len + + std %f0, [$out + 0] + brnz,pt $len, .Ldes_ede3_cbc_enc_loop + add $out, 8, $out + + st %f0, [$ivec + 0] ! write out ivec + retl + st %f1, [$ivec + 4] + +.align 16 +2: ldxa [$inp]0x82, %g4 ! avoid read-after-write hazard + ! and ~2x deterioration + ! in inp==out case + faligndata %f0, %f0, %f2 ! handle unaligned output + + stda %f2, [$out + $omask]0xc0 ! partial store + add $out, 8, $out + orn %g0, $omask, $omask + stda %f2, [$out + $omask]0xc0 ! partial store + + brnz,pt $len, .Ldes_ede3_cbc_enc_loop+4 + orn %g0, $omask, $omask + + st %f0, [$ivec + 0] ! write out ivec + retl + st %f1, [$ivec + 4] +.type des_t4_ede3_cbc_encrypt,#function +.size des_t4_ede3_cbc_encrypt,.-des_t4_ede3_cbc_encrypt + +.globl des_t4_ede3_cbc_decrypt +.align 32 +des_t4_ede3_cbc_decrypt: + cmp $len, 0 + be,pn $::size_t_cc, .Lcbc_abort + srln $len, 0, $len ! needed on v8+, "nop" on v9 + ld [$ivec + 0], %f2 ! load ivec + ld [$ivec + 4], %f3 + + and $inp, 7, $ileft + andn $inp, 7, $inp + sll $ileft, 3, $ileft + mov 0xff, $omask + prefetch [$inp], 20 + prefetch [$inp + 63], 20 + sub %g0, $ileft, $iright + and $out, 7, %g4 + alignaddrl $out, %g0, $out + srl $omask, %g4, $omask + srlx $len, 3, $len + movrz %g4, 0, $omask + prefetch [$out], 22 + + ldd [$key + 0x100+0x78], %f4 ! load key schedule + ldd [$key + 0x100+0x70], %f6 + ldd [$key + 0x100+0x68], %f8 + ldd [$key + 0x100+0x60], %f10 + ldd [$key + 0x100+0x58], %f12 + ldd [$key + 0x100+0x50], %f14 + ldd [$key + 0x100+0x48], %f16 + ldd [$key + 0x100+0x40], %f18 + ldd [$key + 0x100+0x38], %f20 + ldd [$key + 0x100+0x30], %f22 + ldd [$key + 0x100+0x28], %f24 + ldd [$key + 0x100+0x20], %f26 + ldd [$key + 0x100+0x18], %f28 + ldd [$key + 0x100+0x10], %f30 + ldd [$key + 0x100+0x08], %f32 + ldd [$key + 0x100+0x00], %f34 + +.Ldes_ede3_cbc_dec_loop: + ldx [$inp + 0], %g4 + brz,pt $ileft, 4f + nop + + ldx [$inp + 8], %g5 + sllx %g4, $ileft, %g4 + srlx %g5, $iright, %g5 + or %g5, %g4, %g4 +4: + movxtod %g4, %f0 + prefetch [$inp + 8+63], 20 + add $inp, 8, $inp + prefetch [$out + 63], 22 + + des_ip %f0, %f0 + des_round %f4, %f6, %f0, %f0 + des_round %f8, %f10, %f0, %f0 + des_round %f12, %f14, %f0, %f0 + des_round %f16, %f18, %f0, %f0 + ldd [$key + 0x80+0x00], %f36 + ldd [$key + 0x80+0x08], %f38 + des_round %f20, %f22, %f0, %f0 + ldd [$key + 0x80+0x10], %f40 + ldd [$key + 0x80+0x18], %f42 + des_round %f24, %f26, %f0, %f0 + ldd [$key + 0x80+0x20], %f44 + ldd [$key + 0x80+0x28], %f46 + des_round %f28, %f30, %f0, %f0 + ldd [$key + 0x80+0x30], %f48 + ldd [$key + 0x80+0x38], %f50 + des_round %f32, %f34, %f0, %f0 + ldd [$key + 0x80+0x40], %f52 + ldd [$key + 0x80+0x48], %f54 + des_iip %f0, %f0 + + ldd [$key + 0x80+0x50], %f56 + ldd [$key + 0x80+0x58], %f58 + des_ip %f0, %f0 + ldd [$key + 0x80+0x60], %f60 + ldd [$key + 0x80+0x68], %f62 + des_round %f36, %f38, %f0, %f0 + ldd [$key + 0x80+0x70], %f36 + ldd [$key + 0x80+0x78], %f38 + des_round %f40, %f42, %f0, %f0 + des_round %f44, %f46, %f0, %f0 + des_round %f48, %f50, %f0, %f0 + ldd [$key + 0x80-0x08], %f40 + ldd [$key + 0x80-0x10], %f42 + des_round %f52, %f54, %f0, %f0 + ldd [$key + 0x80-0x18], %f44 + ldd [$key + 0x80-0x20], %f46 + des_round %f56, %f58, %f0, %f0 + ldd [$key + 0x80-0x28], %f48 + ldd [$key + 0x80-0x30], %f50 + des_round %f60, %f62, %f0, %f0 + ldd [$key + 0x80-0x38], %f52 + ldd [$key + 0x80-0x40], %f54 + des_round %f36, %f38, %f0, %f0 + ldd [$key + 0x80-0x48], %f56 + ldd [$key + 0x80-0x50], %f58 + des_iip %f0, %f0 + + ldd [$key + 0x80-0x58], %f60 + ldd [$key + 0x80-0x60], %f62 + des_ip %f0, %f0 + ldd [$key + 0x80-0x68], %f36 + ldd [$key + 0x80-0x70], %f38 + des_round %f40, %f42, %f0, %f0 + ldd [$key + 0x80-0x78], %f40 + ldd [$key + 0x80-0x80], %f42 + des_round %f44, %f46, %f0, %f0 + des_round %f48, %f50, %f0, %f0 + des_round %f52, %f54, %f0, %f0 + des_round %f56, %f58, %f0, %f0 + des_round %f60, %f62, %f0, %f0 + des_round %f36, %f38, %f0, %f0 + des_round %f40, %f42, %f0, %f0 + des_iip %f0, %f0 + + fxor %f2, %f0, %f0 ! ^= ivec + movxtod %g4, %f2 + + brnz,pn $omask, 2f + sub $len, 1, $len + + std %f0, [$out + 0] + brnz,pt $len, .Ldes_ede3_cbc_dec_loop + add $out, 8, $out + + st %f2, [$ivec + 0] ! write out ivec + retl + st %f3, [$ivec + 4] + +.align 16 +2: ldxa [$inp]0x82, %g4 ! avoid read-after-write hazard + ! and ~3x deterioration + ! in inp==out case + faligndata %f0, %f0, %f0 ! handle unaligned output + + stda %f0, [$out + $omask]0xc0 ! partial store + add $out, 8, $out + orn %g0, $omask, $omask + stda %f0, [$out + $omask]0xc0 ! partial store + + brnz,pt $len, .Ldes_ede3_cbc_dec_loop+4 + orn %g0, $omask, $omask + + st %f2, [$ivec + 0] ! write out ivec + retl + st %f3, [$ivec + 4] +.type des_t4_ede3_cbc_decrypt,#function +.size des_t4_ede3_cbc_decrypt,.-des_t4_ede3_cbc_decrypt +___ +} +$code.=<<___; +.asciz "DES for SPARC T4, David S. Miller, Andy Polyakov" +.align 4 +___ + +&emit_assembler(); + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/des/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/des/build.info new file mode 100644 index 000000000..05cb154cd --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/des/build.info @@ -0,0 +1,19 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + set_key.c ecb_enc.c cbc_enc.c \ + ecb3_enc.c cfb64enc.c cfb64ede.c cfb_enc.c \ + ofb64ede.c ofb64enc.c ofb_enc.c \ + str2key.c pcbc_enc.c qud_cksm.c rand_key.c \ + {- $target{des_asm_src} -} \ + fcrypt.c xcbc_enc.c cbc_cksm.c + +GENERATE[des_enc-sparc.S]=asm/des_enc.m4 +GENERATE[dest4-sparcv9.S]=asm/dest4-sparcv9.pl $(PERLASM_SCHEME) +INCLUDE[dest4-sparcv9.o]=.. + +GENERATE[des-586.s]=asm/des-586.pl \ + $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) +DEPEND[des-586.s]=../perlasm/x86asm.pl ../perlasm/cbc.pl +GENERATE[crypt586.s]=asm/crypt586.pl \ + $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) +DEPEND[crypt586.s]=../perlasm/x86asm.pl ../perlasm/cbc.pl diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/des/cbc_cksm.c b/trunk/3rdparty/openssl-1.1-fit/crypto/des/cbc_cksm.c new file mode 100644 index 000000000..5a1f72f82 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/des/cbc_cksm.c @@ -0,0 +1,53 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "des_locl.h" + +DES_LONG DES_cbc_cksum(const unsigned char *in, DES_cblock *output, + long length, DES_key_schedule *schedule, + const_DES_cblock *ivec) +{ + register DES_LONG tout0, tout1, tin0, tin1; + register long l = length; + DES_LONG tin[2]; + unsigned char *out = &(*output)[0]; + const unsigned char *iv = &(*ivec)[0]; + + c2l(iv, tout0); + c2l(iv, tout1); + for (; l > 0; l -= 8) { + if (l >= 8) { + c2l(in, tin0); + c2l(in, tin1); + } else + c2ln(in, tin0, tin1, l); + + tin0 ^= tout0; + tin[0] = tin0; + tin1 ^= tout1; + tin[1] = tin1; + DES_encrypt1((DES_LONG *)tin, schedule, DES_ENCRYPT); + tout0 = tin[0]; + tout1 = tin[1]; + } + if (out != NULL) { + l2c(tout0, out); + l2c(tout1, out); + } + tout0 = tin0 = tin1 = tin[0] = tin[1] = 0; + /* + * Transform the data in tout1 so that it will match the return value + * that the MIT Kerberos mit_des_cbc_cksum API returns. + */ + tout1 = ((tout1 >> 24L) & 0x000000FF) + | ((tout1 >> 8L) & 0x0000FF00) + | ((tout1 << 8L) & 0x00FF0000) + | ((tout1 << 24L) & 0xFF000000); + return tout1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/des/cbc_enc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/des/cbc_enc.c new file mode 100644 index 000000000..92e773f81 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/des/cbc_enc.c @@ -0,0 +1,12 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#define CBC_ENC_C__DONT_UPDATE_IV + +#include "ncbc_enc.c" /* des_cbc_encrypt */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/des/cfb64ede.c b/trunk/3rdparty/openssl-1.1-fit/crypto/des/cfb64ede.c new file mode 100644 index 000000000..21943f614 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/des/cfb64ede.c @@ -0,0 +1,189 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "des_locl.h" + +/* + * The input and output encrypted as though 64bit cfb mode is being used. + * The extra state information to record how much of the 64bit block we have + * used is contained in *num; + */ + +void DES_ede3_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3, + DES_cblock *ivec, int *num, int enc) +{ + register DES_LONG v0, v1; + register long l = length; + register int n = *num; + DES_LONG ti[2]; + unsigned char *iv, c, cc; + + iv = &(*ivec)[0]; + if (enc) { + while (l--) { + if (n == 0) { + c2l(iv, v0); + c2l(iv, v1); + + ti[0] = v0; + ti[1] = v1; + DES_encrypt3(ti, ks1, ks2, ks3); + v0 = ti[0]; + v1 = ti[1]; + + iv = &(*ivec)[0]; + l2c(v0, iv); + l2c(v1, iv); + iv = &(*ivec)[0]; + } + c = *(in++) ^ iv[n]; + *(out++) = c; + iv[n] = c; + n = (n + 1) & 0x07; + } + } else { + while (l--) { + if (n == 0) { + c2l(iv, v0); + c2l(iv, v1); + + ti[0] = v0; + ti[1] = v1; + DES_encrypt3(ti, ks1, ks2, ks3); + v0 = ti[0]; + v1 = ti[1]; + + iv = &(*ivec)[0]; + l2c(v0, iv); + l2c(v1, iv); + iv = &(*ivec)[0]; + } + cc = *(in++); + c = iv[n]; + iv[n] = cc; + *(out++) = c ^ cc; + n = (n + 1) & 0x07; + } + } + v0 = v1 = ti[0] = ti[1] = c = cc = 0; + *num = n; +} + +/* + * This is compatible with the single key CFB-r for DES, even thought that's + * not what EVP needs. + */ + +void DES_ede3_cfb_encrypt(const unsigned char *in, unsigned char *out, + int numbits, long length, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3, + DES_cblock *ivec, int enc) +{ + register DES_LONG d0, d1, v0, v1; + register unsigned long l = length, n = ((unsigned int)numbits + 7) / 8; + register int num = numbits, i; + DES_LONG ti[2]; + unsigned char *iv; + unsigned char ovec[16]; + + if (num > 64) + return; + iv = &(*ivec)[0]; + c2l(iv, v0); + c2l(iv, v1); + if (enc) { + while (l >= n) { + l -= n; + ti[0] = v0; + ti[1] = v1; + DES_encrypt3(ti, ks1, ks2, ks3); + c2ln(in, d0, d1, n); + in += n; + d0 ^= ti[0]; + d1 ^= ti[1]; + l2cn(d0, d1, out, n); + out += n; + /* + * 30-08-94 - eay - changed because l>>32 and l<<32 are bad under + * gcc :-( + */ + if (num == 32) { + v0 = v1; + v1 = d0; + } else if (num == 64) { + v0 = d0; + v1 = d1; + } else { + iv = &ovec[0]; + l2c(v0, iv); + l2c(v1, iv); + l2c(d0, iv); + l2c(d1, iv); + /* shift ovec left most of the bits... */ + memmove(ovec, ovec + num / 8, 8 + (num % 8 ? 1 : 0)); + /* now the remaining bits */ + if (num % 8 != 0) + for (i = 0; i < 8; ++i) { + ovec[i] <<= num % 8; + ovec[i] |= ovec[i + 1] >> (8 - num % 8); + } + iv = &ovec[0]; + c2l(iv, v0); + c2l(iv, v1); + } + } + } else { + while (l >= n) { + l -= n; + ti[0] = v0; + ti[1] = v1; + DES_encrypt3(ti, ks1, ks2, ks3); + c2ln(in, d0, d1, n); + in += n; + /* + * 30-08-94 - eay - changed because l>>32 and l<<32 are bad under + * gcc :-( + */ + if (num == 32) { + v0 = v1; + v1 = d0; + } else if (num == 64) { + v0 = d0; + v1 = d1; + } else { + iv = &ovec[0]; + l2c(v0, iv); + l2c(v1, iv); + l2c(d0, iv); + l2c(d1, iv); + /* shift ovec left most of the bits... */ + memmove(ovec, ovec + num / 8, 8 + (num % 8 ? 1 : 0)); + /* now the remaining bits */ + if (num % 8 != 0) + for (i = 0; i < 8; ++i) { + ovec[i] <<= num % 8; + ovec[i] |= ovec[i + 1] >> (8 - num % 8); + } + iv = &ovec[0]; + c2l(iv, v0); + c2l(iv, v1); + } + d0 ^= ti[0]; + d1 ^= ti[1]; + l2cn(d0, d1, out, n); + out += n; + } + } + iv = &(*ivec)[0]; + l2c(v0, iv); + l2c(v1, iv); + v0 = v1 = d0 = d1 = ti[0] = ti[1] = 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/des/cfb64enc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/des/cfb64enc.c new file mode 100644 index 000000000..96de51b05 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/des/cfb64enc.c @@ -0,0 +1,73 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "des_locl.h" + +/* + * The input and output encrypted as though 64bit cfb mode is being used. + * The extra state information to record how much of the 64bit block we have + * used is contained in *num; + */ + +void DES_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, int *num, int enc) +{ + register DES_LONG v0, v1; + register long l = length; + register int n = *num; + DES_LONG ti[2]; + unsigned char *iv, c, cc; + + iv = &(*ivec)[0]; + if (enc) { + while (l--) { + if (n == 0) { + c2l(iv, v0); + ti[0] = v0; + c2l(iv, v1); + ti[1] = v1; + DES_encrypt1(ti, schedule, DES_ENCRYPT); + iv = &(*ivec)[0]; + v0 = ti[0]; + l2c(v0, iv); + v0 = ti[1]; + l2c(v0, iv); + iv = &(*ivec)[0]; + } + c = *(in++) ^ iv[n]; + *(out++) = c; + iv[n] = c; + n = (n + 1) & 0x07; + } + } else { + while (l--) { + if (n == 0) { + c2l(iv, v0); + ti[0] = v0; + c2l(iv, v1); + ti[1] = v1; + DES_encrypt1(ti, schedule, DES_ENCRYPT); + iv = &(*ivec)[0]; + v0 = ti[0]; + l2c(v0, iv); + v0 = ti[1]; + l2c(v0, iv); + iv = &(*ivec)[0]; + } + cc = *(in++); + c = iv[n]; + iv[n] = cc; + *(out++) = c ^ cc; + n = (n + 1) & 0x07; + } + } + v0 = v1 = ti[0] = ti[1] = c = cc = 0; + *num = n; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/des/cfb_enc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/des/cfb_enc.c new file mode 100644 index 000000000..544392e40 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/des/cfb_enc.c @@ -0,0 +1,150 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "e_os.h" +#include "des_locl.h" +#include + +/* + * The input and output are loaded in multiples of 8 bits. What this means is + * that if you hame numbits=12 and length=2 the first 12 bits will be + * retrieved from the first byte and half the second. The second 12 bits + * will come from the 3rd and half the 4th byte. + */ +/* + * Until Aug 1 2003 this function did not correctly implement CFB-r, so it + * will not be compatible with any encryption prior to that date. Ben. + */ +void DES_cfb_encrypt(const unsigned char *in, unsigned char *out, int numbits, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, int enc) +{ + register DES_LONG d0, d1, v0, v1; + register unsigned long l = length; + register int num = numbits / 8, n = (numbits + 7) / 8, i, rem = + numbits % 8; + DES_LONG ti[2]; + unsigned char *iv; +#ifndef L_ENDIAN + unsigned char ovec[16]; +#else + unsigned int sh[4]; + unsigned char *ovec = (unsigned char *)sh; + + /* I kind of count that compiler optimizes away this assertion, */ + assert(sizeof(sh[0]) == 4); /* as this holds true for all, */ + /* but 16-bit platforms... */ + +#endif + + if (numbits <= 0 || numbits > 64) + return; + iv = &(*ivec)[0]; + c2l(iv, v0); + c2l(iv, v1); + if (enc) { + while (l >= (unsigned long)n) { + l -= n; + ti[0] = v0; + ti[1] = v1; + DES_encrypt1((DES_LONG *)ti, schedule, DES_ENCRYPT); + c2ln(in, d0, d1, n); + in += n; + d0 ^= ti[0]; + d1 ^= ti[1]; + l2cn(d0, d1, out, n); + out += n; + /* + * 30-08-94 - eay - changed because l>>32 and l<<32 are bad under + * gcc :-( + */ + if (numbits == 32) { + v0 = v1; + v1 = d0; + } else if (numbits == 64) { + v0 = d0; + v1 = d1; + } else { +#ifndef L_ENDIAN + iv = &ovec[0]; + l2c(v0, iv); + l2c(v1, iv); + l2c(d0, iv); + l2c(d1, iv); +#else + sh[0] = v0, sh[1] = v1, sh[2] = d0, sh[3] = d1; +#endif + if (rem == 0) + memmove(ovec, ovec + num, 8); + else + for (i = 0; i < 8; ++i) + ovec[i] = ovec[i + num] << rem | + ovec[i + num + 1] >> (8 - rem); +#ifdef L_ENDIAN + v0 = sh[0], v1 = sh[1]; +#else + iv = &ovec[0]; + c2l(iv, v0); + c2l(iv, v1); +#endif + } + } + } else { + while (l >= (unsigned long)n) { + l -= n; + ti[0] = v0; + ti[1] = v1; + DES_encrypt1((DES_LONG *)ti, schedule, DES_ENCRYPT); + c2ln(in, d0, d1, n); + in += n; + /* + * 30-08-94 - eay - changed because l>>32 and l<<32 are bad under + * gcc :-( + */ + if (numbits == 32) { + v0 = v1; + v1 = d0; + } else if (numbits == 64) { + v0 = d0; + v1 = d1; + } else { +#ifndef L_ENDIAN + iv = &ovec[0]; + l2c(v0, iv); + l2c(v1, iv); + l2c(d0, iv); + l2c(d1, iv); +#else + sh[0] = v0, sh[1] = v1, sh[2] = d0, sh[3] = d1; +#endif + if (rem == 0) + memmove(ovec, ovec + num, 8); + else + for (i = 0; i < 8; ++i) + ovec[i] = ovec[i + num] << rem | + ovec[i + num + 1] >> (8 - rem); +#ifdef L_ENDIAN + v0 = sh[0], v1 = sh[1]; +#else + iv = &ovec[0]; + c2l(iv, v0); + c2l(iv, v1); +#endif + } + d0 ^= ti[0]; + d1 ^= ti[1]; + l2cn(d0, d1, out, n); + out += n; + } + } + iv = &(*ivec)[0]; + l2c(v0, iv); + l2c(v1, iv); + v0 = v1 = d0 = d1 = ti[0] = ti[1] = 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/des/des_enc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/des/des_enc.c new file mode 100644 index 000000000..ed134ace8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/des/des_enc.c @@ -0,0 +1,299 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "des_locl.h" +#include "spr.h" + +void DES_encrypt1(DES_LONG *data, DES_key_schedule *ks, int enc) +{ + register DES_LONG l, r, t, u; + register DES_LONG *s; + + r = data[0]; + l = data[1]; + + IP(r, l); + /* + * Things have been modified so that the initial rotate is done outside + * the loop. This required the DES_SPtrans values in sp.h to be rotated + * 1 bit to the right. One perl script later and things have a 5% speed + * up on a sparc2. Thanks to Richard Outerbridge for pointing this out. + */ + /* clear the top bits on machines with 8byte longs */ + /* shift left by 2 */ + r = ROTATE(r, 29) & 0xffffffffL; + l = ROTATE(l, 29) & 0xffffffffL; + + s = ks->ks->deslong; + /* + * I don't know if it is worth the effort of loop unrolling the inner + * loop + */ + if (enc) { + D_ENCRYPT(l, r, 0); /* 1 */ + D_ENCRYPT(r, l, 2); /* 2 */ + D_ENCRYPT(l, r, 4); /* 3 */ + D_ENCRYPT(r, l, 6); /* 4 */ + D_ENCRYPT(l, r, 8); /* 5 */ + D_ENCRYPT(r, l, 10); /* 6 */ + D_ENCRYPT(l, r, 12); /* 7 */ + D_ENCRYPT(r, l, 14); /* 8 */ + D_ENCRYPT(l, r, 16); /* 9 */ + D_ENCRYPT(r, l, 18); /* 10 */ + D_ENCRYPT(l, r, 20); /* 11 */ + D_ENCRYPT(r, l, 22); /* 12 */ + D_ENCRYPT(l, r, 24); /* 13 */ + D_ENCRYPT(r, l, 26); /* 14 */ + D_ENCRYPT(l, r, 28); /* 15 */ + D_ENCRYPT(r, l, 30); /* 16 */ + } else { + D_ENCRYPT(l, r, 30); /* 16 */ + D_ENCRYPT(r, l, 28); /* 15 */ + D_ENCRYPT(l, r, 26); /* 14 */ + D_ENCRYPT(r, l, 24); /* 13 */ + D_ENCRYPT(l, r, 22); /* 12 */ + D_ENCRYPT(r, l, 20); /* 11 */ + D_ENCRYPT(l, r, 18); /* 10 */ + D_ENCRYPT(r, l, 16); /* 9 */ + D_ENCRYPT(l, r, 14); /* 8 */ + D_ENCRYPT(r, l, 12); /* 7 */ + D_ENCRYPT(l, r, 10); /* 6 */ + D_ENCRYPT(r, l, 8); /* 5 */ + D_ENCRYPT(l, r, 6); /* 4 */ + D_ENCRYPT(r, l, 4); /* 3 */ + D_ENCRYPT(l, r, 2); /* 2 */ + D_ENCRYPT(r, l, 0); /* 1 */ + } + + /* rotate and clear the top bits on machines with 8byte longs */ + l = ROTATE(l, 3) & 0xffffffffL; + r = ROTATE(r, 3) & 0xffffffffL; + + FP(r, l); + data[0] = l; + data[1] = r; + l = r = t = u = 0; +} + +void DES_encrypt2(DES_LONG *data, DES_key_schedule *ks, int enc) +{ + register DES_LONG l, r, t, u; + register DES_LONG *s; + + r = data[0]; + l = data[1]; + + /* + * Things have been modified so that the initial rotate is done outside + * the loop. This required the DES_SPtrans values in sp.h to be rotated + * 1 bit to the right. One perl script later and things have a 5% speed + * up on a sparc2. Thanks to Richard Outerbridge for pointing this out. + */ + /* clear the top bits on machines with 8byte longs */ + r = ROTATE(r, 29) & 0xffffffffL; + l = ROTATE(l, 29) & 0xffffffffL; + + s = ks->ks->deslong; + /* + * I don't know if it is worth the effort of loop unrolling the inner + * loop + */ + if (enc) { + D_ENCRYPT(l, r, 0); /* 1 */ + D_ENCRYPT(r, l, 2); /* 2 */ + D_ENCRYPT(l, r, 4); /* 3 */ + D_ENCRYPT(r, l, 6); /* 4 */ + D_ENCRYPT(l, r, 8); /* 5 */ + D_ENCRYPT(r, l, 10); /* 6 */ + D_ENCRYPT(l, r, 12); /* 7 */ + D_ENCRYPT(r, l, 14); /* 8 */ + D_ENCRYPT(l, r, 16); /* 9 */ + D_ENCRYPT(r, l, 18); /* 10 */ + D_ENCRYPT(l, r, 20); /* 11 */ + D_ENCRYPT(r, l, 22); /* 12 */ + D_ENCRYPT(l, r, 24); /* 13 */ + D_ENCRYPT(r, l, 26); /* 14 */ + D_ENCRYPT(l, r, 28); /* 15 */ + D_ENCRYPT(r, l, 30); /* 16 */ + } else { + D_ENCRYPT(l, r, 30); /* 16 */ + D_ENCRYPT(r, l, 28); /* 15 */ + D_ENCRYPT(l, r, 26); /* 14 */ + D_ENCRYPT(r, l, 24); /* 13 */ + D_ENCRYPT(l, r, 22); /* 12 */ + D_ENCRYPT(r, l, 20); /* 11 */ + D_ENCRYPT(l, r, 18); /* 10 */ + D_ENCRYPT(r, l, 16); /* 9 */ + D_ENCRYPT(l, r, 14); /* 8 */ + D_ENCRYPT(r, l, 12); /* 7 */ + D_ENCRYPT(l, r, 10); /* 6 */ + D_ENCRYPT(r, l, 8); /* 5 */ + D_ENCRYPT(l, r, 6); /* 4 */ + D_ENCRYPT(r, l, 4); /* 3 */ + D_ENCRYPT(l, r, 2); /* 2 */ + D_ENCRYPT(r, l, 0); /* 1 */ + } + /* rotate and clear the top bits on machines with 8byte longs */ + data[0] = ROTATE(l, 3) & 0xffffffffL; + data[1] = ROTATE(r, 3) & 0xffffffffL; + l = r = t = u = 0; +} + +void DES_encrypt3(DES_LONG *data, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3) +{ + register DES_LONG l, r; + + l = data[0]; + r = data[1]; + IP(l, r); + data[0] = l; + data[1] = r; + DES_encrypt2((DES_LONG *)data, ks1, DES_ENCRYPT); + DES_encrypt2((DES_LONG *)data, ks2, DES_DECRYPT); + DES_encrypt2((DES_LONG *)data, ks3, DES_ENCRYPT); + l = data[0]; + r = data[1]; + FP(r, l); + data[0] = l; + data[1] = r; +} + +void DES_decrypt3(DES_LONG *data, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3) +{ + register DES_LONG l, r; + + l = data[0]; + r = data[1]; + IP(l, r); + data[0] = l; + data[1] = r; + DES_encrypt2((DES_LONG *)data, ks3, DES_DECRYPT); + DES_encrypt2((DES_LONG *)data, ks2, DES_ENCRYPT); + DES_encrypt2((DES_LONG *)data, ks1, DES_DECRYPT); + l = data[0]; + r = data[1]; + FP(r, l); + data[0] = l; + data[1] = r; +} + +#ifndef DES_DEFAULT_OPTIONS + +# undef CBC_ENC_C__DONT_UPDATE_IV +# include "ncbc_enc.c" /* DES_ncbc_encrypt */ + +void DES_ede3_cbc_encrypt(const unsigned char *input, unsigned char *output, + long length, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3, + DES_cblock *ivec, int enc) +{ + register DES_LONG tin0, tin1; + register DES_LONG tout0, tout1, xor0, xor1; + register const unsigned char *in; + unsigned char *out; + register long l = length; + DES_LONG tin[2]; + unsigned char *iv; + + in = input; + out = output; + iv = &(*ivec)[0]; + + if (enc) { + c2l(iv, tout0); + c2l(iv, tout1); + for (l -= 8; l >= 0; l -= 8) { + c2l(in, tin0); + c2l(in, tin1); + tin0 ^= tout0; + tin1 ^= tout1; + + tin[0] = tin0; + tin[1] = tin1; + DES_encrypt3((DES_LONG *)tin, ks1, ks2, ks3); + tout0 = tin[0]; + tout1 = tin[1]; + + l2c(tout0, out); + l2c(tout1, out); + } + if (l != -8) { + c2ln(in, tin0, tin1, l + 8); + tin0 ^= tout0; + tin1 ^= tout1; + + tin[0] = tin0; + tin[1] = tin1; + DES_encrypt3((DES_LONG *)tin, ks1, ks2, ks3); + tout0 = tin[0]; + tout1 = tin[1]; + + l2c(tout0, out); + l2c(tout1, out); + } + iv = &(*ivec)[0]; + l2c(tout0, iv); + l2c(tout1, iv); + } else { + register DES_LONG t0, t1; + + c2l(iv, xor0); + c2l(iv, xor1); + for (l -= 8; l >= 0; l -= 8) { + c2l(in, tin0); + c2l(in, tin1); + + t0 = tin0; + t1 = tin1; + + tin[0] = tin0; + tin[1] = tin1; + DES_decrypt3((DES_LONG *)tin, ks1, ks2, ks3); + tout0 = tin[0]; + tout1 = tin[1]; + + tout0 ^= xor0; + tout1 ^= xor1; + l2c(tout0, out); + l2c(tout1, out); + xor0 = t0; + xor1 = t1; + } + if (l != -8) { + c2l(in, tin0); + c2l(in, tin1); + + t0 = tin0; + t1 = tin1; + + tin[0] = tin0; + tin[1] = tin1; + DES_decrypt3((DES_LONG *)tin, ks1, ks2, ks3); + tout0 = tin[0]; + tout1 = tin[1]; + + tout0 ^= xor0; + tout1 ^= xor1; + l2cn(tout0, tout1, out, l + 8); + xor0 = t0; + xor1 = t1; + } + + iv = &(*ivec)[0]; + l2c(xor0, iv); + l2c(xor1, iv); + } + tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0; + tin[0] = tin[1] = 0; +} + +#endif /* DES_DEFAULT_OPTIONS */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/des/des_locl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/des/des_locl.h new file mode 100644 index 000000000..f401e6f3e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/des/des_locl.h @@ -0,0 +1,226 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_DES_LOCL_H +# define HEADER_DES_LOCL_H + +# include + +# include +# include +# include + +# include + +# ifdef OPENSSL_BUILD_SHLIBCRYPTO +# undef OPENSSL_EXTERN +# define OPENSSL_EXTERN OPENSSL_EXPORT +# endif + +# define ITERATIONS 16 +# define HALF_ITERATIONS 8 + +# define c2l(c,l) (l =((DES_LONG)(*((c)++))) , \ + l|=((DES_LONG)(*((c)++)))<< 8L, \ + l|=((DES_LONG)(*((c)++)))<<16L, \ + l|=((DES_LONG)(*((c)++)))<<24L) + +/* NOTE - c is not incremented as per c2l */ +# define c2ln(c,l1,l2,n) { \ + c+=n; \ + l1=l2=0; \ + switch (n) { \ + case 8: l2 =((DES_LONG)(*(--(c))))<<24L; \ + /* fall thru */ \ + case 7: l2|=((DES_LONG)(*(--(c))))<<16L; \ + /* fall thru */ \ + case 6: l2|=((DES_LONG)(*(--(c))))<< 8L; \ + /* fall thru */ \ + case 5: l2|=((DES_LONG)(*(--(c)))); \ + /* fall thru */ \ + case 4: l1 =((DES_LONG)(*(--(c))))<<24L; \ + /* fall thru */ \ + case 3: l1|=((DES_LONG)(*(--(c))))<<16L; \ + /* fall thru */ \ + case 2: l1|=((DES_LONG)(*(--(c))))<< 8L; \ + /* fall thru */ \ + case 1: l1|=((DES_LONG)(*(--(c)))); \ + } \ + } + +# define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24L)&0xff)) + +/* + * replacements for htonl and ntohl since I have no idea what to do when + * faced with machines with 8 byte longs. + */ + +# define n2l(c,l) (l =((DES_LONG)(*((c)++)))<<24L, \ + l|=((DES_LONG)(*((c)++)))<<16L, \ + l|=((DES_LONG)(*((c)++)))<< 8L, \ + l|=((DES_LONG)(*((c)++)))) + +# define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +/* NOTE - c is not incremented as per l2c */ +# define l2cn(l1,l2,c,n) { \ + c+=n; \ + switch (n) { \ + case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \ + /* fall thru */ \ + case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \ + /* fall thru */ \ + case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \ + /* fall thru */ \ + case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ + /* fall thru */ \ + case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \ + /* fall thru */ \ + case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \ + /* fall thru */ \ + case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \ + /* fall thru */ \ + case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ + } \ + } + +# if defined(_MSC_VER) +# define ROTATE(a,n) (_lrotr(a,n)) +# elif defined(__ICC) +# define ROTATE(a,n) (_rotr(a,n)) +# elif defined(__GNUC__) && __GNUC__>=2 && !defined(__STRICT_ANSI__) && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) && !defined(PEDANTIC) +# if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__) +# define ROTATE(a,n) ({ register unsigned int ret; \ + asm ("rorl %1,%0" \ + : "=r"(ret) \ + : "I"(n),"0"(a) \ + : "cc"); \ + ret; \ + }) +# endif +# endif +# ifndef ROTATE +# define ROTATE(a,n) (((a)>>(n))+((a)<<(32-(n)))) +# endif + +/* + * Don't worry about the LOAD_DATA() stuff, that is used by fcrypt() to add + * it's little bit to the front + */ + +# ifdef DES_FCRYPT + +# define LOAD_DATA_tmp(R,S,u,t,E0,E1) \ + { DES_LONG tmp; LOAD_DATA(R,S,u,t,E0,E1,tmp); } + +# define LOAD_DATA(R,S,u,t,E0,E1,tmp) \ + t=R^(R>>16L); \ + u=t&E0; t&=E1; \ + tmp=(u<<16); u^=R^s[S ]; u^=tmp; \ + tmp=(t<<16); t^=R^s[S+1]; t^=tmp +# else +# define LOAD_DATA_tmp(a,b,c,d,e,f) LOAD_DATA(a,b,c,d,e,f,g) +# define LOAD_DATA(R,S,u,t,E0,E1,tmp) \ + u=R^s[S ]; \ + t=R^s[S+1] +# endif + +/* + * It recently occurred to me that 0^0^0^0^0^0^0 == 0, so there is no reason + * to not xor all the sub items together. This potentially saves a register + * since things can be xored directly into L + */ + +# define D_ENCRYPT(LL,R,S) { \ + LOAD_DATA_tmp(R,S,u,t,E0,E1); \ + t=ROTATE(t,4); \ + LL^= \ + DES_SPtrans[0][(u>> 2L)&0x3f]^ \ + DES_SPtrans[2][(u>>10L)&0x3f]^ \ + DES_SPtrans[4][(u>>18L)&0x3f]^ \ + DES_SPtrans[6][(u>>26L)&0x3f]^ \ + DES_SPtrans[1][(t>> 2L)&0x3f]^ \ + DES_SPtrans[3][(t>>10L)&0x3f]^ \ + DES_SPtrans[5][(t>>18L)&0x3f]^ \ + DES_SPtrans[7][(t>>26L)&0x3f]; } + + /*- + * IP and FP + * The problem is more of a geometric problem that random bit fiddling. + 0 1 2 3 4 5 6 7 62 54 46 38 30 22 14 6 + 8 9 10 11 12 13 14 15 60 52 44 36 28 20 12 4 + 16 17 18 19 20 21 22 23 58 50 42 34 26 18 10 2 + 24 25 26 27 28 29 30 31 to 56 48 40 32 24 16 8 0 + + 32 33 34 35 36 37 38 39 63 55 47 39 31 23 15 7 + 40 41 42 43 44 45 46 47 61 53 45 37 29 21 13 5 + 48 49 50 51 52 53 54 55 59 51 43 35 27 19 11 3 + 56 57 58 59 60 61 62 63 57 49 41 33 25 17 9 1 + + The output has been subject to swaps of the form + 0 1 -> 3 1 but the odd and even bits have been put into + 2 3 2 0 + different words. The main trick is to remember that + t=((l>>size)^r)&(mask); + r^=t; + l^=(t<>(n))^(b))&(m)),\ + (b)^=(t),\ + (a)^=((t)<<(n))) + +# define IP(l,r) \ + { \ + register DES_LONG tt; \ + PERM_OP(r,l,tt, 4,0x0f0f0f0fL); \ + PERM_OP(l,r,tt,16,0x0000ffffL); \ + PERM_OP(r,l,tt, 2,0x33333333L); \ + PERM_OP(l,r,tt, 8,0x00ff00ffL); \ + PERM_OP(r,l,tt, 1,0x55555555L); \ + } + +# define FP(l,r) \ + { \ + register DES_LONG tt; \ + PERM_OP(l,r,tt, 1,0x55555555L); \ + PERM_OP(r,l,tt, 8,0x00ff00ffL); \ + PERM_OP(l,r,tt, 2,0x33333333L); \ + PERM_OP(r,l,tt,16,0x0000ffffL); \ + PERM_OP(l,r,tt, 4,0x0f0f0f0fL); \ + } + +extern const DES_LONG DES_SPtrans[8][64]; + +void fcrypt_body(DES_LONG *out, DES_key_schedule *ks, + DES_LONG Eswap0, DES_LONG Eswap1); + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/des/ecb3_enc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/des/ecb3_enc.c new file mode 100644 index 000000000..6ac89d4e7 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/des/ecb3_enc.c @@ -0,0 +1,33 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "des_locl.h" + +void DES_ecb3_encrypt(const_DES_cblock *input, DES_cblock *output, + DES_key_schedule *ks1, DES_key_schedule *ks2, + DES_key_schedule *ks3, int enc) +{ + register DES_LONG l0, l1; + DES_LONG ll[2]; + const unsigned char *in = &(*input)[0]; + unsigned char *out = &(*output)[0]; + + c2l(in, l0); + c2l(in, l1); + ll[0] = l0; + ll[1] = l1; + if (enc) + DES_encrypt3(ll, ks1, ks2, ks3); + else + DES_decrypt3(ll, ks1, ks2, ks3); + l0 = ll[0]; + l1 = ll[1]; + l2c(l0, out); + l2c(l1, out); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/des/ecb_enc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/des/ecb_enc.c new file mode 100644 index 000000000..5ed079d15 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/des/ecb_enc.c @@ -0,0 +1,48 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "des_locl.h" +#include +#include + + +const char *DES_options(void) +{ + static int init = 1; + static char buf[12]; + + if (init) { + if (sizeof(DES_LONG) != sizeof(long)) + OPENSSL_strlcpy(buf, "des(int)", sizeof(buf)); + else + OPENSSL_strlcpy(buf, "des(long)", sizeof(buf)); + init = 0; + } + return buf; +} + +void DES_ecb_encrypt(const_DES_cblock *input, DES_cblock *output, + DES_key_schedule *ks, int enc) +{ + register DES_LONG l; + DES_LONG ll[2]; + const unsigned char *in = &(*input)[0]; + unsigned char *out = &(*output)[0]; + + c2l(in, l); + ll[0] = l; + c2l(in, l); + ll[1] = l; + DES_encrypt1(ll, ks, enc); + l = ll[0]; + l2c(l, out); + l = ll[1]; + l2c(l, out); + l = ll[0] = ll[1] = 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/des/fcrypt.c b/trunk/3rdparty/openssl-1.1-fit/crypto/des/fcrypt.c new file mode 100644 index 000000000..aaee4bf23 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/des/fcrypt.c @@ -0,0 +1,149 @@ +/* + * Copyright 1998-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* NOCW */ +#include +#ifdef _OSD_POSIX +# ifndef CHARSET_EBCDIC +# define CHARSET_EBCDIC 1 +# endif +#endif +#ifdef CHARSET_EBCDIC +# include +#endif + +#include +#include "des_locl.h" + +/* + * Added more values to handle illegal salt values the way normal crypt() + * implementations do. + */ +static unsigned const char con_salt[128] = { + 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, + 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, + 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, + 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, + 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, + 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0A, 0x0B, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, + 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, + 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, + 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, + 0x23, 0x24, 0x25, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, + 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, + 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, + 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, +}; + +static unsigned const char cov_2char[64] = { + 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, + 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, + 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, + 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62, + 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, + 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, + 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A +}; + +char *DES_crypt(const char *buf, const char *salt) +{ + static char buff[14]; + +#ifndef CHARSET_EBCDIC + return DES_fcrypt(buf, salt, buff); +#else + char e_salt[2 + 1]; + char e_buf[32 + 1]; /* replace 32 by 8 ? */ + char *ret; + + if (salt[0] == '\0' || salt[1] == '\0') + return NULL; + + /* Copy salt, convert to ASCII. */ + e_salt[0] = salt[0]; + e_salt[1] = salt[1]; + e_salt[2] = '\0'; + ebcdic2ascii(e_salt, e_salt, sizeof(e_salt)); + + /* Convert password to ASCII. */ + OPENSSL_strlcpy(e_buf, buf, sizeof(e_buf)); + ebcdic2ascii(e_buf, e_buf, sizeof(e_buf)); + + /* Encrypt it (from/to ASCII); if it worked, convert back. */ + ret = DES_fcrypt(e_buf, e_salt, buff); + if (ret != NULL) + ascii2ebcdic(ret, ret, strlen(ret)); + + return ret; +#endif +} + +char *DES_fcrypt(const char *buf, const char *salt, char *ret) +{ + unsigned int i, j, x, y; + DES_LONG Eswap0, Eswap1; + DES_LONG out[2], ll; + DES_cblock key; + DES_key_schedule ks; + unsigned char bb[9]; + unsigned char *b = bb; + unsigned char c, u; + + x = ret[0] = salt[0]; + if (x == 0 || x >= sizeof(con_salt)) + return NULL; + Eswap0 = con_salt[x] << 2; + x = ret[1] = salt[1]; + if (x == 0 || x >= sizeof(con_salt)) + return NULL; + Eswap1 = con_salt[x] << 6; + + /* + * EAY r=strlen(buf); r=(r+7)/8; + */ + for (i = 0; i < 8; i++) { + c = *(buf++); + if (!c) + break; + key[i] = (c << 1); + } + for (; i < 8; i++) + key[i] = 0; + + DES_set_key_unchecked(&key, &ks); + fcrypt_body(&(out[0]), &ks, Eswap0, Eswap1); + + ll = out[0]; + l2c(ll, b); + ll = out[1]; + l2c(ll, b); + y = 0; + u = 0x80; + bb[8] = 0; + for (i = 2; i < 13; i++) { + c = 0; + for (j = 0; j < 6; j++) { + c <<= 1; + if (bb[y] & u) + c |= 1; + u >>= 1; + if (!u) { + y++; + u = 0x80; + } + } + ret[i] = cov_2char[c]; + } + ret[13] = '\0'; + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/des/fcrypt_b.c b/trunk/3rdparty/openssl-1.1-fit/crypto/des/fcrypt_b.c new file mode 100644 index 000000000..fe2369a93 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/des/fcrypt_b.c @@ -0,0 +1,72 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#define DES_FCRYPT +#include "des_locl.h" +#undef DES_FCRYPT + +#undef PERM_OP +#define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\ + (b)^=(t),\ + (a)^=((t)<<(n))) + +#undef HPERM_OP +#define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\ + (a)=(a)^(t)^(t>>(16-(n))))\ + +void fcrypt_body(DES_LONG *out, DES_key_schedule *ks, DES_LONG Eswap0, + DES_LONG Eswap1) +{ + register DES_LONG l, r, t, u; + register DES_LONG *s; + register int j; + register DES_LONG E0, E1; + + l = 0; + r = 0; + + s = (DES_LONG *)ks; + E0 = Eswap0; + E1 = Eswap1; + + for (j = 0; j < 25; j++) { + D_ENCRYPT(l, r, 0); /* 1 */ + D_ENCRYPT(r, l, 2); /* 2 */ + D_ENCRYPT(l, r, 4); /* 3 */ + D_ENCRYPT(r, l, 6); /* 4 */ + D_ENCRYPT(l, r, 8); /* 5 */ + D_ENCRYPT(r, l, 10); /* 6 */ + D_ENCRYPT(l, r, 12); /* 7 */ + D_ENCRYPT(r, l, 14); /* 8 */ + D_ENCRYPT(l, r, 16); /* 9 */ + D_ENCRYPT(r, l, 18); /* 10 */ + D_ENCRYPT(l, r, 20); /* 11 */ + D_ENCRYPT(r, l, 22); /* 12 */ + D_ENCRYPT(l, r, 24); /* 13 */ + D_ENCRYPT(r, l, 26); /* 14 */ + D_ENCRYPT(l, r, 28); /* 15 */ + D_ENCRYPT(r, l, 30); /* 16 */ + t = l; + l = r; + r = t; + } + l = ROTATE(l, 3) & 0xffffffffL; + r = ROTATE(r, 3) & 0xffffffffL; + + PERM_OP(l, r, t, 1, 0x55555555L); + PERM_OP(r, l, t, 8, 0x00ff00ffL); + PERM_OP(l, r, t, 2, 0x33333333L); + PERM_OP(r, l, t, 16, 0x0000ffffL); + PERM_OP(l, r, t, 4, 0x0f0f0f0fL); + + out[0] = r; + out[1] = l; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/des/ncbc_enc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/des/ncbc_enc.c new file mode 100644 index 000000000..244f15ca2 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/des/ncbc_enc.c @@ -0,0 +1,106 @@ +/* + * Copyright 1998-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * #included by: + * cbc_enc.c (DES_cbc_encrypt) + * des_enc.c (DES_ncbc_encrypt) + */ + +#include "des_locl.h" + +#ifdef CBC_ENC_C__DONT_UPDATE_IV +void DES_cbc_encrypt(const unsigned char *in, unsigned char *out, long length, + DES_key_schedule *_schedule, DES_cblock *ivec, int enc) +#else +void DES_ncbc_encrypt(const unsigned char *in, unsigned char *out, + long length, DES_key_schedule *_schedule, + DES_cblock *ivec, int enc) +#endif +{ + register DES_LONG tin0, tin1; + register DES_LONG tout0, tout1, xor0, xor1; + register long l = length; + DES_LONG tin[2]; + unsigned char *iv; + + iv = &(*ivec)[0]; + + if (enc) { + c2l(iv, tout0); + c2l(iv, tout1); + for (l -= 8; l >= 0; l -= 8) { + c2l(in, tin0); + c2l(in, tin1); + tin0 ^= tout0; + tin[0] = tin0; + tin1 ^= tout1; + tin[1] = tin1; + DES_encrypt1((DES_LONG *)tin, _schedule, DES_ENCRYPT); + tout0 = tin[0]; + l2c(tout0, out); + tout1 = tin[1]; + l2c(tout1, out); + } + if (l != -8) { + c2ln(in, tin0, tin1, l + 8); + tin0 ^= tout0; + tin[0] = tin0; + tin1 ^= tout1; + tin[1] = tin1; + DES_encrypt1((DES_LONG *)tin, _schedule, DES_ENCRYPT); + tout0 = tin[0]; + l2c(tout0, out); + tout1 = tin[1]; + l2c(tout1, out); + } +#ifndef CBC_ENC_C__DONT_UPDATE_IV + iv = &(*ivec)[0]; + l2c(tout0, iv); + l2c(tout1, iv); +#endif + } else { + c2l(iv, xor0); + c2l(iv, xor1); + for (l -= 8; l >= 0; l -= 8) { + c2l(in, tin0); + tin[0] = tin0; + c2l(in, tin1); + tin[1] = tin1; + DES_encrypt1((DES_LONG *)tin, _schedule, DES_DECRYPT); + tout0 = tin[0] ^ xor0; + tout1 = tin[1] ^ xor1; + l2c(tout0, out); + l2c(tout1, out); + xor0 = tin0; + xor1 = tin1; + } + if (l != -8) { + c2l(in, tin0); + tin[0] = tin0; + c2l(in, tin1); + tin[1] = tin1; + DES_encrypt1((DES_LONG *)tin, _schedule, DES_DECRYPT); + tout0 = tin[0] ^ xor0; + tout1 = tin[1] ^ xor1; + l2cn(tout0, tout1, out, l + 8); +#ifndef CBC_ENC_C__DONT_UPDATE_IV + xor0 = tin0; + xor1 = tin1; +#endif + } +#ifndef CBC_ENC_C__DONT_UPDATE_IV + iv = &(*ivec)[0]; + l2c(xor0, iv); + l2c(xor1, iv); +#endif + } + tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0; + tin[0] = tin[1] = 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/des/ofb64ede.c b/trunk/3rdparty/openssl-1.1-fit/crypto/des/ofb64ede.c new file mode 100644 index 000000000..a551a07e0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/des/ofb64ede.c @@ -0,0 +1,62 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "des_locl.h" + +/* + * The input and output encrypted as though 64bit ofb mode is being used. + * The extra state information to record how much of the 64bit block we have + * used is contained in *num; + */ +void DES_ede3_ofb64_encrypt(register const unsigned char *in, + register unsigned char *out, long length, + DES_key_schedule *k1, DES_key_schedule *k2, + DES_key_schedule *k3, DES_cblock *ivec, int *num) +{ + register DES_LONG v0, v1; + register int n = *num; + register long l = length; + DES_cblock d; + register char *dp; + DES_LONG ti[2]; + unsigned char *iv; + int save = 0; + + iv = &(*ivec)[0]; + c2l(iv, v0); + c2l(iv, v1); + ti[0] = v0; + ti[1] = v1; + dp = (char *)d; + l2c(v0, dp); + l2c(v1, dp); + while (l--) { + if (n == 0) { + /* ti[0]=v0; */ + /* ti[1]=v1; */ + DES_encrypt3(ti, k1, k2, k3); + v0 = ti[0]; + v1 = ti[1]; + + dp = (char *)d; + l2c(v0, dp); + l2c(v1, dp); + save++; + } + *(out++) = *(in++) ^ d[n]; + n = (n + 1) & 0x07; + } + if (save) { + iv = &(*ivec)[0]; + l2c(v0, iv); + l2c(v1, iv); + } + v0 = v1 = ti[0] = ti[1] = 0; + *num = n; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/des/ofb64enc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/des/ofb64enc.c new file mode 100644 index 000000000..30976c871 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/des/ofb64enc.c @@ -0,0 +1,60 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "des_locl.h" + +/* + * The input and output encrypted as though 64bit ofb mode is being used. + * The extra state information to record how much of the 64bit block we have + * used is contained in *num; + */ +void DES_ofb64_encrypt(register const unsigned char *in, + register unsigned char *out, long length, + DES_key_schedule *schedule, DES_cblock *ivec, int *num) +{ + register DES_LONG v0, v1, t; + register int n = *num; + register long l = length; + DES_cblock d; + register unsigned char *dp; + DES_LONG ti[2]; + unsigned char *iv; + int save = 0; + + iv = &(*ivec)[0]; + c2l(iv, v0); + c2l(iv, v1); + ti[0] = v0; + ti[1] = v1; + dp = d; + l2c(v0, dp); + l2c(v1, dp); + while (l--) { + if (n == 0) { + DES_encrypt1(ti, schedule, DES_ENCRYPT); + dp = d; + t = ti[0]; + l2c(t, dp); + t = ti[1]; + l2c(t, dp); + save++; + } + *(out++) = *(in++) ^ d[n]; + n = (n + 1) & 0x07; + } + if (save) { + v0 = ti[0]; + v1 = ti[1]; + iv = &(*ivec)[0]; + l2c(v0, iv); + l2c(v1, iv); + } + t = v0 = v1 = ti[0] = ti[1] = 0; + *num = n; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/des/ofb_enc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/des/ofb_enc.c new file mode 100644 index 000000000..65a9b8604 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/des/ofb_enc.c @@ -0,0 +1,82 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "des_locl.h" + +/* + * The input and output are loaded in multiples of 8 bits. What this means is + * that if you have numbits=12 and length=2 the first 12 bits will be + * retrieved from the first byte and half the second. The second 12 bits + * will come from the 3rd and half the 4th byte. + */ +void DES_ofb_encrypt(const unsigned char *in, unsigned char *out, int numbits, + long length, DES_key_schedule *schedule, + DES_cblock *ivec) +{ + register DES_LONG d0, d1, vv0, vv1, v0, v1, n = (numbits + 7) / 8; + register DES_LONG mask0, mask1; + register long l = length; + register int num = numbits; + DES_LONG ti[2]; + unsigned char *iv; + + if (num > 64) + return; + if (num > 32) { + mask0 = 0xffffffffL; + if (num >= 64) + mask1 = mask0; + else + mask1 = (1L << (num - 32)) - 1; + } else { + if (num == 32) + mask0 = 0xffffffffL; + else + mask0 = (1L << num) - 1; + mask1 = 0x00000000L; + } + + iv = &(*ivec)[0]; + c2l(iv, v0); + c2l(iv, v1); + ti[0] = v0; + ti[1] = v1; + while (l-- > 0) { + ti[0] = v0; + ti[1] = v1; + DES_encrypt1((DES_LONG *)ti, schedule, DES_ENCRYPT); + vv0 = ti[0]; + vv1 = ti[1]; + c2ln(in, d0, d1, n); + in += n; + d0 = (d0 ^ vv0) & mask0; + d1 = (d1 ^ vv1) & mask1; + l2cn(d0, d1, out, n); + out += n; + + if (num == 32) { + v0 = v1; + v1 = vv0; + } else if (num == 64) { + v0 = vv0; + v1 = vv1; + } else if (num > 32) { /* && num != 64 */ + v0 = ((v1 >> (num - 32)) | (vv0 << (64 - num))) & 0xffffffffL; + v1 = ((vv0 >> (num - 32)) | (vv1 << (64 - num))) & 0xffffffffL; + } else { /* num < 32 */ + + v0 = ((v0 >> num) | (v1 << (32 - num))) & 0xffffffffL; + v1 = ((v1 >> num) | (vv0 << (32 - num))) & 0xffffffffL; + } + } + iv = &(*ivec)[0]; + l2c(v0, iv); + l2c(v1, iv); + v0 = v1 = d0 = d1 = ti[0] = ti[1] = vv0 = vv1 = 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/des/pcbc_enc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/des/pcbc_enc.c new file mode 100644 index 000000000..0fa058f03 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/des/pcbc_enc.c @@ -0,0 +1,66 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "des_locl.h" + +void DES_pcbc_encrypt(const unsigned char *input, unsigned char *output, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, int enc) +{ + register DES_LONG sin0, sin1, xor0, xor1, tout0, tout1; + DES_LONG tin[2]; + const unsigned char *in; + unsigned char *out, *iv; + + in = input; + out = output; + iv = &(*ivec)[0]; + + if (enc) { + c2l(iv, xor0); + c2l(iv, xor1); + for (; length > 0; length -= 8) { + if (length >= 8) { + c2l(in, sin0); + c2l(in, sin1); + } else + c2ln(in, sin0, sin1, length); + tin[0] = sin0 ^ xor0; + tin[1] = sin1 ^ xor1; + DES_encrypt1((DES_LONG *)tin, schedule, DES_ENCRYPT); + tout0 = tin[0]; + tout1 = tin[1]; + xor0 = sin0 ^ tout0; + xor1 = sin1 ^ tout1; + l2c(tout0, out); + l2c(tout1, out); + } + } else { + c2l(iv, xor0); + c2l(iv, xor1); + for (; length > 0; length -= 8) { + c2l(in, sin0); + c2l(in, sin1); + tin[0] = sin0; + tin[1] = sin1; + DES_encrypt1((DES_LONG *)tin, schedule, DES_DECRYPT); + tout0 = tin[0] ^ xor0; + tout1 = tin[1] ^ xor1; + if (length >= 8) { + l2c(tout0, out); + l2c(tout1, out); + } else + l2cn(tout0, tout1, out, length); + xor0 = tout0 ^ sin0; + xor1 = tout1 ^ sin1; + } + } + tin[0] = tin[1] = 0; + sin0 = sin1 = xor0 = xor1 = tout0 = tout1 = 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/des/qud_cksm.c b/trunk/3rdparty/openssl-1.1-fit/crypto/des/qud_cksm.c new file mode 100644 index 000000000..81e6be822 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/des/qud_cksm.c @@ -0,0 +1,76 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * From "Message Authentication" R.R. Jueneman, S.M. Matyas, C.H. Meyer IEEE + * Communications Magazine Sept 1985 Vol. 23 No. 9 p 29-40 This module in + * only based on the code in this paper and is almost definitely not the same + * as the MIT implementation. + */ +#include "des_locl.h" + +#define Q_B0(a) (((DES_LONG)(a))) +#define Q_B1(a) (((DES_LONG)(a))<<8) +#define Q_B2(a) (((DES_LONG)(a))<<16) +#define Q_B3(a) (((DES_LONG)(a))<<24) + +/* used to scramble things a bit */ +/* Got the value MIT uses via brute force :-) 2/10/90 eay */ +#define NOISE ((DES_LONG)83653421L) + +DES_LONG DES_quad_cksum(const unsigned char *input, DES_cblock output[], + long length, int out_count, DES_cblock *seed) +{ + DES_LONG z0, z1, t0, t1; + int i; + long l; + const unsigned char *cp; + DES_LONG *lp; + + if (out_count < 1) + out_count = 1; + lp = (DES_LONG *)&(output[0])[0]; + + z0 = Q_B0((*seed)[0]) | Q_B1((*seed)[1]) | Q_B2((*seed)[2]) | + Q_B3((*seed)[3]); + z1 = Q_B0((*seed)[4]) | Q_B1((*seed)[5]) | Q_B2((*seed)[6]) | + Q_B3((*seed)[7]); + + for (i = 0; ((i < 4) && (i < out_count)); i++) { + cp = input; + l = length; + while (l > 0) { + if (l > 1) { + t0 = (DES_LONG)(*(cp++)); + t0 |= (DES_LONG)Q_B1(*(cp++)); + l--; + } else + t0 = (DES_LONG)(*(cp++)); + l--; + /* add */ + t0 += z0; + t0 &= 0xffffffffL; + t1 = z1; + /* square, well sort of square */ + z0 = ((((t0 * t0) & 0xffffffffL) + ((t1 * t1) & 0xffffffffL)) + & 0xffffffffL) % 0x7fffffffL; + z1 = ((t0 * ((t1 + NOISE) & 0xffffffffL)) & 0xffffffffL) % + 0x7fffffffL; + } + if (lp != NULL) { + /* + * The MIT library assumes that the checksum is composed of + * 2*out_count 32 bit ints + */ + *lp++ = z0; + *lp++ = z1; + } + } + return z0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/des/rand_key.c b/trunk/3rdparty/openssl-1.1-fit/crypto/des/rand_key.c new file mode 100644 index 000000000..fe8aefec3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/des/rand_key.c @@ -0,0 +1,21 @@ +/* + * Copyright 1998-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +int DES_random_key(DES_cblock *ret) +{ + do { + if (RAND_priv_bytes((unsigned char *)ret, sizeof(DES_cblock)) != 1) + return 0; + } while (DES_is_weak_key(ret)); + DES_set_odd_parity(ret); + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/des/set_key.c b/trunk/3rdparty/openssl-1.1-fit/crypto/des/set_key.c new file mode 100644 index 000000000..adbad7236 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/des/set_key.c @@ -0,0 +1,372 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * set_key.c v 1.4 eay 24/9/91 + * 1.4 Speed up by 400% :-) + * 1.3 added register declarations. + * 1.2 unrolled make_key_sched a bit more + * 1.1 added norm_expand_bits + * 1.0 First working version + */ +#include +#include "des_locl.h" + +/* defaults to false */ +OPENSSL_IMPLEMENT_GLOBAL(int, DES_check_key, 0) + +static const unsigned char odd_parity[256] = { + 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14, + 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31, + 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47, + 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62, + 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79, + 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94, + 97, 97, 98, 98, 100, 100, 103, 103, 104, 104, 107, 107, 109, 109, 110, + 110, + 112, 112, 115, 115, 117, 117, 118, 118, 121, 121, 122, 122, 124, 124, 127, + 127, + 128, 128, 131, 131, 133, 133, 134, 134, 137, 137, 138, 138, 140, 140, 143, + 143, + 145, 145, 146, 146, 148, 148, 151, 151, 152, 152, 155, 155, 157, 157, 158, + 158, + 161, 161, 162, 162, 164, 164, 167, 167, 168, 168, 171, 171, 173, 173, 174, + 174, + 176, 176, 179, 179, 181, 181, 182, 182, 185, 185, 186, 186, 188, 188, 191, + 191, + 193, 193, 194, 194, 196, 196, 199, 199, 200, 200, 203, 203, 205, 205, 206, + 206, + 208, 208, 211, 211, 213, 213, 214, 214, 217, 217, 218, 218, 220, 220, 223, + 223, + 224, 224, 227, 227, 229, 229, 230, 230, 233, 233, 234, 234, 236, 236, 239, + 239, + 241, 241, 242, 242, 244, 244, 247, 247, 248, 248, 251, 251, 253, 253, 254, + 254 +}; + +void DES_set_odd_parity(DES_cblock *key) +{ + unsigned int i; + + for (i = 0; i < DES_KEY_SZ; i++) + (*key)[i] = odd_parity[(*key)[i]]; +} + +int DES_check_key_parity(const_DES_cblock *key) +{ + unsigned int i; + + for (i = 0; i < DES_KEY_SZ; i++) { + if ((*key)[i] != odd_parity[(*key)[i]]) + return 0; + } + return 1; +} + +/*- + * Weak and semi weak keys as taken from + * %A D.W. Davies + * %A W.L. Price + * %T Security for Computer Networks + * %I John Wiley & Sons + * %D 1984 + */ +#define NUM_WEAK_KEY 16 +static const DES_cblock weak_keys[NUM_WEAK_KEY] = { + /* weak keys */ + {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, + {0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE}, + {0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E}, + {0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1}, + /* semi-weak keys */ + {0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE}, + {0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01}, + {0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1}, + {0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E}, + {0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1}, + {0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01}, + {0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE}, + {0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E}, + {0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E}, + {0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01}, + {0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE}, + {0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1} +}; + +int DES_is_weak_key(const_DES_cblock *key) +{ + int i; + + for (i = 0; i < NUM_WEAK_KEY; i++) + if (memcmp(weak_keys[i], key, sizeof(DES_cblock)) == 0) + return 1; + return 0; +} + +/*- + * NOW DEFINED IN des_local.h + * See ecb_encrypt.c for a pseudo description of these macros. + * #define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\ + * (b)^=(t),\ + * (a)=((a)^((t)<<(n)))) + */ + +#define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\ + (a)=(a)^(t)^(t>>(16-(n)))) + +static const DES_LONG des_skb[8][64] = { + { + /* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ + 0x00000000L, 0x00000010L, 0x20000000L, 0x20000010L, + 0x00010000L, 0x00010010L, 0x20010000L, 0x20010010L, + 0x00000800L, 0x00000810L, 0x20000800L, 0x20000810L, + 0x00010800L, 0x00010810L, 0x20010800L, 0x20010810L, + 0x00000020L, 0x00000030L, 0x20000020L, 0x20000030L, + 0x00010020L, 0x00010030L, 0x20010020L, 0x20010030L, + 0x00000820L, 0x00000830L, 0x20000820L, 0x20000830L, + 0x00010820L, 0x00010830L, 0x20010820L, 0x20010830L, + 0x00080000L, 0x00080010L, 0x20080000L, 0x20080010L, + 0x00090000L, 0x00090010L, 0x20090000L, 0x20090010L, + 0x00080800L, 0x00080810L, 0x20080800L, 0x20080810L, + 0x00090800L, 0x00090810L, 0x20090800L, 0x20090810L, + 0x00080020L, 0x00080030L, 0x20080020L, 0x20080030L, + 0x00090020L, 0x00090030L, 0x20090020L, 0x20090030L, + 0x00080820L, 0x00080830L, 0x20080820L, 0x20080830L, + 0x00090820L, 0x00090830L, 0x20090820L, 0x20090830L, + }, + { + /* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */ + 0x00000000L, 0x02000000L, 0x00002000L, 0x02002000L, + 0x00200000L, 0x02200000L, 0x00202000L, 0x02202000L, + 0x00000004L, 0x02000004L, 0x00002004L, 0x02002004L, + 0x00200004L, 0x02200004L, 0x00202004L, 0x02202004L, + 0x00000400L, 0x02000400L, 0x00002400L, 0x02002400L, + 0x00200400L, 0x02200400L, 0x00202400L, 0x02202400L, + 0x00000404L, 0x02000404L, 0x00002404L, 0x02002404L, + 0x00200404L, 0x02200404L, 0x00202404L, 0x02202404L, + 0x10000000L, 0x12000000L, 0x10002000L, 0x12002000L, + 0x10200000L, 0x12200000L, 0x10202000L, 0x12202000L, + 0x10000004L, 0x12000004L, 0x10002004L, 0x12002004L, + 0x10200004L, 0x12200004L, 0x10202004L, 0x12202004L, + 0x10000400L, 0x12000400L, 0x10002400L, 0x12002400L, + 0x10200400L, 0x12200400L, 0x10202400L, 0x12202400L, + 0x10000404L, 0x12000404L, 0x10002404L, 0x12002404L, + 0x10200404L, 0x12200404L, 0x10202404L, 0x12202404L, + }, + { + /* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */ + 0x00000000L, 0x00000001L, 0x00040000L, 0x00040001L, + 0x01000000L, 0x01000001L, 0x01040000L, 0x01040001L, + 0x00000002L, 0x00000003L, 0x00040002L, 0x00040003L, + 0x01000002L, 0x01000003L, 0x01040002L, 0x01040003L, + 0x00000200L, 0x00000201L, 0x00040200L, 0x00040201L, + 0x01000200L, 0x01000201L, 0x01040200L, 0x01040201L, + 0x00000202L, 0x00000203L, 0x00040202L, 0x00040203L, + 0x01000202L, 0x01000203L, 0x01040202L, 0x01040203L, + 0x08000000L, 0x08000001L, 0x08040000L, 0x08040001L, + 0x09000000L, 0x09000001L, 0x09040000L, 0x09040001L, + 0x08000002L, 0x08000003L, 0x08040002L, 0x08040003L, + 0x09000002L, 0x09000003L, 0x09040002L, 0x09040003L, + 0x08000200L, 0x08000201L, 0x08040200L, 0x08040201L, + 0x09000200L, 0x09000201L, 0x09040200L, 0x09040201L, + 0x08000202L, 0x08000203L, 0x08040202L, 0x08040203L, + 0x09000202L, 0x09000203L, 0x09040202L, 0x09040203L, + }, + { + /* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */ + 0x00000000L, 0x00100000L, 0x00000100L, 0x00100100L, + 0x00000008L, 0x00100008L, 0x00000108L, 0x00100108L, + 0x00001000L, 0x00101000L, 0x00001100L, 0x00101100L, + 0x00001008L, 0x00101008L, 0x00001108L, 0x00101108L, + 0x04000000L, 0x04100000L, 0x04000100L, 0x04100100L, + 0x04000008L, 0x04100008L, 0x04000108L, 0x04100108L, + 0x04001000L, 0x04101000L, 0x04001100L, 0x04101100L, + 0x04001008L, 0x04101008L, 0x04001108L, 0x04101108L, + 0x00020000L, 0x00120000L, 0x00020100L, 0x00120100L, + 0x00020008L, 0x00120008L, 0x00020108L, 0x00120108L, + 0x00021000L, 0x00121000L, 0x00021100L, 0x00121100L, + 0x00021008L, 0x00121008L, 0x00021108L, 0x00121108L, + 0x04020000L, 0x04120000L, 0x04020100L, 0x04120100L, + 0x04020008L, 0x04120008L, 0x04020108L, 0x04120108L, + 0x04021000L, 0x04121000L, 0x04021100L, 0x04121100L, + 0x04021008L, 0x04121008L, 0x04021108L, 0x04121108L, + }, + { + /* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ + 0x00000000L, 0x10000000L, 0x00010000L, 0x10010000L, + 0x00000004L, 0x10000004L, 0x00010004L, 0x10010004L, + 0x20000000L, 0x30000000L, 0x20010000L, 0x30010000L, + 0x20000004L, 0x30000004L, 0x20010004L, 0x30010004L, + 0x00100000L, 0x10100000L, 0x00110000L, 0x10110000L, + 0x00100004L, 0x10100004L, 0x00110004L, 0x10110004L, + 0x20100000L, 0x30100000L, 0x20110000L, 0x30110000L, + 0x20100004L, 0x30100004L, 0x20110004L, 0x30110004L, + 0x00001000L, 0x10001000L, 0x00011000L, 0x10011000L, + 0x00001004L, 0x10001004L, 0x00011004L, 0x10011004L, + 0x20001000L, 0x30001000L, 0x20011000L, 0x30011000L, + 0x20001004L, 0x30001004L, 0x20011004L, 0x30011004L, + 0x00101000L, 0x10101000L, 0x00111000L, 0x10111000L, + 0x00101004L, 0x10101004L, 0x00111004L, 0x10111004L, + 0x20101000L, 0x30101000L, 0x20111000L, 0x30111000L, + 0x20101004L, 0x30101004L, 0x20111004L, 0x30111004L, + }, + { + /* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */ + 0x00000000L, 0x08000000L, 0x00000008L, 0x08000008L, + 0x00000400L, 0x08000400L, 0x00000408L, 0x08000408L, + 0x00020000L, 0x08020000L, 0x00020008L, 0x08020008L, + 0x00020400L, 0x08020400L, 0x00020408L, 0x08020408L, + 0x00000001L, 0x08000001L, 0x00000009L, 0x08000009L, + 0x00000401L, 0x08000401L, 0x00000409L, 0x08000409L, + 0x00020001L, 0x08020001L, 0x00020009L, 0x08020009L, + 0x00020401L, 0x08020401L, 0x00020409L, 0x08020409L, + 0x02000000L, 0x0A000000L, 0x02000008L, 0x0A000008L, + 0x02000400L, 0x0A000400L, 0x02000408L, 0x0A000408L, + 0x02020000L, 0x0A020000L, 0x02020008L, 0x0A020008L, + 0x02020400L, 0x0A020400L, 0x02020408L, 0x0A020408L, + 0x02000001L, 0x0A000001L, 0x02000009L, 0x0A000009L, + 0x02000401L, 0x0A000401L, 0x02000409L, 0x0A000409L, + 0x02020001L, 0x0A020001L, 0x02020009L, 0x0A020009L, + 0x02020401L, 0x0A020401L, 0x02020409L, 0x0A020409L, + }, + { + /* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */ + 0x00000000L, 0x00000100L, 0x00080000L, 0x00080100L, + 0x01000000L, 0x01000100L, 0x01080000L, 0x01080100L, + 0x00000010L, 0x00000110L, 0x00080010L, 0x00080110L, + 0x01000010L, 0x01000110L, 0x01080010L, 0x01080110L, + 0x00200000L, 0x00200100L, 0x00280000L, 0x00280100L, + 0x01200000L, 0x01200100L, 0x01280000L, 0x01280100L, + 0x00200010L, 0x00200110L, 0x00280010L, 0x00280110L, + 0x01200010L, 0x01200110L, 0x01280010L, 0x01280110L, + 0x00000200L, 0x00000300L, 0x00080200L, 0x00080300L, + 0x01000200L, 0x01000300L, 0x01080200L, 0x01080300L, + 0x00000210L, 0x00000310L, 0x00080210L, 0x00080310L, + 0x01000210L, 0x01000310L, 0x01080210L, 0x01080310L, + 0x00200200L, 0x00200300L, 0x00280200L, 0x00280300L, + 0x01200200L, 0x01200300L, 0x01280200L, 0x01280300L, + 0x00200210L, 0x00200310L, 0x00280210L, 0x00280310L, + 0x01200210L, 0x01200310L, 0x01280210L, 0x01280310L, + }, + { + /* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */ + 0x00000000L, 0x04000000L, 0x00040000L, 0x04040000L, + 0x00000002L, 0x04000002L, 0x00040002L, 0x04040002L, + 0x00002000L, 0x04002000L, 0x00042000L, 0x04042000L, + 0x00002002L, 0x04002002L, 0x00042002L, 0x04042002L, + 0x00000020L, 0x04000020L, 0x00040020L, 0x04040020L, + 0x00000022L, 0x04000022L, 0x00040022L, 0x04040022L, + 0x00002020L, 0x04002020L, 0x00042020L, 0x04042020L, + 0x00002022L, 0x04002022L, 0x00042022L, 0x04042022L, + 0x00000800L, 0x04000800L, 0x00040800L, 0x04040800L, + 0x00000802L, 0x04000802L, 0x00040802L, 0x04040802L, + 0x00002800L, 0x04002800L, 0x00042800L, 0x04042800L, + 0x00002802L, 0x04002802L, 0x00042802L, 0x04042802L, + 0x00000820L, 0x04000820L, 0x00040820L, 0x04040820L, + 0x00000822L, 0x04000822L, 0x00040822L, 0x04040822L, + 0x00002820L, 0x04002820L, 0x00042820L, 0x04042820L, + 0x00002822L, 0x04002822L, 0x00042822L, 0x04042822L, + } +}; + +int DES_set_key(const_DES_cblock *key, DES_key_schedule *schedule) +{ + if (DES_check_key) { + return DES_set_key_checked(key, schedule); + } else { + DES_set_key_unchecked(key, schedule); + return 0; + } +} + +/*- + * return 0 if key parity is odd (correct), + * return -1 if key parity error, + * return -2 if illegal weak key. + */ +int DES_set_key_checked(const_DES_cblock *key, DES_key_schedule *schedule) +{ + if (!DES_check_key_parity(key)) + return -1; + if (DES_is_weak_key(key)) + return -2; + DES_set_key_unchecked(key, schedule); + return 0; +} + +void DES_set_key_unchecked(const_DES_cblock *key, DES_key_schedule *schedule) +{ + static const int shifts2[16] = + { 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0 }; + register DES_LONG c, d, t, s, t2; + register const unsigned char *in; + register DES_LONG *k; + register int i; + +#ifdef OPENBSD_DEV_CRYPTO + memcpy(schedule->key, key, sizeof(schedule->key)); + schedule->session = NULL; +#endif + k = &schedule->ks->deslong[0]; + in = &(*key)[0]; + + c2l(in, c); + c2l(in, d); + + /* + * do PC1 in 47 simple operations. Thanks to John Fletcher + * for the inspiration. + */ + PERM_OP(d, c, t, 4, 0x0f0f0f0fL); + HPERM_OP(c, t, -2, 0xcccc0000L); + HPERM_OP(d, t, -2, 0xcccc0000L); + PERM_OP(d, c, t, 1, 0x55555555L); + PERM_OP(c, d, t, 8, 0x00ff00ffL); + PERM_OP(d, c, t, 1, 0x55555555L); + d = (((d & 0x000000ffL) << 16L) | (d & 0x0000ff00L) | + ((d & 0x00ff0000L) >> 16L) | ((c & 0xf0000000L) >> 4L)); + c &= 0x0fffffffL; + + for (i = 0; i < ITERATIONS; i++) { + if (shifts2[i]) { + c = ((c >> 2L) | (c << 26L)); + d = ((d >> 2L) | (d << 26L)); + } else { + c = ((c >> 1L) | (c << 27L)); + d = ((d >> 1L) | (d << 27L)); + } + c &= 0x0fffffffL; + d &= 0x0fffffffL; + /* + * could be a few less shifts but I am to lazy at this point in time + * to investigate + */ + s = des_skb[0][(c) & 0x3f] | + des_skb[1][((c >> 6L) & 0x03) | ((c >> 7L) & 0x3c)] | + des_skb[2][((c >> 13L) & 0x0f) | ((c >> 14L) & 0x30)] | + des_skb[3][((c >> 20L) & 0x01) | ((c >> 21L) & 0x06) | + ((c >> 22L) & 0x38)]; + t = des_skb[4][(d) & 0x3f] | + des_skb[5][((d >> 7L) & 0x03) | ((d >> 8L) & 0x3c)] | + des_skb[6][(d >> 15L) & 0x3f] | + des_skb[7][((d >> 21L) & 0x0f) | ((d >> 22L) & 0x30)]; + + /* table contained 0213 4657 */ + t2 = ((t << 16L) | (s & 0x0000ffffL)) & 0xffffffffL; + *(k++) = ROTATE(t2, 30) & 0xffffffffL; + + t2 = ((s >> 16L) | (t & 0xffff0000L)); + *(k++) = ROTATE(t2, 26) & 0xffffffffL; + } +} + +int DES_key_sched(const_DES_cblock *key, DES_key_schedule *schedule) +{ + return DES_set_key(key, schedule); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/des/spr.h b/trunk/3rdparty/openssl-1.1-fit/crypto/des/spr.h new file mode 100644 index 000000000..2404e092d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/des/spr.h @@ -0,0 +1,163 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +const DES_LONG DES_SPtrans[8][64] = { + { + /* nibble 0 */ + 0x02080800L, 0x00080000L, 0x02000002L, 0x02080802L, + 0x02000000L, 0x00080802L, 0x00080002L, 0x02000002L, + 0x00080802L, 0x02080800L, 0x02080000L, 0x00000802L, + 0x02000802L, 0x02000000L, 0x00000000L, 0x00080002L, + 0x00080000L, 0x00000002L, 0x02000800L, 0x00080800L, + 0x02080802L, 0x02080000L, 0x00000802L, 0x02000800L, + 0x00000002L, 0x00000800L, 0x00080800L, 0x02080002L, + 0x00000800L, 0x02000802L, 0x02080002L, 0x00000000L, + 0x00000000L, 0x02080802L, 0x02000800L, 0x00080002L, + 0x02080800L, 0x00080000L, 0x00000802L, 0x02000800L, + 0x02080002L, 0x00000800L, 0x00080800L, 0x02000002L, + 0x00080802L, 0x00000002L, 0x02000002L, 0x02080000L, + 0x02080802L, 0x00080800L, 0x02080000L, 0x02000802L, + 0x02000000L, 0x00000802L, 0x00080002L, 0x00000000L, + 0x00080000L, 0x02000000L, 0x02000802L, 0x02080800L, + 0x00000002L, 0x02080002L, 0x00000800L, 0x00080802L, + }, + { + /* nibble 1 */ + 0x40108010L, 0x00000000L, 0x00108000L, 0x40100000L, + 0x40000010L, 0x00008010L, 0x40008000L, 0x00108000L, + 0x00008000L, 0x40100010L, 0x00000010L, 0x40008000L, + 0x00100010L, 0x40108000L, 0x40100000L, 0x00000010L, + 0x00100000L, 0x40008010L, 0x40100010L, 0x00008000L, + 0x00108010L, 0x40000000L, 0x00000000L, 0x00100010L, + 0x40008010L, 0x00108010L, 0x40108000L, 0x40000010L, + 0x40000000L, 0x00100000L, 0x00008010L, 0x40108010L, + 0x00100010L, 0x40108000L, 0x40008000L, 0x00108010L, + 0x40108010L, 0x00100010L, 0x40000010L, 0x00000000L, + 0x40000000L, 0x00008010L, 0x00100000L, 0x40100010L, + 0x00008000L, 0x40000000L, 0x00108010L, 0x40008010L, + 0x40108000L, 0x00008000L, 0x00000000L, 0x40000010L, + 0x00000010L, 0x40108010L, 0x00108000L, 0x40100000L, + 0x40100010L, 0x00100000L, 0x00008010L, 0x40008000L, + 0x40008010L, 0x00000010L, 0x40100000L, 0x00108000L, + }, + { + /* nibble 2 */ + 0x04000001L, 0x04040100L, 0x00000100L, 0x04000101L, + 0x00040001L, 0x04000000L, 0x04000101L, 0x00040100L, + 0x04000100L, 0x00040000L, 0x04040000L, 0x00000001L, + 0x04040101L, 0x00000101L, 0x00000001L, 0x04040001L, + 0x00000000L, 0x00040001L, 0x04040100L, 0x00000100L, + 0x00000101L, 0x04040101L, 0x00040000L, 0x04000001L, + 0x04040001L, 0x04000100L, 0x00040101L, 0x04040000L, + 0x00040100L, 0x00000000L, 0x04000000L, 0x00040101L, + 0x04040100L, 0x00000100L, 0x00000001L, 0x00040000L, + 0x00000101L, 0x00040001L, 0x04040000L, 0x04000101L, + 0x00000000L, 0x04040100L, 0x00040100L, 0x04040001L, + 0x00040001L, 0x04000000L, 0x04040101L, 0x00000001L, + 0x00040101L, 0x04000001L, 0x04000000L, 0x04040101L, + 0x00040000L, 0x04000100L, 0x04000101L, 0x00040100L, + 0x04000100L, 0x00000000L, 0x04040001L, 0x00000101L, + 0x04000001L, 0x00040101L, 0x00000100L, 0x04040000L, + }, + { + /* nibble 3 */ + 0x00401008L, 0x10001000L, 0x00000008L, 0x10401008L, + 0x00000000L, 0x10400000L, 0x10001008L, 0x00400008L, + 0x10401000L, 0x10000008L, 0x10000000L, 0x00001008L, + 0x10000008L, 0x00401008L, 0x00400000L, 0x10000000L, + 0x10400008L, 0x00401000L, 0x00001000L, 0x00000008L, + 0x00401000L, 0x10001008L, 0x10400000L, 0x00001000L, + 0x00001008L, 0x00000000L, 0x00400008L, 0x10401000L, + 0x10001000L, 0x10400008L, 0x10401008L, 0x00400000L, + 0x10400008L, 0x00001008L, 0x00400000L, 0x10000008L, + 0x00401000L, 0x10001000L, 0x00000008L, 0x10400000L, + 0x10001008L, 0x00000000L, 0x00001000L, 0x00400008L, + 0x00000000L, 0x10400008L, 0x10401000L, 0x00001000L, + 0x10000000L, 0x10401008L, 0x00401008L, 0x00400000L, + 0x10401008L, 0x00000008L, 0x10001000L, 0x00401008L, + 0x00400008L, 0x00401000L, 0x10400000L, 0x10001008L, + 0x00001008L, 0x10000000L, 0x10000008L, 0x10401000L, + }, + { + /* nibble 4 */ + 0x08000000L, 0x00010000L, 0x00000400L, 0x08010420L, + 0x08010020L, 0x08000400L, 0x00010420L, 0x08010000L, + 0x00010000L, 0x00000020L, 0x08000020L, 0x00010400L, + 0x08000420L, 0x08010020L, 0x08010400L, 0x00000000L, + 0x00010400L, 0x08000000L, 0x00010020L, 0x00000420L, + 0x08000400L, 0x00010420L, 0x00000000L, 0x08000020L, + 0x00000020L, 0x08000420L, 0x08010420L, 0x00010020L, + 0x08010000L, 0x00000400L, 0x00000420L, 0x08010400L, + 0x08010400L, 0x08000420L, 0x00010020L, 0x08010000L, + 0x00010000L, 0x00000020L, 0x08000020L, 0x08000400L, + 0x08000000L, 0x00010400L, 0x08010420L, 0x00000000L, + 0x00010420L, 0x08000000L, 0x00000400L, 0x00010020L, + 0x08000420L, 0x00000400L, 0x00000000L, 0x08010420L, + 0x08010020L, 0x08010400L, 0x00000420L, 0x00010000L, + 0x00010400L, 0x08010020L, 0x08000400L, 0x00000420L, + 0x00000020L, 0x00010420L, 0x08010000L, 0x08000020L, + }, + { + /* nibble 5 */ + 0x80000040L, 0x00200040L, 0x00000000L, 0x80202000L, + 0x00200040L, 0x00002000L, 0x80002040L, 0x00200000L, + 0x00002040L, 0x80202040L, 0x00202000L, 0x80000000L, + 0x80002000L, 0x80000040L, 0x80200000L, 0x00202040L, + 0x00200000L, 0x80002040L, 0x80200040L, 0x00000000L, + 0x00002000L, 0x00000040L, 0x80202000L, 0x80200040L, + 0x80202040L, 0x80200000L, 0x80000000L, 0x00002040L, + 0x00000040L, 0x00202000L, 0x00202040L, 0x80002000L, + 0x00002040L, 0x80000000L, 0x80002000L, 0x00202040L, + 0x80202000L, 0x00200040L, 0x00000000L, 0x80002000L, + 0x80000000L, 0x00002000L, 0x80200040L, 0x00200000L, + 0x00200040L, 0x80202040L, 0x00202000L, 0x00000040L, + 0x80202040L, 0x00202000L, 0x00200000L, 0x80002040L, + 0x80000040L, 0x80200000L, 0x00202040L, 0x00000000L, + 0x00002000L, 0x80000040L, 0x80002040L, 0x80202000L, + 0x80200000L, 0x00002040L, 0x00000040L, 0x80200040L, + }, + { + /* nibble 6 */ + 0x00004000L, 0x00000200L, 0x01000200L, 0x01000004L, + 0x01004204L, 0x00004004L, 0x00004200L, 0x00000000L, + 0x01000000L, 0x01000204L, 0x00000204L, 0x01004000L, + 0x00000004L, 0x01004200L, 0x01004000L, 0x00000204L, + 0x01000204L, 0x00004000L, 0x00004004L, 0x01004204L, + 0x00000000L, 0x01000200L, 0x01000004L, 0x00004200L, + 0x01004004L, 0x00004204L, 0x01004200L, 0x00000004L, + 0x00004204L, 0x01004004L, 0x00000200L, 0x01000000L, + 0x00004204L, 0x01004000L, 0x01004004L, 0x00000204L, + 0x00004000L, 0x00000200L, 0x01000000L, 0x01004004L, + 0x01000204L, 0x00004204L, 0x00004200L, 0x00000000L, + 0x00000200L, 0x01000004L, 0x00000004L, 0x01000200L, + 0x00000000L, 0x01000204L, 0x01000200L, 0x00004200L, + 0x00000204L, 0x00004000L, 0x01004204L, 0x01000000L, + 0x01004200L, 0x00000004L, 0x00004004L, 0x01004204L, + 0x01000004L, 0x01004200L, 0x01004000L, 0x00004004L, + }, + { + /* nibble 7 */ + 0x20800080L, 0x20820000L, 0x00020080L, 0x00000000L, + 0x20020000L, 0x00800080L, 0x20800000L, 0x20820080L, + 0x00000080L, 0x20000000L, 0x00820000L, 0x00020080L, + 0x00820080L, 0x20020080L, 0x20000080L, 0x20800000L, + 0x00020000L, 0x00820080L, 0x00800080L, 0x20020000L, + 0x20820080L, 0x20000080L, 0x00000000L, 0x00820000L, + 0x20000000L, 0x00800000L, 0x20020080L, 0x20800080L, + 0x00800000L, 0x00020000L, 0x20820000L, 0x00000080L, + 0x00800000L, 0x00020000L, 0x20000080L, 0x20820080L, + 0x00020080L, 0x20000000L, 0x00000000L, 0x00820000L, + 0x20800080L, 0x20020080L, 0x20020000L, 0x00800080L, + 0x20820000L, 0x00000080L, 0x00800080L, 0x20020000L, + 0x20820080L, 0x00800000L, 0x20800000L, 0x20000080L, + 0x00820000L, 0x00020080L, 0x20020080L, 0x20800000L, + 0x00000080L, 0x20820000L, 0x00820080L, 0x00000000L, + 0x20000000L, 0x20800080L, 0x00020000L, 0x00820080L, + } +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/des/str2key.c b/trunk/3rdparty/openssl-1.1-fit/crypto/des/str2key.c new file mode 100644 index 000000000..e18d72652 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/des/str2key.c @@ -0,0 +1,77 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "des_locl.h" + +void DES_string_to_key(const char *str, DES_cblock *key) +{ + DES_key_schedule ks; + int i, length; + + memset(key, 0, 8); + length = strlen(str); + for (i = 0; i < length; i++) { + register unsigned char j = str[i]; + + if ((i % 16) < 8) + (*key)[i % 8] ^= (j << 1); + else { + /* Reverse the bit order 05/05/92 eay */ + j = ((j << 4) & 0xf0) | ((j >> 4) & 0x0f); + j = ((j << 2) & 0xcc) | ((j >> 2) & 0x33); + j = ((j << 1) & 0xaa) | ((j >> 1) & 0x55); + (*key)[7 - (i % 8)] ^= j; + } + } + DES_set_odd_parity(key); + DES_set_key_unchecked(key, &ks); + DES_cbc_cksum((const unsigned char *)str, key, length, &ks, key); + OPENSSL_cleanse(&ks, sizeof(ks)); + DES_set_odd_parity(key); +} + +void DES_string_to_2keys(const char *str, DES_cblock *key1, DES_cblock *key2) +{ + DES_key_schedule ks; + int i, length; + + memset(key1, 0, 8); + memset(key2, 0, 8); + length = strlen(str); + for (i = 0; i < length; i++) { + register unsigned char j = str[i]; + + if ((i % 32) < 16) { + if ((i % 16) < 8) + (*key1)[i % 8] ^= (j << 1); + else + (*key2)[i % 8] ^= (j << 1); + } else { + j = ((j << 4) & 0xf0) | ((j >> 4) & 0x0f); + j = ((j << 2) & 0xcc) | ((j >> 2) & 0x33); + j = ((j << 1) & 0xaa) | ((j >> 1) & 0x55); + if ((i % 16) < 8) + (*key1)[7 - (i % 8)] ^= j; + else + (*key2)[7 - (i % 8)] ^= j; + } + } + if (length <= 8) + memcpy(key2, key1, 8); + DES_set_odd_parity(key1); + DES_set_odd_parity(key2); + DES_set_key_unchecked(key1, &ks); + DES_cbc_cksum((const unsigned char *)str, key1, length, &ks, key1); + DES_set_key_unchecked(key2, &ks); + DES_cbc_cksum((const unsigned char *)str, key2, length, &ks, key2); + OPENSSL_cleanse(&ks, sizeof(ks)); + DES_set_odd_parity(key1); + DES_set_odd_parity(key2); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/des/xcbc_enc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/des/xcbc_enc.c new file mode 100644 index 000000000..c4e455d9b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/des/xcbc_enc.c @@ -0,0 +1,103 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "des_locl.h" + +/* RSA's DESX */ + +void DES_xcbc_encrypt(const unsigned char *in, unsigned char *out, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, const_DES_cblock *inw, + const_DES_cblock *outw, int enc) +{ + register DES_LONG tin0, tin1; + register DES_LONG tout0, tout1, xor0, xor1; + register DES_LONG inW0, inW1, outW0, outW1; + register const unsigned char *in2; + register long l = length; + DES_LONG tin[2]; + unsigned char *iv; + + in2 = &(*inw)[0]; + c2l(in2, inW0); + c2l(in2, inW1); + in2 = &(*outw)[0]; + c2l(in2, outW0); + c2l(in2, outW1); + + iv = &(*ivec)[0]; + + if (enc) { + c2l(iv, tout0); + c2l(iv, tout1); + for (l -= 8; l >= 0; l -= 8) { + c2l(in, tin0); + c2l(in, tin1); + tin0 ^= tout0 ^ inW0; + tin[0] = tin0; + tin1 ^= tout1 ^ inW1; + tin[1] = tin1; + DES_encrypt1(tin, schedule, DES_ENCRYPT); + tout0 = tin[0] ^ outW0; + l2c(tout0, out); + tout1 = tin[1] ^ outW1; + l2c(tout1, out); + } + if (l != -8) { + c2ln(in, tin0, tin1, l + 8); + tin0 ^= tout0 ^ inW0; + tin[0] = tin0; + tin1 ^= tout1 ^ inW1; + tin[1] = tin1; + DES_encrypt1(tin, schedule, DES_ENCRYPT); + tout0 = tin[0] ^ outW0; + l2c(tout0, out); + tout1 = tin[1] ^ outW1; + l2c(tout1, out); + } + iv = &(*ivec)[0]; + l2c(tout0, iv); + l2c(tout1, iv); + } else { + c2l(iv, xor0); + c2l(iv, xor1); + for (l -= 8; l > 0; l -= 8) { + c2l(in, tin0); + tin[0] = tin0 ^ outW0; + c2l(in, tin1); + tin[1] = tin1 ^ outW1; + DES_encrypt1(tin, schedule, DES_DECRYPT); + tout0 = tin[0] ^ xor0 ^ inW0; + tout1 = tin[1] ^ xor1 ^ inW1; + l2c(tout0, out); + l2c(tout1, out); + xor0 = tin0; + xor1 = tin1; + } + if (l != -8) { + c2l(in, tin0); + tin[0] = tin0 ^ outW0; + c2l(in, tin1); + tin[1] = tin1 ^ outW1; + DES_encrypt1(tin, schedule, DES_DECRYPT); + tout0 = tin[0] ^ xor0 ^ inW0; + tout1 = tin[1] ^ xor1 ^ inW1; + l2cn(tout0, tout1, out, l + 8); + xor0 = tin0; + xor1 = tin1; + } + + iv = &(*ivec)[0]; + l2c(xor0, iv); + l2c(xor1, iv); + } + tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0; + inW0 = inW1 = outW0 = outW1 = 0; + tin[0] = tin[1] = 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dh/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/build.info new file mode 100644 index 000000000..b19ff6dba --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/build.info @@ -0,0 +1,5 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + dh_asn1.c dh_gen.c dh_key.c dh_lib.c dh_check.c dh_err.c dh_depr.c \ + dh_ameth.c dh_pmeth.c dh_prn.c dh_rfc5114.c dh_kdf.c dh_meth.c \ + dh_rfc7919.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh1024.pem b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh1024.pem new file mode 100644 index 000000000..81d43f6a3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh1024.pem @@ -0,0 +1,5 @@ +-----BEGIN DH PARAMETERS----- +MIGHAoGBAJf2QmHKtQXdKCjhPx1ottPb0PMTBH9A6FbaWMsTuKG/K3g6TG1Z1fkq +/Gz/PWk/eLI9TzFgqVAuPvr3q14a1aZeVUMTgo2oO5/y2UHe6VaJ+trqCTat3xlx +/mNbIK9HA2RgPC3gWfVLZQrY+gz3ASHHR5nXWHEyvpuZm7m3h+irAgEC +-----END DH PARAMETERS----- diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh192.pem b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh192.pem new file mode 100644 index 000000000..521c07271 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh192.pem @@ -0,0 +1,3 @@ +-----BEGIN DH PARAMETERS----- +MB4CGQDUoLoCULb9LsYm5+/WN992xxbiLQlEuIsCAQM= +-----END DH PARAMETERS----- diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh2048.pem b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh2048.pem new file mode 100644 index 000000000..295460f50 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh2048.pem @@ -0,0 +1,16 @@ +-----BEGIN DH PARAMETERS----- +MIIBCAKCAQEA7ZKJNYJFVcs7+6J2WmkEYb8h86tT0s0h2v94GRFS8Q7B4lW9aG9o +AFO5Imov5Jo0H2XMWTKKvbHbSe3fpxJmw/0hBHAY8H/W91hRGXKCeyKpNBgdL8sh +z22SrkO2qCnHJ6PLAMXy5fsKpFmFor2tRfCzrfnggTXu2YOzzK7q62bmqVdmufEo +pT8igNcLpvZxk5uBDvhakObMym9mX3rAEBoe8PwttggMYiiw7NuJKO4MqD1llGkW +aVM8U2ATsCun1IKHrRxynkE1/MJ86VHeYYX8GZt2YA8z+GuzylIOKcMH6JAWzMwA +Gbatw6QwizOhr9iMjZ0B26TE3X8LvW84wwIBAg== +-----END DH PARAMETERS----- +-----BEGIN DH PARAMETERS----- +MIIBCAKCAQEArtA3w73zP6Lu3EOQtwogiXt3AXXpuS6yD4BhzNS1pZFyPHk0/an5 +8ydEkPhQZHKDW+BZJxxPLANaTudWo2YT8TgtvUdN6KSgMiEi6McwqDw+SADuvW+F +SKUYFxG6VFIxyEP6xBdf+vhJxEDbRG2EYsHDRRtJ76gp9cSKTHusf2R+4AAVGqnt +gRAbNqtcOar/7FSj+Pl8G3v0Bty0LcCSpbqgYlnv6z+rErQmmC6PPvSz97TDMCok +yKpCE9hFA1zkqK3TH4FmFvGeIaXJUIBZf4mArWuBTjWFW3nmhESRUn1VK3K3x42N +a5k6c2+EhrMFiLjxuH6JZoqL0/E93FF9SwIBAg== +-----END DH PARAMETERS----- diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh4096.pem b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh4096.pem new file mode 100644 index 000000000..390943a21 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh4096.pem @@ -0,0 +1,14 @@ +-----BEGIN DH PARAMETERS----- +MIICCAKCAgEA/urRnb6vkPYc/KEGXWnbCIOaKitq7ySIq9dTH7s+Ri59zs77zty7 +vfVlSe6VFTBWgYjD2XKUFmtqq6CqXMhVX5ElUDoYDpAyTH85xqNFLzFC7nKrff/H +TFKNttp22cZE9V0IPpzedPfnQkE7aUdmF9JnDyv21Z/818O93u1B4r0szdnmEvEF +bKuIxEHX+bp0ZR7RqE1AeifXGJX3d6tsd2PMAObxwwsv55RGkn50vHO4QxtTARr1 +rRUV5j3B3oPMgC7Offxx+98Xn45B1/G0Prp11anDsR1PGwtaCYipqsvMwQUSJtyE +EOQWk+yFkeMe4vWv367eEi0Sd/wnC+TSXBE3pYvpYerJ8n1MceI5GQTdarJ77OW9 +bGTHmxRsLSCM1jpLdPja5jjb4siAa6EHc4qN9c/iFKS3PQPJEnX7pXKBRs5f7AF3 +W3RIGt+G9IVNZfXaS7Z/iCpgzgvKCs0VeqN38QsJGtC1aIkwOeyjPNy2G6jJ4yqH +ovXYt/0mc00vCWeSNS1wren0pR2EiLxX0ypjjgsU1mk/Z3b/+zVf7fZSIB+nDLjb +NPtUlJCVGnAeBK1J1nG3TQicqowOXoM6ISkdaXj5GPJdXHab2+S7cqhKGv5qC7rR +jT6sx7RUr0CNTxzLI7muV2/a4tGmj0PSdXQdsZ7tw7gbXlaWT1+MM2MCAQI= +-----END DH PARAMETERS----- + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh512.pem b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh512.pem new file mode 100644 index 000000000..0a4d863eb --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh512.pem @@ -0,0 +1,4 @@ +-----BEGIN DH PARAMETERS----- +MEYCQQDaWDwW2YUiidDkr3VvTMqS3UvlM7gE+w/tlO+cikQD7VdGUNNpmdsp13Yn +a6LT1BLiGPTdHghM9tgAPnxHdOgzAgEC +-----END DH PARAMETERS----- diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_ameth.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_ameth.c new file mode 100644 index 000000000..05a1d4227 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_ameth.c @@ -0,0 +1,907 @@ +/* + * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include "dh_locl.h" +#include +#include "internal/asn1_int.h" +#include "internal/evp_int.h" +#include + +/* + * i2d/d2i like DH parameter functions which use the appropriate routine for + * PKCS#3 DH or X9.42 DH. + */ + +static DH *d2i_dhp(const EVP_PKEY *pkey, const unsigned char **pp, + long length) +{ + if (pkey->ameth == &dhx_asn1_meth) + return d2i_DHxparams(NULL, pp, length); + return d2i_DHparams(NULL, pp, length); +} + +static int i2d_dhp(const EVP_PKEY *pkey, const DH *a, unsigned char **pp) +{ + if (pkey->ameth == &dhx_asn1_meth) + return i2d_DHxparams(a, pp); + return i2d_DHparams(a, pp); +} + +static void int_dh_free(EVP_PKEY *pkey) +{ + DH_free(pkey->pkey.dh); +} + +static int dh_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) +{ + const unsigned char *p, *pm; + int pklen, pmlen; + int ptype; + const void *pval; + const ASN1_STRING *pstr; + X509_ALGOR *palg; + ASN1_INTEGER *public_key = NULL; + + DH *dh = NULL; + + if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey)) + return 0; + X509_ALGOR_get0(NULL, &ptype, &pval, palg); + + if (ptype != V_ASN1_SEQUENCE) { + DHerr(DH_F_DH_PUB_DECODE, DH_R_PARAMETER_ENCODING_ERROR); + goto err; + } + + pstr = pval; + pm = pstr->data; + pmlen = pstr->length; + + if ((dh = d2i_dhp(pkey, &pm, pmlen)) == NULL) { + DHerr(DH_F_DH_PUB_DECODE, DH_R_DECODE_ERROR); + goto err; + } + + if ((public_key = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL) { + DHerr(DH_F_DH_PUB_DECODE, DH_R_DECODE_ERROR); + goto err; + } + + /* We have parameters now set public key */ + if ((dh->pub_key = ASN1_INTEGER_to_BN(public_key, NULL)) == NULL) { + DHerr(DH_F_DH_PUB_DECODE, DH_R_BN_DECODE_ERROR); + goto err; + } + + ASN1_INTEGER_free(public_key); + EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, dh); + return 1; + + err: + ASN1_INTEGER_free(public_key); + DH_free(dh); + return 0; + +} + +static int dh_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) +{ + DH *dh; + int ptype; + unsigned char *penc = NULL; + int penclen; + ASN1_STRING *str; + ASN1_INTEGER *pub_key = NULL; + + dh = pkey->pkey.dh; + + str = ASN1_STRING_new(); + if (str == NULL) { + DHerr(DH_F_DH_PUB_ENCODE, ERR_R_MALLOC_FAILURE); + goto err; + } + str->length = i2d_dhp(pkey, dh, &str->data); + if (str->length <= 0) { + DHerr(DH_F_DH_PUB_ENCODE, ERR_R_MALLOC_FAILURE); + goto err; + } + ptype = V_ASN1_SEQUENCE; + + pub_key = BN_to_ASN1_INTEGER(dh->pub_key, NULL); + if (!pub_key) + goto err; + + penclen = i2d_ASN1_INTEGER(pub_key, &penc); + + ASN1_INTEGER_free(pub_key); + + if (penclen <= 0) { + DHerr(DH_F_DH_PUB_ENCODE, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(pkey->ameth->pkey_id), + ptype, str, penc, penclen)) + return 1; + + err: + OPENSSL_free(penc); + ASN1_STRING_free(str); + + return 0; +} + +/* + * PKCS#8 DH is defined in PKCS#11 of all places. It is similar to DH in that + * the AlgorithmIdentifier contains the parameters, the private key is + * explicitly included and the pubkey must be recalculated. + */ + +static int dh_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8) +{ + const unsigned char *p, *pm; + int pklen, pmlen; + int ptype; + const void *pval; + const ASN1_STRING *pstr; + const X509_ALGOR *palg; + ASN1_INTEGER *privkey = NULL; + + DH *dh = NULL; + + if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8)) + return 0; + + X509_ALGOR_get0(NULL, &ptype, &pval, palg); + + if (ptype != V_ASN1_SEQUENCE) + goto decerr; + if ((privkey = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL) + goto decerr; + + pstr = pval; + pm = pstr->data; + pmlen = pstr->length; + if ((dh = d2i_dhp(pkey, &pm, pmlen)) == NULL) + goto decerr; + + /* We have parameters now set private key */ + if ((dh->priv_key = BN_secure_new()) == NULL + || !ASN1_INTEGER_to_BN(privkey, dh->priv_key)) { + DHerr(DH_F_DH_PRIV_DECODE, DH_R_BN_ERROR); + goto dherr; + } + /* Calculate public key */ + if (!DH_generate_key(dh)) + goto dherr; + + EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, dh); + + ASN1_STRING_clear_free(privkey); + + return 1; + + decerr: + DHerr(DH_F_DH_PRIV_DECODE, EVP_R_DECODE_ERROR); + dherr: + DH_free(dh); + ASN1_STRING_clear_free(privkey); + return 0; +} + +static int dh_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) +{ + ASN1_STRING *params = NULL; + ASN1_INTEGER *prkey = NULL; + unsigned char *dp = NULL; + int dplen; + + params = ASN1_STRING_new(); + + if (params == NULL) { + DHerr(DH_F_DH_PRIV_ENCODE, ERR_R_MALLOC_FAILURE); + goto err; + } + + params->length = i2d_dhp(pkey, pkey->pkey.dh, ¶ms->data); + if (params->length <= 0) { + DHerr(DH_F_DH_PRIV_ENCODE, ERR_R_MALLOC_FAILURE); + goto err; + } + params->type = V_ASN1_SEQUENCE; + + /* Get private key into integer */ + prkey = BN_to_ASN1_INTEGER(pkey->pkey.dh->priv_key, NULL); + + if (!prkey) { + DHerr(DH_F_DH_PRIV_ENCODE, DH_R_BN_ERROR); + goto err; + } + + dplen = i2d_ASN1_INTEGER(prkey, &dp); + + ASN1_STRING_clear_free(prkey); + prkey = NULL; + + if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(pkey->ameth->pkey_id), 0, + V_ASN1_SEQUENCE, params, dp, dplen)) + goto err; + + return 1; + + err: + OPENSSL_free(dp); + ASN1_STRING_free(params); + ASN1_STRING_clear_free(prkey); + return 0; +} + +static int dh_param_decode(EVP_PKEY *pkey, + const unsigned char **pder, int derlen) +{ + DH *dh; + + if ((dh = d2i_dhp(pkey, pder, derlen)) == NULL) { + DHerr(DH_F_DH_PARAM_DECODE, ERR_R_DH_LIB); + return 0; + } + EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, dh); + return 1; +} + +static int dh_param_encode(const EVP_PKEY *pkey, unsigned char **pder) +{ + return i2d_dhp(pkey, pkey->pkey.dh, pder); +} + +static int do_dh_print(BIO *bp, const DH *x, int indent, int ptype) +{ + int reason = ERR_R_BUF_LIB; + const char *ktype = NULL; + BIGNUM *priv_key, *pub_key; + + if (ptype == 2) + priv_key = x->priv_key; + else + priv_key = NULL; + + if (ptype > 0) + pub_key = x->pub_key; + else + pub_key = NULL; + + if (x->p == NULL || (ptype == 2 && priv_key == NULL) + || (ptype > 0 && pub_key == NULL)) { + reason = ERR_R_PASSED_NULL_PARAMETER; + goto err; + } + + if (ptype == 2) + ktype = "DH Private-Key"; + else if (ptype == 1) + ktype = "DH Public-Key"; + else + ktype = "DH Parameters"; + + BIO_indent(bp, indent, 128); + if (BIO_printf(bp, "%s: (%d bit)\n", ktype, BN_num_bits(x->p)) <= 0) + goto err; + indent += 4; + + if (!ASN1_bn_print(bp, "private-key:", priv_key, NULL, indent)) + goto err; + if (!ASN1_bn_print(bp, "public-key:", pub_key, NULL, indent)) + goto err; + + if (!ASN1_bn_print(bp, "prime:", x->p, NULL, indent)) + goto err; + if (!ASN1_bn_print(bp, "generator:", x->g, NULL, indent)) + goto err; + if (x->q && !ASN1_bn_print(bp, "subgroup order:", x->q, NULL, indent)) + goto err; + if (x->j && !ASN1_bn_print(bp, "subgroup factor:", x->j, NULL, indent)) + goto err; + if (x->seed) { + int i; + BIO_indent(bp, indent, 128); + BIO_puts(bp, "seed:"); + for (i = 0; i < x->seedlen; i++) { + if ((i % 15) == 0) { + if (BIO_puts(bp, "\n") <= 0 + || !BIO_indent(bp, indent + 4, 128)) + goto err; + } + if (BIO_printf(bp, "%02x%s", x->seed[i], + ((i + 1) == x->seedlen) ? "" : ":") <= 0) + goto err; + } + if (BIO_write(bp, "\n", 1) <= 0) + return 0; + } + if (x->counter && !ASN1_bn_print(bp, "counter:", x->counter, NULL, indent)) + goto err; + if (x->length != 0) { + BIO_indent(bp, indent, 128); + if (BIO_printf(bp, "recommended-private-length: %d bits\n", + (int)x->length) <= 0) + goto err; + } + + return 1; + + err: + DHerr(DH_F_DO_DH_PRINT, reason); + return 0; +} + +static int int_dh_size(const EVP_PKEY *pkey) +{ + return DH_size(pkey->pkey.dh); +} + +static int dh_bits(const EVP_PKEY *pkey) +{ + return BN_num_bits(pkey->pkey.dh->p); +} + +static int dh_security_bits(const EVP_PKEY *pkey) +{ + return DH_security_bits(pkey->pkey.dh); +} + +static int dh_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) +{ + if (BN_cmp(a->pkey.dh->p, b->pkey.dh->p) || + BN_cmp(a->pkey.dh->g, b->pkey.dh->g)) + return 0; + else if (a->ameth == &dhx_asn1_meth) { + if (BN_cmp(a->pkey.dh->q, b->pkey.dh->q)) + return 0; + } + return 1; +} + +static int int_dh_bn_cpy(BIGNUM **dst, const BIGNUM *src) +{ + BIGNUM *a; + + /* + * If source is read only just copy the pointer, so + * we don't have to reallocate it. + */ + if (src == NULL) + a = NULL; + else if (BN_get_flags(src, BN_FLG_STATIC_DATA) + && !BN_get_flags(src, BN_FLG_MALLOCED)) + a = (BIGNUM *)src; + else if ((a = BN_dup(src)) == NULL) + return 0; + BN_clear_free(*dst); + *dst = a; + return 1; +} + +static int int_dh_param_copy(DH *to, const DH *from, int is_x942) +{ + if (is_x942 == -1) + is_x942 = ! !from->q; + if (!int_dh_bn_cpy(&to->p, from->p)) + return 0; + if (!int_dh_bn_cpy(&to->g, from->g)) + return 0; + if (is_x942) { + if (!int_dh_bn_cpy(&to->q, from->q)) + return 0; + if (!int_dh_bn_cpy(&to->j, from->j)) + return 0; + OPENSSL_free(to->seed); + to->seed = NULL; + to->seedlen = 0; + if (from->seed) { + to->seed = OPENSSL_memdup(from->seed, from->seedlen); + if (!to->seed) + return 0; + to->seedlen = from->seedlen; + } + } else + to->length = from->length; + return 1; +} + +DH *DHparams_dup(DH *dh) +{ + DH *ret; + ret = DH_new(); + if (ret == NULL) + return NULL; + if (!int_dh_param_copy(ret, dh, -1)) { + DH_free(ret); + return NULL; + } + return ret; +} + +static int dh_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) +{ + if (to->pkey.dh == NULL) { + to->pkey.dh = DH_new(); + if (to->pkey.dh == NULL) + return 0; + } + return int_dh_param_copy(to->pkey.dh, from->pkey.dh, + from->ameth == &dhx_asn1_meth); +} + +static int dh_missing_parameters(const EVP_PKEY *a) +{ + if (a->pkey.dh == NULL || a->pkey.dh->p == NULL || a->pkey.dh->g == NULL) + return 1; + return 0; +} + +static int dh_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) +{ + if (dh_cmp_parameters(a, b) == 0) + return 0; + if (BN_cmp(b->pkey.dh->pub_key, a->pkey.dh->pub_key) != 0) + return 0; + else + return 1; +} + +static int dh_param_print(BIO *bp, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *ctx) +{ + return do_dh_print(bp, pkey->pkey.dh, indent, 0); +} + +static int dh_public_print(BIO *bp, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *ctx) +{ + return do_dh_print(bp, pkey->pkey.dh, indent, 1); +} + +static int dh_private_print(BIO *bp, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *ctx) +{ + return do_dh_print(bp, pkey->pkey.dh, indent, 2); +} + +int DHparams_print(BIO *bp, const DH *x) +{ + return do_dh_print(bp, x, 4, 0); +} + +#ifndef OPENSSL_NO_CMS +static int dh_cms_decrypt(CMS_RecipientInfo *ri); +static int dh_cms_encrypt(CMS_RecipientInfo *ri); +#endif + +static int dh_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) +{ + switch (op) { +#ifndef OPENSSL_NO_CMS + + case ASN1_PKEY_CTRL_CMS_ENVELOPE: + if (arg1 == 1) + return dh_cms_decrypt(arg2); + else if (arg1 == 0) + return dh_cms_encrypt(arg2); + return -2; + + case ASN1_PKEY_CTRL_CMS_RI_TYPE: + *(int *)arg2 = CMS_RECIPINFO_AGREE; + return 1; +#endif + default: + return -2; + } + +} + +static int dh_pkey_public_check(const EVP_PKEY *pkey) +{ + DH *dh = pkey->pkey.dh; + + if (dh->pub_key == NULL) { + DHerr(DH_F_DH_PKEY_PUBLIC_CHECK, DH_R_MISSING_PUBKEY); + return 0; + } + + return DH_check_pub_key_ex(dh, dh->pub_key); +} + +static int dh_pkey_param_check(const EVP_PKEY *pkey) +{ + DH *dh = pkey->pkey.dh; + + return DH_check_ex(dh); +} + +const EVP_PKEY_ASN1_METHOD dh_asn1_meth = { + EVP_PKEY_DH, + EVP_PKEY_DH, + 0, + + "DH", + "OpenSSL PKCS#3 DH method", + + dh_pub_decode, + dh_pub_encode, + dh_pub_cmp, + dh_public_print, + + dh_priv_decode, + dh_priv_encode, + dh_private_print, + + int_dh_size, + dh_bits, + dh_security_bits, + + dh_param_decode, + dh_param_encode, + dh_missing_parameters, + dh_copy_parameters, + dh_cmp_parameters, + dh_param_print, + 0, + + int_dh_free, + 0, + + 0, 0, 0, 0, 0, + + 0, + dh_pkey_public_check, + dh_pkey_param_check +}; + +const EVP_PKEY_ASN1_METHOD dhx_asn1_meth = { + EVP_PKEY_DHX, + EVP_PKEY_DHX, + 0, + + "X9.42 DH", + "OpenSSL X9.42 DH method", + + dh_pub_decode, + dh_pub_encode, + dh_pub_cmp, + dh_public_print, + + dh_priv_decode, + dh_priv_encode, + dh_private_print, + + int_dh_size, + dh_bits, + dh_security_bits, + + dh_param_decode, + dh_param_encode, + dh_missing_parameters, + dh_copy_parameters, + dh_cmp_parameters, + dh_param_print, + 0, + + int_dh_free, + dh_pkey_ctrl, + + 0, 0, 0, 0, 0, + + 0, + dh_pkey_public_check, + dh_pkey_param_check +}; + +#ifndef OPENSSL_NO_CMS + +static int dh_cms_set_peerkey(EVP_PKEY_CTX *pctx, + X509_ALGOR *alg, ASN1_BIT_STRING *pubkey) +{ + const ASN1_OBJECT *aoid; + int atype; + const void *aval; + ASN1_INTEGER *public_key = NULL; + int rv = 0; + EVP_PKEY *pkpeer = NULL, *pk = NULL; + DH *dhpeer = NULL; + const unsigned char *p; + int plen; + + X509_ALGOR_get0(&aoid, &atype, &aval, alg); + if (OBJ_obj2nid(aoid) != NID_dhpublicnumber) + goto err; + /* Only absent parameters allowed in RFC XXXX */ + if (atype != V_ASN1_UNDEF && atype == V_ASN1_NULL) + goto err; + + pk = EVP_PKEY_CTX_get0_pkey(pctx); + if (!pk) + goto err; + if (pk->type != EVP_PKEY_DHX) + goto err; + /* Get parameters from parent key */ + dhpeer = DHparams_dup(pk->pkey.dh); + /* We have parameters now set public key */ + plen = ASN1_STRING_length(pubkey); + p = ASN1_STRING_get0_data(pubkey); + if (!p || !plen) + goto err; + + if ((public_key = d2i_ASN1_INTEGER(NULL, &p, plen)) == NULL) { + DHerr(DH_F_DH_CMS_SET_PEERKEY, DH_R_DECODE_ERROR); + goto err; + } + + /* We have parameters now set public key */ + if ((dhpeer->pub_key = ASN1_INTEGER_to_BN(public_key, NULL)) == NULL) { + DHerr(DH_F_DH_CMS_SET_PEERKEY, DH_R_BN_DECODE_ERROR); + goto err; + } + + pkpeer = EVP_PKEY_new(); + if (pkpeer == NULL) + goto err; + EVP_PKEY_assign(pkpeer, pk->ameth->pkey_id, dhpeer); + dhpeer = NULL; + if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0) + rv = 1; + err: + ASN1_INTEGER_free(public_key); + EVP_PKEY_free(pkpeer); + DH_free(dhpeer); + return rv; +} + +static int dh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri) +{ + int rv = 0; + + X509_ALGOR *alg, *kekalg = NULL; + ASN1_OCTET_STRING *ukm; + const unsigned char *p; + unsigned char *dukm = NULL; + size_t dukmlen = 0; + int keylen, plen; + const EVP_CIPHER *kekcipher; + EVP_CIPHER_CTX *kekctx; + + if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm)) + goto err; + + /* + * For DH we only have one OID permissible. If ever any more get defined + * we will need something cleverer. + */ + if (OBJ_obj2nid(alg->algorithm) != NID_id_smime_alg_ESDH) { + DHerr(DH_F_DH_CMS_SET_SHARED_INFO, DH_R_KDF_PARAMETER_ERROR); + goto err; + } + + if (EVP_PKEY_CTX_set_dh_kdf_type(pctx, EVP_PKEY_DH_KDF_X9_42) <= 0) + goto err; + + if (EVP_PKEY_CTX_set_dh_kdf_md(pctx, EVP_sha1()) <= 0) + goto err; + + if (alg->parameter->type != V_ASN1_SEQUENCE) + goto err; + + p = alg->parameter->value.sequence->data; + plen = alg->parameter->value.sequence->length; + kekalg = d2i_X509_ALGOR(NULL, &p, plen); + if (!kekalg) + goto err; + kekctx = CMS_RecipientInfo_kari_get0_ctx(ri); + if (!kekctx) + goto err; + kekcipher = EVP_get_cipherbyobj(kekalg->algorithm); + if (!kekcipher || EVP_CIPHER_mode(kekcipher) != EVP_CIPH_WRAP_MODE) + goto err; + if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL)) + goto err; + if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0) + goto err; + + keylen = EVP_CIPHER_CTX_key_length(kekctx); + if (EVP_PKEY_CTX_set_dh_kdf_outlen(pctx, keylen) <= 0) + goto err; + /* Use OBJ_nid2obj to ensure we use built in OID that isn't freed */ + if (EVP_PKEY_CTX_set0_dh_kdf_oid(pctx, + OBJ_nid2obj(EVP_CIPHER_type(kekcipher))) + <= 0) + goto err; + + if (ukm) { + dukmlen = ASN1_STRING_length(ukm); + dukm = OPENSSL_memdup(ASN1_STRING_get0_data(ukm), dukmlen); + if (!dukm) + goto err; + } + + if (EVP_PKEY_CTX_set0_dh_kdf_ukm(pctx, dukm, dukmlen) <= 0) + goto err; + dukm = NULL; + + rv = 1; + err: + X509_ALGOR_free(kekalg); + OPENSSL_free(dukm); + return rv; +} + +static int dh_cms_decrypt(CMS_RecipientInfo *ri) +{ + EVP_PKEY_CTX *pctx; + pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); + if (!pctx) + return 0; + /* See if we need to set peer key */ + if (!EVP_PKEY_CTX_get0_peerkey(pctx)) { + X509_ALGOR *alg; + ASN1_BIT_STRING *pubkey; + if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &alg, &pubkey, + NULL, NULL, NULL)) + return 0; + if (!alg || !pubkey) + return 0; + if (!dh_cms_set_peerkey(pctx, alg, pubkey)) { + DHerr(DH_F_DH_CMS_DECRYPT, DH_R_PEER_KEY_ERROR); + return 0; + } + } + /* Set DH derivation parameters and initialise unwrap context */ + if (!dh_cms_set_shared_info(pctx, ri)) { + DHerr(DH_F_DH_CMS_DECRYPT, DH_R_SHARED_INFO_ERROR); + return 0; + } + return 1; +} + +static int dh_cms_encrypt(CMS_RecipientInfo *ri) +{ + EVP_PKEY_CTX *pctx; + EVP_PKEY *pkey; + EVP_CIPHER_CTX *ctx; + int keylen; + X509_ALGOR *talg, *wrap_alg = NULL; + const ASN1_OBJECT *aoid; + ASN1_BIT_STRING *pubkey; + ASN1_STRING *wrap_str; + ASN1_OCTET_STRING *ukm; + unsigned char *penc = NULL, *dukm = NULL; + int penclen; + size_t dukmlen = 0; + int rv = 0; + int kdf_type, wrap_nid; + const EVP_MD *kdf_md; + pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); + if (!pctx) + return 0; + /* Get ephemeral key */ + pkey = EVP_PKEY_CTX_get0_pkey(pctx); + if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey, + NULL, NULL, NULL)) + goto err; + X509_ALGOR_get0(&aoid, NULL, NULL, talg); + /* Is everything uninitialised? */ + if (aoid == OBJ_nid2obj(NID_undef)) { + ASN1_INTEGER *pubk = BN_to_ASN1_INTEGER(pkey->pkey.dh->pub_key, NULL); + if (!pubk) + goto err; + /* Set the key */ + + penclen = i2d_ASN1_INTEGER(pubk, &penc); + ASN1_INTEGER_free(pubk); + if (penclen <= 0) + goto err; + ASN1_STRING_set0(pubkey, penc, penclen); + pubkey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + pubkey->flags |= ASN1_STRING_FLAG_BITS_LEFT; + + penc = NULL; + X509_ALGOR_set0(talg, OBJ_nid2obj(NID_dhpublicnumber), + V_ASN1_UNDEF, NULL); + } + + /* See if custom parameters set */ + kdf_type = EVP_PKEY_CTX_get_dh_kdf_type(pctx); + if (kdf_type <= 0) + goto err; + if (!EVP_PKEY_CTX_get_dh_kdf_md(pctx, &kdf_md)) + goto err; + + if (kdf_type == EVP_PKEY_DH_KDF_NONE) { + kdf_type = EVP_PKEY_DH_KDF_X9_42; + if (EVP_PKEY_CTX_set_dh_kdf_type(pctx, kdf_type) <= 0) + goto err; + } else if (kdf_type != EVP_PKEY_DH_KDF_X9_42) + /* Unknown KDF */ + goto err; + if (kdf_md == NULL) { + /* Only SHA1 supported */ + kdf_md = EVP_sha1(); + if (EVP_PKEY_CTX_set_dh_kdf_md(pctx, kdf_md) <= 0) + goto err; + } else if (EVP_MD_type(kdf_md) != NID_sha1) + /* Unsupported digest */ + goto err; + + if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm)) + goto err; + + /* Get wrap NID */ + ctx = CMS_RecipientInfo_kari_get0_ctx(ri); + wrap_nid = EVP_CIPHER_CTX_type(ctx); + if (EVP_PKEY_CTX_set0_dh_kdf_oid(pctx, OBJ_nid2obj(wrap_nid)) <= 0) + goto err; + keylen = EVP_CIPHER_CTX_key_length(ctx); + + /* Package wrap algorithm in an AlgorithmIdentifier */ + + wrap_alg = X509_ALGOR_new(); + if (wrap_alg == NULL) + goto err; + wrap_alg->algorithm = OBJ_nid2obj(wrap_nid); + wrap_alg->parameter = ASN1_TYPE_new(); + if (wrap_alg->parameter == NULL) + goto err; + if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0) + goto err; + if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef) { + ASN1_TYPE_free(wrap_alg->parameter); + wrap_alg->parameter = NULL; + } + + if (EVP_PKEY_CTX_set_dh_kdf_outlen(pctx, keylen) <= 0) + goto err; + + if (ukm) { + dukmlen = ASN1_STRING_length(ukm); + dukm = OPENSSL_memdup(ASN1_STRING_get0_data(ukm), dukmlen); + if (!dukm) + goto err; + } + + if (EVP_PKEY_CTX_set0_dh_kdf_ukm(pctx, dukm, dukmlen) <= 0) + goto err; + dukm = NULL; + + /* + * Now need to wrap encoding of wrap AlgorithmIdentifier into parameter + * of another AlgorithmIdentifier. + */ + penc = NULL; + penclen = i2d_X509_ALGOR(wrap_alg, &penc); + if (!penc || !penclen) + goto err; + wrap_str = ASN1_STRING_new(); + if (wrap_str == NULL) + goto err; + ASN1_STRING_set0(wrap_str, penc, penclen); + penc = NULL; + X509_ALGOR_set0(talg, OBJ_nid2obj(NID_id_smime_alg_ESDH), + V_ASN1_SEQUENCE, wrap_str); + + rv = 1; + + err: + OPENSSL_free(penc); + X509_ALGOR_free(wrap_alg); + return rv; +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_asn1.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_asn1.c new file mode 100644 index 000000000..1a40633b4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_asn1.c @@ -0,0 +1,138 @@ +/* + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include "dh_locl.h" +#include +#include + +/* Override the default free and new methods */ +static int dh_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + if (operation == ASN1_OP_NEW_PRE) { + *pval = (ASN1_VALUE *)DH_new(); + if (*pval != NULL) + return 2; + return 0; + } else if (operation == ASN1_OP_FREE_PRE) { + DH_free((DH *)*pval); + *pval = NULL; + return 2; + } + return 1; +} + +ASN1_SEQUENCE_cb(DHparams, dh_cb) = { + ASN1_SIMPLE(DH, p, BIGNUM), + ASN1_SIMPLE(DH, g, BIGNUM), + ASN1_OPT_EMBED(DH, length, ZINT32), +} ASN1_SEQUENCE_END_cb(DH, DHparams) + +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DH, DHparams, DHparams) + +/* + * Internal only structures for handling X9.42 DH: this gets translated to or + * from a DH structure straight away. + */ + +typedef struct { + ASN1_BIT_STRING *seed; + BIGNUM *counter; +} int_dhvparams; + +typedef struct { + BIGNUM *p; + BIGNUM *q; + BIGNUM *g; + BIGNUM *j; + int_dhvparams *vparams; +} int_dhx942_dh; + +ASN1_SEQUENCE(DHvparams) = { + ASN1_SIMPLE(int_dhvparams, seed, ASN1_BIT_STRING), + ASN1_SIMPLE(int_dhvparams, counter, BIGNUM) +} static_ASN1_SEQUENCE_END_name(int_dhvparams, DHvparams) + +ASN1_SEQUENCE(DHxparams) = { + ASN1_SIMPLE(int_dhx942_dh, p, BIGNUM), + ASN1_SIMPLE(int_dhx942_dh, g, BIGNUM), + ASN1_SIMPLE(int_dhx942_dh, q, BIGNUM), + ASN1_OPT(int_dhx942_dh, j, BIGNUM), + ASN1_OPT(int_dhx942_dh, vparams, DHvparams), +} static_ASN1_SEQUENCE_END_name(int_dhx942_dh, DHxparams) + +int_dhx942_dh *d2i_int_dhx(int_dhx942_dh **a, + const unsigned char **pp, long length); +int i2d_int_dhx(const int_dhx942_dh *a, unsigned char **pp); + +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(int_dhx942_dh, DHxparams, int_dhx) + +/* Application public function: read in X9.42 DH parameters into DH structure */ + +DH *d2i_DHxparams(DH **a, const unsigned char **pp, long length) +{ + int_dhx942_dh *dhx = NULL; + DH *dh = NULL; + dh = DH_new(); + if (dh == NULL) + return NULL; + dhx = d2i_int_dhx(NULL, pp, length); + if (dhx == NULL) { + DH_free(dh); + return NULL; + } + + if (a) { + DH_free(*a); + *a = dh; + } + + dh->p = dhx->p; + dh->q = dhx->q; + dh->g = dhx->g; + dh->j = dhx->j; + + if (dhx->vparams) { + dh->seed = dhx->vparams->seed->data; + dh->seedlen = dhx->vparams->seed->length; + dh->counter = dhx->vparams->counter; + dhx->vparams->seed->data = NULL; + ASN1_BIT_STRING_free(dhx->vparams->seed); + OPENSSL_free(dhx->vparams); + dhx->vparams = NULL; + } + + OPENSSL_free(dhx); + return dh; +} + +int i2d_DHxparams(const DH *dh, unsigned char **pp) +{ + int_dhx942_dh dhx; + int_dhvparams dhv; + ASN1_BIT_STRING bs; + dhx.p = dh->p; + dhx.g = dh->g; + dhx.q = dh->q; + dhx.j = dh->j; + if (dh->counter && dh->seed && dh->seedlen > 0) { + bs.flags = ASN1_STRING_FLAG_BITS_LEFT; + bs.data = dh->seed; + bs.length = dh->seedlen; + dhv.seed = &bs; + dhv.counter = dh->counter; + dhx.vparams = &dhv; + } else + dhx.vparams = NULL; + + return i2d_int_dhx(&dhx, pp); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_check.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_check.c new file mode 100644 index 000000000..fc4557710 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_check.c @@ -0,0 +1,233 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include "dh_locl.h" + +/*- + * Check that p and g are suitable enough + * + * p is odd + * 1 < g < p - 1 + */ +int DH_check_params_ex(const DH *dh) +{ + int errflags = 0; + + (void)DH_check_params(dh, &errflags); + + if ((errflags & DH_CHECK_P_NOT_PRIME) != 0) + DHerr(DH_F_DH_CHECK_PARAMS_EX, DH_R_CHECK_P_NOT_PRIME); + if ((errflags & DH_NOT_SUITABLE_GENERATOR) != 0) + DHerr(DH_F_DH_CHECK_PARAMS_EX, DH_R_NOT_SUITABLE_GENERATOR); + + return errflags == 0; +} + +int DH_check_params(const DH *dh, int *ret) +{ + int ok = 0; + BIGNUM *tmp = NULL; + BN_CTX *ctx = NULL; + + *ret = 0; + ctx = BN_CTX_new(); + if (ctx == NULL) + goto err; + BN_CTX_start(ctx); + tmp = BN_CTX_get(ctx); + if (tmp == NULL) + goto err; + + if (!BN_is_odd(dh->p)) + *ret |= DH_CHECK_P_NOT_PRIME; + if (BN_is_negative(dh->g) || BN_is_zero(dh->g) || BN_is_one(dh->g)) + *ret |= DH_NOT_SUITABLE_GENERATOR; + if (BN_copy(tmp, dh->p) == NULL || !BN_sub_word(tmp, 1)) + goto err; + if (BN_cmp(dh->g, tmp) >= 0) + *ret |= DH_NOT_SUITABLE_GENERATOR; + + ok = 1; + err: + if (ctx != NULL) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + return ok; +} + +/*- + * Check that p is a safe prime and + * if g is 2, 3 or 5, check that it is a suitable generator + * where + * for 2, p mod 24 == 11 + * for 3, p mod 12 == 5 + * for 5, p mod 10 == 3 or 7 + * should hold. + */ +int DH_check_ex(const DH *dh) +{ + int errflags = 0; + + (void)DH_check(dh, &errflags); + + if ((errflags & DH_NOT_SUITABLE_GENERATOR) != 0) + DHerr(DH_F_DH_CHECK_EX, DH_R_NOT_SUITABLE_GENERATOR); + if ((errflags & DH_CHECK_Q_NOT_PRIME) != 0) + DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_Q_NOT_PRIME); + if ((errflags & DH_CHECK_INVALID_Q_VALUE) != 0) + DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_INVALID_Q_VALUE); + if ((errflags & DH_CHECK_INVALID_J_VALUE) != 0) + DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_INVALID_J_VALUE); + if ((errflags & DH_UNABLE_TO_CHECK_GENERATOR) != 0) + DHerr(DH_F_DH_CHECK_EX, DH_R_UNABLE_TO_CHECK_GENERATOR); + if ((errflags & DH_CHECK_P_NOT_PRIME) != 0) + DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_P_NOT_PRIME); + if ((errflags & DH_CHECK_P_NOT_SAFE_PRIME) != 0) + DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_P_NOT_SAFE_PRIME); + + return errflags == 0; +} + +int DH_check(const DH *dh, int *ret) +{ + int ok = 0, r; + BN_CTX *ctx = NULL; + BN_ULONG l; + BIGNUM *t1 = NULL, *t2 = NULL; + + *ret = 0; + ctx = BN_CTX_new(); + if (ctx == NULL) + goto err; + BN_CTX_start(ctx); + t1 = BN_CTX_get(ctx); + t2 = BN_CTX_get(ctx); + if (t2 == NULL) + goto err; + + if (dh->q) { + if (BN_cmp(dh->g, BN_value_one()) <= 0) + *ret |= DH_NOT_SUITABLE_GENERATOR; + else if (BN_cmp(dh->g, dh->p) >= 0) + *ret |= DH_NOT_SUITABLE_GENERATOR; + else { + /* Check g^q == 1 mod p */ + if (!BN_mod_exp(t1, dh->g, dh->q, dh->p, ctx)) + goto err; + if (!BN_is_one(t1)) + *ret |= DH_NOT_SUITABLE_GENERATOR; + } + r = BN_is_prime_ex(dh->q, BN_prime_checks, ctx, NULL); + if (r < 0) + goto err; + if (!r) + *ret |= DH_CHECK_Q_NOT_PRIME; + /* Check p == 1 mod q i.e. q divides p - 1 */ + if (!BN_div(t1, t2, dh->p, dh->q, ctx)) + goto err; + if (!BN_is_one(t2)) + *ret |= DH_CHECK_INVALID_Q_VALUE; + if (dh->j && BN_cmp(dh->j, t1)) + *ret |= DH_CHECK_INVALID_J_VALUE; + + } else if (BN_is_word(dh->g, DH_GENERATOR_2)) { + l = BN_mod_word(dh->p, 24); + if (l == (BN_ULONG)-1) + goto err; + if (l != 11) + *ret |= DH_NOT_SUITABLE_GENERATOR; + } else if (BN_is_word(dh->g, DH_GENERATOR_5)) { + l = BN_mod_word(dh->p, 10); + if (l == (BN_ULONG)-1) + goto err; + if ((l != 3) && (l != 7)) + *ret |= DH_NOT_SUITABLE_GENERATOR; + } else + *ret |= DH_UNABLE_TO_CHECK_GENERATOR; + + r = BN_is_prime_ex(dh->p, BN_prime_checks, ctx, NULL); + if (r < 0) + goto err; + if (!r) + *ret |= DH_CHECK_P_NOT_PRIME; + else if (!dh->q) { + if (!BN_rshift1(t1, dh->p)) + goto err; + r = BN_is_prime_ex(t1, BN_prime_checks, ctx, NULL); + if (r < 0) + goto err; + if (!r) + *ret |= DH_CHECK_P_NOT_SAFE_PRIME; + } + ok = 1; + err: + if (ctx != NULL) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + return ok; +} + +int DH_check_pub_key_ex(const DH *dh, const BIGNUM *pub_key) +{ + int errflags = 0; + + (void)DH_check(dh, &errflags); + + if ((errflags & DH_CHECK_PUBKEY_TOO_SMALL) != 0) + DHerr(DH_F_DH_CHECK_PUB_KEY_EX, DH_R_CHECK_PUBKEY_TOO_SMALL); + if ((errflags & DH_CHECK_PUBKEY_TOO_LARGE) != 0) + DHerr(DH_F_DH_CHECK_PUB_KEY_EX, DH_R_CHECK_PUBKEY_TOO_LARGE); + if ((errflags & DH_CHECK_PUBKEY_INVALID) != 0) + DHerr(DH_F_DH_CHECK_PUB_KEY_EX, DH_R_CHECK_PUBKEY_INVALID); + + return errflags == 0; +} + +int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret) +{ + int ok = 0; + BIGNUM *tmp = NULL; + BN_CTX *ctx = NULL; + + *ret = 0; + ctx = BN_CTX_new(); + if (ctx == NULL) + goto err; + BN_CTX_start(ctx); + tmp = BN_CTX_get(ctx); + if (tmp == NULL || !BN_set_word(tmp, 1)) + goto err; + if (BN_cmp(pub_key, tmp) <= 0) + *ret |= DH_CHECK_PUBKEY_TOO_SMALL; + if (BN_copy(tmp, dh->p) == NULL || !BN_sub_word(tmp, 1)) + goto err; + if (BN_cmp(pub_key, tmp) >= 0) + *ret |= DH_CHECK_PUBKEY_TOO_LARGE; + + if (dh->q != NULL) { + /* Check pub_key^q == 1 mod p */ + if (!BN_mod_exp(tmp, pub_key, dh->q, dh->p, ctx)) + goto err; + if (!BN_is_one(tmp)) + *ret |= DH_CHECK_PUBKEY_INVALID; + } + + ok = 1; + err: + if (ctx != NULL) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + return ok; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_depr.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_depr.c new file mode 100644 index 000000000..f8ed1b746 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_depr.c @@ -0,0 +1,46 @@ +/* + * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* This file contains deprecated functions as wrappers to the new ones */ + +#include +#if OPENSSL_API_COMPAT >= 0x00908000L +NON_EMPTY_TRANSLATION_UNIT +#else + +# include +# include "internal/cryptlib.h" +# include +# include + +DH *DH_generate_parameters(int prime_len, int generator, + void (*callback) (int, int, void *), void *cb_arg) +{ + BN_GENCB *cb; + DH *ret = NULL; + + if ((ret = DH_new()) == NULL) + return NULL; + cb = BN_GENCB_new(); + if (cb == NULL) { + DH_free(ret); + return NULL; + } + + BN_GENCB_set_old(cb, callback, cb_arg); + + if (DH_generate_parameters_ex(ret, prime_len, generator, cb)) { + BN_GENCB_free(cb); + return ret; + } + BN_GENCB_free(cb); + DH_free(ret); + return NULL; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_err.c new file mode 100644 index 000000000..7285587b4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_err.c @@ -0,0 +1,101 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA DH_str_functs[] = { + {ERR_PACK(ERR_LIB_DH, DH_F_COMPUTE_KEY, 0), "compute_key"}, + {ERR_PACK(ERR_LIB_DH, DH_F_DHPARAMS_PRINT_FP, 0), "DHparams_print_fp"}, + {ERR_PACK(ERR_LIB_DH, DH_F_DH_BUILTIN_GENPARAMS, 0), + "dh_builtin_genparams"}, + {ERR_PACK(ERR_LIB_DH, DH_F_DH_CHECK_EX, 0), "DH_check_ex"}, + {ERR_PACK(ERR_LIB_DH, DH_F_DH_CHECK_PARAMS_EX, 0), "DH_check_params_ex"}, + {ERR_PACK(ERR_LIB_DH, DH_F_DH_CHECK_PUB_KEY_EX, 0), "DH_check_pub_key_ex"}, + {ERR_PACK(ERR_LIB_DH, DH_F_DH_CMS_DECRYPT, 0), "dh_cms_decrypt"}, + {ERR_PACK(ERR_LIB_DH, DH_F_DH_CMS_SET_PEERKEY, 0), "dh_cms_set_peerkey"}, + {ERR_PACK(ERR_LIB_DH, DH_F_DH_CMS_SET_SHARED_INFO, 0), + "dh_cms_set_shared_info"}, + {ERR_PACK(ERR_LIB_DH, DH_F_DH_METH_DUP, 0), "DH_meth_dup"}, + {ERR_PACK(ERR_LIB_DH, DH_F_DH_METH_NEW, 0), "DH_meth_new"}, + {ERR_PACK(ERR_LIB_DH, DH_F_DH_METH_SET1_NAME, 0), "DH_meth_set1_name"}, + {ERR_PACK(ERR_LIB_DH, DH_F_DH_NEW_BY_NID, 0), "DH_new_by_nid"}, + {ERR_PACK(ERR_LIB_DH, DH_F_DH_NEW_METHOD, 0), "DH_new_method"}, + {ERR_PACK(ERR_LIB_DH, DH_F_DH_PARAM_DECODE, 0), "dh_param_decode"}, + {ERR_PACK(ERR_LIB_DH, DH_F_DH_PKEY_PUBLIC_CHECK, 0), + "dh_pkey_public_check"}, + {ERR_PACK(ERR_LIB_DH, DH_F_DH_PRIV_DECODE, 0), "dh_priv_decode"}, + {ERR_PACK(ERR_LIB_DH, DH_F_DH_PRIV_ENCODE, 0), "dh_priv_encode"}, + {ERR_PACK(ERR_LIB_DH, DH_F_DH_PUB_DECODE, 0), "dh_pub_decode"}, + {ERR_PACK(ERR_LIB_DH, DH_F_DH_PUB_ENCODE, 0), "dh_pub_encode"}, + {ERR_PACK(ERR_LIB_DH, DH_F_DO_DH_PRINT, 0), "do_dh_print"}, + {ERR_PACK(ERR_LIB_DH, DH_F_GENERATE_KEY, 0), "generate_key"}, + {ERR_PACK(ERR_LIB_DH, DH_F_PKEY_DH_CTRL_STR, 0), "pkey_dh_ctrl_str"}, + {ERR_PACK(ERR_LIB_DH, DH_F_PKEY_DH_DERIVE, 0), "pkey_dh_derive"}, + {ERR_PACK(ERR_LIB_DH, DH_F_PKEY_DH_INIT, 0), "pkey_dh_init"}, + {ERR_PACK(ERR_LIB_DH, DH_F_PKEY_DH_KEYGEN, 0), "pkey_dh_keygen"}, + {0, NULL} +}; + +static const ERR_STRING_DATA DH_str_reasons[] = { + {ERR_PACK(ERR_LIB_DH, 0, DH_R_BAD_GENERATOR), "bad generator"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_BN_DECODE_ERROR), "bn decode error"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_BN_ERROR), "bn error"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_CHECK_INVALID_J_VALUE), + "check invalid j value"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_CHECK_INVALID_Q_VALUE), + "check invalid q value"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_CHECK_PUBKEY_INVALID), + "check pubkey invalid"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_CHECK_PUBKEY_TOO_LARGE), + "check pubkey too large"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_CHECK_PUBKEY_TOO_SMALL), + "check pubkey too small"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_CHECK_P_NOT_PRIME), "check p not prime"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_CHECK_P_NOT_SAFE_PRIME), + "check p not safe prime"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_CHECK_Q_NOT_PRIME), "check q not prime"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_DECODE_ERROR), "decode error"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_INVALID_PARAMETER_NAME), + "invalid parameter name"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_INVALID_PARAMETER_NID), + "invalid parameter nid"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_INVALID_PUBKEY), "invalid public key"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_KDF_PARAMETER_ERROR), "kdf parameter error"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_KEYS_NOT_SET), "keys not set"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_MISSING_PUBKEY), "missing pubkey"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_MODULUS_TOO_LARGE), "modulus too large"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_NOT_SUITABLE_GENERATOR), + "not suitable generator"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_NO_PARAMETERS_SET), "no parameters set"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_NO_PRIVATE_VALUE), "no private value"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_PARAMETER_ENCODING_ERROR), + "parameter encoding error"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_PEER_KEY_ERROR), "peer key error"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_SHARED_INFO_ERROR), "shared info error"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_UNABLE_TO_CHECK_GENERATOR), + "unable to check generator"}, + {0, NULL} +}; + +#endif + +int ERR_load_DH_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(DH_str_functs[0].error) == NULL) { + ERR_load_strings_const(DH_str_functs); + ERR_load_strings_const(DH_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_gen.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_gen.c new file mode 100644 index 000000000..59137e0f0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_gen.c @@ -0,0 +1,130 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * NB: These functions have been upgraded - the previous prototypes are in + * dh_depr.c as wrappers to these ones. - Geoff + */ + +#include +#include "internal/cryptlib.h" +#include +#include "dh_locl.h" + +static int dh_builtin_genparams(DH *ret, int prime_len, int generator, + BN_GENCB *cb); + +int DH_generate_parameters_ex(DH *ret, int prime_len, int generator, + BN_GENCB *cb) +{ + if (ret->meth->generate_params) + return ret->meth->generate_params(ret, prime_len, generator, cb); + return dh_builtin_genparams(ret, prime_len, generator, cb); +} + +/*- + * We generate DH parameters as follows + * find a prime q which is prime_len/2 bits long. + * p=(2*q)+1 or (p-1)/2 = q + * For this case, g is a generator if + * g^((p-1)/q) mod p != 1 for values of q which are the factors of p-1. + * Since the factors of p-1 are q and 2, we just need to check + * g^2 mod p != 1 and g^q mod p != 1. + * + * Having said all that, + * there is another special case method for the generators 2, 3 and 5. + * for 2, p mod 24 == 11 + * for 3, p mod 12 == 5 <<<<< does not work for safe primes. + * for 5, p mod 10 == 3 or 7 + * + * Thanks to Phil Karn for the pointers about the + * special generators and for answering some of my questions. + * + * I've implemented the second simple method :-). + * Since DH should be using a safe prime (both p and q are prime), + * this generator function can take a very very long time to run. + */ +/* + * Actually there is no reason to insist that 'generator' be a generator. + * It's just as OK (and in some sense better) to use a generator of the + * order-q subgroup. + */ +static int dh_builtin_genparams(DH *ret, int prime_len, int generator, + BN_GENCB *cb) +{ + BIGNUM *t1, *t2; + int g, ok = -1; + BN_CTX *ctx = NULL; + + ctx = BN_CTX_new(); + if (ctx == NULL) + goto err; + BN_CTX_start(ctx); + t1 = BN_CTX_get(ctx); + t2 = BN_CTX_get(ctx); + if (t2 == NULL) + goto err; + + /* Make sure 'ret' has the necessary elements */ + if (!ret->p && ((ret->p = BN_new()) == NULL)) + goto err; + if (!ret->g && ((ret->g = BN_new()) == NULL)) + goto err; + + if (generator <= 1) { + DHerr(DH_F_DH_BUILTIN_GENPARAMS, DH_R_BAD_GENERATOR); + goto err; + } + if (generator == DH_GENERATOR_2) { + if (!BN_set_word(t1, 24)) + goto err; + if (!BN_set_word(t2, 11)) + goto err; + g = 2; + } else if (generator == DH_GENERATOR_5) { + if (!BN_set_word(t1, 10)) + goto err; + if (!BN_set_word(t2, 3)) + goto err; + /* + * BN_set_word(t3,7); just have to miss out on these ones :-( + */ + g = 5; + } else { + /* + * in the general case, don't worry if 'generator' is a generator or + * not: since we are using safe primes, it will generate either an + * order-q or an order-2q group, which both is OK + */ + if (!BN_set_word(t1, 2)) + goto err; + if (!BN_set_word(t2, 1)) + goto err; + g = generator; + } + + if (!BN_generate_prime_ex(ret->p, prime_len, 1, t1, t2, cb)) + goto err; + if (!BN_GENCB_call(cb, 3, 0)) + goto err; + if (!BN_set_word(ret->g, g)) + goto err; + ok = 1; + err: + if (ok == -1) { + DHerr(DH_F_DH_BUILTIN_GENPARAMS, ERR_R_BN_LIB); + ok = 0; + } + + if (ctx != NULL) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + return ok; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_kdf.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_kdf.c new file mode 100644 index 000000000..e17122bc8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_kdf.c @@ -0,0 +1,150 @@ +/* + * Copyright 2013-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "e_os.h" + +#ifndef OPENSSL_NO_CMS +#include +#include +#include +#include +#include + + +/* Key derivation from X9.42/RFC2631 */ +/* Uses CMS functions, hence the #ifdef wrapper. */ + +#define DH_KDF_MAX (1L << 30) + +/* Skip past an ASN1 structure: for OBJECT skip content octets too */ + +static int skip_asn1(unsigned char **pp, long *plen, int exptag) +{ + const unsigned char *q = *pp; + int i, tag, xclass; + long tmplen; + i = ASN1_get_object(&q, &tmplen, &tag, &xclass, *plen); + if (i & 0x80) + return 0; + if (tag != exptag || xclass != V_ASN1_UNIVERSAL) + return 0; + if (tag == V_ASN1_OBJECT) + q += tmplen; + *plen -= q - *pp; + *pp = (unsigned char *)q; + return 1; +} + +/* + * Encode the DH shared info structure, return an offset to the counter value + * so we can update the structure without reencoding it. + */ + +static int dh_sharedinfo_encode(unsigned char **pder, unsigned char **pctr, + ASN1_OBJECT *key_oid, size_t outlen, + const unsigned char *ukm, size_t ukmlen) +{ + unsigned char *p; + int derlen; + long tlen; + /* "magic" value to check offset is sane */ + static unsigned char ctr[4] = { 0xF3, 0x17, 0x22, 0x53 }; + X509_ALGOR atmp; + ASN1_OCTET_STRING ctr_oct, ukm_oct, *pukm_oct; + ASN1_TYPE ctr_atype; + if (ukmlen > DH_KDF_MAX || outlen > DH_KDF_MAX) + return 0; + ctr_oct.data = ctr; + ctr_oct.length = 4; + ctr_oct.flags = 0; + ctr_oct.type = V_ASN1_OCTET_STRING; + ctr_atype.type = V_ASN1_OCTET_STRING; + ctr_atype.value.octet_string = &ctr_oct; + atmp.algorithm = key_oid; + atmp.parameter = &ctr_atype; + if (ukm) { + ukm_oct.type = V_ASN1_OCTET_STRING; + ukm_oct.flags = 0; + ukm_oct.data = (unsigned char *)ukm; + ukm_oct.length = ukmlen; + pukm_oct = &ukm_oct; + } else + pukm_oct = NULL; + derlen = CMS_SharedInfo_encode(pder, &atmp, pukm_oct, outlen); + if (derlen <= 0) + return 0; + p = *pder; + tlen = derlen; + if (!skip_asn1(&p, &tlen, V_ASN1_SEQUENCE)) + return 0; + if (!skip_asn1(&p, &tlen, V_ASN1_SEQUENCE)) + return 0; + if (!skip_asn1(&p, &tlen, V_ASN1_OBJECT)) + return 0; + if (!skip_asn1(&p, &tlen, V_ASN1_OCTET_STRING)) + return 0; + if (CRYPTO_memcmp(p, ctr, 4)) + return 0; + *pctr = p; + return derlen; +} + +int DH_KDF_X9_42(unsigned char *out, size_t outlen, + const unsigned char *Z, size_t Zlen, + ASN1_OBJECT *key_oid, + const unsigned char *ukm, size_t ukmlen, const EVP_MD *md) +{ + EVP_MD_CTX *mctx = NULL; + int rv = 0; + unsigned int i; + size_t mdlen; + unsigned char *der = NULL, *ctr; + int derlen; + if (Zlen > DH_KDF_MAX) + return 0; + mctx = EVP_MD_CTX_new(); + if (mctx == NULL) + return 0; + mdlen = EVP_MD_size(md); + derlen = dh_sharedinfo_encode(&der, &ctr, key_oid, outlen, ukm, ukmlen); + if (derlen == 0) + goto err; + for (i = 1;; i++) { + unsigned char mtmp[EVP_MAX_MD_SIZE]; + if (!EVP_DigestInit_ex(mctx, md, NULL) + || !EVP_DigestUpdate(mctx, Z, Zlen)) + goto err; + ctr[3] = i & 0xFF; + ctr[2] = (i >> 8) & 0xFF; + ctr[1] = (i >> 16) & 0xFF; + ctr[0] = (i >> 24) & 0xFF; + if (!EVP_DigestUpdate(mctx, der, derlen)) + goto err; + if (outlen >= mdlen) { + if (!EVP_DigestFinal(mctx, out, NULL)) + goto err; + outlen -= mdlen; + if (outlen == 0) + break; + out += mdlen; + } else { + if (!EVP_DigestFinal(mctx, mtmp, NULL)) + goto err; + memcpy(out, mtmp, outlen); + OPENSSL_cleanse(mtmp, mdlen); + break; + } + } + rv = 1; + err: + OPENSSL_free(der); + EVP_MD_CTX_free(mctx); + return rv; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_key.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_key.c new file mode 100644 index 000000000..4f85be7e4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_key.c @@ -0,0 +1,232 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include "dh_locl.h" +#include "internal/bn_int.h" + +static int generate_key(DH *dh); +static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh); +static int dh_bn_mod_exp(const DH *dh, BIGNUM *r, + const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); +static int dh_init(DH *dh); +static int dh_finish(DH *dh); + +int DH_generate_key(DH *dh) +{ + return dh->meth->generate_key(dh); +} + +int DH_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh) +{ + return dh->meth->compute_key(key, pub_key, dh); +} + +int DH_compute_key_padded(unsigned char *key, const BIGNUM *pub_key, DH *dh) +{ + int rv, pad; + rv = dh->meth->compute_key(key, pub_key, dh); + if (rv <= 0) + return rv; + pad = BN_num_bytes(dh->p) - rv; + if (pad > 0) { + memmove(key + pad, key, rv); + memset(key, 0, pad); + } + return rv + pad; +} + +static DH_METHOD dh_ossl = { + "OpenSSL DH Method", + generate_key, + compute_key, + dh_bn_mod_exp, + dh_init, + dh_finish, + DH_FLAG_FIPS_METHOD, + NULL, + NULL +}; + +static const DH_METHOD *default_DH_method = &dh_ossl; + +const DH_METHOD *DH_OpenSSL(void) +{ + return &dh_ossl; +} + +void DH_set_default_method(const DH_METHOD *meth) +{ + default_DH_method = meth; +} + +const DH_METHOD *DH_get_default_method(void) +{ + return default_DH_method; +} + +static int generate_key(DH *dh) +{ + int ok = 0; + int generate_new_key = 0; + unsigned l; + BN_CTX *ctx = NULL; + BN_MONT_CTX *mont = NULL; + BIGNUM *pub_key = NULL, *priv_key = NULL; + + if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) { + DHerr(DH_F_GENERATE_KEY, DH_R_MODULUS_TOO_LARGE); + return 0; + } + + ctx = BN_CTX_new(); + if (ctx == NULL) + goto err; + + if (dh->priv_key == NULL) { + priv_key = BN_secure_new(); + if (priv_key == NULL) + goto err; + generate_new_key = 1; + } else + priv_key = dh->priv_key; + + if (dh->pub_key == NULL) { + pub_key = BN_new(); + if (pub_key == NULL) + goto err; + } else + pub_key = dh->pub_key; + + if (dh->flags & DH_FLAG_CACHE_MONT_P) { + mont = BN_MONT_CTX_set_locked(&dh->method_mont_p, + dh->lock, dh->p, ctx); + if (!mont) + goto err; + } + + if (generate_new_key) { + if (dh->q) { + do { + if (!BN_priv_rand_range(priv_key, dh->q)) + goto err; + } + while (BN_is_zero(priv_key) || BN_is_one(priv_key)); + } else { + /* secret exponent length */ + l = dh->length ? dh->length : BN_num_bits(dh->p) - 1; + if (!BN_priv_rand(priv_key, l, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) + goto err; + } + } + + { + BIGNUM *prk = BN_new(); + + if (prk == NULL) + goto err; + BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME); + + if (!dh->meth->bn_mod_exp(dh, pub_key, dh->g, prk, dh->p, ctx, mont)) { + BN_free(prk); + goto err; + } + /* We MUST free prk before any further use of priv_key */ + BN_free(prk); + } + + dh->pub_key = pub_key; + dh->priv_key = priv_key; + ok = 1; + err: + if (ok != 1) + DHerr(DH_F_GENERATE_KEY, ERR_R_BN_LIB); + + if (pub_key != dh->pub_key) + BN_free(pub_key); + if (priv_key != dh->priv_key) + BN_free(priv_key); + BN_CTX_free(ctx); + return ok; +} + +static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh) +{ + BN_CTX *ctx = NULL; + BN_MONT_CTX *mont = NULL; + BIGNUM *tmp; + int ret = -1; + int check_result; + + if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) { + DHerr(DH_F_COMPUTE_KEY, DH_R_MODULUS_TOO_LARGE); + goto err; + } + + ctx = BN_CTX_new(); + if (ctx == NULL) + goto err; + BN_CTX_start(ctx); + tmp = BN_CTX_get(ctx); + if (tmp == NULL) + goto err; + + if (dh->priv_key == NULL) { + DHerr(DH_F_COMPUTE_KEY, DH_R_NO_PRIVATE_VALUE); + goto err; + } + + if (dh->flags & DH_FLAG_CACHE_MONT_P) { + mont = BN_MONT_CTX_set_locked(&dh->method_mont_p, + dh->lock, dh->p, ctx); + BN_set_flags(dh->priv_key, BN_FLG_CONSTTIME); + if (!mont) + goto err; + } + + if (!DH_check_pub_key(dh, pub_key, &check_result) || check_result) { + DHerr(DH_F_COMPUTE_KEY, DH_R_INVALID_PUBKEY); + goto err; + } + + if (!dh-> + meth->bn_mod_exp(dh, tmp, pub_key, dh->priv_key, dh->p, ctx, mont)) { + DHerr(DH_F_COMPUTE_KEY, ERR_R_BN_LIB); + goto err; + } + + ret = BN_bn2bin(tmp, key); + err: + if (ctx != NULL) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + return ret; +} + +static int dh_bn_mod_exp(const DH *dh, BIGNUM *r, + const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) +{ + return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx); +} + +static int dh_init(DH *dh) +{ + dh->flags |= DH_FLAG_CACHE_MONT_P; + return 1; +} + +static int dh_finish(DH *dh) +{ + BN_MONT_CTX_free(dh->method_mont_p); + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_lib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_lib.c new file mode 100644 index 000000000..962f864de --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_lib.c @@ -0,0 +1,291 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include "internal/refcount.h" +#include +#include "dh_locl.h" +#include + +int DH_set_method(DH *dh, const DH_METHOD *meth) +{ + /* + * NB: The caller is specifically setting a method, so it's not up to us + * to deal with which ENGINE it comes from. + */ + const DH_METHOD *mtmp; + mtmp = dh->meth; + if (mtmp->finish) + mtmp->finish(dh); +#ifndef OPENSSL_NO_ENGINE + ENGINE_finish(dh->engine); + dh->engine = NULL; +#endif + dh->meth = meth; + if (meth->init) + meth->init(dh); + return 1; +} + +DH *DH_new(void) +{ + return DH_new_method(NULL); +} + +DH *DH_new_method(ENGINE *engine) +{ + DH *ret = OPENSSL_zalloc(sizeof(*ret)); + + if (ret == NULL) { + DHerr(DH_F_DH_NEW_METHOD, ERR_R_MALLOC_FAILURE); + return NULL; + } + + ret->references = 1; + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) { + DHerr(DH_F_DH_NEW_METHOD, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ret); + return NULL; + } + + ret->meth = DH_get_default_method(); +#ifndef OPENSSL_NO_ENGINE + ret->flags = ret->meth->flags; /* early default init */ + if (engine) { + if (!ENGINE_init(engine)) { + DHerr(DH_F_DH_NEW_METHOD, ERR_R_ENGINE_LIB); + goto err; + } + ret->engine = engine; + } else + ret->engine = ENGINE_get_default_DH(); + if (ret->engine) { + ret->meth = ENGINE_get_DH(ret->engine); + if (ret->meth == NULL) { + DHerr(DH_F_DH_NEW_METHOD, ERR_R_ENGINE_LIB); + goto err; + } + } +#endif + + ret->flags = ret->meth->flags; + + if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DH, ret, &ret->ex_data)) + goto err; + + if ((ret->meth->init != NULL) && !ret->meth->init(ret)) { + DHerr(DH_F_DH_NEW_METHOD, ERR_R_INIT_FAIL); + goto err; + } + + return ret; + + err: + DH_free(ret); + return NULL; +} + +void DH_free(DH *r) +{ + int i; + + if (r == NULL) + return; + + CRYPTO_DOWN_REF(&r->references, &i, r->lock); + REF_PRINT_COUNT("DH", r); + if (i > 0) + return; + REF_ASSERT_ISNT(i < 0); + + if (r->meth != NULL && r->meth->finish != NULL) + r->meth->finish(r); +#ifndef OPENSSL_NO_ENGINE + ENGINE_finish(r->engine); +#endif + + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH, r, &r->ex_data); + + CRYPTO_THREAD_lock_free(r->lock); + + BN_clear_free(r->p); + BN_clear_free(r->g); + BN_clear_free(r->q); + BN_clear_free(r->j); + OPENSSL_free(r->seed); + BN_clear_free(r->counter); + BN_clear_free(r->pub_key); + BN_clear_free(r->priv_key); + OPENSSL_free(r); +} + +int DH_up_ref(DH *r) +{ + int i; + + if (CRYPTO_UP_REF(&r->references, &i, r->lock) <= 0) + return 0; + + REF_PRINT_COUNT("DH", r); + REF_ASSERT_ISNT(i < 2); + return ((i > 1) ? 1 : 0); +} + +int DH_set_ex_data(DH *d, int idx, void *arg) +{ + return CRYPTO_set_ex_data(&d->ex_data, idx, arg); +} + +void *DH_get_ex_data(DH *d, int idx) +{ + return CRYPTO_get_ex_data(&d->ex_data, idx); +} + +int DH_bits(const DH *dh) +{ + return BN_num_bits(dh->p); +} + +int DH_size(const DH *dh) +{ + return BN_num_bytes(dh->p); +} + +int DH_security_bits(const DH *dh) +{ + int N; + if (dh->q) + N = BN_num_bits(dh->q); + else if (dh->length) + N = dh->length; + else + N = -1; + return BN_security_bits(BN_num_bits(dh->p), N); +} + + +void DH_get0_pqg(const DH *dh, + const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) +{ + if (p != NULL) + *p = dh->p; + if (q != NULL) + *q = dh->q; + if (g != NULL) + *g = dh->g; +} + +int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) +{ + /* If the fields p and g in d are NULL, the corresponding input + * parameters MUST be non-NULL. q may remain NULL. + */ + if ((dh->p == NULL && p == NULL) + || (dh->g == NULL && g == NULL)) + return 0; + + if (p != NULL) { + BN_free(dh->p); + dh->p = p; + } + if (q != NULL) { + BN_free(dh->q); + dh->q = q; + } + if (g != NULL) { + BN_free(dh->g); + dh->g = g; + } + + if (q != NULL) { + dh->length = BN_num_bits(q); + } + + return 1; +} + +long DH_get_length(const DH *dh) +{ + return dh->length; +} + +int DH_set_length(DH *dh, long length) +{ + dh->length = length; + return 1; +} + +void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key) +{ + if (pub_key != NULL) + *pub_key = dh->pub_key; + if (priv_key != NULL) + *priv_key = dh->priv_key; +} + +int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) +{ + if (pub_key != NULL) { + BN_free(dh->pub_key); + dh->pub_key = pub_key; + } + if (priv_key != NULL) { + BN_free(dh->priv_key); + dh->priv_key = priv_key; + } + + return 1; +} + +const BIGNUM *DH_get0_p(const DH *dh) +{ + return dh->p; +} + +const BIGNUM *DH_get0_q(const DH *dh) +{ + return dh->q; +} + +const BIGNUM *DH_get0_g(const DH *dh) +{ + return dh->g; +} + +const BIGNUM *DH_get0_priv_key(const DH *dh) +{ + return dh->priv_key; +} + +const BIGNUM *DH_get0_pub_key(const DH *dh) +{ + return dh->pub_key; +} + +void DH_clear_flags(DH *dh, int flags) +{ + dh->flags &= ~flags; +} + +int DH_test_flags(const DH *dh, int flags) +{ + return dh->flags & flags; +} + +void DH_set_flags(DH *dh, int flags) +{ + dh->flags |= flags; +} + +ENGINE *DH_get0_engine(DH *dh) +{ + return dh->engine; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_locl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_locl.h new file mode 100644 index 000000000..0a8391a6c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_locl.h @@ -0,0 +1,57 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/refcount.h" + +struct dh_st { + /* + * This first argument is used to pick up errors when a DH is passed + * instead of a EVP_PKEY + */ + int pad; + int version; + BIGNUM *p; + BIGNUM *g; + int32_t length; /* optional */ + BIGNUM *pub_key; /* g^x % p */ + BIGNUM *priv_key; /* x */ + int flags; + BN_MONT_CTX *method_mont_p; + /* Place holders if we want to do X9.42 DH */ + BIGNUM *q; + BIGNUM *j; + unsigned char *seed; + int seedlen; + BIGNUM *counter; + CRYPTO_REF_COUNT references; + CRYPTO_EX_DATA ex_data; + const DH_METHOD *meth; + ENGINE *engine; + CRYPTO_RWLOCK *lock; +}; + +struct dh_method { + char *name; + /* Methods here */ + int (*generate_key) (DH *dh); + int (*compute_key) (unsigned char *key, const BIGNUM *pub_key, DH *dh); + + /* Can be null */ + int (*bn_mod_exp) (const DH *dh, BIGNUM *r, const BIGNUM *a, + const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *m_ctx); + int (*init) (DH *dh); + int (*finish) (DH *dh); + int flags; + char *app_data; + /* If this is non-NULL, it will be used to generate parameters */ + int (*generate_params) (DH *dh, int prime_len, int generator, + BN_GENCB *cb); +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_meth.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_meth.c new file mode 100644 index 000000000..59c4d7e96 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_meth.c @@ -0,0 +1,173 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "dh_locl.h" +#include +#include + +DH_METHOD *DH_meth_new(const char *name, int flags) +{ + DH_METHOD *dhm = OPENSSL_zalloc(sizeof(*dhm)); + + if (dhm != NULL) { + dhm->flags = flags; + + dhm->name = OPENSSL_strdup(name); + if (dhm->name != NULL) + return dhm; + + OPENSSL_free(dhm); + } + + DHerr(DH_F_DH_METH_NEW, ERR_R_MALLOC_FAILURE); + return NULL; +} + +void DH_meth_free(DH_METHOD *dhm) +{ + if (dhm != NULL) { + OPENSSL_free(dhm->name); + OPENSSL_free(dhm); + } +} + +DH_METHOD *DH_meth_dup(const DH_METHOD *dhm) +{ + DH_METHOD *ret = OPENSSL_malloc(sizeof(*ret)); + + if (ret != NULL) { + memcpy(ret, dhm, sizeof(*dhm)); + + ret->name = OPENSSL_strdup(dhm->name); + if (ret->name != NULL) + return ret; + + OPENSSL_free(ret); + } + + DHerr(DH_F_DH_METH_DUP, ERR_R_MALLOC_FAILURE); + return NULL; +} + +const char *DH_meth_get0_name(const DH_METHOD *dhm) +{ + return dhm->name; +} + +int DH_meth_set1_name(DH_METHOD *dhm, const char *name) +{ + char *tmpname = OPENSSL_strdup(name); + + if (tmpname == NULL) { + DHerr(DH_F_DH_METH_SET1_NAME, ERR_R_MALLOC_FAILURE); + return 0; + } + + OPENSSL_free(dhm->name); + dhm->name = tmpname; + + return 1; +} + +int DH_meth_get_flags(const DH_METHOD *dhm) +{ + return dhm->flags; +} + +int DH_meth_set_flags(DH_METHOD *dhm, int flags) +{ + dhm->flags = flags; + return 1; +} + +void *DH_meth_get0_app_data(const DH_METHOD *dhm) +{ + return dhm->app_data; +} + +int DH_meth_set0_app_data(DH_METHOD *dhm, void *app_data) +{ + dhm->app_data = app_data; + return 1; +} + +int (*DH_meth_get_generate_key(const DH_METHOD *dhm)) (DH *) +{ + return dhm->generate_key; +} + +int DH_meth_set_generate_key(DH_METHOD *dhm, int (*generate_key) (DH *)) +{ + dhm->generate_key = generate_key; + return 1; +} + +int (*DH_meth_get_compute_key(const DH_METHOD *dhm)) + (unsigned char *key, const BIGNUM *pub_key, DH *dh) +{ + return dhm->compute_key; +} + +int DH_meth_set_compute_key(DH_METHOD *dhm, + int (*compute_key) (unsigned char *key, const BIGNUM *pub_key, DH *dh)) +{ + dhm->compute_key = compute_key; + return 1; +} + + +int (*DH_meth_get_bn_mod_exp(const DH_METHOD *dhm)) + (const DH *, BIGNUM *, const BIGNUM *, const BIGNUM *, const BIGNUM *, + BN_CTX *, BN_MONT_CTX *) +{ + return dhm->bn_mod_exp; +} + +int DH_meth_set_bn_mod_exp(DH_METHOD *dhm, + int (*bn_mod_exp) (const DH *, BIGNUM *, const BIGNUM *, const BIGNUM *, + const BIGNUM *, BN_CTX *, BN_MONT_CTX *)) +{ + dhm->bn_mod_exp = bn_mod_exp; + return 1; +} + +int (*DH_meth_get_init(const DH_METHOD *dhm))(DH *) +{ + return dhm->init; +} + +int DH_meth_set_init(DH_METHOD *dhm, int (*init)(DH *)) +{ + dhm->init = init; + return 1; +} + +int (*DH_meth_get_finish(const DH_METHOD *dhm)) (DH *) +{ + return dhm->finish; +} + +int DH_meth_set_finish(DH_METHOD *dhm, int (*finish) (DH *)) +{ + dhm->finish = finish; + return 1; +} + +int (*DH_meth_get_generate_params(const DH_METHOD *dhm)) + (DH *, int, int, BN_GENCB *) +{ + return dhm->generate_params; +} + +int DH_meth_set_generate_params(DH_METHOD *dhm, + int (*generate_params) (DH *, int, int, BN_GENCB *)) +{ + dhm->generate_params = generate_params; + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_pmeth.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_pmeth.c new file mode 100644 index 000000000..cce2d9e26 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_pmeth.c @@ -0,0 +1,547 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include "dh_locl.h" +#include +#include +#include +#include "internal/evp_int.h" + +/* DH pkey context structure */ + +typedef struct { + /* Parameter gen parameters */ + int prime_len; + int generator; + int use_dsa; + int subprime_len; + int pad; + /* message digest used for parameter generation */ + const EVP_MD *md; + int rfc5114_param; + int param_nid; + /* Keygen callback info */ + int gentmp[2]; + /* KDF (if any) to use for DH */ + char kdf_type; + /* OID to use for KDF */ + ASN1_OBJECT *kdf_oid; + /* Message digest to use for key derivation */ + const EVP_MD *kdf_md; + /* User key material */ + unsigned char *kdf_ukm; + size_t kdf_ukmlen; + /* KDF output length */ + size_t kdf_outlen; +} DH_PKEY_CTX; + +static int pkey_dh_init(EVP_PKEY_CTX *ctx) +{ + DH_PKEY_CTX *dctx; + + if ((dctx = OPENSSL_zalloc(sizeof(*dctx))) == NULL) { + DHerr(DH_F_PKEY_DH_INIT, ERR_R_MALLOC_FAILURE); + return 0; + } + dctx->prime_len = 1024; + dctx->subprime_len = -1; + dctx->generator = 2; + dctx->kdf_type = EVP_PKEY_DH_KDF_NONE; + + ctx->data = dctx; + ctx->keygen_info = dctx->gentmp; + ctx->keygen_info_count = 2; + + return 1; +} + +static void pkey_dh_cleanup(EVP_PKEY_CTX *ctx) +{ + DH_PKEY_CTX *dctx = ctx->data; + if (dctx != NULL) { + OPENSSL_free(dctx->kdf_ukm); + ASN1_OBJECT_free(dctx->kdf_oid); + OPENSSL_free(dctx); + } +} + + +static int pkey_dh_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) +{ + DH_PKEY_CTX *dctx, *sctx; + if (!pkey_dh_init(dst)) + return 0; + sctx = src->data; + dctx = dst->data; + dctx->prime_len = sctx->prime_len; + dctx->subprime_len = sctx->subprime_len; + dctx->generator = sctx->generator; + dctx->use_dsa = sctx->use_dsa; + dctx->pad = sctx->pad; + dctx->md = sctx->md; + dctx->rfc5114_param = sctx->rfc5114_param; + dctx->param_nid = sctx->param_nid; + + dctx->kdf_type = sctx->kdf_type; + dctx->kdf_oid = OBJ_dup(sctx->kdf_oid); + if (dctx->kdf_oid == NULL) + return 0; + dctx->kdf_md = sctx->kdf_md; + if (sctx->kdf_ukm != NULL) { + dctx->kdf_ukm = OPENSSL_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen); + if (dctx->kdf_ukm == NULL) + return 0; + dctx->kdf_ukmlen = sctx->kdf_ukmlen; + } + dctx->kdf_outlen = sctx->kdf_outlen; + return 1; +} + +static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) +{ + DH_PKEY_CTX *dctx = ctx->data; + switch (type) { + case EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN: + if (p1 < 256) + return -2; + dctx->prime_len = p1; + return 1; + + case EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN: + if (dctx->use_dsa == 0) + return -2; + dctx->subprime_len = p1; + return 1; + + case EVP_PKEY_CTRL_DH_PAD: + dctx->pad = p1; + return 1; + + case EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR: + if (dctx->use_dsa) + return -2; + dctx->generator = p1; + return 1; + + case EVP_PKEY_CTRL_DH_PARAMGEN_TYPE: +#ifdef OPENSSL_NO_DSA + if (p1 != 0) + return -2; +#else + if (p1 < 0 || p1 > 2) + return -2; +#endif + dctx->use_dsa = p1; + return 1; + + case EVP_PKEY_CTRL_DH_RFC5114: + if (p1 < 1 || p1 > 3 || dctx->param_nid != NID_undef) + return -2; + dctx->rfc5114_param = p1; + return 1; + + case EVP_PKEY_CTRL_DH_NID: + if (p1 <= 0 || dctx->rfc5114_param != 0) + return -2; + dctx->param_nid = p1; + return 1; + + case EVP_PKEY_CTRL_PEER_KEY: + /* Default behaviour is OK */ + return 1; + + case EVP_PKEY_CTRL_DH_KDF_TYPE: + if (p1 == -2) + return dctx->kdf_type; +#ifdef OPENSSL_NO_CMS + if (p1 != EVP_PKEY_DH_KDF_NONE) +#else + if (p1 != EVP_PKEY_DH_KDF_NONE && p1 != EVP_PKEY_DH_KDF_X9_42) +#endif + return -2; + dctx->kdf_type = p1; + return 1; + + case EVP_PKEY_CTRL_DH_KDF_MD: + dctx->kdf_md = p2; + return 1; + + case EVP_PKEY_CTRL_GET_DH_KDF_MD: + *(const EVP_MD **)p2 = dctx->kdf_md; + return 1; + + case EVP_PKEY_CTRL_DH_KDF_OUTLEN: + if (p1 <= 0) + return -2; + dctx->kdf_outlen = (size_t)p1; + return 1; + + case EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN: + *(int *)p2 = dctx->kdf_outlen; + return 1; + + case EVP_PKEY_CTRL_DH_KDF_UKM: + OPENSSL_free(dctx->kdf_ukm); + dctx->kdf_ukm = p2; + if (p2) + dctx->kdf_ukmlen = p1; + else + dctx->kdf_ukmlen = 0; + return 1; + + case EVP_PKEY_CTRL_GET_DH_KDF_UKM: + *(unsigned char **)p2 = dctx->kdf_ukm; + return dctx->kdf_ukmlen; + + case EVP_PKEY_CTRL_DH_KDF_OID: + ASN1_OBJECT_free(dctx->kdf_oid); + dctx->kdf_oid = p2; + return 1; + + case EVP_PKEY_CTRL_GET_DH_KDF_OID: + *(ASN1_OBJECT **)p2 = dctx->kdf_oid; + return 1; + + default: + return -2; + + } +} + +static int pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx, + const char *type, const char *value) +{ + if (strcmp(type, "dh_paramgen_prime_len") == 0) { + int len; + len = atoi(value); + return EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len); + } + if (strcmp(type, "dh_rfc5114") == 0) { + DH_PKEY_CTX *dctx = ctx->data; + int len; + len = atoi(value); + if (len < 0 || len > 3) + return -2; + dctx->rfc5114_param = len; + return 1; + } + if (strcmp(type, "dh_param") == 0) { + DH_PKEY_CTX *dctx = ctx->data; + int nid = OBJ_sn2nid(value); + + if (nid == NID_undef) { + DHerr(DH_F_PKEY_DH_CTRL_STR, DH_R_INVALID_PARAMETER_NAME); + return -2; + } + dctx->param_nid = nid; + return 1; + } + if (strcmp(type, "dh_paramgen_generator") == 0) { + int len; + len = atoi(value); + return EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, len); + } + if (strcmp(type, "dh_paramgen_subprime_len") == 0) { + int len; + len = atoi(value); + return EVP_PKEY_CTX_set_dh_paramgen_subprime_len(ctx, len); + } + if (strcmp(type, "dh_paramgen_type") == 0) { + int typ; + typ = atoi(value); + return EVP_PKEY_CTX_set_dh_paramgen_type(ctx, typ); + } + if (strcmp(type, "dh_pad") == 0) { + int pad; + pad = atoi(value); + return EVP_PKEY_CTX_set_dh_pad(ctx, pad); + } + return -2; +} + +#ifndef OPENSSL_NO_DSA + +extern int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits, + const EVP_MD *evpmd, + const unsigned char *seed_in, size_t seed_len, + unsigned char *seed_out, int *counter_ret, + unsigned long *h_ret, BN_GENCB *cb); + +extern int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N, + const EVP_MD *evpmd, + const unsigned char *seed_in, + size_t seed_len, int idx, + unsigned char *seed_out, int *counter_ret, + unsigned long *h_ret, BN_GENCB *cb); + +static DSA *dsa_dh_generate(DH_PKEY_CTX *dctx, BN_GENCB *pcb) +{ + DSA *ret; + int rv = 0; + int prime_len = dctx->prime_len; + int subprime_len = dctx->subprime_len; + const EVP_MD *md = dctx->md; + if (dctx->use_dsa > 2) + return NULL; + ret = DSA_new(); + if (ret == NULL) + return NULL; + if (subprime_len == -1) { + if (prime_len >= 2048) + subprime_len = 256; + else + subprime_len = 160; + } + if (md == NULL) { + if (prime_len >= 2048) + md = EVP_sha256(); + else + md = EVP_sha1(); + } + if (dctx->use_dsa == 1) + rv = dsa_builtin_paramgen(ret, prime_len, subprime_len, md, + NULL, 0, NULL, NULL, NULL, pcb); + else if (dctx->use_dsa == 2) + rv = dsa_builtin_paramgen2(ret, prime_len, subprime_len, md, + NULL, 0, -1, NULL, NULL, NULL, pcb); + if (rv <= 0) { + DSA_free(ret); + return NULL; + } + return ret; +} + +#endif + +static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) +{ + DH *dh = NULL; + DH_PKEY_CTX *dctx = ctx->data; + BN_GENCB *pcb; + int ret; + if (dctx->rfc5114_param) { + switch (dctx->rfc5114_param) { + case 1: + dh = DH_get_1024_160(); + break; + + case 2: + dh = DH_get_2048_224(); + break; + + case 3: + dh = DH_get_2048_256(); + break; + + default: + return -2; + } + EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh); + return 1; + } + + if (dctx->param_nid != 0) { + if ((dh = DH_new_by_nid(dctx->param_nid)) == NULL) + return 0; + EVP_PKEY_assign(pkey, EVP_PKEY_DH, dh); + return 1; + } + + if (ctx->pkey_gencb) { + pcb = BN_GENCB_new(); + if (pcb == NULL) + return 0; + evp_pkey_set_cb_translate(pcb, ctx); + } else + pcb = NULL; +#ifndef OPENSSL_NO_DSA + if (dctx->use_dsa) { + DSA *dsa_dh; + dsa_dh = dsa_dh_generate(dctx, pcb); + BN_GENCB_free(pcb); + if (dsa_dh == NULL) + return 0; + dh = DSA_dup_DH(dsa_dh); + DSA_free(dsa_dh); + if (!dh) + return 0; + EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh); + return 1; + } +#endif + dh = DH_new(); + if (dh == NULL) { + BN_GENCB_free(pcb); + return 0; + } + ret = DH_generate_parameters_ex(dh, + dctx->prime_len, dctx->generator, pcb); + BN_GENCB_free(pcb); + if (ret) + EVP_PKEY_assign_DH(pkey, dh); + else + DH_free(dh); + return ret; +} + +static int pkey_dh_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) +{ + DH_PKEY_CTX *dctx = ctx->data; + DH *dh = NULL; + + if (ctx->pkey == NULL && dctx->param_nid == 0) { + DHerr(DH_F_PKEY_DH_KEYGEN, DH_R_NO_PARAMETERS_SET); + return 0; + } + if (dctx->param_nid != 0) + dh = DH_new_by_nid(dctx->param_nid); + else + dh = DH_new(); + if (dh == NULL) + return 0; + EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, dh); + /* Note: if error return, pkey is freed by parent routine */ + if (ctx->pkey != NULL && !EVP_PKEY_copy_parameters(pkey, ctx->pkey)) + return 0; + return DH_generate_key(pkey->pkey.dh); +} + +static int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key, + size_t *keylen) +{ + int ret; + DH *dh; + DH_PKEY_CTX *dctx = ctx->data; + BIGNUM *dhpub; + if (!ctx->pkey || !ctx->peerkey) { + DHerr(DH_F_PKEY_DH_DERIVE, DH_R_KEYS_NOT_SET); + return 0; + } + dh = ctx->pkey->pkey.dh; + dhpub = ctx->peerkey->pkey.dh->pub_key; + if (dctx->kdf_type == EVP_PKEY_DH_KDF_NONE) { + if (key == NULL) { + *keylen = DH_size(dh); + return 1; + } + if (dctx->pad) + ret = DH_compute_key_padded(key, dhpub, dh); + else + ret = DH_compute_key(key, dhpub, dh); + if (ret < 0) + return ret; + *keylen = ret; + return 1; + } +#ifndef OPENSSL_NO_CMS + else if (dctx->kdf_type == EVP_PKEY_DH_KDF_X9_42) { + + unsigned char *Z = NULL; + size_t Zlen = 0; + if (!dctx->kdf_outlen || !dctx->kdf_oid) + return 0; + if (key == NULL) { + *keylen = dctx->kdf_outlen; + return 1; + } + if (*keylen != dctx->kdf_outlen) + return 0; + ret = 0; + Zlen = DH_size(dh); + Z = OPENSSL_malloc(Zlen); + if (Z == NULL) { + goto err; + } + if (DH_compute_key_padded(Z, dhpub, dh) <= 0) + goto err; + if (!DH_KDF_X9_42(key, *keylen, Z, Zlen, dctx->kdf_oid, + dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md)) + goto err; + *keylen = dctx->kdf_outlen; + ret = 1; + err: + OPENSSL_clear_free(Z, Zlen); + return ret; + } +#endif + return 0; +} + +const EVP_PKEY_METHOD dh_pkey_meth = { + EVP_PKEY_DH, + 0, + pkey_dh_init, + pkey_dh_copy, + pkey_dh_cleanup, + + 0, + pkey_dh_paramgen, + + 0, + pkey_dh_keygen, + + 0, + 0, + + 0, + 0, + + 0, 0, + + 0, 0, 0, 0, + + 0, 0, + + 0, 0, + + 0, + pkey_dh_derive, + + pkey_dh_ctrl, + pkey_dh_ctrl_str +}; + +const EVP_PKEY_METHOD dhx_pkey_meth = { + EVP_PKEY_DHX, + 0, + pkey_dh_init, + pkey_dh_copy, + pkey_dh_cleanup, + + 0, + pkey_dh_paramgen, + + 0, + pkey_dh_keygen, + + 0, + 0, + + 0, + 0, + + 0, 0, + + 0, 0, 0, 0, + + 0, 0, + + 0, 0, + + 0, + pkey_dh_derive, + + pkey_dh_ctrl, + pkey_dh_ctrl_str +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_prn.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_prn.c new file mode 100644 index 000000000..aab1733db --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_prn.c @@ -0,0 +1,30 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include + +#ifndef OPENSSL_NO_STDIO +int DHparams_print_fp(FILE *fp, const DH *x) +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + DHerr(DH_F_DHPARAMS_PRINT_FP, ERR_R_BUF_LIB); + return 0; + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = DHparams_print(b, x); + BIO_free(b); + return ret; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_rfc5114.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_rfc5114.c new file mode 100644 index 000000000..c4a219590 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_rfc5114.c @@ -0,0 +1,41 @@ +/* + * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include "dh_locl.h" +#include +#include "internal/bn_dh.h" + +/* + * Macro to make a DH structure from BIGNUM data. NB: although just copying + * the BIGNUM static pointers would be more efficient, we can't do that + * because they get wiped using BN_clear_free() when DH_free() is called. + */ + +#define make_dh(x) \ +DH *DH_get_##x(void) \ +{ \ + DH *dh = DH_new(); \ +\ + if (dh == NULL) \ + return NULL; \ + dh->p = BN_dup(&_bignum_dh##x##_p); \ + dh->g = BN_dup(&_bignum_dh##x##_g); \ + dh->q = BN_dup(&_bignum_dh##x##_q); \ + if (dh->p == NULL || dh->q == NULL || dh->g == NULL) {\ + DH_free(dh); \ + return NULL; \ + } \ + return dh; \ +} + +make_dh(1024_160) +make_dh(2048_224) +make_dh(2048_256) diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_rfc7919.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_rfc7919.c new file mode 100644 index 000000000..a54b468e5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dh/dh_rfc7919.c @@ -0,0 +1,74 @@ +/* + * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include "dh_locl.h" +#include +#include +#include "internal/bn_dh.h" + +static DH *dh_param_init(const BIGNUM *p, int32_t nbits) +{ + DH *dh = DH_new(); + if (dh == NULL) + return NULL; + dh->p = (BIGNUM *)p; + dh->g = (BIGNUM *)&_bignum_const_2; + dh->length = nbits; + return dh; +} + +DH *DH_new_by_nid(int nid) +{ + switch (nid) { + case NID_ffdhe2048: + return dh_param_init(&_bignum_ffdhe2048_p, 225); + case NID_ffdhe3072: + return dh_param_init(&_bignum_ffdhe3072_p, 275); + case NID_ffdhe4096: + return dh_param_init(&_bignum_ffdhe4096_p, 325); + case NID_ffdhe6144: + return dh_param_init(&_bignum_ffdhe6144_p, 375); + case NID_ffdhe8192: + return dh_param_init(&_bignum_ffdhe8192_p, 400); + default: + DHerr(DH_F_DH_NEW_BY_NID, DH_R_INVALID_PARAMETER_NID); + return NULL; + } +} + +int DH_get_nid(const DH *dh) +{ + int nid; + + if (BN_get_word(dh->g) != 2) + return NID_undef; + if (!BN_cmp(dh->p, &_bignum_ffdhe2048_p)) + nid = NID_ffdhe2048; + else if (!BN_cmp(dh->p, &_bignum_ffdhe3072_p)) + nid = NID_ffdhe3072; + else if (!BN_cmp(dh->p, &_bignum_ffdhe4096_p)) + nid = NID_ffdhe4096; + else if (!BN_cmp(dh->p, &_bignum_ffdhe6144_p)) + nid = NID_ffdhe6144; + else if (!BN_cmp(dh->p, &_bignum_ffdhe8192_p)) + nid = NID_ffdhe8192; + else + return NID_undef; + if (dh->q != NULL) { + BIGNUM *q = BN_dup(dh->p); + + /* Check q = p * 2 + 1 we already know q is odd, so just shift right */ + if (q == NULL || !BN_rshift1(q, q) || !BN_cmp(dh->q, q)) + nid = NID_undef; + BN_free(q); + } + return nid; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dllmain.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dllmain.c new file mode 100644 index 000000000..0838c55e4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dllmain.c @@ -0,0 +1,46 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "e_os.h" +#include "internal/cryptlib_int.h" + +#if defined(_WIN32) || defined(__CYGWIN__) +# ifdef __CYGWIN__ +/* pick DLL_[PROCESS|THREAD]_[ATTACH|DETACH] definitions */ +# include +/* + * this has side-effect of _WIN32 getting defined, which otherwise is + * mutually exclusive with __CYGWIN__... + */ +# endif + +/* + * All we really need to do is remove the 'error' state when a thread + * detaches + */ + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved); +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + switch (fdwReason) { + case DLL_PROCESS_ATTACH: + OPENSSL_cpuid_setup(); + break; + case DLL_THREAD_ATTACH: + break; + case DLL_THREAD_DETACH: + OPENSSL_thread_stop(); + break; + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} +#endif + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/build.info new file mode 100644 index 000000000..2e759853a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/build.info @@ -0,0 +1,5 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + dsa_gen.c dsa_key.c dsa_lib.c dsa_asn1.c dsa_vrf.c dsa_sign.c \ + dsa_err.c dsa_ossl.c dsa_depr.c dsa_ameth.c dsa_pmeth.c dsa_prn.c \ + dsa_meth.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_ameth.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_ameth.c new file mode 100644 index 000000000..9c5b8aa02 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_ameth.c @@ -0,0 +1,572 @@ +/* + * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include "dsa_locl.h" +#include +#include +#include "internal/asn1_int.h" +#include "internal/evp_int.h" + +static int dsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) +{ + const unsigned char *p, *pm; + int pklen, pmlen; + int ptype; + const void *pval; + const ASN1_STRING *pstr; + X509_ALGOR *palg; + ASN1_INTEGER *public_key = NULL; + + DSA *dsa = NULL; + + if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey)) + return 0; + X509_ALGOR_get0(NULL, &ptype, &pval, palg); + + if (ptype == V_ASN1_SEQUENCE) { + pstr = pval; + pm = pstr->data; + pmlen = pstr->length; + + if ((dsa = d2i_DSAparams(NULL, &pm, pmlen)) == NULL) { + DSAerr(DSA_F_DSA_PUB_DECODE, DSA_R_DECODE_ERROR); + goto err; + } + + } else if ((ptype == V_ASN1_NULL) || (ptype == V_ASN1_UNDEF)) { + if ((dsa = DSA_new()) == NULL) { + DSAerr(DSA_F_DSA_PUB_DECODE, ERR_R_MALLOC_FAILURE); + goto err; + } + } else { + DSAerr(DSA_F_DSA_PUB_DECODE, DSA_R_PARAMETER_ENCODING_ERROR); + goto err; + } + + if ((public_key = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL) { + DSAerr(DSA_F_DSA_PUB_DECODE, DSA_R_DECODE_ERROR); + goto err; + } + + if ((dsa->pub_key = ASN1_INTEGER_to_BN(public_key, NULL)) == NULL) { + DSAerr(DSA_F_DSA_PUB_DECODE, DSA_R_BN_DECODE_ERROR); + goto err; + } + + ASN1_INTEGER_free(public_key); + EVP_PKEY_assign_DSA(pkey, dsa); + return 1; + + err: + ASN1_INTEGER_free(public_key); + DSA_free(dsa); + return 0; + +} + +static int dsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) +{ + DSA *dsa; + int ptype; + unsigned char *penc = NULL; + int penclen; + ASN1_STRING *str = NULL; + ASN1_INTEGER *pubint = NULL; + ASN1_OBJECT *aobj; + + dsa = pkey->pkey.dsa; + if (pkey->save_parameters && dsa->p && dsa->q && dsa->g) { + str = ASN1_STRING_new(); + if (str == NULL) { + DSAerr(DSA_F_DSA_PUB_ENCODE, ERR_R_MALLOC_FAILURE); + goto err; + } + str->length = i2d_DSAparams(dsa, &str->data); + if (str->length <= 0) { + DSAerr(DSA_F_DSA_PUB_ENCODE, ERR_R_MALLOC_FAILURE); + goto err; + } + ptype = V_ASN1_SEQUENCE; + } else + ptype = V_ASN1_UNDEF; + + pubint = BN_to_ASN1_INTEGER(dsa->pub_key, NULL); + + if (pubint == NULL) { + DSAerr(DSA_F_DSA_PUB_ENCODE, ERR_R_MALLOC_FAILURE); + goto err; + } + + penclen = i2d_ASN1_INTEGER(pubint, &penc); + ASN1_INTEGER_free(pubint); + + if (penclen <= 0) { + DSAerr(DSA_F_DSA_PUB_ENCODE, ERR_R_MALLOC_FAILURE); + goto err; + } + + aobj = OBJ_nid2obj(EVP_PKEY_DSA); + if (aobj == NULL) + goto err; + + if (X509_PUBKEY_set0_param(pk, aobj, ptype, str, penc, penclen)) + return 1; + + err: + OPENSSL_free(penc); + ASN1_STRING_free(str); + + return 0; +} + +/* + * In PKCS#8 DSA: you just get a private key integer and parameters in the + * AlgorithmIdentifier the pubkey must be recalculated. + */ + +static int dsa_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8) +{ + const unsigned char *p, *pm; + int pklen, pmlen; + int ptype; + const void *pval; + const ASN1_STRING *pstr; + const X509_ALGOR *palg; + ASN1_INTEGER *privkey = NULL; + BN_CTX *ctx = NULL; + + DSA *dsa = NULL; + + int ret = 0; + + if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8)) + return 0; + X509_ALGOR_get0(NULL, &ptype, &pval, palg); + + if ((privkey = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL) + goto decerr; + if (privkey->type == V_ASN1_NEG_INTEGER || ptype != V_ASN1_SEQUENCE) + goto decerr; + + pstr = pval; + pm = pstr->data; + pmlen = pstr->length; + if ((dsa = d2i_DSAparams(NULL, &pm, pmlen)) == NULL) + goto decerr; + /* We have parameters now set private key */ + if ((dsa->priv_key = BN_secure_new()) == NULL + || !ASN1_INTEGER_to_BN(privkey, dsa->priv_key)) { + DSAerr(DSA_F_DSA_PRIV_DECODE, DSA_R_BN_ERROR); + goto dsaerr; + } + /* Calculate public key */ + if ((dsa->pub_key = BN_new()) == NULL) { + DSAerr(DSA_F_DSA_PRIV_DECODE, ERR_R_MALLOC_FAILURE); + goto dsaerr; + } + if ((ctx = BN_CTX_new()) == NULL) { + DSAerr(DSA_F_DSA_PRIV_DECODE, ERR_R_MALLOC_FAILURE); + goto dsaerr; + } + + BN_set_flags(dsa->priv_key, BN_FLG_CONSTTIME); + if (!BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx)) { + DSAerr(DSA_F_DSA_PRIV_DECODE, DSA_R_BN_ERROR); + goto dsaerr; + } + + EVP_PKEY_assign_DSA(pkey, dsa); + + ret = 1; + goto done; + + decerr: + DSAerr(DSA_F_DSA_PRIV_DECODE, DSA_R_DECODE_ERROR); + dsaerr: + DSA_free(dsa); + done: + BN_CTX_free(ctx); + ASN1_STRING_clear_free(privkey); + return ret; +} + +static int dsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) +{ + ASN1_STRING *params = NULL; + ASN1_INTEGER *prkey = NULL; + unsigned char *dp = NULL; + int dplen; + + if (!pkey->pkey.dsa || !pkey->pkey.dsa->priv_key) { + DSAerr(DSA_F_DSA_PRIV_ENCODE, DSA_R_MISSING_PARAMETERS); + goto err; + } + + params = ASN1_STRING_new(); + + if (params == NULL) { + DSAerr(DSA_F_DSA_PRIV_ENCODE, ERR_R_MALLOC_FAILURE); + goto err; + } + + params->length = i2d_DSAparams(pkey->pkey.dsa, ¶ms->data); + if (params->length <= 0) { + DSAerr(DSA_F_DSA_PRIV_ENCODE, ERR_R_MALLOC_FAILURE); + goto err; + } + params->type = V_ASN1_SEQUENCE; + + /* Get private key into integer */ + prkey = BN_to_ASN1_INTEGER(pkey->pkey.dsa->priv_key, NULL); + + if (!prkey) { + DSAerr(DSA_F_DSA_PRIV_ENCODE, DSA_R_BN_ERROR); + goto err; + } + + dplen = i2d_ASN1_INTEGER(prkey, &dp); + + ASN1_STRING_clear_free(prkey); + prkey = NULL; + + if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_dsa), 0, + V_ASN1_SEQUENCE, params, dp, dplen)) + goto err; + + return 1; + + err: + OPENSSL_free(dp); + ASN1_STRING_free(params); + ASN1_STRING_clear_free(prkey); + return 0; +} + +static int int_dsa_size(const EVP_PKEY *pkey) +{ + return DSA_size(pkey->pkey.dsa); +} + +static int dsa_bits(const EVP_PKEY *pkey) +{ + return DSA_bits(pkey->pkey.dsa); +} + +static int dsa_security_bits(const EVP_PKEY *pkey) +{ + return DSA_security_bits(pkey->pkey.dsa); +} + +static int dsa_missing_parameters(const EVP_PKEY *pkey) +{ + DSA *dsa; + dsa = pkey->pkey.dsa; + if (dsa == NULL || dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) + return 1; + return 0; +} + +static int dsa_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) +{ + BIGNUM *a; + + if (to->pkey.dsa == NULL) { + to->pkey.dsa = DSA_new(); + if (to->pkey.dsa == NULL) + return 0; + } + + if ((a = BN_dup(from->pkey.dsa->p)) == NULL) + return 0; + BN_free(to->pkey.dsa->p); + to->pkey.dsa->p = a; + + if ((a = BN_dup(from->pkey.dsa->q)) == NULL) + return 0; + BN_free(to->pkey.dsa->q); + to->pkey.dsa->q = a; + + if ((a = BN_dup(from->pkey.dsa->g)) == NULL) + return 0; + BN_free(to->pkey.dsa->g); + to->pkey.dsa->g = a; + return 1; +} + +static int dsa_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) +{ + if (BN_cmp(a->pkey.dsa->p, b->pkey.dsa->p) || + BN_cmp(a->pkey.dsa->q, b->pkey.dsa->q) || + BN_cmp(a->pkey.dsa->g, b->pkey.dsa->g)) + return 0; + else + return 1; +} + +static int dsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) +{ + if (BN_cmp(b->pkey.dsa->pub_key, a->pkey.dsa->pub_key) != 0) + return 0; + else + return 1; +} + +static void int_dsa_free(EVP_PKEY *pkey) +{ + DSA_free(pkey->pkey.dsa); +} + +static int do_dsa_print(BIO *bp, const DSA *x, int off, int ptype) +{ + int ret = 0; + const char *ktype = NULL; + const BIGNUM *priv_key, *pub_key; + + if (ptype == 2) + priv_key = x->priv_key; + else + priv_key = NULL; + + if (ptype > 0) + pub_key = x->pub_key; + else + pub_key = NULL; + + if (ptype == 2) + ktype = "Private-Key"; + else if (ptype == 1) + ktype = "Public-Key"; + else + ktype = "DSA-Parameters"; + + if (priv_key) { + if (!BIO_indent(bp, off, 128)) + goto err; + if (BIO_printf(bp, "%s: (%d bit)\n", ktype, BN_num_bits(x->p)) + <= 0) + goto err; + } + + if (!ASN1_bn_print(bp, "priv:", priv_key, NULL, off)) + goto err; + if (!ASN1_bn_print(bp, "pub: ", pub_key, NULL, off)) + goto err; + if (!ASN1_bn_print(bp, "P: ", x->p, NULL, off)) + goto err; + if (!ASN1_bn_print(bp, "Q: ", x->q, NULL, off)) + goto err; + if (!ASN1_bn_print(bp, "G: ", x->g, NULL, off)) + goto err; + ret = 1; + err: + return ret; +} + +static int dsa_param_decode(EVP_PKEY *pkey, + const unsigned char **pder, int derlen) +{ + DSA *dsa; + + if ((dsa = d2i_DSAparams(NULL, pder, derlen)) == NULL) { + DSAerr(DSA_F_DSA_PARAM_DECODE, ERR_R_DSA_LIB); + return 0; + } + EVP_PKEY_assign_DSA(pkey, dsa); + return 1; +} + +static int dsa_param_encode(const EVP_PKEY *pkey, unsigned char **pder) +{ + return i2d_DSAparams(pkey->pkey.dsa, pder); +} + +static int dsa_param_print(BIO *bp, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *ctx) +{ + return do_dsa_print(bp, pkey->pkey.dsa, indent, 0); +} + +static int dsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *ctx) +{ + return do_dsa_print(bp, pkey->pkey.dsa, indent, 1); +} + +static int dsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *ctx) +{ + return do_dsa_print(bp, pkey->pkey.dsa, indent, 2); +} + +static int old_dsa_priv_decode(EVP_PKEY *pkey, + const unsigned char **pder, int derlen) +{ + DSA *dsa; + + if ((dsa = d2i_DSAPrivateKey(NULL, pder, derlen)) == NULL) { + DSAerr(DSA_F_OLD_DSA_PRIV_DECODE, ERR_R_DSA_LIB); + return 0; + } + EVP_PKEY_assign_DSA(pkey, dsa); + return 1; +} + +static int old_dsa_priv_encode(const EVP_PKEY *pkey, unsigned char **pder) +{ + return i2d_DSAPrivateKey(pkey->pkey.dsa, pder); +} + +static int dsa_sig_print(BIO *bp, const X509_ALGOR *sigalg, + const ASN1_STRING *sig, int indent, ASN1_PCTX *pctx) +{ + DSA_SIG *dsa_sig; + const unsigned char *p; + + if (!sig) { + if (BIO_puts(bp, "\n") <= 0) + return 0; + else + return 1; + } + p = sig->data; + dsa_sig = d2i_DSA_SIG(NULL, &p, sig->length); + if (dsa_sig) { + int rv = 0; + const BIGNUM *r, *s; + + DSA_SIG_get0(dsa_sig, &r, &s); + + if (BIO_write(bp, "\n", 1) != 1) + goto err; + + if (!ASN1_bn_print(bp, "r: ", r, NULL, indent)) + goto err; + if (!ASN1_bn_print(bp, "s: ", s, NULL, indent)) + goto err; + rv = 1; + err: + DSA_SIG_free(dsa_sig); + return rv; + } + return X509_signature_dump(bp, sig, indent); +} + +static int dsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) +{ + switch (op) { + case ASN1_PKEY_CTRL_PKCS7_SIGN: + if (arg1 == 0) { + int snid, hnid; + X509_ALGOR *alg1, *alg2; + PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2); + if (alg1 == NULL || alg1->algorithm == NULL) + return -1; + hnid = OBJ_obj2nid(alg1->algorithm); + if (hnid == NID_undef) + return -1; + if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey))) + return -1; + X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0); + } + return 1; +#ifndef OPENSSL_NO_CMS + case ASN1_PKEY_CTRL_CMS_SIGN: + if (arg1 == 0) { + int snid, hnid; + X509_ALGOR *alg1, *alg2; + CMS_SignerInfo_get0_algs(arg2, NULL, NULL, &alg1, &alg2); + if (alg1 == NULL || alg1->algorithm == NULL) + return -1; + hnid = OBJ_obj2nid(alg1->algorithm); + if (hnid == NID_undef) + return -1; + if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey))) + return -1; + X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0); + } + return 1; + + case ASN1_PKEY_CTRL_CMS_RI_TYPE: + *(int *)arg2 = CMS_RECIPINFO_NONE; + return 1; +#endif + + case ASN1_PKEY_CTRL_DEFAULT_MD_NID: + *(int *)arg2 = NID_sha256; + return 2; + + default: + return -2; + + } + +} + +/* NB these are sorted in pkey_id order, lowest first */ + +const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[5] = { + + { + EVP_PKEY_DSA2, + EVP_PKEY_DSA, + ASN1_PKEY_ALIAS}, + + { + EVP_PKEY_DSA1, + EVP_PKEY_DSA, + ASN1_PKEY_ALIAS}, + + { + EVP_PKEY_DSA4, + EVP_PKEY_DSA, + ASN1_PKEY_ALIAS}, + + { + EVP_PKEY_DSA3, + EVP_PKEY_DSA, + ASN1_PKEY_ALIAS}, + + { + EVP_PKEY_DSA, + EVP_PKEY_DSA, + 0, + + "DSA", + "OpenSSL DSA method", + + dsa_pub_decode, + dsa_pub_encode, + dsa_pub_cmp, + dsa_pub_print, + + dsa_priv_decode, + dsa_priv_encode, + dsa_priv_print, + + int_dsa_size, + dsa_bits, + dsa_security_bits, + + dsa_param_decode, + dsa_param_encode, + dsa_missing_parameters, + dsa_copy_parameters, + dsa_cmp_parameters, + dsa_param_print, + dsa_sig_print, + + int_dsa_free, + dsa_pkey_ctrl, + old_dsa_priv_decode, + old_dsa_priv_encode} +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_asn1.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_asn1.c new file mode 100644 index 000000000..6499e87ef --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_asn1.c @@ -0,0 +1,155 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include "dsa_locl.h" +#include +#include +#include + +ASN1_SEQUENCE(DSA_SIG) = { + ASN1_SIMPLE(DSA_SIG, r, CBIGNUM), + ASN1_SIMPLE(DSA_SIG, s, CBIGNUM) +} static_ASN1_SEQUENCE_END(DSA_SIG) + +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA_SIG, DSA_SIG, DSA_SIG) + +DSA_SIG *DSA_SIG_new(void) +{ + DSA_SIG *sig = OPENSSL_zalloc(sizeof(*sig)); + if (sig == NULL) + DSAerr(DSA_F_DSA_SIG_NEW, ERR_R_MALLOC_FAILURE); + return sig; +} + +void DSA_SIG_free(DSA_SIG *sig) +{ + if (sig == NULL) + return; + BN_clear_free(sig->r); + BN_clear_free(sig->s); + OPENSSL_free(sig); +} + +void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) +{ + if (pr != NULL) + *pr = sig->r; + if (ps != NULL) + *ps = sig->s; +} + +int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s) +{ + if (r == NULL || s == NULL) + return 0; + BN_clear_free(sig->r); + BN_clear_free(sig->s); + sig->r = r; + sig->s = s; + return 1; +} + +/* Override the default free and new methods */ +static int dsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + if (operation == ASN1_OP_NEW_PRE) { + *pval = (ASN1_VALUE *)DSA_new(); + if (*pval != NULL) + return 2; + return 0; + } else if (operation == ASN1_OP_FREE_PRE) { + DSA_free((DSA *)*pval); + *pval = NULL; + return 2; + } + return 1; +} + +ASN1_SEQUENCE_cb(DSAPrivateKey, dsa_cb) = { + ASN1_EMBED(DSA, version, INT32), + ASN1_SIMPLE(DSA, p, BIGNUM), + ASN1_SIMPLE(DSA, q, BIGNUM), + ASN1_SIMPLE(DSA, g, BIGNUM), + ASN1_SIMPLE(DSA, pub_key, BIGNUM), + ASN1_SIMPLE(DSA, priv_key, CBIGNUM) +} static_ASN1_SEQUENCE_END_cb(DSA, DSAPrivateKey) + +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA, DSAPrivateKey, DSAPrivateKey) + +ASN1_SEQUENCE_cb(DSAparams, dsa_cb) = { + ASN1_SIMPLE(DSA, p, BIGNUM), + ASN1_SIMPLE(DSA, q, BIGNUM), + ASN1_SIMPLE(DSA, g, BIGNUM), +} static_ASN1_SEQUENCE_END_cb(DSA, DSAparams) + +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA, DSAparams, DSAparams) + +ASN1_SEQUENCE_cb(DSAPublicKey, dsa_cb) = { + ASN1_SIMPLE(DSA, pub_key, BIGNUM), + ASN1_SIMPLE(DSA, p, BIGNUM), + ASN1_SIMPLE(DSA, q, BIGNUM), + ASN1_SIMPLE(DSA, g, BIGNUM) +} static_ASN1_SEQUENCE_END_cb(DSA, DSAPublicKey) + +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA, DSAPublicKey, DSAPublicKey) + +DSA *DSAparams_dup(DSA *dsa) +{ + return ASN1_item_dup(ASN1_ITEM_rptr(DSAparams), dsa); +} + +int DSA_sign(int type, const unsigned char *dgst, int dlen, + unsigned char *sig, unsigned int *siglen, DSA *dsa) +{ + DSA_SIG *s; + + s = DSA_do_sign(dgst, dlen, dsa); + if (s == NULL) { + *siglen = 0; + return 0; + } + *siglen = i2d_DSA_SIG(s, &sig); + DSA_SIG_free(s); + return 1; +} + +/* data has already been hashed (probably with SHA or SHA-1). */ +/*- + * returns + * 1: correct signature + * 0: incorrect signature + * -1: error + */ +int DSA_verify(int type, const unsigned char *dgst, int dgst_len, + const unsigned char *sigbuf, int siglen, DSA *dsa) +{ + DSA_SIG *s; + const unsigned char *p = sigbuf; + unsigned char *der = NULL; + int derlen = -1; + int ret = -1; + + s = DSA_SIG_new(); + if (s == NULL) + return ret; + if (d2i_DSA_SIG(&s, &p, siglen) == NULL) + goto err; + /* Ensure signature uses DER and doesn't have trailing garbage */ + derlen = i2d_DSA_SIG(s, &der); + if (derlen != siglen || memcmp(sigbuf, der, derlen)) + goto err; + ret = DSA_do_verify(dgst, dgst_len, s, dsa); + err: + OPENSSL_clear_free(der, derlen); + DSA_SIG_free(s); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_depr.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_depr.c new file mode 100644 index 000000000..f51aea749 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_depr.c @@ -0,0 +1,62 @@ +/* + * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This file contains deprecated function(s) that are now wrappers to the new + * version(s). + */ + +/* + * Parameter generation follows the updated Appendix 2.2 for FIPS PUB 186, + * also Appendix 2.2 of FIPS PUB 186-1 (i.e. use SHA as defined in FIPS PUB + * 180-1) + */ +#define xxxHASH EVP_sha1() + +#include +#if OPENSSL_API_COMPAT >= 0x00908000L +NON_EMPTY_TRANSLATION_UNIT +#else + +# include +# include +# include "internal/cryptlib.h" +# include +# include +# include +# include + +DSA *DSA_generate_parameters(int bits, + unsigned char *seed_in, int seed_len, + int *counter_ret, unsigned long *h_ret, + void (*callback) (int, int, void *), + void *cb_arg) +{ + BN_GENCB *cb; + DSA *ret; + + if ((ret = DSA_new()) == NULL) + return NULL; + cb = BN_GENCB_new(); + if (cb == NULL) + goto err; + + BN_GENCB_set_old(cb, callback, cb_arg); + + if (DSA_generate_parameters_ex(ret, bits, seed_in, seed_len, + counter_ret, h_ret, cb)) { + BN_GENCB_free(cb); + return ret; + } + BN_GENCB_free(cb); +err: + DSA_free(ret); + return NULL; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_err.c new file mode 100644 index 000000000..8f97f6f3f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_err.c @@ -0,0 +1,76 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA DSA_str_functs[] = { + {ERR_PACK(ERR_LIB_DSA, DSA_F_DSAPARAMS_PRINT, 0), "DSAparams_print"}, + {ERR_PACK(ERR_LIB_DSA, DSA_F_DSAPARAMS_PRINT_FP, 0), "DSAparams_print_fp"}, + {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_BUILTIN_PARAMGEN, 0), + "dsa_builtin_paramgen"}, + {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_BUILTIN_PARAMGEN2, 0), + "dsa_builtin_paramgen2"}, + {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_DO_SIGN, 0), "DSA_do_sign"}, + {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_DO_VERIFY, 0), "DSA_do_verify"}, + {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_METH_DUP, 0), "DSA_meth_dup"}, + {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_METH_NEW, 0), "DSA_meth_new"}, + {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_METH_SET1_NAME, 0), "DSA_meth_set1_name"}, + {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_NEW_METHOD, 0), "DSA_new_method"}, + {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_PARAM_DECODE, 0), "dsa_param_decode"}, + {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_PRINT_FP, 0), "DSA_print_fp"}, + {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_PRIV_DECODE, 0), "dsa_priv_decode"}, + {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_PRIV_ENCODE, 0), "dsa_priv_encode"}, + {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_PUB_DECODE, 0), "dsa_pub_decode"}, + {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_PUB_ENCODE, 0), "dsa_pub_encode"}, + {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_SIGN, 0), "DSA_sign"}, + {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_SIGN_SETUP, 0), "DSA_sign_setup"}, + {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_SIG_NEW, 0), "DSA_SIG_new"}, + {ERR_PACK(ERR_LIB_DSA, DSA_F_OLD_DSA_PRIV_DECODE, 0), + "old_dsa_priv_decode"}, + {ERR_PACK(ERR_LIB_DSA, DSA_F_PKEY_DSA_CTRL, 0), "pkey_dsa_ctrl"}, + {ERR_PACK(ERR_LIB_DSA, DSA_F_PKEY_DSA_CTRL_STR, 0), "pkey_dsa_ctrl_str"}, + {ERR_PACK(ERR_LIB_DSA, DSA_F_PKEY_DSA_KEYGEN, 0), "pkey_dsa_keygen"}, + {0, NULL} +}; + +static const ERR_STRING_DATA DSA_str_reasons[] = { + {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_BAD_Q_VALUE), "bad q value"}, + {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_BN_DECODE_ERROR), "bn decode error"}, + {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_BN_ERROR), "bn error"}, + {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_DECODE_ERROR), "decode error"}, + {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_INVALID_DIGEST_TYPE), + "invalid digest type"}, + {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_INVALID_PARAMETERS), "invalid parameters"}, + {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_MISSING_PARAMETERS), "missing parameters"}, + {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_MODULUS_TOO_LARGE), "modulus too large"}, + {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_NO_PARAMETERS_SET), "no parameters set"}, + {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_PARAMETER_ENCODING_ERROR), + "parameter encoding error"}, + {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_Q_NOT_PRIME), "q not prime"}, + {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_SEED_LEN_SMALL), + "seed_len is less than the length of q"}, + {0, NULL} +}; + +#endif + +int ERR_load_DSA_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(DSA_str_functs[0].error) == NULL) { + ERR_load_strings_const(DSA_str_functs); + ERR_load_strings_const(DSA_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_gen.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_gen.c new file mode 100644 index 000000000..383d853b6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_gen.c @@ -0,0 +1,616 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Parameter generation follows the updated Appendix 2.2 for FIPS PUB 186, + * also Appendix 2.2 of FIPS PUB 186-1 (i.e. use SHA as defined in FIPS PUB + * 180-1) + */ +#define xxxHASH EVP_sha1() + +#include +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "dsa_locl.h" + +int DSA_generate_parameters_ex(DSA *ret, int bits, + const unsigned char *seed_in, int seed_len, + int *counter_ret, unsigned long *h_ret, + BN_GENCB *cb) +{ + if (ret->meth->dsa_paramgen) + return ret->meth->dsa_paramgen(ret, bits, seed_in, seed_len, + counter_ret, h_ret, cb); + else { + const EVP_MD *evpmd = bits >= 2048 ? EVP_sha256() : EVP_sha1(); + size_t qbits = EVP_MD_size(evpmd) * 8; + + return dsa_builtin_paramgen(ret, bits, qbits, evpmd, + seed_in, seed_len, NULL, counter_ret, + h_ret, cb); + } +} + +int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits, + const EVP_MD *evpmd, const unsigned char *seed_in, + size_t seed_len, unsigned char *seed_out, + int *counter_ret, unsigned long *h_ret, BN_GENCB *cb) +{ + int ok = 0; + unsigned char seed[SHA256_DIGEST_LENGTH]; + unsigned char md[SHA256_DIGEST_LENGTH]; + unsigned char buf[SHA256_DIGEST_LENGTH], buf2[SHA256_DIGEST_LENGTH]; + BIGNUM *r0, *W, *X, *c, *test; + BIGNUM *g = NULL, *q = NULL, *p = NULL; + BN_MONT_CTX *mont = NULL; + int i, k, n = 0, m = 0, qsize = qbits >> 3; + int counter = 0; + int r = 0; + BN_CTX *ctx = NULL; + unsigned int h = 2; + + if (qsize != SHA_DIGEST_LENGTH && qsize != SHA224_DIGEST_LENGTH && + qsize != SHA256_DIGEST_LENGTH) + /* invalid q size */ + return 0; + + if (evpmd == NULL) { + if (qsize == SHA_DIGEST_LENGTH) + evpmd = EVP_sha1(); + else if (qsize == SHA224_DIGEST_LENGTH) + evpmd = EVP_sha224(); + else + evpmd = EVP_sha256(); + } else { + qsize = EVP_MD_size(evpmd); + } + + if (bits < 512) + bits = 512; + + bits = (bits + 63) / 64 * 64; + + if (seed_in != NULL) { + if (seed_len < (size_t)qsize) { + DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN, DSA_R_SEED_LEN_SMALL); + return 0; + } + if (seed_len > (size_t)qsize) { + /* Only consume as much seed as is expected. */ + seed_len = qsize; + } + memcpy(seed, seed_in, seed_len); + } + + if ((mont = BN_MONT_CTX_new()) == NULL) + goto err; + + if ((ctx = BN_CTX_new()) == NULL) + goto err; + + BN_CTX_start(ctx); + + r0 = BN_CTX_get(ctx); + g = BN_CTX_get(ctx); + W = BN_CTX_get(ctx); + q = BN_CTX_get(ctx); + X = BN_CTX_get(ctx); + c = BN_CTX_get(ctx); + p = BN_CTX_get(ctx); + test = BN_CTX_get(ctx); + + if (test == NULL) + goto err; + + if (!BN_lshift(test, BN_value_one(), bits - 1)) + goto err; + + for (;;) { + for (;;) { /* find q */ + int use_random_seed = (seed_in == NULL); + + /* step 1 */ + if (!BN_GENCB_call(cb, 0, m++)) + goto err; + + if (use_random_seed) { + if (RAND_bytes(seed, qsize) <= 0) + goto err; + } else { + /* If we come back through, use random seed next time. */ + seed_in = NULL; + } + memcpy(buf, seed, qsize); + memcpy(buf2, seed, qsize); + /* precompute "SEED + 1" for step 7: */ + for (i = qsize - 1; i >= 0; i--) { + buf[i]++; + if (buf[i] != 0) + break; + } + + /* step 2 */ + if (!EVP_Digest(seed, qsize, md, NULL, evpmd, NULL)) + goto err; + if (!EVP_Digest(buf, qsize, buf2, NULL, evpmd, NULL)) + goto err; + for (i = 0; i < qsize; i++) + md[i] ^= buf2[i]; + + /* step 3 */ + md[0] |= 0x80; + md[qsize - 1] |= 0x01; + if (!BN_bin2bn(md, qsize, q)) + goto err; + + /* step 4 */ + r = BN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx, + use_random_seed, cb); + if (r > 0) + break; + if (r != 0) + goto err; + + /* do a callback call */ + /* step 5 */ + } + + if (!BN_GENCB_call(cb, 2, 0)) + goto err; + if (!BN_GENCB_call(cb, 3, 0)) + goto err; + + /* step 6 */ + counter = 0; + /* "offset = 2" */ + + n = (bits - 1) / 160; + + for (;;) { + if ((counter != 0) && !BN_GENCB_call(cb, 0, counter)) + goto err; + + /* step 7 */ + BN_zero(W); + /* now 'buf' contains "SEED + offset - 1" */ + for (k = 0; k <= n; k++) { + /* + * obtain "SEED + offset + k" by incrementing: + */ + for (i = qsize - 1; i >= 0; i--) { + buf[i]++; + if (buf[i] != 0) + break; + } + + if (!EVP_Digest(buf, qsize, md, NULL, evpmd, NULL)) + goto err; + + /* step 8 */ + if (!BN_bin2bn(md, qsize, r0)) + goto err; + if (!BN_lshift(r0, r0, (qsize << 3) * k)) + goto err; + if (!BN_add(W, W, r0)) + goto err; + } + + /* more of step 8 */ + if (!BN_mask_bits(W, bits - 1)) + goto err; + if (!BN_copy(X, W)) + goto err; + if (!BN_add(X, X, test)) + goto err; + + /* step 9 */ + if (!BN_lshift1(r0, q)) + goto err; + if (!BN_mod(c, X, r0, ctx)) + goto err; + if (!BN_sub(r0, c, BN_value_one())) + goto err; + if (!BN_sub(p, X, r0)) + goto err; + + /* step 10 */ + if (BN_cmp(p, test) >= 0) { + /* step 11 */ + r = BN_is_prime_fasttest_ex(p, DSS_prime_checks, ctx, 1, cb); + if (r > 0) + goto end; /* found it */ + if (r != 0) + goto err; + } + + /* step 13 */ + counter++; + /* "offset = offset + n + 1" */ + + /* step 14 */ + if (counter >= 4096) + break; + } + } + end: + if (!BN_GENCB_call(cb, 2, 1)) + goto err; + + /* We now need to generate g */ + /* Set r0=(p-1)/q */ + if (!BN_sub(test, p, BN_value_one())) + goto err; + if (!BN_div(r0, NULL, test, q, ctx)) + goto err; + + if (!BN_set_word(test, h)) + goto err; + if (!BN_MONT_CTX_set(mont, p, ctx)) + goto err; + + for (;;) { + /* g=test^r0%p */ + if (!BN_mod_exp_mont(g, test, r0, p, ctx, mont)) + goto err; + if (!BN_is_one(g)) + break; + if (!BN_add(test, test, BN_value_one())) + goto err; + h++; + } + + if (!BN_GENCB_call(cb, 3, 1)) + goto err; + + ok = 1; + err: + if (ok) { + BN_free(ret->p); + BN_free(ret->q); + BN_free(ret->g); + ret->p = BN_dup(p); + ret->q = BN_dup(q); + ret->g = BN_dup(g); + if (ret->p == NULL || ret->q == NULL || ret->g == NULL) { + ok = 0; + goto err; + } + if (counter_ret != NULL) + *counter_ret = counter; + if (h_ret != NULL) + *h_ret = h; + if (seed_out) + memcpy(seed_out, seed, qsize); + } + if (ctx) + BN_CTX_end(ctx); + BN_CTX_free(ctx); + BN_MONT_CTX_free(mont); + return ok; +} + +/* + * This is a parameter generation algorithm for the DSA2 algorithm as + * described in FIPS 186-3. + */ + +int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N, + const EVP_MD *evpmd, const unsigned char *seed_in, + size_t seed_len, int idx, unsigned char *seed_out, + int *counter_ret, unsigned long *h_ret, + BN_GENCB *cb) +{ + int ok = -1; + unsigned char *seed = NULL, *seed_tmp = NULL; + unsigned char md[EVP_MAX_MD_SIZE]; + int mdsize; + BIGNUM *r0, *W, *X, *c, *test; + BIGNUM *g = NULL, *q = NULL, *p = NULL; + BN_MONT_CTX *mont = NULL; + int i, k, n = 0, m = 0, qsize = N >> 3; + int counter = 0; + int r = 0; + BN_CTX *ctx = NULL; + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); + unsigned int h = 2; + + if (mctx == NULL) + goto err; + + /* make sure L > N, otherwise we'll get trapped in an infinite loop */ + if (L <= N) { + DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN2, DSA_R_INVALID_PARAMETERS); + goto err; + } + + if (evpmd == NULL) { + if (N == 160) + evpmd = EVP_sha1(); + else if (N == 224) + evpmd = EVP_sha224(); + else + evpmd = EVP_sha256(); + } + + mdsize = EVP_MD_size(evpmd); + /* If unverifiable g generation only don't need seed */ + if (!ret->p || !ret->q || idx >= 0) { + if (seed_len == 0) + seed_len = mdsize; + + seed = OPENSSL_malloc(seed_len); + + if (seed_out) + seed_tmp = seed_out; + else + seed_tmp = OPENSSL_malloc(seed_len); + + if (seed == NULL || seed_tmp == NULL) + goto err; + + if (seed_in) + memcpy(seed, seed_in, seed_len); + + } + + if ((ctx = BN_CTX_new()) == NULL) + goto err; + + if ((mont = BN_MONT_CTX_new()) == NULL) + goto err; + + BN_CTX_start(ctx); + r0 = BN_CTX_get(ctx); + g = BN_CTX_get(ctx); + W = BN_CTX_get(ctx); + X = BN_CTX_get(ctx); + c = BN_CTX_get(ctx); + test = BN_CTX_get(ctx); + if (test == NULL) + goto err; + + /* if p, q already supplied generate g only */ + if (ret->p && ret->q) { + p = ret->p; + q = ret->q; + if (idx >= 0) + memcpy(seed_tmp, seed, seed_len); + goto g_only; + } else { + p = BN_CTX_get(ctx); + q = BN_CTX_get(ctx); + if (q == NULL) + goto err; + } + + if (!BN_lshift(test, BN_value_one(), L - 1)) + goto err; + for (;;) { + for (;;) { /* find q */ + unsigned char *pmd; + /* step 1 */ + if (!BN_GENCB_call(cb, 0, m++)) + goto err; + + if (!seed_in) { + if (RAND_bytes(seed, seed_len) <= 0) + goto err; + } + /* step 2 */ + if (!EVP_Digest(seed, seed_len, md, NULL, evpmd, NULL)) + goto err; + /* Take least significant bits of md */ + if (mdsize > qsize) + pmd = md + mdsize - qsize; + else + pmd = md; + + if (mdsize < qsize) + memset(md + mdsize, 0, qsize - mdsize); + + /* step 3 */ + pmd[0] |= 0x80; + pmd[qsize - 1] |= 0x01; + if (!BN_bin2bn(pmd, qsize, q)) + goto err; + + /* step 4 */ + r = BN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx, + seed_in ? 1 : 0, cb); + if (r > 0) + break; + if (r != 0) + goto err; + /* Provided seed didn't produce a prime: error */ + if (seed_in) { + ok = 0; + DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN2, DSA_R_Q_NOT_PRIME); + goto err; + } + + /* do a callback call */ + /* step 5 */ + } + /* Copy seed to seed_out before we mess with it */ + if (seed_out) + memcpy(seed_out, seed, seed_len); + + if (!BN_GENCB_call(cb, 2, 0)) + goto err; + if (!BN_GENCB_call(cb, 3, 0)) + goto err; + + /* step 6 */ + counter = 0; + /* "offset = 1" */ + + n = (L - 1) / (mdsize << 3); + + for (;;) { + if ((counter != 0) && !BN_GENCB_call(cb, 0, counter)) + goto err; + + /* step 7 */ + BN_zero(W); + /* now 'buf' contains "SEED + offset - 1" */ + for (k = 0; k <= n; k++) { + /* + * obtain "SEED + offset + k" by incrementing: + */ + for (i = seed_len - 1; i >= 0; i--) { + seed[i]++; + if (seed[i] != 0) + break; + } + + if (!EVP_Digest(seed, seed_len, md, NULL, evpmd, NULL)) + goto err; + + /* step 8 */ + if (!BN_bin2bn(md, mdsize, r0)) + goto err; + if (!BN_lshift(r0, r0, (mdsize << 3) * k)) + goto err; + if (!BN_add(W, W, r0)) + goto err; + } + + /* more of step 8 */ + if (!BN_mask_bits(W, L - 1)) + goto err; + if (!BN_copy(X, W)) + goto err; + if (!BN_add(X, X, test)) + goto err; + + /* step 9 */ + if (!BN_lshift1(r0, q)) + goto err; + if (!BN_mod(c, X, r0, ctx)) + goto err; + if (!BN_sub(r0, c, BN_value_one())) + goto err; + if (!BN_sub(p, X, r0)) + goto err; + + /* step 10 */ + if (BN_cmp(p, test) >= 0) { + /* step 11 */ + r = BN_is_prime_fasttest_ex(p, DSS_prime_checks, ctx, 1, cb); + if (r > 0) + goto end; /* found it */ + if (r != 0) + goto err; + } + + /* step 13 */ + counter++; + /* "offset = offset + n + 1" */ + + /* step 14 */ + if (counter >= (int)(4 * L)) + break; + } + if (seed_in) { + ok = 0; + DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN2, DSA_R_INVALID_PARAMETERS); + goto err; + } + } + end: + if (!BN_GENCB_call(cb, 2, 1)) + goto err; + + g_only: + + /* We now need to generate g */ + /* Set r0=(p-1)/q */ + if (!BN_sub(test, p, BN_value_one())) + goto err; + if (!BN_div(r0, NULL, test, q, ctx)) + goto err; + + if (idx < 0) { + if (!BN_set_word(test, h)) + goto err; + } else + h = 1; + if (!BN_MONT_CTX_set(mont, p, ctx)) + goto err; + + for (;;) { + static const unsigned char ggen[4] = { 0x67, 0x67, 0x65, 0x6e }; + if (idx >= 0) { + md[0] = idx & 0xff; + md[1] = (h >> 8) & 0xff; + md[2] = h & 0xff; + if (!EVP_DigestInit_ex(mctx, evpmd, NULL)) + goto err; + if (!EVP_DigestUpdate(mctx, seed_tmp, seed_len)) + goto err; + if (!EVP_DigestUpdate(mctx, ggen, sizeof(ggen))) + goto err; + if (!EVP_DigestUpdate(mctx, md, 3)) + goto err; + if (!EVP_DigestFinal_ex(mctx, md, NULL)) + goto err; + if (!BN_bin2bn(md, mdsize, test)) + goto err; + } + /* g=test^r0%p */ + if (!BN_mod_exp_mont(g, test, r0, p, ctx, mont)) + goto err; + if (!BN_is_one(g)) + break; + if (idx < 0 && !BN_add(test, test, BN_value_one())) + goto err; + h++; + if (idx >= 0 && h > 0xffff) + goto err; + } + + if (!BN_GENCB_call(cb, 3, 1)) + goto err; + + ok = 1; + err: + if (ok == 1) { + if (p != ret->p) { + BN_free(ret->p); + ret->p = BN_dup(p); + } + if (q != ret->q) { + BN_free(ret->q); + ret->q = BN_dup(q); + } + BN_free(ret->g); + ret->g = BN_dup(g); + if (ret->p == NULL || ret->q == NULL || ret->g == NULL) { + ok = -1; + goto err; + } + if (counter_ret != NULL) + *counter_ret = counter; + if (h_ret != NULL) + *h_ret = h; + } + OPENSSL_free(seed); + if (seed_out != seed_tmp) + OPENSSL_free(seed_tmp); + if (ctx) + BN_CTX_end(ctx); + BN_CTX_free(ctx); + BN_MONT_CTX_free(mont); + EVP_MD_CTX_free(mctx); + return ok; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_key.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_key.c new file mode 100644 index 000000000..a48af5849 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_key.c @@ -0,0 +1,77 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include +#include "dsa_locl.h" + +static int dsa_builtin_keygen(DSA *dsa); + +int DSA_generate_key(DSA *dsa) +{ + if (dsa->meth->dsa_keygen) + return dsa->meth->dsa_keygen(dsa); + return dsa_builtin_keygen(dsa); +} + +static int dsa_builtin_keygen(DSA *dsa) +{ + int ok = 0; + BN_CTX *ctx = NULL; + BIGNUM *pub_key = NULL, *priv_key = NULL; + + if ((ctx = BN_CTX_new()) == NULL) + goto err; + + if (dsa->priv_key == NULL) { + if ((priv_key = BN_secure_new()) == NULL) + goto err; + } else + priv_key = dsa->priv_key; + + do + if (!BN_priv_rand_range(priv_key, dsa->q)) + goto err; + while (BN_is_zero(priv_key)) ; + + if (dsa->pub_key == NULL) { + if ((pub_key = BN_new()) == NULL) + goto err; + } else + pub_key = dsa->pub_key; + + { + BIGNUM *prk = BN_new(); + + if (prk == NULL) + goto err; + BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME); + + if (!BN_mod_exp(pub_key, dsa->g, prk, dsa->p, ctx)) { + BN_free(prk); + goto err; + } + /* We MUST free prk before any further use of priv_key */ + BN_free(prk); + } + + dsa->priv_key = priv_key; + dsa->pub_key = pub_key; + ok = 1; + + err: + if (pub_key != dsa->pub_key) + BN_free(pub_key); + if (priv_key != dsa->priv_key) + BN_free(priv_key); + BN_CTX_free(ctx); + return ok; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_lib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_lib.c new file mode 100644 index 000000000..1048601be --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_lib.c @@ -0,0 +1,358 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include "internal/refcount.h" +#include +#include "dsa_locl.h" +#include +#include +#include + +DSA *DSA_new(void) +{ + return DSA_new_method(NULL); +} + +int DSA_set_method(DSA *dsa, const DSA_METHOD *meth) +{ + /* + * NB: The caller is specifically setting a method, so it's not up to us + * to deal with which ENGINE it comes from. + */ + const DSA_METHOD *mtmp; + mtmp = dsa->meth; + if (mtmp->finish) + mtmp->finish(dsa); +#ifndef OPENSSL_NO_ENGINE + ENGINE_finish(dsa->engine); + dsa->engine = NULL; +#endif + dsa->meth = meth; + if (meth->init) + meth->init(dsa); + return 1; +} + +const DSA_METHOD *DSA_get_method(DSA *d) +{ + return d->meth; +} + +DSA *DSA_new_method(ENGINE *engine) +{ + DSA *ret = OPENSSL_zalloc(sizeof(*ret)); + + if (ret == NULL) { + DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_MALLOC_FAILURE); + return NULL; + } + + ret->references = 1; + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) { + DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ret); + return NULL; + } + + ret->meth = DSA_get_default_method(); +#ifndef OPENSSL_NO_ENGINE + ret->flags = ret->meth->flags & ~DSA_FLAG_NON_FIPS_ALLOW; /* early default init */ + if (engine) { + if (!ENGINE_init(engine)) { + DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_ENGINE_LIB); + goto err; + } + ret->engine = engine; + } else + ret->engine = ENGINE_get_default_DSA(); + if (ret->engine) { + ret->meth = ENGINE_get_DSA(ret->engine); + if (ret->meth == NULL) { + DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_ENGINE_LIB); + goto err; + } + } +#endif + + ret->flags = ret->meth->flags & ~DSA_FLAG_NON_FIPS_ALLOW; + + if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DSA, ret, &ret->ex_data)) + goto err; + + if ((ret->meth->init != NULL) && !ret->meth->init(ret)) { + DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_INIT_FAIL); + goto err; + } + + return ret; + + err: + DSA_free(ret); + return NULL; +} + +void DSA_free(DSA *r) +{ + int i; + + if (r == NULL) + return; + + CRYPTO_DOWN_REF(&r->references, &i, r->lock); + REF_PRINT_COUNT("DSA", r); + if (i > 0) + return; + REF_ASSERT_ISNT(i < 0); + + if (r->meth != NULL && r->meth->finish != NULL) + r->meth->finish(r); +#ifndef OPENSSL_NO_ENGINE + ENGINE_finish(r->engine); +#endif + + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DSA, r, &r->ex_data); + + CRYPTO_THREAD_lock_free(r->lock); + + BN_clear_free(r->p); + BN_clear_free(r->q); + BN_clear_free(r->g); + BN_clear_free(r->pub_key); + BN_clear_free(r->priv_key); + OPENSSL_free(r); +} + +int DSA_up_ref(DSA *r) +{ + int i; + + if (CRYPTO_UP_REF(&r->references, &i, r->lock) <= 0) + return 0; + + REF_PRINT_COUNT("DSA", r); + REF_ASSERT_ISNT(i < 2); + return ((i > 1) ? 1 : 0); +} + +int DSA_size(const DSA *r) +{ + int ret, i; + ASN1_INTEGER bs; + unsigned char buf[4]; /* 4 bytes looks really small. However, + * i2d_ASN1_INTEGER() will not look beyond + * the first byte, as long as the second + * parameter is NULL. */ + + i = BN_num_bits(r->q); + bs.length = (i + 7) / 8; + bs.data = buf; + bs.type = V_ASN1_INTEGER; + /* If the top bit is set the asn1 encoding is 1 larger. */ + buf[0] = 0xff; + + i = i2d_ASN1_INTEGER(&bs, NULL); + i += i; /* r and s */ + ret = ASN1_object_size(1, i, V_ASN1_SEQUENCE); + return ret; +} + +int DSA_set_ex_data(DSA *d, int idx, void *arg) +{ + return CRYPTO_set_ex_data(&d->ex_data, idx, arg); +} + +void *DSA_get_ex_data(DSA *d, int idx) +{ + return CRYPTO_get_ex_data(&d->ex_data, idx); +} + +int DSA_security_bits(const DSA *d) +{ + if (d->p && d->q) + return BN_security_bits(BN_num_bits(d->p), BN_num_bits(d->q)); + return -1; +} + +#ifndef OPENSSL_NO_DH +DH *DSA_dup_DH(const DSA *r) +{ + /* + * DSA has p, q, g, optional pub_key, optional priv_key. DH has p, + * optional length, g, optional pub_key, optional priv_key, optional q. + */ + + DH *ret = NULL; + BIGNUM *p = NULL, *q = NULL, *g = NULL, *pub_key = NULL, *priv_key = NULL; + + if (r == NULL) + goto err; + ret = DH_new(); + if (ret == NULL) + goto err; + if (r->p != NULL || r->g != NULL || r->q != NULL) { + if (r->p == NULL || r->g == NULL || r->q == NULL) { + /* Shouldn't happen */ + goto err; + } + p = BN_dup(r->p); + g = BN_dup(r->g); + q = BN_dup(r->q); + if (p == NULL || g == NULL || q == NULL || !DH_set0_pqg(ret, p, q, g)) + goto err; + p = g = q = NULL; + } + + if (r->pub_key != NULL) { + pub_key = BN_dup(r->pub_key); + if (pub_key == NULL) + goto err; + if (r->priv_key != NULL) { + priv_key = BN_dup(r->priv_key); + if (priv_key == NULL) + goto err; + } + if (!DH_set0_key(ret, pub_key, priv_key)) + goto err; + } else if (r->priv_key != NULL) { + /* Shouldn't happen */ + goto err; + } + + return ret; + + err: + BN_free(p); + BN_free(g); + BN_free(q); + BN_free(pub_key); + BN_free(priv_key); + DH_free(ret); + return NULL; +} +#endif + +void DSA_get0_pqg(const DSA *d, + const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) +{ + if (p != NULL) + *p = d->p; + if (q != NULL) + *q = d->q; + if (g != NULL) + *g = d->g; +} + +int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g) +{ + /* If the fields p, q and g in d are NULL, the corresponding input + * parameters MUST be non-NULL. + */ + if ((d->p == NULL && p == NULL) + || (d->q == NULL && q == NULL) + || (d->g == NULL && g == NULL)) + return 0; + + if (p != NULL) { + BN_free(d->p); + d->p = p; + } + if (q != NULL) { + BN_free(d->q); + d->q = q; + } + if (g != NULL) { + BN_free(d->g); + d->g = g; + } + + return 1; +} + +void DSA_get0_key(const DSA *d, + const BIGNUM **pub_key, const BIGNUM **priv_key) +{ + if (pub_key != NULL) + *pub_key = d->pub_key; + if (priv_key != NULL) + *priv_key = d->priv_key; +} + +int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key) +{ + /* If the field pub_key in d is NULL, the corresponding input + * parameters MUST be non-NULL. The priv_key field may + * be left NULL. + */ + if (d->pub_key == NULL && pub_key == NULL) + return 0; + + if (pub_key != NULL) { + BN_free(d->pub_key); + d->pub_key = pub_key; + } + if (priv_key != NULL) { + BN_free(d->priv_key); + d->priv_key = priv_key; + } + + return 1; +} + +const BIGNUM *DSA_get0_p(const DSA *d) +{ + return d->p; +} + +const BIGNUM *DSA_get0_q(const DSA *d) +{ + return d->q; +} + +const BIGNUM *DSA_get0_g(const DSA *d) +{ + return d->g; +} + +const BIGNUM *DSA_get0_pub_key(const DSA *d) +{ + return d->pub_key; +} + +const BIGNUM *DSA_get0_priv_key(const DSA *d) +{ + return d->priv_key; +} + +void DSA_clear_flags(DSA *d, int flags) +{ + d->flags &= ~flags; +} + +int DSA_test_flags(const DSA *d, int flags) +{ + return d->flags & flags; +} + +void DSA_set_flags(DSA *d, int flags) +{ + d->flags |= flags; +} + +ENGINE *DSA_get0_engine(DSA *d) +{ + return d->engine; +} + +int DSA_bits(const DSA *dsa) +{ + return BN_num_bits(dsa->p); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_locl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_locl.h new file mode 100644 index 000000000..a81a4b497 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_locl.h @@ -0,0 +1,77 @@ +/* + * Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/refcount.h" + +struct dsa_st { + /* + * This first variable is used to pick up errors where a DSA is passed + * instead of of a EVP_PKEY + */ + int pad; + int32_t version; + BIGNUM *p; + BIGNUM *q; /* == 20 */ + BIGNUM *g; + BIGNUM *pub_key; /* y public key */ + BIGNUM *priv_key; /* x private key */ + int flags; + /* Normally used to cache montgomery values */ + BN_MONT_CTX *method_mont_p; + CRYPTO_REF_COUNT references; + CRYPTO_EX_DATA ex_data; + const DSA_METHOD *meth; + /* functional reference if 'meth' is ENGINE-provided */ + ENGINE *engine; + CRYPTO_RWLOCK *lock; +}; + +struct DSA_SIG_st { + BIGNUM *r; + BIGNUM *s; +}; + +struct dsa_method { + char *name; + DSA_SIG *(*dsa_do_sign) (const unsigned char *dgst, int dlen, DSA *dsa); + int (*dsa_sign_setup) (DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, + BIGNUM **rp); + int (*dsa_do_verify) (const unsigned char *dgst, int dgst_len, + DSA_SIG *sig, DSA *dsa); + int (*dsa_mod_exp) (DSA *dsa, BIGNUM *rr, const BIGNUM *a1, + const BIGNUM *p1, const BIGNUM *a2, const BIGNUM *p2, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont); + /* Can be null */ + int (*bn_mod_exp) (DSA *dsa, BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); + int (*init) (DSA *dsa); + int (*finish) (DSA *dsa); + int flags; + void *app_data; + /* If this is non-NULL, it is used to generate DSA parameters */ + int (*dsa_paramgen) (DSA *dsa, int bits, + const unsigned char *seed, int seed_len, + int *counter_ret, unsigned long *h_ret, + BN_GENCB *cb); + /* If this is non-NULL, it is used to generate DSA keys */ + int (*dsa_keygen) (DSA *dsa); +}; + +int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits, + const EVP_MD *evpmd, const unsigned char *seed_in, + size_t seed_len, unsigned char *seed_out, + int *counter_ret, unsigned long *h_ret, + BN_GENCB *cb); + +int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N, + const EVP_MD *evpmd, const unsigned char *seed_in, + size_t seed_len, int idx, unsigned char *seed_out, + int *counter_ret, unsigned long *h_ret, + BN_GENCB *cb); diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_meth.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_meth.c new file mode 100644 index 000000000..ff4fae44a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_meth.c @@ -0,0 +1,224 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Licensed under the OpenSSL licenses, (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * https://www.openssl.org/source/license.html + * or in the file LICENSE in the source distribution. + */ + +#include "dsa_locl.h" +#include +#include + +DSA_METHOD *DSA_meth_new(const char *name, int flags) +{ + DSA_METHOD *dsam = OPENSSL_zalloc(sizeof(*dsam)); + + if (dsam != NULL) { + dsam->flags = flags; + + dsam->name = OPENSSL_strdup(name); + if (dsam->name != NULL) + return dsam; + + OPENSSL_free(dsam); + } + + DSAerr(DSA_F_DSA_METH_NEW, ERR_R_MALLOC_FAILURE); + return NULL; +} + +void DSA_meth_free(DSA_METHOD *dsam) +{ + if (dsam != NULL) { + OPENSSL_free(dsam->name); + OPENSSL_free(dsam); + } +} + +DSA_METHOD *DSA_meth_dup(const DSA_METHOD *dsam) +{ + DSA_METHOD *ret = OPENSSL_malloc(sizeof(*ret)); + + if (ret != NULL) { + memcpy(ret, dsam, sizeof(*dsam)); + + ret->name = OPENSSL_strdup(dsam->name); + if (ret->name != NULL) + return ret; + + OPENSSL_free(ret); + } + + DSAerr(DSA_F_DSA_METH_DUP, ERR_R_MALLOC_FAILURE); + return NULL; +} + +const char *DSA_meth_get0_name(const DSA_METHOD *dsam) +{ + return dsam->name; +} + +int DSA_meth_set1_name(DSA_METHOD *dsam, const char *name) +{ + char *tmpname = OPENSSL_strdup(name); + + if (tmpname == NULL) { + DSAerr(DSA_F_DSA_METH_SET1_NAME, ERR_R_MALLOC_FAILURE); + return 0; + } + + OPENSSL_free(dsam->name); + dsam->name = tmpname; + + return 1; +} + +int DSA_meth_get_flags(const DSA_METHOD *dsam) +{ + return dsam->flags; +} + +int DSA_meth_set_flags(DSA_METHOD *dsam, int flags) +{ + dsam->flags = flags; + return 1; +} + +void *DSA_meth_get0_app_data(const DSA_METHOD *dsam) +{ + return dsam->app_data; +} + +int DSA_meth_set0_app_data(DSA_METHOD *dsam, void *app_data) +{ + dsam->app_data = app_data; + return 1; +} + +DSA_SIG *(*DSA_meth_get_sign(const DSA_METHOD *dsam)) + (const unsigned char *, int, DSA *) +{ + return dsam->dsa_do_sign; +} + +int DSA_meth_set_sign(DSA_METHOD *dsam, + DSA_SIG *(*sign) (const unsigned char *, int, DSA *)) +{ + dsam->dsa_do_sign = sign; + return 1; +} + +int (*DSA_meth_get_sign_setup(const DSA_METHOD *dsam)) + (DSA *, BN_CTX *, BIGNUM **, BIGNUM **) +{ + return dsam->dsa_sign_setup; +} + +int DSA_meth_set_sign_setup(DSA_METHOD *dsam, + int (*sign_setup) (DSA *, BN_CTX *, BIGNUM **, BIGNUM **)) +{ + dsam->dsa_sign_setup = sign_setup; + return 1; +} + +int (*DSA_meth_get_verify(const DSA_METHOD *dsam)) + (const unsigned char *, int, DSA_SIG *, DSA *) +{ + return dsam->dsa_do_verify; +} + +int DSA_meth_set_verify(DSA_METHOD *dsam, + int (*verify) (const unsigned char *, int, DSA_SIG *, DSA *)) +{ + dsam->dsa_do_verify = verify; + return 1; +} + +int (*DSA_meth_get_mod_exp(const DSA_METHOD *dsam)) + (DSA *, BIGNUM *, const BIGNUM *, const BIGNUM *, const BIGNUM *, + const BIGNUM *, const BIGNUM *, BN_CTX *, BN_MONT_CTX *) +{ + return dsam->dsa_mod_exp; +} + +int DSA_meth_set_mod_exp(DSA_METHOD *dsam, + int (*mod_exp) (DSA *, BIGNUM *, const BIGNUM *, const BIGNUM *, + const BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *, + BN_MONT_CTX *)) +{ + dsam->dsa_mod_exp = mod_exp; + return 1; +} + +int (*DSA_meth_get_bn_mod_exp(const DSA_METHOD *dsam)) + (DSA *, BIGNUM *, const BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *, + BN_MONT_CTX *) +{ + return dsam->bn_mod_exp; +} + +int DSA_meth_set_bn_mod_exp(DSA_METHOD *dsam, + int (*bn_mod_exp) (DSA *, BIGNUM *, const BIGNUM *, const BIGNUM *, + const BIGNUM *, BN_CTX *, BN_MONT_CTX *)) +{ + dsam->bn_mod_exp = bn_mod_exp; + return 1; +} + +int (*DSA_meth_get_init(const DSA_METHOD *dsam))(DSA *) +{ + return dsam->init; +} + +int DSA_meth_set_init(DSA_METHOD *dsam, int (*init)(DSA *)) +{ + dsam->init = init; + return 1; +} + +int (*DSA_meth_get_finish(const DSA_METHOD *dsam)) (DSA *) +{ + return dsam->finish; +} + +int DSA_meth_set_finish(DSA_METHOD *dsam, int (*finish) (DSA *)) +{ + dsam->finish = finish; + return 1; +} + +int (*DSA_meth_get_paramgen(const DSA_METHOD *dsam)) + (DSA *, int, const unsigned char *, int, int *, unsigned long *, + BN_GENCB *) +{ + return dsam->dsa_paramgen; +} + +int DSA_meth_set_paramgen(DSA_METHOD *dsam, + int (*paramgen) (DSA *, int, const unsigned char *, int, int *, + unsigned long *, BN_GENCB *)) +{ + dsam->dsa_paramgen = paramgen; + return 1; +} + +int (*DSA_meth_get_keygen(const DSA_METHOD *dsam)) (DSA *) +{ + return dsam->dsa_keygen; +} + +int DSA_meth_set_keygen(DSA_METHOD *dsam, int (*keygen) (DSA *)) +{ + dsam->dsa_keygen = keygen; + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_ossl.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_ossl.c new file mode 100644 index 000000000..7a0b0874c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_ossl.c @@ -0,0 +1,428 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include "internal/bn_int.h" +#include +#include +#include "dsa_locl.h" +#include + +static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa); +static int dsa_sign_setup_no_digest(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, + BIGNUM **rp); +static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, + BIGNUM **rp, const unsigned char *dgst, int dlen); +static int dsa_do_verify(const unsigned char *dgst, int dgst_len, + DSA_SIG *sig, DSA *dsa); +static int dsa_init(DSA *dsa); +static int dsa_finish(DSA *dsa); +static BIGNUM *dsa_mod_inverse_fermat(const BIGNUM *k, const BIGNUM *q, + BN_CTX *ctx); + +static DSA_METHOD openssl_dsa_meth = { + "OpenSSL DSA method", + dsa_do_sign, + dsa_sign_setup_no_digest, + dsa_do_verify, + NULL, /* dsa_mod_exp, */ + NULL, /* dsa_bn_mod_exp, */ + dsa_init, + dsa_finish, + DSA_FLAG_FIPS_METHOD, + NULL, + NULL, + NULL +}; + +static const DSA_METHOD *default_DSA_method = &openssl_dsa_meth; + +void DSA_set_default_method(const DSA_METHOD *meth) +{ + default_DSA_method = meth; +} + +const DSA_METHOD *DSA_get_default_method(void) +{ + return default_DSA_method; +} + +const DSA_METHOD *DSA_OpenSSL(void) +{ + return &openssl_dsa_meth; +} + +static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) +{ + BIGNUM *kinv = NULL; + BIGNUM *m, *blind, *blindm, *tmp; + BN_CTX *ctx = NULL; + int reason = ERR_R_BN_LIB; + DSA_SIG *ret = NULL; + int rv = 0; + + if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) { + reason = DSA_R_MISSING_PARAMETERS; + goto err; + } + + ret = DSA_SIG_new(); + if (ret == NULL) + goto err; + ret->r = BN_new(); + ret->s = BN_new(); + if (ret->r == NULL || ret->s == NULL) + goto err; + + ctx = BN_CTX_new(); + if (ctx == NULL) + goto err; + m = BN_CTX_get(ctx); + blind = BN_CTX_get(ctx); + blindm = BN_CTX_get(ctx); + tmp = BN_CTX_get(ctx); + if (tmp == NULL) + goto err; + + redo: + if (!dsa_sign_setup(dsa, ctx, &kinv, &ret->r, dgst, dlen)) + goto err; + + if (dlen > BN_num_bytes(dsa->q)) + /* + * if the digest length is greater than the size of q use the + * BN_num_bits(dsa->q) leftmost bits of the digest, see fips 186-3, + * 4.2 + */ + dlen = BN_num_bytes(dsa->q); + if (BN_bin2bn(dgst, dlen, m) == NULL) + goto err; + + /* + * The normal signature calculation is: + * + * s := k^-1 * (m + r * priv_key) mod q + * + * We will blind this to protect against side channel attacks + * + * s := blind^-1 * k^-1 * (blind * m + blind * r * priv_key) mod q + */ + + /* Generate a blinding value */ + do { + if (!BN_priv_rand(blind, BN_num_bits(dsa->q) - 1, + BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) + goto err; + } while (BN_is_zero(blind)); + BN_set_flags(blind, BN_FLG_CONSTTIME); + BN_set_flags(blindm, BN_FLG_CONSTTIME); + BN_set_flags(tmp, BN_FLG_CONSTTIME); + + /* tmp := blind * priv_key * r mod q */ + if (!BN_mod_mul(tmp, blind, dsa->priv_key, dsa->q, ctx)) + goto err; + if (!BN_mod_mul(tmp, tmp, ret->r, dsa->q, ctx)) + goto err; + + /* blindm := blind * m mod q */ + if (!BN_mod_mul(blindm, blind, m, dsa->q, ctx)) + goto err; + + /* s : = (blind * priv_key * r) + (blind * m) mod q */ + if (!BN_mod_add_quick(ret->s, tmp, blindm, dsa->q)) + goto err; + + /* s := s * k^-1 mod q */ + if (!BN_mod_mul(ret->s, ret->s, kinv, dsa->q, ctx)) + goto err; + + /* s:= s * blind^-1 mod q */ + if (BN_mod_inverse(blind, blind, dsa->q, ctx) == NULL) + goto err; + if (!BN_mod_mul(ret->s, ret->s, blind, dsa->q, ctx)) + goto err; + + /* + * Redo if r or s is zero as required by FIPS 186-3: this is very + * unlikely. + */ + if (BN_is_zero(ret->r) || BN_is_zero(ret->s)) + goto redo; + + rv = 1; + + err: + if (rv == 0) { + DSAerr(DSA_F_DSA_DO_SIGN, reason); + DSA_SIG_free(ret); + ret = NULL; + } + BN_CTX_free(ctx); + BN_clear_free(kinv); + return ret; +} + +static int dsa_sign_setup_no_digest(DSA *dsa, BN_CTX *ctx_in, + BIGNUM **kinvp, BIGNUM **rp) +{ + return dsa_sign_setup(dsa, ctx_in, kinvp, rp, NULL, 0); +} + +static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, + BIGNUM **kinvp, BIGNUM **rp, + const unsigned char *dgst, int dlen) +{ + BN_CTX *ctx = NULL; + BIGNUM *k, *kinv = NULL, *r = *rp; + BIGNUM *l; + int ret = 0; + int q_bits, q_words; + + if (!dsa->p || !dsa->q || !dsa->g) { + DSAerr(DSA_F_DSA_SIGN_SETUP, DSA_R_MISSING_PARAMETERS); + return 0; + } + + k = BN_new(); + l = BN_new(); + if (k == NULL || l == NULL) + goto err; + + if (ctx_in == NULL) { + if ((ctx = BN_CTX_new()) == NULL) + goto err; + } else + ctx = ctx_in; + + /* Preallocate space */ + q_bits = BN_num_bits(dsa->q); + q_words = bn_get_top(dsa->q); + if (!bn_wexpand(k, q_words + 2) + || !bn_wexpand(l, q_words + 2)) + goto err; + + /* Get random k */ + do { + if (dgst != NULL) { + /* + * We calculate k from SHA512(private_key + H(message) + random). + * This protects the private key from a weak PRNG. + */ + if (!BN_generate_dsa_nonce(k, dsa->q, dsa->priv_key, dgst, + dlen, ctx)) + goto err; + } else if (!BN_priv_rand_range(k, dsa->q)) + goto err; + } while (BN_is_zero(k)); + + BN_set_flags(k, BN_FLG_CONSTTIME); + BN_set_flags(l, BN_FLG_CONSTTIME); + + if (dsa->flags & DSA_FLAG_CACHE_MONT_P) { + if (!BN_MONT_CTX_set_locked(&dsa->method_mont_p, + dsa->lock, dsa->p, ctx)) + goto err; + } + + /* Compute r = (g^k mod p) mod q */ + + /* + * We do not want timing information to leak the length of k, so we + * compute G^k using an equivalent scalar of fixed bit-length. + * + * We unconditionally perform both of these additions to prevent a + * small timing information leakage. We then choose the sum that is + * one bit longer than the modulus. + * + * There are some concerns about the efficacy of doing this. More + * specificly refer to the discussion starting with: + * https://github.com/openssl/openssl/pull/7486#discussion_r228323705 + * The fix is to rework BN so these gymnastics aren't required. + */ + if (!BN_add(l, k, dsa->q) + || !BN_add(k, l, dsa->q)) + goto err; + + BN_consttime_swap(BN_is_bit_set(l, q_bits), k, l, q_words + 2); + + if ((dsa)->meth->bn_mod_exp != NULL) { + if (!dsa->meth->bn_mod_exp(dsa, r, dsa->g, k, dsa->p, ctx, + dsa->method_mont_p)) + goto err; + } else { + if (!BN_mod_exp_mont(r, dsa->g, k, dsa->p, ctx, dsa->method_mont_p)) + goto err; + } + + if (!BN_mod(r, r, dsa->q, ctx)) + goto err; + + /* Compute part of 's = inv(k) (m + xr) mod q' */ + if ((kinv = dsa_mod_inverse_fermat(k, dsa->q, ctx)) == NULL) + goto err; + + BN_clear_free(*kinvp); + *kinvp = kinv; + kinv = NULL; + ret = 1; + err: + if (!ret) + DSAerr(DSA_F_DSA_SIGN_SETUP, ERR_R_BN_LIB); + if (ctx != ctx_in) + BN_CTX_free(ctx); + BN_clear_free(k); + BN_clear_free(l); + return ret; +} + +static int dsa_do_verify(const unsigned char *dgst, int dgst_len, + DSA_SIG *sig, DSA *dsa) +{ + BN_CTX *ctx; + BIGNUM *u1, *u2, *t1; + BN_MONT_CTX *mont = NULL; + const BIGNUM *r, *s; + int ret = -1, i; + if (!dsa->p || !dsa->q || !dsa->g) { + DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_MISSING_PARAMETERS); + return -1; + } + + i = BN_num_bits(dsa->q); + /* fips 186-3 allows only different sizes for q */ + if (i != 160 && i != 224 && i != 256) { + DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_BAD_Q_VALUE); + return -1; + } + + if (BN_num_bits(dsa->p) > OPENSSL_DSA_MAX_MODULUS_BITS) { + DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_MODULUS_TOO_LARGE); + return -1; + } + u1 = BN_new(); + u2 = BN_new(); + t1 = BN_new(); + ctx = BN_CTX_new(); + if (u1 == NULL || u2 == NULL || t1 == NULL || ctx == NULL) + goto err; + + DSA_SIG_get0(sig, &r, &s); + + if (BN_is_zero(r) || BN_is_negative(r) || + BN_ucmp(r, dsa->q) >= 0) { + ret = 0; + goto err; + } + if (BN_is_zero(s) || BN_is_negative(s) || + BN_ucmp(s, dsa->q) >= 0) { + ret = 0; + goto err; + } + + /* + * Calculate W = inv(S) mod Q save W in u2 + */ + if ((BN_mod_inverse(u2, s, dsa->q, ctx)) == NULL) + goto err; + + /* save M in u1 */ + if (dgst_len > (i >> 3)) + /* + * if the digest length is greater than the size of q use the + * BN_num_bits(dsa->q) leftmost bits of the digest, see fips 186-3, + * 4.2 + */ + dgst_len = (i >> 3); + if (BN_bin2bn(dgst, dgst_len, u1) == NULL) + goto err; + + /* u1 = M * w mod q */ + if (!BN_mod_mul(u1, u1, u2, dsa->q, ctx)) + goto err; + + /* u2 = r * w mod q */ + if (!BN_mod_mul(u2, r, u2, dsa->q, ctx)) + goto err; + + if (dsa->flags & DSA_FLAG_CACHE_MONT_P) { + mont = BN_MONT_CTX_set_locked(&dsa->method_mont_p, + dsa->lock, dsa->p, ctx); + if (!mont) + goto err; + } + + if (dsa->meth->dsa_mod_exp != NULL) { + if (!dsa->meth->dsa_mod_exp(dsa, t1, dsa->g, u1, dsa->pub_key, u2, + dsa->p, ctx, mont)) + goto err; + } else { + if (!BN_mod_exp2_mont(t1, dsa->g, u1, dsa->pub_key, u2, dsa->p, ctx, + mont)) + goto err; + } + + /* let u1 = u1 mod q */ + if (!BN_mod(u1, t1, dsa->q, ctx)) + goto err; + + /* + * V is now in u1. If the signature is correct, it will be equal to R. + */ + ret = (BN_ucmp(u1, r) == 0); + + err: + if (ret < 0) + DSAerr(DSA_F_DSA_DO_VERIFY, ERR_R_BN_LIB); + BN_CTX_free(ctx); + BN_free(u1); + BN_free(u2); + BN_free(t1); + return ret; +} + +static int dsa_init(DSA *dsa) +{ + dsa->flags |= DSA_FLAG_CACHE_MONT_P; + return 1; +} + +static int dsa_finish(DSA *dsa) +{ + BN_MONT_CTX_free(dsa->method_mont_p); + return 1; +} + +/* + * Compute the inverse of k modulo q. + * Since q is prime, Fermat's Little Theorem applies, which reduces this to + * mod-exp operation. Both the exponent and modulus are public information + * so a mod-exp that doesn't leak the base is sufficient. A newly allocated + * BIGNUM is returned which the caller must free. + */ +static BIGNUM *dsa_mod_inverse_fermat(const BIGNUM *k, const BIGNUM *q, + BN_CTX *ctx) +{ + BIGNUM *res = NULL; + BIGNUM *r, *e; + + if ((r = BN_new()) == NULL) + return NULL; + + BN_CTX_start(ctx); + if ((e = BN_CTX_get(ctx)) != NULL + && BN_set_word(r, 2) + && BN_sub(e, q, r) + && BN_mod_exp_mont(r, k, e, q, ctx, NULL)) + res = r; + else + BN_free(r); + BN_CTX_end(ctx); + return res; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_pmeth.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_pmeth.c new file mode 100644 index 000000000..b4ee5a757 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_pmeth.c @@ -0,0 +1,273 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "internal/evp_int.h" +#include "dsa_locl.h" + +/* DSA pkey context structure */ + +typedef struct { + /* Parameter gen parameters */ + int nbits; /* size of p in bits (default: 1024) */ + int qbits; /* size of q in bits (default: 160) */ + const EVP_MD *pmd; /* MD for parameter generation */ + /* Keygen callback info */ + int gentmp[2]; + /* message digest */ + const EVP_MD *md; /* MD for the signature */ +} DSA_PKEY_CTX; + +static int pkey_dsa_init(EVP_PKEY_CTX *ctx) +{ + DSA_PKEY_CTX *dctx = OPENSSL_malloc(sizeof(*dctx)); + + if (dctx == NULL) + return 0; + dctx->nbits = 1024; + dctx->qbits = 160; + dctx->pmd = NULL; + dctx->md = NULL; + + ctx->data = dctx; + ctx->keygen_info = dctx->gentmp; + ctx->keygen_info_count = 2; + + return 1; +} + +static int pkey_dsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) +{ + DSA_PKEY_CTX *dctx, *sctx; + + if (!pkey_dsa_init(dst)) + return 0; + sctx = src->data; + dctx = dst->data; + dctx->nbits = sctx->nbits; + dctx->qbits = sctx->qbits; + dctx->pmd = sctx->pmd; + dctx->md = sctx->md; + return 1; +} + +static void pkey_dsa_cleanup(EVP_PKEY_CTX *ctx) +{ + DSA_PKEY_CTX *dctx = ctx->data; + OPENSSL_free(dctx); +} + +static int pkey_dsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, + size_t *siglen, const unsigned char *tbs, + size_t tbslen) +{ + int ret; + unsigned int sltmp; + DSA_PKEY_CTX *dctx = ctx->data; + DSA *dsa = ctx->pkey->pkey.dsa; + + if (dctx->md != NULL && tbslen != (size_t)EVP_MD_size(dctx->md)) + return 0; + + ret = DSA_sign(0, tbs, tbslen, sig, &sltmp, dsa); + + if (ret <= 0) + return ret; + *siglen = sltmp; + return 1; +} + +static int pkey_dsa_verify(EVP_PKEY_CTX *ctx, + const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen) +{ + int ret; + DSA_PKEY_CTX *dctx = ctx->data; + DSA *dsa = ctx->pkey->pkey.dsa; + + if (dctx->md != NULL && tbslen != (size_t)EVP_MD_size(dctx->md)) + return 0; + + ret = DSA_verify(0, tbs, tbslen, sig, siglen, dsa); + + return ret; +} + +static int pkey_dsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) +{ + DSA_PKEY_CTX *dctx = ctx->data; + + switch (type) { + case EVP_PKEY_CTRL_DSA_PARAMGEN_BITS: + if (p1 < 256) + return -2; + dctx->nbits = p1; + return 1; + + case EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS: + if (p1 != 160 && p1 != 224 && p1 && p1 != 256) + return -2; + dctx->qbits = p1; + return 1; + + case EVP_PKEY_CTRL_DSA_PARAMGEN_MD: + if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 && + EVP_MD_type((const EVP_MD *)p2) != NID_sha224 && + EVP_MD_type((const EVP_MD *)p2) != NID_sha256) { + DSAerr(DSA_F_PKEY_DSA_CTRL, DSA_R_INVALID_DIGEST_TYPE); + return 0; + } + dctx->pmd = p2; + return 1; + + case EVP_PKEY_CTRL_MD: + if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 && + EVP_MD_type((const EVP_MD *)p2) != NID_dsa && + EVP_MD_type((const EVP_MD *)p2) != NID_dsaWithSHA && + EVP_MD_type((const EVP_MD *)p2) != NID_sha224 && + EVP_MD_type((const EVP_MD *)p2) != NID_sha256 && + EVP_MD_type((const EVP_MD *)p2) != NID_sha384 && + EVP_MD_type((const EVP_MD *)p2) != NID_sha512) { + DSAerr(DSA_F_PKEY_DSA_CTRL, DSA_R_INVALID_DIGEST_TYPE); + return 0; + } + dctx->md = p2; + return 1; + + case EVP_PKEY_CTRL_GET_MD: + *(const EVP_MD **)p2 = dctx->md; + return 1; + + case EVP_PKEY_CTRL_DIGESTINIT: + case EVP_PKEY_CTRL_PKCS7_SIGN: + case EVP_PKEY_CTRL_CMS_SIGN: + return 1; + + case EVP_PKEY_CTRL_PEER_KEY: + DSAerr(DSA_F_PKEY_DSA_CTRL, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + default: + return -2; + + } +} + +static int pkey_dsa_ctrl_str(EVP_PKEY_CTX *ctx, + const char *type, const char *value) +{ + if (strcmp(type, "dsa_paramgen_bits") == 0) { + int nbits; + nbits = atoi(value); + return EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, nbits); + } + if (strcmp(type, "dsa_paramgen_q_bits") == 0) { + int qbits = atoi(value); + return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN, + EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS, qbits, + NULL); + } + if (strcmp(type, "dsa_paramgen_md") == 0) { + const EVP_MD *md = EVP_get_digestbyname(value); + + if (md == NULL) { + DSAerr(DSA_F_PKEY_DSA_CTRL_STR, DSA_R_INVALID_DIGEST_TYPE); + return 0; + } + return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN, + EVP_PKEY_CTRL_DSA_PARAMGEN_MD, 0, + (void *)md); + } + return -2; +} + +static int pkey_dsa_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) +{ + DSA *dsa = NULL; + DSA_PKEY_CTX *dctx = ctx->data; + BN_GENCB *pcb; + int ret; + + if (ctx->pkey_gencb) { + pcb = BN_GENCB_new(); + if (pcb == NULL) + return 0; + evp_pkey_set_cb_translate(pcb, ctx); + } else + pcb = NULL; + dsa = DSA_new(); + if (dsa == NULL) { + BN_GENCB_free(pcb); + return 0; + } + ret = dsa_builtin_paramgen(dsa, dctx->nbits, dctx->qbits, dctx->pmd, + NULL, 0, NULL, NULL, NULL, pcb); + BN_GENCB_free(pcb); + if (ret) + EVP_PKEY_assign_DSA(pkey, dsa); + else + DSA_free(dsa); + return ret; +} + +static int pkey_dsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) +{ + DSA *dsa = NULL; + + if (ctx->pkey == NULL) { + DSAerr(DSA_F_PKEY_DSA_KEYGEN, DSA_R_NO_PARAMETERS_SET); + return 0; + } + dsa = DSA_new(); + if (dsa == NULL) + return 0; + EVP_PKEY_assign_DSA(pkey, dsa); + /* Note: if error return, pkey is freed by parent routine */ + if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) + return 0; + return DSA_generate_key(pkey->pkey.dsa); +} + +const EVP_PKEY_METHOD dsa_pkey_meth = { + EVP_PKEY_DSA, + EVP_PKEY_FLAG_AUTOARGLEN, + pkey_dsa_init, + pkey_dsa_copy, + pkey_dsa_cleanup, + + 0, + pkey_dsa_paramgen, + + 0, + pkey_dsa_keygen, + + 0, + pkey_dsa_sign, + + 0, + pkey_dsa_verify, + + 0, 0, + + 0, 0, 0, 0, + + 0, 0, + + 0, 0, + + 0, 0, + + pkey_dsa_ctrl, + pkey_dsa_ctrl_str +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_prn.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_prn.c new file mode 100644 index 000000000..a4a1fd565 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_prn.c @@ -0,0 +1,69 @@ +/* + * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include + +#ifndef OPENSSL_NO_STDIO +int DSA_print_fp(FILE *fp, const DSA *x, int off) +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + DSAerr(DSA_F_DSA_PRINT_FP, ERR_R_BUF_LIB); + return 0; + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = DSA_print(b, x, off); + BIO_free(b); + return ret; +} + +int DSAparams_print_fp(FILE *fp, const DSA *x) +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + DSAerr(DSA_F_DSAPARAMS_PRINT_FP, ERR_R_BUF_LIB); + return 0; + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = DSAparams_print(b, x); + BIO_free(b); + return ret; +} +#endif + +int DSA_print(BIO *bp, const DSA *x, int off) +{ + EVP_PKEY *pk; + int ret; + pk = EVP_PKEY_new(); + if (pk == NULL || !EVP_PKEY_set1_DSA(pk, (DSA *)x)) + return 0; + ret = EVP_PKEY_print_private(bp, pk, off, NULL); + EVP_PKEY_free(pk); + return ret; +} + +int DSAparams_print(BIO *bp, const DSA *x) +{ + EVP_PKEY *pk; + int ret; + pk = EVP_PKEY_new(); + if (pk == NULL || !EVP_PKEY_set1_DSA(pk, (DSA *)x)) + return 0; + ret = EVP_PKEY_print_params(bp, pk, 4, NULL); + EVP_PKEY_free(pk); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_sign.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_sign.c new file mode 100644 index 000000000..e9466b29f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_sign.c @@ -0,0 +1,24 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include "dsa_locl.h" +#include + +DSA_SIG *DSA_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) +{ + return dsa->meth->dsa_do_sign(dgst, dlen, dsa); +} + +#if OPENSSL_API_COMPAT < 0x10200000L +int DSA_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) +{ + return dsa->meth->dsa_sign_setup(dsa, ctx_in, kinvp, rp); +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_vrf.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_vrf.c new file mode 100644 index 000000000..21f98cd94 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dsa/dsa_vrf.c @@ -0,0 +1,17 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include "dsa_locl.h" + +int DSA_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, + DSA *dsa) +{ + return dsa->meth->dsa_do_verify(dgst, dgst_len, sig, dsa); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dso/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/dso/build.info new file mode 100644 index 000000000..82b592d9a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dso/build.info @@ -0,0 +1,4 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + dso_dl.c dso_dlfcn.c dso_err.c dso_lib.c \ + dso_openssl.c dso_win32.c dso_vms.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_dl.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_dl.c new file mode 100644 index 000000000..290d73cf3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_dl.c @@ -0,0 +1,279 @@ +/* + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "dso_locl.h" + +#ifdef DSO_DL + +# include + +/* Part of the hack in "dl_load" ... */ +# define DSO_MAX_TRANSLATED_SIZE 256 + +static int dl_load(DSO *dso); +static int dl_unload(DSO *dso); +static DSO_FUNC_TYPE dl_bind_func(DSO *dso, const char *symname); +static char *dl_name_converter(DSO *dso, const char *filename); +static char *dl_merger(DSO *dso, const char *filespec1, + const char *filespec2); +static int dl_pathbyaddr(void *addr, char *path, int sz); +static void *dl_globallookup(const char *name); + +static DSO_METHOD dso_meth_dl = { + "OpenSSL 'dl' shared library method", + dl_load, + dl_unload, + dl_bind_func, + NULL, /* ctrl */ + dl_name_converter, + dl_merger, + NULL, /* init */ + NULL, /* finish */ + dl_pathbyaddr, + dl_globallookup +}; + +DSO_METHOD *DSO_METHOD_openssl(void) +{ + return &dso_meth_dl; +} + +/* + * For this DSO_METHOD, our meth_data STACK will contain; (i) the handle + * (shl_t) returned from shl_load(). NB: I checked on HPUX11 and shl_t is + * itself a pointer type so the cast is safe. + */ + +static int dl_load(DSO *dso) +{ + shl_t ptr = NULL; + /* + * We don't do any fancy retries or anything, just take the method's (or + * DSO's if it has the callback set) best translation of the + * platform-independent filename and try once with that. + */ + char *filename = DSO_convert_filename(dso, NULL); + + if (filename == NULL) { + DSOerr(DSO_F_DL_LOAD, DSO_R_NO_FILENAME); + goto err; + } + ptr = shl_load(filename, BIND_IMMEDIATE | + (dso->flags & DSO_FLAG_NO_NAME_TRANSLATION ? 0 : + DYNAMIC_PATH), 0L); + if (ptr == NULL) { + char errbuf[160]; + DSOerr(DSO_F_DL_LOAD, DSO_R_LOAD_FAILED); + if (openssl_strerror_r(errno, errbuf, sizeof(errbuf))) + ERR_add_error_data(4, "filename(", filename, "): ", errbuf); + goto err; + } + if (!sk_push(dso->meth_data, (char *)ptr)) { + DSOerr(DSO_F_DL_LOAD, DSO_R_STACK_ERROR); + goto err; + } + /* + * Success, stick the converted filename we've loaded under into the DSO + * (it also serves as the indicator that we are currently loaded). + */ + dso->loaded_filename = filename; + return 1; + err: + /* Cleanup! */ + OPENSSL_free(filename); + if (ptr != NULL) + shl_unload(ptr); + return 0; +} + +static int dl_unload(DSO *dso) +{ + shl_t ptr; + if (dso == NULL) { + DSOerr(DSO_F_DL_UNLOAD, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (sk_num(dso->meth_data) < 1) + return 1; + /* Is this statement legal? */ + ptr = (shl_t) sk_pop(dso->meth_data); + if (ptr == NULL) { + DSOerr(DSO_F_DL_UNLOAD, DSO_R_NULL_HANDLE); + /* + * Should push the value back onto the stack in case of a retry. + */ + sk_push(dso->meth_data, (char *)ptr); + return 0; + } + shl_unload(ptr); + return 1; +} + +static DSO_FUNC_TYPE dl_bind_func(DSO *dso, const char *symname) +{ + shl_t ptr; + void *sym; + + if ((dso == NULL) || (symname == NULL)) { + DSOerr(DSO_F_DL_BIND_FUNC, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + if (sk_num(dso->meth_data) < 1) { + DSOerr(DSO_F_DL_BIND_FUNC, DSO_R_STACK_ERROR); + return NULL; + } + ptr = (shl_t) sk_value(dso->meth_data, sk_num(dso->meth_data) - 1); + if (ptr == NULL) { + DSOerr(DSO_F_DL_BIND_FUNC, DSO_R_NULL_HANDLE); + return NULL; + } + if (shl_findsym(&ptr, symname, TYPE_UNDEFINED, &sym) < 0) { + char errbuf[160]; + DSOerr(DSO_F_DL_BIND_FUNC, DSO_R_SYM_FAILURE); + if (openssl_strerror_r(errno, errbuf, sizeof(errbuf))) + ERR_add_error_data(4, "symname(", symname, "): ", errbuf); + return NULL; + } + return (DSO_FUNC_TYPE)sym; +} + +static char *dl_merger(DSO *dso, const char *filespec1, const char *filespec2) +{ + char *merged; + + if (!filespec1 && !filespec2) { + DSOerr(DSO_F_DL_MERGER, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + /* + * If the first file specification is a rooted path, it rules. same goes + * if the second file specification is missing. + */ + if (!filespec2 || filespec1[0] == '/') { + merged = OPENSSL_strdup(filespec1); + if (merged == NULL) { + DSOerr(DSO_F_DL_MERGER, ERR_R_MALLOC_FAILURE); + return NULL; + } + } + /* + * If the first file specification is missing, the second one rules. + */ + else if (!filespec1) { + merged = OPENSSL_strdup(filespec2); + if (merged == NULL) { + DSOerr(DSO_F_DL_MERGER, ERR_R_MALLOC_FAILURE); + return NULL; + } + } else + /* + * This part isn't as trivial as it looks. It assumes that the + * second file specification really is a directory, and makes no + * checks whatsoever. Therefore, the result becomes the + * concatenation of filespec2 followed by a slash followed by + * filespec1. + */ + { + int spec2len, len; + + spec2len = (filespec2 ? strlen(filespec2) : 0); + len = spec2len + (filespec1 ? strlen(filespec1) : 0); + + if (spec2len && filespec2[spec2len - 1] == '/') { + spec2len--; + len--; + } + merged = OPENSSL_malloc(len + 2); + if (merged == NULL) { + DSOerr(DSO_F_DL_MERGER, ERR_R_MALLOC_FAILURE); + return NULL; + } + strcpy(merged, filespec2); + merged[spec2len] = '/'; + strcpy(&merged[spec2len + 1], filespec1); + } + return merged; +} + +/* + * This function is identical to the one in dso_dlfcn.c, but as it is highly + * unlikely that both the "dl" *and* "dlfcn" variants are being compiled at + * the same time, there's no great duplicating the code. Figuring out an + * elegant way to share one copy of the code would be more difficult and + * would not leave the implementations independent. + */ +static char *dl_name_converter(DSO *dso, const char *filename) +{ + char *translated; + int len, rsize, transform; + + len = strlen(filename); + rsize = len + 1; + transform = (strstr(filename, "/") == NULL); + { + /* We will convert this to "%s.s?" or "lib%s.s?" */ + rsize += strlen(DSO_EXTENSION); /* The length of ".s?" */ + if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0) + rsize += 3; /* The length of "lib" */ + } + translated = OPENSSL_malloc(rsize); + if (translated == NULL) { + DSOerr(DSO_F_DL_NAME_CONVERTER, DSO_R_NAME_TRANSLATION_FAILED); + return NULL; + } + if (transform) { + if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0) + sprintf(translated, "lib%s%s", filename, DSO_EXTENSION); + else + sprintf(translated, "%s%s", filename, DSO_EXTENSION); + } else + sprintf(translated, "%s", filename); + return translated; +} + +static int dl_pathbyaddr(void *addr, char *path, int sz) +{ + struct shl_descriptor inf; + int i, len; + + if (addr == NULL) { + union { + int (*f) (void *, char *, int); + void *p; + } t = { + dl_pathbyaddr + }; + addr = t.p; + } + + for (i = -1; shl_get_r(i, &inf) == 0; i++) { + if (((size_t)addr >= inf.tstart && (size_t)addr < inf.tend) || + ((size_t)addr >= inf.dstart && (size_t)addr < inf.dend)) { + len = (int)strlen(inf.filename); + if (sz <= 0) + return len + 1; + if (len >= sz) + len = sz - 1; + memcpy(path, inf.filename, len); + path[len++] = 0; + return len; + } + } + + return -1; +} + +static void *dl_globallookup(const char *name) +{ + void *ret; + shl_t h = NULL; + + return shl_findsym(&h, name, TYPE_UNDEFINED, &ret) ? NULL : ret; +} +#endif /* DSO_DL */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_dlfcn.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_dlfcn.c new file mode 100644 index 000000000..4240f5f5e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_dlfcn.c @@ -0,0 +1,457 @@ +/* + * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * We need to do this early, because stdio.h includes the header files that + * handle _GNU_SOURCE and other similar macros. Defining it later is simply + * too late, because those headers are protected from re- inclusion. + */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE /* make sure dladdr is declared */ +#endif + +#include "dso_locl.h" +#include "e_os.h" + +#ifdef DSO_DLFCN + +# ifdef HAVE_DLFCN_H +# ifdef __osf__ +# define __EXTENSIONS__ +# endif +# include +# define HAVE_DLINFO 1 +# if defined(__CYGWIN__) || \ + defined(__SCO_VERSION__) || defined(_SCO_ELF) || \ + (defined(__osf__) && !defined(RTLD_NEXT)) || \ + (defined(__OpenBSD__) && !defined(RTLD_SELF)) || \ + defined(__ANDROID__) +# undef HAVE_DLINFO +# endif +# endif + +/* Part of the hack in "dlfcn_load" ... */ +# define DSO_MAX_TRANSLATED_SIZE 256 + +static int dlfcn_load(DSO *dso); +static int dlfcn_unload(DSO *dso); +static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname); +static char *dlfcn_name_converter(DSO *dso, const char *filename); +static char *dlfcn_merger(DSO *dso, const char *filespec1, + const char *filespec2); +static int dlfcn_pathbyaddr(void *addr, char *path, int sz); +static void *dlfcn_globallookup(const char *name); + +static DSO_METHOD dso_meth_dlfcn = { + "OpenSSL 'dlfcn' shared library method", + dlfcn_load, + dlfcn_unload, + dlfcn_bind_func, + NULL, /* ctrl */ + dlfcn_name_converter, + dlfcn_merger, + NULL, /* init */ + NULL, /* finish */ + dlfcn_pathbyaddr, + dlfcn_globallookup +}; + +DSO_METHOD *DSO_METHOD_openssl(void) +{ + return &dso_meth_dlfcn; +} + +/* + * Prior to using the dlopen() function, we should decide on the flag we + * send. There's a few different ways of doing this and it's a messy + * venn-diagram to match up which platforms support what. So as we don't have + * autoconf yet, I'm implementing a hack that could be hacked further + * relatively easily to deal with cases as we find them. Initially this is to + * cope with OpenBSD. + */ +# if defined(__OpenBSD__) || defined(__NetBSD__) +# ifdef DL_LAZY +# define DLOPEN_FLAG DL_LAZY +# else +# ifdef RTLD_NOW +# define DLOPEN_FLAG RTLD_NOW +# else +# define DLOPEN_FLAG 0 +# endif +# endif +# else +# define DLOPEN_FLAG RTLD_NOW /* Hope this works everywhere else */ +# endif + +/* + * For this DSO_METHOD, our meth_data STACK will contain; (i) the handle + * (void*) returned from dlopen(). + */ + +static int dlfcn_load(DSO *dso) +{ + void *ptr = NULL; + /* See applicable comments in dso_dl.c */ + char *filename = DSO_convert_filename(dso, NULL); + int flags = DLOPEN_FLAG; + int saveerrno = get_last_sys_error(); + + if (filename == NULL) { + DSOerr(DSO_F_DLFCN_LOAD, DSO_R_NO_FILENAME); + goto err; + } +# ifdef RTLD_GLOBAL + if (dso->flags & DSO_FLAG_GLOBAL_SYMBOLS) + flags |= RTLD_GLOBAL; +# endif +# ifdef _AIX + if (filename[strlen(filename) - 1] == ')') + flags |= RTLD_MEMBER; +# endif + ptr = dlopen(filename, flags); + if (ptr == NULL) { + DSOerr(DSO_F_DLFCN_LOAD, DSO_R_LOAD_FAILED); + ERR_add_error_data(4, "filename(", filename, "): ", dlerror()); + goto err; + } + /* + * Some dlopen() implementations (e.g. solaris) do no preserve errno, even + * on a successful call. + */ + set_sys_error(saveerrno); + if (!sk_void_push(dso->meth_data, (char *)ptr)) { + DSOerr(DSO_F_DLFCN_LOAD, DSO_R_STACK_ERROR); + goto err; + } + /* Success */ + dso->loaded_filename = filename; + return 1; + err: + /* Cleanup! */ + OPENSSL_free(filename); + if (ptr != NULL) + dlclose(ptr); + return 0; +} + +static int dlfcn_unload(DSO *dso) +{ + void *ptr; + if (dso == NULL) { + DSOerr(DSO_F_DLFCN_UNLOAD, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (sk_void_num(dso->meth_data) < 1) + return 1; + ptr = sk_void_pop(dso->meth_data); + if (ptr == NULL) { + DSOerr(DSO_F_DLFCN_UNLOAD, DSO_R_NULL_HANDLE); + /* + * Should push the value back onto the stack in case of a retry. + */ + sk_void_push(dso->meth_data, ptr); + return 0; + } + /* For now I'm not aware of any errors associated with dlclose() */ + dlclose(ptr); + return 1; +} + +static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname) +{ + void *ptr; + union { + DSO_FUNC_TYPE sym; + void *dlret; + } u; + + if ((dso == NULL) || (symname == NULL)) { + DSOerr(DSO_F_DLFCN_BIND_FUNC, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + if (sk_void_num(dso->meth_data) < 1) { + DSOerr(DSO_F_DLFCN_BIND_FUNC, DSO_R_STACK_ERROR); + return NULL; + } + ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1); + if (ptr == NULL) { + DSOerr(DSO_F_DLFCN_BIND_FUNC, DSO_R_NULL_HANDLE); + return NULL; + } + u.dlret = dlsym(ptr, symname); + if (u.dlret == NULL) { + DSOerr(DSO_F_DLFCN_BIND_FUNC, DSO_R_SYM_FAILURE); + ERR_add_error_data(4, "symname(", symname, "): ", dlerror()); + return NULL; + } + return u.sym; +} + +static char *dlfcn_merger(DSO *dso, const char *filespec1, + const char *filespec2) +{ + char *merged; + + if (!filespec1 && !filespec2) { + DSOerr(DSO_F_DLFCN_MERGER, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + /* + * If the first file specification is a rooted path, it rules. same goes + * if the second file specification is missing. + */ + if (!filespec2 || (filespec1 != NULL && filespec1[0] == '/')) { + merged = OPENSSL_strdup(filespec1); + if (merged == NULL) { + DSOerr(DSO_F_DLFCN_MERGER, ERR_R_MALLOC_FAILURE); + return NULL; + } + } + /* + * If the first file specification is missing, the second one rules. + */ + else if (!filespec1) { + merged = OPENSSL_strdup(filespec2); + if (merged == NULL) { + DSOerr(DSO_F_DLFCN_MERGER, ERR_R_MALLOC_FAILURE); + return NULL; + } + } else { + /* + * This part isn't as trivial as it looks. It assumes that the + * second file specification really is a directory, and makes no + * checks whatsoever. Therefore, the result becomes the + * concatenation of filespec2 followed by a slash followed by + * filespec1. + */ + int spec2len, len; + + spec2len = strlen(filespec2); + len = spec2len + strlen(filespec1); + + if (spec2len && filespec2[spec2len - 1] == '/') { + spec2len--; + len--; + } + merged = OPENSSL_malloc(len + 2); + if (merged == NULL) { + DSOerr(DSO_F_DLFCN_MERGER, ERR_R_MALLOC_FAILURE); + return NULL; + } + strcpy(merged, filespec2); + merged[spec2len] = '/'; + strcpy(&merged[spec2len + 1], filespec1); + } + return merged; +} + +static char *dlfcn_name_converter(DSO *dso, const char *filename) +{ + char *translated; + int len, rsize, transform; + + len = strlen(filename); + rsize = len + 1; + transform = (strstr(filename, "/") == NULL); + if (transform) { + /* We will convert this to "%s.so" or "lib%s.so" etc */ + rsize += strlen(DSO_EXTENSION); /* The length of ".so" */ + if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0) + rsize += 3; /* The length of "lib" */ + } + translated = OPENSSL_malloc(rsize); + if (translated == NULL) { + DSOerr(DSO_F_DLFCN_NAME_CONVERTER, DSO_R_NAME_TRANSLATION_FAILED); + return NULL; + } + if (transform) { + if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0) + sprintf(translated, "lib%s" DSO_EXTENSION, filename); + else + sprintf(translated, "%s" DSO_EXTENSION, filename); + } else + sprintf(translated, "%s", filename); + return translated; +} + +# ifdef __sgi +/*- +This is a quote from IRIX manual for dladdr(3c): + + does not contain a prototype for dladdr or definition of + Dl_info. The #include in the SYNOPSIS line is traditional, + but contains no dladdr prototype and no IRIX library contains an + implementation. Write your own declaration based on the code below. + + The following code is dependent on internal interfaces that are not + part of the IRIX compatibility guarantee; however, there is no future + intention to change this interface, so on a practical level, the code + below is safe to use on IRIX. +*/ +# include +# ifndef _RLD_INTERFACE_DLFCN_H_DLADDR +# define _RLD_INTERFACE_DLFCN_H_DLADDR +typedef struct Dl_info { + const char *dli_fname; + void *dli_fbase; + const char *dli_sname; + void *dli_saddr; + int dli_version; + int dli_reserved1; + long dli_reserved[4]; +} Dl_info; +# else +typedef struct Dl_info Dl_info; +# endif +# define _RLD_DLADDR 14 + +static int dladdr(void *address, Dl_info *dl) +{ + void *v; + v = _rld_new_interface(_RLD_DLADDR, address, dl); + return (int)v; +} +# endif /* __sgi */ + +# ifdef _AIX +/*- + * See IBM's AIX Version 7.2, Technical Reference: + * Base Operating System and Extensions, Volume 1 and 2 + * https://www.ibm.com/support/knowledgecenter/ssw_aix_72/com.ibm.aix.base/technicalreferences.htm + */ +# include +# include +/* ~ 64 * (sizeof(struct ld_info) + _XOPEN_PATH_MAX + _XOPEN_NAME_MAX) */ +# define DLFCN_LDINFO_SIZE 86976 +typedef struct Dl_info { + const char *dli_fname; +} Dl_info; +/* + * This dladdr()-implementation will also find the ptrgl (Pointer Glue) virtual + * address of a function, which is just located in the DATA segment instead of + * the TEXT segment. + */ +static int dladdr(void *ptr, Dl_info *dl) +{ + uintptr_t addr = (uintptr_t)ptr; + unsigned int found = 0; + struct ld_info *ldinfos, *next_ldi, *this_ldi; + + if ((ldinfos = OPENSSL_malloc(DLFCN_LDINFO_SIZE)) == NULL) { + errno = ENOMEM; + dl->dli_fname = NULL; + return 0; + } + + if ((loadquery(L_GETINFO, (void *)ldinfos, DLFCN_LDINFO_SIZE)) < 0) { + /*- + * Error handling is done through errno and dlerror() reading errno: + * ENOMEM (ldinfos buffer is too small), + * EINVAL (invalid flags), + * EFAULT (invalid ldinfos ptr) + */ + OPENSSL_free((void *)ldinfos); + dl->dli_fname = NULL; + return 0; + } + next_ldi = ldinfos; + + do { + this_ldi = next_ldi; + if (((addr >= (uintptr_t)this_ldi->ldinfo_textorg) + && (addr < ((uintptr_t)this_ldi->ldinfo_textorg + + this_ldi->ldinfo_textsize))) + || ((addr >= (uintptr_t)this_ldi->ldinfo_dataorg) + && (addr < ((uintptr_t)this_ldi->ldinfo_dataorg + + this_ldi->ldinfo_datasize)))) { + char *buffer, *member; + size_t buffer_sz, member_len; + + buffer_sz = strlen(this_ldi->ldinfo_filename) + 1; + member = this_ldi->ldinfo_filename + buffer_sz; + if ((member_len = strlen(member)) > 0) + buffer_sz += 1 + member_len + 1; + found = 1; + if ((buffer = OPENSSL_malloc(buffer_sz)) != NULL) { + OPENSSL_strlcpy(buffer, this_ldi->ldinfo_filename, buffer_sz); + if (member_len > 0) { + /* + * Need to respect a possible member name and not just + * returning the path name in this case. See docs: + * sys/ldr.h, loadquery() and dlopen()/RTLD_MEMBER. + */ + OPENSSL_strlcat(buffer, "(", buffer_sz); + OPENSSL_strlcat(buffer, member, buffer_sz); + OPENSSL_strlcat(buffer, ")", buffer_sz); + } + dl->dli_fname = buffer; + } else { + errno = ENOMEM; + } + } else { + next_ldi = (struct ld_info *)((uintptr_t)this_ldi + + this_ldi->ldinfo_next); + } + } while (this_ldi->ldinfo_next && !found); + OPENSSL_free((void *)ldinfos); + return (found && dl->dli_fname != NULL); +} +# endif /* _AIX */ + +static int dlfcn_pathbyaddr(void *addr, char *path, int sz) +{ +# ifdef HAVE_DLINFO + Dl_info dli; + int len; + + if (addr == NULL) { + union { + int (*f) (void *, char *, int); + void *p; + } t = { + dlfcn_pathbyaddr + }; + addr = t.p; + } + + if (dladdr(addr, &dli)) { + len = (int)strlen(dli.dli_fname); + if (sz <= 0) { +# ifdef _AIX + OPENSSL_free((void *)dli.dli_fname); +# endif + return len + 1; + } + if (len >= sz) + len = sz - 1; + memcpy(path, dli.dli_fname, len); + path[len++] = 0; +# ifdef _AIX + OPENSSL_free((void *)dli.dli_fname); +# endif + return len; + } + + ERR_add_error_data(2, "dlfcn_pathbyaddr(): ", dlerror()); +# endif + return -1; +} + +static void *dlfcn_globallookup(const char *name) +{ + void *ret = NULL, *handle = dlopen(NULL, RTLD_LAZY); + + if (handle) { + ret = dlsym(handle, name); + dlclose(handle); + } + + return ret; +} +#endif /* DSO_DLFCN */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_err.c new file mode 100644 index 000000000..613072a8d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_err.c @@ -0,0 +1,100 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/dsoerr.h" + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA DSO_str_functs[] = { + {ERR_PACK(ERR_LIB_DSO, DSO_F_DLFCN_BIND_FUNC, 0), "dlfcn_bind_func"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_DLFCN_LOAD, 0), "dlfcn_load"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_DLFCN_MERGER, 0), "dlfcn_merger"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_DLFCN_NAME_CONVERTER, 0), + "dlfcn_name_converter"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_DLFCN_UNLOAD, 0), "dlfcn_unload"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_DL_BIND_FUNC, 0), "dl_bind_func"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_DL_LOAD, 0), "dl_load"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_DL_MERGER, 0), "dl_merger"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_DL_NAME_CONVERTER, 0), "dl_name_converter"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_DL_UNLOAD, 0), "dl_unload"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_BIND_FUNC, 0), "DSO_bind_func"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_CONVERT_FILENAME, 0), + "DSO_convert_filename"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_CTRL, 0), "DSO_ctrl"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_FREE, 0), "DSO_free"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_GET_FILENAME, 0), "DSO_get_filename"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_GLOBAL_LOOKUP, 0), "DSO_global_lookup"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_LOAD, 0), "DSO_load"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_MERGE, 0), "DSO_merge"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_NEW_METHOD, 0), "DSO_new_method"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_PATHBYADDR, 0), "DSO_pathbyaddr"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_SET_FILENAME, 0), "DSO_set_filename"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_UP_REF, 0), "DSO_up_ref"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_VMS_BIND_SYM, 0), "vms_bind_sym"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_VMS_LOAD, 0), "vms_load"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_VMS_MERGER, 0), "vms_merger"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_VMS_UNLOAD, 0), "vms_unload"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_WIN32_BIND_FUNC, 0), "win32_bind_func"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_WIN32_GLOBALLOOKUP, 0), "win32_globallookup"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_WIN32_JOINER, 0), "win32_joiner"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_WIN32_LOAD, 0), "win32_load"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_WIN32_MERGER, 0), "win32_merger"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_WIN32_NAME_CONVERTER, 0), + "win32_name_converter"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_WIN32_PATHBYADDR, 0), ""}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_WIN32_SPLITTER, 0), "win32_splitter"}, + {ERR_PACK(ERR_LIB_DSO, DSO_F_WIN32_UNLOAD, 0), "win32_unload"}, + {0, NULL} +}; + +static const ERR_STRING_DATA DSO_str_reasons[] = { + {ERR_PACK(ERR_LIB_DSO, 0, DSO_R_CTRL_FAILED), "control command failed"}, + {ERR_PACK(ERR_LIB_DSO, 0, DSO_R_DSO_ALREADY_LOADED), "dso already loaded"}, + {ERR_PACK(ERR_LIB_DSO, 0, DSO_R_EMPTY_FILE_STRUCTURE), + "empty file structure"}, + {ERR_PACK(ERR_LIB_DSO, 0, DSO_R_FAILURE), "failure"}, + {ERR_PACK(ERR_LIB_DSO, 0, DSO_R_FILENAME_TOO_BIG), "filename too big"}, + {ERR_PACK(ERR_LIB_DSO, 0, DSO_R_FINISH_FAILED), + "cleanup method function failed"}, + {ERR_PACK(ERR_LIB_DSO, 0, DSO_R_INCORRECT_FILE_SYNTAX), + "incorrect file syntax"}, + {ERR_PACK(ERR_LIB_DSO, 0, DSO_R_LOAD_FAILED), + "could not load the shared library"}, + {ERR_PACK(ERR_LIB_DSO, 0, DSO_R_NAME_TRANSLATION_FAILED), + "name translation failed"}, + {ERR_PACK(ERR_LIB_DSO, 0, DSO_R_NO_FILENAME), "no filename"}, + {ERR_PACK(ERR_LIB_DSO, 0, DSO_R_NULL_HANDLE), + "a null shared library handle was used"}, + {ERR_PACK(ERR_LIB_DSO, 0, DSO_R_SET_FILENAME_FAILED), + "set filename failed"}, + {ERR_PACK(ERR_LIB_DSO, 0, DSO_R_STACK_ERROR), + "the meth_data stack is corrupt"}, + {ERR_PACK(ERR_LIB_DSO, 0, DSO_R_SYM_FAILURE), + "could not bind to the requested symbol name"}, + {ERR_PACK(ERR_LIB_DSO, 0, DSO_R_UNLOAD_FAILED), + "could not unload the shared library"}, + {ERR_PACK(ERR_LIB_DSO, 0, DSO_R_UNSUPPORTED), + "functionality not supported"}, + {0, NULL} +}; + +#endif + +int ERR_load_DSO_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(DSO_str_functs[0].error) == NULL) { + ERR_load_strings_const(DSO_str_functs); + ERR_load_strings_const(DSO_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_lib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_lib.c new file mode 100644 index 000000000..2e75021d3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_lib.c @@ -0,0 +1,350 @@ +/* + * Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "dso_locl.h" +#include "internal/refcount.h" + +static DSO_METHOD *default_DSO_meth = NULL; + +static DSO *DSO_new_method(DSO_METHOD *meth) +{ + DSO *ret; + + if (default_DSO_meth == NULL) { + /* + * We default to DSO_METH_openssl() which in turn defaults to + * stealing the "best available" method. Will fallback to + * DSO_METH_null() in the worst case. + */ + default_DSO_meth = DSO_METHOD_openssl(); + } + ret = OPENSSL_zalloc(sizeof(*ret)); + if (ret == NULL) { + DSOerr(DSO_F_DSO_NEW_METHOD, ERR_R_MALLOC_FAILURE); + return NULL; + } + ret->meth_data = sk_void_new_null(); + if (ret->meth_data == NULL) { + /* sk_new doesn't generate any errors so we do */ + DSOerr(DSO_F_DSO_NEW_METHOD, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ret); + return NULL; + } + ret->meth = default_DSO_meth; + ret->references = 1; + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) { + DSOerr(DSO_F_DSO_NEW_METHOD, ERR_R_MALLOC_FAILURE); + sk_void_free(ret->meth_data); + OPENSSL_free(ret); + return NULL; + } + + if ((ret->meth->init != NULL) && !ret->meth->init(ret)) { + DSO_free(ret); + ret = NULL; + } + + return ret; +} + +DSO *DSO_new(void) +{ + return DSO_new_method(NULL); +} + +int DSO_free(DSO *dso) +{ + int i; + + if (dso == NULL) + return 1; + + if (CRYPTO_DOWN_REF(&dso->references, &i, dso->lock) <= 0) + return 0; + + REF_PRINT_COUNT("DSO", dso); + if (i > 0) + return 1; + REF_ASSERT_ISNT(i < 0); + + if ((dso->flags & DSO_FLAG_NO_UNLOAD_ON_FREE) == 0) { + if ((dso->meth->dso_unload != NULL) && !dso->meth->dso_unload(dso)) { + DSOerr(DSO_F_DSO_FREE, DSO_R_UNLOAD_FAILED); + return 0; + } + } + + if ((dso->meth->finish != NULL) && !dso->meth->finish(dso)) { + DSOerr(DSO_F_DSO_FREE, DSO_R_FINISH_FAILED); + return 0; + } + + sk_void_free(dso->meth_data); + OPENSSL_free(dso->filename); + OPENSSL_free(dso->loaded_filename); + CRYPTO_THREAD_lock_free(dso->lock); + OPENSSL_free(dso); + return 1; +} + +int DSO_flags(DSO *dso) +{ + return ((dso == NULL) ? 0 : dso->flags); +} + +int DSO_up_ref(DSO *dso) +{ + int i; + + if (dso == NULL) { + DSOerr(DSO_F_DSO_UP_REF, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (CRYPTO_UP_REF(&dso->references, &i, dso->lock) <= 0) + return 0; + + REF_PRINT_COUNT("DSO", r); + REF_ASSERT_ISNT(i < 2); + return ((i > 1) ? 1 : 0); +} + +DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth, int flags) +{ + DSO *ret; + int allocated = 0; + + if (dso == NULL) { + ret = DSO_new_method(meth); + if (ret == NULL) { + DSOerr(DSO_F_DSO_LOAD, ERR_R_MALLOC_FAILURE); + goto err; + } + allocated = 1; + /* Pass the provided flags to the new DSO object */ + if (DSO_ctrl(ret, DSO_CTRL_SET_FLAGS, flags, NULL) < 0) { + DSOerr(DSO_F_DSO_LOAD, DSO_R_CTRL_FAILED); + goto err; + } + } else + ret = dso; + /* Don't load if we're currently already loaded */ + if (ret->filename != NULL) { + DSOerr(DSO_F_DSO_LOAD, DSO_R_DSO_ALREADY_LOADED); + goto err; + } + /* + * filename can only be NULL if we were passed a dso that already has one + * set. + */ + if (filename != NULL) + if (!DSO_set_filename(ret, filename)) { + DSOerr(DSO_F_DSO_LOAD, DSO_R_SET_FILENAME_FAILED); + goto err; + } + filename = ret->filename; + if (filename == NULL) { + DSOerr(DSO_F_DSO_LOAD, DSO_R_NO_FILENAME); + goto err; + } + if (ret->meth->dso_load == NULL) { + DSOerr(DSO_F_DSO_LOAD, DSO_R_UNSUPPORTED); + goto err; + } + if (!ret->meth->dso_load(ret)) { + DSOerr(DSO_F_DSO_LOAD, DSO_R_LOAD_FAILED); + goto err; + } + /* Load succeeded */ + return ret; + err: + if (allocated) + DSO_free(ret); + return NULL; +} + +DSO_FUNC_TYPE DSO_bind_func(DSO *dso, const char *symname) +{ + DSO_FUNC_TYPE ret = NULL; + + if ((dso == NULL) || (symname == NULL)) { + DSOerr(DSO_F_DSO_BIND_FUNC, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + if (dso->meth->dso_bind_func == NULL) { + DSOerr(DSO_F_DSO_BIND_FUNC, DSO_R_UNSUPPORTED); + return NULL; + } + if ((ret = dso->meth->dso_bind_func(dso, symname)) == NULL) { + DSOerr(DSO_F_DSO_BIND_FUNC, DSO_R_SYM_FAILURE); + return NULL; + } + /* Success */ + return ret; +} + +/* + * I don't really like these *_ctrl functions very much to be perfectly + * honest. For one thing, I think I have to return a negative value for any + * error because possible DSO_ctrl() commands may return values such as + * "size"s that can legitimately be zero (making the standard + * "if (DSO_cmd(...))" form that works almost everywhere else fail at odd + * times. I'd prefer "output" values to be passed by reference and the return + * value as success/failure like usual ... but we conform when we must... :-) + */ +long DSO_ctrl(DSO *dso, int cmd, long larg, void *parg) +{ + if (dso == NULL) { + DSOerr(DSO_F_DSO_CTRL, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + /* + * We should intercept certain generic commands and only pass control to + * the method-specific ctrl() function if it's something we don't handle. + */ + switch (cmd) { + case DSO_CTRL_GET_FLAGS: + return dso->flags; + case DSO_CTRL_SET_FLAGS: + dso->flags = (int)larg; + return 0; + case DSO_CTRL_OR_FLAGS: + dso->flags |= (int)larg; + return 0; + default: + break; + } + if ((dso->meth == NULL) || (dso->meth->dso_ctrl == NULL)) { + DSOerr(DSO_F_DSO_CTRL, DSO_R_UNSUPPORTED); + return -1; + } + return dso->meth->dso_ctrl(dso, cmd, larg, parg); +} + +const char *DSO_get_filename(DSO *dso) +{ + if (dso == NULL) { + DSOerr(DSO_F_DSO_GET_FILENAME, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + return dso->filename; +} + +int DSO_set_filename(DSO *dso, const char *filename) +{ + char *copied; + + if ((dso == NULL) || (filename == NULL)) { + DSOerr(DSO_F_DSO_SET_FILENAME, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (dso->loaded_filename) { + DSOerr(DSO_F_DSO_SET_FILENAME, DSO_R_DSO_ALREADY_LOADED); + return 0; + } + /* We'll duplicate filename */ + copied = OPENSSL_strdup(filename); + if (copied == NULL) { + DSOerr(DSO_F_DSO_SET_FILENAME, ERR_R_MALLOC_FAILURE); + return 0; + } + OPENSSL_free(dso->filename); + dso->filename = copied; + return 1; +} + +char *DSO_merge(DSO *dso, const char *filespec1, const char *filespec2) +{ + char *result = NULL; + + if (dso == NULL || filespec1 == NULL) { + DSOerr(DSO_F_DSO_MERGE, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + if ((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0) { + if (dso->merger != NULL) + result = dso->merger(dso, filespec1, filespec2); + else if (dso->meth->dso_merger != NULL) + result = dso->meth->dso_merger(dso, filespec1, filespec2); + } + return result; +} + +char *DSO_convert_filename(DSO *dso, const char *filename) +{ + char *result = NULL; + + if (dso == NULL) { + DSOerr(DSO_F_DSO_CONVERT_FILENAME, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + if (filename == NULL) + filename = dso->filename; + if (filename == NULL) { + DSOerr(DSO_F_DSO_CONVERT_FILENAME, DSO_R_NO_FILENAME); + return NULL; + } + if ((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0) { + if (dso->name_converter != NULL) + result = dso->name_converter(dso, filename); + else if (dso->meth->dso_name_converter != NULL) + result = dso->meth->dso_name_converter(dso, filename); + } + if (result == NULL) { + result = OPENSSL_strdup(filename); + if (result == NULL) { + DSOerr(DSO_F_DSO_CONVERT_FILENAME, ERR_R_MALLOC_FAILURE); + return NULL; + } + } + return result; +} + +int DSO_pathbyaddr(void *addr, char *path, int sz) +{ + DSO_METHOD *meth = default_DSO_meth; + if (meth == NULL) + meth = DSO_METHOD_openssl(); + if (meth->pathbyaddr == NULL) { + DSOerr(DSO_F_DSO_PATHBYADDR, DSO_R_UNSUPPORTED); + return -1; + } + return (*meth->pathbyaddr) (addr, path, sz); +} + +DSO *DSO_dsobyaddr(void *addr, int flags) +{ + DSO *ret = NULL; + char *filename = NULL; + int len = DSO_pathbyaddr(addr, NULL, 0); + + if (len < 0) + return NULL; + + filename = OPENSSL_malloc(len); + if (filename != NULL + && DSO_pathbyaddr(addr, filename, len) == len) + ret = DSO_load(NULL, filename, NULL, flags); + + OPENSSL_free(filename); + return ret; +} + +void *DSO_global_lookup(const char *name) +{ + DSO_METHOD *meth = default_DSO_meth; + if (meth == NULL) + meth = DSO_METHOD_openssl(); + if (meth->globallookup == NULL) { + DSOerr(DSO_F_DSO_GLOBAL_LOOKUP, DSO_R_UNSUPPORTED); + return NULL; + } + return (*meth->globallookup) (name); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_locl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_locl.h new file mode 100644 index 000000000..14a0ccb7c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_locl.h @@ -0,0 +1,107 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include "internal/dso.h" +#include "internal/dso_conf.h" +#include "internal/refcount.h" + +/**********************************************************************/ +/* The low-level handle type used to refer to a loaded shared library */ + +struct dso_st { + DSO_METHOD *meth; + /* + * Standard dlopen uses a (void *). Win32 uses a HANDLE. VMS doesn't use + * anything but will need to cache the filename for use in the dso_bind + * handler. All in all, let each method control its own destiny. + * "Handles" and such go in a STACK. + */ + STACK_OF(void) *meth_data; + CRYPTO_REF_COUNT references; + int flags; + /* + * For use by applications etc ... use this for your bits'n'pieces, don't + * touch meth_data! + */ + CRYPTO_EX_DATA ex_data; + /* + * If this callback function pointer is set to non-NULL, then it will be + * used in DSO_load() in place of meth->dso_name_converter. NB: This + * should normally set using DSO_set_name_converter(). + */ + DSO_NAME_CONVERTER_FUNC name_converter; + /* + * If this callback function pointer is set to non-NULL, then it will be + * used in DSO_load() in place of meth->dso_merger. NB: This should + * normally set using DSO_set_merger(). + */ + DSO_MERGER_FUNC merger; + /* + * This is populated with (a copy of) the platform-independent filename + * used for this DSO. + */ + char *filename; + /* + * This is populated with (a copy of) the translated filename by which + * the DSO was actually loaded. It is NULL iff the DSO is not currently + * loaded. NB: This is here because the filename translation process may + * involve a callback being invoked more than once not only to convert to + * a platform-specific form, but also to try different filenames in the + * process of trying to perform a load. As such, this variable can be + * used to indicate (a) whether this DSO structure corresponds to a + * loaded library or not, and (b) the filename with which it was actually + * loaded. + */ + char *loaded_filename; + CRYPTO_RWLOCK *lock; +}; + +struct dso_meth_st { + const char *name; + /* + * Loads a shared library, NB: new DSO_METHODs must ensure that a + * successful load populates the loaded_filename field, and likewise a + * successful unload OPENSSL_frees and NULLs it out. + */ + int (*dso_load) (DSO *dso); + /* Unloads a shared library */ + int (*dso_unload) (DSO *dso); + /* + * Binds a function - assumes a return type of DSO_FUNC_TYPE. This should + * be cast to the real function prototype by the caller. Platforms that + * don't have compatible representations for different prototypes (this + * is possible within ANSI C) are highly unlikely to have shared + * libraries at all, let alone a DSO_METHOD implemented for them. + */ + DSO_FUNC_TYPE (*dso_bind_func) (DSO *dso, const char *symname); + /* + * The generic (yuck) "ctrl()" function. NB: Negative return values + * (rather than zero) indicate errors. + */ + long (*dso_ctrl) (DSO *dso, int cmd, long larg, void *parg); + /* + * The default DSO_METHOD-specific function for converting filenames to a + * canonical native form. + */ + DSO_NAME_CONVERTER_FUNC dso_name_converter; + /* + * The default DSO_METHOD-specific function for converting filenames to a + * canonical native form. + */ + DSO_MERGER_FUNC dso_merger; + /* [De]Initialisation handlers. */ + int (*init) (DSO *dso); + int (*finish) (DSO *dso); + /* Return pathname of the module containing location */ + int (*pathbyaddr) (void *addr, char *path, int sz); + /* Perform global symbol lookup, i.e. among *all* modules */ + void *(*globallookup) (const char *symname); +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_openssl.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_openssl.c new file mode 100644 index 000000000..6626331e9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_openssl.c @@ -0,0 +1,22 @@ +/* + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "dso_locl.h" + +#if !defined(DSO_VMS) && !defined(DSO_DLCFN) && !defined(DSO_DL) && !defined(DSO_WIN32) && !defined(DSO_DLFCN) + +static DSO_METHOD dso_meth_null = { + "NULL shared library method" +}; + +DSO_METHOD *DSO_METHOD_openssl(void) +{ + return &dso_meth_null; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_vms.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_vms.c new file mode 100644 index 000000000..178e72579 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_vms.c @@ -0,0 +1,466 @@ +/* + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "dso_locl.h" + +#ifdef OPENSSL_SYS_VMS + +# pragma message disable DOLLARID +# include +# include +# include +# include +# include +# include +# include +# include "../vms_rms.h" + +/* Some compiler options may mask the declaration of "_malloc32". */ +# if __INITIAL_POINTER_SIZE && defined _ANSI_C_SOURCE +# if __INITIAL_POINTER_SIZE == 64 +# pragma pointer_size save +# pragma pointer_size 32 +void *_malloc32(__size_t); +# pragma pointer_size restore +# endif /* __INITIAL_POINTER_SIZE == 64 */ +# endif /* __INITIAL_POINTER_SIZE && defined + * _ANSI_C_SOURCE */ + +# pragma message disable DOLLARID + +static int vms_load(DSO *dso); +static int vms_unload(DSO *dso); +static DSO_FUNC_TYPE vms_bind_func(DSO *dso, const char *symname); +static char *vms_name_converter(DSO *dso, const char *filename); +static char *vms_merger(DSO *dso, const char *filespec1, + const char *filespec2); + +static DSO_METHOD dso_meth_vms = { + "OpenSSL 'VMS' shared library method", + vms_load, + NULL, /* unload */ + vms_bind_func, + NULL, /* ctrl */ + vms_name_converter, + vms_merger, + NULL, /* init */ + NULL, /* finish */ + NULL, /* pathbyaddr */ + NULL /* globallookup */ +}; + +/* + * On VMS, the only "handle" is the file name. LIB$FIND_IMAGE_SYMBOL depends + * on the reference to the file name being the same for all calls regarding + * one shared image, so we'll just store it in an instance of the following + * structure and put a pointer to that instance in the meth_data stack. + */ +typedef struct dso_internal_st { + /* + * This should contain the name only, no directory, no extension, nothing + * but a name. + */ + struct dsc$descriptor_s filename_dsc; + char filename[NAMX_MAXRSS + 1]; + /* + * This contains whatever is not in filename, if needed. Normally not + * defined. + */ + struct dsc$descriptor_s imagename_dsc; + char imagename[NAMX_MAXRSS + 1]; +} DSO_VMS_INTERNAL; + +DSO_METHOD *DSO_METHOD_openssl(void) +{ + return &dso_meth_vms; +} + +static int vms_load(DSO *dso) +{ + void *ptr = NULL; + /* See applicable comments in dso_dl.c */ + char *filename = DSO_convert_filename(dso, NULL); + +/* Ensure 32-bit pointer for "p", and appropriate malloc() function. */ +# if __INITIAL_POINTER_SIZE == 64 +# define DSO_MALLOC _malloc32 +# pragma pointer_size save +# pragma pointer_size 32 +# else /* __INITIAL_POINTER_SIZE == 64 */ +# define DSO_MALLOC OPENSSL_malloc +# endif /* __INITIAL_POINTER_SIZE == 64 [else] */ + + DSO_VMS_INTERNAL *p = NULL; + +# if __INITIAL_POINTER_SIZE == 64 +# pragma pointer_size restore +# endif /* __INITIAL_POINTER_SIZE == 64 */ + + const char *sp1, *sp2; /* Search result */ + const char *ext = NULL; /* possible extension to add */ + + if (filename == NULL) { + DSOerr(DSO_F_VMS_LOAD, DSO_R_NO_FILENAME); + goto err; + } + + /*- + * A file specification may look like this: + * + * node::dev:[dir-spec]name.type;ver + * + * or (for compatibility with TOPS-20): + * + * node::dev:name.type;ver + * + * and the dir-spec uses '.' as separator. Also, a dir-spec + * may consist of several parts, with mixed use of [] and <>: + * + * [dir1.] + * + * We need to split the file specification into the name and + * the rest (both before and after the name itself). + */ + /* + * Start with trying to find the end of a dir-spec, and save the position + * of the byte after in sp1 + */ + sp1 = strrchr(filename, ']'); + sp2 = strrchr(filename, '>'); + if (sp1 == NULL) + sp1 = sp2; + if (sp2 != NULL && sp2 > sp1) + sp1 = sp2; + if (sp1 == NULL) + sp1 = strrchr(filename, ':'); + if (sp1 == NULL) + sp1 = filename; + else + sp1++; /* The byte after the found character */ + /* Now, let's see if there's a type, and save the position in sp2 */ + sp2 = strchr(sp1, '.'); + /* + * If there is a period and the next character is a semi-colon, + * we need to add an extension + */ + if (sp2 != NULL && sp2[1] == ';') + ext = ".EXE"; + /* + * If we found it, that's where we'll cut. Otherwise, look for a version + * number and save the position in sp2 + */ + if (sp2 == NULL) { + sp2 = strchr(sp1, ';'); + ext = ".EXE"; + } + /* + * If there was still nothing to find, set sp2 to point at the end of the + * string + */ + if (sp2 == NULL) + sp2 = sp1 + strlen(sp1); + + /* Check that we won't get buffer overflows */ + if (sp2 - sp1 > FILENAME_MAX + || (sp1 - filename) + strlen(sp2) > FILENAME_MAX) { + DSOerr(DSO_F_VMS_LOAD, DSO_R_FILENAME_TOO_BIG); + goto err; + } + + p = DSO_MALLOC(sizeof(*p)); + if (p == NULL) { + DSOerr(DSO_F_VMS_LOAD, ERR_R_MALLOC_FAILURE); + goto err; + } + + strncpy(p->filename, sp1, sp2 - sp1); + p->filename[sp2 - sp1] = '\0'; + + strncpy(p->imagename, filename, sp1 - filename); + p->imagename[sp1 - filename] = '\0'; + if (ext) { + strcat(p->imagename, ext); + if (*sp2 == '.') + sp2++; + } + strcat(p->imagename, sp2); + + p->filename_dsc.dsc$w_length = strlen(p->filename); + p->filename_dsc.dsc$b_dtype = DSC$K_DTYPE_T; + p->filename_dsc.dsc$b_class = DSC$K_CLASS_S; + p->filename_dsc.dsc$a_pointer = p->filename; + p->imagename_dsc.dsc$w_length = strlen(p->imagename); + p->imagename_dsc.dsc$b_dtype = DSC$K_DTYPE_T; + p->imagename_dsc.dsc$b_class = DSC$K_CLASS_S; + p->imagename_dsc.dsc$a_pointer = p->imagename; + + if (!sk_void_push(dso->meth_data, (char *)p)) { + DSOerr(DSO_F_VMS_LOAD, DSO_R_STACK_ERROR); + goto err; + } + + /* Success (for now, we lie. We actually do not know...) */ + dso->loaded_filename = filename; + return 1; + err: + /* Cleanup! */ + OPENSSL_free(p); + OPENSSL_free(filename); + return 0; +} + +/* + * Note that this doesn't actually unload the shared image, as there is no + * such thing in VMS. Next time it get loaded again, a new copy will + * actually be loaded. + */ +static int vms_unload(DSO *dso) +{ + DSO_VMS_INTERNAL *p; + if (dso == NULL) { + DSOerr(DSO_F_VMS_UNLOAD, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (sk_void_num(dso->meth_data) < 1) + return 1; + p = (DSO_VMS_INTERNAL *)sk_void_pop(dso->meth_data); + if (p == NULL) { + DSOerr(DSO_F_VMS_UNLOAD, DSO_R_NULL_HANDLE); + return 0; + } + /* Cleanup */ + OPENSSL_free(p); + return 1; +} + +/* + * We must do this in a separate function because of the way the exception + * handler works (it makes this function return + */ +static int do_find_symbol(DSO_VMS_INTERNAL *ptr, + struct dsc$descriptor_s *symname_dsc, void **sym, + unsigned long flags) +{ + /* + * Make sure that signals are caught and returned instead of aborting the + * program. The exception handler gets unestablished automatically on + * return from this function. + */ + lib$establish(lib$sig_to_ret); + + if (ptr->imagename_dsc.dsc$w_length) + return lib$find_image_symbol(&ptr->filename_dsc, + symname_dsc, sym, + &ptr->imagename_dsc, flags); + else + return lib$find_image_symbol(&ptr->filename_dsc, + symname_dsc, sym, 0, flags); +} + +# ifndef LIB$M_FIS_MIXEDCASE +# define LIB$M_FIS_MIXEDCASE (1 << 4); +# endif +void vms_bind_sym(DSO *dso, const char *symname, void **sym) +{ + DSO_VMS_INTERNAL *ptr; + int status = 0; + struct dsc$descriptor_s symname_dsc; + +/* Arrange 32-bit pointer to (copied) string storage, if needed. */ +# if __INITIAL_POINTER_SIZE == 64 +# define SYMNAME symname_32p +# pragma pointer_size save +# pragma pointer_size 32 + char *symname_32p; +# pragma pointer_size restore + char symname_32[NAMX_MAXRSS + 1]; +# else /* __INITIAL_POINTER_SIZE == 64 */ +# define SYMNAME ((char *) symname) +# endif /* __INITIAL_POINTER_SIZE == 64 [else] */ + + *sym = NULL; + + if ((dso == NULL) || (symname == NULL)) { + DSOerr(DSO_F_VMS_BIND_SYM, ERR_R_PASSED_NULL_PARAMETER); + return; + } +# if __INITIAL_POINTER_SIZE == 64 + /* Copy the symbol name to storage with a 32-bit pointer. */ + symname_32p = symname_32; + strcpy(symname_32p, symname); +# endif /* __INITIAL_POINTER_SIZE == 64 [else] */ + + symname_dsc.dsc$w_length = strlen(SYMNAME); + symname_dsc.dsc$b_dtype = DSC$K_DTYPE_T; + symname_dsc.dsc$b_class = DSC$K_CLASS_S; + symname_dsc.dsc$a_pointer = SYMNAME; + + if (sk_void_num(dso->meth_data) < 1) { + DSOerr(DSO_F_VMS_BIND_SYM, DSO_R_STACK_ERROR); + return; + } + ptr = (DSO_VMS_INTERNAL *)sk_void_value(dso->meth_data, + sk_void_num(dso->meth_data) - 1); + if (ptr == NULL) { + DSOerr(DSO_F_VMS_BIND_SYM, DSO_R_NULL_HANDLE); + return; + } + + status = do_find_symbol(ptr, &symname_dsc, sym, LIB$M_FIS_MIXEDCASE); + + if (!$VMS_STATUS_SUCCESS(status)) + status = do_find_symbol(ptr, &symname_dsc, sym, 0); + + if (!$VMS_STATUS_SUCCESS(status)) { + unsigned short length; + char errstring[257]; + struct dsc$descriptor_s errstring_dsc; + + errstring_dsc.dsc$w_length = sizeof(errstring); + errstring_dsc.dsc$b_dtype = DSC$K_DTYPE_T; + errstring_dsc.dsc$b_class = DSC$K_CLASS_S; + errstring_dsc.dsc$a_pointer = errstring; + + *sym = NULL; + + status = sys$getmsg(status, &length, &errstring_dsc, 1, 0); + + if (!$VMS_STATUS_SUCCESS(status)) + lib$signal(status); /* This is really bad. Abort! */ + else { + errstring[length] = '\0'; + + DSOerr(DSO_F_VMS_BIND_SYM, DSO_R_SYM_FAILURE); + if (ptr->imagename_dsc.dsc$w_length) + ERR_add_error_data(9, + "Symbol ", symname, + " in ", ptr->filename, + " (", ptr->imagename, ")", + ": ", errstring); + else + ERR_add_error_data(6, + "Symbol ", symname, + " in ", ptr->filename, ": ", errstring); + } + return; + } + return; +} + +static DSO_FUNC_TYPE vms_bind_func(DSO *dso, const char *symname) +{ + DSO_FUNC_TYPE sym = 0; + vms_bind_sym(dso, symname, (void **)&sym); + return sym; +} + +static char *vms_merger(DSO *dso, const char *filespec1, + const char *filespec2) +{ + int status; + int filespec1len, filespec2len; + struct FAB fab; + struct NAMX_STRUCT nam; + char esa[NAMX_MAXRSS + 1]; + char *merged; + +/* Arrange 32-bit pointer to (copied) string storage, if needed. */ +# if __INITIAL_POINTER_SIZE == 64 +# define FILESPEC1 filespec1_32p; +# define FILESPEC2 filespec2_32p; +# pragma pointer_size save +# pragma pointer_size 32 + char *filespec1_32p; + char *filespec2_32p; +# pragma pointer_size restore + char filespec1_32[NAMX_MAXRSS + 1]; + char filespec2_32[NAMX_MAXRSS + 1]; +# else /* __INITIAL_POINTER_SIZE == 64 */ +# define FILESPEC1 ((char *) filespec1) +# define FILESPEC2 ((char *) filespec2) +# endif /* __INITIAL_POINTER_SIZE == 64 [else] */ + + if (!filespec1) + filespec1 = ""; + if (!filespec2) + filespec2 = ""; + filespec1len = strlen(filespec1); + filespec2len = strlen(filespec2); + +# if __INITIAL_POINTER_SIZE == 64 + /* Copy the file names to storage with a 32-bit pointer. */ + filespec1_32p = filespec1_32; + filespec2_32p = filespec2_32; + strcpy(filespec1_32p, filespec1); + strcpy(filespec2_32p, filespec2); +# endif /* __INITIAL_POINTER_SIZE == 64 [else] */ + + fab = cc$rms_fab; + nam = CC_RMS_NAMX; + + FAB_OR_NAML(fab, nam).FAB_OR_NAML_FNA = FILESPEC1; + FAB_OR_NAML(fab, nam).FAB_OR_NAML_FNS = filespec1len; + FAB_OR_NAML(fab, nam).FAB_OR_NAML_DNA = FILESPEC2; + FAB_OR_NAML(fab, nam).FAB_OR_NAML_DNS = filespec2len; + NAMX_DNA_FNA_SET(fab) + + nam.NAMX_ESA = esa; + nam.NAMX_ESS = NAMX_MAXRSS; + nam.NAMX_NOP = NAM$M_SYNCHK | NAM$M_PWD; + SET_NAMX_NO_SHORT_UPCASE(nam); + + fab.FAB_NAMX = &nam; + + status = sys$parse(&fab, 0, 0); + + if (!$VMS_STATUS_SUCCESS(status)) { + unsigned short length; + char errstring[257]; + struct dsc$descriptor_s errstring_dsc; + + errstring_dsc.dsc$w_length = sizeof(errstring); + errstring_dsc.dsc$b_dtype = DSC$K_DTYPE_T; + errstring_dsc.dsc$b_class = DSC$K_CLASS_S; + errstring_dsc.dsc$a_pointer = errstring; + + status = sys$getmsg(status, &length, &errstring_dsc, 1, 0); + + if (!$VMS_STATUS_SUCCESS(status)) + lib$signal(status); /* This is really bad. Abort! */ + else { + errstring[length] = '\0'; + + DSOerr(DSO_F_VMS_MERGER, DSO_R_FAILURE); + ERR_add_error_data(7, + "filespec \"", filespec1, "\", ", + "defaults \"", filespec2, "\": ", errstring); + } + return NULL; + } + + merged = OPENSSL_malloc(nam.NAMX_ESL + 1); + if (merged == NULL) + goto malloc_err; + strncpy(merged, nam.NAMX_ESA, nam.NAMX_ESL); + merged[nam.NAMX_ESL] = '\0'; + return merged; + malloc_err: + DSOerr(DSO_F_VMS_MERGER, ERR_R_MALLOC_FAILURE); +} + +static char *vms_name_converter(DSO *dso, const char *filename) +{ + int len = strlen(filename); + char *not_translated = OPENSSL_malloc(len + 1); + if (not_translated != NULL) + strcpy(not_translated, filename); + return not_translated; +} + +#endif /* OPENSSL_SYS_VMS */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_win32.c b/trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_win32.c new file mode 100644 index 000000000..0bbf5b518 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/dso/dso_win32.c @@ -0,0 +1,566 @@ +/* + * Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "e_os.h" +#include "dso_locl.h" + +#if defined(DSO_WIN32) + +# ifdef _WIN32_WCE +# if _WIN32_WCE < 300 +static FARPROC GetProcAddressA(HMODULE hModule, LPCSTR lpProcName) +{ + WCHAR lpProcNameW[64]; + int i; + + for (i = 0; lpProcName[i] && i < 64; i++) + lpProcNameW[i] = (WCHAR)lpProcName[i]; + if (i == 64) + return NULL; + lpProcNameW[i] = 0; + + return GetProcAddressW(hModule, lpProcNameW); +} +# endif +# undef GetProcAddress +# define GetProcAddress GetProcAddressA + +static HINSTANCE LoadLibraryA(LPCSTR lpLibFileName) +{ + WCHAR *fnamw; + size_t len_0 = strlen(lpLibFileName) + 1, i; + +# ifdef _MSC_VER + fnamw = (WCHAR *)_alloca(len_0 * sizeof(WCHAR)); +# else + fnamw = (WCHAR *)alloca(len_0 * sizeof(WCHAR)); +# endif + if (fnamw == NULL) { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return NULL; + } +# if defined(_WIN32_WCE) && _WIN32_WCE>=101 + if (!MultiByteToWideChar(CP_ACP, 0, lpLibFileName, len_0, fnamw, len_0)) +# endif + for (i = 0; i < len_0; i++) + fnamw[i] = (WCHAR)lpLibFileName[i]; + + return LoadLibraryW(fnamw); +} +# endif + +/* Part of the hack in "win32_load" ... */ +# define DSO_MAX_TRANSLATED_SIZE 256 + +static int win32_load(DSO *dso); +static int win32_unload(DSO *dso); +static DSO_FUNC_TYPE win32_bind_func(DSO *dso, const char *symname); +static char *win32_name_converter(DSO *dso, const char *filename); +static char *win32_merger(DSO *dso, const char *filespec1, + const char *filespec2); +static void *win32_globallookup(const char *name); + +static const char *openssl_strnchr(const char *string, int c, size_t len); + +static DSO_METHOD dso_meth_win32 = { + "OpenSSL 'win32' shared library method", + win32_load, + win32_unload, + win32_bind_func, + NULL, /* ctrl */ + win32_name_converter, + win32_merger, + NULL, /* init */ + NULL, /* finish */ + NULL, /* pathbyaddr */ + win32_globallookup +}; + +DSO_METHOD *DSO_METHOD_openssl(void) +{ + return &dso_meth_win32; +} + +/* + * For this DSO_METHOD, our meth_data STACK will contain; (i) a pointer to + * the handle (HINSTANCE) returned from LoadLibrary(), and copied. + */ + +static int win32_load(DSO *dso) +{ + HINSTANCE h = NULL, *p = NULL; + /* See applicable comments from dso_dl.c */ + char *filename = DSO_convert_filename(dso, NULL); + + if (filename == NULL) { + DSOerr(DSO_F_WIN32_LOAD, DSO_R_NO_FILENAME); + goto err; + } + h = LoadLibraryA(filename); + if (h == NULL) { + DSOerr(DSO_F_WIN32_LOAD, DSO_R_LOAD_FAILED); + ERR_add_error_data(3, "filename(", filename, ")"); + goto err; + } + p = OPENSSL_malloc(sizeof(*p)); + if (p == NULL) { + DSOerr(DSO_F_WIN32_LOAD, ERR_R_MALLOC_FAILURE); + goto err; + } + *p = h; + if (!sk_void_push(dso->meth_data, p)) { + DSOerr(DSO_F_WIN32_LOAD, DSO_R_STACK_ERROR); + goto err; + } + /* Success */ + dso->loaded_filename = filename; + return 1; + err: + /* Cleanup ! */ + OPENSSL_free(filename); + OPENSSL_free(p); + if (h != NULL) + FreeLibrary(h); + return 0; +} + +static int win32_unload(DSO *dso) +{ + HINSTANCE *p; + if (dso == NULL) { + DSOerr(DSO_F_WIN32_UNLOAD, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (sk_void_num(dso->meth_data) < 1) + return 1; + p = sk_void_pop(dso->meth_data); + if (p == NULL) { + DSOerr(DSO_F_WIN32_UNLOAD, DSO_R_NULL_HANDLE); + return 0; + } + if (!FreeLibrary(*p)) { + DSOerr(DSO_F_WIN32_UNLOAD, DSO_R_UNLOAD_FAILED); + /* + * We should push the value back onto the stack in case of a retry. + */ + sk_void_push(dso->meth_data, p); + return 0; + } + /* Cleanup */ + OPENSSL_free(p); + return 1; +} + +static DSO_FUNC_TYPE win32_bind_func(DSO *dso, const char *symname) +{ + HINSTANCE *ptr; + union { + void *p; + FARPROC f; + } sym; + + if ((dso == NULL) || (symname == NULL)) { + DSOerr(DSO_F_WIN32_BIND_FUNC, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + if (sk_void_num(dso->meth_data) < 1) { + DSOerr(DSO_F_WIN32_BIND_FUNC, DSO_R_STACK_ERROR); + return NULL; + } + ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1); + if (ptr == NULL) { + DSOerr(DSO_F_WIN32_BIND_FUNC, DSO_R_NULL_HANDLE); + return NULL; + } + sym.f = GetProcAddress(*ptr, symname); + if (sym.p == NULL) { + DSOerr(DSO_F_WIN32_BIND_FUNC, DSO_R_SYM_FAILURE); + ERR_add_error_data(3, "symname(", symname, ")"); + return NULL; + } + return (DSO_FUNC_TYPE)sym.f; +} + +struct file_st { + const char *node; + int nodelen; + const char *device; + int devicelen; + const char *predir; + int predirlen; + const char *dir; + int dirlen; + const char *file; + int filelen; +}; + +static struct file_st *win32_splitter(DSO *dso, const char *filename, + int assume_last_is_dir) +{ + struct file_st *result = NULL; + enum { IN_NODE, IN_DEVICE, IN_FILE } position; + const char *start = filename; + char last; + + if (!filename) { + DSOerr(DSO_F_WIN32_SPLITTER, DSO_R_NO_FILENAME); + return NULL; + } + + result = OPENSSL_zalloc(sizeof(*result)); + if (result == NULL) { + DSOerr(DSO_F_WIN32_SPLITTER, ERR_R_MALLOC_FAILURE); + return NULL; + } + + position = IN_DEVICE; + + if ((filename[0] == '\\' && filename[1] == '\\') + || (filename[0] == '/' && filename[1] == '/')) { + position = IN_NODE; + filename += 2; + start = filename; + result->node = start; + } + + do { + last = filename[0]; + switch (last) { + case ':': + if (position != IN_DEVICE) { + DSOerr(DSO_F_WIN32_SPLITTER, DSO_R_INCORRECT_FILE_SYNTAX); + OPENSSL_free(result); + return NULL; + } + result->device = start; + result->devicelen = (int)(filename - start); + position = IN_FILE; + start = ++filename; + result->dir = start; + break; + case '\\': + case '/': + if (position == IN_NODE) { + result->nodelen = (int)(filename - start); + position = IN_FILE; + start = ++filename; + result->dir = start; + } else if (position == IN_DEVICE) { + position = IN_FILE; + filename++; + result->dir = start; + result->dirlen = (int)(filename - start); + start = filename; + } else { + filename++; + result->dirlen += (int)(filename - start); + start = filename; + } + break; + case '\0': + if (position == IN_NODE) { + result->nodelen = (int)(filename - start); + } else { + if (filename - start > 0) { + if (assume_last_is_dir) { + if (position == IN_DEVICE) { + result->dir = start; + result->dirlen = 0; + } + result->dirlen += (int)(filename - start); + } else { + result->file = start; + result->filelen = (int)(filename - start); + } + } + } + break; + default: + filename++; + break; + } + } + while (last); + + if (!result->nodelen) + result->node = NULL; + if (!result->devicelen) + result->device = NULL; + if (!result->dirlen) + result->dir = NULL; + if (!result->filelen) + result->file = NULL; + + return result; +} + +static char *win32_joiner(DSO *dso, const struct file_st *file_split) +{ + int len = 0, offset = 0; + char *result = NULL; + const char *start; + + if (!file_split) { + DSOerr(DSO_F_WIN32_JOINER, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + if (file_split->node) { + len += 2 + file_split->nodelen; /* 2 for starting \\ */ + if (file_split->predir || file_split->dir || file_split->file) + len++; /* 1 for ending \ */ + } else if (file_split->device) { + len += file_split->devicelen + 1; /* 1 for ending : */ + } + len += file_split->predirlen; + if (file_split->predir && (file_split->dir || file_split->file)) { + len++; /* 1 for ending \ */ + } + len += file_split->dirlen; + if (file_split->dir && file_split->file) { + len++; /* 1 for ending \ */ + } + len += file_split->filelen; + + if (!len) { + DSOerr(DSO_F_WIN32_JOINER, DSO_R_EMPTY_FILE_STRUCTURE); + return NULL; + } + + result = OPENSSL_malloc(len + 1); + if (result == NULL) { + DSOerr(DSO_F_WIN32_JOINER, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (file_split->node) { + strcpy(&result[offset], "\\\\"); + offset += 2; + strncpy(&result[offset], file_split->node, file_split->nodelen); + offset += file_split->nodelen; + if (file_split->predir || file_split->dir || file_split->file) { + result[offset] = '\\'; + offset++; + } + } else if (file_split->device) { + strncpy(&result[offset], file_split->device, file_split->devicelen); + offset += file_split->devicelen; + result[offset] = ':'; + offset++; + } + start = file_split->predir; + while (file_split->predirlen > (start - file_split->predir)) { + const char *end = openssl_strnchr(start, '/', + file_split->predirlen - (start - + file_split->predir)); + if (!end) + end = start + + file_split->predirlen - (start - file_split->predir); + strncpy(&result[offset], start, end - start); + offset += (int)(end - start); + result[offset] = '\\'; + offset++; + start = end + 1; + } + start = file_split->dir; + while (file_split->dirlen > (start - file_split->dir)) { + const char *end = openssl_strnchr(start, '/', + file_split->dirlen - (start - + file_split->dir)); + if (!end) + end = start + file_split->dirlen - (start - file_split->dir); + strncpy(&result[offset], start, end - start); + offset += (int)(end - start); + result[offset] = '\\'; + offset++; + start = end + 1; + } + strncpy(&result[offset], file_split->file, file_split->filelen); + offset += file_split->filelen; + result[offset] = '\0'; + return result; +} + +static char *win32_merger(DSO *dso, const char *filespec1, + const char *filespec2) +{ + char *merged = NULL; + struct file_st *filespec1_split = NULL; + struct file_st *filespec2_split = NULL; + + if (!filespec1 && !filespec2) { + DSOerr(DSO_F_WIN32_MERGER, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + if (!filespec2) { + merged = OPENSSL_strdup(filespec1); + if (merged == NULL) { + DSOerr(DSO_F_WIN32_MERGER, ERR_R_MALLOC_FAILURE); + return NULL; + } + } else if (!filespec1) { + merged = OPENSSL_strdup(filespec2); + if (merged == NULL) { + DSOerr(DSO_F_WIN32_MERGER, ERR_R_MALLOC_FAILURE); + return NULL; + } + } else { + filespec1_split = win32_splitter(dso, filespec1, 0); + if (!filespec1_split) { + DSOerr(DSO_F_WIN32_MERGER, ERR_R_MALLOC_FAILURE); + return NULL; + } + filespec2_split = win32_splitter(dso, filespec2, 1); + if (!filespec2_split) { + DSOerr(DSO_F_WIN32_MERGER, ERR_R_MALLOC_FAILURE); + OPENSSL_free(filespec1_split); + return NULL; + } + + /* Fill in into filespec1_split */ + if (!filespec1_split->node && !filespec1_split->device) { + filespec1_split->node = filespec2_split->node; + filespec1_split->nodelen = filespec2_split->nodelen; + filespec1_split->device = filespec2_split->device; + filespec1_split->devicelen = filespec2_split->devicelen; + } + if (!filespec1_split->dir) { + filespec1_split->dir = filespec2_split->dir; + filespec1_split->dirlen = filespec2_split->dirlen; + } else if (filespec1_split->dir[0] != '\\' + && filespec1_split->dir[0] != '/') { + filespec1_split->predir = filespec2_split->dir; + filespec1_split->predirlen = filespec2_split->dirlen; + } + if (!filespec1_split->file) { + filespec1_split->file = filespec2_split->file; + filespec1_split->filelen = filespec2_split->filelen; + } + + merged = win32_joiner(dso, filespec1_split); + } + OPENSSL_free(filespec1_split); + OPENSSL_free(filespec2_split); + return merged; +} + +static char *win32_name_converter(DSO *dso, const char *filename) +{ + char *translated; + int len, transform; + + len = strlen(filename); + transform = ((strstr(filename, "/") == NULL) && + (strstr(filename, "\\") == NULL) && + (strstr(filename, ":") == NULL)); + if (transform) + /* We will convert this to "%s.dll" */ + translated = OPENSSL_malloc(len + 5); + else + /* We will simply duplicate filename */ + translated = OPENSSL_malloc(len + 1); + if (translated == NULL) { + DSOerr(DSO_F_WIN32_NAME_CONVERTER, DSO_R_NAME_TRANSLATION_FAILED); + return NULL; + } + if (transform) + sprintf(translated, "%s.dll", filename); + else + sprintf(translated, "%s", filename); + return translated; +} + +static const char *openssl_strnchr(const char *string, int c, size_t len) +{ + size_t i; + const char *p; + for (i = 0, p = string; i < len && *p; i++, p++) { + if (*p == c) + return p; + } + return NULL; +} + +# include +# ifdef _WIN32_WCE +# define DLLNAME "TOOLHELP.DLL" +# else +# ifdef MODULEENTRY32 +# undef MODULEENTRY32 /* unmask the ASCII version! */ +# endif +# define DLLNAME "KERNEL32.DLL" +# endif + +typedef HANDLE(WINAPI *CREATETOOLHELP32SNAPSHOT) (DWORD, DWORD); +typedef BOOL(WINAPI *CLOSETOOLHELP32SNAPSHOT) (HANDLE); +typedef BOOL(WINAPI *MODULE32) (HANDLE, MODULEENTRY32 *); + +static void *win32_globallookup(const char *name) +{ + HMODULE dll; + HANDLE hModuleSnap = INVALID_HANDLE_VALUE; + MODULEENTRY32 me32; + CREATETOOLHELP32SNAPSHOT create_snap; + CLOSETOOLHELP32SNAPSHOT close_snap; + MODULE32 module_first, module_next; + union { + void *p; + FARPROC f; + } ret = { NULL }; + + dll = LoadLibrary(TEXT(DLLNAME)); + if (dll == NULL) { + DSOerr(DSO_F_WIN32_GLOBALLOOKUP, DSO_R_UNSUPPORTED); + return NULL; + } + + create_snap = (CREATETOOLHELP32SNAPSHOT) + GetProcAddress(dll, "CreateToolhelp32Snapshot"); + if (create_snap == NULL) { + FreeLibrary(dll); + DSOerr(DSO_F_WIN32_GLOBALLOOKUP, DSO_R_UNSUPPORTED); + return NULL; + } + /* We take the rest for granted... */ +# ifdef _WIN32_WCE + close_snap = (CLOSETOOLHELP32SNAPSHOT) + GetProcAddress(dll, "CloseToolhelp32Snapshot"); +# else + close_snap = (CLOSETOOLHELP32SNAPSHOT) CloseHandle; +# endif + module_first = (MODULE32) GetProcAddress(dll, "Module32First"); + module_next = (MODULE32) GetProcAddress(dll, "Module32Next"); + + hModuleSnap = (*create_snap) (TH32CS_SNAPMODULE, 0); + if (hModuleSnap == INVALID_HANDLE_VALUE) { + FreeLibrary(dll); + DSOerr(DSO_F_WIN32_GLOBALLOOKUP, DSO_R_UNSUPPORTED); + return NULL; + } + + me32.dwSize = sizeof(me32); + + if (!(*module_first) (hModuleSnap, &me32)) { + (*close_snap) (hModuleSnap); + FreeLibrary(dll); + return NULL; + } + + do { + if ((ret.f = GetProcAddress(me32.hModule, name))) { + (*close_snap) (hModuleSnap); + FreeLibrary(dll); + return ret.p; + } + } while ((*module_next) (hModuleSnap, &me32)); + + (*close_snap) (hModuleSnap); + FreeLibrary(dll); + return NULL; +} +#endif /* DSO_WIN32 */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ebcdic.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ebcdic.c new file mode 100644 index 000000000..2a8ca6101 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ebcdic.c @@ -0,0 +1,361 @@ +/* + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +# include +#ifndef CHARSET_EBCDIC +NON_EMPTY_TRANSLATION_UNIT +#else + +# include + +# ifdef CHARSET_EBCDIC_TEST +/* + * Here we're looking to test the EBCDIC code on an ASCII system so we don't do + * any translation in these tables at all. + */ + +/* The ebcdic-to-ascii table: */ +const unsigned char os_toascii[256] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff +}; + +/* The ascii-to-ebcdic table: */ +const unsigned char os_toebcdic[256] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff +}; + +# elif defined(_OSD_POSIX) +/* + * "BS2000 OSD" is a POSIX subsystem on a main frame. It is made by Siemens + * AG, Germany, for their BS2000 mainframe machines. Within the POSIX + * subsystem, the same character set was chosen as in "native BS2000", namely + * EBCDIC. (EDF04) + * + * The name "ASCII" in these routines is misleading: actually, conversion is + * not between EBCDIC and ASCII, but EBCDIC(EDF04) and ISO-8859.1; that means + * that (western european) national characters are preserved. + * + * This table is identical to the one used by rsh/rcp/ftp and other POSIX + * tools. + */ + +/* Here's the bijective ebcdic-to-ascii table: */ +const unsigned char os_toascii[256] = { + /* + * 00 + */ 0x00, 0x01, 0x02, 0x03, 0x85, 0x09, 0x86, 0x7f, + 0x87, 0x8d, 0x8e, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* ................ */ + /* + * 10 + */ 0x10, 0x11, 0x12, 0x13, 0x8f, 0x0a, 0x08, 0x97, + 0x18, 0x19, 0x9c, 0x9d, 0x1c, 0x1d, 0x1e, 0x1f, /* ................ */ + /* + * 20 + */ 0x80, 0x81, 0x82, 0x83, 0x84, 0x92, 0x17, 0x1b, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x05, 0x06, 0x07, /* ................ */ + /* + * 30 + */ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, + 0x98, 0x99, 0x9a, 0x9b, 0x14, 0x15, 0x9e, 0x1a, /* ................ */ + /* + * 40 + */ 0x20, 0xa0, 0xe2, 0xe4, 0xe0, 0xe1, 0xe3, 0xe5, + 0xe7, 0xf1, 0x60, 0x2e, 0x3c, 0x28, 0x2b, 0x7c, /* .........`.<(+| */ + /* + * 50 + */ 0x26, 0xe9, 0xea, 0xeb, 0xe8, 0xed, 0xee, 0xef, + 0xec, 0xdf, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x9f, /* &.........!$*);. */ + /* + * 60 + */ 0x2d, 0x2f, 0xc2, 0xc4, 0xc0, 0xc1, 0xc3, 0xc5, + 0xc7, 0xd1, 0x5e, 0x2c, 0x25, 0x5f, 0x3e, 0x3f, /*-/........^,%_>?*/ + /* + * 70 + */ 0xf8, 0xc9, 0xca, 0xcb, 0xc8, 0xcd, 0xce, 0xcf, + 0xcc, 0xa8, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22, /* ..........:#@'=" */ + /* + * 80 + */ 0xd8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0xab, 0xbb, 0xf0, 0xfd, 0xfe, 0xb1, /* .abcdefghi...... */ + /* + * 90 + */ 0xb0, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, + 0x71, 0x72, 0xaa, 0xba, 0xe6, 0xb8, 0xc6, 0xa4, /* .jklmnopqr...... */ + /* + * a0 + */ 0xb5, 0xaf, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0xa1, 0xbf, 0xd0, 0xdd, 0xde, 0xae, /* ..stuvwxyz...... */ + /* + * b0 + */ 0xa2, 0xa3, 0xa5, 0xb7, 0xa9, 0xa7, 0xb6, 0xbc, + 0xbd, 0xbe, 0xac, 0x5b, 0x5c, 0x5d, 0xb4, 0xd7, /* ...........[\].. */ + /* + * c0 + */ 0xf9, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0xad, 0xf4, 0xf6, 0xf2, 0xf3, 0xf5, /* .ABCDEFGHI...... */ + /* + * d0 + */ 0xa6, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, + 0x51, 0x52, 0xb9, 0xfb, 0xfc, 0xdb, 0xfa, 0xff, /* .JKLMNOPQR...... */ + /* + * e0 + */ 0xd9, 0xf7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0xb2, 0xd4, 0xd6, 0xd2, 0xd3, 0xd5, /* ..STUVWXYZ...... */ + /* + * f0 + */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0xb3, 0x7b, 0xdc, 0x7d, 0xda, 0x7e /* 0123456789.{.}.~ */ +}; + +/* The ascii-to-ebcdic table: */ +const unsigned char os_toebcdic[256] = { + /* + * 00 + */ 0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f, + 0x16, 0x05, 0x15, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* ................ */ + /* + * 10 + */ 0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26, + 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f, /* ................ */ + /* + * 20 + */ 0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d, + 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61, /* !"#$%&'()*+,-./ */ + /* + * 30 + */ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f, /* 0123456789:;<=>? */ + /* + * 40 + */ 0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, /* @ABCDEFGHIJKLMNO */ + /* + * 50 + */ 0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, + 0xe7, 0xe8, 0xe9, 0xbb, 0xbc, 0xbd, 0x6a, 0x6d, /* PQRSTUVWXYZ[\]^_ */ + /* + * 60 + */ 0x4a, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, /* `abcdefghijklmno */ + /* + * 70 + */ 0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, + 0xa7, 0xa8, 0xa9, 0xfb, 0x4f, 0xfd, 0xff, 0x07, /* pqrstuvwxyz{|}~. */ + /* + * 80 + */ 0x20, 0x21, 0x22, 0x23, 0x24, 0x04, 0x06, 0x08, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x09, 0x0a, 0x14, /* ................ */ + /* + * 90 + */ 0x30, 0x31, 0x25, 0x33, 0x34, 0x35, 0x36, 0x17, + 0x38, 0x39, 0x3a, 0x3b, 0x1a, 0x1b, 0x3e, 0x5f, /* ................ */ + /* + * a0 + */ 0x41, 0xaa, 0xb0, 0xb1, 0x9f, 0xb2, 0xd0, 0xb5, + 0x79, 0xb4, 0x9a, 0x8a, 0xba, 0xca, 0xaf, 0xa1, /* ................ */ + /* + * b0 + */ 0x90, 0x8f, 0xea, 0xfa, 0xbe, 0xa0, 0xb6, 0xb3, + 0x9d, 0xda, 0x9b, 0x8b, 0xb7, 0xb8, 0xb9, 0xab, /* ................ */ + /* + * c0 + */ 0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9e, 0x68, + 0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77, /* ................ */ + /* + * d0 + */ 0xac, 0x69, 0xed, 0xee, 0xeb, 0xef, 0xec, 0xbf, + 0x80, 0xe0, 0xfe, 0xdd, 0xfc, 0xad, 0xae, 0x59, /* ................ */ + /* + * e0 + */ 0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9c, 0x48, + 0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57, /* ................ */ + /* + * f0 + */ 0x8c, 0x49, 0xcd, 0xce, 0xcb, 0xcf, 0xcc, 0xe1, + 0x70, 0xc0, 0xde, 0xdb, 0xdc, 0x8d, 0x8e, 0xdf /* ................ */ +}; + +# else /*_OSD_POSIX*/ + +/* + * This code does basic character mapping for IBM's TPF and OS/390 operating + * systems. It is a modified version of the BS2000 table. + * + * Bijective EBCDIC (character set IBM-1047) to US-ASCII table: This table is + * bijective - there are no ambiguous or duplicate characters. + */ +const unsigned char os_toascii[256] = { + 0x00, 0x01, 0x02, 0x03, 0x85, 0x09, 0x86, 0x7f, /* 00-0f: */ + 0x87, 0x8d, 0x8e, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* ................ */ + 0x10, 0x11, 0x12, 0x13, 0x8f, 0x0a, 0x08, 0x97, /* 10-1f: */ + 0x18, 0x19, 0x9c, 0x9d, 0x1c, 0x1d, 0x1e, 0x1f, /* ................ */ + 0x80, 0x81, 0x82, 0x83, 0x84, 0x92, 0x17, 0x1b, /* 20-2f: */ + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x05, 0x06, 0x07, /* ................ */ + 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, /* 30-3f: */ + 0x98, 0x99, 0x9a, 0x9b, 0x14, 0x15, 0x9e, 0x1a, /* ................ */ + 0x20, 0xa0, 0xe2, 0xe4, 0xe0, 0xe1, 0xe3, 0xe5, /* 40-4f: */ + 0xe7, 0xf1, 0xa2, 0x2e, 0x3c, 0x28, 0x2b, 0x7c, /* ...........<(+| */ + 0x26, 0xe9, 0xea, 0xeb, 0xe8, 0xed, 0xee, 0xef, /* 50-5f: */ + 0xec, 0xdf, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x5e, /* &.........!$*);^ */ + 0x2d, 0x2f, 0xc2, 0xc4, 0xc0, 0xc1, 0xc3, 0xc5, /* 60-6f: */ + 0xc7, 0xd1, 0xa6, 0x2c, 0x25, 0x5f, 0x3e, 0x3f, /* -/.........,%_>? */ + 0xf8, 0xc9, 0xca, 0xcb, 0xc8, 0xcd, 0xce, 0xcf, /* 70-7f: */ + 0xcc, 0x60, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22, /* .........`:#@'=" */ + 0xd8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 80-8f: */ + 0x68, 0x69, 0xab, 0xbb, 0xf0, 0xfd, 0xfe, 0xb1, /* .abcdefghi...... */ + 0xb0, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, /* 90-9f: */ + 0x71, 0x72, 0xaa, 0xba, 0xe6, 0xb8, 0xc6, 0xa4, /* .jklmnopqr...... */ + 0xb5, 0x7e, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, /* a0-af: */ + 0x79, 0x7a, 0xa1, 0xbf, 0xd0, 0x5b, 0xde, 0xae, /* .~stuvwxyz...[.. */ + 0xac, 0xa3, 0xa5, 0xb7, 0xa9, 0xa7, 0xb6, 0xbc, /* b0-bf: */ + 0xbd, 0xbe, 0xdd, 0xa8, 0xaf, 0x5d, 0xb4, 0xd7, /* .............].. */ + 0x7b, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* c0-cf: */ + 0x48, 0x49, 0xad, 0xf4, 0xf6, 0xf2, 0xf3, 0xf5, /* {ABCDEFGHI...... */ + 0x7d, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, /* d0-df: */ + 0x51, 0x52, 0xb9, 0xfb, 0xfc, 0xf9, 0xfa, 0xff, /* }JKLMNOPQR...... */ + 0x5c, 0xf7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, /* e0-ef: */ + 0x59, 0x5a, 0xb2, 0xd4, 0xd6, 0xd2, 0xd3, 0xd5, /* \.STUVWXYZ...... */ + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* f0-ff: */ + 0x38, 0x39, 0xb3, 0xdb, 0xdc, 0xd9, 0xda, 0x9f /* 0123456789...... */ +}; + +/* + * The US-ASCII to EBCDIC (character set IBM-1047) table: This table is + * bijective (no ambiguous or duplicate characters) + */ +const unsigned char os_toebcdic[256] = { + 0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f, /* 00-0f: */ + 0x16, 0x05, 0x15, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* ................ */ + 0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26, /* 10-1f: */ + 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f, /* ................ */ + 0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d, /* 20-2f: */ + 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61, /* !"#$%&'()*+,-./ */ + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 30-3f: */ + 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f, /* 0123456789:;<=>? */ + 0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 40-4f: */ + 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, /* @ABCDEFGHIJKLMNO */ + 0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, /* 50-5f: */ + 0xe7, 0xe8, 0xe9, 0xad, 0xe0, 0xbd, 0x5f, 0x6d, /* PQRSTUVWXYZ[\]^_ */ + 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 60-6f: */ + 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, /* `abcdefghijklmno */ + 0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, /* 70-7f: */ + 0xa7, 0xa8, 0xa9, 0xc0, 0x4f, 0xd0, 0xa1, 0x07, /* pqrstuvwxyz{|}~. */ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x04, 0x06, 0x08, /* 80-8f: */ + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x09, 0x0a, 0x14, /* ................ */ + 0x30, 0x31, 0x25, 0x33, 0x34, 0x35, 0x36, 0x17, /* 90-9f: */ + 0x38, 0x39, 0x3a, 0x3b, 0x1a, 0x1b, 0x3e, 0xff, /* ................ */ + 0x41, 0xaa, 0x4a, 0xb1, 0x9f, 0xb2, 0x6a, 0xb5, /* a0-af: */ + 0xbb, 0xb4, 0x9a, 0x8a, 0xb0, 0xca, 0xaf, 0xbc, /* ................ */ + 0x90, 0x8f, 0xea, 0xfa, 0xbe, 0xa0, 0xb6, 0xb3, /* b0-bf: */ + 0x9d, 0xda, 0x9b, 0x8b, 0xb7, 0xb8, 0xb9, 0xab, /* ................ */ + 0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9e, 0x68, /* c0-cf: */ + 0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77, /* ................ */ + 0xac, 0x69, 0xed, 0xee, 0xeb, 0xef, 0xec, 0xbf, /* d0-df: */ + 0x80, 0xfd, 0xfe, 0xfb, 0xfc, 0xba, 0xae, 0x59, /* ................ */ + 0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9c, 0x48, /* e0-ef: */ + 0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57, /* ................ */ + 0x8c, 0x49, 0xcd, 0xce, 0xcb, 0xcf, 0xcc, 0xe1, /* f0-ff: */ + 0x70, 0xdd, 0xde, 0xdb, 0xdc, 0x8d, 0x8e, 0xdf /* ................ */ +}; +# endif/*_OSD_POSIX*/ + +/* + * Translate a memory block from EBCDIC (host charset) to ASCII (net charset) + * dest and srce may be identical, or separate memory blocks, but should not + * overlap. These functions intentionally have an interface compatible to + * memcpy(3). + */ + +void *ebcdic2ascii(void *dest, const void *srce, size_t count) +{ + unsigned char *udest = dest; + const unsigned char *usrce = srce; + + while (count-- != 0) { + *udest++ = os_toascii[*usrce++]; + } + + return dest; +} + +void *ascii2ebcdic(void *dest, const void *srce, size_t count) +{ + unsigned char *udest = dest; + const unsigned char *usrce = srce; + + while (count-- != 0) { + *udest++ = os_toebcdic[*usrce++]; + } + + return dest; +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/ecp_nistz256-armv4.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/ecp_nistz256-armv4.pl new file mode 100755 index 000000000..83abbdd89 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/ecp_nistz256-armv4.pl @@ -0,0 +1,1865 @@ +#! /usr/bin/env perl +# Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# ECP_NISTZ256 module for ARMv4. +# +# October 2014. +# +# Original ECP_NISTZ256 submission targeting x86_64 is detailed in +# http://eprint.iacr.org/2013/816. In the process of adaptation +# original .c module was made 32-bit savvy in order to make this +# implementation possible. +# +# with/without -DECP_NISTZ256_ASM +# Cortex-A8 +53-170% +# Cortex-A9 +76-205% +# Cortex-A15 +100-316% +# Snapdragon S4 +66-187% +# +# Ranges denote minimum and maximum improvement coefficients depending +# on benchmark. Lower coefficients are for ECDSA sign, server-side +# operation. Keep in mind that +200% means 3x improvement. + +$flavour = shift; +if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + open STDOUT,">$output"; +} + +$code.=<<___; +#include "arm_arch.h" + +.text +#if defined(__thumb2__) +.syntax unified +.thumb +#else +.code 32 +#endif +___ +######################################################################## +# Convert ecp_nistz256_table.c to layout expected by ecp_nistz_gather_w7 +# +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +open TABLE,") { + s/TOBN\(\s*(0x[0-9a-f]+),\s*(0x[0-9a-f]+)\s*\)/push @arr,hex($2),hex($1)/geo; +} +close TABLE; + +# See ecp_nistz256_table.c for explanation for why it's 64*16*37. +# 64*16*37-1 is because $#arr returns last valid index or @arr, not +# amount of elements. +die "insane number of elements" if ($#arr != 64*16*37-1); + +$code.=<<___; +.globl ecp_nistz256_precomputed +.type ecp_nistz256_precomputed,%object +.align 12 +ecp_nistz256_precomputed: +___ +######################################################################## +# this conversion smashes P256_POINT_AFFINE by individual bytes with +# 64 byte interval, similar to +# 1111222233334444 +# 1234123412341234 +for(1..37) { + @tbl = splice(@arr,0,64*16); + for($i=0;$i<64;$i++) { + undef @line; + for($j=0;$j<64;$j++) { + push @line,(@tbl[$j*16+$i/4]>>(($i%4)*8))&0xff; + } + $code.=".byte\t"; + $code.=join(',',map { sprintf "0x%02x",$_} @line); + $code.="\n"; + } +} +$code.=<<___; +.size ecp_nistz256_precomputed,.-ecp_nistz256_precomputed +.align 5 +.LRR: @ 2^512 mod P precomputed for NIST P256 polynomial +.long 0x00000003, 0x00000000, 0xffffffff, 0xfffffffb +.long 0xfffffffe, 0xffffffff, 0xfffffffd, 0x00000004 +.Lone: +.long 1,0,0,0,0,0,0,0 +.asciz "ECP_NISTZ256 for ARMv4, CRYPTOGAMS by " +.align 6 +___ + +######################################################################## +# common register layout, note that $t2 is link register, so that if +# internal subroutine uses $t2, then it has to offload lr... + +($r_ptr,$a_ptr,$b_ptr,$ff,$a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7,$t1,$t2)= + map("r$_",(0..12,14)); +($t0,$t3)=($ff,$a_ptr); + +$code.=<<___; +@ void ecp_nistz256_to_mont(BN_ULONG r0[8],const BN_ULONG r1[8]); +.globl ecp_nistz256_to_mont +.type ecp_nistz256_to_mont,%function +ecp_nistz256_to_mont: + adr $b_ptr,.LRR + b .Lecp_nistz256_mul_mont +.size ecp_nistz256_to_mont,.-ecp_nistz256_to_mont + +@ void ecp_nistz256_from_mont(BN_ULONG r0[8],const BN_ULONG r1[8]); +.globl ecp_nistz256_from_mont +.type ecp_nistz256_from_mont,%function +ecp_nistz256_from_mont: + adr $b_ptr,.Lone + b .Lecp_nistz256_mul_mont +.size ecp_nistz256_from_mont,.-ecp_nistz256_from_mont + +@ void ecp_nistz256_mul_by_2(BN_ULONG r0[8],const BN_ULONG r1[8]); +.globl ecp_nistz256_mul_by_2 +.type ecp_nistz256_mul_by_2,%function +.align 4 +ecp_nistz256_mul_by_2: + stmdb sp!,{r4-r12,lr} + bl __ecp_nistz256_mul_by_2 +#if __ARM_ARCH__>=5 || !defined(__thumb__) + ldmia sp!,{r4-r12,pc} +#else + ldmia sp!,{r4-r12,lr} + bx lr @ interoperable with Thumb ISA:-) +#endif +.size ecp_nistz256_mul_by_2,.-ecp_nistz256_mul_by_2 + +.type __ecp_nistz256_mul_by_2,%function +.align 4 +__ecp_nistz256_mul_by_2: + ldr $a0,[$a_ptr,#0] + ldr $a1,[$a_ptr,#4] + ldr $a2,[$a_ptr,#8] + adds $a0,$a0,$a0 @ a[0:7]+=a[0:7], i.e. add with itself + ldr $a3,[$a_ptr,#12] + adcs $a1,$a1,$a1 + ldr $a4,[$a_ptr,#16] + adcs $a2,$a2,$a2 + ldr $a5,[$a_ptr,#20] + adcs $a3,$a3,$a3 + ldr $a6,[$a_ptr,#24] + adcs $a4,$a4,$a4 + ldr $a7,[$a_ptr,#28] + adcs $a5,$a5,$a5 + adcs $a6,$a6,$a6 + mov $ff,#0 + adcs $a7,$a7,$a7 + adc $ff,$ff,#0 + + b .Lreduce_by_sub +.size __ecp_nistz256_mul_by_2,.-__ecp_nistz256_mul_by_2 + +@ void ecp_nistz256_add(BN_ULONG r0[8],const BN_ULONG r1[8], +@ const BN_ULONG r2[8]); +.globl ecp_nistz256_add +.type ecp_nistz256_add,%function +.align 4 +ecp_nistz256_add: + stmdb sp!,{r4-r12,lr} + bl __ecp_nistz256_add +#if __ARM_ARCH__>=5 || !defined(__thumb__) + ldmia sp!,{r4-r12,pc} +#else + ldmia sp!,{r4-r12,lr} + bx lr @ interoperable with Thumb ISA:-) +#endif +.size ecp_nistz256_add,.-ecp_nistz256_add + +.type __ecp_nistz256_add,%function +.align 4 +__ecp_nistz256_add: + str lr,[sp,#-4]! @ push lr + + ldr $a0,[$a_ptr,#0] + ldr $a1,[$a_ptr,#4] + ldr $a2,[$a_ptr,#8] + ldr $a3,[$a_ptr,#12] + ldr $a4,[$a_ptr,#16] + ldr $t0,[$b_ptr,#0] + ldr $a5,[$a_ptr,#20] + ldr $t1,[$b_ptr,#4] + ldr $a6,[$a_ptr,#24] + ldr $t2,[$b_ptr,#8] + ldr $a7,[$a_ptr,#28] + ldr $t3,[$b_ptr,#12] + adds $a0,$a0,$t0 + ldr $t0,[$b_ptr,#16] + adcs $a1,$a1,$t1 + ldr $t1,[$b_ptr,#20] + adcs $a2,$a2,$t2 + ldr $t2,[$b_ptr,#24] + adcs $a3,$a3,$t3 + ldr $t3,[$b_ptr,#28] + adcs $a4,$a4,$t0 + adcs $a5,$a5,$t1 + adcs $a6,$a6,$t2 + mov $ff,#0 + adcs $a7,$a7,$t3 + adc $ff,$ff,#0 + ldr lr,[sp],#4 @ pop lr + +.Lreduce_by_sub: + + @ if a+b >= modulus, subtract modulus. + @ + @ But since comparison implies subtraction, we subtract + @ modulus and then add it back if subtraction borrowed. + + subs $a0,$a0,#-1 + sbcs $a1,$a1,#-1 + sbcs $a2,$a2,#-1 + sbcs $a3,$a3,#0 + sbcs $a4,$a4,#0 + sbcs $a5,$a5,#0 + sbcs $a6,$a6,#1 + sbcs $a7,$a7,#-1 + sbc $ff,$ff,#0 + + @ Note that because mod has special form, i.e. consists of + @ 0xffffffff, 1 and 0s, we can conditionally synthesize it by + @ using value of borrow as a whole or extracting single bit. + @ Follow $ff register... + + adds $a0,$a0,$ff @ add synthesized modulus + adcs $a1,$a1,$ff + str $a0,[$r_ptr,#0] + adcs $a2,$a2,$ff + str $a1,[$r_ptr,#4] + adcs $a3,$a3,#0 + str $a2,[$r_ptr,#8] + adcs $a4,$a4,#0 + str $a3,[$r_ptr,#12] + adcs $a5,$a5,#0 + str $a4,[$r_ptr,#16] + adcs $a6,$a6,$ff,lsr#31 + str $a5,[$r_ptr,#20] + adcs $a7,$a7,$ff + str $a6,[$r_ptr,#24] + str $a7,[$r_ptr,#28] + + mov pc,lr +.size __ecp_nistz256_add,.-__ecp_nistz256_add + +@ void ecp_nistz256_mul_by_3(BN_ULONG r0[8],const BN_ULONG r1[8]); +.globl ecp_nistz256_mul_by_3 +.type ecp_nistz256_mul_by_3,%function +.align 4 +ecp_nistz256_mul_by_3: + stmdb sp!,{r4-r12,lr} + bl __ecp_nistz256_mul_by_3 +#if __ARM_ARCH__>=5 || !defined(__thumb__) + ldmia sp!,{r4-r12,pc} +#else + ldmia sp!,{r4-r12,lr} + bx lr @ interoperable with Thumb ISA:-) +#endif +.size ecp_nistz256_mul_by_3,.-ecp_nistz256_mul_by_3 + +.type __ecp_nistz256_mul_by_3,%function +.align 4 +__ecp_nistz256_mul_by_3: + str lr,[sp,#-4]! @ push lr + + @ As multiplication by 3 is performed as 2*n+n, below are inline + @ copies of __ecp_nistz256_mul_by_2 and __ecp_nistz256_add, see + @ corresponding subroutines for details. + + ldr $a0,[$a_ptr,#0] + ldr $a1,[$a_ptr,#4] + ldr $a2,[$a_ptr,#8] + adds $a0,$a0,$a0 @ a[0:7]+=a[0:7] + ldr $a3,[$a_ptr,#12] + adcs $a1,$a1,$a1 + ldr $a4,[$a_ptr,#16] + adcs $a2,$a2,$a2 + ldr $a5,[$a_ptr,#20] + adcs $a3,$a3,$a3 + ldr $a6,[$a_ptr,#24] + adcs $a4,$a4,$a4 + ldr $a7,[$a_ptr,#28] + adcs $a5,$a5,$a5 + adcs $a6,$a6,$a6 + mov $ff,#0 + adcs $a7,$a7,$a7 + adc $ff,$ff,#0 + + subs $a0,$a0,#-1 @ .Lreduce_by_sub but without stores + sbcs $a1,$a1,#-1 + sbcs $a2,$a2,#-1 + sbcs $a3,$a3,#0 + sbcs $a4,$a4,#0 + sbcs $a5,$a5,#0 + sbcs $a6,$a6,#1 + sbcs $a7,$a7,#-1 + sbc $ff,$ff,#0 + + adds $a0,$a0,$ff @ add synthesized modulus + adcs $a1,$a1,$ff + adcs $a2,$a2,$ff + adcs $a3,$a3,#0 + adcs $a4,$a4,#0 + ldr $b_ptr,[$a_ptr,#0] + adcs $a5,$a5,#0 + ldr $t1,[$a_ptr,#4] + adcs $a6,$a6,$ff,lsr#31 + ldr $t2,[$a_ptr,#8] + adc $a7,$a7,$ff + + ldr $t0,[$a_ptr,#12] + adds $a0,$a0,$b_ptr @ 2*a[0:7]+=a[0:7] + ldr $b_ptr,[$a_ptr,#16] + adcs $a1,$a1,$t1 + ldr $t1,[$a_ptr,#20] + adcs $a2,$a2,$t2 + ldr $t2,[$a_ptr,#24] + adcs $a3,$a3,$t0 + ldr $t3,[$a_ptr,#28] + adcs $a4,$a4,$b_ptr + adcs $a5,$a5,$t1 + adcs $a6,$a6,$t2 + mov $ff,#0 + adcs $a7,$a7,$t3 + adc $ff,$ff,#0 + ldr lr,[sp],#4 @ pop lr + + b .Lreduce_by_sub +.size ecp_nistz256_mul_by_3,.-ecp_nistz256_mul_by_3 + +@ void ecp_nistz256_div_by_2(BN_ULONG r0[8],const BN_ULONG r1[8]); +.globl ecp_nistz256_div_by_2 +.type ecp_nistz256_div_by_2,%function +.align 4 +ecp_nistz256_div_by_2: + stmdb sp!,{r4-r12,lr} + bl __ecp_nistz256_div_by_2 +#if __ARM_ARCH__>=5 || !defined(__thumb__) + ldmia sp!,{r4-r12,pc} +#else + ldmia sp!,{r4-r12,lr} + bx lr @ interoperable with Thumb ISA:-) +#endif +.size ecp_nistz256_div_by_2,.-ecp_nistz256_div_by_2 + +.type __ecp_nistz256_div_by_2,%function +.align 4 +__ecp_nistz256_div_by_2: + @ ret = (a is odd ? a+mod : a) >> 1 + + ldr $a0,[$a_ptr,#0] + ldr $a1,[$a_ptr,#4] + ldr $a2,[$a_ptr,#8] + mov $ff,$a0,lsl#31 @ place least significant bit to most + @ significant position, now arithmetic + @ right shift by 31 will produce -1 or + @ 0, while logical right shift 1 or 0, + @ this is how modulus is conditionally + @ synthesized in this case... + ldr $a3,[$a_ptr,#12] + adds $a0,$a0,$ff,asr#31 + ldr $a4,[$a_ptr,#16] + adcs $a1,$a1,$ff,asr#31 + ldr $a5,[$a_ptr,#20] + adcs $a2,$a2,$ff,asr#31 + ldr $a6,[$a_ptr,#24] + adcs $a3,$a3,#0 + ldr $a7,[$a_ptr,#28] + adcs $a4,$a4,#0 + mov $a0,$a0,lsr#1 @ a[0:7]>>=1, we can start early + @ because it doesn't affect flags + adcs $a5,$a5,#0 + orr $a0,$a0,$a1,lsl#31 + adcs $a6,$a6,$ff,lsr#31 + mov $b_ptr,#0 + adcs $a7,$a7,$ff,asr#31 + mov $a1,$a1,lsr#1 + adc $b_ptr,$b_ptr,#0 @ top-most carry bit from addition + + orr $a1,$a1,$a2,lsl#31 + mov $a2,$a2,lsr#1 + str $a0,[$r_ptr,#0] + orr $a2,$a2,$a3,lsl#31 + mov $a3,$a3,lsr#1 + str $a1,[$r_ptr,#4] + orr $a3,$a3,$a4,lsl#31 + mov $a4,$a4,lsr#1 + str $a2,[$r_ptr,#8] + orr $a4,$a4,$a5,lsl#31 + mov $a5,$a5,lsr#1 + str $a3,[$r_ptr,#12] + orr $a5,$a5,$a6,lsl#31 + mov $a6,$a6,lsr#1 + str $a4,[$r_ptr,#16] + orr $a6,$a6,$a7,lsl#31 + mov $a7,$a7,lsr#1 + str $a5,[$r_ptr,#20] + orr $a7,$a7,$b_ptr,lsl#31 @ don't forget the top-most carry bit + str $a6,[$r_ptr,#24] + str $a7,[$r_ptr,#28] + + mov pc,lr +.size __ecp_nistz256_div_by_2,.-__ecp_nistz256_div_by_2 + +@ void ecp_nistz256_sub(BN_ULONG r0[8],const BN_ULONG r1[8], +@ const BN_ULONG r2[8]); +.globl ecp_nistz256_sub +.type ecp_nistz256_sub,%function +.align 4 +ecp_nistz256_sub: + stmdb sp!,{r4-r12,lr} + bl __ecp_nistz256_sub +#if __ARM_ARCH__>=5 || !defined(__thumb__) + ldmia sp!,{r4-r12,pc} +#else + ldmia sp!,{r4-r12,lr} + bx lr @ interoperable with Thumb ISA:-) +#endif +.size ecp_nistz256_sub,.-ecp_nistz256_sub + +.type __ecp_nistz256_sub,%function +.align 4 +__ecp_nistz256_sub: + str lr,[sp,#-4]! @ push lr + + ldr $a0,[$a_ptr,#0] + ldr $a1,[$a_ptr,#4] + ldr $a2,[$a_ptr,#8] + ldr $a3,[$a_ptr,#12] + ldr $a4,[$a_ptr,#16] + ldr $t0,[$b_ptr,#0] + ldr $a5,[$a_ptr,#20] + ldr $t1,[$b_ptr,#4] + ldr $a6,[$a_ptr,#24] + ldr $t2,[$b_ptr,#8] + ldr $a7,[$a_ptr,#28] + ldr $t3,[$b_ptr,#12] + subs $a0,$a0,$t0 + ldr $t0,[$b_ptr,#16] + sbcs $a1,$a1,$t1 + ldr $t1,[$b_ptr,#20] + sbcs $a2,$a2,$t2 + ldr $t2,[$b_ptr,#24] + sbcs $a3,$a3,$t3 + ldr $t3,[$b_ptr,#28] + sbcs $a4,$a4,$t0 + sbcs $a5,$a5,$t1 + sbcs $a6,$a6,$t2 + sbcs $a7,$a7,$t3 + sbc $ff,$ff,$ff @ broadcast borrow bit + ldr lr,[sp],#4 @ pop lr + +.Lreduce_by_add: + + @ if a-b borrows, add modulus. + @ + @ Note that because mod has special form, i.e. consists of + @ 0xffffffff, 1 and 0s, we can conditionally synthesize it by + @ broadcasting borrow bit to a register, $ff, and using it as + @ a whole or extracting single bit. + + adds $a0,$a0,$ff @ add synthesized modulus + adcs $a1,$a1,$ff + str $a0,[$r_ptr,#0] + adcs $a2,$a2,$ff + str $a1,[$r_ptr,#4] + adcs $a3,$a3,#0 + str $a2,[$r_ptr,#8] + adcs $a4,$a4,#0 + str $a3,[$r_ptr,#12] + adcs $a5,$a5,#0 + str $a4,[$r_ptr,#16] + adcs $a6,$a6,$ff,lsr#31 + str $a5,[$r_ptr,#20] + adcs $a7,$a7,$ff + str $a6,[$r_ptr,#24] + str $a7,[$r_ptr,#28] + + mov pc,lr +.size __ecp_nistz256_sub,.-__ecp_nistz256_sub + +@ void ecp_nistz256_neg(BN_ULONG r0[8],const BN_ULONG r1[8]); +.globl ecp_nistz256_neg +.type ecp_nistz256_neg,%function +.align 4 +ecp_nistz256_neg: + stmdb sp!,{r4-r12,lr} + bl __ecp_nistz256_neg +#if __ARM_ARCH__>=5 || !defined(__thumb__) + ldmia sp!,{r4-r12,pc} +#else + ldmia sp!,{r4-r12,lr} + bx lr @ interoperable with Thumb ISA:-) +#endif +.size ecp_nistz256_neg,.-ecp_nistz256_neg + +.type __ecp_nistz256_neg,%function +.align 4 +__ecp_nistz256_neg: + ldr $a0,[$a_ptr,#0] + eor $ff,$ff,$ff + ldr $a1,[$a_ptr,#4] + ldr $a2,[$a_ptr,#8] + subs $a0,$ff,$a0 + ldr $a3,[$a_ptr,#12] + sbcs $a1,$ff,$a1 + ldr $a4,[$a_ptr,#16] + sbcs $a2,$ff,$a2 + ldr $a5,[$a_ptr,#20] + sbcs $a3,$ff,$a3 + ldr $a6,[$a_ptr,#24] + sbcs $a4,$ff,$a4 + ldr $a7,[$a_ptr,#28] + sbcs $a5,$ff,$a5 + sbcs $a6,$ff,$a6 + sbcs $a7,$ff,$a7 + sbc $ff,$ff,$ff + + b .Lreduce_by_add +.size __ecp_nistz256_neg,.-__ecp_nistz256_neg +___ +{ +my @acc=map("r$_",(3..11)); +my ($t0,$t1,$bj,$t2,$t3)=map("r$_",(0,1,2,12,14)); + +$code.=<<___; +@ void ecp_nistz256_sqr_mont(BN_ULONG r0[8],const BN_ULONG r1[8]); +.globl ecp_nistz256_sqr_mont +.type ecp_nistz256_sqr_mont,%function +.align 4 +ecp_nistz256_sqr_mont: + mov $b_ptr,$a_ptr + b .Lecp_nistz256_mul_mont +.size ecp_nistz256_sqr_mont,.-ecp_nistz256_sqr_mont + +@ void ecp_nistz256_mul_mont(BN_ULONG r0[8],const BN_ULONG r1[8], +@ const BN_ULONG r2[8]); +.globl ecp_nistz256_mul_mont +.type ecp_nistz256_mul_mont,%function +.align 4 +ecp_nistz256_mul_mont: +.Lecp_nistz256_mul_mont: + stmdb sp!,{r4-r12,lr} + bl __ecp_nistz256_mul_mont +#if __ARM_ARCH__>=5 || !defined(__thumb__) + ldmia sp!,{r4-r12,pc} +#else + ldmia sp!,{r4-r12,lr} + bx lr @ interoperable with Thumb ISA:-) +#endif +.size ecp_nistz256_mul_mont,.-ecp_nistz256_mul_mont + +.type __ecp_nistz256_mul_mont,%function +.align 4 +__ecp_nistz256_mul_mont: + stmdb sp!,{r0-r2,lr} @ make a copy of arguments too + + ldr $bj,[$b_ptr,#0] @ b[0] + ldmia $a_ptr,{@acc[1]-@acc[8]} + + umull @acc[0],$t3,@acc[1],$bj @ r[0]=a[0]*b[0] + stmdb sp!,{$acc[1]-@acc[8]} @ copy a[0-7] to stack, so + @ that it can be addressed + @ without spending register + @ on address + umull @acc[1],$t0,@acc[2],$bj @ r[1]=a[1]*b[0] + umull @acc[2],$t1,@acc[3],$bj + adds @acc[1],@acc[1],$t3 @ accumulate high part of mult + umull @acc[3],$t2,@acc[4],$bj + adcs @acc[2],@acc[2],$t0 + umull @acc[4],$t3,@acc[5],$bj + adcs @acc[3],@acc[3],$t1 + umull @acc[5],$t0,@acc[6],$bj + adcs @acc[4],@acc[4],$t2 + umull @acc[6],$t1,@acc[7],$bj + adcs @acc[5],@acc[5],$t3 + umull @acc[7],$t2,@acc[8],$bj + adcs @acc[6],@acc[6],$t0 + adcs @acc[7],@acc[7],$t1 + eor $t3,$t3,$t3 @ first overflow bit is zero + adc @acc[8],$t2,#0 +___ +for(my $i=1;$i<8;$i++) { +my $t4=@acc[0]; + + # Reduction iteration is normally performed by accumulating + # result of multiplication of modulus by "magic" digit [and + # omitting least significant word, which is guaranteed to + # be 0], but thanks to special form of modulus and "magic" + # digit being equal to least significant word, it can be + # performed with additions and subtractions alone. Indeed: + # + # ffff.0001.0000.0000.0000.ffff.ffff.ffff + # * abcd + # + xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.abcd + # + # Now observing that ff..ff*x = (2^n-1)*x = 2^n*x-x, we + # rewrite above as: + # + # xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.abcd + # + abcd.0000.abcd.0000.0000.abcd.0000.0000.0000 + # - abcd.0000.0000.0000.0000.0000.0000.abcd + # + # or marking redundant operations: + # + # xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.---- + # + abcd.0000.abcd.0000.0000.abcd.----.----.---- + # - abcd.----.----.----.----.----.----.---- + +$code.=<<___; + @ multiplication-less reduction $i + adds @acc[3],@acc[3],@acc[0] @ r[3]+=r[0] + ldr $bj,[sp,#40] @ restore b_ptr + adcs @acc[4],@acc[4],#0 @ r[4]+=0 + adcs @acc[5],@acc[5],#0 @ r[5]+=0 + adcs @acc[6],@acc[6],@acc[0] @ r[6]+=r[0] + ldr $t1,[sp,#0] @ load a[0] + adcs @acc[7],@acc[7],#0 @ r[7]+=0 + ldr $bj,[$bj,#4*$i] @ load b[i] + adcs @acc[8],@acc[8],@acc[0] @ r[8]+=r[0] + eor $t0,$t0,$t0 + adc $t3,$t3,#0 @ overflow bit + subs @acc[7],@acc[7],@acc[0] @ r[7]-=r[0] + ldr $t2,[sp,#4] @ a[1] + sbcs @acc[8],@acc[8],#0 @ r[8]-=0 + umlal @acc[1],$t0,$t1,$bj @ "r[0]"+=a[0]*b[i] + eor $t1,$t1,$t1 + sbc @acc[0],$t3,#0 @ overflow bit, keep in mind + @ that netto result is + @ addition of a value which + @ makes underflow impossible + + ldr $t3,[sp,#8] @ a[2] + umlal @acc[2],$t1,$t2,$bj @ "r[1]"+=a[1]*b[i] + str @acc[0],[sp,#36] @ temporarily offload overflow + eor $t2,$t2,$t2 + ldr $t4,[sp,#12] @ a[3], $t4 is alias @acc[0] + umlal @acc[3],$t2,$t3,$bj @ "r[2]"+=a[2]*b[i] + eor $t3,$t3,$t3 + adds @acc[2],@acc[2],$t0 @ accumulate high part of mult + ldr $t0,[sp,#16] @ a[4] + umlal @acc[4],$t3,$t4,$bj @ "r[3]"+=a[3]*b[i] + eor $t4,$t4,$t4 + adcs @acc[3],@acc[3],$t1 + ldr $t1,[sp,#20] @ a[5] + umlal @acc[5],$t4,$t0,$bj @ "r[4]"+=a[4]*b[i] + eor $t0,$t0,$t0 + adcs @acc[4],@acc[4],$t2 + ldr $t2,[sp,#24] @ a[6] + umlal @acc[6],$t0,$t1,$bj @ "r[5]"+=a[5]*b[i] + eor $t1,$t1,$t1 + adcs @acc[5],@acc[5],$t3 + ldr $t3,[sp,#28] @ a[7] + umlal @acc[7],$t1,$t2,$bj @ "r[6]"+=a[6]*b[i] + eor $t2,$t2,$t2 + adcs @acc[6],@acc[6],$t4 + ldr @acc[0],[sp,#36] @ restore overflow bit + umlal @acc[8],$t2,$t3,$bj @ "r[7]"+=a[7]*b[i] + eor $t3,$t3,$t3 + adcs @acc[7],@acc[7],$t0 + adcs @acc[8],@acc[8],$t1 + adcs @acc[0],$acc[0],$t2 + adc $t3,$t3,#0 @ new overflow bit +___ + push(@acc,shift(@acc)); # rotate registers, so that + # "r[i]" becomes r[i] +} +$code.=<<___; + @ last multiplication-less reduction + adds @acc[3],@acc[3],@acc[0] + ldr $r_ptr,[sp,#32] @ restore r_ptr + adcs @acc[4],@acc[4],#0 + adcs @acc[5],@acc[5],#0 + adcs @acc[6],@acc[6],@acc[0] + adcs @acc[7],@acc[7],#0 + adcs @acc[8],@acc[8],@acc[0] + adc $t3,$t3,#0 + subs @acc[7],@acc[7],@acc[0] + sbcs @acc[8],@acc[8],#0 + sbc @acc[0],$t3,#0 @ overflow bit + + @ Final step is "if result > mod, subtract mod", but we do it + @ "other way around", namely subtract modulus from result + @ and if it borrowed, add modulus back. + + adds @acc[1],@acc[1],#1 @ subs @acc[1],@acc[1],#-1 + adcs @acc[2],@acc[2],#0 @ sbcs @acc[2],@acc[2],#-1 + adcs @acc[3],@acc[3],#0 @ sbcs @acc[3],@acc[3],#-1 + sbcs @acc[4],@acc[4],#0 + sbcs @acc[5],@acc[5],#0 + sbcs @acc[6],@acc[6],#0 + sbcs @acc[7],@acc[7],#1 + adcs @acc[8],@acc[8],#0 @ sbcs @acc[8],@acc[8],#-1 + ldr lr,[sp,#44] @ restore lr + sbc @acc[0],@acc[0],#0 @ broadcast borrow bit + add sp,sp,#48 + + @ Note that because mod has special form, i.e. consists of + @ 0xffffffff, 1 and 0s, we can conditionally synthesize it by + @ broadcasting borrow bit to a register, @acc[0], and using it as + @ a whole or extracting single bit. + + adds @acc[1],@acc[1],@acc[0] @ add modulus or zero + adcs @acc[2],@acc[2],@acc[0] + str @acc[1],[$r_ptr,#0] + adcs @acc[3],@acc[3],@acc[0] + str @acc[2],[$r_ptr,#4] + adcs @acc[4],@acc[4],#0 + str @acc[3],[$r_ptr,#8] + adcs @acc[5],@acc[5],#0 + str @acc[4],[$r_ptr,#12] + adcs @acc[6],@acc[6],#0 + str @acc[5],[$r_ptr,#16] + adcs @acc[7],@acc[7],@acc[0],lsr#31 + str @acc[6],[$r_ptr,#20] + adc @acc[8],@acc[8],@acc[0] + str @acc[7],[$r_ptr,#24] + str @acc[8],[$r_ptr,#28] + + mov pc,lr +.size __ecp_nistz256_mul_mont,.-__ecp_nistz256_mul_mont +___ +} + +{ +my ($out,$inp,$index,$mask)=map("r$_",(0..3)); +$code.=<<___; +@ void ecp_nistz256_scatter_w5(void *r0,const P256_POINT *r1, +@ int r2); +.globl ecp_nistz256_scatter_w5 +.type ecp_nistz256_scatter_w5,%function +.align 5 +ecp_nistz256_scatter_w5: + stmdb sp!,{r4-r11} + + add $out,$out,$index,lsl#2 + + ldmia $inp!,{r4-r11} @ X + str r4,[$out,#64*0-4] + str r5,[$out,#64*1-4] + str r6,[$out,#64*2-4] + str r7,[$out,#64*3-4] + str r8,[$out,#64*4-4] + str r9,[$out,#64*5-4] + str r10,[$out,#64*6-4] + str r11,[$out,#64*7-4] + add $out,$out,#64*8 + + ldmia $inp!,{r4-r11} @ Y + str r4,[$out,#64*0-4] + str r5,[$out,#64*1-4] + str r6,[$out,#64*2-4] + str r7,[$out,#64*3-4] + str r8,[$out,#64*4-4] + str r9,[$out,#64*5-4] + str r10,[$out,#64*6-4] + str r11,[$out,#64*7-4] + add $out,$out,#64*8 + + ldmia $inp,{r4-r11} @ Z + str r4,[$out,#64*0-4] + str r5,[$out,#64*1-4] + str r6,[$out,#64*2-4] + str r7,[$out,#64*3-4] + str r8,[$out,#64*4-4] + str r9,[$out,#64*5-4] + str r10,[$out,#64*6-4] + str r11,[$out,#64*7-4] + + ldmia sp!,{r4-r11} +#if __ARM_ARCH__>=5 || defined(__thumb__) + bx lr +#else + mov pc,lr +#endif +.size ecp_nistz256_scatter_w5,.-ecp_nistz256_scatter_w5 + +@ void ecp_nistz256_gather_w5(P256_POINT *r0,const void *r1, +@ int r2); +.globl ecp_nistz256_gather_w5 +.type ecp_nistz256_gather_w5,%function +.align 5 +ecp_nistz256_gather_w5: + stmdb sp!,{r4-r11} + + cmp $index,#0 + mov $mask,#0 +#ifdef __thumb2__ + itt ne +#endif + subne $index,$index,#1 + movne $mask,#-1 + add $inp,$inp,$index,lsl#2 + + ldr r4,[$inp,#64*0] + ldr r5,[$inp,#64*1] + ldr r6,[$inp,#64*2] + and r4,r4,$mask + ldr r7,[$inp,#64*3] + and r5,r5,$mask + ldr r8,[$inp,#64*4] + and r6,r6,$mask + ldr r9,[$inp,#64*5] + and r7,r7,$mask + ldr r10,[$inp,#64*6] + and r8,r8,$mask + ldr r11,[$inp,#64*7] + add $inp,$inp,#64*8 + and r9,r9,$mask + and r10,r10,$mask + and r11,r11,$mask + stmia $out!,{r4-r11} @ X + + ldr r4,[$inp,#64*0] + ldr r5,[$inp,#64*1] + ldr r6,[$inp,#64*2] + and r4,r4,$mask + ldr r7,[$inp,#64*3] + and r5,r5,$mask + ldr r8,[$inp,#64*4] + and r6,r6,$mask + ldr r9,[$inp,#64*5] + and r7,r7,$mask + ldr r10,[$inp,#64*6] + and r8,r8,$mask + ldr r11,[$inp,#64*7] + add $inp,$inp,#64*8 + and r9,r9,$mask + and r10,r10,$mask + and r11,r11,$mask + stmia $out!,{r4-r11} @ Y + + ldr r4,[$inp,#64*0] + ldr r5,[$inp,#64*1] + ldr r6,[$inp,#64*2] + and r4,r4,$mask + ldr r7,[$inp,#64*3] + and r5,r5,$mask + ldr r8,[$inp,#64*4] + and r6,r6,$mask + ldr r9,[$inp,#64*5] + and r7,r7,$mask + ldr r10,[$inp,#64*6] + and r8,r8,$mask + ldr r11,[$inp,#64*7] + and r9,r9,$mask + and r10,r10,$mask + and r11,r11,$mask + stmia $out,{r4-r11} @ Z + + ldmia sp!,{r4-r11} +#if __ARM_ARCH__>=5 || defined(__thumb__) + bx lr +#else + mov pc,lr +#endif +.size ecp_nistz256_gather_w5,.-ecp_nistz256_gather_w5 + +@ void ecp_nistz256_scatter_w7(void *r0,const P256_POINT_AFFINE *r1, +@ int r2); +.globl ecp_nistz256_scatter_w7 +.type ecp_nistz256_scatter_w7,%function +.align 5 +ecp_nistz256_scatter_w7: + add $out,$out,$index + mov $index,#64/4 +.Loop_scatter_w7: + ldr $mask,[$inp],#4 + subs $index,$index,#1 + strb $mask,[$out,#64*0] + mov $mask,$mask,lsr#8 + strb $mask,[$out,#64*1] + mov $mask,$mask,lsr#8 + strb $mask,[$out,#64*2] + mov $mask,$mask,lsr#8 + strb $mask,[$out,#64*3] + add $out,$out,#64*4 + bne .Loop_scatter_w7 + +#if __ARM_ARCH__>=5 || defined(__thumb__) + bx lr +#else + mov pc,lr +#endif +.size ecp_nistz256_scatter_w7,.-ecp_nistz256_scatter_w7 + +@ void ecp_nistz256_gather_w7(P256_POINT_AFFINE *r0,const void *r1, +@ int r2); +.globl ecp_nistz256_gather_w7 +.type ecp_nistz256_gather_w7,%function +.align 5 +ecp_nistz256_gather_w7: + stmdb sp!,{r4-r7} + + cmp $index,#0 + mov $mask,#0 +#ifdef __thumb2__ + itt ne +#endif + subne $index,$index,#1 + movne $mask,#-1 + add $inp,$inp,$index + mov $index,#64/4 + nop +.Loop_gather_w7: + ldrb r4,[$inp,#64*0] + subs $index,$index,#1 + ldrb r5,[$inp,#64*1] + ldrb r6,[$inp,#64*2] + ldrb r7,[$inp,#64*3] + add $inp,$inp,#64*4 + orr r4,r4,r5,lsl#8 + orr r4,r4,r6,lsl#16 + orr r4,r4,r7,lsl#24 + and r4,r4,$mask + str r4,[$out],#4 + bne .Loop_gather_w7 + + ldmia sp!,{r4-r7} +#if __ARM_ARCH__>=5 || defined(__thumb__) + bx lr +#else + mov pc,lr +#endif +.size ecp_nistz256_gather_w7,.-ecp_nistz256_gather_w7 +___ +} +if (0) { +# In comparison to integer-only equivalent of below subroutine: +# +# Cortex-A8 +10% +# Cortex-A9 -10% +# Snapdragon S4 +5% +# +# As not all time is spent in multiplication, overall impact is deemed +# too low to care about. + +my ($A0,$A1,$A2,$A3,$Bi,$zero,$temp)=map("d$_",(0..7)); +my $mask="q4"; +my $mult="q5"; +my @AxB=map("q$_",(8..15)); + +my ($rptr,$aptr,$bptr,$toutptr)=map("r$_",(0..3)); + +$code.=<<___; +#if __ARM_ARCH__>=7 +.fpu neon + +.globl ecp_nistz256_mul_mont_neon +.type ecp_nistz256_mul_mont_neon,%function +.align 5 +ecp_nistz256_mul_mont_neon: + mov ip,sp + stmdb sp!,{r4-r9} + vstmdb sp!,{q4-q5} @ ABI specification says so + + sub $toutptr,sp,#40 + vld1.32 {${Bi}[0]},[$bptr,:32]! + veor $zero,$zero,$zero + vld1.32 {$A0-$A3}, [$aptr] @ can't specify :32 :-( + vzip.16 $Bi,$zero + mov sp,$toutptr @ alloca + vmov.i64 $mask,#0xffff + + vmull.u32 @AxB[0],$Bi,${A0}[0] + vmull.u32 @AxB[1],$Bi,${A0}[1] + vmull.u32 @AxB[2],$Bi,${A1}[0] + vmull.u32 @AxB[3],$Bi,${A1}[1] + vshr.u64 $temp,@AxB[0]#lo,#16 + vmull.u32 @AxB[4],$Bi,${A2}[0] + vadd.u64 @AxB[0]#hi,@AxB[0]#hi,$temp + vmull.u32 @AxB[5],$Bi,${A2}[1] + vshr.u64 $temp,@AxB[0]#hi,#16 @ upper 32 bits of a[0]*b[0] + vmull.u32 @AxB[6],$Bi,${A3}[0] + vand.u64 @AxB[0],@AxB[0],$mask @ lower 32 bits of a[0]*b[0] + vmull.u32 @AxB[7],$Bi,${A3}[1] +___ +for($i=1;$i<8;$i++) { +$code.=<<___; + vld1.32 {${Bi}[0]},[$bptr,:32]! + veor $zero,$zero,$zero + vadd.u64 @AxB[1]#lo,@AxB[1]#lo,$temp @ reduction + vshl.u64 $mult,@AxB[0],#32 + vadd.u64 @AxB[3],@AxB[3],@AxB[0] + vsub.u64 $mult,$mult,@AxB[0] + vzip.16 $Bi,$zero + vadd.u64 @AxB[6],@AxB[6],@AxB[0] + vadd.u64 @AxB[7],@AxB[7],$mult +___ + push(@AxB,shift(@AxB)); +$code.=<<___; + vmlal.u32 @AxB[0],$Bi,${A0}[0] + vmlal.u32 @AxB[1],$Bi,${A0}[1] + vmlal.u32 @AxB[2],$Bi,${A1}[0] + vmlal.u32 @AxB[3],$Bi,${A1}[1] + vshr.u64 $temp,@AxB[0]#lo,#16 + vmlal.u32 @AxB[4],$Bi,${A2}[0] + vadd.u64 @AxB[0]#hi,@AxB[0]#hi,$temp + vmlal.u32 @AxB[5],$Bi,${A2}[1] + vshr.u64 $temp,@AxB[0]#hi,#16 @ upper 33 bits of a[0]*b[i]+t[0] + vmlal.u32 @AxB[6],$Bi,${A3}[0] + vand.u64 @AxB[0],@AxB[0],$mask @ lower 32 bits of a[0]*b[0] + vmull.u32 @AxB[7],$Bi,${A3}[1] +___ +} +$code.=<<___; + vadd.u64 @AxB[1]#lo,@AxB[1]#lo,$temp @ last reduction + vshl.u64 $mult,@AxB[0],#32 + vadd.u64 @AxB[3],@AxB[3],@AxB[0] + vsub.u64 $mult,$mult,@AxB[0] + vadd.u64 @AxB[6],@AxB[6],@AxB[0] + vadd.u64 @AxB[7],@AxB[7],$mult + + vshr.u64 $temp,@AxB[1]#lo,#16 @ convert + vadd.u64 @AxB[1]#hi,@AxB[1]#hi,$temp + vshr.u64 $temp,@AxB[1]#hi,#16 + vzip.16 @AxB[1]#lo,@AxB[1]#hi +___ +foreach (2..7) { +$code.=<<___; + vadd.u64 @AxB[$_]#lo,@AxB[$_]#lo,$temp + vst1.32 {@AxB[$_-1]#lo[0]},[$toutptr,:32]! + vshr.u64 $temp,@AxB[$_]#lo,#16 + vadd.u64 @AxB[$_]#hi,@AxB[$_]#hi,$temp + vshr.u64 $temp,@AxB[$_]#hi,#16 + vzip.16 @AxB[$_]#lo,@AxB[$_]#hi +___ +} +$code.=<<___; + vst1.32 {@AxB[7]#lo[0]},[$toutptr,:32]! + vst1.32 {$temp},[$toutptr] @ upper 33 bits + + ldr r1,[sp,#0] + ldr r2,[sp,#4] + ldr r3,[sp,#8] + subs r1,r1,#-1 + ldr r4,[sp,#12] + sbcs r2,r2,#-1 + ldr r5,[sp,#16] + sbcs r3,r3,#-1 + ldr r6,[sp,#20] + sbcs r4,r4,#0 + ldr r7,[sp,#24] + sbcs r5,r5,#0 + ldr r8,[sp,#28] + sbcs r6,r6,#0 + ldr r9,[sp,#32] @ top-most bit + sbcs r7,r7,#1 + sub sp,ip,#40+16 + sbcs r8,r8,#-1 + sbc r9,r9,#0 + vldmia sp!,{q4-q5} + + adds r1,r1,r9 + adcs r2,r2,r9 + str r1,[$rptr,#0] + adcs r3,r3,r9 + str r2,[$rptr,#4] + adcs r4,r4,#0 + str r3,[$rptr,#8] + adcs r5,r5,#0 + str r4,[$rptr,#12] + adcs r6,r6,#0 + str r5,[$rptr,#16] + adcs r7,r7,r9,lsr#31 + str r6,[$rptr,#20] + adcs r8,r8,r9 + str r7,[$rptr,#24] + str r8,[$rptr,#28] + + ldmia sp!,{r4-r9} + bx lr +.size ecp_nistz256_mul_mont_neon,.-ecp_nistz256_mul_mont_neon +#endif +___ +} + +{{{ +######################################################################## +# Below $aN assignment matches order in which 256-bit result appears in +# register bank at return from __ecp_nistz256_mul_mont, so that we can +# skip over reloading it from memory. This means that below functions +# use custom calling sequence accepting 256-bit input in registers, +# output pointer in r0, $r_ptr, and optional pointer in r2, $b_ptr. +# +# See their "normal" counterparts for insights on calculations. + +my ($a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7, + $t0,$t1,$t2,$t3)=map("r$_",(11,3..10,12,14,1)); +my $ff=$b_ptr; + +$code.=<<___; +.type __ecp_nistz256_sub_from,%function +.align 5 +__ecp_nistz256_sub_from: + str lr,[sp,#-4]! @ push lr + + ldr $t0,[$b_ptr,#0] + ldr $t1,[$b_ptr,#4] + ldr $t2,[$b_ptr,#8] + ldr $t3,[$b_ptr,#12] + subs $a0,$a0,$t0 + ldr $t0,[$b_ptr,#16] + sbcs $a1,$a1,$t1 + ldr $t1,[$b_ptr,#20] + sbcs $a2,$a2,$t2 + ldr $t2,[$b_ptr,#24] + sbcs $a3,$a3,$t3 + ldr $t3,[$b_ptr,#28] + sbcs $a4,$a4,$t0 + sbcs $a5,$a5,$t1 + sbcs $a6,$a6,$t2 + sbcs $a7,$a7,$t3 + sbc $ff,$ff,$ff @ broadcast borrow bit + ldr lr,[sp],#4 @ pop lr + + adds $a0,$a0,$ff @ add synthesized modulus + adcs $a1,$a1,$ff + str $a0,[$r_ptr,#0] + adcs $a2,$a2,$ff + str $a1,[$r_ptr,#4] + adcs $a3,$a3,#0 + str $a2,[$r_ptr,#8] + adcs $a4,$a4,#0 + str $a3,[$r_ptr,#12] + adcs $a5,$a5,#0 + str $a4,[$r_ptr,#16] + adcs $a6,$a6,$ff,lsr#31 + str $a5,[$r_ptr,#20] + adcs $a7,$a7,$ff + str $a6,[$r_ptr,#24] + str $a7,[$r_ptr,#28] + + mov pc,lr +.size __ecp_nistz256_sub_from,.-__ecp_nistz256_sub_from + +.type __ecp_nistz256_sub_morf,%function +.align 5 +__ecp_nistz256_sub_morf: + str lr,[sp,#-4]! @ push lr + + ldr $t0,[$b_ptr,#0] + ldr $t1,[$b_ptr,#4] + ldr $t2,[$b_ptr,#8] + ldr $t3,[$b_ptr,#12] + subs $a0,$t0,$a0 + ldr $t0,[$b_ptr,#16] + sbcs $a1,$t1,$a1 + ldr $t1,[$b_ptr,#20] + sbcs $a2,$t2,$a2 + ldr $t2,[$b_ptr,#24] + sbcs $a3,$t3,$a3 + ldr $t3,[$b_ptr,#28] + sbcs $a4,$t0,$a4 + sbcs $a5,$t1,$a5 + sbcs $a6,$t2,$a6 + sbcs $a7,$t3,$a7 + sbc $ff,$ff,$ff @ broadcast borrow bit + ldr lr,[sp],#4 @ pop lr + + adds $a0,$a0,$ff @ add synthesized modulus + adcs $a1,$a1,$ff + str $a0,[$r_ptr,#0] + adcs $a2,$a2,$ff + str $a1,[$r_ptr,#4] + adcs $a3,$a3,#0 + str $a2,[$r_ptr,#8] + adcs $a4,$a4,#0 + str $a3,[$r_ptr,#12] + adcs $a5,$a5,#0 + str $a4,[$r_ptr,#16] + adcs $a6,$a6,$ff,lsr#31 + str $a5,[$r_ptr,#20] + adcs $a7,$a7,$ff + str $a6,[$r_ptr,#24] + str $a7,[$r_ptr,#28] + + mov pc,lr +.size __ecp_nistz256_sub_morf,.-__ecp_nistz256_sub_morf + +.type __ecp_nistz256_add_self,%function +.align 4 +__ecp_nistz256_add_self: + adds $a0,$a0,$a0 @ a[0:7]+=a[0:7] + adcs $a1,$a1,$a1 + adcs $a2,$a2,$a2 + adcs $a3,$a3,$a3 + adcs $a4,$a4,$a4 + adcs $a5,$a5,$a5 + adcs $a6,$a6,$a6 + mov $ff,#0 + adcs $a7,$a7,$a7 + adc $ff,$ff,#0 + + @ if a+b >= modulus, subtract modulus. + @ + @ But since comparison implies subtraction, we subtract + @ modulus and then add it back if subtraction borrowed. + + subs $a0,$a0,#-1 + sbcs $a1,$a1,#-1 + sbcs $a2,$a2,#-1 + sbcs $a3,$a3,#0 + sbcs $a4,$a4,#0 + sbcs $a5,$a5,#0 + sbcs $a6,$a6,#1 + sbcs $a7,$a7,#-1 + sbc $ff,$ff,#0 + + @ Note that because mod has special form, i.e. consists of + @ 0xffffffff, 1 and 0s, we can conditionally synthesize it by + @ using value of borrow as a whole or extracting single bit. + @ Follow $ff register... + + adds $a0,$a0,$ff @ add synthesized modulus + adcs $a1,$a1,$ff + str $a0,[$r_ptr,#0] + adcs $a2,$a2,$ff + str $a1,[$r_ptr,#4] + adcs $a3,$a3,#0 + str $a2,[$r_ptr,#8] + adcs $a4,$a4,#0 + str $a3,[$r_ptr,#12] + adcs $a5,$a5,#0 + str $a4,[$r_ptr,#16] + adcs $a6,$a6,$ff,lsr#31 + str $a5,[$r_ptr,#20] + adcs $a7,$a7,$ff + str $a6,[$r_ptr,#24] + str $a7,[$r_ptr,#28] + + mov pc,lr +.size __ecp_nistz256_add_self,.-__ecp_nistz256_add_self + +___ + +######################################################################## +# following subroutines are "literal" implementation of those found in +# ecp_nistz256.c +# +######################################################################## +# void ecp_nistz256_point_double(P256_POINT *out,const P256_POINT *inp); +# +{ +my ($S,$M,$Zsqr,$in_x,$tmp0)=map(32*$_,(0..4)); +# above map() describes stack layout with 5 temporary +# 256-bit vectors on top. Then note that we push +# starting from r0, which means that we have copy of +# input arguments just below these temporary vectors. + +$code.=<<___; +.globl ecp_nistz256_point_double +.type ecp_nistz256_point_double,%function +.align 5 +ecp_nistz256_point_double: + stmdb sp!,{r0-r12,lr} @ push from r0, unusual, but intentional + sub sp,sp,#32*5 + +.Lpoint_double_shortcut: + add r3,sp,#$in_x + ldmia $a_ptr!,{r4-r11} @ copy in_x + stmia r3,{r4-r11} + + add $r_ptr,sp,#$S + bl __ecp_nistz256_mul_by_2 @ p256_mul_by_2(S, in_y); + + add $b_ptr,$a_ptr,#32 + add $a_ptr,$a_ptr,#32 + add $r_ptr,sp,#$Zsqr + bl __ecp_nistz256_mul_mont @ p256_sqr_mont(Zsqr, in_z); + + add $a_ptr,sp,#$S + add $b_ptr,sp,#$S + add $r_ptr,sp,#$S + bl __ecp_nistz256_mul_mont @ p256_sqr_mont(S, S); + + ldr $b_ptr,[sp,#32*5+4] + add $a_ptr,$b_ptr,#32 + add $b_ptr,$b_ptr,#64 + add $r_ptr,sp,#$tmp0 + bl __ecp_nistz256_mul_mont @ p256_mul_mont(tmp0, in_z, in_y); + + ldr $r_ptr,[sp,#32*5] + add $r_ptr,$r_ptr,#64 + bl __ecp_nistz256_add_self @ p256_mul_by_2(res_z, tmp0); + + add $a_ptr,sp,#$in_x + add $b_ptr,sp,#$Zsqr + add $r_ptr,sp,#$M + bl __ecp_nistz256_add @ p256_add(M, in_x, Zsqr); + + add $a_ptr,sp,#$in_x + add $b_ptr,sp,#$Zsqr + add $r_ptr,sp,#$Zsqr + bl __ecp_nistz256_sub @ p256_sub(Zsqr, in_x, Zsqr); + + add $a_ptr,sp,#$S + add $b_ptr,sp,#$S + add $r_ptr,sp,#$tmp0 + bl __ecp_nistz256_mul_mont @ p256_sqr_mont(tmp0, S); + + add $a_ptr,sp,#$Zsqr + add $b_ptr,sp,#$M + add $r_ptr,sp,#$M + bl __ecp_nistz256_mul_mont @ p256_mul_mont(M, M, Zsqr); + + ldr $r_ptr,[sp,#32*5] + add $a_ptr,sp,#$tmp0 + add $r_ptr,$r_ptr,#32 + bl __ecp_nistz256_div_by_2 @ p256_div_by_2(res_y, tmp0); + + add $a_ptr,sp,#$M + add $r_ptr,sp,#$M + bl __ecp_nistz256_mul_by_3 @ p256_mul_by_3(M, M); + + add $a_ptr,sp,#$in_x + add $b_ptr,sp,#$S + add $r_ptr,sp,#$S + bl __ecp_nistz256_mul_mont @ p256_mul_mont(S, S, in_x); + + add $r_ptr,sp,#$tmp0 + bl __ecp_nistz256_add_self @ p256_mul_by_2(tmp0, S); + + ldr $r_ptr,[sp,#32*5] + add $a_ptr,sp,#$M + add $b_ptr,sp,#$M + bl __ecp_nistz256_mul_mont @ p256_sqr_mont(res_x, M); + + add $b_ptr,sp,#$tmp0 + bl __ecp_nistz256_sub_from @ p256_sub(res_x, res_x, tmp0); + + add $b_ptr,sp,#$S + add $r_ptr,sp,#$S + bl __ecp_nistz256_sub_morf @ p256_sub(S, S, res_x); + + add $a_ptr,sp,#$M + add $b_ptr,sp,#$S + bl __ecp_nistz256_mul_mont @ p256_mul_mont(S, S, M); + + ldr $r_ptr,[sp,#32*5] + add $b_ptr,$r_ptr,#32 + add $r_ptr,$r_ptr,#32 + bl __ecp_nistz256_sub_from @ p256_sub(res_y, S, res_y); + + add sp,sp,#32*5+16 @ +16 means "skip even over saved r0-r3" +#if __ARM_ARCH__>=5 || !defined(__thumb__) + ldmia sp!,{r4-r12,pc} +#else + ldmia sp!,{r4-r12,lr} + bx lr @ interoperable with Thumb ISA:-) +#endif +.size ecp_nistz256_point_double,.-ecp_nistz256_point_double +___ +} + +######################################################################## +# void ecp_nistz256_point_add(P256_POINT *out,const P256_POINT *in1, +# const P256_POINT *in2); +{ +my ($res_x,$res_y,$res_z, + $in1_x,$in1_y,$in1_z, + $in2_x,$in2_y,$in2_z, + $H,$Hsqr,$R,$Rsqr,$Hcub, + $U1,$U2,$S1,$S2)=map(32*$_,(0..17)); +my ($Z1sqr, $Z2sqr) = ($Hsqr, $Rsqr); +# above map() describes stack layout with 18 temporary +# 256-bit vectors on top. Then note that we push +# starting from r0, which means that we have copy of +# input arguments just below these temporary vectors. +# We use three of them for !in1infty, !in2intfy and +# result of check for zero. + +$code.=<<___; +.globl ecp_nistz256_point_add +.type ecp_nistz256_point_add,%function +.align 5 +ecp_nistz256_point_add: + stmdb sp!,{r0-r12,lr} @ push from r0, unusual, but intentional + sub sp,sp,#32*18+16 + + ldmia $b_ptr!,{r4-r11} @ copy in2_x + add r3,sp,#$in2_x + stmia r3!,{r4-r11} + ldmia $b_ptr!,{r4-r11} @ copy in2_y + stmia r3!,{r4-r11} + ldmia $b_ptr,{r4-r11} @ copy in2_z + orr r12,r4,r5 + orr r12,r12,r6 + orr r12,r12,r7 + orr r12,r12,r8 + orr r12,r12,r9 + orr r12,r12,r10 + orr r12,r12,r11 + cmp r12,#0 +#ifdef __thumb2__ + it ne +#endif + movne r12,#-1 + stmia r3,{r4-r11} + str r12,[sp,#32*18+8] @ !in2infty + + ldmia $a_ptr!,{r4-r11} @ copy in1_x + add r3,sp,#$in1_x + stmia r3!,{r4-r11} + ldmia $a_ptr!,{r4-r11} @ copy in1_y + stmia r3!,{r4-r11} + ldmia $a_ptr,{r4-r11} @ copy in1_z + orr r12,r4,r5 + orr r12,r12,r6 + orr r12,r12,r7 + orr r12,r12,r8 + orr r12,r12,r9 + orr r12,r12,r10 + orr r12,r12,r11 + cmp r12,#0 +#ifdef __thumb2__ + it ne +#endif + movne r12,#-1 + stmia r3,{r4-r11} + str r12,[sp,#32*18+4] @ !in1infty + + add $a_ptr,sp,#$in2_z + add $b_ptr,sp,#$in2_z + add $r_ptr,sp,#$Z2sqr + bl __ecp_nistz256_mul_mont @ p256_sqr_mont(Z2sqr, in2_z); + + add $a_ptr,sp,#$in1_z + add $b_ptr,sp,#$in1_z + add $r_ptr,sp,#$Z1sqr + bl __ecp_nistz256_mul_mont @ p256_sqr_mont(Z1sqr, in1_z); + + add $a_ptr,sp,#$in2_z + add $b_ptr,sp,#$Z2sqr + add $r_ptr,sp,#$S1 + bl __ecp_nistz256_mul_mont @ p256_mul_mont(S1, Z2sqr, in2_z); + + add $a_ptr,sp,#$in1_z + add $b_ptr,sp,#$Z1sqr + add $r_ptr,sp,#$S2 + bl __ecp_nistz256_mul_mont @ p256_mul_mont(S2, Z1sqr, in1_z); + + add $a_ptr,sp,#$in1_y + add $b_ptr,sp,#$S1 + add $r_ptr,sp,#$S1 + bl __ecp_nistz256_mul_mont @ p256_mul_mont(S1, S1, in1_y); + + add $a_ptr,sp,#$in2_y + add $b_ptr,sp,#$S2 + add $r_ptr,sp,#$S2 + bl __ecp_nistz256_mul_mont @ p256_mul_mont(S2, S2, in2_y); + + add $b_ptr,sp,#$S1 + add $r_ptr,sp,#$R + bl __ecp_nistz256_sub_from @ p256_sub(R, S2, S1); + + orr $a0,$a0,$a1 @ see if result is zero + orr $a2,$a2,$a3 + orr $a4,$a4,$a5 + orr $a0,$a0,$a2 + orr $a4,$a4,$a6 + orr $a0,$a0,$a7 + add $a_ptr,sp,#$in1_x + orr $a0,$a0,$a4 + add $b_ptr,sp,#$Z2sqr + str $a0,[sp,#32*18+12] + + add $r_ptr,sp,#$U1 + bl __ecp_nistz256_mul_mont @ p256_mul_mont(U1, in1_x, Z2sqr); + + add $a_ptr,sp,#$in2_x + add $b_ptr,sp,#$Z1sqr + add $r_ptr,sp,#$U2 + bl __ecp_nistz256_mul_mont @ p256_mul_mont(U2, in2_x, Z1sqr); + + add $b_ptr,sp,#$U1 + add $r_ptr,sp,#$H + bl __ecp_nistz256_sub_from @ p256_sub(H, U2, U1); + + orr $a0,$a0,$a1 @ see if result is zero + orr $a2,$a2,$a3 + orr $a4,$a4,$a5 + orr $a0,$a0,$a2 + orr $a4,$a4,$a6 + orr $a0,$a0,$a7 + orrs $a0,$a0,$a4 + + bne .Ladd_proceed @ is_equal(U1,U2)? + + ldr $t0,[sp,#32*18+4] + ldr $t1,[sp,#32*18+8] + ldr $t2,[sp,#32*18+12] + tst $t0,$t1 + beq .Ladd_proceed @ (in1infty || in2infty)? + tst $t2,$t2 + beq .Ladd_double @ is_equal(S1,S2)? + + ldr $r_ptr,[sp,#32*18+16] + eor r4,r4,r4 + eor r5,r5,r5 + eor r6,r6,r6 + eor r7,r7,r7 + eor r8,r8,r8 + eor r9,r9,r9 + eor r10,r10,r10 + eor r11,r11,r11 + stmia $r_ptr!,{r4-r11} + stmia $r_ptr!,{r4-r11} + stmia $r_ptr!,{r4-r11} + b .Ladd_done + +.align 4 +.Ladd_double: + ldr $a_ptr,[sp,#32*18+20] + add sp,sp,#32*(18-5)+16 @ difference in frame sizes + b .Lpoint_double_shortcut + +.align 4 +.Ladd_proceed: + add $a_ptr,sp,#$R + add $b_ptr,sp,#$R + add $r_ptr,sp,#$Rsqr + bl __ecp_nistz256_mul_mont @ p256_sqr_mont(Rsqr, R); + + add $a_ptr,sp,#$H + add $b_ptr,sp,#$in1_z + add $r_ptr,sp,#$res_z + bl __ecp_nistz256_mul_mont @ p256_mul_mont(res_z, H, in1_z); + + add $a_ptr,sp,#$H + add $b_ptr,sp,#$H + add $r_ptr,sp,#$Hsqr + bl __ecp_nistz256_mul_mont @ p256_sqr_mont(Hsqr, H); + + add $a_ptr,sp,#$in2_z + add $b_ptr,sp,#$res_z + add $r_ptr,sp,#$res_z + bl __ecp_nistz256_mul_mont @ p256_mul_mont(res_z, res_z, in2_z); + + add $a_ptr,sp,#$H + add $b_ptr,sp,#$Hsqr + add $r_ptr,sp,#$Hcub + bl __ecp_nistz256_mul_mont @ p256_mul_mont(Hcub, Hsqr, H); + + add $a_ptr,sp,#$Hsqr + add $b_ptr,sp,#$U1 + add $r_ptr,sp,#$U2 + bl __ecp_nistz256_mul_mont @ p256_mul_mont(U2, U1, Hsqr); + + add $r_ptr,sp,#$Hsqr + bl __ecp_nistz256_add_self @ p256_mul_by_2(Hsqr, U2); + + add $b_ptr,sp,#$Rsqr + add $r_ptr,sp,#$res_x + bl __ecp_nistz256_sub_morf @ p256_sub(res_x, Rsqr, Hsqr); + + add $b_ptr,sp,#$Hcub + bl __ecp_nistz256_sub_from @ p256_sub(res_x, res_x, Hcub); + + add $b_ptr,sp,#$U2 + add $r_ptr,sp,#$res_y + bl __ecp_nistz256_sub_morf @ p256_sub(res_y, U2, res_x); + + add $a_ptr,sp,#$Hcub + add $b_ptr,sp,#$S1 + add $r_ptr,sp,#$S2 + bl __ecp_nistz256_mul_mont @ p256_mul_mont(S2, S1, Hcub); + + add $a_ptr,sp,#$R + add $b_ptr,sp,#$res_y + add $r_ptr,sp,#$res_y + bl __ecp_nistz256_mul_mont @ p256_mul_mont(res_y, res_y, R); + + add $b_ptr,sp,#$S2 + bl __ecp_nistz256_sub_from @ p256_sub(res_y, res_y, S2); + + ldr r11,[sp,#32*18+4] @ !in1intfy + ldr r12,[sp,#32*18+8] @ !in2intfy + add r1,sp,#$res_x + add r2,sp,#$in2_x + and r10,r11,r12 + mvn r11,r11 + add r3,sp,#$in1_x + and r11,r11,r12 + mvn r12,r12 + ldr $r_ptr,[sp,#32*18+16] +___ +for($i=0;$i<96;$i+=8) { # conditional moves +$code.=<<___; + ldmia r1!,{r4-r5} @ res_x + ldmia r2!,{r6-r7} @ in2_x + ldmia r3!,{r8-r9} @ in1_x + and r4,r4,r10 + and r5,r5,r10 + and r6,r6,r11 + and r7,r7,r11 + and r8,r8,r12 + and r9,r9,r12 + orr r4,r4,r6 + orr r5,r5,r7 + orr r4,r4,r8 + orr r5,r5,r9 + stmia $r_ptr!,{r4-r5} +___ +} +$code.=<<___; +.Ladd_done: + add sp,sp,#32*18+16+16 @ +16 means "skip even over saved r0-r3" +#if __ARM_ARCH__>=5 || !defined(__thumb__) + ldmia sp!,{r4-r12,pc} +#else + ldmia sp!,{r4-r12,lr} + bx lr @ interoperable with Thumb ISA:-) +#endif +.size ecp_nistz256_point_add,.-ecp_nistz256_point_add +___ +} + +######################################################################## +# void ecp_nistz256_point_add_affine(P256_POINT *out,const P256_POINT *in1, +# const P256_POINT_AFFINE *in2); +{ +my ($res_x,$res_y,$res_z, + $in1_x,$in1_y,$in1_z, + $in2_x,$in2_y, + $U2,$S2,$H,$R,$Hsqr,$Hcub,$Rsqr)=map(32*$_,(0..14)); +my $Z1sqr = $S2; +# above map() describes stack layout with 18 temporary +# 256-bit vectors on top. Then note that we push +# starting from r0, which means that we have copy of +# input arguments just below these temporary vectors. +# We use two of them for !in1infty, !in2intfy. + +my @ONE_mont=(1,0,0,-1,-1,-1,-2,0); + +$code.=<<___; +.globl ecp_nistz256_point_add_affine +.type ecp_nistz256_point_add_affine,%function +.align 5 +ecp_nistz256_point_add_affine: + stmdb sp!,{r0-r12,lr} @ push from r0, unusual, but intentional + sub sp,sp,#32*15 + + ldmia $a_ptr!,{r4-r11} @ copy in1_x + add r3,sp,#$in1_x + stmia r3!,{r4-r11} + ldmia $a_ptr!,{r4-r11} @ copy in1_y + stmia r3!,{r4-r11} + ldmia $a_ptr,{r4-r11} @ copy in1_z + orr r12,r4,r5 + orr r12,r12,r6 + orr r12,r12,r7 + orr r12,r12,r8 + orr r12,r12,r9 + orr r12,r12,r10 + orr r12,r12,r11 + cmp r12,#0 +#ifdef __thumb2__ + it ne +#endif + movne r12,#-1 + stmia r3,{r4-r11} + str r12,[sp,#32*15+4] @ !in1infty + + ldmia $b_ptr!,{r4-r11} @ copy in2_x + add r3,sp,#$in2_x + orr r12,r4,r5 + orr r12,r12,r6 + orr r12,r12,r7 + orr r12,r12,r8 + orr r12,r12,r9 + orr r12,r12,r10 + orr r12,r12,r11 + stmia r3!,{r4-r11} + ldmia $b_ptr!,{r4-r11} @ copy in2_y + orr r12,r12,r4 + orr r12,r12,r5 + orr r12,r12,r6 + orr r12,r12,r7 + orr r12,r12,r8 + orr r12,r12,r9 + orr r12,r12,r10 + orr r12,r12,r11 + stmia r3!,{r4-r11} + cmp r12,#0 +#ifdef __thumb2__ + it ne +#endif + movne r12,#-1 + str r12,[sp,#32*15+8] @ !in2infty + + add $a_ptr,sp,#$in1_z + add $b_ptr,sp,#$in1_z + add $r_ptr,sp,#$Z1sqr + bl __ecp_nistz256_mul_mont @ p256_sqr_mont(Z1sqr, in1_z); + + add $a_ptr,sp,#$Z1sqr + add $b_ptr,sp,#$in2_x + add $r_ptr,sp,#$U2 + bl __ecp_nistz256_mul_mont @ p256_mul_mont(U2, Z1sqr, in2_x); + + add $b_ptr,sp,#$in1_x + add $r_ptr,sp,#$H + bl __ecp_nistz256_sub_from @ p256_sub(H, U2, in1_x); + + add $a_ptr,sp,#$Z1sqr + add $b_ptr,sp,#$in1_z + add $r_ptr,sp,#$S2 + bl __ecp_nistz256_mul_mont @ p256_mul_mont(S2, Z1sqr, in1_z); + + add $a_ptr,sp,#$H + add $b_ptr,sp,#$in1_z + add $r_ptr,sp,#$res_z + bl __ecp_nistz256_mul_mont @ p256_mul_mont(res_z, H, in1_z); + + add $a_ptr,sp,#$in2_y + add $b_ptr,sp,#$S2 + add $r_ptr,sp,#$S2 + bl __ecp_nistz256_mul_mont @ p256_mul_mont(S2, S2, in2_y); + + add $b_ptr,sp,#$in1_y + add $r_ptr,sp,#$R + bl __ecp_nistz256_sub_from @ p256_sub(R, S2, in1_y); + + add $a_ptr,sp,#$H + add $b_ptr,sp,#$H + add $r_ptr,sp,#$Hsqr + bl __ecp_nistz256_mul_mont @ p256_sqr_mont(Hsqr, H); + + add $a_ptr,sp,#$R + add $b_ptr,sp,#$R + add $r_ptr,sp,#$Rsqr + bl __ecp_nistz256_mul_mont @ p256_sqr_mont(Rsqr, R); + + add $a_ptr,sp,#$H + add $b_ptr,sp,#$Hsqr + add $r_ptr,sp,#$Hcub + bl __ecp_nistz256_mul_mont @ p256_mul_mont(Hcub, Hsqr, H); + + add $a_ptr,sp,#$Hsqr + add $b_ptr,sp,#$in1_x + add $r_ptr,sp,#$U2 + bl __ecp_nistz256_mul_mont @ p256_mul_mont(U2, in1_x, Hsqr); + + add $r_ptr,sp,#$Hsqr + bl __ecp_nistz256_add_self @ p256_mul_by_2(Hsqr, U2); + + add $b_ptr,sp,#$Rsqr + add $r_ptr,sp,#$res_x + bl __ecp_nistz256_sub_morf @ p256_sub(res_x, Rsqr, Hsqr); + + add $b_ptr,sp,#$Hcub + bl __ecp_nistz256_sub_from @ p256_sub(res_x, res_x, Hcub); + + add $b_ptr,sp,#$U2 + add $r_ptr,sp,#$res_y + bl __ecp_nistz256_sub_morf @ p256_sub(res_y, U2, res_x); + + add $a_ptr,sp,#$Hcub + add $b_ptr,sp,#$in1_y + add $r_ptr,sp,#$S2 + bl __ecp_nistz256_mul_mont @ p256_mul_mont(S2, in1_y, Hcub); + + add $a_ptr,sp,#$R + add $b_ptr,sp,#$res_y + add $r_ptr,sp,#$res_y + bl __ecp_nistz256_mul_mont @ p256_mul_mont(res_y, res_y, R); + + add $b_ptr,sp,#$S2 + bl __ecp_nistz256_sub_from @ p256_sub(res_y, res_y, S2); + + ldr r11,[sp,#32*15+4] @ !in1intfy + ldr r12,[sp,#32*15+8] @ !in2intfy + add r1,sp,#$res_x + add r2,sp,#$in2_x + and r10,r11,r12 + mvn r11,r11 + add r3,sp,#$in1_x + and r11,r11,r12 + mvn r12,r12 + ldr $r_ptr,[sp,#32*15] +___ +for($i=0;$i<64;$i+=8) { # conditional moves +$code.=<<___; + ldmia r1!,{r4-r5} @ res_x + ldmia r2!,{r6-r7} @ in2_x + ldmia r3!,{r8-r9} @ in1_x + and r4,r4,r10 + and r5,r5,r10 + and r6,r6,r11 + and r7,r7,r11 + and r8,r8,r12 + and r9,r9,r12 + orr r4,r4,r6 + orr r5,r5,r7 + orr r4,r4,r8 + orr r5,r5,r9 + stmia $r_ptr!,{r4-r5} +___ +} +for(;$i<96;$i+=8) { +my $j=($i-64)/4; +$code.=<<___; + ldmia r1!,{r4-r5} @ res_z + ldmia r3!,{r8-r9} @ in1_z + and r4,r4,r10 + and r5,r5,r10 + and r6,r11,#@ONE_mont[$j] + and r7,r11,#@ONE_mont[$j+1] + and r8,r8,r12 + and r9,r9,r12 + orr r4,r4,r6 + orr r5,r5,r7 + orr r4,r4,r8 + orr r5,r5,r9 + stmia $r_ptr!,{r4-r5} +___ +} +$code.=<<___; + add sp,sp,#32*15+16 @ +16 means "skip even over saved r0-r3" +#if __ARM_ARCH__>=5 || !defined(__thumb__) + ldmia sp!,{r4-r12,pc} +#else + ldmia sp!,{r4-r12,lr} + bx lr @ interoperable with Thumb ISA:-) +#endif +.size ecp_nistz256_point_add_affine,.-ecp_nistz256_point_add_affine +___ +} }}} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/geo; + + s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo; + + print $_,"\n"; +} +close STDOUT; # enforce flush diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/ecp_nistz256-armv8.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/ecp_nistz256-armv8.pl new file mode 100644 index 000000000..887ddfb1e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/ecp_nistz256-armv8.pl @@ -0,0 +1,1883 @@ +#! /usr/bin/env perl +# Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# ECP_NISTZ256 module for ARMv8. +# +# February 2015. +# +# Original ECP_NISTZ256 submission targeting x86_64 is detailed in +# http://eprint.iacr.org/2013/816. +# +# with/without -DECP_NISTZ256_ASM +# Apple A7 +190-360% +# Cortex-A53 +190-400% +# Cortex-A57 +190-350% +# Denver +230-400% +# +# Ranges denote minimum and maximum improvement coefficients depending +# on benchmark. Lower coefficients are for ECDSA sign, server-side +# operation. Keep in mind that +400% means 5x improvement. + +$flavour = shift; +while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or +die "can't locate arm-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +{ +my ($rp,$ap,$bp,$bi,$a0,$a1,$a2,$a3,$t0,$t1,$t2,$t3,$poly1,$poly3, + $acc0,$acc1,$acc2,$acc3,$acc4,$acc5) = + map("x$_",(0..17,19,20)); + +my ($acc6,$acc7)=($ap,$bp); # used in __ecp_nistz256_sqr_mont + +$code.=<<___; +#include "arm_arch.h" + +.text +___ +######################################################################## +# Convert ecp_nistz256_table.c to layout expected by ecp_nistz_gather_w7 +# +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +open TABLE,") { + s/TOBN\(\s*(0x[0-9a-f]+),\s*(0x[0-9a-f]+)\s*\)/push @arr,hex($2),hex($1)/geo; +} +close TABLE; + +# See ecp_nistz256_table.c for explanation for why it's 64*16*37. +# 64*16*37-1 is because $#arr returns last valid index or @arr, not +# amount of elements. +die "insane number of elements" if ($#arr != 64*16*37-1); + +$code.=<<___; +.globl ecp_nistz256_precomputed +.type ecp_nistz256_precomputed,%object +.align 12 +ecp_nistz256_precomputed: +___ +######################################################################## +# this conversion smashes P256_POINT_AFFINE by individual bytes with +# 64 byte interval, similar to +# 1111222233334444 +# 1234123412341234 +for(1..37) { + @tbl = splice(@arr,0,64*16); + for($i=0;$i<64;$i++) { + undef @line; + for($j=0;$j<64;$j++) { + push @line,(@tbl[$j*16+$i/4]>>(($i%4)*8))&0xff; + } + $code.=".byte\t"; + $code.=join(',',map { sprintf "0x%02x",$_} @line); + $code.="\n"; + } +} +$code.=<<___; +.size ecp_nistz256_precomputed,.-ecp_nistz256_precomputed +.align 5 +.Lpoly: +.quad 0xffffffffffffffff,0x00000000ffffffff,0x0000000000000000,0xffffffff00000001 +.LRR: // 2^512 mod P precomputed for NIST P256 polynomial +.quad 0x0000000000000003,0xfffffffbffffffff,0xfffffffffffffffe,0x00000004fffffffd +.Lone_mont: +.quad 0x0000000000000001,0xffffffff00000000,0xffffffffffffffff,0x00000000fffffffe +.Lone: +.quad 1,0,0,0 +.Lord: +.quad 0xf3b9cac2fc632551,0xbce6faada7179e84,0xffffffffffffffff,0xffffffff00000000 +.LordK: +.quad 0xccd1c8aaee00bc4f +.asciz "ECP_NISTZ256 for ARMv8, CRYPTOGAMS by " + +// void ecp_nistz256_to_mont(BN_ULONG x0[4],const BN_ULONG x1[4]); +.globl ecp_nistz256_to_mont +.type ecp_nistz256_to_mont,%function +.align 6 +ecp_nistz256_to_mont: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-32]! + add x29,sp,#0 + stp x19,x20,[sp,#16] + + ldr $bi,.LRR // bp[0] + ldp $a0,$a1,[$ap] + ldp $a2,$a3,[$ap,#16] + ldr $poly1,.Lpoly+8 + ldr $poly3,.Lpoly+24 + adr $bp,.LRR // &bp[0] + + bl __ecp_nistz256_mul_mont + + ldp x19,x20,[sp,#16] + ldp x29,x30,[sp],#32 + .inst 0xd50323bf // autiasp + ret +.size ecp_nistz256_to_mont,.-ecp_nistz256_to_mont + +// void ecp_nistz256_from_mont(BN_ULONG x0[4],const BN_ULONG x1[4]); +.globl ecp_nistz256_from_mont +.type ecp_nistz256_from_mont,%function +.align 4 +ecp_nistz256_from_mont: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-32]! + add x29,sp,#0 + stp x19,x20,[sp,#16] + + mov $bi,#1 // bp[0] + ldp $a0,$a1,[$ap] + ldp $a2,$a3,[$ap,#16] + ldr $poly1,.Lpoly+8 + ldr $poly3,.Lpoly+24 + adr $bp,.Lone // &bp[0] + + bl __ecp_nistz256_mul_mont + + ldp x19,x20,[sp,#16] + ldp x29,x30,[sp],#32 + .inst 0xd50323bf // autiasp + ret +.size ecp_nistz256_from_mont,.-ecp_nistz256_from_mont + +// void ecp_nistz256_mul_mont(BN_ULONG x0[4],const BN_ULONG x1[4], +// const BN_ULONG x2[4]); +.globl ecp_nistz256_mul_mont +.type ecp_nistz256_mul_mont,%function +.align 4 +ecp_nistz256_mul_mont: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-32]! + add x29,sp,#0 + stp x19,x20,[sp,#16] + + ldr $bi,[$bp] // bp[0] + ldp $a0,$a1,[$ap] + ldp $a2,$a3,[$ap,#16] + ldr $poly1,.Lpoly+8 + ldr $poly3,.Lpoly+24 + + bl __ecp_nistz256_mul_mont + + ldp x19,x20,[sp,#16] + ldp x29,x30,[sp],#32 + .inst 0xd50323bf // autiasp + ret +.size ecp_nistz256_mul_mont,.-ecp_nistz256_mul_mont + +// void ecp_nistz256_sqr_mont(BN_ULONG x0[4],const BN_ULONG x1[4]); +.globl ecp_nistz256_sqr_mont +.type ecp_nistz256_sqr_mont,%function +.align 4 +ecp_nistz256_sqr_mont: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-32]! + add x29,sp,#0 + stp x19,x20,[sp,#16] + + ldp $a0,$a1,[$ap] + ldp $a2,$a3,[$ap,#16] + ldr $poly1,.Lpoly+8 + ldr $poly3,.Lpoly+24 + + bl __ecp_nistz256_sqr_mont + + ldp x19,x20,[sp,#16] + ldp x29,x30,[sp],#32 + .inst 0xd50323bf // autiasp + ret +.size ecp_nistz256_sqr_mont,.-ecp_nistz256_sqr_mont + +// void ecp_nistz256_add(BN_ULONG x0[4],const BN_ULONG x1[4], +// const BN_ULONG x2[4]); +.globl ecp_nistz256_add +.type ecp_nistz256_add,%function +.align 4 +ecp_nistz256_add: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-16]! + add x29,sp,#0 + + ldp $acc0,$acc1,[$ap] + ldp $t0,$t1,[$bp] + ldp $acc2,$acc3,[$ap,#16] + ldp $t2,$t3,[$bp,#16] + ldr $poly1,.Lpoly+8 + ldr $poly3,.Lpoly+24 + + bl __ecp_nistz256_add + + ldp x29,x30,[sp],#16 + .inst 0xd50323bf // autiasp + ret +.size ecp_nistz256_add,.-ecp_nistz256_add + +// void ecp_nistz256_div_by_2(BN_ULONG x0[4],const BN_ULONG x1[4]); +.globl ecp_nistz256_div_by_2 +.type ecp_nistz256_div_by_2,%function +.align 4 +ecp_nistz256_div_by_2: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-16]! + add x29,sp,#0 + + ldp $acc0,$acc1,[$ap] + ldp $acc2,$acc3,[$ap,#16] + ldr $poly1,.Lpoly+8 + ldr $poly3,.Lpoly+24 + + bl __ecp_nistz256_div_by_2 + + ldp x29,x30,[sp],#16 + .inst 0xd50323bf // autiasp + ret +.size ecp_nistz256_div_by_2,.-ecp_nistz256_div_by_2 + +// void ecp_nistz256_mul_by_2(BN_ULONG x0[4],const BN_ULONG x1[4]); +.globl ecp_nistz256_mul_by_2 +.type ecp_nistz256_mul_by_2,%function +.align 4 +ecp_nistz256_mul_by_2: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-16]! + add x29,sp,#0 + + ldp $acc0,$acc1,[$ap] + ldp $acc2,$acc3,[$ap,#16] + ldr $poly1,.Lpoly+8 + ldr $poly3,.Lpoly+24 + mov $t0,$acc0 + mov $t1,$acc1 + mov $t2,$acc2 + mov $t3,$acc3 + + bl __ecp_nistz256_add // ret = a+a // 2*a + + ldp x29,x30,[sp],#16 + .inst 0xd50323bf // autiasp + ret +.size ecp_nistz256_mul_by_2,.-ecp_nistz256_mul_by_2 + +// void ecp_nistz256_mul_by_3(BN_ULONG x0[4],const BN_ULONG x1[4]); +.globl ecp_nistz256_mul_by_3 +.type ecp_nistz256_mul_by_3,%function +.align 4 +ecp_nistz256_mul_by_3: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-16]! + add x29,sp,#0 + + ldp $acc0,$acc1,[$ap] + ldp $acc2,$acc3,[$ap,#16] + ldr $poly1,.Lpoly+8 + ldr $poly3,.Lpoly+24 + mov $t0,$acc0 + mov $t1,$acc1 + mov $t2,$acc2 + mov $t3,$acc3 + mov $a0,$acc0 + mov $a1,$acc1 + mov $a2,$acc2 + mov $a3,$acc3 + + bl __ecp_nistz256_add // ret = a+a // 2*a + + mov $t0,$a0 + mov $t1,$a1 + mov $t2,$a2 + mov $t3,$a3 + + bl __ecp_nistz256_add // ret += a // 2*a+a=3*a + + ldp x29,x30,[sp],#16 + .inst 0xd50323bf // autiasp + ret +.size ecp_nistz256_mul_by_3,.-ecp_nistz256_mul_by_3 + +// void ecp_nistz256_sub(BN_ULONG x0[4],const BN_ULONG x1[4], +// const BN_ULONG x2[4]); +.globl ecp_nistz256_sub +.type ecp_nistz256_sub,%function +.align 4 +ecp_nistz256_sub: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-16]! + add x29,sp,#0 + + ldp $acc0,$acc1,[$ap] + ldp $acc2,$acc3,[$ap,#16] + ldr $poly1,.Lpoly+8 + ldr $poly3,.Lpoly+24 + + bl __ecp_nistz256_sub_from + + ldp x29,x30,[sp],#16 + .inst 0xd50323bf // autiasp + ret +.size ecp_nistz256_sub,.-ecp_nistz256_sub + +// void ecp_nistz256_neg(BN_ULONG x0[4],const BN_ULONG x1[4]); +.globl ecp_nistz256_neg +.type ecp_nistz256_neg,%function +.align 4 +ecp_nistz256_neg: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-16]! + add x29,sp,#0 + + mov $bp,$ap + mov $acc0,xzr // a = 0 + mov $acc1,xzr + mov $acc2,xzr + mov $acc3,xzr + ldr $poly1,.Lpoly+8 + ldr $poly3,.Lpoly+24 + + bl __ecp_nistz256_sub_from + + ldp x29,x30,[sp],#16 + .inst 0xd50323bf // autiasp + ret +.size ecp_nistz256_neg,.-ecp_nistz256_neg + +// note that __ecp_nistz256_mul_mont expects a[0-3] input pre-loaded +// to $a0-$a3 and b[0] - to $bi +.type __ecp_nistz256_mul_mont,%function +.align 4 +__ecp_nistz256_mul_mont: + mul $acc0,$a0,$bi // a[0]*b[0] + umulh $t0,$a0,$bi + + mul $acc1,$a1,$bi // a[1]*b[0] + umulh $t1,$a1,$bi + + mul $acc2,$a2,$bi // a[2]*b[0] + umulh $t2,$a2,$bi + + mul $acc3,$a3,$bi // a[3]*b[0] + umulh $t3,$a3,$bi + ldr $bi,[$bp,#8] // b[1] + + adds $acc1,$acc1,$t0 // accumulate high parts of multiplication + lsl $t0,$acc0,#32 + adcs $acc2,$acc2,$t1 + lsr $t1,$acc0,#32 + adcs $acc3,$acc3,$t2 + adc $acc4,xzr,$t3 + mov $acc5,xzr +___ +for($i=1;$i<4;$i++) { + # Reduction iteration is normally performed by accumulating + # result of multiplication of modulus by "magic" digit [and + # omitting least significant word, which is guaranteed to + # be 0], but thanks to special form of modulus and "magic" + # digit being equal to least significant word, it can be + # performed with additions and subtractions alone. Indeed: + # + # ffff0001.00000000.0000ffff.ffffffff + # * abcdefgh + # + xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx.abcdefgh + # + # Now observing that ff..ff*x = (2^n-1)*x = 2^n*x-x, we + # rewrite above as: + # + # xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx.abcdefgh + # + abcdefgh.abcdefgh.0000abcd.efgh0000.00000000 + # - 0000abcd.efgh0000.00000000.00000000.abcdefgh + # + # or marking redundant operations: + # + # xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx.-------- + # + abcdefgh.abcdefgh.0000abcd.efgh0000.-------- + # - 0000abcd.efgh0000.--------.--------.-------- + +$code.=<<___; + subs $t2,$acc0,$t0 // "*0xffff0001" + sbc $t3,$acc0,$t1 + adds $acc0,$acc1,$t0 // +=acc[0]<<96 and omit acc[0] + mul $t0,$a0,$bi // lo(a[0]*b[i]) + adcs $acc1,$acc2,$t1 + mul $t1,$a1,$bi // lo(a[1]*b[i]) + adcs $acc2,$acc3,$t2 // +=acc[0]*0xffff0001 + mul $t2,$a2,$bi // lo(a[2]*b[i]) + adcs $acc3,$acc4,$t3 + mul $t3,$a3,$bi // lo(a[3]*b[i]) + adc $acc4,$acc5,xzr + + adds $acc0,$acc0,$t0 // accumulate low parts of multiplication + umulh $t0,$a0,$bi // hi(a[0]*b[i]) + adcs $acc1,$acc1,$t1 + umulh $t1,$a1,$bi // hi(a[1]*b[i]) + adcs $acc2,$acc2,$t2 + umulh $t2,$a2,$bi // hi(a[2]*b[i]) + adcs $acc3,$acc3,$t3 + umulh $t3,$a3,$bi // hi(a[3]*b[i]) + adc $acc4,$acc4,xzr +___ +$code.=<<___ if ($i<3); + ldr $bi,[$bp,#8*($i+1)] // b[$i+1] +___ +$code.=<<___; + adds $acc1,$acc1,$t0 // accumulate high parts of multiplication + lsl $t0,$acc0,#32 + adcs $acc2,$acc2,$t1 + lsr $t1,$acc0,#32 + adcs $acc3,$acc3,$t2 + adcs $acc4,$acc4,$t3 + adc $acc5,xzr,xzr +___ +} +$code.=<<___; + // last reduction + subs $t2,$acc0,$t0 // "*0xffff0001" + sbc $t3,$acc0,$t1 + adds $acc0,$acc1,$t0 // +=acc[0]<<96 and omit acc[0] + adcs $acc1,$acc2,$t1 + adcs $acc2,$acc3,$t2 // +=acc[0]*0xffff0001 + adcs $acc3,$acc4,$t3 + adc $acc4,$acc5,xzr + + adds $t0,$acc0,#1 // subs $t0,$acc0,#-1 // tmp = ret-modulus + sbcs $t1,$acc1,$poly1 + sbcs $t2,$acc2,xzr + sbcs $t3,$acc3,$poly3 + sbcs xzr,$acc4,xzr // did it borrow? + + csel $acc0,$acc0,$t0,lo // ret = borrow ? ret : ret-modulus + csel $acc1,$acc1,$t1,lo + csel $acc2,$acc2,$t2,lo + stp $acc0,$acc1,[$rp] + csel $acc3,$acc3,$t3,lo + stp $acc2,$acc3,[$rp,#16] + + ret +.size __ecp_nistz256_mul_mont,.-__ecp_nistz256_mul_mont + +// note that __ecp_nistz256_sqr_mont expects a[0-3] input pre-loaded +// to $a0-$a3 +.type __ecp_nistz256_sqr_mont,%function +.align 4 +__ecp_nistz256_sqr_mont: + // | | | | | |a1*a0| | + // | | | | |a2*a0| | | + // | |a3*a2|a3*a0| | | | + // | | | |a2*a1| | | | + // | | |a3*a1| | | | | + // *| | | | | | | | 2| + // +|a3*a3|a2*a2|a1*a1|a0*a0| + // |--+--+--+--+--+--+--+--| + // |A7|A6|A5|A4|A3|A2|A1|A0|, where Ax is $accx, i.e. follow $accx + // + // "can't overflow" below mark carrying into high part of + // multiplication result, which can't overflow, because it + // can never be all ones. + + mul $acc1,$a1,$a0 // a[1]*a[0] + umulh $t1,$a1,$a0 + mul $acc2,$a2,$a0 // a[2]*a[0] + umulh $t2,$a2,$a0 + mul $acc3,$a3,$a0 // a[3]*a[0] + umulh $acc4,$a3,$a0 + + adds $acc2,$acc2,$t1 // accumulate high parts of multiplication + mul $t0,$a2,$a1 // a[2]*a[1] + umulh $t1,$a2,$a1 + adcs $acc3,$acc3,$t2 + mul $t2,$a3,$a1 // a[3]*a[1] + umulh $t3,$a3,$a1 + adc $acc4,$acc4,xzr // can't overflow + + mul $acc5,$a3,$a2 // a[3]*a[2] + umulh $acc6,$a3,$a2 + + adds $t1,$t1,$t2 // accumulate high parts of multiplication + mul $acc0,$a0,$a0 // a[0]*a[0] + adc $t2,$t3,xzr // can't overflow + + adds $acc3,$acc3,$t0 // accumulate low parts of multiplication + umulh $a0,$a0,$a0 + adcs $acc4,$acc4,$t1 + mul $t1,$a1,$a1 // a[1]*a[1] + adcs $acc5,$acc5,$t2 + umulh $a1,$a1,$a1 + adc $acc6,$acc6,xzr // can't overflow + + adds $acc1,$acc1,$acc1 // acc[1-6]*=2 + mul $t2,$a2,$a2 // a[2]*a[2] + adcs $acc2,$acc2,$acc2 + umulh $a2,$a2,$a2 + adcs $acc3,$acc3,$acc3 + mul $t3,$a3,$a3 // a[3]*a[3] + adcs $acc4,$acc4,$acc4 + umulh $a3,$a3,$a3 + adcs $acc5,$acc5,$acc5 + adcs $acc6,$acc6,$acc6 + adc $acc7,xzr,xzr + + adds $acc1,$acc1,$a0 // +a[i]*a[i] + adcs $acc2,$acc2,$t1 + adcs $acc3,$acc3,$a1 + adcs $acc4,$acc4,$t2 + adcs $acc5,$acc5,$a2 + lsl $t0,$acc0,#32 + adcs $acc6,$acc6,$t3 + lsr $t1,$acc0,#32 + adc $acc7,$acc7,$a3 +___ +for($i=0;$i<3;$i++) { # reductions, see commentary in + # multiplication for details +$code.=<<___; + subs $t2,$acc0,$t0 // "*0xffff0001" + sbc $t3,$acc0,$t1 + adds $acc0,$acc1,$t0 // +=acc[0]<<96 and omit acc[0] + adcs $acc1,$acc2,$t1 + lsl $t0,$acc0,#32 + adcs $acc2,$acc3,$t2 // +=acc[0]*0xffff0001 + lsr $t1,$acc0,#32 + adc $acc3,$t3,xzr // can't overflow +___ +} +$code.=<<___; + subs $t2,$acc0,$t0 // "*0xffff0001" + sbc $t3,$acc0,$t1 + adds $acc0,$acc1,$t0 // +=acc[0]<<96 and omit acc[0] + adcs $acc1,$acc2,$t1 + adcs $acc2,$acc3,$t2 // +=acc[0]*0xffff0001 + adc $acc3,$t3,xzr // can't overflow + + adds $acc0,$acc0,$acc4 // accumulate upper half + adcs $acc1,$acc1,$acc5 + adcs $acc2,$acc2,$acc6 + adcs $acc3,$acc3,$acc7 + adc $acc4,xzr,xzr + + adds $t0,$acc0,#1 // subs $t0,$acc0,#-1 // tmp = ret-modulus + sbcs $t1,$acc1,$poly1 + sbcs $t2,$acc2,xzr + sbcs $t3,$acc3,$poly3 + sbcs xzr,$acc4,xzr // did it borrow? + + csel $acc0,$acc0,$t0,lo // ret = borrow ? ret : ret-modulus + csel $acc1,$acc1,$t1,lo + csel $acc2,$acc2,$t2,lo + stp $acc0,$acc1,[$rp] + csel $acc3,$acc3,$t3,lo + stp $acc2,$acc3,[$rp,#16] + + ret +.size __ecp_nistz256_sqr_mont,.-__ecp_nistz256_sqr_mont + +// Note that __ecp_nistz256_add expects both input vectors pre-loaded to +// $a0-$a3 and $t0-$t3. This is done because it's used in multiple +// contexts, e.g. in multiplication by 2 and 3... +.type __ecp_nistz256_add,%function +.align 4 +__ecp_nistz256_add: + adds $acc0,$acc0,$t0 // ret = a+b + adcs $acc1,$acc1,$t1 + adcs $acc2,$acc2,$t2 + adcs $acc3,$acc3,$t3 + adc $ap,xzr,xzr // zap $ap + + adds $t0,$acc0,#1 // subs $t0,$a0,#-1 // tmp = ret-modulus + sbcs $t1,$acc1,$poly1 + sbcs $t2,$acc2,xzr + sbcs $t3,$acc3,$poly3 + sbcs xzr,$ap,xzr // did subtraction borrow? + + csel $acc0,$acc0,$t0,lo // ret = borrow ? ret : ret-modulus + csel $acc1,$acc1,$t1,lo + csel $acc2,$acc2,$t2,lo + stp $acc0,$acc1,[$rp] + csel $acc3,$acc3,$t3,lo + stp $acc2,$acc3,[$rp,#16] + + ret +.size __ecp_nistz256_add,.-__ecp_nistz256_add + +.type __ecp_nistz256_sub_from,%function +.align 4 +__ecp_nistz256_sub_from: + ldp $t0,$t1,[$bp] + ldp $t2,$t3,[$bp,#16] + subs $acc0,$acc0,$t0 // ret = a-b + sbcs $acc1,$acc1,$t1 + sbcs $acc2,$acc2,$t2 + sbcs $acc3,$acc3,$t3 + sbc $ap,xzr,xzr // zap $ap + + subs $t0,$acc0,#1 // adds $t0,$a0,#-1 // tmp = ret+modulus + adcs $t1,$acc1,$poly1 + adcs $t2,$acc2,xzr + adc $t3,$acc3,$poly3 + cmp $ap,xzr // did subtraction borrow? + + csel $acc0,$acc0,$t0,eq // ret = borrow ? ret+modulus : ret + csel $acc1,$acc1,$t1,eq + csel $acc2,$acc2,$t2,eq + stp $acc0,$acc1,[$rp] + csel $acc3,$acc3,$t3,eq + stp $acc2,$acc3,[$rp,#16] + + ret +.size __ecp_nistz256_sub_from,.-__ecp_nistz256_sub_from + +.type __ecp_nistz256_sub_morf,%function +.align 4 +__ecp_nistz256_sub_morf: + ldp $t0,$t1,[$bp] + ldp $t2,$t3,[$bp,#16] + subs $acc0,$t0,$acc0 // ret = b-a + sbcs $acc1,$t1,$acc1 + sbcs $acc2,$t2,$acc2 + sbcs $acc3,$t3,$acc3 + sbc $ap,xzr,xzr // zap $ap + + subs $t0,$acc0,#1 // adds $t0,$a0,#-1 // tmp = ret+modulus + adcs $t1,$acc1,$poly1 + adcs $t2,$acc2,xzr + adc $t3,$acc3,$poly3 + cmp $ap,xzr // did subtraction borrow? + + csel $acc0,$acc0,$t0,eq // ret = borrow ? ret+modulus : ret + csel $acc1,$acc1,$t1,eq + csel $acc2,$acc2,$t2,eq + stp $acc0,$acc1,[$rp] + csel $acc3,$acc3,$t3,eq + stp $acc2,$acc3,[$rp,#16] + + ret +.size __ecp_nistz256_sub_morf,.-__ecp_nistz256_sub_morf + +.type __ecp_nistz256_div_by_2,%function +.align 4 +__ecp_nistz256_div_by_2: + subs $t0,$acc0,#1 // adds $t0,$a0,#-1 // tmp = a+modulus + adcs $t1,$acc1,$poly1 + adcs $t2,$acc2,xzr + adcs $t3,$acc3,$poly3 + adc $ap,xzr,xzr // zap $ap + tst $acc0,#1 // is a even? + + csel $acc0,$acc0,$t0,eq // ret = even ? a : a+modulus + csel $acc1,$acc1,$t1,eq + csel $acc2,$acc2,$t2,eq + csel $acc3,$acc3,$t3,eq + csel $ap,xzr,$ap,eq + + lsr $acc0,$acc0,#1 // ret >>= 1 + orr $acc0,$acc0,$acc1,lsl#63 + lsr $acc1,$acc1,#1 + orr $acc1,$acc1,$acc2,lsl#63 + lsr $acc2,$acc2,#1 + orr $acc2,$acc2,$acc3,lsl#63 + lsr $acc3,$acc3,#1 + stp $acc0,$acc1,[$rp] + orr $acc3,$acc3,$ap,lsl#63 + stp $acc2,$acc3,[$rp,#16] + + ret +.size __ecp_nistz256_div_by_2,.-__ecp_nistz256_div_by_2 +___ +######################################################################## +# following subroutines are "literal" implementation of those found in +# ecp_nistz256.c +# +######################################################################## +# void ecp_nistz256_point_double(P256_POINT *out,const P256_POINT *inp); +# +{ +my ($S,$M,$Zsqr,$tmp0)=map(32*$_,(0..3)); +# above map() describes stack layout with 4 temporary +# 256-bit vectors on top. +my ($rp_real,$ap_real) = map("x$_",(21,22)); + +$code.=<<___; +.globl ecp_nistz256_point_double +.type ecp_nistz256_point_double,%function +.align 5 +ecp_nistz256_point_double: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-80]! + add x29,sp,#0 + stp x19,x20,[sp,#16] + stp x21,x22,[sp,#32] + sub sp,sp,#32*4 + +.Ldouble_shortcut: + ldp $acc0,$acc1,[$ap,#32] + mov $rp_real,$rp + ldp $acc2,$acc3,[$ap,#48] + mov $ap_real,$ap + ldr $poly1,.Lpoly+8 + mov $t0,$acc0 + ldr $poly3,.Lpoly+24 + mov $t1,$acc1 + ldp $a0,$a1,[$ap_real,#64] // forward load for p256_sqr_mont + mov $t2,$acc2 + mov $t3,$acc3 + ldp $a2,$a3,[$ap_real,#64+16] + add $rp,sp,#$S + bl __ecp_nistz256_add // p256_mul_by_2(S, in_y); + + add $rp,sp,#$Zsqr + bl __ecp_nistz256_sqr_mont // p256_sqr_mont(Zsqr, in_z); + + ldp $t0,$t1,[$ap_real] + ldp $t2,$t3,[$ap_real,#16] + mov $a0,$acc0 // put Zsqr aside for p256_sub + mov $a1,$acc1 + mov $a2,$acc2 + mov $a3,$acc3 + add $rp,sp,#$M + bl __ecp_nistz256_add // p256_add(M, Zsqr, in_x); + + add $bp,$ap_real,#0 + mov $acc0,$a0 // restore Zsqr + mov $acc1,$a1 + ldp $a0,$a1,[sp,#$S] // forward load for p256_sqr_mont + mov $acc2,$a2 + mov $acc3,$a3 + ldp $a2,$a3,[sp,#$S+16] + add $rp,sp,#$Zsqr + bl __ecp_nistz256_sub_morf // p256_sub(Zsqr, in_x, Zsqr); + + add $rp,sp,#$S + bl __ecp_nistz256_sqr_mont // p256_sqr_mont(S, S); + + ldr $bi,[$ap_real,#32] + ldp $a0,$a1,[$ap_real,#64] + ldp $a2,$a3,[$ap_real,#64+16] + add $bp,$ap_real,#32 + add $rp,sp,#$tmp0 + bl __ecp_nistz256_mul_mont // p256_mul_mont(tmp0, in_z, in_y); + + mov $t0,$acc0 + mov $t1,$acc1 + ldp $a0,$a1,[sp,#$S] // forward load for p256_sqr_mont + mov $t2,$acc2 + mov $t3,$acc3 + ldp $a2,$a3,[sp,#$S+16] + add $rp,$rp_real,#64 + bl __ecp_nistz256_add // p256_mul_by_2(res_z, tmp0); + + add $rp,sp,#$tmp0 + bl __ecp_nistz256_sqr_mont // p256_sqr_mont(tmp0, S); + + ldr $bi,[sp,#$Zsqr] // forward load for p256_mul_mont + ldp $a0,$a1,[sp,#$M] + ldp $a2,$a3,[sp,#$M+16] + add $rp,$rp_real,#32 + bl __ecp_nistz256_div_by_2 // p256_div_by_2(res_y, tmp0); + + add $bp,sp,#$Zsqr + add $rp,sp,#$M + bl __ecp_nistz256_mul_mont // p256_mul_mont(M, M, Zsqr); + + mov $t0,$acc0 // duplicate M + mov $t1,$acc1 + mov $t2,$acc2 + mov $t3,$acc3 + mov $a0,$acc0 // put M aside + mov $a1,$acc1 + mov $a2,$acc2 + mov $a3,$acc3 + add $rp,sp,#$M + bl __ecp_nistz256_add + mov $t0,$a0 // restore M + mov $t1,$a1 + ldr $bi,[$ap_real] // forward load for p256_mul_mont + mov $t2,$a2 + ldp $a0,$a1,[sp,#$S] + mov $t3,$a3 + ldp $a2,$a3,[sp,#$S+16] + bl __ecp_nistz256_add // p256_mul_by_3(M, M); + + add $bp,$ap_real,#0 + add $rp,sp,#$S + bl __ecp_nistz256_mul_mont // p256_mul_mont(S, S, in_x); + + mov $t0,$acc0 + mov $t1,$acc1 + ldp $a0,$a1,[sp,#$M] // forward load for p256_sqr_mont + mov $t2,$acc2 + mov $t3,$acc3 + ldp $a2,$a3,[sp,#$M+16] + add $rp,sp,#$tmp0 + bl __ecp_nistz256_add // p256_mul_by_2(tmp0, S); + + add $rp,$rp_real,#0 + bl __ecp_nistz256_sqr_mont // p256_sqr_mont(res_x, M); + + add $bp,sp,#$tmp0 + bl __ecp_nistz256_sub_from // p256_sub(res_x, res_x, tmp0); + + add $bp,sp,#$S + add $rp,sp,#$S + bl __ecp_nistz256_sub_morf // p256_sub(S, S, res_x); + + ldr $bi,[sp,#$M] + mov $a0,$acc0 // copy S + mov $a1,$acc1 + mov $a2,$acc2 + mov $a3,$acc3 + add $bp,sp,#$M + bl __ecp_nistz256_mul_mont // p256_mul_mont(S, S, M); + + add $bp,$rp_real,#32 + add $rp,$rp_real,#32 + bl __ecp_nistz256_sub_from // p256_sub(res_y, S, res_y); + + add sp,x29,#0 // destroy frame + ldp x19,x20,[x29,#16] + ldp x21,x22,[x29,#32] + ldp x29,x30,[sp],#80 + .inst 0xd50323bf // autiasp + ret +.size ecp_nistz256_point_double,.-ecp_nistz256_point_double +___ +} + +######################################################################## +# void ecp_nistz256_point_add(P256_POINT *out,const P256_POINT *in1, +# const P256_POINT *in2); +{ +my ($res_x,$res_y,$res_z, + $H,$Hsqr,$R,$Rsqr,$Hcub, + $U1,$U2,$S1,$S2)=map(32*$_,(0..11)); +my ($Z1sqr, $Z2sqr) = ($Hsqr, $Rsqr); +# above map() describes stack layout with 12 temporary +# 256-bit vectors on top. +my ($rp_real,$ap_real,$bp_real,$in1infty,$in2infty,$temp)=map("x$_",(21..26)); + +$code.=<<___; +.globl ecp_nistz256_point_add +.type ecp_nistz256_point_add,%function +.align 5 +ecp_nistz256_point_add: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-80]! + add x29,sp,#0 + stp x19,x20,[sp,#16] + stp x21,x22,[sp,#32] + stp x23,x24,[sp,#48] + stp x25,x26,[sp,#64] + sub sp,sp,#32*12 + + ldp $a0,$a1,[$bp,#64] // in2_z + ldp $a2,$a3,[$bp,#64+16] + mov $rp_real,$rp + mov $ap_real,$ap + mov $bp_real,$bp + ldr $poly1,.Lpoly+8 + ldr $poly3,.Lpoly+24 + orr $t0,$a0,$a1 + orr $t2,$a2,$a3 + orr $in2infty,$t0,$t2 + cmp $in2infty,#0 + csetm $in2infty,ne // !in2infty + add $rp,sp,#$Z2sqr + bl __ecp_nistz256_sqr_mont // p256_sqr_mont(Z2sqr, in2_z); + + ldp $a0,$a1,[$ap_real,#64] // in1_z + ldp $a2,$a3,[$ap_real,#64+16] + orr $t0,$a0,$a1 + orr $t2,$a2,$a3 + orr $in1infty,$t0,$t2 + cmp $in1infty,#0 + csetm $in1infty,ne // !in1infty + add $rp,sp,#$Z1sqr + bl __ecp_nistz256_sqr_mont // p256_sqr_mont(Z1sqr, in1_z); + + ldr $bi,[$bp_real,#64] + ldp $a0,$a1,[sp,#$Z2sqr] + ldp $a2,$a3,[sp,#$Z2sqr+16] + add $bp,$bp_real,#64 + add $rp,sp,#$S1 + bl __ecp_nistz256_mul_mont // p256_mul_mont(S1, Z2sqr, in2_z); + + ldr $bi,[$ap_real,#64] + ldp $a0,$a1,[sp,#$Z1sqr] + ldp $a2,$a3,[sp,#$Z1sqr+16] + add $bp,$ap_real,#64 + add $rp,sp,#$S2 + bl __ecp_nistz256_mul_mont // p256_mul_mont(S2, Z1sqr, in1_z); + + ldr $bi,[$ap_real,#32] + ldp $a0,$a1,[sp,#$S1] + ldp $a2,$a3,[sp,#$S1+16] + add $bp,$ap_real,#32 + add $rp,sp,#$S1 + bl __ecp_nistz256_mul_mont // p256_mul_mont(S1, S1, in1_y); + + ldr $bi,[$bp_real,#32] + ldp $a0,$a1,[sp,#$S2] + ldp $a2,$a3,[sp,#$S2+16] + add $bp,$bp_real,#32 + add $rp,sp,#$S2 + bl __ecp_nistz256_mul_mont // p256_mul_mont(S2, S2, in2_y); + + add $bp,sp,#$S1 + ldr $bi,[sp,#$Z2sqr] // forward load for p256_mul_mont + ldp $a0,$a1,[$ap_real] + ldp $a2,$a3,[$ap_real,#16] + add $rp,sp,#$R + bl __ecp_nistz256_sub_from // p256_sub(R, S2, S1); + + orr $acc0,$acc0,$acc1 // see if result is zero + orr $acc2,$acc2,$acc3 + orr $temp,$acc0,$acc2 + + add $bp,sp,#$Z2sqr + add $rp,sp,#$U1 + bl __ecp_nistz256_mul_mont // p256_mul_mont(U1, in1_x, Z2sqr); + + ldr $bi,[sp,#$Z1sqr] + ldp $a0,$a1,[$bp_real] + ldp $a2,$a3,[$bp_real,#16] + add $bp,sp,#$Z1sqr + add $rp,sp,#$U2 + bl __ecp_nistz256_mul_mont // p256_mul_mont(U2, in2_x, Z1sqr); + + add $bp,sp,#$U1 + ldp $a0,$a1,[sp,#$R] // forward load for p256_sqr_mont + ldp $a2,$a3,[sp,#$R+16] + add $rp,sp,#$H + bl __ecp_nistz256_sub_from // p256_sub(H, U2, U1); + + orr $acc0,$acc0,$acc1 // see if result is zero + orr $acc2,$acc2,$acc3 + orr $acc0,$acc0,$acc2 + tst $acc0,$acc0 + b.ne .Ladd_proceed // is_equal(U1,U2)? + + tst $in1infty,$in2infty + b.eq .Ladd_proceed // (in1infty || in2infty)? + + tst $temp,$temp + b.eq .Ladd_double // is_equal(S1,S2)? + + eor $a0,$a0,$a0 + eor $a1,$a1,$a1 + stp $a0,$a1,[$rp_real] + stp $a0,$a1,[$rp_real,#16] + stp $a0,$a1,[$rp_real,#32] + stp $a0,$a1,[$rp_real,#48] + stp $a0,$a1,[$rp_real,#64] + stp $a0,$a1,[$rp_real,#80] + b .Ladd_done + +.align 4 +.Ladd_double: + mov $ap,$ap_real + mov $rp,$rp_real + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + add sp,sp,#32*(12-4) // difference in stack frames + b .Ldouble_shortcut + +.align 4 +.Ladd_proceed: + add $rp,sp,#$Rsqr + bl __ecp_nistz256_sqr_mont // p256_sqr_mont(Rsqr, R); + + ldr $bi,[$ap_real,#64] + ldp $a0,$a1,[sp,#$H] + ldp $a2,$a3,[sp,#$H+16] + add $bp,$ap_real,#64 + add $rp,sp,#$res_z + bl __ecp_nistz256_mul_mont // p256_mul_mont(res_z, H, in1_z); + + ldp $a0,$a1,[sp,#$H] + ldp $a2,$a3,[sp,#$H+16] + add $rp,sp,#$Hsqr + bl __ecp_nistz256_sqr_mont // p256_sqr_mont(Hsqr, H); + + ldr $bi,[$bp_real,#64] + ldp $a0,$a1,[sp,#$res_z] + ldp $a2,$a3,[sp,#$res_z+16] + add $bp,$bp_real,#64 + add $rp,sp,#$res_z + bl __ecp_nistz256_mul_mont // p256_mul_mont(res_z, res_z, in2_z); + + ldr $bi,[sp,#$H] + ldp $a0,$a1,[sp,#$Hsqr] + ldp $a2,$a3,[sp,#$Hsqr+16] + add $bp,sp,#$H + add $rp,sp,#$Hcub + bl __ecp_nistz256_mul_mont // p256_mul_mont(Hcub, Hsqr, H); + + ldr $bi,[sp,#$Hsqr] + ldp $a0,$a1,[sp,#$U1] + ldp $a2,$a3,[sp,#$U1+16] + add $bp,sp,#$Hsqr + add $rp,sp,#$U2 + bl __ecp_nistz256_mul_mont // p256_mul_mont(U2, U1, Hsqr); + + mov $t0,$acc0 + mov $t1,$acc1 + mov $t2,$acc2 + mov $t3,$acc3 + add $rp,sp,#$Hsqr + bl __ecp_nistz256_add // p256_mul_by_2(Hsqr, U2); + + add $bp,sp,#$Rsqr + add $rp,sp,#$res_x + bl __ecp_nistz256_sub_morf // p256_sub(res_x, Rsqr, Hsqr); + + add $bp,sp,#$Hcub + bl __ecp_nistz256_sub_from // p256_sub(res_x, res_x, Hcub); + + add $bp,sp,#$U2 + ldr $bi,[sp,#$Hcub] // forward load for p256_mul_mont + ldp $a0,$a1,[sp,#$S1] + ldp $a2,$a3,[sp,#$S1+16] + add $rp,sp,#$res_y + bl __ecp_nistz256_sub_morf // p256_sub(res_y, U2, res_x); + + add $bp,sp,#$Hcub + add $rp,sp,#$S2 + bl __ecp_nistz256_mul_mont // p256_mul_mont(S2, S1, Hcub); + + ldr $bi,[sp,#$R] + ldp $a0,$a1,[sp,#$res_y] + ldp $a2,$a3,[sp,#$res_y+16] + add $bp,sp,#$R + add $rp,sp,#$res_y + bl __ecp_nistz256_mul_mont // p256_mul_mont(res_y, res_y, R); + + add $bp,sp,#$S2 + bl __ecp_nistz256_sub_from // p256_sub(res_y, res_y, S2); + + ldp $a0,$a1,[sp,#$res_x] // res + ldp $a2,$a3,[sp,#$res_x+16] + ldp $t0,$t1,[$bp_real] // in2 + ldp $t2,$t3,[$bp_real,#16] +___ +for($i=0;$i<64;$i+=32) { # conditional moves +$code.=<<___; + ldp $acc0,$acc1,[$ap_real,#$i] // in1 + cmp $in1infty,#0 // !$in1intfy, remember? + ldp $acc2,$acc3,[$ap_real,#$i+16] + csel $t0,$a0,$t0,ne + csel $t1,$a1,$t1,ne + ldp $a0,$a1,[sp,#$res_x+$i+32] // res + csel $t2,$a2,$t2,ne + csel $t3,$a3,$t3,ne + cmp $in2infty,#0 // !$in2intfy, remember? + ldp $a2,$a3,[sp,#$res_x+$i+48] + csel $acc0,$t0,$acc0,ne + csel $acc1,$t1,$acc1,ne + ldp $t0,$t1,[$bp_real,#$i+32] // in2 + csel $acc2,$t2,$acc2,ne + csel $acc3,$t3,$acc3,ne + ldp $t2,$t3,[$bp_real,#$i+48] + stp $acc0,$acc1,[$rp_real,#$i] + stp $acc2,$acc3,[$rp_real,#$i+16] +___ +} +$code.=<<___; + ldp $acc0,$acc1,[$ap_real,#$i] // in1 + cmp $in1infty,#0 // !$in1intfy, remember? + ldp $acc2,$acc3,[$ap_real,#$i+16] + csel $t0,$a0,$t0,ne + csel $t1,$a1,$t1,ne + csel $t2,$a2,$t2,ne + csel $t3,$a3,$t3,ne + cmp $in2infty,#0 // !$in2intfy, remember? + csel $acc0,$t0,$acc0,ne + csel $acc1,$t1,$acc1,ne + csel $acc2,$t2,$acc2,ne + csel $acc3,$t3,$acc3,ne + stp $acc0,$acc1,[$rp_real,#$i] + stp $acc2,$acc3,[$rp_real,#$i+16] + +.Ladd_done: + add sp,x29,#0 // destroy frame + ldp x19,x20,[x29,#16] + ldp x21,x22,[x29,#32] + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x29,x30,[sp],#80 + .inst 0xd50323bf // autiasp + ret +.size ecp_nistz256_point_add,.-ecp_nistz256_point_add +___ +} + +######################################################################## +# void ecp_nistz256_point_add_affine(P256_POINT *out,const P256_POINT *in1, +# const P256_POINT_AFFINE *in2); +{ +my ($res_x,$res_y,$res_z, + $U2,$S2,$H,$R,$Hsqr,$Hcub,$Rsqr)=map(32*$_,(0..9)); +my $Z1sqr = $S2; +# above map() describes stack layout with 10 temporary +# 256-bit vectors on top. +my ($rp_real,$ap_real,$bp_real,$in1infty,$in2infty,$temp)=map("x$_",(21..26)); + +$code.=<<___; +.globl ecp_nistz256_point_add_affine +.type ecp_nistz256_point_add_affine,%function +.align 5 +ecp_nistz256_point_add_affine: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-80]! + add x29,sp,#0 + stp x19,x20,[sp,#16] + stp x21,x22,[sp,#32] + stp x23,x24,[sp,#48] + stp x25,x26,[sp,#64] + sub sp,sp,#32*10 + + mov $rp_real,$rp + mov $ap_real,$ap + mov $bp_real,$bp + ldr $poly1,.Lpoly+8 + ldr $poly3,.Lpoly+24 + + ldp $a0,$a1,[$ap,#64] // in1_z + ldp $a2,$a3,[$ap,#64+16] + orr $t0,$a0,$a1 + orr $t2,$a2,$a3 + orr $in1infty,$t0,$t2 + cmp $in1infty,#0 + csetm $in1infty,ne // !in1infty + + ldp $acc0,$acc1,[$bp] // in2_x + ldp $acc2,$acc3,[$bp,#16] + ldp $t0,$t1,[$bp,#32] // in2_y + ldp $t2,$t3,[$bp,#48] + orr $acc0,$acc0,$acc1 + orr $acc2,$acc2,$acc3 + orr $t0,$t0,$t1 + orr $t2,$t2,$t3 + orr $acc0,$acc0,$acc2 + orr $t0,$t0,$t2 + orr $in2infty,$acc0,$t0 + cmp $in2infty,#0 + csetm $in2infty,ne // !in2infty + + add $rp,sp,#$Z1sqr + bl __ecp_nistz256_sqr_mont // p256_sqr_mont(Z1sqr, in1_z); + + mov $a0,$acc0 + mov $a1,$acc1 + mov $a2,$acc2 + mov $a3,$acc3 + ldr $bi,[$bp_real] + add $bp,$bp_real,#0 + add $rp,sp,#$U2 + bl __ecp_nistz256_mul_mont // p256_mul_mont(U2, Z1sqr, in2_x); + + add $bp,$ap_real,#0 + ldr $bi,[$ap_real,#64] // forward load for p256_mul_mont + ldp $a0,$a1,[sp,#$Z1sqr] + ldp $a2,$a3,[sp,#$Z1sqr+16] + add $rp,sp,#$H + bl __ecp_nistz256_sub_from // p256_sub(H, U2, in1_x); + + add $bp,$ap_real,#64 + add $rp,sp,#$S2 + bl __ecp_nistz256_mul_mont // p256_mul_mont(S2, Z1sqr, in1_z); + + ldr $bi,[$ap_real,#64] + ldp $a0,$a1,[sp,#$H] + ldp $a2,$a3,[sp,#$H+16] + add $bp,$ap_real,#64 + add $rp,sp,#$res_z + bl __ecp_nistz256_mul_mont // p256_mul_mont(res_z, H, in1_z); + + ldr $bi,[$bp_real,#32] + ldp $a0,$a1,[sp,#$S2] + ldp $a2,$a3,[sp,#$S2+16] + add $bp,$bp_real,#32 + add $rp,sp,#$S2 + bl __ecp_nistz256_mul_mont // p256_mul_mont(S2, S2, in2_y); + + add $bp,$ap_real,#32 + ldp $a0,$a1,[sp,#$H] // forward load for p256_sqr_mont + ldp $a2,$a3,[sp,#$H+16] + add $rp,sp,#$R + bl __ecp_nistz256_sub_from // p256_sub(R, S2, in1_y); + + add $rp,sp,#$Hsqr + bl __ecp_nistz256_sqr_mont // p256_sqr_mont(Hsqr, H); + + ldp $a0,$a1,[sp,#$R] + ldp $a2,$a3,[sp,#$R+16] + add $rp,sp,#$Rsqr + bl __ecp_nistz256_sqr_mont // p256_sqr_mont(Rsqr, R); + + ldr $bi,[sp,#$H] + ldp $a0,$a1,[sp,#$Hsqr] + ldp $a2,$a3,[sp,#$Hsqr+16] + add $bp,sp,#$H + add $rp,sp,#$Hcub + bl __ecp_nistz256_mul_mont // p256_mul_mont(Hcub, Hsqr, H); + + ldr $bi,[$ap_real] + ldp $a0,$a1,[sp,#$Hsqr] + ldp $a2,$a3,[sp,#$Hsqr+16] + add $bp,$ap_real,#0 + add $rp,sp,#$U2 + bl __ecp_nistz256_mul_mont // p256_mul_mont(U2, in1_x, Hsqr); + + mov $t0,$acc0 + mov $t1,$acc1 + mov $t2,$acc2 + mov $t3,$acc3 + add $rp,sp,#$Hsqr + bl __ecp_nistz256_add // p256_mul_by_2(Hsqr, U2); + + add $bp,sp,#$Rsqr + add $rp,sp,#$res_x + bl __ecp_nistz256_sub_morf // p256_sub(res_x, Rsqr, Hsqr); + + add $bp,sp,#$Hcub + bl __ecp_nistz256_sub_from // p256_sub(res_x, res_x, Hcub); + + add $bp,sp,#$U2 + ldr $bi,[$ap_real,#32] // forward load for p256_mul_mont + ldp $a0,$a1,[sp,#$Hcub] + ldp $a2,$a3,[sp,#$Hcub+16] + add $rp,sp,#$res_y + bl __ecp_nistz256_sub_morf // p256_sub(res_y, U2, res_x); + + add $bp,$ap_real,#32 + add $rp,sp,#$S2 + bl __ecp_nistz256_mul_mont // p256_mul_mont(S2, in1_y, Hcub); + + ldr $bi,[sp,#$R] + ldp $a0,$a1,[sp,#$res_y] + ldp $a2,$a3,[sp,#$res_y+16] + add $bp,sp,#$R + add $rp,sp,#$res_y + bl __ecp_nistz256_mul_mont // p256_mul_mont(res_y, res_y, R); + + add $bp,sp,#$S2 + bl __ecp_nistz256_sub_from // p256_sub(res_y, res_y, S2); + + ldp $a0,$a1,[sp,#$res_x] // res + ldp $a2,$a3,[sp,#$res_x+16] + ldp $t0,$t1,[$bp_real] // in2 + ldp $t2,$t3,[$bp_real,#16] +___ +for($i=0;$i<64;$i+=32) { # conditional moves +$code.=<<___; + ldp $acc0,$acc1,[$ap_real,#$i] // in1 + cmp $in1infty,#0 // !$in1intfy, remember? + ldp $acc2,$acc3,[$ap_real,#$i+16] + csel $t0,$a0,$t0,ne + csel $t1,$a1,$t1,ne + ldp $a0,$a1,[sp,#$res_x+$i+32] // res + csel $t2,$a2,$t2,ne + csel $t3,$a3,$t3,ne + cmp $in2infty,#0 // !$in2intfy, remember? + ldp $a2,$a3,[sp,#$res_x+$i+48] + csel $acc0,$t0,$acc0,ne + csel $acc1,$t1,$acc1,ne + ldp $t0,$t1,[$bp_real,#$i+32] // in2 + csel $acc2,$t2,$acc2,ne + csel $acc3,$t3,$acc3,ne + ldp $t2,$t3,[$bp_real,#$i+48] + stp $acc0,$acc1,[$rp_real,#$i] + stp $acc2,$acc3,[$rp_real,#$i+16] +___ +$code.=<<___ if ($i == 0); + adr $bp_real,.Lone_mont-64 +___ +} +$code.=<<___; + ldp $acc0,$acc1,[$ap_real,#$i] // in1 + cmp $in1infty,#0 // !$in1intfy, remember? + ldp $acc2,$acc3,[$ap_real,#$i+16] + csel $t0,$a0,$t0,ne + csel $t1,$a1,$t1,ne + csel $t2,$a2,$t2,ne + csel $t3,$a3,$t3,ne + cmp $in2infty,#0 // !$in2intfy, remember? + csel $acc0,$t0,$acc0,ne + csel $acc1,$t1,$acc1,ne + csel $acc2,$t2,$acc2,ne + csel $acc3,$t3,$acc3,ne + stp $acc0,$acc1,[$rp_real,#$i] + stp $acc2,$acc3,[$rp_real,#$i+16] + + add sp,x29,#0 // destroy frame + ldp x19,x20,[x29,#16] + ldp x21,x22,[x29,#32] + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x29,x30,[sp],#80 + .inst 0xd50323bf // autiasp + ret +.size ecp_nistz256_point_add_affine,.-ecp_nistz256_point_add_affine +___ +} +if (1) { +my ($ord0,$ord1) = ($poly1,$poly3); +my ($ord2,$ord3,$ordk,$t4) = map("x$_",(21..24)); +my $acc7 = $bi; + +$code.=<<___; +//////////////////////////////////////////////////////////////////////// +// void ecp_nistz256_ord_mul_mont(uint64_t res[4], uint64_t a[4], +// uint64_t b[4]); +.globl ecp_nistz256_ord_mul_mont +.type ecp_nistz256_ord_mul_mont,%function +.align 4 +ecp_nistz256_ord_mul_mont: + stp x29,x30,[sp,#-64]! + add x29,sp,#0 + stp x19,x20,[sp,#16] + stp x21,x22,[sp,#32] + stp x23,x24,[sp,#48] + + adr $ordk,.Lord + ldr $bi,[$bp] // bp[0] + ldp $a0,$a1,[$ap] + ldp $a2,$a3,[$ap,#16] + + ldp $ord0,$ord1,[$ordk,#0] + ldp $ord2,$ord3,[$ordk,#16] + ldr $ordk,[$ordk,#32] + + mul $acc0,$a0,$bi // a[0]*b[0] + umulh $t0,$a0,$bi + + mul $acc1,$a1,$bi // a[1]*b[0] + umulh $t1,$a1,$bi + + mul $acc2,$a2,$bi // a[2]*b[0] + umulh $t2,$a2,$bi + + mul $acc3,$a3,$bi // a[3]*b[0] + umulh $acc4,$a3,$bi + + mul $t4,$acc0,$ordk + + adds $acc1,$acc1,$t0 // accumulate high parts of multiplication + adcs $acc2,$acc2,$t1 + adcs $acc3,$acc3,$t2 + adc $acc4,$acc4,xzr + mov $acc5,xzr +___ +for ($i=1;$i<4;$i++) { + ################################################################ + # ffff0000.ffffffff.yyyyyyyy.zzzzzzzz + # * abcdefgh + # + xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx + # + # Now observing that ff..ff*x = (2^n-1)*x = 2^n*x-x, we + # rewrite above as: + # + # xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx + # - 0000abcd.efgh0000.abcdefgh.00000000.00000000 + # + abcdefgh.abcdefgh.yzayzbyz.cyzdyzey.zfyzgyzh +$code.=<<___; + ldr $bi,[$bp,#8*$i] // b[i] + + lsl $t0,$t4,#32 + subs $acc2,$acc2,$t4 + lsr $t1,$t4,#32 + sbcs $acc3,$acc3,$t0 + sbcs $acc4,$acc4,$t1 + sbc $acc5,$acc5,xzr + + subs xzr,$acc0,#1 + umulh $t1,$ord0,$t4 + mul $t2,$ord1,$t4 + umulh $t3,$ord1,$t4 + + adcs $t2,$t2,$t1 + mul $t0,$a0,$bi + adc $t3,$t3,xzr + mul $t1,$a1,$bi + + adds $acc0,$acc1,$t2 + mul $t2,$a2,$bi + adcs $acc1,$acc2,$t3 + mul $t3,$a3,$bi + adcs $acc2,$acc3,$t4 + adcs $acc3,$acc4,$t4 + adc $acc4,$acc5,xzr + + adds $acc0,$acc0,$t0 // accumulate low parts + umulh $t0,$a0,$bi + adcs $acc1,$acc1,$t1 + umulh $t1,$a1,$bi + adcs $acc2,$acc2,$t2 + umulh $t2,$a2,$bi + adcs $acc3,$acc3,$t3 + umulh $t3,$a3,$bi + adc $acc4,$acc4,xzr + mul $t4,$acc0,$ordk + adds $acc1,$acc1,$t0 // accumulate high parts + adcs $acc2,$acc2,$t1 + adcs $acc3,$acc3,$t2 + adcs $acc4,$acc4,$t3 + adc $acc5,xzr,xzr +___ +} +$code.=<<___; + lsl $t0,$t4,#32 // last reduction + subs $acc2,$acc2,$t4 + lsr $t1,$t4,#32 + sbcs $acc3,$acc3,$t0 + sbcs $acc4,$acc4,$t1 + sbc $acc5,$acc5,xzr + + subs xzr,$acc0,#1 + umulh $t1,$ord0,$t4 + mul $t2,$ord1,$t4 + umulh $t3,$ord1,$t4 + + adcs $t2,$t2,$t1 + adc $t3,$t3,xzr + + adds $acc0,$acc1,$t2 + adcs $acc1,$acc2,$t3 + adcs $acc2,$acc3,$t4 + adcs $acc3,$acc4,$t4 + adc $acc4,$acc5,xzr + + subs $t0,$acc0,$ord0 // ret -= modulus + sbcs $t1,$acc1,$ord1 + sbcs $t2,$acc2,$ord2 + sbcs $t3,$acc3,$ord3 + sbcs xzr,$acc4,xzr + + csel $acc0,$acc0,$t0,lo // ret = borrow ? ret : ret-modulus + csel $acc1,$acc1,$t1,lo + csel $acc2,$acc2,$t2,lo + stp $acc0,$acc1,[$rp] + csel $acc3,$acc3,$t3,lo + stp $acc2,$acc3,[$rp,#16] + + ldp x19,x20,[sp,#16] + ldp x21,x22,[sp,#32] + ldp x23,x24,[sp,#48] + ldr x29,[sp],#64 + ret +.size ecp_nistz256_ord_mul_mont,.-ecp_nistz256_ord_mul_mont + +//////////////////////////////////////////////////////////////////////// +// void ecp_nistz256_ord_sqr_mont(uint64_t res[4], uint64_t a[4], +// int rep); +.globl ecp_nistz256_ord_sqr_mont +.type ecp_nistz256_ord_sqr_mont,%function +.align 4 +ecp_nistz256_ord_sqr_mont: + stp x29,x30,[sp,#-64]! + add x29,sp,#0 + stp x19,x20,[sp,#16] + stp x21,x22,[sp,#32] + stp x23,x24,[sp,#48] + + adr $ordk,.Lord + ldp $a0,$a1,[$ap] + ldp $a2,$a3,[$ap,#16] + + ldp $ord0,$ord1,[$ordk,#0] + ldp $ord2,$ord3,[$ordk,#16] + ldr $ordk,[$ordk,#32] + b .Loop_ord_sqr + +.align 4 +.Loop_ord_sqr: + sub $bp,$bp,#1 + //////////////////////////////////////////////////////////////// + // | | | | | |a1*a0| | + // | | | | |a2*a0| | | + // | |a3*a2|a3*a0| | | | + // | | | |a2*a1| | | | + // | | |a3*a1| | | | | + // *| | | | | | | | 2| + // +|a3*a3|a2*a2|a1*a1|a0*a0| + // |--+--+--+--+--+--+--+--| + // |A7|A6|A5|A4|A3|A2|A1|A0|, where Ax is $accx, i.e. follow $accx + // + // "can't overflow" below mark carrying into high part of + // multiplication result, which can't overflow, because it + // can never be all ones. + + mul $acc1,$a1,$a0 // a[1]*a[0] + umulh $t1,$a1,$a0 + mul $acc2,$a2,$a0 // a[2]*a[0] + umulh $t2,$a2,$a0 + mul $acc3,$a3,$a0 // a[3]*a[0] + umulh $acc4,$a3,$a0 + + adds $acc2,$acc2,$t1 // accumulate high parts of multiplication + mul $t0,$a2,$a1 // a[2]*a[1] + umulh $t1,$a2,$a1 + adcs $acc3,$acc3,$t2 + mul $t2,$a3,$a1 // a[3]*a[1] + umulh $t3,$a3,$a1 + adc $acc4,$acc4,xzr // can't overflow + + mul $acc5,$a3,$a2 // a[3]*a[2] + umulh $acc6,$a3,$a2 + + adds $t1,$t1,$t2 // accumulate high parts of multiplication + mul $acc0,$a0,$a0 // a[0]*a[0] + adc $t2,$t3,xzr // can't overflow + + adds $acc3,$acc3,$t0 // accumulate low parts of multiplication + umulh $a0,$a0,$a0 + adcs $acc4,$acc4,$t1 + mul $t1,$a1,$a1 // a[1]*a[1] + adcs $acc5,$acc5,$t2 + umulh $a1,$a1,$a1 + adc $acc6,$acc6,xzr // can't overflow + + adds $acc1,$acc1,$acc1 // acc[1-6]*=2 + mul $t2,$a2,$a2 // a[2]*a[2] + adcs $acc2,$acc2,$acc2 + umulh $a2,$a2,$a2 + adcs $acc3,$acc3,$acc3 + mul $t3,$a3,$a3 // a[3]*a[3] + adcs $acc4,$acc4,$acc4 + umulh $a3,$a3,$a3 + adcs $acc5,$acc5,$acc5 + adcs $acc6,$acc6,$acc6 + adc $acc7,xzr,xzr + + adds $acc1,$acc1,$a0 // +a[i]*a[i] + mul $t4,$acc0,$ordk + adcs $acc2,$acc2,$t1 + adcs $acc3,$acc3,$a1 + adcs $acc4,$acc4,$t2 + adcs $acc5,$acc5,$a2 + adcs $acc6,$acc6,$t3 + adc $acc7,$acc7,$a3 +___ +for($i=0; $i<4; $i++) { # reductions +$code.=<<___; + subs xzr,$acc0,#1 + umulh $t1,$ord0,$t4 + mul $t2,$ord1,$t4 + umulh $t3,$ord1,$t4 + + adcs $t2,$t2,$t1 + adc $t3,$t3,xzr + + adds $acc0,$acc1,$t2 + adcs $acc1,$acc2,$t3 + adcs $acc2,$acc3,$t4 + adc $acc3,xzr,$t4 // can't overflow +___ +$code.=<<___ if ($i<3); + mul $t3,$acc0,$ordk +___ +$code.=<<___; + lsl $t0,$t4,#32 + subs $acc1,$acc1,$t4 + lsr $t1,$t4,#32 + sbcs $acc2,$acc2,$t0 + sbc $acc3,$acc3,$t1 // can't borrow +___ + ($t3,$t4) = ($t4,$t3); +} +$code.=<<___; + adds $acc0,$acc0,$acc4 // accumulate upper half + adcs $acc1,$acc1,$acc5 + adcs $acc2,$acc2,$acc6 + adcs $acc3,$acc3,$acc7 + adc $acc4,xzr,xzr + + subs $t0,$acc0,$ord0 // ret -= modulus + sbcs $t1,$acc1,$ord1 + sbcs $t2,$acc2,$ord2 + sbcs $t3,$acc3,$ord3 + sbcs xzr,$acc4,xzr + + csel $a0,$acc0,$t0,lo // ret = borrow ? ret : ret-modulus + csel $a1,$acc1,$t1,lo + csel $a2,$acc2,$t2,lo + csel $a3,$acc3,$t3,lo + + cbnz $bp,.Loop_ord_sqr + + stp $a0,$a1,[$rp] + stp $a2,$a3,[$rp,#16] + + ldp x19,x20,[sp,#16] + ldp x21,x22,[sp,#32] + ldp x23,x24,[sp,#48] + ldr x29,[sp],#64 + ret +.size ecp_nistz256_ord_sqr_mont,.-ecp_nistz256_ord_sqr_mont +___ +} } + +######################################################################## +# scatter-gather subroutines +{ +my ($out,$inp,$index,$mask)=map("x$_",(0..3)); +$code.=<<___; +// void ecp_nistz256_scatter_w5(void *x0,const P256_POINT *x1, +// int x2); +.globl ecp_nistz256_scatter_w5 +.type ecp_nistz256_scatter_w5,%function +.align 4 +ecp_nistz256_scatter_w5: + stp x29,x30,[sp,#-16]! + add x29,sp,#0 + + add $out,$out,$index,lsl#2 + + ldp x4,x5,[$inp] // X + ldp x6,x7,[$inp,#16] + str w4,[$out,#64*0-4] + lsr x4,x4,#32 + str w5,[$out,#64*1-4] + lsr x5,x5,#32 + str w6,[$out,#64*2-4] + lsr x6,x6,#32 + str w7,[$out,#64*3-4] + lsr x7,x7,#32 + str w4,[$out,#64*4-4] + str w5,[$out,#64*5-4] + str w6,[$out,#64*6-4] + str w7,[$out,#64*7-4] + add $out,$out,#64*8 + + ldp x4,x5,[$inp,#32] // Y + ldp x6,x7,[$inp,#48] + str w4,[$out,#64*0-4] + lsr x4,x4,#32 + str w5,[$out,#64*1-4] + lsr x5,x5,#32 + str w6,[$out,#64*2-4] + lsr x6,x6,#32 + str w7,[$out,#64*3-4] + lsr x7,x7,#32 + str w4,[$out,#64*4-4] + str w5,[$out,#64*5-4] + str w6,[$out,#64*6-4] + str w7,[$out,#64*7-4] + add $out,$out,#64*8 + + ldp x4,x5,[$inp,#64] // Z + ldp x6,x7,[$inp,#80] + str w4,[$out,#64*0-4] + lsr x4,x4,#32 + str w5,[$out,#64*1-4] + lsr x5,x5,#32 + str w6,[$out,#64*2-4] + lsr x6,x6,#32 + str w7,[$out,#64*3-4] + lsr x7,x7,#32 + str w4,[$out,#64*4-4] + str w5,[$out,#64*5-4] + str w6,[$out,#64*6-4] + str w7,[$out,#64*7-4] + + ldr x29,[sp],#16 + ret +.size ecp_nistz256_scatter_w5,.-ecp_nistz256_scatter_w5 + +// void ecp_nistz256_gather_w5(P256_POINT *x0,const void *x1, +// int x2); +.globl ecp_nistz256_gather_w5 +.type ecp_nistz256_gather_w5,%function +.align 4 +ecp_nistz256_gather_w5: + stp x29,x30,[sp,#-16]! + add x29,sp,#0 + + cmp $index,xzr + csetm x3,ne + add $index,$index,x3 + add $inp,$inp,$index,lsl#2 + + ldr w4,[$inp,#64*0] + ldr w5,[$inp,#64*1] + ldr w6,[$inp,#64*2] + ldr w7,[$inp,#64*3] + ldr w8,[$inp,#64*4] + ldr w9,[$inp,#64*5] + ldr w10,[$inp,#64*6] + ldr w11,[$inp,#64*7] + add $inp,$inp,#64*8 + orr x4,x4,x8,lsl#32 + orr x5,x5,x9,lsl#32 + orr x6,x6,x10,lsl#32 + orr x7,x7,x11,lsl#32 + csel x4,x4,xzr,ne + csel x5,x5,xzr,ne + csel x6,x6,xzr,ne + csel x7,x7,xzr,ne + stp x4,x5,[$out] // X + stp x6,x7,[$out,#16] + + ldr w4,[$inp,#64*0] + ldr w5,[$inp,#64*1] + ldr w6,[$inp,#64*2] + ldr w7,[$inp,#64*3] + ldr w8,[$inp,#64*4] + ldr w9,[$inp,#64*5] + ldr w10,[$inp,#64*6] + ldr w11,[$inp,#64*7] + add $inp,$inp,#64*8 + orr x4,x4,x8,lsl#32 + orr x5,x5,x9,lsl#32 + orr x6,x6,x10,lsl#32 + orr x7,x7,x11,lsl#32 + csel x4,x4,xzr,ne + csel x5,x5,xzr,ne + csel x6,x6,xzr,ne + csel x7,x7,xzr,ne + stp x4,x5,[$out,#32] // Y + stp x6,x7,[$out,#48] + + ldr w4,[$inp,#64*0] + ldr w5,[$inp,#64*1] + ldr w6,[$inp,#64*2] + ldr w7,[$inp,#64*3] + ldr w8,[$inp,#64*4] + ldr w9,[$inp,#64*5] + ldr w10,[$inp,#64*6] + ldr w11,[$inp,#64*7] + orr x4,x4,x8,lsl#32 + orr x5,x5,x9,lsl#32 + orr x6,x6,x10,lsl#32 + orr x7,x7,x11,lsl#32 + csel x4,x4,xzr,ne + csel x5,x5,xzr,ne + csel x6,x6,xzr,ne + csel x7,x7,xzr,ne + stp x4,x5,[$out,#64] // Z + stp x6,x7,[$out,#80] + + ldr x29,[sp],#16 + ret +.size ecp_nistz256_gather_w5,.-ecp_nistz256_gather_w5 + +// void ecp_nistz256_scatter_w7(void *x0,const P256_POINT_AFFINE *x1, +// int x2); +.globl ecp_nistz256_scatter_w7 +.type ecp_nistz256_scatter_w7,%function +.align 4 +ecp_nistz256_scatter_w7: + stp x29,x30,[sp,#-16]! + add x29,sp,#0 + + add $out,$out,$index + mov $index,#64/8 +.Loop_scatter_w7: + ldr x3,[$inp],#8 + subs $index,$index,#1 + prfm pstl1strm,[$out,#4096+64*0] + prfm pstl1strm,[$out,#4096+64*1] + prfm pstl1strm,[$out,#4096+64*2] + prfm pstl1strm,[$out,#4096+64*3] + prfm pstl1strm,[$out,#4096+64*4] + prfm pstl1strm,[$out,#4096+64*5] + prfm pstl1strm,[$out,#4096+64*6] + prfm pstl1strm,[$out,#4096+64*7] + strb w3,[$out,#64*0] + lsr x3,x3,#8 + strb w3,[$out,#64*1] + lsr x3,x3,#8 + strb w3,[$out,#64*2] + lsr x3,x3,#8 + strb w3,[$out,#64*3] + lsr x3,x3,#8 + strb w3,[$out,#64*4] + lsr x3,x3,#8 + strb w3,[$out,#64*5] + lsr x3,x3,#8 + strb w3,[$out,#64*6] + lsr x3,x3,#8 + strb w3,[$out,#64*7] + add $out,$out,#64*8 + b.ne .Loop_scatter_w7 + + ldr x29,[sp],#16 + ret +.size ecp_nistz256_scatter_w7,.-ecp_nistz256_scatter_w7 + +// void ecp_nistz256_gather_w7(P256_POINT_AFFINE *x0,const void *x1, +// int x2); +.globl ecp_nistz256_gather_w7 +.type ecp_nistz256_gather_w7,%function +.align 4 +ecp_nistz256_gather_w7: + stp x29,x30,[sp,#-16]! + add x29,sp,#0 + + cmp $index,xzr + csetm x3,ne + add $index,$index,x3 + add $inp,$inp,$index + mov $index,#64/8 + nop +.Loop_gather_w7: + ldrb w4,[$inp,#64*0] + prfm pldl1strm,[$inp,#4096+64*0] + subs $index,$index,#1 + ldrb w5,[$inp,#64*1] + prfm pldl1strm,[$inp,#4096+64*1] + ldrb w6,[$inp,#64*2] + prfm pldl1strm,[$inp,#4096+64*2] + ldrb w7,[$inp,#64*3] + prfm pldl1strm,[$inp,#4096+64*3] + ldrb w8,[$inp,#64*4] + prfm pldl1strm,[$inp,#4096+64*4] + ldrb w9,[$inp,#64*5] + prfm pldl1strm,[$inp,#4096+64*5] + ldrb w10,[$inp,#64*6] + prfm pldl1strm,[$inp,#4096+64*6] + ldrb w11,[$inp,#64*7] + prfm pldl1strm,[$inp,#4096+64*7] + add $inp,$inp,#64*8 + orr x4,x4,x5,lsl#8 + orr x6,x6,x7,lsl#8 + orr x8,x8,x9,lsl#8 + orr x4,x4,x6,lsl#16 + orr x10,x10,x11,lsl#8 + orr x4,x4,x8,lsl#32 + orr x4,x4,x10,lsl#48 + and x4,x4,x3 + str x4,[$out],#8 + b.ne .Loop_gather_w7 + + ldr x29,[sp],#16 + ret +.size ecp_nistz256_gather_w7,.-ecp_nistz256_gather_w7 +___ +} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/ge; + + print $_,"\n"; +} +close STDOUT; # enforce flush diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/ecp_nistz256-avx2.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/ecp_nistz256-avx2.pl new file mode 100755 index 000000000..794e56a08 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/ecp_nistz256-avx2.pl @@ -0,0 +1,2080 @@ +#! /usr/bin/env perl +# Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved. +# Copyright (c) 2014, Intel Corporation. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html +# +# Originally written by Shay Gueron (1, 2), and Vlad Krasnov (1) +# (1) Intel Corporation, Israel Development Center, Haifa, Israel +# (2) University of Haifa, Israel +# +# Reference: +# S.Gueron and V.Krasnov, "Fast Prime Field Elliptic Curve Cryptography with +# 256 Bit Primes" + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler version ([2-9]\.[0-9]+)/) { + $avx = ($1>=2.19) + ($1>=2.22); + $addx = ($1>=2.23); +} + +if (!$addx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) && + `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) { + $avx = ($1>=2.09) + ($1>=2.10); + $addx = ($1>=2.10); +} + +if (!$addx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && + `ml64 2>&1` =~ /Version ([0-9]+)\./) { + $avx = ($1>=10) + ($1>=11); + $addx = ($1>=12); +} + +if (!$addx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9])\.([0-9]+)/) { + my $ver = $2 + $3/100.0; # 3.1->3.01, 3.10->3.10 + $avx = ($ver>=3.0) + ($ver>=3.01); + $addx = ($ver>=3.03); +} + +if ($avx>=2) {{ +$digit_size = "\$29"; +$n_digits = "\$9"; + +$code.=<<___; +.text + +.align 64 +.LAVX2_AND_MASK: +.LAVX2_POLY: +.quad 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff +.quad 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff +.quad 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff +.quad 0x000001ff, 0x000001ff, 0x000001ff, 0x000001ff +.quad 0x00000000, 0x00000000, 0x00000000, 0x00000000 +.quad 0x00000000, 0x00000000, 0x00000000, 0x00000000 +.quad 0x00040000, 0x00040000, 0x00040000, 0x00040000 +.quad 0x1fe00000, 0x1fe00000, 0x1fe00000, 0x1fe00000 +.quad 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff + +.LAVX2_POLY_x2: +.quad 0x7FFFFFFC, 0x7FFFFFFC, 0x7FFFFFFC, 0x7FFFFFFC +.quad 0x7FFFFFFC, 0x7FFFFFFC, 0x7FFFFFFC, 0x7FFFFFFC +.quad 0x7FFFFFFC, 0x7FFFFFFC, 0x7FFFFFFC, 0x7FFFFFFC +.quad 0x400007FC, 0x400007FC, 0x400007FC, 0x400007FC +.quad 0x3FFFFFFE, 0x3FFFFFFE, 0x3FFFFFFE, 0x3FFFFFFE +.quad 0x3FFFFFFE, 0x3FFFFFFE, 0x3FFFFFFE, 0x3FFFFFFE +.quad 0x400FFFFE, 0x400FFFFE, 0x400FFFFE, 0x400FFFFE +.quad 0x7F7FFFFE, 0x7F7FFFFE, 0x7F7FFFFE, 0x7F7FFFFE +.quad 0x03FFFFFC, 0x03FFFFFC, 0x03FFFFFC, 0x03FFFFFC + +.LAVX2_POLY_x8: +.quad 0xFFFFFFF8, 0xFFFFFFF8, 0xFFFFFFF8, 0xFFFFFFF8 +.quad 0xFFFFFFF8, 0xFFFFFFF8, 0xFFFFFFF8, 0xFFFFFFF8 +.quad 0xFFFFFFF8, 0xFFFFFFF8, 0xFFFFFFF8, 0xFFFFFFF8 +.quad 0x80000FF8, 0x80000FF8, 0x80000FF8, 0x80000FF8 +.quad 0x7FFFFFFC, 0x7FFFFFFC, 0x7FFFFFFC, 0x7FFFFFFC +.quad 0x7FFFFFFC, 0x7FFFFFFC, 0x7FFFFFFC, 0x7FFFFFFC +.quad 0x801FFFFC, 0x801FFFFC, 0x801FFFFC, 0x801FFFFC +.quad 0xFEFFFFFC, 0xFEFFFFFC, 0xFEFFFFFC, 0xFEFFFFFC +.quad 0x07FFFFF8, 0x07FFFFF8, 0x07FFFFF8, 0x07FFFFF8 + +.LONE: +.quad 0x00000020, 0x00000020, 0x00000020, 0x00000020 +.quad 0x00000000, 0x00000000, 0x00000000, 0x00000000 +.quad 0x00000000, 0x00000000, 0x00000000, 0x00000000 +.quad 0x1fffc000, 0x1fffc000, 0x1fffc000, 0x1fffc000 +.quad 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff +.quad 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff +.quad 0x1f7fffff, 0x1f7fffff, 0x1f7fffff, 0x1f7fffff +.quad 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff +.quad 0x00000000, 0x00000000, 0x00000000, 0x00000000 + +# RR = 2^266 mod p in AVX2 format, to transform from the native OpenSSL +# Montgomery form (*2^256) to our format (*2^261) + +.LTO_MONT_AVX2: +.quad 0x00000400, 0x00000400, 0x00000400, 0x00000400 +.quad 0x00000000, 0x00000000, 0x00000000, 0x00000000 +.quad 0x00000000, 0x00000000, 0x00000000, 0x00000000 +.quad 0x1ff80000, 0x1ff80000, 0x1ff80000, 0x1ff80000 +.quad 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff +.quad 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff +.quad 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff +.quad 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff +.quad 0x00000003, 0x00000003, 0x00000003, 0x00000003 + +.LFROM_MONT_AVX2: +.quad 0x00000001, 0x00000001, 0x00000001, 0x00000001 +.quad 0x00000000, 0x00000000, 0x00000000, 0x00000000 +.quad 0x00000000, 0x00000000, 0x00000000, 0x00000000 +.quad 0x1ffffe00, 0x1ffffe00, 0x1ffffe00, 0x1ffffe00 +.quad 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff +.quad 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff +.quad 0x1ffbffff, 0x1ffbffff, 0x1ffbffff, 0x1ffbffff +.quad 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff +.quad 0x00000000, 0x00000000, 0x00000000, 0x00000000 + +.LIntOne: +.long 1,1,1,1,1,1,1,1 +___ + +{ +# This function receives a pointer to an array of four affine points +# (X, Y, <1>) and rearranges the data for AVX2 execution, while +# converting it to 2^29 radix redundant form + +my ($X0,$X1,$X2,$X3, $Y0,$Y1,$Y2,$Y3, + $T0,$T1,$T2,$T3, $T4,$T5,$T6,$T7)=map("%ymm$_",(0..15)); + +$code.=<<___; +.globl ecp_nistz256_avx2_transpose_convert +.type ecp_nistz256_avx2_transpose_convert,\@function,2 +.align 64 +ecp_nistz256_avx2_transpose_convert: + vzeroupper +___ +$code.=<<___ if ($win64); + lea -8-16*10(%rsp), %rsp + vmovaps %xmm6, -8-16*10(%rax) + vmovaps %xmm7, -8-16*9(%rax) + vmovaps %xmm8, -8-16*8(%rax) + vmovaps %xmm9, -8-16*7(%rax) + vmovaps %xmm10, -8-16*6(%rax) + vmovaps %xmm11, -8-16*5(%rax) + vmovaps %xmm12, -8-16*4(%rax) + vmovaps %xmm13, -8-16*3(%rax) + vmovaps %xmm14, -8-16*2(%rax) + vmovaps %xmm15, -8-16*1(%rax) +___ +$code.=<<___; + # Load the data + vmovdqa 32*0(%rsi), $X0 + lea 112(%rsi), %rax # size optimization + vmovdqa 32*1(%rsi), $Y0 + lea .LAVX2_AND_MASK(%rip), %rdx + vmovdqa 32*2(%rsi), $X1 + vmovdqa 32*3(%rsi), $Y1 + vmovdqa 32*4-112(%rax), $X2 + vmovdqa 32*5-112(%rax), $Y2 + vmovdqa 32*6-112(%rax), $X3 + vmovdqa 32*7-112(%rax), $Y3 + + # Transpose X and Y independently + vpunpcklqdq $X1, $X0, $T0 # T0 = [B2 A2 B0 A0] + vpunpcklqdq $X3, $X2, $T1 # T1 = [D2 C2 D0 C0] + vpunpckhqdq $X1, $X0, $T2 # T2 = [B3 A3 B1 A1] + vpunpckhqdq $X3, $X2, $T3 # T3 = [D3 C3 D1 C1] + + vpunpcklqdq $Y1, $Y0, $T4 + vpunpcklqdq $Y3, $Y2, $T5 + vpunpckhqdq $Y1, $Y0, $T6 + vpunpckhqdq $Y3, $Y2, $T7 + + vperm2i128 \$0x20, $T1, $T0, $X0 # X0 = [D0 C0 B0 A0] + vperm2i128 \$0x20, $T3, $T2, $X1 # X1 = [D1 C1 B1 A1] + vperm2i128 \$0x31, $T1, $T0, $X2 # X2 = [D2 C2 B2 A2] + vperm2i128 \$0x31, $T3, $T2, $X3 # X3 = [D3 C3 B3 A3] + + vperm2i128 \$0x20, $T5, $T4, $Y0 + vperm2i128 \$0x20, $T7, $T6, $Y1 + vperm2i128 \$0x31, $T5, $T4, $Y2 + vperm2i128 \$0x31, $T7, $T6, $Y3 + vmovdqa (%rdx), $T7 + + vpand (%rdx), $X0, $T0 # out[0] = in[0] & mask; + vpsrlq \$29, $X0, $X0 + vpand $T7, $X0, $T1 # out[1] = (in[0] >> shift) & mask; + vpsrlq \$29, $X0, $X0 + vpsllq \$6, $X1, $T2 + vpxor $X0, $T2, $T2 + vpand $T7, $T2, $T2 # out[2] = ((in[0] >> (shift*2)) ^ (in[1] << (64-shift*2))) & mask; + vpsrlq \$23, $X1, $X1 + vpand $T7, $X1, $T3 # out[3] = (in[1] >> ((shift*3)%64)) & mask; + vpsrlq \$29, $X1, $X1 + vpsllq \$12, $X2, $T4 + vpxor $X1, $T4, $T4 + vpand $T7, $T4, $T4 # out[4] = ((in[1] >> ((shift*4)%64)) ^ (in[2] << (64*2-shift*4))) & mask; + vpsrlq \$17, $X2, $X2 + vpand $T7, $X2, $T5 # out[5] = (in[2] >> ((shift*5)%64)) & mask; + vpsrlq \$29, $X2, $X2 + vpsllq \$18, $X3, $T6 + vpxor $X2, $T6, $T6 + vpand $T7, $T6, $T6 # out[6] = ((in[2] >> ((shift*6)%64)) ^ (in[3] << (64*3-shift*6))) & mask; + vpsrlq \$11, $X3, $X3 + vmovdqa $T0, 32*0(%rdi) + lea 112(%rdi), %rax # size optimization + vpand $T7, $X3, $T0 # out[7] = (in[3] >> ((shift*7)%64)) & mask; + vpsrlq \$29, $X3, $X3 # out[8] = (in[3] >> ((shift*8)%64)) & mask; + + vmovdqa $T1, 32*1(%rdi) + vmovdqa $T2, 32*2(%rdi) + vmovdqa $T3, 32*3(%rdi) + vmovdqa $T4, 32*4-112(%rax) + vmovdqa $T5, 32*5-112(%rax) + vmovdqa $T6, 32*6-112(%rax) + vmovdqa $T0, 32*7-112(%rax) + vmovdqa $X3, 32*8-112(%rax) + lea 448(%rdi), %rax # size optimization + + vpand $T7, $Y0, $T0 # out[0] = in[0] & mask; + vpsrlq \$29, $Y0, $Y0 + vpand $T7, $Y0, $T1 # out[1] = (in[0] >> shift) & mask; + vpsrlq \$29, $Y0, $Y0 + vpsllq \$6, $Y1, $T2 + vpxor $Y0, $T2, $T2 + vpand $T7, $T2, $T2 # out[2] = ((in[0] >> (shift*2)) ^ (in[1] << (64-shift*2))) & mask; + vpsrlq \$23, $Y1, $Y1 + vpand $T7, $Y1, $T3 # out[3] = (in[1] >> ((shift*3)%64)) & mask; + vpsrlq \$29, $Y1, $Y1 + vpsllq \$12, $Y2, $T4 + vpxor $Y1, $T4, $T4 + vpand $T7, $T4, $T4 # out[4] = ((in[1] >> ((shift*4)%64)) ^ (in[2] << (64*2-shift*4))) & mask; + vpsrlq \$17, $Y2, $Y2 + vpand $T7, $Y2, $T5 # out[5] = (in[2] >> ((shift*5)%64)) & mask; + vpsrlq \$29, $Y2, $Y2 + vpsllq \$18, $Y3, $T6 + vpxor $Y2, $T6, $T6 + vpand $T7, $T6, $T6 # out[6] = ((in[2] >> ((shift*6)%64)) ^ (in[3] << (64*3-shift*6))) & mask; + vpsrlq \$11, $Y3, $Y3 + vmovdqa $T0, 32*9-448(%rax) + vpand $T7, $Y3, $T0 # out[7] = (in[3] >> ((shift*7)%64)) & mask; + vpsrlq \$29, $Y3, $Y3 # out[8] = (in[3] >> ((shift*8)%64)) & mask; + + vmovdqa $T1, 32*10-448(%rax) + vmovdqa $T2, 32*11-448(%rax) + vmovdqa $T3, 32*12-448(%rax) + vmovdqa $T4, 32*13-448(%rax) + vmovdqa $T5, 32*14-448(%rax) + vmovdqa $T6, 32*15-448(%rax) + vmovdqa $T0, 32*16-448(%rax) + vmovdqa $Y3, 32*17-448(%rax) + + vzeroupper +___ +$code.=<<___ if ($win64); + movaps 16*0(%rsp), %xmm6 + movaps 16*1(%rsp), %xmm7 + movaps 16*2(%rsp), %xmm8 + movaps 16*3(%rsp), %xmm9 + movaps 16*4(%rsp), %xmm10 + movaps 16*5(%rsp), %xmm11 + movaps 16*6(%rsp), %xmm12 + movaps 16*7(%rsp), %xmm13 + movaps 16*8(%rsp), %xmm14 + movaps 16*9(%rsp), %xmm15 + lea 8+16*10(%rsp), %rsp +___ +$code.=<<___; + ret +.size ecp_nistz256_avx2_transpose_convert,.-ecp_nistz256_avx2_transpose_convert +___ +} +{ +################################################################################ +# This function receives a pointer to an array of four AVX2 formatted points +# (X, Y, Z) convert the data to normal representation, and rearranges the data + +my ($D0,$D1,$D2,$D3, $D4,$D5,$D6,$D7, $D8)=map("%ymm$_",(0..8)); +my ($T0,$T1,$T2,$T3, $T4,$T5,$T6)=map("%ymm$_",(9..15)); + +$code.=<<___; + +.globl ecp_nistz256_avx2_convert_transpose_back +.type ecp_nistz256_avx2_convert_transpose_back,\@function,2 +.align 32 +ecp_nistz256_avx2_convert_transpose_back: + vzeroupper +___ +$code.=<<___ if ($win64); + lea -8-16*10(%rsp), %rsp + vmovaps %xmm6, -8-16*10(%rax) + vmovaps %xmm7, -8-16*9(%rax) + vmovaps %xmm8, -8-16*8(%rax) + vmovaps %xmm9, -8-16*7(%rax) + vmovaps %xmm10, -8-16*6(%rax) + vmovaps %xmm11, -8-16*5(%rax) + vmovaps %xmm12, -8-16*4(%rax) + vmovaps %xmm13, -8-16*3(%rax) + vmovaps %xmm14, -8-16*2(%rax) + vmovaps %xmm15, -8-16*1(%rax) +___ +$code.=<<___; + mov \$3, %ecx + +.Lconv_loop: + vmovdqa 32*0(%rsi), $D0 + lea 160(%rsi), %rax # size optimization + vmovdqa 32*1(%rsi), $D1 + vmovdqa 32*2(%rsi), $D2 + vmovdqa 32*3(%rsi), $D3 + vmovdqa 32*4-160(%rax), $D4 + vmovdqa 32*5-160(%rax), $D5 + vmovdqa 32*6-160(%rax), $D6 + vmovdqa 32*7-160(%rax), $D7 + vmovdqa 32*8-160(%rax), $D8 + + vpsllq \$29, $D1, $D1 + vpsllq \$58, $D2, $T0 + vpaddq $D1, $D0, $D0 + vpaddq $T0, $D0, $D0 # out[0] = (in[0]) ^ (in[1] << shift*1) ^ (in[2] << shift*2); + + vpsrlq \$6, $D2, $D2 + vpsllq \$23, $D3, $D3 + vpsllq \$52, $D4, $T1 + vpaddq $D2, $D3, $D3 + vpaddq $D3, $T1, $D1 # out[1] = (in[2] >> (64*1-shift*2)) ^ (in[3] << shift*3%64) ^ (in[4] << shift*4%64); + + vpsrlq \$12, $D4, $D4 + vpsllq \$17, $D5, $D5 + vpsllq \$46, $D6, $T2 + vpaddq $D4, $D5, $D5 + vpaddq $D5, $T2, $D2 # out[2] = (in[4] >> (64*2-shift*4)) ^ (in[5] << shift*5%64) ^ (in[6] << shift*6%64); + + vpsrlq \$18, $D6, $D6 + vpsllq \$11, $D7, $D7 + vpsllq \$40, $D8, $T3 + vpaddq $D6, $D7, $D7 + vpaddq $D7, $T3, $D3 # out[3] = (in[6] >> (64*3-shift*6)) ^ (in[7] << shift*7%64) ^ (in[8] << shift*8%64); + + vpunpcklqdq $D1, $D0, $T0 # T0 = [B2 A2 B0 A0] + vpunpcklqdq $D3, $D2, $T1 # T1 = [D2 C2 D0 C0] + vpunpckhqdq $D1, $D0, $T2 # T2 = [B3 A3 B1 A1] + vpunpckhqdq $D3, $D2, $T3 # T3 = [D3 C3 D1 C1] + + vperm2i128 \$0x20, $T1, $T0, $D0 # X0 = [D0 C0 B0 A0] + vperm2i128 \$0x20, $T3, $T2, $D1 # X1 = [D1 C1 B1 A1] + vperm2i128 \$0x31, $T1, $T0, $D2 # X2 = [D2 C2 B2 A2] + vperm2i128 \$0x31, $T3, $T2, $D3 # X3 = [D3 C3 B3 A3] + + vmovdqa $D0, 32*0(%rdi) + vmovdqa $D1, 32*3(%rdi) + vmovdqa $D2, 32*6(%rdi) + vmovdqa $D3, 32*9(%rdi) + + lea 32*9(%rsi), %rsi + lea 32*1(%rdi), %rdi + + dec %ecx + jnz .Lconv_loop + + vzeroupper +___ +$code.=<<___ if ($win64); + movaps 16*0(%rsp), %xmm6 + movaps 16*1(%rsp), %xmm7 + movaps 16*2(%rsp), %xmm8 + movaps 16*3(%rsp), %xmm9 + movaps 16*4(%rsp), %xmm10 + movaps 16*5(%rsp), %xmm11 + movaps 16*6(%rsp), %xmm12 + movaps 16*7(%rsp), %xmm13 + movaps 16*8(%rsp), %xmm14 + movaps 16*9(%rsp), %xmm15 + lea 8+16*10(%rsp), %rsp +___ +$code.=<<___; + ret +.size ecp_nistz256_avx2_convert_transpose_back,.-ecp_nistz256_avx2_convert_transpose_back +___ +} +{ +my ($r_ptr,$a_ptr,$b_ptr,$itr)=("%rdi","%rsi","%rdx","%ecx"); +my ($ACC0,$ACC1,$ACC2,$ACC3,$ACC4,$ACC5,$ACC6,$ACC7,$ACC8)=map("%ymm$_",(0..8)); +my ($B,$Y,$T0,$AND_MASK,$OVERFLOW)=map("%ymm$_",(9..13)); + +sub NORMALIZE { +my $ret=<<___; + vpsrlq $digit_size, $ACC0, $T0 + vpand $AND_MASK, $ACC0, $ACC0 + vpaddq $T0, $ACC1, $ACC1 + + vpsrlq $digit_size, $ACC1, $T0 + vpand $AND_MASK, $ACC1, $ACC1 + vpaddq $T0, $ACC2, $ACC2 + + vpsrlq $digit_size, $ACC2, $T0 + vpand $AND_MASK, $ACC2, $ACC2 + vpaddq $T0, $ACC3, $ACC3 + + vpsrlq $digit_size, $ACC3, $T0 + vpand $AND_MASK, $ACC3, $ACC3 + vpaddq $T0, $ACC4, $ACC4 + + vpsrlq $digit_size, $ACC4, $T0 + vpand $AND_MASK, $ACC4, $ACC4 + vpaddq $T0, $ACC5, $ACC5 + + vpsrlq $digit_size, $ACC5, $T0 + vpand $AND_MASK, $ACC5, $ACC5 + vpaddq $T0, $ACC6, $ACC6 + + vpsrlq $digit_size, $ACC6, $T0 + vpand $AND_MASK, $ACC6, $ACC6 + vpaddq $T0, $ACC7, $ACC7 + + vpsrlq $digit_size, $ACC7, $T0 + vpand $AND_MASK, $ACC7, $ACC7 + vpaddq $T0, $ACC8, $ACC8 + #vpand $AND_MASK, $ACC8, $ACC8 +___ + $ret; +} + +sub STORE { +my $ret=<<___; + vmovdqa $ACC0, 32*0(%rdi) + lea 160(%rdi), %rax # size optimization + vmovdqa $ACC1, 32*1(%rdi) + vmovdqa $ACC2, 32*2(%rdi) + vmovdqa $ACC3, 32*3(%rdi) + vmovdqa $ACC4, 32*4-160(%rax) + vmovdqa $ACC5, 32*5-160(%rax) + vmovdqa $ACC6, 32*6-160(%rax) + vmovdqa $ACC7, 32*7-160(%rax) + vmovdqa $ACC8, 32*8-160(%rax) +___ + $ret; +} + +$code.=<<___; +.type avx2_normalize,\@abi-omnipotent +.align 32 +avx2_normalize: + vpsrlq $digit_size, $ACC0, $T0 + vpand $AND_MASK, $ACC0, $ACC0 + vpaddq $T0, $ACC1, $ACC1 + + vpsrlq $digit_size, $ACC1, $T0 + vpand $AND_MASK, $ACC1, $ACC1 + vpaddq $T0, $ACC2, $ACC2 + + vpsrlq $digit_size, $ACC2, $T0 + vpand $AND_MASK, $ACC2, $ACC2 + vpaddq $T0, $ACC3, $ACC3 + + vpsrlq $digit_size, $ACC3, $T0 + vpand $AND_MASK, $ACC3, $ACC3 + vpaddq $T0, $ACC4, $ACC4 + + vpsrlq $digit_size, $ACC4, $T0 + vpand $AND_MASK, $ACC4, $ACC4 + vpaddq $T0, $ACC5, $ACC5 + + vpsrlq $digit_size, $ACC5, $T0 + vpand $AND_MASK, $ACC5, $ACC5 + vpaddq $T0, $ACC6, $ACC6 + + vpsrlq $digit_size, $ACC6, $T0 + vpand $AND_MASK, $ACC6, $ACC6 + vpaddq $T0, $ACC7, $ACC7 + + vpsrlq $digit_size, $ACC7, $T0 + vpand $AND_MASK, $ACC7, $ACC7 + vpaddq $T0, $ACC8, $ACC8 + #vpand $AND_MASK, $ACC8, $ACC8 + + ret +.size avx2_normalize,.-avx2_normalize + +.type avx2_normalize_n_store,\@abi-omnipotent +.align 32 +avx2_normalize_n_store: + vpsrlq $digit_size, $ACC0, $T0 + vpand $AND_MASK, $ACC0, $ACC0 + vpaddq $T0, $ACC1, $ACC1 + + vpsrlq $digit_size, $ACC1, $T0 + vpand $AND_MASK, $ACC1, $ACC1 + vmovdqa $ACC0, 32*0(%rdi) + lea 160(%rdi), %rax # size optimization + vpaddq $T0, $ACC2, $ACC2 + + vpsrlq $digit_size, $ACC2, $T0 + vpand $AND_MASK, $ACC2, $ACC2 + vmovdqa $ACC1, 32*1(%rdi) + vpaddq $T0, $ACC3, $ACC3 + + vpsrlq $digit_size, $ACC3, $T0 + vpand $AND_MASK, $ACC3, $ACC3 + vmovdqa $ACC2, 32*2(%rdi) + vpaddq $T0, $ACC4, $ACC4 + + vpsrlq $digit_size, $ACC4, $T0 + vpand $AND_MASK, $ACC4, $ACC4 + vmovdqa $ACC3, 32*3(%rdi) + vpaddq $T0, $ACC5, $ACC5 + + vpsrlq $digit_size, $ACC5, $T0 + vpand $AND_MASK, $ACC5, $ACC5 + vmovdqa $ACC4, 32*4-160(%rax) + vpaddq $T0, $ACC6, $ACC6 + + vpsrlq $digit_size, $ACC6, $T0 + vpand $AND_MASK, $ACC6, $ACC6 + vmovdqa $ACC5, 32*5-160(%rax) + vpaddq $T0, $ACC7, $ACC7 + + vpsrlq $digit_size, $ACC7, $T0 + vpand $AND_MASK, $ACC7, $ACC7 + vmovdqa $ACC6, 32*6-160(%rax) + vpaddq $T0, $ACC8, $ACC8 + #vpand $AND_MASK, $ACC8, $ACC8 + vmovdqa $ACC7, 32*7-160(%rax) + vmovdqa $ACC8, 32*8-160(%rax) + + ret +.size avx2_normalize_n_store,.-avx2_normalize_n_store + +################################################################################ +# void avx2_mul_x4(void* RESULTx4, void *Ax4, void *Bx4); +.type avx2_mul_x4,\@abi-omnipotent +.align 32 +avx2_mul_x4: + lea .LAVX2_POLY(%rip), %rax + + vpxor $ACC0, $ACC0, $ACC0 + vpxor $ACC1, $ACC1, $ACC1 + vpxor $ACC2, $ACC2, $ACC2 + vpxor $ACC3, $ACC3, $ACC3 + vpxor $ACC4, $ACC4, $ACC4 + vpxor $ACC5, $ACC5, $ACC5 + vpxor $ACC6, $ACC6, $ACC6 + vpxor $ACC7, $ACC7, $ACC7 + + vmovdqa 32*7(%rax), %ymm14 + vmovdqa 32*8(%rax), %ymm15 + + mov $n_digits, $itr + lea -512($a_ptr), $a_ptr # strategic bias to control u-op density + jmp .Lavx2_mul_x4_loop + +.align 32 +.Lavx2_mul_x4_loop: + vmovdqa 32*0($b_ptr), $B + lea 32*1($b_ptr), $b_ptr + + vpmuludq 32*0+512($a_ptr), $B, $T0 + vpmuludq 32*1+512($a_ptr), $B, $OVERFLOW # borrow $OVERFLOW + vpaddq $T0, $ACC0, $ACC0 + vpmuludq 32*2+512($a_ptr), $B, $T0 + vpaddq $OVERFLOW, $ACC1, $ACC1 + vpand $AND_MASK, $ACC0, $Y + vpmuludq 32*3+512($a_ptr), $B, $OVERFLOW + vpaddq $T0, $ACC2, $ACC2 + vpmuludq 32*4+512($a_ptr), $B, $T0 + vpaddq $OVERFLOW, $ACC3, $ACC3 + vpmuludq 32*5+512($a_ptr), $B, $OVERFLOW + vpaddq $T0, $ACC4, $ACC4 + vpmuludq 32*6+512($a_ptr), $B, $T0 + vpaddq $OVERFLOW, $ACC5, $ACC5 + vpmuludq 32*7+512($a_ptr), $B, $OVERFLOW + vpaddq $T0, $ACC6, $ACC6 + + # Skip some multiplications, optimizing for the constant poly + vpmuludq $AND_MASK, $Y, $T0 + vpaddq $OVERFLOW, $ACC7, $ACC7 + vpmuludq 32*8+512($a_ptr), $B, $ACC8 + vpaddq $T0, $ACC0, $OVERFLOW + vpaddq $T0, $ACC1, $ACC0 + vpsrlq $digit_size, $OVERFLOW, $OVERFLOW + vpaddq $T0, $ACC2, $ACC1 + vpmuludq 32*3(%rax), $Y, $T0 + vpaddq $OVERFLOW, $ACC0, $ACC0 + vpaddq $T0, $ACC3, $ACC2 + .byte 0x67 + vmovdqa $ACC4, $ACC3 + vpsllq \$18, $Y, $OVERFLOW + .byte 0x67 + vmovdqa $ACC5, $ACC4 + vpmuludq %ymm14, $Y, $T0 + vpaddq $OVERFLOW, $ACC6, $ACC5 + vpmuludq %ymm15, $Y, $OVERFLOW + vpaddq $T0, $ACC7, $ACC6 + vpaddq $OVERFLOW, $ACC8, $ACC7 + + dec $itr + jnz .Lavx2_mul_x4_loop + + vpxor $ACC8, $ACC8, $ACC8 + + ret +.size avx2_mul_x4,.-avx2_mul_x4 + +# Function optimized for the constant 1 +################################################################################ +# void avx2_mul_by1_x4(void* RESULTx4, void *Ax4); +.type avx2_mul_by1_x4,\@abi-omnipotent +.align 32 +avx2_mul_by1_x4: + lea .LAVX2_POLY(%rip), %rax + + vpxor $ACC0, $ACC0, $ACC0 + vpxor $ACC1, $ACC1, $ACC1 + vpxor $ACC2, $ACC2, $ACC2 + vpxor $ACC3, $ACC3, $ACC3 + vpxor $ACC4, $ACC4, $ACC4 + vpxor $ACC5, $ACC5, $ACC5 + vpxor $ACC6, $ACC6, $ACC6 + vpxor $ACC7, $ACC7, $ACC7 + vpxor $ACC8, $ACC8, $ACC8 + + vmovdqa 32*3+.LONE(%rip), %ymm14 + vmovdqa 32*7+.LONE(%rip), %ymm15 + + mov $n_digits, $itr + jmp .Lavx2_mul_by1_x4_loop + +.align 32 +.Lavx2_mul_by1_x4_loop: + vmovdqa 32*0($a_ptr), $B + .byte 0x48,0x8d,0xb6,0x20,0,0,0 # lea 32*1($a_ptr), $a_ptr + + vpsllq \$5, $B, $OVERFLOW + vpmuludq %ymm14, $B, $T0 + vpaddq $OVERFLOW, $ACC0, $ACC0 + vpaddq $T0, $ACC3, $ACC3 + .byte 0x67 + vpmuludq $AND_MASK, $B, $T0 + vpand $AND_MASK, $ACC0, $Y + vpaddq $T0, $ACC4, $ACC4 + vpaddq $T0, $ACC5, $ACC5 + vpaddq $T0, $ACC6, $ACC6 + vpsllq \$23, $B, $T0 + + .byte 0x67,0x67 + vpmuludq %ymm15, $B, $OVERFLOW + vpsubq $T0, $ACC6, $ACC6 + + vpmuludq $AND_MASK, $Y, $T0 + vpaddq $OVERFLOW, $ACC7, $ACC7 + vpaddq $T0, $ACC0, $OVERFLOW + vpaddq $T0, $ACC1, $ACC0 + .byte 0x67,0x67 + vpsrlq $digit_size, $OVERFLOW, $OVERFLOW + vpaddq $T0, $ACC2, $ACC1 + vpmuludq 32*3(%rax), $Y, $T0 + vpaddq $OVERFLOW, $ACC0, $ACC0 + vpaddq $T0, $ACC3, $ACC2 + vmovdqa $ACC4, $ACC3 + vpsllq \$18, $Y, $OVERFLOW + vmovdqa $ACC5, $ACC4 + vpmuludq 32*7(%rax), $Y, $T0 + vpaddq $OVERFLOW, $ACC6, $ACC5 + vpaddq $T0, $ACC7, $ACC6 + vpmuludq 32*8(%rax), $Y, $ACC7 + + dec $itr + jnz .Lavx2_mul_by1_x4_loop + + ret +.size avx2_mul_by1_x4,.-avx2_mul_by1_x4 + +################################################################################ +# void avx2_sqr_x4(void* RESULTx4, void *Ax4, void *Bx4); +.type avx2_sqr_x4,\@abi-omnipotent +.align 32 +avx2_sqr_x4: + lea .LAVX2_POLY(%rip), %rax + + vmovdqa 32*7(%rax), %ymm14 + vmovdqa 32*8(%rax), %ymm15 + + vmovdqa 32*0($a_ptr), $B + vmovdqa 32*1($a_ptr), $ACC1 + vmovdqa 32*2($a_ptr), $ACC2 + vmovdqa 32*3($a_ptr), $ACC3 + vmovdqa 32*4($a_ptr), $ACC4 + vmovdqa 32*5($a_ptr), $ACC5 + vmovdqa 32*6($a_ptr), $ACC6 + vmovdqa 32*7($a_ptr), $ACC7 + vpaddq $ACC1, $ACC1, $ACC1 # 2*$ACC0..7 + vmovdqa 32*8($a_ptr), $ACC8 + vpaddq $ACC2, $ACC2, $ACC2 + vmovdqa $ACC1, 32*0(%rcx) + vpaddq $ACC3, $ACC3, $ACC3 + vmovdqa $ACC2, 32*1(%rcx) + vpaddq $ACC4, $ACC4, $ACC4 + vmovdqa $ACC3, 32*2(%rcx) + vpaddq $ACC5, $ACC5, $ACC5 + vmovdqa $ACC4, 32*3(%rcx) + vpaddq $ACC6, $ACC6, $ACC6 + vmovdqa $ACC5, 32*4(%rcx) + vpaddq $ACC7, $ACC7, $ACC7 + vmovdqa $ACC6, 32*5(%rcx) + vpaddq $ACC8, $ACC8, $ACC8 + vmovdqa $ACC7, 32*6(%rcx) + vmovdqa $ACC8, 32*7(%rcx) + + #itr 1 + vpmuludq $B, $B, $ACC0 + vpmuludq $B, $ACC1, $ACC1 + vpand $AND_MASK, $ACC0, $Y + vpmuludq $B, $ACC2, $ACC2 + vpmuludq $B, $ACC3, $ACC3 + vpmuludq $B, $ACC4, $ACC4 + vpmuludq $B, $ACC5, $ACC5 + vpmuludq $B, $ACC6, $ACC6 + vpmuludq $AND_MASK, $Y, $T0 + vpmuludq $B, $ACC7, $ACC7 + vpmuludq $B, $ACC8, $ACC8 + vmovdqa 32*1($a_ptr), $B + + vpaddq $T0, $ACC0, $OVERFLOW + vpaddq $T0, $ACC1, $ACC0 + vpsrlq $digit_size, $OVERFLOW, $OVERFLOW + vpaddq $T0, $ACC2, $ACC1 + vpmuludq 32*3(%rax), $Y, $T0 + vpaddq $OVERFLOW, $ACC0, $ACC0 + vpaddq $T0, $ACC3, $ACC2 + vmovdqa $ACC4, $ACC3 + vpsllq \$18, $Y, $T0 + vmovdqa $ACC5, $ACC4 + vpmuludq %ymm14, $Y, $OVERFLOW + vpaddq $T0, $ACC6, $ACC5 + vpmuludq %ymm15, $Y, $T0 + vpaddq $OVERFLOW, $ACC7, $ACC6 + vpaddq $T0, $ACC8, $ACC7 + + #itr 2 + vpmuludq $B, $B, $OVERFLOW + vpand $AND_MASK, $ACC0, $Y + vpmuludq 32*1(%rcx), $B, $T0 + vpaddq $OVERFLOW, $ACC1, $ACC1 + vpmuludq 32*2(%rcx), $B, $OVERFLOW + vpaddq $T0, $ACC2, $ACC2 + vpmuludq 32*3(%rcx), $B, $T0 + vpaddq $OVERFLOW, $ACC3, $ACC3 + vpmuludq 32*4(%rcx), $B, $OVERFLOW + vpaddq $T0, $ACC4, $ACC4 + vpmuludq 32*5(%rcx), $B, $T0 + vpaddq $OVERFLOW, $ACC5, $ACC5 + vpmuludq 32*6(%rcx), $B, $OVERFLOW + vpaddq $T0, $ACC6, $ACC6 + + vpmuludq $AND_MASK, $Y, $T0 + vpaddq $OVERFLOW, $ACC7, $ACC7 + vpmuludq 32*7(%rcx), $B, $ACC8 + vmovdqa 32*2($a_ptr), $B + vpaddq $T0, $ACC0, $OVERFLOW + vpaddq $T0, $ACC1, $ACC0 + vpsrlq $digit_size, $OVERFLOW, $OVERFLOW + vpaddq $T0, $ACC2, $ACC1 + vpmuludq 32*3(%rax), $Y, $T0 + vpaddq $OVERFLOW, $ACC0, $ACC0 + vpaddq $T0, $ACC3, $ACC2 + vmovdqa $ACC4, $ACC3 + vpsllq \$18, $Y, $T0 + vmovdqa $ACC5, $ACC4 + vpmuludq %ymm14, $Y, $OVERFLOW + vpaddq $T0, $ACC6, $ACC5 + vpmuludq %ymm15, $Y, $T0 + vpaddq $OVERFLOW, $ACC7, $ACC6 + vpaddq $T0, $ACC8, $ACC7 + + #itr 3 + vpmuludq $B, $B, $T0 + vpand $AND_MASK, $ACC0, $Y + vpmuludq 32*2(%rcx), $B, $OVERFLOW + vpaddq $T0, $ACC2, $ACC2 + vpmuludq 32*3(%rcx), $B, $T0 + vpaddq $OVERFLOW, $ACC3, $ACC3 + vpmuludq 32*4(%rcx), $B, $OVERFLOW + vpaddq $T0, $ACC4, $ACC4 + vpmuludq 32*5(%rcx), $B, $T0 + vpaddq $OVERFLOW, $ACC5, $ACC5 + vpmuludq 32*6(%rcx), $B, $OVERFLOW + vpaddq $T0, $ACC6, $ACC6 + + vpmuludq $AND_MASK, $Y, $T0 + vpaddq $OVERFLOW, $ACC7, $ACC7 + vpmuludq 32*7(%rcx), $B, $ACC8 + vmovdqa 32*3($a_ptr), $B + vpaddq $T0, $ACC0, $OVERFLOW + vpaddq $T0, $ACC1, $ACC0 + vpsrlq $digit_size, $OVERFLOW, $OVERFLOW + vpaddq $T0, $ACC2, $ACC1 + vpmuludq 32*3(%rax), $Y, $T0 + vpaddq $OVERFLOW, $ACC0, $ACC0 + vpaddq $T0, $ACC3, $ACC2 + vmovdqa $ACC4, $ACC3 + vpsllq \$18, $Y, $T0 + vmovdqa $ACC5, $ACC4 + vpmuludq %ymm14, $Y, $OVERFLOW + vpaddq $T0, $ACC6, $ACC5 + vpmuludq %ymm15, $Y, $T0 + vpand $AND_MASK, $ACC0, $Y + vpaddq $OVERFLOW, $ACC7, $ACC6 + vpaddq $T0, $ACC8, $ACC7 + + #itr 4 + vpmuludq $B, $B, $OVERFLOW + vpmuludq 32*3(%rcx), $B, $T0 + vpaddq $OVERFLOW, $ACC3, $ACC3 + vpmuludq 32*4(%rcx), $B, $OVERFLOW + vpaddq $T0, $ACC4, $ACC4 + vpmuludq 32*5(%rcx), $B, $T0 + vpaddq $OVERFLOW, $ACC5, $ACC5 + vpmuludq 32*6(%rcx), $B, $OVERFLOW + vpaddq $T0, $ACC6, $ACC6 + + vpmuludq $AND_MASK, $Y, $T0 + vpaddq $OVERFLOW, $ACC7, $ACC7 + vpmuludq 32*7(%rcx), $B, $ACC8 + vmovdqa 32*4($a_ptr), $B + vpaddq $T0, $ACC0, $OVERFLOW + vpaddq $T0, $ACC1, $ACC0 + vpsrlq $digit_size, $OVERFLOW, $OVERFLOW + vpaddq $T0, $ACC2, $ACC1 + vpmuludq 32*3(%rax), $Y, $T0 + vpaddq $OVERFLOW, $ACC0, $ACC0 + vpaddq $T0, $ACC3, $ACC2 + vmovdqa $ACC4, $ACC3 + vpsllq \$18, $Y, $T0 + vmovdqa $ACC5, $ACC4 + vpmuludq %ymm14, $Y, $OVERFLOW + vpaddq $T0, $ACC6, $ACC5 + vpmuludq %ymm15, $Y, $T0 + vpand $AND_MASK, $ACC0, $Y + vpaddq $OVERFLOW, $ACC7, $ACC6 + vpaddq $T0, $ACC8, $ACC7 + + #itr 5 + vpmuludq $B, $B, $T0 + vpmuludq 32*4(%rcx), $B, $OVERFLOW + vpaddq $T0, $ACC4, $ACC4 + vpmuludq 32*5(%rcx), $B, $T0 + vpaddq $OVERFLOW, $ACC5, $ACC5 + vpmuludq 32*6(%rcx), $B, $OVERFLOW + vpaddq $T0, $ACC6, $ACC6 + + vpmuludq $AND_MASK, $Y, $T0 + vpaddq $OVERFLOW, $ACC7, $ACC7 + vpmuludq 32*7(%rcx), $B, $ACC8 + vmovdqa 32*5($a_ptr), $B + vpaddq $T0, $ACC0, $OVERFLOW + vpsrlq $digit_size, $OVERFLOW, $OVERFLOW + vpaddq $T0, $ACC1, $ACC0 + vpaddq $T0, $ACC2, $ACC1 + vpmuludq 32*3+.LAVX2_POLY(%rip), $Y, $T0 + vpaddq $OVERFLOW, $ACC0, $ACC0 + vpaddq $T0, $ACC3, $ACC2 + vmovdqa $ACC4, $ACC3 + vpsllq \$18, $Y, $T0 + vmovdqa $ACC5, $ACC4 + vpmuludq %ymm14, $Y, $OVERFLOW + vpaddq $T0, $ACC6, $ACC5 + vpmuludq %ymm15, $Y, $T0 + vpand $AND_MASK, $ACC0, $Y + vpaddq $OVERFLOW, $ACC7, $ACC6 + vpaddq $T0, $ACC8, $ACC7 + + #itr 6 + vpmuludq $B, $B, $OVERFLOW + vpmuludq 32*5(%rcx), $B, $T0 + vpaddq $OVERFLOW, $ACC5, $ACC5 + vpmuludq 32*6(%rcx), $B, $OVERFLOW + vpaddq $T0, $ACC6, $ACC6 + + vpmuludq $AND_MASK, $Y, $T0 + vpaddq $OVERFLOW, $ACC7, $ACC7 + vpmuludq 32*7(%rcx), $B, $ACC8 + vmovdqa 32*6($a_ptr), $B + vpaddq $T0, $ACC0, $OVERFLOW + vpaddq $T0, $ACC1, $ACC0 + vpsrlq $digit_size, $OVERFLOW, $OVERFLOW + vpaddq $T0, $ACC2, $ACC1 + vpmuludq 32*3(%rax), $Y, $T0 + vpaddq $OVERFLOW, $ACC0, $ACC0 + vpaddq $T0, $ACC3, $ACC2 + vmovdqa $ACC4, $ACC3 + vpsllq \$18, $Y, $T0 + vmovdqa $ACC5, $ACC4 + vpmuludq %ymm14, $Y, $OVERFLOW + vpaddq $T0, $ACC6, $ACC5 + vpmuludq %ymm15, $Y, $T0 + vpand $AND_MASK, $ACC0, $Y + vpaddq $OVERFLOW, $ACC7, $ACC6 + vpaddq $T0, $ACC8, $ACC7 + + #itr 7 + vpmuludq $B, $B, $T0 + vpmuludq 32*6(%rcx), $B, $OVERFLOW + vpaddq $T0, $ACC6, $ACC6 + + vpmuludq $AND_MASK, $Y, $T0 + vpaddq $OVERFLOW, $ACC7, $ACC7 + vpmuludq 32*7(%rcx), $B, $ACC8 + vmovdqa 32*7($a_ptr), $B + vpaddq $T0, $ACC0, $OVERFLOW + vpsrlq $digit_size, $OVERFLOW, $OVERFLOW + vpaddq $T0, $ACC1, $ACC0 + vpaddq $T0, $ACC2, $ACC1 + vpmuludq 32*3(%rax), $Y, $T0 + vpaddq $OVERFLOW, $ACC0, $ACC0 + vpaddq $T0, $ACC3, $ACC2 + vmovdqa $ACC4, $ACC3 + vpsllq \$18, $Y, $T0 + vmovdqa $ACC5, $ACC4 + vpmuludq %ymm14, $Y, $OVERFLOW + vpaddq $T0, $ACC6, $ACC5 + vpmuludq %ymm15, $Y, $T0 + vpand $AND_MASK, $ACC0, $Y + vpaddq $OVERFLOW, $ACC7, $ACC6 + vpaddq $T0, $ACC8, $ACC7 + + #itr 8 + vpmuludq $B, $B, $OVERFLOW + + vpmuludq $AND_MASK, $Y, $T0 + vpaddq $OVERFLOW, $ACC7, $ACC7 + vpmuludq 32*7(%rcx), $B, $ACC8 + vmovdqa 32*8($a_ptr), $B + vpaddq $T0, $ACC0, $OVERFLOW + vpsrlq $digit_size, $OVERFLOW, $OVERFLOW + vpaddq $T0, $ACC1, $ACC0 + vpaddq $T0, $ACC2, $ACC1 + vpmuludq 32*3(%rax), $Y, $T0 + vpaddq $OVERFLOW, $ACC0, $ACC0 + vpaddq $T0, $ACC3, $ACC2 + vmovdqa $ACC4, $ACC3 + vpsllq \$18, $Y, $T0 + vmovdqa $ACC5, $ACC4 + vpmuludq %ymm14, $Y, $OVERFLOW + vpaddq $T0, $ACC6, $ACC5 + vpmuludq %ymm15, $Y, $T0 + vpand $AND_MASK, $ACC0, $Y + vpaddq $OVERFLOW, $ACC7, $ACC6 + vpaddq $T0, $ACC8, $ACC7 + + #itr 9 + vpmuludq $B, $B, $ACC8 + + vpmuludq $AND_MASK, $Y, $T0 + vpaddq $T0, $ACC0, $OVERFLOW + vpsrlq $digit_size, $OVERFLOW, $OVERFLOW + vpaddq $T0, $ACC1, $ACC0 + vpaddq $T0, $ACC2, $ACC1 + vpmuludq 32*3(%rax), $Y, $T0 + vpaddq $OVERFLOW, $ACC0, $ACC0 + vpaddq $T0, $ACC3, $ACC2 + vmovdqa $ACC4, $ACC3 + vpsllq \$18, $Y, $T0 + vmovdqa $ACC5, $ACC4 + vpmuludq %ymm14, $Y, $OVERFLOW + vpaddq $T0, $ACC6, $ACC5 + vpmuludq %ymm15, $Y, $T0 + vpaddq $OVERFLOW, $ACC7, $ACC6 + vpaddq $T0, $ACC8, $ACC7 + + vpxor $ACC8, $ACC8, $ACC8 + + ret +.size avx2_sqr_x4,.-avx2_sqr_x4 + +################################################################################ +# void avx2_sub_x4(void* RESULTx4, void *Ax4, void *Bx4); +.type avx2_sub_x4,\@abi-omnipotent +.align 32 +avx2_sub_x4: + vmovdqa 32*0($a_ptr), $ACC0 + lea 160($a_ptr), $a_ptr + lea .LAVX2_POLY_x8+128(%rip), %rax + lea 128($b_ptr), $b_ptr + vmovdqa 32*1-160($a_ptr), $ACC1 + vmovdqa 32*2-160($a_ptr), $ACC2 + vmovdqa 32*3-160($a_ptr), $ACC3 + vmovdqa 32*4-160($a_ptr), $ACC4 + vmovdqa 32*5-160($a_ptr), $ACC5 + vmovdqa 32*6-160($a_ptr), $ACC6 + vmovdqa 32*7-160($a_ptr), $ACC7 + vmovdqa 32*8-160($a_ptr), $ACC8 + + vpaddq 32*0-128(%rax), $ACC0, $ACC0 + vpaddq 32*1-128(%rax), $ACC1, $ACC1 + vpaddq 32*2-128(%rax), $ACC2, $ACC2 + vpaddq 32*3-128(%rax), $ACC3, $ACC3 + vpaddq 32*4-128(%rax), $ACC4, $ACC4 + vpaddq 32*5-128(%rax), $ACC5, $ACC5 + vpaddq 32*6-128(%rax), $ACC6, $ACC6 + vpaddq 32*7-128(%rax), $ACC7, $ACC7 + vpaddq 32*8-128(%rax), $ACC8, $ACC8 + + vpsubq 32*0-128($b_ptr), $ACC0, $ACC0 + vpsubq 32*1-128($b_ptr), $ACC1, $ACC1 + vpsubq 32*2-128($b_ptr), $ACC2, $ACC2 + vpsubq 32*3-128($b_ptr), $ACC3, $ACC3 + vpsubq 32*4-128($b_ptr), $ACC4, $ACC4 + vpsubq 32*5-128($b_ptr), $ACC5, $ACC5 + vpsubq 32*6-128($b_ptr), $ACC6, $ACC6 + vpsubq 32*7-128($b_ptr), $ACC7, $ACC7 + vpsubq 32*8-128($b_ptr), $ACC8, $ACC8 + + ret +.size avx2_sub_x4,.-avx2_sub_x4 + +.type avx2_select_n_store,\@abi-omnipotent +.align 32 +avx2_select_n_store: + vmovdqa `8+32*9*8`(%rsp), $Y + vpor `8+32*9*8+32`(%rsp), $Y, $Y + + vpandn $ACC0, $Y, $ACC0 + vpandn $ACC1, $Y, $ACC1 + vpandn $ACC2, $Y, $ACC2 + vpandn $ACC3, $Y, $ACC3 + vpandn $ACC4, $Y, $ACC4 + vpandn $ACC5, $Y, $ACC5 + vpandn $ACC6, $Y, $ACC6 + vmovdqa `8+32*9*8+32`(%rsp), $B + vpandn $ACC7, $Y, $ACC7 + vpandn `8+32*9*8`(%rsp), $B, $B + vpandn $ACC8, $Y, $ACC8 + + vpand 32*0(%rsi), $B, $T0 + lea 160(%rsi), %rax + vpand 32*1(%rsi), $B, $Y + vpxor $T0, $ACC0, $ACC0 + vpand 32*2(%rsi), $B, $T0 + vpxor $Y, $ACC1, $ACC1 + vpand 32*3(%rsi), $B, $Y + vpxor $T0, $ACC2, $ACC2 + vpand 32*4-160(%rax), $B, $T0 + vpxor $Y, $ACC3, $ACC3 + vpand 32*5-160(%rax), $B, $Y + vpxor $T0, $ACC4, $ACC4 + vpand 32*6-160(%rax), $B, $T0 + vpxor $Y, $ACC5, $ACC5 + vpand 32*7-160(%rax), $B, $Y + vpxor $T0, $ACC6, $ACC6 + vpand 32*8-160(%rax), $B, $T0 + vmovdqa `8+32*9*8+32`(%rsp), $B + vpxor $Y, $ACC7, $ACC7 + + vpand 32*0(%rdx), $B, $Y + lea 160(%rdx), %rax + vpxor $T0, $ACC8, $ACC8 + vpand 32*1(%rdx), $B, $T0 + vpxor $Y, $ACC0, $ACC0 + vpand 32*2(%rdx), $B, $Y + vpxor $T0, $ACC1, $ACC1 + vpand 32*3(%rdx), $B, $T0 + vpxor $Y, $ACC2, $ACC2 + vpand 32*4-160(%rax), $B, $Y + vpxor $T0, $ACC3, $ACC3 + vpand 32*5-160(%rax), $B, $T0 + vpxor $Y, $ACC4, $ACC4 + vpand 32*6-160(%rax), $B, $Y + vpxor $T0, $ACC5, $ACC5 + vpand 32*7-160(%rax), $B, $T0 + vpxor $Y, $ACC6, $ACC6 + vpand 32*8-160(%rax), $B, $Y + vpxor $T0, $ACC7, $ACC7 + vpxor $Y, $ACC8, $ACC8 + `&STORE` + + ret +.size avx2_select_n_store,.-avx2_select_n_store +___ +$code.=<<___ if (0); # inlined +################################################################################ +# void avx2_mul_by2_x4(void* RESULTx4, void *Ax4); +.type avx2_mul_by2_x4,\@abi-omnipotent +.align 32 +avx2_mul_by2_x4: + vmovdqa 32*0($a_ptr), $ACC0 + lea 160($a_ptr), %rax + vmovdqa 32*1($a_ptr), $ACC1 + vmovdqa 32*2($a_ptr), $ACC2 + vmovdqa 32*3($a_ptr), $ACC3 + vmovdqa 32*4-160(%rax), $ACC4 + vmovdqa 32*5-160(%rax), $ACC5 + vmovdqa 32*6-160(%rax), $ACC6 + vmovdqa 32*7-160(%rax), $ACC7 + vmovdqa 32*8-160(%rax), $ACC8 + + vpaddq $ACC0, $ACC0, $ACC0 + vpaddq $ACC1, $ACC1, $ACC1 + vpaddq $ACC2, $ACC2, $ACC2 + vpaddq $ACC3, $ACC3, $ACC3 + vpaddq $ACC4, $ACC4, $ACC4 + vpaddq $ACC5, $ACC5, $ACC5 + vpaddq $ACC6, $ACC6, $ACC6 + vpaddq $ACC7, $ACC7, $ACC7 + vpaddq $ACC8, $ACC8, $ACC8 + + ret +.size avx2_mul_by2_x4,.-avx2_mul_by2_x4 +___ +my ($r_ptr_in,$a_ptr_in,$b_ptr_in)=("%rdi","%rsi","%rdx"); +my ($r_ptr,$a_ptr,$b_ptr)=("%r8","%r9","%r10"); + +$code.=<<___; +################################################################################ +# void ecp_nistz256_avx2_point_add_affine_x4(void* RESULTx4, void *Ax4, void *Bx4); +.globl ecp_nistz256_avx2_point_add_affine_x4 +.type ecp_nistz256_avx2_point_add_affine_x4,\@function,3 +.align 32 +ecp_nistz256_avx2_point_add_affine_x4: + mov %rsp, %rax + push %rbp + vzeroupper +___ +$code.=<<___ if ($win64); + lea -16*10(%rsp), %rsp + vmovaps %xmm6, -8-16*10(%rax) + vmovaps %xmm7, -8-16*9(%rax) + vmovaps %xmm8, -8-16*8(%rax) + vmovaps %xmm9, -8-16*7(%rax) + vmovaps %xmm10, -8-16*6(%rax) + vmovaps %xmm11, -8-16*5(%rax) + vmovaps %xmm12, -8-16*4(%rax) + vmovaps %xmm13, -8-16*3(%rax) + vmovaps %xmm14, -8-16*2(%rax) + vmovaps %xmm15, -8-16*1(%rax) +___ +$code.=<<___; + lea -8(%rax), %rbp + +# Result + 32*0 = Result.X +# Result + 32*9 = Result.Y +# Result + 32*18 = Result.Z + +# A + 32*0 = A.X +# A + 32*9 = A.Y +# A + 32*18 = A.Z + +# B + 32*0 = B.X +# B + 32*9 = B.Y + + sub \$`32*9*8+32*2+32*8`, %rsp + and \$-64, %rsp + + mov $r_ptr_in, $r_ptr + mov $a_ptr_in, $a_ptr + mov $b_ptr_in, $b_ptr + + vmovdqa 32*0($a_ptr_in), %ymm0 + vmovdqa .LAVX2_AND_MASK(%rip), $AND_MASK + vpxor %ymm1, %ymm1, %ymm1 + lea 256($a_ptr_in), %rax # size optimization + vpor 32*1($a_ptr_in), %ymm0, %ymm0 + vpor 32*2($a_ptr_in), %ymm0, %ymm0 + vpor 32*3($a_ptr_in), %ymm0, %ymm0 + vpor 32*4-256(%rax), %ymm0, %ymm0 + lea 256(%rax), %rcx # size optimization + vpor 32*5-256(%rax), %ymm0, %ymm0 + vpor 32*6-256(%rax), %ymm0, %ymm0 + vpor 32*7-256(%rax), %ymm0, %ymm0 + vpor 32*8-256(%rax), %ymm0, %ymm0 + vpor 32*9-256(%rax), %ymm0, %ymm0 + vpor 32*10-256(%rax), %ymm0, %ymm0 + vpor 32*11-256(%rax), %ymm0, %ymm0 + vpor 32*12-512(%rcx), %ymm0, %ymm0 + vpor 32*13-512(%rcx), %ymm0, %ymm0 + vpor 32*14-512(%rcx), %ymm0, %ymm0 + vpor 32*15-512(%rcx), %ymm0, %ymm0 + vpor 32*16-512(%rcx), %ymm0, %ymm0 + vpor 32*17-512(%rcx), %ymm0, %ymm0 + vpcmpeqq %ymm1, %ymm0, %ymm0 + vmovdqa %ymm0, `32*9*8`(%rsp) + + vpxor %ymm1, %ymm1, %ymm1 + vmovdqa 32*0($b_ptr), %ymm0 + lea 256($b_ptr), %rax # size optimization + vpor 32*1($b_ptr), %ymm0, %ymm0 + vpor 32*2($b_ptr), %ymm0, %ymm0 + vpor 32*3($b_ptr), %ymm0, %ymm0 + vpor 32*4-256(%rax), %ymm0, %ymm0 + lea 256(%rax), %rcx # size optimization + vpor 32*5-256(%rax), %ymm0, %ymm0 + vpor 32*6-256(%rax), %ymm0, %ymm0 + vpor 32*7-256(%rax), %ymm0, %ymm0 + vpor 32*8-256(%rax), %ymm0, %ymm0 + vpor 32*9-256(%rax), %ymm0, %ymm0 + vpor 32*10-256(%rax), %ymm0, %ymm0 + vpor 32*11-256(%rax), %ymm0, %ymm0 + vpor 32*12-512(%rcx), %ymm0, %ymm0 + vpor 32*13-512(%rcx), %ymm0, %ymm0 + vpor 32*14-512(%rcx), %ymm0, %ymm0 + vpor 32*15-512(%rcx), %ymm0, %ymm0 + vpor 32*16-512(%rcx), %ymm0, %ymm0 + vpor 32*17-512(%rcx), %ymm0, %ymm0 + vpcmpeqq %ymm1, %ymm0, %ymm0 + vmovdqa %ymm0, `32*9*8+32`(%rsp) + + # Z1^2 = Z1*Z1 + lea `32*9*2`($a_ptr), %rsi + lea `32*9*2`(%rsp), %rdi + lea `32*9*8+32*2`(%rsp), %rcx # temporary vector + call avx2_sqr_x4 + call avx2_normalize_n_store + + # U2 = X2*Z1^2 + lea `32*9*0`($b_ptr), %rsi + lea `32*9*2`(%rsp), %rdx + lea `32*9*0`(%rsp), %rdi + call avx2_mul_x4 + #call avx2_normalize + `&STORE` + + # S2 = Z1*Z1^2 = Z1^3 + lea `32*9*2`($a_ptr), %rsi + lea `32*9*2`(%rsp), %rdx + lea `32*9*1`(%rsp), %rdi + call avx2_mul_x4 + call avx2_normalize_n_store + + # S2 = S2*Y2 = Y2*Z1^3 + lea `32*9*1`($b_ptr), %rsi + lea `32*9*1`(%rsp), %rdx + lea `32*9*1`(%rsp), %rdi + call avx2_mul_x4 + call avx2_normalize_n_store + + # H = U2 - U1 = U2 - X1 + lea `32*9*0`(%rsp), %rsi + lea `32*9*0`($a_ptr), %rdx + lea `32*9*3`(%rsp), %rdi + call avx2_sub_x4 + call avx2_normalize_n_store + + # R = S2 - S1 = S2 - Y1 + lea `32*9*1`(%rsp), %rsi + lea `32*9*1`($a_ptr), %rdx + lea `32*9*4`(%rsp), %rdi + call avx2_sub_x4 + call avx2_normalize_n_store + + # Z3 = H*Z1*Z2 + lea `32*9*3`(%rsp), %rsi + lea `32*9*2`($a_ptr), %rdx + lea `32*9*2`($r_ptr), %rdi + call avx2_mul_x4 + call avx2_normalize + + lea .LONE(%rip), %rsi + lea `32*9*2`($a_ptr), %rdx + call avx2_select_n_store + + # R^2 = R^2 + lea `32*9*4`(%rsp), %rsi + lea `32*9*6`(%rsp), %rdi + lea `32*9*8+32*2`(%rsp), %rcx # temporary vector + call avx2_sqr_x4 + call avx2_normalize_n_store + + # H^2 = H^2 + lea `32*9*3`(%rsp), %rsi + lea `32*9*5`(%rsp), %rdi + call avx2_sqr_x4 + call avx2_normalize_n_store + + # H^3 = H^2*H + lea `32*9*3`(%rsp), %rsi + lea `32*9*5`(%rsp), %rdx + lea `32*9*7`(%rsp), %rdi + call avx2_mul_x4 + call avx2_normalize_n_store + + # U2 = U1*H^2 + lea `32*9*0`($a_ptr), %rsi + lea `32*9*5`(%rsp), %rdx + lea `32*9*0`(%rsp), %rdi + call avx2_mul_x4 + #call avx2_normalize + `&STORE` + + # Hsqr = U2*2 + #lea 32*9*0(%rsp), %rsi + #lea 32*9*5(%rsp), %rdi + #call avx2_mul_by2_x4 + + vpaddq $ACC0, $ACC0, $ACC0 # inlined avx2_mul_by2_x4 + lea `32*9*5`(%rsp), %rdi + vpaddq $ACC1, $ACC1, $ACC1 + vpaddq $ACC2, $ACC2, $ACC2 + vpaddq $ACC3, $ACC3, $ACC3 + vpaddq $ACC4, $ACC4, $ACC4 + vpaddq $ACC5, $ACC5, $ACC5 + vpaddq $ACC6, $ACC6, $ACC6 + vpaddq $ACC7, $ACC7, $ACC7 + vpaddq $ACC8, $ACC8, $ACC8 + call avx2_normalize_n_store + + # X3 = R^2 - H^3 + #lea 32*9*6(%rsp), %rsi + #lea 32*9*7(%rsp), %rdx + #lea 32*9*5(%rsp), %rcx + #lea 32*9*0($r_ptr), %rdi + #call avx2_sub_x4 + #NORMALIZE + #STORE + + # X3 = X3 - U2*2 + #lea 32*9*0($r_ptr), %rsi + #lea 32*9*0($r_ptr), %rdi + #call avx2_sub_x4 + #NORMALIZE + #STORE + + lea `32*9*6+128`(%rsp), %rsi + lea .LAVX2_POLY_x2+128(%rip), %rax + lea `32*9*7+128`(%rsp), %rdx + lea `32*9*5+128`(%rsp), %rcx + lea `32*9*0`($r_ptr), %rdi + + vmovdqa 32*0-128(%rsi), $ACC0 + vmovdqa 32*1-128(%rsi), $ACC1 + vmovdqa 32*2-128(%rsi), $ACC2 + vmovdqa 32*3-128(%rsi), $ACC3 + vmovdqa 32*4-128(%rsi), $ACC4 + vmovdqa 32*5-128(%rsi), $ACC5 + vmovdqa 32*6-128(%rsi), $ACC6 + vmovdqa 32*7-128(%rsi), $ACC7 + vmovdqa 32*8-128(%rsi), $ACC8 + + vpaddq 32*0-128(%rax), $ACC0, $ACC0 + vpaddq 32*1-128(%rax), $ACC1, $ACC1 + vpaddq 32*2-128(%rax), $ACC2, $ACC2 + vpaddq 32*3-128(%rax), $ACC3, $ACC3 + vpaddq 32*4-128(%rax), $ACC4, $ACC4 + vpaddq 32*5-128(%rax), $ACC5, $ACC5 + vpaddq 32*6-128(%rax), $ACC6, $ACC6 + vpaddq 32*7-128(%rax), $ACC7, $ACC7 + vpaddq 32*8-128(%rax), $ACC8, $ACC8 + + vpsubq 32*0-128(%rdx), $ACC0, $ACC0 + vpsubq 32*1-128(%rdx), $ACC1, $ACC1 + vpsubq 32*2-128(%rdx), $ACC2, $ACC2 + vpsubq 32*3-128(%rdx), $ACC3, $ACC3 + vpsubq 32*4-128(%rdx), $ACC4, $ACC4 + vpsubq 32*5-128(%rdx), $ACC5, $ACC5 + vpsubq 32*6-128(%rdx), $ACC6, $ACC6 + vpsubq 32*7-128(%rdx), $ACC7, $ACC7 + vpsubq 32*8-128(%rdx), $ACC8, $ACC8 + + vpsubq 32*0-128(%rcx), $ACC0, $ACC0 + vpsubq 32*1-128(%rcx), $ACC1, $ACC1 + vpsubq 32*2-128(%rcx), $ACC2, $ACC2 + vpsubq 32*3-128(%rcx), $ACC3, $ACC3 + vpsubq 32*4-128(%rcx), $ACC4, $ACC4 + vpsubq 32*5-128(%rcx), $ACC5, $ACC5 + vpsubq 32*6-128(%rcx), $ACC6, $ACC6 + vpsubq 32*7-128(%rcx), $ACC7, $ACC7 + vpsubq 32*8-128(%rcx), $ACC8, $ACC8 + call avx2_normalize + + lea 32*0($b_ptr), %rsi + lea 32*0($a_ptr), %rdx + call avx2_select_n_store + + # H = U2 - X3 + lea `32*9*0`(%rsp), %rsi + lea `32*9*0`($r_ptr), %rdx + lea `32*9*3`(%rsp), %rdi + call avx2_sub_x4 + call avx2_normalize_n_store + + # + lea `32*9*3`(%rsp), %rsi + lea `32*9*4`(%rsp), %rdx + lea `32*9*3`(%rsp), %rdi + call avx2_mul_x4 + call avx2_normalize_n_store + + # + lea `32*9*7`(%rsp), %rsi + lea `32*9*1`($a_ptr), %rdx + lea `32*9*1`(%rsp), %rdi + call avx2_mul_x4 + call avx2_normalize_n_store + + # + lea `32*9*3`(%rsp), %rsi + lea `32*9*1`(%rsp), %rdx + lea `32*9*1`($r_ptr), %rdi + call avx2_sub_x4 + call avx2_normalize + + lea 32*9($b_ptr), %rsi + lea 32*9($a_ptr), %rdx + call avx2_select_n_store + + #lea 32*9*0($r_ptr), %rsi + #lea 32*9*0($r_ptr), %rdi + #call avx2_mul_by1_x4 + #NORMALIZE + #STORE + + lea `32*9*1`($r_ptr), %rsi + lea `32*9*1`($r_ptr), %rdi + call avx2_mul_by1_x4 + call avx2_normalize_n_store + + vzeroupper +___ +$code.=<<___ if ($win64); + movaps %xmm6, -16*10(%rbp) + movaps %xmm7, -16*9(%rbp) + movaps %xmm8, -16*8(%rbp) + movaps %xmm9, -16*7(%rbp) + movaps %xmm10, -16*6(%rbp) + movaps %xmm11, -16*5(%rbp) + movaps %xmm12, -16*4(%rbp) + movaps %xmm13, -16*3(%rbp) + movaps %xmm14, -16*2(%rbp) + movaps %xmm15, -16*1(%rbp) +___ +$code.=<<___; + mov %rbp, %rsp + pop %rbp + ret +.size ecp_nistz256_avx2_point_add_affine_x4,.-ecp_nistz256_avx2_point_add_affine_x4 + +################################################################################ +# void ecp_nistz256_avx2_point_add_affines_x4(void* RESULTx4, void *Ax4, void *Bx4); +.globl ecp_nistz256_avx2_point_add_affines_x4 +.type ecp_nistz256_avx2_point_add_affines_x4,\@function,3 +.align 32 +ecp_nistz256_avx2_point_add_affines_x4: + mov %rsp, %rax + push %rbp + vzeroupper +___ +$code.=<<___ if ($win64); + lea -16*10(%rsp), %rsp + vmovaps %xmm6, -8-16*10(%rax) + vmovaps %xmm7, -8-16*9(%rax) + vmovaps %xmm8, -8-16*8(%rax) + vmovaps %xmm9, -8-16*7(%rax) + vmovaps %xmm10, -8-16*6(%rax) + vmovaps %xmm11, -8-16*5(%rax) + vmovaps %xmm12, -8-16*4(%rax) + vmovaps %xmm13, -8-16*3(%rax) + vmovaps %xmm14, -8-16*2(%rax) + vmovaps %xmm15, -8-16*1(%rax) +___ +$code.=<<___; + lea -8(%rax), %rbp + +# Result + 32*0 = Result.X +# Result + 32*9 = Result.Y +# Result + 32*18 = Result.Z + +# A + 32*0 = A.X +# A + 32*9 = A.Y + +# B + 32*0 = B.X +# B + 32*9 = B.Y + + sub \$`32*9*8+32*2+32*8`, %rsp + and \$-64, %rsp + + mov $r_ptr_in, $r_ptr + mov $a_ptr_in, $a_ptr + mov $b_ptr_in, $b_ptr + + vmovdqa 32*0($a_ptr_in), %ymm0 + vmovdqa .LAVX2_AND_MASK(%rip), $AND_MASK + vpxor %ymm1, %ymm1, %ymm1 + lea 256($a_ptr_in), %rax # size optimization + vpor 32*1($a_ptr_in), %ymm0, %ymm0 + vpor 32*2($a_ptr_in), %ymm0, %ymm0 + vpor 32*3($a_ptr_in), %ymm0, %ymm0 + vpor 32*4-256(%rax), %ymm0, %ymm0 + lea 256(%rax), %rcx # size optimization + vpor 32*5-256(%rax), %ymm0, %ymm0 + vpor 32*6-256(%rax), %ymm0, %ymm0 + vpor 32*7-256(%rax), %ymm0, %ymm0 + vpor 32*8-256(%rax), %ymm0, %ymm0 + vpor 32*9-256(%rax), %ymm0, %ymm0 + vpor 32*10-256(%rax), %ymm0, %ymm0 + vpor 32*11-256(%rax), %ymm0, %ymm0 + vpor 32*12-512(%rcx), %ymm0, %ymm0 + vpor 32*13-512(%rcx), %ymm0, %ymm0 + vpor 32*14-512(%rcx), %ymm0, %ymm0 + vpor 32*15-512(%rcx), %ymm0, %ymm0 + vpor 32*16-512(%rcx), %ymm0, %ymm0 + vpor 32*17-512(%rcx), %ymm0, %ymm0 + vpcmpeqq %ymm1, %ymm0, %ymm0 + vmovdqa %ymm0, `32*9*8`(%rsp) + + vpxor %ymm1, %ymm1, %ymm1 + vmovdqa 32*0($b_ptr), %ymm0 + lea 256($b_ptr), %rax # size optimization + vpor 32*1($b_ptr), %ymm0, %ymm0 + vpor 32*2($b_ptr), %ymm0, %ymm0 + vpor 32*3($b_ptr), %ymm0, %ymm0 + vpor 32*4-256(%rax), %ymm0, %ymm0 + lea 256(%rax), %rcx # size optimization + vpor 32*5-256(%rax), %ymm0, %ymm0 + vpor 32*6-256(%rax), %ymm0, %ymm0 + vpor 32*7-256(%rax), %ymm0, %ymm0 + vpor 32*8-256(%rax), %ymm0, %ymm0 + vpor 32*9-256(%rax), %ymm0, %ymm0 + vpor 32*10-256(%rax), %ymm0, %ymm0 + vpor 32*11-256(%rax), %ymm0, %ymm0 + vpor 32*12-512(%rcx), %ymm0, %ymm0 + vpor 32*13-512(%rcx), %ymm0, %ymm0 + vpor 32*14-512(%rcx), %ymm0, %ymm0 + vpor 32*15-512(%rcx), %ymm0, %ymm0 + vpor 32*16-512(%rcx), %ymm0, %ymm0 + vpor 32*17-512(%rcx), %ymm0, %ymm0 + vpcmpeqq %ymm1, %ymm0, %ymm0 + vmovdqa %ymm0, `32*9*8+32`(%rsp) + + # H = U2 - U1 = X2 - X1 + lea `32*9*0`($b_ptr), %rsi + lea `32*9*0`($a_ptr), %rdx + lea `32*9*3`(%rsp), %rdi + call avx2_sub_x4 + call avx2_normalize_n_store + + # R = S2 - S1 = Y2 - Y1 + lea `32*9*1`($b_ptr), %rsi + lea `32*9*1`($a_ptr), %rdx + lea `32*9*4`(%rsp), %rdi + call avx2_sub_x4 + call avx2_normalize_n_store + + # Z3 = H*Z1*Z2 = H + lea `32*9*3`(%rsp), %rsi + lea `32*9*2`($r_ptr), %rdi + call avx2_mul_by1_x4 + call avx2_normalize + + vmovdqa `32*9*8`(%rsp), $B + vpor `32*9*8+32`(%rsp), $B, $B + + vpandn $ACC0, $B, $ACC0 + lea .LONE+128(%rip), %rax + vpandn $ACC1, $B, $ACC1 + vpandn $ACC2, $B, $ACC2 + vpandn $ACC3, $B, $ACC3 + vpandn $ACC4, $B, $ACC4 + vpandn $ACC5, $B, $ACC5 + vpandn $ACC6, $B, $ACC6 + vpandn $ACC7, $B, $ACC7 + + vpand 32*0-128(%rax), $B, $T0 + vpandn $ACC8, $B, $ACC8 + vpand 32*1-128(%rax), $B, $Y + vpxor $T0, $ACC0, $ACC0 + vpand 32*2-128(%rax), $B, $T0 + vpxor $Y, $ACC1, $ACC1 + vpand 32*3-128(%rax), $B, $Y + vpxor $T0, $ACC2, $ACC2 + vpand 32*4-128(%rax), $B, $T0 + vpxor $Y, $ACC3, $ACC3 + vpand 32*5-128(%rax), $B, $Y + vpxor $T0, $ACC4, $ACC4 + vpand 32*6-128(%rax), $B, $T0 + vpxor $Y, $ACC5, $ACC5 + vpand 32*7-128(%rax), $B, $Y + vpxor $T0, $ACC6, $ACC6 + vpand 32*8-128(%rax), $B, $T0 + vpxor $Y, $ACC7, $ACC7 + vpxor $T0, $ACC8, $ACC8 + `&STORE` + + # R^2 = R^2 + lea `32*9*4`(%rsp), %rsi + lea `32*9*6`(%rsp), %rdi + lea `32*9*8+32*2`(%rsp), %rcx # temporary vector + call avx2_sqr_x4 + call avx2_normalize_n_store + + # H^2 = H^2 + lea `32*9*3`(%rsp), %rsi + lea `32*9*5`(%rsp), %rdi + call avx2_sqr_x4 + call avx2_normalize_n_store + + # H^3 = H^2*H + lea `32*9*3`(%rsp), %rsi + lea `32*9*5`(%rsp), %rdx + lea `32*9*7`(%rsp), %rdi + call avx2_mul_x4 + call avx2_normalize_n_store + + # U2 = U1*H^2 + lea `32*9*0`($a_ptr), %rsi + lea `32*9*5`(%rsp), %rdx + lea `32*9*0`(%rsp), %rdi + call avx2_mul_x4 + #call avx2_normalize + `&STORE` + + # Hsqr = U2*2 + #lea 32*9*0(%rsp), %rsi + #lea 32*9*5(%rsp), %rdi + #call avx2_mul_by2_x4 + + vpaddq $ACC0, $ACC0, $ACC0 # inlined avx2_mul_by2_x4 + lea `32*9*5`(%rsp), %rdi + vpaddq $ACC1, $ACC1, $ACC1 + vpaddq $ACC2, $ACC2, $ACC2 + vpaddq $ACC3, $ACC3, $ACC3 + vpaddq $ACC4, $ACC4, $ACC4 + vpaddq $ACC5, $ACC5, $ACC5 + vpaddq $ACC6, $ACC6, $ACC6 + vpaddq $ACC7, $ACC7, $ACC7 + vpaddq $ACC8, $ACC8, $ACC8 + call avx2_normalize_n_store + + # X3 = R^2 - H^3 + #lea 32*9*6(%rsp), %rsi + #lea 32*9*7(%rsp), %rdx + #lea 32*9*5(%rsp), %rcx + #lea 32*9*0($r_ptr), %rdi + #call avx2_sub_x4 + #NORMALIZE + #STORE + + # X3 = X3 - U2*2 + #lea 32*9*0($r_ptr), %rsi + #lea 32*9*0($r_ptr), %rdi + #call avx2_sub_x4 + #NORMALIZE + #STORE + + lea `32*9*6+128`(%rsp), %rsi + lea .LAVX2_POLY_x2+128(%rip), %rax + lea `32*9*7+128`(%rsp), %rdx + lea `32*9*5+128`(%rsp), %rcx + lea `32*9*0`($r_ptr), %rdi + + vmovdqa 32*0-128(%rsi), $ACC0 + vmovdqa 32*1-128(%rsi), $ACC1 + vmovdqa 32*2-128(%rsi), $ACC2 + vmovdqa 32*3-128(%rsi), $ACC3 + vmovdqa 32*4-128(%rsi), $ACC4 + vmovdqa 32*5-128(%rsi), $ACC5 + vmovdqa 32*6-128(%rsi), $ACC6 + vmovdqa 32*7-128(%rsi), $ACC7 + vmovdqa 32*8-128(%rsi), $ACC8 + + vpaddq 32*0-128(%rax), $ACC0, $ACC0 + vpaddq 32*1-128(%rax), $ACC1, $ACC1 + vpaddq 32*2-128(%rax), $ACC2, $ACC2 + vpaddq 32*3-128(%rax), $ACC3, $ACC3 + vpaddq 32*4-128(%rax), $ACC4, $ACC4 + vpaddq 32*5-128(%rax), $ACC5, $ACC5 + vpaddq 32*6-128(%rax), $ACC6, $ACC6 + vpaddq 32*7-128(%rax), $ACC7, $ACC7 + vpaddq 32*8-128(%rax), $ACC8, $ACC8 + + vpsubq 32*0-128(%rdx), $ACC0, $ACC0 + vpsubq 32*1-128(%rdx), $ACC1, $ACC1 + vpsubq 32*2-128(%rdx), $ACC2, $ACC2 + vpsubq 32*3-128(%rdx), $ACC3, $ACC3 + vpsubq 32*4-128(%rdx), $ACC4, $ACC4 + vpsubq 32*5-128(%rdx), $ACC5, $ACC5 + vpsubq 32*6-128(%rdx), $ACC6, $ACC6 + vpsubq 32*7-128(%rdx), $ACC7, $ACC7 + vpsubq 32*8-128(%rdx), $ACC8, $ACC8 + + vpsubq 32*0-128(%rcx), $ACC0, $ACC0 + vpsubq 32*1-128(%rcx), $ACC1, $ACC1 + vpsubq 32*2-128(%rcx), $ACC2, $ACC2 + vpsubq 32*3-128(%rcx), $ACC3, $ACC3 + vpsubq 32*4-128(%rcx), $ACC4, $ACC4 + vpsubq 32*5-128(%rcx), $ACC5, $ACC5 + vpsubq 32*6-128(%rcx), $ACC6, $ACC6 + vpsubq 32*7-128(%rcx), $ACC7, $ACC7 + vpsubq 32*8-128(%rcx), $ACC8, $ACC8 + call avx2_normalize + + lea 32*0($b_ptr), %rsi + lea 32*0($a_ptr), %rdx + call avx2_select_n_store + + # H = U2 - X3 + lea `32*9*0`(%rsp), %rsi + lea `32*9*0`($r_ptr), %rdx + lea `32*9*3`(%rsp), %rdi + call avx2_sub_x4 + call avx2_normalize_n_store + + # H = H*R + lea `32*9*3`(%rsp), %rsi + lea `32*9*4`(%rsp), %rdx + lea `32*9*3`(%rsp), %rdi + call avx2_mul_x4 + call avx2_normalize_n_store + + # S2 = S1 * H^3 + lea `32*9*7`(%rsp), %rsi + lea `32*9*1`($a_ptr), %rdx + lea `32*9*1`(%rsp), %rdi + call avx2_mul_x4 + call avx2_normalize_n_store + + # + lea `32*9*3`(%rsp), %rsi + lea `32*9*1`(%rsp), %rdx + lea `32*9*1`($r_ptr), %rdi + call avx2_sub_x4 + call avx2_normalize + + lea 32*9($b_ptr), %rsi + lea 32*9($a_ptr), %rdx + call avx2_select_n_store + + #lea 32*9*0($r_ptr), %rsi + #lea 32*9*0($r_ptr), %rdi + #call avx2_mul_by1_x4 + #NORMALIZE + #STORE + + lea `32*9*1`($r_ptr), %rsi + lea `32*9*1`($r_ptr), %rdi + call avx2_mul_by1_x4 + call avx2_normalize_n_store + + vzeroupper +___ +$code.=<<___ if ($win64); + movaps %xmm6, -16*10(%rbp) + movaps %xmm7, -16*9(%rbp) + movaps %xmm8, -16*8(%rbp) + movaps %xmm9, -16*7(%rbp) + movaps %xmm10, -16*6(%rbp) + movaps %xmm11, -16*5(%rbp) + movaps %xmm12, -16*4(%rbp) + movaps %xmm13, -16*3(%rbp) + movaps %xmm14, -16*2(%rbp) + movaps %xmm15, -16*1(%rbp) +___ +$code.=<<___; + mov %rbp, %rsp + pop %rbp + ret +.size ecp_nistz256_avx2_point_add_affines_x4,.-ecp_nistz256_avx2_point_add_affines_x4 + +################################################################################ +# void ecp_nistz256_avx2_to_mont(void* RESULTx4, void *Ax4); +.globl ecp_nistz256_avx2_to_mont +.type ecp_nistz256_avx2_to_mont,\@function,2 +.align 32 +ecp_nistz256_avx2_to_mont: + vzeroupper +___ +$code.=<<___ if ($win64); + lea -8-16*10(%rsp), %rsp + vmovaps %xmm6, -8-16*10(%rax) + vmovaps %xmm7, -8-16*9(%rax) + vmovaps %xmm8, -8-16*8(%rax) + vmovaps %xmm9, -8-16*7(%rax) + vmovaps %xmm10, -8-16*6(%rax) + vmovaps %xmm11, -8-16*5(%rax) + vmovaps %xmm12, -8-16*4(%rax) + vmovaps %xmm13, -8-16*3(%rax) + vmovaps %xmm14, -8-16*2(%rax) + vmovaps %xmm15, -8-16*1(%rax) +___ +$code.=<<___; + vmovdqa .LAVX2_AND_MASK(%rip), $AND_MASK + lea .LTO_MONT_AVX2(%rip), %rdx + call avx2_mul_x4 + call avx2_normalize_n_store + + vzeroupper +___ +$code.=<<___ if ($win64); + movaps 16*0(%rsp), %xmm6 + movaps 16*1(%rsp), %xmm7 + movaps 16*2(%rsp), %xmm8 + movaps 16*3(%rsp), %xmm9 + movaps 16*4(%rsp), %xmm10 + movaps 16*5(%rsp), %xmm11 + movaps 16*6(%rsp), %xmm12 + movaps 16*7(%rsp), %xmm13 + movaps 16*8(%rsp), %xmm14 + movaps 16*9(%rsp), %xmm15 + lea 8+16*10(%rsp), %rsp +___ +$code.=<<___; + ret +.size ecp_nistz256_avx2_to_mont,.-ecp_nistz256_avx2_to_mont + +################################################################################ +# void ecp_nistz256_avx2_from_mont(void* RESULTx4, void *Ax4); +.globl ecp_nistz256_avx2_from_mont +.type ecp_nistz256_avx2_from_mont,\@function,2 +.align 32 +ecp_nistz256_avx2_from_mont: + vzeroupper +___ +$code.=<<___ if ($win64); + lea -8-16*10(%rsp), %rsp + vmovaps %xmm6, -8-16*10(%rax) + vmovaps %xmm7, -8-16*9(%rax) + vmovaps %xmm8, -8-16*8(%rax) + vmovaps %xmm9, -8-16*7(%rax) + vmovaps %xmm10, -8-16*6(%rax) + vmovaps %xmm11, -8-16*5(%rax) + vmovaps %xmm12, -8-16*4(%rax) + vmovaps %xmm13, -8-16*3(%rax) + vmovaps %xmm14, -8-16*2(%rax) + vmovaps %xmm15, -8-16*1(%rax) +___ +$code.=<<___; + vmovdqa .LAVX2_AND_MASK(%rip), $AND_MASK + lea .LFROM_MONT_AVX2(%rip), %rdx + call avx2_mul_x4 + call avx2_normalize_n_store + + vzeroupper +___ +$code.=<<___ if ($win64); + movaps 16*0(%rsp), %xmm6 + movaps 16*1(%rsp), %xmm7 + movaps 16*2(%rsp), %xmm8 + movaps 16*3(%rsp), %xmm9 + movaps 16*4(%rsp), %xmm10 + movaps 16*5(%rsp), %xmm11 + movaps 16*6(%rsp), %xmm12 + movaps 16*7(%rsp), %xmm13 + movaps 16*8(%rsp), %xmm14 + movaps 16*9(%rsp), %xmm15 + lea 8+16*10(%rsp), %rsp +___ +$code.=<<___; + ret +.size ecp_nistz256_avx2_from_mont,.-ecp_nistz256_avx2_from_mont + +################################################################################ +# void ecp_nistz256_avx2_set1(void* RESULTx4); +.globl ecp_nistz256_avx2_set1 +.type ecp_nistz256_avx2_set1,\@function,1 +.align 32 +ecp_nistz256_avx2_set1: + lea .LONE+128(%rip), %rax + lea 128(%rdi), %rdi + vzeroupper + vmovdqa 32*0-128(%rax), %ymm0 + vmovdqa 32*1-128(%rax), %ymm1 + vmovdqa 32*2-128(%rax), %ymm2 + vmovdqa 32*3-128(%rax), %ymm3 + vmovdqa 32*4-128(%rax), %ymm4 + vmovdqa 32*5-128(%rax), %ymm5 + vmovdqa %ymm0, 32*0-128(%rdi) + vmovdqa 32*6-128(%rax), %ymm0 + vmovdqa %ymm1, 32*1-128(%rdi) + vmovdqa 32*7-128(%rax), %ymm1 + vmovdqa %ymm2, 32*2-128(%rdi) + vmovdqa 32*8-128(%rax), %ymm2 + vmovdqa %ymm3, 32*3-128(%rdi) + vmovdqa %ymm4, 32*4-128(%rdi) + vmovdqa %ymm5, 32*5-128(%rdi) + vmovdqa %ymm0, 32*6-128(%rdi) + vmovdqa %ymm1, 32*7-128(%rdi) + vmovdqa %ymm2, 32*8-128(%rdi) + + vzeroupper + ret +.size ecp_nistz256_avx2_set1,.-ecp_nistz256_avx2_set1 +___ +} +{ +################################################################################ +# void ecp_nistz256_avx2_multi_gather_w7(void* RESULT, void *in, +# int index0, int index1, int index2, int index3); +################################################################################ + +my ($val,$in_t,$index0,$index1,$index2,$index3)=("%rdi","%rsi","%edx","%ecx","%r8d","%r9d"); +my ($INDEX0,$INDEX1,$INDEX2,$INDEX3)=map("%ymm$_",(0..3)); +my ($R0a,$R0b,$R1a,$R1b,$R2a,$R2b,$R3a,$R3b)=map("%ymm$_",(4..11)); +my ($M0,$T0,$T1,$TMP0)=map("%ymm$_",(12..15)); + +$code.=<<___; +.globl ecp_nistz256_avx2_multi_gather_w7 +.type ecp_nistz256_avx2_multi_gather_w7,\@function,6 +.align 32 +ecp_nistz256_avx2_multi_gather_w7: + vzeroupper +___ +$code.=<<___ if ($win64); + lea -8-16*10(%rsp), %rsp + vmovaps %xmm6, -8-16*10(%rax) + vmovaps %xmm7, -8-16*9(%rax) + vmovaps %xmm8, -8-16*8(%rax) + vmovaps %xmm9, -8-16*7(%rax) + vmovaps %xmm10, -8-16*6(%rax) + vmovaps %xmm11, -8-16*5(%rax) + vmovaps %xmm12, -8-16*4(%rax) + vmovaps %xmm13, -8-16*3(%rax) + vmovaps %xmm14, -8-16*2(%rax) + vmovaps %xmm15, -8-16*1(%rax) +___ +$code.=<<___; + lea .LIntOne(%rip), %rax + + vmovd $index0, %xmm0 + vmovd $index1, %xmm1 + vmovd $index2, %xmm2 + vmovd $index3, %xmm3 + + vpxor $R0a, $R0a, $R0a + vpxor $R0b, $R0b, $R0b + vpxor $R1a, $R1a, $R1a + vpxor $R1b, $R1b, $R1b + vpxor $R2a, $R2a, $R2a + vpxor $R2b, $R2b, $R2b + vpxor $R3a, $R3a, $R3a + vpxor $R3b, $R3b, $R3b + vmovdqa (%rax), $M0 + + vpermd $INDEX0, $R0a, $INDEX0 + vpermd $INDEX1, $R0a, $INDEX1 + vpermd $INDEX2, $R0a, $INDEX2 + vpermd $INDEX3, $R0a, $INDEX3 + + mov \$64, %ecx + lea 112($val), $val # size optimization + jmp .Lmulti_select_loop_avx2 + +# INDEX=0, corresponds to the point at infty (0,0) +.align 32 +.Lmulti_select_loop_avx2: + vpcmpeqd $INDEX0, $M0, $TMP0 + + vmovdqa `32*0+32*64*2*0`($in_t), $T0 + vmovdqa `32*1+32*64*2*0`($in_t), $T1 + vpand $TMP0, $T0, $T0 + vpand $TMP0, $T1, $T1 + vpxor $T0, $R0a, $R0a + vpxor $T1, $R0b, $R0b + + vpcmpeqd $INDEX1, $M0, $TMP0 + + vmovdqa `32*0+32*64*2*1`($in_t), $T0 + vmovdqa `32*1+32*64*2*1`($in_t), $T1 + vpand $TMP0, $T0, $T0 + vpand $TMP0, $T1, $T1 + vpxor $T0, $R1a, $R1a + vpxor $T1, $R1b, $R1b + + vpcmpeqd $INDEX2, $M0, $TMP0 + + vmovdqa `32*0+32*64*2*2`($in_t), $T0 + vmovdqa `32*1+32*64*2*2`($in_t), $T1 + vpand $TMP0, $T0, $T0 + vpand $TMP0, $T1, $T1 + vpxor $T0, $R2a, $R2a + vpxor $T1, $R2b, $R2b + + vpcmpeqd $INDEX3, $M0, $TMP0 + + vmovdqa `32*0+32*64*2*3`($in_t), $T0 + vmovdqa `32*1+32*64*2*3`($in_t), $T1 + vpand $TMP0, $T0, $T0 + vpand $TMP0, $T1, $T1 + vpxor $T0, $R3a, $R3a + vpxor $T1, $R3b, $R3b + + vpaddd (%rax), $M0, $M0 # increment + lea 32*2($in_t), $in_t + + dec %ecx + jnz .Lmulti_select_loop_avx2 + + vmovdqu $R0a, 32*0-112($val) + vmovdqu $R0b, 32*1-112($val) + vmovdqu $R1a, 32*2-112($val) + vmovdqu $R1b, 32*3-112($val) + vmovdqu $R2a, 32*4-112($val) + vmovdqu $R2b, 32*5-112($val) + vmovdqu $R3a, 32*6-112($val) + vmovdqu $R3b, 32*7-112($val) + + vzeroupper +___ +$code.=<<___ if ($win64); + movaps 16*0(%rsp), %xmm6 + movaps 16*1(%rsp), %xmm7 + movaps 16*2(%rsp), %xmm8 + movaps 16*3(%rsp), %xmm9 + movaps 16*4(%rsp), %xmm10 + movaps 16*5(%rsp), %xmm11 + movaps 16*6(%rsp), %xmm12 + movaps 16*7(%rsp), %xmm13 + movaps 16*8(%rsp), %xmm14 + movaps 16*9(%rsp), %xmm15 + lea 8+16*10(%rsp), %rsp +___ +$code.=<<___; + ret +.size ecp_nistz256_avx2_multi_gather_w7,.-ecp_nistz256_avx2_multi_gather_w7 + +.extern OPENSSL_ia32cap_P +.globl ecp_nistz_avx2_eligible +.type ecp_nistz_avx2_eligible,\@abi-omnipotent +.align 32 +ecp_nistz_avx2_eligible: + mov OPENSSL_ia32cap_P+8(%rip),%eax + shr \$5,%eax + and \$1,%eax + ret +.size ecp_nistz_avx2_eligible,.-ecp_nistz_avx2_eligible +___ +} +}} else {{ # assembler is too old +$code.=<<___; +.text + +.globl ecp_nistz256_avx2_transpose_convert +.globl ecp_nistz256_avx2_convert_transpose_back +.globl ecp_nistz256_avx2_point_add_affine_x4 +.globl ecp_nistz256_avx2_point_add_affines_x4 +.globl ecp_nistz256_avx2_to_mont +.globl ecp_nistz256_avx2_from_mont +.globl ecp_nistz256_avx2_set1 +.globl ecp_nistz256_avx2_multi_gather_w7 +.type ecp_nistz256_avx2_multi_gather_w7,\@abi-omnipotent +ecp_nistz256_avx2_transpose_convert: +ecp_nistz256_avx2_convert_transpose_back: +ecp_nistz256_avx2_point_add_affine_x4: +ecp_nistz256_avx2_point_add_affines_x4: +ecp_nistz256_avx2_to_mont: +ecp_nistz256_avx2_from_mont: +ecp_nistz256_avx2_set1: +ecp_nistz256_avx2_multi_gather_w7: + .byte 0x0f,0x0b # ud2 + ret +.size ecp_nistz256_avx2_multi_gather_w7,.-ecp_nistz256_avx2_multi_gather_w7 + +.globl ecp_nistz_avx2_eligible +.type ecp_nistz_avx2_eligible,\@abi-omnipotent +ecp_nistz_avx2_eligible: + xor %eax,%eax + ret +.size ecp_nistz_avx2_eligible,.-ecp_nistz_avx2_eligible +___ +}} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval($1)/geo; + + print $_,"\n"; +} + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/ecp_nistz256-ppc64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/ecp_nistz256-ppc64.pl new file mode 100755 index 000000000..984c7f205 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/ecp_nistz256-ppc64.pl @@ -0,0 +1,2382 @@ +#! /usr/bin/env perl +# Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# ECP_NISTZ256 module for PPC64. +# +# August 2016. +# +# Original ECP_NISTZ256 submission targeting x86_64 is detailed in +# http://eprint.iacr.org/2013/816. +# +# with/without -DECP_NISTZ256_ASM +# POWER7 +260-530% +# POWER8 +220-340% + +$flavour = shift; +while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or +die "can't locate ppc-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +my $sp="r1"; + +{ +my ($rp,$ap,$bp,$bi,$acc0,$acc1,$acc2,$acc3,$poly1,$poly3, + $acc4,$acc5,$a0,$a1,$a2,$a3,$t0,$t1,$t2,$t3) = + map("r$_",(3..12,22..31)); + +my ($acc6,$acc7)=($bp,$bi); # used in __ecp_nistz256_sqr_mont + +$code.=<<___; +.machine "any" +.text +___ +######################################################################## +# Convert ecp_nistz256_table.c to layout expected by ecp_nistz_gather_w7 +# +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +open TABLE,") { + s/TOBN\(\s*(0x[0-9a-f]+),\s*(0x[0-9a-f]+)\s*\)/push @arr,hex($2),hex($1)/geo; +} +close TABLE; + +# See ecp_nistz256_table.c for explanation for why it's 64*16*37. +# 64*16*37-1 is because $#arr returns last valid index or @arr, not +# amount of elements. +die "insane number of elements" if ($#arr != 64*16*37-1); + +$code.=<<___; +.type ecp_nistz256_precomputed,\@object +.globl ecp_nistz256_precomputed +.align 12 +ecp_nistz256_precomputed: +___ +######################################################################## +# this conversion smashes P256_POINT_AFFINE by individual bytes with +# 64 byte interval, similar to +# 1111222233334444 +# 1234123412341234 +for(1..37) { + @tbl = splice(@arr,0,64*16); + for($i=0;$i<64;$i++) { + undef @line; + for($j=0;$j<64;$j++) { + push @line,(@tbl[$j*16+$i/4]>>(($i%4)*8))&0xff; + } + $code.=".byte\t"; + $code.=join(',',map { sprintf "0x%02x",$_} @line); + $code.="\n"; + } +} + +$code.=<<___; +.size ecp_nistz256_precomputed,.-ecp_nistz256_precomputed +.asciz "ECP_NISTZ256 for PPC64, CRYPTOGAMS by " + +# void ecp_nistz256_mul_mont(BN_ULONG x0[4],const BN_ULONG x1[4], +# const BN_ULONG x2[4]); +.globl ecp_nistz256_mul_mont +.align 5 +ecp_nistz256_mul_mont: + stdu $sp,-128($sp) + mflr r0 + std r22,48($sp) + std r23,56($sp) + std r24,64($sp) + std r25,72($sp) + std r26,80($sp) + std r27,88($sp) + std r28,96($sp) + std r29,104($sp) + std r30,112($sp) + std r31,120($sp) + + ld $a0,0($ap) + ld $bi,0($bp) + ld $a1,8($ap) + ld $a2,16($ap) + ld $a3,24($ap) + + li $poly1,-1 + srdi $poly1,$poly1,32 # 0x00000000ffffffff + li $poly3,1 + orc $poly3,$poly3,$poly1 # 0xffffffff00000001 + + bl __ecp_nistz256_mul_mont + + mtlr r0 + ld r22,48($sp) + ld r23,56($sp) + ld r24,64($sp) + ld r25,72($sp) + ld r26,80($sp) + ld r27,88($sp) + ld r28,96($sp) + ld r29,104($sp) + ld r30,112($sp) + ld r31,120($sp) + addi $sp,$sp,128 + blr + .long 0 + .byte 0,12,4,0,0x80,10,3,0 + .long 0 +.size ecp_nistz256_mul_mont,.-ecp_nistz256_mul_mont + +# void ecp_nistz256_sqr_mont(BN_ULONG x0[4],const BN_ULONG x1[4]); +.globl ecp_nistz256_sqr_mont +.align 4 +ecp_nistz256_sqr_mont: + stdu $sp,-128($sp) + mflr r0 + std r22,48($sp) + std r23,56($sp) + std r24,64($sp) + std r25,72($sp) + std r26,80($sp) + std r27,88($sp) + std r28,96($sp) + std r29,104($sp) + std r30,112($sp) + std r31,120($sp) + + ld $a0,0($ap) + ld $a1,8($ap) + ld $a2,16($ap) + ld $a3,24($ap) + + li $poly1,-1 + srdi $poly1,$poly1,32 # 0x00000000ffffffff + li $poly3,1 + orc $poly3,$poly3,$poly1 # 0xffffffff00000001 + + bl __ecp_nistz256_sqr_mont + + mtlr r0 + ld r22,48($sp) + ld r23,56($sp) + ld r24,64($sp) + ld r25,72($sp) + ld r26,80($sp) + ld r27,88($sp) + ld r28,96($sp) + ld r29,104($sp) + ld r30,112($sp) + ld r31,120($sp) + addi $sp,$sp,128 + blr + .long 0 + .byte 0,12,4,0,0x80,10,2,0 + .long 0 +.size ecp_nistz256_sqr_mont,.-ecp_nistz256_sqr_mont + +# void ecp_nistz256_add(BN_ULONG x0[4],const BN_ULONG x1[4], +# const BN_ULONG x2[4]); +.globl ecp_nistz256_add +.align 4 +ecp_nistz256_add: + stdu $sp,-128($sp) + mflr r0 + std r28,96($sp) + std r29,104($sp) + std r30,112($sp) + std r31,120($sp) + + ld $acc0,0($ap) + ld $t0, 0($bp) + ld $acc1,8($ap) + ld $t1, 8($bp) + ld $acc2,16($ap) + ld $t2, 16($bp) + ld $acc3,24($ap) + ld $t3, 24($bp) + + li $poly1,-1 + srdi $poly1,$poly1,32 # 0x00000000ffffffff + li $poly3,1 + orc $poly3,$poly3,$poly1 # 0xffffffff00000001 + + bl __ecp_nistz256_add + + mtlr r0 + ld r28,96($sp) + ld r29,104($sp) + ld r30,112($sp) + ld r31,120($sp) + addi $sp,$sp,128 + blr + .long 0 + .byte 0,12,4,0,0x80,4,3,0 + .long 0 +.size ecp_nistz256_add,.-ecp_nistz256_add + +# void ecp_nistz256_div_by_2(BN_ULONG x0[4],const BN_ULONG x1[4]); +.globl ecp_nistz256_div_by_2 +.align 4 +ecp_nistz256_div_by_2: + stdu $sp,-128($sp) + mflr r0 + std r28,96($sp) + std r29,104($sp) + std r30,112($sp) + std r31,120($sp) + + ld $acc0,0($ap) + ld $acc1,8($ap) + ld $acc2,16($ap) + ld $acc3,24($ap) + + li $poly1,-1 + srdi $poly1,$poly1,32 # 0x00000000ffffffff + li $poly3,1 + orc $poly3,$poly3,$poly1 # 0xffffffff00000001 + + bl __ecp_nistz256_div_by_2 + + mtlr r0 + ld r28,96($sp) + ld r29,104($sp) + ld r30,112($sp) + ld r31,120($sp) + addi $sp,$sp,128 + blr + .long 0 + .byte 0,12,4,0,0x80,4,2,0 + .long 0 +.size ecp_nistz256_div_by_2,.-ecp_nistz256_div_by_2 + +# void ecp_nistz256_mul_by_2(BN_ULONG x0[4],const BN_ULONG x1[4]); +.globl ecp_nistz256_mul_by_2 +.align 4 +ecp_nistz256_mul_by_2: + stdu $sp,-128($sp) + mflr r0 + std r28,96($sp) + std r29,104($sp) + std r30,112($sp) + std r31,120($sp) + + ld $acc0,0($ap) + ld $acc1,8($ap) + ld $acc2,16($ap) + ld $acc3,24($ap) + + mr $t0,$acc0 + mr $t1,$acc1 + mr $t2,$acc2 + mr $t3,$acc3 + + li $poly1,-1 + srdi $poly1,$poly1,32 # 0x00000000ffffffff + li $poly3,1 + orc $poly3,$poly3,$poly1 # 0xffffffff00000001 + + bl __ecp_nistz256_add # ret = a+a // 2*a + + mtlr r0 + ld r28,96($sp) + ld r29,104($sp) + ld r30,112($sp) + ld r31,120($sp) + addi $sp,$sp,128 + blr + .long 0 + .byte 0,12,4,0,0x80,4,3,0 + .long 0 +.size ecp_nistz256_mul_by_2,.-ecp_nistz256_mul_by_2 + +# void ecp_nistz256_mul_by_3(BN_ULONG x0[4],const BN_ULONG x1[4]); +.globl ecp_nistz256_mul_by_3 +.align 4 +ecp_nistz256_mul_by_3: + stdu $sp,-128($sp) + mflr r0 + std r28,96($sp) + std r29,104($sp) + std r30,112($sp) + std r31,120($sp) + + ld $acc0,0($ap) + ld $acc1,8($ap) + ld $acc2,16($ap) + ld $acc3,24($ap) + + mr $t0,$acc0 + std $acc0,64($sp) + mr $t1,$acc1 + std $acc1,72($sp) + mr $t2,$acc2 + std $acc2,80($sp) + mr $t3,$acc3 + std $acc3,88($sp) + + li $poly1,-1 + srdi $poly1,$poly1,32 # 0x00000000ffffffff + li $poly3,1 + orc $poly3,$poly3,$poly1 # 0xffffffff00000001 + + bl __ecp_nistz256_add # ret = a+a // 2*a + + ld $t0,64($sp) + ld $t1,72($sp) + ld $t2,80($sp) + ld $t3,88($sp) + + bl __ecp_nistz256_add # ret += a // 2*a+a=3*a + + mtlr r0 + ld r28,96($sp) + ld r29,104($sp) + ld r30,112($sp) + ld r31,120($sp) + addi $sp,$sp,128 + blr + .long 0 + .byte 0,12,4,0,0x80,4,2,0 + .long 0 +.size ecp_nistz256_mul_by_3,.-ecp_nistz256_mul_by_3 + +# void ecp_nistz256_sub(BN_ULONG x0[4],const BN_ULONG x1[4], +# const BN_ULONG x2[4]); +.globl ecp_nistz256_sub +.align 4 +ecp_nistz256_sub: + stdu $sp,-128($sp) + mflr r0 + std r28,96($sp) + std r29,104($sp) + std r30,112($sp) + std r31,120($sp) + + ld $acc0,0($ap) + ld $acc1,8($ap) + ld $acc2,16($ap) + ld $acc3,24($ap) + + li $poly1,-1 + srdi $poly1,$poly1,32 # 0x00000000ffffffff + li $poly3,1 + orc $poly3,$poly3,$poly1 # 0xffffffff00000001 + + bl __ecp_nistz256_sub_from + + mtlr r0 + ld r28,96($sp) + ld r29,104($sp) + ld r30,112($sp) + ld r31,120($sp) + addi $sp,$sp,128 + blr + .long 0 + .byte 0,12,4,0,0x80,4,3,0 + .long 0 +.size ecp_nistz256_sub,.-ecp_nistz256_sub + +# void ecp_nistz256_neg(BN_ULONG x0[4],const BN_ULONG x1[4]); +.globl ecp_nistz256_neg +.align 4 +ecp_nistz256_neg: + stdu $sp,-128($sp) + mflr r0 + std r28,96($sp) + std r29,104($sp) + std r30,112($sp) + std r31,120($sp) + + mr $bp,$ap + li $acc0,0 + li $acc1,0 + li $acc2,0 + li $acc3,0 + + li $poly1,-1 + srdi $poly1,$poly1,32 # 0x00000000ffffffff + li $poly3,1 + orc $poly3,$poly3,$poly1 # 0xffffffff00000001 + + bl __ecp_nistz256_sub_from + + mtlr r0 + ld r28,96($sp) + ld r29,104($sp) + ld r30,112($sp) + ld r31,120($sp) + addi $sp,$sp,128 + blr + .long 0 + .byte 0,12,4,0,0x80,4,2,0 + .long 0 +.size ecp_nistz256_neg,.-ecp_nistz256_neg + +# note that __ecp_nistz256_mul_mont expects a[0-3] input pre-loaded +# to $a0-$a3 and b[0] - to $bi +.type __ecp_nistz256_mul_mont,\@function +.align 4 +__ecp_nistz256_mul_mont: + mulld $acc0,$a0,$bi # a[0]*b[0] + mulhdu $t0,$a0,$bi + + mulld $acc1,$a1,$bi # a[1]*b[0] + mulhdu $t1,$a1,$bi + + mulld $acc2,$a2,$bi # a[2]*b[0] + mulhdu $t2,$a2,$bi + + mulld $acc3,$a3,$bi # a[3]*b[0] + mulhdu $t3,$a3,$bi + ld $bi,8($bp) # b[1] + + addc $acc1,$acc1,$t0 # accumulate high parts of multiplication + sldi $t0,$acc0,32 + adde $acc2,$acc2,$t1 + srdi $t1,$acc0,32 + adde $acc3,$acc3,$t2 + addze $acc4,$t3 + li $acc5,0 +___ +for($i=1;$i<4;$i++) { + ################################################################ + # Reduction iteration is normally performed by accumulating + # result of multiplication of modulus by "magic" digit [and + # omitting least significant word, which is guaranteed to + # be 0], but thanks to special form of modulus and "magic" + # digit being equal to least significant word, it can be + # performed with additions and subtractions alone. Indeed: + # + # ffff0001.00000000.0000ffff.ffffffff + # * abcdefgh + # + xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx.abcdefgh + # + # Now observing that ff..ff*x = (2^n-1)*x = 2^n*x-x, we + # rewrite above as: + # + # xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx.abcdefgh + # + abcdefgh.abcdefgh.0000abcd.efgh0000.00000000 + # - 0000abcd.efgh0000.00000000.00000000.abcdefgh + # + # or marking redundant operations: + # + # xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx.-------- + # + abcdefgh.abcdefgh.0000abcd.efgh0000.-------- + # - 0000abcd.efgh0000.--------.--------.-------- + +$code.=<<___; + subfc $t2,$t0,$acc0 # "*0xffff0001" + subfe $t3,$t1,$acc0 + addc $acc0,$acc1,$t0 # +=acc[0]<<96 and omit acc[0] + adde $acc1,$acc2,$t1 + adde $acc2,$acc3,$t2 # +=acc[0]*0xffff0001 + adde $acc3,$acc4,$t3 + addze $acc4,$acc5 + + mulld $t0,$a0,$bi # lo(a[0]*b[i]) + mulld $t1,$a1,$bi # lo(a[1]*b[i]) + mulld $t2,$a2,$bi # lo(a[2]*b[i]) + mulld $t3,$a3,$bi # lo(a[3]*b[i]) + addc $acc0,$acc0,$t0 # accumulate low parts of multiplication + mulhdu $t0,$a0,$bi # hi(a[0]*b[i]) + adde $acc1,$acc1,$t1 + mulhdu $t1,$a1,$bi # hi(a[1]*b[i]) + adde $acc2,$acc2,$t2 + mulhdu $t2,$a2,$bi # hi(a[2]*b[i]) + adde $acc3,$acc3,$t3 + mulhdu $t3,$a3,$bi # hi(a[3]*b[i]) + addze $acc4,$acc4 +___ +$code.=<<___ if ($i<3); + ld $bi,8*($i+1)($bp) # b[$i+1] +___ +$code.=<<___; + addc $acc1,$acc1,$t0 # accumulate high parts of multiplication + sldi $t0,$acc0,32 + adde $acc2,$acc2,$t1 + srdi $t1,$acc0,32 + adde $acc3,$acc3,$t2 + adde $acc4,$acc4,$t3 + li $acc5,0 + addze $acc5,$acc5 +___ +} +$code.=<<___; + # last reduction + subfc $t2,$t0,$acc0 # "*0xffff0001" + subfe $t3,$t1,$acc0 + addc $acc0,$acc1,$t0 # +=acc[0]<<96 and omit acc[0] + adde $acc1,$acc2,$t1 + adde $acc2,$acc3,$t2 # +=acc[0]*0xffff0001 + adde $acc3,$acc4,$t3 + addze $acc4,$acc5 + + li $t2,0 + addic $acc0,$acc0,1 # ret -= modulus + subfe $acc1,$poly1,$acc1 + subfe $acc2,$t2,$acc2 + subfe $acc3,$poly3,$acc3 + subfe $acc4,$t2,$acc4 + + addc $acc0,$acc0,$acc4 # ret += modulus if borrow + and $t1,$poly1,$acc4 + and $t3,$poly3,$acc4 + adde $acc1,$acc1,$t1 + addze $acc2,$acc2 + adde $acc3,$acc3,$t3 + + std $acc0,0($rp) + std $acc1,8($rp) + std $acc2,16($rp) + std $acc3,24($rp) + + blr + .long 0 + .byte 0,12,0x14,0,0,0,1,0 + .long 0 +.size __ecp_nistz256_mul_mont,.-__ecp_nistz256_mul_mont + +# note that __ecp_nistz256_sqr_mont expects a[0-3] input pre-loaded +# to $a0-$a3 +.type __ecp_nistz256_sqr_mont,\@function +.align 4 +__ecp_nistz256_sqr_mont: + ################################################################ + # | | | | | |a1*a0| | + # | | | | |a2*a0| | | + # | |a3*a2|a3*a0| | | | + # | | | |a2*a1| | | | + # | | |a3*a1| | | | | + # *| | | | | | | | 2| + # +|a3*a3|a2*a2|a1*a1|a0*a0| + # |--+--+--+--+--+--+--+--| + # |A7|A6|A5|A4|A3|A2|A1|A0|, where Ax is $accx, i.e. follow $accx + # + # "can't overflow" below mark carrying into high part of + # multiplication result, which can't overflow, because it + # can never be all ones. + + mulld $acc1,$a1,$a0 # a[1]*a[0] + mulhdu $t1,$a1,$a0 + mulld $acc2,$a2,$a0 # a[2]*a[0] + mulhdu $t2,$a2,$a0 + mulld $acc3,$a3,$a0 # a[3]*a[0] + mulhdu $acc4,$a3,$a0 + + addc $acc2,$acc2,$t1 # accumulate high parts of multiplication + mulld $t0,$a2,$a1 # a[2]*a[1] + mulhdu $t1,$a2,$a1 + adde $acc3,$acc3,$t2 + mulld $t2,$a3,$a1 # a[3]*a[1] + mulhdu $t3,$a3,$a1 + addze $acc4,$acc4 # can't overflow + + mulld $acc5,$a3,$a2 # a[3]*a[2] + mulhdu $acc6,$a3,$a2 + + addc $t1,$t1,$t2 # accumulate high parts of multiplication + addze $t2,$t3 # can't overflow + + addc $acc3,$acc3,$t0 # accumulate low parts of multiplication + adde $acc4,$acc4,$t1 + adde $acc5,$acc5,$t2 + addze $acc6,$acc6 # can't overflow + + addc $acc1,$acc1,$acc1 # acc[1-6]*=2 + adde $acc2,$acc2,$acc2 + adde $acc3,$acc3,$acc3 + adde $acc4,$acc4,$acc4 + adde $acc5,$acc5,$acc5 + adde $acc6,$acc6,$acc6 + li $acc7,0 + addze $acc7,$acc7 + + mulld $acc0,$a0,$a0 # a[0]*a[0] + mulhdu $a0,$a0,$a0 + mulld $t1,$a1,$a1 # a[1]*a[1] + mulhdu $a1,$a1,$a1 + mulld $t2,$a2,$a2 # a[2]*a[2] + mulhdu $a2,$a2,$a2 + mulld $t3,$a3,$a3 # a[3]*a[3] + mulhdu $a3,$a3,$a3 + addc $acc1,$acc1,$a0 # +a[i]*a[i] + sldi $t0,$acc0,32 + adde $acc2,$acc2,$t1 + srdi $t1,$acc0,32 + adde $acc3,$acc3,$a1 + adde $acc4,$acc4,$t2 + adde $acc5,$acc5,$a2 + adde $acc6,$acc6,$t3 + adde $acc7,$acc7,$a3 +___ +for($i=0;$i<3;$i++) { # reductions, see commentary in + # multiplication for details +$code.=<<___; + subfc $t2,$t0,$acc0 # "*0xffff0001" + subfe $t3,$t1,$acc0 + addc $acc0,$acc1,$t0 # +=acc[0]<<96 and omit acc[0] + sldi $t0,$acc0,32 + adde $acc1,$acc2,$t1 + srdi $t1,$acc0,32 + adde $acc2,$acc3,$t2 # +=acc[0]*0xffff0001 + addze $acc3,$t3 # can't overflow +___ +} +$code.=<<___; + subfc $t2,$t0,$acc0 # "*0xffff0001" + subfe $t3,$t1,$acc0 + addc $acc0,$acc1,$t0 # +=acc[0]<<96 and omit acc[0] + adde $acc1,$acc2,$t1 + adde $acc2,$acc3,$t2 # +=acc[0]*0xffff0001 + addze $acc3,$t3 # can't overflow + + addc $acc0,$acc0,$acc4 # accumulate upper half + adde $acc1,$acc1,$acc5 + adde $acc2,$acc2,$acc6 + adde $acc3,$acc3,$acc7 + li $t2,0 + addze $acc4,$t2 + + addic $acc0,$acc0,1 # ret -= modulus + subfe $acc1,$poly1,$acc1 + subfe $acc2,$t2,$acc2 + subfe $acc3,$poly3,$acc3 + subfe $acc4,$t2,$acc4 + + addc $acc0,$acc0,$acc4 # ret += modulus if borrow + and $t1,$poly1,$acc4 + and $t3,$poly3,$acc4 + adde $acc1,$acc1,$t1 + addze $acc2,$acc2 + adde $acc3,$acc3,$t3 + + std $acc0,0($rp) + std $acc1,8($rp) + std $acc2,16($rp) + std $acc3,24($rp) + + blr + .long 0 + .byte 0,12,0x14,0,0,0,1,0 + .long 0 +.size __ecp_nistz256_sqr_mont,.-__ecp_nistz256_sqr_mont + +# Note that __ecp_nistz256_add expects both input vectors pre-loaded to +# $a0-$a3 and $t0-$t3. This is done because it's used in multiple +# contexts, e.g. in multiplication by 2 and 3... +.type __ecp_nistz256_add,\@function +.align 4 +__ecp_nistz256_add: + addc $acc0,$acc0,$t0 # ret = a+b + adde $acc1,$acc1,$t1 + adde $acc2,$acc2,$t2 + li $t2,0 + adde $acc3,$acc3,$t3 + addze $t0,$t2 + + # if a+b >= modulus, subtract modulus + # + # But since comparison implies subtraction, we subtract + # modulus and then add it back if subtraction borrowed. + + subic $acc0,$acc0,-1 + subfe $acc1,$poly1,$acc1 + subfe $acc2,$t2,$acc2 + subfe $acc3,$poly3,$acc3 + subfe $t0,$t2,$t0 + + addc $acc0,$acc0,$t0 + and $t1,$poly1,$t0 + and $t3,$poly3,$t0 + adde $acc1,$acc1,$t1 + addze $acc2,$acc2 + adde $acc3,$acc3,$t3 + + std $acc0,0($rp) + std $acc1,8($rp) + std $acc2,16($rp) + std $acc3,24($rp) + + blr + .long 0 + .byte 0,12,0x14,0,0,0,3,0 + .long 0 +.size __ecp_nistz256_add,.-__ecp_nistz256_add + +.type __ecp_nistz256_sub_from,\@function +.align 4 +__ecp_nistz256_sub_from: + ld $t0,0($bp) + ld $t1,8($bp) + ld $t2,16($bp) + ld $t3,24($bp) + subfc $acc0,$t0,$acc0 # ret = a-b + subfe $acc1,$t1,$acc1 + subfe $acc2,$t2,$acc2 + subfe $acc3,$t3,$acc3 + subfe $t0,$t0,$t0 # t0 = borrow ? -1 : 0 + + # if a-b borrowed, add modulus + + addc $acc0,$acc0,$t0 # ret -= modulus & t0 + and $t1,$poly1,$t0 + and $t3,$poly3,$t0 + adde $acc1,$acc1,$t1 + addze $acc2,$acc2 + adde $acc3,$acc3,$t3 + + std $acc0,0($rp) + std $acc1,8($rp) + std $acc2,16($rp) + std $acc3,24($rp) + + blr + .long 0 + .byte 0,12,0x14,0,0,0,3,0 + .long 0 +.size __ecp_nistz256_sub_from,.-__ecp_nistz256_sub_from + +.type __ecp_nistz256_sub_morf,\@function +.align 4 +__ecp_nistz256_sub_morf: + ld $t0,0($bp) + ld $t1,8($bp) + ld $t2,16($bp) + ld $t3,24($bp) + subfc $acc0,$acc0,$t0 # ret = b-a + subfe $acc1,$acc1,$t1 + subfe $acc2,$acc2,$t2 + subfe $acc3,$acc3,$t3 + subfe $t0,$t0,$t0 # t0 = borrow ? -1 : 0 + + # if b-a borrowed, add modulus + + addc $acc0,$acc0,$t0 # ret -= modulus & t0 + and $t1,$poly1,$t0 + and $t3,$poly3,$t0 + adde $acc1,$acc1,$t1 + addze $acc2,$acc2 + adde $acc3,$acc3,$t3 + + std $acc0,0($rp) + std $acc1,8($rp) + std $acc2,16($rp) + std $acc3,24($rp) + + blr + .long 0 + .byte 0,12,0x14,0,0,0,3,0 + .long 0 +.size __ecp_nistz256_sub_morf,.-__ecp_nistz256_sub_morf + +.type __ecp_nistz256_div_by_2,\@function +.align 4 +__ecp_nistz256_div_by_2: + andi. $t0,$acc0,1 + addic $acc0,$acc0,-1 # a += modulus + neg $t0,$t0 + adde $acc1,$acc1,$poly1 + not $t0,$t0 + addze $acc2,$acc2 + li $t2,0 + adde $acc3,$acc3,$poly3 + and $t1,$poly1,$t0 + addze $ap,$t2 # ap = carry + and $t3,$poly3,$t0 + + subfc $acc0,$t0,$acc0 # a -= modulus if a was even + subfe $acc1,$t1,$acc1 + subfe $acc2,$t2,$acc2 + subfe $acc3,$t3,$acc3 + subfe $ap, $t2,$ap + + srdi $acc0,$acc0,1 + sldi $t0,$acc1,63 + srdi $acc1,$acc1,1 + sldi $t1,$acc2,63 + srdi $acc2,$acc2,1 + sldi $t2,$acc3,63 + srdi $acc3,$acc3,1 + sldi $t3,$ap,63 + or $acc0,$acc0,$t0 + or $acc1,$acc1,$t1 + or $acc2,$acc2,$t2 + or $acc3,$acc3,$t3 + + std $acc0,0($rp) + std $acc1,8($rp) + std $acc2,16($rp) + std $acc3,24($rp) + + blr + .long 0 + .byte 0,12,0x14,0,0,0,1,0 + .long 0 +.size __ecp_nistz256_div_by_2,.-__ecp_nistz256_div_by_2 +___ +######################################################################## +# following subroutines are "literal" implementation of those found in +# ecp_nistz256.c +# +######################################################################## +# void ecp_nistz256_point_double(P256_POINT *out,const P256_POINT *inp); +# +if (1) { +my $FRAME=64+32*4+12*8; +my ($S,$M,$Zsqr,$tmp0)=map(64+32*$_,(0..3)); +# above map() describes stack layout with 4 temporary +# 256-bit vectors on top. +my ($rp_real,$ap_real) = map("r$_",(20,21)); + +$code.=<<___; +.globl ecp_nistz256_point_double +.align 5 +ecp_nistz256_point_double: + stdu $sp,-$FRAME($sp) + mflr r0 + std r20,$FRAME-8*12($sp) + std r21,$FRAME-8*11($sp) + std r22,$FRAME-8*10($sp) + std r23,$FRAME-8*9($sp) + std r24,$FRAME-8*8($sp) + std r25,$FRAME-8*7($sp) + std r26,$FRAME-8*6($sp) + std r27,$FRAME-8*5($sp) + std r28,$FRAME-8*4($sp) + std r29,$FRAME-8*3($sp) + std r30,$FRAME-8*2($sp) + std r31,$FRAME-8*1($sp) + + li $poly1,-1 + srdi $poly1,$poly1,32 # 0x00000000ffffffff + li $poly3,1 + orc $poly3,$poly3,$poly1 # 0xffffffff00000001 +.Ldouble_shortcut: + ld $acc0,32($ap) + ld $acc1,40($ap) + ld $acc2,48($ap) + ld $acc3,56($ap) + mr $t0,$acc0 + mr $t1,$acc1 + mr $t2,$acc2 + mr $t3,$acc3 + ld $a0,64($ap) # forward load for p256_sqr_mont + ld $a1,72($ap) + ld $a2,80($ap) + ld $a3,88($ap) + mr $rp_real,$rp + mr $ap_real,$ap + addi $rp,$sp,$S + bl __ecp_nistz256_add # p256_mul_by_2(S, in_y); + + addi $rp,$sp,$Zsqr + bl __ecp_nistz256_sqr_mont # p256_sqr_mont(Zsqr, in_z); + + ld $t0,0($ap_real) + ld $t1,8($ap_real) + ld $t2,16($ap_real) + ld $t3,24($ap_real) + mr $a0,$acc0 # put Zsqr aside for p256_sub + mr $a1,$acc1 + mr $a2,$acc2 + mr $a3,$acc3 + addi $rp,$sp,$M + bl __ecp_nistz256_add # p256_add(M, Zsqr, in_x); + + addi $bp,$ap_real,0 + mr $acc0,$a0 # restore Zsqr + mr $acc1,$a1 + mr $acc2,$a2 + mr $acc3,$a3 + ld $a0,$S+0($sp) # forward load for p256_sqr_mont + ld $a1,$S+8($sp) + ld $a2,$S+16($sp) + ld $a3,$S+24($sp) + addi $rp,$sp,$Zsqr + bl __ecp_nistz256_sub_morf # p256_sub(Zsqr, in_x, Zsqr); + + addi $rp,$sp,$S + bl __ecp_nistz256_sqr_mont # p256_sqr_mont(S, S); + + ld $bi,32($ap_real) + ld $a0,64($ap_real) + ld $a1,72($ap_real) + ld $a2,80($ap_real) + ld $a3,88($ap_real) + addi $bp,$ap_real,32 + addi $rp,$sp,$tmp0 + bl __ecp_nistz256_mul_mont # p256_mul_mont(tmp0, in_z, in_y); + + mr $t0,$acc0 + mr $t1,$acc1 + mr $t2,$acc2 + mr $t3,$acc3 + ld $a0,$S+0($sp) # forward load for p256_sqr_mont + ld $a1,$S+8($sp) + ld $a2,$S+16($sp) + ld $a3,$S+24($sp) + addi $rp,$rp_real,64 + bl __ecp_nistz256_add # p256_mul_by_2(res_z, tmp0); + + addi $rp,$sp,$tmp0 + bl __ecp_nistz256_sqr_mont # p256_sqr_mont(tmp0, S); + + ld $bi,$Zsqr($sp) # forward load for p256_mul_mont + ld $a0,$M+0($sp) + ld $a1,$M+8($sp) + ld $a2,$M+16($sp) + ld $a3,$M+24($sp) + addi $rp,$rp_real,32 + bl __ecp_nistz256_div_by_2 # p256_div_by_2(res_y, tmp0); + + addi $bp,$sp,$Zsqr + addi $rp,$sp,$M + bl __ecp_nistz256_mul_mont # p256_mul_mont(M, M, Zsqr); + + mr $t0,$acc0 # duplicate M + mr $t1,$acc1 + mr $t2,$acc2 + mr $t3,$acc3 + mr $a0,$acc0 # put M aside + mr $a1,$acc1 + mr $a2,$acc2 + mr $a3,$acc3 + addi $rp,$sp,$M + bl __ecp_nistz256_add + mr $t0,$a0 # restore M + mr $t1,$a1 + mr $t2,$a2 + mr $t3,$a3 + ld $bi,0($ap_real) # forward load for p256_mul_mont + ld $a0,$S+0($sp) + ld $a1,$S+8($sp) + ld $a2,$S+16($sp) + ld $a3,$S+24($sp) + bl __ecp_nistz256_add # p256_mul_by_3(M, M); + + addi $bp,$ap_real,0 + addi $rp,$sp,$S + bl __ecp_nistz256_mul_mont # p256_mul_mont(S, S, in_x); + + mr $t0,$acc0 + mr $t1,$acc1 + mr $t2,$acc2 + mr $t3,$acc3 + ld $a0,$M+0($sp) # forward load for p256_sqr_mont + ld $a1,$M+8($sp) + ld $a2,$M+16($sp) + ld $a3,$M+24($sp) + addi $rp,$sp,$tmp0 + bl __ecp_nistz256_add # p256_mul_by_2(tmp0, S); + + addi $rp,$rp_real,0 + bl __ecp_nistz256_sqr_mont # p256_sqr_mont(res_x, M); + + addi $bp,$sp,$tmp0 + bl __ecp_nistz256_sub_from # p256_sub(res_x, res_x, tmp0); + + addi $bp,$sp,$S + addi $rp,$sp,$S + bl __ecp_nistz256_sub_morf # p256_sub(S, S, res_x); + + ld $bi,$M($sp) + mr $a0,$acc0 # copy S + mr $a1,$acc1 + mr $a2,$acc2 + mr $a3,$acc3 + addi $bp,$sp,$M + bl __ecp_nistz256_mul_mont # p256_mul_mont(S, S, M); + + addi $bp,$rp_real,32 + addi $rp,$rp_real,32 + bl __ecp_nistz256_sub_from # p256_sub(res_y, S, res_y); + + mtlr r0 + ld r20,$FRAME-8*12($sp) + ld r21,$FRAME-8*11($sp) + ld r22,$FRAME-8*10($sp) + ld r23,$FRAME-8*9($sp) + ld r24,$FRAME-8*8($sp) + ld r25,$FRAME-8*7($sp) + ld r26,$FRAME-8*6($sp) + ld r27,$FRAME-8*5($sp) + ld r28,$FRAME-8*4($sp) + ld r29,$FRAME-8*3($sp) + ld r30,$FRAME-8*2($sp) + ld r31,$FRAME-8*1($sp) + addi $sp,$sp,$FRAME + blr + .long 0 + .byte 0,12,4,0,0x80,12,2,0 + .long 0 +.size ecp_nistz256_point_double,.-ecp_nistz256_point_double +___ +} + +######################################################################## +# void ecp_nistz256_point_add(P256_POINT *out,const P256_POINT *in1, +# const P256_POINT *in2); +if (1) { +my $FRAME = 64 + 32*12 + 16*8; +my ($res_x,$res_y,$res_z, + $H,$Hsqr,$R,$Rsqr,$Hcub, + $U1,$U2,$S1,$S2)=map(64+32*$_,(0..11)); +my ($Z1sqr, $Z2sqr) = ($Hsqr, $Rsqr); +# above map() describes stack layout with 12 temporary +# 256-bit vectors on top. +my ($rp_real,$ap_real,$bp_real,$in1infty,$in2infty,$temp)=map("r$_",(16..21)); + +$code.=<<___; +.globl ecp_nistz256_point_add +.align 5 +ecp_nistz256_point_add: + stdu $sp,-$FRAME($sp) + mflr r0 + std r16,$FRAME-8*16($sp) + std r17,$FRAME-8*15($sp) + std r18,$FRAME-8*14($sp) + std r19,$FRAME-8*13($sp) + std r20,$FRAME-8*12($sp) + std r21,$FRAME-8*11($sp) + std r22,$FRAME-8*10($sp) + std r23,$FRAME-8*9($sp) + std r24,$FRAME-8*8($sp) + std r25,$FRAME-8*7($sp) + std r26,$FRAME-8*6($sp) + std r27,$FRAME-8*5($sp) + std r28,$FRAME-8*4($sp) + std r29,$FRAME-8*3($sp) + std r30,$FRAME-8*2($sp) + std r31,$FRAME-8*1($sp) + + li $poly1,-1 + srdi $poly1,$poly1,32 # 0x00000000ffffffff + li $poly3,1 + orc $poly3,$poly3,$poly1 # 0xffffffff00000001 + + ld $a0,64($bp) # in2_z + ld $a1,72($bp) + ld $a2,80($bp) + ld $a3,88($bp) + mr $rp_real,$rp + mr $ap_real,$ap + mr $bp_real,$bp + or $t0,$a0,$a1 + or $t2,$a2,$a3 + or $in2infty,$t0,$t2 + neg $t0,$in2infty + or $in2infty,$in2infty,$t0 + sradi $in2infty,$in2infty,63 # !in2infty + addi $rp,$sp,$Z2sqr + bl __ecp_nistz256_sqr_mont # p256_sqr_mont(Z2sqr, in2_z); + + ld $a0,64($ap_real) # in1_z + ld $a1,72($ap_real) + ld $a2,80($ap_real) + ld $a3,88($ap_real) + or $t0,$a0,$a1 + or $t2,$a2,$a3 + or $in1infty,$t0,$t2 + neg $t0,$in1infty + or $in1infty,$in1infty,$t0 + sradi $in1infty,$in1infty,63 # !in1infty + addi $rp,$sp,$Z1sqr + bl __ecp_nistz256_sqr_mont # p256_sqr_mont(Z1sqr, in1_z); + + ld $bi,64($bp_real) + ld $a0,$Z2sqr+0($sp) + ld $a1,$Z2sqr+8($sp) + ld $a2,$Z2sqr+16($sp) + ld $a3,$Z2sqr+24($sp) + addi $bp,$bp_real,64 + addi $rp,$sp,$S1 + bl __ecp_nistz256_mul_mont # p256_mul_mont(S1, Z2sqr, in2_z); + + ld $bi,64($ap_real) + ld $a0,$Z1sqr+0($sp) + ld $a1,$Z1sqr+8($sp) + ld $a2,$Z1sqr+16($sp) + ld $a3,$Z1sqr+24($sp) + addi $bp,$ap_real,64 + addi $rp,$sp,$S2 + bl __ecp_nistz256_mul_mont # p256_mul_mont(S2, Z1sqr, in1_z); + + ld $bi,32($ap_real) + ld $a0,$S1+0($sp) + ld $a1,$S1+8($sp) + ld $a2,$S1+16($sp) + ld $a3,$S1+24($sp) + addi $bp,$ap_real,32 + addi $rp,$sp,$S1 + bl __ecp_nistz256_mul_mont # p256_mul_mont(S1, S1, in1_y); + + ld $bi,32($bp_real) + ld $a0,$S2+0($sp) + ld $a1,$S2+8($sp) + ld $a2,$S2+16($sp) + ld $a3,$S2+24($sp) + addi $bp,$bp_real,32 + addi $rp,$sp,$S2 + bl __ecp_nistz256_mul_mont # p256_mul_mont(S2, S2, in2_y); + + addi $bp,$sp,$S1 + ld $bi,$Z2sqr($sp) # forward load for p256_mul_mont + ld $a0,0($ap_real) + ld $a1,8($ap_real) + ld $a2,16($ap_real) + ld $a3,24($ap_real) + addi $rp,$sp,$R + bl __ecp_nistz256_sub_from # p256_sub(R, S2, S1); + + or $acc0,$acc0,$acc1 # see if result is zero + or $acc2,$acc2,$acc3 + or $temp,$acc0,$acc2 + + addi $bp,$sp,$Z2sqr + addi $rp,$sp,$U1 + bl __ecp_nistz256_mul_mont # p256_mul_mont(U1, in1_x, Z2sqr); + + ld $bi,$Z1sqr($sp) + ld $a0,0($bp_real) + ld $a1,8($bp_real) + ld $a2,16($bp_real) + ld $a3,24($bp_real) + addi $bp,$sp,$Z1sqr + addi $rp,$sp,$U2 + bl __ecp_nistz256_mul_mont # p256_mul_mont(U2, in2_x, Z1sqr); + + addi $bp,$sp,$U1 + ld $a0,$R+0($sp) # forward load for p256_sqr_mont + ld $a1,$R+8($sp) + ld $a2,$R+16($sp) + ld $a3,$R+24($sp) + addi $rp,$sp,$H + bl __ecp_nistz256_sub_from # p256_sub(H, U2, U1); + + or $acc0,$acc0,$acc1 # see if result is zero + or $acc2,$acc2,$acc3 + or. $acc0,$acc0,$acc2 + bne .Ladd_proceed # is_equal(U1,U2)? + + and. $t0,$in1infty,$in2infty + beq .Ladd_proceed # (in1infty || in2infty)? + + cmpldi $temp,0 + beq .Ladd_double # is_equal(S1,S2)? + + xor $a0,$a0,$a0 + std $a0,0($rp_real) + std $a0,8($rp_real) + std $a0,16($rp_real) + std $a0,24($rp_real) + std $a0,32($rp_real) + std $a0,40($rp_real) + std $a0,48($rp_real) + std $a0,56($rp_real) + std $a0,64($rp_real) + std $a0,72($rp_real) + std $a0,80($rp_real) + std $a0,88($rp_real) + b .Ladd_done + +.align 4 +.Ladd_double: + ld $bp,0($sp) # back-link + mr $ap,$ap_real + mr $rp,$rp_real + ld r16,$FRAME-8*16($sp) + ld r17,$FRAME-8*15($sp) + ld r18,$FRAME-8*14($sp) + ld r19,$FRAME-8*13($sp) + stdu $bp,$FRAME-288($sp) # difference in stack frame sizes + b .Ldouble_shortcut + +.align 4 +.Ladd_proceed: + addi $rp,$sp,$Rsqr + bl __ecp_nistz256_sqr_mont # p256_sqr_mont(Rsqr, R); + + ld $bi,64($ap_real) + ld $a0,$H+0($sp) + ld $a1,$H+8($sp) + ld $a2,$H+16($sp) + ld $a3,$H+24($sp) + addi $bp,$ap_real,64 + addi $rp,$sp,$res_z + bl __ecp_nistz256_mul_mont # p256_mul_mont(res_z, H, in1_z); + + ld $a0,$H+0($sp) + ld $a1,$H+8($sp) + ld $a2,$H+16($sp) + ld $a3,$H+24($sp) + addi $rp,$sp,$Hsqr + bl __ecp_nistz256_sqr_mont # p256_sqr_mont(Hsqr, H); + + ld $bi,64($bp_real) + ld $a0,$res_z+0($sp) + ld $a1,$res_z+8($sp) + ld $a2,$res_z+16($sp) + ld $a3,$res_z+24($sp) + addi $bp,$bp_real,64 + addi $rp,$sp,$res_z + bl __ecp_nistz256_mul_mont # p256_mul_mont(res_z, res_z, in2_z); + + ld $bi,$H($sp) + ld $a0,$Hsqr+0($sp) + ld $a1,$Hsqr+8($sp) + ld $a2,$Hsqr+16($sp) + ld $a3,$Hsqr+24($sp) + addi $bp,$sp,$H + addi $rp,$sp,$Hcub + bl __ecp_nistz256_mul_mont # p256_mul_mont(Hcub, Hsqr, H); + + ld $bi,$Hsqr($sp) + ld $a0,$U1+0($sp) + ld $a1,$U1+8($sp) + ld $a2,$U1+16($sp) + ld $a3,$U1+24($sp) + addi $bp,$sp,$Hsqr + addi $rp,$sp,$U2 + bl __ecp_nistz256_mul_mont # p256_mul_mont(U2, U1, Hsqr); + + mr $t0,$acc0 + mr $t1,$acc1 + mr $t2,$acc2 + mr $t3,$acc3 + addi $rp,$sp,$Hsqr + bl __ecp_nistz256_add # p256_mul_by_2(Hsqr, U2); + + addi $bp,$sp,$Rsqr + addi $rp,$sp,$res_x + bl __ecp_nistz256_sub_morf # p256_sub(res_x, Rsqr, Hsqr); + + addi $bp,$sp,$Hcub + bl __ecp_nistz256_sub_from # p256_sub(res_x, res_x, Hcub); + + addi $bp,$sp,$U2 + ld $bi,$Hcub($sp) # forward load for p256_mul_mont + ld $a0,$S1+0($sp) + ld $a1,$S1+8($sp) + ld $a2,$S1+16($sp) + ld $a3,$S1+24($sp) + addi $rp,$sp,$res_y + bl __ecp_nistz256_sub_morf # p256_sub(res_y, U2, res_x); + + addi $bp,$sp,$Hcub + addi $rp,$sp,$S2 + bl __ecp_nistz256_mul_mont # p256_mul_mont(S2, S1, Hcub); + + ld $bi,$R($sp) + ld $a0,$res_y+0($sp) + ld $a1,$res_y+8($sp) + ld $a2,$res_y+16($sp) + ld $a3,$res_y+24($sp) + addi $bp,$sp,$R + addi $rp,$sp,$res_y + bl __ecp_nistz256_mul_mont # p256_mul_mont(res_y, res_y, R); + + addi $bp,$sp,$S2 + bl __ecp_nistz256_sub_from # p256_sub(res_y, res_y, S2); + + ld $t0,0($bp_real) # in2 + ld $t1,8($bp_real) + ld $t2,16($bp_real) + ld $t3,24($bp_real) + ld $a0,$res_x+0($sp) # res + ld $a1,$res_x+8($sp) + ld $a2,$res_x+16($sp) + ld $a3,$res_x+24($sp) +___ +for($i=0;$i<64;$i+=32) { # conditional moves +$code.=<<___; + ld $acc0,$i+0($ap_real) # in1 + ld $acc1,$i+8($ap_real) + ld $acc2,$i+16($ap_real) + ld $acc3,$i+24($ap_real) + andc $t0,$t0,$in1infty + andc $t1,$t1,$in1infty + andc $t2,$t2,$in1infty + andc $t3,$t3,$in1infty + and $a0,$a0,$in1infty + and $a1,$a1,$in1infty + and $a2,$a2,$in1infty + and $a3,$a3,$in1infty + or $t0,$t0,$a0 + or $t1,$t1,$a1 + or $t2,$t2,$a2 + or $t3,$t3,$a3 + andc $acc0,$acc0,$in2infty + andc $acc1,$acc1,$in2infty + andc $acc2,$acc2,$in2infty + andc $acc3,$acc3,$in2infty + and $t0,$t0,$in2infty + and $t1,$t1,$in2infty + and $t2,$t2,$in2infty + and $t3,$t3,$in2infty + or $acc0,$acc0,$t0 + or $acc1,$acc1,$t1 + or $acc2,$acc2,$t2 + or $acc3,$acc3,$t3 + + ld $t0,$i+32($bp_real) # in2 + ld $t1,$i+40($bp_real) + ld $t2,$i+48($bp_real) + ld $t3,$i+56($bp_real) + ld $a0,$res_x+$i+32($sp) + ld $a1,$res_x+$i+40($sp) + ld $a2,$res_x+$i+48($sp) + ld $a3,$res_x+$i+56($sp) + std $acc0,$i+0($rp_real) + std $acc1,$i+8($rp_real) + std $acc2,$i+16($rp_real) + std $acc3,$i+24($rp_real) +___ +} +$code.=<<___; + ld $acc0,$i+0($ap_real) # in1 + ld $acc1,$i+8($ap_real) + ld $acc2,$i+16($ap_real) + ld $acc3,$i+24($ap_real) + andc $t0,$t0,$in1infty + andc $t1,$t1,$in1infty + andc $t2,$t2,$in1infty + andc $t3,$t3,$in1infty + and $a0,$a0,$in1infty + and $a1,$a1,$in1infty + and $a2,$a2,$in1infty + and $a3,$a3,$in1infty + or $t0,$t0,$a0 + or $t1,$t1,$a1 + or $t2,$t2,$a2 + or $t3,$t3,$a3 + andc $acc0,$acc0,$in2infty + andc $acc1,$acc1,$in2infty + andc $acc2,$acc2,$in2infty + andc $acc3,$acc3,$in2infty + and $t0,$t0,$in2infty + and $t1,$t1,$in2infty + and $t2,$t2,$in2infty + and $t3,$t3,$in2infty + or $acc0,$acc0,$t0 + or $acc1,$acc1,$t1 + or $acc2,$acc2,$t2 + or $acc3,$acc3,$t3 + std $acc0,$i+0($rp_real) + std $acc1,$i+8($rp_real) + std $acc2,$i+16($rp_real) + std $acc3,$i+24($rp_real) + +.Ladd_done: + mtlr r0 + ld r16,$FRAME-8*16($sp) + ld r17,$FRAME-8*15($sp) + ld r18,$FRAME-8*14($sp) + ld r19,$FRAME-8*13($sp) + ld r20,$FRAME-8*12($sp) + ld r21,$FRAME-8*11($sp) + ld r22,$FRAME-8*10($sp) + ld r23,$FRAME-8*9($sp) + ld r24,$FRAME-8*8($sp) + ld r25,$FRAME-8*7($sp) + ld r26,$FRAME-8*6($sp) + ld r27,$FRAME-8*5($sp) + ld r28,$FRAME-8*4($sp) + ld r29,$FRAME-8*3($sp) + ld r30,$FRAME-8*2($sp) + ld r31,$FRAME-8*1($sp) + addi $sp,$sp,$FRAME + blr + .long 0 + .byte 0,12,4,0,0x80,16,3,0 + .long 0 +.size ecp_nistz256_point_add,.-ecp_nistz256_point_add +___ +} + +######################################################################## +# void ecp_nistz256_point_add_affine(P256_POINT *out,const P256_POINT *in1, +# const P256_POINT_AFFINE *in2); +if (1) { +my $FRAME = 64 + 32*10 + 16*8; +my ($res_x,$res_y,$res_z, + $U2,$S2,$H,$R,$Hsqr,$Hcub,$Rsqr)=map(64+32*$_,(0..9)); +my $Z1sqr = $S2; +# above map() describes stack layout with 10 temporary +# 256-bit vectors on top. +my ($rp_real,$ap_real,$bp_real,$in1infty,$in2infty,$temp)=map("r$_",(16..21)); + +$code.=<<___; +.globl ecp_nistz256_point_add_affine +.align 5 +ecp_nistz256_point_add_affine: + stdu $sp,-$FRAME($sp) + mflr r0 + std r16,$FRAME-8*16($sp) + std r17,$FRAME-8*15($sp) + std r18,$FRAME-8*14($sp) + std r19,$FRAME-8*13($sp) + std r20,$FRAME-8*12($sp) + std r21,$FRAME-8*11($sp) + std r22,$FRAME-8*10($sp) + std r23,$FRAME-8*9($sp) + std r24,$FRAME-8*8($sp) + std r25,$FRAME-8*7($sp) + std r26,$FRAME-8*6($sp) + std r27,$FRAME-8*5($sp) + std r28,$FRAME-8*4($sp) + std r29,$FRAME-8*3($sp) + std r30,$FRAME-8*2($sp) + std r31,$FRAME-8*1($sp) + + li $poly1,-1 + srdi $poly1,$poly1,32 # 0x00000000ffffffff + li $poly3,1 + orc $poly3,$poly3,$poly1 # 0xffffffff00000001 + + mr $rp_real,$rp + mr $ap_real,$ap + mr $bp_real,$bp + + ld $a0,64($ap) # in1_z + ld $a1,72($ap) + ld $a2,80($ap) + ld $a3,88($ap) + or $t0,$a0,$a1 + or $t2,$a2,$a3 + or $in1infty,$t0,$t2 + neg $t0,$in1infty + or $in1infty,$in1infty,$t0 + sradi $in1infty,$in1infty,63 # !in1infty + + ld $acc0,0($bp) # in2_x + ld $acc1,8($bp) + ld $acc2,16($bp) + ld $acc3,24($bp) + ld $t0,32($bp) # in2_y + ld $t1,40($bp) + ld $t2,48($bp) + ld $t3,56($bp) + or $acc0,$acc0,$acc1 + or $acc2,$acc2,$acc3 + or $acc0,$acc0,$acc2 + or $t0,$t0,$t1 + or $t2,$t2,$t3 + or $t0,$t0,$t2 + or $in2infty,$acc0,$t0 + neg $t0,$in2infty + or $in2infty,$in2infty,$t0 + sradi $in2infty,$in2infty,63 # !in2infty + + addi $rp,$sp,$Z1sqr + bl __ecp_nistz256_sqr_mont # p256_sqr_mont(Z1sqr, in1_z); + + mr $a0,$acc0 + mr $a1,$acc1 + mr $a2,$acc2 + mr $a3,$acc3 + ld $bi,0($bp_real) + addi $bp,$bp_real,0 + addi $rp,$sp,$U2 + bl __ecp_nistz256_mul_mont # p256_mul_mont(U2, Z1sqr, in2_x); + + addi $bp,$ap_real,0 + ld $bi,64($ap_real) # forward load for p256_mul_mont + ld $a0,$Z1sqr+0($sp) + ld $a1,$Z1sqr+8($sp) + ld $a2,$Z1sqr+16($sp) + ld $a3,$Z1sqr+24($sp) + addi $rp,$sp,$H + bl __ecp_nistz256_sub_from # p256_sub(H, U2, in1_x); + + addi $bp,$ap_real,64 + addi $rp,$sp,$S2 + bl __ecp_nistz256_mul_mont # p256_mul_mont(S2, Z1sqr, in1_z); + + ld $bi,64($ap_real) + ld $a0,$H+0($sp) + ld $a1,$H+8($sp) + ld $a2,$H+16($sp) + ld $a3,$H+24($sp) + addi $bp,$ap_real,64 + addi $rp,$sp,$res_z + bl __ecp_nistz256_mul_mont # p256_mul_mont(res_z, H, in1_z); + + ld $bi,32($bp_real) + ld $a0,$S2+0($sp) + ld $a1,$S2+8($sp) + ld $a2,$S2+16($sp) + ld $a3,$S2+24($sp) + addi $bp,$bp_real,32 + addi $rp,$sp,$S2 + bl __ecp_nistz256_mul_mont # p256_mul_mont(S2, S2, in2_y); + + addi $bp,$ap_real,32 + ld $a0,$H+0($sp) # forward load for p256_sqr_mont + ld $a1,$H+8($sp) + ld $a2,$H+16($sp) + ld $a3,$H+24($sp) + addi $rp,$sp,$R + bl __ecp_nistz256_sub_from # p256_sub(R, S2, in1_y); + + addi $rp,$sp,$Hsqr + bl __ecp_nistz256_sqr_mont # p256_sqr_mont(Hsqr, H); + + ld $a0,$R+0($sp) + ld $a1,$R+8($sp) + ld $a2,$R+16($sp) + ld $a3,$R+24($sp) + addi $rp,$sp,$Rsqr + bl __ecp_nistz256_sqr_mont # p256_sqr_mont(Rsqr, R); + + ld $bi,$H($sp) + ld $a0,$Hsqr+0($sp) + ld $a1,$Hsqr+8($sp) + ld $a2,$Hsqr+16($sp) + ld $a3,$Hsqr+24($sp) + addi $bp,$sp,$H + addi $rp,$sp,$Hcub + bl __ecp_nistz256_mul_mont # p256_mul_mont(Hcub, Hsqr, H); + + ld $bi,0($ap_real) + ld $a0,$Hsqr+0($sp) + ld $a1,$Hsqr+8($sp) + ld $a2,$Hsqr+16($sp) + ld $a3,$Hsqr+24($sp) + addi $bp,$ap_real,0 + addi $rp,$sp,$U2 + bl __ecp_nistz256_mul_mont # p256_mul_mont(U2, in1_x, Hsqr); + + mr $t0,$acc0 + mr $t1,$acc1 + mr $t2,$acc2 + mr $t3,$acc3 + addi $rp,$sp,$Hsqr + bl __ecp_nistz256_add # p256_mul_by_2(Hsqr, U2); + + addi $bp,$sp,$Rsqr + addi $rp,$sp,$res_x + bl __ecp_nistz256_sub_morf # p256_sub(res_x, Rsqr, Hsqr); + + addi $bp,$sp,$Hcub + bl __ecp_nistz256_sub_from # p256_sub(res_x, res_x, Hcub); + + addi $bp,$sp,$U2 + ld $bi,32($ap_real) # forward load for p256_mul_mont + ld $a0,$Hcub+0($sp) + ld $a1,$Hcub+8($sp) + ld $a2,$Hcub+16($sp) + ld $a3,$Hcub+24($sp) + addi $rp,$sp,$res_y + bl __ecp_nistz256_sub_morf # p256_sub(res_y, U2, res_x); + + addi $bp,$ap_real,32 + addi $rp,$sp,$S2 + bl __ecp_nistz256_mul_mont # p256_mul_mont(S2, in1_y, Hcub); + + ld $bi,$R($sp) + ld $a0,$res_y+0($sp) + ld $a1,$res_y+8($sp) + ld $a2,$res_y+16($sp) + ld $a3,$res_y+24($sp) + addi $bp,$sp,$R + addi $rp,$sp,$res_y + bl __ecp_nistz256_mul_mont # p256_mul_mont(res_y, res_y, R); + + addi $bp,$sp,$S2 + bl __ecp_nistz256_sub_from # p256_sub(res_y, res_y, S2); + + ld $t0,0($bp_real) # in2 + ld $t1,8($bp_real) + ld $t2,16($bp_real) + ld $t3,24($bp_real) + ld $a0,$res_x+0($sp) # res + ld $a1,$res_x+8($sp) + ld $a2,$res_x+16($sp) + ld $a3,$res_x+24($sp) +___ +for($i=0;$i<64;$i+=32) { # conditional moves +$code.=<<___; + ld $acc0,$i+0($ap_real) # in1 + ld $acc1,$i+8($ap_real) + ld $acc2,$i+16($ap_real) + ld $acc3,$i+24($ap_real) + andc $t0,$t0,$in1infty + andc $t1,$t1,$in1infty + andc $t2,$t2,$in1infty + andc $t3,$t3,$in1infty + and $a0,$a0,$in1infty + and $a1,$a1,$in1infty + and $a2,$a2,$in1infty + and $a3,$a3,$in1infty + or $t0,$t0,$a0 + or $t1,$t1,$a1 + or $t2,$t2,$a2 + or $t3,$t3,$a3 + andc $acc0,$acc0,$in2infty + andc $acc1,$acc1,$in2infty + andc $acc2,$acc2,$in2infty + andc $acc3,$acc3,$in2infty + and $t0,$t0,$in2infty + and $t1,$t1,$in2infty + and $t2,$t2,$in2infty + and $t3,$t3,$in2infty + or $acc0,$acc0,$t0 + or $acc1,$acc1,$t1 + or $acc2,$acc2,$t2 + or $acc3,$acc3,$t3 +___ +$code.=<<___ if ($i==0); + ld $t0,32($bp_real) # in2 + ld $t1,40($bp_real) + ld $t2,48($bp_real) + ld $t3,56($bp_real) +___ +$code.=<<___ if ($i==32); + li $t0,1 # Lone_mont + not $t1,$poly1 + li $t2,-1 + not $t3,$poly3 +___ +$code.=<<___; + ld $a0,$res_x+$i+32($sp) + ld $a1,$res_x+$i+40($sp) + ld $a2,$res_x+$i+48($sp) + ld $a3,$res_x+$i+56($sp) + std $acc0,$i+0($rp_real) + std $acc1,$i+8($rp_real) + std $acc2,$i+16($rp_real) + std $acc3,$i+24($rp_real) +___ +} +$code.=<<___; + ld $acc0,$i+0($ap_real) # in1 + ld $acc1,$i+8($ap_real) + ld $acc2,$i+16($ap_real) + ld $acc3,$i+24($ap_real) + andc $t0,$t0,$in1infty + andc $t1,$t1,$in1infty + andc $t2,$t2,$in1infty + andc $t3,$t3,$in1infty + and $a0,$a0,$in1infty + and $a1,$a1,$in1infty + and $a2,$a2,$in1infty + and $a3,$a3,$in1infty + or $t0,$t0,$a0 + or $t1,$t1,$a1 + or $t2,$t2,$a2 + or $t3,$t3,$a3 + andc $acc0,$acc0,$in2infty + andc $acc1,$acc1,$in2infty + andc $acc2,$acc2,$in2infty + andc $acc3,$acc3,$in2infty + and $t0,$t0,$in2infty + and $t1,$t1,$in2infty + and $t2,$t2,$in2infty + and $t3,$t3,$in2infty + or $acc0,$acc0,$t0 + or $acc1,$acc1,$t1 + or $acc2,$acc2,$t2 + or $acc3,$acc3,$t3 + std $acc0,$i+0($rp_real) + std $acc1,$i+8($rp_real) + std $acc2,$i+16($rp_real) + std $acc3,$i+24($rp_real) + + mtlr r0 + ld r16,$FRAME-8*16($sp) + ld r17,$FRAME-8*15($sp) + ld r18,$FRAME-8*14($sp) + ld r19,$FRAME-8*13($sp) + ld r20,$FRAME-8*12($sp) + ld r21,$FRAME-8*11($sp) + ld r22,$FRAME-8*10($sp) + ld r23,$FRAME-8*9($sp) + ld r24,$FRAME-8*8($sp) + ld r25,$FRAME-8*7($sp) + ld r26,$FRAME-8*6($sp) + ld r27,$FRAME-8*5($sp) + ld r28,$FRAME-8*4($sp) + ld r29,$FRAME-8*3($sp) + ld r30,$FRAME-8*2($sp) + ld r31,$FRAME-8*1($sp) + addi $sp,$sp,$FRAME + blr + .long 0 + .byte 0,12,4,0,0x80,16,3,0 + .long 0 +.size ecp_nistz256_point_add_affine,.-ecp_nistz256_point_add_affine +___ +} +if (1) { +my ($ordk,$ord0,$ord1,$t4) = map("r$_",(18..21)); +my ($ord2,$ord3,$zr) = ($poly1,$poly3,"r0"); + +$code.=<<___; +######################################################################## +# void ecp_nistz256_ord_mul_mont(uint64_t res[4], uint64_t a[4], +# uint64_t b[4]); +.globl ecp_nistz256_ord_mul_mont +.align 5 +ecp_nistz256_ord_mul_mont: + stdu $sp,-160($sp) + std r18,48($sp) + std r19,56($sp) + std r20,64($sp) + std r21,72($sp) + std r22,80($sp) + std r23,88($sp) + std r24,96($sp) + std r25,104($sp) + std r26,112($sp) + std r27,120($sp) + std r28,128($sp) + std r29,136($sp) + std r30,144($sp) + std r31,152($sp) + + ld $a0,0($ap) + ld $bi,0($bp) + ld $a1,8($ap) + ld $a2,16($ap) + ld $a3,24($ap) + + lis $ordk,0xccd1 + lis $ord0,0xf3b9 + lis $ord1,0xbce6 + ori $ordk,$ordk,0xc8aa + ori $ord0,$ord0,0xcac2 + ori $ord1,$ord1,0xfaad + sldi $ordk,$ordk,32 + sldi $ord0,$ord0,32 + sldi $ord1,$ord1,32 + oris $ordk,$ordk,0xee00 + oris $ord0,$ord0,0xfc63 + oris $ord1,$ord1,0xa717 + ori $ordk,$ordk,0xbc4f # 0xccd1c8aaee00bc4f + ori $ord0,$ord0,0x2551 # 0xf3b9cac2fc632551 + ori $ord1,$ord1,0x9e84 # 0xbce6faada7179e84 + li $ord2,-1 # 0xffffffffffffffff + sldi $ord3,$ord2,32 # 0xffffffff00000000 + li $zr,0 + + mulld $acc0,$a0,$bi # a[0]*b[0] + mulhdu $t0,$a0,$bi + + mulld $acc1,$a1,$bi # a[1]*b[0] + mulhdu $t1,$a1,$bi + + mulld $acc2,$a2,$bi # a[2]*b[0] + mulhdu $t2,$a2,$bi + + mulld $acc3,$a3,$bi # a[3]*b[0] + mulhdu $acc4,$a3,$bi + + mulld $t4,$acc0,$ordk + + addc $acc1,$acc1,$t0 # accumulate high parts of multiplication + adde $acc2,$acc2,$t1 + adde $acc3,$acc3,$t2 + addze $acc4,$acc4 + li $acc5,0 +___ +for ($i=1;$i<4;$i++) { + ################################################################ + # ffff0000.ffffffff.yyyyyyyy.zzzzzzzz + # * abcdefgh + # + xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx + # + # Now observing that ff..ff*x = (2^n-1)*x = 2^n*x-x, we + # rewrite above as: + # + # xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx + # - 0000abcd.efgh0000.abcdefgh.00000000.00000000 + # + abcdefgh.abcdefgh.yzayzbyz.cyzdyzey.zfyzgyzh +$code.=<<___; + ld $bi,8*$i($bp) # b[i] + + sldi $t0,$t4,32 + subfc $acc2,$t4,$acc2 + srdi $t1,$t4,32 + subfe $acc3,$t0,$acc3 + subfe $acc4,$t1,$acc4 + subfe $acc5,$zr,$acc5 + + addic $t0,$acc0,-1 # discarded + mulhdu $t1,$ord0,$t4 + mulld $t2,$ord1,$t4 + mulhdu $t3,$ord1,$t4 + + adde $t2,$t2,$t1 + mulld $t0,$a0,$bi + addze $t3,$t3 + mulld $t1,$a1,$bi + + addc $acc0,$acc1,$t2 + mulld $t2,$a2,$bi + adde $acc1,$acc2,$t3 + mulld $t3,$a3,$bi + adde $acc2,$acc3,$t4 + adde $acc3,$acc4,$t4 + addze $acc4,$acc5 + + addc $acc0,$acc0,$t0 # accumulate low parts + mulhdu $t0,$a0,$bi + adde $acc1,$acc1,$t1 + mulhdu $t1,$a1,$bi + adde $acc2,$acc2,$t2 + mulhdu $t2,$a2,$bi + adde $acc3,$acc3,$t3 + mulhdu $t3,$a3,$bi + addze $acc4,$acc4 + mulld $t4,$acc0,$ordk + addc $acc1,$acc1,$t0 # accumulate high parts + adde $acc2,$acc2,$t1 + adde $acc3,$acc3,$t2 + adde $acc4,$acc4,$t3 + addze $acc5,$zr +___ +} +$code.=<<___; + sldi $t0,$t4,32 # last reduction + subfc $acc2,$t4,$acc2 + srdi $t1,$t4,32 + subfe $acc3,$t0,$acc3 + subfe $acc4,$t1,$acc4 + subfe $acc5,$zr,$acc5 + + addic $t0,$acc0,-1 # discarded + mulhdu $t1,$ord0,$t4 + mulld $t2,$ord1,$t4 + mulhdu $t3,$ord1,$t4 + + adde $t2,$t2,$t1 + addze $t3,$t3 + + addc $acc0,$acc1,$t2 + adde $acc1,$acc2,$t3 + adde $acc2,$acc3,$t4 + adde $acc3,$acc4,$t4 + addze $acc4,$acc5 + + subfc $acc0,$ord0,$acc0 # ret -= modulus + subfe $acc1,$ord1,$acc1 + subfe $acc2,$ord2,$acc2 + subfe $acc3,$ord3,$acc3 + subfe $acc4,$zr,$acc4 + + and $t0,$ord0,$acc4 + and $t1,$ord1,$acc4 + addc $acc0,$acc0,$t0 # ret += modulus if borrow + and $t3,$ord3,$acc4 + adde $acc1,$acc1,$t1 + adde $acc2,$acc2,$acc4 + adde $acc3,$acc3,$t3 + + std $acc0,0($rp) + std $acc1,8($rp) + std $acc2,16($rp) + std $acc3,24($rp) + + ld r18,48($sp) + ld r19,56($sp) + ld r20,64($sp) + ld r21,72($sp) + ld r22,80($sp) + ld r23,88($sp) + ld r24,96($sp) + ld r25,104($sp) + ld r26,112($sp) + ld r27,120($sp) + ld r28,128($sp) + ld r29,136($sp) + ld r30,144($sp) + ld r31,152($sp) + addi $sp,$sp,160 + blr + .long 0 + .byte 0,12,4,0,0x80,14,3,0 + .long 0 +.size ecp_nistz256_ord_mul_mont,.-ecp_nistz256_ord_mul_mont + +################################################################################ +# void ecp_nistz256_ord_sqr_mont(uint64_t res[4], uint64_t a[4], +# int rep); +.globl ecp_nistz256_ord_sqr_mont +.align 5 +ecp_nistz256_ord_sqr_mont: + stdu $sp,-160($sp) + std r18,48($sp) + std r19,56($sp) + std r20,64($sp) + std r21,72($sp) + std r22,80($sp) + std r23,88($sp) + std r24,96($sp) + std r25,104($sp) + std r26,112($sp) + std r27,120($sp) + std r28,128($sp) + std r29,136($sp) + std r30,144($sp) + std r31,152($sp) + + mtctr $bp + + ld $a0,0($ap) + ld $a1,8($ap) + ld $a2,16($ap) + ld $a3,24($ap) + + lis $ordk,0xccd1 + lis $ord0,0xf3b9 + lis $ord1,0xbce6 + ori $ordk,$ordk,0xc8aa + ori $ord0,$ord0,0xcac2 + ori $ord1,$ord1,0xfaad + sldi $ordk,$ordk,32 + sldi $ord0,$ord0,32 + sldi $ord1,$ord1,32 + oris $ordk,$ordk,0xee00 + oris $ord0,$ord0,0xfc63 + oris $ord1,$ord1,0xa717 + ori $ordk,$ordk,0xbc4f # 0xccd1c8aaee00bc4f + ori $ord0,$ord0,0x2551 # 0xf3b9cac2fc632551 + ori $ord1,$ord1,0x9e84 # 0xbce6faada7179e84 + li $ord2,-1 # 0xffffffffffffffff + sldi $ord3,$ord2,32 # 0xffffffff00000000 + li $zr,0 + b .Loop_ord_sqr + +.align 5 +.Loop_ord_sqr: + ################################################################ + # | | | | | |a1*a0| | + # | | | | |a2*a0| | | + # | |a3*a2|a3*a0| | | | + # | | | |a2*a1| | | | + # | | |a3*a1| | | | | + # *| | | | | | | | 2| + # +|a3*a3|a2*a2|a1*a1|a0*a0| + # |--+--+--+--+--+--+--+--| + # |A7|A6|A5|A4|A3|A2|A1|A0|, where Ax is $accx, i.e. follow $accx + # + # "can't overflow" below mark carrying into high part of + # multiplication result, which can't overflow, because it + # can never be all ones. + + mulld $acc1,$a1,$a0 # a[1]*a[0] + mulhdu $t1,$a1,$a0 + mulld $acc2,$a2,$a0 # a[2]*a[0] + mulhdu $t2,$a2,$a0 + mulld $acc3,$a3,$a0 # a[3]*a[0] + mulhdu $acc4,$a3,$a0 + + addc $acc2,$acc2,$t1 # accumulate high parts of multiplication + mulld $t0,$a2,$a1 # a[2]*a[1] + mulhdu $t1,$a2,$a1 + adde $acc3,$acc3,$t2 + mulld $t2,$a3,$a1 # a[3]*a[1] + mulhdu $t3,$a3,$a1 + addze $acc4,$acc4 # can't overflow + + mulld $acc5,$a3,$a2 # a[3]*a[2] + mulhdu $acc6,$a3,$a2 + + addc $t1,$t1,$t2 # accumulate high parts of multiplication + mulld $acc0,$a0,$a0 # a[0]*a[0] + addze $t2,$t3 # can't overflow + + addc $acc3,$acc3,$t0 # accumulate low parts of multiplication + mulhdu $a0,$a0,$a0 + adde $acc4,$acc4,$t1 + mulld $t1,$a1,$a1 # a[1]*a[1] + adde $acc5,$acc5,$t2 + mulhdu $a1,$a1,$a1 + addze $acc6,$acc6 # can't overflow + + addc $acc1,$acc1,$acc1 # acc[1-6]*=2 + mulld $t2,$a2,$a2 # a[2]*a[2] + adde $acc2,$acc2,$acc2 + mulhdu $a2,$a2,$a2 + adde $acc3,$acc3,$acc3 + mulld $t3,$a3,$a3 # a[3]*a[3] + adde $acc4,$acc4,$acc4 + mulhdu $a3,$a3,$a3 + adde $acc5,$acc5,$acc5 + adde $acc6,$acc6,$acc6 + addze $acc7,$zr + + addc $acc1,$acc1,$a0 # +a[i]*a[i] + mulld $t4,$acc0,$ordk + adde $acc2,$acc2,$t1 + adde $acc3,$acc3,$a1 + adde $acc4,$acc4,$t2 + adde $acc5,$acc5,$a2 + adde $acc6,$acc6,$t3 + adde $acc7,$acc7,$a3 +___ +for($i=0; $i<4; $i++) { # reductions +$code.=<<___; + addic $t0,$acc0,-1 # discarded + mulhdu $t1,$ord0,$t4 + mulld $t2,$ord1,$t4 + mulhdu $t3,$ord1,$t4 + + adde $t2,$t2,$t1 + addze $t3,$t3 + + addc $acc0,$acc1,$t2 + adde $acc1,$acc2,$t3 + adde $acc2,$acc3,$t4 + adde $acc3,$zr,$t4 # can't overflow +___ +$code.=<<___ if ($i<3); + mulld $t3,$acc0,$ordk +___ +$code.=<<___; + sldi $t0,$t4,32 + subfc $acc1,$t4,$acc1 + srdi $t1,$t4,32 + subfe $acc2,$t0,$acc2 + subfe $acc3,$t1,$acc3 # can't borrow +___ + ($t3,$t4) = ($t4,$t3); +} +$code.=<<___; + addc $acc0,$acc0,$acc4 # accumulate upper half + adde $acc1,$acc1,$acc5 + adde $acc2,$acc2,$acc6 + adde $acc3,$acc3,$acc7 + addze $acc4,$zr + + subfc $acc0,$ord0,$acc0 # ret -= modulus + subfe $acc1,$ord1,$acc1 + subfe $acc2,$ord2,$acc2 + subfe $acc3,$ord3,$acc3 + subfe $acc4,$zr,$acc4 + + and $t0,$ord0,$acc4 + and $t1,$ord1,$acc4 + addc $a0,$acc0,$t0 # ret += modulus if borrow + and $t3,$ord3,$acc4 + adde $a1,$acc1,$t1 + adde $a2,$acc2,$acc4 + adde $a3,$acc3,$t3 + + bdnz .Loop_ord_sqr + + std $a0,0($rp) + std $a1,8($rp) + std $a2,16($rp) + std $a3,24($rp) + + ld r18,48($sp) + ld r19,56($sp) + ld r20,64($sp) + ld r21,72($sp) + ld r22,80($sp) + ld r23,88($sp) + ld r24,96($sp) + ld r25,104($sp) + ld r26,112($sp) + ld r27,120($sp) + ld r28,128($sp) + ld r29,136($sp) + ld r30,144($sp) + ld r31,152($sp) + addi $sp,$sp,160 + blr + .long 0 + .byte 0,12,4,0,0x80,14,3,0 + .long 0 +.size ecp_nistz256_ord_sqr_mont,.-ecp_nistz256_ord_sqr_mont +___ +} } + +######################################################################## +# scatter-gather subroutines +{ +my ($out,$inp,$index,$mask)=map("r$_",(3..7)); +$code.=<<___; +######################################################################## +# void ecp_nistz256_scatter_w5(void *out, const P256_POINT *inp, +# int index); +.globl ecp_nistz256_scatter_w5 +.align 4 +ecp_nistz256_scatter_w5: + slwi $index,$index,2 + add $out,$out,$index + + ld r8, 0($inp) # X + ld r9, 8($inp) + ld r10,16($inp) + ld r11,24($inp) + + stw r8, 64*0-4($out) + srdi r8, r8, 32 + stw r9, 64*1-4($out) + srdi r9, r9, 32 + stw r10,64*2-4($out) + srdi r10,r10,32 + stw r11,64*3-4($out) + srdi r11,r11,32 + stw r8, 64*4-4($out) + stw r9, 64*5-4($out) + stw r10,64*6-4($out) + stw r11,64*7-4($out) + addi $out,$out,64*8 + + ld r8, 32($inp) # Y + ld r9, 40($inp) + ld r10,48($inp) + ld r11,56($inp) + + stw r8, 64*0-4($out) + srdi r8, r8, 32 + stw r9, 64*1-4($out) + srdi r9, r9, 32 + stw r10,64*2-4($out) + srdi r10,r10,32 + stw r11,64*3-4($out) + srdi r11,r11,32 + stw r8, 64*4-4($out) + stw r9, 64*5-4($out) + stw r10,64*6-4($out) + stw r11,64*7-4($out) + addi $out,$out,64*8 + + ld r8, 64($inp) # Z + ld r9, 72($inp) + ld r10,80($inp) + ld r11,88($inp) + + stw r8, 64*0-4($out) + srdi r8, r8, 32 + stw r9, 64*1-4($out) + srdi r9, r9, 32 + stw r10,64*2-4($out) + srdi r10,r10,32 + stw r11,64*3-4($out) + srdi r11,r11,32 + stw r8, 64*4-4($out) + stw r9, 64*5-4($out) + stw r10,64*6-4($out) + stw r11,64*7-4($out) + + blr + .long 0 + .byte 0,12,0x14,0,0,0,3,0 + .long 0 +.size ecp_nistz256_scatter_w5,.-ecp_nistz256_scatter_w5 + +######################################################################## +# void ecp_nistz256_gather_w5(P256_POINT *out, const void *inp, +# int index); +.globl ecp_nistz256_gather_w5 +.align 4 +ecp_nistz256_gather_w5: + neg r0,$index + sradi r0,r0,63 + + add $index,$index,r0 + slwi $index,$index,2 + add $inp,$inp,$index + + lwz r5, 64*0($inp) + lwz r6, 64*1($inp) + lwz r7, 64*2($inp) + lwz r8, 64*3($inp) + lwz r9, 64*4($inp) + lwz r10,64*5($inp) + lwz r11,64*6($inp) + lwz r12,64*7($inp) + addi $inp,$inp,64*8 + sldi r9, r9, 32 + sldi r10,r10,32 + sldi r11,r11,32 + sldi r12,r12,32 + or r5,r5,r9 + or r6,r6,r10 + or r7,r7,r11 + or r8,r8,r12 + and r5,r5,r0 + and r6,r6,r0 + and r7,r7,r0 + and r8,r8,r0 + std r5,0($out) # X + std r6,8($out) + std r7,16($out) + std r8,24($out) + + lwz r5, 64*0($inp) + lwz r6, 64*1($inp) + lwz r7, 64*2($inp) + lwz r8, 64*3($inp) + lwz r9, 64*4($inp) + lwz r10,64*5($inp) + lwz r11,64*6($inp) + lwz r12,64*7($inp) + addi $inp,$inp,64*8 + sldi r9, r9, 32 + sldi r10,r10,32 + sldi r11,r11,32 + sldi r12,r12,32 + or r5,r5,r9 + or r6,r6,r10 + or r7,r7,r11 + or r8,r8,r12 + and r5,r5,r0 + and r6,r6,r0 + and r7,r7,r0 + and r8,r8,r0 + std r5,32($out) # Y + std r6,40($out) + std r7,48($out) + std r8,56($out) + + lwz r5, 64*0($inp) + lwz r6, 64*1($inp) + lwz r7, 64*2($inp) + lwz r8, 64*3($inp) + lwz r9, 64*4($inp) + lwz r10,64*5($inp) + lwz r11,64*6($inp) + lwz r12,64*7($inp) + sldi r9, r9, 32 + sldi r10,r10,32 + sldi r11,r11,32 + sldi r12,r12,32 + or r5,r5,r9 + or r6,r6,r10 + or r7,r7,r11 + or r8,r8,r12 + and r5,r5,r0 + and r6,r6,r0 + and r7,r7,r0 + and r8,r8,r0 + std r5,64($out) # Z + std r6,72($out) + std r7,80($out) + std r8,88($out) + + blr + .long 0 + .byte 0,12,0x14,0,0,0,3,0 + .long 0 +.size ecp_nistz256_gather_w5,.-ecp_nistz256_gather_w5 + +######################################################################## +# void ecp_nistz256_scatter_w7(void *out, const P256_POINT_AFFINE *inp, +# int index); +.globl ecp_nistz256_scatter_w7 +.align 4 +ecp_nistz256_scatter_w7: + li r0,8 + mtctr r0 + add $out,$out,$index + subi $inp,$inp,8 + +.Loop_scatter_w7: + ldu r0,8($inp) + stb r0,64*0($out) + srdi r0,r0,8 + stb r0,64*1($out) + srdi r0,r0,8 + stb r0,64*2($out) + srdi r0,r0,8 + stb r0,64*3($out) + srdi r0,r0,8 + stb r0,64*4($out) + srdi r0,r0,8 + stb r0,64*5($out) + srdi r0,r0,8 + stb r0,64*6($out) + srdi r0,r0,8 + stb r0,64*7($out) + addi $out,$out,64*8 + bdnz .Loop_scatter_w7 + + blr + .long 0 + .byte 0,12,0x14,0,0,0,3,0 + .long 0 +.size ecp_nistz256_scatter_w7,.-ecp_nistz256_scatter_w7 + +######################################################################## +# void ecp_nistz256_gather_w7(P256_POINT_AFFINE *out, const void *inp, +# int index); +.globl ecp_nistz256_gather_w7 +.align 4 +ecp_nistz256_gather_w7: + li r0,8 + mtctr r0 + neg r0,$index + sradi r0,r0,63 + + add $index,$index,r0 + add $inp,$inp,$index + subi $out,$out,8 + +.Loop_gather_w7: + lbz r5, 64*0($inp) + lbz r6, 64*1($inp) + lbz r7, 64*2($inp) + lbz r8, 64*3($inp) + lbz r9, 64*4($inp) + lbz r10,64*5($inp) + lbz r11,64*6($inp) + lbz r12,64*7($inp) + addi $inp,$inp,64*8 + + sldi r6, r6, 8 + sldi r7, r7, 16 + sldi r8, r8, 24 + sldi r9, r9, 32 + sldi r10,r10,40 + sldi r11,r11,48 + sldi r12,r12,56 + + or r5,r5,r6 + or r7,r7,r8 + or r9,r9,r10 + or r11,r11,r12 + or r5,r5,r7 + or r9,r9,r11 + or r5,r5,r9 + and r5,r5,r0 + stdu r5,8($out) + bdnz .Loop_gather_w7 + + blr + .long 0 + .byte 0,12,0x14,0,0,0,3,0 + .long 0 +.size ecp_nistz256_gather_w7,.-ecp_nistz256_gather_w7 +___ +} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/ge; + + print $_,"\n"; +} +close STDOUT; # enforce flush diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/ecp_nistz256-sparcv9.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/ecp_nistz256-sparcv9.pl new file mode 100755 index 000000000..0a4def6e2 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/ecp_nistz256-sparcv9.pl @@ -0,0 +1,3061 @@ +#! /usr/bin/env perl +# Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# ECP_NISTZ256 module for SPARCv9. +# +# February 2015. +# +# Original ECP_NISTZ256 submission targeting x86_64 is detailed in +# http://eprint.iacr.org/2013/816. In the process of adaptation +# original .c module was made 32-bit savvy in order to make this +# implementation possible. +# +# with/without -DECP_NISTZ256_ASM +# UltraSPARC III +12-18% +# SPARC T4 +99-550% (+66-150% on 32-bit Solaris) +# +# Ranges denote minimum and maximum improvement coefficients depending +# on benchmark. Lower coefficients are for ECDSA sign, server-side +# operation. Keep in mind that +200% means 3x improvement. + +$output = pop; +open STDOUT,">$output"; + +$code.=<<___; +#include "sparc_arch.h" + +#define LOCALS (STACK_BIAS+STACK_FRAME) +#ifdef __arch64__ +.register %g2,#scratch +.register %g3,#scratch +# define STACK64_FRAME STACK_FRAME +# define LOCALS64 LOCALS +#else +# define STACK64_FRAME (2047+192) +# define LOCALS64 STACK64_FRAME +#endif + +.section ".text",#alloc,#execinstr +___ +######################################################################## +# Convert ecp_nistz256_table.c to layout expected by ecp_nistz_gather_w7 +# +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +open TABLE,") { + s/TOBN\(\s*(0x[0-9a-f]+),\s*(0x[0-9a-f]+)\s*\)/push @arr,hex($2),hex($1)/geo; +} +close TABLE; + +# See ecp_nistz256_table.c for explanation for why it's 64*16*37. +# 64*16*37-1 is because $#arr returns last valid index or @arr, not +# amount of elements. +die "insane number of elements" if ($#arr != 64*16*37-1); + +$code.=<<___; +.globl ecp_nistz256_precomputed +.align 4096 +ecp_nistz256_precomputed: +___ +######################################################################## +# this conversion smashes P256_POINT_AFFINE by individual bytes with +# 64 byte interval, similar to +# 1111222233334444 +# 1234123412341234 +for(1..37) { + @tbl = splice(@arr,0,64*16); + for($i=0;$i<64;$i++) { + undef @line; + for($j=0;$j<64;$j++) { + push @line,(@tbl[$j*16+$i/4]>>(($i%4)*8))&0xff; + } + $code.=".byte\t"; + $code.=join(',',map { sprintf "0x%02x",$_} @line); + $code.="\n"; + } +} + +{{{ +my ($rp,$ap,$bp)=map("%i$_",(0..2)); +my @acc=map("%l$_",(0..7)); +my ($t0,$t1,$t2,$t3,$t4,$t5,$t6,$t7)=(map("%o$_",(0..5)),"%g4","%g5"); +my ($bi,$a0,$mask,$carry)=(map("%i$_",(3..5)),"%g1"); +my ($rp_real,$ap_real)=("%g2","%g3"); + +$code.=<<___; +.type ecp_nistz256_precomputed,#object +.size ecp_nistz256_precomputed,.-ecp_nistz256_precomputed +.align 64 +.LRR: ! 2^512 mod P precomputed for NIST P256 polynomial +.long 0x00000003, 0x00000000, 0xffffffff, 0xfffffffb +.long 0xfffffffe, 0xffffffff, 0xfffffffd, 0x00000004 +.Lone: +.long 1,0,0,0,0,0,0,0 +.asciz "ECP_NISTZ256 for SPARCv9, CRYPTOGAMS by " + +! void ecp_nistz256_to_mont(BN_ULONG %i0[8],const BN_ULONG %i1[8]); +.globl ecp_nistz256_to_mont +.align 64 +ecp_nistz256_to_mont: + save %sp,-STACK_FRAME,%sp + nop +1: call .+8 + add %o7,.LRR-1b,$bp + call __ecp_nistz256_mul_mont + nop + ret + restore +.type ecp_nistz256_to_mont,#function +.size ecp_nistz256_to_mont,.-ecp_nistz256_to_mont + +! void ecp_nistz256_from_mont(BN_ULONG %i0[8],const BN_ULONG %i1[8]); +.globl ecp_nistz256_from_mont +.align 32 +ecp_nistz256_from_mont: + save %sp,-STACK_FRAME,%sp + nop +1: call .+8 + add %o7,.Lone-1b,$bp + call __ecp_nistz256_mul_mont + nop + ret + restore +.type ecp_nistz256_from_mont,#function +.size ecp_nistz256_from_mont,.-ecp_nistz256_from_mont + +! void ecp_nistz256_mul_mont(BN_ULONG %i0[8],const BN_ULONG %i1[8], +! const BN_ULONG %i2[8]); +.globl ecp_nistz256_mul_mont +.align 32 +ecp_nistz256_mul_mont: + save %sp,-STACK_FRAME,%sp + nop + call __ecp_nistz256_mul_mont + nop + ret + restore +.type ecp_nistz256_mul_mont,#function +.size ecp_nistz256_mul_mont,.-ecp_nistz256_mul_mont + +! void ecp_nistz256_sqr_mont(BN_ULONG %i0[8],const BN_ULONG %i2[8]); +.globl ecp_nistz256_sqr_mont +.align 32 +ecp_nistz256_sqr_mont: + save %sp,-STACK_FRAME,%sp + mov $ap,$bp + call __ecp_nistz256_mul_mont + nop + ret + restore +.type ecp_nistz256_sqr_mont,#function +.size ecp_nistz256_sqr_mont,.-ecp_nistz256_sqr_mont +___ + +######################################################################## +# Special thing to keep in mind is that $t0-$t7 hold 64-bit values, +# while all others are meant to keep 32. "Meant to" means that additions +# to @acc[0-7] do "contaminate" upper bits, but they are cleared before +# they can affect outcome (follow 'and' with $mask). Also keep in mind +# that addition with carry is addition with 32-bit carry, even though +# CPU is 64-bit. [Addition with 64-bit carry was introduced in T3, see +# below for VIS3 code paths.] + +$code.=<<___; +.align 32 +__ecp_nistz256_mul_mont: + ld [$bp+0],$bi ! b[0] + mov -1,$mask + ld [$ap+0],$a0 + srl $mask,0,$mask ! 0xffffffff + ld [$ap+4],$t1 + ld [$ap+8],$t2 + ld [$ap+12],$t3 + ld [$ap+16],$t4 + ld [$ap+20],$t5 + ld [$ap+24],$t6 + ld [$ap+28],$t7 + mulx $a0,$bi,$t0 ! a[0-7]*b[0], 64-bit results + mulx $t1,$bi,$t1 + mulx $t2,$bi,$t2 + mulx $t3,$bi,$t3 + mulx $t4,$bi,$t4 + mulx $t5,$bi,$t5 + mulx $t6,$bi,$t6 + mulx $t7,$bi,$t7 + srlx $t0,32,@acc[1] ! extract high parts + srlx $t1,32,@acc[2] + srlx $t2,32,@acc[3] + srlx $t3,32,@acc[4] + srlx $t4,32,@acc[5] + srlx $t5,32,@acc[6] + srlx $t6,32,@acc[7] + srlx $t7,32,@acc[0] ! "@acc[8]" + mov 0,$carry +___ +for($i=1;$i<8;$i++) { +$code.=<<___; + addcc @acc[1],$t1,@acc[1] ! accumulate high parts + ld [$bp+4*$i],$bi ! b[$i] + ld [$ap+4],$t1 ! re-load a[1-7] + addccc @acc[2],$t2,@acc[2] + addccc @acc[3],$t3,@acc[3] + ld [$ap+8],$t2 + ld [$ap+12],$t3 + addccc @acc[4],$t4,@acc[4] + addccc @acc[5],$t5,@acc[5] + ld [$ap+16],$t4 + ld [$ap+20],$t5 + addccc @acc[6],$t6,@acc[6] + addccc @acc[7],$t7,@acc[7] + ld [$ap+24],$t6 + ld [$ap+28],$t7 + addccc @acc[0],$carry,@acc[0] ! "@acc[8]" + addc %g0,%g0,$carry +___ + # Reduction iteration is normally performed by accumulating + # result of multiplication of modulus by "magic" digit [and + # omitting least significant word, which is guaranteed to + # be 0], but thanks to special form of modulus and "magic" + # digit being equal to least significant word, it can be + # performed with additions and subtractions alone. Indeed: + # + # ffff.0001.0000.0000.0000.ffff.ffff.ffff + # * abcd + # + xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.abcd + # + # Now observing that ff..ff*x = (2^n-1)*x = 2^n*x-x, we + # rewrite above as: + # + # xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.abcd + # + abcd.0000.abcd.0000.0000.abcd.0000.0000.0000 + # - abcd.0000.0000.0000.0000.0000.0000.abcd + # + # or marking redundant operations: + # + # xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.---- + # + abcd.0000.abcd.0000.0000.abcd.----.----.---- + # - abcd.----.----.----.----.----.----.---- + +$code.=<<___; + ! multiplication-less reduction + addcc @acc[3],$t0,@acc[3] ! r[3]+=r[0] + addccc @acc[4],%g0,@acc[4] ! r[4]+=0 + and @acc[1],$mask,@acc[1] + and @acc[2],$mask,@acc[2] + addccc @acc[5],%g0,@acc[5] ! r[5]+=0 + addccc @acc[6],$t0,@acc[6] ! r[6]+=r[0] + and @acc[3],$mask,@acc[3] + and @acc[4],$mask,@acc[4] + addccc @acc[7],%g0,@acc[7] ! r[7]+=0 + addccc @acc[0],$t0,@acc[0] ! r[8]+=r[0] "@acc[8]" + and @acc[5],$mask,@acc[5] + and @acc[6],$mask,@acc[6] + addc $carry,%g0,$carry ! top-most carry + subcc @acc[7],$t0,@acc[7] ! r[7]-=r[0] + subccc @acc[0],%g0,@acc[0] ! r[8]-=0 "@acc[8]" + subc $carry,%g0,$carry ! top-most carry + and @acc[7],$mask,@acc[7] + and @acc[0],$mask,@acc[0] ! "@acc[8]" +___ + push(@acc,shift(@acc)); # rotate registers to "omit" acc[0] +$code.=<<___; + mulx $a0,$bi,$t0 ! a[0-7]*b[$i], 64-bit results + mulx $t1,$bi,$t1 + mulx $t2,$bi,$t2 + mulx $t3,$bi,$t3 + mulx $t4,$bi,$t4 + mulx $t5,$bi,$t5 + mulx $t6,$bi,$t6 + mulx $t7,$bi,$t7 + add @acc[0],$t0,$t0 ! accumulate low parts, can't overflow + add @acc[1],$t1,$t1 + srlx $t0,32,@acc[1] ! extract high parts + add @acc[2],$t2,$t2 + srlx $t1,32,@acc[2] + add @acc[3],$t3,$t3 + srlx $t2,32,@acc[3] + add @acc[4],$t4,$t4 + srlx $t3,32,@acc[4] + add @acc[5],$t5,$t5 + srlx $t4,32,@acc[5] + add @acc[6],$t6,$t6 + srlx $t5,32,@acc[6] + add @acc[7],$t7,$t7 + srlx $t6,32,@acc[7] + srlx $t7,32,@acc[0] ! "@acc[8]" +___ +} +$code.=<<___; + addcc @acc[1],$t1,@acc[1] ! accumulate high parts + addccc @acc[2],$t2,@acc[2] + addccc @acc[3],$t3,@acc[3] + addccc @acc[4],$t4,@acc[4] + addccc @acc[5],$t5,@acc[5] + addccc @acc[6],$t6,@acc[6] + addccc @acc[7],$t7,@acc[7] + addccc @acc[0],$carry,@acc[0] ! "@acc[8]" + addc %g0,%g0,$carry + + addcc @acc[3],$t0,@acc[3] ! multiplication-less reduction + addccc @acc[4],%g0,@acc[4] + addccc @acc[5],%g0,@acc[5] + addccc @acc[6],$t0,@acc[6] + addccc @acc[7],%g0,@acc[7] + addccc @acc[0],$t0,@acc[0] ! "@acc[8]" + addc $carry,%g0,$carry + subcc @acc[7],$t0,@acc[7] + subccc @acc[0],%g0,@acc[0] ! "@acc[8]" + subc $carry,%g0,$carry ! top-most carry +___ + push(@acc,shift(@acc)); # rotate registers to omit acc[0] +$code.=<<___; + ! Final step is "if result > mod, subtract mod", but we do it + ! "other way around", namely subtract modulus from result + ! and if it borrowed, add modulus back. + + subcc @acc[0],-1,@acc[0] ! subtract modulus + subccc @acc[1],-1,@acc[1] + subccc @acc[2],-1,@acc[2] + subccc @acc[3],0,@acc[3] + subccc @acc[4],0,@acc[4] + subccc @acc[5],0,@acc[5] + subccc @acc[6],1,@acc[6] + subccc @acc[7],-1,@acc[7] + subc $carry,0,$carry ! broadcast borrow bit + + ! Note that because mod has special form, i.e. consists of + ! 0xffffffff, 1 and 0s, we can conditionally synthesize it by + ! using value of broadcasted borrow and the borrow bit itself. + ! To minimize dependency chain we first broadcast and then + ! extract the bit by negating (follow $bi). + + addcc @acc[0],$carry,@acc[0] ! add modulus or zero + addccc @acc[1],$carry,@acc[1] + neg $carry,$bi + st @acc[0],[$rp] + addccc @acc[2],$carry,@acc[2] + st @acc[1],[$rp+4] + addccc @acc[3],0,@acc[3] + st @acc[2],[$rp+8] + addccc @acc[4],0,@acc[4] + st @acc[3],[$rp+12] + addccc @acc[5],0,@acc[5] + st @acc[4],[$rp+16] + addccc @acc[6],$bi,@acc[6] + st @acc[5],[$rp+20] + addc @acc[7],$carry,@acc[7] + st @acc[6],[$rp+24] + retl + st @acc[7],[$rp+28] +.type __ecp_nistz256_mul_mont,#function +.size __ecp_nistz256_mul_mont,.-__ecp_nistz256_mul_mont + +! void ecp_nistz256_add(BN_ULONG %i0[8],const BN_ULONG %i1[8], +! const BN_ULONG %i2[8]); +.globl ecp_nistz256_add +.align 32 +ecp_nistz256_add: + save %sp,-STACK_FRAME,%sp + ld [$ap],@acc[0] + ld [$ap+4],@acc[1] + ld [$ap+8],@acc[2] + ld [$ap+12],@acc[3] + ld [$ap+16],@acc[4] + ld [$ap+20],@acc[5] + ld [$ap+24],@acc[6] + call __ecp_nistz256_add + ld [$ap+28],@acc[7] + ret + restore +.type ecp_nistz256_add,#function +.size ecp_nistz256_add,.-ecp_nistz256_add + +.align 32 +__ecp_nistz256_add: + ld [$bp+0],$t0 ! b[0] + ld [$bp+4],$t1 + ld [$bp+8],$t2 + ld [$bp+12],$t3 + addcc @acc[0],$t0,@acc[0] + ld [$bp+16],$t4 + ld [$bp+20],$t5 + addccc @acc[1],$t1,@acc[1] + ld [$bp+24],$t6 + ld [$bp+28],$t7 + addccc @acc[2],$t2,@acc[2] + addccc @acc[3],$t3,@acc[3] + addccc @acc[4],$t4,@acc[4] + addccc @acc[5],$t5,@acc[5] + addccc @acc[6],$t6,@acc[6] + addccc @acc[7],$t7,@acc[7] + addc %g0,%g0,$carry + +.Lreduce_by_sub: + + ! if a+b >= modulus, subtract modulus. + ! + ! But since comparison implies subtraction, we subtract + ! modulus and then add it back if subtraction borrowed. + + subcc @acc[0],-1,@acc[0] + subccc @acc[1],-1,@acc[1] + subccc @acc[2],-1,@acc[2] + subccc @acc[3], 0,@acc[3] + subccc @acc[4], 0,@acc[4] + subccc @acc[5], 0,@acc[5] + subccc @acc[6], 1,@acc[6] + subccc @acc[7],-1,@acc[7] + subc $carry,0,$carry + + ! Note that because mod has special form, i.e. consists of + ! 0xffffffff, 1 and 0s, we can conditionally synthesize it by + ! using value of borrow and its negative. + + addcc @acc[0],$carry,@acc[0] ! add synthesized modulus + addccc @acc[1],$carry,@acc[1] + neg $carry,$bi + st @acc[0],[$rp] + addccc @acc[2],$carry,@acc[2] + st @acc[1],[$rp+4] + addccc @acc[3],0,@acc[3] + st @acc[2],[$rp+8] + addccc @acc[4],0,@acc[4] + st @acc[3],[$rp+12] + addccc @acc[5],0,@acc[5] + st @acc[4],[$rp+16] + addccc @acc[6],$bi,@acc[6] + st @acc[5],[$rp+20] + addc @acc[7],$carry,@acc[7] + st @acc[6],[$rp+24] + retl + st @acc[7],[$rp+28] +.type __ecp_nistz256_add,#function +.size __ecp_nistz256_add,.-__ecp_nistz256_add + +! void ecp_nistz256_mul_by_2(BN_ULONG %i0[8],const BN_ULONG %i1[8]); +.globl ecp_nistz256_mul_by_2 +.align 32 +ecp_nistz256_mul_by_2: + save %sp,-STACK_FRAME,%sp + ld [$ap],@acc[0] + ld [$ap+4],@acc[1] + ld [$ap+8],@acc[2] + ld [$ap+12],@acc[3] + ld [$ap+16],@acc[4] + ld [$ap+20],@acc[5] + ld [$ap+24],@acc[6] + call __ecp_nistz256_mul_by_2 + ld [$ap+28],@acc[7] + ret + restore +.type ecp_nistz256_mul_by_2,#function +.size ecp_nistz256_mul_by_2,.-ecp_nistz256_mul_by_2 + +.align 32 +__ecp_nistz256_mul_by_2: + addcc @acc[0],@acc[0],@acc[0] ! a+a=2*a + addccc @acc[1],@acc[1],@acc[1] + addccc @acc[2],@acc[2],@acc[2] + addccc @acc[3],@acc[3],@acc[3] + addccc @acc[4],@acc[4],@acc[4] + addccc @acc[5],@acc[5],@acc[5] + addccc @acc[6],@acc[6],@acc[6] + addccc @acc[7],@acc[7],@acc[7] + b .Lreduce_by_sub + addc %g0,%g0,$carry +.type __ecp_nistz256_mul_by_2,#function +.size __ecp_nistz256_mul_by_2,.-__ecp_nistz256_mul_by_2 + +! void ecp_nistz256_mul_by_3(BN_ULONG %i0[8],const BN_ULONG %i1[8]); +.globl ecp_nistz256_mul_by_3 +.align 32 +ecp_nistz256_mul_by_3: + save %sp,-STACK_FRAME,%sp + ld [$ap],@acc[0] + ld [$ap+4],@acc[1] + ld [$ap+8],@acc[2] + ld [$ap+12],@acc[3] + ld [$ap+16],@acc[4] + ld [$ap+20],@acc[5] + ld [$ap+24],@acc[6] + call __ecp_nistz256_mul_by_3 + ld [$ap+28],@acc[7] + ret + restore +.type ecp_nistz256_mul_by_3,#function +.size ecp_nistz256_mul_by_3,.-ecp_nistz256_mul_by_3 + +.align 32 +__ecp_nistz256_mul_by_3: + addcc @acc[0],@acc[0],$t0 ! a+a=2*a + addccc @acc[1],@acc[1],$t1 + addccc @acc[2],@acc[2],$t2 + addccc @acc[3],@acc[3],$t3 + addccc @acc[4],@acc[4],$t4 + addccc @acc[5],@acc[5],$t5 + addccc @acc[6],@acc[6],$t6 + addccc @acc[7],@acc[7],$t7 + addc %g0,%g0,$carry + + subcc $t0,-1,$t0 ! .Lreduce_by_sub but without stores + subccc $t1,-1,$t1 + subccc $t2,-1,$t2 + subccc $t3, 0,$t3 + subccc $t4, 0,$t4 + subccc $t5, 0,$t5 + subccc $t6, 1,$t6 + subccc $t7,-1,$t7 + subc $carry,0,$carry + + addcc $t0,$carry,$t0 ! add synthesized modulus + addccc $t1,$carry,$t1 + neg $carry,$bi + addccc $t2,$carry,$t2 + addccc $t3,0,$t3 + addccc $t4,0,$t4 + addccc $t5,0,$t5 + addccc $t6,$bi,$t6 + addc $t7,$carry,$t7 + + addcc $t0,@acc[0],@acc[0] ! 2*a+a=3*a + addccc $t1,@acc[1],@acc[1] + addccc $t2,@acc[2],@acc[2] + addccc $t3,@acc[3],@acc[3] + addccc $t4,@acc[4],@acc[4] + addccc $t5,@acc[5],@acc[5] + addccc $t6,@acc[6],@acc[6] + addccc $t7,@acc[7],@acc[7] + b .Lreduce_by_sub + addc %g0,%g0,$carry +.type __ecp_nistz256_mul_by_3,#function +.size __ecp_nistz256_mul_by_3,.-__ecp_nistz256_mul_by_3 + +! void ecp_nistz256_sub(BN_ULONG %i0[8],const BN_ULONG %i1[8], +! const BN_ULONG %i2[8]); +.globl ecp_nistz256_sub +.align 32 +ecp_nistz256_sub: + save %sp,-STACK_FRAME,%sp + ld [$ap],@acc[0] + ld [$ap+4],@acc[1] + ld [$ap+8],@acc[2] + ld [$ap+12],@acc[3] + ld [$ap+16],@acc[4] + ld [$ap+20],@acc[5] + ld [$ap+24],@acc[6] + call __ecp_nistz256_sub_from + ld [$ap+28],@acc[7] + ret + restore +.type ecp_nistz256_sub,#function +.size ecp_nistz256_sub,.-ecp_nistz256_sub + +! void ecp_nistz256_neg(BN_ULONG %i0[8],const BN_ULONG %i1[8]); +.globl ecp_nistz256_neg +.align 32 +ecp_nistz256_neg: + save %sp,-STACK_FRAME,%sp + mov $ap,$bp + mov 0,@acc[0] + mov 0,@acc[1] + mov 0,@acc[2] + mov 0,@acc[3] + mov 0,@acc[4] + mov 0,@acc[5] + mov 0,@acc[6] + call __ecp_nistz256_sub_from + mov 0,@acc[7] + ret + restore +.type ecp_nistz256_neg,#function +.size ecp_nistz256_neg,.-ecp_nistz256_neg + +.align 32 +__ecp_nistz256_sub_from: + ld [$bp+0],$t0 ! b[0] + ld [$bp+4],$t1 + ld [$bp+8],$t2 + ld [$bp+12],$t3 + subcc @acc[0],$t0,@acc[0] + ld [$bp+16],$t4 + ld [$bp+20],$t5 + subccc @acc[1],$t1,@acc[1] + subccc @acc[2],$t2,@acc[2] + ld [$bp+24],$t6 + ld [$bp+28],$t7 + subccc @acc[3],$t3,@acc[3] + subccc @acc[4],$t4,@acc[4] + subccc @acc[5],$t5,@acc[5] + subccc @acc[6],$t6,@acc[6] + subccc @acc[7],$t7,@acc[7] + subc %g0,%g0,$carry ! broadcast borrow bit + +.Lreduce_by_add: + + ! if a-b borrows, add modulus. + ! + ! Note that because mod has special form, i.e. consists of + ! 0xffffffff, 1 and 0s, we can conditionally synthesize it by + ! using value of broadcasted borrow and the borrow bit itself. + ! To minimize dependency chain we first broadcast and then + ! extract the bit by negating (follow $bi). + + addcc @acc[0],$carry,@acc[0] ! add synthesized modulus + addccc @acc[1],$carry,@acc[1] + neg $carry,$bi + st @acc[0],[$rp] + addccc @acc[2],$carry,@acc[2] + st @acc[1],[$rp+4] + addccc @acc[3],0,@acc[3] + st @acc[2],[$rp+8] + addccc @acc[4],0,@acc[4] + st @acc[3],[$rp+12] + addccc @acc[5],0,@acc[5] + st @acc[4],[$rp+16] + addccc @acc[6],$bi,@acc[6] + st @acc[5],[$rp+20] + addc @acc[7],$carry,@acc[7] + st @acc[6],[$rp+24] + retl + st @acc[7],[$rp+28] +.type __ecp_nistz256_sub_from,#function +.size __ecp_nistz256_sub_from,.-__ecp_nistz256_sub_from + +.align 32 +__ecp_nistz256_sub_morf: + ld [$bp+0],$t0 ! b[0] + ld [$bp+4],$t1 + ld [$bp+8],$t2 + ld [$bp+12],$t3 + subcc $t0,@acc[0],@acc[0] + ld [$bp+16],$t4 + ld [$bp+20],$t5 + subccc $t1,@acc[1],@acc[1] + subccc $t2,@acc[2],@acc[2] + ld [$bp+24],$t6 + ld [$bp+28],$t7 + subccc $t3,@acc[3],@acc[3] + subccc $t4,@acc[4],@acc[4] + subccc $t5,@acc[5],@acc[5] + subccc $t6,@acc[6],@acc[6] + subccc $t7,@acc[7],@acc[7] + b .Lreduce_by_add + subc %g0,%g0,$carry ! broadcast borrow bit +.type __ecp_nistz256_sub_morf,#function +.size __ecp_nistz256_sub_morf,.-__ecp_nistz256_sub_morf + +! void ecp_nistz256_div_by_2(BN_ULONG %i0[8],const BN_ULONG %i1[8]); +.globl ecp_nistz256_div_by_2 +.align 32 +ecp_nistz256_div_by_2: + save %sp,-STACK_FRAME,%sp + ld [$ap],@acc[0] + ld [$ap+4],@acc[1] + ld [$ap+8],@acc[2] + ld [$ap+12],@acc[3] + ld [$ap+16],@acc[4] + ld [$ap+20],@acc[5] + ld [$ap+24],@acc[6] + call __ecp_nistz256_div_by_2 + ld [$ap+28],@acc[7] + ret + restore +.type ecp_nistz256_div_by_2,#function +.size ecp_nistz256_div_by_2,.-ecp_nistz256_div_by_2 + +.align 32 +__ecp_nistz256_div_by_2: + ! ret = (a is odd ? a+mod : a) >> 1 + + and @acc[0],1,$bi + neg $bi,$carry + addcc @acc[0],$carry,@acc[0] + addccc @acc[1],$carry,@acc[1] + addccc @acc[2],$carry,@acc[2] + addccc @acc[3],0,@acc[3] + addccc @acc[4],0,@acc[4] + addccc @acc[5],0,@acc[5] + addccc @acc[6],$bi,@acc[6] + addccc @acc[7],$carry,@acc[7] + addc %g0,%g0,$carry + + ! ret >>= 1 + + srl @acc[0],1,@acc[0] + sll @acc[1],31,$t0 + srl @acc[1],1,@acc[1] + or @acc[0],$t0,@acc[0] + sll @acc[2],31,$t1 + srl @acc[2],1,@acc[2] + or @acc[1],$t1,@acc[1] + sll @acc[3],31,$t2 + st @acc[0],[$rp] + srl @acc[3],1,@acc[3] + or @acc[2],$t2,@acc[2] + sll @acc[4],31,$t3 + st @acc[1],[$rp+4] + srl @acc[4],1,@acc[4] + or @acc[3],$t3,@acc[3] + sll @acc[5],31,$t4 + st @acc[2],[$rp+8] + srl @acc[5],1,@acc[5] + or @acc[4],$t4,@acc[4] + sll @acc[6],31,$t5 + st @acc[3],[$rp+12] + srl @acc[6],1,@acc[6] + or @acc[5],$t5,@acc[5] + sll @acc[7],31,$t6 + st @acc[4],[$rp+16] + srl @acc[7],1,@acc[7] + or @acc[6],$t6,@acc[6] + sll $carry,31,$t7 + st @acc[5],[$rp+20] + or @acc[7],$t7,@acc[7] + st @acc[6],[$rp+24] + retl + st @acc[7],[$rp+28] +.type __ecp_nistz256_div_by_2,#function +.size __ecp_nistz256_div_by_2,.-__ecp_nistz256_div_by_2 +___ + +######################################################################## +# following subroutines are "literal" implementation of those found in +# ecp_nistz256.c +# +######################################################################## +# void ecp_nistz256_point_double(P256_POINT *out,const P256_POINT *inp); +# +{ +my ($S,$M,$Zsqr,$tmp0)=map(32*$_,(0..3)); +# above map() describes stack layout with 4 temporary +# 256-bit vectors on top. + +$code.=<<___; +#ifdef __PIC__ +SPARC_PIC_THUNK(%g1) +#endif + +.globl ecp_nistz256_point_double +.align 32 +ecp_nistz256_point_double: + SPARC_LOAD_ADDRESS_LEAF(OPENSSL_sparcv9cap_P,%g1,%g5) + ld [%g1],%g1 ! OPENSSL_sparcv9cap_P[0] + and %g1,(SPARCV9_VIS3|SPARCV9_64BIT_STACK),%g1 + cmp %g1,(SPARCV9_VIS3|SPARCV9_64BIT_STACK) + be ecp_nistz256_point_double_vis3 + nop + + save %sp,-STACK_FRAME-32*4,%sp + + mov $rp,$rp_real + mov $ap,$ap_real + +.Lpoint_double_shortcut: + ld [$ap+32],@acc[0] + ld [$ap+32+4],@acc[1] + ld [$ap+32+8],@acc[2] + ld [$ap+32+12],@acc[3] + ld [$ap+32+16],@acc[4] + ld [$ap+32+20],@acc[5] + ld [$ap+32+24],@acc[6] + ld [$ap+32+28],@acc[7] + call __ecp_nistz256_mul_by_2 ! p256_mul_by_2(S, in_y); + add %sp,LOCALS+$S,$rp + + add $ap_real,64,$bp + add $ap_real,64,$ap + call __ecp_nistz256_mul_mont ! p256_sqr_mont(Zsqr, in_z); + add %sp,LOCALS+$Zsqr,$rp + + add $ap_real,0,$bp + call __ecp_nistz256_add ! p256_add(M, Zsqr, in_x); + add %sp,LOCALS+$M,$rp + + add %sp,LOCALS+$S,$bp + add %sp,LOCALS+$S,$ap + call __ecp_nistz256_mul_mont ! p256_sqr_mont(S, S); + add %sp,LOCALS+$S,$rp + + ld [$ap_real],@acc[0] + add %sp,LOCALS+$Zsqr,$bp + ld [$ap_real+4],@acc[1] + ld [$ap_real+8],@acc[2] + ld [$ap_real+12],@acc[3] + ld [$ap_real+16],@acc[4] + ld [$ap_real+20],@acc[5] + ld [$ap_real+24],@acc[6] + ld [$ap_real+28],@acc[7] + call __ecp_nistz256_sub_from ! p256_sub(Zsqr, in_x, Zsqr); + add %sp,LOCALS+$Zsqr,$rp + + add $ap_real,32,$bp + add $ap_real,64,$ap + call __ecp_nistz256_mul_mont ! p256_mul_mont(tmp0, in_z, in_y); + add %sp,LOCALS+$tmp0,$rp + + call __ecp_nistz256_mul_by_2 ! p256_mul_by_2(res_z, tmp0); + add $rp_real,64,$rp + + add %sp,LOCALS+$Zsqr,$bp + add %sp,LOCALS+$M,$ap + call __ecp_nistz256_mul_mont ! p256_mul_mont(M, M, Zsqr); + add %sp,LOCALS+$M,$rp + + call __ecp_nistz256_mul_by_3 ! p256_mul_by_3(M, M); + add %sp,LOCALS+$M,$rp + + add %sp,LOCALS+$S,$bp + add %sp,LOCALS+$S,$ap + call __ecp_nistz256_mul_mont ! p256_sqr_mont(tmp0, S); + add %sp,LOCALS+$tmp0,$rp + + call __ecp_nistz256_div_by_2 ! p256_div_by_2(res_y, tmp0); + add $rp_real,32,$rp + + add $ap_real,0,$bp + add %sp,LOCALS+$S,$ap + call __ecp_nistz256_mul_mont ! p256_mul_mont(S, S, in_x); + add %sp,LOCALS+$S,$rp + + call __ecp_nistz256_mul_by_2 ! p256_mul_by_2(tmp0, S); + add %sp,LOCALS+$tmp0,$rp + + add %sp,LOCALS+$M,$bp + add %sp,LOCALS+$M,$ap + call __ecp_nistz256_mul_mont ! p256_sqr_mont(res_x, M); + add $rp_real,0,$rp + + add %sp,LOCALS+$tmp0,$bp + call __ecp_nistz256_sub_from ! p256_sub(res_x, res_x, tmp0); + add $rp_real,0,$rp + + add %sp,LOCALS+$S,$bp + call __ecp_nistz256_sub_morf ! p256_sub(S, S, res_x); + add %sp,LOCALS+$S,$rp + + add %sp,LOCALS+$M,$bp + add %sp,LOCALS+$S,$ap + call __ecp_nistz256_mul_mont ! p256_mul_mont(S, S, M); + add %sp,LOCALS+$S,$rp + + add $rp_real,32,$bp + call __ecp_nistz256_sub_from ! p256_sub(res_y, S, res_y); + add $rp_real,32,$rp + + ret + restore +.type ecp_nistz256_point_double,#function +.size ecp_nistz256_point_double,.-ecp_nistz256_point_double +___ +} + +######################################################################## +# void ecp_nistz256_point_add(P256_POINT *out,const P256_POINT *in1, +# const P256_POINT *in2); +{ +my ($res_x,$res_y,$res_z, + $H,$Hsqr,$R,$Rsqr,$Hcub, + $U1,$U2,$S1,$S2)=map(32*$_,(0..11)); +my ($Z1sqr, $Z2sqr) = ($Hsqr, $Rsqr); + +# above map() describes stack layout with 12 temporary +# 256-bit vectors on top. Then we reserve some space for +# !in1infty, !in2infty, result of check for zero and return pointer. + +my $bp_real=$rp_real; + +$code.=<<___; +.globl ecp_nistz256_point_add +.align 32 +ecp_nistz256_point_add: + SPARC_LOAD_ADDRESS_LEAF(OPENSSL_sparcv9cap_P,%g1,%g5) + ld [%g1],%g1 ! OPENSSL_sparcv9cap_P[0] + and %g1,(SPARCV9_VIS3|SPARCV9_64BIT_STACK),%g1 + cmp %g1,(SPARCV9_VIS3|SPARCV9_64BIT_STACK) + be ecp_nistz256_point_add_vis3 + nop + + save %sp,-STACK_FRAME-32*12-32,%sp + + stx $rp,[%fp+STACK_BIAS-8] ! off-load $rp + mov $ap,$ap_real + mov $bp,$bp_real + + ld [$bp+64],$t0 ! in2_z + ld [$bp+64+4],$t1 + ld [$bp+64+8],$t2 + ld [$bp+64+12],$t3 + ld [$bp+64+16],$t4 + ld [$bp+64+20],$t5 + ld [$bp+64+24],$t6 + ld [$bp+64+28],$t7 + or $t1,$t0,$t0 + or $t3,$t2,$t2 + or $t5,$t4,$t4 + or $t7,$t6,$t6 + or $t2,$t0,$t0 + or $t6,$t4,$t4 + or $t4,$t0,$t0 ! !in2infty + movrnz $t0,-1,$t0 + st $t0,[%fp+STACK_BIAS-12] + + ld [$ap+64],$t0 ! in1_z + ld [$ap+64+4],$t1 + ld [$ap+64+8],$t2 + ld [$ap+64+12],$t3 + ld [$ap+64+16],$t4 + ld [$ap+64+20],$t5 + ld [$ap+64+24],$t6 + ld [$ap+64+28],$t7 + or $t1,$t0,$t0 + or $t3,$t2,$t2 + or $t5,$t4,$t4 + or $t7,$t6,$t6 + or $t2,$t0,$t0 + or $t6,$t4,$t4 + or $t4,$t0,$t0 ! !in1infty + movrnz $t0,-1,$t0 + st $t0,[%fp+STACK_BIAS-16] + + add $bp_real,64,$bp + add $bp_real,64,$ap + call __ecp_nistz256_mul_mont ! p256_sqr_mont(Z2sqr, in2_z); + add %sp,LOCALS+$Z2sqr,$rp + + add $ap_real,64,$bp + add $ap_real,64,$ap + call __ecp_nistz256_mul_mont ! p256_sqr_mont(Z1sqr, in1_z); + add %sp,LOCALS+$Z1sqr,$rp + + add $bp_real,64,$bp + add %sp,LOCALS+$Z2sqr,$ap + call __ecp_nistz256_mul_mont ! p256_mul_mont(S1, Z2sqr, in2_z); + add %sp,LOCALS+$S1,$rp + + add $ap_real,64,$bp + add %sp,LOCALS+$Z1sqr,$ap + call __ecp_nistz256_mul_mont ! p256_mul_mont(S2, Z1sqr, in1_z); + add %sp,LOCALS+$S2,$rp + + add $ap_real,32,$bp + add %sp,LOCALS+$S1,$ap + call __ecp_nistz256_mul_mont ! p256_mul_mont(S1, S1, in1_y); + add %sp,LOCALS+$S1,$rp + + add $bp_real,32,$bp + add %sp,LOCALS+$S2,$ap + call __ecp_nistz256_mul_mont ! p256_mul_mont(S2, S2, in2_y); + add %sp,LOCALS+$S2,$rp + + add %sp,LOCALS+$S1,$bp + call __ecp_nistz256_sub_from ! p256_sub(R, S2, S1); + add %sp,LOCALS+$R,$rp + + or @acc[1],@acc[0],@acc[0] ! see if result is zero + or @acc[3],@acc[2],@acc[2] + or @acc[5],@acc[4],@acc[4] + or @acc[7],@acc[6],@acc[6] + or @acc[2],@acc[0],@acc[0] + or @acc[6],@acc[4],@acc[4] + or @acc[4],@acc[0],@acc[0] + st @acc[0],[%fp+STACK_BIAS-20] + + add $ap_real,0,$bp + add %sp,LOCALS+$Z2sqr,$ap + call __ecp_nistz256_mul_mont ! p256_mul_mont(U1, in1_x, Z2sqr); + add %sp,LOCALS+$U1,$rp + + add $bp_real,0,$bp + add %sp,LOCALS+$Z1sqr,$ap + call __ecp_nistz256_mul_mont ! p256_mul_mont(U2, in2_x, Z1sqr); + add %sp,LOCALS+$U2,$rp + + add %sp,LOCALS+$U1,$bp + call __ecp_nistz256_sub_from ! p256_sub(H, U2, U1); + add %sp,LOCALS+$H,$rp + + or @acc[1],@acc[0],@acc[0] ! see if result is zero + or @acc[3],@acc[2],@acc[2] + or @acc[5],@acc[4],@acc[4] + or @acc[7],@acc[6],@acc[6] + or @acc[2],@acc[0],@acc[0] + or @acc[6],@acc[4],@acc[4] + orcc @acc[4],@acc[0],@acc[0] + + bne,pt %icc,.Ladd_proceed ! is_equal(U1,U2)? + nop + + ld [%fp+STACK_BIAS-12],$t0 + ld [%fp+STACK_BIAS-16],$t1 + ld [%fp+STACK_BIAS-20],$t2 + andcc $t0,$t1,%g0 + be,pt %icc,.Ladd_proceed ! (in1infty || in2infty)? + nop + andcc $t2,$t2,%g0 + be,pt %icc,.Ladd_double ! is_equal(S1,S2)? + nop + + ldx [%fp+STACK_BIAS-8],$rp + st %g0,[$rp] + st %g0,[$rp+4] + st %g0,[$rp+8] + st %g0,[$rp+12] + st %g0,[$rp+16] + st %g0,[$rp+20] + st %g0,[$rp+24] + st %g0,[$rp+28] + st %g0,[$rp+32] + st %g0,[$rp+32+4] + st %g0,[$rp+32+8] + st %g0,[$rp+32+12] + st %g0,[$rp+32+16] + st %g0,[$rp+32+20] + st %g0,[$rp+32+24] + st %g0,[$rp+32+28] + st %g0,[$rp+64] + st %g0,[$rp+64+4] + st %g0,[$rp+64+8] + st %g0,[$rp+64+12] + st %g0,[$rp+64+16] + st %g0,[$rp+64+20] + st %g0,[$rp+64+24] + st %g0,[$rp+64+28] + b .Ladd_done + nop + +.align 16 +.Ladd_double: + ldx [%fp+STACK_BIAS-8],$rp_real + mov $ap_real,$ap + b .Lpoint_double_shortcut + add %sp,32*(12-4)+32,%sp ! difference in frame sizes + +.align 16 +.Ladd_proceed: + add %sp,LOCALS+$R,$bp + add %sp,LOCALS+$R,$ap + call __ecp_nistz256_mul_mont ! p256_sqr_mont(Rsqr, R); + add %sp,LOCALS+$Rsqr,$rp + + add $ap_real,64,$bp + add %sp,LOCALS+$H,$ap + call __ecp_nistz256_mul_mont ! p256_mul_mont(res_z, H, in1_z); + add %sp,LOCALS+$res_z,$rp + + add %sp,LOCALS+$H,$bp + add %sp,LOCALS+$H,$ap + call __ecp_nistz256_mul_mont ! p256_sqr_mont(Hsqr, H); + add %sp,LOCALS+$Hsqr,$rp + + add $bp_real,64,$bp + add %sp,LOCALS+$res_z,$ap + call __ecp_nistz256_mul_mont ! p256_mul_mont(res_z, res_z, in2_z); + add %sp,LOCALS+$res_z,$rp + + add %sp,LOCALS+$H,$bp + add %sp,LOCALS+$Hsqr,$ap + call __ecp_nistz256_mul_mont ! p256_mul_mont(Hcub, Hsqr, H); + add %sp,LOCALS+$Hcub,$rp + + add %sp,LOCALS+$U1,$bp + add %sp,LOCALS+$Hsqr,$ap + call __ecp_nistz256_mul_mont ! p256_mul_mont(U2, U1, Hsqr); + add %sp,LOCALS+$U2,$rp + + call __ecp_nistz256_mul_by_2 ! p256_mul_by_2(Hsqr, U2); + add %sp,LOCALS+$Hsqr,$rp + + add %sp,LOCALS+$Rsqr,$bp + call __ecp_nistz256_sub_morf ! p256_sub(res_x, Rsqr, Hsqr); + add %sp,LOCALS+$res_x,$rp + + add %sp,LOCALS+$Hcub,$bp + call __ecp_nistz256_sub_from ! p256_sub(res_x, res_x, Hcub); + add %sp,LOCALS+$res_x,$rp + + add %sp,LOCALS+$U2,$bp + call __ecp_nistz256_sub_morf ! p256_sub(res_y, U2, res_x); + add %sp,LOCALS+$res_y,$rp + + add %sp,LOCALS+$Hcub,$bp + add %sp,LOCALS+$S1,$ap + call __ecp_nistz256_mul_mont ! p256_mul_mont(S2, S1, Hcub); + add %sp,LOCALS+$S2,$rp + + add %sp,LOCALS+$R,$bp + add %sp,LOCALS+$res_y,$ap + call __ecp_nistz256_mul_mont ! p256_mul_mont(res_y, res_y, R); + add %sp,LOCALS+$res_y,$rp + + add %sp,LOCALS+$S2,$bp + call __ecp_nistz256_sub_from ! p256_sub(res_y, res_y, S2); + add %sp,LOCALS+$res_y,$rp + + ld [%fp+STACK_BIAS-16],$t1 ! !in1infty + ld [%fp+STACK_BIAS-12],$t2 ! !in2infty + ldx [%fp+STACK_BIAS-8],$rp +___ +for($i=0;$i<96;$i+=8) { # conditional moves +$code.=<<___; + ld [%sp+LOCALS+$i],@acc[0] ! res + ld [%sp+LOCALS+$i+4],@acc[1] + ld [$bp_real+$i],@acc[2] ! in2 + ld [$bp_real+$i+4],@acc[3] + ld [$ap_real+$i],@acc[4] ! in1 + ld [$ap_real+$i+4],@acc[5] + movrz $t1,@acc[2],@acc[0] + movrz $t1,@acc[3],@acc[1] + movrz $t2,@acc[4],@acc[0] + movrz $t2,@acc[5],@acc[1] + st @acc[0],[$rp+$i] + st @acc[1],[$rp+$i+4] +___ +} +$code.=<<___; +.Ladd_done: + ret + restore +.type ecp_nistz256_point_add,#function +.size ecp_nistz256_point_add,.-ecp_nistz256_point_add +___ +} + +######################################################################## +# void ecp_nistz256_point_add_affine(P256_POINT *out,const P256_POINT *in1, +# const P256_POINT_AFFINE *in2); +{ +my ($res_x,$res_y,$res_z, + $U2,$S2,$H,$R,$Hsqr,$Hcub,$Rsqr)=map(32*$_,(0..9)); +my $Z1sqr = $S2; +# above map() describes stack layout with 10 temporary +# 256-bit vectors on top. Then we reserve some space for +# !in1infty, !in2infty, result of check for zero and return pointer. + +my @ONE_mont=(1,0,0,-1,-1,-1,-2,0); +my $bp_real=$rp_real; + +$code.=<<___; +.globl ecp_nistz256_point_add_affine +.align 32 +ecp_nistz256_point_add_affine: + SPARC_LOAD_ADDRESS_LEAF(OPENSSL_sparcv9cap_P,%g1,%g5) + ld [%g1],%g1 ! OPENSSL_sparcv9cap_P[0] + and %g1,(SPARCV9_VIS3|SPARCV9_64BIT_STACK),%g1 + cmp %g1,(SPARCV9_VIS3|SPARCV9_64BIT_STACK) + be ecp_nistz256_point_add_affine_vis3 + nop + + save %sp,-STACK_FRAME-32*10-32,%sp + + stx $rp,[%fp+STACK_BIAS-8] ! off-load $rp + mov $ap,$ap_real + mov $bp,$bp_real + + ld [$ap+64],$t0 ! in1_z + ld [$ap+64+4],$t1 + ld [$ap+64+8],$t2 + ld [$ap+64+12],$t3 + ld [$ap+64+16],$t4 + ld [$ap+64+20],$t5 + ld [$ap+64+24],$t6 + ld [$ap+64+28],$t7 + or $t1,$t0,$t0 + or $t3,$t2,$t2 + or $t5,$t4,$t4 + or $t7,$t6,$t6 + or $t2,$t0,$t0 + or $t6,$t4,$t4 + or $t4,$t0,$t0 ! !in1infty + movrnz $t0,-1,$t0 + st $t0,[%fp+STACK_BIAS-16] + + ld [$bp],@acc[0] ! in2_x + ld [$bp+4],@acc[1] + ld [$bp+8],@acc[2] + ld [$bp+12],@acc[3] + ld [$bp+16],@acc[4] + ld [$bp+20],@acc[5] + ld [$bp+24],@acc[6] + ld [$bp+28],@acc[7] + ld [$bp+32],$t0 ! in2_y + ld [$bp+32+4],$t1 + ld [$bp+32+8],$t2 + ld [$bp+32+12],$t3 + ld [$bp+32+16],$t4 + ld [$bp+32+20],$t5 + ld [$bp+32+24],$t6 + ld [$bp+32+28],$t7 + or @acc[1],@acc[0],@acc[0] + or @acc[3],@acc[2],@acc[2] + or @acc[5],@acc[4],@acc[4] + or @acc[7],@acc[6],@acc[6] + or @acc[2],@acc[0],@acc[0] + or @acc[6],@acc[4],@acc[4] + or @acc[4],@acc[0],@acc[0] + or $t1,$t0,$t0 + or $t3,$t2,$t2 + or $t5,$t4,$t4 + or $t7,$t6,$t6 + or $t2,$t0,$t0 + or $t6,$t4,$t4 + or $t4,$t0,$t0 + or @acc[0],$t0,$t0 ! !in2infty + movrnz $t0,-1,$t0 + st $t0,[%fp+STACK_BIAS-12] + + add $ap_real,64,$bp + add $ap_real,64,$ap + call __ecp_nistz256_mul_mont ! p256_sqr_mont(Z1sqr, in1_z); + add %sp,LOCALS+$Z1sqr,$rp + + add $bp_real,0,$bp + add %sp,LOCALS+$Z1sqr,$ap + call __ecp_nistz256_mul_mont ! p256_mul_mont(U2, Z1sqr, in2_x); + add %sp,LOCALS+$U2,$rp + + add $ap_real,0,$bp + call __ecp_nistz256_sub_from ! p256_sub(H, U2, in1_x); + add %sp,LOCALS+$H,$rp + + add $ap_real,64,$bp + add %sp,LOCALS+$Z1sqr,$ap + call __ecp_nistz256_mul_mont ! p256_mul_mont(S2, Z1sqr, in1_z); + add %sp,LOCALS+$S2,$rp + + add $ap_real,64,$bp + add %sp,LOCALS+$H,$ap + call __ecp_nistz256_mul_mont ! p256_mul_mont(res_z, H, in1_z); + add %sp,LOCALS+$res_z,$rp + + add $bp_real,32,$bp + add %sp,LOCALS+$S2,$ap + call __ecp_nistz256_mul_mont ! p256_mul_mont(S2, S2, in2_y); + add %sp,LOCALS+$S2,$rp + + add $ap_real,32,$bp + call __ecp_nistz256_sub_from ! p256_sub(R, S2, in1_y); + add %sp,LOCALS+$R,$rp + + add %sp,LOCALS+$H,$bp + add %sp,LOCALS+$H,$ap + call __ecp_nistz256_mul_mont ! p256_sqr_mont(Hsqr, H); + add %sp,LOCALS+$Hsqr,$rp + + add %sp,LOCALS+$R,$bp + add %sp,LOCALS+$R,$ap + call __ecp_nistz256_mul_mont ! p256_sqr_mont(Rsqr, R); + add %sp,LOCALS+$Rsqr,$rp + + add %sp,LOCALS+$H,$bp + add %sp,LOCALS+$Hsqr,$ap + call __ecp_nistz256_mul_mont ! p256_mul_mont(Hcub, Hsqr, H); + add %sp,LOCALS+$Hcub,$rp + + add $ap_real,0,$bp + add %sp,LOCALS+$Hsqr,$ap + call __ecp_nistz256_mul_mont ! p256_mul_mont(U2, in1_x, Hsqr); + add %sp,LOCALS+$U2,$rp + + call __ecp_nistz256_mul_by_2 ! p256_mul_by_2(Hsqr, U2); + add %sp,LOCALS+$Hsqr,$rp + + add %sp,LOCALS+$Rsqr,$bp + call __ecp_nistz256_sub_morf ! p256_sub(res_x, Rsqr, Hsqr); + add %sp,LOCALS+$res_x,$rp + + add %sp,LOCALS+$Hcub,$bp + call __ecp_nistz256_sub_from ! p256_sub(res_x, res_x, Hcub); + add %sp,LOCALS+$res_x,$rp + + add %sp,LOCALS+$U2,$bp + call __ecp_nistz256_sub_morf ! p256_sub(res_y, U2, res_x); + add %sp,LOCALS+$res_y,$rp + + add $ap_real,32,$bp + add %sp,LOCALS+$Hcub,$ap + call __ecp_nistz256_mul_mont ! p256_mul_mont(S2, in1_y, Hcub); + add %sp,LOCALS+$S2,$rp + + add %sp,LOCALS+$R,$bp + add %sp,LOCALS+$res_y,$ap + call __ecp_nistz256_mul_mont ! p256_mul_mont(res_y, res_y, R); + add %sp,LOCALS+$res_y,$rp + + add %sp,LOCALS+$S2,$bp + call __ecp_nistz256_sub_from ! p256_sub(res_y, res_y, S2); + add %sp,LOCALS+$res_y,$rp + + ld [%fp+STACK_BIAS-16],$t1 ! !in1infty + ld [%fp+STACK_BIAS-12],$t2 ! !in2infty + ldx [%fp+STACK_BIAS-8],$rp +___ +for($i=0;$i<64;$i+=8) { # conditional moves +$code.=<<___; + ld [%sp+LOCALS+$i],@acc[0] ! res + ld [%sp+LOCALS+$i+4],@acc[1] + ld [$bp_real+$i],@acc[2] ! in2 + ld [$bp_real+$i+4],@acc[3] + ld [$ap_real+$i],@acc[4] ! in1 + ld [$ap_real+$i+4],@acc[5] + movrz $t1,@acc[2],@acc[0] + movrz $t1,@acc[3],@acc[1] + movrz $t2,@acc[4],@acc[0] + movrz $t2,@acc[5],@acc[1] + st @acc[0],[$rp+$i] + st @acc[1],[$rp+$i+4] +___ +} +for(;$i<96;$i+=8) { +my $j=($i-64)/4; +$code.=<<___; + ld [%sp+LOCALS+$i],@acc[0] ! res + ld [%sp+LOCALS+$i+4],@acc[1] + ld [$ap_real+$i],@acc[4] ! in1 + ld [$ap_real+$i+4],@acc[5] + movrz $t1,@ONE_mont[$j],@acc[0] + movrz $t1,@ONE_mont[$j+1],@acc[1] + movrz $t2,@acc[4],@acc[0] + movrz $t2,@acc[5],@acc[1] + st @acc[0],[$rp+$i] + st @acc[1],[$rp+$i+4] +___ +} +$code.=<<___; + ret + restore +.type ecp_nistz256_point_add_affine,#function +.size ecp_nistz256_point_add_affine,.-ecp_nistz256_point_add_affine +___ +} }}} +{{{ +my ($out,$inp,$index)=map("%i$_",(0..2)); +my $mask="%o0"; + +$code.=<<___; +! void ecp_nistz256_scatter_w5(void *%i0,const P256_POINT *%i1, +! int %i2); +.globl ecp_nistz256_scatter_w5 +.align 32 +ecp_nistz256_scatter_w5: + save %sp,-STACK_FRAME,%sp + + sll $index,2,$index + add $out,$index,$out + + ld [$inp],%l0 ! X + ld [$inp+4],%l1 + ld [$inp+8],%l2 + ld [$inp+12],%l3 + ld [$inp+16],%l4 + ld [$inp+20],%l5 + ld [$inp+24],%l6 + ld [$inp+28],%l7 + add $inp,32,$inp + st %l0,[$out+64*0-4] + st %l1,[$out+64*1-4] + st %l2,[$out+64*2-4] + st %l3,[$out+64*3-4] + st %l4,[$out+64*4-4] + st %l5,[$out+64*5-4] + st %l6,[$out+64*6-4] + st %l7,[$out+64*7-4] + add $out,64*8,$out + + ld [$inp],%l0 ! Y + ld [$inp+4],%l1 + ld [$inp+8],%l2 + ld [$inp+12],%l3 + ld [$inp+16],%l4 + ld [$inp+20],%l5 + ld [$inp+24],%l6 + ld [$inp+28],%l7 + add $inp,32,$inp + st %l0,[$out+64*0-4] + st %l1,[$out+64*1-4] + st %l2,[$out+64*2-4] + st %l3,[$out+64*3-4] + st %l4,[$out+64*4-4] + st %l5,[$out+64*5-4] + st %l6,[$out+64*6-4] + st %l7,[$out+64*7-4] + add $out,64*8,$out + + ld [$inp],%l0 ! Z + ld [$inp+4],%l1 + ld [$inp+8],%l2 + ld [$inp+12],%l3 + ld [$inp+16],%l4 + ld [$inp+20],%l5 + ld [$inp+24],%l6 + ld [$inp+28],%l7 + st %l0,[$out+64*0-4] + st %l1,[$out+64*1-4] + st %l2,[$out+64*2-4] + st %l3,[$out+64*3-4] + st %l4,[$out+64*4-4] + st %l5,[$out+64*5-4] + st %l6,[$out+64*6-4] + st %l7,[$out+64*7-4] + + ret + restore +.type ecp_nistz256_scatter_w5,#function +.size ecp_nistz256_scatter_w5,.-ecp_nistz256_scatter_w5 + +! void ecp_nistz256_gather_w5(P256_POINT *%i0,const void *%i1, +! int %i2); +.globl ecp_nistz256_gather_w5 +.align 32 +ecp_nistz256_gather_w5: + save %sp,-STACK_FRAME,%sp + + neg $index,$mask + srax $mask,63,$mask + + add $index,$mask,$index + sll $index,2,$index + add $inp,$index,$inp + + ld [$inp+64*0],%l0 + ld [$inp+64*1],%l1 + ld [$inp+64*2],%l2 + ld [$inp+64*3],%l3 + ld [$inp+64*4],%l4 + ld [$inp+64*5],%l5 + ld [$inp+64*6],%l6 + ld [$inp+64*7],%l7 + add $inp,64*8,$inp + and %l0,$mask,%l0 + and %l1,$mask,%l1 + st %l0,[$out] ! X + and %l2,$mask,%l2 + st %l1,[$out+4] + and %l3,$mask,%l3 + st %l2,[$out+8] + and %l4,$mask,%l4 + st %l3,[$out+12] + and %l5,$mask,%l5 + st %l4,[$out+16] + and %l6,$mask,%l6 + st %l5,[$out+20] + and %l7,$mask,%l7 + st %l6,[$out+24] + st %l7,[$out+28] + add $out,32,$out + + ld [$inp+64*0],%l0 + ld [$inp+64*1],%l1 + ld [$inp+64*2],%l2 + ld [$inp+64*3],%l3 + ld [$inp+64*4],%l4 + ld [$inp+64*5],%l5 + ld [$inp+64*6],%l6 + ld [$inp+64*7],%l7 + add $inp,64*8,$inp + and %l0,$mask,%l0 + and %l1,$mask,%l1 + st %l0,[$out] ! Y + and %l2,$mask,%l2 + st %l1,[$out+4] + and %l3,$mask,%l3 + st %l2,[$out+8] + and %l4,$mask,%l4 + st %l3,[$out+12] + and %l5,$mask,%l5 + st %l4,[$out+16] + and %l6,$mask,%l6 + st %l5,[$out+20] + and %l7,$mask,%l7 + st %l6,[$out+24] + st %l7,[$out+28] + add $out,32,$out + + ld [$inp+64*0],%l0 + ld [$inp+64*1],%l1 + ld [$inp+64*2],%l2 + ld [$inp+64*3],%l3 + ld [$inp+64*4],%l4 + ld [$inp+64*5],%l5 + ld [$inp+64*6],%l6 + ld [$inp+64*7],%l7 + and %l0,$mask,%l0 + and %l1,$mask,%l1 + st %l0,[$out] ! Z + and %l2,$mask,%l2 + st %l1,[$out+4] + and %l3,$mask,%l3 + st %l2,[$out+8] + and %l4,$mask,%l4 + st %l3,[$out+12] + and %l5,$mask,%l5 + st %l4,[$out+16] + and %l6,$mask,%l6 + st %l5,[$out+20] + and %l7,$mask,%l7 + st %l6,[$out+24] + st %l7,[$out+28] + + ret + restore +.type ecp_nistz256_gather_w5,#function +.size ecp_nistz256_gather_w5,.-ecp_nistz256_gather_w5 + +! void ecp_nistz256_scatter_w7(void *%i0,const P256_POINT_AFFINE *%i1, +! int %i2); +.globl ecp_nistz256_scatter_w7 +.align 32 +ecp_nistz256_scatter_w7: + save %sp,-STACK_FRAME,%sp + nop + add $out,$index,$out + mov 64/4,$index +.Loop_scatter_w7: + ld [$inp],%l0 + add $inp,4,$inp + subcc $index,1,$index + stb %l0,[$out+64*0] + srl %l0,8,%l1 + stb %l1,[$out+64*1] + srl %l0,16,%l2 + stb %l2,[$out+64*2] + srl %l0,24,%l3 + stb %l3,[$out+64*3] + bne .Loop_scatter_w7 + add $out,64*4,$out + + ret + restore +.type ecp_nistz256_scatter_w7,#function +.size ecp_nistz256_scatter_w7,.-ecp_nistz256_scatter_w7 + +! void ecp_nistz256_gather_w7(P256_POINT_AFFINE *%i0,const void *%i1, +! int %i2); +.globl ecp_nistz256_gather_w7 +.align 32 +ecp_nistz256_gather_w7: + save %sp,-STACK_FRAME,%sp + + neg $index,$mask + srax $mask,63,$mask + + add $index,$mask,$index + add $inp,$index,$inp + mov 64/4,$index + +.Loop_gather_w7: + ldub [$inp+64*0],%l0 + prefetch [$inp+3840+64*0],1 + subcc $index,1,$index + ldub [$inp+64*1],%l1 + prefetch [$inp+3840+64*1],1 + ldub [$inp+64*2],%l2 + prefetch [$inp+3840+64*2],1 + ldub [$inp+64*3],%l3 + prefetch [$inp+3840+64*3],1 + add $inp,64*4,$inp + sll %l1,8,%l1 + sll %l2,16,%l2 + or %l0,%l1,%l0 + sll %l3,24,%l3 + or %l0,%l2,%l0 + or %l0,%l3,%l0 + and %l0,$mask,%l0 + st %l0,[$out] + bne .Loop_gather_w7 + add $out,4,$out + + ret + restore +.type ecp_nistz256_gather_w7,#function +.size ecp_nistz256_gather_w7,.-ecp_nistz256_gather_w7 +___ +}}} +{{{ +######################################################################## +# Following subroutines are VIS3 counterparts of those above that +# implement ones found in ecp_nistz256.c. Key difference is that they +# use 128-bit multiplication and addition with 64-bit carry, and in order +# to do that they perform conversion from uin32_t[8] to uint64_t[4] upon +# entry and vice versa on return. +# +my ($rp,$ap,$bp)=map("%i$_",(0..2)); +my ($t0,$t1,$t2,$t3,$a0,$a1,$a2,$a3)=map("%l$_",(0..7)); +my ($acc0,$acc1,$acc2,$acc3,$acc4,$acc5)=map("%o$_",(0..5)); +my ($bi,$poly1,$poly3,$minus1)=(map("%i$_",(3..5)),"%g1"); +my ($rp_real,$ap_real)=("%g2","%g3"); +my ($acc6,$acc7)=($bp,$bi); # used in squaring + +$code.=<<___; +.align 32 +__ecp_nistz256_mul_by_2_vis3: + addcc $acc0,$acc0,$acc0 + addxccc $acc1,$acc1,$acc1 + addxccc $acc2,$acc2,$acc2 + addxccc $acc3,$acc3,$acc3 + b .Lreduce_by_sub_vis3 + addxc %g0,%g0,$acc4 ! did it carry? +.type __ecp_nistz256_mul_by_2_vis3,#function +.size __ecp_nistz256_mul_by_2_vis3,.-__ecp_nistz256_mul_by_2_vis3 + +.align 32 +__ecp_nistz256_add_vis3: + ldx [$bp+0],$t0 + ldx [$bp+8],$t1 + ldx [$bp+16],$t2 + ldx [$bp+24],$t3 + +__ecp_nistz256_add_noload_vis3: + + addcc $t0,$acc0,$acc0 + addxccc $t1,$acc1,$acc1 + addxccc $t2,$acc2,$acc2 + addxccc $t3,$acc3,$acc3 + addxc %g0,%g0,$acc4 ! did it carry? + +.Lreduce_by_sub_vis3: + + addcc $acc0,1,$t0 ! add -modulus, i.e. subtract + addxccc $acc1,$poly1,$t1 + addxccc $acc2,$minus1,$t2 + addxccc $acc3,$poly3,$t3 + addxc $acc4,$minus1,$acc4 + + movrz $acc4,$t0,$acc0 ! ret = borrow ? ret : ret-modulus + movrz $acc4,$t1,$acc1 + stx $acc0,[$rp] + movrz $acc4,$t2,$acc2 + stx $acc1,[$rp+8] + movrz $acc4,$t3,$acc3 + stx $acc2,[$rp+16] + retl + stx $acc3,[$rp+24] +.type __ecp_nistz256_add_vis3,#function +.size __ecp_nistz256_add_vis3,.-__ecp_nistz256_add_vis3 + +! Trouble with subtraction is that there is no subtraction with 64-bit +! borrow, only with 32-bit one. For this reason we "decompose" 64-bit +! $acc0-$acc3 to 32-bit values and pick b[4] in 32-bit pieces. But +! recall that SPARC is big-endian, which is why you'll observe that +! b[4] is accessed as 4-0-12-8-20-16-28-24. And prior reduction we +! "collect" result back to 64-bit $acc0-$acc3. +.align 32 +__ecp_nistz256_sub_from_vis3: + ld [$bp+4],$t0 + ld [$bp+0],$t1 + ld [$bp+12],$t2 + ld [$bp+8],$t3 + + srlx $acc0,32,$acc4 + not $poly1,$poly1 + srlx $acc1,32,$acc5 + subcc $acc0,$t0,$acc0 + ld [$bp+20],$t0 + subccc $acc4,$t1,$acc4 + ld [$bp+16],$t1 + subccc $acc1,$t2,$acc1 + ld [$bp+28],$t2 + and $acc0,$poly1,$acc0 + subccc $acc5,$t3,$acc5 + ld [$bp+24],$t3 + sllx $acc4,32,$acc4 + and $acc1,$poly1,$acc1 + sllx $acc5,32,$acc5 + or $acc0,$acc4,$acc0 + srlx $acc2,32,$acc4 + or $acc1,$acc5,$acc1 + srlx $acc3,32,$acc5 + subccc $acc2,$t0,$acc2 + subccc $acc4,$t1,$acc4 + subccc $acc3,$t2,$acc3 + and $acc2,$poly1,$acc2 + subccc $acc5,$t3,$acc5 + sllx $acc4,32,$acc4 + and $acc3,$poly1,$acc3 + sllx $acc5,32,$acc5 + or $acc2,$acc4,$acc2 + subc %g0,%g0,$acc4 ! did it borrow? + b .Lreduce_by_add_vis3 + or $acc3,$acc5,$acc3 +.type __ecp_nistz256_sub_from_vis3,#function +.size __ecp_nistz256_sub_from_vis3,.-__ecp_nistz256_sub_from_vis3 + +.align 32 +__ecp_nistz256_sub_morf_vis3: + ld [$bp+4],$t0 + ld [$bp+0],$t1 + ld [$bp+12],$t2 + ld [$bp+8],$t3 + + srlx $acc0,32,$acc4 + not $poly1,$poly1 + srlx $acc1,32,$acc5 + subcc $t0,$acc0,$acc0 + ld [$bp+20],$t0 + subccc $t1,$acc4,$acc4 + ld [$bp+16],$t1 + subccc $t2,$acc1,$acc1 + ld [$bp+28],$t2 + and $acc0,$poly1,$acc0 + subccc $t3,$acc5,$acc5 + ld [$bp+24],$t3 + sllx $acc4,32,$acc4 + and $acc1,$poly1,$acc1 + sllx $acc5,32,$acc5 + or $acc0,$acc4,$acc0 + srlx $acc2,32,$acc4 + or $acc1,$acc5,$acc1 + srlx $acc3,32,$acc5 + subccc $t0,$acc2,$acc2 + subccc $t1,$acc4,$acc4 + subccc $t2,$acc3,$acc3 + and $acc2,$poly1,$acc2 + subccc $t3,$acc5,$acc5 + sllx $acc4,32,$acc4 + and $acc3,$poly1,$acc3 + sllx $acc5,32,$acc5 + or $acc2,$acc4,$acc2 + subc %g0,%g0,$acc4 ! did it borrow? + or $acc3,$acc5,$acc3 + +.Lreduce_by_add_vis3: + + addcc $acc0,-1,$t0 ! add modulus + not $poly3,$t3 + addxccc $acc1,$poly1,$t1 + not $poly1,$poly1 ! restore $poly1 + addxccc $acc2,%g0,$t2 + addxc $acc3,$t3,$t3 + + movrnz $acc4,$t0,$acc0 ! if a-b borrowed, ret = ret+mod + movrnz $acc4,$t1,$acc1 + stx $acc0,[$rp] + movrnz $acc4,$t2,$acc2 + stx $acc1,[$rp+8] + movrnz $acc4,$t3,$acc3 + stx $acc2,[$rp+16] + retl + stx $acc3,[$rp+24] +.type __ecp_nistz256_sub_morf_vis3,#function +.size __ecp_nistz256_sub_morf_vis3,.-__ecp_nistz256_sub_morf_vis3 + +.align 32 +__ecp_nistz256_div_by_2_vis3: + ! ret = (a is odd ? a+mod : a) >> 1 + + not $poly1,$t1 + not $poly3,$t3 + and $acc0,1,$acc5 + addcc $acc0,-1,$t0 ! add modulus + addxccc $acc1,$t1,$t1 + addxccc $acc2,%g0,$t2 + addxccc $acc3,$t3,$t3 + addxc %g0,%g0,$acc4 ! carry bit + + movrnz $acc5,$t0,$acc0 + movrnz $acc5,$t1,$acc1 + movrnz $acc5,$t2,$acc2 + movrnz $acc5,$t3,$acc3 + movrz $acc5,%g0,$acc4 + + ! ret >>= 1 + + srlx $acc0,1,$acc0 + sllx $acc1,63,$t0 + srlx $acc1,1,$acc1 + or $acc0,$t0,$acc0 + sllx $acc2,63,$t1 + srlx $acc2,1,$acc2 + or $acc1,$t1,$acc1 + sllx $acc3,63,$t2 + stx $acc0,[$rp] + srlx $acc3,1,$acc3 + or $acc2,$t2,$acc2 + sllx $acc4,63,$t3 ! don't forget carry bit + stx $acc1,[$rp+8] + or $acc3,$t3,$acc3 + stx $acc2,[$rp+16] + retl + stx $acc3,[$rp+24] +.type __ecp_nistz256_div_by_2_vis3,#function +.size __ecp_nistz256_div_by_2_vis3,.-__ecp_nistz256_div_by_2_vis3 + +! compared to __ecp_nistz256_mul_mont it's almost 4x smaller and +! 4x faster [on T4]... +.align 32 +__ecp_nistz256_mul_mont_vis3: + mulx $a0,$bi,$acc0 + not $poly3,$poly3 ! 0xFFFFFFFF00000001 + umulxhi $a0,$bi,$t0 + mulx $a1,$bi,$acc1 + umulxhi $a1,$bi,$t1 + mulx $a2,$bi,$acc2 + umulxhi $a2,$bi,$t2 + mulx $a3,$bi,$acc3 + umulxhi $a3,$bi,$t3 + ldx [$bp+8],$bi ! b[1] + + addcc $acc1,$t0,$acc1 ! accumulate high parts of multiplication + sllx $acc0,32,$t0 + addxccc $acc2,$t1,$acc2 + srlx $acc0,32,$t1 + addxccc $acc3,$t2,$acc3 + addxc %g0,$t3,$acc4 + mov 0,$acc5 +___ +for($i=1;$i<4;$i++) { + # Reduction iteration is normally performed by accumulating + # result of multiplication of modulus by "magic" digit [and + # omitting least significant word, which is guaranteed to + # be 0], but thanks to special form of modulus and "magic" + # digit being equal to least significant word, it can be + # performed with additions and subtractions alone. Indeed: + # + # ffff0001.00000000.0000ffff.ffffffff + # * abcdefgh + # + xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx.abcdefgh + # + # Now observing that ff..ff*x = (2^n-1)*x = 2^n*x-x, we + # rewrite above as: + # + # xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx.abcdefgh + # + abcdefgh.abcdefgh.0000abcd.efgh0000.00000000 + # - 0000abcd.efgh0000.00000000.00000000.abcdefgh + # + # or marking redundant operations: + # + # xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx.-------- + # + abcdefgh.abcdefgh.0000abcd.efgh0000.-------- + # - 0000abcd.efgh0000.--------.--------.-------- + # ^^^^^^^^ but this word is calculated with umulxhi, because + # there is no subtract with 64-bit borrow:-( + +$code.=<<___; + sub $acc0,$t0,$t2 ! acc0*0xFFFFFFFF00000001, low part + umulxhi $acc0,$poly3,$t3 ! acc0*0xFFFFFFFF00000001, high part + addcc $acc1,$t0,$acc0 ! +=acc[0]<<96 and omit acc[0] + mulx $a0,$bi,$t0 + addxccc $acc2,$t1,$acc1 + mulx $a1,$bi,$t1 + addxccc $acc3,$t2,$acc2 ! +=acc[0]*0xFFFFFFFF00000001 + mulx $a2,$bi,$t2 + addxccc $acc4,$t3,$acc3 + mulx $a3,$bi,$t3 + addxc $acc5,%g0,$acc4 + + addcc $acc0,$t0,$acc0 ! accumulate low parts of multiplication + umulxhi $a0,$bi,$t0 + addxccc $acc1,$t1,$acc1 + umulxhi $a1,$bi,$t1 + addxccc $acc2,$t2,$acc2 + umulxhi $a2,$bi,$t2 + addxccc $acc3,$t3,$acc3 + umulxhi $a3,$bi,$t3 + addxc $acc4,%g0,$acc4 +___ +$code.=<<___ if ($i<3); + ldx [$bp+8*($i+1)],$bi ! bp[$i+1] +___ +$code.=<<___; + addcc $acc1,$t0,$acc1 ! accumulate high parts of multiplication + sllx $acc0,32,$t0 + addxccc $acc2,$t1,$acc2 + srlx $acc0,32,$t1 + addxccc $acc3,$t2,$acc3 + addxccc $acc4,$t3,$acc4 + addxc %g0,%g0,$acc5 +___ +} +$code.=<<___; + sub $acc0,$t0,$t2 ! acc0*0xFFFFFFFF00000001, low part + umulxhi $acc0,$poly3,$t3 ! acc0*0xFFFFFFFF00000001, high part + addcc $acc1,$t0,$acc0 ! +=acc[0]<<96 and omit acc[0] + addxccc $acc2,$t1,$acc1 + addxccc $acc3,$t2,$acc2 ! +=acc[0]*0xFFFFFFFF00000001 + addxccc $acc4,$t3,$acc3 + b .Lmul_final_vis3 ! see below + addxc $acc5,%g0,$acc4 +.type __ecp_nistz256_mul_mont_vis3,#function +.size __ecp_nistz256_mul_mont_vis3,.-__ecp_nistz256_mul_mont_vis3 + +! compared to above __ecp_nistz256_mul_mont_vis3 it's 21% less +! instructions, but only 14% faster [on T4]... +.align 32 +__ecp_nistz256_sqr_mont_vis3: + ! | | | | | |a1*a0| | + ! | | | | |a2*a0| | | + ! | |a3*a2|a3*a0| | | | + ! | | | |a2*a1| | | | + ! | | |a3*a1| | | | | + ! *| | | | | | | | 2| + ! +|a3*a3|a2*a2|a1*a1|a0*a0| + ! |--+--+--+--+--+--+--+--| + ! |A7|A6|A5|A4|A3|A2|A1|A0|, where Ax is $accx, i.e. follow $accx + ! + ! "can't overflow" below mark carrying into high part of + ! multiplication result, which can't overflow, because it + ! can never be all ones. + + mulx $a1,$a0,$acc1 ! a[1]*a[0] + umulxhi $a1,$a0,$t1 + mulx $a2,$a0,$acc2 ! a[2]*a[0] + umulxhi $a2,$a0,$t2 + mulx $a3,$a0,$acc3 ! a[3]*a[0] + umulxhi $a3,$a0,$acc4 + + addcc $acc2,$t1,$acc2 ! accumulate high parts of multiplication + mulx $a2,$a1,$t0 ! a[2]*a[1] + umulxhi $a2,$a1,$t1 + addxccc $acc3,$t2,$acc3 + mulx $a3,$a1,$t2 ! a[3]*a[1] + umulxhi $a3,$a1,$t3 + addxc $acc4,%g0,$acc4 ! can't overflow + + mulx $a3,$a2,$acc5 ! a[3]*a[2] + not $poly3,$poly3 ! 0xFFFFFFFF00000001 + umulxhi $a3,$a2,$acc6 + + addcc $t2,$t1,$t1 ! accumulate high parts of multiplication + mulx $a0,$a0,$acc0 ! a[0]*a[0] + addxc $t3,%g0,$t2 ! can't overflow + + addcc $acc3,$t0,$acc3 ! accumulate low parts of multiplication + umulxhi $a0,$a0,$a0 + addxccc $acc4,$t1,$acc4 + mulx $a1,$a1,$t1 ! a[1]*a[1] + addxccc $acc5,$t2,$acc5 + umulxhi $a1,$a1,$a1 + addxc $acc6,%g0,$acc6 ! can't overflow + + addcc $acc1,$acc1,$acc1 ! acc[1-6]*=2 + mulx $a2,$a2,$t2 ! a[2]*a[2] + addxccc $acc2,$acc2,$acc2 + umulxhi $a2,$a2,$a2 + addxccc $acc3,$acc3,$acc3 + mulx $a3,$a3,$t3 ! a[3]*a[3] + addxccc $acc4,$acc4,$acc4 + umulxhi $a3,$a3,$a3 + addxccc $acc5,$acc5,$acc5 + addxccc $acc6,$acc6,$acc6 + addxc %g0,%g0,$acc7 + + addcc $acc1,$a0,$acc1 ! +a[i]*a[i] + addxccc $acc2,$t1,$acc2 + addxccc $acc3,$a1,$acc3 + addxccc $acc4,$t2,$acc4 + sllx $acc0,32,$t0 + addxccc $acc5,$a2,$acc5 + srlx $acc0,32,$t1 + addxccc $acc6,$t3,$acc6 + sub $acc0,$t0,$t2 ! acc0*0xFFFFFFFF00000001, low part + addxc $acc7,$a3,$acc7 +___ +for($i=0;$i<3;$i++) { # reductions, see commentary + # in multiplication for details +$code.=<<___; + umulxhi $acc0,$poly3,$t3 ! acc0*0xFFFFFFFF00000001, high part + addcc $acc1,$t0,$acc0 ! +=acc[0]<<96 and omit acc[0] + sllx $acc0,32,$t0 + addxccc $acc2,$t1,$acc1 + srlx $acc0,32,$t1 + addxccc $acc3,$t2,$acc2 ! +=acc[0]*0xFFFFFFFF00000001 + sub $acc0,$t0,$t2 ! acc0*0xFFFFFFFF00000001, low part + addxc %g0,$t3,$acc3 ! can't overflow +___ +} +$code.=<<___; + umulxhi $acc0,$poly3,$t3 ! acc0*0xFFFFFFFF00000001, high part + addcc $acc1,$t0,$acc0 ! +=acc[0]<<96 and omit acc[0] + addxccc $acc2,$t1,$acc1 + addxccc $acc3,$t2,$acc2 ! +=acc[0]*0xFFFFFFFF00000001 + addxc %g0,$t3,$acc3 ! can't overflow + + addcc $acc0,$acc4,$acc0 ! accumulate upper half + addxccc $acc1,$acc5,$acc1 + addxccc $acc2,$acc6,$acc2 + addxccc $acc3,$acc7,$acc3 + addxc %g0,%g0,$acc4 + +.Lmul_final_vis3: + + ! Final step is "if result > mod, subtract mod", but as comparison + ! means subtraction, we do the subtraction and then copy outcome + ! if it didn't borrow. But note that as we [have to] replace + ! subtraction with addition with negative, carry/borrow logic is + ! inverse. + + addcc $acc0,1,$t0 ! add -modulus, i.e. subtract + not $poly3,$poly3 ! restore 0x00000000FFFFFFFE + addxccc $acc1,$poly1,$t1 + addxccc $acc2,$minus1,$t2 + addxccc $acc3,$poly3,$t3 + addxccc $acc4,$minus1,%g0 ! did it carry? + + movcs %xcc,$t0,$acc0 + movcs %xcc,$t1,$acc1 + stx $acc0,[$rp] + movcs %xcc,$t2,$acc2 + stx $acc1,[$rp+8] + movcs %xcc,$t3,$acc3 + stx $acc2,[$rp+16] + retl + stx $acc3,[$rp+24] +.type __ecp_nistz256_sqr_mont_vis3,#function +.size __ecp_nistz256_sqr_mont_vis3,.-__ecp_nistz256_sqr_mont_vis3 +___ + +######################################################################## +# void ecp_nistz256_point_double(P256_POINT *out,const P256_POINT *inp); +# +{ +my ($res_x,$res_y,$res_z, + $in_x,$in_y,$in_z, + $S,$M,$Zsqr,$tmp0)=map(32*$_,(0..9)); +# above map() describes stack layout with 10 temporary +# 256-bit vectors on top. + +$code.=<<___; +.align 32 +ecp_nistz256_point_double_vis3: + save %sp,-STACK64_FRAME-32*10,%sp + + mov $rp,$rp_real +.Ldouble_shortcut_vis3: + mov -1,$minus1 + mov -2,$poly3 + sllx $minus1,32,$poly1 ! 0xFFFFFFFF00000000 + srl $poly3,0,$poly3 ! 0x00000000FFFFFFFE + + ! convert input to uint64_t[4] + ld [$ap],$a0 ! in_x + ld [$ap+4],$t0 + ld [$ap+8],$a1 + ld [$ap+12],$t1 + ld [$ap+16],$a2 + ld [$ap+20],$t2 + ld [$ap+24],$a3 + ld [$ap+28],$t3 + sllx $t0,32,$t0 + sllx $t1,32,$t1 + ld [$ap+32],$acc0 ! in_y + or $a0,$t0,$a0 + ld [$ap+32+4],$t0 + sllx $t2,32,$t2 + ld [$ap+32+8],$acc1 + or $a1,$t1,$a1 + ld [$ap+32+12],$t1 + sllx $t3,32,$t3 + ld [$ap+32+16],$acc2 + or $a2,$t2,$a2 + ld [$ap+32+20],$t2 + or $a3,$t3,$a3 + ld [$ap+32+24],$acc3 + sllx $t0,32,$t0 + ld [$ap+32+28],$t3 + sllx $t1,32,$t1 + stx $a0,[%sp+LOCALS64+$in_x] + sllx $t2,32,$t2 + stx $a1,[%sp+LOCALS64+$in_x+8] + sllx $t3,32,$t3 + stx $a2,[%sp+LOCALS64+$in_x+16] + or $acc0,$t0,$acc0 + stx $a3,[%sp+LOCALS64+$in_x+24] + or $acc1,$t1,$acc1 + stx $acc0,[%sp+LOCALS64+$in_y] + or $acc2,$t2,$acc2 + stx $acc1,[%sp+LOCALS64+$in_y+8] + or $acc3,$t3,$acc3 + stx $acc2,[%sp+LOCALS64+$in_y+16] + stx $acc3,[%sp+LOCALS64+$in_y+24] + + ld [$ap+64],$a0 ! in_z + ld [$ap+64+4],$t0 + ld [$ap+64+8],$a1 + ld [$ap+64+12],$t1 + ld [$ap+64+16],$a2 + ld [$ap+64+20],$t2 + ld [$ap+64+24],$a3 + ld [$ap+64+28],$t3 + sllx $t0,32,$t0 + sllx $t1,32,$t1 + or $a0,$t0,$a0 + sllx $t2,32,$t2 + or $a1,$t1,$a1 + sllx $t3,32,$t3 + or $a2,$t2,$a2 + or $a3,$t3,$a3 + sllx $t0,32,$t0 + sllx $t1,32,$t1 + stx $a0,[%sp+LOCALS64+$in_z] + sllx $t2,32,$t2 + stx $a1,[%sp+LOCALS64+$in_z+8] + sllx $t3,32,$t3 + stx $a2,[%sp+LOCALS64+$in_z+16] + stx $a3,[%sp+LOCALS64+$in_z+24] + + ! in_y is still in $acc0-$acc3 + call __ecp_nistz256_mul_by_2_vis3 ! p256_mul_by_2(S, in_y); + add %sp,LOCALS64+$S,$rp + + ! in_z is still in $a0-$a3 + call __ecp_nistz256_sqr_mont_vis3 ! p256_sqr_mont(Zsqr, in_z); + add %sp,LOCALS64+$Zsqr,$rp + + mov $acc0,$a0 ! put Zsqr aside + mov $acc1,$a1 + mov $acc2,$a2 + mov $acc3,$a3 + + add %sp,LOCALS64+$in_x,$bp + call __ecp_nistz256_add_vis3 ! p256_add(M, Zsqr, in_x); + add %sp,LOCALS64+$M,$rp + + mov $a0,$acc0 ! restore Zsqr + ldx [%sp+LOCALS64+$S],$a0 ! forward load + mov $a1,$acc1 + ldx [%sp+LOCALS64+$S+8],$a1 + mov $a2,$acc2 + ldx [%sp+LOCALS64+$S+16],$a2 + mov $a3,$acc3 + ldx [%sp+LOCALS64+$S+24],$a3 + + add %sp,LOCALS64+$in_x,$bp + call __ecp_nistz256_sub_morf_vis3 ! p256_sub(Zsqr, in_x, Zsqr); + add %sp,LOCALS64+$Zsqr,$rp + + call __ecp_nistz256_sqr_mont_vis3 ! p256_sqr_mont(S, S); + add %sp,LOCALS64+$S,$rp + + ldx [%sp+LOCALS64+$in_z],$bi + ldx [%sp+LOCALS64+$in_y],$a0 + ldx [%sp+LOCALS64+$in_y+8],$a1 + ldx [%sp+LOCALS64+$in_y+16],$a2 + ldx [%sp+LOCALS64+$in_y+24],$a3 + add %sp,LOCALS64+$in_z,$bp + call __ecp_nistz256_mul_mont_vis3 ! p256_mul_mont(tmp0, in_z, in_y); + add %sp,LOCALS64+$tmp0,$rp + + ldx [%sp+LOCALS64+$M],$bi ! forward load + ldx [%sp+LOCALS64+$Zsqr],$a0 + ldx [%sp+LOCALS64+$Zsqr+8],$a1 + ldx [%sp+LOCALS64+$Zsqr+16],$a2 + ldx [%sp+LOCALS64+$Zsqr+24],$a3 + + call __ecp_nistz256_mul_by_2_vis3 ! p256_mul_by_2(res_z, tmp0); + add %sp,LOCALS64+$res_z,$rp + + add %sp,LOCALS64+$M,$bp + call __ecp_nistz256_mul_mont_vis3 ! p256_mul_mont(M, M, Zsqr); + add %sp,LOCALS64+$M,$rp + + mov $acc0,$a0 ! put aside M + mov $acc1,$a1 + mov $acc2,$a2 + mov $acc3,$a3 + call __ecp_nistz256_mul_by_2_vis3 + add %sp,LOCALS64+$M,$rp + mov $a0,$t0 ! copy M + ldx [%sp+LOCALS64+$S],$a0 ! forward load + mov $a1,$t1 + ldx [%sp+LOCALS64+$S+8],$a1 + mov $a2,$t2 + ldx [%sp+LOCALS64+$S+16],$a2 + mov $a3,$t3 + ldx [%sp+LOCALS64+$S+24],$a3 + call __ecp_nistz256_add_noload_vis3 ! p256_mul_by_3(M, M); + add %sp,LOCALS64+$M,$rp + + call __ecp_nistz256_sqr_mont_vis3 ! p256_sqr_mont(tmp0, S); + add %sp,LOCALS64+$tmp0,$rp + + ldx [%sp+LOCALS64+$S],$bi ! forward load + ldx [%sp+LOCALS64+$in_x],$a0 + ldx [%sp+LOCALS64+$in_x+8],$a1 + ldx [%sp+LOCALS64+$in_x+16],$a2 + ldx [%sp+LOCALS64+$in_x+24],$a3 + + call __ecp_nistz256_div_by_2_vis3 ! p256_div_by_2(res_y, tmp0); + add %sp,LOCALS64+$res_y,$rp + + add %sp,LOCALS64+$S,$bp + call __ecp_nistz256_mul_mont_vis3 ! p256_mul_mont(S, S, in_x); + add %sp,LOCALS64+$S,$rp + + ldx [%sp+LOCALS64+$M],$a0 ! forward load + ldx [%sp+LOCALS64+$M+8],$a1 + ldx [%sp+LOCALS64+$M+16],$a2 + ldx [%sp+LOCALS64+$M+24],$a3 + + call __ecp_nistz256_mul_by_2_vis3 ! p256_mul_by_2(tmp0, S); + add %sp,LOCALS64+$tmp0,$rp + + call __ecp_nistz256_sqr_mont_vis3 ! p256_sqr_mont(res_x, M); + add %sp,LOCALS64+$res_x,$rp + + add %sp,LOCALS64+$tmp0,$bp + call __ecp_nistz256_sub_from_vis3 ! p256_sub(res_x, res_x, tmp0); + add %sp,LOCALS64+$res_x,$rp + + ldx [%sp+LOCALS64+$M],$a0 ! forward load + ldx [%sp+LOCALS64+$M+8],$a1 + ldx [%sp+LOCALS64+$M+16],$a2 + ldx [%sp+LOCALS64+$M+24],$a3 + + add %sp,LOCALS64+$S,$bp + call __ecp_nistz256_sub_morf_vis3 ! p256_sub(S, S, res_x); + add %sp,LOCALS64+$S,$rp + + mov $acc0,$bi + call __ecp_nistz256_mul_mont_vis3 ! p256_mul_mont(S, S, M); + add %sp,LOCALS64+$S,$rp + + ldx [%sp+LOCALS64+$res_x],$a0 ! forward load + ldx [%sp+LOCALS64+$res_x+8],$a1 + ldx [%sp+LOCALS64+$res_x+16],$a2 + ldx [%sp+LOCALS64+$res_x+24],$a3 + + add %sp,LOCALS64+$res_y,$bp + call __ecp_nistz256_sub_from_vis3 ! p256_sub(res_y, S, res_y); + add %sp,LOCALS64+$res_y,$bp + + ! convert output to uint_32[8] + srlx $a0,32,$t0 + srlx $a1,32,$t1 + st $a0,[$rp_real] ! res_x + srlx $a2,32,$t2 + st $t0,[$rp_real+4] + srlx $a3,32,$t3 + st $a1,[$rp_real+8] + st $t1,[$rp_real+12] + st $a2,[$rp_real+16] + st $t2,[$rp_real+20] + st $a3,[$rp_real+24] + st $t3,[$rp_real+28] + + ldx [%sp+LOCALS64+$res_z],$a0 ! forward load + srlx $acc0,32,$t0 + ldx [%sp+LOCALS64+$res_z+8],$a1 + srlx $acc1,32,$t1 + ldx [%sp+LOCALS64+$res_z+16],$a2 + srlx $acc2,32,$t2 + ldx [%sp+LOCALS64+$res_z+24],$a3 + srlx $acc3,32,$t3 + st $acc0,[$rp_real+32] ! res_y + st $t0, [$rp_real+32+4] + st $acc1,[$rp_real+32+8] + st $t1, [$rp_real+32+12] + st $acc2,[$rp_real+32+16] + st $t2, [$rp_real+32+20] + st $acc3,[$rp_real+32+24] + st $t3, [$rp_real+32+28] + + srlx $a0,32,$t0 + srlx $a1,32,$t1 + st $a0,[$rp_real+64] ! res_z + srlx $a2,32,$t2 + st $t0,[$rp_real+64+4] + srlx $a3,32,$t3 + st $a1,[$rp_real+64+8] + st $t1,[$rp_real+64+12] + st $a2,[$rp_real+64+16] + st $t2,[$rp_real+64+20] + st $a3,[$rp_real+64+24] + st $t3,[$rp_real+64+28] + + ret + restore +.type ecp_nistz256_point_double_vis3,#function +.size ecp_nistz256_point_double_vis3,.-ecp_nistz256_point_double_vis3 +___ +} +######################################################################## +# void ecp_nistz256_point_add(P256_POINT *out,const P256_POINT *in1, +# const P256_POINT *in2); +{ +my ($res_x,$res_y,$res_z, + $in1_x,$in1_y,$in1_z, + $in2_x,$in2_y,$in2_z, + $H,$Hsqr,$R,$Rsqr,$Hcub, + $U1,$U2,$S1,$S2)=map(32*$_,(0..17)); +my ($Z1sqr, $Z2sqr) = ($Hsqr, $Rsqr); + +# above map() describes stack layout with 18 temporary +# 256-bit vectors on top. Then we reserve some space for +# !in1infty, !in2infty and result of check for zero. + +$code.=<<___; +.globl ecp_nistz256_point_add_vis3 +.align 32 +ecp_nistz256_point_add_vis3: + save %sp,-STACK64_FRAME-32*18-32,%sp + + mov $rp,$rp_real + mov -1,$minus1 + mov -2,$poly3 + sllx $minus1,32,$poly1 ! 0xFFFFFFFF00000000 + srl $poly3,0,$poly3 ! 0x00000000FFFFFFFE + + ! convert input to uint64_t[4] + ld [$bp],$a0 ! in2_x + ld [$bp+4],$t0 + ld [$bp+8],$a1 + ld [$bp+12],$t1 + ld [$bp+16],$a2 + ld [$bp+20],$t2 + ld [$bp+24],$a3 + ld [$bp+28],$t3 + sllx $t0,32,$t0 + sllx $t1,32,$t1 + ld [$bp+32],$acc0 ! in2_y + or $a0,$t0,$a0 + ld [$bp+32+4],$t0 + sllx $t2,32,$t2 + ld [$bp+32+8],$acc1 + or $a1,$t1,$a1 + ld [$bp+32+12],$t1 + sllx $t3,32,$t3 + ld [$bp+32+16],$acc2 + or $a2,$t2,$a2 + ld [$bp+32+20],$t2 + or $a3,$t3,$a3 + ld [$bp+32+24],$acc3 + sllx $t0,32,$t0 + ld [$bp+32+28],$t3 + sllx $t1,32,$t1 + stx $a0,[%sp+LOCALS64+$in2_x] + sllx $t2,32,$t2 + stx $a1,[%sp+LOCALS64+$in2_x+8] + sllx $t3,32,$t3 + stx $a2,[%sp+LOCALS64+$in2_x+16] + or $acc0,$t0,$acc0 + stx $a3,[%sp+LOCALS64+$in2_x+24] + or $acc1,$t1,$acc1 + stx $acc0,[%sp+LOCALS64+$in2_y] + or $acc2,$t2,$acc2 + stx $acc1,[%sp+LOCALS64+$in2_y+8] + or $acc3,$t3,$acc3 + stx $acc2,[%sp+LOCALS64+$in2_y+16] + stx $acc3,[%sp+LOCALS64+$in2_y+24] + + ld [$bp+64],$acc0 ! in2_z + ld [$bp+64+4],$t0 + ld [$bp+64+8],$acc1 + ld [$bp+64+12],$t1 + ld [$bp+64+16],$acc2 + ld [$bp+64+20],$t2 + ld [$bp+64+24],$acc3 + ld [$bp+64+28],$t3 + sllx $t0,32,$t0 + sllx $t1,32,$t1 + ld [$ap],$a0 ! in1_x + or $acc0,$t0,$acc0 + ld [$ap+4],$t0 + sllx $t2,32,$t2 + ld [$ap+8],$a1 + or $acc1,$t1,$acc1 + ld [$ap+12],$t1 + sllx $t3,32,$t3 + ld [$ap+16],$a2 + or $acc2,$t2,$acc2 + ld [$ap+20],$t2 + or $acc3,$t3,$acc3 + ld [$ap+24],$a3 + sllx $t0,32,$t0 + ld [$ap+28],$t3 + sllx $t1,32,$t1 + stx $acc0,[%sp+LOCALS64+$in2_z] + sllx $t2,32,$t2 + stx $acc1,[%sp+LOCALS64+$in2_z+8] + sllx $t3,32,$t3 + stx $acc2,[%sp+LOCALS64+$in2_z+16] + stx $acc3,[%sp+LOCALS64+$in2_z+24] + + or $acc1,$acc0,$acc0 + or $acc3,$acc2,$acc2 + or $acc2,$acc0,$acc0 + movrnz $acc0,-1,$acc0 ! !in2infty + stx $acc0,[%fp+STACK_BIAS-8] + + or $a0,$t0,$a0 + ld [$ap+32],$acc0 ! in1_y + or $a1,$t1,$a1 + ld [$ap+32+4],$t0 + or $a2,$t2,$a2 + ld [$ap+32+8],$acc1 + or $a3,$t3,$a3 + ld [$ap+32+12],$t1 + ld [$ap+32+16],$acc2 + ld [$ap+32+20],$t2 + ld [$ap+32+24],$acc3 + sllx $t0,32,$t0 + ld [$ap+32+28],$t3 + sllx $t1,32,$t1 + stx $a0,[%sp+LOCALS64+$in1_x] + sllx $t2,32,$t2 + stx $a1,[%sp+LOCALS64+$in1_x+8] + sllx $t3,32,$t3 + stx $a2,[%sp+LOCALS64+$in1_x+16] + or $acc0,$t0,$acc0 + stx $a3,[%sp+LOCALS64+$in1_x+24] + or $acc1,$t1,$acc1 + stx $acc0,[%sp+LOCALS64+$in1_y] + or $acc2,$t2,$acc2 + stx $acc1,[%sp+LOCALS64+$in1_y+8] + or $acc3,$t3,$acc3 + stx $acc2,[%sp+LOCALS64+$in1_y+16] + stx $acc3,[%sp+LOCALS64+$in1_y+24] + + ldx [%sp+LOCALS64+$in2_z],$a0 ! forward load + ldx [%sp+LOCALS64+$in2_z+8],$a1 + ldx [%sp+LOCALS64+$in2_z+16],$a2 + ldx [%sp+LOCALS64+$in2_z+24],$a3 + + ld [$ap+64],$acc0 ! in1_z + ld [$ap+64+4],$t0 + ld [$ap+64+8],$acc1 + ld [$ap+64+12],$t1 + ld [$ap+64+16],$acc2 + ld [$ap+64+20],$t2 + ld [$ap+64+24],$acc3 + ld [$ap+64+28],$t3 + sllx $t0,32,$t0 + sllx $t1,32,$t1 + or $acc0,$t0,$acc0 + sllx $t2,32,$t2 + or $acc1,$t1,$acc1 + sllx $t3,32,$t3 + stx $acc0,[%sp+LOCALS64+$in1_z] + or $acc2,$t2,$acc2 + stx $acc1,[%sp+LOCALS64+$in1_z+8] + or $acc3,$t3,$acc3 + stx $acc2,[%sp+LOCALS64+$in1_z+16] + stx $acc3,[%sp+LOCALS64+$in1_z+24] + + or $acc1,$acc0,$acc0 + or $acc3,$acc2,$acc2 + or $acc2,$acc0,$acc0 + movrnz $acc0,-1,$acc0 ! !in1infty + stx $acc0,[%fp+STACK_BIAS-16] + + call __ecp_nistz256_sqr_mont_vis3 ! p256_sqr_mont(Z2sqr, in2_z); + add %sp,LOCALS64+$Z2sqr,$rp + + ldx [%sp+LOCALS64+$in1_z],$a0 + ldx [%sp+LOCALS64+$in1_z+8],$a1 + ldx [%sp+LOCALS64+$in1_z+16],$a2 + ldx [%sp+LOCALS64+$in1_z+24],$a3 + call __ecp_nistz256_sqr_mont_vis3 ! p256_sqr_mont(Z1sqr, in1_z); + add %sp,LOCALS64+$Z1sqr,$rp + + ldx [%sp+LOCALS64+$Z2sqr],$bi + ldx [%sp+LOCALS64+$in2_z],$a0 + ldx [%sp+LOCALS64+$in2_z+8],$a1 + ldx [%sp+LOCALS64+$in2_z+16],$a2 + ldx [%sp+LOCALS64+$in2_z+24],$a3 + add %sp,LOCALS64+$Z2sqr,$bp + call __ecp_nistz256_mul_mont_vis3 ! p256_mul_mont(S1, Z2sqr, in2_z); + add %sp,LOCALS64+$S1,$rp + + ldx [%sp+LOCALS64+$Z1sqr],$bi + ldx [%sp+LOCALS64+$in1_z],$a0 + ldx [%sp+LOCALS64+$in1_z+8],$a1 + ldx [%sp+LOCALS64+$in1_z+16],$a2 + ldx [%sp+LOCALS64+$in1_z+24],$a3 + add %sp,LOCALS64+$Z1sqr,$bp + call __ecp_nistz256_mul_mont_vis3 ! p256_mul_mont(S2, Z1sqr, in1_z); + add %sp,LOCALS64+$S2,$rp + + ldx [%sp+LOCALS64+$S1],$bi + ldx [%sp+LOCALS64+$in1_y],$a0 + ldx [%sp+LOCALS64+$in1_y+8],$a1 + ldx [%sp+LOCALS64+$in1_y+16],$a2 + ldx [%sp+LOCALS64+$in1_y+24],$a3 + add %sp,LOCALS64+$S1,$bp + call __ecp_nistz256_mul_mont_vis3 ! p256_mul_mont(S1, S1, in1_y); + add %sp,LOCALS64+$S1,$rp + + ldx [%sp+LOCALS64+$S2],$bi + ldx [%sp+LOCALS64+$in2_y],$a0 + ldx [%sp+LOCALS64+$in2_y+8],$a1 + ldx [%sp+LOCALS64+$in2_y+16],$a2 + ldx [%sp+LOCALS64+$in2_y+24],$a3 + add %sp,LOCALS64+$S2,$bp + call __ecp_nistz256_mul_mont_vis3 ! p256_mul_mont(S2, S2, in2_y); + add %sp,LOCALS64+$S2,$rp + + ldx [%sp+LOCALS64+$Z2sqr],$bi ! forward load + ldx [%sp+LOCALS64+$in1_x],$a0 + ldx [%sp+LOCALS64+$in1_x+8],$a1 + ldx [%sp+LOCALS64+$in1_x+16],$a2 + ldx [%sp+LOCALS64+$in1_x+24],$a3 + + add %sp,LOCALS64+$S1,$bp + call __ecp_nistz256_sub_from_vis3 ! p256_sub(R, S2, S1); + add %sp,LOCALS64+$R,$rp + + or $acc1,$acc0,$acc0 ! see if result is zero + or $acc3,$acc2,$acc2 + or $acc2,$acc0,$acc0 + stx $acc0,[%fp+STACK_BIAS-24] + + add %sp,LOCALS64+$Z2sqr,$bp + call __ecp_nistz256_mul_mont_vis3 ! p256_mul_mont(U1, in1_x, Z2sqr); + add %sp,LOCALS64+$U1,$rp + + ldx [%sp+LOCALS64+$Z1sqr],$bi + ldx [%sp+LOCALS64+$in2_x],$a0 + ldx [%sp+LOCALS64+$in2_x+8],$a1 + ldx [%sp+LOCALS64+$in2_x+16],$a2 + ldx [%sp+LOCALS64+$in2_x+24],$a3 + add %sp,LOCALS64+$Z1sqr,$bp + call __ecp_nistz256_mul_mont_vis3 ! p256_mul_mont(U2, in2_x, Z1sqr); + add %sp,LOCALS64+$U2,$rp + + ldx [%sp+LOCALS64+$R],$a0 ! forward load + ldx [%sp+LOCALS64+$R+8],$a1 + ldx [%sp+LOCALS64+$R+16],$a2 + ldx [%sp+LOCALS64+$R+24],$a3 + + add %sp,LOCALS64+$U1,$bp + call __ecp_nistz256_sub_from_vis3 ! p256_sub(H, U2, U1); + add %sp,LOCALS64+$H,$rp + + or $acc1,$acc0,$acc0 ! see if result is zero + or $acc3,$acc2,$acc2 + orcc $acc2,$acc0,$acc0 + + bne,pt %xcc,.Ladd_proceed_vis3 ! is_equal(U1,U2)? + nop + + ldx [%fp+STACK_BIAS-8],$t0 + ldx [%fp+STACK_BIAS-16],$t1 + ldx [%fp+STACK_BIAS-24],$t2 + andcc $t0,$t1,%g0 + be,pt %xcc,.Ladd_proceed_vis3 ! (in1infty || in2infty)? + nop + andcc $t2,$t2,%g0 + be,a,pt %xcc,.Ldouble_shortcut_vis3 ! is_equal(S1,S2)? + add %sp,32*(12-10)+32,%sp ! difference in frame sizes + + st %g0,[$rp_real] + st %g0,[$rp_real+4] + st %g0,[$rp_real+8] + st %g0,[$rp_real+12] + st %g0,[$rp_real+16] + st %g0,[$rp_real+20] + st %g0,[$rp_real+24] + st %g0,[$rp_real+28] + st %g0,[$rp_real+32] + st %g0,[$rp_real+32+4] + st %g0,[$rp_real+32+8] + st %g0,[$rp_real+32+12] + st %g0,[$rp_real+32+16] + st %g0,[$rp_real+32+20] + st %g0,[$rp_real+32+24] + st %g0,[$rp_real+32+28] + st %g0,[$rp_real+64] + st %g0,[$rp_real+64+4] + st %g0,[$rp_real+64+8] + st %g0,[$rp_real+64+12] + st %g0,[$rp_real+64+16] + st %g0,[$rp_real+64+20] + st %g0,[$rp_real+64+24] + st %g0,[$rp_real+64+28] + b .Ladd_done_vis3 + nop + +.align 16 +.Ladd_proceed_vis3: + call __ecp_nistz256_sqr_mont_vis3 ! p256_sqr_mont(Rsqr, R); + add %sp,LOCALS64+$Rsqr,$rp + + ldx [%sp+LOCALS64+$H],$bi + ldx [%sp+LOCALS64+$in1_z],$a0 + ldx [%sp+LOCALS64+$in1_z+8],$a1 + ldx [%sp+LOCALS64+$in1_z+16],$a2 + ldx [%sp+LOCALS64+$in1_z+24],$a3 + add %sp,LOCALS64+$H,$bp + call __ecp_nistz256_mul_mont_vis3 ! p256_mul_mont(res_z, H, in1_z); + add %sp,LOCALS64+$res_z,$rp + + ldx [%sp+LOCALS64+$H],$a0 + ldx [%sp+LOCALS64+$H+8],$a1 + ldx [%sp+LOCALS64+$H+16],$a2 + ldx [%sp+LOCALS64+$H+24],$a3 + call __ecp_nistz256_sqr_mont_vis3 ! p256_sqr_mont(Hsqr, H); + add %sp,LOCALS64+$Hsqr,$rp + + ldx [%sp+LOCALS64+$res_z],$bi + ldx [%sp+LOCALS64+$in2_z],$a0 + ldx [%sp+LOCALS64+$in2_z+8],$a1 + ldx [%sp+LOCALS64+$in2_z+16],$a2 + ldx [%sp+LOCALS64+$in2_z+24],$a3 + add %sp,LOCALS64+$res_z,$bp + call __ecp_nistz256_mul_mont_vis3 ! p256_mul_mont(res_z, res_z, in2_z); + add %sp,LOCALS64+$res_z,$rp + + ldx [%sp+LOCALS64+$H],$bi + ldx [%sp+LOCALS64+$Hsqr],$a0 + ldx [%sp+LOCALS64+$Hsqr+8],$a1 + ldx [%sp+LOCALS64+$Hsqr+16],$a2 + ldx [%sp+LOCALS64+$Hsqr+24],$a3 + add %sp,LOCALS64+$H,$bp + call __ecp_nistz256_mul_mont_vis3 ! p256_mul_mont(Hcub, Hsqr, H); + add %sp,LOCALS64+$Hcub,$rp + + ldx [%sp+LOCALS64+$U1],$bi + ldx [%sp+LOCALS64+$Hsqr],$a0 + ldx [%sp+LOCALS64+$Hsqr+8],$a1 + ldx [%sp+LOCALS64+$Hsqr+16],$a2 + ldx [%sp+LOCALS64+$Hsqr+24],$a3 + add %sp,LOCALS64+$U1,$bp + call __ecp_nistz256_mul_mont_vis3 ! p256_mul_mont(U2, U1, Hsqr); + add %sp,LOCALS64+$U2,$rp + + call __ecp_nistz256_mul_by_2_vis3 ! p256_mul_by_2(Hsqr, U2); + add %sp,LOCALS64+$Hsqr,$rp + + add %sp,LOCALS64+$Rsqr,$bp + call __ecp_nistz256_sub_morf_vis3 ! p256_sub(res_x, Rsqr, Hsqr); + add %sp,LOCALS64+$res_x,$rp + + add %sp,LOCALS64+$Hcub,$bp + call __ecp_nistz256_sub_from_vis3 ! p256_sub(res_x, res_x, Hcub); + add %sp,LOCALS64+$res_x,$rp + + ldx [%sp+LOCALS64+$S1],$bi ! forward load + ldx [%sp+LOCALS64+$Hcub],$a0 + ldx [%sp+LOCALS64+$Hcub+8],$a1 + ldx [%sp+LOCALS64+$Hcub+16],$a2 + ldx [%sp+LOCALS64+$Hcub+24],$a3 + + add %sp,LOCALS64+$U2,$bp + call __ecp_nistz256_sub_morf_vis3 ! p256_sub(res_y, U2, res_x); + add %sp,LOCALS64+$res_y,$rp + + add %sp,LOCALS64+$S1,$bp + call __ecp_nistz256_mul_mont_vis3 ! p256_mul_mont(S2, S1, Hcub); + add %sp,LOCALS64+$S2,$rp + + ldx [%sp+LOCALS64+$R],$bi + ldx [%sp+LOCALS64+$res_y],$a0 + ldx [%sp+LOCALS64+$res_y+8],$a1 + ldx [%sp+LOCALS64+$res_y+16],$a2 + ldx [%sp+LOCALS64+$res_y+24],$a3 + add %sp,LOCALS64+$R,$bp + call __ecp_nistz256_mul_mont_vis3 ! p256_mul_mont(res_y, res_y, R); + add %sp,LOCALS64+$res_y,$rp + + add %sp,LOCALS64+$S2,$bp + call __ecp_nistz256_sub_from_vis3 ! p256_sub(res_y, res_y, S2); + add %sp,LOCALS64+$res_y,$rp + + ldx [%fp+STACK_BIAS-16],$t1 ! !in1infty + ldx [%fp+STACK_BIAS-8],$t2 ! !in2infty +___ +for($i=0;$i<96;$i+=16) { # conditional moves +$code.=<<___; + ldx [%sp+LOCALS64+$res_x+$i],$acc0 ! res + ldx [%sp+LOCALS64+$res_x+$i+8],$acc1 + ldx [%sp+LOCALS64+$in2_x+$i],$acc2 ! in2 + ldx [%sp+LOCALS64+$in2_x+$i+8],$acc3 + ldx [%sp+LOCALS64+$in1_x+$i],$acc4 ! in1 + ldx [%sp+LOCALS64+$in1_x+$i+8],$acc5 + movrz $t1,$acc2,$acc0 + movrz $t1,$acc3,$acc1 + movrz $t2,$acc4,$acc0 + movrz $t2,$acc5,$acc1 + srlx $acc0,32,$acc2 + srlx $acc1,32,$acc3 + st $acc0,[$rp_real+$i] + st $acc2,[$rp_real+$i+4] + st $acc1,[$rp_real+$i+8] + st $acc3,[$rp_real+$i+12] +___ +} +$code.=<<___; +.Ladd_done_vis3: + ret + restore +.type ecp_nistz256_point_add_vis3,#function +.size ecp_nistz256_point_add_vis3,.-ecp_nistz256_point_add_vis3 +___ +} +######################################################################## +# void ecp_nistz256_point_add_affine(P256_POINT *out,const P256_POINT *in1, +# const P256_POINT_AFFINE *in2); +{ +my ($res_x,$res_y,$res_z, + $in1_x,$in1_y,$in1_z, + $in2_x,$in2_y, + $U2,$S2,$H,$R,$Hsqr,$Hcub,$Rsqr)=map(32*$_,(0..14)); +my $Z1sqr = $S2; +# above map() describes stack layout with 15 temporary +# 256-bit vectors on top. Then we reserve some space for +# !in1infty and !in2infty. + +$code.=<<___; +.align 32 +ecp_nistz256_point_add_affine_vis3: + save %sp,-STACK64_FRAME-32*15-32,%sp + + mov $rp,$rp_real + mov -1,$minus1 + mov -2,$poly3 + sllx $minus1,32,$poly1 ! 0xFFFFFFFF00000000 + srl $poly3,0,$poly3 ! 0x00000000FFFFFFFE + + ! convert input to uint64_t[4] + ld [$bp],$a0 ! in2_x + ld [$bp+4],$t0 + ld [$bp+8],$a1 + ld [$bp+12],$t1 + ld [$bp+16],$a2 + ld [$bp+20],$t2 + ld [$bp+24],$a3 + ld [$bp+28],$t3 + sllx $t0,32,$t0 + sllx $t1,32,$t1 + ld [$bp+32],$acc0 ! in2_y + or $a0,$t0,$a0 + ld [$bp+32+4],$t0 + sllx $t2,32,$t2 + ld [$bp+32+8],$acc1 + or $a1,$t1,$a1 + ld [$bp+32+12],$t1 + sllx $t3,32,$t3 + ld [$bp+32+16],$acc2 + or $a2,$t2,$a2 + ld [$bp+32+20],$t2 + or $a3,$t3,$a3 + ld [$bp+32+24],$acc3 + sllx $t0,32,$t0 + ld [$bp+32+28],$t3 + sllx $t1,32,$t1 + stx $a0,[%sp+LOCALS64+$in2_x] + sllx $t2,32,$t2 + stx $a1,[%sp+LOCALS64+$in2_x+8] + sllx $t3,32,$t3 + stx $a2,[%sp+LOCALS64+$in2_x+16] + or $acc0,$t0,$acc0 + stx $a3,[%sp+LOCALS64+$in2_x+24] + or $acc1,$t1,$acc1 + stx $acc0,[%sp+LOCALS64+$in2_y] + or $acc2,$t2,$acc2 + stx $acc1,[%sp+LOCALS64+$in2_y+8] + or $acc3,$t3,$acc3 + stx $acc2,[%sp+LOCALS64+$in2_y+16] + stx $acc3,[%sp+LOCALS64+$in2_y+24] + + or $a1,$a0,$a0 + or $a3,$a2,$a2 + or $acc1,$acc0,$acc0 + or $acc3,$acc2,$acc2 + or $a2,$a0,$a0 + or $acc2,$acc0,$acc0 + or $acc0,$a0,$a0 + movrnz $a0,-1,$a0 ! !in2infty + stx $a0,[%fp+STACK_BIAS-8] + + ld [$ap],$a0 ! in1_x + ld [$ap+4],$t0 + ld [$ap+8],$a1 + ld [$ap+12],$t1 + ld [$ap+16],$a2 + ld [$ap+20],$t2 + ld [$ap+24],$a3 + ld [$ap+28],$t3 + sllx $t0,32,$t0 + sllx $t1,32,$t1 + ld [$ap+32],$acc0 ! in1_y + or $a0,$t0,$a0 + ld [$ap+32+4],$t0 + sllx $t2,32,$t2 + ld [$ap+32+8],$acc1 + or $a1,$t1,$a1 + ld [$ap+32+12],$t1 + sllx $t3,32,$t3 + ld [$ap+32+16],$acc2 + or $a2,$t2,$a2 + ld [$ap+32+20],$t2 + or $a3,$t3,$a3 + ld [$ap+32+24],$acc3 + sllx $t0,32,$t0 + ld [$ap+32+28],$t3 + sllx $t1,32,$t1 + stx $a0,[%sp+LOCALS64+$in1_x] + sllx $t2,32,$t2 + stx $a1,[%sp+LOCALS64+$in1_x+8] + sllx $t3,32,$t3 + stx $a2,[%sp+LOCALS64+$in1_x+16] + or $acc0,$t0,$acc0 + stx $a3,[%sp+LOCALS64+$in1_x+24] + or $acc1,$t1,$acc1 + stx $acc0,[%sp+LOCALS64+$in1_y] + or $acc2,$t2,$acc2 + stx $acc1,[%sp+LOCALS64+$in1_y+8] + or $acc3,$t3,$acc3 + stx $acc2,[%sp+LOCALS64+$in1_y+16] + stx $acc3,[%sp+LOCALS64+$in1_y+24] + + ld [$ap+64],$a0 ! in1_z + ld [$ap+64+4],$t0 + ld [$ap+64+8],$a1 + ld [$ap+64+12],$t1 + ld [$ap+64+16],$a2 + ld [$ap+64+20],$t2 + ld [$ap+64+24],$a3 + ld [$ap+64+28],$t3 + sllx $t0,32,$t0 + sllx $t1,32,$t1 + or $a0,$t0,$a0 + sllx $t2,32,$t2 + or $a1,$t1,$a1 + sllx $t3,32,$t3 + stx $a0,[%sp+LOCALS64+$in1_z] + or $a2,$t2,$a2 + stx $a1,[%sp+LOCALS64+$in1_z+8] + or $a3,$t3,$a3 + stx $a2,[%sp+LOCALS64+$in1_z+16] + stx $a3,[%sp+LOCALS64+$in1_z+24] + + or $a1,$a0,$t0 + or $a3,$a2,$t2 + or $t2,$t0,$t0 + movrnz $t0,-1,$t0 ! !in1infty + stx $t0,[%fp+STACK_BIAS-16] + + call __ecp_nistz256_sqr_mont_vis3 ! p256_sqr_mont(Z1sqr, in1_z); + add %sp,LOCALS64+$Z1sqr,$rp + + ldx [%sp+LOCALS64+$in2_x],$bi + mov $acc0,$a0 + mov $acc1,$a1 + mov $acc2,$a2 + mov $acc3,$a3 + add %sp,LOCALS64+$in2_x,$bp + call __ecp_nistz256_mul_mont_vis3 ! p256_mul_mont(U2, Z1sqr, in2_x); + add %sp,LOCALS64+$U2,$rp + + ldx [%sp+LOCALS64+$Z1sqr],$bi ! forward load + ldx [%sp+LOCALS64+$in1_z],$a0 + ldx [%sp+LOCALS64+$in1_z+8],$a1 + ldx [%sp+LOCALS64+$in1_z+16],$a2 + ldx [%sp+LOCALS64+$in1_z+24],$a3 + + add %sp,LOCALS64+$in1_x,$bp + call __ecp_nistz256_sub_from_vis3 ! p256_sub(H, U2, in1_x); + add %sp,LOCALS64+$H,$rp + + add %sp,LOCALS64+$Z1sqr,$bp + call __ecp_nistz256_mul_mont_vis3 ! p256_mul_mont(S2, Z1sqr, in1_z); + add %sp,LOCALS64+$S2,$rp + + ldx [%sp+LOCALS64+$H],$bi + ldx [%sp+LOCALS64+$in1_z],$a0 + ldx [%sp+LOCALS64+$in1_z+8],$a1 + ldx [%sp+LOCALS64+$in1_z+16],$a2 + ldx [%sp+LOCALS64+$in1_z+24],$a3 + add %sp,LOCALS64+$H,$bp + call __ecp_nistz256_mul_mont_vis3 ! p256_mul_mont(res_z, H, in1_z); + add %sp,LOCALS64+$res_z,$rp + + ldx [%sp+LOCALS64+$S2],$bi + ldx [%sp+LOCALS64+$in2_y],$a0 + ldx [%sp+LOCALS64+$in2_y+8],$a1 + ldx [%sp+LOCALS64+$in2_y+16],$a2 + ldx [%sp+LOCALS64+$in2_y+24],$a3 + add %sp,LOCALS64+$S2,$bp + call __ecp_nistz256_mul_mont_vis3 ! p256_mul_mont(S2, S2, in2_y); + add %sp,LOCALS64+$S2,$rp + + ldx [%sp+LOCALS64+$H],$a0 ! forward load + ldx [%sp+LOCALS64+$H+8],$a1 + ldx [%sp+LOCALS64+$H+16],$a2 + ldx [%sp+LOCALS64+$H+24],$a3 + + add %sp,LOCALS64+$in1_y,$bp + call __ecp_nistz256_sub_from_vis3 ! p256_sub(R, S2, in1_y); + add %sp,LOCALS64+$R,$rp + + call __ecp_nistz256_sqr_mont_vis3 ! p256_sqr_mont(Hsqr, H); + add %sp,LOCALS64+$Hsqr,$rp + + ldx [%sp+LOCALS64+$R],$a0 + ldx [%sp+LOCALS64+$R+8],$a1 + ldx [%sp+LOCALS64+$R+16],$a2 + ldx [%sp+LOCALS64+$R+24],$a3 + call __ecp_nistz256_sqr_mont_vis3 ! p256_sqr_mont(Rsqr, R); + add %sp,LOCALS64+$Rsqr,$rp + + ldx [%sp+LOCALS64+$H],$bi + ldx [%sp+LOCALS64+$Hsqr],$a0 + ldx [%sp+LOCALS64+$Hsqr+8],$a1 + ldx [%sp+LOCALS64+$Hsqr+16],$a2 + ldx [%sp+LOCALS64+$Hsqr+24],$a3 + add %sp,LOCALS64+$H,$bp + call __ecp_nistz256_mul_mont_vis3 ! p256_mul_mont(Hcub, Hsqr, H); + add %sp,LOCALS64+$Hcub,$rp + + ldx [%sp+LOCALS64+$Hsqr],$bi + ldx [%sp+LOCALS64+$in1_x],$a0 + ldx [%sp+LOCALS64+$in1_x+8],$a1 + ldx [%sp+LOCALS64+$in1_x+16],$a2 + ldx [%sp+LOCALS64+$in1_x+24],$a3 + add %sp,LOCALS64+$Hsqr,$bp + call __ecp_nistz256_mul_mont_vis3 ! p256_mul_mont(U2, in1_x, Hsqr); + add %sp,LOCALS64+$U2,$rp + + call __ecp_nistz256_mul_by_2_vis3 ! p256_mul_by_2(Hsqr, U2); + add %sp,LOCALS64+$Hsqr,$rp + + add %sp,LOCALS64+$Rsqr,$bp + call __ecp_nistz256_sub_morf_vis3 ! p256_sub(res_x, Rsqr, Hsqr); + add %sp,LOCALS64+$res_x,$rp + + add %sp,LOCALS64+$Hcub,$bp + call __ecp_nistz256_sub_from_vis3 ! p256_sub(res_x, res_x, Hcub); + add %sp,LOCALS64+$res_x,$rp + + ldx [%sp+LOCALS64+$Hcub],$bi ! forward load + ldx [%sp+LOCALS64+$in1_y],$a0 + ldx [%sp+LOCALS64+$in1_y+8],$a1 + ldx [%sp+LOCALS64+$in1_y+16],$a2 + ldx [%sp+LOCALS64+$in1_y+24],$a3 + + add %sp,LOCALS64+$U2,$bp + call __ecp_nistz256_sub_morf_vis3 ! p256_sub(res_y, U2, res_x); + add %sp,LOCALS64+$res_y,$rp + + add %sp,LOCALS64+$Hcub,$bp + call __ecp_nistz256_mul_mont_vis3 ! p256_mul_mont(S2, in1_y, Hcub); + add %sp,LOCALS64+$S2,$rp + + ldx [%sp+LOCALS64+$R],$bi + ldx [%sp+LOCALS64+$res_y],$a0 + ldx [%sp+LOCALS64+$res_y+8],$a1 + ldx [%sp+LOCALS64+$res_y+16],$a2 + ldx [%sp+LOCALS64+$res_y+24],$a3 + add %sp,LOCALS64+$R,$bp + call __ecp_nistz256_mul_mont_vis3 ! p256_mul_mont(res_y, res_y, R); + add %sp,LOCALS64+$res_y,$rp + + add %sp,LOCALS64+$S2,$bp + call __ecp_nistz256_sub_from_vis3 ! p256_sub(res_y, res_y, S2); + add %sp,LOCALS64+$res_y,$rp + + ldx [%fp+STACK_BIAS-16],$t1 ! !in1infty + ldx [%fp+STACK_BIAS-8],$t2 ! !in2infty +1: call .+8 + add %o7,.Lone_mont_vis3-1b,$bp +___ +for($i=0;$i<64;$i+=16) { # conditional moves +$code.=<<___; + ldx [%sp+LOCALS64+$res_x+$i],$acc0 ! res + ldx [%sp+LOCALS64+$res_x+$i+8],$acc1 + ldx [%sp+LOCALS64+$in2_x+$i],$acc2 ! in2 + ldx [%sp+LOCALS64+$in2_x+$i+8],$acc3 + ldx [%sp+LOCALS64+$in1_x+$i],$acc4 ! in1 + ldx [%sp+LOCALS64+$in1_x+$i+8],$acc5 + movrz $t1,$acc2,$acc0 + movrz $t1,$acc3,$acc1 + movrz $t2,$acc4,$acc0 + movrz $t2,$acc5,$acc1 + srlx $acc0,32,$acc2 + srlx $acc1,32,$acc3 + st $acc0,[$rp_real+$i] + st $acc2,[$rp_real+$i+4] + st $acc1,[$rp_real+$i+8] + st $acc3,[$rp_real+$i+12] +___ +} +for(;$i<96;$i+=16) { +$code.=<<___; + ldx [%sp+LOCALS64+$res_x+$i],$acc0 ! res + ldx [%sp+LOCALS64+$res_x+$i+8],$acc1 + ldx [$bp+$i-64],$acc2 ! "in2" + ldx [$bp+$i-64+8],$acc3 + ldx [%sp+LOCALS64+$in1_x+$i],$acc4 ! in1 + ldx [%sp+LOCALS64+$in1_x+$i+8],$acc5 + movrz $t1,$acc2,$acc0 + movrz $t1,$acc3,$acc1 + movrz $t2,$acc4,$acc0 + movrz $t2,$acc5,$acc1 + srlx $acc0,32,$acc2 + srlx $acc1,32,$acc3 + st $acc0,[$rp_real+$i] + st $acc2,[$rp_real+$i+4] + st $acc1,[$rp_real+$i+8] + st $acc3,[$rp_real+$i+12] +___ +} +$code.=<<___; + ret + restore +.type ecp_nistz256_point_add_affine_vis3,#function +.size ecp_nistz256_point_add_affine_vis3,.-ecp_nistz256_point_add_affine_vis3 +.align 64 +.Lone_mont_vis3: +.long 0x00000000,0x00000001, 0xffffffff,0x00000000 +.long 0xffffffff,0xffffffff, 0x00000000,0xfffffffe +.align 64 +___ +} }}} + +# Purpose of these subroutines is to explicitly encode VIS instructions, +# so that one can compile the module without having to specify VIS +# extensions on compiler command line, e.g. -xarch=v9 vs. -xarch=v9a. +# Idea is to reserve for option to produce "universal" binary and let +# programmer detect if current CPU is VIS capable at run-time. +sub unvis3 { +my ($mnemonic,$rs1,$rs2,$rd)=@_; +my %bias = ( "g" => 0, "o" => 8, "l" => 16, "i" => 24 ); +my ($ref,$opf); +my %visopf = ( "addxc" => 0x011, + "addxccc" => 0x013, + "umulxhi" => 0x016 ); + + $ref = "$mnemonic\t$rs1,$rs2,$rd"; + + if ($opf=$visopf{$mnemonic}) { + foreach ($rs1,$rs2,$rd) { + return $ref if (!/%([goli])([0-9])/); + $_=$bias{$1}+$2; + } + + return sprintf ".word\t0x%08x !%s", + 0x81b00000|$rd<<25|$rs1<<14|$opf<<5|$rs2, + $ref; + } else { + return $ref; + } +} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/ge; + + s/\b(umulxhi|addxc[c]{0,2})\s+(%[goli][0-7]),\s*(%[goli][0-7]),\s*(%[goli][0-7])/ + &unvis3($1,$2,$3,$4) + /ge; + + print $_,"\n"; +} + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/ecp_nistz256-x86.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/ecp_nistz256-x86.pl new file mode 100755 index 000000000..0c6fc665b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/ecp_nistz256-x86.pl @@ -0,0 +1,1866 @@ +#! /usr/bin/env perl +# Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# ECP_NISTZ256 module for x86/SSE2. +# +# October 2014. +# +# Original ECP_NISTZ256 submission targeting x86_64 is detailed in +# http://eprint.iacr.org/2013/816. In the process of adaptation +# original .c module was made 32-bit savvy in order to make this +# implementation possible. +# +# with/without -DECP_NISTZ256_ASM +# Pentium +66-163% +# PIII +72-172% +# P4 +65-132% +# Core2 +90-215% +# Sandy Bridge +105-265% (contemporary i[57]-* are all close to this) +# Atom +65-155% +# Opteron +54-110% +# Bulldozer +99-240% +# VIA Nano +93-290% +# +# Ranges denote minimum and maximum improvement coefficients depending +# on benchmark. Lower coefficients are for ECDSA sign, server-side +# operation. Keep in mind that +200% means 3x improvement. + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +$output=pop; +open STDOUT,">$output"; + +&asm_init($ARGV[0],$ARGV[$#ARGV] eq "386"); + +$sse2=0; +for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); } + +&external_label("OPENSSL_ia32cap_P") if ($sse2); + + +######################################################################## +# Convert ecp_nistz256_table.c to layout expected by ecp_nistz_gather_w7 +# +open TABLE,") { + s/TOBN\(\s*(0x[0-9a-f]+),\s*(0x[0-9a-f]+)\s*\)/push @arr,hex($2),hex($1)/geo; +} +close TABLE; + +# See ecp_nistz256_table.c for explanation for why it's 64*16*37. +# 64*16*37-1 is because $#arr returns last valid index or @arr, not +# amount of elements. +die "insane number of elements" if ($#arr != 64*16*37-1); + +&public_label("ecp_nistz256_precomputed"); +&align(4096); +&set_label("ecp_nistz256_precomputed"); + +######################################################################## +# this conversion smashes P256_POINT_AFFINE by individual bytes with +# 64 byte interval, similar to +# 1111222233334444 +# 1234123412341234 +for(1..37) { + @tbl = splice(@arr,0,64*16); + for($i=0;$i<64;$i++) { + undef @line; + for($j=0;$j<64;$j++) { + push @line,(@tbl[$j*16+$i/4]>>(($i%4)*8))&0xff; + } + &data_byte(join(',',map { sprintf "0x%02x",$_} @line)); + } +} + +######################################################################## +# Keep in mind that constants are stored least to most significant word +&static_label("RR"); +&set_label("RR",64); +&data_word(3,0,-1,-5,-2,-1,-3,4); # 2^512 mod P-256 + +&static_label("ONE_mont"); +&set_label("ONE_mont"); +&data_word(1,0,0,-1,-1,-1,-2,0); + +&static_label("ONE"); +&set_label("ONE"); +&data_word(1,0,0,0,0,0,0,0); +&asciz("ECP_NISZ256 for x86/SSE2, CRYPTOGAMS by "); +&align(64); + +######################################################################## +# void ecp_nistz256_mul_by_2(BN_ULONG edi[8],const BN_ULONG esi[8]); +&function_begin("ecp_nistz256_mul_by_2"); + &mov ("esi",&wparam(1)); + &mov ("edi",&wparam(0)); + &mov ("ebp","esi"); +######################################################################## +# common pattern for internal functions is that %edi is result pointer, +# %esi and %ebp are input ones, %ebp being optional. %edi is preserved. + &call ("_ecp_nistz256_add"); +&function_end("ecp_nistz256_mul_by_2"); + +######################################################################## +# void ecp_nistz256_mul_by_3(BN_ULONG edi[8],const BN_ULONG esi[8]); +&function_begin("ecp_nistz256_mul_by_3"); + &mov ("esi",&wparam(1)); + # multiplication by 3 is performed + # as 2*n+n, but we can't use output + # to store 2*n, because if output + # pointer equals to input, then + # we'll get 2*n+2*n. + &stack_push(8); # therefore we need to allocate + # 256-bit intermediate buffer. + &mov ("edi","esp"); + &mov ("ebp","esi"); + &call ("_ecp_nistz256_add"); + &lea ("esi",&DWP(0,"edi")); + &mov ("ebp",&wparam(1)); + &mov ("edi",&wparam(0)); + &call ("_ecp_nistz256_add"); + &stack_pop(8); +&function_end("ecp_nistz256_mul_by_3"); + +######################################################################## +# void ecp_nistz256_div_by_2(BN_ULONG edi[8],const BN_ULONG esi[8]); +&function_begin("ecp_nistz256_div_by_2"); + &mov ("esi",&wparam(1)); + &mov ("edi",&wparam(0)); + &call ("_ecp_nistz256_div_by_2"); +&function_end("ecp_nistz256_div_by_2"); + +&function_begin_B("_ecp_nistz256_div_by_2"); + # tmp = a is odd ? a+mod : a + # + # note that because mod has special form, i.e. consists of + # 0xffffffff, 1 and 0s, we can conditionally synthesize it by + # assigning least significant bit of input to one register, + # %ebp, and its negative to another, %edx. + + &mov ("ebp",&DWP(0,"esi")); + &xor ("edx","edx"); + &mov ("ebx",&DWP(4,"esi")); + &mov ("eax","ebp"); + &and ("ebp",1); + &mov ("ecx",&DWP(8,"esi")); + &sub ("edx","ebp"); + + &add ("eax","edx"); + &adc ("ebx","edx"); + &mov (&DWP(0,"edi"),"eax"); + &adc ("ecx","edx"); + &mov (&DWP(4,"edi"),"ebx"); + &mov (&DWP(8,"edi"),"ecx"); + + &mov ("eax",&DWP(12,"esi")); + &mov ("ebx",&DWP(16,"esi")); + &adc ("eax",0); + &mov ("ecx",&DWP(20,"esi")); + &adc ("ebx",0); + &mov (&DWP(12,"edi"),"eax"); + &adc ("ecx",0); + &mov (&DWP(16,"edi"),"ebx"); + &mov (&DWP(20,"edi"),"ecx"); + + &mov ("eax",&DWP(24,"esi")); + &mov ("ebx",&DWP(28,"esi")); + &adc ("eax","ebp"); + &adc ("ebx","edx"); + &mov (&DWP(24,"edi"),"eax"); + &sbb ("esi","esi"); # broadcast carry bit + &mov (&DWP(28,"edi"),"ebx"); + + # ret = tmp >> 1 + + &mov ("eax",&DWP(0,"edi")); + &mov ("ebx",&DWP(4,"edi")); + &mov ("ecx",&DWP(8,"edi")); + &mov ("edx",&DWP(12,"edi")); + + &shr ("eax",1); + &mov ("ebp","ebx"); + &shl ("ebx",31); + &or ("eax","ebx"); + + &shr ("ebp",1); + &mov ("ebx","ecx"); + &shl ("ecx",31); + &mov (&DWP(0,"edi"),"eax"); + &or ("ebp","ecx"); + &mov ("eax",&DWP(16,"edi")); + + &shr ("ebx",1); + &mov ("ecx","edx"); + &shl ("edx",31); + &mov (&DWP(4,"edi"),"ebp"); + &or ("ebx","edx"); + &mov ("ebp",&DWP(20,"edi")); + + &shr ("ecx",1); + &mov ("edx","eax"); + &shl ("eax",31); + &mov (&DWP(8,"edi"),"ebx"); + &or ("ecx","eax"); + &mov ("ebx",&DWP(24,"edi")); + + &shr ("edx",1); + &mov ("eax","ebp"); + &shl ("ebp",31); + &mov (&DWP(12,"edi"),"ecx"); + &or ("edx","ebp"); + &mov ("ecx",&DWP(28,"edi")); + + &shr ("eax",1); + &mov ("ebp","ebx"); + &shl ("ebx",31); + &mov (&DWP(16,"edi"),"edx"); + &or ("eax","ebx"); + + &shr ("ebp",1); + &mov ("ebx","ecx"); + &shl ("ecx",31); + &mov (&DWP(20,"edi"),"eax"); + &or ("ebp","ecx"); + + &shr ("ebx",1); + &shl ("esi",31); + &mov (&DWP(24,"edi"),"ebp"); + &or ("ebx","esi"); # handle top-most carry bit + &mov (&DWP(28,"edi"),"ebx"); + + &ret (); +&function_end_B("_ecp_nistz256_div_by_2"); + +######################################################################## +# void ecp_nistz256_add(BN_ULONG edi[8],const BN_ULONG esi[8], +# const BN_ULONG ebp[8]); +&function_begin("ecp_nistz256_add"); + &mov ("esi",&wparam(1)); + &mov ("ebp",&wparam(2)); + &mov ("edi",&wparam(0)); + &call ("_ecp_nistz256_add"); +&function_end("ecp_nistz256_add"); + +&function_begin_B("_ecp_nistz256_add"); + &mov ("eax",&DWP(0,"esi")); + &mov ("ebx",&DWP(4,"esi")); + &mov ("ecx",&DWP(8,"esi")); + &add ("eax",&DWP(0,"ebp")); + &mov ("edx",&DWP(12,"esi")); + &adc ("ebx",&DWP(4,"ebp")); + &mov (&DWP(0,"edi"),"eax"); + &adc ("ecx",&DWP(8,"ebp")); + &mov (&DWP(4,"edi"),"ebx"); + &adc ("edx",&DWP(12,"ebp")); + &mov (&DWP(8,"edi"),"ecx"); + &mov (&DWP(12,"edi"),"edx"); + + &mov ("eax",&DWP(16,"esi")); + &mov ("ebx",&DWP(20,"esi")); + &mov ("ecx",&DWP(24,"esi")); + &adc ("eax",&DWP(16,"ebp")); + &mov ("edx",&DWP(28,"esi")); + &adc ("ebx",&DWP(20,"ebp")); + &mov (&DWP(16,"edi"),"eax"); + &adc ("ecx",&DWP(24,"ebp")); + &mov (&DWP(20,"edi"),"ebx"); + &mov ("esi",0); + &adc ("edx",&DWP(28,"ebp")); + &mov (&DWP(24,"edi"),"ecx"); + &adc ("esi",0); + &mov (&DWP(28,"edi"),"edx"); + + # if a+b >= modulus, subtract modulus. + # + # But since comparison implies subtraction, we subtract modulus + # to see if it borrows, and then subtract it for real if + # subtraction didn't borrow. + + &mov ("eax",&DWP(0,"edi")); + &mov ("ebx",&DWP(4,"edi")); + &mov ("ecx",&DWP(8,"edi")); + &sub ("eax",-1); + &mov ("edx",&DWP(12,"edi")); + &sbb ("ebx",-1); + &mov ("eax",&DWP(16,"edi")); + &sbb ("ecx",-1); + &mov ("ebx",&DWP(20,"edi")); + &sbb ("edx",0); + &mov ("ecx",&DWP(24,"edi")); + &sbb ("eax",0); + &mov ("edx",&DWP(28,"edi")); + &sbb ("ebx",0); + &sbb ("ecx",1); + &sbb ("edx",-1); + &sbb ("esi",0); + + # Note that because mod has special form, i.e. consists of + # 0xffffffff, 1 and 0s, we can conditionally synthesize it by + # by using borrow. + + ¬ ("esi"); + &mov ("eax",&DWP(0,"edi")); + &mov ("ebp","esi"); + &mov ("ebx",&DWP(4,"edi")); + &shr ("ebp",31); + &mov ("ecx",&DWP(8,"edi")); + &sub ("eax","esi"); + &mov ("edx",&DWP(12,"edi")); + &sbb ("ebx","esi"); + &mov (&DWP(0,"edi"),"eax"); + &sbb ("ecx","esi"); + &mov (&DWP(4,"edi"),"ebx"); + &sbb ("edx",0); + &mov (&DWP(8,"edi"),"ecx"); + &mov (&DWP(12,"edi"),"edx"); + + &mov ("eax",&DWP(16,"edi")); + &mov ("ebx",&DWP(20,"edi")); + &mov ("ecx",&DWP(24,"edi")); + &sbb ("eax",0); + &mov ("edx",&DWP(28,"edi")); + &sbb ("ebx",0); + &mov (&DWP(16,"edi"),"eax"); + &sbb ("ecx","ebp"); + &mov (&DWP(20,"edi"),"ebx"); + &sbb ("edx","esi"); + &mov (&DWP(24,"edi"),"ecx"); + &mov (&DWP(28,"edi"),"edx"); + + &ret (); +&function_end_B("_ecp_nistz256_add"); + +######################################################################## +# void ecp_nistz256_sub(BN_ULONG edi[8],const BN_ULONG esi[8], +# const BN_ULONG ebp[8]); +&function_begin("ecp_nistz256_sub"); + &mov ("esi",&wparam(1)); + &mov ("ebp",&wparam(2)); + &mov ("edi",&wparam(0)); + &call ("_ecp_nistz256_sub"); +&function_end("ecp_nistz256_sub"); + +&function_begin_B("_ecp_nistz256_sub"); + &mov ("eax",&DWP(0,"esi")); + &mov ("ebx",&DWP(4,"esi")); + &mov ("ecx",&DWP(8,"esi")); + &sub ("eax",&DWP(0,"ebp")); + &mov ("edx",&DWP(12,"esi")); + &sbb ("ebx",&DWP(4,"ebp")); + &mov (&DWP(0,"edi"),"eax"); + &sbb ("ecx",&DWP(8,"ebp")); + &mov (&DWP(4,"edi"),"ebx"); + &sbb ("edx",&DWP(12,"ebp")); + &mov (&DWP(8,"edi"),"ecx"); + &mov (&DWP(12,"edi"),"edx"); + + &mov ("eax",&DWP(16,"esi")); + &mov ("ebx",&DWP(20,"esi")); + &mov ("ecx",&DWP(24,"esi")); + &sbb ("eax",&DWP(16,"ebp")); + &mov ("edx",&DWP(28,"esi")); + &sbb ("ebx",&DWP(20,"ebp")); + &sbb ("ecx",&DWP(24,"ebp")); + &mov (&DWP(16,"edi"),"eax"); + &sbb ("edx",&DWP(28,"ebp")); + &mov (&DWP(20,"edi"),"ebx"); + &sbb ("esi","esi"); # broadcast borrow bit + &mov (&DWP(24,"edi"),"ecx"); + &mov (&DWP(28,"edi"),"edx"); + + # if a-b borrows, add modulus. + # + # Note that because mod has special form, i.e. consists of + # 0xffffffff, 1 and 0s, we can conditionally synthesize it by + # assigning borrow bit to one register, %ebp, and its negative + # to another, %esi. But we started by calculating %esi... + + &mov ("eax",&DWP(0,"edi")); + &mov ("ebp","esi"); + &mov ("ebx",&DWP(4,"edi")); + &shr ("ebp",31); + &mov ("ecx",&DWP(8,"edi")); + &add ("eax","esi"); + &mov ("edx",&DWP(12,"edi")); + &adc ("ebx","esi"); + &mov (&DWP(0,"edi"),"eax"); + &adc ("ecx","esi"); + &mov (&DWP(4,"edi"),"ebx"); + &adc ("edx",0); + &mov (&DWP(8,"edi"),"ecx"); + &mov (&DWP(12,"edi"),"edx"); + + &mov ("eax",&DWP(16,"edi")); + &mov ("ebx",&DWP(20,"edi")); + &mov ("ecx",&DWP(24,"edi")); + &adc ("eax",0); + &mov ("edx",&DWP(28,"edi")); + &adc ("ebx",0); + &mov (&DWP(16,"edi"),"eax"); + &adc ("ecx","ebp"); + &mov (&DWP(20,"edi"),"ebx"); + &adc ("edx","esi"); + &mov (&DWP(24,"edi"),"ecx"); + &mov (&DWP(28,"edi"),"edx"); + + &ret (); +&function_end_B("_ecp_nistz256_sub"); + +######################################################################## +# void ecp_nistz256_neg(BN_ULONG edi[8],const BN_ULONG esi[8]); +&function_begin("ecp_nistz256_neg"); + &mov ("ebp",&wparam(1)); + &mov ("edi",&wparam(0)); + + &xor ("eax","eax"); + &stack_push(8); + &mov (&DWP(0,"esp"),"eax"); + &mov ("esi","esp"); + &mov (&DWP(4,"esp"),"eax"); + &mov (&DWP(8,"esp"),"eax"); + &mov (&DWP(12,"esp"),"eax"); + &mov (&DWP(16,"esp"),"eax"); + &mov (&DWP(20,"esp"),"eax"); + &mov (&DWP(24,"esp"),"eax"); + &mov (&DWP(28,"esp"),"eax"); + + &call ("_ecp_nistz256_sub"); + + &stack_pop(8); +&function_end("ecp_nistz256_neg"); + +&function_begin_B("_picup_eax"); + &mov ("eax",&DWP(0,"esp")); + &ret (); +&function_end_B("_picup_eax"); + +######################################################################## +# void ecp_nistz256_to_mont(BN_ULONG edi[8],const BN_ULONG esi[8]); +&function_begin("ecp_nistz256_to_mont"); + &mov ("esi",&wparam(1)); + &call ("_picup_eax"); + &set_label("pic"); + &lea ("ebp",&DWP(&label("RR")."-".&label("pic"),"eax")); + if ($sse2) { + &picmeup("eax","OPENSSL_ia32cap_P","eax",&label("pic")); + &mov ("eax",&DWP(0,"eax")); } + &mov ("edi",&wparam(0)); + &call ("_ecp_nistz256_mul_mont"); +&function_end("ecp_nistz256_to_mont"); + +######################################################################## +# void ecp_nistz256_from_mont(BN_ULONG edi[8],const BN_ULONG esi[8]); +&function_begin("ecp_nistz256_from_mont"); + &mov ("esi",&wparam(1)); + &call ("_picup_eax"); + &set_label("pic"); + &lea ("ebp",&DWP(&label("ONE")."-".&label("pic"),"eax")); + if ($sse2) { + &picmeup("eax","OPENSSL_ia32cap_P","eax",&label("pic")); + &mov ("eax",&DWP(0,"eax")); } + &mov ("edi",&wparam(0)); + &call ("_ecp_nistz256_mul_mont"); +&function_end("ecp_nistz256_from_mont"); + +######################################################################## +# void ecp_nistz256_mul_mont(BN_ULONG edi[8],const BN_ULONG esi[8], +# const BN_ULONG ebp[8]); +&function_begin("ecp_nistz256_mul_mont"); + &mov ("esi",&wparam(1)); + &mov ("ebp",&wparam(2)); + if ($sse2) { + &call ("_picup_eax"); + &set_label("pic"); + &picmeup("eax","OPENSSL_ia32cap_P","eax",&label("pic")); + &mov ("eax",&DWP(0,"eax")); } + &mov ("edi",&wparam(0)); + &call ("_ecp_nistz256_mul_mont"); +&function_end("ecp_nistz256_mul_mont"); + +######################################################################## +# void ecp_nistz256_sqr_mont(BN_ULONG edi[8],const BN_ULONG esi[8]); +&function_begin("ecp_nistz256_sqr_mont"); + &mov ("esi",&wparam(1)); + if ($sse2) { + &call ("_picup_eax"); + &set_label("pic"); + &picmeup("eax","OPENSSL_ia32cap_P","eax",&label("pic")); + &mov ("eax",&DWP(0,"eax")); } + &mov ("edi",&wparam(0)); + &mov ("ebp","esi"); + &call ("_ecp_nistz256_mul_mont"); +&function_end("ecp_nistz256_sqr_mont"); + +&function_begin_B("_ecp_nistz256_mul_mont"); + if ($sse2) { + &and ("eax",1<<24|1<<26); + &cmp ("eax",1<<24|1<<26); # see if XMM+SSE2 is on + &jne (&label("mul_mont_ialu")); + + ######################################## + # SSE2 code path featuring 32x16-bit + # multiplications is ~2x faster than + # IALU counterpart (except on Atom)... + ######################################## + # stack layout: + # +------------------------------------+< %esp + # | 7 16-byte temporary XMM words, | + # | "sliding" toward lower address | + # . . + # +------------------------------------+ + # | unused XMM word | + # +------------------------------------+< +128,%ebx + # | 8 16-byte XMM words holding copies | + # | of a[i]<<64|a[i] | + # . . + # . . + # +------------------------------------+< +256 + &mov ("edx","esp"); + &sub ("esp",0x100); + + &movd ("xmm7",&DWP(0,"ebp")); # b[0] -> 0000.00xy + &lea ("ebp",&DWP(4,"ebp")); + &pcmpeqd("xmm6","xmm6"); + &psrlq ("xmm6",48); # compose 0xffff<<64|0xffff + + &pshuflw("xmm7","xmm7",0b11011100); # 0000.00xy -> 0000.0x0y + &and ("esp",-64); + &pshufd ("xmm7","xmm7",0b11011100); # 0000.0x0y -> 000x.000y + &lea ("ebx",&DWP(0x80,"esp")); + + &movd ("xmm0",&DWP(4*0,"esi")); # a[0] -> 0000.00xy + &pshufd ("xmm0","xmm0",0b11001100); # 0000.00xy -> 00xy.00xy + &movd ("xmm1",&DWP(4*1,"esi")); # a[1] -> ... + &movdqa (&QWP(0x00,"ebx"),"xmm0"); # offload converted a[0] + &pmuludq("xmm0","xmm7"); # a[0]*b[0] + + &movd ("xmm2",&DWP(4*2,"esi")); + &pshufd ("xmm1","xmm1",0b11001100); + &movdqa (&QWP(0x10,"ebx"),"xmm1"); + &pmuludq("xmm1","xmm7"); # a[1]*b[0] + + &movq ("xmm4","xmm0"); # clear upper 64 bits + &pslldq("xmm4",6); + &paddq ("xmm4","xmm0"); + &movdqa("xmm5","xmm4"); + &psrldq("xmm4",10); # upper 32 bits of a[0]*b[0] + &pand ("xmm5","xmm6"); # lower 32 bits of a[0]*b[0] + + # Upper half of a[0]*b[i] is carried into next multiplication + # iteration, while lower one "participates" in actual reduction. + # Normally latter is done by accumulating result of multiplication + # of modulus by "magic" digit, but thanks to special form of modulus + # and "magic" digit it can be performed only with additions and + # subtractions (see note in IALU section below). Note that we are + # not bothered with carry bits, they are accumulated in "flatten" + # phase after all multiplications and reductions. + + &movd ("xmm3",&DWP(4*3,"esi")); + &pshufd ("xmm2","xmm2",0b11001100); + &movdqa (&QWP(0x20,"ebx"),"xmm2"); + &pmuludq("xmm2","xmm7"); # a[2]*b[0] + &paddq ("xmm1","xmm4"); # a[1]*b[0]+hw(a[0]*b[0]), carry + &movdqa (&QWP(0x00,"esp"),"xmm1"); # t[0] + + &movd ("xmm0",&DWP(4*4,"esi")); + &pshufd ("xmm3","xmm3",0b11001100); + &movdqa (&QWP(0x30,"ebx"),"xmm3"); + &pmuludq("xmm3","xmm7"); # a[3]*b[0] + &movdqa (&QWP(0x10,"esp"),"xmm2"); + + &movd ("xmm1",&DWP(4*5,"esi")); + &pshufd ("xmm0","xmm0",0b11001100); + &movdqa (&QWP(0x40,"ebx"),"xmm0"); + &pmuludq("xmm0","xmm7"); # a[4]*b[0] + &paddq ("xmm3","xmm5"); # a[3]*b[0]+lw(a[0]*b[0]), reduction step + &movdqa (&QWP(0x20,"esp"),"xmm3"); + + &movd ("xmm2",&DWP(4*6,"esi")); + &pshufd ("xmm1","xmm1",0b11001100); + &movdqa (&QWP(0x50,"ebx"),"xmm1"); + &pmuludq("xmm1","xmm7"); # a[5]*b[0] + &movdqa (&QWP(0x30,"esp"),"xmm0"); + &pshufd("xmm4","xmm5",0b10110001); # xmm4 = xmm5<<32, reduction step + + &movd ("xmm3",&DWP(4*7,"esi")); + &pshufd ("xmm2","xmm2",0b11001100); + &movdqa (&QWP(0x60,"ebx"),"xmm2"); + &pmuludq("xmm2","xmm7"); # a[6]*b[0] + &movdqa (&QWP(0x40,"esp"),"xmm1"); + &psubq ("xmm4","xmm5"); # xmm4 = xmm5*0xffffffff, reduction step + + &movd ("xmm0",&DWP(0,"ebp")); # b[1] -> 0000.00xy + &pshufd ("xmm3","xmm3",0b11001100); + &movdqa (&QWP(0x70,"ebx"),"xmm3"); + &pmuludq("xmm3","xmm7"); # a[7]*b[0] + + &pshuflw("xmm7","xmm0",0b11011100); # 0000.00xy -> 0000.0x0y + &movdqa ("xmm0",&QWP(0x00,"ebx")); # pre-load converted a[0] + &pshufd ("xmm7","xmm7",0b11011100); # 0000.0x0y -> 000x.000y + + &mov ("ecx",6); + &lea ("ebp",&DWP(4,"ebp")); + &jmp (&label("madd_sse2")); + +&set_label("madd_sse2",16); + &paddq ("xmm2","xmm5"); # a[6]*b[i-1]+lw(a[0]*b[i-1]), reduction step [modulo-scheduled] + &paddq ("xmm3","xmm4"); # a[7]*b[i-1]+lw(a[0]*b[i-1])*0xffffffff, reduction step [modulo-scheduled] + &movdqa ("xmm1",&QWP(0x10,"ebx")); + &pmuludq("xmm0","xmm7"); # a[0]*b[i] + &movdqa(&QWP(0x50,"esp"),"xmm2"); + + &movdqa ("xmm2",&QWP(0x20,"ebx")); + &pmuludq("xmm1","xmm7"); # a[1]*b[i] + &movdqa(&QWP(0x60,"esp"),"xmm3"); + &paddq ("xmm0",&QWP(0x00,"esp")); + + &movdqa ("xmm3",&QWP(0x30,"ebx")); + &pmuludq("xmm2","xmm7"); # a[2]*b[i] + &movq ("xmm4","xmm0"); # clear upper 64 bits + &pslldq("xmm4",6); + &paddq ("xmm1",&QWP(0x10,"esp")); + &paddq ("xmm4","xmm0"); + &movdqa("xmm5","xmm4"); + &psrldq("xmm4",10); # upper 33 bits of a[0]*b[i]+t[0] + + &movdqa ("xmm0",&QWP(0x40,"ebx")); + &pmuludq("xmm3","xmm7"); # a[3]*b[i] + &paddq ("xmm1","xmm4"); # a[1]*b[i]+hw(a[0]*b[i]), carry + &paddq ("xmm2",&QWP(0x20,"esp")); + &movdqa (&QWP(0x00,"esp"),"xmm1"); + + &movdqa ("xmm1",&QWP(0x50,"ebx")); + &pmuludq("xmm0","xmm7"); # a[4]*b[i] + &paddq ("xmm3",&QWP(0x30,"esp")); + &movdqa (&QWP(0x10,"esp"),"xmm2"); + &pand ("xmm5","xmm6"); # lower 32 bits of a[0]*b[i] + + &movdqa ("xmm2",&QWP(0x60,"ebx")); + &pmuludq("xmm1","xmm7"); # a[5]*b[i] + &paddq ("xmm3","xmm5"); # a[3]*b[i]+lw(a[0]*b[i]), reduction step + &paddq ("xmm0",&QWP(0x40,"esp")); + &movdqa (&QWP(0x20,"esp"),"xmm3"); + &pshufd("xmm4","xmm5",0b10110001); # xmm4 = xmm5<<32, reduction step + + &movdqa ("xmm3","xmm7"); + &pmuludq("xmm2","xmm7"); # a[6]*b[i] + &movd ("xmm7",&DWP(0,"ebp")); # b[i++] -> 0000.00xy + &lea ("ebp",&DWP(4,"ebp")); + &paddq ("xmm1",&QWP(0x50,"esp")); + &psubq ("xmm4","xmm5"); # xmm4 = xmm5*0xffffffff, reduction step + &movdqa (&QWP(0x30,"esp"),"xmm0"); + &pshuflw("xmm7","xmm7",0b11011100); # 0000.00xy -> 0000.0x0y + + &pmuludq("xmm3",&QWP(0x70,"ebx")); # a[7]*b[i] + &pshufd("xmm7","xmm7",0b11011100); # 0000.0x0y -> 000x.000y + &movdqa("xmm0",&QWP(0x00,"ebx")); # pre-load converted a[0] + &movdqa (&QWP(0x40,"esp"),"xmm1"); + &paddq ("xmm2",&QWP(0x60,"esp")); + + &dec ("ecx"); + &jnz (&label("madd_sse2")); + + &paddq ("xmm2","xmm5"); # a[6]*b[6]+lw(a[0]*b[6]), reduction step [modulo-scheduled] + &paddq ("xmm3","xmm4"); # a[7]*b[6]+lw(a[0]*b[6])*0xffffffff, reduction step [modulo-scheduled] + &movdqa ("xmm1",&QWP(0x10,"ebx")); + &pmuludq("xmm0","xmm7"); # a[0]*b[7] + &movdqa(&QWP(0x50,"esp"),"xmm2"); + + &movdqa ("xmm2",&QWP(0x20,"ebx")); + &pmuludq("xmm1","xmm7"); # a[1]*b[7] + &movdqa(&QWP(0x60,"esp"),"xmm3"); + &paddq ("xmm0",&QWP(0x00,"esp")); + + &movdqa ("xmm3",&QWP(0x30,"ebx")); + &pmuludq("xmm2","xmm7"); # a[2]*b[7] + &movq ("xmm4","xmm0"); # clear upper 64 bits + &pslldq("xmm4",6); + &paddq ("xmm1",&QWP(0x10,"esp")); + &paddq ("xmm4","xmm0"); + &movdqa("xmm5","xmm4"); + &psrldq("xmm4",10); # upper 33 bits of a[0]*b[i]+t[0] + + &movdqa ("xmm0",&QWP(0x40,"ebx")); + &pmuludq("xmm3","xmm7"); # a[3]*b[7] + &paddq ("xmm1","xmm4"); # a[1]*b[7]+hw(a[0]*b[7]), carry + &paddq ("xmm2",&QWP(0x20,"esp")); + &movdqa (&QWP(0x00,"esp"),"xmm1"); + + &movdqa ("xmm1",&QWP(0x50,"ebx")); + &pmuludq("xmm0","xmm7"); # a[4]*b[7] + &paddq ("xmm3",&QWP(0x30,"esp")); + &movdqa (&QWP(0x10,"esp"),"xmm2"); + &pand ("xmm5","xmm6"); # lower 32 bits of a[0]*b[i] + + &movdqa ("xmm2",&QWP(0x60,"ebx")); + &pmuludq("xmm1","xmm7"); # a[5]*b[7] + &paddq ("xmm3","xmm5"); # reduction step + &paddq ("xmm0",&QWP(0x40,"esp")); + &movdqa (&QWP(0x20,"esp"),"xmm3"); + &pshufd("xmm4","xmm5",0b10110001); # xmm4 = xmm5<<32, reduction step + + &movdqa ("xmm3",&QWP(0x70,"ebx")); + &pmuludq("xmm2","xmm7"); # a[6]*b[7] + &paddq ("xmm1",&QWP(0x50,"esp")); + &psubq ("xmm4","xmm5"); # xmm4 = xmm5*0xffffffff, reduction step + &movdqa (&QWP(0x30,"esp"),"xmm0"); + + &pmuludq("xmm3","xmm7"); # a[7]*b[7] + &pcmpeqd("xmm7","xmm7"); + &movdqa ("xmm0",&QWP(0x00,"esp")); + &pslldq ("xmm7",8); + &movdqa (&QWP(0x40,"esp"),"xmm1"); + &paddq ("xmm2",&QWP(0x60,"esp")); + + &paddq ("xmm2","xmm5"); # a[6]*b[7]+lw(a[0]*b[7]), reduction step + &paddq ("xmm3","xmm4"); # a[6]*b[7]+lw(a[0]*b[7])*0xffffffff, reduction step + &movdqa(&QWP(0x50,"esp"),"xmm2"); + &movdqa(&QWP(0x60,"esp"),"xmm3"); + + &movdqa ("xmm1",&QWP(0x10,"esp")); + &movdqa ("xmm2",&QWP(0x20,"esp")); + &movdqa ("xmm3",&QWP(0x30,"esp")); + + &movq ("xmm4","xmm0"); # "flatten" + &pand ("xmm0","xmm7"); + &xor ("ebp","ebp"); + &pslldq ("xmm4",6); + &movq ("xmm5","xmm1"); + &paddq ("xmm0","xmm4"); + &pand ("xmm1","xmm7"); + &psrldq ("xmm0",6); + &movd ("eax","xmm0"); + &psrldq ("xmm0",4); + + &paddq ("xmm5","xmm0"); + &movdqa ("xmm0",&QWP(0x40,"esp")); + &sub ("eax",-1); # start subtracting modulus, + # this is used to determine + # if result is larger/smaller + # than modulus (see below) + &pslldq ("xmm5",6); + &movq ("xmm4","xmm2"); + &paddq ("xmm1","xmm5"); + &pand ("xmm2","xmm7"); + &psrldq ("xmm1",6); + &mov (&DWP(4*0,"edi"),"eax"); + &movd ("eax","xmm1"); + &psrldq ("xmm1",4); + + &paddq ("xmm4","xmm1"); + &movdqa ("xmm1",&QWP(0x50,"esp")); + &sbb ("eax",-1); + &pslldq ("xmm4",6); + &movq ("xmm5","xmm3"); + &paddq ("xmm2","xmm4"); + &pand ("xmm3","xmm7"); + &psrldq ("xmm2",6); + &mov (&DWP(4*1,"edi"),"eax"); + &movd ("eax","xmm2"); + &psrldq ("xmm2",4); + + &paddq ("xmm5","xmm2"); + &movdqa ("xmm2",&QWP(0x60,"esp")); + &sbb ("eax",-1); + &pslldq ("xmm5",6); + &movq ("xmm4","xmm0"); + &paddq ("xmm3","xmm5"); + &pand ("xmm0","xmm7"); + &psrldq ("xmm3",6); + &mov (&DWP(4*2,"edi"),"eax"); + &movd ("eax","xmm3"); + &psrldq ("xmm3",4); + + &paddq ("xmm4","xmm3"); + &sbb ("eax",0); + &pslldq ("xmm4",6); + &movq ("xmm5","xmm1"); + &paddq ("xmm0","xmm4"); + &pand ("xmm1","xmm7"); + &psrldq ("xmm0",6); + &mov (&DWP(4*3,"edi"),"eax"); + &movd ("eax","xmm0"); + &psrldq ("xmm0",4); + + &paddq ("xmm5","xmm0"); + &sbb ("eax",0); + &pslldq ("xmm5",6); + &movq ("xmm4","xmm2"); + &paddq ("xmm1","xmm5"); + &pand ("xmm2","xmm7"); + &psrldq ("xmm1",6); + &movd ("ebx","xmm1"); + &psrldq ("xmm1",4); + &mov ("esp","edx"); + + &paddq ("xmm4","xmm1"); + &pslldq ("xmm4",6); + &paddq ("xmm2","xmm4"); + &psrldq ("xmm2",6); + &movd ("ecx","xmm2"); + &psrldq ("xmm2",4); + &sbb ("ebx",0); + &movd ("edx","xmm2"); + &pextrw ("esi","xmm2",2); # top-most overflow bit + &sbb ("ecx",1); + &sbb ("edx",-1); + &sbb ("esi",0); # borrow from subtraction + + # Final step is "if result > mod, subtract mod", and at this point + # we have result - mod written to output buffer, as well as borrow + # bit from this subtraction, and if borrow bit is set, we add + # modulus back. + # + # Note that because mod has special form, i.e. consists of + # 0xffffffff, 1 and 0s, we can conditionally synthesize it by + # assigning borrow bit to one register, %ebp, and its negative + # to another, %esi. But we started by calculating %esi... + + &sub ("ebp","esi"); + &add (&DWP(4*0,"edi"),"esi"); # add modulus or zero + &adc (&DWP(4*1,"edi"),"esi"); + &adc (&DWP(4*2,"edi"),"esi"); + &adc (&DWP(4*3,"edi"),0); + &adc ("eax",0); + &adc ("ebx",0); + &mov (&DWP(4*4,"edi"),"eax"); + &adc ("ecx","ebp"); + &mov (&DWP(4*5,"edi"),"ebx"); + &adc ("edx","esi"); + &mov (&DWP(4*6,"edi"),"ecx"); + &mov (&DWP(4*7,"edi"),"edx"); + + &ret (); + +&set_label("mul_mont_ialu",16); } + + ######################################## + # IALU code path suitable for all CPUs. + ######################################## + # stack layout: + # +------------------------------------+< %esp + # | 8 32-bit temporary words, accessed | + # | as circular buffer | + # . . + # . . + # +------------------------------------+< +32 + # | offloaded destination pointer | + # +------------------------------------+ + # | unused | + # +------------------------------------+< +40 + &sub ("esp",10*4); + + &mov ("eax",&DWP(0*4,"esi")); # a[0] + &mov ("ebx",&DWP(0*4,"ebp")); # b[0] + &mov (&DWP(8*4,"esp"),"edi"); # off-load dst ptr + + &mul ("ebx"); # a[0]*b[0] + &mov (&DWP(0*4,"esp"),"eax"); # t[0] + &mov ("eax",&DWP(1*4,"esi")); + &mov ("ecx","edx") + + &mul ("ebx"); # a[1]*b[0] + &add ("ecx","eax"); + &mov ("eax",&DWP(2*4,"esi")); + &adc ("edx",0); + &mov (&DWP(1*4,"esp"),"ecx"); # t[1] + &mov ("ecx","edx"); + + &mul ("ebx"); # a[2]*b[0] + &add ("ecx","eax"); + &mov ("eax",&DWP(3*4,"esi")); + &adc ("edx",0); + &mov (&DWP(2*4,"esp"),"ecx"); # t[2] + &mov ("ecx","edx"); + + &mul ("ebx"); # a[3]*b[0] + &add ("ecx","eax"); + &mov ("eax",&DWP(4*4,"esi")); + &adc ("edx",0); + &mov (&DWP(3*4,"esp"),"ecx"); # t[3] + &mov ("ecx","edx"); + + &mul ("ebx"); # a[4]*b[0] + &add ("ecx","eax"); + &mov ("eax",&DWP(5*4,"esi")); + &adc ("edx",0); + &mov (&DWP(4*4,"esp"),"ecx"); # t[4] + &mov ("ecx","edx"); + + &mul ("ebx"); # a[5]*b[0] + &add ("ecx","eax"); + &mov ("eax",&DWP(6*4,"esi")); + &adc ("edx",0); + &mov (&DWP(5*4,"esp"),"ecx"); # t[5] + &mov ("ecx","edx"); + + &mul ("ebx"); # a[6]*b[0] + &add ("ecx","eax"); + &mov ("eax",&DWP(7*4,"esi")); + &adc ("edx",0); + &mov (&DWP(6*4,"esp"),"ecx"); # t[6] + &mov ("ecx","edx"); + + &xor ("edi","edi"); # initial top-most carry + &mul ("ebx"); # a[7]*b[0] + &add ("ecx","eax"); # t[7] + &mov ("eax",&DWP(0*4,"esp")); # t[0] + &adc ("edx",0); # t[8] + +for ($i=0;$i<7;$i++) { + my $j=$i+1; + + # Reduction iteration is normally performed by accumulating + # result of multiplication of modulus by "magic" digit [and + # omitting least significant word, which is guaranteed to + # be 0], but thanks to special form of modulus and "magic" + # digit being equal to least significant word, it can be + # performed with additions and subtractions alone. Indeed: + # + # ffff.0001.0000.0000.0000.ffff.ffff.ffff + # * abcd + # + xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.abcd + # + # Now observing that ff..ff*x = (2^n-1)*x = 2^n*x-x, we + # rewrite above as: + # + # xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.abcd + # + abcd.0000.abcd.0000.0000.abcd.0000.0000.0000 + # - abcd.0000.0000.0000.0000.0000.0000.abcd + # + # or marking redundant operations: + # + # xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.---- + # + abcd.0000.abcd.0000.0000.abcd.----.----.---- + # - abcd.----.----.----.----.----.----.---- + + &add (&DWP((($i+3)%8)*4,"esp"),"eax"); # t[3]+=t[0] + &adc (&DWP((($i+4)%8)*4,"esp"),0); # t[4]+=0 + &adc (&DWP((($i+5)%8)*4,"esp"),0); # t[5]+=0 + &adc (&DWP((($i+6)%8)*4,"esp"),"eax"); # t[6]+=t[0] + &adc ("ecx",0); # t[7]+=0 + &adc ("edx","eax"); # t[8]+=t[0] + &adc ("edi",0); # top-most carry + &mov ("ebx",&DWP($j*4,"ebp")); # b[i] + &sub ("ecx","eax"); # t[7]-=t[0] + &mov ("eax",&DWP(0*4,"esi")); # a[0] + &sbb ("edx",0); # t[8]-=0 + &mov (&DWP((($i+7)%8)*4,"esp"),"ecx"); + &sbb ("edi",0); # top-most carry, + # keep in mind that + # netto result is + # *addition* of value + # with (abcd<<32)-abcd + # on top, so that + # underflow is + # impossible, because + # (abcd<<32)-abcd + # doesn't underflow + &mov (&DWP((($i+8)%8)*4,"esp"),"edx"); + + &mul ("ebx"); # a[0]*b[i] + &add ("eax",&DWP((($j+0)%8)*4,"esp")); + &adc ("edx",0); + &mov (&DWP((($j+0)%8)*4,"esp"),"eax"); + &mov ("eax",&DWP(1*4,"esi")); + &mov ("ecx","edx") + + &mul ("ebx"); # a[1]*b[i] + &add ("ecx",&DWP((($j+1)%8)*4,"esp")); + &adc ("edx",0); + &add ("ecx","eax"); + &adc ("edx",0); + &mov ("eax",&DWP(2*4,"esi")); + &mov (&DWP((($j+1)%8)*4,"esp"),"ecx"); + &mov ("ecx","edx"); + + &mul ("ebx"); # a[2]*b[i] + &add ("ecx",&DWP((($j+2)%8)*4,"esp")); + &adc ("edx",0); + &add ("ecx","eax"); + &adc ("edx",0); + &mov ("eax",&DWP(3*4,"esi")); + &mov (&DWP((($j+2)%8)*4,"esp"),"ecx"); + &mov ("ecx","edx"); + + &mul ("ebx"); # a[3]*b[i] + &add ("ecx",&DWP((($j+3)%8)*4,"esp")); + &adc ("edx",0); + &add ("ecx","eax"); + &adc ("edx",0); + &mov ("eax",&DWP(4*4,"esi")); + &mov (&DWP((($j+3)%8)*4,"esp"),"ecx"); + &mov ("ecx","edx"); + + &mul ("ebx"); # a[4]*b[i] + &add ("ecx",&DWP((($j+4)%8)*4,"esp")); + &adc ("edx",0); + &add ("ecx","eax"); + &adc ("edx",0); + &mov ("eax",&DWP(5*4,"esi")); + &mov (&DWP((($j+4)%8)*4,"esp"),"ecx"); + &mov ("ecx","edx"); + + &mul ("ebx"); # a[5]*b[i] + &add ("ecx",&DWP((($j+5)%8)*4,"esp")); + &adc ("edx",0); + &add ("ecx","eax"); + &adc ("edx",0); + &mov ("eax",&DWP(6*4,"esi")); + &mov (&DWP((($j+5)%8)*4,"esp"),"ecx"); + &mov ("ecx","edx"); + + &mul ("ebx"); # a[6]*b[i] + &add ("ecx",&DWP((($j+6)%8)*4,"esp")); + &adc ("edx",0); + &add ("ecx","eax"); + &adc ("edx",0); + &mov ("eax",&DWP(7*4,"esi")); + &mov (&DWP((($j+6)%8)*4,"esp"),"ecx"); + &mov ("ecx","edx"); + + &mul ("ebx"); # a[7]*b[i] + &add ("ecx",&DWP((($j+7)%8)*4,"esp")); + &adc ("edx",0); + &add ("ecx","eax"); # t[7] + &mov ("eax",&DWP((($j+0)%8)*4,"esp")); # t[0] + &adc ("edx","edi"); # t[8] + &mov ("edi",0); + &adc ("edi",0); # top-most carry +} + &mov ("ebp",&DWP(8*4,"esp")); # restore dst ptr + &xor ("esi","esi"); + my $j=$i+1; + + # last multiplication-less reduction + &add (&DWP((($i+3)%8)*4,"esp"),"eax"); # t[3]+=t[0] + &adc (&DWP((($i+4)%8)*4,"esp"),0); # t[4]+=0 + &adc (&DWP((($i+5)%8)*4,"esp"),0); # t[5]+=0 + &adc (&DWP((($i+6)%8)*4,"esp"),"eax"); # t[6]+=t[0] + &adc ("ecx",0); # t[7]+=0 + &adc ("edx","eax"); # t[8]+=t[0] + &adc ("edi",0); # top-most carry + &mov ("ebx",&DWP((($j+1)%8)*4,"esp")); + &sub ("ecx","eax"); # t[7]-=t[0] + &mov ("eax",&DWP((($j+0)%8)*4,"esp")); + &sbb ("edx",0); # t[8]-=0 + &mov (&DWP((($i+7)%8)*4,"esp"),"ecx"); + &sbb ("edi",0); # top-most carry + &mov (&DWP((($i+8)%8)*4,"esp"),"edx"); + + # Final step is "if result > mod, subtract mod", but we do it + # "other way around", namely write result - mod to output buffer + # and if subtraction borrowed, add modulus back. + + &mov ("ecx",&DWP((($j+2)%8)*4,"esp")); + &sub ("eax",-1); + &mov ("edx",&DWP((($j+3)%8)*4,"esp")); + &sbb ("ebx",-1); + &mov (&DWP(0*4,"ebp"),"eax"); + &sbb ("ecx",-1); + &mov (&DWP(1*4,"ebp"),"ebx"); + &sbb ("edx",0); + &mov (&DWP(2*4,"ebp"),"ecx"); + &mov (&DWP(3*4,"ebp"),"edx"); + + &mov ("eax",&DWP((($j+4)%8)*4,"esp")); + &mov ("ebx",&DWP((($j+5)%8)*4,"esp")); + &mov ("ecx",&DWP((($j+6)%8)*4,"esp")); + &sbb ("eax",0); + &mov ("edx",&DWP((($j+7)%8)*4,"esp")); + &sbb ("ebx",0); + &sbb ("ecx",1); + &sbb ("edx",-1); + &sbb ("edi",0); + + # Note that because mod has special form, i.e. consists of + # 0xffffffff, 1 and 0s, we can conditionally synthesize it by + # assigning borrow bit to one register, %ebp, and its negative + # to another, %esi. But we started by calculating %esi... + + &sub ("esi","edi"); + &add (&DWP(0*4,"ebp"),"edi"); # add modulus or zero + &adc (&DWP(1*4,"ebp"),"edi"); + &adc (&DWP(2*4,"ebp"),"edi"); + &adc (&DWP(3*4,"ebp"),0); + &adc ("eax",0); + &adc ("ebx",0); + &mov (&DWP(4*4,"ebp"),"eax"); + &adc ("ecx","esi"); + &mov (&DWP(5*4,"ebp"),"ebx"); + &adc ("edx","edi"); + &mov (&DWP(6*4,"ebp"),"ecx"); + &mov ("edi","ebp"); # fulfill contract + &mov (&DWP(7*4,"ebp"),"edx"); + + &add ("esp",10*4); + &ret (); +&function_end_B("_ecp_nistz256_mul_mont"); + +######################################################################## +# void ecp_nistz256_scatter_w5(void *edi,const P256_POINT *esi, +# int ebp); +&function_begin("ecp_nistz256_scatter_w5"); + &mov ("edi",&wparam(0)); + &mov ("esi",&wparam(1)); + &mov ("ebp",&wparam(2)); + + &lea ("edi",&DWP(128-4,"edi","ebp",4)); + &mov ("ebp",96/16); +&set_label("scatter_w5_loop"); + &mov ("eax",&DWP(0,"esi")); + &mov ("ebx",&DWP(4,"esi")); + &mov ("ecx",&DWP(8,"esi")); + &mov ("edx",&DWP(12,"esi")); + &lea ("esi",&DWP(16,"esi")); + &mov (&DWP(64*0-128,"edi"),"eax"); + &mov (&DWP(64*1-128,"edi"),"ebx"); + &mov (&DWP(64*2-128,"edi"),"ecx"); + &mov (&DWP(64*3-128,"edi"),"edx"); + &lea ("edi",&DWP(64*4,"edi")); + &dec ("ebp"); + &jnz (&label("scatter_w5_loop")); +&function_end("ecp_nistz256_scatter_w5"); + +######################################################################## +# void ecp_nistz256_gather_w5(P256_POINT *edi,const void *esi, +# int ebp); +&function_begin("ecp_nistz256_gather_w5"); + &mov ("esi",&wparam(1)); + &mov ("ebp",&wparam(2)); + + &lea ("esi",&DWP(0,"esi","ebp",4)); + &neg ("ebp"); + &sar ("ebp",31); + &mov ("edi",&wparam(0)); + &lea ("esi",&DWP(0,"esi","ebp",4)); + + for($i=0;$i<24;$i+=4) { + &mov ("eax",&DWP(64*($i+0),"esi")); + &mov ("ebx",&DWP(64*($i+1),"esi")); + &mov ("ecx",&DWP(64*($i+2),"esi")); + &mov ("edx",&DWP(64*($i+3),"esi")); + &and ("eax","ebp"); + &and ("ebx","ebp"); + &and ("ecx","ebp"); + &and ("edx","ebp"); + &mov (&DWP(4*($i+0),"edi"),"eax"); + &mov (&DWP(4*($i+1),"edi"),"ebx"); + &mov (&DWP(4*($i+2),"edi"),"ecx"); + &mov (&DWP(4*($i+3),"edi"),"edx"); + } +&function_end("ecp_nistz256_gather_w5"); + +######################################################################## +# void ecp_nistz256_scatter_w7(void *edi,const P256_POINT_AFFINE *esi, +# int ebp); +&function_begin("ecp_nistz256_scatter_w7"); + &mov ("edi",&wparam(0)); + &mov ("esi",&wparam(1)); + &mov ("ebp",&wparam(2)); + + &lea ("edi",&DWP(0,"edi","ebp")); + &mov ("ebp",64/4); +&set_label("scatter_w7_loop"); + &mov ("eax",&DWP(0,"esi")); + &lea ("esi",&DWP(4,"esi")); + &mov (&BP(64*0,"edi"),"al"); + &mov (&BP(64*1,"edi"),"ah"); + &shr ("eax",16); + &mov (&BP(64*2,"edi"),"al"); + &mov (&BP(64*3,"edi"),"ah"); + &lea ("edi",&DWP(64*4,"edi")); + &dec ("ebp"); + &jnz (&label("scatter_w7_loop")); +&function_end("ecp_nistz256_scatter_w7"); + +######################################################################## +# void ecp_nistz256_gather_w7(P256_POINT_AFFINE *edi,const void *esi, +# int ebp); +&function_begin("ecp_nistz256_gather_w7"); + &mov ("esi",&wparam(1)); + &mov ("ebp",&wparam(2)); + + &add ("esi","ebp"); + &neg ("ebp"), + &sar ("ebp",31); + &mov ("edi",&wparam(0)); + &lea ("esi",&DWP(0,"esi","ebp")); + + for($i=0;$i<64;$i+=4) { + &movz ("eax",&BP(64*($i+0),"esi")); + &movz ("ebx",&BP(64*($i+1),"esi")); + &movz ("ecx",&BP(64*($i+2),"esi")); + &and ("eax","ebp"); + &movz ("edx",&BP(64*($i+3),"esi")); + &and ("ebx","ebp"); + &mov (&BP($i+0,"edi"),"al"); + &and ("ecx","ebp"); + &mov (&BP($i+1,"edi"),"bl"); + &and ("edx","ebp"); + &mov (&BP($i+2,"edi"),"cl"); + &mov (&BP($i+3,"edi"),"dl"); + } +&function_end("ecp_nistz256_gather_w7"); + +######################################################################## +# following subroutines are "literal" implementation of those found in +# ecp_nistz256.c +# +######################################################################## +# void ecp_nistz256_point_double(P256_POINT *out,const P256_POINT *inp); +# +&static_label("point_double_shortcut"); +&function_begin("ecp_nistz256_point_double"); +{ my ($S,$M,$Zsqr,$in_x,$tmp0)=map(32*$_,(0..4)); + + &mov ("esi",&wparam(1)); + + # above map() describes stack layout with 5 temporary + # 256-bit vectors on top, then we take extra word for + # OPENSSL_ia32cap_P copy. + &stack_push(8*5+1); + if ($sse2) { + &call ("_picup_eax"); + &set_label("pic"); + &picmeup("edx","OPENSSL_ia32cap_P","eax",&label("pic")); + &mov ("ebp",&DWP(0,"edx")); } + +&set_label("point_double_shortcut"); + &mov ("eax",&DWP(0,"esi")); # copy in_x + &mov ("ebx",&DWP(4,"esi")); + &mov ("ecx",&DWP(8,"esi")); + &mov ("edx",&DWP(12,"esi")); + &mov (&DWP($in_x+0,"esp"),"eax"); + &mov (&DWP($in_x+4,"esp"),"ebx"); + &mov (&DWP($in_x+8,"esp"),"ecx"); + &mov (&DWP($in_x+12,"esp"),"edx"); + &mov ("eax",&DWP(16,"esi")); + &mov ("ebx",&DWP(20,"esi")); + &mov ("ecx",&DWP(24,"esi")); + &mov ("edx",&DWP(28,"esi")); + &mov (&DWP($in_x+16,"esp"),"eax"); + &mov (&DWP($in_x+20,"esp"),"ebx"); + &mov (&DWP($in_x+24,"esp"),"ecx"); + &mov (&DWP($in_x+28,"esp"),"edx"); + &mov (&DWP(32*5,"esp"),"ebp"); # OPENSSL_ia32cap_P copy + + &lea ("ebp",&DWP(32,"esi")); + &lea ("esi",&DWP(32,"esi")); + &lea ("edi",&DWP($S,"esp")); + &call ("_ecp_nistz256_add"); # p256_mul_by_2(S, in_y); + + &mov ("eax",&DWP(32*5,"esp")); # OPENSSL_ia32cap_P copy + &mov ("esi",64); + &add ("esi",&wparam(1)); + &lea ("edi",&DWP($Zsqr,"esp")); + &mov ("ebp","esi"); + &call ("_ecp_nistz256_mul_mont"); # p256_sqr_mont(Zsqr, in_z); + + &mov ("eax",&DWP(32*5,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($S,"esp")); + &lea ("ebp",&DWP($S,"esp")); + &lea ("edi",&DWP($S,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_sqr_mont(S, S); + + &mov ("eax",&DWP(32*5,"esp")); # OPENSSL_ia32cap_P copy + &mov ("ebp",&wparam(1)); + &lea ("esi",&DWP(32,"ebp")); + &lea ("ebp",&DWP(64,"ebp")); + &lea ("edi",&DWP($tmp0,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_mul_mont(tmp0, in_z, in_y); + + &lea ("esi",&DWP($in_x,"esp")); + &lea ("ebp",&DWP($Zsqr,"esp")); + &lea ("edi",&DWP($M,"esp")); + &call ("_ecp_nistz256_add"); # p256_add(M, in_x, Zsqr); + + &mov ("edi",64); + &lea ("esi",&DWP($tmp0,"esp")); + &lea ("ebp",&DWP($tmp0,"esp")); + &add ("edi",&wparam(0)); + &call ("_ecp_nistz256_add"); # p256_mul_by_2(res_z, tmp0); + + &lea ("esi",&DWP($in_x,"esp")); + &lea ("ebp",&DWP($Zsqr,"esp")); + &lea ("edi",&DWP($Zsqr,"esp")); + &call ("_ecp_nistz256_sub"); # p256_sub(Zsqr, in_x, Zsqr); + + &mov ("eax",&DWP(32*5,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($S,"esp")); + &lea ("ebp",&DWP($S,"esp")); + &lea ("edi",&DWP($tmp0,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_sqr_mont(tmp0, S); + + &mov ("eax",&DWP(32*5,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($M,"esp")); + &lea ("ebp",&DWP($Zsqr,"esp")); + &lea ("edi",&DWP($M,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_mul_mont(M, M, Zsqr); + + &mov ("edi",32); + &lea ("esi",&DWP($tmp0,"esp")); + &add ("edi",&wparam(0)); + &call ("_ecp_nistz256_div_by_2"); # p256_div_by_2(res_y, tmp0); + + &lea ("esi",&DWP($M,"esp")); + &lea ("ebp",&DWP($M,"esp")); + &lea ("edi",&DWP($tmp0,"esp")); + &call ("_ecp_nistz256_add"); # 1/2 p256_mul_by_3(M, M); + + &mov ("eax",&DWP(32*5,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($in_x,"esp")); + &lea ("ebp",&DWP($S,"esp")); + &lea ("edi",&DWP($S,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_mul_mont(S, S, in_x); + + &lea ("esi",&DWP($tmp0,"esp")); + &lea ("ebp",&DWP($M,"esp")); + &lea ("edi",&DWP($M,"esp")); + &call ("_ecp_nistz256_add"); # 2/2 p256_mul_by_3(M, M); + + &lea ("esi",&DWP($S,"esp")); + &lea ("ebp",&DWP($S,"esp")); + &lea ("edi",&DWP($tmp0,"esp")); + &call ("_ecp_nistz256_add"); # p256_mul_by_2(tmp0, S); + + &mov ("eax",&DWP(32*5,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($M,"esp")); + &lea ("ebp",&DWP($M,"esp")); + &mov ("edi",&wparam(0)); + &call ("_ecp_nistz256_mul_mont"); # p256_sqr_mont(res_x, M); + + &mov ("esi","edi"); # %edi is still res_x here + &lea ("ebp",&DWP($tmp0,"esp")); + &call ("_ecp_nistz256_sub"); # p256_sub(res_x, res_x, tmp0); + + &lea ("esi",&DWP($S,"esp")); + &mov ("ebp","edi"); # %edi is still res_x + &lea ("edi",&DWP($S,"esp")); + &call ("_ecp_nistz256_sub"); # p256_sub(S, S, res_x); + + &mov ("eax",&DWP(32*5,"esp")); # OPENSSL_ia32cap_P copy + &mov ("esi","edi"); # %edi is still &S + &lea ("ebp",&DWP($M,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_mul_mont(S, S, M); + + &mov ("ebp",32); + &lea ("esi",&DWP($S,"esp")); + &add ("ebp",&wparam(0)); + &mov ("edi","ebp"); + &call ("_ecp_nistz256_sub"); # p256_sub(res_y, S, res_y); + + &stack_pop(8*5+1); +} &function_end("ecp_nistz256_point_double"); + +######################################################################## +# void ecp_nistz256_point_add(P256_POINT *out,const P256_POINT *in1, +# const P256_POINT *in2); +&function_begin("ecp_nistz256_point_add"); +{ my ($res_x,$res_y,$res_z, + $in1_x,$in1_y,$in1_z, + $in2_x,$in2_y,$in2_z, + $H,$Hsqr,$R,$Rsqr,$Hcub, + $U1,$U2,$S1,$S2)=map(32*$_,(0..17)); + my ($Z1sqr, $Z2sqr) = ($Hsqr, $Rsqr); + + &mov ("esi",&wparam(2)); + + # above map() describes stack layout with 18 temporary + # 256-bit vectors on top, then we take extra words for + # !in1infty, !in2infty, result of check for zero and + # OPENSSL_ia32cap_P copy. [one unused word for padding] + &stack_push(8*18+5); + if ($sse2) { + &call ("_picup_eax"); + &set_label("pic"); + &picmeup("edx","OPENSSL_ia32cap_P","eax",&label("pic")); + &mov ("ebp",&DWP(0,"edx")); } + + &lea ("edi",&DWP($in2_x,"esp")); + for($i=0;$i<96;$i+=16) { + &mov ("eax",&DWP($i+0,"esi")); # copy in2 + &mov ("ebx",&DWP($i+4,"esi")); + &mov ("ecx",&DWP($i+8,"esi")); + &mov ("edx",&DWP($i+12,"esi")); + &mov (&DWP($i+0,"edi"),"eax"); + &mov (&DWP(32*18+12,"esp"),"ebp") if ($i==0); + &mov ("ebp","eax") if ($i==64); + &or ("ebp","eax") if ($i>64); + &mov (&DWP($i+4,"edi"),"ebx"); + &or ("ebp","ebx") if ($i>=64); + &mov (&DWP($i+8,"edi"),"ecx"); + &or ("ebp","ecx") if ($i>=64); + &mov (&DWP($i+12,"edi"),"edx"); + &or ("ebp","edx") if ($i>=64); + } + &xor ("eax","eax"); + &mov ("esi",&wparam(1)); + &sub ("eax","ebp"); + &or ("ebp","eax"); + &sar ("ebp",31); + &mov (&DWP(32*18+4,"esp"),"ebp"); # !in2infty + + &lea ("edi",&DWP($in1_x,"esp")); + for($i=0;$i<96;$i+=16) { + &mov ("eax",&DWP($i+0,"esi")); # copy in1 + &mov ("ebx",&DWP($i+4,"esi")); + &mov ("ecx",&DWP($i+8,"esi")); + &mov ("edx",&DWP($i+12,"esi")); + &mov (&DWP($i+0,"edi"),"eax"); + &mov ("ebp","eax") if ($i==64); + &or ("ebp","eax") if ($i>64); + &mov (&DWP($i+4,"edi"),"ebx"); + &or ("ebp","ebx") if ($i>=64); + &mov (&DWP($i+8,"edi"),"ecx"); + &or ("ebp","ecx") if ($i>=64); + &mov (&DWP($i+12,"edi"),"edx"); + &or ("ebp","edx") if ($i>=64); + } + &xor ("eax","eax"); + &sub ("eax","ebp"); + &or ("ebp","eax"); + &sar ("ebp",31); + &mov (&DWP(32*18+0,"esp"),"ebp"); # !in1infty + + &mov ("eax",&DWP(32*18+12,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($in2_z,"esp")); + &lea ("ebp",&DWP($in2_z,"esp")); + &lea ("edi",&DWP($Z2sqr,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_sqr_mont(Z2sqr, in2_z); + + &mov ("eax",&DWP(32*18+12,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($in1_z,"esp")); + &lea ("ebp",&DWP($in1_z,"esp")); + &lea ("edi",&DWP($Z1sqr,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_sqr_mont(Z1sqr, in1_z); + + &mov ("eax",&DWP(32*18+12,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($Z2sqr,"esp")); + &lea ("ebp",&DWP($in2_z,"esp")); + &lea ("edi",&DWP($S1,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_mul_mont(S1, Z2sqr, in2_z); + + &mov ("eax",&DWP(32*18+12,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($Z1sqr,"esp")); + &lea ("ebp",&DWP($in1_z,"esp")); + &lea ("edi",&DWP($S2,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_mul_mont(S2, Z1sqr, in1_z); + + &mov ("eax",&DWP(32*18+12,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($in1_y,"esp")); + &lea ("ebp",&DWP($S1,"esp")); + &lea ("edi",&DWP($S1,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_mul_mont(S1, S1, in1_y); + + &mov ("eax",&DWP(32*18+12,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($in2_y,"esp")); + &lea ("ebp",&DWP($S2,"esp")); + &lea ("edi",&DWP($S2,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_mul_mont(S2, S2, in2_y); + + &lea ("esi",&DWP($S2,"esp")); + &lea ("ebp",&DWP($S1,"esp")); + &lea ("edi",&DWP($R,"esp")); + &call ("_ecp_nistz256_sub"); # p256_sub(R, S2, S1); + + &or ("ebx","eax"); # see if result is zero + &mov ("eax",&DWP(32*18+12,"esp")); # OPENSSL_ia32cap_P copy + &or ("ebx","ecx"); + &or ("ebx","edx"); + &or ("ebx",&DWP(0,"edi")); + &or ("ebx",&DWP(4,"edi")); + &lea ("esi",&DWP($in1_x,"esp")); + &or ("ebx",&DWP(8,"edi")); + &lea ("ebp",&DWP($Z2sqr,"esp")); + &or ("ebx",&DWP(12,"edi")); + &lea ("edi",&DWP($U1,"esp")); + &mov (&DWP(32*18+8,"esp"),"ebx"); + + &call ("_ecp_nistz256_mul_mont"); # p256_mul_mont(U1, in1_x, Z2sqr); + + &mov ("eax",&DWP(32*18+12,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($in2_x,"esp")); + &lea ("ebp",&DWP($Z1sqr,"esp")); + &lea ("edi",&DWP($U2,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_mul_mont(U2, in2_x, Z1sqr); + + &lea ("esi",&DWP($U2,"esp")); + &lea ("ebp",&DWP($U1,"esp")); + &lea ("edi",&DWP($H,"esp")); + &call ("_ecp_nistz256_sub"); # p256_sub(H, U2, U1); + + &or ("eax","ebx"); # see if result is zero + &or ("eax","ecx"); + &or ("eax","edx"); + &or ("eax",&DWP(0,"edi")); + &or ("eax",&DWP(4,"edi")); + &or ("eax",&DWP(8,"edi")); + &or ("eax",&DWP(12,"edi")); + + &data_byte(0x3e); # predict taken + &jnz (&label("add_proceed")); # is_equal(U1,U2)? + + &mov ("eax",&DWP(32*18+0,"esp")); + &and ("eax",&DWP(32*18+4,"esp")); + &mov ("ebx",&DWP(32*18+8,"esp")); + &jz (&label("add_proceed")); # (in1infty || in2infty)? + &test ("ebx","ebx"); + &jz (&label("add_double")); # is_equal(S1,S2)? + + &mov ("edi",&wparam(0)); + &xor ("eax","eax"); + &mov ("ecx",96/4); + &data_byte(0xfc,0xf3,0xab); # cld; stosd + &jmp (&label("add_done")); + +&set_label("add_double",16); + &mov ("esi",&wparam(1)); + &mov ("ebp",&DWP(32*18+12,"esp")); # OPENSSL_ia32cap_P copy + &add ("esp",4*((8*18+5)-(8*5+1))); # difference in frame sizes + &jmp (&label("point_double_shortcut")); + +&set_label("add_proceed",16); + &mov ("eax",&DWP(32*18+12,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($R,"esp")); + &lea ("ebp",&DWP($R,"esp")); + &lea ("edi",&DWP($Rsqr,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_sqr_mont(Rsqr, R); + + &mov ("eax",&DWP(32*18+12,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($H,"esp")); + &lea ("ebp",&DWP($in1_z,"esp")); + &lea ("edi",&DWP($res_z,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_mul_mont(res_z, H, in1_z); + + &mov ("eax",&DWP(32*18+12,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($H,"esp")); + &lea ("ebp",&DWP($H,"esp")); + &lea ("edi",&DWP($Hsqr,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_sqr_mont(Hsqr, H); + + &mov ("eax",&DWP(32*18+12,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($in2_z,"esp")); + &lea ("ebp",&DWP($res_z,"esp")); + &lea ("edi",&DWP($res_z,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_mul_mont(res_z, res_z, in2_z); + + &mov ("eax",&DWP(32*18+12,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($Hsqr,"esp")); + &lea ("ebp",&DWP($U1,"esp")); + &lea ("edi",&DWP($U2,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_mul_mont(U2, U1, Hsqr); + + &mov ("eax",&DWP(32*18+12,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($H,"esp")); + &lea ("ebp",&DWP($Hsqr,"esp")); + &lea ("edi",&DWP($Hcub,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_mul_mont(Hcub, Hsqr, H); + + &lea ("esi",&DWP($U2,"esp")); + &lea ("ebp",&DWP($U2,"esp")); + &lea ("edi",&DWP($Hsqr,"esp")); + &call ("_ecp_nistz256_add"); # p256_mul_by_2(Hsqr, U2); + + &lea ("esi",&DWP($Rsqr,"esp")); + &lea ("ebp",&DWP($Hsqr,"esp")); + &lea ("edi",&DWP($res_x,"esp")); + &call ("_ecp_nistz256_sub"); # p256_sub(res_x, Rsqr, Hsqr); + + &lea ("esi",&DWP($res_x,"esp")); + &lea ("ebp",&DWP($Hcub,"esp")); + &lea ("edi",&DWP($res_x,"esp")); + &call ("_ecp_nistz256_sub"); # p256_sub(res_x, res_x, Hcub); + + &lea ("esi",&DWP($U2,"esp")); + &lea ("ebp",&DWP($res_x,"esp")); + &lea ("edi",&DWP($res_y,"esp")); + &call ("_ecp_nistz256_sub"); # p256_sub(res_y, U2, res_x); + + &mov ("eax",&DWP(32*18+12,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($Hcub,"esp")); + &lea ("ebp",&DWP($S1,"esp")); + &lea ("edi",&DWP($S2,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_mul_mont(S2, S1, Hcub); + + &mov ("eax",&DWP(32*18+12,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($R,"esp")); + &lea ("ebp",&DWP($res_y,"esp")); + &lea ("edi",&DWP($res_y,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_mul_mont(res_y, R, res_y); + + &lea ("esi",&DWP($res_y,"esp")); + &lea ("ebp",&DWP($S2,"esp")); + &lea ("edi",&DWP($res_y,"esp")); + &call ("_ecp_nistz256_sub"); # p256_sub(res_y, res_y, S2); + + &mov ("ebp",&DWP(32*18+0,"esp")); # !in1infty + &mov ("esi",&DWP(32*18+4,"esp")); # !in2infty + &mov ("edi",&wparam(0)); + &mov ("edx","ebp"); + ¬ ("ebp"); + &and ("edx","esi"); + &and ("ebp","esi"); + ¬ ("esi"); + + ######################################## + # conditional moves + for($i=64;$i<96;$i+=4) { + &mov ("eax","edx"); + &and ("eax",&DWP($res_x+$i,"esp")); + &mov ("ebx","ebp"); + &and ("ebx",&DWP($in2_x+$i,"esp")); + &mov ("ecx","esi"); + &and ("ecx",&DWP($in1_x+$i,"esp")); + &or ("eax","ebx"); + &or ("eax","ecx"); + &mov (&DWP($i,"edi"),"eax"); + } + for($i=0;$i<64;$i+=4) { + &mov ("eax","edx"); + &and ("eax",&DWP($res_x+$i,"esp")); + &mov ("ebx","ebp"); + &and ("ebx",&DWP($in2_x+$i,"esp")); + &mov ("ecx","esi"); + &and ("ecx",&DWP($in1_x+$i,"esp")); + &or ("eax","ebx"); + &or ("eax","ecx"); + &mov (&DWP($i,"edi"),"eax"); + } + &set_label("add_done"); + &stack_pop(8*18+5); +} &function_end("ecp_nistz256_point_add"); + +######################################################################## +# void ecp_nistz256_point_add_affine(P256_POINT *out, +# const P256_POINT *in1, +# const P256_POINT_AFFINE *in2); +&function_begin("ecp_nistz256_point_add_affine"); +{ + my ($res_x,$res_y,$res_z, + $in1_x,$in1_y,$in1_z, + $in2_x,$in2_y, + $U2,$S2,$H,$R,$Hsqr,$Hcub,$Rsqr)=map(32*$_,(0..14)); + my $Z1sqr = $S2; + my @ONE_mont=(1,0,0,-1,-1,-1,-2,0); + + &mov ("esi",&wparam(1)); + + # above map() describes stack layout with 15 temporary + # 256-bit vectors on top, then we take extra words for + # !in1infty, !in2infty, and OPENSSL_ia32cap_P copy. + &stack_push(8*15+3); + if ($sse2) { + &call ("_picup_eax"); + &set_label("pic"); + &picmeup("edx","OPENSSL_ia32cap_P","eax",&label("pic")); + &mov ("ebp",&DWP(0,"edx")); } + + &lea ("edi",&DWP($in1_x,"esp")); + for($i=0;$i<96;$i+=16) { + &mov ("eax",&DWP($i+0,"esi")); # copy in1 + &mov ("ebx",&DWP($i+4,"esi")); + &mov ("ecx",&DWP($i+8,"esi")); + &mov ("edx",&DWP($i+12,"esi")); + &mov (&DWP($i+0,"edi"),"eax"); + &mov (&DWP(32*15+8,"esp"),"ebp") if ($i==0); + &mov ("ebp","eax") if ($i==64); + &or ("ebp","eax") if ($i>64); + &mov (&DWP($i+4,"edi"),"ebx"); + &or ("ebp","ebx") if ($i>=64); + &mov (&DWP($i+8,"edi"),"ecx"); + &or ("ebp","ecx") if ($i>=64); + &mov (&DWP($i+12,"edi"),"edx"); + &or ("ebp","edx") if ($i>=64); + } + &xor ("eax","eax"); + &mov ("esi",&wparam(2)); + &sub ("eax","ebp"); + &or ("ebp","eax"); + &sar ("ebp",31); + &mov (&DWP(32*15+0,"esp"),"ebp"); # !in1infty + + &lea ("edi",&DWP($in2_x,"esp")); + for($i=0;$i<64;$i+=16) { + &mov ("eax",&DWP($i+0,"esi")); # copy in2 + &mov ("ebx",&DWP($i+4,"esi")); + &mov ("ecx",&DWP($i+8,"esi")); + &mov ("edx",&DWP($i+12,"esi")); + &mov (&DWP($i+0,"edi"),"eax"); + &mov ("ebp","eax") if ($i==0); + &or ("ebp","eax") if ($i!=0); + &mov (&DWP($i+4,"edi"),"ebx"); + &or ("ebp","ebx"); + &mov (&DWP($i+8,"edi"),"ecx"); + &or ("ebp","ecx"); + &mov (&DWP($i+12,"edi"),"edx"); + &or ("ebp","edx"); + } + &xor ("ebx","ebx"); + &mov ("eax",&DWP(32*15+8,"esp")); # OPENSSL_ia32cap_P copy + &sub ("ebx","ebp"); + &lea ("esi",&DWP($in1_z,"esp")); + &or ("ebx","ebp"); + &lea ("ebp",&DWP($in1_z,"esp")); + &sar ("ebx",31); + &lea ("edi",&DWP($Z1sqr,"esp")); + &mov (&DWP(32*15+4,"esp"),"ebx"); # !in2infty + + &call ("_ecp_nistz256_mul_mont"); # p256_sqr_mont(Z1sqr, in1_z); + + &mov ("eax",&DWP(32*15+8,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($in2_x,"esp")); + &mov ("ebp","edi"); # %esi is stull &Z1sqr + &lea ("edi",&DWP($U2,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_mul_mont(U2, Z1sqr, in2_x); + + &mov ("eax",&DWP(32*15+8,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($in1_z,"esp")); + &lea ("ebp",&DWP($Z1sqr,"esp")); + &lea ("edi",&DWP($S2,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_mul_mont(S2, Z1sqr, in1_z); + + &lea ("esi",&DWP($U2,"esp")); + &lea ("ebp",&DWP($in1_x,"esp")); + &lea ("edi",&DWP($H,"esp")); + &call ("_ecp_nistz256_sub"); # p256_sub(H, U2, in1_x); + + &mov ("eax",&DWP(32*15+8,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($in2_y,"esp")); + &lea ("ebp",&DWP($S2,"esp")); + &lea ("edi",&DWP($S2,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_mul_mont(S2, S2, in2_y); + + &mov ("eax",&DWP(32*15+8,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($in1_z,"esp")); + &lea ("ebp",&DWP($H,"esp")); + &lea ("edi",&DWP($res_z,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_mul_mont(res_z, H, in1_z); + + &lea ("esi",&DWP($S2,"esp")); + &lea ("ebp",&DWP($in1_y,"esp")); + &lea ("edi",&DWP($R,"esp")); + &call ("_ecp_nistz256_sub"); # p256_sub(R, S2, in1_y); + + &mov ("eax",&DWP(32*15+8,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($H,"esp")); + &lea ("ebp",&DWP($H,"esp")); + &lea ("edi",&DWP($Hsqr,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_sqr_mont(Hsqr, H); + + &mov ("eax",&DWP(32*15+8,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($R,"esp")); + &lea ("ebp",&DWP($R,"esp")); + &lea ("edi",&DWP($Rsqr,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_sqr_mont(Rsqr, R); + + &mov ("eax",&DWP(32*15+8,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($in1_x,"esp")); + &lea ("ebp",&DWP($Hsqr,"esp")); + &lea ("edi",&DWP($U2,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_mul_mont(U2, in1_x, Hsqr); + + &mov ("eax",&DWP(32*15+8,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($H,"esp")); + &lea ("ebp",&DWP($Hsqr,"esp")); + &lea ("edi",&DWP($Hcub,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_mul_mont(Hcub, Hsqr, H); + + &lea ("esi",&DWP($U2,"esp")); + &lea ("ebp",&DWP($U2,"esp")); + &lea ("edi",&DWP($Hsqr,"esp")); + &call ("_ecp_nistz256_add"); # p256_mul_by_2(Hsqr, U2); + + &lea ("esi",&DWP($Rsqr,"esp")); + &lea ("ebp",&DWP($Hsqr,"esp")); + &lea ("edi",&DWP($res_x,"esp")); + &call ("_ecp_nistz256_sub"); # p256_sub(res_x, Rsqr, Hsqr); + + &lea ("esi",&DWP($res_x,"esp")); + &lea ("ebp",&DWP($Hcub,"esp")); + &lea ("edi",&DWP($res_x,"esp")); + &call ("_ecp_nistz256_sub"); # p256_sub(res_x, res_x, Hcub); + + &lea ("esi",&DWP($U2,"esp")); + &lea ("ebp",&DWP($res_x,"esp")); + &lea ("edi",&DWP($res_y,"esp")); + &call ("_ecp_nistz256_sub"); # p256_sub(res_y, U2, res_x); + + &mov ("eax",&DWP(32*15+8,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($Hcub,"esp")); + &lea ("ebp",&DWP($in1_y,"esp")); + &lea ("edi",&DWP($S2,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_mul_mont(S2, Hcub, in1_y); + + &mov ("eax",&DWP(32*15+8,"esp")); # OPENSSL_ia32cap_P copy + &lea ("esi",&DWP($R,"esp")); + &lea ("ebp",&DWP($res_y,"esp")); + &lea ("edi",&DWP($res_y,"esp")); + &call ("_ecp_nistz256_mul_mont"); # p256_mul_mont(res_y, res_y, R); + + &lea ("esi",&DWP($res_y,"esp")); + &lea ("ebp",&DWP($S2,"esp")); + &lea ("edi",&DWP($res_y,"esp")); + &call ("_ecp_nistz256_sub"); # p256_sub(res_y, res_y, S2); + + &mov ("ebp",&DWP(32*15+0,"esp")); # !in1infty + &mov ("esi",&DWP(32*15+4,"esp")); # !in2infty + &mov ("edi",&wparam(0)); + &mov ("edx","ebp"); + ¬ ("ebp"); + &and ("edx","esi"); + &and ("ebp","esi"); + ¬ ("esi"); + + ######################################## + # conditional moves + for($i=64;$i<96;$i+=4) { + my $one=@ONE_mont[($i-64)/4]; + + &mov ("eax","edx"); + &and ("eax",&DWP($res_x+$i,"esp")); + &mov ("ebx","ebp") if ($one && $one!=-1); + &and ("ebx",$one) if ($one && $one!=-1); + &mov ("ecx","esi"); + &and ("ecx",&DWP($in1_x+$i,"esp")); + &or ("eax",$one==-1?"ebp":"ebx") if ($one); + &or ("eax","ecx"); + &mov (&DWP($i,"edi"),"eax"); + } + for($i=0;$i<64;$i+=4) { + &mov ("eax","edx"); + &and ("eax",&DWP($res_x+$i,"esp")); + &mov ("ebx","ebp"); + &and ("ebx",&DWP($in2_x+$i,"esp")); + &mov ("ecx","esi"); + &and ("ecx",&DWP($in1_x+$i,"esp")); + &or ("eax","ebx"); + &or ("eax","ecx"); + &mov (&DWP($i,"edi"),"eax"); + } + &stack_pop(8*15+3); +} &function_end("ecp_nistz256_point_add_affine"); + +&asm_finish(); + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/ecp_nistz256-x86_64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/ecp_nistz256-x86_64.pl new file mode 100755 index 000000000..87149e7f6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/ecp_nistz256-x86_64.pl @@ -0,0 +1,4741 @@ +#! /usr/bin/env perl +# Copyright 2014-2019 The OpenSSL Project Authors. All Rights Reserved. +# Copyright (c) 2014, Intel Corporation. All Rights Reserved. +# Copyright (c) 2015 CloudFlare, Inc. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html +# +# Originally written by Shay Gueron (1, 2), and Vlad Krasnov (1, 3) +# (1) Intel Corporation, Israel Development Center, Haifa, Israel +# (2) University of Haifa, Israel +# (3) CloudFlare, Inc. +# +# Reference: +# S.Gueron and V.Krasnov, "Fast Prime Field Elliptic Curve Cryptography with +# 256 Bit Primes" + +# Further optimization by : +# +# this/original with/without -DECP_NISTZ256_ASM(*) +# Opteron +15-49% +150-195% +# Bulldozer +18-45% +175-240% +# P4 +24-46% +100-150% +# Westmere +18-34% +87-160% +# Sandy Bridge +14-35% +120-185% +# Ivy Bridge +11-35% +125-180% +# Haswell +10-37% +160-200% +# Broadwell +24-58% +210-270% +# Atom +20-50% +180-240% +# VIA Nano +50-160% +480-480% +# +# (*) "without -DECP_NISTZ256_ASM" refers to build with +# "enable-ec_nistp_64_gcc_128"; +# +# Ranges denote minimum and maximum improvement coefficients depending +# on benchmark. In "this/original" column lower coefficient is for +# ECDSA sign, while in "with/without" - for ECDH key agreement, and +# higher - for ECDSA sign, relatively fastest server-side operation. +# Keep in mind that +100% means 2x improvement. + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +*STDOUT=*OUT; + +if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler version ([2-9]\.[0-9]+)/) { + $avx = ($1>=2.19) + ($1>=2.22); + $addx = ($1>=2.23); +} + +if (!$addx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) && + `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) { + $avx = ($1>=2.09) + ($1>=2.10); + $addx = ($1>=2.10); +} + +if (!$addx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && + `ml64 2>&1` =~ /Version ([0-9]+)\./) { + $avx = ($1>=10) + ($1>=11); + $addx = ($1>=12); +} + +if (!$addx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9])\.([0-9]+)/) { + my $ver = $2 + $3/100.0; # 3.1->3.01, 3.10->3.10 + $avx = ($ver>=3.0) + ($ver>=3.01); + $addx = ($ver>=3.03); +} + +$code.=<<___; +.text +.extern OPENSSL_ia32cap_P + +# The polynomial +.align 64 +.Lpoly: +.quad 0xffffffffffffffff, 0x00000000ffffffff, 0x0000000000000000, 0xffffffff00000001 + +# 2^512 mod P precomputed for NIST P256 polynomial +.LRR: +.quad 0x0000000000000003, 0xfffffffbffffffff, 0xfffffffffffffffe, 0x00000004fffffffd + +.LOne: +.long 1,1,1,1,1,1,1,1 +.LTwo: +.long 2,2,2,2,2,2,2,2 +.LThree: +.long 3,3,3,3,3,3,3,3 +.LONE_mont: +.quad 0x0000000000000001, 0xffffffff00000000, 0xffffffffffffffff, 0x00000000fffffffe + +# Constants for computations modulo ord(p256) +.Lord: +.quad 0xf3b9cac2fc632551, 0xbce6faada7179e84, 0xffffffffffffffff, 0xffffffff00000000 +.LordK: +.quad 0xccd1c8aaee00bc4f +___ + +{ +################################################################################ +# void ecp_nistz256_mul_by_2(uint64_t res[4], uint64_t a[4]); + +my ($a0,$a1,$a2,$a3)=map("%r$_",(8..11)); +my ($t0,$t1,$t2,$t3,$t4)=("%rax","%rdx","%rcx","%r12","%r13"); +my ($r_ptr,$a_ptr,$b_ptr)=("%rdi","%rsi","%rdx"); + +$code.=<<___; + +.globl ecp_nistz256_mul_by_2 +.type ecp_nistz256_mul_by_2,\@function,2 +.align 64 +ecp_nistz256_mul_by_2: +.cfi_startproc + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 +.Lmul_by_2_body: + + mov 8*0($a_ptr), $a0 + xor $t4,$t4 + mov 8*1($a_ptr), $a1 + add $a0, $a0 # a0:a3+a0:a3 + mov 8*2($a_ptr), $a2 + adc $a1, $a1 + mov 8*3($a_ptr), $a3 + lea .Lpoly(%rip), $a_ptr + mov $a0, $t0 + adc $a2, $a2 + adc $a3, $a3 + mov $a1, $t1 + adc \$0, $t4 + + sub 8*0($a_ptr), $a0 + mov $a2, $t2 + sbb 8*1($a_ptr), $a1 + sbb 8*2($a_ptr), $a2 + mov $a3, $t3 + sbb 8*3($a_ptr), $a3 + sbb \$0, $t4 + + cmovc $t0, $a0 + cmovc $t1, $a1 + mov $a0, 8*0($r_ptr) + cmovc $t2, $a2 + mov $a1, 8*1($r_ptr) + cmovc $t3, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) + + mov 0(%rsp),%r13 +.cfi_restore %r13 + mov 8(%rsp),%r12 +.cfi_restore %r12 + lea 16(%rsp),%rsp +.cfi_adjust_cfa_offset -16 +.Lmul_by_2_epilogue: + ret +.cfi_endproc +.size ecp_nistz256_mul_by_2,.-ecp_nistz256_mul_by_2 + +################################################################################ +# void ecp_nistz256_div_by_2(uint64_t res[4], uint64_t a[4]); +.globl ecp_nistz256_div_by_2 +.type ecp_nistz256_div_by_2,\@function,2 +.align 32 +ecp_nistz256_div_by_2: +.cfi_startproc + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 +.Ldiv_by_2_body: + + mov 8*0($a_ptr), $a0 + mov 8*1($a_ptr), $a1 + mov 8*2($a_ptr), $a2 + mov $a0, $t0 + mov 8*3($a_ptr), $a3 + lea .Lpoly(%rip), $a_ptr + + mov $a1, $t1 + xor $t4, $t4 + add 8*0($a_ptr), $a0 + mov $a2, $t2 + adc 8*1($a_ptr), $a1 + adc 8*2($a_ptr), $a2 + mov $a3, $t3 + adc 8*3($a_ptr), $a3 + adc \$0, $t4 + xor $a_ptr, $a_ptr # borrow $a_ptr + test \$1, $t0 + + cmovz $t0, $a0 + cmovz $t1, $a1 + cmovz $t2, $a2 + cmovz $t3, $a3 + cmovz $a_ptr, $t4 + + mov $a1, $t0 # a0:a3>>1 + shr \$1, $a0 + shl \$63, $t0 + mov $a2, $t1 + shr \$1, $a1 + or $t0, $a0 + shl \$63, $t1 + mov $a3, $t2 + shr \$1, $a2 + or $t1, $a1 + shl \$63, $t2 + shr \$1, $a3 + shl \$63, $t4 + or $t2, $a2 + or $t4, $a3 + + mov $a0, 8*0($r_ptr) + mov $a1, 8*1($r_ptr) + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) + + mov 0(%rsp),%r13 +.cfi_restore %r13 + mov 8(%rsp),%r12 +.cfi_restore %r12 + lea 16(%rsp),%rsp +.cfi_adjust_cfa_offset -16 +.Ldiv_by_2_epilogue: + ret +.cfi_endproc +.size ecp_nistz256_div_by_2,.-ecp_nistz256_div_by_2 + +################################################################################ +# void ecp_nistz256_mul_by_3(uint64_t res[4], uint64_t a[4]); +.globl ecp_nistz256_mul_by_3 +.type ecp_nistz256_mul_by_3,\@function,2 +.align 32 +ecp_nistz256_mul_by_3: +.cfi_startproc + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 +.Lmul_by_3_body: + + mov 8*0($a_ptr), $a0 + xor $t4, $t4 + mov 8*1($a_ptr), $a1 + add $a0, $a0 # a0:a3+a0:a3 + mov 8*2($a_ptr), $a2 + adc $a1, $a1 + mov 8*3($a_ptr), $a3 + mov $a0, $t0 + adc $a2, $a2 + adc $a3, $a3 + mov $a1, $t1 + adc \$0, $t4 + + sub \$-1, $a0 + mov $a2, $t2 + sbb .Lpoly+8*1(%rip), $a1 + sbb \$0, $a2 + mov $a3, $t3 + sbb .Lpoly+8*3(%rip), $a3 + sbb \$0, $t4 + + cmovc $t0, $a0 + cmovc $t1, $a1 + cmovc $t2, $a2 + cmovc $t3, $a3 + + xor $t4, $t4 + add 8*0($a_ptr), $a0 # a0:a3+=a_ptr[0:3] + adc 8*1($a_ptr), $a1 + mov $a0, $t0 + adc 8*2($a_ptr), $a2 + adc 8*3($a_ptr), $a3 + mov $a1, $t1 + adc \$0, $t4 + + sub \$-1, $a0 + mov $a2, $t2 + sbb .Lpoly+8*1(%rip), $a1 + sbb \$0, $a2 + mov $a3, $t3 + sbb .Lpoly+8*3(%rip), $a3 + sbb \$0, $t4 + + cmovc $t0, $a0 + cmovc $t1, $a1 + mov $a0, 8*0($r_ptr) + cmovc $t2, $a2 + mov $a1, 8*1($r_ptr) + cmovc $t3, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) + + mov 0(%rsp),%r13 +.cfi_restore %r13 + mov 8(%rsp),%r12 +.cfi_restore %r12 + lea 16(%rsp),%rsp +.cfi_adjust_cfa_offset -16 +.Lmul_by_3_epilogue: + ret +.cfi_endproc +.size ecp_nistz256_mul_by_3,.-ecp_nistz256_mul_by_3 + +################################################################################ +# void ecp_nistz256_add(uint64_t res[4], uint64_t a[4], uint64_t b[4]); +.globl ecp_nistz256_add +.type ecp_nistz256_add,\@function,3 +.align 32 +ecp_nistz256_add: +.cfi_startproc + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 +.Ladd_body: + + mov 8*0($a_ptr), $a0 + xor $t4, $t4 + mov 8*1($a_ptr), $a1 + mov 8*2($a_ptr), $a2 + mov 8*3($a_ptr), $a3 + lea .Lpoly(%rip), $a_ptr + + add 8*0($b_ptr), $a0 + adc 8*1($b_ptr), $a1 + mov $a0, $t0 + adc 8*2($b_ptr), $a2 + adc 8*3($b_ptr), $a3 + mov $a1, $t1 + adc \$0, $t4 + + sub 8*0($a_ptr), $a0 + mov $a2, $t2 + sbb 8*1($a_ptr), $a1 + sbb 8*2($a_ptr), $a2 + mov $a3, $t3 + sbb 8*3($a_ptr), $a3 + sbb \$0, $t4 + + cmovc $t0, $a0 + cmovc $t1, $a1 + mov $a0, 8*0($r_ptr) + cmovc $t2, $a2 + mov $a1, 8*1($r_ptr) + cmovc $t3, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) + + mov 0(%rsp),%r13 +.cfi_restore %r13 + mov 8(%rsp),%r12 +.cfi_restore %r12 + lea 16(%rsp),%rsp +.cfi_adjust_cfa_offset -16 +.Ladd_epilogue: + ret +.cfi_endproc +.size ecp_nistz256_add,.-ecp_nistz256_add + +################################################################################ +# void ecp_nistz256_sub(uint64_t res[4], uint64_t a[4], uint64_t b[4]); +.globl ecp_nistz256_sub +.type ecp_nistz256_sub,\@function,3 +.align 32 +ecp_nistz256_sub: +.cfi_startproc + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 +.Lsub_body: + + mov 8*0($a_ptr), $a0 + xor $t4, $t4 + mov 8*1($a_ptr), $a1 + mov 8*2($a_ptr), $a2 + mov 8*3($a_ptr), $a3 + lea .Lpoly(%rip), $a_ptr + + sub 8*0($b_ptr), $a0 + sbb 8*1($b_ptr), $a1 + mov $a0, $t0 + sbb 8*2($b_ptr), $a2 + sbb 8*3($b_ptr), $a3 + mov $a1, $t1 + sbb \$0, $t4 + + add 8*0($a_ptr), $a0 + mov $a2, $t2 + adc 8*1($a_ptr), $a1 + adc 8*2($a_ptr), $a2 + mov $a3, $t3 + adc 8*3($a_ptr), $a3 + test $t4, $t4 + + cmovz $t0, $a0 + cmovz $t1, $a1 + mov $a0, 8*0($r_ptr) + cmovz $t2, $a2 + mov $a1, 8*1($r_ptr) + cmovz $t3, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) + + mov 0(%rsp),%r13 +.cfi_restore %r13 + mov 8(%rsp),%r12 +.cfi_restore %r12 + lea 16(%rsp),%rsp +.cfi_adjust_cfa_offset -16 +.Lsub_epilogue: + ret +.cfi_endproc +.size ecp_nistz256_sub,.-ecp_nistz256_sub + +################################################################################ +# void ecp_nistz256_neg(uint64_t res[4], uint64_t a[4]); +.globl ecp_nistz256_neg +.type ecp_nistz256_neg,\@function,2 +.align 32 +ecp_nistz256_neg: +.cfi_startproc + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 +.Lneg_body: + + xor $a0, $a0 + xor $a1, $a1 + xor $a2, $a2 + xor $a3, $a3 + xor $t4, $t4 + + sub 8*0($a_ptr), $a0 + sbb 8*1($a_ptr), $a1 + sbb 8*2($a_ptr), $a2 + mov $a0, $t0 + sbb 8*3($a_ptr), $a3 + lea .Lpoly(%rip), $a_ptr + mov $a1, $t1 + sbb \$0, $t4 + + add 8*0($a_ptr), $a0 + mov $a2, $t2 + adc 8*1($a_ptr), $a1 + adc 8*2($a_ptr), $a2 + mov $a3, $t3 + adc 8*3($a_ptr), $a3 + test $t4, $t4 + + cmovz $t0, $a0 + cmovz $t1, $a1 + mov $a0, 8*0($r_ptr) + cmovz $t2, $a2 + mov $a1, 8*1($r_ptr) + cmovz $t3, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) + + mov 0(%rsp),%r13 +.cfi_restore %r13 + mov 8(%rsp),%r12 +.cfi_restore %r12 + lea 16(%rsp),%rsp +.cfi_adjust_cfa_offset -16 +.Lneg_epilogue: + ret +.cfi_endproc +.size ecp_nistz256_neg,.-ecp_nistz256_neg +___ +} +{ +my ($r_ptr,$a_ptr,$b_org,$b_ptr)=("%rdi","%rsi","%rdx","%rbx"); +my ($acc0,$acc1,$acc2,$acc3,$acc4,$acc5,$acc6,$acc7)=map("%r$_",(8..15)); +my ($t0,$t1,$t2,$t3,$t4)=("%rcx","%rbp","%rbx","%rdx","%rax"); +my ($poly1,$poly3)=($acc6,$acc7); + +$code.=<<___; +################################################################################ +# void ecp_nistz256_ord_mul_mont( +# uint64_t res[4], +# uint64_t a[4], +# uint64_t b[4]); + +.globl ecp_nistz256_ord_mul_mont +.type ecp_nistz256_ord_mul_mont,\@function,3 +.align 32 +ecp_nistz256_ord_mul_mont: +.cfi_startproc +___ +$code.=<<___ if ($addx); + mov \$0x80100, %ecx + and OPENSSL_ia32cap_P+8(%rip), %ecx + cmp \$0x80100, %ecx + je .Lecp_nistz256_ord_mul_montx +___ +$code.=<<___; + push %rbp +.cfi_push %rbp + push %rbx +.cfi_push %rbx + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +.Lord_mul_body: + + mov 8*0($b_org), %rax + mov $b_org, $b_ptr + lea .Lord(%rip), %r14 + mov .LordK(%rip), %r15 + + ################################# * b[0] + mov %rax, $t0 + mulq 8*0($a_ptr) + mov %rax, $acc0 + mov $t0, %rax + mov %rdx, $acc1 + + mulq 8*1($a_ptr) + add %rax, $acc1 + mov $t0, %rax + adc \$0, %rdx + mov %rdx, $acc2 + + mulq 8*2($a_ptr) + add %rax, $acc2 + mov $t0, %rax + adc \$0, %rdx + + mov $acc0, $acc5 + imulq %r15,$acc0 + + mov %rdx, $acc3 + mulq 8*3($a_ptr) + add %rax, $acc3 + mov $acc0, %rax + adc \$0, %rdx + mov %rdx, $acc4 + + ################################# First reduction step + mulq 8*0(%r14) + mov $acc0, $t1 + add %rax, $acc5 # guaranteed to be zero + mov $acc0, %rax + adc \$0, %rdx + mov %rdx, $t0 + + sub $acc0, $acc2 + sbb \$0, $acc0 # can't borrow + + mulq 8*1(%r14) + add $t0, $acc1 + adc \$0, %rdx + add %rax, $acc1 + mov $t1, %rax + adc %rdx, $acc2 + mov $t1, %rdx + adc \$0, $acc0 # can't overflow + + shl \$32, %rax + shr \$32, %rdx + sub %rax, $acc3 + mov 8*1($b_ptr), %rax + sbb %rdx, $t1 # can't borrow + + add $acc0, $acc3 + adc $t1, $acc4 + adc \$0, $acc5 + + ################################# * b[1] + mov %rax, $t0 + mulq 8*0($a_ptr) + add %rax, $acc1 + mov $t0, %rax + adc \$0, %rdx + mov %rdx, $t1 + + mulq 8*1($a_ptr) + add $t1, $acc2 + adc \$0, %rdx + add %rax, $acc2 + mov $t0, %rax + adc \$0, %rdx + mov %rdx, $t1 + + mulq 8*2($a_ptr) + add $t1, $acc3 + adc \$0, %rdx + add %rax, $acc3 + mov $t0, %rax + adc \$0, %rdx + + mov $acc1, $t0 + imulq %r15, $acc1 + + mov %rdx, $t1 + mulq 8*3($a_ptr) + add $t1, $acc4 + adc \$0, %rdx + xor $acc0, $acc0 + add %rax, $acc4 + mov $acc1, %rax + adc %rdx, $acc5 + adc \$0, $acc0 + + ################################# Second reduction step + mulq 8*0(%r14) + mov $acc1, $t1 + add %rax, $t0 # guaranteed to be zero + mov $acc1, %rax + adc %rdx, $t0 + + sub $acc1, $acc3 + sbb \$0, $acc1 # can't borrow + + mulq 8*1(%r14) + add $t0, $acc2 + adc \$0, %rdx + add %rax, $acc2 + mov $t1, %rax + adc %rdx, $acc3 + mov $t1, %rdx + adc \$0, $acc1 # can't overflow + + shl \$32, %rax + shr \$32, %rdx + sub %rax, $acc4 + mov 8*2($b_ptr), %rax + sbb %rdx, $t1 # can't borrow + + add $acc1, $acc4 + adc $t1, $acc5 + adc \$0, $acc0 + + ################################## * b[2] + mov %rax, $t0 + mulq 8*0($a_ptr) + add %rax, $acc2 + mov $t0, %rax + adc \$0, %rdx + mov %rdx, $t1 + + mulq 8*1($a_ptr) + add $t1, $acc3 + adc \$0, %rdx + add %rax, $acc3 + mov $t0, %rax + adc \$0, %rdx + mov %rdx, $t1 + + mulq 8*2($a_ptr) + add $t1, $acc4 + adc \$0, %rdx + add %rax, $acc4 + mov $t0, %rax + adc \$0, %rdx + + mov $acc2, $t0 + imulq %r15, $acc2 + + mov %rdx, $t1 + mulq 8*3($a_ptr) + add $t1, $acc5 + adc \$0, %rdx + xor $acc1, $acc1 + add %rax, $acc5 + mov $acc2, %rax + adc %rdx, $acc0 + adc \$0, $acc1 + + ################################# Third reduction step + mulq 8*0(%r14) + mov $acc2, $t1 + add %rax, $t0 # guaranteed to be zero + mov $acc2, %rax + adc %rdx, $t0 + + sub $acc2, $acc4 + sbb \$0, $acc2 # can't borrow + + mulq 8*1(%r14) + add $t0, $acc3 + adc \$0, %rdx + add %rax, $acc3 + mov $t1, %rax + adc %rdx, $acc4 + mov $t1, %rdx + adc \$0, $acc2 # can't overflow + + shl \$32, %rax + shr \$32, %rdx + sub %rax, $acc5 + mov 8*3($b_ptr), %rax + sbb %rdx, $t1 # can't borrow + + add $acc2, $acc5 + adc $t1, $acc0 + adc \$0, $acc1 + + ################################# * b[3] + mov %rax, $t0 + mulq 8*0($a_ptr) + add %rax, $acc3 + mov $t0, %rax + adc \$0, %rdx + mov %rdx, $t1 + + mulq 8*1($a_ptr) + add $t1, $acc4 + adc \$0, %rdx + add %rax, $acc4 + mov $t0, %rax + adc \$0, %rdx + mov %rdx, $t1 + + mulq 8*2($a_ptr) + add $t1, $acc5 + adc \$0, %rdx + add %rax, $acc5 + mov $t0, %rax + adc \$0, %rdx + + mov $acc3, $t0 + imulq %r15, $acc3 + + mov %rdx, $t1 + mulq 8*3($a_ptr) + add $t1, $acc0 + adc \$0, %rdx + xor $acc2, $acc2 + add %rax, $acc0 + mov $acc3, %rax + adc %rdx, $acc1 + adc \$0, $acc2 + + ################################# Last reduction step + mulq 8*0(%r14) + mov $acc3, $t1 + add %rax, $t0 # guaranteed to be zero + mov $acc3, %rax + adc %rdx, $t0 + + sub $acc3, $acc5 + sbb \$0, $acc3 # can't borrow + + mulq 8*1(%r14) + add $t0, $acc4 + adc \$0, %rdx + add %rax, $acc4 + mov $t1, %rax + adc %rdx, $acc5 + mov $t1, %rdx + adc \$0, $acc3 # can't overflow + + shl \$32, %rax + shr \$32, %rdx + sub %rax, $acc0 + sbb %rdx, $t1 # can't borrow + + add $acc3, $acc0 + adc $t1, $acc1 + adc \$0, $acc2 + + ################################# Subtract ord + mov $acc4, $a_ptr + sub 8*0(%r14), $acc4 + mov $acc5, $acc3 + sbb 8*1(%r14), $acc5 + mov $acc0, $t0 + sbb 8*2(%r14), $acc0 + mov $acc1, $t1 + sbb 8*3(%r14), $acc1 + sbb \$0, $acc2 + + cmovc $a_ptr, $acc4 + cmovc $acc3, $acc5 + cmovc $t0, $acc0 + cmovc $t1, $acc1 + + mov $acc4, 8*0($r_ptr) + mov $acc5, 8*1($r_ptr) + mov $acc0, 8*2($r_ptr) + mov $acc1, 8*3($r_ptr) + + mov 0(%rsp),%r15 +.cfi_restore %r15 + mov 8(%rsp),%r14 +.cfi_restore %r14 + mov 16(%rsp),%r13 +.cfi_restore %r13 + mov 24(%rsp),%r12 +.cfi_restore %r12 + mov 32(%rsp),%rbx +.cfi_restore %rbx + mov 40(%rsp),%rbp +.cfi_restore %rbp + lea 48(%rsp),%rsp +.cfi_adjust_cfa_offset -48 +.Lord_mul_epilogue: + ret +.cfi_endproc +.size ecp_nistz256_ord_mul_mont,.-ecp_nistz256_ord_mul_mont + +################################################################################ +# void ecp_nistz256_ord_sqr_mont( +# uint64_t res[4], +# uint64_t a[4], +# int rep); + +.globl ecp_nistz256_ord_sqr_mont +.type ecp_nistz256_ord_sqr_mont,\@function,3 +.align 32 +ecp_nistz256_ord_sqr_mont: +.cfi_startproc +___ +$code.=<<___ if ($addx); + mov \$0x80100, %ecx + and OPENSSL_ia32cap_P+8(%rip), %ecx + cmp \$0x80100, %ecx + je .Lecp_nistz256_ord_sqr_montx +___ +$code.=<<___; + push %rbp +.cfi_push %rbp + push %rbx +.cfi_push %rbx + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +.Lord_sqr_body: + + mov 8*0($a_ptr), $acc0 + mov 8*1($a_ptr), %rax + mov 8*2($a_ptr), $acc6 + mov 8*3($a_ptr), $acc7 + lea .Lord(%rip), $a_ptr # pointer to modulus + mov $b_org, $b_ptr + jmp .Loop_ord_sqr + +.align 32 +.Loop_ord_sqr: + ################################# a[1:] * a[0] + mov %rax, $t1 # put aside a[1] + mul $acc0 # a[1] * a[0] + mov %rax, $acc1 + movq $t1, %xmm1 # offload a[1] + mov $acc6, %rax + mov %rdx, $acc2 + + mul $acc0 # a[2] * a[0] + add %rax, $acc2 + mov $acc7, %rax + movq $acc6, %xmm2 # offload a[2] + adc \$0, %rdx + mov %rdx, $acc3 + + mul $acc0 # a[3] * a[0] + add %rax, $acc3 + mov $acc7, %rax + movq $acc7, %xmm3 # offload a[3] + adc \$0, %rdx + mov %rdx, $acc4 + + ################################# a[3] * a[2] + mul $acc6 # a[3] * a[2] + mov %rax, $acc5 + mov $acc6, %rax + mov %rdx, $acc6 + + ################################# a[2:] * a[1] + mul $t1 # a[2] * a[1] + add %rax, $acc3 + mov $acc7, %rax + adc \$0, %rdx + mov %rdx, $acc7 + + mul $t1 # a[3] * a[1] + add %rax, $acc4 + adc \$0, %rdx + + add $acc7, $acc4 + adc %rdx, $acc5 + adc \$0, $acc6 # can't overflow + + ################################# *2 + xor $acc7, $acc7 + mov $acc0, %rax + add $acc1, $acc1 + adc $acc2, $acc2 + adc $acc3, $acc3 + adc $acc4, $acc4 + adc $acc5, $acc5 + adc $acc6, $acc6 + adc \$0, $acc7 + + ################################# Missing products + mul %rax # a[0] * a[0] + mov %rax, $acc0 + movq %xmm1, %rax + mov %rdx, $t1 + + mul %rax # a[1] * a[1] + add $t1, $acc1 + adc %rax, $acc2 + movq %xmm2, %rax + adc \$0, %rdx + mov %rdx, $t1 + + mul %rax # a[2] * a[2] + add $t1, $acc3 + adc %rax, $acc4 + movq %xmm3, %rax + adc \$0, %rdx + mov %rdx, $t1 + + mov $acc0, $t0 + imulq 8*4($a_ptr), $acc0 # *= .LordK + + mul %rax # a[3] * a[3] + add $t1, $acc5 + adc %rax, $acc6 + mov 8*0($a_ptr), %rax # modulus[0] + adc %rdx, $acc7 # can't overflow + + ################################# First reduction step + mul $acc0 + mov $acc0, $t1 + add %rax, $t0 # guaranteed to be zero + mov 8*1($a_ptr), %rax # modulus[1] + adc %rdx, $t0 + + sub $acc0, $acc2 + sbb \$0, $t1 # can't borrow + + mul $acc0 + add $t0, $acc1 + adc \$0, %rdx + add %rax, $acc1 + mov $acc0, %rax + adc %rdx, $acc2 + mov $acc0, %rdx + adc \$0, $t1 # can't overflow + + mov $acc1, $t0 + imulq 8*4($a_ptr), $acc1 # *= .LordK + + shl \$32, %rax + shr \$32, %rdx + sub %rax, $acc3 + mov 8*0($a_ptr), %rax + sbb %rdx, $acc0 # can't borrow + + add $t1, $acc3 + adc \$0, $acc0 # can't overflow + + ################################# Second reduction step + mul $acc1 + mov $acc1, $t1 + add %rax, $t0 # guaranteed to be zero + mov 8*1($a_ptr), %rax + adc %rdx, $t0 + + sub $acc1, $acc3 + sbb \$0, $t1 # can't borrow + + mul $acc1 + add $t0, $acc2 + adc \$0, %rdx + add %rax, $acc2 + mov $acc1, %rax + adc %rdx, $acc3 + mov $acc1, %rdx + adc \$0, $t1 # can't overflow + + mov $acc2, $t0 + imulq 8*4($a_ptr), $acc2 # *= .LordK + + shl \$32, %rax + shr \$32, %rdx + sub %rax, $acc0 + mov 8*0($a_ptr), %rax + sbb %rdx, $acc1 # can't borrow + + add $t1, $acc0 + adc \$0, $acc1 # can't overflow + + ################################# Third reduction step + mul $acc2 + mov $acc2, $t1 + add %rax, $t0 # guaranteed to be zero + mov 8*1($a_ptr), %rax + adc %rdx, $t0 + + sub $acc2, $acc0 + sbb \$0, $t1 # can't borrow + + mul $acc2 + add $t0, $acc3 + adc \$0, %rdx + add %rax, $acc3 + mov $acc2, %rax + adc %rdx, $acc0 + mov $acc2, %rdx + adc \$0, $t1 # can't overflow + + mov $acc3, $t0 + imulq 8*4($a_ptr), $acc3 # *= .LordK + + shl \$32, %rax + shr \$32, %rdx + sub %rax, $acc1 + mov 8*0($a_ptr), %rax + sbb %rdx, $acc2 # can't borrow + + add $t1, $acc1 + adc \$0, $acc2 # can't overflow + + ################################# Last reduction step + mul $acc3 + mov $acc3, $t1 + add %rax, $t0 # guaranteed to be zero + mov 8*1($a_ptr), %rax + adc %rdx, $t0 + + sub $acc3, $acc1 + sbb \$0, $t1 # can't borrow + + mul $acc3 + add $t0, $acc0 + adc \$0, %rdx + add %rax, $acc0 + mov $acc3, %rax + adc %rdx, $acc1 + mov $acc3, %rdx + adc \$0, $t1 # can't overflow + + shl \$32, %rax + shr \$32, %rdx + sub %rax, $acc2 + sbb %rdx, $acc3 # can't borrow + + add $t1, $acc2 + adc \$0, $acc3 # can't overflow + + ################################# Add bits [511:256] of the sqr result + xor %rdx, %rdx + add $acc4, $acc0 + adc $acc5, $acc1 + mov $acc0, $acc4 + adc $acc6, $acc2 + adc $acc7, $acc3 + mov $acc1, %rax + adc \$0, %rdx + + ################################# Compare to modulus + sub 8*0($a_ptr), $acc0 + mov $acc2, $acc6 + sbb 8*1($a_ptr), $acc1 + sbb 8*2($a_ptr), $acc2 + mov $acc3, $acc7 + sbb 8*3($a_ptr), $acc3 + sbb \$0, %rdx + + cmovc $acc4, $acc0 + cmovnc $acc1, %rax + cmovnc $acc2, $acc6 + cmovnc $acc3, $acc7 + + dec $b_ptr + jnz .Loop_ord_sqr + + mov $acc0, 8*0($r_ptr) + mov %rax, 8*1($r_ptr) + pxor %xmm1, %xmm1 + mov $acc6, 8*2($r_ptr) + pxor %xmm2, %xmm2 + mov $acc7, 8*3($r_ptr) + pxor %xmm3, %xmm3 + + mov 0(%rsp),%r15 +.cfi_restore %r15 + mov 8(%rsp),%r14 +.cfi_restore %r14 + mov 16(%rsp),%r13 +.cfi_restore %r13 + mov 24(%rsp),%r12 +.cfi_restore %r12 + mov 32(%rsp),%rbx +.cfi_restore %rbx + mov 40(%rsp),%rbp +.cfi_restore %rbp + lea 48(%rsp),%rsp +.cfi_adjust_cfa_offset -48 +.Lord_sqr_epilogue: + ret +.cfi_endproc +.size ecp_nistz256_ord_sqr_mont,.-ecp_nistz256_ord_sqr_mont +___ + +$code.=<<___ if ($addx); +################################################################################ +.type ecp_nistz256_ord_mul_montx,\@function,3 +.align 32 +ecp_nistz256_ord_mul_montx: +.cfi_startproc +.Lecp_nistz256_ord_mul_montx: + push %rbp +.cfi_push %rbp + push %rbx +.cfi_push %rbx + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +.Lord_mulx_body: + + mov $b_org, $b_ptr + mov 8*0($b_org), %rdx + mov 8*0($a_ptr), $acc1 + mov 8*1($a_ptr), $acc2 + mov 8*2($a_ptr), $acc3 + mov 8*3($a_ptr), $acc4 + lea -128($a_ptr), $a_ptr # control u-op density + lea .Lord-128(%rip), %r14 + mov .LordK(%rip), %r15 + + ################################# Multiply by b[0] + mulx $acc1, $acc0, $acc1 + mulx $acc2, $t0, $acc2 + mulx $acc3, $t1, $acc3 + add $t0, $acc1 + mulx $acc4, $t0, $acc4 + mov $acc0, %rdx + mulx %r15, %rdx, %rax + adc $t1, $acc2 + adc $t0, $acc3 + adc \$0, $acc4 + + ################################# reduction + xor $acc5, $acc5 # $acc5=0, cf=0, of=0 + mulx 8*0+128(%r14), $t0, $t1 + adcx $t0, $acc0 # guaranteed to be zero + adox $t1, $acc1 + + mulx 8*1+128(%r14), $t0, $t1 + adcx $t0, $acc1 + adox $t1, $acc2 + + mulx 8*2+128(%r14), $t0, $t1 + adcx $t0, $acc2 + adox $t1, $acc3 + + mulx 8*3+128(%r14), $t0, $t1 + mov 8*1($b_ptr), %rdx + adcx $t0, $acc3 + adox $t1, $acc4 + adcx $acc0, $acc4 + adox $acc0, $acc5 + adc \$0, $acc5 # cf=0, of=0 + + ################################# Multiply by b[1] + mulx 8*0+128($a_ptr), $t0, $t1 + adcx $t0, $acc1 + adox $t1, $acc2 + + mulx 8*1+128($a_ptr), $t0, $t1 + adcx $t0, $acc2 + adox $t1, $acc3 + + mulx 8*2+128($a_ptr), $t0, $t1 + adcx $t0, $acc3 + adox $t1, $acc4 + + mulx 8*3+128($a_ptr), $t0, $t1 + mov $acc1, %rdx + mulx %r15, %rdx, %rax + adcx $t0, $acc4 + adox $t1, $acc5 + + adcx $acc0, $acc5 + adox $acc0, $acc0 + adc \$0, $acc0 # cf=0, of=0 + + ################################# reduction + mulx 8*0+128(%r14), $t0, $t1 + adcx $t0, $acc1 # guaranteed to be zero + adox $t1, $acc2 + + mulx 8*1+128(%r14), $t0, $t1 + adcx $t0, $acc2 + adox $t1, $acc3 + + mulx 8*2+128(%r14), $t0, $t1 + adcx $t0, $acc3 + adox $t1, $acc4 + + mulx 8*3+128(%r14), $t0, $t1 + mov 8*2($b_ptr), %rdx + adcx $t0, $acc4 + adox $t1, $acc5 + adcx $acc1, $acc5 + adox $acc1, $acc0 + adc \$0, $acc0 # cf=0, of=0 + + ################################# Multiply by b[2] + mulx 8*0+128($a_ptr), $t0, $t1 + adcx $t0, $acc2 + adox $t1, $acc3 + + mulx 8*1+128($a_ptr), $t0, $t1 + adcx $t0, $acc3 + adox $t1, $acc4 + + mulx 8*2+128($a_ptr), $t0, $t1 + adcx $t0, $acc4 + adox $t1, $acc5 + + mulx 8*3+128($a_ptr), $t0, $t1 + mov $acc2, %rdx + mulx %r15, %rdx, %rax + adcx $t0, $acc5 + adox $t1, $acc0 + + adcx $acc1, $acc0 + adox $acc1, $acc1 + adc \$0, $acc1 # cf=0, of=0 + + ################################# reduction + mulx 8*0+128(%r14), $t0, $t1 + adcx $t0, $acc2 # guaranteed to be zero + adox $t1, $acc3 + + mulx 8*1+128(%r14), $t0, $t1 + adcx $t0, $acc3 + adox $t1, $acc4 + + mulx 8*2+128(%r14), $t0, $t1 + adcx $t0, $acc4 + adox $t1, $acc5 + + mulx 8*3+128(%r14), $t0, $t1 + mov 8*3($b_ptr), %rdx + adcx $t0, $acc5 + adox $t1, $acc0 + adcx $acc2, $acc0 + adox $acc2, $acc1 + adc \$0, $acc1 # cf=0, of=0 + + ################################# Multiply by b[3] + mulx 8*0+128($a_ptr), $t0, $t1 + adcx $t0, $acc3 + adox $t1, $acc4 + + mulx 8*1+128($a_ptr), $t0, $t1 + adcx $t0, $acc4 + adox $t1, $acc5 + + mulx 8*2+128($a_ptr), $t0, $t1 + adcx $t0, $acc5 + adox $t1, $acc0 + + mulx 8*3+128($a_ptr), $t0, $t1 + mov $acc3, %rdx + mulx %r15, %rdx, %rax + adcx $t0, $acc0 + adox $t1, $acc1 + + adcx $acc2, $acc1 + adox $acc2, $acc2 + adc \$0, $acc2 # cf=0, of=0 + + ################################# reduction + mulx 8*0+128(%r14), $t0, $t1 + adcx $t0, $acc3 # guranteed to be zero + adox $t1, $acc4 + + mulx 8*1+128(%r14), $t0, $t1 + adcx $t0, $acc4 + adox $t1, $acc5 + + mulx 8*2+128(%r14), $t0, $t1 + adcx $t0, $acc5 + adox $t1, $acc0 + + mulx 8*3+128(%r14), $t0, $t1 + lea 128(%r14),%r14 + mov $acc4, $t2 + adcx $t0, $acc0 + adox $t1, $acc1 + mov $acc5, $t3 + adcx $acc3, $acc1 + adox $acc3, $acc2 + adc \$0, $acc2 + + ################################# + # Branch-less conditional subtraction of P + mov $acc0, $t0 + sub 8*0(%r14), $acc4 + sbb 8*1(%r14), $acc5 + sbb 8*2(%r14), $acc0 + mov $acc1, $t1 + sbb 8*3(%r14), $acc1 + sbb \$0, $acc2 + + cmovc $t2, $acc4 + cmovc $t3, $acc5 + cmovc $t0, $acc0 + cmovc $t1, $acc1 + + mov $acc4, 8*0($r_ptr) + mov $acc5, 8*1($r_ptr) + mov $acc0, 8*2($r_ptr) + mov $acc1, 8*3($r_ptr) + + mov 0(%rsp),%r15 +.cfi_restore %r15 + mov 8(%rsp),%r14 +.cfi_restore %r14 + mov 16(%rsp),%r13 +.cfi_restore %r13 + mov 24(%rsp),%r12 +.cfi_restore %r12 + mov 32(%rsp),%rbx +.cfi_restore %rbx + mov 40(%rsp),%rbp +.cfi_restore %rbp + lea 48(%rsp),%rsp +.cfi_adjust_cfa_offset -48 +.Lord_mulx_epilogue: + ret +.cfi_endproc +.size ecp_nistz256_ord_mul_montx,.-ecp_nistz256_ord_mul_montx + +.type ecp_nistz256_ord_sqr_montx,\@function,3 +.align 32 +ecp_nistz256_ord_sqr_montx: +.cfi_startproc +.Lecp_nistz256_ord_sqr_montx: + push %rbp +.cfi_push %rbp + push %rbx +.cfi_push %rbx + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +.Lord_sqrx_body: + + mov $b_org, $b_ptr + mov 8*0($a_ptr), %rdx + mov 8*1($a_ptr), $acc6 + mov 8*2($a_ptr), $acc7 + mov 8*3($a_ptr), $acc0 + lea .Lord(%rip), $a_ptr + jmp .Loop_ord_sqrx + +.align 32 +.Loop_ord_sqrx: + mulx $acc6, $acc1, $acc2 # a[0]*a[1] + mulx $acc7, $t0, $acc3 # a[0]*a[2] + mov %rdx, %rax # offload a[0] + movq $acc6, %xmm1 # offload a[1] + mulx $acc0, $t1, $acc4 # a[0]*a[3] + mov $acc6, %rdx + add $t0, $acc2 + movq $acc7, %xmm2 # offload a[2] + adc $t1, $acc3 + adc \$0, $acc4 + xor $acc5, $acc5 # $acc5=0,cf=0,of=0 + ################################# + mulx $acc7, $t0, $t1 # a[1]*a[2] + adcx $t0, $acc3 + adox $t1, $acc4 + + mulx $acc0, $t0, $t1 # a[1]*a[3] + mov $acc7, %rdx + adcx $t0, $acc4 + adox $t1, $acc5 + adc \$0, $acc5 + ################################# + mulx $acc0, $t0, $acc6 # a[2]*a[3] + mov %rax, %rdx + movq $acc0, %xmm3 # offload a[3] + xor $acc7, $acc7 # $acc7=0,cf=0,of=0 + adcx $acc1, $acc1 # acc1:6<<1 + adox $t0, $acc5 + adcx $acc2, $acc2 + adox $acc7, $acc6 # of=0 + + ################################# a[i]*a[i] + mulx %rdx, $acc0, $t1 + movq %xmm1, %rdx + adcx $acc3, $acc3 + adox $t1, $acc1 + adcx $acc4, $acc4 + mulx %rdx, $t0, $t4 + movq %xmm2, %rdx + adcx $acc5, $acc5 + adox $t0, $acc2 + adcx $acc6, $acc6 + mulx %rdx, $t0, $t1 + .byte 0x67 + movq %xmm3, %rdx + adox $t4, $acc3 + adcx $acc7, $acc7 + adox $t0, $acc4 + adox $t1, $acc5 + mulx %rdx, $t0, $t4 + adox $t0, $acc6 + adox $t4, $acc7 + + ################################# reduction + mov $acc0, %rdx + mulx 8*4($a_ptr), %rdx, $t0 + + xor %rax, %rax # cf=0, of=0 + mulx 8*0($a_ptr), $t0, $t1 + adcx $t0, $acc0 # guaranteed to be zero + adox $t1, $acc1 + mulx 8*1($a_ptr), $t0, $t1 + adcx $t0, $acc1 + adox $t1, $acc2 + mulx 8*2($a_ptr), $t0, $t1 + adcx $t0, $acc2 + adox $t1, $acc3 + mulx 8*3($a_ptr), $t0, $t1 + adcx $t0, $acc3 + adox $t1, $acc0 # of=0 + adcx %rax, $acc0 # cf=0 + + ################################# + mov $acc1, %rdx + mulx 8*4($a_ptr), %rdx, $t0 + + mulx 8*0($a_ptr), $t0, $t1 + adox $t0, $acc1 # guaranteed to be zero + adcx $t1, $acc2 + mulx 8*1($a_ptr), $t0, $t1 + adox $t0, $acc2 + adcx $t1, $acc3 + mulx 8*2($a_ptr), $t0, $t1 + adox $t0, $acc3 + adcx $t1, $acc0 + mulx 8*3($a_ptr), $t0, $t1 + adox $t0, $acc0 + adcx $t1, $acc1 # cf=0 + adox %rax, $acc1 # of=0 + + ################################# + mov $acc2, %rdx + mulx 8*4($a_ptr), %rdx, $t0 + + mulx 8*0($a_ptr), $t0, $t1 + adcx $t0, $acc2 # guaranteed to be zero + adox $t1, $acc3 + mulx 8*1($a_ptr), $t0, $t1 + adcx $t0, $acc3 + adox $t1, $acc0 + mulx 8*2($a_ptr), $t0, $t1 + adcx $t0, $acc0 + adox $t1, $acc1 + mulx 8*3($a_ptr), $t0, $t1 + adcx $t0, $acc1 + adox $t1, $acc2 # of=0 + adcx %rax, $acc2 # cf=0 + + ################################# + mov $acc3, %rdx + mulx 8*4($a_ptr), %rdx, $t0 + + mulx 8*0($a_ptr), $t0, $t1 + adox $t0, $acc3 # guaranteed to be zero + adcx $t1, $acc0 + mulx 8*1($a_ptr), $t0, $t1 + adox $t0, $acc0 + adcx $t1, $acc1 + mulx 8*2($a_ptr), $t0, $t1 + adox $t0, $acc1 + adcx $t1, $acc2 + mulx 8*3($a_ptr), $t0, $t1 + adox $t0, $acc2 + adcx $t1, $acc3 + adox %rax, $acc3 + + ################################# accumulate upper half + add $acc0, $acc4 # add $acc4, $acc0 + adc $acc5, $acc1 + mov $acc4, %rdx + adc $acc6, $acc2 + adc $acc7, $acc3 + mov $acc1, $acc6 + adc \$0, %rax + + ################################# compare to modulus + sub 8*0($a_ptr), $acc4 + mov $acc2, $acc7 + sbb 8*1($a_ptr), $acc1 + sbb 8*2($a_ptr), $acc2 + mov $acc3, $acc0 + sbb 8*3($a_ptr), $acc3 + sbb \$0, %rax + + cmovnc $acc4, %rdx + cmovnc $acc1, $acc6 + cmovnc $acc2, $acc7 + cmovnc $acc3, $acc0 + + dec $b_ptr + jnz .Loop_ord_sqrx + + mov %rdx, 8*0($r_ptr) + mov $acc6, 8*1($r_ptr) + pxor %xmm1, %xmm1 + mov $acc7, 8*2($r_ptr) + pxor %xmm2, %xmm2 + mov $acc0, 8*3($r_ptr) + pxor %xmm3, %xmm3 + + mov 0(%rsp),%r15 +.cfi_restore %r15 + mov 8(%rsp),%r14 +.cfi_restore %r14 + mov 16(%rsp),%r13 +.cfi_restore %r13 + mov 24(%rsp),%r12 +.cfi_restore %r12 + mov 32(%rsp),%rbx +.cfi_restore %rbx + mov 40(%rsp),%rbp +.cfi_restore %rbp + lea 48(%rsp),%rsp +.cfi_adjust_cfa_offset -48 +.Lord_sqrx_epilogue: + ret +.cfi_endproc +.size ecp_nistz256_ord_sqr_montx,.-ecp_nistz256_ord_sqr_montx +___ + +$code.=<<___; +################################################################################ +# void ecp_nistz256_to_mont( +# uint64_t res[4], +# uint64_t in[4]); +.globl ecp_nistz256_to_mont +.type ecp_nistz256_to_mont,\@function,2 +.align 32 +ecp_nistz256_to_mont: +___ +$code.=<<___ if ($addx); + mov \$0x80100, %ecx + and OPENSSL_ia32cap_P+8(%rip), %ecx +___ +$code.=<<___; + lea .LRR(%rip), $b_org + jmp .Lmul_mont +.size ecp_nistz256_to_mont,.-ecp_nistz256_to_mont + +################################################################################ +# void ecp_nistz256_mul_mont( +# uint64_t res[4], +# uint64_t a[4], +# uint64_t b[4]); + +.globl ecp_nistz256_mul_mont +.type ecp_nistz256_mul_mont,\@function,3 +.align 32 +ecp_nistz256_mul_mont: +.cfi_startproc +___ +$code.=<<___ if ($addx); + mov \$0x80100, %ecx + and OPENSSL_ia32cap_P+8(%rip), %ecx +___ +$code.=<<___; +.Lmul_mont: + push %rbp +.cfi_push %rbp + push %rbx +.cfi_push %rbx + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +.Lmul_body: +___ +$code.=<<___ if ($addx); + cmp \$0x80100, %ecx + je .Lmul_montx +___ +$code.=<<___; + mov $b_org, $b_ptr + mov 8*0($b_org), %rax + mov 8*0($a_ptr), $acc1 + mov 8*1($a_ptr), $acc2 + mov 8*2($a_ptr), $acc3 + mov 8*3($a_ptr), $acc4 + + call __ecp_nistz256_mul_montq +___ +$code.=<<___ if ($addx); + jmp .Lmul_mont_done + +.align 32 +.Lmul_montx: + mov $b_org, $b_ptr + mov 8*0($b_org), %rdx + mov 8*0($a_ptr), $acc1 + mov 8*1($a_ptr), $acc2 + mov 8*2($a_ptr), $acc3 + mov 8*3($a_ptr), $acc4 + lea -128($a_ptr), $a_ptr # control u-op density + + call __ecp_nistz256_mul_montx +___ +$code.=<<___; +.Lmul_mont_done: + mov 0(%rsp),%r15 +.cfi_restore %r15 + mov 8(%rsp),%r14 +.cfi_restore %r14 + mov 16(%rsp),%r13 +.cfi_restore %r13 + mov 24(%rsp),%r12 +.cfi_restore %r12 + mov 32(%rsp),%rbx +.cfi_restore %rbx + mov 40(%rsp),%rbp +.cfi_restore %rbp + lea 48(%rsp),%rsp +.cfi_adjust_cfa_offset -48 +.Lmul_epilogue: + ret +.cfi_endproc +.size ecp_nistz256_mul_mont,.-ecp_nistz256_mul_mont + +.type __ecp_nistz256_mul_montq,\@abi-omnipotent +.align 32 +__ecp_nistz256_mul_montq: +.cfi_startproc + ######################################################################## + # Multiply a by b[0] + mov %rax, $t1 + mulq $acc1 + mov .Lpoly+8*1(%rip),$poly1 + mov %rax, $acc0 + mov $t1, %rax + mov %rdx, $acc1 + + mulq $acc2 + mov .Lpoly+8*3(%rip),$poly3 + add %rax, $acc1 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $acc2 + + mulq $acc3 + add %rax, $acc2 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $acc3 + + mulq $acc4 + add %rax, $acc3 + mov $acc0, %rax + adc \$0, %rdx + xor $acc5, $acc5 + mov %rdx, $acc4 + + ######################################################################## + # First reduction step + # Basically now we want to multiply acc[0] by p256, + # and add the result to the acc. + # Due to the special form of p256 we do some optimizations + # + # acc[0] x p256[0..1] = acc[0] x 2^96 - acc[0] + # then we add acc[0] and get acc[0] x 2^96 + + mov $acc0, $t1 + shl \$32, $acc0 + mulq $poly3 + shr \$32, $t1 + add $acc0, $acc1 # +=acc[0]<<96 + adc $t1, $acc2 + adc %rax, $acc3 + mov 8*1($b_ptr), %rax + adc %rdx, $acc4 + adc \$0, $acc5 + xor $acc0, $acc0 + + ######################################################################## + # Multiply by b[1] + mov %rax, $t1 + mulq 8*0($a_ptr) + add %rax, $acc1 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq 8*1($a_ptr) + add $t0, $acc2 + adc \$0, %rdx + add %rax, $acc2 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq 8*2($a_ptr) + add $t0, $acc3 + adc \$0, %rdx + add %rax, $acc3 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq 8*3($a_ptr) + add $t0, $acc4 + adc \$0, %rdx + add %rax, $acc4 + mov $acc1, %rax + adc %rdx, $acc5 + adc \$0, $acc0 + + ######################################################################## + # Second reduction step + mov $acc1, $t1 + shl \$32, $acc1 + mulq $poly3 + shr \$32, $t1 + add $acc1, $acc2 + adc $t1, $acc3 + adc %rax, $acc4 + mov 8*2($b_ptr), %rax + adc %rdx, $acc5 + adc \$0, $acc0 + xor $acc1, $acc1 + + ######################################################################## + # Multiply by b[2] + mov %rax, $t1 + mulq 8*0($a_ptr) + add %rax, $acc2 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq 8*1($a_ptr) + add $t0, $acc3 + adc \$0, %rdx + add %rax, $acc3 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq 8*2($a_ptr) + add $t0, $acc4 + adc \$0, %rdx + add %rax, $acc4 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq 8*3($a_ptr) + add $t0, $acc5 + adc \$0, %rdx + add %rax, $acc5 + mov $acc2, %rax + adc %rdx, $acc0 + adc \$0, $acc1 + + ######################################################################## + # Third reduction step + mov $acc2, $t1 + shl \$32, $acc2 + mulq $poly3 + shr \$32, $t1 + add $acc2, $acc3 + adc $t1, $acc4 + adc %rax, $acc5 + mov 8*3($b_ptr), %rax + adc %rdx, $acc0 + adc \$0, $acc1 + xor $acc2, $acc2 + + ######################################################################## + # Multiply by b[3] + mov %rax, $t1 + mulq 8*0($a_ptr) + add %rax, $acc3 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq 8*1($a_ptr) + add $t0, $acc4 + adc \$0, %rdx + add %rax, $acc4 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq 8*2($a_ptr) + add $t0, $acc5 + adc \$0, %rdx + add %rax, $acc5 + mov $t1, %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq 8*3($a_ptr) + add $t0, $acc0 + adc \$0, %rdx + add %rax, $acc0 + mov $acc3, %rax + adc %rdx, $acc1 + adc \$0, $acc2 + + ######################################################################## + # Final reduction step + mov $acc3, $t1 + shl \$32, $acc3 + mulq $poly3 + shr \$32, $t1 + add $acc3, $acc4 + adc $t1, $acc5 + mov $acc4, $t0 + adc %rax, $acc0 + adc %rdx, $acc1 + mov $acc5, $t1 + adc \$0, $acc2 + + ######################################################################## + # Branch-less conditional subtraction of P + sub \$-1, $acc4 # .Lpoly[0] + mov $acc0, $t2 + sbb $poly1, $acc5 # .Lpoly[1] + sbb \$0, $acc0 # .Lpoly[2] + mov $acc1, $t3 + sbb $poly3, $acc1 # .Lpoly[3] + sbb \$0, $acc2 + + cmovc $t0, $acc4 + cmovc $t1, $acc5 + mov $acc4, 8*0($r_ptr) + cmovc $t2, $acc0 + mov $acc5, 8*1($r_ptr) + cmovc $t3, $acc1 + mov $acc0, 8*2($r_ptr) + mov $acc1, 8*3($r_ptr) + + ret +.cfi_endproc +.size __ecp_nistz256_mul_montq,.-__ecp_nistz256_mul_montq + +################################################################################ +# void ecp_nistz256_sqr_mont( +# uint64_t res[4], +# uint64_t a[4]); + +# we optimize the square according to S.Gueron and V.Krasnov, +# "Speeding up Big-Number Squaring" +.globl ecp_nistz256_sqr_mont +.type ecp_nistz256_sqr_mont,\@function,2 +.align 32 +ecp_nistz256_sqr_mont: +.cfi_startproc +___ +$code.=<<___ if ($addx); + mov \$0x80100, %ecx + and OPENSSL_ia32cap_P+8(%rip), %ecx +___ +$code.=<<___; + push %rbp +.cfi_push %rbp + push %rbx +.cfi_push %rbx + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +.Lsqr_body: +___ +$code.=<<___ if ($addx); + cmp \$0x80100, %ecx + je .Lsqr_montx +___ +$code.=<<___; + mov 8*0($a_ptr), %rax + mov 8*1($a_ptr), $acc6 + mov 8*2($a_ptr), $acc7 + mov 8*3($a_ptr), $acc0 + + call __ecp_nistz256_sqr_montq +___ +$code.=<<___ if ($addx); + jmp .Lsqr_mont_done + +.align 32 +.Lsqr_montx: + mov 8*0($a_ptr), %rdx + mov 8*1($a_ptr), $acc6 + mov 8*2($a_ptr), $acc7 + mov 8*3($a_ptr), $acc0 + lea -128($a_ptr), $a_ptr # control u-op density + + call __ecp_nistz256_sqr_montx +___ +$code.=<<___; +.Lsqr_mont_done: + mov 0(%rsp),%r15 +.cfi_restore %r15 + mov 8(%rsp),%r14 +.cfi_restore %r14 + mov 16(%rsp),%r13 +.cfi_restore %r13 + mov 24(%rsp),%r12 +.cfi_restore %r12 + mov 32(%rsp),%rbx +.cfi_restore %rbx + mov 40(%rsp),%rbp +.cfi_restore %rbp + lea 48(%rsp),%rsp +.cfi_adjust_cfa_offset -48 +.Lsqr_epilogue: + ret +.cfi_endproc +.size ecp_nistz256_sqr_mont,.-ecp_nistz256_sqr_mont + +.type __ecp_nistz256_sqr_montq,\@abi-omnipotent +.align 32 +__ecp_nistz256_sqr_montq: +.cfi_startproc + mov %rax, $acc5 + mulq $acc6 # a[1]*a[0] + mov %rax, $acc1 + mov $acc7, %rax + mov %rdx, $acc2 + + mulq $acc5 # a[0]*a[2] + add %rax, $acc2 + mov $acc0, %rax + adc \$0, %rdx + mov %rdx, $acc3 + + mulq $acc5 # a[0]*a[3] + add %rax, $acc3 + mov $acc7, %rax + adc \$0, %rdx + mov %rdx, $acc4 + + ################################# + mulq $acc6 # a[1]*a[2] + add %rax, $acc3 + mov $acc0, %rax + adc \$0, %rdx + mov %rdx, $t1 + + mulq $acc6 # a[1]*a[3] + add %rax, $acc4 + mov $acc0, %rax + adc \$0, %rdx + add $t1, $acc4 + mov %rdx, $acc5 + adc \$0, $acc5 + + ################################# + mulq $acc7 # a[2]*a[3] + xor $acc7, $acc7 + add %rax, $acc5 + mov 8*0($a_ptr), %rax + mov %rdx, $acc6 + adc \$0, $acc6 + + add $acc1, $acc1 # acc1:6<<1 + adc $acc2, $acc2 + adc $acc3, $acc3 + adc $acc4, $acc4 + adc $acc5, $acc5 + adc $acc6, $acc6 + adc \$0, $acc7 + + mulq %rax + mov %rax, $acc0 + mov 8*1($a_ptr), %rax + mov %rdx, $t0 + + mulq %rax + add $t0, $acc1 + adc %rax, $acc2 + mov 8*2($a_ptr), %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq %rax + add $t0, $acc3 + adc %rax, $acc4 + mov 8*3($a_ptr), %rax + adc \$0, %rdx + mov %rdx, $t0 + + mulq %rax + add $t0, $acc5 + adc %rax, $acc6 + mov $acc0, %rax + adc %rdx, $acc7 + + mov .Lpoly+8*1(%rip), $a_ptr + mov .Lpoly+8*3(%rip), $t1 + + ########################################## + # Now the reduction + # First iteration + mov $acc0, $t0 + shl \$32, $acc0 + mulq $t1 + shr \$32, $t0 + add $acc0, $acc1 # +=acc[0]<<96 + adc $t0, $acc2 + adc %rax, $acc3 + mov $acc1, %rax + adc \$0, %rdx + + ########################################## + # Second iteration + mov $acc1, $t0 + shl \$32, $acc1 + mov %rdx, $acc0 + mulq $t1 + shr \$32, $t0 + add $acc1, $acc2 + adc $t0, $acc3 + adc %rax, $acc0 + mov $acc2, %rax + adc \$0, %rdx + + ########################################## + # Third iteration + mov $acc2, $t0 + shl \$32, $acc2 + mov %rdx, $acc1 + mulq $t1 + shr \$32, $t0 + add $acc2, $acc3 + adc $t0, $acc0 + adc %rax, $acc1 + mov $acc3, %rax + adc \$0, %rdx + + ########################################### + # Last iteration + mov $acc3, $t0 + shl \$32, $acc3 + mov %rdx, $acc2 + mulq $t1 + shr \$32, $t0 + add $acc3, $acc0 + adc $t0, $acc1 + adc %rax, $acc2 + adc \$0, %rdx + xor $acc3, $acc3 + + ############################################ + # Add the rest of the acc + add $acc0, $acc4 + adc $acc1, $acc5 + mov $acc4, $acc0 + adc $acc2, $acc6 + adc %rdx, $acc7 + mov $acc5, $acc1 + adc \$0, $acc3 + + sub \$-1, $acc4 # .Lpoly[0] + mov $acc6, $acc2 + sbb $a_ptr, $acc5 # .Lpoly[1] + sbb \$0, $acc6 # .Lpoly[2] + mov $acc7, $t0 + sbb $t1, $acc7 # .Lpoly[3] + sbb \$0, $acc3 + + cmovc $acc0, $acc4 + cmovc $acc1, $acc5 + mov $acc4, 8*0($r_ptr) + cmovc $acc2, $acc6 + mov $acc5, 8*1($r_ptr) + cmovc $t0, $acc7 + mov $acc6, 8*2($r_ptr) + mov $acc7, 8*3($r_ptr) + + ret +.cfi_endproc +.size __ecp_nistz256_sqr_montq,.-__ecp_nistz256_sqr_montq +___ + +if ($addx) { +$code.=<<___; +.type __ecp_nistz256_mul_montx,\@abi-omnipotent +.align 32 +__ecp_nistz256_mul_montx: +.cfi_startproc + ######################################################################## + # Multiply by b[0] + mulx $acc1, $acc0, $acc1 + mulx $acc2, $t0, $acc2 + mov \$32, $poly1 + xor $acc5, $acc5 # cf=0 + mulx $acc3, $t1, $acc3 + mov .Lpoly+8*3(%rip), $poly3 + adc $t0, $acc1 + mulx $acc4, $t0, $acc4 + mov $acc0, %rdx + adc $t1, $acc2 + shlx $poly1,$acc0,$t1 + adc $t0, $acc3 + shrx $poly1,$acc0,$t0 + adc \$0, $acc4 + + ######################################################################## + # First reduction step + add $t1, $acc1 + adc $t0, $acc2 + + mulx $poly3, $t0, $t1 + mov 8*1($b_ptr), %rdx + adc $t0, $acc3 + adc $t1, $acc4 + adc \$0, $acc5 + xor $acc0, $acc0 # $acc0=0,cf=0,of=0 + + ######################################################################## + # Multiply by b[1] + mulx 8*0+128($a_ptr), $t0, $t1 + adcx $t0, $acc1 + adox $t1, $acc2 + + mulx 8*1+128($a_ptr), $t0, $t1 + adcx $t0, $acc2 + adox $t1, $acc3 + + mulx 8*2+128($a_ptr), $t0, $t1 + adcx $t0, $acc3 + adox $t1, $acc4 + + mulx 8*3+128($a_ptr), $t0, $t1 + mov $acc1, %rdx + adcx $t0, $acc4 + shlx $poly1, $acc1, $t0 + adox $t1, $acc5 + shrx $poly1, $acc1, $t1 + + adcx $acc0, $acc5 + adox $acc0, $acc0 + adc \$0, $acc0 + + ######################################################################## + # Second reduction step + add $t0, $acc2 + adc $t1, $acc3 + + mulx $poly3, $t0, $t1 + mov 8*2($b_ptr), %rdx + adc $t0, $acc4 + adc $t1, $acc5 + adc \$0, $acc0 + xor $acc1 ,$acc1 # $acc1=0,cf=0,of=0 + + ######################################################################## + # Multiply by b[2] + mulx 8*0+128($a_ptr), $t0, $t1 + adcx $t0, $acc2 + adox $t1, $acc3 + + mulx 8*1+128($a_ptr), $t0, $t1 + adcx $t0, $acc3 + adox $t1, $acc4 + + mulx 8*2+128($a_ptr), $t0, $t1 + adcx $t0, $acc4 + adox $t1, $acc5 + + mulx 8*3+128($a_ptr), $t0, $t1 + mov $acc2, %rdx + adcx $t0, $acc5 + shlx $poly1, $acc2, $t0 + adox $t1, $acc0 + shrx $poly1, $acc2, $t1 + + adcx $acc1, $acc0 + adox $acc1, $acc1 + adc \$0, $acc1 + + ######################################################################## + # Third reduction step + add $t0, $acc3 + adc $t1, $acc4 + + mulx $poly3, $t0, $t1 + mov 8*3($b_ptr), %rdx + adc $t0, $acc5 + adc $t1, $acc0 + adc \$0, $acc1 + xor $acc2, $acc2 # $acc2=0,cf=0,of=0 + + ######################################################################## + # Multiply by b[3] + mulx 8*0+128($a_ptr), $t0, $t1 + adcx $t0, $acc3 + adox $t1, $acc4 + + mulx 8*1+128($a_ptr), $t0, $t1 + adcx $t0, $acc4 + adox $t1, $acc5 + + mulx 8*2+128($a_ptr), $t0, $t1 + adcx $t0, $acc5 + adox $t1, $acc0 + + mulx 8*3+128($a_ptr), $t0, $t1 + mov $acc3, %rdx + adcx $t0, $acc0 + shlx $poly1, $acc3, $t0 + adox $t1, $acc1 + shrx $poly1, $acc3, $t1 + + adcx $acc2, $acc1 + adox $acc2, $acc2 + adc \$0, $acc2 + + ######################################################################## + # Fourth reduction step + add $t0, $acc4 + adc $t1, $acc5 + + mulx $poly3, $t0, $t1 + mov $acc4, $t2 + mov .Lpoly+8*1(%rip), $poly1 + adc $t0, $acc0 + mov $acc5, $t3 + adc $t1, $acc1 + adc \$0, $acc2 + + ######################################################################## + # Branch-less conditional subtraction of P + xor %eax, %eax + mov $acc0, $t0 + sbb \$-1, $acc4 # .Lpoly[0] + sbb $poly1, $acc5 # .Lpoly[1] + sbb \$0, $acc0 # .Lpoly[2] + mov $acc1, $t1 + sbb $poly3, $acc1 # .Lpoly[3] + sbb \$0, $acc2 + + cmovc $t2, $acc4 + cmovc $t3, $acc5 + mov $acc4, 8*0($r_ptr) + cmovc $t0, $acc0 + mov $acc5, 8*1($r_ptr) + cmovc $t1, $acc1 + mov $acc0, 8*2($r_ptr) + mov $acc1, 8*3($r_ptr) + + ret +.cfi_endproc +.size __ecp_nistz256_mul_montx,.-__ecp_nistz256_mul_montx + +.type __ecp_nistz256_sqr_montx,\@abi-omnipotent +.align 32 +__ecp_nistz256_sqr_montx: +.cfi_startproc + mulx $acc6, $acc1, $acc2 # a[0]*a[1] + mulx $acc7, $t0, $acc3 # a[0]*a[2] + xor %eax, %eax + adc $t0, $acc2 + mulx $acc0, $t1, $acc4 # a[0]*a[3] + mov $acc6, %rdx + adc $t1, $acc3 + adc \$0, $acc4 + xor $acc5, $acc5 # $acc5=0,cf=0,of=0 + + ################################# + mulx $acc7, $t0, $t1 # a[1]*a[2] + adcx $t0, $acc3 + adox $t1, $acc4 + + mulx $acc0, $t0, $t1 # a[1]*a[3] + mov $acc7, %rdx + adcx $t0, $acc4 + adox $t1, $acc5 + adc \$0, $acc5 + + ################################# + mulx $acc0, $t0, $acc6 # a[2]*a[3] + mov 8*0+128($a_ptr), %rdx + xor $acc7, $acc7 # $acc7=0,cf=0,of=0 + adcx $acc1, $acc1 # acc1:6<<1 + adox $t0, $acc5 + adcx $acc2, $acc2 + adox $acc7, $acc6 # of=0 + + mulx %rdx, $acc0, $t1 + mov 8*1+128($a_ptr), %rdx + adcx $acc3, $acc3 + adox $t1, $acc1 + adcx $acc4, $acc4 + mulx %rdx, $t0, $t4 + mov 8*2+128($a_ptr), %rdx + adcx $acc5, $acc5 + adox $t0, $acc2 + adcx $acc6, $acc6 + .byte 0x67 + mulx %rdx, $t0, $t1 + mov 8*3+128($a_ptr), %rdx + adox $t4, $acc3 + adcx $acc7, $acc7 + adox $t0, $acc4 + mov \$32, $a_ptr + adox $t1, $acc5 + .byte 0x67,0x67 + mulx %rdx, $t0, $t4 + mov .Lpoly+8*3(%rip), %rdx + adox $t0, $acc6 + shlx $a_ptr, $acc0, $t0 + adox $t4, $acc7 + shrx $a_ptr, $acc0, $t4 + mov %rdx,$t1 + + # reduction step 1 + add $t0, $acc1 + adc $t4, $acc2 + + mulx $acc0, $t0, $acc0 + adc $t0, $acc3 + shlx $a_ptr, $acc1, $t0 + adc \$0, $acc0 + shrx $a_ptr, $acc1, $t4 + + # reduction step 2 + add $t0, $acc2 + adc $t4, $acc3 + + mulx $acc1, $t0, $acc1 + adc $t0, $acc0 + shlx $a_ptr, $acc2, $t0 + adc \$0, $acc1 + shrx $a_ptr, $acc2, $t4 + + # reduction step 3 + add $t0, $acc3 + adc $t4, $acc0 + + mulx $acc2, $t0, $acc2 + adc $t0, $acc1 + shlx $a_ptr, $acc3, $t0 + adc \$0, $acc2 + shrx $a_ptr, $acc3, $t4 + + # reduction step 4 + add $t0, $acc0 + adc $t4, $acc1 + + mulx $acc3, $t0, $acc3 + adc $t0, $acc2 + adc \$0, $acc3 + + xor $t3, $t3 + add $acc0, $acc4 # accumulate upper half + mov .Lpoly+8*1(%rip), $a_ptr + adc $acc1, $acc5 + mov $acc4, $acc0 + adc $acc2, $acc6 + adc $acc3, $acc7 + mov $acc5, $acc1 + adc \$0, $t3 + + sub \$-1, $acc4 # .Lpoly[0] + mov $acc6, $acc2 + sbb $a_ptr, $acc5 # .Lpoly[1] + sbb \$0, $acc6 # .Lpoly[2] + mov $acc7, $acc3 + sbb $t1, $acc7 # .Lpoly[3] + sbb \$0, $t3 + + cmovc $acc0, $acc4 + cmovc $acc1, $acc5 + mov $acc4, 8*0($r_ptr) + cmovc $acc2, $acc6 + mov $acc5, 8*1($r_ptr) + cmovc $acc3, $acc7 + mov $acc6, 8*2($r_ptr) + mov $acc7, 8*3($r_ptr) + + ret +.cfi_endproc +.size __ecp_nistz256_sqr_montx,.-__ecp_nistz256_sqr_montx +___ +} +} +{ +my ($r_ptr,$in_ptr)=("%rdi","%rsi"); +my ($acc0,$acc1,$acc2,$acc3)=map("%r$_",(8..11)); +my ($t0,$t1,$t2)=("%rcx","%r12","%r13"); + +$code.=<<___; +################################################################################ +# void ecp_nistz256_from_mont( +# uint64_t res[4], +# uint64_t in[4]); +# This one performs Montgomery multiplication by 1, so we only need the reduction + +.globl ecp_nistz256_from_mont +.type ecp_nistz256_from_mont,\@function,2 +.align 32 +ecp_nistz256_from_mont: +.cfi_startproc + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 +.Lfrom_body: + + mov 8*0($in_ptr), %rax + mov .Lpoly+8*3(%rip), $t2 + mov 8*1($in_ptr), $acc1 + mov 8*2($in_ptr), $acc2 + mov 8*3($in_ptr), $acc3 + mov %rax, $acc0 + mov .Lpoly+8*1(%rip), $t1 + + ######################################### + # First iteration + mov %rax, $t0 + shl \$32, $acc0 + mulq $t2 + shr \$32, $t0 + add $acc0, $acc1 + adc $t0, $acc2 + adc %rax, $acc3 + mov $acc1, %rax + adc \$0, %rdx + + ######################################### + # Second iteration + mov $acc1, $t0 + shl \$32, $acc1 + mov %rdx, $acc0 + mulq $t2 + shr \$32, $t0 + add $acc1, $acc2 + adc $t0, $acc3 + adc %rax, $acc0 + mov $acc2, %rax + adc \$0, %rdx + + ########################################## + # Third iteration + mov $acc2, $t0 + shl \$32, $acc2 + mov %rdx, $acc1 + mulq $t2 + shr \$32, $t0 + add $acc2, $acc3 + adc $t0, $acc0 + adc %rax, $acc1 + mov $acc3, %rax + adc \$0, %rdx + + ########################################### + # Last iteration + mov $acc3, $t0 + shl \$32, $acc3 + mov %rdx, $acc2 + mulq $t2 + shr \$32, $t0 + add $acc3, $acc0 + adc $t0, $acc1 + mov $acc0, $t0 + adc %rax, $acc2 + mov $acc1, $in_ptr + adc \$0, %rdx + + ########################################### + # Branch-less conditional subtraction + sub \$-1, $acc0 + mov $acc2, %rax + sbb $t1, $acc1 + sbb \$0, $acc2 + mov %rdx, $acc3 + sbb $t2, %rdx + sbb $t2, $t2 + + cmovnz $t0, $acc0 + cmovnz $in_ptr, $acc1 + mov $acc0, 8*0($r_ptr) + cmovnz %rax, $acc2 + mov $acc1, 8*1($r_ptr) + cmovz %rdx, $acc3 + mov $acc2, 8*2($r_ptr) + mov $acc3, 8*3($r_ptr) + + mov 0(%rsp),%r13 +.cfi_restore %r13 + mov 8(%rsp),%r12 +.cfi_restore %r12 + lea 16(%rsp),%rsp +.cfi_adjust_cfa_offset -16 +.Lfrom_epilogue: + ret +.cfi_endproc +.size ecp_nistz256_from_mont,.-ecp_nistz256_from_mont +___ +} +{ +my ($val,$in_t,$index)=$win64?("%rcx","%rdx","%r8d"):("%rdi","%rsi","%edx"); +my ($ONE,$INDEX,$Ra,$Rb,$Rc,$Rd,$Re,$Rf)=map("%xmm$_",(0..7)); +my ($M0,$T0a,$T0b,$T0c,$T0d,$T0e,$T0f,$TMP0)=map("%xmm$_",(8..15)); +my ($M1,$T2a,$T2b,$TMP2,$M2,$T2a,$T2b,$TMP2)=map("%xmm$_",(8..15)); + +$code.=<<___; +################################################################################ +# void ecp_nistz256_scatter_w5(uint64_t *val, uint64_t *in_t, int index); +.globl ecp_nistz256_scatter_w5 +.type ecp_nistz256_scatter_w5,\@abi-omnipotent +.align 32 +ecp_nistz256_scatter_w5: + lea -3($index,$index,2), $index + movdqa 0x00($in_t), %xmm0 + shl \$5, $index + movdqa 0x10($in_t), %xmm1 + movdqa 0x20($in_t), %xmm2 + movdqa 0x30($in_t), %xmm3 + movdqa 0x40($in_t), %xmm4 + movdqa 0x50($in_t), %xmm5 + movdqa %xmm0, 0x00($val,$index) + movdqa %xmm1, 0x10($val,$index) + movdqa %xmm2, 0x20($val,$index) + movdqa %xmm3, 0x30($val,$index) + movdqa %xmm4, 0x40($val,$index) + movdqa %xmm5, 0x50($val,$index) + + ret +.size ecp_nistz256_scatter_w5,.-ecp_nistz256_scatter_w5 + +################################################################################ +# void ecp_nistz256_gather_w5(uint64_t *val, uint64_t *in_t, int index); +.globl ecp_nistz256_gather_w5 +.type ecp_nistz256_gather_w5,\@abi-omnipotent +.align 32 +ecp_nistz256_gather_w5: +.cfi_startproc +___ +$code.=<<___ if ($avx>1); + mov OPENSSL_ia32cap_P+8(%rip), %eax + test \$`1<<5`, %eax + jnz .Lavx2_gather_w5 +___ +$code.=<<___ if ($win64); + lea -0x88(%rsp), %rax +.LSEH_begin_ecp_nistz256_gather_w5: + .byte 0x48,0x8d,0x60,0xe0 #lea -0x20(%rax), %rsp + .byte 0x0f,0x29,0x70,0xe0 #movaps %xmm6, -0x20(%rax) + .byte 0x0f,0x29,0x78,0xf0 #movaps %xmm7, -0x10(%rax) + .byte 0x44,0x0f,0x29,0x00 #movaps %xmm8, 0(%rax) + .byte 0x44,0x0f,0x29,0x48,0x10 #movaps %xmm9, 0x10(%rax) + .byte 0x44,0x0f,0x29,0x50,0x20 #movaps %xmm10, 0x20(%rax) + .byte 0x44,0x0f,0x29,0x58,0x30 #movaps %xmm11, 0x30(%rax) + .byte 0x44,0x0f,0x29,0x60,0x40 #movaps %xmm12, 0x40(%rax) + .byte 0x44,0x0f,0x29,0x68,0x50 #movaps %xmm13, 0x50(%rax) + .byte 0x44,0x0f,0x29,0x70,0x60 #movaps %xmm14, 0x60(%rax) + .byte 0x44,0x0f,0x29,0x78,0x70 #movaps %xmm15, 0x70(%rax) +___ +$code.=<<___; + movdqa .LOne(%rip), $ONE + movd $index, $INDEX + + pxor $Ra, $Ra + pxor $Rb, $Rb + pxor $Rc, $Rc + pxor $Rd, $Rd + pxor $Re, $Re + pxor $Rf, $Rf + + movdqa $ONE, $M0 + pshufd \$0, $INDEX, $INDEX + + mov \$16, %rax +.Lselect_loop_sse_w5: + + movdqa $M0, $TMP0 + paddd $ONE, $M0 + pcmpeqd $INDEX, $TMP0 + + movdqa 16*0($in_t), $T0a + movdqa 16*1($in_t), $T0b + movdqa 16*2($in_t), $T0c + movdqa 16*3($in_t), $T0d + movdqa 16*4($in_t), $T0e + movdqa 16*5($in_t), $T0f + lea 16*6($in_t), $in_t + + pand $TMP0, $T0a + pand $TMP0, $T0b + por $T0a, $Ra + pand $TMP0, $T0c + por $T0b, $Rb + pand $TMP0, $T0d + por $T0c, $Rc + pand $TMP0, $T0e + por $T0d, $Rd + pand $TMP0, $T0f + por $T0e, $Re + por $T0f, $Rf + + dec %rax + jnz .Lselect_loop_sse_w5 + + movdqu $Ra, 16*0($val) + movdqu $Rb, 16*1($val) + movdqu $Rc, 16*2($val) + movdqu $Rd, 16*3($val) + movdqu $Re, 16*4($val) + movdqu $Rf, 16*5($val) +___ +$code.=<<___ if ($win64); + movaps (%rsp), %xmm6 + movaps 0x10(%rsp), %xmm7 + movaps 0x20(%rsp), %xmm8 + movaps 0x30(%rsp), %xmm9 + movaps 0x40(%rsp), %xmm10 + movaps 0x50(%rsp), %xmm11 + movaps 0x60(%rsp), %xmm12 + movaps 0x70(%rsp), %xmm13 + movaps 0x80(%rsp), %xmm14 + movaps 0x90(%rsp), %xmm15 + lea 0xa8(%rsp), %rsp +___ +$code.=<<___; + ret +.cfi_endproc +.LSEH_end_ecp_nistz256_gather_w5: +.size ecp_nistz256_gather_w5,.-ecp_nistz256_gather_w5 + +################################################################################ +# void ecp_nistz256_scatter_w7(uint64_t *val, uint64_t *in_t, int index); +.globl ecp_nistz256_scatter_w7 +.type ecp_nistz256_scatter_w7,\@abi-omnipotent +.align 32 +ecp_nistz256_scatter_w7: + movdqu 0x00($in_t), %xmm0 + shl \$6, $index + movdqu 0x10($in_t), %xmm1 + movdqu 0x20($in_t), %xmm2 + movdqu 0x30($in_t), %xmm3 + movdqa %xmm0, 0x00($val,$index) + movdqa %xmm1, 0x10($val,$index) + movdqa %xmm2, 0x20($val,$index) + movdqa %xmm3, 0x30($val,$index) + + ret +.size ecp_nistz256_scatter_w7,.-ecp_nistz256_scatter_w7 + +################################################################################ +# void ecp_nistz256_gather_w7(uint64_t *val, uint64_t *in_t, int index); +.globl ecp_nistz256_gather_w7 +.type ecp_nistz256_gather_w7,\@abi-omnipotent +.align 32 +ecp_nistz256_gather_w7: +.cfi_startproc +___ +$code.=<<___ if ($avx>1); + mov OPENSSL_ia32cap_P+8(%rip), %eax + test \$`1<<5`, %eax + jnz .Lavx2_gather_w7 +___ +$code.=<<___ if ($win64); + lea -0x88(%rsp), %rax +.LSEH_begin_ecp_nistz256_gather_w7: + .byte 0x48,0x8d,0x60,0xe0 #lea -0x20(%rax), %rsp + .byte 0x0f,0x29,0x70,0xe0 #movaps %xmm6, -0x20(%rax) + .byte 0x0f,0x29,0x78,0xf0 #movaps %xmm7, -0x10(%rax) + .byte 0x44,0x0f,0x29,0x00 #movaps %xmm8, 0(%rax) + .byte 0x44,0x0f,0x29,0x48,0x10 #movaps %xmm9, 0x10(%rax) + .byte 0x44,0x0f,0x29,0x50,0x20 #movaps %xmm10, 0x20(%rax) + .byte 0x44,0x0f,0x29,0x58,0x30 #movaps %xmm11, 0x30(%rax) + .byte 0x44,0x0f,0x29,0x60,0x40 #movaps %xmm12, 0x40(%rax) + .byte 0x44,0x0f,0x29,0x68,0x50 #movaps %xmm13, 0x50(%rax) + .byte 0x44,0x0f,0x29,0x70,0x60 #movaps %xmm14, 0x60(%rax) + .byte 0x44,0x0f,0x29,0x78,0x70 #movaps %xmm15, 0x70(%rax) +___ +$code.=<<___; + movdqa .LOne(%rip), $M0 + movd $index, $INDEX + + pxor $Ra, $Ra + pxor $Rb, $Rb + pxor $Rc, $Rc + pxor $Rd, $Rd + + movdqa $M0, $ONE + pshufd \$0, $INDEX, $INDEX + mov \$64, %rax + +.Lselect_loop_sse_w7: + movdqa $M0, $TMP0 + paddd $ONE, $M0 + movdqa 16*0($in_t), $T0a + movdqa 16*1($in_t), $T0b + pcmpeqd $INDEX, $TMP0 + movdqa 16*2($in_t), $T0c + movdqa 16*3($in_t), $T0d + lea 16*4($in_t), $in_t + + pand $TMP0, $T0a + pand $TMP0, $T0b + por $T0a, $Ra + pand $TMP0, $T0c + por $T0b, $Rb + pand $TMP0, $T0d + por $T0c, $Rc + prefetcht0 255($in_t) + por $T0d, $Rd + + dec %rax + jnz .Lselect_loop_sse_w7 + + movdqu $Ra, 16*0($val) + movdqu $Rb, 16*1($val) + movdqu $Rc, 16*2($val) + movdqu $Rd, 16*3($val) +___ +$code.=<<___ if ($win64); + movaps (%rsp), %xmm6 + movaps 0x10(%rsp), %xmm7 + movaps 0x20(%rsp), %xmm8 + movaps 0x30(%rsp), %xmm9 + movaps 0x40(%rsp), %xmm10 + movaps 0x50(%rsp), %xmm11 + movaps 0x60(%rsp), %xmm12 + movaps 0x70(%rsp), %xmm13 + movaps 0x80(%rsp), %xmm14 + movaps 0x90(%rsp), %xmm15 + lea 0xa8(%rsp), %rsp +___ +$code.=<<___; + ret +.cfi_endproc +.LSEH_end_ecp_nistz256_gather_w7: +.size ecp_nistz256_gather_w7,.-ecp_nistz256_gather_w7 +___ +} +if ($avx>1) { +my ($val,$in_t,$index)=$win64?("%rcx","%rdx","%r8d"):("%rdi","%rsi","%edx"); +my ($TWO,$INDEX,$Ra,$Rb,$Rc)=map("%ymm$_",(0..4)); +my ($M0,$T0a,$T0b,$T0c,$TMP0)=map("%ymm$_",(5..9)); +my ($M1,$T1a,$T1b,$T1c,$TMP1)=map("%ymm$_",(10..14)); + +$code.=<<___; +################################################################################ +# void ecp_nistz256_avx2_gather_w5(uint64_t *val, uint64_t *in_t, int index); +.type ecp_nistz256_avx2_gather_w5,\@abi-omnipotent +.align 32 +ecp_nistz256_avx2_gather_w5: +.cfi_startproc +.Lavx2_gather_w5: + vzeroupper +___ +$code.=<<___ if ($win64); + lea -0x88(%rsp), %rax + mov %rsp,%r11 +.LSEH_begin_ecp_nistz256_avx2_gather_w5: + .byte 0x48,0x8d,0x60,0xe0 # lea -0x20(%rax), %rsp + .byte 0xc5,0xf8,0x29,0x70,0xe0 # vmovaps %xmm6, -0x20(%rax) + .byte 0xc5,0xf8,0x29,0x78,0xf0 # vmovaps %xmm7, -0x10(%rax) + .byte 0xc5,0x78,0x29,0x40,0x00 # vmovaps %xmm8, 8(%rax) + .byte 0xc5,0x78,0x29,0x48,0x10 # vmovaps %xmm9, 0x10(%rax) + .byte 0xc5,0x78,0x29,0x50,0x20 # vmovaps %xmm10, 0x20(%rax) + .byte 0xc5,0x78,0x29,0x58,0x30 # vmovaps %xmm11, 0x30(%rax) + .byte 0xc5,0x78,0x29,0x60,0x40 # vmovaps %xmm12, 0x40(%rax) + .byte 0xc5,0x78,0x29,0x68,0x50 # vmovaps %xmm13, 0x50(%rax) + .byte 0xc5,0x78,0x29,0x70,0x60 # vmovaps %xmm14, 0x60(%rax) + .byte 0xc5,0x78,0x29,0x78,0x70 # vmovaps %xmm15, 0x70(%rax) +___ +$code.=<<___; + vmovdqa .LTwo(%rip), $TWO + + vpxor $Ra, $Ra, $Ra + vpxor $Rb, $Rb, $Rb + vpxor $Rc, $Rc, $Rc + + vmovdqa .LOne(%rip), $M0 + vmovdqa .LTwo(%rip), $M1 + + vmovd $index, %xmm1 + vpermd $INDEX, $Ra, $INDEX + + mov \$8, %rax +.Lselect_loop_avx2_w5: + + vmovdqa 32*0($in_t), $T0a + vmovdqa 32*1($in_t), $T0b + vmovdqa 32*2($in_t), $T0c + + vmovdqa 32*3($in_t), $T1a + vmovdqa 32*4($in_t), $T1b + vmovdqa 32*5($in_t), $T1c + + vpcmpeqd $INDEX, $M0, $TMP0 + vpcmpeqd $INDEX, $M1, $TMP1 + + vpaddd $TWO, $M0, $M0 + vpaddd $TWO, $M1, $M1 + lea 32*6($in_t), $in_t + + vpand $TMP0, $T0a, $T0a + vpand $TMP0, $T0b, $T0b + vpand $TMP0, $T0c, $T0c + vpand $TMP1, $T1a, $T1a + vpand $TMP1, $T1b, $T1b + vpand $TMP1, $T1c, $T1c + + vpxor $T0a, $Ra, $Ra + vpxor $T0b, $Rb, $Rb + vpxor $T0c, $Rc, $Rc + vpxor $T1a, $Ra, $Ra + vpxor $T1b, $Rb, $Rb + vpxor $T1c, $Rc, $Rc + + dec %rax + jnz .Lselect_loop_avx2_w5 + + vmovdqu $Ra, 32*0($val) + vmovdqu $Rb, 32*1($val) + vmovdqu $Rc, 32*2($val) + vzeroupper +___ +$code.=<<___ if ($win64); + movaps (%rsp), %xmm6 + movaps 0x10(%rsp), %xmm7 + movaps 0x20(%rsp), %xmm8 + movaps 0x30(%rsp), %xmm9 + movaps 0x40(%rsp), %xmm10 + movaps 0x50(%rsp), %xmm11 + movaps 0x60(%rsp), %xmm12 + movaps 0x70(%rsp), %xmm13 + movaps 0x80(%rsp), %xmm14 + movaps 0x90(%rsp), %xmm15 + lea (%r11), %rsp +___ +$code.=<<___; + ret +.cfi_endproc +.LSEH_end_ecp_nistz256_avx2_gather_w5: +.size ecp_nistz256_avx2_gather_w5,.-ecp_nistz256_avx2_gather_w5 +___ +} +if ($avx>1) { +my ($val,$in_t,$index)=$win64?("%rcx","%rdx","%r8d"):("%rdi","%rsi","%edx"); +my ($THREE,$INDEX,$Ra,$Rb)=map("%ymm$_",(0..3)); +my ($M0,$T0a,$T0b,$TMP0)=map("%ymm$_",(4..7)); +my ($M1,$T1a,$T1b,$TMP1)=map("%ymm$_",(8..11)); +my ($M2,$T2a,$T2b,$TMP2)=map("%ymm$_",(12..15)); + +$code.=<<___; + +################################################################################ +# void ecp_nistz256_avx2_gather_w7(uint64_t *val, uint64_t *in_t, int index); +.globl ecp_nistz256_avx2_gather_w7 +.type ecp_nistz256_avx2_gather_w7,\@abi-omnipotent +.align 32 +ecp_nistz256_avx2_gather_w7: +.cfi_startproc +.Lavx2_gather_w7: + vzeroupper +___ +$code.=<<___ if ($win64); + mov %rsp,%r11 + lea -0x88(%rsp), %rax +.LSEH_begin_ecp_nistz256_avx2_gather_w7: + .byte 0x48,0x8d,0x60,0xe0 # lea -0x20(%rax), %rsp + .byte 0xc5,0xf8,0x29,0x70,0xe0 # vmovaps %xmm6, -0x20(%rax) + .byte 0xc5,0xf8,0x29,0x78,0xf0 # vmovaps %xmm7, -0x10(%rax) + .byte 0xc5,0x78,0x29,0x40,0x00 # vmovaps %xmm8, 8(%rax) + .byte 0xc5,0x78,0x29,0x48,0x10 # vmovaps %xmm9, 0x10(%rax) + .byte 0xc5,0x78,0x29,0x50,0x20 # vmovaps %xmm10, 0x20(%rax) + .byte 0xc5,0x78,0x29,0x58,0x30 # vmovaps %xmm11, 0x30(%rax) + .byte 0xc5,0x78,0x29,0x60,0x40 # vmovaps %xmm12, 0x40(%rax) + .byte 0xc5,0x78,0x29,0x68,0x50 # vmovaps %xmm13, 0x50(%rax) + .byte 0xc5,0x78,0x29,0x70,0x60 # vmovaps %xmm14, 0x60(%rax) + .byte 0xc5,0x78,0x29,0x78,0x70 # vmovaps %xmm15, 0x70(%rax) +___ +$code.=<<___; + vmovdqa .LThree(%rip), $THREE + + vpxor $Ra, $Ra, $Ra + vpxor $Rb, $Rb, $Rb + + vmovdqa .LOne(%rip), $M0 + vmovdqa .LTwo(%rip), $M1 + vmovdqa .LThree(%rip), $M2 + + vmovd $index, %xmm1 + vpermd $INDEX, $Ra, $INDEX + # Skip index = 0, because it is implicitly the point at infinity + + mov \$21, %rax +.Lselect_loop_avx2_w7: + + vmovdqa 32*0($in_t), $T0a + vmovdqa 32*1($in_t), $T0b + + vmovdqa 32*2($in_t), $T1a + vmovdqa 32*3($in_t), $T1b + + vmovdqa 32*4($in_t), $T2a + vmovdqa 32*5($in_t), $T2b + + vpcmpeqd $INDEX, $M0, $TMP0 + vpcmpeqd $INDEX, $M1, $TMP1 + vpcmpeqd $INDEX, $M2, $TMP2 + + vpaddd $THREE, $M0, $M0 + vpaddd $THREE, $M1, $M1 + vpaddd $THREE, $M2, $M2 + lea 32*6($in_t), $in_t + + vpand $TMP0, $T0a, $T0a + vpand $TMP0, $T0b, $T0b + vpand $TMP1, $T1a, $T1a + vpand $TMP1, $T1b, $T1b + vpand $TMP2, $T2a, $T2a + vpand $TMP2, $T2b, $T2b + + vpxor $T0a, $Ra, $Ra + vpxor $T0b, $Rb, $Rb + vpxor $T1a, $Ra, $Ra + vpxor $T1b, $Rb, $Rb + vpxor $T2a, $Ra, $Ra + vpxor $T2b, $Rb, $Rb + + dec %rax + jnz .Lselect_loop_avx2_w7 + + + vmovdqa 32*0($in_t), $T0a + vmovdqa 32*1($in_t), $T0b + + vpcmpeqd $INDEX, $M0, $TMP0 + + vpand $TMP0, $T0a, $T0a + vpand $TMP0, $T0b, $T0b + + vpxor $T0a, $Ra, $Ra + vpxor $T0b, $Rb, $Rb + + vmovdqu $Ra, 32*0($val) + vmovdqu $Rb, 32*1($val) + vzeroupper +___ +$code.=<<___ if ($win64); + movaps (%rsp), %xmm6 + movaps 0x10(%rsp), %xmm7 + movaps 0x20(%rsp), %xmm8 + movaps 0x30(%rsp), %xmm9 + movaps 0x40(%rsp), %xmm10 + movaps 0x50(%rsp), %xmm11 + movaps 0x60(%rsp), %xmm12 + movaps 0x70(%rsp), %xmm13 + movaps 0x80(%rsp), %xmm14 + movaps 0x90(%rsp), %xmm15 + lea (%r11), %rsp +___ +$code.=<<___; + ret +.cfi_endproc +.LSEH_end_ecp_nistz256_avx2_gather_w7: +.size ecp_nistz256_avx2_gather_w7,.-ecp_nistz256_avx2_gather_w7 +___ +} else { +$code.=<<___; +.globl ecp_nistz256_avx2_gather_w7 +.type ecp_nistz256_avx2_gather_w7,\@function,3 +.align 32 +ecp_nistz256_avx2_gather_w7: + .byte 0x0f,0x0b # ud2 + ret +.size ecp_nistz256_avx2_gather_w7,.-ecp_nistz256_avx2_gather_w7 +___ +} +{{{ +######################################################################## +# This block implements higher level point_double, point_add and +# point_add_affine. The key to performance in this case is to allow +# out-of-order execution logic to overlap computations from next step +# with tail processing from current step. By using tailored calling +# sequence we minimize inter-step overhead to give processor better +# shot at overlapping operations... +# +# You will notice that input data is copied to stack. Trouble is that +# there are no registers to spare for holding original pointers and +# reloading them, pointers, would create undesired dependencies on +# effective addresses calculation paths. In other words it's too done +# to favour out-of-order execution logic. +# + +my ($r_ptr,$a_ptr,$b_org,$b_ptr)=("%rdi","%rsi","%rdx","%rbx"); +my ($acc0,$acc1,$acc2,$acc3,$acc4,$acc5,$acc6,$acc7)=map("%r$_",(8..15)); +my ($t0,$t1,$t2,$t3,$t4)=("%rax","%rbp","%rcx",$acc4,$acc4); +my ($poly1,$poly3)=($acc6,$acc7); + +sub load_for_mul () { +my ($a,$b,$src0) = @_; +my $bias = $src0 eq "%rax" ? 0 : -128; + +" mov $b, $src0 + lea $b, $b_ptr + mov 8*0+$a, $acc1 + mov 8*1+$a, $acc2 + lea $bias+$a, $a_ptr + mov 8*2+$a, $acc3 + mov 8*3+$a, $acc4" +} + +sub load_for_sqr () { +my ($a,$src0) = @_; +my $bias = $src0 eq "%rax" ? 0 : -128; + +" mov 8*0+$a, $src0 + mov 8*1+$a, $acc6 + lea $bias+$a, $a_ptr + mov 8*2+$a, $acc7 + mov 8*3+$a, $acc0" +} + + { +######################################################################## +# operate in 4-5-0-1 "name space" that matches multiplication output +# +my ($a0,$a1,$a2,$a3,$t3,$t4)=($acc4,$acc5,$acc0,$acc1,$acc2,$acc3); + +$code.=<<___; +.type __ecp_nistz256_add_toq,\@abi-omnipotent +.align 32 +__ecp_nistz256_add_toq: +.cfi_startproc + xor $t4,$t4 + add 8*0($b_ptr), $a0 + adc 8*1($b_ptr), $a1 + mov $a0, $t0 + adc 8*2($b_ptr), $a2 + adc 8*3($b_ptr), $a3 + mov $a1, $t1 + adc \$0, $t4 + + sub \$-1, $a0 + mov $a2, $t2 + sbb $poly1, $a1 + sbb \$0, $a2 + mov $a3, $t3 + sbb $poly3, $a3 + sbb \$0, $t4 + + cmovc $t0, $a0 + cmovc $t1, $a1 + mov $a0, 8*0($r_ptr) + cmovc $t2, $a2 + mov $a1, 8*1($r_ptr) + cmovc $t3, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) + + ret +.cfi_endproc +.size __ecp_nistz256_add_toq,.-__ecp_nistz256_add_toq + +.type __ecp_nistz256_sub_fromq,\@abi-omnipotent +.align 32 +__ecp_nistz256_sub_fromq: +.cfi_startproc + sub 8*0($b_ptr), $a0 + sbb 8*1($b_ptr), $a1 + mov $a0, $t0 + sbb 8*2($b_ptr), $a2 + sbb 8*3($b_ptr), $a3 + mov $a1, $t1 + sbb $t4, $t4 + + add \$-1, $a0 + mov $a2, $t2 + adc $poly1, $a1 + adc \$0, $a2 + mov $a3, $t3 + adc $poly3, $a3 + test $t4, $t4 + + cmovz $t0, $a0 + cmovz $t1, $a1 + mov $a0, 8*0($r_ptr) + cmovz $t2, $a2 + mov $a1, 8*1($r_ptr) + cmovz $t3, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) + + ret +.cfi_endproc +.size __ecp_nistz256_sub_fromq,.-__ecp_nistz256_sub_fromq + +.type __ecp_nistz256_subq,\@abi-omnipotent +.align 32 +__ecp_nistz256_subq: +.cfi_startproc + sub $a0, $t0 + sbb $a1, $t1 + mov $t0, $a0 + sbb $a2, $t2 + sbb $a3, $t3 + mov $t1, $a1 + sbb $t4, $t4 + + add \$-1, $t0 + mov $t2, $a2 + adc $poly1, $t1 + adc \$0, $t2 + mov $t3, $a3 + adc $poly3, $t3 + test $t4, $t4 + + cmovnz $t0, $a0 + cmovnz $t1, $a1 + cmovnz $t2, $a2 + cmovnz $t3, $a3 + + ret +.cfi_endproc +.size __ecp_nistz256_subq,.-__ecp_nistz256_subq + +.type __ecp_nistz256_mul_by_2q,\@abi-omnipotent +.align 32 +__ecp_nistz256_mul_by_2q: +.cfi_startproc + xor $t4, $t4 + add $a0, $a0 # a0:a3+a0:a3 + adc $a1, $a1 + mov $a0, $t0 + adc $a2, $a2 + adc $a3, $a3 + mov $a1, $t1 + adc \$0, $t4 + + sub \$-1, $a0 + mov $a2, $t2 + sbb $poly1, $a1 + sbb \$0, $a2 + mov $a3, $t3 + sbb $poly3, $a3 + sbb \$0, $t4 + + cmovc $t0, $a0 + cmovc $t1, $a1 + mov $a0, 8*0($r_ptr) + cmovc $t2, $a2 + mov $a1, 8*1($r_ptr) + cmovc $t3, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) + + ret +.cfi_endproc +.size __ecp_nistz256_mul_by_2q,.-__ecp_nistz256_mul_by_2q +___ + } +sub gen_double () { + my $x = shift; + my ($src0,$sfx,$bias); + my ($S,$M,$Zsqr,$in_x,$tmp0)=map(32*$_,(0..4)); + + if ($x ne "x") { + $src0 = "%rax"; + $sfx = ""; + $bias = 0; + +$code.=<<___; +.globl ecp_nistz256_point_double +.type ecp_nistz256_point_double,\@function,2 +.align 32 +ecp_nistz256_point_double: +.cfi_startproc +___ +$code.=<<___ if ($addx); + mov \$0x80100, %ecx + and OPENSSL_ia32cap_P+8(%rip), %ecx + cmp \$0x80100, %ecx + je .Lpoint_doublex +___ + } else { + $src0 = "%rdx"; + $sfx = "x"; + $bias = 128; + +$code.=<<___; +.type ecp_nistz256_point_doublex,\@function,2 +.align 32 +ecp_nistz256_point_doublex: +.cfi_startproc +.Lpoint_doublex: +___ + } +$code.=<<___; + push %rbp +.cfi_push %rbp + push %rbx +.cfi_push %rbx + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + sub \$32*5+8, %rsp +.cfi_adjust_cfa_offset 32*5+8 +.Lpoint_double${x}_body: + +.Lpoint_double_shortcut$x: + movdqu 0x00($a_ptr), %xmm0 # copy *(P256_POINT *)$a_ptr.x + mov $a_ptr, $b_ptr # backup copy + movdqu 0x10($a_ptr), %xmm1 + mov 0x20+8*0($a_ptr), $acc4 # load in_y in "5-4-0-1" order + mov 0x20+8*1($a_ptr), $acc5 + mov 0x20+8*2($a_ptr), $acc0 + mov 0x20+8*3($a_ptr), $acc1 + mov .Lpoly+8*1(%rip), $poly1 + mov .Lpoly+8*3(%rip), $poly3 + movdqa %xmm0, $in_x(%rsp) + movdqa %xmm1, $in_x+0x10(%rsp) + lea 0x20($r_ptr), $acc2 + lea 0x40($r_ptr), $acc3 + movq $r_ptr, %xmm0 + movq $acc2, %xmm1 + movq $acc3, %xmm2 + + lea $S(%rsp), $r_ptr + call __ecp_nistz256_mul_by_2$x # p256_mul_by_2(S, in_y); + + mov 0x40+8*0($a_ptr), $src0 + mov 0x40+8*1($a_ptr), $acc6 + mov 0x40+8*2($a_ptr), $acc7 + mov 0x40+8*3($a_ptr), $acc0 + lea 0x40-$bias($a_ptr), $a_ptr + lea $Zsqr(%rsp), $r_ptr + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(Zsqr, in_z); + + `&load_for_sqr("$S(%rsp)", "$src0")` + lea $S(%rsp), $r_ptr + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(S, S); + + mov 0x20($b_ptr), $src0 # $b_ptr is still valid + mov 0x40+8*0($b_ptr), $acc1 + mov 0x40+8*1($b_ptr), $acc2 + mov 0x40+8*2($b_ptr), $acc3 + mov 0x40+8*3($b_ptr), $acc4 + lea 0x40-$bias($b_ptr), $a_ptr + lea 0x20($b_ptr), $b_ptr + movq %xmm2, $r_ptr + call __ecp_nistz256_mul_mont$x # p256_mul_mont(res_z, in_z, in_y); + call __ecp_nistz256_mul_by_2$x # p256_mul_by_2(res_z, res_z); + + mov $in_x+8*0(%rsp), $acc4 # "5-4-0-1" order + mov $in_x+8*1(%rsp), $acc5 + lea $Zsqr(%rsp), $b_ptr + mov $in_x+8*2(%rsp), $acc0 + mov $in_x+8*3(%rsp), $acc1 + lea $M(%rsp), $r_ptr + call __ecp_nistz256_add_to$x # p256_add(M, in_x, Zsqr); + + mov $in_x+8*0(%rsp), $acc4 # "5-4-0-1" order + mov $in_x+8*1(%rsp), $acc5 + lea $Zsqr(%rsp), $b_ptr + mov $in_x+8*2(%rsp), $acc0 + mov $in_x+8*3(%rsp), $acc1 + lea $Zsqr(%rsp), $r_ptr + call __ecp_nistz256_sub_from$x # p256_sub(Zsqr, in_x, Zsqr); + + `&load_for_sqr("$S(%rsp)", "$src0")` + movq %xmm1, $r_ptr + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(res_y, S); +___ +{ +######## ecp_nistz256_div_by_2(res_y, res_y); ########################## +# operate in 4-5-6-7 "name space" that matches squaring output +# +my ($poly1,$poly3)=($a_ptr,$t1); +my ($a0,$a1,$a2,$a3,$t3,$t4,$t1)=($acc4,$acc5,$acc6,$acc7,$acc0,$acc1,$acc2); + +$code.=<<___; + xor $t4, $t4 + mov $a0, $t0 + add \$-1, $a0 + mov $a1, $t1 + adc $poly1, $a1 + mov $a2, $t2 + adc \$0, $a2 + mov $a3, $t3 + adc $poly3, $a3 + adc \$0, $t4 + xor $a_ptr, $a_ptr # borrow $a_ptr + test \$1, $t0 + + cmovz $t0, $a0 + cmovz $t1, $a1 + cmovz $t2, $a2 + cmovz $t3, $a3 + cmovz $a_ptr, $t4 + + mov $a1, $t0 # a0:a3>>1 + shr \$1, $a0 + shl \$63, $t0 + mov $a2, $t1 + shr \$1, $a1 + or $t0, $a0 + shl \$63, $t1 + mov $a3, $t2 + shr \$1, $a2 + or $t1, $a1 + shl \$63, $t2 + mov $a0, 8*0($r_ptr) + shr \$1, $a3 + mov $a1, 8*1($r_ptr) + shl \$63, $t4 + or $t2, $a2 + or $t4, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) +___ +} +$code.=<<___; + `&load_for_mul("$M(%rsp)", "$Zsqr(%rsp)", "$src0")` + lea $M(%rsp), $r_ptr + call __ecp_nistz256_mul_mont$x # p256_mul_mont(M, M, Zsqr); + + lea $tmp0(%rsp), $r_ptr + call __ecp_nistz256_mul_by_2$x + + lea $M(%rsp), $b_ptr + lea $M(%rsp), $r_ptr + call __ecp_nistz256_add_to$x # p256_mul_by_3(M, M); + + `&load_for_mul("$S(%rsp)", "$in_x(%rsp)", "$src0")` + lea $S(%rsp), $r_ptr + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S, S, in_x); + + lea $tmp0(%rsp), $r_ptr + call __ecp_nistz256_mul_by_2$x # p256_mul_by_2(tmp0, S); + + `&load_for_sqr("$M(%rsp)", "$src0")` + movq %xmm0, $r_ptr + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(res_x, M); + + lea $tmp0(%rsp), $b_ptr + mov $acc6, $acc0 # harmonize sqr output and sub input + mov $acc7, $acc1 + mov $a_ptr, $poly1 + mov $t1, $poly3 + call __ecp_nistz256_sub_from$x # p256_sub(res_x, res_x, tmp0); + + mov $S+8*0(%rsp), $t0 + mov $S+8*1(%rsp), $t1 + mov $S+8*2(%rsp), $t2 + mov $S+8*3(%rsp), $acc2 # "4-5-0-1" order + lea $S(%rsp), $r_ptr + call __ecp_nistz256_sub$x # p256_sub(S, S, res_x); + + mov $M(%rsp), $src0 + lea $M(%rsp), $b_ptr + mov $acc4, $acc6 # harmonize sub output and mul input + xor %ecx, %ecx + mov $acc4, $S+8*0(%rsp) # have to save:-( + mov $acc5, $acc2 + mov $acc5, $S+8*1(%rsp) + cmovz $acc0, $acc3 + mov $acc0, $S+8*2(%rsp) + lea $S-$bias(%rsp), $a_ptr + cmovz $acc1, $acc4 + mov $acc1, $S+8*3(%rsp) + mov $acc6, $acc1 + lea $S(%rsp), $r_ptr + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S, S, M); + + movq %xmm1, $b_ptr + movq %xmm1, $r_ptr + call __ecp_nistz256_sub_from$x # p256_sub(res_y, S, res_y); + + lea 32*5+56(%rsp), %rsi +.cfi_def_cfa %rsi,8 + mov -48(%rsi),%r15 +.cfi_restore %r15 + mov -40(%rsi),%r14 +.cfi_restore %r14 + mov -32(%rsi),%r13 +.cfi_restore %r13 + mov -24(%rsi),%r12 +.cfi_restore %r12 + mov -16(%rsi),%rbx +.cfi_restore %rbx + mov -8(%rsi),%rbp +.cfi_restore %rbp + lea (%rsi),%rsp +.cfi_def_cfa_register %rsp +.Lpoint_double${x}_epilogue: + ret +.cfi_endproc +.size ecp_nistz256_point_double$sfx,.-ecp_nistz256_point_double$sfx +___ +} +&gen_double("q"); + +sub gen_add () { + my $x = shift; + my ($src0,$sfx,$bias); + my ($H,$Hsqr,$R,$Rsqr,$Hcub, + $U1,$U2,$S1,$S2, + $res_x,$res_y,$res_z, + $in1_x,$in1_y,$in1_z, + $in2_x,$in2_y,$in2_z)=map(32*$_,(0..17)); + my ($Z1sqr, $Z2sqr) = ($Hsqr, $Rsqr); + + if ($x ne "x") { + $src0 = "%rax"; + $sfx = ""; + $bias = 0; + +$code.=<<___; +.globl ecp_nistz256_point_add +.type ecp_nistz256_point_add,\@function,3 +.align 32 +ecp_nistz256_point_add: +.cfi_startproc +___ +$code.=<<___ if ($addx); + mov \$0x80100, %ecx + and OPENSSL_ia32cap_P+8(%rip), %ecx + cmp \$0x80100, %ecx + je .Lpoint_addx +___ + } else { + $src0 = "%rdx"; + $sfx = "x"; + $bias = 128; + +$code.=<<___; +.type ecp_nistz256_point_addx,\@function,3 +.align 32 +ecp_nistz256_point_addx: +.cfi_startproc +.Lpoint_addx: +___ + } +$code.=<<___; + push %rbp +.cfi_push %rbp + push %rbx +.cfi_push %rbx + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + sub \$32*18+8, %rsp +.cfi_adjust_cfa_offset 32*18+8 +.Lpoint_add${x}_body: + + movdqu 0x00($a_ptr), %xmm0 # copy *(P256_POINT *)$a_ptr + movdqu 0x10($a_ptr), %xmm1 + movdqu 0x20($a_ptr), %xmm2 + movdqu 0x30($a_ptr), %xmm3 + movdqu 0x40($a_ptr), %xmm4 + movdqu 0x50($a_ptr), %xmm5 + mov $a_ptr, $b_ptr # reassign + mov $b_org, $a_ptr # reassign + movdqa %xmm0, $in1_x(%rsp) + movdqa %xmm1, $in1_x+0x10(%rsp) + movdqa %xmm2, $in1_y(%rsp) + movdqa %xmm3, $in1_y+0x10(%rsp) + movdqa %xmm4, $in1_z(%rsp) + movdqa %xmm5, $in1_z+0x10(%rsp) + por %xmm4, %xmm5 + + movdqu 0x00($a_ptr), %xmm0 # copy *(P256_POINT *)$b_ptr + pshufd \$0xb1, %xmm5, %xmm3 + movdqu 0x10($a_ptr), %xmm1 + movdqu 0x20($a_ptr), %xmm2 + por %xmm3, %xmm5 + movdqu 0x30($a_ptr), %xmm3 + mov 0x40+8*0($a_ptr), $src0 # load original in2_z + mov 0x40+8*1($a_ptr), $acc6 + mov 0x40+8*2($a_ptr), $acc7 + mov 0x40+8*3($a_ptr), $acc0 + movdqa %xmm0, $in2_x(%rsp) + pshufd \$0x1e, %xmm5, %xmm4 + movdqa %xmm1, $in2_x+0x10(%rsp) + movdqu 0x40($a_ptr),%xmm0 # in2_z again + movdqu 0x50($a_ptr),%xmm1 + movdqa %xmm2, $in2_y(%rsp) + movdqa %xmm3, $in2_y+0x10(%rsp) + por %xmm4, %xmm5 + pxor %xmm4, %xmm4 + por %xmm0, %xmm1 + movq $r_ptr, %xmm0 # save $r_ptr + + lea 0x40-$bias($a_ptr), $a_ptr # $a_ptr is still valid + mov $src0, $in2_z+8*0(%rsp) # make in2_z copy + mov $acc6, $in2_z+8*1(%rsp) + mov $acc7, $in2_z+8*2(%rsp) + mov $acc0, $in2_z+8*3(%rsp) + lea $Z2sqr(%rsp), $r_ptr # Z2^2 + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(Z2sqr, in2_z); + + pcmpeqd %xmm4, %xmm5 + pshufd \$0xb1, %xmm1, %xmm4 + por %xmm1, %xmm4 + pshufd \$0, %xmm5, %xmm5 # in1infty + pshufd \$0x1e, %xmm4, %xmm3 + por %xmm3, %xmm4 + pxor %xmm3, %xmm3 + pcmpeqd %xmm3, %xmm4 + pshufd \$0, %xmm4, %xmm4 # in2infty + mov 0x40+8*0($b_ptr), $src0 # load original in1_z + mov 0x40+8*1($b_ptr), $acc6 + mov 0x40+8*2($b_ptr), $acc7 + mov 0x40+8*3($b_ptr), $acc0 + movq $b_ptr, %xmm1 + + lea 0x40-$bias($b_ptr), $a_ptr + lea $Z1sqr(%rsp), $r_ptr # Z1^2 + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(Z1sqr, in1_z); + + `&load_for_mul("$Z2sqr(%rsp)", "$in2_z(%rsp)", "$src0")` + lea $S1(%rsp), $r_ptr # S1 = Z2^3 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S1, Z2sqr, in2_z); + + `&load_for_mul("$Z1sqr(%rsp)", "$in1_z(%rsp)", "$src0")` + lea $S2(%rsp), $r_ptr # S2 = Z1^3 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S2, Z1sqr, in1_z); + + `&load_for_mul("$S1(%rsp)", "$in1_y(%rsp)", "$src0")` + lea $S1(%rsp), $r_ptr # S1 = Y1*Z2^3 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S1, S1, in1_y); + + `&load_for_mul("$S2(%rsp)", "$in2_y(%rsp)", "$src0")` + lea $S2(%rsp), $r_ptr # S2 = Y2*Z1^3 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S2, S2, in2_y); + + lea $S1(%rsp), $b_ptr + lea $R(%rsp), $r_ptr # R = S2 - S1 + call __ecp_nistz256_sub_from$x # p256_sub(R, S2, S1); + + or $acc5, $acc4 # see if result is zero + movdqa %xmm4, %xmm2 + or $acc0, $acc4 + or $acc1, $acc4 + por %xmm5, %xmm2 # in1infty || in2infty + movq $acc4, %xmm3 + + `&load_for_mul("$Z2sqr(%rsp)", "$in1_x(%rsp)", "$src0")` + lea $U1(%rsp), $r_ptr # U1 = X1*Z2^2 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(U1, in1_x, Z2sqr); + + `&load_for_mul("$Z1sqr(%rsp)", "$in2_x(%rsp)", "$src0")` + lea $U2(%rsp), $r_ptr # U2 = X2*Z1^2 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(U2, in2_x, Z1sqr); + + lea $U1(%rsp), $b_ptr + lea $H(%rsp), $r_ptr # H = U2 - U1 + call __ecp_nistz256_sub_from$x # p256_sub(H, U2, U1); + + or $acc5, $acc4 # see if result is zero + or $acc0, $acc4 + or $acc1, $acc4 + + .byte 0x3e # predict taken + jnz .Ladd_proceed$x # is_equal(U1,U2)? + movq %xmm2, $acc0 + movq %xmm3, $acc1 + test $acc0, $acc0 + jnz .Ladd_proceed$x # (in1infty || in2infty)? + test $acc1, $acc1 + jz .Ladd_double$x # is_equal(S1,S2)? + + movq %xmm0, $r_ptr # restore $r_ptr + pxor %xmm0, %xmm0 + movdqu %xmm0, 0x00($r_ptr) + movdqu %xmm0, 0x10($r_ptr) + movdqu %xmm0, 0x20($r_ptr) + movdqu %xmm0, 0x30($r_ptr) + movdqu %xmm0, 0x40($r_ptr) + movdqu %xmm0, 0x50($r_ptr) + jmp .Ladd_done$x + +.align 32 +.Ladd_double$x: + movq %xmm1, $a_ptr # restore $a_ptr + movq %xmm0, $r_ptr # restore $r_ptr + add \$`32*(18-5)`, %rsp # difference in frame sizes +.cfi_adjust_cfa_offset `-32*(18-5)` + jmp .Lpoint_double_shortcut$x +.cfi_adjust_cfa_offset `32*(18-5)` + +.align 32 +.Ladd_proceed$x: + `&load_for_sqr("$R(%rsp)", "$src0")` + lea $Rsqr(%rsp), $r_ptr # R^2 + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(Rsqr, R); + + `&load_for_mul("$H(%rsp)", "$in1_z(%rsp)", "$src0")` + lea $res_z(%rsp), $r_ptr # Z3 = H*Z1*Z2 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(res_z, H, in1_z); + + `&load_for_sqr("$H(%rsp)", "$src0")` + lea $Hsqr(%rsp), $r_ptr # H^2 + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(Hsqr, H); + + `&load_for_mul("$res_z(%rsp)", "$in2_z(%rsp)", "$src0")` + lea $res_z(%rsp), $r_ptr # Z3 = H*Z1*Z2 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(res_z, res_z, in2_z); + + `&load_for_mul("$Hsqr(%rsp)", "$H(%rsp)", "$src0")` + lea $Hcub(%rsp), $r_ptr # H^3 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(Hcub, Hsqr, H); + + `&load_for_mul("$Hsqr(%rsp)", "$U1(%rsp)", "$src0")` + lea $U2(%rsp), $r_ptr # U1*H^2 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(U2, U1, Hsqr); +___ +{ +####################################################################### +# operate in 4-5-0-1 "name space" that matches multiplication output +# +my ($acc0,$acc1,$acc2,$acc3,$t3,$t4)=($acc4,$acc5,$acc0,$acc1,$acc2,$acc3); +my ($poly1, $poly3)=($acc6,$acc7); + +$code.=<<___; + #lea $U2(%rsp), $a_ptr + #lea $Hsqr(%rsp), $r_ptr # 2*U1*H^2 + #call __ecp_nistz256_mul_by_2 # ecp_nistz256_mul_by_2(Hsqr, U2); + + xor $t4, $t4 + add $acc0, $acc0 # a0:a3+a0:a3 + lea $Rsqr(%rsp), $a_ptr + adc $acc1, $acc1 + mov $acc0, $t0 + adc $acc2, $acc2 + adc $acc3, $acc3 + mov $acc1, $t1 + adc \$0, $t4 + + sub \$-1, $acc0 + mov $acc2, $t2 + sbb $poly1, $acc1 + sbb \$0, $acc2 + mov $acc3, $t3 + sbb $poly3, $acc3 + sbb \$0, $t4 + + cmovc $t0, $acc0 + mov 8*0($a_ptr), $t0 + cmovc $t1, $acc1 + mov 8*1($a_ptr), $t1 + cmovc $t2, $acc2 + mov 8*2($a_ptr), $t2 + cmovc $t3, $acc3 + mov 8*3($a_ptr), $t3 + + call __ecp_nistz256_sub$x # p256_sub(res_x, Rsqr, Hsqr); + + lea $Hcub(%rsp), $b_ptr + lea $res_x(%rsp), $r_ptr + call __ecp_nistz256_sub_from$x # p256_sub(res_x, res_x, Hcub); + + mov $U2+8*0(%rsp), $t0 + mov $U2+8*1(%rsp), $t1 + mov $U2+8*2(%rsp), $t2 + mov $U2+8*3(%rsp), $t3 + lea $res_y(%rsp), $r_ptr + + call __ecp_nistz256_sub$x # p256_sub(res_y, U2, res_x); + + mov $acc0, 8*0($r_ptr) # save the result, as + mov $acc1, 8*1($r_ptr) # __ecp_nistz256_sub doesn't + mov $acc2, 8*2($r_ptr) + mov $acc3, 8*3($r_ptr) +___ +} +$code.=<<___; + `&load_for_mul("$S1(%rsp)", "$Hcub(%rsp)", "$src0")` + lea $S2(%rsp), $r_ptr + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S2, S1, Hcub); + + `&load_for_mul("$R(%rsp)", "$res_y(%rsp)", "$src0")` + lea $res_y(%rsp), $r_ptr + call __ecp_nistz256_mul_mont$x # p256_mul_mont(res_y, R, res_y); + + lea $S2(%rsp), $b_ptr + lea $res_y(%rsp), $r_ptr + call __ecp_nistz256_sub_from$x # p256_sub(res_y, res_y, S2); + + movq %xmm0, $r_ptr # restore $r_ptr + + movdqa %xmm5, %xmm0 # copy_conditional(res_z, in2_z, in1infty); + movdqa %xmm5, %xmm1 + pandn $res_z(%rsp), %xmm0 + movdqa %xmm5, %xmm2 + pandn $res_z+0x10(%rsp), %xmm1 + movdqa %xmm5, %xmm3 + pand $in2_z(%rsp), %xmm2 + pand $in2_z+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + + movdqa %xmm4, %xmm0 # copy_conditional(res_z, in1_z, in2infty); + movdqa %xmm4, %xmm1 + pandn %xmm2, %xmm0 + movdqa %xmm4, %xmm2 + pandn %xmm3, %xmm1 + movdqa %xmm4, %xmm3 + pand $in1_z(%rsp), %xmm2 + pand $in1_z+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + movdqu %xmm2, 0x40($r_ptr) + movdqu %xmm3, 0x50($r_ptr) + + movdqa %xmm5, %xmm0 # copy_conditional(res_x, in2_x, in1infty); + movdqa %xmm5, %xmm1 + pandn $res_x(%rsp), %xmm0 + movdqa %xmm5, %xmm2 + pandn $res_x+0x10(%rsp), %xmm1 + movdqa %xmm5, %xmm3 + pand $in2_x(%rsp), %xmm2 + pand $in2_x+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + + movdqa %xmm4, %xmm0 # copy_conditional(res_x, in1_x, in2infty); + movdqa %xmm4, %xmm1 + pandn %xmm2, %xmm0 + movdqa %xmm4, %xmm2 + pandn %xmm3, %xmm1 + movdqa %xmm4, %xmm3 + pand $in1_x(%rsp), %xmm2 + pand $in1_x+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + movdqu %xmm2, 0x00($r_ptr) + movdqu %xmm3, 0x10($r_ptr) + + movdqa %xmm5, %xmm0 # copy_conditional(res_y, in2_y, in1infty); + movdqa %xmm5, %xmm1 + pandn $res_y(%rsp), %xmm0 + movdqa %xmm5, %xmm2 + pandn $res_y+0x10(%rsp), %xmm1 + movdqa %xmm5, %xmm3 + pand $in2_y(%rsp), %xmm2 + pand $in2_y+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + + movdqa %xmm4, %xmm0 # copy_conditional(res_y, in1_y, in2infty); + movdqa %xmm4, %xmm1 + pandn %xmm2, %xmm0 + movdqa %xmm4, %xmm2 + pandn %xmm3, %xmm1 + movdqa %xmm4, %xmm3 + pand $in1_y(%rsp), %xmm2 + pand $in1_y+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + movdqu %xmm2, 0x20($r_ptr) + movdqu %xmm3, 0x30($r_ptr) + +.Ladd_done$x: + lea 32*18+56(%rsp), %rsi +.cfi_def_cfa %rsi,8 + mov -48(%rsi),%r15 +.cfi_restore %r15 + mov -40(%rsi),%r14 +.cfi_restore %r14 + mov -32(%rsi),%r13 +.cfi_restore %r13 + mov -24(%rsi),%r12 +.cfi_restore %r12 + mov -16(%rsi),%rbx +.cfi_restore %rbx + mov -8(%rsi),%rbp +.cfi_restore %rbp + lea (%rsi),%rsp +.cfi_def_cfa_register %rsp +.Lpoint_add${x}_epilogue: + ret +.cfi_endproc +.size ecp_nistz256_point_add$sfx,.-ecp_nistz256_point_add$sfx +___ +} +&gen_add("q"); + +sub gen_add_affine () { + my $x = shift; + my ($src0,$sfx,$bias); + my ($U2,$S2,$H,$R,$Hsqr,$Hcub,$Rsqr, + $res_x,$res_y,$res_z, + $in1_x,$in1_y,$in1_z, + $in2_x,$in2_y)=map(32*$_,(0..14)); + my $Z1sqr = $S2; + + if ($x ne "x") { + $src0 = "%rax"; + $sfx = ""; + $bias = 0; + +$code.=<<___; +.globl ecp_nistz256_point_add_affine +.type ecp_nistz256_point_add_affine,\@function,3 +.align 32 +ecp_nistz256_point_add_affine: +.cfi_startproc +___ +$code.=<<___ if ($addx); + mov \$0x80100, %ecx + and OPENSSL_ia32cap_P+8(%rip), %ecx + cmp \$0x80100, %ecx + je .Lpoint_add_affinex +___ + } else { + $src0 = "%rdx"; + $sfx = "x"; + $bias = 128; + +$code.=<<___; +.type ecp_nistz256_point_add_affinex,\@function,3 +.align 32 +ecp_nistz256_point_add_affinex: +.cfi_startproc +.Lpoint_add_affinex: +___ + } +$code.=<<___; + push %rbp +.cfi_push %rbp + push %rbx +.cfi_push %rbx + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + sub \$32*15+8, %rsp +.cfi_adjust_cfa_offset 32*15+8 +.Ladd_affine${x}_body: + + movdqu 0x00($a_ptr), %xmm0 # copy *(P256_POINT *)$a_ptr + mov $b_org, $b_ptr # reassign + movdqu 0x10($a_ptr), %xmm1 + movdqu 0x20($a_ptr), %xmm2 + movdqu 0x30($a_ptr), %xmm3 + movdqu 0x40($a_ptr), %xmm4 + movdqu 0x50($a_ptr), %xmm5 + mov 0x40+8*0($a_ptr), $src0 # load original in1_z + mov 0x40+8*1($a_ptr), $acc6 + mov 0x40+8*2($a_ptr), $acc7 + mov 0x40+8*3($a_ptr), $acc0 + movdqa %xmm0, $in1_x(%rsp) + movdqa %xmm1, $in1_x+0x10(%rsp) + movdqa %xmm2, $in1_y(%rsp) + movdqa %xmm3, $in1_y+0x10(%rsp) + movdqa %xmm4, $in1_z(%rsp) + movdqa %xmm5, $in1_z+0x10(%rsp) + por %xmm4, %xmm5 + + movdqu 0x00($b_ptr), %xmm0 # copy *(P256_POINT_AFFINE *)$b_ptr + pshufd \$0xb1, %xmm5, %xmm3 + movdqu 0x10($b_ptr), %xmm1 + movdqu 0x20($b_ptr), %xmm2 + por %xmm3, %xmm5 + movdqu 0x30($b_ptr), %xmm3 + movdqa %xmm0, $in2_x(%rsp) + pshufd \$0x1e, %xmm5, %xmm4 + movdqa %xmm1, $in2_x+0x10(%rsp) + por %xmm0, %xmm1 + movq $r_ptr, %xmm0 # save $r_ptr + movdqa %xmm2, $in2_y(%rsp) + movdqa %xmm3, $in2_y+0x10(%rsp) + por %xmm2, %xmm3 + por %xmm4, %xmm5 + pxor %xmm4, %xmm4 + por %xmm1, %xmm3 + + lea 0x40-$bias($a_ptr), $a_ptr # $a_ptr is still valid + lea $Z1sqr(%rsp), $r_ptr # Z1^2 + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(Z1sqr, in1_z); + + pcmpeqd %xmm4, %xmm5 + pshufd \$0xb1, %xmm3, %xmm4 + mov 0x00($b_ptr), $src0 # $b_ptr is still valid + #lea 0x00($b_ptr), $b_ptr + mov $acc4, $acc1 # harmonize sqr output and mul input + por %xmm3, %xmm4 + pshufd \$0, %xmm5, %xmm5 # in1infty + pshufd \$0x1e, %xmm4, %xmm3 + mov $acc5, $acc2 + por %xmm3, %xmm4 + pxor %xmm3, %xmm3 + mov $acc6, $acc3 + pcmpeqd %xmm3, %xmm4 + pshufd \$0, %xmm4, %xmm4 # in2infty + + lea $Z1sqr-$bias(%rsp), $a_ptr + mov $acc7, $acc4 + lea $U2(%rsp), $r_ptr # U2 = X2*Z1^2 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(U2, Z1sqr, in2_x); + + lea $in1_x(%rsp), $b_ptr + lea $H(%rsp), $r_ptr # H = U2 - U1 + call __ecp_nistz256_sub_from$x # p256_sub(H, U2, in1_x); + + `&load_for_mul("$Z1sqr(%rsp)", "$in1_z(%rsp)", "$src0")` + lea $S2(%rsp), $r_ptr # S2 = Z1^3 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S2, Z1sqr, in1_z); + + `&load_for_mul("$H(%rsp)", "$in1_z(%rsp)", "$src0")` + lea $res_z(%rsp), $r_ptr # Z3 = H*Z1*Z2 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(res_z, H, in1_z); + + `&load_for_mul("$S2(%rsp)", "$in2_y(%rsp)", "$src0")` + lea $S2(%rsp), $r_ptr # S2 = Y2*Z1^3 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S2, S2, in2_y); + + lea $in1_y(%rsp), $b_ptr + lea $R(%rsp), $r_ptr # R = S2 - S1 + call __ecp_nistz256_sub_from$x # p256_sub(R, S2, in1_y); + + `&load_for_sqr("$H(%rsp)", "$src0")` + lea $Hsqr(%rsp), $r_ptr # H^2 + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(Hsqr, H); + + `&load_for_sqr("$R(%rsp)", "$src0")` + lea $Rsqr(%rsp), $r_ptr # R^2 + call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(Rsqr, R); + + `&load_for_mul("$H(%rsp)", "$Hsqr(%rsp)", "$src0")` + lea $Hcub(%rsp), $r_ptr # H^3 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(Hcub, Hsqr, H); + + `&load_for_mul("$Hsqr(%rsp)", "$in1_x(%rsp)", "$src0")` + lea $U2(%rsp), $r_ptr # U1*H^2 + call __ecp_nistz256_mul_mont$x # p256_mul_mont(U2, in1_x, Hsqr); +___ +{ +####################################################################### +# operate in 4-5-0-1 "name space" that matches multiplication output +# +my ($acc0,$acc1,$acc2,$acc3,$t3,$t4)=($acc4,$acc5,$acc0,$acc1,$acc2,$acc3); +my ($poly1, $poly3)=($acc6,$acc7); + +$code.=<<___; + #lea $U2(%rsp), $a_ptr + #lea $Hsqr(%rsp), $r_ptr # 2*U1*H^2 + #call __ecp_nistz256_mul_by_2 # ecp_nistz256_mul_by_2(Hsqr, U2); + + xor $t4, $t4 + add $acc0, $acc0 # a0:a3+a0:a3 + lea $Rsqr(%rsp), $a_ptr + adc $acc1, $acc1 + mov $acc0, $t0 + adc $acc2, $acc2 + adc $acc3, $acc3 + mov $acc1, $t1 + adc \$0, $t4 + + sub \$-1, $acc0 + mov $acc2, $t2 + sbb $poly1, $acc1 + sbb \$0, $acc2 + mov $acc3, $t3 + sbb $poly3, $acc3 + sbb \$0, $t4 + + cmovc $t0, $acc0 + mov 8*0($a_ptr), $t0 + cmovc $t1, $acc1 + mov 8*1($a_ptr), $t1 + cmovc $t2, $acc2 + mov 8*2($a_ptr), $t2 + cmovc $t3, $acc3 + mov 8*3($a_ptr), $t3 + + call __ecp_nistz256_sub$x # p256_sub(res_x, Rsqr, Hsqr); + + lea $Hcub(%rsp), $b_ptr + lea $res_x(%rsp), $r_ptr + call __ecp_nistz256_sub_from$x # p256_sub(res_x, res_x, Hcub); + + mov $U2+8*0(%rsp), $t0 + mov $U2+8*1(%rsp), $t1 + mov $U2+8*2(%rsp), $t2 + mov $U2+8*3(%rsp), $t3 + lea $H(%rsp), $r_ptr + + call __ecp_nistz256_sub$x # p256_sub(H, U2, res_x); + + mov $acc0, 8*0($r_ptr) # save the result, as + mov $acc1, 8*1($r_ptr) # __ecp_nistz256_sub doesn't + mov $acc2, 8*2($r_ptr) + mov $acc3, 8*3($r_ptr) +___ +} +$code.=<<___; + `&load_for_mul("$Hcub(%rsp)", "$in1_y(%rsp)", "$src0")` + lea $S2(%rsp), $r_ptr + call __ecp_nistz256_mul_mont$x # p256_mul_mont(S2, Hcub, in1_y); + + `&load_for_mul("$H(%rsp)", "$R(%rsp)", "$src0")` + lea $H(%rsp), $r_ptr + call __ecp_nistz256_mul_mont$x # p256_mul_mont(H, H, R); + + lea $S2(%rsp), $b_ptr + lea $res_y(%rsp), $r_ptr + call __ecp_nistz256_sub_from$x # p256_sub(res_y, H, S2); + + movq %xmm0, $r_ptr # restore $r_ptr + + movdqa %xmm5, %xmm0 # copy_conditional(res_z, ONE, in1infty); + movdqa %xmm5, %xmm1 + pandn $res_z(%rsp), %xmm0 + movdqa %xmm5, %xmm2 + pandn $res_z+0x10(%rsp), %xmm1 + movdqa %xmm5, %xmm3 + pand .LONE_mont(%rip), %xmm2 + pand .LONE_mont+0x10(%rip), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + + movdqa %xmm4, %xmm0 # copy_conditional(res_z, in1_z, in2infty); + movdqa %xmm4, %xmm1 + pandn %xmm2, %xmm0 + movdqa %xmm4, %xmm2 + pandn %xmm3, %xmm1 + movdqa %xmm4, %xmm3 + pand $in1_z(%rsp), %xmm2 + pand $in1_z+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + movdqu %xmm2, 0x40($r_ptr) + movdqu %xmm3, 0x50($r_ptr) + + movdqa %xmm5, %xmm0 # copy_conditional(res_x, in2_x, in1infty); + movdqa %xmm5, %xmm1 + pandn $res_x(%rsp), %xmm0 + movdqa %xmm5, %xmm2 + pandn $res_x+0x10(%rsp), %xmm1 + movdqa %xmm5, %xmm3 + pand $in2_x(%rsp), %xmm2 + pand $in2_x+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + + movdqa %xmm4, %xmm0 # copy_conditional(res_x, in1_x, in2infty); + movdqa %xmm4, %xmm1 + pandn %xmm2, %xmm0 + movdqa %xmm4, %xmm2 + pandn %xmm3, %xmm1 + movdqa %xmm4, %xmm3 + pand $in1_x(%rsp), %xmm2 + pand $in1_x+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + movdqu %xmm2, 0x00($r_ptr) + movdqu %xmm3, 0x10($r_ptr) + + movdqa %xmm5, %xmm0 # copy_conditional(res_y, in2_y, in1infty); + movdqa %xmm5, %xmm1 + pandn $res_y(%rsp), %xmm0 + movdqa %xmm5, %xmm2 + pandn $res_y+0x10(%rsp), %xmm1 + movdqa %xmm5, %xmm3 + pand $in2_y(%rsp), %xmm2 + pand $in2_y+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + + movdqa %xmm4, %xmm0 # copy_conditional(res_y, in1_y, in2infty); + movdqa %xmm4, %xmm1 + pandn %xmm2, %xmm0 + movdqa %xmm4, %xmm2 + pandn %xmm3, %xmm1 + movdqa %xmm4, %xmm3 + pand $in1_y(%rsp), %xmm2 + pand $in1_y+0x10(%rsp), %xmm3 + por %xmm0, %xmm2 + por %xmm1, %xmm3 + movdqu %xmm2, 0x20($r_ptr) + movdqu %xmm3, 0x30($r_ptr) + + lea 32*15+56(%rsp), %rsi +.cfi_def_cfa %rsi,8 + mov -48(%rsi),%r15 +.cfi_restore %r15 + mov -40(%rsi),%r14 +.cfi_restore %r14 + mov -32(%rsi),%r13 +.cfi_restore %r13 + mov -24(%rsi),%r12 +.cfi_restore %r12 + mov -16(%rsi),%rbx +.cfi_restore %rbx + mov -8(%rsi),%rbp +.cfi_restore %rbp + lea (%rsi),%rsp +.cfi_def_cfa_register %rsp +.Ladd_affine${x}_epilogue: + ret +.cfi_endproc +.size ecp_nistz256_point_add_affine$sfx,.-ecp_nistz256_point_add_affine$sfx +___ +} +&gen_add_affine("q"); + +######################################################################## +# AD*X magic +# +if ($addx) { { +######################################################################## +# operate in 4-5-0-1 "name space" that matches multiplication output +# +my ($a0,$a1,$a2,$a3,$t3,$t4)=($acc4,$acc5,$acc0,$acc1,$acc2,$acc3); + +$code.=<<___; +.type __ecp_nistz256_add_tox,\@abi-omnipotent +.align 32 +__ecp_nistz256_add_tox: +.cfi_startproc + xor $t4, $t4 + adc 8*0($b_ptr), $a0 + adc 8*1($b_ptr), $a1 + mov $a0, $t0 + adc 8*2($b_ptr), $a2 + adc 8*3($b_ptr), $a3 + mov $a1, $t1 + adc \$0, $t4 + + xor $t3, $t3 + sbb \$-1, $a0 + mov $a2, $t2 + sbb $poly1, $a1 + sbb \$0, $a2 + mov $a3, $t3 + sbb $poly3, $a3 + sbb \$0, $t4 + + cmovc $t0, $a0 + cmovc $t1, $a1 + mov $a0, 8*0($r_ptr) + cmovc $t2, $a2 + mov $a1, 8*1($r_ptr) + cmovc $t3, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) + + ret +.cfi_endproc +.size __ecp_nistz256_add_tox,.-__ecp_nistz256_add_tox + +.type __ecp_nistz256_sub_fromx,\@abi-omnipotent +.align 32 +__ecp_nistz256_sub_fromx: +.cfi_startproc + xor $t4, $t4 + sbb 8*0($b_ptr), $a0 + sbb 8*1($b_ptr), $a1 + mov $a0, $t0 + sbb 8*2($b_ptr), $a2 + sbb 8*3($b_ptr), $a3 + mov $a1, $t1 + sbb \$0, $t4 + + xor $t3, $t3 + adc \$-1, $a0 + mov $a2, $t2 + adc $poly1, $a1 + adc \$0, $a2 + mov $a3, $t3 + adc $poly3, $a3 + + bt \$0, $t4 + cmovnc $t0, $a0 + cmovnc $t1, $a1 + mov $a0, 8*0($r_ptr) + cmovnc $t2, $a2 + mov $a1, 8*1($r_ptr) + cmovnc $t3, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) + + ret +.cfi_endproc +.size __ecp_nistz256_sub_fromx,.-__ecp_nistz256_sub_fromx + +.type __ecp_nistz256_subx,\@abi-omnipotent +.align 32 +__ecp_nistz256_subx: +.cfi_startproc + xor $t4, $t4 + sbb $a0, $t0 + sbb $a1, $t1 + mov $t0, $a0 + sbb $a2, $t2 + sbb $a3, $t3 + mov $t1, $a1 + sbb \$0, $t4 + + xor $a3 ,$a3 + adc \$-1, $t0 + mov $t2, $a2 + adc $poly1, $t1 + adc \$0, $t2 + mov $t3, $a3 + adc $poly3, $t3 + + bt \$0, $t4 + cmovc $t0, $a0 + cmovc $t1, $a1 + cmovc $t2, $a2 + cmovc $t3, $a3 + + ret +.cfi_endproc +.size __ecp_nistz256_subx,.-__ecp_nistz256_subx + +.type __ecp_nistz256_mul_by_2x,\@abi-omnipotent +.align 32 +__ecp_nistz256_mul_by_2x: +.cfi_startproc + xor $t4, $t4 + adc $a0, $a0 # a0:a3+a0:a3 + adc $a1, $a1 + mov $a0, $t0 + adc $a2, $a2 + adc $a3, $a3 + mov $a1, $t1 + adc \$0, $t4 + + xor $t3, $t3 + sbb \$-1, $a0 + mov $a2, $t2 + sbb $poly1, $a1 + sbb \$0, $a2 + mov $a3, $t3 + sbb $poly3, $a3 + sbb \$0, $t4 + + cmovc $t0, $a0 + cmovc $t1, $a1 + mov $a0, 8*0($r_ptr) + cmovc $t2, $a2 + mov $a1, 8*1($r_ptr) + cmovc $t3, $a3 + mov $a2, 8*2($r_ptr) + mov $a3, 8*3($r_ptr) + + ret +.cfi_endproc +.size __ecp_nistz256_mul_by_2x,.-__ecp_nistz256_mul_by_2x +___ + } +&gen_double("x"); +&gen_add("x"); +&gen_add_affine("x"); +} +}}} + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind + +.type short_handler,\@abi-omnipotent +.align 16 +short_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # end of prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lcommon_seh_tail + + lea 16(%rax),%rax + + mov -8(%rax),%r12 + mov -16(%rax),%r13 + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + + jmp .Lcommon_seh_tail +.size short_handler,.-short_handler + +.type full_handler,\@abi-omnipotent +.align 16 +full_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # end of prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lcommon_seh_tail + + mov 8(%r11),%r10d # HandlerData[2] + lea (%rax,%r10),%rax + + mov -8(%rax),%rbp + mov -16(%rax),%rbx + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov -48(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + +.Lcommon_seh_tail: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size full_handler,.-full_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_ecp_nistz256_mul_by_2 + .rva .LSEH_end_ecp_nistz256_mul_by_2 + .rva .LSEH_info_ecp_nistz256_mul_by_2 + + .rva .LSEH_begin_ecp_nistz256_div_by_2 + .rva .LSEH_end_ecp_nistz256_div_by_2 + .rva .LSEH_info_ecp_nistz256_div_by_2 + + .rva .LSEH_begin_ecp_nistz256_mul_by_3 + .rva .LSEH_end_ecp_nistz256_mul_by_3 + .rva .LSEH_info_ecp_nistz256_mul_by_3 + + .rva .LSEH_begin_ecp_nistz256_add + .rva .LSEH_end_ecp_nistz256_add + .rva .LSEH_info_ecp_nistz256_add + + .rva .LSEH_begin_ecp_nistz256_sub + .rva .LSEH_end_ecp_nistz256_sub + .rva .LSEH_info_ecp_nistz256_sub + + .rva .LSEH_begin_ecp_nistz256_neg + .rva .LSEH_end_ecp_nistz256_neg + .rva .LSEH_info_ecp_nistz256_neg + + .rva .LSEH_begin_ecp_nistz256_ord_mul_mont + .rva .LSEH_end_ecp_nistz256_ord_mul_mont + .rva .LSEH_info_ecp_nistz256_ord_mul_mont + + .rva .LSEH_begin_ecp_nistz256_ord_sqr_mont + .rva .LSEH_end_ecp_nistz256_ord_sqr_mont + .rva .LSEH_info_ecp_nistz256_ord_sqr_mont +___ +$code.=<<___ if ($addx); + .rva .LSEH_begin_ecp_nistz256_ord_mul_montx + .rva .LSEH_end_ecp_nistz256_ord_mul_montx + .rva .LSEH_info_ecp_nistz256_ord_mul_montx + + .rva .LSEH_begin_ecp_nistz256_ord_sqr_montx + .rva .LSEH_end_ecp_nistz256_ord_sqr_montx + .rva .LSEH_info_ecp_nistz256_ord_sqr_montx +___ +$code.=<<___; + .rva .LSEH_begin_ecp_nistz256_to_mont + .rva .LSEH_end_ecp_nistz256_to_mont + .rva .LSEH_info_ecp_nistz256_to_mont + + .rva .LSEH_begin_ecp_nistz256_mul_mont + .rva .LSEH_end_ecp_nistz256_mul_mont + .rva .LSEH_info_ecp_nistz256_mul_mont + + .rva .LSEH_begin_ecp_nistz256_sqr_mont + .rva .LSEH_end_ecp_nistz256_sqr_mont + .rva .LSEH_info_ecp_nistz256_sqr_mont + + .rva .LSEH_begin_ecp_nistz256_from_mont + .rva .LSEH_end_ecp_nistz256_from_mont + .rva .LSEH_info_ecp_nistz256_from_mont + + .rva .LSEH_begin_ecp_nistz256_gather_w5 + .rva .LSEH_end_ecp_nistz256_gather_w5 + .rva .LSEH_info_ecp_nistz256_gather_wX + + .rva .LSEH_begin_ecp_nistz256_gather_w7 + .rva .LSEH_end_ecp_nistz256_gather_w7 + .rva .LSEH_info_ecp_nistz256_gather_wX +___ +$code.=<<___ if ($avx>1); + .rva .LSEH_begin_ecp_nistz256_avx2_gather_w5 + .rva .LSEH_end_ecp_nistz256_avx2_gather_w5 + .rva .LSEH_info_ecp_nistz256_avx2_gather_wX + + .rva .LSEH_begin_ecp_nistz256_avx2_gather_w7 + .rva .LSEH_end_ecp_nistz256_avx2_gather_w7 + .rva .LSEH_info_ecp_nistz256_avx2_gather_wX +___ +$code.=<<___; + .rva .LSEH_begin_ecp_nistz256_point_double + .rva .LSEH_end_ecp_nistz256_point_double + .rva .LSEH_info_ecp_nistz256_point_double + + .rva .LSEH_begin_ecp_nistz256_point_add + .rva .LSEH_end_ecp_nistz256_point_add + .rva .LSEH_info_ecp_nistz256_point_add + + .rva .LSEH_begin_ecp_nistz256_point_add_affine + .rva .LSEH_end_ecp_nistz256_point_add_affine + .rva .LSEH_info_ecp_nistz256_point_add_affine +___ +$code.=<<___ if ($addx); + .rva .LSEH_begin_ecp_nistz256_point_doublex + .rva .LSEH_end_ecp_nistz256_point_doublex + .rva .LSEH_info_ecp_nistz256_point_doublex + + .rva .LSEH_begin_ecp_nistz256_point_addx + .rva .LSEH_end_ecp_nistz256_point_addx + .rva .LSEH_info_ecp_nistz256_point_addx + + .rva .LSEH_begin_ecp_nistz256_point_add_affinex + .rva .LSEH_end_ecp_nistz256_point_add_affinex + .rva .LSEH_info_ecp_nistz256_point_add_affinex +___ +$code.=<<___; + +.section .xdata +.align 8 +.LSEH_info_ecp_nistz256_mul_by_2: + .byte 9,0,0,0 + .rva short_handler + .rva .Lmul_by_2_body,.Lmul_by_2_epilogue # HandlerData[] +.LSEH_info_ecp_nistz256_div_by_2: + .byte 9,0,0,0 + .rva short_handler + .rva .Ldiv_by_2_body,.Ldiv_by_2_epilogue # HandlerData[] +.LSEH_info_ecp_nistz256_mul_by_3: + .byte 9,0,0,0 + .rva short_handler + .rva .Lmul_by_3_body,.Lmul_by_3_epilogue # HandlerData[] +.LSEH_info_ecp_nistz256_add: + .byte 9,0,0,0 + .rva short_handler + .rva .Ladd_body,.Ladd_epilogue # HandlerData[] +.LSEH_info_ecp_nistz256_sub: + .byte 9,0,0,0 + .rva short_handler + .rva .Lsub_body,.Lsub_epilogue # HandlerData[] +.LSEH_info_ecp_nistz256_neg: + .byte 9,0,0,0 + .rva short_handler + .rva .Lneg_body,.Lneg_epilogue # HandlerData[] +.LSEH_info_ecp_nistz256_ord_mul_mont: + .byte 9,0,0,0 + .rva full_handler + .rva .Lord_mul_body,.Lord_mul_epilogue # HandlerData[] + .long 48,0 +.LSEH_info_ecp_nistz256_ord_sqr_mont: + .byte 9,0,0,0 + .rva full_handler + .rva .Lord_sqr_body,.Lord_sqr_epilogue # HandlerData[] + .long 48,0 +___ +$code.=<<___ if ($addx); +.LSEH_info_ecp_nistz256_ord_mul_montx: + .byte 9,0,0,0 + .rva full_handler + .rva .Lord_mulx_body,.Lord_mulx_epilogue # HandlerData[] + .long 48,0 +.LSEH_info_ecp_nistz256_ord_sqr_montx: + .byte 9,0,0,0 + .rva full_handler + .rva .Lord_sqrx_body,.Lord_sqrx_epilogue # HandlerData[] + .long 48,0 +___ +$code.=<<___; +.LSEH_info_ecp_nistz256_to_mont: + .byte 9,0,0,0 + .rva full_handler + .rva .Lmul_body,.Lmul_epilogue # HandlerData[] + .long 48,0 +.LSEH_info_ecp_nistz256_mul_mont: + .byte 9,0,0,0 + .rva full_handler + .rva .Lmul_body,.Lmul_epilogue # HandlerData[] + .long 48,0 +.LSEH_info_ecp_nistz256_sqr_mont: + .byte 9,0,0,0 + .rva full_handler + .rva .Lsqr_body,.Lsqr_epilogue # HandlerData[] + .long 48,0 +.LSEH_info_ecp_nistz256_from_mont: + .byte 9,0,0,0 + .rva short_handler + .rva .Lfrom_body,.Lfrom_epilogue # HandlerData[] +.LSEH_info_ecp_nistz256_gather_wX: + .byte 0x01,0x33,0x16,0x00 + .byte 0x33,0xf8,0x09,0x00 #movaps 0x90(rsp),xmm15 + .byte 0x2e,0xe8,0x08,0x00 #movaps 0x80(rsp),xmm14 + .byte 0x29,0xd8,0x07,0x00 #movaps 0x70(rsp),xmm13 + .byte 0x24,0xc8,0x06,0x00 #movaps 0x60(rsp),xmm12 + .byte 0x1f,0xb8,0x05,0x00 #movaps 0x50(rsp),xmm11 + .byte 0x1a,0xa8,0x04,0x00 #movaps 0x40(rsp),xmm10 + .byte 0x15,0x98,0x03,0x00 #movaps 0x30(rsp),xmm9 + .byte 0x10,0x88,0x02,0x00 #movaps 0x20(rsp),xmm8 + .byte 0x0c,0x78,0x01,0x00 #movaps 0x10(rsp),xmm7 + .byte 0x08,0x68,0x00,0x00 #movaps 0x00(rsp),xmm6 + .byte 0x04,0x01,0x15,0x00 #sub rsp,0xa8 + .align 8 +___ +$code.=<<___ if ($avx>1); +.LSEH_info_ecp_nistz256_avx2_gather_wX: + .byte 0x01,0x36,0x17,0x0b + .byte 0x36,0xf8,0x09,0x00 # vmovaps 0x90(rsp),xmm15 + .byte 0x31,0xe8,0x08,0x00 # vmovaps 0x80(rsp),xmm14 + .byte 0x2c,0xd8,0x07,0x00 # vmovaps 0x70(rsp),xmm13 + .byte 0x27,0xc8,0x06,0x00 # vmovaps 0x60(rsp),xmm12 + .byte 0x22,0xb8,0x05,0x00 # vmovaps 0x50(rsp),xmm11 + .byte 0x1d,0xa8,0x04,0x00 # vmovaps 0x40(rsp),xmm10 + .byte 0x18,0x98,0x03,0x00 # vmovaps 0x30(rsp),xmm9 + .byte 0x13,0x88,0x02,0x00 # vmovaps 0x20(rsp),xmm8 + .byte 0x0e,0x78,0x01,0x00 # vmovaps 0x10(rsp),xmm7 + .byte 0x09,0x68,0x00,0x00 # vmovaps 0x00(rsp),xmm6 + .byte 0x04,0x01,0x15,0x00 # sub rsp,0xa8 + .byte 0x00,0xb3,0x00,0x00 # set_frame r11 + .align 8 +___ +$code.=<<___; +.LSEH_info_ecp_nistz256_point_double: + .byte 9,0,0,0 + .rva full_handler + .rva .Lpoint_doubleq_body,.Lpoint_doubleq_epilogue # HandlerData[] + .long 32*5+56,0 +.LSEH_info_ecp_nistz256_point_add: + .byte 9,0,0,0 + .rva full_handler + .rva .Lpoint_addq_body,.Lpoint_addq_epilogue # HandlerData[] + .long 32*18+56,0 +.LSEH_info_ecp_nistz256_point_add_affine: + .byte 9,0,0,0 + .rva full_handler + .rva .Ladd_affineq_body,.Ladd_affineq_epilogue # HandlerData[] + .long 32*15+56,0 +___ +$code.=<<___ if ($addx); +.align 8 +.LSEH_info_ecp_nistz256_point_doublex: + .byte 9,0,0,0 + .rva full_handler + .rva .Lpoint_doublex_body,.Lpoint_doublex_epilogue # HandlerData[] + .long 32*5+56,0 +.LSEH_info_ecp_nistz256_point_addx: + .byte 9,0,0,0 + .rva full_handler + .rva .Lpoint_addx_body,.Lpoint_addx_epilogue # HandlerData[] + .long 32*18+56,0 +.LSEH_info_ecp_nistz256_point_add_affinex: + .byte 9,0,0,0 + .rva full_handler + .rva .Ladd_affinex_body,.Ladd_affinex_epilogue # HandlerData[] + .long 32*15+56,0 +___ +} + +######################################################################## +# Convert ecp_nistz256_table.c to layout expected by ecp_nistz_gather_w7 +# +open TABLE,") { + s/TOBN\(\s*(0x[0-9a-f]+),\s*(0x[0-9a-f]+)\s*\)/push @arr,hex($2),hex($1)/geo; +} +close TABLE; + +die "insane number of elements" if ($#arr != 64*16*37-1); + +print <<___; +.text +.globl ecp_nistz256_precomputed +.type ecp_nistz256_precomputed,\@object +.align 4096 +ecp_nistz256_precomputed: +___ +while (@line=splice(@arr,0,16)) { + print ".long\t",join(',',map { sprintf "0x%08x",$_} @line),"\n"; +} +print <<___; +.size ecp_nistz256_precomputed,.-ecp_nistz256_precomputed +___ + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/x25519-ppc64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/x25519-ppc64.pl new file mode 100755 index 000000000..3773cb27c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/x25519-ppc64.pl @@ -0,0 +1,824 @@ +#! /usr/bin/env perl +# Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# X25519 lower-level primitives for PPC64. +# +# July 2018. +# +# Base 2^64 is faster than base 2^51 on pre-POWER8, most notably ~15% +# faster on PPC970/G5. POWER8 on the other hand seems to trip on own +# shoelaces when handling longer carry chains. As base 2^51 has just +# single-carry pairs, it's 25% faster than base 2^64. Since PPC970 is +# pretty old, base 2^64 implementation is not engaged. Comparison to +# compiler-generated code is complicated by the fact that not all +# compilers support 128-bit integers. When compiler doesn't, like xlc, +# this module delivers more than 2x improvement, and when it does, +# from 12% to 30% improvement was measured... + +$flavour = shift; +while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or +die "can't locate ppc-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +my $sp = "r1"; +my ($rp,$ap,$bp) = map("r$_",3..5); + +####################################################### base 2^64 +if (0) { +my ($bi,$a0,$a1,$a2,$a3,$t0,$t1, $t2,$t3, + $acc0,$acc1,$acc2,$acc3,$acc4,$acc5,$acc6,$acc7) = + map("r$_",(6..12,22..31)); +my $zero = "r0"; +my $FRAME = 16*8; + +$code.=<<___; +.text + +.globl x25519_fe64_mul +.type x25519_fe64_mul,\@function +.align 5 +x25519_fe64_mul: + stdu $sp,-$FRAME($sp) + std r22,`$FRAME-8*10`($sp) + std r23,`$FRAME-8*9`($sp) + std r24,`$FRAME-8*8`($sp) + std r25,`$FRAME-8*7`($sp) + std r26,`$FRAME-8*6`($sp) + std r27,`$FRAME-8*5`($sp) + std r28,`$FRAME-8*4`($sp) + std r29,`$FRAME-8*3`($sp) + std r30,`$FRAME-8*2`($sp) + std r31,`$FRAME-8*1`($sp) + + ld $bi,0($bp) + ld $a0,0($ap) + xor $zero,$zero,$zero + ld $a1,8($ap) + ld $a2,16($ap) + ld $a3,24($ap) + + mulld $acc0,$a0,$bi # a[0]*b[0] + mulhdu $t0,$a0,$bi + mulld $acc1,$a1,$bi # a[1]*b[0] + mulhdu $t1,$a1,$bi + mulld $acc2,$a2,$bi # a[2]*b[0] + mulhdu $t2,$a2,$bi + mulld $acc3,$a3,$bi # a[3]*b[0] + mulhdu $t3,$a3,$bi +___ +for(my @acc=($acc0,$acc1,$acc2,$acc3,$acc4,$acc5,$acc6,$acc7), + my $i=1; $i<4; shift(@acc), $i++) { +my $acc4 = $i==1? $zero : @acc[4]; + +$code.=<<___; + ld $bi,`8*$i`($bp) + addc @acc[1],@acc[1],$t0 # accumulate high parts + mulld $t0,$a0,$bi + adde @acc[2],@acc[2],$t1 + mulld $t1,$a1,$bi + adde @acc[3],@acc[3],$t2 + mulld $t2,$a2,$bi + adde @acc[4],$acc4,$t3 + mulld $t3,$a3,$bi + addc @acc[1],@acc[1],$t0 # accumulate low parts + mulhdu $t0,$a0,$bi + adde @acc[2],@acc[2],$t1 + mulhdu $t1,$a1,$bi + adde @acc[3],@acc[3],$t2 + mulhdu $t2,$a2,$bi + adde @acc[4],@acc[4],$t3 + mulhdu $t3,$a3,$bi + adde @acc[5],$zero,$zero +___ +} +$code.=<<___; + li $bi,38 + addc $acc4,$acc4,$t0 + mulld $t0,$acc4,$bi + adde $acc5,$acc5,$t1 + mulld $t1,$acc5,$bi + adde $acc6,$acc6,$t2 + mulld $t2,$acc6,$bi + adde $acc7,$acc7,$t3 + mulld $t3,$acc7,$bi + + addc $acc0,$acc0,$t0 + mulhdu $t0,$acc4,$bi + adde $acc1,$acc1,$t1 + mulhdu $t1,$acc5,$bi + adde $acc2,$acc2,$t2 + mulhdu $t2,$acc6,$bi + adde $acc3,$acc3,$t3 + mulhdu $t3,$acc7,$bi + adde $acc4,$zero,$zero + + addc $acc1,$acc1,$t0 + adde $acc2,$acc2,$t1 + adde $acc3,$acc3,$t2 + adde $acc4,$acc4,$t3 + + mulld $acc4,$acc4,$bi + + addc $acc0,$acc0,$acc4 + addze $acc1,$acc1 + addze $acc2,$acc2 + addze $acc3,$acc3 + + subfe $acc4,$acc4,$acc4 # carry -> ~mask + std $acc1,8($rp) + andc $acc4,$bi,$acc4 + std $acc2,16($rp) + add $acc0,$acc0,$acc4 + std $acc3,24($rp) + std $acc0,0($rp) + + ld r22,`$FRAME-8*10`($sp) + ld r23,`$FRAME-8*9`($sp) + ld r24,`$FRAME-8*8`($sp) + ld r25,`$FRAME-8*7`($sp) + ld r26,`$FRAME-8*6`($sp) + ld r27,`$FRAME-8*5`($sp) + ld r28,`$FRAME-8*4`($sp) + ld r29,`$FRAME-8*3`($sp) + ld r30,`$FRAME-8*2`($sp) + ld r31,`$FRAME-8*1`($sp) + addi $sp,$sp,$FRAME + blr + .long 0 + .byte 0,12,4,0,0x80,10,3,0 + .long 0 +.size x25519_fe64_mul,.-x25519_fe64_mul + +.globl x25519_fe64_sqr +.type x25519_fe64_sqr,\@function +.align 5 +x25519_fe64_sqr: + stdu $sp,-$FRAME($sp) + std r22,`$FRAME-8*10`($sp) + std r23,`$FRAME-8*9`($sp) + std r24,`$FRAME-8*8`($sp) + std r25,`$FRAME-8*7`($sp) + std r26,`$FRAME-8*6`($sp) + std r27,`$FRAME-8*5`($sp) + std r28,`$FRAME-8*4`($sp) + std r29,`$FRAME-8*3`($sp) + std r30,`$FRAME-8*2`($sp) + std r31,`$FRAME-8*1`($sp) + + ld $a0,0($ap) + xor $zero,$zero,$zero + ld $a1,8($ap) + ld $a2,16($ap) + ld $a3,24($ap) + + ################################ + # | | | | | |a1*a0| | + # | | | | |a2*a0| | | + # | |a3*a2|a3*a0| | | | + # | | | |a2*a1| | | | + # | | |a3*a1| | | | | + # *| | | | | | | | 2| + # +|a3*a3|a2*a2|a1*a1|a0*a0| + # |--+--+--+--+--+--+--+--| + # |A7|A6|A5|A4|A3|A2|A1|A0|, where Ax is $accx, i.e. follow $accx + # + # "can't overflow" below mark carrying into high part of + # multiplication result, which can't overflow, because it + # can never be all ones. + + mulld $acc1,$a1,$a0 # a[1]*a[0] + mulhdu $t1,$a1,$a0 + mulld $acc2,$a2,$a0 # a[2]*a[0] + mulhdu $t2,$a2,$a0 + mulld $acc3,$a3,$a0 # a[3]*a[0] + mulhdu $acc4,$a3,$a0 + + addc $acc2,$acc2,$t1 # accumulate high parts of multiplication + mulld $t0,$a2,$a1 # a[2]*a[1] + mulhdu $t1,$a2,$a1 + adde $acc3,$acc3,$t2 + mulld $t2,$a3,$a1 # a[3]*a[1] + mulhdu $t3,$a3,$a1 + addze $acc4,$acc4 # can't overflow + + mulld $acc5,$a3,$a2 # a[3]*a[2] + mulhdu $acc6,$a3,$a2 + + addc $t1,$t1,$t2 # accumulate high parts of multiplication + mulld $acc0,$a0,$a0 # a[0]*a[0] + addze $t2,$t3 # can't overflow + + addc $acc3,$acc3,$t0 # accumulate low parts of multiplication + mulhdu $a0,$a0,$a0 + adde $acc4,$acc4,$t1 + mulld $t1,$a1,$a1 # a[1]*a[1] + adde $acc5,$acc5,$t2 + mulhdu $a1,$a1,$a1 + addze $acc6,$acc6 # can't overflow + + addc $acc1,$acc1,$acc1 # acc[1-6]*=2 + mulld $t2,$a2,$a2 # a[2]*a[2] + adde $acc2,$acc2,$acc2 + mulhdu $a2,$a2,$a2 + adde $acc3,$acc3,$acc3 + mulld $t3,$a3,$a3 # a[3]*a[3] + adde $acc4,$acc4,$acc4 + mulhdu $a3,$a3,$a3 + adde $acc5,$acc5,$acc5 + adde $acc6,$acc6,$acc6 + addze $acc7,$zero + + addc $acc1,$acc1,$a0 # +a[i]*a[i] + li $bi,38 + adde $acc2,$acc2,$t1 + adde $acc3,$acc3,$a1 + adde $acc4,$acc4,$t2 + adde $acc5,$acc5,$a2 + adde $acc6,$acc6,$t3 + adde $acc7,$acc7,$a3 + + mulld $t0,$acc4,$bi + mulld $t1,$acc5,$bi + mulld $t2,$acc6,$bi + mulld $t3,$acc7,$bi + + addc $acc0,$acc0,$t0 + mulhdu $t0,$acc4,$bi + adde $acc1,$acc1,$t1 + mulhdu $t1,$acc5,$bi + adde $acc2,$acc2,$t2 + mulhdu $t2,$acc6,$bi + adde $acc3,$acc3,$t3 + mulhdu $t3,$acc7,$bi + addze $acc4,$zero + + addc $acc1,$acc1,$t0 + adde $acc2,$acc2,$t1 + adde $acc3,$acc3,$t2 + adde $acc4,$acc4,$t3 + + mulld $acc4,$acc4,$bi + + addc $acc0,$acc0,$acc4 + addze $acc1,$acc1 + addze $acc2,$acc2 + addze $acc3,$acc3 + + subfe $acc4,$acc4,$acc4 # carry -> ~mask + std $acc1,8($rp) + andc $acc4,$bi,$acc4 + std $acc2,16($rp) + add $acc0,$acc0,$acc4 + std $acc3,24($rp) + std $acc0,0($rp) + + ld r22,`$FRAME-8*10`($sp) + ld r23,`$FRAME-8*9`($sp) + ld r24,`$FRAME-8*8`($sp) + ld r25,`$FRAME-8*7`($sp) + ld r26,`$FRAME-8*6`($sp) + ld r27,`$FRAME-8*5`($sp) + ld r28,`$FRAME-8*4`($sp) + ld r29,`$FRAME-8*3`($sp) + ld r30,`$FRAME-8*2`($sp) + ld r31,`$FRAME-8*1`($sp) + addi $sp,$sp,$FRAME + blr + .long 0 + .byte 0,12,4,0,0x80,10,2,0 + .long 0 +.size x25519_fe64_sqr,.-x25519_fe64_sqr + +.globl x25519_fe64_mul121666 +.type x25519_fe64_mul121666,\@function +.align 5 +x25519_fe64_mul121666: + lis $bi,`65536>>16` + ori $bi,$bi,`121666-65536` + + ld $t0,0($ap) + ld $t1,8($ap) + ld $bp,16($ap) + ld $ap,24($ap) + + mulld $a0,$t0,$bi + mulhdu $t0,$t0,$bi + mulld $a1,$t1,$bi + mulhdu $t1,$t1,$bi + mulld $a2,$bp,$bi + mulhdu $bp,$bp,$bi + mulld $a3,$ap,$bi + mulhdu $ap,$ap,$bi + + addc $a1,$a1,$t0 + adde $a2,$a2,$t1 + adde $a3,$a3,$bp + addze $ap, $ap + + mulli $ap,$ap,38 + + addc $a0,$a0,$ap + addze $a1,$a1 + addze $a2,$a2 + addze $a3,$a3 + + subfe $t1,$t1,$t1 # carry -> ~mask + std $a1,8($rp) + andc $t0,$t0,$t1 + std $a2,16($rp) + add $a0,$a0,$t0 + std $a3,24($rp) + std $a0,0($rp) + + blr + .long 0 + .byte 0,12,0x14,0,0,0,2,0 + .long 0 +.size x25519_fe64_mul121666,.-x25519_fe64_mul121666 + +.globl x25519_fe64_add +.type x25519_fe64_add,\@function +.align 5 +x25519_fe64_add: + ld $a0,0($ap) + ld $t0,0($bp) + ld $a1,8($ap) + ld $t1,8($bp) + ld $a2,16($ap) + ld $bi,16($bp) + ld $a3,24($ap) + ld $bp,24($bp) + + addc $a0,$a0,$t0 + adde $a1,$a1,$t1 + adde $a2,$a2,$bi + adde $a3,$a3,$bp + + li $t0,38 + subfe $t1,$t1,$t1 # carry -> ~mask + andc $t1,$t0,$t1 + + addc $a0,$a0,$t1 + addze $a1,$a1 + addze $a2,$a2 + addze $a3,$a3 + + subfe $t1,$t1,$t1 # carry -> ~mask + std $a1,8($rp) + andc $t0,$t0,$t1 + std $a2,16($rp) + add $a0,$a0,$t0 + std $a3,24($rp) + std $a0,0($rp) + + blr + .long 0 + .byte 0,12,0x14,0,0,0,3,0 + .long 0 +.size x25519_fe64_add,.-x25519_fe64_add + +.globl x25519_fe64_sub +.type x25519_fe64_sub,\@function +.align 5 +x25519_fe64_sub: + ld $a0,0($ap) + ld $t0,0($bp) + ld $a1,8($ap) + ld $t1,8($bp) + ld $a2,16($ap) + ld $bi,16($bp) + ld $a3,24($ap) + ld $bp,24($bp) + + subfc $a0,$t0,$a0 + subfe $a1,$t1,$a1 + subfe $a2,$bi,$a2 + subfe $a3,$bp,$a3 + + li $t0,38 + subfe $t1,$t1,$t1 # borrow -> mask + xor $zero,$zero,$zero + and $t1,$t0,$t1 + + subfc $a0,$t1,$a0 + subfe $a1,$zero,$a1 + subfe $a2,$zero,$a2 + subfe $a3,$zero,$a3 + + subfe $t1,$t1,$t1 # borrow -> mask + std $a1,8($rp) + and $t0,$t0,$t1 + std $a2,16($rp) + subf $a0,$t0,$a0 + std $a3,24($rp) + std $a0,0($rp) + + blr + .long 0 + .byte 0,12,0x14,0,0,0,3,0 + .long 0 +.size x25519_fe64_sub,.-x25519_fe64_sub + +.globl x25519_fe64_tobytes +.type x25519_fe64_tobytes,\@function +.align 5 +x25519_fe64_tobytes: + ld $a3,24($ap) + ld $a0,0($ap) + ld $a1,8($ap) + ld $a2,16($ap) + + sradi $t0,$a3,63 # most significant bit -> mask + li $t1,19 + and $t0,$t0,$t1 + sldi $a3,$a3,1 + add $t0,$t0,$t1 # compare to modulus in the same go + srdi $a3,$a3,1 # most signifcant bit cleared + + addc $a0,$a0,$t0 + addze $a1,$a1 + addze $a2,$a2 + addze $a3,$a3 + + xor $zero,$zero,$zero + sradi $t0,$a3,63 # most significant bit -> mask + sldi $a3,$a3,1 + andc $t0,$t1,$t0 + srdi $a3,$a3,1 # most signifcant bit cleared + + subi $rp,$rp,1 + subfc $a0,$t0,$a0 + subfe $a1,$zero,$a1 + subfe $a2,$zero,$a2 + subfe $a3,$zero,$a3 + +___ +for (my @a=($a0,$a1,$a2,$a3), my $i=0; $i<4; shift(@a), $i++) { +$code.=<<___; + srdi $t0,@a[0],8 + stbu @a[0],1($rp) + srdi @a[0],@a[0],16 + stbu $t0,1($rp) + srdi $t0,@a[0],8 + stbu @a[0],1($rp) + srdi @a[0],@a[0],16 + stbu $t0,1($rp) + srdi $t0,@a[0],8 + stbu @a[0],1($rp) + srdi @a[0],@a[0],16 + stbu $t0,1($rp) + srdi $t0,@a[0],8 + stbu @a[0],1($rp) + stbu $t0,1($rp) +___ +} +$code.=<<___; + blr + .long 0 + .byte 0,12,0x14,0,0,0,2,0 + .long 0 +.size x25519_fe64_tobytes,.-x25519_fe64_tobytes +___ +} +####################################################### base 2^51 +{ +my ($bi,$a0,$a1,$a2,$a3,$a4,$t0, $t1, + $h0lo,$h0hi,$h1lo,$h1hi,$h2lo,$h2hi,$h3lo,$h3hi,$h4lo,$h4hi) = + map("r$_",(6..12,21..31)); +my $mask = "r0"; +my $FRAME = 18*8; + +$code.=<<___; +.text + +.globl x25519_fe51_mul +.type x25519_fe51_mul,\@function +.align 5 +x25519_fe51_mul: + stdu $sp,-$FRAME($sp) + std r21,`$FRAME-8*11`($sp) + std r22,`$FRAME-8*10`($sp) + std r23,`$FRAME-8*9`($sp) + std r24,`$FRAME-8*8`($sp) + std r25,`$FRAME-8*7`($sp) + std r26,`$FRAME-8*6`($sp) + std r27,`$FRAME-8*5`($sp) + std r28,`$FRAME-8*4`($sp) + std r29,`$FRAME-8*3`($sp) + std r30,`$FRAME-8*2`($sp) + std r31,`$FRAME-8*1`($sp) + + ld $bi,0($bp) + ld $a0,0($ap) + ld $a1,8($ap) + ld $a2,16($ap) + ld $a3,24($ap) + ld $a4,32($ap) + + mulld $h0lo,$a0,$bi # a[0]*b[0] + mulhdu $h0hi,$a0,$bi + + mulld $h1lo,$a1,$bi # a[1]*b[0] + mulhdu $h1hi,$a1,$bi + + mulld $h4lo,$a4,$bi # a[4]*b[0] + mulhdu $h4hi,$a4,$bi + ld $ap,8($bp) + mulli $a4,$a4,19 + + mulld $h2lo,$a2,$bi # a[2]*b[0] + mulhdu $h2hi,$a2,$bi + + mulld $h3lo,$a3,$bi # a[3]*b[0] + mulhdu $h3hi,$a3,$bi +___ +for(my @a=($a0,$a1,$a2,$a3,$a4), + my $i=1; $i<4; $i++) { + ($ap,$bi) = ($bi,$ap); +$code.=<<___; + mulld $t0,@a[4],$bi + mulhdu $t1,@a[4],$bi + addc $h0lo,$h0lo,$t0 + adde $h0hi,$h0hi,$t1 + + mulld $t0,@a[0],$bi + mulhdu $t1,@a[0],$bi + addc $h1lo,$h1lo,$t0 + adde $h1hi,$h1hi,$t1 + + mulld $t0,@a[3],$bi + mulhdu $t1,@a[3],$bi + ld $ap,`8*($i+1)`($bp) + mulli @a[3],@a[3],19 + addc $h4lo,$h4lo,$t0 + adde $h4hi,$h4hi,$t1 + + mulld $t0,@a[1],$bi + mulhdu $t1,@a[1],$bi + addc $h2lo,$h2lo,$t0 + adde $h2hi,$h2hi,$t1 + + mulld $t0,@a[2],$bi + mulhdu $t1,@a[2],$bi + addc $h3lo,$h3lo,$t0 + adde $h3hi,$h3hi,$t1 +___ + unshift(@a,pop(@a)); +} + ($ap,$bi) = ($bi,$ap); +$code.=<<___; + mulld $t0,$a1,$bi + mulhdu $t1,$a1,$bi + addc $h0lo,$h0lo,$t0 + adde $h0hi,$h0hi,$t1 + + mulld $t0,$a2,$bi + mulhdu $t1,$a2,$bi + addc $h1lo,$h1lo,$t0 + adde $h1hi,$h1hi,$t1 + + mulld $t0,$a3,$bi + mulhdu $t1,$a3,$bi + addc $h2lo,$h2lo,$t0 + adde $h2hi,$h2hi,$t1 + + mulld $t0,$a4,$bi + mulhdu $t1,$a4,$bi + addc $h3lo,$h3lo,$t0 + adde $h3hi,$h3hi,$t1 + + mulld $t0,$a0,$bi + mulhdu $t1,$a0,$bi + addc $h4lo,$h4lo,$t0 + adde $h4hi,$h4hi,$t1 + +.Lfe51_reduce: + li $mask,-1 + srdi $mask,$mask,13 # 0x7ffffffffffff + + srdi $t0,$h2lo,51 + and $a2,$h2lo,$mask + insrdi $t0,$h2hi,51,0 # h2>>51 + srdi $t1,$h0lo,51 + and $a0,$h0lo,$mask + insrdi $t1,$h0hi,51,0 # h0>>51 + addc $h3lo,$h3lo,$t0 + addze $h3hi,$h3hi + addc $h1lo,$h1lo,$t1 + addze $h1hi,$h1hi + + srdi $t0,$h3lo,51 + and $a3,$h3lo,$mask + insrdi $t0,$h3hi,51,0 # h3>>51 + srdi $t1,$h1lo,51 + and $a1,$h1lo,$mask + insrdi $t1,$h1hi,51,0 # h1>>51 + addc $h4lo,$h4lo,$t0 + addze $h4hi,$h4hi + add $a2,$a2,$t1 + + srdi $t0,$h4lo,51 + and $a4,$h4lo,$mask + insrdi $t0,$h4hi,51,0 + mulli $t0,$t0,19 # (h4 >> 51) * 19 + + add $a0,$a0,$t0 + + srdi $t1,$a2,51 + and $a2,$a2,$mask + add $a3,$a3,$t1 + + srdi $t0,$a0,51 + and $a0,$a0,$mask + add $a1,$a1,$t0 + + std $a2,16($rp) + std $a3,24($rp) + std $a4,32($rp) + std $a0,0($rp) + std $a1,8($rp) + + ld r21,`$FRAME-8*11`($sp) + ld r22,`$FRAME-8*10`($sp) + ld r23,`$FRAME-8*9`($sp) + ld r24,`$FRAME-8*8`($sp) + ld r25,`$FRAME-8*7`($sp) + ld r26,`$FRAME-8*6`($sp) + ld r27,`$FRAME-8*5`($sp) + ld r28,`$FRAME-8*4`($sp) + ld r29,`$FRAME-8*3`($sp) + ld r30,`$FRAME-8*2`($sp) + ld r31,`$FRAME-8*1`($sp) + addi $sp,$sp,$FRAME + blr + .long 0 + .byte 0,12,4,0,0x80,11,3,0 + .long 0 +.size x25519_fe51_mul,.-x25519_fe51_mul +___ +{ +my ($a0,$a1,$a2,$a3,$a4,$t0,$t1) = ($a0,$a1,$a2,$a3,$a4,$t0,$t1); +$code.=<<___; +.globl x25519_fe51_sqr +.type x25519_fe51_sqr,\@function +.align 5 +x25519_fe51_sqr: + stdu $sp,-$FRAME($sp) + std r21,`$FRAME-8*11`($sp) + std r22,`$FRAME-8*10`($sp) + std r23,`$FRAME-8*9`($sp) + std r24,`$FRAME-8*8`($sp) + std r25,`$FRAME-8*7`($sp) + std r26,`$FRAME-8*6`($sp) + std r27,`$FRAME-8*5`($sp) + std r28,`$FRAME-8*4`($sp) + std r29,`$FRAME-8*3`($sp) + std r30,`$FRAME-8*2`($sp) + std r31,`$FRAME-8*1`($sp) + + ld $a0,0($ap) + ld $a1,8($ap) + ld $a2,16($ap) + ld $a3,24($ap) + ld $a4,32($ap) + + add $bi,$a0,$a0 # a[0]*2 + mulli $t1,$a4,19 # a[4]*19 + + mulld $h0lo,$a0,$a0 + mulhdu $h0hi,$a0,$a0 + mulld $h1lo,$a1,$bi + mulhdu $h1hi,$a1,$bi + mulld $h2lo,$a2,$bi + mulhdu $h2hi,$a2,$bi + mulld $h3lo,$a3,$bi + mulhdu $h3hi,$a3,$bi + mulld $h4lo,$a4,$bi + mulhdu $h4hi,$a4,$bi + add $bi,$a1,$a1 # a[1]*2 +___ + ($a4,$t1) = ($t1,$a4); +$code.=<<___; + mulld $t0,$t1,$a4 + mulhdu $t1,$t1,$a4 + addc $h3lo,$h3lo,$t0 + adde $h3hi,$h3hi,$t1 + + mulli $bp,$a3,19 # a[3]*19 + + mulld $t0,$a1,$a1 + mulhdu $t1,$a1,$a1 + addc $h2lo,$h2lo,$t0 + adde $h2hi,$h2hi,$t1 + mulld $t0,$a2,$bi + mulhdu $t1,$a2,$bi + addc $h3lo,$h3lo,$t0 + adde $h3hi,$h3hi,$t1 + mulld $t0,$a3,$bi + mulhdu $t1,$a3,$bi + addc $h4lo,$h4lo,$t0 + adde $h4hi,$h4hi,$t1 + mulld $t0,$a4,$bi + mulhdu $t1,$a4,$bi + add $bi,$a3,$a3 # a[3]*2 + addc $h0lo,$h0lo,$t0 + adde $h0hi,$h0hi,$t1 +___ + ($a3,$t1) = ($bp,$a3); +$code.=<<___; + mulld $t0,$t1,$a3 + mulhdu $t1,$t1,$a3 + addc $h1lo,$h1lo,$t0 + adde $h1hi,$h1hi,$t1 + mulld $t0,$bi,$a4 + mulhdu $t1,$bi,$a4 + add $bi,$a2,$a2 # a[2]*2 + addc $h2lo,$h2lo,$t0 + adde $h2hi,$h2hi,$t1 + + mulld $t0,$a2,$a2 + mulhdu $t1,$a2,$a2 + addc $h4lo,$h4lo,$t0 + adde $h4hi,$h4hi,$t1 + mulld $t0,$a3,$bi + mulhdu $t1,$a3,$bi + addc $h0lo,$h0lo,$t0 + adde $h0hi,$h0hi,$t1 + mulld $t0,$a4,$bi + mulhdu $t1,$a4,$bi + addc $h1lo,$h1lo,$t0 + adde $h1hi,$h1hi,$t1 + + b .Lfe51_reduce + .long 0 + .byte 0,12,4,0,0x80,11,2,0 + .long 0 +.size x25519_fe51_sqr,.-x25519_fe51_sqr +___ +} +$code.=<<___; +.globl x25519_fe51_mul121666 +.type x25519_fe51_mul121666,\@function +.align 5 +x25519_fe51_mul121666: + stdu $sp,-$FRAME($sp) + std r21,`$FRAME-8*11`($sp) + std r22,`$FRAME-8*10`($sp) + std r23,`$FRAME-8*9`($sp) + std r24,`$FRAME-8*8`($sp) + std r25,`$FRAME-8*7`($sp) + std r26,`$FRAME-8*6`($sp) + std r27,`$FRAME-8*5`($sp) + std r28,`$FRAME-8*4`($sp) + std r29,`$FRAME-8*3`($sp) + std r30,`$FRAME-8*2`($sp) + std r31,`$FRAME-8*1`($sp) + + lis $bi,`65536>>16` + ori $bi,$bi,`121666-65536` + ld $a0,0($ap) + ld $a1,8($ap) + ld $a2,16($ap) + ld $a3,24($ap) + ld $a4,32($ap) + + mulld $h0lo,$a0,$bi # a[0]*121666 + mulhdu $h0hi,$a0,$bi + mulld $h1lo,$a1,$bi # a[1]*121666 + mulhdu $h1hi,$a1,$bi + mulld $h2lo,$a2,$bi # a[2]*121666 + mulhdu $h2hi,$a2,$bi + mulld $h3lo,$a3,$bi # a[3]*121666 + mulhdu $h3hi,$a3,$bi + mulld $h4lo,$a4,$bi # a[4]*121666 + mulhdu $h4hi,$a4,$bi + + b .Lfe51_reduce + .long 0 + .byte 0,12,4,0,0x80,11,2,0 + .long 0 +.size x25519_fe51_mul121666,.-x25519_fe51_mul121666 +___ +} + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/x25519-x86_64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/x25519-x86_64.pl new file mode 100755 index 000000000..18dc6af9f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/asm/x25519-x86_64.pl @@ -0,0 +1,1117 @@ +#!/usr/bin/env perl +# Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# X25519 lower-level primitives for x86_64. +# +# February 2018. +# +# This module implements radix 2^51 multiplication and squaring, and +# radix 2^64 multiplication, squaring, addition, subtraction and final +# reduction. Latter radix is used on ADCX/ADOX-capable processors such +# as Broadwell. On related note one should mention that there are +# vector implementations that provide significantly better performance +# on some processors(*), but they are large and overly complex. Which +# in combination with them being effectively processor-specific makes +# the undertaking hard to justify. The goal for this implementation +# is rather versatility and simplicity [and ultimately formal +# verification]. +# +# (*) For example sandy2x should provide ~30% improvement on Sandy +# Bridge, but only nominal ~5% on Haswell [and big loss on +# Broadwell and successors]. +# +###################################################################### +# Improvement coefficients: +# +# amd64-51(*) gcc-5.x(**) +# +# P4 +22% +40% +# Sandy Bridge -3% +11% +# Haswell -1% +13% +# Broadwell(***) +30% +35% +# Skylake(***) +33% +47% +# Silvermont +20% +26% +# Goldmont +40% +50% +# Bulldozer +20% +9% +# Ryzen(***) +43% +40% +# VIA +170% +120% +# +# (*) amd64-51 is popular assembly implementation with 2^51 radix, +# only multiplication and squaring subroutines were linked +# for comparison, but not complete ladder step; gain on most +# processors is because this module refrains from shld, and +# minor regression on others is because this does result in +# higher instruction count; +# (**) compiler is free to inline functions, in assembly one would +# need to implement ladder step to do that, and it will improve +# performance by several percent; +# (***) ADCX/ADOX result for 2^64 radix, there is no corresponding +# C implementation, so that comparison is always against +# 2^51 radix; + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +*STDOUT=*OUT; + +if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler version ([2-9]\.[0-9]+)/) { + $addx = ($1>=2.23); +} + +if (!$addx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) && + `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) { + $addx = ($1>=2.10); +} + +if (!$addx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && + `ml64 2>&1` =~ /Version ([0-9]+)\./) { + $addx = ($1>=12); +} + +if (!$addx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9])\.([0-9]+)/) { + my $ver = $2 + $3/100.0; # 3.1->3.01, 3.10->3.10 + $addx = ($ver>=3.03); +} + +$code.=<<___; +.text + +.globl x25519_fe51_mul +.type x25519_fe51_mul,\@function,3 +.align 32 +x25519_fe51_mul: +.cfi_startproc + push %rbp +.cfi_push %rbp + push %rbx +.cfi_push %rbx + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + lea -8*5(%rsp),%rsp +.cfi_adjust_cfa_offset 40 +.Lfe51_mul_body: + + mov 8*0(%rsi),%rax # f[0] + mov 8*0(%rdx),%r11 # load g[0-4] + mov 8*1(%rdx),%r12 + mov 8*2(%rdx),%r13 + mov 8*3(%rdx),%rbp + mov 8*4(%rdx),%r14 + + mov %rdi,8*4(%rsp) # offload 1st argument + mov %rax,%rdi + mulq %r11 # f[0]*g[0] + mov %r11,8*0(%rsp) # offload g[0] + mov %rax,%rbx # %rbx:%rcx = h0 + mov %rdi,%rax + mov %rdx,%rcx + mulq %r12 # f[0]*g[1] + mov %r12,8*1(%rsp) # offload g[1] + mov %rax,%r8 # %r8:%r9 = h1 + mov %rdi,%rax + lea (%r14,%r14,8),%r15 + mov %rdx,%r9 + mulq %r13 # f[0]*g[2] + mov %r13,8*2(%rsp) # offload g[2] + mov %rax,%r10 # %r10:%r11 = h2 + mov %rdi,%rax + lea (%r14,%r15,2),%rdi # g[4]*19 + mov %rdx,%r11 + mulq %rbp # f[0]*g[3] + mov %rax,%r12 # %r12:%r13 = h3 + mov 8*0(%rsi),%rax # f[0] + mov %rdx,%r13 + mulq %r14 # f[0]*g[4] + mov %rax,%r14 # %r14:%r15 = h4 + mov 8*1(%rsi),%rax # f[1] + mov %rdx,%r15 + + mulq %rdi # f[1]*g[4]*19 + add %rax,%rbx + mov 8*2(%rsi),%rax # f[2] + adc %rdx,%rcx + mulq %rdi # f[2]*g[4]*19 + add %rax,%r8 + mov 8*3(%rsi),%rax # f[3] + adc %rdx,%r9 + mulq %rdi # f[3]*g[4]*19 + add %rax,%r10 + mov 8*4(%rsi),%rax # f[4] + adc %rdx,%r11 + mulq %rdi # f[4]*g[4]*19 + imulq \$19,%rbp,%rdi # g[3]*19 + add %rax,%r12 + mov 8*1(%rsi),%rax # f[1] + adc %rdx,%r13 + mulq %rbp # f[1]*g[3] + mov 8*2(%rsp),%rbp # g[2] + add %rax,%r14 + mov 8*2(%rsi),%rax # f[2] + adc %rdx,%r15 + + mulq %rdi # f[2]*g[3]*19 + add %rax,%rbx + mov 8*3(%rsi),%rax # f[3] + adc %rdx,%rcx + mulq %rdi # f[3]*g[3]*19 + add %rax,%r8 + mov 8*4(%rsi),%rax # f[4] + adc %rdx,%r9 + mulq %rdi # f[4]*g[3]*19 + imulq \$19,%rbp,%rdi # g[2]*19 + add %rax,%r10 + mov 8*1(%rsi),%rax # f[1] + adc %rdx,%r11 + mulq %rbp # f[1]*g[2] + add %rax,%r12 + mov 8*2(%rsi),%rax # f[2] + adc %rdx,%r13 + mulq %rbp # f[2]*g[2] + mov 8*1(%rsp),%rbp # g[1] + add %rax,%r14 + mov 8*3(%rsi),%rax # f[3] + adc %rdx,%r15 + + mulq %rdi # f[3]*g[2]*19 + add %rax,%rbx + mov 8*4(%rsi),%rax # f[3] + adc %rdx,%rcx + mulq %rdi # f[4]*g[2]*19 + add %rax,%r8 + mov 8*1(%rsi),%rax # f[1] + adc %rdx,%r9 + mulq %rbp # f[1]*g[1] + imulq \$19,%rbp,%rdi + add %rax,%r10 + mov 8*2(%rsi),%rax # f[2] + adc %rdx,%r11 + mulq %rbp # f[2]*g[1] + add %rax,%r12 + mov 8*3(%rsi),%rax # f[3] + adc %rdx,%r13 + mulq %rbp # f[3]*g[1] + mov 8*0(%rsp),%rbp # g[0] + add %rax,%r14 + mov 8*4(%rsi),%rax # f[4] + adc %rdx,%r15 + + mulq %rdi # f[4]*g[1]*19 + add %rax,%rbx + mov 8*1(%rsi),%rax # f[1] + adc %rdx,%rcx + mul %rbp # f[1]*g[0] + add %rax,%r8 + mov 8*2(%rsi),%rax # f[2] + adc %rdx,%r9 + mul %rbp # f[2]*g[0] + add %rax,%r10 + mov 8*3(%rsi),%rax # f[3] + adc %rdx,%r11 + mul %rbp # f[3]*g[0] + add %rax,%r12 + mov 8*4(%rsi),%rax # f[4] + adc %rdx,%r13 + mulq %rbp # f[4]*g[0] + add %rax,%r14 + adc %rdx,%r15 + + mov 8*4(%rsp),%rdi # restore 1st argument + jmp .Lreduce51 +.Lfe51_mul_epilogue: +.cfi_endproc +.size x25519_fe51_mul,.-x25519_fe51_mul + +.globl x25519_fe51_sqr +.type x25519_fe51_sqr,\@function,2 +.align 32 +x25519_fe51_sqr: +.cfi_startproc + push %rbp +.cfi_push %rbp + push %rbx +.cfi_push %rbx + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + lea -8*5(%rsp),%rsp +.cfi_adjust_cfa_offset 40 +.Lfe51_sqr_body: + + mov 8*0(%rsi),%rax # g[0] + mov 8*2(%rsi),%r15 # g[2] + mov 8*4(%rsi),%rbp # g[4] + + mov %rdi,8*4(%rsp) # offload 1st argument + lea (%rax,%rax),%r14 + mulq %rax # g[0]*g[0] + mov %rax,%rbx + mov 8*1(%rsi),%rax # g[1] + mov %rdx,%rcx + mulq %r14 # 2*g[0]*g[1] + mov %rax,%r8 + mov %r15,%rax + mov %r15,8*0(%rsp) # offload g[2] + mov %rdx,%r9 + mulq %r14 # 2*g[0]*g[2] + mov %rax,%r10 + mov 8*3(%rsi),%rax + mov %rdx,%r11 + imulq \$19,%rbp,%rdi # g[4]*19 + mulq %r14 # 2*g[0]*g[3] + mov %rax,%r12 + mov %rbp,%rax + mov %rdx,%r13 + mulq %r14 # 2*g[0]*g[4] + mov %rax,%r14 + mov %rbp,%rax + mov %rdx,%r15 + + mulq %rdi # g[4]*g[4]*19 + add %rax,%r12 + mov 8*1(%rsi),%rax # g[1] + adc %rdx,%r13 + + mov 8*3(%rsi),%rsi # g[3] + lea (%rax,%rax),%rbp + mulq %rax # g[1]*g[1] + add %rax,%r10 + mov 8*0(%rsp),%rax # g[2] + adc %rdx,%r11 + mulq %rbp # 2*g[1]*g[2] + add %rax,%r12 + mov %rbp,%rax + adc %rdx,%r13 + mulq %rsi # 2*g[1]*g[3] + add %rax,%r14 + mov %rbp,%rax + adc %rdx,%r15 + imulq \$19,%rsi,%rbp # g[3]*19 + mulq %rdi # 2*g[1]*g[4]*19 + add %rax,%rbx + lea (%rsi,%rsi),%rax + adc %rdx,%rcx + + mulq %rdi # 2*g[3]*g[4]*19 + add %rax,%r10 + mov %rsi,%rax + adc %rdx,%r11 + mulq %rbp # g[3]*g[3]*19 + add %rax,%r8 + mov 8*0(%rsp),%rax # g[2] + adc %rdx,%r9 + + lea (%rax,%rax),%rsi + mulq %rax # g[2]*g[2] + add %rax,%r14 + mov %rbp,%rax + adc %rdx,%r15 + mulq %rsi # 2*g[2]*g[3]*19 + add %rax,%rbx + mov %rsi,%rax + adc %rdx,%rcx + mulq %rdi # 2*g[2]*g[4]*19 + add %rax,%r8 + adc %rdx,%r9 + + mov 8*4(%rsp),%rdi # restore 1st argument + jmp .Lreduce51 + +.align 32 +.Lreduce51: + mov \$0x7ffffffffffff,%rbp + + mov %r10,%rdx + shr \$51,%r10 + shl \$13,%r11 + and %rbp,%rdx # %rdx = g2 = h2 & mask + or %r10,%r11 # h2>>51 + add %r11,%r12 + adc \$0,%r13 # h3 += h2>>51 + + mov %rbx,%rax + shr \$51,%rbx + shl \$13,%rcx + and %rbp,%rax # %rax = g0 = h0 & mask + or %rbx,%rcx # h0>>51 + add %rcx,%r8 # h1 += h0>>51 + adc \$0,%r9 + + mov %r12,%rbx + shr \$51,%r12 + shl \$13,%r13 + and %rbp,%rbx # %rbx = g3 = h3 & mask + or %r12,%r13 # h3>>51 + add %r13,%r14 # h4 += h3>>51 + adc \$0,%r15 + + mov %r8,%rcx + shr \$51,%r8 + shl \$13,%r9 + and %rbp,%rcx # %rcx = g1 = h1 & mask + or %r8,%r9 + add %r9,%rdx # g2 += h1>>51 + + mov %r14,%r10 + shr \$51,%r14 + shl \$13,%r15 + and %rbp,%r10 # %r10 = g4 = h0 & mask + or %r14,%r15 # h0>>51 + + lea (%r15,%r15,8),%r14 + lea (%r15,%r14,2),%r15 + add %r15,%rax # g0 += (h0>>51)*19 + + mov %rdx,%r8 + and %rbp,%rdx # g2 &= mask + shr \$51,%r8 + add %r8,%rbx # g3 += g2>>51 + + mov %rax,%r9 + and %rbp,%rax # g0 &= mask + shr \$51,%r9 + add %r9,%rcx # g1 += g0>>51 + + mov %rax,8*0(%rdi) # save the result + mov %rcx,8*1(%rdi) + mov %rdx,8*2(%rdi) + mov %rbx,8*3(%rdi) + mov %r10,8*4(%rdi) + + mov 8*5(%rsp),%r15 +.cfi_restore %r15 + mov 8*6(%rsp),%r14 +.cfi_restore %r14 + mov 8*7(%rsp),%r13 +.cfi_restore %r13 + mov 8*8(%rsp),%r12 +.cfi_restore %r12 + mov 8*9(%rsp),%rbx +.cfi_restore %rbx + mov 8*10(%rsp),%rbp +.cfi_restore %rbp + lea 8*11(%rsp),%rsp +.cfi_adjust_cfa_offset 88 +.Lfe51_sqr_epilogue: + ret +.cfi_endproc +.size x25519_fe51_sqr,.-x25519_fe51_sqr + +.globl x25519_fe51_mul121666 +.type x25519_fe51_mul121666,\@function,2 +.align 32 +x25519_fe51_mul121666: +.cfi_startproc + push %rbp +.cfi_push %rbp + push %rbx +.cfi_push %rbx + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + lea -8*5(%rsp),%rsp +.cfi_adjust_cfa_offset 40 +.Lfe51_mul121666_body: + mov \$121666,%eax + + mulq 8*0(%rsi) + mov %rax,%rbx # %rbx:%rcx = h0 + mov \$121666,%eax + mov %rdx,%rcx + mulq 8*1(%rsi) + mov %rax,%r8 # %r8:%r9 = h1 + mov \$121666,%eax + mov %rdx,%r9 + mulq 8*2(%rsi) + mov %rax,%r10 # %r10:%r11 = h2 + mov \$121666,%eax + mov %rdx,%r11 + mulq 8*3(%rsi) + mov %rax,%r12 # %r12:%r13 = h3 + mov \$121666,%eax # f[0] + mov %rdx,%r13 + mulq 8*4(%rsi) + mov %rax,%r14 # %r14:%r15 = h4 + mov %rdx,%r15 + + jmp .Lreduce51 +.Lfe51_mul121666_epilogue: +.cfi_endproc +.size x25519_fe51_mul121666,.-x25519_fe51_mul121666 +___ +######################################################################## +# Base 2^64 subroutines modulo 2*(2^255-19) +# +if ($addx) { +my ($acc0,$acc1,$acc2,$acc3,$acc4,$acc5,$acc6,$acc7) = map("%r$_",(8..15)); + +$code.=<<___; +.extern OPENSSL_ia32cap_P +.globl x25519_fe64_eligible +.type x25519_fe64_eligible,\@abi-omnipotent +.align 32 +x25519_fe64_eligible: + mov OPENSSL_ia32cap_P+8(%rip),%ecx + xor %eax,%eax + and \$0x80100,%ecx + cmp \$0x80100,%ecx + cmove %ecx,%eax + ret +.size x25519_fe64_eligible,.-x25519_fe64_eligible + +.globl x25519_fe64_mul +.type x25519_fe64_mul,\@function,3 +.align 32 +x25519_fe64_mul: +.cfi_startproc + push %rbp +.cfi_push %rbp + push %rbx +.cfi_push %rbx + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + push %rdi # offload dst +.cfi_push %rdi + lea -8*2(%rsp),%rsp +.cfi_adjust_cfa_offset 16 +.Lfe64_mul_body: + + mov %rdx,%rax + mov 8*0(%rdx),%rbp # b[0] + mov 8*0(%rsi),%rdx # a[0] + mov 8*1(%rax),%rcx # b[1] + mov 8*2(%rax),$acc6 # b[2] + mov 8*3(%rax),$acc7 # b[3] + + mulx %rbp,$acc0,%rax # a[0]*b[0] + xor %edi,%edi # cf=0,of=0 + mulx %rcx,$acc1,%rbx # a[0]*b[1] + adcx %rax,$acc1 + mulx $acc6,$acc2,%rax # a[0]*b[2] + adcx %rbx,$acc2 + mulx $acc7,$acc3,$acc4 # a[0]*b[3] + mov 8*1(%rsi),%rdx # a[1] + adcx %rax,$acc3 + mov $acc6,(%rsp) # offload b[2] + adcx %rdi,$acc4 # cf=0 + + mulx %rbp,%rax,%rbx # a[1]*b[0] + adox %rax,$acc1 + adcx %rbx,$acc2 + mulx %rcx,%rax,%rbx # a[1]*b[1] + adox %rax,$acc2 + adcx %rbx,$acc3 + mulx $acc6,%rax,%rbx # a[1]*b[2] + adox %rax,$acc3 + adcx %rbx,$acc4 + mulx $acc7,%rax,$acc5 # a[1]*b[3] + mov 8*2(%rsi),%rdx # a[2] + adox %rax,$acc4 + adcx %rdi,$acc5 # cf=0 + adox %rdi,$acc5 # of=0 + + mulx %rbp,%rax,%rbx # a[2]*b[0] + adcx %rax,$acc2 + adox %rbx,$acc3 + mulx %rcx,%rax,%rbx # a[2]*b[1] + adcx %rax,$acc3 + adox %rbx,$acc4 + mulx $acc6,%rax,%rbx # a[2]*b[2] + adcx %rax,$acc4 + adox %rbx,$acc5 + mulx $acc7,%rax,$acc6 # a[2]*b[3] + mov 8*3(%rsi),%rdx # a[3] + adcx %rax,$acc5 + adox %rdi,$acc6 # of=0 + adcx %rdi,$acc6 # cf=0 + + mulx %rbp,%rax,%rbx # a[3]*b[0] + adox %rax,$acc3 + adcx %rbx,$acc4 + mulx %rcx,%rax,%rbx # a[3]*b[1] + adox %rax,$acc4 + adcx %rbx,$acc5 + mulx (%rsp),%rax,%rbx # a[3]*b[2] + adox %rax,$acc5 + adcx %rbx,$acc6 + mulx $acc7,%rax,$acc7 # a[3]*b[3] + mov \$38,%edx + adox %rax,$acc6 + adcx %rdi,$acc7 # cf=0 + adox %rdi,$acc7 # of=0 + + jmp .Lreduce64 +.Lfe64_mul_epilogue: +.cfi_endproc +.size x25519_fe64_mul,.-x25519_fe64_mul + +.globl x25519_fe64_sqr +.type x25519_fe64_sqr,\@function,2 +.align 32 +x25519_fe64_sqr: +.cfi_startproc + push %rbp +.cfi_push %rbp + push %rbx +.cfi_push %rbx + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + push %rdi # offload dst +.cfi_push %rdi + lea -8*2(%rsp),%rsp +.cfi_adjust_cfa_offset 16 +.Lfe64_sqr_body: + + mov 8*0(%rsi),%rdx # a[0] + mov 8*1(%rsi),%rcx # a[1] + mov 8*2(%rsi),%rbp # a[2] + mov 8*3(%rsi),%rsi # a[3] + + ################################################################ + mulx %rdx,$acc0,$acc7 # a[0]*a[0] + mulx %rcx,$acc1,%rax # a[0]*a[1] + xor %edi,%edi # cf=0,of=0 + mulx %rbp,$acc2,%rbx # a[0]*a[2] + adcx %rax,$acc2 + mulx %rsi,$acc3,$acc4 # a[0]*a[3] + mov %rcx,%rdx # a[1] + adcx %rbx,$acc3 + adcx %rdi,$acc4 # cf=0 + + ################################################################ + mulx %rbp,%rax,%rbx # a[1]*a[2] + adox %rax,$acc3 + adcx %rbx,$acc4 + mulx %rsi,%rax,$acc5 # a[1]*a[3] + mov %rbp,%rdx # a[2] + adox %rax,$acc4 + adcx %rdi,$acc5 + + ################################################################ + mulx %rsi,%rax,$acc6 # a[2]*a[3] + mov %rcx,%rdx # a[1] + adox %rax,$acc5 + adcx %rdi,$acc6 # cf=0 + adox %rdi,$acc6 # of=0 + + adcx $acc1,$acc1 # acc1:6<<1 + adox $acc7,$acc1 + adcx $acc2,$acc2 + mulx %rdx,%rax,%rbx # a[1]*a[1] + mov %rbp,%rdx # a[2] + adcx $acc3,$acc3 + adox %rax,$acc2 + adcx $acc4,$acc4 + adox %rbx,$acc3 + mulx %rdx,%rax,%rbx # a[2]*a[2] + mov %rsi,%rdx # a[3] + adcx $acc5,$acc5 + adox %rax,$acc4 + adcx $acc6,$acc6 + adox %rbx,$acc5 + mulx %rdx,%rax,$acc7 # a[3]*a[3] + mov \$38,%edx + adox %rax,$acc6 + adcx %rdi,$acc7 # cf=0 + adox %rdi,$acc7 # of=0 + jmp .Lreduce64 + +.align 32 +.Lreduce64: + mulx $acc4,%rax,%rbx + adcx %rax,$acc0 + adox %rbx,$acc1 + mulx $acc5,%rax,%rbx + adcx %rax,$acc1 + adox %rbx,$acc2 + mulx $acc6,%rax,%rbx + adcx %rax,$acc2 + adox %rbx,$acc3 + mulx $acc7,%rax,$acc4 + adcx %rax,$acc3 + adox %rdi,$acc4 + adcx %rdi,$acc4 + + mov 8*2(%rsp),%rdi # restore dst + imulq %rdx,$acc4 + + add $acc4,$acc0 + adc \$0,$acc1 + adc \$0,$acc2 + adc \$0,$acc3 + + sbb %rax,%rax # cf -> mask + and \$38,%rax + + add %rax,$acc0 + mov $acc1,8*1(%rdi) + mov $acc2,8*2(%rdi) + mov $acc3,8*3(%rdi) + mov $acc0,8*0(%rdi) + + mov 8*3(%rsp),%r15 +.cfi_restore %r15 + mov 8*4(%rsp),%r14 +.cfi_restore %r14 + mov 8*5(%rsp),%r13 +.cfi_restore %r13 + mov 8*6(%rsp),%r12 +.cfi_restore %r12 + mov 8*7(%rsp),%rbx +.cfi_restore %rbx + mov 8*8(%rsp),%rbp +.cfi_restore %rbp + lea 8*9(%rsp),%rsp +.cfi_adjust_cfa_offset 88 +.Lfe64_sqr_epilogue: + ret +.cfi_endproc +.size x25519_fe64_sqr,.-x25519_fe64_sqr + +.globl x25519_fe64_mul121666 +.type x25519_fe64_mul121666,\@function,2 +.align 32 +x25519_fe64_mul121666: +.Lfe64_mul121666_body: + mov \$121666,%edx + mulx 8*0(%rsi),$acc0,%rcx + mulx 8*1(%rsi),$acc1,%rax + add %rcx,$acc1 + mulx 8*2(%rsi),$acc2,%rcx + adc %rax,$acc2 + mulx 8*3(%rsi),$acc3,%rax + adc %rcx,$acc3 + adc \$0,%rax + + imulq \$38,%rax,%rax + + add %rax,$acc0 + adc \$0,$acc1 + adc \$0,$acc2 + adc \$0,$acc3 + + sbb %rax,%rax # cf -> mask + and \$38,%rax + + add %rax,$acc0 + mov $acc1,8*1(%rdi) + mov $acc2,8*2(%rdi) + mov $acc3,8*3(%rdi) + mov $acc0,8*0(%rdi) + +.Lfe64_mul121666_epilogue: + ret +.size x25519_fe64_mul121666,.-x25519_fe64_mul121666 + +.globl x25519_fe64_add +.type x25519_fe64_add,\@function,3 +.align 32 +x25519_fe64_add: +.Lfe64_add_body: + mov 8*0(%rsi),$acc0 + mov 8*1(%rsi),$acc1 + mov 8*2(%rsi),$acc2 + mov 8*3(%rsi),$acc3 + + add 8*0(%rdx),$acc0 + adc 8*1(%rdx),$acc1 + adc 8*2(%rdx),$acc2 + adc 8*3(%rdx),$acc3 + + sbb %rax,%rax # cf -> mask + and \$38,%rax + + add %rax,$acc0 + adc \$0,$acc1 + adc \$0,$acc2 + mov $acc1,8*1(%rdi) + adc \$0,$acc3 + mov $acc2,8*2(%rdi) + sbb %rax,%rax # cf -> mask + mov $acc3,8*3(%rdi) + and \$38,%rax + + add %rax,$acc0 + mov $acc0,8*0(%rdi) + +.Lfe64_add_epilogue: + ret +.size x25519_fe64_add,.-x25519_fe64_add + +.globl x25519_fe64_sub +.type x25519_fe64_sub,\@function,3 +.align 32 +x25519_fe64_sub: +.Lfe64_sub_body: + mov 8*0(%rsi),$acc0 + mov 8*1(%rsi),$acc1 + mov 8*2(%rsi),$acc2 + mov 8*3(%rsi),$acc3 + + sub 8*0(%rdx),$acc0 + sbb 8*1(%rdx),$acc1 + sbb 8*2(%rdx),$acc2 + sbb 8*3(%rdx),$acc3 + + sbb %rax,%rax # cf -> mask + and \$38,%rax + + sub %rax,$acc0 + sbb \$0,$acc1 + sbb \$0,$acc2 + mov $acc1,8*1(%rdi) + sbb \$0,$acc3 + mov $acc2,8*2(%rdi) + sbb %rax,%rax # cf -> mask + mov $acc3,8*3(%rdi) + and \$38,%rax + + sub %rax,$acc0 + mov $acc0,8*0(%rdi) + +.Lfe64_sub_epilogue: + ret +.size x25519_fe64_sub,.-x25519_fe64_sub + +.globl x25519_fe64_tobytes +.type x25519_fe64_tobytes,\@function,2 +.align 32 +x25519_fe64_tobytes: +.Lfe64_to_body: + mov 8*0(%rsi),$acc0 + mov 8*1(%rsi),$acc1 + mov 8*2(%rsi),$acc2 + mov 8*3(%rsi),$acc3 + + ################################# reduction modulo 2^255-19 + lea ($acc3,$acc3),%rax + sar \$63,$acc3 # most significant bit -> mask + shr \$1,%rax # most significant bit cleared + and \$19,$acc3 + add \$19,$acc3 # compare to modulus in the same go + + add $acc3,$acc0 + adc \$0,$acc1 + adc \$0,$acc2 + adc \$0,%rax + + lea (%rax,%rax),$acc3 + sar \$63,%rax # most significant bit -> mask + shr \$1,$acc3 # most significant bit cleared + not %rax + and \$19,%rax + + sub %rax,$acc0 + sbb \$0,$acc1 + sbb \$0,$acc2 + sbb \$0,$acc3 + + mov $acc0,8*0(%rdi) + mov $acc1,8*1(%rdi) + mov $acc2,8*2(%rdi) + mov $acc3,8*3(%rdi) + +.Lfe64_to_epilogue: + ret +.size x25519_fe64_tobytes,.-x25519_fe64_tobytes +___ +} else { +$code.=<<___; +.globl x25519_fe64_eligible +.type x25519_fe64_eligible,\@abi-omnipotent +.align 32 +x25519_fe64_eligible: + xor %eax,%eax + ret +.size x25519_fe64_eligible,.-x25519_fe64_eligible + +.globl x25519_fe64_mul +.type x25519_fe64_mul,\@abi-omnipotent +.globl x25519_fe64_sqr +.globl x25519_fe64_mul121666 +.globl x25519_fe64_add +.globl x25519_fe64_sub +.globl x25519_fe64_tobytes +x25519_fe64_mul: +x25519_fe64_sqr: +x25519_fe64_mul121666: +x25519_fe64_add: +x25519_fe64_sub: +x25519_fe64_tobytes: + .byte 0x0f,0x0b # ud2 + ret +.size x25519_fe64_mul,.-x25519_fe64_mul +___ +} +$code.=<<___; +.asciz "X25519 primitives for x86_64, CRYPTOGAMS by " +___ + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind + +.type short_handler,\@abi-omnipotent +.align 16 +short_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # end of prologue label + cmp %r10,%rbx # context->RipRsp + jmp .Lcommon_seh_tail +.size short_handler,.-short_handler + +.type full_handler,\@abi-omnipotent +.align 16 +full_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # end of prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lcommon_seh_tail + + mov 8(%r11),%r10d # HandlerData[2] + lea (%rax,%r10),%rax + + mov -8(%rax),%rbp + mov -16(%rax),%rbx + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov -48(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + +.Lcommon_seh_tail: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size full_handler,.-full_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_x25519_fe51_mul + .rva .LSEH_end_x25519_fe51_mul + .rva .LSEH_info_x25519_fe51_mul + + .rva .LSEH_begin_x25519_fe51_sqr + .rva .LSEH_end_x25519_fe51_sqr + .rva .LSEH_info_x25519_fe51_sqr + + .rva .LSEH_begin_x25519_fe51_mul121666 + .rva .LSEH_end_x25519_fe51_mul121666 + .rva .LSEH_info_x25519_fe51_mul121666 +___ +$code.=<<___ if ($addx); + .rva .LSEH_begin_x25519_fe64_mul + .rva .LSEH_end_x25519_fe64_mul + .rva .LSEH_info_x25519_fe64_mul + + .rva .LSEH_begin_x25519_fe64_sqr + .rva .LSEH_end_x25519_fe64_sqr + .rva .LSEH_info_x25519_fe64_sqr + + .rva .LSEH_begin_x25519_fe64_mul121666 + .rva .LSEH_end_x25519_fe64_mul121666 + .rva .LSEH_info_x25519_fe64_mul121666 + + .rva .LSEH_begin_x25519_fe64_add + .rva .LSEH_end_x25519_fe64_add + .rva .LSEH_info_x25519_fe64_add + + .rva .LSEH_begin_x25519_fe64_sub + .rva .LSEH_end_x25519_fe64_sub + .rva .LSEH_info_x25519_fe64_sub + + .rva .LSEH_begin_x25519_fe64_tobytes + .rva .LSEH_end_x25519_fe64_tobytes + .rva .LSEH_info_x25519_fe64_tobytes +___ +$code.=<<___; +.section .xdata +.align 8 +.LSEH_info_x25519_fe51_mul: + .byte 9,0,0,0 + .rva full_handler + .rva .Lfe51_mul_body,.Lfe51_mul_epilogue # HandlerData[] + .long 88,0 +.LSEH_info_x25519_fe51_sqr: + .byte 9,0,0,0 + .rva full_handler + .rva .Lfe51_sqr_body,.Lfe51_sqr_epilogue # HandlerData[] + .long 88,0 +.LSEH_info_x25519_fe51_mul121666: + .byte 9,0,0,0 + .rva full_handler + .rva .Lfe51_mul121666_body,.Lfe51_mul121666_epilogue # HandlerData[] + .long 88,0 +___ +$code.=<<___ if ($addx); +.LSEH_info_x25519_fe64_mul: + .byte 9,0,0,0 + .rva full_handler + .rva .Lfe64_mul_body,.Lfe64_mul_epilogue # HandlerData[] + .long 72,0 +.LSEH_info_x25519_fe64_sqr: + .byte 9,0,0,0 + .rva full_handler + .rva .Lfe64_sqr_body,.Lfe64_sqr_epilogue # HandlerData[] + .long 72,0 +.LSEH_info_x25519_fe64_mul121666: + .byte 9,0,0,0 + .rva short_handler + .rva .Lfe64_mul121666_body,.Lfe64_mul121666_epilogue # HandlerData[] +.LSEH_info_x25519_fe64_add: + .byte 9,0,0,0 + .rva short_handler + .rva .Lfe64_add_body,.Lfe64_add_epilogue # HandlerData[] +.LSEH_info_x25519_fe64_sub: + .byte 9,0,0,0 + .rva short_handler + .rva .Lfe64_sub_body,.Lfe64_sub_epilogue # HandlerData[] +.LSEH_info_x25519_fe64_tobytes: + .byte 9,0,0,0 + .rva short_handler + .rva .Lfe64_to_body,.Lfe64_to_epilogue # HandlerData[] +___ +} + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/build.info new file mode 100644 index 000000000..a1e673e34 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/build.info @@ -0,0 +1,42 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + ec_lib.c ecp_smpl.c ecp_mont.c ecp_nist.c ec_cvt.c ec_mult.c \ + ec_err.c ec_curve.c ec_check.c ec_print.c ec_asn1.c ec_key.c \ + ec2_smpl.c ec_ameth.c ec_pmeth.c eck_prn.c \ + ecp_nistp224.c ecp_nistp256.c ecp_nistp521.c ecp_nistputil.c \ + ecp_oct.c ec2_oct.c ec_oct.c ec_kmeth.c ecdh_ossl.c ecdh_kdf.c \ + ecdsa_ossl.c ecdsa_sign.c ecdsa_vrf.c curve25519.c ecx_meth.c \ + curve448/arch_32/f_impl.c curve448/f_generic.c curve448/scalar.c \ + curve448/curve448_tables.c curve448/eddsa.c curve448/curve448.c \ + {- $target{ec_asm_src} -} + +GENERATE[ecp_nistz256-x86.s]=asm/ecp_nistz256-x86.pl \ + $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) + +GENERATE[ecp_nistz256-x86_64.s]=asm/ecp_nistz256-x86_64.pl $(PERLASM_SCHEME) + +GENERATE[ecp_nistz256-avx2.s]=asm/ecp_nistz256-avx2.pl $(PERLASM_SCHEME) + +GENERATE[ecp_nistz256-sparcv9.S]=asm/ecp_nistz256-sparcv9.pl $(PERLASM_SCHEME) +INCLUDE[ecp_nistz256-sparcv9.o]=.. + +GENERATE[ecp_nistz256-armv4.S]=asm/ecp_nistz256-armv4.pl $(PERLASM_SCHEME) +INCLUDE[ecp_nistz256-armv4.o]=.. +GENERATE[ecp_nistz256-armv8.S]=asm/ecp_nistz256-armv8.pl $(PERLASM_SCHEME) +INCLUDE[ecp_nistz256-armv8.o]=.. +GENERATE[ecp_nistz256-ppc64.s]=asm/ecp_nistz256-ppc64.pl $(PERLASM_SCHEME) + +GENERATE[x25519-x86_64.s]=asm/x25519-x86_64.pl $(PERLASM_SCHEME) +GENERATE[x25519-ppc64.s]=asm/x25519-ppc64.pl $(PERLASM_SCHEME) + +BEGINRAW[Makefile] +{- $builddir -}/ecp_nistz256-%.S: {- $sourcedir -}/asm/ecp_nistz256-%.pl + CC="$(CC)" $(PERL) $< $(PERLASM_SCHEME) $@ +ENDRAW[Makefile] + +INCLUDE[curve448/arch_32/f_impl.o]=curve448/arch_32 curve448 +INCLUDE[curve448/f_generic.o]=curve448/arch_32 curve448 +INCLUDE[curve448/scalar.o]=curve448/arch_32 curve448 +INCLUDE[curve448/curve448_tables.o]=curve448/arch_32 curve448 +INCLUDE[curve448/eddsa.o]=curve448/arch_32 curve448 +INCLUDE[curve448/curve448.o]=curve448/arch_32 curve448 diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve25519.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve25519.c new file mode 100644 index 000000000..aa999cc59 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve25519.c @@ -0,0 +1,5596 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "ec_lcl.h" +#include + +#if defined(X25519_ASM) && (defined(__x86_64) || defined(__x86_64__) || \ + defined(_M_AMD64) || defined(_M_X64)) + +# define BASE_2_64_IMPLEMENTED + +typedef uint64_t fe64[4]; + +int x25519_fe64_eligible(void); + +/* + * Following subroutines perform corresponding operations modulo + * 2^256-38, i.e. double the curve modulus. However, inputs and + * outputs are permitted to be partially reduced, i.e. to remain + * in [0..2^256) range. It's all tied up in final fe64_tobytes + * that performs full reduction modulo 2^255-19. + * + * There are no reference C implementations for these. + */ +void x25519_fe64_mul(fe64 h, const fe64 f, const fe64 g); +void x25519_fe64_sqr(fe64 h, const fe64 f); +void x25519_fe64_mul121666(fe64 h, fe64 f); +void x25519_fe64_add(fe64 h, const fe64 f, const fe64 g); +void x25519_fe64_sub(fe64 h, const fe64 f, const fe64 g); +void x25519_fe64_tobytes(uint8_t *s, const fe64 f); +# define fe64_mul x25519_fe64_mul +# define fe64_sqr x25519_fe64_sqr +# define fe64_mul121666 x25519_fe64_mul121666 +# define fe64_add x25519_fe64_add +# define fe64_sub x25519_fe64_sub +# define fe64_tobytes x25519_fe64_tobytes + +static uint64_t load_8(const uint8_t *in) +{ + uint64_t result; + + result = in[0]; + result |= ((uint64_t)in[1]) << 8; + result |= ((uint64_t)in[2]) << 16; + result |= ((uint64_t)in[3]) << 24; + result |= ((uint64_t)in[4]) << 32; + result |= ((uint64_t)in[5]) << 40; + result |= ((uint64_t)in[6]) << 48; + result |= ((uint64_t)in[7]) << 56; + + return result; +} + +static void fe64_frombytes(fe64 h, const uint8_t *s) +{ + h[0] = load_8(s); + h[1] = load_8(s + 8); + h[2] = load_8(s + 16); + h[3] = load_8(s + 24) & 0x7fffffffffffffff; +} + +static void fe64_0(fe64 h) +{ + h[0] = 0; + h[1] = 0; + h[2] = 0; + h[3] = 0; +} + +static void fe64_1(fe64 h) +{ + h[0] = 1; + h[1] = 0; + h[2] = 0; + h[3] = 0; +} + +static void fe64_copy(fe64 h, const fe64 f) +{ + h[0] = f[0]; + h[1] = f[1]; + h[2] = f[2]; + h[3] = f[3]; +} + +static void fe64_cswap(fe64 f, fe64 g, unsigned int b) +{ + int i; + uint64_t mask = 0 - (uint64_t)b; + + for (i = 0; i < 4; i++) { + uint64_t x = f[i] ^ g[i]; + x &= mask; + f[i] ^= x; + g[i] ^= x; + } +} + +static void fe64_invert(fe64 out, const fe64 z) +{ + fe64 t0; + fe64 t1; + fe64 t2; + fe64 t3; + int i; + + /* + * Compute z ** -1 = z ** (2 ** 255 - 19 - 2) with the exponent as + * 2 ** 255 - 21 = (2 ** 5) * (2 ** 250 - 1) + 11. + */ + + /* t0 = z ** 2 */ + fe64_sqr(t0, z); + + /* t1 = t0 ** (2 ** 2) = z ** 8 */ + fe64_sqr(t1, t0); + fe64_sqr(t1, t1); + + /* t1 = z * t1 = z ** 9 */ + fe64_mul(t1, z, t1); + /* t0 = t0 * t1 = z ** 11 -- stash t0 away for the end. */ + fe64_mul(t0, t0, t1); + + /* t2 = t0 ** 2 = z ** 22 */ + fe64_sqr(t2, t0); + + /* t1 = t1 * t2 = z ** (2 ** 5 - 1) */ + fe64_mul(t1, t1, t2); + + /* t2 = t1 ** (2 ** 5) = z ** ((2 ** 5) * (2 ** 5 - 1)) */ + fe64_sqr(t2, t1); + for (i = 1; i < 5; ++i) + fe64_sqr(t2, t2); + + /* t1 = t1 * t2 = z ** ((2 ** 5 + 1) * (2 ** 5 - 1)) = z ** (2 ** 10 - 1) */ + fe64_mul(t1, t2, t1); + + /* Continuing similarly... */ + + /* t2 = z ** (2 ** 20 - 1) */ + fe64_sqr(t2, t1); + for (i = 1; i < 10; ++i) + fe64_sqr(t2, t2); + + fe64_mul(t2, t2, t1); + + /* t2 = z ** (2 ** 40 - 1) */ + fe64_sqr(t3, t2); + for (i = 1; i < 20; ++i) + fe64_sqr(t3, t3); + + fe64_mul(t2, t3, t2); + + /* t2 = z ** (2 ** 10) * (2 ** 40 - 1) */ + for (i = 0; i < 10; ++i) + fe64_sqr(t2, t2); + + /* t1 = z ** (2 ** 50 - 1) */ + fe64_mul(t1, t2, t1); + + /* t2 = z ** (2 ** 100 - 1) */ + fe64_sqr(t2, t1); + for (i = 1; i < 50; ++i) + fe64_sqr(t2, t2); + + fe64_mul(t2, t2, t1); + + /* t2 = z ** (2 ** 200 - 1) */ + fe64_sqr(t3, t2); + for (i = 1; i < 100; ++i) + fe64_sqr(t3, t3); + + fe64_mul(t2, t3, t2); + + /* t2 = z ** ((2 ** 50) * (2 ** 200 - 1) */ + for (i = 0; i < 50; ++i) + fe64_sqr(t2, t2); + + /* t1 = z ** (2 ** 250 - 1) */ + fe64_mul(t1, t2, t1); + + /* t1 = z ** ((2 ** 5) * (2 ** 250 - 1)) */ + for (i = 0; i < 5; ++i) + fe64_sqr(t1, t1); + + /* Recall t0 = z ** 11; out = z ** (2 ** 255 - 21) */ + fe64_mul(out, t1, t0); +} + +/* + * Duplicate of original x25519_scalar_mult_generic, but using + * fe64_* subroutines. + */ +static void x25519_scalar_mulx(uint8_t out[32], const uint8_t scalar[32], + const uint8_t point[32]) +{ + fe64 x1, x2, z2, x3, z3, tmp0, tmp1; + uint8_t e[32]; + unsigned swap = 0; + int pos; + + memcpy(e, scalar, 32); + e[0] &= 0xf8; + e[31] &= 0x7f; + e[31] |= 0x40; + fe64_frombytes(x1, point); + fe64_1(x2); + fe64_0(z2); + fe64_copy(x3, x1); + fe64_1(z3); + + for (pos = 254; pos >= 0; --pos) { + unsigned int b = 1 & (e[pos / 8] >> (pos & 7)); + + swap ^= b; + fe64_cswap(x2, x3, swap); + fe64_cswap(z2, z3, swap); + swap = b; + fe64_sub(tmp0, x3, z3); + fe64_sub(tmp1, x2, z2); + fe64_add(x2, x2, z2); + fe64_add(z2, x3, z3); + fe64_mul(z3, x2, tmp0); + fe64_mul(z2, z2, tmp1); + fe64_sqr(tmp0, tmp1); + fe64_sqr(tmp1, x2); + fe64_add(x3, z3, z2); + fe64_sub(z2, z3, z2); + fe64_mul(x2, tmp1, tmp0); + fe64_sub(tmp1, tmp1, tmp0); + fe64_sqr(z2, z2); + fe64_mul121666(z3, tmp1); + fe64_sqr(x3, x3); + fe64_add(tmp0, tmp0, z3); + fe64_mul(z3, x1, z2); + fe64_mul(z2, tmp1, tmp0); + } + + fe64_invert(z2, z2); + fe64_mul(x2, x2, z2); + fe64_tobytes(out, x2); + + OPENSSL_cleanse(e, sizeof(e)); +} +#endif + +#if defined(X25519_ASM) \ + || ( (defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16) \ + && !defined(__sparc__) \ + && !(defined(__ANDROID__) && !defined(__clang__)) ) +/* + * Base 2^51 implementation. It's virtually no different from reference + * base 2^25.5 implementation in respect to lax boundary conditions for + * intermediate values and even individual limbs. So that whatever you + * know about the reference, applies even here... + */ +# define BASE_2_51_IMPLEMENTED + +typedef uint64_t fe51[5]; + +static const uint64_t MASK51 = 0x7ffffffffffff; + +static uint64_t load_7(const uint8_t *in) +{ + uint64_t result; + + result = in[0]; + result |= ((uint64_t)in[1]) << 8; + result |= ((uint64_t)in[2]) << 16; + result |= ((uint64_t)in[3]) << 24; + result |= ((uint64_t)in[4]) << 32; + result |= ((uint64_t)in[5]) << 40; + result |= ((uint64_t)in[6]) << 48; + + return result; +} + +static uint64_t load_6(const uint8_t *in) +{ + uint64_t result; + + result = in[0]; + result |= ((uint64_t)in[1]) << 8; + result |= ((uint64_t)in[2]) << 16; + result |= ((uint64_t)in[3]) << 24; + result |= ((uint64_t)in[4]) << 32; + result |= ((uint64_t)in[5]) << 40; + + return result; +} + +static void fe51_frombytes(fe51 h, const uint8_t *s) +{ + uint64_t h0 = load_7(s); /* 56 bits */ + uint64_t h1 = load_6(s + 7) << 5; /* 53 bits */ + uint64_t h2 = load_7(s + 13) << 2; /* 58 bits */ + uint64_t h3 = load_6(s + 20) << 7; /* 55 bits */ + uint64_t h4 = (load_6(s + 26) & 0x7fffffffffff) << 4; /* 51 bits */ + + h1 |= h0 >> 51; h0 &= MASK51; + h2 |= h1 >> 51; h1 &= MASK51; + h3 |= h2 >> 51; h2 &= MASK51; + h4 |= h3 >> 51; h3 &= MASK51; + + h[0] = h0; + h[1] = h1; + h[2] = h2; + h[3] = h3; + h[4] = h4; +} + +static void fe51_tobytes(uint8_t *s, const fe51 h) +{ + uint64_t h0 = h[0]; + uint64_t h1 = h[1]; + uint64_t h2 = h[2]; + uint64_t h3 = h[3]; + uint64_t h4 = h[4]; + uint64_t q; + + /* compare to modulus */ + q = (h0 + 19) >> 51; + q = (h1 + q) >> 51; + q = (h2 + q) >> 51; + q = (h3 + q) >> 51; + q = (h4 + q) >> 51; + + /* full reduce */ + h0 += 19 * q; + h1 += h0 >> 51; h0 &= MASK51; + h2 += h1 >> 51; h1 &= MASK51; + h3 += h2 >> 51; h2 &= MASK51; + h4 += h3 >> 51; h3 &= MASK51; + h4 &= MASK51; + + /* smash */ + s[0] = (uint8_t)(h0 >> 0); + s[1] = (uint8_t)(h0 >> 8); + s[2] = (uint8_t)(h0 >> 16); + s[3] = (uint8_t)(h0 >> 24); + s[4] = (uint8_t)(h0 >> 32); + s[5] = (uint8_t)(h0 >> 40); + s[6] = (uint8_t)((h0 >> 48) | ((uint32_t)h1 << 3)); + s[7] = (uint8_t)(h1 >> 5); + s[8] = (uint8_t)(h1 >> 13); + s[9] = (uint8_t)(h1 >> 21); + s[10] = (uint8_t)(h1 >> 29); + s[11] = (uint8_t)(h1 >> 37); + s[12] = (uint8_t)((h1 >> 45) | ((uint32_t)h2 << 6)); + s[13] = (uint8_t)(h2 >> 2); + s[14] = (uint8_t)(h2 >> 10); + s[15] = (uint8_t)(h2 >> 18); + s[16] = (uint8_t)(h2 >> 26); + s[17] = (uint8_t)(h2 >> 34); + s[18] = (uint8_t)(h2 >> 42); + s[19] = (uint8_t)((h2 >> 50) | ((uint32_t)h3 << 1)); + s[20] = (uint8_t)(h3 >> 7); + s[21] = (uint8_t)(h3 >> 15); + s[22] = (uint8_t)(h3 >> 23); + s[23] = (uint8_t)(h3 >> 31); + s[24] = (uint8_t)(h3 >> 39); + s[25] = (uint8_t)((h3 >> 47) | ((uint32_t)h4 << 4)); + s[26] = (uint8_t)(h4 >> 4); + s[27] = (uint8_t)(h4 >> 12); + s[28] = (uint8_t)(h4 >> 20); + s[29] = (uint8_t)(h4 >> 28); + s[30] = (uint8_t)(h4 >> 36); + s[31] = (uint8_t)(h4 >> 44); +} + +# if defined(X25519_ASM) +void x25519_fe51_mul(fe51 h, const fe51 f, const fe51 g); +void x25519_fe51_sqr(fe51 h, const fe51 f); +void x25519_fe51_mul121666(fe51 h, fe51 f); +# define fe51_mul x25519_fe51_mul +# define fe51_sq x25519_fe51_sqr +# define fe51_mul121666 x25519_fe51_mul121666 +# else + +typedef __uint128_t u128; + +static void fe51_mul(fe51 h, const fe51 f, const fe51 g) +{ + u128 h0, h1, h2, h3, h4; + uint64_t f_i, g0, g1, g2, g3, g4; + + f_i = f[0]; + h0 = (u128)f_i * (g0 = g[0]); + h1 = (u128)f_i * (g1 = g[1]); + h2 = (u128)f_i * (g2 = g[2]); + h3 = (u128)f_i * (g3 = g[3]); + h4 = (u128)f_i * (g4 = g[4]); + + f_i = f[1]; + h0 += (u128)f_i * (g4 *= 19); + h1 += (u128)f_i * g0; + h2 += (u128)f_i * g1; + h3 += (u128)f_i * g2; + h4 += (u128)f_i * g3; + + f_i = f[2]; + h0 += (u128)f_i * (g3 *= 19); + h1 += (u128)f_i * g4; + h2 += (u128)f_i * g0; + h3 += (u128)f_i * g1; + h4 += (u128)f_i * g2; + + f_i = f[3]; + h0 += (u128)f_i * (g2 *= 19); + h1 += (u128)f_i * g3; + h2 += (u128)f_i * g4; + h3 += (u128)f_i * g0; + h4 += (u128)f_i * g1; + + f_i = f[4]; + h0 += (u128)f_i * (g1 *= 19); + h1 += (u128)f_i * g2; + h2 += (u128)f_i * g3; + h3 += (u128)f_i * g4; + h4 += (u128)f_i * g0; + + /* partial [lazy] reduction */ + h3 += (uint64_t)(h2 >> 51); g2 = (uint64_t)h2 & MASK51; + h1 += (uint64_t)(h0 >> 51); g0 = (uint64_t)h0 & MASK51; + + h4 += (uint64_t)(h3 >> 51); g3 = (uint64_t)h3 & MASK51; + g2 += (uint64_t)(h1 >> 51); g1 = (uint64_t)h1 & MASK51; + + g0 += (uint64_t)(h4 >> 51) * 19; g4 = (uint64_t)h4 & MASK51; + g3 += g2 >> 51; g2 &= MASK51; + g1 += g0 >> 51; g0 &= MASK51; + + h[0] = g0; + h[1] = g1; + h[2] = g2; + h[3] = g3; + h[4] = g4; +} + +static void fe51_sq(fe51 h, const fe51 f) +{ +# if defined(OPENSSL_SMALL_FOOTPRINT) + fe51_mul(h, f, f); +# else + /* dedicated squaring gives 16-25% overall improvement */ + uint64_t g0 = f[0]; + uint64_t g1 = f[1]; + uint64_t g2 = f[2]; + uint64_t g3 = f[3]; + uint64_t g4 = f[4]; + u128 h0, h1, h2, h3, h4; + + h0 = (u128)g0 * g0; g0 *= 2; + h1 = (u128)g0 * g1; + h2 = (u128)g0 * g2; + h3 = (u128)g0 * g3; + h4 = (u128)g0 * g4; + + g0 = g4; /* borrow g0 */ + h3 += (u128)g0 * (g4 *= 19); + + h2 += (u128)g1 * g1; g1 *= 2; + h3 += (u128)g1 * g2; + h4 += (u128)g1 * g3; + h0 += (u128)g1 * g4; + + g0 = g3; /* borrow g0 */ + h1 += (u128)g0 * (g3 *= 19); + h2 += (u128)(g0 * 2) * g4; + + h4 += (u128)g2 * g2; g2 *= 2; + h0 += (u128)g2 * g3; + h1 += (u128)g2 * g4; + + /* partial [lazy] reduction */ + h3 += (uint64_t)(h2 >> 51); g2 = (uint64_t)h2 & MASK51; + h1 += (uint64_t)(h0 >> 51); g0 = (uint64_t)h0 & MASK51; + + h4 += (uint64_t)(h3 >> 51); g3 = (uint64_t)h3 & MASK51; + g2 += (uint64_t)(h1 >> 51); g1 = (uint64_t)h1 & MASK51; + + g0 += (uint64_t)(h4 >> 51) * 19; g4 = (uint64_t)h4 & MASK51; + g3 += g2 >> 51; g2 &= MASK51; + g1 += g0 >> 51; g0 &= MASK51; + + h[0] = g0; + h[1] = g1; + h[2] = g2; + h[3] = g3; + h[4] = g4; +# endif +} + +static void fe51_mul121666(fe51 h, fe51 f) +{ + u128 h0 = f[0] * (u128)121666; + u128 h1 = f[1] * (u128)121666; + u128 h2 = f[2] * (u128)121666; + u128 h3 = f[3] * (u128)121666; + u128 h4 = f[4] * (u128)121666; + uint64_t g0, g1, g2, g3, g4; + + h3 += (uint64_t)(h2 >> 51); g2 = (uint64_t)h2 & MASK51; + h1 += (uint64_t)(h0 >> 51); g0 = (uint64_t)h0 & MASK51; + + h4 += (uint64_t)(h3 >> 51); g3 = (uint64_t)h3 & MASK51; + g2 += (uint64_t)(h1 >> 51); g1 = (uint64_t)h1 & MASK51; + + g0 += (uint64_t)(h4 >> 51) * 19; g4 = (uint64_t)h4 & MASK51; + g3 += g2 >> 51; g2 &= MASK51; + g1 += g0 >> 51; g0 &= MASK51; + + h[0] = g0; + h[1] = g1; + h[2] = g2; + h[3] = g3; + h[4] = g4; +} +# endif + +static void fe51_add(fe51 h, const fe51 f, const fe51 g) +{ + h[0] = f[0] + g[0]; + h[1] = f[1] + g[1]; + h[2] = f[2] + g[2]; + h[3] = f[3] + g[3]; + h[4] = f[4] + g[4]; +} + +static void fe51_sub(fe51 h, const fe51 f, const fe51 g) +{ + /* + * Add 2*modulus to ensure that result remains positive + * even if subtrahend is partially reduced. + */ + h[0] = (f[0] + 0xfffffffffffda) - g[0]; + h[1] = (f[1] + 0xffffffffffffe) - g[1]; + h[2] = (f[2] + 0xffffffffffffe) - g[2]; + h[3] = (f[3] + 0xffffffffffffe) - g[3]; + h[4] = (f[4] + 0xffffffffffffe) - g[4]; +} + +static void fe51_0(fe51 h) +{ + h[0] = 0; + h[1] = 0; + h[2] = 0; + h[3] = 0; + h[4] = 0; +} + +static void fe51_1(fe51 h) +{ + h[0] = 1; + h[1] = 0; + h[2] = 0; + h[3] = 0; + h[4] = 0; +} + +static void fe51_copy(fe51 h, const fe51 f) +{ + h[0] = f[0]; + h[1] = f[1]; + h[2] = f[2]; + h[3] = f[3]; + h[4] = f[4]; +} + +static void fe51_cswap(fe51 f, fe51 g, unsigned int b) +{ + int i; + uint64_t mask = 0 - (uint64_t)b; + + for (i = 0; i < 5; i++) { + int64_t x = f[i] ^ g[i]; + x &= mask; + f[i] ^= x; + g[i] ^= x; + } +} + +static void fe51_invert(fe51 out, const fe51 z) +{ + fe51 t0; + fe51 t1; + fe51 t2; + fe51 t3; + int i; + + /* + * Compute z ** -1 = z ** (2 ** 255 - 19 - 2) with the exponent as + * 2 ** 255 - 21 = (2 ** 5) * (2 ** 250 - 1) + 11. + */ + + /* t0 = z ** 2 */ + fe51_sq(t0, z); + + /* t1 = t0 ** (2 ** 2) = z ** 8 */ + fe51_sq(t1, t0); + fe51_sq(t1, t1); + + /* t1 = z * t1 = z ** 9 */ + fe51_mul(t1, z, t1); + /* t0 = t0 * t1 = z ** 11 -- stash t0 away for the end. */ + fe51_mul(t0, t0, t1); + + /* t2 = t0 ** 2 = z ** 22 */ + fe51_sq(t2, t0); + + /* t1 = t1 * t2 = z ** (2 ** 5 - 1) */ + fe51_mul(t1, t1, t2); + + /* t2 = t1 ** (2 ** 5) = z ** ((2 ** 5) * (2 ** 5 - 1)) */ + fe51_sq(t2, t1); + for (i = 1; i < 5; ++i) + fe51_sq(t2, t2); + + /* t1 = t1 * t2 = z ** ((2 ** 5 + 1) * (2 ** 5 - 1)) = z ** (2 ** 10 - 1) */ + fe51_mul(t1, t2, t1); + + /* Continuing similarly... */ + + /* t2 = z ** (2 ** 20 - 1) */ + fe51_sq(t2, t1); + for (i = 1; i < 10; ++i) + fe51_sq(t2, t2); + + fe51_mul(t2, t2, t1); + + /* t2 = z ** (2 ** 40 - 1) */ + fe51_sq(t3, t2); + for (i = 1; i < 20; ++i) + fe51_sq(t3, t3); + + fe51_mul(t2, t3, t2); + + /* t2 = z ** (2 ** 10) * (2 ** 40 - 1) */ + for (i = 0; i < 10; ++i) + fe51_sq(t2, t2); + + /* t1 = z ** (2 ** 50 - 1) */ + fe51_mul(t1, t2, t1); + + /* t2 = z ** (2 ** 100 - 1) */ + fe51_sq(t2, t1); + for (i = 1; i < 50; ++i) + fe51_sq(t2, t2); + + fe51_mul(t2, t2, t1); + + /* t2 = z ** (2 ** 200 - 1) */ + fe51_sq(t3, t2); + for (i = 1; i < 100; ++i) + fe51_sq(t3, t3); + + fe51_mul(t2, t3, t2); + + /* t2 = z ** ((2 ** 50) * (2 ** 200 - 1) */ + for (i = 0; i < 50; ++i) + fe51_sq(t2, t2); + + /* t1 = z ** (2 ** 250 - 1) */ + fe51_mul(t1, t2, t1); + + /* t1 = z ** ((2 ** 5) * (2 ** 250 - 1)) */ + for (i = 0; i < 5; ++i) + fe51_sq(t1, t1); + + /* Recall t0 = z ** 11; out = z ** (2 ** 255 - 21) */ + fe51_mul(out, t1, t0); +} + +/* + * Duplicate of original x25519_scalar_mult_generic, but using + * fe51_* subroutines. + */ +static void x25519_scalar_mult(uint8_t out[32], const uint8_t scalar[32], + const uint8_t point[32]) +{ + fe51 x1, x2, z2, x3, z3, tmp0, tmp1; + uint8_t e[32]; + unsigned swap = 0; + int pos; + +# ifdef BASE_2_64_IMPLEMENTED + if (x25519_fe64_eligible()) { + x25519_scalar_mulx(out, scalar, point); + return; + } +# endif + + memcpy(e, scalar, 32); + e[0] &= 0xf8; + e[31] &= 0x7f; + e[31] |= 0x40; + fe51_frombytes(x1, point); + fe51_1(x2); + fe51_0(z2); + fe51_copy(x3, x1); + fe51_1(z3); + + for (pos = 254; pos >= 0; --pos) { + unsigned int b = 1 & (e[pos / 8] >> (pos & 7)); + + swap ^= b; + fe51_cswap(x2, x3, swap); + fe51_cswap(z2, z3, swap); + swap = b; + fe51_sub(tmp0, x3, z3); + fe51_sub(tmp1, x2, z2); + fe51_add(x2, x2, z2); + fe51_add(z2, x3, z3); + fe51_mul(z3, tmp0, x2); + fe51_mul(z2, z2, tmp1); + fe51_sq(tmp0, tmp1); + fe51_sq(tmp1, x2); + fe51_add(x3, z3, z2); + fe51_sub(z2, z3, z2); + fe51_mul(x2, tmp1, tmp0); + fe51_sub(tmp1, tmp1, tmp0); + fe51_sq(z2, z2); + fe51_mul121666(z3, tmp1); + fe51_sq(x3, x3); + fe51_add(tmp0, tmp0, z3); + fe51_mul(z3, x1, z2); + fe51_mul(z2, tmp1, tmp0); + } + + fe51_invert(z2, z2); + fe51_mul(x2, x2, z2); + fe51_tobytes(out, x2); + + OPENSSL_cleanse(e, sizeof(e)); +} +#endif + +/* + * Reference base 2^25.5 implementation. + * + * This code is mostly taken from the ref10 version of Ed25519 in SUPERCOP + * 20141124 (http://bench.cr.yp.to/supercop.html). + * + * The field functions are shared by Ed25519 and X25519 where possible. + */ + +/* + * fe means field element. Here the field is \Z/(2^255-19). An element t, + * entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77 + * t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on + * context. + */ +typedef int32_t fe[10]; + +static const int64_t kBottom21Bits = 0x1fffffLL; +static const int64_t kBottom25Bits = 0x1ffffffLL; +static const int64_t kBottom26Bits = 0x3ffffffLL; +static const int64_t kTop39Bits = 0xfffffffffe000000LL; +static const int64_t kTop38Bits = 0xfffffffffc000000LL; + +static uint64_t load_3(const uint8_t *in) +{ + uint64_t result; + + result = ((uint64_t)in[0]); + result |= ((uint64_t)in[1]) << 8; + result |= ((uint64_t)in[2]) << 16; + return result; +} + +static uint64_t load_4(const uint8_t *in) +{ + uint64_t result; + + result = ((uint64_t)in[0]); + result |= ((uint64_t)in[1]) << 8; + result |= ((uint64_t)in[2]) << 16; + result |= ((uint64_t)in[3]) << 24; + return result; +} + +static void fe_frombytes(fe h, const uint8_t *s) +{ + /* Ignores top bit of h. */ + int64_t h0 = load_4(s); + int64_t h1 = load_3(s + 4) << 6; + int64_t h2 = load_3(s + 7) << 5; + int64_t h3 = load_3(s + 10) << 3; + int64_t h4 = load_3(s + 13) << 2; + int64_t h5 = load_4(s + 16); + int64_t h6 = load_3(s + 20) << 7; + int64_t h7 = load_3(s + 23) << 5; + int64_t h8 = load_3(s + 26) << 4; + int64_t h9 = (load_3(s + 29) & 0x7fffff) << 2; + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + + carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits; + carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits; + carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits; + carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits; + carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits; + + carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits; + carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits; + carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits; + carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits; + carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits; + + h[0] = (int32_t)h0; + h[1] = (int32_t)h1; + h[2] = (int32_t)h2; + h[3] = (int32_t)h3; + h[4] = (int32_t)h4; + h[5] = (int32_t)h5; + h[6] = (int32_t)h6; + h[7] = (int32_t)h7; + h[8] = (int32_t)h8; + h[9] = (int32_t)h9; +} + +/* + * Preconditions: + * |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. + * + * Write p=2^255-19; q=floor(h/p). + * Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). + * + * Proof: + * Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. + * Also have |h-2^230 h9|<2^231 so |19 2^(-255)(h-2^230 h9)|<1/4. + * + * Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). + * Then 0> 25; + q = (h0 + q) >> 26; + q = (h1 + q) >> 25; + q = (h2 + q) >> 26; + q = (h3 + q) >> 25; + q = (h4 + q) >> 26; + q = (h5 + q) >> 25; + q = (h6 + q) >> 26; + q = (h7 + q) >> 25; + q = (h8 + q) >> 26; + q = (h9 + q) >> 25; + + /* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */ + h0 += 19 * q; + /* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */ + + h1 += h0 >> 26; h0 &= kBottom26Bits; + h2 += h1 >> 25; h1 &= kBottom25Bits; + h3 += h2 >> 26; h2 &= kBottom26Bits; + h4 += h3 >> 25; h3 &= kBottom25Bits; + h5 += h4 >> 26; h4 &= kBottom26Bits; + h6 += h5 >> 25; h5 &= kBottom25Bits; + h7 += h6 >> 26; h6 &= kBottom26Bits; + h8 += h7 >> 25; h7 &= kBottom25Bits; + h9 += h8 >> 26; h8 &= kBottom26Bits; + h9 &= kBottom25Bits; + /* h10 = carry9 */ + + /* + * Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. + * Have h0+...+2^230 h9 between 0 and 2^255-1; + * evidently 2^255 h10-2^255 q = 0. + * Goal: Output h0+...+2^230 h9. + */ + s[ 0] = (uint8_t) (h0 >> 0); + s[ 1] = (uint8_t) (h0 >> 8); + s[ 2] = (uint8_t) (h0 >> 16); + s[ 3] = (uint8_t)((h0 >> 24) | ((uint32_t)(h1) << 2)); + s[ 4] = (uint8_t) (h1 >> 6); + s[ 5] = (uint8_t) (h1 >> 14); + s[ 6] = (uint8_t)((h1 >> 22) | ((uint32_t)(h2) << 3)); + s[ 7] = (uint8_t) (h2 >> 5); + s[ 8] = (uint8_t) (h2 >> 13); + s[ 9] = (uint8_t)((h2 >> 21) | ((uint32_t)(h3) << 5)); + s[10] = (uint8_t) (h3 >> 3); + s[11] = (uint8_t) (h3 >> 11); + s[12] = (uint8_t)((h3 >> 19) | ((uint32_t)(h4) << 6)); + s[13] = (uint8_t) (h4 >> 2); + s[14] = (uint8_t) (h4 >> 10); + s[15] = (uint8_t) (h4 >> 18); + s[16] = (uint8_t) (h5 >> 0); + s[17] = (uint8_t) (h5 >> 8); + s[18] = (uint8_t) (h5 >> 16); + s[19] = (uint8_t)((h5 >> 24) | ((uint32_t)(h6) << 1)); + s[20] = (uint8_t) (h6 >> 7); + s[21] = (uint8_t) (h6 >> 15); + s[22] = (uint8_t)((h6 >> 23) | ((uint32_t)(h7) << 3)); + s[23] = (uint8_t) (h7 >> 5); + s[24] = (uint8_t) (h7 >> 13); + s[25] = (uint8_t)((h7 >> 21) | ((uint32_t)(h8) << 4)); + s[26] = (uint8_t) (h8 >> 4); + s[27] = (uint8_t) (h8 >> 12); + s[28] = (uint8_t)((h8 >> 20) | ((uint32_t)(h9) << 6)); + s[29] = (uint8_t) (h9 >> 2); + s[30] = (uint8_t) (h9 >> 10); + s[31] = (uint8_t) (h9 >> 18); +} + +/* h = f */ +static void fe_copy(fe h, const fe f) +{ + memmove(h, f, sizeof(int32_t) * 10); +} + +/* h = 0 */ +static void fe_0(fe h) +{ + memset(h, 0, sizeof(int32_t) * 10); +} + +/* h = 1 */ +static void fe_1(fe h) +{ + memset(h, 0, sizeof(int32_t) * 10); + h[0] = 1; +} + +/* + * h = f + g + * + * Can overlap h with f or g. + * + * Preconditions: + * |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. + * |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. + * + * Postconditions: + * |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. + */ +static void fe_add(fe h, const fe f, const fe g) +{ + unsigned i; + + for (i = 0; i < 10; i++) { + h[i] = f[i] + g[i]; + } +} + +/* + * h = f - g + * + * Can overlap h with f or g. + * + * Preconditions: + * |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. + * |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. + * + * Postconditions: + * |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. + */ +static void fe_sub(fe h, const fe f, const fe g) +{ + unsigned i; + + for (i = 0; i < 10; i++) { + h[i] = f[i] - g[i]; + } +} + +/* + * h = f * g + * + * Can overlap h with f or g. + * + * Preconditions: + * |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. + * |g| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. + * + * Postconditions: + * |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. + * + * Notes on implementation strategy: + * + * Using schoolbook multiplication. + * Karatsuba would save a little in some cost models. + * + * Most multiplications by 2 and 19 are 32-bit precomputations; + * cheaper than 64-bit postcomputations. + * + * There is one remaining multiplication by 19 in the carry chain; + * one *19 precomputation can be merged into this, + * but the resulting data flow is considerably less clean. + * + * There are 12 carries below. + * 10 of them are 2-way parallelizable and vectorizable. + * Can get away with 11 carries, but then data flow is much deeper. + * + * With tighter constraints on inputs can squeeze carries into int32. + */ +static void fe_mul(fe h, const fe f, const fe g) +{ + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int32_t g0 = g[0]; + int32_t g1 = g[1]; + int32_t g2 = g[2]; + int32_t g3 = g[3]; + int32_t g4 = g[4]; + int32_t g5 = g[5]; + int32_t g6 = g[6]; + int32_t g7 = g[7]; + int32_t g8 = g[8]; + int32_t g9 = g[9]; + int32_t g1_19 = 19 * g1; /* 1.959375*2^29 */ + int32_t g2_19 = 19 * g2; /* 1.959375*2^30; still ok */ + int32_t g3_19 = 19 * g3; + int32_t g4_19 = 19 * g4; + int32_t g5_19 = 19 * g5; + int32_t g6_19 = 19 * g6; + int32_t g7_19 = 19 * g7; + int32_t g8_19 = 19 * g8; + int32_t g9_19 = 19 * g9; + int32_t f1_2 = 2 * f1; + int32_t f3_2 = 2 * f3; + int32_t f5_2 = 2 * f5; + int32_t f7_2 = 2 * f7; + int32_t f9_2 = 2 * f9; + int64_t f0g0 = f0 * (int64_t) g0; + int64_t f0g1 = f0 * (int64_t) g1; + int64_t f0g2 = f0 * (int64_t) g2; + int64_t f0g3 = f0 * (int64_t) g3; + int64_t f0g4 = f0 * (int64_t) g4; + int64_t f0g5 = f0 * (int64_t) g5; + int64_t f0g6 = f0 * (int64_t) g6; + int64_t f0g7 = f0 * (int64_t) g7; + int64_t f0g8 = f0 * (int64_t) g8; + int64_t f0g9 = f0 * (int64_t) g9; + int64_t f1g0 = f1 * (int64_t) g0; + int64_t f1g1_2 = f1_2 * (int64_t) g1; + int64_t f1g2 = f1 * (int64_t) g2; + int64_t f1g3_2 = f1_2 * (int64_t) g3; + int64_t f1g4 = f1 * (int64_t) g4; + int64_t f1g5_2 = f1_2 * (int64_t) g5; + int64_t f1g6 = f1 * (int64_t) g6; + int64_t f1g7_2 = f1_2 * (int64_t) g7; + int64_t f1g8 = f1 * (int64_t) g8; + int64_t f1g9_38 = f1_2 * (int64_t) g9_19; + int64_t f2g0 = f2 * (int64_t) g0; + int64_t f2g1 = f2 * (int64_t) g1; + int64_t f2g2 = f2 * (int64_t) g2; + int64_t f2g3 = f2 * (int64_t) g3; + int64_t f2g4 = f2 * (int64_t) g4; + int64_t f2g5 = f2 * (int64_t) g5; + int64_t f2g6 = f2 * (int64_t) g6; + int64_t f2g7 = f2 * (int64_t) g7; + int64_t f2g8_19 = f2 * (int64_t) g8_19; + int64_t f2g9_19 = f2 * (int64_t) g9_19; + int64_t f3g0 = f3 * (int64_t) g0; + int64_t f3g1_2 = f3_2 * (int64_t) g1; + int64_t f3g2 = f3 * (int64_t) g2; + int64_t f3g3_2 = f3_2 * (int64_t) g3; + int64_t f3g4 = f3 * (int64_t) g4; + int64_t f3g5_2 = f3_2 * (int64_t) g5; + int64_t f3g6 = f3 * (int64_t) g6; + int64_t f3g7_38 = f3_2 * (int64_t) g7_19; + int64_t f3g8_19 = f3 * (int64_t) g8_19; + int64_t f3g9_38 = f3_2 * (int64_t) g9_19; + int64_t f4g0 = f4 * (int64_t) g0; + int64_t f4g1 = f4 * (int64_t) g1; + int64_t f4g2 = f4 * (int64_t) g2; + int64_t f4g3 = f4 * (int64_t) g3; + int64_t f4g4 = f4 * (int64_t) g4; + int64_t f4g5 = f4 * (int64_t) g5; + int64_t f4g6_19 = f4 * (int64_t) g6_19; + int64_t f4g7_19 = f4 * (int64_t) g7_19; + int64_t f4g8_19 = f4 * (int64_t) g8_19; + int64_t f4g9_19 = f4 * (int64_t) g9_19; + int64_t f5g0 = f5 * (int64_t) g0; + int64_t f5g1_2 = f5_2 * (int64_t) g1; + int64_t f5g2 = f5 * (int64_t) g2; + int64_t f5g3_2 = f5_2 * (int64_t) g3; + int64_t f5g4 = f5 * (int64_t) g4; + int64_t f5g5_38 = f5_2 * (int64_t) g5_19; + int64_t f5g6_19 = f5 * (int64_t) g6_19; + int64_t f5g7_38 = f5_2 * (int64_t) g7_19; + int64_t f5g8_19 = f5 * (int64_t) g8_19; + int64_t f5g9_38 = f5_2 * (int64_t) g9_19; + int64_t f6g0 = f6 * (int64_t) g0; + int64_t f6g1 = f6 * (int64_t) g1; + int64_t f6g2 = f6 * (int64_t) g2; + int64_t f6g3 = f6 * (int64_t) g3; + int64_t f6g4_19 = f6 * (int64_t) g4_19; + int64_t f6g5_19 = f6 * (int64_t) g5_19; + int64_t f6g6_19 = f6 * (int64_t) g6_19; + int64_t f6g7_19 = f6 * (int64_t) g7_19; + int64_t f6g8_19 = f6 * (int64_t) g8_19; + int64_t f6g9_19 = f6 * (int64_t) g9_19; + int64_t f7g0 = f7 * (int64_t) g0; + int64_t f7g1_2 = f7_2 * (int64_t) g1; + int64_t f7g2 = f7 * (int64_t) g2; + int64_t f7g3_38 = f7_2 * (int64_t) g3_19; + int64_t f7g4_19 = f7 * (int64_t) g4_19; + int64_t f7g5_38 = f7_2 * (int64_t) g5_19; + int64_t f7g6_19 = f7 * (int64_t) g6_19; + int64_t f7g7_38 = f7_2 * (int64_t) g7_19; + int64_t f7g8_19 = f7 * (int64_t) g8_19; + int64_t f7g9_38 = f7_2 * (int64_t) g9_19; + int64_t f8g0 = f8 * (int64_t) g0; + int64_t f8g1 = f8 * (int64_t) g1; + int64_t f8g2_19 = f8 * (int64_t) g2_19; + int64_t f8g3_19 = f8 * (int64_t) g3_19; + int64_t f8g4_19 = f8 * (int64_t) g4_19; + int64_t f8g5_19 = f8 * (int64_t) g5_19; + int64_t f8g6_19 = f8 * (int64_t) g6_19; + int64_t f8g7_19 = f8 * (int64_t) g7_19; + int64_t f8g8_19 = f8 * (int64_t) g8_19; + int64_t f8g9_19 = f8 * (int64_t) g9_19; + int64_t f9g0 = f9 * (int64_t) g0; + int64_t f9g1_38 = f9_2 * (int64_t) g1_19; + int64_t f9g2_19 = f9 * (int64_t) g2_19; + int64_t f9g3_38 = f9_2 * (int64_t) g3_19; + int64_t f9g4_19 = f9 * (int64_t) g4_19; + int64_t f9g5_38 = f9_2 * (int64_t) g5_19; + int64_t f9g6_19 = f9 * (int64_t) g6_19; + int64_t f9g7_38 = f9_2 * (int64_t) g7_19; + int64_t f9g8_19 = f9 * (int64_t) g8_19; + int64_t f9g9_38 = f9_2 * (int64_t) g9_19; + int64_t h0 = f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38; + int64_t h1 = f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19; + int64_t h2 = f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38; + int64_t h3 = f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19; + int64_t h4 = f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38; + int64_t h5 = f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19; + int64_t h6 = f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38; + int64_t h7 = f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19; + int64_t h8 = f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38; + int64_t h9 = f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0 ; + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + + /* |h0| <= (1.65*1.65*2^52*(1+19+19+19+19)+1.65*1.65*2^50*(38+38+38+38+38)) + * i.e. |h0| <= 1.4*2^60; narrower ranges for h2, h4, h6, h8 + * |h1| <= (1.65*1.65*2^51*(1+1+19+19+19+19+19+19+19+19)) + * i.e. |h1| <= 1.7*2^59; narrower ranges for h3, h5, h7, h9 */ + + carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits; + carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits; + /* |h0| <= 2^25 */ + /* |h4| <= 2^25 */ + /* |h1| <= 1.71*2^59 */ + /* |h5| <= 1.71*2^59 */ + + carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits; + carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits; + /* |h1| <= 2^24; from now on fits into int32 */ + /* |h5| <= 2^24; from now on fits into int32 */ + /* |h2| <= 1.41*2^60 */ + /* |h6| <= 1.41*2^60 */ + + carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits; + carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits; + /* |h2| <= 2^25; from now on fits into int32 unchanged */ + /* |h6| <= 2^25; from now on fits into int32 unchanged */ + /* |h3| <= 1.71*2^59 */ + /* |h7| <= 1.71*2^59 */ + + carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits; + carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits; + /* |h3| <= 2^24; from now on fits into int32 unchanged */ + /* |h7| <= 2^24; from now on fits into int32 unchanged */ + /* |h4| <= 1.72*2^34 */ + /* |h8| <= 1.41*2^60 */ + + carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits; + carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits; + /* |h4| <= 2^25; from now on fits into int32 unchanged */ + /* |h8| <= 2^25; from now on fits into int32 unchanged */ + /* |h5| <= 1.01*2^24 */ + /* |h9| <= 1.71*2^59 */ + + carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits; + /* |h9| <= 2^24; from now on fits into int32 unchanged */ + /* |h0| <= 1.1*2^39 */ + + carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits; + /* |h0| <= 2^25; from now on fits into int32 unchanged */ + /* |h1| <= 1.01*2^24 */ + + h[0] = (int32_t)h0; + h[1] = (int32_t)h1; + h[2] = (int32_t)h2; + h[3] = (int32_t)h3; + h[4] = (int32_t)h4; + h[5] = (int32_t)h5; + h[6] = (int32_t)h6; + h[7] = (int32_t)h7; + h[8] = (int32_t)h8; + h[9] = (int32_t)h9; +} + +/* + * h = f * f + * + * Can overlap h with f. + * + * Preconditions: + * |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. + * + * Postconditions: + * |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. + * + * See fe_mul.c for discussion of implementation strategy. + */ +static void fe_sq(fe h, const fe f) +{ + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int32_t f0_2 = 2 * f0; + int32_t f1_2 = 2 * f1; + int32_t f2_2 = 2 * f2; + int32_t f3_2 = 2 * f3; + int32_t f4_2 = 2 * f4; + int32_t f5_2 = 2 * f5; + int32_t f6_2 = 2 * f6; + int32_t f7_2 = 2 * f7; + int32_t f5_38 = 38 * f5; /* 1.959375*2^30 */ + int32_t f6_19 = 19 * f6; /* 1.959375*2^30 */ + int32_t f7_38 = 38 * f7; /* 1.959375*2^30 */ + int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */ + int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */ + int64_t f0f0 = f0 * (int64_t) f0; + int64_t f0f1_2 = f0_2 * (int64_t) f1; + int64_t f0f2_2 = f0_2 * (int64_t) f2; + int64_t f0f3_2 = f0_2 * (int64_t) f3; + int64_t f0f4_2 = f0_2 * (int64_t) f4; + int64_t f0f5_2 = f0_2 * (int64_t) f5; + int64_t f0f6_2 = f0_2 * (int64_t) f6; + int64_t f0f7_2 = f0_2 * (int64_t) f7; + int64_t f0f8_2 = f0_2 * (int64_t) f8; + int64_t f0f9_2 = f0_2 * (int64_t) f9; + int64_t f1f1_2 = f1_2 * (int64_t) f1; + int64_t f1f2_2 = f1_2 * (int64_t) f2; + int64_t f1f3_4 = f1_2 * (int64_t) f3_2; + int64_t f1f4_2 = f1_2 * (int64_t) f4; + int64_t f1f5_4 = f1_2 * (int64_t) f5_2; + int64_t f1f6_2 = f1_2 * (int64_t) f6; + int64_t f1f7_4 = f1_2 * (int64_t) f7_2; + int64_t f1f8_2 = f1_2 * (int64_t) f8; + int64_t f1f9_76 = f1_2 * (int64_t) f9_38; + int64_t f2f2 = f2 * (int64_t) f2; + int64_t f2f3_2 = f2_2 * (int64_t) f3; + int64_t f2f4_2 = f2_2 * (int64_t) f4; + int64_t f2f5_2 = f2_2 * (int64_t) f5; + int64_t f2f6_2 = f2_2 * (int64_t) f6; + int64_t f2f7_2 = f2_2 * (int64_t) f7; + int64_t f2f8_38 = f2_2 * (int64_t) f8_19; + int64_t f2f9_38 = f2 * (int64_t) f9_38; + int64_t f3f3_2 = f3_2 * (int64_t) f3; + int64_t f3f4_2 = f3_2 * (int64_t) f4; + int64_t f3f5_4 = f3_2 * (int64_t) f5_2; + int64_t f3f6_2 = f3_2 * (int64_t) f6; + int64_t f3f7_76 = f3_2 * (int64_t) f7_38; + int64_t f3f8_38 = f3_2 * (int64_t) f8_19; + int64_t f3f9_76 = f3_2 * (int64_t) f9_38; + int64_t f4f4 = f4 * (int64_t) f4; + int64_t f4f5_2 = f4_2 * (int64_t) f5; + int64_t f4f6_38 = f4_2 * (int64_t) f6_19; + int64_t f4f7_38 = f4 * (int64_t) f7_38; + int64_t f4f8_38 = f4_2 * (int64_t) f8_19; + int64_t f4f9_38 = f4 * (int64_t) f9_38; + int64_t f5f5_38 = f5 * (int64_t) f5_38; + int64_t f5f6_38 = f5_2 * (int64_t) f6_19; + int64_t f5f7_76 = f5_2 * (int64_t) f7_38; + int64_t f5f8_38 = f5_2 * (int64_t) f8_19; + int64_t f5f9_76 = f5_2 * (int64_t) f9_38; + int64_t f6f6_19 = f6 * (int64_t) f6_19; + int64_t f6f7_38 = f6 * (int64_t) f7_38; + int64_t f6f8_38 = f6_2 * (int64_t) f8_19; + int64_t f6f9_38 = f6 * (int64_t) f9_38; + int64_t f7f7_38 = f7 * (int64_t) f7_38; + int64_t f7f8_38 = f7_2 * (int64_t) f8_19; + int64_t f7f9_76 = f7_2 * (int64_t) f9_38; + int64_t f8f8_19 = f8 * (int64_t) f8_19; + int64_t f8f9_38 = f8 * (int64_t) f9_38; + int64_t f9f9_38 = f9 * (int64_t) f9_38; + int64_t h0 = f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38; + int64_t h1 = f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38; + int64_t h2 = f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19; + int64_t h3 = f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38; + int64_t h4 = f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38; + int64_t h5 = f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38; + int64_t h6 = f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19; + int64_t h7 = f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38; + int64_t h8 = f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38; + int64_t h9 = f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2; + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + + carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits; + carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits; + + carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits; + carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits; + + carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits; + carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits; + + carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits; + carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits; + + carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits; + carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits; + + carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits; + + carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits; + + h[0] = (int32_t)h0; + h[1] = (int32_t)h1; + h[2] = (int32_t)h2; + h[3] = (int32_t)h3; + h[4] = (int32_t)h4; + h[5] = (int32_t)h5; + h[6] = (int32_t)h6; + h[7] = (int32_t)h7; + h[8] = (int32_t)h8; + h[9] = (int32_t)h9; +} + +static void fe_invert(fe out, const fe z) +{ + fe t0; + fe t1; + fe t2; + fe t3; + int i; + + /* + * Compute z ** -1 = z ** (2 ** 255 - 19 - 2) with the exponent as + * 2 ** 255 - 21 = (2 ** 5) * (2 ** 250 - 1) + 11. + */ + + /* t0 = z ** 2 */ + fe_sq(t0, z); + + /* t1 = t0 ** (2 ** 2) = z ** 8 */ + fe_sq(t1, t0); + fe_sq(t1, t1); + + /* t1 = z * t1 = z ** 9 */ + fe_mul(t1, z, t1); + /* t0 = t0 * t1 = z ** 11 -- stash t0 away for the end. */ + fe_mul(t0, t0, t1); + + /* t2 = t0 ** 2 = z ** 22 */ + fe_sq(t2, t0); + + /* t1 = t1 * t2 = z ** (2 ** 5 - 1) */ + fe_mul(t1, t1, t2); + + /* t2 = t1 ** (2 ** 5) = z ** ((2 ** 5) * (2 ** 5 - 1)) */ + fe_sq(t2, t1); + for (i = 1; i < 5; ++i) { + fe_sq(t2, t2); + } + + /* t1 = t1 * t2 = z ** ((2 ** 5 + 1) * (2 ** 5 - 1)) = z ** (2 ** 10 - 1) */ + fe_mul(t1, t2, t1); + + /* Continuing similarly... */ + + /* t2 = z ** (2 ** 20 - 1) */ + fe_sq(t2, t1); + for (i = 1; i < 10; ++i) { + fe_sq(t2, t2); + } + fe_mul(t2, t2, t1); + + /* t2 = z ** (2 ** 40 - 1) */ + fe_sq(t3, t2); + for (i = 1; i < 20; ++i) { + fe_sq(t3, t3); + } + fe_mul(t2, t3, t2); + + /* t2 = z ** (2 ** 10) * (2 ** 40 - 1) */ + for (i = 0; i < 10; ++i) { + fe_sq(t2, t2); + } + /* t1 = z ** (2 ** 50 - 1) */ + fe_mul(t1, t2, t1); + + /* t2 = z ** (2 ** 100 - 1) */ + fe_sq(t2, t1); + for (i = 1; i < 50; ++i) { + fe_sq(t2, t2); + } + fe_mul(t2, t2, t1); + + /* t2 = z ** (2 ** 200 - 1) */ + fe_sq(t3, t2); + for (i = 1; i < 100; ++i) { + fe_sq(t3, t3); + } + fe_mul(t2, t3, t2); + + /* t2 = z ** ((2 ** 50) * (2 ** 200 - 1) */ + fe_sq(t2, t2); + for (i = 1; i < 50; ++i) { + fe_sq(t2, t2); + } + + /* t1 = z ** (2 ** 250 - 1) */ + fe_mul(t1, t2, t1); + + /* t1 = z ** ((2 ** 5) * (2 ** 250 - 1)) */ + fe_sq(t1, t1); + for (i = 1; i < 5; ++i) { + fe_sq(t1, t1); + } + + /* Recall t0 = z ** 11; out = z ** (2 ** 255 - 21) */ + fe_mul(out, t1, t0); +} + +/* + * h = -f + * + * Preconditions: + * |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. + * + * Postconditions: + * |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. + */ +static void fe_neg(fe h, const fe f) +{ + unsigned i; + + for (i = 0; i < 10; i++) { + h[i] = -f[i]; + } +} + +/* + * Replace (f,g) with (g,g) if b == 1; + * replace (f,g) with (f,g) if b == 0. + * + * Preconditions: b in {0,1}. + */ +static void fe_cmov(fe f, const fe g, unsigned b) +{ + size_t i; + + b = 0-b; + for (i = 0; i < 10; i++) { + int32_t x = f[i] ^ g[i]; + x &= b; + f[i] ^= x; + } +} + +/* + * return 0 if f == 0 + * return 1 if f != 0 + * + * Preconditions: + * |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. + */ +static int fe_isnonzero(const fe f) +{ + uint8_t s[32]; + static const uint8_t zero[32] = {0}; + + fe_tobytes(s, f); + + return CRYPTO_memcmp(s, zero, sizeof(zero)) != 0; +} + +/* + * return 1 if f is in {1,3,5,...,q-2} + * return 0 if f is in {0,2,4,...,q-1} + * + * Preconditions: + * |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. + */ +static int fe_isnegative(const fe f) +{ + uint8_t s[32]; + + fe_tobytes(s, f); + return s[0] & 1; +} + +/* + * h = 2 * f * f + * + * Can overlap h with f. + * + * Preconditions: + * |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. + * + * Postconditions: + * |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. + * + * See fe_mul.c for discussion of implementation strategy. + */ +static void fe_sq2(fe h, const fe f) +{ + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int32_t f0_2 = 2 * f0; + int32_t f1_2 = 2 * f1; + int32_t f2_2 = 2 * f2; + int32_t f3_2 = 2 * f3; + int32_t f4_2 = 2 * f4; + int32_t f5_2 = 2 * f5; + int32_t f6_2 = 2 * f6; + int32_t f7_2 = 2 * f7; + int32_t f5_38 = 38 * f5; /* 1.959375*2^30 */ + int32_t f6_19 = 19 * f6; /* 1.959375*2^30 */ + int32_t f7_38 = 38 * f7; /* 1.959375*2^30 */ + int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */ + int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */ + int64_t f0f0 = f0 * (int64_t) f0; + int64_t f0f1_2 = f0_2 * (int64_t) f1; + int64_t f0f2_2 = f0_2 * (int64_t) f2; + int64_t f0f3_2 = f0_2 * (int64_t) f3; + int64_t f0f4_2 = f0_2 * (int64_t) f4; + int64_t f0f5_2 = f0_2 * (int64_t) f5; + int64_t f0f6_2 = f0_2 * (int64_t) f6; + int64_t f0f7_2 = f0_2 * (int64_t) f7; + int64_t f0f8_2 = f0_2 * (int64_t) f8; + int64_t f0f9_2 = f0_2 * (int64_t) f9; + int64_t f1f1_2 = f1_2 * (int64_t) f1; + int64_t f1f2_2 = f1_2 * (int64_t) f2; + int64_t f1f3_4 = f1_2 * (int64_t) f3_2; + int64_t f1f4_2 = f1_2 * (int64_t) f4; + int64_t f1f5_4 = f1_2 * (int64_t) f5_2; + int64_t f1f6_2 = f1_2 * (int64_t) f6; + int64_t f1f7_4 = f1_2 * (int64_t) f7_2; + int64_t f1f8_2 = f1_2 * (int64_t) f8; + int64_t f1f9_76 = f1_2 * (int64_t) f9_38; + int64_t f2f2 = f2 * (int64_t) f2; + int64_t f2f3_2 = f2_2 * (int64_t) f3; + int64_t f2f4_2 = f2_2 * (int64_t) f4; + int64_t f2f5_2 = f2_2 * (int64_t) f5; + int64_t f2f6_2 = f2_2 * (int64_t) f6; + int64_t f2f7_2 = f2_2 * (int64_t) f7; + int64_t f2f8_38 = f2_2 * (int64_t) f8_19; + int64_t f2f9_38 = f2 * (int64_t) f9_38; + int64_t f3f3_2 = f3_2 * (int64_t) f3; + int64_t f3f4_2 = f3_2 * (int64_t) f4; + int64_t f3f5_4 = f3_2 * (int64_t) f5_2; + int64_t f3f6_2 = f3_2 * (int64_t) f6; + int64_t f3f7_76 = f3_2 * (int64_t) f7_38; + int64_t f3f8_38 = f3_2 * (int64_t) f8_19; + int64_t f3f9_76 = f3_2 * (int64_t) f9_38; + int64_t f4f4 = f4 * (int64_t) f4; + int64_t f4f5_2 = f4_2 * (int64_t) f5; + int64_t f4f6_38 = f4_2 * (int64_t) f6_19; + int64_t f4f7_38 = f4 * (int64_t) f7_38; + int64_t f4f8_38 = f4_2 * (int64_t) f8_19; + int64_t f4f9_38 = f4 * (int64_t) f9_38; + int64_t f5f5_38 = f5 * (int64_t) f5_38; + int64_t f5f6_38 = f5_2 * (int64_t) f6_19; + int64_t f5f7_76 = f5_2 * (int64_t) f7_38; + int64_t f5f8_38 = f5_2 * (int64_t) f8_19; + int64_t f5f9_76 = f5_2 * (int64_t) f9_38; + int64_t f6f6_19 = f6 * (int64_t) f6_19; + int64_t f6f7_38 = f6 * (int64_t) f7_38; + int64_t f6f8_38 = f6_2 * (int64_t) f8_19; + int64_t f6f9_38 = f6 * (int64_t) f9_38; + int64_t f7f7_38 = f7 * (int64_t) f7_38; + int64_t f7f8_38 = f7_2 * (int64_t) f8_19; + int64_t f7f9_76 = f7_2 * (int64_t) f9_38; + int64_t f8f8_19 = f8 * (int64_t) f8_19; + int64_t f8f9_38 = f8 * (int64_t) f9_38; + int64_t f9f9_38 = f9 * (int64_t) f9_38; + int64_t h0 = f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38; + int64_t h1 = f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38; + int64_t h2 = f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19; + int64_t h3 = f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38; + int64_t h4 = f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38; + int64_t h5 = f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38; + int64_t h6 = f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19; + int64_t h7 = f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38; + int64_t h8 = f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38; + int64_t h9 = f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2; + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + + h0 += h0; + h1 += h1; + h2 += h2; + h3 += h3; + h4 += h4; + h5 += h5; + h6 += h6; + h7 += h7; + h8 += h8; + h9 += h9; + + carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits; + carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits; + + carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits; + carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits; + + carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits; + carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits; + + carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits; + carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits; + + carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits; + carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits; + + carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits; + + carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits; + + h[0] = (int32_t)h0; + h[1] = (int32_t)h1; + h[2] = (int32_t)h2; + h[3] = (int32_t)h3; + h[4] = (int32_t)h4; + h[5] = (int32_t)h5; + h[6] = (int32_t)h6; + h[7] = (int32_t)h7; + h[8] = (int32_t)h8; + h[9] = (int32_t)h9; +} + +static void fe_pow22523(fe out, const fe z) +{ + fe t0; + fe t1; + fe t2; + int i; + + fe_sq(t0, z); + fe_sq(t1, t0); + for (i = 1; i < 2; ++i) { + fe_sq(t1, t1); + } + fe_mul(t1, z, t1); + fe_mul(t0, t0, t1); + fe_sq(t0, t0); + fe_mul(t0, t1, t0); + fe_sq(t1, t0); + for (i = 1; i < 5; ++i) { + fe_sq(t1, t1); + } + fe_mul(t0, t1, t0); + fe_sq(t1, t0); + for (i = 1; i < 10; ++i) { + fe_sq(t1, t1); + } + fe_mul(t1, t1, t0); + fe_sq(t2, t1); + for (i = 1; i < 20; ++i) { + fe_sq(t2, t2); + } + fe_mul(t1, t2, t1); + fe_sq(t1, t1); + for (i = 1; i < 10; ++i) { + fe_sq(t1, t1); + } + fe_mul(t0, t1, t0); + fe_sq(t1, t0); + for (i = 1; i < 50; ++i) { + fe_sq(t1, t1); + } + fe_mul(t1, t1, t0); + fe_sq(t2, t1); + for (i = 1; i < 100; ++i) { + fe_sq(t2, t2); + } + fe_mul(t1, t2, t1); + fe_sq(t1, t1); + for (i = 1; i < 50; ++i) { + fe_sq(t1, t1); + } + fe_mul(t0, t1, t0); + fe_sq(t0, t0); + for (i = 1; i < 2; ++i) { + fe_sq(t0, t0); + } + fe_mul(out, t0, z); +} + +/* + * ge means group element. + * + * Here the group is the set of pairs (x,y) of field elements (see fe.h) + * satisfying -x^2 + y^2 = 1 + d x^2y^2 + * where d = -121665/121666. + * + * Representations: + * ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z + * ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT + * ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T + * ge_precomp (Duif): (y+x,y-x,2dxy) + */ +typedef struct { + fe X; + fe Y; + fe Z; +} ge_p2; + +typedef struct { + fe X; + fe Y; + fe Z; + fe T; +} ge_p3; + +typedef struct { + fe X; + fe Y; + fe Z; + fe T; +} ge_p1p1; + +typedef struct { + fe yplusx; + fe yminusx; + fe xy2d; +} ge_precomp; + +typedef struct { + fe YplusX; + fe YminusX; + fe Z; + fe T2d; +} ge_cached; + +static void ge_tobytes(uint8_t *s, const ge_p2 *h) +{ + fe recip; + fe x; + fe y; + + fe_invert(recip, h->Z); + fe_mul(x, h->X, recip); + fe_mul(y, h->Y, recip); + fe_tobytes(s, y); + s[31] ^= fe_isnegative(x) << 7; +} + +static void ge_p3_tobytes(uint8_t *s, const ge_p3 *h) +{ + fe recip; + fe x; + fe y; + + fe_invert(recip, h->Z); + fe_mul(x, h->X, recip); + fe_mul(y, h->Y, recip); + fe_tobytes(s, y); + s[31] ^= fe_isnegative(x) << 7; +} + +static const fe d = { + -10913610, 13857413, -15372611, 6949391, 114729, + -8787816, -6275908, -3247719, -18696448, -12055116 +}; + +static const fe sqrtm1 = { + -32595792, -7943725, 9377950, 3500415, 12389472, + -272473, -25146209, -2005654, 326686, 11406482 +}; + +static int ge_frombytes_vartime(ge_p3 *h, const uint8_t *s) +{ + fe u; + fe v; + fe v3; + fe vxx; + fe check; + + fe_frombytes(h->Y, s); + fe_1(h->Z); + fe_sq(u, h->Y); + fe_mul(v, u, d); + fe_sub(u, u, h->Z); /* u = y^2-1 */ + fe_add(v, v, h->Z); /* v = dy^2+1 */ + + fe_sq(v3, v); + fe_mul(v3, v3, v); /* v3 = v^3 */ + fe_sq(h->X, v3); + fe_mul(h->X, h->X, v); + fe_mul(h->X, h->X, u); /* x = uv^7 */ + + fe_pow22523(h->X, h->X); /* x = (uv^7)^((q-5)/8) */ + fe_mul(h->X, h->X, v3); + fe_mul(h->X, h->X, u); /* x = uv^3(uv^7)^((q-5)/8) */ + + fe_sq(vxx, h->X); + fe_mul(vxx, vxx, v); + fe_sub(check, vxx, u); /* vx^2-u */ + if (fe_isnonzero(check)) { + fe_add(check, vxx, u); /* vx^2+u */ + if (fe_isnonzero(check)) { + return -1; + } + fe_mul(h->X, h->X, sqrtm1); + } + + if (fe_isnegative(h->X) != (s[31] >> 7)) { + fe_neg(h->X, h->X); + } + + fe_mul(h->T, h->X, h->Y); + return 0; +} + +static void ge_p2_0(ge_p2 *h) +{ + fe_0(h->X); + fe_1(h->Y); + fe_1(h->Z); +} + +static void ge_p3_0(ge_p3 *h) +{ + fe_0(h->X); + fe_1(h->Y); + fe_1(h->Z); + fe_0(h->T); +} + +static void ge_precomp_0(ge_precomp *h) +{ + fe_1(h->yplusx); + fe_1(h->yminusx); + fe_0(h->xy2d); +} + +/* r = p */ +static void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p) +{ + fe_copy(r->X, p->X); + fe_copy(r->Y, p->Y); + fe_copy(r->Z, p->Z); +} + +static const fe d2 = { + -21827239, -5839606, -30745221, 13898782, 229458, + 15978800, -12551817, -6495438, 29715968, 9444199 +}; + +/* r = p */ +static void ge_p3_to_cached(ge_cached *r, const ge_p3 *p) +{ + fe_add(r->YplusX, p->Y, p->X); + fe_sub(r->YminusX, p->Y, p->X); + fe_copy(r->Z, p->Z); + fe_mul(r->T2d, p->T, d2); +} + +/* r = p */ +static void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p) +{ + fe_mul(r->X, p->X, p->T); + fe_mul(r->Y, p->Y, p->Z); + fe_mul(r->Z, p->Z, p->T); +} + +/* r = p */ +static void ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p) +{ + fe_mul(r->X, p->X, p->T); + fe_mul(r->Y, p->Y, p->Z); + fe_mul(r->Z, p->Z, p->T); + fe_mul(r->T, p->X, p->Y); +} + +/* r = 2 * p */ +static void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p) +{ + fe t0; + + fe_sq(r->X, p->X); + fe_sq(r->Z, p->Y); + fe_sq2(r->T, p->Z); + fe_add(r->Y, p->X, p->Y); + fe_sq(t0, r->Y); + fe_add(r->Y, r->Z, r->X); + fe_sub(r->Z, r->Z, r->X); + fe_sub(r->X, t0, r->Y); + fe_sub(r->T, r->T, r->Z); +} + +/* r = 2 * p */ +static void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p) +{ + ge_p2 q; + ge_p3_to_p2(&q, p); + ge_p2_dbl(r, &q); +} + +/* r = p + q */ +static void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) +{ + fe t0; + + fe_add(r->X, p->Y, p->X); + fe_sub(r->Y, p->Y, p->X); + fe_mul(r->Z, r->X, q->yplusx); + fe_mul(r->Y, r->Y, q->yminusx); + fe_mul(r->T, q->xy2d, p->T); + fe_add(t0, p->Z, p->Z); + fe_sub(r->X, r->Z, r->Y); + fe_add(r->Y, r->Z, r->Y); + fe_add(r->Z, t0, r->T); + fe_sub(r->T, t0, r->T); +} + +/* r = p - q */ +static void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) +{ + fe t0; + + fe_add(r->X, p->Y, p->X); + fe_sub(r->Y, p->Y, p->X); + fe_mul(r->Z, r->X, q->yminusx); + fe_mul(r->Y, r->Y, q->yplusx); + fe_mul(r->T, q->xy2d, p->T); + fe_add(t0, p->Z, p->Z); + fe_sub(r->X, r->Z, r->Y); + fe_add(r->Y, r->Z, r->Y); + fe_sub(r->Z, t0, r->T); + fe_add(r->T, t0, r->T); +} + +/* r = p + q */ +static void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) +{ + fe t0; + + fe_add(r->X, p->Y, p->X); + fe_sub(r->Y, p->Y, p->X); + fe_mul(r->Z, r->X, q->YplusX); + fe_mul(r->Y, r->Y, q->YminusX); + fe_mul(r->T, q->T2d, p->T); + fe_mul(r->X, p->Z, q->Z); + fe_add(t0, r->X, r->X); + fe_sub(r->X, r->Z, r->Y); + fe_add(r->Y, r->Z, r->Y); + fe_add(r->Z, t0, r->T); + fe_sub(r->T, t0, r->T); +} + +/* r = p - q */ +static void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) +{ + fe t0; + + fe_add(r->X, p->Y, p->X); + fe_sub(r->Y, p->Y, p->X); + fe_mul(r->Z, r->X, q->YminusX); + fe_mul(r->Y, r->Y, q->YplusX); + fe_mul(r->T, q->T2d, p->T); + fe_mul(r->X, p->Z, q->Z); + fe_add(t0, r->X, r->X); + fe_sub(r->X, r->Z, r->Y); + fe_add(r->Y, r->Z, r->Y); + fe_sub(r->Z, t0, r->T); + fe_add(r->T, t0, r->T); +} + +static uint8_t equal(signed char b, signed char c) +{ + uint8_t ub = b; + uint8_t uc = c; + uint8_t x = ub ^ uc; /* 0: yes; 1..255: no */ + uint32_t y = x; /* 0: yes; 1..255: no */ + y -= 1; /* 4294967295: yes; 0..254: no */ + y >>= 31; /* 1: yes; 0: no */ + return y; +} + +static void cmov(ge_precomp *t, const ge_precomp *u, uint8_t b) +{ + fe_cmov(t->yplusx, u->yplusx, b); + fe_cmov(t->yminusx, u->yminusx, b); + fe_cmov(t->xy2d, u->xy2d, b); +} + +/* k25519Precomp[i][j] = (j+1)*256^i*B */ +static const ge_precomp k25519Precomp[32][8] = { + { + { + {25967493, -14356035, 29566456, 3660896, -12694345, 4014787, + 27544626, -11754271, -6079156, 2047605}, + {-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, + 5043384, 19500929, -15469378}, + {-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, + 29287919, 11864899, -24514362, -4438546}, + }, + { + {-12815894, -12976347, -21581243, 11784320, -25355658, -2750717, + -11717903, -3814571, -358445, -10211303}, + {-21703237, 6903825, 27185491, 6451973, -29577724, -9554005, + -15616551, 11189268, -26829678, -5319081}, + {26966642, 11152617, 32442495, 15396054, 14353839, -12752335, + -3128826, -9541118, -15472047, -4166697}, + }, + { + {15636291, -9688557, 24204773, -7912398, 616977, -16685262, + 27787600, -14772189, 28944400, -1550024}, + {16568933, 4717097, -11556148, -1102322, 15682896, -11807043, + 16354577, -11775962, 7689662, 11199574}, + {30464156, -5976125, -11779434, -15670865, 23220365, 15915852, + 7512774, 10017326, -17749093, -9920357}, + }, + { + {-17036878, 13921892, 10945806, -6033431, 27105052, -16084379, + -28926210, 15006023, 3284568, -6276540}, + {23599295, -8306047, -11193664, -7687416, 13236774, 10506355, + 7464579, 9656445, 13059162, 10374397}, + {7798556, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664, + -3839045, -641708, -101325}, + }, + { + {10861363, 11473154, 27284546, 1981175, -30064349, 12577861, + 32867885, 14515107, -15438304, 10819380}, + {4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, + 12483688, -12668491, 5581306}, + {19563160, 16186464, -29386857, 4097519, 10237984, -4348115, + 28542350, 13850243, -23678021, -15815942}, + }, + { + {-15371964, -12862754, 32573250, 4720197, -26436522, 5875511, + -19188627, -15224819, -9818940, -12085777}, + {-8549212, 109983, 15149363, 2178705, 22900618, 4543417, 3044240, + -15689887, 1762328, 14866737}, + {-18199695, -15951423, -10473290, 1707278, -17185920, 3916101, + -28236412, 3959421, 27914454, 4383652}, + }, + { + {5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, + 5230134, -23952439, -15175766}, + {-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, + 20654025, 16520125, 30598449, 7715701}, + {28881845, 14381568, 9657904, 3680757, -20181635, 7843316, + -31400660, 1370708, 29794553, -1409300}, + }, + { + {14499471, -2729599, -33191113, -4254652, 28494862, 14271267, + 30290735, 10876454, -33154098, 2381726}, + {-7195431, -2655363, -14730155, 462251, -27724326, 3941372, + -6236617, 3696005, -32300832, 15351955}, + {27431194, 8222322, 16448760, -3907995, -18707002, 11938355, + -32961401, -2970515, 29551813, 10109425}, + }, + }, + { + { + {-13657040, -13155431, -31283750, 11777098, 21447386, 6519384, + -2378284, -1627556, 10092783, -4764171}, + {27939166, 14210322, 4677035, 16277044, -22964462, -12398139, + -32508754, 12005538, -17810127, 12803510}, + {17228999, -15661624, -1233527, 300140, -1224870, -11714777, + 30364213, -9038194, 18016357, 4397660}, + }, + { + {-10958843, -7690207, 4776341, -14954238, 27850028, -15602212, + -26619106, 14544525, -17477504, 982639}, + {29253598, 15796703, -2863982, -9908884, 10057023, 3163536, 7332899, + -4120128, -21047696, 9934963}, + {5793303, 16271923, -24131614, -10116404, 29188560, 1206517, + -14747930, 4559895, -30123922, -10897950}, + }, + { + {-27643952, -11493006, 16282657, -11036493, 28414021, -15012264, + 24191034, 4541697, -13338309, 5500568}, + {12650548, -1497113, 9052871, 11355358, -17680037, -8400164, + -17430592, 12264343, 10874051, 13524335}, + {25556948, -3045990, 714651, 2510400, 23394682, -10415330, 33119038, + 5080568, -22528059, 5376628}, + }, + { + {-26088264, -4011052, -17013699, -3537628, -6726793, 1920897, + -22321305, -9447443, 4535768, 1569007}, + {-2255422, 14606630, -21692440, -8039818, 28430649, 8775819, + -30494562, 3044290, 31848280, 12543772}, + {-22028579, 2943893, -31857513, 6777306, 13784462, -4292203, + -27377195, -2062731, 7718482, 14474653}, + }, + { + {2385315, 2454213, -22631320, 46603, -4437935, -15680415, 656965, + -7236665, 24316168, -5253567}, + {13741529, 10911568, -33233417, -8603737, -20177830, -1033297, + 33040651, -13424532, -20729456, 8321686}, + {21060490, -2212744, 15712757, -4336099, 1639040, 10656336, + 23845965, -11874838, -9984458, 608372}, + }, + { + {-13672732, -15087586, -10889693, -7557059, -6036909, 11305547, + 1123968, -6780577, 27229399, 23887}, + {-23244140, -294205, -11744728, 14712571, -29465699, -2029617, + 12797024, -6440308, -1633405, 16678954}, + {-29500620, 4770662, -16054387, 14001338, 7830047, 9564805, + -1508144, -4795045, -17169265, 4904953}, + }, + { + {24059557, 14617003, 19037157, -15039908, 19766093, -14906429, + 5169211, 16191880, 2128236, -4326833}, + {-16981152, 4124966, -8540610, -10653797, 30336522, -14105247, + -29806336, 916033, -6882542, -2986532}, + {-22630907, 12419372, -7134229, -7473371, -16478904, 16739175, + 285431, 2763829, 15736322, 4143876}, + }, + { + {2379352, 11839345, -4110402, -5988665, 11274298, 794957, 212801, + -14594663, 23527084, -16458268}, + {33431127, -11130478, -17838966, -15626900, 8909499, 8376530, + -32625340, 4087881, -15188911, -14416214}, + {1767683, 7197987, -13205226, -2022635, -13091350, 448826, 5799055, + 4357868, -4774191, -16323038}, + }, + }, + { + { + {6721966, 13833823, -23523388, -1551314, 26354293, -11863321, + 23365147, -3949732, 7390890, 2759800}, + {4409041, 2052381, 23373853, 10530217, 7676779, -12885954, 21302353, + -4264057, 1244380, -12919645}, + {-4421239, 7169619, 4982368, -2957590, 30256825, -2777540, 14086413, + 9208236, 15886429, 16489664}, + }, + { + {1996075, 10375649, 14346367, 13311202, -6874135, -16438411, + -13693198, 398369, -30606455, -712933}, + {-25307465, 9795880, -2777414, 14878809, -33531835, 14780363, + 13348553, 12076947, -30836462, 5113182}, + {-17770784, 11797796, 31950843, 13929123, -25888302, 12288344, + -30341101, -7336386, 13847711, 5387222}, + }, + { + {-18582163, -3416217, 17824843, -2340966, 22744343, -10442611, + 8763061, 3617786, -19600662, 10370991}, + {20246567, -14369378, 22358229, -543712, 18507283, -10413996, + 14554437, -8746092, 32232924, 16763880}, + {9648505, 10094563, 26416693, 14745928, -30374318, -6472621, + 11094161, 15689506, 3140038, -16510092}, + }, + { + {-16160072, 5472695, 31895588, 4744994, 8823515, 10365685, + -27224800, 9448613, -28774454, 366295}, + {19153450, 11523972, -11096490, -6503142, -24647631, 5420647, + 28344573, 8041113, 719605, 11671788}, + {8678025, 2694440, -6808014, 2517372, 4964326, 11152271, -15432916, + -15266516, 27000813, -10195553}, + }, + { + {-15157904, 7134312, 8639287, -2814877, -7235688, 10421742, 564065, + 5336097, 6750977, -14521026}, + {11836410, -3979488, 26297894, 16080799, 23455045, 15735944, + 1695823, -8819122, 8169720, 16220347}, + {-18115838, 8653647, 17578566, -6092619, -8025777, -16012763, + -11144307, -2627664, -5990708, -14166033}, + }, + { + {-23308498, -10968312, 15213228, -10081214, -30853605, -11050004, + 27884329, 2847284, 2655861, 1738395}, + {-27537433, -14253021, -25336301, -8002780, -9370762, 8129821, + 21651608, -3239336, -19087449, -11005278}, + {1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092, + 5821408, 10478196, 8544890}, + }, + { + {32173121, -16129311, 24896207, 3921497, 22579056, -3410854, + 19270449, 12217473, 17789017, -3395995}, + {-30552961, -2228401, -15578829, -10147201, 13243889, 517024, + 15479401, -3853233, 30460520, 1052596}, + {-11614875, 13323618, 32618793, 8175907, -15230173, 12596687, + 27491595, -4612359, 3179268, -9478891}, + }, + { + {31947069, -14366651, -4640583, -15339921, -15125977, -6039709, + -14756777, -16411740, 19072640, -9511060}, + {11685058, 11822410, 3158003, -13952594, 33402194, -4165066, + 5977896, -5215017, 473099, 5040608}, + {-20290863, 8198642, -27410132, 11602123, 1290375, -2799760, + 28326862, 1721092, -19558642, -3131606}, + }, + }, + { + { + {7881532, 10687937, 7578723, 7738378, -18951012, -2553952, 21820786, + 8076149, -27868496, 11538389}, + {-19935666, 3899861, 18283497, -6801568, -15728660, -11249211, + 8754525, 7446702, -5676054, 5797016}, + {-11295600, -3793569, -15782110, -7964573, 12708869, -8456199, + 2014099, -9050574, -2369172, -5877341}, + }, + { + {-22472376, -11568741, -27682020, 1146375, 18956691, 16640559, + 1192730, -3714199, 15123619, 10811505}, + {14352098, -3419715, -18942044, 10822655, 32750596, 4699007, -70363, + 15776356, -28886779, -11974553}, + {-28241164, -8072475, -4978962, -5315317, 29416931, 1847569, + -20654173, -16484855, 4714547, -9600655}, + }, + { + {15200332, 8368572, 19679101, 15970074, -31872674, 1959451, + 24611599, -4543832, -11745876, 12340220}, + {12876937, -10480056, 33134381, 6590940, -6307776, 14872440, + 9613953, 8241152, 15370987, 9608631}, + {-4143277, -12014408, 8446281, -391603, 4407738, 13629032, -7724868, + 15866074, -28210621, -8814099}, + }, + { + {26660628, -15677655, 8393734, 358047, -7401291, 992988, -23904233, + 858697, 20571223, 8420556}, + {14620715, 13067227, -15447274, 8264467, 14106269, 15080814, + 33531827, 12516406, -21574435, -12476749}, + {236881, 10476226, 57258, -14677024, 6472998, 2466984, 17258519, + 7256740, 8791136, 15069930}, + }, + { + {1276410, -9371918, 22949635, -16322807, -23493039, -5702186, + 14711875, 4874229, -30663140, -2331391}, + {5855666, 4990204, -13711848, 7294284, -7804282, 1924647, -1423175, + -7912378, -33069337, 9234253}, + {20590503, -9018988, 31529744, -7352666, -2706834, 10650548, + 31559055, -11609587, 18979186, 13396066}, + }, + { + {24474287, 4968103, 22267082, 4407354, 24063882, -8325180, + -18816887, 13594782, 33514650, 7021958}, + {-11566906, -6565505, -21365085, 15928892, -26158305, 4315421, + -25948728, -3916677, -21480480, 12868082}, + {-28635013, 13504661, 19988037, -2132761, 21078225, 6443208, + -21446107, 2244500, -12455797, -8089383}, + }, + { + {-30595528, 13793479, -5852820, 319136, -25723172, -6263899, + 33086546, 8957937, -15233648, 5540521}, + {-11630176, -11503902, -8119500, -7643073, 2620056, 1022908, + -23710744, -1568984, -16128528, -14962807}, + {23152971, 775386, 27395463, 14006635, -9701118, 4649512, 1689819, + 892185, -11513277, -15205948}, + }, + { + {9770129, 9586738, 26496094, 4324120, 1556511, -3550024, 27453819, + 4763127, -19179614, 5867134}, + {-32765025, 1927590, 31726409, -4753295, 23962434, -16019500, + 27846559, 5931263, -29749703, -16108455}, + {27461885, -2977536, 22380810, 1815854, -23033753, -3031938, + 7283490, -15148073, -19526700, 7734629}, + }, + }, + { + { + {-8010264, -9590817, -11120403, 6196038, 29344158, -13430885, + 7585295, -3176626, 18549497, 15302069}, + {-32658337, -6171222, -7672793, -11051681, 6258878, 13504381, + 10458790, -6418461, -8872242, 8424746}, + {24687205, 8613276, -30667046, -3233545, 1863892, -1830544, + 19206234, 7134917, -11284482, -828919}, + }, + { + {11334899, -9218022, 8025293, 12707519, 17523892, -10476071, + 10243738, -14685461, -5066034, 16498837}, + {8911542, 6887158, -9584260, -6958590, 11145641, -9543680, 17303925, + -14124238, 6536641, 10543906}, + {-28946384, 15479763, -17466835, 568876, -1497683, 11223454, + -2669190, -16625574, -27235709, 8876771}, + }, + { + {-25742899, -12566864, -15649966, -846607, -33026686, -796288, + -33481822, 15824474, -604426, -9039817}, + {10330056, 70051, 7957388, -9002667, 9764902, 15609756, 27698697, + -4890037, 1657394, 3084098}, + {10477963, -7470260, 12119566, -13250805, 29016247, -5365589, + 31280319, 14396151, -30233575, 15272409}, + }, + { + {-12288309, 3169463, 28813183, 16658753, 25116432, -5630466, + -25173957, -12636138, -25014757, 1950504}, + {-26180358, 9489187, 11053416, -14746161, -31053720, 5825630, + -8384306, -8767532, 15341279, 8373727}, + {28685821, 7759505, -14378516, -12002860, -31971820, 4079242, + 298136, -10232602, -2878207, 15190420}, + }, + { + {-32932876, 13806336, -14337485, -15794431, -24004620, 10940928, + 8669718, 2742393, -26033313, -6875003}, + {-1580388, -11729417, -25979658, -11445023, -17411874, -10912854, + 9291594, -16247779, -12154742, 6048605}, + {-30305315, 14843444, 1539301, 11864366, 20201677, 1900163, + 13934231, 5128323, 11213262, 9168384}, + }, + { + {-26280513, 11007847, 19408960, -940758, -18592965, -4328580, + -5088060, -11105150, 20470157, -16398701}, + {-23136053, 9282192, 14855179, -15390078, -7362815, -14408560, + -22783952, 14461608, 14042978, 5230683}, + {29969567, -2741594, -16711867, -8552442, 9175486, -2468974, + 21556951, 3506042, -5933891, -12449708}, + }, + { + {-3144746, 8744661, 19704003, 4581278, -20430686, 6830683, + -21284170, 8971513, -28539189, 15326563}, + {-19464629, 10110288, -17262528, -3503892, -23500387, 1355669, + -15523050, 15300988, -20514118, 9168260}, + {-5353335, 4488613, -23803248, 16314347, 7780487, -15638939, + -28948358, 9601605, 33087103, -9011387}, + }, + { + {-19443170, -15512900, -20797467, -12445323, -29824447, 10229461, + -27444329, -15000531, -5996870, 15664672}, + {23294591, -16632613, -22650781, -8470978, 27844204, 11461195, + 13099750, -2460356, 18151676, 13417686}, + {-24722913, -4176517, -31150679, 5988919, -26858785, 6685065, + 1661597, -12551441, 15271676, -15452665}, + }, + }, + { + { + {11433042, -13228665, 8239631, -5279517, -1985436, -725718, + -18698764, 2167544, -6921301, -13440182}, + {-31436171, 15575146, 30436815, 12192228, -22463353, 9395379, + -9917708, -8638997, 12215110, 12028277}, + {14098400, 6555944, 23007258, 5757252, -15427832, -12950502, + 30123440, 4617780, -16900089, -655628}, + }, + { + {-4026201, -15240835, 11893168, 13718664, -14809462, 1847385, + -15819999, 10154009, 23973261, -12684474}, + {-26531820, -3695990, -1908898, 2534301, -31870557, -16550355, + 18341390, -11419951, 32013174, -10103539}, + {-25479301, 10876443, -11771086, -14625140, -12369567, 1838104, + 21911214, 6354752, 4425632, -837822}, + }, + { + {-10433389, -14612966, 22229858, -3091047, -13191166, 776729, + -17415375, -12020462, 4725005, 14044970}, + {19268650, -7304421, 1555349, 8692754, -21474059, -9910664, 6347390, + -1411784, -19522291, -16109756}, + {-24864089, 12986008, -10898878, -5558584, -11312371, -148526, + 19541418, 8180106, 9282262, 10282508}, + }, + { + {-26205082, 4428547, -8661196, -13194263, 4098402, -14165257, + 15522535, 8372215, 5542595, -10702683}, + {-10562541, 14895633, 26814552, -16673850, -17480754, -2489360, + -2781891, 6993761, -18093885, 10114655}, + {-20107055, -929418, 31422704, 10427861, -7110749, 6150669, + -29091755, -11529146, 25953725, -106158}, + }, + { + {-4234397, -8039292, -9119125, 3046000, 2101609, -12607294, + 19390020, 6094296, -3315279, 12831125}, + {-15998678, 7578152, 5310217, 14408357, -33548620, -224739, + 31575954, 6326196, 7381791, -2421839}, + {-20902779, 3296811, 24736065, -16328389, 18374254, 7318640, + 6295303, 8082724, -15362489, 12339664}, + }, + { + {27724736, 2291157, 6088201, -14184798, 1792727, 5857634, 13848414, + 15768922, 25091167, 14856294}, + {-18866652, 8331043, 24373479, 8541013, -701998, -9269457, 12927300, + -12695493, -22182473, -9012899}, + {-11423429, -5421590, 11632845, 3405020, 30536730, -11674039, + -27260765, 13866390, 30146206, 9142070}, + }, + { + {3924129, -15307516, -13817122, -10054960, 12291820, -668366, + -27702774, 9326384, -8237858, 4171294}, + {-15921940, 16037937, 6713787, 16606682, -21612135, 2790944, + 26396185, 3731949, 345228, -5462949}, + {-21327538, 13448259, 25284571, 1143661, 20614966, -8849387, + 2031539, -12391231, -16253183, -13582083}, + }, + { + {31016211, -16722429, 26371392, -14451233, -5027349, 14854137, + 17477601, 3842657, 28012650, -16405420}, + {-5075835, 9368966, -8562079, -4600902, -15249953, 6970560, + -9189873, 16292057, -8867157, 3507940}, + {29439664, 3537914, 23333589, 6997794, -17555561, -11018068, + -15209202, -15051267, -9164929, 6580396}, + }, + }, + { + { + {-12185861, -7679788, 16438269, 10826160, -8696817, -6235611, + 17860444, -9273846, -2095802, 9304567}, + {20714564, -4336911, 29088195, 7406487, 11426967, -5095705, + 14792667, -14608617, 5289421, -477127}, + {-16665533, -10650790, -6160345, -13305760, 9192020, -1802462, + 17271490, 12349094, 26939669, -3752294}, + }, + { + {-12889898, 9373458, 31595848, 16374215, 21471720, 13221525, + -27283495, -12348559, -3698806, 117887}, + {22263325, -6560050, 3984570, -11174646, -15114008, -566785, + 28311253, 5358056, -23319780, 541964}, + {16259219, 3261970, 2309254, -15534474, -16885711, -4581916, + 24134070, -16705829, -13337066, -13552195}, + }, + { + {9378160, -13140186, -22845982, -12745264, 28198281, -7244098, + -2399684, -717351, 690426, 14876244}, + {24977353, -314384, -8223969, -13465086, 28432343, -1176353, + -13068804, -12297348, -22380984, 6618999}, + {-1538174, 11685646, 12944378, 13682314, -24389511, -14413193, + 8044829, -13817328, 32239829, -5652762}, + }, + { + {-18603066, 4762990, -926250, 8885304, -28412480, -3187315, 9781647, + -10350059, 32779359, 5095274}, + {-33008130, -5214506, -32264887, -3685216, 9460461, -9327423, + -24601656, 14506724, 21639561, -2630236}, + {-16400943, -13112215, 25239338, 15531969, 3987758, -4499318, + -1289502, -6863535, 17874574, 558605}, + }, + { + {-13600129, 10240081, 9171883, 16131053, -20869254, 9599700, + 33499487, 5080151, 2085892, 5119761}, + {-22205145, -2519528, -16381601, 414691, -25019550, 2170430, + 30634760, -8363614, -31999993, -5759884}, + {-6845704, 15791202, 8550074, -1312654, 29928809, -12092256, + 27534430, -7192145, -22351378, 12961482}, + }, + { + {-24492060, -9570771, 10368194, 11582341, -23397293, -2245287, + 16533930, 8206996, -30194652, -5159638}, + {-11121496, -3382234, 2307366, 6362031, -135455, 8868177, -16835630, + 7031275, 7589640, 8945490}, + {-32152748, 8917967, 6661220, -11677616, -1192060, -15793393, + 7251489, -11182180, 24099109, -14456170}, + }, + { + {5019558, -7907470, 4244127, -14714356, -26933272, 6453165, + -19118182, -13289025, -6231896, -10280736}, + {10853594, 10721687, 26480089, 5861829, -22995819, 1972175, + -1866647, -10557898, -3363451, -6441124}, + {-17002408, 5906790, 221599, -6563147, 7828208, -13248918, 24362661, + -2008168, -13866408, 7421392}, + }, + { + {8139927, -6546497, 32257646, -5890546, 30375719, 1886181, + -21175108, 15441252, 28826358, -4123029}, + {6267086, 9695052, 7709135, -16603597, -32869068, -1886135, + 14795160, -7840124, 13746021, -1742048}, + {28584902, 7787108, -6732942, -15050729, 22846041, -7571236, + -3181936, -363524, 4771362, -8419958}, + }, + }, + { + { + {24949256, 6376279, -27466481, -8174608, -18646154, -9930606, + 33543569, -12141695, 3569627, 11342593}, + {26514989, 4740088, 27912651, 3697550, 19331575, -11472339, 6809886, + 4608608, 7325975, -14801071}, + {-11618399, -14554430, -24321212, 7655128, -1369274, 5214312, + -27400540, 10258390, -17646694, -8186692}, + }, + { + {11431204, 15823007, 26570245, 14329124, 18029990, 4796082, + -31446179, 15580664, 9280358, -3973687}, + {-160783, -10326257, -22855316, -4304997, -20861367, -13621002, + -32810901, -11181622, -15545091, 4387441}, + {-20799378, 12194512, 3937617, -5805892, -27154820, 9340370, + -24513992, 8548137, 20617071, -7482001}, + }, + { + {-938825, -3930586, -8714311, 16124718, 24603125, -6225393, + -13775352, -11875822, 24345683, 10325460}, + {-19855277, -1568885, -22202708, 8714034, 14007766, 6928528, + 16318175, -1010689, 4766743, 3552007}, + {-21751364, -16730916, 1351763, -803421, -4009670, 3950935, 3217514, + 14481909, 10988822, -3994762}, + }, + { + {15564307, -14311570, 3101243, 5684148, 30446780, -8051356, + 12677127, -6505343, -8295852, 13296005}, + {-9442290, 6624296, -30298964, -11913677, -4670981, -2057379, + 31521204, 9614054, -30000824, 12074674}, + {4771191, -135239, 14290749, -13089852, 27992298, 14998318, + -1413936, -1556716, 29832613, -16391035}, + }, + { + {7064884, -7541174, -19161962, -5067537, -18891269, -2912736, + 25825242, 5293297, -27122660, 13101590}, + {-2298563, 2439670, -7466610, 1719965, -27267541, -16328445, + 32512469, -5317593, -30356070, -4190957}, + {-30006540, 10162316, -33180176, 3981723, -16482138, -13070044, + 14413974, 9515896, 19568978, 9628812}, + }, + { + {33053803, 199357, 15894591, 1583059, 27380243, -4580435, -17838894, + -6106839, -6291786, 3437740}, + {-18978877, 3884493, 19469877, 12726490, 15913552, 13614290, + -22961733, 70104, 7463304, 4176122}, + {-27124001, 10659917, 11482427, -16070381, 12771467, -6635117, + -32719404, -5322751, 24216882, 5944158}, + }, + { + {8894125, 7450974, -2664149, -9765752, -28080517, -12389115, + 19345746, 14680796, 11632993, 5847885}, + {26942781, -2315317, 9129564, -4906607, 26024105, 11769399, + -11518837, 6367194, -9727230, 4782140}, + {19916461, -4828410, -22910704, -11414391, 25606324, -5972441, + 33253853, 8220911, 6358847, -1873857}, + }, + { + {801428, -2081702, 16569428, 11065167, 29875704, 96627, 7908388, + -4480480, -13538503, 1387155}, + {19646058, 5720633, -11416706, 12814209, 11607948, 12749789, + 14147075, 15156355, -21866831, 11835260}, + {19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523, + 15467869, -26560550, 5052483}, + }, + }, + { + { + {-3017432, 10058206, 1980837, 3964243, 22160966, 12322533, -6431123, + -12618185, 12228557, -7003677}, + {32944382, 14922211, -22844894, 5188528, 21913450, -8719943, + 4001465, 13238564, -6114803, 8653815}, + {22865569, -4652735, 27603668, -12545395, 14348958, 8234005, + 24808405, 5719875, 28483275, 2841751}, + }, + { + {-16420968, -1113305, -327719, -12107856, 21886282, -15552774, + -1887966, -315658, 19932058, -12739203}, + {-11656086, 10087521, -8864888, -5536143, -19278573, -3055912, + 3999228, 13239134, -4777469, -13910208}, + {1382174, -11694719, 17266790, 9194690, -13324356, 9720081, + 20403944, 11284705, -14013818, 3093230}, + }, + { + {16650921, -11037932, -1064178, 1570629, -8329746, 7352753, -302424, + 16271225, -24049421, -6691850}, + {-21911077, -5927941, -4611316, -5560156, -31744103, -10785293, + 24123614, 15193618, -21652117, -16739389}, + {-9935934, -4289447, -25279823, 4372842, 2087473, 10399484, + 31870908, 14690798, 17361620, 11864968}, + }, + { + {-11307610, 6210372, 13206574, 5806320, -29017692, -13967200, + -12331205, -7486601, -25578460, -16240689}, + {14668462, -12270235, 26039039, 15305210, 25515617, 4542480, + 10453892, 6577524, 9145645, -6443880}, + {5974874, 3053895, -9433049, -10385191, -31865124, 3225009, + -7972642, 3936128, -5652273, -3050304}, + }, + { + {30625386, -4729400, -25555961, -12792866, -20484575, 7695099, + 17097188, -16303496, -27999779, 1803632}, + {-3553091, 9865099, -5228566, 4272701, -5673832, -16689700, + 14911344, 12196514, -21405489, 7047412}, + {20093277, 9920966, -11138194, -5343857, 13161587, 12044805, + -32856851, 4124601, -32343828, -10257566}, + }, + { + {-20788824, 14084654, -13531713, 7842147, 19119038, -13822605, + 4752377, -8714640, -21679658, 2288038}, + {-26819236, -3283715, 29965059, 3039786, -14473765, 2540457, + 29457502, 14625692, -24819617, 12570232}, + {-1063558, -11551823, 16920318, 12494842, 1278292, -5869109, + -21159943, -3498680, -11974704, 4724943}, + }, + { + {17960970, -11775534, -4140968, -9702530, -8876562, -1410617, + -12907383, -8659932, -29576300, 1903856}, + {23134274, -14279132, -10681997, -1611936, 20684485, 15770816, + -12989750, 3190296, 26955097, 14109738}, + {15308788, 5320727, -30113809, -14318877, 22902008, 7767164, + 29425325, -11277562, 31960942, 11934971}, + }, + { + {-27395711, 8435796, 4109644, 12222639, -24627868, 14818669, + 20638173, 4875028, 10491392, 1379718}, + {-13159415, 9197841, 3875503, -8936108, -1383712, -5879801, + 33518459, 16176658, 21432314, 12180697}, + {-11787308, 11500838, 13787581, -13832590, -22430679, 10140205, + 1465425, 12689540, -10301319, -13872883}, + }, + }, + { + { + {5414091, -15386041, -21007664, 9643570, 12834970, 1186149, + -2622916, -1342231, 26128231, 6032912}, + {-26337395, -13766162, 32496025, -13653919, 17847801, -12669156, + 3604025, 8316894, -25875034, -10437358}, + {3296484, 6223048, 24680646, -12246460, -23052020, 5903205, + -8862297, -4639164, 12376617, 3188849}, + }, + { + {29190488, -14659046, 27549113, -1183516, 3520066, -10697301, + 32049515, -7309113, -16109234, -9852307}, + {-14744486, -9309156, 735818, -598978, -20407687, -5057904, + 25246078, -15795669, 18640741, -960977}, + {-6928835, -16430795, 10361374, 5642961, 4910474, 12345252, + -31638386, -494430, 10530747, 1053335}, + }, + { + {-29265967, -14186805, -13538216, -12117373, -19457059, -10655384, + -31462369, -2948985, 24018831, 15026644}, + {-22592535, -3145277, -2289276, 5953843, -13440189, 9425631, + 25310643, 13003497, -2314791, -15145616}, + {-27419985, -603321, -8043984, -1669117, -26092265, 13987819, + -27297622, 187899, -23166419, -2531735}, + }, + { + {-21744398, -13810475, 1844840, 5021428, -10434399, -15911473, + 9716667, 16266922, -5070217, 726099}, + {29370922, -6053998, 7334071, -15342259, 9385287, 2247707, + -13661962, -4839461, 30007388, -15823341}, + {-936379, 16086691, 23751945, -543318, -1167538, -5189036, 9137109, + 730663, 9835848, 4555336}, + }, + { + {-23376435, 1410446, -22253753, -12899614, 30867635, 15826977, + 17693930, 544696, -11985298, 12422646}, + {31117226, -12215734, -13502838, 6561947, -9876867, -12757670, + -5118685, -4096706, 29120153, 13924425}, + {-17400879, -14233209, 19675799, -2734756, -11006962, -5858820, + -9383939, -11317700, 7240931, -237388}, + }, + { + {-31361739, -11346780, -15007447, -5856218, -22453340, -12152771, + 1222336, 4389483, 3293637, -15551743}, + {-16684801, -14444245, 11038544, 11054958, -13801175, -3338533, + -24319580, 7733547, 12796905, -6335822}, + {-8759414, -10817836, -25418864, 10783769, -30615557, -9746811, + -28253339, 3647836, 3222231, -11160462}, + }, + { + {18606113, 1693100, -25448386, -15170272, 4112353, 10045021, + 23603893, -2048234, -7550776, 2484985}, + {9255317, -3131197, -12156162, -1004256, 13098013, -9214866, + 16377220, -2102812, -19802075, -3034702}, + {-22729289, 7496160, -5742199, 11329249, 19991973, -3347502, + -31718148, 9936966, -30097688, -10618797}, + }, + { + {21878590, -5001297, 4338336, 13643897, -3036865, 13160960, + 19708896, 5415497, -7360503, -4109293}, + {27736861, 10103576, 12500508, 8502413, -3413016, -9633558, + 10436918, -1550276, -23659143, -8132100}, + {19492550, -12104365, -29681976, -852630, -3208171, 12403437, + 30066266, 8367329, 13243957, 8709688}, + }, + }, + { + { + {12015105, 2801261, 28198131, 10151021, 24818120, -4743133, + -11194191, -5645734, 5150968, 7274186}, + {2831366, -12492146, 1478975, 6122054, 23825128, -12733586, + 31097299, 6083058, 31021603, -9793610}, + {-2529932, -2229646, 445613, 10720828, -13849527, -11505937, + -23507731, 16354465, 15067285, -14147707}, + }, + { + {7840942, 14037873, -33364863, 15934016, -728213, -3642706, + 21403988, 1057586, -19379462, -12403220}, + {915865, -16469274, 15608285, -8789130, -24357026, 6060030, + -17371319, 8410997, -7220461, 16527025}, + {32922597, -556987, 20336074, -16184568, 10903705, -5384487, + 16957574, 52992, 23834301, 6588044}, + }, + { + {32752030, 11232950, 3381995, -8714866, 22652988, -10744103, + 17159699, 16689107, -20314580, -1305992}, + {-4689649, 9166776, -25710296, -10847306, 11576752, 12733943, + 7924251, -2752281, 1976123, -7249027}, + {21251222, 16309901, -2983015, -6783122, 30810597, 12967303, 156041, + -3371252, 12331345, -8237197}, + }, + { + {8651614, -4477032, -16085636, -4996994, 13002507, 2950805, + 29054427, -5106970, 10008136, -4667901}, + {31486080, 15114593, -14261250, 12951354, 14369431, -7387845, + 16347321, -13662089, 8684155, -10532952}, + {19443825, 11385320, 24468943, -9659068, -23919258, 2187569, + -26263207, -6086921, 31316348, 14219878}, + }, + { + {-28594490, 1193785, 32245219, 11392485, 31092169, 15722801, + 27146014, 6992409, 29126555, 9207390}, + {32382935, 1110093, 18477781, 11028262, -27411763, -7548111, + -4980517, 10843782, -7957600, -14435730}, + {2814918, 7836403, 27519878, -7868156, -20894015, -11553689, + -21494559, 8550130, 28346258, 1994730}, + }, + { + {-19578299, 8085545, -14000519, -3948622, 2785838, -16231307, + -19516951, 7174894, 22628102, 8115180}, + {-30405132, 955511, -11133838, -15078069, -32447087, -13278079, + -25651578, 3317160, -9943017, 930272}, + {-15303681, -6833769, 28856490, 1357446, 23421993, 1057177, + 24091212, -1388970, -22765376, -10650715}, + }, + { + {-22751231, -5303997, -12907607, -12768866, -15811511, -7797053, + -14839018, -16554220, -1867018, 8398970}, + {-31969310, 2106403, -4736360, 1362501, 12813763, 16200670, + 22981545, -6291273, 18009408, -15772772}, + {-17220923, -9545221, -27784654, 14166835, 29815394, 7444469, + 29551787, -3727419, 19288549, 1325865}, + }, + { + {15100157, -15835752, -23923978, -1005098, -26450192, 15509408, + 12376730, -3479146, 33166107, -8042750}, + {20909231, 13023121, -9209752, 16251778, -5778415, -8094914, + 12412151, 10018715, 2213263, -13878373}, + {32529814, -11074689, 30361439, -16689753, -9135940, 1513226, + 22922121, 6382134, -5766928, 8371348}, + }, + }, + { + { + {9923462, 11271500, 12616794, 3544722, -29998368, -1721626, + 12891687, -8193132, -26442943, 10486144}, + {-22597207, -7012665, 8587003, -8257861, 4084309, -12970062, 361726, + 2610596, -23921530, -11455195}, + {5408411, -1136691, -4969122, 10561668, 24145918, 14240566, + 31319731, -4235541, 19985175, -3436086}, + }, + { + {-13994457, 16616821, 14549246, 3341099, 32155958, 13648976, + -17577068, 8849297, 65030, 8370684}, + {-8320926, -12049626, 31204563, 5839400, -20627288, -1057277, + -19442942, 6922164, 12743482, -9800518}, + {-2361371, 12678785, 28815050, 4759974, -23893047, 4884717, + 23783145, 11038569, 18800704, 255233}, + }, + { + {-5269658, -1773886, 13957886, 7990715, 23132995, 728773, 13393847, + 9066957, 19258688, -14753793}, + {-2936654, -10827535, -10432089, 14516793, -3640786, 4372541, + -31934921, 2209390, -1524053, 2055794}, + {580882, 16705327, 5468415, -2683018, -30926419, -14696000, + -7203346, -8994389, -30021019, 7394435}, + }, + { + {23838809, 1822728, -15738443, 15242727, 8318092, -3733104, + -21672180, -3492205, -4821741, 14799921}, + {13345610, 9759151, 3371034, -16137791, 16353039, 8577942, 31129804, + 13496856, -9056018, 7402518}, + {2286874, -4435931, -20042458, -2008336, -13696227, 5038122, + 11006906, -15760352, 8205061, 1607563}, + }, + { + {14414086, -8002132, 3331830, -3208217, 22249151, -5594188, + 18364661, -2906958, 30019587, -9029278}, + {-27688051, 1585953, -10775053, 931069, -29120221, -11002319, + -14410829, 12029093, 9944378, 8024}, + {4368715, -3709630, 29874200, -15022983, -20230386, -11410704, + -16114594, -999085, -8142388, 5640030}, + }, + { + {10299610, 13746483, 11661824, 16234854, 7630238, 5998374, 9809887, + -16694564, 15219798, -14327783}, + {27425505, -5719081, 3055006, 10660664, 23458024, 595578, -15398605, + -1173195, -18342183, 9742717}, + {6744077, 2427284, 26042789, 2720740, -847906, 1118974, 32324614, + 7406442, 12420155, 1994844}, + }, + { + {14012521, -5024720, -18384453, -9578469, -26485342, -3936439, + -13033478, -10909803, 24319929, -6446333}, + {16412690, -4507367, 10772641, 15929391, -17068788, -4658621, + 10555945, -10484049, -30102368, -4739048}, + {22397382, -7767684, -9293161, -12792868, 17166287, -9755136, + -27333065, 6199366, 21880021, -12250760}, + }, + { + {-4283307, 5368523, -31117018, 8163389, -30323063, 3209128, + 16557151, 8890729, 8840445, 4957760}, + {-15447727, 709327, -6919446, -10870178, -29777922, 6522332, + -21720181, 12130072, -14796503, 5005757}, + {-2114751, -14308128, 23019042, 15765735, -25269683, 6002752, + 10183197, -13239326, -16395286, -2176112}, + }, + }, + { + { + {-19025756, 1632005, 13466291, -7995100, -23640451, 16573537, + -32013908, -3057104, 22208662, 2000468}, + {3065073, -1412761, -25598674, -361432, -17683065, -5703415, + -8164212, 11248527, -3691214, -7414184}, + {10379208, -6045554, 8877319, 1473647, -29291284, -12507580, + 16690915, 2553332, -3132688, 16400289}, + }, + { + {15716668, 1254266, -18472690, 7446274, -8448918, 6344164, + -22097271, -7285580, 26894937, 9132066}, + {24158887, 12938817, 11085297, -8177598, -28063478, -4457083, + -30576463, 64452, -6817084, -2692882}, + {13488534, 7794716, 22236231, 5989356, 25426474, -12578208, 2350710, + -3418511, -4688006, 2364226}, + }, + { + {16335052, 9132434, 25640582, 6678888, 1725628, 8517937, -11807024, + -11697457, 15445875, -7798101}, + {29004207, -7867081, 28661402, -640412, -12794003, -7943086, + 31863255, -4135540, -278050, -15759279}, + {-6122061, -14866665, -28614905, 14569919, -10857999, -3591829, + 10343412, -6976290, -29828287, -10815811}, + }, + { + {27081650, 3463984, 14099042, -4517604, 1616303, -6205604, 29542636, + 15372179, 17293797, 960709}, + {20263915, 11434237, -5765435, 11236810, 13505955, -10857102, + -16111345, 6493122, -19384511, 7639714}, + {-2830798, -14839232, 25403038, -8215196, -8317012, -16173699, + 18006287, -16043750, 29994677, -15808121}, + }, + { + {9769828, 5202651, -24157398, -13631392, -28051003, -11561624, + -24613141, -13860782, -31184575, 709464}, + {12286395, 13076066, -21775189, -1176622, -25003198, 4057652, + -32018128, -8890874, 16102007, 13205847}, + {13733362, 5599946, 10557076, 3195751, -5557991, 8536970, -25540170, + 8525972, 10151379, 10394400}, + }, + { + {4024660, -16137551, 22436262, 12276534, -9099015, -2686099, + 19698229, 11743039, -33302334, 8934414}, + {-15879800, -4525240, -8580747, -2934061, 14634845, -698278, + -9449077, 3137094, -11536886, 11721158}, + {17555939, -5013938, 8268606, 2331751, -22738815, 9761013, 9319229, + 8835153, -9205489, -1280045}, + }, + { + {-461409, -7830014, 20614118, 16688288, -7514766, -4807119, + 22300304, 505429, 6108462, -6183415}, + {-5070281, 12367917, -30663534, 3234473, 32617080, -8422642, + 29880583, -13483331, -26898490, -7867459}, + {-31975283, 5726539, 26934134, 10237677, -3173717, -605053, + 24199304, 3795095, 7592688, -14992079}, + }, + { + {21594432, -14964228, 17466408, -4077222, 32537084, 2739898, + 6407723, 12018833, -28256052, 4298412}, + {-20650503, -11961496, -27236275, 570498, 3767144, -1717540, + 13891942, -1569194, 13717174, 10805743}, + {-14676630, -15644296, 15287174, 11927123, 24177847, -8175568, + -796431, 14860609, -26938930, -5863836}, + }, + }, + { + { + {12962541, 5311799, -10060768, 11658280, 18855286, -7954201, + 13286263, -12808704, -4381056, 9882022}, + {18512079, 11319350, -20123124, 15090309, 18818594, 5271736, + -22727904, 3666879, -23967430, -3299429}, + {-6789020, -3146043, 16192429, 13241070, 15898607, -14206114, + -10084880, -6661110, -2403099, 5276065}, + }, + { + {30169808, -5317648, 26306206, -11750859, 27814964, 7069267, + 7152851, 3684982, 1449224, 13082861}, + {10342826, 3098505, 2119311, 193222, 25702612, 12233820, 23697382, + 15056736, -21016438, -8202000}, + {-33150110, 3261608, 22745853, 7948688, 19370557, -15177665, + -26171976, 6482814, -10300080, -11060101}, + }, + { + {32869458, -5408545, 25609743, 15678670, -10687769, -15471071, + 26112421, 2521008, -22664288, 6904815}, + {29506923, 4457497, 3377935, -9796444, -30510046, 12935080, 1561737, + 3841096, -29003639, -6657642}, + {10340844, -6630377, -18656632, -2278430, 12621151, -13339055, + 30878497, -11824370, -25584551, 5181966}, + }, + { + {25940115, -12658025, 17324188, -10307374, -8671468, 15029094, + 24396252, -16450922, -2322852, -12388574}, + {-21765684, 9916823, -1300409, 4079498, -1028346, 11909559, 1782390, + 12641087, 20603771, -6561742}, + {-18882287, -11673380, 24849422, 11501709, 13161720, -4768874, + 1925523, 11914390, 4662781, 7820689}, + }, + { + {12241050, -425982, 8132691, 9393934, 32846760, -1599620, 29749456, + 12172924, 16136752, 15264020}, + {-10349955, -14680563, -8211979, 2330220, -17662549, -14545780, + 10658213, 6671822, 19012087, 3772772}, + {3753511, -3421066, 10617074, 2028709, 14841030, -6721664, 28718732, + -15762884, 20527771, 12988982}, + }, + { + {-14822485, -5797269, -3707987, 12689773, -898983, -10914866, + -24183046, -10564943, 3299665, -12424953}, + {-16777703, -15253301, -9642417, 4978983, 3308785, 8755439, 6943197, + 6461331, -25583147, 8991218}, + {-17226263, 1816362, -1673288, -6086439, 31783888, -8175991, + -32948145, 7417950, -30242287, 1507265}, + }, + { + {29692663, 6829891, -10498800, 4334896, 20945975, -11906496, + -28887608, 8209391, 14606362, -10647073}, + {-3481570, 8707081, 32188102, 5672294, 22096700, 1711240, -33020695, + 9761487, 4170404, -2085325}, + {-11587470, 14855945, -4127778, -1531857, -26649089, 15084046, + 22186522, 16002000, -14276837, -8400798}, + }, + { + {-4811456, 13761029, -31703877, -2483919, -3312471, 7869047, + -7113572, -9620092, 13240845, 10965870}, + {-7742563, -8256762, -14768334, -13656260, -23232383, 12387166, + 4498947, 14147411, 29514390, 4302863}, + {-13413405, -12407859, 20757302, -13801832, 14785143, 8976368, + -5061276, -2144373, 17846988, -13971927}, + }, + }, + { + { + {-2244452, -754728, -4597030, -1066309, -6247172, 1455299, + -21647728, -9214789, -5222701, 12650267}, + {-9906797, -16070310, 21134160, 12198166, -27064575, 708126, 387813, + 13770293, -19134326, 10958663}, + {22470984, 12369526, 23446014, -5441109, -21520802, -9698723, + -11772496, -11574455, -25083830, 4271862}, + }, + { + {-25169565, -10053642, -19909332, 15361595, -5984358, 2159192, + 75375, -4278529, -32526221, 8469673}, + {15854970, 4148314, -8893890, 7259002, 11666551, 13824734, + -30531198, 2697372, 24154791, -9460943}, + {15446137, -15806644, 29759747, 14019369, 30811221, -9610191, + -31582008, 12840104, 24913809, 9815020}, + }, + { + {-4709286, -5614269, -31841498, -12288893, -14443537, 10799414, + -9103676, 13438769, 18735128, 9466238}, + {11933045, 9281483, 5081055, -5183824, -2628162, -4905629, -7727821, + -10896103, -22728655, 16199064}, + {14576810, 379472, -26786533, -8317236, -29426508, -10812974, + -102766, 1876699, 30801119, 2164795}, + }, + { + {15995086, 3199873, 13672555, 13712240, -19378835, -4647646, + -13081610, -15496269, -13492807, 1268052}, + {-10290614, -3659039, -3286592, 10948818, 23037027, 3794475, + -3470338, -12600221, -17055369, 3565904}, + {29210088, -9419337, -5919792, -4952785, 10834811, -13327726, + -16512102, -10820713, -27162222, -14030531}, + }, + { + {-13161890, 15508588, 16663704, -8156150, -28349942, 9019123, + -29183421, -3769423, 2244111, -14001979}, + {-5152875, -3800936, -9306475, -6071583, 16243069, 14684434, + -25673088, -16180800, 13491506, 4641841}, + {10813417, 643330, -19188515, -728916, 30292062, -16600078, + 27548447, -7721242, 14476989, -12767431}, + }, + { + {10292079, 9984945, 6481436, 8279905, -7251514, 7032743, 27282937, + -1644259, -27912810, 12651324}, + {-31185513, -813383, 22271204, 11835308, 10201545, 15351028, + 17099662, 3988035, 21721536, -3148940}, + {10202177, -6545839, -31373232, -9574638, -32150642, -8119683, + -12906320, 3852694, 13216206, 14842320}, + }, + { + {-15815640, -10601066, -6538952, -7258995, -6984659, -6581778, + -31500847, 13765824, -27434397, 9900184}, + {14465505, -13833331, -32133984, -14738873, -27443187, 12990492, + 33046193, 15796406, -7051866, -8040114}, + {30924417, -8279620, 6359016, -12816335, 16508377, 9071735, + -25488601, 15413635, 9524356, -7018878}, + }, + { + {12274201, -13175547, 32627641, -1785326, 6736625, 13267305, + 5237659, -5109483, 15663516, 4035784}, + {-2951309, 8903985, 17349946, 601635, -16432815, -4612556, + -13732739, -15889334, -22258478, 4659091}, + {-16916263, -4952973, -30393711, -15158821, 20774812, 15897498, + 5736189, 15026997, -2178256, -13455585}, + }, + }, + { + { + {-8858980, -2219056, 28571666, -10155518, -474467, -10105698, + -3801496, 278095, 23440562, -290208}, + {10226241, -5928702, 15139956, 120818, -14867693, 5218603, 32937275, + 11551483, -16571960, -7442864}, + {17932739, -12437276, -24039557, 10749060, 11316803, 7535897, + 22503767, 5561594, -3646624, 3898661}, + }, + { + {7749907, -969567, -16339731, -16464, -25018111, 15122143, -1573531, + 7152530, 21831162, 1245233}, + {26958459, -14658026, 4314586, 8346991, -5677764, 11960072, + -32589295, -620035, -30402091, -16716212}, + {-12165896, 9166947, 33491384, 13673479, 29787085, 13096535, + 6280834, 14587357, -22338025, 13987525}, + }, + { + {-24349909, 7778775, 21116000, 15572597, -4833266, -5357778, + -4300898, -5124639, -7469781, -2858068}, + {9681908, -6737123, -31951644, 13591838, -6883821, 386950, 31622781, + 6439245, -14581012, 4091397}, + {-8426427, 1470727, -28109679, -1596990, 3978627, -5123623, + -19622683, 12092163, 29077877, -14741988}, + }, + { + {5269168, -6859726, -13230211, -8020715, 25932563, 1763552, + -5606110, -5505881, -20017847, 2357889}, + {32264008, -15407652, -5387735, -1160093, -2091322, -3946900, + 23104804, -12869908, 5727338, 189038}, + {14609123, -8954470, -6000566, -16622781, -14577387, -7743898, + -26745169, 10942115, -25888931, -14884697}, + }, + { + {20513500, 5557931, -15604613, 7829531, 26413943, -2019404, + -21378968, 7471781, 13913677, -5137875}, + {-25574376, 11967826, 29233242, 12948236, -6754465, 4713227, + -8940970, 14059180, 12878652, 8511905}, + {-25656801, 3393631, -2955415, -7075526, -2250709, 9366908, + -30223418, 6812974, 5568676, -3127656}, + }, + { + {11630004, 12144454, 2116339, 13606037, 27378885, 15676917, + -17408753, -13504373, -14395196, 8070818}, + {27117696, -10007378, -31282771, -5570088, 1127282, 12772488, + -29845906, 10483306, -11552749, -1028714}, + {10637467, -5688064, 5674781, 1072708, -26343588, -6982302, + -1683975, 9177853, -27493162, 15431203}, + }, + { + {20525145, 10892566, -12742472, 12779443, -29493034, 16150075, + -28240519, 14943142, -15056790, -7935931}, + {-30024462, 5626926, -551567, -9981087, 753598, 11981191, 25244767, + -3239766, -3356550, 9594024}, + {-23752644, 2636870, -5163910, -10103818, 585134, 7877383, 11345683, + -6492290, 13352335, -10977084}, + }, + { + {-1931799, -5407458, 3304649, -12884869, 17015806, -4877091, + -29783850, -7752482, -13215537, -319204}, + {20239939, 6607058, 6203985, 3483793, -18386976, -779229, -20723742, + 15077870, -22750759, 14523817}, + {27406042, -6041657, 27423596, -4497394, 4996214, 10002360, + -28842031, -4545494, -30172742, -4805667}, + }, + }, + { + { + {11374242, 12660715, 17861383, -12540833, 10935568, 1099227, + -13886076, -9091740, -27727044, 11358504}, + {-12730809, 10311867, 1510375, 10778093, -2119455, -9145702, + 32676003, 11149336, -26123651, 4985768}, + {-19096303, 341147, -6197485, -239033, 15756973, -8796662, -983043, + 13794114, -19414307, -15621255}, + }, + { + {6490081, 11940286, 25495923, -7726360, 8668373, -8751316, 3367603, + 6970005, -1691065, -9004790}, + {1656497, 13457317, 15370807, 6364910, 13605745, 8362338, -19174622, + -5475723, -16796596, -5031438}, + {-22273315, -13524424, -64685, -4334223, -18605636, -10921968, + -20571065, -7007978, -99853, -10237333}, + }, + { + {17747465, 10039260, 19368299, -4050591, -20630635, -16041286, + 31992683, -15857976, -29260363, -5511971}, + {31932027, -4986141, -19612382, 16366580, 22023614, 88450, 11371999, + -3744247, 4882242, -10626905}, + {29796507, 37186, 19818052, 10115756, -11829032, 3352736, 18551198, + 3272828, -5190932, -4162409}, + }, + { + {12501286, 4044383, -8612957, -13392385, -32430052, 5136599, + -19230378, -3529697, 330070, -3659409}, + {6384877, 2899513, 17807477, 7663917, -2358888, 12363165, 25366522, + -8573892, -271295, 12071499}, + {-8365515, -4042521, 25133448, -4517355, -6211027, 2265927, + -32769618, 1936675, -5159697, 3829363}, + }, + { + {28425966, -5835433, -577090, -4697198, -14217555, 6870930, 7921550, + -6567787, 26333140, 14267664}, + {-11067219, 11871231, 27385719, -10559544, -4585914, -11189312, + 10004786, -8709488, -21761224, 8930324}, + {-21197785, -16396035, 25654216, -1725397, 12282012, 11008919, + 1541940, 4757911, -26491501, -16408940}, + }, + { + {13537262, -7759490, -20604840, 10961927, -5922820, -13218065, + -13156584, 6217254, -15943699, 13814990}, + {-17422573, 15157790, 18705543, 29619, 24409717, -260476, 27361681, + 9257833, -1956526, -1776914}, + {-25045300, -10191966, 15366585, 15166509, -13105086, 8423556, + -29171540, 12361135, -18685978, 4578290}, + }, + { + {24579768, 3711570, 1342322, -11180126, -27005135, 14124956, + -22544529, 14074919, 21964432, 8235257}, + {-6528613, -2411497, 9442966, -5925588, 12025640, -1487420, + -2981514, -1669206, 13006806, 2355433}, + {-16304899, -13605259, -6632427, -5142349, 16974359, -10911083, + 27202044, 1719366, 1141648, -12796236}, + }, + { + {-12863944, -13219986, -8318266, -11018091, -6810145, -4843894, + 13475066, -3133972, 32674895, 13715045}, + {11423335, -5468059, 32344216, 8962751, 24989809, 9241752, + -13265253, 16086212, -28740881, -15642093}, + {-1409668, 12530728, -6368726, 10847387, 19531186, -14132160, + -11709148, 7791794, -27245943, 4383347}, + }, + }, + { + { + {-28970898, 5271447, -1266009, -9736989, -12455236, 16732599, + -4862407, -4906449, 27193557, 6245191}, + {-15193956, 5362278, -1783893, 2695834, 4960227, 12840725, 23061898, + 3260492, 22510453, 8577507}, + {-12632451, 11257346, -32692994, 13548177, -721004, 10879011, + 31168030, 13952092, -29571492, -3635906}, + }, + { + {3877321, -9572739, 32416692, 5405324, -11004407, -13656635, + 3759769, 11935320, 5611860, 8164018}, + {-16275802, 14667797, 15906460, 12155291, -22111149, -9039718, + 32003002, -8832289, 5773085, -8422109}, + {-23788118, -8254300, 1950875, 8937633, 18686727, 16459170, -905725, + 12376320, 31632953, 190926}, + }, + { + {-24593607, -16138885, -8423991, 13378746, 14162407, 6901328, + -8288749, 4508564, -25341555, -3627528}, + {8884438, -5884009, 6023974, 10104341, -6881569, -4941533, 18722941, + -14786005, -1672488, 827625}, + {-32720583, -16289296, -32503547, 7101210, 13354605, 2659080, + -1800575, -14108036, -24878478, 1541286}, + }, + { + {2901347, -1117687, 3880376, -10059388, -17620940, -3612781, + -21802117, -3567481, 20456845, -1885033}, + {27019610, 12299467, -13658288, -1603234, -12861660, -4861471, + -19540150, -5016058, 29439641, 15138866}, + {21536104, -6626420, -32447818, -10690208, -22408077, 5175814, + -5420040, -16361163, 7779328, 109896}, + }, + { + {30279744, 14648750, -8044871, 6425558, 13639621, -743509, 28698390, + 12180118, 23177719, -554075}, + {26572847, 3405927, -31701700, 12890905, -19265668, 5335866, + -6493768, 2378492, 4439158, -13279347}, + {-22716706, 3489070, -9225266, -332753, 18875722, -1140095, + 14819434, -12731527, -17717757, -5461437}, + }, + { + {-5056483, 16566551, 15953661, 3767752, -10436499, 15627060, + -820954, 2177225, 8550082, -15114165}, + {-18473302, 16596775, -381660, 15663611, 22860960, 15585581, + -27844109, -3582739, -23260460, -8428588}, + {-32480551, 15707275, -8205912, -5652081, 29464558, 2713815, + -22725137, 15860482, -21902570, 1494193}, + }, + { + {-19562091, -14087393, -25583872, -9299552, 13127842, 759709, + 21923482, 16529112, 8742704, 12967017}, + {-28464899, 1553205, 32536856, -10473729, -24691605, -406174, + -8914625, -2933896, -29903758, 15553883}, + {21877909, 3230008, 9881174, 10539357, -4797115, 2841332, 11543572, + 14513274, 19375923, -12647961}, + }, + { + {8832269, -14495485, 13253511, 5137575, 5037871, 4078777, 24880818, + -6222716, 2862653, 9455043}, + {29306751, 5123106, 20245049, -14149889, 9592566, 8447059, -2077124, + -2990080, 15511449, 4789663}, + {-20679756, 7004547, 8824831, -9434977, -4045704, -3750736, + -5754762, 108893, 23513200, 16652362}, + }, + }, + { + { + {-33256173, 4144782, -4476029, -6579123, 10770039, -7155542, + -6650416, -12936300, -18319198, 10212860}, + {2756081, 8598110, 7383731, -6859892, 22312759, -1105012, 21179801, + 2600940, -9988298, -12506466}, + {-24645692, 13317462, -30449259, -15653928, 21365574, -10869657, + 11344424, 864440, -2499677, -16710063}, + }, + { + {-26432803, 6148329, -17184412, -14474154, 18782929, -275997, + -22561534, 211300, 2719757, 4940997}, + {-1323882, 3911313, -6948744, 14759765, -30027150, 7851207, + 21690126, 8518463, 26699843, 5276295}, + {-13149873, -6429067, 9396249, 365013, 24703301, -10488939, 1321586, + 149635, -15452774, 7159369}, + }, + { + {9987780, -3404759, 17507962, 9505530, 9731535, -2165514, 22356009, + 8312176, 22477218, -8403385}, + {18155857, -16504990, 19744716, 9006923, 15154154, -10538976, + 24256460, -4864995, -22548173, 9334109}, + {2986088, -4911893, 10776628, -3473844, 10620590, -7083203, + -21413845, 14253545, -22587149, 536906}, + }, + { + {4377756, 8115836, 24567078, 15495314, 11625074, 13064599, 7390551, + 10589625, 10838060, -15420424}, + {-19342404, 867880, 9277171, -3218459, -14431572, -1986443, + 19295826, -15796950, 6378260, 699185}, + {7895026, 4057113, -7081772, -13077756, -17886831, -323126, -716039, + 15693155, -5045064, -13373962}, + }, + { + {-7737563, -5869402, -14566319, -7406919, 11385654, 13201616, + 31730678, -10962840, -3918636, -9669325}, + {10188286, -15770834, -7336361, 13427543, 22223443, 14896287, + 30743455, 7116568, -21786507, 5427593}, + {696102, 13206899, 27047647, -10632082, 15285305, -9853179, + 10798490, -4578720, 19236243, 12477404}, + }, + { + {-11229439, 11243796, -17054270, -8040865, -788228, -8167967, + -3897669, 11180504, -23169516, 7733644}, + {17800790, -14036179, -27000429, -11766671, 23887827, 3149671, + 23466177, -10538171, 10322027, 15313801}, + {26246234, 11968874, 32263343, -5468728, 6830755, -13323031, + -15794704, -101982, -24449242, 10890804}, + }, + { + {-31365647, 10271363, -12660625, -6267268, 16690207, -13062544, + -14982212, 16484931, 25180797, -5334884}, + {-586574, 10376444, -32586414, -11286356, 19801893, 10997610, + 2276632, 9482883, 316878, 13820577}, + {-9882808, -4510367, -2115506, 16457136, -11100081, 11674996, + 30756178, -7515054, 30696930, -3712849}, + }, + { + {32988917, -9603412, 12499366, 7910787, -10617257, -11931514, + -7342816, -9985397, -32349517, 7392473}, + {-8855661, 15927861, 9866406, -3649411, -2396914, -16655781, + -30409476, -9134995, 25112947, -2926644}, + {-2504044, -436966, 25621774, -5678772, 15085042, -5479877, + -24884878, -13526194, 5537438, -13914319}, + }, + }, + { + { + {-11225584, 2320285, -9584280, 10149187, -33444663, 5808648, + -14876251, -1729667, 31234590, 6090599}, + {-9633316, 116426, 26083934, 2897444, -6364437, -2688086, 609721, + 15878753, -6970405, -9034768}, + {-27757857, 247744, -15194774, -9002551, 23288161, -10011936, + -23869595, 6503646, 20650474, 1804084}, + }, + { + {-27589786, 15456424, 8972517, 8469608, 15640622, 4439847, 3121995, + -10329713, 27842616, -202328}, + {-15306973, 2839644, 22530074, 10026331, 4602058, 5048462, 28248656, + 5031932, -11375082, 12714369}, + {20807691, -7270825, 29286141, 11421711, -27876523, -13868230, + -21227475, 1035546, -19733229, 12796920}, + }, + { + {12076899, -14301286, -8785001, -11848922, -25012791, 16400684, + -17591495, -12899438, 3480665, -15182815}, + {-32361549, 5457597, 28548107, 7833186, 7303070, -11953545, + -24363064, -15921875, -33374054, 2771025}, + {-21389266, 421932, 26597266, 6860826, 22486084, -6737172, + -17137485, -4210226, -24552282, 15673397}, + }, + { + {-20184622, 2338216, 19788685, -9620956, -4001265, -8740893, + -20271184, 4733254, 3727144, -12934448}, + {6120119, 814863, -11794402, -622716, 6812205, -15747771, 2019594, + 7975683, 31123697, -10958981}, + {30069250, -11435332, 30434654, 2958439, 18399564, -976289, + 12296869, 9204260, -16432438, 9648165}, + }, + { + {32705432, -1550977, 30705658, 7451065, -11805606, 9631813, 3305266, + 5248604, -26008332, -11377501}, + {17219865, 2375039, -31570947, -5575615, -19459679, 9219903, 294711, + 15298639, 2662509, -16297073}, + {-1172927, -7558695, -4366770, -4287744, -21346413, -8434326, + 32087529, -1222777, 32247248, -14389861}, + }, + { + {14312628, 1221556, 17395390, -8700143, -4945741, -8684635, + -28197744, -9637817, -16027623, -13378845}, + {-1428825, -9678990, -9235681, 6549687, -7383069, -468664, 23046502, + 9803137, 17597934, 2346211}, + {18510800, 15337574, 26171504, 981392, -22241552, 7827556, + -23491134, -11323352, 3059833, -11782870}, + }, + { + {10141598, 6082907, 17829293, -1947643, 9830092, 13613136, + -25556636, -5544586, -33502212, 3592096}, + {33114168, -15889352, -26525686, -13343397, 33076705, 8716171, + 1151462, 1521897, -982665, -6837803}, + {-32939165, -4255815, 23947181, -324178, -33072974, -12305637, + -16637686, 3891704, 26353178, 693168}, + }, + { + {30374239, 1595580, -16884039, 13186931, 4600344, 406904, 9585294, + -400668, 31375464, 14369965}, + {-14370654, -7772529, 1510301, 6434173, -18784789, -6262728, + 32732230, -13108839, 17901441, 16011505}, + {18171223, -11934626, -12500402, 15197122, -11038147, -15230035, + -19172240, -16046376, 8764035, 12309598}, + }, + }, + { + { + {5975908, -5243188, -19459362, -9681747, -11541277, 14015782, + -23665757, 1228319, 17544096, -10593782}, + {5811932, -1715293, 3442887, -2269310, -18367348, -8359541, + -18044043, -15410127, -5565381, 12348900}, + {-31399660, 11407555, 25755363, 6891399, -3256938, 14872274, + -24849353, 8141295, -10632534, -585479}, + }, + { + {-12675304, 694026, -5076145, 13300344, 14015258, -14451394, + -9698672, -11329050, 30944593, 1130208}, + {8247766, -6710942, -26562381, -7709309, -14401939, -14648910, + 4652152, 2488540, 23550156, -271232}, + {17294316, -3788438, 7026748, 15626851, 22990044, 113481, 2267737, + -5908146, -408818, -137719}, + }, + { + {16091085, -16253926, 18599252, 7340678, 2137637, -1221657, + -3364161, 14550936, 3260525, -7166271}, + {-4910104, -13332887, 18550887, 10864893, -16459325, -7291596, + -23028869, -13204905, -12748722, 2701326}, + {-8574695, 16099415, 4629974, -16340524, -20786213, -6005432, + -10018363, 9276971, 11329923, 1862132}, + }, + { + {14763076, -15903608, -30918270, 3689867, 3511892, 10313526, + -21951088, 12219231, -9037963, -940300}, + {8894987, -3446094, 6150753, 3013931, 301220, 15693451, -31981216, + -2909717, -15438168, 11595570}, + {15214962, 3537601, -26238722, -14058872, 4418657, -15230761, + 13947276, 10730794, -13489462, -4363670}, + }, + { + {-2538306, 7682793, 32759013, 263109, -29984731, -7955452, + -22332124, -10188635, 977108, 699994}, + {-12466472, 4195084, -9211532, 550904, -15565337, 12917920, + 19118110, -439841, -30534533, -14337913}, + {31788461, -14507657, 4799989, 7372237, 8808585, -14747943, 9408237, + -10051775, 12493932, -5409317}, + }, + { + {-25680606, 5260744, -19235809, -6284470, -3695942, 16566087, + 27218280, 2607121, 29375955, 6024730}, + {842132, -2794693, -4763381, -8722815, 26332018, -12405641, + 11831880, 6985184, -9940361, 2854096}, + {-4847262, -7969331, 2516242, -5847713, 9695691, -7221186, 16512645, + 960770, 12121869, 16648078}, + }, + { + {-15218652, 14667096, -13336229, 2013717, 30598287, -464137, + -31504922, -7882064, 20237806, 2838411}, + {-19288047, 4453152, 15298546, -16178388, 22115043, -15972604, + 12544294, -13470457, 1068881, -12499905}, + {-9558883, -16518835, 33238498, 13506958, 30505848, -1114596, + -8486907, -2630053, 12521378, 4845654}, + }, + { + {-28198521, 10744108, -2958380, 10199664, 7759311, -13088600, + 3409348, -873400, -6482306, -12885870}, + {-23561822, 6230156, -20382013, 10655314, -24040585, -11621172, + 10477734, -1240216, -3113227, 13974498}, + {12966261, 15550616, -32038948, -1615346, 21025980, -629444, + 5642325, 7188737, 18895762, 12629579}, + }, + }, + { + { + {14741879, -14946887, 22177208, -11721237, 1279741, 8058600, + 11758140, 789443, 32195181, 3895677}, + {10758205, 15755439, -4509950, 9243698, -4879422, 6879879, -2204575, + -3566119, -8982069, 4429647}, + {-2453894, 15725973, -20436342, -10410672, -5803908, -11040220, + -7135870, -11642895, 18047436, -15281743}, + }, + { + {-25173001, -11307165, 29759956, 11776784, -22262383, -15820455, + 10993114, -12850837, -17620701, -9408468}, + {21987233, 700364, -24505048, 14972008, -7774265, -5718395, + 32155026, 2581431, -29958985, 8773375}, + {-25568350, 454463, -13211935, 16126715, 25240068, 8594567, + 20656846, 12017935, -7874389, -13920155}, + }, + { + {6028182, 6263078, -31011806, -11301710, -818919, 2461772, + -31841174, -5468042, -1721788, -2776725}, + {-12278994, 16624277, 987579, -5922598, 32908203, 1248608, 7719845, + -4166698, 28408820, 6816612}, + {-10358094, -8237829, 19549651, -12169222, 22082623, 16147817, + 20613181, 13982702, -10339570, 5067943}, + }, + { + {-30505967, -3821767, 12074681, 13582412, -19877972, 2443951, + -19719286, 12746132, 5331210, -10105944}, + {30528811, 3601899, -1957090, 4619785, -27361822, -15436388, + 24180793, -12570394, 27679908, -1648928}, + {9402404, -13957065, 32834043, 10838634, -26580150, -13237195, + 26653274, -8685565, 22611444, -12715406}, + }, + { + {22190590, 1118029, 22736441, 15130463, -30460692, -5991321, + 19189625, -4648942, 4854859, 6622139}, + {-8310738, -2953450, -8262579, -3388049, -10401731, -271929, + 13424426, -3567227, 26404409, 13001963}, + {-31241838, -15415700, -2994250, 8939346, 11562230, -12840670, + -26064365, -11621720, -15405155, 11020693}, + }, + { + {1866042, -7949489, -7898649, -10301010, 12483315, 13477547, + 3175636, -12424163, 28761762, 1406734}, + {-448555, -1777666, 13018551, 3194501, -9580420, -11161737, + 24760585, -4347088, 25577411, -13378680}, + {-24290378, 4759345, -690653, -1852816, 2066747, 10693769, + -29595790, 9884936, -9368926, 4745410}, + }, + { + {-9141284, 6049714, -19531061, -4341411, -31260798, 9944276, + -15462008, -11311852, 10931924, -11931931}, + {-16561513, 14112680, -8012645, 4817318, -8040464, -11414606, + -22853429, 10856641, -20470770, 13434654}, + {22759489, -10073434, -16766264, -1871422, 13637442, -10168091, + 1765144, -12654326, 28445307, -5364710}, + }, + { + {29875063, 12493613, 2795536, -3786330, 1710620, 15181182, + -10195717, -8788675, 9074234, 1167180}, + {-26205683, 11014233, -9842651, -2635485, -26908120, 7532294, + -18716888, -9535498, 3843903, 9367684}, + {-10969595, -6403711, 9591134, 9582310, 11349256, 108879, 16235123, + 8601684, -139197, 4242895}, + }, + }, + { + { + {22092954, -13191123, -2042793, -11968512, 32186753, -11517388, + -6574341, 2470660, -27417366, 16625501}, + {-11057722, 3042016, 13770083, -9257922, 584236, -544855, -7770857, + 2602725, -27351616, 14247413}, + {6314175, -10264892, -32772502, 15957557, -10157730, 168750, + -8618807, 14290061, 27108877, -1180880}, + }, + { + {-8586597, -7170966, 13241782, 10960156, -32991015, -13794596, + 33547976, -11058889, -27148451, 981874}, + {22833440, 9293594, -32649448, -13618667, -9136966, 14756819, + -22928859, -13970780, -10479804, -16197962}, + {-7768587, 3326786, -28111797, 10783824, 19178761, 14905060, + 22680049, 13906969, -15933690, 3797899}, + }, + { + {21721356, -4212746, -12206123, 9310182, -3882239, -13653110, + 23740224, -2709232, 20491983, -8042152}, + {9209270, -15135055, -13256557, -6167798, -731016, 15289673, + 25947805, 15286587, 30997318, -6703063}, + {7392032, 16618386, 23946583, -8039892, -13265164, -1533858, + -14197445, -2321576, 17649998, -250080}, + }, + { + {-9301088, -14193827, 30609526, -3049543, -25175069, -1283752, + -15241566, -9525724, -2233253, 7662146}, + {-17558673, 1763594, -33114336, 15908610, -30040870, -12174295, + 7335080, -8472199, -3174674, 3440183}, + {-19889700, -5977008, -24111293, -9688870, 10799743, -16571957, + 40450, -4431835, 4862400, 1133}, + }, + { + {-32856209, -7873957, -5422389, 14860950, -16319031, 7956142, + 7258061, 311861, -30594991, -7379421}, + {-3773428, -1565936, 28985340, 7499440, 24445838, 9325937, 29727763, + 16527196, 18278453, 15405622}, + {-4381906, 8508652, -19898366, -3674424, -5984453, 15149970, + -13313598, 843523, -21875062, 13626197}, + }, + { + {2281448, -13487055, -10915418, -2609910, 1879358, 16164207, + -10783882, 3953792, 13340839, 15928663}, + {31727126, -7179855, -18437503, -8283652, 2875793, -16390330, + -25269894, -7014826, -23452306, 5964753}, + {4100420, -5959452, -17179337, 6017714, -18705837, 12227141, + -26684835, 11344144, 2538215, -7570755}, + }, + { + {-9433605, 6123113, 11159803, -2156608, 30016280, 14966241, + -20474983, 1485421, -629256, -15958862}, + {-26804558, 4260919, 11851389, 9658551, -32017107, 16367492, + -20205425, -13191288, 11659922, -11115118}, + {26180396, 10015009, -30844224, -8581293, 5418197, 9480663, 2231568, + -10170080, 33100372, -1306171}, + }, + { + {15121113, -5201871, -10389905, 15427821, -27509937, -15992507, + 21670947, 4486675, -5931810, -14466380}, + {16166486, -9483733, -11104130, 6023908, -31926798, -1364923, + 2340060, -16254968, -10735770, -10039824}, + {28042865, -3557089, -12126526, 12259706, -3717498, -6945899, + 6766453, -8689599, 18036436, 5803270}, + }, + }, + { + { + {-817581, 6763912, 11803561, 1585585, 10958447, -2671165, 23855391, + 4598332, -6159431, -14117438}, + {-31031306, -14256194, 17332029, -2383520, 31312682, -5967183, + 696309, 50292, -20095739, 11763584}, + {-594563, -2514283, -32234153, 12643980, 12650761, 14811489, 665117, + -12613632, -19773211, -10713562}, + }, + { + {30464590, -11262872, -4127476, -12734478, 19835327, -7105613, + -24396175, 2075773, -17020157, 992471}, + {18357185, -6994433, 7766382, 16342475, -29324918, 411174, 14578841, + 8080033, -11574335, -10601610}, + {19598397, 10334610, 12555054, 2555664, 18821899, -10339780, + 21873263, 16014234, 26224780, 16452269}, + }, + { + {-30223925, 5145196, 5944548, 16385966, 3976735, 2009897, -11377804, + -7618186, -20533829, 3698650}, + {14187449, 3448569, -10636236, -10810935, -22663880, -3433596, + 7268410, -10890444, 27394301, 12015369}, + {19695761, 16087646, 28032085, 12999827, 6817792, 11427614, + 20244189, -1312777, -13259127, -3402461}, + }, + { + {30860103, 12735208, -1888245, -4699734, -16974906, 2256940, + -8166013, 12298312, -8550524, -10393462}, + {-5719826, -11245325, -1910649, 15569035, 26642876, -7587760, + -5789354, -15118654, -4976164, 12651793}, + {-2848395, 9953421, 11531313, -5282879, 26895123, -12697089, + -13118820, -16517902, 9768698, -2533218}, + }, + { + {-24719459, 1894651, -287698, -4704085, 15348719, -8156530, + 32767513, 12765450, 4940095, 10678226}, + {18860224, 15980149, -18987240, -1562570, -26233012, -11071856, + -7843882, 13944024, -24372348, 16582019}, + {-15504260, 4970268, -29893044, 4175593, -20993212, -2199756, + -11704054, 15444560, -11003761, 7989037}, + }, + { + {31490452, 5568061, -2412803, 2182383, -32336847, 4531686, + -32078269, 6200206, -19686113, -14800171}, + {-17308668, -15879940, -31522777, -2831, -32887382, 16375549, + 8680158, -16371713, 28550068, -6857132}, + {-28126887, -5688091, 16837845, -1820458, -6850681, 12700016, + -30039981, 4364038, 1155602, 5988841}, + }, + { + {21890435, -13272907, -12624011, 12154349, -7831873, 15300496, + 23148983, -4470481, 24618407, 8283181}, + {-33136107, -10512751, 9975416, 6841041, -31559793, 16356536, + 3070187, -7025928, 1466169, 10740210}, + {-1509399, -15488185, -13503385, -10655916, 32799044, 909394, + -13938903, -5779719, -32164649, -15327040}, + }, + { + {3960823, -14267803, -28026090, -15918051, -19404858, 13146868, + 15567327, 951507, -3260321, -573935}, + {24740841, 5052253, -30094131, 8961361, 25877428, 6165135, + -24368180, 14397372, -7380369, -6144105}, + {-28888365, 3510803, -28103278, -1158478, -11238128, -10631454, + -15441463, -14453128, -1625486, -6494814}, + }, + }, + { + { + {793299, -9230478, 8836302, -6235707, -27360908, -2369593, 33152843, + -4885251, -9906200, -621852}, + {5666233, 525582, 20782575, -8038419, -24538499, 14657740, 16099374, + 1468826, -6171428, -15186581}, + {-4859255, -3779343, -2917758, -6748019, 7778750, 11688288, + -30404353, -9871238, -1558923, -9863646}, + }, + { + {10896332, -7719704, 824275, 472601, -19460308, 3009587, 25248958, + 14783338, -30581476, -15757844}, + {10566929, 12612572, -31944212, 11118703, -12633376, 12362879, + 21752402, 8822496, 24003793, 14264025}, + {27713862, -7355973, -11008240, 9227530, 27050101, 2504721, + 23886875, -13117525, 13958495, -5732453}, + }, + { + {-23481610, 4867226, -27247128, 3900521, 29838369, -8212291, + -31889399, -10041781, 7340521, -15410068}, + {4646514, -8011124, -22766023, -11532654, 23184553, 8566613, + 31366726, -1381061, -15066784, -10375192}, + {-17270517, 12723032, -16993061, 14878794, 21619651, -6197576, + 27584817, 3093888, -8843694, 3849921}, + }, + { + {-9064912, 2103172, 25561640, -15125738, -5239824, 9582958, + 32477045, -9017955, 5002294, -15550259}, + {-12057553, -11177906, 21115585, -13365155, 8808712, -12030708, + 16489530, 13378448, -25845716, 12741426}, + {-5946367, 10645103, -30911586, 15390284, -3286982, -7118677, + 24306472, 15852464, 28834118, -7646072}, + }, + { + {-17335748, -9107057, -24531279, 9434953, -8472084, -583362, + -13090771, 455841, 20461858, 5491305}, + {13669248, -16095482, -12481974, -10203039, -14569770, -11893198, + -24995986, 11293807, -28588204, -9421832}, + {28497928, 6272777, -33022994, 14470570, 8906179, -1225630, + 18504674, -14165166, 29867745, -8795943}, + }, + { + {-16207023, 13517196, -27799630, -13697798, 24009064, -6373891, + -6367600, -13175392, 22853429, -4012011}, + {24191378, 16712145, -13931797, 15217831, 14542237, 1646131, + 18603514, -11037887, 12876623, -2112447}, + {17902668, 4518229, -411702, -2829247, 26878217, 5258055, -12860753, + 608397, 16031844, 3723494}, + }, + { + {-28632773, 12763728, -20446446, 7577504, 33001348, -13017745, + 17558842, -7872890, 23896954, -4314245}, + {-20005381, -12011952, 31520464, 605201, 2543521, 5991821, -2945064, + 7229064, -9919646, -8826859}, + {28816045, 298879, -28165016, -15920938, 19000928, -1665890, + -12680833, -2949325, -18051778, -2082915}, + }, + { + {16000882, -344896, 3493092, -11447198, -29504595, -13159789, + 12577740, 16041268, -19715240, 7847707}, + {10151868, 10572098, 27312476, 7922682, 14825339, 4723128, + -32855931, -6519018, -10020567, 3852848}, + {-11430470, 15697596, -21121557, -4420647, 5386314, 15063598, + 16514493, -15932110, 29330899, -15076224}, + }, + }, + { + { + {-25499735, -4378794, -15222908, -6901211, 16615731, 2051784, + 3303702, 15490, -27548796, 12314391}, + {15683520, -6003043, 18109120, -9980648, 15337968, -5997823, + -16717435, 15921866, 16103996, -3731215}, + {-23169824, -10781249, 13588192, -1628807, -3798557, -1074929, + -19273607, 5402699, -29815713, -9841101}, + }, + { + {23190676, 2384583, -32714340, 3462154, -29903655, -1529132, + -11266856, 8911517, -25205859, 2739713}, + {21374101, -3554250, -33524649, 9874411, 15377179, 11831242, + -33529904, 6134907, 4931255, 11987849}, + {-7732, -2978858, -16223486, 7277597, 105524, -322051, -31480539, + 13861388, -30076310, 10117930}, + }, + { + {-29501170, -10744872, -26163768, 13051539, -25625564, 5089643, + -6325503, 6704079, 12890019, 15728940}, + {-21972360, -11771379, -951059, -4418840, 14704840, 2695116, 903376, + -10428139, 12885167, 8311031}, + {-17516482, 5352194, 10384213, -13811658, 7506451, 13453191, + 26423267, 4384730, 1888765, -5435404}, + }, + { + {-25817338, -3107312, -13494599, -3182506, 30896459, -13921729, + -32251644, -12707869, -19464434, -3340243}, + {-23607977, -2665774, -526091, 4651136, 5765089, 4618330, 6092245, + 14845197, 17151279, -9854116}, + {-24830458, -12733720, -15165978, 10367250, -29530908, -265356, + 22825805, -7087279, -16866484, 16176525}, + }, + { + {-23583256, 6564961, 20063689, 3798228, -4740178, 7359225, 2006182, + -10363426, -28746253, -10197509}, + {-10626600, -4486402, -13320562, -5125317, 3432136, -6393229, + 23632037, -1940610, 32808310, 1099883}, + {15030977, 5768825, -27451236, -2887299, -6427378, -15361371, + -15277896, -6809350, 2051441, -15225865}, + }, + { + {-3362323, -7239372, 7517890, 9824992, 23555850, 295369, 5148398, + -14154188, -22686354, 16633660}, + {4577086, -16752288, 13249841, -15304328, 19958763, -14537274, + 18559670, -10759549, 8402478, -9864273}, + {-28406330, -1051581, -26790155, -907698, -17212414, -11030789, + 9453451, -14980072, 17983010, 9967138}, + }, + { + {-25762494, 6524722, 26585488, 9969270, 24709298, 1220360, -1677990, + 7806337, 17507396, 3651560}, + {-10420457, -4118111, 14584639, 15971087, -15768321, 8861010, + 26556809, -5574557, -18553322, -11357135}, + {2839101, 14284142, 4029895, 3472686, 14402957, 12689363, -26642121, + 8459447, -5605463, -7621941}, + }, + { + {-4839289, -3535444, 9744961, 2871048, 25113978, 3187018, -25110813, + -849066, 17258084, -7977739}, + {18164541, -10595176, -17154882, -1542417, 19237078, -9745295, + 23357533, -15217008, 26908270, 12150756}, + {-30264870, -7647865, 5112249, -7036672, -1499807, -6974257, 43168, + -5537701, -32302074, 16215819}, + }, + }, + { + { + {-6898905, 9824394, -12304779, -4401089, -31397141, -6276835, + 32574489, 12532905, -7503072, -8675347}, + {-27343522, -16515468, -27151524, -10722951, 946346, 16291093, + 254968, 7168080, 21676107, -1943028}, + {21260961, -8424752, -16831886, -11920822, -23677961, 3968121, + -3651949, -6215466, -3556191, -7913075}, + }, + { + {16544754, 13250366, -16804428, 15546242, -4583003, 12757258, + -2462308, -8680336, -18907032, -9662799}, + {-2415239, -15577728, 18312303, 4964443, -15272530, -12653564, + 26820651, 16690659, 25459437, -4564609}, + {-25144690, 11425020, 28423002, -11020557, -6144921, -15826224, + 9142795, -2391602, -6432418, -1644817}, + }, + { + {-23104652, 6253476, 16964147, -3768872, -25113972, -12296437, + -27457225, -16344658, 6335692, 7249989}, + {-30333227, 13979675, 7503222, -12368314, -11956721, -4621693, + -30272269, 2682242, 25993170, -12478523}, + {4364628, 5930691, 32304656, -10044554, -8054781, 15091131, + 22857016, -10598955, 31820368, 15075278}, + }, + { + {31879134, -8918693, 17258761, 90626, -8041836, -4917709, 24162788, + -9650886, -17970238, 12833045}, + {19073683, 14851414, -24403169, -11860168, 7625278, 11091125, + -19619190, 2074449, -9413939, 14905377}, + {24483667, -11935567, -2518866, -11547418, -1553130, 15355506, + -25282080, 9253129, 27628530, -7555480}, + }, + { + {17597607, 8340603, 19355617, 552187, 26198470, -3176583, 4593324, + -9157582, -14110875, 15297016}, + {510886, 14337390, -31785257, 16638632, 6328095, 2713355, -20217417, + -11864220, 8683221, 2921426}, + {18606791, 11874196, 27155355, -5281482, -24031742, 6265446, + -25178240, -1278924, 4674690, 13890525}, + }, + { + {13609624, 13069022, -27372361, -13055908, 24360586, 9592974, + 14977157, 9835105, 4389687, 288396}, + {9922506, -519394, 13613107, 5883594, -18758345, -434263, -12304062, + 8317628, 23388070, 16052080}, + {12720016, 11937594, -31970060, -5028689, 26900120, 8561328, + -20155687, -11632979, -14754271, -10812892}, + }, + { + {15961858, 14150409, 26716931, -665832, -22794328, 13603569, + 11829573, 7467844, -28822128, 929275}, + {11038231, -11582396, -27310482, -7316562, -10498527, -16307831, + -23479533, -9371869, -21393143, 2465074}, + {20017163, -4323226, 27915242, 1529148, 12396362, 15675764, + 13817261, -9658066, 2463391, -4622140}, + }, + { + {-16358878, -12663911, -12065183, 4996454, -1256422, 1073572, + 9583558, 12851107, 4003896, 12673717}, + {-1731589, -15155870, -3262930, 16143082, 19294135, 13385325, + 14741514, -9103726, 7903886, 2348101}, + {24536016, -16515207, 12715592, -3862155, 1511293, 10047386, + -3842346, -7129159, -28377538, 10048127}, + }, + }, + { + { + {-12622226, -6204820, 30718825, 2591312, -10617028, 12192840, + 18873298, -7297090, -32297756, 15221632}, + {-26478122, -11103864, 11546244, -1852483, 9180880, 7656409, + -21343950, 2095755, 29769758, 6593415}, + {-31994208, -2907461, 4176912, 3264766, 12538965, -868111, 26312345, + -6118678, 30958054, 8292160}, + }, + { + {31429822, -13959116, 29173532, 15632448, 12174511, -2760094, + 32808831, 3977186, 26143136, -3148876}, + {22648901, 1402143, -22799984, 13746059, 7936347, 365344, -8668633, + -1674433, -3758243, -2304625}, + {-15491917, 8012313, -2514730, -12702462, -23965846, -10254029, + -1612713, -1535569, -16664475, 8194478}, + }, + { + {27338066, -7507420, -7414224, 10140405, -19026427, -6589889, + 27277191, 8855376, 28572286, 3005164}, + {26287124, 4821776, 25476601, -4145903, -3764513, -15788984, + -18008582, 1182479, -26094821, -13079595}, + {-7171154, 3178080, 23970071, 6201893, -17195577, -4489192, + -21876275, -13982627, 32208683, -1198248}, + }, + { + {-16657702, 2817643, -10286362, 14811298, 6024667, 13349505, + -27315504, -10497842, -27672585, -11539858}, + {15941029, -9405932, -21367050, 8062055, 31876073, -238629, + -15278393, -1444429, 15397331, -4130193}, + {8934485, -13485467, -23286397, -13423241, -32446090, 14047986, + 31170398, -1441021, -27505566, 15087184}, + }, + { + {-18357243, -2156491, 24524913, -16677868, 15520427, -6360776, + -15502406, 11461896, 16788528, -5868942}, + {-1947386, 16013773, 21750665, 3714552, -17401782, -16055433, + -3770287, -10323320, 31322514, -11615635}, + {21426655, -5650218, -13648287, -5347537, -28812189, -4920970, + -18275391, -14621414, 13040862, -12112948}, + }, + { + {11293895, 12478086, -27136401, 15083750, -29307421, 14748872, + 14555558, -13417103, 1613711, 4896935}, + {-25894883, 15323294, -8489791, -8057900, 25967126, -13425460, + 2825960, -4897045, -23971776, -11267415}, + {-15924766, -5229880, -17443532, 6410664, 3622847, 10243618, + 20615400, 12405433, -23753030, -8436416}, + }, + { + {-7091295, 12556208, -20191352, 9025187, -17072479, 4333801, + 4378436, 2432030, 23097949, -566018}, + {4565804, -16025654, 20084412, -7842817, 1724999, 189254, 24767264, + 10103221, -18512313, 2424778}, + {366633, -11976806, 8173090, -6890119, 30788634, 5745705, -7168678, + 1344109, -3642553, 12412659}, + }, + { + {-24001791, 7690286, 14929416, -168257, -32210835, -13412986, + 24162697, -15326504, -3141501, 11179385}, + {18289522, -14724954, 8056945, 16430056, -21729724, 7842514, + -6001441, -1486897, -18684645, -11443503}, + {476239, 6601091, -6152790, -9723375, 17503545, -4863900, 27672959, + 13403813, 11052904, 5219329}, + }, + }, + { + { + {20678546, -8375738, -32671898, 8849123, -5009758, 14574752, + 31186971, -3973730, 9014762, -8579056}, + {-13644050, -10350239, -15962508, 5075808, -1514661, -11534600, + -33102500, 9160280, 8473550, -3256838}, + {24900749, 14435722, 17209120, -15292541, -22592275, 9878983, + -7689309, -16335821, -24568481, 11788948}, + }, + { + {-3118155, -11395194, -13802089, 14797441, 9652448, -6845904, + -20037437, 10410733, -24568470, -1458691}, + {-15659161, 16736706, -22467150, 10215878, -9097177, 7563911, + 11871841, -12505194, -18513325, 8464118}, + {-23400612, 8348507, -14585951, -861714, -3950205, -6373419, + 14325289, 8628612, 33313881, -8370517}, + }, + { + {-20186973, -4967935, 22367356, 5271547, -1097117, -4788838, + -24805667, -10236854, -8940735, -5818269}, + {-6948785, -1795212, -32625683, -16021179, 32635414, -7374245, + 15989197, -12838188, 28358192, -4253904}, + {-23561781, -2799059, -32351682, -1661963, -9147719, 10429267, + -16637684, 4072016, -5351664, 5596589}, + }, + { + {-28236598, -3390048, 12312896, 6213178, 3117142, 16078565, + 29266239, 2557221, 1768301, 15373193}, + {-7243358, -3246960, -4593467, -7553353, -127927, -912245, -1090902, + -4504991, -24660491, 3442910}, + {-30210571, 5124043, 14181784, 8197961, 18964734, -11939093, + 22597931, 7176455, -18585478, 13365930}, + }, + { + {-7877390, -1499958, 8324673, 4690079, 6261860, 890446, 24538107, + -8570186, -9689599, -3031667}, + {25008904, -10771599, -4305031, -9638010, 16265036, 15721635, + 683793, -11823784, 15723479, -15163481}, + {-9660625, 12374379, -27006999, -7026148, -7724114, -12314514, + 11879682, 5400171, 519526, -1235876}, + }, + { + {22258397, -16332233, -7869817, 14613016, -22520255, -2950923, + -20353881, 7315967, 16648397, 7605640}, + {-8081308, -8464597, -8223311, 9719710, 19259459, -15348212, + 23994942, -5281555, -9468848, 4763278}, + {-21699244, 9220969, -15730624, 1084137, -25476107, -2852390, + 31088447, -7764523, -11356529, 728112}, + }, + { + {26047220, -11751471, -6900323, -16521798, 24092068, 9158119, + -4273545, -12555558, -29365436, -5498272}, + {17510331, -322857, 5854289, 8403524, 17133918, -3112612, -28111007, + 12327945, 10750447, 10014012}, + {-10312768, 3936952, 9156313, -8897683, 16498692, -994647, + -27481051, -666732, 3424691, 7540221}, + }, + { + {30322361, -6964110, 11361005, -4143317, 7433304, 4989748, -7071422, + -16317219, -9244265, 15258046}, + {13054562, -2779497, 19155474, 469045, -12482797, 4566042, 5631406, + 2711395, 1062915, -5136345}, + {-19240248, -11254599, -29509029, -7499965, -5835763, 13005411, + -6066489, 12194497, 32960380, 1459310}, + }, + }, + { + { + {19852034, 7027924, 23669353, 10020366, 8586503, -6657907, 394197, + -6101885, 18638003, -11174937}, + {31395534, 15098109, 26581030, 8030562, -16527914, -5007134, + 9012486, -7584354, -6643087, -5442636}, + {-9192165, -2347377, -1997099, 4529534, 25766844, 607986, -13222, + 9677543, -32294889, -6456008}, + }, + { + {-2444496, -149937, 29348902, 8186665, 1873760, 12489863, -30934579, + -7839692, -7852844, -8138429}, + {-15236356, -15433509, 7766470, 746860, 26346930, -10221762, + -27333451, 10754588, -9431476, 5203576}, + {31834314, 14135496, -770007, 5159118, 20917671, -16768096, + -7467973, -7337524, 31809243, 7347066}, + }, + { + {-9606723, -11874240, 20414459, 13033986, 13716524, -11691881, + 19797970, -12211255, 15192876, -2087490}, + {-12663563, -2181719, 1168162, -3804809, 26747877, -14138091, + 10609330, 12694420, 33473243, -13382104}, + {33184999, 11180355, 15832085, -11385430, -1633671, 225884, + 15089336, -11023903, -6135662, 14480053}, + }, + { + {31308717, -5619998, 31030840, -1897099, 15674547, -6582883, + 5496208, 13685227, 27595050, 8737275}, + {-20318852, -15150239, 10933843, -16178022, 8335352, -7546022, + -31008351, -12610604, 26498114, 66511}, + {22644454, -8761729, -16671776, 4884562, -3105614, -13559366, + 30540766, -4286747, -13327787, -7515095}, + }, + { + {-28017847, 9834845, 18617207, -2681312, -3401956, -13307506, + 8205540, 13585437, -17127465, 15115439}, + {23711543, -672915, 31206561, -8362711, 6164647, -9709987, + -33535882, -1426096, 8236921, 16492939}, + {-23910559, -13515526, -26299483, -4503841, 25005590, -7687270, + 19574902, 10071562, 6708380, -6222424}, + }, + { + {2101391, -4930054, 19702731, 2367575, -15427167, 1047675, 5301017, + 9328700, 29955601, -11678310}, + {3096359, 9271816, -21620864, -15521844, -14847996, -7592937, + -25892142, -12635595, -9917575, 6216608}, + {-32615849, 338663, -25195611, 2510422, -29213566, -13820213, + 24822830, -6146567, -26767480, 7525079}, + }, + { + {-23066649, -13985623, 16133487, -7896178, -3389565, 778788, + -910336, -2782495, -19386633, 11994101}, + {21691500, -13624626, -641331, -14367021, 3285881, -3483596, + -25064666, 9718258, -7477437, 13381418}, + {18445390, -4202236, 14979846, 11622458, -1727110, -3582980, + 23111648, -6375247, 28535282, 15779576}, + }, + { + {30098053, 3089662, -9234387, 16662135, -21306940, 11308411, + -14068454, 12021730, 9955285, -16303356}, + {9734894, -14576830, -7473633, -9138735, 2060392, 11313496, + -18426029, 9924399, 20194861, 13380996}, + {-26378102, -7965207, -22167821, 15789297, -18055342, -6168792, + -1984914, 15707771, 26342023, 10146099}, + }, + }, + { + { + {-26016874, -219943, 21339191, -41388, 19745256, -2878700, + -29637280, 2227040, 21612326, -545728}, + {-13077387, 1184228, 23562814, -5970442, -20351244, -6348714, + 25764461, 12243797, -20856566, 11649658}, + {-10031494, 11262626, 27384172, 2271902, 26947504, -15997771, 39944, + 6114064, 33514190, 2333242}, + }, + { + {-21433588, -12421821, 8119782, 7219913, -21830522, -9016134, + -6679750, -12670638, 24350578, -13450001}, + {-4116307, -11271533, -23886186, 4843615, -30088339, 690623, + -31536088, -10406836, 8317860, 12352766}, + {18200138, -14475911, -33087759, -2696619, -23702521, -9102511, + -23552096, -2287550, 20712163, 6719373}, + }, + { + {26656208, 6075253, -7858556, 1886072, -28344043, 4262326, 11117530, + -3763210, 26224235, -3297458}, + {-17168938, -14854097, -3395676, -16369877, -19954045, 14050420, + 21728352, 9493610, 18620611, -16428628}, + {-13323321, 13325349, 11432106, 5964811, 18609221, 6062965, + -5269471, -9725556, -30701573, -16479657}, + }, + { + {-23860538, -11233159, 26961357, 1640861, -32413112, -16737940, + 12248509, -5240639, 13735342, 1934062}, + {25089769, 6742589, 17081145, -13406266, 21909293, -16067981, + -15136294, -3765346, -21277997, 5473616}, + {31883677, -7961101, 1083432, -11572403, 22828471, 13290673, + -7125085, 12469656, 29111212, -5451014}, + }, + { + {24244947, -15050407, -26262976, 2791540, -14997599, 16666678, + 24367466, 6388839, -10295587, 452383}, + {-25640782, -3417841, 5217916, 16224624, 19987036, -4082269, + -24236251, -5915248, 15766062, 8407814}, + {-20406999, 13990231, 15495425, 16395525, 5377168, 15166495, + -8917023, -4388953, -8067909, 2276718}, + }, + { + {30157918, 12924066, -17712050, 9245753, 19895028, 3368142, + -23827587, 5096219, 22740376, -7303417}, + {2041139, -14256350, 7783687, 13876377, -25946985, -13352459, + 24051124, 13742383, -15637599, 13295222}, + {33338237, -8505733, 12532113, 7977527, 9106186, -1715251, + -17720195, -4612972, -4451357, -14669444}, + }, + { + {-20045281, 5454097, -14346548, 6447146, 28862071, 1883651, + -2469266, -4141880, 7770569, 9620597}, + {23208068, 7979712, 33071466, 8149229, 1758231, -10834995, 30945528, + -1694323, -33502340, -14767970}, + {1439958, -16270480, -1079989, -793782, 4625402, 10647766, -5043801, + 1220118, 30494170, -11440799}, + }, + { + {-5037580, -13028295, -2970559, -3061767, 15640974, -6701666, + -26739026, 926050, -1684339, -13333647}, + {13908495, -3549272, 30919928, -6273825, -21521863, 7989039, + 9021034, 9078865, 3353509, 4033511}, + {-29663431, -15113610, 32259991, -344482, 24295849, -12912123, + 23161163, 8839127, 27485041, 7356032}, + }, + }, + { + { + {9661027, 705443, 11980065, -5370154, -1628543, 14661173, -6346142, + 2625015, 28431036, -16771834}, + {-23839233, -8311415, -25945511, 7480958, -17681669, -8354183, + -22545972, 14150565, 15970762, 4099461}, + {29262576, 16756590, 26350592, -8793563, 8529671, -11208050, + 13617293, -9937143, 11465739, 8317062}, + }, + { + {-25493081, -6962928, 32500200, -9419051, -23038724, -2302222, + 14898637, 3848455, 20969334, -5157516}, + {-20384450, -14347713, -18336405, 13884722, -33039454, 2842114, + -21610826, -3649888, 11177095, 14989547}, + {-24496721, -11716016, 16959896, 2278463, 12066309, 10137771, + 13515641, 2581286, -28487508, 9930240}, + }, + { + {-17751622, -2097826, 16544300, -13009300, -15914807, -14949081, + 18345767, -13403753, 16291481, -5314038}, + {-33229194, 2553288, 32678213, 9875984, 8534129, 6889387, -9676774, + 6957617, 4368891, 9788741}, + {16660756, 7281060, -10830758, 12911820, 20108584, -8101676, + -21722536, -8613148, 16250552, -11111103}, + }, + { + {-19765507, 2390526, -16551031, 14161980, 1905286, 6414907, 4689584, + 10604807, -30190403, 4782747}, + {-1354539, 14736941, -7367442, -13292886, 7710542, -14155590, + -9981571, 4383045, 22546403, 437323}, + {31665577, -12180464, -16186830, 1491339, -18368625, 3294682, + 27343084, 2786261, -30633590, -14097016}, + }, + { + {-14467279, -683715, -33374107, 7448552, 19294360, 14334329, + -19690631, 2355319, -19284671, -6114373}, + {15121312, -15796162, 6377020, -6031361, -10798111, -12957845, + 18952177, 15496498, -29380133, 11754228}, + {-2637277, -13483075, 8488727, -14303896, 12728761, -1622493, + 7141596, 11724556, 22761615, -10134141}, + }, + { + {16918416, 11729663, -18083579, 3022987, -31015732, -13339659, + -28741185, -12227393, 32851222, 11717399}, + {11166634, 7338049, -6722523, 4531520, -29468672, -7302055, + 31474879, 3483633, -1193175, -4030831}, + {-185635, 9921305, 31456609, -13536438, -12013818, 13348923, + 33142652, 6546660, -19985279, -3948376}, + }, + { + {-32460596, 11266712, -11197107, -7899103, 31703694, 3855903, + -8537131, -12833048, -30772034, -15486313}, + {-18006477, 12709068, 3991746, -6479188, -21491523, -10550425, + -31135347, -16049879, 10928917, 3011958}, + {-6957757, -15594337, 31696059, 334240, 29576716, 14796075, + -30831056, -12805180, 18008031, 10258577}, + }, + { + {-22448644, 15655569, 7018479, -4410003, -30314266, -1201591, + -1853465, 1367120, 25127874, 6671743}, + {29701166, -14373934, -10878120, 9279288, -17568, 13127210, + 21382910, 11042292, 25838796, 4642684}, + {-20430234, 14955537, -24126347, 8124619, -5369288, -5990470, + 30468147, -13900640, 18423289, 4177476}, + }, + }, +}; + +static uint8_t negative(signed char b) +{ + uint32_t x = b; + + x >>= 31; /* 1: yes; 0: no */ + return x; +} + +static void table_select(ge_precomp *t, int pos, signed char b) +{ + ge_precomp minust; + uint8_t bnegative = negative(b); + uint8_t babs = b - ((uint8_t)((-bnegative) & b) << 1); + + ge_precomp_0(t); + cmov(t, &k25519Precomp[pos][0], equal(babs, 1)); + cmov(t, &k25519Precomp[pos][1], equal(babs, 2)); + cmov(t, &k25519Precomp[pos][2], equal(babs, 3)); + cmov(t, &k25519Precomp[pos][3], equal(babs, 4)); + cmov(t, &k25519Precomp[pos][4], equal(babs, 5)); + cmov(t, &k25519Precomp[pos][5], equal(babs, 6)); + cmov(t, &k25519Precomp[pos][6], equal(babs, 7)); + cmov(t, &k25519Precomp[pos][7], equal(babs, 8)); + fe_copy(minust.yplusx, t->yminusx); + fe_copy(minust.yminusx, t->yplusx); + fe_neg(minust.xy2d, t->xy2d); + cmov(t, &minust, bnegative); +} + +/* + * h = a * B + * + * where a = a[0]+256*a[1]+...+256^31 a[31] + * B is the Ed25519 base point (x,4/5) with x positive. + * + * Preconditions: + * a[31] <= 127 + */ +static void ge_scalarmult_base(ge_p3 *h, const uint8_t *a) +{ + signed char e[64]; + signed char carry; + ge_p1p1 r; + ge_p2 s; + ge_precomp t; + int i; + + for (i = 0; i < 32; ++i) { + e[2 * i + 0] = (a[i] >> 0) & 15; + e[2 * i + 1] = (a[i] >> 4) & 15; + } + /* each e[i] is between 0 and 15 */ + /* e[63] is between 0 and 7 */ + + carry = 0; + for (i = 0; i < 63; ++i) { + e[i] += carry; + carry = e[i] + 8; + carry >>= 4; + e[i] -= carry << 4; + } + e[63] += carry; + /* each e[i] is between -8 and 8 */ + + ge_p3_0(h); + for (i = 1; i < 64; i += 2) { + table_select(&t, i / 2, e[i]); + ge_madd(&r, h, &t); + ge_p1p1_to_p3(h, &r); + } + + ge_p3_dbl(&r, h); + ge_p1p1_to_p2(&s, &r); + ge_p2_dbl(&r, &s); + ge_p1p1_to_p2(&s, &r); + ge_p2_dbl(&r, &s); + ge_p1p1_to_p2(&s, &r); + ge_p2_dbl(&r, &s); + ge_p1p1_to_p3(h, &r); + + for (i = 0; i < 64; i += 2) { + table_select(&t, i / 2, e[i]); + ge_madd(&r, h, &t); + ge_p1p1_to_p3(h, &r); + } + + OPENSSL_cleanse(e, sizeof(e)); +} + +#if !defined(BASE_2_51_IMPLEMENTED) +/* + * Replace (f,g) with (g,f) if b == 1; + * replace (f,g) with (f,g) if b == 0. + * + * Preconditions: b in {0,1}. + */ +static void fe_cswap(fe f, fe g, unsigned int b) +{ + size_t i; + + b = 0-b; + for (i = 0; i < 10; i++) { + int32_t x = f[i] ^ g[i]; + x &= b; + f[i] ^= x; + g[i] ^= x; + } +} + +/* + * h = f * 121666 + * + * Can overlap h with f. + * + * Preconditions: + * |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. + * + * Postconditions: + * |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. + */ +static void fe_mul121666(fe h, fe f) +{ + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int64_t h0 = f0 * (int64_t) 121666; + int64_t h1 = f1 * (int64_t) 121666; + int64_t h2 = f2 * (int64_t) 121666; + int64_t h3 = f3 * (int64_t) 121666; + int64_t h4 = f4 * (int64_t) 121666; + int64_t h5 = f5 * (int64_t) 121666; + int64_t h6 = f6 * (int64_t) 121666; + int64_t h7 = f7 * (int64_t) 121666; + int64_t h8 = f8 * (int64_t) 121666; + int64_t h9 = f9 * (int64_t) 121666; + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + + carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits; + carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits; + carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits; + carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits; + carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits; + + carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits; + carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits; + carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits; + carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits; + carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits; + + h[0] = (int32_t)h0; + h[1] = (int32_t)h1; + h[2] = (int32_t)h2; + h[3] = (int32_t)h3; + h[4] = (int32_t)h4; + h[5] = (int32_t)h5; + h[6] = (int32_t)h6; + h[7] = (int32_t)h7; + h[8] = (int32_t)h8; + h[9] = (int32_t)h9; +} + +static void x25519_scalar_mult_generic(uint8_t out[32], + const uint8_t scalar[32], + const uint8_t point[32]) { + fe x1, x2, z2, x3, z3, tmp0, tmp1; + uint8_t e[32]; + unsigned swap = 0; + int pos; + + memcpy(e, scalar, 32); + e[0] &= 248; + e[31] &= 127; + e[31] |= 64; + fe_frombytes(x1, point); + fe_1(x2); + fe_0(z2); + fe_copy(x3, x1); + fe_1(z3); + + for (pos = 254; pos >= 0; --pos) { + unsigned b = 1 & (e[pos / 8] >> (pos & 7)); + swap ^= b; + fe_cswap(x2, x3, swap); + fe_cswap(z2, z3, swap); + swap = b; + fe_sub(tmp0, x3, z3); + fe_sub(tmp1, x2, z2); + fe_add(x2, x2, z2); + fe_add(z2, x3, z3); + fe_mul(z3, tmp0, x2); + fe_mul(z2, z2, tmp1); + fe_sq(tmp0, tmp1); + fe_sq(tmp1, x2); + fe_add(x3, z3, z2); + fe_sub(z2, z3, z2); + fe_mul(x2, tmp1, tmp0); + fe_sub(tmp1, tmp1, tmp0); + fe_sq(z2, z2); + fe_mul121666(z3, tmp1); + fe_sq(x3, x3); + fe_add(tmp0, tmp0, z3); + fe_mul(z3, x1, z2); + fe_mul(z2, tmp1, tmp0); + } + + fe_invert(z2, z2); + fe_mul(x2, x2, z2); + fe_tobytes(out, x2); + + OPENSSL_cleanse(e, sizeof(e)); +} + +static void x25519_scalar_mult(uint8_t out[32], const uint8_t scalar[32], + const uint8_t point[32]) { + x25519_scalar_mult_generic(out, scalar, point); +} +#endif + +static void slide(signed char *r, const uint8_t *a) +{ + int i; + int b; + int k; + + for (i = 0; i < 256; ++i) { + r[i] = 1 & (a[i >> 3] >> (i & 7)); + } + + for (i = 0; i < 256; ++i) { + if (r[i]) { + for (b = 1; b <= 6 && i + b < 256; ++b) { + if (r[i + b]) { + if (r[i] + (r[i + b] << b) <= 15) { + r[i] += r[i + b] << b; + r[i + b] = 0; + } else if (r[i] - (r[i + b] << b) >= -15) { + r[i] -= r[i + b] << b; + for (k = i + b; k < 256; ++k) { + if (!r[k]) { + r[k] = 1; + break; + } + r[k] = 0; + } + } else { + break; + } + } + } + } + } +} + +static const ge_precomp Bi[8] = { + { + {25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, + -11754271, -6079156, 2047605}, + {-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, + 5043384, 19500929, -15469378}, + {-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, + 11864899, -24514362, -4438546}, + }, + { + {15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, + -14772189, 28944400, -1550024}, + {16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, + -11775962, 7689662, 11199574}, + {30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, + 10017326, -17749093, -9920357}, + }, + { + {10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, + 14515107, -15438304, 10819380}, + {4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, + 12483688, -12668491, 5581306}, + {19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, + 13850243, -23678021, -15815942}, + }, + { + {5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, + 5230134, -23952439, -15175766}, + {-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, + 16520125, 30598449, 7715701}, + {28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, + 1370708, 29794553, -1409300}, + }, + { + {-22518993, -6692182, 14201702, -8745502, -23510406, 8844726, 18474211, + -1361450, -13062696, 13821877}, + {-6455177, -7839871, 3374702, -4740862, -27098617, -10571707, 31655028, + -7212327, 18853322, -14220951}, + {4566830, -12963868, -28974889, -12240689, -7602672, -2830569, -8514358, + -10431137, 2207753, -3209784}, + }, + { + {-25154831, -4185821, 29681144, 7868801, -6854661, -9423865, -12437364, + -663000, -31111463, -16132436}, + {25576264, -2703214, 7349804, -11814844, 16472782, 9300885, 3844789, + 15725684, 171356, 6466918}, + {23103977, 13316479, 9739013, -16149481, 817875, -15038942, 8965339, + -14088058, -30714912, 16193877}, + }, + { + {-33521811, 3180713, -2394130, 14003687, -16903474, -16270840, 17238398, + 4729455, -18074513, 9256800}, + {-25182317, -4174131, 32336398, 5036987, -21236817, 11360617, 22616405, + 9761698, -19827198, 630305}, + {-13720693, 2639453, -24237460, -7406481, 9494427, -5774029, -6554551, + -15960994, -2449256, -14291300}, + }, + { + {-3151181, -5046075, 9282714, 6866145, -31907062, -863023, -18940575, + 15033784, 25105118, -7894876}, + {-24326370, 15950226, -31801215, -14592823, -11662737, -5090925, + 1573892, -2625887, 2198790, -15804619}, + {-3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022, + -16236442, -32461234, -12290683}, + }, +}; + +/* + * r = a * A + b * B + * + * where a = a[0]+256*a[1]+...+256^31 a[31]. + * and b = b[0]+256*b[1]+...+256^31 b[31]. + * B is the Ed25519 base point (x,4/5) with x positive. + */ +static void ge_double_scalarmult_vartime(ge_p2 *r, const uint8_t *a, + const ge_p3 *A, const uint8_t *b) +{ + signed char aslide[256]; + signed char bslide[256]; + ge_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */ + ge_p1p1 t; + ge_p3 u; + ge_p3 A2; + int i; + + slide(aslide, a); + slide(bslide, b); + + ge_p3_to_cached(&Ai[0], A); + ge_p3_dbl(&t, A); + ge_p1p1_to_p3(&A2, &t); + ge_add(&t, &A2, &Ai[0]); + ge_p1p1_to_p3(&u, &t); + ge_p3_to_cached(&Ai[1], &u); + ge_add(&t, &A2, &Ai[1]); + ge_p1p1_to_p3(&u, &t); + ge_p3_to_cached(&Ai[2], &u); + ge_add(&t, &A2, &Ai[2]); + ge_p1p1_to_p3(&u, &t); + ge_p3_to_cached(&Ai[3], &u); + ge_add(&t, &A2, &Ai[3]); + ge_p1p1_to_p3(&u, &t); + ge_p3_to_cached(&Ai[4], &u); + ge_add(&t, &A2, &Ai[4]); + ge_p1p1_to_p3(&u, &t); + ge_p3_to_cached(&Ai[5], &u); + ge_add(&t, &A2, &Ai[5]); + ge_p1p1_to_p3(&u, &t); + ge_p3_to_cached(&Ai[6], &u); + ge_add(&t, &A2, &Ai[6]); + ge_p1p1_to_p3(&u, &t); + ge_p3_to_cached(&Ai[7], &u); + + ge_p2_0(r); + + for (i = 255; i >= 0; --i) { + if (aslide[i] || bslide[i]) { + break; + } + } + + for (; i >= 0; --i) { + ge_p2_dbl(&t, r); + + if (aslide[i] > 0) { + ge_p1p1_to_p3(&u, &t); + ge_add(&t, &u, &Ai[aslide[i] / 2]); + } else if (aslide[i] < 0) { + ge_p1p1_to_p3(&u, &t); + ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]); + } + + if (bslide[i] > 0) { + ge_p1p1_to_p3(&u, &t); + ge_madd(&t, &u, &Bi[bslide[i] / 2]); + } else if (bslide[i] < 0) { + ge_p1p1_to_p3(&u, &t); + ge_msub(&t, &u, &Bi[(-bslide[i]) / 2]); + } + + ge_p1p1_to_p2(r, &t); + } +} + +/* + * The set of scalars is \Z/l + * where l = 2^252 + 27742317777372353535851937790883648493. + * + * Input: + * s[0]+256*s[1]+...+256^63*s[63] = s + * + * Output: + * s[0]+256*s[1]+...+256^31*s[31] = s mod l + * where l = 2^252 + 27742317777372353535851937790883648493. + * Overwrites s in place. +*/ +static void x25519_sc_reduce(uint8_t *s) +{ + int64_t s0 = kBottom21Bits & load_3(s); + int64_t s1 = kBottom21Bits & (load_4(s + 2) >> 5); + int64_t s2 = kBottom21Bits & (load_3(s + 5) >> 2); + int64_t s3 = kBottom21Bits & (load_4(s + 7) >> 7); + int64_t s4 = kBottom21Bits & (load_4(s + 10) >> 4); + int64_t s5 = kBottom21Bits & (load_3(s + 13) >> 1); + int64_t s6 = kBottom21Bits & (load_4(s + 15) >> 6); + int64_t s7 = kBottom21Bits & (load_3(s + 18) >> 3); + int64_t s8 = kBottom21Bits & load_3(s + 21); + int64_t s9 = kBottom21Bits & (load_4(s + 23) >> 5); + int64_t s10 = kBottom21Bits & (load_3(s + 26) >> 2); + int64_t s11 = kBottom21Bits & (load_4(s + 28) >> 7); + int64_t s12 = kBottom21Bits & (load_4(s + 31) >> 4); + int64_t s13 = kBottom21Bits & (load_3(s + 34) >> 1); + int64_t s14 = kBottom21Bits & (load_4(s + 36) >> 6); + int64_t s15 = kBottom21Bits & (load_3(s + 39) >> 3); + int64_t s16 = kBottom21Bits & load_3(s + 42); + int64_t s17 = kBottom21Bits & (load_4(s + 44) >> 5); + int64_t s18 = kBottom21Bits & (load_3(s + 47) >> 2); + int64_t s19 = kBottom21Bits & (load_4(s + 49) >> 7); + int64_t s20 = kBottom21Bits & (load_4(s + 52) >> 4); + int64_t s21 = kBottom21Bits & (load_3(s + 55) >> 1); + int64_t s22 = kBottom21Bits & (load_4(s + 57) >> 6); + int64_t s23 = (load_4(s + 60) >> 3); + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + int64_t carry10; + int64_t carry11; + int64_t carry12; + int64_t carry13; + int64_t carry14; + int64_t carry15; + int64_t carry16; + + s11 += s23 * 666643; + s12 += s23 * 470296; + s13 += s23 * 654183; + s14 -= s23 * 997805; + s15 += s23 * 136657; + s16 -= s23 * 683901; + s23 = 0; + + s10 += s22 * 666643; + s11 += s22 * 470296; + s12 += s22 * 654183; + s13 -= s22 * 997805; + s14 += s22 * 136657; + s15 -= s22 * 683901; + s22 = 0; + + s9 += s21 * 666643; + s10 += s21 * 470296; + s11 += s21 * 654183; + s12 -= s21 * 997805; + s13 += s21 * 136657; + s14 -= s21 * 683901; + s21 = 0; + + s8 += s20 * 666643; + s9 += s20 * 470296; + s10 += s20 * 654183; + s11 -= s20 * 997805; + s12 += s20 * 136657; + s13 -= s20 * 683901; + s20 = 0; + + s7 += s19 * 666643; + s8 += s19 * 470296; + s9 += s19 * 654183; + s10 -= s19 * 997805; + s11 += s19 * 136657; + s12 -= s19 * 683901; + s19 = 0; + + s6 += s18 * 666643; + s7 += s18 * 470296; + s8 += s18 * 654183; + s9 -= s18 * 997805; + s10 += s18 * 136657; + s11 -= s18 * 683901; + s18 = 0; + + carry6 = (s6 + (1 << 20)) >> 21; + s7 += carry6; + s6 -= carry6 * (1 << 21); + carry8 = (s8 + (1 << 20)) >> 21; + s9 += carry8; + s8 -= carry8 * (1 << 21); + carry10 = (s10 + (1 << 20)) >> 21; + s11 += carry10; + s10 -= carry10 * (1 << 21); + carry12 = (s12 + (1 << 20)) >> 21; + s13 += carry12; + s12 -= carry12 * (1 << 21); + carry14 = (s14 + (1 << 20)) >> 21; + s15 += carry14; + s14 -= carry14 * (1 << 21); + carry16 = (s16 + (1 << 20)) >> 21; + s17 += carry16; + s16 -= carry16 * (1 << 21); + + carry7 = (s7 + (1 << 20)) >> 21; + s8 += carry7; + s7 -= carry7 * (1 << 21); + carry9 = (s9 + (1 << 20)) >> 21; + s10 += carry9; + s9 -= carry9 * (1 << 21); + carry11 = (s11 + (1 << 20)) >> 21; + s12 += carry11; + s11 -= carry11 * (1 << 21); + carry13 = (s13 + (1 << 20)) >> 21; + s14 += carry13; + s13 -= carry13 * (1 << 21); + carry15 = (s15 + (1 << 20)) >> 21; + s16 += carry15; + s15 -= carry15 * (1 << 21); + + s5 += s17 * 666643; + s6 += s17 * 470296; + s7 += s17 * 654183; + s8 -= s17 * 997805; + s9 += s17 * 136657; + s10 -= s17 * 683901; + s17 = 0; + + s4 += s16 * 666643; + s5 += s16 * 470296; + s6 += s16 * 654183; + s7 -= s16 * 997805; + s8 += s16 * 136657; + s9 -= s16 * 683901; + s16 = 0; + + s3 += s15 * 666643; + s4 += s15 * 470296; + s5 += s15 * 654183; + s6 -= s15 * 997805; + s7 += s15 * 136657; + s8 -= s15 * 683901; + s15 = 0; + + s2 += s14 * 666643; + s3 += s14 * 470296; + s4 += s14 * 654183; + s5 -= s14 * 997805; + s6 += s14 * 136657; + s7 -= s14 * 683901; + s14 = 0; + + s1 += s13 * 666643; + s2 += s13 * 470296; + s3 += s13 * 654183; + s4 -= s13 * 997805; + s5 += s13 * 136657; + s6 -= s13 * 683901; + s13 = 0; + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = (s0 + (1 << 20)) >> 21; + s1 += carry0; + s0 -= carry0 * (1 << 21); + carry2 = (s2 + (1 << 20)) >> 21; + s3 += carry2; + s2 -= carry2 * (1 << 21); + carry4 = (s4 + (1 << 20)) >> 21; + s5 += carry4; + s4 -= carry4 * (1 << 21); + carry6 = (s6 + (1 << 20)) >> 21; + s7 += carry6; + s6 -= carry6 * (1 << 21); + carry8 = (s8 + (1 << 20)) >> 21; + s9 += carry8; + s8 -= carry8 * (1 << 21); + carry10 = (s10 + (1 << 20)) >> 21; + s11 += carry10; + s10 -= carry10 * (1 << 21); + + carry1 = (s1 + (1 << 20)) >> 21; + s2 += carry1; + s1 -= carry1 * (1 << 21); + carry3 = (s3 + (1 << 20)) >> 21; + s4 += carry3; + s3 -= carry3 * (1 << 21); + carry5 = (s5 + (1 << 20)) >> 21; + s6 += carry5; + s5 -= carry5 * (1 << 21); + carry7 = (s7 + (1 << 20)) >> 21; + s8 += carry7; + s7 -= carry7 * (1 << 21); + carry9 = (s9 + (1 << 20)) >> 21; + s10 += carry9; + s9 -= carry9 * (1 << 21); + carry11 = (s11 + (1 << 20)) >> 21; + s12 += carry11; + s11 -= carry11 * (1 << 21); + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = s0 >> 21; + s1 += carry0; + s0 -= carry0 * (1 << 21); + carry1 = s1 >> 21; + s2 += carry1; + s1 -= carry1 * (1 << 21); + carry2 = s2 >> 21; + s3 += carry2; + s2 -= carry2 * (1 << 21); + carry3 = s3 >> 21; + s4 += carry3; + s3 -= carry3 * (1 << 21); + carry4 = s4 >> 21; + s5 += carry4; + s4 -= carry4 * (1 << 21); + carry5 = s5 >> 21; + s6 += carry5; + s5 -= carry5 * (1 << 21); + carry6 = s6 >> 21; + s7 += carry6; + s6 -= carry6 * (1 << 21); + carry7 = s7 >> 21; + s8 += carry7; + s7 -= carry7 * (1 << 21); + carry8 = s8 >> 21; + s9 += carry8; + s8 -= carry8 * (1 << 21); + carry9 = s9 >> 21; + s10 += carry9; + s9 -= carry9 * (1 << 21); + carry10 = s10 >> 21; + s11 += carry10; + s10 -= carry10 * (1 << 21); + carry11 = s11 >> 21; + s12 += carry11; + s11 -= carry11 * (1 << 21); + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = s0 >> 21; + s1 += carry0; + s0 -= carry0 * (1 << 21); + carry1 = s1 >> 21; + s2 += carry1; + s1 -= carry1 * (1 << 21); + carry2 = s2 >> 21; + s3 += carry2; + s2 -= carry2 * (1 << 21); + carry3 = s3 >> 21; + s4 += carry3; + s3 -= carry3 * (1 << 21); + carry4 = s4 >> 21; + s5 += carry4; + s4 -= carry4 * (1 << 21); + carry5 = s5 >> 21; + s6 += carry5; + s5 -= carry5 * (1 << 21); + carry6 = s6 >> 21; + s7 += carry6; + s6 -= carry6 * (1 << 21); + carry7 = s7 >> 21; + s8 += carry7; + s7 -= carry7 * (1 << 21); + carry8 = s8 >> 21; + s9 += carry8; + s8 -= carry8 * (1 << 21); + carry9 = s9 >> 21; + s10 += carry9; + s9 -= carry9 * (1 << 21); + carry10 = s10 >> 21; + s11 += carry10; + s10 -= carry10 * (1 << 21); + + s[ 0] = (uint8_t) (s0 >> 0); + s[ 1] = (uint8_t) (s0 >> 8); + s[ 2] = (uint8_t)((s0 >> 16) | (s1 << 5)); + s[ 3] = (uint8_t) (s1 >> 3); + s[ 4] = (uint8_t) (s1 >> 11); + s[ 5] = (uint8_t)((s1 >> 19) | (s2 << 2)); + s[ 6] = (uint8_t) (s2 >> 6); + s[ 7] = (uint8_t)((s2 >> 14) | (s3 << 7)); + s[ 8] = (uint8_t) (s3 >> 1); + s[ 9] = (uint8_t) (s3 >> 9); + s[10] = (uint8_t)((s3 >> 17) | (s4 << 4)); + s[11] = (uint8_t) (s4 >> 4); + s[12] = (uint8_t) (s4 >> 12); + s[13] = (uint8_t)((s4 >> 20) | (s5 << 1)); + s[14] = (uint8_t) (s5 >> 7); + s[15] = (uint8_t)((s5 >> 15) | (s6 << 6)); + s[16] = (uint8_t) (s6 >> 2); + s[17] = (uint8_t) (s6 >> 10); + s[18] = (uint8_t)((s6 >> 18) | (s7 << 3)); + s[19] = (uint8_t) (s7 >> 5); + s[20] = (uint8_t) (s7 >> 13); + s[21] = (uint8_t) (s8 >> 0); + s[22] = (uint8_t) (s8 >> 8); + s[23] = (uint8_t)((s8 >> 16) | (s9 << 5)); + s[24] = (uint8_t) (s9 >> 3); + s[25] = (uint8_t) (s9 >> 11); + s[26] = (uint8_t)((s9 >> 19) | (s10 << 2)); + s[27] = (uint8_t) (s10 >> 6); + s[28] = (uint8_t)((s10 >> 14) | (s11 << 7)); + s[29] = (uint8_t) (s11 >> 1); + s[30] = (uint8_t) (s11 >> 9); + s[31] = (uint8_t) (s11 >> 17); +} + +/* + * Input: + * a[0]+256*a[1]+...+256^31*a[31] = a + * b[0]+256*b[1]+...+256^31*b[31] = b + * c[0]+256*c[1]+...+256^31*c[31] = c + * + * Output: + * s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l + * where l = 2^252 + 27742317777372353535851937790883648493. + */ +static void sc_muladd(uint8_t *s, const uint8_t *a, const uint8_t *b, + const uint8_t *c) +{ + int64_t a0 = kBottom21Bits & load_3(a); + int64_t a1 = kBottom21Bits & (load_4(a + 2) >> 5); + int64_t a2 = kBottom21Bits & (load_3(a + 5) >> 2); + int64_t a3 = kBottom21Bits & (load_4(a + 7) >> 7); + int64_t a4 = kBottom21Bits & (load_4(a + 10) >> 4); + int64_t a5 = kBottom21Bits & (load_3(a + 13) >> 1); + int64_t a6 = kBottom21Bits & (load_4(a + 15) >> 6); + int64_t a7 = kBottom21Bits & (load_3(a + 18) >> 3); + int64_t a8 = kBottom21Bits & load_3(a + 21); + int64_t a9 = kBottom21Bits & (load_4(a + 23) >> 5); + int64_t a10 = kBottom21Bits & (load_3(a + 26) >> 2); + int64_t a11 = (load_4(a + 28) >> 7); + int64_t b0 = kBottom21Bits & load_3(b); + int64_t b1 = kBottom21Bits & (load_4(b + 2) >> 5); + int64_t b2 = kBottom21Bits & (load_3(b + 5) >> 2); + int64_t b3 = kBottom21Bits & (load_4(b + 7) >> 7); + int64_t b4 = kBottom21Bits & (load_4(b + 10) >> 4); + int64_t b5 = kBottom21Bits & (load_3(b + 13) >> 1); + int64_t b6 = kBottom21Bits & (load_4(b + 15) >> 6); + int64_t b7 = kBottom21Bits & (load_3(b + 18) >> 3); + int64_t b8 = kBottom21Bits & load_3(b + 21); + int64_t b9 = kBottom21Bits & (load_4(b + 23) >> 5); + int64_t b10 = kBottom21Bits & (load_3(b + 26) >> 2); + int64_t b11 = (load_4(b + 28) >> 7); + int64_t c0 = kBottom21Bits & load_3(c); + int64_t c1 = kBottom21Bits & (load_4(c + 2) >> 5); + int64_t c2 = kBottom21Bits & (load_3(c + 5) >> 2); + int64_t c3 = kBottom21Bits & (load_4(c + 7) >> 7); + int64_t c4 = kBottom21Bits & (load_4(c + 10) >> 4); + int64_t c5 = kBottom21Bits & (load_3(c + 13) >> 1); + int64_t c6 = kBottom21Bits & (load_4(c + 15) >> 6); + int64_t c7 = kBottom21Bits & (load_3(c + 18) >> 3); + int64_t c8 = kBottom21Bits & load_3(c + 21); + int64_t c9 = kBottom21Bits & (load_4(c + 23) >> 5); + int64_t c10 = kBottom21Bits & (load_3(c + 26) >> 2); + int64_t c11 = (load_4(c + 28) >> 7); + int64_t s0; + int64_t s1; + int64_t s2; + int64_t s3; + int64_t s4; + int64_t s5; + int64_t s6; + int64_t s7; + int64_t s8; + int64_t s9; + int64_t s10; + int64_t s11; + int64_t s12; + int64_t s13; + int64_t s14; + int64_t s15; + int64_t s16; + int64_t s17; + int64_t s18; + int64_t s19; + int64_t s20; + int64_t s21; + int64_t s22; + int64_t s23; + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + int64_t carry10; + int64_t carry11; + int64_t carry12; + int64_t carry13; + int64_t carry14; + int64_t carry15; + int64_t carry16; + int64_t carry17; + int64_t carry18; + int64_t carry19; + int64_t carry20; + int64_t carry21; + int64_t carry22; + + s0 = c0 + a0 * b0; + s1 = c1 + a0 * b1 + a1 * b0; + s2 = c2 + a0 * b2 + a1 * b1 + a2 * b0; + s3 = c3 + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0; + s4 = c4 + a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0; + s5 = c5 + a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0; + s6 = c6 + a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 + a6 * b0; + s7 = c7 + a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 + a6 * b1 + a7 * b0; + s8 = c8 + a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 + a6 * b2 + a7 * b1 + a8 * b0; + s9 = c9 + a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 + a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0; + s10 = c10 + a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 + a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0; + s11 = c11 + a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 + a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0; + s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 + a7 * b5 + a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1; + s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 + a8 * b5 + a9 * b4 + a10 * b3 + a11 * b2; + s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 + a9 * b5 + a10 * b4 + a11 * b3; + s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 + a10 * b5 + a11 * b4; + s16 = a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5; + s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6; + s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7; + s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8; + s20 = a9 * b11 + a10 * b10 + a11 * b9; + s21 = a10 * b11 + a11 * b10; + s22 = a11 * b11; + s23 = 0; + + carry0 = (s0 + (1 << 20)) >> 21; + s1 += carry0; + s0 -= carry0 * (1 << 21); + carry2 = (s2 + (1 << 20)) >> 21; + s3 += carry2; + s2 -= carry2 * (1 << 21); + carry4 = (s4 + (1 << 20)) >> 21; + s5 += carry4; + s4 -= carry4 * (1 << 21); + carry6 = (s6 + (1 << 20)) >> 21; + s7 += carry6; + s6 -= carry6 * (1 << 21); + carry8 = (s8 + (1 << 20)) >> 21; + s9 += carry8; + s8 -= carry8 * (1 << 21); + carry10 = (s10 + (1 << 20)) >> 21; + s11 += carry10; + s10 -= carry10 * (1 << 21); + carry12 = (s12 + (1 << 20)) >> 21; + s13 += carry12; + s12 -= carry12 * (1 << 21); + carry14 = (s14 + (1 << 20)) >> 21; + s15 += carry14; + s14 -= carry14 * (1 << 21); + carry16 = (s16 + (1 << 20)) >> 21; + s17 += carry16; + s16 -= carry16 * (1 << 21); + carry18 = (s18 + (1 << 20)) >> 21; + s19 += carry18; + s18 -= carry18 * (1 << 21); + carry20 = (s20 + (1 << 20)) >> 21; + s21 += carry20; + s20 -= carry20 * (1 << 21); + carry22 = (s22 + (1 << 20)) >> 21; + s23 += carry22; + s22 -= carry22 * (1 << 21); + + carry1 = (s1 + (1 << 20)) >> 21; + s2 += carry1; + s1 -= carry1 * (1 << 21); + carry3 = (s3 + (1 << 20)) >> 21; + s4 += carry3; + s3 -= carry3 * (1 << 21); + carry5 = (s5 + (1 << 20)) >> 21; + s6 += carry5; + s5 -= carry5 * (1 << 21); + carry7 = (s7 + (1 << 20)) >> 21; + s8 += carry7; + s7 -= carry7 * (1 << 21); + carry9 = (s9 + (1 << 20)) >> 21; + s10 += carry9; + s9 -= carry9 * (1 << 21); + carry11 = (s11 + (1 << 20)) >> 21; + s12 += carry11; + s11 -= carry11 * (1 << 21); + carry13 = (s13 + (1 << 20)) >> 21; + s14 += carry13; + s13 -= carry13 * (1 << 21); + carry15 = (s15 + (1 << 20)) >> 21; + s16 += carry15; + s15 -= carry15 * (1 << 21); + carry17 = (s17 + (1 << 20)) >> 21; + s18 += carry17; + s17 -= carry17 * (1 << 21); + carry19 = (s19 + (1 << 20)) >> 21; + s20 += carry19; + s19 -= carry19 * (1 << 21); + carry21 = (s21 + (1 << 20)) >> 21; + s22 += carry21; + s21 -= carry21 * (1 << 21); + + s11 += s23 * 666643; + s12 += s23 * 470296; + s13 += s23 * 654183; + s14 -= s23 * 997805; + s15 += s23 * 136657; + s16 -= s23 * 683901; + s23 = 0; + + s10 += s22 * 666643; + s11 += s22 * 470296; + s12 += s22 * 654183; + s13 -= s22 * 997805; + s14 += s22 * 136657; + s15 -= s22 * 683901; + s22 = 0; + + s9 += s21 * 666643; + s10 += s21 * 470296; + s11 += s21 * 654183; + s12 -= s21 * 997805; + s13 += s21 * 136657; + s14 -= s21 * 683901; + s21 = 0; + + s8 += s20 * 666643; + s9 += s20 * 470296; + s10 += s20 * 654183; + s11 -= s20 * 997805; + s12 += s20 * 136657; + s13 -= s20 * 683901; + s20 = 0; + + s7 += s19 * 666643; + s8 += s19 * 470296; + s9 += s19 * 654183; + s10 -= s19 * 997805; + s11 += s19 * 136657; + s12 -= s19 * 683901; + s19 = 0; + + s6 += s18 * 666643; + s7 += s18 * 470296; + s8 += s18 * 654183; + s9 -= s18 * 997805; + s10 += s18 * 136657; + s11 -= s18 * 683901; + s18 = 0; + + carry6 = (s6 + (1 << 20)) >> 21; + s7 += carry6; + s6 -= carry6 * (1 << 21); + carry8 = (s8 + (1 << 20)) >> 21; + s9 += carry8; + s8 -= carry8 * (1 << 21); + carry10 = (s10 + (1 << 20)) >> 21; + s11 += carry10; + s10 -= carry10 * (1 << 21); + carry12 = (s12 + (1 << 20)) >> 21; + s13 += carry12; + s12 -= carry12 * (1 << 21); + carry14 = (s14 + (1 << 20)) >> 21; + s15 += carry14; + s14 -= carry14 * (1 << 21); + carry16 = (s16 + (1 << 20)) >> 21; + s17 += carry16; + s16 -= carry16 * (1 << 21); + + carry7 = (s7 + (1 << 20)) >> 21; + s8 += carry7; + s7 -= carry7 * (1 << 21); + carry9 = (s9 + (1 << 20)) >> 21; + s10 += carry9; + s9 -= carry9 * (1 << 21); + carry11 = (s11 + (1 << 20)) >> 21; + s12 += carry11; + s11 -= carry11 * (1 << 21); + carry13 = (s13 + (1 << 20)) >> 21; + s14 += carry13; + s13 -= carry13 * (1 << 21); + carry15 = (s15 + (1 << 20)) >> 21; + s16 += carry15; + s15 -= carry15 * (1 << 21); + + s5 += s17 * 666643; + s6 += s17 * 470296; + s7 += s17 * 654183; + s8 -= s17 * 997805; + s9 += s17 * 136657; + s10 -= s17 * 683901; + s17 = 0; + + s4 += s16 * 666643; + s5 += s16 * 470296; + s6 += s16 * 654183; + s7 -= s16 * 997805; + s8 += s16 * 136657; + s9 -= s16 * 683901; + s16 = 0; + + s3 += s15 * 666643; + s4 += s15 * 470296; + s5 += s15 * 654183; + s6 -= s15 * 997805; + s7 += s15 * 136657; + s8 -= s15 * 683901; + s15 = 0; + + s2 += s14 * 666643; + s3 += s14 * 470296; + s4 += s14 * 654183; + s5 -= s14 * 997805; + s6 += s14 * 136657; + s7 -= s14 * 683901; + s14 = 0; + + s1 += s13 * 666643; + s2 += s13 * 470296; + s3 += s13 * 654183; + s4 -= s13 * 997805; + s5 += s13 * 136657; + s6 -= s13 * 683901; + s13 = 0; + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = (s0 + (1 << 20)) >> 21; + s1 += carry0; + s0 -= carry0 * (1 << 21); + carry2 = (s2 + (1 << 20)) >> 21; + s3 += carry2; + s2 -= carry2 * (1 << 21); + carry4 = (s4 + (1 << 20)) >> 21; + s5 += carry4; + s4 -= carry4 * (1 << 21); + carry6 = (s6 + (1 << 20)) >> 21; + s7 += carry6; + s6 -= carry6 * (1 << 21); + carry8 = (s8 + (1 << 20)) >> 21; + s9 += carry8; + s8 -= carry8 * (1 << 21); + carry10 = (s10 + (1 << 20)) >> 21; + s11 += carry10; + s10 -= carry10 * (1 << 21); + + carry1 = (s1 + (1 << 20)) >> 21; + s2 += carry1; + s1 -= carry1 * (1 << 21); + carry3 = (s3 + (1 << 20)) >> 21; + s4 += carry3; + s3 -= carry3 * (1 << 21); + carry5 = (s5 + (1 << 20)) >> 21; + s6 += carry5; + s5 -= carry5 * (1 << 21); + carry7 = (s7 + (1 << 20)) >> 21; + s8 += carry7; + s7 -= carry7 * (1 << 21); + carry9 = (s9 + (1 << 20)) >> 21; + s10 += carry9; + s9 -= carry9 * (1 << 21); + carry11 = (s11 + (1 << 20)) >> 21; + s12 += carry11; + s11 -= carry11 * (1 << 21); + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = s0 >> 21; + s1 += carry0; + s0 -= carry0 * (1 << 21); + carry1 = s1 >> 21; + s2 += carry1; + s1 -= carry1 * (1 << 21); + carry2 = s2 >> 21; + s3 += carry2; + s2 -= carry2 * (1 << 21); + carry3 = s3 >> 21; + s4 += carry3; + s3 -= carry3 * (1 << 21); + carry4 = s4 >> 21; + s5 += carry4; + s4 -= carry4 * (1 << 21); + carry5 = s5 >> 21; + s6 += carry5; + s5 -= carry5 * (1 << 21); + carry6 = s6 >> 21; + s7 += carry6; + s6 -= carry6 * (1 << 21); + carry7 = s7 >> 21; + s8 += carry7; + s7 -= carry7 * (1 << 21); + carry8 = s8 >> 21; + s9 += carry8; + s8 -= carry8 * (1 << 21); + carry9 = s9 >> 21; + s10 += carry9; + s9 -= carry9 * (1 << 21); + carry10 = s10 >> 21; + s11 += carry10; + s10 -= carry10 * (1 << 21); + carry11 = s11 >> 21; + s12 += carry11; + s11 -= carry11 * (1 << 21); + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = s0 >> 21; + s1 += carry0; + s0 -= carry0 * (1 << 21); + carry1 = s1 >> 21; + s2 += carry1; + s1 -= carry1 * (1 << 21); + carry2 = s2 >> 21; + s3 += carry2; + s2 -= carry2 * (1 << 21); + carry3 = s3 >> 21; + s4 += carry3; + s3 -= carry3 * (1 << 21); + carry4 = s4 >> 21; + s5 += carry4; + s4 -= carry4 * (1 << 21); + carry5 = s5 >> 21; + s6 += carry5; + s5 -= carry5 * (1 << 21); + carry6 = s6 >> 21; + s7 += carry6; + s6 -= carry6 * (1 << 21); + carry7 = s7 >> 21; + s8 += carry7; + s7 -= carry7 * (1 << 21); + carry8 = s8 >> 21; + s9 += carry8; + s8 -= carry8 * (1 << 21); + carry9 = s9 >> 21; + s10 += carry9; + s9 -= carry9 * (1 << 21); + carry10 = s10 >> 21; + s11 += carry10; + s10 -= carry10 * (1 << 21); + + s[ 0] = (uint8_t) (s0 >> 0); + s[ 1] = (uint8_t) (s0 >> 8); + s[ 2] = (uint8_t)((s0 >> 16) | (s1 << 5)); + s[ 3] = (uint8_t) (s1 >> 3); + s[ 4] = (uint8_t) (s1 >> 11); + s[ 5] = (uint8_t)((s1 >> 19) | (s2 << 2)); + s[ 6] = (uint8_t) (s2 >> 6); + s[ 7] = (uint8_t)((s2 >> 14) | (s3 << 7)); + s[ 8] = (uint8_t) (s3 >> 1); + s[ 9] = (uint8_t) (s3 >> 9); + s[10] = (uint8_t)((s3 >> 17) | (s4 << 4)); + s[11] = (uint8_t) (s4 >> 4); + s[12] = (uint8_t) (s4 >> 12); + s[13] = (uint8_t)((s4 >> 20) | (s5 << 1)); + s[14] = (uint8_t) (s5 >> 7); + s[15] = (uint8_t)((s5 >> 15) | (s6 << 6)); + s[16] = (uint8_t) (s6 >> 2); + s[17] = (uint8_t) (s6 >> 10); + s[18] = (uint8_t)((s6 >> 18) | (s7 << 3)); + s[19] = (uint8_t) (s7 >> 5); + s[20] = (uint8_t) (s7 >> 13); + s[21] = (uint8_t) (s8 >> 0); + s[22] = (uint8_t) (s8 >> 8); + s[23] = (uint8_t)((s8 >> 16) | (s9 << 5)); + s[24] = (uint8_t) (s9 >> 3); + s[25] = (uint8_t) (s9 >> 11); + s[26] = (uint8_t)((s9 >> 19) | (s10 << 2)); + s[27] = (uint8_t) (s10 >> 6); + s[28] = (uint8_t)((s10 >> 14) | (s11 << 7)); + s[29] = (uint8_t) (s11 >> 1); + s[30] = (uint8_t) (s11 >> 9); + s[31] = (uint8_t) (s11 >> 17); +} + +int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len, + const uint8_t public_key[32], const uint8_t private_key[32]) +{ + uint8_t az[SHA512_DIGEST_LENGTH]; + uint8_t nonce[SHA512_DIGEST_LENGTH]; + ge_p3 R; + uint8_t hram[SHA512_DIGEST_LENGTH]; + SHA512_CTX hash_ctx; + + SHA512_Init(&hash_ctx); + SHA512_Update(&hash_ctx, private_key, 32); + SHA512_Final(az, &hash_ctx); + + az[0] &= 248; + az[31] &= 63; + az[31] |= 64; + + SHA512_Init(&hash_ctx); + SHA512_Update(&hash_ctx, az + 32, 32); + SHA512_Update(&hash_ctx, message, message_len); + SHA512_Final(nonce, &hash_ctx); + + x25519_sc_reduce(nonce); + ge_scalarmult_base(&R, nonce); + ge_p3_tobytes(out_sig, &R); + + SHA512_Init(&hash_ctx); + SHA512_Update(&hash_ctx, out_sig, 32); + SHA512_Update(&hash_ctx, public_key, 32); + SHA512_Update(&hash_ctx, message, message_len); + SHA512_Final(hram, &hash_ctx); + + x25519_sc_reduce(hram); + sc_muladd(out_sig + 32, hram, az, nonce); + + OPENSSL_cleanse(&hash_ctx, sizeof(hash_ctx)); + OPENSSL_cleanse(nonce, sizeof(nonce)); + OPENSSL_cleanse(az, sizeof(az)); + + return 1; +} + +static const char allzeroes[15]; + +int ED25519_verify(const uint8_t *message, size_t message_len, + const uint8_t signature[64], const uint8_t public_key[32]) +{ + int i; + ge_p3 A; + const uint8_t *r, *s; + SHA512_CTX hash_ctx; + ge_p2 R; + uint8_t rcheck[32]; + uint8_t h[SHA512_DIGEST_LENGTH]; + /* 27742317777372353535851937790883648493 in little endian format */ + const uint8_t l_low[16] = { + 0xED, 0xD3, 0xF5, 0x5C, 0x1A, 0x63, 0x12, 0x58, 0xD6, 0x9C, 0xF7, 0xA2, + 0xDE, 0xF9, 0xDE, 0x14 + }; + + r = signature; + s = signature + 32; + + /* + * Check 0 <= s < L where L = 2^252 + 27742317777372353535851937790883648493 + * + * If not the signature is publicly invalid. Since it's public we can do the + * check in variable time. + * + * First check the most significant byte + */ + if (s[31] > 0x10) + return 0; + if (s[31] == 0x10) { + /* + * Most significant byte indicates a value close to 2^252 so check the + * rest + */ + if (memcmp(s + 16, allzeroes, sizeof(allzeroes)) != 0) + return 0; + for (i = 15; i >= 0; i--) { + if (s[i] < l_low[i]) + break; + if (s[i] > l_low[i]) + return 0; + } + if (i < 0) + return 0; + } + + if (ge_frombytes_vartime(&A, public_key) != 0) { + return 0; + } + + fe_neg(A.X, A.X); + fe_neg(A.T, A.T); + + SHA512_Init(&hash_ctx); + SHA512_Update(&hash_ctx, r, 32); + SHA512_Update(&hash_ctx, public_key, 32); + SHA512_Update(&hash_ctx, message, message_len); + SHA512_Final(h, &hash_ctx); + + x25519_sc_reduce(h); + + ge_double_scalarmult_vartime(&R, h, &A, s); + + ge_tobytes(rcheck, &R); + + return CRYPTO_memcmp(rcheck, r, sizeof(rcheck)) == 0; +} + +void ED25519_public_from_private(uint8_t out_public_key[32], + const uint8_t private_key[32]) +{ + uint8_t az[SHA512_DIGEST_LENGTH]; + ge_p3 A; + + SHA512(private_key, 32, az); + + az[0] &= 248; + az[31] &= 63; + az[31] |= 64; + + ge_scalarmult_base(&A, az); + ge_p3_tobytes(out_public_key, &A); + + OPENSSL_cleanse(az, sizeof(az)); +} + +int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32], + const uint8_t peer_public_value[32]) +{ + static const uint8_t kZeros[32] = {0}; + x25519_scalar_mult(out_shared_key, private_key, peer_public_value); + /* The all-zero output results when the input is a point of small order. */ + return CRYPTO_memcmp(kZeros, out_shared_key, 32) != 0; +} + +void X25519_public_from_private(uint8_t out_public_value[32], + const uint8_t private_key[32]) +{ + uint8_t e[32]; + ge_p3 A; + fe zplusy, zminusy, zminusy_inv; + + memcpy(e, private_key, 32); + e[0] &= 248; + e[31] &= 127; + e[31] |= 64; + + ge_scalarmult_base(&A, e); + + /* + * We only need the u-coordinate of the curve25519 point. + * The map is u=(y+1)/(1-y). Since y=Y/Z, this gives + * u=(Z+Y)/(Z-Y). + */ + fe_add(zplusy, A.Z, A.Y); + fe_sub(zminusy, A.Z, A.Y); + fe_invert(zminusy_inv, zminusy); + fe_mul(zplusy, zplusy, zminusy_inv); + fe_tobytes(out_public_value, zplusy); + + OPENSSL_cleanse(e, sizeof(e)); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/arch_32/arch_intrinsics.h b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/arch_32/arch_intrinsics.h new file mode 100644 index 000000000..48081c771 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/arch_32/arch_intrinsics.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016 Cryptography Research, Inc. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + * + * Originally written by Mike Hamburg + */ + +#ifndef HEADER_ARCH_32_ARCH_INTRINSICS_H +# define HEADER_ARCH_32_ARCH_INTRINSICS_H + +#include "internal/constant_time_locl.h" + +# define ARCH_WORD_BITS 32 + +#define word_is_zero(a) constant_time_is_zero_32(a) + +static ossl_inline uint64_t widemul(uint32_t a, uint32_t b) +{ + return ((uint64_t)a) * b; +} + +#endif /* HEADER_ARCH_32_ARCH_INTRINSICS_H */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/arch_32/f_impl.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/arch_32/f_impl.c new file mode 100644 index 000000000..8a89d276e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/arch_32/f_impl.c @@ -0,0 +1,95 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2014 Cryptography Research, Inc. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + * + * Originally written by Mike Hamburg + */ + +#include "field.h" + +void gf_mul(gf_s * RESTRICT cs, const gf as, const gf bs) +{ + const uint32_t *a = as->limb, *b = bs->limb; + uint32_t *c = cs->limb; + uint64_t accum0 = 0, accum1 = 0, accum2 = 0; + uint32_t mask = (1 << 28) - 1; + uint32_t aa[8], bb[8]; + int i, j; + + for (i = 0; i < 8; i++) { + aa[i] = a[i] + a[i + 8]; + bb[i] = b[i] + b[i + 8]; + } + + for (j = 0; j < 8; j++) { + accum2 = 0; + for (i = 0; i < j + 1; i++) { + accum2 += widemul(a[j - i], b[i]); + accum1 += widemul(aa[j - i], bb[i]); + accum0 += widemul(a[8 + j - i], b[8 + i]); + } + accum1 -= accum2; + accum0 += accum2; + accum2 = 0; + for (i = j + 1; i < 8; i++) { + accum0 -= widemul(a[8 + j - i], b[i]); + accum2 += widemul(aa[8 + j - i], bb[i]); + accum1 += widemul(a[16 + j - i], b[8 + i]); + } + accum1 += accum2; + accum0 += accum2; + c[j] = ((uint32_t)(accum0)) & mask; + c[j + 8] = ((uint32_t)(accum1)) & mask; + accum0 >>= 28; + accum1 >>= 28; + } + + accum0 += accum1; + accum0 += c[8]; + accum1 += c[0]; + c[8] = ((uint32_t)(accum0)) & mask; + c[0] = ((uint32_t)(accum1)) & mask; + + accum0 >>= 28; + accum1 >>= 28; + c[9] += ((uint32_t)(accum0)); + c[1] += ((uint32_t)(accum1)); +} + +void gf_mulw_unsigned(gf_s * RESTRICT cs, const gf as, uint32_t b) +{ + const uint32_t *a = as->limb; + uint32_t *c = cs->limb; + uint64_t accum0 = 0, accum8 = 0; + uint32_t mask = (1 << 28) - 1; + int i; + + assert(b <= mask); + + for (i = 0; i < 8; i++) { + accum0 += widemul(b, a[i]); + accum8 += widemul(b, a[i + 8]); + c[i] = accum0 & mask; + accum0 >>= 28; + c[i + 8] = accum8 & mask; + accum8 >>= 28; + } + + accum0 += accum8 + c[8]; + c[8] = ((uint32_t)accum0) & mask; + c[9] += (uint32_t)(accum0 >> 28); + + accum8 += c[0]; + c[0] = ((uint32_t)accum8) & mask; + c[1] += (uint32_t)(accum8 >> 28); +} + +void gf_sqr(gf_s * RESTRICT cs, const gf as) +{ + gf_mul(cs, as, as); /* Performs better with a dedicated square */ +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/arch_32/f_impl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/arch_32/f_impl.h new file mode 100644 index 000000000..bbde84a03 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/arch_32/f_impl.h @@ -0,0 +1,60 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2014-2016 Cryptography Research, Inc. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + * + * Originally written by Mike Hamburg + */ + +#ifndef HEADER_ARCH_32_F_IMPL_H +# define HEADER_ARCH_32_F_IMPL_H + +# define GF_HEADROOM 2 +# define LIMB(x) ((x) & ((1 << 28) - 1)), ((x) >> 28) +# define FIELD_LITERAL(a, b, c, d, e, f, g, h) \ + {{LIMB(a), LIMB(b), LIMB(c), LIMB(d), LIMB(e), LIMB(f), LIMB(g), LIMB(h)}} + +# define LIMB_PLACE_VALUE(i) 28 + +void gf_add_RAW(gf out, const gf a, const gf b) +{ + unsigned int i; + + for (i = 0; i < NLIMBS; i++) + out->limb[i] = a->limb[i] + b->limb[i]; +} + +void gf_sub_RAW(gf out, const gf a, const gf b) +{ + unsigned int i; + + for (i = 0; i < NLIMBS; i++) + out->limb[i] = a->limb[i] - b->limb[i]; +} + +void gf_bias(gf a, int amt) +{ + unsigned int i; + uint32_t co1 = ((1 << 28) - 1) * amt, co2 = co1 - amt; + + for (i = 0; i < NLIMBS; i++) + a->limb[i] += (i == NLIMBS / 2) ? co2 : co1; +} + +void gf_weak_reduce(gf a) +{ + uint32_t mask = (1 << 28) - 1; + uint32_t tmp = a->limb[NLIMBS - 1] >> 28; + unsigned int i; + + a->limb[NLIMBS / 2] += tmp; + for (i = NLIMBS - 1; i > 0; i--) + a->limb[i] = (a->limb[i] & mask) + (a->limb[i - 1] >> 28); + a->limb[0] = (a->limb[0] & mask) + tmp; +} + +#endif /* HEADER_ARCH_32_F_IMPL_H */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/curve448.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/curve448.c new file mode 100644 index 000000000..7dc68c885 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/curve448.c @@ -0,0 +1,727 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2016 Cryptography Research, Inc. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + * + * Originally written by Mike Hamburg + */ +#include +#include "word.h" +#include "field.h" + +#include "point_448.h" +#include "ed448.h" +#include "curve448_lcl.h" + +#define COFACTOR 4 + +#define C448_WNAF_FIXED_TABLE_BITS 5 +#define C448_WNAF_VAR_TABLE_BITS 3 + +#define EDWARDS_D (-39081) + +static const curve448_scalar_t precomputed_scalarmul_adjustment = { + { + { + SC_LIMB(0xc873d6d54a7bb0cf), SC_LIMB(0xe933d8d723a70aad), + SC_LIMB(0xbb124b65129c96fd), SC_LIMB(0x00000008335dc163) + } + } +}; + +#define TWISTED_D (EDWARDS_D - 1) + +#define WBITS C448_WORD_BITS /* NB this may be different from ARCH_WORD_BITS */ + +/* Inverse. */ +static void gf_invert(gf y, const gf x, int assert_nonzero) +{ + mask_t ret; + gf t1, t2; + + gf_sqr(t1, x); /* o^2 */ + ret = gf_isr(t2, t1); /* +-1/sqrt(o^2) = +-1/o */ + (void)ret; + if (assert_nonzero) + assert(ret); + gf_sqr(t1, t2); + gf_mul(t2, t1, x); /* not direct to y in case of alias. */ + gf_copy(y, t2); +} + +/** identity = (0,1) */ +const curve448_point_t curve448_point_identity = + { {{{{0}}}, {{{1}}}, {{{1}}}, {{{0}}}} }; + +static void point_double_internal(curve448_point_t p, const curve448_point_t q, + int before_double) +{ + gf a, b, c, d; + + gf_sqr(c, q->x); + gf_sqr(a, q->y); + gf_add_nr(d, c, a); /* 2+e */ + gf_add_nr(p->t, q->y, q->x); /* 2+e */ + gf_sqr(b, p->t); + gf_subx_nr(b, b, d, 3); /* 4+e */ + gf_sub_nr(p->t, a, c); /* 3+e */ + gf_sqr(p->x, q->z); + gf_add_nr(p->z, p->x, p->x); /* 2+e */ + gf_subx_nr(a, p->z, p->t, 4); /* 6+e */ + if (GF_HEADROOM == 5) + gf_weak_reduce(a); /* or 1+e */ + gf_mul(p->x, a, b); + gf_mul(p->z, p->t, a); + gf_mul(p->y, p->t, d); + if (!before_double) + gf_mul(p->t, b, d); +} + +void curve448_point_double(curve448_point_t p, const curve448_point_t q) +{ + point_double_internal(p, q, 0); +} + +/* Operations on [p]niels */ +static ossl_inline void cond_neg_niels(niels_t n, mask_t neg) +{ + gf_cond_swap(n->a, n->b, neg); + gf_cond_neg(n->c, neg); +} + +static void pt_to_pniels(pniels_t b, const curve448_point_t a) +{ + gf_sub(b->n->a, a->y, a->x); + gf_add(b->n->b, a->x, a->y); + gf_mulw(b->n->c, a->t, 2 * TWISTED_D); + gf_add(b->z, a->z, a->z); +} + +static void pniels_to_pt(curve448_point_t e, const pniels_t d) +{ + gf eu; + + gf_add(eu, d->n->b, d->n->a); + gf_sub(e->y, d->n->b, d->n->a); + gf_mul(e->t, e->y, eu); + gf_mul(e->x, d->z, e->y); + gf_mul(e->y, d->z, eu); + gf_sqr(e->z, d->z); +} + +static void niels_to_pt(curve448_point_t e, const niels_t n) +{ + gf_add(e->y, n->b, n->a); + gf_sub(e->x, n->b, n->a); + gf_mul(e->t, e->y, e->x); + gf_copy(e->z, ONE); +} + +static void add_niels_to_pt(curve448_point_t d, const niels_t e, + int before_double) +{ + gf a, b, c; + + gf_sub_nr(b, d->y, d->x); /* 3+e */ + gf_mul(a, e->a, b); + gf_add_nr(b, d->x, d->y); /* 2+e */ + gf_mul(d->y, e->b, b); + gf_mul(d->x, e->c, d->t); + gf_add_nr(c, a, d->y); /* 2+e */ + gf_sub_nr(b, d->y, a); /* 3+e */ + gf_sub_nr(d->y, d->z, d->x); /* 3+e */ + gf_add_nr(a, d->x, d->z); /* 2+e */ + gf_mul(d->z, a, d->y); + gf_mul(d->x, d->y, b); + gf_mul(d->y, a, c); + if (!before_double) + gf_mul(d->t, b, c); +} + +static void sub_niels_from_pt(curve448_point_t d, const niels_t e, + int before_double) +{ + gf a, b, c; + + gf_sub_nr(b, d->y, d->x); /* 3+e */ + gf_mul(a, e->b, b); + gf_add_nr(b, d->x, d->y); /* 2+e */ + gf_mul(d->y, e->a, b); + gf_mul(d->x, e->c, d->t); + gf_add_nr(c, a, d->y); /* 2+e */ + gf_sub_nr(b, d->y, a); /* 3+e */ + gf_add_nr(d->y, d->z, d->x); /* 2+e */ + gf_sub_nr(a, d->z, d->x); /* 3+e */ + gf_mul(d->z, a, d->y); + gf_mul(d->x, d->y, b); + gf_mul(d->y, a, c); + if (!before_double) + gf_mul(d->t, b, c); +} + +static void add_pniels_to_pt(curve448_point_t p, const pniels_t pn, + int before_double) +{ + gf L0; + + gf_mul(L0, p->z, pn->z); + gf_copy(p->z, L0); + add_niels_to_pt(p, pn->n, before_double); +} + +static void sub_pniels_from_pt(curve448_point_t p, const pniels_t pn, + int before_double) +{ + gf L0; + + gf_mul(L0, p->z, pn->z); + gf_copy(p->z, L0); + sub_niels_from_pt(p, pn->n, before_double); +} + +c448_bool_t curve448_point_eq(const curve448_point_t p, + const curve448_point_t q) +{ + mask_t succ; + gf a, b; + + /* equality mod 2-torsion compares x/y */ + gf_mul(a, p->y, q->x); + gf_mul(b, q->y, p->x); + succ = gf_eq(a, b); + + return mask_to_bool(succ); +} + +c448_bool_t curve448_point_valid(const curve448_point_t p) +{ + mask_t out; + gf a, b, c; + + gf_mul(a, p->x, p->y); + gf_mul(b, p->z, p->t); + out = gf_eq(a, b); + gf_sqr(a, p->x); + gf_sqr(b, p->y); + gf_sub(a, b, a); + gf_sqr(b, p->t); + gf_mulw(c, b, TWISTED_D); + gf_sqr(b, p->z); + gf_add(b, b, c); + out &= gf_eq(a, b); + out &= ~gf_eq(p->z, ZERO); + return mask_to_bool(out); +} + +static ossl_inline void constant_time_lookup_niels(niels_s * RESTRICT ni, + const niels_t * table, + int nelts, int idx) +{ + constant_time_lookup(ni, table, sizeof(niels_s), nelts, idx); +} + +void curve448_precomputed_scalarmul(curve448_point_t out, + const curve448_precomputed_s * table, + const curve448_scalar_t scalar) +{ + unsigned int i, j, k; + const unsigned int n = COMBS_N, t = COMBS_T, s = COMBS_S; + niels_t ni; + curve448_scalar_t scalar1x; + + curve448_scalar_add(scalar1x, scalar, precomputed_scalarmul_adjustment); + curve448_scalar_halve(scalar1x, scalar1x); + + for (i = s; i > 0; i--) { + if (i != s) + point_double_internal(out, out, 0); + + for (j = 0; j < n; j++) { + int tab = 0; + mask_t invert; + + for (k = 0; k < t; k++) { + unsigned int bit = (i - 1) + s * (k + j * t); + + if (bit < C448_SCALAR_BITS) + tab |= + (scalar1x->limb[bit / WBITS] >> (bit % WBITS) & 1) << k; + } + + invert = (tab >> (t - 1)) - 1; + tab ^= invert; + tab &= (1 << (t - 1)) - 1; + + constant_time_lookup_niels(ni, &table->table[j << (t - 1)], + 1 << (t - 1), tab); + + cond_neg_niels(ni, invert); + if ((i != s) || j != 0) + add_niels_to_pt(out, ni, j == n - 1 && i != 1); + else + niels_to_pt(out, ni); + } + } + + OPENSSL_cleanse(ni, sizeof(ni)); + OPENSSL_cleanse(scalar1x, sizeof(scalar1x)); +} + +void curve448_point_mul_by_ratio_and_encode_like_eddsa( + uint8_t enc[EDDSA_448_PUBLIC_BYTES], + const curve448_point_t p) +{ + gf x, y, z, t; + curve448_point_t q; + + /* The point is now on the twisted curve. Move it to untwisted. */ + curve448_point_copy(q, p); + + { + /* 4-isogeny: 2xy/(y^+x^2), (y^2-x^2)/(2z^2-y^2+x^2) */ + gf u; + + gf_sqr(x, q->x); + gf_sqr(t, q->y); + gf_add(u, x, t); + gf_add(z, q->y, q->x); + gf_sqr(y, z); + gf_sub(y, y, u); + gf_sub(z, t, x); + gf_sqr(x, q->z); + gf_add(t, x, x); + gf_sub(t, t, z); + gf_mul(x, t, y); + gf_mul(y, z, u); + gf_mul(z, u, t); + OPENSSL_cleanse(u, sizeof(u)); + } + + /* Affinize */ + gf_invert(z, z, 1); + gf_mul(t, x, z); + gf_mul(x, y, z); + + /* Encode */ + enc[EDDSA_448_PRIVATE_BYTES - 1] = 0; + gf_serialize(enc, x, 1); + enc[EDDSA_448_PRIVATE_BYTES - 1] |= 0x80 & gf_lobit(t); + + OPENSSL_cleanse(x, sizeof(x)); + OPENSSL_cleanse(y, sizeof(y)); + OPENSSL_cleanse(z, sizeof(z)); + OPENSSL_cleanse(t, sizeof(t)); + curve448_point_destroy(q); +} + +c448_error_t curve448_point_decode_like_eddsa_and_mul_by_ratio( + curve448_point_t p, + const uint8_t enc[EDDSA_448_PUBLIC_BYTES]) +{ + uint8_t enc2[EDDSA_448_PUBLIC_BYTES]; + mask_t low; + mask_t succ; + + memcpy(enc2, enc, sizeof(enc2)); + + low = ~word_is_zero(enc2[EDDSA_448_PRIVATE_BYTES - 1] & 0x80); + enc2[EDDSA_448_PRIVATE_BYTES - 1] &= ~0x80; + + succ = gf_deserialize(p->y, enc2, 1, 0); + succ &= word_is_zero(enc2[EDDSA_448_PRIVATE_BYTES - 1]); + + gf_sqr(p->x, p->y); + gf_sub(p->z, ONE, p->x); /* num = 1-y^2 */ + gf_mulw(p->t, p->x, EDWARDS_D); /* dy^2 */ + gf_sub(p->t, ONE, p->t); /* denom = 1-dy^2 or 1-d + dy^2 */ + + gf_mul(p->x, p->z, p->t); + succ &= gf_isr(p->t, p->x); /* 1/sqrt(num * denom) */ + + gf_mul(p->x, p->t, p->z); /* sqrt(num / denom) */ + gf_cond_neg(p->x, gf_lobit(p->x) ^ low); + gf_copy(p->z, ONE); + + { + gf a, b, c, d; + + /* 4-isogeny 2xy/(y^2-ax^2), (y^2+ax^2)/(2-y^2-ax^2) */ + gf_sqr(c, p->x); + gf_sqr(a, p->y); + gf_add(d, c, a); + gf_add(p->t, p->y, p->x); + gf_sqr(b, p->t); + gf_sub(b, b, d); + gf_sub(p->t, a, c); + gf_sqr(p->x, p->z); + gf_add(p->z, p->x, p->x); + gf_sub(a, p->z, d); + gf_mul(p->x, a, b); + gf_mul(p->z, p->t, a); + gf_mul(p->y, p->t, d); + gf_mul(p->t, b, d); + OPENSSL_cleanse(a, sizeof(a)); + OPENSSL_cleanse(b, sizeof(b)); + OPENSSL_cleanse(c, sizeof(c)); + OPENSSL_cleanse(d, sizeof(d)); + } + + OPENSSL_cleanse(enc2, sizeof(enc2)); + assert(curve448_point_valid(p) || ~succ); + + return c448_succeed_if(mask_to_bool(succ)); +} + +c448_error_t x448_int(uint8_t out[X_PUBLIC_BYTES], + const uint8_t base[X_PUBLIC_BYTES], + const uint8_t scalar[X_PRIVATE_BYTES]) +{ + gf x1, x2, z2, x3, z3, t1, t2; + int t; + mask_t swap = 0; + mask_t nz; + + (void)gf_deserialize(x1, base, 1, 0); + gf_copy(x2, ONE); + gf_copy(z2, ZERO); + gf_copy(x3, x1); + gf_copy(z3, ONE); + + for (t = X_PRIVATE_BITS - 1; t >= 0; t--) { + uint8_t sb = scalar[t / 8]; + mask_t k_t; + + /* Scalar conditioning */ + if (t / 8 == 0) + sb &= -(uint8_t)COFACTOR; + else if (t == X_PRIVATE_BITS - 1) + sb = -1; + + k_t = (sb >> (t % 8)) & 1; + k_t = 0 - k_t; /* set to all 0s or all 1s */ + + swap ^= k_t; + gf_cond_swap(x2, x3, swap); + gf_cond_swap(z2, z3, swap); + swap = k_t; + + /* + * The "_nr" below skips coefficient reduction. In the following + * comments, "2+e" is saying that the coefficients are at most 2+epsilon + * times the reduction limit. + */ + gf_add_nr(t1, x2, z2); /* A = x2 + z2 */ /* 2+e */ + gf_sub_nr(t2, x2, z2); /* B = x2 - z2 */ /* 3+e */ + gf_sub_nr(z2, x3, z3); /* D = x3 - z3 */ /* 3+e */ + gf_mul(x2, t1, z2); /* DA */ + gf_add_nr(z2, z3, x3); /* C = x3 + z3 */ /* 2+e */ + gf_mul(x3, t2, z2); /* CB */ + gf_sub_nr(z3, x2, x3); /* DA-CB */ /* 3+e */ + gf_sqr(z2, z3); /* (DA-CB)^2 */ + gf_mul(z3, x1, z2); /* z3 = x1(DA-CB)^2 */ + gf_add_nr(z2, x2, x3); /* (DA+CB) */ /* 2+e */ + gf_sqr(x3, z2); /* x3 = (DA+CB)^2 */ + + gf_sqr(z2, t1); /* AA = A^2 */ + gf_sqr(t1, t2); /* BB = B^2 */ + gf_mul(x2, z2, t1); /* x2 = AA*BB */ + gf_sub_nr(t2, z2, t1); /* E = AA-BB */ /* 3+e */ + + gf_mulw(t1, t2, -EDWARDS_D); /* E*-d = a24*E */ + gf_add_nr(t1, t1, z2); /* AA + a24*E */ /* 2+e */ + gf_mul(z2, t2, t1); /* z2 = E(AA+a24*E) */ + } + + /* Finish */ + gf_cond_swap(x2, x3, swap); + gf_cond_swap(z2, z3, swap); + gf_invert(z2, z2, 0); + gf_mul(x1, x2, z2); + gf_serialize(out, x1, 1); + nz = ~gf_eq(x1, ZERO); + + OPENSSL_cleanse(x1, sizeof(x1)); + OPENSSL_cleanse(x2, sizeof(x2)); + OPENSSL_cleanse(z2, sizeof(z2)); + OPENSSL_cleanse(x3, sizeof(x3)); + OPENSSL_cleanse(z3, sizeof(z3)); + OPENSSL_cleanse(t1, sizeof(t1)); + OPENSSL_cleanse(t2, sizeof(t2)); + + return c448_succeed_if(mask_to_bool(nz)); +} + +void curve448_point_mul_by_ratio_and_encode_like_x448(uint8_t + out[X_PUBLIC_BYTES], + const curve448_point_t p) +{ + curve448_point_t q; + + curve448_point_copy(q, p); + gf_invert(q->t, q->x, 0); /* 1/x */ + gf_mul(q->z, q->t, q->y); /* y/x */ + gf_sqr(q->y, q->z); /* (y/x)^2 */ + gf_serialize(out, q->y, 1); + curve448_point_destroy(q); +} + +void x448_derive_public_key(uint8_t out[X_PUBLIC_BYTES], + const uint8_t scalar[X_PRIVATE_BYTES]) +{ + /* Scalar conditioning */ + uint8_t scalar2[X_PRIVATE_BYTES]; + curve448_scalar_t the_scalar; + curve448_point_t p; + unsigned int i; + + memcpy(scalar2, scalar, sizeof(scalar2)); + scalar2[0] &= -(uint8_t)COFACTOR; + + scalar2[X_PRIVATE_BYTES - 1] &= ~((0u - 1u) << ((X_PRIVATE_BITS + 7) % 8)); + scalar2[X_PRIVATE_BYTES - 1] |= 1 << ((X_PRIVATE_BITS + 7) % 8); + + curve448_scalar_decode_long(the_scalar, scalar2, sizeof(scalar2)); + + /* Compensate for the encoding ratio */ + for (i = 1; i < X448_ENCODE_RATIO; i <<= 1) + curve448_scalar_halve(the_scalar, the_scalar); + + curve448_precomputed_scalarmul(p, curve448_precomputed_base, the_scalar); + curve448_point_mul_by_ratio_and_encode_like_x448(out, p); + curve448_point_destroy(p); +} + +/* Control for variable-time scalar multiply algorithms. */ +struct smvt_control { + int power, addend; +}; + +#if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3)) +# define NUMTRAILINGZEROS __builtin_ctz +#else +# define NUMTRAILINGZEROS numtrailingzeros +static uint32_t numtrailingzeros(uint32_t i) +{ + uint32_t tmp; + uint32_t num = 31; + + if (i == 0) + return 32; + + tmp = i << 16; + if (tmp != 0) { + i = tmp; + num -= 16; + } + tmp = i << 8; + if (tmp != 0) { + i = tmp; + num -= 8; + } + tmp = i << 4; + if (tmp != 0) { + i = tmp; + num -= 4; + } + tmp = i << 2; + if (tmp != 0) { + i = tmp; + num -= 2; + } + tmp = i << 1; + if (tmp != 0) + num--; + + return num; +} +#endif + +static int recode_wnaf(struct smvt_control *control, + /* [nbits/(table_bits + 1) + 3] */ + const curve448_scalar_t scalar, + unsigned int table_bits) +{ + unsigned int table_size = C448_SCALAR_BITS / (table_bits + 1) + 3; + int position = table_size - 1; /* at the end */ + uint64_t current = scalar->limb[0] & 0xFFFF; + uint32_t mask = (1 << (table_bits + 1)) - 1; + unsigned int w; + const unsigned int B_OVER_16 = sizeof(scalar->limb[0]) / 2; + unsigned int n, i; + + /* place the end marker */ + control[position].power = -1; + control[position].addend = 0; + position--; + + /* + * PERF: Could negate scalar if it's large. But then would need more cases + * in the actual code that uses it, all for an expected reduction of like + * 1/5 op. Probably not worth it. + */ + + for (w = 1; w < (C448_SCALAR_BITS - 1) / 16 + 3; w++) { + if (w < (C448_SCALAR_BITS - 1) / 16 + 1) { + /* Refill the 16 high bits of current */ + current += (uint32_t)((scalar->limb[w / B_OVER_16] + >> (16 * (w % B_OVER_16))) << 16); + } + + while (current & 0xFFFF) { + uint32_t pos = NUMTRAILINGZEROS((uint32_t)current); + uint32_t odd = (uint32_t)current >> pos; + int32_t delta = odd & mask; + + assert(position >= 0); + if (odd & (1 << (table_bits + 1))) + delta -= (1 << (table_bits + 1)); + current -= delta * (1 << pos); + control[position].power = pos + 16 * (w - 1); + control[position].addend = delta; + position--; + } + current >>= 16; + } + assert(current == 0); + + position++; + n = table_size - position; + for (i = 0; i < n; i++) + control[i] = control[i + position]; + + return n - 1; +} + +static void prepare_wnaf_table(pniels_t * output, + const curve448_point_t working, + unsigned int tbits) +{ + curve448_point_t tmp; + int i; + pniels_t twop; + + pt_to_pniels(output[0], working); + + if (tbits == 0) + return; + + curve448_point_double(tmp, working); + pt_to_pniels(twop, tmp); + + add_pniels_to_pt(tmp, output[0], 0); + pt_to_pniels(output[1], tmp); + + for (i = 2; i < 1 << tbits; i++) { + add_pniels_to_pt(tmp, twop, 0); + pt_to_pniels(output[i], tmp); + } + + curve448_point_destroy(tmp); + OPENSSL_cleanse(twop, sizeof(twop)); +} + +void curve448_base_double_scalarmul_non_secret(curve448_point_t combo, + const curve448_scalar_t scalar1, + const curve448_point_t base2, + const curve448_scalar_t scalar2) +{ + const int table_bits_var = C448_WNAF_VAR_TABLE_BITS; + const int table_bits_pre = C448_WNAF_FIXED_TABLE_BITS; + struct smvt_control control_var[C448_SCALAR_BITS / + (C448_WNAF_VAR_TABLE_BITS + 1) + 3]; + struct smvt_control control_pre[C448_SCALAR_BITS / + (C448_WNAF_FIXED_TABLE_BITS + 1) + 3]; + int ncb_pre = recode_wnaf(control_pre, scalar1, table_bits_pre); + int ncb_var = recode_wnaf(control_var, scalar2, table_bits_var); + pniels_t precmp_var[1 << C448_WNAF_VAR_TABLE_BITS]; + int contp = 0, contv = 0, i; + + prepare_wnaf_table(precmp_var, base2, table_bits_var); + i = control_var[0].power; + + if (i < 0) { + curve448_point_copy(combo, curve448_point_identity); + return; + } + if (i > control_pre[0].power) { + pniels_to_pt(combo, precmp_var[control_var[0].addend >> 1]); + contv++; + } else if (i == control_pre[0].power && i >= 0) { + pniels_to_pt(combo, precmp_var[control_var[0].addend >> 1]); + add_niels_to_pt(combo, curve448_wnaf_base[control_pre[0].addend >> 1], + i); + contv++; + contp++; + } else { + i = control_pre[0].power; + niels_to_pt(combo, curve448_wnaf_base[control_pre[0].addend >> 1]); + contp++; + } + + for (i--; i >= 0; i--) { + int cv = (i == control_var[contv].power); + int cp = (i == control_pre[contp].power); + + point_double_internal(combo, combo, i && !(cv || cp)); + + if (cv) { + assert(control_var[contv].addend); + + if (control_var[contv].addend > 0) + add_pniels_to_pt(combo, + precmp_var[control_var[contv].addend >> 1], + i && !cp); + else + sub_pniels_from_pt(combo, + precmp_var[(-control_var[contv].addend) + >> 1], i && !cp); + contv++; + } + + if (cp) { + assert(control_pre[contp].addend); + + if (control_pre[contp].addend > 0) + add_niels_to_pt(combo, + curve448_wnaf_base[control_pre[contp].addend + >> 1], i); + else + sub_niels_from_pt(combo, + curve448_wnaf_base[(-control_pre + [contp].addend) >> 1], i); + contp++; + } + } + + /* This function is non-secret, but whatever this is cheap. */ + OPENSSL_cleanse(control_var, sizeof(control_var)); + OPENSSL_cleanse(control_pre, sizeof(control_pre)); + OPENSSL_cleanse(precmp_var, sizeof(precmp_var)); + + assert(contv == ncb_var); + (void)ncb_var; + assert(contp == ncb_pre); + (void)ncb_pre; +} + +void curve448_point_destroy(curve448_point_t point) +{ + OPENSSL_cleanse(point, sizeof(curve448_point_t)); +} + +int X448(uint8_t out_shared_key[56], const uint8_t private_key[56], + const uint8_t peer_public_value[56]) +{ + return x448_int(out_shared_key, peer_public_value, private_key) + == C448_SUCCESS; +} + +void X448_public_from_private(uint8_t out_public_value[56], + const uint8_t private_key[56]) +{ + x448_derive_public_key(out_public_value, private_key); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/curve448_lcl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/curve448_lcl.h new file mode 100644 index 000000000..2bc3bd84c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/curve448_lcl.h @@ -0,0 +1,38 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ +#ifndef HEADER_CURVE448_LCL_H +# define HEADER_CURVE448_LCL_H +# include "curve448utils.h" + +int X448(uint8_t out_shared_key[56], const uint8_t private_key[56], + const uint8_t peer_public_value[56]); + +void X448_public_from_private(uint8_t out_public_value[56], + const uint8_t private_key[56]); + +int ED448_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len, + const uint8_t public_key[57], const uint8_t private_key[57], + const uint8_t *context, size_t context_len); + +int ED448_verify(const uint8_t *message, size_t message_len, + const uint8_t signature[114], const uint8_t public_key[57], + const uint8_t *context, size_t context_len); + +int ED448ph_sign(uint8_t *out_sig, const uint8_t hash[64], + const uint8_t public_key[57], const uint8_t private_key[57], + const uint8_t *context, size_t context_len); + +int ED448ph_verify(const uint8_t hash[64], const uint8_t signature[114], + const uint8_t public_key[57], const uint8_t *context, + size_t context_len); + +int ED448_public_from_private(uint8_t out_public_key[57], + const uint8_t private_key[57]); + +#endif /* HEADER_CURVE448_LCL_H */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/curve448_tables.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/curve448_tables.c new file mode 100644 index 000000000..a1185b1ee --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/curve448_tables.c @@ -0,0 +1,475 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2016 Cryptography Research, Inc. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + * + * Originally written by Mike Hamburg + */ +#include "field.h" + +#include "point_448.h" + +static const curve448_precomputed_s curve448_precomputed_base_table = { + { + {{ + {FIELD_LITERAL(0x00cc3b062366f4cc,0x003d6e34e314aa3c,0x00d51c0a7521774d,0x0094e060eec6ab8b,0x00d21291b4d80082,0x00befed12b55ef1e,0x00c3dd2df5c94518,0x00e0a7b112b8d4e6)}, + {FIELD_LITERAL(0x0019eb5608d8723a,0x00d1bab52fb3aedb,0x00270a7311ebc90c,0x0037c12b91be7f13,0x005be16cd8b5c704,0x003e181acda888e1,0x00bc1f00fc3fc6d0,0x00d3839bfa319e20)}, + {FIELD_LITERAL(0x003caeb88611909f,0x00ea8b378c4df3d4,0x00b3295b95a5a19a,0x00a65f97514bdfb5,0x00b39efba743cab1,0x0016ba98b862fd2d,0x0001508812ee71d7,0x000a75740eea114a)}, + }}, {{ + {FIELD_LITERAL(0x00ebcf0eb649f823,0x00166d332e98ea03,0x0059ddf64f5cd5f6,0x0047763123d9471b,0x00a64065c53ef62f,0x00978e44c480153d,0x000b5b2a0265f194,0x0046a24b9f32965a)}, + {FIELD_LITERAL(0x00b9eef787034df0,0x0020bc24de3390cd,0x000022160bae99bb,0x00ae66e886e97946,0x0048d4bbe02cbb8b,0x0072ba97b34e38d4,0x00eae7ec8f03e85a,0x005ba92ecf808b2c)}, + {FIELD_LITERAL(0x00c9cfbbe74258fd,0x00843a979ea9eaa7,0x000cbb4371cfbe90,0x0059bac8f7f0a628,0x004b3dff882ff530,0x0011869df4d90733,0x00595aa71f4abfc2,0x0070e2d38990c2e6)}, + }}, {{ + {FIELD_LITERAL(0x00de2010c0a01733,0x00c739a612e24297,0x00a7212643141d7c,0x00f88444f6b67c11,0x00484b7b16ec28f2,0x009c1b8856af9c68,0x00ff4669591fe9d6,0x0054974be08a32c8)}, + {FIELD_LITERAL(0x0010de3fd682ceed,0x008c07642d83ca4e,0x0013bb064e00a1cc,0x009411ae27870e11,0x00ea8e5b4d531223,0x0032fe7d2aaece2e,0x00d989e243e7bb41,0x000fe79a508e9b8b)}, + {FIELD_LITERAL(0x005e0426b9bfc5b1,0x0041a5b1d29ee4fa,0x0015b0def7774391,0x00bc164f1f51af01,0x00d543b0942797b9,0x003c129b6398099c,0x002b114c6e5adf18,0x00b4e630e4018a7b)}, + }}, {{ + {FIELD_LITERAL(0x00d490afc95f8420,0x00b096bf50c1d9b9,0x00799fd707679866,0x007c74d9334afbea,0x00efaa8be80ff4ed,0x0075c4943bb81694,0x00c21c2fca161f36,0x00e77035d492bfee)}, + {FIELD_LITERAL(0x006658a190dd6661,0x00e0e9bab38609a6,0x0028895c802237ed,0x006a0229c494f587,0x002dcde96c9916b7,0x00d158822de16218,0x00173b917a06856f,0x00ca78a79ae07326)}, + {FIELD_LITERAL(0x00e35bfc79caced4,0x0087238a3e1fe3bb,0x00bcbf0ff4ceff5b,0x00a19c1c94099b91,0x0071e102b49db976,0x0059e3d004eada1e,0x008da78afa58a47e,0x00579c8ebf269187)}, + }}, {{ + {FIELD_LITERAL(0x00a16c2905eee75f,0x009d4bcaea2c7e1d,0x00d3bd79bfad19df,0x0050da745193342c,0x006abdb8f6b29ab1,0x00a24fe0a4fef7ef,0x0063730da1057dfb,0x00a08c312c8eb108)}, + {FIELD_LITERAL(0x00b583be005375be,0x00a40c8f8a4e3df4,0x003fac4a8f5bdbf7,0x00d4481d872cd718,0x004dc8749cdbaefe,0x00cce740d5e5c975,0x000b1c1f4241fd21,0x00a76de1b4e1cd07)}, + {FIELD_LITERAL(0x007a076500d30b62,0x000a6e117b7f090f,0x00c8712ae7eebd9a,0x000fbd6c1d5f6ff7,0x003a7977246ebf11,0x00166ed969c6600e,0x00aa42e469c98bec,0x00dc58f307cf0666)}, + }}, {{ + {FIELD_LITERAL(0x004b491f65a9a28b,0x006a10309e8a55b7,0x00b67210185187ef,0x00cf6497b12d9b8f,0x0085778c56e2b1ba,0x0015b4c07a814d85,0x00686479e62da561,0x008de5d88f114916)}, + {FIELD_LITERAL(0x00e37c88d6bba7b1,0x003e4577e1b8d433,0x0050d8ea5f510ec0,0x0042fc9f2da9ef59,0x003bd074c1141420,0x00561b8b7b68774e,0x00232e5e5d1013a3,0x006b7f2cb3d7e73f)}, + {FIELD_LITERAL(0x004bdd0f0b41e6a0,0x001773057c405d24,0x006029f99915bd97,0x006a5ba70a17fe2f,0x0046111977df7e08,0x004d8124c89fb6b7,0x00580983b2bb2724,0x00207bf330d6f3fe)}, + }}, {{ + {FIELD_LITERAL(0x007efdc93972a48b,0x002f5e50e78d5fee,0x0080dc11d61c7fe5,0x0065aa598707245b,0x009abba2300641be,0x000c68787656543a,0x00ffe0fef2dc0a17,0x00007ffbd6cb4f3a)}, + {FIELD_LITERAL(0x0036012f2b836efc,0x00458c126d6b5fbc,0x00a34436d719ad1e,0x0097be6167117dea,0x0009c219c879cff3,0x0065564493e60755,0x00993ac94a8cdec0,0x002d4885a4d0dbaf)}, + {FIELD_LITERAL(0x00598b60b4c068ba,0x00c547a0be7f1afd,0x009582164acf12af,0x00af4acac4fbbe40,0x005f6ca7c539121a,0x003b6e752ebf9d66,0x00f08a30d5cac5d4,0x00e399bb5f97c5a9)}, + }}, {{ + {FIELD_LITERAL(0x007445a0409c0a66,0x00a65c369f3829c0,0x0031d248a4f74826,0x006817f34defbe8e,0x00649741d95ebf2e,0x00d46466ab16b397,0x00fdc35703bee414,0x00343b43334525f8)}, + {FIELD_LITERAL(0x001796bea93f6401,0x00090c5a42e85269,0x00672412ba1252ed,0x001201d47b6de7de,0x006877bccfe66497,0x00b554fd97a4c161,0x009753f42dbac3cf,0x00e983e3e378270a)}, + {FIELD_LITERAL(0x00ac3eff18849872,0x00f0eea3bff05690,0x00a6d72c21dd505d,0x001b832642424169,0x00a6813017b540e5,0x00a744bd71b385cd,0x0022a7d089130a7b,0x004edeec9a133486)}, + }}, {{ + {FIELD_LITERAL(0x00b2d6729196e8a9,0x0088a9bb2031cef4,0x00579e7787dc1567,0x0030f49feb059190,0x00a0b1d69c7f7d8f,0x0040bdcc6d9d806f,0x00d76c4037edd095,0x00bbf24376415dd7)}, + {FIELD_LITERAL(0x00240465ff5a7197,0x00bb97e76caf27d0,0x004b4edbf8116d39,0x001d8586f708cbaa,0x000f8ee8ff8e4a50,0x00dde5a1945dd622,0x00e6fc1c0957e07c,0x0041c9cdabfd88a0)}, + {FIELD_LITERAL(0x005344b0bf5b548c,0x002957d0b705cc99,0x00f586a70390553d,0x0075b3229f583cc3,0x00a1aa78227490e4,0x001bf09cf7957717,0x00cf6bf344325f52,0x0065bd1c23ca3ecf)}, + }}, {{ + {FIELD_LITERAL(0x009bff3b3239363c,0x00e17368796ef7c0,0x00528b0fe0971f3a,0x0008014fc8d4a095,0x00d09f2e8a521ec4,0x006713ab5dde5987,0x0003015758e0dbb1,0x00215999f1ba212d)}, + {FIELD_LITERAL(0x002c88e93527da0e,0x0077c78f3456aad5,0x0071087a0a389d1c,0x00934dac1fb96dbd,0x008470e801162697,0x005bc2196cd4ad49,0x00e535601d5087c3,0x00769888700f497f)}, + {FIELD_LITERAL(0x00da7a4b557298ad,0x0019d2589ea5df76,0x00ef3e38be0c6497,0x00a9644e1312609a,0x004592f61b2558da,0x0082c1df510d7e46,0x0042809a535c0023,0x00215bcb5afd7757)}, + }}, {{ + {FIELD_LITERAL(0x002b9df55a1a4213,0x00dcfc3b464a26be,0x00c4f9e07a8144d5,0x00c8e0617a92b602,0x008e3c93accafae0,0x00bf1bcb95b2ca60,0x004ce2426a613bf3,0x00266cac58e40921)}, + {FIELD_LITERAL(0x008456d5db76e8f0,0x0032ca9cab2ce163,0x0059f2b8bf91abcf,0x0063c2a021712788,0x00f86155af22f72d,0x00db98b2a6c005a0,0x00ac6e416a693ac4,0x007a93572af53226)}, + {FIELD_LITERAL(0x0087767520f0de22,0x0091f64012279fb5,0x001050f1f0644999,0x004f097a2477ad3c,0x006b37913a9947bd,0x001a3d78645af241,0x0057832bbb3008a7,0x002c1d902b80dc20)}, + }}, {{ + {FIELD_LITERAL(0x001a6002bf178877,0x009bce168aa5af50,0x005fc318ff04a7f5,0x0052818f55c36461,0x008768f5d4b24afb,0x0037ffbae7b69c85,0x0018195a4b61edc0,0x001e12ea088434b2)}, + {FIELD_LITERAL(0x0047d3f804e7ab07,0x00a809ab5f905260,0x00b3ffc7cdaf306d,0x00746e8ec2d6e509,0x00d0dade8887a645,0x00acceeebde0dd37,0x009bc2579054686b,0x0023804f97f1c2bf)}, + {FIELD_LITERAL(0x0043e2e2e50b80d7,0x00143aafe4427e0f,0x005594aaecab855b,0x008b12ccaaecbc01,0x002deeb091082bc3,0x009cca4be2ae7514,0x00142b96e696d047,0x00ad2a2b1c05256a)}, + }}, {{ + {FIELD_LITERAL(0x003914f2f144b78b,0x007a95dd8bee6f68,0x00c7f4384d61c8e6,0x004e51eb60f1bdb2,0x00f64be7aa4621d8,0x006797bfec2f0ac0,0x007d17aab3c75900,0x001893e73cac8bc5)}, + {FIELD_LITERAL(0x00140360b768665b,0x00b68aca4967f977,0x0001089b66195ae4,0x00fe71122185e725,0x000bca2618d49637,0x00a54f0557d7e98a,0x00cdcd2f91d6f417,0x00ab8c13741fd793)}, + {FIELD_LITERAL(0x00725ee6b1e549e0,0x007124a0769777fa,0x000b68fdad07ae42,0x0085b909cd4952df,0x0092d2e3c81606f4,0x009f22f6cac099a0,0x00f59da57f2799a8,0x00f06c090122f777)}, + }}, {{ + {FIELD_LITERAL(0x00ce0bed0a3532bc,0x001a5048a22df16b,0x00e31db4cbad8bf1,0x00e89292120cf00e,0x007d1dd1a9b00034,0x00e2a9041ff8f680,0x006a4c837ae596e7,0x00713af1068070b3)}, + {FIELD_LITERAL(0x00c4fe64ce66d04b,0x00b095d52e09b3d7,0x00758bbecb1a3a8e,0x00f35cce8d0650c0,0x002b878aa5984473,0x0062e0a3b7544ddc,0x00b25b290ed116fe,0x007b0f6abe0bebf2)}, + {FIELD_LITERAL(0x0081d4e3addae0a8,0x003410c836c7ffcc,0x00c8129ad89e4314,0x000e3d5a23922dcd,0x00d91e46f29c31f3,0x006c728cde8c5947,0x002bc655ba2566c0,0x002ca94721533108)}, + }}, {{ + {FIELD_LITERAL(0x0051e4b3f764d8a9,0x0019792d46e904a0,0x00853bc13dbc8227,0x000840208179f12d,0x0068243474879235,0x0013856fbfe374d0,0x00bda12fe8676424,0x00bbb43635926eb2)}, + {FIELD_LITERAL(0x0012cdc880a93982,0x003c495b21cd1b58,0x00b7e5c93f22a26e,0x0044aa82dfb99458,0x009ba092cdffe9c0,0x00a14b3ab2083b73,0x000271c2f70e1c4b,0x00eea9cac0f66eb8)}, + {FIELD_LITERAL(0x001a1847c4ac5480,0x00b1b412935bb03a,0x00f74285983bf2b2,0x00624138b5b5d0f1,0x008820c0b03d38bf,0x00b94e50a18c1572,0x0060f6934841798f,0x00c52f5d66d6ebe2)}, + }}, {{ + {FIELD_LITERAL(0x00da23d59f9bcea6,0x00e0f27007a06a4b,0x00128b5b43a6758c,0x000cf50190fa8b56,0x00fc877aba2b2d72,0x00623bef52edf53f,0x00e6af6b819669e2,0x00e314dc34fcaa4f)}, + {FIELD_LITERAL(0x0066e5eddd164d1e,0x00418a7c6fe28238,0x0002e2f37e962c25,0x00f01f56b5975306,0x0048842fa503875c,0x0057b0e968078143,0x00ff683024f3d134,0x0082ae28fcad12e4)}, + {FIELD_LITERAL(0x0011ddfd21260e42,0x00d05b0319a76892,0x00183ea4368e9b8f,0x00b0815662affc96,0x00b466a5e7ce7c88,0x00db93b07506e6ee,0x0033885f82f62401,0x0086f9090ec9b419)}, + }}, {{ + {FIELD_LITERAL(0x00d95d1c5fcb435a,0x0016d1ed6b5086f9,0x00792aa0b7e54d71,0x0067b65715f1925d,0x00a219755ec6176b,0x00bc3f026b12c28f,0x00700c897ffeb93e,0x0089b83f6ec50b46)}, + {FIELD_LITERAL(0x003c97e6384da36e,0x00423d53eac81a09,0x00b70d68f3cdce35,0x00ee7959b354b92c,0x00f4e9718819c8ca,0x009349f12acbffe9,0x005aee7b62cb7da6,0x00d97764154ffc86)}, + {FIELD_LITERAL(0x00526324babb46dc,0x002ee99b38d7bf9e,0x007ea51794706ef4,0x00abeb04da6e3c39,0x006b457c1d281060,0x00fe243e9a66c793,0x00378de0fb6c6ee4,0x003e4194b9c3cb93)}, + }}, {{ + {FIELD_LITERAL(0x00fed3cd80ca2292,0x0015b043a73ca613,0x000a9fd7bf9be227,0x003b5e03de2db983,0x005af72d46904ef7,0x00c0f1b5c49faa99,0x00dc86fc3bd305e1,0x00c92f08c1cb1797)}, + {FIELD_LITERAL(0x0079680ce111ed3b,0x001a1ed82806122c,0x000c2e7466d15df3,0x002c407f6f7150fd,0x00c5e7c96b1b0ce3,0x009aa44626863ff9,0x00887b8b5b80be42,0x00b6023cec964825)}, + {FIELD_LITERAL(0x00e4a8e1048970c8,0x0062887b7830a302,0x00bcf1c8cd81402b,0x0056dbb81a68f5be,0x0014eced83f12452,0x00139e1a510150df,0x00bb81140a82d1a3,0x000febcc1aaf1aa7)}, + }}, {{ + {FIELD_LITERAL(0x00a7527958238159,0x0013ec9537a84cd6,0x001d7fee7d562525,0x00b9eefa6191d5e5,0x00dbc97db70bcb8a,0x00481affc7a4d395,0x006f73d3e70c31bb,0x00183f324ed96a61)}, + {FIELD_LITERAL(0x0039dd7ce7fc6860,0x00d64f6425653da1,0x003e037c7f57d0af,0x0063477a06e2bcf2,0x001727dbb7ac67e6,0x0049589f5efafe2e,0x00fc0fef2e813d54,0x008baa5d087fb50d)}, + {FIELD_LITERAL(0x0024fb59d9b457c7,0x00a7d4e060223e4c,0x00c118d1b555fd80,0x0082e216c732f22a,0x00cd2a2993089504,0x003638e836a3e13d,0x000d855ee89b4729,0x008ec5b7d4810c91)}, + }}, {{ + {FIELD_LITERAL(0x001bf51f7d65cdfd,0x00d14cdafa16a97d,0x002c38e60fcd10e7,0x00a27446e393efbd,0x000b5d8946a71fdd,0x0063df2cde128f2f,0x006c8679569b1888,0x0059ffc4925d732d)}, + {FIELD_LITERAL(0x00ece96f95f2b66f,0x00ece7952813a27b,0x0026fc36592e489e,0x007157d1a2de0f66,0x00759dc111d86ddf,0x0012881e5780bb0f,0x00c8ccc83ad29496,0x0012b9bd1929eb71)}, + {FIELD_LITERAL(0x000fa15a20da5df0,0x00349ddb1a46cd31,0x002c512ad1d8e726,0x00047611f669318d,0x009e68fba591e17e,0x004320dffa803906,0x00a640874951a3d3,0x00b6353478baa24f)}, + }}, {{ + {FIELD_LITERAL(0x009696510000d333,0x00ec2f788bc04826,0x000e4d02b1f67ba5,0x00659aa8dace08b6,0x00d7a38a3a3ae533,0x008856defa8c746b,0x004d7a4402d3da1a,0x00ea82e06229260f)}, + {FIELD_LITERAL(0x006a15bb20f75c0c,0x0079a144027a5d0c,0x00d19116ce0b4d70,0x0059b83bcb0b268e,0x005f58f63f16c127,0x0079958318ee2c37,0x00defbb063d07f82,0x00f1f0b931d2d446)}, + {FIELD_LITERAL(0x00cb5e4c3c35d422,0x008df885ca43577f,0x00fa50b16ca3e471,0x005a0e58e17488c8,0x00b2ceccd6d34d19,0x00f01d5d235e36e9,0x00db2e7e4be6ca44,0x00260ab77f35fccd)}, + }}, {{ + {FIELD_LITERAL(0x006f6fd9baac61d5,0x002a7710a020a895,0x009de0db7fc03d4d,0x00cdedcb1875f40b,0x00050caf9b6b1e22,0x005e3a6654456ab0,0x00775fdf8c4423d4,0x0028701ea5738b5d)}, + {FIELD_LITERAL(0x009ffd90abfeae96,0x00cba3c2b624a516,0x005ef08bcee46c91,0x00e6fde30afb6185,0x00f0b4db4f818ce4,0x006c54f45d2127f5,0x00040125035854c7,0x00372658a3287e13)}, + {FIELD_LITERAL(0x00d7070fb1beb2ab,0x0078fc845a93896b,0x006894a4b2f224a6,0x005bdd8192b9dbde,0x00b38839874b3a9e,0x00f93618b04b7a57,0x003e3ec75fd2c67e,0x00bf5e6bfc29494a)}, + }}, {{ + {FIELD_LITERAL(0x00f19224ebba2aa5,0x0074f89d358e694d,0x00eea486597135ad,0x0081579a4555c7e1,0x0010b9b872930a9d,0x00f002e87a30ecc0,0x009b9d66b6de56e2,0x00a3c4f45e8004eb)}, + {FIELD_LITERAL(0x0045e8dda9400888,0x002ff12e5fc05db7,0x00a7098d54afe69c,0x00cdbe846a500585,0x00879c1593ca1882,0x003f7a7fea76c8b0,0x002cd73dd0c8e0a1,0x00645d6ce96f51fe)}, + {FIELD_LITERAL(0x002b7e83e123d6d6,0x00398346f7419c80,0x0042922e55940163,0x005e7fc5601886a3,0x00e88f2cee1d3103,0x00e7fab135f2e377,0x00b059984dbf0ded,0x0009ce080faa5bb8)}, + }}, {{ + {FIELD_LITERAL(0x0085e78af7758979,0x00275a4ee1631a3a,0x00d26bc0ed78b683,0x004f8355ea21064f,0x00d618e1a32696e5,0x008d8d7b150e5680,0x00a74cd854b278d2,0x001dd62702203ea0)}, + {FIELD_LITERAL(0x00f89335c2a59286,0x00a0f5c905d55141,0x00b41fb836ee9382,0x00e235d51730ca43,0x00a5cb37b5c0a69a,0x009b966ffe136c45,0x00cb2ea10bf80ed1,0x00fb2b370b40dc35)}, + {FIELD_LITERAL(0x00d687d16d4ee8ba,0x0071520bdd069dff,0x00de85c60d32355d,0x0087d2e3565102f4,0x00cde391b8dfc9aa,0x00e18d69efdfefe5,0x004a9d0591954e91,0x00fa36dd8b50eee5)}, + }}, {{ + {FIELD_LITERAL(0x002e788749a865f7,0x006e4dc3116861ea,0x009f1428c37276e6,0x00e7d2e0fc1e1226,0x003aeebc6b6c45f6,0x0071a8073bf500c9,0x004b22ad986b530c,0x00f439e63c0d79d4)}, + {FIELD_LITERAL(0x006bc3d53011f470,0x00032d6e692b83e8,0x00059722f497cd0b,0x0009b4e6f0c497cc,0x0058a804b7cce6c0,0x002b71d3302bbd5d,0x00e2f82a36765fce,0x008dded99524c703)}, + {FIELD_LITERAL(0x004d058953747d64,0x00701940fe79aa6f,0x00a620ac71c760bf,0x009532b611158b75,0x00547ed7f466f300,0x003cb5ab53a8401a,0x00c7763168ce3120,0x007e48e33e4b9ab2)}, + }}, {{ + {FIELD_LITERAL(0x001b2fc57bf3c738,0x006a3f918993fb80,0x0026f7a14fdec288,0x0075a2cdccef08db,0x00d3ecbc9eecdbf1,0x0048c40f06e5bf7f,0x00d63e423009896b,0x000598bc99c056a8)}, + {FIELD_LITERAL(0x002f194eaafa46dc,0x008e38f57fe87613,0x00dc8e5ae25f4ab2,0x000a17809575e6bd,0x00d3ec7923ba366a,0x003a7e72e0ad75e3,0x0010024b88436e0a,0x00ed3c5444b64051)}, + {FIELD_LITERAL(0x00831fc1340af342,0x00c9645669466d35,0x007692b4cc5a080f,0x009fd4a47ac9259f,0x001eeddf7d45928b,0x003c0446fc45f28b,0x002c0713aa3e2507,0x0095706935f0f41e)}, + }}, {{ + {FIELD_LITERAL(0x00766ae4190ec6d8,0x0065768cabc71380,0x00b902598416cdc2,0x00380021ad38df52,0x008f0b89d6551134,0x004254d4cc62c5a5,0x000d79f4484b9b94,0x00b516732ae3c50e)}, + {FIELD_LITERAL(0x001fb73475c45509,0x00d2b2e5ea43345a,0x00cb3c3842077bd1,0x0029f90ad820946e,0x007c11b2380778aa,0x009e54ece62c1704,0x004bc60c41ca01c3,0x004525679a5a0b03)}, + {FIELD_LITERAL(0x00c64fbddbed87b3,0x0040601d11731faa,0x009c22475b6f9d67,0x0024b79dae875f15,0x00616fed3f02c3b0,0x0000cf39f6af2d3b,0x00c46bac0aa9a688,0x00ab23e2800da204)}, + }}, {{ + {FIELD_LITERAL(0x000b3a37617632b0,0x00597199fe1cfb6c,0x0042a7ccdfeafdd6,0x004cc9f15ebcea17,0x00f436e596a6b4a4,0x00168861142df0d8,0x000753edfec26af5,0x000c495d7e388116)}, + {FIELD_LITERAL(0x0017085f4a346148,0x00c7cf7a37f62272,0x001776e129bc5c30,0x009955134c9eef2a,0x001ba5bdf1df07be,0x00ec39497103a55c,0x006578354fda6cfb,0x005f02719d4f15ee)}, + {FIELD_LITERAL(0x0052b9d9b5d9655d,0x00d4ec7ba1b461c3,0x00f95df4974f280b,0x003d8e5ca11aeb51,0x00d4981eb5a70b26,0x000af9a4f6659f29,0x004598c846faeb43,0x0049d9a183a47670)}, + }}, {{ + {FIELD_LITERAL(0x000a72d23dcb3f1f,0x00a3737f84011727,0x00f870c0fbbf4a47,0x00a7aadd04b5c9ca,0x000c7715c67bd072,0x00015a136afcd74e,0x0080d5caea499634,0x0026b448ec7514b7)}, + {FIELD_LITERAL(0x00b60167d9e7d065,0x00e60ba0d07381e8,0x003a4f17b725c2d4,0x006c19fe176b64fa,0x003b57b31af86ccb,0x0021047c286180fd,0x00bdc8fb00c6dbb6,0x00fe4a9f4bab4f3f)}, + {FIELD_LITERAL(0x0088ffc3a16111f7,0x009155e4245d0bc8,0x00851d68220572d5,0x00557ace1e514d29,0x0031d7c339d91022,0x00101d0ae2eaceea,0x00246ab3f837b66a,0x00d5216d381ff530)}, + }}, {{ + {FIELD_LITERAL(0x0057e7ea35f36dae,0x00f47d7ad15de22e,0x00d757ea4b105115,0x008311457d579d7e,0x00b49b75b1edd4eb,0x0081c7ff742fd63a,0x00ddda3187433df6,0x00475727d55f9c66)}, + {FIELD_LITERAL(0x00a6295218dc136a,0x00563b3af0e9c012,0x00d3753b0145db1b,0x004550389c043dc1,0x00ea94ae27401bdf,0x002b0b949f2b7956,0x00c63f780ad8e23c,0x00e591c47d6bab15)}, + {FIELD_LITERAL(0x00416c582b058eb6,0x004107da5b2cc695,0x00b3cd2556aeec64,0x00c0b418267e57a1,0x001799293579bd2e,0x0046ed44590e4d07,0x001d7459b3630a1e,0x00c6afba8b6696aa)}, + }}, {{ + {FIELD_LITERAL(0x008d6009b26da3f8,0x00898e88ca06b1ca,0x00edb22b2ed7fe62,0x00fbc93516aabe80,0x008b4b470c42ce0d,0x00e0032ba7d0dcbb,0x00d76da3a956ecc8,0x007f20fe74e3852a)}, + {FIELD_LITERAL(0x002419222c607674,0x00a7f23af89188b3,0x00ad127284e73d1c,0x008bba582fae1c51,0x00fc6aa7ca9ecab1,0x003df5319eb6c2ba,0x002a05af8a8b199a,0x004bf8354558407c)}, + {FIELD_LITERAL(0x00ce7d4a30f0fcbf,0x00d02c272629f03d,0x0048c001f7400bc2,0x002c21368011958d,0x0098a550391e96b5,0x002d80b66390f379,0x001fa878760cc785,0x001adfce54b613d5)}, + }}, {{ + {FIELD_LITERAL(0x001ed4dc71fa2523,0x005d0bff19bf9b5c,0x00c3801cee065a64,0x001ed0b504323fbf,0x0003ab9fdcbbc593,0x00df82070178b8d2,0x00a2bcaa9c251f85,0x00c628a3674bd02e)}, + {FIELD_LITERAL(0x006b7a0674f9f8de,0x00a742414e5c7cff,0x0041cbf3c6e13221,0x00e3a64fd207af24,0x0087c05f15fbe8d1,0x004c50936d9e8a33,0x001306ec21042b6d,0x00a4f4137d1141c2)}, + {FIELD_LITERAL(0x0009e6fb921568b0,0x00b3c60120219118,0x002a6c3460dd503a,0x009db1ef11654b54,0x0063e4bf0be79601,0x00670d34bb2592b9,0x00dcee2f6c4130ce,0x00b2682e88e77f54)}, + }}, {{ + {FIELD_LITERAL(0x000d5b4b3da135ab,0x00838f3e5064d81d,0x00d44eb50f6d94ed,0x0008931ab502ac6d,0x00debe01ca3d3586,0x0025c206775f0641,0x005ad4b6ae912763,0x007e2c318ad8f247)}, + {FIELD_LITERAL(0x00ddbe0750dd1add,0x004b3c7b885844b8,0x00363e7ecf12f1ae,0x0062e953e6438f9d,0x0023cc73b076afe9,0x00b09fa083b4da32,0x00c7c3d2456c541d,0x005b591ec6b694d4)}, + {FIELD_LITERAL(0x0028656e19d62fcf,0x0052a4af03df148d,0x00122765ddd14e42,0x00f2252904f67157,0x004741965b636f3a,0x006441d296132cb9,0x005e2106f956a5b7,0x00247029592d335c)}, + }}, {{ + {FIELD_LITERAL(0x003fe038eb92f894,0x000e6da1b72e8e32,0x003a1411bfcbe0fa,0x00b55d473164a9e4,0x00b9a775ac2df48d,0x0002ddf350659e21,0x00a279a69eb19cb3,0x00f844eab25cba44)}, + {FIELD_LITERAL(0x00c41d1f9c1f1ac1,0x007b2df4e9f19146,0x00b469355fd5ba7a,0x00b5e1965afc852a,0x00388d5f1e2d8217,0x0022079e4c09ae93,0x0014268acd4ef518,0x00c1dd8d9640464c)}, + {FIELD_LITERAL(0x0038526adeed0c55,0x00dd68c607e3fe85,0x00f746ddd48a5d57,0x0042f2952b963b7c,0x001cbbd6876d5ec2,0x005e341470bca5c2,0x00871d41e085f413,0x00e53ab098f45732)}, + }}, {{ + {FIELD_LITERAL(0x004d51124797c831,0x008f5ae3750347ad,0x0070ced94c1a0c8e,0x00f6db2043898e64,0x000d00c9a5750cd0,0x000741ec59bad712,0x003c9d11aab37b7f,0x00a67ba169807714)}, + {FIELD_LITERAL(0x00adb2c1566e8b8f,0x0096c68a35771a9a,0x00869933356f334a,0x00ba9c93459f5962,0x009ec73fb6e8ca4b,0x003c3802c27202e1,0x0031f5b733e0c008,0x00f9058c19611fa9)}, + {FIELD_LITERAL(0x00238f01814a3421,0x00c325a44b6cce28,0x002136f97aeb0e73,0x000cac8268a4afe2,0x0022fd218da471b3,0x009dcd8dfff8def9,0x00cb9f8181d999bb,0x00143ae56edea349)}, + }}, {{ + {FIELD_LITERAL(0x0000623bf87622c5,0x00a1966fdd069496,0x00c315b7b812f9fc,0x00bdf5efcd128b97,0x001d464f532e3e16,0x003cd94f081bfd7e,0x00ed9dae12ce4009,0x002756f5736eee70)}, + {FIELD_LITERAL(0x00a5187e6ee7341b,0x00e6d52e82d83b6e,0x00df3c41323094a7,0x00b3324f444e9de9,0x00689eb21a35bfe5,0x00f16363becd548d,0x00e187cc98e7f60f,0x00127d9062f0ccab)}, + {FIELD_LITERAL(0x004ad71b31c29e40,0x00a5fcace12fae29,0x004425b5597280ed,0x00e7ef5d716c3346,0x0010b53ada410ac8,0x0092310226060c9b,0x0091c26128729c7e,0x0088b42900f8ec3b)}, + }}, {{ + {FIELD_LITERAL(0x00f1e26e9762d4a8,0x00d9d74082183414,0x00ffec9bd57a0282,0x000919e128fd497a,0x00ab7ae7d00fe5f8,0x0054dc442851ff68,0x00c9ebeb3b861687,0x00507f7cab8b698f)}, + {FIELD_LITERAL(0x00c13c5aae3ae341,0x009c6c9ed98373e7,0x00098f26864577a8,0x0015b886e9488b45,0x0037692c42aadba5,0x00b83170b8e7791c,0x001670952ece1b44,0x00fd932a39276da2)}, + {FIELD_LITERAL(0x0081a3259bef3398,0x005480fff416107b,0x00ce4f607d21be98,0x003ffc084b41df9b,0x0043d0bb100502d1,0x00ec35f575ba3261,0x00ca18f677300ef3,0x00e8bb0a827d8548)}, + }}, {{ + {FIELD_LITERAL(0x00df76b3328ada72,0x002e20621604a7c2,0x00f910638a105b09,0x00ef4724d96ef2cd,0x00377d83d6b8a2f7,0x00b4f48805ade324,0x001cd5da8b152018,0x0045af671a20ca7f)}, + {FIELD_LITERAL(0x009ae3b93a56c404,0x004a410b7a456699,0x00023a619355e6b2,0x009cdc7297387257,0x0055b94d4ae70d04,0x002cbd607f65b005,0x003208b489697166,0x00ea2aa058867370)}, + {FIELD_LITERAL(0x00f29d2598ee3f32,0x00b4ac5385d82adc,0x007633eaf04df19b,0x00aa2d3d77ceab01,0x004a2302fcbb778a,0x00927f225d5afa34,0x004a8e9d5047f237,0x008224ae9dbce530)}, + }}, {{ + {FIELD_LITERAL(0x001cf640859b02f8,0x00758d1d5d5ce427,0x00763c784ef4604c,0x005fa81aee205270,0x00ac537bfdfc44cb,0x004b919bd342d670,0x00238508d9bf4b7a,0x00154888795644f3)}, + {FIELD_LITERAL(0x00c845923c084294,0x00072419a201bc25,0x0045f408b5f8e669,0x00e9d6a186b74dfe,0x00e19108c68fa075,0x0017b91d874177b7,0x002f0ca2c7912c5a,0x009400aa385a90a2)}, + {FIELD_LITERAL(0x0071110b01482184,0x00cfed0044f2bef8,0x0034f2901cf4662e,0x003b4ae2a67f9834,0x00cca9b96fe94810,0x00522507ae77abd0,0x00bac7422721e73e,0x0066622b0f3a62b0)}, + }}, {{ + {FIELD_LITERAL(0x00f8ac5cf4705b6a,0x00867d82dcb457e3,0x007e13ab2ccc2ce9,0x009ee9a018d3930e,0x008370f8ecb42df8,0x002d9f019add263e,0x003302385b92d196,0x00a15654536e2c0c)}, + {FIELD_LITERAL(0x0026ef1614e160af,0x00c023f9edfc9c76,0x00cff090da5f57ba,0x0076db7a66643ae9,0x0019462f8c646999,0x008fec00b3854b22,0x00d55041692a0a1c,0x0065db894215ca00)}, + {FIELD_LITERAL(0x00a925036e0a451c,0x002a0390c36b6cc1,0x00f27020d90894f4,0x008d90d52cbd3d7f,0x00e1d0137392f3b8,0x00f017c158b51a8f,0x00cac313d3ed7dbc,0x00b99a81e3eb42d3)}, + }}, {{ + {FIELD_LITERAL(0x00b54850275fe626,0x0053a3fd1ec71140,0x00e3d2d7dbe096fa,0x00e4ac7b595cce4c,0x0077bad449c0a494,0x00b7c98814afd5b3,0x0057226f58486cf9,0x00b1557154f0cc57)}, + {FIELD_LITERAL(0x008cc9cd236315c0,0x0031d9c5b39fda54,0x00a5713ef37e1171,0x00293d5ae2886325,0x00c4aba3e05015e1,0x0003f35ef78e4fc6,0x0039d6bd3ac1527b,0x0019d7c3afb77106)}, + {FIELD_LITERAL(0x007b162931a985af,0x00ad40a2e0daa713,0x006df27c4009f118,0x00503e9f4e2e8bec,0x00751a77c82c182d,0x000298937769245b,0x00ffb1e8fabf9ee5,0x0008334706e09abe)}, + }}, {{ + {FIELD_LITERAL(0x00dbca4e98a7dcd9,0x00ee29cfc78bde99,0x00e4a3b6995f52e9,0x0045d70189ae8096,0x00fd2a8a3b9b0d1b,0x00af1793b107d8e1,0x00dbf92cbe4afa20,0x00da60f798e3681d)}, + {FIELD_LITERAL(0x004246bfcecc627a,0x004ba431246c03a4,0x00bd1d101872d497,0x003b73d3f185ee16,0x001feb2e2678c0e3,0x00ff13c5a89dec76,0x00ed06042e771d8f,0x00a4fd2a897a83dd)}, + {FIELD_LITERAL(0x009a4a3be50d6597,0x00de3165fc5a1096,0x004f3f56e345b0c7,0x00f7bf721d5ab8bc,0x004313e47b098c50,0x00e4c7d5c0e1adbb,0x002e3e3db365051e,0x00a480c2cd6a96fb)}, + }}, {{ + {FIELD_LITERAL(0x00417fa30a7119ed,0x00af257758419751,0x00d358a487b463d4,0x0089703cc720b00d,0x00ce56314ff7f271,0x0064db171ade62c1,0x00640b36d4a22fed,0x00424eb88696d23f)}, + {FIELD_LITERAL(0x004ede34af2813f3,0x00d4a8e11c9e8216,0x004796d5041de8a5,0x00c4c6b4d21cc987,0x00e8a433ee07fa1e,0x0055720b5abcc5a1,0x008873ea9c74b080,0x005b3fec1ab65d48)}, + {FIELD_LITERAL(0x0047e5277db70ec5,0x000a096c66db7d6b,0x00b4164cc1730159,0x004a9f783fe720fe,0x00a8177b94449dbc,0x0095a24ff49a599f,0x0069c1c578250cbc,0x00452019213debf4)}, + }}, {{ + {FIELD_LITERAL(0x0021ce99e09ebda3,0x00fcbd9f91875ad0,0x009bbf6b7b7a0b5f,0x00388886a69b1940,0x00926a56d0f81f12,0x00e12903c3358d46,0x005dfce4e8e1ce9d,0x0044cfa94e2f7e23)}, + {FIELD_LITERAL(0x001bd59c09e982ea,0x00f72daeb937b289,0x0018b76dca908e0e,0x00edb498512384ad,0x00ce0243b6cc9538,0x00f96ff690cb4e70,0x007c77bf9f673c8d,0x005bf704c088a528)}, + {FIELD_LITERAL(0x0093d4628dcb33be,0x0095263d51d42582,0x0049b3222458fe06,0x00e7fce73b653a7f,0x003ca2ebce60b369,0x00c5de239a32bea4,0x0063b8b3d71fb6bf,0x0039aeeb78a1a839)}, + }}, {{ + {FIELD_LITERAL(0x007dc52da400336c,0x001fded1e15b9457,0x00902e00f5568e3a,0x00219bef40456d2d,0x005684161fb3dbc9,0x004a4e9be49a76ea,0x006e685ae88b78ff,0x0021c42f13042d3c)}, + {FIELD_LITERAL(0x00fb22bb5fd3ce50,0x0017b48aada7ae54,0x00fd5c44ad19a536,0x000ccc4e4e55e45c,0x00fd637d45b4c3f5,0x0038914e023c37cf,0x00ac1881d6a8d898,0x00611ed8d3d943a8)}, + {FIELD_LITERAL(0x0056e2259d113d2b,0x00594819b284ec16,0x00c7bf794bb36696,0x00721ee75097cdc6,0x00f71be9047a2892,0x00df6ba142564edf,0x0069580b7a184e8d,0x00f056e38fca0fee)}, + }}, {{ + {FIELD_LITERAL(0x009df98566a18c6d,0x00cf3a200968f219,0x0044ba60da6d9086,0x00dbc9c0e344da03,0x000f9401c4466855,0x00d46a57c5b0a8d1,0x00875a635d7ac7c6,0x00ef4a933b7e0ae6)}, + {FIELD_LITERAL(0x005e8694077a1535,0x008bef75f71c8f1d,0x000a7c1316423511,0x00906e1d70604320,0x003fc46c1a2ffbd6,0x00d1d5022e68f360,0x002515fba37bbf46,0x00ca16234e023b44)}, + {FIELD_LITERAL(0x00787c99561f4690,0x00a857a8c1561f27,0x00a10df9223c09fe,0x00b98a9562e3b154,0x004330b8744c3ed2,0x00e06812807ec5c4,0x00e4cf6a7db9f1e3,0x00d95b089f132a34)}, + }}, {{ + {FIELD_LITERAL(0x002922b39ca33eec,0x0090d12a5f3ab194,0x00ab60c02fb5f8ed,0x00188d292abba1cf,0x00e10edec9698f6e,0x0069a4d9934133c8,0x0024aac40e6d3d06,0x001702c2177661b0)}, + {FIELD_LITERAL(0x00139078397030bd,0x000e3c447e859a00,0x0064a5b334c82393,0x00b8aabeb7358093,0x00020778bb9ae73b,0x0032ee94c7892a18,0x008215253cb41bda,0x005e2797593517ae)}, + {FIELD_LITERAL(0x0083765a5f855d4a,0x0051b6d1351b8ee2,0x00116de548b0f7bb,0x0087bd88703affa0,0x0095b2cc34d7fdd2,0x0084cd81b53f0bc8,0x008562fc995350ed,0x00a39abb193651e3)}, + }}, {{ + {FIELD_LITERAL(0x0019e23f0474b114,0x00eb94c2ad3b437e,0x006ddb34683b75ac,0x00391f9209b564c6,0x00083b3bb3bff7aa,0x00eedcd0f6dceefc,0x00b50817f794fe01,0x0036474deaaa75c9)}, + {FIELD_LITERAL(0x0091868594265aa2,0x00797accae98ca6d,0x0008d8c5f0f8a184,0x00d1f4f1c2b2fe6e,0x0036783dfb48a006,0x008c165120503527,0x0025fd780058ce9b,0x0068beb007be7d27)}, + {FIELD_LITERAL(0x00d0ff88aa7c90c2,0x00b2c60dacf53394,0x0094a7284d9666d6,0x00bed9022ce7a19d,0x00c51553f0cd7682,0x00c3fb870b124992,0x008d0bc539956c9b,0x00fc8cf258bb8885)}, + }}, {{ + {FIELD_LITERAL(0x003667bf998406f8,0x0000115c43a12975,0x001e662f3b20e8fd,0x0019ffa534cb24eb,0x00016be0dc8efb45,0x00ff76a8b26243f5,0x00ae20d241a541e3,0x0069bd6af13cd430)}, + {FIELD_LITERAL(0x0045fdc16487cda3,0x00b2d8e844cf2ed7,0x00612c50e88c1607,0x00a08aabc66c1672,0x006031fdcbb24d97,0x001b639525744b93,0x004409d62639ab17,0x00a1853d0347ab1d)}, + {FIELD_LITERAL(0x0075a1a56ebf5c21,0x00a3e72be9ac53ed,0x00efcde1629170c2,0x0004225fe91ef535,0x0088049fc73dfda7,0x004abc74857e1288,0x0024e2434657317c,0x00d98cb3d3e5543c)}, + }}, {{ + {FIELD_LITERAL(0x00b4b53eab6bdb19,0x009b22d8b43711d0,0x00d948b9d961785d,0x00cb167b6f279ead,0x00191de3a678e1c9,0x00d9dd9511095c2e,0x00f284324cd43067,0x00ed74fa535151dd)}, + {FIELD_LITERAL(0x007e32c049b5c477,0x009d2bfdbd9bcfd8,0x00636e93045938c6,0x007fde4af7687298,0x0046a5184fafa5d3,0x0079b1e7f13a359b,0x00875adf1fb927d6,0x00333e21c61bcad2)}, + {FIELD_LITERAL(0x00048014f73d8b8d,0x0075684aa0966388,0x0092be7df06dc47c,0x0097cebcd0f5568a,0x005a7004d9c4c6a9,0x00b0ecbb659924c7,0x00d90332dd492a7c,0x0057fc14df11493d)}, + }}, {{ + {FIELD_LITERAL(0x0008ed8ea0ad95be,0x0041d324b9709645,0x00e25412257a19b4,0x0058df9f3423d8d2,0x00a9ab20def71304,0x009ae0dbf8ac4a81,0x00c9565977e4392a,0x003c9269444baf55)}, + {FIELD_LITERAL(0x007df6cbb926830b,0x00d336058ae37865,0x007af47dac696423,0x0048d3011ec64ac8,0x006b87666e40049f,0x0036a2e0e51303d7,0x00ba319bd79dbc55,0x003e2737ecc94f53)}, + {FIELD_LITERAL(0x00d296ff726272d9,0x00f6d097928fcf57,0x00e0e616a55d7013,0x00deaf454ed9eac7,0x0073a56bedef4d92,0x006ccfdf6fc92e19,0x009d1ee1371a7218,0x00ee3c2ee4462d80)}, + }}, {{ + {FIELD_LITERAL(0x00437bce9bccdf9d,0x00e0c8e2f85dc0a3,0x00c91a7073995a19,0x00856ec9fe294559,0x009e4b33394b156e,0x00e245b0dc497e5c,0x006a54e687eeaeff,0x00f1cd1cd00fdb7c)}, + {FIELD_LITERAL(0x008132ae5c5d8cd1,0x00121d68324a1d9f,0x00d6be9dafcb8c76,0x00684d9070edf745,0x00519fbc96d7448e,0x00388182fdc1f27e,0x000235baed41f158,0x00bf6cf6f1a1796a)}, + {FIELD_LITERAL(0x002adc4b4d148219,0x003084ada0d3a90a,0x0046de8aab0f2e4e,0x00452d342a67b5fd,0x00d4b50f01d4de21,0x00db6d9fc0cefb79,0x008c184c86a462cd,0x00e17c83764d42da)}, + }}, {{ + {FIELD_LITERAL(0x007b2743b9a1e01a,0x007847ffd42688c4,0x006c7844d610a316,0x00f0cb8b250aa4b0,0x00a19060143b3ae6,0x0014eb10b77cfd80,0x000170905729dd06,0x00063b5b9cd72477)}, + {FIELD_LITERAL(0x00ce382dc7993d92,0x00021153e938b4c8,0x00096f7567f48f51,0x0058f81ddfe4b0d5,0x00cc379a56b355c7,0x002c760770d3e819,0x00ee22d1d26e5a40,0x00de6d93d5b082d7)}, + {FIELD_LITERAL(0x000a91a42c52e056,0x00185f6b77fce7ea,0x000803c51962f6b5,0x0022528582ba563d,0x0043f8040e9856d6,0x0085a29ec81fb860,0x005f9a611549f5ff,0x00c1f974ecbd4b06)}, + }}, {{ + {FIELD_LITERAL(0x005b64c6fd65ec97,0x00c1fdd7f877bc7f,0x000d9cc6c89f841c,0x005c97b7f1aff9ad,0x0075e3c61475d47e,0x001ecb1ba8153011,0x00fe7f1c8d71d40d,0x003fa9757a229832)}, + {FIELD_LITERAL(0x00ffc5c89d2b0cba,0x00d363d42e3e6fc3,0x0019a1a0118e2e8a,0x00f7baeff48882e1,0x001bd5af28c6b514,0x0055476ca2253cb2,0x00d8eb1977e2ddf3,0x00b173b1adb228a1)}, + {FIELD_LITERAL(0x00f2cb99dd0ad707,0x00e1e08b6859ddd8,0x000008f2d0650bcc,0x00d7ed392f8615c3,0x00976750a94da27f,0x003e83bb0ecb69ba,0x00df8e8d15c14ac6,0x00f9f7174295d9c2)}, + }}, {{ + {FIELD_LITERAL(0x00f11cc8e0e70bcb,0x00e5dc689974e7dd,0x0014e409f9ee5870,0x00826e6689acbd63,0x008a6f4e3d895d88,0x00b26a8da41fd4ad,0x000fb7723f83efd7,0x009c749db0a5f6c3)}, + {FIELD_LITERAL(0x002389319450f9ba,0x003677f31aa1250a,0x0092c3db642f38cb,0x00f8b64c0dfc9773,0x00cd49fe3505b795,0x0068105a4090a510,0x00df0ba2072a8bb6,0x00eb396143afd8be)}, + {FIELD_LITERAL(0x00a0d4ecfb24cdff,0x00ddaf8008ba6479,0x00f0b3e36d4b0f44,0x003734bd3af1f146,0x00b87e2efc75527e,0x00d230df55ddab50,0x002613257ae56c1d,0x00bc0946d135934d)}, + }}, {{ + {FIELD_LITERAL(0x00468711bd994651,0x0033108fa67561bf,0x0089d760192a54b4,0x00adc433de9f1871,0x000467d05f36e050,0x007847e0f0579f7f,0x00a2314ad320052d,0x00b3a93649f0b243)}, + {FIELD_LITERAL(0x0067f8f0c4fe26c9,0x0079c4a3cc8f67b9,0x0082b1e62f23550d,0x00f2d409caefd7f5,0x0080e67dcdb26e81,0x0087ae993ea1f98a,0x00aa108becf61d03,0x001acf11efb608a3)}, + {FIELD_LITERAL(0x008225febbab50d9,0x00f3b605e4dd2083,0x00a32b28189e23d2,0x00d507e5e5eb4c97,0x005a1a84e302821f,0x0006f54c1c5f08c7,0x00a347c8cb2843f0,0x0009f73e9544bfa5)}, + }}, {{ + {FIELD_LITERAL(0x006c59c9ae744185,0x009fc32f1b4282cd,0x004d6348ca59b1ac,0x00105376881be067,0x00af4096013147dc,0x004abfb5a5cb3124,0x000d2a7f8626c354,0x009c6ed568e07431)}, + {FIELD_LITERAL(0x00e828333c297f8b,0x009ef3cf8c3f7e1f,0x00ab45f8fff31cb9,0x00c8b4178cb0b013,0x00d0c50dd3260a3f,0x0097126ac257f5bc,0x0042376cc90c705a,0x001d96fdb4a1071e)}, + {FIELD_LITERAL(0x00542d44d89ee1a8,0x00306642e0442d98,0x0090853872b87338,0x002362cbf22dc044,0x002c222adff663b8,0x0067c924495fcb79,0x000e621d983c977c,0x00df77a9eccb66fb)}, + }}, {{ + {FIELD_LITERAL(0x002809e4bbf1814a,0x00b9e854f9fafb32,0x00d35e67c10f7a67,0x008f1bcb76e748cf,0x004224d9515687d2,0x005ba0b774e620c4,0x00b5e57db5d54119,0x00e15babe5683282)}, + {FIELD_LITERAL(0x00832d02369b482c,0x00cba52ff0d93450,0x003fa9c908d554db,0x008d1e357b54122f,0x00abd91c2dc950c6,0x007eff1df4c0ec69,0x003f6aeb13fb2d31,0x00002d6179fc5b2c)}, + {FIELD_LITERAL(0x0046c9eda81c9c89,0x00b60cb71c8f62fc,0x0022f5a683baa558,0x00f87319fccdf997,0x009ca09b51ce6a22,0x005b12baf4af7d77,0x008a46524a1e33e2,0x00035a77e988be0d)}, + }}, {{ + {FIELD_LITERAL(0x00a7efe46a7dbe2f,0x002f66fd55014fe7,0x006a428afa1ff026,0x0056caaa9604ab72,0x0033f3bcd7fac8ae,0x00ccb1aa01c86764,0x00158d1edf13bf40,0x009848ee76fcf3b4)}, + {FIELD_LITERAL(0x00a9e7730a819691,0x00d9cc73c4992b70,0x00e299bde067de5a,0x008c314eb705192a,0x00e7226f17e8a3cc,0x0029dfd956e65a47,0x0053a8e839073b12,0x006f942b2ab1597e)}, + {FIELD_LITERAL(0x001c3d780ecd5e39,0x0094f247fbdcc5fe,0x00d5c786fd527764,0x00b6f4da74f0db2a,0x0080f1f8badcd5fc,0x00f36a373ad2e23b,0x00f804f9f4343bf2,0x00d1af40ec623982)}, + }}, {{ + {FIELD_LITERAL(0x0082aeace5f1b144,0x00f68b3108cf4dd3,0x00634af01dde3020,0x000beab5df5c2355,0x00e8b790d1b49b0b,0x00e48d15854e36f4,0x0040ab2d95f3db9f,0x002711c4ed9e899a)}, + {FIELD_LITERAL(0x0039343746531ebe,0x00c8509d835d429d,0x00e79eceff6b0018,0x004abfd31e8efce5,0x007bbfaaa1e20210,0x00e3be89c193e179,0x001c420f4c31d585,0x00f414a315bef5ae)}, + {FIELD_LITERAL(0x007c296a24990df8,0x00d5d07525a75588,0x00dd8e113e94b7e7,0x007bbc58febe0cc8,0x0029f51af9bfcad3,0x007e9311ec7ab6f3,0x009a884de1676343,0x0050d5f2dce84be9)}, + }}, {{ + {FIELD_LITERAL(0x005fa020cca2450a,0x00491c29db6416d8,0x0037cefe3f9f9a85,0x003d405230647066,0x0049e835f0fdbe89,0x00feb78ac1a0815c,0x00828e4b32dc9724,0x00db84f2dc8d6fd4)}, + {FIELD_LITERAL(0x0098cddc8b39549a,0x006da37e3b05d22c,0x00ce633cfd4eb3cb,0x00fda288ef526acd,0x0025338878c5d30a,0x00f34438c4e5a1b4,0x00584efea7c310f1,0x0041a551f1b660ad)}, + {FIELD_LITERAL(0x00d7f7a8fbd6437a,0x0062872413bf3753,0x00ad4bbcb43c584b,0x007fe49be601d7e3,0x0077c659789babf4,0x00eb45fcb06a741b,0x005ce244913f9708,0x0088426401736326)}, + }}, {{ + {FIELD_LITERAL(0x007bf562ca768d7c,0x006c1f3a174e387c,0x00f024b447fee939,0x007e7af75f01143f,0x003adb70b4eed89d,0x00e43544021ad79a,0x0091f7f7042011f6,0x0093c1a1ee3a0ddc)}, + {FIELD_LITERAL(0x00a0b68ec1eb72d2,0x002c03235c0d45a0,0x00553627323fe8c5,0x006186e94b17af94,0x00a9906196e29f14,0x0025b3aee6567733,0x007e0dd840080517,0x0018eb5801a4ba93)}, + {FIELD_LITERAL(0x00d7fe7017bf6a40,0x006e3f0624be0c42,0x00ffbba205358245,0x00f9fc2cf8194239,0x008d93b37bf15b4e,0x006ddf2e38be8e95,0x002b6e79bf5fcff9,0x00ab355da425e2de)}, + }}, {{ + {FIELD_LITERAL(0x00938f97e20be973,0x0099141a36aaf306,0x0057b0ca29e545a1,0x0085db571f9fbc13,0x008b333c554b4693,0x0043ab6ef3e241cb,0x0054fb20aa1e5c70,0x00be0ff852760adf)}, + {FIELD_LITERAL(0x003973d8938971d6,0x002aca26fa80c1f5,0x00108af1faa6b513,0x00daae275d7924e6,0x0053634ced721308,0x00d2355fe0bbd443,0x00357612b2d22095,0x00f9bb9dd4136cf3)}, + {FIELD_LITERAL(0x002bff12cf5e03a5,0x001bdb1fa8a19cf8,0x00c91c6793f84d39,0x00f869f1b2eba9af,0x0059bc547dc3236b,0x00d91611d6d38689,0x00e062daaa2c0214,0x00ed3c047cc2bc82)}, + }}, {{ + {FIELD_LITERAL(0x000050d70c32b31a,0x001939d576d437b3,0x00d709e598bf9fe6,0x00a885b34bd2ee9e,0x00dd4b5c08ab1a50,0x0091bebd50b55639,0x00cf79ff64acdbc6,0x006067a39d826336)}, + {FIELD_LITERAL(0x0062dd0fb31be374,0x00fcc96b84c8e727,0x003f64f1375e6ae3,0x0057d9b6dd1af004,0x00d6a167b1103c7b,0x00dd28f3180fb537,0x004ff27ad7167128,0x008934c33461f2ac)}, + {FIELD_LITERAL(0x0065b472b7900043,0x00ba7efd2ff1064b,0x000b67d6c4c3020f,0x0012d28469f4e46d,0x0031c32939703ec7,0x00b49f0bce133066,0x00f7e10416181d47,0x005c90f51867eecc)}, + }}, {{ + {FIELD_LITERAL(0x0051207abd179101,0x00fc2a5c20d9c5da,0x00fb9d5f2701b6df,0x002dd040fdea82b8,0x00f163b0738442ff,0x00d9736bd68855b8,0x00e0d8e93005e61c,0x00df5a40b3988570)}, + {FIELD_LITERAL(0x0006918f5dfce6dc,0x00d4bf1c793c57fb,0x0069a3f649435364,0x00e89a50e5b0cd6e,0x00b9f6a237e973af,0x006d4ed8b104e41d,0x00498946a3924cd2,0x00c136ec5ac9d4f7)}, + {FIELD_LITERAL(0x0011a9c290ac5336,0x002b9a2d4a6a6533,0x009a8a68c445d937,0x00361b27b07e5e5c,0x003c043b1755b974,0x00b7eb66cf1155ee,0x0077af5909eefff2,0x0098f609877cc806)}, + }}, {{ + {FIELD_LITERAL(0x00ab13af436bf8f4,0x000bcf0a0dac8574,0x00d50c864f705045,0x00c40e611debc842,0x0085010489bd5caa,0x007c5050acec026f,0x00f67d943c8da6d1,0x00de1da0278074c6)}, + {FIELD_LITERAL(0x00b373076597455f,0x00e83f1af53ac0f5,0x0041f63c01dc6840,0x0097dea19b0c6f4b,0x007f9d63b4c1572c,0x00e692d492d0f5f0,0x00cbcb392e83b4ad,0x0069c0f39ed9b1a8)}, + {FIELD_LITERAL(0x00861030012707c9,0x009fbbdc7fd4aafb,0x008f591d6b554822,0x00df08a41ea18ade,0x009d7d83e642abea,0x0098c71bda3b78ff,0x0022c89e7021f005,0x0044d29a3fe1e3c4)}, + }}, {{ + {FIELD_LITERAL(0x00e748cd7b5c52f2,0x00ea9df883f89cc3,0x0018970df156b6c7,0x00c5a46c2a33a847,0x00cbde395e32aa09,0x0072474ebb423140,0x00fb00053086a23d,0x001dafcfe22d4e1f)}, + {FIELD_LITERAL(0x00c903ee6d825540,0x00add6c4cf98473e,0x007636efed4227f1,0x00905124ae55e772,0x00e6b38fab12ed53,0x0045e132b863fe55,0x003974662edb366a,0x00b1787052be8208)}, + {FIELD_LITERAL(0x00a614b00d775c7c,0x00d7c78941cc7754,0x00422dd68b5dabc4,0x00a6110f0167d28b,0x00685a309c252886,0x00b439ffd5143660,0x003656e29ee7396f,0x00c7c9b9ed5ad854)}, + }}, {{ + {FIELD_LITERAL(0x0040f7e7c5b37bf2,0x0064e4dc81181bba,0x00a8767ae2a366b6,0x001496b4f90546f2,0x002a28493f860441,0x0021f59513049a3a,0x00852d369a8b7ee3,0x00dd2e7d8b7d30a9)}, + {FIELD_LITERAL(0x00006e34a35d9fbc,0x00eee4e48b2f019a,0x006b344743003a5f,0x00541d514f04a7e3,0x00e81f9ee7647455,0x005e2b916c438f81,0x00116f8137b7eff0,0x009bd3decc7039d1)}, + {FIELD_LITERAL(0x0005d226f434110d,0x00af8288b8ef21d5,0x004a7a52ef181c8c,0x00be0b781b4b06de,0x00e6e3627ded07e1,0x00e43aa342272b8b,0x00e86ab424577d84,0x00fb292c566e35bb)}, + }}, {{ + {FIELD_LITERAL(0x00334f5303ea1222,0x00dfb3dbeb0a5d3e,0x002940d9592335c1,0x00706a7a63e8938a,0x005a533558bc4caf,0x00558e33192022a9,0x00970d9faf74c133,0x002979fcb63493ca)}, + {FIELD_LITERAL(0x00e38abece3c82ab,0x005a51f18a2c7a86,0x009dafa2e86d592e,0x00495a62eb688678,0x00b79df74c0eb212,0x0023e8cc78b75982,0x005998cb91075e13,0x00735aa9ba61bc76)}, + {FIELD_LITERAL(0x00d9f7a82ddbe628,0x00a1fc782889ae0f,0x0071ffda12d14b66,0x0037cf4eca7fb3d5,0x00c80bc242c58808,0x0075bf8c2d08c863,0x008d41f31afc52a7,0x00197962ecf38741)}, + }}, {{ + {FIELD_LITERAL(0x006e9f475cccf2ee,0x00454b9cd506430c,0x00224a4fb79ee479,0x0062e3347ef0b5e2,0x0034fd2a3512232a,0x00b8b3cb0f457046,0x00eb20165daa38ec,0x00128eebc2d9c0f7)}, + {FIELD_LITERAL(0x00bfc5fa1e4ea21f,0x00c21d7b6bb892e6,0x00cf043f3acf0291,0x00c13f2f849b3c90,0x00d1a97ebef10891,0x0061e130a445e7fe,0x0019513fdedbf22b,0x001d60c813bff841)}, + {FIELD_LITERAL(0x0019561c7fcf0213,0x00e3dca6843ebd77,0x0068ea95b9ca920e,0x009bdfb70f253595,0x00c68f59186aa02a,0x005aee1cca1c3039,0x00ab79a8a937a1ce,0x00b9a0e549959e6f)}, + }}, {{ + {FIELD_LITERAL(0x00c79e0b6d97dfbd,0x00917c71fd2bc6e8,0x00db7529ccfb63d8,0x00be5be957f17866,0x00a9e11fdc2cdac1,0x007b91a8e1f44443,0x00a3065e4057d80f,0x004825f5b8d5f6d4)}, + {FIELD_LITERAL(0x003e4964fa8a8fc8,0x00f6a1cdbcf41689,0x00943cb18fe7fda7,0x00606dafbf34440a,0x005d37a86399c789,0x00e79a2a69417403,0x00fe34f7e68b8866,0x0011f448ed2df10e)}, + {FIELD_LITERAL(0x00f1f57efcc1fcc4,0x00513679117de154,0x002e5b5b7c86d8c3,0x009f6486561f9cfb,0x00169e74b0170cf7,0x00900205af4af696,0x006acfddb77853f3,0x00df184c90f31068)}, + }}, {{ + {FIELD_LITERAL(0x00b37396c3320791,0x00fc7b67175c5783,0x00c36d2cd73ecc38,0x0080ebcc0b328fc5,0x0043a5b22b35d35d,0x00466c9f1713c9da,0x0026ad346dcaa8da,0x007c684e701183a6)}, + {FIELD_LITERAL(0x00fd579ffb691713,0x00b76af4f81c412d,0x00f239de96110f82,0x00e965fb437f0306,0x00ca7e9436900921,0x00e487f1325fa24a,0x00633907de476380,0x00721c62ac5b8ea0)}, + {FIELD_LITERAL(0x00c0d54e542eb4f9,0x004ed657171c8dcf,0x00b743a4f7c2a39b,0x00fd9f93ed6cc567,0x00307fae3113e58b,0x0058aa577c93c319,0x00d254556f35b346,0x00491aada2203f0d)}, + }}, {{ + {FIELD_LITERAL(0x00dff3103786ff34,0x000144553b1f20c3,0x0095613baeb930e4,0x00098058275ea5d4,0x007cd1402b046756,0x0074d74e4d58aee3,0x005f93fc343ff69b,0x00873df17296b3b0)}, + {FIELD_LITERAL(0x00c4a1fb48635413,0x00b5dd54423ad59f,0x009ff5d53fd24a88,0x003c98d267fc06a7,0x002db7cb20013641,0x00bd1d6716e191f2,0x006dbc8b29094241,0x0044bbf233dafa2c)}, + {FIELD_LITERAL(0x0055838d41f531e6,0x00bf6a2dd03c81b2,0x005827a061c4839e,0x0000de2cbb36aac3,0x002efa29d9717478,0x00f9e928cc8a77ba,0x00c134b458def9ef,0x00958a182223fc48)}, + }}, {{ + {FIELD_LITERAL(0x000a9ee23c06881f,0x002c727d3d871945,0x00f47d971512d24a,0x00671e816f9ef31a,0x00883af2cfaad673,0x00601f98583d6c9a,0x00b435f5adc79655,0x00ad87b71c04bff2)}, + {FIELD_LITERAL(0x007860d99db787cf,0x00fda8983018f4a8,0x008c8866bac4743c,0x00ef471f84c82a3f,0x00abea5976d3b8e7,0x00714882896cd015,0x00b49fae584ddac5,0x008e33a1a0b69c81)}, + {FIELD_LITERAL(0x007b6ee2c9e8a9ec,0x002455dbbd89d622,0x006490cf4eaab038,0x00d925f6c3081561,0x00153b3047de7382,0x003b421f8bdceb6f,0x00761a4a5049da78,0x00980348c5202433)}, + }}, {{ + {FIELD_LITERAL(0x007f8a43da97dd5c,0x00058539c800fc7b,0x0040f3cf5a28414a,0x00d68dd0d95283d6,0x004adce9da90146e,0x00befa41c7d4f908,0x007603bc2e3c3060,0x00bdf360ab3545db)}, + {FIELD_LITERAL(0x00eebfd4e2312cc3,0x00474b2564e4fc8c,0x003303ef14b1da9b,0x003c93e0e66beb1d,0x0013619b0566925a,0x008817c24d901bf3,0x00b62bd8898d218b,0x0075a7716f1e88a2)}, + {FIELD_LITERAL(0x0009218da1e6890f,0x0026907f5fd02575,0x004dabed5f19d605,0x003abf181870249d,0x00b52fd048cc92c4,0x00b6dd51e415a5c5,0x00d9eb82bd2b4014,0x002c865a43b46b43)}, + }}, {{ + {FIELD_LITERAL(0x0070047189452f4c,0x00f7ad12e1ce78d5,0x00af1ba51ec44a8b,0x005f39f63e667cd6,0x00058eac4648425e,0x00d7fdab42bea03b,0x0028576a5688de15,0x00af973209e77c10)}, + {FIELD_LITERAL(0x00c338b915d8fef0,0x00a893292045c39a,0x0028ab4f2eba6887,0x0060743cb519fd61,0x0006213964093ac0,0x007c0b7a43f6266d,0x008e3557c4fa5bda,0x002da976de7b8d9d)}, + {FIELD_LITERAL(0x0048729f8a8b6dcd,0x00fe23b85cc4d323,0x00e7384d16e4db0e,0x004a423970678942,0x00ec0b763345d4ba,0x00c477b9f99ed721,0x00c29dad3777b230,0x001c517b466f7df6)}, + }}, {{ + {FIELD_LITERAL(0x006366c380f7b574,0x001c7d1f09ff0438,0x003e20a7301f5b22,0x00d3efb1916d28f6,0x0049f4f81060ce83,0x00c69d91ea43ced1,0x002b6f3e5cd269ed,0x005b0fb22ce9ec65)}, + {FIELD_LITERAL(0x00aa2261022d883f,0x00ebcca4548010ac,0x002528512e28a437,0x0070ca7676b66082,0x0084bda170f7c6d3,0x00581b4747c9b8bb,0x005c96a01061c7e2,0x00fb7c4a362b5273)}, + {FIELD_LITERAL(0x00c30020eb512d02,0x0060f288283a4d26,0x00b7ed13becde260,0x0075ebb74220f6e9,0x00701079fcfe8a1f,0x001c28fcdff58938,0x002e4544b8f4df6b,0x0060c5bc4f1a7d73)}, + }}, {{ + {FIELD_LITERAL(0x00ae307cf069f701,0x005859f222dd618b,0x00212d6c46ec0b0d,0x00a0fe4642afb62d,0x00420d8e4a0a8903,0x00a80ff639bdf7b0,0x0019bee1490b5d8e,0x007439e4b9c27a86)}, + {FIELD_LITERAL(0x00a94700032a093f,0x0076e96c225216e7,0x00a63a4316e45f91,0x007d8bbb4645d3b2,0x00340a6ff22793eb,0x006f935d4572aeb7,0x00b1fb69f00afa28,0x009e8f3423161ed3)}, + {FIELD_LITERAL(0x009ef49c6b5ced17,0x00a555e6269e9f0a,0x007e6f1d79ec73b5,0x009ac78695a32ac4,0x0001d77fbbcd5682,0x008cea1fee0aaeed,0x00f42bea82a53462,0x002e46ab96cafcc9)}, + }}, {{ + {FIELD_LITERAL(0x0051cfcc5885377a,0x00dce566cb1803ca,0x00430c7643f2c7d4,0x00dce1a1337bdcc0,0x0010d5bd7283c128,0x003b1b547f9b46fe,0x000f245e37e770ab,0x007b72511f022b37)}, + {FIELD_LITERAL(0x0060db815bc4786c,0x006fab25beedc434,0x00c610d06084797c,0x000c48f08537bec0,0x0031aba51c5b93da,0x007968fa6e01f347,0x0030070da52840c6,0x00c043c225a4837f)}, + {FIELD_LITERAL(0x001bcfd00649ee93,0x006dceb47e2a0fd5,0x00f2cebda0cf8fd0,0x00b6b9d9d1fbdec3,0x00815262e6490611,0x00ef7f5ce3176760,0x00e49cd0c998d58b,0x005fc6cc269ba57c)}, + }}, {{ + {FIELD_LITERAL(0x008940211aa0d633,0x00addae28136571d,0x00d68fdbba20d673,0x003bc6129bc9e21a,0x000346cf184ebe9a,0x0068774d741ebc7f,0x0019d5e9e6966557,0x0003cbd7f981b651)}, + {FIELD_LITERAL(0x004a2902926f8d3f,0x00ad79b42637ab75,0x0088f60b90f2d4e8,0x0030f54ef0e398c4,0x00021dc9bf99681e,0x007ebf66fde74ee3,0x004ade654386e9a4,0x00e7485066be4c27)}, + {FIELD_LITERAL(0x00445f1263983be0,0x004cf371dda45e6a,0x00744a89d5a310e7,0x001f20ce4f904833,0x00e746edebe66e29,0x000912ab1f6c153d,0x00f61d77d9b2444c,0x0001499cd6647610)}, + }} + } +}; +const struct curve448_precomputed_s *curve448_precomputed_base + = &curve448_precomputed_base_table; + +static const niels_t curve448_wnaf_base_table[32] = { + {{ + {FIELD_LITERAL(0x00303cda6feea532,0x00860f1d5a3850e4,0x00226b9fa4728ccd,0x00e822938a0a0c0c,0x00263a61c9ea9216,0x001204029321b828,0x006a468360983c65,0x0002846f0a782143)}, + {FIELD_LITERAL(0x00303cda6feea532,0x00860f1d5a3850e4,0x00226b9fa4728ccd,0x006822938a0a0c0c,0x00263a61c9ea9215,0x001204029321b828,0x006a468360983c65,0x0082846f0a782143)}, + {FIELD_LITERAL(0x00ef8e22b275198d,0x00b0eb141a0b0e8b,0x001f6789da3cb38c,0x006d2ff8ed39073e,0x00610bdb69a167f3,0x00571f306c9689b4,0x00f557e6f84b2df8,0x002affd38b2c86db)}, + }}, {{ + {FIELD_LITERAL(0x00cea0fc8d2e88b5,0x00821612d69f1862,0x0074c283b3e67522,0x005a195ba05a876d,0x000cddfe557feea4,0x008046c795bcc5e5,0x00540969f4d6e119,0x00d27f96d6b143d5)}, + {FIELD_LITERAL(0x000c3b1019d474e8,0x00e19533e4952284,0x00cc9810ba7c920a,0x00f103d2785945ac,0x00bfa5696cc69b34,0x00a8d3d51e9ca839,0x005623cb459586b9,0x00eae7ce1cd52e9e)}, + {FIELD_LITERAL(0x0005a178751dd7d8,0x002cc3844c69c42f,0x00acbfe5efe10539,0x009c20f43431a65a,0x008435d96374a7b3,0x009ee57566877bd3,0x0044691725ed4757,0x001e87bb2fe2c6b2)}, + }}, {{ + {FIELD_LITERAL(0x000cedc4debf7a04,0x002ffa45000470ac,0x002e9f9678201915,0x0017da1208c4fe72,0x007d558cc7d656cb,0x0037a827287cf289,0x00142472d3441819,0x009c21f166cf8dd1)}, + {FIELD_LITERAL(0x003ef83af164b2f2,0x000949a5a0525d0d,0x00f4498186cac051,0x00e77ac09ef126d2,0x0073ae0b2c9296e9,0x001c163f6922e3ed,0x0062946159321bea,0x00cfb79b22990b39)}, + {FIELD_LITERAL(0x00b001431ca9e654,0x002d7e5eabcc9a3a,0x0052e8114c2f6747,0x0079ac4f94487f92,0x00bffd919b5d749c,0x00261f92ad15e620,0x00718397b7a97895,0x00c1443e6ebbc0c4)}, + }}, {{ + {FIELD_LITERAL(0x00eacd90c1e0a049,0x008977935b149fbe,0x0004cb9ba11c93dc,0x009fbd5b3470844d,0x004bc18c9bfc22cf,0x0057679a991839f3,0x00ef15b76fb4092e,0x0074a5173a225041)}, + {FIELD_LITERAL(0x003f5f9d7ec4777b,0x00ab2e733c919c94,0x001bb6c035245ae5,0x00a325a49a883630,0x0033e9a9ea3cea2f,0x00e442a1eaa0e844,0x00b2116d5b0e71b8,0x00c16abed6d64047)}, + {FIELD_LITERAL(0x00c560b5ed051165,0x001945adc5d65094,0x00e221865710f910,0x00cc12bc9e9b8ceb,0x004faa9518914e35,0x0017476d89d42f6d,0x00b8f637c8fa1c8b,0x0088c7d2790864b8)}, + }}, {{ + {FIELD_LITERAL(0x00ef7eafc1c69be6,0x0085d3855778fbea,0x002c8d5b450cb6f5,0x004e77de5e1e7fec,0x0047c057893abded,0x001b430b85d51e16,0x00965c7b45640c3c,0x00487b2bb1162b97)}, + {FIELD_LITERAL(0x0099c73a311beec2,0x00a3eff38d8912ad,0x002efa9d1d7e8972,0x00f717ae1e14d126,0x002833f795850c8b,0x0066c12ad71486bd,0x00ae9889da4820eb,0x00d6044309555c08)}, + {FIELD_LITERAL(0x004b1c5283d15e41,0x00669d8ea308ff75,0x0004390233f762a1,0x00e1d67b83cb6cec,0x003eebaa964c78b1,0x006b0aff965eb664,0x00b313d4470bdc37,0x008814ffcb3cb9d8)}, + }}, {{ + {FIELD_LITERAL(0x009724b8ce68db70,0x007678b5ed006f3d,0x00bdf4b89c0abd73,0x00299748e04c7c6d,0x00ddd86492c3c977,0x00c5a7febfa30a99,0x00ed84715b4b02bb,0x00319568adf70486)}, + {FIELD_LITERAL(0x0070ff2d864de5bb,0x005a37eeb637ee95,0x0033741c258de160,0x00e6ca5cb1988f46,0x001ceabd92a24661,0x0030957bd500fe40,0x001c3362afe912c5,0x005187889f678bd2)}, + {FIELD_LITERAL(0x0086835fc62bbdc7,0x009c3516ca4910a1,0x00956c71f8d00783,0x0095c78fcf63235f,0x00fc7ff6ba05c222,0x00cdd8b3f8d74a52,0x00ac5ae16de8256e,0x00e9d4be8ed48624)}, + }}, {{ + {FIELD_LITERAL(0x00c0ce11405df2d8,0x004e3f37b293d7b6,0x002410172e1ac6db,0x00b8dbff4bf8143d,0x003a7b409d56eb66,0x003e0f6a0dfef9af,0x0081c4e4d3645be1,0x00ce76076b127623)}, + {FIELD_LITERAL(0x00f6ee0f98974239,0x0042d89af07d3a4f,0x00846b7fe84346b5,0x006a21fc6a8d39a1,0x00ac8bc2541ff2d9,0x006d4e2a77732732,0x009a39b694cc3f2f,0x0085c0aa2a404c8f)}, + {FIELD_LITERAL(0x00b261101a218548,0x00c1cae96424277b,0x00869da0a77dd268,0x00bc0b09f8ec83ea,0x00d61027f8e82ba9,0x00aa4c85999dce67,0x00eac3132b9f3fe1,0x00fb9b0cf1c695d2)}, + }}, {{ + {FIELD_LITERAL(0x0043079295512f0d,0x0046a009861758e0,0x003ee2842a807378,0x0034cc9d1298e4fa,0x009744eb4d31b3ee,0x00afacec96650cd0,0x00ac891b313761ae,0x00e864d6d26e708a)}, + {FIELD_LITERAL(0x00a84d7c8a23b491,0x0088e19aa868b27f,0x0005986d43e78ce9,0x00f28012f0606d28,0x0017ded7e10249b3,0x005ed4084b23af9b,0x00b9b0a940564472,0x00ad9056cceeb1f4)}, + {FIELD_LITERAL(0x00db91b357fe755e,0x00a1aa544b15359c,0x00af4931a0195574,0x007686124fe11aef,0x00d1ead3c7b9ef7e,0x00aaf5fc580f8c15,0x00e727be147ee1ec,0x003c61c1e1577b86)}, + }}, {{ + {FIELD_LITERAL(0x009d3fca983220cf,0x00cd11acbc853dc4,0x0017590409d27f1d,0x00d2176698082802,0x00fa01251b2838c8,0x00dd297a0d9b51c6,0x00d76c92c045820a,0x00534bc7c46c9033)}, + {FIELD_LITERAL(0x0080ed9bc9b07338,0x00fceac7745d2652,0x008a9d55f5f2cc69,0x0096ce72df301ac5,0x00f53232e7974d87,0x0071728c7ae73947,0x0090507602570778,0x00cb81cfd883b1b2)}, + {FIELD_LITERAL(0x005011aadea373da,0x003a8578ec896034,0x00f20a6535fa6d71,0x005152d31e5a87cf,0x002bac1c8e68ca31,0x00b0e323db4c1381,0x00f1d596b7d5ae25,0x00eae458097cb4e0)}, + }}, {{ + {FIELD_LITERAL(0x00920ac80f9b0d21,0x00f80f7f73401246,0x0086d37849b557d6,0x0002bd4b317b752e,0x00b26463993a42bb,0x002070422a73b129,0x00341acaa0380cb3,0x00541914dd66a1b2)}, + {FIELD_LITERAL(0x00c1513cd66abe8c,0x000139e01118944d,0x0064abbcb8080bbb,0x00b3b08202473142,0x00c629ef25da2403,0x00f0aec3310d9b7f,0x0050b2227472d8cd,0x00f6c8a922d41fb4)}, + {FIELD_LITERAL(0x001075ccf26b7b1f,0x00bb6bb213170433,0x00e9491ad262da79,0x009ef4f48d2d384c,0x008992770766f09d,0x001584396b6b1101,0x00af3f8676c9feef,0x0024603c40269118)}, + }}, {{ + {FIELD_LITERAL(0x009dd7b31319527c,0x001e7ac948d873a9,0x00fa54b46ef9673a,0x0066efb8d5b02fe6,0x00754b1d3928aeae,0x0004262ac72a6f6b,0x0079b7d49a6eb026,0x003126a753540102)}, + {FIELD_LITERAL(0x009666e24f693947,0x00f714311269d45f,0x0010ffac1d0c851c,0x0066e80c37363497,0x00f1f4ad010c60b0,0x0015c87408470ff7,0x00651d5e9c7766a4,0x008138819d7116de)}, + {FIELD_LITERAL(0x003934b11c57253b,0x00ef308edf21f46e,0x00e54e99c7a16198,0x0080d57135764e63,0x00751c27b946bc24,0x00dd389ce4e9e129,0x00a1a2bfd1cd84dc,0x002fae73e5149b32)}, + }}, {{ + {FIELD_LITERAL(0x00911657dffb4cdd,0x00c100b7cc553d06,0x00449d075ec467cc,0x007062100bc64e70,0x0043cf86f7bd21e7,0x00f401dc4b797dea,0x005224afb2f62e65,0x00d1ede3fb5a42be)}, + {FIELD_LITERAL(0x00f2ba36a41aa144,0x00a0c22d946ee18f,0x008aae8ef9a14f99,0x00eef4d79b19bb36,0x008e75ce3d27b1fc,0x00a65daa03b29a27,0x00d9cc83684eb145,0x009e1ed80cc2ed74)}, + {FIELD_LITERAL(0x00bed953d1997988,0x00b93ed175a24128,0x00871c5963fb6365,0x00ca2df20014a787,0x00f5d9c1d0b34322,0x00f6f5942818db0a,0x004cc091f49c9906,0x00e8a188a60bff9f)}, + }}, {{ + {FIELD_LITERAL(0x0032c7762032fae8,0x00e4087232e0bc21,0x00f767344b6e8d85,0x00bbf369b76c2aa2,0x008a1f46c6e1570c,0x001368cd9780369f,0x007359a39d079430,0x0003646512921434)}, + {FIELD_LITERAL(0x007c4b47ca7c73e7,0x005396221039734b,0x008b64ddf0e45d7e,0x00bfad5af285e6c2,0x008ec711c5b1a1a8,0x00cf663301237f98,0x00917ee3f1655126,0x004152f337efedd8)}, + {FIELD_LITERAL(0x0007c7edc9305daa,0x000a6664f273701c,0x00f6e78795e200b1,0x005d05b9ecd2473e,0x0014f5f17c865786,0x00c7fd2d166fa995,0x004939a2d8eb80e0,0x002244ba0942c199)}, + }}, {{ + {FIELD_LITERAL(0x00321e767f0262cf,0x002e57d776caf68e,0x00bf2c94814f0437,0x00c339196acd622f,0x001db4cce71e2770,0x001ded5ddba6eee2,0x0078608ab1554c8d,0x00067fe0ab76365b)}, + {FIELD_LITERAL(0x00f09758e11e3985,0x00169efdbd64fad3,0x00e8889b7d6dacd6,0x0035cdd58ea88209,0x00bcda47586d7f49,0x003cdddcb2879088,0x0016da70187e954b,0x009556ea2e92aacd)}, + {FIELD_LITERAL(0x008cab16bd1ff897,0x00b389972cdf753f,0x00ea8ed1e46dfdc0,0x004fe7ef94c589f4,0x002b8ae9b805ecf3,0x0025c08d892874a5,0x0023938e98d44c4c,0x00f759134cabf69c)}, + }}, {{ + {FIELD_LITERAL(0x006c2a84678e4b3b,0x007a194aacd1868f,0x00ed0225af424761,0x00da0a6f293c64b8,0x001062ac5c6a7a18,0x0030f5775a8aeef4,0x0002acaad76b7af0,0x00410b8fd63a579f)}, + {FIELD_LITERAL(0x001ec59db3d9590e,0x001e9e3f1c3f182d,0x0045a9c3ec2cab14,0x0008198572aeb673,0x00773b74068bd167,0x0012535eaa395434,0x0044dba9e3bbb74a,0x002fba4d3c74bd0e)}, + {FIELD_LITERAL(0x0042bf08fe66922c,0x003318b8fbb49e8c,0x00d75946004aa14c,0x00f601586b42bf1c,0x00c74cf1d912fe66,0x00abcb36974b30ad,0x007eb78720c9d2b8,0x009f54ab7bd4df85)}, + }}, {{ + {FIELD_LITERAL(0x00db9fc948f73826,0x00fa8b3746ed8ee9,0x00132cb65aafbeb2,0x00c36ff3fe7925b8,0x00837daed353d2fe,0x00ec661be0667cf4,0x005beb8ed2e90204,0x00d77dd69e564967)}, + {FIELD_LITERAL(0x0042e6268b861751,0x0008dd0469500c16,0x00b51b57c338a3fd,0x00cc4497d85cff6b,0x002f13d6b57c34a4,0x0083652eaf301105,0x00cc344294cc93a8,0x0060f4d02810e270)}, + {FIELD_LITERAL(0x00a8954363cd518b,0x00ad171124bccb7b,0x0065f46a4adaae00,0x001b1a5b2a96e500,0x0043fe24f8233285,0x0066996d8ae1f2c3,0x00c530f3264169f9,0x00c0f92d07cf6a57)}, + }}, {{ + {FIELD_LITERAL(0x0036a55c6815d943,0x008c8d1def993db3,0x002e0e1e8ff7318f,0x00d883a4b92db00a,0x002f5e781ae33906,0x001a72adb235c06d,0x00f2e59e736e9caa,0x001a4b58e3031914)}, + {FIELD_LITERAL(0x00d73bfae5e00844,0x00bf459766fb5f52,0x0061b4f5a5313cde,0x004392d4c3b95514,0x000d3551b1077523,0x0000998840ee5d71,0x006de6e340448b7b,0x00251aa504875d6e)}, + {FIELD_LITERAL(0x003bf343427ac342,0x00adc0a78642b8c5,0x0003b893175a8314,0x0061a34ade5703bc,0x00ea3ea8bb71d632,0x00be0df9a1f198c2,0x0046dd8e7c1635fb,0x00f1523fdd25d5e5)}, + }}, {{ + {FIELD_LITERAL(0x00633f63fc9dd406,0x00e713ff80e04a43,0x0060c6e970f2d621,0x00a57cd7f0df1891,0x00f2406a550650bb,0x00b064290efdc684,0x001eab0144d17916,0x00cd15f863c293ab)}, + {FIELD_LITERAL(0x0029cec55273f70d,0x007044ee275c6340,0x0040f637a93015e2,0x00338bb78db5aae9,0x001491b2a6132147,0x00a125d6cfe6bde3,0x005f7ac561ba8669,0x001d5eaea3fbaacf)}, + {FIELD_LITERAL(0x00054e9635e3be31,0x000e43f31e2872be,0x00d05b1c9e339841,0x006fac50bd81fd98,0x00cdc7852eaebb09,0x004ff519b061991b,0x009099e8107d4c85,0x00273e24c36a4a61)}, + }}, {{ + {FIELD_LITERAL(0x00070b4441ef2c46,0x00efa5b02801a109,0x00bf0b8c3ee64adf,0x008a67e0b3452e98,0x001916b1f2fa7a74,0x00d781a78ff6cdc3,0x008682ce57e5c919,0x00cc1109dd210da3)}, + {FIELD_LITERAL(0x00cae8aaff388663,0x005e983a35dda1c7,0x007ab1030d8e37f4,0x00e48940f5d032fe,0x006a36f9ef30b331,0x009be6f03958c757,0x0086231ceba91400,0x008bd0f7b823e7aa)}, + {FIELD_LITERAL(0x00cf881ebef5a45a,0x004ebea78e7c6f2c,0x0090da9209cf26a0,0x00de2b2e4c775b84,0x0071d6031c3c15ae,0x00d9e927ef177d70,0x00894ee8c23896fd,0x00e3b3b401e41aad)}, + }}, {{ + {FIELD_LITERAL(0x00204fef26864170,0x00819269c5dee0f8,0x00bfb4713ec97966,0x0026339a6f34df78,0x001f26e64c761dc2,0x00effe3af313cb60,0x00e17b70138f601b,0x00f16e1ccd9ede5e)}, + {FIELD_LITERAL(0x005d9a8353fdb2db,0x0055cc2048c698f0,0x00f6c4ac89657218,0x00525034d73faeb2,0x00435776fbda3c7d,0x0070ea5312323cbc,0x007a105d44d069fb,0x006dbc8d6dc786aa)}, + {FIELD_LITERAL(0x0017cff19cd394ec,0x00fef7b810922587,0x00e6483970dff548,0x00ddf36ad6874264,0x00e61778523fcce2,0x0093a66c0c93b24a,0x00fd367114db7f86,0x007652d7ddce26dd)}, + }}, {{ + {FIELD_LITERAL(0x00d92ced7ba12843,0x00aea9c7771e86e7,0x0046639693354f7b,0x00a628dbb6a80c47,0x003a0b0507372953,0x00421113ab45c0d9,0x00e545f08362ab7a,0x0028ce087b4d6d96)}, + {FIELD_LITERAL(0x00a67ee7cf9f99eb,0x005713b275f2ff68,0x00f1d536a841513d,0x00823b59b024712e,0x009c46b9d0d38cec,0x00cdb1595aa2d7d4,0x008375b3423d9af8,0x000ab0b516d978f7)}, + {FIELD_LITERAL(0x00428dcb3c510b0f,0x00585607ea24bb4e,0x003736bf1603687a,0x00c47e568c4fe3c7,0x003cd00282848605,0x0043a487c3b91939,0x004ffc04e1095a06,0x00a4c989a3d4b918)}, + }}, {{ + {FIELD_LITERAL(0x00a8778d0e429f7a,0x004c02b059105a68,0x0016653b609da3ff,0x00d5107bd1a12d27,0x00b4708f9a771cab,0x00bb63b662033f69,0x0072f322240e7215,0x0019445b59c69222)}, + {FIELD_LITERAL(0x00cf4f6069a658e6,0x0053ca52859436a6,0x0064b994d7e3e117,0x00cb469b9a07f534,0x00cfb68f399e9d47,0x00f0dcb8dac1c6e7,0x00f2ab67f538b3a5,0x0055544f178ab975)}, + {FIELD_LITERAL(0x0099b7a2685d538c,0x00e2f1897b7c0018,0x003adac8ce48dae3,0x00089276d5c50c0c,0x00172fca07ad6717,0x00cb1a72f54069e5,0x004ee42f133545b3,0x00785f8651362f16)}, + }}, {{ + {FIELD_LITERAL(0x0049cbac38509e11,0x0015234505d42cdf,0x00794fb0b5840f1c,0x00496437344045a5,0x0031b6d944e4f9b0,0x00b207318ac1f5d8,0x0000c840da7f5c5d,0x00526f373a5c8814)}, + {FIELD_LITERAL(0x002c7b7742d1dfd9,0x002cabeb18623c01,0x00055f5e3e044446,0x006c20f3b4ef54ba,0x00c600141ec6b35f,0x00354f437f1a32a3,0x00bac4624a3520f9,0x00c483f734a90691)}, + {FIELD_LITERAL(0x0053a737d422918d,0x00f7fca1d8758625,0x00c360336dadb04c,0x00f38e3d9158a1b8,0x0069ce3b418e84c6,0x005d1697eca16ead,0x00f8bd6a35ece13d,0x007885dfc2b5afea)}, + }}, {{ + {FIELD_LITERAL(0x00c3617ae260776c,0x00b20dc3e96922d7,0x00a1a7802246706a,0x00ca6505a5240244,0x002246b62d919782,0x001439102d7aa9b3,0x00e8af1139e6422c,0x00c888d1b52f2b05)}, + {FIELD_LITERAL(0x005b67690ffd41d9,0x005294f28df516f9,0x00a879272412fcb9,0x00098b629a6d1c8d,0x00fabd3c8050865a,0x00cd7e5b0a3879c5,0x00153238210f3423,0x00357cac101e9f42)}, + {FIELD_LITERAL(0x008917b454444fb7,0x00f59247c97e441b,0x00a6200a6815152d,0x0009a4228601d254,0x001c0360559bd374,0x007563362039cb36,0x00bd75b48d74e32b,0x0017f515ac3499e8)}, + }}, {{ + {FIELD_LITERAL(0x001532a7ffe41c5a,0x00eb1edce358d6bf,0x00ddbacc7b678a7b,0x008a7b70f3c841a3,0x00f1923bf27d3f4c,0x000b2713ed8f7873,0x00aaf67e29047902,0x0044994a70b3976d)}, + {FIELD_LITERAL(0x00d54e802082d42c,0x00a55aa0dce7cc6c,0x006477b96073f146,0x0082efe4ceb43594,0x00a922bcba026845,0x0077f19d1ab75182,0x00c2bb2737846e59,0x0004d7eec791dd33)}, + {FIELD_LITERAL(0x0044588d1a81d680,0x00b0a9097208e4f8,0x00212605350dc57e,0x0028717cd2871123,0x00fb083c100fd979,0x0045a056ce063fdf,0x00a5d604b4dd6a41,0x001dabc08ba4e236)}, + }}, {{ + {FIELD_LITERAL(0x00c4887198d7a7fa,0x00244f98fb45784a,0x0045911e15a15d01,0x001d323d374c0966,0x00967c3915196562,0x0039373abd2f3c67,0x000d2c5614312423,0x0041cf2215442ce3)}, + {FIELD_LITERAL(0x008ede889ada7f06,0x001611e91de2e135,0x00fdb9a458a471b9,0x00563484e03710d1,0x0031cc81925e3070,0x0062c97b3af80005,0x00fa733eea28edeb,0x00e82457e1ebbc88)}, + {FIELD_LITERAL(0x006a0df5fe9b6f59,0x00a0d4ff46040d92,0x004a7cedb6f93250,0x00d1df8855b8c357,0x00e73a46086fd058,0x0048fb0add6dfe59,0x001e03a28f1b4e3d,0x00a871c993308d76)}, + }}, {{ + {FIELD_LITERAL(0x0030dbb2d1766ec8,0x00586c0ad138555e,0x00d1a34f9e91c77c,0x0063408ad0e89014,0x00d61231b05f6f5b,0x0009abf569f5fd8a,0x00aec67a110f1c43,0x0031d1a790938dd7)}, + {FIELD_LITERAL(0x006cded841e2a862,0x00198d60af0ab6fb,0x0018f09db809e750,0x004e6ac676016263,0x00eafcd1620969cb,0x002c9784ca34917d,0x0054f00079796de7,0x00d9fab5c5972204)}, + {FIELD_LITERAL(0x004bd0fee2438a83,0x00b571e62b0f83bd,0x0059287d7ce74800,0x00fb3631b645c3f0,0x00a018e977f78494,0x0091e27065c27b12,0x007696c1817165e0,0x008c40be7c45ba3a)}, + }}, {{ + {FIELD_LITERAL(0x00a0f326327cb684,0x001c7d0f672680ff,0x008c1c81ffb112d1,0x00f8f801674eddc8,0x00e926d5d48c2a9d,0x005bd6d954c6fe9a,0x004c6b24b4e33703,0x00d05eb5c09105cc)}, + {FIELD_LITERAL(0x00d61731caacf2cf,0x002df0c7609e01c5,0x00306172208b1e2b,0x00b413fe4fb2b686,0x00826d360902a221,0x003f8d056e67e7f7,0x0065025b0175e989,0x00369add117865eb)}, + {FIELD_LITERAL(0x00aaf895aec2fa11,0x000f892bc313eb52,0x005b1c794dad050b,0x003f8ec4864cec14,0x00af81058d0b90e5,0x00ebe43e183997bb,0x00a9d610f9f3e615,0x007acd8eec2e88d3)}, + }}, {{ + {FIELD_LITERAL(0x0049b2fab13812a3,0x00846db32cd60431,0x000177fa578c8d6c,0x00047d0e2ad4bc51,0x00b158ba38d1e588,0x006a45daad79e3f3,0x000997b93cab887b,0x00c47ea42fa23dc3)}, + {FIELD_LITERAL(0x0012b6fef7aeb1ca,0x009412768194b6a7,0x00ff0d351f23ab93,0x007e8a14c1aff71b,0x006c1c0170c512bc,0x0016243ea02ab2e5,0x007bb6865b303f3e,0x0015ce6b29b159f4)}, + {FIELD_LITERAL(0x009961cd02e68108,0x00e2035d3a1d0836,0x005d51f69b5e1a1d,0x004bccb4ea36edcd,0x0069be6a7aeef268,0x0063f4dd9de8d5a7,0x006283783092ca35,0x0075a31af2c35409)}, + }}, {{ + {FIELD_LITERAL(0x00c412365162e8cf,0x00012283fb34388a,0x003e6543babf39e2,0x00eead6b3a804978,0x0099c0314e8b326f,0x00e98e0a8d477a4f,0x00d2eb96b127a687,0x00ed8d7df87571bb)}, + {FIELD_LITERAL(0x00777463e308cacf,0x00c8acb93950132d,0x00ebddbf4ca48b2c,0x0026ad7ca0795a0a,0x00f99a3d9a715064,0x000d60bcf9d4dfcc,0x005e65a73a437a06,0x0019d536a8db56c8)}, + {FIELD_LITERAL(0x00192d7dd558d135,0x0027cd6a8323ffa7,0x00239f1a412dc1e7,0x0046b4b3be74fc5c,0x0020c47a2bef5bce,0x00aa17e48f43862b,0x00f7e26c96342e5f,0x0008011c530f39a9)}, + }}, {{ + {FIELD_LITERAL(0x00aad4ac569bf0f1,0x00a67adc90b27740,0x0048551369a5751a,0x0031252584a3306a,0x0084e15df770e6fc,0x00d7bba1c74b5805,0x00a80ef223af1012,0x0089c85ceb843a34)}, + {FIELD_LITERAL(0x00c4545be4a54004,0x0099e11f60357e6c,0x001f3936d19515a6,0x007793df84341a6e,0x0051061886717ffa,0x00e9b0a660b28f85,0x0044ea685892de0d,0x000257d2a1fda9d9)}, + {FIELD_LITERAL(0x007e8b01b24ac8a8,0x006cf3b0b5ca1337,0x00f1607d3e36a570,0x0039b7fab82991a1,0x00231777065840c5,0x00998e5afdd346f9,0x00b7dc3e64acc85f,0x00baacc748013ad6)}, + }}, {{ + {FIELD_LITERAL(0x008ea6a4177580bf,0x005fa1953e3f0378,0x005fe409ac74d614,0x00452327f477e047,0x00a4018507fb6073,0x007b6e71951caac8,0x0012b42ab8a6ce91,0x0080eca677294ab7)}, + {FIELD_LITERAL(0x00a53edc023ba69b,0x00c6afa83ddde2e8,0x00c3f638b307b14e,0x004a357a64414062,0x00e4d94d8b582dc9,0x001739caf71695b7,0x0012431b2ae28de1,0x003b6bc98682907c)}, + {FIELD_LITERAL(0x008a9a93be1f99d6,0x0079fa627cc699c8,0x00b0cfb134ba84c8,0x001c4b778249419a,0x00df4ab3d9c44f40,0x009f596e6c1a9e3c,0x001979c0df237316,0x00501e953a919b87)}, + }} +}; +const niels_t *curve448_wnaf_base = curve448_wnaf_base_table; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/curve448utils.h b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/curve448utils.h new file mode 100644 index 000000000..9bf837993 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/curve448utils.h @@ -0,0 +1,78 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015 Cryptography Research, Inc. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + * + * Originally written by Mike Hamburg + */ + +#ifndef HEADER_CURVE448UTILS_H +# define HEADER_CURVE448UTILS_H + +# include + +/* + * Internal word types. Somewhat tricky. This could be decided separately per + * platform. However, the structs do need to be all the same size and + * alignment on a given platform to support dynamic linking, since even if you + * header was built with eg arch_neon, you might end up linking a library built + * with arch_arm32. + */ +# ifndef C448_WORD_BITS +# if (defined(__SIZEOF_INT128__) && (__SIZEOF_INT128__ == 16)) \ + && !defined(__sparc__) +# define C448_WORD_BITS 64 /* The number of bits in a word */ +# else +# define C448_WORD_BITS 32 /* The number of bits in a word */ +# endif +# endif + +# if C448_WORD_BITS == 64 +/* Word size for internal computations */ +typedef uint64_t c448_word_t; +/* Signed word size for internal computations */ +typedef int64_t c448_sword_t; +/* "Boolean" type, will be set to all-zero or all-one (i.e. -1u) */ +typedef uint64_t c448_bool_t; +/* Double-word size for internal computations */ +typedef __uint128_t c448_dword_t; +/* Signed double-word size for internal computations */ +typedef __int128_t c448_dsword_t; +# elif C448_WORD_BITS == 32 +/* Word size for internal computations */ +typedef uint32_t c448_word_t; +/* Signed word size for internal computations */ +typedef int32_t c448_sword_t; +/* "Boolean" type, will be set to all-zero or all-one (i.e. -1u) */ +typedef uint32_t c448_bool_t; +/* Double-word size for internal computations */ +typedef uint64_t c448_dword_t; +/* Signed double-word size for internal computations */ +typedef int64_t c448_dsword_t; +# else +# error "Only supporting C448_WORD_BITS = 32 or 64 for now" +# endif + +/* C448_TRUE = -1 so that C448_TRUE & x = x */ +# define C448_TRUE (0 - (c448_bool_t)1) + +/* C448_FALSE = 0 so that C448_FALSE & x = 0 */ +# define C448_FALSE 0 + +/* Another boolean type used to indicate success or failure. */ +typedef enum { + C448_SUCCESS = -1, /**< The operation succeeded. */ + C448_FAILURE = 0 /**< The operation failed. */ +} c448_error_t; + +/* Return success if x is true */ +static ossl_inline c448_error_t c448_succeed_if(c448_bool_t x) +{ + return (c448_error_t) x; +} + +#endif /* __C448_COMMON_H__ */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/ed448.h b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/ed448.h new file mode 100644 index 000000000..5fe939e8e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/ed448.h @@ -0,0 +1,195 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2016 Cryptography Research, Inc. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + * + * Originally written by Mike Hamburg + */ + +#ifndef HEADER_ED448_H +# define HEADER_ED448_H + +# include "point_448.h" + +/* Number of bytes in an EdDSA public key. */ +# define EDDSA_448_PUBLIC_BYTES 57 + +/* Number of bytes in an EdDSA private key. */ +# define EDDSA_448_PRIVATE_BYTES EDDSA_448_PUBLIC_BYTES + +/* Number of bytes in an EdDSA private key. */ +# define EDDSA_448_SIGNATURE_BYTES (EDDSA_448_PUBLIC_BYTES + \ + EDDSA_448_PRIVATE_BYTES) + +/* EdDSA encoding ratio. */ +# define C448_EDDSA_ENCODE_RATIO 4 + +/* EdDSA decoding ratio. */ +# define C448_EDDSA_DECODE_RATIO (4 / 4) + +/* + * EdDSA key generation. This function uses a different (non-Decaf) encoding. + * + * pubkey (out): The public key. + * privkey (in): The private key. + */ +c448_error_t c448_ed448_derive_public_key( + uint8_t pubkey [EDDSA_448_PUBLIC_BYTES], + const uint8_t privkey [EDDSA_448_PRIVATE_BYTES]); + +/* + * EdDSA signing. + * + * signature (out): The signature. + * privkey (in): The private key. + * pubkey (in): The public key. + * message (in): The message to sign. + * message_len (in): The length of the message. + * prehashed (in): Nonzero if the message is actually the hash of something + * you want to sign. + * context (in): A "context" for this signature of up to 255 bytes. + * context_len (in): Length of the context. + * + * For Ed25519, it is unsafe to use the same key for both prehashed and + * non-prehashed messages, at least without some very careful protocol-level + * disambiguation. For Ed448 it is safe. + */ +c448_error_t c448_ed448_sign( + uint8_t signature[EDDSA_448_SIGNATURE_BYTES], + const uint8_t privkey[EDDSA_448_PRIVATE_BYTES], + const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES], + const uint8_t *message, size_t message_len, + uint8_t prehashed, const uint8_t *context, + size_t context_len); + +/* + * EdDSA signing with prehash. + * + * signature (out): The signature. + * privkey (in): The private key. + * pubkey (in): The public key. + * hash (in): The hash of the message. This object will not be modified by the + * call. + * context (in): A "context" for this signature of up to 255 bytes. Must be the + * same as what was used for the prehash. + * context_len (in): Length of the context. + * + * For Ed25519, it is unsafe to use the same key for both prehashed and + * non-prehashed messages, at least without some very careful protocol-level + * disambiguation. For Ed448 it is safe. + */ +c448_error_t c448_ed448_sign_prehash( + uint8_t signature[EDDSA_448_SIGNATURE_BYTES], + const uint8_t privkey[EDDSA_448_PRIVATE_BYTES], + const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES], + const uint8_t hash[64], + const uint8_t *context, + size_t context_len); + +/* + * EdDSA signature verification. + * + * Uses the standard (i.e. less-strict) verification formula. + * + * signature (in): The signature. + * pubkey (in): The public key. + * message (in): The message to verify. + * message_len (in): The length of the message. + * prehashed (in): Nonzero if the message is actually the hash of something you + * want to verify. + * context (in): A "context" for this signature of up to 255 bytes. + * context_len (in): Length of the context. + * + * For Ed25519, it is unsafe to use the same key for both prehashed and + * non-prehashed messages, at least without some very careful protocol-level + * disambiguation. For Ed448 it is safe. + */ +c448_error_t c448_ed448_verify(const uint8_t + signature[EDDSA_448_SIGNATURE_BYTES], + const uint8_t + pubkey[EDDSA_448_PUBLIC_BYTES], + const uint8_t *message, size_t message_len, + uint8_t prehashed, const uint8_t *context, + uint8_t context_len); + +/* + * EdDSA signature verification. + * + * Uses the standard (i.e. less-strict) verification formula. + * + * signature (in): The signature. + * pubkey (in): The public key. + * hash (in): The hash of the message. This object will not be modified by the + * call. + * context (in): A "context" for this signature of up to 255 bytes. Must be the + * same as what was used for the prehash. + * context_len (in): Length of the context. + * + * For Ed25519, it is unsafe to use the same key for both prehashed and + * non-prehashed messages, at least without some very careful protocol-level + * disambiguation. For Ed448 it is safe. + */ +c448_error_t c448_ed448_verify_prehash( + const uint8_t signature[EDDSA_448_SIGNATURE_BYTES], + const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES], + const uint8_t hash[64], + const uint8_t *context, + uint8_t context_len); + +/* + * EdDSA point encoding. Used internally, exposed externally. + * Multiplies by C448_EDDSA_ENCODE_RATIO first. + * + * The multiplication is required because the EdDSA encoding represents + * the cofactor information, but the Decaf encoding ignores it (which + * is the whole point). So if you decode from EdDSA and re-encode to + * EdDSA, the cofactor info must get cleared, because the intermediate + * representation doesn't track it. + * + * The way we handle this is to multiply by C448_EDDSA_DECODE_RATIO when + * decoding, and by C448_EDDSA_ENCODE_RATIO when encoding. The product of + * these ratios is always exactly the cofactor 4, so the cofactor ends up + * cleared one way or another. But exactly how that shakes out depends on the + * base points specified in RFC 8032. + * + * The upshot is that if you pass the Decaf/Ristretto base point to + * this function, you will get C448_EDDSA_ENCODE_RATIO times the + * EdDSA base point. + * + * enc (out): The encoded point. + * p (in): The point. + */ +void curve448_point_mul_by_ratio_and_encode_like_eddsa( + uint8_t enc [EDDSA_448_PUBLIC_BYTES], + const curve448_point_t p); + +/* + * EdDSA point decoding. Multiplies by C448_EDDSA_DECODE_RATIO, and + * ignores cofactor information. + * + * See notes on curve448_point_mul_by_ratio_and_encode_like_eddsa + * + * enc (out): The encoded point. + * p (in): The point. + */ +c448_error_t curve448_point_decode_like_eddsa_and_mul_by_ratio( + curve448_point_t p, + const uint8_t enc[EDDSA_448_PUBLIC_BYTES]); + +/* + * EdDSA to ECDH private key conversion + * Using the appropriate hash function, hash the EdDSA private key + * and keep only the lower bytes to get the ECDH private key + * + * x (out): The ECDH private key as in RFC7748 + * ed (in): The EdDSA private key + */ +c448_error_t c448_ed448_convert_private_key_to_x448( + uint8_t x[X448_PRIVATE_BYTES], + const uint8_t ed[EDDSA_448_PRIVATE_BYTES]); + +#endif /* HEADER_ED448_H */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/eddsa.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/eddsa.c new file mode 100644 index 000000000..b28f7dff9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/eddsa.c @@ -0,0 +1,372 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2016 Cryptography Research, Inc. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + * + * Originally written by Mike Hamburg + */ +#include +#include +#include +#include "curve448_lcl.h" +#include "word.h" +#include "ed448.h" +#include "internal/numbers.h" + +#define COFACTOR 4 + +static c448_error_t oneshot_hash(uint8_t *out, size_t outlen, + const uint8_t *in, size_t inlen) +{ + EVP_MD_CTX *hashctx = EVP_MD_CTX_new(); + + if (hashctx == NULL) + return C448_FAILURE; + + if (!EVP_DigestInit_ex(hashctx, EVP_shake256(), NULL) + || !EVP_DigestUpdate(hashctx, in, inlen) + || !EVP_DigestFinalXOF(hashctx, out, outlen)) { + EVP_MD_CTX_free(hashctx); + return C448_FAILURE; + } + + EVP_MD_CTX_free(hashctx); + return C448_SUCCESS; +} + +static void clamp(uint8_t secret_scalar_ser[EDDSA_448_PRIVATE_BYTES]) +{ + secret_scalar_ser[0] &= -COFACTOR; + secret_scalar_ser[EDDSA_448_PRIVATE_BYTES - 1] = 0; + secret_scalar_ser[EDDSA_448_PRIVATE_BYTES - 2] |= 0x80; +} + +static c448_error_t hash_init_with_dom(EVP_MD_CTX *hashctx, uint8_t prehashed, + uint8_t for_prehash, + const uint8_t *context, + size_t context_len) +{ + const char *dom_s = "SigEd448"; + uint8_t dom[2]; + + if (context_len > UINT8_MAX) + return C448_FAILURE; + + dom[0] = (uint8_t)(2 - (prehashed == 0 ? 1 : 0) + - (for_prehash == 0 ? 1 : 0)); + dom[1] = (uint8_t)context_len; + + if (!EVP_DigestInit_ex(hashctx, EVP_shake256(), NULL) + || !EVP_DigestUpdate(hashctx, dom_s, strlen(dom_s)) + || !EVP_DigestUpdate(hashctx, dom, sizeof(dom)) + || !EVP_DigestUpdate(hashctx, context, context_len)) + return C448_FAILURE; + + return C448_SUCCESS; +} + +/* In this file because it uses the hash */ +c448_error_t c448_ed448_convert_private_key_to_x448( + uint8_t x[X448_PRIVATE_BYTES], + const uint8_t ed [EDDSA_448_PRIVATE_BYTES]) +{ + /* pass the private key through oneshot_hash function */ + /* and keep the first X448_PRIVATE_BYTES bytes */ + return oneshot_hash(x, X448_PRIVATE_BYTES, ed, + EDDSA_448_PRIVATE_BYTES); +} + +c448_error_t c448_ed448_derive_public_key( + uint8_t pubkey[EDDSA_448_PUBLIC_BYTES], + const uint8_t privkey[EDDSA_448_PRIVATE_BYTES]) +{ + /* only this much used for keygen */ + uint8_t secret_scalar_ser[EDDSA_448_PRIVATE_BYTES]; + curve448_scalar_t secret_scalar; + unsigned int c; + curve448_point_t p; + + if (!oneshot_hash(secret_scalar_ser, sizeof(secret_scalar_ser), privkey, + EDDSA_448_PRIVATE_BYTES)) + return C448_FAILURE; + + clamp(secret_scalar_ser); + + curve448_scalar_decode_long(secret_scalar, secret_scalar_ser, + sizeof(secret_scalar_ser)); + + /* + * Since we are going to mul_by_cofactor during encoding, divide by it + * here. However, the EdDSA base point is not the same as the decaf base + * point if the sigma isogeny is in use: the EdDSA base point is on + * Etwist_d/(1-d) and the decaf base point is on Etwist_d, and when + * converted it effectively picks up a factor of 2 from the isogenies. So + * we might start at 2 instead of 1. + */ + for (c = 1; c < C448_EDDSA_ENCODE_RATIO; c <<= 1) + curve448_scalar_halve(secret_scalar, secret_scalar); + + curve448_precomputed_scalarmul(p, curve448_precomputed_base, secret_scalar); + + curve448_point_mul_by_ratio_and_encode_like_eddsa(pubkey, p); + + /* Cleanup */ + curve448_scalar_destroy(secret_scalar); + curve448_point_destroy(p); + OPENSSL_cleanse(secret_scalar_ser, sizeof(secret_scalar_ser)); + + return C448_SUCCESS; +} + +c448_error_t c448_ed448_sign( + uint8_t signature[EDDSA_448_SIGNATURE_BYTES], + const uint8_t privkey[EDDSA_448_PRIVATE_BYTES], + const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES], + const uint8_t *message, size_t message_len, + uint8_t prehashed, const uint8_t *context, + size_t context_len) +{ + curve448_scalar_t secret_scalar; + EVP_MD_CTX *hashctx = EVP_MD_CTX_new(); + c448_error_t ret = C448_FAILURE; + curve448_scalar_t nonce_scalar; + uint8_t nonce_point[EDDSA_448_PUBLIC_BYTES] = { 0 }; + unsigned int c; + curve448_scalar_t challenge_scalar; + + if (hashctx == NULL) + return C448_FAILURE; + + { + /* + * Schedule the secret key, First EDDSA_448_PRIVATE_BYTES is serialised + * secret scalar,next EDDSA_448_PRIVATE_BYTES bytes is the seed. + */ + uint8_t expanded[EDDSA_448_PRIVATE_BYTES * 2]; + + if (!oneshot_hash(expanded, sizeof(expanded), privkey, + EDDSA_448_PRIVATE_BYTES)) + goto err; + clamp(expanded); + curve448_scalar_decode_long(secret_scalar, expanded, + EDDSA_448_PRIVATE_BYTES); + + /* Hash to create the nonce */ + if (!hash_init_with_dom(hashctx, prehashed, 0, context, context_len) + || !EVP_DigestUpdate(hashctx, + expanded + EDDSA_448_PRIVATE_BYTES, + EDDSA_448_PRIVATE_BYTES) + || !EVP_DigestUpdate(hashctx, message, message_len)) { + OPENSSL_cleanse(expanded, sizeof(expanded)); + goto err; + } + OPENSSL_cleanse(expanded, sizeof(expanded)); + } + + /* Decode the nonce */ + { + uint8_t nonce[2 * EDDSA_448_PRIVATE_BYTES]; + + if (!EVP_DigestFinalXOF(hashctx, nonce, sizeof(nonce))) + goto err; + curve448_scalar_decode_long(nonce_scalar, nonce, sizeof(nonce)); + OPENSSL_cleanse(nonce, sizeof(nonce)); + } + + { + /* Scalarmul to create the nonce-point */ + curve448_scalar_t nonce_scalar_2; + curve448_point_t p; + + curve448_scalar_halve(nonce_scalar_2, nonce_scalar); + for (c = 2; c < C448_EDDSA_ENCODE_RATIO; c <<= 1) + curve448_scalar_halve(nonce_scalar_2, nonce_scalar_2); + + curve448_precomputed_scalarmul(p, curve448_precomputed_base, + nonce_scalar_2); + curve448_point_mul_by_ratio_and_encode_like_eddsa(nonce_point, p); + curve448_point_destroy(p); + curve448_scalar_destroy(nonce_scalar_2); + } + + { + uint8_t challenge[2 * EDDSA_448_PRIVATE_BYTES]; + + /* Compute the challenge */ + if (!hash_init_with_dom(hashctx, prehashed, 0, context, context_len) + || !EVP_DigestUpdate(hashctx, nonce_point, sizeof(nonce_point)) + || !EVP_DigestUpdate(hashctx, pubkey, EDDSA_448_PUBLIC_BYTES) + || !EVP_DigestUpdate(hashctx, message, message_len) + || !EVP_DigestFinalXOF(hashctx, challenge, sizeof(challenge))) + goto err; + + curve448_scalar_decode_long(challenge_scalar, challenge, + sizeof(challenge)); + OPENSSL_cleanse(challenge, sizeof(challenge)); + } + + curve448_scalar_mul(challenge_scalar, challenge_scalar, secret_scalar); + curve448_scalar_add(challenge_scalar, challenge_scalar, nonce_scalar); + + OPENSSL_cleanse(signature, EDDSA_448_SIGNATURE_BYTES); + memcpy(signature, nonce_point, sizeof(nonce_point)); + curve448_scalar_encode(&signature[EDDSA_448_PUBLIC_BYTES], + challenge_scalar); + + curve448_scalar_destroy(secret_scalar); + curve448_scalar_destroy(nonce_scalar); + curve448_scalar_destroy(challenge_scalar); + + ret = C448_SUCCESS; + err: + EVP_MD_CTX_free(hashctx); + return ret; +} + +c448_error_t c448_ed448_sign_prehash( + uint8_t signature[EDDSA_448_SIGNATURE_BYTES], + const uint8_t privkey[EDDSA_448_PRIVATE_BYTES], + const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES], + const uint8_t hash[64], const uint8_t *context, + size_t context_len) +{ + return c448_ed448_sign(signature, privkey, pubkey, hash, 64, 1, context, + context_len); +} + +c448_error_t c448_ed448_verify( + const uint8_t signature[EDDSA_448_SIGNATURE_BYTES], + const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES], + const uint8_t *message, size_t message_len, + uint8_t prehashed, const uint8_t *context, + uint8_t context_len) +{ + curve448_point_t pk_point, r_point; + c448_error_t error; + curve448_scalar_t challenge_scalar; + curve448_scalar_t response_scalar; + /* Order in little endian format */ + static const uint8_t order[] = { + 0xF3, 0x44, 0x58, 0xAB, 0x92, 0xC2, 0x78, 0x23, 0x55, 0x8F, 0xC5, 0x8D, + 0x72, 0xC2, 0x6C, 0x21, 0x90, 0x36, 0xD6, 0xAE, 0x49, 0xDB, 0x4E, 0xC4, + 0xE9, 0x23, 0xCA, 0x7C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00 + }; + int i; + + /* + * Check that s (second 57 bytes of the sig) is less than the order. Both + * s and the order are in little-endian format. This can be done in + * variable time, since if this is not the case the signature if publicly + * invalid. + */ + for (i = EDDSA_448_PUBLIC_BYTES - 1; i >= 0; i--) { + if (signature[i + EDDSA_448_PUBLIC_BYTES] > order[i]) + return C448_FAILURE; + if (signature[i + EDDSA_448_PUBLIC_BYTES] < order[i]) + break; + } + if (i < 0) + return C448_FAILURE; + + error = + curve448_point_decode_like_eddsa_and_mul_by_ratio(pk_point, pubkey); + + if (C448_SUCCESS != error) + return error; + + error = + curve448_point_decode_like_eddsa_and_mul_by_ratio(r_point, signature); + if (C448_SUCCESS != error) + return error; + + { + /* Compute the challenge */ + EVP_MD_CTX *hashctx = EVP_MD_CTX_new(); + uint8_t challenge[2 * EDDSA_448_PRIVATE_BYTES]; + + if (hashctx == NULL + || !hash_init_with_dom(hashctx, prehashed, 0, context, + context_len) + || !EVP_DigestUpdate(hashctx, signature, EDDSA_448_PUBLIC_BYTES) + || !EVP_DigestUpdate(hashctx, pubkey, EDDSA_448_PUBLIC_BYTES) + || !EVP_DigestUpdate(hashctx, message, message_len) + || !EVP_DigestFinalXOF(hashctx, challenge, sizeof(challenge))) { + EVP_MD_CTX_free(hashctx); + return C448_FAILURE; + } + + EVP_MD_CTX_free(hashctx); + curve448_scalar_decode_long(challenge_scalar, challenge, + sizeof(challenge)); + OPENSSL_cleanse(challenge, sizeof(challenge)); + } + curve448_scalar_sub(challenge_scalar, curve448_scalar_zero, + challenge_scalar); + + curve448_scalar_decode_long(response_scalar, + &signature[EDDSA_448_PUBLIC_BYTES], + EDDSA_448_PRIVATE_BYTES); + + /* pk_point = -c(x(P)) + (cx + k)G = kG */ + curve448_base_double_scalarmul_non_secret(pk_point, + response_scalar, + pk_point, challenge_scalar); + return c448_succeed_if(curve448_point_eq(pk_point, r_point)); +} + +c448_error_t c448_ed448_verify_prehash( + const uint8_t signature[EDDSA_448_SIGNATURE_BYTES], + const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES], + const uint8_t hash[64], const uint8_t *context, + uint8_t context_len) +{ + return c448_ed448_verify(signature, pubkey, hash, 64, 1, context, + context_len); +} + +int ED448_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len, + const uint8_t public_key[57], const uint8_t private_key[57], + const uint8_t *context, size_t context_len) +{ + return c448_ed448_sign(out_sig, private_key, public_key, message, + message_len, 0, context, context_len) + == C448_SUCCESS; +} + +int ED448_verify(const uint8_t *message, size_t message_len, + const uint8_t signature[114], const uint8_t public_key[57], + const uint8_t *context, size_t context_len) +{ + return c448_ed448_verify(signature, public_key, message, message_len, 0, + context, (uint8_t)context_len) == C448_SUCCESS; +} + +int ED448ph_sign(uint8_t *out_sig, const uint8_t hash[64], + const uint8_t public_key[57], const uint8_t private_key[57], + const uint8_t *context, size_t context_len) +{ + return c448_ed448_sign_prehash(out_sig, private_key, public_key, hash, + context, context_len) == C448_SUCCESS; + +} + +int ED448ph_verify(const uint8_t hash[64], const uint8_t signature[114], + const uint8_t public_key[57], const uint8_t *context, + size_t context_len) +{ + return c448_ed448_verify_prehash(signature, public_key, hash, context, + (uint8_t)context_len) == C448_SUCCESS; +} + +int ED448_public_from_private(uint8_t out_public_key[57], + const uint8_t private_key[57]) +{ + return c448_ed448_derive_public_key(out_public_key, private_key) + == C448_SUCCESS; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/f_generic.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/f_generic.c new file mode 100644 index 000000000..ed8f36d86 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/f_generic.c @@ -0,0 +1,204 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2016 Cryptography Research, Inc. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + * + * Originally written by Mike Hamburg + */ +#include "field.h" + +static const gf MODULUS = { + FIELD_LITERAL(0xffffffffffffff, 0xffffffffffffff, 0xffffffffffffff, + 0xffffffffffffff, 0xfffffffffffffe, 0xffffffffffffff, + 0xffffffffffffff, 0xffffffffffffff) +}; + +/* Serialize to wire format. */ +void gf_serialize(uint8_t serial[SER_BYTES], const gf x, int with_hibit) +{ + unsigned int j = 0, fill = 0; + dword_t buffer = 0; + int i; + gf red; + + gf_copy(red, x); + gf_strong_reduce(red); + if (!with_hibit) + assert(gf_hibit(red) == 0); + + for (i = 0; i < (with_hibit ? X_SER_BYTES : SER_BYTES); i++) { + if (fill < 8 && j < NLIMBS) { + buffer |= ((dword_t) red->limb[LIMBPERM(j)]) << fill; + fill += LIMB_PLACE_VALUE(LIMBPERM(j)); + j++; + } + serial[i] = (uint8_t)buffer; + fill -= 8; + buffer >>= 8; + } +} + +/* Return high bit of x = low bit of 2x mod p */ +mask_t gf_hibit(const gf x) +{ + gf y; + + gf_add(y, x, x); + gf_strong_reduce(y); + return 0 - (y->limb[0] & 1); +} + +/* Return high bit of x = low bit of 2x mod p */ +mask_t gf_lobit(const gf x) +{ + gf y; + + gf_copy(y, x); + gf_strong_reduce(y); + return 0 - (y->limb[0] & 1); +} + +/* Deserialize from wire format; return -1 on success and 0 on failure. */ +mask_t gf_deserialize(gf x, const uint8_t serial[SER_BYTES], int with_hibit, + uint8_t hi_nmask) +{ + unsigned int j = 0, fill = 0; + dword_t buffer = 0; + dsword_t scarry = 0; + const unsigned nbytes = with_hibit ? X_SER_BYTES : SER_BYTES; + unsigned int i; + mask_t succ; + + for (i = 0; i < NLIMBS; i++) { + while (fill < LIMB_PLACE_VALUE(LIMBPERM(i)) && j < nbytes) { + uint8_t sj; + + sj = serial[j]; + if (j == nbytes - 1) + sj &= ~hi_nmask; + buffer |= ((dword_t) sj) << fill; + fill += 8; + j++; + } + x->limb[LIMBPERM(i)] = (word_t) + ((i < NLIMBS - 1) ? buffer & LIMB_MASK(LIMBPERM(i)) : buffer); + fill -= LIMB_PLACE_VALUE(LIMBPERM(i)); + buffer >>= LIMB_PLACE_VALUE(LIMBPERM(i)); + scarry = + (scarry + x->limb[LIMBPERM(i)] - + MODULUS->limb[LIMBPERM(i)]) >> (8 * sizeof(word_t)); + } + succ = with_hibit ? 0 - (mask_t) 1 : ~gf_hibit(x); + return succ & word_is_zero((word_t)buffer) & ~word_is_zero((word_t)scarry); +} + +/* Reduce to canonical form. */ +void gf_strong_reduce(gf a) +{ + dsword_t scarry; + word_t scarry_0; + dword_t carry = 0; + unsigned int i; + + /* first, clear high */ + gf_weak_reduce(a); /* Determined to have negligible perf impact. */ + + /* now the total is less than 2p */ + + /* compute total_value - p. No need to reduce mod p. */ + scarry = 0; + for (i = 0; i < NLIMBS; i++) { + scarry = scarry + a->limb[LIMBPERM(i)] - MODULUS->limb[LIMBPERM(i)]; + a->limb[LIMBPERM(i)] = scarry & LIMB_MASK(LIMBPERM(i)); + scarry >>= LIMB_PLACE_VALUE(LIMBPERM(i)); + } + + /* + * uncommon case: it was >= p, so now scarry = 0 and this = x common case: + * it was < p, so now scarry = -1 and this = x - p + 2^255 so let's add + * back in p. will carry back off the top for 2^255. + */ + assert(scarry == 0 || scarry == -1); + + scarry_0 = (word_t)scarry; + + /* add it back */ + for (i = 0; i < NLIMBS; i++) { + carry = + carry + a->limb[LIMBPERM(i)] + + (scarry_0 & MODULUS->limb[LIMBPERM(i)]); + a->limb[LIMBPERM(i)] = carry & LIMB_MASK(LIMBPERM(i)); + carry >>= LIMB_PLACE_VALUE(LIMBPERM(i)); + } + + assert(carry < 2 && ((word_t)carry + scarry_0) == 0); +} + +/* Subtract two gf elements d=a-b */ +void gf_sub(gf d, const gf a, const gf b) +{ + gf_sub_RAW(d, a, b); + gf_bias(d, 2); + gf_weak_reduce(d); +} + +/* Add two field elements d = a+b */ +void gf_add(gf d, const gf a, const gf b) +{ + gf_add_RAW(d, a, b); + gf_weak_reduce(d); +} + +/* Compare a==b */ +mask_t gf_eq(const gf a, const gf b) +{ + gf c; + mask_t ret = 0; + unsigned int i; + + gf_sub(c, a, b); + gf_strong_reduce(c); + + for (i = 0; i < NLIMBS; i++) + ret |= c->limb[LIMBPERM(i)]; + + return word_is_zero(ret); +} + +mask_t gf_isr(gf a, const gf x) +{ + gf L0, L1, L2; + + gf_sqr(L1, x); + gf_mul(L2, x, L1); + gf_sqr(L1, L2); + gf_mul(L2, x, L1); + gf_sqrn(L1, L2, 3); + gf_mul(L0, L2, L1); + gf_sqrn(L1, L0, 3); + gf_mul(L0, L2, L1); + gf_sqrn(L2, L0, 9); + gf_mul(L1, L0, L2); + gf_sqr(L0, L1); + gf_mul(L2, x, L0); + gf_sqrn(L0, L2, 18); + gf_mul(L2, L1, L0); + gf_sqrn(L0, L2, 37); + gf_mul(L1, L2, L0); + gf_sqrn(L0, L1, 37); + gf_mul(L1, L2, L0); + gf_sqrn(L0, L1, 111); + gf_mul(L2, L1, L0); + gf_sqr(L0, L2); + gf_mul(L1, x, L0); + gf_sqrn(L0, L1, 223); + gf_mul(L1, L2, L0); + gf_sqr(L2, L1); + gf_mul(L0, L2, x); + gf_copy(a, L1); + return gf_eq(L0, ONE); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/field.h b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/field.h new file mode 100644 index 000000000..d96d4c023 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/field.h @@ -0,0 +1,168 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2014 Cryptography Research, Inc. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + * + * Originally written by Mike Hamburg + */ + +#ifndef HEADER_FIELD_H +# define HEADER_FIELD_H + +# include "internal/constant_time_locl.h" +# include +# include +# include "word.h" + +# define NLIMBS (64/sizeof(word_t)) +# define X_SER_BYTES 56 +# define SER_BYTES 56 + +# if defined(__GNUC__) || defined(__clang__) +# define INLINE_UNUSED __inline__ __attribute__((__unused__,__always_inline__)) +# define RESTRICT __restrict__ +# define ALIGNED __attribute__((__aligned__(16))) +# else +# define INLINE_UNUSED ossl_inline +# define RESTRICT +# define ALIGNED +# endif + +typedef struct gf_s { + word_t limb[NLIMBS]; +} ALIGNED gf_s, gf[1]; + +/* RFC 7748 support */ +# define X_PUBLIC_BYTES X_SER_BYTES +# define X_PRIVATE_BYTES X_PUBLIC_BYTES +# define X_PRIVATE_BITS 448 + +static INLINE_UNUSED void gf_copy(gf out, const gf a) +{ + *out = *a; +} + +static INLINE_UNUSED void gf_add_RAW(gf out, const gf a, const gf b); +static INLINE_UNUSED void gf_sub_RAW(gf out, const gf a, const gf b); +static INLINE_UNUSED void gf_bias(gf inout, int amount); +static INLINE_UNUSED void gf_weak_reduce(gf inout); + +void gf_strong_reduce(gf inout); +void gf_add(gf out, const gf a, const gf b); +void gf_sub(gf out, const gf a, const gf b); +void gf_mul(gf_s * RESTRICT out, const gf a, const gf b); +void gf_mulw_unsigned(gf_s * RESTRICT out, const gf a, uint32_t b); +void gf_sqr(gf_s * RESTRICT out, const gf a); +mask_t gf_isr(gf a, const gf x); /** a^2 x = 1, QNR, or 0 if x=0. Return true if successful */ +mask_t gf_eq(const gf x, const gf y); +mask_t gf_lobit(const gf x); +mask_t gf_hibit(const gf x); + +void gf_serialize(uint8_t *serial, const gf x, int with_highbit); +mask_t gf_deserialize(gf x, const uint8_t serial[SER_BYTES], int with_hibit, + uint8_t hi_nmask); + +# include "f_impl.h" /* Bring in the inline implementations */ + +# define LIMBPERM(i) (i) +# define LIMB_MASK(i) (((1)< 0); + if (n & 1) { + gf_sqr(y, x); + n--; + } else { + gf_sqr(tmp, x); + gf_sqr(y, tmp); + n -= 2; + } + for (; n; n -= 2) { + gf_sqr(tmp, y); + gf_sqr(y, tmp); + } +} + +# define gf_add_nr gf_add_RAW + +/* Subtract mod p. Bias by 2 and don't reduce */ +static ossl_inline void gf_sub_nr(gf c, const gf a, const gf b) +{ + gf_sub_RAW(c, a, b); + gf_bias(c, 2); + if (GF_HEADROOM < 3) + gf_weak_reduce(c); +} + +/* Subtract mod p. Bias by amt but don't reduce. */ +static ossl_inline void gf_subx_nr(gf c, const gf a, const gf b, int amt) +{ + gf_sub_RAW(c, a, b); + gf_bias(c, amt); + if (GF_HEADROOM < amt + 1) + gf_weak_reduce(c); +} + +/* Mul by signed int. Not constant-time WRT the sign of that int. */ +static ossl_inline void gf_mulw(gf c, const gf a, int32_t w) +{ + if (w > 0) { + gf_mulw_unsigned(c, a, w); + } else { + gf_mulw_unsigned(c, a, -w); + gf_sub(c, ZERO, c); + } +} + +/* Constant time, x = is_z ? z : y */ +static ossl_inline void gf_cond_sel(gf x, const gf y, const gf z, mask_t is_z) +{ + size_t i; + + for (i = 0; i < NLIMBS; i++) { +#if ARCH_WORD_BITS == 32 + x[0].limb[i] = constant_time_select_32(is_z, z[0].limb[i], + y[0].limb[i]); +#else + /* Must be 64 bit */ + x[0].limb[i] = constant_time_select_64(is_z, z[0].limb[i], + y[0].limb[i]); +#endif + } +} + +/* Constant time, if (neg) x=-x; */ +static ossl_inline void gf_cond_neg(gf x, mask_t neg) +{ + gf y; + + gf_sub(y, ZERO, x); + gf_cond_sel(x, x, y, neg); +} + +/* Constant time, if (swap) (x,y) = (y,x); */ +static ossl_inline void gf_cond_swap(gf x, gf_s * RESTRICT y, mask_t swap) +{ + size_t i; + + for (i = 0; i < NLIMBS; i++) { +#if ARCH_WORD_BITS == 32 + constant_time_cond_swap_32(swap, &(x[0].limb[i]), &(y->limb[i])); +#else + /* Must be 64 bit */ + constant_time_cond_swap_64(swap, &(x[0].limb[i]), &(y->limb[i])); +#endif + } +} + +#endif /* HEADER_FIELD_H */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/point_448.h b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/point_448.h new file mode 100644 index 000000000..399f91b9a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/point_448.h @@ -0,0 +1,301 @@ +/* + * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2016 Cryptography Research, Inc. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + * + * Originally written by Mike Hamburg + */ + +#ifndef HEADER_POINT_448_H +# define HEADER_POINT_448_H + +# include "curve448utils.h" +# include "field.h" + +/* Comb config: number of combs, n, t, s. */ +#define COMBS_N 5 +#define COMBS_T 5 +#define COMBS_S 18 + +/* Projective Niels coordinates */ +typedef struct { + gf a, b, c; +} niels_s, niels_t[1]; +typedef struct { + niels_t n; + gf z; +} pniels_t[1]; + +/* Precomputed base */ +struct curve448_precomputed_s { + niels_t table[COMBS_N << (COMBS_T - 1)]; +}; + +# define C448_SCALAR_LIMBS ((446-1)/C448_WORD_BITS+1) + +/* The number of bits in a scalar */ +# define C448_SCALAR_BITS 446 + +/* Number of bytes in a serialized scalar. */ +# define C448_SCALAR_BYTES 56 + +/* X448 encoding ratio. */ +# define X448_ENCODE_RATIO 2 + +/* Number of bytes in an x448 public key */ +# define X448_PUBLIC_BYTES 56 + +/* Number of bytes in an x448 private key */ +# define X448_PRIVATE_BYTES 56 + +/* Twisted Edwards extended homogeneous coordinates */ +typedef struct curve448_point_s { + gf x, y, z, t; +} curve448_point_t[1]; + +/* Precomputed table based on a point. Can be trivial implementation. */ +struct curve448_precomputed_s; + +/* Precomputed table based on a point. Can be trivial implementation. */ +typedef struct curve448_precomputed_s curve448_precomputed_s; + +/* Scalar is stored packed, because we don't need the speed. */ +typedef struct curve448_scalar_s { + c448_word_t limb[C448_SCALAR_LIMBS]; +} curve448_scalar_t[1]; + +/* A scalar equal to 1. */ +extern const curve448_scalar_t curve448_scalar_one; + +/* A scalar equal to 0. */ +extern const curve448_scalar_t curve448_scalar_zero; + +/* The identity point on the curve. */ +extern const curve448_point_t curve448_point_identity; + +/* Precomputed table for the base point on the curve. */ +extern const struct curve448_precomputed_s *curve448_precomputed_base; +extern const niels_t *curve448_wnaf_base; + +/* + * Read a scalar from wire format or from bytes. + * + * ser (in): Serialized form of a scalar. + * out (out): Deserialized form. + * + * Returns: + * C448_SUCCESS: The scalar was correctly encoded. + * C448_FAILURE: The scalar was greater than the modulus, and has been reduced + * modulo that modulus. + */ +c448_error_t curve448_scalar_decode(curve448_scalar_t out, + const unsigned char ser[C448_SCALAR_BYTES]); + +/* + * Read a scalar from wire format or from bytes. Reduces mod scalar prime. + * + * ser (in): Serialized form of a scalar. + * ser_len (in): Length of serialized form. + * out (out): Deserialized form. + */ +void curve448_scalar_decode_long(curve448_scalar_t out, + const unsigned char *ser, size_t ser_len); + +/* + * Serialize a scalar to wire format. + * + * ser (out): Serialized form of a scalar. + * s (in): Deserialized scalar. + */ +void curve448_scalar_encode(unsigned char ser[C448_SCALAR_BYTES], + const curve448_scalar_t s); + +/* + * Add two scalars. |a|, |b| and |out| may alias each other. + * + * a (in): One scalar. + * b (in): Another scalar. + * out (out): a+b. + */ +void curve448_scalar_add(curve448_scalar_t out, + const curve448_scalar_t a, const curve448_scalar_t b); + +/* + * Subtract two scalars. |a|, |b| and |out| may alias each other. + * a (in): One scalar. + * b (in): Another scalar. + * out (out): a-b. + */ +void curve448_scalar_sub(curve448_scalar_t out, + const curve448_scalar_t a, const curve448_scalar_t b); + +/* + * Multiply two scalars. |a|, |b| and |out| may alias each other. + * + * a (in): One scalar. + * b (in): Another scalar. + * out (out): a*b. + */ +void curve448_scalar_mul(curve448_scalar_t out, + const curve448_scalar_t a, const curve448_scalar_t b); + +/* +* Halve a scalar. |a| and |out| may alias each other. +* +* a (in): A scalar. +* out (out): a/2. +*/ +void curve448_scalar_halve(curve448_scalar_t out, const curve448_scalar_t a); + +/* + * Copy a scalar. The scalars may alias each other, in which case this + * function does nothing. + * + * a (in): A scalar. + * out (out): Will become a copy of a. + */ +static ossl_inline void curve448_scalar_copy(curve448_scalar_t out, + const curve448_scalar_t a) +{ + *out = *a; +} + +/* + * Copy a point. The input and output may alias, in which case this function + * does nothing. + * + * a (out): A copy of the point. + * b (in): Any point. + */ +static ossl_inline void curve448_point_copy(curve448_point_t a, + const curve448_point_t b) +{ + *a = *b; +} + +/* + * Test whether two points are equal. If yes, return C448_TRUE, else return + * C448_FALSE. + * + * a (in): A point. + * b (in): Another point. + * + * Returns: + * C448_TRUE: The points are equal. + * C448_FALSE: The points are not equal. + */ +__owur c448_bool_t curve448_point_eq(const curve448_point_t a, + const curve448_point_t b); + +/* + * Double a point. Equivalent to curve448_point_add(two_a,a,a), but potentially + * faster. + * + * two_a (out): The sum a+a. + * a (in): A point. + */ +void curve448_point_double(curve448_point_t two_a, const curve448_point_t a); + +/* + * RFC 7748 Diffie-Hellman scalarmul. This function uses a different + * (non-Decaf) encoding. + * + * out (out): The scaled point base*scalar + * base (in): The point to be scaled. + * scalar (in): The scalar to multiply by. + * + * Returns: + * C448_SUCCESS: The scalarmul succeeded. + * C448_FAILURE: The scalarmul didn't succeed, because the base point is in a + * small subgroup. + */ +__owur c448_error_t x448_int(uint8_t out[X448_PUBLIC_BYTES], + const uint8_t base[X448_PUBLIC_BYTES], + const uint8_t scalar[X448_PRIVATE_BYTES]); + +/* + * Multiply a point by X448_ENCODE_RATIO, then encode it like RFC 7748. + * + * This function is mainly used internally, but is exported in case + * it will be useful. + * + * The ratio is necessary because the internal representation doesn't + * track the cofactor information, so on output we must clear the cofactor. + * This would multiply by the cofactor, but in fact internally points are always + * even, so it multiplies by half the cofactor instead. + * + * As it happens, this aligns with the base point definitions; that is, + * if you pass the Decaf/Ristretto base point to this function, the result + * will be X448_ENCODE_RATIO times the X448 + * base point. + * + * out (out): The scaled and encoded point. + * p (in): The point to be scaled and encoded. + */ +void curve448_point_mul_by_ratio_and_encode_like_x448( + uint8_t out[X448_PUBLIC_BYTES], + const curve448_point_t p); + +/* + * RFC 7748 Diffie-Hellman base point scalarmul. This function uses a different + * (non-Decaf) encoding. + * + * out (out): The scaled point base*scalar + * scalar (in): The scalar to multiply by. + */ +void x448_derive_public_key(uint8_t out[X448_PUBLIC_BYTES], + const uint8_t scalar[X448_PRIVATE_BYTES]); + +/* + * Multiply a precomputed base point by a scalar: out = scalar*base. + * + * scaled (out): The scaled point base*scalar + * base (in): The point to be scaled. + * scalar (in): The scalar to multiply by. + */ +void curve448_precomputed_scalarmul(curve448_point_t scaled, + const curve448_precomputed_s * base, + const curve448_scalar_t scalar); + +/* + * Multiply two base points by two scalars: + * combo = scalar1*curve448_point_base + scalar2*base2. + * + * Otherwise equivalent to curve448_point_double_scalarmul, but may be + * faster at the expense of being variable time. + * + * combo (out): The linear combination scalar1*base + scalar2*base2. + * scalar1 (in): A first scalar to multiply by. + * base2 (in): A second point to be scaled. + * scalar2 (in) A second scalar to multiply by. + * + * Warning: This function takes variable time, and may leak the scalars used. + * It is designed for signature verification. + */ +void curve448_base_double_scalarmul_non_secret(curve448_point_t combo, + const curve448_scalar_t scalar1, + const curve448_point_t base2, + const curve448_scalar_t scalar2); + +/* + * Test that a point is valid, for debugging purposes. + * + * to_test (in): The point to test. + * + * Returns: + * C448_TRUE The point is valid. + * C448_FALSE The point is invalid. + */ +__owur c448_bool_t curve448_point_valid(const curve448_point_t to_test); + +/* Overwrite scalar with zeros. */ +void curve448_scalar_destroy(curve448_scalar_t scalar); + +/* Overwrite point with zeros. */ +void curve448_point_destroy(curve448_point_t point); + +#endif /* HEADER_POINT_448_H */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/scalar.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/scalar.c new file mode 100644 index 000000000..b5702c025 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/scalar.c @@ -0,0 +1,235 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2016 Cryptography Research, Inc. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + * + * Originally written by Mike Hamburg + */ +#include + +#include "word.h" +#include "point_448.h" + +static const c448_word_t MONTGOMERY_FACTOR = (c448_word_t) 0x3bd440fae918bc5; +static const curve448_scalar_t sc_p = { + { + { + SC_LIMB(0x2378c292ab5844f3), SC_LIMB(0x216cc2728dc58f55), + SC_LIMB(0xc44edb49aed63690), SC_LIMB(0xffffffff7cca23e9), + SC_LIMB(0xffffffffffffffff), SC_LIMB(0xffffffffffffffff), + SC_LIMB(0x3fffffffffffffff) + } + } +}, sc_r2 = { + { + { + + SC_LIMB(0xe3539257049b9b60), SC_LIMB(0x7af32c4bc1b195d9), + SC_LIMB(0x0d66de2388ea1859), SC_LIMB(0xae17cf725ee4d838), + SC_LIMB(0x1a9cc14ba3c47c44), SC_LIMB(0x2052bcb7e4d070af), + SC_LIMB(0x3402a939f823b729) + } + } +}; + +#define WBITS C448_WORD_BITS /* NB this may be different from ARCH_WORD_BITS */ + +const curve448_scalar_t curve448_scalar_one = {{{1}}}; +const curve448_scalar_t curve448_scalar_zero = {{{0}}}; + +/* + * {extra,accum} - sub +? p + * Must have extra <= 1 + */ +static void sc_subx(curve448_scalar_t out, + const c448_word_t accum[C448_SCALAR_LIMBS], + const curve448_scalar_t sub, + const curve448_scalar_t p, c448_word_t extra) +{ + c448_dsword_t chain = 0; + unsigned int i; + c448_word_t borrow; + + for (i = 0; i < C448_SCALAR_LIMBS; i++) { + chain = (chain + accum[i]) - sub->limb[i]; + out->limb[i] = (c448_word_t)chain; + chain >>= WBITS; + } + borrow = (c448_word_t)chain + extra; /* = 0 or -1 */ + + chain = 0; + for (i = 0; i < C448_SCALAR_LIMBS; i++) { + chain = (chain + out->limb[i]) + (p->limb[i] & borrow); + out->limb[i] = (c448_word_t)chain; + chain >>= WBITS; + } +} + +static void sc_montmul(curve448_scalar_t out, const curve448_scalar_t a, + const curve448_scalar_t b) +{ + unsigned int i, j; + c448_word_t accum[C448_SCALAR_LIMBS + 1] = { 0 }; + c448_word_t hi_carry = 0; + + for (i = 0; i < C448_SCALAR_LIMBS; i++) { + c448_word_t mand = a->limb[i]; + const c448_word_t *mier = b->limb; + + c448_dword_t chain = 0; + for (j = 0; j < C448_SCALAR_LIMBS; j++) { + chain += ((c448_dword_t) mand) * mier[j] + accum[j]; + accum[j] = (c448_word_t)chain; + chain >>= WBITS; + } + accum[j] = (c448_word_t)chain; + + mand = accum[0] * MONTGOMERY_FACTOR; + chain = 0; + mier = sc_p->limb; + for (j = 0; j < C448_SCALAR_LIMBS; j++) { + chain += (c448_dword_t) mand *mier[j] + accum[j]; + if (j) + accum[j - 1] = (c448_word_t)chain; + chain >>= WBITS; + } + chain += accum[j]; + chain += hi_carry; + accum[j - 1] = (c448_word_t)chain; + hi_carry = chain >> WBITS; + } + + sc_subx(out, accum, sc_p, sc_p, hi_carry); +} + +void curve448_scalar_mul(curve448_scalar_t out, const curve448_scalar_t a, + const curve448_scalar_t b) +{ + sc_montmul(out, a, b); + sc_montmul(out, out, sc_r2); +} + +void curve448_scalar_sub(curve448_scalar_t out, const curve448_scalar_t a, + const curve448_scalar_t b) +{ + sc_subx(out, a->limb, b, sc_p, 0); +} + +void curve448_scalar_add(curve448_scalar_t out, const curve448_scalar_t a, + const curve448_scalar_t b) +{ + c448_dword_t chain = 0; + unsigned int i; + + for (i = 0; i < C448_SCALAR_LIMBS; i++) { + chain = (chain + a->limb[i]) + b->limb[i]; + out->limb[i] = (c448_word_t)chain; + chain >>= WBITS; + } + sc_subx(out, out->limb, sc_p, sc_p, (c448_word_t)chain); +} + +static ossl_inline void scalar_decode_short(curve448_scalar_t s, + const unsigned char *ser, + size_t nbytes) +{ + size_t i, j, k = 0; + + for (i = 0; i < C448_SCALAR_LIMBS; i++) { + c448_word_t out = 0; + + for (j = 0; j < sizeof(c448_word_t) && k < nbytes; j++, k++) + out |= ((c448_word_t) ser[k]) << (8 * j); + s->limb[i] = out; + } +} + +c448_error_t curve448_scalar_decode( + curve448_scalar_t s, + const unsigned char ser[C448_SCALAR_BYTES]) +{ + unsigned int i; + c448_dsword_t accum = 0; + + scalar_decode_short(s, ser, C448_SCALAR_BYTES); + for (i = 0; i < C448_SCALAR_LIMBS; i++) + accum = (accum + s->limb[i] - sc_p->limb[i]) >> WBITS; + /* Here accum == 0 or -1 */ + + curve448_scalar_mul(s, s, curve448_scalar_one); /* ham-handed reduce */ + + return c448_succeed_if(~word_is_zero((uint32_t)accum)); +} + +void curve448_scalar_destroy(curve448_scalar_t scalar) +{ + OPENSSL_cleanse(scalar, sizeof(curve448_scalar_t)); +} + +void curve448_scalar_decode_long(curve448_scalar_t s, + const unsigned char *ser, size_t ser_len) +{ + size_t i; + curve448_scalar_t t1, t2; + + if (ser_len == 0) { + curve448_scalar_copy(s, curve448_scalar_zero); + return; + } + + i = ser_len - (ser_len % C448_SCALAR_BYTES); + if (i == ser_len) + i -= C448_SCALAR_BYTES; + + scalar_decode_short(t1, &ser[i], ser_len - i); + + if (ser_len == sizeof(curve448_scalar_t)) { + assert(i == 0); + /* ham-handed reduce */ + curve448_scalar_mul(s, t1, curve448_scalar_one); + curve448_scalar_destroy(t1); + return; + } + + while (i) { + i -= C448_SCALAR_BYTES; + sc_montmul(t1, t1, sc_r2); + (void)curve448_scalar_decode(t2, ser + i); + curve448_scalar_add(t1, t1, t2); + } + + curve448_scalar_copy(s, t1); + curve448_scalar_destroy(t1); + curve448_scalar_destroy(t2); +} + +void curve448_scalar_encode(unsigned char ser[C448_SCALAR_BYTES], + const curve448_scalar_t s) +{ + unsigned int i, j, k = 0; + + for (i = 0; i < C448_SCALAR_LIMBS; i++) { + for (j = 0; j < sizeof(c448_word_t); j++, k++) + ser[k] = s->limb[i] >> (8 * j); + } +} + +void curve448_scalar_halve(curve448_scalar_t out, const curve448_scalar_t a) +{ + c448_word_t mask = 0 - (a->limb[0] & 1); + c448_dword_t chain = 0; + unsigned int i; + + for (i = 0; i < C448_SCALAR_LIMBS; i++) { + chain = (chain + a->limb[i]) + (sc_p->limb[i] & mask); + out->limb[i] = (c448_word_t)chain; + chain >>= C448_WORD_BITS; + } + for (i = 0; i < C448_SCALAR_LIMBS - 1; i++) + out->limb[i] = out->limb[i] >> 1 | out->limb[i + 1] << (WBITS - 1); + out->limb[i] = out->limb[i] >> 1 | (c448_word_t)(chain << (WBITS - 1)); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/word.h b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/word.h new file mode 100644 index 000000000..a48b9e053 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/curve448/word.h @@ -0,0 +1,81 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2014 Cryptography Research, Inc. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + * + * Originally written by Mike Hamburg + */ + +#ifndef HEADER_WORD_H +# define HEADER_WORD_H + +# include +# include +# include +# include +# include "arch_intrinsics.h" +# include "curve448utils.h" + +# if (ARCH_WORD_BITS == 64) +typedef uint64_t word_t, mask_t; +typedef __uint128_t dword_t; +typedef int32_t hsword_t; +typedef int64_t sword_t; +typedef __int128_t dsword_t; +# elif (ARCH_WORD_BITS == 32) +typedef uint32_t word_t, mask_t; +typedef uint64_t dword_t; +typedef int16_t hsword_t; +typedef int32_t sword_t; +typedef int64_t dsword_t; +# else +# error "For now, we only support 32- and 64-bit architectures." +# endif + +/* + * Scalar limbs are keyed off of the API word size instead of the arch word + * size. + */ +# if C448_WORD_BITS == 64 +# define SC_LIMB(x) (x) +# elif C448_WORD_BITS == 32 +# define SC_LIMB(x) ((uint32_t)(x)),((x) >> 32) +# else +# error "For now we only support 32- and 64-bit architectures." +# endif + +/* + * The plan on booleans: The external interface uses c448_bool_t, but this + * might be a different size than our particular arch's word_t (and thus + * mask_t). Also, the caller isn't guaranteed to pass it as nonzero. So + * bool_to_mask converts word sizes and checks nonzero. On the flip side, + * mask_t is always -1 or 0, but it might be a different size than + * c448_bool_t. On the third hand, we have success vs boolean types, but + * that's handled in common.h: it converts between c448_bool_t and + * c448_error_t. + */ +static ossl_inline c448_bool_t mask_to_bool(mask_t m) +{ + return (c448_sword_t)(sword_t)m; +} + +static ossl_inline mask_t bool_to_mask(c448_bool_t m) +{ + /* On most arches this will be optimized to a simple cast. */ + mask_t ret = 0; + unsigned int i; + unsigned int limit = sizeof(c448_bool_t) / sizeof(mask_t); + + if (limit < 1) + limit = 1; + for (i = 0; i < limit; i++) + ret |= ~word_is_zero(m >> (i * 8 * sizeof(word_t))); + + return ret; +} + +#endif /* HEADER_WORD_H */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec2_oct.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec2_oct.c new file mode 100644 index 000000000..0867f994e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec2_oct.c @@ -0,0 +1,337 @@ +/* + * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#include "ec_lcl.h" + +#ifndef OPENSSL_NO_EC2M + +/*- + * Calculates and sets the affine coordinates of an EC_POINT from the given + * compressed coordinates. Uses algorithm 2.3.4 of SEC 1. + * Note that the simple implementation only uses affine coordinates. + * + * The method is from the following publication: + * + * Harper, Menezes, Vanstone: + * "Public-Key Cryptosystems with Very Small Key Lengths", + * EUROCRYPT '92, Springer-Verlag LNCS 658, + * published February 1993 + * + * US Patents 6,141,420 and 6,618,483 (Vanstone, Mullin, Agnew) describe + * the same method, but claim no priority date earlier than July 29, 1994 + * (and additionally fail to cite the EUROCRYPT '92 publication as prior art). + */ +int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group, + EC_POINT *point, + const BIGNUM *x_, int y_bit, + BN_CTX *ctx) +{ + BN_CTX *new_ctx = NULL; + BIGNUM *tmp, *x, *y, *z; + int ret = 0, z0; + + /* clear error queue */ + ERR_clear_error(); + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + y_bit = (y_bit != 0) ? 1 : 0; + + BN_CTX_start(ctx); + tmp = BN_CTX_get(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + z = BN_CTX_get(ctx); + if (z == NULL) + goto err; + + if (!BN_GF2m_mod_arr(x, x_, group->poly)) + goto err; + if (BN_is_zero(x)) { + if (!BN_GF2m_mod_sqrt_arr(y, group->b, group->poly, ctx)) + goto err; + } else { + if (!group->meth->field_sqr(group, tmp, x, ctx)) + goto err; + if (!group->meth->field_div(group, tmp, group->b, tmp, ctx)) + goto err; + if (!BN_GF2m_add(tmp, group->a, tmp)) + goto err; + if (!BN_GF2m_add(tmp, x, tmp)) + goto err; + if (!BN_GF2m_mod_solve_quad_arr(z, tmp, group->poly, ctx)) { + unsigned long err = ERR_peek_last_error(); + + if (ERR_GET_LIB(err) == ERR_LIB_BN + && ERR_GET_REASON(err) == BN_R_NO_SOLUTION) { + ERR_clear_error(); + ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, + EC_R_INVALID_COMPRESSED_POINT); + } else + ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, + ERR_R_BN_LIB); + goto err; + } + z0 = (BN_is_odd(z)) ? 1 : 0; + if (!group->meth->field_mul(group, y, x, z, ctx)) + goto err; + if (z0 != y_bit) { + if (!BN_GF2m_add(y, y, x)) + goto err; + } + } + + if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx)) + goto err; + + ret = 1; + + err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +/* + * Converts an EC_POINT to an octet string. If buf is NULL, the encoded + * length will be returned. If the length len of buf is smaller than required + * an error will be returned. + */ +size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, + point_conversion_form_t form, + unsigned char *buf, size_t len, BN_CTX *ctx) +{ + size_t ret; + BN_CTX *new_ctx = NULL; + int used_ctx = 0; + BIGNUM *x, *y, *yxi; + size_t field_len, i, skip; + + if ((form != POINT_CONVERSION_COMPRESSED) + && (form != POINT_CONVERSION_UNCOMPRESSED) + && (form != POINT_CONVERSION_HYBRID)) { + ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_INVALID_FORM); + goto err; + } + + if (EC_POINT_is_at_infinity(group, point)) { + /* encodes to a single 0 octet */ + if (buf != NULL) { + if (len < 1) { + ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); + return 0; + } + buf[0] = 0; + } + return 1; + } + + /* ret := required output buffer length */ + field_len = (EC_GROUP_get_degree(group) + 7) / 8; + ret = + (form == + POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len; + + /* if 'buf' is NULL, just return required length */ + if (buf != NULL) { + if (len < ret) { + ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); + goto err; + } + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + BN_CTX_start(ctx); + used_ctx = 1; + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + yxi = BN_CTX_get(ctx); + if (yxi == NULL) + goto err; + + if (!EC_POINT_get_affine_coordinates(group, point, x, y, ctx)) + goto err; + + buf[0] = form; + if ((form != POINT_CONVERSION_UNCOMPRESSED) && !BN_is_zero(x)) { + if (!group->meth->field_div(group, yxi, y, x, ctx)) + goto err; + if (BN_is_odd(yxi)) + buf[0]++; + } + + i = 1; + + skip = field_len - BN_num_bytes(x); + if (skip > field_len) { + ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); + goto err; + } + while (skip > 0) { + buf[i++] = 0; + skip--; + } + skip = BN_bn2bin(x, buf + i); + i += skip; + if (i != 1 + field_len) { + ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); + goto err; + } + + if (form == POINT_CONVERSION_UNCOMPRESSED + || form == POINT_CONVERSION_HYBRID) { + skip = field_len - BN_num_bytes(y); + if (skip > field_len) { + ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); + goto err; + } + while (skip > 0) { + buf[i++] = 0; + skip--; + } + skip = BN_bn2bin(y, buf + i); + i += skip; + } + + if (i != ret) { + ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); + goto err; + } + } + + if (used_ctx) + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; + + err: + if (used_ctx) + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return 0; +} + +/* + * Converts an octet string representation to an EC_POINT. Note that the + * simple implementation only uses affine coordinates. + */ +int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point, + const unsigned char *buf, size_t len, + BN_CTX *ctx) +{ + point_conversion_form_t form; + int y_bit; + BN_CTX *new_ctx = NULL; + BIGNUM *x, *y, *yxi; + size_t field_len, enc_len; + int ret = 0; + + if (len == 0) { + ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL); + return 0; + } + form = buf[0]; + y_bit = form & 1; + form = form & ~1U; + if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED) + && (form != POINT_CONVERSION_UNCOMPRESSED) + && (form != POINT_CONVERSION_HYBRID)) { + ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + return 0; + } + if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit) { + ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + return 0; + } + + if (form == 0) { + if (len != 1) { + ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + return 0; + } + + return EC_POINT_set_to_infinity(group, point); + } + + field_len = (EC_GROUP_get_degree(group) + 7) / 8; + enc_len = + (form == + POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len; + + if (len != enc_len) { + ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + return 0; + } + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + BN_CTX_start(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + yxi = BN_CTX_get(ctx); + if (yxi == NULL) + goto err; + + if (!BN_bin2bn(buf + 1, field_len, x)) + goto err; + if (BN_ucmp(x, group->field) >= 0) { + ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + goto err; + } + + if (form == POINT_CONVERSION_COMPRESSED) { + if (!EC_POINT_set_compressed_coordinates(group, point, x, y_bit, ctx)) + goto err; + } else { + if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) + goto err; + if (BN_ucmp(y, group->field) >= 0) { + ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + goto err; + } + if (form == POINT_CONVERSION_HYBRID) { + if (!group->meth->field_div(group, yxi, y, x, ctx)) + goto err; + if (y_bit != BN_is_odd(yxi)) { + ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + goto err; + } + } + + /* + * EC_POINT_set_affine_coordinates is responsible for checking that + * the point is on the curve. + */ + if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx)) + goto err; + } + + ret = 1; + + err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec2_smpl.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec2_smpl.c new file mode 100644 index 000000000..0a05a7aee --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec2_smpl.c @@ -0,0 +1,970 @@ +/* + * Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#include "internal/bn_int.h" +#include "ec_lcl.h" + +#ifndef OPENSSL_NO_EC2M + +/* + * Initialize a GF(2^m)-based EC_GROUP structure. Note that all other members + * are handled by EC_GROUP_new. + */ +int ec_GF2m_simple_group_init(EC_GROUP *group) +{ + group->field = BN_new(); + group->a = BN_new(); + group->b = BN_new(); + + if (group->field == NULL || group->a == NULL || group->b == NULL) { + BN_free(group->field); + BN_free(group->a); + BN_free(group->b); + return 0; + } + return 1; +} + +/* + * Free a GF(2^m)-based EC_GROUP structure. Note that all other members are + * handled by EC_GROUP_free. + */ +void ec_GF2m_simple_group_finish(EC_GROUP *group) +{ + BN_free(group->field); + BN_free(group->a); + BN_free(group->b); +} + +/* + * Clear and free a GF(2^m)-based EC_GROUP structure. Note that all other + * members are handled by EC_GROUP_clear_free. + */ +void ec_GF2m_simple_group_clear_finish(EC_GROUP *group) +{ + BN_clear_free(group->field); + BN_clear_free(group->a); + BN_clear_free(group->b); + group->poly[0] = 0; + group->poly[1] = 0; + group->poly[2] = 0; + group->poly[3] = 0; + group->poly[4] = 0; + group->poly[5] = -1; +} + +/* + * Copy a GF(2^m)-based EC_GROUP structure. Note that all other members are + * handled by EC_GROUP_copy. + */ +int ec_GF2m_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src) +{ + if (!BN_copy(dest->field, src->field)) + return 0; + if (!BN_copy(dest->a, src->a)) + return 0; + if (!BN_copy(dest->b, src->b)) + return 0; + dest->poly[0] = src->poly[0]; + dest->poly[1] = src->poly[1]; + dest->poly[2] = src->poly[2]; + dest->poly[3] = src->poly[3]; + dest->poly[4] = src->poly[4]; + dest->poly[5] = src->poly[5]; + if (bn_wexpand(dest->a, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == + NULL) + return 0; + if (bn_wexpand(dest->b, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == + NULL) + return 0; + bn_set_all_zero(dest->a); + bn_set_all_zero(dest->b); + return 1; +} + +/* Set the curve parameters of an EC_GROUP structure. */ +int ec_GF2m_simple_group_set_curve(EC_GROUP *group, + const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx) +{ + int ret = 0, i; + + /* group->field */ + if (!BN_copy(group->field, p)) + goto err; + i = BN_GF2m_poly2arr(group->field, group->poly, 6) - 1; + if ((i != 5) && (i != 3)) { + ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, EC_R_UNSUPPORTED_FIELD); + goto err; + } + + /* group->a */ + if (!BN_GF2m_mod_arr(group->a, a, group->poly)) + goto err; + if (bn_wexpand(group->a, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2) + == NULL) + goto err; + bn_set_all_zero(group->a); + + /* group->b */ + if (!BN_GF2m_mod_arr(group->b, b, group->poly)) + goto err; + if (bn_wexpand(group->b, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2) + == NULL) + goto err; + bn_set_all_zero(group->b); + + ret = 1; + err: + return ret; +} + +/* + * Get the curve parameters of an EC_GROUP structure. If p, a, or b are NULL + * then there values will not be set but the method will return with success. + */ +int ec_GF2m_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, + BIGNUM *a, BIGNUM *b, BN_CTX *ctx) +{ + int ret = 0; + + if (p != NULL) { + if (!BN_copy(p, group->field)) + return 0; + } + + if (a != NULL) { + if (!BN_copy(a, group->a)) + goto err; + } + + if (b != NULL) { + if (!BN_copy(b, group->b)) + goto err; + } + + ret = 1; + + err: + return ret; +} + +/* + * Gets the degree of the field. For a curve over GF(2^m) this is the value + * m. + */ +int ec_GF2m_simple_group_get_degree(const EC_GROUP *group) +{ + return BN_num_bits(group->field) - 1; +} + +/* + * Checks the discriminant of the curve. y^2 + x*y = x^3 + a*x^2 + b is an + * elliptic curve <=> b != 0 (mod p) + */ +int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group, + BN_CTX *ctx) +{ + int ret = 0; + BIGNUM *b; + BN_CTX *new_ctx = NULL; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) { + ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT, + ERR_R_MALLOC_FAILURE); + goto err; + } + } + BN_CTX_start(ctx); + b = BN_CTX_get(ctx); + if (b == NULL) + goto err; + + if (!BN_GF2m_mod_arr(b, group->b, group->poly)) + goto err; + + /* + * check the discriminant: y^2 + x*y = x^3 + a*x^2 + b is an elliptic + * curve <=> b != 0 (mod p) + */ + if (BN_is_zero(b)) + goto err; + + ret = 1; + + err: + if (ctx != NULL) + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +/* Initializes an EC_POINT. */ +int ec_GF2m_simple_point_init(EC_POINT *point) +{ + point->X = BN_new(); + point->Y = BN_new(); + point->Z = BN_new(); + + if (point->X == NULL || point->Y == NULL || point->Z == NULL) { + BN_free(point->X); + BN_free(point->Y); + BN_free(point->Z); + return 0; + } + return 1; +} + +/* Frees an EC_POINT. */ +void ec_GF2m_simple_point_finish(EC_POINT *point) +{ + BN_free(point->X); + BN_free(point->Y); + BN_free(point->Z); +} + +/* Clears and frees an EC_POINT. */ +void ec_GF2m_simple_point_clear_finish(EC_POINT *point) +{ + BN_clear_free(point->X); + BN_clear_free(point->Y); + BN_clear_free(point->Z); + point->Z_is_one = 0; +} + +/* + * Copy the contents of one EC_POINT into another. Assumes dest is + * initialized. + */ +int ec_GF2m_simple_point_copy(EC_POINT *dest, const EC_POINT *src) +{ + if (!BN_copy(dest->X, src->X)) + return 0; + if (!BN_copy(dest->Y, src->Y)) + return 0; + if (!BN_copy(dest->Z, src->Z)) + return 0; + dest->Z_is_one = src->Z_is_one; + dest->curve_name = src->curve_name; + + return 1; +} + +/* + * Set an EC_POINT to the point at infinity. A point at infinity is + * represented by having Z=0. + */ +int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group, + EC_POINT *point) +{ + point->Z_is_one = 0; + BN_zero(point->Z); + return 1; +} + +/* + * Set the coordinates of an EC_POINT using affine coordinates. Note that + * the simple implementation only uses affine coordinates. + */ +int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group, + EC_POINT *point, + const BIGNUM *x, + const BIGNUM *y, BN_CTX *ctx) +{ + int ret = 0; + if (x == NULL || y == NULL) { + ECerr(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (!BN_copy(point->X, x)) + goto err; + BN_set_negative(point->X, 0); + if (!BN_copy(point->Y, y)) + goto err; + BN_set_negative(point->Y, 0); + if (!BN_copy(point->Z, BN_value_one())) + goto err; + BN_set_negative(point->Z, 0); + point->Z_is_one = 1; + ret = 1; + + err: + return ret; +} + +/* + * Gets the affine coordinates of an EC_POINT. Note that the simple + * implementation only uses affine coordinates. + */ +int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx) +{ + int ret = 0; + + if (EC_POINT_is_at_infinity(group, point)) { + ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, + EC_R_POINT_AT_INFINITY); + return 0; + } + + if (BN_cmp(point->Z, BN_value_one())) { + ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (x != NULL) { + if (!BN_copy(x, point->X)) + goto err; + BN_set_negative(x, 0); + } + if (y != NULL) { + if (!BN_copy(y, point->Y)) + goto err; + BN_set_negative(y, 0); + } + ret = 1; + + err: + return ret; +} + +/* + * Computes a + b and stores the result in r. r could be a or b, a could be + * b. Uses algorithm A.10.2 of IEEE P1363. + */ +int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, + const EC_POINT *b, BN_CTX *ctx) +{ + BN_CTX *new_ctx = NULL; + BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t; + int ret = 0; + + if (EC_POINT_is_at_infinity(group, a)) { + if (!EC_POINT_copy(r, b)) + return 0; + return 1; + } + + if (EC_POINT_is_at_infinity(group, b)) { + if (!EC_POINT_copy(r, a)) + return 0; + return 1; + } + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + BN_CTX_start(ctx); + x0 = BN_CTX_get(ctx); + y0 = BN_CTX_get(ctx); + x1 = BN_CTX_get(ctx); + y1 = BN_CTX_get(ctx); + x2 = BN_CTX_get(ctx); + y2 = BN_CTX_get(ctx); + s = BN_CTX_get(ctx); + t = BN_CTX_get(ctx); + if (t == NULL) + goto err; + + if (a->Z_is_one) { + if (!BN_copy(x0, a->X)) + goto err; + if (!BN_copy(y0, a->Y)) + goto err; + } else { + if (!EC_POINT_get_affine_coordinates(group, a, x0, y0, ctx)) + goto err; + } + if (b->Z_is_one) { + if (!BN_copy(x1, b->X)) + goto err; + if (!BN_copy(y1, b->Y)) + goto err; + } else { + if (!EC_POINT_get_affine_coordinates(group, b, x1, y1, ctx)) + goto err; + } + + if (BN_GF2m_cmp(x0, x1)) { + if (!BN_GF2m_add(t, x0, x1)) + goto err; + if (!BN_GF2m_add(s, y0, y1)) + goto err; + if (!group->meth->field_div(group, s, s, t, ctx)) + goto err; + if (!group->meth->field_sqr(group, x2, s, ctx)) + goto err; + if (!BN_GF2m_add(x2, x2, group->a)) + goto err; + if (!BN_GF2m_add(x2, x2, s)) + goto err; + if (!BN_GF2m_add(x2, x2, t)) + goto err; + } else { + if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1)) { + if (!EC_POINT_set_to_infinity(group, r)) + goto err; + ret = 1; + goto err; + } + if (!group->meth->field_div(group, s, y1, x1, ctx)) + goto err; + if (!BN_GF2m_add(s, s, x1)) + goto err; + + if (!group->meth->field_sqr(group, x2, s, ctx)) + goto err; + if (!BN_GF2m_add(x2, x2, s)) + goto err; + if (!BN_GF2m_add(x2, x2, group->a)) + goto err; + } + + if (!BN_GF2m_add(y2, x1, x2)) + goto err; + if (!group->meth->field_mul(group, y2, y2, s, ctx)) + goto err; + if (!BN_GF2m_add(y2, y2, x2)) + goto err; + if (!BN_GF2m_add(y2, y2, y1)) + goto err; + + if (!EC_POINT_set_affine_coordinates(group, r, x2, y2, ctx)) + goto err; + + ret = 1; + + err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +/* + * Computes 2 * a and stores the result in r. r could be a. Uses algorithm + * A.10.2 of IEEE P1363. + */ +int ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, + BN_CTX *ctx) +{ + return ec_GF2m_simple_add(group, r, a, a, ctx); +} + +int ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) +{ + if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(point->Y)) + /* point is its own inverse */ + return 1; + + if (!EC_POINT_make_affine(group, point, ctx)) + return 0; + return BN_GF2m_add(point->Y, point->X, point->Y); +} + +/* Indicates whether the given point is the point at infinity. */ +int ec_GF2m_simple_is_at_infinity(const EC_GROUP *group, + const EC_POINT *point) +{ + return BN_is_zero(point->Z); +} + +/*- + * Determines whether the given EC_POINT is an actual point on the curve defined + * in the EC_GROUP. A point is valid if it satisfies the Weierstrass equation: + * y^2 + x*y = x^3 + a*x^2 + b. + */ +int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, + BN_CTX *ctx) +{ + int ret = -1; + BN_CTX *new_ctx = NULL; + BIGNUM *lh, *y2; + int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, + const BIGNUM *, BN_CTX *); + int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); + + if (EC_POINT_is_at_infinity(group, point)) + return 1; + + field_mul = group->meth->field_mul; + field_sqr = group->meth->field_sqr; + + /* only support affine coordinates */ + if (!point->Z_is_one) + return -1; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return -1; + } + + BN_CTX_start(ctx); + y2 = BN_CTX_get(ctx); + lh = BN_CTX_get(ctx); + if (lh == NULL) + goto err; + + /*- + * We have a curve defined by a Weierstrass equation + * y^2 + x*y = x^3 + a*x^2 + b. + * <=> x^3 + a*x^2 + x*y + b + y^2 = 0 + * <=> ((x + a) * x + y ) * x + b + y^2 = 0 + */ + if (!BN_GF2m_add(lh, point->X, group->a)) + goto err; + if (!field_mul(group, lh, lh, point->X, ctx)) + goto err; + if (!BN_GF2m_add(lh, lh, point->Y)) + goto err; + if (!field_mul(group, lh, lh, point->X, ctx)) + goto err; + if (!BN_GF2m_add(lh, lh, group->b)) + goto err; + if (!field_sqr(group, y2, point->Y, ctx)) + goto err; + if (!BN_GF2m_add(lh, lh, y2)) + goto err; + ret = BN_is_zero(lh); + + err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +/*- + * Indicates whether two points are equal. + * Return values: + * -1 error + * 0 equal (in affine coordinates) + * 1 not equal + */ +int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a, + const EC_POINT *b, BN_CTX *ctx) +{ + BIGNUM *aX, *aY, *bX, *bY; + BN_CTX *new_ctx = NULL; + int ret = -1; + + if (EC_POINT_is_at_infinity(group, a)) { + return EC_POINT_is_at_infinity(group, b) ? 0 : 1; + } + + if (EC_POINT_is_at_infinity(group, b)) + return 1; + + if (a->Z_is_one && b->Z_is_one) { + return ((BN_cmp(a->X, b->X) == 0) && BN_cmp(a->Y, b->Y) == 0) ? 0 : 1; + } + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return -1; + } + + BN_CTX_start(ctx); + aX = BN_CTX_get(ctx); + aY = BN_CTX_get(ctx); + bX = BN_CTX_get(ctx); + bY = BN_CTX_get(ctx); + if (bY == NULL) + goto err; + + if (!EC_POINT_get_affine_coordinates(group, a, aX, aY, ctx)) + goto err; + if (!EC_POINT_get_affine_coordinates(group, b, bX, bY, ctx)) + goto err; + ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1; + + err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +/* Forces the given EC_POINT to internally use affine coordinates. */ +int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point, + BN_CTX *ctx) +{ + BN_CTX *new_ctx = NULL; + BIGNUM *x, *y; + int ret = 0; + + if (point->Z_is_one || EC_POINT_is_at_infinity(group, point)) + return 1; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + BN_CTX_start(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (y == NULL) + goto err; + + if (!EC_POINT_get_affine_coordinates(group, point, x, y, ctx)) + goto err; + if (!BN_copy(point->X, x)) + goto err; + if (!BN_copy(point->Y, y)) + goto err; + if (!BN_one(point->Z)) + goto err; + point->Z_is_one = 1; + + ret = 1; + + err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +/* + * Forces each of the EC_POINTs in the given array to use affine coordinates. + */ +int ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num, + EC_POINT *points[], BN_CTX *ctx) +{ + size_t i; + + for (i = 0; i < num; i++) { + if (!group->meth->make_affine(group, points[i], ctx)) + return 0; + } + + return 1; +} + +/* Wrapper to simple binary polynomial field multiplication implementation. */ +int ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r, + const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) +{ + return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx); +} + +/* Wrapper to simple binary polynomial field squaring implementation. */ +int ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, + const BIGNUM *a, BN_CTX *ctx) +{ + return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx); +} + +/* Wrapper to simple binary polynomial field division implementation. */ +int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r, + const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) +{ + return BN_GF2m_mod_div(r, a, b, group->field, ctx); +} + +/*- + * Lopez-Dahab ladder, pre step. + * See e.g. "Guide to ECC" Alg 3.40. + * Modified to blind s and r independently. + * s:= p, r := 2p + */ +static +int ec_GF2m_simple_ladder_pre(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx) +{ + /* if p is not affine, something is wrong */ + if (p->Z_is_one == 0) + return 0; + + /* s blinding: make sure lambda (s->Z here) is not zero */ + do { + if (!BN_priv_rand(s->Z, BN_num_bits(group->field) - 1, + BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) { + ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_PRE, ERR_R_BN_LIB); + return 0; + } + } while (BN_is_zero(s->Z)); + + /* if field_encode defined convert between representations */ + if ((group->meth->field_encode != NULL + && !group->meth->field_encode(group, s->Z, s->Z, ctx)) + || !group->meth->field_mul(group, s->X, p->X, s->Z, ctx)) + return 0; + + /* r blinding: make sure lambda (r->Y here for storage) is not zero */ + do { + if (!BN_priv_rand(r->Y, BN_num_bits(group->field) - 1, + BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) { + ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_PRE, ERR_R_BN_LIB); + return 0; + } + } while (BN_is_zero(r->Y)); + + if ((group->meth->field_encode != NULL + && !group->meth->field_encode(group, r->Y, r->Y, ctx)) + || !group->meth->field_sqr(group, r->Z, p->X, ctx) + || !group->meth->field_sqr(group, r->X, r->Z, ctx) + || !BN_GF2m_add(r->X, r->X, group->b) + || !group->meth->field_mul(group, r->Z, r->Z, r->Y, ctx) + || !group->meth->field_mul(group, r->X, r->X, r->Y, ctx)) + return 0; + + s->Z_is_one = 0; + r->Z_is_one = 0; + + return 1; +} + +/*- + * Ladder step: differential addition-and-doubling, mixed Lopez-Dahab coords. + * http://www.hyperelliptic.org/EFD/g12o/auto-code/shortw/xz/ladder/mladd-2003-s.op3 + * s := r + s, r := 2r + */ +static +int ec_GF2m_simple_ladder_step(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx) +{ + if (!group->meth->field_mul(group, r->Y, r->Z, s->X, ctx) + || !group->meth->field_mul(group, s->X, r->X, s->Z, ctx) + || !group->meth->field_sqr(group, s->Y, r->Z, ctx) + || !group->meth->field_sqr(group, r->Z, r->X, ctx) + || !BN_GF2m_add(s->Z, r->Y, s->X) + || !group->meth->field_sqr(group, s->Z, s->Z, ctx) + || !group->meth->field_mul(group, s->X, r->Y, s->X, ctx) + || !group->meth->field_mul(group, r->Y, s->Z, p->X, ctx) + || !BN_GF2m_add(s->X, s->X, r->Y) + || !group->meth->field_sqr(group, r->Y, r->Z, ctx) + || !group->meth->field_mul(group, r->Z, r->Z, s->Y, ctx) + || !group->meth->field_sqr(group, s->Y, s->Y, ctx) + || !group->meth->field_mul(group, s->Y, s->Y, group->b, ctx) + || !BN_GF2m_add(r->X, r->Y, s->Y)) + return 0; + + return 1; +} + +/*- + * Recover affine (x,y) result from Lopez-Dahab r and s, affine p. + * See e.g. "Fast Multiplication on Elliptic Curves over GF(2**m) + * without Precomputation" (Lopez and Dahab, CHES 1999), + * Appendix Alg Mxy. + */ +static +int ec_GF2m_simple_ladder_post(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx) +{ + int ret = 0; + BIGNUM *t0, *t1, *t2 = NULL; + + if (BN_is_zero(r->Z)) + return EC_POINT_set_to_infinity(group, r); + + if (BN_is_zero(s->Z)) { + if (!EC_POINT_copy(r, p) + || !EC_POINT_invert(group, r, ctx)) { + ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_POST, ERR_R_EC_LIB); + return 0; + } + return 1; + } + + BN_CTX_start(ctx); + t0 = BN_CTX_get(ctx); + t1 = BN_CTX_get(ctx); + t2 = BN_CTX_get(ctx); + if (t2 == NULL) { + ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_POST, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!group->meth->field_mul(group, t0, r->Z, s->Z, ctx) + || !group->meth->field_mul(group, t1, p->X, r->Z, ctx) + || !BN_GF2m_add(t1, r->X, t1) + || !group->meth->field_mul(group, t2, p->X, s->Z, ctx) + || !group->meth->field_mul(group, r->Z, r->X, t2, ctx) + || !BN_GF2m_add(t2, t2, s->X) + || !group->meth->field_mul(group, t1, t1, t2, ctx) + || !group->meth->field_sqr(group, t2, p->X, ctx) + || !BN_GF2m_add(t2, p->Y, t2) + || !group->meth->field_mul(group, t2, t2, t0, ctx) + || !BN_GF2m_add(t1, t2, t1) + || !group->meth->field_mul(group, t2, p->X, t0, ctx) + || !group->meth->field_inv(group, t2, t2, ctx) + || !group->meth->field_mul(group, t1, t1, t2, ctx) + || !group->meth->field_mul(group, r->X, r->Z, t2, ctx) + || !BN_GF2m_add(t2, p->X, r->X) + || !group->meth->field_mul(group, t2, t2, t1, ctx) + || !BN_GF2m_add(r->Y, p->Y, t2) + || !BN_one(r->Z)) + goto err; + + r->Z_is_one = 1; + + /* GF(2^m) field elements should always have BIGNUM::neg = 0 */ + BN_set_negative(r->X, 0); + BN_set_negative(r->Y, 0); + + ret = 1; + + err: + BN_CTX_end(ctx); + return ret; +} + +static +int ec_GF2m_simple_points_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], + const BIGNUM *scalars[], + BN_CTX *ctx) +{ + int ret = 0; + EC_POINT *t = NULL; + + /*- + * We limit use of the ladder only to the following cases: + * - r := scalar * G + * Fixed point mul: scalar != NULL && num == 0; + * - r := scalars[0] * points[0] + * Variable point mul: scalar == NULL && num == 1; + * - r := scalar * G + scalars[0] * points[0] + * used, e.g., in ECDSA verification: scalar != NULL && num == 1 + * + * In any other case (num > 1) we use the default wNAF implementation. + * + * We also let the default implementation handle degenerate cases like group + * order or cofactor set to 0. + */ + if (num > 1 || BN_is_zero(group->order) || BN_is_zero(group->cofactor)) + return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx); + + if (scalar != NULL && num == 0) + /* Fixed point multiplication */ + return ec_scalar_mul_ladder(group, r, scalar, NULL, ctx); + + if (scalar == NULL && num == 1) + /* Variable point multiplication */ + return ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx); + + /*- + * Double point multiplication: + * r := scalar * G + scalars[0] * points[0] + */ + + if ((t = EC_POINT_new(group)) == NULL) { + ECerr(EC_F_EC_GF2M_SIMPLE_POINTS_MUL, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (!ec_scalar_mul_ladder(group, t, scalar, NULL, ctx) + || !ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx) + || !EC_POINT_add(group, r, t, r, ctx)) + goto err; + + ret = 1; + + err: + EC_POINT_free(t); + return ret; +} + +/*- + * Computes the multiplicative inverse of a in GF(2^m), storing the result in r. + * If a is zero (or equivalent), you'll get a EC_R_CANNOT_INVERT error. + * SCA hardening is with blinding: BN_GF2m_mod_inv does that. + */ +static int ec_GF2m_simple_field_inv(const EC_GROUP *group, BIGNUM *r, + const BIGNUM *a, BN_CTX *ctx) +{ + int ret; + + if (!(ret = BN_GF2m_mod_inv(r, a, group->field, ctx))) + ECerr(EC_F_EC_GF2M_SIMPLE_FIELD_INV, EC_R_CANNOT_INVERT); + return ret; +} + +const EC_METHOD *EC_GF2m_simple_method(void) +{ + static const EC_METHOD ret = { + EC_FLAGS_DEFAULT_OCT, + NID_X9_62_characteristic_two_field, + ec_GF2m_simple_group_init, + ec_GF2m_simple_group_finish, + ec_GF2m_simple_group_clear_finish, + ec_GF2m_simple_group_copy, + ec_GF2m_simple_group_set_curve, + ec_GF2m_simple_group_get_curve, + ec_GF2m_simple_group_get_degree, + ec_group_simple_order_bits, + ec_GF2m_simple_group_check_discriminant, + ec_GF2m_simple_point_init, + ec_GF2m_simple_point_finish, + ec_GF2m_simple_point_clear_finish, + ec_GF2m_simple_point_copy, + ec_GF2m_simple_point_set_to_infinity, + 0, /* set_Jprojective_coordinates_GFp */ + 0, /* get_Jprojective_coordinates_GFp */ + ec_GF2m_simple_point_set_affine_coordinates, + ec_GF2m_simple_point_get_affine_coordinates, + 0, /* point_set_compressed_coordinates */ + 0, /* point2oct */ + 0, /* oct2point */ + ec_GF2m_simple_add, + ec_GF2m_simple_dbl, + ec_GF2m_simple_invert, + ec_GF2m_simple_is_at_infinity, + ec_GF2m_simple_is_on_curve, + ec_GF2m_simple_cmp, + ec_GF2m_simple_make_affine, + ec_GF2m_simple_points_make_affine, + ec_GF2m_simple_points_mul, + 0, /* precompute_mult */ + 0, /* have_precompute_mult */ + ec_GF2m_simple_field_mul, + ec_GF2m_simple_field_sqr, + ec_GF2m_simple_field_div, + ec_GF2m_simple_field_inv, + 0, /* field_encode */ + 0, /* field_decode */ + 0, /* field_set_to_one */ + ec_key_simple_priv2oct, + ec_key_simple_oct2priv, + 0, /* set private */ + ec_key_simple_generate_key, + ec_key_simple_check_key, + ec_key_simple_generate_public_key, + 0, /* keycopy */ + 0, /* keyfinish */ + ecdh_simple_compute_key, + 0, /* field_inverse_mod_ord */ + 0, /* blind_coordinates */ + ec_GF2m_simple_ladder_pre, + ec_GF2m_simple_ladder_step, + ec_GF2m_simple_ladder_post + }; + + return &ret; +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_ameth.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_ameth.c new file mode 100644 index 000000000..8b363e096 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_ameth.c @@ -0,0 +1,942 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include "internal/asn1_int.h" +#include "internal/evp_int.h" +#include "ec_lcl.h" + +#ifndef OPENSSL_NO_CMS +static int ecdh_cms_decrypt(CMS_RecipientInfo *ri); +static int ecdh_cms_encrypt(CMS_RecipientInfo *ri); +#endif + +static int eckey_param2type(int *pptype, void **ppval, EC_KEY *ec_key) +{ + const EC_GROUP *group; + int nid; + if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) { + ECerr(EC_F_ECKEY_PARAM2TYPE, EC_R_MISSING_PARAMETERS); + return 0; + } + if (EC_GROUP_get_asn1_flag(group) + && (nid = EC_GROUP_get_curve_name(group))) + /* we have a 'named curve' => just set the OID */ + { + *ppval = OBJ_nid2obj(nid); + *pptype = V_ASN1_OBJECT; + } else { /* explicit parameters */ + + ASN1_STRING *pstr = NULL; + pstr = ASN1_STRING_new(); + if (pstr == NULL) + return 0; + pstr->length = i2d_ECParameters(ec_key, &pstr->data); + if (pstr->length <= 0) { + ASN1_STRING_free(pstr); + ECerr(EC_F_ECKEY_PARAM2TYPE, ERR_R_EC_LIB); + return 0; + } + *ppval = pstr; + *pptype = V_ASN1_SEQUENCE; + } + return 1; +} + +static int eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) +{ + EC_KEY *ec_key = pkey->pkey.ec; + void *pval = NULL; + int ptype; + unsigned char *penc = NULL, *p; + int penclen; + + if (!eckey_param2type(&ptype, &pval, ec_key)) { + ECerr(EC_F_ECKEY_PUB_ENCODE, ERR_R_EC_LIB); + return 0; + } + penclen = i2o_ECPublicKey(ec_key, NULL); + if (penclen <= 0) + goto err; + penc = OPENSSL_malloc(penclen); + if (penc == NULL) + goto err; + p = penc; + penclen = i2o_ECPublicKey(ec_key, &p); + if (penclen <= 0) + goto err; + if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_EC), + ptype, pval, penc, penclen)) + return 1; + err: + if (ptype == V_ASN1_OBJECT) + ASN1_OBJECT_free(pval); + else + ASN1_STRING_free(pval); + OPENSSL_free(penc); + return 0; +} + +static EC_KEY *eckey_type2param(int ptype, const void *pval) +{ + EC_KEY *eckey = NULL; + EC_GROUP *group = NULL; + + if (ptype == V_ASN1_SEQUENCE) { + const ASN1_STRING *pstr = pval; + const unsigned char *pm = pstr->data; + int pmlen = pstr->length; + + if ((eckey = d2i_ECParameters(NULL, &pm, pmlen)) == NULL) { + ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR); + goto ecerr; + } + } else if (ptype == V_ASN1_OBJECT) { + const ASN1_OBJECT *poid = pval; + + /* + * type == V_ASN1_OBJECT => the parameters are given by an asn1 OID + */ + if ((eckey = EC_KEY_new()) == NULL) { + ECerr(EC_F_ECKEY_TYPE2PARAM, ERR_R_MALLOC_FAILURE); + goto ecerr; + } + group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(poid)); + if (group == NULL) + goto ecerr; + EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); + if (EC_KEY_set_group(eckey, group) == 0) + goto ecerr; + EC_GROUP_free(group); + } else { + ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR); + goto ecerr; + } + + return eckey; + + ecerr: + EC_KEY_free(eckey); + EC_GROUP_free(group); + return NULL; +} + +static int eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) +{ + const unsigned char *p = NULL; + const void *pval; + int ptype, pklen; + EC_KEY *eckey = NULL; + X509_ALGOR *palg; + + if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey)) + return 0; + X509_ALGOR_get0(NULL, &ptype, &pval, palg); + + eckey = eckey_type2param(ptype, pval); + + if (!eckey) { + ECerr(EC_F_ECKEY_PUB_DECODE, ERR_R_EC_LIB); + return 0; + } + + /* We have parameters now set public key */ + if (!o2i_ECPublicKey(&eckey, &p, pklen)) { + ECerr(EC_F_ECKEY_PUB_DECODE, EC_R_DECODE_ERROR); + goto ecerr; + } + + EVP_PKEY_assign_EC_KEY(pkey, eckey); + return 1; + + ecerr: + EC_KEY_free(eckey); + return 0; +} + +static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) +{ + int r; + const EC_GROUP *group = EC_KEY_get0_group(b->pkey.ec); + const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec), + *pb = EC_KEY_get0_public_key(b->pkey.ec); + if (group == NULL || pa == NULL || pb == NULL) + return -2; + r = EC_POINT_cmp(group, pa, pb, NULL); + if (r == 0) + return 1; + if (r == 1) + return 0; + return -2; +} + +static int eckey_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8) +{ + const unsigned char *p = NULL; + const void *pval; + int ptype, pklen; + EC_KEY *eckey = NULL; + const X509_ALGOR *palg; + + if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8)) + return 0; + X509_ALGOR_get0(NULL, &ptype, &pval, palg); + + eckey = eckey_type2param(ptype, pval); + + if (!eckey) + goto ecliberr; + + /* We have parameters now set private key */ + if (!d2i_ECPrivateKey(&eckey, &p, pklen)) { + ECerr(EC_F_ECKEY_PRIV_DECODE, EC_R_DECODE_ERROR); + goto ecerr; + } + + EVP_PKEY_assign_EC_KEY(pkey, eckey); + return 1; + + ecliberr: + ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB); + ecerr: + EC_KEY_free(eckey); + return 0; +} + +static int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) +{ + EC_KEY ec_key = *(pkey->pkey.ec); + unsigned char *ep, *p; + int eplen, ptype; + void *pval; + unsigned int old_flags; + + if (!eckey_param2type(&ptype, &pval, &ec_key)) { + ECerr(EC_F_ECKEY_PRIV_ENCODE, EC_R_DECODE_ERROR); + return 0; + } + + /* set the private key */ + + /* + * do not include the parameters in the SEC1 private key see PKCS#11 + * 12.11 + */ + old_flags = EC_KEY_get_enc_flags(&ec_key); + EC_KEY_set_enc_flags(&ec_key, old_flags | EC_PKEY_NO_PARAMETERS); + + eplen = i2d_ECPrivateKey(&ec_key, NULL); + if (!eplen) { + ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB); + return 0; + } + ep = OPENSSL_malloc(eplen); + if (ep == NULL) { + ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_MALLOC_FAILURE); + return 0; + } + p = ep; + if (!i2d_ECPrivateKey(&ec_key, &p)) { + OPENSSL_free(ep); + ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB); + return 0; + } + + if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), 0, + ptype, pval, ep, eplen)) { + OPENSSL_free(ep); + return 0; + } + + return 1; +} + +static int int_ec_size(const EVP_PKEY *pkey) +{ + return ECDSA_size(pkey->pkey.ec); +} + +static int ec_bits(const EVP_PKEY *pkey) +{ + return EC_GROUP_order_bits(EC_KEY_get0_group(pkey->pkey.ec)); +} + +static int ec_security_bits(const EVP_PKEY *pkey) +{ + int ecbits = ec_bits(pkey); + if (ecbits >= 512) + return 256; + if (ecbits >= 384) + return 192; + if (ecbits >= 256) + return 128; + if (ecbits >= 224) + return 112; + if (ecbits >= 160) + return 80; + return ecbits / 2; +} + +static int ec_missing_parameters(const EVP_PKEY *pkey) +{ + if (pkey->pkey.ec == NULL || EC_KEY_get0_group(pkey->pkey.ec) == NULL) + return 1; + return 0; +} + +static int ec_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) +{ + EC_GROUP *group = EC_GROUP_dup(EC_KEY_get0_group(from->pkey.ec)); + + if (group == NULL) + return 0; + if (to->pkey.ec == NULL) { + to->pkey.ec = EC_KEY_new(); + if (to->pkey.ec == NULL) + goto err; + } + if (EC_KEY_set_group(to->pkey.ec, group) == 0) + goto err; + EC_GROUP_free(group); + return 1; + err: + EC_GROUP_free(group); + return 0; +} + +static int ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) +{ + const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec), + *group_b = EC_KEY_get0_group(b->pkey.ec); + if (group_a == NULL || group_b == NULL) + return -2; + if (EC_GROUP_cmp(group_a, group_b, NULL)) + return 0; + else + return 1; +} + +static void int_ec_free(EVP_PKEY *pkey) +{ + EC_KEY_free(pkey->pkey.ec); +} + +typedef enum { + EC_KEY_PRINT_PRIVATE, + EC_KEY_PRINT_PUBLIC, + EC_KEY_PRINT_PARAM +} ec_print_t; + +static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, ec_print_t ktype) +{ + const char *ecstr; + unsigned char *priv = NULL, *pub = NULL; + size_t privlen = 0, publen = 0; + int ret = 0; + const EC_GROUP *group; + + if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) { + ECerr(EC_F_DO_EC_KEY_PRINT, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (ktype != EC_KEY_PRINT_PARAM && EC_KEY_get0_public_key(x) != NULL) { + publen = EC_KEY_key2buf(x, EC_KEY_get_conv_form(x), &pub, NULL); + if (publen == 0) + goto err; + } + + if (ktype == EC_KEY_PRINT_PRIVATE && EC_KEY_get0_private_key(x) != NULL) { + privlen = EC_KEY_priv2buf(x, &priv); + if (privlen == 0) + goto err; + } + + if (ktype == EC_KEY_PRINT_PRIVATE) + ecstr = "Private-Key"; + else if (ktype == EC_KEY_PRINT_PUBLIC) + ecstr = "Public-Key"; + else + ecstr = "ECDSA-Parameters"; + + if (!BIO_indent(bp, off, 128)) + goto err; + if (BIO_printf(bp, "%s: (%d bit)\n", ecstr, + EC_GROUP_order_bits(group)) <= 0) + goto err; + + if (privlen != 0) { + if (BIO_printf(bp, "%*spriv:\n", off, "") <= 0) + goto err; + if (ASN1_buf_print(bp, priv, privlen, off + 4) == 0) + goto err; + } + + if (publen != 0) { + if (BIO_printf(bp, "%*spub:\n", off, "") <= 0) + goto err; + if (ASN1_buf_print(bp, pub, publen, off + 4) == 0) + goto err; + } + + if (!ECPKParameters_print(bp, group, off)) + goto err; + ret = 1; + err: + if (!ret) + ECerr(EC_F_DO_EC_KEY_PRINT, ERR_R_EC_LIB); + OPENSSL_clear_free(priv, privlen); + OPENSSL_free(pub); + return ret; +} + +static int eckey_param_decode(EVP_PKEY *pkey, + const unsigned char **pder, int derlen) +{ + EC_KEY *eckey; + + if ((eckey = d2i_ECParameters(NULL, pder, derlen)) == NULL) { + ECerr(EC_F_ECKEY_PARAM_DECODE, ERR_R_EC_LIB); + return 0; + } + EVP_PKEY_assign_EC_KEY(pkey, eckey); + return 1; +} + +static int eckey_param_encode(const EVP_PKEY *pkey, unsigned char **pder) +{ + return i2d_ECParameters(pkey->pkey.ec, pder); +} + +static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *ctx) +{ + return do_EC_KEY_print(bp, pkey->pkey.ec, indent, EC_KEY_PRINT_PARAM); +} + +static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *ctx) +{ + return do_EC_KEY_print(bp, pkey->pkey.ec, indent, EC_KEY_PRINT_PUBLIC); +} + +static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *ctx) +{ + return do_EC_KEY_print(bp, pkey->pkey.ec, indent, EC_KEY_PRINT_PRIVATE); +} + +static int old_ec_priv_decode(EVP_PKEY *pkey, + const unsigned char **pder, int derlen) +{ + EC_KEY *ec; + + if ((ec = d2i_ECPrivateKey(NULL, pder, derlen)) == NULL) { + ECerr(EC_F_OLD_EC_PRIV_DECODE, EC_R_DECODE_ERROR); + return 0; + } + EVP_PKEY_assign_EC_KEY(pkey, ec); + return 1; +} + +static int old_ec_priv_encode(const EVP_PKEY *pkey, unsigned char **pder) +{ + return i2d_ECPrivateKey(pkey->pkey.ec, pder); +} + +static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) +{ + switch (op) { + case ASN1_PKEY_CTRL_PKCS7_SIGN: + if (arg1 == 0) { + int snid, hnid; + X509_ALGOR *alg1, *alg2; + PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2); + if (alg1 == NULL || alg1->algorithm == NULL) + return -1; + hnid = OBJ_obj2nid(alg1->algorithm); + if (hnid == NID_undef) + return -1; + if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey))) + return -1; + X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0); + } + return 1; +#ifndef OPENSSL_NO_CMS + case ASN1_PKEY_CTRL_CMS_SIGN: + if (arg1 == 0) { + int snid, hnid; + X509_ALGOR *alg1, *alg2; + CMS_SignerInfo_get0_algs(arg2, NULL, NULL, &alg1, &alg2); + if (alg1 == NULL || alg1->algorithm == NULL) + return -1; + hnid = OBJ_obj2nid(alg1->algorithm); + if (hnid == NID_undef) + return -1; + if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey))) + return -1; + X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0); + } + return 1; + + case ASN1_PKEY_CTRL_CMS_ENVELOPE: + if (arg1 == 1) + return ecdh_cms_decrypt(arg2); + else if (arg1 == 0) + return ecdh_cms_encrypt(arg2); + return -2; + + case ASN1_PKEY_CTRL_CMS_RI_TYPE: + *(int *)arg2 = CMS_RECIPINFO_AGREE; + return 1; +#endif + + case ASN1_PKEY_CTRL_DEFAULT_MD_NID: + *(int *)arg2 = NID_sha256; + return 1; + + case ASN1_PKEY_CTRL_SET1_TLS_ENCPT: + return EC_KEY_oct2key(EVP_PKEY_get0_EC_KEY(pkey), arg2, arg1, NULL); + + case ASN1_PKEY_CTRL_GET1_TLS_ENCPT: + return EC_KEY_key2buf(EVP_PKEY_get0_EC_KEY(pkey), + POINT_CONVERSION_UNCOMPRESSED, arg2, NULL); + + default: + return -2; + + } + +} + +static int ec_pkey_check(const EVP_PKEY *pkey) +{ + EC_KEY *eckey = pkey->pkey.ec; + + /* stay consistent to what EVP_PKEY_check demands */ + if (eckey->priv_key == NULL) { + ECerr(EC_F_EC_PKEY_CHECK, EC_R_MISSING_PRIVATE_KEY); + return 0; + } + + return EC_KEY_check_key(eckey); +} + +static int ec_pkey_public_check(const EVP_PKEY *pkey) +{ + EC_KEY *eckey = pkey->pkey.ec; + + /* + * Note: it unnecessary to check eckey->pub_key here since + * it will be checked in EC_KEY_check_key(). In fact, the + * EC_KEY_check_key() mainly checks the public key, and checks + * the private key optionally (only if there is one). So if + * someone passes a whole EC key (public + private), this + * will also work... + */ + + return EC_KEY_check_key(eckey); +} + +static int ec_pkey_param_check(const EVP_PKEY *pkey) +{ + EC_KEY *eckey = pkey->pkey.ec; + + /* stay consistent to what EVP_PKEY_check demands */ + if (eckey->group == NULL) { + ECerr(EC_F_EC_PKEY_PARAM_CHECK, EC_R_MISSING_PARAMETERS); + return 0; + } + + return EC_GROUP_check(eckey->group, NULL); +} + +const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = { + EVP_PKEY_EC, + EVP_PKEY_EC, + 0, + "EC", + "OpenSSL EC algorithm", + + eckey_pub_decode, + eckey_pub_encode, + eckey_pub_cmp, + eckey_pub_print, + + eckey_priv_decode, + eckey_priv_encode, + eckey_priv_print, + + int_ec_size, + ec_bits, + ec_security_bits, + + eckey_param_decode, + eckey_param_encode, + ec_missing_parameters, + ec_copy_parameters, + ec_cmp_parameters, + eckey_param_print, + 0, + + int_ec_free, + ec_pkey_ctrl, + old_ec_priv_decode, + old_ec_priv_encode, + + 0, 0, 0, + + ec_pkey_check, + ec_pkey_public_check, + ec_pkey_param_check +}; + +#if !defined(OPENSSL_NO_SM2) +const EVP_PKEY_ASN1_METHOD sm2_asn1_meth = { + EVP_PKEY_SM2, + EVP_PKEY_EC, + ASN1_PKEY_ALIAS +}; +#endif + +int EC_KEY_print(BIO *bp, const EC_KEY *x, int off) +{ + int private = EC_KEY_get0_private_key(x) != NULL; + + return do_EC_KEY_print(bp, x, off, + private ? EC_KEY_PRINT_PRIVATE : EC_KEY_PRINT_PUBLIC); +} + +int ECParameters_print(BIO *bp, const EC_KEY *x) +{ + return do_EC_KEY_print(bp, x, 4, EC_KEY_PRINT_PARAM); +} + +#ifndef OPENSSL_NO_CMS + +static int ecdh_cms_set_peerkey(EVP_PKEY_CTX *pctx, + X509_ALGOR *alg, ASN1_BIT_STRING *pubkey) +{ + const ASN1_OBJECT *aoid; + int atype; + const void *aval; + int rv = 0; + EVP_PKEY *pkpeer = NULL; + EC_KEY *ecpeer = NULL; + const unsigned char *p; + int plen; + X509_ALGOR_get0(&aoid, &atype, &aval, alg); + if (OBJ_obj2nid(aoid) != NID_X9_62_id_ecPublicKey) + goto err; + /* If absent parameters get group from main key */ + if (atype == V_ASN1_UNDEF || atype == V_ASN1_NULL) { + const EC_GROUP *grp; + EVP_PKEY *pk; + pk = EVP_PKEY_CTX_get0_pkey(pctx); + if (!pk) + goto err; + grp = EC_KEY_get0_group(pk->pkey.ec); + ecpeer = EC_KEY_new(); + if (ecpeer == NULL) + goto err; + if (!EC_KEY_set_group(ecpeer, grp)) + goto err; + } else { + ecpeer = eckey_type2param(atype, aval); + if (!ecpeer) + goto err; + } + /* We have parameters now set public key */ + plen = ASN1_STRING_length(pubkey); + p = ASN1_STRING_get0_data(pubkey); + if (!p || !plen) + goto err; + if (!o2i_ECPublicKey(&ecpeer, &p, plen)) + goto err; + pkpeer = EVP_PKEY_new(); + if (pkpeer == NULL) + goto err; + EVP_PKEY_set1_EC_KEY(pkpeer, ecpeer); + if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0) + rv = 1; + err: + EC_KEY_free(ecpeer); + EVP_PKEY_free(pkpeer); + return rv; +} + +/* Set KDF parameters based on KDF NID */ +static int ecdh_cms_set_kdf_param(EVP_PKEY_CTX *pctx, int eckdf_nid) +{ + int kdf_nid, kdfmd_nid, cofactor; + const EVP_MD *kdf_md; + if (eckdf_nid == NID_undef) + return 0; + + /* Lookup KDF type, cofactor mode and digest */ + if (!OBJ_find_sigid_algs(eckdf_nid, &kdfmd_nid, &kdf_nid)) + return 0; + + if (kdf_nid == NID_dh_std_kdf) + cofactor = 0; + else if (kdf_nid == NID_dh_cofactor_kdf) + cofactor = 1; + else + return 0; + + if (EVP_PKEY_CTX_set_ecdh_cofactor_mode(pctx, cofactor) <= 0) + return 0; + + if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_X9_63) <= 0) + return 0; + + kdf_md = EVP_get_digestbynid(kdfmd_nid); + if (!kdf_md) + return 0; + + if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0) + return 0; + return 1; +} + +static int ecdh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri) +{ + int rv = 0; + + X509_ALGOR *alg, *kekalg = NULL; + ASN1_OCTET_STRING *ukm; + const unsigned char *p; + unsigned char *der = NULL; + int plen, keylen; + const EVP_CIPHER *kekcipher; + EVP_CIPHER_CTX *kekctx; + + if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm)) + return 0; + + if (!ecdh_cms_set_kdf_param(pctx, OBJ_obj2nid(alg->algorithm))) { + ECerr(EC_F_ECDH_CMS_SET_SHARED_INFO, EC_R_KDF_PARAMETER_ERROR); + return 0; + } + + if (alg->parameter->type != V_ASN1_SEQUENCE) + return 0; + + p = alg->parameter->value.sequence->data; + plen = alg->parameter->value.sequence->length; + kekalg = d2i_X509_ALGOR(NULL, &p, plen); + if (!kekalg) + goto err; + kekctx = CMS_RecipientInfo_kari_get0_ctx(ri); + if (!kekctx) + goto err; + kekcipher = EVP_get_cipherbyobj(kekalg->algorithm); + if (!kekcipher || EVP_CIPHER_mode(kekcipher) != EVP_CIPH_WRAP_MODE) + goto err; + if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL)) + goto err; + if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0) + goto err; + + keylen = EVP_CIPHER_CTX_key_length(kekctx); + if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0) + goto err; + + plen = CMS_SharedInfo_encode(&der, kekalg, ukm, keylen); + + if (!plen) + goto err; + + if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, der, plen) <= 0) + goto err; + der = NULL; + + rv = 1; + err: + X509_ALGOR_free(kekalg); + OPENSSL_free(der); + return rv; +} + +static int ecdh_cms_decrypt(CMS_RecipientInfo *ri) +{ + EVP_PKEY_CTX *pctx; + pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); + if (!pctx) + return 0; + /* See if we need to set peer key */ + if (!EVP_PKEY_CTX_get0_peerkey(pctx)) { + X509_ALGOR *alg; + ASN1_BIT_STRING *pubkey; + if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &alg, &pubkey, + NULL, NULL, NULL)) + return 0; + if (!alg || !pubkey) + return 0; + if (!ecdh_cms_set_peerkey(pctx, alg, pubkey)) { + ECerr(EC_F_ECDH_CMS_DECRYPT, EC_R_PEER_KEY_ERROR); + return 0; + } + } + /* Set ECDH derivation parameters and initialise unwrap context */ + if (!ecdh_cms_set_shared_info(pctx, ri)) { + ECerr(EC_F_ECDH_CMS_DECRYPT, EC_R_SHARED_INFO_ERROR); + return 0; + } + return 1; +} + +static int ecdh_cms_encrypt(CMS_RecipientInfo *ri) +{ + EVP_PKEY_CTX *pctx; + EVP_PKEY *pkey; + EVP_CIPHER_CTX *ctx; + int keylen; + X509_ALGOR *talg, *wrap_alg = NULL; + const ASN1_OBJECT *aoid; + ASN1_BIT_STRING *pubkey; + ASN1_STRING *wrap_str; + ASN1_OCTET_STRING *ukm; + unsigned char *penc = NULL; + int penclen; + int rv = 0; + int ecdh_nid, kdf_type, kdf_nid, wrap_nid; + const EVP_MD *kdf_md; + pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); + if (!pctx) + return 0; + /* Get ephemeral key */ + pkey = EVP_PKEY_CTX_get0_pkey(pctx); + if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey, + NULL, NULL, NULL)) + goto err; + X509_ALGOR_get0(&aoid, NULL, NULL, talg); + /* Is everything uninitialised? */ + if (aoid == OBJ_nid2obj(NID_undef)) { + + EC_KEY *eckey = pkey->pkey.ec; + /* Set the key */ + unsigned char *p; + + penclen = i2o_ECPublicKey(eckey, NULL); + if (penclen <= 0) + goto err; + penc = OPENSSL_malloc(penclen); + if (penc == NULL) + goto err; + p = penc; + penclen = i2o_ECPublicKey(eckey, &p); + if (penclen <= 0) + goto err; + ASN1_STRING_set0(pubkey, penc, penclen); + pubkey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + pubkey->flags |= ASN1_STRING_FLAG_BITS_LEFT; + + penc = NULL; + X509_ALGOR_set0(talg, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), + V_ASN1_UNDEF, NULL); + } + + /* See if custom parameters set */ + kdf_type = EVP_PKEY_CTX_get_ecdh_kdf_type(pctx); + if (kdf_type <= 0) + goto err; + if (!EVP_PKEY_CTX_get_ecdh_kdf_md(pctx, &kdf_md)) + goto err; + ecdh_nid = EVP_PKEY_CTX_get_ecdh_cofactor_mode(pctx); + if (ecdh_nid < 0) + goto err; + else if (ecdh_nid == 0) + ecdh_nid = NID_dh_std_kdf; + else if (ecdh_nid == 1) + ecdh_nid = NID_dh_cofactor_kdf; + + if (kdf_type == EVP_PKEY_ECDH_KDF_NONE) { + kdf_type = EVP_PKEY_ECDH_KDF_X9_63; + if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, kdf_type) <= 0) + goto err; + } else + /* Unknown KDF */ + goto err; + if (kdf_md == NULL) { + /* Fixme later for better MD */ + kdf_md = EVP_sha1(); + if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0) + goto err; + } + + if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm)) + goto err; + + /* Lookup NID for KDF+cofactor+digest */ + + if (!OBJ_find_sigid_by_algs(&kdf_nid, EVP_MD_type(kdf_md), ecdh_nid)) + goto err; + /* Get wrap NID */ + ctx = CMS_RecipientInfo_kari_get0_ctx(ri); + wrap_nid = EVP_CIPHER_CTX_type(ctx); + keylen = EVP_CIPHER_CTX_key_length(ctx); + + /* Package wrap algorithm in an AlgorithmIdentifier */ + + wrap_alg = X509_ALGOR_new(); + if (wrap_alg == NULL) + goto err; + wrap_alg->algorithm = OBJ_nid2obj(wrap_nid); + wrap_alg->parameter = ASN1_TYPE_new(); + if (wrap_alg->parameter == NULL) + goto err; + if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0) + goto err; + if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef) { + ASN1_TYPE_free(wrap_alg->parameter); + wrap_alg->parameter = NULL; + } + + if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0) + goto err; + + penclen = CMS_SharedInfo_encode(&penc, wrap_alg, ukm, keylen); + + if (!penclen) + goto err; + + if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, penc, penclen) <= 0) + goto err; + penc = NULL; + + /* + * Now need to wrap encoding of wrap AlgorithmIdentifier into parameter + * of another AlgorithmIdentifier. + */ + penclen = i2d_X509_ALGOR(wrap_alg, &penc); + if (!penc || !penclen) + goto err; + wrap_str = ASN1_STRING_new(); + if (wrap_str == NULL) + goto err; + ASN1_STRING_set0(wrap_str, penc, penclen); + penc = NULL; + X509_ALGOR_set0(talg, OBJ_nid2obj(kdf_nid), V_ASN1_SEQUENCE, wrap_str); + + rv = 1; + + err: + OPENSSL_free(penc); + X509_ALGOR_free(wrap_alg); + return rv; +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_asn1.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_asn1.c new file mode 100644 index 000000000..13c56a621 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_asn1.c @@ -0,0 +1,1221 @@ +/* + * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "ec_lcl.h" +#include +#include +#include +#include "internal/nelem.h" + +int EC_GROUP_get_basis_type(const EC_GROUP *group) +{ + int i; + + if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != + NID_X9_62_characteristic_two_field) + /* everything else is currently not supported */ + return 0; + + /* Find the last non-zero element of group->poly[] */ + for (i = 0; + i < (int)OSSL_NELEM(group->poly) && group->poly[i] != 0; + i++) + continue; + + if (i == 4) + return NID_X9_62_ppBasis; + else if (i == 2) + return NID_X9_62_tpBasis; + else + /* everything else is currently not supported */ + return 0; +} + +#ifndef OPENSSL_NO_EC2M +int EC_GROUP_get_trinomial_basis(const EC_GROUP *group, unsigned int *k) +{ + if (group == NULL) + return 0; + + if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != + NID_X9_62_characteristic_two_field + || !((group->poly[0] != 0) && (group->poly[1] != 0) + && (group->poly[2] == 0))) { + ECerr(EC_F_EC_GROUP_GET_TRINOMIAL_BASIS, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + if (k) + *k = group->poly[1]; + + return 1; +} + +int EC_GROUP_get_pentanomial_basis(const EC_GROUP *group, unsigned int *k1, + unsigned int *k2, unsigned int *k3) +{ + if (group == NULL) + return 0; + + if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != + NID_X9_62_characteristic_two_field + || !((group->poly[0] != 0) && (group->poly[1] != 0) + && (group->poly[2] != 0) && (group->poly[3] != 0) + && (group->poly[4] == 0))) { + ECerr(EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + if (k1) + *k1 = group->poly[3]; + if (k2) + *k2 = group->poly[2]; + if (k3) + *k3 = group->poly[1]; + + return 1; +} +#endif + +/* some structures needed for the asn1 encoding */ +typedef struct x9_62_pentanomial_st { + int32_t k1; + int32_t k2; + int32_t k3; +} X9_62_PENTANOMIAL; + +typedef struct x9_62_characteristic_two_st { + int32_t m; + ASN1_OBJECT *type; + union { + char *ptr; + /* NID_X9_62_onBasis */ + ASN1_NULL *onBasis; + /* NID_X9_62_tpBasis */ + ASN1_INTEGER *tpBasis; + /* NID_X9_62_ppBasis */ + X9_62_PENTANOMIAL *ppBasis; + /* anything else */ + ASN1_TYPE *other; + } p; +} X9_62_CHARACTERISTIC_TWO; + +typedef struct x9_62_fieldid_st { + ASN1_OBJECT *fieldType; + union { + char *ptr; + /* NID_X9_62_prime_field */ + ASN1_INTEGER *prime; + /* NID_X9_62_characteristic_two_field */ + X9_62_CHARACTERISTIC_TWO *char_two; + /* anything else */ + ASN1_TYPE *other; + } p; +} X9_62_FIELDID; + +typedef struct x9_62_curve_st { + ASN1_OCTET_STRING *a; + ASN1_OCTET_STRING *b; + ASN1_BIT_STRING *seed; +} X9_62_CURVE; + +struct ec_parameters_st { + int32_t version; + X9_62_FIELDID *fieldID; + X9_62_CURVE *curve; + ASN1_OCTET_STRING *base; + ASN1_INTEGER *order; + ASN1_INTEGER *cofactor; +} /* ECPARAMETERS */ ; + +struct ecpk_parameters_st { + int type; + union { + ASN1_OBJECT *named_curve; + ECPARAMETERS *parameters; + ASN1_NULL *implicitlyCA; + } value; +} /* ECPKPARAMETERS */ ; + +/* SEC1 ECPrivateKey */ +typedef struct ec_privatekey_st { + int32_t version; + ASN1_OCTET_STRING *privateKey; + ECPKPARAMETERS *parameters; + ASN1_BIT_STRING *publicKey; +} EC_PRIVATEKEY; + +/* the OpenSSL ASN.1 definitions */ +ASN1_SEQUENCE(X9_62_PENTANOMIAL) = { + ASN1_EMBED(X9_62_PENTANOMIAL, k1, INT32), + ASN1_EMBED(X9_62_PENTANOMIAL, k2, INT32), + ASN1_EMBED(X9_62_PENTANOMIAL, k3, INT32) +} static_ASN1_SEQUENCE_END(X9_62_PENTANOMIAL) + +DECLARE_ASN1_ALLOC_FUNCTIONS(X9_62_PENTANOMIAL) +IMPLEMENT_ASN1_ALLOC_FUNCTIONS(X9_62_PENTANOMIAL) + +ASN1_ADB_TEMPLATE(char_two_def) = ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.other, ASN1_ANY); + +ASN1_ADB(X9_62_CHARACTERISTIC_TWO) = { + ADB_ENTRY(NID_X9_62_onBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.onBasis, ASN1_NULL)), + ADB_ENTRY(NID_X9_62_tpBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.tpBasis, ASN1_INTEGER)), + ADB_ENTRY(NID_X9_62_ppBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.ppBasis, X9_62_PENTANOMIAL)) +} ASN1_ADB_END(X9_62_CHARACTERISTIC_TWO, 0, type, 0, &char_two_def_tt, NULL); + +ASN1_SEQUENCE(X9_62_CHARACTERISTIC_TWO) = { + ASN1_EMBED(X9_62_CHARACTERISTIC_TWO, m, INT32), + ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, type, ASN1_OBJECT), + ASN1_ADB_OBJECT(X9_62_CHARACTERISTIC_TWO) +} static_ASN1_SEQUENCE_END(X9_62_CHARACTERISTIC_TWO) + +DECLARE_ASN1_ALLOC_FUNCTIONS(X9_62_CHARACTERISTIC_TWO) +IMPLEMENT_ASN1_ALLOC_FUNCTIONS(X9_62_CHARACTERISTIC_TWO) + +ASN1_ADB_TEMPLATE(fieldID_def) = ASN1_SIMPLE(X9_62_FIELDID, p.other, ASN1_ANY); + +ASN1_ADB(X9_62_FIELDID) = { + ADB_ENTRY(NID_X9_62_prime_field, ASN1_SIMPLE(X9_62_FIELDID, p.prime, ASN1_INTEGER)), + ADB_ENTRY(NID_X9_62_characteristic_two_field, ASN1_SIMPLE(X9_62_FIELDID, p.char_two, X9_62_CHARACTERISTIC_TWO)) +} ASN1_ADB_END(X9_62_FIELDID, 0, fieldType, 0, &fieldID_def_tt, NULL); + +ASN1_SEQUENCE(X9_62_FIELDID) = { + ASN1_SIMPLE(X9_62_FIELDID, fieldType, ASN1_OBJECT), + ASN1_ADB_OBJECT(X9_62_FIELDID) +} static_ASN1_SEQUENCE_END(X9_62_FIELDID) + +ASN1_SEQUENCE(X9_62_CURVE) = { + ASN1_SIMPLE(X9_62_CURVE, a, ASN1_OCTET_STRING), + ASN1_SIMPLE(X9_62_CURVE, b, ASN1_OCTET_STRING), + ASN1_OPT(X9_62_CURVE, seed, ASN1_BIT_STRING) +} static_ASN1_SEQUENCE_END(X9_62_CURVE) + +ASN1_SEQUENCE(ECPARAMETERS) = { + ASN1_EMBED(ECPARAMETERS, version, INT32), + ASN1_SIMPLE(ECPARAMETERS, fieldID, X9_62_FIELDID), + ASN1_SIMPLE(ECPARAMETERS, curve, X9_62_CURVE), + ASN1_SIMPLE(ECPARAMETERS, base, ASN1_OCTET_STRING), + ASN1_SIMPLE(ECPARAMETERS, order, ASN1_INTEGER), + ASN1_OPT(ECPARAMETERS, cofactor, ASN1_INTEGER) +} ASN1_SEQUENCE_END(ECPARAMETERS) + +DECLARE_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS) +IMPLEMENT_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS) + +ASN1_CHOICE(ECPKPARAMETERS) = { + ASN1_SIMPLE(ECPKPARAMETERS, value.named_curve, ASN1_OBJECT), + ASN1_SIMPLE(ECPKPARAMETERS, value.parameters, ECPARAMETERS), + ASN1_SIMPLE(ECPKPARAMETERS, value.implicitlyCA, ASN1_NULL) +} ASN1_CHOICE_END(ECPKPARAMETERS) + +DECLARE_ASN1_FUNCTIONS_const(ECPKPARAMETERS) +DECLARE_ASN1_ENCODE_FUNCTIONS_const(ECPKPARAMETERS, ECPKPARAMETERS) +IMPLEMENT_ASN1_FUNCTIONS_const(ECPKPARAMETERS) + +ASN1_SEQUENCE(EC_PRIVATEKEY) = { + ASN1_EMBED(EC_PRIVATEKEY, version, INT32), + ASN1_SIMPLE(EC_PRIVATEKEY, privateKey, ASN1_OCTET_STRING), + ASN1_EXP_OPT(EC_PRIVATEKEY, parameters, ECPKPARAMETERS, 0), + ASN1_EXP_OPT(EC_PRIVATEKEY, publicKey, ASN1_BIT_STRING, 1) +} static_ASN1_SEQUENCE_END(EC_PRIVATEKEY) + +DECLARE_ASN1_FUNCTIONS_const(EC_PRIVATEKEY) +DECLARE_ASN1_ENCODE_FUNCTIONS_const(EC_PRIVATEKEY, EC_PRIVATEKEY) +IMPLEMENT_ASN1_FUNCTIONS_const(EC_PRIVATEKEY) + +/* some declarations of internal function */ + +/* ec_asn1_group2field() sets the values in a X9_62_FIELDID object */ +static int ec_asn1_group2fieldid(const EC_GROUP *, X9_62_FIELDID *); +/* ec_asn1_group2curve() sets the values in a X9_62_CURVE object */ +static int ec_asn1_group2curve(const EC_GROUP *, X9_62_CURVE *); + +/* the function definitions */ + +static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field) +{ + int ok = 0, nid; + BIGNUM *tmp = NULL; + + if (group == NULL || field == NULL) + return 0; + + /* clear the old values (if necessary) */ + ASN1_OBJECT_free(field->fieldType); + ASN1_TYPE_free(field->p.other); + + nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group)); + /* set OID for the field */ + if ((field->fieldType = OBJ_nid2obj(nid)) == NULL) { + ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB); + goto err; + } + + if (nid == NID_X9_62_prime_field) { + if ((tmp = BN_new()) == NULL) { + ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); + goto err; + } + /* the parameters are specified by the prime number p */ + if (!EC_GROUP_get_curve(group, tmp, NULL, NULL, NULL)) { + ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB); + goto err; + } + /* set the prime number */ + field->p.prime = BN_to_ASN1_INTEGER(tmp, NULL); + if (field->p.prime == NULL) { + ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_ASN1_LIB); + goto err; + } + } else if (nid == NID_X9_62_characteristic_two_field) +#ifdef OPENSSL_NO_EC2M + { + ECerr(EC_F_EC_ASN1_GROUP2FIELDID, EC_R_GF2M_NOT_SUPPORTED); + goto err; + } +#else + { + int field_type; + X9_62_CHARACTERISTIC_TWO *char_two; + + field->p.char_two = X9_62_CHARACTERISTIC_TWO_new(); + char_two = field->p.char_two; + + if (char_two == NULL) { + ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); + goto err; + } + + char_two->m = (long)EC_GROUP_get_degree(group); + + field_type = EC_GROUP_get_basis_type(group); + + if (field_type == 0) { + ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB); + goto err; + } + /* set base type OID */ + if ((char_two->type = OBJ_nid2obj(field_type)) == NULL) { + ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB); + goto err; + } + + if (field_type == NID_X9_62_tpBasis) { + unsigned int k; + + if (!EC_GROUP_get_trinomial_basis(group, &k)) + goto err; + + char_two->p.tpBasis = ASN1_INTEGER_new(); + if (char_two->p.tpBasis == NULL) { + ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!ASN1_INTEGER_set(char_two->p.tpBasis, (long)k)) { + ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_ASN1_LIB); + goto err; + } + } else if (field_type == NID_X9_62_ppBasis) { + unsigned int k1, k2, k3; + + if (!EC_GROUP_get_pentanomial_basis(group, &k1, &k2, &k3)) + goto err; + + char_two->p.ppBasis = X9_62_PENTANOMIAL_new(); + if (char_two->p.ppBasis == NULL) { + ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* set k? values */ + char_two->p.ppBasis->k1 = (long)k1; + char_two->p.ppBasis->k2 = (long)k2; + char_two->p.ppBasis->k3 = (long)k3; + } else { /* field_type == NID_X9_62_onBasis */ + + /* for ONB the parameters are (asn1) NULL */ + char_two->p.onBasis = ASN1_NULL_new(); + if (char_two->p.onBasis == NULL) { + ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); + goto err; + } + } + } +#endif + else { + ECerr(EC_F_EC_ASN1_GROUP2FIELDID, EC_R_UNSUPPORTED_FIELD); + goto err; + } + + ok = 1; + + err: + BN_free(tmp); + return ok; +} + +static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve) +{ + int ok = 0; + BIGNUM *tmp_1 = NULL, *tmp_2 = NULL; + unsigned char *a_buf = NULL, *b_buf = NULL; + size_t len; + + if (!group || !curve || !curve->a || !curve->b) + return 0; + + if ((tmp_1 = BN_new()) == NULL || (tmp_2 = BN_new()) == NULL) { + ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* get a and b */ + if (!EC_GROUP_get_curve(group, NULL, tmp_1, tmp_2, NULL)) { + ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB); + goto err; + } + + /* + * Per SEC 1, the curve coefficients must be padded up to size. See C.2's + * definition of Curve, C.1's definition of FieldElement, and 2.3.5's + * definition of how to encode the field elements. + */ + len = ((size_t)EC_GROUP_get_degree(group) + 7) / 8; + if ((a_buf = OPENSSL_malloc(len)) == NULL + || (b_buf = OPENSSL_malloc(len)) == NULL) { + ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE); + goto err; + } + if (BN_bn2binpad(tmp_1, a_buf, len) < 0 + || BN_bn2binpad(tmp_2, b_buf, len) < 0) { + ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB); + goto err; + } + + /* set a and b */ + if (!ASN1_OCTET_STRING_set(curve->a, a_buf, len) + || !ASN1_OCTET_STRING_set(curve->b, b_buf, len)) { + ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB); + goto err; + } + + /* set the seed (optional) */ + if (group->seed) { + if (!curve->seed) + if ((curve->seed = ASN1_BIT_STRING_new()) == NULL) { + ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE); + goto err; + } + curve->seed->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + curve->seed->flags |= ASN1_STRING_FLAG_BITS_LEFT; + if (!ASN1_BIT_STRING_set(curve->seed, group->seed, + (int)group->seed_len)) { + ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB); + goto err; + } + } else { + ASN1_BIT_STRING_free(curve->seed); + curve->seed = NULL; + } + + ok = 1; + + err: + OPENSSL_free(a_buf); + OPENSSL_free(b_buf); + BN_free(tmp_1); + BN_free(tmp_2); + return ok; +} + +ECPARAMETERS *EC_GROUP_get_ecparameters(const EC_GROUP *group, + ECPARAMETERS *params) +{ + size_t len = 0; + ECPARAMETERS *ret = NULL; + const BIGNUM *tmp; + unsigned char *buffer = NULL; + const EC_POINT *point = NULL; + point_conversion_form_t form; + + if (params == NULL) { + if ((ret = ECPARAMETERS_new()) == NULL) { + ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_MALLOC_FAILURE); + goto err; + } + } else + ret = params; + + /* set the version (always one) */ + ret->version = (long)0x1; + + /* set the fieldID */ + if (!ec_asn1_group2fieldid(group, ret->fieldID)) { + ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_EC_LIB); + goto err; + } + + /* set the curve */ + if (!ec_asn1_group2curve(group, ret->curve)) { + ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_EC_LIB); + goto err; + } + + /* set the base point */ + if ((point = EC_GROUP_get0_generator(group)) == NULL) { + ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, EC_R_UNDEFINED_GENERATOR); + goto err; + } + + form = EC_GROUP_get_point_conversion_form(group); + + len = EC_POINT_point2buf(group, point, form, &buffer, NULL); + if (len == 0) { + ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_EC_LIB); + goto err; + } + if (ret->base == NULL && (ret->base = ASN1_OCTET_STRING_new()) == NULL) { + OPENSSL_free(buffer); + ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_MALLOC_FAILURE); + goto err; + } + ASN1_STRING_set0(ret->base, buffer, len); + + /* set the order */ + tmp = EC_GROUP_get0_order(group); + if (tmp == NULL) { + ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_EC_LIB); + goto err; + } + ret->order = BN_to_ASN1_INTEGER(tmp, ret->order); + if (ret->order == NULL) { + ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_ASN1_LIB); + goto err; + } + + /* set the cofactor (optional) */ + tmp = EC_GROUP_get0_cofactor(group); + if (tmp != NULL) { + ret->cofactor = BN_to_ASN1_INTEGER(tmp, ret->cofactor); + if (ret->cofactor == NULL) { + ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_ASN1_LIB); + goto err; + } + } + + return ret; + + err: + if (params == NULL) + ECPARAMETERS_free(ret); + return NULL; +} + +ECPKPARAMETERS *EC_GROUP_get_ecpkparameters(const EC_GROUP *group, + ECPKPARAMETERS *params) +{ + int ok = 1, tmp; + ECPKPARAMETERS *ret = params; + + if (ret == NULL) { + if ((ret = ECPKPARAMETERS_new()) == NULL) { + ECerr(EC_F_EC_GROUP_GET_ECPKPARAMETERS, ERR_R_MALLOC_FAILURE); + return NULL; + } + } else { + if (ret->type == 0) + ASN1_OBJECT_free(ret->value.named_curve); + else if (ret->type == 1 && ret->value.parameters) + ECPARAMETERS_free(ret->value.parameters); + } + + if (EC_GROUP_get_asn1_flag(group)) { + /* + * use the asn1 OID to describe the elliptic curve parameters + */ + tmp = EC_GROUP_get_curve_name(group); + if (tmp) { + ret->type = 0; + if ((ret->value.named_curve = OBJ_nid2obj(tmp)) == NULL) + ok = 0; + } else + /* we don't know the nid => ERROR */ + ok = 0; + } else { + /* use the ECPARAMETERS structure */ + ret->type = 1; + if ((ret->value.parameters = + EC_GROUP_get_ecparameters(group, NULL)) == NULL) + ok = 0; + } + + if (!ok) { + ECPKPARAMETERS_free(ret); + return NULL; + } + return ret; +} + +EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params) +{ + int ok = 0, tmp; + EC_GROUP *ret = NULL; + BIGNUM *p = NULL, *a = NULL, *b = NULL; + EC_POINT *point = NULL; + long field_bits; + + if (!params->fieldID || !params->fieldID->fieldType || + !params->fieldID->p.ptr) { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR); + goto err; + } + + /* + * Now extract the curve parameters a and b. Note that, although SEC 1 + * specifies the length of their encodings, historical versions of OpenSSL + * encoded them incorrectly, so we must accept any length for backwards + * compatibility. + */ + if (!params->curve || !params->curve->a || + !params->curve->a->data || !params->curve->b || + !params->curve->b->data) { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR); + goto err; + } + a = BN_bin2bn(params->curve->a->data, params->curve->a->length, NULL); + if (a == NULL) { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_BN_LIB); + goto err; + } + b = BN_bin2bn(params->curve->b->data, params->curve->b->length, NULL); + if (b == NULL) { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_BN_LIB); + goto err; + } + + /* get the field parameters */ + tmp = OBJ_obj2nid(params->fieldID->fieldType); + if (tmp == NID_X9_62_characteristic_two_field) +#ifdef OPENSSL_NO_EC2M + { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_GF2M_NOT_SUPPORTED); + goto err; + } +#else + { + X9_62_CHARACTERISTIC_TWO *char_two; + + char_two = params->fieldID->p.char_two; + + field_bits = char_two->m; + if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_FIELD_TOO_LARGE); + goto err; + } + + if ((p = BN_new()) == NULL) { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* get the base type */ + tmp = OBJ_obj2nid(char_two->type); + + if (tmp == NID_X9_62_tpBasis) { + long tmp_long; + + if (!char_two->p.tpBasis) { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR); + goto err; + } + + tmp_long = ASN1_INTEGER_get(char_two->p.tpBasis); + + if (!(char_two->m > tmp_long && tmp_long > 0)) { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, + EC_R_INVALID_TRINOMIAL_BASIS); + goto err; + } + + /* create the polynomial */ + if (!BN_set_bit(p, (int)char_two->m)) + goto err; + if (!BN_set_bit(p, (int)tmp_long)) + goto err; + if (!BN_set_bit(p, 0)) + goto err; + } else if (tmp == NID_X9_62_ppBasis) { + X9_62_PENTANOMIAL *penta; + + penta = char_two->p.ppBasis; + if (!penta) { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR); + goto err; + } + + if (! + (char_two->m > penta->k3 && penta->k3 > penta->k2 + && penta->k2 > penta->k1 && penta->k1 > 0)) { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, + EC_R_INVALID_PENTANOMIAL_BASIS); + goto err; + } + + /* create the polynomial */ + if (!BN_set_bit(p, (int)char_two->m)) + goto err; + if (!BN_set_bit(p, (int)penta->k1)) + goto err; + if (!BN_set_bit(p, (int)penta->k2)) + goto err; + if (!BN_set_bit(p, (int)penta->k3)) + goto err; + if (!BN_set_bit(p, 0)) + goto err; + } else if (tmp == NID_X9_62_onBasis) { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_NOT_IMPLEMENTED); + goto err; + } else { /* error */ + + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR); + goto err; + } + + /* create the EC_GROUP structure */ + ret = EC_GROUP_new_curve_GF2m(p, a, b, NULL); + } +#endif + else if (tmp == NID_X9_62_prime_field) { + /* we have a curve over a prime field */ + /* extract the prime number */ + if (!params->fieldID->p.prime) { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR); + goto err; + } + p = ASN1_INTEGER_to_BN(params->fieldID->p.prime, NULL); + if (p == NULL) { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_ASN1_LIB); + goto err; + } + + if (BN_is_negative(p) || BN_is_zero(p)) { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_INVALID_FIELD); + goto err; + } + + field_bits = BN_num_bits(p); + if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_FIELD_TOO_LARGE); + goto err; + } + + /* create the EC_GROUP structure */ + ret = EC_GROUP_new_curve_GFp(p, a, b, NULL); + } else { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_INVALID_FIELD); + goto err; + } + + if (ret == NULL) { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_EC_LIB); + goto err; + } + + /* extract seed (optional) */ + if (params->curve->seed != NULL) { + OPENSSL_free(ret->seed); + if ((ret->seed = OPENSSL_malloc(params->curve->seed->length)) == NULL) { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_MALLOC_FAILURE); + goto err; + } + memcpy(ret->seed, params->curve->seed->data, + params->curve->seed->length); + ret->seed_len = params->curve->seed->length; + } + + if (!params->order || !params->base || !params->base->data) { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR); + goto err; + } + + if ((point = EC_POINT_new(ret)) == NULL) + goto err; + + /* set the point conversion form */ + EC_GROUP_set_point_conversion_form(ret, (point_conversion_form_t) + (params->base->data[0] & ~0x01)); + + /* extract the ec point */ + if (!EC_POINT_oct2point(ret, point, params->base->data, + params->base->length, NULL)) { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_EC_LIB); + goto err; + } + + /* extract the order */ + if ((a = ASN1_INTEGER_to_BN(params->order, a)) == NULL) { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_ASN1_LIB); + goto err; + } + if (BN_is_negative(a) || BN_is_zero(a)) { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_INVALID_GROUP_ORDER); + goto err; + } + if (BN_num_bits(a) > (int)field_bits + 1) { /* Hasse bound */ + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_INVALID_GROUP_ORDER); + goto err; + } + + /* extract the cofactor (optional) */ + if (params->cofactor == NULL) { + BN_free(b); + b = NULL; + } else if ((b = ASN1_INTEGER_to_BN(params->cofactor, b)) == NULL) { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_ASN1_LIB); + goto err; + } + /* set the generator, order and cofactor (if present) */ + if (!EC_GROUP_set_generator(ret, point, a, b)) { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_EC_LIB); + goto err; + } + + ok = 1; + + err: + if (!ok) { + EC_GROUP_clear_free(ret); + ret = NULL; + } + + BN_free(p); + BN_free(a); + BN_free(b); + EC_POINT_free(point); + return ret; +} + +EC_GROUP *EC_GROUP_new_from_ecpkparameters(const ECPKPARAMETERS *params) +{ + EC_GROUP *ret = NULL; + int tmp = 0; + + if (params == NULL) { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS, EC_R_MISSING_PARAMETERS); + return NULL; + } + + if (params->type == 0) { /* the curve is given by an OID */ + tmp = OBJ_obj2nid(params->value.named_curve); + if ((ret = EC_GROUP_new_by_curve_name(tmp)) == NULL) { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS, + EC_R_EC_GROUP_NEW_BY_NAME_FAILURE); + return NULL; + } + EC_GROUP_set_asn1_flag(ret, OPENSSL_EC_NAMED_CURVE); + } else if (params->type == 1) { /* the parameters are given by a + * ECPARAMETERS structure */ + ret = EC_GROUP_new_from_ecparameters(params->value.parameters); + if (!ret) { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS, ERR_R_EC_LIB); + return NULL; + } + EC_GROUP_set_asn1_flag(ret, OPENSSL_EC_EXPLICIT_CURVE); + } else if (params->type == 2) { /* implicitlyCA */ + return NULL; + } else { + ECerr(EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS, EC_R_ASN1_ERROR); + return NULL; + } + + return ret; +} + +/* EC_GROUP <-> DER encoding of ECPKPARAMETERS */ + +EC_GROUP *d2i_ECPKParameters(EC_GROUP **a, const unsigned char **in, long len) +{ + EC_GROUP *group = NULL; + ECPKPARAMETERS *params = NULL; + const unsigned char *p = *in; + + if ((params = d2i_ECPKPARAMETERS(NULL, &p, len)) == NULL) { + ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_D2I_ECPKPARAMETERS_FAILURE); + ECPKPARAMETERS_free(params); + return NULL; + } + + if ((group = EC_GROUP_new_from_ecpkparameters(params)) == NULL) { + ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_PKPARAMETERS2GROUP_FAILURE); + ECPKPARAMETERS_free(params); + return NULL; + } + + if (a) { + EC_GROUP_clear_free(*a); + *a = group; + } + + ECPKPARAMETERS_free(params); + *in = p; + return group; +} + +int i2d_ECPKParameters(const EC_GROUP *a, unsigned char **out) +{ + int ret = 0; + ECPKPARAMETERS *tmp = EC_GROUP_get_ecpkparameters(a, NULL); + if (tmp == NULL) { + ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_GROUP2PKPARAMETERS_FAILURE); + return 0; + } + if ((ret = i2d_ECPKPARAMETERS(tmp, out)) == 0) { + ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_I2D_ECPKPARAMETERS_FAILURE); + ECPKPARAMETERS_free(tmp); + return 0; + } + ECPKPARAMETERS_free(tmp); + return ret; +} + +/* some EC_KEY functions */ + +EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len) +{ + EC_KEY *ret = NULL; + EC_PRIVATEKEY *priv_key = NULL; + const unsigned char *p = *in; + + if ((priv_key = d2i_EC_PRIVATEKEY(NULL, &p, len)) == NULL) { + ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); + return NULL; + } + + if (a == NULL || *a == NULL) { + if ((ret = EC_KEY_new()) == NULL) { + ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE); + goto err; + } + } else + ret = *a; + + if (priv_key->parameters) { + EC_GROUP_clear_free(ret->group); + ret->group = EC_GROUP_new_from_ecpkparameters(priv_key->parameters); + } + + if (ret->group == NULL) { + ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); + goto err; + } + + ret->version = priv_key->version; + + if (priv_key->privateKey) { + ASN1_OCTET_STRING *pkey = priv_key->privateKey; + if (EC_KEY_oct2priv(ret, ASN1_STRING_get0_data(pkey), + ASN1_STRING_length(pkey)) == 0) + goto err; + } else { + ECerr(EC_F_D2I_ECPRIVATEKEY, EC_R_MISSING_PRIVATE_KEY); + goto err; + } + + EC_POINT_clear_free(ret->pub_key); + ret->pub_key = EC_POINT_new(ret->group); + if (ret->pub_key == NULL) { + ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); + goto err; + } + + if (priv_key->publicKey) { + const unsigned char *pub_oct; + int pub_oct_len; + + pub_oct = ASN1_STRING_get0_data(priv_key->publicKey); + pub_oct_len = ASN1_STRING_length(priv_key->publicKey); + if (!EC_KEY_oct2key(ret, pub_oct, pub_oct_len, NULL)) { + ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); + goto err; + } + } else { + if (ret->group->meth->keygenpub == NULL + || ret->group->meth->keygenpub(ret) == 0) + goto err; + /* Remember the original private-key-only encoding. */ + ret->enc_flag |= EC_PKEY_NO_PUBKEY; + } + + if (a) + *a = ret; + EC_PRIVATEKEY_free(priv_key); + *in = p; + return ret; + + err: + if (a == NULL || *a != ret) + EC_KEY_free(ret); + EC_PRIVATEKEY_free(priv_key); + return NULL; +} + +int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out) +{ + int ret = 0, ok = 0; + unsigned char *priv= NULL, *pub= NULL; + size_t privlen = 0, publen = 0; + + EC_PRIVATEKEY *priv_key = NULL; + + if (a == NULL || a->group == NULL || + (!(a->enc_flag & EC_PKEY_NO_PUBKEY) && a->pub_key == NULL)) { + ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER); + goto err; + } + + if ((priv_key = EC_PRIVATEKEY_new()) == NULL) { + ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE); + goto err; + } + + priv_key->version = a->version; + + privlen = EC_KEY_priv2buf(a, &priv); + + if (privlen == 0) { + ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB); + goto err; + } + + ASN1_STRING_set0(priv_key->privateKey, priv, privlen); + priv = NULL; + + if (!(a->enc_flag & EC_PKEY_NO_PARAMETERS)) { + if ((priv_key->parameters = + EC_GROUP_get_ecpkparameters(a->group, + priv_key->parameters)) == NULL) { + ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB); + goto err; + } + } + + if (!(a->enc_flag & EC_PKEY_NO_PUBKEY)) { + priv_key->publicKey = ASN1_BIT_STRING_new(); + if (priv_key->publicKey == NULL) { + ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE); + goto err; + } + + publen = EC_KEY_key2buf(a, a->conv_form, &pub, NULL); + + if (publen == 0) { + ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB); + goto err; + } + + priv_key->publicKey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + priv_key->publicKey->flags |= ASN1_STRING_FLAG_BITS_LEFT; + ASN1_STRING_set0(priv_key->publicKey, pub, publen); + pub = NULL; + } + + if ((ret = i2d_EC_PRIVATEKEY(priv_key, out)) == 0) { + ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB); + goto err; + } + ok = 1; + err: + OPENSSL_clear_free(priv, privlen); + OPENSSL_free(pub); + EC_PRIVATEKEY_free(priv_key); + return (ok ? ret : 0); +} + +int i2d_ECParameters(EC_KEY *a, unsigned char **out) +{ + if (a == NULL) { + ECerr(EC_F_I2D_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + return i2d_ECPKParameters(a->group, out); +} + +EC_KEY *d2i_ECParameters(EC_KEY **a, const unsigned char **in, long len) +{ + EC_KEY *ret; + + if (in == NULL || *in == NULL) { + ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + if (a == NULL || *a == NULL) { + if ((ret = EC_KEY_new()) == NULL) { + ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_MALLOC_FAILURE); + return NULL; + } + } else + ret = *a; + + if (!d2i_ECPKParameters(&ret->group, in, len)) { + ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_EC_LIB); + if (a == NULL || *a != ret) + EC_KEY_free(ret); + return NULL; + } + + if (a) + *a = ret; + + return ret; +} + +EC_KEY *o2i_ECPublicKey(EC_KEY **a, const unsigned char **in, long len) +{ + EC_KEY *ret = NULL; + + if (a == NULL || (*a) == NULL || (*a)->group == NULL) { + /* + * sorry, but a EC_GROUP-structure is necessary to set the public key + */ + ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + ret = *a; + if (!EC_KEY_oct2key(ret, *in, len, NULL)) { + ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_EC_LIB); + return 0; + } + *in += len; + return ret; +} + +int i2o_ECPublicKey(const EC_KEY *a, unsigned char **out) +{ + size_t buf_len = 0; + int new_buffer = 0; + + if (a == NULL) { + ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + buf_len = EC_POINT_point2oct(a->group, a->pub_key, + a->conv_form, NULL, 0, NULL); + + if (out == NULL || buf_len == 0) + /* out == NULL => just return the length of the octet string */ + return buf_len; + + if (*out == NULL) { + if ((*out = OPENSSL_malloc(buf_len)) == NULL) { + ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_MALLOC_FAILURE); + return 0; + } + new_buffer = 1; + } + if (!EC_POINT_point2oct(a->group, a->pub_key, a->conv_form, + *out, buf_len, NULL)) { + ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_EC_LIB); + if (new_buffer) { + OPENSSL_free(*out); + *out = NULL; + } + return 0; + } + if (!new_buffer) + *out += buf_len; + return buf_len; +} + +ASN1_SEQUENCE(ECDSA_SIG) = { + ASN1_SIMPLE(ECDSA_SIG, r, CBIGNUM), + ASN1_SIMPLE(ECDSA_SIG, s, CBIGNUM) +} static_ASN1_SEQUENCE_END(ECDSA_SIG) + +DECLARE_ASN1_FUNCTIONS_const(ECDSA_SIG) +DECLARE_ASN1_ENCODE_FUNCTIONS_const(ECDSA_SIG, ECDSA_SIG) +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ECDSA_SIG, ECDSA_SIG, ECDSA_SIG) + +ECDSA_SIG *ECDSA_SIG_new(void) +{ + ECDSA_SIG *sig = OPENSSL_zalloc(sizeof(*sig)); + if (sig == NULL) + ECerr(EC_F_ECDSA_SIG_NEW, ERR_R_MALLOC_FAILURE); + return sig; +} + +void ECDSA_SIG_free(ECDSA_SIG *sig) +{ + if (sig == NULL) + return; + BN_clear_free(sig->r); + BN_clear_free(sig->s); + OPENSSL_free(sig); +} + +void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) +{ + if (pr != NULL) + *pr = sig->r; + if (ps != NULL) + *ps = sig->s; +} + +const BIGNUM *ECDSA_SIG_get0_r(const ECDSA_SIG *sig) +{ + return sig->r; +} + +const BIGNUM *ECDSA_SIG_get0_s(const ECDSA_SIG *sig) +{ + return sig->s; +} + +int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) +{ + if (r == NULL || s == NULL) + return 0; + BN_clear_free(sig->r); + BN_clear_free(sig->s); + sig->r = r; + sig->s = s; + return 1; +} + +int ECDSA_size(const EC_KEY *r) +{ + int ret, i; + ASN1_INTEGER bs; + unsigned char buf[4]; + const EC_GROUP *group; + + if (r == NULL) + return 0; + group = EC_KEY_get0_group(r); + if (group == NULL) + return 0; + + i = EC_GROUP_order_bits(group); + if (i == 0) + return 0; + bs.length = (i + 7) / 8; + bs.data = buf; + bs.type = V_ASN1_INTEGER; + /* If the top bit is set the asn1 encoding is 1 larger. */ + buf[0] = 0xff; + + i = i2d_ASN1_INTEGER(&bs, NULL); + i += i; /* r and s */ + ret = ASN1_object_size(1, i, V_ASN1_SEQUENCE); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_check.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_check.c new file mode 100644 index 000000000..eeb06ec1c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_check.c @@ -0,0 +1,72 @@ +/* + * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "ec_lcl.h" +#include + +int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx) +{ + int ret = 0; + const BIGNUM *order; + BN_CTX *new_ctx = NULL; + EC_POINT *point = NULL; + + /* Custom curves assumed to be correct */ + if ((group->meth->flags & EC_FLAGS_CUSTOM_CURVE) != 0) + return 1; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) { + ECerr(EC_F_EC_GROUP_CHECK, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + /* check the discriminant */ + if (!EC_GROUP_check_discriminant(group, ctx)) { + ECerr(EC_F_EC_GROUP_CHECK, EC_R_DISCRIMINANT_IS_ZERO); + goto err; + } + + /* check the generator */ + if (group->generator == NULL) { + ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_GENERATOR); + goto err; + } + if (EC_POINT_is_on_curve(group, group->generator, ctx) <= 0) { + ECerr(EC_F_EC_GROUP_CHECK, EC_R_POINT_IS_NOT_ON_CURVE); + goto err; + } + + /* check the order of the generator */ + if ((point = EC_POINT_new(group)) == NULL) + goto err; + order = EC_GROUP_get0_order(group); + if (order == NULL) + goto err; + if (BN_is_zero(order)) { + ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_ORDER); + goto err; + } + + if (!EC_POINT_mul(group, point, order, NULL, NULL, ctx)) + goto err; + if (!EC_POINT_is_at_infinity(group, point)) { + ECerr(EC_F_EC_GROUP_CHECK, EC_R_INVALID_GROUP_ORDER); + goto err; + } + + ret = 1; + + err: + BN_CTX_free(new_ctx); + EC_POINT_free(point); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_curve.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_curve.c new file mode 100644 index 000000000..bb1ce196d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_curve.c @@ -0,0 +1,3199 @@ +/* + * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "ec_lcl.h" +#include +#include +#include +#include "internal/nelem.h" + +typedef struct { + int field_type, /* either NID_X9_62_prime_field or + * NID_X9_62_characteristic_two_field */ + seed_len, param_len; + unsigned int cofactor; /* promoted to BN_ULONG */ +} EC_CURVE_DATA; + +/* the nist prime curves */ +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 24 * 6]; +} _EC_NIST_PRIME_192 = { + { + NID_X9_62_prime_field, 20, 24, 1 + }, + { + /* seed */ + 0x30, 0x45, 0xAE, 0x6F, 0xC8, 0x42, 0x2F, 0x64, 0xED, 0x57, 0x95, 0x28, + 0xD3, 0x81, 0x20, 0xEA, 0xE1, 0x21, 0x96, 0xD5, + /* p */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* a */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + /* b */ + 0x64, 0x21, 0x05, 0x19, 0xE5, 0x9C, 0x80, 0xE7, 0x0F, 0xA7, 0xE9, 0xAB, + 0x72, 0x24, 0x30, 0x49, 0xFE, 0xB8, 0xDE, 0xEC, 0xC1, 0x46, 0xB9, 0xB1, + /* x */ + 0x18, 0x8D, 0xA8, 0x0E, 0xB0, 0x30, 0x90, 0xF6, 0x7C, 0xBF, 0x20, 0xEB, + 0x43, 0xA1, 0x88, 0x00, 0xF4, 0xFF, 0x0A, 0xFD, 0x82, 0xFF, 0x10, 0x12, + /* y */ + 0x07, 0x19, 0x2b, 0x95, 0xff, 0xc8, 0xda, 0x78, 0x63, 0x10, 0x11, 0xed, + 0x6b, 0x24, 0xcd, 0xd5, 0x73, 0xf9, 0x77, 0xa1, 0x1e, 0x79, 0x48, 0x11, + /* order */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x99, 0xDE, 0xF8, 0x36, 0x14, 0x6B, 0xC9, 0xB1, 0xB4, 0xD2, 0x28, 0x31 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 28 * 6]; +} _EC_NIST_PRIME_224 = { + { + NID_X9_62_prime_field, 20, 28, 1 + }, + { + /* seed */ + 0xBD, 0x71, 0x34, 0x47, 0x99, 0xD5, 0xC7, 0xFC, 0xDC, 0x45, 0xB5, 0x9F, + 0xA3, 0xB9, 0xAB, 0x8F, 0x6A, 0x94, 0x8B, 0xC5, + /* p */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + /* a */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, + /* b */ + 0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, 0x32, 0x56, + 0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B, 0x39, 0x43, + 0x23, 0x55, 0xFF, 0xB4, + /* x */ + 0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, 0x90, 0xB9, + 0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xD6, + 0x11, 0x5C, 0x1D, 0x21, + /* y */ + 0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, 0xdf, 0xe6, + 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, 0x44, 0xd5, 0x81, 0x99, + 0x85, 0x00, 0x7e, 0x34, + /* order */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x16, 0xA2, 0xE0, 0xB8, 0xF0, 0x3E, 0x13, 0xDD, 0x29, 0x45, + 0x5C, 0x5C, 0x2A, 0x3D + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 48 * 6]; +} _EC_NIST_PRIME_384 = { + { + NID_X9_62_prime_field, 20, 48, 1 + }, + { + /* seed */ + 0xA3, 0x35, 0x92, 0x6A, 0xA3, 0x19, 0xA2, 0x7A, 0x1D, 0x00, 0x89, 0x6A, + 0x67, 0x73, 0xA4, 0x82, 0x7A, 0xCD, 0xAC, 0x73, + /* p */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + /* a */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC, + /* b */ + 0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4, 0x98, 0x8E, 0x05, 0x6B, + 0xE3, 0xF8, 0x2D, 0x19, 0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12, + 0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A, 0xC6, 0x56, 0x39, 0x8D, + 0x8A, 0x2E, 0xD1, 0x9D, 0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF, + /* x */ + 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E, + 0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98, + 0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D, + 0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7, + /* y */ + 0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f, 0x5d, 0x9e, 0x98, 0xbf, + 0x92, 0x92, 0xdc, 0x29, 0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c, + 0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0, 0x0a, 0x60, 0xb1, 0xce, + 0x1d, 0x7e, 0x81, 0x9d, 0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f, + /* order */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, 0x58, 0x1A, 0x0D, 0xB2, + 0x48, 0xB0, 0xA7, 0x7A, 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 66 * 6]; +} _EC_NIST_PRIME_521 = { + { + NID_X9_62_prime_field, 20, 66, 1 + }, + { + /* seed */ + 0xD0, 0x9E, 0x88, 0x00, 0x29, 0x1C, 0xB8, 0x53, 0x96, 0xCC, 0x67, 0x17, + 0x39, 0x32, 0x84, 0xAA, 0xA0, 0xDA, 0x64, 0xBA, + /* p */ + 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* a */ + 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + /* b */ + 0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F, 0x92, 0x9A, + 0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3, + 0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1, 0x56, 0x19, + 0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1, + 0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1, 0xEF, 0x45, + 0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00, + /* x */ + 0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E, + 0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F, + 0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B, + 0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF, + 0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E, + 0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66, + /* y */ + 0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04, 0x5c, 0x8a, + 0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b, + 0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee, + 0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad, + 0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40, 0x88, 0xbe, + 0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50, + /* order */ + 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x51, 0x86, + 0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09, + 0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE, 0xBB, 0x6F, + 0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09 + } +}; + +/* the x9.62 prime curves (minus the nist prime curves) */ +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 24 * 6]; +} _EC_X9_62_PRIME_192V2 = { + { + NID_X9_62_prime_field, 20, 24, 1 + }, + { + /* seed */ + 0x31, 0xA9, 0x2E, 0xE2, 0x02, 0x9F, 0xD1, 0x0D, 0x90, 0x1B, 0x11, 0x3E, + 0x99, 0x07, 0x10, 0xF0, 0xD2, 0x1A, 0xC6, 0xB6, + /* p */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* a */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + /* b */ + 0xCC, 0x22, 0xD6, 0xDF, 0xB9, 0x5C, 0x6B, 0x25, 0xE4, 0x9C, 0x0D, 0x63, + 0x64, 0xA4, 0xE5, 0x98, 0x0C, 0x39, 0x3A, 0xA2, 0x16, 0x68, 0xD9, 0x53, + /* x */ + 0xEE, 0xA2, 0xBA, 0xE7, 0xE1, 0x49, 0x78, 0x42, 0xF2, 0xDE, 0x77, 0x69, + 0xCF, 0xE9, 0xC9, 0x89, 0xC0, 0x72, 0xAD, 0x69, 0x6F, 0x48, 0x03, 0x4A, + /* y */ + 0x65, 0x74, 0xd1, 0x1d, 0x69, 0xb6, 0xec, 0x7a, 0x67, 0x2b, 0xb8, 0x2a, + 0x08, 0x3d, 0xf2, 0xf2, 0xb0, 0x84, 0x7d, 0xe9, 0x70, 0xb2, 0xde, 0x15, + /* order */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0x5F, 0xB1, 0xA7, 0x24, 0xDC, 0x80, 0x41, 0x86, 0x48, 0xD8, 0xDD, 0x31 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 24 * 6]; +} _EC_X9_62_PRIME_192V3 = { + { + NID_X9_62_prime_field, 20, 24, 1 + }, + { + /* seed */ + 0xC4, 0x69, 0x68, 0x44, 0x35, 0xDE, 0xB3, 0x78, 0xC4, 0xB6, 0x5C, 0xA9, + 0x59, 0x1E, 0x2A, 0x57, 0x63, 0x05, 0x9A, 0x2E, + /* p */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* a */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + /* b */ + 0x22, 0x12, 0x3D, 0xC2, 0x39, 0x5A, 0x05, 0xCA, 0xA7, 0x42, 0x3D, 0xAE, + 0xCC, 0xC9, 0x47, 0x60, 0xA7, 0xD4, 0x62, 0x25, 0x6B, 0xD5, 0x69, 0x16, + /* x */ + 0x7D, 0x29, 0x77, 0x81, 0x00, 0xC6, 0x5A, 0x1D, 0xA1, 0x78, 0x37, 0x16, + 0x58, 0x8D, 0xCE, 0x2B, 0x8B, 0x4A, 0xEE, 0x8E, 0x22, 0x8F, 0x18, 0x96, + /* y */ + 0x38, 0xa9, 0x0f, 0x22, 0x63, 0x73, 0x37, 0x33, 0x4b, 0x49, 0xdc, 0xb6, + 0x6a, 0x6d, 0xc8, 0xf9, 0x97, 0x8a, 0xca, 0x76, 0x48, 0xa9, 0x43, 0xb0, + /* order */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x7A, 0x62, 0xD0, 0x31, 0xC8, 0x3F, 0x42, 0x94, 0xF6, 0x40, 0xEC, 0x13 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 30 * 6]; +} _EC_X9_62_PRIME_239V1 = { + { + NID_X9_62_prime_field, 20, 30, 1 + }, + { + /* seed */ + 0xE4, 0x3B, 0xB4, 0x60, 0xF0, 0xB8, 0x0C, 0xC0, 0xC0, 0xB0, 0x75, 0x79, + 0x8E, 0x94, 0x80, 0x60, 0xF8, 0x32, 0x1B, 0x7D, + /* p */ + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* a */ + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + /* b */ + 0x6B, 0x01, 0x6C, 0x3B, 0xDC, 0xF1, 0x89, 0x41, 0xD0, 0xD6, 0x54, 0x92, + 0x14, 0x75, 0xCA, 0x71, 0xA9, 0xDB, 0x2F, 0xB2, 0x7D, 0x1D, 0x37, 0x79, + 0x61, 0x85, 0xC2, 0x94, 0x2C, 0x0A, + /* x */ + 0x0F, 0xFA, 0x96, 0x3C, 0xDC, 0xA8, 0x81, 0x6C, 0xCC, 0x33, 0xB8, 0x64, + 0x2B, 0xED, 0xF9, 0x05, 0xC3, 0xD3, 0x58, 0x57, 0x3D, 0x3F, 0x27, 0xFB, + 0xBD, 0x3B, 0x3C, 0xB9, 0xAA, 0xAF, + /* y */ + 0x7d, 0xeb, 0xe8, 0xe4, 0xe9, 0x0a, 0x5d, 0xae, 0x6e, 0x40, 0x54, 0xca, + 0x53, 0x0b, 0xa0, 0x46, 0x54, 0xb3, 0x68, 0x18, 0xce, 0x22, 0x6b, 0x39, + 0xfc, 0xcb, 0x7b, 0x02, 0xf1, 0xae, + /* order */ + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x7F, 0xFF, 0xFF, 0x9E, 0x5E, 0x9A, 0x9F, 0x5D, 0x90, 0x71, 0xFB, 0xD1, + 0x52, 0x26, 0x88, 0x90, 0x9D, 0x0B + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 30 * 6]; +} _EC_X9_62_PRIME_239V2 = { + { + NID_X9_62_prime_field, 20, 30, 1 + }, + { + /* seed */ + 0xE8, 0xB4, 0x01, 0x16, 0x04, 0x09, 0x53, 0x03, 0xCA, 0x3B, 0x80, 0x99, + 0x98, 0x2B, 0xE0, 0x9F, 0xCB, 0x9A, 0xE6, 0x16, + /* p */ + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* a */ + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + /* b */ + 0x61, 0x7F, 0xAB, 0x68, 0x32, 0x57, 0x6C, 0xBB, 0xFE, 0xD5, 0x0D, 0x99, + 0xF0, 0x24, 0x9C, 0x3F, 0xEE, 0x58, 0xB9, 0x4B, 0xA0, 0x03, 0x8C, 0x7A, + 0xE8, 0x4C, 0x8C, 0x83, 0x2F, 0x2C, + /* x */ + 0x38, 0xAF, 0x09, 0xD9, 0x87, 0x27, 0x70, 0x51, 0x20, 0xC9, 0x21, 0xBB, + 0x5E, 0x9E, 0x26, 0x29, 0x6A, 0x3C, 0xDC, 0xF2, 0xF3, 0x57, 0x57, 0xA0, + 0xEA, 0xFD, 0x87, 0xB8, 0x30, 0xE7, + /* y */ + 0x5b, 0x01, 0x25, 0xe4, 0xdb, 0xea, 0x0e, 0xc7, 0x20, 0x6d, 0xa0, 0xfc, + 0x01, 0xd9, 0xb0, 0x81, 0x32, 0x9f, 0xb5, 0x55, 0xde, 0x6e, 0xf4, 0x60, + 0x23, 0x7d, 0xff, 0x8b, 0xe4, 0xba, + /* order */ + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x80, 0x00, 0x00, 0xCF, 0xA7, 0xE8, 0x59, 0x43, 0x77, 0xD4, 0x14, 0xC0, + 0x38, 0x21, 0xBC, 0x58, 0x20, 0x63 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 30 * 6]; +} _EC_X9_62_PRIME_239V3 = { + { + NID_X9_62_prime_field, 20, 30, 1 + }, + { + /* seed */ + 0x7D, 0x73, 0x74, 0x16, 0x8F, 0xFE, 0x34, 0x71, 0xB6, 0x0A, 0x85, 0x76, + 0x86, 0xA1, 0x94, 0x75, 0xD3, 0xBF, 0xA2, 0xFF, + /* p */ + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* a */ + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + /* b */ + 0x25, 0x57, 0x05, 0xFA, 0x2A, 0x30, 0x66, 0x54, 0xB1, 0xF4, 0xCB, 0x03, + 0xD6, 0xA7, 0x50, 0xA3, 0x0C, 0x25, 0x01, 0x02, 0xD4, 0x98, 0x87, 0x17, + 0xD9, 0xBA, 0x15, 0xAB, 0x6D, 0x3E, + /* x */ + 0x67, 0x68, 0xAE, 0x8E, 0x18, 0xBB, 0x92, 0xCF, 0xCF, 0x00, 0x5C, 0x94, + 0x9A, 0xA2, 0xC6, 0xD9, 0x48, 0x53, 0xD0, 0xE6, 0x60, 0xBB, 0xF8, 0x54, + 0xB1, 0xC9, 0x50, 0x5F, 0xE9, 0x5A, + /* y */ + 0x16, 0x07, 0xe6, 0x89, 0x8f, 0x39, 0x0c, 0x06, 0xbc, 0x1d, 0x55, 0x2b, + 0xad, 0x22, 0x6f, 0x3b, 0x6f, 0xcf, 0xe4, 0x8b, 0x6e, 0x81, 0x84, 0x99, + 0xaf, 0x18, 0xe3, 0xed, 0x6c, 0xf3, + /* order */ + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x7F, 0xFF, 0xFF, 0x97, 0x5D, 0xEB, 0x41, 0xB3, 0xA6, 0x05, 0x7C, 0x3C, + 0x43, 0x21, 0x46, 0x52, 0x65, 0x51 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 32 * 6]; +} _EC_X9_62_PRIME_256V1 = { + { + NID_X9_62_prime_field, 20, 32, 1 + }, + { + /* seed */ + 0xC4, 0x9D, 0x36, 0x08, 0x86, 0xE7, 0x04, 0x93, 0x6A, 0x66, 0x78, 0xE1, + 0x13, 0x9D, 0x26, 0xB7, 0x81, 0x9F, 0x7E, 0x90, + /* p */ + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* a */ + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + /* b */ + 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB, 0xBD, 0x55, + 0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6, + 0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B, + /* x */ + 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5, + 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0, + 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96, + /* y */ + 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, + 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, + 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5, + /* order */ + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84, + 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51 + } +}; + +/* the secg prime curves (minus the nist and x9.62 prime curves) */ +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 14 * 6]; +} _EC_SECG_PRIME_112R1 = { + { + NID_X9_62_prime_field, 20, 14, 1 + }, + { + /* seed */ + 0x00, 0xF5, 0x0B, 0x02, 0x8E, 0x4D, 0x69, 0x6E, 0x67, 0x68, 0x75, 0x61, + 0x51, 0x75, 0x29, 0x04, 0x72, 0x78, 0x3F, 0xB1, + /* p */ + 0xDB, 0x7C, 0x2A, 0xBF, 0x62, 0xE3, 0x5E, 0x66, 0x80, 0x76, 0xBE, 0xAD, + 0x20, 0x8B, + /* a */ + 0xDB, 0x7C, 0x2A, 0xBF, 0x62, 0xE3, 0x5E, 0x66, 0x80, 0x76, 0xBE, 0xAD, + 0x20, 0x88, + /* b */ + 0x65, 0x9E, 0xF8, 0xBA, 0x04, 0x39, 0x16, 0xEE, 0xDE, 0x89, 0x11, 0x70, + 0x2B, 0x22, + /* x */ + 0x09, 0x48, 0x72, 0x39, 0x99, 0x5A, 0x5E, 0xE7, 0x6B, 0x55, 0xF9, 0xC2, + 0xF0, 0x98, + /* y */ + 0xa8, 0x9c, 0xe5, 0xaf, 0x87, 0x24, 0xc0, 0xa2, 0x3e, 0x0e, 0x0f, 0xf7, + 0x75, 0x00, + /* order */ + 0xDB, 0x7C, 0x2A, 0xBF, 0x62, 0xE3, 0x5E, 0x76, 0x28, 0xDF, 0xAC, 0x65, + 0x61, 0xC5 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 14 * 6]; +} _EC_SECG_PRIME_112R2 = { + { + NID_X9_62_prime_field, 20, 14, 4 + }, + { + /* seed */ + 0x00, 0x27, 0x57, 0xA1, 0x11, 0x4D, 0x69, 0x6E, 0x67, 0x68, 0x75, 0x61, + 0x51, 0x75, 0x53, 0x16, 0xC0, 0x5E, 0x0B, 0xD4, + /* p */ + 0xDB, 0x7C, 0x2A, 0xBF, 0x62, 0xE3, 0x5E, 0x66, 0x80, 0x76, 0xBE, 0xAD, + 0x20, 0x8B, + /* a */ + 0x61, 0x27, 0xC2, 0x4C, 0x05, 0xF3, 0x8A, 0x0A, 0xAA, 0xF6, 0x5C, 0x0E, + 0xF0, 0x2C, + /* b */ + 0x51, 0xDE, 0xF1, 0x81, 0x5D, 0xB5, 0xED, 0x74, 0xFC, 0xC3, 0x4C, 0x85, + 0xD7, 0x09, + /* x */ + 0x4B, 0xA3, 0x0A, 0xB5, 0xE8, 0x92, 0xB4, 0xE1, 0x64, 0x9D, 0xD0, 0x92, + 0x86, 0x43, + /* y */ + 0xad, 0xcd, 0x46, 0xf5, 0x88, 0x2e, 0x37, 0x47, 0xde, 0xf3, 0x6e, 0x95, + 0x6e, 0x97, + /* order */ + 0x36, 0xDF, 0x0A, 0xAF, 0xD8, 0xB8, 0xD7, 0x59, 0x7C, 0xA1, 0x05, 0x20, + 0xD0, 0x4B + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 16 * 6]; +} _EC_SECG_PRIME_128R1 = { + { + NID_X9_62_prime_field, 20, 16, 1 + }, + { + /* seed */ + 0x00, 0x0E, 0x0D, 0x4D, 0x69, 0x6E, 0x67, 0x68, 0x75, 0x61, 0x51, 0x75, + 0x0C, 0xC0, 0x3A, 0x44, 0x73, 0xD0, 0x36, 0x79, + /* p */ + 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + /* a */ + 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFC, + /* b */ + 0xE8, 0x75, 0x79, 0xC1, 0x10, 0x79, 0xF4, 0x3D, 0xD8, 0x24, 0x99, 0x3C, + 0x2C, 0xEE, 0x5E, 0xD3, + /* x */ + 0x16, 0x1F, 0xF7, 0x52, 0x8B, 0x89, 0x9B, 0x2D, 0x0C, 0x28, 0x60, 0x7C, + 0xA5, 0x2C, 0x5B, 0x86, + /* y */ + 0xcf, 0x5a, 0xc8, 0x39, 0x5b, 0xaf, 0xeb, 0x13, 0xc0, 0x2d, 0xa2, 0x92, + 0xdd, 0xed, 0x7a, 0x83, + /* order */ + 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x75, 0xA3, 0x0D, 0x1B, + 0x90, 0x38, 0xA1, 0x15 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 16 * 6]; +} _EC_SECG_PRIME_128R2 = { + { + NID_X9_62_prime_field, 20, 16, 4 + }, + { + /* seed */ + 0x00, 0x4D, 0x69, 0x6E, 0x67, 0x68, 0x75, 0x61, 0x51, 0x75, 0x12, 0xD8, + 0xF0, 0x34, 0x31, 0xFC, 0xE6, 0x3B, 0x88, 0xF4, + /* p */ + 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + /* a */ + 0xD6, 0x03, 0x19, 0x98, 0xD1, 0xB3, 0xBB, 0xFE, 0xBF, 0x59, 0xCC, 0x9B, + 0xBF, 0xF9, 0xAE, 0xE1, + /* b */ + 0x5E, 0xEE, 0xFC, 0xA3, 0x80, 0xD0, 0x29, 0x19, 0xDC, 0x2C, 0x65, 0x58, + 0xBB, 0x6D, 0x8A, 0x5D, + /* x */ + 0x7B, 0x6A, 0xA5, 0xD8, 0x5E, 0x57, 0x29, 0x83, 0xE6, 0xFB, 0x32, 0xA7, + 0xCD, 0xEB, 0xC1, 0x40, + /* y */ + 0x27, 0xb6, 0x91, 0x6a, 0x89, 0x4d, 0x3a, 0xee, 0x71, 0x06, 0xfe, 0x80, + 0x5f, 0xc3, 0x4b, 0x44, + /* order */ + 0x3F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xBE, 0x00, 0x24, 0x72, + 0x06, 0x13, 0xB5, 0xA3 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 21 * 6]; +} _EC_SECG_PRIME_160K1 = { + { + NID_X9_62_prime_field, 0, 21, 1 + }, + { + /* no seed */ + /* p */ + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xAC, 0x73, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + /* x */ + 0x00, 0x3B, 0x4C, 0x38, 0x2C, 0xE3, 0x7A, 0xA1, 0x92, 0xA4, 0x01, 0x9E, + 0x76, 0x30, 0x36, 0xF4, 0xF5, 0xDD, 0x4D, 0x7E, 0xBB, + /* y */ + 0x00, 0x93, 0x8c, 0xf9, 0x35, 0x31, 0x8f, 0xdc, 0xed, 0x6b, 0xc2, 0x82, + 0x86, 0x53, 0x17, 0x33, 0xc3, 0xf0, 0x3c, 0x4f, 0xee, + /* order */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xB8, + 0xFA, 0x16, 0xDF, 0xAB, 0x9A, 0xCA, 0x16, 0xB6, 0xB3 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 21 * 6]; +} _EC_SECG_PRIME_160R1 = { + { + NID_X9_62_prime_field, 20, 21, 1 + }, + { + /* seed */ + 0x10, 0x53, 0xCD, 0xE4, 0x2C, 0x14, 0xD6, 0x96, 0xE6, 0x76, 0x87, 0x56, + 0x15, 0x17, 0x53, 0x3B, 0xF3, 0xF8, 0x33, 0x45, + /* p */ + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, + /* a */ + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFC, + /* b */ + 0x00, 0x1C, 0x97, 0xBE, 0xFC, 0x54, 0xBD, 0x7A, 0x8B, 0x65, 0xAC, 0xF8, + 0x9F, 0x81, 0xD4, 0xD4, 0xAD, 0xC5, 0x65, 0xFA, 0x45, + /* x */ + 0x00, 0x4A, 0x96, 0xB5, 0x68, 0x8E, 0xF5, 0x73, 0x28, 0x46, 0x64, 0x69, + 0x89, 0x68, 0xC3, 0x8B, 0xB9, 0x13, 0xCB, 0xFC, 0x82, + /* y */ + 0x00, 0x23, 0xa6, 0x28, 0x55, 0x31, 0x68, 0x94, 0x7d, 0x59, 0xdc, 0xc9, + 0x12, 0x04, 0x23, 0x51, 0x37, 0x7a, 0xc5, 0xfb, 0x32, + /* order */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF4, + 0xC8, 0xF9, 0x27, 0xAE, 0xD3, 0xCA, 0x75, 0x22, 0x57 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 21 * 6]; +} _EC_SECG_PRIME_160R2 = { + { + NID_X9_62_prime_field, 20, 21, 1 + }, + { + /* seed */ + 0xB9, 0x9B, 0x99, 0xB0, 0x99, 0xB3, 0x23, 0xE0, 0x27, 0x09, 0xA4, 0xD6, + 0x96, 0xE6, 0x76, 0x87, 0x56, 0x15, 0x17, 0x51, + /* p */ + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xAC, 0x73, + /* a */ + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xAC, 0x70, + /* b */ + 0x00, 0xB4, 0xE1, 0x34, 0xD3, 0xFB, 0x59, 0xEB, 0x8B, 0xAB, 0x57, 0x27, + 0x49, 0x04, 0x66, 0x4D, 0x5A, 0xF5, 0x03, 0x88, 0xBA, + /* x */ + 0x00, 0x52, 0xDC, 0xB0, 0x34, 0x29, 0x3A, 0x11, 0x7E, 0x1F, 0x4F, 0xF1, + 0x1B, 0x30, 0xF7, 0x19, 0x9D, 0x31, 0x44, 0xCE, 0x6D, + /* y */ + 0x00, 0xfe, 0xaf, 0xfe, 0xf2, 0xe3, 0x31, 0xf2, 0x96, 0xe0, 0x71, 0xfa, + 0x0d, 0xf9, 0x98, 0x2c, 0xfe, 0xa7, 0xd4, 0x3f, 0x2e, + /* order */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, + 0x1E, 0xE7, 0x86, 0xA8, 0x18, 0xF3, 0xA1, 0xA1, 0x6B + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 24 * 6]; +} _EC_SECG_PRIME_192K1 = { + { + NID_X9_62_prime_field, 0, 24, 1 + }, + { + /* no seed */ + /* p */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xEE, 0x37, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + /* x */ + 0xDB, 0x4F, 0xF1, 0x0E, 0xC0, 0x57, 0xE9, 0xAE, 0x26, 0xB0, 0x7D, 0x02, + 0x80, 0xB7, 0xF4, 0x34, 0x1D, 0xA5, 0xD1, 0xB1, 0xEA, 0xE0, 0x6C, 0x7D, + /* y */ + 0x9b, 0x2f, 0x2f, 0x6d, 0x9c, 0x56, 0x28, 0xa7, 0x84, 0x41, 0x63, 0xd0, + 0x15, 0xbe, 0x86, 0x34, 0x40, 0x82, 0xaa, 0x88, 0xd9, 0x5e, 0x2f, 0x9d, + /* order */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0x26, 0xF2, 0xFC, 0x17, 0x0F, 0x69, 0x46, 0x6A, 0x74, 0xDE, 0xFD, 0x8D + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 29 * 6]; +} _EC_SECG_PRIME_224K1 = { + { + NID_X9_62_prime_field, 0, 29, 1 + }, + { + /* no seed */ + /* p */ + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFE, 0xFF, 0xFF, 0xE5, 0x6D, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, + /* x */ + 0x00, 0xA1, 0x45, 0x5B, 0x33, 0x4D, 0xF0, 0x99, 0xDF, 0x30, 0xFC, 0x28, + 0xA1, 0x69, 0xA4, 0x67, 0xE9, 0xE4, 0x70, 0x75, 0xA9, 0x0F, 0x7E, 0x65, + 0x0E, 0xB6, 0xB7, 0xA4, 0x5C, + /* y */ + 0x00, 0x7e, 0x08, 0x9f, 0xed, 0x7f, 0xba, 0x34, 0x42, 0x82, 0xca, 0xfb, + 0xd6, 0xf7, 0xe3, 0x19, 0xf7, 0xc0, 0xb0, 0xbd, 0x59, 0xe2, 0xca, 0x4b, + 0xdb, 0x55, 0x6d, 0x61, 0xa5, + /* order */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xDC, 0xE8, 0xD2, 0xEC, 0x61, 0x84, 0xCA, 0xF0, 0xA9, + 0x71, 0x76, 0x9F, 0xB1, 0xF7 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 32 * 6]; +} _EC_SECG_PRIME_256K1 = { + { + NID_X9_62_prime_field, 0, 32, 1 + }, + { + /* no seed */ + /* p */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x2F, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + /* x */ + 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, + 0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, + 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98, + /* y */ + 0x48, 0x3a, 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65, 0x5d, 0xa4, 0xfb, 0xfc, + 0x0e, 0x11, 0x08, 0xa8, 0xfd, 0x17, 0xb4, 0x48, 0xa6, 0x85, 0x54, 0x19, + 0x9c, 0x47, 0xd0, 0x8f, 0xfb, 0x10, 0xd4, 0xb8, + /* order */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, + 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41 + } +}; + +/* some wap/wtls curves */ +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 15 * 6]; +} _EC_WTLS_8 = { + { + NID_X9_62_prime_field, 0, 15, 1 + }, + { + /* no seed */ + /* p */ + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFD, 0xE7, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, + /* x */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, + /* y */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, + /* order */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xEC, 0xEA, 0x55, 0x1A, + 0xD8, 0x37, 0xE9 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 21 * 6]; +} _EC_WTLS_9 = { + { + NID_X9_62_prime_field, 0, 21, 1 + }, + { + /* no seed */ + /* p */ + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x80, 0x8F, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + /* x */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* y */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + /* order */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xCD, + 0xC9, 0x8A, 0xE0, 0xE2, 0xDE, 0x57, 0x4A, 0xBF, 0x33 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 28 * 6]; +} _EC_WTLS_12 = { + { + NID_X9_62_prime_field, 0, 28, 1 + }, + { + /* no seed */ + /* p */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + /* a */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, + /* b */ + 0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, 0x32, 0x56, + 0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B, 0x39, 0x43, + 0x23, 0x55, 0xFF, 0xB4, + /* x */ + 0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, 0x90, 0xB9, + 0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xD6, + 0x11, 0x5C, 0x1D, 0x21, + /* y */ + 0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, 0xdf, 0xe6, + 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, 0x44, 0xd5, 0x81, 0x99, + 0x85, 0x00, 0x7e, 0x34, + /* order */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x16, 0xA2, 0xE0, 0xB8, 0xF0, 0x3E, 0x13, 0xDD, 0x29, 0x45, + 0x5C, 0x5C, 0x2A, 0x3D + } +}; + +#ifndef OPENSSL_NO_EC2M + +/* characteristic two curves */ +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 15 * 6]; +} _EC_SECG_CHAR2_113R1 = { + { + NID_X9_62_characteristic_two_field, 20, 15, 2 + }, + { + /* seed */ + 0x10, 0xE7, 0x23, 0xAB, 0x14, 0xD6, 0x96, 0xE6, 0x76, 0x87, 0x56, 0x15, + 0x17, 0x56, 0xFE, 0xBF, 0x8F, 0xCB, 0x49, 0xA9, + /* p */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x01, + /* a */ + 0x00, 0x30, 0x88, 0x25, 0x0C, 0xA6, 0xE7, 0xC7, 0xFE, 0x64, 0x9C, 0xE8, + 0x58, 0x20, 0xF7, + /* b */ + 0x00, 0xE8, 0xBE, 0xE4, 0xD3, 0xE2, 0x26, 0x07, 0x44, 0x18, 0x8B, 0xE0, + 0xE9, 0xC7, 0x23, + /* x */ + 0x00, 0x9D, 0x73, 0x61, 0x6F, 0x35, 0xF4, 0xAB, 0x14, 0x07, 0xD7, 0x35, + 0x62, 0xC1, 0x0F, + /* y */ + 0x00, 0xA5, 0x28, 0x30, 0x27, 0x79, 0x58, 0xEE, 0x84, 0xD1, 0x31, 0x5E, + 0xD3, 0x18, 0x86, + /* order */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD9, 0xCC, 0xEC, 0x8A, + 0x39, 0xE5, 0x6F + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 15 * 6]; +} _EC_SECG_CHAR2_113R2 = { + { + NID_X9_62_characteristic_two_field, 20, 15, 2 + }, + { + /* seed */ + 0x10, 0xC0, 0xFB, 0x15, 0x76, 0x08, 0x60, 0xDE, 0xF1, 0xEE, 0xF4, 0xD6, + 0x96, 0xE6, 0x76, 0x87, 0x56, 0x15, 0x17, 0x5D, + /* p */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x01, + /* a */ + 0x00, 0x68, 0x99, 0x18, 0xDB, 0xEC, 0x7E, 0x5A, 0x0D, 0xD6, 0xDF, 0xC0, + 0xAA, 0x55, 0xC7, + /* b */ + 0x00, 0x95, 0xE9, 0xA9, 0xEC, 0x9B, 0x29, 0x7B, 0xD4, 0xBF, 0x36, 0xE0, + 0x59, 0x18, 0x4F, + /* x */ + 0x01, 0xA5, 0x7A, 0x6A, 0x7B, 0x26, 0xCA, 0x5E, 0xF5, 0x2F, 0xCD, 0xB8, + 0x16, 0x47, 0x97, + /* y */ + 0x00, 0xB3, 0xAD, 0xC9, 0x4E, 0xD1, 0xFE, 0x67, 0x4C, 0x06, 0xE6, 0x95, + 0xBA, 0xBA, 0x1D, + /* order */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x78, 0x9B, 0x24, + 0x96, 0xAF, 0x93 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 17 * 6]; +} _EC_SECG_CHAR2_131R1 = { + { + NID_X9_62_characteristic_two_field, 20, 17, 2 + }, + { + /* seed */ + 0x4D, 0x69, 0x6E, 0x67, 0x68, 0x75, 0x61, 0x51, 0x75, 0x98, 0x5B, 0xD3, + 0xAD, 0xBA, 0xDA, 0x21, 0xB4, 0x3A, 0x97, 0xE2, + /* p */ + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x0D, + /* a */ + 0x07, 0xA1, 0x1B, 0x09, 0xA7, 0x6B, 0x56, 0x21, 0x44, 0x41, 0x8F, 0xF3, + 0xFF, 0x8C, 0x25, 0x70, 0xB8, + /* b */ + 0x02, 0x17, 0xC0, 0x56, 0x10, 0x88, 0x4B, 0x63, 0xB9, 0xC6, 0xC7, 0x29, + 0x16, 0x78, 0xF9, 0xD3, 0x41, + /* x */ + 0x00, 0x81, 0xBA, 0xF9, 0x1F, 0xDF, 0x98, 0x33, 0xC4, 0x0F, 0x9C, 0x18, + 0x13, 0x43, 0x63, 0x83, 0x99, + /* y */ + 0x07, 0x8C, 0x6E, 0x7E, 0xA3, 0x8C, 0x00, 0x1F, 0x73, 0xC8, 0x13, 0x4B, + 0x1B, 0x4E, 0xF9, 0xE1, 0x50, + /* order */ + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x31, 0x23, 0x95, + 0x3A, 0x94, 0x64, 0xB5, 0x4D + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 17 * 6]; +} _EC_SECG_CHAR2_131R2 = { + { + NID_X9_62_characteristic_two_field, 20, 17, 2 + }, + { + /* seed */ + 0x98, 0x5B, 0xD3, 0xAD, 0xBA, 0xD4, 0xD6, 0x96, 0xE6, 0x76, 0x87, 0x56, + 0x15, 0x17, 0x5A, 0x21, 0xB4, 0x3A, 0x97, 0xE3, + /* p */ + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x0D, + /* a */ + 0x03, 0xE5, 0xA8, 0x89, 0x19, 0xD7, 0xCA, 0xFC, 0xBF, 0x41, 0x5F, 0x07, + 0xC2, 0x17, 0x65, 0x73, 0xB2, + /* b */ + 0x04, 0xB8, 0x26, 0x6A, 0x46, 0xC5, 0x56, 0x57, 0xAC, 0x73, 0x4C, 0xE3, + 0x8F, 0x01, 0x8F, 0x21, 0x92, + /* x */ + 0x03, 0x56, 0xDC, 0xD8, 0xF2, 0xF9, 0x50, 0x31, 0xAD, 0x65, 0x2D, 0x23, + 0x95, 0x1B, 0xB3, 0x66, 0xA8, + /* y */ + 0x06, 0x48, 0xF0, 0x6D, 0x86, 0x79, 0x40, 0xA5, 0x36, 0x6D, 0x9E, 0x26, + 0x5D, 0xE9, 0xEB, 0x24, 0x0F, + /* order */ + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x69, 0x54, 0xA2, + 0x33, 0x04, 0x9B, 0xA9, 0x8F + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 21 * 6]; +} _EC_NIST_CHAR2_163K = { + { + NID_X9_62_characteristic_two_field, 0, 21, 2 + }, + { + /* no seed */ + /* p */ + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC9, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* x */ + 0x02, 0xFE, 0x13, 0xC0, 0x53, 0x7B, 0xBC, 0x11, 0xAC, 0xAA, 0x07, 0xD7, + 0x93, 0xDE, 0x4E, 0x6D, 0x5E, 0x5C, 0x94, 0xEE, 0xE8, + /* y */ + 0x02, 0x89, 0x07, 0x0F, 0xB0, 0x5D, 0x38, 0xFF, 0x58, 0x32, 0x1F, 0x2E, + 0x80, 0x05, 0x36, 0xD5, 0x38, 0xCC, 0xDA, 0xA3, 0xD9, + /* order */ + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, + 0x08, 0xA2, 0xE0, 0xCC, 0x0D, 0x99, 0xF8, 0xA5, 0xEF + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 21 * 6]; +} _EC_SECG_CHAR2_163R1 = { + { + NID_X9_62_characteristic_two_field, 0, 21, 2 + }, + { + /* p */ + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC9, + /* a */ + 0x07, 0xB6, 0x88, 0x2C, 0xAA, 0xEF, 0xA8, 0x4F, 0x95, 0x54, 0xFF, 0x84, + 0x28, 0xBD, 0x88, 0xE2, 0x46, 0xD2, 0x78, 0x2A, 0xE2, + /* b */ + 0x07, 0x13, 0x61, 0x2D, 0xCD, 0xDC, 0xB4, 0x0A, 0xAB, 0x94, 0x6B, 0xDA, + 0x29, 0xCA, 0x91, 0xF7, 0x3A, 0xF9, 0x58, 0xAF, 0xD9, + /* x */ + 0x03, 0x69, 0x97, 0x96, 0x97, 0xAB, 0x43, 0x89, 0x77, 0x89, 0x56, 0x67, + 0x89, 0x56, 0x7F, 0x78, 0x7A, 0x78, 0x76, 0xA6, 0x54, + /* y */ + 0x00, 0x43, 0x5E, 0xDB, 0x42, 0xEF, 0xAF, 0xB2, 0x98, 0x9D, 0x51, 0xFE, + 0xFC, 0xE3, 0xC8, 0x09, 0x88, 0xF4, 0x1F, 0xF8, 0x83, + /* order */ + 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x48, + 0xAA, 0xB6, 0x89, 0xC2, 0x9C, 0xA7, 0x10, 0x27, 0x9B + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 21 * 6]; +} _EC_NIST_CHAR2_163B = { + { + NID_X9_62_characteristic_two_field, 0, 21, 2 + }, + { + /* p */ + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC9, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* b */ + 0x02, 0x0A, 0x60, 0x19, 0x07, 0xB8, 0xC9, 0x53, 0xCA, 0x14, 0x81, 0xEB, + 0x10, 0x51, 0x2F, 0x78, 0x74, 0x4A, 0x32, 0x05, 0xFD, + /* x */ + 0x03, 0xF0, 0xEB, 0xA1, 0x62, 0x86, 0xA2, 0xD5, 0x7E, 0xA0, 0x99, 0x11, + 0x68, 0xD4, 0x99, 0x46, 0x37, 0xE8, 0x34, 0x3E, 0x36, + /* y */ + 0x00, 0xD5, 0x1F, 0xBC, 0x6C, 0x71, 0xA0, 0x09, 0x4F, 0xA2, 0xCD, 0xD5, + 0x45, 0xB1, 0x1C, 0x5C, 0x0C, 0x79, 0x73, 0x24, 0xF1, + /* order */ + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x92, + 0xFE, 0x77, 0xE7, 0x0C, 0x12, 0xA4, 0x23, 0x4C, 0x33 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 25 * 6]; +} _EC_SECG_CHAR2_193R1 = { + { + NID_X9_62_characteristic_two_field, 20, 25, 2 + }, + { + /* seed */ + 0x10, 0x3F, 0xAE, 0xC7, 0x4D, 0x69, 0x6E, 0x67, 0x68, 0x75, 0x61, 0x51, + 0x75, 0x77, 0x7F, 0xC5, 0xB1, 0x91, 0xEF, 0x30, + /* p */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x01, + /* a */ + 0x00, 0x17, 0x85, 0x8F, 0xEB, 0x7A, 0x98, 0x97, 0x51, 0x69, 0xE1, 0x71, + 0xF7, 0x7B, 0x40, 0x87, 0xDE, 0x09, 0x8A, 0xC8, 0xA9, 0x11, 0xDF, 0x7B, + 0x01, + /* b */ + 0x00, 0xFD, 0xFB, 0x49, 0xBF, 0xE6, 0xC3, 0xA8, 0x9F, 0xAC, 0xAD, 0xAA, + 0x7A, 0x1E, 0x5B, 0xBC, 0x7C, 0xC1, 0xC2, 0xE5, 0xD8, 0x31, 0x47, 0x88, + 0x14, + /* x */ + 0x01, 0xF4, 0x81, 0xBC, 0x5F, 0x0F, 0xF8, 0x4A, 0x74, 0xAD, 0x6C, 0xDF, + 0x6F, 0xDE, 0xF4, 0xBF, 0x61, 0x79, 0x62, 0x53, 0x72, 0xD8, 0xC0, 0xC5, + 0xE1, + /* y */ + 0x00, 0x25, 0xE3, 0x99, 0xF2, 0x90, 0x37, 0x12, 0xCC, 0xF3, 0xEA, 0x9E, + 0x3A, 0x1A, 0xD1, 0x7F, 0xB0, 0xB3, 0x20, 0x1B, 0x6A, 0xF7, 0xCE, 0x1B, + 0x05, + /* order */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xC7, 0xF3, 0x4A, 0x77, 0x8F, 0x44, 0x3A, 0xCC, 0x92, 0x0E, 0xBA, + 0x49 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 25 * 6]; +} _EC_SECG_CHAR2_193R2 = { + { + NID_X9_62_characteristic_two_field, 20, 25, 2 + }, + { + /* seed */ + 0x10, 0xB7, 0xB4, 0xD6, 0x96, 0xE6, 0x76, 0x87, 0x56, 0x15, 0x17, 0x51, + 0x37, 0xC8, 0xA1, 0x6F, 0xD0, 0xDA, 0x22, 0x11, + /* p */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x01, + /* a */ + 0x01, 0x63, 0xF3, 0x5A, 0x51, 0x37, 0xC2, 0xCE, 0x3E, 0xA6, 0xED, 0x86, + 0x67, 0x19, 0x0B, 0x0B, 0xC4, 0x3E, 0xCD, 0x69, 0x97, 0x77, 0x02, 0x70, + 0x9B, + /* b */ + 0x00, 0xC9, 0xBB, 0x9E, 0x89, 0x27, 0xD4, 0xD6, 0x4C, 0x37, 0x7E, 0x2A, + 0xB2, 0x85, 0x6A, 0x5B, 0x16, 0xE3, 0xEF, 0xB7, 0xF6, 0x1D, 0x43, 0x16, + 0xAE, + /* x */ + 0x00, 0xD9, 0xB6, 0x7D, 0x19, 0x2E, 0x03, 0x67, 0xC8, 0x03, 0xF3, 0x9E, + 0x1A, 0x7E, 0x82, 0xCA, 0x14, 0xA6, 0x51, 0x35, 0x0A, 0xAE, 0x61, 0x7E, + 0x8F, + /* y */ + 0x01, 0xCE, 0x94, 0x33, 0x56, 0x07, 0xC3, 0x04, 0xAC, 0x29, 0xE7, 0xDE, + 0xFB, 0xD9, 0xCA, 0x01, 0xF5, 0x96, 0xF9, 0x27, 0x22, 0x4C, 0xDE, 0xCF, + 0x6C, + /* order */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x5A, 0xAB, 0x56, 0x1B, 0x00, 0x54, 0x13, 0xCC, 0xD4, 0xEE, 0x99, + 0xD5 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 30 * 6]; +} _EC_NIST_CHAR2_233K = { + { + NID_X9_62_characteristic_two_field, 0, 30, 4 + }, + { + /* no seed */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* x */ + 0x01, 0x72, 0x32, 0xBA, 0x85, 0x3A, 0x7E, 0x73, 0x1A, 0xF1, 0x29, 0xF2, + 0x2F, 0xF4, 0x14, 0x95, 0x63, 0xA4, 0x19, 0xC2, 0x6B, 0xF5, 0x0A, 0x4C, + 0x9D, 0x6E, 0xEF, 0xAD, 0x61, 0x26, + /* y */ + 0x01, 0xDB, 0x53, 0x7D, 0xEC, 0xE8, 0x19, 0xB7, 0xF7, 0x0F, 0x55, 0x5A, + 0x67, 0xC4, 0x27, 0xA8, 0xCD, 0x9B, 0xF1, 0x8A, 0xEB, 0x9B, 0x56, 0xE0, + 0xC1, 0x10, 0x56, 0xFA, 0xE6, 0xA3, + /* order */ + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x9D, 0x5B, 0xB9, 0x15, 0xBC, 0xD4, 0x6E, 0xFB, + 0x1A, 0xD5, 0xF1, 0x73, 0xAB, 0xDF + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 30 * 6]; +} _EC_NIST_CHAR2_233B = { + { + NID_X9_62_characteristic_two_field, 20, 30, 2 + }, + { + /* seed */ + 0x74, 0xD5, 0x9F, 0xF0, 0x7F, 0x6B, 0x41, 0x3D, 0x0E, 0xA1, 0x4B, 0x34, + 0x4B, 0x20, 0xA2, 0xDB, 0x04, 0x9B, 0x50, 0xC3, + /* p */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* b */ + 0x00, 0x66, 0x64, 0x7E, 0xDE, 0x6C, 0x33, 0x2C, 0x7F, 0x8C, 0x09, 0x23, + 0xBB, 0x58, 0x21, 0x3B, 0x33, 0x3B, 0x20, 0xE9, 0xCE, 0x42, 0x81, 0xFE, + 0x11, 0x5F, 0x7D, 0x8F, 0x90, 0xAD, + /* x */ + 0x00, 0xFA, 0xC9, 0xDF, 0xCB, 0xAC, 0x83, 0x13, 0xBB, 0x21, 0x39, 0xF1, + 0xBB, 0x75, 0x5F, 0xEF, 0x65, 0xBC, 0x39, 0x1F, 0x8B, 0x36, 0xF8, 0xF8, + 0xEB, 0x73, 0x71, 0xFD, 0x55, 0x8B, + /* y */ + 0x01, 0x00, 0x6A, 0x08, 0xA4, 0x19, 0x03, 0x35, 0x06, 0x78, 0xE5, 0x85, + 0x28, 0xBE, 0xBF, 0x8A, 0x0B, 0xEF, 0xF8, 0x67, 0xA7, 0xCA, 0x36, 0x71, + 0x6F, 0x7E, 0x01, 0xF8, 0x10, 0x52, + /* order */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x13, 0xE9, 0x74, 0xE7, 0x2F, 0x8A, 0x69, 0x22, 0x03, + 0x1D, 0x26, 0x03, 0xCF, 0xE0, 0xD7 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 30 * 6]; +} _EC_SECG_CHAR2_239K1 = { + { + NID_X9_62_characteristic_two_field, 0, 30, 4 + }, + { + /* no seed */ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* x */ + 0x29, 0xA0, 0xB6, 0xA8, 0x87, 0xA9, 0x83, 0xE9, 0x73, 0x09, 0x88, 0xA6, + 0x87, 0x27, 0xA8, 0xB2, 0xD1, 0x26, 0xC4, 0x4C, 0xC2, 0xCC, 0x7B, 0x2A, + 0x65, 0x55, 0x19, 0x30, 0x35, 0xDC, + /* y */ + 0x76, 0x31, 0x08, 0x04, 0xF1, 0x2E, 0x54, 0x9B, 0xDB, 0x01, 0x1C, 0x10, + 0x30, 0x89, 0xE7, 0x35, 0x10, 0xAC, 0xB2, 0x75, 0xFC, 0x31, 0x2A, 0x5D, + 0xC6, 0xB7, 0x65, 0x53, 0xF0, 0xCA, + /* order */ + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x5A, 0x79, 0xFE, 0xC6, 0x7C, 0xB6, 0xE9, 0x1F, 0x1C, + 0x1D, 0xA8, 0x00, 0xE4, 0x78, 0xA5 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 36 * 6]; +} _EC_NIST_CHAR2_283K = { + { + NID_X9_62_characteristic_two_field, 0, 36, 4 + }, + { + /* no seed */ + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA1, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* x */ + 0x05, 0x03, 0x21, 0x3F, 0x78, 0xCA, 0x44, 0x88, 0x3F, 0x1A, 0x3B, 0x81, + 0x62, 0xF1, 0x88, 0xE5, 0x53, 0xCD, 0x26, 0x5F, 0x23, 0xC1, 0x56, 0x7A, + 0x16, 0x87, 0x69, 0x13, 0xB0, 0xC2, 0xAC, 0x24, 0x58, 0x49, 0x28, 0x36, + /* y */ + 0x01, 0xCC, 0xDA, 0x38, 0x0F, 0x1C, 0x9E, 0x31, 0x8D, 0x90, 0xF9, 0x5D, + 0x07, 0xE5, 0x42, 0x6F, 0xE8, 0x7E, 0x45, 0xC0, 0xE8, 0x18, 0x46, 0x98, + 0xE4, 0x59, 0x62, 0x36, 0x4E, 0x34, 0x11, 0x61, 0x77, 0xDD, 0x22, 0x59, + /* order */ + 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE9, 0xAE, 0x2E, 0xD0, 0x75, 0x77, + 0x26, 0x5D, 0xFF, 0x7F, 0x94, 0x45, 0x1E, 0x06, 0x1E, 0x16, 0x3C, 0x61 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 36 * 6]; +} _EC_NIST_CHAR2_283B = { + { + NID_X9_62_characteristic_two_field, 20, 36, 2 + }, + { + /* no seed */ + 0x77, 0xE2, 0xB0, 0x73, 0x70, 0xEB, 0x0F, 0x83, 0x2A, 0x6D, 0xD5, 0xB6, + 0x2D, 0xFC, 0x88, 0xCD, 0x06, 0xBB, 0x84, 0xBE, + /* p */ + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA1, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* b */ + 0x02, 0x7B, 0x68, 0x0A, 0xC8, 0xB8, 0x59, 0x6D, 0xA5, 0xA4, 0xAF, 0x8A, + 0x19, 0xA0, 0x30, 0x3F, 0xCA, 0x97, 0xFD, 0x76, 0x45, 0x30, 0x9F, 0xA2, + 0xA5, 0x81, 0x48, 0x5A, 0xF6, 0x26, 0x3E, 0x31, 0x3B, 0x79, 0xA2, 0xF5, + /* x */ + 0x05, 0xF9, 0x39, 0x25, 0x8D, 0xB7, 0xDD, 0x90, 0xE1, 0x93, 0x4F, 0x8C, + 0x70, 0xB0, 0xDF, 0xEC, 0x2E, 0xED, 0x25, 0xB8, 0x55, 0x7E, 0xAC, 0x9C, + 0x80, 0xE2, 0xE1, 0x98, 0xF8, 0xCD, 0xBE, 0xCD, 0x86, 0xB1, 0x20, 0x53, + /* y */ + 0x03, 0x67, 0x68, 0x54, 0xFE, 0x24, 0x14, 0x1C, 0xB9, 0x8F, 0xE6, 0xD4, + 0xB2, 0x0D, 0x02, 0xB4, 0x51, 0x6F, 0xF7, 0x02, 0x35, 0x0E, 0xDD, 0xB0, + 0x82, 0x67, 0x79, 0xC8, 0x13, 0xF0, 0xDF, 0x45, 0xBE, 0x81, 0x12, 0xF4, + /* order */ + 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x90, 0x39, 0x96, 0x60, 0xFC, + 0x93, 0x8A, 0x90, 0x16, 0x5B, 0x04, 0x2A, 0x7C, 0xEF, 0xAD, 0xB3, 0x07 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 52 * 6]; +} _EC_NIST_CHAR2_409K = { + { + NID_X9_62_characteristic_two_field, 0, 52, 4 + }, + { + /* no seed */ + /* p */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + /* x */ + 0x00, 0x60, 0xF0, 0x5F, 0x65, 0x8F, 0x49, 0xC1, 0xAD, 0x3A, 0xB1, 0x89, + 0x0F, 0x71, 0x84, 0x21, 0x0E, 0xFD, 0x09, 0x87, 0xE3, 0x07, 0xC8, 0x4C, + 0x27, 0xAC, 0xCF, 0xB8, 0xF9, 0xF6, 0x7C, 0xC2, 0xC4, 0x60, 0x18, 0x9E, + 0xB5, 0xAA, 0xAA, 0x62, 0xEE, 0x22, 0x2E, 0xB1, 0xB3, 0x55, 0x40, 0xCF, + 0xE9, 0x02, 0x37, 0x46, + /* y */ + 0x01, 0xE3, 0x69, 0x05, 0x0B, 0x7C, 0x4E, 0x42, 0xAC, 0xBA, 0x1D, 0xAC, + 0xBF, 0x04, 0x29, 0x9C, 0x34, 0x60, 0x78, 0x2F, 0x91, 0x8E, 0xA4, 0x27, + 0xE6, 0x32, 0x51, 0x65, 0xE9, 0xEA, 0x10, 0xE3, 0xDA, 0x5F, 0x6C, 0x42, + 0xE9, 0xC5, 0x52, 0x15, 0xAA, 0x9C, 0xA2, 0x7A, 0x58, 0x63, 0xEC, 0x48, + 0xD8, 0xE0, 0x28, 0x6B, + /* order */ + 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFE, 0x5F, 0x83, 0xB2, 0xD4, 0xEA, 0x20, 0x40, 0x0E, 0xC4, + 0x55, 0x7D, 0x5E, 0xD3, 0xE3, 0xE7, 0xCA, 0x5B, 0x4B, 0x5C, 0x83, 0xB8, + 0xE0, 0x1E, 0x5F, 0xCF + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 52 * 6]; +} _EC_NIST_CHAR2_409B = { + { + NID_X9_62_characteristic_two_field, 20, 52, 2 + }, + { + /* seed */ + 0x40, 0x99, 0xB5, 0xA4, 0x57, 0xF9, 0xD6, 0x9F, 0x79, 0x21, 0x3D, 0x09, + 0x4C, 0x4B, 0xCD, 0x4D, 0x42, 0x62, 0x21, 0x0B, + /* p */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + /* b */ + 0x00, 0x21, 0xA5, 0xC2, 0xC8, 0xEE, 0x9F, 0xEB, 0x5C, 0x4B, 0x9A, 0x75, + 0x3B, 0x7B, 0x47, 0x6B, 0x7F, 0xD6, 0x42, 0x2E, 0xF1, 0xF3, 0xDD, 0x67, + 0x47, 0x61, 0xFA, 0x99, 0xD6, 0xAC, 0x27, 0xC8, 0xA9, 0xA1, 0x97, 0xB2, + 0x72, 0x82, 0x2F, 0x6C, 0xD5, 0x7A, 0x55, 0xAA, 0x4F, 0x50, 0xAE, 0x31, + 0x7B, 0x13, 0x54, 0x5F, + /* x */ + 0x01, 0x5D, 0x48, 0x60, 0xD0, 0x88, 0xDD, 0xB3, 0x49, 0x6B, 0x0C, 0x60, + 0x64, 0x75, 0x62, 0x60, 0x44, 0x1C, 0xDE, 0x4A, 0xF1, 0x77, 0x1D, 0x4D, + 0xB0, 0x1F, 0xFE, 0x5B, 0x34, 0xE5, 0x97, 0x03, 0xDC, 0x25, 0x5A, 0x86, + 0x8A, 0x11, 0x80, 0x51, 0x56, 0x03, 0xAE, 0xAB, 0x60, 0x79, 0x4E, 0x54, + 0xBB, 0x79, 0x96, 0xA7, + /* y */ + 0x00, 0x61, 0xB1, 0xCF, 0xAB, 0x6B, 0xE5, 0xF3, 0x2B, 0xBF, 0xA7, 0x83, + 0x24, 0xED, 0x10, 0x6A, 0x76, 0x36, 0xB9, 0xC5, 0xA7, 0xBD, 0x19, 0x8D, + 0x01, 0x58, 0xAA, 0x4F, 0x54, 0x88, 0xD0, 0x8F, 0x38, 0x51, 0x4F, 0x1F, + 0xDF, 0x4B, 0x4F, 0x40, 0xD2, 0x18, 0x1B, 0x36, 0x81, 0xC3, 0x64, 0xBA, + 0x02, 0x73, 0xC7, 0x06, + /* order */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xE2, 0xAA, 0xD6, 0xA6, 0x12, 0xF3, 0x33, 0x07, 0xBE, + 0x5F, 0xA4, 0x7C, 0x3C, 0x9E, 0x05, 0x2F, 0x83, 0x81, 0x64, 0xCD, 0x37, + 0xD9, 0xA2, 0x11, 0x73 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 72 * 6]; +} _EC_NIST_CHAR2_571K = { + { + NID_X9_62_characteristic_two_field, 0, 72, 4 + }, + { + /* no seed */ + /* p */ + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x25, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* x */ + 0x02, 0x6E, 0xB7, 0xA8, 0x59, 0x92, 0x3F, 0xBC, 0x82, 0x18, 0x96, 0x31, + 0xF8, 0x10, 0x3F, 0xE4, 0xAC, 0x9C, 0xA2, 0x97, 0x00, 0x12, 0xD5, 0xD4, + 0x60, 0x24, 0x80, 0x48, 0x01, 0x84, 0x1C, 0xA4, 0x43, 0x70, 0x95, 0x84, + 0x93, 0xB2, 0x05, 0xE6, 0x47, 0xDA, 0x30, 0x4D, 0xB4, 0xCE, 0xB0, 0x8C, + 0xBB, 0xD1, 0xBA, 0x39, 0x49, 0x47, 0x76, 0xFB, 0x98, 0x8B, 0x47, 0x17, + 0x4D, 0xCA, 0x88, 0xC7, 0xE2, 0x94, 0x52, 0x83, 0xA0, 0x1C, 0x89, 0x72, + /* y */ + 0x03, 0x49, 0xDC, 0x80, 0x7F, 0x4F, 0xBF, 0x37, 0x4F, 0x4A, 0xEA, 0xDE, + 0x3B, 0xCA, 0x95, 0x31, 0x4D, 0xD5, 0x8C, 0xEC, 0x9F, 0x30, 0x7A, 0x54, + 0xFF, 0xC6, 0x1E, 0xFC, 0x00, 0x6D, 0x8A, 0x2C, 0x9D, 0x49, 0x79, 0xC0, + 0xAC, 0x44, 0xAE, 0xA7, 0x4F, 0xBE, 0xBB, 0xB9, 0xF7, 0x72, 0xAE, 0xDC, + 0xB6, 0x20, 0xB0, 0x1A, 0x7B, 0xA7, 0xAF, 0x1B, 0x32, 0x04, 0x30, 0xC8, + 0x59, 0x19, 0x84, 0xF6, 0x01, 0xCD, 0x4C, 0x14, 0x3E, 0xF1, 0xC7, 0xA3, + /* order */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x13, 0x18, 0x50, 0xE1, 0xF1, 0x9A, 0x63, 0xE4, 0xB3, 0x91, 0xA8, 0xDB, + 0x91, 0x7F, 0x41, 0x38, 0xB6, 0x30, 0xD8, 0x4B, 0xE5, 0xD6, 0x39, 0x38, + 0x1E, 0x91, 0xDE, 0xB4, 0x5C, 0xFE, 0x77, 0x8F, 0x63, 0x7C, 0x10, 0x01 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 72 * 6]; +} _EC_NIST_CHAR2_571B = { + { + NID_X9_62_characteristic_two_field, 20, 72, 2 + }, + { + /* seed */ + 0x2A, 0xA0, 0x58, 0xF7, 0x3A, 0x0E, 0x33, 0xAB, 0x48, 0x6B, 0x0F, 0x61, + 0x04, 0x10, 0xC5, 0x3A, 0x7F, 0x13, 0x23, 0x10, + /* p */ + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x25, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* b */ + 0x02, 0xF4, 0x0E, 0x7E, 0x22, 0x21, 0xF2, 0x95, 0xDE, 0x29, 0x71, 0x17, + 0xB7, 0xF3, 0xD6, 0x2F, 0x5C, 0x6A, 0x97, 0xFF, 0xCB, 0x8C, 0xEF, 0xF1, + 0xCD, 0x6B, 0xA8, 0xCE, 0x4A, 0x9A, 0x18, 0xAD, 0x84, 0xFF, 0xAB, 0xBD, + 0x8E, 0xFA, 0x59, 0x33, 0x2B, 0xE7, 0xAD, 0x67, 0x56, 0xA6, 0x6E, 0x29, + 0x4A, 0xFD, 0x18, 0x5A, 0x78, 0xFF, 0x12, 0xAA, 0x52, 0x0E, 0x4D, 0xE7, + 0x39, 0xBA, 0xCA, 0x0C, 0x7F, 0xFE, 0xFF, 0x7F, 0x29, 0x55, 0x72, 0x7A, + /* x */ + 0x03, 0x03, 0x00, 0x1D, 0x34, 0xB8, 0x56, 0x29, 0x6C, 0x16, 0xC0, 0xD4, + 0x0D, 0x3C, 0xD7, 0x75, 0x0A, 0x93, 0xD1, 0xD2, 0x95, 0x5F, 0xA8, 0x0A, + 0xA5, 0xF4, 0x0F, 0xC8, 0xDB, 0x7B, 0x2A, 0xBD, 0xBD, 0xE5, 0x39, 0x50, + 0xF4, 0xC0, 0xD2, 0x93, 0xCD, 0xD7, 0x11, 0xA3, 0x5B, 0x67, 0xFB, 0x14, + 0x99, 0xAE, 0x60, 0x03, 0x86, 0x14, 0xF1, 0x39, 0x4A, 0xBF, 0xA3, 0xB4, + 0xC8, 0x50, 0xD9, 0x27, 0xE1, 0xE7, 0x76, 0x9C, 0x8E, 0xEC, 0x2D, 0x19, + /* y */ + 0x03, 0x7B, 0xF2, 0x73, 0x42, 0xDA, 0x63, 0x9B, 0x6D, 0xCC, 0xFF, 0xFE, + 0xB7, 0x3D, 0x69, 0xD7, 0x8C, 0x6C, 0x27, 0xA6, 0x00, 0x9C, 0xBB, 0xCA, + 0x19, 0x80, 0xF8, 0x53, 0x39, 0x21, 0xE8, 0xA6, 0x84, 0x42, 0x3E, 0x43, + 0xBA, 0xB0, 0x8A, 0x57, 0x62, 0x91, 0xAF, 0x8F, 0x46, 0x1B, 0xB2, 0xA8, + 0xB3, 0x53, 0x1D, 0x2F, 0x04, 0x85, 0xC1, 0x9B, 0x16, 0xE2, 0xF1, 0x51, + 0x6E, 0x23, 0xDD, 0x3C, 0x1A, 0x48, 0x27, 0xAF, 0x1B, 0x8A, 0xC1, 0x5B, + /* order */ + 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE6, 0x61, 0xCE, 0x18, 0xFF, 0x55, 0x98, 0x73, 0x08, 0x05, 0x9B, 0x18, + 0x68, 0x23, 0x85, 0x1E, 0xC7, 0xDD, 0x9C, 0xA1, 0x16, 0x1D, 0xE9, 0x3D, + 0x51, 0x74, 0xD6, 0x6E, 0x83, 0x82, 0xE9, 0xBB, 0x2F, 0xE8, 0x4E, 0x47 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 21 * 6]; +} _EC_X9_62_CHAR2_163V1 = { + { + NID_X9_62_characteristic_two_field, 20, 21, 2 + }, + { + /* seed */ + 0xD2, 0xC0, 0xFB, 0x15, 0x76, 0x08, 0x60, 0xDE, 0xF1, 0xEE, 0xF4, 0xD6, + 0x96, 0xE6, 0x76, 0x87, 0x56, 0x15, 0x17, 0x54, + /* p */ + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, + /* a */ + 0x07, 0x25, 0x46, 0xB5, 0x43, 0x52, 0x34, 0xA4, 0x22, 0xE0, 0x78, 0x96, + 0x75, 0xF4, 0x32, 0xC8, 0x94, 0x35, 0xDE, 0x52, 0x42, + /* b */ + 0x00, 0xC9, 0x51, 0x7D, 0x06, 0xD5, 0x24, 0x0D, 0x3C, 0xFF, 0x38, 0xC7, + 0x4B, 0x20, 0xB6, 0xCD, 0x4D, 0x6F, 0x9D, 0xD4, 0xD9, + /* x */ + 0x07, 0xAF, 0x69, 0x98, 0x95, 0x46, 0x10, 0x3D, 0x79, 0x32, 0x9F, 0xCC, + 0x3D, 0x74, 0x88, 0x0F, 0x33, 0xBB, 0xE8, 0x03, 0xCB, + /* y */ + 0x01, 0xEC, 0x23, 0x21, 0x1B, 0x59, 0x66, 0xAD, 0xEA, 0x1D, 0x3F, 0x87, + 0xF7, 0xEA, 0x58, 0x48, 0xAE, 0xF0, 0xB7, 0xCA, 0x9F, + /* order */ + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE6, + 0x0F, 0xC8, 0x82, 0x1C, 0xC7, 0x4D, 0xAE, 0xAF, 0xC1 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 21 * 6]; +} _EC_X9_62_CHAR2_163V2 = { + { + NID_X9_62_characteristic_two_field, 20, 21, 2 + }, + { + /* seed */ + 0x53, 0x81, 0x4C, 0x05, 0x0D, 0x44, 0xD6, 0x96, 0xE6, 0x76, 0x87, 0x56, + 0x15, 0x17, 0x58, 0x0C, 0xA4, 0xE2, 0x9F, 0xFD, + /* p */ + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, + /* a */ + 0x01, 0x08, 0xB3, 0x9E, 0x77, 0xC4, 0xB1, 0x08, 0xBE, 0xD9, 0x81, 0xED, + 0x0E, 0x89, 0x0E, 0x11, 0x7C, 0x51, 0x1C, 0xF0, 0x72, + /* b */ + 0x06, 0x67, 0xAC, 0xEB, 0x38, 0xAF, 0x4E, 0x48, 0x8C, 0x40, 0x74, 0x33, + 0xFF, 0xAE, 0x4F, 0x1C, 0x81, 0x16, 0x38, 0xDF, 0x20, + /* x */ + 0x00, 0x24, 0x26, 0x6E, 0x4E, 0xB5, 0x10, 0x6D, 0x0A, 0x96, 0x4D, 0x92, + 0xC4, 0x86, 0x0E, 0x26, 0x71, 0xDB, 0x9B, 0x6C, 0xC5, + /* y */ + 0x07, 0x9F, 0x68, 0x4D, 0xDF, 0x66, 0x84, 0xC5, 0xCD, 0x25, 0x8B, 0x38, + 0x90, 0x02, 0x1B, 0x23, 0x86, 0xDF, 0xD1, 0x9F, 0xC5, + /* order */ + 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xF6, + 0x4D, 0xE1, 0x15, 0x1A, 0xDB, 0xB7, 0x8F, 0x10, 0xA7 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 21 * 6]; +} _EC_X9_62_CHAR2_163V3 = { + { + NID_X9_62_characteristic_two_field, 20, 21, 2 + }, + { + /* seed */ + 0x50, 0xCB, 0xF1, 0xD9, 0x5C, 0xA9, 0x4D, 0x69, 0x6E, 0x67, 0x68, 0x75, + 0x61, 0x51, 0x75, 0xF1, 0x6A, 0x36, 0xA3, 0xB8, + /* p */ + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, + /* a */ + 0x07, 0xA5, 0x26, 0xC6, 0x3D, 0x3E, 0x25, 0xA2, 0x56, 0xA0, 0x07, 0x69, + 0x9F, 0x54, 0x47, 0xE3, 0x2A, 0xE4, 0x56, 0xB5, 0x0E, + /* b */ + 0x03, 0xF7, 0x06, 0x17, 0x98, 0xEB, 0x99, 0xE2, 0x38, 0xFD, 0x6F, 0x1B, + 0xF9, 0x5B, 0x48, 0xFE, 0xEB, 0x48, 0x54, 0x25, 0x2B, + /* x */ + 0x02, 0xF9, 0xF8, 0x7B, 0x7C, 0x57, 0x4D, 0x0B, 0xDE, 0xCF, 0x8A, 0x22, + 0xE6, 0x52, 0x47, 0x75, 0xF9, 0x8C, 0xDE, 0xBD, 0xCB, + /* y */ + 0x05, 0xB9, 0x35, 0x59, 0x0C, 0x15, 0x5E, 0x17, 0xEA, 0x48, 0xEB, 0x3F, + 0xF3, 0x71, 0x8B, 0x89, 0x3D, 0xF5, 0x9A, 0x05, 0xD0, + /* order */ + 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x1A, + 0xEE, 0x14, 0x0F, 0x11, 0x0A, 0xFF, 0x96, 0x13, 0x09 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 23 * 6]; +} _EC_X9_62_CHAR2_176V1 = { + { + NID_X9_62_characteristic_two_field, 0, 23, 0xFF6E + }, + { + /* no seed */ + /* p */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x07, + /* a */ + 0x00, 0xE4, 0xE6, 0xDB, 0x29, 0x95, 0x06, 0x5C, 0x40, 0x7D, 0x9D, 0x39, + 0xB8, 0xD0, 0x96, 0x7B, 0x96, 0x70, 0x4B, 0xA8, 0xE9, 0xC9, 0x0B, + /* b */ + 0x00, 0x5D, 0xDA, 0x47, 0x0A, 0xBE, 0x64, 0x14, 0xDE, 0x8E, 0xC1, 0x33, + 0xAE, 0x28, 0xE9, 0xBB, 0xD7, 0xFC, 0xEC, 0x0A, 0xE0, 0xFF, 0xF2, + /* x */ + 0x00, 0x8D, 0x16, 0xC2, 0x86, 0x67, 0x98, 0xB6, 0x00, 0xF9, 0xF0, 0x8B, + 0xB4, 0xA8, 0xE8, 0x60, 0xF3, 0x29, 0x8C, 0xE0, 0x4A, 0x57, 0x98, + /* y */ + 0x00, 0x6F, 0xA4, 0x53, 0x9C, 0x2D, 0xAD, 0xDD, 0xD6, 0xBA, 0xB5, 0x16, + 0x7D, 0x61, 0xB4, 0x36, 0xE1, 0xD9, 0x2B, 0xB1, 0x6A, 0x56, 0x2C, + /* order */ + 0x00, 0x00, 0x01, 0x00, 0x92, 0x53, 0x73, 0x97, 0xEC, 0xA4, 0xF6, 0x14, + 0x57, 0x99, 0xD6, 0x2B, 0x0A, 0x19, 0xCE, 0x06, 0xFE, 0x26, 0xAD + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 24 * 6]; +} _EC_X9_62_CHAR2_191V1 = { + { + NID_X9_62_characteristic_two_field, 20, 24, 2 + }, + { + /* seed */ + 0x4E, 0x13, 0xCA, 0x54, 0x27, 0x44, 0xD6, 0x96, 0xE6, 0x76, 0x87, 0x56, + 0x15, 0x17, 0x55, 0x2F, 0x27, 0x9A, 0x8C, 0x84, + /* p */ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, + /* a */ + 0x28, 0x66, 0x53, 0x7B, 0x67, 0x67, 0x52, 0x63, 0x6A, 0x68, 0xF5, 0x65, + 0x54, 0xE1, 0x26, 0x40, 0x27, 0x6B, 0x64, 0x9E, 0xF7, 0x52, 0x62, 0x67, + /* b */ + 0x2E, 0x45, 0xEF, 0x57, 0x1F, 0x00, 0x78, 0x6F, 0x67, 0xB0, 0x08, 0x1B, + 0x94, 0x95, 0xA3, 0xD9, 0x54, 0x62, 0xF5, 0xDE, 0x0A, 0xA1, 0x85, 0xEC, + /* x */ + 0x36, 0xB3, 0xDA, 0xF8, 0xA2, 0x32, 0x06, 0xF9, 0xC4, 0xF2, 0x99, 0xD7, + 0xB2, 0x1A, 0x9C, 0x36, 0x91, 0x37, 0xF2, 0xC8, 0x4A, 0xE1, 0xAA, 0x0D, + /* y */ + 0x76, 0x5B, 0xE7, 0x34, 0x33, 0xB3, 0xF9, 0x5E, 0x33, 0x29, 0x32, 0xE7, + 0x0E, 0xA2, 0x45, 0xCA, 0x24, 0x18, 0xEA, 0x0E, 0xF9, 0x80, 0x18, 0xFB, + /* order */ + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0xA2, 0x0E, 0x90, 0xC3, 0x90, 0x67, 0xC8, 0x93, 0xBB, 0xB9, 0xA5 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 24 * 6]; +} _EC_X9_62_CHAR2_191V2 = { + { + NID_X9_62_characteristic_two_field, 20, 24, 4 + }, + { + /* seed */ + 0x08, 0x71, 0xEF, 0x2F, 0xEF, 0x24, 0xD6, 0x96, 0xE6, 0x76, 0x87, 0x56, + 0x15, 0x17, 0x58, 0xBE, 0xE0, 0xD9, 0x5C, 0x15, + /* p */ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, + /* a */ + 0x40, 0x10, 0x28, 0x77, 0x4D, 0x77, 0x77, 0xC7, 0xB7, 0x66, 0x6D, 0x13, + 0x66, 0xEA, 0x43, 0x20, 0x71, 0x27, 0x4F, 0x89, 0xFF, 0x01, 0xE7, 0x18, + /* b */ + 0x06, 0x20, 0x04, 0x8D, 0x28, 0xBC, 0xBD, 0x03, 0xB6, 0x24, 0x9C, 0x99, + 0x18, 0x2B, 0x7C, 0x8C, 0xD1, 0x97, 0x00, 0xC3, 0x62, 0xC4, 0x6A, 0x01, + /* x */ + 0x38, 0x09, 0xB2, 0xB7, 0xCC, 0x1B, 0x28, 0xCC, 0x5A, 0x87, 0x92, 0x6A, + 0xAD, 0x83, 0xFD, 0x28, 0x78, 0x9E, 0x81, 0xE2, 0xC9, 0xE3, 0xBF, 0x10, + /* y */ + 0x17, 0x43, 0x43, 0x86, 0x62, 0x6D, 0x14, 0xF3, 0xDB, 0xF0, 0x17, 0x60, + 0xD9, 0x21, 0x3A, 0x3E, 0x1C, 0xF3, 0x7A, 0xEC, 0x43, 0x7D, 0x66, 0x8A, + /* order */ + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x50, 0x50, 0x8C, 0xB8, 0x9F, 0x65, 0x28, 0x24, 0xE0, 0x6B, 0x81, 0x73 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 24 * 6]; +} _EC_X9_62_CHAR2_191V3 = { + { + NID_X9_62_characteristic_two_field, 20, 24, 6 + }, + { + /* seed */ + 0xE0, 0x53, 0x51, 0x2D, 0xC6, 0x84, 0xD6, 0x96, 0xE6, 0x76, 0x87, 0x56, + 0x15, 0x17, 0x50, 0x67, 0xAE, 0x78, 0x6D, 0x1F, + /* p */ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, + /* a */ + 0x6C, 0x01, 0x07, 0x47, 0x56, 0x09, 0x91, 0x22, 0x22, 0x10, 0x56, 0x91, + 0x1C, 0x77, 0xD7, 0x7E, 0x77, 0xA7, 0x77, 0xE7, 0xE7, 0xE7, 0x7F, 0xCB, + /* b */ + 0x71, 0xFE, 0x1A, 0xF9, 0x26, 0xCF, 0x84, 0x79, 0x89, 0xEF, 0xEF, 0x8D, + 0xB4, 0x59, 0xF6, 0x63, 0x94, 0xD9, 0x0F, 0x32, 0xAD, 0x3F, 0x15, 0xE8, + /* x */ + 0x37, 0x5D, 0x4C, 0xE2, 0x4F, 0xDE, 0x43, 0x44, 0x89, 0xDE, 0x87, 0x46, + 0xE7, 0x17, 0x86, 0x01, 0x50, 0x09, 0xE6, 0x6E, 0x38, 0xA9, 0x26, 0xDD, + /* y */ + 0x54, 0x5A, 0x39, 0x17, 0x61, 0x96, 0x57, 0x5D, 0x98, 0x59, 0x99, 0x36, + 0x6E, 0x6A, 0xD3, 0x4C, 0xE0, 0xA7, 0x7C, 0xD7, 0x12, 0x7B, 0x06, 0xBE, + /* order */ + 0x15, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x61, 0x0C, 0x0B, 0x19, 0x68, 0x12, 0xBF, 0xB6, 0x28, 0x8A, 0x3E, 0xA3 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 27 * 6]; +} _EC_X9_62_CHAR2_208W1 = { + { + NID_X9_62_characteristic_two_field, 0, 27, 0xFE48 + }, + { + /* no seed */ + /* p */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x07, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + /* b */ + 0x00, 0xC8, 0x61, 0x9E, 0xD4, 0x5A, 0x62, 0xE6, 0x21, 0x2E, 0x11, 0x60, + 0x34, 0x9E, 0x2B, 0xFA, 0x84, 0x44, 0x39, 0xFA, 0xFC, 0x2A, 0x3F, 0xD1, + 0x63, 0x8F, 0x9E, + /* x */ + 0x00, 0x89, 0xFD, 0xFB, 0xE4, 0xAB, 0xE1, 0x93, 0xDF, 0x95, 0x59, 0xEC, + 0xF0, 0x7A, 0xC0, 0xCE, 0x78, 0x55, 0x4E, 0x27, 0x84, 0xEB, 0x8C, 0x1E, + 0xD1, 0xA5, 0x7A, + /* y */ + 0x00, 0x0F, 0x55, 0xB5, 0x1A, 0x06, 0xE7, 0x8E, 0x9A, 0xC3, 0x8A, 0x03, + 0x5F, 0xF5, 0x20, 0xD8, 0xB0, 0x17, 0x81, 0xBE, 0xB1, 0xA6, 0xBB, 0x08, + 0x61, 0x7D, 0xE3, + /* order */ + 0x00, 0x00, 0x01, 0x01, 0xBA, 0xF9, 0x5C, 0x97, 0x23, 0xC5, 0x7B, 0x6C, + 0x21, 0xDA, 0x2E, 0xFF, 0x2D, 0x5E, 0xD5, 0x88, 0xBD, 0xD5, 0x71, 0x7E, + 0x21, 0x2F, 0x9D + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 30 * 6]; +} _EC_X9_62_CHAR2_239V1 = { + { + NID_X9_62_characteristic_two_field, 20, 30, 4 + }, + { + /* seed */ + 0xD3, 0x4B, 0x9A, 0x4D, 0x69, 0x6E, 0x67, 0x68, 0x75, 0x61, 0x51, 0x75, + 0xCA, 0x71, 0xB9, 0x20, 0xBF, 0xEF, 0xB0, 0x5D, + /* p */ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, + /* a */ + 0x32, 0x01, 0x08, 0x57, 0x07, 0x7C, 0x54, 0x31, 0x12, 0x3A, 0x46, 0xB8, + 0x08, 0x90, 0x67, 0x56, 0xF5, 0x43, 0x42, 0x3E, 0x8D, 0x27, 0x87, 0x75, + 0x78, 0x12, 0x57, 0x78, 0xAC, 0x76, + /* b */ + 0x79, 0x04, 0x08, 0xF2, 0xEE, 0xDA, 0xF3, 0x92, 0xB0, 0x12, 0xED, 0xEF, + 0xB3, 0x39, 0x2F, 0x30, 0xF4, 0x32, 0x7C, 0x0C, 0xA3, 0xF3, 0x1F, 0xC3, + 0x83, 0xC4, 0x22, 0xAA, 0x8C, 0x16, + /* x */ + 0x57, 0x92, 0x70, 0x98, 0xFA, 0x93, 0x2E, 0x7C, 0x0A, 0x96, 0xD3, 0xFD, + 0x5B, 0x70, 0x6E, 0xF7, 0xE5, 0xF5, 0xC1, 0x56, 0xE1, 0x6B, 0x7E, 0x7C, + 0x86, 0x03, 0x85, 0x52, 0xE9, 0x1D, + /* y */ + 0x61, 0xD8, 0xEE, 0x50, 0x77, 0xC3, 0x3F, 0xEC, 0xF6, 0xF1, 0xA1, 0x6B, + 0x26, 0x8D, 0xE4, 0x69, 0xC3, 0xC7, 0x74, 0x4E, 0xA9, 0xA9, 0x71, 0x64, + 0x9F, 0xC7, 0xA9, 0x61, 0x63, 0x05, + /* order */ + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0F, 0x4D, 0x42, 0xFF, 0xE1, 0x49, 0x2A, 0x49, 0x93, + 0xF1, 0xCA, 0xD6, 0x66, 0xE4, 0x47 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 30 * 6]; +} _EC_X9_62_CHAR2_239V2 = { + { + NID_X9_62_characteristic_two_field, 20, 30, 6 + }, + { + /* seed */ + 0x2A, 0xA6, 0x98, 0x2F, 0xDF, 0xA4, 0xD6, 0x96, 0xE6, 0x76, 0x87, 0x56, + 0x15, 0x17, 0x5D, 0x26, 0x67, 0x27, 0x27, 0x7D, + /* p */ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, + /* a */ + 0x42, 0x30, 0x01, 0x77, 0x57, 0xA7, 0x67, 0xFA, 0xE4, 0x23, 0x98, 0x56, + 0x9B, 0x74, 0x63, 0x25, 0xD4, 0x53, 0x13, 0xAF, 0x07, 0x66, 0x26, 0x64, + 0x79, 0xB7, 0x56, 0x54, 0xE6, 0x5F, + /* b */ + 0x50, 0x37, 0xEA, 0x65, 0x41, 0x96, 0xCF, 0xF0, 0xCD, 0x82, 0xB2, 0xC1, + 0x4A, 0x2F, 0xCF, 0x2E, 0x3F, 0xF8, 0x77, 0x52, 0x85, 0xB5, 0x45, 0x72, + 0x2F, 0x03, 0xEA, 0xCD, 0xB7, 0x4B, + /* x */ + 0x28, 0xF9, 0xD0, 0x4E, 0x90, 0x00, 0x69, 0xC8, 0xDC, 0x47, 0xA0, 0x85, + 0x34, 0xFE, 0x76, 0xD2, 0xB9, 0x00, 0xB7, 0xD7, 0xEF, 0x31, 0xF5, 0x70, + 0x9F, 0x20, 0x0C, 0x4C, 0xA2, 0x05, + /* y */ + 0x56, 0x67, 0x33, 0x4C, 0x45, 0xAF, 0xF3, 0xB5, 0xA0, 0x3B, 0xAD, 0x9D, + 0xD7, 0x5E, 0x2C, 0x71, 0xA9, 0x93, 0x62, 0x56, 0x7D, 0x54, 0x53, 0xF7, + 0xFA, 0x6E, 0x22, 0x7E, 0xC8, 0x33, + /* order */ + 0x15, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x3C, 0x6F, 0x28, 0x85, 0x25, 0x9C, 0x31, 0xE3, 0xFC, + 0xDF, 0x15, 0x46, 0x24, 0x52, 0x2D + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 30 * 6]; +} _EC_X9_62_CHAR2_239V3 = { + { + NID_X9_62_characteristic_two_field, 20, 30, 0xA + }, + { + /* seed */ + 0x9E, 0x07, 0x6F, 0x4D, 0x69, 0x6E, 0x67, 0x68, 0x75, 0x61, 0x51, 0x75, + 0xE1, 0x1E, 0x9F, 0xDD, 0x77, 0xF9, 0x20, 0x41, + /* p */ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, + /* a */ + 0x01, 0x23, 0x87, 0x74, 0x66, 0x6A, 0x67, 0x76, 0x6D, 0x66, 0x76, 0xF7, + 0x78, 0xE6, 0x76, 0xB6, 0x69, 0x99, 0x17, 0x66, 0x66, 0xE6, 0x87, 0x66, + 0x6D, 0x87, 0x66, 0xC6, 0x6A, 0x9F, + /* b */ + 0x6A, 0x94, 0x19, 0x77, 0xBA, 0x9F, 0x6A, 0x43, 0x51, 0x99, 0xAC, 0xFC, + 0x51, 0x06, 0x7E, 0xD5, 0x87, 0xF5, 0x19, 0xC5, 0xEC, 0xB5, 0x41, 0xB8, + 0xE4, 0x41, 0x11, 0xDE, 0x1D, 0x40, + /* x */ + 0x70, 0xF6, 0xE9, 0xD0, 0x4D, 0x28, 0x9C, 0x4E, 0x89, 0x91, 0x3C, 0xE3, + 0x53, 0x0B, 0xFD, 0xE9, 0x03, 0x97, 0x7D, 0x42, 0xB1, 0x46, 0xD5, 0x39, + 0xBF, 0x1B, 0xDE, 0x4E, 0x9C, 0x92, + /* y */ + 0x2E, 0x5A, 0x0E, 0xAF, 0x6E, 0x5E, 0x13, 0x05, 0xB9, 0x00, 0x4D, 0xCE, + 0x5C, 0x0E, 0xD7, 0xFE, 0x59, 0xA3, 0x56, 0x08, 0xF3, 0x38, 0x37, 0xC8, + 0x16, 0xD8, 0x0B, 0x79, 0xF4, 0x61, + /* order */ + 0x0C, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xAC, 0x49, 0x12, 0xD2, 0xD9, 0xDF, 0x90, 0x3E, 0xF9, + 0x88, 0x8B, 0x8A, 0x0E, 0x4C, 0xFF + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 35 * 6]; +} _EC_X9_62_CHAR2_272W1 = { + { + NID_X9_62_characteristic_two_field, 0, 35, 0xFF06 + }, + { + /* no seed */ + /* p */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, + /* a */ + 0x00, 0x91, 0xA0, 0x91, 0xF0, 0x3B, 0x5F, 0xBA, 0x4A, 0xB2, 0xCC, 0xF4, + 0x9C, 0x4E, 0xDD, 0x22, 0x0F, 0xB0, 0x28, 0x71, 0x2D, 0x42, 0xBE, 0x75, + 0x2B, 0x2C, 0x40, 0x09, 0x4D, 0xBA, 0xCD, 0xB5, 0x86, 0xFB, 0x20, + /* b */ + 0x00, 0x71, 0x67, 0xEF, 0xC9, 0x2B, 0xB2, 0xE3, 0xCE, 0x7C, 0x8A, 0xAA, + 0xFF, 0x34, 0xE1, 0x2A, 0x9C, 0x55, 0x70, 0x03, 0xD7, 0xC7, 0x3A, 0x6F, + 0xAF, 0x00, 0x3F, 0x99, 0xF6, 0xCC, 0x84, 0x82, 0xE5, 0x40, 0xF7, + /* x */ + 0x00, 0x61, 0x08, 0xBA, 0xBB, 0x2C, 0xEE, 0xBC, 0xF7, 0x87, 0x05, 0x8A, + 0x05, 0x6C, 0xBE, 0x0C, 0xFE, 0x62, 0x2D, 0x77, 0x23, 0xA2, 0x89, 0xE0, + 0x8A, 0x07, 0xAE, 0x13, 0xEF, 0x0D, 0x10, 0xD1, 0x71, 0xDD, 0x8D, + /* y */ + 0x00, 0x10, 0xC7, 0x69, 0x57, 0x16, 0x85, 0x1E, 0xEF, 0x6B, 0xA7, 0xF6, + 0x87, 0x2E, 0x61, 0x42, 0xFB, 0xD2, 0x41, 0xB8, 0x30, 0xFF, 0x5E, 0xFC, + 0xAC, 0xEC, 0xCA, 0xB0, 0x5E, 0x02, 0x00, 0x5D, 0xDE, 0x9D, 0x23, + /* order */ + 0x00, 0x00, 0x01, 0x00, 0xFA, 0xF5, 0x13, 0x54, 0xE0, 0xE3, 0x9E, 0x48, + 0x92, 0xDF, 0x6E, 0x31, 0x9C, 0x72, 0xC8, 0x16, 0x16, 0x03, 0xFA, 0x45, + 0xAA, 0x7B, 0x99, 0x8A, 0x16, 0x7B, 0x8F, 0x1E, 0x62, 0x95, 0x21 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 39 * 6]; +} _EC_X9_62_CHAR2_304W1 = { + { + NID_X9_62_characteristic_two_field, 0, 39, 0xFE2E + }, + { + /* no seed */ + /* p */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x07, + /* a */ + 0x00, 0xFD, 0x0D, 0x69, 0x31, 0x49, 0xA1, 0x18, 0xF6, 0x51, 0xE6, 0xDC, + 0xE6, 0x80, 0x20, 0x85, 0x37, 0x7E, 0x5F, 0x88, 0x2D, 0x1B, 0x51, 0x0B, + 0x44, 0x16, 0x00, 0x74, 0xC1, 0x28, 0x80, 0x78, 0x36, 0x5A, 0x03, 0x96, + 0xC8, 0xE6, 0x81, + /* b */ + 0x00, 0xBD, 0xDB, 0x97, 0xE5, 0x55, 0xA5, 0x0A, 0x90, 0x8E, 0x43, 0xB0, + 0x1C, 0x79, 0x8E, 0xA5, 0xDA, 0xA6, 0x78, 0x8F, 0x1E, 0xA2, 0x79, 0x4E, + 0xFC, 0xF5, 0x71, 0x66, 0xB8, 0xC1, 0x40, 0x39, 0x60, 0x1E, 0x55, 0x82, + 0x73, 0x40, 0xBE, + /* x */ + 0x00, 0x19, 0x7B, 0x07, 0x84, 0x5E, 0x9B, 0xE2, 0xD9, 0x6A, 0xDB, 0x0F, + 0x5F, 0x3C, 0x7F, 0x2C, 0xFF, 0xBD, 0x7A, 0x3E, 0xB8, 0xB6, 0xFE, 0xC3, + 0x5C, 0x7F, 0xD6, 0x7F, 0x26, 0xDD, 0xF6, 0x28, 0x5A, 0x64, 0x4F, 0x74, + 0x0A, 0x26, 0x14, + /* y */ + 0x00, 0xE1, 0x9F, 0xBE, 0xB7, 0x6E, 0x0D, 0xA1, 0x71, 0x51, 0x7E, 0xCF, + 0x40, 0x1B, 0x50, 0x28, 0x9B, 0xF0, 0x14, 0x10, 0x32, 0x88, 0x52, 0x7A, + 0x9B, 0x41, 0x6A, 0x10, 0x5E, 0x80, 0x26, 0x0B, 0x54, 0x9F, 0xDC, 0x1B, + 0x92, 0xC0, 0x3B, + /* order */ + 0x00, 0x00, 0x01, 0x01, 0xD5, 0x56, 0x57, 0x2A, 0xAB, 0xAC, 0x80, 0x01, + 0x01, 0xD5, 0x56, 0x57, 0x2A, 0xAB, 0xAC, 0x80, 0x01, 0x02, 0x2D, 0x5C, + 0x91, 0xDD, 0x17, 0x3F, 0x8F, 0xB5, 0x61, 0xDA, 0x68, 0x99, 0x16, 0x44, + 0x43, 0x05, 0x1D + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 45 * 6]; +} _EC_X9_62_CHAR2_359V1 = { + { + NID_X9_62_characteristic_two_field, 20, 45, 0x4C + }, + { + /* seed */ + 0x2B, 0x35, 0x49, 0x20, 0xB7, 0x24, 0xD6, 0x96, 0xE6, 0x76, 0x87, 0x56, + 0x15, 0x17, 0x58, 0x5B, 0xA1, 0x33, 0x2D, 0xC6, + /* p */ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* a */ + 0x56, 0x67, 0x67, 0x6A, 0x65, 0x4B, 0x20, 0x75, 0x4F, 0x35, 0x6E, 0xA9, + 0x20, 0x17, 0xD9, 0x46, 0x56, 0x7C, 0x46, 0x67, 0x55, 0x56, 0xF1, 0x95, + 0x56, 0xA0, 0x46, 0x16, 0xB5, 0x67, 0xD2, 0x23, 0xA5, 0xE0, 0x56, 0x56, + 0xFB, 0x54, 0x90, 0x16, 0xA9, 0x66, 0x56, 0xA5, 0x57, + /* b */ + 0x24, 0x72, 0xE2, 0xD0, 0x19, 0x7C, 0x49, 0x36, 0x3F, 0x1F, 0xE7, 0xF5, + 0xB6, 0xDB, 0x07, 0x5D, 0x52, 0xB6, 0x94, 0x7D, 0x13, 0x5D, 0x8C, 0xA4, + 0x45, 0x80, 0x5D, 0x39, 0xBC, 0x34, 0x56, 0x26, 0x08, 0x96, 0x87, 0x74, + 0x2B, 0x63, 0x29, 0xE7, 0x06, 0x80, 0x23, 0x19, 0x88, + /* x */ + 0x3C, 0x25, 0x8E, 0xF3, 0x04, 0x77, 0x67, 0xE7, 0xED, 0xE0, 0xF1, 0xFD, + 0xAA, 0x79, 0xDA, 0xEE, 0x38, 0x41, 0x36, 0x6A, 0x13, 0x2E, 0x16, 0x3A, + 0xCE, 0xD4, 0xED, 0x24, 0x01, 0xDF, 0x9C, 0x6B, 0xDC, 0xDE, 0x98, 0xE8, + 0xE7, 0x07, 0xC0, 0x7A, 0x22, 0x39, 0xB1, 0xB0, 0x97, + /* y */ + 0x53, 0xD7, 0xE0, 0x85, 0x29, 0x54, 0x70, 0x48, 0x12, 0x1E, 0x9C, 0x95, + 0xF3, 0x79, 0x1D, 0xD8, 0x04, 0x96, 0x39, 0x48, 0xF3, 0x4F, 0xAE, 0x7B, + 0xF4, 0x4E, 0xA8, 0x23, 0x65, 0xDC, 0x78, 0x68, 0xFE, 0x57, 0xE4, 0xAE, + 0x2D, 0xE2, 0x11, 0x30, 0x5A, 0x40, 0x71, 0x04, 0xBD, + /* order */ + 0x01, 0xAF, 0x28, 0x6B, 0xCA, 0x1A, 0xF2, 0x86, 0xBC, 0xA1, 0xAF, 0x28, + 0x6B, 0xCA, 0x1A, 0xF2, 0x86, 0xBC, 0xA1, 0xAF, 0x28, 0x6B, 0xC9, 0xFB, + 0x8F, 0x6B, 0x85, 0xC5, 0x56, 0x89, 0x2C, 0x20, 0xA7, 0xEB, 0x96, 0x4F, + 0xE7, 0x71, 0x9E, 0x74, 0xF4, 0x90, 0x75, 0x8D, 0x3B + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 47 * 6]; +} _EC_X9_62_CHAR2_368W1 = { + { + NID_X9_62_characteristic_two_field, 0, 47, 0xFF70 + }, + { + /* no seed */ + /* p */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + /* a */ + 0x00, 0xE0, 0xD2, 0xEE, 0x25, 0x09, 0x52, 0x06, 0xF5, 0xE2, 0xA4, 0xF9, + 0xED, 0x22, 0x9F, 0x1F, 0x25, 0x6E, 0x79, 0xA0, 0xE2, 0xB4, 0x55, 0x97, + 0x0D, 0x8D, 0x0D, 0x86, 0x5B, 0xD9, 0x47, 0x78, 0xC5, 0x76, 0xD6, 0x2F, + 0x0A, 0xB7, 0x51, 0x9C, 0xCD, 0x2A, 0x1A, 0x90, 0x6A, 0xE3, 0x0D, + /* b */ + 0x00, 0xFC, 0x12, 0x17, 0xD4, 0x32, 0x0A, 0x90, 0x45, 0x2C, 0x76, 0x0A, + 0x58, 0xED, 0xCD, 0x30, 0xC8, 0xDD, 0x06, 0x9B, 0x3C, 0x34, 0x45, 0x38, + 0x37, 0xA3, 0x4E, 0xD5, 0x0C, 0xB5, 0x49, 0x17, 0xE1, 0xC2, 0x11, 0x2D, + 0x84, 0xD1, 0x64, 0xF4, 0x44, 0xF8, 0xF7, 0x47, 0x86, 0x04, 0x6A, + /* x */ + 0x00, 0x10, 0x85, 0xE2, 0x75, 0x53, 0x81, 0xDC, 0xCC, 0xE3, 0xC1, 0x55, + 0x7A, 0xFA, 0x10, 0xC2, 0xF0, 0xC0, 0xC2, 0x82, 0x56, 0x46, 0xC5, 0xB3, + 0x4A, 0x39, 0x4C, 0xBC, 0xFA, 0x8B, 0xC1, 0x6B, 0x22, 0xE7, 0xE7, 0x89, + 0xE9, 0x27, 0xBE, 0x21, 0x6F, 0x02, 0xE1, 0xFB, 0x13, 0x6A, 0x5F, + /* y */ + 0x00, 0x7B, 0x3E, 0xB1, 0xBD, 0xDC, 0xBA, 0x62, 0xD5, 0xD8, 0xB2, 0x05, + 0x9B, 0x52, 0x57, 0x97, 0xFC, 0x73, 0x82, 0x2C, 0x59, 0x05, 0x9C, 0x62, + 0x3A, 0x45, 0xFF, 0x38, 0x43, 0xCE, 0xE8, 0xF8, 0x7C, 0xD1, 0x85, 0x5A, + 0xDA, 0xA8, 0x1E, 0x2A, 0x07, 0x50, 0xB8, 0x0F, 0xDA, 0x23, 0x10, + /* order */ + 0x00, 0x00, 0x01, 0x00, 0x90, 0x51, 0x2D, 0xA9, 0xAF, 0x72, 0xB0, 0x83, + 0x49, 0xD9, 0x8A, 0x5D, 0xD4, 0xC7, 0xB0, 0x53, 0x2E, 0xCA, 0x51, 0xCE, + 0x03, 0xE2, 0xD1, 0x0F, 0x3B, 0x7A, 0xC5, 0x79, 0xBD, 0x87, 0xE9, 0x09, + 0xAE, 0x40, 0xA6, 0xF1, 0x31, 0xE9, 0xCF, 0xCE, 0x5B, 0xD9, 0x67 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 54 * 6]; +} _EC_X9_62_CHAR2_431R1 = { + { + NID_X9_62_characteristic_two_field, 0, 54, 0x2760 + }, + { + /* no seed */ + /* p */ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* a */ + 0x1A, 0x82, 0x7E, 0xF0, 0x0D, 0xD6, 0xFC, 0x0E, 0x23, 0x4C, 0xAF, 0x04, + 0x6C, 0x6A, 0x5D, 0x8A, 0x85, 0x39, 0x5B, 0x23, 0x6C, 0xC4, 0xAD, 0x2C, + 0xF3, 0x2A, 0x0C, 0xAD, 0xBD, 0xC9, 0xDD, 0xF6, 0x20, 0xB0, 0xEB, 0x99, + 0x06, 0xD0, 0x95, 0x7F, 0x6C, 0x6F, 0xEA, 0xCD, 0x61, 0x54, 0x68, 0xDF, + 0x10, 0x4D, 0xE2, 0x96, 0xCD, 0x8F, + /* b */ + 0x10, 0xD9, 0xB4, 0xA3, 0xD9, 0x04, 0x7D, 0x8B, 0x15, 0x43, 0x59, 0xAB, + 0xFB, 0x1B, 0x7F, 0x54, 0x85, 0xB0, 0x4C, 0xEB, 0x86, 0x82, 0x37, 0xDD, + 0xC9, 0xDE, 0xDA, 0x98, 0x2A, 0x67, 0x9A, 0x5A, 0x91, 0x9B, 0x62, 0x6D, + 0x4E, 0x50, 0xA8, 0xDD, 0x73, 0x1B, 0x10, 0x7A, 0x99, 0x62, 0x38, 0x1F, + 0xB5, 0xD8, 0x07, 0xBF, 0x26, 0x18, + /* x */ + 0x12, 0x0F, 0xC0, 0x5D, 0x3C, 0x67, 0xA9, 0x9D, 0xE1, 0x61, 0xD2, 0xF4, + 0x09, 0x26, 0x22, 0xFE, 0xCA, 0x70, 0x1B, 0xE4, 0xF5, 0x0F, 0x47, 0x58, + 0x71, 0x4E, 0x8A, 0x87, 0xBB, 0xF2, 0xA6, 0x58, 0xEF, 0x8C, 0x21, 0xE7, + 0xC5, 0xEF, 0xE9, 0x65, 0x36, 0x1F, 0x6C, 0x29, 0x99, 0xC0, 0xC2, 0x47, + 0xB0, 0xDB, 0xD7, 0x0C, 0xE6, 0xB7, + /* y */ + 0x20, 0xD0, 0xAF, 0x89, 0x03, 0xA9, 0x6F, 0x8D, 0x5F, 0xA2, 0xC2, 0x55, + 0x74, 0x5D, 0x3C, 0x45, 0x1B, 0x30, 0x2C, 0x93, 0x46, 0xD9, 0xB7, 0xE4, + 0x85, 0xE7, 0xBC, 0xE4, 0x1F, 0x6B, 0x59, 0x1F, 0x3E, 0x8F, 0x6A, 0xDD, + 0xCB, 0xB0, 0xBC, 0x4C, 0x2F, 0x94, 0x7A, 0x7D, 0xE1, 0xA8, 0x9B, 0x62, + 0x5D, 0x6A, 0x59, 0x8B, 0x37, 0x60, + /* order */ + 0x00, 0x03, 0x40, 0x34, 0x03, 0x40, 0x34, 0x03, 0x40, 0x34, 0x03, 0x40, + 0x34, 0x03, 0x40, 0x34, 0x03, 0x40, 0x34, 0x03, 0x40, 0x34, 0x03, 0x40, + 0x34, 0x03, 0x40, 0x34, 0x03, 0x23, 0xC3, 0x13, 0xFA, 0xB5, 0x05, 0x89, + 0x70, 0x3B, 0x5E, 0xC6, 0x8D, 0x35, 0x87, 0xFE, 0xC6, 0x0D, 0x16, 0x1C, + 0xC1, 0x49, 0xC1, 0xAD, 0x4A, 0x91 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 15 * 6]; +} _EC_WTLS_1 = { + { + NID_X9_62_characteristic_two_field, 0, 15, 2 + }, + { + /* no seed */ + /* p */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x01, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, + /* x */ + 0x01, 0x66, 0x79, 0x79, 0xA4, 0x0B, 0xA4, 0x97, 0xE5, 0xD5, 0xC2, 0x70, + 0x78, 0x06, 0x17, + /* y */ + 0x00, 0xF4, 0x4B, 0x4A, 0xF1, 0xEC, 0xC2, 0x63, 0x0E, 0x08, 0x78, 0x5C, + 0xEB, 0xCC, 0x15, + /* order */ + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xBF, 0x91, 0xAF, + 0x6D, 0xEA, 0x73 + } +}; + +/* IPSec curves */ +/* + * NOTE: The of curves over a extension field of non prime degree is not + * recommended (Weil-descent). As the group order is not a prime this curve + * is not suitable for ECDSA. + */ +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 20 * 6]; +} _EC_IPSEC_155_ID3 = { + { + NID_X9_62_characteristic_two_field, 0, 20, 3 + }, + { + /* no seed */ + /* p */ + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x33, 0x8f, + /* x */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, + /* y */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc8, + /* order */ + 0x02, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xC7, 0xF3, + 0xC7, 0x88, 0x1B, 0xD0, 0x86, 0x8F, 0xA8, 0x6C + } +}; + +/* + * NOTE: The of curves over a extension field of non prime degree is not + * recommended (Weil-descent). As the group order is not a prime this curve + * is not suitable for ECDSA. + */ +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 24 * 6]; +} _EC_IPSEC_185_ID4 = { + { + NID_X9_62_characteristic_two_field, 0, 24, 2 + }, + { + /* no seed */ + /* p */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0xe9, + /* x */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + /* y */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, + /* order */ + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xED, 0xF9, 0x7C, 0x44, 0xDB, 0x9F, 0x24, 0x20, 0xBA, 0xFC, 0xA7, 0x5E + } +}; + +#endif + +/* + * These curves were added by Annie Yousar. + * For the definition of RFC 5639 curves see + * http://www.ietf.org/rfc/rfc5639.txt These curves are generated verifiable + * at random, nevertheless the seed is omitted as parameter because the + * generation mechanism is different from those defined in ANSI X9.62. + */ + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 20 * 6]; +} _EC_brainpoolP160r1 = { + { + NID_X9_62_prime_field, 0, 20, 1 + }, + { + /* no seed */ + /* p */ + 0xE9, 0x5E, 0x4A, 0x5F, 0x73, 0x70, 0x59, 0xDC, 0x60, 0xDF, 0xC7, 0xAD, + 0x95, 0xB3, 0xD8, 0x13, 0x95, 0x15, 0x62, 0x0F, + /* a */ + 0x34, 0x0E, 0x7B, 0xE2, 0xA2, 0x80, 0xEB, 0x74, 0xE2, 0xBE, 0x61, 0xBA, + 0xDA, 0x74, 0x5D, 0x97, 0xE8, 0xF7, 0xC3, 0x00, + /* b */ + 0x1E, 0x58, 0x9A, 0x85, 0x95, 0x42, 0x34, 0x12, 0x13, 0x4F, 0xAA, 0x2D, + 0xBD, 0xEC, 0x95, 0xC8, 0xD8, 0x67, 0x5E, 0x58, + /* x */ + 0xBE, 0xD5, 0xAF, 0x16, 0xEA, 0x3F, 0x6A, 0x4F, 0x62, 0x93, 0x8C, 0x46, + 0x31, 0xEB, 0x5A, 0xF7, 0xBD, 0xBC, 0xDB, 0xC3, + /* y */ + 0x16, 0x67, 0xCB, 0x47, 0x7A, 0x1A, 0x8E, 0xC3, 0x38, 0xF9, 0x47, 0x41, + 0x66, 0x9C, 0x97, 0x63, 0x16, 0xDA, 0x63, 0x21, + /* order */ + 0xE9, 0x5E, 0x4A, 0x5F, 0x73, 0x70, 0x59, 0xDC, 0x60, 0xDF, 0x59, 0x91, + 0xD4, 0x50, 0x29, 0x40, 0x9E, 0x60, 0xFC, 0x09 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 20 * 6]; +} _EC_brainpoolP160t1 = { + { + NID_X9_62_prime_field, 0, 20, 1 + }, + { + /* no seed */ + /* p */ + 0xE9, 0x5E, 0x4A, 0x5F, 0x73, 0x70, 0x59, 0xDC, 0x60, 0xDF, 0xC7, 0xAD, + 0x95, 0xB3, 0xD8, 0x13, 0x95, 0x15, 0x62, 0x0F, + /* a */ + 0xE9, 0x5E, 0x4A, 0x5F, 0x73, 0x70, 0x59, 0xDC, 0x60, 0xDF, 0xC7, 0xAD, + 0x95, 0xB3, 0xD8, 0x13, 0x95, 0x15, 0x62, 0x0C, + /* b */ + 0x7A, 0x55, 0x6B, 0x6D, 0xAE, 0x53, 0x5B, 0x7B, 0x51, 0xED, 0x2C, 0x4D, + 0x7D, 0xAA, 0x7A, 0x0B, 0x5C, 0x55, 0xF3, 0x80, + /* x */ + 0xB1, 0x99, 0xB1, 0x3B, 0x9B, 0x34, 0xEF, 0xC1, 0x39, 0x7E, 0x64, 0xBA, + 0xEB, 0x05, 0xAC, 0xC2, 0x65, 0xFF, 0x23, 0x78, + /* y */ + 0xAD, 0xD6, 0x71, 0x8B, 0x7C, 0x7C, 0x19, 0x61, 0xF0, 0x99, 0x1B, 0x84, + 0x24, 0x43, 0x77, 0x21, 0x52, 0xC9, 0xE0, 0xAD, + /* order */ + 0xE9, 0x5E, 0x4A, 0x5F, 0x73, 0x70, 0x59, 0xDC, 0x60, 0xDF, 0x59, 0x91, + 0xD4, 0x50, 0x29, 0x40, 0x9E, 0x60, 0xFC, 0x09 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 24 * 6]; +} _EC_brainpoolP192r1 = { + { + NID_X9_62_prime_field, 0, 24, 1 + }, + { + /* no seed */ + /* p */ + 0xC3, 0x02, 0xF4, 0x1D, 0x93, 0x2A, 0x36, 0xCD, 0xA7, 0xA3, 0x46, 0x30, + 0x93, 0xD1, 0x8D, 0xB7, 0x8F, 0xCE, 0x47, 0x6D, 0xE1, 0xA8, 0x62, 0x97, + /* a */ + 0x6A, 0x91, 0x17, 0x40, 0x76, 0xB1, 0xE0, 0xE1, 0x9C, 0x39, 0xC0, 0x31, + 0xFE, 0x86, 0x85, 0xC1, 0xCA, 0xE0, 0x40, 0xE5, 0xC6, 0x9A, 0x28, 0xEF, + /* b */ + 0x46, 0x9A, 0x28, 0xEF, 0x7C, 0x28, 0xCC, 0xA3, 0xDC, 0x72, 0x1D, 0x04, + 0x4F, 0x44, 0x96, 0xBC, 0xCA, 0x7E, 0xF4, 0x14, 0x6F, 0xBF, 0x25, 0xC9, + /* x */ + 0xC0, 0xA0, 0x64, 0x7E, 0xAA, 0xB6, 0xA4, 0x87, 0x53, 0xB0, 0x33, 0xC5, + 0x6C, 0xB0, 0xF0, 0x90, 0x0A, 0x2F, 0x5C, 0x48, 0x53, 0x37, 0x5F, 0xD6, + /* y */ + 0x14, 0xB6, 0x90, 0x86, 0x6A, 0xBD, 0x5B, 0xB8, 0x8B, 0x5F, 0x48, 0x28, + 0xC1, 0x49, 0x00, 0x02, 0xE6, 0x77, 0x3F, 0xA2, 0xFA, 0x29, 0x9B, 0x8F, + /* order */ + 0xC3, 0x02, 0xF4, 0x1D, 0x93, 0x2A, 0x36, 0xCD, 0xA7, 0xA3, 0x46, 0x2F, + 0x9E, 0x9E, 0x91, 0x6B, 0x5B, 0xE8, 0xF1, 0x02, 0x9A, 0xC4, 0xAC, 0xC1 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 24 * 6]; +} _EC_brainpoolP192t1 = { + { + NID_X9_62_prime_field, 0, 24, 1 + }, + { + /* no seed */ + /* p */ + 0xC3, 0x02, 0xF4, 0x1D, 0x93, 0x2A, 0x36, 0xCD, 0xA7, 0xA3, 0x46, 0x30, + 0x93, 0xD1, 0x8D, 0xB7, 0x8F, 0xCE, 0x47, 0x6D, 0xE1, 0xA8, 0x62, 0x97, + /* a */ + 0xC3, 0x02, 0xF4, 0x1D, 0x93, 0x2A, 0x36, 0xCD, 0xA7, 0xA3, 0x46, 0x30, + 0x93, 0xD1, 0x8D, 0xB7, 0x8F, 0xCE, 0x47, 0x6D, 0xE1, 0xA8, 0x62, 0x94, + /* b */ + 0x13, 0xD5, 0x6F, 0xFA, 0xEC, 0x78, 0x68, 0x1E, 0x68, 0xF9, 0xDE, 0xB4, + 0x3B, 0x35, 0xBE, 0xC2, 0xFB, 0x68, 0x54, 0x2E, 0x27, 0x89, 0x7B, 0x79, + /* x */ + 0x3A, 0xE9, 0xE5, 0x8C, 0x82, 0xF6, 0x3C, 0x30, 0x28, 0x2E, 0x1F, 0xE7, + 0xBB, 0xF4, 0x3F, 0xA7, 0x2C, 0x44, 0x6A, 0xF6, 0xF4, 0x61, 0x81, 0x29, + /* y */ + 0x09, 0x7E, 0x2C, 0x56, 0x67, 0xC2, 0x22, 0x3A, 0x90, 0x2A, 0xB5, 0xCA, + 0x44, 0x9D, 0x00, 0x84, 0xB7, 0xE5, 0xB3, 0xDE, 0x7C, 0xCC, 0x01, 0xC9, + /* order */ + 0xC3, 0x02, 0xF4, 0x1D, 0x93, 0x2A, 0x36, 0xCD, 0xA7, 0xA3, 0x46, 0x2F, + 0x9E, 0x9E, 0x91, 0x6B, 0x5B, 0xE8, 0xF1, 0x02, 0x9A, 0xC4, 0xAC, 0xC1 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 28 * 6]; +} _EC_brainpoolP224r1 = { + { + NID_X9_62_prime_field, 0, 28, 1 + }, + { + /* no seed */ + /* p */ + 0xD7, 0xC1, 0x34, 0xAA, 0x26, 0x43, 0x66, 0x86, 0x2A, 0x18, 0x30, 0x25, + 0x75, 0xD1, 0xD7, 0x87, 0xB0, 0x9F, 0x07, 0x57, 0x97, 0xDA, 0x89, 0xF5, + 0x7E, 0xC8, 0xC0, 0xFF, + /* a */ + 0x68, 0xA5, 0xE6, 0x2C, 0xA9, 0xCE, 0x6C, 0x1C, 0x29, 0x98, 0x03, 0xA6, + 0xC1, 0x53, 0x0B, 0x51, 0x4E, 0x18, 0x2A, 0xD8, 0xB0, 0x04, 0x2A, 0x59, + 0xCA, 0xD2, 0x9F, 0x43, + /* b */ + 0x25, 0x80, 0xF6, 0x3C, 0xCF, 0xE4, 0x41, 0x38, 0x87, 0x07, 0x13, 0xB1, + 0xA9, 0x23, 0x69, 0xE3, 0x3E, 0x21, 0x35, 0xD2, 0x66, 0xDB, 0xB3, 0x72, + 0x38, 0x6C, 0x40, 0x0B, + /* x */ + 0x0D, 0x90, 0x29, 0xAD, 0x2C, 0x7E, 0x5C, 0xF4, 0x34, 0x08, 0x23, 0xB2, + 0xA8, 0x7D, 0xC6, 0x8C, 0x9E, 0x4C, 0xE3, 0x17, 0x4C, 0x1E, 0x6E, 0xFD, + 0xEE, 0x12, 0xC0, 0x7D, + /* y */ + 0x58, 0xAA, 0x56, 0xF7, 0x72, 0xC0, 0x72, 0x6F, 0x24, 0xC6, 0xB8, 0x9E, + 0x4E, 0xCD, 0xAC, 0x24, 0x35, 0x4B, 0x9E, 0x99, 0xCA, 0xA3, 0xF6, 0xD3, + 0x76, 0x14, 0x02, 0xCD, + /* order */ + 0xD7, 0xC1, 0x34, 0xAA, 0x26, 0x43, 0x66, 0x86, 0x2A, 0x18, 0x30, 0x25, + 0x75, 0xD0, 0xFB, 0x98, 0xD1, 0x16, 0xBC, 0x4B, 0x6D, 0xDE, 0xBC, 0xA3, + 0xA5, 0xA7, 0x93, 0x9F + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 28 * 6]; +} _EC_brainpoolP224t1 = { + { + NID_X9_62_prime_field, 0, 28, 1 + }, + { + /* no seed */ + /* p */ + 0xD7, 0xC1, 0x34, 0xAA, 0x26, 0x43, 0x66, 0x86, 0x2A, 0x18, 0x30, 0x25, + 0x75, 0xD1, 0xD7, 0x87, 0xB0, 0x9F, 0x07, 0x57, 0x97, 0xDA, 0x89, 0xF5, + 0x7E, 0xC8, 0xC0, 0xFF, + /* a */ + 0xD7, 0xC1, 0x34, 0xAA, 0x26, 0x43, 0x66, 0x86, 0x2A, 0x18, 0x30, 0x25, + 0x75, 0xD1, 0xD7, 0x87, 0xB0, 0x9F, 0x07, 0x57, 0x97, 0xDA, 0x89, 0xF5, + 0x7E, 0xC8, 0xC0, 0xFC, + /* b */ + 0x4B, 0x33, 0x7D, 0x93, 0x41, 0x04, 0xCD, 0x7B, 0xEF, 0x27, 0x1B, 0xF6, + 0x0C, 0xED, 0x1E, 0xD2, 0x0D, 0xA1, 0x4C, 0x08, 0xB3, 0xBB, 0x64, 0xF1, + 0x8A, 0x60, 0x88, 0x8D, + /* x */ + 0x6A, 0xB1, 0xE3, 0x44, 0xCE, 0x25, 0xFF, 0x38, 0x96, 0x42, 0x4E, 0x7F, + 0xFE, 0x14, 0x76, 0x2E, 0xCB, 0x49, 0xF8, 0x92, 0x8A, 0xC0, 0xC7, 0x60, + 0x29, 0xB4, 0xD5, 0x80, + /* y */ + 0x03, 0x74, 0xE9, 0xF5, 0x14, 0x3E, 0x56, 0x8C, 0xD2, 0x3F, 0x3F, 0x4D, + 0x7C, 0x0D, 0x4B, 0x1E, 0x41, 0xC8, 0xCC, 0x0D, 0x1C, 0x6A, 0xBD, 0x5F, + 0x1A, 0x46, 0xDB, 0x4C, + /* order */ + 0xD7, 0xC1, 0x34, 0xAA, 0x26, 0x43, 0x66, 0x86, 0x2A, 0x18, 0x30, 0x25, + 0x75, 0xD0, 0xFB, 0x98, 0xD1, 0x16, 0xBC, 0x4B, 0x6D, 0xDE, 0xBC, 0xA3, + 0xA5, 0xA7, 0x93, 0x9F + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 32 * 6]; +} _EC_brainpoolP256r1 = { + { + NID_X9_62_prime_field, 0, 32, 1 + }, + { + /* no seed */ + /* p */ + 0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC, 0x3E, 0x66, 0x0A, 0x90, + 0x9D, 0x83, 0x8D, 0x72, 0x6E, 0x3B, 0xF6, 0x23, 0xD5, 0x26, 0x20, 0x28, + 0x20, 0x13, 0x48, 0x1D, 0x1F, 0x6E, 0x53, 0x77, + /* a */ + 0x7D, 0x5A, 0x09, 0x75, 0xFC, 0x2C, 0x30, 0x57, 0xEE, 0xF6, 0x75, 0x30, + 0x41, 0x7A, 0xFF, 0xE7, 0xFB, 0x80, 0x55, 0xC1, 0x26, 0xDC, 0x5C, 0x6C, + 0xE9, 0x4A, 0x4B, 0x44, 0xF3, 0x30, 0xB5, 0xD9, + /* b */ + 0x26, 0xDC, 0x5C, 0x6C, 0xE9, 0x4A, 0x4B, 0x44, 0xF3, 0x30, 0xB5, 0xD9, + 0xBB, 0xD7, 0x7C, 0xBF, 0x95, 0x84, 0x16, 0x29, 0x5C, 0xF7, 0xE1, 0xCE, + 0x6B, 0xCC, 0xDC, 0x18, 0xFF, 0x8C, 0x07, 0xB6, + /* x */ + 0x8B, 0xD2, 0xAE, 0xB9, 0xCB, 0x7E, 0x57, 0xCB, 0x2C, 0x4B, 0x48, 0x2F, + 0xFC, 0x81, 0xB7, 0xAF, 0xB9, 0xDE, 0x27, 0xE1, 0xE3, 0xBD, 0x23, 0xC2, + 0x3A, 0x44, 0x53, 0xBD, 0x9A, 0xCE, 0x32, 0x62, + /* y */ + 0x54, 0x7E, 0xF8, 0x35, 0xC3, 0xDA, 0xC4, 0xFD, 0x97, 0xF8, 0x46, 0x1A, + 0x14, 0x61, 0x1D, 0xC9, 0xC2, 0x77, 0x45, 0x13, 0x2D, 0xED, 0x8E, 0x54, + 0x5C, 0x1D, 0x54, 0xC7, 0x2F, 0x04, 0x69, 0x97, + /* order */ + 0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC, 0x3E, 0x66, 0x0A, 0x90, + 0x9D, 0x83, 0x8D, 0x71, 0x8C, 0x39, 0x7A, 0xA3, 0xB5, 0x61, 0xA6, 0xF7, + 0x90, 0x1E, 0x0E, 0x82, 0x97, 0x48, 0x56, 0xA7 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 32 * 6]; +} _EC_brainpoolP256t1 = { + { + NID_X9_62_prime_field, 0, 32, 1 + }, + { + /* no seed */ + /* p */ + 0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC, 0x3E, 0x66, 0x0A, 0x90, + 0x9D, 0x83, 0x8D, 0x72, 0x6E, 0x3B, 0xF6, 0x23, 0xD5, 0x26, 0x20, 0x28, + 0x20, 0x13, 0x48, 0x1D, 0x1F, 0x6E, 0x53, 0x77, + /* a */ + 0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC, 0x3E, 0x66, 0x0A, 0x90, + 0x9D, 0x83, 0x8D, 0x72, 0x6E, 0x3B, 0xF6, 0x23, 0xD5, 0x26, 0x20, 0x28, + 0x20, 0x13, 0x48, 0x1D, 0x1F, 0x6E, 0x53, 0x74, + /* b */ + 0x66, 0x2C, 0x61, 0xC4, 0x30, 0xD8, 0x4E, 0xA4, 0xFE, 0x66, 0xA7, 0x73, + 0x3D, 0x0B, 0x76, 0xB7, 0xBF, 0x93, 0xEB, 0xC4, 0xAF, 0x2F, 0x49, 0x25, + 0x6A, 0xE5, 0x81, 0x01, 0xFE, 0xE9, 0x2B, 0x04, + /* x */ + 0xA3, 0xE8, 0xEB, 0x3C, 0xC1, 0xCF, 0xE7, 0xB7, 0x73, 0x22, 0x13, 0xB2, + 0x3A, 0x65, 0x61, 0x49, 0xAF, 0xA1, 0x42, 0xC4, 0x7A, 0xAF, 0xBC, 0x2B, + 0x79, 0xA1, 0x91, 0x56, 0x2E, 0x13, 0x05, 0xF4, + /* y */ + 0x2D, 0x99, 0x6C, 0x82, 0x34, 0x39, 0xC5, 0x6D, 0x7F, 0x7B, 0x22, 0xE1, + 0x46, 0x44, 0x41, 0x7E, 0x69, 0xBC, 0xB6, 0xDE, 0x39, 0xD0, 0x27, 0x00, + 0x1D, 0xAB, 0xE8, 0xF3, 0x5B, 0x25, 0xC9, 0xBE, + /* order */ + 0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC, 0x3E, 0x66, 0x0A, 0x90, + 0x9D, 0x83, 0x8D, 0x71, 0x8C, 0x39, 0x7A, 0xA3, 0xB5, 0x61, 0xA6, 0xF7, + 0x90, 0x1E, 0x0E, 0x82, 0x97, 0x48, 0x56, 0xA7 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 40 * 6]; +} _EC_brainpoolP320r1 = { + { + NID_X9_62_prime_field, 0, 40, 1 + }, + { + /* no seed */ + /* p */ + 0xD3, 0x5E, 0x47, 0x20, 0x36, 0xBC, 0x4F, 0xB7, 0xE1, 0x3C, 0x78, 0x5E, + 0xD2, 0x01, 0xE0, 0x65, 0xF9, 0x8F, 0xCF, 0xA6, 0xF6, 0xF4, 0x0D, 0xEF, + 0x4F, 0x92, 0xB9, 0xEC, 0x78, 0x93, 0xEC, 0x28, 0xFC, 0xD4, 0x12, 0xB1, + 0xF1, 0xB3, 0x2E, 0x27, + /* a */ + 0x3E, 0xE3, 0x0B, 0x56, 0x8F, 0xBA, 0xB0, 0xF8, 0x83, 0xCC, 0xEB, 0xD4, + 0x6D, 0x3F, 0x3B, 0xB8, 0xA2, 0xA7, 0x35, 0x13, 0xF5, 0xEB, 0x79, 0xDA, + 0x66, 0x19, 0x0E, 0xB0, 0x85, 0xFF, 0xA9, 0xF4, 0x92, 0xF3, 0x75, 0xA9, + 0x7D, 0x86, 0x0E, 0xB4, + /* b */ + 0x52, 0x08, 0x83, 0x94, 0x9D, 0xFD, 0xBC, 0x42, 0xD3, 0xAD, 0x19, 0x86, + 0x40, 0x68, 0x8A, 0x6F, 0xE1, 0x3F, 0x41, 0x34, 0x95, 0x54, 0xB4, 0x9A, + 0xCC, 0x31, 0xDC, 0xCD, 0x88, 0x45, 0x39, 0x81, 0x6F, 0x5E, 0xB4, 0xAC, + 0x8F, 0xB1, 0xF1, 0xA6, + /* x */ + 0x43, 0xBD, 0x7E, 0x9A, 0xFB, 0x53, 0xD8, 0xB8, 0x52, 0x89, 0xBC, 0xC4, + 0x8E, 0xE5, 0xBF, 0xE6, 0xF2, 0x01, 0x37, 0xD1, 0x0A, 0x08, 0x7E, 0xB6, + 0xE7, 0x87, 0x1E, 0x2A, 0x10, 0xA5, 0x99, 0xC7, 0x10, 0xAF, 0x8D, 0x0D, + 0x39, 0xE2, 0x06, 0x11, + /* y */ + 0x14, 0xFD, 0xD0, 0x55, 0x45, 0xEC, 0x1C, 0xC8, 0xAB, 0x40, 0x93, 0x24, + 0x7F, 0x77, 0x27, 0x5E, 0x07, 0x43, 0xFF, 0xED, 0x11, 0x71, 0x82, 0xEA, + 0xA9, 0xC7, 0x78, 0x77, 0xAA, 0xAC, 0x6A, 0xC7, 0xD3, 0x52, 0x45, 0xD1, + 0x69, 0x2E, 0x8E, 0xE1, + /* order */ + 0xD3, 0x5E, 0x47, 0x20, 0x36, 0xBC, 0x4F, 0xB7, 0xE1, 0x3C, 0x78, 0x5E, + 0xD2, 0x01, 0xE0, 0x65, 0xF9, 0x8F, 0xCF, 0xA5, 0xB6, 0x8F, 0x12, 0xA3, + 0x2D, 0x48, 0x2E, 0xC7, 0xEE, 0x86, 0x58, 0xE9, 0x86, 0x91, 0x55, 0x5B, + 0x44, 0xC5, 0x93, 0x11 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 40 * 6]; +} _EC_brainpoolP320t1 = { + { + NID_X9_62_prime_field, 0, 40, 1 + }, + { + /* no seed */ + /* p */ + 0xD3, 0x5E, 0x47, 0x20, 0x36, 0xBC, 0x4F, 0xB7, 0xE1, 0x3C, 0x78, 0x5E, + 0xD2, 0x01, 0xE0, 0x65, 0xF9, 0x8F, 0xCF, 0xA6, 0xF6, 0xF4, 0x0D, 0xEF, + 0x4F, 0x92, 0xB9, 0xEC, 0x78, 0x93, 0xEC, 0x28, 0xFC, 0xD4, 0x12, 0xB1, + 0xF1, 0xB3, 0x2E, 0x27, + /* a */ + 0xD3, 0x5E, 0x47, 0x20, 0x36, 0xBC, 0x4F, 0xB7, 0xE1, 0x3C, 0x78, 0x5E, + 0xD2, 0x01, 0xE0, 0x65, 0xF9, 0x8F, 0xCF, 0xA6, 0xF6, 0xF4, 0x0D, 0xEF, + 0x4F, 0x92, 0xB9, 0xEC, 0x78, 0x93, 0xEC, 0x28, 0xFC, 0xD4, 0x12, 0xB1, + 0xF1, 0xB3, 0x2E, 0x24, + /* b */ + 0xA7, 0xF5, 0x61, 0xE0, 0x38, 0xEB, 0x1E, 0xD5, 0x60, 0xB3, 0xD1, 0x47, + 0xDB, 0x78, 0x20, 0x13, 0x06, 0x4C, 0x19, 0xF2, 0x7E, 0xD2, 0x7C, 0x67, + 0x80, 0xAA, 0xF7, 0x7F, 0xB8, 0xA5, 0x47, 0xCE, 0xB5, 0xB4, 0xFE, 0xF4, + 0x22, 0x34, 0x03, 0x53, + /* x */ + 0x92, 0x5B, 0xE9, 0xFB, 0x01, 0xAF, 0xC6, 0xFB, 0x4D, 0x3E, 0x7D, 0x49, + 0x90, 0x01, 0x0F, 0x81, 0x34, 0x08, 0xAB, 0x10, 0x6C, 0x4F, 0x09, 0xCB, + 0x7E, 0xE0, 0x78, 0x68, 0xCC, 0x13, 0x6F, 0xFF, 0x33, 0x57, 0xF6, 0x24, + 0xA2, 0x1B, 0xED, 0x52, + /* y */ + 0x63, 0xBA, 0x3A, 0x7A, 0x27, 0x48, 0x3E, 0xBF, 0x66, 0x71, 0xDB, 0xEF, + 0x7A, 0xBB, 0x30, 0xEB, 0xEE, 0x08, 0x4E, 0x58, 0xA0, 0xB0, 0x77, 0xAD, + 0x42, 0xA5, 0xA0, 0x98, 0x9D, 0x1E, 0xE7, 0x1B, 0x1B, 0x9B, 0xC0, 0x45, + 0x5F, 0xB0, 0xD2, 0xC3, + /* order */ + 0xD3, 0x5E, 0x47, 0x20, 0x36, 0xBC, 0x4F, 0xB7, 0xE1, 0x3C, 0x78, 0x5E, + 0xD2, 0x01, 0xE0, 0x65, 0xF9, 0x8F, 0xCF, 0xA5, 0xB6, 0x8F, 0x12, 0xA3, + 0x2D, 0x48, 0x2E, 0xC7, 0xEE, 0x86, 0x58, 0xE9, 0x86, 0x91, 0x55, 0x5B, + 0x44, 0xC5, 0x93, 0x11 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 48 * 6]; +} _EC_brainpoolP384r1 = { + { + NID_X9_62_prime_field, 0, 48, 1 + }, + { + /* no seed */ + /* p */ + 0x8C, 0xB9, 0x1E, 0x82, 0xA3, 0x38, 0x6D, 0x28, 0x0F, 0x5D, 0x6F, 0x7E, + 0x50, 0xE6, 0x41, 0xDF, 0x15, 0x2F, 0x71, 0x09, 0xED, 0x54, 0x56, 0xB4, + 0x12, 0xB1, 0xDA, 0x19, 0x7F, 0xB7, 0x11, 0x23, 0xAC, 0xD3, 0xA7, 0x29, + 0x90, 0x1D, 0x1A, 0x71, 0x87, 0x47, 0x00, 0x13, 0x31, 0x07, 0xEC, 0x53, + /* a */ + 0x7B, 0xC3, 0x82, 0xC6, 0x3D, 0x8C, 0x15, 0x0C, 0x3C, 0x72, 0x08, 0x0A, + 0xCE, 0x05, 0xAF, 0xA0, 0xC2, 0xBE, 0xA2, 0x8E, 0x4F, 0xB2, 0x27, 0x87, + 0x13, 0x91, 0x65, 0xEF, 0xBA, 0x91, 0xF9, 0x0F, 0x8A, 0xA5, 0x81, 0x4A, + 0x50, 0x3A, 0xD4, 0xEB, 0x04, 0xA8, 0xC7, 0xDD, 0x22, 0xCE, 0x28, 0x26, + /* b */ + 0x04, 0xA8, 0xC7, 0xDD, 0x22, 0xCE, 0x28, 0x26, 0x8B, 0x39, 0xB5, 0x54, + 0x16, 0xF0, 0x44, 0x7C, 0x2F, 0xB7, 0x7D, 0xE1, 0x07, 0xDC, 0xD2, 0xA6, + 0x2E, 0x88, 0x0E, 0xA5, 0x3E, 0xEB, 0x62, 0xD5, 0x7C, 0xB4, 0x39, 0x02, + 0x95, 0xDB, 0xC9, 0x94, 0x3A, 0xB7, 0x86, 0x96, 0xFA, 0x50, 0x4C, 0x11, + /* x */ + 0x1D, 0x1C, 0x64, 0xF0, 0x68, 0xCF, 0x45, 0xFF, 0xA2, 0xA6, 0x3A, 0x81, + 0xB7, 0xC1, 0x3F, 0x6B, 0x88, 0x47, 0xA3, 0xE7, 0x7E, 0xF1, 0x4F, 0xE3, + 0xDB, 0x7F, 0xCA, 0xFE, 0x0C, 0xBD, 0x10, 0xE8, 0xE8, 0x26, 0xE0, 0x34, + 0x36, 0xD6, 0x46, 0xAA, 0xEF, 0x87, 0xB2, 0xE2, 0x47, 0xD4, 0xAF, 0x1E, + /* y */ + 0x8A, 0xBE, 0x1D, 0x75, 0x20, 0xF9, 0xC2, 0xA4, 0x5C, 0xB1, 0xEB, 0x8E, + 0x95, 0xCF, 0xD5, 0x52, 0x62, 0xB7, 0x0B, 0x29, 0xFE, 0xEC, 0x58, 0x64, + 0xE1, 0x9C, 0x05, 0x4F, 0xF9, 0x91, 0x29, 0x28, 0x0E, 0x46, 0x46, 0x21, + 0x77, 0x91, 0x81, 0x11, 0x42, 0x82, 0x03, 0x41, 0x26, 0x3C, 0x53, 0x15, + /* order */ + 0x8C, 0xB9, 0x1E, 0x82, 0xA3, 0x38, 0x6D, 0x28, 0x0F, 0x5D, 0x6F, 0x7E, + 0x50, 0xE6, 0x41, 0xDF, 0x15, 0x2F, 0x71, 0x09, 0xED, 0x54, 0x56, 0xB3, + 0x1F, 0x16, 0x6E, 0x6C, 0xAC, 0x04, 0x25, 0xA7, 0xCF, 0x3A, 0xB6, 0xAF, + 0x6B, 0x7F, 0xC3, 0x10, 0x3B, 0x88, 0x32, 0x02, 0xE9, 0x04, 0x65, 0x65 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 48 * 6]; +} _EC_brainpoolP384t1 = { + { + NID_X9_62_prime_field, 0, 48, 1 + }, + { + /* no seed */ + /* p */ + 0x8C, 0xB9, 0x1E, 0x82, 0xA3, 0x38, 0x6D, 0x28, 0x0F, 0x5D, 0x6F, 0x7E, + 0x50, 0xE6, 0x41, 0xDF, 0x15, 0x2F, 0x71, 0x09, 0xED, 0x54, 0x56, 0xB4, + 0x12, 0xB1, 0xDA, 0x19, 0x7F, 0xB7, 0x11, 0x23, 0xAC, 0xD3, 0xA7, 0x29, + 0x90, 0x1D, 0x1A, 0x71, 0x87, 0x47, 0x00, 0x13, 0x31, 0x07, 0xEC, 0x53, + /* a */ + 0x8C, 0xB9, 0x1E, 0x82, 0xA3, 0x38, 0x6D, 0x28, 0x0F, 0x5D, 0x6F, 0x7E, + 0x50, 0xE6, 0x41, 0xDF, 0x15, 0x2F, 0x71, 0x09, 0xED, 0x54, 0x56, 0xB4, + 0x12, 0xB1, 0xDA, 0x19, 0x7F, 0xB7, 0x11, 0x23, 0xAC, 0xD3, 0xA7, 0x29, + 0x90, 0x1D, 0x1A, 0x71, 0x87, 0x47, 0x00, 0x13, 0x31, 0x07, 0xEC, 0x50, + /* b */ + 0x7F, 0x51, 0x9E, 0xAD, 0xA7, 0xBD, 0xA8, 0x1B, 0xD8, 0x26, 0xDB, 0xA6, + 0x47, 0x91, 0x0F, 0x8C, 0x4B, 0x93, 0x46, 0xED, 0x8C, 0xCD, 0xC6, 0x4E, + 0x4B, 0x1A, 0xBD, 0x11, 0x75, 0x6D, 0xCE, 0x1D, 0x20, 0x74, 0xAA, 0x26, + 0x3B, 0x88, 0x80, 0x5C, 0xED, 0x70, 0x35, 0x5A, 0x33, 0xB4, 0x71, 0xEE, + /* x */ + 0x18, 0xDE, 0x98, 0xB0, 0x2D, 0xB9, 0xA3, 0x06, 0xF2, 0xAF, 0xCD, 0x72, + 0x35, 0xF7, 0x2A, 0x81, 0x9B, 0x80, 0xAB, 0x12, 0xEB, 0xD6, 0x53, 0x17, + 0x24, 0x76, 0xFE, 0xCD, 0x46, 0x2A, 0xAB, 0xFF, 0xC4, 0xFF, 0x19, 0x1B, + 0x94, 0x6A, 0x5F, 0x54, 0xD8, 0xD0, 0xAA, 0x2F, 0x41, 0x88, 0x08, 0xCC, + /* y */ + 0x25, 0xAB, 0x05, 0x69, 0x62, 0xD3, 0x06, 0x51, 0xA1, 0x14, 0xAF, 0xD2, + 0x75, 0x5A, 0xD3, 0x36, 0x74, 0x7F, 0x93, 0x47, 0x5B, 0x7A, 0x1F, 0xCA, + 0x3B, 0x88, 0xF2, 0xB6, 0xA2, 0x08, 0xCC, 0xFE, 0x46, 0x94, 0x08, 0x58, + 0x4D, 0xC2, 0xB2, 0x91, 0x26, 0x75, 0xBF, 0x5B, 0x9E, 0x58, 0x29, 0x28, + /* order */ + 0x8C, 0xB9, 0x1E, 0x82, 0xA3, 0x38, 0x6D, 0x28, 0x0F, 0x5D, 0x6F, 0x7E, + 0x50, 0xE6, 0x41, 0xDF, 0x15, 0x2F, 0x71, 0x09, 0xED, 0x54, 0x56, 0xB3, + 0x1F, 0x16, 0x6E, 0x6C, 0xAC, 0x04, 0x25, 0xA7, 0xCF, 0x3A, 0xB6, 0xAF, + 0x6B, 0x7F, 0xC3, 0x10, 0x3B, 0x88, 0x32, 0x02, 0xE9, 0x04, 0x65, 0x65 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 64 * 6]; +} _EC_brainpoolP512r1 = { + { + NID_X9_62_prime_field, 0, 64, 1 + }, + { + /* no seed */ + /* p */ + 0xAA, 0xDD, 0x9D, 0xB8, 0xDB, 0xE9, 0xC4, 0x8B, 0x3F, 0xD4, 0xE6, 0xAE, + 0x33, 0xC9, 0xFC, 0x07, 0xCB, 0x30, 0x8D, 0xB3, 0xB3, 0xC9, 0xD2, 0x0E, + 0xD6, 0x63, 0x9C, 0xCA, 0x70, 0x33, 0x08, 0x71, 0x7D, 0x4D, 0x9B, 0x00, + 0x9B, 0xC6, 0x68, 0x42, 0xAE, 0xCD, 0xA1, 0x2A, 0xE6, 0xA3, 0x80, 0xE6, + 0x28, 0x81, 0xFF, 0x2F, 0x2D, 0x82, 0xC6, 0x85, 0x28, 0xAA, 0x60, 0x56, + 0x58, 0x3A, 0x48, 0xF3, + /* a */ + 0x78, 0x30, 0xA3, 0x31, 0x8B, 0x60, 0x3B, 0x89, 0xE2, 0x32, 0x71, 0x45, + 0xAC, 0x23, 0x4C, 0xC5, 0x94, 0xCB, 0xDD, 0x8D, 0x3D, 0xF9, 0x16, 0x10, + 0xA8, 0x34, 0x41, 0xCA, 0xEA, 0x98, 0x63, 0xBC, 0x2D, 0xED, 0x5D, 0x5A, + 0xA8, 0x25, 0x3A, 0xA1, 0x0A, 0x2E, 0xF1, 0xC9, 0x8B, 0x9A, 0xC8, 0xB5, + 0x7F, 0x11, 0x17, 0xA7, 0x2B, 0xF2, 0xC7, 0xB9, 0xE7, 0xC1, 0xAC, 0x4D, + 0x77, 0xFC, 0x94, 0xCA, + /* b */ + 0x3D, 0xF9, 0x16, 0x10, 0xA8, 0x34, 0x41, 0xCA, 0xEA, 0x98, 0x63, 0xBC, + 0x2D, 0xED, 0x5D, 0x5A, 0xA8, 0x25, 0x3A, 0xA1, 0x0A, 0x2E, 0xF1, 0xC9, + 0x8B, 0x9A, 0xC8, 0xB5, 0x7F, 0x11, 0x17, 0xA7, 0x2B, 0xF2, 0xC7, 0xB9, + 0xE7, 0xC1, 0xAC, 0x4D, 0x77, 0xFC, 0x94, 0xCA, 0xDC, 0x08, 0x3E, 0x67, + 0x98, 0x40, 0x50, 0xB7, 0x5E, 0xBA, 0xE5, 0xDD, 0x28, 0x09, 0xBD, 0x63, + 0x80, 0x16, 0xF7, 0x23, + /* x */ + 0x81, 0xAE, 0xE4, 0xBD, 0xD8, 0x2E, 0xD9, 0x64, 0x5A, 0x21, 0x32, 0x2E, + 0x9C, 0x4C, 0x6A, 0x93, 0x85, 0xED, 0x9F, 0x70, 0xB5, 0xD9, 0x16, 0xC1, + 0xB4, 0x3B, 0x62, 0xEE, 0xF4, 0xD0, 0x09, 0x8E, 0xFF, 0x3B, 0x1F, 0x78, + 0xE2, 0xD0, 0xD4, 0x8D, 0x50, 0xD1, 0x68, 0x7B, 0x93, 0xB9, 0x7D, 0x5F, + 0x7C, 0x6D, 0x50, 0x47, 0x40, 0x6A, 0x5E, 0x68, 0x8B, 0x35, 0x22, 0x09, + 0xBC, 0xB9, 0xF8, 0x22, + /* y */ + 0x7D, 0xDE, 0x38, 0x5D, 0x56, 0x63, 0x32, 0xEC, 0xC0, 0xEA, 0xBF, 0xA9, + 0xCF, 0x78, 0x22, 0xFD, 0xF2, 0x09, 0xF7, 0x00, 0x24, 0xA5, 0x7B, 0x1A, + 0xA0, 0x00, 0xC5, 0x5B, 0x88, 0x1F, 0x81, 0x11, 0xB2, 0xDC, 0xDE, 0x49, + 0x4A, 0x5F, 0x48, 0x5E, 0x5B, 0xCA, 0x4B, 0xD8, 0x8A, 0x27, 0x63, 0xAE, + 0xD1, 0xCA, 0x2B, 0x2F, 0xA8, 0xF0, 0x54, 0x06, 0x78, 0xCD, 0x1E, 0x0F, + 0x3A, 0xD8, 0x08, 0x92, + /* order */ + 0xAA, 0xDD, 0x9D, 0xB8, 0xDB, 0xE9, 0xC4, 0x8B, 0x3F, 0xD4, 0xE6, 0xAE, + 0x33, 0xC9, 0xFC, 0x07, 0xCB, 0x30, 0x8D, 0xB3, 0xB3, 0xC9, 0xD2, 0x0E, + 0xD6, 0x63, 0x9C, 0xCA, 0x70, 0x33, 0x08, 0x70, 0x55, 0x3E, 0x5C, 0x41, + 0x4C, 0xA9, 0x26, 0x19, 0x41, 0x86, 0x61, 0x19, 0x7F, 0xAC, 0x10, 0x47, + 0x1D, 0xB1, 0xD3, 0x81, 0x08, 0x5D, 0xDA, 0xDD, 0xB5, 0x87, 0x96, 0x82, + 0x9C, 0xA9, 0x00, 0x69 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 64 * 6]; +} _EC_brainpoolP512t1 = { + { + NID_X9_62_prime_field, 0, 64, 1 + }, + { + /* no seed */ + /* p */ + 0xAA, 0xDD, 0x9D, 0xB8, 0xDB, 0xE9, 0xC4, 0x8B, 0x3F, 0xD4, 0xE6, 0xAE, + 0x33, 0xC9, 0xFC, 0x07, 0xCB, 0x30, 0x8D, 0xB3, 0xB3, 0xC9, 0xD2, 0x0E, + 0xD6, 0x63, 0x9C, 0xCA, 0x70, 0x33, 0x08, 0x71, 0x7D, 0x4D, 0x9B, 0x00, + 0x9B, 0xC6, 0x68, 0x42, 0xAE, 0xCD, 0xA1, 0x2A, 0xE6, 0xA3, 0x80, 0xE6, + 0x28, 0x81, 0xFF, 0x2F, 0x2D, 0x82, 0xC6, 0x85, 0x28, 0xAA, 0x60, 0x56, + 0x58, 0x3A, 0x48, 0xF3, + /* a */ + 0xAA, 0xDD, 0x9D, 0xB8, 0xDB, 0xE9, 0xC4, 0x8B, 0x3F, 0xD4, 0xE6, 0xAE, + 0x33, 0xC9, 0xFC, 0x07, 0xCB, 0x30, 0x8D, 0xB3, 0xB3, 0xC9, 0xD2, 0x0E, + 0xD6, 0x63, 0x9C, 0xCA, 0x70, 0x33, 0x08, 0x71, 0x7D, 0x4D, 0x9B, 0x00, + 0x9B, 0xC6, 0x68, 0x42, 0xAE, 0xCD, 0xA1, 0x2A, 0xE6, 0xA3, 0x80, 0xE6, + 0x28, 0x81, 0xFF, 0x2F, 0x2D, 0x82, 0xC6, 0x85, 0x28, 0xAA, 0x60, 0x56, + 0x58, 0x3A, 0x48, 0xF0, + /* b */ + 0x7C, 0xBB, 0xBC, 0xF9, 0x44, 0x1C, 0xFA, 0xB7, 0x6E, 0x18, 0x90, 0xE4, + 0x68, 0x84, 0xEA, 0xE3, 0x21, 0xF7, 0x0C, 0x0B, 0xCB, 0x49, 0x81, 0x52, + 0x78, 0x97, 0x50, 0x4B, 0xEC, 0x3E, 0x36, 0xA6, 0x2B, 0xCD, 0xFA, 0x23, + 0x04, 0x97, 0x65, 0x40, 0xF6, 0x45, 0x00, 0x85, 0xF2, 0xDA, 0xE1, 0x45, + 0xC2, 0x25, 0x53, 0xB4, 0x65, 0x76, 0x36, 0x89, 0x18, 0x0E, 0xA2, 0x57, + 0x18, 0x67, 0x42, 0x3E, + /* x */ + 0x64, 0x0E, 0xCE, 0x5C, 0x12, 0x78, 0x87, 0x17, 0xB9, 0xC1, 0xBA, 0x06, + 0xCB, 0xC2, 0xA6, 0xFE, 0xBA, 0x85, 0x84, 0x24, 0x58, 0xC5, 0x6D, 0xDE, + 0x9D, 0xB1, 0x75, 0x8D, 0x39, 0xC0, 0x31, 0x3D, 0x82, 0xBA, 0x51, 0x73, + 0x5C, 0xDB, 0x3E, 0xA4, 0x99, 0xAA, 0x77, 0xA7, 0xD6, 0x94, 0x3A, 0x64, + 0xF7, 0xA3, 0xF2, 0x5F, 0xE2, 0x6F, 0x06, 0xB5, 0x1B, 0xAA, 0x26, 0x96, + 0xFA, 0x90, 0x35, 0xDA, + /* y */ + 0x5B, 0x53, 0x4B, 0xD5, 0x95, 0xF5, 0xAF, 0x0F, 0xA2, 0xC8, 0x92, 0x37, + 0x6C, 0x84, 0xAC, 0xE1, 0xBB, 0x4E, 0x30, 0x19, 0xB7, 0x16, 0x34, 0xC0, + 0x11, 0x31, 0x15, 0x9C, 0xAE, 0x03, 0xCE, 0xE9, 0xD9, 0x93, 0x21, 0x84, + 0xBE, 0xEF, 0x21, 0x6B, 0xD7, 0x1D, 0xF2, 0xDA, 0xDF, 0x86, 0xA6, 0x27, + 0x30, 0x6E, 0xCF, 0xF9, 0x6D, 0xBB, 0x8B, 0xAC, 0xE1, 0x98, 0xB6, 0x1E, + 0x00, 0xF8, 0xB3, 0x32, + /* order */ + 0xAA, 0xDD, 0x9D, 0xB8, 0xDB, 0xE9, 0xC4, 0x8B, 0x3F, 0xD4, 0xE6, 0xAE, + 0x33, 0xC9, 0xFC, 0x07, 0xCB, 0x30, 0x8D, 0xB3, 0xB3, 0xC9, 0xD2, 0x0E, + 0xD6, 0x63, 0x9C, 0xCA, 0x70, 0x33, 0x08, 0x70, 0x55, 0x3E, 0x5C, 0x41, + 0x4C, 0xA9, 0x26, 0x19, 0x41, 0x86, 0x61, 0x19, 0x7F, 0xAC, 0x10, 0x47, + 0x1D, 0xB1, 0xD3, 0x81, 0x08, 0x5D, 0xDA, 0xDD, 0xB5, 0x87, 0x96, 0x82, + 0x9C, 0xA9, 0x00, 0x69 + } +}; + +#ifndef OPENSSL_NO_SM2 +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 32 * 6]; +} _EC_sm2p256v1 = { + { + NID_X9_62_prime_field, 0, 32, 1 + }, + { + /* no seed */ + + /* p */ + 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + /* a */ + 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, + /* b */ + 0x28, 0xe9, 0xfa, 0x9e, 0x9d, 0x9f, 0x5e, 0x34, 0x4d, 0x5a, 0x9e, 0x4b, + 0xcf, 0x65, 0x09, 0xa7, 0xf3, 0x97, 0x89, 0xf5, 0x15, 0xab, 0x8f, 0x92, + 0xdd, 0xbc, 0xbd, 0x41, 0x4d, 0x94, 0x0e, 0x93, + /* x */ + 0x32, 0xc4, 0xae, 0x2c, 0x1f, 0x19, 0x81, 0x19, 0x5f, 0x99, 0x04, 0x46, + 0x6a, 0x39, 0xc9, 0x94, 0x8f, 0xe3, 0x0b, 0xbf, 0xf2, 0x66, 0x0b, 0xe1, + 0x71, 0x5a, 0x45, 0x89, 0x33, 0x4c, 0x74, 0xc7, + /* y */ + 0xbc, 0x37, 0x36, 0xa2, 0xf4, 0xf6, 0x77, 0x9c, 0x59, 0xbd, 0xce, 0xe3, + 0x6b, 0x69, 0x21, 0x53, 0xd0, 0xa9, 0x87, 0x7c, 0xc6, 0x2a, 0x47, 0x40, + 0x02, 0xdf, 0x32, 0xe5, 0x21, 0x39, 0xf0, 0xa0, + /* order */ + 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x72, 0x03, 0xdf, 0x6b, 0x21, 0xc6, 0x05, 0x2b, + 0x53, 0xbb, 0xf4, 0x09, 0x39, 0xd5, 0x41, 0x23, + } +}; +#endif /* OPENSSL_NO_SM2 */ + +typedef struct _ec_list_element_st { + int nid; + const EC_CURVE_DATA *data; + const EC_METHOD *(*meth) (void); + const char *comment; +} ec_list_element; + +static const ec_list_element curve_list[] = { + /* prime field curves */ + /* secg curves */ + {NID_secp112r1, &_EC_SECG_PRIME_112R1.h, 0, + "SECG/WTLS curve over a 112 bit prime field"}, + {NID_secp112r2, &_EC_SECG_PRIME_112R2.h, 0, + "SECG curve over a 112 bit prime field"}, + {NID_secp128r1, &_EC_SECG_PRIME_128R1.h, 0, + "SECG curve over a 128 bit prime field"}, + {NID_secp128r2, &_EC_SECG_PRIME_128R2.h, 0, + "SECG curve over a 128 bit prime field"}, + {NID_secp160k1, &_EC_SECG_PRIME_160K1.h, 0, + "SECG curve over a 160 bit prime field"}, + {NID_secp160r1, &_EC_SECG_PRIME_160R1.h, 0, + "SECG curve over a 160 bit prime field"}, + {NID_secp160r2, &_EC_SECG_PRIME_160R2.h, 0, + "SECG/WTLS curve over a 160 bit prime field"}, + /* SECG secp192r1 is the same as X9.62 prime192v1 and hence omitted */ + {NID_secp192k1, &_EC_SECG_PRIME_192K1.h, 0, + "SECG curve over a 192 bit prime field"}, + {NID_secp224k1, &_EC_SECG_PRIME_224K1.h, 0, + "SECG curve over a 224 bit prime field"}, +#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 + {NID_secp224r1, &_EC_NIST_PRIME_224.h, EC_GFp_nistp224_method, + "NIST/SECG curve over a 224 bit prime field"}, +#else + {NID_secp224r1, &_EC_NIST_PRIME_224.h, 0, + "NIST/SECG curve over a 224 bit prime field"}, +#endif + {NID_secp256k1, &_EC_SECG_PRIME_256K1.h, 0, + "SECG curve over a 256 bit prime field"}, + /* SECG secp256r1 is the same as X9.62 prime256v1 and hence omitted */ + {NID_secp384r1, &_EC_NIST_PRIME_384.h, 0, + "NIST/SECG curve over a 384 bit prime field"}, +#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 + {NID_secp521r1, &_EC_NIST_PRIME_521.h, EC_GFp_nistp521_method, + "NIST/SECG curve over a 521 bit prime field"}, +#else + {NID_secp521r1, &_EC_NIST_PRIME_521.h, 0, + "NIST/SECG curve over a 521 bit prime field"}, +#endif + /* X9.62 curves */ + {NID_X9_62_prime192v1, &_EC_NIST_PRIME_192.h, 0, + "NIST/X9.62/SECG curve over a 192 bit prime field"}, + {NID_X9_62_prime192v2, &_EC_X9_62_PRIME_192V2.h, 0, + "X9.62 curve over a 192 bit prime field"}, + {NID_X9_62_prime192v3, &_EC_X9_62_PRIME_192V3.h, 0, + "X9.62 curve over a 192 bit prime field"}, + {NID_X9_62_prime239v1, &_EC_X9_62_PRIME_239V1.h, 0, + "X9.62 curve over a 239 bit prime field"}, + {NID_X9_62_prime239v2, &_EC_X9_62_PRIME_239V2.h, 0, + "X9.62 curve over a 239 bit prime field"}, + {NID_X9_62_prime239v3, &_EC_X9_62_PRIME_239V3.h, 0, + "X9.62 curve over a 239 bit prime field"}, + {NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h, +#if defined(ECP_NISTZ256_ASM) + EC_GFp_nistz256_method, +#elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128) + EC_GFp_nistp256_method, +#else + 0, +#endif + "X9.62/SECG curve over a 256 bit prime field"}, +#ifndef OPENSSL_NO_EC2M + /* characteristic two field curves */ + /* NIST/SECG curves */ + {NID_sect113r1, &_EC_SECG_CHAR2_113R1.h, 0, + "SECG curve over a 113 bit binary field"}, + {NID_sect113r2, &_EC_SECG_CHAR2_113R2.h, 0, + "SECG curve over a 113 bit binary field"}, + {NID_sect131r1, &_EC_SECG_CHAR2_131R1.h, 0, + "SECG/WTLS curve over a 131 bit binary field"}, + {NID_sect131r2, &_EC_SECG_CHAR2_131R2.h, 0, + "SECG curve over a 131 bit binary field"}, + {NID_sect163k1, &_EC_NIST_CHAR2_163K.h, 0, + "NIST/SECG/WTLS curve over a 163 bit binary field"}, + {NID_sect163r1, &_EC_SECG_CHAR2_163R1.h, 0, + "SECG curve over a 163 bit binary field"}, + {NID_sect163r2, &_EC_NIST_CHAR2_163B.h, 0, + "NIST/SECG curve over a 163 bit binary field"}, + {NID_sect193r1, &_EC_SECG_CHAR2_193R1.h, 0, + "SECG curve over a 193 bit binary field"}, + {NID_sect193r2, &_EC_SECG_CHAR2_193R2.h, 0, + "SECG curve over a 193 bit binary field"}, + {NID_sect233k1, &_EC_NIST_CHAR2_233K.h, 0, + "NIST/SECG/WTLS curve over a 233 bit binary field"}, + {NID_sect233r1, &_EC_NIST_CHAR2_233B.h, 0, + "NIST/SECG/WTLS curve over a 233 bit binary field"}, + {NID_sect239k1, &_EC_SECG_CHAR2_239K1.h, 0, + "SECG curve over a 239 bit binary field"}, + {NID_sect283k1, &_EC_NIST_CHAR2_283K.h, 0, + "NIST/SECG curve over a 283 bit binary field"}, + {NID_sect283r1, &_EC_NIST_CHAR2_283B.h, 0, + "NIST/SECG curve over a 283 bit binary field"}, + {NID_sect409k1, &_EC_NIST_CHAR2_409K.h, 0, + "NIST/SECG curve over a 409 bit binary field"}, + {NID_sect409r1, &_EC_NIST_CHAR2_409B.h, 0, + "NIST/SECG curve over a 409 bit binary field"}, + {NID_sect571k1, &_EC_NIST_CHAR2_571K.h, 0, + "NIST/SECG curve over a 571 bit binary field"}, + {NID_sect571r1, &_EC_NIST_CHAR2_571B.h, 0, + "NIST/SECG curve over a 571 bit binary field"}, + /* X9.62 curves */ + {NID_X9_62_c2pnb163v1, &_EC_X9_62_CHAR2_163V1.h, 0, + "X9.62 curve over a 163 bit binary field"}, + {NID_X9_62_c2pnb163v2, &_EC_X9_62_CHAR2_163V2.h, 0, + "X9.62 curve over a 163 bit binary field"}, + {NID_X9_62_c2pnb163v3, &_EC_X9_62_CHAR2_163V3.h, 0, + "X9.62 curve over a 163 bit binary field"}, + {NID_X9_62_c2pnb176v1, &_EC_X9_62_CHAR2_176V1.h, 0, + "X9.62 curve over a 176 bit binary field"}, + {NID_X9_62_c2tnb191v1, &_EC_X9_62_CHAR2_191V1.h, 0, + "X9.62 curve over a 191 bit binary field"}, + {NID_X9_62_c2tnb191v2, &_EC_X9_62_CHAR2_191V2.h, 0, + "X9.62 curve over a 191 bit binary field"}, + {NID_X9_62_c2tnb191v3, &_EC_X9_62_CHAR2_191V3.h, 0, + "X9.62 curve over a 191 bit binary field"}, + {NID_X9_62_c2pnb208w1, &_EC_X9_62_CHAR2_208W1.h, 0, + "X9.62 curve over a 208 bit binary field"}, + {NID_X9_62_c2tnb239v1, &_EC_X9_62_CHAR2_239V1.h, 0, + "X9.62 curve over a 239 bit binary field"}, + {NID_X9_62_c2tnb239v2, &_EC_X9_62_CHAR2_239V2.h, 0, + "X9.62 curve over a 239 bit binary field"}, + {NID_X9_62_c2tnb239v3, &_EC_X9_62_CHAR2_239V3.h, 0, + "X9.62 curve over a 239 bit binary field"}, + {NID_X9_62_c2pnb272w1, &_EC_X9_62_CHAR2_272W1.h, 0, + "X9.62 curve over a 272 bit binary field"}, + {NID_X9_62_c2pnb304w1, &_EC_X9_62_CHAR2_304W1.h, 0, + "X9.62 curve over a 304 bit binary field"}, + {NID_X9_62_c2tnb359v1, &_EC_X9_62_CHAR2_359V1.h, 0, + "X9.62 curve over a 359 bit binary field"}, + {NID_X9_62_c2pnb368w1, &_EC_X9_62_CHAR2_368W1.h, 0, + "X9.62 curve over a 368 bit binary field"}, + {NID_X9_62_c2tnb431r1, &_EC_X9_62_CHAR2_431R1.h, 0, + "X9.62 curve over a 431 bit binary field"}, + /* + * the WAP/WTLS curves [unlike SECG, spec has its own OIDs for curves + * from X9.62] + */ + {NID_wap_wsg_idm_ecid_wtls1, &_EC_WTLS_1.h, 0, + "WTLS curve over a 113 bit binary field"}, + {NID_wap_wsg_idm_ecid_wtls3, &_EC_NIST_CHAR2_163K.h, 0, + "NIST/SECG/WTLS curve over a 163 bit binary field"}, + {NID_wap_wsg_idm_ecid_wtls4, &_EC_SECG_CHAR2_113R1.h, 0, + "SECG curve over a 113 bit binary field"}, + {NID_wap_wsg_idm_ecid_wtls5, &_EC_X9_62_CHAR2_163V1.h, 0, + "X9.62 curve over a 163 bit binary field"}, +#endif + {NID_wap_wsg_idm_ecid_wtls6, &_EC_SECG_PRIME_112R1.h, 0, + "SECG/WTLS curve over a 112 bit prime field"}, + {NID_wap_wsg_idm_ecid_wtls7, &_EC_SECG_PRIME_160R2.h, 0, + "SECG/WTLS curve over a 160 bit prime field"}, + {NID_wap_wsg_idm_ecid_wtls8, &_EC_WTLS_8.h, 0, + "WTLS curve over a 112 bit prime field"}, + {NID_wap_wsg_idm_ecid_wtls9, &_EC_WTLS_9.h, 0, + "WTLS curve over a 160 bit prime field"}, +#ifndef OPENSSL_NO_EC2M + {NID_wap_wsg_idm_ecid_wtls10, &_EC_NIST_CHAR2_233K.h, 0, + "NIST/SECG/WTLS curve over a 233 bit binary field"}, + {NID_wap_wsg_idm_ecid_wtls11, &_EC_NIST_CHAR2_233B.h, 0, + "NIST/SECG/WTLS curve over a 233 bit binary field"}, +#endif + {NID_wap_wsg_idm_ecid_wtls12, &_EC_WTLS_12.h, 0, + "WTLS curve over a 224 bit prime field"}, +#ifndef OPENSSL_NO_EC2M + /* IPSec curves */ + {NID_ipsec3, &_EC_IPSEC_155_ID3.h, 0, + "\n\tIPSec/IKE/Oakley curve #3 over a 155 bit binary field.\n" + "\tNot suitable for ECDSA.\n\tQuestionable extension field!"}, + {NID_ipsec4, &_EC_IPSEC_185_ID4.h, 0, + "\n\tIPSec/IKE/Oakley curve #4 over a 185 bit binary field.\n" + "\tNot suitable for ECDSA.\n\tQuestionable extension field!"}, +#endif + /* brainpool curves */ + {NID_brainpoolP160r1, &_EC_brainpoolP160r1.h, 0, + "RFC 5639 curve over a 160 bit prime field"}, + {NID_brainpoolP160t1, &_EC_brainpoolP160t1.h, 0, + "RFC 5639 curve over a 160 bit prime field"}, + {NID_brainpoolP192r1, &_EC_brainpoolP192r1.h, 0, + "RFC 5639 curve over a 192 bit prime field"}, + {NID_brainpoolP192t1, &_EC_brainpoolP192t1.h, 0, + "RFC 5639 curve over a 192 bit prime field"}, + {NID_brainpoolP224r1, &_EC_brainpoolP224r1.h, 0, + "RFC 5639 curve over a 224 bit prime field"}, + {NID_brainpoolP224t1, &_EC_brainpoolP224t1.h, 0, + "RFC 5639 curve over a 224 bit prime field"}, + {NID_brainpoolP256r1, &_EC_brainpoolP256r1.h, 0, + "RFC 5639 curve over a 256 bit prime field"}, + {NID_brainpoolP256t1, &_EC_brainpoolP256t1.h, 0, + "RFC 5639 curve over a 256 bit prime field"}, + {NID_brainpoolP320r1, &_EC_brainpoolP320r1.h, 0, + "RFC 5639 curve over a 320 bit prime field"}, + {NID_brainpoolP320t1, &_EC_brainpoolP320t1.h, 0, + "RFC 5639 curve over a 320 bit prime field"}, + {NID_brainpoolP384r1, &_EC_brainpoolP384r1.h, 0, + "RFC 5639 curve over a 384 bit prime field"}, + {NID_brainpoolP384t1, &_EC_brainpoolP384t1.h, 0, + "RFC 5639 curve over a 384 bit prime field"}, + {NID_brainpoolP512r1, &_EC_brainpoolP512r1.h, 0, + "RFC 5639 curve over a 512 bit prime field"}, + {NID_brainpoolP512t1, &_EC_brainpoolP512t1.h, 0, + "RFC 5639 curve over a 512 bit prime field"}, +#ifndef OPENSSL_NO_SM2 + {NID_sm2, &_EC_sm2p256v1.h, 0, + "SM2 curve over a 256 bit prime field"}, +#endif +}; + +#define curve_list_length OSSL_NELEM(curve_list) + +static EC_GROUP *ec_group_new_from_data(const ec_list_element curve) +{ + EC_GROUP *group = NULL; + EC_POINT *P = NULL; + BN_CTX *ctx = NULL; + BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL, *order = + NULL; + int ok = 0; + int seed_len, param_len; + const EC_METHOD *meth; + const EC_CURVE_DATA *data; + const unsigned char *params; + + /* If no curve data curve method must handle everything */ + if (curve.data == NULL) + return EC_GROUP_new(curve.meth != NULL ? curve.meth() : NULL); + + if ((ctx = BN_CTX_new()) == NULL) { + ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_MALLOC_FAILURE); + goto err; + } + + data = curve.data; + seed_len = data->seed_len; + param_len = data->param_len; + params = (const unsigned char *)(data + 1); /* skip header */ + params += seed_len; /* skip seed */ + + if ((p = BN_bin2bn(params + 0 * param_len, param_len, NULL)) == NULL + || (a = BN_bin2bn(params + 1 * param_len, param_len, NULL)) == NULL + || (b = BN_bin2bn(params + 2 * param_len, param_len, NULL)) == NULL) { + ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB); + goto err; + } + + if (curve.meth != 0) { + meth = curve.meth(); + if (((group = EC_GROUP_new(meth)) == NULL) || + (!(group->meth->group_set_curve(group, p, a, b, ctx)))) { + ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); + goto err; + } + } else if (data->field_type == NID_X9_62_prime_field) { + if ((group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL) { + ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); + goto err; + } + } +#ifndef OPENSSL_NO_EC2M + else { /* field_type == + * NID_X9_62_characteristic_two_field */ + + if ((group = EC_GROUP_new_curve_GF2m(p, a, b, ctx)) == NULL) { + ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); + goto err; + } + } +#endif + + EC_GROUP_set_curve_name(group, curve.nid); + + if ((P = EC_POINT_new(group)) == NULL) { + ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); + goto err; + } + + if ((x = BN_bin2bn(params + 3 * param_len, param_len, NULL)) == NULL + || (y = BN_bin2bn(params + 4 * param_len, param_len, NULL)) == NULL) { + ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB); + goto err; + } + if (!EC_POINT_set_affine_coordinates(group, P, x, y, ctx)) { + ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); + goto err; + } + if ((order = BN_bin2bn(params + 5 * param_len, param_len, NULL)) == NULL + || !BN_set_word(x, (BN_ULONG)data->cofactor)) { + ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB); + goto err; + } + if (!EC_GROUP_set_generator(group, P, order, x)) { + ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); + goto err; + } + if (seed_len) { + if (!EC_GROUP_set_seed(group, params - seed_len, seed_len)) { + ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); + goto err; + } + } + ok = 1; + err: + if (!ok) { + EC_GROUP_free(group); + group = NULL; + } + EC_POINT_free(P); + BN_CTX_free(ctx); + BN_free(p); + BN_free(a); + BN_free(b); + BN_free(order); + BN_free(x); + BN_free(y); + return group; +} + +EC_GROUP *EC_GROUP_new_by_curve_name(int nid) +{ + size_t i; + EC_GROUP *ret = NULL; + + if (nid <= 0) + return NULL; + + for (i = 0; i < curve_list_length; i++) + if (curve_list[i].nid == nid) { + ret = ec_group_new_from_data(curve_list[i]); + break; + } + + if (ret == NULL) { + ECerr(EC_F_EC_GROUP_NEW_BY_CURVE_NAME, EC_R_UNKNOWN_GROUP); + return NULL; + } + + return ret; +} + +size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems) +{ + size_t i, min; + + if (r == NULL || nitems == 0) + return curve_list_length; + + min = nitems < curve_list_length ? nitems : curve_list_length; + + for (i = 0; i < min; i++) { + r[i].nid = curve_list[i].nid; + r[i].comment = curve_list[i].comment; + } + + return curve_list_length; +} + +/* Functions to translate between common NIST curve names and NIDs */ + +typedef struct { + const char *name; /* NIST Name of curve */ + int nid; /* Curve NID */ +} EC_NIST_NAME; + +static EC_NIST_NAME nist_curves[] = { + {"B-163", NID_sect163r2}, + {"B-233", NID_sect233r1}, + {"B-283", NID_sect283r1}, + {"B-409", NID_sect409r1}, + {"B-571", NID_sect571r1}, + {"K-163", NID_sect163k1}, + {"K-233", NID_sect233k1}, + {"K-283", NID_sect283k1}, + {"K-409", NID_sect409k1}, + {"K-571", NID_sect571k1}, + {"P-192", NID_X9_62_prime192v1}, + {"P-224", NID_secp224r1}, + {"P-256", NID_X9_62_prime256v1}, + {"P-384", NID_secp384r1}, + {"P-521", NID_secp521r1} +}; + +const char *EC_curve_nid2nist(int nid) +{ + size_t i; + for (i = 0; i < OSSL_NELEM(nist_curves); i++) { + if (nist_curves[i].nid == nid) + return nist_curves[i].name; + } + return NULL; +} + +int EC_curve_nist2nid(const char *name) +{ + size_t i; + for (i = 0; i < OSSL_NELEM(nist_curves); i++) { + if (strcmp(nist_curves[i].name, name) == 0) + return nist_curves[i].nid; + } + return NID_undef; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_cvt.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_cvt.c new file mode 100644 index 000000000..0ec346c12 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_cvt.c @@ -0,0 +1,82 @@ +/* + * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "ec_lcl.h" + +EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx) +{ + const EC_METHOD *meth; + EC_GROUP *ret; + +#if defined(OPENSSL_BN_ASM_MONT) + /* + * This might appear controversial, but the fact is that generic + * prime method was observed to deliver better performance even + * for NIST primes on a range of platforms, e.g.: 60%-15% + * improvement on IA-64, ~25% on ARM, 30%-90% on P4, 20%-25% + * in 32-bit build and 35%--12% in 64-bit build on Core2... + * Coefficients are relative to optimized bn_nist.c for most + * intensive ECDSA verify and ECDH operations for 192- and 521- + * bit keys respectively. Choice of these boundary values is + * arguable, because the dependency of improvement coefficient + * from key length is not a "monotone" curve. For example while + * 571-bit result is 23% on ARM, 384-bit one is -1%. But it's + * generally faster, sometimes "respectfully" faster, sometimes + * "tolerably" slower... What effectively happens is that loop + * with bn_mul_add_words is put against bn_mul_mont, and the + * latter "wins" on short vectors. Correct solution should be + * implementing dedicated NxN multiplication subroutines for + * small N. But till it materializes, let's stick to generic + * prime method... + * + */ + meth = EC_GFp_mont_method(); +#else + if (BN_nist_mod_func(p)) + meth = EC_GFp_nist_method(); + else + meth = EC_GFp_mont_method(); +#endif + + ret = EC_GROUP_new(meth); + if (ret == NULL) + return NULL; + + if (!EC_GROUP_set_curve(ret, p, a, b, ctx)) { + EC_GROUP_clear_free(ret); + return NULL; + } + + return ret; +} + +#ifndef OPENSSL_NO_EC2M +EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx) +{ + const EC_METHOD *meth; + EC_GROUP *ret; + + meth = EC_GF2m_simple_method(); + + ret = EC_GROUP_new(meth); + if (ret == NULL) + return NULL; + + if (!EC_GROUP_set_curve(ret, p, a, b, ctx)) { + EC_GROUP_clear_free(ret); + return NULL; + } + + return ret; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_err.c new file mode 100644 index 000000000..ce3493823 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_err.c @@ -0,0 +1,394 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA EC_str_functs[] = { + {ERR_PACK(ERR_LIB_EC, EC_F_BN_TO_FELEM, 0), "BN_to_felem"}, + {ERR_PACK(ERR_LIB_EC, EC_F_D2I_ECPARAMETERS, 0), "d2i_ECParameters"}, + {ERR_PACK(ERR_LIB_EC, EC_F_D2I_ECPKPARAMETERS, 0), "d2i_ECPKParameters"}, + {ERR_PACK(ERR_LIB_EC, EC_F_D2I_ECPRIVATEKEY, 0), "d2i_ECPrivateKey"}, + {ERR_PACK(ERR_LIB_EC, EC_F_DO_EC_KEY_PRINT, 0), "do_EC_KEY_print"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECDH_CMS_DECRYPT, 0), "ecdh_cms_decrypt"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECDH_CMS_SET_SHARED_INFO, 0), + "ecdh_cms_set_shared_info"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECDH_COMPUTE_KEY, 0), "ECDH_compute_key"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECDH_SIMPLE_COMPUTE_KEY, 0), + "ecdh_simple_compute_key"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECDSA_DO_SIGN_EX, 0), "ECDSA_do_sign_ex"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECDSA_DO_VERIFY, 0), "ECDSA_do_verify"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECDSA_SIGN_EX, 0), "ECDSA_sign_ex"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECDSA_SIGN_SETUP, 0), "ECDSA_sign_setup"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECDSA_SIG_NEW, 0), "ECDSA_SIG_new"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECDSA_VERIFY, 0), "ECDSA_verify"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECD_ITEM_VERIFY, 0), "ecd_item_verify"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECKEY_PARAM2TYPE, 0), "eckey_param2type"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECKEY_PARAM_DECODE, 0), "eckey_param_decode"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECKEY_PRIV_DECODE, 0), "eckey_priv_decode"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECKEY_PRIV_ENCODE, 0), "eckey_priv_encode"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECKEY_PUB_DECODE, 0), "eckey_pub_decode"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECKEY_PUB_ENCODE, 0), "eckey_pub_encode"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECKEY_TYPE2PARAM, 0), "eckey_type2param"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECPARAMETERS_PRINT, 0), "ECParameters_print"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECPARAMETERS_PRINT_FP, 0), + "ECParameters_print_fp"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECPKPARAMETERS_PRINT, 0), + "ECPKParameters_print"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECPKPARAMETERS_PRINT_FP, 0), + "ECPKParameters_print_fp"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECP_NISTZ256_GET_AFFINE, 0), + "ecp_nistz256_get_affine"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECP_NISTZ256_INV_MOD_ORD, 0), + "ecp_nistz256_inv_mod_ord"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECP_NISTZ256_MULT_PRECOMPUTE, 0), + "ecp_nistz256_mult_precompute"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECP_NISTZ256_POINTS_MUL, 0), + "ecp_nistz256_points_mul"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECP_NISTZ256_PRE_COMP_NEW, 0), + "ecp_nistz256_pre_comp_new"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECP_NISTZ256_WINDOWED_MUL, 0), + "ecp_nistz256_windowed_mul"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECX_KEY_OP, 0), "ecx_key_op"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECX_PRIV_ENCODE, 0), "ecx_priv_encode"}, + {ERR_PACK(ERR_LIB_EC, EC_F_ECX_PUB_ENCODE, 0), "ecx_pub_encode"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_ASN1_GROUP2CURVE, 0), "ec_asn1_group2curve"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_ASN1_GROUP2FIELDID, 0), + "ec_asn1_group2fieldid"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY, 0), + "ec_GF2m_montgomery_point_multiply"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_FIELD_INV, 0), + "ec_GF2m_simple_field_inv"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT, 0), + "ec_GF2m_simple_group_check_discriminant"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, 0), + "ec_GF2m_simple_group_set_curve"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_LADDER_POST, 0), + "ec_GF2m_simple_ladder_post"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_LADDER_PRE, 0), + "ec_GF2m_simple_ladder_pre"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_OCT2POINT, 0), + "ec_GF2m_simple_oct2point"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_POINT2OCT, 0), + "ec_GF2m_simple_point2oct"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_POINTS_MUL, 0), + "ec_GF2m_simple_points_mul"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, 0), + "ec_GF2m_simple_point_get_affine_coordinates"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES, 0), + "ec_GF2m_simple_point_set_affine_coordinates"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, 0), + "ec_GF2m_simple_set_compressed_coordinates"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_MONT_FIELD_DECODE, 0), + "ec_GFp_mont_field_decode"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_MONT_FIELD_ENCODE, 0), + "ec_GFp_mont_field_encode"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_MONT_FIELD_INV, 0), + "ec_GFp_mont_field_inv"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_MONT_FIELD_MUL, 0), + "ec_GFp_mont_field_mul"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE, 0), + "ec_GFp_mont_field_set_to_one"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_MONT_FIELD_SQR, 0), + "ec_GFp_mont_field_sqr"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_MONT_GROUP_SET_CURVE, 0), + "ec_GFp_mont_group_set_curve"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE, 0), + "ec_GFp_nistp224_group_set_curve"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP224_POINTS_MUL, 0), + "ec_GFp_nistp224_points_mul"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES, 0), + "ec_GFp_nistp224_point_get_affine_coordinates"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE, 0), + "ec_GFp_nistp256_group_set_curve"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP256_POINTS_MUL, 0), + "ec_GFp_nistp256_points_mul"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES, 0), + "ec_GFp_nistp256_point_get_affine_coordinates"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE, 0), + "ec_GFp_nistp521_group_set_curve"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP521_POINTS_MUL, 0), + "ec_GFp_nistp521_points_mul"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES, 0), + "ec_GFp_nistp521_point_get_affine_coordinates"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NIST_FIELD_MUL, 0), + "ec_GFp_nist_field_mul"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NIST_FIELD_SQR, 0), + "ec_GFp_nist_field_sqr"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NIST_GROUP_SET_CURVE, 0), + "ec_GFp_nist_group_set_curve"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES, 0), + "ec_GFp_simple_blind_coordinates"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_FIELD_INV, 0), + "ec_GFp_simple_field_inv"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT, 0), + "ec_GFp_simple_group_check_discriminant"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE, 0), + "ec_GFp_simple_group_set_curve"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_MAKE_AFFINE, 0), + "ec_GFp_simple_make_affine"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_OCT2POINT, 0), + "ec_GFp_simple_oct2point"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_POINT2OCT, 0), + "ec_GFp_simple_point2oct"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE, 0), + "ec_GFp_simple_points_make_affine"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, 0), + "ec_GFp_simple_point_get_affine_coordinates"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES, 0), + "ec_GFp_simple_point_set_affine_coordinates"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, 0), + "ec_GFp_simple_set_compressed_coordinates"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_CHECK, 0), "EC_GROUP_check"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_CHECK_DISCRIMINANT, 0), + "EC_GROUP_check_discriminant"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_COPY, 0), "EC_GROUP_copy"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_CURVE, 0), "EC_GROUP_get_curve"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_CURVE_GF2M, 0), + "EC_GROUP_get_curve_GF2m"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_CURVE_GFP, 0), + "EC_GROUP_get_curve_GFp"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_DEGREE, 0), "EC_GROUP_get_degree"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_ECPARAMETERS, 0), + "EC_GROUP_get_ecparameters"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_ECPKPARAMETERS, 0), + "EC_GROUP_get_ecpkparameters"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS, 0), + "EC_GROUP_get_pentanomial_basis"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_TRINOMIAL_BASIS, 0), + "EC_GROUP_get_trinomial_basis"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_NEW, 0), "EC_GROUP_new"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_NEW_BY_CURVE_NAME, 0), + "EC_GROUP_new_by_curve_name"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_NEW_FROM_DATA, 0), + "ec_group_new_from_data"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, 0), + "EC_GROUP_new_from_ecparameters"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS, 0), + "EC_GROUP_new_from_ecpkparameters"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_SET_CURVE, 0), "EC_GROUP_set_curve"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_SET_CURVE_GF2M, 0), + "EC_GROUP_set_curve_GF2m"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_SET_CURVE_GFP, 0), + "EC_GROUP_set_curve_GFp"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_SET_GENERATOR, 0), + "EC_GROUP_set_generator"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_SET_SEED, 0), "EC_GROUP_set_seed"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_CHECK_KEY, 0), "EC_KEY_check_key"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_COPY, 0), "EC_KEY_copy"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_GENERATE_KEY, 0), "EC_KEY_generate_key"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_NEW, 0), "EC_KEY_new"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_NEW_METHOD, 0), "EC_KEY_new_method"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_OCT2PRIV, 0), "EC_KEY_oct2priv"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_PRINT, 0), "EC_KEY_print"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_PRINT_FP, 0), "EC_KEY_print_fp"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_PRIV2BUF, 0), "EC_KEY_priv2buf"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_PRIV2OCT, 0), "EC_KEY_priv2oct"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES, 0), + "EC_KEY_set_public_key_affine_coordinates"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_SIMPLE_CHECK_KEY, 0), + "ec_key_simple_check_key"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_SIMPLE_OCT2PRIV, 0), + "ec_key_simple_oct2priv"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_SIMPLE_PRIV2OCT, 0), + "ec_key_simple_priv2oct"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_PKEY_CHECK, 0), "ec_pkey_check"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_PKEY_PARAM_CHECK, 0), "ec_pkey_param_check"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINTS_MAKE_AFFINE, 0), + "EC_POINTs_make_affine"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINTS_MUL, 0), "EC_POINTs_mul"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_ADD, 0), "EC_POINT_add"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_BN2POINT, 0), "EC_POINT_bn2point"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_CMP, 0), "EC_POINT_cmp"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_COPY, 0), "EC_POINT_copy"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_DBL, 0), "EC_POINT_dbl"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_GET_AFFINE_COORDINATES, 0), + "EC_POINT_get_affine_coordinates"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, 0), + "EC_POINT_get_affine_coordinates_GF2m"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, 0), + "EC_POINT_get_affine_coordinates_GFp"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, 0), + "EC_POINT_get_Jprojective_coordinates_GFp"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_INVERT, 0), "EC_POINT_invert"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_IS_AT_INFINITY, 0), + "EC_POINT_is_at_infinity"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_IS_ON_CURVE, 0), + "EC_POINT_is_on_curve"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_MAKE_AFFINE, 0), + "EC_POINT_make_affine"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_NEW, 0), "EC_POINT_new"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_OCT2POINT, 0), "EC_POINT_oct2point"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_POINT2BUF, 0), "EC_POINT_point2buf"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_POINT2OCT, 0), "EC_POINT_point2oct"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_AFFINE_COORDINATES, 0), + "EC_POINT_set_affine_coordinates"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, 0), + "EC_POINT_set_affine_coordinates_GF2m"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, 0), + "EC_POINT_set_affine_coordinates_GFp"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_COMPRESSED_COORDINATES, 0), + "EC_POINT_set_compressed_coordinates"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, 0), + "EC_POINT_set_compressed_coordinates_GF2m"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, 0), + "EC_POINT_set_compressed_coordinates_GFp"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, 0), + "EC_POINT_set_Jprojective_coordinates_GFp"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_TO_INFINITY, 0), + "EC_POINT_set_to_infinity"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_PRE_COMP_NEW, 0), "ec_pre_comp_new"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_SCALAR_MUL_LADDER, 0), + "ec_scalar_mul_ladder"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_WNAF_MUL, 0), "ec_wNAF_mul"}, + {ERR_PACK(ERR_LIB_EC, EC_F_EC_WNAF_PRECOMPUTE_MULT, 0), + "ec_wNAF_precompute_mult"}, + {ERR_PACK(ERR_LIB_EC, EC_F_I2D_ECPARAMETERS, 0), "i2d_ECParameters"}, + {ERR_PACK(ERR_LIB_EC, EC_F_I2D_ECPKPARAMETERS, 0), "i2d_ECPKParameters"}, + {ERR_PACK(ERR_LIB_EC, EC_F_I2D_ECPRIVATEKEY, 0), "i2d_ECPrivateKey"}, + {ERR_PACK(ERR_LIB_EC, EC_F_I2O_ECPUBLICKEY, 0), "i2o_ECPublicKey"}, + {ERR_PACK(ERR_LIB_EC, EC_F_NISTP224_PRE_COMP_NEW, 0), + "nistp224_pre_comp_new"}, + {ERR_PACK(ERR_LIB_EC, EC_F_NISTP256_PRE_COMP_NEW, 0), + "nistp256_pre_comp_new"}, + {ERR_PACK(ERR_LIB_EC, EC_F_NISTP521_PRE_COMP_NEW, 0), + "nistp521_pre_comp_new"}, + {ERR_PACK(ERR_LIB_EC, EC_F_O2I_ECPUBLICKEY, 0), "o2i_ECPublicKey"}, + {ERR_PACK(ERR_LIB_EC, EC_F_OLD_EC_PRIV_DECODE, 0), "old_ec_priv_decode"}, + {ERR_PACK(ERR_LIB_EC, EC_F_OSSL_ECDH_COMPUTE_KEY, 0), + "ossl_ecdh_compute_key"}, + {ERR_PACK(ERR_LIB_EC, EC_F_OSSL_ECDSA_SIGN_SIG, 0), "ossl_ecdsa_sign_sig"}, + {ERR_PACK(ERR_LIB_EC, EC_F_OSSL_ECDSA_VERIFY_SIG, 0), + "ossl_ecdsa_verify_sig"}, + {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_ECD_CTRL, 0), "pkey_ecd_ctrl"}, + {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_ECD_DIGESTSIGN, 0), "pkey_ecd_digestsign"}, + {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_ECD_DIGESTSIGN25519, 0), + "pkey_ecd_digestsign25519"}, + {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_ECD_DIGESTSIGN448, 0), + "pkey_ecd_digestsign448"}, + {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_ECX_DERIVE, 0), "pkey_ecx_derive"}, + {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_CTRL, 0), "pkey_ec_ctrl"}, + {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_CTRL_STR, 0), "pkey_ec_ctrl_str"}, + {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_DERIVE, 0), "pkey_ec_derive"}, + {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_INIT, 0), "pkey_ec_init"}, + {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_KDF_DERIVE, 0), "pkey_ec_kdf_derive"}, + {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_KEYGEN, 0), "pkey_ec_keygen"}, + {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_PARAMGEN, 0), "pkey_ec_paramgen"}, + {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_SIGN, 0), "pkey_ec_sign"}, + {ERR_PACK(ERR_LIB_EC, EC_F_VALIDATE_ECX_DERIVE, 0), "validate_ecx_derive"}, + {0, NULL} +}; + +static const ERR_STRING_DATA EC_str_reasons[] = { + {ERR_PACK(ERR_LIB_EC, 0, EC_R_ASN1_ERROR), "asn1 error"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_BAD_SIGNATURE), "bad signature"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_BIGNUM_OUT_OF_RANGE), "bignum out of range"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_BUFFER_TOO_SMALL), "buffer too small"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_CANNOT_INVERT), "cannot invert"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_COORDINATES_OUT_OF_RANGE), + "coordinates out of range"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_CURVE_DOES_NOT_SUPPORT_ECDH), + "curve does not support ecdh"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING), + "curve does not support signing"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_D2I_ECPKPARAMETERS_FAILURE), + "d2i ecpkparameters failure"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_DECODE_ERROR), "decode error"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_DISCRIMINANT_IS_ZERO), + "discriminant is zero"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_EC_GROUP_NEW_BY_NAME_FAILURE), + "ec group new by name failure"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_FIELD_TOO_LARGE), "field too large"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_GF2M_NOT_SUPPORTED), "gf2m not supported"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_GROUP2PKPARAMETERS_FAILURE), + "group2pkparameters failure"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_I2D_ECPKPARAMETERS_FAILURE), + "i2d ecpkparameters failure"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_INCOMPATIBLE_OBJECTS), + "incompatible objects"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_ARGUMENT), "invalid argument"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_COMPRESSED_POINT), + "invalid compressed point"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_COMPRESSION_BIT), + "invalid compression bit"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_CURVE), "invalid curve"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_DIGEST), "invalid digest"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_DIGEST_TYPE), "invalid digest type"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_ENCODING), "invalid encoding"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_FIELD), "invalid field"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_FORM), "invalid form"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_GROUP_ORDER), "invalid group order"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_KEY), "invalid key"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_OUTPUT_LENGTH), + "invalid output length"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_PEER_KEY), "invalid peer key"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_PENTANOMIAL_BASIS), + "invalid pentanomial basis"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_PRIVATE_KEY), "invalid private key"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_TRINOMIAL_BASIS), + "invalid trinomial basis"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_KDF_PARAMETER_ERROR), "kdf parameter error"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_KEYS_NOT_SET), "keys not set"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_LADDER_POST_FAILURE), "ladder post failure"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_LADDER_PRE_FAILURE), "ladder pre failure"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_LADDER_STEP_FAILURE), "ladder step failure"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_MISSING_PARAMETERS), "missing parameters"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_MISSING_PRIVATE_KEY), "missing private key"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_NEED_NEW_SETUP_VALUES), + "need new setup values"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_NOT_A_NIST_PRIME), "not a NIST prime"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_NOT_IMPLEMENTED), "not implemented"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_NOT_INITIALIZED), "not initialized"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_NO_PARAMETERS_SET), "no parameters set"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_NO_PRIVATE_VALUE), "no private value"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_OPERATION_NOT_SUPPORTED), + "operation not supported"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_PASSED_NULL_PARAMETER), + "passed null parameter"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_PEER_KEY_ERROR), "peer key error"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_PKPARAMETERS2GROUP_FAILURE), + "pkparameters2group failure"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_POINT_ARITHMETIC_FAILURE), + "point arithmetic failure"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_POINT_AT_INFINITY), "point at infinity"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_POINT_COORDINATES_BLIND_FAILURE), + "point coordinates blind failure"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_POINT_IS_NOT_ON_CURVE), + "point is not on curve"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_RANDOM_NUMBER_GENERATION_FAILED), + "random number generation failed"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_SHARED_INFO_ERROR), "shared info error"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_SLOT_FULL), "slot full"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_UNDEFINED_GENERATOR), "undefined generator"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_UNDEFINED_ORDER), "undefined order"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_UNKNOWN_COFACTOR), "unknown cofactor"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_UNKNOWN_GROUP), "unknown group"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_UNKNOWN_ORDER), "unknown order"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_UNSUPPORTED_FIELD), "unsupported field"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_WRONG_CURVE_PARAMETERS), + "wrong curve parameters"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_WRONG_ORDER), "wrong order"}, + {0, NULL} +}; + +#endif + +int ERR_load_EC_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(EC_str_functs[0].error) == NULL) { + ERR_load_strings_const(EC_str_functs); + ERR_load_strings_const(EC_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_key.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_key.c new file mode 100644 index 000000000..9349abf03 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_key.c @@ -0,0 +1,618 @@ +/* + * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include +#include "ec_lcl.h" +#include "internal/refcount.h" +#include +#include + +EC_KEY *EC_KEY_new(void) +{ + return EC_KEY_new_method(NULL); +} + +EC_KEY *EC_KEY_new_by_curve_name(int nid) +{ + EC_KEY *ret = EC_KEY_new(); + if (ret == NULL) + return NULL; + ret->group = EC_GROUP_new_by_curve_name(nid); + if (ret->group == NULL) { + EC_KEY_free(ret); + return NULL; + } + if (ret->meth->set_group != NULL + && ret->meth->set_group(ret, ret->group) == 0) { + EC_KEY_free(ret); + return NULL; + } + return ret; +} + +void EC_KEY_free(EC_KEY *r) +{ + int i; + + if (r == NULL) + return; + + CRYPTO_DOWN_REF(&r->references, &i, r->lock); + REF_PRINT_COUNT("EC_KEY", r); + if (i > 0) + return; + REF_ASSERT_ISNT(i < 0); + + if (r->meth != NULL && r->meth->finish != NULL) + r->meth->finish(r); + +#ifndef OPENSSL_NO_ENGINE + ENGINE_finish(r->engine); +#endif + + if (r->group && r->group->meth->keyfinish) + r->group->meth->keyfinish(r); + + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EC_KEY, r, &r->ex_data); + CRYPTO_THREAD_lock_free(r->lock); + EC_GROUP_free(r->group); + EC_POINT_free(r->pub_key); + BN_clear_free(r->priv_key); + + OPENSSL_clear_free((void *)r, sizeof(EC_KEY)); +} + +EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src) +{ + if (dest == NULL || src == NULL) { + ECerr(EC_F_EC_KEY_COPY, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + if (src->meth != dest->meth) { + if (dest->meth->finish != NULL) + dest->meth->finish(dest); + if (dest->group && dest->group->meth->keyfinish) + dest->group->meth->keyfinish(dest); +#ifndef OPENSSL_NO_ENGINE + if (ENGINE_finish(dest->engine) == 0) + return 0; + dest->engine = NULL; +#endif + } + /* copy the parameters */ + if (src->group != NULL) { + const EC_METHOD *meth = EC_GROUP_method_of(src->group); + /* clear the old group */ + EC_GROUP_free(dest->group); + dest->group = EC_GROUP_new(meth); + if (dest->group == NULL) + return NULL; + if (!EC_GROUP_copy(dest->group, src->group)) + return NULL; + + /* copy the public key */ + if (src->pub_key != NULL) { + EC_POINT_free(dest->pub_key); + dest->pub_key = EC_POINT_new(src->group); + if (dest->pub_key == NULL) + return NULL; + if (!EC_POINT_copy(dest->pub_key, src->pub_key)) + return NULL; + } + /* copy the private key */ + if (src->priv_key != NULL) { + if (dest->priv_key == NULL) { + dest->priv_key = BN_new(); + if (dest->priv_key == NULL) + return NULL; + } + if (!BN_copy(dest->priv_key, src->priv_key)) + return NULL; + if (src->group->meth->keycopy + && src->group->meth->keycopy(dest, src) == 0) + return NULL; + } + } + + + /* copy the rest */ + dest->enc_flag = src->enc_flag; + dest->conv_form = src->conv_form; + dest->version = src->version; + dest->flags = src->flags; + if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EC_KEY, + &dest->ex_data, &src->ex_data)) + return NULL; + + if (src->meth != dest->meth) { +#ifndef OPENSSL_NO_ENGINE + if (src->engine != NULL && ENGINE_init(src->engine) == 0) + return NULL; + dest->engine = src->engine; +#endif + dest->meth = src->meth; + } + + if (src->meth->copy != NULL && src->meth->copy(dest, src) == 0) + return NULL; + + return dest; +} + +EC_KEY *EC_KEY_dup(const EC_KEY *ec_key) +{ + EC_KEY *ret = EC_KEY_new_method(ec_key->engine); + + if (ret == NULL) + return NULL; + + if (EC_KEY_copy(ret, ec_key) == NULL) { + EC_KEY_free(ret); + return NULL; + } + return ret; +} + +int EC_KEY_up_ref(EC_KEY *r) +{ + int i; + + if (CRYPTO_UP_REF(&r->references, &i, r->lock) <= 0) + return 0; + + REF_PRINT_COUNT("EC_KEY", r); + REF_ASSERT_ISNT(i < 2); + return ((i > 1) ? 1 : 0); +} + +ENGINE *EC_KEY_get0_engine(const EC_KEY *eckey) +{ + return eckey->engine; +} + +int EC_KEY_generate_key(EC_KEY *eckey) +{ + if (eckey == NULL || eckey->group == NULL) { + ECerr(EC_F_EC_KEY_GENERATE_KEY, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (eckey->meth->keygen != NULL) + return eckey->meth->keygen(eckey); + ECerr(EC_F_EC_KEY_GENERATE_KEY, EC_R_OPERATION_NOT_SUPPORTED); + return 0; +} + +int ossl_ec_key_gen(EC_KEY *eckey) +{ + return eckey->group->meth->keygen(eckey); +} + +int ec_key_simple_generate_key(EC_KEY *eckey) +{ + int ok = 0; + BN_CTX *ctx = NULL; + BIGNUM *priv_key = NULL; + const BIGNUM *order = NULL; + EC_POINT *pub_key = NULL; + + if ((ctx = BN_CTX_new()) == NULL) + goto err; + + if (eckey->priv_key == NULL) { + priv_key = BN_new(); + if (priv_key == NULL) + goto err; + } else + priv_key = eckey->priv_key; + + order = EC_GROUP_get0_order(eckey->group); + if (order == NULL) + goto err; + + do + if (!BN_priv_rand_range(priv_key, order)) + goto err; + while (BN_is_zero(priv_key)) ; + + if (eckey->pub_key == NULL) { + pub_key = EC_POINT_new(eckey->group); + if (pub_key == NULL) + goto err; + } else + pub_key = eckey->pub_key; + + if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, ctx)) + goto err; + + eckey->priv_key = priv_key; + eckey->pub_key = pub_key; + + ok = 1; + + err: + if (eckey->pub_key == NULL) + EC_POINT_free(pub_key); + if (eckey->priv_key != priv_key) + BN_free(priv_key); + BN_CTX_free(ctx); + return ok; +} + +int ec_key_simple_generate_public_key(EC_KEY *eckey) +{ + return EC_POINT_mul(eckey->group, eckey->pub_key, eckey->priv_key, NULL, + NULL, NULL); +} + +int EC_KEY_check_key(const EC_KEY *eckey) +{ + if (eckey == NULL || eckey->group == NULL || eckey->pub_key == NULL) { + ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (eckey->group->meth->keycheck == NULL) { + ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + return eckey->group->meth->keycheck(eckey); +} + +int ec_key_simple_check_key(const EC_KEY *eckey) +{ + int ok = 0; + BN_CTX *ctx = NULL; + const BIGNUM *order = NULL; + EC_POINT *point = NULL; + + if (eckey == NULL || eckey->group == NULL || eckey->pub_key == NULL) { + ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) { + ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_POINT_AT_INFINITY); + goto err; + } + + if ((ctx = BN_CTX_new()) == NULL) + goto err; + if ((point = EC_POINT_new(eckey->group)) == NULL) + goto err; + + /* testing whether the pub_key is on the elliptic curve */ + if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0) { + ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE); + goto err; + } + /* testing whether pub_key * order is the point at infinity */ + order = eckey->group->order; + if (BN_is_zero(order)) { + ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_INVALID_GROUP_ORDER); + goto err; + } + if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx)) { + ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, ERR_R_EC_LIB); + goto err; + } + if (!EC_POINT_is_at_infinity(eckey->group, point)) { + ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_WRONG_ORDER); + goto err; + } + /* + * in case the priv_key is present : check if generator * priv_key == + * pub_key + */ + if (eckey->priv_key != NULL) { + if (BN_cmp(eckey->priv_key, order) >= 0) { + ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_WRONG_ORDER); + goto err; + } + if (!EC_POINT_mul(eckey->group, point, eckey->priv_key, + NULL, NULL, ctx)) { + ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, ERR_R_EC_LIB); + goto err; + } + if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) { + ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_INVALID_PRIVATE_KEY); + goto err; + } + } + ok = 1; + err: + BN_CTX_free(ctx); + EC_POINT_free(point); + return ok; +} + +int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, + BIGNUM *y) +{ + BN_CTX *ctx = NULL; + BIGNUM *tx, *ty; + EC_POINT *point = NULL; + int ok = 0; + + if (key == NULL || key->group == NULL || x == NULL || y == NULL) { + ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + + BN_CTX_start(ctx); + point = EC_POINT_new(key->group); + + if (point == NULL) + goto err; + + tx = BN_CTX_get(ctx); + ty = BN_CTX_get(ctx); + if (ty == NULL) + goto err; + + if (!EC_POINT_set_affine_coordinates(key->group, point, x, y, ctx)) + goto err; + if (!EC_POINT_get_affine_coordinates(key->group, point, tx, ty, ctx)) + goto err; + + /* + * Check if retrieved coordinates match originals and are less than field + * order: if not values are out of range. + */ + if (BN_cmp(x, tx) || BN_cmp(y, ty) + || (BN_cmp(x, key->group->field) >= 0) + || (BN_cmp(y, key->group->field) >= 0)) { + ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES, + EC_R_COORDINATES_OUT_OF_RANGE); + goto err; + } + + if (!EC_KEY_set_public_key(key, point)) + goto err; + + if (EC_KEY_check_key(key) == 0) + goto err; + + ok = 1; + + err: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + EC_POINT_free(point); + return ok; + +} + +const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key) +{ + return key->group; +} + +int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group) +{ + if (key->meth->set_group != NULL && key->meth->set_group(key, group) == 0) + return 0; + EC_GROUP_free(key->group); + key->group = EC_GROUP_dup(group); + return (key->group == NULL) ? 0 : 1; +} + +const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key) +{ + return key->priv_key; +} + +int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key) +{ + if (key->group == NULL || key->group->meth == NULL) + return 0; + if (key->group->meth->set_private != NULL + && key->group->meth->set_private(key, priv_key) == 0) + return 0; + if (key->meth->set_private != NULL + && key->meth->set_private(key, priv_key) == 0) + return 0; + BN_clear_free(key->priv_key); + key->priv_key = BN_dup(priv_key); + return (key->priv_key == NULL) ? 0 : 1; +} + +const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key) +{ + return key->pub_key; +} + +int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key) +{ + if (key->meth->set_public != NULL + && key->meth->set_public(key, pub_key) == 0) + return 0; + EC_POINT_free(key->pub_key); + key->pub_key = EC_POINT_dup(pub_key, key->group); + return (key->pub_key == NULL) ? 0 : 1; +} + +unsigned int EC_KEY_get_enc_flags(const EC_KEY *key) +{ + return key->enc_flag; +} + +void EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags) +{ + key->enc_flag = flags; +} + +point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key) +{ + return key->conv_form; +} + +void EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform) +{ + key->conv_form = cform; + if (key->group != NULL) + EC_GROUP_set_point_conversion_form(key->group, cform); +} + +void EC_KEY_set_asn1_flag(EC_KEY *key, int flag) +{ + if (key->group != NULL) + EC_GROUP_set_asn1_flag(key->group, flag); +} + +int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx) +{ + if (key->group == NULL) + return 0; + return EC_GROUP_precompute_mult(key->group, ctx); +} + +int EC_KEY_get_flags(const EC_KEY *key) +{ + return key->flags; +} + +void EC_KEY_set_flags(EC_KEY *key, int flags) +{ + key->flags |= flags; +} + +void EC_KEY_clear_flags(EC_KEY *key, int flags) +{ + key->flags &= ~flags; +} + +size_t EC_KEY_key2buf(const EC_KEY *key, point_conversion_form_t form, + unsigned char **pbuf, BN_CTX *ctx) +{ + if (key == NULL || key->pub_key == NULL || key->group == NULL) + return 0; + return EC_POINT_point2buf(key->group, key->pub_key, form, pbuf, ctx); +} + +int EC_KEY_oct2key(EC_KEY *key, const unsigned char *buf, size_t len, + BN_CTX *ctx) +{ + if (key == NULL || key->group == NULL) + return 0; + if (key->pub_key == NULL) + key->pub_key = EC_POINT_new(key->group); + if (key->pub_key == NULL) + return 0; + if (EC_POINT_oct2point(key->group, key->pub_key, buf, len, ctx) == 0) + return 0; + /* + * Save the point conversion form. + * For non-custom curves the first octet of the buffer (excluding + * the last significant bit) contains the point conversion form. + * EC_POINT_oct2point() has already performed sanity checking of + * the buffer so we know it is valid. + */ + if ((key->group->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) + key->conv_form = (point_conversion_form_t)(buf[0] & ~0x01); + return 1; +} + +size_t EC_KEY_priv2oct(const EC_KEY *eckey, + unsigned char *buf, size_t len) +{ + if (eckey->group == NULL || eckey->group->meth == NULL) + return 0; + if (eckey->group->meth->priv2oct == NULL) { + ECerr(EC_F_EC_KEY_PRIV2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + return eckey->group->meth->priv2oct(eckey, buf, len); +} + +size_t ec_key_simple_priv2oct(const EC_KEY *eckey, + unsigned char *buf, size_t len) +{ + size_t buf_len; + + buf_len = (EC_GROUP_order_bits(eckey->group) + 7) / 8; + if (eckey->priv_key == NULL) + return 0; + if (buf == NULL) + return buf_len; + else if (len < buf_len) + return 0; + + /* Octetstring may need leading zeros if BN is to short */ + + if (BN_bn2binpad(eckey->priv_key, buf, buf_len) == -1) { + ECerr(EC_F_EC_KEY_SIMPLE_PRIV2OCT, EC_R_BUFFER_TOO_SMALL); + return 0; + } + + return buf_len; +} + +int EC_KEY_oct2priv(EC_KEY *eckey, const unsigned char *buf, size_t len) +{ + if (eckey->group == NULL || eckey->group->meth == NULL) + return 0; + if (eckey->group->meth->oct2priv == NULL) { + ECerr(EC_F_EC_KEY_OCT2PRIV, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + return eckey->group->meth->oct2priv(eckey, buf, len); +} + +int ec_key_simple_oct2priv(EC_KEY *eckey, const unsigned char *buf, size_t len) +{ + if (eckey->priv_key == NULL) + eckey->priv_key = BN_secure_new(); + if (eckey->priv_key == NULL) { + ECerr(EC_F_EC_KEY_SIMPLE_OCT2PRIV, ERR_R_MALLOC_FAILURE); + return 0; + } + eckey->priv_key = BN_bin2bn(buf, len, eckey->priv_key); + if (eckey->priv_key == NULL) { + ECerr(EC_F_EC_KEY_SIMPLE_OCT2PRIV, ERR_R_BN_LIB); + return 0; + } + return 1; +} + +size_t EC_KEY_priv2buf(const EC_KEY *eckey, unsigned char **pbuf) +{ + size_t len; + unsigned char *buf; + + len = EC_KEY_priv2oct(eckey, NULL, 0); + if (len == 0) + return 0; + if ((buf = OPENSSL_malloc(len)) == NULL) { + ECerr(EC_F_EC_KEY_PRIV2BUF, ERR_R_MALLOC_FAILURE); + return 0; + } + len = EC_KEY_priv2oct(eckey, buf, len); + if (len == 0) { + OPENSSL_free(buf); + return 0; + } + *pbuf = buf; + return len; +} + +int EC_KEY_can_sign(const EC_KEY *eckey) +{ + if (eckey->group == NULL || eckey->group->meth == NULL + || (eckey->group->meth->flags & EC_FLAGS_NO_SIGN)) + return 0; + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_kmeth.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_kmeth.c new file mode 100644 index 000000000..64a5d2087 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_kmeth.c @@ -0,0 +1,317 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include "ec_lcl.h" + + +static const EC_KEY_METHOD openssl_ec_key_method = { + "OpenSSL EC_KEY method", + 0, + 0,0,0,0,0,0, + ossl_ec_key_gen, + ossl_ecdh_compute_key, + ossl_ecdsa_sign, + ossl_ecdsa_sign_setup, + ossl_ecdsa_sign_sig, + ossl_ecdsa_verify, + ossl_ecdsa_verify_sig +}; + +static const EC_KEY_METHOD *default_ec_key_meth = &openssl_ec_key_method; + +const EC_KEY_METHOD *EC_KEY_OpenSSL(void) +{ + return &openssl_ec_key_method; +} + +const EC_KEY_METHOD *EC_KEY_get_default_method(void) +{ + return default_ec_key_meth; +} + +void EC_KEY_set_default_method(const EC_KEY_METHOD *meth) +{ + if (meth == NULL) + default_ec_key_meth = &openssl_ec_key_method; + else + default_ec_key_meth = meth; +} + +const EC_KEY_METHOD *EC_KEY_get_method(const EC_KEY *key) +{ + return key->meth; +} + +int EC_KEY_set_method(EC_KEY *key, const EC_KEY_METHOD *meth) +{ + void (*finish)(EC_KEY *key) = key->meth->finish; + + if (finish != NULL) + finish(key); + +#ifndef OPENSSL_NO_ENGINE + ENGINE_finish(key->engine); + key->engine = NULL; +#endif + + key->meth = meth; + if (meth->init != NULL) + return meth->init(key); + return 1; +} + +EC_KEY *EC_KEY_new_method(ENGINE *engine) +{ + EC_KEY *ret = OPENSSL_zalloc(sizeof(*ret)); + + if (ret == NULL) { + ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_MALLOC_FAILURE); + return NULL; + } + + ret->references = 1; + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) { + ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ret); + return NULL; + } + + ret->meth = EC_KEY_get_default_method(); +#ifndef OPENSSL_NO_ENGINE + if (engine != NULL) { + if (!ENGINE_init(engine)) { + ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_ENGINE_LIB); + goto err; + } + ret->engine = engine; + } else + ret->engine = ENGINE_get_default_EC(); + if (ret->engine != NULL) { + ret->meth = ENGINE_get_EC(ret->engine); + if (ret->meth == NULL) { + ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_ENGINE_LIB); + goto err; + } + } +#endif + + ret->version = 1; + ret->conv_form = POINT_CONVERSION_UNCOMPRESSED; + + if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_EC_KEY, ret, &ret->ex_data)) { + goto err; + } + + if (ret->meth->init != NULL && ret->meth->init(ret) == 0) { + ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_INIT_FAIL); + goto err; + } + return ret; + + err: + EC_KEY_free(ret); + return NULL; +} + +int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, + const EC_KEY *eckey, + void *(*KDF) (const void *in, size_t inlen, void *out, + size_t *outlen)) +{ + unsigned char *sec = NULL; + size_t seclen; + if (eckey->meth->compute_key == NULL) { + ECerr(EC_F_ECDH_COMPUTE_KEY, EC_R_OPERATION_NOT_SUPPORTED); + return 0; + } + if (outlen > INT_MAX) { + ECerr(EC_F_ECDH_COMPUTE_KEY, EC_R_INVALID_OUTPUT_LENGTH); + return 0; + } + if (!eckey->meth->compute_key(&sec, &seclen, pub_key, eckey)) + return 0; + if (KDF != NULL) { + KDF(sec, seclen, out, &outlen); + } else { + if (outlen > seclen) + outlen = seclen; + memcpy(out, sec, outlen); + } + OPENSSL_clear_free(sec, seclen); + return outlen; +} + +EC_KEY_METHOD *EC_KEY_METHOD_new(const EC_KEY_METHOD *meth) +{ + EC_KEY_METHOD *ret = OPENSSL_zalloc(sizeof(*meth)); + + if (ret == NULL) + return NULL; + if (meth != NULL) + *ret = *meth; + ret->flags |= EC_KEY_METHOD_DYNAMIC; + return ret; +} + +void EC_KEY_METHOD_free(EC_KEY_METHOD *meth) +{ + if (meth->flags & EC_KEY_METHOD_DYNAMIC) + OPENSSL_free(meth); +} + +void EC_KEY_METHOD_set_init(EC_KEY_METHOD *meth, + int (*init)(EC_KEY *key), + void (*finish)(EC_KEY *key), + int (*copy)(EC_KEY *dest, const EC_KEY *src), + int (*set_group)(EC_KEY *key, const EC_GROUP *grp), + int (*set_private)(EC_KEY *key, + const BIGNUM *priv_key), + int (*set_public)(EC_KEY *key, + const EC_POINT *pub_key)) +{ + meth->init = init; + meth->finish = finish; + meth->copy = copy; + meth->set_group = set_group; + meth->set_private = set_private; + meth->set_public = set_public; +} + +void EC_KEY_METHOD_set_keygen(EC_KEY_METHOD *meth, + int (*keygen)(EC_KEY *key)) +{ + meth->keygen = keygen; +} + +void EC_KEY_METHOD_set_compute_key(EC_KEY_METHOD *meth, + int (*ckey)(unsigned char **psec, + size_t *pseclen, + const EC_POINT *pub_key, + const EC_KEY *ecdh)) +{ + meth->compute_key = ckey; +} + +void EC_KEY_METHOD_set_sign(EC_KEY_METHOD *meth, + int (*sign)(int type, const unsigned char *dgst, + int dlen, unsigned char *sig, + unsigned int *siglen, + const BIGNUM *kinv, const BIGNUM *r, + EC_KEY *eckey), + int (*sign_setup)(EC_KEY *eckey, BN_CTX *ctx_in, + BIGNUM **kinvp, BIGNUM **rp), + ECDSA_SIG *(*sign_sig)(const unsigned char *dgst, + int dgst_len, + const BIGNUM *in_kinv, + const BIGNUM *in_r, + EC_KEY *eckey)) +{ + meth->sign = sign; + meth->sign_setup = sign_setup; + meth->sign_sig = sign_sig; +} + +void EC_KEY_METHOD_set_verify(EC_KEY_METHOD *meth, + int (*verify)(int type, const unsigned + char *dgst, int dgst_len, + const unsigned char *sigbuf, + int sig_len, EC_KEY *eckey), + int (*verify_sig)(const unsigned char *dgst, + int dgst_len, + const ECDSA_SIG *sig, + EC_KEY *eckey)) +{ + meth->verify = verify; + meth->verify_sig = verify_sig; +} + +void EC_KEY_METHOD_get_init(const EC_KEY_METHOD *meth, + int (**pinit)(EC_KEY *key), + void (**pfinish)(EC_KEY *key), + int (**pcopy)(EC_KEY *dest, const EC_KEY *src), + int (**pset_group)(EC_KEY *key, + const EC_GROUP *grp), + int (**pset_private)(EC_KEY *key, + const BIGNUM *priv_key), + int (**pset_public)(EC_KEY *key, + const EC_POINT *pub_key)) +{ + if (pinit != NULL) + *pinit = meth->init; + if (pfinish != NULL) + *pfinish = meth->finish; + if (pcopy != NULL) + *pcopy = meth->copy; + if (pset_group != NULL) + *pset_group = meth->set_group; + if (pset_private != NULL) + *pset_private = meth->set_private; + if (pset_public != NULL) + *pset_public = meth->set_public; +} + +void EC_KEY_METHOD_get_keygen(const EC_KEY_METHOD *meth, + int (**pkeygen)(EC_KEY *key)) +{ + if (pkeygen != NULL) + *pkeygen = meth->keygen; +} + +void EC_KEY_METHOD_get_compute_key(const EC_KEY_METHOD *meth, + int (**pck)(unsigned char **pout, + size_t *poutlen, + const EC_POINT *pub_key, + const EC_KEY *ecdh)) +{ + if (pck != NULL) + *pck = meth->compute_key; +} + +void EC_KEY_METHOD_get_sign(const EC_KEY_METHOD *meth, + int (**psign)(int type, const unsigned char *dgst, + int dlen, unsigned char *sig, + unsigned int *siglen, + const BIGNUM *kinv, const BIGNUM *r, + EC_KEY *eckey), + int (**psign_setup)(EC_KEY *eckey, BN_CTX *ctx_in, + BIGNUM **kinvp, BIGNUM **rp), + ECDSA_SIG *(**psign_sig)(const unsigned char *dgst, + int dgst_len, + const BIGNUM *in_kinv, + const BIGNUM *in_r, + EC_KEY *eckey)) +{ + if (psign != NULL) + *psign = meth->sign; + if (psign_setup != NULL) + *psign_setup = meth->sign_setup; + if (psign_sig != NULL) + *psign_sig = meth->sign_sig; +} + +void EC_KEY_METHOD_get_verify(const EC_KEY_METHOD *meth, + int (**pverify)(int type, const unsigned + char *dgst, int dgst_len, + const unsigned char *sigbuf, + int sig_len, EC_KEY *eckey), + int (**pverify_sig)(const unsigned char *dgst, + int dgst_len, + const ECDSA_SIG *sig, + EC_KEY *eckey)) +{ + if (pverify != NULL) + *pverify = meth->verify; + if (pverify_sig != NULL) + *pverify_sig = meth->verify_sig; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_lcl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_lcl.h new file mode 100644 index 000000000..119255f1d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_lcl.h @@ -0,0 +1,737 @@ +/* + * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#include +#include +#include +#include "internal/refcount.h" +#include "internal/ec_int.h" + +#if defined(__SUNPRO_C) +# if __SUNPRO_C >= 0x520 +# pragma error_messages (off,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE) +# endif +#endif + +/* Use default functions for poin2oct, oct2point and compressed coordinates */ +#define EC_FLAGS_DEFAULT_OCT 0x1 + +/* Use custom formats for EC_GROUP, EC_POINT and EC_KEY */ +#define EC_FLAGS_CUSTOM_CURVE 0x2 + +/* Curve does not support signing operations */ +#define EC_FLAGS_NO_SIGN 0x4 + +/* + * Structure details are not part of the exported interface, so all this may + * change in future versions. + */ + +struct ec_method_st { + /* Various method flags */ + int flags; + /* used by EC_METHOD_get_field_type: */ + int field_type; /* a NID */ + /* + * used by EC_GROUP_new, EC_GROUP_free, EC_GROUP_clear_free, + * EC_GROUP_copy: + */ + int (*group_init) (EC_GROUP *); + void (*group_finish) (EC_GROUP *); + void (*group_clear_finish) (EC_GROUP *); + int (*group_copy) (EC_GROUP *, const EC_GROUP *); + /* used by EC_GROUP_set_curve, EC_GROUP_get_curve: */ + int (*group_set_curve) (EC_GROUP *, const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); + int (*group_get_curve) (const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, + BN_CTX *); + /* used by EC_GROUP_get_degree: */ + int (*group_get_degree) (const EC_GROUP *); + int (*group_order_bits) (const EC_GROUP *); + /* used by EC_GROUP_check: */ + int (*group_check_discriminant) (const EC_GROUP *, BN_CTX *); + /* + * used by EC_POINT_new, EC_POINT_free, EC_POINT_clear_free, + * EC_POINT_copy: + */ + int (*point_init) (EC_POINT *); + void (*point_finish) (EC_POINT *); + void (*point_clear_finish) (EC_POINT *); + int (*point_copy) (EC_POINT *, const EC_POINT *); + /*- + * used by EC_POINT_set_to_infinity, + * EC_POINT_set_Jprojective_coordinates_GFp, + * EC_POINT_get_Jprojective_coordinates_GFp, + * EC_POINT_set_affine_coordinates, + * EC_POINT_get_affine_coordinates, + * EC_POINT_set_compressed_coordinates: + */ + int (*point_set_to_infinity) (const EC_GROUP *, EC_POINT *); + int (*point_set_Jprojective_coordinates_GFp) (const EC_GROUP *, + EC_POINT *, const BIGNUM *x, + const BIGNUM *y, + const BIGNUM *z, BN_CTX *); + int (*point_get_Jprojective_coordinates_GFp) (const EC_GROUP *, + const EC_POINT *, BIGNUM *x, + BIGNUM *y, BIGNUM *z, + BN_CTX *); + int (*point_set_affine_coordinates) (const EC_GROUP *, EC_POINT *, + const BIGNUM *x, const BIGNUM *y, + BN_CTX *); + int (*point_get_affine_coordinates) (const EC_GROUP *, const EC_POINT *, + BIGNUM *x, BIGNUM *y, BN_CTX *); + int (*point_set_compressed_coordinates) (const EC_GROUP *, EC_POINT *, + const BIGNUM *x, int y_bit, + BN_CTX *); + /* used by EC_POINT_point2oct, EC_POINT_oct2point: */ + size_t (*point2oct) (const EC_GROUP *, const EC_POINT *, + point_conversion_form_t form, unsigned char *buf, + size_t len, BN_CTX *); + int (*oct2point) (const EC_GROUP *, EC_POINT *, const unsigned char *buf, + size_t len, BN_CTX *); + /* used by EC_POINT_add, EC_POINT_dbl, ECP_POINT_invert: */ + int (*add) (const EC_GROUP *, EC_POINT *r, const EC_POINT *a, + const EC_POINT *b, BN_CTX *); + int (*dbl) (const EC_GROUP *, EC_POINT *r, const EC_POINT *a, BN_CTX *); + int (*invert) (const EC_GROUP *, EC_POINT *, BN_CTX *); + /* + * used by EC_POINT_is_at_infinity, EC_POINT_is_on_curve, EC_POINT_cmp: + */ + int (*is_at_infinity) (const EC_GROUP *, const EC_POINT *); + int (*is_on_curve) (const EC_GROUP *, const EC_POINT *, BN_CTX *); + int (*point_cmp) (const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, + BN_CTX *); + /* used by EC_POINT_make_affine, EC_POINTs_make_affine: */ + int (*make_affine) (const EC_GROUP *, EC_POINT *, BN_CTX *); + int (*points_make_affine) (const EC_GROUP *, size_t num, EC_POINT *[], + BN_CTX *); + /* + * used by EC_POINTs_mul, EC_POINT_mul, EC_POINT_precompute_mult, + * EC_POINT_have_precompute_mult (default implementations are used if the + * 'mul' pointer is 0): + */ + /*- + * mul() calculates the value + * + * r := generator * scalar + * + points[0] * scalars[0] + * + ... + * + points[num-1] * scalars[num-1]. + * + * For a fixed point multiplication (scalar != NULL, num == 0) + * or a variable point multiplication (scalar == NULL, num == 1), + * mul() must use a constant time algorithm: in both cases callers + * should provide an input scalar (either scalar or scalars[0]) + * in the range [0, ec_group_order); for robustness, implementers + * should handle the case when the scalar has not been reduced, but + * may treat it as an unusual input, without any constant-timeness + * guarantee. + */ + int (*mul) (const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, + size_t num, const EC_POINT *points[], const BIGNUM *scalars[], + BN_CTX *); + int (*precompute_mult) (EC_GROUP *group, BN_CTX *); + int (*have_precompute_mult) (const EC_GROUP *group); + /* internal functions */ + /* + * 'field_mul', 'field_sqr', and 'field_div' can be used by 'add' and + * 'dbl' so that the same implementations of point operations can be used + * with different optimized implementations of expensive field + * operations: + */ + int (*field_mul) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); + int (*field_sqr) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); + int (*field_div) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); + /*- + * 'field_inv' computes the multipicative inverse of a in the field, + * storing the result in r. + * + * If 'a' is zero (or equivalent), you'll get an EC_R_CANNOT_INVERT error. + */ + int (*field_inv) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); + /* e.g. to Montgomery */ + int (*field_encode) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); + /* e.g. from Montgomery */ + int (*field_decode) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); + int (*field_set_to_one) (const EC_GROUP *, BIGNUM *r, BN_CTX *); + /* private key operations */ + size_t (*priv2oct)(const EC_KEY *eckey, unsigned char *buf, size_t len); + int (*oct2priv)(EC_KEY *eckey, const unsigned char *buf, size_t len); + int (*set_private)(EC_KEY *eckey, const BIGNUM *priv_key); + int (*keygen)(EC_KEY *eckey); + int (*keycheck)(const EC_KEY *eckey); + int (*keygenpub)(EC_KEY *eckey); + int (*keycopy)(EC_KEY *dst, const EC_KEY *src); + void (*keyfinish)(EC_KEY *eckey); + /* custom ECDH operation */ + int (*ecdh_compute_key)(unsigned char **pout, size_t *poutlen, + const EC_POINT *pub_key, const EC_KEY *ecdh); + /* Inverse modulo order */ + int (*field_inverse_mod_ord)(const EC_GROUP *, BIGNUM *r, + const BIGNUM *x, BN_CTX *); + int (*blind_coordinates)(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx); + int (*ladder_pre)(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx); + int (*ladder_step)(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx); + int (*ladder_post)(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx); +}; + +/* + * Types and functions to manipulate pre-computed values. + */ +typedef struct nistp224_pre_comp_st NISTP224_PRE_COMP; +typedef struct nistp256_pre_comp_st NISTP256_PRE_COMP; +typedef struct nistp521_pre_comp_st NISTP521_PRE_COMP; +typedef struct nistz256_pre_comp_st NISTZ256_PRE_COMP; +typedef struct ec_pre_comp_st EC_PRE_COMP; + +struct ec_group_st { + const EC_METHOD *meth; + EC_POINT *generator; /* optional */ + BIGNUM *order, *cofactor; + int curve_name; /* optional NID for named curve */ + int asn1_flag; /* flag to control the asn1 encoding */ + point_conversion_form_t asn1_form; + unsigned char *seed; /* optional seed for parameters (appears in + * ASN1) */ + size_t seed_len; + /* + * The following members are handled by the method functions, even if + * they appear generic + */ + /* + * Field specification. For curves over GF(p), this is the modulus; for + * curves over GF(2^m), this is the irreducible polynomial defining the + * field. + */ + BIGNUM *field; + /* + * Field specification for curves over GF(2^m). The irreducible f(t) is + * then of the form: t^poly[0] + t^poly[1] + ... + t^poly[k] where m = + * poly[0] > poly[1] > ... > poly[k] = 0. The array is terminated with + * poly[k+1]=-1. All elliptic curve irreducibles have at most 5 non-zero + * terms. + */ + int poly[6]; + /* + * Curve coefficients. (Here the assumption is that BIGNUMs can be used + * or abused for all kinds of fields, not just GF(p).) For characteristic + * > 3, the curve is defined by a Weierstrass equation of the form y^2 = + * x^3 + a*x + b. For characteristic 2, the curve is defined by an + * equation of the form y^2 + x*y = x^3 + a*x^2 + b. + */ + BIGNUM *a, *b; + /* enable optimized point arithmetics for special case */ + int a_is_minus3; + /* method-specific (e.g., Montgomery structure) */ + void *field_data1; + /* method-specific */ + void *field_data2; + /* method-specific */ + int (*field_mod_func) (BIGNUM *, const BIGNUM *, const BIGNUM *, + BN_CTX *); + /* data for ECDSA inverse */ + BN_MONT_CTX *mont_data; + + /* + * Precomputed values for speed. The PCT_xxx names match the + * pre_comp.xxx union names; see the SETPRECOMP and HAVEPRECOMP + * macros, below. + */ + enum { + PCT_none, + PCT_nistp224, PCT_nistp256, PCT_nistp521, PCT_nistz256, + PCT_ec + } pre_comp_type; + union { + NISTP224_PRE_COMP *nistp224; + NISTP256_PRE_COMP *nistp256; + NISTP521_PRE_COMP *nistp521; + NISTZ256_PRE_COMP *nistz256; + EC_PRE_COMP *ec; + } pre_comp; +}; + +#define SETPRECOMP(g, type, pre) \ + g->pre_comp_type = PCT_##type, g->pre_comp.type = pre +#define HAVEPRECOMP(g, type) \ + g->pre_comp_type == PCT_##type && g->pre_comp.type != NULL + +struct ec_key_st { + const EC_KEY_METHOD *meth; + ENGINE *engine; + int version; + EC_GROUP *group; + EC_POINT *pub_key; + BIGNUM *priv_key; + unsigned int enc_flag; + point_conversion_form_t conv_form; + CRYPTO_REF_COUNT references; + int flags; + CRYPTO_EX_DATA ex_data; + CRYPTO_RWLOCK *lock; +}; + +struct ec_point_st { + const EC_METHOD *meth; + /* NID for the curve if known */ + int curve_name; + /* + * All members except 'meth' are handled by the method functions, even if + * they appear generic + */ + BIGNUM *X; + BIGNUM *Y; + BIGNUM *Z; /* Jacobian projective coordinates: * (X, Y, + * Z) represents (X/Z^2, Y/Z^3) if Z != 0 */ + int Z_is_one; /* enable optimized point arithmetics for + * special case */ +}; + +static ossl_inline int ec_point_is_compat(const EC_POINT *point, + const EC_GROUP *group) +{ + if (group->meth != point->meth + || (group->curve_name != 0 + && point->curve_name != 0 + && group->curve_name != point->curve_name)) + return 0; + + return 1; +} + +NISTP224_PRE_COMP *EC_nistp224_pre_comp_dup(NISTP224_PRE_COMP *); +NISTP256_PRE_COMP *EC_nistp256_pre_comp_dup(NISTP256_PRE_COMP *); +NISTP521_PRE_COMP *EC_nistp521_pre_comp_dup(NISTP521_PRE_COMP *); +NISTZ256_PRE_COMP *EC_nistz256_pre_comp_dup(NISTZ256_PRE_COMP *); +NISTP256_PRE_COMP *EC_nistp256_pre_comp_dup(NISTP256_PRE_COMP *); +EC_PRE_COMP *EC_ec_pre_comp_dup(EC_PRE_COMP *); + +void EC_pre_comp_free(EC_GROUP *group); +void EC_nistp224_pre_comp_free(NISTP224_PRE_COMP *); +void EC_nistp256_pre_comp_free(NISTP256_PRE_COMP *); +void EC_nistp521_pre_comp_free(NISTP521_PRE_COMP *); +void EC_nistz256_pre_comp_free(NISTZ256_PRE_COMP *); +void EC_ec_pre_comp_free(EC_PRE_COMP *); + +/* + * method functions in ec_mult.c (ec_lib.c uses these as defaults if + * group->method->mul is 0) + */ +int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, + size_t num, const EC_POINT *points[], const BIGNUM *scalars[], + BN_CTX *); +int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *); +int ec_wNAF_have_precompute_mult(const EC_GROUP *group); + +/* method functions in ecp_smpl.c */ +int ec_GFp_simple_group_init(EC_GROUP *); +void ec_GFp_simple_group_finish(EC_GROUP *); +void ec_GFp_simple_group_clear_finish(EC_GROUP *); +int ec_GFp_simple_group_copy(EC_GROUP *, const EC_GROUP *); +int ec_GFp_simple_group_set_curve(EC_GROUP *, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *b, BN_CTX *); +int ec_GFp_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a, + BIGNUM *b, BN_CTX *); +int ec_GFp_simple_group_get_degree(const EC_GROUP *); +int ec_GFp_simple_group_check_discriminant(const EC_GROUP *, BN_CTX *); +int ec_GFp_simple_point_init(EC_POINT *); +void ec_GFp_simple_point_finish(EC_POINT *); +void ec_GFp_simple_point_clear_finish(EC_POINT *); +int ec_GFp_simple_point_copy(EC_POINT *, const EC_POINT *); +int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *); +int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *, + EC_POINT *, const BIGNUM *x, + const BIGNUM *y, + const BIGNUM *z, BN_CTX *); +int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *, + const EC_POINT *, BIGNUM *x, + BIGNUM *y, BIGNUM *z, + BN_CTX *); +int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *, EC_POINT *, + const BIGNUM *x, + const BIGNUM *y, BN_CTX *); +int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *, + const EC_POINT *, BIGNUM *x, + BIGNUM *y, BN_CTX *); +int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *, + const BIGNUM *x, int y_bit, + BN_CTX *); +size_t ec_GFp_simple_point2oct(const EC_GROUP *, const EC_POINT *, + point_conversion_form_t form, + unsigned char *buf, size_t len, BN_CTX *); +int ec_GFp_simple_oct2point(const EC_GROUP *, EC_POINT *, + const unsigned char *buf, size_t len, BN_CTX *); +int ec_GFp_simple_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, + const EC_POINT *b, BN_CTX *); +int ec_GFp_simple_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, + BN_CTX *); +int ec_GFp_simple_invert(const EC_GROUP *, EC_POINT *, BN_CTX *); +int ec_GFp_simple_is_at_infinity(const EC_GROUP *, const EC_POINT *); +int ec_GFp_simple_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *); +int ec_GFp_simple_cmp(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, + BN_CTX *); +int ec_GFp_simple_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *); +int ec_GFp_simple_points_make_affine(const EC_GROUP *, size_t num, + EC_POINT *[], BN_CTX *); +int ec_GFp_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); +int ec_GFp_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); +int ec_GFp_simple_field_inv(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); +int ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p, + BN_CTX *ctx); +int ec_GFp_simple_ladder_pre(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx); +int ec_GFp_simple_ladder_step(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx); +int ec_GFp_simple_ladder_post(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx); + +/* method functions in ecp_mont.c */ +int ec_GFp_mont_group_init(EC_GROUP *); +int ec_GFp_mont_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); +void ec_GFp_mont_group_finish(EC_GROUP *); +void ec_GFp_mont_group_clear_finish(EC_GROUP *); +int ec_GFp_mont_group_copy(EC_GROUP *, const EC_GROUP *); +int ec_GFp_mont_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); +int ec_GFp_mont_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); +int ec_GFp_mont_field_inv(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); +int ec_GFp_mont_field_encode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); +int ec_GFp_mont_field_decode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); +int ec_GFp_mont_field_set_to_one(const EC_GROUP *, BIGNUM *r, BN_CTX *); + +/* method functions in ecp_nist.c */ +int ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src); +int ec_GFp_nist_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); +int ec_GFp_nist_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); +int ec_GFp_nist_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); + +/* method functions in ec2_smpl.c */ +int ec_GF2m_simple_group_init(EC_GROUP *); +void ec_GF2m_simple_group_finish(EC_GROUP *); +void ec_GF2m_simple_group_clear_finish(EC_GROUP *); +int ec_GF2m_simple_group_copy(EC_GROUP *, const EC_GROUP *); +int ec_GF2m_simple_group_set_curve(EC_GROUP *, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *b, + BN_CTX *); +int ec_GF2m_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a, + BIGNUM *b, BN_CTX *); +int ec_GF2m_simple_group_get_degree(const EC_GROUP *); +int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *, BN_CTX *); +int ec_GF2m_simple_point_init(EC_POINT *); +void ec_GF2m_simple_point_finish(EC_POINT *); +void ec_GF2m_simple_point_clear_finish(EC_POINT *); +int ec_GF2m_simple_point_copy(EC_POINT *, const EC_POINT *); +int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *); +int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *, EC_POINT *, + const BIGNUM *x, + const BIGNUM *y, BN_CTX *); +int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *, + const EC_POINT *, BIGNUM *x, + BIGNUM *y, BN_CTX *); +int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *, + const BIGNUM *x, int y_bit, + BN_CTX *); +size_t ec_GF2m_simple_point2oct(const EC_GROUP *, const EC_POINT *, + point_conversion_form_t form, + unsigned char *buf, size_t len, BN_CTX *); +int ec_GF2m_simple_oct2point(const EC_GROUP *, EC_POINT *, + const unsigned char *buf, size_t len, BN_CTX *); +int ec_GF2m_simple_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, + const EC_POINT *b, BN_CTX *); +int ec_GF2m_simple_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, + BN_CTX *); +int ec_GF2m_simple_invert(const EC_GROUP *, EC_POINT *, BN_CTX *); +int ec_GF2m_simple_is_at_infinity(const EC_GROUP *, const EC_POINT *); +int ec_GF2m_simple_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *); +int ec_GF2m_simple_cmp(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, + BN_CTX *); +int ec_GF2m_simple_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *); +int ec_GF2m_simple_points_make_affine(const EC_GROUP *, size_t num, + EC_POINT *[], BN_CTX *); +int ec_GF2m_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); +int ec_GF2m_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); +int ec_GF2m_simple_field_div(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); + +#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 +/* method functions in ecp_nistp224.c */ +int ec_GFp_nistp224_group_init(EC_GROUP *group); +int ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *n, + BN_CTX *); +int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx); +int ec_GFp_nistp224_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], const BIGNUM *scalars[], + BN_CTX *); +int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], + const BIGNUM *scalars[], BN_CTX *ctx); +int ec_GFp_nistp224_precompute_mult(EC_GROUP *group, BN_CTX *ctx); +int ec_GFp_nistp224_have_precompute_mult(const EC_GROUP *group); + +/* method functions in ecp_nistp256.c */ +int ec_GFp_nistp256_group_init(EC_GROUP *group); +int ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *n, + BN_CTX *); +int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx); +int ec_GFp_nistp256_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], const BIGNUM *scalars[], + BN_CTX *); +int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], + const BIGNUM *scalars[], BN_CTX *ctx); +int ec_GFp_nistp256_precompute_mult(EC_GROUP *group, BN_CTX *ctx); +int ec_GFp_nistp256_have_precompute_mult(const EC_GROUP *group); + +/* method functions in ecp_nistp521.c */ +int ec_GFp_nistp521_group_init(EC_GROUP *group); +int ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *n, + BN_CTX *); +int ec_GFp_nistp521_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx); +int ec_GFp_nistp521_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], const BIGNUM *scalars[], + BN_CTX *); +int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], + const BIGNUM *scalars[], BN_CTX *ctx); +int ec_GFp_nistp521_precompute_mult(EC_GROUP *group, BN_CTX *ctx); +int ec_GFp_nistp521_have_precompute_mult(const EC_GROUP *group); + +/* utility functions in ecp_nistputil.c */ +void ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array, + size_t felem_size, + void *tmp_felems, + void (*felem_one) (void *out), + int (*felem_is_zero) (const void + *in), + void (*felem_assign) (void *out, + const void + *in), + void (*felem_square) (void *out, + const void + *in), + void (*felem_mul) (void *out, + const void + *in1, + const void + *in2), + void (*felem_inv) (void *out, + const void + *in), + void (*felem_contract) (void + *out, + const + void + *in)); +void ec_GFp_nistp_recode_scalar_bits(unsigned char *sign, + unsigned char *digit, unsigned char in); +#endif +int ec_group_simple_order_bits(const EC_GROUP *group); + +#ifdef ECP_NISTZ256_ASM +/** Returns GFp methods using montgomery multiplication, with x86-64 optimized + * P256. See http://eprint.iacr.org/2013/816. + * \return EC_METHOD object + */ +const EC_METHOD *EC_GFp_nistz256_method(void); +#endif + +size_t ec_key_simple_priv2oct(const EC_KEY *eckey, + unsigned char *buf, size_t len); +int ec_key_simple_oct2priv(EC_KEY *eckey, const unsigned char *buf, size_t len); +int ec_key_simple_generate_key(EC_KEY *eckey); +int ec_key_simple_generate_public_key(EC_KEY *eckey); +int ec_key_simple_check_key(const EC_KEY *eckey); + +/* EC_METHOD definitions */ + +struct ec_key_method_st { + const char *name; + int32_t flags; + int (*init)(EC_KEY *key); + void (*finish)(EC_KEY *key); + int (*copy)(EC_KEY *dest, const EC_KEY *src); + int (*set_group)(EC_KEY *key, const EC_GROUP *grp); + int (*set_private)(EC_KEY *key, const BIGNUM *priv_key); + int (*set_public)(EC_KEY *key, const EC_POINT *pub_key); + int (*keygen)(EC_KEY *key); + int (*compute_key)(unsigned char **pout, size_t *poutlen, + const EC_POINT *pub_key, const EC_KEY *ecdh); + int (*sign)(int type, const unsigned char *dgst, int dlen, unsigned char + *sig, unsigned int *siglen, const BIGNUM *kinv, + const BIGNUM *r, EC_KEY *eckey); + int (*sign_setup)(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, + BIGNUM **rp); + ECDSA_SIG *(*sign_sig)(const unsigned char *dgst, int dgst_len, + const BIGNUM *in_kinv, const BIGNUM *in_r, + EC_KEY *eckey); + + int (*verify)(int type, const unsigned char *dgst, int dgst_len, + const unsigned char *sigbuf, int sig_len, EC_KEY *eckey); + int (*verify_sig)(const unsigned char *dgst, int dgst_len, + const ECDSA_SIG *sig, EC_KEY *eckey); +}; + +#define EC_KEY_METHOD_DYNAMIC 1 + +int ossl_ec_key_gen(EC_KEY *eckey); +int ossl_ecdh_compute_key(unsigned char **pout, size_t *poutlen, + const EC_POINT *pub_key, const EC_KEY *ecdh); +int ecdh_simple_compute_key(unsigned char **pout, size_t *poutlen, + const EC_POINT *pub_key, const EC_KEY *ecdh); + +struct ECDSA_SIG_st { + BIGNUM *r; + BIGNUM *s; +}; + +int ossl_ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, + BIGNUM **rp); +int ossl_ecdsa_sign(int type, const unsigned char *dgst, int dlen, + unsigned char *sig, unsigned int *siglen, + const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey); +ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len, + const BIGNUM *in_kinv, const BIGNUM *in_r, + EC_KEY *eckey); +int ossl_ecdsa_verify(int type, const unsigned char *dgst, int dgst_len, + const unsigned char *sigbuf, int sig_len, EC_KEY *eckey); +int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len, + const ECDSA_SIG *sig, EC_KEY *eckey); + +int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len, + const uint8_t public_key[32], const uint8_t private_key[32]); +int ED25519_verify(const uint8_t *message, size_t message_len, + const uint8_t signature[64], const uint8_t public_key[32]); +void ED25519_public_from_private(uint8_t out_public_key[32], + const uint8_t private_key[32]); + +int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32], + const uint8_t peer_public_value[32]); +void X25519_public_from_private(uint8_t out_public_value[32], + const uint8_t private_key[32]); + +/*- + * This functions computes a single point multiplication over the EC group, + * using, at a high level, a Montgomery ladder with conditional swaps, with + * various timing attack defenses. + * + * It performs either a fixed point multiplication + * (scalar * generator) + * when point is NULL, or a variable point multiplication + * (scalar * point) + * when point is not NULL. + * + * `scalar` cannot be NULL and should be in the range [0,n) otherwise all + * constant time bets are off (where n is the cardinality of the EC group). + * + * This function expects `group->order` and `group->cardinality` to be well + * defined and non-zero: it fails with an error code otherwise. + * + * NB: This says nothing about the constant-timeness of the ladder step + * implementation (i.e., the default implementation is based on EC_POINT_add and + * EC_POINT_dbl, which of course are not constant time themselves) or the + * underlying multiprecision arithmetic. + * + * The product is stored in `r`. + * + * This is an internal function: callers are in charge of ensuring that the + * input parameters `group`, `r`, `scalar` and `ctx` are not NULL. + * + * Returns 1 on success, 0 otherwise. + */ +int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, const EC_POINT *point, + BN_CTX *ctx); + +int ec_point_blind_coordinates(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx); + +static ossl_inline int ec_point_ladder_pre(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx) +{ + if (group->meth->ladder_pre != NULL) + return group->meth->ladder_pre(group, r, s, p, ctx); + + if (!EC_POINT_copy(s, p) + || !EC_POINT_dbl(group, r, s, ctx)) + return 0; + + return 1; +} + +static ossl_inline int ec_point_ladder_step(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx) +{ + if (group->meth->ladder_step != NULL) + return group->meth->ladder_step(group, r, s, p, ctx); + + if (!EC_POINT_add(group, s, r, s, ctx) + || !EC_POINT_dbl(group, r, r, ctx)) + return 0; + + return 1; + +} + +static ossl_inline int ec_point_ladder_post(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx) +{ + if (group->meth->ladder_post != NULL) + return group->meth->ladder_post(group, r, s, p, ctx); + + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_lib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_lib.c new file mode 100644 index 000000000..b89e3979d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_lib.c @@ -0,0 +1,1121 @@ +/* + * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#include +#include + +#include "ec_lcl.h" + +/* functions for EC_GROUP objects */ + +EC_GROUP *EC_GROUP_new(const EC_METHOD *meth) +{ + EC_GROUP *ret; + + if (meth == NULL) { + ECerr(EC_F_EC_GROUP_NEW, EC_R_SLOT_FULL); + return NULL; + } + if (meth->group_init == 0) { + ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return NULL; + } + + ret = OPENSSL_zalloc(sizeof(*ret)); + if (ret == NULL) { + ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + ret->meth = meth; + if ((ret->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) { + ret->order = BN_new(); + if (ret->order == NULL) + goto err; + ret->cofactor = BN_new(); + if (ret->cofactor == NULL) + goto err; + } + ret->asn1_flag = OPENSSL_EC_NAMED_CURVE; + ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED; + if (!meth->group_init(ret)) + goto err; + return ret; + + err: + BN_free(ret->order); + BN_free(ret->cofactor); + OPENSSL_free(ret); + return NULL; +} + +void EC_pre_comp_free(EC_GROUP *group) +{ + switch (group->pre_comp_type) { + case PCT_none: + break; + case PCT_nistz256: +#ifdef ECP_NISTZ256_ASM + EC_nistz256_pre_comp_free(group->pre_comp.nistz256); +#endif + break; +#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 + case PCT_nistp224: + EC_nistp224_pre_comp_free(group->pre_comp.nistp224); + break; + case PCT_nistp256: + EC_nistp256_pre_comp_free(group->pre_comp.nistp256); + break; + case PCT_nistp521: + EC_nistp521_pre_comp_free(group->pre_comp.nistp521); + break; +#else + case PCT_nistp224: + case PCT_nistp256: + case PCT_nistp521: + break; +#endif + case PCT_ec: + EC_ec_pre_comp_free(group->pre_comp.ec); + break; + } + group->pre_comp.ec = NULL; +} + +void EC_GROUP_free(EC_GROUP *group) +{ + if (!group) + return; + + if (group->meth->group_finish != 0) + group->meth->group_finish(group); + + EC_pre_comp_free(group); + BN_MONT_CTX_free(group->mont_data); + EC_POINT_free(group->generator); + BN_free(group->order); + BN_free(group->cofactor); + OPENSSL_free(group->seed); + OPENSSL_free(group); +} + +void EC_GROUP_clear_free(EC_GROUP *group) +{ + if (!group) + return; + + if (group->meth->group_clear_finish != 0) + group->meth->group_clear_finish(group); + else if (group->meth->group_finish != 0) + group->meth->group_finish(group); + + EC_pre_comp_free(group); + BN_MONT_CTX_free(group->mont_data); + EC_POINT_clear_free(group->generator); + BN_clear_free(group->order); + BN_clear_free(group->cofactor); + OPENSSL_clear_free(group->seed, group->seed_len); + OPENSSL_clear_free(group, sizeof(*group)); +} + +int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) +{ + if (dest->meth->group_copy == 0) { + ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (dest->meth != src->meth) { + ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + if (dest == src) + return 1; + + dest->curve_name = src->curve_name; + + /* Copy precomputed */ + dest->pre_comp_type = src->pre_comp_type; + switch (src->pre_comp_type) { + case PCT_none: + dest->pre_comp.ec = NULL; + break; + case PCT_nistz256: +#ifdef ECP_NISTZ256_ASM + dest->pre_comp.nistz256 = EC_nistz256_pre_comp_dup(src->pre_comp.nistz256); +#endif + break; +#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 + case PCT_nistp224: + dest->pre_comp.nistp224 = EC_nistp224_pre_comp_dup(src->pre_comp.nistp224); + break; + case PCT_nistp256: + dest->pre_comp.nistp256 = EC_nistp256_pre_comp_dup(src->pre_comp.nistp256); + break; + case PCT_nistp521: + dest->pre_comp.nistp521 = EC_nistp521_pre_comp_dup(src->pre_comp.nistp521); + break; +#else + case PCT_nistp224: + case PCT_nistp256: + case PCT_nistp521: + break; +#endif + case PCT_ec: + dest->pre_comp.ec = EC_ec_pre_comp_dup(src->pre_comp.ec); + break; + } + + if (src->mont_data != NULL) { + if (dest->mont_data == NULL) { + dest->mont_data = BN_MONT_CTX_new(); + if (dest->mont_data == NULL) + return 0; + } + if (!BN_MONT_CTX_copy(dest->mont_data, src->mont_data)) + return 0; + } else { + /* src->generator == NULL */ + BN_MONT_CTX_free(dest->mont_data); + dest->mont_data = NULL; + } + + if (src->generator != NULL) { + if (dest->generator == NULL) { + dest->generator = EC_POINT_new(dest); + if (dest->generator == NULL) + return 0; + } + if (!EC_POINT_copy(dest->generator, src->generator)) + return 0; + } else { + /* src->generator == NULL */ + EC_POINT_clear_free(dest->generator); + dest->generator = NULL; + } + + if ((src->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) { + if (!BN_copy(dest->order, src->order)) + return 0; + if (!BN_copy(dest->cofactor, src->cofactor)) + return 0; + } + + dest->asn1_flag = src->asn1_flag; + dest->asn1_form = src->asn1_form; + + if (src->seed) { + OPENSSL_free(dest->seed); + if ((dest->seed = OPENSSL_malloc(src->seed_len)) == NULL) { + ECerr(EC_F_EC_GROUP_COPY, ERR_R_MALLOC_FAILURE); + return 0; + } + if (!memcpy(dest->seed, src->seed, src->seed_len)) + return 0; + dest->seed_len = src->seed_len; + } else { + OPENSSL_free(dest->seed); + dest->seed = NULL; + dest->seed_len = 0; + } + + return dest->meth->group_copy(dest, src); +} + +EC_GROUP *EC_GROUP_dup(const EC_GROUP *a) +{ + EC_GROUP *t = NULL; + int ok = 0; + + if (a == NULL) + return NULL; + + if ((t = EC_GROUP_new(a->meth)) == NULL) + return NULL; + if (!EC_GROUP_copy(t, a)) + goto err; + + ok = 1; + + err: + if (!ok) { + EC_GROUP_free(t); + return NULL; + } + return t; +} + +const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group) +{ + return group->meth; +} + +int EC_METHOD_get_field_type(const EC_METHOD *meth) +{ + return meth->field_type; +} + +static int ec_precompute_mont_data(EC_GROUP *); + +int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, + const BIGNUM *order, const BIGNUM *cofactor) +{ + if (generator == NULL) { + ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (group->generator == NULL) { + group->generator = EC_POINT_new(group); + if (group->generator == NULL) + return 0; + } + if (!EC_POINT_copy(group->generator, generator)) + return 0; + + if (order != NULL) { + if (!BN_copy(group->order, order)) + return 0; + } else + BN_zero(group->order); + + if (cofactor != NULL) { + if (!BN_copy(group->cofactor, cofactor)) + return 0; + } else + BN_zero(group->cofactor); + + /* + * Some groups have an order with + * factors of two, which makes the Montgomery setup fail. + * |group->mont_data| will be NULL in this case. + */ + if (BN_is_odd(group->order)) { + return ec_precompute_mont_data(group); + } + + BN_MONT_CTX_free(group->mont_data); + group->mont_data = NULL; + return 1; +} + +const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) +{ + return group->generator; +} + +BN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group) +{ + return group->mont_data; +} + +int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) +{ + if (group->order == NULL) + return 0; + if (!BN_copy(order, group->order)) + return 0; + + return !BN_is_zero(order); +} + +const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group) +{ + return group->order; +} + +int EC_GROUP_order_bits(const EC_GROUP *group) +{ + return group->meth->group_order_bits(group); +} + +int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, + BN_CTX *ctx) +{ + + if (group->cofactor == NULL) + return 0; + if (!BN_copy(cofactor, group->cofactor)) + return 0; + + return !BN_is_zero(group->cofactor); +} + +const BIGNUM *EC_GROUP_get0_cofactor(const EC_GROUP *group) +{ + return group->cofactor; +} + +void EC_GROUP_set_curve_name(EC_GROUP *group, int nid) +{ + group->curve_name = nid; +} + +int EC_GROUP_get_curve_name(const EC_GROUP *group) +{ + return group->curve_name; +} + +void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) +{ + group->asn1_flag = flag; +} + +int EC_GROUP_get_asn1_flag(const EC_GROUP *group) +{ + return group->asn1_flag; +} + +void EC_GROUP_set_point_conversion_form(EC_GROUP *group, + point_conversion_form_t form) +{ + group->asn1_form = form; +} + +point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP + *group) +{ + return group->asn1_form; +} + +size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len) +{ + OPENSSL_free(group->seed); + group->seed = NULL; + group->seed_len = 0; + + if (!len || !p) + return 1; + + if ((group->seed = OPENSSL_malloc(len)) == NULL) { + ECerr(EC_F_EC_GROUP_SET_SEED, ERR_R_MALLOC_FAILURE); + return 0; + } + memcpy(group->seed, p, len); + group->seed_len = len; + + return len; +} + +unsigned char *EC_GROUP_get0_seed(const EC_GROUP *group) +{ + return group->seed; +} + +size_t EC_GROUP_get_seed_len(const EC_GROUP *group) +{ + return group->seed_len; +} + +int EC_GROUP_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx) +{ + if (group->meth->group_set_curve == 0) { + ECerr(EC_F_EC_GROUP_SET_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + return group->meth->group_set_curve(group, p, a, b, ctx); +} + +int EC_GROUP_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, + BN_CTX *ctx) +{ + if (group->meth->group_get_curve == NULL) { + ECerr(EC_F_EC_GROUP_GET_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + return group->meth->group_get_curve(group, p, a, b, ctx); +} + +#if OPENSSL_API_COMPAT < 0x10200000L +int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx) +{ + return EC_GROUP_set_curve(group, p, a, b, ctx); +} + +int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, + BIGNUM *b, BN_CTX *ctx) +{ + return EC_GROUP_get_curve(group, p, a, b, ctx); +} + +# ifndef OPENSSL_NO_EC2M +int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx) +{ + return EC_GROUP_set_curve(group, p, a, b, ctx); +} + +int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, + BIGNUM *b, BN_CTX *ctx) +{ + return EC_GROUP_get_curve(group, p, a, b, ctx); +} +# endif +#endif + +int EC_GROUP_get_degree(const EC_GROUP *group) +{ + if (group->meth->group_get_degree == 0) { + ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + return group->meth->group_get_degree(group); +} + +int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx) +{ + if (group->meth->group_check_discriminant == 0) { + ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + return group->meth->group_check_discriminant(group, ctx); +} + +int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx) +{ + int r = 0; + BIGNUM *a1, *a2, *a3, *b1, *b2, *b3; + BN_CTX *ctx_new = NULL; + + /* compare the field types */ + if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) != + EC_METHOD_get_field_type(EC_GROUP_method_of(b))) + return 1; + /* compare the curve name (if present in both) */ + if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) && + EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b)) + return 1; + if (a->meth->flags & EC_FLAGS_CUSTOM_CURVE) + return 0; + + if (ctx == NULL) + ctx_new = ctx = BN_CTX_new(); + if (ctx == NULL) + return -1; + + BN_CTX_start(ctx); + a1 = BN_CTX_get(ctx); + a2 = BN_CTX_get(ctx); + a3 = BN_CTX_get(ctx); + b1 = BN_CTX_get(ctx); + b2 = BN_CTX_get(ctx); + b3 = BN_CTX_get(ctx); + if (b3 == NULL) { + BN_CTX_end(ctx); + BN_CTX_free(ctx_new); + return -1; + } + + /* + * XXX This approach assumes that the external representation of curves + * over the same field type is the same. + */ + if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) || + !b->meth->group_get_curve(b, b1, b2, b3, ctx)) + r = 1; + + if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3)) + r = 1; + + /* XXX EC_POINT_cmp() assumes that the methods are equal */ + if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a), + EC_GROUP_get0_generator(b), ctx)) + r = 1; + + if (!r) { + const BIGNUM *ao, *bo, *ac, *bc; + /* compare the order and cofactor */ + ao = EC_GROUP_get0_order(a); + bo = EC_GROUP_get0_order(b); + ac = EC_GROUP_get0_cofactor(a); + bc = EC_GROUP_get0_cofactor(b); + if (ao == NULL || bo == NULL) { + BN_CTX_end(ctx); + BN_CTX_free(ctx_new); + return -1; + } + if (BN_cmp(ao, bo) || BN_cmp(ac, bc)) + r = 1; + } + + BN_CTX_end(ctx); + BN_CTX_free(ctx_new); + + return r; +} + +/* functions for EC_POINT objects */ + +EC_POINT *EC_POINT_new(const EC_GROUP *group) +{ + EC_POINT *ret; + + if (group == NULL) { + ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + if (group->meth->point_init == NULL) { + ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return NULL; + } + + ret = OPENSSL_zalloc(sizeof(*ret)); + if (ret == NULL) { + ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + ret->meth = group->meth; + ret->curve_name = group->curve_name; + + if (!ret->meth->point_init(ret)) { + OPENSSL_free(ret); + return NULL; + } + + return ret; +} + +void EC_POINT_free(EC_POINT *point) +{ + if (!point) + return; + + if (point->meth->point_finish != 0) + point->meth->point_finish(point); + OPENSSL_free(point); +} + +void EC_POINT_clear_free(EC_POINT *point) +{ + if (!point) + return; + + if (point->meth->point_clear_finish != 0) + point->meth->point_clear_finish(point); + else if (point->meth->point_finish != 0) + point->meth->point_finish(point); + OPENSSL_clear_free(point, sizeof(*point)); +} + +int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) +{ + if (dest->meth->point_copy == 0) { + ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (dest->meth != src->meth + || (dest->curve_name != src->curve_name + && dest->curve_name != 0 + && src->curve_name != 0)) { + ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + if (dest == src) + return 1; + return dest->meth->point_copy(dest, src); +} + +EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group) +{ + EC_POINT *t; + int r; + + if (a == NULL) + return NULL; + + t = EC_POINT_new(group); + if (t == NULL) + return NULL; + r = EC_POINT_copy(t, a); + if (!r) { + EC_POINT_free(t); + return NULL; + } + return t; +} + +const EC_METHOD *EC_POINT_method_of(const EC_POINT *point) +{ + return point->meth; +} + +int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point) +{ + if (group->meth->point_set_to_infinity == 0) { + ECerr(EC_F_EC_POINT_SET_TO_INFINITY, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (group->meth != point->meth) { + ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->point_set_to_infinity(group, point); +} + +int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, + EC_POINT *point, const BIGNUM *x, + const BIGNUM *y, const BIGNUM *z, + BN_CTX *ctx) +{ + if (group->meth->point_set_Jprojective_coordinates_GFp == 0) { + ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (!ec_point_is_compat(point, group)) { + ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, + EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x, + y, z, ctx); +} + +int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, + const EC_POINT *point, BIGNUM *x, + BIGNUM *y, BIGNUM *z, + BN_CTX *ctx) +{ + if (group->meth->point_get_Jprojective_coordinates_GFp == 0) { + ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (!ec_point_is_compat(point, group)) { + ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, + EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x, + y, z, ctx); +} + +int EC_POINT_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point, + const BIGNUM *x, const BIGNUM *y, + BN_CTX *ctx) +{ + if (group->meth->point_set_affine_coordinates == NULL) { + ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (!ec_point_is_compat(point, group)) { + ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + if (!group->meth->point_set_affine_coordinates(group, point, x, y, ctx)) + return 0; + + if (EC_POINT_is_on_curve(group, point, ctx) <= 0) { + ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES, EC_R_POINT_IS_NOT_ON_CURVE); + return 0; + } + return 1; +} + +#if OPENSSL_API_COMPAT < 0x10200000L +int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, + EC_POINT *point, const BIGNUM *x, + const BIGNUM *y, BN_CTX *ctx) +{ + return EC_POINT_set_affine_coordinates(group, point, x, y, ctx); +} + +# ifndef OPENSSL_NO_EC2M +int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, + EC_POINT *point, const BIGNUM *x, + const BIGNUM *y, BN_CTX *ctx) +{ + return EC_POINT_set_affine_coordinates(group, point, x, y, ctx); +} +# endif +#endif + +int EC_POINT_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, BIGNUM *x, BIGNUM *y, + BN_CTX *ctx) +{ + if (group->meth->point_get_affine_coordinates == NULL) { + ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (!ec_point_is_compat(point, group)) { + ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + if (EC_POINT_is_at_infinity(group, point)) { + ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY); + return 0; + } + return group->meth->point_get_affine_coordinates(group, point, x, y, ctx); +} + +#if OPENSSL_API_COMPAT < 0x10200000L +int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, + const EC_POINT *point, BIGNUM *x, + BIGNUM *y, BN_CTX *ctx) +{ + return EC_POINT_get_affine_coordinates(group, point, x, y, ctx); +} + +# ifndef OPENSSL_NO_EC2M +int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, + const EC_POINT *point, BIGNUM *x, + BIGNUM *y, BN_CTX *ctx) +{ + return EC_POINT_get_affine_coordinates(group, point, x, y, ctx); +} +# endif +#endif + +int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, + const EC_POINT *b, BN_CTX *ctx) +{ + if (group->meth->add == 0) { + ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (!ec_point_is_compat(r, group) || !ec_point_is_compat(a, group) + || !ec_point_is_compat(b, group)) { + ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->add(group, r, a, b, ctx); +} + +int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, + BN_CTX *ctx) +{ + if (group->meth->dbl == 0) { + ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (!ec_point_is_compat(r, group) || !ec_point_is_compat(a, group)) { + ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->dbl(group, r, a, ctx); +} + +int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) +{ + if (group->meth->invert == 0) { + ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (!ec_point_is_compat(a, group)) { + ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->invert(group, a, ctx); +} + +int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) +{ + if (group->meth->is_at_infinity == 0) { + ECerr(EC_F_EC_POINT_IS_AT_INFINITY, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (!ec_point_is_compat(point, group)) { + ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->is_at_infinity(group, point); +} + +/* + * Check whether an EC_POINT is on the curve or not. Note that the return + * value for this function should NOT be treated as a boolean. Return values: + * 1: The point is on the curve + * 0: The point is not on the curve + * -1: An error occurred + */ +int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, + BN_CTX *ctx) +{ + if (group->meth->is_on_curve == 0) { + ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (!ec_point_is_compat(point, group)) { + ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->is_on_curve(group, point, ctx); +} + +int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, + BN_CTX *ctx) +{ + if (group->meth->point_cmp == 0) { + ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return -1; + } + if (!ec_point_is_compat(a, group) || !ec_point_is_compat(b, group)) { + ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS); + return -1; + } + return group->meth->point_cmp(group, a, b, ctx); +} + +int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) +{ + if (group->meth->make_affine == 0) { + ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (!ec_point_is_compat(point, group)) { + ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->make_affine(group, point, ctx); +} + +int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, + EC_POINT *points[], BN_CTX *ctx) +{ + size_t i; + + if (group->meth->points_make_affine == 0) { + ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + for (i = 0; i < num; i++) { + if (!ec_point_is_compat(points[i], group)) { + ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + } + return group->meth->points_make_affine(group, num, points, ctx); +} + +/* + * Functions for point multiplication. If group->meth->mul is 0, we use the + * wNAF-based implementations in ec_mult.c; otherwise we dispatch through + * methods. + */ + +int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, + size_t num, const EC_POINT *points[], + const BIGNUM *scalars[], BN_CTX *ctx) +{ + int ret = 0; + size_t i = 0; + BN_CTX *new_ctx = NULL; + + if ((scalar == NULL) && (num == 0)) { + return EC_POINT_set_to_infinity(group, r); + } + + if (!ec_point_is_compat(r, group)) { + ECerr(EC_F_EC_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + for (i = 0; i < num; i++) { + if (!ec_point_is_compat(points[i], group)) { + ECerr(EC_F_EC_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + } + + if (ctx == NULL && (ctx = new_ctx = BN_CTX_secure_new()) == NULL) { + ECerr(EC_F_EC_POINTS_MUL, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (group->meth->mul != NULL) + ret = group->meth->mul(group, r, scalar, num, points, scalars, ctx); + else + /* use default */ + ret = ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx); + + BN_CTX_free(new_ctx); + return ret; +} + +int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, + const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx) +{ + /* just a convenient interface to EC_POINTs_mul() */ + + const EC_POINT *points[1]; + const BIGNUM *scalars[1]; + + points[0] = point; + scalars[0] = p_scalar; + + return EC_POINTs_mul(group, r, g_scalar, + (point != NULL + && p_scalar != NULL), points, scalars, ctx); +} + +int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx) +{ + if (group->meth->mul == 0) + /* use default */ + return ec_wNAF_precompute_mult(group, ctx); + + if (group->meth->precompute_mult != 0) + return group->meth->precompute_mult(group, ctx); + else + return 1; /* nothing to do, so report success */ +} + +int EC_GROUP_have_precompute_mult(const EC_GROUP *group) +{ + if (group->meth->mul == 0) + /* use default */ + return ec_wNAF_have_precompute_mult(group); + + if (group->meth->have_precompute_mult != 0) + return group->meth->have_precompute_mult(group); + else + return 0; /* cannot tell whether precomputation has + * been performed */ +} + +/* + * ec_precompute_mont_data sets |group->mont_data| from |group->order| and + * returns one on success. On error it returns zero. + */ +static int ec_precompute_mont_data(EC_GROUP *group) +{ + BN_CTX *ctx = BN_CTX_new(); + int ret = 0; + + BN_MONT_CTX_free(group->mont_data); + group->mont_data = NULL; + + if (ctx == NULL) + goto err; + + group->mont_data = BN_MONT_CTX_new(); + if (group->mont_data == NULL) + goto err; + + if (!BN_MONT_CTX_set(group->mont_data, group->order, ctx)) { + BN_MONT_CTX_free(group->mont_data); + group->mont_data = NULL; + goto err; + } + + ret = 1; + + err: + + BN_CTX_free(ctx); + return ret; +} + +int EC_KEY_set_ex_data(EC_KEY *key, int idx, void *arg) +{ + return CRYPTO_set_ex_data(&key->ex_data, idx, arg); +} + +void *EC_KEY_get_ex_data(const EC_KEY *key, int idx) +{ + return CRYPTO_get_ex_data(&key->ex_data, idx); +} + +int ec_group_simple_order_bits(const EC_GROUP *group) +{ + if (group->order == NULL) + return 0; + return BN_num_bits(group->order); +} + +static int ec_field_inverse_mod_ord(const EC_GROUP *group, BIGNUM *r, + const BIGNUM *x, BN_CTX *ctx) +{ + BIGNUM *e = NULL; + BN_CTX *new_ctx = NULL; + int ret = 0; + + if (group->mont_data == NULL) + return 0; + + if (ctx == NULL && (ctx = new_ctx = BN_CTX_secure_new()) == NULL) + return 0; + + BN_CTX_start(ctx); + if ((e = BN_CTX_get(ctx)) == NULL) + goto err; + + /*- + * We want inverse in constant time, therefore we utilize the fact + * order must be prime and use Fermats Little Theorem instead. + */ + if (!BN_set_word(e, 2)) + goto err; + if (!BN_sub(e, group->order, e)) + goto err; + /*- + * Exponent e is public. + * No need for scatter-gather or BN_FLG_CONSTTIME. + */ + if (!BN_mod_exp_mont(r, x, e, group->order, ctx, group->mont_data)) + goto err; + + ret = 1; + + err: + if (ctx != NULL) + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +/*- + * Default behavior, if group->meth->field_inverse_mod_ord is NULL: + * - When group->order is even, this function returns an error. + * - When group->order is otherwise composite, the correctness + * of the output is not guaranteed. + * - When x is outside the range [1, group->order), the correctness + * of the output is not guaranteed. + * - Otherwise, this function returns the multiplicative inverse in the + * range [1, group->order). + * + * EC_METHODs must implement their own field_inverse_mod_ord for + * other functionality. + */ +int ec_group_do_inverse_ord(const EC_GROUP *group, BIGNUM *res, + const BIGNUM *x, BN_CTX *ctx) +{ + if (group->meth->field_inverse_mod_ord != NULL) + return group->meth->field_inverse_mod_ord(group, res, x, ctx); + else + return ec_field_inverse_mod_ord(group, res, x, ctx); +} + +/*- + * Coordinate blinding for EC_POINT. + * + * The underlying EC_METHOD can optionally implement this function: + * underlying implementations should return 0 on errors, or 1 on + * success. + * + * This wrapper returns 1 in case the underlying EC_METHOD does not + * support coordinate blinding. + */ +int ec_point_blind_coordinates(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx) +{ + if (group->meth->blind_coordinates == NULL) + return 1; /* ignore if not implemented */ + + return group->meth->blind_coordinates(group, p, ctx); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_mult.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_mult.c new file mode 100644 index 000000000..0e0a5e139 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_mult.c @@ -0,0 +1,970 @@ +/* + * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#include "internal/cryptlib.h" +#include "internal/bn_int.h" +#include "ec_lcl.h" +#include "internal/refcount.h" + +/* + * This file implements the wNAF-based interleaving multi-exponentiation method + * Formerly at: + * http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#multiexp + * You might now find it here: + * http://link.springer.com/chapter/10.1007%2F3-540-45537-X_13 + * http://www.bmoeller.de/pdf/TI-01-08.multiexp.pdf + * For multiplication with precomputation, we use wNAF splitting, formerly at: + * http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#fastexp + */ + +/* structure for precomputed multiples of the generator */ +struct ec_pre_comp_st { + const EC_GROUP *group; /* parent EC_GROUP object */ + size_t blocksize; /* block size for wNAF splitting */ + size_t numblocks; /* max. number of blocks for which we have + * precomputation */ + size_t w; /* window size */ + EC_POINT **points; /* array with pre-calculated multiples of + * generator: 'num' pointers to EC_POINT + * objects followed by a NULL */ + size_t num; /* numblocks * 2^(w-1) */ + CRYPTO_REF_COUNT references; + CRYPTO_RWLOCK *lock; +}; + +static EC_PRE_COMP *ec_pre_comp_new(const EC_GROUP *group) +{ + EC_PRE_COMP *ret = NULL; + + if (!group) + return NULL; + + ret = OPENSSL_zalloc(sizeof(*ret)); + if (ret == NULL) { + ECerr(EC_F_EC_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); + return ret; + } + + ret->group = group; + ret->blocksize = 8; /* default */ + ret->w = 4; /* default */ + ret->references = 1; + + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) { + ECerr(EC_F_EC_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ret); + return NULL; + } + return ret; +} + +EC_PRE_COMP *EC_ec_pre_comp_dup(EC_PRE_COMP *pre) +{ + int i; + if (pre != NULL) + CRYPTO_UP_REF(&pre->references, &i, pre->lock); + return pre; +} + +void EC_ec_pre_comp_free(EC_PRE_COMP *pre) +{ + int i; + + if (pre == NULL) + return; + + CRYPTO_DOWN_REF(&pre->references, &i, pre->lock); + REF_PRINT_COUNT("EC_ec", pre); + if (i > 0) + return; + REF_ASSERT_ISNT(i < 0); + + if (pre->points != NULL) { + EC_POINT **pts; + + for (pts = pre->points; *pts != NULL; pts++) + EC_POINT_free(*pts); + OPENSSL_free(pre->points); + } + CRYPTO_THREAD_lock_free(pre->lock); + OPENSSL_free(pre); +} + +#define EC_POINT_BN_set_flags(P, flags) do { \ + BN_set_flags((P)->X, (flags)); \ + BN_set_flags((P)->Y, (flags)); \ + BN_set_flags((P)->Z, (flags)); \ +} while(0) + +/*- + * This functions computes a single point multiplication over the EC group, + * using, at a high level, a Montgomery ladder with conditional swaps, with + * various timing attack defenses. + * + * It performs either a fixed point multiplication + * (scalar * generator) + * when point is NULL, or a variable point multiplication + * (scalar * point) + * when point is not NULL. + * + * `scalar` cannot be NULL and should be in the range [0,n) otherwise all + * constant time bets are off (where n is the cardinality of the EC group). + * + * This function expects `group->order` and `group->cardinality` to be well + * defined and non-zero: it fails with an error code otherwise. + * + * NB: This says nothing about the constant-timeness of the ladder step + * implementation (i.e., the default implementation is based on EC_POINT_add and + * EC_POINT_dbl, which of course are not constant time themselves) or the + * underlying multiprecision arithmetic. + * + * The product is stored in `r`. + * + * This is an internal function: callers are in charge of ensuring that the + * input parameters `group`, `r`, `scalar` and `ctx` are not NULL. + * + * Returns 1 on success, 0 otherwise. + */ +int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, const EC_POINT *point, + BN_CTX *ctx) +{ + int i, cardinality_bits, group_top, kbit, pbit, Z_is_one; + EC_POINT *p = NULL; + EC_POINT *s = NULL; + BIGNUM *k = NULL; + BIGNUM *lambda = NULL; + BIGNUM *cardinality = NULL; + int ret = 0; + + /* early exit if the input point is the point at infinity */ + if (point != NULL && EC_POINT_is_at_infinity(group, point)) + return EC_POINT_set_to_infinity(group, r); + + if (BN_is_zero(group->order)) { + ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_UNKNOWN_ORDER); + return 0; + } + if (BN_is_zero(group->cofactor)) { + ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_UNKNOWN_COFACTOR); + return 0; + } + + BN_CTX_start(ctx); + + if (((p = EC_POINT_new(group)) == NULL) + || ((s = EC_POINT_new(group)) == NULL)) { + ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (point == NULL) { + if (!EC_POINT_copy(p, group->generator)) { + ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_EC_LIB); + goto err; + } + } else { + if (!EC_POINT_copy(p, point)) { + ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_EC_LIB); + goto err; + } + } + + EC_POINT_BN_set_flags(p, BN_FLG_CONSTTIME); + EC_POINT_BN_set_flags(r, BN_FLG_CONSTTIME); + EC_POINT_BN_set_flags(s, BN_FLG_CONSTTIME); + + cardinality = BN_CTX_get(ctx); + lambda = BN_CTX_get(ctx); + k = BN_CTX_get(ctx); + if (k == NULL) { + ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!BN_mul(cardinality, group->order, group->cofactor, ctx)) { + ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB); + goto err; + } + + /* + * Group cardinalities are often on a word boundary. + * So when we pad the scalar, some timing diff might + * pop if it needs to be expanded due to carries. + * So expand ahead of time. + */ + cardinality_bits = BN_num_bits(cardinality); + group_top = bn_get_top(cardinality); + if ((bn_wexpand(k, group_top + 2) == NULL) + || (bn_wexpand(lambda, group_top + 2) == NULL)) { + ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB); + goto err; + } + + if (!BN_copy(k, scalar)) { + ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB); + goto err; + } + + BN_set_flags(k, BN_FLG_CONSTTIME); + + if ((BN_num_bits(k) > cardinality_bits) || (BN_is_negative(k))) { + /*- + * this is an unusual input, and we don't guarantee + * constant-timeness + */ + if (!BN_nnmod(k, k, cardinality, ctx)) { + ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB); + goto err; + } + } + + if (!BN_add(lambda, k, cardinality)) { + ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB); + goto err; + } + BN_set_flags(lambda, BN_FLG_CONSTTIME); + if (!BN_add(k, lambda, cardinality)) { + ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB); + goto err; + } + /* + * lambda := scalar + cardinality + * k := scalar + 2*cardinality + */ + kbit = BN_is_bit_set(lambda, cardinality_bits); + BN_consttime_swap(kbit, k, lambda, group_top + 2); + + group_top = bn_get_top(group->field); + if ((bn_wexpand(s->X, group_top) == NULL) + || (bn_wexpand(s->Y, group_top) == NULL) + || (bn_wexpand(s->Z, group_top) == NULL) + || (bn_wexpand(r->X, group_top) == NULL) + || (bn_wexpand(r->Y, group_top) == NULL) + || (bn_wexpand(r->Z, group_top) == NULL) + || (bn_wexpand(p->X, group_top) == NULL) + || (bn_wexpand(p->Y, group_top) == NULL) + || (bn_wexpand(p->Z, group_top) == NULL)) { + ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB); + goto err; + } + + /*- + * Apply coordinate blinding for EC_POINT. + * + * The underlying EC_METHOD can optionally implement this function: + * ec_point_blind_coordinates() returns 0 in case of errors or 1 on + * success or if coordinate blinding is not implemented for this + * group. + */ + if (!ec_point_blind_coordinates(group, p, ctx)) { + ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_POINT_COORDINATES_BLIND_FAILURE); + goto err; + } + + /* Initialize the Montgomery ladder */ + if (!ec_point_ladder_pre(group, r, s, p, ctx)) { + ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_LADDER_PRE_FAILURE); + goto err; + } + + /* top bit is a 1, in a fixed pos */ + pbit = 1; + +#define EC_POINT_CSWAP(c, a, b, w, t) do { \ + BN_consttime_swap(c, (a)->X, (b)->X, w); \ + BN_consttime_swap(c, (a)->Y, (b)->Y, w); \ + BN_consttime_swap(c, (a)->Z, (b)->Z, w); \ + t = ((a)->Z_is_one ^ (b)->Z_is_one) & (c); \ + (a)->Z_is_one ^= (t); \ + (b)->Z_is_one ^= (t); \ +} while(0) + + /*- + * The ladder step, with branches, is + * + * k[i] == 0: S = add(R, S), R = dbl(R) + * k[i] == 1: R = add(S, R), S = dbl(S) + * + * Swapping R, S conditionally on k[i] leaves you with state + * + * k[i] == 0: T, U = R, S + * k[i] == 1: T, U = S, R + * + * Then perform the ECC ops. + * + * U = add(T, U) + * T = dbl(T) + * + * Which leaves you with state + * + * k[i] == 0: U = add(R, S), T = dbl(R) + * k[i] == 1: U = add(S, R), T = dbl(S) + * + * Swapping T, U conditionally on k[i] leaves you with state + * + * k[i] == 0: R, S = T, U + * k[i] == 1: R, S = U, T + * + * Which leaves you with state + * + * k[i] == 0: S = add(R, S), R = dbl(R) + * k[i] == 1: R = add(S, R), S = dbl(S) + * + * So we get the same logic, but instead of a branch it's a + * conditional swap, followed by ECC ops, then another conditional swap. + * + * Optimization: The end of iteration i and start of i-1 looks like + * + * ... + * CSWAP(k[i], R, S) + * ECC + * CSWAP(k[i], R, S) + * (next iteration) + * CSWAP(k[i-1], R, S) + * ECC + * CSWAP(k[i-1], R, S) + * ... + * + * So instead of two contiguous swaps, you can merge the condition + * bits and do a single swap. + * + * k[i] k[i-1] Outcome + * 0 0 No Swap + * 0 1 Swap + * 1 0 Swap + * 1 1 No Swap + * + * This is XOR. pbit tracks the previous bit of k. + */ + + for (i = cardinality_bits - 1; i >= 0; i--) { + kbit = BN_is_bit_set(k, i) ^ pbit; + EC_POINT_CSWAP(kbit, r, s, group_top, Z_is_one); + + /* Perform a single step of the Montgomery ladder */ + if (!ec_point_ladder_step(group, r, s, p, ctx)) { + ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_LADDER_STEP_FAILURE); + goto err; + } + /* + * pbit logic merges this cswap with that of the + * next iteration + */ + pbit ^= kbit; + } + /* one final cswap to move the right value into r */ + EC_POINT_CSWAP(pbit, r, s, group_top, Z_is_one); +#undef EC_POINT_CSWAP + + /* Finalize ladder (and recover full point coordinates) */ + if (!ec_point_ladder_post(group, r, s, p, ctx)) { + ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_LADDER_POST_FAILURE); + goto err; + } + + ret = 1; + + err: + EC_POINT_free(p); + EC_POINT_free(s); + BN_CTX_end(ctx); + + return ret; +} + +#undef EC_POINT_BN_set_flags + +/* + * TODO: table should be optimised for the wNAF-based implementation, + * sometimes smaller windows will give better performance (thus the + * boundaries should be increased) + */ +#define EC_window_bits_for_scalar_size(b) \ + ((size_t) \ + ((b) >= 2000 ? 6 : \ + (b) >= 800 ? 5 : \ + (b) >= 300 ? 4 : \ + (b) >= 70 ? 3 : \ + (b) >= 20 ? 2 : \ + 1)) + +/*- + * Compute + * \sum scalars[i]*points[i], + * also including + * scalar*generator + * in the addition if scalar != NULL + */ +int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, + size_t num, const EC_POINT *points[], const BIGNUM *scalars[], + BN_CTX *ctx) +{ + const EC_POINT *generator = NULL; + EC_POINT *tmp = NULL; + size_t totalnum; + size_t blocksize = 0, numblocks = 0; /* for wNAF splitting */ + size_t pre_points_per_block = 0; + size_t i, j; + int k; + int r_is_inverted = 0; + int r_is_at_infinity = 1; + size_t *wsize = NULL; /* individual window sizes */ + signed char **wNAF = NULL; /* individual wNAFs */ + size_t *wNAF_len = NULL; + size_t max_len = 0; + size_t num_val; + EC_POINT **val = NULL; /* precomputation */ + EC_POINT **v; + EC_POINT ***val_sub = NULL; /* pointers to sub-arrays of 'val' or + * 'pre_comp->points' */ + const EC_PRE_COMP *pre_comp = NULL; + int num_scalar = 0; /* flag: will be set to 1 if 'scalar' must be + * treated like other scalars, i.e. + * precomputation is not available */ + int ret = 0; + + if (!BN_is_zero(group->order) && !BN_is_zero(group->cofactor)) { + /*- + * Handle the common cases where the scalar is secret, enforcing a + * scalar multiplication implementation based on a Montgomery ladder, + * with various timing attack defenses. + */ + if ((scalar != NULL) && (num == 0)) { + /*- + * In this case we want to compute scalar * GeneratorPoint: this + * codepath is reached most prominently by (ephemeral) key + * generation of EC cryptosystems (i.e. ECDSA keygen and sign setup, + * ECDH keygen/first half), where the scalar is always secret. This + * is why we ignore if BN_FLG_CONSTTIME is actually set and we + * always call the ladder version. + */ + return ec_scalar_mul_ladder(group, r, scalar, NULL, ctx); + } + if ((scalar == NULL) && (num == 1)) { + /*- + * In this case we want to compute scalar * VariablePoint: this + * codepath is reached most prominently by the second half of ECDH, + * where the secret scalar is multiplied by the peer's public point. + * To protect the secret scalar, we ignore if BN_FLG_CONSTTIME is + * actually set and we always call the ladder version. + */ + return ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx); + } + } + + if (scalar != NULL) { + generator = EC_GROUP_get0_generator(group); + if (generator == NULL) { + ECerr(EC_F_EC_WNAF_MUL, EC_R_UNDEFINED_GENERATOR); + goto err; + } + + /* look if we can use precomputed multiples of generator */ + + pre_comp = group->pre_comp.ec; + if (pre_comp && pre_comp->numblocks + && (EC_POINT_cmp(group, generator, pre_comp->points[0], ctx) == + 0)) { + blocksize = pre_comp->blocksize; + + /* + * determine maximum number of blocks that wNAF splitting may + * yield (NB: maximum wNAF length is bit length plus one) + */ + numblocks = (BN_num_bits(scalar) / blocksize) + 1; + + /* + * we cannot use more blocks than we have precomputation for + */ + if (numblocks > pre_comp->numblocks) + numblocks = pre_comp->numblocks; + + pre_points_per_block = (size_t)1 << (pre_comp->w - 1); + + /* check that pre_comp looks sane */ + if (pre_comp->num != (pre_comp->numblocks * pre_points_per_block)) { + ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); + goto err; + } + } else { + /* can't use precomputation */ + pre_comp = NULL; + numblocks = 1; + num_scalar = 1; /* treat 'scalar' like 'num'-th element of + * 'scalars' */ + } + } + + totalnum = num + numblocks; + + wsize = OPENSSL_malloc(totalnum * sizeof(wsize[0])); + wNAF_len = OPENSSL_malloc(totalnum * sizeof(wNAF_len[0])); + /* include space for pivot */ + wNAF = OPENSSL_malloc((totalnum + 1) * sizeof(wNAF[0])); + val_sub = OPENSSL_malloc(totalnum * sizeof(val_sub[0])); + + /* Ensure wNAF is initialised in case we end up going to err */ + if (wNAF != NULL) + wNAF[0] = NULL; /* preliminary pivot */ + + if (wsize == NULL || wNAF_len == NULL || wNAF == NULL || val_sub == NULL) { + ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* + * num_val will be the total number of temporarily precomputed points + */ + num_val = 0; + + for (i = 0; i < num + num_scalar; i++) { + size_t bits; + + bits = i < num ? BN_num_bits(scalars[i]) : BN_num_bits(scalar); + wsize[i] = EC_window_bits_for_scalar_size(bits); + num_val += (size_t)1 << (wsize[i] - 1); + wNAF[i + 1] = NULL; /* make sure we always have a pivot */ + wNAF[i] = + bn_compute_wNAF((i < num ? scalars[i] : scalar), wsize[i], + &wNAF_len[i]); + if (wNAF[i] == NULL) + goto err; + if (wNAF_len[i] > max_len) + max_len = wNAF_len[i]; + } + + if (numblocks) { + /* we go here iff scalar != NULL */ + + if (pre_comp == NULL) { + if (num_scalar != 1) { + ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); + goto err; + } + /* we have already generated a wNAF for 'scalar' */ + } else { + signed char *tmp_wNAF = NULL; + size_t tmp_len = 0; + + if (num_scalar != 0) { + ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); + goto err; + } + + /* + * use the window size for which we have precomputation + */ + wsize[num] = pre_comp->w; + tmp_wNAF = bn_compute_wNAF(scalar, wsize[num], &tmp_len); + if (!tmp_wNAF) + goto err; + + if (tmp_len <= max_len) { + /* + * One of the other wNAFs is at least as long as the wNAF + * belonging to the generator, so wNAF splitting will not buy + * us anything. + */ + + numblocks = 1; + totalnum = num + 1; /* don't use wNAF splitting */ + wNAF[num] = tmp_wNAF; + wNAF[num + 1] = NULL; + wNAF_len[num] = tmp_len; + /* + * pre_comp->points starts with the points that we need here: + */ + val_sub[num] = pre_comp->points; + } else { + /* + * don't include tmp_wNAF directly into wNAF array - use wNAF + * splitting and include the blocks + */ + + signed char *pp; + EC_POINT **tmp_points; + + if (tmp_len < numblocks * blocksize) { + /* + * possibly we can do with fewer blocks than estimated + */ + numblocks = (tmp_len + blocksize - 1) / blocksize; + if (numblocks > pre_comp->numblocks) { + ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); + OPENSSL_free(tmp_wNAF); + goto err; + } + totalnum = num + numblocks; + } + + /* split wNAF in 'numblocks' parts */ + pp = tmp_wNAF; + tmp_points = pre_comp->points; + + for (i = num; i < totalnum; i++) { + if (i < totalnum - 1) { + wNAF_len[i] = blocksize; + if (tmp_len < blocksize) { + ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); + OPENSSL_free(tmp_wNAF); + goto err; + } + tmp_len -= blocksize; + } else + /* + * last block gets whatever is left (this could be + * more or less than 'blocksize'!) + */ + wNAF_len[i] = tmp_len; + + wNAF[i + 1] = NULL; + wNAF[i] = OPENSSL_malloc(wNAF_len[i]); + if (wNAF[i] == NULL) { + ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE); + OPENSSL_free(tmp_wNAF); + goto err; + } + memcpy(wNAF[i], pp, wNAF_len[i]); + if (wNAF_len[i] > max_len) + max_len = wNAF_len[i]; + + if (*tmp_points == NULL) { + ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); + OPENSSL_free(tmp_wNAF); + goto err; + } + val_sub[i] = tmp_points; + tmp_points += pre_points_per_block; + pp += blocksize; + } + OPENSSL_free(tmp_wNAF); + } + } + } + + /* + * All points we precompute now go into a single array 'val'. + * 'val_sub[i]' is a pointer to the subarray for the i-th point, or to a + * subarray of 'pre_comp->points' if we already have precomputation. + */ + val = OPENSSL_malloc((num_val + 1) * sizeof(val[0])); + if (val == NULL) { + ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE); + goto err; + } + val[num_val] = NULL; /* pivot element */ + + /* allocate points for precomputation */ + v = val; + for (i = 0; i < num + num_scalar; i++) { + val_sub[i] = v; + for (j = 0; j < ((size_t)1 << (wsize[i] - 1)); j++) { + *v = EC_POINT_new(group); + if (*v == NULL) + goto err; + v++; + } + } + if (!(v == val + num_val)) { + ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); + goto err; + } + + if ((tmp = EC_POINT_new(group)) == NULL) + goto err; + + /*- + * prepare precomputed values: + * val_sub[i][0] := points[i] + * val_sub[i][1] := 3 * points[i] + * val_sub[i][2] := 5 * points[i] + * ... + */ + for (i = 0; i < num + num_scalar; i++) { + if (i < num) { + if (!EC_POINT_copy(val_sub[i][0], points[i])) + goto err; + } else { + if (!EC_POINT_copy(val_sub[i][0], generator)) + goto err; + } + + if (wsize[i] > 1) { + if (!EC_POINT_dbl(group, tmp, val_sub[i][0], ctx)) + goto err; + for (j = 1; j < ((size_t)1 << (wsize[i] - 1)); j++) { + if (!EC_POINT_add + (group, val_sub[i][j], val_sub[i][j - 1], tmp, ctx)) + goto err; + } + } + } + + if (!EC_POINTs_make_affine(group, num_val, val, ctx)) + goto err; + + r_is_at_infinity = 1; + + for (k = max_len - 1; k >= 0; k--) { + if (!r_is_at_infinity) { + if (!EC_POINT_dbl(group, r, r, ctx)) + goto err; + } + + for (i = 0; i < totalnum; i++) { + if (wNAF_len[i] > (size_t)k) { + int digit = wNAF[i][k]; + int is_neg; + + if (digit) { + is_neg = digit < 0; + + if (is_neg) + digit = -digit; + + if (is_neg != r_is_inverted) { + if (!r_is_at_infinity) { + if (!EC_POINT_invert(group, r, ctx)) + goto err; + } + r_is_inverted = !r_is_inverted; + } + + /* digit > 0 */ + + if (r_is_at_infinity) { + if (!EC_POINT_copy(r, val_sub[i][digit >> 1])) + goto err; + r_is_at_infinity = 0; + } else { + if (!EC_POINT_add + (group, r, r, val_sub[i][digit >> 1], ctx)) + goto err; + } + } + } + } + } + + if (r_is_at_infinity) { + if (!EC_POINT_set_to_infinity(group, r)) + goto err; + } else { + if (r_is_inverted) + if (!EC_POINT_invert(group, r, ctx)) + goto err; + } + + ret = 1; + + err: + EC_POINT_free(tmp); + OPENSSL_free(wsize); + OPENSSL_free(wNAF_len); + if (wNAF != NULL) { + signed char **w; + + for (w = wNAF; *w != NULL; w++) + OPENSSL_free(*w); + + OPENSSL_free(wNAF); + } + if (val != NULL) { + for (v = val; *v != NULL; v++) + EC_POINT_clear_free(*v); + + OPENSSL_free(val); + } + OPENSSL_free(val_sub); + return ret; +} + +/*- + * ec_wNAF_precompute_mult() + * creates an EC_PRE_COMP object with preprecomputed multiples of the generator + * for use with wNAF splitting as implemented in ec_wNAF_mul(). + * + * 'pre_comp->points' is an array of multiples of the generator + * of the following form: + * points[0] = generator; + * points[1] = 3 * generator; + * ... + * points[2^(w-1)-1] = (2^(w-1)-1) * generator; + * points[2^(w-1)] = 2^blocksize * generator; + * points[2^(w-1)+1] = 3 * 2^blocksize * generator; + * ... + * points[2^(w-1)*(numblocks-1)-1] = (2^(w-1)) * 2^(blocksize*(numblocks-2)) * generator + * points[2^(w-1)*(numblocks-1)] = 2^(blocksize*(numblocks-1)) * generator + * ... + * points[2^(w-1)*numblocks-1] = (2^(w-1)) * 2^(blocksize*(numblocks-1)) * generator + * points[2^(w-1)*numblocks] = NULL + */ +int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx) +{ + const EC_POINT *generator; + EC_POINT *tmp_point = NULL, *base = NULL, **var; + BN_CTX *new_ctx = NULL; + const BIGNUM *order; + size_t i, bits, w, pre_points_per_block, blocksize, numblocks, num; + EC_POINT **points = NULL; + EC_PRE_COMP *pre_comp; + int ret = 0; + + /* if there is an old EC_PRE_COMP object, throw it away */ + EC_pre_comp_free(group); + if ((pre_comp = ec_pre_comp_new(group)) == NULL) + return 0; + + generator = EC_GROUP_get0_generator(group); + if (generator == NULL) { + ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, EC_R_UNDEFINED_GENERATOR); + goto err; + } + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + goto err; + } + + BN_CTX_start(ctx); + + order = EC_GROUP_get0_order(group); + if (order == NULL) + goto err; + if (BN_is_zero(order)) { + ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, EC_R_UNKNOWN_ORDER); + goto err; + } + + bits = BN_num_bits(order); + /* + * The following parameters mean we precompute (approximately) one point + * per bit. TBD: The combination 8, 4 is perfect for 160 bits; for other + * bit lengths, other parameter combinations might provide better + * efficiency. + */ + blocksize = 8; + w = 4; + if (EC_window_bits_for_scalar_size(bits) > w) { + /* let's not make the window too small ... */ + w = EC_window_bits_for_scalar_size(bits); + } + + numblocks = (bits + blocksize - 1) / blocksize; /* max. number of blocks + * to use for wNAF + * splitting */ + + pre_points_per_block = (size_t)1 << (w - 1); + num = pre_points_per_block * numblocks; /* number of points to compute + * and store */ + + points = OPENSSL_malloc(sizeof(*points) * (num + 1)); + if (points == NULL) { + ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE); + goto err; + } + + var = points; + var[num] = NULL; /* pivot */ + for (i = 0; i < num; i++) { + if ((var[i] = EC_POINT_new(group)) == NULL) { + ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + if ((tmp_point = EC_POINT_new(group)) == NULL + || (base = EC_POINT_new(group)) == NULL) { + ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!EC_POINT_copy(base, generator)) + goto err; + + /* do the precomputation */ + for (i = 0; i < numblocks; i++) { + size_t j; + + if (!EC_POINT_dbl(group, tmp_point, base, ctx)) + goto err; + + if (!EC_POINT_copy(*var++, base)) + goto err; + + for (j = 1; j < pre_points_per_block; j++, var++) { + /* + * calculate odd multiples of the current base point + */ + if (!EC_POINT_add(group, *var, tmp_point, *(var - 1), ctx)) + goto err; + } + + if (i < numblocks - 1) { + /* + * get the next base (multiply current one by 2^blocksize) + */ + size_t k; + + if (blocksize <= 2) { + ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_INTERNAL_ERROR); + goto err; + } + + if (!EC_POINT_dbl(group, base, tmp_point, ctx)) + goto err; + for (k = 2; k < blocksize; k++) { + if (!EC_POINT_dbl(group, base, base, ctx)) + goto err; + } + } + } + + if (!EC_POINTs_make_affine(group, num, points, ctx)) + goto err; + + pre_comp->group = group; + pre_comp->blocksize = blocksize; + pre_comp->numblocks = numblocks; + pre_comp->w = w; + pre_comp->points = points; + points = NULL; + pre_comp->num = num; + SETPRECOMP(group, ec, pre_comp); + pre_comp = NULL; + ret = 1; + + err: + if (ctx != NULL) + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + EC_ec_pre_comp_free(pre_comp); + if (points) { + EC_POINT **p; + + for (p = points; *p != NULL; p++) + EC_POINT_free(*p); + OPENSSL_free(points); + } + EC_POINT_free(tmp_point); + EC_POINT_free(base); + return ret; +} + +int ec_wNAF_have_precompute_mult(const EC_GROUP *group) +{ + return HAVEPRECOMP(group, ec); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_oct.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_oct.c new file mode 100644 index 000000000..522f79e67 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_oct.c @@ -0,0 +1,150 @@ +/* + * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#include +#include + +#include "ec_lcl.h" + +int EC_POINT_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point, + const BIGNUM *x, int y_bit, BN_CTX *ctx) +{ + if (group->meth->point_set_compressed_coordinates == NULL + && !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) { + ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (!ec_point_is_compat(point, group)) { + ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES, + EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) { + if (group->meth->field_type == NID_X9_62_prime_field) + return ec_GFp_simple_set_compressed_coordinates(group, point, x, + y_bit, ctx); + else +#ifdef OPENSSL_NO_EC2M + { + ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES, + EC_R_GF2M_NOT_SUPPORTED); + return 0; + } +#else + return ec_GF2m_simple_set_compressed_coordinates(group, point, x, + y_bit, ctx); +#endif + } + return group->meth->point_set_compressed_coordinates(group, point, x, + y_bit, ctx); +} + +#if OPENSSL_API_COMPAT < 0x10200000L +int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, + EC_POINT *point, const BIGNUM *x, + int y_bit, BN_CTX *ctx) +{ + return EC_POINT_set_compressed_coordinates(group, point, x, y_bit, ctx); +} + +# ifndef OPENSSL_NO_EC2M +int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, + EC_POINT *point, const BIGNUM *x, + int y_bit, BN_CTX *ctx) +{ + return EC_POINT_set_compressed_coordinates(group, point, x, y_bit, ctx); +} +# endif +#endif + +size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point, + point_conversion_form_t form, unsigned char *buf, + size_t len, BN_CTX *ctx) +{ + if (group->meth->point2oct == 0 + && !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) { + ECerr(EC_F_EC_POINT_POINT2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (!ec_point_is_compat(point, group)) { + ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) { + if (group->meth->field_type == NID_X9_62_prime_field) + return ec_GFp_simple_point2oct(group, point, form, buf, len, ctx); + else +#ifdef OPENSSL_NO_EC2M + { + ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_GF2M_NOT_SUPPORTED); + return 0; + } +#else + return ec_GF2m_simple_point2oct(group, point, + form, buf, len, ctx); +#endif + } + + return group->meth->point2oct(group, point, form, buf, len, ctx); +} + +int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point, + const unsigned char *buf, size_t len, BN_CTX *ctx) +{ + if (group->meth->oct2point == 0 + && !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) { + ECerr(EC_F_EC_POINT_OCT2POINT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (!ec_point_is_compat(point, group)) { + ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) { + if (group->meth->field_type == NID_X9_62_prime_field) + return ec_GFp_simple_oct2point(group, point, buf, len, ctx); + else +#ifdef OPENSSL_NO_EC2M + { + ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_GF2M_NOT_SUPPORTED); + return 0; + } +#else + return ec_GF2m_simple_oct2point(group, point, buf, len, ctx); +#endif + } + return group->meth->oct2point(group, point, buf, len, ctx); +} + +size_t EC_POINT_point2buf(const EC_GROUP *group, const EC_POINT *point, + point_conversion_form_t form, + unsigned char **pbuf, BN_CTX *ctx) +{ + size_t len; + unsigned char *buf; + + len = EC_POINT_point2oct(group, point, form, NULL, 0, NULL); + if (len == 0) + return 0; + if ((buf = OPENSSL_malloc(len)) == NULL) { + ECerr(EC_F_EC_POINT_POINT2BUF, ERR_R_MALLOC_FAILURE); + return 0; + } + len = EC_POINT_point2oct(group, point, form, buf, len, ctx); + if (len == 0) { + OPENSSL_free(buf); + return 0; + } + *pbuf = buf; + return len; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_pmeth.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_pmeth.c new file mode 100644 index 000000000..f4ad0749e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_pmeth.c @@ -0,0 +1,472 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include "ec_lcl.h" +#include +#include "internal/evp_int.h" + +/* EC pkey context structure */ + +typedef struct { + /* Key and paramgen group */ + EC_GROUP *gen_group; + /* message digest */ + const EVP_MD *md; + /* Duplicate key if custom cofactor needed */ + EC_KEY *co_key; + /* Cofactor mode */ + signed char cofactor_mode; + /* KDF (if any) to use for ECDH */ + char kdf_type; + /* Message digest to use for key derivation */ + const EVP_MD *kdf_md; + /* User key material */ + unsigned char *kdf_ukm; + size_t kdf_ukmlen; + /* KDF output length */ + size_t kdf_outlen; +} EC_PKEY_CTX; + +static int pkey_ec_init(EVP_PKEY_CTX *ctx) +{ + EC_PKEY_CTX *dctx; + + if ((dctx = OPENSSL_zalloc(sizeof(*dctx))) == NULL) { + ECerr(EC_F_PKEY_EC_INIT, ERR_R_MALLOC_FAILURE); + return 0; + } + + dctx->cofactor_mode = -1; + dctx->kdf_type = EVP_PKEY_ECDH_KDF_NONE; + ctx->data = dctx; + return 1; +} + +static int pkey_ec_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) +{ + EC_PKEY_CTX *dctx, *sctx; + if (!pkey_ec_init(dst)) + return 0; + sctx = src->data; + dctx = dst->data; + if (sctx->gen_group) { + dctx->gen_group = EC_GROUP_dup(sctx->gen_group); + if (!dctx->gen_group) + return 0; + } + dctx->md = sctx->md; + + if (sctx->co_key) { + dctx->co_key = EC_KEY_dup(sctx->co_key); + if (!dctx->co_key) + return 0; + } + dctx->kdf_type = sctx->kdf_type; + dctx->kdf_md = sctx->kdf_md; + dctx->kdf_outlen = sctx->kdf_outlen; + if (sctx->kdf_ukm) { + dctx->kdf_ukm = OPENSSL_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen); + if (!dctx->kdf_ukm) + return 0; + } else + dctx->kdf_ukm = NULL; + dctx->kdf_ukmlen = sctx->kdf_ukmlen; + return 1; +} + +static void pkey_ec_cleanup(EVP_PKEY_CTX *ctx) +{ + EC_PKEY_CTX *dctx = ctx->data; + if (dctx != NULL) { + EC_GROUP_free(dctx->gen_group); + EC_KEY_free(dctx->co_key); + OPENSSL_free(dctx->kdf_ukm); + OPENSSL_free(dctx); + ctx->data = NULL; + } +} + +static int pkey_ec_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbslen) +{ + int ret, type; + unsigned int sltmp; + EC_PKEY_CTX *dctx = ctx->data; + EC_KEY *ec = ctx->pkey->pkey.ec; + const int sig_sz = ECDSA_size(ec); + + /* ensure cast to size_t is safe */ + if (!ossl_assert(sig_sz > 0)) + return 0; + + if (sig == NULL) { + *siglen = (size_t)sig_sz; + return 1; + } + + if (*siglen < (size_t)sig_sz) { + ECerr(EC_F_PKEY_EC_SIGN, EC_R_BUFFER_TOO_SMALL); + return 0; + } + + type = (dctx->md != NULL) ? EVP_MD_type(dctx->md) : NID_sha1; + + ret = ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec); + + if (ret <= 0) + return ret; + *siglen = (size_t)sltmp; + return 1; +} + +static int pkey_ec_verify(EVP_PKEY_CTX *ctx, + const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen) +{ + int ret, type; + EC_PKEY_CTX *dctx = ctx->data; + EC_KEY *ec = ctx->pkey->pkey.ec; + + if (dctx->md) + type = EVP_MD_type(dctx->md); + else + type = NID_sha1; + + ret = ECDSA_verify(type, tbs, tbslen, sig, siglen, ec); + + return ret; +} + +#ifndef OPENSSL_NO_EC +static int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) +{ + int ret; + size_t outlen; + const EC_POINT *pubkey = NULL; + EC_KEY *eckey; + EC_PKEY_CTX *dctx = ctx->data; + if (!ctx->pkey || !ctx->peerkey) { + ECerr(EC_F_PKEY_EC_DERIVE, EC_R_KEYS_NOT_SET); + return 0; + } + + eckey = dctx->co_key ? dctx->co_key : ctx->pkey->pkey.ec; + + if (!key) { + const EC_GROUP *group; + group = EC_KEY_get0_group(eckey); + *keylen = (EC_GROUP_get_degree(group) + 7) / 8; + return 1; + } + pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec); + + /* + * NB: unlike PKCS#3 DH, if *outlen is less than maximum size this is not + * an error, the result is truncated. + */ + + outlen = *keylen; + + ret = ECDH_compute_key(key, outlen, pubkey, eckey, 0); + if (ret <= 0) + return 0; + *keylen = ret; + return 1; +} + +static int pkey_ec_kdf_derive(EVP_PKEY_CTX *ctx, + unsigned char *key, size_t *keylen) +{ + EC_PKEY_CTX *dctx = ctx->data; + unsigned char *ktmp = NULL; + size_t ktmplen; + int rv = 0; + if (dctx->kdf_type == EVP_PKEY_ECDH_KDF_NONE) + return pkey_ec_derive(ctx, key, keylen); + if (!key) { + *keylen = dctx->kdf_outlen; + return 1; + } + if (*keylen != dctx->kdf_outlen) + return 0; + if (!pkey_ec_derive(ctx, NULL, &ktmplen)) + return 0; + if ((ktmp = OPENSSL_malloc(ktmplen)) == NULL) { + ECerr(EC_F_PKEY_EC_KDF_DERIVE, ERR_R_MALLOC_FAILURE); + return 0; + } + if (!pkey_ec_derive(ctx, ktmp, &ktmplen)) + goto err; + /* Do KDF stuff */ + if (!ecdh_KDF_X9_63(key, *keylen, ktmp, ktmplen, + dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md)) + goto err; + rv = 1; + + err: + OPENSSL_clear_free(ktmp, ktmplen); + return rv; +} +#endif + +static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) +{ + EC_PKEY_CTX *dctx = ctx->data; + EC_GROUP *group; + switch (type) { + case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID: + group = EC_GROUP_new_by_curve_name(p1); + if (group == NULL) { + ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_CURVE); + return 0; + } + EC_GROUP_free(dctx->gen_group); + dctx->gen_group = group; + return 1; + + case EVP_PKEY_CTRL_EC_PARAM_ENC: + if (!dctx->gen_group) { + ECerr(EC_F_PKEY_EC_CTRL, EC_R_NO_PARAMETERS_SET); + return 0; + } + EC_GROUP_set_asn1_flag(dctx->gen_group, p1); + return 1; + +#ifndef OPENSSL_NO_EC + case EVP_PKEY_CTRL_EC_ECDH_COFACTOR: + if (p1 == -2) { + if (dctx->cofactor_mode != -1) + return dctx->cofactor_mode; + else { + EC_KEY *ec_key = ctx->pkey->pkey.ec; + return EC_KEY_get_flags(ec_key) & EC_FLAG_COFACTOR_ECDH ? 1 : 0; + } + } else if (p1 < -1 || p1 > 1) + return -2; + dctx->cofactor_mode = p1; + if (p1 != -1) { + EC_KEY *ec_key = ctx->pkey->pkey.ec; + if (!ec_key->group) + return -2; + /* If cofactor is 1 cofactor mode does nothing */ + if (BN_is_one(ec_key->group->cofactor)) + return 1; + if (!dctx->co_key) { + dctx->co_key = EC_KEY_dup(ec_key); + if (!dctx->co_key) + return 0; + } + if (p1) + EC_KEY_set_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH); + else + EC_KEY_clear_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH); + } else { + EC_KEY_free(dctx->co_key); + dctx->co_key = NULL; + } + return 1; +#endif + + case EVP_PKEY_CTRL_EC_KDF_TYPE: + if (p1 == -2) + return dctx->kdf_type; + if (p1 != EVP_PKEY_ECDH_KDF_NONE && p1 != EVP_PKEY_ECDH_KDF_X9_63) + return -2; + dctx->kdf_type = p1; + return 1; + + case EVP_PKEY_CTRL_EC_KDF_MD: + dctx->kdf_md = p2; + return 1; + + case EVP_PKEY_CTRL_GET_EC_KDF_MD: + *(const EVP_MD **)p2 = dctx->kdf_md; + return 1; + + case EVP_PKEY_CTRL_EC_KDF_OUTLEN: + if (p1 <= 0) + return -2; + dctx->kdf_outlen = (size_t)p1; + return 1; + + case EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN: + *(int *)p2 = dctx->kdf_outlen; + return 1; + + case EVP_PKEY_CTRL_EC_KDF_UKM: + OPENSSL_free(dctx->kdf_ukm); + dctx->kdf_ukm = p2; + if (p2) + dctx->kdf_ukmlen = p1; + else + dctx->kdf_ukmlen = 0; + return 1; + + case EVP_PKEY_CTRL_GET_EC_KDF_UKM: + *(unsigned char **)p2 = dctx->kdf_ukm; + return dctx->kdf_ukmlen; + + case EVP_PKEY_CTRL_MD: + if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 && + EVP_MD_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 && + EVP_MD_type((const EVP_MD *)p2) != NID_sha224 && + EVP_MD_type((const EVP_MD *)p2) != NID_sha256 && + EVP_MD_type((const EVP_MD *)p2) != NID_sha384 && + EVP_MD_type((const EVP_MD *)p2) != NID_sha512) { + ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_DIGEST_TYPE); + return 0; + } + dctx->md = p2; + return 1; + + case EVP_PKEY_CTRL_GET_MD: + *(const EVP_MD **)p2 = dctx->md; + return 1; + + case EVP_PKEY_CTRL_PEER_KEY: + /* Default behaviour is OK */ + case EVP_PKEY_CTRL_DIGESTINIT: + case EVP_PKEY_CTRL_PKCS7_SIGN: + case EVP_PKEY_CTRL_CMS_SIGN: + return 1; + + default: + return -2; + + } +} + +static int pkey_ec_ctrl_str(EVP_PKEY_CTX *ctx, + const char *type, const char *value) +{ + if (strcmp(type, "ec_paramgen_curve") == 0) { + int nid; + nid = EC_curve_nist2nid(value); + if (nid == NID_undef) + nid = OBJ_sn2nid(value); + if (nid == NID_undef) + nid = OBJ_ln2nid(value); + if (nid == NID_undef) { + ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_CURVE); + return 0; + } + return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid); + } else if (strcmp(type, "ec_param_enc") == 0) { + int param_enc; + if (strcmp(value, "explicit") == 0) + param_enc = 0; + else if (strcmp(value, "named_curve") == 0) + param_enc = OPENSSL_EC_NAMED_CURVE; + else + return -2; + return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc); + } else if (strcmp(type, "ecdh_kdf_md") == 0) { + const EVP_MD *md; + if ((md = EVP_get_digestbyname(value)) == NULL) { + ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_DIGEST); + return 0; + } + return EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md); + } else if (strcmp(type, "ecdh_cofactor_mode") == 0) { + int co_mode; + co_mode = atoi(value); + return EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, co_mode); + } + + return -2; +} + +static int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) +{ + EC_KEY *ec = NULL; + EC_PKEY_CTX *dctx = ctx->data; + int ret; + + if (dctx->gen_group == NULL) { + ECerr(EC_F_PKEY_EC_PARAMGEN, EC_R_NO_PARAMETERS_SET); + return 0; + } + ec = EC_KEY_new(); + if (ec == NULL) + return 0; + if (!(ret = EC_KEY_set_group(ec, dctx->gen_group)) + || !ossl_assert(ret = EVP_PKEY_assign_EC_KEY(pkey, ec))) + EC_KEY_free(ec); + return ret; +} + +static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) +{ + EC_KEY *ec = NULL; + EC_PKEY_CTX *dctx = ctx->data; + int ret; + + if (ctx->pkey == NULL && dctx->gen_group == NULL) { + ECerr(EC_F_PKEY_EC_KEYGEN, EC_R_NO_PARAMETERS_SET); + return 0; + } + ec = EC_KEY_new(); + if (ec == NULL) + return 0; + if (!ossl_assert(EVP_PKEY_assign_EC_KEY(pkey, ec))) { + EC_KEY_free(ec); + return 0; + } + /* Note: if error is returned, we count on caller to free pkey->pkey.ec */ + if (ctx->pkey != NULL) + ret = EVP_PKEY_copy_parameters(pkey, ctx->pkey); + else + ret = EC_KEY_set_group(ec, dctx->gen_group); + + return ret ? EC_KEY_generate_key(ec) : 0; +} + +const EVP_PKEY_METHOD ec_pkey_meth = { + EVP_PKEY_EC, + 0, + pkey_ec_init, + pkey_ec_copy, + pkey_ec_cleanup, + + 0, + pkey_ec_paramgen, + + 0, + pkey_ec_keygen, + + 0, + pkey_ec_sign, + + 0, + pkey_ec_verify, + + 0, 0, + + 0, 0, 0, 0, + + 0, + 0, + + 0, + 0, + + 0, +#ifndef OPENSSL_NO_EC + pkey_ec_kdf_derive, +#else + 0, +#endif + pkey_ec_ctrl, + pkey_ec_ctrl_str +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_print.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_print.c new file mode 100644 index 000000000..027a51928 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ec_print.c @@ -0,0 +1,121 @@ +/* + * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "ec_lcl.h" + +BIGNUM *EC_POINT_point2bn(const EC_GROUP *group, + const EC_POINT *point, + point_conversion_form_t form, + BIGNUM *ret, BN_CTX *ctx) +{ + size_t buf_len = 0; + unsigned char *buf; + + buf_len = EC_POINT_point2buf(group, point, form, &buf, ctx); + + if (buf_len == 0) + return NULL; + + ret = BN_bin2bn(buf, buf_len, ret); + + OPENSSL_free(buf); + + return ret; +} + +EC_POINT *EC_POINT_bn2point(const EC_GROUP *group, + const BIGNUM *bn, EC_POINT *point, BN_CTX *ctx) +{ + size_t buf_len = 0; + unsigned char *buf; + EC_POINT *ret; + + if ((buf_len = BN_num_bytes(bn)) == 0) + return NULL; + if ((buf = OPENSSL_malloc(buf_len)) == NULL) { + ECerr(EC_F_EC_POINT_BN2POINT, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (!BN_bn2bin(bn, buf)) { + OPENSSL_free(buf); + return NULL; + } + + if (point == NULL) { + if ((ret = EC_POINT_new(group)) == NULL) { + OPENSSL_free(buf); + return NULL; + } + } else + ret = point; + + if (!EC_POINT_oct2point(group, ret, buf, buf_len, ctx)) { + if (ret != point) + EC_POINT_clear_free(ret); + OPENSSL_free(buf); + return NULL; + } + + OPENSSL_free(buf); + return ret; +} + +static const char *HEX_DIGITS = "0123456789ABCDEF"; + +/* the return value must be freed (using OPENSSL_free()) */ +char *EC_POINT_point2hex(const EC_GROUP *group, + const EC_POINT *point, + point_conversion_form_t form, BN_CTX *ctx) +{ + char *ret, *p; + size_t buf_len = 0, i; + unsigned char *buf = NULL, *pbuf; + + buf_len = EC_POINT_point2buf(group, point, form, &buf, ctx); + + if (buf_len == 0) + return NULL; + + ret = OPENSSL_malloc(buf_len * 2 + 2); + if (ret == NULL) { + OPENSSL_free(buf); + return NULL; + } + p = ret; + pbuf = buf; + for (i = buf_len; i > 0; i--) { + int v = (int)*(pbuf++); + *(p++) = HEX_DIGITS[v >> 4]; + *(p++) = HEX_DIGITS[v & 0x0F]; + } + *p = '\0'; + + OPENSSL_free(buf); + + return ret; +} + +EC_POINT *EC_POINT_hex2point(const EC_GROUP *group, + const char *buf, EC_POINT *point, BN_CTX *ctx) +{ + EC_POINT *ret = NULL; + BIGNUM *tmp_bn = NULL; + + if (!BN_hex2bn(&tmp_bn, buf)) + return NULL; + + ret = EC_POINT_bn2point(group, tmp_bn, point, ctx); + + BN_clear_free(tmp_bn); + + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecdh_kdf.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecdh_kdf.c new file mode 100644 index 000000000..d686f9d89 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecdh_kdf.c @@ -0,0 +1,81 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "ec_lcl.h" + +/* Key derivation function from X9.63/SECG */ +/* Way more than we will ever need */ +#define ECDH_KDF_MAX (1 << 30) + +int ecdh_KDF_X9_63(unsigned char *out, size_t outlen, + const unsigned char *Z, size_t Zlen, + const unsigned char *sinfo, size_t sinfolen, + const EVP_MD *md) +{ + EVP_MD_CTX *mctx = NULL; + int rv = 0; + unsigned int i; + size_t mdlen; + unsigned char ctr[4]; + if (sinfolen > ECDH_KDF_MAX || outlen > ECDH_KDF_MAX + || Zlen > ECDH_KDF_MAX) + return 0; + mctx = EVP_MD_CTX_new(); + if (mctx == NULL) + return 0; + mdlen = EVP_MD_size(md); + for (i = 1;; i++) { + unsigned char mtmp[EVP_MAX_MD_SIZE]; + if (!EVP_DigestInit_ex(mctx, md, NULL)) + goto err; + ctr[3] = i & 0xFF; + ctr[2] = (i >> 8) & 0xFF; + ctr[1] = (i >> 16) & 0xFF; + ctr[0] = (i >> 24) & 0xFF; + if (!EVP_DigestUpdate(mctx, Z, Zlen)) + goto err; + if (!EVP_DigestUpdate(mctx, ctr, sizeof(ctr))) + goto err; + if (!EVP_DigestUpdate(mctx, sinfo, sinfolen)) + goto err; + if (outlen >= mdlen) { + if (!EVP_DigestFinal(mctx, out, NULL)) + goto err; + outlen -= mdlen; + if (outlen == 0) + break; + out += mdlen; + } else { + if (!EVP_DigestFinal(mctx, mtmp, NULL)) + goto err; + memcpy(out, mtmp, outlen); + OPENSSL_cleanse(mtmp, mdlen); + break; + } + } + rv = 1; + err: + EVP_MD_CTX_free(mctx); + return rv; +} + +/*- + * The old name for ecdh_KDF_X9_63 + * Retained for ABI compatibility + */ +int ECDH_KDF_X9_62(unsigned char *out, size_t outlen, + const unsigned char *Z, size_t Zlen, + const unsigned char *sinfo, size_t sinfolen, + const EVP_MD *md) +{ + return ecdh_KDF_X9_63(out, outlen, Z, Zlen, sinfo, sinfolen, md); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecdh_ossl.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecdh_ossl.c new file mode 100644 index 000000000..bd93793a1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecdh_ossl.c @@ -0,0 +1,121 @@ +/* + * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#include "internal/cryptlib.h" + +#include +#include +#include +#include +#include "ec_lcl.h" + +int ossl_ecdh_compute_key(unsigned char **psec, size_t *pseclen, + const EC_POINT *pub_key, const EC_KEY *ecdh) +{ + if (ecdh->group->meth->ecdh_compute_key == NULL) { + ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, EC_R_CURVE_DOES_NOT_SUPPORT_ECDH); + return 0; + } + + return ecdh->group->meth->ecdh_compute_key(psec, pseclen, pub_key, ecdh); +} + +/*- + * This implementation is based on the following primitives in the IEEE 1363 standard: + * - ECKAS-DH1 + * - ECSVDP-DH + */ +int ecdh_simple_compute_key(unsigned char **pout, size_t *poutlen, + const EC_POINT *pub_key, const EC_KEY *ecdh) +{ + BN_CTX *ctx; + EC_POINT *tmp = NULL; + BIGNUM *x = NULL; + const BIGNUM *priv_key; + const EC_GROUP *group; + int ret = 0; + size_t buflen, len; + unsigned char *buf = NULL; + + if ((ctx = BN_CTX_new()) == NULL) + goto err; + BN_CTX_start(ctx); + x = BN_CTX_get(ctx); + if (x == NULL) { + ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); + goto err; + } + + priv_key = EC_KEY_get0_private_key(ecdh); + if (priv_key == NULL) { + ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, EC_R_NO_PRIVATE_VALUE); + goto err; + } + + group = EC_KEY_get0_group(ecdh); + + if (EC_KEY_get_flags(ecdh) & EC_FLAG_COFACTOR_ECDH) { + if (!EC_GROUP_get_cofactor(group, x, NULL) || + !BN_mul(x, x, priv_key, ctx)) { + ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); + goto err; + } + priv_key = x; + } + + if ((tmp = EC_POINT_new(group)) == NULL) { + ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!EC_POINT_mul(group, tmp, NULL, pub_key, priv_key, ctx)) { + ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, EC_R_POINT_ARITHMETIC_FAILURE); + goto err; + } + + if (!EC_POINT_get_affine_coordinates(group, tmp, x, NULL, ctx)) { + ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, EC_R_POINT_ARITHMETIC_FAILURE); + goto err; + } + + buflen = (EC_GROUP_get_degree(group) + 7) / 8; + len = BN_num_bytes(x); + if (len > buflen) { + ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_INTERNAL_ERROR); + goto err; + } + if ((buf = OPENSSL_malloc(buflen)) == NULL) { + ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); + goto err; + } + + memset(buf, 0, buflen - len); + if (len != (size_t)BN_bn2bin(x, buf + buflen - len)) { + ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_BN_LIB); + goto err; + } + + *pout = buf; + *poutlen = buflen; + buf = NULL; + + ret = 1; + + err: + EC_POINT_free(tmp); + if (ctx) + BN_CTX_end(ctx); + BN_CTX_free(ctx); + OPENSSL_free(buf); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecdsa_ossl.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecdsa_ossl.c new file mode 100644 index 000000000..e35c7600d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecdsa_ossl.c @@ -0,0 +1,417 @@ +/* + * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include "internal/bn_int.h" +#include "ec_lcl.h" + +int ossl_ecdsa_sign(int type, const unsigned char *dgst, int dlen, + unsigned char *sig, unsigned int *siglen, + const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey) +{ + ECDSA_SIG *s; + + s = ECDSA_do_sign_ex(dgst, dlen, kinv, r, eckey); + if (s == NULL) { + *siglen = 0; + return 0; + } + *siglen = i2d_ECDSA_SIG(s, &sig); + ECDSA_SIG_free(s); + return 1; +} + +static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, + BIGNUM **kinvp, BIGNUM **rp, + const unsigned char *dgst, int dlen) +{ + BN_CTX *ctx = NULL; + BIGNUM *k = NULL, *r = NULL, *X = NULL; + const BIGNUM *order; + EC_POINT *tmp_point = NULL; + const EC_GROUP *group; + int ret = 0; + int order_bits; + + if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL) { + ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (!EC_KEY_can_sign(eckey)) { + ECerr(EC_F_ECDSA_SIGN_SETUP, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING); + return 0; + } + + if ((ctx = ctx_in) == NULL) { + if ((ctx = BN_CTX_new()) == NULL) { + ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE); + return 0; + } + } + + k = BN_new(); /* this value is later returned in *kinvp */ + r = BN_new(); /* this value is later returned in *rp */ + X = BN_new(); + if (k == NULL || r == NULL || X == NULL) { + ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE); + goto err; + } + if ((tmp_point = EC_POINT_new(group)) == NULL) { + ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); + goto err; + } + order = EC_GROUP_get0_order(group); + + /* Preallocate space */ + order_bits = BN_num_bits(order); + if (!BN_set_bit(k, order_bits) + || !BN_set_bit(r, order_bits) + || !BN_set_bit(X, order_bits)) + goto err; + + do { + /* get random k */ + do { + if (dgst != NULL) { + if (!BN_generate_dsa_nonce(k, order, + EC_KEY_get0_private_key(eckey), + dgst, dlen, ctx)) { + ECerr(EC_F_ECDSA_SIGN_SETUP, + EC_R_RANDOM_NUMBER_GENERATION_FAILED); + goto err; + } + } else { + if (!BN_priv_rand_range(k, order)) { + ECerr(EC_F_ECDSA_SIGN_SETUP, + EC_R_RANDOM_NUMBER_GENERATION_FAILED); + goto err; + } + } + } while (BN_is_zero(k)); + + /* compute r the x-coordinate of generator * k */ + if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) { + ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); + goto err; + } + + if (!EC_POINT_get_affine_coordinates(group, tmp_point, X, NULL, ctx)) { + ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); + goto err; + } + + if (!BN_nnmod(r, X, order, ctx)) { + ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); + goto err; + } + } while (BN_is_zero(r)); + + /* compute the inverse of k */ + if (!ec_group_do_inverse_ord(group, k, k, ctx)) { + ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); + goto err; + } + + /* clear old values if necessary */ + BN_clear_free(*rp); + BN_clear_free(*kinvp); + /* save the pre-computed values */ + *rp = r; + *kinvp = k; + ret = 1; + err: + if (!ret) { + BN_clear_free(k); + BN_clear_free(r); + } + if (ctx != ctx_in) + BN_CTX_free(ctx); + EC_POINT_free(tmp_point); + BN_clear_free(X); + return ret; +} + +int ossl_ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, + BIGNUM **rp) +{ + return ecdsa_sign_setup(eckey, ctx_in, kinvp, rp, NULL, 0); +} + +ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len, + const BIGNUM *in_kinv, const BIGNUM *in_r, + EC_KEY *eckey) +{ + int ok = 0, i; + BIGNUM *kinv = NULL, *s, *m = NULL; + const BIGNUM *order, *ckinv; + BN_CTX *ctx = NULL; + const EC_GROUP *group; + ECDSA_SIG *ret; + const BIGNUM *priv_key; + + group = EC_KEY_get0_group(eckey); + priv_key = EC_KEY_get0_private_key(eckey); + + if (group == NULL || priv_key == NULL) { + ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + if (!EC_KEY_can_sign(eckey)) { + ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING); + return NULL; + } + + ret = ECDSA_SIG_new(); + if (ret == NULL) { + ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE); + return NULL; + } + ret->r = BN_new(); + ret->s = BN_new(); + if (ret->r == NULL || ret->s == NULL) { + ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE); + goto err; + } + s = ret->s; + + if ((ctx = BN_CTX_new()) == NULL + || (m = BN_new()) == NULL) { + ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE); + goto err; + } + + order = EC_GROUP_get0_order(group); + i = BN_num_bits(order); + /* + * Need to truncate digest if it is too long: first truncate whole bytes. + */ + if (8 * dgst_len > i) + dgst_len = (i + 7) / 8; + if (!BN_bin2bn(dgst, dgst_len, m)) { + ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB); + goto err; + } + /* If still too long, truncate remaining bits with a shift */ + if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) { + ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB); + goto err; + } + do { + if (in_kinv == NULL || in_r == NULL) { + if (!ecdsa_sign_setup(eckey, ctx, &kinv, &ret->r, dgst, dgst_len)) { + ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_ECDSA_LIB); + goto err; + } + ckinv = kinv; + } else { + ckinv = in_kinv; + if (BN_copy(ret->r, in_r) == NULL) { + ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + /* + * With only one multiplicant being in Montgomery domain + * multiplication yields real result without post-conversion. + * Also note that all operations but last are performed with + * zero-padded vectors. Last operation, BN_mod_mul_montgomery + * below, returns user-visible value with removed zero padding. + */ + if (!bn_to_mont_fixed_top(s, ret->r, group->mont_data, ctx) + || !bn_mul_mont_fixed_top(s, s, priv_key, group->mont_data, ctx)) { + ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB); + goto err; + } + if (!bn_mod_add_fixed_top(s, s, m, order)) { + ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB); + goto err; + } + /* + * |s| can still be larger than modulus, because |m| can be. In + * such case we count on Montgomery reduction to tie it up. + */ + if (!bn_to_mont_fixed_top(s, s, group->mont_data, ctx) + || !BN_mod_mul_montgomery(s, s, ckinv, group->mont_data, ctx)) { + ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB); + goto err; + } + + if (BN_is_zero(s)) { + /* + * if kinv and r have been supplied by the caller, don't + * generate new kinv and r values + */ + if (in_kinv != NULL && in_r != NULL) { + ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, EC_R_NEED_NEW_SETUP_VALUES); + goto err; + } + } else { + /* s != 0 => we have a valid signature */ + break; + } + } while (1); + + ok = 1; + err: + if (!ok) { + ECDSA_SIG_free(ret); + ret = NULL; + } + BN_CTX_free(ctx); + BN_clear_free(m); + BN_clear_free(kinv); + return ret; +} + +/*- + * returns + * 1: correct signature + * 0: incorrect signature + * -1: error + */ +int ossl_ecdsa_verify(int type, const unsigned char *dgst, int dgst_len, + const unsigned char *sigbuf, int sig_len, EC_KEY *eckey) +{ + ECDSA_SIG *s; + const unsigned char *p = sigbuf; + unsigned char *der = NULL; + int derlen = -1; + int ret = -1; + + s = ECDSA_SIG_new(); + if (s == NULL) + return ret; + if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL) + goto err; + /* Ensure signature uses DER and doesn't have trailing garbage */ + derlen = i2d_ECDSA_SIG(s, &der); + if (derlen != sig_len || memcmp(sigbuf, der, derlen) != 0) + goto err; + ret = ECDSA_do_verify(dgst, dgst_len, s, eckey); + err: + OPENSSL_clear_free(der, derlen); + ECDSA_SIG_free(s); + return ret; +} + +int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len, + const ECDSA_SIG *sig, EC_KEY *eckey) +{ + int ret = -1, i; + BN_CTX *ctx; + const BIGNUM *order; + BIGNUM *u1, *u2, *m, *X; + EC_POINT *point = NULL; + const EC_GROUP *group; + const EC_POINT *pub_key; + + /* check input values */ + if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL || + (pub_key = EC_KEY_get0_public_key(eckey)) == NULL || sig == NULL) { + ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, EC_R_MISSING_PARAMETERS); + return -1; + } + + if (!EC_KEY_can_sign(eckey)) { + ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING); + return -1; + } + + ctx = BN_CTX_new(); + if (ctx == NULL) { + ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_MALLOC_FAILURE); + return -1; + } + BN_CTX_start(ctx); + u1 = BN_CTX_get(ctx); + u2 = BN_CTX_get(ctx); + m = BN_CTX_get(ctx); + X = BN_CTX_get(ctx); + if (X == NULL) { + ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB); + goto err; + } + + order = EC_GROUP_get0_order(group); + if (order == NULL) { + ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_EC_LIB); + goto err; + } + + if (BN_is_zero(sig->r) || BN_is_negative(sig->r) || + BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s) || + BN_is_negative(sig->s) || BN_ucmp(sig->s, order) >= 0) { + ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, EC_R_BAD_SIGNATURE); + ret = 0; /* signature is invalid */ + goto err; + } + /* calculate tmp1 = inv(S) mod order */ + if (!ec_group_do_inverse_ord(group, u2, sig->s, ctx)) { + ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB); + goto err; + } + /* digest -> m */ + i = BN_num_bits(order); + /* + * Need to truncate digest if it is too long: first truncate whole bytes. + */ + if (8 * dgst_len > i) + dgst_len = (i + 7) / 8; + if (!BN_bin2bn(dgst, dgst_len, m)) { + ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB); + goto err; + } + /* If still too long truncate remaining bits with a shift */ + if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) { + ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB); + goto err; + } + /* u1 = m * tmp mod order */ + if (!BN_mod_mul(u1, m, u2, order, ctx)) { + ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB); + goto err; + } + /* u2 = r * w mod q */ + if (!BN_mod_mul(u2, sig->r, u2, order, ctx)) { + ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB); + goto err; + } + + if ((point = EC_POINT_new(group)) == NULL) { + ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx)) { + ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_EC_LIB); + goto err; + } + + if (!EC_POINT_get_affine_coordinates(group, point, X, NULL, ctx)) { + ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_EC_LIB); + goto err; + } + + if (!BN_nnmod(u1, X, order, ctx)) { + ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB); + goto err; + } + /* if the signature is correct u1 is equal to sig->r */ + ret = (BN_ucmp(u1, sig->r) == 0); + err: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + EC_POINT_free(point); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecdsa_sign.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecdsa_sign.c new file mode 100644 index 000000000..aee06e991 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecdsa_sign.c @@ -0,0 +1,52 @@ +/* + * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "ec_lcl.h" +#include + +ECDSA_SIG *ECDSA_do_sign(const unsigned char *dgst, int dlen, EC_KEY *eckey) +{ + return ECDSA_do_sign_ex(dgst, dlen, NULL, NULL, eckey); +} + +ECDSA_SIG *ECDSA_do_sign_ex(const unsigned char *dgst, int dlen, + const BIGNUM *kinv, const BIGNUM *rp, + EC_KEY *eckey) +{ + if (eckey->meth->sign_sig != NULL) + return eckey->meth->sign_sig(dgst, dlen, kinv, rp, eckey); + ECerr(EC_F_ECDSA_DO_SIGN_EX, EC_R_OPERATION_NOT_SUPPORTED); + return NULL; +} + +int ECDSA_sign(int type, const unsigned char *dgst, int dlen, unsigned char + *sig, unsigned int *siglen, EC_KEY *eckey) +{ + return ECDSA_sign_ex(type, dgst, dlen, sig, siglen, NULL, NULL, eckey); +} + +int ECDSA_sign_ex(int type, const unsigned char *dgst, int dlen, + unsigned char *sig, unsigned int *siglen, const BIGNUM *kinv, + const BIGNUM *r, EC_KEY *eckey) +{ + if (eckey->meth->sign != NULL) + return eckey->meth->sign(type, dgst, dlen, sig, siglen, kinv, r, eckey); + ECerr(EC_F_ECDSA_SIGN_EX, EC_R_OPERATION_NOT_SUPPORTED); + return 0; +} + +int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, + BIGNUM **rp) +{ + if (eckey->meth->sign_setup != NULL) + return eckey->meth->sign_setup(eckey, ctx_in, kinvp, rp); + ECerr(EC_F_ECDSA_SIGN_SETUP, EC_R_OPERATION_NOT_SUPPORTED); + return 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecdsa_vrf.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecdsa_vrf.c new file mode 100644 index 000000000..f61a20063 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecdsa_vrf.c @@ -0,0 +1,43 @@ +/* + * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "ec_lcl.h" +#include + +/*- + * returns + * 1: correct signature + * 0: incorrect signature + * -1: error + */ +int ECDSA_do_verify(const unsigned char *dgst, int dgst_len, + const ECDSA_SIG *sig, EC_KEY *eckey) +{ + if (eckey->meth->verify_sig != NULL) + return eckey->meth->verify_sig(dgst, dgst_len, sig, eckey); + ECerr(EC_F_ECDSA_DO_VERIFY, EC_R_OPERATION_NOT_SUPPORTED); + return 0; +} + +/*- + * returns + * 1: correct signature + * 0: incorrect signature + * -1: error + */ +int ECDSA_verify(int type, const unsigned char *dgst, int dgst_len, + const unsigned char *sigbuf, int sig_len, EC_KEY *eckey) +{ + if (eckey->meth->verify != NULL) + return eckey->meth->verify(type, dgst, dgst_len, sigbuf, sig_len, + eckey); + ECerr(EC_F_ECDSA_VERIFY, EC_R_OPERATION_NOT_SUPPORTED); + return 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/eck_prn.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/eck_prn.c new file mode 100644 index 000000000..b538fadcb --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/eck_prn.c @@ -0,0 +1,259 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include + +#ifndef OPENSSL_NO_STDIO +int ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off) +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + ECerr(EC_F_ECPKPARAMETERS_PRINT_FP, ERR_R_BUF_LIB); + return 0; + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = ECPKParameters_print(b, x, off); + BIO_free(b); + return ret; +} + +int EC_KEY_print_fp(FILE *fp, const EC_KEY *x, int off) +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + ECerr(EC_F_EC_KEY_PRINT_FP, ERR_R_BIO_LIB); + return 0; + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = EC_KEY_print(b, x, off); + BIO_free(b); + return ret; +} + +int ECParameters_print_fp(FILE *fp, const EC_KEY *x) +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + ECerr(EC_F_ECPARAMETERS_PRINT_FP, ERR_R_BIO_LIB); + return 0; + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = ECParameters_print(b, x); + BIO_free(b); + return ret; +} +#endif + +static int print_bin(BIO *fp, const char *str, const unsigned char *num, + size_t len, int off); + +int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off) +{ + int ret = 0, reason = ERR_R_BIO_LIB; + BN_CTX *ctx = NULL; + const EC_POINT *point = NULL; + BIGNUM *p = NULL, *a = NULL, *b = NULL, *gen = NULL; + const BIGNUM *order = NULL, *cofactor = NULL; + const unsigned char *seed; + size_t seed_len = 0; + + static const char *gen_compressed = "Generator (compressed):"; + static const char *gen_uncompressed = "Generator (uncompressed):"; + static const char *gen_hybrid = "Generator (hybrid):"; + + if (!x) { + reason = ERR_R_PASSED_NULL_PARAMETER; + goto err; + } + + ctx = BN_CTX_new(); + if (ctx == NULL) { + reason = ERR_R_MALLOC_FAILURE; + goto err; + } + + if (EC_GROUP_get_asn1_flag(x)) { + /* the curve parameter are given by an asn1 OID */ + int nid; + const char *nname; + + if (!BIO_indent(bp, off, 128)) + goto err; + + nid = EC_GROUP_get_curve_name(x); + if (nid == 0) + goto err; + if (BIO_printf(bp, "ASN1 OID: %s", OBJ_nid2sn(nid)) <= 0) + goto err; + if (BIO_printf(bp, "\n") <= 0) + goto err; + nname = EC_curve_nid2nist(nid); + if (nname) { + if (!BIO_indent(bp, off, 128)) + goto err; + if (BIO_printf(bp, "NIST CURVE: %s\n", nname) <= 0) + goto err; + } + } else { + /* explicit parameters */ + int is_char_two = 0; + point_conversion_form_t form; + int tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(x)); + + if (tmp_nid == NID_X9_62_characteristic_two_field) + is_char_two = 1; + + if ((p = BN_new()) == NULL || (a = BN_new()) == NULL || + (b = BN_new()) == NULL) { + reason = ERR_R_MALLOC_FAILURE; + goto err; + } + + if (!EC_GROUP_get_curve(x, p, a, b, ctx)) { + reason = ERR_R_EC_LIB; + goto err; + } + + if ((point = EC_GROUP_get0_generator(x)) == NULL) { + reason = ERR_R_EC_LIB; + goto err; + } + order = EC_GROUP_get0_order(x); + cofactor = EC_GROUP_get0_cofactor(x); + if (order == NULL) { + reason = ERR_R_EC_LIB; + goto err; + } + + form = EC_GROUP_get_point_conversion_form(x); + + if ((gen = EC_POINT_point2bn(x, point, form, NULL, ctx)) == NULL) { + reason = ERR_R_EC_LIB; + goto err; + } + + if ((seed = EC_GROUP_get0_seed(x)) != NULL) + seed_len = EC_GROUP_get_seed_len(x); + + if (!BIO_indent(bp, off, 128)) + goto err; + + /* print the 'short name' of the field type */ + if (BIO_printf(bp, "Field Type: %s\n", OBJ_nid2sn(tmp_nid)) + <= 0) + goto err; + + if (is_char_two) { + /* print the 'short name' of the base type OID */ + int basis_type = EC_GROUP_get_basis_type(x); + if (basis_type == 0) + goto err; + + if (!BIO_indent(bp, off, 128)) + goto err; + + if (BIO_printf(bp, "Basis Type: %s\n", + OBJ_nid2sn(basis_type)) <= 0) + goto err; + + /* print the polynomial */ + if ((p != NULL) && !ASN1_bn_print(bp, "Polynomial:", p, NULL, + off)) + goto err; + } else { + if ((p != NULL) && !ASN1_bn_print(bp, "Prime:", p, NULL, off)) + goto err; + } + if ((a != NULL) && !ASN1_bn_print(bp, "A: ", a, NULL, off)) + goto err; + if ((b != NULL) && !ASN1_bn_print(bp, "B: ", b, NULL, off)) + goto err; + if (form == POINT_CONVERSION_COMPRESSED) { + if ((gen != NULL) && !ASN1_bn_print(bp, gen_compressed, gen, + NULL, off)) + goto err; + } else if (form == POINT_CONVERSION_UNCOMPRESSED) { + if ((gen != NULL) && !ASN1_bn_print(bp, gen_uncompressed, gen, + NULL, off)) + goto err; + } else { /* form == POINT_CONVERSION_HYBRID */ + + if ((gen != NULL) && !ASN1_bn_print(bp, gen_hybrid, gen, + NULL, off)) + goto err; + } + if ((order != NULL) && !ASN1_bn_print(bp, "Order: ", order, + NULL, off)) + goto err; + if ((cofactor != NULL) && !ASN1_bn_print(bp, "Cofactor: ", cofactor, + NULL, off)) + goto err; + if (seed && !print_bin(bp, "Seed:", seed, seed_len, off)) + goto err; + } + ret = 1; + err: + if (!ret) + ECerr(EC_F_ECPKPARAMETERS_PRINT, reason); + BN_free(p); + BN_free(a); + BN_free(b); + BN_free(gen); + BN_CTX_free(ctx); + return ret; +} + +static int print_bin(BIO *fp, const char *name, const unsigned char *buf, + size_t len, int off) +{ + size_t i; + char str[128 + 1 + 4]; + + if (buf == NULL) + return 1; + if (off > 0) { + if (off > 128) + off = 128; + memset(str, ' ', off); + if (BIO_write(fp, str, off) <= 0) + return 0; + } else { + off = 0; + } + + if (BIO_printf(fp, "%s", name) <= 0) + return 0; + + for (i = 0; i < len; i++) { + if ((i % 15) == 0) { + str[0] = '\n'; + memset(&(str[1]), ' ', off + 4); + if (BIO_write(fp, str, off + 1 + 4) <= 0) + return 0; + } + if (BIO_printf(fp, "%02x%s", buf[i], ((i + 1) == len) ? "" : ":") <= + 0) + return 0; + } + if (BIO_write(fp, "\n", 1) <= 0) + return 0; + + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_mont.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_mont.c new file mode 100644 index 000000000..252e66ef3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_mont.c @@ -0,0 +1,291 @@ +/* + * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#include "ec_lcl.h" + +const EC_METHOD *EC_GFp_mont_method(void) +{ + static const EC_METHOD ret = { + EC_FLAGS_DEFAULT_OCT, + NID_X9_62_prime_field, + ec_GFp_mont_group_init, + ec_GFp_mont_group_finish, + ec_GFp_mont_group_clear_finish, + ec_GFp_mont_group_copy, + ec_GFp_mont_group_set_curve, + ec_GFp_simple_group_get_curve, + ec_GFp_simple_group_get_degree, + ec_group_simple_order_bits, + ec_GFp_simple_group_check_discriminant, + ec_GFp_simple_point_init, + ec_GFp_simple_point_finish, + ec_GFp_simple_point_clear_finish, + ec_GFp_simple_point_copy, + ec_GFp_simple_point_set_to_infinity, + ec_GFp_simple_set_Jprojective_coordinates_GFp, + ec_GFp_simple_get_Jprojective_coordinates_GFp, + ec_GFp_simple_point_set_affine_coordinates, + ec_GFp_simple_point_get_affine_coordinates, + 0, 0, 0, + ec_GFp_simple_add, + ec_GFp_simple_dbl, + ec_GFp_simple_invert, + ec_GFp_simple_is_at_infinity, + ec_GFp_simple_is_on_curve, + ec_GFp_simple_cmp, + ec_GFp_simple_make_affine, + ec_GFp_simple_points_make_affine, + 0 /* mul */ , + 0 /* precompute_mult */ , + 0 /* have_precompute_mult */ , + ec_GFp_mont_field_mul, + ec_GFp_mont_field_sqr, + 0 /* field_div */ , + ec_GFp_mont_field_inv, + ec_GFp_mont_field_encode, + ec_GFp_mont_field_decode, + ec_GFp_mont_field_set_to_one, + ec_key_simple_priv2oct, + ec_key_simple_oct2priv, + 0, /* set private */ + ec_key_simple_generate_key, + ec_key_simple_check_key, + ec_key_simple_generate_public_key, + 0, /* keycopy */ + 0, /* keyfinish */ + ecdh_simple_compute_key, + 0, /* field_inverse_mod_ord */ + ec_GFp_simple_blind_coordinates, + ec_GFp_simple_ladder_pre, + ec_GFp_simple_ladder_step, + ec_GFp_simple_ladder_post + }; + + return &ret; +} + +int ec_GFp_mont_group_init(EC_GROUP *group) +{ + int ok; + + ok = ec_GFp_simple_group_init(group); + group->field_data1 = NULL; + group->field_data2 = NULL; + return ok; +} + +void ec_GFp_mont_group_finish(EC_GROUP *group) +{ + BN_MONT_CTX_free(group->field_data1); + group->field_data1 = NULL; + BN_free(group->field_data2); + group->field_data2 = NULL; + ec_GFp_simple_group_finish(group); +} + +void ec_GFp_mont_group_clear_finish(EC_GROUP *group) +{ + BN_MONT_CTX_free(group->field_data1); + group->field_data1 = NULL; + BN_clear_free(group->field_data2); + group->field_data2 = NULL; + ec_GFp_simple_group_clear_finish(group); +} + +int ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src) +{ + BN_MONT_CTX_free(dest->field_data1); + dest->field_data1 = NULL; + BN_clear_free(dest->field_data2); + dest->field_data2 = NULL; + + if (!ec_GFp_simple_group_copy(dest, src)) + return 0; + + if (src->field_data1 != NULL) { + dest->field_data1 = BN_MONT_CTX_new(); + if (dest->field_data1 == NULL) + return 0; + if (!BN_MONT_CTX_copy(dest->field_data1, src->field_data1)) + goto err; + } + if (src->field_data2 != NULL) { + dest->field_data2 = BN_dup(src->field_data2); + if (dest->field_data2 == NULL) + goto err; + } + + return 1; + + err: + BN_MONT_CTX_free(dest->field_data1); + dest->field_data1 = NULL; + return 0; +} + +int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) +{ + BN_CTX *new_ctx = NULL; + BN_MONT_CTX *mont = NULL; + BIGNUM *one = NULL; + int ret = 0; + + BN_MONT_CTX_free(group->field_data1); + group->field_data1 = NULL; + BN_free(group->field_data2); + group->field_data2 = NULL; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + mont = BN_MONT_CTX_new(); + if (mont == NULL) + goto err; + if (!BN_MONT_CTX_set(mont, p, ctx)) { + ECerr(EC_F_EC_GFP_MONT_GROUP_SET_CURVE, ERR_R_BN_LIB); + goto err; + } + one = BN_new(); + if (one == NULL) + goto err; + if (!BN_to_montgomery(one, BN_value_one(), mont, ctx)) + goto err; + + group->field_data1 = mont; + mont = NULL; + group->field_data2 = one; + one = NULL; + + ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); + + if (!ret) { + BN_MONT_CTX_free(group->field_data1); + group->field_data1 = NULL; + BN_free(group->field_data2); + group->field_data2 = NULL; + } + + err: + BN_free(one); + BN_CTX_free(new_ctx); + BN_MONT_CTX_free(mont); + return ret; +} + +int ec_GFp_mont_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx) +{ + if (group->field_data1 == NULL) { + ECerr(EC_F_EC_GFP_MONT_FIELD_MUL, EC_R_NOT_INITIALIZED); + return 0; + } + + return BN_mod_mul_montgomery(r, a, b, group->field_data1, ctx); +} + +int ec_GFp_mont_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, + BN_CTX *ctx) +{ + if (group->field_data1 == NULL) { + ECerr(EC_F_EC_GFP_MONT_FIELD_SQR, EC_R_NOT_INITIALIZED); + return 0; + } + + return BN_mod_mul_montgomery(r, a, a, group->field_data1, ctx); +} + +/*- + * Computes the multiplicative inverse of a in GF(p), storing the result in r. + * If a is zero (or equivalent), you'll get a EC_R_CANNOT_INVERT error. + * We have a Mont structure, so SCA hardening is FLT inversion. + */ +int ec_GFp_mont_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, + BN_CTX *ctx) +{ + BIGNUM *e = NULL; + BN_CTX *new_ctx = NULL; + int ret = 0; + + if (group->field_data1 == NULL) + return 0; + + if (ctx == NULL && (ctx = new_ctx = BN_CTX_secure_new()) == NULL) + return 0; + + BN_CTX_start(ctx); + if ((e = BN_CTX_get(ctx)) == NULL) + goto err; + + /* Inverse in constant time with Fermats Little Theorem */ + if (!BN_set_word(e, 2)) + goto err; + if (!BN_sub(e, group->field, e)) + goto err; + /*- + * Exponent e is public. + * No need for scatter-gather or BN_FLG_CONSTTIME. + */ + if (!BN_mod_exp_mont(r, a, e, group->field, ctx, group->field_data1)) + goto err; + + /* throw an error on zero */ + if (BN_is_zero(r)) { + ECerr(EC_F_EC_GFP_MONT_FIELD_INV, EC_R_CANNOT_INVERT); + goto err; + } + + ret = 1; + + err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +int ec_GFp_mont_field_encode(const EC_GROUP *group, BIGNUM *r, + const BIGNUM *a, BN_CTX *ctx) +{ + if (group->field_data1 == NULL) { + ECerr(EC_F_EC_GFP_MONT_FIELD_ENCODE, EC_R_NOT_INITIALIZED); + return 0; + } + + return BN_to_montgomery(r, a, (BN_MONT_CTX *)group->field_data1, ctx); +} + +int ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r, + const BIGNUM *a, BN_CTX *ctx) +{ + if (group->field_data1 == NULL) { + ECerr(EC_F_EC_GFP_MONT_FIELD_DECODE, EC_R_NOT_INITIALIZED); + return 0; + } + + return BN_from_montgomery(r, a, group->field_data1, ctx); +} + +int ec_GFp_mont_field_set_to_one(const EC_GROUP *group, BIGNUM *r, + BN_CTX *ctx) +{ + if (group->field_data2 == NULL) { + ECerr(EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE, EC_R_NOT_INITIALIZED); + return 0; + } + + if (!BN_copy(r, group->field_data2)) + return 0; + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_nist.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_nist.c new file mode 100644 index 000000000..5eaa99d84 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_nist.c @@ -0,0 +1,168 @@ +/* + * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#include +#include +#include "ec_lcl.h" + +const EC_METHOD *EC_GFp_nist_method(void) +{ + static const EC_METHOD ret = { + EC_FLAGS_DEFAULT_OCT, + NID_X9_62_prime_field, + ec_GFp_simple_group_init, + ec_GFp_simple_group_finish, + ec_GFp_simple_group_clear_finish, + ec_GFp_nist_group_copy, + ec_GFp_nist_group_set_curve, + ec_GFp_simple_group_get_curve, + ec_GFp_simple_group_get_degree, + ec_group_simple_order_bits, + ec_GFp_simple_group_check_discriminant, + ec_GFp_simple_point_init, + ec_GFp_simple_point_finish, + ec_GFp_simple_point_clear_finish, + ec_GFp_simple_point_copy, + ec_GFp_simple_point_set_to_infinity, + ec_GFp_simple_set_Jprojective_coordinates_GFp, + ec_GFp_simple_get_Jprojective_coordinates_GFp, + ec_GFp_simple_point_set_affine_coordinates, + ec_GFp_simple_point_get_affine_coordinates, + 0, 0, 0, + ec_GFp_simple_add, + ec_GFp_simple_dbl, + ec_GFp_simple_invert, + ec_GFp_simple_is_at_infinity, + ec_GFp_simple_is_on_curve, + ec_GFp_simple_cmp, + ec_GFp_simple_make_affine, + ec_GFp_simple_points_make_affine, + 0 /* mul */ , + 0 /* precompute_mult */ , + 0 /* have_precompute_mult */ , + ec_GFp_nist_field_mul, + ec_GFp_nist_field_sqr, + 0 /* field_div */ , + ec_GFp_simple_field_inv, + 0 /* field_encode */ , + 0 /* field_decode */ , + 0, /* field_set_to_one */ + ec_key_simple_priv2oct, + ec_key_simple_oct2priv, + 0, /* set private */ + ec_key_simple_generate_key, + ec_key_simple_check_key, + ec_key_simple_generate_public_key, + 0, /* keycopy */ + 0, /* keyfinish */ + ecdh_simple_compute_key, + 0, /* field_inverse_mod_ord */ + ec_GFp_simple_blind_coordinates, + ec_GFp_simple_ladder_pre, + ec_GFp_simple_ladder_step, + ec_GFp_simple_ladder_post + }; + + return &ret; +} + +int ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src) +{ + dest->field_mod_func = src->field_mod_func; + + return ec_GFp_simple_group_copy(dest, src); +} + +int ec_GFp_nist_group_set_curve(EC_GROUP *group, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) +{ + int ret = 0; + BN_CTX *new_ctx = NULL; + + if (ctx == NULL) + if ((ctx = new_ctx = BN_CTX_new()) == NULL) + return 0; + + BN_CTX_start(ctx); + + if (BN_ucmp(BN_get0_nist_prime_192(), p) == 0) + group->field_mod_func = BN_nist_mod_192; + else if (BN_ucmp(BN_get0_nist_prime_224(), p) == 0) + group->field_mod_func = BN_nist_mod_224; + else if (BN_ucmp(BN_get0_nist_prime_256(), p) == 0) + group->field_mod_func = BN_nist_mod_256; + else if (BN_ucmp(BN_get0_nist_prime_384(), p) == 0) + group->field_mod_func = BN_nist_mod_384; + else if (BN_ucmp(BN_get0_nist_prime_521(), p) == 0) + group->field_mod_func = BN_nist_mod_521; + else { + ECerr(EC_F_EC_GFP_NIST_GROUP_SET_CURVE, EC_R_NOT_A_NIST_PRIME); + goto err; + } + + ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); + + err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +int ec_GFp_nist_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx) +{ + int ret = 0; + BN_CTX *ctx_new = NULL; + + if (!group || !r || !a || !b) { + ECerr(EC_F_EC_GFP_NIST_FIELD_MUL, ERR_R_PASSED_NULL_PARAMETER); + goto err; + } + if (!ctx) + if ((ctx_new = ctx = BN_CTX_new()) == NULL) + goto err; + + if (!BN_mul(r, a, b, ctx)) + goto err; + if (!group->field_mod_func(r, r, group->field, ctx)) + goto err; + + ret = 1; + err: + BN_CTX_free(ctx_new); + return ret; +} + +int ec_GFp_nist_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, + BN_CTX *ctx) +{ + int ret = 0; + BN_CTX *ctx_new = NULL; + + if (!group || !r || !a) { + ECerr(EC_F_EC_GFP_NIST_FIELD_SQR, EC_R_PASSED_NULL_PARAMETER); + goto err; + } + if (!ctx) + if ((ctx_new = ctx = BN_CTX_new()) == NULL) + goto err; + + if (!BN_sqr(r, a, ctx)) + goto err; + if (!group->field_mod_func(r, r, group->field, ctx)) + goto err; + + ret = 1; + err: + BN_CTX_free(ctx_new); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_nistp224.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_nistp224.c new file mode 100644 index 000000000..025273a14 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_nistp224.c @@ -0,0 +1,1716 @@ +/* + * Copyright 2010-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Copyright 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * A 64-bit implementation of the NIST P-224 elliptic curve point multiplication + * + * Inspired by Daniel J. Bernstein's public domain nistp224 implementation + * and Adam Langley's public domain 64-bit C implementation of curve25519 + */ + +#include +#ifdef OPENSSL_NO_EC_NISTP_64_GCC_128 +NON_EMPTY_TRANSLATION_UNIT +#else + +# include +# include +# include +# include "ec_lcl.h" + +# if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__==16 + /* even with gcc, the typedef won't work for 32-bit platforms */ +typedef __uint128_t uint128_t; /* nonstandard; implemented by gcc on 64-bit + * platforms */ +# else +# error "Your compiler doesn't appear to support 128-bit integer types" +# endif + +typedef uint8_t u8; +typedef uint64_t u64; + +/******************************************************************************/ +/*- + * INTERNAL REPRESENTATION OF FIELD ELEMENTS + * + * Field elements are represented as a_0 + 2^56*a_1 + 2^112*a_2 + 2^168*a_3 + * using 64-bit coefficients called 'limbs', + * and sometimes (for multiplication results) as + * b_0 + 2^56*b_1 + 2^112*b_2 + 2^168*b_3 + 2^224*b_4 + 2^280*b_5 + 2^336*b_6 + * using 128-bit coefficients called 'widelimbs'. + * A 4-limb representation is an 'felem'; + * a 7-widelimb representation is a 'widefelem'. + * Even within felems, bits of adjacent limbs overlap, and we don't always + * reduce the representations: we ensure that inputs to each felem + * multiplication satisfy a_i < 2^60, so outputs satisfy b_i < 4*2^60*2^60, + * and fit into a 128-bit word without overflow. The coefficients are then + * again partially reduced to obtain an felem satisfying a_i < 2^57. + * We only reduce to the unique minimal representation at the end of the + * computation. + */ + +typedef uint64_t limb; +typedef uint128_t widelimb; + +typedef limb felem[4]; +typedef widelimb widefelem[7]; + +/* + * Field element represented as a byte array. 28*8 = 224 bits is also the + * group order size for the elliptic curve, and we also use this type for + * scalars for point multiplication. + */ +typedef u8 felem_bytearray[28]; + +static const felem_bytearray nistp224_curve_params[5] = { + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* p */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* a */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE}, + {0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, /* b */ + 0x32, 0x56, 0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA, + 0x27, 0x0B, 0x39, 0x43, 0x23, 0x55, 0xFF, 0xB4}, + {0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, /* x */ + 0x90, 0xB9, 0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22, + 0x34, 0x32, 0x80, 0xD6, 0x11, 0x5C, 0x1D, 0x21}, + {0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, /* y */ + 0xdf, 0xe6, 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, + 0x44, 0xd5, 0x81, 0x99, 0x85, 0x00, 0x7e, 0x34} +}; + +/*- + * Precomputed multiples of the standard generator + * Points are given in coordinates (X, Y, Z) where Z normally is 1 + * (0 for the point at infinity). + * For each field element, slice a_0 is word 0, etc. + * + * The table has 2 * 16 elements, starting with the following: + * index | bits | point + * ------+---------+------------------------------ + * 0 | 0 0 0 0 | 0G + * 1 | 0 0 0 1 | 1G + * 2 | 0 0 1 0 | 2^56G + * 3 | 0 0 1 1 | (2^56 + 1)G + * 4 | 0 1 0 0 | 2^112G + * 5 | 0 1 0 1 | (2^112 + 1)G + * 6 | 0 1 1 0 | (2^112 + 2^56)G + * 7 | 0 1 1 1 | (2^112 + 2^56 + 1)G + * 8 | 1 0 0 0 | 2^168G + * 9 | 1 0 0 1 | (2^168 + 1)G + * 10 | 1 0 1 0 | (2^168 + 2^56)G + * 11 | 1 0 1 1 | (2^168 + 2^56 + 1)G + * 12 | 1 1 0 0 | (2^168 + 2^112)G + * 13 | 1 1 0 1 | (2^168 + 2^112 + 1)G + * 14 | 1 1 1 0 | (2^168 + 2^112 + 2^56)G + * 15 | 1 1 1 1 | (2^168 + 2^112 + 2^56 + 1)G + * followed by a copy of this with each element multiplied by 2^28. + * + * The reason for this is so that we can clock bits into four different + * locations when doing simple scalar multiplies against the base point, + * and then another four locations using the second 16 elements. + */ +static const felem gmul[2][16][3] = { +{{{0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}}, + {{0x3280d6115c1d21, 0xc1d356c2112234, 0x7f321390b94a03, 0xb70e0cbd6bb4bf}, + {0xd5819985007e34, 0x75a05a07476444, 0xfb4c22dfe6cd43, 0xbd376388b5f723}, + {1, 0, 0, 0}}, + {{0xfd9675666ebbe9, 0xbca7664d40ce5e, 0x2242df8d8a2a43, 0x1f49bbb0f99bc5}, + {0x29e0b892dc9c43, 0xece8608436e662, 0xdc858f185310d0, 0x9812dd4eb8d321}, + {1, 0, 0, 0}}, + {{0x6d3e678d5d8eb8, 0x559eed1cb362f1, 0x16e9a3bbce8a3f, 0xeedcccd8c2a748}, + {0xf19f90ed50266d, 0xabf2b4bf65f9df, 0x313865468fafec, 0x5cb379ba910a17}, + {1, 0, 0, 0}}, + {{0x0641966cab26e3, 0x91fb2991fab0a0, 0xefec27a4e13a0b, 0x0499aa8a5f8ebe}, + {0x7510407766af5d, 0x84d929610d5450, 0x81d77aae82f706, 0x6916f6d4338c5b}, + {1, 0, 0, 0}}, + {{0xea95ac3b1f15c6, 0x086000905e82d4, 0xdd323ae4d1c8b1, 0x932b56be7685a3}, + {0x9ef93dea25dbbf, 0x41665960f390f0, 0xfdec76dbe2a8a7, 0x523e80f019062a}, + {1, 0, 0, 0}}, + {{0x822fdd26732c73, 0xa01c83531b5d0f, 0x363f37347c1ba4, 0xc391b45c84725c}, + {0xbbd5e1b2d6ad24, 0xddfbcde19dfaec, 0xc393da7e222a7f, 0x1efb7890ede244}, + {1, 0, 0, 0}}, + {{0x4c9e90ca217da1, 0xd11beca79159bb, 0xff8d33c2c98b7c, 0x2610b39409f849}, + {0x44d1352ac64da0, 0xcdbb7b2c46b4fb, 0x966c079b753c89, 0xfe67e4e820b112}, + {1, 0, 0, 0}}, + {{0xe28cae2df5312d, 0xc71b61d16f5c6e, 0x79b7619a3e7c4c, 0x05c73240899b47}, + {0x9f7f6382c73e3a, 0x18615165c56bda, 0x641fab2116fd56, 0x72855882b08394}, + {1, 0, 0, 0}}, + {{0x0469182f161c09, 0x74a98ca8d00fb5, 0xb89da93489a3e0, 0x41c98768fb0c1d}, + {0xe5ea05fb32da81, 0x3dce9ffbca6855, 0x1cfe2d3fbf59e6, 0x0e5e03408738a7}, + {1, 0, 0, 0}}, + {{0xdab22b2333e87f, 0x4430137a5dd2f6, 0xe03ab9f738beb8, 0xcb0c5d0dc34f24}, + {0x764a7df0c8fda5, 0x185ba5c3fa2044, 0x9281d688bcbe50, 0xc40331df893881}, + {1, 0, 0, 0}}, + {{0xb89530796f0f60, 0xade92bd26909a3, 0x1a0c83fb4884da, 0x1765bf22a5a984}, + {0x772a9ee75db09e, 0x23bc6c67cec16f, 0x4c1edba8b14e2f, 0xe2a215d9611369}, + {1, 0, 0, 0}}, + {{0x571e509fb5efb3, 0xade88696410552, 0xc8ae85fada74fe, 0x6c7e4be83bbde3}, + {0xff9f51160f4652, 0xb47ce2495a6539, 0xa2946c53b582f4, 0x286d2db3ee9a60}, + {1, 0, 0, 0}}, + {{0x40bbd5081a44af, 0x0995183b13926c, 0xbcefba6f47f6d0, 0x215619e9cc0057}, + {0x8bc94d3b0df45e, 0xf11c54a3694f6f, 0x8631b93cdfe8b5, 0xe7e3f4b0982db9}, + {1, 0, 0, 0}}, + {{0xb17048ab3e1c7b, 0xac38f36ff8a1d8, 0x1c29819435d2c6, 0xc813132f4c07e9}, + {0x2891425503b11f, 0x08781030579fea, 0xf5426ba5cc9674, 0x1e28ebf18562bc}, + {1, 0, 0, 0}}, + {{0x9f31997cc864eb, 0x06cd91d28b5e4c, 0xff17036691a973, 0xf1aef351497c58}, + {0xdd1f2d600564ff, 0xdead073b1402db, 0x74a684435bd693, 0xeea7471f962558}, + {1, 0, 0, 0}}}, +{{{0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}}, + {{0x9665266dddf554, 0x9613d78b60ef2d, 0xce27a34cdba417, 0xd35ab74d6afc31}, + {0x85ccdd22deb15e, 0x2137e5783a6aab, 0xa141cffd8c93c6, 0x355a1830e90f2d}, + {1, 0, 0, 0}}, + {{0x1a494eadaade65, 0xd6da4da77fe53c, 0xe7992996abec86, 0x65c3553c6090e3}, + {0xfa610b1fb09346, 0xf1c6540b8a4aaf, 0xc51a13ccd3cbab, 0x02995b1b18c28a}, + {1, 0, 0, 0}}, + {{0x7874568e7295ef, 0x86b419fbe38d04, 0xdc0690a7550d9a, 0xd3966a44beac33}, + {0x2b7280ec29132f, 0xbeaa3b6a032df3, 0xdc7dd88ae41200, 0xd25e2513e3a100}, + {1, 0, 0, 0}}, + {{0x924857eb2efafd, 0xac2bce41223190, 0x8edaa1445553fc, 0x825800fd3562d5}, + {0x8d79148ea96621, 0x23a01c3dd9ed8d, 0xaf8b219f9416b5, 0xd8db0cc277daea}, + {1, 0, 0, 0}}, + {{0x76a9c3b1a700f0, 0xe9acd29bc7e691, 0x69212d1a6b0327, 0x6322e97fe154be}, + {0x469fc5465d62aa, 0x8d41ed18883b05, 0x1f8eae66c52b88, 0xe4fcbe9325be51}, + {1, 0, 0, 0}}, + {{0x825fdf583cac16, 0x020b857c7b023a, 0x683c17744b0165, 0x14ffd0a2daf2f1}, + {0x323b36184218f9, 0x4944ec4e3b47d4, 0xc15b3080841acf, 0x0bced4b01a28bb}, + {1, 0, 0, 0}}, + {{0x92ac22230df5c4, 0x52f33b4063eda8, 0xcb3f19870c0c93, 0x40064f2ba65233}, + {0xfe16f0924f8992, 0x012da25af5b517, 0x1a57bb24f723a6, 0x06f8bc76760def}, + {1, 0, 0, 0}}, + {{0x4a7084f7817cb9, 0xbcab0738ee9a78, 0x3ec11e11d9c326, 0xdc0fe90e0f1aae}, + {0xcf639ea5f98390, 0x5c350aa22ffb74, 0x9afae98a4047b7, 0x956ec2d617fc45}, + {1, 0, 0, 0}}, + {{0x4306d648c1be6a, 0x9247cd8bc9a462, 0xf5595e377d2f2e, 0xbd1c3caff1a52e}, + {0x045e14472409d0, 0x29f3e17078f773, 0x745a602b2d4f7d, 0x191837685cdfbb}, + {1, 0, 0, 0}}, + {{0x5b6ee254a8cb79, 0x4953433f5e7026, 0xe21faeb1d1def4, 0xc4c225785c09de}, + {0x307ce7bba1e518, 0x31b125b1036db8, 0x47e91868839e8f, 0xc765866e33b9f3}, + {1, 0, 0, 0}}, + {{0x3bfece24f96906, 0x4794da641e5093, 0xde5df64f95db26, 0x297ecd89714b05}, + {0x701bd3ebb2c3aa, 0x7073b4f53cb1d5, 0x13c5665658af16, 0x9895089d66fe58}, + {1, 0, 0, 0}}, + {{0x0fef05f78c4790, 0x2d773633b05d2e, 0x94229c3a951c94, 0xbbbd70df4911bb}, + {0xb2c6963d2c1168, 0x105f47a72b0d73, 0x9fdf6111614080, 0x7b7e94b39e67b0}, + {1, 0, 0, 0}}, + {{0xad1a7d6efbe2b3, 0xf012482c0da69d, 0x6b3bdf12438345, 0x40d7558d7aa4d9}, + {0x8a09fffb5c6d3d, 0x9a356e5d9ffd38, 0x5973f15f4f9b1c, 0xdcd5f59f63c3ea}, + {1, 0, 0, 0}}, + {{0xacf39f4c5ca7ab, 0x4c8071cc5fd737, 0xc64e3602cd1184, 0x0acd4644c9abba}, + {0x6c011a36d8bf6e, 0xfecd87ba24e32a, 0x19f6f56574fad8, 0x050b204ced9405}, + {1, 0, 0, 0}}, + {{0xed4f1cae7d9a96, 0x5ceef7ad94c40a, 0x778e4a3bf3ef9b, 0x7405783dc3b55e}, + {0x32477c61b6e8c6, 0xb46a97570f018b, 0x91176d0a7e95d1, 0x3df90fbc4c7d0e}, + {1, 0, 0, 0}}} +}; + +/* Precomputation for the group generator. */ +struct nistp224_pre_comp_st { + felem g_pre_comp[2][16][3]; + CRYPTO_REF_COUNT references; + CRYPTO_RWLOCK *lock; +}; + +const EC_METHOD *EC_GFp_nistp224_method(void) +{ + static const EC_METHOD ret = { + EC_FLAGS_DEFAULT_OCT, + NID_X9_62_prime_field, + ec_GFp_nistp224_group_init, + ec_GFp_simple_group_finish, + ec_GFp_simple_group_clear_finish, + ec_GFp_nist_group_copy, + ec_GFp_nistp224_group_set_curve, + ec_GFp_simple_group_get_curve, + ec_GFp_simple_group_get_degree, + ec_group_simple_order_bits, + ec_GFp_simple_group_check_discriminant, + ec_GFp_simple_point_init, + ec_GFp_simple_point_finish, + ec_GFp_simple_point_clear_finish, + ec_GFp_simple_point_copy, + ec_GFp_simple_point_set_to_infinity, + ec_GFp_simple_set_Jprojective_coordinates_GFp, + ec_GFp_simple_get_Jprojective_coordinates_GFp, + ec_GFp_simple_point_set_affine_coordinates, + ec_GFp_nistp224_point_get_affine_coordinates, + 0 /* point_set_compressed_coordinates */ , + 0 /* point2oct */ , + 0 /* oct2point */ , + ec_GFp_simple_add, + ec_GFp_simple_dbl, + ec_GFp_simple_invert, + ec_GFp_simple_is_at_infinity, + ec_GFp_simple_is_on_curve, + ec_GFp_simple_cmp, + ec_GFp_simple_make_affine, + ec_GFp_simple_points_make_affine, + ec_GFp_nistp224_points_mul, + ec_GFp_nistp224_precompute_mult, + ec_GFp_nistp224_have_precompute_mult, + ec_GFp_nist_field_mul, + ec_GFp_nist_field_sqr, + 0 /* field_div */ , + ec_GFp_simple_field_inv, + 0 /* field_encode */ , + 0 /* field_decode */ , + 0, /* field_set_to_one */ + ec_key_simple_priv2oct, + ec_key_simple_oct2priv, + 0, /* set private */ + ec_key_simple_generate_key, + ec_key_simple_check_key, + ec_key_simple_generate_public_key, + 0, /* keycopy */ + 0, /* keyfinish */ + ecdh_simple_compute_key, + 0, /* field_inverse_mod_ord */ + 0, /* blind_coordinates */ + 0, /* ladder_pre */ + 0, /* ladder_step */ + 0 /* ladder_post */ + }; + + return &ret; +} + +/* + * Helper functions to convert field elements to/from internal representation + */ +static void bin28_to_felem(felem out, const u8 in[28]) +{ + out[0] = *((const uint64_t *)(in)) & 0x00ffffffffffffff; + out[1] = (*((const uint64_t *)(in + 7))) & 0x00ffffffffffffff; + out[2] = (*((const uint64_t *)(in + 14))) & 0x00ffffffffffffff; + out[3] = (*((const uint64_t *)(in+20))) >> 8; +} + +static void felem_to_bin28(u8 out[28], const felem in) +{ + unsigned i; + for (i = 0; i < 7; ++i) { + out[i] = in[0] >> (8 * i); + out[i + 7] = in[1] >> (8 * i); + out[i + 14] = in[2] >> (8 * i); + out[i + 21] = in[3] >> (8 * i); + } +} + +/* To preserve endianness when using BN_bn2bin and BN_bin2bn */ +static void flip_endian(u8 *out, const u8 *in, unsigned len) +{ + unsigned i; + for (i = 0; i < len; ++i) + out[i] = in[len - 1 - i]; +} + +/* From OpenSSL BIGNUM to internal representation */ +static int BN_to_felem(felem out, const BIGNUM *bn) +{ + felem_bytearray b_in; + felem_bytearray b_out; + unsigned num_bytes; + + /* BN_bn2bin eats leading zeroes */ + memset(b_out, 0, sizeof(b_out)); + num_bytes = BN_num_bytes(bn); + if (num_bytes > sizeof(b_out)) { + ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE); + return 0; + } + if (BN_is_negative(bn)) { + ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE); + return 0; + } + num_bytes = BN_bn2bin(bn, b_in); + flip_endian(b_out, b_in, num_bytes); + bin28_to_felem(out, b_out); + return 1; +} + +/* From internal representation to OpenSSL BIGNUM */ +static BIGNUM *felem_to_BN(BIGNUM *out, const felem in) +{ + felem_bytearray b_in, b_out; + felem_to_bin28(b_in, in); + flip_endian(b_out, b_in, sizeof(b_out)); + return BN_bin2bn(b_out, sizeof(b_out), out); +} + +/******************************************************************************/ +/*- + * FIELD OPERATIONS + * + * Field operations, using the internal representation of field elements. + * NB! These operations are specific to our point multiplication and cannot be + * expected to be correct in general - e.g., multiplication with a large scalar + * will cause an overflow. + * + */ + +static void felem_one(felem out) +{ + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 0; +} + +static void felem_assign(felem out, const felem in) +{ + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; +} + +/* Sum two field elements: out += in */ +static void felem_sum(felem out, const felem in) +{ + out[0] += in[0]; + out[1] += in[1]; + out[2] += in[2]; + out[3] += in[3]; +} + +/* Subtract field elements: out -= in */ +/* Assumes in[i] < 2^57 */ +static void felem_diff(felem out, const felem in) +{ + static const limb two58p2 = (((limb) 1) << 58) + (((limb) 1) << 2); + static const limb two58m2 = (((limb) 1) << 58) - (((limb) 1) << 2); + static const limb two58m42m2 = (((limb) 1) << 58) - + (((limb) 1) << 42) - (((limb) 1) << 2); + + /* Add 0 mod 2^224-2^96+1 to ensure out > in */ + out[0] += two58p2; + out[1] += two58m42m2; + out[2] += two58m2; + out[3] += two58m2; + + out[0] -= in[0]; + out[1] -= in[1]; + out[2] -= in[2]; + out[3] -= in[3]; +} + +/* Subtract in unreduced 128-bit mode: out -= in */ +/* Assumes in[i] < 2^119 */ +static void widefelem_diff(widefelem out, const widefelem in) +{ + static const widelimb two120 = ((widelimb) 1) << 120; + static const widelimb two120m64 = (((widelimb) 1) << 120) - + (((widelimb) 1) << 64); + static const widelimb two120m104m64 = (((widelimb) 1) << 120) - + (((widelimb) 1) << 104) - (((widelimb) 1) << 64); + + /* Add 0 mod 2^224-2^96+1 to ensure out > in */ + out[0] += two120; + out[1] += two120m64; + out[2] += two120m64; + out[3] += two120; + out[4] += two120m104m64; + out[5] += two120m64; + out[6] += two120m64; + + out[0] -= in[0]; + out[1] -= in[1]; + out[2] -= in[2]; + out[3] -= in[3]; + out[4] -= in[4]; + out[5] -= in[5]; + out[6] -= in[6]; +} + +/* Subtract in mixed mode: out128 -= in64 */ +/* in[i] < 2^63 */ +static void felem_diff_128_64(widefelem out, const felem in) +{ + static const widelimb two64p8 = (((widelimb) 1) << 64) + + (((widelimb) 1) << 8); + static const widelimb two64m8 = (((widelimb) 1) << 64) - + (((widelimb) 1) << 8); + static const widelimb two64m48m8 = (((widelimb) 1) << 64) - + (((widelimb) 1) << 48) - (((widelimb) 1) << 8); + + /* Add 0 mod 2^224-2^96+1 to ensure out > in */ + out[0] += two64p8; + out[1] += two64m48m8; + out[2] += two64m8; + out[3] += two64m8; + + out[0] -= in[0]; + out[1] -= in[1]; + out[2] -= in[2]; + out[3] -= in[3]; +} + +/* + * Multiply a field element by a scalar: out = out * scalar The scalars we + * actually use are small, so results fit without overflow + */ +static void felem_scalar(felem out, const limb scalar) +{ + out[0] *= scalar; + out[1] *= scalar; + out[2] *= scalar; + out[3] *= scalar; +} + +/* + * Multiply an unreduced field element by a scalar: out = out * scalar The + * scalars we actually use are small, so results fit without overflow + */ +static void widefelem_scalar(widefelem out, const widelimb scalar) +{ + out[0] *= scalar; + out[1] *= scalar; + out[2] *= scalar; + out[3] *= scalar; + out[4] *= scalar; + out[5] *= scalar; + out[6] *= scalar; +} + +/* Square a field element: out = in^2 */ +static void felem_square(widefelem out, const felem in) +{ + limb tmp0, tmp1, tmp2; + tmp0 = 2 * in[0]; + tmp1 = 2 * in[1]; + tmp2 = 2 * in[2]; + out[0] = ((widelimb) in[0]) * in[0]; + out[1] = ((widelimb) in[0]) * tmp1; + out[2] = ((widelimb) in[0]) * tmp2 + ((widelimb) in[1]) * in[1]; + out[3] = ((widelimb) in[3]) * tmp0 + ((widelimb) in[1]) * tmp2; + out[4] = ((widelimb) in[3]) * tmp1 + ((widelimb) in[2]) * in[2]; + out[5] = ((widelimb) in[3]) * tmp2; + out[6] = ((widelimb) in[3]) * in[3]; +} + +/* Multiply two field elements: out = in1 * in2 */ +static void felem_mul(widefelem out, const felem in1, const felem in2) +{ + out[0] = ((widelimb) in1[0]) * in2[0]; + out[1] = ((widelimb) in1[0]) * in2[1] + ((widelimb) in1[1]) * in2[0]; + out[2] = ((widelimb) in1[0]) * in2[2] + ((widelimb) in1[1]) * in2[1] + + ((widelimb) in1[2]) * in2[0]; + out[3] = ((widelimb) in1[0]) * in2[3] + ((widelimb) in1[1]) * in2[2] + + ((widelimb) in1[2]) * in2[1] + ((widelimb) in1[3]) * in2[0]; + out[4] = ((widelimb) in1[1]) * in2[3] + ((widelimb) in1[2]) * in2[2] + + ((widelimb) in1[3]) * in2[1]; + out[5] = ((widelimb) in1[2]) * in2[3] + ((widelimb) in1[3]) * in2[2]; + out[6] = ((widelimb) in1[3]) * in2[3]; +} + +/*- + * Reduce seven 128-bit coefficients to four 64-bit coefficients. + * Requires in[i] < 2^126, + * ensures out[0] < 2^56, out[1] < 2^56, out[2] < 2^56, out[3] <= 2^56 + 2^16 */ +static void felem_reduce(felem out, const widefelem in) +{ + static const widelimb two127p15 = (((widelimb) 1) << 127) + + (((widelimb) 1) << 15); + static const widelimb two127m71 = (((widelimb) 1) << 127) - + (((widelimb) 1) << 71); + static const widelimb two127m71m55 = (((widelimb) 1) << 127) - + (((widelimb) 1) << 71) - (((widelimb) 1) << 55); + widelimb output[5]; + + /* Add 0 mod 2^224-2^96+1 to ensure all differences are positive */ + output[0] = in[0] + two127p15; + output[1] = in[1] + two127m71m55; + output[2] = in[2] + two127m71; + output[3] = in[3]; + output[4] = in[4]; + + /* Eliminate in[4], in[5], in[6] */ + output[4] += in[6] >> 16; + output[3] += (in[6] & 0xffff) << 40; + output[2] -= in[6]; + + output[3] += in[5] >> 16; + output[2] += (in[5] & 0xffff) << 40; + output[1] -= in[5]; + + output[2] += output[4] >> 16; + output[1] += (output[4] & 0xffff) << 40; + output[0] -= output[4]; + + /* Carry 2 -> 3 -> 4 */ + output[3] += output[2] >> 56; + output[2] &= 0x00ffffffffffffff; + + output[4] = output[3] >> 56; + output[3] &= 0x00ffffffffffffff; + + /* Now output[2] < 2^56, output[3] < 2^56, output[4] < 2^72 */ + + /* Eliminate output[4] */ + output[2] += output[4] >> 16; + /* output[2] < 2^56 + 2^56 = 2^57 */ + output[1] += (output[4] & 0xffff) << 40; + output[0] -= output[4]; + + /* Carry 0 -> 1 -> 2 -> 3 */ + output[1] += output[0] >> 56; + out[0] = output[0] & 0x00ffffffffffffff; + + output[2] += output[1] >> 56; + /* output[2] < 2^57 + 2^72 */ + out[1] = output[1] & 0x00ffffffffffffff; + output[3] += output[2] >> 56; + /* output[3] <= 2^56 + 2^16 */ + out[2] = output[2] & 0x00ffffffffffffff; + + /*- + * out[0] < 2^56, out[1] < 2^56, out[2] < 2^56, + * out[3] <= 2^56 + 2^16 (due to final carry), + * so out < 2*p + */ + out[3] = output[3]; +} + +static void felem_square_reduce(felem out, const felem in) +{ + widefelem tmp; + felem_square(tmp, in); + felem_reduce(out, tmp); +} + +static void felem_mul_reduce(felem out, const felem in1, const felem in2) +{ + widefelem tmp; + felem_mul(tmp, in1, in2); + felem_reduce(out, tmp); +} + +/* + * Reduce to unique minimal representation. Requires 0 <= in < 2*p (always + * call felem_reduce first) + */ +static void felem_contract(felem out, const felem in) +{ + static const int64_t two56 = ((limb) 1) << 56; + /* 0 <= in < 2*p, p = 2^224 - 2^96 + 1 */ + /* if in > p , reduce in = in - 2^224 + 2^96 - 1 */ + int64_t tmp[4], a; + tmp[0] = in[0]; + tmp[1] = in[1]; + tmp[2] = in[2]; + tmp[3] = in[3]; + /* Case 1: a = 1 iff in >= 2^224 */ + a = (in[3] >> 56); + tmp[0] -= a; + tmp[1] += a << 40; + tmp[3] &= 0x00ffffffffffffff; + /* + * Case 2: a = 0 iff p <= in < 2^224, i.e., the high 128 bits are all 1 + * and the lower part is non-zero + */ + a = ((in[3] & in[2] & (in[1] | 0x000000ffffffffff)) + 1) | + (((int64_t) (in[0] + (in[1] & 0x000000ffffffffff)) - 1) >> 63); + a &= 0x00ffffffffffffff; + /* turn a into an all-one mask (if a = 0) or an all-zero mask */ + a = (a - 1) >> 63; + /* subtract 2^224 - 2^96 + 1 if a is all-one */ + tmp[3] &= a ^ 0xffffffffffffffff; + tmp[2] &= a ^ 0xffffffffffffffff; + tmp[1] &= (a ^ 0xffffffffffffffff) | 0x000000ffffffffff; + tmp[0] -= 1 & a; + + /* + * eliminate negative coefficients: if tmp[0] is negative, tmp[1] must be + * non-zero, so we only need one step + */ + a = tmp[0] >> 63; + tmp[0] += two56 & a; + tmp[1] -= 1 & a; + + /* carry 1 -> 2 -> 3 */ + tmp[2] += tmp[1] >> 56; + tmp[1] &= 0x00ffffffffffffff; + + tmp[3] += tmp[2] >> 56; + tmp[2] &= 0x00ffffffffffffff; + + /* Now 0 <= out < p */ + out[0] = tmp[0]; + out[1] = tmp[1]; + out[2] = tmp[2]; + out[3] = tmp[3]; +} + +/* + * Get negative value: out = -in + * Requires in[i] < 2^63, + * ensures out[0] < 2^56, out[1] < 2^56, out[2] < 2^56, out[3] <= 2^56 + 2^16 + */ +static void felem_neg(felem out, const felem in) +{ + widefelem tmp = {0}; + felem_diff_128_64(tmp, in); + felem_reduce(out, tmp); +} + +/* + * Zero-check: returns 1 if input is 0, and 0 otherwise. We know that field + * elements are reduced to in < 2^225, so we only need to check three cases: + * 0, 2^224 - 2^96 + 1, and 2^225 - 2^97 + 2 + */ +static limb felem_is_zero(const felem in) +{ + limb zero, two224m96p1, two225m97p2; + + zero = in[0] | in[1] | in[2] | in[3]; + zero = (((int64_t) (zero) - 1) >> 63) & 1; + two224m96p1 = (in[0] ^ 1) | (in[1] ^ 0x00ffff0000000000) + | (in[2] ^ 0x00ffffffffffffff) | (in[3] ^ 0x00ffffffffffffff); + two224m96p1 = (((int64_t) (two224m96p1) - 1) >> 63) & 1; + two225m97p2 = (in[0] ^ 2) | (in[1] ^ 0x00fffe0000000000) + | (in[2] ^ 0x00ffffffffffffff) | (in[3] ^ 0x01ffffffffffffff); + two225m97p2 = (((int64_t) (two225m97p2) - 1) >> 63) & 1; + return (zero | two224m96p1 | two225m97p2); +} + +static int felem_is_zero_int(const void *in) +{ + return (int)(felem_is_zero(in) & ((limb) 1)); +} + +/* Invert a field element */ +/* Computation chain copied from djb's code */ +static void felem_inv(felem out, const felem in) +{ + felem ftmp, ftmp2, ftmp3, ftmp4; + widefelem tmp; + unsigned i; + + felem_square(tmp, in); + felem_reduce(ftmp, tmp); /* 2 */ + felem_mul(tmp, in, ftmp); + felem_reduce(ftmp, tmp); /* 2^2 - 1 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^3 - 2 */ + felem_mul(tmp, in, ftmp); + felem_reduce(ftmp, tmp); /* 2^3 - 1 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp2, tmp); /* 2^4 - 2 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); /* 2^5 - 4 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); /* 2^6 - 8 */ + felem_mul(tmp, ftmp2, ftmp); + felem_reduce(ftmp, tmp); /* 2^6 - 1 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp2, tmp); /* 2^7 - 2 */ + for (i = 0; i < 5; ++i) { /* 2^12 - 2^6 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); + } + felem_mul(tmp, ftmp2, ftmp); + felem_reduce(ftmp2, tmp); /* 2^12 - 1 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^13 - 2 */ + for (i = 0; i < 11; ++i) { /* 2^24 - 2^12 */ + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); + } + felem_mul(tmp, ftmp3, ftmp2); + felem_reduce(ftmp2, tmp); /* 2^24 - 1 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^25 - 2 */ + for (i = 0; i < 23; ++i) { /* 2^48 - 2^24 */ + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); + } + felem_mul(tmp, ftmp3, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^48 - 1 */ + felem_square(tmp, ftmp3); + felem_reduce(ftmp4, tmp); /* 2^49 - 2 */ + for (i = 0; i < 47; ++i) { /* 2^96 - 2^48 */ + felem_square(tmp, ftmp4); + felem_reduce(ftmp4, tmp); + } + felem_mul(tmp, ftmp3, ftmp4); + felem_reduce(ftmp3, tmp); /* 2^96 - 1 */ + felem_square(tmp, ftmp3); + felem_reduce(ftmp4, tmp); /* 2^97 - 2 */ + for (i = 0; i < 23; ++i) { /* 2^120 - 2^24 */ + felem_square(tmp, ftmp4); + felem_reduce(ftmp4, tmp); + } + felem_mul(tmp, ftmp2, ftmp4); + felem_reduce(ftmp2, tmp); /* 2^120 - 1 */ + for (i = 0; i < 6; ++i) { /* 2^126 - 2^6 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); + } + felem_mul(tmp, ftmp2, ftmp); + felem_reduce(ftmp, tmp); /* 2^126 - 1 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^127 - 2 */ + felem_mul(tmp, ftmp, in); + felem_reduce(ftmp, tmp); /* 2^127 - 1 */ + for (i = 0; i < 97; ++i) { /* 2^224 - 2^97 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); + } + felem_mul(tmp, ftmp, ftmp3); + felem_reduce(out, tmp); /* 2^224 - 2^96 - 1 */ +} + +/* + * Copy in constant time: if icopy == 1, copy in to out, if icopy == 0, copy + * out to itself. + */ +static void copy_conditional(felem out, const felem in, limb icopy) +{ + unsigned i; + /* + * icopy is a (64-bit) 0 or 1, so copy is either all-zero or all-one + */ + const limb copy = -icopy; + for (i = 0; i < 4; ++i) { + const limb tmp = copy & (in[i] ^ out[i]); + out[i] ^= tmp; + } +} + +/******************************************************************************/ +/*- + * ELLIPTIC CURVE POINT OPERATIONS + * + * Points are represented in Jacobian projective coordinates: + * (X, Y, Z) corresponds to the affine point (X/Z^2, Y/Z^3), + * or to the point at infinity if Z == 0. + * + */ + +/*- + * Double an elliptic curve point: + * (X', Y', Z') = 2 * (X, Y, Z), where + * X' = (3 * (X - Z^2) * (X + Z^2))^2 - 8 * X * Y^2 + * Y' = 3 * (X - Z^2) * (X + Z^2) * (4 * X * Y^2 - X') - 8 * Y^4 + * Z' = (Y + Z)^2 - Y^2 - Z^2 = 2 * Y * Z + * Outputs can equal corresponding inputs, i.e., x_out == x_in is allowed, + * while x_out == y_in is not (maybe this works, but it's not tested). + */ +static void +point_double(felem x_out, felem y_out, felem z_out, + const felem x_in, const felem y_in, const felem z_in) +{ + widefelem tmp, tmp2; + felem delta, gamma, beta, alpha, ftmp, ftmp2; + + felem_assign(ftmp, x_in); + felem_assign(ftmp2, x_in); + + /* delta = z^2 */ + felem_square(tmp, z_in); + felem_reduce(delta, tmp); + + /* gamma = y^2 */ + felem_square(tmp, y_in); + felem_reduce(gamma, tmp); + + /* beta = x*gamma */ + felem_mul(tmp, x_in, gamma); + felem_reduce(beta, tmp); + + /* alpha = 3*(x-delta)*(x+delta) */ + felem_diff(ftmp, delta); + /* ftmp[i] < 2^57 + 2^58 + 2 < 2^59 */ + felem_sum(ftmp2, delta); + /* ftmp2[i] < 2^57 + 2^57 = 2^58 */ + felem_scalar(ftmp2, 3); + /* ftmp2[i] < 3 * 2^58 < 2^60 */ + felem_mul(tmp, ftmp, ftmp2); + /* tmp[i] < 2^60 * 2^59 * 4 = 2^121 */ + felem_reduce(alpha, tmp); + + /* x' = alpha^2 - 8*beta */ + felem_square(tmp, alpha); + /* tmp[i] < 4 * 2^57 * 2^57 = 2^116 */ + felem_assign(ftmp, beta); + felem_scalar(ftmp, 8); + /* ftmp[i] < 8 * 2^57 = 2^60 */ + felem_diff_128_64(tmp, ftmp); + /* tmp[i] < 2^116 + 2^64 + 8 < 2^117 */ + felem_reduce(x_out, tmp); + + /* z' = (y + z)^2 - gamma - delta */ + felem_sum(delta, gamma); + /* delta[i] < 2^57 + 2^57 = 2^58 */ + felem_assign(ftmp, y_in); + felem_sum(ftmp, z_in); + /* ftmp[i] < 2^57 + 2^57 = 2^58 */ + felem_square(tmp, ftmp); + /* tmp[i] < 4 * 2^58 * 2^58 = 2^118 */ + felem_diff_128_64(tmp, delta); + /* tmp[i] < 2^118 + 2^64 + 8 < 2^119 */ + felem_reduce(z_out, tmp); + + /* y' = alpha*(4*beta - x') - 8*gamma^2 */ + felem_scalar(beta, 4); + /* beta[i] < 4 * 2^57 = 2^59 */ + felem_diff(beta, x_out); + /* beta[i] < 2^59 + 2^58 + 2 < 2^60 */ + felem_mul(tmp, alpha, beta); + /* tmp[i] < 4 * 2^57 * 2^60 = 2^119 */ + felem_square(tmp2, gamma); + /* tmp2[i] < 4 * 2^57 * 2^57 = 2^116 */ + widefelem_scalar(tmp2, 8); + /* tmp2[i] < 8 * 2^116 = 2^119 */ + widefelem_diff(tmp, tmp2); + /* tmp[i] < 2^119 + 2^120 < 2^121 */ + felem_reduce(y_out, tmp); +} + +/*- + * Add two elliptic curve points: + * (X_1, Y_1, Z_1) + (X_2, Y_2, Z_2) = (X_3, Y_3, Z_3), where + * X_3 = (Z_1^3 * Y_2 - Z_2^3 * Y_1)^2 - (Z_1^2 * X_2 - Z_2^2 * X_1)^3 - + * 2 * Z_2^2 * X_1 * (Z_1^2 * X_2 - Z_2^2 * X_1)^2 + * Y_3 = (Z_1^3 * Y_2 - Z_2^3 * Y_1) * (Z_2^2 * X_1 * (Z_1^2 * X_2 - Z_2^2 * X_1)^2 - X_3) - + * Z_2^3 * Y_1 * (Z_1^2 * X_2 - Z_2^2 * X_1)^3 + * Z_3 = (Z_1^2 * X_2 - Z_2^2 * X_1) * (Z_1 * Z_2) + * + * This runs faster if 'mixed' is set, which requires Z_2 = 1 or Z_2 = 0. + */ + +/* + * This function is not entirely constant-time: it includes a branch for + * checking whether the two input points are equal, (while not equal to the + * point at infinity). This case never happens during single point + * multiplication, so there is no timing leak for ECDH or ECDSA signing. + */ +static void point_add(felem x3, felem y3, felem z3, + const felem x1, const felem y1, const felem z1, + const int mixed, const felem x2, const felem y2, + const felem z2) +{ + felem ftmp, ftmp2, ftmp3, ftmp4, ftmp5, x_out, y_out, z_out; + widefelem tmp, tmp2; + limb z1_is_zero, z2_is_zero, x_equal, y_equal; + + if (!mixed) { + /* ftmp2 = z2^2 */ + felem_square(tmp, z2); + felem_reduce(ftmp2, tmp); + + /* ftmp4 = z2^3 */ + felem_mul(tmp, ftmp2, z2); + felem_reduce(ftmp4, tmp); + + /* ftmp4 = z2^3*y1 */ + felem_mul(tmp2, ftmp4, y1); + felem_reduce(ftmp4, tmp2); + + /* ftmp2 = z2^2*x1 */ + felem_mul(tmp2, ftmp2, x1); + felem_reduce(ftmp2, tmp2); + } else { + /* + * We'll assume z2 = 1 (special case z2 = 0 is handled later) + */ + + /* ftmp4 = z2^3*y1 */ + felem_assign(ftmp4, y1); + + /* ftmp2 = z2^2*x1 */ + felem_assign(ftmp2, x1); + } + + /* ftmp = z1^2 */ + felem_square(tmp, z1); + felem_reduce(ftmp, tmp); + + /* ftmp3 = z1^3 */ + felem_mul(tmp, ftmp, z1); + felem_reduce(ftmp3, tmp); + + /* tmp = z1^3*y2 */ + felem_mul(tmp, ftmp3, y2); + /* tmp[i] < 4 * 2^57 * 2^57 = 2^116 */ + + /* ftmp3 = z1^3*y2 - z2^3*y1 */ + felem_diff_128_64(tmp, ftmp4); + /* tmp[i] < 2^116 + 2^64 + 8 < 2^117 */ + felem_reduce(ftmp3, tmp); + + /* tmp = z1^2*x2 */ + felem_mul(tmp, ftmp, x2); + /* tmp[i] < 4 * 2^57 * 2^57 = 2^116 */ + + /* ftmp = z1^2*x2 - z2^2*x1 */ + felem_diff_128_64(tmp, ftmp2); + /* tmp[i] < 2^116 + 2^64 + 8 < 2^117 */ + felem_reduce(ftmp, tmp); + + /* + * the formulae are incorrect if the points are equal so we check for + * this and do doubling if this happens + */ + x_equal = felem_is_zero(ftmp); + y_equal = felem_is_zero(ftmp3); + z1_is_zero = felem_is_zero(z1); + z2_is_zero = felem_is_zero(z2); + /* In affine coordinates, (X_1, Y_1) == (X_2, Y_2) */ + if (x_equal && y_equal && !z1_is_zero && !z2_is_zero) { + point_double(x3, y3, z3, x1, y1, z1); + return; + } + + /* ftmp5 = z1*z2 */ + if (!mixed) { + felem_mul(tmp, z1, z2); + felem_reduce(ftmp5, tmp); + } else { + /* special case z2 = 0 is handled later */ + felem_assign(ftmp5, z1); + } + + /* z_out = (z1^2*x2 - z2^2*x1)*(z1*z2) */ + felem_mul(tmp, ftmp, ftmp5); + felem_reduce(z_out, tmp); + + /* ftmp = (z1^2*x2 - z2^2*x1)^2 */ + felem_assign(ftmp5, ftmp); + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); + + /* ftmp5 = (z1^2*x2 - z2^2*x1)^3 */ + felem_mul(tmp, ftmp, ftmp5); + felem_reduce(ftmp5, tmp); + + /* ftmp2 = z2^2*x1*(z1^2*x2 - z2^2*x1)^2 */ + felem_mul(tmp, ftmp2, ftmp); + felem_reduce(ftmp2, tmp); + + /* tmp = z2^3*y1*(z1^2*x2 - z2^2*x1)^3 */ + felem_mul(tmp, ftmp4, ftmp5); + /* tmp[i] < 4 * 2^57 * 2^57 = 2^116 */ + + /* tmp2 = (z1^3*y2 - z2^3*y1)^2 */ + felem_square(tmp2, ftmp3); + /* tmp2[i] < 4 * 2^57 * 2^57 < 2^116 */ + + /* tmp2 = (z1^3*y2 - z2^3*y1)^2 - (z1^2*x2 - z2^2*x1)^3 */ + felem_diff_128_64(tmp2, ftmp5); + /* tmp2[i] < 2^116 + 2^64 + 8 < 2^117 */ + + /* ftmp5 = 2*z2^2*x1*(z1^2*x2 - z2^2*x1)^2 */ + felem_assign(ftmp5, ftmp2); + felem_scalar(ftmp5, 2); + /* ftmp5[i] < 2 * 2^57 = 2^58 */ + + /*- + * x_out = (z1^3*y2 - z2^3*y1)^2 - (z1^2*x2 - z2^2*x1)^3 - + * 2*z2^2*x1*(z1^2*x2 - z2^2*x1)^2 + */ + felem_diff_128_64(tmp2, ftmp5); + /* tmp2[i] < 2^117 + 2^64 + 8 < 2^118 */ + felem_reduce(x_out, tmp2); + + /* ftmp2 = z2^2*x1*(z1^2*x2 - z2^2*x1)^2 - x_out */ + felem_diff(ftmp2, x_out); + /* ftmp2[i] < 2^57 + 2^58 + 2 < 2^59 */ + + /* + * tmp2 = (z1^3*y2 - z2^3*y1)*(z2^2*x1*(z1^2*x2 - z2^2*x1)^2 - x_out) + */ + felem_mul(tmp2, ftmp3, ftmp2); + /* tmp2[i] < 4 * 2^57 * 2^59 = 2^118 */ + + /*- + * y_out = (z1^3*y2 - z2^3*y1)*(z2^2*x1*(z1^2*x2 - z2^2*x1)^2 - x_out) - + * z2^3*y1*(z1^2*x2 - z2^2*x1)^3 + */ + widefelem_diff(tmp2, tmp); + /* tmp2[i] < 2^118 + 2^120 < 2^121 */ + felem_reduce(y_out, tmp2); + + /* + * the result (x_out, y_out, z_out) is incorrect if one of the inputs is + * the point at infinity, so we need to check for this separately + */ + + /* + * if point 1 is at infinity, copy point 2 to output, and vice versa + */ + copy_conditional(x_out, x2, z1_is_zero); + copy_conditional(x_out, x1, z2_is_zero); + copy_conditional(y_out, y2, z1_is_zero); + copy_conditional(y_out, y1, z2_is_zero); + copy_conditional(z_out, z2, z1_is_zero); + copy_conditional(z_out, z1, z2_is_zero); + felem_assign(x3, x_out); + felem_assign(y3, y_out); + felem_assign(z3, z_out); +} + +/* + * select_point selects the |idx|th point from a precomputation table and + * copies it to out. + * The pre_comp array argument should be size of |size| argument + */ +static void select_point(const u64 idx, unsigned int size, + const felem pre_comp[][3], felem out[3]) +{ + unsigned i, j; + limb *outlimbs = &out[0][0]; + + memset(out, 0, sizeof(*out) * 3); + for (i = 0; i < size; i++) { + const limb *inlimbs = &pre_comp[i][0][0]; + u64 mask = i ^ idx; + mask |= mask >> 4; + mask |= mask >> 2; + mask |= mask >> 1; + mask &= 1; + mask--; + for (j = 0; j < 4 * 3; j++) + outlimbs[j] |= inlimbs[j] & mask; + } +} + +/* get_bit returns the |i|th bit in |in| */ +static char get_bit(const felem_bytearray in, unsigned i) +{ + if (i >= 224) + return 0; + return (in[i >> 3] >> (i & 7)) & 1; +} + +/* + * Interleaved point multiplication using precomputed point multiples: The + * small point multiples 0*P, 1*P, ..., 16*P are in pre_comp[], the scalars + * in scalars[]. If g_scalar is non-NULL, we also add this multiple of the + * generator, using certain (large) precomputed multiples in g_pre_comp. + * Output point (X, Y, Z) is stored in x_out, y_out, z_out + */ +static void batch_mul(felem x_out, felem y_out, felem z_out, + const felem_bytearray scalars[], + const unsigned num_points, const u8 *g_scalar, + const int mixed, const felem pre_comp[][17][3], + const felem g_pre_comp[2][16][3]) +{ + int i, skip; + unsigned num; + unsigned gen_mul = (g_scalar != NULL); + felem nq[3], tmp[4]; + u64 bits; + u8 sign, digit; + + /* set nq to the point at infinity */ + memset(nq, 0, sizeof(nq)); + + /* + * Loop over all scalars msb-to-lsb, interleaving additions of multiples + * of the generator (two in each of the last 28 rounds) and additions of + * other points multiples (every 5th round). + */ + skip = 1; /* save two point operations in the first + * round */ + for (i = (num_points ? 220 : 27); i >= 0; --i) { + /* double */ + if (!skip) + point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]); + + /* add multiples of the generator */ + if (gen_mul && (i <= 27)) { + /* first, look 28 bits upwards */ + bits = get_bit(g_scalar, i + 196) << 3; + bits |= get_bit(g_scalar, i + 140) << 2; + bits |= get_bit(g_scalar, i + 84) << 1; + bits |= get_bit(g_scalar, i + 28); + /* select the point to add, in constant time */ + select_point(bits, 16, g_pre_comp[1], tmp); + + if (!skip) { + /* value 1 below is argument for "mixed" */ + point_add(nq[0], nq[1], nq[2], + nq[0], nq[1], nq[2], 1, tmp[0], tmp[1], tmp[2]); + } else { + memcpy(nq, tmp, 3 * sizeof(felem)); + skip = 0; + } + + /* second, look at the current position */ + bits = get_bit(g_scalar, i + 168) << 3; + bits |= get_bit(g_scalar, i + 112) << 2; + bits |= get_bit(g_scalar, i + 56) << 1; + bits |= get_bit(g_scalar, i); + /* select the point to add, in constant time */ + select_point(bits, 16, g_pre_comp[0], tmp); + point_add(nq[0], nq[1], nq[2], + nq[0], nq[1], nq[2], + 1 /* mixed */ , tmp[0], tmp[1], tmp[2]); + } + + /* do other additions every 5 doublings */ + if (num_points && (i % 5 == 0)) { + /* loop over all scalars */ + for (num = 0; num < num_points; ++num) { + bits = get_bit(scalars[num], i + 4) << 5; + bits |= get_bit(scalars[num], i + 3) << 4; + bits |= get_bit(scalars[num], i + 2) << 3; + bits |= get_bit(scalars[num], i + 1) << 2; + bits |= get_bit(scalars[num], i) << 1; + bits |= get_bit(scalars[num], i - 1); + ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits); + + /* select the point to add or subtract */ + select_point(digit, 17, pre_comp[num], tmp); + felem_neg(tmp[3], tmp[1]); /* (X, -Y, Z) is the negative + * point */ + copy_conditional(tmp[1], tmp[3], sign); + + if (!skip) { + point_add(nq[0], nq[1], nq[2], + nq[0], nq[1], nq[2], + mixed, tmp[0], tmp[1], tmp[2]); + } else { + memcpy(nq, tmp, 3 * sizeof(felem)); + skip = 0; + } + } + } + } + felem_assign(x_out, nq[0]); + felem_assign(y_out, nq[1]); + felem_assign(z_out, nq[2]); +} + +/******************************************************************************/ +/* + * FUNCTIONS TO MANAGE PRECOMPUTATION + */ + +static NISTP224_PRE_COMP *nistp224_pre_comp_new(void) +{ + NISTP224_PRE_COMP *ret = OPENSSL_zalloc(sizeof(*ret)); + + if (!ret) { + ECerr(EC_F_NISTP224_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); + return ret; + } + + ret->references = 1; + + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) { + ECerr(EC_F_NISTP224_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ret); + return NULL; + } + return ret; +} + +NISTP224_PRE_COMP *EC_nistp224_pre_comp_dup(NISTP224_PRE_COMP *p) +{ + int i; + if (p != NULL) + CRYPTO_UP_REF(&p->references, &i, p->lock); + return p; +} + +void EC_nistp224_pre_comp_free(NISTP224_PRE_COMP *p) +{ + int i; + + if (p == NULL) + return; + + CRYPTO_DOWN_REF(&p->references, &i, p->lock); + REF_PRINT_COUNT("EC_nistp224", x); + if (i > 0) + return; + REF_ASSERT_ISNT(i < 0); + + CRYPTO_THREAD_lock_free(p->lock); + OPENSSL_free(p); +} + +/******************************************************************************/ +/* + * OPENSSL EC_METHOD FUNCTIONS + */ + +int ec_GFp_nistp224_group_init(EC_GROUP *group) +{ + int ret; + ret = ec_GFp_simple_group_init(group); + group->a_is_minus3 = 1; + return ret; +} + +int ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *b, + BN_CTX *ctx) +{ + int ret = 0; + BN_CTX *new_ctx = NULL; + BIGNUM *curve_p, *curve_a, *curve_b; + + if (ctx == NULL) + if ((ctx = new_ctx = BN_CTX_new()) == NULL) + return 0; + BN_CTX_start(ctx); + curve_p = BN_CTX_get(ctx); + curve_a = BN_CTX_get(ctx); + curve_b = BN_CTX_get(ctx); + if (curve_b == NULL) + goto err; + BN_bin2bn(nistp224_curve_params[0], sizeof(felem_bytearray), curve_p); + BN_bin2bn(nistp224_curve_params[1], sizeof(felem_bytearray), curve_a); + BN_bin2bn(nistp224_curve_params[2], sizeof(felem_bytearray), curve_b); + if ((BN_cmp(curve_p, p)) || (BN_cmp(curve_a, a)) || (BN_cmp(curve_b, b))) { + ECerr(EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE, + EC_R_WRONG_CURVE_PARAMETERS); + goto err; + } + group->field_mod_func = BN_nist_mod_224; + ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); + err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +/* + * Takes the Jacobian coordinates (X, Y, Z) of a point and returns (X', Y') = + * (X/Z^2, Y/Z^3) + */ +int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx) +{ + felem z1, z2, x_in, y_in, x_out, y_out; + widefelem tmp; + + if (EC_POINT_is_at_infinity(group, point)) { + ECerr(EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES, + EC_R_POINT_AT_INFINITY); + return 0; + } + if ((!BN_to_felem(x_in, point->X)) || (!BN_to_felem(y_in, point->Y)) || + (!BN_to_felem(z1, point->Z))) + return 0; + felem_inv(z2, z1); + felem_square(tmp, z2); + felem_reduce(z1, tmp); + felem_mul(tmp, x_in, z1); + felem_reduce(x_in, tmp); + felem_contract(x_out, x_in); + if (x != NULL) { + if (!felem_to_BN(x, x_out)) { + ECerr(EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES, + ERR_R_BN_LIB); + return 0; + } + } + felem_mul(tmp, z1, z2); + felem_reduce(z1, tmp); + felem_mul(tmp, y_in, z1); + felem_reduce(y_in, tmp); + felem_contract(y_out, y_in); + if (y != NULL) { + if (!felem_to_BN(y, y_out)) { + ECerr(EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES, + ERR_R_BN_LIB); + return 0; + } + } + return 1; +} + +static void make_points_affine(size_t num, felem points[ /* num */ ][3], + felem tmp_felems[ /* num+1 */ ]) +{ + /* + * Runs in constant time, unless an input is the point at infinity (which + * normally shouldn't happen). + */ + ec_GFp_nistp_points_make_affine_internal(num, + points, + sizeof(felem), + tmp_felems, + (void (*)(void *))felem_one, + felem_is_zero_int, + (void (*)(void *, const void *)) + felem_assign, + (void (*)(void *, const void *)) + felem_square_reduce, (void (*) + (void *, + const void + *, + const void + *)) + felem_mul_reduce, + (void (*)(void *, const void *)) + felem_inv, + (void (*)(void *, const void *)) + felem_contract); +} + +/* + * Computes scalar*generator + \sum scalars[i]*points[i], ignoring NULL + * values Result is stored in r (r can equal one of the inputs). + */ +int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], + const BIGNUM *scalars[], BN_CTX *ctx) +{ + int ret = 0; + int j; + unsigned i; + int mixed = 0; + BIGNUM *x, *y, *z, *tmp_scalar; + felem_bytearray g_secret; + felem_bytearray *secrets = NULL; + felem (*pre_comp)[17][3] = NULL; + felem *tmp_felems = NULL; + felem_bytearray tmp; + unsigned num_bytes; + int have_pre_comp = 0; + size_t num_points = num; + felem x_in, y_in, z_in, x_out, y_out, z_out; + NISTP224_PRE_COMP *pre = NULL; + const felem(*g_pre_comp)[16][3] = NULL; + EC_POINT *generator = NULL; + const EC_POINT *p = NULL; + const BIGNUM *p_scalar = NULL; + + BN_CTX_start(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + z = BN_CTX_get(ctx); + tmp_scalar = BN_CTX_get(ctx); + if (tmp_scalar == NULL) + goto err; + + if (scalar != NULL) { + pre = group->pre_comp.nistp224; + if (pre) + /* we have precomputation, try to use it */ + g_pre_comp = (const felem(*)[16][3])pre->g_pre_comp; + else + /* try to use the standard precomputation */ + g_pre_comp = &gmul[0]; + generator = EC_POINT_new(group); + if (generator == NULL) + goto err; + /* get the generator from precomputation */ + if (!felem_to_BN(x, g_pre_comp[0][1][0]) || + !felem_to_BN(y, g_pre_comp[0][1][1]) || + !felem_to_BN(z, g_pre_comp[0][1][2])) { + ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB); + goto err; + } + if (!EC_POINT_set_Jprojective_coordinates_GFp(group, + generator, x, y, z, + ctx)) + goto err; + if (0 == EC_POINT_cmp(group, generator, group->generator, ctx)) + /* precomputation matches generator */ + have_pre_comp = 1; + else + /* + * we don't have valid precomputation: treat the generator as a + * random point + */ + num_points = num_points + 1; + } + + if (num_points > 0) { + if (num_points >= 3) { + /* + * unless we precompute multiples for just one or two points, + * converting those into affine form is time well spent + */ + mixed = 1; + } + secrets = OPENSSL_zalloc(sizeof(*secrets) * num_points); + pre_comp = OPENSSL_zalloc(sizeof(*pre_comp) * num_points); + if (mixed) + tmp_felems = + OPENSSL_malloc(sizeof(felem) * (num_points * 17 + 1)); + if ((secrets == NULL) || (pre_comp == NULL) + || (mixed && (tmp_felems == NULL))) { + ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* + * we treat NULL scalars as 0, and NULL points as points at infinity, + * i.e., they contribute nothing to the linear combination + */ + for (i = 0; i < num_points; ++i) { + if (i == num) + /* the generator */ + { + p = EC_GROUP_get0_generator(group); + p_scalar = scalar; + } else + /* the i^th point */ + { + p = points[i]; + p_scalar = scalars[i]; + } + if ((p_scalar != NULL) && (p != NULL)) { + /* reduce scalar to 0 <= scalar < 2^224 */ + if ((BN_num_bits(p_scalar) > 224) + || (BN_is_negative(p_scalar))) { + /* + * this is an unusual input, and we don't guarantee + * constant-timeness + */ + if (!BN_nnmod(tmp_scalar, p_scalar, group->order, ctx)) { + ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB); + goto err; + } + num_bytes = BN_bn2bin(tmp_scalar, tmp); + } else + num_bytes = BN_bn2bin(p_scalar, tmp); + flip_endian(secrets[i], tmp, num_bytes); + /* precompute multiples */ + if ((!BN_to_felem(x_out, p->X)) || + (!BN_to_felem(y_out, p->Y)) || + (!BN_to_felem(z_out, p->Z))) + goto err; + felem_assign(pre_comp[i][1][0], x_out); + felem_assign(pre_comp[i][1][1], y_out); + felem_assign(pre_comp[i][1][2], z_out); + for (j = 2; j <= 16; ++j) { + if (j & 1) { + point_add(pre_comp[i][j][0], pre_comp[i][j][1], + pre_comp[i][j][2], pre_comp[i][1][0], + pre_comp[i][1][1], pre_comp[i][1][2], 0, + pre_comp[i][j - 1][0], + pre_comp[i][j - 1][1], + pre_comp[i][j - 1][2]); + } else { + point_double(pre_comp[i][j][0], pre_comp[i][j][1], + pre_comp[i][j][2], pre_comp[i][j / 2][0], + pre_comp[i][j / 2][1], + pre_comp[i][j / 2][2]); + } + } + } + } + if (mixed) + make_points_affine(num_points * 17, pre_comp[0], tmp_felems); + } + + /* the scalar for the generator */ + if ((scalar != NULL) && (have_pre_comp)) { + memset(g_secret, 0, sizeof(g_secret)); + /* reduce scalar to 0 <= scalar < 2^224 */ + if ((BN_num_bits(scalar) > 224) || (BN_is_negative(scalar))) { + /* + * this is an unusual input, and we don't guarantee + * constant-timeness + */ + if (!BN_nnmod(tmp_scalar, scalar, group->order, ctx)) { + ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB); + goto err; + } + num_bytes = BN_bn2bin(tmp_scalar, tmp); + } else + num_bytes = BN_bn2bin(scalar, tmp); + flip_endian(g_secret, tmp, num_bytes); + /* do the multiplication with generator precomputation */ + batch_mul(x_out, y_out, z_out, + (const felem_bytearray(*))secrets, num_points, + g_secret, + mixed, (const felem(*)[17][3])pre_comp, g_pre_comp); + } else + /* do the multiplication without generator precomputation */ + batch_mul(x_out, y_out, z_out, + (const felem_bytearray(*))secrets, num_points, + NULL, mixed, (const felem(*)[17][3])pre_comp, NULL); + /* reduce the output to its unique minimal representation */ + felem_contract(x_in, x_out); + felem_contract(y_in, y_out); + felem_contract(z_in, z_out); + if ((!felem_to_BN(x, x_in)) || (!felem_to_BN(y, y_in)) || + (!felem_to_BN(z, z_in))) { + ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB); + goto err; + } + ret = EC_POINT_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx); + + err: + BN_CTX_end(ctx); + EC_POINT_free(generator); + OPENSSL_free(secrets); + OPENSSL_free(pre_comp); + OPENSSL_free(tmp_felems); + return ret; +} + +int ec_GFp_nistp224_precompute_mult(EC_GROUP *group, BN_CTX *ctx) +{ + int ret = 0; + NISTP224_PRE_COMP *pre = NULL; + int i, j; + BN_CTX *new_ctx = NULL; + BIGNUM *x, *y; + EC_POINT *generator = NULL; + felem tmp_felems[32]; + + /* throw away old precomputation */ + EC_pre_comp_free(group); + if (ctx == NULL) + if ((ctx = new_ctx = BN_CTX_new()) == NULL) + return 0; + BN_CTX_start(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (y == NULL) + goto err; + /* get the generator */ + if (group->generator == NULL) + goto err; + generator = EC_POINT_new(group); + if (generator == NULL) + goto err; + BN_bin2bn(nistp224_curve_params[3], sizeof(felem_bytearray), x); + BN_bin2bn(nistp224_curve_params[4], sizeof(felem_bytearray), y); + if (!EC_POINT_set_affine_coordinates(group, generator, x, y, ctx)) + goto err; + if ((pre = nistp224_pre_comp_new()) == NULL) + goto err; + /* + * if the generator is the standard one, use built-in precomputation + */ + if (0 == EC_POINT_cmp(group, generator, group->generator, ctx)) { + memcpy(pre->g_pre_comp, gmul, sizeof(pre->g_pre_comp)); + goto done; + } + if ((!BN_to_felem(pre->g_pre_comp[0][1][0], group->generator->X)) || + (!BN_to_felem(pre->g_pre_comp[0][1][1], group->generator->Y)) || + (!BN_to_felem(pre->g_pre_comp[0][1][2], group->generator->Z))) + goto err; + /* + * compute 2^56*G, 2^112*G, 2^168*G for the first table, 2^28*G, 2^84*G, + * 2^140*G, 2^196*G for the second one + */ + for (i = 1; i <= 8; i <<= 1) { + point_double(pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], + pre->g_pre_comp[1][i][2], pre->g_pre_comp[0][i][0], + pre->g_pre_comp[0][i][1], pre->g_pre_comp[0][i][2]); + for (j = 0; j < 27; ++j) { + point_double(pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], + pre->g_pre_comp[1][i][2], pre->g_pre_comp[1][i][0], + pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2]); + } + if (i == 8) + break; + point_double(pre->g_pre_comp[0][2 * i][0], + pre->g_pre_comp[0][2 * i][1], + pre->g_pre_comp[0][2 * i][2], pre->g_pre_comp[1][i][0], + pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2]); + for (j = 0; j < 27; ++j) { + point_double(pre->g_pre_comp[0][2 * i][0], + pre->g_pre_comp[0][2 * i][1], + pre->g_pre_comp[0][2 * i][2], + pre->g_pre_comp[0][2 * i][0], + pre->g_pre_comp[0][2 * i][1], + pre->g_pre_comp[0][2 * i][2]); + } + } + for (i = 0; i < 2; i++) { + /* g_pre_comp[i][0] is the point at infinity */ + memset(pre->g_pre_comp[i][0], 0, sizeof(pre->g_pre_comp[i][0])); + /* the remaining multiples */ + /* 2^56*G + 2^112*G resp. 2^84*G + 2^140*G */ + point_add(pre->g_pre_comp[i][6][0], pre->g_pre_comp[i][6][1], + pre->g_pre_comp[i][6][2], pre->g_pre_comp[i][4][0], + pre->g_pre_comp[i][4][1], pre->g_pre_comp[i][4][2], + 0, pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1], + pre->g_pre_comp[i][2][2]); + /* 2^56*G + 2^168*G resp. 2^84*G + 2^196*G */ + point_add(pre->g_pre_comp[i][10][0], pre->g_pre_comp[i][10][1], + pre->g_pre_comp[i][10][2], pre->g_pre_comp[i][8][0], + pre->g_pre_comp[i][8][1], pre->g_pre_comp[i][8][2], + 0, pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1], + pre->g_pre_comp[i][2][2]); + /* 2^112*G + 2^168*G resp. 2^140*G + 2^196*G */ + point_add(pre->g_pre_comp[i][12][0], pre->g_pre_comp[i][12][1], + pre->g_pre_comp[i][12][2], pre->g_pre_comp[i][8][0], + pre->g_pre_comp[i][8][1], pre->g_pre_comp[i][8][2], + 0, pre->g_pre_comp[i][4][0], pre->g_pre_comp[i][4][1], + pre->g_pre_comp[i][4][2]); + /* + * 2^56*G + 2^112*G + 2^168*G resp. 2^84*G + 2^140*G + 2^196*G + */ + point_add(pre->g_pre_comp[i][14][0], pre->g_pre_comp[i][14][1], + pre->g_pre_comp[i][14][2], pre->g_pre_comp[i][12][0], + pre->g_pre_comp[i][12][1], pre->g_pre_comp[i][12][2], + 0, pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1], + pre->g_pre_comp[i][2][2]); + for (j = 1; j < 8; ++j) { + /* odd multiples: add G resp. 2^28*G */ + point_add(pre->g_pre_comp[i][2 * j + 1][0], + pre->g_pre_comp[i][2 * j + 1][1], + pre->g_pre_comp[i][2 * j + 1][2], + pre->g_pre_comp[i][2 * j][0], + pre->g_pre_comp[i][2 * j][1], + pre->g_pre_comp[i][2 * j][2], 0, + pre->g_pre_comp[i][1][0], pre->g_pre_comp[i][1][1], + pre->g_pre_comp[i][1][2]); + } + } + make_points_affine(31, &(pre->g_pre_comp[0][1]), tmp_felems); + + done: + SETPRECOMP(group, nistp224, pre); + pre = NULL; + ret = 1; + err: + BN_CTX_end(ctx); + EC_POINT_free(generator); + BN_CTX_free(new_ctx); + EC_nistp224_pre_comp_free(pre); + return ret; +} + +int ec_GFp_nistp224_have_precompute_mult(const EC_GROUP *group) +{ + return HAVEPRECOMP(group, nistp224); +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_nistp256.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_nistp256.c new file mode 100644 index 000000000..a21e5f78f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_nistp256.c @@ -0,0 +1,2355 @@ +/* + * Copyright 2011-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Copyright 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * A 64-bit implementation of the NIST P-256 elliptic curve point multiplication + * + * OpenSSL integration was taken from Emilia Kasper's work in ecp_nistp224.c. + * Otherwise based on Emilia's P224 work, which was inspired by my curve25519 + * work which got its smarts from Daniel J. Bernstein's work on the same. + */ + +#include +#ifdef OPENSSL_NO_EC_NISTP_64_GCC_128 +NON_EMPTY_TRANSLATION_UNIT +#else + +# include +# include +# include +# include "ec_lcl.h" + +# if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__==16 + /* even with gcc, the typedef won't work for 32-bit platforms */ +typedef __uint128_t uint128_t; /* nonstandard; implemented by gcc on 64-bit + * platforms */ +typedef __int128_t int128_t; +# else +# error "Your compiler doesn't appear to support 128-bit integer types" +# endif + +typedef uint8_t u8; +typedef uint32_t u32; +typedef uint64_t u64; + +/* + * The underlying field. P256 operates over GF(2^256-2^224+2^192+2^96-1). We + * can serialise an element of this field into 32 bytes. We call this an + * felem_bytearray. + */ + +typedef u8 felem_bytearray[32]; + +/* + * These are the parameters of P256, taken from FIPS 186-3, page 86. These + * values are big-endian. + */ +static const felem_bytearray nistp256_curve_params[5] = { + {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, /* p */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, /* a = -3 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc}, /* b */ + {0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, + 0xb3, 0xeb, 0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, + 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, 0xb0, 0xf6, + 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b}, + {0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, /* x */ + 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, + 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, + 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96}, + {0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, /* y */ + 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, + 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, + 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5} +}; + +/*- + * The representation of field elements. + * ------------------------------------ + * + * We represent field elements with either four 128-bit values, eight 128-bit + * values, or four 64-bit values. The field element represented is: + * v[0]*2^0 + v[1]*2^64 + v[2]*2^128 + v[3]*2^192 (mod p) + * or: + * v[0]*2^0 + v[1]*2^64 + v[2]*2^128 + ... + v[8]*2^512 (mod p) + * + * 128-bit values are called 'limbs'. Since the limbs are spaced only 64 bits + * apart, but are 128-bits wide, the most significant bits of each limb overlap + * with the least significant bits of the next. + * + * A field element with four limbs is an 'felem'. One with eight limbs is a + * 'longfelem' + * + * A field element with four, 64-bit values is called a 'smallfelem'. Small + * values are used as intermediate values before multiplication. + */ + +# define NLIMBS 4 + +typedef uint128_t limb; +typedef limb felem[NLIMBS]; +typedef limb longfelem[NLIMBS * 2]; +typedef u64 smallfelem[NLIMBS]; + +/* This is the value of the prime as four 64-bit words, little-endian. */ +static const u64 kPrime[4] = + { 0xfffffffffffffffful, 0xffffffff, 0, 0xffffffff00000001ul }; +static const u64 bottom63bits = 0x7ffffffffffffffful; + +/* + * bin32_to_felem takes a little-endian byte array and converts it into felem + * form. This assumes that the CPU is little-endian. + */ +static void bin32_to_felem(felem out, const u8 in[32]) +{ + out[0] = *((u64 *)&in[0]); + out[1] = *((u64 *)&in[8]); + out[2] = *((u64 *)&in[16]); + out[3] = *((u64 *)&in[24]); +} + +/* + * smallfelem_to_bin32 takes a smallfelem and serialises into a little + * endian, 32 byte array. This assumes that the CPU is little-endian. + */ +static void smallfelem_to_bin32(u8 out[32], const smallfelem in) +{ + *((u64 *)&out[0]) = in[0]; + *((u64 *)&out[8]) = in[1]; + *((u64 *)&out[16]) = in[2]; + *((u64 *)&out[24]) = in[3]; +} + +/* To preserve endianness when using BN_bn2bin and BN_bin2bn */ +static void flip_endian(u8 *out, const u8 *in, unsigned len) +{ + unsigned i; + for (i = 0; i < len; ++i) + out[i] = in[len - 1 - i]; +} + +/* BN_to_felem converts an OpenSSL BIGNUM into an felem */ +static int BN_to_felem(felem out, const BIGNUM *bn) +{ + felem_bytearray b_in; + felem_bytearray b_out; + unsigned num_bytes; + + /* BN_bn2bin eats leading zeroes */ + memset(b_out, 0, sizeof(b_out)); + num_bytes = BN_num_bytes(bn); + if (num_bytes > sizeof(b_out)) { + ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE); + return 0; + } + if (BN_is_negative(bn)) { + ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE); + return 0; + } + num_bytes = BN_bn2bin(bn, b_in); + flip_endian(b_out, b_in, num_bytes); + bin32_to_felem(out, b_out); + return 1; +} + +/* felem_to_BN converts an felem into an OpenSSL BIGNUM */ +static BIGNUM *smallfelem_to_BN(BIGNUM *out, const smallfelem in) +{ + felem_bytearray b_in, b_out; + smallfelem_to_bin32(b_in, in); + flip_endian(b_out, b_in, sizeof(b_out)); + return BN_bin2bn(b_out, sizeof(b_out), out); +} + +/*- + * Field operations + * ---------------- + */ + +static void smallfelem_one(smallfelem out) +{ + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 0; +} + +static void smallfelem_assign(smallfelem out, const smallfelem in) +{ + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; +} + +static void felem_assign(felem out, const felem in) +{ + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; +} + +/* felem_sum sets out = out + in. */ +static void felem_sum(felem out, const felem in) +{ + out[0] += in[0]; + out[1] += in[1]; + out[2] += in[2]; + out[3] += in[3]; +} + +/* felem_small_sum sets out = out + in. */ +static void felem_small_sum(felem out, const smallfelem in) +{ + out[0] += in[0]; + out[1] += in[1]; + out[2] += in[2]; + out[3] += in[3]; +} + +/* felem_scalar sets out = out * scalar */ +static void felem_scalar(felem out, const u64 scalar) +{ + out[0] *= scalar; + out[1] *= scalar; + out[2] *= scalar; + out[3] *= scalar; +} + +/* longfelem_scalar sets out = out * scalar */ +static void longfelem_scalar(longfelem out, const u64 scalar) +{ + out[0] *= scalar; + out[1] *= scalar; + out[2] *= scalar; + out[3] *= scalar; + out[4] *= scalar; + out[5] *= scalar; + out[6] *= scalar; + out[7] *= scalar; +} + +# define two105m41m9 (((limb)1) << 105) - (((limb)1) << 41) - (((limb)1) << 9) +# define two105 (((limb)1) << 105) +# define two105m41p9 (((limb)1) << 105) - (((limb)1) << 41) + (((limb)1) << 9) + +/* zero105 is 0 mod p */ +static const felem zero105 = + { two105m41m9, two105, two105m41p9, two105m41p9 }; + +/*- + * smallfelem_neg sets |out| to |-small| + * On exit: + * out[i] < out[i] + 2^105 + */ +static void smallfelem_neg(felem out, const smallfelem small) +{ + /* In order to prevent underflow, we subtract from 0 mod p. */ + out[0] = zero105[0] - small[0]; + out[1] = zero105[1] - small[1]; + out[2] = zero105[2] - small[2]; + out[3] = zero105[3] - small[3]; +} + +/*- + * felem_diff subtracts |in| from |out| + * On entry: + * in[i] < 2^104 + * On exit: + * out[i] < out[i] + 2^105 + */ +static void felem_diff(felem out, const felem in) +{ + /* + * In order to prevent underflow, we add 0 mod p before subtracting. + */ + out[0] += zero105[0]; + out[1] += zero105[1]; + out[2] += zero105[2]; + out[3] += zero105[3]; + + out[0] -= in[0]; + out[1] -= in[1]; + out[2] -= in[2]; + out[3] -= in[3]; +} + +# define two107m43m11 (((limb)1) << 107) - (((limb)1) << 43) - (((limb)1) << 11) +# define two107 (((limb)1) << 107) +# define two107m43p11 (((limb)1) << 107) - (((limb)1) << 43) + (((limb)1) << 11) + +/* zero107 is 0 mod p */ +static const felem zero107 = + { two107m43m11, two107, two107m43p11, two107m43p11 }; + +/*- + * An alternative felem_diff for larger inputs |in| + * felem_diff_zero107 subtracts |in| from |out| + * On entry: + * in[i] < 2^106 + * On exit: + * out[i] < out[i] + 2^107 + */ +static void felem_diff_zero107(felem out, const felem in) +{ + /* + * In order to prevent underflow, we add 0 mod p before subtracting. + */ + out[0] += zero107[0]; + out[1] += zero107[1]; + out[2] += zero107[2]; + out[3] += zero107[3]; + + out[0] -= in[0]; + out[1] -= in[1]; + out[2] -= in[2]; + out[3] -= in[3]; +} + +/*- + * longfelem_diff subtracts |in| from |out| + * On entry: + * in[i] < 7*2^67 + * On exit: + * out[i] < out[i] + 2^70 + 2^40 + */ +static void longfelem_diff(longfelem out, const longfelem in) +{ + static const limb two70m8p6 = + (((limb) 1) << 70) - (((limb) 1) << 8) + (((limb) 1) << 6); + static const limb two70p40 = (((limb) 1) << 70) + (((limb) 1) << 40); + static const limb two70 = (((limb) 1) << 70); + static const limb two70m40m38p6 = + (((limb) 1) << 70) - (((limb) 1) << 40) - (((limb) 1) << 38) + + (((limb) 1) << 6); + static const limb two70m6 = (((limb) 1) << 70) - (((limb) 1) << 6); + + /* add 0 mod p to avoid underflow */ + out[0] += two70m8p6; + out[1] += two70p40; + out[2] += two70; + out[3] += two70m40m38p6; + out[4] += two70m6; + out[5] += two70m6; + out[6] += two70m6; + out[7] += two70m6; + + /* in[i] < 7*2^67 < 2^70 - 2^40 - 2^38 + 2^6 */ + out[0] -= in[0]; + out[1] -= in[1]; + out[2] -= in[2]; + out[3] -= in[3]; + out[4] -= in[4]; + out[5] -= in[5]; + out[6] -= in[6]; + out[7] -= in[7]; +} + +# define two64m0 (((limb)1) << 64) - 1 +# define two110p32m0 (((limb)1) << 110) + (((limb)1) << 32) - 1 +# define two64m46 (((limb)1) << 64) - (((limb)1) << 46) +# define two64m32 (((limb)1) << 64) - (((limb)1) << 32) + +/* zero110 is 0 mod p */ +static const felem zero110 = { two64m0, two110p32m0, two64m46, two64m32 }; + +/*- + * felem_shrink converts an felem into a smallfelem. The result isn't quite + * minimal as the value may be greater than p. + * + * On entry: + * in[i] < 2^109 + * On exit: + * out[i] < 2^64 + */ +static void felem_shrink(smallfelem out, const felem in) +{ + felem tmp; + u64 a, b, mask; + u64 high, low; + static const u64 kPrime3Test = 0x7fffffff00000001ul; /* 2^63 - 2^32 + 1 */ + + /* Carry 2->3 */ + tmp[3] = zero110[3] + in[3] + ((u64)(in[2] >> 64)); + /* tmp[3] < 2^110 */ + + tmp[2] = zero110[2] + (u64)in[2]; + tmp[0] = zero110[0] + in[0]; + tmp[1] = zero110[1] + in[1]; + /* tmp[0] < 2**110, tmp[1] < 2^111, tmp[2] < 2**65 */ + + /* + * We perform two partial reductions where we eliminate the high-word of + * tmp[3]. We don't update the other words till the end. + */ + a = tmp[3] >> 64; /* a < 2^46 */ + tmp[3] = (u64)tmp[3]; + tmp[3] -= a; + tmp[3] += ((limb) a) << 32; + /* tmp[3] < 2^79 */ + + b = a; + a = tmp[3] >> 64; /* a < 2^15 */ + b += a; /* b < 2^46 + 2^15 < 2^47 */ + tmp[3] = (u64)tmp[3]; + tmp[3] -= a; + tmp[3] += ((limb) a) << 32; + /* tmp[3] < 2^64 + 2^47 */ + + /* + * This adjusts the other two words to complete the two partial + * reductions. + */ + tmp[0] += b; + tmp[1] -= (((limb) b) << 32); + + /* + * In order to make space in tmp[3] for the carry from 2 -> 3, we + * conditionally subtract kPrime if tmp[3] is large enough. + */ + high = (u64)(tmp[3] >> 64); + /* As tmp[3] < 2^65, high is either 1 or 0 */ + high = 0 - high; + /*- + * high is: + * all ones if the high word of tmp[3] is 1 + * all zeros if the high word of tmp[3] if 0 + */ + low = (u64)tmp[3]; + mask = 0 - (low >> 63); + /*- + * mask is: + * all ones if the MSB of low is 1 + * all zeros if the MSB of low if 0 + */ + low &= bottom63bits; + low -= kPrime3Test; + /* if low was greater than kPrime3Test then the MSB is zero */ + low = ~low; + low = 0 - (low >> 63); + /*- + * low is: + * all ones if low was > kPrime3Test + * all zeros if low was <= kPrime3Test + */ + mask = (mask & low) | high; + tmp[0] -= mask & kPrime[0]; + tmp[1] -= mask & kPrime[1]; + /* kPrime[2] is zero, so omitted */ + tmp[3] -= mask & kPrime[3]; + /* tmp[3] < 2**64 - 2**32 + 1 */ + + tmp[1] += ((u64)(tmp[0] >> 64)); + tmp[0] = (u64)tmp[0]; + tmp[2] += ((u64)(tmp[1] >> 64)); + tmp[1] = (u64)tmp[1]; + tmp[3] += ((u64)(tmp[2] >> 64)); + tmp[2] = (u64)tmp[2]; + /* tmp[i] < 2^64 */ + + out[0] = tmp[0]; + out[1] = tmp[1]; + out[2] = tmp[2]; + out[3] = tmp[3]; +} + +/* smallfelem_expand converts a smallfelem to an felem */ +static void smallfelem_expand(felem out, const smallfelem in) +{ + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; +} + +/*- + * smallfelem_square sets |out| = |small|^2 + * On entry: + * small[i] < 2^64 + * On exit: + * out[i] < 7 * 2^64 < 2^67 + */ +static void smallfelem_square(longfelem out, const smallfelem small) +{ + limb a; + u64 high, low; + + a = ((uint128_t) small[0]) * small[0]; + low = a; + high = a >> 64; + out[0] = low; + out[1] = high; + + a = ((uint128_t) small[0]) * small[1]; + low = a; + high = a >> 64; + out[1] += low; + out[1] += low; + out[2] = high; + + a = ((uint128_t) small[0]) * small[2]; + low = a; + high = a >> 64; + out[2] += low; + out[2] *= 2; + out[3] = high; + + a = ((uint128_t) small[0]) * small[3]; + low = a; + high = a >> 64; + out[3] += low; + out[4] = high; + + a = ((uint128_t) small[1]) * small[2]; + low = a; + high = a >> 64; + out[3] += low; + out[3] *= 2; + out[4] += high; + + a = ((uint128_t) small[1]) * small[1]; + low = a; + high = a >> 64; + out[2] += low; + out[3] += high; + + a = ((uint128_t) small[1]) * small[3]; + low = a; + high = a >> 64; + out[4] += low; + out[4] *= 2; + out[5] = high; + + a = ((uint128_t) small[2]) * small[3]; + low = a; + high = a >> 64; + out[5] += low; + out[5] *= 2; + out[6] = high; + out[6] += high; + + a = ((uint128_t) small[2]) * small[2]; + low = a; + high = a >> 64; + out[4] += low; + out[5] += high; + + a = ((uint128_t) small[3]) * small[3]; + low = a; + high = a >> 64; + out[6] += low; + out[7] = high; +} + +/*- + * felem_square sets |out| = |in|^2 + * On entry: + * in[i] < 2^109 + * On exit: + * out[i] < 7 * 2^64 < 2^67 + */ +static void felem_square(longfelem out, const felem in) +{ + u64 small[4]; + felem_shrink(small, in); + smallfelem_square(out, small); +} + +/*- + * smallfelem_mul sets |out| = |small1| * |small2| + * On entry: + * small1[i] < 2^64 + * small2[i] < 2^64 + * On exit: + * out[i] < 7 * 2^64 < 2^67 + */ +static void smallfelem_mul(longfelem out, const smallfelem small1, + const smallfelem small2) +{ + limb a; + u64 high, low; + + a = ((uint128_t) small1[0]) * small2[0]; + low = a; + high = a >> 64; + out[0] = low; + out[1] = high; + + a = ((uint128_t) small1[0]) * small2[1]; + low = a; + high = a >> 64; + out[1] += low; + out[2] = high; + + a = ((uint128_t) small1[1]) * small2[0]; + low = a; + high = a >> 64; + out[1] += low; + out[2] += high; + + a = ((uint128_t) small1[0]) * small2[2]; + low = a; + high = a >> 64; + out[2] += low; + out[3] = high; + + a = ((uint128_t) small1[1]) * small2[1]; + low = a; + high = a >> 64; + out[2] += low; + out[3] += high; + + a = ((uint128_t) small1[2]) * small2[0]; + low = a; + high = a >> 64; + out[2] += low; + out[3] += high; + + a = ((uint128_t) small1[0]) * small2[3]; + low = a; + high = a >> 64; + out[3] += low; + out[4] = high; + + a = ((uint128_t) small1[1]) * small2[2]; + low = a; + high = a >> 64; + out[3] += low; + out[4] += high; + + a = ((uint128_t) small1[2]) * small2[1]; + low = a; + high = a >> 64; + out[3] += low; + out[4] += high; + + a = ((uint128_t) small1[3]) * small2[0]; + low = a; + high = a >> 64; + out[3] += low; + out[4] += high; + + a = ((uint128_t) small1[1]) * small2[3]; + low = a; + high = a >> 64; + out[4] += low; + out[5] = high; + + a = ((uint128_t) small1[2]) * small2[2]; + low = a; + high = a >> 64; + out[4] += low; + out[5] += high; + + a = ((uint128_t) small1[3]) * small2[1]; + low = a; + high = a >> 64; + out[4] += low; + out[5] += high; + + a = ((uint128_t) small1[2]) * small2[3]; + low = a; + high = a >> 64; + out[5] += low; + out[6] = high; + + a = ((uint128_t) small1[3]) * small2[2]; + low = a; + high = a >> 64; + out[5] += low; + out[6] += high; + + a = ((uint128_t) small1[3]) * small2[3]; + low = a; + high = a >> 64; + out[6] += low; + out[7] = high; +} + +/*- + * felem_mul sets |out| = |in1| * |in2| + * On entry: + * in1[i] < 2^109 + * in2[i] < 2^109 + * On exit: + * out[i] < 7 * 2^64 < 2^67 + */ +static void felem_mul(longfelem out, const felem in1, const felem in2) +{ + smallfelem small1, small2; + felem_shrink(small1, in1); + felem_shrink(small2, in2); + smallfelem_mul(out, small1, small2); +} + +/*- + * felem_small_mul sets |out| = |small1| * |in2| + * On entry: + * small1[i] < 2^64 + * in2[i] < 2^109 + * On exit: + * out[i] < 7 * 2^64 < 2^67 + */ +static void felem_small_mul(longfelem out, const smallfelem small1, + const felem in2) +{ + smallfelem small2; + felem_shrink(small2, in2); + smallfelem_mul(out, small1, small2); +} + +# define two100m36m4 (((limb)1) << 100) - (((limb)1) << 36) - (((limb)1) << 4) +# define two100 (((limb)1) << 100) +# define two100m36p4 (((limb)1) << 100) - (((limb)1) << 36) + (((limb)1) << 4) +/* zero100 is 0 mod p */ +static const felem zero100 = + { two100m36m4, two100, two100m36p4, two100m36p4 }; + +/*- + * Internal function for the different flavours of felem_reduce. + * felem_reduce_ reduces the higher coefficients in[4]-in[7]. + * On entry: + * out[0] >= in[6] + 2^32*in[6] + in[7] + 2^32*in[7] + * out[1] >= in[7] + 2^32*in[4] + * out[2] >= in[5] + 2^32*in[5] + * out[3] >= in[4] + 2^32*in[5] + 2^32*in[6] + * On exit: + * out[0] <= out[0] + in[4] + 2^32*in[5] + * out[1] <= out[1] + in[5] + 2^33*in[6] + * out[2] <= out[2] + in[7] + 2*in[6] + 2^33*in[7] + * out[3] <= out[3] + 2^32*in[4] + 3*in[7] + */ +static void felem_reduce_(felem out, const longfelem in) +{ + int128_t c; + /* combine common terms from below */ + c = in[4] + (in[5] << 32); + out[0] += c; + out[3] -= c; + + c = in[5] - in[7]; + out[1] += c; + out[2] -= c; + + /* the remaining terms */ + /* 256: [(0,1),(96,-1),(192,-1),(224,1)] */ + out[1] -= (in[4] << 32); + out[3] += (in[4] << 32); + + /* 320: [(32,1),(64,1),(128,-1),(160,-1),(224,-1)] */ + out[2] -= (in[5] << 32); + + /* 384: [(0,-1),(32,-1),(96,2),(128,2),(224,-1)] */ + out[0] -= in[6]; + out[0] -= (in[6] << 32); + out[1] += (in[6] << 33); + out[2] += (in[6] * 2); + out[3] -= (in[6] << 32); + + /* 448: [(0,-1),(32,-1),(64,-1),(128,1),(160,2),(192,3)] */ + out[0] -= in[7]; + out[0] -= (in[7] << 32); + out[2] += (in[7] << 33); + out[3] += (in[7] * 3); +} + +/*- + * felem_reduce converts a longfelem into an felem. + * To be called directly after felem_square or felem_mul. + * On entry: + * in[0] < 2^64, in[1] < 3*2^64, in[2] < 5*2^64, in[3] < 7*2^64 + * in[4] < 7*2^64, in[5] < 5*2^64, in[6] < 3*2^64, in[7] < 2*64 + * On exit: + * out[i] < 2^101 + */ +static void felem_reduce(felem out, const longfelem in) +{ + out[0] = zero100[0] + in[0]; + out[1] = zero100[1] + in[1]; + out[2] = zero100[2] + in[2]; + out[3] = zero100[3] + in[3]; + + felem_reduce_(out, in); + + /*- + * out[0] > 2^100 - 2^36 - 2^4 - 3*2^64 - 3*2^96 - 2^64 - 2^96 > 0 + * out[1] > 2^100 - 2^64 - 7*2^96 > 0 + * out[2] > 2^100 - 2^36 + 2^4 - 5*2^64 - 5*2^96 > 0 + * out[3] > 2^100 - 2^36 + 2^4 - 7*2^64 - 5*2^96 - 3*2^96 > 0 + * + * out[0] < 2^100 + 2^64 + 7*2^64 + 5*2^96 < 2^101 + * out[1] < 2^100 + 3*2^64 + 5*2^64 + 3*2^97 < 2^101 + * out[2] < 2^100 + 5*2^64 + 2^64 + 3*2^65 + 2^97 < 2^101 + * out[3] < 2^100 + 7*2^64 + 7*2^96 + 3*2^64 < 2^101 + */ +} + +/*- + * felem_reduce_zero105 converts a larger longfelem into an felem. + * On entry: + * in[0] < 2^71 + * On exit: + * out[i] < 2^106 + */ +static void felem_reduce_zero105(felem out, const longfelem in) +{ + out[0] = zero105[0] + in[0]; + out[1] = zero105[1] + in[1]; + out[2] = zero105[2] + in[2]; + out[3] = zero105[3] + in[3]; + + felem_reduce_(out, in); + + /*- + * out[0] > 2^105 - 2^41 - 2^9 - 2^71 - 2^103 - 2^71 - 2^103 > 0 + * out[1] > 2^105 - 2^71 - 2^103 > 0 + * out[2] > 2^105 - 2^41 + 2^9 - 2^71 - 2^103 > 0 + * out[3] > 2^105 - 2^41 + 2^9 - 2^71 - 2^103 - 2^103 > 0 + * + * out[0] < 2^105 + 2^71 + 2^71 + 2^103 < 2^106 + * out[1] < 2^105 + 2^71 + 2^71 + 2^103 < 2^106 + * out[2] < 2^105 + 2^71 + 2^71 + 2^71 + 2^103 < 2^106 + * out[3] < 2^105 + 2^71 + 2^103 + 2^71 < 2^106 + */ +} + +/* + * subtract_u64 sets *result = *result - v and *carry to one if the + * subtraction underflowed. + */ +static void subtract_u64(u64 *result, u64 *carry, u64 v) +{ + uint128_t r = *result; + r -= v; + *carry = (r >> 64) & 1; + *result = (u64)r; +} + +/* + * felem_contract converts |in| to its unique, minimal representation. On + * entry: in[i] < 2^109 + */ +static void felem_contract(smallfelem out, const felem in) +{ + unsigned i; + u64 all_equal_so_far = 0, result = 0, carry; + + felem_shrink(out, in); + /* small is minimal except that the value might be > p */ + + all_equal_so_far--; + /* + * We are doing a constant time test if out >= kPrime. We need to compare + * each u64, from most-significant to least significant. For each one, if + * all words so far have been equal (m is all ones) then a non-equal + * result is the answer. Otherwise we continue. + */ + for (i = 3; i < 4; i--) { + u64 equal; + uint128_t a = ((uint128_t) kPrime[i]) - out[i]; + /* + * if out[i] > kPrime[i] then a will underflow and the high 64-bits + * will all be set. + */ + result |= all_equal_so_far & ((u64)(a >> 64)); + + /* + * if kPrime[i] == out[i] then |equal| will be all zeros and the + * decrement will make it all ones. + */ + equal = kPrime[i] ^ out[i]; + equal--; + equal &= equal << 32; + equal &= equal << 16; + equal &= equal << 8; + equal &= equal << 4; + equal &= equal << 2; + equal &= equal << 1; + equal = 0 - (equal >> 63); + + all_equal_so_far &= equal; + } + + /* + * if all_equal_so_far is still all ones then the two values are equal + * and so out >= kPrime is true. + */ + result |= all_equal_so_far; + + /* if out >= kPrime then we subtract kPrime. */ + subtract_u64(&out[0], &carry, result & kPrime[0]); + subtract_u64(&out[1], &carry, carry); + subtract_u64(&out[2], &carry, carry); + subtract_u64(&out[3], &carry, carry); + + subtract_u64(&out[1], &carry, result & kPrime[1]); + subtract_u64(&out[2], &carry, carry); + subtract_u64(&out[3], &carry, carry); + + subtract_u64(&out[2], &carry, result & kPrime[2]); + subtract_u64(&out[3], &carry, carry); + + subtract_u64(&out[3], &carry, result & kPrime[3]); +} + +static void smallfelem_square_contract(smallfelem out, const smallfelem in) +{ + longfelem longtmp; + felem tmp; + + smallfelem_square(longtmp, in); + felem_reduce(tmp, longtmp); + felem_contract(out, tmp); +} + +static void smallfelem_mul_contract(smallfelem out, const smallfelem in1, + const smallfelem in2) +{ + longfelem longtmp; + felem tmp; + + smallfelem_mul(longtmp, in1, in2); + felem_reduce(tmp, longtmp); + felem_contract(out, tmp); +} + +/*- + * felem_is_zero returns a limb with all bits set if |in| == 0 (mod p) and 0 + * otherwise. + * On entry: + * small[i] < 2^64 + */ +static limb smallfelem_is_zero(const smallfelem small) +{ + limb result; + u64 is_p; + + u64 is_zero = small[0] | small[1] | small[2] | small[3]; + is_zero--; + is_zero &= is_zero << 32; + is_zero &= is_zero << 16; + is_zero &= is_zero << 8; + is_zero &= is_zero << 4; + is_zero &= is_zero << 2; + is_zero &= is_zero << 1; + is_zero = 0 - (is_zero >> 63); + + is_p = (small[0] ^ kPrime[0]) | + (small[1] ^ kPrime[1]) | + (small[2] ^ kPrime[2]) | (small[3] ^ kPrime[3]); + is_p--; + is_p &= is_p << 32; + is_p &= is_p << 16; + is_p &= is_p << 8; + is_p &= is_p << 4; + is_p &= is_p << 2; + is_p &= is_p << 1; + is_p = 0 - (is_p >> 63); + + is_zero |= is_p; + + result = is_zero; + result |= ((limb) is_zero) << 64; + return result; +} + +static int smallfelem_is_zero_int(const void *small) +{ + return (int)(smallfelem_is_zero(small) & ((limb) 1)); +} + +/*- + * felem_inv calculates |out| = |in|^{-1} + * + * Based on Fermat's Little Theorem: + * a^p = a (mod p) + * a^{p-1} = 1 (mod p) + * a^{p-2} = a^{-1} (mod p) + */ +static void felem_inv(felem out, const felem in) +{ + felem ftmp, ftmp2; + /* each e_I will hold |in|^{2^I - 1} */ + felem e2, e4, e8, e16, e32, e64; + longfelem tmp; + unsigned i; + + felem_square(tmp, in); + felem_reduce(ftmp, tmp); /* 2^1 */ + felem_mul(tmp, in, ftmp); + felem_reduce(ftmp, tmp); /* 2^2 - 2^0 */ + felem_assign(e2, ftmp); + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^3 - 2^1 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^4 - 2^2 */ + felem_mul(tmp, ftmp, e2); + felem_reduce(ftmp, tmp); /* 2^4 - 2^0 */ + felem_assign(e4, ftmp); + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^5 - 2^1 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^6 - 2^2 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^7 - 2^3 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^8 - 2^4 */ + felem_mul(tmp, ftmp, e4); + felem_reduce(ftmp, tmp); /* 2^8 - 2^0 */ + felem_assign(e8, ftmp); + for (i = 0; i < 8; i++) { + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); + } /* 2^16 - 2^8 */ + felem_mul(tmp, ftmp, e8); + felem_reduce(ftmp, tmp); /* 2^16 - 2^0 */ + felem_assign(e16, ftmp); + for (i = 0; i < 16; i++) { + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); + } /* 2^32 - 2^16 */ + felem_mul(tmp, ftmp, e16); + felem_reduce(ftmp, tmp); /* 2^32 - 2^0 */ + felem_assign(e32, ftmp); + for (i = 0; i < 32; i++) { + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); + } /* 2^64 - 2^32 */ + felem_assign(e64, ftmp); + felem_mul(tmp, ftmp, in); + felem_reduce(ftmp, tmp); /* 2^64 - 2^32 + 2^0 */ + for (i = 0; i < 192; i++) { + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); + } /* 2^256 - 2^224 + 2^192 */ + + felem_mul(tmp, e64, e32); + felem_reduce(ftmp2, tmp); /* 2^64 - 2^0 */ + for (i = 0; i < 16; i++) { + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); + } /* 2^80 - 2^16 */ + felem_mul(tmp, ftmp2, e16); + felem_reduce(ftmp2, tmp); /* 2^80 - 2^0 */ + for (i = 0; i < 8; i++) { + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); + } /* 2^88 - 2^8 */ + felem_mul(tmp, ftmp2, e8); + felem_reduce(ftmp2, tmp); /* 2^88 - 2^0 */ + for (i = 0; i < 4; i++) { + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); + } /* 2^92 - 2^4 */ + felem_mul(tmp, ftmp2, e4); + felem_reduce(ftmp2, tmp); /* 2^92 - 2^0 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); /* 2^93 - 2^1 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); /* 2^94 - 2^2 */ + felem_mul(tmp, ftmp2, e2); + felem_reduce(ftmp2, tmp); /* 2^94 - 2^0 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); /* 2^95 - 2^1 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); /* 2^96 - 2^2 */ + felem_mul(tmp, ftmp2, in); + felem_reduce(ftmp2, tmp); /* 2^96 - 3 */ + + felem_mul(tmp, ftmp2, ftmp); + felem_reduce(out, tmp); /* 2^256 - 2^224 + 2^192 + 2^96 - 3 */ +} + +static void smallfelem_inv_contract(smallfelem out, const smallfelem in) +{ + felem tmp; + + smallfelem_expand(tmp, in); + felem_inv(tmp, tmp); + felem_contract(out, tmp); +} + +/*- + * Group operations + * ---------------- + * + * Building on top of the field operations we have the operations on the + * elliptic curve group itself. Points on the curve are represented in Jacobian + * coordinates + */ + +/*- + * point_double calculates 2*(x_in, y_in, z_in) + * + * The method is taken from: + * http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b + * + * Outputs can equal corresponding inputs, i.e., x_out == x_in is allowed. + * while x_out == y_in is not (maybe this works, but it's not tested). + */ +static void +point_double(felem x_out, felem y_out, felem z_out, + const felem x_in, const felem y_in, const felem z_in) +{ + longfelem tmp, tmp2; + felem delta, gamma, beta, alpha, ftmp, ftmp2; + smallfelem small1, small2; + + felem_assign(ftmp, x_in); + /* ftmp[i] < 2^106 */ + felem_assign(ftmp2, x_in); + /* ftmp2[i] < 2^106 */ + + /* delta = z^2 */ + felem_square(tmp, z_in); + felem_reduce(delta, tmp); + /* delta[i] < 2^101 */ + + /* gamma = y^2 */ + felem_square(tmp, y_in); + felem_reduce(gamma, tmp); + /* gamma[i] < 2^101 */ + felem_shrink(small1, gamma); + + /* beta = x*gamma */ + felem_small_mul(tmp, small1, x_in); + felem_reduce(beta, tmp); + /* beta[i] < 2^101 */ + + /* alpha = 3*(x-delta)*(x+delta) */ + felem_diff(ftmp, delta); + /* ftmp[i] < 2^105 + 2^106 < 2^107 */ + felem_sum(ftmp2, delta); + /* ftmp2[i] < 2^105 + 2^106 < 2^107 */ + felem_scalar(ftmp2, 3); + /* ftmp2[i] < 3 * 2^107 < 2^109 */ + felem_mul(tmp, ftmp, ftmp2); + felem_reduce(alpha, tmp); + /* alpha[i] < 2^101 */ + felem_shrink(small2, alpha); + + /* x' = alpha^2 - 8*beta */ + smallfelem_square(tmp, small2); + felem_reduce(x_out, tmp); + felem_assign(ftmp, beta); + felem_scalar(ftmp, 8); + /* ftmp[i] < 8 * 2^101 = 2^104 */ + felem_diff(x_out, ftmp); + /* x_out[i] < 2^105 + 2^101 < 2^106 */ + + /* z' = (y + z)^2 - gamma - delta */ + felem_sum(delta, gamma); + /* delta[i] < 2^101 + 2^101 = 2^102 */ + felem_assign(ftmp, y_in); + felem_sum(ftmp, z_in); + /* ftmp[i] < 2^106 + 2^106 = 2^107 */ + felem_square(tmp, ftmp); + felem_reduce(z_out, tmp); + felem_diff(z_out, delta); + /* z_out[i] < 2^105 + 2^101 < 2^106 */ + + /* y' = alpha*(4*beta - x') - 8*gamma^2 */ + felem_scalar(beta, 4); + /* beta[i] < 4 * 2^101 = 2^103 */ + felem_diff_zero107(beta, x_out); + /* beta[i] < 2^107 + 2^103 < 2^108 */ + felem_small_mul(tmp, small2, beta); + /* tmp[i] < 7 * 2^64 < 2^67 */ + smallfelem_square(tmp2, small1); + /* tmp2[i] < 7 * 2^64 */ + longfelem_scalar(tmp2, 8); + /* tmp2[i] < 8 * 7 * 2^64 = 7 * 2^67 */ + longfelem_diff(tmp, tmp2); + /* tmp[i] < 2^67 + 2^70 + 2^40 < 2^71 */ + felem_reduce_zero105(y_out, tmp); + /* y_out[i] < 2^106 */ +} + +/* + * point_double_small is the same as point_double, except that it operates on + * smallfelems + */ +static void +point_double_small(smallfelem x_out, smallfelem y_out, smallfelem z_out, + const smallfelem x_in, const smallfelem y_in, + const smallfelem z_in) +{ + felem felem_x_out, felem_y_out, felem_z_out; + felem felem_x_in, felem_y_in, felem_z_in; + + smallfelem_expand(felem_x_in, x_in); + smallfelem_expand(felem_y_in, y_in); + smallfelem_expand(felem_z_in, z_in); + point_double(felem_x_out, felem_y_out, felem_z_out, + felem_x_in, felem_y_in, felem_z_in); + felem_shrink(x_out, felem_x_out); + felem_shrink(y_out, felem_y_out); + felem_shrink(z_out, felem_z_out); +} + +/* copy_conditional copies in to out iff mask is all ones. */ +static void copy_conditional(felem out, const felem in, limb mask) +{ + unsigned i; + for (i = 0; i < NLIMBS; ++i) { + const limb tmp = mask & (in[i] ^ out[i]); + out[i] ^= tmp; + } +} + +/* copy_small_conditional copies in to out iff mask is all ones. */ +static void copy_small_conditional(felem out, const smallfelem in, limb mask) +{ + unsigned i; + const u64 mask64 = mask; + for (i = 0; i < NLIMBS; ++i) { + out[i] = ((limb) (in[i] & mask64)) | (out[i] & ~mask); + } +} + +/*- + * point_add calculates (x1, y1, z1) + (x2, y2, z2) + * + * The method is taken from: + * http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl, + * adapted for mixed addition (z2 = 1, or z2 = 0 for the point at infinity). + * + * This function includes a branch for checking whether the two input points + * are equal, (while not equal to the point at infinity). This case never + * happens during single point multiplication, so there is no timing leak for + * ECDH or ECDSA signing. + */ +static void point_add(felem x3, felem y3, felem z3, + const felem x1, const felem y1, const felem z1, + const int mixed, const smallfelem x2, + const smallfelem y2, const smallfelem z2) +{ + felem ftmp, ftmp2, ftmp3, ftmp4, ftmp5, ftmp6, x_out, y_out, z_out; + longfelem tmp, tmp2; + smallfelem small1, small2, small3, small4, small5; + limb x_equal, y_equal, z1_is_zero, z2_is_zero; + + felem_shrink(small3, z1); + + z1_is_zero = smallfelem_is_zero(small3); + z2_is_zero = smallfelem_is_zero(z2); + + /* ftmp = z1z1 = z1**2 */ + smallfelem_square(tmp, small3); + felem_reduce(ftmp, tmp); + /* ftmp[i] < 2^101 */ + felem_shrink(small1, ftmp); + + if (!mixed) { + /* ftmp2 = z2z2 = z2**2 */ + smallfelem_square(tmp, z2); + felem_reduce(ftmp2, tmp); + /* ftmp2[i] < 2^101 */ + felem_shrink(small2, ftmp2); + + felem_shrink(small5, x1); + + /* u1 = ftmp3 = x1*z2z2 */ + smallfelem_mul(tmp, small5, small2); + felem_reduce(ftmp3, tmp); + /* ftmp3[i] < 2^101 */ + + /* ftmp5 = z1 + z2 */ + felem_assign(ftmp5, z1); + felem_small_sum(ftmp5, z2); + /* ftmp5[i] < 2^107 */ + + /* ftmp5 = (z1 + z2)**2 - (z1z1 + z2z2) = 2z1z2 */ + felem_square(tmp, ftmp5); + felem_reduce(ftmp5, tmp); + /* ftmp2 = z2z2 + z1z1 */ + felem_sum(ftmp2, ftmp); + /* ftmp2[i] < 2^101 + 2^101 = 2^102 */ + felem_diff(ftmp5, ftmp2); + /* ftmp5[i] < 2^105 + 2^101 < 2^106 */ + + /* ftmp2 = z2 * z2z2 */ + smallfelem_mul(tmp, small2, z2); + felem_reduce(ftmp2, tmp); + + /* s1 = ftmp2 = y1 * z2**3 */ + felem_mul(tmp, y1, ftmp2); + felem_reduce(ftmp6, tmp); + /* ftmp6[i] < 2^101 */ + } else { + /* + * We'll assume z2 = 1 (special case z2 = 0 is handled later) + */ + + /* u1 = ftmp3 = x1*z2z2 */ + felem_assign(ftmp3, x1); + /* ftmp3[i] < 2^106 */ + + /* ftmp5 = 2z1z2 */ + felem_assign(ftmp5, z1); + felem_scalar(ftmp5, 2); + /* ftmp5[i] < 2*2^106 = 2^107 */ + + /* s1 = ftmp2 = y1 * z2**3 */ + felem_assign(ftmp6, y1); + /* ftmp6[i] < 2^106 */ + } + + /* u2 = x2*z1z1 */ + smallfelem_mul(tmp, x2, small1); + felem_reduce(ftmp4, tmp); + + /* h = ftmp4 = u2 - u1 */ + felem_diff_zero107(ftmp4, ftmp3); + /* ftmp4[i] < 2^107 + 2^101 < 2^108 */ + felem_shrink(small4, ftmp4); + + x_equal = smallfelem_is_zero(small4); + + /* z_out = ftmp5 * h */ + felem_small_mul(tmp, small4, ftmp5); + felem_reduce(z_out, tmp); + /* z_out[i] < 2^101 */ + + /* ftmp = z1 * z1z1 */ + smallfelem_mul(tmp, small1, small3); + felem_reduce(ftmp, tmp); + + /* s2 = tmp = y2 * z1**3 */ + felem_small_mul(tmp, y2, ftmp); + felem_reduce(ftmp5, tmp); + + /* r = ftmp5 = (s2 - s1)*2 */ + felem_diff_zero107(ftmp5, ftmp6); + /* ftmp5[i] < 2^107 + 2^107 = 2^108 */ + felem_scalar(ftmp5, 2); + /* ftmp5[i] < 2^109 */ + felem_shrink(small1, ftmp5); + y_equal = smallfelem_is_zero(small1); + + if (x_equal && y_equal && !z1_is_zero && !z2_is_zero) { + point_double(x3, y3, z3, x1, y1, z1); + return; + } + + /* I = ftmp = (2h)**2 */ + felem_assign(ftmp, ftmp4); + felem_scalar(ftmp, 2); + /* ftmp[i] < 2*2^108 = 2^109 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); + + /* J = ftmp2 = h * I */ + felem_mul(tmp, ftmp4, ftmp); + felem_reduce(ftmp2, tmp); + + /* V = ftmp4 = U1 * I */ + felem_mul(tmp, ftmp3, ftmp); + felem_reduce(ftmp4, tmp); + + /* x_out = r**2 - J - 2V */ + smallfelem_square(tmp, small1); + felem_reduce(x_out, tmp); + felem_assign(ftmp3, ftmp4); + felem_scalar(ftmp4, 2); + felem_sum(ftmp4, ftmp2); + /* ftmp4[i] < 2*2^101 + 2^101 < 2^103 */ + felem_diff(x_out, ftmp4); + /* x_out[i] < 2^105 + 2^101 */ + + /* y_out = r(V-x_out) - 2 * s1 * J */ + felem_diff_zero107(ftmp3, x_out); + /* ftmp3[i] < 2^107 + 2^101 < 2^108 */ + felem_small_mul(tmp, small1, ftmp3); + felem_mul(tmp2, ftmp6, ftmp2); + longfelem_scalar(tmp2, 2); + /* tmp2[i] < 2*2^67 = 2^68 */ + longfelem_diff(tmp, tmp2); + /* tmp[i] < 2^67 + 2^70 + 2^40 < 2^71 */ + felem_reduce_zero105(y_out, tmp); + /* y_out[i] < 2^106 */ + + copy_small_conditional(x_out, x2, z1_is_zero); + copy_conditional(x_out, x1, z2_is_zero); + copy_small_conditional(y_out, y2, z1_is_zero); + copy_conditional(y_out, y1, z2_is_zero); + copy_small_conditional(z_out, z2, z1_is_zero); + copy_conditional(z_out, z1, z2_is_zero); + felem_assign(x3, x_out); + felem_assign(y3, y_out); + felem_assign(z3, z_out); +} + +/* + * point_add_small is the same as point_add, except that it operates on + * smallfelems + */ +static void point_add_small(smallfelem x3, smallfelem y3, smallfelem z3, + smallfelem x1, smallfelem y1, smallfelem z1, + smallfelem x2, smallfelem y2, smallfelem z2) +{ + felem felem_x3, felem_y3, felem_z3; + felem felem_x1, felem_y1, felem_z1; + smallfelem_expand(felem_x1, x1); + smallfelem_expand(felem_y1, y1); + smallfelem_expand(felem_z1, z1); + point_add(felem_x3, felem_y3, felem_z3, felem_x1, felem_y1, felem_z1, 0, + x2, y2, z2); + felem_shrink(x3, felem_x3); + felem_shrink(y3, felem_y3); + felem_shrink(z3, felem_z3); +} + +/*- + * Base point pre computation + * -------------------------- + * + * Two different sorts of precomputed tables are used in the following code. + * Each contain various points on the curve, where each point is three field + * elements (x, y, z). + * + * For the base point table, z is usually 1 (0 for the point at infinity). + * This table has 2 * 16 elements, starting with the following: + * index | bits | point + * ------+---------+------------------------------ + * 0 | 0 0 0 0 | 0G + * 1 | 0 0 0 1 | 1G + * 2 | 0 0 1 0 | 2^64G + * 3 | 0 0 1 1 | (2^64 + 1)G + * 4 | 0 1 0 0 | 2^128G + * 5 | 0 1 0 1 | (2^128 + 1)G + * 6 | 0 1 1 0 | (2^128 + 2^64)G + * 7 | 0 1 1 1 | (2^128 + 2^64 + 1)G + * 8 | 1 0 0 0 | 2^192G + * 9 | 1 0 0 1 | (2^192 + 1)G + * 10 | 1 0 1 0 | (2^192 + 2^64)G + * 11 | 1 0 1 1 | (2^192 + 2^64 + 1)G + * 12 | 1 1 0 0 | (2^192 + 2^128)G + * 13 | 1 1 0 1 | (2^192 + 2^128 + 1)G + * 14 | 1 1 1 0 | (2^192 + 2^128 + 2^64)G + * 15 | 1 1 1 1 | (2^192 + 2^128 + 2^64 + 1)G + * followed by a copy of this with each element multiplied by 2^32. + * + * The reason for this is so that we can clock bits into four different + * locations when doing simple scalar multiplies against the base point, + * and then another four locations using the second 16 elements. + * + * Tables for other points have table[i] = iG for i in 0 .. 16. */ + +/* gmul is the table of precomputed base points */ +static const smallfelem gmul[2][16][3] = { + {{{0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}}, + {{0xf4a13945d898c296, 0x77037d812deb33a0, 0xf8bce6e563a440f2, + 0x6b17d1f2e12c4247}, + {0xcbb6406837bf51f5, 0x2bce33576b315ece, 0x8ee7eb4a7c0f9e16, + 0x4fe342e2fe1a7f9b}, + {1, 0, 0, 0}}, + {{0x90e75cb48e14db63, 0x29493baaad651f7e, 0x8492592e326e25de, + 0x0fa822bc2811aaa5}, + {0xe41124545f462ee7, 0x34b1a65050fe82f5, 0x6f4ad4bcb3df188b, + 0xbff44ae8f5dba80d}, + {1, 0, 0, 0}}, + {{0x93391ce2097992af, 0xe96c98fd0d35f1fa, 0xb257c0de95e02789, + 0x300a4bbc89d6726f}, + {0xaa54a291c08127a0, 0x5bb1eeada9d806a5, 0x7f1ddb25ff1e3c6f, + 0x72aac7e0d09b4644}, + {1, 0, 0, 0}}, + {{0x57c84fc9d789bd85, 0xfc35ff7dc297eac3, 0xfb982fd588c6766e, + 0x447d739beedb5e67}, + {0x0c7e33c972e25b32, 0x3d349b95a7fae500, 0xe12e9d953a4aaff7, + 0x2d4825ab834131ee}, + {1, 0, 0, 0}}, + {{0x13949c932a1d367f, 0xef7fbd2b1a0a11b7, 0xddc6068bb91dfc60, + 0xef9519328a9c72ff}, + {0x196035a77376d8a8, 0x23183b0895ca1740, 0xc1ee9807022c219c, + 0x611e9fc37dbb2c9b}, + {1, 0, 0, 0}}, + {{0xcae2b1920b57f4bc, 0x2936df5ec6c9bc36, 0x7dea6482e11238bf, + 0x550663797b51f5d8}, + {0x44ffe216348a964c, 0x9fb3d576dbdefbe1, 0x0afa40018d9d50e5, + 0x157164848aecb851}, + {1, 0, 0, 0}}, + {{0xe48ecafffc5cde01, 0x7ccd84e70d715f26, 0xa2e8f483f43e4391, + 0xeb5d7745b21141ea}, + {0xcac917e2731a3479, 0x85f22cfe2844b645, 0x0990e6a158006cee, + 0xeafd72ebdbecc17b}, + {1, 0, 0, 0}}, + {{0x6cf20ffb313728be, 0x96439591a3c6b94a, 0x2736ff8344315fc5, + 0xa6d39677a7849276}, + {0xf2bab833c357f5f4, 0x824a920c2284059b, 0x66b8babd2d27ecdf, + 0x674f84749b0b8816}, + {1, 0, 0, 0}}, + {{0x2df48c04677c8a3e, 0x74e02f080203a56b, 0x31855f7db8c7fedb, + 0x4e769e7672c9ddad}, + {0xa4c36165b824bbb0, 0xfb9ae16f3b9122a5, 0x1ec0057206947281, + 0x42b99082de830663}, + {1, 0, 0, 0}}, + {{0x6ef95150dda868b9, 0xd1f89e799c0ce131, 0x7fdc1ca008a1c478, + 0x78878ef61c6ce04d}, + {0x9c62b9121fe0d976, 0x6ace570ebde08d4f, 0xde53142c12309def, + 0xb6cb3f5d7b72c321}, + {1, 0, 0, 0}}, + {{0x7f991ed2c31a3573, 0x5b82dd5bd54fb496, 0x595c5220812ffcae, + 0x0c88bc4d716b1287}, + {0x3a57bf635f48aca8, 0x7c8181f4df2564f3, 0x18d1b5b39c04e6aa, + 0xdd5ddea3f3901dc6}, + {1, 0, 0, 0}}, + {{0xe96a79fb3e72ad0c, 0x43a0a28c42ba792f, 0xefe0a423083e49f3, + 0x68f344af6b317466}, + {0xcdfe17db3fb24d4a, 0x668bfc2271f5c626, 0x604ed93c24d67ff3, + 0x31b9c405f8540a20}, + {1, 0, 0, 0}}, + {{0xd36b4789a2582e7f, 0x0d1a10144ec39c28, 0x663c62c3edbad7a0, + 0x4052bf4b6f461db9}, + {0x235a27c3188d25eb, 0xe724f33999bfcc5b, 0x862be6bd71d70cc8, + 0xfecf4d5190b0fc61}, + {1, 0, 0, 0}}, + {{0x74346c10a1d4cfac, 0xafdf5cc08526a7a4, 0x123202a8f62bff7a, + 0x1eddbae2c802e41a}, + {0x8fa0af2dd603f844, 0x36e06b7e4c701917, 0x0c45f45273db33a0, + 0x43104d86560ebcfc}, + {1, 0, 0, 0}}, + {{0x9615b5110d1d78e5, 0x66b0de3225c4744b, 0x0a4a46fb6aaf363a, + 0xb48e26b484f7a21c}, + {0x06ebb0f621a01b2d, 0xc004e4048b7b0f98, 0x64131bcdfed6f668, + 0xfac015404d4d3dab}, + {1, 0, 0, 0}}}, + {{{0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}}, + {{0x3a5a9e22185a5943, 0x1ab919365c65dfb6, 0x21656b32262c71da, + 0x7fe36b40af22af89}, + {0xd50d152c699ca101, 0x74b3d5867b8af212, 0x9f09f40407dca6f1, + 0xe697d45825b63624}, + {1, 0, 0, 0}}, + {{0xa84aa9397512218e, 0xe9a521b074ca0141, 0x57880b3a18a2e902, + 0x4a5b506612a677a6}, + {0x0beada7a4c4f3840, 0x626db15419e26d9d, 0xc42604fbe1627d40, + 0xeb13461ceac089f1}, + {1, 0, 0, 0}}, + {{0xf9faed0927a43281, 0x5e52c4144103ecbc, 0xc342967aa815c857, + 0x0781b8291c6a220a}, + {0x5a8343ceeac55f80, 0x88f80eeee54a05e3, 0x97b2a14f12916434, + 0x690cde8df0151593}, + {1, 0, 0, 0}}, + {{0xaee9c75df7f82f2a, 0x9e4c35874afdf43a, 0xf5622df437371326, + 0x8a535f566ec73617}, + {0xc5f9a0ac223094b7, 0xcde533864c8c7669, 0x37e02819085a92bf, + 0x0455c08468b08bd7}, + {1, 0, 0, 0}}, + {{0x0c0a6e2c9477b5d9, 0xf9a4bf62876dc444, 0x5050a949b6cdc279, + 0x06bada7ab77f8276}, + {0xc8b4aed1ea48dac9, 0xdebd8a4b7ea1070f, 0x427d49101366eb70, + 0x5b476dfd0e6cb18a}, + {1, 0, 0, 0}}, + {{0x7c5c3e44278c340a, 0x4d54606812d66f3b, 0x29a751b1ae23c5d8, + 0x3e29864e8a2ec908}, + {0x142d2a6626dbb850, 0xad1744c4765bd780, 0x1f150e68e322d1ed, + 0x239b90ea3dc31e7e}, + {1, 0, 0, 0}}, + {{0x78c416527a53322a, 0x305dde6709776f8e, 0xdbcab759f8862ed4, + 0x820f4dd949f72ff7}, + {0x6cc544a62b5debd4, 0x75be5d937b4e8cc4, 0x1b481b1b215c14d3, + 0x140406ec783a05ec}, + {1, 0, 0, 0}}, + {{0x6a703f10e895df07, 0xfd75f3fa01876bd8, 0xeb5b06e70ce08ffe, + 0x68f6b8542783dfee}, + {0x90c76f8a78712655, 0xcf5293d2f310bf7f, 0xfbc8044dfda45028, + 0xcbe1feba92e40ce6}, + {1, 0, 0, 0}}, + {{0xe998ceea4396e4c1, 0xfc82ef0b6acea274, 0x230f729f2250e927, + 0xd0b2f94d2f420109}, + {0x4305adddb38d4966, 0x10b838f8624c3b45, 0x7db2636658954e7a, + 0x971459828b0719e5}, + {1, 0, 0, 0}}, + {{0x4bd6b72623369fc9, 0x57f2929e53d0b876, 0xc2d5cba4f2340687, + 0x961610004a866aba}, + {0x49997bcd2e407a5e, 0x69ab197d92ddcb24, 0x2cf1f2438fe5131c, + 0x7acb9fadcee75e44}, + {1, 0, 0, 0}}, + {{0x254e839423d2d4c0, 0xf57f0c917aea685b, 0xa60d880f6f75aaea, + 0x24eb9acca333bf5b}, + {0xe3de4ccb1cda5dea, 0xfeef9341c51a6b4f, 0x743125f88bac4c4d, + 0x69f891c5acd079cc}, + {1, 0, 0, 0}}, + {{0xeee44b35702476b5, 0x7ed031a0e45c2258, 0xb422d1e7bd6f8514, + 0xe51f547c5972a107}, + {0xa25bcd6fc9cf343d, 0x8ca922ee097c184e, 0xa62f98b3a9fe9a06, + 0x1c309a2b25bb1387}, + {1, 0, 0, 0}}, + {{0x9295dbeb1967c459, 0xb00148833472c98e, 0xc504977708011828, + 0x20b87b8aa2c4e503}, + {0x3063175de057c277, 0x1bd539338fe582dd, 0x0d11adef5f69a044, + 0xf5c6fa49919776be}, + {1, 0, 0, 0}}, + {{0x8c944e760fd59e11, 0x3876cba1102fad5f, 0xa454c3fad83faa56, + 0x1ed7d1b9332010b9}, + {0xa1011a270024b889, 0x05e4d0dcac0cd344, 0x52b520f0eb6a2a24, + 0x3a2b03f03217257a}, + {1, 0, 0, 0}}, + {{0xf20fc2afdf1d043d, 0xf330240db58d5a62, 0xfc7d229ca0058c3b, + 0x15fee545c78dd9f6}, + {0x501e82885bc98cda, 0x41ef80e5d046ac04, 0x557d9f49461210fb, + 0x4ab5b6b2b8753f81}, + {1, 0, 0, 0}}} +}; + +/* + * select_point selects the |idx|th point from a precomputation table and + * copies it to out. + */ +static void select_point(const u64 idx, unsigned int size, + const smallfelem pre_comp[16][3], smallfelem out[3]) +{ + unsigned i, j; + u64 *outlimbs = &out[0][0]; + + memset(out, 0, sizeof(*out) * 3); + + for (i = 0; i < size; i++) { + const u64 *inlimbs = (u64 *)&pre_comp[i][0][0]; + u64 mask = i ^ idx; + mask |= mask >> 4; + mask |= mask >> 2; + mask |= mask >> 1; + mask &= 1; + mask--; + for (j = 0; j < NLIMBS * 3; j++) + outlimbs[j] |= inlimbs[j] & mask; + } +} + +/* get_bit returns the |i|th bit in |in| */ +static char get_bit(const felem_bytearray in, int i) +{ + if ((i < 0) || (i >= 256)) + return 0; + return (in[i >> 3] >> (i & 7)) & 1; +} + +/* + * Interleaved point multiplication using precomputed point multiples: The + * small point multiples 0*P, 1*P, ..., 17*P are in pre_comp[], the scalars + * in scalars[]. If g_scalar is non-NULL, we also add this multiple of the + * generator, using certain (large) precomputed multiples in g_pre_comp. + * Output point (X, Y, Z) is stored in x_out, y_out, z_out + */ +static void batch_mul(felem x_out, felem y_out, felem z_out, + const felem_bytearray scalars[], + const unsigned num_points, const u8 *g_scalar, + const int mixed, const smallfelem pre_comp[][17][3], + const smallfelem g_pre_comp[2][16][3]) +{ + int i, skip; + unsigned num, gen_mul = (g_scalar != NULL); + felem nq[3], ftmp; + smallfelem tmp[3]; + u64 bits; + u8 sign, digit; + + /* set nq to the point at infinity */ + memset(nq, 0, sizeof(nq)); + + /* + * Loop over all scalars msb-to-lsb, interleaving additions of multiples + * of the generator (two in each of the last 32 rounds) and additions of + * other points multiples (every 5th round). + */ + skip = 1; /* save two point operations in the first + * round */ + for (i = (num_points ? 255 : 31); i >= 0; --i) { + /* double */ + if (!skip) + point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]); + + /* add multiples of the generator */ + if (gen_mul && (i <= 31)) { + /* first, look 32 bits upwards */ + bits = get_bit(g_scalar, i + 224) << 3; + bits |= get_bit(g_scalar, i + 160) << 2; + bits |= get_bit(g_scalar, i + 96) << 1; + bits |= get_bit(g_scalar, i + 32); + /* select the point to add, in constant time */ + select_point(bits, 16, g_pre_comp[1], tmp); + + if (!skip) { + /* Arg 1 below is for "mixed" */ + point_add(nq[0], nq[1], nq[2], + nq[0], nq[1], nq[2], 1, tmp[0], tmp[1], tmp[2]); + } else { + smallfelem_expand(nq[0], tmp[0]); + smallfelem_expand(nq[1], tmp[1]); + smallfelem_expand(nq[2], tmp[2]); + skip = 0; + } + + /* second, look at the current position */ + bits = get_bit(g_scalar, i + 192) << 3; + bits |= get_bit(g_scalar, i + 128) << 2; + bits |= get_bit(g_scalar, i + 64) << 1; + bits |= get_bit(g_scalar, i); + /* select the point to add, in constant time */ + select_point(bits, 16, g_pre_comp[0], tmp); + /* Arg 1 below is for "mixed" */ + point_add(nq[0], nq[1], nq[2], + nq[0], nq[1], nq[2], 1, tmp[0], tmp[1], tmp[2]); + } + + /* do other additions every 5 doublings */ + if (num_points && (i % 5 == 0)) { + /* loop over all scalars */ + for (num = 0; num < num_points; ++num) { + bits = get_bit(scalars[num], i + 4) << 5; + bits |= get_bit(scalars[num], i + 3) << 4; + bits |= get_bit(scalars[num], i + 2) << 3; + bits |= get_bit(scalars[num], i + 1) << 2; + bits |= get_bit(scalars[num], i) << 1; + bits |= get_bit(scalars[num], i - 1); + ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits); + + /* + * select the point to add or subtract, in constant time + */ + select_point(digit, 17, pre_comp[num], tmp); + smallfelem_neg(ftmp, tmp[1]); /* (X, -Y, Z) is the negative + * point */ + copy_small_conditional(ftmp, tmp[1], (((limb) sign) - 1)); + felem_contract(tmp[1], ftmp); + + if (!skip) { + point_add(nq[0], nq[1], nq[2], + nq[0], nq[1], nq[2], + mixed, tmp[0], tmp[1], tmp[2]); + } else { + smallfelem_expand(nq[0], tmp[0]); + smallfelem_expand(nq[1], tmp[1]); + smallfelem_expand(nq[2], tmp[2]); + skip = 0; + } + } + } + } + felem_assign(x_out, nq[0]); + felem_assign(y_out, nq[1]); + felem_assign(z_out, nq[2]); +} + +/* Precomputation for the group generator. */ +struct nistp256_pre_comp_st { + smallfelem g_pre_comp[2][16][3]; + CRYPTO_REF_COUNT references; + CRYPTO_RWLOCK *lock; +}; + +const EC_METHOD *EC_GFp_nistp256_method(void) +{ + static const EC_METHOD ret = { + EC_FLAGS_DEFAULT_OCT, + NID_X9_62_prime_field, + ec_GFp_nistp256_group_init, + ec_GFp_simple_group_finish, + ec_GFp_simple_group_clear_finish, + ec_GFp_nist_group_copy, + ec_GFp_nistp256_group_set_curve, + ec_GFp_simple_group_get_curve, + ec_GFp_simple_group_get_degree, + ec_group_simple_order_bits, + ec_GFp_simple_group_check_discriminant, + ec_GFp_simple_point_init, + ec_GFp_simple_point_finish, + ec_GFp_simple_point_clear_finish, + ec_GFp_simple_point_copy, + ec_GFp_simple_point_set_to_infinity, + ec_GFp_simple_set_Jprojective_coordinates_GFp, + ec_GFp_simple_get_Jprojective_coordinates_GFp, + ec_GFp_simple_point_set_affine_coordinates, + ec_GFp_nistp256_point_get_affine_coordinates, + 0 /* point_set_compressed_coordinates */ , + 0 /* point2oct */ , + 0 /* oct2point */ , + ec_GFp_simple_add, + ec_GFp_simple_dbl, + ec_GFp_simple_invert, + ec_GFp_simple_is_at_infinity, + ec_GFp_simple_is_on_curve, + ec_GFp_simple_cmp, + ec_GFp_simple_make_affine, + ec_GFp_simple_points_make_affine, + ec_GFp_nistp256_points_mul, + ec_GFp_nistp256_precompute_mult, + ec_GFp_nistp256_have_precompute_mult, + ec_GFp_nist_field_mul, + ec_GFp_nist_field_sqr, + 0 /* field_div */ , + ec_GFp_simple_field_inv, + 0 /* field_encode */ , + 0 /* field_decode */ , + 0, /* field_set_to_one */ + ec_key_simple_priv2oct, + ec_key_simple_oct2priv, + 0, /* set private */ + ec_key_simple_generate_key, + ec_key_simple_check_key, + ec_key_simple_generate_public_key, + 0, /* keycopy */ + 0, /* keyfinish */ + ecdh_simple_compute_key, + 0, /* field_inverse_mod_ord */ + 0, /* blind_coordinates */ + 0, /* ladder_pre */ + 0, /* ladder_step */ + 0 /* ladder_post */ + }; + + return &ret; +} + +/******************************************************************************/ +/* + * FUNCTIONS TO MANAGE PRECOMPUTATION + */ + +static NISTP256_PRE_COMP *nistp256_pre_comp_new(void) +{ + NISTP256_PRE_COMP *ret = OPENSSL_zalloc(sizeof(*ret)); + + if (ret == NULL) { + ECerr(EC_F_NISTP256_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); + return ret; + } + + ret->references = 1; + + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) { + ECerr(EC_F_NISTP256_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ret); + return NULL; + } + return ret; +} + +NISTP256_PRE_COMP *EC_nistp256_pre_comp_dup(NISTP256_PRE_COMP *p) +{ + int i; + if (p != NULL) + CRYPTO_UP_REF(&p->references, &i, p->lock); + return p; +} + +void EC_nistp256_pre_comp_free(NISTP256_PRE_COMP *pre) +{ + int i; + + if (pre == NULL) + return; + + CRYPTO_DOWN_REF(&pre->references, &i, pre->lock); + REF_PRINT_COUNT("EC_nistp256", x); + if (i > 0) + return; + REF_ASSERT_ISNT(i < 0); + + CRYPTO_THREAD_lock_free(pre->lock); + OPENSSL_free(pre); +} + +/******************************************************************************/ +/* + * OPENSSL EC_METHOD FUNCTIONS + */ + +int ec_GFp_nistp256_group_init(EC_GROUP *group) +{ + int ret; + ret = ec_GFp_simple_group_init(group); + group->a_is_minus3 = 1; + return ret; +} + +int ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *b, + BN_CTX *ctx) +{ + int ret = 0; + BN_CTX *new_ctx = NULL; + BIGNUM *curve_p, *curve_a, *curve_b; + + if (ctx == NULL) + if ((ctx = new_ctx = BN_CTX_new()) == NULL) + return 0; + BN_CTX_start(ctx); + curve_p = BN_CTX_get(ctx); + curve_a = BN_CTX_get(ctx); + curve_b = BN_CTX_get(ctx); + if (curve_b == NULL) + goto err; + BN_bin2bn(nistp256_curve_params[0], sizeof(felem_bytearray), curve_p); + BN_bin2bn(nistp256_curve_params[1], sizeof(felem_bytearray), curve_a); + BN_bin2bn(nistp256_curve_params[2], sizeof(felem_bytearray), curve_b); + if ((BN_cmp(curve_p, p)) || (BN_cmp(curve_a, a)) || (BN_cmp(curve_b, b))) { + ECerr(EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE, + EC_R_WRONG_CURVE_PARAMETERS); + goto err; + } + group->field_mod_func = BN_nist_mod_256; + ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); + err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +/* + * Takes the Jacobian coordinates (X, Y, Z) of a point and returns (X', Y') = + * (X/Z^2, Y/Z^3) + */ +int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx) +{ + felem z1, z2, x_in, y_in; + smallfelem x_out, y_out; + longfelem tmp; + + if (EC_POINT_is_at_infinity(group, point)) { + ECerr(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES, + EC_R_POINT_AT_INFINITY); + return 0; + } + if ((!BN_to_felem(x_in, point->X)) || (!BN_to_felem(y_in, point->Y)) || + (!BN_to_felem(z1, point->Z))) + return 0; + felem_inv(z2, z1); + felem_square(tmp, z2); + felem_reduce(z1, tmp); + felem_mul(tmp, x_in, z1); + felem_reduce(x_in, tmp); + felem_contract(x_out, x_in); + if (x != NULL) { + if (!smallfelem_to_BN(x, x_out)) { + ECerr(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES, + ERR_R_BN_LIB); + return 0; + } + } + felem_mul(tmp, z1, z2); + felem_reduce(z1, tmp); + felem_mul(tmp, y_in, z1); + felem_reduce(y_in, tmp); + felem_contract(y_out, y_in); + if (y != NULL) { + if (!smallfelem_to_BN(y, y_out)) { + ECerr(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES, + ERR_R_BN_LIB); + return 0; + } + } + return 1; +} + +/* points below is of size |num|, and tmp_smallfelems is of size |num+1| */ +static void make_points_affine(size_t num, smallfelem points[][3], + smallfelem tmp_smallfelems[]) +{ + /* + * Runs in constant time, unless an input is the point at infinity (which + * normally shouldn't happen). + */ + ec_GFp_nistp_points_make_affine_internal(num, + points, + sizeof(smallfelem), + tmp_smallfelems, + (void (*)(void *))smallfelem_one, + smallfelem_is_zero_int, + (void (*)(void *, const void *)) + smallfelem_assign, + (void (*)(void *, const void *)) + smallfelem_square_contract, + (void (*) + (void *, const void *, + const void *)) + smallfelem_mul_contract, + (void (*)(void *, const void *)) + smallfelem_inv_contract, + /* nothing to contract */ + (void (*)(void *, const void *)) + smallfelem_assign); +} + +/* + * Computes scalar*generator + \sum scalars[i]*points[i], ignoring NULL + * values Result is stored in r (r can equal one of the inputs). + */ +int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], + const BIGNUM *scalars[], BN_CTX *ctx) +{ + int ret = 0; + int j; + int mixed = 0; + BIGNUM *x, *y, *z, *tmp_scalar; + felem_bytearray g_secret; + felem_bytearray *secrets = NULL; + smallfelem (*pre_comp)[17][3] = NULL; + smallfelem *tmp_smallfelems = NULL; + felem_bytearray tmp; + unsigned i, num_bytes; + int have_pre_comp = 0; + size_t num_points = num; + smallfelem x_in, y_in, z_in; + felem x_out, y_out, z_out; + NISTP256_PRE_COMP *pre = NULL; + const smallfelem(*g_pre_comp)[16][3] = NULL; + EC_POINT *generator = NULL; + const EC_POINT *p = NULL; + const BIGNUM *p_scalar = NULL; + + BN_CTX_start(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + z = BN_CTX_get(ctx); + tmp_scalar = BN_CTX_get(ctx); + if (tmp_scalar == NULL) + goto err; + + if (scalar != NULL) { + pre = group->pre_comp.nistp256; + if (pre) + /* we have precomputation, try to use it */ + g_pre_comp = (const smallfelem(*)[16][3])pre->g_pre_comp; + else + /* try to use the standard precomputation */ + g_pre_comp = &gmul[0]; + generator = EC_POINT_new(group); + if (generator == NULL) + goto err; + /* get the generator from precomputation */ + if (!smallfelem_to_BN(x, g_pre_comp[0][1][0]) || + !smallfelem_to_BN(y, g_pre_comp[0][1][1]) || + !smallfelem_to_BN(z, g_pre_comp[0][1][2])) { + ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB); + goto err; + } + if (!EC_POINT_set_Jprojective_coordinates_GFp(group, + generator, x, y, z, + ctx)) + goto err; + if (0 == EC_POINT_cmp(group, generator, group->generator, ctx)) + /* precomputation matches generator */ + have_pre_comp = 1; + else + /* + * we don't have valid precomputation: treat the generator as a + * random point + */ + num_points++; + } + if (num_points > 0) { + if (num_points >= 3) { + /* + * unless we precompute multiples for just one or two points, + * converting those into affine form is time well spent + */ + mixed = 1; + } + secrets = OPENSSL_malloc(sizeof(*secrets) * num_points); + pre_comp = OPENSSL_malloc(sizeof(*pre_comp) * num_points); + if (mixed) + tmp_smallfelems = + OPENSSL_malloc(sizeof(*tmp_smallfelems) * (num_points * 17 + 1)); + if ((secrets == NULL) || (pre_comp == NULL) + || (mixed && (tmp_smallfelems == NULL))) { + ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* + * we treat NULL scalars as 0, and NULL points as points at infinity, + * i.e., they contribute nothing to the linear combination + */ + memset(secrets, 0, sizeof(*secrets) * num_points); + memset(pre_comp, 0, sizeof(*pre_comp) * num_points); + for (i = 0; i < num_points; ++i) { + if (i == num) + /* + * we didn't have a valid precomputation, so we pick the + * generator + */ + { + p = EC_GROUP_get0_generator(group); + p_scalar = scalar; + } else + /* the i^th point */ + { + p = points[i]; + p_scalar = scalars[i]; + } + if ((p_scalar != NULL) && (p != NULL)) { + /* reduce scalar to 0 <= scalar < 2^256 */ + if ((BN_num_bits(p_scalar) > 256) + || (BN_is_negative(p_scalar))) { + /* + * this is an unusual input, and we don't guarantee + * constant-timeness + */ + if (!BN_nnmod(tmp_scalar, p_scalar, group->order, ctx)) { + ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB); + goto err; + } + num_bytes = BN_bn2bin(tmp_scalar, tmp); + } else + num_bytes = BN_bn2bin(p_scalar, tmp); + flip_endian(secrets[i], tmp, num_bytes); + /* precompute multiples */ + if ((!BN_to_felem(x_out, p->X)) || + (!BN_to_felem(y_out, p->Y)) || + (!BN_to_felem(z_out, p->Z))) + goto err; + felem_shrink(pre_comp[i][1][0], x_out); + felem_shrink(pre_comp[i][1][1], y_out); + felem_shrink(pre_comp[i][1][2], z_out); + for (j = 2; j <= 16; ++j) { + if (j & 1) { + point_add_small(pre_comp[i][j][0], pre_comp[i][j][1], + pre_comp[i][j][2], pre_comp[i][1][0], + pre_comp[i][1][1], pre_comp[i][1][2], + pre_comp[i][j - 1][0], + pre_comp[i][j - 1][1], + pre_comp[i][j - 1][2]); + } else { + point_double_small(pre_comp[i][j][0], + pre_comp[i][j][1], + pre_comp[i][j][2], + pre_comp[i][j / 2][0], + pre_comp[i][j / 2][1], + pre_comp[i][j / 2][2]); + } + } + } + } + if (mixed) + make_points_affine(num_points * 17, pre_comp[0], tmp_smallfelems); + } + + /* the scalar for the generator */ + if ((scalar != NULL) && (have_pre_comp)) { + memset(g_secret, 0, sizeof(g_secret)); + /* reduce scalar to 0 <= scalar < 2^256 */ + if ((BN_num_bits(scalar) > 256) || (BN_is_negative(scalar))) { + /* + * this is an unusual input, and we don't guarantee + * constant-timeness + */ + if (!BN_nnmod(tmp_scalar, scalar, group->order, ctx)) { + ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB); + goto err; + } + num_bytes = BN_bn2bin(tmp_scalar, tmp); + } else + num_bytes = BN_bn2bin(scalar, tmp); + flip_endian(g_secret, tmp, num_bytes); + /* do the multiplication with generator precomputation */ + batch_mul(x_out, y_out, z_out, + (const felem_bytearray(*))secrets, num_points, + g_secret, + mixed, (const smallfelem(*)[17][3])pre_comp, g_pre_comp); + } else + /* do the multiplication without generator precomputation */ + batch_mul(x_out, y_out, z_out, + (const felem_bytearray(*))secrets, num_points, + NULL, mixed, (const smallfelem(*)[17][3])pre_comp, NULL); + /* reduce the output to its unique minimal representation */ + felem_contract(x_in, x_out); + felem_contract(y_in, y_out); + felem_contract(z_in, z_out); + if ((!smallfelem_to_BN(x, x_in)) || (!smallfelem_to_BN(y, y_in)) || + (!smallfelem_to_BN(z, z_in))) { + ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB); + goto err; + } + ret = EC_POINT_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx); + + err: + BN_CTX_end(ctx); + EC_POINT_free(generator); + OPENSSL_free(secrets); + OPENSSL_free(pre_comp); + OPENSSL_free(tmp_smallfelems); + return ret; +} + +int ec_GFp_nistp256_precompute_mult(EC_GROUP *group, BN_CTX *ctx) +{ + int ret = 0; + NISTP256_PRE_COMP *pre = NULL; + int i, j; + BN_CTX *new_ctx = NULL; + BIGNUM *x, *y; + EC_POINT *generator = NULL; + smallfelem tmp_smallfelems[32]; + felem x_tmp, y_tmp, z_tmp; + + /* throw away old precomputation */ + EC_pre_comp_free(group); + if (ctx == NULL) + if ((ctx = new_ctx = BN_CTX_new()) == NULL) + return 0; + BN_CTX_start(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (y == NULL) + goto err; + /* get the generator */ + if (group->generator == NULL) + goto err; + generator = EC_POINT_new(group); + if (generator == NULL) + goto err; + BN_bin2bn(nistp256_curve_params[3], sizeof(felem_bytearray), x); + BN_bin2bn(nistp256_curve_params[4], sizeof(felem_bytearray), y); + if (!EC_POINT_set_affine_coordinates(group, generator, x, y, ctx)) + goto err; + if ((pre = nistp256_pre_comp_new()) == NULL) + goto err; + /* + * if the generator is the standard one, use built-in precomputation + */ + if (0 == EC_POINT_cmp(group, generator, group->generator, ctx)) { + memcpy(pre->g_pre_comp, gmul, sizeof(pre->g_pre_comp)); + goto done; + } + if ((!BN_to_felem(x_tmp, group->generator->X)) || + (!BN_to_felem(y_tmp, group->generator->Y)) || + (!BN_to_felem(z_tmp, group->generator->Z))) + goto err; + felem_shrink(pre->g_pre_comp[0][1][0], x_tmp); + felem_shrink(pre->g_pre_comp[0][1][1], y_tmp); + felem_shrink(pre->g_pre_comp[0][1][2], z_tmp); + /* + * compute 2^64*G, 2^128*G, 2^192*G for the first table, 2^32*G, 2^96*G, + * 2^160*G, 2^224*G for the second one + */ + for (i = 1; i <= 8; i <<= 1) { + point_double_small(pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], + pre->g_pre_comp[1][i][2], pre->g_pre_comp[0][i][0], + pre->g_pre_comp[0][i][1], + pre->g_pre_comp[0][i][2]); + for (j = 0; j < 31; ++j) { + point_double_small(pre->g_pre_comp[1][i][0], + pre->g_pre_comp[1][i][1], + pre->g_pre_comp[1][i][2], + pre->g_pre_comp[1][i][0], + pre->g_pre_comp[1][i][1], + pre->g_pre_comp[1][i][2]); + } + if (i == 8) + break; + point_double_small(pre->g_pre_comp[0][2 * i][0], + pre->g_pre_comp[0][2 * i][1], + pre->g_pre_comp[0][2 * i][2], + pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], + pre->g_pre_comp[1][i][2]); + for (j = 0; j < 31; ++j) { + point_double_small(pre->g_pre_comp[0][2 * i][0], + pre->g_pre_comp[0][2 * i][1], + pre->g_pre_comp[0][2 * i][2], + pre->g_pre_comp[0][2 * i][0], + pre->g_pre_comp[0][2 * i][1], + pre->g_pre_comp[0][2 * i][2]); + } + } + for (i = 0; i < 2; i++) { + /* g_pre_comp[i][0] is the point at infinity */ + memset(pre->g_pre_comp[i][0], 0, sizeof(pre->g_pre_comp[i][0])); + /* the remaining multiples */ + /* 2^64*G + 2^128*G resp. 2^96*G + 2^160*G */ + point_add_small(pre->g_pre_comp[i][6][0], pre->g_pre_comp[i][6][1], + pre->g_pre_comp[i][6][2], pre->g_pre_comp[i][4][0], + pre->g_pre_comp[i][4][1], pre->g_pre_comp[i][4][2], + pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1], + pre->g_pre_comp[i][2][2]); + /* 2^64*G + 2^192*G resp. 2^96*G + 2^224*G */ + point_add_small(pre->g_pre_comp[i][10][0], pre->g_pre_comp[i][10][1], + pre->g_pre_comp[i][10][2], pre->g_pre_comp[i][8][0], + pre->g_pre_comp[i][8][1], pre->g_pre_comp[i][8][2], + pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1], + pre->g_pre_comp[i][2][2]); + /* 2^128*G + 2^192*G resp. 2^160*G + 2^224*G */ + point_add_small(pre->g_pre_comp[i][12][0], pre->g_pre_comp[i][12][1], + pre->g_pre_comp[i][12][2], pre->g_pre_comp[i][8][0], + pre->g_pre_comp[i][8][1], pre->g_pre_comp[i][8][2], + pre->g_pre_comp[i][4][0], pre->g_pre_comp[i][4][1], + pre->g_pre_comp[i][4][2]); + /* + * 2^64*G + 2^128*G + 2^192*G resp. 2^96*G + 2^160*G + 2^224*G + */ + point_add_small(pre->g_pre_comp[i][14][0], pre->g_pre_comp[i][14][1], + pre->g_pre_comp[i][14][2], pre->g_pre_comp[i][12][0], + pre->g_pre_comp[i][12][1], pre->g_pre_comp[i][12][2], + pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1], + pre->g_pre_comp[i][2][2]); + for (j = 1; j < 8; ++j) { + /* odd multiples: add G resp. 2^32*G */ + point_add_small(pre->g_pre_comp[i][2 * j + 1][0], + pre->g_pre_comp[i][2 * j + 1][1], + pre->g_pre_comp[i][2 * j + 1][2], + pre->g_pre_comp[i][2 * j][0], + pre->g_pre_comp[i][2 * j][1], + pre->g_pre_comp[i][2 * j][2], + pre->g_pre_comp[i][1][0], + pre->g_pre_comp[i][1][1], + pre->g_pre_comp[i][1][2]); + } + } + make_points_affine(31, &(pre->g_pre_comp[0][1]), tmp_smallfelems); + + done: + SETPRECOMP(group, nistp256, pre); + pre = NULL; + ret = 1; + + err: + BN_CTX_end(ctx); + EC_POINT_free(generator); + BN_CTX_free(new_ctx); + EC_nistp256_pre_comp_free(pre); + return ret; +} + +int ec_GFp_nistp256_have_precompute_mult(const EC_GROUP *group) +{ + return HAVEPRECOMP(group, nistp256); +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_nistp521.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_nistp521.c new file mode 100644 index 000000000..2f47772a3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_nistp521.c @@ -0,0 +1,2159 @@ +/* + * Copyright 2011-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Copyright 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * A 64-bit implementation of the NIST P-521 elliptic curve point multiplication + * + * OpenSSL integration was taken from Emilia Kasper's work in ecp_nistp224.c. + * Otherwise based on Emilia's P224 work, which was inspired by my curve25519 + * work which got its smarts from Daniel J. Bernstein's work on the same. + */ + +#include +#ifdef OPENSSL_NO_EC_NISTP_64_GCC_128 +NON_EMPTY_TRANSLATION_UNIT +#else + +# include +# include +# include "ec_lcl.h" + +# if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__==16 + /* even with gcc, the typedef won't work for 32-bit platforms */ +typedef __uint128_t uint128_t; /* nonstandard; implemented by gcc on 64-bit + * platforms */ +# else +# error "Your compiler doesn't appear to support 128-bit integer types" +# endif + +typedef uint8_t u8; +typedef uint64_t u64; + +/* + * The underlying field. P521 operates over GF(2^521-1). We can serialise an + * element of this field into 66 bytes where the most significant byte + * contains only a single bit. We call this an felem_bytearray. + */ + +typedef u8 felem_bytearray[66]; + +/* + * These are the parameters of P521, taken from FIPS 186-3, section D.1.2.5. + * These values are big-endian. + */ +static const felem_bytearray nistp521_curve_params[5] = { + {0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* p */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff}, + {0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* a = -3 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfc}, + {0x00, 0x51, 0x95, 0x3e, 0xb9, 0x61, 0x8e, 0x1c, /* b */ + 0x9a, 0x1f, 0x92, 0x9a, 0x21, 0xa0, 0xb6, 0x85, + 0x40, 0xee, 0xa2, 0xda, 0x72, 0x5b, 0x99, 0xb3, + 0x15, 0xf3, 0xb8, 0xb4, 0x89, 0x91, 0x8e, 0xf1, + 0x09, 0xe1, 0x56, 0x19, 0x39, 0x51, 0xec, 0x7e, + 0x93, 0x7b, 0x16, 0x52, 0xc0, 0xbd, 0x3b, 0xb1, + 0xbf, 0x07, 0x35, 0x73, 0xdf, 0x88, 0x3d, 0x2c, + 0x34, 0xf1, 0xef, 0x45, 0x1f, 0xd4, 0x6b, 0x50, + 0x3f, 0x00}, + {0x00, 0xc6, 0x85, 0x8e, 0x06, 0xb7, 0x04, 0x04, /* x */ + 0xe9, 0xcd, 0x9e, 0x3e, 0xcb, 0x66, 0x23, 0x95, + 0xb4, 0x42, 0x9c, 0x64, 0x81, 0x39, 0x05, 0x3f, + 0xb5, 0x21, 0xf8, 0x28, 0xaf, 0x60, 0x6b, 0x4d, + 0x3d, 0xba, 0xa1, 0x4b, 0x5e, 0x77, 0xef, 0xe7, + 0x59, 0x28, 0xfe, 0x1d, 0xc1, 0x27, 0xa2, 0xff, + 0xa8, 0xde, 0x33, 0x48, 0xb3, 0xc1, 0x85, 0x6a, + 0x42, 0x9b, 0xf9, 0x7e, 0x7e, 0x31, 0xc2, 0xe5, + 0xbd, 0x66}, + {0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, /* y */ + 0xc0, 0x04, 0x5c, 0x8a, 0x5f, 0xb4, 0x2c, 0x7d, + 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b, + 0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, + 0x66, 0x2c, 0x97, 0xee, 0x72, 0x99, 0x5e, 0xf4, + 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad, + 0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, + 0xc2, 0x40, 0x88, 0xbe, 0x94, 0x76, 0x9f, 0xd1, + 0x66, 0x50} +}; + +/*- + * The representation of field elements. + * ------------------------------------ + * + * We represent field elements with nine values. These values are either 64 or + * 128 bits and the field element represented is: + * v[0]*2^0 + v[1]*2^58 + v[2]*2^116 + ... + v[8]*2^464 (mod p) + * Each of the nine values is called a 'limb'. Since the limbs are spaced only + * 58 bits apart, but are greater than 58 bits in length, the most significant + * bits of each limb overlap with the least significant bits of the next. + * + * A field element with 64-bit limbs is an 'felem'. One with 128-bit limbs is a + * 'largefelem' */ + +# define NLIMBS 9 + +typedef uint64_t limb; +typedef limb felem[NLIMBS]; +typedef uint128_t largefelem[NLIMBS]; + +static const limb bottom57bits = 0x1ffffffffffffff; +static const limb bottom58bits = 0x3ffffffffffffff; + +/* + * bin66_to_felem takes a little-endian byte array and converts it into felem + * form. This assumes that the CPU is little-endian. + */ +static void bin66_to_felem(felem out, const u8 in[66]) +{ + out[0] = (*((limb *) & in[0])) & bottom58bits; + out[1] = (*((limb *) & in[7]) >> 2) & bottom58bits; + out[2] = (*((limb *) & in[14]) >> 4) & bottom58bits; + out[3] = (*((limb *) & in[21]) >> 6) & bottom58bits; + out[4] = (*((limb *) & in[29])) & bottom58bits; + out[5] = (*((limb *) & in[36]) >> 2) & bottom58bits; + out[6] = (*((limb *) & in[43]) >> 4) & bottom58bits; + out[7] = (*((limb *) & in[50]) >> 6) & bottom58bits; + out[8] = (*((limb *) & in[58])) & bottom57bits; +} + +/* + * felem_to_bin66 takes an felem and serialises into a little endian, 66 byte + * array. This assumes that the CPU is little-endian. + */ +static void felem_to_bin66(u8 out[66], const felem in) +{ + memset(out, 0, 66); + (*((limb *) & out[0])) = in[0]; + (*((limb *) & out[7])) |= in[1] << 2; + (*((limb *) & out[14])) |= in[2] << 4; + (*((limb *) & out[21])) |= in[3] << 6; + (*((limb *) & out[29])) = in[4]; + (*((limb *) & out[36])) |= in[5] << 2; + (*((limb *) & out[43])) |= in[6] << 4; + (*((limb *) & out[50])) |= in[7] << 6; + (*((limb *) & out[58])) = in[8]; +} + +/* To preserve endianness when using BN_bn2bin and BN_bin2bn */ +static void flip_endian(u8 *out, const u8 *in, unsigned len) +{ + unsigned i; + for (i = 0; i < len; ++i) + out[i] = in[len - 1 - i]; +} + +/* BN_to_felem converts an OpenSSL BIGNUM into an felem */ +static int BN_to_felem(felem out, const BIGNUM *bn) +{ + felem_bytearray b_in; + felem_bytearray b_out; + unsigned num_bytes; + + /* BN_bn2bin eats leading zeroes */ + memset(b_out, 0, sizeof(b_out)); + num_bytes = BN_num_bytes(bn); + if (num_bytes > sizeof(b_out)) { + ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE); + return 0; + } + if (BN_is_negative(bn)) { + ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE); + return 0; + } + num_bytes = BN_bn2bin(bn, b_in); + flip_endian(b_out, b_in, num_bytes); + bin66_to_felem(out, b_out); + return 1; +} + +/* felem_to_BN converts an felem into an OpenSSL BIGNUM */ +static BIGNUM *felem_to_BN(BIGNUM *out, const felem in) +{ + felem_bytearray b_in, b_out; + felem_to_bin66(b_in, in); + flip_endian(b_out, b_in, sizeof(b_out)); + return BN_bin2bn(b_out, sizeof(b_out), out); +} + +/*- + * Field operations + * ---------------- + */ + +static void felem_one(felem out) +{ + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 0; + out[4] = 0; + out[5] = 0; + out[6] = 0; + out[7] = 0; + out[8] = 0; +} + +static void felem_assign(felem out, const felem in) +{ + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; + out[4] = in[4]; + out[5] = in[5]; + out[6] = in[6]; + out[7] = in[7]; + out[8] = in[8]; +} + +/* felem_sum64 sets out = out + in. */ +static void felem_sum64(felem out, const felem in) +{ + out[0] += in[0]; + out[1] += in[1]; + out[2] += in[2]; + out[3] += in[3]; + out[4] += in[4]; + out[5] += in[5]; + out[6] += in[6]; + out[7] += in[7]; + out[8] += in[8]; +} + +/* felem_scalar sets out = in * scalar */ +static void felem_scalar(felem out, const felem in, limb scalar) +{ + out[0] = in[0] * scalar; + out[1] = in[1] * scalar; + out[2] = in[2] * scalar; + out[3] = in[3] * scalar; + out[4] = in[4] * scalar; + out[5] = in[5] * scalar; + out[6] = in[6] * scalar; + out[7] = in[7] * scalar; + out[8] = in[8] * scalar; +} + +/* felem_scalar64 sets out = out * scalar */ +static void felem_scalar64(felem out, limb scalar) +{ + out[0] *= scalar; + out[1] *= scalar; + out[2] *= scalar; + out[3] *= scalar; + out[4] *= scalar; + out[5] *= scalar; + out[6] *= scalar; + out[7] *= scalar; + out[8] *= scalar; +} + +/* felem_scalar128 sets out = out * scalar */ +static void felem_scalar128(largefelem out, limb scalar) +{ + out[0] *= scalar; + out[1] *= scalar; + out[2] *= scalar; + out[3] *= scalar; + out[4] *= scalar; + out[5] *= scalar; + out[6] *= scalar; + out[7] *= scalar; + out[8] *= scalar; +} + +/*- + * felem_neg sets |out| to |-in| + * On entry: + * in[i] < 2^59 + 2^14 + * On exit: + * out[i] < 2^62 + */ +static void felem_neg(felem out, const felem in) +{ + /* In order to prevent underflow, we subtract from 0 mod p. */ + static const limb two62m3 = (((limb) 1) << 62) - (((limb) 1) << 5); + static const limb two62m2 = (((limb) 1) << 62) - (((limb) 1) << 4); + + out[0] = two62m3 - in[0]; + out[1] = two62m2 - in[1]; + out[2] = two62m2 - in[2]; + out[3] = two62m2 - in[3]; + out[4] = two62m2 - in[4]; + out[5] = two62m2 - in[5]; + out[6] = two62m2 - in[6]; + out[7] = two62m2 - in[7]; + out[8] = two62m2 - in[8]; +} + +/*- + * felem_diff64 subtracts |in| from |out| + * On entry: + * in[i] < 2^59 + 2^14 + * On exit: + * out[i] < out[i] + 2^62 + */ +static void felem_diff64(felem out, const felem in) +{ + /* + * In order to prevent underflow, we add 0 mod p before subtracting. + */ + static const limb two62m3 = (((limb) 1) << 62) - (((limb) 1) << 5); + static const limb two62m2 = (((limb) 1) << 62) - (((limb) 1) << 4); + + out[0] += two62m3 - in[0]; + out[1] += two62m2 - in[1]; + out[2] += two62m2 - in[2]; + out[3] += two62m2 - in[3]; + out[4] += two62m2 - in[4]; + out[5] += two62m2 - in[5]; + out[6] += two62m2 - in[6]; + out[7] += two62m2 - in[7]; + out[8] += two62m2 - in[8]; +} + +/*- + * felem_diff_128_64 subtracts |in| from |out| + * On entry: + * in[i] < 2^62 + 2^17 + * On exit: + * out[i] < out[i] + 2^63 + */ +static void felem_diff_128_64(largefelem out, const felem in) +{ + /* + * In order to prevent underflow, we add 0 mod p before subtracting. + */ + static const limb two63m6 = (((limb) 1) << 62) - (((limb) 1) << 5); + static const limb two63m5 = (((limb) 1) << 62) - (((limb) 1) << 4); + + out[0] += two63m6 - in[0]; + out[1] += two63m5 - in[1]; + out[2] += two63m5 - in[2]; + out[3] += two63m5 - in[3]; + out[4] += two63m5 - in[4]; + out[5] += two63m5 - in[5]; + out[6] += two63m5 - in[6]; + out[7] += two63m5 - in[7]; + out[8] += two63m5 - in[8]; +} + +/*- + * felem_diff_128_64 subtracts |in| from |out| + * On entry: + * in[i] < 2^126 + * On exit: + * out[i] < out[i] + 2^127 - 2^69 + */ +static void felem_diff128(largefelem out, const largefelem in) +{ + /* + * In order to prevent underflow, we add 0 mod p before subtracting. + */ + static const uint128_t two127m70 = + (((uint128_t) 1) << 127) - (((uint128_t) 1) << 70); + static const uint128_t two127m69 = + (((uint128_t) 1) << 127) - (((uint128_t) 1) << 69); + + out[0] += (two127m70 - in[0]); + out[1] += (two127m69 - in[1]); + out[2] += (two127m69 - in[2]); + out[3] += (two127m69 - in[3]); + out[4] += (two127m69 - in[4]); + out[5] += (two127m69 - in[5]); + out[6] += (two127m69 - in[6]); + out[7] += (two127m69 - in[7]); + out[8] += (two127m69 - in[8]); +} + +/*- + * felem_square sets |out| = |in|^2 + * On entry: + * in[i] < 2^62 + * On exit: + * out[i] < 17 * max(in[i]) * max(in[i]) + */ +static void felem_square(largefelem out, const felem in) +{ + felem inx2, inx4; + felem_scalar(inx2, in, 2); + felem_scalar(inx4, in, 4); + + /*- + * We have many cases were we want to do + * in[x] * in[y] + + * in[y] * in[x] + * This is obviously just + * 2 * in[x] * in[y] + * However, rather than do the doubling on the 128 bit result, we + * double one of the inputs to the multiplication by reading from + * |inx2| + */ + + out[0] = ((uint128_t) in[0]) * in[0]; + out[1] = ((uint128_t) in[0]) * inx2[1]; + out[2] = ((uint128_t) in[0]) * inx2[2] + ((uint128_t) in[1]) * in[1]; + out[3] = ((uint128_t) in[0]) * inx2[3] + ((uint128_t) in[1]) * inx2[2]; + out[4] = ((uint128_t) in[0]) * inx2[4] + + ((uint128_t) in[1]) * inx2[3] + ((uint128_t) in[2]) * in[2]; + out[5] = ((uint128_t) in[0]) * inx2[5] + + ((uint128_t) in[1]) * inx2[4] + ((uint128_t) in[2]) * inx2[3]; + out[6] = ((uint128_t) in[0]) * inx2[6] + + ((uint128_t) in[1]) * inx2[5] + + ((uint128_t) in[2]) * inx2[4] + ((uint128_t) in[3]) * in[3]; + out[7] = ((uint128_t) in[0]) * inx2[7] + + ((uint128_t) in[1]) * inx2[6] + + ((uint128_t) in[2]) * inx2[5] + ((uint128_t) in[3]) * inx2[4]; + out[8] = ((uint128_t) in[0]) * inx2[8] + + ((uint128_t) in[1]) * inx2[7] + + ((uint128_t) in[2]) * inx2[6] + + ((uint128_t) in[3]) * inx2[5] + ((uint128_t) in[4]) * in[4]; + + /* + * The remaining limbs fall above 2^521, with the first falling at 2^522. + * They correspond to locations one bit up from the limbs produced above + * so we would have to multiply by two to align them. Again, rather than + * operate on the 128-bit result, we double one of the inputs to the + * multiplication. If we want to double for both this reason, and the + * reason above, then we end up multiplying by four. + */ + + /* 9 */ + out[0] += ((uint128_t) in[1]) * inx4[8] + + ((uint128_t) in[2]) * inx4[7] + + ((uint128_t) in[3]) * inx4[6] + ((uint128_t) in[4]) * inx4[5]; + + /* 10 */ + out[1] += ((uint128_t) in[2]) * inx4[8] + + ((uint128_t) in[3]) * inx4[7] + + ((uint128_t) in[4]) * inx4[6] + ((uint128_t) in[5]) * inx2[5]; + + /* 11 */ + out[2] += ((uint128_t) in[3]) * inx4[8] + + ((uint128_t) in[4]) * inx4[7] + ((uint128_t) in[5]) * inx4[6]; + + /* 12 */ + out[3] += ((uint128_t) in[4]) * inx4[8] + + ((uint128_t) in[5]) * inx4[7] + ((uint128_t) in[6]) * inx2[6]; + + /* 13 */ + out[4] += ((uint128_t) in[5]) * inx4[8] + ((uint128_t) in[6]) * inx4[7]; + + /* 14 */ + out[5] += ((uint128_t) in[6]) * inx4[8] + ((uint128_t) in[7]) * inx2[7]; + + /* 15 */ + out[6] += ((uint128_t) in[7]) * inx4[8]; + + /* 16 */ + out[7] += ((uint128_t) in[8]) * inx2[8]; +} + +/*- + * felem_mul sets |out| = |in1| * |in2| + * On entry: + * in1[i] < 2^64 + * in2[i] < 2^63 + * On exit: + * out[i] < 17 * max(in1[i]) * max(in2[i]) + */ +static void felem_mul(largefelem out, const felem in1, const felem in2) +{ + felem in2x2; + felem_scalar(in2x2, in2, 2); + + out[0] = ((uint128_t) in1[0]) * in2[0]; + + out[1] = ((uint128_t) in1[0]) * in2[1] + + ((uint128_t) in1[1]) * in2[0]; + + out[2] = ((uint128_t) in1[0]) * in2[2] + + ((uint128_t) in1[1]) * in2[1] + + ((uint128_t) in1[2]) * in2[0]; + + out[3] = ((uint128_t) in1[0]) * in2[3] + + ((uint128_t) in1[1]) * in2[2] + + ((uint128_t) in1[2]) * in2[1] + + ((uint128_t) in1[3]) * in2[0]; + + out[4] = ((uint128_t) in1[0]) * in2[4] + + ((uint128_t) in1[1]) * in2[3] + + ((uint128_t) in1[2]) * in2[2] + + ((uint128_t) in1[3]) * in2[1] + + ((uint128_t) in1[4]) * in2[0]; + + out[5] = ((uint128_t) in1[0]) * in2[5] + + ((uint128_t) in1[1]) * in2[4] + + ((uint128_t) in1[2]) * in2[3] + + ((uint128_t) in1[3]) * in2[2] + + ((uint128_t) in1[4]) * in2[1] + + ((uint128_t) in1[5]) * in2[0]; + + out[6] = ((uint128_t) in1[0]) * in2[6] + + ((uint128_t) in1[1]) * in2[5] + + ((uint128_t) in1[2]) * in2[4] + + ((uint128_t) in1[3]) * in2[3] + + ((uint128_t) in1[4]) * in2[2] + + ((uint128_t) in1[5]) * in2[1] + + ((uint128_t) in1[6]) * in2[0]; + + out[7] = ((uint128_t) in1[0]) * in2[7] + + ((uint128_t) in1[1]) * in2[6] + + ((uint128_t) in1[2]) * in2[5] + + ((uint128_t) in1[3]) * in2[4] + + ((uint128_t) in1[4]) * in2[3] + + ((uint128_t) in1[5]) * in2[2] + + ((uint128_t) in1[6]) * in2[1] + + ((uint128_t) in1[7]) * in2[0]; + + out[8] = ((uint128_t) in1[0]) * in2[8] + + ((uint128_t) in1[1]) * in2[7] + + ((uint128_t) in1[2]) * in2[6] + + ((uint128_t) in1[3]) * in2[5] + + ((uint128_t) in1[4]) * in2[4] + + ((uint128_t) in1[5]) * in2[3] + + ((uint128_t) in1[6]) * in2[2] + + ((uint128_t) in1[7]) * in2[1] + + ((uint128_t) in1[8]) * in2[0]; + + /* See comment in felem_square about the use of in2x2 here */ + + out[0] += ((uint128_t) in1[1]) * in2x2[8] + + ((uint128_t) in1[2]) * in2x2[7] + + ((uint128_t) in1[3]) * in2x2[6] + + ((uint128_t) in1[4]) * in2x2[5] + + ((uint128_t) in1[5]) * in2x2[4] + + ((uint128_t) in1[6]) * in2x2[3] + + ((uint128_t) in1[7]) * in2x2[2] + + ((uint128_t) in1[8]) * in2x2[1]; + + out[1] += ((uint128_t) in1[2]) * in2x2[8] + + ((uint128_t) in1[3]) * in2x2[7] + + ((uint128_t) in1[4]) * in2x2[6] + + ((uint128_t) in1[5]) * in2x2[5] + + ((uint128_t) in1[6]) * in2x2[4] + + ((uint128_t) in1[7]) * in2x2[3] + + ((uint128_t) in1[8]) * in2x2[2]; + + out[2] += ((uint128_t) in1[3]) * in2x2[8] + + ((uint128_t) in1[4]) * in2x2[7] + + ((uint128_t) in1[5]) * in2x2[6] + + ((uint128_t) in1[6]) * in2x2[5] + + ((uint128_t) in1[7]) * in2x2[4] + + ((uint128_t) in1[8]) * in2x2[3]; + + out[3] += ((uint128_t) in1[4]) * in2x2[8] + + ((uint128_t) in1[5]) * in2x2[7] + + ((uint128_t) in1[6]) * in2x2[6] + + ((uint128_t) in1[7]) * in2x2[5] + + ((uint128_t) in1[8]) * in2x2[4]; + + out[4] += ((uint128_t) in1[5]) * in2x2[8] + + ((uint128_t) in1[6]) * in2x2[7] + + ((uint128_t) in1[7]) * in2x2[6] + + ((uint128_t) in1[8]) * in2x2[5]; + + out[5] += ((uint128_t) in1[6]) * in2x2[8] + + ((uint128_t) in1[7]) * in2x2[7] + + ((uint128_t) in1[8]) * in2x2[6]; + + out[6] += ((uint128_t) in1[7]) * in2x2[8] + + ((uint128_t) in1[8]) * in2x2[7]; + + out[7] += ((uint128_t) in1[8]) * in2x2[8]; +} + +static const limb bottom52bits = 0xfffffffffffff; + +/*- + * felem_reduce converts a largefelem to an felem. + * On entry: + * in[i] < 2^128 + * On exit: + * out[i] < 2^59 + 2^14 + */ +static void felem_reduce(felem out, const largefelem in) +{ + u64 overflow1, overflow2; + + out[0] = ((limb) in[0]) & bottom58bits; + out[1] = ((limb) in[1]) & bottom58bits; + out[2] = ((limb) in[2]) & bottom58bits; + out[3] = ((limb) in[3]) & bottom58bits; + out[4] = ((limb) in[4]) & bottom58bits; + out[5] = ((limb) in[5]) & bottom58bits; + out[6] = ((limb) in[6]) & bottom58bits; + out[7] = ((limb) in[7]) & bottom58bits; + out[8] = ((limb) in[8]) & bottom58bits; + + /* out[i] < 2^58 */ + + out[1] += ((limb) in[0]) >> 58; + out[1] += (((limb) (in[0] >> 64)) & bottom52bits) << 6; + /*- + * out[1] < 2^58 + 2^6 + 2^58 + * = 2^59 + 2^6 + */ + out[2] += ((limb) (in[0] >> 64)) >> 52; + + out[2] += ((limb) in[1]) >> 58; + out[2] += (((limb) (in[1] >> 64)) & bottom52bits) << 6; + out[3] += ((limb) (in[1] >> 64)) >> 52; + + out[3] += ((limb) in[2]) >> 58; + out[3] += (((limb) (in[2] >> 64)) & bottom52bits) << 6; + out[4] += ((limb) (in[2] >> 64)) >> 52; + + out[4] += ((limb) in[3]) >> 58; + out[4] += (((limb) (in[3] >> 64)) & bottom52bits) << 6; + out[5] += ((limb) (in[3] >> 64)) >> 52; + + out[5] += ((limb) in[4]) >> 58; + out[5] += (((limb) (in[4] >> 64)) & bottom52bits) << 6; + out[6] += ((limb) (in[4] >> 64)) >> 52; + + out[6] += ((limb) in[5]) >> 58; + out[6] += (((limb) (in[5] >> 64)) & bottom52bits) << 6; + out[7] += ((limb) (in[5] >> 64)) >> 52; + + out[7] += ((limb) in[6]) >> 58; + out[7] += (((limb) (in[6] >> 64)) & bottom52bits) << 6; + out[8] += ((limb) (in[6] >> 64)) >> 52; + + out[8] += ((limb) in[7]) >> 58; + out[8] += (((limb) (in[7] >> 64)) & bottom52bits) << 6; + /*- + * out[x > 1] < 2^58 + 2^6 + 2^58 + 2^12 + * < 2^59 + 2^13 + */ + overflow1 = ((limb) (in[7] >> 64)) >> 52; + + overflow1 += ((limb) in[8]) >> 58; + overflow1 += (((limb) (in[8] >> 64)) & bottom52bits) << 6; + overflow2 = ((limb) (in[8] >> 64)) >> 52; + + overflow1 <<= 1; /* overflow1 < 2^13 + 2^7 + 2^59 */ + overflow2 <<= 1; /* overflow2 < 2^13 */ + + out[0] += overflow1; /* out[0] < 2^60 */ + out[1] += overflow2; /* out[1] < 2^59 + 2^6 + 2^13 */ + + out[1] += out[0] >> 58; + out[0] &= bottom58bits; + /*- + * out[0] < 2^58 + * out[1] < 2^59 + 2^6 + 2^13 + 2^2 + * < 2^59 + 2^14 + */ +} + +static void felem_square_reduce(felem out, const felem in) +{ + largefelem tmp; + felem_square(tmp, in); + felem_reduce(out, tmp); +} + +static void felem_mul_reduce(felem out, const felem in1, const felem in2) +{ + largefelem tmp; + felem_mul(tmp, in1, in2); + felem_reduce(out, tmp); +} + +/*- + * felem_inv calculates |out| = |in|^{-1} + * + * Based on Fermat's Little Theorem: + * a^p = a (mod p) + * a^{p-1} = 1 (mod p) + * a^{p-2} = a^{-1} (mod p) + */ +static void felem_inv(felem out, const felem in) +{ + felem ftmp, ftmp2, ftmp3, ftmp4; + largefelem tmp; + unsigned i; + + felem_square(tmp, in); + felem_reduce(ftmp, tmp); /* 2^1 */ + felem_mul(tmp, in, ftmp); + felem_reduce(ftmp, tmp); /* 2^2 - 2^0 */ + felem_assign(ftmp2, ftmp); + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^3 - 2^1 */ + felem_mul(tmp, in, ftmp); + felem_reduce(ftmp, tmp); /* 2^3 - 2^0 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^4 - 2^1 */ + + felem_square(tmp, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^3 - 2^1 */ + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); /* 2^4 - 2^2 */ + felem_mul(tmp, ftmp3, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^4 - 2^0 */ + + felem_assign(ftmp2, ftmp3); + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); /* 2^5 - 2^1 */ + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); /* 2^6 - 2^2 */ + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); /* 2^7 - 2^3 */ + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); /* 2^8 - 2^4 */ + felem_assign(ftmp4, ftmp3); + felem_mul(tmp, ftmp3, ftmp); + felem_reduce(ftmp4, tmp); /* 2^8 - 2^1 */ + felem_square(tmp, ftmp4); + felem_reduce(ftmp4, tmp); /* 2^9 - 2^2 */ + felem_mul(tmp, ftmp3, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^8 - 2^0 */ + felem_assign(ftmp2, ftmp3); + + for (i = 0; i < 8; i++) { + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); /* 2^16 - 2^8 */ + } + felem_mul(tmp, ftmp3, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^16 - 2^0 */ + felem_assign(ftmp2, ftmp3); + + for (i = 0; i < 16; i++) { + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); /* 2^32 - 2^16 */ + } + felem_mul(tmp, ftmp3, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^32 - 2^0 */ + felem_assign(ftmp2, ftmp3); + + for (i = 0; i < 32; i++) { + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); /* 2^64 - 2^32 */ + } + felem_mul(tmp, ftmp3, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^64 - 2^0 */ + felem_assign(ftmp2, ftmp3); + + for (i = 0; i < 64; i++) { + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); /* 2^128 - 2^64 */ + } + felem_mul(tmp, ftmp3, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^128 - 2^0 */ + felem_assign(ftmp2, ftmp3); + + for (i = 0; i < 128; i++) { + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); /* 2^256 - 2^128 */ + } + felem_mul(tmp, ftmp3, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^256 - 2^0 */ + felem_assign(ftmp2, ftmp3); + + for (i = 0; i < 256; i++) { + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); /* 2^512 - 2^256 */ + } + felem_mul(tmp, ftmp3, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^512 - 2^0 */ + + for (i = 0; i < 9; i++) { + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); /* 2^521 - 2^9 */ + } + felem_mul(tmp, ftmp3, ftmp4); + felem_reduce(ftmp3, tmp); /* 2^512 - 2^2 */ + felem_mul(tmp, ftmp3, in); + felem_reduce(out, tmp); /* 2^512 - 3 */ +} + +/* This is 2^521-1, expressed as an felem */ +static const felem kPrime = { + 0x03ffffffffffffff, 0x03ffffffffffffff, 0x03ffffffffffffff, + 0x03ffffffffffffff, 0x03ffffffffffffff, 0x03ffffffffffffff, + 0x03ffffffffffffff, 0x03ffffffffffffff, 0x01ffffffffffffff +}; + +/*- + * felem_is_zero returns a limb with all bits set if |in| == 0 (mod p) and 0 + * otherwise. + * On entry: + * in[i] < 2^59 + 2^14 + */ +static limb felem_is_zero(const felem in) +{ + felem ftmp; + limb is_zero, is_p; + felem_assign(ftmp, in); + + ftmp[0] += ftmp[8] >> 57; + ftmp[8] &= bottom57bits; + /* ftmp[8] < 2^57 */ + ftmp[1] += ftmp[0] >> 58; + ftmp[0] &= bottom58bits; + ftmp[2] += ftmp[1] >> 58; + ftmp[1] &= bottom58bits; + ftmp[3] += ftmp[2] >> 58; + ftmp[2] &= bottom58bits; + ftmp[4] += ftmp[3] >> 58; + ftmp[3] &= bottom58bits; + ftmp[5] += ftmp[4] >> 58; + ftmp[4] &= bottom58bits; + ftmp[6] += ftmp[5] >> 58; + ftmp[5] &= bottom58bits; + ftmp[7] += ftmp[6] >> 58; + ftmp[6] &= bottom58bits; + ftmp[8] += ftmp[7] >> 58; + ftmp[7] &= bottom58bits; + /* ftmp[8] < 2^57 + 4 */ + + /* + * The ninth limb of 2*(2^521-1) is 0x03ffffffffffffff, which is greater + * than our bound for ftmp[8]. Therefore we only have to check if the + * zero is zero or 2^521-1. + */ + + is_zero = 0; + is_zero |= ftmp[0]; + is_zero |= ftmp[1]; + is_zero |= ftmp[2]; + is_zero |= ftmp[3]; + is_zero |= ftmp[4]; + is_zero |= ftmp[5]; + is_zero |= ftmp[6]; + is_zero |= ftmp[7]; + is_zero |= ftmp[8]; + + is_zero--; + /* + * We know that ftmp[i] < 2^63, therefore the only way that the top bit + * can be set is if is_zero was 0 before the decrement. + */ + is_zero = 0 - (is_zero >> 63); + + is_p = ftmp[0] ^ kPrime[0]; + is_p |= ftmp[1] ^ kPrime[1]; + is_p |= ftmp[2] ^ kPrime[2]; + is_p |= ftmp[3] ^ kPrime[3]; + is_p |= ftmp[4] ^ kPrime[4]; + is_p |= ftmp[5] ^ kPrime[5]; + is_p |= ftmp[6] ^ kPrime[6]; + is_p |= ftmp[7] ^ kPrime[7]; + is_p |= ftmp[8] ^ kPrime[8]; + + is_p--; + is_p = 0 - (is_p >> 63); + + is_zero |= is_p; + return is_zero; +} + +static int felem_is_zero_int(const void *in) +{ + return (int)(felem_is_zero(in) & ((limb) 1)); +} + +/*- + * felem_contract converts |in| to its unique, minimal representation. + * On entry: + * in[i] < 2^59 + 2^14 + */ +static void felem_contract(felem out, const felem in) +{ + limb is_p, is_greater, sign; + static const limb two58 = ((limb) 1) << 58; + + felem_assign(out, in); + + out[0] += out[8] >> 57; + out[8] &= bottom57bits; + /* out[8] < 2^57 */ + out[1] += out[0] >> 58; + out[0] &= bottom58bits; + out[2] += out[1] >> 58; + out[1] &= bottom58bits; + out[3] += out[2] >> 58; + out[2] &= bottom58bits; + out[4] += out[3] >> 58; + out[3] &= bottom58bits; + out[5] += out[4] >> 58; + out[4] &= bottom58bits; + out[6] += out[5] >> 58; + out[5] &= bottom58bits; + out[7] += out[6] >> 58; + out[6] &= bottom58bits; + out[8] += out[7] >> 58; + out[7] &= bottom58bits; + /* out[8] < 2^57 + 4 */ + + /* + * If the value is greater than 2^521-1 then we have to subtract 2^521-1 + * out. See the comments in felem_is_zero regarding why we don't test for + * other multiples of the prime. + */ + + /* + * First, if |out| is equal to 2^521-1, we subtract it out to get zero. + */ + + is_p = out[0] ^ kPrime[0]; + is_p |= out[1] ^ kPrime[1]; + is_p |= out[2] ^ kPrime[2]; + is_p |= out[3] ^ kPrime[3]; + is_p |= out[4] ^ kPrime[4]; + is_p |= out[5] ^ kPrime[5]; + is_p |= out[6] ^ kPrime[6]; + is_p |= out[7] ^ kPrime[7]; + is_p |= out[8] ^ kPrime[8]; + + is_p--; + is_p &= is_p << 32; + is_p &= is_p << 16; + is_p &= is_p << 8; + is_p &= is_p << 4; + is_p &= is_p << 2; + is_p &= is_p << 1; + is_p = 0 - (is_p >> 63); + is_p = ~is_p; + + /* is_p is 0 iff |out| == 2^521-1 and all ones otherwise */ + + out[0] &= is_p; + out[1] &= is_p; + out[2] &= is_p; + out[3] &= is_p; + out[4] &= is_p; + out[5] &= is_p; + out[6] &= is_p; + out[7] &= is_p; + out[8] &= is_p; + + /* + * In order to test that |out| >= 2^521-1 we need only test if out[8] >> + * 57 is greater than zero as (2^521-1) + x >= 2^522 + */ + is_greater = out[8] >> 57; + is_greater |= is_greater << 32; + is_greater |= is_greater << 16; + is_greater |= is_greater << 8; + is_greater |= is_greater << 4; + is_greater |= is_greater << 2; + is_greater |= is_greater << 1; + is_greater = 0 - (is_greater >> 63); + + out[0] -= kPrime[0] & is_greater; + out[1] -= kPrime[1] & is_greater; + out[2] -= kPrime[2] & is_greater; + out[3] -= kPrime[3] & is_greater; + out[4] -= kPrime[4] & is_greater; + out[5] -= kPrime[5] & is_greater; + out[6] -= kPrime[6] & is_greater; + out[7] -= kPrime[7] & is_greater; + out[8] -= kPrime[8] & is_greater; + + /* Eliminate negative coefficients */ + sign = -(out[0] >> 63); + out[0] += (two58 & sign); + out[1] -= (1 & sign); + sign = -(out[1] >> 63); + out[1] += (two58 & sign); + out[2] -= (1 & sign); + sign = -(out[2] >> 63); + out[2] += (two58 & sign); + out[3] -= (1 & sign); + sign = -(out[3] >> 63); + out[3] += (two58 & sign); + out[4] -= (1 & sign); + sign = -(out[4] >> 63); + out[4] += (two58 & sign); + out[5] -= (1 & sign); + sign = -(out[0] >> 63); + out[5] += (two58 & sign); + out[6] -= (1 & sign); + sign = -(out[6] >> 63); + out[6] += (two58 & sign); + out[7] -= (1 & sign); + sign = -(out[7] >> 63); + out[7] += (two58 & sign); + out[8] -= (1 & sign); + sign = -(out[5] >> 63); + out[5] += (two58 & sign); + out[6] -= (1 & sign); + sign = -(out[6] >> 63); + out[6] += (two58 & sign); + out[7] -= (1 & sign); + sign = -(out[7] >> 63); + out[7] += (two58 & sign); + out[8] -= (1 & sign); +} + +/*- + * Group operations + * ---------------- + * + * Building on top of the field operations we have the operations on the + * elliptic curve group itself. Points on the curve are represented in Jacobian + * coordinates */ + +/*- + * point_double calculates 2*(x_in, y_in, z_in) + * + * The method is taken from: + * http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b + * + * Outputs can equal corresponding inputs, i.e., x_out == x_in is allowed. + * while x_out == y_in is not (maybe this works, but it's not tested). */ +static void +point_double(felem x_out, felem y_out, felem z_out, + const felem x_in, const felem y_in, const felem z_in) +{ + largefelem tmp, tmp2; + felem delta, gamma, beta, alpha, ftmp, ftmp2; + + felem_assign(ftmp, x_in); + felem_assign(ftmp2, x_in); + + /* delta = z^2 */ + felem_square(tmp, z_in); + felem_reduce(delta, tmp); /* delta[i] < 2^59 + 2^14 */ + + /* gamma = y^2 */ + felem_square(tmp, y_in); + felem_reduce(gamma, tmp); /* gamma[i] < 2^59 + 2^14 */ + + /* beta = x*gamma */ + felem_mul(tmp, x_in, gamma); + felem_reduce(beta, tmp); /* beta[i] < 2^59 + 2^14 */ + + /* alpha = 3*(x-delta)*(x+delta) */ + felem_diff64(ftmp, delta); + /* ftmp[i] < 2^61 */ + felem_sum64(ftmp2, delta); + /* ftmp2[i] < 2^60 + 2^15 */ + felem_scalar64(ftmp2, 3); + /* ftmp2[i] < 3*2^60 + 3*2^15 */ + felem_mul(tmp, ftmp, ftmp2); + /*- + * tmp[i] < 17(3*2^121 + 3*2^76) + * = 61*2^121 + 61*2^76 + * < 64*2^121 + 64*2^76 + * = 2^127 + 2^82 + * < 2^128 + */ + felem_reduce(alpha, tmp); + + /* x' = alpha^2 - 8*beta */ + felem_square(tmp, alpha); + /* + * tmp[i] < 17*2^120 < 2^125 + */ + felem_assign(ftmp, beta); + felem_scalar64(ftmp, 8); + /* ftmp[i] < 2^62 + 2^17 */ + felem_diff_128_64(tmp, ftmp); + /* tmp[i] < 2^125 + 2^63 + 2^62 + 2^17 */ + felem_reduce(x_out, tmp); + + /* z' = (y + z)^2 - gamma - delta */ + felem_sum64(delta, gamma); + /* delta[i] < 2^60 + 2^15 */ + felem_assign(ftmp, y_in); + felem_sum64(ftmp, z_in); + /* ftmp[i] < 2^60 + 2^15 */ + felem_square(tmp, ftmp); + /* + * tmp[i] < 17(2^122) < 2^127 + */ + felem_diff_128_64(tmp, delta); + /* tmp[i] < 2^127 + 2^63 */ + felem_reduce(z_out, tmp); + + /* y' = alpha*(4*beta - x') - 8*gamma^2 */ + felem_scalar64(beta, 4); + /* beta[i] < 2^61 + 2^16 */ + felem_diff64(beta, x_out); + /* beta[i] < 2^61 + 2^60 + 2^16 */ + felem_mul(tmp, alpha, beta); + /*- + * tmp[i] < 17*((2^59 + 2^14)(2^61 + 2^60 + 2^16)) + * = 17*(2^120 + 2^75 + 2^119 + 2^74 + 2^75 + 2^30) + * = 17*(2^120 + 2^119 + 2^76 + 2^74 + 2^30) + * < 2^128 + */ + felem_square(tmp2, gamma); + /*- + * tmp2[i] < 17*(2^59 + 2^14)^2 + * = 17*(2^118 + 2^74 + 2^28) + */ + felem_scalar128(tmp2, 8); + /*- + * tmp2[i] < 8*17*(2^118 + 2^74 + 2^28) + * = 2^125 + 2^121 + 2^81 + 2^77 + 2^35 + 2^31 + * < 2^126 + */ + felem_diff128(tmp, tmp2); + /*- + * tmp[i] < 2^127 - 2^69 + 17(2^120 + 2^119 + 2^76 + 2^74 + 2^30) + * = 2^127 + 2^124 + 2^122 + 2^120 + 2^118 + 2^80 + 2^78 + 2^76 + + * 2^74 + 2^69 + 2^34 + 2^30 + * < 2^128 + */ + felem_reduce(y_out, tmp); +} + +/* copy_conditional copies in to out iff mask is all ones. */ +static void copy_conditional(felem out, const felem in, limb mask) +{ + unsigned i; + for (i = 0; i < NLIMBS; ++i) { + const limb tmp = mask & (in[i] ^ out[i]); + out[i] ^= tmp; + } +} + +/*- + * point_add calculates (x1, y1, z1) + (x2, y2, z2) + * + * The method is taken from + * http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl, + * adapted for mixed addition (z2 = 1, or z2 = 0 for the point at infinity). + * + * This function includes a branch for checking whether the two input points + * are equal (while not equal to the point at infinity). See comment below + * on constant-time. + */ +static void point_add(felem x3, felem y3, felem z3, + const felem x1, const felem y1, const felem z1, + const int mixed, const felem x2, const felem y2, + const felem z2) +{ + felem ftmp, ftmp2, ftmp3, ftmp4, ftmp5, ftmp6, x_out, y_out, z_out; + largefelem tmp, tmp2; + limb x_equal, y_equal, z1_is_zero, z2_is_zero; + + z1_is_zero = felem_is_zero(z1); + z2_is_zero = felem_is_zero(z2); + + /* ftmp = z1z1 = z1**2 */ + felem_square(tmp, z1); + felem_reduce(ftmp, tmp); + + if (!mixed) { + /* ftmp2 = z2z2 = z2**2 */ + felem_square(tmp, z2); + felem_reduce(ftmp2, tmp); + + /* u1 = ftmp3 = x1*z2z2 */ + felem_mul(tmp, x1, ftmp2); + felem_reduce(ftmp3, tmp); + + /* ftmp5 = z1 + z2 */ + felem_assign(ftmp5, z1); + felem_sum64(ftmp5, z2); + /* ftmp5[i] < 2^61 */ + + /* ftmp5 = (z1 + z2)**2 - z1z1 - z2z2 = 2*z1z2 */ + felem_square(tmp, ftmp5); + /* tmp[i] < 17*2^122 */ + felem_diff_128_64(tmp, ftmp); + /* tmp[i] < 17*2^122 + 2^63 */ + felem_diff_128_64(tmp, ftmp2); + /* tmp[i] < 17*2^122 + 2^64 */ + felem_reduce(ftmp5, tmp); + + /* ftmp2 = z2 * z2z2 */ + felem_mul(tmp, ftmp2, z2); + felem_reduce(ftmp2, tmp); + + /* s1 = ftmp6 = y1 * z2**3 */ + felem_mul(tmp, y1, ftmp2); + felem_reduce(ftmp6, tmp); + } else { + /* + * We'll assume z2 = 1 (special case z2 = 0 is handled later) + */ + + /* u1 = ftmp3 = x1*z2z2 */ + felem_assign(ftmp3, x1); + + /* ftmp5 = 2*z1z2 */ + felem_scalar(ftmp5, z1, 2); + + /* s1 = ftmp6 = y1 * z2**3 */ + felem_assign(ftmp6, y1); + } + + /* u2 = x2*z1z1 */ + felem_mul(tmp, x2, ftmp); + /* tmp[i] < 17*2^120 */ + + /* h = ftmp4 = u2 - u1 */ + felem_diff_128_64(tmp, ftmp3); + /* tmp[i] < 17*2^120 + 2^63 */ + felem_reduce(ftmp4, tmp); + + x_equal = felem_is_zero(ftmp4); + + /* z_out = ftmp5 * h */ + felem_mul(tmp, ftmp5, ftmp4); + felem_reduce(z_out, tmp); + + /* ftmp = z1 * z1z1 */ + felem_mul(tmp, ftmp, z1); + felem_reduce(ftmp, tmp); + + /* s2 = tmp = y2 * z1**3 */ + felem_mul(tmp, y2, ftmp); + /* tmp[i] < 17*2^120 */ + + /* r = ftmp5 = (s2 - s1)*2 */ + felem_diff_128_64(tmp, ftmp6); + /* tmp[i] < 17*2^120 + 2^63 */ + felem_reduce(ftmp5, tmp); + y_equal = felem_is_zero(ftmp5); + felem_scalar64(ftmp5, 2); + /* ftmp5[i] < 2^61 */ + + if (x_equal && y_equal && !z1_is_zero && !z2_is_zero) { + /* + * This is obviously not constant-time but it will almost-never happen + * for ECDH / ECDSA. The case where it can happen is during scalar-mult + * where the intermediate value gets very close to the group order. + * Since |ec_GFp_nistp_recode_scalar_bits| produces signed digits for + * the scalar, it's possible for the intermediate value to be a small + * negative multiple of the base point, and for the final signed digit + * to be the same value. We believe that this only occurs for the scalar + * 1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + * ffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb + * 71e913863f7, in that case the penultimate intermediate is -9G and + * the final digit is also -9G. Since this only happens for a single + * scalar, the timing leak is irrelevent. (Any attacker who wanted to + * check whether a secret scalar was that exact value, can already do + * so.) + */ + point_double(x3, y3, z3, x1, y1, z1); + return; + } + + /* I = ftmp = (2h)**2 */ + felem_assign(ftmp, ftmp4); + felem_scalar64(ftmp, 2); + /* ftmp[i] < 2^61 */ + felem_square(tmp, ftmp); + /* tmp[i] < 17*2^122 */ + felem_reduce(ftmp, tmp); + + /* J = ftmp2 = h * I */ + felem_mul(tmp, ftmp4, ftmp); + felem_reduce(ftmp2, tmp); + + /* V = ftmp4 = U1 * I */ + felem_mul(tmp, ftmp3, ftmp); + felem_reduce(ftmp4, tmp); + + /* x_out = r**2 - J - 2V */ + felem_square(tmp, ftmp5); + /* tmp[i] < 17*2^122 */ + felem_diff_128_64(tmp, ftmp2); + /* tmp[i] < 17*2^122 + 2^63 */ + felem_assign(ftmp3, ftmp4); + felem_scalar64(ftmp4, 2); + /* ftmp4[i] < 2^61 */ + felem_diff_128_64(tmp, ftmp4); + /* tmp[i] < 17*2^122 + 2^64 */ + felem_reduce(x_out, tmp); + + /* y_out = r(V-x_out) - 2 * s1 * J */ + felem_diff64(ftmp3, x_out); + /* + * ftmp3[i] < 2^60 + 2^60 = 2^61 + */ + felem_mul(tmp, ftmp5, ftmp3); + /* tmp[i] < 17*2^122 */ + felem_mul(tmp2, ftmp6, ftmp2); + /* tmp2[i] < 17*2^120 */ + felem_scalar128(tmp2, 2); + /* tmp2[i] < 17*2^121 */ + felem_diff128(tmp, tmp2); + /*- + * tmp[i] < 2^127 - 2^69 + 17*2^122 + * = 2^126 - 2^122 - 2^6 - 2^2 - 1 + * < 2^127 + */ + felem_reduce(y_out, tmp); + + copy_conditional(x_out, x2, z1_is_zero); + copy_conditional(x_out, x1, z2_is_zero); + copy_conditional(y_out, y2, z1_is_zero); + copy_conditional(y_out, y1, z2_is_zero); + copy_conditional(z_out, z2, z1_is_zero); + copy_conditional(z_out, z1, z2_is_zero); + felem_assign(x3, x_out); + felem_assign(y3, y_out); + felem_assign(z3, z_out); +} + +/*- + * Base point pre computation + * -------------------------- + * + * Two different sorts of precomputed tables are used in the following code. + * Each contain various points on the curve, where each point is three field + * elements (x, y, z). + * + * For the base point table, z is usually 1 (0 for the point at infinity). + * This table has 16 elements: + * index | bits | point + * ------+---------+------------------------------ + * 0 | 0 0 0 0 | 0G + * 1 | 0 0 0 1 | 1G + * 2 | 0 0 1 0 | 2^130G + * 3 | 0 0 1 1 | (2^130 + 1)G + * 4 | 0 1 0 0 | 2^260G + * 5 | 0 1 0 1 | (2^260 + 1)G + * 6 | 0 1 1 0 | (2^260 + 2^130)G + * 7 | 0 1 1 1 | (2^260 + 2^130 + 1)G + * 8 | 1 0 0 0 | 2^390G + * 9 | 1 0 0 1 | (2^390 + 1)G + * 10 | 1 0 1 0 | (2^390 + 2^130)G + * 11 | 1 0 1 1 | (2^390 + 2^130 + 1)G + * 12 | 1 1 0 0 | (2^390 + 2^260)G + * 13 | 1 1 0 1 | (2^390 + 2^260 + 1)G + * 14 | 1 1 1 0 | (2^390 + 2^260 + 2^130)G + * 15 | 1 1 1 1 | (2^390 + 2^260 + 2^130 + 1)G + * + * The reason for this is so that we can clock bits into four different + * locations when doing simple scalar multiplies against the base point. + * + * Tables for other points have table[i] = iG for i in 0 .. 16. */ + +/* gmul is the table of precomputed base points */ +static const felem gmul[16][3] = { +{{0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x017e7e31c2e5bd66, 0x022cf0615a90a6fe, 0x00127a2ffa8de334, + 0x01dfbf9d64a3f877, 0x006b4d3dbaa14b5e, 0x014fed487e0a2bd8, + 0x015b4429c6481390, 0x03a73678fb2d988e, 0x00c6858e06b70404}, + {0x00be94769fd16650, 0x031c21a89cb09022, 0x039013fad0761353, + 0x02657bd099031542, 0x03273e662c97ee72, 0x01e6d11a05ebef45, + 0x03d1bd998f544495, 0x03001172297ed0b1, 0x011839296a789a3b}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x0373faacbc875bae, 0x00f325023721c671, 0x00f666fd3dbde5ad, + 0x01a6932363f88ea7, 0x01fc6d9e13f9c47b, 0x03bcbffc2bbf734e, + 0x013ee3c3647f3a92, 0x029409fefe75d07d, 0x00ef9199963d85e5}, + {0x011173743ad5b178, 0x02499c7c21bf7d46, 0x035beaeabb8b1a58, + 0x00f989c4752ea0a3, 0x0101e1de48a9c1a3, 0x01a20076be28ba6c, + 0x02f8052e5eb2de95, 0x01bfe8f82dea117c, 0x0160074d3c36ddb7}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x012f3fc373393b3b, 0x03d3d6172f1419fa, 0x02adc943c0b86873, + 0x00d475584177952b, 0x012a4d1673750ee2, 0x00512517a0f13b0c, + 0x02b184671a7b1734, 0x0315b84236f1a50a, 0x00a4afc472edbdb9}, + {0x00152a7077f385c4, 0x03044007d8d1c2ee, 0x0065829d61d52b52, + 0x00494ff6b6631d0d, 0x00a11d94d5f06bcf, 0x02d2f89474d9282e, + 0x0241c5727c06eeb9, 0x0386928710fbdb9d, 0x01f883f727b0dfbe}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x019b0c3c9185544d, 0x006243a37c9d97db, 0x02ee3cbe030a2ad2, + 0x00cfdd946bb51e0d, 0x0271c00932606b91, 0x03f817d1ec68c561, + 0x03f37009806a369c, 0x03c1f30baf184fd5, 0x01091022d6d2f065}, + {0x0292c583514c45ed, 0x0316fca51f9a286c, 0x00300af507c1489a, + 0x0295f69008298cf1, 0x02c0ed8274943d7b, 0x016509b9b47a431e, + 0x02bc9de9634868ce, 0x005b34929bffcb09, 0x000c1a0121681524}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x0286abc0292fb9f2, 0x02665eee9805b3f7, 0x01ed7455f17f26d6, + 0x0346355b83175d13, 0x006284944cd0a097, 0x0191895bcdec5e51, + 0x02e288370afda7d9, 0x03b22312bfefa67a, 0x01d104d3fc0613fe}, + {0x0092421a12f7e47f, 0x0077a83fa373c501, 0x03bd25c5f696bd0d, + 0x035c41e4d5459761, 0x01ca0d1742b24f53, 0x00aaab27863a509c, + 0x018b6de47df73917, 0x025c0b771705cd01, 0x01fd51d566d760a7}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x01dd92ff6b0d1dbd, 0x039c5e2e8f8afa69, 0x0261ed13242c3b27, + 0x0382c6e67026e6a0, 0x01d60b10be2089f9, 0x03c15f3dce86723f, + 0x03c764a32d2a062d, 0x017307eac0fad056, 0x018207c0b96c5256}, + {0x0196a16d60e13154, 0x03e6ce74c0267030, 0x00ddbf2b4e52a5aa, + 0x012738241bbf31c8, 0x00ebe8dc04685a28, 0x024c2ad6d380d4a2, + 0x035ee062a6e62d0e, 0x0029ed74af7d3a0f, 0x00eef32aec142ebd}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x00c31ec398993b39, 0x03a9f45bcda68253, 0x00ac733c24c70890, + 0x00872b111401ff01, 0x01d178c23195eafb, 0x03bca2c816b87f74, + 0x0261a9af46fbad7a, 0x0324b2a8dd3d28f9, 0x00918121d8f24e23}, + {0x032bc8c1ca983cd7, 0x00d869dfb08fc8c6, 0x01693cb61fce1516, + 0x012a5ea68f4e88a8, 0x010869cab88d7ae3, 0x009081ad277ceee1, + 0x033a77166d064cdc, 0x03955235a1fb3a95, 0x01251a4a9b25b65e}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x00148a3a1b27f40b, 0x0123186df1b31fdc, 0x00026e7beaad34ce, + 0x01db446ac1d3dbba, 0x0299c1a33437eaec, 0x024540610183cbb7, + 0x0173bb0e9ce92e46, 0x02b937e43921214b, 0x01ab0436a9bf01b5}, + {0x0383381640d46948, 0x008dacbf0e7f330f, 0x03602122bcc3f318, + 0x01ee596b200620d6, 0x03bd0585fda430b3, 0x014aed77fd123a83, + 0x005ace749e52f742, 0x0390fe041da2b842, 0x0189a8ceb3299242}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x012a19d6b3282473, 0x00c0915918b423ce, 0x023a954eb94405ae, + 0x00529f692be26158, 0x0289fa1b6fa4b2aa, 0x0198ae4ceea346ef, + 0x0047d8cdfbdedd49, 0x00cc8c8953f0f6b8, 0x001424abbff49203}, + {0x0256732a1115a03a, 0x0351bc38665c6733, 0x03f7b950fb4a6447, + 0x000afffa94c22155, 0x025763d0a4dab540, 0x000511e92d4fc283, + 0x030a7e9eda0ee96c, 0x004c3cd93a28bf0a, 0x017edb3a8719217f}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x011de5675a88e673, 0x031d7d0f5e567fbe, 0x0016b2062c970ae5, + 0x03f4a2be49d90aa7, 0x03cef0bd13822866, 0x03f0923dcf774a6c, + 0x0284bebc4f322f72, 0x016ab2645302bb2c, 0x01793f95dace0e2a}, + {0x010646e13527a28f, 0x01ca1babd59dc5e7, 0x01afedfd9a5595df, + 0x01f15785212ea6b1, 0x0324e5d64f6ae3f4, 0x02d680f526d00645, + 0x0127920fadf627a7, 0x03b383f75df4f684, 0x0089e0057e783b0a}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x00f334b9eb3c26c6, 0x0298fdaa98568dce, 0x01c2d24843a82292, + 0x020bcb24fa1b0711, 0x02cbdb3d2b1875e6, 0x0014907598f89422, + 0x03abe3aa43b26664, 0x02cbf47f720bc168, 0x0133b5e73014b79b}, + {0x034aab5dab05779d, 0x00cdc5d71fee9abb, 0x0399f16bd4bd9d30, + 0x03582fa592d82647, 0x02be1cdfb775b0e9, 0x0034f7cea32e94cb, + 0x0335a7f08f56f286, 0x03b707e9565d1c8b, 0x0015c946ea5b614f}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x024676f6cff72255, 0x00d14625cac96378, 0x00532b6008bc3767, + 0x01fc16721b985322, 0x023355ea1b091668, 0x029de7afdc0317c3, + 0x02fc8a7ca2da037c, 0x02de1217d74a6f30, 0x013f7173175b73bf}, + {0x0344913f441490b5, 0x0200f9e272b61eca, 0x0258a246b1dd55d2, + 0x03753db9ea496f36, 0x025e02937a09c5ef, 0x030cbd3d14012692, + 0x01793a67e70dc72a, 0x03ec1d37048a662e, 0x006550f700c32a8d}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x00d3f48a347eba27, 0x008e636649b61bd8, 0x00d3b93716778fb3, + 0x004d1915757bd209, 0x019d5311a3da44e0, 0x016d1afcbbe6aade, + 0x0241bf5f73265616, 0x0384672e5d50d39b, 0x005009fee522b684}, + {0x029b4fab064435fe, 0x018868ee095bbb07, 0x01ea3d6936cc92b8, + 0x000608b00f78a2f3, 0x02db911073d1c20f, 0x018205938470100a, + 0x01f1e4964cbe6ff2, 0x021a19a29eed4663, 0x01414485f42afa81}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x01612b3a17f63e34, 0x03813992885428e6, 0x022b3c215b5a9608, + 0x029b4057e19f2fcb, 0x0384059a587af7e6, 0x02d6400ace6fe610, + 0x029354d896e8e331, 0x00c047ee6dfba65e, 0x0037720542e9d49d}, + {0x02ce9eed7c5e9278, 0x0374ed703e79643b, 0x01316c54c4072006, + 0x005aaa09054b2ee8, 0x002824000c840d57, 0x03d4eba24771ed86, + 0x0189c50aabc3bdae, 0x0338c01541e15510, 0x00466d56e38eed42}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x007efd8330ad8bd6, 0x02465ed48047710b, 0x0034c6606b215e0c, + 0x016ae30c53cbf839, 0x01fa17bd37161216, 0x018ead4e61ce8ab9, + 0x005482ed5f5dee46, 0x037543755bba1d7f, 0x005e5ac7e70a9d0f}, + {0x0117e1bb2fdcb2a2, 0x03deea36249f40c4, 0x028d09b4a6246cb7, + 0x03524b8855bcf756, 0x023d7d109d5ceb58, 0x0178e43e3223ef9c, + 0x0154536a0c6e966a, 0x037964d1286ee9fe, 0x0199bcd90e125055}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}} +}; + +/* + * select_point selects the |idx|th point from a precomputation table and + * copies it to out. + */ + /* pre_comp below is of the size provided in |size| */ +static void select_point(const limb idx, unsigned int size, + const felem pre_comp[][3], felem out[3]) +{ + unsigned i, j; + limb *outlimbs = &out[0][0]; + + memset(out, 0, sizeof(*out) * 3); + + for (i = 0; i < size; i++) { + const limb *inlimbs = &pre_comp[i][0][0]; + limb mask = i ^ idx; + mask |= mask >> 4; + mask |= mask >> 2; + mask |= mask >> 1; + mask &= 1; + mask--; + for (j = 0; j < NLIMBS * 3; j++) + outlimbs[j] |= inlimbs[j] & mask; + } +} + +/* get_bit returns the |i|th bit in |in| */ +static char get_bit(const felem_bytearray in, int i) +{ + if (i < 0) + return 0; + return (in[i >> 3] >> (i & 7)) & 1; +} + +/* + * Interleaved point multiplication using precomputed point multiples: The + * small point multiples 0*P, 1*P, ..., 16*P are in pre_comp[], the scalars + * in scalars[]. If g_scalar is non-NULL, we also add this multiple of the + * generator, using certain (large) precomputed multiples in g_pre_comp. + * Output point (X, Y, Z) is stored in x_out, y_out, z_out + */ +static void batch_mul(felem x_out, felem y_out, felem z_out, + const felem_bytearray scalars[], + const unsigned num_points, const u8 *g_scalar, + const int mixed, const felem pre_comp[][17][3], + const felem g_pre_comp[16][3]) +{ + int i, skip; + unsigned num, gen_mul = (g_scalar != NULL); + felem nq[3], tmp[4]; + limb bits; + u8 sign, digit; + + /* set nq to the point at infinity */ + memset(nq, 0, sizeof(nq)); + + /* + * Loop over all scalars msb-to-lsb, interleaving additions of multiples + * of the generator (last quarter of rounds) and additions of other + * points multiples (every 5th round). + */ + skip = 1; /* save two point operations in the first + * round */ + for (i = (num_points ? 520 : 130); i >= 0; --i) { + /* double */ + if (!skip) + point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]); + + /* add multiples of the generator */ + if (gen_mul && (i <= 130)) { + bits = get_bit(g_scalar, i + 390) << 3; + if (i < 130) { + bits |= get_bit(g_scalar, i + 260) << 2; + bits |= get_bit(g_scalar, i + 130) << 1; + bits |= get_bit(g_scalar, i); + } + /* select the point to add, in constant time */ + select_point(bits, 16, g_pre_comp, tmp); + if (!skip) { + /* The 1 argument below is for "mixed" */ + point_add(nq[0], nq[1], nq[2], + nq[0], nq[1], nq[2], 1, tmp[0], tmp[1], tmp[2]); + } else { + memcpy(nq, tmp, 3 * sizeof(felem)); + skip = 0; + } + } + + /* do other additions every 5 doublings */ + if (num_points && (i % 5 == 0)) { + /* loop over all scalars */ + for (num = 0; num < num_points; ++num) { + bits = get_bit(scalars[num], i + 4) << 5; + bits |= get_bit(scalars[num], i + 3) << 4; + bits |= get_bit(scalars[num], i + 2) << 3; + bits |= get_bit(scalars[num], i + 1) << 2; + bits |= get_bit(scalars[num], i) << 1; + bits |= get_bit(scalars[num], i - 1); + ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits); + + /* + * select the point to add or subtract, in constant time + */ + select_point(digit, 17, pre_comp[num], tmp); + felem_neg(tmp[3], tmp[1]); /* (X, -Y, Z) is the negative + * point */ + copy_conditional(tmp[1], tmp[3], (-(limb) sign)); + + if (!skip) { + point_add(nq[0], nq[1], nq[2], + nq[0], nq[1], nq[2], + mixed, tmp[0], tmp[1], tmp[2]); + } else { + memcpy(nq, tmp, 3 * sizeof(felem)); + skip = 0; + } + } + } + } + felem_assign(x_out, nq[0]); + felem_assign(y_out, nq[1]); + felem_assign(z_out, nq[2]); +} + +/* Precomputation for the group generator. */ +struct nistp521_pre_comp_st { + felem g_pre_comp[16][3]; + CRYPTO_REF_COUNT references; + CRYPTO_RWLOCK *lock; +}; + +const EC_METHOD *EC_GFp_nistp521_method(void) +{ + static const EC_METHOD ret = { + EC_FLAGS_DEFAULT_OCT, + NID_X9_62_prime_field, + ec_GFp_nistp521_group_init, + ec_GFp_simple_group_finish, + ec_GFp_simple_group_clear_finish, + ec_GFp_nist_group_copy, + ec_GFp_nistp521_group_set_curve, + ec_GFp_simple_group_get_curve, + ec_GFp_simple_group_get_degree, + ec_group_simple_order_bits, + ec_GFp_simple_group_check_discriminant, + ec_GFp_simple_point_init, + ec_GFp_simple_point_finish, + ec_GFp_simple_point_clear_finish, + ec_GFp_simple_point_copy, + ec_GFp_simple_point_set_to_infinity, + ec_GFp_simple_set_Jprojective_coordinates_GFp, + ec_GFp_simple_get_Jprojective_coordinates_GFp, + ec_GFp_simple_point_set_affine_coordinates, + ec_GFp_nistp521_point_get_affine_coordinates, + 0 /* point_set_compressed_coordinates */ , + 0 /* point2oct */ , + 0 /* oct2point */ , + ec_GFp_simple_add, + ec_GFp_simple_dbl, + ec_GFp_simple_invert, + ec_GFp_simple_is_at_infinity, + ec_GFp_simple_is_on_curve, + ec_GFp_simple_cmp, + ec_GFp_simple_make_affine, + ec_GFp_simple_points_make_affine, + ec_GFp_nistp521_points_mul, + ec_GFp_nistp521_precompute_mult, + ec_GFp_nistp521_have_precompute_mult, + ec_GFp_nist_field_mul, + ec_GFp_nist_field_sqr, + 0 /* field_div */ , + ec_GFp_simple_field_inv, + 0 /* field_encode */ , + 0 /* field_decode */ , + 0, /* field_set_to_one */ + ec_key_simple_priv2oct, + ec_key_simple_oct2priv, + 0, /* set private */ + ec_key_simple_generate_key, + ec_key_simple_check_key, + ec_key_simple_generate_public_key, + 0, /* keycopy */ + 0, /* keyfinish */ + ecdh_simple_compute_key, + 0, /* field_inverse_mod_ord */ + 0, /* blind_coordinates */ + 0, /* ladder_pre */ + 0, /* ladder_step */ + 0 /* ladder_post */ + }; + + return &ret; +} + +/******************************************************************************/ +/* + * FUNCTIONS TO MANAGE PRECOMPUTATION + */ + +static NISTP521_PRE_COMP *nistp521_pre_comp_new(void) +{ + NISTP521_PRE_COMP *ret = OPENSSL_zalloc(sizeof(*ret)); + + if (ret == NULL) { + ECerr(EC_F_NISTP521_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); + return ret; + } + + ret->references = 1; + + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) { + ECerr(EC_F_NISTP521_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ret); + return NULL; + } + return ret; +} + +NISTP521_PRE_COMP *EC_nistp521_pre_comp_dup(NISTP521_PRE_COMP *p) +{ + int i; + if (p != NULL) + CRYPTO_UP_REF(&p->references, &i, p->lock); + return p; +} + +void EC_nistp521_pre_comp_free(NISTP521_PRE_COMP *p) +{ + int i; + + if (p == NULL) + return; + + CRYPTO_DOWN_REF(&p->references, &i, p->lock); + REF_PRINT_COUNT("EC_nistp521", x); + if (i > 0) + return; + REF_ASSERT_ISNT(i < 0); + + CRYPTO_THREAD_lock_free(p->lock); + OPENSSL_free(p); +} + +/******************************************************************************/ +/* + * OPENSSL EC_METHOD FUNCTIONS + */ + +int ec_GFp_nistp521_group_init(EC_GROUP *group) +{ + int ret; + ret = ec_GFp_simple_group_init(group); + group->a_is_minus3 = 1; + return ret; +} + +int ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *b, + BN_CTX *ctx) +{ + int ret = 0; + BN_CTX *new_ctx = NULL; + BIGNUM *curve_p, *curve_a, *curve_b; + + if (ctx == NULL) + if ((ctx = new_ctx = BN_CTX_new()) == NULL) + return 0; + BN_CTX_start(ctx); + curve_p = BN_CTX_get(ctx); + curve_a = BN_CTX_get(ctx); + curve_b = BN_CTX_get(ctx); + if (curve_b == NULL) + goto err; + BN_bin2bn(nistp521_curve_params[0], sizeof(felem_bytearray), curve_p); + BN_bin2bn(nistp521_curve_params[1], sizeof(felem_bytearray), curve_a); + BN_bin2bn(nistp521_curve_params[2], sizeof(felem_bytearray), curve_b); + if ((BN_cmp(curve_p, p)) || (BN_cmp(curve_a, a)) || (BN_cmp(curve_b, b))) { + ECerr(EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE, + EC_R_WRONG_CURVE_PARAMETERS); + goto err; + } + group->field_mod_func = BN_nist_mod_521; + ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); + err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +/* + * Takes the Jacobian coordinates (X, Y, Z) of a point and returns (X', Y') = + * (X/Z^2, Y/Z^3) + */ +int ec_GFp_nistp521_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx) +{ + felem z1, z2, x_in, y_in, x_out, y_out; + largefelem tmp; + + if (EC_POINT_is_at_infinity(group, point)) { + ECerr(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES, + EC_R_POINT_AT_INFINITY); + return 0; + } + if ((!BN_to_felem(x_in, point->X)) || (!BN_to_felem(y_in, point->Y)) || + (!BN_to_felem(z1, point->Z))) + return 0; + felem_inv(z2, z1); + felem_square(tmp, z2); + felem_reduce(z1, tmp); + felem_mul(tmp, x_in, z1); + felem_reduce(x_in, tmp); + felem_contract(x_out, x_in); + if (x != NULL) { + if (!felem_to_BN(x, x_out)) { + ECerr(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES, + ERR_R_BN_LIB); + return 0; + } + } + felem_mul(tmp, z1, z2); + felem_reduce(z1, tmp); + felem_mul(tmp, y_in, z1); + felem_reduce(y_in, tmp); + felem_contract(y_out, y_in); + if (y != NULL) { + if (!felem_to_BN(y, y_out)) { + ECerr(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES, + ERR_R_BN_LIB); + return 0; + } + } + return 1; +} + +/* points below is of size |num|, and tmp_felems is of size |num+1/ */ +static void make_points_affine(size_t num, felem points[][3], + felem tmp_felems[]) +{ + /* + * Runs in constant time, unless an input is the point at infinity (which + * normally shouldn't happen). + */ + ec_GFp_nistp_points_make_affine_internal(num, + points, + sizeof(felem), + tmp_felems, + (void (*)(void *))felem_one, + felem_is_zero_int, + (void (*)(void *, const void *)) + felem_assign, + (void (*)(void *, const void *)) + felem_square_reduce, (void (*) + (void *, + const void + *, + const void + *)) + felem_mul_reduce, + (void (*)(void *, const void *)) + felem_inv, + (void (*)(void *, const void *)) + felem_contract); +} + +/* + * Computes scalar*generator + \sum scalars[i]*points[i], ignoring NULL + * values Result is stored in r (r can equal one of the inputs). + */ +int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], + const BIGNUM *scalars[], BN_CTX *ctx) +{ + int ret = 0; + int j; + int mixed = 0; + BIGNUM *x, *y, *z, *tmp_scalar; + felem_bytearray g_secret; + felem_bytearray *secrets = NULL; + felem (*pre_comp)[17][3] = NULL; + felem *tmp_felems = NULL; + felem_bytearray tmp; + unsigned i, num_bytes; + int have_pre_comp = 0; + size_t num_points = num; + felem x_in, y_in, z_in, x_out, y_out, z_out; + NISTP521_PRE_COMP *pre = NULL; + felem(*g_pre_comp)[3] = NULL; + EC_POINT *generator = NULL; + const EC_POINT *p = NULL; + const BIGNUM *p_scalar = NULL; + + BN_CTX_start(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + z = BN_CTX_get(ctx); + tmp_scalar = BN_CTX_get(ctx); + if (tmp_scalar == NULL) + goto err; + + if (scalar != NULL) { + pre = group->pre_comp.nistp521; + if (pre) + /* we have precomputation, try to use it */ + g_pre_comp = &pre->g_pre_comp[0]; + else + /* try to use the standard precomputation */ + g_pre_comp = (felem(*)[3]) gmul; + generator = EC_POINT_new(group); + if (generator == NULL) + goto err; + /* get the generator from precomputation */ + if (!felem_to_BN(x, g_pre_comp[1][0]) || + !felem_to_BN(y, g_pre_comp[1][1]) || + !felem_to_BN(z, g_pre_comp[1][2])) { + ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB); + goto err; + } + if (!EC_POINT_set_Jprojective_coordinates_GFp(group, + generator, x, y, z, + ctx)) + goto err; + if (0 == EC_POINT_cmp(group, generator, group->generator, ctx)) + /* precomputation matches generator */ + have_pre_comp = 1; + else + /* + * we don't have valid precomputation: treat the generator as a + * random point + */ + num_points++; + } + + if (num_points > 0) { + if (num_points >= 2) { + /* + * unless we precompute multiples for just one point, converting + * those into affine form is time well spent + */ + mixed = 1; + } + secrets = OPENSSL_zalloc(sizeof(*secrets) * num_points); + pre_comp = OPENSSL_zalloc(sizeof(*pre_comp) * num_points); + if (mixed) + tmp_felems = + OPENSSL_malloc(sizeof(*tmp_felems) * (num_points * 17 + 1)); + if ((secrets == NULL) || (pre_comp == NULL) + || (mixed && (tmp_felems == NULL))) { + ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* + * we treat NULL scalars as 0, and NULL points as points at infinity, + * i.e., they contribute nothing to the linear combination + */ + for (i = 0; i < num_points; ++i) { + if (i == num) + /* + * we didn't have a valid precomputation, so we pick the + * generator + */ + { + p = EC_GROUP_get0_generator(group); + p_scalar = scalar; + } else + /* the i^th point */ + { + p = points[i]; + p_scalar = scalars[i]; + } + if ((p_scalar != NULL) && (p != NULL)) { + /* reduce scalar to 0 <= scalar < 2^521 */ + if ((BN_num_bits(p_scalar) > 521) + || (BN_is_negative(p_scalar))) { + /* + * this is an unusual input, and we don't guarantee + * constant-timeness + */ + if (!BN_nnmod(tmp_scalar, p_scalar, group->order, ctx)) { + ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB); + goto err; + } + num_bytes = BN_bn2bin(tmp_scalar, tmp); + } else + num_bytes = BN_bn2bin(p_scalar, tmp); + flip_endian(secrets[i], tmp, num_bytes); + /* precompute multiples */ + if ((!BN_to_felem(x_out, p->X)) || + (!BN_to_felem(y_out, p->Y)) || + (!BN_to_felem(z_out, p->Z))) + goto err; + memcpy(pre_comp[i][1][0], x_out, sizeof(felem)); + memcpy(pre_comp[i][1][1], y_out, sizeof(felem)); + memcpy(pre_comp[i][1][2], z_out, sizeof(felem)); + for (j = 2; j <= 16; ++j) { + if (j & 1) { + point_add(pre_comp[i][j][0], pre_comp[i][j][1], + pre_comp[i][j][2], pre_comp[i][1][0], + pre_comp[i][1][1], pre_comp[i][1][2], 0, + pre_comp[i][j - 1][0], + pre_comp[i][j - 1][1], + pre_comp[i][j - 1][2]); + } else { + point_double(pre_comp[i][j][0], pre_comp[i][j][1], + pre_comp[i][j][2], pre_comp[i][j / 2][0], + pre_comp[i][j / 2][1], + pre_comp[i][j / 2][2]); + } + } + } + } + if (mixed) + make_points_affine(num_points * 17, pre_comp[0], tmp_felems); + } + + /* the scalar for the generator */ + if ((scalar != NULL) && (have_pre_comp)) { + memset(g_secret, 0, sizeof(g_secret)); + /* reduce scalar to 0 <= scalar < 2^521 */ + if ((BN_num_bits(scalar) > 521) || (BN_is_negative(scalar))) { + /* + * this is an unusual input, and we don't guarantee + * constant-timeness + */ + if (!BN_nnmod(tmp_scalar, scalar, group->order, ctx)) { + ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB); + goto err; + } + num_bytes = BN_bn2bin(tmp_scalar, tmp); + } else + num_bytes = BN_bn2bin(scalar, tmp); + flip_endian(g_secret, tmp, num_bytes); + /* do the multiplication with generator precomputation */ + batch_mul(x_out, y_out, z_out, + (const felem_bytearray(*))secrets, num_points, + g_secret, + mixed, (const felem(*)[17][3])pre_comp, + (const felem(*)[3])g_pre_comp); + } else + /* do the multiplication without generator precomputation */ + batch_mul(x_out, y_out, z_out, + (const felem_bytearray(*))secrets, num_points, + NULL, mixed, (const felem(*)[17][3])pre_comp, NULL); + /* reduce the output to its unique minimal representation */ + felem_contract(x_in, x_out); + felem_contract(y_in, y_out); + felem_contract(z_in, z_out); + if ((!felem_to_BN(x, x_in)) || (!felem_to_BN(y, y_in)) || + (!felem_to_BN(z, z_in))) { + ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB); + goto err; + } + ret = EC_POINT_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx); + + err: + BN_CTX_end(ctx); + EC_POINT_free(generator); + OPENSSL_free(secrets); + OPENSSL_free(pre_comp); + OPENSSL_free(tmp_felems); + return ret; +} + +int ec_GFp_nistp521_precompute_mult(EC_GROUP *group, BN_CTX *ctx) +{ + int ret = 0; + NISTP521_PRE_COMP *pre = NULL; + int i, j; + BN_CTX *new_ctx = NULL; + BIGNUM *x, *y; + EC_POINT *generator = NULL; + felem tmp_felems[16]; + + /* throw away old precomputation */ + EC_pre_comp_free(group); + if (ctx == NULL) + if ((ctx = new_ctx = BN_CTX_new()) == NULL) + return 0; + BN_CTX_start(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (y == NULL) + goto err; + /* get the generator */ + if (group->generator == NULL) + goto err; + generator = EC_POINT_new(group); + if (generator == NULL) + goto err; + BN_bin2bn(nistp521_curve_params[3], sizeof(felem_bytearray), x); + BN_bin2bn(nistp521_curve_params[4], sizeof(felem_bytearray), y); + if (!EC_POINT_set_affine_coordinates(group, generator, x, y, ctx)) + goto err; + if ((pre = nistp521_pre_comp_new()) == NULL) + goto err; + /* + * if the generator is the standard one, use built-in precomputation + */ + if (0 == EC_POINT_cmp(group, generator, group->generator, ctx)) { + memcpy(pre->g_pre_comp, gmul, sizeof(pre->g_pre_comp)); + goto done; + } + if ((!BN_to_felem(pre->g_pre_comp[1][0], group->generator->X)) || + (!BN_to_felem(pre->g_pre_comp[1][1], group->generator->Y)) || + (!BN_to_felem(pre->g_pre_comp[1][2], group->generator->Z))) + goto err; + /* compute 2^130*G, 2^260*G, 2^390*G */ + for (i = 1; i <= 4; i <<= 1) { + point_double(pre->g_pre_comp[2 * i][0], pre->g_pre_comp[2 * i][1], + pre->g_pre_comp[2 * i][2], pre->g_pre_comp[i][0], + pre->g_pre_comp[i][1], pre->g_pre_comp[i][2]); + for (j = 0; j < 129; ++j) { + point_double(pre->g_pre_comp[2 * i][0], + pre->g_pre_comp[2 * i][1], + pre->g_pre_comp[2 * i][2], + pre->g_pre_comp[2 * i][0], + pre->g_pre_comp[2 * i][1], + pre->g_pre_comp[2 * i][2]); + } + } + /* g_pre_comp[0] is the point at infinity */ + memset(pre->g_pre_comp[0], 0, sizeof(pre->g_pre_comp[0])); + /* the remaining multiples */ + /* 2^130*G + 2^260*G */ + point_add(pre->g_pre_comp[6][0], pre->g_pre_comp[6][1], + pre->g_pre_comp[6][2], pre->g_pre_comp[4][0], + pre->g_pre_comp[4][1], pre->g_pre_comp[4][2], + 0, pre->g_pre_comp[2][0], pre->g_pre_comp[2][1], + pre->g_pre_comp[2][2]); + /* 2^130*G + 2^390*G */ + point_add(pre->g_pre_comp[10][0], pre->g_pre_comp[10][1], + pre->g_pre_comp[10][2], pre->g_pre_comp[8][0], + pre->g_pre_comp[8][1], pre->g_pre_comp[8][2], + 0, pre->g_pre_comp[2][0], pre->g_pre_comp[2][1], + pre->g_pre_comp[2][2]); + /* 2^260*G + 2^390*G */ + point_add(pre->g_pre_comp[12][0], pre->g_pre_comp[12][1], + pre->g_pre_comp[12][2], pre->g_pre_comp[8][0], + pre->g_pre_comp[8][1], pre->g_pre_comp[8][2], + 0, pre->g_pre_comp[4][0], pre->g_pre_comp[4][1], + pre->g_pre_comp[4][2]); + /* 2^130*G + 2^260*G + 2^390*G */ + point_add(pre->g_pre_comp[14][0], pre->g_pre_comp[14][1], + pre->g_pre_comp[14][2], pre->g_pre_comp[12][0], + pre->g_pre_comp[12][1], pre->g_pre_comp[12][2], + 0, pre->g_pre_comp[2][0], pre->g_pre_comp[2][1], + pre->g_pre_comp[2][2]); + for (i = 1; i < 8; ++i) { + /* odd multiples: add G */ + point_add(pre->g_pre_comp[2 * i + 1][0], + pre->g_pre_comp[2 * i + 1][1], + pre->g_pre_comp[2 * i + 1][2], pre->g_pre_comp[2 * i][0], + pre->g_pre_comp[2 * i][1], pre->g_pre_comp[2 * i][2], 0, + pre->g_pre_comp[1][0], pre->g_pre_comp[1][1], + pre->g_pre_comp[1][2]); + } + make_points_affine(15, &(pre->g_pre_comp[1]), tmp_felems); + + done: + SETPRECOMP(group, nistp521, pre); + ret = 1; + pre = NULL; + err: + BN_CTX_end(ctx); + EC_POINT_free(generator); + BN_CTX_free(new_ctx); + EC_nistp521_pre_comp_free(pre); + return ret; +} + +int ec_GFp_nistp521_have_precompute_mult(const EC_GROUP *group) +{ + return HAVEPRECOMP(group, nistp521); +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_nistputil.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_nistputil.c new file mode 100644 index 000000000..97fb63100 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_nistputil.c @@ -0,0 +1,223 @@ +/* + * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Copyright 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#ifdef OPENSSL_NO_EC_NISTP_64_GCC_128 +NON_EMPTY_TRANSLATION_UNIT +#else + +/* + * Common utility functions for ecp_nistp224.c, ecp_nistp256.c, ecp_nistp521.c. + */ + +# include +# include "ec_lcl.h" + +/* + * Convert an array of points into affine coordinates. (If the point at + * infinity is found (Z = 0), it remains unchanged.) This function is + * essentially an equivalent to EC_POINTs_make_affine(), but works with the + * internal representation of points as used by ecp_nistp###.c rather than + * with (BIGNUM-based) EC_POINT data structures. point_array is the + * input/output buffer ('num' points in projective form, i.e. three + * coordinates each), based on an internal representation of field elements + * of size 'felem_size'. tmp_felems needs to point to a temporary array of + * 'num'+1 field elements for storage of intermediate values. + */ +void ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array, + size_t felem_size, + void *tmp_felems, + void (*felem_one) (void *out), + int (*felem_is_zero) (const void + *in), + void (*felem_assign) (void *out, + const void + *in), + void (*felem_square) (void *out, + const void + *in), + void (*felem_mul) (void *out, + const void + *in1, + const void + *in2), + void (*felem_inv) (void *out, + const void + *in), + void (*felem_contract) (void + *out, + const + void + *in)) +{ + int i = 0; + +# define tmp_felem(I) (&((char *)tmp_felems)[(I) * felem_size]) +# define X(I) (&((char *)point_array)[3*(I) * felem_size]) +# define Y(I) (&((char *)point_array)[(3*(I) + 1) * felem_size]) +# define Z(I) (&((char *)point_array)[(3*(I) + 2) * felem_size]) + + if (!felem_is_zero(Z(0))) + felem_assign(tmp_felem(0), Z(0)); + else + felem_one(tmp_felem(0)); + for (i = 1; i < (int)num; i++) { + if (!felem_is_zero(Z(i))) + felem_mul(tmp_felem(i), tmp_felem(i - 1), Z(i)); + else + felem_assign(tmp_felem(i), tmp_felem(i - 1)); + } + /* + * Now each tmp_felem(i) is the product of Z(0) .. Z(i), skipping any + * zero-valued factors: if Z(i) = 0, we essentially pretend that Z(i) = 1 + */ + + felem_inv(tmp_felem(num - 1), tmp_felem(num - 1)); + for (i = num - 1; i >= 0; i--) { + if (i > 0) + /* + * tmp_felem(i-1) is the product of Z(0) .. Z(i-1), tmp_felem(i) + * is the inverse of the product of Z(0) .. Z(i) + */ + /* 1/Z(i) */ + felem_mul(tmp_felem(num), tmp_felem(i - 1), tmp_felem(i)); + else + felem_assign(tmp_felem(num), tmp_felem(0)); /* 1/Z(0) */ + + if (!felem_is_zero(Z(i))) { + if (i > 0) + /* + * For next iteration, replace tmp_felem(i-1) by its inverse + */ + felem_mul(tmp_felem(i - 1), tmp_felem(i), Z(i)); + + /* + * Convert point (X, Y, Z) into affine form (X/(Z^2), Y/(Z^3), 1) + */ + felem_square(Z(i), tmp_felem(num)); /* 1/(Z^2) */ + felem_mul(X(i), X(i), Z(i)); /* X/(Z^2) */ + felem_mul(Z(i), Z(i), tmp_felem(num)); /* 1/(Z^3) */ + felem_mul(Y(i), Y(i), Z(i)); /* Y/(Z^3) */ + felem_contract(X(i), X(i)); + felem_contract(Y(i), Y(i)); + felem_one(Z(i)); + } else { + if (i > 0) + /* + * For next iteration, replace tmp_felem(i-1) by its inverse + */ + felem_assign(tmp_felem(i - 1), tmp_felem(i)); + } + } +} + +/*- + * This function looks at 5+1 scalar bits (5 current, 1 adjacent less + * significant bit), and recodes them into a signed digit for use in fast point + * multiplication: the use of signed rather than unsigned digits means that + * fewer points need to be precomputed, given that point inversion is easy + * (a precomputed point dP makes -dP available as well). + * + * BACKGROUND: + * + * Signed digits for multiplication were introduced by Booth ("A signed binary + * multiplication technique", Quart. Journ. Mech. and Applied Math., vol. IV, + * pt. 2 (1951), pp. 236-240), in that case for multiplication of integers. + * Booth's original encoding did not generally improve the density of nonzero + * digits over the binary representation, and was merely meant to simplify the + * handling of signed factors given in two's complement; but it has since been + * shown to be the basis of various signed-digit representations that do have + * further advantages, including the wNAF, using the following general approach: + * + * (1) Given a binary representation + * + * b_k ... b_2 b_1 b_0, + * + * of a nonnegative integer (b_k in {0, 1}), rewrite it in digits 0, 1, -1 + * by using bit-wise subtraction as follows: + * + * b_k b_(k-1) ... b_2 b_1 b_0 + * - b_k ... b_3 b_2 b_1 b_0 + * ------------------------------------- + * s_k b_(k-1) ... s_3 s_2 s_1 s_0 + * + * A left-shift followed by subtraction of the original value yields a new + * representation of the same value, using signed bits s_i = b_(i+1) - b_i. + * This representation from Booth's paper has since appeared in the + * literature under a variety of different names including "reversed binary + * form", "alternating greedy expansion", "mutual opposite form", and + * "sign-alternating {+-1}-representation". + * + * An interesting property is that among the nonzero bits, values 1 and -1 + * strictly alternate. + * + * (2) Various window schemes can be applied to the Booth representation of + * integers: for example, right-to-left sliding windows yield the wNAF + * (a signed-digit encoding independently discovered by various researchers + * in the 1990s), and left-to-right sliding windows yield a left-to-right + * equivalent of the wNAF (independently discovered by various researchers + * around 2004). + * + * To prevent leaking information through side channels in point multiplication, + * we need to recode the given integer into a regular pattern: sliding windows + * as in wNAFs won't do, we need their fixed-window equivalent -- which is a few + * decades older: we'll be using the so-called "modified Booth encoding" due to + * MacSorley ("High-speed arithmetic in binary computers", Proc. IRE, vol. 49 + * (1961), pp. 67-91), in a radix-2^5 setting. That is, we always combine five + * signed bits into a signed digit: + * + * s_(4j + 4) s_(4j + 3) s_(4j + 2) s_(4j + 1) s_(4j) + * + * The sign-alternating property implies that the resulting digit values are + * integers from -16 to 16. + * + * Of course, we don't actually need to compute the signed digits s_i as an + * intermediate step (that's just a nice way to see how this scheme relates + * to the wNAF): a direct computation obtains the recoded digit from the + * six bits b_(4j + 4) ... b_(4j - 1). + * + * This function takes those five bits as an integer (0 .. 63), writing the + * recoded digit to *sign (0 for positive, 1 for negative) and *digit (absolute + * value, in the range 0 .. 8). Note that this integer essentially provides the + * input bits "shifted to the left" by one position: for example, the input to + * compute the least significant recoded digit, given that there's no bit b_-1, + * has to be b_4 b_3 b_2 b_1 b_0 0. + * + */ +void ec_GFp_nistp_recode_scalar_bits(unsigned char *sign, + unsigned char *digit, unsigned char in) +{ + unsigned char s, d; + + s = ~((in >> 5) - 1); /* sets all bits to MSB(in), 'in' seen as + * 6-bit value */ + d = (1 << 6) - in - 1; + d = (d & s) | (in & ~s); + d = (d >> 1) + (d & 1); + + *sign = s & 1; + *digit = d; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_nistz256.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_nistz256.c new file mode 100644 index 000000000..aea639416 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_nistz256.c @@ -0,0 +1,1701 @@ +/* + * Copyright 2014-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2014, Intel Corporation. All Rights Reserved. + * Copyright (c) 2015, CloudFlare, Inc. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + * + * Originally written by Shay Gueron (1, 2), and Vlad Krasnov (1, 3) + * (1) Intel Corporation, Israel Development Center, Haifa, Israel + * (2) University of Haifa, Israel + * (3) CloudFlare, Inc. + * + * Reference: + * S.Gueron and V.Krasnov, "Fast Prime Field Elliptic Curve Cryptography with + * 256 Bit Primes" + */ + +#include + +#include "internal/cryptlib.h" +#include "internal/bn_int.h" +#include "ec_lcl.h" +#include "internal/refcount.h" + +#if BN_BITS2 != 64 +# define TOBN(hi,lo) lo,hi +#else +# define TOBN(hi,lo) ((BN_ULONG)hi<<32|lo) +#endif + +#if defined(__GNUC__) +# define ALIGN32 __attribute((aligned(32))) +#elif defined(_MSC_VER) +# define ALIGN32 __declspec(align(32)) +#else +# define ALIGN32 +#endif + +#define ALIGNPTR(p,N) ((unsigned char *)p+N-(size_t)p%N) +#define P256_LIMBS (256/BN_BITS2) + +typedef unsigned short u16; + +typedef struct { + BN_ULONG X[P256_LIMBS]; + BN_ULONG Y[P256_LIMBS]; + BN_ULONG Z[P256_LIMBS]; +} P256_POINT; + +typedef struct { + BN_ULONG X[P256_LIMBS]; + BN_ULONG Y[P256_LIMBS]; +} P256_POINT_AFFINE; + +typedef P256_POINT_AFFINE PRECOMP256_ROW[64]; + +/* structure for precomputed multiples of the generator */ +struct nistz256_pre_comp_st { + const EC_GROUP *group; /* Parent EC_GROUP object */ + size_t w; /* Window size */ + /* + * Constant time access to the X and Y coordinates of the pre-computed, + * generator multiplies, in the Montgomery domain. Pre-calculated + * multiplies are stored in affine form. + */ + PRECOMP256_ROW *precomp; + void *precomp_storage; + CRYPTO_REF_COUNT references; + CRYPTO_RWLOCK *lock; +}; + +/* Functions implemented in assembly */ +/* + * Most of below mentioned functions *preserve* the property of inputs + * being fully reduced, i.e. being in [0, modulus) range. Simply put if + * inputs are fully reduced, then output is too. Note that reverse is + * not true, in sense that given partially reduced inputs output can be + * either, not unlikely reduced. And "most" in first sentence refers to + * the fact that given the calculations flow one can tolerate that + * addition, 1st function below, produces partially reduced result *if* + * multiplications by 2 and 3, which customarily use addition, fully + * reduce it. This effectively gives two options: a) addition produces + * fully reduced result [as long as inputs are, just like remaining + * functions]; b) addition is allowed to produce partially reduced + * result, but multiplications by 2 and 3 perform additional reduction + * step. Choice between the two can be platform-specific, but it was a) + * in all cases so far... + */ +/* Modular add: res = a+b mod P */ +void ecp_nistz256_add(BN_ULONG res[P256_LIMBS], + const BN_ULONG a[P256_LIMBS], + const BN_ULONG b[P256_LIMBS]); +/* Modular mul by 2: res = 2*a mod P */ +void ecp_nistz256_mul_by_2(BN_ULONG res[P256_LIMBS], + const BN_ULONG a[P256_LIMBS]); +/* Modular mul by 3: res = 3*a mod P */ +void ecp_nistz256_mul_by_3(BN_ULONG res[P256_LIMBS], + const BN_ULONG a[P256_LIMBS]); + +/* Modular div by 2: res = a/2 mod P */ +void ecp_nistz256_div_by_2(BN_ULONG res[P256_LIMBS], + const BN_ULONG a[P256_LIMBS]); +/* Modular sub: res = a-b mod P */ +void ecp_nistz256_sub(BN_ULONG res[P256_LIMBS], + const BN_ULONG a[P256_LIMBS], + const BN_ULONG b[P256_LIMBS]); +/* Modular neg: res = -a mod P */ +void ecp_nistz256_neg(BN_ULONG res[P256_LIMBS], const BN_ULONG a[P256_LIMBS]); +/* Montgomery mul: res = a*b*2^-256 mod P */ +void ecp_nistz256_mul_mont(BN_ULONG res[P256_LIMBS], + const BN_ULONG a[P256_LIMBS], + const BN_ULONG b[P256_LIMBS]); +/* Montgomery sqr: res = a*a*2^-256 mod P */ +void ecp_nistz256_sqr_mont(BN_ULONG res[P256_LIMBS], + const BN_ULONG a[P256_LIMBS]); +/* Convert a number from Montgomery domain, by multiplying with 1 */ +void ecp_nistz256_from_mont(BN_ULONG res[P256_LIMBS], + const BN_ULONG in[P256_LIMBS]); +/* Convert a number to Montgomery domain, by multiplying with 2^512 mod P*/ +void ecp_nistz256_to_mont(BN_ULONG res[P256_LIMBS], + const BN_ULONG in[P256_LIMBS]); +/* Functions that perform constant time access to the precomputed tables */ +void ecp_nistz256_scatter_w5(P256_POINT *val, + const P256_POINT *in_t, int idx); +void ecp_nistz256_gather_w5(P256_POINT *val, + const P256_POINT *in_t, int idx); +void ecp_nistz256_scatter_w7(P256_POINT_AFFINE *val, + const P256_POINT_AFFINE *in_t, int idx); +void ecp_nistz256_gather_w7(P256_POINT_AFFINE *val, + const P256_POINT_AFFINE *in_t, int idx); + +/* One converted into the Montgomery domain */ +static const BN_ULONG ONE[P256_LIMBS] = { + TOBN(0x00000000, 0x00000001), TOBN(0xffffffff, 0x00000000), + TOBN(0xffffffff, 0xffffffff), TOBN(0x00000000, 0xfffffffe) +}; + +static NISTZ256_PRE_COMP *ecp_nistz256_pre_comp_new(const EC_GROUP *group); + +/* Precomputed tables for the default generator */ +extern const PRECOMP256_ROW ecp_nistz256_precomputed[37]; + +/* Recode window to a signed digit, see ecp_nistputil.c for details */ +static unsigned int _booth_recode_w5(unsigned int in) +{ + unsigned int s, d; + + s = ~((in >> 5) - 1); + d = (1 << 6) - in - 1; + d = (d & s) | (in & ~s); + d = (d >> 1) + (d & 1); + + return (d << 1) + (s & 1); +} + +static unsigned int _booth_recode_w7(unsigned int in) +{ + unsigned int s, d; + + s = ~((in >> 7) - 1); + d = (1 << 8) - in - 1; + d = (d & s) | (in & ~s); + d = (d >> 1) + (d & 1); + + return (d << 1) + (s & 1); +} + +static void copy_conditional(BN_ULONG dst[P256_LIMBS], + const BN_ULONG src[P256_LIMBS], BN_ULONG move) +{ + BN_ULONG mask1 = 0-move; + BN_ULONG mask2 = ~mask1; + + dst[0] = (src[0] & mask1) ^ (dst[0] & mask2); + dst[1] = (src[1] & mask1) ^ (dst[1] & mask2); + dst[2] = (src[2] & mask1) ^ (dst[2] & mask2); + dst[3] = (src[3] & mask1) ^ (dst[3] & mask2); + if (P256_LIMBS == 8) { + dst[4] = (src[4] & mask1) ^ (dst[4] & mask2); + dst[5] = (src[5] & mask1) ^ (dst[5] & mask2); + dst[6] = (src[6] & mask1) ^ (dst[6] & mask2); + dst[7] = (src[7] & mask1) ^ (dst[7] & mask2); + } +} + +static BN_ULONG is_zero(BN_ULONG in) +{ + in |= (0 - in); + in = ~in; + in >>= BN_BITS2 - 1; + return in; +} + +static BN_ULONG is_equal(const BN_ULONG a[P256_LIMBS], + const BN_ULONG b[P256_LIMBS]) +{ + BN_ULONG res; + + res = a[0] ^ b[0]; + res |= a[1] ^ b[1]; + res |= a[2] ^ b[2]; + res |= a[3] ^ b[3]; + if (P256_LIMBS == 8) { + res |= a[4] ^ b[4]; + res |= a[5] ^ b[5]; + res |= a[6] ^ b[6]; + res |= a[7] ^ b[7]; + } + + return is_zero(res); +} + +static BN_ULONG is_one(const BIGNUM *z) +{ + BN_ULONG res = 0; + BN_ULONG *a = bn_get_words(z); + + if (bn_get_top(z) == (P256_LIMBS - P256_LIMBS / 8)) { + res = a[0] ^ ONE[0]; + res |= a[1] ^ ONE[1]; + res |= a[2] ^ ONE[2]; + res |= a[3] ^ ONE[3]; + if (P256_LIMBS == 8) { + res |= a[4] ^ ONE[4]; + res |= a[5] ^ ONE[5]; + res |= a[6] ^ ONE[6]; + /* + * no check for a[7] (being zero) on 32-bit platforms, + * because value of "one" takes only 7 limbs. + */ + } + res = is_zero(res); + } + + return res; +} + +/* + * For reference, this macro is used only when new ecp_nistz256 assembly + * module is being developed. For example, configure with + * -DECP_NISTZ256_REFERENCE_IMPLEMENTATION and implement only functions + * performing simplest arithmetic operations on 256-bit vectors. Then + * work on implementation of higher-level functions performing point + * operations. Then remove ECP_NISTZ256_REFERENCE_IMPLEMENTATION + * and never define it again. (The correct macro denoting presence of + * ecp_nistz256 module is ECP_NISTZ256_ASM.) + */ +#ifndef ECP_NISTZ256_REFERENCE_IMPLEMENTATION +void ecp_nistz256_point_double(P256_POINT *r, const P256_POINT *a); +void ecp_nistz256_point_add(P256_POINT *r, + const P256_POINT *a, const P256_POINT *b); +void ecp_nistz256_point_add_affine(P256_POINT *r, + const P256_POINT *a, + const P256_POINT_AFFINE *b); +#else +/* Point double: r = 2*a */ +static void ecp_nistz256_point_double(P256_POINT *r, const P256_POINT *a) +{ + BN_ULONG S[P256_LIMBS]; + BN_ULONG M[P256_LIMBS]; + BN_ULONG Zsqr[P256_LIMBS]; + BN_ULONG tmp0[P256_LIMBS]; + + const BN_ULONG *in_x = a->X; + const BN_ULONG *in_y = a->Y; + const BN_ULONG *in_z = a->Z; + + BN_ULONG *res_x = r->X; + BN_ULONG *res_y = r->Y; + BN_ULONG *res_z = r->Z; + + ecp_nistz256_mul_by_2(S, in_y); + + ecp_nistz256_sqr_mont(Zsqr, in_z); + + ecp_nistz256_sqr_mont(S, S); + + ecp_nistz256_mul_mont(res_z, in_z, in_y); + ecp_nistz256_mul_by_2(res_z, res_z); + + ecp_nistz256_add(M, in_x, Zsqr); + ecp_nistz256_sub(Zsqr, in_x, Zsqr); + + ecp_nistz256_sqr_mont(res_y, S); + ecp_nistz256_div_by_2(res_y, res_y); + + ecp_nistz256_mul_mont(M, M, Zsqr); + ecp_nistz256_mul_by_3(M, M); + + ecp_nistz256_mul_mont(S, S, in_x); + ecp_nistz256_mul_by_2(tmp0, S); + + ecp_nistz256_sqr_mont(res_x, M); + + ecp_nistz256_sub(res_x, res_x, tmp0); + ecp_nistz256_sub(S, S, res_x); + + ecp_nistz256_mul_mont(S, S, M); + ecp_nistz256_sub(res_y, S, res_y); +} + +/* Point addition: r = a+b */ +static void ecp_nistz256_point_add(P256_POINT *r, + const P256_POINT *a, const P256_POINT *b) +{ + BN_ULONG U2[P256_LIMBS], S2[P256_LIMBS]; + BN_ULONG U1[P256_LIMBS], S1[P256_LIMBS]; + BN_ULONG Z1sqr[P256_LIMBS]; + BN_ULONG Z2sqr[P256_LIMBS]; + BN_ULONG H[P256_LIMBS], R[P256_LIMBS]; + BN_ULONG Hsqr[P256_LIMBS]; + BN_ULONG Rsqr[P256_LIMBS]; + BN_ULONG Hcub[P256_LIMBS]; + + BN_ULONG res_x[P256_LIMBS]; + BN_ULONG res_y[P256_LIMBS]; + BN_ULONG res_z[P256_LIMBS]; + + BN_ULONG in1infty, in2infty; + + const BN_ULONG *in1_x = a->X; + const BN_ULONG *in1_y = a->Y; + const BN_ULONG *in1_z = a->Z; + + const BN_ULONG *in2_x = b->X; + const BN_ULONG *in2_y = b->Y; + const BN_ULONG *in2_z = b->Z; + + /* + * Infinity in encoded as (,,0) + */ + in1infty = (in1_z[0] | in1_z[1] | in1_z[2] | in1_z[3]); + if (P256_LIMBS == 8) + in1infty |= (in1_z[4] | in1_z[5] | in1_z[6] | in1_z[7]); + + in2infty = (in2_z[0] | in2_z[1] | in2_z[2] | in2_z[3]); + if (P256_LIMBS == 8) + in2infty |= (in2_z[4] | in2_z[5] | in2_z[6] | in2_z[7]); + + in1infty = is_zero(in1infty); + in2infty = is_zero(in2infty); + + ecp_nistz256_sqr_mont(Z2sqr, in2_z); /* Z2^2 */ + ecp_nistz256_sqr_mont(Z1sqr, in1_z); /* Z1^2 */ + + ecp_nistz256_mul_mont(S1, Z2sqr, in2_z); /* S1 = Z2^3 */ + ecp_nistz256_mul_mont(S2, Z1sqr, in1_z); /* S2 = Z1^3 */ + + ecp_nistz256_mul_mont(S1, S1, in1_y); /* S1 = Y1*Z2^3 */ + ecp_nistz256_mul_mont(S2, S2, in2_y); /* S2 = Y2*Z1^3 */ + ecp_nistz256_sub(R, S2, S1); /* R = S2 - S1 */ + + ecp_nistz256_mul_mont(U1, in1_x, Z2sqr); /* U1 = X1*Z2^2 */ + ecp_nistz256_mul_mont(U2, in2_x, Z1sqr); /* U2 = X2*Z1^2 */ + ecp_nistz256_sub(H, U2, U1); /* H = U2 - U1 */ + + /* + * This should not happen during sign/ecdh, so no constant time violation + */ + if (is_equal(U1, U2) && !in1infty && !in2infty) { + if (is_equal(S1, S2)) { + ecp_nistz256_point_double(r, a); + return; + } else { + memset(r, 0, sizeof(*r)); + return; + } + } + + ecp_nistz256_sqr_mont(Rsqr, R); /* R^2 */ + ecp_nistz256_mul_mont(res_z, H, in1_z); /* Z3 = H*Z1*Z2 */ + ecp_nistz256_sqr_mont(Hsqr, H); /* H^2 */ + ecp_nistz256_mul_mont(res_z, res_z, in2_z); /* Z3 = H*Z1*Z2 */ + ecp_nistz256_mul_mont(Hcub, Hsqr, H); /* H^3 */ + + ecp_nistz256_mul_mont(U2, U1, Hsqr); /* U1*H^2 */ + ecp_nistz256_mul_by_2(Hsqr, U2); /* 2*U1*H^2 */ + + ecp_nistz256_sub(res_x, Rsqr, Hsqr); + ecp_nistz256_sub(res_x, res_x, Hcub); + + ecp_nistz256_sub(res_y, U2, res_x); + + ecp_nistz256_mul_mont(S2, S1, Hcub); + ecp_nistz256_mul_mont(res_y, R, res_y); + ecp_nistz256_sub(res_y, res_y, S2); + + copy_conditional(res_x, in2_x, in1infty); + copy_conditional(res_y, in2_y, in1infty); + copy_conditional(res_z, in2_z, in1infty); + + copy_conditional(res_x, in1_x, in2infty); + copy_conditional(res_y, in1_y, in2infty); + copy_conditional(res_z, in1_z, in2infty); + + memcpy(r->X, res_x, sizeof(res_x)); + memcpy(r->Y, res_y, sizeof(res_y)); + memcpy(r->Z, res_z, sizeof(res_z)); +} + +/* Point addition when b is known to be affine: r = a+b */ +static void ecp_nistz256_point_add_affine(P256_POINT *r, + const P256_POINT *a, + const P256_POINT_AFFINE *b) +{ + BN_ULONG U2[P256_LIMBS], S2[P256_LIMBS]; + BN_ULONG Z1sqr[P256_LIMBS]; + BN_ULONG H[P256_LIMBS], R[P256_LIMBS]; + BN_ULONG Hsqr[P256_LIMBS]; + BN_ULONG Rsqr[P256_LIMBS]; + BN_ULONG Hcub[P256_LIMBS]; + + BN_ULONG res_x[P256_LIMBS]; + BN_ULONG res_y[P256_LIMBS]; + BN_ULONG res_z[P256_LIMBS]; + + BN_ULONG in1infty, in2infty; + + const BN_ULONG *in1_x = a->X; + const BN_ULONG *in1_y = a->Y; + const BN_ULONG *in1_z = a->Z; + + const BN_ULONG *in2_x = b->X; + const BN_ULONG *in2_y = b->Y; + + /* + * Infinity in encoded as (,,0) + */ + in1infty = (in1_z[0] | in1_z[1] | in1_z[2] | in1_z[3]); + if (P256_LIMBS == 8) + in1infty |= (in1_z[4] | in1_z[5] | in1_z[6] | in1_z[7]); + + /* + * In affine representation we encode infinity as (0,0), which is + * not on the curve, so it is OK + */ + in2infty = (in2_x[0] | in2_x[1] | in2_x[2] | in2_x[3] | + in2_y[0] | in2_y[1] | in2_y[2] | in2_y[3]); + if (P256_LIMBS == 8) + in2infty |= (in2_x[4] | in2_x[5] | in2_x[6] | in2_x[7] | + in2_y[4] | in2_y[5] | in2_y[6] | in2_y[7]); + + in1infty = is_zero(in1infty); + in2infty = is_zero(in2infty); + + ecp_nistz256_sqr_mont(Z1sqr, in1_z); /* Z1^2 */ + + ecp_nistz256_mul_mont(U2, in2_x, Z1sqr); /* U2 = X2*Z1^2 */ + ecp_nistz256_sub(H, U2, in1_x); /* H = U2 - U1 */ + + ecp_nistz256_mul_mont(S2, Z1sqr, in1_z); /* S2 = Z1^3 */ + + ecp_nistz256_mul_mont(res_z, H, in1_z); /* Z3 = H*Z1*Z2 */ + + ecp_nistz256_mul_mont(S2, S2, in2_y); /* S2 = Y2*Z1^3 */ + ecp_nistz256_sub(R, S2, in1_y); /* R = S2 - S1 */ + + ecp_nistz256_sqr_mont(Hsqr, H); /* H^2 */ + ecp_nistz256_sqr_mont(Rsqr, R); /* R^2 */ + ecp_nistz256_mul_mont(Hcub, Hsqr, H); /* H^3 */ + + ecp_nistz256_mul_mont(U2, in1_x, Hsqr); /* U1*H^2 */ + ecp_nistz256_mul_by_2(Hsqr, U2); /* 2*U1*H^2 */ + + ecp_nistz256_sub(res_x, Rsqr, Hsqr); + ecp_nistz256_sub(res_x, res_x, Hcub); + ecp_nistz256_sub(H, U2, res_x); + + ecp_nistz256_mul_mont(S2, in1_y, Hcub); + ecp_nistz256_mul_mont(H, H, R); + ecp_nistz256_sub(res_y, H, S2); + + copy_conditional(res_x, in2_x, in1infty); + copy_conditional(res_x, in1_x, in2infty); + + copy_conditional(res_y, in2_y, in1infty); + copy_conditional(res_y, in1_y, in2infty); + + copy_conditional(res_z, ONE, in1infty); + copy_conditional(res_z, in1_z, in2infty); + + memcpy(r->X, res_x, sizeof(res_x)); + memcpy(r->Y, res_y, sizeof(res_y)); + memcpy(r->Z, res_z, sizeof(res_z)); +} +#endif + +/* r = in^-1 mod p */ +static void ecp_nistz256_mod_inverse(BN_ULONG r[P256_LIMBS], + const BN_ULONG in[P256_LIMBS]) +{ + /* + * The poly is ffffffff 00000001 00000000 00000000 00000000 ffffffff + * ffffffff ffffffff We use FLT and used poly-2 as exponent + */ + BN_ULONG p2[P256_LIMBS]; + BN_ULONG p4[P256_LIMBS]; + BN_ULONG p8[P256_LIMBS]; + BN_ULONG p16[P256_LIMBS]; + BN_ULONG p32[P256_LIMBS]; + BN_ULONG res[P256_LIMBS]; + int i; + + ecp_nistz256_sqr_mont(res, in); + ecp_nistz256_mul_mont(p2, res, in); /* 3*p */ + + ecp_nistz256_sqr_mont(res, p2); + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_mul_mont(p4, res, p2); /* f*p */ + + ecp_nistz256_sqr_mont(res, p4); + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_mul_mont(p8, res, p4); /* ff*p */ + + ecp_nistz256_sqr_mont(res, p8); + for (i = 0; i < 7; i++) + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_mul_mont(p16, res, p8); /* ffff*p */ + + ecp_nistz256_sqr_mont(res, p16); + for (i = 0; i < 15; i++) + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_mul_mont(p32, res, p16); /* ffffffff*p */ + + ecp_nistz256_sqr_mont(res, p32); + for (i = 0; i < 31; i++) + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_mul_mont(res, res, in); + + for (i = 0; i < 32 * 4; i++) + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_mul_mont(res, res, p32); + + for (i = 0; i < 32; i++) + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_mul_mont(res, res, p32); + + for (i = 0; i < 16; i++) + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_mul_mont(res, res, p16); + + for (i = 0; i < 8; i++) + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_mul_mont(res, res, p8); + + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_mul_mont(res, res, p4); + + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_mul_mont(res, res, p2); + + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_sqr_mont(res, res); + ecp_nistz256_mul_mont(res, res, in); + + memcpy(r, res, sizeof(res)); +} + +/* + * ecp_nistz256_bignum_to_field_elem copies the contents of |in| to |out| and + * returns one if it fits. Otherwise it returns zero. + */ +__owur static int ecp_nistz256_bignum_to_field_elem(BN_ULONG out[P256_LIMBS], + const BIGNUM *in) +{ + return bn_copy_words(out, in, P256_LIMBS); +} + +/* r = sum(scalar[i]*point[i]) */ +__owur static int ecp_nistz256_windowed_mul(const EC_GROUP *group, + P256_POINT *r, + const BIGNUM **scalar, + const EC_POINT **point, + size_t num, BN_CTX *ctx) +{ + size_t i; + int j, ret = 0; + unsigned int idx; + unsigned char (*p_str)[33] = NULL; + const unsigned int window_size = 5; + const unsigned int mask = (1 << (window_size + 1)) - 1; + unsigned int wvalue; + P256_POINT *temp; /* place for 5 temporary points */ + const BIGNUM **scalars = NULL; + P256_POINT (*table)[16] = NULL; + void *table_storage = NULL; + + if ((num * 16 + 6) > OPENSSL_MALLOC_MAX_NELEMS(P256_POINT) + || (table_storage = + OPENSSL_malloc((num * 16 + 5) * sizeof(P256_POINT) + 64)) == NULL + || (p_str = + OPENSSL_malloc(num * 33 * sizeof(unsigned char))) == NULL + || (scalars = OPENSSL_malloc(num * sizeof(BIGNUM *))) == NULL) { + ECerr(EC_F_ECP_NISTZ256_WINDOWED_MUL, ERR_R_MALLOC_FAILURE); + goto err; + } + + table = (void *)ALIGNPTR(table_storage, 64); + temp = (P256_POINT *)(table + num); + + for (i = 0; i < num; i++) { + P256_POINT *row = table[i]; + + /* This is an unusual input, we don't guarantee constant-timeness. */ + if ((BN_num_bits(scalar[i]) > 256) || BN_is_negative(scalar[i])) { + BIGNUM *mod; + + if ((mod = BN_CTX_get(ctx)) == NULL) + goto err; + if (!BN_nnmod(mod, scalar[i], group->order, ctx)) { + ECerr(EC_F_ECP_NISTZ256_WINDOWED_MUL, ERR_R_BN_LIB); + goto err; + } + scalars[i] = mod; + } else + scalars[i] = scalar[i]; + + for (j = 0; j < bn_get_top(scalars[i]) * BN_BYTES; j += BN_BYTES) { + BN_ULONG d = bn_get_words(scalars[i])[j / BN_BYTES]; + + p_str[i][j + 0] = (unsigned char)d; + p_str[i][j + 1] = (unsigned char)(d >> 8); + p_str[i][j + 2] = (unsigned char)(d >> 16); + p_str[i][j + 3] = (unsigned char)(d >>= 24); + if (BN_BYTES == 8) { + d >>= 8; + p_str[i][j + 4] = (unsigned char)d; + p_str[i][j + 5] = (unsigned char)(d >> 8); + p_str[i][j + 6] = (unsigned char)(d >> 16); + p_str[i][j + 7] = (unsigned char)(d >> 24); + } + } + for (; j < 33; j++) + p_str[i][j] = 0; + + if (!ecp_nistz256_bignum_to_field_elem(temp[0].X, point[i]->X) + || !ecp_nistz256_bignum_to_field_elem(temp[0].Y, point[i]->Y) + || !ecp_nistz256_bignum_to_field_elem(temp[0].Z, point[i]->Z)) { + ECerr(EC_F_ECP_NISTZ256_WINDOWED_MUL, + EC_R_COORDINATES_OUT_OF_RANGE); + goto err; + } + + /* + * row[0] is implicitly (0,0,0) (the point at infinity), therefore it + * is not stored. All other values are actually stored with an offset + * of -1 in table. + */ + + ecp_nistz256_scatter_w5 (row, &temp[0], 1); + ecp_nistz256_point_double(&temp[1], &temp[0]); /*1+1=2 */ + ecp_nistz256_scatter_w5 (row, &temp[1], 2); + ecp_nistz256_point_add (&temp[2], &temp[1], &temp[0]); /*2+1=3 */ + ecp_nistz256_scatter_w5 (row, &temp[2], 3); + ecp_nistz256_point_double(&temp[1], &temp[1]); /*2*2=4 */ + ecp_nistz256_scatter_w5 (row, &temp[1], 4); + ecp_nistz256_point_double(&temp[2], &temp[2]); /*2*3=6 */ + ecp_nistz256_scatter_w5 (row, &temp[2], 6); + ecp_nistz256_point_add (&temp[3], &temp[1], &temp[0]); /*4+1=5 */ + ecp_nistz256_scatter_w5 (row, &temp[3], 5); + ecp_nistz256_point_add (&temp[4], &temp[2], &temp[0]); /*6+1=7 */ + ecp_nistz256_scatter_w5 (row, &temp[4], 7); + ecp_nistz256_point_double(&temp[1], &temp[1]); /*2*4=8 */ + ecp_nistz256_scatter_w5 (row, &temp[1], 8); + ecp_nistz256_point_double(&temp[2], &temp[2]); /*2*6=12 */ + ecp_nistz256_scatter_w5 (row, &temp[2], 12); + ecp_nistz256_point_double(&temp[3], &temp[3]); /*2*5=10 */ + ecp_nistz256_scatter_w5 (row, &temp[3], 10); + ecp_nistz256_point_double(&temp[4], &temp[4]); /*2*7=14 */ + ecp_nistz256_scatter_w5 (row, &temp[4], 14); + ecp_nistz256_point_add (&temp[2], &temp[2], &temp[0]); /*12+1=13*/ + ecp_nistz256_scatter_w5 (row, &temp[2], 13); + ecp_nistz256_point_add (&temp[3], &temp[3], &temp[0]); /*10+1=11*/ + ecp_nistz256_scatter_w5 (row, &temp[3], 11); + ecp_nistz256_point_add (&temp[4], &temp[4], &temp[0]); /*14+1=15*/ + ecp_nistz256_scatter_w5 (row, &temp[4], 15); + ecp_nistz256_point_add (&temp[2], &temp[1], &temp[0]); /*8+1=9 */ + ecp_nistz256_scatter_w5 (row, &temp[2], 9); + ecp_nistz256_point_double(&temp[1], &temp[1]); /*2*8=16 */ + ecp_nistz256_scatter_w5 (row, &temp[1], 16); + } + + idx = 255; + + wvalue = p_str[0][(idx - 1) / 8]; + wvalue = (wvalue >> ((idx - 1) % 8)) & mask; + + /* + * We gather to temp[0], because we know it's position relative + * to table + */ + ecp_nistz256_gather_w5(&temp[0], table[0], _booth_recode_w5(wvalue) >> 1); + memcpy(r, &temp[0], sizeof(temp[0])); + + while (idx >= 5) { + for (i = (idx == 255 ? 1 : 0); i < num; i++) { + unsigned int off = (idx - 1) / 8; + + wvalue = p_str[i][off] | p_str[i][off + 1] << 8; + wvalue = (wvalue >> ((idx - 1) % 8)) & mask; + + wvalue = _booth_recode_w5(wvalue); + + ecp_nistz256_gather_w5(&temp[0], table[i], wvalue >> 1); + + ecp_nistz256_neg(temp[1].Y, temp[0].Y); + copy_conditional(temp[0].Y, temp[1].Y, (wvalue & 1)); + + ecp_nistz256_point_add(r, r, &temp[0]); + } + + idx -= window_size; + + ecp_nistz256_point_double(r, r); + ecp_nistz256_point_double(r, r); + ecp_nistz256_point_double(r, r); + ecp_nistz256_point_double(r, r); + ecp_nistz256_point_double(r, r); + } + + /* Final window */ + for (i = 0; i < num; i++) { + wvalue = p_str[i][0]; + wvalue = (wvalue << 1) & mask; + + wvalue = _booth_recode_w5(wvalue); + + ecp_nistz256_gather_w5(&temp[0], table[i], wvalue >> 1); + + ecp_nistz256_neg(temp[1].Y, temp[0].Y); + copy_conditional(temp[0].Y, temp[1].Y, wvalue & 1); + + ecp_nistz256_point_add(r, r, &temp[0]); + } + + ret = 1; + err: + OPENSSL_free(table_storage); + OPENSSL_free(p_str); + OPENSSL_free(scalars); + return ret; +} + +/* Coordinates of G, for which we have precomputed tables */ +static const BN_ULONG def_xG[P256_LIMBS] = { + TOBN(0x79e730d4, 0x18a9143c), TOBN(0x75ba95fc, 0x5fedb601), + TOBN(0x79fb732b, 0x77622510), TOBN(0x18905f76, 0xa53755c6) +}; + +static const BN_ULONG def_yG[P256_LIMBS] = { + TOBN(0xddf25357, 0xce95560a), TOBN(0x8b4ab8e4, 0xba19e45c), + TOBN(0xd2e88688, 0xdd21f325), TOBN(0x8571ff18, 0x25885d85) +}; + +/* + * ecp_nistz256_is_affine_G returns one if |generator| is the standard, P-256 + * generator. + */ +static int ecp_nistz256_is_affine_G(const EC_POINT *generator) +{ + return (bn_get_top(generator->X) == P256_LIMBS) && + (bn_get_top(generator->Y) == P256_LIMBS) && + is_equal(bn_get_words(generator->X), def_xG) && + is_equal(bn_get_words(generator->Y), def_yG) && + is_one(generator->Z); +} + +__owur static int ecp_nistz256_mult_precompute(EC_GROUP *group, BN_CTX *ctx) +{ + /* + * We precompute a table for a Booth encoded exponent (wNAF) based + * computation. Each table holds 64 values for safe access, with an + * implicit value of infinity at index zero. We use window of size 7, and + * therefore require ceil(256/7) = 37 tables. + */ + const BIGNUM *order; + EC_POINT *P = NULL, *T = NULL; + const EC_POINT *generator; + NISTZ256_PRE_COMP *pre_comp; + BN_CTX *new_ctx = NULL; + int i, j, k, ret = 0; + size_t w; + + PRECOMP256_ROW *preComputedTable = NULL; + unsigned char *precomp_storage = NULL; + + /* if there is an old NISTZ256_PRE_COMP object, throw it away */ + EC_pre_comp_free(group); + generator = EC_GROUP_get0_generator(group); + if (generator == NULL) { + ECerr(EC_F_ECP_NISTZ256_MULT_PRECOMPUTE, EC_R_UNDEFINED_GENERATOR); + return 0; + } + + if (ecp_nistz256_is_affine_G(generator)) { + /* + * No need to calculate tables for the standard generator because we + * have them statically. + */ + return 1; + } + + if ((pre_comp = ecp_nistz256_pre_comp_new(group)) == NULL) + return 0; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + goto err; + } + + BN_CTX_start(ctx); + + order = EC_GROUP_get0_order(group); + if (order == NULL) + goto err; + + if (BN_is_zero(order)) { + ECerr(EC_F_ECP_NISTZ256_MULT_PRECOMPUTE, EC_R_UNKNOWN_ORDER); + goto err; + } + + w = 7; + + if ((precomp_storage = + OPENSSL_malloc(37 * 64 * sizeof(P256_POINT_AFFINE) + 64)) == NULL) { + ECerr(EC_F_ECP_NISTZ256_MULT_PRECOMPUTE, ERR_R_MALLOC_FAILURE); + goto err; + } + + preComputedTable = (void *)ALIGNPTR(precomp_storage, 64); + + P = EC_POINT_new(group); + T = EC_POINT_new(group); + if (P == NULL || T == NULL) + goto err; + + /* + * The zero entry is implicitly infinity, and we skip it, storing other + * values with -1 offset. + */ + if (!EC_POINT_copy(T, generator)) + goto err; + + for (k = 0; k < 64; k++) { + if (!EC_POINT_copy(P, T)) + goto err; + for (j = 0; j < 37; j++) { + P256_POINT_AFFINE temp; + /* + * It would be faster to use EC_POINTs_make_affine and + * make multiple points affine at the same time. + */ + if (!EC_POINT_make_affine(group, P, ctx)) + goto err; + if (!ecp_nistz256_bignum_to_field_elem(temp.X, P->X) || + !ecp_nistz256_bignum_to_field_elem(temp.Y, P->Y)) { + ECerr(EC_F_ECP_NISTZ256_MULT_PRECOMPUTE, + EC_R_COORDINATES_OUT_OF_RANGE); + goto err; + } + ecp_nistz256_scatter_w7(preComputedTable[j], &temp, k); + for (i = 0; i < 7; i++) { + if (!EC_POINT_dbl(group, P, P, ctx)) + goto err; + } + } + if (!EC_POINT_add(group, T, T, generator, ctx)) + goto err; + } + + pre_comp->group = group; + pre_comp->w = w; + pre_comp->precomp = preComputedTable; + pre_comp->precomp_storage = precomp_storage; + precomp_storage = NULL; + SETPRECOMP(group, nistz256, pre_comp); + pre_comp = NULL; + ret = 1; + + err: + if (ctx != NULL) + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + + EC_nistz256_pre_comp_free(pre_comp); + OPENSSL_free(precomp_storage); + EC_POINT_free(P); + EC_POINT_free(T); + return ret; +} + +/* + * Note that by default ECP_NISTZ256_AVX2 is undefined. While it's great + * code processing 4 points in parallel, corresponding serial operation + * is several times slower, because it uses 29x29=58-bit multiplication + * as opposite to 64x64=128-bit in integer-only scalar case. As result + * it doesn't provide *significant* performance improvement. Note that + * just defining ECP_NISTZ256_AVX2 is not sufficient to make it work, + * you'd need to compile even asm/ecp_nistz256-avx.pl module. + */ +#if defined(ECP_NISTZ256_AVX2) +# if !(defined(__x86_64) || defined(__x86_64__) || \ + defined(_M_AMD64) || defined(_M_X64)) || \ + !(defined(__GNUC__) || defined(_MSC_VER)) /* this is for ALIGN32 */ +# undef ECP_NISTZ256_AVX2 +# else +/* Constant time access, loading four values, from four consecutive tables */ +void ecp_nistz256_avx2_multi_gather_w7(void *result, const void *in, + int index0, int index1, int index2, + int index3); +void ecp_nistz256_avx2_transpose_convert(void *RESULTx4, const void *in); +void ecp_nistz256_avx2_convert_transpose_back(void *result, const void *Ax4); +void ecp_nistz256_avx2_point_add_affine_x4(void *RESULTx4, const void *Ax4, + const void *Bx4); +void ecp_nistz256_avx2_point_add_affines_x4(void *RESULTx4, const void *Ax4, + const void *Bx4); +void ecp_nistz256_avx2_to_mont(void *RESULTx4, const void *Ax4); +void ecp_nistz256_avx2_from_mont(void *RESULTx4, const void *Ax4); +void ecp_nistz256_avx2_set1(void *RESULTx4); +int ecp_nistz_avx2_eligible(void); + +static void booth_recode_w7(unsigned char *sign, + unsigned char *digit, unsigned char in) +{ + unsigned char s, d; + + s = ~((in >> 7) - 1); + d = (1 << 8) - in - 1; + d = (d & s) | (in & ~s); + d = (d >> 1) + (d & 1); + + *sign = s & 1; + *digit = d; +} + +/* + * ecp_nistz256_avx2_mul_g performs multiplication by G, using only the + * precomputed table. It does 4 affine point additions in parallel, + * significantly speeding up point multiplication for a fixed value. + */ +static void ecp_nistz256_avx2_mul_g(P256_POINT *r, + unsigned char p_str[33], + const P256_POINT_AFFINE(*preComputedTable)[64]) +{ + const unsigned int window_size = 7; + const unsigned int mask = (1 << (window_size + 1)) - 1; + unsigned int wvalue; + /* Using 4 windows at a time */ + unsigned char sign0, digit0; + unsigned char sign1, digit1; + unsigned char sign2, digit2; + unsigned char sign3, digit3; + unsigned int idx = 0; + BN_ULONG tmp[P256_LIMBS]; + int i; + + ALIGN32 BN_ULONG aX4[4 * 9 * 3] = { 0 }; + ALIGN32 BN_ULONG bX4[4 * 9 * 2] = { 0 }; + ALIGN32 P256_POINT_AFFINE point_arr[4]; + ALIGN32 P256_POINT res_point_arr[4]; + + /* Initial four windows */ + wvalue = *((u16 *) & p_str[0]); + wvalue = (wvalue << 1) & mask; + idx += window_size; + booth_recode_w7(&sign0, &digit0, wvalue); + wvalue = *((u16 *) & p_str[(idx - 1) / 8]); + wvalue = (wvalue >> ((idx - 1) % 8)) & mask; + idx += window_size; + booth_recode_w7(&sign1, &digit1, wvalue); + wvalue = *((u16 *) & p_str[(idx - 1) / 8]); + wvalue = (wvalue >> ((idx - 1) % 8)) & mask; + idx += window_size; + booth_recode_w7(&sign2, &digit2, wvalue); + wvalue = *((u16 *) & p_str[(idx - 1) / 8]); + wvalue = (wvalue >> ((idx - 1) % 8)) & mask; + idx += window_size; + booth_recode_w7(&sign3, &digit3, wvalue); + + ecp_nistz256_avx2_multi_gather_w7(point_arr, preComputedTable[0], + digit0, digit1, digit2, digit3); + + ecp_nistz256_neg(tmp, point_arr[0].Y); + copy_conditional(point_arr[0].Y, tmp, sign0); + ecp_nistz256_neg(tmp, point_arr[1].Y); + copy_conditional(point_arr[1].Y, tmp, sign1); + ecp_nistz256_neg(tmp, point_arr[2].Y); + copy_conditional(point_arr[2].Y, tmp, sign2); + ecp_nistz256_neg(tmp, point_arr[3].Y); + copy_conditional(point_arr[3].Y, tmp, sign3); + + ecp_nistz256_avx2_transpose_convert(aX4, point_arr); + ecp_nistz256_avx2_to_mont(aX4, aX4); + ecp_nistz256_avx2_to_mont(&aX4[4 * 9], &aX4[4 * 9]); + ecp_nistz256_avx2_set1(&aX4[4 * 9 * 2]); + + wvalue = *((u16 *) & p_str[(idx - 1) / 8]); + wvalue = (wvalue >> ((idx - 1) % 8)) & mask; + idx += window_size; + booth_recode_w7(&sign0, &digit0, wvalue); + wvalue = *((u16 *) & p_str[(idx - 1) / 8]); + wvalue = (wvalue >> ((idx - 1) % 8)) & mask; + idx += window_size; + booth_recode_w7(&sign1, &digit1, wvalue); + wvalue = *((u16 *) & p_str[(idx - 1) / 8]); + wvalue = (wvalue >> ((idx - 1) % 8)) & mask; + idx += window_size; + booth_recode_w7(&sign2, &digit2, wvalue); + wvalue = *((u16 *) & p_str[(idx - 1) / 8]); + wvalue = (wvalue >> ((idx - 1) % 8)) & mask; + idx += window_size; + booth_recode_w7(&sign3, &digit3, wvalue); + + ecp_nistz256_avx2_multi_gather_w7(point_arr, preComputedTable[4 * 1], + digit0, digit1, digit2, digit3); + + ecp_nistz256_neg(tmp, point_arr[0].Y); + copy_conditional(point_arr[0].Y, tmp, sign0); + ecp_nistz256_neg(tmp, point_arr[1].Y); + copy_conditional(point_arr[1].Y, tmp, sign1); + ecp_nistz256_neg(tmp, point_arr[2].Y); + copy_conditional(point_arr[2].Y, tmp, sign2); + ecp_nistz256_neg(tmp, point_arr[3].Y); + copy_conditional(point_arr[3].Y, tmp, sign3); + + ecp_nistz256_avx2_transpose_convert(bX4, point_arr); + ecp_nistz256_avx2_to_mont(bX4, bX4); + ecp_nistz256_avx2_to_mont(&bX4[4 * 9], &bX4[4 * 9]); + /* Optimized when both inputs are affine */ + ecp_nistz256_avx2_point_add_affines_x4(aX4, aX4, bX4); + + for (i = 2; i < 9; i++) { + wvalue = *((u16 *) & p_str[(idx - 1) / 8]); + wvalue = (wvalue >> ((idx - 1) % 8)) & mask; + idx += window_size; + booth_recode_w7(&sign0, &digit0, wvalue); + wvalue = *((u16 *) & p_str[(idx - 1) / 8]); + wvalue = (wvalue >> ((idx - 1) % 8)) & mask; + idx += window_size; + booth_recode_w7(&sign1, &digit1, wvalue); + wvalue = *((u16 *) & p_str[(idx - 1) / 8]); + wvalue = (wvalue >> ((idx - 1) % 8)) & mask; + idx += window_size; + booth_recode_w7(&sign2, &digit2, wvalue); + wvalue = *((u16 *) & p_str[(idx - 1) / 8]); + wvalue = (wvalue >> ((idx - 1) % 8)) & mask; + idx += window_size; + booth_recode_w7(&sign3, &digit3, wvalue); + + ecp_nistz256_avx2_multi_gather_w7(point_arr, + preComputedTable[4 * i], + digit0, digit1, digit2, digit3); + + ecp_nistz256_neg(tmp, point_arr[0].Y); + copy_conditional(point_arr[0].Y, tmp, sign0); + ecp_nistz256_neg(tmp, point_arr[1].Y); + copy_conditional(point_arr[1].Y, tmp, sign1); + ecp_nistz256_neg(tmp, point_arr[2].Y); + copy_conditional(point_arr[2].Y, tmp, sign2); + ecp_nistz256_neg(tmp, point_arr[3].Y); + copy_conditional(point_arr[3].Y, tmp, sign3); + + ecp_nistz256_avx2_transpose_convert(bX4, point_arr); + ecp_nistz256_avx2_to_mont(bX4, bX4); + ecp_nistz256_avx2_to_mont(&bX4[4 * 9], &bX4[4 * 9]); + + ecp_nistz256_avx2_point_add_affine_x4(aX4, aX4, bX4); + } + + ecp_nistz256_avx2_from_mont(&aX4[4 * 9 * 0], &aX4[4 * 9 * 0]); + ecp_nistz256_avx2_from_mont(&aX4[4 * 9 * 1], &aX4[4 * 9 * 1]); + ecp_nistz256_avx2_from_mont(&aX4[4 * 9 * 2], &aX4[4 * 9 * 2]); + + ecp_nistz256_avx2_convert_transpose_back(res_point_arr, aX4); + /* Last window is performed serially */ + wvalue = *((u16 *) & p_str[(idx - 1) / 8]); + wvalue = (wvalue >> ((idx - 1) % 8)) & mask; + booth_recode_w7(&sign0, &digit0, wvalue); + ecp_nistz256_gather_w7((P256_POINT_AFFINE *)r, + preComputedTable[36], digit0); + ecp_nistz256_neg(tmp, r->Y); + copy_conditional(r->Y, tmp, sign0); + memcpy(r->Z, ONE, sizeof(ONE)); + /* Sum the four windows */ + ecp_nistz256_point_add(r, r, &res_point_arr[0]); + ecp_nistz256_point_add(r, r, &res_point_arr[1]); + ecp_nistz256_point_add(r, r, &res_point_arr[2]); + ecp_nistz256_point_add(r, r, &res_point_arr[3]); +} +# endif +#endif + +__owur static int ecp_nistz256_set_from_affine(EC_POINT *out, const EC_GROUP *group, + const P256_POINT_AFFINE *in, + BN_CTX *ctx) +{ + int ret = 0; + + if ((ret = bn_set_words(out->X, in->X, P256_LIMBS)) + && (ret = bn_set_words(out->Y, in->Y, P256_LIMBS)) + && (ret = bn_set_words(out->Z, ONE, P256_LIMBS))) + out->Z_is_one = 1; + + return ret; +} + +/* r = scalar*G + sum(scalars[i]*points[i]) */ +__owur static int ecp_nistz256_points_mul(const EC_GROUP *group, + EC_POINT *r, + const BIGNUM *scalar, + size_t num, + const EC_POINT *points[], + const BIGNUM *scalars[], BN_CTX *ctx) +{ + int i = 0, ret = 0, no_precomp_for_generator = 0, p_is_infinity = 0; + unsigned char p_str[33] = { 0 }; + const PRECOMP256_ROW *preComputedTable = NULL; + const NISTZ256_PRE_COMP *pre_comp = NULL; + const EC_POINT *generator = NULL; + const BIGNUM **new_scalars = NULL; + const EC_POINT **new_points = NULL; + unsigned int idx = 0; + const unsigned int window_size = 7; + const unsigned int mask = (1 << (window_size + 1)) - 1; + unsigned int wvalue; + ALIGN32 union { + P256_POINT p; + P256_POINT_AFFINE a; + } t, p; + BIGNUM *tmp_scalar; + + if ((num + 1) == 0 || (num + 1) > OPENSSL_MALLOC_MAX_NELEMS(void *)) { + ECerr(EC_F_ECP_NISTZ256_POINTS_MUL, ERR_R_MALLOC_FAILURE); + return 0; + } + + BN_CTX_start(ctx); + + if (scalar) { + generator = EC_GROUP_get0_generator(group); + if (generator == NULL) { + ECerr(EC_F_ECP_NISTZ256_POINTS_MUL, EC_R_UNDEFINED_GENERATOR); + goto err; + } + + /* look if we can use precomputed multiples of generator */ + pre_comp = group->pre_comp.nistz256; + + if (pre_comp) { + /* + * If there is a precomputed table for the generator, check that + * it was generated with the same generator. + */ + EC_POINT *pre_comp_generator = EC_POINT_new(group); + if (pre_comp_generator == NULL) + goto err; + + ecp_nistz256_gather_w7(&p.a, pre_comp->precomp[0], 1); + if (!ecp_nistz256_set_from_affine(pre_comp_generator, + group, &p.a, ctx)) { + EC_POINT_free(pre_comp_generator); + goto err; + } + + if (0 == EC_POINT_cmp(group, generator, pre_comp_generator, ctx)) + preComputedTable = (const PRECOMP256_ROW *)pre_comp->precomp; + + EC_POINT_free(pre_comp_generator); + } + + if (preComputedTable == NULL && ecp_nistz256_is_affine_G(generator)) { + /* + * If there is no precomputed data, but the generator is the + * default, a hardcoded table of precomputed data is used. This + * is because applications, such as Apache, do not use + * EC_KEY_precompute_mult. + */ + preComputedTable = ecp_nistz256_precomputed; + } + + if (preComputedTable) { + if ((BN_num_bits(scalar) > 256) + || BN_is_negative(scalar)) { + if ((tmp_scalar = BN_CTX_get(ctx)) == NULL) + goto err; + + if (!BN_nnmod(tmp_scalar, scalar, group->order, ctx)) { + ECerr(EC_F_ECP_NISTZ256_POINTS_MUL, ERR_R_BN_LIB); + goto err; + } + scalar = tmp_scalar; + } + + for (i = 0; i < bn_get_top(scalar) * BN_BYTES; i += BN_BYTES) { + BN_ULONG d = bn_get_words(scalar)[i / BN_BYTES]; + + p_str[i + 0] = (unsigned char)d; + p_str[i + 1] = (unsigned char)(d >> 8); + p_str[i + 2] = (unsigned char)(d >> 16); + p_str[i + 3] = (unsigned char)(d >>= 24); + if (BN_BYTES == 8) { + d >>= 8; + p_str[i + 4] = (unsigned char)d; + p_str[i + 5] = (unsigned char)(d >> 8); + p_str[i + 6] = (unsigned char)(d >> 16); + p_str[i + 7] = (unsigned char)(d >> 24); + } + } + + for (; i < 33; i++) + p_str[i] = 0; + +#if defined(ECP_NISTZ256_AVX2) + if (ecp_nistz_avx2_eligible()) { + ecp_nistz256_avx2_mul_g(&p.p, p_str, preComputedTable); + } else +#endif + { + BN_ULONG infty; + + /* First window */ + wvalue = (p_str[0] << 1) & mask; + idx += window_size; + + wvalue = _booth_recode_w7(wvalue); + + ecp_nistz256_gather_w7(&p.a, preComputedTable[0], + wvalue >> 1); + + ecp_nistz256_neg(p.p.Z, p.p.Y); + copy_conditional(p.p.Y, p.p.Z, wvalue & 1); + + /* + * Since affine infinity is encoded as (0,0) and + * Jacobian ias (,,0), we need to harmonize them + * by assigning "one" or zero to Z. + */ + infty = (p.p.X[0] | p.p.X[1] | p.p.X[2] | p.p.X[3] | + p.p.Y[0] | p.p.Y[1] | p.p.Y[2] | p.p.Y[3]); + if (P256_LIMBS == 8) + infty |= (p.p.X[4] | p.p.X[5] | p.p.X[6] | p.p.X[7] | + p.p.Y[4] | p.p.Y[5] | p.p.Y[6] | p.p.Y[7]); + + infty = 0 - is_zero(infty); + infty = ~infty; + + p.p.Z[0] = ONE[0] & infty; + p.p.Z[1] = ONE[1] & infty; + p.p.Z[2] = ONE[2] & infty; + p.p.Z[3] = ONE[3] & infty; + if (P256_LIMBS == 8) { + p.p.Z[4] = ONE[4] & infty; + p.p.Z[5] = ONE[5] & infty; + p.p.Z[6] = ONE[6] & infty; + p.p.Z[7] = ONE[7] & infty; + } + + for (i = 1; i < 37; i++) { + unsigned int off = (idx - 1) / 8; + wvalue = p_str[off] | p_str[off + 1] << 8; + wvalue = (wvalue >> ((idx - 1) % 8)) & mask; + idx += window_size; + + wvalue = _booth_recode_w7(wvalue); + + ecp_nistz256_gather_w7(&t.a, + preComputedTable[i], wvalue >> 1); + + ecp_nistz256_neg(t.p.Z, t.a.Y); + copy_conditional(t.a.Y, t.p.Z, wvalue & 1); + + ecp_nistz256_point_add_affine(&p.p, &p.p, &t.a); + } + } + } else { + p_is_infinity = 1; + no_precomp_for_generator = 1; + } + } else + p_is_infinity = 1; + + if (no_precomp_for_generator) { + /* + * Without a precomputed table for the generator, it has to be + * handled like a normal point. + */ + new_scalars = OPENSSL_malloc((num + 1) * sizeof(BIGNUM *)); + if (new_scalars == NULL) { + ECerr(EC_F_ECP_NISTZ256_POINTS_MUL, ERR_R_MALLOC_FAILURE); + goto err; + } + + new_points = OPENSSL_malloc((num + 1) * sizeof(EC_POINT *)); + if (new_points == NULL) { + ECerr(EC_F_ECP_NISTZ256_POINTS_MUL, ERR_R_MALLOC_FAILURE); + goto err; + } + + memcpy(new_scalars, scalars, num * sizeof(BIGNUM *)); + new_scalars[num] = scalar; + memcpy(new_points, points, num * sizeof(EC_POINT *)); + new_points[num] = generator; + + scalars = new_scalars; + points = new_points; + num++; + } + + if (num) { + P256_POINT *out = &t.p; + if (p_is_infinity) + out = &p.p; + + if (!ecp_nistz256_windowed_mul(group, out, scalars, points, num, ctx)) + goto err; + + if (!p_is_infinity) + ecp_nistz256_point_add(&p.p, &p.p, out); + } + + /* Not constant-time, but we're only operating on the public output. */ + if (!bn_set_words(r->X, p.p.X, P256_LIMBS) || + !bn_set_words(r->Y, p.p.Y, P256_LIMBS) || + !bn_set_words(r->Z, p.p.Z, P256_LIMBS)) { + goto err; + } + r->Z_is_one = is_one(r->Z) & 1; + + ret = 1; + +err: + BN_CTX_end(ctx); + OPENSSL_free(new_points); + OPENSSL_free(new_scalars); + return ret; +} + +__owur static int ecp_nistz256_get_affine(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, BN_CTX *ctx) +{ + BN_ULONG z_inv2[P256_LIMBS]; + BN_ULONG z_inv3[P256_LIMBS]; + BN_ULONG x_aff[P256_LIMBS]; + BN_ULONG y_aff[P256_LIMBS]; + BN_ULONG point_x[P256_LIMBS], point_y[P256_LIMBS], point_z[P256_LIMBS]; + BN_ULONG x_ret[P256_LIMBS], y_ret[P256_LIMBS]; + + if (EC_POINT_is_at_infinity(group, point)) { + ECerr(EC_F_ECP_NISTZ256_GET_AFFINE, EC_R_POINT_AT_INFINITY); + return 0; + } + + if (!ecp_nistz256_bignum_to_field_elem(point_x, point->X) || + !ecp_nistz256_bignum_to_field_elem(point_y, point->Y) || + !ecp_nistz256_bignum_to_field_elem(point_z, point->Z)) { + ECerr(EC_F_ECP_NISTZ256_GET_AFFINE, EC_R_COORDINATES_OUT_OF_RANGE); + return 0; + } + + ecp_nistz256_mod_inverse(z_inv3, point_z); + ecp_nistz256_sqr_mont(z_inv2, z_inv3); + ecp_nistz256_mul_mont(x_aff, z_inv2, point_x); + + if (x != NULL) { + ecp_nistz256_from_mont(x_ret, x_aff); + if (!bn_set_words(x, x_ret, P256_LIMBS)) + return 0; + } + + if (y != NULL) { + ecp_nistz256_mul_mont(z_inv3, z_inv3, z_inv2); + ecp_nistz256_mul_mont(y_aff, z_inv3, point_y); + ecp_nistz256_from_mont(y_ret, y_aff); + if (!bn_set_words(y, y_ret, P256_LIMBS)) + return 0; + } + + return 1; +} + +static NISTZ256_PRE_COMP *ecp_nistz256_pre_comp_new(const EC_GROUP *group) +{ + NISTZ256_PRE_COMP *ret = NULL; + + if (!group) + return NULL; + + ret = OPENSSL_zalloc(sizeof(*ret)); + + if (ret == NULL) { + ECerr(EC_F_ECP_NISTZ256_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); + return ret; + } + + ret->group = group; + ret->w = 6; /* default */ + ret->references = 1; + + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) { + ECerr(EC_F_ECP_NISTZ256_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ret); + return NULL; + } + return ret; +} + +NISTZ256_PRE_COMP *EC_nistz256_pre_comp_dup(NISTZ256_PRE_COMP *p) +{ + int i; + if (p != NULL) + CRYPTO_UP_REF(&p->references, &i, p->lock); + return p; +} + +void EC_nistz256_pre_comp_free(NISTZ256_PRE_COMP *pre) +{ + int i; + + if (pre == NULL) + return; + + CRYPTO_DOWN_REF(&pre->references, &i, pre->lock); + REF_PRINT_COUNT("EC_nistz256", x); + if (i > 0) + return; + REF_ASSERT_ISNT(i < 0); + + OPENSSL_free(pre->precomp_storage); + CRYPTO_THREAD_lock_free(pre->lock); + OPENSSL_free(pre); +} + + +static int ecp_nistz256_window_have_precompute_mult(const EC_GROUP *group) +{ + /* There is a hard-coded table for the default generator. */ + const EC_POINT *generator = EC_GROUP_get0_generator(group); + + if (generator != NULL && ecp_nistz256_is_affine_G(generator)) { + /* There is a hard-coded table for the default generator. */ + return 1; + } + + return HAVEPRECOMP(group, nistz256); +} + +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(_M_AMD64) || defined(_M_X64) || \ + defined(__powerpc64__) || defined(_ARCH_PP64) || \ + defined(__aarch64__) +/* + * Montgomery mul modulo Order(P): res = a*b*2^-256 mod Order(P) + */ +void ecp_nistz256_ord_mul_mont(BN_ULONG res[P256_LIMBS], + const BN_ULONG a[P256_LIMBS], + const BN_ULONG b[P256_LIMBS]); +void ecp_nistz256_ord_sqr_mont(BN_ULONG res[P256_LIMBS], + const BN_ULONG a[P256_LIMBS], + int rep); + +static int ecp_nistz256_inv_mod_ord(const EC_GROUP *group, BIGNUM *r, + const BIGNUM *x, BN_CTX *ctx) +{ + /* RR = 2^512 mod ord(p256) */ + static const BN_ULONG RR[P256_LIMBS] = { + TOBN(0x83244c95,0xbe79eea2), TOBN(0x4699799c,0x49bd6fa6), + TOBN(0x2845b239,0x2b6bec59), TOBN(0x66e12d94,0xf3d95620) + }; + /* The constant 1 (unlike ONE that is one in Montgomery representation) */ + static const BN_ULONG one[P256_LIMBS] = { + TOBN(0,1), TOBN(0,0), TOBN(0,0), TOBN(0,0) + }; + /* + * We don't use entry 0 in the table, so we omit it and address + * with -1 offset. + */ + BN_ULONG table[15][P256_LIMBS]; + BN_ULONG out[P256_LIMBS], t[P256_LIMBS]; + int i, ret = 0; + enum { + i_1 = 0, i_10, i_11, i_101, i_111, i_1010, i_1111, + i_10101, i_101010, i_101111, i_x6, i_x8, i_x16, i_x32 + }; + + /* + * Catch allocation failure early. + */ + if (bn_wexpand(r, P256_LIMBS) == NULL) { + ECerr(EC_F_ECP_NISTZ256_INV_MOD_ORD, ERR_R_BN_LIB); + goto err; + } + + if ((BN_num_bits(x) > 256) || BN_is_negative(x)) { + BIGNUM *tmp; + + if ((tmp = BN_CTX_get(ctx)) == NULL + || !BN_nnmod(tmp, x, group->order, ctx)) { + ECerr(EC_F_ECP_NISTZ256_INV_MOD_ORD, ERR_R_BN_LIB); + goto err; + } + x = tmp; + } + + if (!ecp_nistz256_bignum_to_field_elem(t, x)) { + ECerr(EC_F_ECP_NISTZ256_INV_MOD_ORD, EC_R_COORDINATES_OUT_OF_RANGE); + goto err; + } + + ecp_nistz256_ord_mul_mont(table[0], t, RR); +#if 0 + /* + * Original sparse-then-fixed-window algorithm, retained for reference. + */ + for (i = 2; i < 16; i += 2) { + ecp_nistz256_ord_sqr_mont(table[i-1], table[i/2-1], 1); + ecp_nistz256_ord_mul_mont(table[i], table[i-1], table[0]); + } + + /* + * The top 128bit of the exponent are highly redudndant, so we + * perform an optimized flow + */ + ecp_nistz256_ord_sqr_mont(t, table[15-1], 4); /* f0 */ + ecp_nistz256_ord_mul_mont(t, t, table[15-1]); /* ff */ + + ecp_nistz256_ord_sqr_mont(out, t, 8); /* ff00 */ + ecp_nistz256_ord_mul_mont(out, out, t); /* ffff */ + + ecp_nistz256_ord_sqr_mont(t, out, 16); /* ffff0000 */ + ecp_nistz256_ord_mul_mont(t, t, out); /* ffffffff */ + + ecp_nistz256_ord_sqr_mont(out, t, 64); /* ffffffff0000000000000000 */ + ecp_nistz256_ord_mul_mont(out, out, t); /* ffffffff00000000ffffffff */ + + ecp_nistz256_ord_sqr_mont(out, out, 32); /* ffffffff00000000ffffffff00000000 */ + ecp_nistz256_ord_mul_mont(out, out, t); /* ffffffff00000000ffffffffffffffff */ + + /* + * The bottom 128 bit of the exponent are processed with fixed 4-bit window + */ + for(i = 0; i < 32; i++) { + /* expLo - the low 128 bits of the exponent we use (ord(p256) - 2), + * split into nibbles */ + static const unsigned char expLo[32] = { + 0xb,0xc,0xe,0x6,0xf,0xa,0xa,0xd,0xa,0x7,0x1,0x7,0x9,0xe,0x8,0x4, + 0xf,0x3,0xb,0x9,0xc,0xa,0xc,0x2,0xf,0xc,0x6,0x3,0x2,0x5,0x4,0xf + }; + + ecp_nistz256_ord_sqr_mont(out, out, 4); + /* The exponent is public, no need in constant-time access */ + ecp_nistz256_ord_mul_mont(out, out, table[expLo[i]-1]); + } +#else + /* + * https://briansmith.org/ecc-inversion-addition-chains-01#p256_scalar_inversion + * + * Even though this code path spares 12 squarings, 4.5%, and 13 + * multiplications, 25%, on grand scale sign operation is not that + * much faster, not more that 2%... + */ + + /* pre-calculate powers */ + ecp_nistz256_ord_sqr_mont(table[i_10], table[i_1], 1); + + ecp_nistz256_ord_mul_mont(table[i_11], table[i_1], table[i_10]); + + ecp_nistz256_ord_mul_mont(table[i_101], table[i_11], table[i_10]); + + ecp_nistz256_ord_mul_mont(table[i_111], table[i_101], table[i_10]); + + ecp_nistz256_ord_sqr_mont(table[i_1010], table[i_101], 1); + + ecp_nistz256_ord_mul_mont(table[i_1111], table[i_1010], table[i_101]); + + ecp_nistz256_ord_sqr_mont(table[i_10101], table[i_1010], 1); + ecp_nistz256_ord_mul_mont(table[i_10101], table[i_10101], table[i_1]); + + ecp_nistz256_ord_sqr_mont(table[i_101010], table[i_10101], 1); + + ecp_nistz256_ord_mul_mont(table[i_101111], table[i_101010], table[i_101]); + + ecp_nistz256_ord_mul_mont(table[i_x6], table[i_101010], table[i_10101]); + + ecp_nistz256_ord_sqr_mont(table[i_x8], table[i_x6], 2); + ecp_nistz256_ord_mul_mont(table[i_x8], table[i_x8], table[i_11]); + + ecp_nistz256_ord_sqr_mont(table[i_x16], table[i_x8], 8); + ecp_nistz256_ord_mul_mont(table[i_x16], table[i_x16], table[i_x8]); + + ecp_nistz256_ord_sqr_mont(table[i_x32], table[i_x16], 16); + ecp_nistz256_ord_mul_mont(table[i_x32], table[i_x32], table[i_x16]); + + /* calculations */ + ecp_nistz256_ord_sqr_mont(out, table[i_x32], 64); + ecp_nistz256_ord_mul_mont(out, out, table[i_x32]); + + for (i = 0; i < 27; i++) { + static const struct { unsigned char p, i; } chain[27] = { + { 32, i_x32 }, { 6, i_101111 }, { 5, i_111 }, + { 4, i_11 }, { 5, i_1111 }, { 5, i_10101 }, + { 4, i_101 }, { 3, i_101 }, { 3, i_101 }, + { 5, i_111 }, { 9, i_101111 }, { 6, i_1111 }, + { 2, i_1 }, { 5, i_1 }, { 6, i_1111 }, + { 5, i_111 }, { 4, i_111 }, { 5, i_111 }, + { 5, i_101 }, { 3, i_11 }, { 10, i_101111 }, + { 2, i_11 }, { 5, i_11 }, { 5, i_11 }, + { 3, i_1 }, { 7, i_10101 }, { 6, i_1111 } + }; + + ecp_nistz256_ord_sqr_mont(out, out, chain[i].p); + ecp_nistz256_ord_mul_mont(out, out, table[chain[i].i]); + } +#endif + ecp_nistz256_ord_mul_mont(out, out, one); + + /* + * Can't fail, but check return code to be consistent anyway. + */ + if (!bn_set_words(r, out, P256_LIMBS)) + goto err; + + ret = 1; +err: + return ret; +} +#else +# define ecp_nistz256_inv_mod_ord NULL +#endif + +const EC_METHOD *EC_GFp_nistz256_method(void) +{ + static const EC_METHOD ret = { + EC_FLAGS_DEFAULT_OCT, + NID_X9_62_prime_field, + ec_GFp_mont_group_init, + ec_GFp_mont_group_finish, + ec_GFp_mont_group_clear_finish, + ec_GFp_mont_group_copy, + ec_GFp_mont_group_set_curve, + ec_GFp_simple_group_get_curve, + ec_GFp_simple_group_get_degree, + ec_group_simple_order_bits, + ec_GFp_simple_group_check_discriminant, + ec_GFp_simple_point_init, + ec_GFp_simple_point_finish, + ec_GFp_simple_point_clear_finish, + ec_GFp_simple_point_copy, + ec_GFp_simple_point_set_to_infinity, + ec_GFp_simple_set_Jprojective_coordinates_GFp, + ec_GFp_simple_get_Jprojective_coordinates_GFp, + ec_GFp_simple_point_set_affine_coordinates, + ecp_nistz256_get_affine, + 0, 0, 0, + ec_GFp_simple_add, + ec_GFp_simple_dbl, + ec_GFp_simple_invert, + ec_GFp_simple_is_at_infinity, + ec_GFp_simple_is_on_curve, + ec_GFp_simple_cmp, + ec_GFp_simple_make_affine, + ec_GFp_simple_points_make_affine, + ecp_nistz256_points_mul, /* mul */ + ecp_nistz256_mult_precompute, /* precompute_mult */ + ecp_nistz256_window_have_precompute_mult, /* have_precompute_mult */ + ec_GFp_mont_field_mul, + ec_GFp_mont_field_sqr, + 0, /* field_div */ + ec_GFp_mont_field_inv, + ec_GFp_mont_field_encode, + ec_GFp_mont_field_decode, + ec_GFp_mont_field_set_to_one, + ec_key_simple_priv2oct, + ec_key_simple_oct2priv, + 0, /* set private */ + ec_key_simple_generate_key, + ec_key_simple_check_key, + ec_key_simple_generate_public_key, + 0, /* keycopy */ + 0, /* keyfinish */ + ecdh_simple_compute_key, + ecp_nistz256_inv_mod_ord, /* can be #define-d NULL */ + 0, /* blind_coordinates */ + 0, /* ladder_pre */ + 0, /* ladder_step */ + 0 /* ladder_post */ + }; + + return &ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_nistz256_table.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_nistz256_table.c new file mode 100644 index 000000000..3f5625c6c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_nistz256_table.c @@ -0,0 +1,9542 @@ +/* + * Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This is the precomputed constant time access table for the code in + * ecp_montp256.c, for the default generator. The table consists of 37 + * subtables, each subtable contains 64 affine points. The affine points are + * encoded as eight uint64's, four for the x coordinate and four for the y. + * Both values are in little-endian order. There are 37 tables because a + * signed, 6-bit wNAF form of the scalar is used and ceil(256/(6 + 1)) = 37. + * Within each table there are 64 values because the 6-bit wNAF value can + * take 64 values, ignoring the sign bit, which is implemented by performing + * a negation of the affine point when required. We would like to align it + * to 2MB in order to increase the chances of using a large page but that + * appears to lead to invalid ELF files being produced. + */ + +#if defined(__GNUC__) +__attribute((aligned(4096))) +#elif defined(_MSC_VER) +__declspec(align(4096)) +#elif defined(__SUNPRO_C) +# pragma align 4096(ecp_nistz256_precomputed) +#endif +static const BN_ULONG ecp_nistz256_precomputed[37][64 * + sizeof(P256_POINT_AFFINE) / + sizeof(BN_ULONG)] = { + {TOBN(0x79e730d4, 0x18a9143c), TOBN(0x75ba95fc, 0x5fedb601), + TOBN(0x79fb732b, 0x77622510), TOBN(0x18905f76, 0xa53755c6), + TOBN(0xddf25357, 0xce95560a), TOBN(0x8b4ab8e4, 0xba19e45c), + TOBN(0xd2e88688, 0xdd21f325), TOBN(0x8571ff18, 0x25885d85), + TOBN(0x850046d4, 0x10ddd64d), TOBN(0xaa6ae3c1, 0xa433827d), + TOBN(0x73220503, 0x8d1490d9), TOBN(0xf6bb32e4, 0x3dcf3a3b), + TOBN(0x2f3648d3, 0x61bee1a5), TOBN(0x152cd7cb, 0xeb236ff8), + TOBN(0x19a8fb0e, 0x92042dbe), TOBN(0x78c57751, 0x0a5b8a3b), + TOBN(0xffac3f90, 0x4eebc127), TOBN(0xb027f84a, 0x087d81fb), + TOBN(0x66ad77dd, 0x87cbbc98), TOBN(0x26936a3f, 0xb6ff747e), + TOBN(0xb04c5c1f, 0xc983a7eb), TOBN(0x583e47ad, 0x0861fe1a), + TOBN(0x78820831, 0x1a2ee98e), TOBN(0xd5f06a29, 0xe587cc07), + TOBN(0x74b0b50d, 0x46918dcc), TOBN(0x4650a6ed, 0xc623c173), + TOBN(0x0cdaacac, 0xe8100af2), TOBN(0x577362f5, 0x41b0176b), + TOBN(0x2d96f24c, 0xe4cbaba6), TOBN(0x17628471, 0xfad6f447), + TOBN(0x6b6c36de, 0xe5ddd22e), TOBN(0x84b14c39, 0x4c5ab863), + TOBN(0xbe1b8aae, 0xc45c61f5), TOBN(0x90ec649a, 0x94b9537d), + TOBN(0x941cb5aa, 0xd076c20c), TOBN(0xc9079605, 0x890523c8), + TOBN(0xeb309b4a, 0xe7ba4f10), TOBN(0x73c568ef, 0xe5eb882b), + TOBN(0x3540a987, 0x7e7a1f68), TOBN(0x73a076bb, 0x2dd1e916), + TOBN(0x40394737, 0x3e77664a), TOBN(0x55ae744f, 0x346cee3e), + TOBN(0xd50a961a, 0x5b17a3ad), TOBN(0x13074b59, 0x54213673), + TOBN(0x93d36220, 0xd377e44b), TOBN(0x299c2b53, 0xadff14b5), + TOBN(0xf424d44c, 0xef639f11), TOBN(0xa4c9916d, 0x4a07f75f), + TOBN(0x0746354e, 0xa0173b4f), TOBN(0x2bd20213, 0xd23c00f7), + TOBN(0xf43eaab5, 0x0c23bb08), TOBN(0x13ba5119, 0xc3123e03), + TOBN(0x2847d030, 0x3f5b9d4d), TOBN(0x6742f2f2, 0x5da67bdd), + TOBN(0xef933bdc, 0x77c94195), TOBN(0xeaedd915, 0x6e240867), + TOBN(0x27f14cd1, 0x9499a78f), TOBN(0x462ab5c5, 0x6f9b3455), + TOBN(0x8f90f02a, 0xf02cfc6b), TOBN(0xb763891e, 0xb265230d), + TOBN(0xf59da3a9, 0x532d4977), TOBN(0x21e3327d, 0xcf9eba15), + TOBN(0x123c7b84, 0xbe60bbf0), TOBN(0x56ec12f2, 0x7706df76), + TOBN(0x75c96e8f, 0x264e20e8), TOBN(0xabe6bfed, 0x59a7a841), + TOBN(0x2cc09c04, 0x44c8eb00), TOBN(0xe05b3080, 0xf0c4e16b), + TOBN(0x1eb7777a, 0xa45f3314), TOBN(0x56af7bed, 0xce5d45e3), + TOBN(0x2b6e019a, 0x88b12f1a), TOBN(0x086659cd, 0xfd835f9b), + TOBN(0x2c18dbd1, 0x9dc21ec8), TOBN(0x98f9868a, 0x0fcf8139), + TOBN(0x737d2cd6, 0x48250b49), TOBN(0xcc61c947, 0x24b3428f), + TOBN(0x0c2b4078, 0x80dd9e76), TOBN(0xc43a8991, 0x383fbe08), + TOBN(0x5f7d2d65, 0x779be5d2), TOBN(0x78719a54, 0xeb3b4ab5), + TOBN(0xea7d260a, 0x6245e404), TOBN(0x9de40795, 0x6e7fdfe0), + TOBN(0x1ff3a415, 0x8dac1ab5), TOBN(0x3e7090f1, 0x649c9073), + TOBN(0x1a768561, 0x2b944e88), TOBN(0x250f939e, 0xe57f61c8), + TOBN(0x0c0daa89, 0x1ead643d), TOBN(0x68930023, 0xe125b88e), + TOBN(0x04b71aa7, 0xd2697768), TOBN(0xabdedef5, 0xca345a33), + TOBN(0x2409d29d, 0xee37385e), TOBN(0x4ee1df77, 0xcb83e156), + TOBN(0x0cac12d9, 0x1cbb5b43), TOBN(0x170ed2f6, 0xca895637), + TOBN(0x28228cfa, 0x8ade6d66), TOBN(0x7ff57c95, 0x53238aca), + TOBN(0xccc42563, 0x4b2ed709), TOBN(0x0e356769, 0x856fd30d), + TOBN(0xbcbcd43f, 0x559e9811), TOBN(0x738477ac, 0x5395b759), + TOBN(0x35752b90, 0xc00ee17f), TOBN(0x68748390, 0x742ed2e3), + TOBN(0x7cd06422, 0xbd1f5bc1), TOBN(0xfbc08769, 0xc9e7b797), + TOBN(0xa242a35b, 0xb0cf664a), TOBN(0x126e48f7, 0x7f9707e3), + TOBN(0x1717bf54, 0xc6832660), TOBN(0xfaae7332, 0xfd12c72e), + TOBN(0x27b52db7, 0x995d586b), TOBN(0xbe29569e, 0x832237c2), + TOBN(0xe8e4193e, 0x2a65e7db), TOBN(0x152706dc, 0x2eaa1bbb), + TOBN(0x72bcd8b7, 0xbc60055b), TOBN(0x03cc23ee, 0x56e27e4b), + TOBN(0xee337424, 0xe4819370), TOBN(0xe2aa0e43, 0x0ad3da09), + TOBN(0x40b8524f, 0x6383c45d), TOBN(0xd7663554, 0x42a41b25), + TOBN(0x64efa6de, 0x778a4797), TOBN(0x2042170a, 0x7079adf4), + TOBN(0x808b0b65, 0x0bc6fb80), TOBN(0x5882e075, 0x3ffe2e6b), + TOBN(0xd5ef2f7c, 0x2c83f549), TOBN(0x54d63c80, 0x9103b723), + TOBN(0xf2f11bd6, 0x52a23f9b), TOBN(0x3670c319, 0x4b0b6587), + TOBN(0x55c4623b, 0xb1580e9e), TOBN(0x64edf7b2, 0x01efe220), + TOBN(0x97091dcb, 0xd53c5c9d), TOBN(0xf17624b6, 0xac0a177b), + TOBN(0xb0f13975, 0x2cfe2dff), TOBN(0xc1a35c0a, 0x6c7a574e), + TOBN(0x227d3146, 0x93e79987), TOBN(0x0575bf30, 0xe89cb80e), + TOBN(0x2f4e247f, 0x0d1883bb), TOBN(0xebd51226, 0x3274c3d0), + TOBN(0x5f3e51c8, 0x56ada97a), TOBN(0x4afc964d, 0x8f8b403e), + TOBN(0xa6f247ab, 0x412e2979), TOBN(0x675abd1b, 0x6f80ebda), + TOBN(0x66a2bd72, 0x5e485a1d), TOBN(0x4b2a5caf, 0x8f4f0b3c), + TOBN(0x2626927f, 0x1b847bba), TOBN(0x6c6fc7d9, 0x0502394d), + TOBN(0xfea912ba, 0xa5659ae8), TOBN(0x68363aba, 0x25e1a16e), + TOBN(0xb8842277, 0x752c41ac), TOBN(0xfe545c28, 0x2897c3fc), + TOBN(0x2d36e9e7, 0xdc4c696b), TOBN(0x5806244a, 0xfba977c5), + TOBN(0x85665e9b, 0xe39508c1), TOBN(0xf720ee25, 0x6d12597b), + TOBN(0x8a979129, 0xd2337a31), TOBN(0x5916868f, 0x0f862bdc), + TOBN(0x048099d9, 0x5dd283ba), TOBN(0xe2d1eeb6, 0xfe5bfb4e), + TOBN(0x82ef1c41, 0x7884005d), TOBN(0xa2d4ec17, 0xffffcbae), + TOBN(0x9161c53f, 0x8aa95e66), TOBN(0x5ee104e1, 0xc5fee0d0), + TOBN(0x562e4cec, 0xc135b208), TOBN(0x74e1b265, 0x4783f47d), + TOBN(0x6d2a506c, 0x5a3f3b30), TOBN(0xecead9f4, 0xc16762fc), + TOBN(0xf29dd4b2, 0xe286e5b9), TOBN(0x1b0fadc0, 0x83bb3c61), + TOBN(0x7a75023e, 0x7fac29a4), TOBN(0xc086d5f1, 0xc9477fa3), + TOBN(0x0fc61135, 0x2f6f3076), TOBN(0xc99ffa23, 0xe3912a9a), + TOBN(0x6a0b0685, 0xd2f8ba3d), TOBN(0xfdc777e8, 0xe93358a4), + TOBN(0x94a787bb, 0x35415f04), TOBN(0x640c2d6a, 0x4d23fea4), + TOBN(0x9de917da, 0x153a35b5), TOBN(0x793e8d07, 0x5d5cd074), + TOBN(0xf4f87653, 0x2de45068), TOBN(0x37c7a7e8, 0x9e2e1f6e), + TOBN(0xd0825fa2, 0xa3584069), TOBN(0xaf2cea7c, 0x1727bf42), + TOBN(0x0360a4fb, 0x9e4785a9), TOBN(0xe5fda49c, 0x27299f4a), + TOBN(0x48068e13, 0x71ac2f71), TOBN(0x83d0687b, 0x9077666f), + TOBN(0x6d3883b2, 0x15d02819), TOBN(0x6d0d7550, 0x40dd9a35), + TOBN(0x61d7cbf9, 0x1d2b469f), TOBN(0xf97b232f, 0x2efc3115), + TOBN(0xa551d750, 0xb24bcbc7), TOBN(0x11ea4949, 0x88a1e356), + TOBN(0x7669f031, 0x93cb7501), TOBN(0x595dc55e, 0xca737b8a), + TOBN(0xa4a319ac, 0xd837879f), TOBN(0x6fc1b49e, 0xed6b67b0), + TOBN(0xe3959933, 0x32f1f3af), TOBN(0x966742eb, 0x65432a2e), + TOBN(0x4b8dc9fe, 0xb4966228), TOBN(0x96cc6312, 0x43f43950), + TOBN(0x12068859, 0xc9b731ee), TOBN(0x7b948dc3, 0x56f79968), + TOBN(0x61e4ad32, 0xed1f8008), TOBN(0xe6c9267a, 0xd8b17538), + TOBN(0x1ac7c5eb, 0x857ff6fb), TOBN(0x994baaa8, 0x55f2fb10), + TOBN(0x84cf14e1, 0x1d248018), TOBN(0x5a39898b, 0x628ac508), + TOBN(0x14fde97b, 0x5fa944f5), TOBN(0xed178030, 0xd12e5ac7), + TOBN(0x042c2af4, 0x97e2feb4), TOBN(0xd36a42d7, 0xaebf7313), + TOBN(0x49d2c9eb, 0x084ffdd7), TOBN(0x9f8aa54b, 0x2ef7c76a), + TOBN(0x9200b7ba, 0x09895e70), TOBN(0x3bd0c66f, 0xddb7fb58), + TOBN(0x2d97d108, 0x78eb4cbb), TOBN(0x2d431068, 0xd84bde31), + TOBN(0x4b523eb7, 0x172ccd1f), TOBN(0x7323cb28, 0x30a6a892), + TOBN(0x97082ec0, 0xcfe153eb), TOBN(0xe97f6b6a, 0xf2aadb97), + TOBN(0x1d3d393e, 0xd1a83da1), TOBN(0xa6a7f9c7, 0x804b2a68), + TOBN(0x4a688b48, 0x2d0cb71e), TOBN(0xa9b4cc5f, 0x40585278), + TOBN(0x5e5db46a, 0xcb66e132), TOBN(0xf1be963a, 0x0d925880), + TOBN(0x944a7027, 0x0317b9e2), TOBN(0xe266f959, 0x48603d48), + TOBN(0x98db6673, 0x5c208899), TOBN(0x90472447, 0xa2fb18a3), + TOBN(0x8a966939, 0x777c619f), TOBN(0x3798142a, 0x2a3be21b), + TOBN(0xb4241cb1, 0x3298b343), TOBN(0xa3a14e49, 0xb44f65a1), + TOBN(0xc5f4d6cd, 0x3ac77acd), TOBN(0xd0288cb5, 0x52b6fc3c), + TOBN(0xd5cc8c2f, 0x1c040abc), TOBN(0xb675511e, 0x06bf9b4a), + TOBN(0xd667da37, 0x9b3aa441), TOBN(0x460d45ce, 0x51601f72), + TOBN(0xe2f73c69, 0x6755ff89), TOBN(0xdd3cf7e7, 0x473017e6), + TOBN(0x8ef5689d, 0x3cf7600d), TOBN(0x948dc4f8, 0xb1fc87b4), + TOBN(0xd9e9fe81, 0x4ea53299), TOBN(0x2d921ca2, 0x98eb6028), + TOBN(0xfaecedfd, 0x0c9803fc), TOBN(0xf38ae891, 0x4d7b4745), + TOBN(0xd8c5fccf, 0xc5e3a3d8), TOBN(0xbefd904c, 0x4079dfbf), + TOBN(0xbc6d6a58, 0xfead0197), TOBN(0x39227077, 0x695532a4), + TOBN(0x09e23e6d, 0xdbef42f5), TOBN(0x7e449b64, 0x480a9908), + TOBN(0x7b969c1a, 0xad9a2e40), TOBN(0x6231d792, 0x9591c2a4), + TOBN(0x87151456, 0x0f664534), TOBN(0x85ceae7c, 0x4b68f103), + TOBN(0xac09c4ae, 0x65578ab9), TOBN(0x33ec6868, 0xf044b10c), + TOBN(0x6ac4832b, 0x3a8ec1f1), TOBN(0x5509d128, 0x5847d5ef), + TOBN(0xf909604f, 0x763f1574), TOBN(0xb16c4303, 0xc32f63c4), + TOBN(0xb6ab2014, 0x7ca23cd3), TOBN(0xcaa7a5c6, 0xa391849d), + TOBN(0x5b0673a3, 0x75678d94), TOBN(0xc982ddd4, 0xdd303e64), + TOBN(0xfd7b000b, 0x5db6f971), TOBN(0xbba2cb1f, 0x6f876f92), + TOBN(0xc77332a3, 0x3c569426), TOBN(0xa159100c, 0x570d74f8), + TOBN(0xfd16847f, 0xdec67ef5), TOBN(0x742ee464, 0x233e76b7), + TOBN(0x0b8e4134, 0xefc2b4c8), TOBN(0xca640b86, 0x42a3e521), + TOBN(0x653a0190, 0x8ceb6aa9), TOBN(0x313c300c, 0x547852d5), + TOBN(0x24e4ab12, 0x6b237af7), TOBN(0x2ba90162, 0x8bb47af8), + TOBN(0x3d5e58d6, 0xa8219bb7), TOBN(0xc691d0bd, 0x1b06c57f), + TOBN(0x0ae4cb10, 0xd257576e), TOBN(0x3569656c, 0xd54a3dc3), + TOBN(0xe5ebaebd, 0x94cda03a), TOBN(0x934e82d3, 0x162bfe13), + TOBN(0x450ac0ba, 0xe251a0c6), TOBN(0x480b9e11, 0xdd6da526), + TOBN(0x00467bc5, 0x8cce08b5), TOBN(0xb636458c, 0x7f178d55), + TOBN(0xc5748bae, 0xa677d806), TOBN(0x2763a387, 0xdfa394eb), + TOBN(0xa12b448a, 0x7d3cebb6), TOBN(0xe7adda3e, 0x6f20d850), + TOBN(0xf63ebce5, 0x1558462c), TOBN(0x58b36143, 0x620088a8), + TOBN(0x8a2cc3ca, 0x4d63c0ee), TOBN(0x51233117, 0x0fe948ce), + TOBN(0x7463fd85, 0x222ef33b), TOBN(0xadf0c7dc, 0x7c603d6c), + TOBN(0x0ec32d3b, 0xfe7765e5), TOBN(0xccaab359, 0xbf380409), + TOBN(0xbdaa84d6, 0x8e59319c), TOBN(0xd9a4c280, 0x9c80c34d), + TOBN(0xa9d89488, 0xa059c142), TOBN(0x6f5ae714, 0xff0b9346), + TOBN(0x068f237d, 0x16fb3664), TOBN(0x5853e4c4, 0x363186ac), + TOBN(0xe2d87d23, 0x63c52f98), TOBN(0x2ec4a766, 0x81828876), + TOBN(0x47b864fa, 0xe14e7b1c), TOBN(0x0c0bc0e5, 0x69192408), + TOBN(0xe4d7681d, 0xb82e9f3e), TOBN(0x83200f0b, 0xdf25e13c), + TOBN(0x8909984c, 0x66f27280), TOBN(0x462d7b00, 0x75f73227), + TOBN(0xd90ba188, 0xf2651798), TOBN(0x74c6e18c, 0x36ab1c34), + TOBN(0xab256ea3, 0x5ef54359), TOBN(0x03466612, 0xd1aa702f), + TOBN(0x624d6049, 0x2ed22e91), TOBN(0x6fdfe0b5, 0x6f072822), + TOBN(0xeeca1115, 0x39ce2271), TOBN(0x98100a4f, 0xdb01614f), + TOBN(0xb6b0daa2, 0xa35c628f), TOBN(0xb6f94d2e, 0xc87e9a47), + TOBN(0xc6773259, 0x1d57d9ce), TOBN(0xf70bfeec, 0x03884a7b), + TOBN(0x5fb35ccf, 0xed2bad01), TOBN(0xa155cbe3, 0x1da6a5c7), + TOBN(0xc2e2594c, 0x30a92f8f), TOBN(0x649c89ce, 0x5bfafe43), + TOBN(0xd158667d, 0xe9ff257a), TOBN(0x9b359611, 0xf32c50ae), + TOBN(0x4b00b20b, 0x906014cf), TOBN(0xf3a8cfe3, 0x89bc7d3d), + TOBN(0x4ff23ffd, 0x248a7d06), TOBN(0x80c5bfb4, 0x878873fa), + TOBN(0xb7d9ad90, 0x05745981), TOBN(0x179c85db, 0x3db01994), + TOBN(0xba41b062, 0x61a6966c), TOBN(0x4d82d052, 0xeadce5a8), + TOBN(0x9e91cd3b, 0xa5e6a318), TOBN(0x47795f4f, 0x95b2dda0), + TOBN(0xecfd7c1f, 0xd55a897c), TOBN(0x009194ab, 0xb29110fb), + TOBN(0x5f0e2046, 0xe381d3b0), TOBN(0x5f3425f6, 0xa98dd291), + TOBN(0xbfa06687, 0x730d50da), TOBN(0x0423446c, 0x4b083b7f), + TOBN(0x397a247d, 0xd69d3417), TOBN(0xeb629f90, 0x387ba42a), + TOBN(0x1ee426cc, 0xd5cd79bf), TOBN(0x0032940b, 0x946c6e18), + TOBN(0x1b1e8ae0, 0x57477f58), TOBN(0xe94f7d34, 0x6d823278), + TOBN(0xc747cb96, 0x782ba21a), TOBN(0xc5254469, 0xf72b33a5), + TOBN(0x772ef6de, 0xc7f80c81), TOBN(0xd73acbfe, 0x2cd9e6b5), + TOBN(0x4075b5b1, 0x49ee90d9), TOBN(0x785c339a, 0xa06e9eba), + TOBN(0xa1030d5b, 0xabf825e0), TOBN(0xcec684c3, 0xa42931dc), + TOBN(0x42ab62c9, 0xc1586e63), TOBN(0x45431d66, 0x5ab43f2b), + TOBN(0x57c8b2c0, 0x55f7835d), TOBN(0x033da338, 0xc1b7f865), + TOBN(0x283c7513, 0xcaa76097), TOBN(0x0a624fa9, 0x36c83906), + TOBN(0x6b20afec, 0x715af2c7), TOBN(0x4b969974, 0xeba78bfd), + TOBN(0x220755cc, 0xd921d60e), TOBN(0x9b944e10, 0x7baeca13), + TOBN(0x04819d51, 0x5ded93d4), TOBN(0x9bbff86e, 0x6dddfd27), + TOBN(0x6b344130, 0x77adc612), TOBN(0xa7496529, 0xbbd803a0), + TOBN(0x1a1baaa7, 0x6d8805bd), TOBN(0xc8403902, 0x470343ad), + TOBN(0x39f59f66, 0x175adff1), TOBN(0x0b26d7fb, 0xb7d8c5b7), + TOBN(0xa875f5ce, 0x529d75e3), TOBN(0x85efc7e9, 0x41325cc2), + TOBN(0x21950b42, 0x1ff6acd3), TOBN(0xffe70484, 0x53dc6909), + TOBN(0xff4cd0b2, 0x28766127), TOBN(0xabdbe608, 0x4fb7db2b), + TOBN(0x837c9228, 0x5e1109e8), TOBN(0x26147d27, 0xf4645b5a), + TOBN(0x4d78f592, 0xf7818ed8), TOBN(0xd394077e, 0xf247fa36), + TOBN(0x0fb9c2d0, 0x488c171a), TOBN(0xa78bfbaa, 0x13685278), + TOBN(0xedfbe268, 0xd5b1fa6a), TOBN(0x0dceb8db, 0x2b7eaba7), + TOBN(0xbf9e8089, 0x9ae2b710), TOBN(0xefde7ae6, 0xa4449c96), + TOBN(0x43b7716b, 0xcc143a46), TOBN(0xd7d34194, 0xc3628c13), + TOBN(0x508cec1c, 0x3b3f64c9), TOBN(0xe20bc0ba, 0x1e5edf3f), + TOBN(0xda1deb85, 0x2f4318d4), TOBN(0xd20ebe0d, 0x5c3fa443), + TOBN(0x370b4ea7, 0x73241ea3), TOBN(0x61f1511c, 0x5e1a5f65), + TOBN(0x99a5e23d, 0x82681c62), TOBN(0xd731e383, 0xa2f54c2d), + TOBN(0x2692f36e, 0x83445904), TOBN(0x2e0ec469, 0xaf45f9c0), + TOBN(0x905a3201, 0xc67528b7), TOBN(0x88f77f34, 0xd0e5e542), + TOBN(0xf67a8d29, 0x5864687c), TOBN(0x23b92eae, 0x22df3562), + TOBN(0x5c27014b, 0x9bbec39e), TOBN(0x7ef2f226, 0x9c0f0f8d), + TOBN(0x97359638, 0x546c4d8d), TOBN(0x5f9c3fc4, 0x92f24679), + TOBN(0x912e8bed, 0xa8c8acd9), TOBN(0xec3a318d, 0x306634b0), + TOBN(0x80167f41, 0xc31cb264), TOBN(0x3db82f6f, 0x522113f2), + TOBN(0xb155bcd2, 0xdcafe197), TOBN(0xfba1da59, 0x43465283), + TOBN(0xa0425b8e, 0xb212cf53), TOBN(0x4f2e512e, 0xf8557c5f), + TOBN(0xc1286ff9, 0x25c4d56c), TOBN(0xbb8a0fea, 0xee26c851), + TOBN(0xc28f70d2, 0xe7d6107e), TOBN(0x7ee0c444, 0xe76265aa), + TOBN(0x3df277a4, 0x1d1936b1), TOBN(0x1a556e3f, 0xea9595eb), + TOBN(0x258bbbf9, 0xe7305683), TOBN(0x31eea5bf, 0x07ef5be6), + TOBN(0x0deb0e4a, 0x46c814c1), TOBN(0x5cee8449, 0xa7b730dd), + TOBN(0xeab495c5, 0xa0182bde), TOBN(0xee759f87, 0x9e27a6b4), + TOBN(0xc2cf6a68, 0x80e518ca), TOBN(0x25e8013f, 0xf14cf3f4), + TOBN(0x8fc44140, 0x7e8d7a14), TOBN(0xbb1ff3ca, 0x9556f36a), + TOBN(0x6a844385, 0x14600044), TOBN(0xba3f0c4a, 0x7451ae63), + TOBN(0xdfcac25b, 0x1f9af32a), TOBN(0x01e0db86, 0xb1f2214b), + TOBN(0x4e9a5bc2, 0xa4b596ac), TOBN(0x83927681, 0x026c2c08), + TOBN(0x3ec832e7, 0x7acaca28), TOBN(0x1bfeea57, 0xc7385b29), + TOBN(0x068212e3, 0xfd1eaf38), TOBN(0xc1329830, 0x6acf8ccc), + TOBN(0xb909f2db, 0x2aac9e59), TOBN(0x5748060d, 0xb661782a), + TOBN(0xc5ab2632, 0xc79b7a01), TOBN(0xda44c6c6, 0x00017626), + TOBN(0xf26c00e8, 0xa7ea82f0), TOBN(0x99cac80d, 0xe4299aaf), + TOBN(0xd66fe3b6, 0x7ed78be1), TOBN(0x305f725f, 0x648d02cd), + TOBN(0x33ed1bc4, 0x623fb21b), TOBN(0xfa70533e, 0x7a6319ad), + TOBN(0x17ab562d, 0xbe5ffb3e), TOBN(0x06374994, 0x56674741), + TOBN(0x69d44ed6, 0x5c46aa8e), TOBN(0x2100d5d3, 0xa8d063d1), + TOBN(0xcb9727ea, 0xa2d17c36), TOBN(0x4c2bab1b, 0x8add53b7), + TOBN(0xa084e90c, 0x15426704), TOBN(0x778afcd3, 0xa837ebea), + TOBN(0x6651f701, 0x7ce477f8), TOBN(0xa0624998, 0x46fb7a8b), + TOBN(0xdc1e6828, 0xed8a6e19), TOBN(0x33fc2336, 0x4189d9c7), + TOBN(0x026f8fe2, 0x671c39bc), TOBN(0xd40c4ccd, 0xbc6f9915), + TOBN(0xafa135bb, 0xf80e75ca), TOBN(0x12c651a0, 0x22adff2c), + TOBN(0xc40a04bd, 0x4f51ad96), TOBN(0x04820109, 0xbbe4e832), + TOBN(0x3667eb1a, 0x7f4c04cc), TOBN(0x59556621, 0xa9404f84), + TOBN(0x71cdf653, 0x7eceb50a), TOBN(0x994a44a6, 0x9b8335fa), + TOBN(0xd7faf819, 0xdbeb9b69), TOBN(0x473c5680, 0xeed4350d), + TOBN(0xb6658466, 0xda44bba2), TOBN(0x0d1bc780, 0x872bdbf3), + TOBN(0xe535f175, 0xa1962f91), TOBN(0x6ed7e061, 0xed58f5a7), + TOBN(0x177aa4c0, 0x2089a233), TOBN(0x0dbcb03a, 0xe539b413), + TOBN(0xe3dc424e, 0xbb32e38e), TOBN(0x6472e5ef, 0x6806701e), + TOBN(0xdd47ff98, 0x814be9ee), TOBN(0x6b60cfff, 0x35ace009), + TOBN(0xb8d3d931, 0x9ff91fe5), TOBN(0x039c4800, 0xf0518eed), + TOBN(0x95c37632, 0x9182cb26), TOBN(0x0763a434, 0x82fc568d), + TOBN(0x707c04d5, 0x383e76ba), TOBN(0xac98b930, 0x824e8197), + TOBN(0x92bf7c8f, 0x91230de0), TOBN(0x90876a01, 0x40959b70), + TOBN(0xdb6d96f3, 0x05968b80), TOBN(0x380a0913, 0x089f73b9), + TOBN(0x7da70b83, 0xc2c61e01), TOBN(0x95fb8394, 0x569b38c7), + TOBN(0x9a3c6512, 0x80edfe2f), TOBN(0x8f726bb9, 0x8faeaf82), + TOBN(0x8010a4a0, 0x78424bf8), TOBN(0x29672044, 0x0e844970)} + , + {TOBN(0x63c5cb81, 0x7a2ad62a), TOBN(0x7ef2b6b9, 0xac62ff54), + TOBN(0x3749bba4, 0xb3ad9db5), TOBN(0xad311f2c, 0x46d5a617), + TOBN(0xb77a8087, 0xc2ff3b6d), TOBN(0xb46feaf3, 0x367834ff), + TOBN(0xf8aa266d, 0x75d6b138), TOBN(0xfa38d320, 0xec008188), + TOBN(0x486d8ffa, 0x696946fc), TOBN(0x50fbc6d8, 0xb9cba56d), + TOBN(0x7e3d423e, 0x90f35a15), TOBN(0x7c3da195, 0xc0dd962c), + TOBN(0xe673fdb0, 0x3cfd5d8b), TOBN(0x0704b7c2, 0x889dfca5), + TOBN(0xf6ce581f, 0xf52305aa), TOBN(0x399d49eb, 0x914d5e53), + TOBN(0x380a496d, 0x6ec293cd), TOBN(0x733dbda7, 0x8e7051f5), + TOBN(0x037e388d, 0xb849140a), TOBN(0xee4b32b0, 0x5946dbf6), + TOBN(0xb1c4fda9, 0xcae368d1), TOBN(0x5001a7b0, 0xfdb0b2f3), + TOBN(0x6df59374, 0x2e3ac46e), TOBN(0x4af675f2, 0x39b3e656), + TOBN(0x44e38110, 0x39949296), TOBN(0x5b63827b, 0x361db1b5), + TOBN(0x3e5323ed, 0x206eaff5), TOBN(0x942370d2, 0xc21f4290), + TOBN(0xf2caaf2e, 0xe0d985a1), TOBN(0x192cc64b, 0x7239846d), + TOBN(0x7c0b8f47, 0xae6312f8), TOBN(0x7dc61f91, 0x96620108), + TOBN(0xb830fb5b, 0xc2da7de9), TOBN(0xd0e643df, 0x0ff8d3be), + TOBN(0x31ee77ba, 0x188a9641), TOBN(0x4e8aa3aa, 0xbcf6d502), + TOBN(0xf9fb6532, 0x9a49110f), TOBN(0xd18317f6, 0x2dd6b220), + TOBN(0x7e3ced41, 0x52c3ea5a), TOBN(0x0d296a14, 0x7d579c4a), + TOBN(0x35d6a53e, 0xed4c3717), TOBN(0x9f8240cf, 0x3d0ed2a3), + TOBN(0x8c0d4d05, 0xe5543aa5), TOBN(0x45d5bbfb, 0xdd33b4b4), + TOBN(0xfa04cc73, 0x137fd28e), TOBN(0x862ac6ef, 0xc73b3ffd), + TOBN(0x403ff9f5, 0x31f51ef2), TOBN(0x34d5e0fc, 0xbc73f5a2), + TOBN(0xf2526820, 0x08913f4f), TOBN(0xea20ed61, 0xeac93d95), + TOBN(0x51ed38b4, 0x6ca6b26c), TOBN(0x8662dcbc, 0xea4327b0), + TOBN(0x6daf295c, 0x725d2aaa), TOBN(0xbad2752f, 0x8e52dcda), + TOBN(0x2210e721, 0x0b17dacc), TOBN(0xa37f7912, 0xd51e8232), + TOBN(0x4f7081e1, 0x44cc3add), TOBN(0xd5ffa1d6, 0x87be82cf), + TOBN(0x89890b6c, 0x0edd6472), TOBN(0xada26e1a, 0x3ed17863), + TOBN(0x276f2715, 0x63483caa), TOBN(0xe6924cd9, 0x2f6077fd), + TOBN(0x05a7fe98, 0x0a466e3c), TOBN(0xf1c794b0, 0xb1902d1f), + TOBN(0xe5213688, 0x82a8042c), TOBN(0xd931cfaf, 0xcd278298), + TOBN(0x069a0ae0, 0xf597a740), TOBN(0x0adbb3f3, 0xeb59107c), + TOBN(0x983e951e, 0x5eaa8eb8), TOBN(0xe663a8b5, 0x11b48e78), + TOBN(0x1631cc0d, 0x8a03f2c5), TOBN(0x7577c11e, 0x11e271e2), + TOBN(0x33b2385c, 0x08369a90), TOBN(0x2990c59b, 0x190eb4f8), + TOBN(0x819a6145, 0xc68eac80), TOBN(0x7a786d62, 0x2ec4a014), + TOBN(0x33faadbe, 0x20ac3a8d), TOBN(0x31a21781, 0x5aba2d30), + TOBN(0x209d2742, 0xdba4f565), TOBN(0xdb2ce9e3, 0x55aa0fbb), + TOBN(0x8cef334b, 0x168984df), TOBN(0xe81dce17, 0x33879638), + TOBN(0xf6e6949c, 0x263720f0), TOBN(0x5c56feaf, 0xf593cbec), + TOBN(0x8bff5601, 0xfde58c84), TOBN(0x74e24117, 0x2eccb314), + TOBN(0xbcf01b61, 0x4c9a8a78), TOBN(0xa233e35e, 0x544c9868), + TOBN(0xb3156bf3, 0x8bd7aff1), TOBN(0x1b5ee4cb, 0x1d81b146), + TOBN(0x7ba1ac41, 0xd628a915), TOBN(0x8f3a8f9c, 0xfd89699e), + TOBN(0x7329b9c9, 0xa0748be7), TOBN(0x1d391c95, 0xa92e621f), + TOBN(0xe51e6b21, 0x4d10a837), TOBN(0xd255f53a, 0x4947b435), + TOBN(0x07669e04, 0xf1788ee3), TOBN(0xc14f27af, 0xa86938a2), + TOBN(0x8b47a334, 0xe93a01c0), TOBN(0xff627438, 0xd9366808), + TOBN(0x7a0985d8, 0xca2a5965), TOBN(0x3d9a5542, 0xd6e9b9b3), + TOBN(0xc23eb80b, 0x4cf972e8), TOBN(0x5c1c33bb, 0x4fdf72fd), + TOBN(0x0c4a58d4, 0x74a86108), TOBN(0xf8048a8f, 0xee4c5d90), + TOBN(0xe3c7c924, 0xe86d4c80), TOBN(0x28c889de, 0x056a1e60), + TOBN(0x57e2662e, 0xb214a040), TOBN(0xe8c48e98, 0x37e10347), + TOBN(0x87742862, 0x80ac748a), TOBN(0xf1c24022, 0x186b06f2), + TOBN(0xac2dd4c3, 0x5f74040a), TOBN(0x409aeb71, 0xfceac957), + TOBN(0x4fbad782, 0x55c4ec23), TOBN(0xb359ed61, 0x8a7b76ec), + TOBN(0x12744926, 0xed6f4a60), TOBN(0xe21e8d7f, 0x4b912de3), + TOBN(0xe2575a59, 0xfc705a59), TOBN(0x72f1d4de, 0xed2dbc0e), + TOBN(0x3d2b24b9, 0xeb7926b8), TOBN(0xbff88cb3, 0xcdbe5509), + TOBN(0xd0f399af, 0xe4dd640b), TOBN(0x3c5fe130, 0x2f76ed45), + TOBN(0x6f3562f4, 0x3764fb3d), TOBN(0x7b5af318, 0x3151b62d), + TOBN(0xd5bd0bc7, 0xd79ce5f3), TOBN(0xfdaf6b20, 0xec66890f), + TOBN(0x735c67ec, 0x6063540c), TOBN(0x50b259c2, 0xe5f9cb8f), + TOBN(0xb8734f9a, 0x3f99c6ab), TOBN(0xf8cc13d5, 0xa3a7bc85), + TOBN(0x80c1b305, 0xc5217659), TOBN(0xfe5364d4, 0x4ec12a54), + TOBN(0xbd87045e, 0x681345fe), TOBN(0x7f8efeb1, 0x582f897f), + TOBN(0xe8cbf1e5, 0xd5923359), TOBN(0xdb0cea9d, 0x539b9fb0), + TOBN(0x0c5b34cf, 0x49859b98), TOBN(0x5e583c56, 0xa4403cc6), + TOBN(0x11fc1a2d, 0xd48185b7), TOBN(0xc93fbc7e, 0x6e521787), + TOBN(0x47e7a058, 0x05105b8b), TOBN(0x7b4d4d58, 0xdb8260c8), + TOBN(0xe33930b0, 0x46eb842a), TOBN(0x8e844a9a, 0x7bdae56d), + TOBN(0x34ef3a9e, 0x13f7fdfc), TOBN(0xb3768f82, 0x636ca176), + TOBN(0x2821f4e0, 0x4e09e61c), TOBN(0x414dc3a1, 0xa0c7cddc), + TOBN(0xd5379437, 0x54945fcd), TOBN(0x151b6eef, 0xb3555ff1), + TOBN(0xb31bd613, 0x6339c083), TOBN(0x39ff8155, 0xdfb64701), + TOBN(0x7c3388d2, 0xe29604ab), TOBN(0x1e19084b, 0xa6b10442), + TOBN(0x17cf54c0, 0xeccd47ef), TOBN(0x89693385, 0x4a5dfb30), + TOBN(0x69d023fb, 0x47daf9f6), TOBN(0x9222840b, 0x7d91d959), + TOBN(0x439108f5, 0x803bac62), TOBN(0x0b7dd91d, 0x379bd45f), + TOBN(0xd651e827, 0xca63c581), TOBN(0x5c5d75f6, 0x509c104f), + TOBN(0x7d5fc738, 0x1f2dc308), TOBN(0x20faa7bf, 0xd98454be), + TOBN(0x95374bee, 0xa517b031), TOBN(0xf036b9b1, 0x642692ac), + TOBN(0xc5106109, 0x39842194), TOBN(0xb7e2353e, 0x49d05295), + TOBN(0xfc8c1d5c, 0xefb42ee0), TOBN(0xe04884eb, 0x08ce811c), + TOBN(0xf1f75d81, 0x7419f40e), TOBN(0x5b0ac162, 0xa995c241), + TOBN(0x120921bb, 0xc4c55646), TOBN(0x713520c2, 0x8d33cf97), + TOBN(0xb4a65a5c, 0xe98c5100), TOBN(0x6cec871d, 0x2ddd0f5a), + TOBN(0x251f0b7f, 0x9ba2e78b), TOBN(0x224a8434, 0xce3a2a5f), + TOBN(0x26827f61, 0x25f5c46f), TOBN(0x6a22bedc, 0x48545ec0), + TOBN(0x25ae5fa0, 0xb1bb5cdc), TOBN(0xd693682f, 0xfcb9b98f), + TOBN(0x32027fe8, 0x91e5d7d3), TOBN(0xf14b7d17, 0x73a07678), + TOBN(0xf88497b3, 0xc0dfdd61), TOBN(0xf7c2eec0, 0x2a8c4f48), + TOBN(0xaa5573f4, 0x3756e621), TOBN(0xc013a240, 0x1825b948), + TOBN(0x1c03b345, 0x63878572), TOBN(0xa0472bea, 0x653a4184), + TOBN(0xf4222e27, 0x0ac69a80), TOBN(0x34096d25, 0xf51e54f6), + TOBN(0x00a648cb, 0x8fffa591), TOBN(0x4e87acdc, 0x69b6527f), + TOBN(0x0575e037, 0xe285ccb4), TOBN(0x188089e4, 0x50ddcf52), + TOBN(0xaa96c9a8, 0x870ff719), TOBN(0x74a56cd8, 0x1fc7e369), + TOBN(0x41d04ee2, 0x1726931a), TOBN(0x0bbbb2c8, 0x3660ecfd), + TOBN(0xa6ef6de5, 0x24818e18), TOBN(0xe421cc51, 0xe7d57887), + TOBN(0xf127d208, 0xbea87be6), TOBN(0x16a475d3, 0xb1cdd682), + TOBN(0x9db1b684, 0x439b63f7), TOBN(0x5359b3db, 0xf0f113b6), + TOBN(0xdfccf1de, 0x8bf06e31), TOBN(0x1fdf8f44, 0xdd383901), + TOBN(0x10775cad, 0x5017e7d2), TOBN(0xdfc3a597, 0x58d11eef), + TOBN(0x6ec9c8a0, 0xb1ecff10), TOBN(0xee6ed6cc, 0x28400549), + TOBN(0xb5ad7bae, 0x1b4f8d73), TOBN(0x61b4f11d, 0xe00aaab9), + TOBN(0x7b32d69b, 0xd4eff2d7), TOBN(0x88ae6771, 0x4288b60f), + TOBN(0x159461b4, 0x37a1e723), TOBN(0x1f3d4789, 0x570aae8c), + TOBN(0x869118c0, 0x7f9871da), TOBN(0x35fbda78, 0xf635e278), + TOBN(0x738f3641, 0xe1541dac), TOBN(0x6794b13a, 0xc0dae45f), + TOBN(0x065064ac, 0x09cc0917), TOBN(0x27c53729, 0xc68540fd), + TOBN(0x0d2d4c8e, 0xef227671), TOBN(0xd23a9f80, 0xa1785a04), + TOBN(0x98c59528, 0x52650359), TOBN(0xfa09ad01, 0x74a1acad), + TOBN(0x082d5a29, 0x0b55bf5c), TOBN(0xa40f1c67, 0x419b8084), + TOBN(0x3a5c752e, 0xdcc18770), TOBN(0x4baf1f2f, 0x8825c3a5), + TOBN(0xebd63f74, 0x21b153ed), TOBN(0xa2383e47, 0xb2f64723), + TOBN(0xe7bf620a, 0x2646d19a), TOBN(0x56cb44ec, 0x03c83ffd), + TOBN(0xaf7267c9, 0x4f6be9f1), TOBN(0x8b2dfd7b, 0xc06bb5e9), + TOBN(0xb87072f2, 0xa672c5c7), TOBN(0xeacb11c8, 0x0d53c5e2), + TOBN(0x22dac29d, 0xff435932), TOBN(0x37bdb99d, 0x4408693c), + TOBN(0xf6e62fb6, 0x2899c20f), TOBN(0x3535d512, 0x447ece24), + TOBN(0xfbdc6b88, 0xff577ce3), TOBN(0x726693bd, 0x190575f2), + TOBN(0x6772b0e5, 0xab4b35a2), TOBN(0x1d8b6001, 0xf5eeaacf), + TOBN(0x728f7ce4, 0x795b9580), TOBN(0x4a20ed2a, 0x41fb81da), + TOBN(0x9f685cd4, 0x4fec01e6), TOBN(0x3ed7ddcc, 0xa7ff50ad), + TOBN(0x460fd264, 0x0c2d97fd), TOBN(0x3a241426, 0xeb82f4f9), + TOBN(0x17d1df2c, 0x6a8ea820), TOBN(0xb2b50d3b, 0xf22cc254), + TOBN(0x03856cba, 0xb7291426), TOBN(0x87fd26ae, 0x04f5ee39), + TOBN(0x9cb696cc, 0x02bee4ba), TOBN(0x53121804, 0x06820fd6), + TOBN(0xa5dfc269, 0x0212e985), TOBN(0x666f7ffa, 0x160f9a09), + TOBN(0xc503cd33, 0xbccd9617), TOBN(0x365dede4, 0xba7730a3), + TOBN(0x798c6355, 0x5ddb0786), TOBN(0xa6c3200e, 0xfc9cd3bc), + TOBN(0x060ffb2c, 0xe5e35efd), TOBN(0x99a4e25b, 0x5555a1c1), + TOBN(0x11d95375, 0xf70b3751), TOBN(0x0a57354a, 0x160e1bf6), + TOBN(0xecb3ae4b, 0xf8e4b065), TOBN(0x07a834c4, 0x2e53022b), + TOBN(0x1cd300b3, 0x8692ed96), TOBN(0x16a6f792, 0x61ee14ec), + TOBN(0x8f1063c6, 0x6a8649ed), TOBN(0xfbcdfcfe, 0x869f3e14), + TOBN(0x2cfb97c1, 0x00a7b3ec), TOBN(0xcea49b3c, 0x7130c2f1), + TOBN(0x462d044f, 0xe9d96488), TOBN(0x4b53d52e, 0x8182a0c1), + TOBN(0x84b6ddd3, 0x0391e9e9), TOBN(0x80ab7b48, 0xb1741a09), + TOBN(0xec0e15d4, 0x27d3317f), TOBN(0x8dfc1ddb, 0x1a64671e), + TOBN(0x93cc5d5f, 0xd49c5b92), TOBN(0xc995d53d, 0x3674a331), + TOBN(0x302e41ec, 0x090090ae), TOBN(0x2278a0cc, 0xedb06830), + TOBN(0x1d025932, 0xfbc99690), TOBN(0x0c32fbd2, 0xb80d68da), + TOBN(0xd79146da, 0xf341a6c1), TOBN(0xae0ba139, 0x1bef68a0), + TOBN(0xc6b8a563, 0x8d774b3a), TOBN(0x1cf307bd, 0x880ba4d7), + TOBN(0xc033bdc7, 0x19803511), TOBN(0xa9f97b3b, 0x8888c3be), + TOBN(0x3d68aebc, 0x85c6d05e), TOBN(0xc3b88a9d, 0x193919eb), + TOBN(0x2d300748, 0xc48b0ee3), TOBN(0x7506bc7c, 0x07a746c1), + TOBN(0xfc48437c, 0x6e6d57f3), TOBN(0x5bd71587, 0xcfeaa91a), + TOBN(0xa4ed0408, 0xc1bc5225), TOBN(0xd0b946db, 0x2719226d), + TOBN(0x109ecd62, 0x758d2d43), TOBN(0x75c8485a, 0x2751759b), + TOBN(0xb0b75f49, 0x9ce4177a), TOBN(0x4fa61a1e, 0x79c10c3d), + TOBN(0xc062d300, 0xa167fcd7), TOBN(0x4df3874c, 0x750f0fa8), + TOBN(0x29ae2cf9, 0x83dfedc9), TOBN(0xf8437134, 0x8d87631a), + TOBN(0xaf571711, 0x7429c8d2), TOBN(0x18d15867, 0x146d9272), + TOBN(0x83053ecf, 0x69769bb7), TOBN(0xc55eb856, 0xc479ab82), + TOBN(0x5ef7791c, 0x21b0f4b2), TOBN(0xaa5956ba, 0x3d491525), + TOBN(0x407a96c2, 0x9fe20eba), TOBN(0xf27168bb, 0xe52a5ad3), + TOBN(0x43b60ab3, 0xbf1d9d89), TOBN(0xe45c51ef, 0x710e727a), + TOBN(0xdfca5276, 0x099b4221), TOBN(0x8dc6407c, 0x2557a159), + TOBN(0x0ead8335, 0x91035895), TOBN(0x0a9db957, 0x9c55dc32), + TOBN(0xe40736d3, 0xdf61bc76), TOBN(0x13a619c0, 0x3f778cdb), + TOBN(0x6dd921a4, 0xc56ea28f), TOBN(0x76a52433, 0x2fa647b4), + TOBN(0x23591891, 0xac5bdc5d), TOBN(0xff4a1a72, 0xbac7dc01), + TOBN(0x9905e261, 0x62df8453), TOBN(0x3ac045df, 0xe63b265f), + TOBN(0x8a3f341b, 0xad53dba7), TOBN(0x8ec269cc, 0x837b625a), + TOBN(0xd71a2782, 0x3ae31189), TOBN(0x8fb4f9a3, 0x55e96120), + TOBN(0x804af823, 0xff9875cf), TOBN(0x23224f57, 0x5d442a9b), + TOBN(0x1c4d3b9e, 0xecc62679), TOBN(0x91da22fb, 0xa0e7ddb1), + TOBN(0xa370324d, 0x6c04a661), TOBN(0x9710d3b6, 0x5e376d17), + TOBN(0xed8c98f0, 0x3044e357), TOBN(0xc364ebbe, 0x6422701c), + TOBN(0x347f5d51, 0x7733d61c), TOBN(0xd55644b9, 0xcea826c3), + TOBN(0x80c6e0ad, 0x55a25548), TOBN(0x0aa7641d, 0x844220a7), + TOBN(0x1438ec81, 0x31810660), TOBN(0x9dfa6507, 0xde4b4043), + TOBN(0x10b515d8, 0xcc3e0273), TOBN(0x1b6066dd, 0x28d8cfb2), + TOBN(0xd3b04591, 0x9c9efebd), TOBN(0x425d4bdf, 0xa21c1ff4), + TOBN(0x5fe5af19, 0xd57607d3), TOBN(0xbbf773f7, 0x54481084), + TOBN(0x8435bd69, 0x94b03ed1), TOBN(0xd9ad1de3, 0x634cc546), + TOBN(0x2cf423fc, 0x00e420ca), TOBN(0xeed26d80, 0xa03096dd), + TOBN(0xd7f60be7, 0xa4db09d2), TOBN(0xf47f569d, 0x960622f7), + TOBN(0xe5925fd7, 0x7296c729), TOBN(0xeff2db26, 0x26ca2715), + TOBN(0xa6fcd014, 0xb913e759), TOBN(0x53da4786, 0x8ff4de93), + TOBN(0x14616d79, 0xc32068e1), TOBN(0xb187d664, 0xccdf352e), + TOBN(0xf7afb650, 0x1dc90b59), TOBN(0x8170e943, 0x7daa1b26), + TOBN(0xc8e3bdd8, 0x700c0a84), TOBN(0x6e8d345f, 0x6482bdfa), + TOBN(0x84cfbfa1, 0xc5c5ea50), TOBN(0xd3baf14c, 0x67960681), + TOBN(0x26398403, 0x0dd50942), TOBN(0xe4b7839c, 0x4716a663), + TOBN(0xd5f1f794, 0xe7de6dc0), TOBN(0x5cd0f4d4, 0x622aa7ce), + TOBN(0x5295f3f1, 0x59acfeec), TOBN(0x8d933552, 0x953e0607), + TOBN(0xc7db8ec5, 0x776c5722), TOBN(0xdc467e62, 0x2b5f290c), + TOBN(0xd4297e70, 0x4ff425a9), TOBN(0x4be924c1, 0x0cf7bb72), + TOBN(0x0d5dc5ae, 0xa1892131), TOBN(0x8bf8a8e3, 0xa705c992), + TOBN(0x73a0b064, 0x7a305ac5), TOBN(0x00c9ca4e, 0x9a8c77a8), + TOBN(0x5dfee80f, 0x83774bdd), TOBN(0x63131602, 0x85734485), + TOBN(0xa1b524ae, 0x914a69a9), TOBN(0xebc2ffaf, 0xd4e300d7), + TOBN(0x52c93db7, 0x7cfa46a5), TOBN(0x71e6161f, 0x21653b50), + TOBN(0x3574fc57, 0xa4bc580a), TOBN(0xc09015dd, 0xe1bc1253), + TOBN(0x4b7b47b2, 0xd174d7aa), TOBN(0x4072d8e8, 0xf3a15d04), + TOBN(0xeeb7d47f, 0xd6fa07ed), TOBN(0x6f2b9ff9, 0xedbdafb1), + TOBN(0x18c51615, 0x3760fe8a), TOBN(0x7a96e6bf, 0xf06c6c13), + TOBN(0x4d7a0410, 0x0ea2d071), TOBN(0xa1914e9b, 0x0be2a5ce), + TOBN(0x5726e357, 0xd8a3c5cf), TOBN(0x1197ecc3, 0x2abb2b13), + TOBN(0x6c0d7f7f, 0x31ae88dd), TOBN(0x15b20d1a, 0xfdbb3efe), + TOBN(0xcd06aa26, 0x70584039), TOBN(0x2277c969, 0xa7dc9747), + TOBN(0xbca69587, 0x7855d815), TOBN(0x899ea238, 0x5188b32a), + TOBN(0x37d9228b, 0x760c1c9d), TOBN(0xc7efbb11, 0x9b5c18da), + TOBN(0x7f0d1bc8, 0x19f6dbc5), TOBN(0x4875384b, 0x07e6905b), + TOBN(0xc7c50baa, 0x3ba8cd86), TOBN(0xb0ce40fb, 0xc2905de0), + TOBN(0x70840673, 0x7a231952), TOBN(0xa912a262, 0xcf43de26), + TOBN(0x9c38ddcc, 0xeb5b76c1), TOBN(0x746f5285, 0x26fc0ab4), + TOBN(0x52a63a50, 0xd62c269f), TOBN(0x60049c55, 0x99458621), + TOBN(0xe7f48f82, 0x3c2f7c9e), TOBN(0x6bd99043, 0x917d5cf3), + TOBN(0xeb1317a8, 0x8701f469), TOBN(0xbd3fe2ed, 0x9a449fe0), + TOBN(0x421e79ca, 0x12ef3d36), TOBN(0x9ee3c36c, 0x3e7ea5de), + TOBN(0xe48198b5, 0xcdff36f7), TOBN(0xaff4f967, 0xc6b82228), + TOBN(0x15e19dd0, 0xc47adb7e), TOBN(0x45699b23, 0x032e7dfa), + TOBN(0x40680c8b, 0x1fae026a), TOBN(0x5a347a48, 0x550dbf4d), + TOBN(0xe652533b, 0x3cef0d7d), TOBN(0xd94f7b18, 0x2bbb4381), + TOBN(0x838752be, 0x0e80f500), TOBN(0x8e6e2488, 0x9e9c9bfb), + TOBN(0xc9751697, 0x16caca6a), TOBN(0x866c49d8, 0x38531ad9), + TOBN(0xc917e239, 0x7151ade1), TOBN(0x2d016ec1, 0x6037c407), + TOBN(0xa407ccc9, 0x00eac3f9), TOBN(0x835f6280, 0xe2ed4748), + TOBN(0xcc54c347, 0x1cc98e0d), TOBN(0x0e969937, 0xdcb572eb), + TOBN(0x1b16c8e8, 0x8f30c9cb), TOBN(0xa606ae75, 0x373c4661), + TOBN(0x47aa689b, 0x35502cab), TOBN(0xf89014ae, 0x4d9bb64f), + TOBN(0x202f6a9c, 0x31c71f7b), TOBN(0x01f95aa3, 0x296ffe5c), + TOBN(0x5fc06014, 0x53cec3a3), TOBN(0xeb991237, 0x5f498a45), + TOBN(0xae9a935e, 0x5d91ba87), TOBN(0xc6ac6281, 0x0b564a19), + TOBN(0x8a8fe81c, 0x3bd44e69), TOBN(0x7c8b467f, 0x9dd11d45), + TOBN(0xf772251f, 0xea5b8e69), TOBN(0xaeecb3bd, 0xc5b75fbc), + TOBN(0x1aca3331, 0x887ff0e5), TOBN(0xbe5d49ff, 0x19f0a131), + TOBN(0x582c13aa, 0xe5c8646f), TOBN(0xdbaa12e8, 0x20e19980), + TOBN(0x8f40f31a, 0xf7abbd94), TOBN(0x1f13f5a8, 0x1dfc7663), + TOBN(0x5d81f1ee, 0xaceb4fc0), TOBN(0x36256002, 0x5e6f0f42), + TOBN(0x4b67d6d7, 0x751370c8), TOBN(0x2608b698, 0x03e80589), + TOBN(0xcfc0d2fc, 0x05268301), TOBN(0xa6943d39, 0x40309212), + TOBN(0x192a90c2, 0x1fd0e1c2), TOBN(0xb209f113, 0x37f1dc76), + TOBN(0xefcc5e06, 0x97bf1298), TOBN(0xcbdb6730, 0x219d639e), + TOBN(0xd009c116, 0xb81e8c6f), TOBN(0xa3ffdde3, 0x1a7ce2e5), + TOBN(0xc53fbaaa, 0xa914d3ba), TOBN(0x836d500f, 0x88df85ee), + TOBN(0xd98dc71b, 0x66ee0751), TOBN(0x5a3d7005, 0x714516fd), + TOBN(0x21d3634d, 0x39eedbba), TOBN(0x35cd2e68, 0x0455a46d), + TOBN(0xc8cafe65, 0xf9d7eb0c), TOBN(0xbda3ce9e, 0x00cefb3e), + TOBN(0xddc17a60, 0x2c9cf7a4), TOBN(0x01572ee4, 0x7bcb8773), + TOBN(0xa92b2b01, 0x8c7548df), TOBN(0x732fd309, 0xa84600e3), + TOBN(0xe22109c7, 0x16543a40), TOBN(0x9acafd36, 0xfede3c6c), + TOBN(0xfb206852, 0x6824e614), TOBN(0x2a4544a9, 0xda25dca0), + TOBN(0x25985262, 0x91d60b06), TOBN(0x281b7be9, 0x28753545), + TOBN(0xec667b1a, 0x90f13b27), TOBN(0x33a83aff, 0x940e2eb4), + TOBN(0x80009862, 0xd5d721d5), TOBN(0x0c3357a3, 0x5bd3a182), + TOBN(0x27f3a83b, 0x7aa2cda4), TOBN(0xb58ae74e, 0xf6f83085), + TOBN(0x2a911a81, 0x2e6dad6b), TOBN(0xde286051, 0xf43d6c5b), + TOBN(0x4bdccc41, 0xf996c4d8), TOBN(0xe7312ec0, 0x0ae1e24e)} + , + {TOBN(0xf8d112e7, 0x6e6485b3), TOBN(0x4d3e24db, 0x771c52f8), + TOBN(0x48e3ee41, 0x684a2f6d), TOBN(0x7161957d, 0x21d95551), + TOBN(0x19631283, 0xcdb12a6c), TOBN(0xbf3fa882, 0x2e50e164), + TOBN(0xf6254b63, 0x3166cc73), TOBN(0x3aefa7ae, 0xaee8cc38), + TOBN(0x79b0fe62, 0x3b36f9fd), TOBN(0x26543b23, 0xfde19fc0), + TOBN(0x136e64a0, 0x958482ef), TOBN(0x23f63771, 0x9b095825), + TOBN(0x14cfd596, 0xb6a1142e), TOBN(0x5ea6aac6, 0x335aac0b), + TOBN(0x86a0e8bd, 0xf3081dd5), TOBN(0x5fb89d79, 0x003dc12a), + TOBN(0xf615c33a, 0xf72e34d4), TOBN(0x0bd9ea40, 0x110eec35), + TOBN(0x1c12bc5b, 0xc1dea34e), TOBN(0x686584c9, 0x49ae4699), + TOBN(0x13ad95d3, 0x8c97b942), TOBN(0x4609561a, 0x4e5c7562), + TOBN(0x9e94a4ae, 0xf2737f89), TOBN(0xf57594c6, 0x371c78b6), + TOBN(0x0f0165fc, 0xe3779ee3), TOBN(0xe00e7f9d, 0xbd495d9e), + TOBN(0x1fa4efa2, 0x20284e7a), TOBN(0x4564bade, 0x47ac6219), + TOBN(0x90e6312a, 0xc4708e8e), TOBN(0x4f5725fb, 0xa71e9adf), + TOBN(0xe95f55ae, 0x3d684b9f), TOBN(0x47f7ccb1, 0x1e94b415), + TOBN(0x7322851b, 0x8d946581), TOBN(0xf0d13133, 0xbdf4a012), + TOBN(0xa3510f69, 0x6584dae0), TOBN(0x03a7c171, 0x3c9f6c6d), + TOBN(0x5be97f38, 0xe475381a), TOBN(0xca1ba422, 0x85823334), + TOBN(0xf83cc5c7, 0x0be17dda), TOBN(0x158b1494, 0x0b918c0f), + TOBN(0xda3a77e5, 0x522e6b69), TOBN(0x69c908c3, 0xbbcd6c18), + TOBN(0x1f1b9e48, 0xd924fd56), TOBN(0x37c64e36, 0xaa4bb3f7), + TOBN(0x5a4fdbdf, 0xee478d7d), TOBN(0xba75c8bc, 0x0193f7a0), + TOBN(0x84bc1e84, 0x56cd16df), TOBN(0x1fb08f08, 0x46fad151), + TOBN(0x8a7cabf9, 0x842e9f30), TOBN(0xa331d4bf, 0x5eab83af), + TOBN(0xd272cfba, 0x017f2a6a), TOBN(0x27560abc, 0x83aba0e3), + TOBN(0x94b83387, 0x0e3a6b75), TOBN(0x25c6aea2, 0x6b9f50f5), + TOBN(0x803d691d, 0xb5fdf6d0), TOBN(0x03b77509, 0xe6333514), + TOBN(0x36178903, 0x61a341c1), TOBN(0x3604dc60, 0x0cfd6142), + TOBN(0x022295eb, 0x8533316c), TOBN(0x3dbde4ac, 0x44af2922), + TOBN(0x898afc5d, 0x1c7eef69), TOBN(0x58896805, 0xd14f4fa1), + TOBN(0x05002160, 0x203c21ca), TOBN(0x6f0d1f30, 0x40ef730b), + TOBN(0x8e8c44d4, 0x196224f8), TOBN(0x75a4ab95, 0x374d079d), + TOBN(0x79085ecc, 0x7d48f123), TOBN(0x56f04d31, 0x1bf65ad8), + TOBN(0xe220bf1c, 0xbda602b2), TOBN(0x73ee1742, 0xf9612c69), + TOBN(0x76008fc8, 0x084fd06b), TOBN(0x4000ef9f, 0xf11380d1), + TOBN(0x48201b4b, 0x12cfe297), TOBN(0x3eee129c, 0x292f74e5), + TOBN(0xe1fe114e, 0xc9e874e8), TOBN(0x899b055c, 0x92c5fc41), + TOBN(0x4e477a64, 0x3a39c8cf), TOBN(0x82f09efe, 0x78963cc9), + TOBN(0x6fd3fd8f, 0xd333f863), TOBN(0x85132b2a, 0xdc949c63), + TOBN(0x7e06a3ab, 0x516eb17b), TOBN(0x73bec06f, 0xd2c7372b), + TOBN(0xe4f74f55, 0xba896da6), TOBN(0xbb4afef8, 0x8e9eb40f), + TOBN(0x2d75bec8, 0xe61d66b0), TOBN(0x02bda4b4, 0xef29300b), + TOBN(0x8bbaa8de, 0x026baa5a), TOBN(0xff54befd, 0xa07f4440), + TOBN(0xbd9b8b1d, 0xbe7a2af3), TOBN(0xec51caa9, 0x4fb74a72), + TOBN(0xb9937a4b, 0x63879697), TOBN(0x7c9a9d20, 0xec2687d5), + TOBN(0x1773e44f, 0x6ef5f014), TOBN(0x8abcf412, 0xe90c6900), + TOBN(0x387bd022, 0x8142161e), TOBN(0x50393755, 0xfcb6ff2a), + TOBN(0x9813fd56, 0xed6def63), TOBN(0x53cf6482, 0x7d53106c), + TOBN(0x991a35bd, 0x431f7ac1), TOBN(0xf1e274dd, 0x63e65faf), + TOBN(0xf63ffa3c, 0x44cc7880), TOBN(0x411a426b, 0x7c256981), + TOBN(0xb698b9fd, 0x93a420e0), TOBN(0x89fdddc0, 0xae53f8fe), + TOBN(0x766e0722, 0x32398baa), TOBN(0x205fee42, 0x5cfca031), + TOBN(0xa49f5341, 0x7a029cf2), TOBN(0xa88c68b8, 0x4023890d), + TOBN(0xbc275041, 0x7337aaa8), TOBN(0x9ed364ad, 0x0eb384f4), + TOBN(0xe0816f85, 0x29aba92f), TOBN(0x2e9e1941, 0x04e38a88), + TOBN(0x57eef44a, 0x3dafd2d5), TOBN(0x35d1fae5, 0x97ed98d8), + TOBN(0x50628c09, 0x2307f9b1), TOBN(0x09d84aae, 0xd6cba5c6), + TOBN(0x67071bc7, 0x88aaa691), TOBN(0x2dea57a9, 0xafe6cb03), + TOBN(0xdfe11bb4, 0x3d78ac01), TOBN(0x7286418c, 0x7fd7aa51), + TOBN(0xfabf7709, 0x77f7195a), TOBN(0x8ec86167, 0xadeb838f), + TOBN(0xea1285a8, 0xbb4f012d), TOBN(0xd6883503, 0x9a3eab3f), + TOBN(0xee5d24f8, 0x309004c2), TOBN(0xa96e4b76, 0x13ffe95e), + TOBN(0x0cdffe12, 0xbd223ea4), TOBN(0x8f5c2ee5, 0xb6739a53), + TOBN(0x5cb4aaa5, 0xdd968198), TOBN(0xfa131c52, 0x72413a6c), + TOBN(0x53d46a90, 0x9536d903), TOBN(0xb270f0d3, 0x48606d8e), + TOBN(0x518c7564, 0xa053a3bc), TOBN(0x088254b7, 0x1a86caef), + TOBN(0xb3ba8cb4, 0x0ab5efd0), TOBN(0x5c59900e, 0x4605945d), + TOBN(0xecace1dd, 0xa1887395), TOBN(0x40960f36, 0x932a65de), + TOBN(0x9611ff5c, 0x3aa95529), TOBN(0xc58215b0, 0x7c1e5a36), + TOBN(0xd48c9b58, 0xf0e1a524), TOBN(0xb406856b, 0xf590dfb8), + TOBN(0xc7605e04, 0x9cd95662), TOBN(0x0dd036ee, 0xa33ecf82), + TOBN(0xa50171ac, 0xc33156b3), TOBN(0xf09d24ea, 0x4a80172e), + TOBN(0x4e1f72c6, 0x76dc8eef), TOBN(0xe60caadc, 0x5e3d44ee), + TOBN(0x006ef8a6, 0x979b1d8f), TOBN(0x60908a1c, 0x97788d26), + TOBN(0x6e08f95b, 0x266feec0), TOBN(0x618427c2, 0x22e8c94e), + TOBN(0x3d613339, 0x59145a65), TOBN(0xcd9bc368, 0xfa406337), + TOBN(0x82d11be3, 0x2d8a52a0), TOBN(0xf6877b27, 0x97a1c590), + TOBN(0x837a819b, 0xf5cbdb25), TOBN(0x2a4fd1d8, 0xde090249), + TOBN(0x622a7de7, 0x74990e5f), TOBN(0x840fa5a0, 0x7945511b), + TOBN(0x30b974be, 0x6558842d), TOBN(0x70df8c64, 0x17f3d0a6), + TOBN(0x7c803520, 0x7542e46d), TOBN(0x7251fe7f, 0xe4ecc823), + TOBN(0xe59134cb, 0x5e9aac9a), TOBN(0x11bb0934, 0xf0045d71), + TOBN(0x53e5d9b5, 0xdbcb1d4e), TOBN(0x8d97a905, 0x92defc91), + TOBN(0xfe289327, 0x7946d3f9), TOBN(0xe132bd24, 0x07472273), + TOBN(0xeeeb510c, 0x1eb6ae86), TOBN(0x777708c5, 0xf0595067), + TOBN(0x18e2c8cd, 0x1297029e), TOBN(0x2c61095c, 0xbbf9305e), + TOBN(0xe466c258, 0x6b85d6d9), TOBN(0x8ac06c36, 0xda1ea530), + TOBN(0xa365dc39, 0xa1304668), TOBN(0xe4a9c885, 0x07f89606), + TOBN(0x65a4898f, 0xacc7228d), TOBN(0x3e2347ff, 0x84ca8303), + TOBN(0xa5f6fb77, 0xea7d23a3), TOBN(0x2fac257d, 0x672a71cd), + TOBN(0x6908bef8, 0x7e6a44d3), TOBN(0x8ff87566, 0x891d3d7a), + TOBN(0xe58e90b3, 0x6b0cf82e), TOBN(0x6438d246, 0x2615b5e7), + TOBN(0x07b1f8fc, 0x669c145a), TOBN(0xb0d8b2da, 0x36f1e1cb), + TOBN(0x54d5dadb, 0xd9184c4d), TOBN(0x3dbb18d5, 0xf93d9976), + TOBN(0x0a3e0f56, 0xd1147d47), TOBN(0x2afa8c8d, 0xa0a48609), + TOBN(0x275353e8, 0xbc36742c), TOBN(0x898f427e, 0xeea0ed90), + TOBN(0x26f4947e, 0x3e477b00), TOBN(0x8ad8848a, 0x308741e3), + TOBN(0x6c703c38, 0xd74a2a46), TOBN(0x5e3e05a9, 0x9ba17ba2), + TOBN(0xc1fa6f66, 0x4ab9a9e4), TOBN(0x474a2d9a, 0x3841d6ec), + TOBN(0x871239ad, 0x653ae326), TOBN(0x14bcf72a, 0xa74cbb43), + TOBN(0x8737650e, 0x20d4c083), TOBN(0x3df86536, 0x110ed4af), + TOBN(0xd2d86fe7, 0xb53ca555), TOBN(0x688cb00d, 0xabd5d538), + TOBN(0xcf81bda3, 0x1ad38468), TOBN(0x7ccfe3cc, 0xf01167b6), + TOBN(0xcf4f47e0, 0x6c4c1fe6), TOBN(0x557e1f1a, 0x298bbb79), + TOBN(0xf93b974f, 0x30d45a14), TOBN(0x174a1d2d, 0x0baf97c4), + TOBN(0x7a003b30, 0xc51fbf53), TOBN(0xd8940991, 0xee68b225), + TOBN(0x5b0aa7b7, 0x1c0f4173), TOBN(0x975797c9, 0xa20a7153), + TOBN(0x26e08c07, 0xe3533d77), TOBN(0xd7222e6a, 0x2e341c99), + TOBN(0x9d60ec3d, 0x8d2dc4ed), TOBN(0xbdfe0d8f, 0x7c476cf8), + TOBN(0x1fe59ab6, 0x1d056605), TOBN(0xa9ea9df6, 0x86a8551f), + TOBN(0x8489941e, 0x47fb8d8c), TOBN(0xfeb874eb, 0x4a7f1b10), + TOBN(0xfe5fea86, 0x7ee0d98f), TOBN(0x201ad34b, 0xdbf61864), + TOBN(0x45d8fe47, 0x37c031d4), TOBN(0xd5f49fae, 0x795f0822), + TOBN(0xdb0fb291, 0xc7f4a40c), TOBN(0x2e69d9c1, 0x730ddd92), + TOBN(0x754e1054, 0x49d76987), TOBN(0x8a24911d, 0x7662db87), + TOBN(0x61fc1810, 0x60a71676), TOBN(0xe852d1a8, 0xf66a8ad1), + TOBN(0x172bbd65, 0x6417231e), TOBN(0x0d6de7bd, 0x3babb11f), + TOBN(0x6fde6f88, 0xc8e347f8), TOBN(0x1c587547, 0x9bd99cc3), + TOBN(0x78e54ed0, 0x34076950), TOBN(0x97f0f334, 0x796e83ba), + TOBN(0xe4dbe1ce, 0x4924867a), TOBN(0xbd5f51b0, 0x60b84917), + TOBN(0x37530040, 0x3cb09a79), TOBN(0xdb3fe0f8, 0xff1743d8), + TOBN(0xed7894d8, 0x556fa9db), TOBN(0xfa262169, 0x23412fbf), + TOBN(0x563be0db, 0xba7b9291), TOBN(0x6ca8b8c0, 0x0c9fb234), + TOBN(0xed406aa9, 0xbd763802), TOBN(0xc21486a0, 0x65303da1), + TOBN(0x61ae291e, 0xc7e62ec4), TOBN(0x622a0492, 0xdf99333e), + TOBN(0x7fd80c9d, 0xbb7a8ee0), TOBN(0xdc2ed3bc, 0x6c01aedb), + TOBN(0x35c35a12, 0x08be74ec), TOBN(0xd540cb1a, 0x469f671f), + TOBN(0xd16ced4e, 0xcf84f6c7), TOBN(0x8561fb9c, 0x2d090f43), + TOBN(0x7e693d79, 0x6f239db4), TOBN(0xa736f928, 0x77bd0d94), + TOBN(0x07b4d929, 0x2c1950ee), TOBN(0xda177543, 0x56dc11b3), + TOBN(0xa5dfbbaa, 0x7a6a878e), TOBN(0x1c70cb29, 0x4decb08a), + TOBN(0xfba28c8b, 0x6f0f7c50), TOBN(0xa8eba2b8, 0x854dcc6d), + TOBN(0x5ff8e89a, 0x36b78642), TOBN(0x070c1c8e, 0xf6873adf), + TOBN(0xbbd3c371, 0x6484d2e4), TOBN(0xfb78318f, 0x0d414129), + TOBN(0x2621a39c, 0x6ad93b0b), TOBN(0x979d74c2, 0xa9e917f7), + TOBN(0xfc195647, 0x61fb0428), TOBN(0x4d78954a, 0xbee624d4), + TOBN(0xb94896e0, 0xb8ae86fd), TOBN(0x6667ac0c, 0xc91c8b13), + TOBN(0x9f180512, 0x43bcf832), TOBN(0xfbadf8b7, 0xa0010137), + TOBN(0xc69b4089, 0xb3ba8aa7), TOBN(0xfac4bacd, 0xe687ce85), + TOBN(0x9164088d, 0x977eab40), TOBN(0x51f4c5b6, 0x2760b390), + TOBN(0xd238238f, 0x340dd553), TOBN(0x358566c3, 0xdb1d31c9), + TOBN(0x3a5ad69e, 0x5068f5ff), TOBN(0xf31435fc, 0xdaff6b06), + TOBN(0xae549a5b, 0xd6debff0), TOBN(0x59e5f0b7, 0x75e01331), + TOBN(0x5d492fb8, 0x98559acf), TOBN(0x96018c2e, 0x4db79b50), + TOBN(0x55f4a48f, 0x609f66aa), TOBN(0x1943b3af, 0x4900a14f), + TOBN(0xc22496df, 0x15a40d39), TOBN(0xb2a44684, 0x4c20f7c5), + TOBN(0x76a35afa, 0x3b98404c), TOBN(0xbec75725, 0xff5d1b77), + TOBN(0xb67aa163, 0xbea06444), TOBN(0x27e95bb2, 0xf724b6f2), + TOBN(0x3c20e3e9, 0xd238c8ab), TOBN(0x1213754e, 0xddd6ae17), + TOBN(0x8c431020, 0x716e0f74), TOBN(0x6679c82e, 0xffc095c2), + TOBN(0x2eb3adf4, 0xd0ac2932), TOBN(0x2cc970d3, 0x01bb7a76), + TOBN(0x70c71f2f, 0x740f0e66), TOBN(0x545c616b, 0x2b6b23cc), + TOBN(0x4528cfcb, 0xb40a8bd7), TOBN(0xff839633, 0x2ab27722), + TOBN(0x049127d9, 0x025ac99a), TOBN(0xd314d4a0, 0x2b63e33b), + TOBN(0xc8c310e7, 0x28d84519), TOBN(0x0fcb8983, 0xb3bc84ba), + TOBN(0x2cc52261, 0x38634818), TOBN(0x501814f4, 0xb44c2e0b), + TOBN(0xf7e181aa, 0x54dfdba3), TOBN(0xcfd58ff0, 0xe759718c), + TOBN(0xf90cdb14, 0xd3b507a8), TOBN(0x57bd478e, 0xc50bdad8), + TOBN(0x29c197e2, 0x50e5f9aa), TOBN(0x4db6eef8, 0xe40bc855), + TOBN(0x2cc8f21a, 0xd1fc0654), TOBN(0xc71cc963, 0x81269d73), + TOBN(0xecfbb204, 0x077f49f9), TOBN(0xdde92571, 0xca56b793), + TOBN(0x9abed6a3, 0xf97ad8f7), TOBN(0xe6c19d3f, 0x924de3bd), + TOBN(0x8dce92f4, 0xa140a800), TOBN(0x85f44d1e, 0x1337af07), + TOBN(0x5953c08b, 0x09d64c52), TOBN(0xa1b5e49f, 0xf5df9749), + TOBN(0x336a8fb8, 0x52735f7d), TOBN(0xb332b6db, 0x9add676b), + TOBN(0x558b88a0, 0xb4511aa4), TOBN(0x09788752, 0xdbd5cc55), + TOBN(0x16b43b9c, 0xd8cd52bd), TOBN(0x7f0bc5a0, 0xc2a2696b), + TOBN(0x146e12d4, 0xc11f61ef), TOBN(0x9ce10754, 0x3a83e79e), + TOBN(0x08ec73d9, 0x6cbfca15), TOBN(0x09ff29ad, 0x5b49653f), + TOBN(0xe31b72bd, 0xe7da946e), TOBN(0xebf9eb3b, 0xee80a4f2), + TOBN(0xd1aabd08, 0x17598ce4), TOBN(0x18b5fef4, 0x53f37e80), + TOBN(0xd5d5cdd3, 0x5958cd79), TOBN(0x3580a1b5, 0x1d373114), + TOBN(0xa36e4c91, 0xfa935726), TOBN(0xa38c534d, 0xef20d760), + TOBN(0x7088e40a, 0x2ff5845b), TOBN(0xe5bb40bd, 0xbd78177f), + TOBN(0x4f06a7a8, 0x857f9920), TOBN(0xe3cc3e50, 0xe968f05d), + TOBN(0x1d68b7fe, 0xe5682d26), TOBN(0x5206f76f, 0xaec7f87c), + TOBN(0x41110530, 0x041951ab), TOBN(0x58ec52c1, 0xd4b5a71a), + TOBN(0xf3488f99, 0x0f75cf9a), TOBN(0xf411951f, 0xba82d0d5), + TOBN(0x27ee75be, 0x618895ab), TOBN(0xeae060d4, 0x6d8aab14), + TOBN(0x9ae1df73, 0x7fb54dc2), TOBN(0x1f3e391b, 0x25963649), + TOBN(0x242ec32a, 0xfe055081), TOBN(0x5bd450ef, 0x8491c9bd), + TOBN(0x367efc67, 0x981eb389), TOBN(0xed7e1928, 0x3a0550d5), + TOBN(0x362e776b, 0xab3ce75c), TOBN(0xe890e308, 0x1f24c523), + TOBN(0xb961b682, 0xfeccef76), TOBN(0x8b8e11f5, 0x8bba6d92), + TOBN(0x8f2ccc4c, 0x2b2375c4), TOBN(0x0d7f7a52, 0xe2f86cfa), + TOBN(0xfd94d30a, 0x9efe5633), TOBN(0x2d8d246b, 0x5451f934), + TOBN(0x2234c6e3, 0x244e6a00), TOBN(0xde2b5b0d, 0xddec8c50), + TOBN(0x2ce53c5a, 0xbf776f5b), TOBN(0x6f724071, 0x60357b05), + TOBN(0xb2593717, 0x71bf3f7a), TOBN(0x87d2501c, 0x440c4a9f), + TOBN(0x440552e1, 0x87b05340), TOBN(0xb7bf7cc8, 0x21624c32), + TOBN(0x4155a6ce, 0x22facddb), TOBN(0x5a4228cb, 0x889837ef), + TOBN(0xef87d6d6, 0xfd4fd671), TOBN(0xa233687e, 0xc2daa10e), + TOBN(0x75622244, 0x03c0eb96), TOBN(0x7632d184, 0x8bf19be6), + TOBN(0x05d0f8e9, 0x40735ff4), TOBN(0x3a3e6e13, 0xc00931f1), + TOBN(0x31ccde6a, 0xdafe3f18), TOBN(0xf381366a, 0xcfe51207), + TOBN(0x24c222a9, 0x60167d92), TOBN(0x62f9d6f8, 0x7529f18c), + TOBN(0x412397c0, 0x0353b114), TOBN(0x334d89dc, 0xef808043), + TOBN(0xd9ec63ba, 0x2a4383ce), TOBN(0xcec8e937, 0x5cf92ba0), + TOBN(0xfb8b4288, 0xc8be74c0), TOBN(0x67d6912f, 0x105d4391), + TOBN(0x7b996c46, 0x1b913149), TOBN(0x36aae2ef, 0x3a4e02da), + TOBN(0xb68aa003, 0x972de594), TOBN(0x284ec70d, 0x4ec6d545), + TOBN(0xf3d2b2d0, 0x61391d54), TOBN(0x69c5d5d6, 0xfe114e92), + TOBN(0xbe0f00b5, 0xb4482dff), TOBN(0xe1596fa5, 0xf5bf33c5), + TOBN(0x10595b56, 0x96a71cba), TOBN(0x944938b2, 0xfdcadeb7), + TOBN(0xa282da4c, 0xfccd8471), TOBN(0x98ec05f3, 0x0d37bfe1), + TOBN(0xe171ce1b, 0x0698304a), TOBN(0x2d691444, 0x21bdf79b), + TOBN(0xd0cd3b74, 0x1b21dec1), TOBN(0x712ecd8b, 0x16a15f71), + TOBN(0x8d4c00a7, 0x00fd56e1), TOBN(0x02ec9692, 0xf9527c18), + TOBN(0x21c44937, 0x4a3e42e1), TOBN(0x9176fbab, 0x1392ae0a), + TOBN(0x8726f1ba, 0x44b7b618), TOBN(0xb4d7aae9, 0xf1de491c), + TOBN(0xf91df7b9, 0x07b582c0), TOBN(0x7e116c30, 0xef60aa3a), + TOBN(0x99270f81, 0x466265d7), TOBN(0xb15b6fe2, 0x4df7adf0), + TOBN(0xfe33b2d3, 0xf9738f7f), TOBN(0x48553ab9, 0xd6d70f95), + TOBN(0x2cc72ac8, 0xc21e94db), TOBN(0x795ac38d, 0xbdc0bbee), + TOBN(0x0a1be449, 0x2e40478f), TOBN(0x81bd3394, 0x052bde55), + TOBN(0x63c8dbe9, 0x56b3c4f2), TOBN(0x017a99cf, 0x904177cc), + TOBN(0x947bbddb, 0x4d010fc1), TOBN(0xacf9b00b, 0xbb2c9b21), + TOBN(0x2970bc8d, 0x47173611), TOBN(0x1a4cbe08, 0xac7d756f), + TOBN(0x06d9f4aa, 0x67d541a2), TOBN(0xa3e8b689, 0x59c2cf44), + TOBN(0xaad066da, 0x4d88f1dd), TOBN(0xc604f165, 0x7ad35dea), + TOBN(0x7edc0720, 0x4478ca67), TOBN(0xa10dfae0, 0xba02ce06), + TOBN(0xeceb1c76, 0xaf36f4e4), TOBN(0x994b2292, 0xaf3f8f48), + TOBN(0xbf9ed77b, 0x77c8a68c), TOBN(0x74f544ea, 0x51744c9d), + TOBN(0x82d05bb9, 0x8113a757), TOBN(0x4ef2d2b4, 0x8a9885e4), + TOBN(0x1e332be5, 0x1aa7865f), TOBN(0x22b76b18, 0x290d1a52), + TOBN(0x308a2310, 0x44351683), TOBN(0x9d861896, 0xa3f22840), + TOBN(0x5959ddcd, 0x841ed947), TOBN(0x0def0c94, 0x154b73bf), + TOBN(0xf0105417, 0x4c7c15e0), TOBN(0x539bfb02, 0x3a277c32), + TOBN(0xe699268e, 0xf9dccf5f), TOBN(0x9f5796a5, 0x0247a3bd), + TOBN(0x8b839de8, 0x4f157269), TOBN(0xc825c1e5, 0x7a30196b), + TOBN(0x6ef0aabc, 0xdc8a5a91), TOBN(0xf4a8ce6c, 0x498b7fe6), + TOBN(0x1cce35a7, 0x70cbac78), TOBN(0x83488e9b, 0xf6b23958), + TOBN(0x0341a070, 0xd76cb011), TOBN(0xda6c9d06, 0xae1b2658), + TOBN(0xb701fb30, 0xdd648c52), TOBN(0x994ca02c, 0x52fb9fd1), + TOBN(0x06933117, 0x6f563086), TOBN(0x3d2b8100, 0x17856bab), + TOBN(0xe89f48c8, 0x5963a46e), TOBN(0x658ab875, 0xa99e61c7), + TOBN(0x6e296f87, 0x4b8517b4), TOBN(0x36c4fcdc, 0xfc1bc656), + TOBN(0xde5227a1, 0xa3906def), TOBN(0x9fe95f57, 0x62418945), + TOBN(0x20c91e81, 0xfdd96cde), TOBN(0x5adbe47e, 0xda4480de), + TOBN(0xa009370f, 0x396de2b6), TOBN(0x98583d4b, 0xf0ecc7bd), + TOBN(0xf44f6b57, 0xe51d0672), TOBN(0x03d6b078, 0x556b1984), + TOBN(0x27dbdd93, 0xb0b64912), TOBN(0x9b3a3434, 0x15687b09), + TOBN(0x0dba6461, 0x51ec20a9), TOBN(0xec93db7f, 0xff28187c), + TOBN(0x00ff8c24, 0x66e48bdd), TOBN(0x2514f2f9, 0x11ccd78e), + TOBN(0xeba11f4f, 0xe1250603), TOBN(0x8a22cd41, 0x243fa156), + TOBN(0xa4e58df4, 0xb283e4c6), TOBN(0x78c29859, 0x8b39783f), + TOBN(0x5235aee2, 0xa5259809), TOBN(0xc16284b5, 0x0e0227dd), + TOBN(0xa5f57916, 0x1338830d), TOBN(0x6d4b8a6b, 0xd2123fca), + TOBN(0x236ea68a, 0xf9c546f8), TOBN(0xc1d36873, 0xfa608d36), + TOBN(0xcd76e495, 0x8d436d13), TOBN(0xd4d9c221, 0x8fb080af), + TOBN(0x665c1728, 0xe8ad3fb5), TOBN(0xcf1ebe4d, 0xb3d572e0), + TOBN(0xa7a8746a, 0x584c5e20), TOBN(0x267e4ea1, 0xb9dc7035), + TOBN(0x593a15cf, 0xb9548c9b), TOBN(0x5e6e2135, 0x4bd012f3), + TOBN(0xdf31cc6a, 0x8c8f936e), TOBN(0x8af84d04, 0xb5c241dc), + TOBN(0x63990a6f, 0x345efb86), TOBN(0x6fef4e61, 0xb9b962cb)} + , + {TOBN(0xf6368f09, 0x25722608), TOBN(0x131260db, 0x131cf5c6), + TOBN(0x40eb353b, 0xfab4f7ac), TOBN(0x85c78880, 0x37eee829), + TOBN(0x4c1581ff, 0xc3bdf24e), TOBN(0x5bff75cb, 0xf5c3c5a8), + TOBN(0x35e8c83f, 0xa14e6f40), TOBN(0xb81d1c0f, 0x0295e0ca), + TOBN(0xfcde7cc8, 0xf43a730f), TOBN(0xe89b6f3c, 0x33ab590e), + TOBN(0xc823f529, 0xad03240b), TOBN(0x82b79afe, 0x98bea5db), + TOBN(0x568f2856, 0x962fe5de), TOBN(0x0c590adb, 0x60c591f3), + TOBN(0x1fc74a14, 0x4a28a858), TOBN(0x3b662498, 0xb3203f4c), + TOBN(0x91e3cf0d, 0x6c39765a), TOBN(0xa2db3acd, 0xac3cca0b), + TOBN(0x288f2f08, 0xcb953b50), TOBN(0x2414582c, 0xcf43cf1a), + TOBN(0x8dec8bbc, 0x60eee9a8), TOBN(0x54c79f02, 0x729aa042), + TOBN(0xd81cd5ec, 0x6532f5d5), TOBN(0xa672303a, 0xcf82e15f), + TOBN(0x376aafa8, 0x719c0563), TOBN(0xcd8ad2dc, 0xbc5fc79f), + TOBN(0x303fdb9f, 0xcb750cd3), TOBN(0x14ff052f, 0x4418b08e), + TOBN(0xf75084cf, 0x3e2d6520), TOBN(0x7ebdf0f8, 0x144ed509), + TOBN(0xf43bf0f2, 0xd3f25b98), TOBN(0x86ad71cf, 0xa354d837), + TOBN(0xb827fe92, 0x26f43572), TOBN(0xdfd3ab5b, 0x5d824758), + TOBN(0x315dd23a, 0x539094c1), TOBN(0x85c0e37a, 0x66623d68), + TOBN(0x575c7972, 0x7be19ae0), TOBN(0x616a3396, 0xdf0d36b5), + TOBN(0xa1ebb3c8, 0x26b1ff7e), TOBN(0x635b9485, 0x140ad453), + TOBN(0x92bf3cda, 0xda430c0b), TOBN(0x4702850e, 0x3a96dac6), + TOBN(0xc91cf0a5, 0x15ac326a), TOBN(0x95de4f49, 0xab8c25e4), + TOBN(0xb01bad09, 0xe265c17c), TOBN(0x24e45464, 0x087b3881), + TOBN(0xd43e583c, 0xe1fac5ca), TOBN(0xe17cb318, 0x6ead97a6), + TOBN(0x6cc39243, 0x74dcec46), TOBN(0x33cfc02d, 0x54c2b73f), + TOBN(0x82917844, 0xf26cd99c), TOBN(0x8819dd95, 0xd1773f89), + TOBN(0x09572aa6, 0x0871f427), TOBN(0x8e0cf365, 0xf6f01c34), + TOBN(0x7fa52988, 0xbff1f5af), TOBN(0x4eb357ea, 0xe75e8e50), + TOBN(0xd9d0c8c4, 0x868af75d), TOBN(0xd7325cff, 0x45c8c7ea), + TOBN(0xab471996, 0xcc81ecb0), TOBN(0xff5d55f3, 0x611824ed), + TOBN(0xbe314541, 0x1977a0ee), TOBN(0x5085c4c5, 0x722038c6), + TOBN(0x2d5335bf, 0xf94bb495), TOBN(0x894ad8a6, 0xc8e2a082), + TOBN(0x5c3e2341, 0xada35438), TOBN(0xf4a9fc89, 0x049b8c4e), + TOBN(0xbeeb355a, 0x9f17cf34), TOBN(0x3f311e0e, 0x6c91fe10), + TOBN(0xc2d20038, 0x92ab9891), TOBN(0x257bdcc1, 0x3e8ce9a9), + TOBN(0x1b2d9789, 0x88c53bee), TOBN(0x927ce89a, 0xcdba143a), + TOBN(0xb0a32cca, 0x523db280), TOBN(0x5c889f8a, 0x50d43783), + TOBN(0x503e04b3, 0x4897d16f), TOBN(0x8cdb6e78, 0x08f5f2e8), + TOBN(0x6ab91cf0, 0x179c8e74), TOBN(0xd8874e52, 0x48211d60), + TOBN(0xf948d4d5, 0xea851200), TOBN(0x4076d41e, 0xe6f9840a), + TOBN(0xc20e263c, 0x47b517ea), TOBN(0x79a448fd, 0x30685e5e), + TOBN(0xe55f6f78, 0xf90631a0), TOBN(0x88a790b1, 0xa79e6346), + TOBN(0x62160c7d, 0x80969fe8), TOBN(0x54f92fd4, 0x41491bb9), + TOBN(0xa6645c23, 0x5c957526), TOBN(0xf44cc5ae, 0xbea3ce7b), + TOBN(0xf7628327, 0x8b1e68b7), TOBN(0xc731ad7a, 0x303f29d3), + TOBN(0xfe5a9ca9, 0x57d03ecb), TOBN(0x96c0d50c, 0x41bc97a7), + TOBN(0xc4669fe7, 0x9b4f7f24), TOBN(0xfdd781d8, 0x3d9967ef), + TOBN(0x7892c7c3, 0x5d2c208d), TOBN(0x8bf64f7c, 0xae545cb3), + TOBN(0xc01f862c, 0x467be912), TOBN(0xf4c85ee9, 0xc73d30cc), + TOBN(0x1fa6f4be, 0x6ab83ec7), TOBN(0xa07a3c1c, 0x4e3e3cf9), + TOBN(0x87f8ef45, 0x0c00beb3), TOBN(0x30e2c2b3, 0x000d4c3e), + TOBN(0x1aa00b94, 0xfe08bf5b), TOBN(0x32c133aa, 0x9224ef52), + TOBN(0x38df16bb, 0x32e5685d), TOBN(0x68a9e069, 0x58e6f544), + TOBN(0x495aaff7, 0xcdc5ebc6), TOBN(0xf894a645, 0x378b135f), + TOBN(0xf316350a, 0x09e27ecf), TOBN(0xeced201e, 0x58f7179d), + TOBN(0x2eec273c, 0xe97861ba), TOBN(0x47ec2cae, 0xd693be2e), + TOBN(0xfa4c97c4, 0xf68367ce), TOBN(0xe4f47d0b, 0xbe5a5755), + TOBN(0x17de815d, 0xb298a979), TOBN(0xd7eca659, 0xc177dc7d), + TOBN(0x20fdbb71, 0x49ded0a3), TOBN(0x4cb2aad4, 0xfb34d3c5), + TOBN(0x2cf31d28, 0x60858a33), TOBN(0x3b6873ef, 0xa24aa40f), + TOBN(0x540234b2, 0x2c11bb37), TOBN(0x2d0366dd, 0xed4c74a3), + TOBN(0xf9a968da, 0xeec5f25d), TOBN(0x36601068, 0x67b63142), + TOBN(0x07cd6d2c, 0x68d7b6d4), TOBN(0xa8f74f09, 0x0c842942), + TOBN(0xe2751404, 0x7768b1ee), TOBN(0x4b5f7e89, 0xfe62aee4), + TOBN(0xc6a77177, 0x89070d26), TOBN(0xa1f28e4e, 0xdd1c8bc7), + TOBN(0xea5f4f06, 0x469e1f17), TOBN(0x78fc242a, 0xfbdb78e0), + TOBN(0xc9c7c592, 0x8b0588f1), TOBN(0xb6b7a0fd, 0x1535921e), + TOBN(0xcc5bdb91, 0xbde5ae35), TOBN(0xb42c485e, 0x12ff1864), + TOBN(0xa1113e13, 0xdbab98aa), TOBN(0xde9d469b, 0xa17b1024), + TOBN(0x23f48b37, 0xc0462d3a), TOBN(0x3752e537, 0x7c5c078d), + TOBN(0xe3a86add, 0x15544eb9), TOBN(0xf013aea7, 0x80fba279), + TOBN(0x8b5bb76c, 0xf22001b5), TOBN(0xe617ba14, 0xf02891ab), + TOBN(0xd39182a6, 0x936219d3), TOBN(0x5ce1f194, 0xae51cb19), + TOBN(0xc78f8598, 0xbf07a74c), TOBN(0x6d7158f2, 0x22cbf1bc), + TOBN(0x3b846b21, 0xe300ce18), TOBN(0x35fba630, 0x2d11275d), + TOBN(0x5fe25c36, 0xa0239b9b), TOBN(0xd8beb35d, 0xdf05d940), + TOBN(0x4db02bb0, 0x1f7e320d), TOBN(0x0641c364, 0x6da320ea), + TOBN(0x6d95fa5d, 0x821389a3), TOBN(0x92699748, 0x8fcd8e3d), + TOBN(0x316fef17, 0xceb6c143), TOBN(0x67fcb841, 0xd933762b), + TOBN(0xbb837e35, 0x118b17f8), TOBN(0x4b92552f, 0x9fd24821), + TOBN(0xae6bc70e, 0x46aca793), TOBN(0x1cf0b0e4, 0xe579311b), + TOBN(0x8dc631be, 0x5802f716), TOBN(0x099bdc6f, 0xbddbee4d), + TOBN(0xcc352bb2, 0x0caf8b05), TOBN(0xf74d505a, 0x72d63df2), + TOBN(0xb9876d4b, 0x91c4f408), TOBN(0x1ce18473, 0x9e229b2d), + TOBN(0x49507597, 0x83abdb4a), TOBN(0x850fbcb6, 0xdee84b18), + TOBN(0x6325236e, 0x609e67dc), TOBN(0x04d831d9, 0x9336c6d8), + TOBN(0x8deaae3b, 0xfa12d45d), TOBN(0xe425f8ce, 0x4746e246), + TOBN(0x8004c175, 0x24f5f31e), TOBN(0xaca16d8f, 0xad62c3b7), + TOBN(0x0dc15a6a, 0x9152f934), TOBN(0xf1235e5d, 0xed0e12c1), + TOBN(0xc33c06ec, 0xda477dac), TOBN(0x76be8732, 0xb2ea0006), + TOBN(0xcf3f7831, 0x0c0cd313), TOBN(0x3c524553, 0xa614260d), + TOBN(0x31a756f8, 0xcab22d15), TOBN(0x03ee10d1, 0x77827a20), + TOBN(0xd1e059b2, 0x1994ef20), TOBN(0x2a653b69, 0x638ae318), + TOBN(0x70d5eb58, 0x2f699010), TOBN(0x279739f7, 0x09f5f84a), + TOBN(0x5da4663c, 0x8b799336), TOBN(0xfdfdf14d, 0x203c37eb), + TOBN(0x32d8a9dc, 0xa1dbfb2d), TOBN(0xab40cff0, 0x77d48f9b), + TOBN(0xc018b383, 0xd20b42d5), TOBN(0xf9a810ef, 0x9f78845f), + TOBN(0x40af3753, 0xbdba9df0), TOBN(0xb90bdcfc, 0x131dfdf9), + TOBN(0x18720591, 0xf01ab782), TOBN(0xc823f211, 0x6af12a88), + TOBN(0xa51b80f3, 0x0dc14401), TOBN(0xde248f77, 0xfb2dfbe3), + TOBN(0xef5a44e5, 0x0cafe751), TOBN(0x73997c9c, 0xd4dcd221), + TOBN(0x32fd86d1, 0xde854024), TOBN(0xd5b53adc, 0xa09b84bb), + TOBN(0x008d7a11, 0xdcedd8d1), TOBN(0x406bd1c8, 0x74b32c84), + TOBN(0x5d4472ff, 0x05dde8b1), TOBN(0x2e25f2cd, 0xfce2b32f), + TOBN(0xbec0dd5e, 0x29dfc254), TOBN(0x4455fcf6, 0x2b98b267), + TOBN(0x0b4d43a5, 0xc72df2ad), TOBN(0xea70e6be, 0x48a75397), + TOBN(0x2aad6169, 0x5820f3bf), TOBN(0xf410d2dd, 0x9e37f68f), + TOBN(0x70fb7dba, 0x7be5ac83), TOBN(0x636bb645, 0x36ec3eec), + TOBN(0x27104ea3, 0x9754e21c), TOBN(0xbc87a3e6, 0x8d63c373), + TOBN(0x483351d7, 0x4109db9a), TOBN(0x0fa724e3, 0x60134da7), + TOBN(0x9ff44c29, 0xb0720b16), TOBN(0x2dd0cf13, 0x06aceead), + TOBN(0x5942758c, 0xe26929a6), TOBN(0x96c5db92, 0xb766a92b), + TOBN(0xcec7d4c0, 0x5f18395e), TOBN(0xd3f22744, 0x1f80d032), + TOBN(0x7a68b37a, 0xcb86075b), TOBN(0x074764dd, 0xafef92db), + TOBN(0xded1e950, 0x7bc7f389), TOBN(0xc580c850, 0xb9756460), + TOBN(0xaeeec2a4, 0x7da48157), TOBN(0x3f0b4e7f, 0x82c587b3), + TOBN(0x231c6de8, 0xa9f19c53), TOBN(0x5717bd73, 0x6974e34e), + TOBN(0xd9e1d216, 0xf1508fa9), TOBN(0x9f112361, 0xdadaa124), + TOBN(0x80145e31, 0x823b7348), TOBN(0x4dd8f0d5, 0xac634069), + TOBN(0xe3d82fc7, 0x2297c258), TOBN(0x276fcfee, 0x9cee7431), + TOBN(0x8eb61b5e, 0x2bc0aea9), TOBN(0x4f668fd5, 0xde329431), + TOBN(0x03a32ab1, 0x38e4b87e), TOBN(0xe1374517, 0x73d0ef0b), + TOBN(0x1a46f7e6, 0x853ac983), TOBN(0xc3bdf42e, 0x68e78a57), + TOBN(0xacf20785, 0x2ea96dd1), TOBN(0xa10649b9, 0xf1638460), + TOBN(0xf2369f0b, 0x879fbbed), TOBN(0x0ff0ae86, 0xda9d1869), + TOBN(0x5251d759, 0x56766f45), TOBN(0x4984d8c0, 0x2be8d0fc), + TOBN(0x7ecc95a6, 0xd21008f0), TOBN(0x29bd54a0, 0x3a1a1c49), + TOBN(0xab9828c5, 0xd26c50f3), TOBN(0x32c0087c, 0x51d0d251), + TOBN(0x9bac3ce6, 0x0c1cdb26), TOBN(0xcd94d947, 0x557ca205), + TOBN(0x1b1bd598, 0x9db1fdcd), TOBN(0x0eda0108, 0xa3d8b149), + TOBN(0x95066610, 0x56152fcc), TOBN(0xc2f037e6, 0xe7192b33), + TOBN(0xdeffb41a, 0xc92e05a4), TOBN(0x1105f6c2, 0xc2f6c62e), + TOBN(0x68e73500, 0x8733913c), TOBN(0xcce86163, 0x3f3adc40), + TOBN(0xf407a942, 0x38a278e9), TOBN(0xd13c1b9d, 0x2ab21292), + TOBN(0x93ed7ec7, 0x1c74cf5c), TOBN(0x8887dc48, 0xf1a4c1b4), + TOBN(0x3830ff30, 0x4b3a11f1), TOBN(0x358c5a3c, 0x58937cb6), + TOBN(0x027dc404, 0x89022829), TOBN(0x40e93977, 0x3b798f79), + TOBN(0x90ad3337, 0x38be6ead), TOBN(0x9c23f6bc, 0xf34c0a5d), + TOBN(0xd1711a35, 0xfbffd8bb), TOBN(0x60fcfb49, 0x1949d3dd), + TOBN(0x09c8ef4b, 0x7825d93a), TOBN(0x24233cff, 0xa0a8c968), + TOBN(0x67ade46c, 0xe6d982af), TOBN(0xebb6bf3e, 0xe7544d7c), + TOBN(0xd6b9ba76, 0x3d8bd087), TOBN(0x46fe382d, 0x4dc61280), + TOBN(0xbd39a7e8, 0xb5bdbd75), TOBN(0xab381331, 0xb8f228fe), + TOBN(0x0709a77c, 0xce1c4300), TOBN(0x6a247e56, 0xf337ceac), + TOBN(0x8f34f21b, 0x636288be), TOBN(0x9dfdca74, 0xc8a7c305), + TOBN(0x6decfd1b, 0xea919e04), TOBN(0xcdf2688d, 0x8e1991f8), + TOBN(0xe607df44, 0xd0f8a67e), TOBN(0xd985df4b, 0x0b58d010), + TOBN(0x57f834c5, 0x0c24f8f4), TOBN(0xe976ef56, 0xa0bf01ae), + TOBN(0x536395ac, 0xa1c32373), TOBN(0x351027aa, 0x734c0a13), + TOBN(0xd2f1b5d6, 0x5e6bd5bc), TOBN(0x2b539e24, 0x223debed), + TOBN(0xd4994cec, 0x0eaa1d71), TOBN(0x2a83381d, 0x661dcf65), + TOBN(0x5f1aed2f, 0x7b54c740), TOBN(0x0bea3fa5, 0xd6dda5ee), + TOBN(0x9d4fb684, 0x36cc6134), TOBN(0x8eb9bbf3, 0xc0a443dd), + TOBN(0xfc500e2e, 0x383b7d2a), TOBN(0x7aad621c, 0x5b775257), + TOBN(0x69284d74, 0x0a8f7cc0), TOBN(0xe820c2ce, 0x07562d65), + TOBN(0xbf9531b9, 0x499758ee), TOBN(0x73e95ca5, 0x6ee0cc2d), + TOBN(0xf61790ab, 0xfbaf50a5), TOBN(0xdf55e76b, 0x684e0750), + TOBN(0xec516da7, 0xf176b005), TOBN(0x575553bb, 0x7a2dddc7), + TOBN(0x37c87ca3, 0x553afa73), TOBN(0x315f3ffc, 0x4d55c251), + TOBN(0xe846442a, 0xaf3e5d35), TOBN(0x61b91149, 0x6495ff28), + TOBN(0x23cc95d3, 0xfa326dc3), TOBN(0x1df4da1f, 0x18fc2cea), + TOBN(0x24bf9adc, 0xd0a37d59), TOBN(0xb6710053, 0x320d6e1e), + TOBN(0x96f9667e, 0x618344d1), TOBN(0xcc7ce042, 0xa06445af), + TOBN(0xa02d8514, 0xd68dbc3a), TOBN(0x4ea109e4, 0x280b5a5b), + TOBN(0x5741a7ac, 0xb40961bf), TOBN(0x4ada5937, 0x6aa56bfa), + TOBN(0x7feb9145, 0x02b765d1), TOBN(0x561e97be, 0xe6ad1582), + TOBN(0xbbc4a5b6, 0xda3982f5), TOBN(0x0c2659ed, 0xb546f468), + TOBN(0xb8e7e6aa, 0x59612d20), TOBN(0xd83dfe20, 0xac19e8e0), + TOBN(0x8530c45f, 0xb835398c), TOBN(0x6106a8bf, 0xb38a41c2), + TOBN(0x21e8f9a6, 0x35f5dcdb), TOBN(0x39707137, 0xcae498ed), + TOBN(0x70c23834, 0xd8249f00), TOBN(0x9f14b58f, 0xab2537a0), + TOBN(0xd043c365, 0x5f61c0c2), TOBN(0xdc5926d6, 0x09a194a7), + TOBN(0xddec0339, 0x8e77738a), TOBN(0xd07a63ef, 0xfba46426), + TOBN(0x2e58e79c, 0xee7f6e86), TOBN(0xe59b0459, 0xff32d241), + TOBN(0xc5ec84e5, 0x20fa0338), TOBN(0x97939ac8, 0xeaff5ace), + TOBN(0x0310a4e3, 0xb4a38313), TOBN(0x9115fba2, 0x8f9d9885), + TOBN(0x8dd710c2, 0x5fadf8c3), TOBN(0x66be38a2, 0xce19c0e2), + TOBN(0xd42a279c, 0x4cfe5022), TOBN(0x597bb530, 0x0e24e1b8), + TOBN(0x3cde86b7, 0xc153ca7f), TOBN(0xa8d30fb3, 0x707d63bd), + TOBN(0xac905f92, 0xbd60d21e), TOBN(0x98e7ffb6, 0x7b9a54ab), + TOBN(0xd7147df8, 0xe9726a30), TOBN(0xb5e216ff, 0xafce3533), + TOBN(0xb550b799, 0x2ff1ec40), TOBN(0x6b613b87, 0xa1e953fd), + TOBN(0x87b88dba, 0x792d5610), TOBN(0x2ee1270a, 0xa190fbe1), + TOBN(0x02f4e2dc, 0x2ef581da), TOBN(0x016530e4, 0xeff82a95), + TOBN(0xcbb93dfd, 0x8fd6ee89), TOBN(0x16d3d986, 0x46848fff), + TOBN(0x600eff24, 0x1da47adf), TOBN(0x1b9754a0, 0x0ad47a71), + TOBN(0x8f9266df, 0x70c33b98), TOBN(0xaadc87ae, 0xdf34186e), + TOBN(0x0d2ce8e1, 0x4ad24132), TOBN(0x8a47cbfc, 0x19946eba), + TOBN(0x47feeb66, 0x62b5f3af), TOBN(0xcefab561, 0x0abb3734), + TOBN(0x449de60e, 0x19f35cb1), TOBN(0x39f8db14, 0x157f0eb9), + TOBN(0xffaecc5b, 0x3c61bfd6), TOBN(0xa5a4d41d, 0x41216703), + TOBN(0x7f8fabed, 0x224e1cc2), TOBN(0x0d5a8186, 0x871ad953), + TOBN(0xf10774f7, 0xd22da9a9), TOBN(0x45b8a678, 0xcc8a9b0d), + TOBN(0xd9c2e722, 0xbdc32cff), TOBN(0xbf71b5f5, 0x337202a5), + TOBN(0x95c57f2f, 0x69fc4db9), TOBN(0xb6dad34c, 0x765d01e1), + TOBN(0x7e0bd13f, 0xcb904635), TOBN(0x61751253, 0x763a588c), + TOBN(0xd85c2997, 0x81af2c2d), TOBN(0xc0f7d9c4, 0x81b9d7da), + TOBN(0x838a34ae, 0x08533e8d), TOBN(0x15c4cb08, 0x311d8311), + TOBN(0x97f83285, 0x8e121e14), TOBN(0xeea7dc1e, 0x85000a5f), + TOBN(0x0c6059b6, 0x5d256274), TOBN(0xec9beace, 0xb95075c0), + TOBN(0x173daad7, 0x1df97828), TOBN(0xbf851cb5, 0xa8937877), + TOBN(0xb083c594, 0x01646f3c), TOBN(0x3bad30cf, 0x50c6d352), + TOBN(0xfeb2b202, 0x496bbcea), TOBN(0x3cf9fd4f, 0x18a1e8ba), + TOBN(0xd26de7ff, 0x1c066029), TOBN(0x39c81e9e, 0x4e9ed4f8), + TOBN(0xd8be0cb9, 0x7b390d35), TOBN(0x01df2bbd, 0x964aab27), + TOBN(0x3e8c1a65, 0xc3ef64f8), TOBN(0x567291d1, 0x716ed1dd), + TOBN(0x95499c6c, 0x5f5406d3), TOBN(0x71fdda39, 0x5ba8e23f), + TOBN(0xcfeb320e, 0xd5096ece), TOBN(0xbe7ba92b, 0xca66dd16), + TOBN(0x4608d36b, 0xc6fb5a7d), TOBN(0xe3eea15a, 0x6d2dd0e0), + TOBN(0x75b0a3eb, 0x8f97a36a), TOBN(0xf59814cc, 0x1c83de1e), + TOBN(0x56c9c5b0, 0x1c33c23f), TOBN(0xa96c1da4, 0x6faa4136), + TOBN(0x46bf2074, 0xde316551), TOBN(0x3b866e7b, 0x1f756c8f), + TOBN(0x727727d8, 0x1495ed6b), TOBN(0xb2394243, 0xb682dce7), + TOBN(0x8ab8454e, 0x758610f3), TOBN(0xc243ce84, 0x857d72a4), + TOBN(0x7b320d71, 0xdbbf370f), TOBN(0xff9afa37, 0x78e0f7ca), + TOBN(0x0119d1e0, 0xea7b523f), TOBN(0xb997f8cb, 0x058c7d42), + TOBN(0x285bcd2a, 0x37bbb184), TOBN(0x51dcec49, 0xa45d1fa6), + TOBN(0x6ade3b64, 0xe29634cb), TOBN(0x080c94a7, 0x26b86ef1), + TOBN(0xba583db1, 0x2283fbe3), TOBN(0x902bddc8, 0x5a9315ed), + TOBN(0x07c1ccb3, 0x86964bec), TOBN(0x78f4eacf, 0xb6258301), + TOBN(0x4bdf3a49, 0x56f90823), TOBN(0xba0f5080, 0x741d777b), + TOBN(0x091d71c3, 0xf38bf760), TOBN(0x9633d50f, 0x9b625b02), + TOBN(0x03ecb743, 0xb8c9de61), TOBN(0xb4751254, 0x5de74720), + TOBN(0x9f9defc9, 0x74ce1cb2), TOBN(0x774a4f6a, 0x00bd32ef), + TOBN(0xaca385f7, 0x73848f22), TOBN(0x53dad716, 0xf3f8558e), + TOBN(0xab7b34b0, 0x93c471f9), TOBN(0xf530e069, 0x19644bc7), + TOBN(0x3d9fb1ff, 0xdd59d31a), TOBN(0x4382e0df, 0x08daa795), + TOBN(0x165c6f4b, 0xd5cc88d7), TOBN(0xeaa392d5, 0x4a18c900), + TOBN(0x94203c67, 0x648024ee), TOBN(0x188763f2, 0x8c2fabcd), + TOBN(0xa80f87ac, 0xbbaec835), TOBN(0x632c96e0, 0xf29d8d54), + TOBN(0x29b0a60e, 0x4c00a95e), TOBN(0x2ef17f40, 0xe011e9fa), + TOBN(0xf6c0e1d1, 0x15b77223), TOBN(0xaaec2c62, 0x14b04e32), + TOBN(0xd35688d8, 0x3d84e58c), TOBN(0x2af5094c, 0x958571db), + TOBN(0x4fff7e19, 0x760682a6), TOBN(0x4cb27077, 0xe39a407c), + TOBN(0x0f59c547, 0x4ff0e321), TOBN(0x169f34a6, 0x1b34c8ff), + TOBN(0x2bff1096, 0x52bc1ba7), TOBN(0xa25423b7, 0x83583544), + TOBN(0x5d55d5d5, 0x0ac8b782), TOBN(0xff6622ec, 0x2db3c892), + TOBN(0x48fce741, 0x6b8bb642), TOBN(0x31d6998c, 0x69d7e3dc), + TOBN(0xdbaf8004, 0xcadcaed0), TOBN(0x801b0142, 0xd81d053c), + TOBN(0x94b189fc, 0x59630ec6), TOBN(0x120e9934, 0xaf762c8e), + TOBN(0x53a29aa4, 0xfdc6a404), TOBN(0x19d8e01e, 0xa1909948), + TOBN(0x3cfcabf1, 0xd7e89681), TOBN(0x3321a50d, 0x4e132d37), + TOBN(0xd0496863, 0xe9a86111), TOBN(0x8c0cde61, 0x06a3bc65), + TOBN(0xaf866c49, 0xfc9f8eef), TOBN(0x2066350e, 0xff7f5141), + TOBN(0x4f8a4689, 0xe56ddfbd), TOBN(0xea1b0c07, 0xfe32983a), + TOBN(0x2b317462, 0x873cb8cb), TOBN(0x658deddc, 0x2d93229f), + TOBN(0x65efaf4d, 0x0f64ef58), TOBN(0xfe43287d, 0x730cc7a8), + TOBN(0xaebc0c72, 0x3d047d70), TOBN(0x92efa539, 0xd92d26c9), + TOBN(0x06e78457, 0x94b56526), TOBN(0x415cb80f, 0x0961002d), + TOBN(0x89e5c565, 0x76dcb10f), TOBN(0x8bbb6982, 0xff9259fe), + TOBN(0x4fe8795b, 0x9abc2668), TOBN(0xb5d4f534, 0x1e678fb1), + TOBN(0x6601f3be, 0x7b7da2b9), TOBN(0x98da59e2, 0xa13d6805), + TOBN(0x190d8ea6, 0x01799a52), TOBN(0xa20cec41, 0xb86d2952), + TOBN(0x3062ffb2, 0x7fff2a7c), TOBN(0x741b32e5, 0x79f19d37), + TOBN(0xf80d8181, 0x4eb57d47), TOBN(0x7a2d0ed4, 0x16aef06b), + TOBN(0x09735fb0, 0x1cecb588), TOBN(0x1641caaa, 0xc6061f5b)} + , + {TOBN(0x7f99824f, 0x20151427), TOBN(0x206828b6, 0x92430206), + TOBN(0xaa9097d7, 0xe1112357), TOBN(0xacf9a2f2, 0x09e414ec), + TOBN(0xdbdac9da, 0x27915356), TOBN(0x7e0734b7, 0x001efee3), + TOBN(0x54fab5bb, 0xd2b288e2), TOBN(0x4c630fc4, 0xf62dd09c), + TOBN(0x8537107a, 0x1ac2703b), TOBN(0xb49258d8, 0x6bc857b5), + TOBN(0x57df14de, 0xbcdaccd1), TOBN(0x24ab68d7, 0xc4ae8529), + TOBN(0x7ed8b5d4, 0x734e59d0), TOBN(0x5f8740c8, 0xc495cc80), + TOBN(0x84aedd5a, 0x291db9b3), TOBN(0x80b360f8, 0x4fb995be), + TOBN(0xae915f5d, 0x5fa067d1), TOBN(0x4134b57f, 0x9668960c), + TOBN(0xbd3656d6, 0xa48edaac), TOBN(0xdac1e3e4, 0xfc1d7436), + TOBN(0x674ff869, 0xd81fbb26), TOBN(0x449ed3ec, 0xb26c33d4), + TOBN(0x85138705, 0xd94203e8), TOBN(0xccde538b, 0xbeeb6f4a), + TOBN(0x55d5c68d, 0xa61a76fa), TOBN(0x598b441d, 0xca1554dc), + TOBN(0xd39923b9, 0x773b279c), TOBN(0x33331d3c, 0x36bf9efc), + TOBN(0x2d4c848e, 0x298de399), TOBN(0xcfdb8e77, 0xa1a27f56), + TOBN(0x94c855ea, 0x57b8ab70), TOBN(0xdcdb9dae, 0x6f7879ba), + TOBN(0x7bdff8c2, 0x019f2a59), TOBN(0xb3ce5bb3, 0xcb4fbc74), + TOBN(0xea907f68, 0x8a9173dd), TOBN(0x6cd3d0d3, 0x95a75439), + TOBN(0x92ecc4d6, 0xefed021c), TOBN(0x09a9f9b0, 0x6a77339a), + TOBN(0x87ca6b15, 0x7188c64a), TOBN(0x10c29968, 0x44899158), + TOBN(0x5859a229, 0xed6e82ef), TOBN(0x16f338e3, 0x65ebaf4e), + TOBN(0x0cd31387, 0x5ead67ae), TOBN(0x1c73d228, 0x54ef0bb4), + TOBN(0x4cb55131, 0x74a5c8c7), TOBN(0x01cd2970, 0x7f69ad6a), + TOBN(0xa04d00dd, 0xe966f87e), TOBN(0xd96fe447, 0x0b7b0321), + TOBN(0x342ac06e, 0x88fbd381), TOBN(0x02cd4a84, 0x5c35a493), + TOBN(0xe8fa89de, 0x54f1bbcd), TOBN(0x341d6367, 0x2575ed4c), + TOBN(0xebe357fb, 0xd238202b), TOBN(0x600b4d1a, 0xa984ead9), + TOBN(0xc35c9f44, 0x52436ea0), TOBN(0x96fe0a39, 0xa370751b), + TOBN(0x4c4f0736, 0x7f636a38), TOBN(0x9f943fb7, 0x0e76d5cb), + TOBN(0xb03510ba, 0xa8b68b8b), TOBN(0xc246780a, 0x9ed07a1f), + TOBN(0x3c051415, 0x6d549fc2), TOBN(0xc2953f31, 0x607781ca), + TOBN(0x955e2c69, 0xd8d95413), TOBN(0xb300fadc, 0x7bd282e3), + TOBN(0x81fe7b50, 0x87e9189f), TOBN(0xdb17375c, 0xf42dda27), + TOBN(0x22f7d896, 0xcf0a5904), TOBN(0xa0e57c5a, 0xebe348e6), + TOBN(0xa61011d3, 0xf40e3c80), TOBN(0xb1189321, 0x8db705c5), + TOBN(0x4ed9309e, 0x50fedec3), TOBN(0xdcf14a10, 0x4d6d5c1d), + TOBN(0x056c265b, 0x55691342), TOBN(0xe8e08504, 0x91049dc7), + TOBN(0x131329f5, 0xc9bae20a), TOBN(0x96c8b3e8, 0xd9dccdb4), + TOBN(0x8c5ff838, 0xfb4ee6b4), TOBN(0xfc5a9aeb, 0x41e8ccf0), + TOBN(0x7417b764, 0xfae050c6), TOBN(0x0953c3d7, 0x00452080), + TOBN(0x21372682, 0x38dfe7e8), TOBN(0xea417e15, 0x2bb79d4b), + TOBN(0x59641f1c, 0x76e7cf2d), TOBN(0x271e3059, 0xea0bcfcc), + TOBN(0x624c7dfd, 0x7253ecbd), TOBN(0x2f552e25, 0x4fca6186), + TOBN(0xcbf84ecd, 0x4d866e9c), TOBN(0x73967709, 0xf68d4610), + TOBN(0xa14b1163, 0xc27901b4), TOBN(0xfd9236e0, 0x899b8bf3), + TOBN(0x42b091ec, 0xcbc6da0a), TOBN(0xbb1dac6f, 0x5ad1d297), + TOBN(0x80e61d53, 0xa91cf76e), TOBN(0x4110a412, 0xd31f1ee7), + TOBN(0x2d87c3ba, 0x13efcf77), TOBN(0x1f374bb4, 0xdf450d76), + TOBN(0x5e78e2f2, 0x0d188dab), TOBN(0xe3968ed0, 0xf4b885ef), + TOBN(0x46c0568e, 0x7314570f), TOBN(0x31616338, 0x01170521), + TOBN(0x18e1e7e2, 0x4f0c8afe), TOBN(0x4caa75ff, 0xdeea78da), + TOBN(0x82db67f2, 0x7c5d8a51), TOBN(0x36a44d86, 0x6f505370), + TOBN(0xd72c5bda, 0x0333974f), TOBN(0x5db516ae, 0x27a70146), + TOBN(0x34705281, 0x210ef921), TOBN(0xbff17a8f, 0x0c9c38e5), + TOBN(0x78f4814e, 0x12476da1), TOBN(0xc1e16613, 0x33c16980), + TOBN(0x9e5b386f, 0x424d4bca), TOBN(0x4c274e87, 0xc85740de), + TOBN(0xb6a9b88d, 0x6c2f5226), TOBN(0x14d1b944, 0x550d7ca8), + TOBN(0x580c85fc, 0x1fc41709), TOBN(0xc1da368b, 0x54c6d519), + TOBN(0x2b0785ce, 0xd5113cf7), TOBN(0x0670f633, 0x5a34708f), + TOBN(0x46e23767, 0x15cc3f88), TOBN(0x1b480cfa, 0x50c72c8f), + TOBN(0x20288602, 0x4147519a), TOBN(0xd0981eac, 0x26b372f0), + TOBN(0xa9d4a7ca, 0xa785ebc8), TOBN(0xd953c50d, 0xdbdf58e9), + TOBN(0x9d6361cc, 0xfd590f8f), TOBN(0x72e9626b, 0x44e6c917), + TOBN(0x7fd96110, 0x22eb64cf), TOBN(0x863ebb7e, 0x9eb288f3), + TOBN(0x6e6ab761, 0x6aca8ee7), TOBN(0x97d10b39, 0xd7b40358), + TOBN(0x1687d377, 0x1e5feb0d), TOBN(0xc83e50e4, 0x8265a27a), + TOBN(0x8f75a9fe, 0xc954b313), TOBN(0xcc2e8f47, 0x310d1f61), + TOBN(0xf5ba81c5, 0x6557d0e0), TOBN(0x25f9680c, 0x3eaf6207), + TOBN(0xf95c6609, 0x4354080b), TOBN(0x5225bfa5, 0x7bf2fe1c), + TOBN(0xc5c004e2, 0x5c7d98fa), TOBN(0x3561bf1c, 0x019aaf60), + TOBN(0x5e6f9f17, 0xba151474), TOBN(0xdec2f934, 0xb04f6eca), + TOBN(0x64e368a1, 0x269acb1e), TOBN(0x1332d9e4, 0x0cdda493), + TOBN(0x60d6cf69, 0xdf23de05), TOBN(0x66d17da2, 0x009339a0), + TOBN(0x9fcac985, 0x0a693923), TOBN(0xbcf057fc, 0xed7c6a6d), + TOBN(0xc3c5c8c5, 0xf0b5662c), TOBN(0x25318dd8, 0xdcba4f24), + TOBN(0x60e8cb75, 0x082b69ff), TOBN(0x7c23b3ee, 0x1e728c01), + TOBN(0x15e10a0a, 0x097e4403), TOBN(0xcb3d0a86, 0x19854665), + TOBN(0x88d8e211, 0xd67d4826), TOBN(0xb39af66e, 0x0b9d2839), + TOBN(0xa5f94588, 0xbd475ca8), TOBN(0xe06b7966, 0xc077b80b), + TOBN(0xfedb1485, 0xda27c26c), TOBN(0xd290d33a, 0xfe0fd5e0), + TOBN(0xa40bcc47, 0xf34fb0fa), TOBN(0xb4760cc8, 0x1fb1ab09), + TOBN(0x8fca0993, 0xa273bfe3), TOBN(0x13e4fe07, 0xf70b213c), + TOBN(0x3bcdb992, 0xfdb05163), TOBN(0x8c484b11, 0x0c2b19b6), + TOBN(0x1acb815f, 0xaaf2e3e2), TOBN(0xc6905935, 0xb89ff1b4), + TOBN(0xb2ad6f9d, 0x586e74e1), TOBN(0x488883ad, 0x67b80484), + TOBN(0x758aa2c7, 0x369c3ddb), TOBN(0x8ab74e69, 0x9f9afd31), + TOBN(0x10fc2d28, 0x5e21beb1), TOBN(0x3484518a, 0x318c42f9), + TOBN(0x377427dc, 0x53cf40c3), TOBN(0x9de0781a, 0x391bc1d9), + TOBN(0x8faee858, 0x693807e1), TOBN(0xa3865327, 0x4e81ccc7), + TOBN(0x02c30ff2, 0x6f835b84), TOBN(0xb604437b, 0x0d3d38d4), + TOBN(0xb3fc8a98, 0x5ca1823d), TOBN(0xb82f7ec9, 0x03be0324), + TOBN(0xee36d761, 0xcf684a33), TOBN(0x5a01df0e, 0x9f29bf7d), + TOBN(0x686202f3, 0x1306583d), TOBN(0x05b10da0, 0x437c622e), + TOBN(0xbf9aaa0f, 0x076a7bc8), TOBN(0x25e94efb, 0x8f8f4e43), + TOBN(0x8a35c9b7, 0xfa3dc26d), TOBN(0xe0e5fb93, 0x96ff03c5), + TOBN(0xa77e3843, 0xebc394ce), TOBN(0xcede6595, 0x8361de60), + TOBN(0xd27c22f6, 0xa1993545), TOBN(0xab01cc36, 0x24d671ba), + TOBN(0x63fa2877, 0xa169c28e), TOBN(0x925ef904, 0x2eb08376), + TOBN(0x3b2fa3cf, 0x53aa0b32), TOBN(0xb27beb5b, 0x71c49d7a), + TOBN(0xb60e1834, 0xd105e27f), TOBN(0xd6089788, 0x4f68570d), + TOBN(0x23094ce0, 0xd6fbc2ac), TOBN(0x738037a1, 0x815ff551), + TOBN(0xda73b1bb, 0x6bef119c), TOBN(0xdcf6c430, 0xeef506ba), + TOBN(0x00e4fe7b, 0xe3ef104a), TOBN(0xebdd9a2c, 0x0a065628), + TOBN(0x853a81c3, 0x8792043e), TOBN(0x22ad6ece, 0xb3b59108), + TOBN(0x9fb813c0, 0x39cd297d), TOBN(0x8ec7e16e, 0x05bda5d9), + TOBN(0x2834797c, 0x0d104b96), TOBN(0xcc11a2e7, 0x7c511510), + TOBN(0x96ca5a53, 0x96ee6380), TOBN(0x054c8655, 0xcea38742), + TOBN(0xb5946852, 0xd54dfa7d), TOBN(0x97c422e7, 0x1f4ab207), + TOBN(0xbf907509, 0x0c22b540), TOBN(0x2cde42aa, 0xb7c267d4), + TOBN(0xba18f9ed, 0x5ab0d693), TOBN(0x3ba62aa6, 0x6e4660d9), + TOBN(0xb24bf97b, 0xab9ea96a), TOBN(0x5d039642, 0xe3b60e32), + TOBN(0x4e6a4506, 0x7c4d9bd5), TOBN(0x666c5b9e, 0x7ed4a6a4), + TOBN(0xfa3fdcd9, 0x8edbd7cc), TOBN(0x4660bb87, 0xc6ccd753), + TOBN(0x9ae90820, 0x21e6b64f), TOBN(0x8a56a713, 0xb36bfb3f), + TOBN(0xabfce096, 0x5726d47f), TOBN(0x9eed01b2, 0x0b1a9a7f), + TOBN(0x30e9cad4, 0x4eb74a37), TOBN(0x7b2524cc, 0x53e9666d), + TOBN(0x6a29683b, 0x8f4b002f), TOBN(0xc2200d7a, 0x41f4fc20), + TOBN(0xcf3af47a, 0x3a338acc), TOBN(0x6539a4fb, 0xe7128975), + TOBN(0xcec31c14, 0xc33c7fcf), TOBN(0x7eb6799b, 0xc7be322b), + TOBN(0x119ef4e9, 0x6646f623), TOBN(0x7b7a26a5, 0x54d7299b), + TOBN(0xcb37f08d, 0x403f46f2), TOBN(0x94b8fc43, 0x1a0ec0c7), + TOBN(0xbb8514e3, 0xc332142f), TOBN(0xf3ed2c33, 0xe80d2a7a), + TOBN(0x8d2080af, 0xb639126c), TOBN(0xf7b6be60, 0xe3553ade), + TOBN(0x3950aa9f, 0x1c7e2b09), TOBN(0x847ff958, 0x6410f02b), + TOBN(0x877b7cf5, 0x678a31b0), TOBN(0xd50301ae, 0x3998b620), + TOBN(0x734257c5, 0xc00fb396), TOBN(0xf9fb18a0, 0x04e672a6), + TOBN(0xff8bd8eb, 0xe8758851), TOBN(0x1e64e4c6, 0x5d99ba44), + TOBN(0x4b8eaedf, 0x7dfd93b7), TOBN(0xba2f2a98, 0x04e76b8c), + TOBN(0x7d790cba, 0xe8053433), TOBN(0xc8e725a0, 0x3d2c9585), + TOBN(0x58c5c476, 0xcdd8f5ed), TOBN(0xd106b952, 0xefa9fe1d), + TOBN(0x3c5c775b, 0x0eff13a9), TOBN(0x242442ba, 0xe057b930), + TOBN(0xe9f458d4, 0xc9b70cbd), TOBN(0x69b71448, 0xa3cdb89a), + TOBN(0x41ee46f6, 0x0e2ed742), TOBN(0x573f1045, 0x40067493), + TOBN(0xb1e154ff, 0x9d54c304), TOBN(0x2ad0436a, 0x8d3a7502), + TOBN(0xee4aaa2d, 0x431a8121), TOBN(0xcd38b3ab, 0x886f11ed), + TOBN(0x57d49ea6, 0x034a0eb7), TOBN(0xd2b773bd, 0xf7e85e58), + TOBN(0x4a559ac4, 0x9b5c1f14), TOBN(0xc444be1a, 0x3e54df2b), + TOBN(0x13aad704, 0xeda41891), TOBN(0xcd927bec, 0x5eb5c788), + TOBN(0xeb3c8516, 0xe48c8a34), TOBN(0x1b7ac812, 0x4b546669), + TOBN(0x1815f896, 0x594df8ec), TOBN(0x87c6a79c, 0x79227865), + TOBN(0xae02a2f0, 0x9b56ddbd), TOBN(0x1339b5ac, 0x8a2f1cf3), + TOBN(0xf2b569c7, 0x839dff0d), TOBN(0xb0b9e864, 0xfee9a43d), + TOBN(0x4ff8ca41, 0x77bb064e), TOBN(0x145a2812, 0xfd249f63), + TOBN(0x3ab7beac, 0xf86f689a), TOBN(0x9bafec27, 0x01d35f5e), + TOBN(0x28054c65, 0x4265aa91), TOBN(0xa4b18304, 0x035efe42), + TOBN(0x6887b0e6, 0x9639dec7), TOBN(0xf4b8f6ad, 0x3d52aea5), + TOBN(0xfb9293cc, 0x971a8a13), TOBN(0x3f159e5d, 0x4c934d07), + TOBN(0x2c50e9b1, 0x09acbc29), TOBN(0x08eb65e6, 0x7154d129), + TOBN(0x4feff589, 0x30b75c3e), TOBN(0x0bb82fe2, 0x94491c93), + TOBN(0xd8ac377a, 0x89af62bb), TOBN(0xd7b51490, 0x9685e49f), + TOBN(0xabca9a7b, 0x04497f19), TOBN(0x1b35ed0a, 0x1a7ad13f), + TOBN(0x6b601e21, 0x3ec86ed6), TOBN(0xda91fcb9, 0xce0c76f1), + TOBN(0x9e28507b, 0xd7ab27e1), TOBN(0x7c19a555, 0x63945b7b), + TOBN(0x6b43f0a1, 0xaafc9827), TOBN(0x443b4fbd, 0x3aa55b91), + TOBN(0x962b2e65, 0x6962c88f), TOBN(0x139da8d4, 0xce0db0ca), + TOBN(0xb93f05dd, 0x1b8d6c4f), TOBN(0x779cdff7, 0x180b9824), + TOBN(0xbba23fdd, 0xae57c7b7), TOBN(0x345342f2, 0x1b932522), + TOBN(0xfd9c80fe, 0x556d4aa3), TOBN(0xa03907ba, 0x6525bb61), + TOBN(0x38b010e1, 0xff218933), TOBN(0xc066b654, 0xaa52117b), + TOBN(0x8e141920, 0x94f2e6ea), TOBN(0x66a27dca, 0x0d32f2b2), + TOBN(0x69c7f993, 0x048b3717), TOBN(0xbf5a989a, 0xb178ae1c), + TOBN(0x49fa9058, 0x564f1d6b), TOBN(0x27ec6e15, 0xd31fde4e), + TOBN(0x4cce0373, 0x7276e7fc), TOBN(0x64086d79, 0x89d6bf02), + TOBN(0x5a72f046, 0x4ccdd979), TOBN(0x909c3566, 0x47775631), + TOBN(0x1c07bc6b, 0x75dd7125), TOBN(0xb4c6bc97, 0x87a0428d), + TOBN(0x507ece52, 0xfdeb6b9d), TOBN(0xfca56512, 0xb2c95432), + TOBN(0x15d97181, 0xd0e8bd06), TOBN(0x384dd317, 0xc6bb46ea), + TOBN(0x5441ea20, 0x3952b624), TOBN(0xbcf70dee, 0x4e7dc2fb), + TOBN(0x372b016e, 0x6628e8c3), TOBN(0x07a0d667, 0xb60a7522), + TOBN(0xcf05751b, 0x0a344ee2), TOBN(0x0ec09a48, 0x118bdeec), + TOBN(0x6e4b3d4e, 0xd83dce46), TOBN(0x43a6316d, 0x99d2fc6e), + TOBN(0xa99d8989, 0x56cf044c), TOBN(0x7c7f4454, 0xae3e5fb7), + TOBN(0xb2e6b121, 0xfbabbe92), TOBN(0x281850fb, 0xe1330076), + TOBN(0x093581ec, 0x97890015), TOBN(0x69b1dded, 0x75ff77f5), + TOBN(0x7cf0b18f, 0xab105105), TOBN(0x953ced31, 0xa89ccfef), + TOBN(0x3151f85f, 0xeb914009), TOBN(0x3c9f1b87, 0x88ed48ad), + TOBN(0xc9aba1a1, 0x4a7eadcb), TOBN(0x928e7501, 0x522e71cf), + TOBN(0xeaede727, 0x3a2e4f83), TOBN(0x467e10d1, 0x1ce3bbd3), + TOBN(0xf3442ac3, 0xb955dcf0), TOBN(0xba96307d, 0xd3d5e527), + TOBN(0xf763a10e, 0xfd77f474), TOBN(0x5d744bd0, 0x6a6e1ff0), + TOBN(0xd287282a, 0xa777899e), TOBN(0xe20eda8f, 0xd03f3cde), + TOBN(0x6a7e75bb, 0x50b07d31), TOBN(0x0b7e2a94, 0x6f379de4), + TOBN(0x31cb64ad, 0x19f593cf), TOBN(0x7b1a9e4f, 0x1e76ef1d), + TOBN(0xe18c9c9d, 0xb62d609c), TOBN(0x439bad6d, 0xe779a650), + TOBN(0x219d9066, 0xe032f144), TOBN(0x1db632b8, 0xe8b2ec6a), + TOBN(0xff0d0fd4, 0xfda12f78), TOBN(0x56fb4c2d, 0x2a25d265), + TOBN(0x5f4e2ee1, 0x255a03f1), TOBN(0x61cd6af2, 0xe96af176), + TOBN(0xe0317ba8, 0xd068bc97), TOBN(0x927d6bab, 0x264b988e), + TOBN(0xa18f07e0, 0xe90fb21e), TOBN(0x00fd2b80, 0xbba7fca1), + TOBN(0x20387f27, 0x95cd67b5), TOBN(0x5b89a4e7, 0xd39707f7), + TOBN(0x8f83ad3f, 0x894407ce), TOBN(0xa0025b94, 0x6c226132), + TOBN(0xc79563c7, 0xf906c13b), TOBN(0x5f548f31, 0x4e7bb025), + TOBN(0x2b4c6b8f, 0xeac6d113), TOBN(0xa67e3f9c, 0x0e813c76), + TOBN(0x3982717c, 0x3fe1f4b9), TOBN(0x58865819, 0x26d8050e), + TOBN(0x99f3640c, 0xf7f06f20), TOBN(0xdc610216, 0x2a66ebc2), + TOBN(0x52f2c175, 0x767a1e08), TOBN(0x05660e1a, 0x5999871b), + TOBN(0x6b0f1762, 0x6d3c4693), TOBN(0xf0e7d627, 0x37ed7bea), + TOBN(0xc51758c7, 0xb75b226d), TOBN(0x40a88628, 0x1f91613b), + TOBN(0x889dbaa7, 0xbbb38ce0), TOBN(0xe0404b65, 0xbddcad81), + TOBN(0xfebccd3a, 0x8bc9671f), TOBN(0xfbf9a357, 0xee1f5375), + TOBN(0x5dc169b0, 0x28f33398), TOBN(0xb07ec11d, 0x72e90f65), + TOBN(0xae7f3b4a, 0xfaab1eb1), TOBN(0xd970195e, 0x5f17538a), + TOBN(0x52b05cbe, 0x0181e640), TOBN(0xf5debd62, 0x2643313d), + TOBN(0x76148154, 0x5df31f82), TOBN(0x23e03b33, 0x3a9e13c5), + TOBN(0xff758949, 0x4fde0c1f), TOBN(0xbf8a1abe, 0xe5b6ec20), + TOBN(0x702278fb, 0x87e1db6c), TOBN(0xc447ad7a, 0x35ed658f), + TOBN(0x48d4aa38, 0x03d0ccf2), TOBN(0x80acb338, 0x819a7c03), + TOBN(0x9bc7c89e, 0x6e17cecc), TOBN(0x46736b8b, 0x03be1d82), + TOBN(0xd65d7b60, 0xc0432f96), TOBN(0xddebe7a3, 0xdeb5442f), + TOBN(0x79a25307, 0x7dff69a2), TOBN(0x37a56d94, 0x02cf3122), + TOBN(0x8bab8aed, 0xf2350d0a), TOBN(0x13c3f276, 0x037b0d9a), + TOBN(0xc664957c, 0x44c65cae), TOBN(0x88b44089, 0xc2e71a88), + TOBN(0xdb88e5a3, 0x5cb02664), TOBN(0x5d4c0bf1, 0x8686c72e), + TOBN(0xea3d9b62, 0xa682d53e), TOBN(0x9b605ef4, 0x0b2ad431), + TOBN(0x71bac202, 0xc69645d0), TOBN(0xa115f03a, 0x6a1b66e7), + TOBN(0xfe2c563a, 0x158f4dc4), TOBN(0xf715b3a0, 0x4d12a78c), + TOBN(0x8f7f0a48, 0xd413213a), TOBN(0x2035806d, 0xc04becdb), + TOBN(0xecd34a99, 0x5d8587f5), TOBN(0x4d8c3079, 0x9f6d3a71), + TOBN(0x1b2a2a67, 0x8d95a8f6), TOBN(0xc58c9d7d, 0xf2110d0d), + TOBN(0xdeee81d5, 0xcf8fba3f), TOBN(0xa42be3c0, 0x0c7cdf68), + TOBN(0x2126f742, 0xd43b5eaa), TOBN(0x054a0766, 0xdfa59b85), + TOBN(0x9d0d5e36, 0x126bfd45), TOBN(0xa1f8fbd7, 0x384f8a8f), + TOBN(0x317680f5, 0xd563fccc), TOBN(0x48ca5055, 0xf280a928), + TOBN(0xe00b81b2, 0x27b578cf), TOBN(0x10aad918, 0x2994a514), + TOBN(0xd9e07b62, 0xb7bdc953), TOBN(0x9f0f6ff2, 0x5bc086dd), + TOBN(0x09d1ccff, 0x655eee77), TOBN(0x45475f79, 0x5bef7df1), + TOBN(0x3faa28fa, 0x86f702cc), TOBN(0x92e60905, 0x0f021f07), + TOBN(0xe9e62968, 0x7f8fa8c6), TOBN(0xbd71419a, 0xf036ea2c), + TOBN(0x171ee1cc, 0x6028da9a), TOBN(0x5352fe1a, 0xc251f573), + TOBN(0xf8ff236e, 0x3fa997f4), TOBN(0xd831b6c9, 0xa5749d5f), + TOBN(0x7c872e1d, 0xe350e2c2), TOBN(0xc56240d9, 0x1e0ce403), + TOBN(0xf9deb077, 0x6974f5cb), TOBN(0x7d50ba87, 0x961c3728), + TOBN(0xd6f89426, 0x5a3a2518), TOBN(0xcf817799, 0xc6303d43), + TOBN(0x510a0471, 0x619e5696), TOBN(0xab049ff6, 0x3a5e307b), + TOBN(0xe4cdf9b0, 0xfeb13ec7), TOBN(0xd5e97117, 0x9d8ff90c), + TOBN(0xf6f64d06, 0x9afa96af), TOBN(0x00d0bf5e, 0x9d2012a2), + TOBN(0xe63f301f, 0x358bcdc0), TOBN(0x07689e99, 0x0a9d47f8), + TOBN(0x1f689e2f, 0x4f43d43a), TOBN(0x4d542a16, 0x90920904), + TOBN(0xaea293d5, 0x9ca0a707), TOBN(0xd061fe45, 0x8ac68065), + TOBN(0x1033bf1b, 0x0090008c), TOBN(0x29749558, 0xc08a6db6), + TOBN(0x74b5fc59, 0xc1d5d034), TOBN(0xf712e9f6, 0x67e215e0), + TOBN(0xfd520cbd, 0x860200e6), TOBN(0x0229acb4, 0x3ea22588), + TOBN(0x9cd1e14c, 0xfff0c82e), TOBN(0x87684b62, 0x59c69e73), + TOBN(0xda85e61c, 0x96ccb989), TOBN(0x2d5dbb02, 0xa3d06493), + TOBN(0xf22ad33a, 0xe86b173c), TOBN(0xe8e41ea5, 0xa79ff0e3), + TOBN(0x01d2d725, 0xdd0d0c10), TOBN(0x31f39088, 0x032d28f9), + TOBN(0x7b3f71e1, 0x7829839e), TOBN(0x0cf691b4, 0x4502ae58), + TOBN(0xef658dbd, 0xbefc6115), TOBN(0xa5cd6ee5, 0xb3ab5314), + TOBN(0x206c8d7b, 0x5f1d2347), TOBN(0x794645ba, 0x4cc2253a), + TOBN(0xd517d8ff, 0x58389e08), TOBN(0x4fa20dee, 0x9f847288), + TOBN(0xeba072d8, 0xd797770a), TOBN(0x7360c91d, 0xbf429e26), + TOBN(0x7200a3b3, 0x80af8279), TOBN(0x6a1c9150, 0x82dadce3), + TOBN(0x0ee6d3a7, 0xc35d8794), TOBN(0x042e6558, 0x0356bae5), + TOBN(0x9f59698d, 0x643322fd), TOBN(0x9379ae15, 0x50a61967), + TOBN(0x64b9ae62, 0xfcc9981e), TOBN(0xaed3d631, 0x6d2934c6), + TOBN(0x2454b302, 0x5e4e65eb), TOBN(0xab09f647, 0xf9950428)} + , + {TOBN(0xb2083a12, 0x22248acc), TOBN(0x1f6ec0ef, 0x3264e366), + TOBN(0x5659b704, 0x5afdee28), TOBN(0x7a823a40, 0xe6430bb5), + TOBN(0x24592a04, 0xe1900a79), TOBN(0xcde09d4a, 0xc9ee6576), + TOBN(0x52b6463f, 0x4b5ea54a), TOBN(0x1efe9ed3, 0xd3ca65a7), + TOBN(0xe27a6dbe, 0x305406dd), TOBN(0x8eb7dc7f, 0xdd5d1957), + TOBN(0xf54a6876, 0x387d4d8f), TOBN(0x9c479409, 0xc7762de4), + TOBN(0xbe4d5b5d, 0x99b30778), TOBN(0x25380c56, 0x6e793682), + TOBN(0x602d37f3, 0xdac740e3), TOBN(0x140deabe, 0x1566e4ae), + TOBN(0x4481d067, 0xafd32acf), TOBN(0xd8f0fcca, 0xe1f71ccf), + TOBN(0xd208dd0c, 0xb596f2da), TOBN(0xd049d730, 0x9aad93f9), + TOBN(0xc79f263d, 0x42ab580e), TOBN(0x09411bb1, 0x23f707b4), + TOBN(0x8cfde1ff, 0x835e0eda), TOBN(0x72707490, 0x90f03402), + TOBN(0xeaee6126, 0xc49a861e), TOBN(0x024f3b65, 0xe14f0d06), + TOBN(0x51a3f1e8, 0xc69bfc17), TOBN(0xc3c3a8e9, 0xa7686381), + TOBN(0x3400752c, 0xb103d4c8), TOBN(0x02bc4613, 0x9218b36b), + TOBN(0xc67f75eb, 0x7651504a), TOBN(0xd6848b56, 0xd02aebfa), + TOBN(0xbd9802e6, 0xc30fa92b), TOBN(0x5a70d96d, 0x9a552784), + TOBN(0x9085c4ea, 0x3f83169b), TOBN(0xfa9423bb, 0x06908228), + TOBN(0x2ffebe12, 0xfe97a5b9), TOBN(0x85da6049, 0x71b99118), + TOBN(0x9cbc2f7f, 0x63178846), TOBN(0xfd96bc70, 0x9153218e), + TOBN(0x958381db, 0x1782269b), TOBN(0xae34bf79, 0x2597e550), + TOBN(0xbb5c6064, 0x5f385153), TOBN(0x6f0e96af, 0xe3088048), + TOBN(0xbf6a0215, 0x77884456), TOBN(0xb3b5688c, 0x69310ea7), + TOBN(0x17c94295, 0x04fad2de), TOBN(0xe020f0e5, 0x17896d4d), + TOBN(0x730ba0ab, 0x0976505f), TOBN(0x567f6813, 0x095e2ec5), + TOBN(0x47062010, 0x6331ab71), TOBN(0x72cfa977, 0x41d22b9f), + TOBN(0x33e55ead, 0x8a2373da), TOBN(0xa8d0d5f4, 0x7ba45a68), + TOBN(0xba1d8f9c, 0x03029d15), TOBN(0x8f34f1cc, 0xfc55b9f3), + TOBN(0xcca4428d, 0xbbe5a1a9), TOBN(0x8187fd5f, 0x3126bd67), + TOBN(0x0036973a, 0x48105826), TOBN(0xa39b6663, 0xb8bd61a0), + TOBN(0x6d42deef, 0x2d65a808), TOBN(0x4969044f, 0x94636b19), + TOBN(0xf611ee47, 0xdd5d564c), TOBN(0x7b2f3a49, 0xd2873077), + TOBN(0x94157d45, 0x300eb294), TOBN(0x2b2a656e, 0x169c1494), + TOBN(0xc000dd76, 0xd3a47aa9), TOBN(0xa2864e4f, 0xa6243ea4), + TOBN(0x82716c47, 0xdb89842e), TOBN(0x12dfd7d7, 0x61479fb7), + TOBN(0x3b9a2c56, 0xe0b2f6dc), TOBN(0x46be862a, 0xd7f85d67), + TOBN(0x03b0d8dd, 0x0f82b214), TOBN(0x460c34f9, 0xf103cbc6), + TOBN(0xf32e5c03, 0x18d79e19), TOBN(0x8b8888ba, 0xa84117f8), + TOBN(0x8f3c37dc, 0xc0722677), TOBN(0x10d21be9, 0x1c1c0f27), + TOBN(0xd47c8468, 0xe0f7a0c6), TOBN(0x9bf02213, 0xadecc0e0), + TOBN(0x0baa7d12, 0x42b48b99), TOBN(0x1bcb665d, 0x48424096), + TOBN(0x8b847cd6, 0xebfb5cfb), TOBN(0x87c2ae56, 0x9ad4d10d), + TOBN(0xf1cbb122, 0x0de36726), TOBN(0xe7043c68, 0x3fdfbd21), + TOBN(0x4bd0826a, 0x4e79d460), TOBN(0x11f5e598, 0x4bd1a2cb), + TOBN(0x97554160, 0xb7fe7b6e), TOBN(0x7d16189a, 0x400a3fb2), + TOBN(0xd73e9bea, 0xe328ca1e), TOBN(0x0dd04b97, 0xe793d8cc), + TOBN(0xa9c83c9b, 0x506db8cc), TOBN(0x5cd47aae, 0xcf38814c), + TOBN(0x26fc430d, 0xb64b45e6), TOBN(0x079b5499, 0xd818ea84), + TOBN(0xebb01102, 0xc1c24a3b), TOBN(0xca24e568, 0x1c161c1a), + TOBN(0x103eea69, 0x36f00a4a), TOBN(0x9ad76ee8, 0x76176c7b), + TOBN(0x97451fc2, 0x538e0ff7), TOBN(0x94f89809, 0x6604b3b0), + TOBN(0x6311436e, 0x3249cfd7), TOBN(0x27b4a7bd, 0x41224f69), + TOBN(0x03b5d21a, 0xe0ac2941), TOBN(0x279b0254, 0xc2d31937), + TOBN(0x3307c052, 0xcac992d0), TOBN(0x6aa7cb92, 0xefa8b1f3), + TOBN(0x5a182580, 0x0d37c7a5), TOBN(0x13380c37, 0x342d5422), + TOBN(0x92ac2d66, 0xd5d2ef92), TOBN(0x035a70c9, 0x030c63c6), + TOBN(0xc16025dd, 0x4ce4f152), TOBN(0x1f419a71, 0xf9df7c06), + TOBN(0x6d5b2214, 0x91e4bb14), TOBN(0xfc43c6cc, 0x839fb4ce), + TOBN(0x49f06591, 0x925d6b2d), TOBN(0x4b37d9d3, 0x62186598), + TOBN(0x8c54a971, 0xd01b1629), TOBN(0xe1a9c29f, 0x51d50e05), + TOBN(0x5109b785, 0x71ba1861), TOBN(0x48b22d5c, 0xd0c8f93d), + TOBN(0xe8fa84a7, 0x8633bb93), TOBN(0x53fba6ba, 0x5aebbd08), + TOBN(0x7ff27df3, 0xe5eea7d8), TOBN(0x521c8796, 0x68ca7158), + TOBN(0xb9d5133b, 0xce6f1a05), TOBN(0x2d50cd53, 0xfd0ebee4), + TOBN(0xc82115d6, 0xc5a3ef16), TOBN(0x993eff9d, 0xba079221), + TOBN(0xe4da2c5e, 0x4b5da81c), TOBN(0x9a89dbdb, 0x8033fd85), + TOBN(0x60819ebf, 0x2b892891), TOBN(0x53902b21, 0x5d14a4d5), + TOBN(0x6ac35051, 0xd7fda421), TOBN(0xcc6ab885, 0x61c83284), + TOBN(0x14eba133, 0xf74cff17), TOBN(0x240aaa03, 0xecb813f2), + TOBN(0xcfbb6540, 0x6f665bee), TOBN(0x084b1fe4, 0xa425ad73), + TOBN(0x009d5d16, 0xd081f6a6), TOBN(0x35304fe8, 0xeef82c90), + TOBN(0xf20346d5, 0xaa9eaa22), TOBN(0x0ada9f07, 0xac1c91e3), + TOBN(0xa6e21678, 0x968a6144), TOBN(0x54c1f77c, 0x07b31a1e), + TOBN(0xd6bb787e, 0x5781fbe1), TOBN(0x61bd2ee0, 0xe31f1c4a), + TOBN(0xf25aa1e9, 0x781105fc), TOBN(0x9cf2971f, 0x7b2f8e80), + TOBN(0x26d15412, 0xcdff919b), TOBN(0x01db4ebe, 0x34bc896e), + TOBN(0x7d9b3e23, 0xb40df1cf), TOBN(0x59337373, 0x94e971b4), + TOBN(0xbf57bd14, 0x669cf921), TOBN(0x865daedf, 0x0c1a1064), + TOBN(0x3eb70bd3, 0x83279125), TOBN(0xbc3d5b9f, 0x34ecdaab), + TOBN(0x91e3ed7e, 0x5f755caf), TOBN(0x49699f54, 0xd41e6f02), + TOBN(0x185770e1, 0xd4a7a15b), TOBN(0x08f3587a, 0xeaac87e7), + TOBN(0x352018db, 0x473133ea), TOBN(0x674ce719, 0x04fd30fc), + TOBN(0x7b8d9835, 0x088b3e0e), TOBN(0x7a0356a9, 0x5d0d47a1), + TOBN(0x9d9e7659, 0x6474a3c4), TOBN(0x61ea48a7, 0xff66966c), + TOBN(0x30417758, 0x0f3e4834), TOBN(0xfdbb21c2, 0x17a9afcb), + TOBN(0x756fa17f, 0x2f9a67b3), TOBN(0x2a6b2421, 0xa245c1a8), + TOBN(0x64be2794, 0x4af02291), TOBN(0xade465c6, 0x2a5804fe), + TOBN(0x8dffbd39, 0xa6f08fd7), TOBN(0xc4efa84c, 0xaa14403b), + TOBN(0xa1b91b2a, 0x442b0f5c), TOBN(0xb748e317, 0xcf997736), + TOBN(0x8d1b62bf, 0xcee90e16), TOBN(0x907ae271, 0x0b2078c0), + TOBN(0xdf31534b, 0x0c9bcddd), TOBN(0x043fb054, 0x39adce83), + TOBN(0x99031043, 0xd826846a), TOBN(0x61a9c0d6, 0xb144f393), + TOBN(0xdab48046, 0x47718427), TOBN(0xdf17ff9b, 0x6e830f8b), + TOBN(0x408d7ee8, 0xe49a1347), TOBN(0x6ac71e23, 0x91c1d4ae), + TOBN(0xc8cbb9fd, 0x1defd73c), TOBN(0x19840657, 0xbbbbfec5), + TOBN(0x39db1cb5, 0x9e7ef8ea), TOBN(0x78aa8296, 0x64105f30), + TOBN(0xa3d9b7f0, 0xa3738c29), TOBN(0x0a2f235a, 0xbc3250a3), + TOBN(0x55e506f6, 0x445e4caf), TOBN(0x0974f73d, 0x33475f7a), + TOBN(0xd37dbba3, 0x5ba2f5a8), TOBN(0x542c6e63, 0x6af40066), + TOBN(0x26d99b53, 0xc5d73e2c), TOBN(0x06060d7d, 0x6c3ca33e), + TOBN(0xcdbef1c2, 0x065fef4a), TOBN(0x77e60f7d, 0xfd5b92e3), + TOBN(0xd7c549f0, 0x26708350), TOBN(0x201b3ad0, 0x34f121bf), + TOBN(0x5fcac2a1, 0x0334fc14), TOBN(0x8a9a9e09, 0x344552f6), + TOBN(0x7dd8a1d3, 0x97653082), TOBN(0x5fc0738f, 0x79d4f289), + TOBN(0x787d244d, 0x17d2d8c3), TOBN(0xeffc6345, 0x70830684), + TOBN(0x5ddb96dd, 0xe4f73ae5), TOBN(0x8efb14b1, 0x172549a5), + TOBN(0x6eb73eee, 0x2245ae7a), TOBN(0xbca4061e, 0xea11f13e), + TOBN(0xb577421d, 0x30b01f5d), TOBN(0xaa688b24, 0x782e152c), + TOBN(0x67608e71, 0xbd3502ba), TOBN(0x4ef41f24, 0xb4de75a0), + TOBN(0xb08dde5e, 0xfd6125e5), TOBN(0xde484825, 0xa409543f), + TOBN(0x1f198d98, 0x65cc2295), TOBN(0x428a3771, 0x6e0edfa2), + TOBN(0x4f9697a2, 0xadf35fc7), TOBN(0x01a43c79, 0xf7cac3c7), + TOBN(0xb05d7059, 0x0fd3659a), TOBN(0x8927f30c, 0xbb7f2d9a), + TOBN(0x4023d1ac, 0x8cf984d3), TOBN(0x32125ed3, 0x02897a45), + TOBN(0xfb572dad, 0x3d414205), TOBN(0x73000ef2, 0xe3fa82a9), + TOBN(0x4c0868e9, 0xf10a5581), TOBN(0x5b61fc67, 0x6b0b3ca5), + TOBN(0xc1258d5b, 0x7cae440c), TOBN(0x21c08b41, 0x402b7531), + TOBN(0xf61a8955, 0xde932321), TOBN(0x3568faf8, 0x2d1408af), + TOBN(0x71b15e99, 0x9ecf965b), TOBN(0xf14ed248, 0xe917276f), + TOBN(0xc6f4caa1, 0x820cf9e2), TOBN(0x681b20b2, 0x18d83c7e), + TOBN(0x6cde738d, 0xc6c01120), TOBN(0x71db0813, 0xae70e0db), + TOBN(0x95fc0644, 0x74afe18c), TOBN(0x34619053, 0x129e2be7), + TOBN(0x80615cea, 0xdb2a3b15), TOBN(0x0a49a19e, 0xdb4c7073), + TOBN(0x0e1b84c8, 0x8fd2d367), TOBN(0xd74bf462, 0x033fb8aa), + TOBN(0x889f6d65, 0x533ef217), TOBN(0x7158c7e4, 0xc3ca2e87), + TOBN(0xfb670dfb, 0xdc2b4167), TOBN(0x75910a01, 0x844c257f), + TOBN(0xf336bf07, 0xcf88577d), TOBN(0x22245250, 0xe45e2ace), + TOBN(0x2ed92e8d, 0x7ca23d85), TOBN(0x29f8be4c, 0x2b812f58), + TOBN(0xdd9ebaa7, 0x076fe12b), TOBN(0x3f2400cb, 0xae1537f9), + TOBN(0x1aa93528, 0x17bdfb46), TOBN(0xc0f98430, 0x67883b41), + TOBN(0x5590ede1, 0x0170911d), TOBN(0x7562f5bb, 0x34d4b17f), + TOBN(0xe1fa1df2, 0x1826b8d2), TOBN(0xb40b796a, 0x6bd80d59), + TOBN(0xd65bf197, 0x3467ba92), TOBN(0x8c9b46db, 0xf70954b0), + TOBN(0x97c8a0f3, 0x0e78f15d), TOBN(0xa8f3a69a, 0x85a4c961), + TOBN(0x4242660f, 0x61e4ce9b), TOBN(0xbf06aab3, 0x6ea6790c), + TOBN(0xc6706f8e, 0xec986416), TOBN(0x9e56dec1, 0x9a9fc225), + TOBN(0x527c46f4, 0x9a9898d9), TOBN(0xd799e77b, 0x5633cdef), + TOBN(0x24eacc16, 0x7d9e4297), TOBN(0xabb61cea, 0x6b1cb734), + TOBN(0xbee2e8a7, 0xf778443c), TOBN(0x3bb42bf1, 0x29de2fe6), + TOBN(0xcbed86a1, 0x3003bb6f), TOBN(0xd3918e6c, 0xd781cdf6), + TOBN(0x4bee3271, 0x9a5103f1), TOBN(0x5243efc6, 0xf50eac06), + TOBN(0xb8e122cb, 0x6adcc119), TOBN(0x1b7faa84, 0xc0b80a08), + TOBN(0x32c3d1bd, 0x6dfcd08c), TOBN(0x129dec4e, 0x0be427de), + TOBN(0x98ab679c, 0x1d263c83), TOBN(0xafc83cb7, 0xcef64eff), + TOBN(0x85eb6088, 0x2fa6be76), TOBN(0x892585fb, 0x1328cbfe), + TOBN(0xc154d3ed, 0xcf618dda), TOBN(0xc44f601b, 0x3abaf26e), + TOBN(0x7bf57d0b, 0x2be1fdfd), TOBN(0xa833bd2d, 0x21137fee), + TOBN(0x9353af36, 0x2db591a8), TOBN(0xc76f26dc, 0x5562a056), + TOBN(0x1d87e47d, 0x3fdf5a51), TOBN(0x7afb5f93, 0x55c9cab0), + TOBN(0x91bbf58f, 0x89e0586e), TOBN(0x7c72c018, 0x0d843709), + TOBN(0xa9a5aafb, 0x99b5c3dc), TOBN(0xa48a0f1d, 0x3844aeb0), + TOBN(0x7178b7dd, 0xb667e482), TOBN(0x453985e9, 0x6e23a59a), + TOBN(0x4a54c860, 0x01b25dd8), TOBN(0x0dd37f48, 0xfb897c8a), + TOBN(0x5f8aa610, 0x0ea90cd9), TOBN(0xc8892c68, 0x16d5830d), + TOBN(0xeb4befc0, 0xef514ca5), TOBN(0x478eb679, 0xe72c9ee6), + TOBN(0x9bca20da, 0xdbc40d5f), TOBN(0xf015de21, 0xdde4f64a), + TOBN(0xaa6a4de0, 0xeaf4b8a5), TOBN(0x68cfd9ca, 0x4bc60e32), + TOBN(0x668a4b01, 0x7fd15e70), TOBN(0xd9f0694a, 0xf27dc09d), + TOBN(0xf6c3cad5, 0xba708bcd), TOBN(0x5cd2ba69, 0x5bb95c2a), + TOBN(0xaa28c1d3, 0x33c0a58f), TOBN(0x23e274e3, 0xabc77870), + TOBN(0x44c3692d, 0xdfd20a4a), TOBN(0x091c5fd3, 0x81a66653), + TOBN(0x6c0bb691, 0x09a0757d), TOBN(0x9072e8b9, 0x667343ea), + TOBN(0x31d40eb0, 0x80848bec), TOBN(0x95bd480a, 0x79fd36cc), + TOBN(0x01a77c61, 0x65ed43f5), TOBN(0xafccd127, 0x2e0d40bf), + TOBN(0xeccfc82d, 0x1cc1884b), TOBN(0xc85ac201, 0x5d4753b4), + TOBN(0xc7a6caac, 0x658e099f), TOBN(0xcf46369e, 0x04b27390), + TOBN(0xe2e7d049, 0x506467ea), TOBN(0x481b63a2, 0x37cdeccc), + TOBN(0x4029abd8, 0xed80143a), TOBN(0x28bfe3c7, 0xbcb00b88), + TOBN(0x3bec1009, 0x0643d84a), TOBN(0x885f3668, 0xabd11041), + TOBN(0xdb02432c, 0xf83a34d6), TOBN(0x32f7b360, 0x719ceebe), + TOBN(0xf06c7837, 0xdad1fe7a), TOBN(0x60a157a9, 0x5441a0b0), + TOBN(0x704970e9, 0xe2d47550), TOBN(0xcd2bd553, 0x271b9020), + TOBN(0xff57f82f, 0x33e24a0b), TOBN(0x9cbee23f, 0xf2565079), + TOBN(0x16353427, 0xeb5f5825), TOBN(0x276feec4, 0xe948d662), + TOBN(0xd1b62bc6, 0xda10032b), TOBN(0x718351dd, 0xf0e72a53), + TOBN(0x93452076, 0x2420e7ba), TOBN(0x96368fff, 0x3a00118d), + TOBN(0x00ce2d26, 0x150a49e4), TOBN(0x0c28b636, 0x3f04706b), + TOBN(0xbad65a46, 0x58b196d0), TOBN(0x6c8455fc, 0xec9f8b7c), + TOBN(0xe90c895f, 0x2d71867e), TOBN(0x5c0be31b, 0xedf9f38c), + TOBN(0x2a37a15e, 0xd8f6ec04), TOBN(0x239639e7, 0x8cd85251), + TOBN(0xd8975315, 0x9c7c4c6b), TOBN(0x603aa3c0, 0xd7409af7), + TOBN(0xb8d53d0c, 0x007132fb), TOBN(0x68d12af7, 0xa6849238), + TOBN(0xbe0607e7, 0xbf5d9279), TOBN(0x9aa50055, 0xaada74ce), + TOBN(0xe81079cb, 0xba7e8ccb), TOBN(0x610c71d1, 0xa5f4ff5e), + TOBN(0x9e2ee1a7, 0x5aa07093), TOBN(0xca84004b, 0xa75da47c), + TOBN(0x074d3951, 0x3de75401), TOBN(0xf938f756, 0xbb311592), + TOBN(0x96197618, 0x00a43421), TOBN(0x39a25362, 0x07bc78c8), + TOBN(0x278f710a, 0x0a171276), TOBN(0xb28446ea, 0x8d1a8f08), + TOBN(0x184781bf, 0xe3b6a661), TOBN(0x7751cb1d, 0xe6d279f7), + TOBN(0xf8ff95d6, 0xc59eb662), TOBN(0x186d90b7, 0x58d3dea7), + TOBN(0x0e4bb6c1, 0xdfb4f754), TOBN(0x5c5cf56b, 0x2b2801dc), + TOBN(0xc561e452, 0x1f54564d), TOBN(0xb4fb8c60, 0xf0dd7f13), + TOBN(0xf8849630, 0x33ff98c7), TOBN(0x9619fffa, 0xcf17769c), + TOBN(0xf8090bf6, 0x1bfdd80a), TOBN(0x14d9a149, 0x422cfe63), + TOBN(0xb354c360, 0x6f6df9ea), TOBN(0xdbcf770d, 0x218f17ea), + TOBN(0x207db7c8, 0x79eb3480), TOBN(0x213dbda8, 0x559b6a26), + TOBN(0xac4c200b, 0x29fc81b3), TOBN(0xebc3e09f, 0x171d87c1), + TOBN(0x91799530, 0x1481aa9e), TOBN(0x051b92e1, 0x92e114fa), + TOBN(0xdf8f92e9, 0xecb5537f), TOBN(0x44b1b2cc, 0x290c7483), + TOBN(0xa711455a, 0x2adeb016), TOBN(0x964b6856, 0x81a10c2c), + TOBN(0x4f159d99, 0xcec03623), TOBN(0x05532225, 0xef3271ea), + TOBN(0xb231bea3, 0xc5ee4849), TOBN(0x57a54f50, 0x7094f103), + TOBN(0x3e2d421d, 0x9598b352), TOBN(0xe865a49c, 0x67412ab4), + TOBN(0xd2998a25, 0x1cc3a912), TOBN(0x5d092808, 0x0c74d65d), + TOBN(0x73f45908, 0x4088567a), TOBN(0xeb6b280e, 0x1f214a61), + TOBN(0x8c9adc34, 0xcaf0c13d), TOBN(0x39d12938, 0xf561fb80), + TOBN(0xb2dc3a5e, 0xbc6edfb4), TOBN(0x7485b1b1, 0xfe4d210e), + TOBN(0x062e0400, 0xe186ae72), TOBN(0x91e32d5c, 0x6eeb3b88), + TOBN(0x6df574d7, 0x4be59224), TOBN(0xebc88ccc, 0x716d55f3), + TOBN(0x26c2e6d0, 0xcad6ed33), TOBN(0xc6e21e7d, 0x0d3e8b10), + TOBN(0x2cc5840e, 0x5bcc36bb), TOBN(0x9292445e, 0x7da74f69), + TOBN(0x8be8d321, 0x4e5193a8), TOBN(0x3ec23629, 0x8df06413), + TOBN(0xc7e9ae85, 0xb134defa), TOBN(0x6073b1d0, 0x1bb2d475), + TOBN(0xb9ad615e, 0x2863c00d), TOBN(0x9e29493d, 0x525f4ac4), + TOBN(0xc32b1dea, 0x4e9acf4f), TOBN(0x3e1f01c8, 0xa50db88d), + TOBN(0xb05d70ea, 0x04da916c), TOBN(0x714b0d0a, 0xd865803e), + TOBN(0x4bd493fc, 0x9920cb5e), TOBN(0x5b44b1f7, 0x92c7a3ac), + TOBN(0xa2a77293, 0xbcec9235), TOBN(0x5ee06e87, 0xcd378553), + TOBN(0xceff8173, 0xda621607), TOBN(0x2bb03e4c, 0x99f5d290), + TOBN(0x2945106a, 0xa6f734ac), TOBN(0xb5056604, 0xd25c4732), + TOBN(0x5945920c, 0xe079afee), TOBN(0x686e17a0, 0x6789831f), + TOBN(0x5966bee8, 0xb74a5ae5), TOBN(0x38a673a2, 0x1e258d46), + TOBN(0xbd1cc1f2, 0x83141c95), TOBN(0x3b2ecf4f, 0x0e96e486), + TOBN(0xcd3aa896, 0x74e5fc78), TOBN(0x415ec10c, 0x2482fa7a), + TOBN(0x15234419, 0x80503380), TOBN(0x513d917a, 0xd314b392), + TOBN(0xb0b52f4e, 0x63caecae), TOBN(0x07bf22ad, 0x2dc7780b), + TOBN(0xe761e8a1, 0xe4306839), TOBN(0x1b3be962, 0x5dd7feaa), + TOBN(0x4fe728de, 0x74c778f1), TOBN(0xf1fa0bda, 0x5e0070f6), + TOBN(0x85205a31, 0x6ec3f510), TOBN(0x2c7e4a14, 0xd2980475), + TOBN(0xde3c19c0, 0x6f30ebfd), TOBN(0xdb1c1f38, 0xd4b7e644), + TOBN(0xfe291a75, 0x5dce364a), TOBN(0xb7b22a3c, 0x058f5be3), + TOBN(0x2cd2c302, 0x37fea38c), TOBN(0x2930967a, 0x2e17be17), + TOBN(0x87f009de, 0x0c061c65), TOBN(0xcb014aac, 0xedc6ed44), + TOBN(0x49bd1cb4, 0x3bafb1eb), TOBN(0x81bd8b5c, 0x282d3688), + TOBN(0x1cdab87e, 0xf01a17af), TOBN(0x21f37ac4, 0xe710063b), + TOBN(0x5a6c5676, 0x42fc8193), TOBN(0xf4753e70, 0x56a6015c), + TOBN(0x020f795e, 0xa15b0a44), TOBN(0x8f37c8d7, 0x8958a958), + TOBN(0x63b7e89b, 0xa4b675b5), TOBN(0xb4fb0c0c, 0x0fc31aea), + TOBN(0xed95e639, 0xa7ff1f2e), TOBN(0x9880f5a3, 0x619614fb), + TOBN(0xdeb6ff02, 0x947151ab), TOBN(0x5bc5118c, 0xa868dcdb), + TOBN(0xd8da2055, 0x4c20cea5), TOBN(0xcac2776e, 0x14c4d69a), + TOBN(0xcccb22c1, 0x622d599b), TOBN(0xa4ddb653, 0x68a9bb50), + TOBN(0x2c4ff151, 0x1b4941b4), TOBN(0xe1ff19b4, 0x6efba588), + TOBN(0x35034363, 0xc48345e0), TOBN(0x45542e3d, 0x1e29dfc4), + TOBN(0xf197cb91, 0x349f7aed), TOBN(0x3b2b5a00, 0x8fca8420), + TOBN(0x7c175ee8, 0x23aaf6d8), TOBN(0x54dcf421, 0x35af32b6), + TOBN(0x0ba14307, 0x27d6561e), TOBN(0x879d5ee4, 0xd175b1e2), + TOBN(0xc7c43673, 0x99807db5), TOBN(0x77a54455, 0x9cd55bcd), + TOBN(0xe6c2ff13, 0x0105c072), TOBN(0x18f7a99f, 0x8dda7da4), + TOBN(0x4c301820, 0x0e2d35c1), TOBN(0x06a53ca0, 0xd9cc6c82), + TOBN(0xaa21cc1e, 0xf1aa1d9e), TOBN(0x32414334, 0x4a75b1e8), + TOBN(0x2a6d1328, 0x0ebe9fdc), TOBN(0x16bd173f, 0x98a4755a), + TOBN(0xfbb9b245, 0x2133ffd9), TOBN(0x39a8b2f1, 0x830f1a20), + TOBN(0x484bc97d, 0xd5a1f52a), TOBN(0xd6aebf56, 0xa40eddf8), + TOBN(0x32257acb, 0x76ccdac6), TOBN(0xaf4d36ec, 0x1586ff27), + TOBN(0x8eaa8863, 0xf8de7dd1), TOBN(0x0045d5cf, 0x88647c16)} + , + {TOBN(0xa6f3d574, 0xc005979d), TOBN(0xc2072b42, 0x6a40e350), + TOBN(0xfca5c156, 0x8de2ecf9), TOBN(0xa8c8bf5b, 0xa515344e), + TOBN(0x97aee555, 0x114df14a), TOBN(0xd4374a4d, 0xfdc5ec6b), + TOBN(0x754cc28f, 0x2ca85418), TOBN(0x71cb9e27, 0xd3c41f78), + TOBN(0x89105079, 0x03605c39), TOBN(0xf0843d9e, 0xa142c96c), + TOBN(0xf3744934, 0x16923684), TOBN(0x732caa2f, 0xfa0a2893), + TOBN(0xb2e8c270, 0x61160170), TOBN(0xc32788cc, 0x437fbaa3), + TOBN(0x39cd818e, 0xa6eda3ac), TOBN(0xe2e94239, 0x9e2b2e07), + TOBN(0x6967d39b, 0x0260e52a), TOBN(0xd42585cc, 0x90653325), + TOBN(0x0d9bd605, 0x21ca7954), TOBN(0x4fa20877, 0x81ed57b3), + TOBN(0x60c1eff8, 0xe34a0bbe), TOBN(0x56b0040c, 0x84f6ef64), + TOBN(0x28be2b24, 0xb1af8483), TOBN(0xb2278163, 0xf5531614), + TOBN(0x8df27545, 0x5922ac1c), TOBN(0xa7b3ef5c, 0xa52b3f63), + TOBN(0x8e77b214, 0x71de57c4), TOBN(0x31682c10, 0x834c008b), + TOBN(0xc76824f0, 0x4bd55d31), TOBN(0xb6d1c086, 0x17b61c71), + TOBN(0x31db0903, 0xc2a5089d), TOBN(0x9c092172, 0x184e5d3f), + TOBN(0xdd7ced5b, 0xc00cc638), TOBN(0x1a2015eb, 0x61278fc2), + TOBN(0x2e8e5288, 0x6a37f8d6), TOBN(0xc457786f, 0xe79933ad), + TOBN(0xb3fe4cce, 0x2c51211a), TOBN(0xad9b10b2, 0x24c20498), + TOBN(0x90d87a4f, 0xd28db5e5), TOBN(0x698cd105, 0x3aca2fc3), + TOBN(0x4f112d07, 0xe91b536d), TOBN(0xceb982f2, 0x9eba09d6), + TOBN(0x3c157b2c, 0x197c396f), TOBN(0xe23c2d41, 0x7b66eb24), + TOBN(0x480c57d9, 0x3f330d37), TOBN(0xb3a4c8a1, 0x79108deb), + TOBN(0x702388de, 0xcb199ce5), TOBN(0x0b019211, 0xb944a8d4), + TOBN(0x24f2a692, 0x840bb336), TOBN(0x7c353bdc, 0xa669fa7b), + TOBN(0xda20d6fc, 0xdec9c300), TOBN(0x625fbe2f, 0xa13a4f17), + TOBN(0xa2b1b61a, 0xdbc17328), TOBN(0x008965bf, 0xa9515621), + TOBN(0x49690939, 0xc620ff46), TOBN(0x182dd27d, 0x8717e91c), + TOBN(0x5ace5035, 0xea6c3997), TOBN(0x54259aaa, 0xc2610bef), + TOBN(0xef18bb3f, 0x3c80dd39), TOBN(0x6910b95b, 0x5fc3fa39), + TOBN(0xfce2f510, 0x43e09aee), TOBN(0xced56c9f, 0xa7675665), + TOBN(0x10e265ac, 0xd872db61), TOBN(0x6982812e, 0xae9fce69), + TOBN(0x29be11c6, 0xce800998), TOBN(0x72bb1752, 0xb90360d9), + TOBN(0x2c193197, 0x5a4ad590), TOBN(0x2ba2f548, 0x9fc1dbc0), + TOBN(0x7fe4eebb, 0xe490ebe0), TOBN(0x12a0a4cd, 0x7fae11c0), + TOBN(0x7197cf81, 0xe903ba37), TOBN(0xcf7d4aa8, 0xde1c6dd8), + TOBN(0x92af6bf4, 0x3fd5684c), TOBN(0x2b26eecf, 0x80360aa1), + TOBN(0xbd960f30, 0x00546a82), TOBN(0x407b3c43, 0xf59ad8fe), + TOBN(0x86cae5fe, 0x249c82ba), TOBN(0x9e0faec7, 0x2463744c), + TOBN(0x87f551e8, 0x94916272), TOBN(0x033f9344, 0x6ceb0615), + TOBN(0x1e5eb0d1, 0x8be82e84), TOBN(0x89967f0e, 0x7a582fef), + TOBN(0xbcf687d5, 0xa6e921fa), TOBN(0xdfee4cf3, 0xd37a09ba), + TOBN(0x94f06965, 0xb493c465), TOBN(0x638b9a1c, 0x7635c030), + TOBN(0x76667864, 0x66f05e9f), TOBN(0xccaf6808, 0xc04da725), + TOBN(0xca2eb690, 0x768fccfc), TOBN(0xf402d37d, 0xb835b362), + TOBN(0x0efac0d0, 0xe2fdfcce), TOBN(0xefc9cdef, 0xb638d990), + TOBN(0x2af12b72, 0xd1669a8b), TOBN(0x33c536bc, 0x5774ccbd), + TOBN(0x30b21909, 0xfb34870e), TOBN(0xc38fa2f7, 0x7df25aca), + TOBN(0x74c5f02b, 0xbf81f3f5), TOBN(0x0525a5ae, 0xaf7e4581), + TOBN(0x88d2aaba, 0x433c54ae), TOBN(0xed9775db, 0x806a56c5), + TOBN(0xd320738a, 0xc0edb37d), TOBN(0x25fdb6ee, 0x66cc1f51), + TOBN(0xac661d17, 0x10600d76), TOBN(0x931ec1f3, 0xbdd1ed76), + TOBN(0x65c11d62, 0x19ee43f1), TOBN(0x5cd57c3e, 0x60829d97), + TOBN(0xd26c91a3, 0x984be6e8), TOBN(0xf08d9309, 0x8b0c53bd), + TOBN(0x94bc9e5b, 0xc016e4ea), TOBN(0xd3916839, 0x11d43d2b), + TOBN(0x886c5ad7, 0x73701155), TOBN(0xe0377626, 0x20b00715), + TOBN(0x7f01c9ec, 0xaa80ba59), TOBN(0x3083411a, 0x68538e51), + TOBN(0x970370f1, 0xe88128af), TOBN(0x625cc3db, 0x91dec14b), + TOBN(0xfef9666c, 0x01ac3107), TOBN(0xb2a8d577, 0xd5057ac3), + TOBN(0xb0f26299, 0x92be5df7), TOBN(0xf579c8e5, 0x00353924), + TOBN(0xb8fa3d93, 0x1341ed7a), TOBN(0x4223272c, 0xa7b59d49), + TOBN(0x3dcb1947, 0x83b8c4a4), TOBN(0x4e413c01, 0xed1302e4), + TOBN(0x6d999127, 0xe17e44ce), TOBN(0xee86bf75, 0x33b3adfb), + TOBN(0xf6902fe6, 0x25aa96ca), TOBN(0xb73540e4, 0xe5aae47d), + TOBN(0x32801d7b, 0x1b4a158c), TOBN(0xe571c99e, 0x27e2a369), + TOBN(0x40cb76c0, 0x10d9f197), TOBN(0xc308c289, 0x3167c0ae), + TOBN(0xa6ef9dd3, 0xeb7958f2), TOBN(0xa7226dfc, 0x300879b1), + TOBN(0x6cd0b362, 0x7edf0636), TOBN(0x4efbce6c, 0x7bc37eed), + TOBN(0x75f92a05, 0x8d699021), TOBN(0x586d4c79, 0x772566e3), + TOBN(0x378ca5f1, 0x761ad23a), TOBN(0x650d86fc, 0x1465a8ac), + TOBN(0x7a4ed457, 0x842ba251), TOBN(0x6b65e3e6, 0x42234933), + TOBN(0xaf1543b7, 0x31aad657), TOBN(0xa4cefe98, 0xcbfec369), + TOBN(0xb587da90, 0x9f47befb), TOBN(0x6562e9fb, 0x41312d13), + TOBN(0xa691ea59, 0xeff1cefe), TOBN(0xcc30477a, 0x05fc4cf6), + TOBN(0xa1632461, 0x0b0ffd3d), TOBN(0xa1f16f3b, 0x5b355956), + TOBN(0x5b148d53, 0x4224ec24), TOBN(0xdc834e7b, 0xf977012a), + TOBN(0x7bfc5e75, 0xb2c69dbc), TOBN(0x3aa77a29, 0x03c3da6c), + TOBN(0xde0df03c, 0xca910271), TOBN(0xcbd5ca4a, 0x7806dc55), + TOBN(0xe1ca5807, 0x6db476cb), TOBN(0xfde15d62, 0x5f37a31e), + TOBN(0xf49af520, 0xf41af416), TOBN(0x96c5c5b1, 0x7d342db5), + TOBN(0x155c43b7, 0xeb4ceb9b), TOBN(0x2e993010, 0x4e77371a), + TOBN(0x1d2987da, 0x675d43af), TOBN(0xef2bc1c0, 0x8599fd72), + TOBN(0x96894b7b, 0x9342f6b2), TOBN(0x201eadf2, 0x7c8e71f0), + TOBN(0xf3479d9f, 0x4a1f3efc), TOBN(0xe0f8a742, 0x702a9704), + TOBN(0xeafd44b6, 0xb3eba40c), TOBN(0xf9739f29, 0xc1c1e0d0), + TOBN(0x0091471a, 0x619d505e), TOBN(0xc15f9c96, 0x9d7c263e), + TOBN(0x5be47285, 0x83afbe33), TOBN(0xa3b6d6af, 0x04f1e092), + TOBN(0xe76526b9, 0x751a9d11), TOBN(0x2ec5b26d, 0x9a4ae4d2), + TOBN(0xeb66f4d9, 0x02f6fb8d), TOBN(0x4063c561, 0x96912164), + TOBN(0xeb7050c1, 0x80ef3000), TOBN(0x288d1c33, 0xeaa5b3f0), + TOBN(0xe87c68d6, 0x07806fd8), TOBN(0xb2f7f9d5, 0x4bbbf50f), + TOBN(0x25972f3a, 0xac8d6627), TOBN(0xf8547774, 0x10e8c13b), + TOBN(0xcc50ef6c, 0x872b4a60), TOBN(0xab2a34a4, 0x4613521b), + TOBN(0x39c5c190, 0x983e15d1), TOBN(0x61dde5df, 0x59905512), + TOBN(0xe417f621, 0x9f2275f3), TOBN(0x0750c8b6, 0x451d894b), + TOBN(0x75b04ab9, 0x78b0bdaa), TOBN(0x3bfd9fd4, 0x458589bd), + TOBN(0xf1013e30, 0xee9120b6), TOBN(0x2b51af93, 0x23a4743e), + TOBN(0xea96ffae, 0x48d14d9e), TOBN(0x71dc0dbe, 0x698a1d32), + TOBN(0x914962d2, 0x0180cca4), TOBN(0x1ae60677, 0xc3568963), + TOBN(0x8cf227b1, 0x437bc444), TOBN(0xc650c83b, 0xc9962c7a), + TOBN(0x23c2c7dd, 0xfe7ccfc4), TOBN(0xf925c89d, 0x1b929d48), + TOBN(0x4460f74b, 0x06783c33), TOBN(0xac2c8d49, 0xa590475a), + TOBN(0xfb40b407, 0xb807bba0), TOBN(0x9d1e362d, 0x69ff8f3a), + TOBN(0xa33e9681, 0xcbef64a4), TOBN(0x67ece5fa, 0x332fb4b2), + TOBN(0x6900a99b, 0x739f10e3), TOBN(0xc3341ca9, 0xff525925), + TOBN(0xee18a626, 0xa9e2d041), TOBN(0xa5a83685, 0x29580ddd), + TOBN(0xf3470c81, 0x9d7de3cd), TOBN(0xedf02586, 0x2062cf9c), + TOBN(0xf43522fa, 0xc010edb0), TOBN(0x30314135, 0x13a4b1ae), + TOBN(0xc792e02a, 0xdb22b94b), TOBN(0x993d8ae9, 0xa1eaa45b), + TOBN(0x8aad6cd3, 0xcd1e1c63), TOBN(0x89529ca7, 0xc5ce688a), + TOBN(0x2ccee3aa, 0xe572a253), TOBN(0xe02b6438, 0x02a21efb), + TOBN(0xa7091b6e, 0xc9430358), TOBN(0x06d1b1fa, 0x9d7db504), + TOBN(0x58846d32, 0xc4744733), TOBN(0x40517c71, 0x379f9e34), + TOBN(0x2f65655f, 0x130ef6ca), TOBN(0x526e4488, 0xf1f3503f), + TOBN(0x8467bd17, 0x7ee4a976), TOBN(0x1d9dc913, 0x921363d1), + TOBN(0xd8d24c33, 0xb069e041), TOBN(0x5eb5da0a, 0x2cdf7f51), + TOBN(0x1c0f3cb1, 0x197b994f), TOBN(0x3c95a6c5, 0x2843eae9), + TOBN(0x7766ffc9, 0xa6097ea5), TOBN(0x7bea4093, 0xd723b867), + TOBN(0xb48e1f73, 0x4db378f9), TOBN(0x70025b00, 0xe37b77ac), + TOBN(0x943dc8e7, 0xaf24ad46), TOBN(0xb98a15ac, 0x16d00a85), + TOBN(0x3adc38ba, 0x2743b004), TOBN(0xb1c7f4f7, 0x334415ee), + TOBN(0xea43df8f, 0x1e62d05a), TOBN(0x32618905, 0x9d76a3b6), + TOBN(0x2fbd0bb5, 0xa23a0f46), TOBN(0x5bc971db, 0x6a01918c), + TOBN(0x7801d94a, 0xb4743f94), TOBN(0xb94df65e, 0x676ae22b), + TOBN(0xaafcbfab, 0xaf95894c), TOBN(0x7b9bdc07, 0x276b2241), + TOBN(0xeaf98362, 0x5bdda48b), TOBN(0x5977faf2, 0xa3fcb4df), + TOBN(0xbed042ef, 0x052c4b5b), TOBN(0x9fe87f71, 0x067591f0), + TOBN(0xc89c73ca, 0x22f24ec7), TOBN(0x7d37fa9e, 0xe64a9f1b), + TOBN(0x2710841a, 0x15562627), TOBN(0x2c01a613, 0xc243b034), + TOBN(0x1d135c56, 0x2bc68609), TOBN(0xc2ca1715, 0x8b03f1f6), + TOBN(0xc9966c2d, 0x3eb81d82), TOBN(0xc02abf4a, 0x8f6df13e), + TOBN(0x77b34bd7, 0x8f72b43b), TOBN(0xaff6218f, 0x360c82b0), + TOBN(0x0aa5726c, 0x8d55b9d2), TOBN(0xdc0adbe9, 0x99e9bffb), + TOBN(0x9097549c, 0xefb9e72a), TOBN(0x16755712, 0x9dfb3111), + TOBN(0xdd8bf984, 0xf26847f9), TOBN(0xbcb8e387, 0xdfb30cb7), + TOBN(0xc1fd32a7, 0x5171ef9c), TOBN(0x977f3fc7, 0x389b363f), + TOBN(0x116eaf2b, 0xf4babda0), TOBN(0xfeab68bd, 0xf7113c8e), + TOBN(0xd1e3f064, 0xb7def526), TOBN(0x1ac30885, 0xe0b3fa02), + TOBN(0x1c5a6e7b, 0x40142d9d), TOBN(0x839b5603, 0x30921c0b), + TOBN(0x48f301fa, 0x36a116a3), TOBN(0x380e1107, 0xcfd9ee6d), + TOBN(0x7945ead8, 0x58854be1), TOBN(0x4111c12e, 0xcbd4d49d), + TOBN(0xece3b1ec, 0x3a29c2ef), TOBN(0x6356d404, 0x8d3616f5), + TOBN(0x9f0d6a8f, 0x594d320e), TOBN(0x0989316d, 0xf651ccd2), + TOBN(0x6c32117a, 0x0f8fdde4), TOBN(0x9abe5cc5, 0xa26a9bbc), + TOBN(0xcff560fb, 0x9723f671), TOBN(0x21b2a12d, 0x7f3d593c), + TOBN(0xe4cb18da, 0x24ba0696), TOBN(0x186e2220, 0xc3543384), + TOBN(0x722f64e0, 0x88312c29), TOBN(0x94282a99, 0x17dc7752), + TOBN(0x62467bbf, 0x5a85ee89), TOBN(0xf435c650, 0xf10076a0), + TOBN(0xc9ff1539, 0x43b3a50b), TOBN(0x7132130c, 0x1a53efbc), + TOBN(0x31bfe063, 0xf7b0c5b7), TOBN(0xb0179a7d, 0x4ea994cc), + TOBN(0x12d064b3, 0xc85f455b), TOBN(0x47259328, 0x8f6e0062), + TOBN(0xf64e590b, 0xb875d6d9), TOBN(0x22dd6225, 0xad92bcc7), + TOBN(0xb658038e, 0xb9c3bd6d), TOBN(0x00cdb0d6, 0xfbba27c8), + TOBN(0x0c681337, 0x1062c45d), TOBN(0xd8515b8c, 0x2d33407d), + TOBN(0xcb8f699e, 0x8cbb5ecf), TOBN(0x8c4347f8, 0xc608d7d8), + TOBN(0x2c11850a, 0xbb3e00db), TOBN(0x20a8dafd, 0xecb49d19), + TOBN(0xbd781480, 0x45ee2f40), TOBN(0x75e354af, 0x416b60cf), + TOBN(0xde0b58a1, 0x8d49a8c4), TOBN(0xe40e94e2, 0xfa359536), + TOBN(0xbd4fa59f, 0x62accd76), TOBN(0x05cf466a, 0x8c762837), + TOBN(0xb5abda99, 0x448c277b), TOBN(0x5a9e01bf, 0x48b13740), + TOBN(0x9d457798, 0x326aad8d), TOBN(0xbdef4954, 0xc396f7e7), + TOBN(0x6fb274a2, 0xc253e292), TOBN(0x2800bf0a, 0x1cfe53e7), + TOBN(0x22426d31, 0x44438fd4), TOBN(0xef233923, 0x5e259f9a), + TOBN(0x4188503c, 0x03f66264), TOBN(0x9e5e7f13, 0x7f9fdfab), + TOBN(0x565eb76c, 0x5fcc1aba), TOBN(0xea632548, 0x59b5bff8), + TOBN(0x5587c087, 0xaab6d3fa), TOBN(0x92b639ea, 0x6ce39c1b), + TOBN(0x0706e782, 0x953b135c), TOBN(0x7308912e, 0x425268ef), + TOBN(0x599e92c7, 0x090e7469), TOBN(0x83b90f52, 0x9bc35e75), + TOBN(0x4750b3d0, 0x244975b3), TOBN(0xf3a44358, 0x11965d72), + TOBN(0x179c6774, 0x9c8dc751), TOBN(0xff18cdfe, 0xd23d9ff0), + TOBN(0xc4013833, 0x2028e247), TOBN(0x96e280e2, 0xf3bfbc79), + TOBN(0xf60417bd, 0xd0880a84), TOBN(0x263c9f3d, 0x2a568151), + TOBN(0x36be15b3, 0x2d2ce811), TOBN(0x846dc0c2, 0xf8291d21), + TOBN(0x5cfa0ecb, 0x789fcfdb), TOBN(0x45a0beed, 0xd7535b9a), + TOBN(0xec8e9f07, 0x96d69af1), TOBN(0x31a7c5b8, 0x599ab6dc), + TOBN(0xd36d45ef, 0xf9e2e09f), TOBN(0x3cf49ef1, 0xdcee954b), + TOBN(0x6be34cf3, 0x086cff9b), TOBN(0x88dbd491, 0x39a3360f), + TOBN(0x1e96b8cc, 0x0dbfbd1d), TOBN(0xc1e5f7bf, 0xcb7e2552), + TOBN(0x0547b214, 0x28819d98), TOBN(0xc770dd9c, 0x7aea9dcb), + TOBN(0xaef0d4c7, 0x041d68c8), TOBN(0xcc2b9818, 0x13cb9ba8), + TOBN(0x7fc7bc76, 0xfe86c607), TOBN(0x6b7b9337, 0x502a9a95), + TOBN(0x1948dc27, 0xd14dab63), TOBN(0x249dd198, 0xdae047be), + TOBN(0xe8356584, 0xa981a202), TOBN(0x3531dd18, 0x3a893387), + TOBN(0x1be11f90, 0xc85c7209), TOBN(0x93d2fe1e, 0xe2a52b5a), + TOBN(0x8225bfe2, 0xec6d6b97), TOBN(0x9cf6d6f4, 0xbd0aa5de), + TOBN(0x911459cb, 0x54779f5f), TOBN(0x5649cddb, 0x86aeb1f3), + TOBN(0x32133579, 0x3f26ce5a), TOBN(0xc289a102, 0x550f431e), + TOBN(0x559dcfda, 0x73b84c6f), TOBN(0x84973819, 0xee3ac4d7), + TOBN(0xb51e55e6, 0xf2606a82), TOBN(0xe25f7061, 0x90f2fb57), + TOBN(0xacef6c2a, 0xb1a4e37c), TOBN(0x864e359d, 0x5dcf2706), + TOBN(0x479e6b18, 0x7ce57316), TOBN(0x2cab2500, 0x3a96b23d), + TOBN(0xed489862, 0x8ef16df7), TOBN(0x2056538c, 0xef3758b5), + TOBN(0xa7df865e, 0xf15d3101), TOBN(0x80c5533a, 0x61b553d7), + TOBN(0x366e1997, 0x4ed14294), TOBN(0x6620741f, 0xb3c0bcd6), + TOBN(0x21d1d9c4, 0xedc45418), TOBN(0x005b859e, 0xc1cc4a9d), + TOBN(0xdf01f630, 0xa1c462f0), TOBN(0x15d06cf3, 0xf26820c7), + TOBN(0x9f7f24ee, 0x3484be47), TOBN(0x2ff33e96, 0x4a0c902f), + TOBN(0x00bdf457, 0x5a0bc453), TOBN(0x2378dfaf, 0x1aa238db), + TOBN(0x272420ec, 0x856720f2), TOBN(0x2ad9d95b, 0x96797291), + TOBN(0xd1242cc6, 0x768a1558), TOBN(0x2e287f8b, 0x5cc86aa8), + TOBN(0x796873d0, 0x990cecaa), TOBN(0xade55f81, 0x675d4080), + TOBN(0x2645eea3, 0x21f0cd84), TOBN(0x7a1efa0f, 0xb4e17d02), + TOBN(0xf6858420, 0x037cc061), TOBN(0x682e05f0, 0xd5d43e12), + TOBN(0x59c36994, 0x27218710), TOBN(0x85cbba4d, 0x3f7cd2fc), + TOBN(0x726f9729, 0x7a3cd22a), TOBN(0x9f8cd5dc, 0x4a628397), + TOBN(0x17b93ab9, 0xc23165ed), TOBN(0xff5f5dbf, 0x122823d4), + TOBN(0xc1e4e4b5, 0x654a446d), TOBN(0xd1a9496f, 0x677257ba), + TOBN(0x6387ba94, 0xde766a56), TOBN(0x23608bc8, 0x521ec74a), + TOBN(0x16a522d7, 0x6688c4d4), TOBN(0x9d6b4282, 0x07373abd), + TOBN(0xa62f07ac, 0xb42efaa3), TOBN(0xf73e00f7, 0xe3b90180), + TOBN(0x36175fec, 0x49421c3e), TOBN(0xc4e44f9b, 0x3dcf2678), + TOBN(0x76df436b, 0x7220f09f), TOBN(0x172755fb, 0x3aa8b6cf), + TOBN(0xbab89d57, 0x446139cc), TOBN(0x0a0a6e02, 0x5fe0208f), + TOBN(0xcdbb63e2, 0x11e5d399), TOBN(0x33ecaa12, 0xa8977f0b), + TOBN(0x59598b21, 0xf7c42664), TOBN(0xb3e91b32, 0xab65d08a), + TOBN(0x035822ee, 0xf4502526), TOBN(0x1dcf0176, 0x720a82a9), + TOBN(0x50f8598f, 0x3d589e02), TOBN(0xdf0478ff, 0xb1d63d2c), + TOBN(0x8b8068bd, 0x1571cd07), TOBN(0x30c3aa4f, 0xd79670cd), + TOBN(0x25e8fd4b, 0x941ade7f), TOBN(0x3d1debdc, 0x32790011), + TOBN(0x65b6dcbd, 0x3a3f9ff0), TOBN(0x282736a4, 0x793de69c), + TOBN(0xef69a0c3, 0xd41d3bd3), TOBN(0xb533b8c9, 0x07a26bde), + TOBN(0xe2801d97, 0xdb2edf9f), TOBN(0xdc4a8269, 0xe1877af0), + TOBN(0x6c1c5851, 0x3d590dbe), TOBN(0x84632f6b, 0xee4e9357), + TOBN(0xd36d36b7, 0x79b33374), TOBN(0xb46833e3, 0x9bbca2e6), + TOBN(0x37893913, 0xf7fc0586), TOBN(0x385315f7, 0x66bf4719), + TOBN(0x72c56293, 0xb31855dc), TOBN(0xd1416d4e, 0x849061fe), + TOBN(0xbeb3ab78, 0x51047213), TOBN(0x447f6e61, 0xf040c996), + TOBN(0xd06d310d, 0x638b1d0c), TOBN(0xe28a413f, 0xbad1522e), + TOBN(0x685a76cb, 0x82003f86), TOBN(0x610d07f7, 0x0bcdbca3), + TOBN(0x6ff66021, 0x9ca4c455), TOBN(0x7df39b87, 0xcea10eec), + TOBN(0xb9255f96, 0xe22db218), TOBN(0x8cc6d9eb, 0x08a34c44), + TOBN(0xcd4ffb86, 0x859f9276), TOBN(0x8fa15eb2, 0x50d07335), + TOBN(0xdf553845, 0xcf2c24b5), TOBN(0x89f66a9f, 0x52f9c3ba), + TOBN(0x8f22b5b9, 0xe4a7ceb3), TOBN(0xaffef809, 0x0e134686), + TOBN(0x3e53e1c6, 0x8eb8fac2), TOBN(0x93c1e4eb, 0x28aec98e), + TOBN(0xb6b91ec5, 0x32a43bcb), TOBN(0x2dbfa947, 0xb2d74a51), + TOBN(0xe065d190, 0xca84bad7), TOBN(0xfb13919f, 0xad58e65c), + TOBN(0x3c41718b, 0xf1cb6e31), TOBN(0x688969f0, 0x06d05c3f), + TOBN(0xd4f94ce7, 0x21264d45), TOBN(0xfdfb65e9, 0x7367532b), + TOBN(0x5b1be8b1, 0x0945a39d), TOBN(0x229f789c, 0x2b8baf3b), + TOBN(0xd8f41f3e, 0x6f49f15d), TOBN(0x678ce828, 0x907f0792), + TOBN(0xc69ace82, 0xfca6e867), TOBN(0x106451ae, 0xd01dcc89), + TOBN(0x1bb4f7f0, 0x19fc32d2), TOBN(0x64633dfc, 0xb00c52d2), + TOBN(0x8f13549a, 0xad9ea445), TOBN(0x99a3bf50, 0xfb323705), + TOBN(0x0c9625a2, 0x534d4dbc), TOBN(0x45b8f1d1, 0xc2a2fea3), + TOBN(0x76ec21a1, 0xa530fc1a), TOBN(0x4bac9c2a, 0x9e5bd734), + TOBN(0x5996d76a, 0x7b4e3587), TOBN(0x0045cdee, 0x1182d9e3), + TOBN(0x1aee24b9, 0x1207f13d), TOBN(0x66452e97, 0x97345a41), + TOBN(0x16e5b054, 0x9f950cd0), TOBN(0x9cc72fb1, 0xd7fdd075), + TOBN(0x6edd61e7, 0x66249663), TOBN(0xde4caa4d, 0xf043cccb), + TOBN(0x11b1f57a, 0x55c7ac17), TOBN(0x779cbd44, 0x1a85e24d), + TOBN(0x78030f86, 0xe46081e7), TOBN(0xfd4a6032, 0x8e20f643), + TOBN(0xcc7a6488, 0x0a750c0f), TOBN(0x39bacfe3, 0x4e548e83), + TOBN(0x3d418c76, 0x0c110f05), TOBN(0x3e4daa4c, 0xb1f11588), + TOBN(0x2733e7b5, 0x5ffc69ff), TOBN(0x46f147bc, 0x92053127), + TOBN(0x885b2434, 0xd722df94), TOBN(0x6a444f65, 0xe6fc6b7c)} + , + {TOBN(0x7a1a465a, 0xc3f16ea8), TOBN(0x115a461d, 0xb2f1d11c), + TOBN(0x4767dd95, 0x6c68a172), TOBN(0x3392f2eb, 0xd13a4698), + TOBN(0xc7a99ccd, 0xe526cdc7), TOBN(0x8e537fdc, 0x22292b81), + TOBN(0x76d8cf69, 0xa6d39198), TOBN(0xffc5ff43, 0x2446852d), + TOBN(0x97b14f7e, 0xa90567e6), TOBN(0x513257b7, 0xb6ae5cb7), + TOBN(0x85454a3c, 0x9f10903d), TOBN(0xd8d2c9ad, 0x69bc3724), + TOBN(0x38da9324, 0x6b29cb44), TOBN(0xb540a21d, 0x77c8cbac), + TOBN(0x9bbfe435, 0x01918e42), TOBN(0xfffa707a, 0x56c3614e), + TOBN(0x0ce4e3f1, 0xd4e353b7), TOBN(0x062d8a14, 0xef46b0a0), + TOBN(0x6408d5ab, 0x574b73fd), TOBN(0xbc41d1c9, 0xd3273ffd), + TOBN(0x3538e1e7, 0x6be77800), TOBN(0x71fe8b37, 0xc5655031), + TOBN(0x1cd91621, 0x6b9b331a), TOBN(0xad825d0b, 0xbb388f73), + TOBN(0x56c2e05b, 0x1cb76219), TOBN(0x0ec0bf91, 0x71567e7e), + TOBN(0xe7076f86, 0x61c4c910), TOBN(0xd67b085b, 0xbabc04d9), + TOBN(0x9fb90459, 0x5e93a96a), TOBN(0x7526c1ea, 0xfbdc249a), + TOBN(0x0d44d367, 0xecdd0bb7), TOBN(0x95399917, 0x9dc0d695), + TOBN(0x61360ee9, 0x9e240d18), TOBN(0x057cdcac, 0xb4b94466), + TOBN(0xe7667cd1, 0x2fe5325c), TOBN(0x1fa297b5, 0x21974e3b), + TOBN(0xfa4081e7, 0xdb083d76), TOBN(0x31993be6, 0xf206bd15), + TOBN(0x8949269b, 0x14c19f8c), TOBN(0x21468d72, 0xa9d92357), + TOBN(0x2ccbc583, 0xa4c506ec), TOBN(0x957ed188, 0xd1acfe97), + TOBN(0x8baed833, 0x12f1aea2), TOBN(0xef2a6cb4, 0x8325362d), + TOBN(0x130dde42, 0x8e195c43), TOBN(0xc842025a, 0x0e6050c6), + TOBN(0x2da972a7, 0x08686a5d), TOBN(0xb52999a1, 0xe508b4a8), + TOBN(0xd9f090b9, 0x10a5a8bd), TOBN(0xca91d249, 0x096864da), + TOBN(0x8e6a93be, 0x3f67dbc1), TOBN(0xacae6fba, 0xf5f4764c), + TOBN(0x1563c6e0, 0xd21411a0), TOBN(0x28fa787f, 0xda0a4ad8), + TOBN(0xd524491c, 0x908c8030), TOBN(0x1257ba0e, 0x4c795f07), + TOBN(0x83f49167, 0xceca9754), TOBN(0x426d2cf6, 0x4b7939a0), + TOBN(0x2555e355, 0x723fd0bf), TOBN(0xa96e6d06, 0xc4f144e2), + TOBN(0x4768a8dd, 0x87880e61), TOBN(0x15543815, 0xe508e4d5), + TOBN(0x09d7e772, 0xb1b65e15), TOBN(0x63439dd6, 0xac302fa0), + TOBN(0xb93f802f, 0xc14e35c2), TOBN(0x71735b7c, 0x4341333c), + TOBN(0x03a25104, 0x16d4f362), TOBN(0x3f4d069b, 0xbf433c8e), + TOBN(0x0d83ae01, 0xf78f5a7c), TOBN(0x50a8ffbe, 0x7c4eed07), + TOBN(0xc74f8906, 0x76e10f83), TOBN(0x7d080966, 0x9ddaf8e1), + TOBN(0xb11df8e1, 0x698e04cc), TOBN(0x877be203, 0x169005c8), + TOBN(0x32749e8c, 0x4f3c6179), TOBN(0x2dbc9d0a, 0x7853fc05), + TOBN(0x187d4f93, 0x9454d937), TOBN(0xe682ce9d, 0xb4800e1b), + TOBN(0xa9129ad8, 0x165e68e8), TOBN(0x0fe29735, 0xbe7f785b), + TOBN(0x5303f40c, 0x5b9e02b7), TOBN(0xa37c9692, 0x35ee04e8), + TOBN(0x5f46cc20, 0x34d6632b), TOBN(0x55ef72b2, 0x96ac545b), + TOBN(0xabec5c1f, 0x7b91b062), TOBN(0x0a79e1c7, 0xbb33e821), + TOBN(0xbb04b428, 0x3a9f4117), TOBN(0x0de1f28f, 0xfd2a475a), + TOBN(0x31019ccf, 0x3a4434b4), TOBN(0xa3458111, 0x1a7954dc), + TOBN(0xa9dac80d, 0xe34972a7), TOBN(0xb043d054, 0x74f6b8dd), + TOBN(0x021c319e, 0x11137b1a), TOBN(0x00a754ce, 0xed5cc03f), + TOBN(0x0aa2c794, 0xcbea5ad4), TOBN(0x093e67f4, 0x70c015b6), + TOBN(0x72cdfee9, 0xc97e3f6b), TOBN(0xc10bcab4, 0xb6da7461), + TOBN(0x3b02d2fc, 0xb59806b9), TOBN(0x85185e89, 0xa1de6f47), + TOBN(0x39e6931f, 0x0eb6c4d4), TOBN(0x4d4440bd, 0xd4fa5b04), + TOBN(0x5418786e, 0x34be7eb8), TOBN(0x6380e521, 0x9d7259bc), + TOBN(0x20ac0351, 0xd598d710), TOBN(0x272c4166, 0xcb3a4da4), + TOBN(0xdb82fe1a, 0xca71de1f), TOBN(0x746e79f2, 0xd8f54b0f), + TOBN(0x6e7fc736, 0x4b573e9b), TOBN(0x75d03f46, 0xfd4b5040), + TOBN(0x5c1cc36d, 0x0b98d87b), TOBN(0x513ba3f1, 0x1f472da1), + TOBN(0x79d0af26, 0xabb177dd), TOBN(0xf82ab568, 0x7891d564), + TOBN(0x2b6768a9, 0x72232173), TOBN(0xefbb3bb0, 0x8c1f6619), + TOBN(0xb29c11db, 0xa6d18358), TOBN(0x519e2797, 0xb0916d3a), + TOBN(0xd4dc18f0, 0x9188e290), TOBN(0x648e86e3, 0x98b0ca7f), + TOBN(0x859d3145, 0x983c38b5), TOBN(0xb14f176c, 0x637abc8b), + TOBN(0x2793fb9d, 0xcaff7be6), TOBN(0xebe5a55f, 0x35a66a5a), + TOBN(0x7cec1dcd, 0x9f87dc59), TOBN(0x7c595cd3, 0xfbdbf560), + TOBN(0x5b543b22, 0x26eb3257), TOBN(0x69080646, 0xc4c935fd), + TOBN(0x7f2e4403, 0x81e9ede3), TOBN(0x243c3894, 0xcaf6df0a), + TOBN(0x7c605bb1, 0x1c073b11), TOBN(0xcd06a541, 0xba6a4a62), + TOBN(0x29168949, 0x49d4e2e5), TOBN(0x33649d07, 0x4af66880), + TOBN(0xbfc0c885, 0xe9a85035), TOBN(0xb4e52113, 0xfc410f4b), + TOBN(0xdca3b706, 0x78a6513b), TOBN(0x92ea4a2a, 0x9edb1943), + TOBN(0x02642216, 0xdb6e2dd8), TOBN(0x9b45d0b4, 0x9fd57894), + TOBN(0x114e70db, 0xc69d11ae), TOBN(0x1477dd19, 0x4c57595f), + TOBN(0xbc2208b4, 0xec77c272), TOBN(0x95c5b4d7, 0xdb68f59c), + TOBN(0xb8c4fc63, 0x42e532b7), TOBN(0x386ba422, 0x9ae35290), + TOBN(0xfb5dda42, 0xd201ecbc), TOBN(0x2353dc8b, 0xa0e38fd6), + TOBN(0x9a0b85ea, 0x68f7e978), TOBN(0x96ec5682, 0x2ad6d11f), + TOBN(0x5e279d6c, 0xe5f6886d), TOBN(0xd3fe03cd, 0x3cb1914d), + TOBN(0xfe541fa4, 0x7ea67c77), TOBN(0x952bd2af, 0xe3ea810c), + TOBN(0x791fef56, 0x8d01d374), TOBN(0xa3a1c621, 0x0f11336e), + TOBN(0x5ad0d5a9, 0xc7ec6d79), TOBN(0xff7038af, 0x3225c342), + TOBN(0x003c6689, 0xbc69601b), TOBN(0x25059bc7, 0x45e8747d), + TOBN(0xfa4965b2, 0xf2086fbf), TOBN(0xf6840ea6, 0x86916078), + TOBN(0xd7ac7620, 0x70081d6c), TOBN(0xe600da31, 0xb5328645), + TOBN(0x01916f63, 0x529b8a80), TOBN(0xe80e4858, 0x2d7d6f3e), + TOBN(0x29eb0fe8, 0xd664ca7c), TOBN(0xf017637b, 0xe7b43b0c), + TOBN(0x9a75c806, 0x76cb2566), TOBN(0x8f76acb1, 0xb24892d9), + TOBN(0x7ae7b9cc, 0x1f08fe45), TOBN(0x19ef7329, 0x6a4907d8), + TOBN(0x2db4ab71, 0x5f228bf0), TOBN(0xf3cdea39, 0x817032d7), + TOBN(0x0b1f482e, 0xdcabe3c0), TOBN(0x3baf76b4, 0xbb86325c), + TOBN(0xd49065e0, 0x10089465), TOBN(0x3bab5d29, 0x8e77c596), + TOBN(0x7636c3a6, 0x193dbd95), TOBN(0xdef5d294, 0xb246e499), + TOBN(0xb22c58b9, 0x286b2475), TOBN(0xa0b93939, 0xcd80862b), + TOBN(0x3002c83a, 0xf0992388), TOBN(0x6de01f9b, 0xeacbe14c), + TOBN(0x6aac688e, 0xadd70482), TOBN(0x708de92a, 0x7b4a4e8a), + TOBN(0x75b6dd73, 0x758a6eef), TOBN(0xea4bf352, 0x725b3c43), + TOBN(0x10041f2c, 0x87912868), TOBN(0xb1b1be95, 0xef09297a), + TOBN(0x19ae23c5, 0xa9f3860a), TOBN(0xc4f0f839, 0x515dcf4b), + TOBN(0x3c7ecca3, 0x97f6306a), TOBN(0x744c44ae, 0x68a3a4b0), + TOBN(0x69cd13a0, 0xb3a1d8a2), TOBN(0x7cad0a1e, 0x5256b578), + TOBN(0xea653fcd, 0x33791d9e), TOBN(0x9cc2a05d, 0x74b2e05f), + TOBN(0x73b391dc, 0xfd7affa2), TOBN(0xddb7091e, 0xb6b05442), + TOBN(0xc71e27bf, 0x8538a5c6), TOBN(0x195c63dd, 0x89abff17), + TOBN(0xfd315285, 0x1b71e3da), TOBN(0x9cbdfda7, 0xfa680fa0), + TOBN(0x9db876ca, 0x849d7eab), TOBN(0xebe2764b, 0x3c273271), + TOBN(0x663357e3, 0xf208dcea), TOBN(0x8c5bd833, 0x565b1b70), + TOBN(0xccc3b4f5, 0x9837fc0d), TOBN(0x9b641ba8, 0xa79cf00f), + TOBN(0x7428243d, 0xdfdf3990), TOBN(0x83a594c4, 0x020786b1), + TOBN(0xb712451a, 0x526c4502), TOBN(0x9d39438e, 0x6adb3f93), + TOBN(0xfdb261e3, 0xe9ff0ccd), TOBN(0x80344e3c, 0xe07af4c3), + TOBN(0x75900d7c, 0x2fa4f126), TOBN(0x08a3b865, 0x5c99a232), + TOBN(0x2478b6bf, 0xdb25e0c3), TOBN(0x482cc2c2, 0x71db2edf), + TOBN(0x37df7e64, 0x5f321bb8), TOBN(0x8a93821b, 0x9a8005b4), + TOBN(0x3fa2f10c, 0xcc8c1958), TOBN(0x0d332218, 0x2c269d0a), + TOBN(0x20ab8119, 0xe246b0e6), TOBN(0xb39781e4, 0xd349fd17), + TOBN(0xd293231e, 0xb31aa100), TOBN(0x4b779c97, 0xbb032168), + TOBN(0x4b3f19e1, 0xc8470500), TOBN(0x45b7efe9, 0x0c4c869d), + TOBN(0xdb84f38a, 0xa1a6bbcc), TOBN(0x3b59cb15, 0xb2fddbc1), + TOBN(0xba5514df, 0x3fd165e8), TOBN(0x499fd6a9, 0x061f8811), + TOBN(0x72cd1fe0, 0xbfef9f00), TOBN(0x120a4bb9, 0x79ad7e8a), + TOBN(0xf2ffd095, 0x5f4a5ac5), TOBN(0xcfd174f1, 0x95a7a2f0), + TOBN(0xd42301ba, 0x9d17baf1), TOBN(0xd2fa487a, 0x77f22089), + TOBN(0x9cb09efe, 0xb1dc77e1), TOBN(0xe9566939, 0x21c99682), + TOBN(0x8c546901, 0x6c6067bb), TOBN(0xfd378574, 0x61c24456), + TOBN(0x2b6a6cbe, 0x81796b33), TOBN(0x62d550f6, 0x58e87f8b), + TOBN(0x1b763e1c, 0x7f1b01b4), TOBN(0x4b93cfea, 0x1b1b5e12), + TOBN(0xb9345238, 0x1d531696), TOBN(0x57201c00, 0x88cdde69), + TOBN(0xdde92251, 0x9a86afc7), TOBN(0xe3043895, 0xbd35cea8), + TOBN(0x7608c1e1, 0x8555970d), TOBN(0x8267dfa9, 0x2535935e), + TOBN(0xd4c60a57, 0x322ea38b), TOBN(0xe0bf7977, 0x804ef8b5), + TOBN(0x1a0dab28, 0xc06fece4), TOBN(0xd405991e, 0x94e7b49d), + TOBN(0xc542b6d2, 0x706dab28), TOBN(0xcb228da3, 0xa91618fb), + TOBN(0x224e4164, 0x107d1cea), TOBN(0xeb9fdab3, 0xd0f5d8f1), + TOBN(0xc02ba386, 0x0d6e41cd), TOBN(0x676a72c5, 0x9b1f7146), + TOBN(0xffd6dd98, 0x4d6cb00b), TOBN(0xcef9c5ca, 0xde2e8d7c), + TOBN(0xa1bbf5d7, 0x641c7936), TOBN(0x1b95b230, 0xee8f772e), + TOBN(0xf765a92e, 0xe8ac25b1), TOBN(0xceb04cfc, 0x3a18b7c6), + TOBN(0x27944cef, 0x0acc8966), TOBN(0xcbb3c957, 0x434c1004), + TOBN(0x9c9971a1, 0xa43ff93c), TOBN(0x5bc2db17, 0xa1e358a9), + TOBN(0x45b4862e, 0xa8d9bc82), TOBN(0x70ebfbfb, 0x2201e052), + TOBN(0xafdf64c7, 0x92871591), TOBN(0xea5bcae6, 0xb42d0219), + TOBN(0xde536c55, 0x2ad8f03c), TOBN(0xcd6c3f4d, 0xa76aa33c), + TOBN(0xbeb5f623, 0x0bca6de3), TOBN(0xdd20dd99, 0xb1e706fd), + TOBN(0x90b3ff9d, 0xac9059d4), TOBN(0x2d7b2902, 0x7ccccc4e), + TOBN(0x8a090a59, 0xce98840f), TOBN(0xa5d947e0, 0x8410680a), + TOBN(0x49ae346a, 0x923379a5), TOBN(0x7dbc84f9, 0xb28a3156), + TOBN(0xfd40d916, 0x54a1aff2), TOBN(0xabf318ba, 0x3a78fb9b), + TOBN(0x50152ed8, 0x3029f95e), TOBN(0x9fc1dd77, 0xc58ad7fa), + TOBN(0x5fa57915, 0x13595c17), TOBN(0xb9504668, 0x8f62b3a9), + TOBN(0x907b5b24, 0xff3055b0), TOBN(0x2e995e35, 0x9a84f125), + TOBN(0x87dacf69, 0x7e9bbcfb), TOBN(0x95d0c1d6, 0xe86d96e3), + TOBN(0x65726e3c, 0x2d95a75c), TOBN(0x2c3c9001, 0xacd27f21), + TOBN(0x1deab561, 0x6c973f57), TOBN(0x108b7e2c, 0xa5221643), + TOBN(0x5fee9859, 0xc4ef79d4), TOBN(0xbd62b88a, 0x40d4b8c6), + TOBN(0xb4dd29c4, 0x197c75d6), TOBN(0x266a6df2, 0xb7076feb), + TOBN(0x9512d0ea, 0x4bf2df11), TOBN(0x1320c24f, 0x6b0cc9ec), + TOBN(0x6bb1e0e1, 0x01a59596), TOBN(0x8317c5bb, 0xeff9aaac), + TOBN(0x65bb405e, 0x385aa6c9), TOBN(0x613439c1, 0x8f07988f), + TOBN(0xd730049f, 0x16a66e91), TOBN(0xe97f2820, 0xfa1b0e0d), + TOBN(0x4131e003, 0x304c28ea), TOBN(0x820ab732, 0x526bac62), + TOBN(0xb2ac9ef9, 0x28714423), TOBN(0x54ecfffa, 0xadb10cb2), + TOBN(0x8781476e, 0xf886a4cc), TOBN(0x4b2c87b5, 0xdb2f8d49), + TOBN(0xe857cd20, 0x0a44295d), TOBN(0x707d7d21, 0x58c6b044), + TOBN(0xae8521f9, 0xf596757c), TOBN(0x87448f03, 0x67b2b714), + TOBN(0x13a9bc45, 0x5ebcd58d), TOBN(0x79bcced9, 0x9122d3c1), + TOBN(0x3c644247, 0x9e076642), TOBN(0x0cf22778, 0x2df4767d), + TOBN(0x5e61aee4, 0x71d444b6), TOBN(0x211236bf, 0xc5084a1d), + TOBN(0x7e15bc9a, 0x4fd3eaf6), TOBN(0x68df2c34, 0xab622bf5), + TOBN(0x9e674f0f, 0x59bf4f36), TOBN(0xf883669b, 0xd7f34d73), + TOBN(0xc48ac1b8, 0x31497b1d), TOBN(0x323b925d, 0x5106703b), + TOBN(0x22156f42, 0x74082008), TOBN(0xeffc521a, 0xc8482bcb), + TOBN(0x5c6831bf, 0x12173479), TOBN(0xcaa2528f, 0xc4739490), + TOBN(0x84d2102a, 0x8f1b3c4d), TOBN(0xcf64dfc1, 0x2d9bec0d), + TOBN(0x433febad, 0x78a546ef), TOBN(0x1f621ec3, 0x7b73cef1), + TOBN(0x6aecd627, 0x37338615), TOBN(0x162082ab, 0x01d8edf6), + TOBN(0x833a8119, 0x19e86b66), TOBN(0x6023a251, 0xd299b5db), + TOBN(0xf5bb0c3a, 0xbbf04b89), TOBN(0x6735eb69, 0xae749a44), + TOBN(0xd0e058c5, 0x4713de3b), TOBN(0xfdf2593e, 0x2c3d4ccd), + TOBN(0x1b8f414e, 0xfdd23667), TOBN(0xdd52aaca, 0xfa2015ee), + TOBN(0x3e31b517, 0xbd9625ff), TOBN(0x5ec9322d, 0x8db5918c), + TOBN(0xbc73ac85, 0xa96f5294), TOBN(0x82aa5bf3, 0x61a0666a), + TOBN(0x49755810, 0xbf08ac42), TOBN(0xd21cdfd5, 0x891cedfc), + TOBN(0x918cb57b, 0x67f8be10), TOBN(0x365d1a7c, 0x56ffa726), + TOBN(0x2435c504, 0x6532de93), TOBN(0xc0fc5e10, 0x2674cd02), + TOBN(0x6e51fcf8, 0x9cbbb142), TOBN(0x1d436e5a, 0xafc50692), + TOBN(0x766bffff, 0x3fbcae22), TOBN(0x3148c2fd, 0xfd55d3b8), + TOBN(0x52c7fdc9, 0x233222fa), TOBN(0x89ff1092, 0xe419fb6b), + TOBN(0x3cd6db99, 0x25254977), TOBN(0x2e85a161, 0x1cf12ca7), + TOBN(0xadd2547c, 0xdc810bc9), TOBN(0xea3f458f, 0x9d257c22), + TOBN(0x642c1fbe, 0x27d6b19b), TOBN(0xed07e6b5, 0x140481a6), + TOBN(0x6ada1d42, 0x86d2e0f8), TOBN(0xe5920122, 0x0e8a9fd5), + TOBN(0x02c936af, 0x708c1b49), TOBN(0x60f30fee, 0x2b4bfaff), + TOBN(0x6637ad06, 0x858e6a61), TOBN(0xce4c7767, 0x3fd374d0), + TOBN(0x39d54b2d, 0x7188defb), TOBN(0xa8c9d250, 0xf56a6b66), + TOBN(0x58fc0f5e, 0xb24fe1dc), TOBN(0x9eaf9dee, 0x6b73f24c), + TOBN(0xa90d588b, 0x33650705), TOBN(0xde5b62c5, 0xaf2ec729), + TOBN(0x5c72cfae, 0xd3c2b36e), TOBN(0x868c19d5, 0x034435da), + TOBN(0x88605f93, 0xe17ee145), TOBN(0xaa60c4ee, 0x77a5d5b1), + TOBN(0xbcf5bfd2, 0x3b60c472), TOBN(0xaf4ef13c, 0xeb1d3049), + TOBN(0x373f44fc, 0xe13895c9), TOBN(0xf29b382f, 0x0cbc9822), + TOBN(0x1bfcb853, 0x73efaef6), TOBN(0xcf56ac9c, 0xa8c96f40), + TOBN(0xd7adf109, 0x7a191e24), TOBN(0x98035f44, 0xbf8a8dc2), + TOBN(0xf40a71b9, 0x1e750c84), TOBN(0xc57f7b0c, 0x5dc6c469), + TOBN(0x49a0e79c, 0x6fbc19c1), TOBN(0x6b0f5889, 0xa48ebdb8), + TOBN(0x5d3fd084, 0xa07c4e9f), TOBN(0xc3830111, 0xab27de14), + TOBN(0x0e4929fe, 0x33e08dcc), TOBN(0xf4a5ad24, 0x40bb73a3), + TOBN(0xde86c2bf, 0x490f97ca), TOBN(0x288f09c6, 0x67a1ce18), + TOBN(0x364bb886, 0x1844478d), TOBN(0x7840fa42, 0xceedb040), + TOBN(0x1269fdd2, 0x5a631b37), TOBN(0x94761f1e, 0xa47c8b7d), + TOBN(0xfc0c2e17, 0x481c6266), TOBN(0x85e16ea2, 0x3daa5fa7), + TOBN(0xccd86033, 0x92491048), TOBN(0x0c2f6963, 0xf4d402d7), + TOBN(0x6336f7df, 0xdf6a865c), TOBN(0x0a2a463c, 0xb5c02a87), + TOBN(0xb0e29be7, 0xbf2f12ee), TOBN(0xf0a22002, 0x66bad988), + TOBN(0x27f87e03, 0x9123c1d7), TOBN(0x21669c55, 0x328a8c98), + TOBN(0x186b9803, 0x92f14529), TOBN(0xd3d056cc, 0x63954df3), + TOBN(0x2f03fd58, 0x175a46f6), TOBN(0x63e34ebe, 0x11558558), + TOBN(0xe13fedee, 0x5b80cfa5), TOBN(0xe872a120, 0xd401dbd1), + TOBN(0x52657616, 0xe8a9d667), TOBN(0xbc8da4b6, 0xe08d6693), + TOBN(0x370fb9bb, 0x1b703e75), TOBN(0x6773b186, 0xd4338363), + TOBN(0x18dad378, 0xecef7bff), TOBN(0xaac787ed, 0x995677da), + TOBN(0x4801ea8b, 0x0437164b), TOBN(0xf430ad20, 0x73fe795e), + TOBN(0xb164154d, 0x8ee5eb73), TOBN(0x0884ecd8, 0x108f7c0e), + TOBN(0x0e6ec096, 0x5f520698), TOBN(0x640631fe, 0x44f7b8d9), + TOBN(0x92fd34fc, 0xa35a68b9), TOBN(0x9c5a4b66, 0x4d40cf4e), + TOBN(0x949454bf, 0x80b6783d), TOBN(0x80e701fe, 0x3a320a10), + TOBN(0x8d1a564a, 0x1a0a39b2), TOBN(0x1436d53d, 0x320587db), + TOBN(0xf5096e6d, 0x6556c362), TOBN(0xbc23a3c0, 0xe2455d7e), + TOBN(0x3a7aee54, 0x807230f9), TOBN(0x9ba1cfa6, 0x22ae82fd), + TOBN(0x833a057a, 0x99c5d706), TOBN(0x8be85f4b, 0x842315c9), + TOBN(0xd083179a, 0x66a72f12), TOBN(0x2fc77d5d, 0xcdcc73cd), + TOBN(0x22b88a80, 0x5616ee30), TOBN(0xfb09548f, 0xe7ab1083), + TOBN(0x8ad6ab0d, 0x511270cd), TOBN(0x61f6c57a, 0x6924d9ab), + TOBN(0xa0f7bf72, 0x90aecb08), TOBN(0x849f87c9, 0x0df784a4), + TOBN(0x27c79c15, 0xcfaf1d03), TOBN(0xbbf9f675, 0xc463face), + TOBN(0x91502c65, 0x765ba543), TOBN(0x18ce3cac, 0x42ea60dd), + TOBN(0xe5cee6ac, 0x6e43ecb3), TOBN(0x63e4e910, 0x68f2aeeb), + TOBN(0x26234fa3, 0xc85932ee), TOBN(0x96883e8b, 0x4c90c44d), + TOBN(0x29b9e738, 0xa18a50f6), TOBN(0xbfc62b2a, 0x3f0420df), + TOBN(0xd22a7d90, 0x6d3e1fa9), TOBN(0x17115618, 0xfe05b8a3), + TOBN(0x2a0c9926, 0xbb2b9c01), TOBN(0xc739fcc6, 0xe07e76a2), + TOBN(0x540e9157, 0x165e439a), TOBN(0x06353a62, 0x6a9063d8), + TOBN(0x84d95594, 0x61e927a3), TOBN(0x013b9b26, 0xe2e0be7f), + TOBN(0x4feaec3b, 0x973497f1), TOBN(0x15c0f94e, 0x093ebc2d), + TOBN(0x6af5f227, 0x33af0583), TOBN(0x0c2af206, 0xc61f3340), + TOBN(0xd25dbdf1, 0x4457397c), TOBN(0x2e8ed017, 0xcabcbae0), + TOBN(0xe3010938, 0xc2815306), TOBN(0xbaa99337, 0xe8c6cd68), + TOBN(0x08513182, 0x3b0ec7de), TOBN(0x1e1b822b, 0x58df05df), + TOBN(0x5c14842f, 0xa5c3b683), TOBN(0x98fe977e, 0x3eba34ce), + TOBN(0xfd2316c2, 0x0d5e8873), TOBN(0xe48d839a, 0xbd0d427d), + TOBN(0x495b2218, 0x623fc961), TOBN(0x24ee56e7, 0xb46fba5e), + TOBN(0x9184a55b, 0x91e4de58), TOBN(0xa7488ca5, 0xdfdea288), + TOBN(0xa723862e, 0xa8dcc943), TOBN(0x92d762b2, 0x849dc0fc), + TOBN(0x3c444a12, 0x091ff4a9), TOBN(0x581113fa, 0x0cada274), + TOBN(0xb9de0a45, 0x30d8eae2), TOBN(0x5e0fcd85, 0xdf6b41ea), + TOBN(0x6233ea68, 0xc094dbb5), TOBN(0xb77d062e, 0xd968d410), + TOBN(0x3e719bbc, 0x58b3002d), TOBN(0x68e7dd3d, 0x3dc49d58), + TOBN(0x8d825740, 0x013a5e58), TOBN(0x21311747, 0x3c9e3c1b), + TOBN(0x0cb0a2a7, 0x7c99b6ab), TOBN(0x5c48a3b3, 0xc2f888f2)} + , + {TOBN(0xc7913e91, 0x991724f3), TOBN(0x5eda799c, 0x39cbd686), + TOBN(0xddb595c7, 0x63d4fc1e), TOBN(0x6b63b80b, 0xac4fed54), + TOBN(0x6ea0fc69, 0x7e5fb516), TOBN(0x737708ba, 0xd0f1c964), + TOBN(0x9628745f, 0x11a92ca5), TOBN(0x61f37958, 0x9a86967a), + TOBN(0x9af39b2c, 0xaa665072), TOBN(0x78322fa4, 0xefd324ef), + TOBN(0x3d153394, 0xc327bd31), TOBN(0x81d5f271, 0x3129dab0), + TOBN(0xc72e0c42, 0xf48027f5), TOBN(0xaa40cdbc, 0x8536e717), + TOBN(0xf45a657a, 0x2d369d0f), TOBN(0xb03bbfc4, 0xea7f74e6), + TOBN(0x46a8c418, 0x0d738ded), TOBN(0x6f1a5bb0, 0xe0de5729), + TOBN(0xf10230b9, 0x8ba81675), TOBN(0x32c6f30c, 0x112b33d4), + TOBN(0x7559129d, 0xd8fffb62), TOBN(0x6a281b47, 0xb459bf05), + TOBN(0x77c1bd3a, 0xfa3b6776), TOBN(0x0709b380, 0x7829973a), + TOBN(0x8c26b232, 0xa3326505), TOBN(0x38d69272, 0xee1d41bf), + TOBN(0x0459453e, 0xffe32afa), TOBN(0xce8143ad, 0x7cb3ea87), + TOBN(0x932ec1fa, 0x7e6ab666), TOBN(0x6cd2d230, 0x22286264), + TOBN(0x459a46fe, 0x6736f8ed), TOBN(0x50bf0d00, 0x9eca85bb), + TOBN(0x0b825852, 0x877a21ec), TOBN(0x300414a7, 0x0f537a94), + TOBN(0x3f1cba40, 0x21a9a6a2), TOBN(0x50824eee, 0x76943c00), + TOBN(0xa0dbfcec, 0xf83cba5d), TOBN(0xf9538148, 0x93b4f3c0), + TOBN(0x61744162, 0x48f24dd7), TOBN(0x5322d64d, 0xe4fb09dd), + TOBN(0x57447384, 0x3d9325f3), TOBN(0xa9bef2d0, 0xf371cb84), + TOBN(0x77d2188b, 0xa61e36c5), TOBN(0xbbd6a7d7, 0xc602df72), + TOBN(0xba3aa902, 0x8f61bc0b), TOBN(0xf49085ed, 0x6ed0b6a1), + TOBN(0x8bc625d6, 0xae6e8298), TOBN(0x832b0b1d, 0xa2e9c01d), + TOBN(0xa337c447, 0xf1f0ced1), TOBN(0x800cc793, 0x9492dd2b), + TOBN(0x4b93151d, 0xbea08efa), TOBN(0x820cf3f8, 0xde0a741e), + TOBN(0xff1982dc, 0x1c0f7d13), TOBN(0xef921960, 0x84dde6ca), + TOBN(0x1ad7d972, 0x45f96ee3), TOBN(0x319c8dbe, 0x29dea0c7), + TOBN(0xd3ea3871, 0x7b82b99b), TOBN(0x75922d4d, 0x470eb624), + TOBN(0x8f66ec54, 0x3b95d466), TOBN(0x66e673cc, 0xbee1e346), + TOBN(0x6afe67c4, 0xb5f2b89a), TOBN(0x3de9c1e6, 0x290e5cd3), + TOBN(0x8c278bb6, 0x310a2ada), TOBN(0x420fa384, 0x0bdb323b), + TOBN(0x0ae1d63b, 0x0eb919b0), TOBN(0xd74ee51d, 0xa74b9620), + TOBN(0x395458d0, 0xa674290c), TOBN(0x324c930f, 0x4620a510), + TOBN(0x2d1f4d19, 0xfbac27d4), TOBN(0x4086e8ca, 0x9bedeeac), + TOBN(0x0cdd211b, 0x9b679ab8), TOBN(0x5970167d, 0x7090fec4), + TOBN(0x3420f2c9, 0xfaf1fc63), TOBN(0x616d333a, 0x328c8bb4), + TOBN(0x7d65364c, 0x57f1fe4a), TOBN(0x9343e877, 0x55e5c73a), + TOBN(0x5795176b, 0xe970e78c), TOBN(0xa36ccebf, 0x60533627), + TOBN(0xfc7c7380, 0x09cdfc1b), TOBN(0xb39a2afe, 0xb3fec326), + TOBN(0xb7ff1ba1, 0x6224408a), TOBN(0xcc856e92, 0x247cfc5e), + TOBN(0x01f102e7, 0xc18bc493), TOBN(0x4613ab74, 0x2091c727), + TOBN(0xaa25e89c, 0xc420bf2b), TOBN(0x00a53176, 0x90337ec2), + TOBN(0xd2be9f43, 0x7d025fc7), TOBN(0x3316fb85, 0x6e6fe3dc), + TOBN(0x27520af5, 0x9ac50814), TOBN(0xfdf95e78, 0x9a8e4223), + TOBN(0xb7e7df2a, 0x56bec5a0), TOBN(0xf7022f7d, 0xdf159e5d), + TOBN(0x93eeeab1, 0xcac1fe8f), TOBN(0x8040188c, 0x37451168), + TOBN(0x7ee8aa8a, 0xd967dce6), TOBN(0xfa0e79e7, 0x3abc9299), + TOBN(0x67332cfc, 0x2064cfd1), TOBN(0x339c31de, 0xb0651934), + TOBN(0x719b28d5, 0x2a3bcbea), TOBN(0xee74c82b, 0x9d6ae5c6), + TOBN(0x0927d05e, 0xbaf28ee6), TOBN(0x82cecf2c, 0x9d719028), + TOBN(0x0b0d353e, 0xddb30289), TOBN(0xfe4bb977, 0xfddb2e29), + TOBN(0xbb5bb990, 0x640bfd9e), TOBN(0xd226e277, 0x82f62108), + TOBN(0x4bf00985, 0x02ffdd56), TOBN(0x7756758a, 0x2ca1b1b5), + TOBN(0xc32b62a3, 0x5285fe91), TOBN(0xedbc546a, 0x8c9cd140), + TOBN(0x1e47a013, 0xaf5cb008), TOBN(0xbca7e720, 0x073ce8f2), + TOBN(0xe10b2ab8, 0x17a91cae), TOBN(0xb89aab65, 0x08e27f63), + TOBN(0x7b3074a7, 0xdba3ddf9), TOBN(0x1c20ce09, 0x330c2972), + TOBN(0x6b9917b4, 0x5fcf7e33), TOBN(0xe6793743, 0x945ceb42), + TOBN(0x18fc2215, 0x5c633d19), TOBN(0xad1adb3c, 0xc7485474), + TOBN(0x646f9679, 0x6424c49b), TOBN(0xf888dfe8, 0x67c241c9), + TOBN(0xe12d4b93, 0x24f68b49), TOBN(0x9a6b62d8, 0xa571df20), + TOBN(0x81b4b26d, 0x179483cb), TOBN(0x666f9632, 0x9511fae2), + TOBN(0xd281b3e4, 0xd53aa51f), TOBN(0x7f96a765, 0x7f3dbd16), + TOBN(0xa7f8b5bf, 0x074a30ce), TOBN(0xd7f52107, 0x005a32e6), + TOBN(0x6f9e0907, 0x50237ed4), TOBN(0x2f21da47, 0x8096fa2b), + TOBN(0xf3e19cb4, 0xeec863a0), TOBN(0xd18f77fd, 0x9527620a), + TOBN(0x9505c81c, 0x407c1cf8), TOBN(0x9998db4e, 0x1b6ec284), + TOBN(0x7e3389e5, 0xc247d44d), TOBN(0x12507141, 0x3f4f3d80), + TOBN(0xd4ba0110, 0x4a78a6c7), TOBN(0x312874a0, 0x767720be), + TOBN(0xded059a6, 0x75944370), TOBN(0xd6123d90, 0x3b2c0bdd), + TOBN(0xa56b717b, 0x51c108e3), TOBN(0x9bb7940e, 0x070623e9), + TOBN(0x794e2d59, 0x84ac066c), TOBN(0xf5954a92, 0xe68c69a0), + TOBN(0x28c52458, 0x4fd99dcc), TOBN(0x60e639fc, 0xb1012517), + TOBN(0xc2e60125, 0x7de79248), TOBN(0xe9ef6404, 0xf12fc6d7), + TOBN(0x4c4f2808, 0x2a3b5d32), TOBN(0x865ad32e, 0xc768eb8a), + TOBN(0xac02331b, 0x13fb70b6), TOBN(0x037b44c1, 0x95599b27), + TOBN(0x1a860fc4, 0x60bd082c), TOBN(0xa2e25745, 0xc980cd01), + TOBN(0xee3387a8, 0x1da0263e), TOBN(0x931bfb95, 0x2d10f3d6), + TOBN(0x5b687270, 0xa1f24a32), TOBN(0xf140e65d, 0xca494b86), + TOBN(0x4f4ddf91, 0xb2f1ac7a), TOBN(0xf99eaabb, 0x760fee27), + TOBN(0x57f4008a, 0x49c228e5), TOBN(0x090be440, 0x1cf713bb), + TOBN(0xac91fbe4, 0x5004f022), TOBN(0xd838c2c2, 0x569e1af6), + TOBN(0xd6c7d20b, 0x0f1daaa5), TOBN(0xaa063ac1, 0x1bbb02c0), + TOBN(0x0938a422, 0x59558a78), TOBN(0x5343c669, 0x8435da2f), + TOBN(0x96f67b18, 0x034410dc), TOBN(0x7cc1e424, 0x84510804), + TOBN(0x86a1543f, 0x16dfbb7d), TOBN(0x921fa942, 0x5b5bd592), + TOBN(0x9dcccb6e, 0xb33dd03c), TOBN(0x8581ddd9, 0xb843f51e), + TOBN(0x54935fcb, 0x81d73c9e), TOBN(0x6d07e979, 0x0a5e97ab), + TOBN(0x4dc7b30a, 0xcf3a6bab), TOBN(0x147ab1f3, 0x170bee11), + TOBN(0x0aaf8e3d, 0x9fafdee4), TOBN(0xfab3dbcb, 0x538a8b95), + TOBN(0x405df4b3, 0x6ef13871), TOBN(0xf1f4e9cb, 0x088d5a49), + TOBN(0x9bcd24d3, 0x66b33f1d), TOBN(0x3b97b820, 0x5ce445c0), + TOBN(0xe2926549, 0xba93ff61), TOBN(0xd9c341ce, 0x4dafe616), + TOBN(0xfb30a76e, 0x16efb6f3), TOBN(0xdf24b8ca, 0x605b953c), + TOBN(0x8bd52afe, 0xc2fffb9f), TOBN(0xbbac5ff7, 0xe19d0b96), + TOBN(0x43c01b87, 0x459afccd), TOBN(0x6bd45143, 0xb7432652), + TOBN(0x84734530, 0x55b5d78e), TOBN(0x81088fdb, 0x1554ba7d), + TOBN(0xada0a52c, 0x1e269375), TOBN(0xf9f037c4, 0x2dc5ec10), + TOBN(0xc0660607, 0x94bfbc11), TOBN(0xc0a630bb, 0xc9c40d2f), + TOBN(0x5efc797e, 0xab64c31e), TOBN(0xffdb1dab, 0x74507144), + TOBN(0xf6124287, 0x1ca6790c), TOBN(0xe9609d81, 0xe69bf1bf), + TOBN(0xdb898595, 0x00d24fc9), TOBN(0x9c750333, 0xe51fb417), + TOBN(0x51830a91, 0xfef7bbde), TOBN(0x0ce67dc8, 0x945f585c), + TOBN(0x9a730ed4, 0x4763eb50), TOBN(0x24a0e221, 0xc1ab0d66), + TOBN(0x643b6393, 0x648748f3), TOBN(0x1982daa1, 0x6d3c6291), + TOBN(0x6f00a9f7, 0x8bbc5549), TOBN(0x7a1783e1, 0x7f36384e), + TOBN(0xe8346323, 0xde977f50), TOBN(0x91ab688d, 0xb245502a), + TOBN(0x331ab6b5, 0x6d0bdd66), TOBN(0x0a6ef32e, 0x64b71229), + TOBN(0x1028150e, 0xfe7c352f), TOBN(0x27e04350, 0xce7b39d3), + TOBN(0x2a3c8acd, 0xc1070c82), TOBN(0xfb2034d3, 0x80c9feef), + TOBN(0x2d729621, 0x709f3729), TOBN(0x8df290bf, 0x62cb4549), + TOBN(0x02f99f33, 0xfc2e4326), TOBN(0x3b30076d, 0x5eddf032), + TOBN(0xbb21f8cf, 0x0c652fb5), TOBN(0x314fb49e, 0xed91cf7b), + TOBN(0xa013eca5, 0x2f700750), TOBN(0x2b9e3c23, 0x712a4575), + TOBN(0xe5355557, 0xaf30fbb0), TOBN(0x1ada3516, 0x7c77e771), + TOBN(0x45f6ecb2, 0x7b135670), TOBN(0xe85d19df, 0x7cfc202e), + TOBN(0x0f1b50c7, 0x58d1be9f), TOBN(0x5ebf2c0a, 0xead2e344), + TOBN(0x1531fe4e, 0xabc199c9), TOBN(0xc7032592, 0x56bab0ae), + TOBN(0x16ab2e48, 0x6c1fec54), TOBN(0x0f87fda8, 0x04280188), + TOBN(0xdc9f46fc, 0x609e4a74), TOBN(0x2a44a143, 0xba667f91), + TOBN(0xbc3d8b95, 0xb4d83436), TOBN(0xa01e4bd0, 0xc7bd2958), + TOBN(0x7b182932, 0x73483c90), TOBN(0xa79c6aa1, 0xa7c7b598), + TOBN(0xbf3983c6, 0xeaaac07e), TOBN(0x8f18181e, 0x96e0d4e6), + TOBN(0x8553d37c, 0x051af62b), TOBN(0xe9a998eb, 0x0bf94496), + TOBN(0xe0844f9f, 0xb0d59aa1), TOBN(0x983fd558, 0xe6afb813), + TOBN(0x9670c0ca, 0x65d69804), TOBN(0x732b22de, 0x6ea5ff2d), + TOBN(0xd7640ba9, 0x5fd8623b), TOBN(0x9f619163, 0xa6351782), + TOBN(0x0bfc27ee, 0xacee5043), TOBN(0xae419e73, 0x2eb10f02), + TOBN(0x19c028d1, 0x8943fb05), TOBN(0x71f01cf7, 0xff13aa2a), + TOBN(0x7790737e, 0x8887a132), TOBN(0x67513309, 0x66318410), + TOBN(0x9819e8a3, 0x7ddb795e), TOBN(0xfecb8ef5, 0xdad100b2), + TOBN(0x59f74a22, 0x3021926a), TOBN(0xb7c28a49, 0x6f9b4c1c), + TOBN(0xed1a733f, 0x912ad0ab), TOBN(0x42a910af, 0x01a5659c), + TOBN(0x3842c6e0, 0x7bd68cab), TOBN(0x2b57fa38, 0x76d70ac8), + TOBN(0x8a6707a8, 0x3c53aaeb), TOBN(0x62c1c510, 0x65b4db18), + TOBN(0x8de2c1fb, 0xb2d09dc7), TOBN(0xc3dfed12, 0x266bd23b), + TOBN(0x927d039b, 0xd5b27db6), TOBN(0x2fb2f0f1, 0x103243da), + TOBN(0xf855a07b, 0x80be7399), TOBN(0xed9327ce, 0x1f9f27a8), + TOBN(0xa0bd99c7, 0x729bdef7), TOBN(0x2b67125e, 0x28250d88), + TOBN(0x784b26e8, 0x8670ced7), TOBN(0xe3dfe41f, 0xc31bd3b4), + TOBN(0x9e353a06, 0xbcc85cbc), TOBN(0x302e2909, 0x60178a9d), + TOBN(0x860abf11, 0xa6eac16e), TOBN(0x76447000, 0xaa2b3aac), + TOBN(0x46ff9d19, 0x850afdab), TOBN(0x35bdd6a5, 0xfdb2d4c1), + TOBN(0xe82594b0, 0x7e5c9ce9), TOBN(0x0f379e53, 0x20af346e), + TOBN(0x608b31e3, 0xbc65ad4a), TOBN(0x710c6b12, 0x267c4826), + TOBN(0x51c966f9, 0x71954cf1), TOBN(0xb1cec793, 0x0d0aa215), + TOBN(0x1f155989, 0x86bd23a8), TOBN(0xae2ff99c, 0xf9452e86), + TOBN(0xd8dd953c, 0x340ceaa2), TOBN(0x26355275, 0x2e2e9333), + TOBN(0x15d4e5f9, 0x8586f06d), TOBN(0xd6bf94a8, 0xf7cab546), + TOBN(0x33c59a0a, 0xb76a9af0), TOBN(0x52740ab3, 0xba095af7), + TOBN(0xc444de8a, 0x24389ca0), TOBN(0xcc6f9863, 0x706da0cb), + TOBN(0xb5a741a7, 0x6b2515cf), TOBN(0x71c41601, 0x9585c749), + TOBN(0x78350d4f, 0xe683de97), TOBN(0x31d61524, 0x63d0b5f5), + TOBN(0x7a0cc5e1, 0xfbce090b), TOBN(0xaac927ed, 0xfbcb2a5b), + TOBN(0xe920de49, 0x20d84c35), TOBN(0x8c06a0b6, 0x22b4de26), + TOBN(0xd34dd58b, 0xafe7ddf3), TOBN(0x55851fed, 0xc1e6e55b), + TOBN(0xd1395616, 0x960696e7), TOBN(0x940304b2, 0x5f22705f), + TOBN(0x6f43f861, 0xb0a2a860), TOBN(0xcf121282, 0x0e7cc981), + TOBN(0x12186212, 0x0ab64a96), TOBN(0x09215b9a, 0xb789383c), + TOBN(0x311eb305, 0x37387c09), TOBN(0xc5832fce, 0xf03ee760), + TOBN(0x30358f58, 0x32f7ea19), TOBN(0xe01d3c34, 0x91d53551), + TOBN(0x1ca5ee41, 0xda48ea80), TOBN(0x34e71e8e, 0xcf4fa4c1), + TOBN(0x312abd25, 0x7af1e1c7), TOBN(0xe3afcdeb, 0x2153f4a5), + TOBN(0x9d5c84d7, 0x00235e9a), TOBN(0x0308d3f4, 0x8c4c836f), + TOBN(0xc0a66b04, 0x89332de5), TOBN(0x610dd399, 0x89e566ef), + TOBN(0xf8eea460, 0xd1ac1635), TOBN(0x84cbb3fb, 0x20a2c0df), + TOBN(0x40afb488, 0xe74a48c5), TOBN(0x29738198, 0xd326b150), + TOBN(0x2a17747f, 0xa6d74081), TOBN(0x60ea4c05, 0x55a26214), + TOBN(0x53514bb4, 0x1f88c5fe), TOBN(0xedd64567, 0x7e83426c), + TOBN(0xd5d6cbec, 0x96460b25), TOBN(0xa12fd0ce, 0x68dc115e), + TOBN(0xc5bc3ed2, 0x697840ea), TOBN(0x969876a8, 0xa6331e31), + TOBN(0x60c36217, 0x472ff580), TOBN(0xf4229705, 0x4ad41393), + TOBN(0x4bd99ef0, 0xa03b8b92), TOBN(0x501c7317, 0xc144f4f6), + TOBN(0x159009b3, 0x18464945), TOBN(0x6d5e594c, 0x74c5c6be), + TOBN(0x2d587011, 0x321a3660), TOBN(0xd1e184b1, 0x3898d022), + TOBN(0x5ba04752, 0x4c6a7e04), TOBN(0x47fa1e2b, 0x45550b65), + TOBN(0x9419daf0, 0x48c0a9a5), TOBN(0x66362953, 0x7c243236), + TOBN(0xcd0744b1, 0x5cb12a88), TOBN(0x561b6f9a, 0x2b646188), + TOBN(0x599415a5, 0x66c2c0c0), TOBN(0xbe3f0859, 0x0f83f09a), + TOBN(0x9141c5be, 0xb92041b8), TOBN(0x01ae38c7, 0x26477d0d), + TOBN(0xca8b71f3, 0xd12c7a94), TOBN(0xfab5b31f, 0x765c70db), + TOBN(0x76ae7492, 0x487443e9), TOBN(0x8595a310, 0x990d1349), + TOBN(0xf8dbeda8, 0x7d460a37), TOBN(0x7f7ad082, 0x1e45a38f), + TOBN(0xed1d4db6, 0x1059705a), TOBN(0xa3dd492a, 0xe6b9c697), + TOBN(0x4b92ee3a, 0x6eb38bd5), TOBN(0xbab2609d, 0x67cc0bb7), + TOBN(0x7fc4fe89, 0x6e70ee82), TOBN(0xeff2c56e, 0x13e6b7e3), + TOBN(0x9b18959e, 0x34d26fca), TOBN(0x2517ab66, 0x889d6b45), + TOBN(0xf167b4e0, 0xbdefdd4f), TOBN(0x69958465, 0xf366e401), + TOBN(0x5aa368ab, 0xa73bbec0), TOBN(0x12148709, 0x7b240c21), + TOBN(0x378c3233, 0x18969006), TOBN(0xcb4d73ce, 0xe1fe53d1), + TOBN(0x5f50a80e, 0x130c4361), TOBN(0xd67f5951, 0x7ef5212b), + TOBN(0xf145e21e, 0x9e70c72e), TOBN(0xb2e52e29, 0x5566d2fb), + TOBN(0x44eaba4a, 0x032397f5), TOBN(0x5e56937b, 0x7e31a7de), + TOBN(0x68dcf517, 0x456c61e1), TOBN(0xbc2e954a, 0xa8b0a388), + TOBN(0xe3552fa7, 0x60a8b755), TOBN(0x03442dae, 0x73ad0cde), + TOBN(0x37ffe747, 0xceb26210), TOBN(0x983545e8, 0x787baef9), + TOBN(0x8b8c8535, 0x86a3de31), TOBN(0xc621dbcb, 0xfacd46db), + TOBN(0x82e442e9, 0x59266fbb), TOBN(0xa3514c37, 0x339d471c), + TOBN(0x3a11b771, 0x62cdad96), TOBN(0xf0cb3b3c, 0xecf9bdf0), + TOBN(0x3fcbdbce, 0x478e2135), TOBN(0x7547b5cf, 0xbda35342), + TOBN(0xa97e81f1, 0x8a677af6), TOBN(0xc8c2bf83, 0x28817987), + TOBN(0xdf07eaaf, 0x45580985), TOBN(0xc68d1f05, 0xc93b45cb), + TOBN(0x106aa2fe, 0xc77b4cac), TOBN(0x4c1d8afc, 0x04a7ae86), + TOBN(0xdb41c3fd, 0x9eb45ab2), TOBN(0x5b234b5b, 0xd4b22e74), + TOBN(0xda253dec, 0xf215958a), TOBN(0x67e0606e, 0xa04edfa0), + TOBN(0xabbbf070, 0xef751b11), TOBN(0xf352f175, 0xf6f06dce), + TOBN(0xdfc4b6af, 0x6839f6b4), TOBN(0x53ddf9a8, 0x9959848e), + TOBN(0xda49c379, 0xc21520b0), TOBN(0x90864ff0, 0xdbd5d1b6), + TOBN(0x2f055d23, 0x5f49c7f7), TOBN(0xe51e4e6a, 0xa796b2d8), + TOBN(0xc361a67f, 0x5c9dc340), TOBN(0x5ad53c37, 0xbca7c620), + TOBN(0xda1d6588, 0x32c756d0), TOBN(0xad60d911, 0x8bb67e13), + TOBN(0xd6c47bdf, 0x0eeec8c6), TOBN(0x4a27fec1, 0x078a1821), + TOBN(0x081f7415, 0xc3099524), TOBN(0x8effdf0b, 0x82cd8060), + TOBN(0xdb70ec1c, 0x65842df8), TOBN(0x8821b358, 0xd319a901), + TOBN(0x72ee56ee, 0xde42b529), TOBN(0x5bb39592, 0x236e4286), + TOBN(0xd1183316, 0xfd6f7140), TOBN(0xf9fadb5b, 0xbd8e81f7), + TOBN(0x701d5e0c, 0x5a02d962), TOBN(0xfdee4dbf, 0x1b601324), + TOBN(0xbed17407, 0x35d7620e), TOBN(0x04e3c2c3, 0xf48c0012), + TOBN(0x9ee29da7, 0x3455449a), TOBN(0x562cdef4, 0x91a836c4), + TOBN(0x8f682a5f, 0x47701097), TOBN(0x617125d8, 0xff88d0c2), + TOBN(0x948fda24, 0x57bb86dd), TOBN(0x348abb8f, 0x289f7286), + TOBN(0xeb10eab5, 0x99d94bbd), TOBN(0xd51ba28e, 0x4684d160), + TOBN(0xabe0e51c, 0x30c8f41a), TOBN(0x66588b45, 0x13254f4a), + TOBN(0x147ebf01, 0xfad097a5), TOBN(0x49883ea8, 0x610e815d), + TOBN(0xe44d60ba, 0x8a11de56), TOBN(0xa970de6e, 0x827a7a6d), + TOBN(0x2be41424, 0x5e17fc19), TOBN(0xd833c657, 0x01214057), + TOBN(0x1375813b, 0x363e723f), TOBN(0x6820bb88, 0xe6a52e9b), + TOBN(0x7e7f6970, 0xd875d56a), TOBN(0xd6a0a9ac, 0x51fbf6bf), + TOBN(0x54ba8790, 0xa3083c12), TOBN(0xebaeb23d, 0x6ae7eb64), + TOBN(0xa8685c3a, 0xb99a907a), TOBN(0xf1e74550, 0x026bf40b), + TOBN(0x7b73a027, 0xc802cd9e), TOBN(0x9a8a927c, 0x4fef4635), + TOBN(0xe1b6f60c, 0x08191224), TOBN(0xc4126ebb, 0xde4ec091), + TOBN(0xe1dff4dc, 0x4ae38d84), TOBN(0xde3f57db, 0x4f2ef985), + TOBN(0x34964337, 0xd446a1dd), TOBN(0x7bf217a0, 0x859e77f6), + TOBN(0x8ff10527, 0x8e1d13f5), TOBN(0xa304ef03, 0x74eeae27), + TOBN(0xfc6f5e47, 0xd19dfa5a), TOBN(0xdb007de3, 0x7fad982b), + TOBN(0x28205ad1, 0x613715f5), TOBN(0x251e6729, 0x7889529e), + TOBN(0x72705184, 0x1ae98e78), TOBN(0xf818537d, 0x271cac32), + TOBN(0xc8a15b7e, 0xb7f410f5), TOBN(0xc474356f, 0x81f62393), + TOBN(0x92dbdc5a, 0xc242316b), TOBN(0xabe060ac, 0xdbf4aff5), + TOBN(0x6e8c38fe, 0x909a8ec6), TOBN(0x43e514e5, 0x6116cb94), + TOBN(0x2078fa38, 0x07d784f9), TOBN(0x1161a880, 0xf4b5b357), + TOBN(0x5283ce79, 0x13adea3d), TOBN(0x0756c3e6, 0xcc6a910b), + TOBN(0x60bcfe01, 0xaaa79697), TOBN(0x04a73b29, 0x56391db1), + TOBN(0xdd8dad47, 0x189b45a0), TOBN(0xbfac0dd0, 0x48d5b8d9), + TOBN(0x34ab3af5, 0x7d3d2ec2), TOBN(0x6fa2fc2d, 0x207bd3af), + TOBN(0x9ff40092, 0x66550ded), TOBN(0x719b3e87, 0x1fd5b913), + TOBN(0xa573a496, 0x6d17fbc7), TOBN(0x0cd1a70a, 0x73d2b24e), + TOBN(0x34e2c5ca, 0xb2676937), TOBN(0xe7050b06, 0xbf669f21), + TOBN(0xfbe948b6, 0x1ede9046), TOBN(0xa0530051, 0x97662659), + TOBN(0x58cbd4ed, 0xf10124c5), TOBN(0xde2646e4, 0xdd6c06c8), + TOBN(0x332f8108, 0x8cad38c0), TOBN(0x471b7e90, 0x6bd68ae2), + TOBN(0x56ac3fb2, 0x0d8e27a3), TOBN(0xb54660db, 0x136b4b0d), + TOBN(0x123a1e11, 0xa6fd8de4), TOBN(0x44dbffea, 0xa37799ef), + TOBN(0x4540b977, 0xce6ac17c), TOBN(0x495173a8, 0xaf60acef)} + , + {TOBN(0x9ebb284d, 0x391c2a82), TOBN(0xbcdd4863, 0x158308e8), + TOBN(0x006f16ec, 0x83f1edca), TOBN(0xa13e2c37, 0x695dc6c8), + TOBN(0x2ab756f0, 0x4a057a87), TOBN(0xa8765500, 0xa6b48f98), + TOBN(0x4252face, 0x68651c44), TOBN(0xa52b540b, 0xe1765e02), + TOBN(0x4f922fc5, 0x16a0d2bb), TOBN(0x0d5cc16c, 0x1a623499), + TOBN(0x9241cf3a, 0x57c62c8b), TOBN(0x2f5e6961, 0xfd1b667f), + TOBN(0x5c15c70b, 0xf5a01797), TOBN(0x3d20b44d, 0x60956192), + TOBN(0x04911b37, 0x071fdb52), TOBN(0xf648f916, 0x8d6f0f7b), + TOBN(0x6dc1acaf, 0xe60b7cf7), TOBN(0x25860a50, 0x84a9d869), + TOBN(0x56fc6f09, 0xe7ba8ac4), TOBN(0x828c5bd0, 0x6148d29e), + TOBN(0xac6b435e, 0xdc55ae5f), TOBN(0xa527f56c, 0xc0117411), + TOBN(0x94d5045e, 0xfd24342c), TOBN(0x2c4c0a35, 0x70b67c0d), + TOBN(0x027cc8b8, 0xfac61d9a), TOBN(0x7d25e062, 0xe3c6fe8a), + TOBN(0xe08805bf, 0xe5bff503), TOBN(0x13271e6c, 0x6ff632f7), + TOBN(0x55dca6c0, 0x232f76a5), TOBN(0x8957c32d, 0x701ef426), + TOBN(0xee728bcb, 0xa10a5178), TOBN(0x5ea60411, 0xb62c5173), + TOBN(0xfc4e964e, 0xd0b8892b), TOBN(0x9ea17683, 0x9301bb74), + TOBN(0x6265c5ae, 0xfcc48626), TOBN(0xe60cf82e, 0xbb3e9102), + TOBN(0x57adf797, 0xd4df5531), TOBN(0x235b59a1, 0x8deeefe2), + TOBN(0x60adcf58, 0x3f306eb1), TOBN(0x105c2753, 0x3d09492d), + TOBN(0x4090914b, 0xb5def996), TOBN(0x1cb69c83, 0x233dd1e7), + TOBN(0xc1e9c1d3, 0x9b3d5e76), TOBN(0x1f3338ed, 0xfccf6012), + TOBN(0xb1e95d0d, 0x2f5378a8), TOBN(0xacf4c2c7, 0x2f00cd21), + TOBN(0x6e984240, 0xeb5fe290), TOBN(0xd66c038d, 0x248088ae), + TOBN(0x804d264a, 0xf94d70cf), TOBN(0xbdb802ef, 0x7314bf7e), + TOBN(0x8fb54de2, 0x4333ed02), TOBN(0x740461e0, 0x285635d9), + TOBN(0x4113b2c8, 0x365e9383), TOBN(0xea762c83, 0x3fdef652), + TOBN(0x4eec6e2e, 0x47b956c1), TOBN(0xa3d814be, 0x65620fa4), + TOBN(0x9ad5462b, 0xb4d8bc50), TOBN(0x181c0b16, 0xa9195770), + TOBN(0xebd4fe1c, 0x78412a68), TOBN(0xae0341bc, 0xc0dff48c), + TOBN(0xb6bc45cf, 0x7003e866), TOBN(0xf11a6dea, 0x8a24a41b), + TOBN(0x5407151a, 0xd04c24c2), TOBN(0x62c9d27d, 0xda5b7b68), + TOBN(0x2e964235, 0x88cceff6), TOBN(0x8594c54f, 0x8b07ed69), + TOBN(0x1578e73c, 0xc84d0d0d), TOBN(0x7b4e1055, 0xff532868), + TOBN(0xa348c0d5, 0xb5ec995a), TOBN(0xbf4b9d55, 0x14289a54), + TOBN(0x9ba155a6, 0x58fbd777), TOBN(0x186ed7a8, 0x1a84491d), + TOBN(0xd4992b30, 0x614c0900), TOBN(0xda98d121, 0xbd00c24b), + TOBN(0x7f534dc8, 0x7ec4bfa1), TOBN(0x4a5ff674, 0x37dc34bc), + TOBN(0x68c196b8, 0x1d7ea1d7), TOBN(0x38cf2893, 0x80a6d208), + TOBN(0xfd56cd09, 0xe3cbbd6e), TOBN(0xec72e27e, 0x4205a5b6), + TOBN(0x15ea68f5, 0xa44f77f7), TOBN(0x7aa5f9fd, 0xb43c52bc), + TOBN(0x86ff676f, 0x94f0e609), TOBN(0xa4cde963, 0x2e2d432b), + TOBN(0x8cafa0c0, 0xeee470af), TOBN(0x84137d0e, 0x8a3f5ec8), + TOBN(0xebb40411, 0xfaa31231), TOBN(0xa239c13f, 0x6f7f7ccf), + TOBN(0x32865719, 0xa8afd30b), TOBN(0x86798328, 0x8a826dce), + TOBN(0xdf04e891, 0xc4a8fbe0), TOBN(0xbb6b6e1b, 0xebf56ad3), + TOBN(0x0a695b11, 0x471f1ff0), TOBN(0xd76c3389, 0xbe15baf0), + TOBN(0x018edb95, 0xbe96c43e), TOBN(0xf2beaaf4, 0x90794158), + TOBN(0x152db09e, 0xc3076a27), TOBN(0x5e82908e, 0xe416545d), + TOBN(0xa2c41272, 0x356d6f2e), TOBN(0xdc9c9642, 0x31fd74e1), + TOBN(0x66ceb88d, 0x519bf615), TOBN(0xe29ecd76, 0x05a2274e), + TOBN(0x3a0473c4, 0xbf5e2fa0), TOBN(0x6b6eb671, 0x64284e67), + TOBN(0xe8b97932, 0xb88756dd), TOBN(0xed4e8652, 0xf17e3e61), + TOBN(0xc2dd1499, 0x3ee1c4a4), TOBN(0xc0aaee17, 0x597f8c0e), + TOBN(0x15c4edb9, 0x6c168af3), TOBN(0x6563c7bf, 0xb39ae875), + TOBN(0xadfadb6f, 0x20adb436), TOBN(0xad55e8c9, 0x9a042ac0), + TOBN(0x975a1ed8, 0xb76da1f5), TOBN(0x10dfa466, 0xa58acb94), + TOBN(0x8dd7f7e3, 0xac060282), TOBN(0x6813e66a, 0x572a051e), + TOBN(0xb4ccae1e, 0x350cb901), TOBN(0xb653d656, 0x50cb7822), + TOBN(0x42484710, 0xdfab3b87), TOBN(0xcd7ee537, 0x9b670fd0), + TOBN(0x0a50b12e, 0x523b8bf6), TOBN(0x8009eb5b, 0x8f910c1b), + TOBN(0xf535af82, 0x4a167588), TOBN(0x0f835f9c, 0xfb2a2abd), + TOBN(0xf59b2931, 0x2afceb62), TOBN(0xc797df2a, 0x169d383f), + TOBN(0xeb3f5fb0, 0x66ac02b0), TOBN(0x029d4c6f, 0xdaa2d0ca), + TOBN(0xd4059bc1, 0xafab4bc5), TOBN(0x833f5c6f, 0x56783247), + TOBN(0xb5346630, 0x8d2d3605), TOBN(0x83387891, 0xd34d8433), + TOBN(0xd973b30f, 0xadd9419a), TOBN(0xbcca1099, 0xafe3fce8), + TOBN(0x08178315, 0x0809aac6), TOBN(0x01b7f21a, 0x540f0f11), + TOBN(0x65c29219, 0x909523c8), TOBN(0xa62f648f, 0xa3a1c741), + TOBN(0x88598d4f, 0x60c9e55a), TOBN(0xbce9141b, 0x0e4f347a), + TOBN(0x9af97d84, 0x35f9b988), TOBN(0x0210da62, 0x320475b6), + TOBN(0x3c076e22, 0x9191476c), TOBN(0x7520dbd9, 0x44fc7834), + TOBN(0x6a6b2cfe, 0xc1ab1bbd), TOBN(0xef8a65be, 0xdc650938), + TOBN(0x72855540, 0x805d7bc4), TOBN(0xda389396, 0xed11fdfd), + TOBN(0xa9d5bd36, 0x74660876), TOBN(0x11d67c54, 0xb45dff35), + TOBN(0x6af7d148, 0xa4f5da94), TOBN(0xbb8d4c3f, 0xc0bbeb31), + TOBN(0x87a7ebd1, 0xe0a1b12a), TOBN(0x1e4ef88d, 0x770ba95f), + TOBN(0x8c33345c, 0xdc2ae9cb), TOBN(0xcecf1276, 0x01cc8403), + TOBN(0x687c012e, 0x1b39b80f), TOBN(0xfd90d0ad, 0x35c33ba4), + TOBN(0xa3ef5a67, 0x5c9661c2), TOBN(0x368fc88e, 0xe017429e), + TOBN(0xd30c6761, 0x196a2fa2), TOBN(0x931b9817, 0xbd5b312e), + TOBN(0xba01000c, 0x72f54a31), TOBN(0xa203d2c8, 0x66eaa541), + TOBN(0xf2abdee0, 0x98939db3), TOBN(0xe37d6c2c, 0x3e606c02), + TOBN(0xf2921574, 0x521ff643), TOBN(0x2781b3c4, 0xd7e2fca3), + TOBN(0x664300b0, 0x7850ec06), TOBN(0xac5a38b9, 0x7d3a10cf), + TOBN(0x9233188d, 0xe34ab39d), TOBN(0xe77057e4, 0x5072cbb9), + TOBN(0xbcf0c042, 0xb59e78df), TOBN(0x4cfc91e8, 0x1d97de52), + TOBN(0x4661a26c, 0x3ee0ca4a), TOBN(0x5620a4c1, 0xfb8507bc), + TOBN(0x4b44d4aa, 0x049f842c), TOBN(0xceabc5d5, 0x1540e82b), + TOBN(0x306710fd, 0x15c6f156), TOBN(0xbe5ae52b, 0x63db1d72), + TOBN(0x06f1e7e6, 0x334957f1), TOBN(0x57e388f0, 0x31144a70), + TOBN(0xfb69bb2f, 0xdf96447b), TOBN(0x0f78ebd3, 0x73e38a12), + TOBN(0xb8222605, 0x2b7ce542), TOBN(0xe6d4ce99, 0x7472bde1), + TOBN(0x53e16ebe, 0x09d2f4da), TOBN(0x180ff42e, 0x53b92b2e), + TOBN(0xc59bcc02, 0x2c34a1c6), TOBN(0x3803d6f9, 0x422c46c2), + TOBN(0x18aff74f, 0x5c14a8a2), TOBN(0x55aebf80, 0x10a08b28), + TOBN(0x66097d58, 0x7135593f), TOBN(0x32e6eff7, 0x2be570cd), + TOBN(0x584e6a10, 0x2a8c860d), TOBN(0xcd185890, 0xa2eb4163), + TOBN(0x7ceae99d, 0x6d97e134), TOBN(0xd42c6b70, 0xdd8447ce), + TOBN(0x59ddbb4a, 0xb8c50273), TOBN(0x03c612df, 0x3cf34e1e), + TOBN(0x84b9ca15, 0x04b6c5a0), TOBN(0x35216f39, 0x18f0e3a3), + TOBN(0x3ec2d2bc, 0xbd986c00), TOBN(0x8bf546d9, 0xd19228fe), + TOBN(0xd1c655a4, 0x4cd623c3), TOBN(0x366ce718, 0x502b8e5a), + TOBN(0x2cfc84b4, 0xeea0bfe7), TOBN(0xe01d5cee, 0xcf443e8e), + TOBN(0x8ec045d9, 0x036520f8), TOBN(0xdfb3c3d1, 0x92d40e98), + TOBN(0x0bac4cce, 0xcc559a04), TOBN(0x35eccae5, 0x240ea6b1), + TOBN(0x180b32db, 0xf8a5a0ac), TOBN(0x547972a5, 0xeb699700), + TOBN(0xa3765801, 0xca26bca0), TOBN(0x57e09d0e, 0xa647f25a), + TOBN(0xb956970e, 0x2fdd23cc), TOBN(0xb80288bc, 0x5682e971), + TOBN(0xe6e6d91e, 0x9ae86ebc), TOBN(0x0564c83f, 0x8c9f1939), + TOBN(0x551932a2, 0x39560368), TOBN(0xe893752b, 0x049c28e2), + TOBN(0x0b03cee5, 0xa6a158c3), TOBN(0xe12d656b, 0x04964263), + TOBN(0x4b47554e, 0x63e3bc1d), TOBN(0xc719b6a2, 0x45044ff7), + TOBN(0x4f24d30a, 0xe48daa07), TOBN(0xa3f37556, 0xc8c1edc3), + TOBN(0x9a47bf76, 0x0700d360), TOBN(0xbb1a1824, 0x822ae4e2), + TOBN(0x22e275a3, 0x89f1fb4c), TOBN(0x72b1aa23, 0x9968c5f5), + TOBN(0xa75feaca, 0xbe063f64), TOBN(0x9b392f43, 0xbce47a09), + TOBN(0xd4241509, 0x1ad07aca), TOBN(0x4b0c591b, 0x8d26cd0f), + TOBN(0x2d42ddfd, 0x92f1169a), TOBN(0x63aeb1ac, 0x4cbf2392), + TOBN(0x1de9e877, 0x0691a2af), TOBN(0xebe79af7, 0xd98021da), + TOBN(0xcfdf2a4e, 0x40e50acf), TOBN(0xf0a98ad7, 0xaf01d665), + TOBN(0xefb640bf, 0x1831be1f), TOBN(0x6fe8bd2f, 0x80e9ada0), + TOBN(0x94c103a1, 0x6cafbc91), TOBN(0x170f8759, 0x8308e08c), + TOBN(0x5de2d2ab, 0x9780ff4f), TOBN(0x666466bc, 0x45b201f2), + TOBN(0x58af2010, 0xf5b343bc), TOBN(0x0f2e400a, 0xf2f142fe), + TOBN(0x3483bfde, 0xa85f4bdf), TOBN(0xf0b1d093, 0x03bfeaa9), + TOBN(0x2ea01b95, 0xc7081603), TOBN(0xe943e4c9, 0x3dba1097), + TOBN(0x47be92ad, 0xb438f3a6), TOBN(0x00bb7742, 0xe5bf6636), + TOBN(0x136b7083, 0x824297b4), TOBN(0x9d0e5580, 0x5584455f), + TOBN(0xab48cedc, 0xf1c7d69e), TOBN(0x53a9e481, 0x2a256e76), + TOBN(0x0402b0e0, 0x65eb2413), TOBN(0xdadbbb84, 0x8fc407a7), + TOBN(0xa65cd5a4, 0x8d7f5492), TOBN(0x21d44293, 0x74bae294), + TOBN(0x66917ce6, 0x3b5f1cc4), TOBN(0x37ae52ea, 0xce872e62), + TOBN(0xbb087b72, 0x2905f244), TOBN(0x12077086, 0x1e6af74f), + TOBN(0x4b644e49, 0x1058edea), TOBN(0x827510e3, 0xb638ca1d), + TOBN(0x8cf2b704, 0x6038591c), TOBN(0xffc8b47a, 0xfe635063), + TOBN(0x3ae220e6, 0x1b4d5e63), TOBN(0xbd864742, 0x9d961b4b), + TOBN(0x610c107e, 0x9bd16bed), TOBN(0x4270352a, 0x1127147b), + TOBN(0x7d17ffe6, 0x64cfc50e), TOBN(0x50dee01a, 0x1e36cb42), + TOBN(0x068a7622, 0x35dc5f9a), TOBN(0x9a08d536, 0xdf53f62c), + TOBN(0x4ed71457, 0x6be5f7de), TOBN(0xd93006f8, 0xc2263c9e), + TOBN(0xe073694c, 0xcacacb36), TOBN(0x2ff7a5b4, 0x3ae118ab), + TOBN(0x3cce53f1, 0xcd871236), TOBN(0xf156a39d, 0xc2aa6d52), + TOBN(0x9cc5f271, 0xb198d76d), TOBN(0xbc615b6f, 0x81383d39), + TOBN(0xa54538e8, 0xde3eee6b), TOBN(0x58c77538, 0xab910d91), + TOBN(0x31e5bdbc, 0x58d278bd), TOBN(0x3cde4adf, 0xb963acae), + TOBN(0xb1881fd2, 0x5302169c), TOBN(0x8ca60fa0, 0xa989ed8b), + TOBN(0xa1999458, 0xff96a0ee), TOBN(0xc1141f03, 0xac6c283d), + TOBN(0x7677408d, 0x6dfafed3), TOBN(0x33a01653, 0x39661588), + TOBN(0x3c9c15ec, 0x0b726fa0), TOBN(0x090cfd93, 0x6c9b56da), + TOBN(0xe34f4bae, 0xa3c40af5), TOBN(0x3469eadb, 0xd21129f1), + TOBN(0xcc51674a, 0x1e207ce8), TOBN(0x1e293b24, 0xc83b1ef9), + TOBN(0x17173d13, 0x1e6c0bb4), TOBN(0x19004695, 0x90776d35), + TOBN(0xe7980e34, 0x6de6f922), TOBN(0x873554cb, 0xf4dd9a22), + TOBN(0x0316c627, 0xcbf18a51), TOBN(0x4d93651b, 0x3032c081), + TOBN(0x207f2771, 0x3946834d), TOBN(0x2c08d7b4, 0x30cdbf80), + TOBN(0x137a4fb4, 0x86df2a61), TOBN(0xa1ed9c07, 0xecf7b4a2), + TOBN(0xb2e460e2, 0x7bd042ff), TOBN(0xb7f5e2fa, 0x5f62f5ec), + TOBN(0x7aa6ec6b, 0xcc2423b7), TOBN(0x75ce0a7f, 0xba63eea7), + TOBN(0x67a45fb1, 0xf250a6e1), TOBN(0x93bc919c, 0xe53cdc9f), + TOBN(0x9271f56f, 0x871942df), TOBN(0x2372ff6f, 0x7859ad66), + TOBN(0x5f4c2b96, 0x33cb1a78), TOBN(0xe3e29101, 0x5838aa83), + TOBN(0xa7ed1611, 0xe4e8110c), TOBN(0x2a2d70d5, 0x330198ce), + TOBN(0xbdf132e8, 0x6720efe0), TOBN(0xe61a8962, 0x66a471bf), + TOBN(0x796d3a85, 0x825808bd), TOBN(0x51dc3cb7, 0x3fd6e902), + TOBN(0x643c768a, 0x916219d1), TOBN(0x36cd7685, 0xa2ad7d32), + TOBN(0xe3db9d05, 0xb22922a4), TOBN(0x6494c87e, 0xdba29660), + TOBN(0xf0ac91df, 0xbcd2ebc7), TOBN(0x4deb57a0, 0x45107f8d), + TOBN(0x42271f59, 0xc3d12a73), TOBN(0x5f71687c, 0xa5c2c51d), + TOBN(0xcb1f50c6, 0x05797bcb), TOBN(0x29ed0ed9, 0xd6d34eb0), + TOBN(0xe5fe5b47, 0x4683c2eb), TOBN(0x4956eeb5, 0x97447c46), + TOBN(0x5b163a43, 0x71207167), TOBN(0x93fa2fed, 0x0248c5ef), + TOBN(0x67930af2, 0x31f63950), TOBN(0xa77797c1, 0x14caa2c9), + TOBN(0x526e80ee, 0x27ac7e62), TOBN(0xe1e6e626, 0x58b28aec), + TOBN(0x636178b0, 0xb3c9fef0), TOBN(0xaf7752e0, 0x6d5f90be), + TOBN(0x94ecaf18, 0xeece51cf), TOBN(0x2864d0ed, 0xca806e1f), + TOBN(0x6de2e383, 0x97c69134), TOBN(0x5a42c316, 0xeb291293), + TOBN(0xc7779219, 0x6a60bae0), TOBN(0xa24de346, 0x6b7599d1), + TOBN(0x49d374aa, 0xb75d4941), TOBN(0x98900586, 0x2d501ff0), + TOBN(0x9f16d40e, 0xeb7974cf), TOBN(0x1033860b, 0xcdd8c115), + TOBN(0xb6c69ac8, 0x2094cec3), TOBN(0x9976fb88, 0x403b770c), + TOBN(0x1dea026c, 0x4859590d), TOBN(0xb6acbb46, 0x8562d1fd), + TOBN(0x7cd6c461, 0x44569d85), TOBN(0xc3190a36, 0x97f0891d), + TOBN(0xc6f53195, 0x48d5a17d), TOBN(0x7d919966, 0xd749abc8), + TOBN(0x65104837, 0xdd1c8a20), TOBN(0x7e5410c8, 0x2f683419), + TOBN(0x958c3ca8, 0xbe94022e), TOBN(0x605c3197, 0x6145dac2), + TOBN(0x3fc07501, 0x01683d54), TOBN(0x1d7127c5, 0x595b1234), + TOBN(0x10b8f87c, 0x9481277f), TOBN(0x677db2a8, 0xe65a1adb), + TOBN(0xec2fccaa, 0xddce3345), TOBN(0x2a6811b7, 0x012a4350), + TOBN(0x96760ff1, 0xac598bdc), TOBN(0x054d652a, 0xd1bf4128), + TOBN(0x0a1151d4, 0x92a21005), TOBN(0xad7f3971, 0x33110fdf), + TOBN(0x8c95928c, 0x1960100f), TOBN(0x6c91c825, 0x7bf03362), + TOBN(0xc8c8b2a2, 0xce309f06), TOBN(0xfdb27b59, 0xca27204b), + TOBN(0xd223eaa5, 0x0848e32e), TOBN(0xb93e4b2e, 0xe7bfaf1e), + TOBN(0xc5308ae6, 0x44aa3ded), TOBN(0x317a666a, 0xc015d573), + TOBN(0xc888ce23, 0x1a979707), TOBN(0xf141c1e6, 0x0d5c4958), + TOBN(0xb53b7de5, 0x61906373), TOBN(0x858dbade, 0xeb999595), + TOBN(0x8cbb47b2, 0xa59e5c36), TOBN(0x660318b3, 0xdcf4e842), + TOBN(0xbd161ccd, 0x12ba4b7a), TOBN(0xf399daab, 0xf8c8282a), + TOBN(0x1587633a, 0xeeb2130d), TOBN(0xa465311a, 0xda38dd7d), + TOBN(0x5f75eec8, 0x64d3779b), TOBN(0x3c5d0476, 0xad64c171), + TOBN(0x87410371, 0x2a914428), TOBN(0x8096a891, 0x90e2fc29), + TOBN(0xd3d2ae9d, 0x23b3ebc2), TOBN(0x90bdd6db, 0xa580cfd6), + TOBN(0x52dbb7f3, 0xc5b01f6c), TOBN(0xe68eded4, 0xe102a2dc), + TOBN(0x17785b77, 0x99eb6df0), TOBN(0x26c3cc51, 0x7386b779), + TOBN(0x345ed988, 0x6417a48e), TOBN(0xe990b4e4, 0x07d6ef31), + TOBN(0x0f456b7e, 0x2586abba), TOBN(0x239ca6a5, 0x59c96e9a), + TOBN(0xe327459c, 0xe2eb4206), TOBN(0x3a4c3313, 0xa002b90a), + TOBN(0x2a114806, 0xf6a3f6fb), TOBN(0xad5cad2f, 0x85c251dd), + TOBN(0x92c1f613, 0xf5a784d3), TOBN(0xec7bfacf, 0x349766d5), + TOBN(0x04b3cd33, 0x3e23cb3b), TOBN(0x3979fe84, 0xc5a64b2d), + TOBN(0x192e2720, 0x7e589106), TOBN(0xa60c43d1, 0xa15b527f), + TOBN(0x2dae9082, 0xbe7cf3a6), TOBN(0xcc86ba92, 0xbc967274), + TOBN(0xf28a2ce8, 0xaea0a8a9), TOBN(0x404ca6d9, 0x6ee988b3), + TOBN(0xfd7e9c5d, 0x005921b8), TOBN(0xf56297f1, 0x44e79bf9), + TOBN(0xa163b460, 0x0d75ddc2), TOBN(0x30b23616, 0xa1f2be87), + TOBN(0x4b070d21, 0xbfe50e2b), TOBN(0x7ef8cfd0, 0xe1bfede1), + TOBN(0xadba0011, 0x2aac4ae0), TOBN(0x2a3e7d01, 0xb9ebd033), + TOBN(0x995277ec, 0xe38d9d1c), TOBN(0xb500249e, 0x9c5d2de3), + TOBN(0x8912b820, 0xf13ca8c9), TOBN(0xc8798114, 0x877793af), + TOBN(0x19e6125d, 0xec3f1dec), TOBN(0x07b1f040, 0x911178da), + TOBN(0xd93ededa, 0x904a6738), TOBN(0x55187a5a, 0x0bebedcd), + TOBN(0xf7d04722, 0xeb329d41), TOBN(0xf449099e, 0xf170b391), + TOBN(0xfd317a69, 0xca99f828), TOBN(0x50c3db2b, 0x34a4976d), + TOBN(0xe9ba7784, 0x3757b392), TOBN(0x326caefd, 0xaa3ca05a), + TOBN(0x78e5293b, 0xf1e593d4), TOBN(0x7842a937, 0x0d98fd13), + TOBN(0xe694bf96, 0x5f96b10d), TOBN(0x373a9df6, 0x06a8cd05), + TOBN(0x997d1e51, 0xe8f0c7fc), TOBN(0x1d019790, 0x63fd972e), + TOBN(0x0064d858, 0x5499fb32), TOBN(0x7b67bad9, 0x77a8aeb7), + TOBN(0x1d3eb977, 0x2d08eec5), TOBN(0x5fc047a6, 0xcbabae1d), + TOBN(0x0577d159, 0xe54a64bb), TOBN(0x8862201b, 0xc43497e4), + TOBN(0xad6b4e28, 0x2ce0608d), TOBN(0x8b687b7d, 0x0b167aac), + TOBN(0x6ed4d367, 0x8b2ecfa9), TOBN(0x24dfe62d, 0xa90c3c38), + TOBN(0xa1862e10, 0x3fe5c42b), TOBN(0x1ca73dca, 0xd5732a9f), + TOBN(0x35f038b7, 0x76bb87ad), TOBN(0x674976ab, 0xf242b81f), + TOBN(0x4f2bde7e, 0xb0fd90cd), TOBN(0x6efc172e, 0xa7fdf092), + TOBN(0x3806b69b, 0x92222f1f), TOBN(0x5a2459ca, 0x6cf7ae70), + TOBN(0x6789f69c, 0xa85217ee), TOBN(0x5f232b5e, 0xe3dc85ac), + TOBN(0x660e3ec5, 0x48e9e516), TOBN(0x124b4e47, 0x3197eb31), + TOBN(0x10a0cb13, 0xaafcca23), TOBN(0x7bd63ba4, 0x8213224f), + TOBN(0xaffad7cc, 0x290a7f4f), TOBN(0x6b409c9e, 0x0286b461), + TOBN(0x58ab809f, 0xffa407af), TOBN(0xc3122eed, 0xc68ac073), + TOBN(0x17bf9e50, 0x4ef24d7e), TOBN(0x5d929794, 0x3e2a5811), + TOBN(0x519bc867, 0x02902e01), TOBN(0x76bba5da, 0x39c8a851), + TOBN(0xe9f9669c, 0xda94951e), TOBN(0x4b6af58d, 0x66b8d418), + TOBN(0xfa321074, 0x17d426a4), TOBN(0xc78e66a9, 0x9dde6027), + TOBN(0x0516c083, 0x4a53b964), TOBN(0xfc659d38, 0xff602330), + TOBN(0x0ab55e5c, 0x58c5c897), TOBN(0x985099b2, 0x838bc5df), + TOBN(0x061d9efc, 0xc52fc238), TOBN(0x712b2728, 0x6ac1da3f), + TOBN(0xfb658149, 0x9283fe08), TOBN(0x4954ac94, 0xb8aaa2f7), + TOBN(0x85c0ada4, 0x7fb2e74f), TOBN(0xee8ba98e, 0xb89926b0), + TOBN(0xe4f9d37d, 0x23d1af5b), TOBN(0x14ccdbf9, 0xba9b015e), + TOBN(0xb674481b, 0x7bfe7178), TOBN(0x4e1debae, 0x65405868), + TOBN(0x061b2821, 0xc48c867d), TOBN(0x69c15b35, 0x513b30ea), + TOBN(0x3b4a1666, 0x36871088), TOBN(0xe5e29f5d, 0x1220b1ff), + TOBN(0x4b82bb35, 0x233d9f4d), TOBN(0x4e076333, 0x18cdc675)} + , + {TOBN(0x0d53f5c7, 0xa3e6fced), TOBN(0xe8cbbdd5, 0xf45fbdeb), + TOBN(0xf85c01df, 0x13339a70), TOBN(0x0ff71880, 0x142ceb81), + TOBN(0x4c4e8774, 0xbd70437a), TOBN(0x5fb32891, 0xba0bda6a), + TOBN(0x1cdbebd2, 0xf18bd26e), TOBN(0x2f9526f1, 0x03a9d522), + TOBN(0x40ce3051, 0x92c4d684), TOBN(0x8b04d725, 0x7612efcd), + TOBN(0xb9dcda36, 0x6f9cae20), TOBN(0x0edc4d24, 0xf058856c), + TOBN(0x64f2e6bf, 0x85427900), TOBN(0x3de81295, 0xdc09dfea), + TOBN(0xd41b4487, 0x379bf26c), TOBN(0x50b62c6d, 0x6df135a9), + TOBN(0xd4f8e3b4, 0xc72dfe67), TOBN(0xc416b0f6, 0x90e19fdf), + TOBN(0x18b9098d, 0x4c13bd35), TOBN(0xac11118a, 0x15b8cb9e), + TOBN(0xf598a318, 0xf0062841), TOBN(0xbfe0602f, 0x89f356f4), + TOBN(0x7ae3637e, 0x30177a0c), TOBN(0x34097747, 0x61136537), + TOBN(0x0db2fb5e, 0xd005832a), TOBN(0x5f5efd3b, 0x91042e4f), + TOBN(0x8c4ffdc6, 0xed70f8ca), TOBN(0xe4645d0b, 0xb52da9cc), + TOBN(0x9596f58b, 0xc9001d1f), TOBN(0x52c8f0bc, 0x4e117205), + TOBN(0xfd4aa0d2, 0xe398a084), TOBN(0x815bfe3a, 0x104f49de), + TOBN(0x97e5443f, 0x23885e5f), TOBN(0xf72f8f99, 0xe8433aab), + TOBN(0xbd00b154, 0xe4d4e604), TOBN(0xd0b35e6a, 0xe5e173ff), + TOBN(0x57b2a048, 0x9164722d), TOBN(0x3e3c665b, 0x88761ec8), + TOBN(0x6bdd1397, 0x3da83832), TOBN(0x3c8b1a1e, 0x73dafe3b), + TOBN(0x4497ace6, 0x54317cac), TOBN(0xbe600ab9, 0x521771b3), + TOBN(0xb42e409e, 0xb0dfe8b8), TOBN(0x386a67d7, 0x3942310f), + TOBN(0x25548d8d, 0x4431cc28), TOBN(0xa7cff142, 0x985dc524), + TOBN(0x4d60f5a1, 0x93c4be32), TOBN(0x83ebd5c8, 0xd071c6e1), + TOBN(0xba3a80a7, 0xb1fd2b0b), TOBN(0x9b3ad396, 0x5bec33e8), + TOBN(0xb3868d61, 0x79743fb3), TOBN(0xcfd169fc, 0xfdb462fa), + TOBN(0xd3b499d7, 0x9ce0a6af), TOBN(0x55dc1cf1, 0xe42d3ff8), + TOBN(0x04fb9e6c, 0xc6c3e1b2), TOBN(0x47e6961d, 0x6f69a474), + TOBN(0x54eb3acc, 0xe548b37b), TOBN(0xb38e7542, 0x84d40549), + TOBN(0x8c3daa51, 0x7b341b4f), TOBN(0x2f6928ec, 0x690bf7fa), + TOBN(0x0496b323, 0x86ce6c41), TOBN(0x01be1c55, 0x10adadcd), + TOBN(0xc04e67e7, 0x4bb5faf9), TOBN(0x3cbaf678, 0xe15c9985), + TOBN(0x8cd12145, 0x50ca4247), TOBN(0xba1aa47a, 0xe7dd30aa), + TOBN(0x2f81ddf1, 0xe58fee24), TOBN(0x03452936, 0xeec9b0e8), + TOBN(0x8bdc3b81, 0x243aea96), TOBN(0x9a2919af, 0x15c3d0e5), + TOBN(0x9ea640ec, 0x10948361), TOBN(0x5ac86d5b, 0x6e0bcccf), + TOBN(0xf892d918, 0xc36cf440), TOBN(0xaed3e837, 0xc939719c), + TOBN(0xb07b08d2, 0xc0218b64), TOBN(0x6f1bcbba, 0xce9790dd), + TOBN(0x4a84d6ed, 0x60919b8e), TOBN(0xd8900791, 0x8ac1f9eb), + TOBN(0xf84941aa, 0x0dd5daef), TOBN(0xb22fe40a, 0x67fd62c5), + TOBN(0x97e15ba2, 0x157f2db3), TOBN(0xbda2fc8f, 0x8e28ca9c), + TOBN(0x5d050da4, 0x37b9f454), TOBN(0x3d57eb57, 0x2379d72e), + TOBN(0xe9b5eba2, 0xfb5ee997), TOBN(0x01648ca2, 0xe11538ca), + TOBN(0x32bb76f6, 0xf6327974), TOBN(0x338f14b8, 0xff3f4bb7), + TOBN(0x524d226a, 0xd7ab9a2d), TOBN(0x9c00090d, 0x7dfae958), + TOBN(0x0ba5f539, 0x8751d8c2), TOBN(0x8afcbcdd, 0x3ab8262d), + TOBN(0x57392729, 0xe99d043b), TOBN(0xef51263b, 0xaebc943a), + TOBN(0x9feace93, 0x20862935), TOBN(0x639efc03, 0xb06c817b), + TOBN(0x1fe054b3, 0x66b4be7a), TOBN(0x3f25a9de, 0x84a37a1e), + TOBN(0xf39ef1ad, 0x78d75cd9), TOBN(0xd7b58f49, 0x5062c1b5), + TOBN(0x6f74f9a9, 0xff563436), TOBN(0xf718ff29, 0xe8af51e7), + TOBN(0x5234d313, 0x15e97fec), TOBN(0xb6a8e2b1, 0x292f1c0a), + TOBN(0xa7f53aa8, 0x327720c1), TOBN(0x956ca322, 0xba092cc8), + TOBN(0x8f03d64a, 0x28746c4d), TOBN(0x51fe1782, 0x66d0d392), + TOBN(0xd19b34db, 0x3c832c80), TOBN(0x60dccc5c, 0x6da2e3b4), + TOBN(0x245dd62e, 0x0a104ccc), TOBN(0xa7ab1de1, 0x620b21fd), + TOBN(0xb293ae0b, 0x3893d123), TOBN(0xf7b75783, 0xb15ee71c), + TOBN(0x5aa3c614, 0x42a9468b), TOBN(0xd686123c, 0xdb15d744), + TOBN(0x8c616891, 0xa7ab4116), TOBN(0x6fcd72c8, 0xa4e6a459), + TOBN(0xac219110, 0x77e5fad7), TOBN(0xfb6a20e7, 0x704fa46b), + TOBN(0xe839be7d, 0x341d81dc), TOBN(0xcddb6889, 0x32148379), + TOBN(0xda6211a1, 0xf7026ead), TOBN(0xf3b2575f, 0xf4d1cc5e), + TOBN(0x40cfc8f6, 0xa7a73ae6), TOBN(0x83879a5e, 0x61d5b483), + TOBN(0xc5acb1ed, 0x41a50ebc), TOBN(0x59a60cc8, 0x3c07d8fa), + TOBN(0x1b73bdce, 0xb1876262), TOBN(0x2b0d79f0, 0x12af4ee9), + TOBN(0x8bcf3b0b, 0xd46e1d07), TOBN(0x17d6af9d, 0xe45d152f), + TOBN(0x73520461, 0x6d736451), TOBN(0x43cbbd97, 0x56b0bf5a), + TOBN(0xb0833a5b, 0xd5999b9d), TOBN(0x702614f0, 0xeb72e398), + TOBN(0x0aadf01a, 0x59c3e9f8), TOBN(0x40200e77, 0xce6b3d16), + TOBN(0xda22bdd3, 0xdeddafad), TOBN(0x76dedaf4, 0x310d72e1), + TOBN(0x49ef807c, 0x4bc2e88f), TOBN(0x6ba81291, 0x146dd5a5), + TOBN(0xa1a4077a, 0x7d8d59e9), TOBN(0x87b6a2e7, 0x802db349), + TOBN(0xd5679997, 0x1b4e598e), TOBN(0xf499ef1f, 0x06fe4b1d), + TOBN(0x3978d3ae, 0xfcb267c5), TOBN(0xb582b557, 0x235786d0), + TOBN(0x32b3b2ca, 0x1715cb07), TOBN(0x4c3de6a2, 0x8480241d), + TOBN(0x63b5ffed, 0xcb571ecd), TOBN(0xeaf53900, 0xed2fe9a9), + TOBN(0xdec98d4a, 0xc3b81990), TOBN(0x1cb83722, 0x9e0cc8fe), + TOBN(0xfe0b0491, 0xd2b427b9), TOBN(0x0f2386ac, 0xe983a66c), + TOBN(0x930c4d1e, 0xb3291213), TOBN(0xa2f82b2e, 0x59a62ae4), + TOBN(0x77233853, 0xf93e89e3), TOBN(0x7f8063ac, 0x11777c7f), + TOBN(0xff0eb567, 0x59ad2877), TOBN(0x6f454642, 0x9865c754), + TOBN(0xe6fe701a, 0x236e9a84), TOBN(0xc586ef16, 0x06e40fc3), + TOBN(0x3f62b6e0, 0x24bafad9), TOBN(0xc8b42bd2, 0x64da906a), + TOBN(0xc98e1eb4, 0xda3276a0), TOBN(0x30d0e5fc, 0x06cbf852), + TOBN(0x1b6b2ae1, 0xe8b4dfd4), TOBN(0xd754d5c7, 0x8301cbac), + TOBN(0x66097629, 0x112a39ac), TOBN(0xf86b5999, 0x93ba4ab9), + TOBN(0x26c9dea7, 0x99f9d581), TOBN(0x0473b1a8, 0xc2fafeaa), + TOBN(0x1469af55, 0x3b2505a5), TOBN(0x227d16d7, 0xd6a43323), + TOBN(0x3316f73c, 0xad3d97f9), TOBN(0x52bf3bb5, 0x1f137455), + TOBN(0x953eafeb, 0x09954e7c), TOBN(0xa721dfed, 0xdd732411), + TOBN(0xb4929821, 0x141d4579), TOBN(0x3411321c, 0xaa3bd435), + TOBN(0xafb355aa, 0x17fa6015), TOBN(0xb4e7ef4a, 0x18e42f0e), + TOBN(0x604ac97c, 0x59371000), TOBN(0xe1c48c70, 0x7f759c18), + TOBN(0x3f62ecc5, 0xa5db6b65), TOBN(0x0a78b173, 0x38a21495), + TOBN(0x6be1819d, 0xbcc8ad94), TOBN(0x70dc04f6, 0xd89c3400), + TOBN(0x462557b4, 0xa6b4840a), TOBN(0x544c6ade, 0x60bd21c0), + TOBN(0x6a00f24e, 0x907a544b), TOBN(0xa7520dcb, 0x313da210), + TOBN(0xfe939b75, 0x11e4994b), TOBN(0x918b6ba6, 0xbc275d70), + TOBN(0xd3e5e0fc, 0x644be892), TOBN(0x707a9816, 0xfdaf6c42), + TOBN(0x60145567, 0xf15c13fe), TOBN(0x4818ebaa, 0xe130a54a), + TOBN(0x28aad3ad, 0x58d2f767), TOBN(0xdc5267fd, 0xd7e7c773), + TOBN(0x4919cc88, 0xc3afcc98), TOBN(0xaa2e6ab0, 0x2db8cd4b), + TOBN(0xd46fec04, 0xd0c63eaa), TOBN(0xa1cb92c5, 0x19ffa832), + TOBN(0x678dd178, 0xe43a631f), TOBN(0xfb5ae1cd, 0x3dc788b3), + TOBN(0x68b4fb90, 0x6e77de04), TOBN(0x7992bcf0, 0xf06dbb97), + TOBN(0x896e6a13, 0xc417c01d), TOBN(0x8d96332c, 0xb956be01), + TOBN(0x902fc93a, 0x413aa2b9), TOBN(0x99a4d915, 0xfc98c8a5), + TOBN(0x52c29407, 0x565f1137), TOBN(0x4072690f, 0x21e4f281), + TOBN(0x36e607cf, 0x02ff6072), TOBN(0xa47d2ca9, 0x8ad98cdc), + TOBN(0xbf471d1e, 0xf5f56609), TOBN(0xbcf86623, 0xf264ada0), + TOBN(0xb70c0687, 0xaa9e5cb6), TOBN(0xc98124f2, 0x17401c6c), + TOBN(0x8189635f, 0xd4a61435), TOBN(0xd28fb8af, 0xa9d98ea6), + TOBN(0xb9a67c2a, 0x40c251f8), TOBN(0x88cd5d87, 0xa2da44be), + TOBN(0x437deb96, 0xe09b5423), TOBN(0x150467db, 0x64287dc1), + TOBN(0xe161debb, 0xcdabb839), TOBN(0xa79e9742, 0xf1839a3e), + TOBN(0xbb8dd3c2, 0x652d202b), TOBN(0x7b3e67f7, 0xe9f97d96), + TOBN(0x5aa5d78f, 0xb1cb6ac9), TOBN(0xffa13e8e, 0xca1d0d45), + TOBN(0x369295dd, 0x2ba5bf95), TOBN(0xd68bd1f8, 0x39aff05e), + TOBN(0xaf0d86f9, 0x26d783f2), TOBN(0x543a59b3, 0xfc3aafc1), + TOBN(0x3fcf81d2, 0x7b7da97c), TOBN(0xc990a056, 0xd25dee46), + TOBN(0x3e6775b8, 0x519cce2c), TOBN(0xfc9af71f, 0xae13d863), + TOBN(0x774a4a6f, 0x47c1605c), TOBN(0x46ba4245, 0x2fd205e8), + TOBN(0xa06feea4, 0xd3fd524d), TOBN(0x1e724641, 0x6de1acc2), + TOBN(0xf53816f1, 0x334e2b42), TOBN(0x49e5918e, 0x922f0024), + TOBN(0x439530b6, 0x65c7322d), TOBN(0xcf12cc01, 0xb3c1b3fb), + TOBN(0xc70b0186, 0x0172f685), TOBN(0xb915ee22, 0x1b58391d), + TOBN(0x9afdf03b, 0xa317db24), TOBN(0x87dec659, 0x17b8ffc4), + TOBN(0x7f46597b, 0xe4d3d050), TOBN(0x80a1c1ed, 0x006500e7), + TOBN(0x84902a96, 0x78bf030e), TOBN(0xfb5e9c9a, 0x50560148), + TOBN(0x6dae0a92, 0x63362426), TOBN(0xdcaeecf4, 0xa9e30c40), + TOBN(0xc0d887bb, 0x518d0c6b), TOBN(0x99181152, 0xcb985b9d), + TOBN(0xad186898, 0xef7bc381), TOBN(0x18168ffb, 0x9ee46201), + TOBN(0x9a04cdaa, 0x2502753c), TOBN(0xbb279e26, 0x51407c41), + TOBN(0xeacb03aa, 0xf23564e5), TOBN(0x18336582, 0x71e61016), + TOBN(0x8684b8c4, 0xeb809877), TOBN(0xb336e18d, 0xea0e672e), + TOBN(0xefb601f0, 0x34ee5867), TOBN(0x2733edbe, 0x1341cfd1), + TOBN(0xb15e809a, 0x26025c3c), TOBN(0xe6e981a6, 0x9350df88), + TOBN(0x92376237, 0x8502fd8e), TOBN(0x4791f216, 0x0c12be9b), + TOBN(0xb7256789, 0x25f02425), TOBN(0xec863194, 0x7a974443), + TOBN(0x7c0ce882, 0xfb41cc52), TOBN(0xc266ff7e, 0xf25c07f2), + TOBN(0x3d4da8c3, 0x017025f3), TOBN(0xefcf628c, 0xfb9579b4), + TOBN(0x5c4d0016, 0x1f3716ec), TOBN(0x9c27ebc4, 0x6801116e), + TOBN(0x5eba0ea1, 0x1da1767e), TOBN(0xfe151452, 0x47004c57), + TOBN(0x3ace6df6, 0x8c2373b7), TOBN(0x75c3dffe, 0x5dbc37ac), + TOBN(0x3dc32a73, 0xddc925fc), TOBN(0xb679c841, 0x2f65ee0b), + TOBN(0x715a3295, 0x451cbfeb), TOBN(0xd9889768, 0xf76e9a29), + TOBN(0xec20ce7f, 0xb28ad247), TOBN(0xe99146c4, 0x00894d79), + TOBN(0x71457d7c, 0x9f5e3ea7), TOBN(0x097b2662, 0x38030031), + TOBN(0xdb7f6ae6, 0xcf9f82a8), TOBN(0x319decb9, 0x438f473a), + TOBN(0xa63ab386, 0x283856c3), TOBN(0x13e3172f, 0xb06a361b), + TOBN(0x2959f8dc, 0x7d5a006c), TOBN(0x2dbc27c6, 0x75fba752), + TOBN(0xc1227ab2, 0x87c22c9e), TOBN(0x06f61f75, 0x71a268b2), + TOBN(0x1b6bb971, 0x04779ce2), TOBN(0xaca83812, 0x0aadcb1d), + TOBN(0x297ae0bc, 0xaeaab2d5), TOBN(0xa5c14ee7, 0x5bfb9f13), + TOBN(0xaa00c583, 0xf17a62c7), TOBN(0x39eb962c, 0x173759f6), + TOBN(0x1eeba1d4, 0x86c9a88f), TOBN(0x0ab6c37a, 0xdf016c5e), + TOBN(0xa2a147db, 0xa28a0749), TOBN(0x246c20d6, 0xee519165), + TOBN(0x5068d1b1, 0xd3810715), TOBN(0xb1e7018c, 0x748160b9), + TOBN(0x03f5b1fa, 0xf380ff62), TOBN(0xef7fb1dd, 0xf3cb2c1e), + TOBN(0xeab539a8, 0xfc91a7da), TOBN(0x83ddb707, 0xf3f9b561), + TOBN(0xc550e211, 0xfe7df7a4), TOBN(0xa7cd07f2, 0x063f6f40), + TOBN(0xb0de3635, 0x2976879c), TOBN(0xb5f83f85, 0xe55741da), + TOBN(0x4ea9d25e, 0xf3d8ac3d), TOBN(0x6fe2066f, 0x62819f02), + TOBN(0x4ab2b9c2, 0xcef4a564), TOBN(0x1e155d96, 0x5ffa2de3), + TOBN(0x0eb0a19b, 0xc3a72d00), TOBN(0x4037665b, 0x8513c31b), + TOBN(0x2fb2b6bf, 0x04c64637), TOBN(0x45c34d6e, 0x08cdc639), + TOBN(0x56f1e10f, 0xf01fd796), TOBN(0x4dfb8101, 0xfe3667b8), + TOBN(0xe0eda253, 0x9021d0c0), TOBN(0x7a94e9ff, 0x8a06c6ab), + TOBN(0x2d3bb0d9, 0xbb9aa882), TOBN(0xea20e4e5, 0xec05fd10), + TOBN(0xed7eeb5f, 0x1a1ca64e), TOBN(0x2fa6b43c, 0xc6327cbd), + TOBN(0xb577e3cf, 0x3aa91121), TOBN(0x8c6bd5ea, 0x3a34079b), + TOBN(0xd7e5ba39, 0x60e02fc0), TOBN(0xf16dd2c3, 0x90141bf8), + TOBN(0xb57276d9, 0x80101b98), TOBN(0x760883fd, 0xb82f0f66), + TOBN(0x89d7de75, 0x4bc3eff3), TOBN(0x03b60643, 0x5dc2ab40), + TOBN(0xcd6e53df, 0xe05beeac), TOBN(0xf2f1e862, 0xbc3325cd), + TOBN(0xdd0f7921, 0x774f03c3), TOBN(0x97ca7221, 0x4552cc1b), + TOBN(0x5a0d6afe, 0x1cd19f72), TOBN(0xa20915dc, 0xf183fbeb), + TOBN(0x9fda4b40, 0x832c403c), TOBN(0x32738edd, 0xbe425442), + TOBN(0x469a1df6, 0xb5eccf1a), TOBN(0x4b5aff42, 0x28bbe1f0), + TOBN(0x31359d7f, 0x570dfc93), TOBN(0xa18be235, 0xf0088628), + TOBN(0xa5b30fba, 0xb00ed3a9), TOBN(0x34c61374, 0x73cdf8be), + TOBN(0x2c5c5f46, 0xabc56797), TOBN(0x5cecf93d, 0xb82a8ae2), + TOBN(0x7d3dbe41, 0xa968fbf0), TOBN(0xd23d4583, 0x1a5c7f3d), + TOBN(0xf28f69a0, 0xc087a9c7), TOBN(0xc2d75471, 0x474471ca), + TOBN(0x36ec9f4a, 0x4eb732ec), TOBN(0x6c943bbd, 0xb1ca6bed), + TOBN(0xd64535e1, 0xf2457892), TOBN(0x8b84a8ea, 0xf7e2ac06), + TOBN(0xe0936cd3, 0x2499dd5f), TOBN(0x12053d7e, 0x0ed04e57), + TOBN(0x4bdd0076, 0xe4305d9d), TOBN(0x34a527b9, 0x1f67f0a2), + TOBN(0xe79a4af0, 0x9cec46ea), TOBN(0xb15347a1, 0x658b9bc7), + TOBN(0x6bd2796f, 0x35af2f75), TOBN(0xac957990, 0x4051c435), + TOBN(0x2669dda3, 0xc33a655d), TOBN(0x5d503c2e, 0x88514aa3), + TOBN(0xdfa11337, 0x3753dd41), TOBN(0x3f054673, 0x0b754f78), + TOBN(0xbf185677, 0x496125bd), TOBN(0xfb0023c8, 0x3775006c), + TOBN(0xfa0f072f, 0x3a037899), TOBN(0x4222b6eb, 0x0e4aea57), + TOBN(0x3dde5e76, 0x7866d25a), TOBN(0xb6eb04f8, 0x4837aa6f), + TOBN(0x5315591a, 0x2cf1cdb8), TOBN(0x6dfb4f41, 0x2d4e683c), + TOBN(0x7e923ea4, 0x48ee1f3a), TOBN(0x9604d9f7, 0x05a2afd5), + TOBN(0xbe1d4a33, 0x40ea4948), TOBN(0x5b45f1f4, 0xb44cbd2f), + TOBN(0x5faf8376, 0x4acc757e), TOBN(0xa7cf9ab8, 0x63d68ff7), + TOBN(0x8ad62f69, 0xdf0e404b), TOBN(0xd65f33c2, 0x12bdafdf), + TOBN(0xc365de15, 0xa377b14e), TOBN(0x6bf5463b, 0x8e39f60c), + TOBN(0x62030d2d, 0x2ce68148), TOBN(0xd95867ef, 0xe6f843a8), + TOBN(0xd39a0244, 0xef5ab017), TOBN(0x0bd2d8c1, 0x4ab55d12), + TOBN(0xc9503db3, 0x41639169), TOBN(0x2d4e25b0, 0xf7660c8a), + TOBN(0x760cb3b5, 0xe224c5d7), TOBN(0xfa3baf8c, 0x68616919), + TOBN(0x9fbca113, 0x8d142552), TOBN(0x1ab18bf1, 0x7669ebf5), + TOBN(0x55e6f53e, 0x9bdf25dd), TOBN(0x04cc0bf3, 0xcb6cd154), + TOBN(0x595bef49, 0x95e89080), TOBN(0xfe9459a8, 0x104a9ac1), + TOBN(0xad2d89ca, 0xcce9bb32), TOBN(0xddea65e1, 0xf7de8285), + TOBN(0x62ed8c35, 0xb351bd4b), TOBN(0x4150ff36, 0x0c0e19a7), + TOBN(0x86e3c801, 0x345f4e47), TOBN(0x3bf21f71, 0x203a266c), + TOBN(0x7ae110d4, 0x855b1f13), TOBN(0x5d6aaf6a, 0x07262517), + TOBN(0x1e0f12e1, 0x813d28f1), TOBN(0x6000e11d, 0x7ad7a523), + TOBN(0xc7d8deef, 0xc744a17b), TOBN(0x1e990b48, 0x14c05a00), + TOBN(0x68fddaee, 0x93e976d5), TOBN(0x696241d1, 0x46610d63), + TOBN(0xb204e7c3, 0x893dda88), TOBN(0x8bccfa65, 0x6a3a6946), + TOBN(0xb59425b4, 0xc5cd1411), TOBN(0x701b4042, 0xff3658b1), + TOBN(0xe3e56bca, 0x4784cf93), TOBN(0x27de5f15, 0x8fe68d60), + TOBN(0x4ab9cfce, 0xf8d53f19), TOBN(0xddb10311, 0xa40a730d), + TOBN(0x6fa73cd1, 0x4eee0a8a), TOBN(0xfd548748, 0x5249719d), + TOBN(0x49d66316, 0xa8123ef0), TOBN(0x73c32db4, 0xe7f95438), + TOBN(0x2e2ed209, 0x0d9e7854), TOBN(0xf98a9329, 0x9d9f0507), + TOBN(0xc5d33cf6, 0x0c6aa20a), TOBN(0x9a32ba14, 0x75279bb2), + TOBN(0x7e3202cb, 0x774a7307), TOBN(0x64ed4bc4, 0xe8c42dbd), + TOBN(0xc20f1a06, 0xd4caed0d), TOBN(0xb8021407, 0x171d22b3), + TOBN(0xd426ca04, 0xd13268d7), TOBN(0x92377007, 0x25f4d126), + TOBN(0x4204cbc3, 0x71f21a85), TOBN(0x18461b7a, 0xf82369ba), + TOBN(0xc0c07d31, 0x3fc858f9), TOBN(0x5deb5a50, 0xe2bab569), + TOBN(0xd5959d46, 0xd5eea89e), TOBN(0xfdff8424, 0x08437f4b), + TOBN(0xf21071e4, 0x3cfe254f), TOBN(0x72417696, 0x95468321), + TOBN(0x5d8288b9, 0x102cae3e), TOBN(0x2d143e3d, 0xf1965dff), + TOBN(0x00c9a376, 0xa078d847), TOBN(0x6fc0da31, 0x26028731), + TOBN(0xa2baeadf, 0xe45083a2), TOBN(0x66bc7218, 0x5e5b4bcd), + TOBN(0x2c826442, 0xd04b8e7f), TOBN(0xc19f5451, 0x6c4b586b), + TOBN(0x60182c49, 0x5b7eeed5), TOBN(0xd9954ecd, 0x7aa9dfa1), + TOBN(0xa403a8ec, 0xc73884ad), TOBN(0x7fb17de2, 0x9bb39041), + TOBN(0x694b64c5, 0xabb020e8), TOBN(0x3d18c184, 0x19c4eec7), + TOBN(0x9c4673ef, 0x1c4793e5), TOBN(0xc7b8aeb5, 0x056092e6), + TOBN(0x3aa1ca43, 0xf0f8c16b), TOBN(0x224ed5ec, 0xd679b2f6), + TOBN(0x0d56eeaf, 0x55a205c9), TOBN(0xbfe115ba, 0x4b8e028b), + TOBN(0x97e60849, 0x3927f4fe), TOBN(0xf91fbf94, 0x759aa7c5), + TOBN(0x985af769, 0x6be90a51), TOBN(0xc1277b78, 0x78ccb823), + TOBN(0x395b656e, 0xe7a75952), TOBN(0x00df7de0, 0x928da5f5), + TOBN(0x09c23175, 0x4ca4454f), TOBN(0x4ec971f4, 0x7aa2d3c1), + TOBN(0x45c3c507, 0xe75d9ccc), TOBN(0x63b7be8a, 0x3dc90306), + TOBN(0x37e09c66, 0x5db44bdc), TOBN(0x50d60da1, 0x6841c6a2), + TOBN(0x6f9b65ee, 0x08df1b12), TOBN(0x38734879, 0x7ff089df), + TOBN(0x9c331a66, 0x3fe8013d), TOBN(0x017f5de9, 0x5f42fcc8), + TOBN(0x43077866, 0xe8e57567), TOBN(0xc9f781ce, 0xf9fcdb18), + TOBN(0x38131dda, 0x9b12e174), TOBN(0x25d84aa3, 0x8a03752a), + TOBN(0x45e09e09, 0x4d0c0ce2), TOBN(0x1564008b, 0x92bebba5), + TOBN(0xf7e8ad31, 0xa87284c7), TOBN(0xb7c4b46c, 0x97e7bbaa), + TOBN(0x3e22a7b3, 0x97acf4ec), TOBN(0x0426c400, 0x5ea8b640), + TOBN(0x5e3295a6, 0x4e969285), TOBN(0x22aabc59, 0xa6a45670), + TOBN(0xb929714c, 0x5f5942bc), TOBN(0x9a6168bd, 0xfa3182ed), + TOBN(0x2216a665, 0x104152ba), TOBN(0x46908d03, 0xb6926368)} + , + {TOBN(0xa9f5d874, 0x5a1251fb), TOBN(0x967747a8, 0xc72725c7), + TOBN(0x195c33e5, 0x31ffe89e), TOBN(0x609d210f, 0xe964935e), + TOBN(0xcafd6ca8, 0x2fe12227), TOBN(0xaf9b5b96, 0x0426469d), + TOBN(0x2e9ee04c, 0x5693183c), TOBN(0x1084a333, 0xc8146fef), + TOBN(0x96649933, 0xaed1d1f7), TOBN(0x566eaff3, 0x50563090), + TOBN(0x345057f0, 0xad2e39cf), TOBN(0x148ff65b, 0x1f832124), + TOBN(0x042e89d4, 0xcf94cf0d), TOBN(0x319bec84, 0x520c58b3), + TOBN(0x2a267626, 0x5361aa0d), TOBN(0xc86fa302, 0x8fbc87ad), + TOBN(0xfc83d2ab, 0x5c8b06d5), TOBN(0xb1a785a2, 0xfe4eac46), + TOBN(0xb99315bc, 0x846f7779), TOBN(0xcf31d816, 0xef9ea505), + TOBN(0x2391fe6a, 0x15d7dc85), TOBN(0x2f132b04, 0xb4016b33), + TOBN(0x29547fe3, 0x181cb4c7), TOBN(0xdb66d8a6, 0x650155a1), + TOBN(0x6b66d7e1, 0xadc1696f), TOBN(0x98ebe593, 0x0acd72d0), + TOBN(0x65f24550, 0xcc1b7435), TOBN(0xce231393, 0xb4b9a5ec), + TOBN(0x234a22d4, 0xdb067df9), TOBN(0x98dda095, 0xcaff9b00), + TOBN(0x1bbc75a0, 0x6100c9c1), TOBN(0x1560a9c8, 0x939cf695), + TOBN(0xcf006d3e, 0x99e0925f), TOBN(0x2dd74a96, 0x6322375a), + TOBN(0xc58b446a, 0xb56af5ba), TOBN(0x50292683, 0xe0b9b4f1), + TOBN(0xe2c34cb4, 0x1aeaffa3), TOBN(0x8b17203f, 0x9b9587c1), + TOBN(0x6d559207, 0xead1350c), TOBN(0x2b66a215, 0xfb7f9604), + TOBN(0x0850325e, 0xfe51bf74), TOBN(0x9c4f579e, 0x5e460094), + TOBN(0x5c87b92a, 0x76da2f25), TOBN(0x889de4e0, 0x6febef33), + TOBN(0x6900ec06, 0x646083ce), TOBN(0xbe2a0335, 0xbfe12773), + TOBN(0xadd1da35, 0xc5344110), TOBN(0x757568b7, 0xb802cd20), + TOBN(0x75559779, 0x00f7e6c8), TOBN(0x38e8b94f, 0x0facd2f0), + TOBN(0xfea1f3af, 0x03fde375), TOBN(0x5e11a1d8, 0x75881dfc), + TOBN(0xb3a6b02e, 0xc1e2f2ef), TOBN(0x193d2bbb, 0xc605a6c5), + TOBN(0x325ffeee, 0x339a0b2d), TOBN(0x27b6a724, 0x9e0c8846), + TOBN(0xe4050f1c, 0xf1c367ca), TOBN(0x9bc85a9b, 0xc90fbc7d), + TOBN(0xa373c4a2, 0xe1a11032), TOBN(0xb64232b7, 0xad0393a9), + TOBN(0xf5577eb0, 0x167dad29), TOBN(0x1604f301, 0x94b78ab2), + TOBN(0x0baa94af, 0xe829348b), TOBN(0x77fbd8dd, 0x41654342), + TOBN(0xdab50ea5, 0xb964e39a), TOBN(0xd4c29e3c, 0xd0d3c76e), + TOBN(0x80dae67c, 0x56d11964), TOBN(0x7307a8bf, 0xe5ffcc2f), + TOBN(0x65bbc1aa, 0x91708c3b), TOBN(0xa151e62c, 0x28bf0eeb), + TOBN(0x6cb53381, 0x6fa34db7), TOBN(0x5139e05c, 0xa29403a8), + TOBN(0x6ff651b4, 0x94a7cd2e), TOBN(0x5671ffd1, 0x0699336c), + TOBN(0x6f5fd2cc, 0x979a896a), TOBN(0x11e893a8, 0xd8148cef), + TOBN(0x988906a1, 0x65cf7b10), TOBN(0x81b67178, 0xc50d8485), + TOBN(0x7c0deb35, 0x8a35b3de), TOBN(0x423ac855, 0xc1d29799), + TOBN(0xaf580d87, 0xdac50b74), TOBN(0x28b2b89f, 0x5869734c), + TOBN(0x99a3b936, 0x874e28fb), TOBN(0xbb2c9190, 0x25f3f73a), + TOBN(0x199f6918, 0x84a9d5b7), TOBN(0x7ebe2325, 0x7e770374), + TOBN(0xf442e107, 0x0738efe2), TOBN(0xcf9f3f56, 0xcf9082d2), + TOBN(0x719f69e1, 0x09618708), TOBN(0xcc9e8364, 0xc183f9b1), + TOBN(0xec203a95, 0x366a21af), TOBN(0x6aec5d6d, 0x068b141f), + TOBN(0xee2df78a, 0x994f04e9), TOBN(0xb39ccae8, 0x271245b0), + TOBN(0xb875a4a9, 0x97e43f4f), TOBN(0x507dfe11, 0xdb2cea98), + TOBN(0x4fbf81cb, 0x489b03e9), TOBN(0xdb86ec5b, 0x6ec414fa), + TOBN(0xfad444f9, 0xf51b3ae5), TOBN(0xca7d33d6, 0x1914e3fe), + TOBN(0xa9c32f5c, 0x0ae6c4d0), TOBN(0xa9ca1d1e, 0x73969568), + TOBN(0x98043c31, 0x1aa7467e), TOBN(0xe832e75c, 0xe21b5ac6), + TOBN(0x314b7aea, 0x5232123d), TOBN(0x08307c8c, 0x65ae86db), + TOBN(0x06e7165c, 0xaa4668ed), TOBN(0xb170458b, 0xb4d3ec39), + TOBN(0x4d2e3ec6, 0xc19bb986), TOBN(0xc5f34846, 0xae0304ed), + TOBN(0x917695a0, 0x6c9f9722), TOBN(0x6c7f7317, 0x4cab1c0a), + TOBN(0x6295940e, 0x9d6d2e8b), TOBN(0xd318b8c1, 0x549f7c97), + TOBN(0x22453204, 0x97713885), TOBN(0x468d834b, 0xa8a440fe), + TOBN(0xd81fe5b2, 0xbfba796e), TOBN(0x152364db, 0x6d71f116), + TOBN(0xbb8c7c59, 0xb5b66e53), TOBN(0x0b12c61b, 0x2641a192), + TOBN(0x31f14802, 0xfcf0a7fd), TOBN(0x42fd0789, 0x5488b01e), + TOBN(0x71d78d6d, 0x9952b498), TOBN(0x8eb572d9, 0x07ac5201), + TOBN(0xe0a2a44c, 0x4d194a88), TOBN(0xd2b63fd9, 0xba017e66), + TOBN(0x78efc6c8, 0xf888aefc), TOBN(0xb76f6bda, 0x4a881a11), + TOBN(0x187f314b, 0xb46c2397), TOBN(0x004cf566, 0x5ded2819), + TOBN(0xa9ea5704, 0x38764d34), TOBN(0xbba45217, 0x78084709), + TOBN(0x06474571, 0x1171121e), TOBN(0xad7b7eb1, 0xe7c9b671), + TOBN(0xdacfbc40, 0x730f7507), TOBN(0x178cd8c6, 0xc7ad7bd1), + TOBN(0xbf0be101, 0xb2a67238), TOBN(0x3556d367, 0xaf9c14f2), + TOBN(0x104b7831, 0xa5662075), TOBN(0x58ca59bb, 0x79d9e60a), + TOBN(0x4bc45392, 0xa569a73b), TOBN(0x517a52e8, 0x5698f6c9), + TOBN(0x85643da5, 0xaeadd755), TOBN(0x1aed0cd5, 0x2a581b84), + TOBN(0xb9b4ff84, 0x80af1372), TOBN(0x244c3113, 0xf1ba5d1f), + TOBN(0x2a5dacbe, 0xf5f98d31), TOBN(0x2c3323e8, 0x4375bc2a), + TOBN(0x17a3ab4a, 0x5594b1dd), TOBN(0xa1928bfb, 0xceb4797e), + TOBN(0xe83af245, 0xe4886a19), TOBN(0x8979d546, 0x72b5a74a), + TOBN(0xa0f726bc, 0x19f9e967), TOBN(0xd9d03152, 0xe8fbbf4e), + TOBN(0xcfd6f51d, 0xb7707d40), TOBN(0x633084d9, 0x63f6e6e0), + TOBN(0xedcd9cdc, 0x55667eaf), TOBN(0x73b7f92b, 0x2e44d56f), + TOBN(0xfb2e39b6, 0x4e962b14), TOBN(0x7d408f6e, 0xf671fcbf), + TOBN(0xcc634ddc, 0x164a89bb), TOBN(0x74a42bb2, 0x3ef3bd05), + TOBN(0x1280dbb2, 0x428decbb), TOBN(0x6103f6bb, 0x402c8596), + TOBN(0xfa2bf581, 0x355a5752), TOBN(0x562f96a8, 0x00946674), + TOBN(0x4e4ca16d, 0x6da0223b), TOBN(0xfe47819f, 0x28d3aa25), + TOBN(0x9eea3075, 0xf8dfcf8a), TOBN(0xa284f0aa, 0x95669825), + TOBN(0xb3fca250, 0x867d3fd8), TOBN(0x20757b5f, 0x269d691e), + TOBN(0xf2c24020, 0x93b8a5de), TOBN(0xd3f93359, 0xebc06da6), + TOBN(0x1178293e, 0xb2739c33), TOBN(0xd2a3e770, 0xbcd686e5), + TOBN(0xa76f49f4, 0xcd941534), TOBN(0x0d37406b, 0xe3c71c0e), + TOBN(0x172d9397, 0x3b97f7e3), TOBN(0xec17e239, 0xbd7fd0de), + TOBN(0xe3290551, 0x6f496ba2), TOBN(0x6a693172, 0x36ad50e7), + TOBN(0xc4e539a2, 0x83e7eff5), TOBN(0x752737e7, 0x18e1b4cf), + TOBN(0xa2f7932c, 0x68af43ee), TOBN(0x5502468e, 0x703d00bd), + TOBN(0xe5dc978f, 0x2fb061f5), TOBN(0xc9a1904a, 0x28c815ad), + TOBN(0xd3af538d, 0x470c56a4), TOBN(0x159abc5f, 0x193d8ced), + TOBN(0x2a37245f, 0x20108ef3), TOBN(0xfa17081e, 0x223f7178), + TOBN(0x27b0fb2b, 0x10c8c0f5), TOBN(0x2102c3ea, 0x40650547), + TOBN(0x594564df, 0x8ac3bfa7), TOBN(0x98102033, 0x509dad96), + TOBN(0x6989643f, 0xf1d18a13), TOBN(0x35eebd91, 0xd7fc5af0), + TOBN(0x078d096a, 0xfaeaafd8), TOBN(0xb7a89341, 0xdef3de98), + TOBN(0x2a206e8d, 0xecf2a73a), TOBN(0x066a6397, 0x8e551994), + TOBN(0x3a6a088a, 0xb98d53a2), TOBN(0x0ce7c67c, 0x2d1124aa), + TOBN(0x48cec671, 0x759a113c), TOBN(0xe3b373d3, 0x4f6f67fa), + TOBN(0x5455d479, 0xfd36727b), TOBN(0xe5a428ee, 0xa13c0d81), + TOBN(0xb853dbc8, 0x1c86682b), TOBN(0xb78d2727, 0xb8d02b2a), + TOBN(0xaaf69bed, 0x8ebc329a), TOBN(0xdb6b40b3, 0x293b2148), + TOBN(0xe42ea77d, 0xb8c4961f), TOBN(0xb1a12f7c, 0x20e5e0ab), + TOBN(0xa0ec5274, 0x79e8b05e), TOBN(0x68027391, 0xfab60a80), + TOBN(0x6bfeea5f, 0x16b1bd5e), TOBN(0xf957e420, 0x4de30ad3), + TOBN(0xcbaf664e, 0x6a353b9e), TOBN(0x5c873312, 0x26d14feb), + TOBN(0x4e87f98c, 0xb65f57cb), TOBN(0xdb60a621, 0x5e0cdd41), + TOBN(0x67c16865, 0xa6881440), TOBN(0x1093ef1a, 0x46ab52aa), + TOBN(0xc095afb5, 0x3f4ece64), TOBN(0x6a6bb02e, 0x7604551a), + TOBN(0x55d44b4e, 0x0b26b8cd), TOBN(0xe5f9a999, 0xf971268a), + TOBN(0xc08ec425, 0x11a7de84), TOBN(0x83568095, 0xfda469dd), + TOBN(0x737bfba1, 0x6c6c90a2), TOBN(0x1cb9c4a0, 0xbe229831), + TOBN(0x93bccbba, 0xbb2eec64), TOBN(0xa0c23b64, 0xda03adbe), + TOBN(0x5f7aa00a, 0xe0e86ac4), TOBN(0x470b941e, 0xfc1401e6), + TOBN(0x5ad8d679, 0x9df43574), TOBN(0x4ccfb8a9, 0x0f65d810), + TOBN(0x1bce80e3, 0xaa7fbd81), TOBN(0x273291ad, 0x9508d20a), + TOBN(0xf5c4b46b, 0x42a92806), TOBN(0x810684ec, 0xa86ab44a), + TOBN(0x4591640b, 0xca0bc9f8), TOBN(0xb5efcdfc, 0x5c4b6054), + TOBN(0x16fc8907, 0x6e9edd12), TOBN(0xe29d0b50, 0xd4d792f9), + TOBN(0xa45fd01c, 0x9b03116d), TOBN(0x85035235, 0xc81765a4), + TOBN(0x1fe2a9b2, 0xb4b4b67c), TOBN(0xc1d10df0, 0xe8020604), + TOBN(0x9d64abfc, 0xbc8058d8), TOBN(0x8943b9b2, 0x712a0fbb), + TOBN(0x90eed914, 0x3b3def04), TOBN(0x85ab3aa2, 0x4ce775ff), + TOBN(0x605fd4ca, 0x7bbc9040), TOBN(0x8b34a564, 0xe2c75dfb), + TOBN(0x41ffc94a, 0x10358560), TOBN(0x2d8a5072, 0x9e5c28aa), + TOBN(0xe915a0fc, 0x4cc7eb15), TOBN(0xe9efab05, 0x8f6d0f5d), + TOBN(0xdbab47a9, 0xd19e9b91), TOBN(0x8cfed745, 0x0276154c), + TOBN(0x154357ae, 0x2cfede0d), TOBN(0x520630df, 0x19f5a4ef), + TOBN(0x25759f7c, 0xe382360f), TOBN(0xb6db05c9, 0x88bf5857), + TOBN(0x2917d61d, 0x6c58d46c), TOBN(0x14f8e491, 0xfd20cb7a), + TOBN(0xb68a727a, 0x11c20340), TOBN(0x0386f86f, 0xaf7ccbb6), + TOBN(0x5c8bc6cc, 0xfee09a20), TOBN(0x7d76ff4a, 0xbb7eea35), + TOBN(0xa7bdebe7, 0xdb15be7a), TOBN(0x67a08054, 0xd89f0302), + TOBN(0x56bf0ea9, 0xc1193364), TOBN(0xc8244467, 0x62837ebe), + TOBN(0x32bd8e8b, 0x20d841b8), TOBN(0x127a0548, 0xdbb8a54f), + TOBN(0x83dd4ca6, 0x63b20236), TOBN(0x87714718, 0x203491fa), + TOBN(0x4dabcaaa, 0xaa8a5288), TOBN(0x91cc0c8a, 0xaf23a1c9), + TOBN(0x34c72c6a, 0x3f220e0c), TOBN(0xbcc20bdf, 0x1232144a), + TOBN(0x6e2f42da, 0xa20ede1b), TOBN(0xc441f00c, 0x74a00515), + TOBN(0xbf46a5b6, 0x734b8c4b), TOBN(0x57409503, 0x7b56c9a4), + TOBN(0x9f735261, 0xe4585d45), TOBN(0x9231faed, 0x6734e642), + TOBN(0x1158a176, 0xbe70ee6c), TOBN(0x35f1068d, 0x7c3501bf), + TOBN(0x6beef900, 0xa2d26115), TOBN(0x649406f2, 0xef0afee3), + TOBN(0x3f43a60a, 0xbc2420a1), TOBN(0x509002a7, 0xd5aee4ac), + TOBN(0xb46836a5, 0x3ff3571b), TOBN(0x24f98b78, 0x837927c1), + TOBN(0x6254256a, 0x4533c716), TOBN(0xf27abb0b, 0xd07ee196), + TOBN(0xd7cf64fc, 0x5c6d5bfd), TOBN(0x6915c751, 0xf0cd7a77), + TOBN(0xd9f59012, 0x8798f534), TOBN(0x772b0da8, 0xf81d8b5f), + TOBN(0x1244260c, 0x2e03fa69), TOBN(0x36cf0e3a, 0x3be1a374), + TOBN(0x6e7c1633, 0xef06b960), TOBN(0xa71a4c55, 0x671f90f6), + TOBN(0x7a941251, 0x33c673db), TOBN(0xc0bea510, 0x73e8c131), + TOBN(0x61a8a699, 0xd4f6c734), TOBN(0x25e78c88, 0x341ed001), + TOBN(0x5c18acf8, 0x8e2f7d90), TOBN(0xfdbf33d7, 0x77be32cd), + TOBN(0x0a085cd7, 0xd2eb5ee9), TOBN(0x2d702cfb, 0xb3201115), + TOBN(0xb6e0ebdb, 0x85c88ce8), TOBN(0x23a3ce3c, 0x1e01d617), + TOBN(0x3041618e, 0x567333ac), TOBN(0x9dd0fd8f, 0x157edb6b), + TOBN(0x27f74702, 0xb57872b8), TOBN(0x2ef26b4f, 0x657d5fe1), + TOBN(0x95426f0a, 0x57cf3d40), TOBN(0x847e2ad1, 0x65a6067a), + TOBN(0xd474d9a0, 0x09996a74), TOBN(0x16a56acd, 0x2a26115c), + TOBN(0x02a615c3, 0xd16f4d43), TOBN(0xcc3fc965, 0xaadb85b7), + TOBN(0x386bda73, 0xce07d1b0), TOBN(0xd82910c2, 0x58ad4178), + TOBN(0x124f82cf, 0xcd2617f4), TOBN(0xcc2f5e8d, 0xef691770), + TOBN(0x82702550, 0xb8c30ccc), TOBN(0x7b856aea, 0x1a8e575a), + TOBN(0xbb822fef, 0xb1ab9459), TOBN(0x085928bc, 0xec24e38e), + TOBN(0x5d0402ec, 0xba8f4b4d), TOBN(0xc07cd4ba, 0x00b4d58b), + TOBN(0x5d8dffd5, 0x29227e7a), TOBN(0x61d44d0c, 0x31bf386f), + TOBN(0xe486dc2b, 0x135e6f4d), TOBN(0x680962eb, 0xe79410ef), + TOBN(0xa61bd343, 0xf10088b5), TOBN(0x6aa76076, 0xe2e28686), + TOBN(0x80463d11, 0x8fb98871), TOBN(0xcb26f5c3, 0xbbc76aff), + TOBN(0xd4ab8edd, 0xfbe03614), TOBN(0xc8eb579b, 0xc0cf2dee), + TOBN(0xcc004c15, 0xc93bae41), TOBN(0x46fbae5d, 0x3aeca3b2), + TOBN(0x671235cf, 0x0f1e9ab1), TOBN(0xadfba934, 0x9ec285c1), + TOBN(0x88ded013, 0xf216c980), TOBN(0xc8ac4fb8, 0xf79e0bc1), + TOBN(0xa29b89c6, 0xfb97a237), TOBN(0xb697b780, 0x9922d8e7), + TOBN(0x3142c639, 0xddb945b5), TOBN(0x447b06c7, 0xe094c3a9), + TOBN(0xcdcb3642, 0x72266c90), TOBN(0x633aad08, 0xa9385046), + TOBN(0xa36c936b, 0xb57c6477), TOBN(0x871f8b64, 0xe94dbcc6), + TOBN(0x28d0fb62, 0xa591a67b), TOBN(0x9d40e081, 0xc1d926f5), + TOBN(0x3111eaf6, 0xf2d84b5a), TOBN(0x228993f9, 0xa565b644), + TOBN(0x0ccbf592, 0x2c83188b), TOBN(0xf87b30ab, 0x3df3e197), + TOBN(0xb8658b31, 0x7642bca8), TOBN(0x1a032d7f, 0x52800f17), + TOBN(0x051dcae5, 0x79bf9445), TOBN(0xeba6b8ee, 0x54a2e253), + TOBN(0x5c8b9cad, 0xd4485692), TOBN(0x84bda40e, 0x8986e9be), + TOBN(0xd16d16a4, 0x2f0db448), TOBN(0x8ec80050, 0xa14d4188), + TOBN(0xb2b26107, 0x98fa7aaa), TOBN(0x41209ee4, 0xf073aa4e), + TOBN(0xf1570359, 0xf2d6b19b), TOBN(0xcbe6868c, 0xfc577caf), + TOBN(0x186c4bdc, 0x32c04dd3), TOBN(0xa6c35fae, 0xcfeee397), + TOBN(0xb4a1b312, 0xf086c0cf), TOBN(0xe0a5ccc6, 0xd9461fe2), + TOBN(0xc32278aa, 0x1536189f), TOBN(0x1126c55f, 0xba6df571), + TOBN(0x0f71a602, 0xb194560e), TOBN(0x8b2d7405, 0x324bd6e1), + TOBN(0x8481939e, 0x3738be71), TOBN(0xb5090b1a, 0x1a4d97a9), + TOBN(0x116c65a3, 0xf05ba915), TOBN(0x21863ad3, 0xaae448aa), + TOBN(0xd24e2679, 0xa7aae5d3), TOBN(0x7076013d, 0x0de5c1c4), + TOBN(0x2d50f8ba, 0xbb05b629), TOBN(0x73c1abe2, 0x6e66efbb), + TOBN(0xefd4b422, 0xf2488af7), TOBN(0xe4105d02, 0x663ba575), + TOBN(0x7eb60a8b, 0x53a69457), TOBN(0x62210008, 0xc945973b), + TOBN(0xfb255478, 0x77a50ec6), TOBN(0xbf0392f7, 0x0a37a72c), + TOBN(0xa0a7a19c, 0x4be18e7a), TOBN(0x90d8ea16, 0x25b1e0af), + TOBN(0x7582a293, 0xef953f57), TOBN(0x90a64d05, 0xbdc5465a), + TOBN(0xca79c497, 0xe2510717), TOBN(0x560dbb7c, 0x18cb641f), + TOBN(0x1d8e3286, 0x4b66abfb), TOBN(0xd26f52e5, 0x59030900), + TOBN(0x1ee3f643, 0x5584941a), TOBN(0x6d3b3730, 0x569f5958), + TOBN(0x9ff2a62f, 0x4789dba5), TOBN(0x91fcb815, 0x72b5c9b7), + TOBN(0xf446cb7d, 0x6c8f9a0e), TOBN(0x48f625c1, 0x39b7ecb5), + TOBN(0xbabae801, 0x1c6219b8), TOBN(0xe7a562d9, 0x28ac2f23), + TOBN(0xe1b48732, 0x26e20588), TOBN(0x06ee1cad, 0x775af051), + TOBN(0xda29ae43, 0xfaff79f7), TOBN(0xc141a412, 0x652ee9e0), + TOBN(0x1e127f6f, 0x195f4bd0), TOBN(0x29c6ab4f, 0x072f34f8), + TOBN(0x7b7c1477, 0x30448112), TOBN(0x82b51af1, 0xe4a38656), + TOBN(0x2bf2028a, 0x2f315010), TOBN(0xc9a4a01f, 0x6ea88cd4), + TOBN(0xf63e95d8, 0x257e5818), TOBN(0xdd8efa10, 0xb4519b16), + TOBN(0xed8973e0, 0x0da910bf), TOBN(0xed49d077, 0x5c0fe4a9), + TOBN(0xac3aac5e, 0xb7caee1e), TOBN(0x1033898d, 0xa7f4da57), + TOBN(0x42145c0e, 0x5c6669b9), TOBN(0x42daa688, 0xc1aa2aa0), + TOBN(0x629cc15c, 0x1a1d885a), TOBN(0x25572ec0, 0xf4b76817), + TOBN(0x8312e435, 0x9c8f8f28), TOBN(0x8107f8cd, 0x81965490), + TOBN(0x516ff3a3, 0x6fa6110c), TOBN(0x74fb1eb1, 0xfb93561f), + TOBN(0x6c0c9047, 0x8457522b), TOBN(0xcfd32104, 0x6bb8bdc6), + TOBN(0x2d6884a2, 0xcc80ad57), TOBN(0x7c27fc35, 0x86a9b637), + TOBN(0x3461baed, 0xadf4e8cd), TOBN(0x1d56251a, 0x617242f0), + TOBN(0x0b80d209, 0xc955bef4), TOBN(0xdf02cad2, 0x06adb047), + TOBN(0xf0d7cb91, 0x5ec74fee), TOBN(0xd2503375, 0x1111ba44), + TOBN(0x9671755e, 0xdf53cb36), TOBN(0x54dcb612, 0x3368551b), + TOBN(0x66d69aac, 0xc8a025a4), TOBN(0x6be946c6, 0xe77ef445), + TOBN(0x719946d1, 0xa995e094), TOBN(0x65e848f6, 0xe51e04d8), + TOBN(0xe62f3300, 0x6a1e3113), TOBN(0x1541c7c1, 0x501de503), + TOBN(0x4daac9fa, 0xf4acfade), TOBN(0x0e585897, 0x44cd0b71), + TOBN(0x544fd869, 0x0a51cd77), TOBN(0x60fc20ed, 0x0031016d), + TOBN(0x58b404ec, 0xa4276867), TOBN(0x46f6c3cc, 0x34f34993), + TOBN(0x477ca007, 0xc636e5bd), TOBN(0x8018f5e5, 0x7c458b47), + TOBN(0xa1202270, 0xe47b668f), TOBN(0xcef48ccd, 0xee14f203), + TOBN(0x23f98bae, 0x62ff9b4d), TOBN(0x55acc035, 0xc589eddd), + TOBN(0x3fe712af, 0x64db4444), TOBN(0x19e9d634, 0xbecdd480), + TOBN(0xe08bc047, 0xa930978a), TOBN(0x2dbf24ec, 0xa1280733), + TOBN(0x3c0ae38c, 0x2cd706b2), TOBN(0x5b012a5b, 0x359017b9), + TOBN(0x3943c38c, 0x72e0f5ae), TOBN(0x786167ea, 0x57176fa3), + TOBN(0xe5f9897d, 0x594881dc), TOBN(0x6b5efad8, 0xcfb820c1), + TOBN(0xb2179093, 0xd55018de), TOBN(0x39ad7d32, 0x0bac56ce), + TOBN(0xb55122e0, 0x2cfc0e81), TOBN(0x117c4661, 0xf6d89daa), + TOBN(0x362d01e1, 0xcb64fa09), TOBN(0x6a309b4e, 0x3e9c4ddd), + TOBN(0xfa979fb7, 0xabea49b1), TOBN(0xb4b1d27d, 0x10e2c6c5), + TOBN(0xbd61c2c4, 0x23afde7a), TOBN(0xeb6614f8, 0x9786d358), + TOBN(0x4a5d816b, 0x7f6f7459), TOBN(0xe431a44f, 0x09360e7b), + TOBN(0x8c27a032, 0xc309914c), TOBN(0xcea5d68a, 0xcaede3d8), + TOBN(0x3668f665, 0x3a0a3f95), TOBN(0x89369416, 0x7ceba27b), + TOBN(0x89981fad, 0xe4728fe9), TOBN(0x7102c8a0, 0x8a093562), + TOBN(0xbb80310e, 0x235d21c8), TOBN(0x505e55d1, 0xbefb7f7b), + TOBN(0xa0a90811, 0x12958a67), TOBN(0xd67e106a, 0x4d851fef), + TOBN(0xb84011a9, 0x431dd80e), TOBN(0xeb7c7cca, 0x73306cd9), + TOBN(0x20fadd29, 0xd1b3b730), TOBN(0x83858b5b, 0xfe37b3d3), + TOBN(0xbf4cd193, 0xb6251d5c), TOBN(0x1cca1fd3, 0x1352d952), + TOBN(0xc66157a4, 0x90fbc051), TOBN(0x7990a638, 0x89b98636),} + , + {TOBN(0xe5aa692a, 0x87dec0e1), TOBN(0x010ded8d, 0xf7b39d00), + TOBN(0x7b1b80c8, 0x54cfa0b5), TOBN(0x66beb876, 0xa0f8ea28), + TOBN(0x50d7f531, 0x3476cd0e), TOBN(0xa63d0e65, 0xb08d3949), + TOBN(0x1a09eea9, 0x53479fc6), TOBN(0x82ae9891, 0xf499e742), + TOBN(0xab58b910, 0x5ca7d866), TOBN(0x582967e2, 0x3adb3b34), + TOBN(0x89ae4447, 0xcceac0bc), TOBN(0x919c667c, 0x7bf56af5), + TOBN(0x9aec17b1, 0x60f5dcd7), TOBN(0xec697b9f, 0xddcaadbc), + TOBN(0x0b98f341, 0x463467f5), TOBN(0xb187f1f7, 0xa967132f), + TOBN(0x90fe7a1d, 0x214aeb18), TOBN(0x1506af3c, 0x741432f7), + TOBN(0xbb5565f9, 0xe591a0c4), TOBN(0x10d41a77, 0xb44f1bc3), + TOBN(0xa09d65e4, 0xa84bde96), TOBN(0x42f060d8, 0xf20a6a1c), + TOBN(0x652a3bfd, 0xf27f9ce7), TOBN(0xb6bdb65c, 0x3b3d739f), + TOBN(0xeb5ddcb6, 0xec7fae9f), TOBN(0x995f2714, 0xefb66e5a), + TOBN(0xdee95d8e, 0x69445d52), TOBN(0x1b6c2d46, 0x09e27620), + TOBN(0x32621c31, 0x8129d716), TOBN(0xb03909f1, 0x0958c1aa), + TOBN(0x8c468ef9, 0x1af4af63), TOBN(0x162c429f, 0xfba5cdf6), + TOBN(0x2f682343, 0x753b9371), TOBN(0x29cab45a, 0x5f1f9cd7), + TOBN(0x571623ab, 0xb245db96), TOBN(0xc507db09, 0x3fd79999), + TOBN(0x4e2ef652, 0xaf036c32), TOBN(0x86f0cc78, 0x05018e5c), + TOBN(0xc10a73d4, 0xab8be350), TOBN(0x6519b397, 0x7e826327), + TOBN(0xe8cb5eef, 0x9c053df7), TOBN(0x8de25b37, 0xb300ea6f), + TOBN(0xdb03fa92, 0xc849cffb), TOBN(0x242e43a7, 0xe84169bb), + TOBN(0xe4fa51f4, 0xdd6f958e), TOBN(0x6925a77f, 0xf4445a8d), + TOBN(0xe6e72a50, 0xe90d8949), TOBN(0xc66648e3, 0x2b1f6390), + TOBN(0xb2ab1957, 0x173e460c), TOBN(0x1bbbce75, 0x30704590), + TOBN(0xc0a90dbd, 0xdb1c7162), TOBN(0x505e399e, 0x15cdd65d), + TOBN(0x68434dcb, 0x57797ab7), TOBN(0x60ad35ba, 0x6a2ca8e8), + TOBN(0x4bfdb1e0, 0xde3336c1), TOBN(0xbbef99eb, 0xd8b39015), + TOBN(0x6c3b96f3, 0x1711ebec), TOBN(0x2da40f1f, 0xce98fdc4), + TOBN(0xb99774d3, 0x57b4411f), TOBN(0x87c8bdf4, 0x15b65bb6), + TOBN(0xda3a89e3, 0xc2eef12d), TOBN(0xde95bb9b, 0x3c7471f3), + TOBN(0x600f225b, 0xd812c594), TOBN(0x54907c5d, 0x2b75a56b), + TOBN(0xa93cc5f0, 0x8db60e35), TOBN(0x743e3cd6, 0xfa833319), + TOBN(0x7dad5c41, 0xf81683c9), TOBN(0x70c1e7d9, 0x9c34107e), + TOBN(0x0edc4a39, 0xa6be0907), TOBN(0x36d47035, 0x86d0b7d3), + TOBN(0x8c76da03, 0x272bfa60), TOBN(0x0b4a07ea, 0x0f08a414), + TOBN(0x699e4d29, 0x45c1dd53), TOBN(0xcadc5898, 0x231debb5), + TOBN(0xdf49fcc7, 0xa77f00e0), TOBN(0x93057bbf, 0xa73e5a0e), + TOBN(0x2f8b7ecd, 0x027a4cd1), TOBN(0x114734b3, 0xc614011a), + TOBN(0xe7a01db7, 0x67677c68), TOBN(0x89d9be5e, 0x7e273f4f), + TOBN(0xd225cb2e, 0x089808ef), TOBN(0xf1f7a27d, 0xd59e4107), + TOBN(0x53afc761, 0x8211b9c9), TOBN(0x0361bc67, 0xe6819159), + TOBN(0x2a865d0b, 0x7f071426), TOBN(0x6a3c1810, 0xe7072567), + TOBN(0x3e3bca1e, 0x0d6bcabd), TOBN(0xa1b02bc1, 0x408591bc), + TOBN(0xe0deee59, 0x31fba239), TOBN(0xf47424d3, 0x98bd91d1), + TOBN(0x0f8886f4, 0x071a3c1d), TOBN(0x3f7d41e8, 0xa819233b), + TOBN(0x708623c2, 0xcf6eb998), TOBN(0x86bb49af, 0x609a287f), + TOBN(0x942bb249, 0x63c90762), TOBN(0x0ef6eea5, 0x55a9654b), + TOBN(0x5f6d2d72, 0x36f5defe), TOBN(0xfa9922dc, 0x56f99176), + TOBN(0x6c8c5ece, 0xf78ce0c7), TOBN(0x7b44589d, 0xbe09b55e), + TOBN(0xe11b3bca, 0x9ea83770), TOBN(0xd7fa2c7f, 0x2ab71547), + TOBN(0x2a3dd6fa, 0x2a1ddcc0), TOBN(0x09acb430, 0x5a7b7707), + TOBN(0x4add4a2e, 0x649d4e57), TOBN(0xcd53a2b0, 0x1917526e), + TOBN(0xc5262330, 0x20b44ac4), TOBN(0x4028746a, 0xbaa2c31d), + TOBN(0x51318390, 0x64291d4c), TOBN(0xbf48f151, 0xee5ad909), + TOBN(0xcce57f59, 0x7b185681), TOBN(0x7c3ac1b0, 0x4854d442), + TOBN(0x65587dc3, 0xc093c171), TOBN(0xae7acb24, 0x24f42b65), + TOBN(0x5a338adb, 0x955996cb), TOBN(0xc8e65675, 0x6051f91b), + TOBN(0x66711fba, 0x28b8d0b1), TOBN(0x15d74137, 0xb6c10a90), + TOBN(0x70cdd7eb, 0x3a232a80), TOBN(0xc9e2f07f, 0x6191ed24), + TOBN(0xa80d1db6, 0xf79588c0), TOBN(0xfa52fc69, 0xb55768cc), + TOBN(0x0b4df1ae, 0x7f54438a), TOBN(0x0cadd1a7, 0xf9b46a4f), + TOBN(0xb40ea6b3, 0x1803dd6f), TOBN(0x488e4fa5, 0x55eaae35), + TOBN(0x9f047d55, 0x382e4e16), TOBN(0xc9b5b7e0, 0x2f6e0c98), + TOBN(0x6b1bd2d3, 0x95762649), TOBN(0xa9604ee7, 0xc7aea3f6), + TOBN(0x3646ff27, 0x6dc6f896), TOBN(0x9bf0e7f5, 0x2860bad1), + TOBN(0x2d92c821, 0x7cb44b92), TOBN(0xa2f5ce63, 0xaea9c182), + TOBN(0xd0a2afb1, 0x9154a5fd), TOBN(0x482e474c, 0x95801da6), + TOBN(0xc19972d0, 0xb611c24b), TOBN(0x1d468e65, 0x60a8f351), + TOBN(0xeb758069, 0x7bcf6421), TOBN(0xec9dd0ee, 0x88fbc491), + TOBN(0x5b59d2bf, 0x956c2e32), TOBN(0x73dc6864, 0xdcddf94e), + TOBN(0xfd5e2321, 0xbcee7665), TOBN(0xa7b4f8ef, 0x5e9a06c4), + TOBN(0xfba918dd, 0x7280f855), TOBN(0xbbaac260, 0x8baec688), + TOBN(0xa3b3f00f, 0x33400f42), TOBN(0x3d2dba29, 0x66f2e6e4), + TOBN(0xb6f71a94, 0x98509375), TOBN(0x8f33031f, 0xcea423cc), + TOBN(0x009b8dd0, 0x4807e6fb), TOBN(0x5163cfe5, 0x5cdb954c), + TOBN(0x03cc8f17, 0xcf41c6e8), TOBN(0xf1f03c2a, 0x037b925c), + TOBN(0xc39c19cc, 0x66d2427c), TOBN(0x823d24ba, 0x7b6c18e4), + TOBN(0x32ef9013, 0x901f0b4f), TOBN(0x684360f1, 0xf8941c2e), + TOBN(0x0ebaff52, 0x2c28092e), TOBN(0x7891e4e3, 0x256c932f), + TOBN(0x51264319, 0xac445e3d), TOBN(0x553432e7, 0x8ea74381), + TOBN(0xe6eeaa69, 0x67e9c50a), TOBN(0x27ced284, 0x62e628c7), + TOBN(0x3f96d375, 0x7a4afa57), TOBN(0xde0a14c3, 0xe484c150), + TOBN(0x364a24eb, 0x38bd9923), TOBN(0x1df18da0, 0xe5177422), + TOBN(0x174e8f82, 0xd8d38a9b), TOBN(0x2e97c600, 0xe7de1391), + TOBN(0xc5709850, 0xa1c175dd), TOBN(0x969041a0, 0x32ae5035), + TOBN(0xcbfd533b, 0x76a2086b), TOBN(0xd6bba71b, 0xd7c2e8fe), + TOBN(0xb2d58ee6, 0x099dfb67), TOBN(0x3a8b342d, 0x064a85d9), + TOBN(0x3bc07649, 0x522f9be3), TOBN(0x690c075b, 0xdf1f49a8), + TOBN(0x80e1aee8, 0x3854ec42), TOBN(0x2a7dbf44, 0x17689dc7), + TOBN(0xc004fc0e, 0x3faf4078), TOBN(0xb2f02e9e, 0xdf11862c), + TOBN(0xf10a5e0f, 0xa0a1b7b3), TOBN(0x30aca623, 0x8936ec80), + TOBN(0xf83cbf05, 0x02f40d9a), TOBN(0x4681c468, 0x2c318a4d), + TOBN(0x98575618, 0x0e9c2674), TOBN(0xbe79d046, 0x1847092e), + TOBN(0xaf1e480a, 0x78bd01e0), TOBN(0x6dd359e4, 0x72a51db9), + TOBN(0x62ce3821, 0xe3afbab6), TOBN(0xc5cee5b6, 0x17733199), + TOBN(0xe08b30d4, 0x6ffd9fbb), TOBN(0x6e5bc699, 0x36c610b7), + TOBN(0xf343cff2, 0x9ce262cf), TOBN(0xca2e4e35, 0x68b914c1), + TOBN(0x011d64c0, 0x16de36c5), TOBN(0xe0b10fdd, 0x42e2b829), + TOBN(0x78942981, 0x6685aaf8), TOBN(0xe7511708, 0x230ede97), + TOBN(0x671ed8fc, 0x3b922bf8), TOBN(0xe4d8c0a0, 0x4c29b133), + TOBN(0x87eb1239, 0x3b6e99c4), TOBN(0xaff3974c, 0x8793beba), + TOBN(0x03749405, 0x2c18df9b), TOBN(0xc5c3a293, 0x91007139), + TOBN(0x6a77234f, 0xe37a0b95), TOBN(0x02c29a21, 0xb661c96b), + TOBN(0xc3aaf1d6, 0x141ecf61), TOBN(0x9195509e, 0x3bb22f53), + TOBN(0x29597404, 0x22d51357), TOBN(0x1b083822, 0x537bed60), + TOBN(0xcd7d6e35, 0xe07289f0), TOBN(0x1f94c48c, 0x6dd86eff), + TOBN(0xc8bb1f82, 0xeb0f9cfa), TOBN(0x9ee0b7e6, 0x1b2eb97d), + TOBN(0x5a52fe2e, 0x34d74e31), TOBN(0xa352c310, 0x3bf79ab6), + TOBN(0x97ff6c5a, 0xabfeeb8f), TOBN(0xbfbe8fef, 0xf5c97305), + TOBN(0xd6081ce6, 0xa7904608), TOBN(0x1f812f3a, 0xc4fca249), + TOBN(0x9b24bc9a, 0xb9e5e200), TOBN(0x91022c67, 0x38012ee8), + TOBN(0xe83d9c5d, 0x30a713a1), TOBN(0x4876e3f0, 0x84ef0f93), + TOBN(0xc9777029, 0xc1fbf928), TOBN(0xef7a6bb3, 0xbce7d2a4), + TOBN(0xb8067228, 0xdfa2a659), TOBN(0xd5cd3398, 0xd877a48f), + TOBN(0xbea4fd8f, 0x025d0f3f), TOBN(0xd67d2e35, 0x2eae7c2b), + TOBN(0x184de7d7, 0xcc5f4394), TOBN(0xb5551b5c, 0x4536e142), + TOBN(0x2e89b212, 0xd34aa60a), TOBN(0x14a96fea, 0xf50051d5), + TOBN(0x4e21ef74, 0x0d12bb0b), TOBN(0xc522f020, 0x60b9677e), + TOBN(0x8b12e467, 0x2df7731d), TOBN(0x39f80382, 0x7b326d31), + TOBN(0xdfb8630c, 0x39024a94), TOBN(0xaacb96a8, 0x97319452), + TOBN(0xd68a3961, 0xeda3867c), TOBN(0x0c58e2b0, 0x77c4ffca), + TOBN(0x3d545d63, 0x4da919fa), TOBN(0xef79b69a, 0xf15e2289), + TOBN(0x54bc3d3d, 0x808bab10), TOBN(0xc8ab3007, 0x45f82c37), + TOBN(0xc12738b6, 0x7c4a658a), TOBN(0xb3c47639, 0x40e72182), + TOBN(0x3b77be46, 0x8798e44f), TOBN(0xdc047df2, 0x17a7f85f), + TOBN(0x2439d4c5, 0x5e59d92d), TOBN(0xcedca475, 0xe8e64d8d), + TOBN(0xa724cd0d, 0x87ca9b16), TOBN(0x35e4fd59, 0xa5540dfe), + TOBN(0xf8c1ff18, 0xe4bcf6b1), TOBN(0x856d6285, 0x295018fa), + TOBN(0x433f665c, 0x3263c949), TOBN(0xa6a76dd6, 0xa1f21409), + TOBN(0x17d32334, 0xcc7b4f79), TOBN(0xa1d03122, 0x06720e4a), + TOBN(0xadb6661d, 0x81d9bed5), TOBN(0xf0d6fb02, 0x11db15d1), + TOBN(0x7fd11ad5, 0x1fb747d2), TOBN(0xab50f959, 0x3033762b), + TOBN(0x2a7e711b, 0xfbefaf5a), TOBN(0xc7393278, 0x3fef2bbf), + TOBN(0xe29fa244, 0x0df6f9be), TOBN(0x9092757b, 0x71efd215), + TOBN(0xee60e311, 0x4f3d6fd9), TOBN(0x338542d4, 0x0acfb78b), + TOBN(0x44a23f08, 0x38961a0f), TOBN(0x1426eade, 0x986987ca), + TOBN(0x36e6ee2e, 0x4a863cc6), TOBN(0x48059420, 0x628b8b79), + TOBN(0x30303ad8, 0x7396e1de), TOBN(0x5c8bdc48, 0x38c5aad1), + TOBN(0x3e40e11f, 0x5c8f5066), TOBN(0xabd6e768, 0x8d246bbd), + TOBN(0x68aa40bb, 0x23330a01), TOBN(0xd23f5ee4, 0xc34eafa0), + TOBN(0x3bbee315, 0x5de02c21), TOBN(0x18dd4397, 0xd1d8dd06), + TOBN(0x3ba1939a, 0x122d7b44), TOBN(0xe6d3b40a, 0xa33870d6), + TOBN(0x8e620f70, 0x1c4fe3f8), TOBN(0xf6bba1a5, 0xd3a50cbf), + TOBN(0x4a78bde5, 0xcfc0aee0), TOBN(0x847edc46, 0xc08c50bd), + TOBN(0xbaa2439c, 0xad63c9b2), TOBN(0xceb4a728, 0x10fc2acb), + TOBN(0xa419e40e, 0x26da033d), TOBN(0x6cc3889d, 0x03e02683), + TOBN(0x1cd28559, 0xfdccf725), TOBN(0x0fd7e0f1, 0x8d13d208), + TOBN(0x01b9733b, 0x1f0df9d4), TOBN(0x8cc2c5f3, 0xa2b5e4f3), + TOBN(0x43053bfa, 0x3a304fd4), TOBN(0x8e87665c, 0x0a9f1aa7), + TOBN(0x087f29ec, 0xd73dc965), TOBN(0x15ace455, 0x3e9023db), + TOBN(0x2370e309, 0x2bce28b4), TOBN(0xf9723442, 0xb6b1e84a), + TOBN(0xbeee662e, 0xb72d9f26), TOBN(0xb19396de, 0xf0e47109), + TOBN(0x85b1fa73, 0xe13289d0), TOBN(0x436cf77e, 0x54e58e32), + TOBN(0x0ec833b3, 0xe990ef77), TOBN(0x7373e3ed, 0x1b11fc25), + TOBN(0xbe0eda87, 0x0fc332ce), TOBN(0xced04970, 0x8d7ea856), + TOBN(0xf85ff785, 0x7e977ca0), TOBN(0xb66ee8da, 0xdfdd5d2b), + TOBN(0xf5e37950, 0x905af461), TOBN(0x587b9090, 0x966d487c), + TOBN(0x6a198a1b, 0x32ba0127), TOBN(0xa7720e07, 0x141615ac), + TOBN(0xa23f3499, 0x996ef2f2), TOBN(0xef5f64b4, 0x470bcb3d), + TOBN(0xa526a962, 0x92b8c559), TOBN(0x0c14aac0, 0x69740a0f), + TOBN(0x0d41a9e3, 0xa6bdc0a5), TOBN(0x97d52106, 0x9c48aef4), + TOBN(0xcf16bd30, 0x3e7c253b), TOBN(0xcc834b1a, 0x47fdedc1), + TOBN(0x7362c6e5, 0x373aab2e), TOBN(0x264ed85e, 0xc5f590ff), + TOBN(0x7a46d9c0, 0x66d41870), TOBN(0xa50c20b1, 0x4787ba09), + TOBN(0x185e7e51, 0xe3d44635), TOBN(0xb3b3e080, 0x31e2d8dc), + TOBN(0xbed1e558, 0xa179e9d9), TOBN(0x2daa3f79, 0x74a76781), + TOBN(0x4372baf2, 0x3a40864f), TOBN(0x46900c54, 0x4fe75cb5), + TOBN(0xb95f171e, 0xf76765d0), TOBN(0x4ad726d2, 0x95c87502), + TOBN(0x2ec769da, 0x4d7c99bd), TOBN(0x5e2ddd19, 0xc36cdfa8), + TOBN(0xc22117fc, 0xa93e6dea), TOBN(0xe8a2583b, 0x93771123), + TOBN(0xbe2f6089, 0xfa08a3a2), TOBN(0x4809d5ed, 0x8f0e1112), + TOBN(0x3b414aa3, 0xda7a095e), TOBN(0x9049acf1, 0x26f5aadd), + TOBN(0x78d46a4d, 0x6be8b84a), TOBN(0xd66b1963, 0xb732b9b3), + TOBN(0x5c2ac2a0, 0xde6e9555), TOBN(0xcf52d098, 0xb5bd8770), + TOBN(0x15a15fa6, 0x0fd28921), TOBN(0x56ccb81e, 0x8b27536d), + TOBN(0x0f0d8ab8, 0x9f4ccbb8), TOBN(0xed5f44d2, 0xdb221729), + TOBN(0x43141988, 0x00bed10c), TOBN(0xc94348a4, 0x1d735b8b), + TOBN(0x79f3e9c4, 0x29ef8479), TOBN(0x4c13a4e3, 0x614c693f), + TOBN(0x32c9af56, 0x8e143a14), TOBN(0xbc517799, 0xe29ac5c4), + TOBN(0x05e17992, 0x2774856f), TOBN(0x6e52fb05, 0x6c1bf55f), + TOBN(0xaeda4225, 0xe4f19e16), TOBN(0x70f4728a, 0xaf5ccb26), + TOBN(0x5d2118d1, 0xb2947f22), TOBN(0xc827ea16, 0x281d6fb9), + TOBN(0x8412328d, 0x8cf0eabd), TOBN(0x45ee9fb2, 0x03ef9dcf), + TOBN(0x8e700421, 0xbb937d63), TOBN(0xdf8ff2d5, 0xcc4b37a6), + TOBN(0xa4c0d5b2, 0x5ced7b68), TOBN(0x6537c1ef, 0xc7308f59), + TOBN(0x25ce6a26, 0x3b37f8e8), TOBN(0x170e9a9b, 0xdeebc6ce), + TOBN(0xdd037952, 0x8728d72c), TOBN(0x445b0e55, 0x850154bc), + TOBN(0x4b7d0e06, 0x83a7337b), TOBN(0x1e3416d4, 0xffecf249), + TOBN(0x24840eff, 0x66a2b71f), TOBN(0xd0d9a50a, 0xb37cc26d), + TOBN(0xe2198150, 0x6fe28ef7), TOBN(0x3cc5ef16, 0x23324c7f), + TOBN(0x220f3455, 0x769b5263), TOBN(0xe2ade2f1, 0xa10bf475), + TOBN(0x28cd20fa, 0x458d3671), TOBN(0x1549722c, 0x2dc4847b), + TOBN(0x6dd01e55, 0x591941e3), TOBN(0x0e6fbcea, 0x27128ccb), + TOBN(0xae1a1e6b, 0x3bef0262), TOBN(0xfa8c472c, 0x8f54e103), + TOBN(0x7539c0a8, 0x72c052ec), TOBN(0xd7b27369, 0x5a3490e9), + TOBN(0x143fe1f1, 0x71684349), TOBN(0x36b4722e, 0x32e19b97), + TOBN(0xdc059227, 0x90980aff), TOBN(0x175c9c88, 0x9e13d674), + TOBN(0xa7de5b22, 0x6e6bfdb1), TOBN(0x5ea5b7b2, 0xbedb4b46), + TOBN(0xd5570191, 0xd34a6e44), TOBN(0xfcf60d2e, 0xa24ff7e6), + TOBN(0x614a392d, 0x677819e1), TOBN(0x7be74c7e, 0xaa5a29e8), + TOBN(0xab50fece, 0x63c85f3f), TOBN(0xaca2e2a9, 0x46cab337), + TOBN(0x7f700388, 0x122a6fe3), TOBN(0xdb69f703, 0x882a04a8), + TOBN(0x9a77935d, 0xcf7aed57), TOBN(0xdf16207c, 0x8d91c86f), + TOBN(0x2fca49ab, 0x63ed9998), TOBN(0xa3125c44, 0xa77ddf96), + TOBN(0x05dd8a86, 0x24344072), TOBN(0xa023dda2, 0xfec3fb56), + TOBN(0x421b41fc, 0x0c743032), TOBN(0x4f2120c1, 0x5e438639), + TOBN(0xfb7cae51, 0xc83c1b07), TOBN(0xb2370caa, 0xcac2171a), + TOBN(0x2eb2d962, 0x6cc820fb), TOBN(0x59feee5c, 0xb85a44bf), + TOBN(0x94620fca, 0x5b6598f0), TOBN(0x6b922cae, 0x7e314051), + TOBN(0xff8745ad, 0x106bed4e), TOBN(0x546e71f5, 0xdfa1e9ab), + TOBN(0x935c1e48, 0x1ec29487), TOBN(0x9509216c, 0x4d936530), + TOBN(0xc7ca3067, 0x85c9a2db), TOBN(0xd6ae5152, 0x6be8606f), + TOBN(0x09dbcae6, 0xe14c651d), TOBN(0xc9536e23, 0x9bc32f96), + TOBN(0xa90535a9, 0x34521b03), TOBN(0xf39c526c, 0x878756ff), + TOBN(0x383172ec, 0x8aedf03c), TOBN(0x20a8075e, 0xefe0c034), + TOBN(0xf22f9c62, 0x64026422), TOBN(0x8dd10780, 0x24b9d076), + TOBN(0x944c742a, 0x3bef2950), TOBN(0x55b9502e, 0x88a2b00b), + TOBN(0xa59e14b4, 0x86a09817), TOBN(0xa39dd3ac, 0x47bb4071), + TOBN(0x55137f66, 0x3be0592f), TOBN(0x07fcafd4, 0xc9e63f5b), + TOBN(0x963652ee, 0x346eb226), TOBN(0x7dfab085, 0xec2facb7), + TOBN(0x273bf2b8, 0x691add26), TOBN(0x30d74540, 0xf2b46c44), + TOBN(0x05e8e73e, 0xf2c2d065), TOBN(0xff9b8a00, 0xd42eeac9), + TOBN(0x2fcbd205, 0x97209d22), TOBN(0xeb740ffa, 0xde14ea2c), + TOBN(0xc71ff913, 0xa8aef518), TOBN(0x7bfc74bb, 0xfff4cfa2), + TOBN(0x1716680c, 0xb6b36048), TOBN(0x121b2cce, 0x9ef79af1), + TOBN(0xbff3c836, 0xa01eb3d3), TOBN(0x50eb1c6a, 0x5f79077b), + TOBN(0xa48c32d6, 0xa004bbcf), TOBN(0x47a59316, 0x7d64f61d), + TOBN(0x6068147f, 0x93102016), TOBN(0x12c5f654, 0x94d12576), + TOBN(0xefb071a7, 0xc9bc6b91), TOBN(0x7c2da0c5, 0x6e23ea95), + TOBN(0xf4fd45b6, 0xd4a1dd5d), TOBN(0x3e7ad9b6, 0x9122b13c), + TOBN(0x342ca118, 0xe6f57a48), TOBN(0x1c2e94a7, 0x06f8288f), + TOBN(0x99e68f07, 0x5a97d231), TOBN(0x7c80de97, 0x4d838758), + TOBN(0xbce0f5d0, 0x05872727), TOBN(0xbe5d95c2, 0x19c4d016), + TOBN(0x921d5cb1, 0x9c2492ee), TOBN(0x42192dc1, 0x404d6fb3), + TOBN(0x4c84dcd1, 0x32f988d3), TOBN(0xde26d61f, 0xa17b8e85), + TOBN(0xc466dcb6, 0x137c7408), TOBN(0x9a38d7b6, 0x36a266da), + TOBN(0x7ef5cb06, 0x83bebf1b), TOBN(0xe5cdcbbf, 0x0fd014e3), + TOBN(0x30aa376d, 0xf65965a0), TOBN(0x60fe88c2, 0xebb3e95e), + TOBN(0x33fd0b61, 0x66ee6f20), TOBN(0x8827dcdb, 0x3f41f0a0), + TOBN(0xbf8a9d24, 0x0c56c690), TOBN(0x40265dad, 0xddb7641d), + TOBN(0x522b05bf, 0x3a6b662b), TOBN(0x466d1dfe, 0xb1478c9b), + TOBN(0xaa616962, 0x1484469b), TOBN(0x0db60549, 0x02df8f9f), + TOBN(0xc37bca02, 0x3cb8bf51), TOBN(0x5effe346, 0x21371ce8), + TOBN(0xe8f65264, 0xff112c32), TOBN(0x8a9c736d, 0x7b971fb2), + TOBN(0xa4f19470, 0x7b75080d), TOBN(0xfc3f2c5a, 0x8839c59b), + TOBN(0x1d6c777e, 0x5aeb49c2), TOBN(0xf3db034d, 0xda1addfe), + TOBN(0xd76fee5a, 0x5535affc), TOBN(0x0853ac70, 0xb92251fd), + TOBN(0x37e3d594, 0x8b2a29d5), TOBN(0x28f1f457, 0x4de00ddb), + TOBN(0x8083c1b5, 0xf42c328b), TOBN(0xd8ef1d8f, 0xe493c73b), + TOBN(0x96fb6260, 0x41dc61bd), TOBN(0xf74e8a9d, 0x27ee2f8a), + TOBN(0x7c605a80, 0x2c946a5d), TOBN(0xeed48d65, 0x3839ccfd), + TOBN(0x9894344f, 0x3a29467a), TOBN(0xde81e949, 0xc51eba6d), + TOBN(0xdaea066b, 0xa5e5c2f2), TOBN(0x3fc8a614, 0x08c8c7b3), + TOBN(0x7adff88f, 0x06d0de9f), TOBN(0xbbc11cf5, 0x3b75ce0a), + TOBN(0x9fbb7acc, 0xfbbc87d5), TOBN(0xa1458e26, 0x7badfde2)} + , + {TOBN(0x1cb43668, 0xe039c256), TOBN(0x5f26fb8b, 0x7c17fd5d), + TOBN(0xeee426af, 0x79aa062b), TOBN(0x072002d0, 0xd78fbf04), + TOBN(0x4c9ca237, 0xe84fb7e3), TOBN(0xb401d8a1, 0x0c82133d), + TOBN(0xaaa52592, 0x6d7e4181), TOBN(0xe9430833, 0x73dbb152), + TOBN(0xf92dda31, 0xbe24319a), TOBN(0x03f7d28b, 0xe095a8e7), + TOBN(0xa52fe840, 0x98782185), TOBN(0x276ddafe, 0x29c24dbc), + TOBN(0x80cd5496, 0x1d7a64eb), TOBN(0xe4360889, 0x7f1dbe42), + TOBN(0x2f81a877, 0x8438d2d5), TOBN(0x7e4d52a8, 0x85169036), + TOBN(0x19e3d5b1, 0x1d59715d), TOBN(0xc7eaa762, 0xd788983e), + TOBN(0xe5a730b0, 0xabf1f248), TOBN(0xfbab8084, 0xfae3fd83), + TOBN(0x65e50d21, 0x53765b2f), TOBN(0xbdd4e083, 0xfa127f3d), + TOBN(0x9cf3c074, 0x397b1b10), TOBN(0x59f8090c, 0xb1b59fd3), + TOBN(0x7b15fd9d, 0x615faa8f), TOBN(0x8fa1eb40, 0x968554ed), + TOBN(0x7bb4447e, 0x7aa44882), TOBN(0x2bb2d0d1, 0x029fff32), + TOBN(0x075e2a64, 0x6caa6d2f), TOBN(0x8eb879de, 0x22e7351b), + TOBN(0xbcd5624e, 0x9a506c62), TOBN(0x218eaef0, 0xa87e24dc), + TOBN(0x37e56847, 0x44ddfa35), TOBN(0x9ccfc5c5, 0xdab3f747), + TOBN(0x9ac1df3f, 0x1ee96cf4), TOBN(0x0c0571a1, 0x3b480b8f), + TOBN(0x2fbeb3d5, 0x4b3a7b3c), TOBN(0x35c03669, 0x5dcdbb99), + TOBN(0x52a0f5dc, 0xb2415b3a), TOBN(0xd57759b4, 0x4413ed9a), + TOBN(0x1fe647d8, 0x3d30a2c5), TOBN(0x0857f77e, 0xf78a81dc), + TOBN(0x11d5a334, 0x131a4a9b), TOBN(0xc0a94af9, 0x29d393f5), + TOBN(0xbc3a5c0b, 0xdaa6ec1a), TOBN(0xba9fe493, 0x88d2d7ed), + TOBN(0xbb4335b4, 0xbb614797), TOBN(0x991c4d68, 0x72f83533), + TOBN(0x53258c28, 0xd2f01cb3), TOBN(0x93d6eaa3, 0xd75db0b1), + TOBN(0x419a2b0d, 0xe87d0db4), TOBN(0xa1e48f03, 0xd8fe8493), + TOBN(0xf747faf6, 0xc508b23a), TOBN(0xf137571a, 0x35d53549), + TOBN(0x9f5e58e2, 0xfcf9b838), TOBN(0xc7186cee, 0xa7fd3cf5), + TOBN(0x77b868ce, 0xe978a1d3), TOBN(0xe3a68b33, 0x7ab92d04), + TOBN(0x51029794, 0x87a5b862), TOBN(0x5f0606c3, 0x3a61d41d), + TOBN(0x2814be27, 0x6f9326f1), TOBN(0x2f521c14, 0xc6fe3c2e), + TOBN(0x17464d7d, 0xacdf7351), TOBN(0x10f5f9d3, 0x777f7e44), + TOBN(0xce8e616b, 0x269fb37d), TOBN(0xaaf73804, 0x7de62de5), + TOBN(0xaba11175, 0x4fdd4153), TOBN(0x515759ba, 0x3770b49b), + TOBN(0x8b09ebf8, 0xaa423a61), TOBN(0x592245a1, 0xcd41fb92), + TOBN(0x1cba8ec1, 0x9b4c8936), TOBN(0xa87e91e3, 0xaf36710e), + TOBN(0x1fd84ce4, 0x3d34a2e3), TOBN(0xee3759ce, 0xb43b5d61), + TOBN(0x895bc78c, 0x619186c7), TOBN(0xf19c3809, 0xcbb9725a), + TOBN(0xc0be21aa, 0xde744b1f), TOBN(0xa7d222b0, 0x60f8056b), + TOBN(0x74be6157, 0xb23efe11), TOBN(0x6fab2b4f, 0x0cd68253), + TOBN(0xad33ea5f, 0x4bf1d725), TOBN(0x9c1d8ee2, 0x4f6c950f), + TOBN(0x544ee78a, 0xa377af06), TOBN(0x54f489bb, 0x94a113e1), + TOBN(0x8f11d634, 0x992fb7e8), TOBN(0x0169a7aa, 0xa2a44347), + TOBN(0x1d49d4af, 0x95020e00), TOBN(0x95945722, 0xe08e120b), + TOBN(0xb6e33878, 0xa4d32282), TOBN(0xe36e029d, 0x48020ae7), + TOBN(0xe05847fb, 0x37a9b750), TOBN(0xf876812c, 0xb29e3819), + TOBN(0x84ad138e, 0xd23a17f0), TOBN(0x6d7b4480, 0xf0b3950e), + TOBN(0xdfa8aef4, 0x2fd67ae0), TOBN(0x8d3eea24, 0x52333af6), + TOBN(0x0d052075, 0xb15d5acc), TOBN(0xc6d9c79f, 0xbd815bc4), + TOBN(0x8dcafd88, 0xdfa36cf2), TOBN(0x908ccbe2, 0x38aa9070), + TOBN(0x638722c4, 0xba35afce), TOBN(0x5a3da8b0, 0xfd6abf0b), + TOBN(0x2dce252c, 0xc9c335c1), TOBN(0x84e7f0de, 0x65aa799b), + TOBN(0x2101a522, 0xb99a72cb), TOBN(0x06de6e67, 0x87618016), + TOBN(0x5ff8c7cd, 0xe6f3653e), TOBN(0x0a821ab5, 0xc7a6754a), + TOBN(0x7e3fa52b, 0x7cb0b5a2), TOBN(0xa7fb121c, 0xc9048790), + TOBN(0x1a725020, 0x06ce053a), TOBN(0xb490a31f, 0x04e929b0), + TOBN(0xe17be47d, 0x62dd61ad), TOBN(0x781a961c, 0x6be01371), + TOBN(0x1063bfd3, 0xdae3cbba), TOBN(0x35647406, 0x7f73c9ba), + TOBN(0xf50e957b, 0x2736a129), TOBN(0xa6313702, 0xed13f256), + TOBN(0x9436ee65, 0x3a19fcc5), TOBN(0xcf2bdb29, 0xe7a4c8b6), + TOBN(0xb06b1244, 0xc5f95cd8), TOBN(0xda8c8af0, 0xf4ab95f4), + TOBN(0x1bae59c2, 0xb9e5836d), TOBN(0x07d51e7e, 0x3acffffc), + TOBN(0x01e15e6a, 0xc2ccbcda), TOBN(0x3bc1923f, 0x8528c3e0), + TOBN(0x43324577, 0xa49fead4), TOBN(0x61a1b884, 0x2aa7a711), + TOBN(0xf9a86e08, 0x700230ef), TOBN(0x0af585a1, 0xbd19adf8), + TOBN(0x7645f361, 0xf55ad8f2), TOBN(0x6e676223, 0x46c3614c), + TOBN(0x23cb257c, 0x4e774d3f), TOBN(0x82a38513, 0xac102d1b), + TOBN(0x9bcddd88, 0x7b126aa5), TOBN(0xe716998b, 0xeefd3ee4), + TOBN(0x4239d571, 0xfb167583), TOBN(0xdd011c78, 0xd16c8f8a), + TOBN(0x271c2895, 0x69a27519), TOBN(0x9ce0a3b7, 0xd2d64b6a), + TOBN(0x8c977289, 0xd5ec6738), TOBN(0xa3b49f9a, 0x8840ef6b), + TOBN(0x808c14c9, 0x9a453419), TOBN(0x5c00295b, 0x0cf0a2d5), + TOBN(0x524414fb, 0x1d4bcc76), TOBN(0xb07691d2, 0x459a88f1), + TOBN(0x77f43263, 0xf70d110f), TOBN(0x64ada5e0, 0xb7abf9f3), + TOBN(0xafd0f94e, 0x5b544cf5), TOBN(0xb4a13a15, 0xfd2713fe), + TOBN(0xb99b7d6e, 0x250c74f4), TOBN(0x097f2f73, 0x20324e45), + TOBN(0x994b37d8, 0xaffa8208), TOBN(0xc3c31b0b, 0xdc29aafc), + TOBN(0x3da74651, 0x7a3a607f), TOBN(0xd8e1b8c1, 0xfe6955d6), + TOBN(0x716e1815, 0xc8418682), TOBN(0x541d487f, 0x7dc91d97), + TOBN(0x48a04669, 0xc6996982), TOBN(0xf39cab15, 0x83a6502e), + TOBN(0x025801a0, 0xe68db055), TOBN(0xf3569758, 0xba3338d5), + TOBN(0xb0c8c0aa, 0xee2afa84), TOBN(0x4f6985d3, 0xfb6562d1), + TOBN(0x351f1f15, 0x132ed17a), TOBN(0x510ed0b4, 0xc04365fe), + TOBN(0xa3f98138, 0xe5b1f066), TOBN(0xbc9d95d6, 0x32df03dc), + TOBN(0xa83ccf6e, 0x19abd09e), TOBN(0x0b4097c1, 0x4ff17edb), + TOBN(0x58a5c478, 0xd64a06ce), TOBN(0x2ddcc3fd, 0x544a58fd), + TOBN(0xd449503d, 0x9e8153b8), TOBN(0x3324fd02, 0x7774179b), + TOBN(0xaf5d47c8, 0xdbd9120c), TOBN(0xeb860162, 0x34fa94db), + TOBN(0x5817bdd1, 0x972f07f4), TOBN(0xe5579e2e, 0xd27bbceb), + TOBN(0x86847a1f, 0x5f11e5a6), TOBN(0xb39ed255, 0x7c3cf048), + TOBN(0xe1076417, 0xa2f62e55), TOBN(0x6b9ab38f, 0x1bcf82a2), + TOBN(0x4bb7c319, 0x7aeb29f9), TOBN(0xf6d17da3, 0x17227a46), + TOBN(0xab53ddbd, 0x0f968c00), TOBN(0xa03da7ec, 0x000c880b), + TOBN(0x7b239624, 0x6a9ad24d), TOBN(0x612c0401, 0x01ec60d0), + TOBN(0x70d10493, 0x109f5df1), TOBN(0xfbda4030, 0x80af7550), + TOBN(0x30b93f95, 0xc6b9a9b3), TOBN(0x0c74ec71, 0x007d9418), + TOBN(0x94175564, 0x6edb951f), TOBN(0x5f4a9d78, 0x7f22c282), + TOBN(0xb7870895, 0xb38d1196), TOBN(0xbc593df3, 0xa228ce7c), + TOBN(0xc78c5bd4, 0x6af3641a), TOBN(0x7802200b, 0x3d9b3dcc), + TOBN(0x0dc73f32, 0x8be33304), TOBN(0x847ed87d, 0x61ffb79a), + TOBN(0xf85c974e, 0x6d671192), TOBN(0x1e14100a, 0xde16f60f), + TOBN(0x45cb0d5a, 0x95c38797), TOBN(0x18923bba, 0x9b022da4), + TOBN(0xef2be899, 0xbbe7e86e), TOBN(0x4a1510ee, 0x216067bf), + TOBN(0xd98c8154, 0x84d5ce3e), TOBN(0x1af777f0, 0xf92a2b90), + TOBN(0x9fbcb400, 0x4ef65724), TOBN(0x3e04a4c9, 0x3c0ca6fe), + TOBN(0xfb3e2cb5, 0x55002994), TOBN(0x1f3a93c5, 0x5363ecab), + TOBN(0x1fe00efe, 0x3923555b), TOBN(0x744bedd9, 0x1e1751ea), + TOBN(0x3fb2db59, 0x6ab69357), TOBN(0x8dbd7365, 0xf5e6618b), + TOBN(0x99d53099, 0xdf1ea40e), TOBN(0xb3f24a0b, 0x57d61e64), + TOBN(0xd088a198, 0x596eb812), TOBN(0x22c8361b, 0x5762940b), + TOBN(0x66f01f97, 0xf9c0d95c), TOBN(0x88461172, 0x8e43cdae), + TOBN(0x11599a7f, 0xb72b15c3), TOBN(0x135a7536, 0x420d95cc), + TOBN(0x2dcdf0f7, 0x5f7ae2f6), TOBN(0x15fc6e1d, 0xd7fa6da2), + TOBN(0x81ca829a, 0xd1d441b6), TOBN(0x84c10cf8, 0x04a106b6), + TOBN(0xa9b26c95, 0xa73fbbd0), TOBN(0x7f24e0cb, 0x4d8f6ee8), + TOBN(0x48b45937, 0x1e25a043), TOBN(0xf8a74fca, 0x036f3dfe), + TOBN(0x1ed46585, 0xc9f84296), TOBN(0x7fbaa8fb, 0x3bc278b0), + TOBN(0xa8e96cd4, 0x6c4fcbd0), TOBN(0x940a1202, 0x73b60a5f), + TOBN(0x34aae120, 0x55a4aec8), TOBN(0x550e9a74, 0xdbd742f0), + TOBN(0x794456d7, 0x228c68ab), TOBN(0x492f8868, 0xa4e25ec6), + TOBN(0x682915ad, 0xb2d8f398), TOBN(0xf13b51cc, 0x5b84c953), + TOBN(0xcda90ab8, 0x5bb917d6), TOBN(0x4b615560, 0x4ea3dee1), + TOBN(0x578b4e85, 0x0a52c1c8), TOBN(0xeab1a695, 0x20b75fc4), + TOBN(0x60c14f3c, 0xaa0bb3c6), TOBN(0x220f448a, 0xb8216094), + TOBN(0x4fe7ee31, 0xb0e63d34), TOBN(0xf4600572, 0xa9e54fab), + TOBN(0xc0493334, 0xd5e7b5a4), TOBN(0x8589fb92, 0x06d54831), + TOBN(0xaa70f5cc, 0x6583553a), TOBN(0x0879094a, 0xe25649e5), + TOBN(0xcc904507, 0x10044652), TOBN(0xebb0696d, 0x02541c4f), + TOBN(0x5a171fde, 0xb9718710), TOBN(0x38f1bed8, 0xf374a9f5), + TOBN(0xc8c582e1, 0xba39bdc1), TOBN(0xfc457b0a, 0x908cc0ce), + TOBN(0x9a187fd4, 0x883841e2), TOBN(0x8ec25b39, 0x38725381), + TOBN(0x2553ed05, 0x96f84395), TOBN(0x095c7661, 0x6f6c6897), + TOBN(0x917ac85c, 0x4bdc5610), TOBN(0xb2885fe4, 0x179eb301), + TOBN(0x5fc65547, 0x8b78bdcc), TOBN(0x4a9fc893, 0xe59e4699), + TOBN(0xbb7ff0cd, 0x3ce299af), TOBN(0x195be9b3, 0xadf38b20), + TOBN(0x6a929c87, 0xd38ddb8f), TOBN(0x55fcc99c, 0xb21a51b9), + TOBN(0x2b695b4c, 0x721a4593), TOBN(0xed1e9a15, 0x768eaac2), + TOBN(0xfb63d71c, 0x7489f914), TOBN(0xf98ba31c, 0x78118910), + TOBN(0x80291373, 0x9b128eb4), TOBN(0x7801214e, 0xd448af4a), + TOBN(0xdbd2e22b, 0x55418dd3), TOBN(0xeffb3c0d, 0xd3998242), + TOBN(0xdfa6077c, 0xc7bf3827), TOBN(0xf2165bcb, 0x47f8238f), + TOBN(0xfe37cf68, 0x8564d554), TOBN(0xe5f825c4, 0x0a81fb98), + TOBN(0x43cc4f67, 0xffed4d6f), TOBN(0xbc609578, 0xb50a34b0), + TOBN(0x8aa8fcf9, 0x5041faf1), TOBN(0x5659f053, 0x651773b6), + TOBN(0xe87582c3, 0x6044d63b), TOBN(0xa6089409, 0x0cdb0ca0), + TOBN(0x8c993e0f, 0xbfb2bcf6), TOBN(0xfc64a719, 0x45985cfc), + TOBN(0x15c4da80, 0x83dbedba), TOBN(0x804ae112, 0x2be67df7), + TOBN(0xda4c9658, 0xa23defde), TOBN(0x12002ddd, 0x5156e0d3), + TOBN(0xe68eae89, 0x5dd21b96), TOBN(0x8b99f28b, 0xcf44624d), + TOBN(0x0ae00808, 0x1ec8897a), TOBN(0xdd0a9303, 0x6712f76e), + TOBN(0x96237522, 0x4e233de4), TOBN(0x192445b1, 0x2b36a8a5), + TOBN(0xabf9ff74, 0x023993d9), TOBN(0x21f37bf4, 0x2aad4a8f), + TOBN(0x340a4349, 0xf8bd2bbd), TOBN(0x1d902cd9, 0x4868195d), + TOBN(0x3d27bbf1, 0xe5fdb6f1), TOBN(0x7a5ab088, 0x124f9f1c), + TOBN(0xc466ab06, 0xf7a09e03), TOBN(0x2f8a1977, 0x31f2c123), + TOBN(0xda355dc7, 0x041b6657), TOBN(0xcb840d12, 0x8ece2a7c), + TOBN(0xb600ad9f, 0x7db32675), TOBN(0x78fea133, 0x07a06f1b), + TOBN(0x5d032269, 0xb31f6094), TOBN(0x07753ef5, 0x83ec37aa), + TOBN(0x03485aed, 0x9c0bea78), TOBN(0x41bb3989, 0xbc3f4524), + TOBN(0x09403761, 0x697f726d), TOBN(0x6109beb3, 0xdf394820), + TOBN(0x804111ea, 0x3b6d1145), TOBN(0xb6271ea9, 0xa8582654), + TOBN(0x619615e6, 0x24e66562), TOBN(0xa2554945, 0xd7b6ad9c), + TOBN(0xd9c4985e, 0x99bfe35f), TOBN(0x9770ccc0, 0x7b51cdf6), + TOBN(0x7c327013, 0x92881832), TOBN(0x8777d45f, 0x286b26d1), + TOBN(0x9bbeda22, 0xd847999d), TOBN(0x03aa33b6, 0xc3525d32), + TOBN(0x4b7b96d4, 0x28a959a1), TOBN(0xbb3786e5, 0x31e5d234), + TOBN(0xaeb5d3ce, 0x6961f247), TOBN(0x20aa85af, 0x02f93d3f), + TOBN(0x9cd1ad3d, 0xd7a7ae4f), TOBN(0xbf6688f0, 0x781adaa8), + TOBN(0xb1b40e86, 0x7469cead), TOBN(0x1904c524, 0x309fca48), + TOBN(0x9b7312af, 0x4b54bbc7), TOBN(0xbe24bf8f, 0x593affa2), + TOBN(0xbe5e0790, 0xbd98764b), TOBN(0xa0f45f17, 0xa26e299e), + TOBN(0x4af0d2c2, 0x6b8fe4c7), TOBN(0xef170db1, 0x8ae8a3e6), + TOBN(0x0e8d61a0, 0x29e0ccc1), TOBN(0xcd53e87e, 0x60ad36ca), + TOBN(0x328c6623, 0xc8173822), TOBN(0x7ee1767d, 0xa496be55), + TOBN(0x89f13259, 0x648945af), TOBN(0x9e45a5fd, 0x25c8009c), + TOBN(0xaf2febd9, 0x1f61ab8c), TOBN(0x43f6bc86, 0x8a275385), + TOBN(0x87792348, 0xf2142e79), TOBN(0x17d89259, 0xc6e6238a), + TOBN(0x7536d2f6, 0x4a839d9b), TOBN(0x1f428fce, 0x76a1fbdc), + TOBN(0x1c109601, 0x0db06dfe), TOBN(0xbfc16bc1, 0x50a3a3cc), + TOBN(0xf9cbd9ec, 0x9b30f41b), TOBN(0x5b5da0d6, 0x00138cce), + TOBN(0xec1d0a48, 0x56ef96a7), TOBN(0xb47eb848, 0x982bf842), + TOBN(0x66deae32, 0xec3f700d), TOBN(0x4e43c42c, 0xaa1181e0), + TOBN(0xa1d72a31, 0xd1a4aa2a), TOBN(0x440d4668, 0xc004f3ce), + TOBN(0x0d6a2d3b, 0x45fe8a7a), TOBN(0x820e52e2, 0xfb128365), + TOBN(0x29ac5fcf, 0x25e51b09), TOBN(0x180cd2bf, 0x2023d159), + TOBN(0xa9892171, 0xa1ebf90e), TOBN(0xf97c4c87, 0x7c132181), + TOBN(0x9f1dc724, 0xc03dbb7e), TOBN(0xae043765, 0x018cbbe4), + TOBN(0xfb0b2a36, 0x0767d153), TOBN(0xa8e2f4d6, 0x249cbaeb), + TOBN(0x172a5247, 0xd95ea168), TOBN(0x1758fada, 0x2970764a), + TOBN(0xac803a51, 0x1d978169), TOBN(0x299cfe2e, 0xde77e01b), + TOBN(0x652a1e17, 0xb0a98927), TOBN(0x2e26e1d1, 0x20014495), + TOBN(0x7ae0af9f, 0x7175b56a), TOBN(0xc2e22a80, 0xd64b9f95), + TOBN(0x4d0ff9fb, 0xd90a060a), TOBN(0x496a27db, 0xbaf38085), + TOBN(0x32305401, 0xda776bcf), TOBN(0xb8cdcef6, 0x725f209e), + TOBN(0x61ba0f37, 0x436a0bba), TOBN(0x263fa108, 0x76860049), + TOBN(0x92beb98e, 0xda3542cf), TOBN(0xa2d4d14a, 0xd5849538), + TOBN(0x989b9d68, 0x12e9a1bc), TOBN(0x61d9075c, 0x5f6e3268), + TOBN(0x352c6aa9, 0x99ace638), TOBN(0xde4e4a55, 0x920f43ff), + TOBN(0xe5e4144a, 0xd673c017), TOBN(0x667417ae, 0x6f6e05ea), + TOBN(0x613416ae, 0xdcd1bd56), TOBN(0x5eb36201, 0x86693711), + TOBN(0x2d7bc504, 0x3a1aa914), TOBN(0x175a1299, 0x76dc5975), + TOBN(0xe900e0f2, 0x3fc8125c), TOBN(0x569ef68c, 0x11198875), + TOBN(0x9012db63, 0x63a113b4), TOBN(0xe3bd3f56, 0x98835766), + TOBN(0xa5c94a52, 0x76412dea), TOBN(0xad9e2a09, 0xaa735e5c), + TOBN(0x405a984c, 0x508b65e9), TOBN(0xbde4a1d1, 0x6df1a0d1), + TOBN(0x1a9433a1, 0xdfba80da), TOBN(0xe9192ff9, 0x9440ad2e), + TOBN(0x9f649696, 0x5099fe92), TOBN(0x25ddb65c, 0x0b27a54a), + TOBN(0x178279dd, 0xc590da61), TOBN(0x5479a999, 0xfbde681a), + TOBN(0xd0e84e05, 0x013fe162), TOBN(0xbe11dc92, 0x632d471b), + TOBN(0xdf0b0c45, 0xfc0e089f), TOBN(0x04fb15b0, 0x4c144025), + TOBN(0xa61d5fc2, 0x13c99927), TOBN(0xa033e9e0, 0x3de2eb35), + TOBN(0xf8185d5c, 0xb8dacbb4), TOBN(0x9a88e265, 0x8644549d), + TOBN(0xf717af62, 0x54671ff6), TOBN(0x4bd4241b, 0x5fa58603), + TOBN(0x06fba40b, 0xe67773c0), TOBN(0xc1d933d2, 0x6a2847e9), + TOBN(0xf4f5acf3, 0x689e2c70), TOBN(0x92aab0e7, 0x46bafd31), + TOBN(0x798d76aa, 0x3473f6e5), TOBN(0xcc6641db, 0x93141934), + TOBN(0xcae27757, 0xd31e535e), TOBN(0x04cc43b6, 0x87c2ee11), + TOBN(0x8d1f9675, 0x2e029ffa), TOBN(0xc2150672, 0xe4cc7a2c), + TOBN(0x3b03c1e0, 0x8d68b013), TOBN(0xa9d6816f, 0xedf298f3), + TOBN(0x1bfbb529, 0xa2804464), TOBN(0x95a52fae, 0x5db22125), + TOBN(0x55b32160, 0x0e1cb64e), TOBN(0x004828f6, 0x7e7fc9fe), + TOBN(0x13394b82, 0x1bb0fb93), TOBN(0xb6293a2d, 0x35f1a920), + TOBN(0xde35ef21, 0xd145d2d9), TOBN(0xbe6225b3, 0xbb8fa603), + TOBN(0x00fc8f6b, 0x32cf252d), TOBN(0xa28e52e6, 0x117cf8c2), + TOBN(0x9d1dc89b, 0x4c371e6d), TOBN(0xcebe0675, 0x36ef0f28), + TOBN(0x5de05d09, 0xa4292f81), TOBN(0xa8303593, 0x353e3083), + TOBN(0xa1715b0a, 0x7e37a9bb), TOBN(0x8c56f61e, 0x2b8faec3), + TOBN(0x52507431, 0x33c9b102), TOBN(0x0130cefc, 0xa44431f0), + TOBN(0x56039fa0, 0xbd865cfb), TOBN(0x4b03e578, 0xbc5f1dd7), + TOBN(0x40edf2e4, 0xbabe7224), TOBN(0xc752496d, 0x3a1988f6), + TOBN(0xd1572d3b, 0x564beb6b), TOBN(0x0db1d110, 0x39a1c608), + TOBN(0x568d1934, 0x16f60126), TOBN(0x05ae9668, 0xf354af33), + TOBN(0x19de6d37, 0xc92544f2), TOBN(0xcc084353, 0xa35837d5), + TOBN(0xcbb6869c, 0x1a514ece), TOBN(0xb633e728, 0x2e1d1066), + TOBN(0xf15dd69f, 0x936c581c), TOBN(0x96e7b8ce, 0x7439c4f9), + TOBN(0x5e676f48, 0x2e448a5b), TOBN(0xb2ca7d5b, 0xfd916bbb), + TOBN(0xd55a2541, 0xf5024025), TOBN(0x47bc5769, 0xe4c2d937), + TOBN(0x7d31b92a, 0x0362189f), TOBN(0x83f3086e, 0xef7816f9), + TOBN(0xf9f46d94, 0xb587579a), TOBN(0xec2d22d8, 0x30e76c5f), + TOBN(0x27d57461, 0xb000ffcf), TOBN(0xbb7e65f9, 0x364ffc2c), + TOBN(0x7c7c9477, 0x6652a220), TOBN(0x61618f89, 0xd696c981), + TOBN(0x5021701d, 0x89effff3), TOBN(0xf2c8ff8e, 0x7c314163), + TOBN(0x2da413ad, 0x8efb4d3e), TOBN(0x937b5adf, 0xce176d95), + TOBN(0x22867d34, 0x2a67d51c), TOBN(0x262b9b10, 0x18eb3ac9), + TOBN(0x4e314fe4, 0xc43ff28b), TOBN(0x76476627, 0x6a664e7a), + TOBN(0x3e90e40b, 0xb7a565c2), TOBN(0x8588993a, 0xc1acf831), + TOBN(0xd7b501d6, 0x8f938829), TOBN(0x996627ee, 0x3edd7d4c), + TOBN(0x37d44a62, 0x90cd34c7), TOBN(0xa8327499, 0xf3833e8d), + TOBN(0x2e18917d, 0x4bf50353), TOBN(0x85dd726b, 0x556765fb), + TOBN(0x54fe65d6, 0x93d5ab66), TOBN(0x3ddbaced, 0x915c25fe), + TOBN(0xa799d9a4, 0x12f22e85), TOBN(0xe2a24867, 0x6d06f6bc), + TOBN(0xf4f1ee56, 0x43ca1637), TOBN(0xfda2828b, 0x61ece30a), + TOBN(0x758c1a3e, 0xa2dee7a6), TOBN(0xdcde2f3c, 0x734b2284), + TOBN(0xaba445d2, 0x4eaba6ad), TOBN(0x35aaf668, 0x76cee0a7), + TOBN(0x7e0b04a9, 0xe5aa049a), TOBN(0xe74083ad, 0x91103e84), + TOBN(0xbeb183ce, 0x40afecc3), TOBN(0x6b89de9f, 0xea043f7a),} + , + {TOBN(0x0e299d23, 0xfe67ba66), TOBN(0x91450760, 0x93cf2f34), + TOBN(0xf45b5ea9, 0x97fcf913), TOBN(0x5be00843, 0x8bd7ddda), + TOBN(0x358c3e05, 0xd53ff04d), TOBN(0xbf7ccdc3, 0x5de91ef7), + TOBN(0xad684dbf, 0xb69ec1a0), TOBN(0x367e7cf2, 0x801fd997), + TOBN(0x0ca1f3b7, 0xb0dc8595), TOBN(0x27de4608, 0x9f1d9f2e), + TOBN(0x1af3bf39, 0xbadd82a7), TOBN(0x79356a79, 0x65862448), + TOBN(0xc0602345, 0xf5f9a052), TOBN(0x1a8b0f89, 0x139a42f9), + TOBN(0xb53eee42, 0x844d40fc), TOBN(0x93b0bfe5, 0x4e5b6368), + TOBN(0x5434dd02, 0xc024789c), TOBN(0x90dca9ea, 0x41b57bfc), + TOBN(0x8aa898e2, 0x243398df), TOBN(0xf607c834, 0x894a94bb), + TOBN(0xbb07be97, 0xc2c99b76), TOBN(0x6576ba67, 0x18c29302), + TOBN(0x3d79efcc, 0xe703a88c), TOBN(0xf259ced7, 0xb6a0d106), + TOBN(0x0f893a5d, 0xc8de610b), TOBN(0xe8c515fb, 0x67e223ce), + TOBN(0x7774bfa6, 0x4ead6dc5), TOBN(0x89d20f95, 0x925c728f), + TOBN(0x7a1e0966, 0x098583ce), TOBN(0xa2eedb94, 0x93f2a7d7), + TOBN(0x1b282097, 0x4c304d4a), TOBN(0x0842e3da, 0xc077282d), + TOBN(0xe4d972a3, 0x3b9e2d7b), TOBN(0x7cc60b27, 0xc48218ff), + TOBN(0x8fc70838, 0x84149d91), TOBN(0x5c04346f, 0x2f461ecc), + TOBN(0xebe9fdf2, 0x614650a9), TOBN(0x5e35b537, 0xc1f666ac), + TOBN(0x645613d1, 0x88babc83), TOBN(0x88cace3a, 0xc5e1c93e), + TOBN(0x209ca375, 0x3de92e23), TOBN(0xccb03cc8, 0x5fbbb6e3), + TOBN(0xccb90f03, 0xd7b1487e), TOBN(0xfa9c2a38, 0xc710941f), + TOBN(0x756c3823, 0x6724ceed), TOBN(0x3a902258, 0x192d0323), + TOBN(0xb150e519, 0xea5e038e), TOBN(0xdcba2865, 0xc7427591), + TOBN(0xe549237f, 0x78890732), TOBN(0xc443bef9, 0x53fcb4d9), + TOBN(0x9884d8a6, 0xeb3480d6), TOBN(0x8a35b6a1, 0x3048b186), + TOBN(0xb4e44716, 0x65e9a90a), TOBN(0x45bf380d, 0x653006c0), + TOBN(0x8f3f820d, 0x4fe9ae3b), TOBN(0x244a35a0, 0x979a3b71), + TOBN(0xa1010e9d, 0x74cd06ff), TOBN(0x9c17c7df, 0xaca3eeac), + TOBN(0x74c86cd3, 0x8063aa2b), TOBN(0x8595c4b3, 0x734614ff), + TOBN(0xa3de00ca, 0x990f62cc), TOBN(0xd9bed213, 0xca0c3be5), + TOBN(0x7886078a, 0xdf8ce9f5), TOBN(0xddb27ce3, 0x5cd44444), + TOBN(0xed374a66, 0x58926ddd), TOBN(0x138b2d49, 0x908015b8), + TOBN(0x886c6579, 0xde1f7ab8), TOBN(0x888b9aa0, 0xc3020b7a), + TOBN(0xd3ec034e, 0x3a96e355), TOBN(0xba65b0b8, 0xf30fbe9a), + TOBN(0x064c8e50, 0xff21367a), TOBN(0x1f508ea4, 0x0b04b46e), + TOBN(0x98561a49, 0x747c866c), TOBN(0xbbb1e5fe, 0x0518a062), + TOBN(0x20ff4e8b, 0xecdc3608), TOBN(0x7f55cded, 0x20184027), + TOBN(0x8d73ec95, 0xf38c85f0), TOBN(0x5b589fdf, 0x8bc3b8c3), + TOBN(0xbe95dd98, 0x0f12b66f), TOBN(0xf5bd1a09, 0x0e338e01), + TOBN(0x65163ae5, 0x5e915918), TOBN(0x6158d6d9, 0x86f8a46b), + TOBN(0x8466b538, 0xeeebf99c), TOBN(0xca8761f6, 0xbca477ef), + TOBN(0xaf3449c2, 0x9ebbc601), TOBN(0xef3b0f41, 0xe0c3ae2f), + TOBN(0xaa6c577d, 0x5de63752), TOBN(0xe9166601, 0x64682a51), + TOBN(0x5a3097be, 0xfc15aa1e), TOBN(0x40d12548, 0xb54b0745), + TOBN(0x5bad4706, 0x519a5f12), TOBN(0xed03f717, 0xa439dee6), + TOBN(0x0794bb6c, 0x4a02c499), TOBN(0xf725083d, 0xcffe71d2), + TOBN(0x2cad7519, 0x0f3adcaf), TOBN(0x7f68ea1c, 0x43729310), + TOBN(0xe747c8c7, 0xb7ffd977), TOBN(0xec104c35, 0x80761a22), + TOBN(0x8395ebaf, 0x5a3ffb83), TOBN(0xfb3261f4, 0xe4b63db7), + TOBN(0x53544960, 0xd883e544), TOBN(0x13520d70, 0x8cc2eeb8), + TOBN(0x08f6337b, 0xd3d65f99), TOBN(0x83997db2, 0x781cf95b), + TOBN(0xce6ff106, 0x0dbd2c01), TOBN(0x4f8eea6b, 0x1f9ce934), + TOBN(0x546f7c4b, 0x0e993921), TOBN(0x6236a324, 0x5e753fc7), + TOBN(0x65a41f84, 0xa16022e9), TOBN(0x0c18d878, 0x43d1dbb2), + TOBN(0x73c55640, 0x2d4cef9c), TOBN(0xa0428108, 0x70444c74), + TOBN(0x68e4f15e, 0x9afdfb3c), TOBN(0x49a56143, 0x5bdfb6df), + TOBN(0xa9bc1bd4, 0x5f823d97), TOBN(0xbceb5970, 0xea111c2a), + TOBN(0x366b455f, 0xb269bbc4), TOBN(0x7cd85e1e, 0xe9bc5d62), + TOBN(0xc743c41c, 0x4f18b086), TOBN(0xa4b40990, 0x95294fb9), + TOBN(0x9c7c581d, 0x26ee8382), TOBN(0xcf17dcc5, 0x359d638e), + TOBN(0xee8273ab, 0xb728ae3d), TOBN(0x1d112926, 0xf821f047), + TOBN(0x11498477, 0x50491a74), TOBN(0x687fa761, 0xfde0dfb9), + TOBN(0x2c258022, 0x7ea435ab), TOBN(0x6b8bdb94, 0x91ce7e3f), + TOBN(0x4c5b5dc9, 0x3bf834aa), TOBN(0x04371819, 0x4f6c7e4b), + TOBN(0xc284e00a, 0x3736bcad), TOBN(0x0d881118, 0x21ae8f8d), + TOBN(0xf9cf0f82, 0xf48c8e33), TOBN(0xa11fd075, 0xa1bf40db), + TOBN(0xdceab0de, 0xdc2733e5), TOBN(0xc560a8b5, 0x8e986bd7), + TOBN(0x48dd1fe2, 0x3929d097), TOBN(0x3885b290, 0x92f188f1), + TOBN(0x0f2ae613, 0xda6fcdac), TOBN(0x9054303e, 0xb662a46c), + TOBN(0xb6871e44, 0x0738042a), TOBN(0x98e6a977, 0xbdaf6449), + TOBN(0xd8bc0650, 0xd1c9df1b), TOBN(0xef3d6451, 0x36e098f9), + TOBN(0x03fbae82, 0xb6d72d28), TOBN(0x77ca9db1, 0xf5d84080), + TOBN(0x8a112cff, 0xa58efc1c), TOBN(0x518d761c, 0xc564cb4a), + TOBN(0x69b5740e, 0xf0d1b5ce), TOBN(0x717039cc, 0xe9eb1785), + TOBN(0x3fe29f90, 0x22f53382), TOBN(0x8e54ba56, 0x6bc7c95c), + TOBN(0x9c806d8a, 0xf7f91d0f), TOBN(0x3b61b0f1, 0xa82a5728), + TOBN(0x4640032d, 0x94d76754), TOBN(0x273eb5de, 0x47d834c6), + TOBN(0x2988abf7, 0x7b4e4d53), TOBN(0xb7ce66bf, 0xde401777), + TOBN(0x9fba6b32, 0x715071b3), TOBN(0x82413c24, 0xad3a1a98), + TOBN(0x5b7fc8c4, 0xe0e8ad93), TOBN(0xb5679aee, 0x5fab868d), + TOBN(0xb1f9d2fa, 0x2b3946f3), TOBN(0x458897dc, 0x5685b50a), + TOBN(0x1e98c930, 0x89d0caf3), TOBN(0x39564c5f, 0x78642e92), + TOBN(0x1b77729a, 0x0dbdaf18), TOBN(0xf9170722, 0x579e82e6), + TOBN(0x680c0317, 0xe4515fa5), TOBN(0xf85cff84, 0xfb0c790f), + TOBN(0xc7a82aab, 0x6d2e0765), TOBN(0x7446bca9, 0x35c82b32), + TOBN(0x5de607aa, 0x6d63184f), TOBN(0x7c1a46a8, 0x262803a6), + TOBN(0xd218313d, 0xaebe8035), TOBN(0x92113ffd, 0xc73c51f8), + TOBN(0x4b38e083, 0x12e7e46c), TOBN(0x69d0a37a, 0x56126bd5), + TOBN(0xfb3f324b, 0x73c07e04), TOBN(0xa0c22f67, 0x8fda7267), + TOBN(0x8f2c0051, 0x4d2c7d8f), TOBN(0xbc45ced3, 0xcbe2cae5), + TOBN(0xe1c6cf07, 0xa8f0f277), TOBN(0xbc392312, 0x1eb99a98), + TOBN(0x75537b7e, 0x3cc8ac85), TOBN(0x8d725f57, 0xdd02753b), + TOBN(0xfd05ff64, 0xb737df2f), TOBN(0x55fe8712, 0xf6d2531d), + TOBN(0x57ce04a9, 0x6ab6b01c), TOBN(0x69a02a89, 0x7cd93724), + TOBN(0x4f82ac35, 0xcf86699b), TOBN(0x8242d3ad, 0x9cb4b232), + TOBN(0x713d0f65, 0xd62105e5), TOBN(0xbb222bfa, 0x2d29be61), + TOBN(0xf2f9a79e, 0x6cfbef09), TOBN(0xfc24d8d3, 0xd5d6782f), + TOBN(0x5db77085, 0xd4129967), TOBN(0xdb81c3cc, 0xdc3c2a43), + TOBN(0x9d655fc0, 0x05d8d9a3), TOBN(0x3f5d057a, 0x54298026), + TOBN(0x1157f56d, 0x88c54694), TOBN(0xb26baba5, 0x9b09573e), + TOBN(0x2cab03b0, 0x22adffd1), TOBN(0x60a412c8, 0xdd69f383), + TOBN(0xed76e98b, 0x54b25039), TOBN(0xd4ee67d3, 0x687e714d), + TOBN(0x87739648, 0x7b00b594), TOBN(0xce419775, 0xc9ef709b), + TOBN(0x40f76f85, 0x1c203a40), TOBN(0x30d352d6, 0xeafd8f91), + TOBN(0xaf196d3d, 0x95578dd2), TOBN(0xea4bb3d7, 0x77cc3f3d), + TOBN(0x42a5bd03, 0xb98e782b), TOBN(0xac958c40, 0x0624920d), + TOBN(0xb838134c, 0xfc56fcc8), TOBN(0x86ec4ccf, 0x89572e5e), + TOBN(0x69c43526, 0x9be47be0), TOBN(0x323b7dd8, 0xcb28fea1), + TOBN(0xfa5538ba, 0x3a6c67e5), TOBN(0xef921d70, 0x1d378e46), + TOBN(0xf92961fc, 0x3c4b880e), TOBN(0x3f6f914e, 0x98940a67), + TOBN(0xa990eb0a, 0xfef0ff39), TOBN(0xa6c2920f, 0xf0eeff9c), + TOBN(0xca804166, 0x51b8d9a3), TOBN(0x42531bc9, 0x0ffb0db1), + TOBN(0x72ce4718, 0xaa82e7ce), TOBN(0x6e199913, 0xdf574741), + TOBN(0xd5f1b13d, 0xd5d36946), TOBN(0x8255dc65, 0xf68f0194), + TOBN(0xdc9df4cd, 0x8710d230), TOBN(0x3453c20f, 0x138c1988), + TOBN(0x9af98dc0, 0x89a6ef01), TOBN(0x4dbcc3f0, 0x9857df85), + TOBN(0x34805601, 0x5c1ad924), TOBN(0x40448da5, 0xd0493046), + TOBN(0xf629926d, 0x4ee343e2), TOBN(0x6343f1bd, 0x90e8a301), + TOBN(0xefc93491, 0x40815b3f), TOBN(0xf882a423, 0xde8f66fb), + TOBN(0x3a12d5f4, 0xe7db9f57), TOBN(0x7dfba38a, 0x3c384c27), + TOBN(0x7a904bfd, 0x6fc660b1), TOBN(0xeb6c5db3, 0x2773b21c), + TOBN(0xc350ee66, 0x1cdfe049), TOBN(0x9baac0ce, 0x44540f29), + TOBN(0xbc57b6ab, 0xa5ec6aad), TOBN(0x167ce8c3, 0x0a7c1baa), + TOBN(0xb23a03a5, 0x53fb2b56), TOBN(0x6ce141e7, 0x4e057f78), + TOBN(0x796525c3, 0x89e490d9), TOBN(0x0bc95725, 0xa31a7e75), + TOBN(0x1ec56791, 0x1220fd06), TOBN(0x716e3a3c, 0x408b0bd6), + TOBN(0x31cd6bf7, 0xe8ebeba9), TOBN(0xa7326ca6, 0xbee6b670), + TOBN(0x3d9f851c, 0xcd090c43), TOBN(0x561e8f13, 0xf12c3988), + TOBN(0x50490b6a, 0x904b7be4), TOBN(0x61690ce1, 0x0410737b), + TOBN(0x299e9a37, 0x0f009052), TOBN(0x258758f0, 0xf026092e), + TOBN(0x9fa255f3, 0xfdfcdc0f), TOBN(0xdbc9fb1f, 0xc0e1bcd2), + TOBN(0x35f9dd6e, 0x24651840), TOBN(0xdca45a84, 0xa5c59abc), + TOBN(0x103d396f, 0xecca4938), TOBN(0x4532da0a, 0xb97b3f29), + TOBN(0xc4135ea5, 0x1999a6bf), TOBN(0x3aa9505a, 0x5e6bf2ee), + TOBN(0xf77cef06, 0x3f5be093), TOBN(0x97d1a0f8, 0xa943152e), + TOBN(0x2cb0ebba, 0x2e1c21dd), TOBN(0xf41b29fc, 0x2c6797c4), + TOBN(0xc6e17321, 0xb300101f), TOBN(0x4422b0e9, 0xd0d79a89), + TOBN(0x49e4901c, 0x92f1bfc4), TOBN(0x06ab1f8f, 0xe1e10ed9), + TOBN(0x84d35577, 0xdb2926b8), TOBN(0xca349d39, 0x356e8ec2), + TOBN(0x70b63d32, 0x343bf1a9), TOBN(0x8fd3bd28, 0x37d1a6b1), + TOBN(0x0454879c, 0x316865b4), TOBN(0xee959ff6, 0xc458efa2), + TOBN(0x0461dcf8, 0x9706dc3f), TOBN(0x737db0e2, 0x164e4b2e), + TOBN(0x09262680, 0x2f8843c8), TOBN(0x54498bbc, 0x7745e6f6), + TOBN(0x359473fa, 0xa29e24af), TOBN(0xfcc3c454, 0x70aa87a1), + TOBN(0xfd2c4bf5, 0x00573ace), TOBN(0xb65b514e, 0x28dd1965), + TOBN(0xe46ae7cf, 0x2193e393), TOBN(0x60e9a4e1, 0xf5444d97), + TOBN(0xe7594e96, 0x00ff38ed), TOBN(0x43d84d2f, 0x0a0e0f02), + TOBN(0x8b6db141, 0xee398a21), TOBN(0xb88a56ae, 0xe3bcc5be), + TOBN(0x0a1aa52f, 0x373460ea), TOBN(0x20da1a56, 0x160bb19b), + TOBN(0xfb54999d, 0x65bf0384), TOBN(0x71a14d24, 0x5d5a180e), + TOBN(0xbc44db7b, 0x21737b04), TOBN(0xd84fcb18, 0x01dd8e92), + TOBN(0x80de937b, 0xfa44b479), TOBN(0x53505499, 0x5c98fd4f), + TOBN(0x1edb12ab, 0x28f08727), TOBN(0x4c58b582, 0xa5f3ef53), + TOBN(0xbfb236d8, 0x8327f246), TOBN(0xc3a3bfaa, 0x4d7df320), + TOBN(0xecd96c59, 0xb96024f2), TOBN(0xfc293a53, 0x7f4e0433), + TOBN(0x5341352b, 0x5acf6e10), TOBN(0xc50343fd, 0xafe652c3), + TOBN(0x4af3792d, 0x18577a7f), TOBN(0xe1a4c617, 0xaf16823d), + TOBN(0x9b26d0cd, 0x33425d0a), TOBN(0x306399ed, 0x9b7bc47f), + TOBN(0x2a792f33, 0x706bb20b), TOBN(0x31219614, 0x98111055), + TOBN(0x864ec064, 0x87f5d28b), TOBN(0x11392d91, 0x962277fd), + TOBN(0xb5aa7942, 0xbb6aed5f), TOBN(0x080094dc, 0x47e799d9), + TOBN(0x4afa588c, 0x208ba19b), TOBN(0xd3e7570f, 0x8512f284), + TOBN(0xcbae64e6, 0x02f5799a), TOBN(0xdeebe7ef, 0x514b9492), + TOBN(0x30300f98, 0xe5c298ff), TOBN(0x17f561be, 0x3678361f), + TOBN(0xf52ff312, 0x98cb9a16), TOBN(0x6233c3bc, 0x5562d490), + TOBN(0x7bfa15a1, 0x92e3a2cb), TOBN(0x961bcfd1, 0xe6365119), + TOBN(0x3bdd29bf, 0x2c8c53b1), TOBN(0x739704df, 0x822844ba), + TOBN(0x7dacfb58, 0x7e7b754b), TOBN(0x23360791, 0xa806c9b9), + TOBN(0xe7eb88c9, 0x23504452), TOBN(0x2983e996, 0x852c1783), + TOBN(0xdd4ae529, 0x958d881d), TOBN(0x026bae03, 0x262c7b3c), + TOBN(0x3a6f9193, 0x960b52d1), TOBN(0xd0980f90, 0x92696cfb), + TOBN(0x4c1f428c, 0xd5f30851), TOBN(0x94dfed27, 0x2a4f6630), + TOBN(0x4df53772, 0xfc5d48a4), TOBN(0xdd2d5a2f, 0x933260ce), + TOBN(0x574115bd, 0xd44cc7a5), TOBN(0x4ba6b20d, 0xbd12533a), + TOBN(0x30e93cb8, 0x243057c9), TOBN(0x794c486a, 0x14de320e), + TOBN(0xe925d4ce, 0xf21496e4), TOBN(0xf951d198, 0xec696331), + TOBN(0x9810e2de, 0x3e8d812f), TOBN(0xd0a47259, 0x389294ab), + TOBN(0x513ba2b5, 0x0e3bab66), TOBN(0x462caff5, 0xabad306f), + TOBN(0xe2dc6d59, 0xaf04c49e), TOBN(0x1aeb8750, 0xe0b84b0b), + TOBN(0xc034f12f, 0x2f7d0ca2), TOBN(0x6d2e8128, 0xe06acf2f), + TOBN(0x801f4f83, 0x21facc2f), TOBN(0xa1170c03, 0xf40ef607), + TOBN(0xfe0a1d4f, 0x7805a99c), TOBN(0xbde56a36, 0xcc26aba5), + TOBN(0x5b1629d0, 0x35531f40), TOBN(0xac212c2b, 0x9afa6108), + TOBN(0x30a06bf3, 0x15697be5), TOBN(0x6f0545dc, 0x2c63c7c1), + TOBN(0x5d8cb842, 0x7ccdadaf), TOBN(0xd52e379b, 0xac7015bb), + TOBN(0xc4f56147, 0xf462c23e), TOBN(0xd44a4298, 0x46bc24b0), + TOBN(0xbc73d23a, 0xe2856d4f), TOBN(0x61cedd8c, 0x0832bcdf), + TOBN(0x60953556, 0x99f241d7), TOBN(0xee4adbd7, 0x001a349d), + TOBN(0x0b35bf6a, 0xaa89e491), TOBN(0x7f0076f4, 0x136f7546), + TOBN(0xd19a18ba, 0x9264da3d), TOBN(0x6eb2d2cd, 0x62a7a28b), + TOBN(0xcdba941f, 0x8761c971), TOBN(0x1550518b, 0xa3be4a5d), + TOBN(0xd0e8e2f0, 0x57d0b70c), TOBN(0xeea8612e, 0xcd133ba3), + TOBN(0x814670f0, 0x44416aec), TOBN(0x424db6c3, 0x30775061), + TOBN(0xd96039d1, 0x16213fd1), TOBN(0xc61e7fa5, 0x18a3478f), + TOBN(0xa805bdcc, 0xcb0c5021), TOBN(0xbdd6f3a8, 0x0cc616dd), + TOBN(0x06009667, 0x5d97f7e2), TOBN(0x31db0fc1, 0xaf0bf4b6), + TOBN(0x23680ed4, 0x5491627a), TOBN(0xb99a3c66, 0x7d741fb1), + TOBN(0xe9bb5f55, 0x36b1ff92), TOBN(0x29738577, 0x512b388d), + TOBN(0xdb8a2ce7, 0x50fcf263), TOBN(0x385346d4, 0x6c4f7b47), + TOBN(0xbe86c5ef, 0x31631f9e), TOBN(0xbf91da21, 0x03a57a29), + TOBN(0xc3b1f796, 0x7b23f821), TOBN(0x0f7d00d2, 0x770db354), + TOBN(0x8ffc6c3b, 0xd8fe79da), TOBN(0xcc5e8c40, 0xd525c996), + TOBN(0x4640991d, 0xcfff632a), TOBN(0x64d97e8c, 0x67112528), + TOBN(0xc232d973, 0x02f1cd1e), TOBN(0xce87eacb, 0x1dd212a4), + TOBN(0x6e4c8c73, 0xe69802f7), TOBN(0x12ef0290, 0x1fffddbd), + TOBN(0x941ec74e, 0x1bcea6e2), TOBN(0xd0b54024, 0x3cb92cbb), + TOBN(0x809fb9d4, 0x7e8f9d05), TOBN(0x3bf16159, 0xf2992aae), + TOBN(0xad40f279, 0xf8a7a838), TOBN(0x11aea631, 0x05615660), + TOBN(0xbf52e6f1, 0xa01f6fa1), TOBN(0xef046995, 0x3dc2aec9), + TOBN(0x785dbec9, 0xd8080711), TOBN(0xe1aec60a, 0x9fdedf76), + TOBN(0xece797b5, 0xfa21c126), TOBN(0xc66e898f, 0x05e52732), + TOBN(0x39bb69c4, 0x08811fdb), TOBN(0x8bfe1ef8, 0x2fc7f082), + TOBN(0xc8e7a393, 0x174f4138), TOBN(0xfba8ad1d, 0xd58d1f98), + TOBN(0xbc21d0ce, 0xbfd2fd5b), TOBN(0x0b839a82, 0x6ee60d61), + TOBN(0xaacf7658, 0xafd22253), TOBN(0xb526bed8, 0xaae396b3), + TOBN(0xccc1bbc2, 0x38564464), TOBN(0x9e3ff947, 0x8c45bc73), + TOBN(0xcde9bca3, 0x58188a78), TOBN(0x138b8ee0, 0xd73bf8f7), + TOBN(0x5c7e234c, 0x4123c489), TOBN(0x66e69368, 0xfa643297), + TOBN(0x0629eeee, 0x39a15fa3), TOBN(0x95fab881, 0xa9e2a927), + TOBN(0xb2497007, 0xeafbb1e1), TOBN(0xd75c9ce6, 0xe75b7a93), + TOBN(0x3558352d, 0xefb68d78), TOBN(0xa2f26699, 0x223f6396), + TOBN(0xeb911ecf, 0xe469b17a), TOBN(0x62545779, 0xe72d3ec2), + TOBN(0x8ea47de7, 0x82cb113f), TOBN(0xebe4b086, 0x4e1fa98d), + TOBN(0xec2d5ed7, 0x8cdfedb1), TOBN(0xa535c077, 0xfe211a74), + TOBN(0x9678109b, 0x11d244c5), TOBN(0xf17c8bfb, 0xbe299a76), + TOBN(0xb651412e, 0xfb11fbc4), TOBN(0xea0b5482, 0x94ab3f65), + TOBN(0xd8dffd95, 0x0cf78243), TOBN(0x2e719e57, 0xce0361d4), + TOBN(0x9007f085, 0x304ddc5b), TOBN(0x095e8c6d, 0x4daba2ea), + TOBN(0x5a33cdb4, 0x3f9d28a9), TOBN(0x85b95cd8, 0xe2283003), + TOBN(0xbcd6c819, 0xb9744733), TOBN(0x29c5f538, 0xfc7f5783), + TOBN(0x6c49b2fa, 0xd59038e4), TOBN(0x68349cc1, 0x3bbe1018), + TOBN(0xcc490c1d, 0x21830ee5), TOBN(0x36f9c4ee, 0xe9bfa297), + TOBN(0x58fd7294, 0x48de1a94), TOBN(0xaadb13a8, 0x4e8f2cdc), + TOBN(0x515eaaa0, 0x81313dba), TOBN(0xc76bb468, 0xc2152dd8), + TOBN(0x357f8d75, 0xa653dbf8), TOBN(0xe4d8c4d1, 0xb14ac143), + TOBN(0xbdb8e675, 0xb055cb40), TOBN(0x898f8e7b, 0x977b5167), + TOBN(0xecc65651, 0xb82fb863), TOBN(0x56544814, 0x6d88f01f), + TOBN(0xb0928e95, 0x263a75a9), TOBN(0xcfb6836f, 0x1a22fcda), + TOBN(0x651d14db, 0x3f3bd37c), TOBN(0x1d3837fb, 0xb6ad4664), + TOBN(0x7c5fb538, 0xff4f94ab), TOBN(0x7243c712, 0x6d7fb8f2), + TOBN(0xef13d60c, 0xa85c5287), TOBN(0x18cfb7c7, 0x4bb8dd1b), + TOBN(0x82f9bfe6, 0x72908219), TOBN(0x35c4592b, 0x9d5144ab), + TOBN(0x52734f37, 0x9cf4b42f), TOBN(0x6bac55e7, 0x8c60ddc4), + TOBN(0xb5cd811e, 0x94dea0f6), TOBN(0x259ecae4, 0xe18cc1a3), + TOBN(0x6a0e836e, 0x15e660f8), TOBN(0x6c639ea6, 0x0e02bff2), + TOBN(0x8721b8cb, 0x7e1026fd), TOBN(0x9e73b50b, 0x63261942), + TOBN(0xb8c70974, 0x77f01da3), TOBN(0x1839e6a6, 0x8268f57f), + TOBN(0x571b9415, 0x5150b805), TOBN(0x1892389e, 0xf92c7097), + TOBN(0x8d69c18e, 0x4a084b95), TOBN(0x7014c512, 0xbe5b495c), + TOBN(0x4780db36, 0x1b07523c), TOBN(0x2f6219ce, 0x2c1c64fa), + TOBN(0xc38b81b0, 0x602c105a), TOBN(0xab4f4f20, 0x5dc8e360), + TOBN(0x20d3c982, 0xcf7d62d2), TOBN(0x1f36e29d, 0x23ba8150), + TOBN(0x48ae0bf0, 0x92763f9e), TOBN(0x7a527e6b, 0x1d3a7007), + TOBN(0xb4a89097, 0x581a85e3), TOBN(0x1f1a520f, 0xdc158be5), + TOBN(0xf98db37d, 0x167d726e), TOBN(0x8802786e, 0x1113e862)} + , + {TOBN(0xefb2149e, 0x36f09ab0), TOBN(0x03f163ca, 0x4a10bb5b), + TOBN(0xd0297045, 0x06e20998), TOBN(0x56f0af00, 0x1b5a3bab), + TOBN(0x7af4cfec, 0x70880e0d), TOBN(0x7332a66f, 0xbe3d913f), + TOBN(0x32e6c84a, 0x7eceb4bd), TOBN(0xedc4a79a, 0x9c228f55), + TOBN(0xc37c7dd0, 0xc55c4496), TOBN(0xa6a96357, 0x25bbabd2), + TOBN(0x5b7e63f2, 0xadd7f363), TOBN(0x9dce3782, 0x2e73f1df), + TOBN(0xe1e5a16a, 0xb2b91f71), TOBN(0xe4489823, 0x5ba0163c), + TOBN(0xf2759c32, 0xf6e515ad), TOBN(0xa5e2f1f8, 0x8615eecf), + TOBN(0x74519be7, 0xabded551), TOBN(0x03d358b8, 0xc8b74410), + TOBN(0x4d00b10b, 0x0e10d9a9), TOBN(0x6392b0b1, 0x28da52b7), + TOBN(0x6744a298, 0x0b75c904), TOBN(0xc305b0ae, 0xa8f7f96c), + TOBN(0x042e421d, 0x182cf932), TOBN(0xf6fc5d50, 0x9e4636ca), + TOBN(0x795847c9, 0xd64cc78c), TOBN(0x6c50621b, 0x9b6cb27b), + TOBN(0x07099bf8, 0xdf8022ab), TOBN(0x48f862eb, 0xc04eda1d), + TOBN(0xd12732ed, 0xe1603c16), TOBN(0x19a80e0f, 0x5c9a9450), + TOBN(0xe2257f54, 0xb429b4fc), TOBN(0x66d3b2c6, 0x45460515), + TOBN(0x6ca4f87e, 0x822e37be), TOBN(0x73f237b4, 0x253bda4e), + TOBN(0xf747f3a2, 0x41190aeb), TOBN(0xf06fa36f, 0x804cf284), + TOBN(0x0a6bbb6e, 0xfc621c12), TOBN(0x5d624b64, 0x40b80ec6), + TOBN(0x4b072425, 0x7ba556f3), TOBN(0x7fa0c354, 0x3e2d20a8), + TOBN(0xe921fa31, 0xe3229d41), TOBN(0xa929c652, 0x94531bd4), + TOBN(0x84156027, 0xa6d38209), TOBN(0xf3d69f73, 0x6bdb97bd), + TOBN(0x8906d19a, 0x16833631), TOBN(0x68a34c2e, 0x03d51be3), + TOBN(0xcb59583b, 0x0e511cd8), TOBN(0x99ce6bfd, 0xfdc132a8), + TOBN(0x3facdaaa, 0xffcdb463), TOBN(0x658bbc1a, 0x34a38b08), + TOBN(0x12a801f8, 0xf1a9078d), TOBN(0x1567bcf9, 0x6ab855de), + TOBN(0xe08498e0, 0x3572359b), TOBN(0xcf0353e5, 0x8659e68b), + TOBN(0xbb86e9c8, 0x7d23807c), TOBN(0xbc08728d, 0x2198e8a2), + TOBN(0x8de2b7bc, 0x453cadd6), TOBN(0x203900a7, 0xbc0bc1f8), + TOBN(0xbcd86e47, 0xa6abd3af), TOBN(0x911cac12, 0x8502effb), + TOBN(0x2d550242, 0xec965469), TOBN(0x0e9f7692, 0x29e0017e), + TOBN(0x633f078f, 0x65979885), TOBN(0xfb87d449, 0x4cf751ef), + TOBN(0xe1790e4b, 0xfc25419a), TOBN(0x36467203, 0x4bff3cfd), + TOBN(0xc8db6386, 0x25b6e83f), TOBN(0x6cc69f23, 0x6cad6fd2), + TOBN(0x0219e45a, 0x6bc68bb9), TOBN(0xe43d79b6, 0x297f7334), + TOBN(0x7d445368, 0x465dc97c), TOBN(0x4b9eea32, 0x2a0b949a), + TOBN(0x1b96c6ba, 0x6102d021), TOBN(0xeaafac78, 0x2f4461ea), + TOBN(0xd4b85c41, 0xc49f19a8), TOBN(0x275c28e4, 0xcf538875), + TOBN(0x35451a9d, 0xdd2e54e0), TOBN(0x6991adb5, 0x0605618b), + TOBN(0x5b8b4bcd, 0x7b36cd24), TOBN(0x372a4f8c, 0x56f37216), + TOBN(0xc890bd73, 0xa6a5da60), TOBN(0x6f083da0, 0xdc4c9ff0), + TOBN(0xf4e14d94, 0xf0536e57), TOBN(0xf9ee1eda, 0xaaec8243), + TOBN(0x571241ec, 0x8bdcf8e7), TOBN(0xa5db8271, 0x0b041e26), + TOBN(0x9a0b9a99, 0xe3fff040), TOBN(0xcaaf21dd, 0x7c271202), + TOBN(0xb4e2b2e1, 0x4f0dd2e8), TOBN(0xe77e7c4f, 0x0a377ac7), + TOBN(0x69202c3f, 0x0d7a2198), TOBN(0xf759b7ff, 0x28200eb8), + TOBN(0xc87526ed, 0xdcfe314e), TOBN(0xeb84c524, 0x53d5cf99), + TOBN(0xb1b52ace, 0x515138b6), TOBN(0x5aa7ff8c, 0x23fca3f4), + TOBN(0xff0b13c3, 0xb9791a26), TOBN(0x960022da, 0xcdd58b16), + TOBN(0xdbd55c92, 0x57aad2de), TOBN(0x3baaaaa3, 0xf30fe619), + TOBN(0x9a4b2346, 0x0d881efd), TOBN(0x506416c0, 0x46325e2a), + TOBN(0x91381e76, 0x035c18d4), TOBN(0xb3bb68be, 0xf27817b0), + TOBN(0x15bfb8bf, 0x5116f937), TOBN(0x7c64a586, 0xc1268943), + TOBN(0x71e25cc3, 0x8419a2c8), TOBN(0x9fd6b0c4, 0x8335f463), + TOBN(0x4bf0ba3c, 0xe8ee0e0e), TOBN(0x6f6fba60, 0x298c21fa), + TOBN(0x57d57b39, 0xae66bee0), TOBN(0x292d5130, 0x22672544), + TOBN(0xf451105d, 0xbab093b3), TOBN(0x012f59b9, 0x02839986), + TOBN(0x8a915802, 0x3474a89c), TOBN(0x048c919c, 0x2de03e97), + TOBN(0xc476a2b5, 0x91071cd5), TOBN(0x791ed89a, 0x034970a5), + TOBN(0x89bd9042, 0xe1b7994b), TOBN(0x8eaf5179, 0xa1057ffd), + TOBN(0x6066e2a2, 0xd551ee10), TOBN(0x87a8f1d8, 0x727e09a6), + TOBN(0x00d08bab, 0x2c01148d), TOBN(0x6da8e4f1, 0x424f33fe), + TOBN(0x466d17f0, 0xcf9a4e71), TOBN(0xff502010, 0x3bf5cb19), + TOBN(0xdccf97d8, 0xd062ecc0), TOBN(0x80c0d9af, 0x81d80ac4), + TOBN(0xe87771d8, 0x033f2876), TOBN(0xb0186ec6, 0x7d5cc3db), + TOBN(0x58e8bb80, 0x3bc9bc1d), TOBN(0x4d1395cc, 0x6f6ef60e), + TOBN(0xa73c62d6, 0x186244a0), TOBN(0x918e5f23, 0x110a5b53), + TOBN(0xed4878ca, 0x741b7eab), TOBN(0x3038d71a, 0xdbe03e51), + TOBN(0x840204b7, 0xa93c3246), TOBN(0x21ab6069, 0xa0b9b4cd), + TOBN(0xf5fa6e2b, 0xb1d64218), TOBN(0x1de6ad0e, 0xf3d56191), + TOBN(0x570aaa88, 0xff1929c7), TOBN(0xc6df4c6b, 0x640e87b5), + TOBN(0xde8a74f2, 0xc65f0ccc), TOBN(0x8b972fd5, 0xe6f6cc01), + TOBN(0x3fff36b6, 0x0b846531), TOBN(0xba7e45e6, 0x10a5e475), + TOBN(0x84a1d10e, 0x4145b6c5), TOBN(0xf1f7f91a, 0x5e046d9d), + TOBN(0x0317a692, 0x44de90d7), TOBN(0x951a1d4a, 0xf199c15e), + TOBN(0x91f78046, 0xc9d73deb), TOBN(0x74c82828, 0xfab8224f), + TOBN(0xaa6778fc, 0xe7560b90), TOBN(0xb4073e61, 0xa7e824ce), + TOBN(0xff0d693c, 0xd642eba8), TOBN(0x7ce2e57a, 0x5dccef38), + TOBN(0x89c2c789, 0x1df1ad46), TOBN(0x83a06922, 0x098346fd), + TOBN(0x2d715d72, 0xda2fc177), TOBN(0x7b6dd71d, 0x85b6cf1d), + TOBN(0xc60a6d0a, 0x73fa9cb0), TOBN(0xedd3992e, 0x328bf5a9), + TOBN(0xc380ddd0, 0x832c8c82), TOBN(0xd182d410, 0xa2a0bf50), + TOBN(0x7d9d7438, 0xd9a528db), TOBN(0xe8b1a0e9, 0xcaf53994), + TOBN(0xddd6e5fe, 0x0e19987c), TOBN(0xacb8df03, 0x190b059d), + TOBN(0x53703a32, 0x8300129f), TOBN(0x1f637662, 0x68c43bfd), + TOBN(0xbcbd1913, 0x00e54051), TOBN(0x812fcc62, 0x7bf5a8c5), + TOBN(0x3f969d5f, 0x29fb85da), TOBN(0x72f4e00a, 0x694759e8), + TOBN(0x426b6e52, 0x790726b7), TOBN(0x617bbc87, 0x3bdbb209), + TOBN(0x511f8bb9, 0x97aee317), TOBN(0x812a4096, 0xe81536a8), + TOBN(0x137dfe59, 0x3ac09b9b), TOBN(0x0682238f, 0xba8c9a7a), + TOBN(0x7072ead6, 0xaeccb4bd), TOBN(0x6a34e9aa, 0x692ba633), + TOBN(0xc82eaec2, 0x6fff9d33), TOBN(0xfb753512, 0x1d4d2b62), + TOBN(0x1a0445ff, 0x1d7aadab), TOBN(0x65d38260, 0xd5f6a67c), + TOBN(0x6e62fb08, 0x91cfb26f), TOBN(0xef1e0fa5, 0x5c7d91d6), + TOBN(0x47e7c7ba, 0x33db72cd), TOBN(0x017cbc09, 0xfa7c74b2), + TOBN(0x3c931590, 0xf50a503c), TOBN(0xcac54f60, 0x616baa42), + TOBN(0x9b6cd380, 0xb2369f0f), TOBN(0x97d3a70d, 0x23c76151), + TOBN(0x5f9dd6fc, 0x9862a9c6), TOBN(0x044c4ab2, 0x12312f51), + TOBN(0x035ea0fd, 0x834a2ddc), TOBN(0x49e6b862, 0xcc7b826d), + TOBN(0xb03d6883, 0x62fce490), TOBN(0x62f2497a, 0xb37e36e9), + TOBN(0x04b005b6, 0xc6458293), TOBN(0x36bb5276, 0xe8d10af7), + TOBN(0xacf2dc13, 0x8ee617b8), TOBN(0x470d2d35, 0xb004b3d4), + TOBN(0x06790832, 0xfeeb1b77), TOBN(0x2bb75c39, 0x85657f9c), + TOBN(0xd70bd4ed, 0xc0f60004), TOBN(0xfe797ecc, 0x219b018b), + TOBN(0x9b5bec2a, 0x753aebcc), TOBN(0xdaf9f3dc, 0xc939eca5), + TOBN(0xd6bc6833, 0xd095ad09), TOBN(0x98abdd51, 0xdaa4d2fc), + TOBN(0xd9840a31, 0x8d168be5), TOBN(0xcf7c10e0, 0x2325a23c), + TOBN(0xa5c02aa0, 0x7e6ecfaf), TOBN(0x2462e7e6, 0xb5bfdf18), + TOBN(0xab2d8a8b, 0xa0cc3f12), TOBN(0x68dd485d, 0xbc672a29), + TOBN(0x72039752, 0x596f2cd3), TOBN(0x5d3eea67, 0xa0cf3d8d), + TOBN(0x810a1a81, 0xe6602671), TOBN(0x8f144a40, 0x14026c0c), + TOBN(0xbc753a6d, 0x76b50f85), TOBN(0xc4dc21e8, 0x645cd4a4), + TOBN(0xc5262dea, 0x521d0378), TOBN(0x802b8e0e, 0x05011c6f), + TOBN(0x1ba19cbb, 0x0b4c19ea), TOBN(0x21db64b5, 0xebf0aaec), + TOBN(0x1f394ee9, 0x70342f9d), TOBN(0x93a10aee, 0x1bc44a14), + TOBN(0xa7eed31b, 0x3efd0baa), TOBN(0x6e7c824e, 0x1d154e65), + TOBN(0xee23fa81, 0x9966e7ee), TOBN(0x64ec4aa8, 0x05b7920d), + TOBN(0x2d44462d, 0x2d90aad4), TOBN(0xf44dd195, 0xdf277ad5), + TOBN(0x8d6471f1, 0xbb46b6a1), TOBN(0x1e65d313, 0xfd885090), + TOBN(0x33a800f5, 0x13a977b4), TOBN(0xaca9d721, 0x0797e1ef), + TOBN(0x9a5a85a0, 0xfcff6a17), TOBN(0x9970a3f3, 0x1eca7cee), + TOBN(0xbb9f0d6b, 0xc9504be3), TOBN(0xe0c504be, 0xadd24ee2), + TOBN(0x7e09d956, 0x77fcc2f4), TOBN(0xef1a5227, 0x65bb5fc4), + TOBN(0x145d4fb1, 0x8b9286aa), TOBN(0x66fd0c5d, 0x6649028b), + TOBN(0x98857ceb, 0x1bf4581c), TOBN(0xe635e186, 0xaca7b166), + TOBN(0x278ddd22, 0x659722ac), TOBN(0xa0903c4c, 0x1db68007), + TOBN(0x366e4589, 0x48f21402), TOBN(0x31b49c14, 0xb96abda2), + TOBN(0x329c4b09, 0xe0403190), TOBN(0x97197ca3, 0xd29f43fe), + TOBN(0x8073dd1e, 0x274983d8), TOBN(0xda1a3bde, 0x55717c8f), + TOBN(0xfd3d4da2, 0x0361f9d1), TOBN(0x1332d081, 0x4c7de1ce), + TOBN(0x9b7ef7a3, 0xaa6d0e10), TOBN(0x17db2e73, 0xf54f1c4a), + TOBN(0xaf3dffae, 0x4cd35567), TOBN(0xaaa2f406, 0xe56f4e71), + TOBN(0x8966759e, 0x7ace3fc7), TOBN(0x9594eacf, 0x45a8d8c6), + TOBN(0x8de3bd8b, 0x91834e0e), TOBN(0xafe4ca53, 0x548c0421), + TOBN(0xfdd7e856, 0xe6ee81c6), TOBN(0x8f671beb, 0x6b891a3a), + TOBN(0xf7a58f2b, 0xfae63829), TOBN(0x9ab186fb, 0x9c11ac9f), + TOBN(0x8d6eb369, 0x10b5be76), TOBN(0x046b7739, 0xfb040bcd), + TOBN(0xccb4529f, 0xcb73de88), TOBN(0x1df0fefc, 0xcf26be03), + TOBN(0xad7757a6, 0xbcfcd027), TOBN(0xa8786c75, 0xbb3165ca), + TOBN(0xe9db1e34, 0x7e99a4d9), TOBN(0x99ee86df, 0xb06c504b), + TOBN(0x5b7c2ddd, 0xc15c9f0a), TOBN(0xdf87a734, 0x4295989e), + TOBN(0x59ece47c, 0x03d08fda), TOBN(0xb074d3dd, 0xad5fc702), + TOBN(0x20407903, 0x51a03776), TOBN(0x2bb1f77b, 0x2a608007), + TOBN(0x25c58f4f, 0xe1153185), TOBN(0xe6df62f6, 0x766e6447), + TOBN(0xefb3d1be, 0xed51275a), TOBN(0x5de47dc7, 0x2f0f483f), + TOBN(0x7932d98e, 0x97c2bedf), TOBN(0xd5c11927, 0x0219f8a1), + TOBN(0x9d751200, 0xa73a294e), TOBN(0x5f88434a, 0x9dc20172), + TOBN(0xd28d9fd3, 0xa26f506a), TOBN(0xa890cd31, 0x9d1dcd48), + TOBN(0x0aebaec1, 0x70f4d3b4), TOBN(0xfd1a1369, 0x0ffc8d00), + TOBN(0xb9d9c240, 0x57d57838), TOBN(0x45929d26, 0x68bac361), + TOBN(0x5a2cd060, 0x25b15ca6), TOBN(0x4b3c83e1, 0x6e474446), + TOBN(0x1aac7578, 0xee1e5134), TOBN(0xa418f5d6, 0xc91e2f41), + TOBN(0x6936fc8a, 0x213ed68b), TOBN(0x860ae7ed, 0x510a5224), + TOBN(0x63660335, 0xdef09b53), TOBN(0x641b2897, 0xcd79c98d), + TOBN(0x29bd38e1, 0x01110f35), TOBN(0x79c26f42, 0x648b1937), + TOBN(0x64dae519, 0x9d9164f4), TOBN(0xd85a2310, 0x0265c273), + TOBN(0x7173dd5d, 0x4b07e2b1), TOBN(0xd144c4cb, 0x8d9ea221), + TOBN(0xe8b04ea4, 0x1105ab14), TOBN(0x92dda542, 0xfe80d8f1), + TOBN(0xe9982fa8, 0xcf03dce6), TOBN(0x8b5ea965, 0x1a22cffc), + TOBN(0xf7f4ea7f, 0x3fad88c4), TOBN(0x62db773e, 0x6a5ba95c), + TOBN(0xd20f02fb, 0x93f24567), TOBN(0xfd46c69a, 0x315257ca), + TOBN(0x0ac74cc7, 0x8bcab987), TOBN(0x46f31c01, 0x5ceca2f5), + TOBN(0x40aedb59, 0x888b219e), TOBN(0xe50ecc37, 0xe1fccd02), + TOBN(0x1bcd9dad, 0x911f816c), TOBN(0x583cc1ec, 0x8db9b00c), + TOBN(0xf3cd2e66, 0xa483bf11), TOBN(0xfa08a6f5, 0xb1b2c169), + TOBN(0xf375e245, 0x4be9fa28), TOBN(0x99a7ffec, 0x5b6d011f), + TOBN(0x6a3ebddb, 0xc4ae62da), TOBN(0x6cea00ae, 0x374aef5d), + TOBN(0xab5fb98d, 0x9d4d05bc), TOBN(0x7cba1423, 0xd560f252), + TOBN(0x49b2cc21, 0x208490de), TOBN(0x1ca66ec3, 0xbcfb2879), + TOBN(0x7f1166b7, 0x1b6fb16f), TOBN(0xfff63e08, 0x65fe5db3), + TOBN(0xb8345abe, 0x8b2610be), TOBN(0xb732ed80, 0x39de3df4), + TOBN(0x0e24ed50, 0x211c32b4), TOBN(0xd10d8a69, 0x848ff27d), + TOBN(0xc1074398, 0xed4de248), TOBN(0xd7cedace, 0x10488927), + TOBN(0xa4aa6bf8, 0x85673e13), TOBN(0xb46bae91, 0x6daf30af), + TOBN(0x07088472, 0xfcef7ad8), TOBN(0x61151608, 0xd4b35e97), + TOBN(0xbcfe8f26, 0xdde29986), TOBN(0xeb84c4c7, 0xd5a34c79), + TOBN(0xc1eec55c, 0x164e1214), TOBN(0x891be86d, 0xa147bb03), + TOBN(0x9fab4d10, 0x0ba96835), TOBN(0xbf01e9b8, 0xa5c1ae9f), + TOBN(0x6b4de139, 0xb186ebc0), TOBN(0xd5c74c26, 0x85b91bca), + TOBN(0x5086a99c, 0xc2d93854), TOBN(0xeed62a7b, 0xa7a9dfbc), + TOBN(0x8778ed6f, 0x76b7618a), TOBN(0xbff750a5, 0x03b66062), + TOBN(0x4cb7be22, 0xb65186db), TOBN(0x369dfbf0, 0xcc3a6d13), + TOBN(0xc7dab26c, 0x7191a321), TOBN(0x9edac3f9, 0x40ed718e), + TOBN(0xbc142b36, 0xd0cfd183), TOBN(0xc8af82f6, 0x7c991693), + TOBN(0xb3d1e4d8, 0x97ce0b2a), TOBN(0xe6d7c87f, 0xc3a55cdf), + TOBN(0x35846b95, 0x68b81afe), TOBN(0x018d12af, 0xd3c239d8), + TOBN(0x2b2c6208, 0x01206e15), TOBN(0xe0e42453, 0xa3b882c6), + TOBN(0x854470a3, 0xa50162d5), TOBN(0x08157478, 0x7017a62a), + TOBN(0x18bd3fb4, 0x820357c7), TOBN(0x992039ae, 0x6f1458ad), + TOBN(0x9a1df3c5, 0x25b44aa1), TOBN(0x2d780357, 0xed3d5281), + TOBN(0x58cf7e4d, 0xc77ad4d4), TOBN(0xd49a7998, 0xf9df4fc4), + TOBN(0x4465a8b5, 0x1d71205e), TOBN(0xa0ee0ea6, 0x649254aa), + TOBN(0x4b5eeecf, 0xab7bd771), TOBN(0x6c873073, 0x35c262b9), + TOBN(0xdc5bd648, 0x3c9d61e7), TOBN(0x233d6d54, 0x321460d2), + TOBN(0xd20c5626, 0xfc195bcc), TOBN(0x25445958, 0x04d78b63), + TOBN(0xe03fcb3d, 0x17ec8ef3), TOBN(0x54b690d1, 0x46b8f781), + TOBN(0x82fa2c8a, 0x21230646), TOBN(0xf51aabb9, 0x084f418c), + TOBN(0xff4fbec1, 0x1a30ba43), TOBN(0x6a5acf73, 0x743c9df7), + TOBN(0x1da2b357, 0xd635b4d5), TOBN(0xc3de68dd, 0xecd5c1da), + TOBN(0xa689080b, 0xd61af0dd), TOBN(0xdea5938a, 0xd665bf99), + TOBN(0x0231d71a, 0xfe637294), TOBN(0x01968aa6, 0xa5a81cd8), + TOBN(0x11252d50, 0x048e63b5), TOBN(0xc446bc52, 0x6ca007e9), + TOBN(0xef8c50a6, 0x96d6134b), TOBN(0x9361fbf5, 0x9e09a05c), + TOBN(0xf17f85a6, 0xdca3291a), TOBN(0xb178d548, 0xff251a21), + TOBN(0x87f6374b, 0xa4df3915), TOBN(0x566ce1bf, 0x2fd5d608), + TOBN(0x425cba4d, 0x7de35102), TOBN(0x6b745f8f, 0x58c5d5e2), + TOBN(0x88402af6, 0x63122edf), TOBN(0x3190f9ed, 0x3b989a89), + TOBN(0x4ad3d387, 0xebba3156), TOBN(0xef385ad9, 0xc7c469a5), + TOBN(0xb08281de, 0x3f642c29), TOBN(0x20be0888, 0x910ffb88), + TOBN(0xf353dd4a, 0xd5292546), TOBN(0x3f1627de, 0x8377a262), + TOBN(0xa5faa013, 0xeefcd638), TOBN(0x8f3bf626, 0x74cc77c3), + TOBN(0x32618f65, 0xa348f55e), TOBN(0x5787c0dc, 0x9fefeb9e), + TOBN(0xf1673aa2, 0xd9a23e44), TOBN(0x88dfa993, 0x4e10690d), + TOBN(0x1ced1b36, 0x2bf91108), TOBN(0x9193ceca, 0x3af48649), + TOBN(0xfb34327d, 0x2d738fc5), TOBN(0x6697b037, 0x975fee6c), + TOBN(0x2f485da0, 0xc04079a5), TOBN(0x2cdf5735, 0x2feaa1ac), + TOBN(0x76944420, 0xbd55659e), TOBN(0x7973e32b, 0x4376090c), + TOBN(0x86bb4fe1, 0x163b591a), TOBN(0x10441aed, 0xc196f0ca), + TOBN(0x3b431f4a, 0x045ad915), TOBN(0x6c11b437, 0xa4afacb1), + TOBN(0x30b0c7db, 0x71fdbbd8), TOBN(0xb642931f, 0xeda65acd), + TOBN(0x4baae6e8, 0x9c92b235), TOBN(0xa73bbd0e, 0x6b3993a1), + TOBN(0xd06d60ec, 0x693dd031), TOBN(0x03cab91b, 0x7156881c), + TOBN(0xd615862f, 0x1db3574b), TOBN(0x485b0185, 0x64bb061a), + TOBN(0x27434988, 0xa0181e06), TOBN(0x2cd61ad4, 0xc1c0c757), + TOBN(0x3effed5a, 0x2ff9f403), TOBN(0x8dc98d8b, 0x62239029), + TOBN(0x2206021e, 0x1f17b70d), TOBN(0xafbec0ca, 0xbf510015), + TOBN(0x9fed7164, 0x80130dfa), TOBN(0x306dc2b5, 0x8a02dcf5), + TOBN(0x48f06620, 0xfeb10fc0), TOBN(0x78d1e1d5, 0x5a57cf51), + TOBN(0xadef8c5a, 0x192ef710), TOBN(0x88afbd4b, 0x3b7431f9), + TOBN(0x7e1f7407, 0x64250c9e), TOBN(0x6e31318d, 0xb58bec07), + TOBN(0xfd4fc4b8, 0x24f89b4e), TOBN(0x65a5dd88, 0x48c36a2a), + TOBN(0x4f1eccff, 0xf024baa7), TOBN(0x22a21cf2, 0xcba94650), + TOBN(0x95d29dee, 0x42a554f7), TOBN(0x828983a5, 0x002ec4ba), + TOBN(0x8112a1f7, 0x8badb73d), TOBN(0x79ea8897, 0xa27c1839), + TOBN(0x8969a5a7, 0xd065fd83), TOBN(0xf49af791, 0xb262a0bc), + TOBN(0xfcdea8b6, 0xaf2b5127), TOBN(0x10e913e1, 0x564c2dbc), + TOBN(0x51239d14, 0xbc21ef51), TOBN(0xe51c3ceb, 0x4ce57292), + TOBN(0x795ff068, 0x47bbcc3b), TOBN(0x86b46e1e, 0xbd7e11e6), + TOBN(0x0ea6ba23, 0x80041ef4), TOBN(0xd72fe505, 0x6262342e), + TOBN(0x8abc6dfd, 0x31d294d4), TOBN(0xbbe017a2, 0x1278c2c9), + TOBN(0xb1fcfa09, 0xb389328a), TOBN(0x322fbc62, 0xd01771b5), + TOBN(0x04c0d063, 0x60b045bf), TOBN(0xdb652edc, 0x10e52d01), + TOBN(0x50ef932c, 0x03ec6627), TOBN(0xde1b3b2d, 0xc1ee50e3), + TOBN(0x5ab7bdc5, 0xdc37a90d), TOBN(0xfea67213, 0x31e33a96), + TOBN(0x6482b5cb, 0x4f2999aa), TOBN(0x38476cc6, 0xb8cbf0dd), + TOBN(0x93ebfacb, 0x173405bb), TOBN(0x15cdafe7, 0xe52369ec), + TOBN(0xd42d5ba4, 0xd935b7db), TOBN(0x648b6004, 0x1c99a4cd), + TOBN(0x785101bd, 0xa3b5545b), TOBN(0x4bf2c38a, 0x9dd67faf), + TOBN(0xb1aadc63, 0x4442449c), TOBN(0xe0e9921a, 0x33ad4fb8), + TOBN(0x5c552313, 0xaa686d82), TOBN(0xdee635fa, 0x465d866c), + TOBN(0xbc3c224a, 0x18ee6e8a), TOBN(0xeed748a6, 0xed42e02f), + TOBN(0xe70f930a, 0xd474cd08), TOBN(0x774ea6ec, 0xfff24adf), + TOBN(0x03e2de1c, 0xf3480d4a), TOBN(0xf0d8edc7, 0xbc8acf1a), + TOBN(0xf23e3303, 0x68295a9c), TOBN(0xfadd5f68, 0xc546a97d), + TOBN(0x895597ad, 0x96f8acb1), TOBN(0xbddd49d5, 0x671bdae2), + TOBN(0x16fcd528, 0x21dd43f4), TOBN(0xa5a45412, 0x6619141a)} + , + {TOBN(0x8ce9b6bf, 0xc360e25a), TOBN(0xe6425195, 0x075a1a78), + TOBN(0x9dc756a8, 0x481732f4), TOBN(0x83c0440f, 0x5432b57a), + TOBN(0xc670b3f1, 0xd720281f), TOBN(0x2205910e, 0xd135e051), + TOBN(0xded14b0e, 0xdb052be7), TOBN(0x697b3d27, 0xc568ea39), + TOBN(0x2e599b9a, 0xfb3ff9ed), TOBN(0x28c2e0ab, 0x17f6515c), + TOBN(0x1cbee4fd, 0x474da449), TOBN(0x071279a4, 0x4f364452), + TOBN(0x97abff66, 0x01fbe855), TOBN(0x3ee394e8, 0x5fda51c4), + TOBN(0x190385f6, 0x67597c0b), TOBN(0x6e9fccc6, 0xa27ee34b), + TOBN(0x0b89de93, 0x14092ebb), TOBN(0xf17256bd, 0x428e240c), + TOBN(0xcf89a7f3, 0x93d2f064), TOBN(0x4f57841e, 0xe1ed3b14), + TOBN(0x4ee14405, 0xe708d855), TOBN(0x856aae72, 0x03f1c3d0), + TOBN(0xc8e5424f, 0xbdd7eed5), TOBN(0x3333e4ef, 0x73ab4270), + TOBN(0x3bc77ade, 0xdda492f8), TOBN(0xc11a3aea, 0x78297205), + TOBN(0x5e89a3e7, 0x34931b4c), TOBN(0x17512e2e, 0x9f5694bb), + TOBN(0x5dc349f3, 0x177bf8b6), TOBN(0x232ea4ba, 0x08c7ff3e), + TOBN(0x9c4f9d16, 0xf511145d), TOBN(0xccf109a3, 0x33b379c3), + TOBN(0xe75e7a88, 0xa1f25897), TOBN(0x7ac6961f, 0xa1b5d4d8), + TOBN(0xe3e10773, 0x08f3ed5c), TOBN(0x208a54ec, 0x0a892dfb), + TOBN(0xbe826e19, 0x78660710), TOBN(0x0cf70a97, 0x237df2c8), + TOBN(0x418a7340, 0xed704da5), TOBN(0xa3eeb9a9, 0x08ca33fd), + TOBN(0x49d96233, 0x169bca96), TOBN(0x04d286d4, 0x2da6aafb), + TOBN(0xc09606ec, 0xa0c2fa94), TOBN(0x8869d0d5, 0x23ff0fb3), + TOBN(0xa99937e5, 0xd0150d65), TOBN(0xa92e2503, 0x240c14c9), + TOBN(0x656bf945, 0x108e2d49), TOBN(0x152a733a, 0xa2f59e2b), + TOBN(0xb4323d58, 0x8434a920), TOBN(0xc0af8e93, 0x622103c5), + TOBN(0x667518ef, 0x938dbf9a), TOBN(0xa1843073, 0x83a9cdf2), + TOBN(0x350a94aa, 0x5447ab80), TOBN(0xe5e5a325, 0xc75a3d61), + TOBN(0x74ba507f, 0x68411a9e), TOBN(0x10581fc1, 0x594f70c5), + TOBN(0x60e28570, 0x80eb24a9), TOBN(0x7bedfb4d, 0x488e0cfd), + TOBN(0x721ebbd7, 0xc259cdb8), TOBN(0x0b0da855, 0xbc6390a9), + TOBN(0x2b4d04db, 0xde314c70), TOBN(0xcdbf1fbc, 0x6c32e846), + TOBN(0x33833eab, 0xb162fc9e), TOBN(0x9939b48b, 0xb0dd3ab7), + TOBN(0x5aaa98a7, 0xcb0c9c8c), TOBN(0x75105f30, 0x81c4375c), + TOBN(0xceee5057, 0x5ef1c90f), TOBN(0xb31e065f, 0xc23a17bf), + TOBN(0x5364d275, 0xd4b6d45a), TOBN(0xd363f3ad, 0x62ec8996), + TOBN(0xb5d21239, 0x4391c65b), TOBN(0x84564765, 0xebb41b47), + TOBN(0x20d18ecc, 0x37107c78), TOBN(0xacff3b6b, 0x570c2a66), + TOBN(0x22f975d9, 0x9bd0d845), TOBN(0xef0a0c46, 0xba178fa0), + TOBN(0x1a419651, 0x76b6028e), TOBN(0xc49ec674, 0x248612d4), + TOBN(0x5b6ac4f2, 0x7338af55), TOBN(0x06145e62, 0x7bee5a36), + TOBN(0x33e95d07, 0xe75746b5), TOBN(0x1c1e1f6d, 0xc40c78be), + TOBN(0x967833ef, 0x222ff8e2), TOBN(0x4bedcf6a, 0xb49180ad), + TOBN(0x6b37e9c1, 0x3d7a4c8a), TOBN(0x2748887c, 0x6ddfe760), + TOBN(0xf7055123, 0xaa3a5bbc), TOBN(0x954ff225, 0x7bbb8e74), + TOBN(0xc42b8ab1, 0x97c3dfb9), TOBN(0x55a549b0, 0xcf168154), + TOBN(0xad6748e7, 0xc1b50692), TOBN(0x2775780f, 0x6fc5cbcb), + TOBN(0x4eab80b8, 0xe1c9d7c8), TOBN(0x8c69dae1, 0x3fdbcd56), + TOBN(0x47e6b4fb, 0x9969eace), TOBN(0x002f1085, 0xa705cb5a), + TOBN(0x4e23ca44, 0x6d3fea55), TOBN(0xb4ae9c86, 0xf4810568), + TOBN(0x47bfb91b, 0x2a62f27d), TOBN(0x60deb4c9, 0xd9bac28c), + TOBN(0xa892d894, 0x7de6c34c), TOBN(0x4ee68259, 0x4494587d), + TOBN(0x914ee14e, 0x1a3f8a5b), TOBN(0xbb113eaa, 0x28700385), + TOBN(0x81ca03b9, 0x2115b4c9), TOBN(0x7c163d38, 0x8908cad1), + TOBN(0xc912a118, 0xaa18179a), TOBN(0xe09ed750, 0x886e3081), + TOBN(0xa676e3fa, 0x26f516ca), TOBN(0x753cacf7, 0x8e732f91), + TOBN(0x51592aea, 0x833da8b4), TOBN(0xc626f42f, 0x4cbea8aa), + TOBN(0xef9dc899, 0xa7b56eaf), TOBN(0x00c0e52c, 0x34ef7316), + TOBN(0x5b1e4e24, 0xfe818a86), TOBN(0x9d31e20d, 0xc538be47), + TOBN(0x22eb932d, 0x3ed68974), TOBN(0xe44bbc08, 0x7c4e87c4), + TOBN(0x4121086e, 0x0dde9aef), TOBN(0x8e6b9cff, 0x134f4345), + TOBN(0x96892c1f, 0x711b0eb9), TOBN(0xb905f2c8, 0x780ab954), + TOBN(0xace26309, 0xa20792db), TOBN(0xec8ac9b3, 0x0684e126), + TOBN(0x486ad8b6, 0xb40a2447), TOBN(0x60121fc1, 0x9fe3fb24), + TOBN(0x5626fccf, 0x1a8e3b3f), TOBN(0x4e568622, 0x6ad1f394), + TOBN(0xda7aae0d, 0x196aa5a1), TOBN(0xe0df8c77, 0x1041b5fb), + TOBN(0x451465d9, 0x26b318b7), TOBN(0xc29b6e55, 0x7ab136e9), + TOBN(0x2c2ab48b, 0x71148463), TOBN(0xb5738de3, 0x64454a76), + TOBN(0x54ccf9a0, 0x5a03abe4), TOBN(0x377c0296, 0x0427d58e), + TOBN(0x73f5f0b9, 0x2bb39c1f), TOBN(0x14373f2c, 0xe608d8c5), + TOBN(0xdcbfd314, 0x00fbb805), TOBN(0xdf18fb20, 0x83afdcfb), + TOBN(0x81a57f42, 0x42b3523f), TOBN(0xe958532d, 0x87f650fb), + TOBN(0xaa8dc8b6, 0x8b0a7d7c), TOBN(0x1b75dfb7, 0x150166be), + TOBN(0x90e4f7c9, 0x2d7d1413), TOBN(0x67e2d6b5, 0x9834f597), + TOBN(0x4fd4f4f9, 0xa808c3e8), TOBN(0xaf8237e0, 0xd5281ec1), + TOBN(0x25ab5fdc, 0x84687cee), TOBN(0xc5ded6b1, 0xa5b26c09), + TOBN(0x8e4a5aec, 0xc8ea7650), TOBN(0x23b73e5c, 0x14cc417f), + TOBN(0x2bfb4318, 0x3037bf52), TOBN(0xb61e6db5, 0x78c725d7), + TOBN(0x8efd4060, 0xbbb3e5d7), TOBN(0x2e014701, 0xdbac488e), + TOBN(0xac75cf9a, 0x360aa449), TOBN(0xb70cfd05, 0x79634d08), + TOBN(0xa591536d, 0xfffb15ef), TOBN(0xb2c37582, 0xd07c106c), + TOBN(0xb4293fdc, 0xf50225f9), TOBN(0xc52e175c, 0xb0e12b03), + TOBN(0xf649c3ba, 0xd0a8bf64), TOBN(0x745a8fef, 0xeb8ae3c6), + TOBN(0x30d7e5a3, 0x58321bc3), TOBN(0xb1732be7, 0x0bc4df48), + TOBN(0x1f217993, 0xe9ea5058), TOBN(0xf7a71cde, 0x3e4fd745), + TOBN(0x86cc533e, 0x894c5bbb), TOBN(0x6915c7d9, 0x69d83082), + TOBN(0xa6aa2d05, 0x5815c244), TOBN(0xaeeee592, 0x49b22ce5), + TOBN(0x89e39d13, 0x78135486), TOBN(0x3a275c1f, 0x16b76f2f), + TOBN(0xdb6bcc1b, 0xe036e8f5), TOBN(0x4df69b21, 0x5e4709f5), + TOBN(0xa188b250, 0x2d0f39aa), TOBN(0x622118bb, 0x15a85947), + TOBN(0x2ebf520f, 0xfde0f4fa), TOBN(0xa40e9f29, 0x4860e539), + TOBN(0x7b6a51eb, 0x22b57f0f), TOBN(0x849a33b9, 0x7e80644a), + TOBN(0x50e5d16f, 0x1cf095fe), TOBN(0xd754b54e, 0xec55f002), + TOBN(0x5cfbbb22, 0x236f4a98), TOBN(0x0b0c59e9, 0x066800bb), + TOBN(0x4ac69a8f, 0x5a9a7774), TOBN(0x2b33f804, 0xd6bec948), + TOBN(0xb3729295, 0x32e6c466), TOBN(0x68956d0f, 0x4e599c73), + TOBN(0xa47a249f, 0x155c31cc), TOBN(0x24d80f0d, 0xe1ce284e), + TOBN(0xcd821dfb, 0x988baf01), TOBN(0xe6331a7d, 0xdbb16647), + TOBN(0x1eb8ad33, 0x094cb960), TOBN(0x593cca38, 0xc91bbca5), + TOBN(0x384aac8d, 0x26567456), TOBN(0x40fa0309, 0xc04b6490), + TOBN(0x97834cd6, 0xdab6c8f6), TOBN(0x68a7318d, 0x3f91e55f), + TOBN(0xa00fd04e, 0xfc4d3157), TOBN(0xb56f8ab2, 0x2bf3bdea), + TOBN(0x014f5648, 0x4fa57172), TOBN(0x948c5860, 0x450abdb3), + TOBN(0x342b5df0, 0x0ebd4f08), TOBN(0x3e5168cd, 0x0e82938e), + TOBN(0x7aedc1ce, 0xb0df5dd0), TOBN(0x6bbbc6d9, 0xe5732516), + TOBN(0xc7bfd486, 0x605daaa6), TOBN(0x46fd72b7, 0xbb9a6c9e), + TOBN(0xe4847fb1, 0xa124fb89), TOBN(0x75959cbd, 0xa2d8ffbc), + TOBN(0x42579f65, 0xc8a588ee), TOBN(0x368c92e6, 0xb80b499d), + TOBN(0xea4ef6cd, 0x999a5df1), TOBN(0xaa73bb7f, 0x936fe604), + TOBN(0xf347a70d, 0x6457d188), TOBN(0x86eda86b, 0x8b7a388b), + TOBN(0xb7cdff06, 0x0ccd6013), TOBN(0xbeb1b6c7, 0xd0053fb2), + TOBN(0x0b022387, 0x99240a9f), TOBN(0x1bbb384f, 0x776189b2), + TOBN(0x8695e71e, 0x9066193a), TOBN(0x2eb50097, 0x06ffac7e), + TOBN(0x0654a9c0, 0x4a7d2caa), TOBN(0x6f3fb3d1, 0xa5aaa290), + TOBN(0x835db041, 0xff476e8f), TOBN(0x540b8b0b, 0xc42295e4), + TOBN(0xa5c73ac9, 0x05e214f5), TOBN(0x9a74075a, 0x56a0b638), + TOBN(0x2e4b1090, 0xce9e680b), TOBN(0x57a5b479, 0x6b8d9afa), + TOBN(0x0dca48e7, 0x26bfe65c), TOBN(0x097e391c, 0x7290c307), + TOBN(0x683c462e, 0x6669e72e), TOBN(0xf505be1e, 0x062559ac), + TOBN(0x5fbe3ea1, 0xe3a3035a), TOBN(0x6431ebf6, 0x9cd50da8), + TOBN(0xfd169d5c, 0x1f6407f2), TOBN(0x8d838a95, 0x60fce6b8), + TOBN(0x2a2bfa7f, 0x650006f0), TOBN(0xdfd7dad3, 0x50c0fbb2), + TOBN(0x92452495, 0xccf9ad96), TOBN(0x183bf494, 0xd95635f9), + TOBN(0x02d5df43, 0x4a7bd989), TOBN(0x505385cc, 0xa5431095), + TOBN(0xdd98e67d, 0xfd43f53e), TOBN(0xd61e1a6c, 0x500c34a9), + TOBN(0x5a4b46c6, 0x4a8a3d62), TOBN(0x8469c4d0, 0x247743d2), + TOBN(0x2bb3a13d, 0x88f7e433), TOBN(0x62b23a10, 0x01be5849), + TOBN(0xe83596b4, 0xa63d1a4c), TOBN(0x454e7fea, 0x7d183f3e), + TOBN(0x643fce61, 0x17afb01c), TOBN(0x4e65e5e6, 0x1c4c3638), + TOBN(0x41d85ea1, 0xef74c45b), TOBN(0x2cfbfa66, 0xae328506), + TOBN(0x98b078f5, 0x3ada7da9), TOBN(0xd985fe37, 0xec752fbb), + TOBN(0xeece68fe, 0x5a0148b4), TOBN(0x6f9a55c7, 0x2d78136d), + TOBN(0x232dccc4, 0xd2b729ce), TOBN(0xa27e0dfd, 0x90aafbc4), + TOBN(0x96474452, 0x12b4603e), TOBN(0xa876c551, 0x6b706d14), + TOBN(0xdf145fcf, 0x69a9d412), TOBN(0xe2ab75b7, 0x2d479c34), + TOBN(0x12df9a76, 0x1a23ff97), TOBN(0xc6138992, 0x5d359d10), + TOBN(0x6e51c7ae, 0xfa835f22), TOBN(0x69a79cb1, 0xc0fcc4d9), + TOBN(0xf57f350d, 0x594cc7e1), TOBN(0x3079ca63, 0x3350ab79), + TOBN(0x226fb614, 0x9aff594a), TOBN(0x35afec02, 0x6d59a62b), + TOBN(0x9bee46f4, 0x06ed2c6e), TOBN(0x58da1735, 0x7d939a57), + TOBN(0x44c50402, 0x8fd1797e), TOBN(0xd8853e7c, 0x5ccea6ca), + TOBN(0x4065508d, 0xa35fcd5f), TOBN(0x8965df8c, 0x495ccaeb), + TOBN(0x0f2da850, 0x12e1a962), TOBN(0xee471b94, 0xc1cf1cc4), + TOBN(0xcef19bc8, 0x0a08fb75), TOBN(0x704958f5, 0x81de3591), + TOBN(0x2867f8b2, 0x3aef4f88), TOBN(0x8d749384, 0xea9f9a5f), + TOBN(0x1b385537, 0x8c9049f4), TOBN(0x5be948f3, 0x7b92d8b6), + TOBN(0xd96f725d, 0xb6e2bd6b), TOBN(0x37a222bc, 0x958c454d), + TOBN(0xe7c61abb, 0x8809bf61), TOBN(0x46f07fbc, 0x1346f18d), + TOBN(0xfb567a7a, 0xe87c0d1c), TOBN(0x84a461c8, 0x7ef3d07a), + TOBN(0x0a5adce6, 0xd9278d98), TOBN(0x24d94813, 0x9dfc73e1), + TOBN(0x4f3528b6, 0x054321c3), TOBN(0x2e03fdde, 0x692ea706), + TOBN(0x10e60619, 0x47b533c0), TOBN(0x1a8bc73f, 0x2ca3c055), + TOBN(0xae58d4b2, 0x1bb62b8f), TOBN(0xb2045a73, 0x584a24e3), + TOBN(0x3ab3d5af, 0xbd76e195), TOBN(0x478dd1ad, 0x6938a810), + TOBN(0x6ffab393, 0x6ee3d5cb), TOBN(0xdfb693db, 0x22b361e4), + TOBN(0xf9694496, 0x51dbf1a7), TOBN(0xcab4b4ef, 0x08a2e762), + TOBN(0xe8c92f25, 0xd39bba9a), TOBN(0x850e61bc, 0xf1464d96), + TOBN(0xb7e830e3, 0xdc09508b), TOBN(0xfaf6d2cf, 0x74317655), + TOBN(0x72606ceb, 0xdf690355), TOBN(0x48bb92b3, 0xd0c3ded6), + TOBN(0x65b75484, 0x5c7cf892), TOBN(0xf6cd7ac9, 0xd5d5f01f), + TOBN(0xc2c30a59, 0x96401d69), TOBN(0x91268650, 0xed921878), + TOBN(0x380bf913, 0xb78c558f), TOBN(0x43c0baeb, 0xc8afdaa9), + TOBN(0x377f61d5, 0x54f169d3), TOBN(0xf8da07e3, 0xae5ff20b), + TOBN(0xb676c49d, 0xa8a90ea8), TOBN(0x81c1ff2b, 0x83a29b21), + TOBN(0x383297ac, 0x2ad8d276), TOBN(0x3001122f, 0xba89f982), + TOBN(0xe1d794be, 0x6718e448), TOBN(0x246c1482, 0x7c3e6e13), + TOBN(0x56646ef8, 0x5d26b5ef), TOBN(0x80f5091e, 0x88069cdd), + TOBN(0xc5992e2f, 0x724bdd38), TOBN(0x02e915b4, 0x8471e8c7), + TOBN(0x96ff320a, 0x0d0ff2a9), TOBN(0xbf886487, 0x4384d1a0), + TOBN(0xbbe1e6a6, 0xc93f72d6), TOBN(0xd5f75d12, 0xcad800ea), + TOBN(0xfa40a09f, 0xe7acf117), TOBN(0x32c8cdd5, 0x7581a355), + TOBN(0x74221992, 0x7023c499), TOBN(0xa8afe5d7, 0x38ec3901), + TOBN(0x5691afcb, 0xa90e83f0), TOBN(0x41bcaa03, 0x0b8f8eac), + TOBN(0xe38b5ff9, 0x8d2668d5), TOBN(0x0715281a, 0x7ad81965), + TOBN(0x1bc8fc7c, 0x03c6ce11), TOBN(0xcbbee6e2, 0x8b650436), + TOBN(0x06b00fe8, 0x0cdb9808), TOBN(0x17d6e066, 0xfe3ed315), + TOBN(0x2e9d38c6, 0x4d0b5018), TOBN(0xab8bfd56, 0x844dcaef), + TOBN(0x42894a59, 0x513aed8b), TOBN(0xf77f3b6d, 0x314bd07a), + TOBN(0xbbdecb8f, 0x8e42b582), TOBN(0xf10e2fa8, 0xd2390fe6), + TOBN(0xefb95022, 0x62a2f201), TOBN(0x4d59ea50, 0x50ee32b0), + TOBN(0xd87f7728, 0x6da789a8), TOBN(0xcf98a2cf, 0xf79492c4), + TOBN(0xf9577239, 0x720943c2), TOBN(0xba044cf5, 0x3990b9d0), + TOBN(0x5aa8e823, 0x95f2884a), TOBN(0x834de6ed, 0x0278a0af), + TOBN(0xc8e1ee9a, 0x5f25bd12), TOBN(0x9259ceaa, 0x6f7ab271), + TOBN(0x7e6d97a2, 0x77d00b76), TOBN(0x5c0c6eea, 0xa437832a), + TOBN(0x5232c20f, 0x5606b81d), TOBN(0xabd7b375, 0x0d991ee5), + TOBN(0x4d2bfe35, 0x8632d951), TOBN(0x78f85146, 0x98ed9364), + TOBN(0x951873f0, 0xf30c3282), TOBN(0x0da8ac80, 0xa789230b), + TOBN(0x3ac7789c, 0x5398967f), TOBN(0xa69b8f7f, 0xbdda0fb5), + TOBN(0xe5db7717, 0x6add8545), TOBN(0x1b71cb66, 0x72c49b66), + TOBN(0xd8560739, 0x68421d77), TOBN(0x03840fe8, 0x83e3afea), + TOBN(0xb391dad5, 0x1ec69977), TOBN(0xae243fb9, 0x307f6726), + TOBN(0xc88ac87b, 0xe8ca160c), TOBN(0x5174cced, 0x4ce355f4), + TOBN(0x98a35966, 0xe58ba37d), TOBN(0xfdcc8da2, 0x7817335d), + TOBN(0x5b752830, 0x83fbc7bf), TOBN(0x68e419d4, 0xd9c96984), + TOBN(0x409a39f4, 0x02a40380), TOBN(0x88940faf, 0x1fe977bc), + TOBN(0xc640a94b, 0x8f8edea6), TOBN(0x1e22cd17, 0xed11547d), + TOBN(0xe28568ce, 0x59ffc3e2), TOBN(0x60aa1b55, 0xc1dee4e7), + TOBN(0xc67497c8, 0x837cb363), TOBN(0x06fb438a, 0x105a2bf2), + TOBN(0x30357ec4, 0x500d8e20), TOBN(0x1ad9095d, 0x0670db10), + TOBN(0x7f589a05, 0xc73b7cfd), TOBN(0xf544607d, 0x880d6d28), + TOBN(0x17ba93b1, 0xa20ef103), TOBN(0xad859130, 0x6ba6577b), + TOBN(0x65c91cf6, 0x6fa214a0), TOBN(0xd7d49c6c, 0x27990da5), + TOBN(0xecd9ec8d, 0x20bb569d), TOBN(0xbd4b2502, 0xeeffbc33), + TOBN(0x2056ca5a, 0x6bed0467), TOBN(0x7916a1f7, 0x5b63728c), + TOBN(0xd4f9497d, 0x53a4f566), TOBN(0x89734664, 0x97b56810), + TOBN(0xf8e1da74, 0x0494a621), TOBN(0x82546a93, 0x8d011c68), + TOBN(0x1f3acb19, 0xc61ac162), TOBN(0x52f8fa9c, 0xabad0d3e), + TOBN(0x15356523, 0xb4b7ea43), TOBN(0x5a16ad61, 0xae608125), + TOBN(0xb0bcb87f, 0x4faed184), TOBN(0x5f236b1d, 0x5029f45f), + TOBN(0xd42c7607, 0x0bc6b1fc), TOBN(0xc644324e, 0x68aefce3), + TOBN(0x8e191d59, 0x5c5d8446), TOBN(0xc0208077, 0x13ae1979), + TOBN(0xadcaee55, 0x3ba59cc7), TOBN(0x20ed6d6b, 0xa2cb81ba), + TOBN(0x0952ba19, 0xb6efcffc), TOBN(0x60f12d68, 0x97c0b87c), + TOBN(0x4ee2c7c4, 0x9caa30bc), TOBN(0x767238b7, 0x97fbff4e), + TOBN(0xebc73921, 0x501b5d92), TOBN(0x3279e3df, 0xc2a37737), + TOBN(0x9fc12bc8, 0x6d197543), TOBN(0xfa94dc6f, 0x0a40db4e), + TOBN(0x7392b41a, 0x530ccbbd), TOBN(0x87c82146, 0xea823525), + TOBN(0xa52f984c, 0x05d98d0c), TOBN(0x2ae57d73, 0x5ef6974c), + TOBN(0x9377f7bf, 0x3042a6dd), TOBN(0xb1a007c0, 0x19647a64), + TOBN(0xfaa9079a, 0x0cca9767), TOBN(0x3d81a25b, 0xf68f72d5), + TOBN(0x752067f8, 0xff81578e), TOBN(0x78622150, 0x9045447d), + TOBN(0xc0c22fcf, 0x0505aa6f), TOBN(0x1030f0a6, 0x6bed1c77), + TOBN(0x31f29f15, 0x1f0bd739), TOBN(0x2d7989c7, 0xe6debe85), + TOBN(0x5c070e72, 0x8e677e98), TOBN(0x0a817bd3, 0x06e81fd5), + TOBN(0xc110d830, 0xb0f2ac95), TOBN(0x48d0995a, 0xab20e64e), + TOBN(0x0f3e00e1, 0x7729cd9a), TOBN(0x2a570c20, 0xdd556946), + TOBN(0x912dbcfd, 0x4e86214d), TOBN(0x2d014ee2, 0xcf615498), + TOBN(0x55e2b1e6, 0x3530d76e), TOBN(0xc5135ae4, 0xfd0fd6d1), + TOBN(0x0066273a, 0xd4f3049f), TOBN(0xbb8e9893, 0xe7087477), + TOBN(0x2dba1ddb, 0x14c6e5fd), TOBN(0xdba37886, 0x51f57e6c), + TOBN(0x5aaee0a6, 0x5a72f2cf), TOBN(0x1208bfbf, 0x7bea5642), + TOBN(0xf5c6aa3b, 0x67872c37), TOBN(0xd726e083, 0x43f93224), + TOBN(0x1854daa5, 0x061f1658), TOBN(0xc0016df1, 0xdf0cd2b3), + TOBN(0xc2a3f23e, 0x833d50de), TOBN(0x73b681d2, 0xbbbd3017), + TOBN(0x2f046dc4, 0x3ac343c0), TOBN(0x9c847e7d, 0x85716421), + TOBN(0xe1e13c91, 0x0917eed4), TOBN(0x3fc9eebd, 0x63a1b9c6), + TOBN(0x0f816a72, 0x7fe02299), TOBN(0x6335ccc2, 0x294f3319), + TOBN(0x3820179f, 0x4745c5be), TOBN(0xe647b782, 0x922f066e), + TOBN(0xc22e49de, 0x02cafb8a), TOBN(0x299bc2ff, 0xfcc2eccc), + TOBN(0x9a8feea2, 0x6e0e8282), TOBN(0xa627278b, 0xfe893205), + TOBN(0xa7e19733, 0x7933e47b), TOBN(0xf4ff6b13, 0x2e766402), + TOBN(0xa4d8be0a, 0x98440d9f), TOBN(0x658f5c2f, 0x38938808), + TOBN(0x90b75677, 0xc95b3b3e), TOBN(0xfa044269, 0x3137b6ff), + TOBN(0x077b039b, 0x43c47c29), TOBN(0xcca95dd3, 0x8a6445b2), + TOBN(0x0b498ba4, 0x2333fc4c), TOBN(0x274f8e68, 0xf736a1b1), + TOBN(0x6ca348fd, 0x5f1d4b2e), TOBN(0x24d3be78, 0xa8f10199), + TOBN(0x8535f858, 0xca14f530), TOBN(0xa6e7f163, 0x5b982e51), + TOBN(0x847c8512, 0x36e1bf62), TOBN(0xf6a7c58e, 0x03448418), + TOBN(0x583f3703, 0xf9374ab6), TOBN(0x864f9195, 0x6e564145), + TOBN(0x33bc3f48, 0x22526d50), TOBN(0x9f323c80, 0x1262a496), + TOBN(0xaa97a7ae, 0x3f046a9a), TOBN(0x70da183e, 0xdf8a039a), + TOBN(0x5b68f71c, 0x52aa0ba6), TOBN(0x9be0fe51, 0x21459c2d), + TOBN(0xc1e17eb6, 0xcbc613e5), TOBN(0x33131d55, 0x497ea61c), + TOBN(0x2f69d39e, 0xaf7eded5), TOBN(0x73c2f434, 0xde6af11b), + TOBN(0x4ca52493, 0xa4a375fa), TOBN(0x5f06787c, 0xb833c5c2), + TOBN(0x814e091f, 0x3e6e71cf), TOBN(0x76451f57, 0x8b746666)} + , + {TOBN(0x80f9bdef, 0x694db7e0), TOBN(0xedca8787, 0xb9fcddc6), + TOBN(0x51981c34, 0x03b8dce1), TOBN(0x4274dcf1, 0x70e10ba1), + TOBN(0xf72743b8, 0x6def6d1a), TOBN(0xd25b1670, 0xebdb1866), + TOBN(0xc4491e8c, 0x050c6f58), TOBN(0x2be2b2ab, 0x87fbd7f5), + TOBN(0x3e0e5c9d, 0xd111f8ec), TOBN(0xbcc33f8d, 0xb7c4e760), + TOBN(0x702f9a91, 0xbd392a51), TOBN(0x7da4a795, 0xc132e92d), + TOBN(0x1a0b0ae3, 0x0bb1151b), TOBN(0x54febac8, 0x02e32251), + TOBN(0xea3a5082, 0x694e9e78), TOBN(0xe58ffec1, 0xe4fe40b8), + TOBN(0xf85592fc, 0xd1e0cf9e), TOBN(0xdea75f0d, 0xc0e7b2e8), + TOBN(0xc04215cf, 0xc135584e), TOBN(0x174fc727, 0x2f57092a), + TOBN(0xe7277877, 0xeb930bea), TOBN(0x504caccb, 0x5eb02a5a), + TOBN(0xf9fe08f7, 0xf5241b9b), TOBN(0xe7fb62f4, 0x8d5ca954), + TOBN(0xfbb8349d, 0x29c4120b), TOBN(0x9f94391f, 0xc0d0d915), + TOBN(0xc4074fa7, 0x5410ba51), TOBN(0xa66adbf6, 0x150a5911), + TOBN(0xc164543c, 0x34bfca38), TOBN(0xe0f27560, 0xb9e1ccfc), + TOBN(0x99da0f53, 0xe820219c), TOBN(0xe8234498, 0xc6b4997a), + TOBN(0xcfb88b76, 0x9d4c5423), TOBN(0x9e56eb10, 0xb0521c49), + TOBN(0x418e0b5e, 0xbe8700a1), TOBN(0x00cbaad6, 0xf93cb58a), + TOBN(0xe923fbde, 0xd92a5e67), TOBN(0xca4979ac, 0x1f347f11), + TOBN(0x89162d85, 0x6bc0585b), TOBN(0xdd6254af, 0xac3c70e3), + TOBN(0x7b23c513, 0x516e19e4), TOBN(0x56e2e847, 0xc5c4d593), + TOBN(0x9f727d73, 0x5ce71ef6), TOBN(0x5b6304a6, 0xf79a44c5), + TOBN(0x6638a736, 0x3ab7e433), TOBN(0x1adea470, 0xfe742f83), + TOBN(0xe054b854, 0x5b7fc19f), TOBN(0xf935381a, 0xba1d0698), + TOBN(0x546eab2d, 0x799e9a74), TOBN(0x96239e0e, 0xa949f729), + TOBN(0xca274c6b, 0x7090055a), TOBN(0x835142c3, 0x9020c9b0), + TOBN(0xa405667a, 0xa2e8807f), TOBN(0x29f2c085, 0x1aa3d39e), + TOBN(0xcc555d64, 0x42fc72f5), TOBN(0xe856e0e7, 0xfbeacb3c), + TOBN(0xb5504f9d, 0x918e4936), TOBN(0x65035ef6, 0xb2513982), + TOBN(0x0553a0c2, 0x6f4d9cb9), TOBN(0x6cb10d56, 0xbea85509), + TOBN(0x48d957b7, 0xa242da11), TOBN(0x16a4d3dd, 0x672b7268), + TOBN(0x3d7e637c, 0x8502a96b), TOBN(0x27c7032b, 0x730d463b), + TOBN(0xbdc02b18, 0xe4136a14), TOBN(0xbacf969d, 0x678e32bf), + TOBN(0xc98d89a3, 0xdd9c3c03), TOBN(0x7b92420a, 0x23becc4f), + TOBN(0xd4b41f78, 0xc64d565c), TOBN(0x9f969d00, 0x10f28295), + TOBN(0xec7f7f76, 0xb13d051a), TOBN(0x08945e1e, 0xa92da585), + TOBN(0x55366b7d, 0x5846426f), TOBN(0xe7d09e89, 0x247d441d), + TOBN(0x510b404d, 0x736fbf48), TOBN(0x7fa003d0, 0xe784bd7d), + TOBN(0x25f7614f, 0x17fd9596), TOBN(0x49e0e0a1, 0x35cb98db), + TOBN(0x2c65957b, 0x2e83a76a), TOBN(0x5d40da8d, 0xcddbe0f8), + TOBN(0xf2b8c405, 0x050bad24), TOBN(0x8918426d, 0xc2aa4823), + TOBN(0x2aeab3dd, 0xa38365a7), TOBN(0x72031717, 0x7c91b690), + TOBN(0x8b00d699, 0x60a94120), TOBN(0x478a255d, 0xe99eaeec), + TOBN(0xbf656a5f, 0x6f60aafd), TOBN(0xdfd7cb75, 0x5dee77b3), + TOBN(0x37f68bb4, 0xa595939d), TOBN(0x03556479, 0x28740217), + TOBN(0x8e740e7c, 0x84ad7612), TOBN(0xd89bc843, 0x9044695f), + TOBN(0xf7f3da5d, 0x85a9184d), TOBN(0x562563bb, 0x9fc0b074), + TOBN(0x06d2e6aa, 0xf88a888e), TOBN(0x612d8643, 0x161fbe7c), + TOBN(0x465edba7, 0xf64085e7), TOBN(0xb230f304, 0x29aa8511), + TOBN(0x53388426, 0xcda2d188), TOBN(0x90885735, 0x4b666649), + TOBN(0x6f02ff9a, 0x652f54f6), TOBN(0x65c82294, 0x5fae2bf0), + TOBN(0x7816ade0, 0x62f5eee3), TOBN(0xdcdbdf43, 0xfcc56d70), + TOBN(0x9fb3bba3, 0x54530bb2), TOBN(0xbde3ef77, 0xcb0869ea), + TOBN(0x89bc9046, 0x0b431163), TOBN(0x4d03d7d2, 0xe4819a35), + TOBN(0x33ae4f9e, 0x43b6a782), TOBN(0x216db307, 0x9c88a686), + TOBN(0x91dd88e0, 0x00ffedd9), TOBN(0xb280da9f, 0x12bd4840), + TOBN(0x32a7cb8a, 0x1635e741), TOBN(0xfe14008a, 0x78be02a7), + TOBN(0x3fafb334, 0x1b7ae030), TOBN(0x7fd508e7, 0x5add0ce9), + TOBN(0x72c83219, 0xd607ad51), TOBN(0x0f229c0a, 0x8d40964a), + TOBN(0x1be2c336, 0x1c878da2), TOBN(0xe0c96742, 0xeab2ab86), + TOBN(0x458f8691, 0x3e538cd7), TOBN(0xa7001f6c, 0x8e08ad53), + TOBN(0x52b8c6e6, 0xbf5d15ff), TOBN(0x548234a4, 0x011215dd), + TOBN(0xff5a9d2d, 0x3d5b4045), TOBN(0xb0ffeeb6, 0x4a904190), + TOBN(0x55a3aca4, 0x48607f8b), TOBN(0x8cbd665c, 0x30a0672a), + TOBN(0x87f834e0, 0x42583068), TOBN(0x02da2aeb, 0xf3f6e683), + TOBN(0x6b763e5d, 0x05c12248), TOBN(0x7230378f, 0x65a8aefc), + TOBN(0x93bd80b5, 0x71e8e5ca), TOBN(0x53ab041c, 0xb3b62524), + TOBN(0x1b860513, 0x6c9c552e), TOBN(0xe84d402c, 0xd5524e66), + TOBN(0xa37f3573, 0xf37f5937), TOBN(0xeb0f6c7d, 0xd1e4fca5), + TOBN(0x2965a554, 0xac8ab0fc), TOBN(0x17fbf56c, 0x274676ac), + TOBN(0x2e2f6bd9, 0xacf7d720), TOBN(0x41fc8f88, 0x10224766), + TOBN(0x517a14b3, 0x85d53bef), TOBN(0xdae327a5, 0x7d76a7d1), + TOBN(0x6ad0a065, 0xc4818267), TOBN(0x33aa189b, 0x37c1bbc1), + TOBN(0x64970b52, 0x27392a92), TOBN(0x21699a1c, 0x2d1535ea), + TOBN(0xcd20779c, 0xc2d7a7fd), TOBN(0xe3186059, 0x99c83cf2), + TOBN(0x9b69440b, 0x72c0b8c7), TOBN(0xa81497d7, 0x7b9e0e4d), + TOBN(0x515d5c89, 0x1f5f82dc), TOBN(0x9a7f67d7, 0x6361079e), + TOBN(0xa8da81e3, 0x11a35330), TOBN(0xe44990c4, 0x4b18be1b), + TOBN(0xc7d5ed95, 0xaf103e59), TOBN(0xece8aba7, 0x8dac9261), + TOBN(0xbe82b099, 0x9394b8d3), TOBN(0x6830f09a, 0x16adfe83), + TOBN(0x250a29b4, 0x88172d01), TOBN(0x8b20bd65, 0xcaff9e02), + TOBN(0xb8a7661e, 0xe8a6329a), TOBN(0x4520304d, 0xd3fce920), + TOBN(0xae45da1f, 0x2b47f7ef), TOBN(0xe07f5288, 0x5bffc540), + TOBN(0xf7997009, 0x3464f874), TOBN(0x2244c2cd, 0xa6fa1f38), + TOBN(0x43c41ac1, 0x94d7d9b1), TOBN(0x5bafdd82, 0xc82e7f17), + TOBN(0xdf0614c1, 0x5fda0fca), TOBN(0x74b043a7, 0xa8ae37ad), + TOBN(0x3ba6afa1, 0x9e71734c), TOBN(0x15d5437e, 0x9c450f2e), + TOBN(0x4a5883fe, 0x67e242b1), TOBN(0x5143bdc2, 0x2c1953c2), + TOBN(0x542b8b53, 0xfc5e8920), TOBN(0x363bf9a8, 0x9a9cee08), + TOBN(0x02375f10, 0xc3486e08), TOBN(0x2037543b, 0x8c5e70d2), + TOBN(0x7109bccc, 0x625640b4), TOBN(0xcbc1051e, 0x8bc62c3b), + TOBN(0xf8455fed, 0x803f26ea), TOBN(0x6badceab, 0xeb372424), + TOBN(0xa2a9ce7c, 0x6b53f5f9), TOBN(0x64246595, 0x1b176d99), + TOBN(0xb1298d36, 0xb95c081b), TOBN(0x53505bb8, 0x1d9a9ee6), + TOBN(0x3f6f9e61, 0xf2ba70b0), TOBN(0xd07e16c9, 0x8afad453), + TOBN(0x9f1694bb, 0xe7eb4a6a), TOBN(0xdfebced9, 0x3cb0bc8e), + TOBN(0x92d3dcdc, 0x53868c8b), TOBN(0x174311a2, 0x386107a6), + TOBN(0x4109e07c, 0x689b4e64), TOBN(0x30e4587f, 0x2df3dcb6), + TOBN(0x841aea31, 0x0811b3b2), TOBN(0x6144d41d, 0x0cce43ea), + TOBN(0x464c4581, 0x2a9a7803), TOBN(0xd03d371f, 0x3e158930), + TOBN(0xc676d7f2, 0xb1f3390b), TOBN(0x9f7a1b8c, 0xa5b61272), + TOBN(0x4ebebfc9, 0xc2e127a9), TOBN(0x4602500c, 0x5dd997bf), + TOBN(0x7f09771c, 0x4711230f), TOBN(0x058eb37c, 0x020f09c1), + TOBN(0xab693d4b, 0xfee5e38b), TOBN(0x9289eb1f, 0x4653cbc0), + TOBN(0xbecf46ab, 0xd51b9cf5), TOBN(0xd2aa9c02, 0x9f0121af), + TOBN(0x36aaf7d2, 0xe90dc274), TOBN(0x909e4ea0, 0x48b95a3c), + TOBN(0xe6b70496, 0x6f32dbdb), TOBN(0x672188a0, 0x8b030b3e), + TOBN(0xeeffe5b3, 0xcfb617e2), TOBN(0x87e947de, 0x7c82709e), + TOBN(0xa44d2b39, 0x1770f5a7), TOBN(0xe4d4d791, 0x0e44eb82), + TOBN(0x42e69d1e, 0x3f69712a), TOBN(0xbf11c4d6, 0xac6a820e), + TOBN(0xb5e7f3e5, 0x42c4224c), TOBN(0xd6b4e81c, 0x449d941c), + TOBN(0x5d72bd16, 0x5450e878), TOBN(0x6a61e28a, 0xee25ac54), + TOBN(0x33272094, 0xe6f1cd95), TOBN(0x7512f30d, 0x0d18673f), + TOBN(0x32f7a4ca, 0x5afc1464), TOBN(0x2f095656, 0x6bbb977b), + TOBN(0x586f47ca, 0xa8226200), TOBN(0x02c868ad, 0x1ac07369), + TOBN(0x4ef2b845, 0xc613acbe), TOBN(0x43d7563e, 0x0386054c), + TOBN(0x54da9dc7, 0xab952578), TOBN(0xb5423df2, 0x26e84d0b), + TOBN(0xa8b64eeb, 0x9b872042), TOBN(0xac205782, 0x5990f6df), + TOBN(0x4ff696eb, 0x21f4c77a), TOBN(0x1a79c3e4, 0xaab273af), + TOBN(0x29bc922e, 0x9436b3f1), TOBN(0xff807ef8, 0xd6d9a27a), + TOBN(0x82acea3d, 0x778f22a0), TOBN(0xfb10b2e8, 0x5b5e7469), + TOBN(0xc0b16980, 0x2818ee7d), TOBN(0x011afff4, 0xc91c1a2f), + TOBN(0x95a6d126, 0xad124418), TOBN(0x31c081a5, 0xe72e295f), + TOBN(0x36bb283a, 0xf2f4db75), TOBN(0xd115540f, 0x7acef462), + TOBN(0xc7f3a8f8, 0x33f6746c), TOBN(0x21e46f65, 0xfea990ca), + TOBN(0x915fd5c5, 0xcaddb0a9), TOBN(0xbd41f016, 0x78614555), + TOBN(0x346f4434, 0x426ffb58), TOBN(0x80559436, 0x14dbc204), + TOBN(0xf3dd20fe, 0x5a969b7f), TOBN(0x9d59e956, 0xe899a39a), + TOBN(0xf1b0971c, 0x8ad4cf4b), TOBN(0x03448860, 0x2ffb8fb8), + TOBN(0xf071ac3c, 0x65340ba4), TOBN(0x408d0596, 0xb27fd758), + TOBN(0xe7c78ea4, 0x98c364b0), TOBN(0xa4aac4a5, 0x051e8ab5), + TOBN(0xb9e1d560, 0x485d9002), TOBN(0x9acd518a, 0x88844455), + TOBN(0xe4ca688f, 0xd06f56c0), TOBN(0xa48af70d, 0xdf027972), + TOBN(0x691f0f04, 0x5e9a609d), TOBN(0xa9dd82cd, 0xee61270e), + TOBN(0x8903ca63, 0xa0ef18d3), TOBN(0x9fb7ee35, 0x3d6ca3bd), + TOBN(0xa7b4a09c, 0xabf47d03), TOBN(0x4cdada01, 0x1c67de8e), + TOBN(0x52003749, 0x9355a244), TOBN(0xe77fd2b6, 0x4f2151a9), + TOBN(0x695d6cf6, 0x66b4efcb), TOBN(0xc5a0cacf, 0xda2cfe25), + TOBN(0x104efe5c, 0xef811865), TOBN(0xf52813e8, 0x9ea5cc3d), + TOBN(0x855683dc, 0x40b58dbc), TOBN(0x0338ecde, 0x175fcb11), + TOBN(0xf9a05637, 0x74921592), TOBN(0xb4f1261d, 0xb9bb9d31), + TOBN(0x551429b7, 0x4e9c5459), TOBN(0xbe182e6f, 0x6ea71f53), + TOBN(0xd3a3b07c, 0xdfc50573), TOBN(0x9ba1afda, 0x62be8d44), + TOBN(0x9bcfd2cb, 0x52ab65d3), TOBN(0xdf11d547, 0xa9571802), + TOBN(0x099403ee, 0x02a2404a), TOBN(0x497406f4, 0x21088a71), + TOBN(0x99479409, 0x5004ae71), TOBN(0xbdb42078, 0xa812c362), + TOBN(0x2b72a30f, 0xd8828442), TOBN(0x283add27, 0xfcb5ed1c), + TOBN(0xf7c0e200, 0x66a40015), TOBN(0x3e3be641, 0x08b295ef), + TOBN(0xac127dc1, 0xe038a675), TOBN(0x729deff3, 0x8c5c6320), + TOBN(0xb7df8fd4, 0xa90d2c53), TOBN(0x9b74b0ec, 0x681e7cd3), + TOBN(0x5cb5a623, 0xdab407e5), TOBN(0xcdbd3615, 0x76b340c6), + TOBN(0xa184415a, 0x7d28392c), TOBN(0xc184c1d8, 0xe96f7830), + TOBN(0xc3204f19, 0x81d3a80f), TOBN(0xfde0c841, 0xc8e02432), + TOBN(0x78203b3e, 0x8149e0c1), TOBN(0x5904bdbb, 0x08053a73), + TOBN(0x30fc1dd1, 0x101b6805), TOBN(0x43c223bc, 0x49aa6d49), + TOBN(0x9ed67141, 0x7a174087), TOBN(0x311469a0, 0xd5997008), + TOBN(0xb189b684, 0x5e43fc61), TOBN(0xf3282375, 0xe0d3ab57), + TOBN(0x4fa34b67, 0xb1181da8), TOBN(0x621ed0b2, 0x99ee52b8), + TOBN(0x9b178de1, 0xad990676), TOBN(0xd51de67b, 0x56d54065), + TOBN(0x2a2c27c4, 0x7538c201), TOBN(0x33856ec8, 0x38a40f5c), + TOBN(0x2522fc15, 0xbe6cdcde), TOBN(0x1e603f33, 0x9f0c6f89), + TOBN(0x7994edc3, 0x103e30a6), TOBN(0x033a00db, 0x220c853e), + TOBN(0xd3cfa409, 0xf7bb7fd7), TOBN(0x70f8781e, 0x462d18f6), + TOBN(0xbbd82980, 0x687fe295), TOBN(0x6eef4c32, 0x595669f3), + TOBN(0x86a9303b, 0x2f7e85c3), TOBN(0x5fce4621, 0x71988f9b), + TOBN(0x5b935bf6, 0xc138acb5), TOBN(0x30ea7d67, 0x25661212), + TOBN(0xef1eb5f4, 0xe51ab9a2), TOBN(0x0587c98a, 0xae067c78), + TOBN(0xb3ce1b3c, 0x77ca9ca6), TOBN(0x2a553d4d, 0x54b5f057), + TOBN(0xc7898236, 0x4da29ec2), TOBN(0xdbdd5d13, 0xb9c57316), + TOBN(0xc57d6e6b, 0x2cd80d47), TOBN(0x80b460cf, 0xfe9e7391), + TOBN(0x98648cab, 0xf963c31e), TOBN(0x67f9f633, 0xcc4d32fd), + TOBN(0x0af42a9d, 0xfdf7c687), TOBN(0x55f292a3, 0x0b015ea7), + TOBN(0x89e468b2, 0xcd21ab3d), TOBN(0xe504f022, 0xc393d392), + TOBN(0xab21e1d4, 0xa5013af9), TOBN(0xe3283f78, 0xc2c28acb), + TOBN(0xf38b35f6, 0x226bf99f), TOBN(0xe8354274, 0x0e291e69), + TOBN(0x61673a15, 0xb20c162d), TOBN(0xc101dc75, 0xb04fbdbe), + TOBN(0x8323b4c2, 0x255bd617), TOBN(0x6c969693, 0x6c2a9154), + TOBN(0xc6e65860, 0x62679387), TOBN(0x8e01db0c, 0xb8c88e23), + TOBN(0x33c42873, 0x893a5559), TOBN(0x7630f04b, 0x47a3e149), + TOBN(0xb5d80805, 0xddcf35f8), TOBN(0x582ca080, 0x77dfe732), + TOBN(0x2c7156e1, 0x0b1894a0), TOBN(0x92034001, 0xd81c68c0), + TOBN(0xed225d00, 0xc8b115b5), TOBN(0x237f9c22, 0x83b907f2), + TOBN(0x0ea2f32f, 0x4470e2c0), TOBN(0xb725f7c1, 0x58be4e95), + TOBN(0x0f1dcafa, 0xb1ae5463), TOBN(0x59ed5187, 0x1ba2fc04), + TOBN(0xf6e0f316, 0xd0115d4d), TOBN(0x5180b12f, 0xd3691599), + TOBN(0x157e32c9, 0x527f0a41), TOBN(0x7b0b081d, 0xa8e0ecc0), + TOBN(0x6dbaaa8a, 0xbf4f0dd0), TOBN(0x99b289c7, 0x4d252696), + TOBN(0x79b7755e, 0xdbf864fe), TOBN(0x6974e2b1, 0x76cad3ab), + TOBN(0x35dbbee2, 0x06ddd657), TOBN(0xe7cbdd11, 0x2ff3a96d), + TOBN(0x88381968, 0x076be758), TOBN(0x2d737e72, 0x08c91f5d), + TOBN(0x5f83ab62, 0x86ec3776), TOBN(0x98aa649d, 0x945fa7a1), + TOBN(0xf477ec37, 0x72ef0933), TOBN(0x66f52b1e, 0x098c17b1), + TOBN(0x9eec58fb, 0xd803738b), TOBN(0x91aaade7, 0xe4e86aa4), + TOBN(0x6b1ae617, 0xa5b51492), TOBN(0x63272121, 0xbbc45974), + TOBN(0x7e0e28f0, 0x862c5129), TOBN(0x0a8f79a9, 0x3321a4a0), + TOBN(0xe26d1664, 0x5041c88f), TOBN(0x0571b805, 0x53233e3a), + TOBN(0xd1b0ccde, 0xc9520711), TOBN(0x55a9e4ed, 0x3c8b84bf), + TOBN(0x9426bd39, 0xa1fef314), TOBN(0x4f5f638e, 0x6eb93f2b), + TOBN(0xba2a1ed3, 0x2bf9341b), TOBN(0xd63c1321, 0x4d42d5a9), + TOBN(0xd2964a89, 0x316dc7c5), TOBN(0xd1759606, 0xca511851), + TOBN(0xd8a9201f, 0xf9e6ed35), TOBN(0xb7b5ee45, 0x6736925a), + TOBN(0x0a83fbbc, 0x99581af7), TOBN(0x3076bc40, 0x64eeb051), + TOBN(0x5511c98c, 0x02dec312), TOBN(0x270de898, 0x238dcb78), + TOBN(0x2cf4cf9c, 0x539c08c9), TOBN(0xa70cb65e, 0x38d3b06e), + TOBN(0xb12ec10e, 0xcfe57bbd), TOBN(0x82c7b656, 0x35a0c2b5), + TOBN(0xddc7d5cd, 0x161c67bd), TOBN(0xe32e8985, 0xae3a32cc), + TOBN(0x7aba9444, 0xd11a5529), TOBN(0xe964ed02, 0x2427fa1a), + TOBN(0x1528392d, 0x24a1770a), TOBN(0xa152ce2c, 0x12c72fcd), + TOBN(0x714553a4, 0x8ec07649), TOBN(0x18b4c290, 0x459dd453), + TOBN(0xea32b714, 0x7b64b110), TOBN(0xb871bfa5, 0x2e6f07a2), + TOBN(0xb67112e5, 0x9e2e3c9b), TOBN(0xfbf250e5, 0x44aa90f6), + TOBN(0xf77aedb8, 0xbd539006), TOBN(0x3b0cdf9a, 0xd172a66f), + TOBN(0xedf69fea, 0xf8c51187), TOBN(0x05bb67ec, 0x741e4da7), + TOBN(0x47df0f32, 0x08114345), TOBN(0x56facb07, 0xbb9792b1), + TOBN(0xf3e007e9, 0x8f6229e4), TOBN(0x62d103f4, 0x526fba0f), + TOBN(0x4f33bef7, 0xb0339d79), TOBN(0x9841357b, 0xb59bfec1), + TOBN(0xfa8dbb59, 0xc34e6705), TOBN(0xc3c7180b, 0x7fdaa84c), + TOBN(0xf95872fc, 0xa4108537), TOBN(0x8750cc3b, 0x932a3e5a), + TOBN(0xb61cc69d, 0xb7275d7d), TOBN(0xffa0168b, 0x2e59b2e9), + TOBN(0xca032abc, 0x6ecbb493), TOBN(0x1d86dbd3, 0x2c9082d8), + TOBN(0xae1e0b67, 0xe28ef5ba), TOBN(0x2c9a4699, 0xcb18e169), + TOBN(0x0ecd0e33, 0x1e6bbd20), TOBN(0x571b360e, 0xaf5e81d2), + TOBN(0xcd9fea58, 0x101c1d45), TOBN(0x6651788e, 0x18880452), + TOBN(0xa9972635, 0x1f8dd446), TOBN(0x44bed022, 0xe37281d0), + TOBN(0x094b2b2d, 0x33da525d), TOBN(0xf193678e, 0x13144fd8), + TOBN(0xb8ab5ba4, 0xf4c1061d), TOBN(0x4343b5fa, 0xdccbe0f4), + TOBN(0xa8702371, 0x63812713), TOBN(0x47bf6d2d, 0xf7611d93), + TOBN(0x46729b8c, 0xbd21e1d7), TOBN(0x7484d4e0, 0xd629e77d), + TOBN(0x830e6eea, 0x60dbac1f), TOBN(0x23d8c484, 0xda06a2f7), + TOBN(0x896714b0, 0x50ca535b), TOBN(0xdc8d3644, 0xebd97a9b), + TOBN(0x106ef9fa, 0xb12177b4), TOBN(0xf79bf464, 0x534d5d9c), + TOBN(0x2537a349, 0xa6ab360b), TOBN(0xc7c54253, 0xa00c744f), + TOBN(0xb3c7a047, 0xe5911a76), TOBN(0x61ffa5c8, 0x647f1ee7), + TOBN(0x15aed36f, 0x8f56ab42), TOBN(0x6a0d41b0, 0xa3ff9ac9), + TOBN(0x68f469f5, 0xcc30d357), TOBN(0xbe9adf81, 0x6b72be96), + TOBN(0x1cd926fe, 0x903ad461), TOBN(0x7e89e38f, 0xcaca441b), + TOBN(0xf0f82de5, 0xfacf69d4), TOBN(0x363b7e76, 0x4775344c), + TOBN(0x6894f312, 0xb2e36d04), TOBN(0x3c6cb4fe, 0x11d1c9a5), + TOBN(0x85d9c339, 0x4008e1f2), TOBN(0x5e9a85ea, 0x249f326c), + TOBN(0xdc35c60a, 0x678c5e06), TOBN(0xc08b944f, 0x9f86fba9), + TOBN(0xde40c02c, 0x89f71f0f), TOBN(0xad8f3e31, 0xff3da3c0), + TOBN(0x3ea5096b, 0x42125ded), TOBN(0x13879cbf, 0xa7379183), + TOBN(0x6f4714a5, 0x6b306a0b), TOBN(0x359c2ea6, 0x67646c5e), + TOBN(0xfacf8943, 0x07726368), TOBN(0x07a58935, 0x65ff431e), + TOBN(0x24d661d1, 0x68754ab0), TOBN(0x801fce1d, 0x6f429a76), + TOBN(0xc068a85f, 0xa58ce769), TOBN(0xedc35c54, 0x5d5eca2b), + TOBN(0xea31276f, 0xa3f660d1), TOBN(0xa0184ebe, 0xb8fc7167), + TOBN(0x0f20f21a, 0x1d8db0ae), TOBN(0xd96d095f, 0x56c35e12), + TOBN(0xedf402b5, 0xf8c2a25b), TOBN(0x1bb772b9, 0x059204b6), + TOBN(0x50cbeae2, 0x19b4e34c), TOBN(0x93109d80, 0x3fa0845a), + TOBN(0x54f7ccf7, 0x8ef59fb5), TOBN(0x3b438fe2, 0x88070963), + TOBN(0x9e28c659, 0x31f3ba9b), TOBN(0x9cc31b46, 0xead9da92), + TOBN(0x3c2f0ba9, 0xb733aa5f), TOBN(0xdece47cb, 0xf05af235), + TOBN(0xf8e3f715, 0xa2ac82a5), TOBN(0xc97ba641, 0x2203f18a), + TOBN(0xc3af5504, 0x09c11060), TOBN(0x56ea2c05, 0x46af512d), + TOBN(0xfac28daf, 0xf3f28146), TOBN(0x87fab43a, 0x959ef494),} + , + {TOBN(0x09891641, 0xd4c5105f), TOBN(0x1ae80f8e, 0x6d7fbd65), + TOBN(0x9d67225f, 0xbee6bdb0), TOBN(0x3b433b59, 0x7fc4d860), + TOBN(0x44e66db6, 0x93e85638), TOBN(0xf7b59252, 0xe3e9862f), + TOBN(0xdb785157, 0x665c32ec), TOBN(0x702fefd7, 0xae362f50), + TOBN(0x3754475d, 0x0fefb0c3), TOBN(0xd48fb56b, 0x46d7c35d), + TOBN(0xa070b633, 0x363798a4), TOBN(0xae89f3d2, 0x8fdb98e6), + TOBN(0x970b89c8, 0x6363d14c), TOBN(0x89817521, 0x67abd27d), + TOBN(0x9bf7d474, 0x44d5a021), TOBN(0xb3083baf, 0xcac72aee), + TOBN(0x389741de, 0xbe949a44), TOBN(0x638e9388, 0x546a4fa5), + TOBN(0x3fe6419c, 0xa0047bdc), TOBN(0x7047f648, 0xaaea57ca), + TOBN(0x54e48a90, 0x41fbab17), TOBN(0xda8e0b28, 0x576bdba2), + TOBN(0xe807eebc, 0xc72afddc), TOBN(0x07d3336d, 0xf42577bf), + TOBN(0x62a8c244, 0xbfe20925), TOBN(0x91c19ac3, 0x8fdce867), + TOBN(0x5a96a5d5, 0xdd387063), TOBN(0x61d587d4, 0x21d324f6), + TOBN(0xe87673a2, 0xa37173ea), TOBN(0x23848008, 0x53778b65), + TOBN(0x10f8441e, 0x05bab43e), TOBN(0xfa11fe12, 0x4621efbe), + TOBN(0x047b772e, 0x81685d7b), TOBN(0x23f27d81, 0xbf34a976), + TOBN(0xc27608e2, 0x915f48ef), TOBN(0x3b0b43fa, 0xa521d5c3), + TOBN(0x7613fb26, 0x63ca7284), TOBN(0x7f5729b4, 0x1d4db837), + TOBN(0x87b14898, 0x583b526b), TOBN(0x00b732a6, 0xbbadd3d1), + TOBN(0x8e02f426, 0x2048e396), TOBN(0x436b50b6, 0x383d9de4), + TOBN(0xf78d3481, 0x471e85ad), TOBN(0x8b01ea6a, 0xd005c8d6), + TOBN(0xd3c7afee, 0x97015c07), TOBN(0x46cdf1a9, 0x4e3ba2ae), + TOBN(0x7a42e501, 0x83d3a1d2), TOBN(0xd54b5268, 0xb541dff4), + TOBN(0x3f24cf30, 0x4e23e9bc), TOBN(0x4387f816, 0x126e3624), + TOBN(0x26a46a03, 0x3b0b6d61), TOBN(0xaf1bc845, 0x8b2d777c), + TOBN(0x25c401ba, 0x527de79c), TOBN(0x0e1346d4, 0x4261bbb6), + TOBN(0x4b96c44b, 0x287b4bc7), TOBN(0x658493c7, 0x5254562f), + TOBN(0x23f949fe, 0xb8a24a20), TOBN(0x17ebfed1, 0xf52ca53f), + TOBN(0x9b691bbe, 0xbcfb4853), TOBN(0x5617ff6b, 0x6278a05d), + TOBN(0x241b34c5, 0xe3c99ebd), TOBN(0xfc64242e, 0x1784156a), + TOBN(0x4206482f, 0x695d67df), TOBN(0xb967ce0e, 0xee27c011), + TOBN(0x65db3751, 0x21c80b5d), TOBN(0x2e7a563c, 0xa31ecca0), + TOBN(0xe56ffc4e, 0x5238a07e), TOBN(0x3d6c2966, 0x32ced854), + TOBN(0xe99d7d1a, 0xaf70b885), TOBN(0xafc3bad9, 0x2d686459), + TOBN(0x9c78bf46, 0x0cc8ba5b), TOBN(0x5a439519, 0x18955aa3), + TOBN(0xf8b517a8, 0x5fe4e314), TOBN(0xe60234d0, 0xfcb8906f), + TOBN(0xffe542ac, 0xf2061b23), TOBN(0x287e191f, 0x6b4cb59c), + TOBN(0x21857ddc, 0x09d877d8), TOBN(0x1c23478c, 0x14678941), + TOBN(0xbbf0c056, 0xb6e05ea4), TOBN(0x82da4b53, 0xb01594fe), + TOBN(0xf7526791, 0xfadb8608), TOBN(0x049e832d, 0x7b74cdf6), + TOBN(0xa43581cc, 0xc2b90a34), TOBN(0x73639eb8, 0x9360b10c), + TOBN(0x4fba331f, 0xe1e4a71b), TOBN(0x6ffd6b93, 0x8072f919), + TOBN(0x6e53271c, 0x65679032), TOBN(0x67206444, 0xf14272ce), + TOBN(0xc0f734a3, 0xb2335834), TOBN(0x9526205a, 0x90ef6860), + TOBN(0xcb8be717, 0x04e2bb0d), TOBN(0x2418871e, 0x02f383fa), + TOBN(0xd7177681, 0x4082c157), TOBN(0xcc914ad0, 0x29c20073), + TOBN(0xf186c1eb, 0xe587e728), TOBN(0x6fdb3c22, 0x61bcd5fd), + TOBN(0x30d014a6, 0xf2f9f8e9), TOBN(0x963ece23, 0x4fec49d2), + TOBN(0x862025c5, 0x9605a8d9), TOBN(0x39874445, 0x19f8929a), + TOBN(0x01b6ff65, 0x12bf476a), TOBN(0x598a64d8, 0x09cf7d91), + TOBN(0xd7ec7749, 0x93be56ca), TOBN(0x10899785, 0xcbb33615), + TOBN(0xb8a092fd, 0x02eee3ad), TOBN(0xa86b3d35, 0x30145270), + TOBN(0x323d98c6, 0x8512b675), TOBN(0x4b8bc785, 0x62ebb40f), + TOBN(0x7d301f54, 0x413f9cde), TOBN(0xa5e4fb4f, 0x2bab5664), + TOBN(0x1d2b252d, 0x1cbfec23), TOBN(0xfcd576bb, 0xe177120d), + TOBN(0x04427d3e, 0x83731a34), TOBN(0x2bb9028e, 0xed836e8e), + TOBN(0xb36acff8, 0xb612ca7c), TOBN(0xb88fe5ef, 0xd3d9c73a), + TOBN(0xbe2a6bc6, 0xedea4eb3), TOBN(0x43b93133, 0x488eec77), + TOBN(0xf41ff566, 0xb17106e1), TOBN(0x469e9172, 0x654efa32), + TOBN(0xb4480f04, 0x41c23fa3), TOBN(0xb4712eb0, 0xc1989a2e), + TOBN(0x3ccbba0f, 0x93a29ca7), TOBN(0x6e205c14, 0xd619428c), + TOBN(0x90db7957, 0xb3641686), TOBN(0x0432691d, 0x45ac8b4e), + TOBN(0x07a759ac, 0xf64e0350), TOBN(0x0514d89c, 0x9c972517), + TOBN(0x1701147f, 0xa8e67fc3), TOBN(0x9e2e0b8b, 0xab2085be), + TOBN(0xd5651824, 0xac284e57), TOBN(0x890d4325, 0x74893664), + TOBN(0x8a7c5e6e, 0xc55e68a3), TOBN(0xbf12e90b, 0x4339c85a), + TOBN(0x31846b85, 0xf922b655), TOBN(0x9a54ce4d, 0x0bf4d700), + TOBN(0xd7f4e83a, 0xf1a14295), TOBN(0x916f955c, 0xb285d4f9), + TOBN(0xe57bb0e0, 0x99ffdaba), TOBN(0x28a43034, 0xeab0d152), + TOBN(0x0a36ffa2, 0xb8a9cef8), TOBN(0x5517407e, 0xb9ec051a), + TOBN(0x9c796096, 0xea68e672), TOBN(0x853db5fb, 0xfb3c77fb), + TOBN(0x21474ba9, 0xe864a51a), TOBN(0x6c267699, 0x6e8a1b8b), + TOBN(0x7c823626, 0x94120a28), TOBN(0xe61e9a48, 0x8383a5db), + TOBN(0x7dd75003, 0x9f84216d), TOBN(0xab020d07, 0xad43cd85), + TOBN(0x9437ae48, 0xda12c659), TOBN(0x6449c2eb, 0xe65452ad), + TOBN(0xcc7c4c1c, 0x2cf9d7c1), TOBN(0x1320886a, 0xee95e5ab), + TOBN(0xbb7b9056, 0xbeae170c), TOBN(0xc8a5b250, 0xdbc0d662), + TOBN(0x4ed81432, 0xc11d2303), TOBN(0x7da66912, 0x1f03769f), + TOBN(0x3ac7a5fd, 0x84539828), TOBN(0x14dada94, 0x3bccdd02), + TOBN(0x8b84c321, 0x7ef6b0d1), TOBN(0x52a9477a, 0x7c933f22), + TOBN(0x5ef6728a, 0xfd440b82), TOBN(0x5c3bd859, 0x6ce4bd5e), + TOBN(0x918b80f5, 0xf22c2d3e), TOBN(0x368d5040, 0xb7bb6cc5), + TOBN(0xb66142a1, 0x2695a11c), TOBN(0x60ac583a, 0xeb19ea70), + TOBN(0x317cbb98, 0x0eab2437), TOBN(0x8cc08c55, 0x5e2654c8), + TOBN(0xfe2d6520, 0xe6d8307f), TOBN(0xe9f147f3, 0x57428993), + TOBN(0x5f9c7d14, 0xd2fd6cf1), TOBN(0xa3ecd064, 0x2d4fcbb0), + TOBN(0xad83fef0, 0x8e7341f7), TOBN(0x643f23a0, 0x3a63115c), + TOBN(0xd38a78ab, 0xe65ab743), TOBN(0xbf7c75b1, 0x35edc89c), + TOBN(0x3dd8752e, 0x530df568), TOBN(0xf85c4a76, 0xe308c682), + TOBN(0x4c9955b2, 0xe68acf37), TOBN(0xa544df3d, 0xab32af85), + TOBN(0x4b8ec3f5, 0xa25cf493), TOBN(0x4d8f2764, 0x1a622feb), + TOBN(0x7bb4f7aa, 0xf0dcbc49), TOBN(0x7de551f9, 0x70bbb45b), + TOBN(0xcfd0f3e4, 0x9f2ca2e5), TOBN(0xece58709, 0x1f5c76ef), + TOBN(0x32920edd, 0x167d79ae), TOBN(0x039df8a2, 0xfa7d7ec1), + TOBN(0xf46206c0, 0xbb30af91), TOBN(0x1ff5e2f5, 0x22676b59), + TOBN(0x11f4a039, 0x6ea51d66), TOBN(0x506c1445, 0x807d7a26), + TOBN(0x60da5705, 0x755a9b24), TOBN(0x8fc8cc32, 0x1f1a319e), + TOBN(0x83642d4d, 0x9433d67d), TOBN(0x7fa5cb8f, 0x6a7dd296), + TOBN(0x576591db, 0x9b7bde07), TOBN(0x13173d25, 0x419716fb), + TOBN(0xea30599d, 0xd5b340ff), TOBN(0xfc6b5297, 0xb0fe76c5), + TOBN(0x1c6968c8, 0xab8f5adc), TOBN(0xf723c7f5, 0x901c928d), + TOBN(0x4203c321, 0x9773d402), TOBN(0xdf7c6aa3, 0x1b51dd47), + TOBN(0x3d49e37a, 0x552be23c), TOBN(0x57febee8, 0x0b5a6e87), + TOBN(0xc5ecbee4, 0x7bd8e739), TOBN(0x79d44994, 0xae63bf75), + TOBN(0x168bd00f, 0x38fb8923), TOBN(0x75d48ee4, 0xd0533130), + TOBN(0x554f77aa, 0xdb5cdf33), TOBN(0x3396e896, 0x3c696769), + TOBN(0x2fdddbf2, 0xd3fd674e), TOBN(0xbbb8f6ee, 0x99d0e3e5), + TOBN(0x51b90651, 0xcbae2f70), TOBN(0xefc4bc05, 0x93aaa8eb), + TOBN(0x8ecd8689, 0xdd1df499), TOBN(0x1aee99a8, 0x22f367a5), + TOBN(0x95d485b9, 0xae8274c5), TOBN(0x6c14d445, 0x7d30b39c), + TOBN(0xbafea90b, 0xbcc1ef81), TOBN(0x7c5f317a, 0xa459a2ed), + TOBN(0x01211075, 0x4ef44227), TOBN(0xa17bed6e, 0xdc20f496), + TOBN(0x0cdfe424, 0x819853cd), TOBN(0x13793298, 0xf71e2ce7), + TOBN(0x3c1f3078, 0xdbbe307b), TOBN(0x6dd1c20e, 0x76ee9936), + TOBN(0x23ee4b57, 0x423caa20), TOBN(0x4ac3793b, 0x8efb840e), + TOBN(0x934438eb, 0xed1f8ca0), TOBN(0x3e546658, 0x4ebb25a2), + TOBN(0xc415af0e, 0xc069896f), TOBN(0xc13eddb0, 0x9a5aa43d), + TOBN(0x7a04204f, 0xd49eb8f6), TOBN(0xd0d5bdfc, 0xd74f1670), + TOBN(0x3697e286, 0x56fc0558), TOBN(0x10207371, 0x01cebade), + TOBN(0x5f87e690, 0x0647a82b), TOBN(0x908e0ed4, 0x8f40054f), + TOBN(0xa9f633d4, 0x79853803), TOBN(0x8ed13c9a, 0x4a28b252), + TOBN(0x3e2ef676, 0x1f460f64), TOBN(0x53930b9b, 0x36d06336), + TOBN(0x347073ac, 0x8fc4979b), TOBN(0x84380e0e, 0x5ecd5597), + TOBN(0xe3b22c6b, 0xc4fe3c39), TOBN(0xba4a8153, 0x6c7bebdf), + TOBN(0xf23ab6b7, 0x25693459), TOBN(0x53bc3770, 0x14922b11), + TOBN(0x4645c8ab, 0x5afc60db), TOBN(0xaa022355, 0x20b9f2a3), + TOBN(0x52a2954c, 0xce0fc507), TOBN(0x8c2731bb, 0x7ce1c2e7), + TOBN(0xf39608ab, 0x18a0339d), TOBN(0xac7a658d, 0x3735436c), + TOBN(0xb22c2b07, 0xcd992b4f), TOBN(0x4e83daec, 0xf40dcfd4), + TOBN(0x8a34c7be, 0x2f39ea3e), TOBN(0xef0c005f, 0xb0a56d2e), + TOBN(0x62731f6a, 0x6edd8038), TOBN(0x5721d740, 0x4e3cb075), + TOBN(0x1ea41511, 0xfbeeee1b), TOBN(0xd1ef5e73, 0xef1d0c05), + TOBN(0x42feefd1, 0x73c07d35), TOBN(0xe530a00a, 0x8a329493), + TOBN(0x5d55b7fe, 0xf15ebfb0), TOBN(0x549de03c, 0xd322491a), + TOBN(0xf7b5f602, 0x745b3237), TOBN(0x3632a3a2, 0x1ab6e2b6), + TOBN(0x0d3bba89, 0x0ef59f78), TOBN(0x0dfc6443, 0xc9e52b9a), + TOBN(0x1dc79699, 0x72631447), TOBN(0xef033917, 0xb3be20b1), + TOBN(0x0c92735d, 0xb1383948), TOBN(0xc1fc29a2, 0xc0dd7d7d), + TOBN(0x6485b697, 0x403ed068), TOBN(0x13bfaab3, 0xaac93bdc), + TOBN(0x410dc6a9, 0x0deeaf52), TOBN(0xb003fb02, 0x4c641c15), + TOBN(0x1384978c, 0x5bc504c4), TOBN(0x37640487, 0x864a6a77), + TOBN(0x05991bc6, 0x222a77da), TOBN(0x62260a57, 0x5e47eb11), + TOBN(0xc7af6613, 0xf21b432c), TOBN(0x22f3acc9, 0xab4953e9), + TOBN(0x52934922, 0x8e41d155), TOBN(0x4d024568, 0x3ac059ef), + TOBN(0xb0201755, 0x4d884411), TOBN(0xce8055cf, 0xa59a178f), + TOBN(0xcd77d1af, 0xf6204549), TOBN(0xa0a00a3e, 0xc7066759), + TOBN(0x471071ef, 0x0272c229), TOBN(0x009bcf6b, 0xd3c4b6b0), + TOBN(0x2a2638a8, 0x22305177), TOBN(0xd51d59df, 0x41645bbf), + TOBN(0xa81142fd, 0xc0a7a3c0), TOBN(0xa17eca6d, 0x4c7063ee), + TOBN(0x0bb887ed, 0x60d9dcec), TOBN(0xd6d28e51, 0x20ad2455), + TOBN(0xebed6308, 0xa67102ba), TOBN(0x042c3114, 0x8bffa408), + TOBN(0xfd099ac5, 0x8aa68e30), TOBN(0x7a6a3d7c, 0x1483513e), + TOBN(0xffcc6b75, 0xba2d8f0c), TOBN(0x54dacf96, 0x1e78b954), + TOBN(0xf645696f, 0xa4a9af89), TOBN(0x3a411940, 0x06ac98ec), + TOBN(0x41b8b3f6, 0x22a67a20), TOBN(0x2d0b1e0f, 0x99dec626), + TOBN(0x27c89192, 0x40be34e8), TOBN(0xc7162b37, 0x91907f35), + TOBN(0x90188ec1, 0xa956702b), TOBN(0xca132f7d, 0xdf93769c), + TOBN(0x3ece44f9, 0x0e2025b4), TOBN(0x67aaec69, 0x0c62f14c), + TOBN(0xad741418, 0x22e3cc11), TOBN(0xcf9b75c3, 0x7ff9a50e), + TOBN(0x02fa2b16, 0x4d348272), TOBN(0xbd99d61a, 0x9959d56d), + TOBN(0xbc4f19db, 0x18762916), TOBN(0xcc7cce50, 0x49c1ac80), + TOBN(0x4d59ebaa, 0xd846bd83), TOBN(0x8775a9dc, 0xa9202849), + TOBN(0x07ec4ae1, 0x6e1f4ca9), TOBN(0x27eb5875, 0xba893f11), + TOBN(0x00284d51, 0x662cc565), TOBN(0x82353a6b, 0x0db4138d), + TOBN(0xd9c7aaaa, 0xaa32a594), TOBN(0xf5528b5e, 0xa5669c47), + TOBN(0xf3220231, 0x2f23c5ff), TOBN(0xe3e8147a, 0x6affa3a1), + TOBN(0xfb423d5c, 0x202ddda0), TOBN(0x3d6414ac, 0x6b871bd4), + TOBN(0x586f82e1, 0xa51a168a), TOBN(0xb712c671, 0x48ae5448), + TOBN(0x9a2e4bd1, 0x76233eb8), TOBN(0x0188223a, 0x78811ca9), + TOBN(0x553c5e21, 0xf7c18de1), TOBN(0x7682e451, 0xb27bb286), + TOBN(0x3ed036b3, 0x0e51e929), TOBN(0xf487211b, 0xec9cb34f), + TOBN(0x0d094277, 0x0c24efc8), TOBN(0x0349fd04, 0xbef737a4), + TOBN(0x6d1c9dd2, 0x514cdd28), TOBN(0x29c135ff, 0x30da9521), + TOBN(0xea6e4508, 0xf78b0b6f), TOBN(0x176f5dd2, 0x678c143c), + TOBN(0x08148418, 0x4be21e65), TOBN(0x27f7525c, 0xe7df38c4), + TOBN(0x1fb70e09, 0x748ab1a4), TOBN(0x9cba50a0, 0x5efe4433), + TOBN(0x7846c7a6, 0x15f75af2), TOBN(0x2a7c2c57, 0x5ee73ea8), + TOBN(0x42e566a4, 0x3f0a449a), TOBN(0x45474c3b, 0xad90fc3d), + TOBN(0x7447be3d, 0x8b61d057), TOBN(0x3e9d1cf1, 0x3a4ec092), + TOBN(0x1603e453, 0xf380a6e6), TOBN(0x0b86e431, 0x9b1437c2), + TOBN(0x7a4173f2, 0xef29610a), TOBN(0x8fa729a7, 0xf03d57f7), + TOBN(0x3e186f6e, 0x6c9c217e), TOBN(0xbe1d3079, 0x91919524), + TOBN(0x92a62a70, 0x153d4fb1), TOBN(0x32ed3e34, 0xd68c2f71), + TOBN(0xd785027f, 0x9eb1a8b7), TOBN(0xbc37eb77, 0xc5b22fe8), + TOBN(0x466b34f0, 0xb9d6a191), TOBN(0x008a89af, 0x9a05f816), + TOBN(0x19b028fb, 0x7d42c10a), TOBN(0x7fe8c92f, 0x49b3f6b8), + TOBN(0x58907cc0, 0xa5a0ade3), TOBN(0xb3154f51, 0x559d1a7c), + TOBN(0x5066efb6, 0xd9790ed6), TOBN(0xa77a0cbc, 0xa6aa793b), + TOBN(0x1a915f3c, 0x223e042e), TOBN(0x1c5def04, 0x69c5874b), + TOBN(0x0e830078, 0x73b6c1da), TOBN(0x55cf85d2, 0xfcd8557a), + TOBN(0x0f7c7c76, 0x0460f3b1), TOBN(0x87052acb, 0x46e58063), + TOBN(0x09212b80, 0x907eae66), TOBN(0x3cb068e0, 0x4d721c89), + TOBN(0xa87941ae, 0xdd45ac1c), TOBN(0xde8d5c0d, 0x0daa0dbb), + TOBN(0xda421fdc, 0xe3502e6e), TOBN(0xc8944201, 0x4d89a084), + TOBN(0x7307ba5e, 0xf0c24bfb), TOBN(0xda212beb, 0x20bde0ef), + TOBN(0xea2da24b, 0xf82ce682), TOBN(0x058d3816, 0x07f71fe4), + TOBN(0x35a02462, 0x5ffad8de), TOBN(0xcd7b05dc, 0xaadcefab), + TOBN(0xd442f8ed, 0x1d9f54ec), TOBN(0x8be3d618, 0xb2d3b5ca), + TOBN(0xe2220ed0, 0xe06b2ce2), TOBN(0x82699a5f, 0x1b0da4c0), + TOBN(0x3ff106f5, 0x71c0c3a7), TOBN(0x8f580f5a, 0x0d34180c), + TOBN(0x4ebb120e, 0x22d7d375), TOBN(0x5e5782cc, 0xe9513675), + TOBN(0x2275580c, 0x99c82a70), TOBN(0xe8359fbf, 0x15ea8c4c), + TOBN(0x53b48db8, 0x7b415e70), TOBN(0xaacf2240, 0x100c6014), + TOBN(0x9faaccf5, 0xe4652f1d), TOBN(0xbd6fdd2a, 0xd56157b2), + TOBN(0xa4f4fb1f, 0x6261ec50), TOBN(0x244e55ad, 0x476bcd52), + TOBN(0x881c9305, 0x047d320b), TOBN(0x1ca983d5, 0x6181263f), + TOBN(0x354e9a44, 0x278fb8ee), TOBN(0xad2dbc0f, 0x396e4964), + TOBN(0x723f3aa2, 0x9268b3de), TOBN(0x0d1ca29a, 0xe6e0609a), + TOBN(0x794866aa, 0x6cf44252), TOBN(0x0b59f3e3, 0x01af87ed), + TOBN(0xe234e5ff, 0x7f4a6c51), TOBN(0xa8768fd2, 0x61dc2f7e), + TOBN(0xdafc7332, 0x0a94d81f), TOBN(0xd7f84282, 0x06938ce1), + TOBN(0xae0b3c0e, 0x0546063e), TOBN(0x7fbadcb2, 0x5d61abc6), + TOBN(0xd5d7a2c9, 0x369ac400), TOBN(0xa5978d09, 0xae67d10c), + TOBN(0x290f211e, 0x4f85eaac), TOBN(0xe61e2ad1, 0xfacac681), + TOBN(0xae125225, 0x388384cd), TOBN(0xa7fb68e9, 0xccfde30f), + TOBN(0x7a59b936, 0x3daed4c2), TOBN(0x80a9aa40, 0x2606f789), + TOBN(0xb40c1ea5, 0xf6a6d90a), TOBN(0x948364d3, 0x514d5885), + TOBN(0x062ebc60, 0x70985182), TOBN(0xa6db5b0e, 0x33310895), + TOBN(0x64a12175, 0xe329c2f5), TOBN(0xc5f25bd2, 0x90ea237e), + TOBN(0x7915c524, 0x2d0a4c23), TOBN(0xeb5d26e4, 0x6bb3cc52), + TOBN(0x369a9116, 0xc09e2c92), TOBN(0x0c527f92, 0xcf182cf8), + TOBN(0x9e591938, 0x2aede0ac), TOBN(0xb2922208, 0x6cc34939), + TOBN(0x3c9d8962, 0x99a34361), TOBN(0x3c81836d, 0xc1905fe6), + TOBN(0x4bfeb57f, 0xa001ec5a), TOBN(0xe993f5bb, 0xa0dc5dba), + TOBN(0x47884109, 0x724a1380), TOBN(0x8a0369ab, 0x32fe9a04), + TOBN(0xea068d60, 0x8c927db8), TOBN(0xbf5f37cf, 0x94655741), + TOBN(0x47d402a2, 0x04b6c7ea), TOBN(0x4551c295, 0x6af259cb), + TOBN(0x698b71e7, 0xed77ee8b), TOBN(0xbddf7bd0, 0xf309d5c7), + TOBN(0x6201c22c, 0x34e780ca), TOBN(0xab04f7d8, 0x4c295ef4), + TOBN(0x1c947294, 0x4313a8ce), TOBN(0xe532e4ac, 0x92ca4cfe), + TOBN(0x89738f80, 0xd0a7a97a), TOBN(0xec088c88, 0xa580fd5b), + TOBN(0x612b1ecc, 0x42ce9e51), TOBN(0x8f9840fd, 0xb25fdd2a), + TOBN(0x3cda78c0, 0x01e7f839), TOBN(0x546b3d3a, 0xece05480), + TOBN(0x271719a9, 0x80d30916), TOBN(0x45497107, 0x584c20c4), + TOBN(0xaf8f9478, 0x5bc78608), TOBN(0x28c7d484, 0x277e2a4c), + TOBN(0xfce01767, 0x88a2ffe4), TOBN(0xdc506a35, 0x28e169a5), + TOBN(0x0ea10861, 0x7af9c93a), TOBN(0x1ed24361, 0x03fa0e08), + TOBN(0x96eaaa92, 0xa3d694e7), TOBN(0xc0f43b4d, 0xef50bc74), + TOBN(0xce6aa58c, 0x64114db4), TOBN(0x8218e8ea, 0x7c000fd4), + TOBN(0xac815dfb, 0x185f8844), TOBN(0xcd7e90cb, 0x1557abfb), + TOBN(0x23d16655, 0xafbfecdf), TOBN(0x80f3271f, 0x085cac4a), + TOBN(0x7fc39aa7, 0xd0e62f47), TOBN(0x88d519d1, 0x460a48e5), + TOBN(0x59559ac4, 0xd28f101e), TOBN(0x7981d9e9, 0xca9ae816), + TOBN(0x5c38652c, 0x9ac38203), TOBN(0x86eaf87f, 0x57657fe5), + TOBN(0x568fc472, 0xe21f5416), TOBN(0x2afff39c, 0xe7e597b5), + TOBN(0x3adbbb07, 0x256d4eab), TOBN(0x22598692, 0x8285ab89), + TOBN(0x35f8112a, 0x041caefe), TOBN(0x95df02e3, 0xa5064c8b), + TOBN(0x4d63356e, 0xc7004bf3), TOBN(0x230a08f4, 0xdb83c7de), + TOBN(0xca27b270, 0x8709a7b7), TOBN(0x0d1c4cc4, 0xcb9abd2d), + TOBN(0x8a0bc66e, 0x7550fee8), TOBN(0x369cd4c7, 0x9cf7247e), + TOBN(0x75562e84, 0x92b5b7e7), TOBN(0x8fed0da0, 0x5802af7b), + TOBN(0x6a7091c2, 0xe48fb889), TOBN(0x26882c13, 0x7b8a9d06), + TOBN(0xa2498663, 0x1b82a0e2), TOBN(0x844ed736, 0x3518152d), + TOBN(0x282f476f, 0xd86e27c7), TOBN(0xa04edaca, 0x04afefdc), + TOBN(0x8b256ebc, 0x6119e34d), TOBN(0x56a413e9, 0x0787d78b),} + , + {TOBN(0x82ee061d, 0x5a74be50), TOBN(0xe41781c4, 0xdea16ff5), + TOBN(0xe0b0c81e, 0x99bfc8a2), TOBN(0x624f4d69, 0x0b547e2d), + TOBN(0x3a83545d, 0xbdcc9ae4), TOBN(0x2573dbb6, 0x409b1e8e), + TOBN(0x482960c4, 0xa6c93539), TOBN(0xf01059ad, 0x5ae18798), + TOBN(0x715c9f97, 0x3112795f), TOBN(0xe8244437, 0x984e6ee1), + TOBN(0x55cb4858, 0xecb66bcd), TOBN(0x7c136735, 0xabaffbee), + TOBN(0x54661595, 0x5dbec38e), TOBN(0x51c0782c, 0x388ad153), + TOBN(0x9ba4c53a, 0xc6e0952f), TOBN(0x27e6782a, 0x1b21dfa8), + TOBN(0x682f903d, 0x4ed2dbc2), TOBN(0x0eba59c8, 0x7c3b2d83), + TOBN(0x8e9dc84d, 0x9c7e9335), TOBN(0x5f9b21b0, 0x0eb226d7), + TOBN(0xe33bd394, 0xaf267bae), TOBN(0xaa86cc25, 0xbe2e15ae), + TOBN(0x4f0bf67d, 0x6a8ec500), TOBN(0x5846aa44, 0xf9630658), + TOBN(0xfeb09740, 0xe2c2bf15), TOBN(0x627a2205, 0xa9e99704), + TOBN(0xec8d73d0, 0xc2fbc565), TOBN(0x223eed8f, 0xc20c8de8), + TOBN(0x1ee32583, 0xa8363b49), TOBN(0x1a0b6cb9, 0xc9c2b0a6), + TOBN(0x49f7c3d2, 0x90dbc85c), TOBN(0xa8dfbb97, 0x1ef4c1ac), + TOBN(0xafb34d4c, 0x65c7c2ab), TOBN(0x1d4610e7, 0xe2c5ea84), + TOBN(0x893f6d1b, 0x973c4ab5), TOBN(0xa3cdd7e9, 0x945ba5c4), + TOBN(0x60514983, 0x064417ee), TOBN(0x1459b23c, 0xad6bdf2b), + TOBN(0x23b2c341, 0x5cf726c3), TOBN(0x3a829635, 0x32d6354a), + TOBN(0x294f901f, 0xab192c18), TOBN(0xec5fcbfe, 0x7030164f), + TOBN(0xe2e2fcb7, 0xe2246ba6), TOBN(0x1e7c88b3, 0x221a1a0c), + TOBN(0x72c7dd93, 0xc92d88c5), TOBN(0x41c2148e, 0x1106fb59), + TOBN(0x547dd4f5, 0xa0f60f14), TOBN(0xed9b52b2, 0x63960f31), + TOBN(0x6c8349eb, 0xb0a5b358), TOBN(0xb154c5c2, 0x9e7e2ed6), + TOBN(0xcad5eccf, 0xeda462db), TOBN(0xf2d6dbe4, 0x2de66b69), + TOBN(0x426aedf3, 0x8665e5b2), TOBN(0x488a8513, 0x7b7f5723), + TOBN(0x15cc43b3, 0x8bcbb386), TOBN(0x27ad0af3, 0xd791d879), + TOBN(0xc16c236e, 0x846e364f), TOBN(0x7f33527c, 0xdea50ca0), + TOBN(0xc4810775, 0x0926b86d), TOBN(0x6c2a3609, 0x0598e70c), + TOBN(0xa6755e52, 0xf024e924), TOBN(0xe0fa07a4, 0x9db4afca), + TOBN(0x15c3ce7d, 0x66831790), TOBN(0x5b4ef350, 0xa6cbb0d6), + TOBN(0x2c4aafc4, 0xb6205969), TOBN(0x42563f02, 0xf6c7854f), + TOBN(0x016aced5, 0x1d983b48), TOBN(0xfeb356d8, 0x99949755), + TOBN(0x8c2a2c81, 0xd1a39bd7), TOBN(0x8f44340f, 0xe6934ae9), + TOBN(0x148cf91c, 0x447904da), TOBN(0x7340185f, 0x0f51a926), + TOBN(0x2f8f00fb, 0x7409ab46), TOBN(0x057e78e6, 0x80e289b2), + TOBN(0x03e5022c, 0xa888e5d1), TOBN(0x3c87111a, 0x9dede4e2), + TOBN(0x5b9b0e1c, 0x7809460b), TOBN(0xe751c852, 0x71c9abc7), + TOBN(0x8b944e28, 0xc7cc1dc9), TOBN(0x4f201ffa, 0x1d3cfa08), + TOBN(0x02fc905c, 0x3e6721ce), TOBN(0xd52d70da, 0xd0b3674c), + TOBN(0x5dc2e5ca, 0x18810da4), TOBN(0xa984b273, 0x5c69dd99), + TOBN(0x63b92527, 0x84de5ca4), TOBN(0x2f1c9872, 0xc852dec4), + TOBN(0x18b03593, 0xc2e3de09), TOBN(0x19d70b01, 0x9813dc2f), + TOBN(0x42806b2d, 0xa6dc1d29), TOBN(0xd3030009, 0xf871e144), + TOBN(0xa1feb333, 0xaaf49276), TOBN(0xb5583b9e, 0xc70bc04b), + TOBN(0x1db0be78, 0x95695f20), TOBN(0xfc841811, 0x89d012b5), + TOBN(0x6409f272, 0x05f61643), TOBN(0x40d34174, 0xd5883128), + TOBN(0xd79196f5, 0x67419833), TOBN(0x6059e252, 0x863b7b08), + TOBN(0x84da1817, 0x1c56700c), TOBN(0x5758ee56, 0xb28d3ec4), + TOBN(0x7da2771d, 0x013b0ea6), TOBN(0xfddf524b, 0x54c5e9b9), + TOBN(0x7df4faf8, 0x24305d80), TOBN(0x58f5c1bf, 0x3a97763f), + TOBN(0xa5af37f1, 0x7c696042), TOBN(0xd4cba22c, 0x4a2538de), + TOBN(0x211cb995, 0x9ea42600), TOBN(0xcd105f41, 0x7b069889), + TOBN(0xb1e1cf19, 0xddb81e74), TOBN(0x472f2d89, 0x5157b8ca), + TOBN(0x086fb008, 0xee9db885), TOBN(0x365cd570, 0x0f26d131), + TOBN(0x284b02bb, 0xa2be7053), TOBN(0xdcbbf7c6, 0x7ab9a6d6), + TOBN(0x4425559c, 0x20f7a530), TOBN(0x961f2dfa, 0x188767c8), + TOBN(0xe2fd9435, 0x70dc80c4), TOBN(0x104d6b63, 0xf0784120), + TOBN(0x7f592bc1, 0x53567122), TOBN(0xf6bc1246, 0xf688ad77), + TOBN(0x05214c05, 0x0f15dde9), TOBN(0xa47a76a8, 0x0d5f2b82), + TOBN(0xbb254d30, 0x62e82b62), TOBN(0x11a05fe0, 0x3ec955ee), + TOBN(0x7eaff46e, 0x9d529b36), TOBN(0x55ab1301, 0x8f9e3df6), + TOBN(0xc463e371, 0x99317698), TOBN(0xfd251438, 0xccda47ad), + TOBN(0xca9c3547, 0x23d695ea), TOBN(0x48ce626e, 0x16e589b5), + TOBN(0x6b5b64c7, 0xb187d086), TOBN(0xd02e1794, 0xb2207948), + TOBN(0x8b58e98f, 0x7198111d), TOBN(0x90ca6305, 0xdcf9c3cc), + TOBN(0x5691fe72, 0xf34089b0), TOBN(0x60941af1, 0xfc7c80ff), + TOBN(0xa09bc0a2, 0x22eb51e5), TOBN(0xc0bb7244, 0xaa9cf09a), + TOBN(0x36a8077f, 0x80159f06), TOBN(0x8b5c989e, 0xdddc560e), + TOBN(0x19d2f316, 0x512e1f43), TOBN(0x02eac554, 0xad08ff62), + TOBN(0x012ab84c, 0x07d20b4e), TOBN(0x37d1e115, 0xd6d4e4e1), + TOBN(0xb6443e1a, 0xab7b19a8), TOBN(0xf08d067e, 0xdef8cd45), + TOBN(0x63adf3e9, 0x685e03da), TOBN(0xcf15a10e, 0x4792b916), + TOBN(0xf44bcce5, 0xb738a425), TOBN(0xebe131d5, 0x9636b2fd), + TOBN(0x94068841, 0x7850d605), TOBN(0x09684eaa, 0xb40d749d), + TOBN(0x8c3c669c, 0x72ba075b), TOBN(0x89f78b55, 0xba469015), + TOBN(0x5706aade, 0x3e9f8ba8), TOBN(0x6d8bd565, 0xb32d7ed7), + TOBN(0x25f4e63b, 0x805f08d6), TOBN(0x7f48200d, 0xc3bcc1b5), + TOBN(0x4e801968, 0xb025d847), TOBN(0x74afac04, 0x87cbe0a8), + TOBN(0x43ed2c2b, 0x7e63d690), TOBN(0xefb6bbf0, 0x0223cdb8), + TOBN(0x4fec3cae, 0x2884d3fe), TOBN(0x065ecce6, 0xd75e25a4), + TOBN(0x6c2294ce, 0x69f79071), TOBN(0x0d9a8e5f, 0x044b8666), + TOBN(0x5009f238, 0x17b69d8f), TOBN(0x3c29f8fe, 0xc5dfdaf7), + TOBN(0x9067528f, 0xebae68c4), TOBN(0x5b385632, 0x30c5ba21), + TOBN(0x540df119, 0x1fdd1aec), TOBN(0xcf37825b, 0xcfba4c78), + TOBN(0x77eff980, 0xbeb11454), TOBN(0x40a1a991, 0x60c1b066), + TOBN(0xe8018980, 0xf889a1c7), TOBN(0xb9c52ae9, 0x76c24be0), + TOBN(0x05fbbcce, 0x45650ef4), TOBN(0xae000f10, 0x8aa29ac7), + TOBN(0x884b7172, 0x4f04c470), TOBN(0x7cd4fde2, 0x19bb5c25), + TOBN(0x6477b22a, 0xe8840869), TOBN(0xa8868859, 0x5fbd0686), + TOBN(0xf23cc02e, 0x1116dfba), TOBN(0x76cd563f, 0xd87d7776), + TOBN(0xe2a37598, 0xa9d82abf), TOBN(0x5f188ccb, 0xe6c170f5), + TOBN(0x81682200, 0x5066b087), TOBN(0xda22c212, 0xc7155ada), + TOBN(0x151e5d3a, 0xfbddb479), TOBN(0x4b606b84, 0x6d715b99), + TOBN(0x4a73b54b, 0xf997cb2e), TOBN(0x9a1bfe43, 0x3ecd8b66), + TOBN(0x1c312809, 0x2a67d48a), TOBN(0xcd6a671e, 0x031fa9e2), + TOBN(0xbec3312a, 0x0e43a34a), TOBN(0x1d935639, 0x55ef47d3), + TOBN(0x5ea02489, 0x8fea73ea), TOBN(0x8247b364, 0xa035afb2), + TOBN(0xb58300a6, 0x5265b54c), TOBN(0x3286662f, 0x722c7148), + TOBN(0xb77fd76b, 0xb4ec4c20), TOBN(0xf0a12fa7, 0x0f3fe3fd), + TOBN(0xf845bbf5, 0x41d8c7e8), TOBN(0xe4d969ca, 0x5ec10aa8), + TOBN(0x4c0053b7, 0x43e232a3), TOBN(0xdc7a3fac, 0x37f8a45a), + TOBN(0x3c4261c5, 0x20d81c8f), TOBN(0xfd4b3453, 0xb00eab00), + TOBN(0x76d48f86, 0xd36e3062), TOBN(0x626c5277, 0xa143ff02), + TOBN(0x538174de, 0xaf76f42e), TOBN(0x2267aa86, 0x6407ceac), + TOBN(0xfad76351, 0x72e572d5), TOBN(0xab861af7, 0xba7330eb), + TOBN(0xa0a1c8c7, 0x418d8657), TOBN(0x988821cb, 0x20289a52), + TOBN(0x79732522, 0xcccc18ad), TOBN(0xaadf3f8d, 0xf1a6e027), + TOBN(0xf7382c93, 0x17c2354d), TOBN(0x5ce1680c, 0xd818b689), + TOBN(0x359ebbfc, 0xd9ecbee9), TOBN(0x4330689c, 0x1cae62ac), + TOBN(0xb55ce5b4, 0xc51ac38a), TOBN(0x7921dfea, 0xfe238ee8), + TOBN(0x3972bef8, 0x271d1ca5), TOBN(0x3e423bc7, 0xe8aabd18), + TOBN(0x57b09f3f, 0x44a3e5e3), TOBN(0x5da886ae, 0x7b444d66), + TOBN(0x68206634, 0xa9964375), TOBN(0x356a2fa3, 0x699cd0ff), + TOBN(0xaf0faa24, 0xdba515e9), TOBN(0x536e1f5c, 0xb321d79a), + TOBN(0xd3b9913a, 0x5c04e4ea), TOBN(0xd549dcfe, 0xd6f11513), + TOBN(0xee227bf5, 0x79fd1d94), TOBN(0x9f35afee, 0xb43f2c67), + TOBN(0xd2638d24, 0xf1314f53), TOBN(0x62baf948, 0xcabcd822), + TOBN(0x5542de29, 0x4ef48db0), TOBN(0xb3eb6a04, 0xfc5f6bb2), + TOBN(0x23c110ae, 0x1208e16a), TOBN(0x1a4d15b5, 0xf8363e24), + TOBN(0x30716844, 0x164be00b), TOBN(0xa8e24824, 0xf6f4690d), + TOBN(0x548773a2, 0x90b170cf), TOBN(0xa1bef331, 0x42f191f4), + TOBN(0x70f418d0, 0x9247aa97), TOBN(0xea06028e, 0x48be9147), + TOBN(0xe13122f3, 0xdbfb894e), TOBN(0xbe9b79f6, 0xce274b18), + TOBN(0x85a49de5, 0xca58aadf), TOBN(0x24957758, 0x11487351), + TOBN(0x111def61, 0xbb939099), TOBN(0x1d6a974a, 0x26d13694), + TOBN(0x4474b4ce, 0xd3fc253b), TOBN(0x3a1485e6, 0x4c5db15e), + TOBN(0xe79667b4, 0x147c15b4), TOBN(0xe34f553b, 0x7bc61301), + TOBN(0x032b80f8, 0x17094381), TOBN(0x55d8bafd, 0x723eaa21), + TOBN(0x5a987995, 0xf1c0e74e), TOBN(0x5a9b292e, 0xebba289c), + TOBN(0x413cd4b2, 0xeb4c8251), TOBN(0x98b5d243, 0xd162db0a), + TOBN(0xbb47bf66, 0x68342520), TOBN(0x08d68949, 0xbaa862d1), + TOBN(0x11f349c7, 0xe906abcd), TOBN(0x454ce985, 0xed7bf00e), + TOBN(0xacab5c9e, 0xb55b803b), TOBN(0xb03468ea, 0x31e3c16d), + TOBN(0x5c24213d, 0xd273bf12), TOBN(0x211538eb, 0x71587887), + TOBN(0x198e4a2f, 0x731dea2d), TOBN(0xd5856cf2, 0x74ed7b2a), + TOBN(0x86a632eb, 0x13a664fe), TOBN(0x932cd909, 0xbda41291), + TOBN(0x850e95d4, 0xc0c4ddc0), TOBN(0xc0f422f8, 0x347fc2c9), + TOBN(0xe68cbec4, 0x86076bcb), TOBN(0xf9e7c0c0, 0xcd6cd286), + TOBN(0x65994ddb, 0x0f5f27ca), TOBN(0xe85461fb, 0xa80d59ff), + TOBN(0xff05481a, 0x66601023), TOBN(0xc665427a, 0xfc9ebbfb), + TOBN(0xb0571a69, 0x7587fd52), TOBN(0x935289f8, 0x8d49efce), + TOBN(0x61becc60, 0xea420688), TOBN(0xb22639d9, 0x13a786af), + TOBN(0x1a8e6220, 0x361ecf90), TOBN(0x001f23e0, 0x25506463), + TOBN(0xe4ae9b5d, 0x0a5c2b79), TOBN(0xebc9cdad, 0xd8149db5), + TOBN(0xb33164a1, 0x934aa728), TOBN(0x750eb00e, 0xae9b60f3), + TOBN(0x5a91615b, 0x9b9cfbfd), TOBN(0x97015cbf, 0xef45f7f6), + TOBN(0xb462c4a5, 0xbf5151df), TOBN(0x21adcc41, 0xb07118f2), + TOBN(0xd60c545b, 0x043fa42c), TOBN(0xfc21aa54, 0xe96be1ab), + TOBN(0xe84bc32f, 0x4e51ea80), TOBN(0x3dae45f0, 0x259b5d8d), + TOBN(0xbb73c7eb, 0xc38f1b5e), TOBN(0xe405a74a, 0xe8ae617d), + TOBN(0xbb1ae9c6, 0x9f1c56bd), TOBN(0x8c176b98, 0x49f196a4), + TOBN(0xc448f311, 0x6875092b), TOBN(0xb5afe3de, 0x9f976033), + TOBN(0xa8dafd49, 0x145813e5), TOBN(0x687fc4d9, 0xe2b34226), + TOBN(0xf2dfc92d, 0x4c7ff57f), TOBN(0x004e3fc1, 0x401f1b46), + TOBN(0x5afddab6, 0x1430c9ab), TOBN(0x0bdd41d3, 0x2238e997), + TOBN(0xf0947430, 0x418042ae), TOBN(0x71f9adda, 0xcdddc4cb), + TOBN(0x7090c016, 0xc52dd907), TOBN(0xd9bdf44d, 0x29e2047f), + TOBN(0xe6f1fe80, 0x1b1011a6), TOBN(0xb63accbc, 0xd9acdc78), + TOBN(0xcfc7e235, 0x1272a95b), TOBN(0x0c667717, 0xa6276ac8), + TOBN(0x3c0d3709, 0xe2d7eef7), TOBN(0x5add2b06, 0x9a685b3e), + TOBN(0x363ad32d, 0x14ea5d65), TOBN(0xf8e01f06, 0x8d7dd506), + TOBN(0xc9ea2213, 0x75b4aac6), TOBN(0xed2a2bf9, 0x0d353466), + TOBN(0x439d79b5, 0xe9d3a7c3), TOBN(0x8e0ee5a6, 0x81b7f34b), + TOBN(0xcf3dacf5, 0x1dc4ba75), TOBN(0x1d3d1773, 0xeb3310c7), + TOBN(0xa8e67112, 0x7747ae83), TOBN(0x31f43160, 0x197d6b40), + TOBN(0x0521ccee, 0xcd961400), TOBN(0x67246f11, 0xf6535768), + TOBN(0x702fcc5a, 0xef0c3133), TOBN(0x247cc45d, 0x7e16693b), + TOBN(0xfd484e49, 0xc729b749), TOBN(0x522cef7d, 0xb218320f), + TOBN(0xe56ef405, 0x59ab93b3), TOBN(0x225fba11, 0x9f181071), + TOBN(0x33bd6595, 0x15330ed0), TOBN(0xc4be69d5, 0x1ddb32f7), + TOBN(0x264c7668, 0x0448087c), TOBN(0xac30903f, 0x71432dae), + TOBN(0x3851b266, 0x00f9bf47), TOBN(0x400ed311, 0x6cdd6d03), + TOBN(0x045e79fe, 0xf8fd2424), TOBN(0xfdfd974a, 0xfa6da98b), + TOBN(0x45c9f641, 0x0c1e673a), TOBN(0x76f2e733, 0x5b2c5168), + TOBN(0x1adaebb5, 0x2a601753), TOBN(0xb286514c, 0xc57c2d49), + TOBN(0xd8769670, 0x1e0bfd24), TOBN(0x950c547e, 0x04478922), + TOBN(0xd1d41969, 0xe5d32bfe), TOBN(0x30bc1472, 0x750d6c3e), + TOBN(0x8f3679fe, 0xe0e27f3a), TOBN(0x8f64a7dc, 0xa4a6ee0c), + TOBN(0x2fe59937, 0x633dfb1f), TOBN(0xea82c395, 0x977f2547), + TOBN(0xcbdfdf1a, 0x661ea646), TOBN(0xc7ccc591, 0xb9085451), + TOBN(0x82177962, 0x81761e13), TOBN(0xda57596f, 0x9196885c), + TOBN(0xbc17e849, 0x28ffbd70), TOBN(0x1e6e0a41, 0x2671d36f), + TOBN(0x61ae872c, 0x4152fcf5), TOBN(0x441c87b0, 0x9e77e754), + TOBN(0xd0799dd5, 0xa34dff09), TOBN(0x766b4e44, 0x88a6b171), + TOBN(0xdc06a512, 0x11f1c792), TOBN(0xea02ae93, 0x4be35c3e), + TOBN(0xe5ca4d6d, 0xe90c469e), TOBN(0x4df4368e, 0x56e4ff5c), + TOBN(0x7817acab, 0x4baef62e), TOBN(0x9f5a2202, 0xa85b91e8), + TOBN(0x9666ebe6, 0x6ce57610), TOBN(0x32ad31f3, 0xf73bfe03), + TOBN(0x628330a4, 0x25bcf4d6), TOBN(0xea950593, 0x515056e6), + TOBN(0x59811c89, 0xe1332156), TOBN(0xc89cf1fe, 0x8c11b2d7), + TOBN(0x75b63913, 0x04e60cc0), TOBN(0xce811e8d, 0x4625d375), + TOBN(0x030e43fc, 0x2d26e562), TOBN(0xfbb30b4b, 0x608d36a0), + TOBN(0x634ff82c, 0x48528118), TOBN(0x7c6fe085, 0xcd285911), + TOBN(0x7f2830c0, 0x99358f28), TOBN(0x2e60a95e, 0x665e6c09), + TOBN(0x08407d3d, 0x9b785dbf), TOBN(0x530889ab, 0xa759bce7), + TOBN(0xf228e0e6, 0x52f61239), TOBN(0x2b6d1461, 0x6879be3c), + TOBN(0xe6902c04, 0x51a7bbf7), TOBN(0x30ad99f0, 0x76f24a64), + TOBN(0x66d9317a, 0x98bc6da0), TOBN(0xf4f877f3, 0xcb596ac0), + TOBN(0xb05ff62d, 0x4c44f119), TOBN(0x4555f536, 0xe9b77416), + TOBN(0xc7c0d059, 0x8caed63b), TOBN(0x0cd2b7ce, 0xc358b2a9), + TOBN(0x3f33287b, 0x46945fa3), TOBN(0xf8785b20, 0xd67c8791), + TOBN(0xc54a7a61, 0x9637bd08), TOBN(0x54d4598c, 0x18be79d7), + TOBN(0x889e5acb, 0xc46d7ce1), TOBN(0x9a515bb7, 0x8b085877), + TOBN(0xfac1a03d, 0x0b7a5050), TOBN(0x7d3e738a, 0xf2926035), + TOBN(0x861cc2ce, 0x2a6cb0eb), TOBN(0x6f2e2955, 0x8f7adc79), + TOBN(0x61c4d451, 0x33016376), TOBN(0xd9fd2c80, 0x5ad59090), + TOBN(0xe5a83738, 0xb2b836a1), TOBN(0x855b41a0, 0x7c0d6622), + TOBN(0x186fe317, 0x7cc19af1), TOBN(0x6465c1ff, 0xfdd99acb), + TOBN(0x46e5c23f, 0x6974b99e), TOBN(0x75a7cf8b, 0xa2717cbe), + TOBN(0x4d2ebc3f, 0x062be658), TOBN(0x094b4447, 0x5f209c98), + TOBN(0x4af285ed, 0xb940cb5a), TOBN(0x6706d792, 0x7cc82f10), + TOBN(0xc8c8776c, 0x030526fa), TOBN(0xfa8e6f76, 0xa0da9140), + TOBN(0x77ea9d34, 0x591ee4f0), TOBN(0x5f46e337, 0x40274166), + TOBN(0x1bdf98bb, 0xea671457), TOBN(0xd7c08b46, 0x862a1fe2), + TOBN(0x46cc303c, 0x1c08ad63), TOBN(0x99543440, 0x4c845e7b), + TOBN(0x1b8fbdb5, 0x48f36bf7), TOBN(0x5b82c392, 0x8c8273a7), + TOBN(0x08f712c4, 0x928435d5), TOBN(0x071cf0f1, 0x79330380), + TOBN(0xc74c2d24, 0xa8da054a), TOBN(0xcb0e7201, 0x43c46b5c), + TOBN(0x0ad7337a, 0xc0b7eff3), TOBN(0x8552225e, 0xc5e48b3c), + TOBN(0xe6f78b0c, 0x73f13a5f), TOBN(0x5e70062e, 0x82349cbe), + TOBN(0x6b8d5048, 0xe7073969), TOBN(0x392d2a29, 0xc33cb3d2), + TOBN(0xee4f727c, 0x4ecaa20f), TOBN(0xa068c99e, 0x2ccde707), + TOBN(0xfcd5651f, 0xb87a2913), TOBN(0xea3e3c15, 0x3cc252f0), + TOBN(0x777d92df, 0x3b6cd3e4), TOBN(0x7a414143, 0xc5a732e7), + TOBN(0xa895951a, 0xa71ff493), TOBN(0xfe980c92, 0xbbd37cf6), + TOBN(0x45bd5e64, 0xdecfeeff), TOBN(0x910dc2a9, 0xa44c43e9), + TOBN(0xcb403f26, 0xcca9f54d), TOBN(0x928bbdfb, 0x9303f6db), + TOBN(0x3c37951e, 0xa9eee67c), TOBN(0x3bd61a52, 0xf79961c3), + TOBN(0x09a238e6, 0x395c9a79), TOBN(0x6940ca2d, 0x61eb352d), + TOBN(0x7d1e5c5e, 0xc1875631), TOBN(0x1e19742c, 0x1e1b20d1), + TOBN(0x4633d908, 0x23fc2e6e), TOBN(0xa76e29a9, 0x08959149), + TOBN(0x61069d9c, 0x84ed7da5), TOBN(0x0baa11cf, 0x5dbcad51), + TOBN(0xd01eec64, 0x961849da), TOBN(0x93b75f1f, 0xaf3d8c28), + TOBN(0x57bc4f9f, 0x1ca2ee44), TOBN(0x5a26322d, 0x00e00558), + TOBN(0x1888d658, 0x61a023ef), TOBN(0x1d72aab4, 0xb9e5246e), + TOBN(0xa9a26348, 0xe5563ec0), TOBN(0xa0971963, 0xc3439a43), + TOBN(0x567dd54b, 0xadb9b5b7), TOBN(0x73fac1a1, 0xc45a524b), + TOBN(0x8fe97ef7, 0xfe38e608), TOBN(0x608748d2, 0x3f384f48), + TOBN(0xb0571794, 0xc486094f), TOBN(0x869254a3, 0x8bf3a8d6), + TOBN(0x148a8dd1, 0x310b0e25), TOBN(0x99ab9f3f, 0x9aa3f7d8), + TOBN(0x0927c68a, 0x6706c02e), TOBN(0x22b5e76c, 0x69790e6c), + TOBN(0x6c325260, 0x6c71376c), TOBN(0x53a57690, 0x09ef6657), + TOBN(0x8d63f852, 0xedffcf3a), TOBN(0xb4d2ed04, 0x3c0a6f55), + TOBN(0xdb3aa8de, 0x12519b9e), TOBN(0x5d38e9c4, 0x1e0a569a), + TOBN(0x871528bf, 0x303747e2), TOBN(0xa208e77c, 0xf5b5c18d), + TOBN(0x9d129c88, 0xca6bf923), TOBN(0xbcbf197f, 0xbf02839f), + TOBN(0x9b9bf030, 0x27323194), TOBN(0x3b055a8b, 0x339ca59d), + TOBN(0xb46b2312, 0x0f669520), TOBN(0x19789f1f, 0x497e5f24), + TOBN(0x9c499468, 0xaaf01801), TOBN(0x72ee1190, 0x8b69d59c), + TOBN(0x8bd39595, 0xacf4c079), TOBN(0x3ee11ece, 0x8e0cd048), + TOBN(0xebde86ec, 0x1ed66f18), TOBN(0x225d906b, 0xd61fce43), + TOBN(0x5cab07d6, 0xe8bed74d), TOBN(0x16e4617f, 0x27855ab7), + TOBN(0x6568aadd, 0xb2fbc3dd), TOBN(0xedb5484f, 0x8aeddf5b), + TOBN(0x878f20e8, 0x6dcf2fad), TOBN(0x3516497c, 0x615f5699),} + , + {TOBN(0xef0a3fec, 0xfa181e69), TOBN(0x9ea02f81, 0x30d69a98), + TOBN(0xb2e9cf8e, 0x66eab95d), TOBN(0x520f2beb, 0x24720021), + TOBN(0x621c540a, 0x1df84361), TOBN(0x12037721, 0x71fa6d5d), + TOBN(0x6e3c7b51, 0x0ff5f6ff), TOBN(0x817a069b, 0xabb2bef3), + TOBN(0x83572fb6, 0xb294cda6), TOBN(0x6ce9bf75, 0xb9039f34), + TOBN(0x20e012f0, 0x095cbb21), TOBN(0xa0aecc1b, 0xd063f0da), + TOBN(0x57c21c3a, 0xf02909e5), TOBN(0xc7d59ecf, 0x48ce9cdc), + TOBN(0x2732b844, 0x8ae336f8), TOBN(0x056e3723, 0x3f4f85f4), + TOBN(0x8a10b531, 0x89e800ca), TOBN(0x50fe0c17, 0x145208fd), + TOBN(0x9e43c0d3, 0xb714ba37), TOBN(0x427d200e, 0x34189acc), + TOBN(0x05dee24f, 0xe616e2c0), TOBN(0x9c25f4c8, 0xee1854c1), + TOBN(0x4d3222a5, 0x8f342a73), TOBN(0x0807804f, 0xa027c952), + TOBN(0xc222653a, 0x4f0d56f3), TOBN(0x961e4047, 0xca28b805), + TOBN(0x2c03f8b0, 0x4a73434b), TOBN(0x4c966787, 0xab712a19), + TOBN(0xcc196c42, 0x864fee42), TOBN(0xc1be93da, 0x5b0ece5c), + TOBN(0xa87d9f22, 0xc131c159), TOBN(0x2bb6d593, 0xdce45655), + TOBN(0x22c49ec9, 0xb809b7ce), TOBN(0x8a41486b, 0xe2c72c2c), + TOBN(0x813b9420, 0xfea0bf36), TOBN(0xb3d36ee9, 0xa66dac69), + TOBN(0x6fddc08a, 0x328cc987), TOBN(0x0a3bcd2c, 0x3a326461), + TOBN(0x7103c49d, 0xd810dbba), TOBN(0xf9d81a28, 0x4b78a4c4), + TOBN(0x3de865ad, 0xe4d55941), TOBN(0xdedafa5e, 0x30384087), + TOBN(0x6f414abb, 0x4ef18b9b), TOBN(0x9ee9ea42, 0xfaee5268), + TOBN(0x260faa16, 0x37a55a4a), TOBN(0xeb19a514, 0x015f93b9), + TOBN(0x51d7ebd2, 0x9e9c3598), TOBN(0x523fc56d, 0x1932178e), + TOBN(0x501d070c, 0xb98fe684), TOBN(0xd60fbe9a, 0x124a1458), + TOBN(0xa45761c8, 0x92bc6b3f), TOBN(0xf5384858, 0xfe6f27cb), + TOBN(0x4b0271f7, 0xb59e763b), TOBN(0x3d4606a9, 0x5b5a8e5e), + TOBN(0x1eda5d9b, 0x05a48292), TOBN(0xda7731d0, 0xe6fec446), + TOBN(0xa3e33693, 0x90d45871), TOBN(0xe9764040, 0x06166d8d), + TOBN(0xb5c33682, 0x89a90403), TOBN(0x4bd17983, 0x72f1d637), + TOBN(0xa616679e, 0xd5d2c53a), TOBN(0x5ec4bcd8, 0xfdcf3b87), + TOBN(0xae6d7613, 0xb66a694e), TOBN(0x7460fc76, 0xe3fc27e5), + TOBN(0x70469b82, 0x95caabee), TOBN(0xde024ca5, 0x889501e3), + TOBN(0x6bdadc06, 0x076ed265), TOBN(0x0cb1236b, 0x5a0ef8b2), + TOBN(0x4065ddbf, 0x0972ebf9), TOBN(0xf1dd3875, 0x22aca432), + TOBN(0xa88b97cf, 0x744aff76), TOBN(0xd1359afd, 0xfe8e3d24), + TOBN(0x52a3ba2b, 0x91502cf3), TOBN(0x2c3832a8, 0x084db75d), + TOBN(0x04a12ddd, 0xde30b1c9), TOBN(0x7802eabc, 0xe31fd60c), + TOBN(0x33707327, 0xa37fddab), TOBN(0x65d6f2ab, 0xfaafa973), + TOBN(0x3525c5b8, 0x11e6f91a), TOBN(0x76aeb0c9, 0x5f46530b), + TOBN(0xe8815ff6, 0x2f93a675), TOBN(0xa6ec9684, 0x05f48679), + TOBN(0x6dcbb556, 0x358ae884), TOBN(0x0af61472, 0xe19e3873), + TOBN(0x72334372, 0xa5f696be), TOBN(0xc65e57ea, 0x6f22fb70), + TOBN(0x268da30c, 0x946cea90), TOBN(0x136a8a87, 0x65681b2a), + TOBN(0xad5e81dc, 0x0f9f44d4), TOBN(0xf09a6960, 0x2c46585a), + TOBN(0xd1649164, 0xc447d1b1), TOBN(0x3b4b36c8, 0x879dc8b1), + TOBN(0x20d4177b, 0x3b6b234c), TOBN(0x096a2505, 0x1730d9d0), + TOBN(0x0611b9b8, 0xef80531d), TOBN(0xba904b3b, 0x64bb495d), + TOBN(0x1192d9d4, 0x93a3147a), TOBN(0x9f30a5dc, 0x9a565545), + TOBN(0x90b1f9cb, 0x6ef07212), TOBN(0x29958546, 0x0d87fc13), + TOBN(0xd3323eff, 0xc17db9ba), TOBN(0xcb18548c, 0xcb1644a8), + TOBN(0x18a306d4, 0x4f49ffbc), TOBN(0x28d658f1, 0x4c2e8684), + TOBN(0x44ba60cd, 0xa99f8c71), TOBN(0x67b7abdb, 0x4bf742ff), + TOBN(0x66310f9c, 0x914b3f99), TOBN(0xae430a32, 0xf412c161), + TOBN(0x1e6776d3, 0x88ace52f), TOBN(0x4bc0fa24, 0x52d7067d), + TOBN(0x03c286aa, 0x8f07cd1b), TOBN(0x4cb8f38c, 0xa985b2c1), + TOBN(0x83ccbe80, 0x8c3bff36), TOBN(0x005a0bd2, 0x5263e575), + TOBN(0x460d7dda, 0x259bdcd1), TOBN(0x4a1c5642, 0xfa5cab6b), + TOBN(0x2b7bdbb9, 0x9fe4fc88), TOBN(0x09418e28, 0xcc97bbb5), + TOBN(0xd8274fb4, 0xa12321ae), TOBN(0xb137007d, 0x5c87b64e), + TOBN(0x80531fe1, 0xc63c4962), TOBN(0x50541e89, 0x981fdb25), + TOBN(0xdc1291a1, 0xfd4c2b6b), TOBN(0xc0693a17, 0xa6df4fca), + TOBN(0xb2c4604e, 0x0117f203), TOBN(0x245f1963, 0x0a99b8d0), + TOBN(0xaedc20aa, 0xc6212c44), TOBN(0xb1ed4e56, 0x520f52a8), + TOBN(0xfe48f575, 0xf8547be3), TOBN(0x0a7033cd, 0xa9e45f98), + TOBN(0x4b45d3a9, 0x18c50100), TOBN(0xb2a6cd6a, 0xa61d41da), + TOBN(0x60bbb4f5, 0x57933c6b), TOBN(0xa7538ebd, 0x2b0d7ffc), + TOBN(0x9ea3ab8d, 0x8cd626b6), TOBN(0x8273a484, 0x3601625a), + TOBN(0x88859845, 0x0168e508), TOBN(0x8cbc9bb2, 0x99a94abd), + TOBN(0x713ac792, 0xfab0a671), TOBN(0xa3995b19, 0x6c9ebffc), + TOBN(0xe711668e, 0x1239e152), TOBN(0x56892558, 0xbbb8dff4), + TOBN(0x8bfc7dab, 0xdbf17963), TOBN(0x5b59fe5a, 0xb3de1253), + TOBN(0x7e3320eb, 0x34a9f7ae), TOBN(0xe5e8cf72, 0xd751efe4), + TOBN(0x7ea003bc, 0xd9be2f37), TOBN(0xc0f551a0, 0xb6c08ef7), + TOBN(0x56606268, 0x038f6725), TOBN(0x1dd38e35, 0x6d92d3b6), + TOBN(0x07dfce7c, 0xc3cbd686), TOBN(0x4e549e04, 0x651c5da8), + TOBN(0x4058f93b, 0x08b19340), TOBN(0xc2fae6f4, 0xcac6d89d), + TOBN(0x4bad8a8c, 0x8f159cc7), TOBN(0x0ddba4b3, 0xcb0b601c), + TOBN(0xda4fc7b5, 0x1dd95f8c), TOBN(0x1d163cd7, 0xcea5c255), + TOBN(0x30707d06, 0x274a8c4c), TOBN(0x79d9e008, 0x2802e9ce), + TOBN(0x02a29ebf, 0xe6ddd505), TOBN(0x37064e74, 0xb50bed1a), + TOBN(0x3f6bae65, 0xa7327d57), TOBN(0x3846f5f1, 0xf83920bc), + TOBN(0x87c37491, 0x60df1b9b), TOBN(0x4cfb2895, 0x2d1da29f), + TOBN(0x10a478ca, 0x4ed1743c), TOBN(0x390c6030, 0x3edd47c6), + TOBN(0x8f3e5312, 0x8c0a78de), TOBN(0xccd02bda, 0x1e85df70), + TOBN(0xd6c75c03, 0xa61b6582), TOBN(0x0762921c, 0xfc0eebd1), + TOBN(0xd34d0823, 0xd85010c0), TOBN(0xd73aaacb, 0x0044cf1f), + TOBN(0xfb4159bb, 0xa3b5e78a), TOBN(0x2287c7f7, 0xe5826f3f), + TOBN(0x4aeaf742, 0x580b1a01), TOBN(0xf080415d, 0x60423b79), + TOBN(0xe12622cd, 0xa7dea144), TOBN(0x49ea4996, 0x59d62472), + TOBN(0xb42991ef, 0x571f3913), TOBN(0x0610f214, 0xf5b25a8a), + TOBN(0x47adc585, 0x30b79e8f), TOBN(0xf90e3df6, 0x07a065a2), + TOBN(0x5d0a5deb, 0x43e2e034), TOBN(0x53fb5a34, 0x444024aa), + TOBN(0xa8628c68, 0x6b0c9f7f), TOBN(0x9c69c29c, 0xac563656), + TOBN(0x5a231feb, 0xbace47b6), TOBN(0xbdce0289, 0x9ea5a2ec), + TOBN(0x05da1fac, 0x9463853e), TOBN(0x96812c52, 0x509e78aa), + TOBN(0xd3fb5771, 0x57151692), TOBN(0xeb2721f8, 0xd98e1c44), + TOBN(0xc0506087, 0x32399be1), TOBN(0xda5a5511, 0xd979d8b8), + TOBN(0x737ed55d, 0xc6f56780), TOBN(0xe20d3004, 0x0dc7a7f4), + TOBN(0x02ce7301, 0xf5941a03), TOBN(0x91ef5215, 0xed30f83a), + TOBN(0x28727fc1, 0x4092d85f), TOBN(0x72d223c6, 0x5c49e41a), + TOBN(0xa7cf30a2, 0xba6a4d81), TOBN(0x7c086209, 0xb030d87d), + TOBN(0x04844c7d, 0xfc588b09), TOBN(0x728cd499, 0x5874bbb0), + TOBN(0xcc1281ee, 0xe84c0495), TOBN(0x0769b5ba, 0xec31958f), + TOBN(0x665c228b, 0xf99c2471), TOBN(0xf2d8a11b, 0x191eb110), + TOBN(0x4594f494, 0xd36d7024), TOBN(0x482ded8b, 0xcdcb25a1), + TOBN(0xc958a9d8, 0xdadd4885), TOBN(0x7004477e, 0xf1d2b547), + TOBN(0x0a45f6ef, 0x2a0af550), TOBN(0x4fc739d6, 0x2f8d6351), + TOBN(0x75cdaf27, 0x786f08a9), TOBN(0x8700bb26, 0x42c2737f), + TOBN(0x855a7141, 0x1c4e2670), TOBN(0x810188c1, 0x15076fef), + TOBN(0xc251d0c9, 0xabcd3297), TOBN(0xae4c8967, 0xf48108eb), + TOBN(0xbd146de7, 0x18ceed30), TOBN(0xf9d4f07a, 0xc986bced), + TOBN(0x5ad98ed5, 0x83fa1e08), TOBN(0x7780d33e, 0xbeabd1fb), + TOBN(0xe330513c, 0x903b1196), TOBN(0xba11de9e, 0xa47bc8c4), + TOBN(0x684334da, 0x02c2d064), TOBN(0x7ecf360d, 0xa48de23b), + TOBN(0x57a1b474, 0x0a9089d8), TOBN(0xf28fa439, 0xff36734c), + TOBN(0xf2a482cb, 0xea4570b3), TOBN(0xee65d68b, 0xa5ebcee9), + TOBN(0x988d0036, 0xb9694cd5), TOBN(0x53edd0e9, 0x37885d32), + TOBN(0xe37e3307, 0xbeb9bc6d), TOBN(0xe9abb907, 0x9f5c6768), + TOBN(0x4396ccd5, 0x51f2160f), TOBN(0x2500888c, 0x47336da6), + TOBN(0x383f9ed9, 0x926fce43), TOBN(0x809dd1c7, 0x04da2930), + TOBN(0x30f6f596, 0x8a4cb227), TOBN(0x0d700c7f, 0x73a56b38), + TOBN(0x1825ea33, 0xab64a065), TOBN(0xaab9b735, 0x1338df80), + TOBN(0x1516100d, 0x9b63f57f), TOBN(0x2574395a, 0x27a6a634), + TOBN(0xb5560fb6, 0x700a1acd), TOBN(0xe823fd73, 0xfd999681), + TOBN(0xda915d1f, 0x6cb4e1ba), TOBN(0x0d030118, 0x6ebe00a3), + TOBN(0x744fb0c9, 0x89fca8cd), TOBN(0x970d01db, 0xf9da0e0b), + TOBN(0x0ad8c564, 0x7931d76f), TOBN(0xb15737bf, 0xf659b96a), + TOBN(0xdc9933e8, 0xa8b484e7), TOBN(0xb2fdbdf9, 0x7a26dec7), + TOBN(0x2349e9a4, 0x9f1f0136), TOBN(0x7860368e, 0x70fddddb), + TOBN(0xd93d2c1c, 0xf9ad3e18), TOBN(0x6d6c5f17, 0x689f4e79), + TOBN(0x7a544d91, 0xb24ff1b6), TOBN(0x3e12a5eb, 0xfe16cd8c), + TOBN(0x543574e9, 0xa56b872f), TOBN(0xa1ad550c, 0xfcf68ea2), + TOBN(0x689e37d2, 0x3f560ef7), TOBN(0x8c54b9ca, 0xc9d47a8b), + TOBN(0x46d40a4a, 0x088ac342), TOBN(0xec450c7c, 0x1576c6d0), + TOBN(0xb589e31c, 0x1f9689e9), TOBN(0xdacf2602, 0xb8781718), + TOBN(0xa89237c6, 0xc8cb6b42), TOBN(0x1326fc93, 0xb96ef381), + TOBN(0x55d56c6d, 0xb5f07825), TOBN(0xacba2eea, 0x7449e22d), + TOBN(0x74e0887a, 0x633c3000), TOBN(0xcb6cd172, 0xd7cbcf71), + TOBN(0x309e81de, 0xc36cf1be), TOBN(0x07a18a6d, 0x60ae399b), + TOBN(0xb36c2679, 0x9edce57e), TOBN(0x52b892f4, 0xdf001d41), + TOBN(0xd884ae5d, 0x16a1f2c6), TOBN(0x9b329424, 0xefcc370a), + TOBN(0x3120daf2, 0xbd2e21df), TOBN(0x55298d2d, 0x02470a99), + TOBN(0x0b78af6c, 0xa05db32e), TOBN(0x5c76a331, 0x601f5636), + TOBN(0xaae861ff, 0xf8a4f29c), TOBN(0x70dc9240, 0xd68f8d49), + TOBN(0x960e649f, 0x81b1321c), TOBN(0x3d2c801b, 0x8792e4ce), + TOBN(0xf479f772, 0x42521876), TOBN(0x0bed93bc, 0x416c79b1), + TOBN(0xa67fbc05, 0x263e5bc9), TOBN(0x01e8e630, 0x521db049), + TOBN(0x76f26738, 0xc6f3431e), TOBN(0xe609cb02, 0xe3267541), + TOBN(0xb10cff2d, 0x818c877c), TOBN(0x1f0e75ce, 0x786a13cb), + TOBN(0xf4fdca64, 0x1158544d), TOBN(0x5d777e89, 0x6cb71ed0), + TOBN(0x3c233737, 0xa9aa4755), TOBN(0x7b453192, 0xe527ab40), + TOBN(0xdb59f688, 0x39f05ffe), TOBN(0x8f4f4be0, 0x6d82574e), + TOBN(0xcce3450c, 0xee292d1b), TOBN(0xaa448a12, 0x61ccd086), + TOBN(0xabce91b3, 0xf7914967), TOBN(0x4537f09b, 0x1908a5ed), + TOBN(0xa812421e, 0xf51042e7), TOBN(0xfaf5cebc, 0xec0b3a34), + TOBN(0x730ffd87, 0x4ca6b39a), TOBN(0x70fb72ed, 0x02efd342), + TOBN(0xeb4735f9, 0xd75c8edb), TOBN(0xc11f2157, 0xc278aa51), + TOBN(0xc459f635, 0xbf3bfebf), TOBN(0x3a1ff0b4, 0x6bd9601f), + TOBN(0xc9d12823, 0xc420cb73), TOBN(0x3e9af3e2, 0x3c2915a3), + TOBN(0xe0c82c72, 0xb41c3440), TOBN(0x175239e5, 0xe3039a5f), + TOBN(0xe1084b8a, 0x558795a3), TOBN(0x328d0a1d, 0xd01e5c60), + TOBN(0x0a495f2e, 0xd3788a04), TOBN(0x25d8ff16, 0x66c11a9f), + TOBN(0xf5155f05, 0x9ed692d6), TOBN(0x954fa107, 0x4f425fe4), + TOBN(0xd16aabf2, 0xe98aaa99), TOBN(0x90cd8ba0, 0x96b0f88a), + TOBN(0x957f4782, 0xc154026a), TOBN(0x54ee0734, 0x52af56d2), + TOBN(0xbcf89e54, 0x45b4147a), TOBN(0x3d102f21, 0x9a52816c), + TOBN(0x6808517e, 0x39b62e77), TOBN(0x92e25421, 0x69169ad8), + TOBN(0xd721d871, 0xbb608558), TOBN(0x60e4ebae, 0xf6d4ff9b), + TOBN(0x0ba10819, 0x41f2763e), TOBN(0xca2e45be, 0x51ee3247), + TOBN(0x66d172ec, 0x2bfd7a5f), TOBN(0x528a8f2f, 0x74d0b12d), + TOBN(0xe17f1e38, 0xdabe70dc), TOBN(0x1d5d7316, 0x9f93983c), + TOBN(0x51b2184a, 0xdf423e31), TOBN(0xcb417291, 0xaedb1a10), + TOBN(0x2054ca93, 0x625bcab9), TOBN(0x54396860, 0xa98998f0), + TOBN(0x4e53f6c4, 0xa54ae57e), TOBN(0x0ffeb590, 0xee648e9d), + TOBN(0xfbbdaadc, 0x6afaf6bc), TOBN(0xf88ae796, 0xaa3bfb8a), + TOBN(0x209f1d44, 0xd2359ed9), TOBN(0xac68dd03, 0xf3544ce2), + TOBN(0xf378da47, 0xfd51e569), TOBN(0xe1abd860, 0x2cc80097), + TOBN(0x23ca18d9, 0x343b6e3a), TOBN(0x480797e8, 0xb40a1bae), + TOBN(0xd1f0c717, 0x533f3e67), TOBN(0x44896970, 0x06e6cdfc), + TOBN(0x8ca21055, 0x52a82e8d), TOBN(0xb2caf785, 0x78460cdc), + TOBN(0x4c1b7b62, 0xe9037178), TOBN(0xefc09d2c, 0xdb514b58), + TOBN(0x5f2df9ee, 0x9113be5c), TOBN(0x2fbda78f, 0xb3f9271c), + TOBN(0xe09a81af, 0x8f83fc54), TOBN(0x06b13866, 0x8afb5141), + TOBN(0x38f6480f, 0x43e3865d), TOBN(0x72dd77a8, 0x1ddf47d9), + TOBN(0xf2a8e971, 0x4c205ff7), TOBN(0x46d449d8, 0x9d088ad8), + TOBN(0x926619ea, 0x185d706f), TOBN(0xe47e02eb, 0xc7dd7f62), + TOBN(0xe7f120a7, 0x8cbc2031), TOBN(0xc18bef00, 0x998d4ac9), + TOBN(0x18f37a9c, 0x6bdf22da), TOBN(0xefbc432f, 0x90dc82df), + TOBN(0xc52cef8e, 0x5d703651), TOBN(0x82887ba0, 0xd99881a5), + TOBN(0x7cec9dda, 0xb920ec1d), TOBN(0xd0d7e8c3, 0xec3e8d3b), + TOBN(0x445bc395, 0x4ca88747), TOBN(0xedeaa2e0, 0x9fd53535), + TOBN(0x461b1d93, 0x6cc87475), TOBN(0xd92a52e2, 0x6d2383bd), + TOBN(0xfabccb59, 0xd7903546), TOBN(0x6111a761, 0x3d14b112), + TOBN(0x0ae584fe, 0xb3d5f612), TOBN(0x5ea69b8d, 0x60e828ec), + TOBN(0x6c078985, 0x54087030), TOBN(0x649cab04, 0xac4821fe), + TOBN(0x25ecedcf, 0x8bdce214), TOBN(0xb5622f72, 0x86af7361), + TOBN(0x0e1227aa, 0x7038b9e2), TOBN(0xd0efb273, 0xac20fa77), + TOBN(0x817ff88b, 0x79df975b), TOBN(0x856bf286, 0x1999503e), + TOBN(0xb4d5351f, 0x5038ec46), TOBN(0x740a52c5, 0xfc42af6e), + TOBN(0x2e38bb15, 0x2cbb1a3f), TOBN(0xc3eb99fe, 0x17a83429), + TOBN(0xca4fcbf1, 0xdd66bb74), TOBN(0x880784d6, 0xcde5e8fc), + TOBN(0xddc84c1c, 0xb4e7a0be), TOBN(0x8780510d, 0xbd15a72f), + TOBN(0x44bcf1af, 0x81ec30e1), TOBN(0x141e50a8, 0x0a61073e), + TOBN(0x0d955718, 0x47be87ae), TOBN(0x68a61417, 0xf76a4372), + TOBN(0xf57e7e87, 0xc607c3d3), TOBN(0x043afaf8, 0x5252f332), + TOBN(0xcc14e121, 0x1552a4d2), TOBN(0xb6dee692, 0xbb4d4ab4), + TOBN(0xb6ab74c8, 0xa03816a4), TOBN(0x84001ae4, 0x6f394a29), + TOBN(0x5bed8344, 0xd795fb45), TOBN(0x57326e7d, 0xb79f55a5), + TOBN(0xc9533ce0, 0x4accdffc), TOBN(0x53473caf, 0x3993fa04), + TOBN(0x7906eb93, 0xa13df4c8), TOBN(0xa73e51f6, 0x97cbe46f), + TOBN(0xd1ab3ae1, 0x0ae4ccf8), TOBN(0x25614508, 0x8a5b3dbc), + TOBN(0x61eff962, 0x11a71b27), TOBN(0xdf71412b, 0x6bb7fa39), + TOBN(0xb31ba6b8, 0x2bd7f3ef), TOBN(0xb0b9c415, 0x69180d29), + TOBN(0xeec14552, 0x014cdde5), TOBN(0x702c624b, 0x227b4bbb), + TOBN(0x2b15e8c2, 0xd3e988f3), TOBN(0xee3bcc6d, 0xa4f7fd04), + TOBN(0x9d00822a, 0x42ac6c85), TOBN(0x2db0cea6, 0x1df9f2b7), + TOBN(0xd7cad2ab, 0x42de1e58), TOBN(0x346ed526, 0x2d6fbb61), + TOBN(0xb3962995, 0x1a2faf09), TOBN(0x2fa8a580, 0x7c25612e), + TOBN(0x30ae04da, 0x7cf56490), TOBN(0x75662908, 0x0eea3961), + TOBN(0x3609f5c5, 0x3d080847), TOBN(0xcb081d39, 0x5241d4f6), + TOBN(0xb4fb3810, 0x77961a63), TOBN(0xc20c5984, 0x2abb66fc), + TOBN(0x3d40aa7c, 0xf902f245), TOBN(0x9cb12736, 0x4e536b1e), + TOBN(0x5eda24da, 0x99b3134f), TOBN(0xafbd9c69, 0x5cd011af), + TOBN(0x9a16e30a, 0xc7088c7d), TOBN(0x5ab65710, 0x3207389f), + TOBN(0x1b09547f, 0xe7407a53), TOBN(0x2322f9d7, 0x4fdc6eab), + TOBN(0xc0f2f22d, 0x7430de4d), TOBN(0x19382696, 0xe68ca9a9), + TOBN(0x17f1eff1, 0x918e5868), TOBN(0xe3b5b635, 0x586f4204), + TOBN(0x146ef980, 0x3fbc4341), TOBN(0x359f2c80, 0x5b5eed4e), + TOBN(0x9f35744e, 0x7482e41d), TOBN(0x9a9ac3ec, 0xf3b224c2), + TOBN(0x9161a6fe, 0x91fc50ae), TOBN(0x89ccc66b, 0xc613fa7c), + TOBN(0x89268b14, 0xc732f15a), TOBN(0x7cd6f4e2, 0xb467ed03), + TOBN(0xfbf79869, 0xce56b40e), TOBN(0xf93e094c, 0xc02dde98), + TOBN(0xefe0c3a8, 0xedee2cd7), TOBN(0x90f3ffc0, 0xb268fd42), + TOBN(0x81a7fd56, 0x08241aed), TOBN(0x95ab7ad8, 0x00b1afe8), + TOBN(0x40127056, 0x3e310d52), TOBN(0xd3ffdeb1, 0x09d9fc43), + TOBN(0xc8f85c91, 0xd11a8594), TOBN(0x2e74d258, 0x31cf6db8), + TOBN(0x829c7ca3, 0x02b5dfd0), TOBN(0xe389cfbe, 0x69143c86), + TOBN(0xd01b6405, 0x941768d8), TOBN(0x45103995, 0x03bf825d), + TOBN(0xcc4ee166, 0x56cd17e2), TOBN(0xbea3c283, 0xba037e79), + TOBN(0x4e1ac06e, 0xd9a47520), TOBN(0xfbfe18aa, 0xaf852404), + TOBN(0x5615f8e2, 0x8087648a), TOBN(0x7301e47e, 0xb9d150d9), + TOBN(0x79f9f9dd, 0xb299b977), TOBN(0x76697a7b, 0xa5b78314), + TOBN(0x10d67468, 0x7d7c90e7), TOBN(0x7afffe03, 0x937210b5), + TOBN(0x5aef3e4b, 0x28c22cee), TOBN(0xefb0ecd8, 0x09fd55ae), + TOBN(0x4cea7132, 0x0d2a5d6a), TOBN(0x9cfb5fa1, 0x01db6357), + TOBN(0x395e0b57, 0xf36e1ac5), TOBN(0x008fa9ad, 0x36cafb7d), + TOBN(0x8f6cdf70, 0x5308c4db), TOBN(0x51527a37, 0x95ed2477), + TOBN(0xba0dee30, 0x5bd21311), TOBN(0x6ed41b22, 0x909c90d7), + TOBN(0xc5f6b758, 0x7c8696d3), TOBN(0x0db8eaa8, 0x3ce83a80), + TOBN(0xd297fe37, 0xb24b4b6f), TOBN(0xfe58afe8, 0x522d1f0d), + TOBN(0x97358736, 0x8c98dbd9), TOBN(0x6bc226ca, 0x9454a527), + TOBN(0xa12b384e, 0xce53c2d0), TOBN(0x779d897d, 0x5e4606da), + TOBN(0xa53e47b0, 0x73ec12b0), TOBN(0x462dbbba, 0x5756f1ad), + TOBN(0x69fe09f2, 0xcafe37b6), TOBN(0x273d1ebf, 0xecce2e17), + TOBN(0x8ac1d538, 0x3cf607fd), TOBN(0x8035f7ff, 0x12e10c25),} + , + {TOBN(0x854d34c7, 0x7e6c5520), TOBN(0xc27df9ef, 0xdcb9ea58), + TOBN(0x405f2369, 0xd686666d), TOBN(0x29d1febf, 0x0417aa85), + TOBN(0x9846819e, 0x93470afe), TOBN(0x3e6a9669, 0xe2a27f9e), + TOBN(0x24d008a2, 0xe31e6504), TOBN(0xdba7cecf, 0x9cb7680a), + TOBN(0xecaff541, 0x338d6e43), TOBN(0x56f7dd73, 0x4541d5cc), + TOBN(0xb5d426de, 0x96bc88ca), TOBN(0x48d94f6b, 0x9ed3a2c3), + TOBN(0x6354a3bb, 0x2ef8279c), TOBN(0xd575465b, 0x0b1867f2), + TOBN(0xef99b0ff, 0x95225151), TOBN(0xf3e19d88, 0xf94500d8), + TOBN(0x92a83268, 0xe32dd620), TOBN(0x913ec99f, 0x627849a2), + TOBN(0xedd8fdfa, 0x2c378882), TOBN(0xaf96f33e, 0xee6f8cfe), + TOBN(0xc06737e5, 0xdc3fa8a5), TOBN(0x236bb531, 0xb0b03a1d), + TOBN(0x33e59f29, 0x89f037b0), TOBN(0x13f9b5a7, 0xd9a12a53), + TOBN(0x0d0df6ce, 0x51efb310), TOBN(0xcb5b2eb4, 0x958df5be), + TOBN(0xd6459e29, 0x36158e59), TOBN(0x82aae2b9, 0x1466e336), + TOBN(0xfb658a39, 0x411aa636), TOBN(0x7152ecc5, 0xd4c0a933), + TOBN(0xf10c758a, 0x49f026b7), TOBN(0xf4837f97, 0xcb09311f), + TOBN(0xddfb02c4, 0xc753c45f), TOBN(0x18ca81b6, 0xf9c840fe), + TOBN(0x846fd09a, 0xb0f8a3e6), TOBN(0xb1162add, 0xe7733dbc), + TOBN(0x7070ad20, 0x236e3ab6), TOBN(0xf88cdaf5, 0xb2a56326), + TOBN(0x05fc8719, 0x997cbc7a), TOBN(0x442cd452, 0x4b665272), + TOBN(0x7807f364, 0xb71698f5), TOBN(0x6ba418d2, 0x9f7b605e), + TOBN(0xfd20b00f, 0xa03b2cbb), TOBN(0x883eca37, 0xda54386f), + TOBN(0xff0be43f, 0xf3437f24), TOBN(0xe910b432, 0xa48bb33c), + TOBN(0x4963a128, 0x329df765), TOBN(0xac1dd556, 0xbe2fe6f7), + TOBN(0x557610f9, 0x24a0a3fc), TOBN(0x38e17bf4, 0xe881c3f9), + TOBN(0x6ba84faf, 0xed0dac99), TOBN(0xd4a222c3, 0x59eeb918), + TOBN(0xc79c1dbe, 0x13f542b6), TOBN(0x1fc65e0d, 0xe425d457), + TOBN(0xeffb754f, 0x1debb779), TOBN(0x638d8fd0, 0x9e08af60), + TOBN(0x994f523a, 0x626332d5), TOBN(0x7bc38833, 0x5561bb44), + TOBN(0x005ed4b0, 0x3d845ea2), TOBN(0xd39d3ee1, 0xc2a1f08a), + TOBN(0x6561fdd3, 0xe7676b0d), TOBN(0x620e35ff, 0xfb706017), + TOBN(0x36ce424f, 0xf264f9a8), TOBN(0xc4c3419f, 0xda2681f7), + TOBN(0xfb6afd2f, 0x69beb6e8), TOBN(0x3a50b993, 0x6d700d03), + TOBN(0xc840b2ad, 0x0c83a14f), TOBN(0x573207be, 0x54085bef), + TOBN(0x5af882e3, 0x09fe7e5b), TOBN(0x957678a4, 0x3b40a7e1), + TOBN(0x172d4bdd, 0x543056e2), TOBN(0x9c1b26b4, 0x0df13c0a), + TOBN(0x1c30861c, 0xf405ff06), TOBN(0xebac86bd, 0x486e828b), + TOBN(0xe791a971, 0x636933fc), TOBN(0x50e7c2be, 0x7aeee947), + TOBN(0xc3d4a095, 0xfa90d767), TOBN(0xae60eb7b, 0xe670ab7b), + TOBN(0x17633a64, 0x397b056d), TOBN(0x93a21f33, 0x105012aa), + TOBN(0x663c370b, 0xabb88643), TOBN(0x91df36d7, 0x22e21599), + TOBN(0x183ba835, 0x8b761671), TOBN(0x381eea1d, 0x728f3bf1), + TOBN(0xb9b2f1ba, 0x39966e6c), TOBN(0x7c464a28, 0xe7295492), + TOBN(0x0fd5f70a, 0x09b26b7f), TOBN(0xa9aba1f9, 0xfbe009df), + TOBN(0x857c1f22, 0x369b87ad), TOBN(0x3c00e5d9, 0x32fca556), + TOBN(0x1ad74cab, 0x90b06466), TOBN(0xa7112386, 0x550faaf2), + TOBN(0x7435e198, 0x6d9bd5f5), TOBN(0x2dcc7e38, 0x59c3463f), + TOBN(0xdc7df748, 0xca7bd4b2), TOBN(0x13cd4c08, 0x9dec2f31), + TOBN(0x0d3b5df8, 0xe3237710), TOBN(0x0dadb26e, 0xcbd2f7b0), + TOBN(0x9f5966ab, 0xe4aa082b), TOBN(0x666ec8de, 0x350e966e), + TOBN(0x1bfd1ed5, 0xee524216), TOBN(0xcd93c59b, 0x41dab0b6), + TOBN(0x658a8435, 0xd186d6ba), TOBN(0x1b7d34d2, 0x159d1195), + TOBN(0x5936e460, 0x22caf46b), TOBN(0x6a45dd8f, 0x9a96fe4f), + TOBN(0xf7925434, 0xb98f474e), TOBN(0x41410412, 0x0053ef15), + TOBN(0x71cf8d12, 0x41de97bf), TOBN(0xb8547b61, 0xbd80bef4), + TOBN(0xb47d3970, 0xc4db0037), TOBN(0xf1bcd328, 0xfef20dff), + TOBN(0x31a92e09, 0x10caad67), TOBN(0x1f591960, 0x5531a1e1), + TOBN(0x3bb852e0, 0x5f4fc840), TOBN(0x63e297ca, 0x93a72c6c), + TOBN(0x3c2b0b2e, 0x49abad67), TOBN(0x6ec405fc, 0xed3db0d9), + TOBN(0xdc14a530, 0x7fef1d40), TOBN(0xccd19846, 0x280896fc), + TOBN(0x00f83176, 0x9bb81648), TOBN(0xd69eb485, 0x653120d0), + TOBN(0xd17d75f4, 0x4ccabc62), TOBN(0x34a07f82, 0xb749fcb1), + TOBN(0x2c3af787, 0xbbfb5554), TOBN(0xb06ed4d0, 0x62e283f8), + TOBN(0x5722889f, 0xa19213a0), TOBN(0x162b085e, 0xdcf3c7b4), + TOBN(0xbcaecb31, 0xe0dd3eca), TOBN(0xc6237fbc, 0xe52f13a5), + TOBN(0xcc2b6b03, 0x27bac297), TOBN(0x2ae1cac5, 0xb917f54a), + TOBN(0x474807d4, 0x7845ae4f), TOBN(0xfec7dd92, 0xce5972e0), + TOBN(0xc3bd2541, 0x1d7915bb), TOBN(0x66f85dc4, 0xd94907ca), + TOBN(0xd981b888, 0xbdbcf0ca), TOBN(0xd75f5da6, 0xdf279e9f), + TOBN(0x128bbf24, 0x7054e934), TOBN(0x3c6ff6e5, 0x81db134b), + TOBN(0x795b7cf4, 0x047d26e4), TOBN(0xf370f7b8, 0x5049ec37), + TOBN(0xc6712d4d, 0xced945af), TOBN(0xdf30b5ec, 0x095642bc), + TOBN(0x9b034c62, 0x4896246e), TOBN(0x5652c016, 0xee90bbd1), + TOBN(0xeb38636f, 0x87fedb73), TOBN(0x5e32f847, 0x0135a613), + TOBN(0x0703b312, 0xcf933c83), TOBN(0xd05bb76e, 0x1a7f47e6), + TOBN(0x825e4f0c, 0x949c2415), TOBN(0x569e5622, 0x7250d6f8), + TOBN(0xbbe9eb3a, 0x6568013e), TOBN(0x8dbd203f, 0x22f243fc), + TOBN(0x9dbd7694, 0xb342734a), TOBN(0x8f6d12f8, 0x46afa984), + TOBN(0xb98610a2, 0xc9eade29), TOBN(0xbab4f323, 0x47dd0f18), + TOBN(0x5779737b, 0x671c0d46), TOBN(0x10b6a7c6, 0xd3e0a42a), + TOBN(0xfb19ddf3, 0x3035b41c), TOBN(0xd336343f, 0x99c45895), + TOBN(0x61fe4938, 0x54c857e5), TOBN(0xc4d506be, 0xae4e57d5), + TOBN(0x3cd8c8cb, 0xbbc33f75), TOBN(0x7281f08a, 0x9262c77d), + TOBN(0x083f4ea6, 0xf11a2823), TOBN(0x8895041e, 0x9fba2e33), + TOBN(0xfcdfea49, 0x9c438edf), TOBN(0x7678dcc3, 0x91edba44), + TOBN(0xf07b3b87, 0xe2ba50f0), TOBN(0xc13888ef, 0x43948c1b), + TOBN(0xc2135ad4, 0x1140af42), TOBN(0x8e5104f3, 0x926ed1a7), + TOBN(0xf24430cb, 0x88f6695f), TOBN(0x0ce0637b, 0x6d73c120), + TOBN(0xb2db01e6, 0xfe631e8f), TOBN(0x1c5563d7, 0xd7bdd24b), + TOBN(0x8daea3ba, 0x369ad44f), TOBN(0x000c81b6, 0x8187a9f9), + TOBN(0x5f48a951, 0xaae1fd9a), TOBN(0xe35626c7, 0x8d5aed8a), + TOBN(0x20952763, 0x0498c622), TOBN(0x76d17634, 0x773aa504), + TOBN(0x36d90dda, 0xeb300f7a), TOBN(0x9dcf7dfc, 0xedb5e801), + TOBN(0x645cb268, 0x74d5244c), TOBN(0xa127ee79, 0x348e3aa2), + TOBN(0x488acc53, 0x575f1dbb), TOBN(0x95037e85, 0x80e6161e), + TOBN(0x57e59283, 0x292650d0), TOBN(0xabe67d99, 0x14938216), + TOBN(0x3c7f944b, 0x3f8e1065), TOBN(0xed908cb6, 0x330e8924), + TOBN(0x08ee8fd5, 0x6f530136), TOBN(0x2227b7d5, 0xd7ffc169), + TOBN(0x4f55c893, 0xb5cd6dd5), TOBN(0x82225e11, 0xa62796e8), + TOBN(0x5c6cead1, 0xcb18e12c), TOBN(0x4381ae0c, 0x84f5a51a), + TOBN(0x345913d3, 0x7fafa4c8), TOBN(0x3d918082, 0x0491aac0), + TOBN(0x9347871f, 0x3e69264c), TOBN(0xbea9dd3c, 0xb4f4f0cd), + TOBN(0xbda5d067, 0x3eadd3e7), TOBN(0x0033c1b8, 0x0573bcd8), + TOBN(0x25589379, 0x5da2486c), TOBN(0xcb89ee5b, 0x86abbee7), + TOBN(0x8fe0a8f3, 0x22532e5d), TOBN(0xb6410ff0, 0x727dfc4c), + TOBN(0x619b9d58, 0x226726db), TOBN(0x5ec25669, 0x7a2b2dc7), + TOBN(0xaf4d2e06, 0x4c3beb01), TOBN(0x852123d0, 0x7acea556), + TOBN(0x0e9470fa, 0xf783487a), TOBN(0x75a7ea04, 0x5664b3eb), + TOBN(0x4ad78f35, 0x6798e4ba), TOBN(0x9214e6e5, 0xc7d0e091), + TOBN(0xc420b488, 0xb1290403), TOBN(0x64049e0a, 0xfc295749), + TOBN(0x03ef5af1, 0x3ae9841f), TOBN(0xdbe4ca19, 0xb0b662a6), + TOBN(0x46845c5f, 0xfa453458), TOBN(0xf8dabf19, 0x10b66722), + TOBN(0xb650f0aa, 0xcce2793b), TOBN(0x71db851e, 0xc5ec47c1), + TOBN(0x3eb78f3e, 0x3b234fa9), TOBN(0xb0c60f35, 0xfc0106ce), + TOBN(0x05427121, 0x774eadbd), TOBN(0x25367faf, 0xce323863), + TOBN(0x7541b5c9, 0xcd086976), TOBN(0x4ff069e2, 0xdc507ad1), + TOBN(0x74145256, 0x8776e667), TOBN(0x6e76142c, 0xb23c6bb5), + TOBN(0xdbf30712, 0x1b3a8a87), TOBN(0x60e7363e, 0x98450836), + TOBN(0x5741450e, 0xb7366d80), TOBN(0xe4ee14ca, 0x4837dbdf), + TOBN(0xa765eb9b, 0x69d4316f), TOBN(0x04548dca, 0x8ef43825), + TOBN(0x9c9f4e4c, 0x5ae888eb), TOBN(0x733abb51, 0x56e9ac99), + TOBN(0xdaad3c20, 0xba6ac029), TOBN(0x9b8dd3d3, 0x2ba3e38e), + TOBN(0xa9bb4c92, 0x0bc5d11a), TOBN(0xf20127a7, 0x9c5f88a3), + TOBN(0x4f52b06e, 0x161d3cb8), TOBN(0x26c1ff09, 0x6afaf0a6), + TOBN(0x32670d2f, 0x7189e71f), TOBN(0xc6438748, 0x5ecf91e7), + TOBN(0x15758e57, 0xdb757a21), TOBN(0x427d09f8, 0x290a9ce5), + TOBN(0x846a308f, 0x38384a7a), TOBN(0xaac3acb4, 0xb0732b99), + TOBN(0x9e941009, 0x17845819), TOBN(0x95cba111, 0xa7ce5e03), + TOBN(0x6f3d4f7f, 0xb00009c4), TOBN(0xb8396c27, 0x8ff28b5f), + TOBN(0xb1a9ae43, 0x1c97975d), TOBN(0x9d7ba8af, 0xe5d9fed5), + TOBN(0x338cf09f, 0x34f485b6), TOBN(0xbc0ddacc, 0x64122516), + TOBN(0xa450da12, 0x05d471fe), TOBN(0x4c3a6250, 0x628dd8c9), + TOBN(0x69c7d103, 0xd1295837), TOBN(0xa2893e50, 0x3807eb2f), + TOBN(0xd6e1e1de, 0xbdb41491), TOBN(0xc630745b, 0x5e138235), + TOBN(0xc892109e, 0x48661ae1), TOBN(0x8d17e7eb, 0xea2b2674), + TOBN(0x00ec0f87, 0xc328d6b5), TOBN(0x6d858645, 0xf079ff9e), + TOBN(0x6cdf243e, 0x19115ead), TOBN(0x1ce1393e, 0x4bac4fcf), + TOBN(0x2c960ed0, 0x9c29f25b), TOBN(0x59be4d8e, 0x9d388a05), + TOBN(0x0d46e06c, 0xd0def72b), TOBN(0xb923db5d, 0xe0342748), + TOBN(0xf7d3aacd, 0x936d4a3d), TOBN(0x558519cc, 0x0b0b099e), + TOBN(0x3ea8ebf8, 0x827097ef), TOBN(0x259353db, 0xd054f55d), + TOBN(0x84c89abc, 0x6d2ed089), TOBN(0x5c548b69, 0x8e096a7c), + TOBN(0xd587f616, 0x994b995d), TOBN(0x4d1531f6, 0xa5845601), + TOBN(0x792ab31e, 0x451fd9f0), TOBN(0xc8b57bb2, 0x65adf6ca), + TOBN(0x68440fcb, 0x1cd5ad73), TOBN(0xb9c860e6, 0x6144da4f), + TOBN(0x2ab286aa, 0x8462beb8), TOBN(0xcc6b8fff, 0xef46797f), + TOBN(0xac820da4, 0x20c8a471), TOBN(0x69ae05a1, 0x77ff7faf), + TOBN(0xb9163f39, 0xbfb5da77), TOBN(0xbd03e590, 0x2c73ab7a), + TOBN(0x7e862b5e, 0xb2940d9e), TOBN(0x3c663d86, 0x4b9af564), + TOBN(0xd8309031, 0xbde3033d), TOBN(0x298231b2, 0xd42c5bc6), + TOBN(0x42090d2c, 0x552ad093), TOBN(0xa4799d1c, 0xff854695), + TOBN(0x0a88b5d6, 0xd31f0d00), TOBN(0xf8b40825, 0xa2f26b46), + TOBN(0xec29b1ed, 0xf1bd7218), TOBN(0xd491c53b, 0x4b24c86e), + TOBN(0xd2fe588f, 0x3395ea65), TOBN(0x6f3764f7, 0x4456ef15), + TOBN(0xdb43116d, 0xcdc34800), TOBN(0xcdbcd456, 0xc1e33955), + TOBN(0xefdb5540, 0x74ab286b), TOBN(0x948c7a51, 0xd18c5d7c), + TOBN(0xeb81aa37, 0x7378058e), TOBN(0x41c746a1, 0x04411154), + TOBN(0xa10c73bc, 0xfb828ac7), TOBN(0x6439be91, 0x9d972b29), + TOBN(0x4bf3b4b0, 0x43a2fbad), TOBN(0x39e6dadf, 0x82b5e840), + TOBN(0x4f716408, 0x6397bd4c), TOBN(0x0f7de568, 0x7f1eeccb), + TOBN(0x5865c5a1, 0xd2ffbfc1), TOBN(0xf74211fa, 0x4ccb6451), + TOBN(0x66368a88, 0xc0b32558), TOBN(0x5b539dc2, 0x9ad7812e), + TOBN(0x579483d0, 0x2f3af6f6), TOBN(0x52132078, 0x99934ece), + TOBN(0x50b9650f, 0xdcc9e983), TOBN(0xca989ec9, 0xaee42b8a), + TOBN(0x6a44c829, 0xd6f62f99), TOBN(0x8f06a309, 0x4c2a7c0c), + TOBN(0x4ea2b3a0, 0x98a0cb0a), TOBN(0x5c547b70, 0xbeee8364), + TOBN(0x461d40e1, 0x682afe11), TOBN(0x9e0fc77a, 0x7b41c0a8), + TOBN(0x79e4aefd, 0xe20d5d36), TOBN(0x2916e520, 0x32dd9f63), + TOBN(0xf59e52e8, 0x3f883faf), TOBN(0x396f9639, 0x2b868d35), + TOBN(0xc902a9df, 0x4ca19881), TOBN(0x0fc96822, 0xdb2401a6), + TOBN(0x41237587, 0x66f1c68d), TOBN(0x10fc6de3, 0xfb476c0d), + TOBN(0xf8b6b579, 0x841f5d90), TOBN(0x2ba8446c, 0xfa24f44a), + TOBN(0xa237b920, 0xef4a9975), TOBN(0x60bb6004, 0x2330435f), + TOBN(0xd6f4ab5a, 0xcfb7e7b5), TOBN(0xb2ac5097, 0x83435391), + TOBN(0xf036ee2f, 0xb0d1ea67), TOBN(0xae779a6a, 0x74c56230), + TOBN(0x59bff8c8, 0xab838ae6), TOBN(0xcd83ca99, 0x9b38e6f0), + TOBN(0xbb27bef5, 0xe33deed3), TOBN(0xe6356f6f, 0x001892a8), + TOBN(0xbf3be6cc, 0x7adfbd3e), TOBN(0xaecbc81c, 0x33d1ac9d), + TOBN(0xe4feb909, 0xe6e861dc), TOBN(0x90a247a4, 0x53f5f801), + TOBN(0x01c50acb, 0x27346e57), TOBN(0xce29242e, 0x461acc1b), + TOBN(0x04dd214a, 0x2f998a91), TOBN(0x271ee9b1, 0xd4baf27b), + TOBN(0x7e3027d1, 0xe8c26722), TOBN(0x21d1645c, 0x1820dce5), + TOBN(0x086f242c, 0x7501779c), TOBN(0xf0061407, 0xfa0e8009), + TOBN(0xf23ce477, 0x60187129), TOBN(0x05bbdedb, 0x0fde9bd0), + TOBN(0x682f4832, 0x25d98473), TOBN(0xf207fe85, 0x5c658427), + TOBN(0xb6fdd7ba, 0x4166ffa1), TOBN(0x0c314056, 0x9eed799d), + TOBN(0x0db8048f, 0x4107e28f), TOBN(0x74ed3871, 0x41216840), + TOBN(0x74489f8f, 0x56a3c06e), TOBN(0x1e1c005b, 0x12777134), + TOBN(0xdb332a73, 0xf37ec3c3), TOBN(0xc65259bd, 0xdd59eba0), + TOBN(0x2291709c, 0xdb4d3257), TOBN(0x9a793b25, 0xbd389390), + TOBN(0xf39fe34b, 0xe43756f0), TOBN(0x2f76bdce, 0x9afb56c9), + TOBN(0x9f37867a, 0x61208b27), TOBN(0xea1d4307, 0x089972c3), + TOBN(0x8c595330, 0x8bdf623a), TOBN(0x5f5accda, 0x8441fb7d), + TOBN(0xfafa9418, 0x32ddfd95), TOBN(0x6ad40c5a, 0x0fde9be7), + TOBN(0x43faba89, 0xaeca8709), TOBN(0xc64a7cf1, 0x2c248a9d), + TOBN(0x16620252, 0x72637a76), TOBN(0xaee1c791, 0x22b8d1bb), + TOBN(0xf0f798fd, 0x21a843b2), TOBN(0x56e4ed4d, 0x8d005cb1), + TOBN(0x355f7780, 0x1f0d8abe), TOBN(0x197b04cf, 0x34522326), + TOBN(0x41f9b31f, 0xfd42c13f), TOBN(0x5ef7feb2, 0xb40f933d), + TOBN(0x27326f42, 0x5d60bad4), TOBN(0x027ecdb2, 0x8c92cf89), + TOBN(0x04aae4d1, 0x4e3352fe), TOBN(0x08414d2f, 0x73591b90), + TOBN(0x5ed6124e, 0xb7da7d60), TOBN(0xb985b931, 0x4d13d4ec), + TOBN(0xa592d3ab, 0x96bf36f9), TOBN(0x012dbed5, 0xbbdf51df), + TOBN(0xa57963c0, 0xdf6c177d), TOBN(0x010ec869, 0x87ca29cf), + TOBN(0xba1700f6, 0xbf926dff), TOBN(0x7c9fdbd1, 0xf4bf6bc2), + TOBN(0xdc18dc8f, 0x64da11f5), TOBN(0xa6074b7a, 0xd938ae75), + TOBN(0x14270066, 0xe84f44a4), TOBN(0x99998d38, 0xd27b954e), + TOBN(0xc1be8ab2, 0xb4f38e9a), TOBN(0x8bb55bbf, 0x15c01016), + TOBN(0xf73472b4, 0x0ea2ab30), TOBN(0xd365a340, 0xf73d68dd), + TOBN(0xc01a7168, 0x19c2e1eb), TOBN(0x32f49e37, 0x34061719), + TOBN(0xb73c57f1, 0x01d8b4d6), TOBN(0x03c8423c, 0x26b47700), + TOBN(0x321d0bc8, 0xa4d8826a), TOBN(0x6004213c, 0x4bc0e638), + TOBN(0xf78c64a1, 0xc1c06681), TOBN(0x16e0a16f, 0xef018e50), + TOBN(0x31cbdf91, 0xdb42b2b3), TOBN(0xf8f4ffce, 0xe0d36f58), + TOBN(0xcdcc71cd, 0x4cc5e3e0), TOBN(0xd55c7cfa, 0xa129e3e0), + TOBN(0xccdb6ba0, 0x0fb2cbf1), TOBN(0x6aba0005, 0xc4bce3cb), + TOBN(0x501cdb30, 0xd232cfc4), TOBN(0x9ddcf12e, 0xd58a3cef), + TOBN(0x02d2cf9c, 0x87e09149), TOBN(0xdc5d7ec7, 0x2c976257), + TOBN(0x6447986e, 0x0b50d7dd), TOBN(0x88fdbaf7, 0x807f112a), + TOBN(0x58c9822a, 0xb00ae9f6), TOBN(0x6abfb950, 0x6d3d27e0), + TOBN(0xd0a74487, 0x8a429f4f), TOBN(0x0649712b, 0xdb516609), + TOBN(0xb826ba57, 0xe769b5df), TOBN(0x82335df2, 0x1fc7aaf2), + TOBN(0x2389f067, 0x5c93d995), TOBN(0x59ac367a, 0x68677be6), + TOBN(0xa77985ff, 0x21d9951b), TOBN(0x038956fb, 0x85011cce), + TOBN(0x608e48cb, 0xbb734e37), TOBN(0xc08c0bf2, 0x2be5b26f), + TOBN(0x17bbdd3b, 0xf9b1a0d9), TOBN(0xeac7d898, 0x10483319), + TOBN(0xc95c4baf, 0xbc1a6dea), TOBN(0xfdd0e2bf, 0x172aafdb), + TOBN(0x40373cbc, 0x8235c41a), TOBN(0x14303f21, 0xfb6f41d5), + TOBN(0xba063621, 0x0408f237), TOBN(0xcad3b09a, 0xecd2d1ed), + TOBN(0x4667855a, 0x52abb6a2), TOBN(0xba9157dc, 0xaa8b417b), + TOBN(0xfe7f3507, 0x4f013efb), TOBN(0x1b112c4b, 0xaa38c4a2), + TOBN(0xa1406a60, 0x9ba64345), TOBN(0xe53cba33, 0x6993c80b), + TOBN(0x45466063, 0xded40d23), TOBN(0x3d5f1f4d, 0x54908e25), + TOBN(0x9ebefe62, 0x403c3c31), TOBN(0x274ea0b5, 0x0672a624), + TOBN(0xff818d99, 0x451d1b71), TOBN(0x80e82643, 0x8f79cf79), + TOBN(0xa165df13, 0x73ce37f5), TOBN(0xa744ef4f, 0xfe3a21fd), + TOBN(0x73f1e7f5, 0xcf551396), TOBN(0xc616898e, 0x868c676b), + TOBN(0x671c28c7, 0x8c442c36), TOBN(0xcfe5e558, 0x5e0a317d), + TOBN(0x1242d818, 0x7051f476), TOBN(0x56fad2a6, 0x14f03442), + TOBN(0x262068bc, 0x0a44d0f6), TOBN(0xdfa2cd6e, 0xce6edf4e), + TOBN(0x0f43813a, 0xd15d1517), TOBN(0x61214cb2, 0x377d44f5), + TOBN(0xd399aa29, 0xc639b35f), TOBN(0x42136d71, 0x54c51c19), + TOBN(0x9774711b, 0x08417221), TOBN(0x0a5546b3, 0x52545a57), + TOBN(0x80624c41, 0x1150582d), TOBN(0x9ec5c418, 0xfbc555bc), + TOBN(0x2c87dcad, 0x771849f1), TOBN(0xb0c932c5, 0x01d7bf6f), + TOBN(0x6aa5cd3e, 0x89116eb2), TOBN(0xd378c25a, 0x51ca7bd3), + TOBN(0xc612a0da, 0x9e6e3e31), TOBN(0x0417a54d, 0xb68ad5d0), + TOBN(0x00451e4a, 0x22c6edb8), TOBN(0x9fbfe019, 0xb42827ce), + TOBN(0x2fa92505, 0xba9384a2), TOBN(0x21b8596e, 0x64ad69c1), + TOBN(0x8f4fcc49, 0x983b35a6), TOBN(0xde093760, 0x72754672), + TOBN(0x2f14ccc8, 0xf7bffe6d), TOBN(0x27566bff, 0x5d94263d), + TOBN(0xb5b4e9c6, 0x2df3ec30), TOBN(0x94f1d7d5, 0x3e6ea6ba), + TOBN(0x97b7851a, 0xaaca5e9b), TOBN(0x518aa521, 0x56713b97), + TOBN(0x3357e8c7, 0x150a61f6), TOBN(0x7842e7e2, 0xec2c2b69), + TOBN(0x8dffaf65, 0x6868a548), TOBN(0xd963bd82, 0xe068fc81), + TOBN(0x64da5c8b, 0x65917733), TOBN(0x927090ff, 0x7b247328),} + , + {TOBN(0x214bc9a7, 0xd298c241), TOBN(0xe3b697ba, 0x56807cfd), + TOBN(0xef1c7802, 0x4564eadb), TOBN(0xdde8cdcf, 0xb48149c5), + TOBN(0x946bf0a7, 0x5a4d2604), TOBN(0x27154d7f, 0x6c1538af), + TOBN(0x95cc9230, 0xde5b1fcc), TOBN(0xd88519e9, 0x66864f82), + TOBN(0xb828dd1a, 0x7cb1282c), TOBN(0xa08d7626, 0xbe46973a), + TOBN(0x6baf8d40, 0xe708d6b2), TOBN(0x72571fa1, 0x4daeb3f3), + TOBN(0x85b1732f, 0xf22dfd98), TOBN(0x87ab01a7, 0x0087108d), + TOBN(0xaaaafea8, 0x5988207a), TOBN(0xccc832f8, 0x69f00755), + TOBN(0x964d950e, 0x36ff3bf0), TOBN(0x8ad20f6f, 0xf0b34638), + TOBN(0x4d9177b3, 0xb5d7585f), TOBN(0xcf839760, 0xef3f019f), + TOBN(0x582fc5b3, 0x8288c545), TOBN(0x2f8e4e9b, 0x13116bd1), + TOBN(0xf91e1b2f, 0x332120ef), TOBN(0xcf568724, 0x2a17dd23), + TOBN(0x488f1185, 0xca8d9d1a), TOBN(0xadf2c77d, 0xd987ded2), + TOBN(0x5f3039f0, 0x60c46124), TOBN(0xe5d70b75, 0x71e095f4), + TOBN(0x82d58650, 0x6260e70f), TOBN(0x39d75ea7, 0xf750d105), + TOBN(0x8cf3d0b1, 0x75bac364), TOBN(0xf3a7564d, 0x21d01329), + TOBN(0x182f04cd, 0x2f52d2a7), TOBN(0x4fde149a, 0xe2df565a), + TOBN(0xb80c5eec, 0xa79fb2f7), TOBN(0xab491d7b, 0x22ddc897), + TOBN(0x99d76c18, 0xc6312c7f), TOBN(0xca0d5f3d, 0x6aa41a57), + TOBN(0x71207325, 0xd15363a0), TOBN(0xe82aa265, 0xbeb252c2), + TOBN(0x94ab4700, 0xec3128c2), TOBN(0x6c76d862, 0x8e383f49), + TOBN(0xdc36b150, 0xc03024eb), TOBN(0xfb439477, 0x53daac69), + TOBN(0xfc68764a, 0x8dc79623), TOBN(0x5b86995d, 0xb440fbb2), + TOBN(0xd66879bf, 0xccc5ee0d), TOBN(0x05228942, 0x95aa8bd3), + TOBN(0xb51a40a5, 0x1e6a75c1), TOBN(0x24327c76, 0x0ea7d817), + TOBN(0x06630182, 0x07774597), TOBN(0xd6fdbec3, 0x97fa7164), + TOBN(0x20c99dfb, 0x13c90f48), TOBN(0xd6ac5273, 0x686ef263), + TOBN(0xc6a50bdc, 0xfef64eeb), TOBN(0xcd87b281, 0x86fdfc32), + TOBN(0xb24aa43e, 0x3fcd3efc), TOBN(0xdd26c034, 0xb8088e9a), + TOBN(0xa5ef4dc9, 0xbd3d46ea), TOBN(0xa2f99d58, 0x8a4c6a6f), + TOBN(0xddabd355, 0x2f1da46c), TOBN(0x72c3f8ce, 0x1afacdd1), + TOBN(0xd90c4eee, 0x92d40578), TOBN(0xd28bb41f, 0xca623b94), + TOBN(0x50fc0711, 0x745edc11), TOBN(0x9dd9ad7d, 0x3dc87558), + TOBN(0xce6931fb, 0xb49d1e64), TOBN(0x6c77a0a2, 0xc98bd0f9), + TOBN(0x62b9a629, 0x6baf7cb1), TOBN(0xcf065f91, 0xccf72d22), + TOBN(0x7203cce9, 0x79639071), TOBN(0x09ae4885, 0xf9cb732f), + TOBN(0x5e7c3bec, 0xee8314f3), TOBN(0x1c068aed, 0xdbea298f), + TOBN(0x08d381f1, 0x7c80acec), TOBN(0x03b56be8, 0xe330495b), + TOBN(0xaeffb8f2, 0x9222882d), TOBN(0x95ff38f6, 0xc4af8bf7), + TOBN(0x50e32d35, 0x1fc57d8c), TOBN(0x6635be52, 0x17b444f0), + TOBN(0x04d15276, 0xa5177900), TOBN(0x4e1dbb47, 0xf6858752), + TOBN(0x5b475622, 0xc615796c), TOBN(0xa6fa0387, 0x691867bf), + TOBN(0xed7f5d56, 0x2844c6d0), TOBN(0xc633cf9b, 0x03a2477d), + TOBN(0xf6be5c40, 0x2d3721d6), TOBN(0xaf312eb7, 0xe9fd68e6), + TOBN(0x242792d2, 0xe7417ce1), TOBN(0xff42bc71, 0x970ee7f5), + TOBN(0x1ff4dc6d, 0x5c67a41e), TOBN(0x77709b7b, 0x20882a58), + TOBN(0x3554731d, 0xbe217f2c), TOBN(0x2af2a8cd, 0x5bb72177), + TOBN(0x58eee769, 0x591dd059), TOBN(0xbb2930c9, 0x4bba6477), + TOBN(0x863ee047, 0x7d930cfc), TOBN(0x4c262ad1, 0x396fd1f4), + TOBN(0xf4765bc8, 0x039af7e1), TOBN(0x2519834b, 0x5ba104f6), + TOBN(0x7cd61b4c, 0xd105f961), TOBN(0xa5415da5, 0xd63bca54), + TOBN(0x778280a0, 0x88a1f17c), TOBN(0xc4968949, 0x2329512c), + TOBN(0x174a9126, 0xcecdaa7a), TOBN(0xfc8c7e0e, 0x0b13247b), + TOBN(0x29c110d2, 0x3484c1c4), TOBN(0xf8eb8757, 0x831dfc3b), + TOBN(0x022f0212, 0xc0067452), TOBN(0x3f6f69ee, 0x7b9b926c), + TOBN(0x09032da0, 0xef42daf4), TOBN(0x79f00ade, 0x83f80de4), + TOBN(0x6210db71, 0x81236c97), TOBN(0x74f7685b, 0x3ee0781f), + TOBN(0x4df7da7b, 0xa3e41372), TOBN(0x2aae38b1, 0xb1a1553e), + TOBN(0x1688e222, 0xf6dd9d1b), TOBN(0x57695448, 0x5b8b6487), + TOBN(0x478d2127, 0x4b2edeaa), TOBN(0xb2818fa5, 0x1e85956a), + TOBN(0x1e6addda, 0xf176f2c0), TOBN(0x01ca4604, 0xe2572658), + TOBN(0x0a404ded, 0x85342ffb), TOBN(0x8cf60f96, 0x441838d6), + TOBN(0x9bbc691c, 0xc9071c4a), TOBN(0xfd588744, 0x34442803), + TOBN(0x97101c85, 0x809c0d81), TOBN(0xa7fb754c, 0x8c456f7f), + TOBN(0xc95f3c5c, 0xd51805e1), TOBN(0xab4ccd39, 0xb299dca8), + TOBN(0x3e03d20b, 0x47eaf500), TOBN(0xfa3165c1, 0xd7b80893), + TOBN(0x005e8b54, 0xe160e552), TOBN(0xdc4972ba, 0x9019d11f), + TOBN(0x21a6972e, 0x0c9a4a7a), TOBN(0xa52c258f, 0x37840fd7), + TOBN(0xf8559ff4, 0xc1e99d81), TOBN(0x08e1a7d6, 0xa3c617c0), + TOBN(0xb398fd43, 0x248c6ba7), TOBN(0x6ffedd91, 0xd1283794), + TOBN(0x8a6a59d2, 0xd629d208), TOBN(0xa9d141d5, 0x3490530e), + TOBN(0x42f6fc18, 0x38505989), TOBN(0x09bf250d, 0x479d94ee), + TOBN(0x223ad3b1, 0xb3822790), TOBN(0x6c5926c0, 0x93b8971c), + TOBN(0x609efc7e, 0x75f7fa62), TOBN(0x45d66a6d, 0x1ec2d989), + TOBN(0x4422d663, 0x987d2792), TOBN(0x4a73caad, 0x3eb31d2b), + TOBN(0xf06c2ac1, 0xa32cb9e6), TOBN(0xd9445c5f, 0x91aeba84), + TOBN(0x6af7a1d5, 0xaf71013f), TOBN(0xe68216e5, 0x0bedc946), + TOBN(0xf4cba30b, 0xd27370a0), TOBN(0x7981afbf, 0x870421cc), + TOBN(0x02496a67, 0x9449f0e1), TOBN(0x86cfc4be, 0x0a47edae), + TOBN(0x3073c936, 0xb1feca22), TOBN(0xf5694612, 0x03f8f8fb), + TOBN(0xd063b723, 0x901515ea), TOBN(0x4c6c77a5, 0x749cf038), + TOBN(0x6361e360, 0xab9e5059), TOBN(0x596cf171, 0xa76a37c0), + TOBN(0x800f53fa, 0x6530ae7a), TOBN(0x0f5e631e, 0x0792a7a6), + TOBN(0x5cc29c24, 0xefdb81c9), TOBN(0xa269e868, 0x3f9c40ba), + TOBN(0xec14f9e1, 0x2cb7191e), TOBN(0x78ea1bd8, 0xe5b08ea6), + TOBN(0x3c65aa9b, 0x46332bb9), TOBN(0x84cc22b3, 0xbf80ce25), + TOBN(0x0098e9e9, 0xd49d5bf1), TOBN(0xcd4ec1c6, 0x19087da4), + TOBN(0x3c9d07c5, 0xaef6e357), TOBN(0x839a0268, 0x9f8f64b8), + TOBN(0xc5e9eb62, 0xc6d8607f), TOBN(0x759689f5, 0x6aa995e4), + TOBN(0x70464669, 0xbbb48317), TOBN(0x921474bf, 0xe402417d), + TOBN(0xcabe135b, 0x2a354c8c), TOBN(0xd51e52d2, 0x812fa4b5), + TOBN(0xec741096, 0x53311fe8), TOBN(0x4f774535, 0xb864514b), + TOBN(0xbcadd671, 0x5bde48f8), TOBN(0xc9703873, 0x2189bc7d), + TOBN(0x5d45299e, 0xc709ee8a), TOBN(0xd1287ee2, 0x845aaff8), + TOBN(0x7d1f8874, 0xdb1dbf1f), TOBN(0xea46588b, 0x990c88d6), + TOBN(0x60ba649a, 0x84368313), TOBN(0xd5fdcbce, 0x60d543ae), + TOBN(0x90b46d43, 0x810d5ab0), TOBN(0x6739d8f9, 0x04d7e5cc), + TOBN(0x021c1a58, 0x0d337c33), TOBN(0x00a61162, 0x68e67c40), + TOBN(0x95ef413b, 0x379f0a1f), TOBN(0xfe126605, 0xe9e2ab95), + TOBN(0x67578b85, 0x2f5f199c), TOBN(0xf5c00329, 0x2cb84913), + TOBN(0xf7956430, 0x37577dd8), TOBN(0x83b82af4, 0x29c5fe88), + TOBN(0x9c1bea26, 0xcdbdc132), TOBN(0x589fa086, 0x9c04339e), + TOBN(0x033e9538, 0xb13799df), TOBN(0x85fa8b21, 0xd295d034), + TOBN(0xdf17f73f, 0xbd9ddcca), TOBN(0xf32bd122, 0xddb66334), + TOBN(0x55ef88a7, 0x858b044c), TOBN(0x1f0d69c2, 0x5aa9e397), + TOBN(0x55fd9cc3, 0x40d85559), TOBN(0xc774df72, 0x7785ddb2), + TOBN(0x5dcce9f6, 0xd3bd2e1c), TOBN(0xeb30da20, 0xa85dfed0), + TOBN(0x5ed7f5bb, 0xd3ed09c4), TOBN(0x7d42a35c, 0x82a9c1bd), + TOBN(0xcf3de995, 0x9890272d), TOBN(0x75f3432a, 0x3e713a10), + TOBN(0x5e13479f, 0xe28227b8), TOBN(0xb8561ea9, 0xfefacdc8), + TOBN(0xa6a297a0, 0x8332aafd), TOBN(0x9b0d8bb5, 0x73809b62), + TOBN(0xd2fa1cfd, 0x0c63036f), TOBN(0x7a16eb55, 0xbd64bda8), + TOBN(0x3f5cf5f6, 0x78e62ddc), TOBN(0x2267c454, 0x07fd752b), + TOBN(0x5e361b6b, 0x5e437bbe), TOBN(0x95c59501, 0x8354e075), + TOBN(0xec725f85, 0xf2b254d9), TOBN(0x844b617d, 0x2cb52b4e), + TOBN(0xed8554f5, 0xcf425fb5), TOBN(0xab67703e, 0x2af9f312), + TOBN(0x4cc34ec1, 0x3cf48283), TOBN(0xb09daa25, 0x9c8a705e), + TOBN(0xd1e9d0d0, 0x5b7d4f84), TOBN(0x4df6ef64, 0xdb38929d), + TOBN(0xe16b0763, 0xaa21ba46), TOBN(0xc6b1d178, 0xa293f8fb), + TOBN(0x0ff5b602, 0xd520aabf), TOBN(0x94d671bd, 0xc339397a), + TOBN(0x7c7d98cf, 0x4f5792fa), TOBN(0x7c5e0d67, 0x11215261), + TOBN(0x9b19a631, 0xa7c5a6d4), TOBN(0xc8511a62, 0x7a45274d), + TOBN(0x0c16621c, 0xa5a60d99), TOBN(0xf7fbab88, 0xcf5e48cb), + TOBN(0xab1e6ca2, 0xf7ddee08), TOBN(0x83bd08ce, 0xe7867f3c), + TOBN(0xf7e48e8a, 0x2ac13e27), TOBN(0x4494f6df, 0x4eb1a9f5), + TOBN(0xedbf84eb, 0x981f0a62), TOBN(0x49badc32, 0x536438f0), + TOBN(0x50bea541, 0x004f7571), TOBN(0xbac67d10, 0xdf1c94ee), + TOBN(0x253d73a1, 0xb727bc31), TOBN(0xb3d01cf2, 0x30686e28), + TOBN(0x51b77b1b, 0x55fd0b8b), TOBN(0xa099d183, 0xfeec3173), + TOBN(0x202b1fb7, 0x670e72b7), TOBN(0xadc88b33, 0xa8e1635f), + TOBN(0x34e8216a, 0xf989d905), TOBN(0xc2e68d20, 0x29b58d01), + TOBN(0x11f81c92, 0x6fe55a93), TOBN(0x15f1462a, 0x8f296f40), + TOBN(0x1915d375, 0xea3d62f2), TOBN(0xa17765a3, 0x01c8977d), + TOBN(0x7559710a, 0xe47b26f6), TOBN(0xe0bd29c8, 0x535077a5), + TOBN(0x615f976d, 0x08d84858), TOBN(0x370dfe85, 0x69ced5c1), + TOBN(0xbbc7503c, 0xa734fa56), TOBN(0xfbb9f1ec, 0x91ac4574), + TOBN(0x95d7ec53, 0x060dd7ef), TOBN(0xeef2dacd, 0x6e657979), + TOBN(0x54511af3, 0xe2a08235), TOBN(0x1e324aa4, 0x1f4aea3d), + TOBN(0x550e7e71, 0xe6e67671), TOBN(0xbccd5190, 0xbf52faf7), + TOBN(0xf880d316, 0x223cc62a), TOBN(0x0d402c7e, 0x2b32eb5d), + TOBN(0xa40bc039, 0x306a5a3b), TOBN(0x4e0a41fd, 0x96783a1b), + TOBN(0xa1e8d39a, 0x0253cdd4), TOBN(0x6480be26, 0xc7388638), + TOBN(0xee365e1d, 0x2285f382), TOBN(0x188d8d8f, 0xec0b5c36), + TOBN(0x34ef1a48, 0x1f0f4d82), TOBN(0x1a8f43e1, 0xa487d29a), + TOBN(0x8168226d, 0x77aefb3a), TOBN(0xf69a751e, 0x1e72c253), + TOBN(0x8e04359a, 0xe9594df1), TOBN(0x475ffd7d, 0xd14c0467), + TOBN(0xb5a2c2b1, 0x3844e95c), TOBN(0x85caf647, 0xdd12ef94), + TOBN(0x1ecd2a9f, 0xf1063d00), TOBN(0x1dd2e229, 0x23843311), + TOBN(0x38f0e09d, 0x73d17244), TOBN(0x3ede7746, 0x8fc653f1), + TOBN(0xae4459f5, 0xdc20e21c), TOBN(0x00db2ffa, 0x6a8599ea), + TOBN(0x11682c39, 0x30cfd905), TOBN(0x4934d074, 0xa5c112a6), + TOBN(0xbdf063c5, 0x568bfe95), TOBN(0x779a440a, 0x016c441a), + TOBN(0x0c23f218, 0x97d6fbdc), TOBN(0xd3a5cd87, 0xe0776aac), + TOBN(0xcee37f72, 0xd712e8db), TOBN(0xfb28c70d, 0x26f74e8d), + TOBN(0xffe0c728, 0xb61301a0), TOBN(0xa6282168, 0xd3724354), + TOBN(0x7ff4cb00, 0x768ffedc), TOBN(0xc51b3088, 0x03b02de9), + TOBN(0xa5a8147c, 0x3902dda5), TOBN(0x35d2f706, 0xfe6973b4), + TOBN(0x5ac2efcf, 0xc257457e), TOBN(0x933f48d4, 0x8700611b), + TOBN(0xc365af88, 0x4912beb2), TOBN(0x7f5a4de6, 0x162edf94), + TOBN(0xc646ba7c, 0x0c32f34b), TOBN(0x632c6af3, 0xb2091074), + TOBN(0x58d4f2e3, 0x753e43a9), TOBN(0x70e1d217, 0x24d4e23f), + TOBN(0xb24bf729, 0xafede6a6), TOBN(0x7f4a94d8, 0x710c8b60), + TOBN(0xaad90a96, 0x8d4faa6a), TOBN(0xd9ed0b32, 0xb066b690), + TOBN(0x52fcd37b, 0x78b6dbfd), TOBN(0x0b64615e, 0x8bd2b431), + TOBN(0x228e2048, 0xcfb9fad5), TOBN(0xbeaa386d, 0x240b76bd), + TOBN(0x2d6681c8, 0x90dad7bc), TOBN(0x3e553fc3, 0x06d38f5e), + TOBN(0xf27cdb9b, 0x9d5f9750), TOBN(0x3e85c52a, 0xd28c5b0e), + TOBN(0x190795af, 0x5247c39b), TOBN(0x547831eb, 0xbddd6828), + TOBN(0xf327a227, 0x4a82f424), TOBN(0x36919c78, 0x7e47f89d), + TOBN(0xe4783919, 0x43c7392c), TOBN(0xf101b9aa, 0x2316fefe), + TOBN(0xbcdc9e9c, 0x1c5009d2), TOBN(0xfb55ea13, 0x9cd18345), + TOBN(0xf5b5e231, 0xa3ce77c7), TOBN(0xde6b4527, 0xd2f2cb3d), + TOBN(0x10f6a333, 0x9bb26f5f), TOBN(0x1e85db8e, 0x044d85b6), + TOBN(0xc3697a08, 0x94197e54), TOBN(0x65e18cc0, 0xa7cb4ea8), + TOBN(0xa38c4f50, 0xa471fe6e), TOBN(0xf031747a, 0x2f13439c), + TOBN(0x53c4a6ba, 0xc007318b), TOBN(0xa8da3ee5, 0x1deccb3d), + TOBN(0x0555b31c, 0x558216b1), TOBN(0x90c7810c, 0x2f79e6c2), + TOBN(0x9b669f4d, 0xfe8eed3c), TOBN(0x70398ec8, 0xe0fac126), + TOBN(0xa96a449e, 0xf701b235), TOBN(0x0ceecdb3, 0xeb94f395), + TOBN(0x285fc368, 0xd0cb7431), TOBN(0x0d37bb52, 0x16a18c64), + TOBN(0x05110d38, 0xb880d2dd), TOBN(0xa60f177b, 0x65930d57), + TOBN(0x7da34a67, 0xf36235f5), TOBN(0x47f5e17c, 0x183816b9), + TOBN(0xc7664b57, 0xdb394af4), TOBN(0x39ba215d, 0x7036f789), + TOBN(0x46d2ca0e, 0x2f27b472), TOBN(0xc42647ee, 0xf73a84b7), + TOBN(0x44bc7545, 0x64488f1d), TOBN(0xaa922708, 0xf4cf85d5), + TOBN(0x721a01d5, 0x53e4df63), TOBN(0x649c0c51, 0x5db46ced), + TOBN(0x6bf0d64e, 0x3cffcb6c), TOBN(0xe3bf93fe, 0x50f71d96), + TOBN(0x75044558, 0xbcc194a0), TOBN(0x16ae3372, 0x6afdc554), + TOBN(0xbfc01adf, 0x5ca48f3f), TOBN(0x64352f06, 0xe22a9b84), + TOBN(0xcee54da1, 0xc1099e4a), TOBN(0xbbda54e8, 0xfa1b89c0), + TOBN(0x166a3df5, 0x6f6e55fb), TOBN(0x1ca44a24, 0x20176f88), + TOBN(0x936afd88, 0xdfb7b5ff), TOBN(0xe34c2437, 0x8611d4a0), + TOBN(0x7effbb75, 0x86142103), TOBN(0x6704ba1b, 0x1f34fc4d), + TOBN(0x7c2a468f, 0x10c1b122), TOBN(0x36b3a610, 0x8c6aace9), + TOBN(0xabfcc0a7, 0x75a0d050), TOBN(0x066f9197, 0x3ce33e32), + TOBN(0xce905ef4, 0x29fe09be), TOBN(0x89ee25ba, 0xa8376351), + TOBN(0x2a3ede22, 0xfd29dc76), TOBN(0x7fd32ed9, 0x36f17260), + TOBN(0x0cadcf68, 0x284b4126), TOBN(0x63422f08, 0xa7951fc8), + TOBN(0x562b24f4, 0x0807e199), TOBN(0xfe9ce5d1, 0x22ad4490), + TOBN(0xc2f51b10, 0x0db2b1b4), TOBN(0xeb3613ff, 0xe4541d0d), + TOBN(0xbd2c4a05, 0x2680813b), TOBN(0x527aa55d, 0x561b08d6), + TOBN(0xa9f8a40e, 0xa7205558), TOBN(0xe3eea56f, 0x243d0bec), + TOBN(0x7b853817, 0xa0ff58b3), TOBN(0xb67d3f65, 0x1a69e627), + TOBN(0x0b76bbb9, 0xa869b5d6), TOBN(0xa3afeb82, 0x546723ed), + TOBN(0x5f24416d, 0x3e554892), TOBN(0x8413b53d, 0x430e2a45), + TOBN(0x99c56aee, 0x9032a2a0), TOBN(0x09432bf6, 0xeec367b1), + TOBN(0x552850c6, 0xdaf0ecc1), TOBN(0x49ebce55, 0x5bc92048), + TOBN(0xdfb66ba6, 0x54811307), TOBN(0x1b84f797, 0x6f298597), + TOBN(0x79590481, 0x8d1d7a0d), TOBN(0xd9fabe03, 0x3a6fa556), + TOBN(0xa40f9c59, 0xba9e5d35), TOBN(0xcb1771c1, 0xf6247577), + TOBN(0x542a47ca, 0xe9a6312b), TOBN(0xa34b3560, 0x552dd8c5), + TOBN(0xfdf94de0, 0x0d794716), TOBN(0xd46124a9, 0x9c623094), + TOBN(0x56b7435d, 0x68afe8b4), TOBN(0x27f20540, 0x6c0d8ea1), + TOBN(0x12b77e14, 0x73186898), TOBN(0xdbc3dd46, 0x7479490f), + TOBN(0x951a9842, 0xc03b0c05), TOBN(0x8b1b3bb3, 0x7921bc96), + TOBN(0xa573b346, 0x2b202e0a), TOBN(0x77e4665d, 0x47254d56), + TOBN(0x08b70dfc, 0xd23e3984), TOBN(0xab86e8bc, 0xebd14236), + TOBN(0xaa3e07f8, 0x57114ba7), TOBN(0x5ac71689, 0xab0ef4f2), + TOBN(0x88fca384, 0x0139d9af), TOBN(0x72733f88, 0x76644af0), + TOBN(0xf122f72a, 0x65d74f4a), TOBN(0x13931577, 0xa5626c7a), + TOBN(0xd5b5d9eb, 0x70f8d5a4), TOBN(0x375adde7, 0xd7bbb228), + TOBN(0x31e88b86, 0x0c1c0b32), TOBN(0xd1f568c4, 0x173edbaa), + TOBN(0x1592fc83, 0x5459df02), TOBN(0x2beac0fb, 0x0fcd9a7e), + TOBN(0xb0a6fdb8, 0x1b473b0a), TOBN(0xe3224c6f, 0x0fe8fc48), + TOBN(0x680bd00e, 0xe87edf5b), TOBN(0x30385f02, 0x20e77cf5), + TOBN(0xe9ab98c0, 0x4d42d1b2), TOBN(0x72d191d2, 0xd3816d77), + TOBN(0x1564daca, 0x0917d9e5), TOBN(0x394eab59, 0x1f8fed7f), + TOBN(0xa209aa8d, 0x7fbb3896), TOBN(0x5564f3b9, 0xbe6ac98e), + TOBN(0xead21d05, 0xd73654ef), TOBN(0x68d1a9c4, 0x13d78d74), + TOBN(0x61e01708, 0x6d4973a0), TOBN(0x83da3500, 0x46e6d32a), + TOBN(0x6a3dfca4, 0x68ae0118), TOBN(0xa1b9a4c9, 0xd02da069), + TOBN(0x0b2ff9c7, 0xebab8302), TOBN(0x98af07c3, 0x944ba436), + TOBN(0x85997326, 0x995f0f9f), TOBN(0x467fade0, 0x71b58bc6), + TOBN(0x47e4495a, 0xbd625a2b), TOBN(0xfdd2d01d, 0x33c3b8cd), + TOBN(0x2c38ae28, 0xc693f9fa), TOBN(0x48622329, 0x348f7999), + TOBN(0x97bf738e, 0x2161f583), TOBN(0x15ee2fa7, 0x565e8cc9), + TOBN(0xa1a5c845, 0x5777e189), TOBN(0xcc10bee0, 0x456f2829), + TOBN(0x8ad95c56, 0xda762bd5), TOBN(0x152e2214, 0xe9d91da8), + TOBN(0x975b0e72, 0x7cb23c74), TOBN(0xfd5d7670, 0xa90c66df), + TOBN(0xb5b5b8ad, 0x225ffc53), TOBN(0xab6dff73, 0xfaded2ae), + TOBN(0xebd56781, 0x6f4cbe9d), TOBN(0x0ed8b249, 0x6a574bd7), + TOBN(0x41c246fe, 0x81a881fa), TOBN(0x91564805, 0xc3db9c70), + TOBN(0xd7c12b08, 0x5b862809), TOBN(0x1facd1f1, 0x55858d7b), + TOBN(0x7693747c, 0xaf09e92a), TOBN(0x3b69dcba, 0x189a425f), + TOBN(0x0be28e9f, 0x967365ef), TOBN(0x57300eb2, 0xe801f5c9), + TOBN(0x93b8ac6a, 0xd583352f), TOBN(0xa2cf1f89, 0xcd05b2b7), + TOBN(0x7c0c9b74, 0x4dcc40cc), TOBN(0xfee38c45, 0xada523fb), + TOBN(0xb49a4dec, 0x1099cc4d), TOBN(0x325c377f, 0x69f069c6), + TOBN(0xe12458ce, 0x476cc9ff), TOBN(0x580e0b6c, 0xc6d4cb63), + TOBN(0xd561c8b7, 0x9072289b), TOBN(0x0377f264, 0xa619e6da), + TOBN(0x26685362, 0x88e591a5), TOBN(0xa453a7bd, 0x7523ca2b), + TOBN(0x8a9536d2, 0xc1df4533), TOBN(0xc8e50f2f, 0xbe972f79), + TOBN(0xd433e50f, 0x6d3549cf), TOBN(0x6f33696f, 0xfacd665e), + TOBN(0x695bfdac, 0xce11fcb4), TOBN(0x810ee252, 0xaf7c9860), + TOBN(0x65450fe1, 0x7159bb2c), TOBN(0xf7dfbebe, 0x758b357b), + TOBN(0x2b057e74, 0xd69fea72), TOBN(0xd485717a, 0x92731745),} + , + {TOBN(0x896c42e8, 0xee36860c), TOBN(0xdaf04dfd, 0x4113c22d), + TOBN(0x1adbb7b7, 0x44104213), TOBN(0xe5fd5fa1, 0x1fd394ea), + TOBN(0x68235d94, 0x1a4e0551), TOBN(0x6772cfbe, 0x18d10151), + TOBN(0x276071e3, 0x09984523), TOBN(0xe4e879de, 0x5a56ba98), + TOBN(0xaaafafb0, 0x285b9491), TOBN(0x01a0be88, 0x1e4c705e), + TOBN(0xff1d4f5d, 0x2ad9caab), TOBN(0x6e349a4a, 0xc37a233f), + TOBN(0xcf1c1246, 0x4a1c6a16), TOBN(0xd99e6b66, 0x29383260), + TOBN(0xea3d4366, 0x5f6d5471), TOBN(0x36974d04, 0xff8cc89b), + TOBN(0xc26c49a1, 0xcfe89d80), TOBN(0xb42c026d, 0xda9c8371), + TOBN(0xca6c013a, 0xdad066d2), TOBN(0xfb8f7228, 0x56a4f3ee), + TOBN(0x08b579ec, 0xd850935b), TOBN(0x34c1a74c, 0xd631e1b3), + TOBN(0xcb5fe596, 0xac198534), TOBN(0x39ff21f6, 0xe1f24f25), + TOBN(0x27f29e14, 0x8f929057), TOBN(0x7a64ae06, 0xc0c853df), + TOBN(0x256cd183, 0x58e9c5ce), TOBN(0x9d9cce82, 0xded092a5), + TOBN(0xcc6e5979, 0x6e93b7c7), TOBN(0xe1e47092, 0x31bb9e27), + TOBN(0xb70b3083, 0xaa9e29a0), TOBN(0xbf181a75, 0x3785e644), + TOBN(0xf53f2c65, 0x8ead09f7), TOBN(0x1335e1d5, 0x9780d14d), + TOBN(0x69cc20e0, 0xcd1b66bc), TOBN(0x9b670a37, 0xbbe0bfc8), + TOBN(0xce53dc81, 0x28efbeed), TOBN(0x0c74e77c, 0x8326a6e5), + TOBN(0x3604e0d2, 0xb88e9a63), TOBN(0xbab38fca, 0x13dc2248), + TOBN(0x8ed6e8c8, 0x5c0a3f1e), TOBN(0xbcad2492, 0x7c87c37f), + TOBN(0xfdfb62bb, 0x9ee3b78d), TOBN(0xeba8e477, 0xcbceba46), + TOBN(0x37d38cb0, 0xeeaede4b), TOBN(0x0bc498e8, 0x7976deb6), + TOBN(0xb2944c04, 0x6b6147fb), TOBN(0x8b123f35, 0xf71f9609), + TOBN(0xa155dcc7, 0xde79dc24), TOBN(0xf1168a32, 0x558f69cd), + TOBN(0xbac21595, 0x0d1850df), TOBN(0x15c8295b, 0xb204c848), + TOBN(0xf661aa36, 0x7d8184ff), TOBN(0xc396228e, 0x30447bdb), + TOBN(0x11cd5143, 0xbde4a59e), TOBN(0xe3a26e3b, 0x6beab5e6), + TOBN(0xd3b3a13f, 0x1402b9d0), TOBN(0x573441c3, 0x2c7bc863), + TOBN(0x4b301ec4, 0x578c3e6e), TOBN(0xc26fc9c4, 0x0adaf57e), + TOBN(0x96e71bfd, 0x7493cea3), TOBN(0xd05d4b3f, 0x1af81456), + TOBN(0xdaca2a8a, 0x6a8c608f), TOBN(0x53ef07f6, 0x0725b276), + TOBN(0x07a5fbd2, 0x7824fc56), TOBN(0x34675218, 0x13289077), + TOBN(0x5bf69fd5, 0xe0c48349), TOBN(0xa613ddd3, 0xb6aa7875), + TOBN(0x7f78c19c, 0x5450d866), TOBN(0x46f4409c, 0x8f84a481), + TOBN(0x9f1d1928, 0x90fce239), TOBN(0x016c4168, 0xb2ce44b9), + TOBN(0xbae023f0, 0xc7435978), TOBN(0xb152c888, 0x20e30e19), + TOBN(0x9c241645, 0xe3fa6faf), TOBN(0x735d95c1, 0x84823e60), + TOBN(0x03197573, 0x03955317), TOBN(0x0b4b02a9, 0xf03b4995), + TOBN(0x076bf559, 0x70274600), TOBN(0x32c5cc53, 0xaaf57508), + TOBN(0xe8af6d1f, 0x60624129), TOBN(0xb7bc5d64, 0x9a5e2b5e), + TOBN(0x3814b048, 0x5f082d72), TOBN(0x76f267f2, 0xce19677a), + TOBN(0x626c630f, 0xb36eed93), TOBN(0x55230cd7, 0x3bf56803), + TOBN(0x78837949, 0xce2736a0), TOBN(0x0d792d60, 0xaa6c55f1), + TOBN(0x0318dbfd, 0xd5c7c5d2), TOBN(0xb38f8da7, 0x072b342d), + TOBN(0x3569bddc, 0x7b8de38a), TOBN(0xf25b5887, 0xa1c94842), + TOBN(0xb2d5b284, 0x2946ad60), TOBN(0x854f29ad, 0xe9d1707e), + TOBN(0xaa5159dc, 0x2c6a4509), TOBN(0x899f94c0, 0x57189837), + TOBN(0xcf6adc51, 0xf4a55b03), TOBN(0x261762de, 0x35e3b2d5), + TOBN(0x4cc43012, 0x04827b51), TOBN(0xcd22a113, 0xc6021442), + TOBN(0xce2fd61a, 0x247c9569), TOBN(0x59a50973, 0xd152beca), + TOBN(0x6c835a11, 0x63a716d4), TOBN(0xc26455ed, 0x187dedcf), + TOBN(0x27f536e0, 0x49ce89e7), TOBN(0x18908539, 0xcc890cb5), + TOBN(0x308909ab, 0xd83c2aa1), TOBN(0xecd3142b, 0x1ab73bd3), + TOBN(0x6a85bf59, 0xb3f5ab84), TOBN(0x3c320a68, 0xf2bea4c6), + TOBN(0xad8dc538, 0x6da4541f), TOBN(0xeaf34eb0, 0xb7c41186), + TOBN(0x1c780129, 0x977c97c4), TOBN(0x5ff9beeb, 0xc57eb9fa), + TOBN(0xa24d0524, 0xc822c478), TOBN(0xfd8eec2a, 0x461cd415), + TOBN(0xfbde194e, 0xf027458c), TOBN(0xb4ff5319, 0x1d1be115), + TOBN(0x63f874d9, 0x4866d6f4), TOBN(0x35c75015, 0xb21ad0c9), + TOBN(0xa6b5c9d6, 0x46ac49d2), TOBN(0x42c77c0b, 0x83137aa9), + TOBN(0x24d000fc, 0x68225a38), TOBN(0x0f63cfc8, 0x2fe1e907), + TOBN(0x22d1b01b, 0xc6441f95), TOBN(0x7d38f719, 0xec8e448f), + TOBN(0x9b33fa5f, 0x787fb1ba), TOBN(0x94dcfda1, 0x190158df), + TOBN(0xc47cb339, 0x5f6d4a09), TOBN(0x6b4f355c, 0xee52b826), + TOBN(0x3d100f5d, 0xf51b930a), TOBN(0xf4512fac, 0x9f668f69), + TOBN(0x546781d5, 0x206c4c74), TOBN(0xd021d4d4, 0xcb4d2e48), + TOBN(0x494a54c2, 0xca085c2d), TOBN(0xf1dbaca4, 0x520850a8), + TOBN(0x63c79326, 0x490a1aca), TOBN(0xcb64dd9c, 0x41526b02), + TOBN(0xbb772591, 0xa2979258), TOBN(0x3f582970, 0x48d97846), + TOBN(0xd66b70d1, 0x7c213ba7), TOBN(0xc28febb5, 0xe8a0ced4), + TOBN(0x6b911831, 0xc10338c1), TOBN(0x0d54e389, 0xbf0126f3), + TOBN(0x7048d460, 0x4af206ee), TOBN(0x786c88f6, 0x77e97cb9), + TOBN(0xd4375ae1, 0xac64802e), TOBN(0x469bcfe1, 0xd53ec11c), + TOBN(0xfc9b340d, 0x47062230), TOBN(0xe743bb57, 0xc5b4a3ac), + TOBN(0xfe00b4aa, 0x59ef45ac), TOBN(0x29a4ef23, 0x59edf188), + TOBN(0x40242efe, 0xb483689b), TOBN(0x2575d3f6, 0x513ac262), + TOBN(0xf30037c8, 0x0ca6db72), TOBN(0xc9fcce82, 0x98864be2), + TOBN(0x84a112ff, 0x0149362d), TOBN(0x95e57582, 0x1c4ae971), + TOBN(0x1fa4b1a8, 0x945cf86c), TOBN(0x4525a734, 0x0b024a2f), + TOBN(0xe76c8b62, 0x8f338360), TOBN(0x483ff593, 0x28edf32b), + TOBN(0x67e8e90a, 0x298b1aec), TOBN(0x9caab338, 0x736d9a21), + TOBN(0x5c09d2fd, 0x66892709), TOBN(0x2496b4dc, 0xb55a1d41), + TOBN(0x93f5fb1a, 0xe24a4394), TOBN(0x08c75049, 0x6fa8f6c1), + TOBN(0xcaead1c2, 0xc905d85f), TOBN(0xe9d7f790, 0x0733ae57), + TOBN(0x24c9a65c, 0xf07cdd94), TOBN(0x7389359c, 0xa4b55931), + TOBN(0xf58709b7, 0x367e45f7), TOBN(0x1f203067, 0xcb7e7adc), + TOBN(0x82444bff, 0xc7b72818), TOBN(0x07303b35, 0xbaac8033), + TOBN(0x1e1ee4e4, 0xd13b7ea1), TOBN(0xe6489b24, 0xe0e74180), + TOBN(0xa5f2c610, 0x7e70ef70), TOBN(0xa1655412, 0xbdd10894), + TOBN(0x555ebefb, 0x7af4194e), TOBN(0x533c1c3c, 0x8e89bd9c), + TOBN(0x735b9b57, 0x89895856), TOBN(0x15fb3cd2, 0x567f5c15), + TOBN(0x057fed45, 0x526f09fd), TOBN(0xe8a4f10c, 0x8128240a), + TOBN(0x9332efc4, 0xff2bfd8d), TOBN(0x214e77a0, 0xbd35aa31), + TOBN(0x32896d73, 0x14faa40e), TOBN(0x767867ec, 0x01e5f186), + TOBN(0xc9adf8f1, 0x17a1813e), TOBN(0xcb6cda78, 0x54741795), + TOBN(0xb7521b6d, 0x349d51aa), TOBN(0xf56b5a9e, 0xe3c7b8e9), + TOBN(0xc6f1e5c9, 0x32a096df), TOBN(0x083667c4, 0xa3635024), + TOBN(0x365ea135, 0x18087f2f), TOBN(0xf1b8eaac, 0xd136e45d), + TOBN(0xc8a0e484, 0x73aec989), TOBN(0xd75a324b, 0x142c9259), + TOBN(0xb7b4d001, 0x01dae185), TOBN(0x45434e0b, 0x9b7a94bc), + TOBN(0xf54339af, 0xfbd8cb0b), TOBN(0xdcc4569e, 0xe98ef49e), + TOBN(0x7789318a, 0x09a51299), TOBN(0x81b4d206, 0xb2b025d8), + TOBN(0xf64aa418, 0xfae85792), TOBN(0x3e50258f, 0xacd7baf7), + TOBN(0xdce84cdb, 0x2996864b), TOBN(0xa2e67089, 0x1f485fa4), + TOBN(0xb28b2bb6, 0x534c6a5a), TOBN(0x31a7ec6b, 0xc94b9d39), + TOBN(0x1d217766, 0xd6bc20da), TOBN(0x4acdb5ec, 0x86761190), + TOBN(0x68726328, 0x73701063), TOBN(0x4d24ee7c, 0x2128c29b), + TOBN(0xc072ebd3, 0xa19fd868), TOBN(0x612e481c, 0xdb8ddd3b), + TOBN(0xb4e1d754, 0x1a64d852), TOBN(0x00ef95ac, 0xc4c6c4ab), + TOBN(0x1536d2ed, 0xaa0a6c46), TOBN(0x61294086, 0x43774790), + TOBN(0x54af25e8, 0x343fda10), TOBN(0x9ff9d98d, 0xfd25d6f2), + TOBN(0x0746af7c, 0x468b8835), TOBN(0x977a31cb, 0x730ecea7), + TOBN(0xa5096b80, 0xc2cf4a81), TOBN(0xaa986833, 0x6458c37a), + TOBN(0x6af29bf3, 0xa6bd9d34), TOBN(0x6a62fe9b, 0x33c5d854), + TOBN(0x50e6c304, 0xb7133b5e), TOBN(0x04b60159, 0x7d6e6848), + TOBN(0x4cd296df, 0x5579bea4), TOBN(0x10e35ac8, 0x5ceedaf1), + TOBN(0x04c4c5fd, 0xe3bcc5b1), TOBN(0x95f9ee8a, 0x89412cf9), + TOBN(0x2c9459ee, 0x82b6eb0f), TOBN(0x2e845765, 0x95c2aadd), + TOBN(0x774a84ae, 0xd327fcfe), TOBN(0xd8c93722, 0x0368d476), + TOBN(0x0dbd5748, 0xf83e8a3b), TOBN(0xa579aa96, 0x8d2495f3), + TOBN(0x535996a0, 0xae496e9b), TOBN(0x07afbfe9, 0xb7f9bcc2), + TOBN(0x3ac1dc6d, 0x5b7bd293), TOBN(0x3b592cff, 0x7022323d), + TOBN(0xba0deb98, 0x9c0a3e76), TOBN(0x18e78e9f, 0x4b197acb), + TOBN(0x211cde10, 0x296c36ef), TOBN(0x7ee89672, 0x82c4da77), + TOBN(0xb617d270, 0xa57836da), TOBN(0xf0cd9c31, 0x9cb7560b), + TOBN(0x01fdcbf7, 0xe455fe90), TOBN(0x3fb53cbb, 0x7e7334f3), + TOBN(0x781e2ea4, 0x4e7de4ec), TOBN(0x8adab3ad, 0x0b384fd0), + TOBN(0x129eee2f, 0x53d64829), TOBN(0x7a471e17, 0xa261492b), + TOBN(0xe4f9adb9, 0xe4cb4a2c), TOBN(0x3d359f6f, 0x97ba2c2d), + TOBN(0x346c6786, 0x0aacd697), TOBN(0x92b444c3, 0x75c2f8a8), + TOBN(0xc79fa117, 0xd85df44e), TOBN(0x56782372, 0x398ddf31), + TOBN(0x60e690f2, 0xbbbab3b8), TOBN(0x4851f8ae, 0x8b04816b), + TOBN(0xc72046ab, 0x9c92e4d2), TOBN(0x518c74a1, 0x7cf3136b), + TOBN(0xff4eb50a, 0xf9877d4c), TOBN(0x14578d90, 0xa919cabb), + TOBN(0x8218f8c4, 0xac5eb2b6), TOBN(0xa3ccc547, 0x542016e4), + TOBN(0x025bf48e, 0x327f8349), TOBN(0xf3e97346, 0xf43cb641), + TOBN(0xdc2bafdf, 0x500f1085), TOBN(0x57167876, 0x2f063055), + TOBN(0x5bd914b9, 0x411925a6), TOBN(0x7c078d48, 0xa1123de5), + TOBN(0xee6bf835, 0x182b165d), TOBN(0xb11b5e5b, 0xba519727), + TOBN(0xe33ea76c, 0x1eea7b85), TOBN(0x2352b461, 0x92d4f85e), + TOBN(0xf101d334, 0xafe115bb), TOBN(0xfabc1294, 0x889175a3), + TOBN(0x7f6bcdc0, 0x5233f925), TOBN(0xe0a802db, 0xe77fec55), + TOBN(0xbdb47b75, 0x8069b659), TOBN(0x1c5e12de, 0xf98fbd74), + TOBN(0x869c58c6, 0x4b8457ee), TOBN(0xa5360f69, 0x4f7ea9f7), + TOBN(0xe576c09f, 0xf460b38f), TOBN(0x6b70d548, 0x22b7fb36), + TOBN(0x3fd237f1, 0x3bfae315), TOBN(0x33797852, 0xcbdff369), + TOBN(0x97df25f5, 0x25b516f9), TOBN(0x46f388f2, 0xba38ad2d), + TOBN(0x656c4658, 0x89d8ddbb), TOBN(0x8830b26e, 0x70f38ee8), + TOBN(0x4320fd5c, 0xde1212b0), TOBN(0xc34f30cf, 0xe4a2edb2), + TOBN(0xabb131a3, 0x56ab64b8), TOBN(0x7f77f0cc, 0xd99c5d26), + TOBN(0x66856a37, 0xbf981d94), TOBN(0x19e76d09, 0x738bd76e), + TOBN(0xe76c8ac3, 0x96238f39), TOBN(0xc0a482be, 0xa830b366), + TOBN(0xb7b8eaff, 0x0b4eb499), TOBN(0x8ecd83bc, 0x4bfb4865), + TOBN(0x971b2cb7, 0xa2f3776f), TOBN(0xb42176a4, 0xf4b88adf), + TOBN(0xb9617df5, 0xbe1fa446), TOBN(0x8b32d508, 0xcd031bd2), + TOBN(0x1c6bd47d, 0x53b618c0), TOBN(0xc424f46c, 0x6a227923), + TOBN(0x7303ffde, 0xdd92d964), TOBN(0xe9712878, 0x71b5abf2), + TOBN(0x8f48a632, 0xf815561d), TOBN(0x85f48ff5, 0xd3c055d1), + TOBN(0x222a1427, 0x7525684f), TOBN(0xd0d841a0, 0x67360cc3), + TOBN(0x4245a926, 0x0b9267c6), TOBN(0xc78913f1, 0xcf07f863), + TOBN(0xaa844c8e, 0x4d0d9e24), TOBN(0xa42ad522, 0x3d5f9017), + TOBN(0xbd371749, 0xa2c989d5), TOBN(0x928292df, 0xe1f5e78e), + TOBN(0x493b383e, 0x0a1ea6da), TOBN(0x5136fd8d, 0x13aee529), + TOBN(0x860c44b1, 0xf2c34a99), TOBN(0x3b00aca4, 0xbf5855ac), + TOBN(0xabf6aaa0, 0xfaaf37be), TOBN(0x65f43682, 0x2a53ec08), + TOBN(0x1d9a5801, 0xa11b12e1), TOBN(0x78a7ab2c, 0xe20ed475), + TOBN(0x0de1067e, 0x9a41e0d5), TOBN(0x30473f5f, 0x305023ea), + TOBN(0xdd3ae09d, 0x169c7d97), TOBN(0x5cd5baa4, 0xcfaef9cd), + TOBN(0x5cd7440b, 0x65a44803), TOBN(0xdc13966a, 0x47f364de), + TOBN(0x077b2be8, 0x2b8357c1), TOBN(0x0cb1b4c5, 0xe9d57c2a), + TOBN(0x7a4ceb32, 0x05ff363e), TOBN(0xf310fa4d, 0xca35a9ef), + TOBN(0xdbb7b352, 0xf97f68c6), TOBN(0x0c773b50, 0x0b02cf58), + TOBN(0xea2e4821, 0x3c1f96d9), TOBN(0xffb357b0, 0xeee01815), + TOBN(0xb9c924cd, 0xe0f28039), TOBN(0x0b36c95a, 0x46a3fbe4), + TOBN(0x1faaaea4, 0x5e46db6c), TOBN(0xcae575c3, 0x1928aaff), + TOBN(0x7f671302, 0xa70dab86), TOBN(0xfcbd12a9, 0x71c58cfc), + TOBN(0xcbef9acf, 0xbee0cb92), TOBN(0x573da0b9, 0xf8c1b583), + TOBN(0x4752fcfe, 0x0d41d550), TOBN(0xe7eec0e3, 0x2155cffe), + TOBN(0x0fc39fcb, 0x545ae248), TOBN(0x522cb8d1, 0x8065f44e), + TOBN(0x263c962a, 0x70cbb96c), TOBN(0xe034362a, 0xbcd124a9), + TOBN(0xf120db28, 0x3c2ae58d), TOBN(0xb9a38d49, 0xfef6d507), + TOBN(0xb1fd2a82, 0x1ff140fd), TOBN(0xbd162f30, 0x20aee7e0), + TOBN(0x4e17a5d4, 0xcb251949), TOBN(0x2aebcb83, 0x4f7e1c3d), + TOBN(0x608eb25f, 0x937b0527), TOBN(0xf42e1e47, 0xeb7d9997), + TOBN(0xeba699c4, 0xb8a53a29), TOBN(0x1f921c71, 0xe091b536), + TOBN(0xcce29e7b, 0x5b26bbd5), TOBN(0x7a8ef5ed, 0x3b61a680), + TOBN(0xe5ef8043, 0xba1f1c7e), TOBN(0x16ea8217, 0x18158dda), + TOBN(0x01778a2b, 0x599ff0f9), TOBN(0x68a923d7, 0x8104fc6b), + TOBN(0x5bfa44df, 0xda694ff3), TOBN(0x4f7199db, 0xf7667f12), + TOBN(0xc06d8ff6, 0xe46f2a79), TOBN(0x08b5dead, 0xe9f8131d), + TOBN(0x02519a59, 0xabb4ce7c), TOBN(0xc4f710bc, 0xb42aec3e), + TOBN(0x3d77b057, 0x78bde41a), TOBN(0x6474bf80, 0xb4186b5a), + TOBN(0x048b3f67, 0x88c65741), TOBN(0xc64519de, 0x03c7c154), + TOBN(0xdf073846, 0x0edfcc4f), TOBN(0x319aa737, 0x48f1aa6b), + TOBN(0x8b9f8a02, 0xca909f77), TOBN(0x90258139, 0x7580bfef), + TOBN(0xd8bfd3ca, 0xc0c22719), TOBN(0xc60209e4, 0xc9ca151e), + TOBN(0x7a744ab5, 0xd9a1a69c), TOBN(0x6de5048b, 0x14937f8f), + TOBN(0x171938d8, 0xe115ac04), TOBN(0x7df70940, 0x1c6b16d2), + TOBN(0xa6aeb663, 0x7f8e94e7), TOBN(0xc130388e, 0x2a2cf094), + TOBN(0x1850be84, 0x77f54e6e), TOBN(0x9f258a72, 0x65d60fe5), + TOBN(0xff7ff0c0, 0x6c9146d6), TOBN(0x039aaf90, 0xe63a830b), + TOBN(0x38f27a73, 0x9460342f), TOBN(0x4703148c, 0x3f795f8a), + TOBN(0x1bb5467b, 0x9681a97e), TOBN(0x00931ba5, 0xecaeb594), + TOBN(0xcdb6719d, 0x786f337c), TOBN(0xd9c01cd2, 0xe704397d), + TOBN(0x0f4a3f20, 0x555c2fef), TOBN(0x00452509, 0x7c0af223), + TOBN(0x54a58047, 0x84db8e76), TOBN(0x3bacf1aa, 0x93c8aa06), + TOBN(0x11ca957c, 0xf7919422), TOBN(0x50641053, 0x78cdaa40), + TOBN(0x7a303874, 0x9f7144ae), TOBN(0x170c963f, 0x43d4acfd), + TOBN(0x5e148149, 0x58ddd3ef), TOBN(0xa7bde582, 0x9e72dba8), + TOBN(0x0769da8b, 0x6fa68750), TOBN(0xfa64e532, 0x572e0249), + TOBN(0xfcaadf9d, 0x2619ad31), TOBN(0x87882daa, 0xa7b349cd), + TOBN(0x9f6eb731, 0x6c67a775), TOBN(0xcb10471a, 0xefc5d0b1), + TOBN(0xb433750c, 0xe1b806b2), TOBN(0x19c5714d, 0x57b1ae7e), + TOBN(0xc0dc8b7b, 0xed03fd3f), TOBN(0xdd03344f, 0x31bc194e), + TOBN(0xa66c52a7, 0x8c6320b5), TOBN(0x8bc82ce3, 0xd0b6fd93), + TOBN(0xf8e13501, 0xb35f1341), TOBN(0xe53156dd, 0x25a43e42), + TOBN(0xd3adf27e, 0x4daeb85c), TOBN(0xb81d8379, 0xbbeddeb5), + TOBN(0x1b0b546e, 0x2e435867), TOBN(0x9020eb94, 0xeba5dd60), + TOBN(0x37d91161, 0x8210cb9d), TOBN(0x4c596b31, 0x5c91f1cf), + TOBN(0xb228a90f, 0x0e0b040d), TOBN(0xbaf02d82, 0x45ff897f), + TOBN(0x2aac79e6, 0x00fa6122), TOBN(0x24828817, 0x8e36f557), + TOBN(0xb9521d31, 0x113ec356), TOBN(0x9e48861e, 0x15eff1f8), + TOBN(0x2aa1d412, 0xe0d41715), TOBN(0x71f86203, 0x53f131b8), + TOBN(0xf60da8da, 0x3fd19408), TOBN(0x4aa716dc, 0x278d9d99), + TOBN(0x394531f7, 0xa8c51c90), TOBN(0xb560b0e8, 0xf59db51c), + TOBN(0xa28fc992, 0xfa34bdad), TOBN(0xf024fa14, 0x9cd4f8bd), + TOBN(0x5cf530f7, 0x23a9d0d3), TOBN(0x615ca193, 0xe28c9b56), + TOBN(0x6d2a483d, 0x6f73c51e), TOBN(0xa4cb2412, 0xea0dc2dd), + TOBN(0x50663c41, 0x1eb917ff), TOBN(0x3d3a74cf, 0xeade299e), + TOBN(0x29b3990f, 0x4a7a9202), TOBN(0xa9bccf59, 0xa7b15c3d), + TOBN(0x66a3ccdc, 0xa5df9208), TOBN(0x48027c14, 0x43f2f929), + TOBN(0xd385377c, 0x40b557f0), TOBN(0xe001c366, 0xcd684660), + TOBN(0x1b18ed6b, 0xe2183a27), TOBN(0x879738d8, 0x63210329), + TOBN(0xa687c74b, 0xbda94882), TOBN(0xd1bbcc48, 0xa684b299), + TOBN(0xaf6f1112, 0x863b3724), TOBN(0x6943d1b4, 0x2c8ce9f8), + TOBN(0xe044a3bb, 0x098cafb4), TOBN(0x27ed2310, 0x60d48caf), + TOBN(0x542b5675, 0x3a31b84d), TOBN(0xcbf3dd50, 0xfcddbed7), + TOBN(0x25031f16, 0x41b1d830), TOBN(0xa7ec851d, 0xcb0c1e27), + TOBN(0xac1c8fe0, 0xb5ae75db), TOBN(0xb24c7557, 0x08c52120), + TOBN(0x57f811dc, 0x1d4636c3), TOBN(0xf8436526, 0x681a9939), + TOBN(0x1f6bc6d9, 0x9c81adb3), TOBN(0x840f8ac3, 0x5b7d80d4), + TOBN(0x731a9811, 0xf4387f1a), TOBN(0x7c501cd3, 0xb5156880), + TOBN(0xa5ca4a07, 0xdfe68867), TOBN(0xf123d8f0, 0x5fcea120), + TOBN(0x1fbb0e71, 0xd607039e), TOBN(0x2b70e215, 0xcd3a4546), + TOBN(0x32d2f01d, 0x53324091), TOBN(0xb796ff08, 0x180ab19b), + TOBN(0x32d87a86, 0x3c57c4aa), TOBN(0x2aed9caf, 0xb7c49a27), + TOBN(0x9fb35eac, 0x31630d98), TOBN(0x338e8cdf, 0x5c3e20a3), + TOBN(0x80f16182, 0x66cde8db), TOBN(0x4e159980, 0x2d72fd36), + TOBN(0xd7b8f13b, 0x9b6e5072), TOBN(0xf5213907, 0x3b7b5dc1), + TOBN(0x4d431f1d, 0x8ce4396e), TOBN(0x37a1a680, 0xa7ed2142), + TOBN(0xbf375696, 0xd01aaf6b), TOBN(0xaa1c0c54, 0xe63aab66), + TOBN(0x3014368b, 0x4ed80940), TOBN(0x67e6d056, 0x7a6fcedd), + TOBN(0x7c208c49, 0xca97579f), TOBN(0xfe3d7a81, 0xa23597f6), + TOBN(0x5e203202, 0x7e096ae2), TOBN(0xb1f3e1e7, 0x24b39366), + TOBN(0x26da26f3, 0x2fdcdffc), TOBN(0x79422f1d, 0x6097be83),} + , + {TOBN(0x263a2cfb, 0x9db3b381), TOBN(0x9c3a2dee, 0xd4df0a4b), + TOBN(0x728d06e9, 0x7d04e61f), TOBN(0x8b1adfbc, 0x42449325), + TOBN(0x6ec1d939, 0x7e053a1b), TOBN(0xee2be5c7, 0x66daf707), + TOBN(0x80ba1e14, 0x810ac7ab), TOBN(0xdd2ae778, 0xf530f174), + TOBN(0x0435d97a, 0x205b9d8b), TOBN(0x6eb8f064, 0x056756d4), + TOBN(0xd5e88a8b, 0xb6f8210e), TOBN(0x070ef12d, 0xec9fd9ea), + TOBN(0x4d849505, 0x3bcc876a), TOBN(0x12a75338, 0xa7404ce3), + TOBN(0xd22b49e1, 0xb8a1db5e), TOBN(0xec1f2051, 0x14bfa5ad), + TOBN(0xadbaeb79, 0xb6828f36), TOBN(0x9d7a0258, 0x01bd5b9e), + TOBN(0xeda01e0d, 0x1e844b0c), TOBN(0x4b625175, 0x887edfc9), + TOBN(0x14109fdd, 0x9669b621), TOBN(0x88a2ca56, 0xf6f87b98), + TOBN(0xfe2eb788, 0x170df6bc), TOBN(0x0cea06f4, 0xffa473f9), + TOBN(0x43ed81b5, 0xc4e83d33), TOBN(0xd9f35879, 0x5efd488b), + TOBN(0x164a620f, 0x9deb4d0f), TOBN(0xc6927bdb, 0xac6a7394), + TOBN(0x45c28df7, 0x9f9e0f03), TOBN(0x2868661e, 0xfcd7e1a9), + TOBN(0x7cf4e8d0, 0xffa348f1), TOBN(0x6bd4c284, 0x398538e0), + TOBN(0x2618a091, 0x289a8619), TOBN(0xef796e60, 0x6671b173), + TOBN(0x664e46e5, 0x9090c632), TOBN(0xa38062d4, 0x1e66f8fb), + TOBN(0x6c744a20, 0x0573274e), TOBN(0xd07b67e4, 0xa9271394), + TOBN(0x391223b2, 0x6bdc0e20), TOBN(0xbe2d93f1, 0xeb0a05a7), + TOBN(0xf23e2e53, 0x3f36d141), TOBN(0xe84bb3d4, 0x4dfca442), + TOBN(0xb804a48d, 0x6b7c023a), TOBN(0x1e16a8fa, 0x76431c3b), + TOBN(0x1b5452ad, 0xddd472e0), TOBN(0x7d405ee7, 0x0d1ee127), + TOBN(0x50fc6f1d, 0xffa27599), TOBN(0x351ac53c, 0xbf391b35), + TOBN(0x7efa14b8, 0x4444896b), TOBN(0x64974d2f, 0xf94027fb), + TOBN(0xefdcd0e8, 0xde84487d), TOBN(0x8c45b260, 0x2b48989b), + TOBN(0xa8fcbbc2, 0xd8463487), TOBN(0xd1b2b3f7, 0x3fbc476c), + TOBN(0x21d005b7, 0xc8f443c0), TOBN(0x518f2e67, 0x40c0139c), + TOBN(0x56036e8c, 0x06d75fc1), TOBN(0x2dcf7bb7, 0x3249a89f), + TOBN(0x81dd1d3d, 0xe245e7dd), TOBN(0xf578dc4b, 0xebd6e2a7), + TOBN(0x4c028903, 0xdf2ce7a0), TOBN(0xaee36288, 0x9c39afac), + TOBN(0xdc847c31, 0x146404ab), TOBN(0x6304c0d8, 0xa4e97818), + TOBN(0xae51dca2, 0xa91f6791), TOBN(0x2abe4190, 0x9baa9efc), + TOBN(0xd9d2e2f4, 0x559c7ac1), TOBN(0xe82f4b51, 0xfc9f773a), + TOBN(0xa7713027, 0x4073e81c), TOBN(0xc0276fac, 0xfbb596fc), + TOBN(0x1d819fc9, 0xa684f70c), TOBN(0x29b47fdd, 0xc9f7b1e0), + TOBN(0x358de103, 0x459b1940), TOBN(0xec881c59, 0x5b013e93), + TOBN(0x51574c93, 0x49532ad3), TOBN(0x2db1d445, 0xb37b46de), + TOBN(0xc6445b87, 0xdf239fd8), TOBN(0xc718af75, 0x151d24ee), + TOBN(0xaea1c4a4, 0xf43c6259), TOBN(0x40c0e5d7, 0x70be02f7), + TOBN(0x6a4590f4, 0x721b33f2), TOBN(0x2124f1fb, 0xfedf04ea), + TOBN(0xf8e53cde, 0x9745efe7), TOBN(0xe7e10432, 0x65f046d9), + TOBN(0xc3fca28e, 0xe4d0c7e6), TOBN(0x847e339a, 0x87253b1b), + TOBN(0x9b595348, 0x3743e643), TOBN(0xcb6a0a0b, 0x4fd12fc5), + TOBN(0xfb6836c3, 0x27d02dcc), TOBN(0x5ad00982, 0x7a68bcc2), + TOBN(0x1b24b44c, 0x005e912d), TOBN(0xcc83d20f, 0x811fdcfe), + TOBN(0x36527ec1, 0x666fba0c), TOBN(0x69948197, 0x14754635), + TOBN(0xfcdcb1a8, 0x556da9c2), TOBN(0xa5934267, 0x81a732b2), + TOBN(0xec1214ed, 0xa714181d), TOBN(0x609ac13b, 0x6067b341), + TOBN(0xff4b4c97, 0xa545df1f), TOBN(0xa1240501, 0x34d2076b), + TOBN(0x6efa0c23, 0x1409ca97), TOBN(0x254cc1a8, 0x20638c43), + TOBN(0xd4e363af, 0xdcfb46cd), TOBN(0x62c2adc3, 0x03942a27), + TOBN(0xc67b9df0, 0x56e46483), TOBN(0xa55abb20, 0x63736356), + TOBN(0xab93c098, 0xc551bc52), TOBN(0x382b49f9, 0xb15fe64b), + TOBN(0x9ec221ad, 0x4dff8d47), TOBN(0x79caf615, 0x437df4d6), + TOBN(0x5f13dc64, 0xbb456509), TOBN(0xe4c589d9, 0x191f0714), + TOBN(0x27b6a8ab, 0x3fd40e09), TOBN(0xe455842e, 0x77313ea9), + TOBN(0x8b51d1e2, 0x1f55988b), TOBN(0x5716dd73, 0x062bbbfc), + TOBN(0x633c11e5, 0x4e8bf3de), TOBN(0x9a0e77b6, 0x1b85be3b), + TOBN(0x56510729, 0x0911cca6), TOBN(0x27e76495, 0xefa6590f), + TOBN(0xe4ac8b33, 0x070d3aab), TOBN(0x2643672b, 0x9a2cd5e5), + TOBN(0x52eff79b, 0x1cfc9173), TOBN(0x665ca49b, 0x90a7c13f), + TOBN(0x5a8dda59, 0xb3efb998), TOBN(0x8a5b922d, 0x052f1341), + TOBN(0xae9ebbab, 0x3cf9a530), TOBN(0x35986e7b, 0xf56da4d7), + TOBN(0x3a636b5c, 0xff3513cc), TOBN(0xbb0cf8ba, 0x3198f7dd), + TOBN(0xb8d40522, 0x41f16f86), TOBN(0x760575d8, 0xde13a7bf), + TOBN(0x36f74e16, 0x9f7aa181), TOBN(0x163a3ecf, 0xf509ed1c), + TOBN(0x6aead61f, 0x3c40a491), TOBN(0x158c95fc, 0xdfe8fcaa), + TOBN(0xa3991b6e, 0x13cda46f), TOBN(0x79482415, 0x342faed0), + TOBN(0xf3ba5bde, 0x666b5970), TOBN(0x1d52e6bc, 0xb26ab6dd), + TOBN(0x768ba1e7, 0x8608dd3d), TOBN(0x4930db2a, 0xea076586), + TOBN(0xd9575714, 0xe7dc1afa), TOBN(0x1fc7bf7d, 0xf7c58817), + TOBN(0x6b47accd, 0xd9eee96c), TOBN(0x0ca277fb, 0xe58cec37), + TOBN(0x113fe413, 0xe702c42a), TOBN(0xdd1764ee, 0xc47cbe51), + TOBN(0x041e7cde, 0x7b3ed739), TOBN(0x50cb7459, 0x5ce9e1c0), + TOBN(0x35568513, 0x2925b212), TOBN(0x7cff95c4, 0x001b081c), + TOBN(0x63ee4cbd, 0x8088b454), TOBN(0xdb7f32f7, 0x9a9e0c8a), + TOBN(0xb377d418, 0x6b2447cb), TOBN(0xe3e982aa, 0xd370219b), + TOBN(0x06ccc1e4, 0xc2a2a593), TOBN(0x72c36865, 0x0773f24f), + TOBN(0xa13b4da7, 0x95859423), TOBN(0x8bbf1d33, 0x75040c8f), + TOBN(0x726f0973, 0xda50c991), TOBN(0x48afcd5b, 0x822d6ee2), + TOBN(0xe5fc718b, 0x20fd7771), TOBN(0xb9e8e77d, 0xfd0807a1), + TOBN(0x7f5e0f44, 0x99a7703d), TOBN(0x6972930e, 0x618e36f3), + TOBN(0x2b7c77b8, 0x23807bbe), TOBN(0xe5b82405, 0xcb27ff50), + TOBN(0xba8b8be3, 0xbd379062), TOBN(0xd64b7a1d, 0x2dce4a92), + TOBN(0x040a73c5, 0xb2952e37), TOBN(0x0a9e252e, 0xd438aeca), + TOBN(0xdd43956b, 0xc39d3bcb), TOBN(0x1a31ca00, 0xb32b2d63), + TOBN(0xd67133b8, 0x5c417a18), TOBN(0xd08e4790, 0x2ef442c8), + TOBN(0x98cb1ae9, 0x255c0980), TOBN(0x4bd86381, 0x2b4a739f), + TOBN(0x5a5c31e1, 0x1e4a45a1), TOBN(0x1e5d55fe, 0x9cb0db2f), + TOBN(0x74661b06, 0x8ff5cc29), TOBN(0x026b389f, 0x0eb8a4f4), + TOBN(0x536b21a4, 0x58848c24), TOBN(0x2e5bf8ec, 0x81dc72b0), + TOBN(0x03c187d0, 0xad886aac), TOBN(0x5c16878a, 0xb771b645), + TOBN(0xb07dfc6f, 0xc74045ab), TOBN(0x2c6360bf, 0x7800caed), + TOBN(0x24295bb5, 0xb9c972a3), TOBN(0xc9e6f88e, 0x7c9a6dba), + TOBN(0x90ffbf24, 0x92a79aa6), TOBN(0xde29d50a, 0x41c26ac2), + TOBN(0x9f0af483, 0xd309cbe6), TOBN(0x5b020d8a, 0xe0bced4f), + TOBN(0x606e986d, 0xb38023e3), TOBN(0xad8f2c9d, 0x1abc6933), + TOBN(0x19292e1d, 0xe7400e93), TOBN(0xfe3e18a9, 0x52be5e4d), + TOBN(0xe8e9771d, 0x2e0680bf), TOBN(0x8c5bec98, 0xc54db063), + TOBN(0x2af9662a, 0x74a55d1f), TOBN(0xe3fbf28f, 0x046f66d8), + TOBN(0xa3a72ab4, 0xd4dc4794), TOBN(0x09779f45, 0x5c7c2dd8), + TOBN(0xd893bdaf, 0xc3d19d8d), TOBN(0xd5a75094, 0x57d6a6df), + TOBN(0x8cf8fef9, 0x952e6255), TOBN(0x3da67cfb, 0xda9a8aff), + TOBN(0x4c23f62a, 0x2c160dcd), TOBN(0x34e6c5e3, 0x8f90eaef), + TOBN(0x35865519, 0xa9a65d5a), TOBN(0x07c48aae, 0x8fd38a3d), + TOBN(0xb7e7aeda, 0x50068527), TOBN(0x2c09ef23, 0x1c90936a), + TOBN(0x31ecfeb6, 0xe879324c), TOBN(0xa0871f6b, 0xfb0ec938), + TOBN(0xb1f0fb68, 0xd84d835d), TOBN(0xc90caf39, 0x861dc1e6), + TOBN(0x12e5b046, 0x7594f8d7), TOBN(0x26897ae2, 0x65012b92), + TOBN(0xbcf68a08, 0xa4d6755d), TOBN(0x403ee41c, 0x0991fbda), + TOBN(0x733e343e, 0x3bbf17e8), TOBN(0xd2c7980d, 0x679b3d65), + TOBN(0x33056232, 0xd2e11305), TOBN(0x966be492, 0xf3c07a6f), + TOBN(0x6a8878ff, 0xbb15509d), TOBN(0xff221101, 0x0a9b59a4), + TOBN(0x6c9f564a, 0xabe30129), TOBN(0xc6f2c940, 0x336e64cf), + TOBN(0x0fe75262, 0x8b0c8022), TOBN(0xbe0267e9, 0x6ae8db87), + TOBN(0x22e192f1, 0x93bc042b), TOBN(0xf085b534, 0xb237c458), + TOBN(0xa0d192bd, 0x832c4168), TOBN(0x7a76e9e3, 0xbdf6271d), + TOBN(0x52a882fa, 0xb88911b5), TOBN(0xc85345e4, 0xb4db0eb5), + TOBN(0xa3be02a6, 0x81a7c3ff), TOBN(0x51889c8c, 0xf0ec0469), + TOBN(0x9d031369, 0xa5e829e5), TOBN(0xcbb4c6fc, 0x1607aa41), + TOBN(0x75ac59a6, 0x241d84c1), TOBN(0xc043f2bf, 0x8829e0ee), + TOBN(0x82a38f75, 0x8ea5e185), TOBN(0x8bda40b9, 0xd87cbd9f), + TOBN(0x9e65e75e, 0x2d8fc601), TOBN(0x3d515f74, 0xa35690b3), + TOBN(0x534acf4f, 0xda79e5ac), TOBN(0x68b83b3a, 0x8630215f), + TOBN(0x5c748b2e, 0xd085756e), TOBN(0xb0317258, 0xe5d37cb2), + TOBN(0x6735841a, 0xc5ccc2c4), TOBN(0x7d7dc96b, 0x3d9d5069), + TOBN(0xa147e410, 0xfd1754bd), TOBN(0x65296e94, 0xd399ddd5), + TOBN(0xf6b5b2d0, 0xbc8fa5bc), TOBN(0x8a5ead67, 0x500c277b), + TOBN(0x214625e6, 0xdfa08a5d), TOBN(0x51fdfedc, 0x959cf047), + TOBN(0x6bc9430b, 0x289fca32), TOBN(0xe36ff0cf, 0x9d9bdc3f), + TOBN(0x2fe187cb, 0x58ea0ede), TOBN(0xed66af20, 0x5a900b3f), + TOBN(0x00e0968b, 0x5fa9f4d6), TOBN(0x2d4066ce, 0x37a362e7), + TOBN(0xa99a9748, 0xbd07e772), TOBN(0x710989c0, 0x06a4f1d0), + TOBN(0xd5dedf35, 0xce40cbd8), TOBN(0xab55c5f0, 0x1743293d), + TOBN(0x766f1144, 0x8aa24e2c), TOBN(0x94d874f8, 0x605fbcb4), + TOBN(0xa365f0e8, 0xa518001b), TOBN(0xee605eb6, 0x9d04ef0f), + TOBN(0x5a3915cd, 0xba8d4d25), TOBN(0x44c0e1b8, 0xb5113472), + TOBN(0xcbb024e8, 0x8b6740dc), TOBN(0x89087a53, 0xee1d4f0c), + TOBN(0xa88fa05c, 0x1fc4e372), TOBN(0x8bf395cb, 0xaf8b3af2), + TOBN(0x1e71c9a1, 0xdeb8568b), TOBN(0xa35daea0, 0x80fb3d32), + TOBN(0xe8b6f266, 0x2cf8fb81), TOBN(0x6d51afe8, 0x9490696a), + TOBN(0x81beac6e, 0x51803a19), TOBN(0xe3d24b7f, 0x86219080), + TOBN(0x727cfd9d, 0xdf6f463c), TOBN(0x8c6865ca, 0x72284ee8), + TOBN(0x32c88b7d, 0xb743f4ef), TOBN(0x3793909b, 0xe7d11dce), + TOBN(0xd398f922, 0x2ff2ebe8), TOBN(0x2c70ca44, 0xe5e49796), + TOBN(0xdf4d9929, 0xcb1131b1), TOBN(0x7826f298, 0x25888e79), + TOBN(0x4d3a112c, 0xf1d8740a), TOBN(0x00384cb6, 0x270afa8b), + TOBN(0xcb64125b, 0x3ab48095), TOBN(0x3451c256, 0x62d05106), + TOBN(0xd73d577d, 0xa4955845), TOBN(0x39570c16, 0xbf9f4433), + TOBN(0xd7dfaad3, 0xadecf263), TOBN(0xf1c3d8d1, 0xdc76e102), + TOBN(0x5e774a58, 0x54c6a836), TOBN(0xdad4b672, 0x3e92d47b), + TOBN(0xbe7e990f, 0xf0d796a0), TOBN(0x5fc62478, 0xdf0e8b02), + TOBN(0x8aae8bf4, 0x030c00ad), TOBN(0x3d2db93b, 0x9004ba0f), + TOBN(0xe48c8a79, 0xd85d5ddc), TOBN(0xe907caa7, 0x6bb07f34), + TOBN(0x58db343a, 0xa39eaed5), TOBN(0x0ea6e007, 0xadaf5724), + TOBN(0xe00df169, 0xd23233f3), TOBN(0x3e322796, 0x77cb637f), + TOBN(0x1f897c0e, 0x1da0cf6c), TOBN(0xa651f5d8, 0x31d6bbdd), + TOBN(0xdd61af19, 0x1a230c76), TOBN(0xbd527272, 0xcdaa5e4a), + TOBN(0xca753636, 0xd0abcd7e), TOBN(0x78bdd37c, 0x370bd8dc), + TOBN(0xc23916c2, 0x17cd93fe), TOBN(0x65b97a4d, 0xdadce6e2), + TOBN(0xe04ed4eb, 0x174e42f8), TOBN(0x1491ccaa, 0xbb21480a), + TOBN(0x145a8280, 0x23196332), TOBN(0x3c3862d7, 0x587b479a), + TOBN(0x9f4a88a3, 0x01dcd0ed), TOBN(0x4da2b7ef, 0x3ea12f1f), + TOBN(0xf8e7ae33, 0xb126e48e), TOBN(0x404a0b32, 0xf494e237), + TOBN(0x9beac474, 0xc55acadb), TOBN(0x4ee5cf3b, 0xcbec9fd9), + TOBN(0x336b33b9, 0x7df3c8c3), TOBN(0xbd905fe3, 0xb76808fd), + TOBN(0x8f436981, 0xaa45c16a), TOBN(0x255c5bfa, 0x3dd27b62), + TOBN(0x71965cbf, 0xc3dd9b4d), TOBN(0xce23edbf, 0xfc068a87), + TOBN(0xb78d4725, 0x745b029b), TOBN(0x74610713, 0xcefdd9bd), + TOBN(0x7116f75f, 0x1266bf52), TOBN(0x02046722, 0x18e49bb6), + TOBN(0xdf43df9f, 0x3d6f19e3), TOBN(0xef1bc7d0, 0xe685cb2f), + TOBN(0xcddb27c1, 0x7078c432), TOBN(0xe1961b9c, 0xb77fedb7), + TOBN(0x1edc2f5c, 0xc2290570), TOBN(0x2c3fefca, 0x19cbd886), + TOBN(0xcf880a36, 0xc2af389a), TOBN(0x96c610fd, 0xbda71cea), + TOBN(0xf03977a9, 0x32aa8463), TOBN(0x8eb7763f, 0x8586d90a), + TOBN(0x3f342454, 0x2a296e77), TOBN(0xc8718683, 0x42837a35), + TOBN(0x7dc71090, 0x6a09c731), TOBN(0x54778ffb, 0x51b816db), + TOBN(0x6b33bfec, 0xaf06defd), TOBN(0xfe3c105f, 0x8592b70b), + TOBN(0xf937fda4, 0x61da6114), TOBN(0x3c13e651, 0x4c266ad7), + TOBN(0xe363a829, 0x855938e8), TOBN(0x2eeb5d9e, 0x9de54b72), + TOBN(0xbeb93b0e, 0x20ccfab9), TOBN(0x3dffbb5f, 0x25e61a25), + TOBN(0x7f655e43, 0x1acc093d), TOBN(0x0cb6cc3d, 0x3964ce61), + TOBN(0x6ab283a1, 0xe5e9b460), TOBN(0x55d787c5, 0xa1c7e72d), + TOBN(0x4d2efd47, 0xdeadbf02), TOBN(0x11e80219, 0xac459068), + TOBN(0x810c7626, 0x71f311f0), TOBN(0xfa17ef8d, 0x4ab6ef53), + TOBN(0xaf47fd25, 0x93e43bff), TOBN(0x5cb5ff3f, 0x0be40632), + TOBN(0x54687106, 0x8ee61da3), TOBN(0x7764196e, 0xb08afd0f), + TOBN(0x831ab3ed, 0xf0290a8f), TOBN(0xcae81966, 0xcb47c387), + TOBN(0xaad7dece, 0x184efb4f), TOBN(0xdcfc53b3, 0x4749110e), + TOBN(0x6698f23c, 0x4cb632f9), TOBN(0xc42a1ad6, 0xb91f8067), + TOBN(0xb116a81d, 0x6284180a), TOBN(0xebedf5f8, 0xe901326f), + TOBN(0xf2274c9f, 0x97e3e044), TOBN(0x42018520, 0x11d09fc9), + TOBN(0x56a65f17, 0xd18e6e23), TOBN(0x2ea61e2a, 0x352b683c), + TOBN(0x27d291bc, 0x575eaa94), TOBN(0x9e7bc721, 0xb8ff522d), + TOBN(0x5f7268bf, 0xa7f04d6f), TOBN(0x5868c73f, 0xaba41748), + TOBN(0x9f85c2db, 0x7be0eead), TOBN(0x511e7842, 0xff719135), + TOBN(0x5a06b1e9, 0xc5ea90d7), TOBN(0x0c19e283, 0x26fab631), + TOBN(0x8af8f0cf, 0xe9206c55), TOBN(0x89389cb4, 0x3553c06a), + TOBN(0x39dbed97, 0xf65f8004), TOBN(0x0621b037, 0xc508991d), + TOBN(0x1c52e635, 0x96e78cc4), TOBN(0x5385c8b2, 0x0c06b4a8), + TOBN(0xd84ddfdb, 0xb0e87d03), TOBN(0xc49dfb66, 0x934bafad), + TOBN(0x7071e170, 0x59f70772), TOBN(0x3a073a84, 0x3a1db56b), + TOBN(0x03494903, 0x3b8af190), TOBN(0x7d882de3, 0xd32920f0), + TOBN(0x91633f0a, 0xb2cf8940), TOBN(0x72b0b178, 0x6f948f51), + TOBN(0x2d28dc30, 0x782653c8), TOBN(0x88829849, 0xdb903a05), + TOBN(0xb8095d0c, 0x6a19d2bb), TOBN(0x4b9e7f0c, 0x86f782cb), + TOBN(0x7af73988, 0x2d907064), TOBN(0xd12be0fe, 0x8b32643c), + TOBN(0x358ed23d, 0x0e165dc3), TOBN(0x3d47ce62, 0x4e2378ce), + TOBN(0x7e2bb0b9, 0xfeb8a087), TOBN(0x3246e8ae, 0xe29e10b9), + TOBN(0x459f4ec7, 0x03ce2b4d), TOBN(0xe9b4ca1b, 0xbbc077cf), + TOBN(0x2613b4f2, 0x0e9940c1), TOBN(0xfc598bb9, 0x047d1eb1), + TOBN(0x9744c62b, 0x45036099), TOBN(0xa9dee742, 0x167c65d8), + TOBN(0x0c511525, 0xdabe1943), TOBN(0xda110554, 0x93c6c624), + TOBN(0xae00a52c, 0x651a3be2), TOBN(0xcda5111d, 0x884449a6), + TOBN(0x063c06f4, 0xff33bed1), TOBN(0x73baaf9a, 0x0d3d76b4), + TOBN(0x52fb0c9d, 0x7fc63668), TOBN(0x6886c9dd, 0x0c039cde), + TOBN(0x602bd599, 0x55b22351), TOBN(0xb00cab02, 0x360c7c13), + TOBN(0x8cb616bc, 0x81b69442), TOBN(0x41486700, 0xb55c3cee), + TOBN(0x71093281, 0xf49ba278), TOBN(0xad956d9c, 0x64a50710), + TOBN(0x9561f28b, 0x638a7e81), TOBN(0x54155cdf, 0x5980ddc3), + TOBN(0xb2db4a96, 0xd26f247a), TOBN(0x9d774e4e, 0x4787d100), + TOBN(0x1a9e6e2e, 0x078637d2), TOBN(0x1c363e2d, 0x5e0ae06a), + TOBN(0x7493483e, 0xe9cfa354), TOBN(0x76843cb3, 0x7f74b98d), + TOBN(0xbaca6591, 0xd4b66947), TOBN(0xb452ce98, 0x04460a8c), + TOBN(0x6830d246, 0x43768f55), TOBN(0xf4197ed8, 0x7dff12df), + TOBN(0x6521b472, 0x400dd0f7), TOBN(0x59f5ca8f, 0x4b1e7093), + TOBN(0x6feff11b, 0x080338ae), TOBN(0x0ada31f6, 0xa29ca3c6), + TOBN(0x24794eb6, 0x94a2c215), TOBN(0xd83a43ab, 0x05a57ab4), + TOBN(0x264a543a, 0x2a6f89fe), TOBN(0x2c2a3868, 0xdd5ec7c2), + TOBN(0xd3373940, 0x8439d9b2), TOBN(0x715ea672, 0x0acd1f11), + TOBN(0x42c1d235, 0xe7e6cc19), TOBN(0x81ce6e96, 0xb990585c), + TOBN(0x04e5dfe0, 0xd809c7bd), TOBN(0xd7b2580c, 0x8f1050ab), + TOBN(0x6d91ad78, 0xd8a4176f), TOBN(0x0af556ee, 0x4e2e897c), + TOBN(0x162a8b73, 0x921de0ac), TOBN(0x52ac9c22, 0x7ea78400), + TOBN(0xee2a4eea, 0xefce2174), TOBN(0xbe61844e, 0x6d637f79), + TOBN(0x0491f1bc, 0x789a283b), TOBN(0x72d3ac3d, 0x880836f4), + TOBN(0xaa1c5ea3, 0x88e5402d), TOBN(0x1b192421, 0xd5cc473d), + TOBN(0x5c0b9998, 0x9dc84cac), TOBN(0xb0a8482d, 0x9c6e75b8), + TOBN(0x639961d0, 0x3a191ce2), TOBN(0xda3bc865, 0x6d837930), + TOBN(0xca990653, 0x056e6f8f), TOBN(0x84861c41, 0x64d133a7), + TOBN(0x8b403276, 0x746abe40), TOBN(0xb7b4d51a, 0xebf8e303), + TOBN(0x05b43211, 0x220a255d), TOBN(0xc997152c, 0x02419e6e), + TOBN(0x76ff47b6, 0x630c2fea), TOBN(0x50518677, 0x281fdade), + TOBN(0x3283b8ba, 0xcf902b0b), TOBN(0x8d4b4eb5, 0x37db303b), + TOBN(0xcc89f42d, 0x755011bc), TOBN(0xb43d74bb, 0xdd09d19b), + TOBN(0x65746bc9, 0x8adba350), TOBN(0x364eaf8c, 0xb51c1927), + TOBN(0x13c76596, 0x10ad72ec), TOBN(0x30045121, 0xf8d40c20), + TOBN(0x6d2d99b7, 0xea7b979b), TOBN(0xcd78cd74, 0xe6fb3bcd), + TOBN(0x11e45a9e, 0x86cffbfe), TOBN(0x78a61cf4, 0x637024f6), + TOBN(0xd06bc872, 0x3d502295), TOBN(0xf1376854, 0x458cb288), + TOBN(0xb9db26a1, 0x342f8586), TOBN(0xf33effcf, 0x4beee09e), + TOBN(0xd7e0c4cd, 0xb30cfb3a), TOBN(0x6d09b8c1, 0x6c9db4c8), + TOBN(0x40ba1a42, 0x07c8d9df), TOBN(0x6fd495f7, 0x1c52c66d), + TOBN(0xfb0e169f, 0x275264da), TOBN(0x80c2b746, 0xe57d8362), + TOBN(0xedd987f7, 0x49ad7222), TOBN(0xfdc229af, 0x4398ec7b),} + , + {TOBN(0xb0d1ed84, 0x52666a58), TOBN(0x4bcb6e00, 0xe6a9c3c2), + TOBN(0x3c57411c, 0x26906408), TOBN(0xcfc20755, 0x13556400), + TOBN(0xa08b1c50, 0x5294dba3), TOBN(0xa30ba286, 0x8b7dd31e), + TOBN(0xd70ba90e, 0x991eca74), TOBN(0x094e142c, 0xe762c2b9), + TOBN(0xb81d783e, 0x979f3925), TOBN(0x1efd130a, 0xaf4c89a7), + TOBN(0x525c2144, 0xfd1bf7fa), TOBN(0x4b296904, 0x1b265a9e), + TOBN(0xed8e9634, 0xb9db65b6), TOBN(0x35c82e32, 0x03599d8a), + TOBN(0xdaa7a54f, 0x403563f3), TOBN(0x9df088ad, 0x022c38ab), + TOBN(0xe5cfb066, 0xbb3fd30a), TOBN(0x429169da, 0xeff0354e), + TOBN(0x809cf852, 0x3524e36c), TOBN(0x136f4fb3, 0x0155be1d), + TOBN(0x4826af01, 0x1fbba712), TOBN(0x6ef0f0b4, 0x506ba1a1), + TOBN(0xd9928b31, 0x77aea73e), TOBN(0xe2bf6af2, 0x5eaa244e), + TOBN(0x8d084f12, 0x4237b64b), TOBN(0x688ebe99, 0xe3ecfd07), + TOBN(0x57b8a70c, 0xf6845dd8), TOBN(0x808fc59c, 0x5da4a325), + TOBN(0xa9032b2b, 0xa3585862), TOBN(0xb66825d5, 0xedf29386), + TOBN(0xb5a5a8db, 0x431ec29b), TOBN(0xbb143a98, 0x3a1e8dc8), + TOBN(0x35ee94ce, 0x12ae381b), TOBN(0x3a7f176c, 0x86ccda90), + TOBN(0xc63a657e, 0x4606eaca), TOBN(0x9ae5a380, 0x43cd04df), + TOBN(0x9bec8d15, 0xed251b46), TOBN(0x1f5d6d30, 0xcaca5e64), + TOBN(0x347b3b35, 0x9ff20f07), TOBN(0x4d65f034, 0xf7e4b286), + TOBN(0x9e93ba24, 0xf111661e), TOBN(0xedced484, 0xb105eb04), + TOBN(0x96dc9ba1, 0xf424b578), TOBN(0xbf8f66b7, 0xe83e9069), + TOBN(0x872d4df4, 0xd7ed8216), TOBN(0xbf07f377, 0x8e2cbecf), + TOBN(0x4281d899, 0x98e73754), TOBN(0xfec85fbb, 0x8aab8708), + TOBN(0x9a3c0dee, 0xa5ba5b0b), TOBN(0xe6a116ce, 0x42d05299), + TOBN(0xae9775fe, 0xe9b02d42), TOBN(0x72b05200, 0xa1545cb6), + TOBN(0xbc506f7d, 0x31a3b4ea), TOBN(0xe5893078, 0x8bbd9b32), + TOBN(0xc8bc5f37, 0xe4b12a97), TOBN(0x6b000c06, 0x4a73b671), + TOBN(0x13b5bf22, 0x765fa7d0), TOBN(0x59805bf0, 0x1d6a5370), + TOBN(0x67a5e29d, 0x4280db98), TOBN(0x4f53916f, 0x776b1ce3), + TOBN(0x714ff61f, 0x33ddf626), TOBN(0x4206238e, 0xa085d103), + TOBN(0x1c50d4b7, 0xe5809ee3), TOBN(0x999f450d, 0x85f8eb1d), + TOBN(0x658a6051, 0xe4c79e9b), TOBN(0x1394cb73, 0xc66a9fea), + TOBN(0x27f31ed5, 0xc6be7b23), TOBN(0xf4c88f36, 0x5aa6f8fe), + TOBN(0x0fb0721f, 0x4aaa499e), TOBN(0x68b3a7d5, 0xe3fb2a6b), + TOBN(0xa788097d, 0x3a92851d), TOBN(0x060e7f8a, 0xe96f4913), + TOBN(0x82eebe73, 0x1a3a93bc), TOBN(0x42bbf465, 0xa21adc1a), + TOBN(0xc10b6fa4, 0xef030efd), TOBN(0x247aa4c7, 0x87b097bb), + TOBN(0x8b8dc632, 0xf60c77da), TOBN(0x6ffbc26a, 0xc223523e), + TOBN(0xa4f6ff11, 0x344579cf), TOBN(0x5825653c, 0x980250f6), + TOBN(0xb2dd097e, 0xbc1aa2b9), TOBN(0x07889393, 0x37a0333a), + TOBN(0x1cf55e71, 0x37a0db38), TOBN(0x2648487f, 0x792c1613), + TOBN(0xdad01336, 0x3fcef261), TOBN(0x6239c81d, 0x0eabf129), + TOBN(0x8ee761de, 0x9d276be2), TOBN(0x406a7a34, 0x1eda6ad3), + TOBN(0x4bf367ba, 0x4a493b31), TOBN(0x54f20a52, 0x9bf7f026), + TOBN(0xb696e062, 0x9795914b), TOBN(0xcddab96d, 0x8bf236ac), + TOBN(0x4ff2c70a, 0xed25ea13), TOBN(0xfa1d09eb, 0x81cbbbe7), + TOBN(0x88fc8c87, 0x468544c5), TOBN(0x847a670d, 0x696b3317), + TOBN(0xf133421e, 0x64bcb626), TOBN(0xaea638c8, 0x26dee0b5), + TOBN(0xd6e7680b, 0xb310346c), TOBN(0xe06f4097, 0xd5d4ced3), + TOBN(0x09961452, 0x7512a30b), TOBN(0xf3d867fd, 0xe589a59a), + TOBN(0x2e73254f, 0x52d0c180), TOBN(0x9063d8a3, 0x333c74ac), + TOBN(0xeda6c595, 0xd314e7bc), TOBN(0x2ee7464b, 0x467899ed), + TOBN(0x1cef423c, 0x0a1ed5d3), TOBN(0x217e76ea, 0x69cc7613), + TOBN(0x27ccce1f, 0xe7cda917), TOBN(0x12d8016b, 0x8a893f16), + TOBN(0xbcd6de84, 0x9fc74f6b), TOBN(0xfa5817e2, 0xf3144e61), + TOBN(0x1f354164, 0x0821ee4c), TOBN(0x1583eab4, 0x0bc61992), + TOBN(0x7490caf6, 0x1d72879f), TOBN(0x998ad9f3, 0xf76ae7b2), + TOBN(0x1e181950, 0xa41157f7), TOBN(0xa9d7e1e6, 0xe8da3a7e), + TOBN(0x963784eb, 0x8426b95f), TOBN(0x0ee4ed6e, 0x542e2a10), + TOBN(0xb79d4cc5, 0xac751e7b), TOBN(0x93f96472, 0xfd4211bd), + TOBN(0x8c72d3d2, 0xc8de4fc6), TOBN(0x7b69cbf5, 0xdf44f064), + TOBN(0x3da90ca2, 0xf4bf94e1), TOBN(0x1a5325f8, 0xf12894e2), + TOBN(0x0a437f6c, 0x7917d60b), TOBN(0x9be70486, 0x96c9cb5d), + TOBN(0xb4d880bf, 0xe1dc5c05), TOBN(0xd738adda, 0xeebeeb57), + TOBN(0x6f0119d3, 0xdf0fe6a3), TOBN(0x5c686e55, 0x66eaaf5a), + TOBN(0x9cb10b50, 0xdfd0b7ec), TOBN(0xbdd0264b, 0x6a497c21), + TOBN(0xfc093514, 0x8c546c96), TOBN(0x58a947fa, 0x79dbf42a), + TOBN(0xc0b48d4e, 0x49ccd6d7), TOBN(0xff8fb02c, 0x88bd5580), + TOBN(0xc75235e9, 0x07d473b2), TOBN(0x4fab1ac5, 0xa2188af3), + TOBN(0x030fa3bc, 0x97576ec0), TOBN(0xe8c946e8, 0x0b7e7d2f), + TOBN(0x40a5c9cc, 0x70305600), TOBN(0x6d8260a9, 0xc8b013b4), + TOBN(0x0368304f, 0x70bba85c), TOBN(0xad090da1, 0xa4a0d311), + TOBN(0x7170e870, 0x2415eec1), TOBN(0xbfba35fe, 0x8461ea47), + TOBN(0x6279019a, 0xc1e91938), TOBN(0xa47638f3, 0x1afc415f), + TOBN(0x36c65cbb, 0xbcba0e0f), TOBN(0x02160efb, 0x034e2c48), + TOBN(0xe6c51073, 0x615cd9e4), TOBN(0x498ec047, 0xf1243c06), + TOBN(0x3e5a8809, 0xb17b3d8c), TOBN(0x5cd99e61, 0x0cc565f1), + TOBN(0x81e312df, 0x7851dafe), TOBN(0xf156f5ba, 0xa79061e2), + TOBN(0x80d62b71, 0x880c590e), TOBN(0xbec9746f, 0x0a39faa1), + TOBN(0x1d98a9c1, 0xc8ed1f7a), TOBN(0x09e43bb5, 0xa81d5ff2), + TOBN(0xd5f00f68, 0x0da0794a), TOBN(0x412050d9, 0x661aa836), + TOBN(0xa89f7c4e, 0x90747e40), TOBN(0x6dc05ebb, 0xb62a3686), + TOBN(0xdf4de847, 0x308e3353), TOBN(0x53868fbb, 0x9fb53bb9), + TOBN(0x2b09d2c3, 0xcfdcf7dd), TOBN(0x41a9fce3, 0x723fcab4), + TOBN(0x73d905f7, 0x07f57ca3), TOBN(0x080f9fb1, 0xac8e1555), + TOBN(0x7c088e84, 0x9ba7a531), TOBN(0x07d35586, 0xed9a147f), + TOBN(0x602846ab, 0xaf48c336), TOBN(0x7320fd32, 0x0ccf0e79), + TOBN(0xaa780798, 0xb18bd1ff), TOBN(0x52c2e300, 0xafdd2905), + TOBN(0xf27ea3d6, 0x434267cd), TOBN(0x8b96d16d, 0x15605b5f), + TOBN(0x7bb31049, 0x4b45706b), TOBN(0xe7f58b8e, 0x743d25f8), + TOBN(0xe9b5e45b, 0x87f30076), TOBN(0xd19448d6, 0x5d053d5a), + TOBN(0x1ecc8cb9, 0xd3210a04), TOBN(0x6bc7d463, 0xdafb5269), + TOBN(0x3e59b10a, 0x67c3489f), TOBN(0x1769788c, 0x65641e1b), + TOBN(0x8a53b82d, 0xbd6cb838), TOBN(0x7066d6e6, 0x236d5f22), + TOBN(0x03aa1c61, 0x6908536e), TOBN(0xc971da0d, 0x66ae9809), + TOBN(0x01b3a86b, 0xc49a2fac), TOBN(0x3b8420c0, 0x3092e77a), + TOBN(0x02057300, 0x7d6fb556), TOBN(0x6941b2a1, 0xbff40a87), + TOBN(0x140b6308, 0x0658ff2a), TOBN(0x87804363, 0x3424ab36), + TOBN(0x0253bd51, 0x5751e299), TOBN(0xc75bcd76, 0x449c3e3a), + TOBN(0x92eb4090, 0x7f8f875d), TOBN(0x9c9d754e, 0x56c26bbf), + TOBN(0x158cea61, 0x8110bbe7), TOBN(0x62a6b802, 0x745f91ea), + TOBN(0xa79c41aa, 0xc6e7394b), TOBN(0x445b6a83, 0xad57ef10), + TOBN(0x0c5277eb, 0x6ea6f40c), TOBN(0x319fe96b, 0x88633365), + TOBN(0x0b0fc61f, 0x385f63cb), TOBN(0x41250c84, 0x22bdd127), + TOBN(0x67d153f1, 0x09e942c2), TOBN(0x60920d08, 0xc021ad5d), + TOBN(0x229f5746, 0x724d81a5), TOBN(0xb7ffb892, 0x5bba3299), + TOBN(0x518c51a1, 0xde413032), TOBN(0x2a9bfe77, 0x3c2fd94c), + TOBN(0xcbcde239, 0x3191f4fd), TOBN(0x43093e16, 0xd3d6ada1), + TOBN(0x184579f3, 0x58769606), TOBN(0x2c94a8b3, 0xd236625c), + TOBN(0x6922b9c0, 0x5c437d8e), TOBN(0x3d4ae423, 0xd8d9f3c8), + TOBN(0xf72c31c1, 0x2e7090a2), TOBN(0x4ac3f5f3, 0xd76a55bd), + TOBN(0x342508fc, 0x6b6af991), TOBN(0x0d527100, 0x1b5cebbd), + TOBN(0xb84740d0, 0xdd440dd7), TOBN(0x748ef841, 0x780162fd), + TOBN(0xa8dbfe0e, 0xdfc6fafb), TOBN(0xeadfdf05, 0xf7300f27), + TOBN(0x7d06555f, 0xfeba4ec9), TOBN(0x12c56f83, 0x9e25fa97), + TOBN(0x77f84203, 0xd39b8c34), TOBN(0xed8b1be6, 0x3125eddb), + TOBN(0x5bbf2441, 0xf6e39dc5), TOBN(0xb00f6ee6, 0x6a5d678a), + TOBN(0xba456ecf, 0x57d0ea99), TOBN(0xdcae0f58, 0x17e06c43), + TOBN(0x01643de4, 0x0f5b4baa), TOBN(0x2c324341, 0xd161b9be), + TOBN(0x80177f55, 0xe126d468), TOBN(0xed325f1f, 0x76748e09), + TOBN(0x6116004a, 0xcfa9bdc2), TOBN(0x2d8607e6, 0x3a9fb468), + TOBN(0x0e573e27, 0x6009d660), TOBN(0x3a525d2e, 0x8d10c5a1), + TOBN(0xd26cb45c, 0x3b9009a0), TOBN(0xb6b0cdc0, 0xde9d7448), + TOBN(0x949c9976, 0xe1337c26), TOBN(0x6faadebd, 0xd73d68e5), + TOBN(0x9e158614, 0xf1b768d9), TOBN(0x22dfa557, 0x9cc4f069), + TOBN(0xccd6da17, 0xbe93c6d6), TOBN(0x24866c61, 0xa504f5b9), + TOBN(0x2121353c, 0x8d694da1), TOBN(0x1c6ca580, 0x0140b8c6), + TOBN(0xc245ad8c, 0xe964021e), TOBN(0xb83bffba, 0x032b82b3), + TOBN(0xfaa220c6, 0x47ef9898), TOBN(0x7e8d3ac6, 0x982c948a), + TOBN(0x1faa2091, 0xbc2d124a), TOBN(0xbd54c3dd, 0x05b15ff4), + TOBN(0x386bf3ab, 0xc87c6fb7), TOBN(0xfb2b0563, 0xfdeb6f66), + TOBN(0x4e77c557, 0x5b45afb4), TOBN(0xe9ded649, 0xefb8912d), + TOBN(0x7ec9bbf5, 0x42f6e557), TOBN(0x2570dfff, 0x62671f00), + TOBN(0x2b3bfb78, 0x88e084bd), TOBN(0xa024b238, 0xf37fe5b4), + TOBN(0x44e7dc04, 0x95649aee), TOBN(0x498ca255, 0x5e7ec1d8), + TOBN(0x3bc766ea, 0xaaa07e86), TOBN(0x0db6facb, 0xf3608586), + TOBN(0xbadd2549, 0xbdc259c8), TOBN(0x95af3c6e, 0x041c649f), + TOBN(0xb36a928c, 0x02e30afb), TOBN(0x9b5356ad, 0x008a88b8), + TOBN(0x4b67a5f1, 0xcf1d9e9d), TOBN(0xc6542e47, 0xa5d8d8ce), + TOBN(0x73061fe8, 0x7adfb6cc), TOBN(0xcc826fd3, 0x98678141), + TOBN(0x00e758b1, 0x3c80515a), TOBN(0x6afe3247, 0x41485083), + TOBN(0x0fcb08b9, 0xb6ae8a75), TOBN(0xb8cf388d, 0x4acf51e1), + TOBN(0x344a5560, 0x6961b9d6), TOBN(0x1a6778b8, 0x6a97fd0c), + TOBN(0xd840fdc1, 0xecc4c7e3), TOBN(0xde9fe47d, 0x16db68cc), + TOBN(0xe95f89de, 0xa3e216aa), TOBN(0x84f1a6a4, 0x9594a8be), + TOBN(0x7ddc7d72, 0x5a7b162b), TOBN(0xc5cfda19, 0xadc817a3), + TOBN(0x80a5d350, 0x78b58d46), TOBN(0x93365b13, 0x82978f19), + TOBN(0x2e44d225, 0x26a1fc90), TOBN(0x0d6d10d2, 0x4d70705d), + TOBN(0xd94b6b10, 0xd70c45f4), TOBN(0x0f201022, 0xb216c079), + TOBN(0xcec966c5, 0x658fde41), TOBN(0xa8d2bc7d, 0x7e27601d), + TOBN(0xbfcce3e1, 0xff230be7), TOBN(0x3394ff6b, 0x0033ffb5), + TOBN(0xd890c509, 0x8132c9af), TOBN(0xaac4b0eb, 0x361e7868), + TOBN(0x5194ded3, 0xe82d15aa), TOBN(0x4550bd2e, 0x23ae6b7d), + TOBN(0x3fda318e, 0xea5399d4), TOBN(0xd989bffa, 0x91638b80), + TOBN(0x5ea124d0, 0xa14aa12d), TOBN(0x1fb1b899, 0x3667b944), + TOBN(0x95ec7969, 0x44c44d6a), TOBN(0x91df144a, 0x57e86137), + TOBN(0x915fd620, 0x73adac44), TOBN(0x8f01732d, 0x59a83801), + TOBN(0xec579d25, 0x3aa0a633), TOBN(0x06de5e7c, 0xc9d6d59c), + TOBN(0xc132f958, 0xb1ef8010), TOBN(0x29476f96, 0xe65c1a02), + TOBN(0x336a77c0, 0xd34c3565), TOBN(0xef1105b2, 0x1b9f1e9e), + TOBN(0x63e6d08b, 0xf9e08002), TOBN(0x9aff2f21, 0xc613809e), + TOBN(0xb5754f85, 0x3a80e75d), TOBN(0xde71853e, 0x6bbda681), + TOBN(0x86f041df, 0x8197fd7a), TOBN(0x8b332e08, 0x127817fa), + TOBN(0x05d99be8, 0xb9c20cda), TOBN(0x89f7aad5, 0xd5cd0c98), + TOBN(0x7ef936fe, 0x5bb94183), TOBN(0x92ca0753, 0xb05cd7f2), + TOBN(0x9d65db11, 0x74a1e035), TOBN(0x02628cc8, 0x13eaea92), + TOBN(0xf2d9e242, 0x49e4fbf2), TOBN(0x94fdfd9b, 0xe384f8b7), + TOBN(0x65f56054, 0x63428c6b), TOBN(0x2f7205b2, 0x90b409a5), + TOBN(0xf778bb78, 0xff45ae11), TOBN(0xa13045be, 0xc5ee53b2), + TOBN(0xe00a14ff, 0x03ef77fe), TOBN(0x689cd59f, 0xffef8bef), + TOBN(0x3578f0ed, 0x1e9ade22), TOBN(0xe99f3ec0, 0x6268b6a8), + TOBN(0xa2057d91, 0xea1b3c3e), TOBN(0x2d1a7053, 0xb8823a4a), + TOBN(0xabbb336a, 0x2cca451e), TOBN(0xcd2466e3, 0x2218bb5d), + TOBN(0x3ac1f42f, 0xc8cb762d), TOBN(0x7e312aae, 0x7690211f), + TOBN(0xebb9bd73, 0x45d07450), TOBN(0x207c4b82, 0x46c2213f), + TOBN(0x99d425c1, 0x375913ec), TOBN(0x94e45e96, 0x67908220), + TOBN(0xc08f3087, 0xcd67dbf6), TOBN(0xa5670fbe, 0xc0887056), + TOBN(0x6717b64a, 0x66f5b8fc), TOBN(0xd5a56aea, 0x786fec28), + TOBN(0xa8c3f55f, 0xc0ff4952), TOBN(0xa77fefae, 0x457ac49b), + TOBN(0x29882d7c, 0x98379d44), TOBN(0xd000bdfb, 0x509edc8a), + TOBN(0xc6f95979, 0xe66fe464), TOBN(0x504a6115, 0xfa61bde0), + TOBN(0x56b3b871, 0xeffea31a), TOBN(0x2d3de26d, 0xf0c21a54), + TOBN(0x21dbff31, 0x834753bf), TOBN(0xe67ecf49, 0x69269d86), + TOBN(0x7a176952, 0x151fe690), TOBN(0x03515804, 0x7f2adb5f), + TOBN(0xee794b15, 0xd1b62a8d), TOBN(0xf004ceec, 0xaae454e6), + TOBN(0x0897ea7c, 0xf0386fac), TOBN(0x3b62ff12, 0xd1fca751), + TOBN(0x154181df, 0x1b7a04ec), TOBN(0x2008e04a, 0xfb5847ec), + TOBN(0xd147148e, 0x41dbd772), TOBN(0x2b419f73, 0x22942654), + TOBN(0x669f30d3, 0xe9c544f7), TOBN(0x52a2c223, 0xc8540149), + TOBN(0x5da9ee14, 0x634dfb02), TOBN(0x5f074ff0, 0xf47869f3), + TOBN(0x74ee878d, 0xa3933acc), TOBN(0xe6510651, 0x4fe35ed1), + TOBN(0xb3eb9482, 0xf1012e7a), TOBN(0x51013cc0, 0xa8a566ae), + TOBN(0xdd5e9243, 0x47c00d3b), TOBN(0x7fde089d, 0x946bb0e5), + TOBN(0x030754fe, 0xc731b4b3), TOBN(0x12a136a4, 0x99fda062), + TOBN(0x7c1064b8, 0x5a1a35bc), TOBN(0xbf1f5763, 0x446c84ef), + TOBN(0xed29a56d, 0xa16d4b34), TOBN(0x7fba9d09, 0xdca21c4f), + TOBN(0x66d7ac00, 0x6d8de486), TOBN(0x60061987, 0x73a2a5e1), + TOBN(0x8b400f86, 0x9da28ff0), TOBN(0x3133f708, 0x43c4599c), + TOBN(0x9911c9b8, 0xee28cb0d), TOBN(0xcd7e2874, 0x8e0af61d), + TOBN(0x5a85f0f2, 0x72ed91fc), TOBN(0x85214f31, 0x9cd4a373), + TOBN(0x881fe5be, 0x1925253c), TOBN(0xd8dc98e0, 0x91e8bc76), + TOBN(0x7120affe, 0x585cc3a2), TOBN(0x724952ed, 0x735bf97a), + TOBN(0x5581e7dc, 0x3eb34581), TOBN(0x5cbff4f2, 0xe52ee57d), + TOBN(0x8d320a0e, 0x87d8cc7b), TOBN(0x9beaa7f3, 0xf1d280d0), + TOBN(0x7a0b9571, 0x9beec704), TOBN(0x9126332e, 0x5b7f0057), + TOBN(0x01fbc1b4, 0x8ed3bd6d), TOBN(0x35bb2c12, 0xd945eb24), + TOBN(0x6404694e, 0x9a8ae255), TOBN(0xb6092eec, 0x8d6abfb3), + TOBN(0x4d76143f, 0xcc058865), TOBN(0x7b0a5af2, 0x6e249922), + TOBN(0x8aef9440, 0x6a50d353), TOBN(0xe11e4bcc, 0x64f0e07a), + TOBN(0x4472993a, 0xa14a90fa), TOBN(0x7706e20c, 0xba0c51d4), + TOBN(0xf403292f, 0x1532672d), TOBN(0x52573bfa, 0x21829382), + TOBN(0x6a7bb6a9, 0x3b5bdb83), TOBN(0x08da65c0, 0xa4a72318), + TOBN(0xc58d22aa, 0x63eb065f), TOBN(0x1717596c, 0x1b15d685), + TOBN(0x112df0d0, 0xb266d88b), TOBN(0xf688ae97, 0x5941945a), + TOBN(0x487386e3, 0x7c292cac), TOBN(0x42f3b50d, 0x57d6985c), + TOBN(0x6da4f998, 0x6a90fc34), TOBN(0xc8f257d3, 0x65ca8a8d), + TOBN(0xc2feabca, 0x6951f762), TOBN(0xe1bc81d0, 0x74c323ac), + TOBN(0x1bc68f67, 0x251a2a12), TOBN(0x10d86587, 0xbe8a70dc), + TOBN(0xd648af7f, 0xf0f84d2e), TOBN(0xf0aa9ebc, 0x6a43ac92), + TOBN(0x69e3be04, 0x27596893), TOBN(0xb6bb02a6, 0x45bf452b), + TOBN(0x0875c11a, 0xf4c698c8), TOBN(0x6652b5c7, 0xbece3794), + TOBN(0x7b3755fd, 0x4f5c0499), TOBN(0x6ea16558, 0xb5532b38), + TOBN(0xd1c69889, 0xa2e96ef7), TOBN(0x9c773c3a, 0x61ed8f48), + TOBN(0x2b653a40, 0x9b323abc), TOBN(0xe26605e1, 0xf0e1d791), + TOBN(0x45d41064, 0x4a87157a), TOBN(0x8f9a78b7, 0xcbbce616), + TOBN(0xcf1e44aa, 0xc407eddd), TOBN(0x81ddd1d8, 0xa35b964f), + TOBN(0x473e339e, 0xfd083999), TOBN(0x6c94bdde, 0x8e796802), + TOBN(0x5a304ada, 0x8545d185), TOBN(0x82ae44ea, 0x738bb8cb), + TOBN(0x628a35e3, 0xdf87e10e), TOBN(0xd3624f3d, 0xa15b9fe3), + TOBN(0xcc44209b, 0x14be4254), TOBN(0x7d0efcbc, 0xbdbc2ea5), + TOBN(0x1f603362, 0x04c37bbe), TOBN(0x21f363f5, 0x56a5852c), + TOBN(0xa1503d1c, 0xa8501550), TOBN(0x2251e0e1, 0xd8ab10bb), + TOBN(0xde129c96, 0x6961c51c), TOBN(0x1f7246a4, 0x81910f68), + TOBN(0x2eb744ee, 0x5f2591f2), TOBN(0x3c47d33f, 0x5e627157), + TOBN(0x4d6d62c9, 0x22f3bd68), TOBN(0x6120a64b, 0xcb8df856), + TOBN(0x3a9ac6c0, 0x7b5d07df), TOBN(0xa92b9558, 0x7ef39783), + TOBN(0xe128a134, 0xab3a9b4f), TOBN(0x41c18807, 0xb1252f05), + TOBN(0xfc7ed089, 0x80ba9b1c), TOBN(0xac8dc6de, 0xc532a9dd), + TOBN(0xbf829cef, 0x55246809), TOBN(0x101b784f, 0x5b4ee80f), + TOBN(0xc09945bb, 0xb6f11603), TOBN(0x57b09dbe, 0x41d2801e), + TOBN(0xfba5202f, 0xa97534a8), TOBN(0x7fd8ae5f, 0xc17b9614), + TOBN(0xa50ba666, 0x78308435), TOBN(0x9572f77c, 0xd3868c4d), + TOBN(0x0cef7bfd, 0x2dd7aab0), TOBN(0xe7958e08, 0x2c7c79ff), + TOBN(0x81262e42, 0x25346689), TOBN(0x716da290, 0xb07c7004), + TOBN(0x35f911ea, 0xb7950ee3), TOBN(0x6fd72969, 0x261d21b5), + TOBN(0x52389803, 0x08b640d3), TOBN(0x5b0026ee, 0x887f12a1), + TOBN(0x20e21660, 0x742e9311), TOBN(0x0ef6d541, 0x5ff77ff7), + TOBN(0x969127f0, 0xf9c41135), TOBN(0xf21d60c9, 0x68a64993), + TOBN(0x656e5d0c, 0xe541875c), TOBN(0xf1e0f84e, 0xa1d3c233), + TOBN(0x9bcca359, 0x06002d60), TOBN(0xbe2da60c, 0x06191552), + TOBN(0x5da8bbae, 0x61181ec3), TOBN(0x9f04b823, 0x65806f19), + TOBN(0xf1604a7d, 0xd4b79bb8), TOBN(0xaee806fb, 0x52c878c8), + TOBN(0x34144f11, 0x8d47b8e8), TOBN(0x72edf52b, 0x949f9054), + TOBN(0xebfca84e, 0x2127015a), TOBN(0x9051d0c0, 0x9cb7cef3), + TOBN(0x86e8fe58, 0x296deec8), TOBN(0x33b28188, 0x41010d74),} + , + {TOBN(0x01079383, 0x171b445f), TOBN(0x9bcf21e3, 0x8131ad4c), + TOBN(0x8cdfe205, 0xc93987e8), TOBN(0xe63f4152, 0xc92e8c8f), + TOBN(0x729462a9, 0x30add43d), TOBN(0x62ebb143, 0xc980f05a), + TOBN(0x4f3954e5, 0x3b06e968), TOBN(0xfe1d75ad, 0x242cf6b1), + TOBN(0x5f95c6c7, 0xaf8685c8), TOBN(0xd4c1c8ce, 0x2f8f01aa), + TOBN(0xc44bbe32, 0x2574692a), TOBN(0xb8003478, 0xd4a4a068), + TOBN(0x7c8fc6e5, 0x2eca3cdb), TOBN(0xea1db16b, 0xec04d399), + TOBN(0xb05bc82e, 0x8f2bc5cf), TOBN(0x763d517f, 0xf44793d2), + TOBN(0x4451c1b8, 0x08bd98d0), TOBN(0x644b1cd4, 0x6575f240), + TOBN(0x6907eb33, 0x7375d270), TOBN(0x56c8bebd, 0xfa2286bd), + TOBN(0xc713d2ac, 0xc4632b46), TOBN(0x17da427a, 0xafd60242), + TOBN(0x313065b7, 0xc95c7546), TOBN(0xf8239898, 0xbf17a3de), + TOBN(0xf3b7963f, 0x4c830320), TOBN(0x842c7aa0, 0x903203e3), + TOBN(0xaf22ca0a, 0xe7327afb), TOBN(0x38e13092, 0x967609b6), + TOBN(0x73b8fb62, 0x757558f1), TOBN(0x3cc3e831, 0xf7eca8c1), + TOBN(0xe4174474, 0xf6331627), TOBN(0xa77989ca, 0xc3c40234), + TOBN(0xe5fd17a1, 0x44a081e0), TOBN(0xd797fb7d, 0xb70e296a), + TOBN(0x2b472b30, 0x481f719c), TOBN(0x0e632a98, 0xfe6f8c52), + TOBN(0x89ccd116, 0xc5f0c284), TOBN(0xf51088af, 0x2d987c62), + TOBN(0x2a2bccda, 0x4c2de6cf), TOBN(0x810f9efe, 0xf679f0f9), + TOBN(0xb0f394b9, 0x7ffe4b3e), TOBN(0x0b691d21, 0xe5fa5d21), + TOBN(0xb0bd7747, 0x9dfbbc75), TOBN(0xd2830fda, 0xfaf78b00), + TOBN(0xf78c249c, 0x52434f57), TOBN(0x4b1f7545, 0x98096dab), + TOBN(0x73bf6f94, 0x8ff8c0b3), TOBN(0x34aef03d, 0x454e134c), + TOBN(0xf8d151f4, 0xb7ac7ec5), TOBN(0xd6ceb95a, 0xe50da7d5), + TOBN(0xa1b492b0, 0xdc3a0eb8), TOBN(0x75157b69, 0xb3dd2863), + TOBN(0xe2c4c74e, 0xc5413d62), TOBN(0xbe329ff7, 0xbc5fc4c7), + TOBN(0x835a2aea, 0x60fa9dda), TOBN(0xf117f5ad, 0x7445cb87), + TOBN(0xae8317f4, 0xb0166f7a), TOBN(0xfbd3e3f7, 0xceec74e6), + TOBN(0xfdb516ac, 0xe0874bfd), TOBN(0x3d846019, 0xc681f3a3), + TOBN(0x0b12ee5c, 0x7c1620b0), TOBN(0xba68b4dd, 0x2b63c501), + TOBN(0xac03cd32, 0x6668c51e), TOBN(0x2a6279f7, 0x4e0bcb5b), + TOBN(0x17bd69b0, 0x6ae85c10), TOBN(0x72946979, 0x1dfdd3a6), + TOBN(0xd9a03268, 0x2c078bec), TOBN(0x41c6a658, 0xbfd68a52), + TOBN(0xcdea1024, 0x0e023900), TOBN(0xbaeec121, 0xb10d144d), + TOBN(0x5a600e74, 0x058ab8dc), TOBN(0x1333af21, 0xbb89ccdd), + TOBN(0xdf25eae0, 0x3aaba1f1), TOBN(0x2cada16e, 0x3b7144cf), + TOBN(0x657ee27d, 0x71ab98bc), TOBN(0x99088b4c, 0x7a6fc96e), + TOBN(0x05d5c0a0, 0x3549dbd4), TOBN(0x42cbdf8f, 0xf158c3ac), + TOBN(0x3fb6b3b0, 0x87edd685), TOBN(0x22071cf6, 0x86f064d0), + TOBN(0xd2d6721f, 0xff2811e5), TOBN(0xdb81b703, 0xfe7fae8c), + TOBN(0x3cfb74ef, 0xd3f1f7bb), TOBN(0x0cdbcd76, 0x16cdeb5d), + TOBN(0x4f39642a, 0x566a808c), TOBN(0x02b74454, 0x340064d6), + TOBN(0xfabbadca, 0x0528fa6f), TOBN(0xe4c3074c, 0xd3fc0bb6), + TOBN(0xb32cb8b0, 0xb796d219), TOBN(0xc3e95f4f, 0x34741dd9), + TOBN(0x87212125, 0x68edf6f5), TOBN(0x7a03aee4, 0xa2b9cb8e), + TOBN(0x0cd3c376, 0xf53a89aa), TOBN(0x0d8af9b1, 0x948a28dc), + TOBN(0xcf86a3f4, 0x902ab04f), TOBN(0x8aacb62a, 0x7f42002d), + TOBN(0x106985eb, 0xf62ffd52), TOBN(0xe670b54e, 0x5797bf10), + TOBN(0x4b405209, 0xc5e30aef), TOBN(0x12c97a20, 0x4365b5e9), + TOBN(0x104646ce, 0x1fe32093), TOBN(0x13cb4ff6, 0x3907a8c9), + TOBN(0x8b9f30d1, 0xd46e726b), TOBN(0xe1985e21, 0xaba0f499), + TOBN(0xc573dea9, 0x10a230cd), TOBN(0x24f46a93, 0xcd30f947), + TOBN(0xf2623fcf, 0xabe2010a), TOBN(0x3f278cb2, 0x73f00e4f), + TOBN(0xed55c67d, 0x50b920eb), TOBN(0xf1cb9a2d, 0x8e760571), + TOBN(0x7c50d109, 0x0895b709), TOBN(0x4207cf07, 0x190d4369), + TOBN(0x3b027e81, 0xc4127fe1), TOBN(0xa9f8b9ad, 0x3ae9c566), + TOBN(0x5ab10851, 0xacbfbba5), TOBN(0xa747d648, 0x569556f5), + TOBN(0xcc172b5c, 0x2ba97bf7), TOBN(0x15e0f77d, 0xbcfa3324), + TOBN(0xa345b797, 0x7686279d), TOBN(0x5a723480, 0xe38003d3), + TOBN(0xfd8e139f, 0x8f5fcda8), TOBN(0xf3e558c4, 0xbdee5bfd), + TOBN(0xd76cbaf4, 0xe33f9f77), TOBN(0x3a4c97a4, 0x71771969), + TOBN(0xda27e84b, 0xf6dce6a7), TOBN(0xff373d96, 0x13e6c2d1), + TOBN(0xf115193c, 0xd759a6e9), TOBN(0x3f9b7025, 0x63d2262c), + TOBN(0xd9764a31, 0x317cd062), TOBN(0x30779d8e, 0x199f8332), + TOBN(0xd8074106, 0x16b11b0b), TOBN(0x7917ab9f, 0x78aeaed8), + TOBN(0xb67a9cbe, 0x28fb1d8e), TOBN(0x2e313563, 0x136eda33), + TOBN(0x010b7069, 0xa371a86c), TOBN(0x44d90fa2, 0x6744e6b7), + TOBN(0x68190867, 0xd6b3e243), TOBN(0x9fe6cd9d, 0x59048c48), + TOBN(0xb900b028, 0x95731538), TOBN(0xa012062f, 0x32cae04f), + TOBN(0x8107c8bc, 0x9399d082), TOBN(0x47e8c54a, 0x41df12e2), + TOBN(0x14ba5117, 0xb6ef3f73), TOBN(0x22260bea, 0x81362f0b), + TOBN(0x90ea261e, 0x1a18cc20), TOBN(0x2192999f, 0x2321d636), + TOBN(0xef64d314, 0xe311b6a0), TOBN(0xd7401e4c, 0x3b54a1f5), + TOBN(0x19019983, 0x6fbca2ba), TOBN(0x46ad3293, 0x8fbffc4b), + TOBN(0xa142d3f6, 0x3786bf40), TOBN(0xeb5cbc26, 0xb67039fc), + TOBN(0x9cb0ae6c, 0x252bd479), TOBN(0x05e0f88a, 0x12b5848f), + TOBN(0x78f6d2b2, 0xa5c97663), TOBN(0x6f6e149b, 0xc162225c), + TOBN(0xe602235c, 0xde601a89), TOBN(0xd17bbe98, 0xf373be1f), + TOBN(0xcaf49a5b, 0xa8471827), TOBN(0x7e1a0a85, 0x18aaa116), + TOBN(0x6c833196, 0x270580c3), TOBN(0x1e233839, 0xf1c98a14), + TOBN(0x67b2f7b4, 0xae34e0a5), TOBN(0x47ac8745, 0xd8ce7289), + TOBN(0x2b74779a, 0x100dd467), TOBN(0x274a4337, 0x4ee50d09), + TOBN(0x603dcf13, 0x83608bc9), TOBN(0xcd9da6c3, 0xc89e8388), + TOBN(0x2660199f, 0x355116ac), TOBN(0xcc38bb59, 0xb6d18eed), + TOBN(0x3075f31f, 0x2f4bc071), TOBN(0x9774457f, 0x265dc57e), + TOBN(0x06a6a9c8, 0xc6db88bb), TOBN(0x6429d07f, 0x4ec98e04), + TOBN(0x8d05e57b, 0x05ecaa8b), TOBN(0x20f140b1, 0x7872ea7b), + TOBN(0xdf8c0f09, 0xca494693), TOBN(0x48d3a020, 0xf252e909), + TOBN(0x4c5c29af, 0x57b14b12), TOBN(0x7e6fa37d, 0xbf47ad1c), + TOBN(0x66e7b506, 0x49a0c938), TOBN(0xb72c0d48, 0x6be5f41f), + TOBN(0x6a6242b8, 0xb2359412), TOBN(0xcd35c774, 0x8e859480), + TOBN(0x12536fea, 0x87baa627), TOBN(0x58c1fec1, 0xf72aa680), + TOBN(0x6c29b637, 0x601e5dc9), TOBN(0x9e3c3c1c, 0xde9e01b9), + TOBN(0xefc8127b, 0x2bcfe0b0), TOBN(0x35107102, 0x2a12f50d), + TOBN(0x6ccd6cb1, 0x4879b397), TOBN(0xf792f804, 0xf8a82f21), + TOBN(0x509d4804, 0xa9b46402), TOBN(0xedddf85d, 0xc10f0850), + TOBN(0x928410dc, 0x4b6208aa), TOBN(0xf6229c46, 0x391012dc), + TOBN(0xc5a7c41e, 0x7727b9b6), TOBN(0x289e4e4b, 0xaa444842), + TOBN(0x049ba1d9, 0xe9a947ea), TOBN(0x44f9e47f, 0x83c8debc), + TOBN(0xfa77a1fe, 0x611f8b8e), TOBN(0xfd2e416a, 0xf518f427), + TOBN(0xc5fffa70, 0x114ebac3), TOBN(0xfe57c4e9, 0x5d89697b), + TOBN(0xfdd053ac, 0xb1aaf613), TOBN(0x31df210f, 0xea585a45), + TOBN(0x318cc10e, 0x24985034), TOBN(0x1a38efd1, 0x5f1d6130), + TOBN(0xbf86f237, 0x0b1e9e21), TOBN(0xb258514d, 0x1dbe88aa), + TOBN(0x1e38a588, 0x90c1baf9), TOBN(0x2936a01e, 0xbdb9b692), + TOBN(0xd576de98, 0x6dd5b20c), TOBN(0xb586bf71, 0x70f98ecf), + TOBN(0xcccf0f12, 0xc42d2fd7), TOBN(0x8717e61c, 0xfb35bd7b), + TOBN(0x8b1e5722, 0x35e6fc06), TOBN(0x3477728f, 0x0b3e13d5), + TOBN(0x150c294d, 0xaa8a7372), TOBN(0xc0291d43, 0x3bfa528a), + TOBN(0xc6c8bc67, 0xcec5a196), TOBN(0xdeeb31e4, 0x5c2e8a7c), + TOBN(0xba93e244, 0xfb6e1c51), TOBN(0xb9f8b71b, 0x2e28e156), + TOBN(0xce65a287, 0x968a2ab9), TOBN(0xe3c5ce69, 0x46bbcb1f), + TOBN(0xf8c835b9, 0xe7ae3f30), TOBN(0x16bbee26, 0xff72b82b), + TOBN(0x665e2017, 0xfd42cd22), TOBN(0x1e139970, 0xf8b1d2a0), + TOBN(0x125cda29, 0x79204932), TOBN(0x7aee94a5, 0x49c3bee5), + TOBN(0x68c70160, 0x89821a66), TOBN(0xf7c37678, 0x8f981669), + TOBN(0xd90829fc, 0x48cc3645), TOBN(0x346af049, 0xd70addfc), + TOBN(0x2057b232, 0x370bf29c), TOBN(0xf90c73ce, 0x42e650ee), + TOBN(0xe03386ea, 0xa126ab90), TOBN(0x0e266e7e, 0x975a087b), + TOBN(0x80578eb9, 0x0fca65d9), TOBN(0x7e2989ea, 0x16af45b8), + TOBN(0x7438212d, 0xcac75a4e), TOBN(0x38c7ca39, 0x4fef36b8), + TOBN(0x8650c494, 0xd402676a), TOBN(0x26ab5a66, 0xf72c7c48), + TOBN(0x4e6cb426, 0xce3a464e), TOBN(0xf8f99896, 0x2b72f841), + TOBN(0x8c318491, 0x1a335cc8), TOBN(0x563459ba, 0x6a5913e4), + TOBN(0x1b920d61, 0xc7b32919), TOBN(0x805ab8b6, 0xa02425ad), + TOBN(0x2ac512da, 0x8d006086), TOBN(0x6ca4846a, 0xbcf5c0fd), + TOBN(0xafea51d8, 0xac2138d7), TOBN(0xcb647545, 0x344cd443), + TOBN(0x0429ee8f, 0xbd7d9040), TOBN(0xee66a2de, 0x819b9c96), + TOBN(0x54f9ec25, 0xdea7d744), TOBN(0x2ffea642, 0x671721bb), + TOBN(0x4f19dbd1, 0x114344ea), TOBN(0x04304536, 0xfd0dbc8b), + TOBN(0x014b50aa, 0x29ec7f91), TOBN(0xb5fc22fe, 0xbb06014d), + TOBN(0x60d963a9, 0x1ee682e0), TOBN(0xdf48abc0, 0xfe85c727), + TOBN(0x0cadba13, 0x2e707c2d), TOBN(0xde608d3a, 0xa645aeff), + TOBN(0x05f1c28b, 0xedafd883), TOBN(0x3c362ede, 0xbd94de1f), + TOBN(0x8dd0629d, 0x13593e41), TOBN(0x0a5e736f, 0x766d6eaf), + TOBN(0xbfa92311, 0xf68cf9d1), TOBN(0xa4f9ef87, 0xc1797556), + TOBN(0x10d75a1f, 0x5601c209), TOBN(0x651c374c, 0x09b07361), + TOBN(0x49950b58, 0x88b5cead), TOBN(0x0ef00058, 0x6fa9dbaa), + TOBN(0xf51ddc26, 0x4e15f33a), TOBN(0x1f8b5ca6, 0x2ef46140), + TOBN(0x343ac0a3, 0xee9523f0), TOBN(0xbb75eab2, 0x975ea978), + TOBN(0x1bccf332, 0x107387f4), TOBN(0x790f9259, 0x9ab0062e), + TOBN(0xf1a363ad, 0x1e4f6a5f), TOBN(0x06e08b84, 0x62519a50), + TOBN(0x60915187, 0x7265f1ee), TOBN(0x6a80ca34, 0x93ae985e), + TOBN(0x81b29768, 0xaaba4864), TOBN(0xb13cabf2, 0x8d52a7d6), + TOBN(0xb5c36348, 0x8ead03f1), TOBN(0xc932ad95, 0x81c7c1c0), + TOBN(0x5452708e, 0xcae1e27b), TOBN(0x9dac4269, 0x1b0df648), + TOBN(0x233e3f0c, 0xdfcdb8bc), TOBN(0xe6ceccdf, 0xec540174), + TOBN(0xbd0d845e, 0x95081181), TOBN(0xcc8a7920, 0x699355d5), + TOBN(0x111c0f6d, 0xc3b375a8), TOBN(0xfd95bc6b, 0xfd51e0dc), + TOBN(0x4a106a26, 0x6888523a), TOBN(0x4d142bd6, 0xcb01a06d), + TOBN(0x79bfd289, 0xadb9b397), TOBN(0x0bdbfb94, 0xe9863914), + TOBN(0x29d8a229, 0x1660f6a6), TOBN(0x7f6abcd6, 0x551c042d), + TOBN(0x13039deb, 0x0ac3ffe8), TOBN(0xa01be628, 0xec8523fb), + TOBN(0x6ea34103, 0x0ca1c328), TOBN(0xc74114bd, 0xb903928e), + TOBN(0x8aa4ff4e, 0x9e9144b0), TOBN(0x7064091f, 0x7f9a4b17), + TOBN(0xa3f4f521, 0xe447f2c4), TOBN(0x81b8da7a, 0x604291f0), + TOBN(0xd680bc46, 0x7d5926de), TOBN(0x84f21fd5, 0x34a1202f), + TOBN(0x1d1e3181, 0x4e9df3d8), TOBN(0x1ca4861a, 0x39ab8d34), + TOBN(0x809ddeec, 0x5b19aa4a), TOBN(0x59f72f7e, 0x4d329366), + TOBN(0xa2f93f41, 0x386d5087), TOBN(0x40bf739c, 0xdd67d64f), + TOBN(0xb4494205, 0x66702158), TOBN(0xc33c65be, 0x73b1e178), + TOBN(0xcdcd657c, 0x38ca6153), TOBN(0x97f4519a, 0xdc791976), + TOBN(0xcc7c7f29, 0xcd6e1f39), TOBN(0x38de9cfb, 0x7e3c3932), + TOBN(0xe448eba3, 0x7b793f85), TOBN(0xe9f8dbf9, 0xf067e914), + TOBN(0xc0390266, 0xf114ae87), TOBN(0x39ed75a7, 0xcd6a8e2a), + TOBN(0xadb14848, 0x7ffba390), TOBN(0x67f8cb8b, 0x6af9bc09), + TOBN(0x322c3848, 0x9c7476db), TOBN(0xa320fecf, 0x52a538d6), + TOBN(0xe0493002, 0xb2aced2b), TOBN(0xdfba1809, 0x616bd430), + TOBN(0x531c4644, 0xc331be70), TOBN(0xbc04d32e, 0x90d2e450), + TOBN(0x1805a0d1, 0x0f9f142d), TOBN(0x2c44a0c5, 0x47ee5a23), + TOBN(0x31875a43, 0x3989b4e3), TOBN(0x6b1949fd, 0x0c063481), + TOBN(0x2dfb9e08, 0xbe0f4492), TOBN(0x3ff0da03, 0xe9d5e517), + TOBN(0x03dbe9a1, 0xf79466a8), TOBN(0x0b87bcd0, 0x15ea9932), + TOBN(0xeb64fc83, 0xab1f58ab), TOBN(0x6d9598da, 0x817edc8a), + TOBN(0x699cff66, 0x1d3b67e5), TOBN(0x645c0f29, 0x92635853), + TOBN(0x253cdd82, 0xeabaf21c), TOBN(0x82b9602a, 0x2241659e), + TOBN(0x2cae07ec, 0x2d9f7091), TOBN(0xbe4c720c, 0x8b48cd9b), + TOBN(0x6ce5bc03, 0x6f08d6c9), TOBN(0x36e8a997, 0xaf10bf40), + TOBN(0x83422d21, 0x3e10ff12), TOBN(0x7b26d3eb, 0xbcc12494), + TOBN(0xb240d2d0, 0xc9469ad6), TOBN(0xc4a11b4d, 0x30afa05b), + TOBN(0x4b604ace, 0xdd6ba286), TOBN(0x18486600, 0x3ee2864c), + TOBN(0x5869d6ba, 0x8d9ce5be), TOBN(0x0d8f68c5, 0xff4bfb0d), + TOBN(0xb69f210b, 0x5700cf73), TOBN(0x61f6653a, 0x6d37c135), + TOBN(0xff3d432b, 0x5aff5a48), TOBN(0x0d81c4b9, 0x72ba3a69), + TOBN(0xee879ae9, 0xfa1899ef), TOBN(0xbac7e2a0, 0x2d6acafd), + TOBN(0xd6d93f6c, 0x1c664399), TOBN(0x4c288de1, 0x5bcb135d), + TOBN(0x83031dab, 0x9dab7cbf), TOBN(0xfe23feb0, 0x3abbf5f0), + TOBN(0x9f1b2466, 0xcdedca85), TOBN(0x140bb710, 0x1a09538c), + TOBN(0xac8ae851, 0x5e11115d), TOBN(0x0d63ff67, 0x6f03f59e), + TOBN(0x755e5551, 0x7d234afb), TOBN(0x61c2db4e, 0x7e208fc1), + TOBN(0xaa9859ce, 0xf28a4b5d), TOBN(0xbdd6d4fc, 0x34af030f), + TOBN(0xd1c4a26d, 0x3be01cb1), TOBN(0x9ba14ffc, 0x243aa07c), + TOBN(0xf95cd3a9, 0xb2503502), TOBN(0xe379bc06, 0x7d2a93ab), + TOBN(0x3efc18e9, 0xd4ca8d68), TOBN(0x083558ec, 0x80bb412a), + TOBN(0xd903b940, 0x9645a968), TOBN(0xa499f0b6, 0x9ba6054f), + TOBN(0x208b573c, 0xb8349abe), TOBN(0x3baab3e5, 0x30b4fc1c), + TOBN(0x87e978ba, 0xcb524990), TOBN(0x3524194e, 0xccdf0e80), + TOBN(0x62711725, 0x7d4bcc42), TOBN(0xe90a3d9b, 0xb90109ba), + TOBN(0x3b1bdd57, 0x1323e1e0), TOBN(0xb78e9bd5, 0x5eae1599), + TOBN(0x0794b746, 0x9e03d278), TOBN(0x80178605, 0xd70e6297), + TOBN(0x171792f8, 0x99c97855), TOBN(0x11b393ee, 0xf5a86b5c), + TOBN(0x48ef6582, 0xd8884f27), TOBN(0xbd44737a, 0xbf19ba5f), + TOBN(0x8698de4c, 0xa42062c6), TOBN(0x8975eb80, 0x61ce9c54), + TOBN(0xd50e57c7, 0xd7fe71f3), TOBN(0x15342190, 0xbc97ce38), + TOBN(0x51bda2de, 0x4df07b63), TOBN(0xba12aeae, 0x200eb87d), + TOBN(0xabe135d2, 0xa9b4f8f6), TOBN(0x04619d65, 0xfad6d99c), + TOBN(0x4a6683a7, 0x7994937c), TOBN(0x7a778c8b, 0x6f94f09a), + TOBN(0x8c508623, 0x20a71b89), TOBN(0x241a2aed, 0x1c229165), + TOBN(0x352be595, 0xaaf83a99), TOBN(0x9fbfee7f, 0x1562bac8), + TOBN(0xeaf658b9, 0x5c4017e3), TOBN(0x1dc7f9e0, 0x15120b86), + TOBN(0xd84f13dd, 0x4c034d6f), TOBN(0x283dd737, 0xeaea3038), + TOBN(0x197f2609, 0xcd85d6a2), TOBN(0x6ebbc345, 0xfae60177), + TOBN(0xb80f031b, 0x4e12fede), TOBN(0xde55d0c2, 0x07a2186b), + TOBN(0x1fb3e37f, 0x24dcdd5a), TOBN(0x8d602da5, 0x7ed191fb), + TOBN(0x108fb056, 0x76023e0d), TOBN(0x70178c71, 0x459c20c0), + TOBN(0xfad5a386, 0x3fe54cf0), TOBN(0xa4a3ec4f, 0x02bbb475), + TOBN(0x1aa5ec20, 0x919d94d7), TOBN(0x5d3b63b5, 0xa81e4ab3), + TOBN(0x7fa733d8, 0x5ad3d2af), TOBN(0xfbc586dd, 0xd1ac7a37), + TOBN(0x282925de, 0x40779614), TOBN(0xfe0ffffb, 0xe74a242a), + TOBN(0x3f39e67f, 0x906151e5), TOBN(0xcea27f5f, 0x55e10649), + TOBN(0xdca1d4e1, 0xc17cf7b7), TOBN(0x0c326d12, 0x2fe2362d), + TOBN(0x05f7ac33, 0x7dd35df3), TOBN(0x0c3b7639, 0xc396dbdf), + TOBN(0x0912f5ac, 0x03b7db1c), TOBN(0x9dea4b70, 0x5c9ed4a9), + TOBN(0x475e6e53, 0xaae3f639), TOBN(0xfaba0e7c, 0xfc278bac), + TOBN(0x16f9e221, 0x9490375f), TOBN(0xaebf9746, 0xa5a7ed0a), + TOBN(0x45f9af3f, 0xf41ad5d6), TOBN(0x03c4623c, 0xb2e99224), + TOBN(0x82c5bb5c, 0xb3cf56aa), TOBN(0x64311819, 0x34567ed3), + TOBN(0xec57f211, 0x8be489ac), TOBN(0x2821895d, 0xb9a1104b), + TOBN(0x610dc875, 0x6064e007), TOBN(0x8e526f3f, 0x5b20d0fe), + TOBN(0x6e71ca77, 0x5b645aee), TOBN(0x3d1dcb9f, 0x800e10ff), + TOBN(0x36b51162, 0x189cf6de), TOBN(0x2c5a3e30, 0x6bb17353), + TOBN(0xc186cd3e, 0x2a6c6fbf), TOBN(0xa74516fa, 0x4bf97906), + TOBN(0x5b4b8f4b, 0x279d6901), TOBN(0x0c4e57b4, 0x2b573743), + TOBN(0x75fdb229, 0xb6e386b6), TOBN(0xb46793fd, 0x99deac27), + TOBN(0xeeec47ea, 0xcf712629), TOBN(0xe965f3c4, 0xcbc3b2dd), + TOBN(0x8dd1fb83, 0x425c6559), TOBN(0x7fc00ee6, 0x0af06fda), + TOBN(0xe98c9225, 0x33d956df), TOBN(0x0f1ef335, 0x4fbdc8a2), + TOBN(0x2abb5145, 0xb79b8ea2), TOBN(0x40fd2945, 0xbdbff288), + TOBN(0x6a814ac4, 0xd7185db7), TOBN(0xc4329d6f, 0xc084609a), + TOBN(0xc9ba7b52, 0xed1be45d), TOBN(0x891dd20d, 0xe4cd2c74), + TOBN(0x5a4d4a7f, 0x824139b1), TOBN(0x66c17716, 0xb873c710), + TOBN(0x5e5bc141, 0x2843c4e0), TOBN(0xd5ac4817, 0xb97eb5bf), + TOBN(0xc0f8af54, 0x450c95c7), TOBN(0xc91b3fa0, 0x318406c5), + TOBN(0x360c340a, 0xab9d97f8), TOBN(0xfb57bd07, 0x90a2d611), + TOBN(0x4339ae3c, 0xa6a6f7e5), TOBN(0x9c1fcd2a, 0x2feb8a10), + TOBN(0x972bcca9, 0xc7ea7432), TOBN(0x1b0b924c, 0x308076f6), + TOBN(0x80b2814a, 0x2a5b4ca5), TOBN(0x2f78f55b, 0x61ef3b29), + TOBN(0xf838744a, 0xc18a414f), TOBN(0xc611eaae, 0x903d0a86), + TOBN(0x94dabc16, 0x2a453f55), TOBN(0xe6f2e3da, 0x14efb279), + TOBN(0x5b7a6017, 0x9320dc3c), TOBN(0x692e382f, 0x8df6b5a4), + TOBN(0x3f5e15e0, 0x2d40fa90), TOBN(0xc87883ae, 0x643dd318), + TOBN(0x511053e4, 0x53544774), TOBN(0x834d0ecc, 0x3adba2bc), + TOBN(0x4215d7f7, 0xbae371f5), TOBN(0xfcfd57bf, 0x6c8663bc), + TOBN(0xded2383d, 0xd6901b1d), TOBN(0x3b49fbb4, 0xb5587dc3), + TOBN(0xfd44a08d, 0x07625f62), TOBN(0x3ee4d65b, 0x9de9b762),} + , + {TOBN(0x64e5137d, 0x0d63d1fa), TOBN(0x658fc052, 0x02a9d89f), + TOBN(0x48894874, 0x50436309), TOBN(0xe9ae30f8, 0xd598da61), + TOBN(0x2ed710d1, 0x818baf91), TOBN(0xe27e9e06, 0x8b6a0c20), + TOBN(0x1e28dcfb, 0x1c1a6b44), TOBN(0x883acb64, 0xd6ac57dc), + TOBN(0x8735728d, 0xc2c6ff70), TOBN(0x79d6122f, 0xc5dc2235), + TOBN(0x23f5d003, 0x19e277f9), TOBN(0x7ee84e25, 0xdded8cc7), + TOBN(0x91a8afb0, 0x63cd880a), TOBN(0x3f3ea7c6, 0x3574af60), + TOBN(0x0cfcdc84, 0x02de7f42), TOBN(0x62d0792f, 0xb31aa152), + TOBN(0x8e1b4e43, 0x8a5807ce), TOBN(0xad283893, 0xe4109a7e), + TOBN(0xc30cc9cb, 0xafd59dda), TOBN(0xf65f36c6, 0x3d8d8093), + TOBN(0xdf31469e, 0xa60d32b2), TOBN(0xee93df4b, 0x3e8191c8), + TOBN(0x9c1017c5, 0x355bdeb5), TOBN(0xd2623185, 0x8616aa28), + TOBN(0xb02c83f9, 0xdec31a21), TOBN(0x988c8b23, 0x6ad9d573), + TOBN(0x53e983ae, 0xa57be365), TOBN(0xe968734d, 0x646f834e), + TOBN(0x9137ea8f, 0x5da6309b), TOBN(0x10f3a624, 0xc1f1ce16), + TOBN(0x782a9ea2, 0xca440921), TOBN(0xdf94739e, 0x5b46f1b5), + TOBN(0x9f9be006, 0xcce85c9b), TOBN(0x360e70d6, 0xa4c7c2d3), + TOBN(0x2cd5beea, 0xaefa1e60), TOBN(0x64cf63c0, 0x8c3d2b6d), + TOBN(0xfb107fa3, 0xe1cf6f90), TOBN(0xb7e937c6, 0xd5e044e6), + TOBN(0x74e8ca78, 0xce34db9f), TOBN(0x4f8b36c1, 0x3e210bd0), + TOBN(0x1df165a4, 0x34a35ea8), TOBN(0x3418e0f7, 0x4d4412f6), + TOBN(0x5af1f8af, 0x518836c3), TOBN(0x42ceef4d, 0x130e1965), + TOBN(0x5560ca0b, 0x543a1957), TOBN(0xc33761e5, 0x886cb123), + TOBN(0x66624b1f, 0xfe98ed30), TOBN(0xf772f4bf, 0x1090997d), + TOBN(0xf4e540bb, 0x4885d410), TOBN(0x7287f810, 0x9ba5f8d7), + TOBN(0x22d0d865, 0xde98dfb1), TOBN(0x49ff51a1, 0xbcfbb8a3), + TOBN(0xb6b6fa53, 0x6bc3012e), TOBN(0x3d31fd72, 0x170d541d), + TOBN(0x8018724f, 0x4b0f4966), TOBN(0x79e7399f, 0x87dbde07), + TOBN(0x56f8410e, 0xf4f8b16a), TOBN(0x97241afe, 0xc47b266a), + TOBN(0x0a406b8e, 0x6d9c87c1), TOBN(0x803f3e02, 0xcd42ab1b), + TOBN(0x7f0309a8, 0x04dbec69), TOBN(0xa83b85f7, 0x3bbad05f), + TOBN(0xc6097273, 0xad8e197f), TOBN(0xc097440e, 0x5067adc1), + TOBN(0x730eafb6, 0x3524ff16), TOBN(0xd7f9b51e, 0x823fc6ce), + TOBN(0x27bd0d32, 0x443e4ac0), TOBN(0x40c59ad9, 0x4d66f217), + TOBN(0x6c33136f, 0x17c387a4), TOBN(0x5043b8d5, 0xeb86804d), + TOBN(0x74970312, 0x675a73c9), TOBN(0x838fdb31, 0xf16669b6), + TOBN(0xc507b6dd, 0x418e7ddd), TOBN(0x39888d93, 0x472f19d6), + TOBN(0x7eae26be, 0x0c27eb4d), TOBN(0x17b53ed3, 0xfbabb884), + TOBN(0xfc27021b, 0x2b01ae4f), TOBN(0x88462e87, 0xcf488682), + TOBN(0xbee096ec, 0x215e2d87), TOBN(0xeb2fea9a, 0xd242e29b), + TOBN(0x5d985b5f, 0xb821fc28), TOBN(0x89d2e197, 0xdc1e2ad2), + TOBN(0x55b566b8, 0x9030ba62), TOBN(0xe3fd41b5, 0x4f41b1c6), + TOBN(0xb738ac2e, 0xb9a96d61), TOBN(0x7f8567ca, 0x369443f4), + TOBN(0x8698622d, 0xf803a440), TOBN(0x2b586236, 0x8fe2f4dc), + TOBN(0xbbcc00c7, 0x56b95bce), TOBN(0x5ec03906, 0x616da680), + TOBN(0x79162ee6, 0x72214252), TOBN(0x43132b63, 0x86a892d2), + TOBN(0x4bdd3ff2, 0x2f3263bf), TOBN(0xd5b3733c, 0x9cd0a142), + TOBN(0x592eaa82, 0x44415ccb), TOBN(0x663e8924, 0x8d5474ea), + TOBN(0x8058a25e, 0x5236344e), TOBN(0x82e8df9d, 0xbda76ee6), + TOBN(0xdcf6efd8, 0x11cc3d22), TOBN(0x00089cda, 0x3b4ab529), + TOBN(0x91d3a071, 0xbd38a3db), TOBN(0x4ea97fc0, 0xef72b925), + TOBN(0x0c9fc15b, 0xea3edf75), TOBN(0x5a6297cd, 0xa4348ed3), + TOBN(0x0d38ab35, 0xce7c42d4), TOBN(0x9fd493ef, 0x82feab10), + TOBN(0x46056b6d, 0x82111b45), TOBN(0xda11dae1, 0x73efc5c3), + TOBN(0xdc740278, 0x5545a7fb), TOBN(0xbdb2601c, 0x40d507e6), + TOBN(0x121dfeeb, 0x7066fa58), TOBN(0x214369a8, 0x39ae8c2a), + TOBN(0x195709cb, 0x06e0956c), TOBN(0x4c9d254f, 0x010cd34b), + TOBN(0xf51e13f7, 0x0471a532), TOBN(0xe19d6791, 0x1e73054d), + TOBN(0xf702a628, 0xdb5c7be3), TOBN(0xc7141218, 0xb24dde05), + TOBN(0xdc18233c, 0xf29b2e2e), TOBN(0x3a6bd1e8, 0x85342dba), + TOBN(0x3f747fa0, 0xb311898c), TOBN(0xe2a272e4, 0xcd0eac65), + TOBN(0x4bba5851, 0xf914d0bc), TOBN(0x7a1a9660, 0xc4a43ee3), + TOBN(0xe5a367ce, 0xa1c8cde9), TOBN(0x9d958ba9, 0x7271abe3), + TOBN(0xf3ff7eb6, 0x3d1615cd), TOBN(0xa2280dce, 0xf5ae20b0), + TOBN(0x56dba5c1, 0xcf640147), TOBN(0xea5a2e3d, 0x5e83d118), + TOBN(0x04cd6b6d, 0xda24c511), TOBN(0x1c0f4671, 0xe854d214), + TOBN(0x91a6b7a9, 0x69565381), TOBN(0xdc966240, 0xdecf1f5b), + TOBN(0x1b22d21c, 0xfcf5d009), TOBN(0x2a05f641, 0x9021dbd5), + TOBN(0x8c0ed566, 0xd4312483), TOBN(0x5179a95d, 0x643e216f), + TOBN(0xcc185fec, 0x17044493), TOBN(0xb3063339, 0x54991a21), + TOBN(0xd801ecdb, 0x0081a726), TOBN(0x0149b0c6, 0x4fa89bbb), + TOBN(0xafe9065a, 0x4391b6b9), TOBN(0xedc92786, 0xd633f3a3), + TOBN(0xe408c24a, 0xae6a8e13), TOBN(0x85833fde, 0x9f3897ab), + TOBN(0x43800e7e, 0xd81a0715), TOBN(0xde08e346, 0xb44ffc5f), + TOBN(0x7094184c, 0xcdeff2e0), TOBN(0x49f9387b, 0x165eaed1), + TOBN(0x635d6129, 0x777c468a), TOBN(0x8c0dcfd1, 0x538c2dd8), + TOBN(0xd6d9d9e3, 0x7a6a308b), TOBN(0x62375830, 0x4c2767d3), + TOBN(0x874a8bc6, 0xf38cbeb6), TOBN(0xd94d3f1a, 0xccb6fd9e), + TOBN(0x92a9735b, 0xba21f248), TOBN(0x272ad0e5, 0x6cd1efb0), + TOBN(0x7437b69c, 0x05b03284), TOBN(0xe7f04702, 0x6948c225), + TOBN(0x8a56c04a, 0xcba2ecec), TOBN(0x0c181270, 0xe3a73e41), + TOBN(0x6cb34e9d, 0x03e93725), TOBN(0xf77c8713, 0x496521a9), + TOBN(0x94569183, 0xfa7f9f90), TOBN(0xf2e7aa4c, 0x8c9707ad), + TOBN(0xced2c9ba, 0x26c1c9a3), TOBN(0x9109fe96, 0x40197507), + TOBN(0x9ae868a9, 0xe9adfe1c), TOBN(0x3984403d, 0x314e39bb), + TOBN(0xb5875720, 0xf2fe378f), TOBN(0x33f901e0, 0xba44a628), + TOBN(0xea1125fe, 0x3652438c), TOBN(0xae9ec4e6, 0x9dd1f20b), + TOBN(0x1e740d9e, 0xbebf7fbd), TOBN(0x6dbd3ddc, 0x42dbe79c), + TOBN(0x62082aec, 0xedd36776), TOBN(0xf612c478, 0xe9859039), + TOBN(0xa493b201, 0x032f7065), TOBN(0xebd4d8f2, 0x4ff9b211), + TOBN(0x3f23a0aa, 0xaac4cb32), TOBN(0xea3aadb7, 0x15ed4005), + TOBN(0xacf17ea4, 0xafa27e63), TOBN(0x56125c1a, 0xc11fd66c), + TOBN(0x266344a4, 0x3794f8dc), TOBN(0xdcca923a, 0x483c5c36), + TOBN(0x2d6b6bbf, 0x3f9d10a0), TOBN(0xb320c5ca, 0x81d9bdf3), + TOBN(0x620e28ff, 0x47b50a95), TOBN(0x933e3b01, 0xcef03371), + TOBN(0xf081bf85, 0x99100153), TOBN(0x183be9a0, 0xc3a8c8d6), + TOBN(0x4e3ddc5a, 0xd6bbe24d), TOBN(0xc6c74630, 0x53843795), + TOBN(0x78193dd7, 0x65ec2d4c), TOBN(0xb8df26cc, 0xcd3c89b2), + TOBN(0x98dbe399, 0x5a483f8d), TOBN(0x72d8a957, 0x7dd3313a), + TOBN(0x65087294, 0xab0bd375), TOBN(0xfcd89248, 0x7c259d16), + TOBN(0x8a9443d7, 0x7613aa81), TOBN(0x80100800, 0x85fe6584), + TOBN(0x70fc4dbc, 0x7fb10288), TOBN(0xf58280d3, 0xe86beee8), + TOBN(0x14fdd82f, 0x7c978c38), TOBN(0xdf1204c1, 0x0de44d7b), + TOBN(0xa08a1c84, 0x4160252f), TOBN(0x591554ca, 0xc17646a5), + TOBN(0x214a37d6, 0xa05bd525), TOBN(0x48d5f09b, 0x07957b3c), + TOBN(0x0247cdcb, 0xd7109bc9), TOBN(0x40f9e4bb, 0x30599ce7), + TOBN(0xc325fa03, 0xf46ad2ec), TOBN(0x00f766cf, 0xc3e3f9ee), + TOBN(0xab556668, 0xd43a4577), TOBN(0x68d30a61, 0x3ee03b93), + TOBN(0x7ddc81ea, 0x77b46a08), TOBN(0xcf5a6477, 0xc7480699), + TOBN(0x43a8cb34, 0x6633f683), TOBN(0x1b867e6b, 0x92363c60), + TOBN(0x43921114, 0x1f60558e), TOBN(0xcdbcdd63, 0x2f41450e), + TOBN(0x7fc04601, 0xcc630e8b), TOBN(0xea7c66d5, 0x97038b43), + TOBN(0x7259b8a5, 0x04e99fd8), TOBN(0x98a8dd12, 0x4785549a), + TOBN(0x0e459a7c, 0x840552e1), TOBN(0xcdfcf4d0, 0x4bb0909e), + TOBN(0x34a86db2, 0x53758da7), TOBN(0xe643bb83, 0xeac997e1), + TOBN(0x96400bd7, 0x530c5b7e), TOBN(0x9f97af87, 0xb41c8b52), + TOBN(0x34fc8820, 0xfbeee3f9), TOBN(0x93e53490, 0x49091afd), + TOBN(0x764b9be5, 0x9a31f35c), TOBN(0x71f37864, 0x57e3d924), + TOBN(0x02fb34e0, 0x943aa75e), TOBN(0xa18c9c58, 0xab8ff6e4), + TOBN(0x080f31b1, 0x33cf0d19), TOBN(0x5c9682db, 0x083518a7), + TOBN(0x873d4ca6, 0xb709c3de), TOBN(0x64a84262, 0x3575b8f0), + TOBN(0x6275da1f, 0x020154bb), TOBN(0x97678caa, 0xd17cf1ab), + TOBN(0x8779795f, 0x951a95c3), TOBN(0xdd35b163, 0x50fccc08), + TOBN(0x32709627, 0x33d8f031), TOBN(0x3c5ab10a, 0x498dd85c), + TOBN(0xb6c185c3, 0x41dca566), TOBN(0x7de7feda, 0xd8622aa3), + TOBN(0x99e84d92, 0x901b6dfb), TOBN(0x30a02b0e, 0x7c4ad288), + TOBN(0xc7c81daa, 0x2fd3cf36), TOBN(0xd1319547, 0xdf89e59f), + TOBN(0xb2be8184, 0xcd496733), TOBN(0xd5f449eb, 0x93d3412b), + TOBN(0x7ea41b1b, 0x25fe531d), TOBN(0xf9797432, 0x6a1d5646), + TOBN(0x86067f72, 0x2bde501a), TOBN(0xf91481c0, 0x0c85e89c), + TOBN(0xca8ee465, 0xf8b05bc6), TOBN(0x1844e1cf, 0x02e83cda), + TOBN(0xca82114a, 0xb4dbe33b), TOBN(0x0f9f8769, 0x4eabfde2), + TOBN(0x4936b1c0, 0x38b27fe2), TOBN(0x63b6359b, 0xaba402df), + TOBN(0x40c0ea2f, 0x656bdbab), TOBN(0x9c992a89, 0x6580c39c), + TOBN(0x600e8f15, 0x2a60aed1), TOBN(0xeb089ca4, 0xe0bf49df), + TOBN(0x9c233d7d, 0x2d42d99a), TOBN(0x648d3f95, 0x4c6bc2fa), + TOBN(0xdcc383a8, 0xe1add3f3), TOBN(0xf42c0c6a, 0x4f64a348), + TOBN(0x2abd176f, 0x0030dbdb), TOBN(0x4de501a3, 0x7d6c215e), + TOBN(0x4a107c1f, 0x4b9a64bc), TOBN(0xa77f0ad3, 0x2496cd59), + TOBN(0xfb78ac62, 0x7688dffb), TOBN(0x7025a2ca, 0x67937d8e), + TOBN(0xfde8b2d1, 0xd1a8f4e7), TOBN(0xf5b3da47, 0x7354927c), + TOBN(0xe48606a3, 0xd9205735), TOBN(0xac477cc6, 0xe177b917), + TOBN(0xfb1f73d2, 0xa883239a), TOBN(0xe12572f6, 0xcc8b8357), + TOBN(0x9d355e9c, 0xfb1f4f86), TOBN(0x89b795f8, 0xd9f3ec6e), + TOBN(0x27be56f1, 0xb54398dc), TOBN(0x1890efd7, 0x3fedeed5), + TOBN(0x62f77f1f, 0x9c6d0140), TOBN(0x7ef0e314, 0x596f0ee4), + TOBN(0x50ca6631, 0xcc61dab3), TOBN(0x4a39801d, 0xf4866e4f), + TOBN(0x66c8d032, 0xae363b39), TOBN(0x22c591e5, 0x2ead66aa), + TOBN(0x954ba308, 0xde02a53e), TOBN(0x2a6c060f, 0xd389f357), + TOBN(0xe6cfcde8, 0xfbf40b66), TOBN(0x8e02fc56, 0xc6340ce1), + TOBN(0xe4957795, 0x73adb4ba), TOBN(0x7b86122c, 0xa7b03805), + TOBN(0x63f83512, 0x0c8e6fa6), TOBN(0x83660ea0, 0x057d7804), + TOBN(0xbad79105, 0x21ba473c), TOBN(0xb6c50bee, 0xded5389d), + TOBN(0xee2caf4d, 0xaa7c9bc0), TOBN(0xd97b8de4, 0x8c4e98a7), + TOBN(0xa9f63e70, 0xab3bbddb), TOBN(0x3898aabf, 0x2597815a), + TOBN(0x7659af89, 0xac15b3d9), TOBN(0xedf7725b, 0x703ce784), + TOBN(0x25470fab, 0xe085116b), TOBN(0x04a43375, 0x87285310), + TOBN(0x4e39187e, 0xe2bfd52f), TOBN(0x36166b44, 0x7d9ebc74), + TOBN(0x92ad433c, 0xfd4b322c), TOBN(0x726aa817, 0xba79ab51), + TOBN(0xf96eacd8, 0xc1db15eb), TOBN(0xfaf71e91, 0x0476be63), + TOBN(0xdd69a640, 0x641fad98), TOBN(0xb7995918, 0x29622559), + TOBN(0x03c6daa5, 0xde4199dc), TOBN(0x92cadc97, 0xad545eb4), + TOBN(0x1028238b, 0x256534e4), TOBN(0x73e80ce6, 0x8595409a), + TOBN(0x690d4c66, 0xd05dc59b), TOBN(0xc95f7b8f, 0x981dee80), + TOBN(0xf4337014, 0xd856ac25), TOBN(0x441bd9dd, 0xac524dca), + TOBN(0x640b3d85, 0x5f0499f5), TOBN(0x39cf84a9, 0xd5fda182), + TOBN(0x04e7b055, 0xb2aa95a0), TOBN(0x29e33f0a, 0x0ddf1860), + TOBN(0x082e74b5, 0x423f6b43), TOBN(0x217edeb9, 0x0aaa2b0f), + TOBN(0x58b83f35, 0x83cbea55), TOBN(0xc485ee4d, 0xbc185d70), + TOBN(0x833ff03b, 0x1e5f6992), TOBN(0xb5b9b9cc, 0xcf0c0dd5), + TOBN(0x7caaee8e, 0x4e9e8a50), TOBN(0x462e907b, 0x6269dafd), + TOBN(0x6ed5cee9, 0xfbe791c6), TOBN(0x68ca3259, 0xed430790), + TOBN(0x2b72bdf2, 0x13b5ba88), TOBN(0x60294c8a, 0x35ef0ac4), + TOBN(0x9c3230ed, 0x19b99b08), TOBN(0x560fff17, 0x6c2589aa), + TOBN(0x552b8487, 0xd6770374), TOBN(0xa373202d, 0x9a56f685), + TOBN(0xd3e7f907, 0x45f175d9), TOBN(0x3c2f315f, 0xd080d810), + TOBN(0x1130e9dd, 0x7b9520e8), TOBN(0xc078f9e2, 0x0af037b5), + TOBN(0x38cd2ec7, 0x1e9c104c), TOBN(0x0f684368, 0xc472fe92), + TOBN(0xd3f1b5ed, 0x6247e7ef), TOBN(0xb32d33a9, 0x396dfe21), + TOBN(0x46f59cf4, 0x4a9aa2c2), TOBN(0x69cd5168, 0xff0f7e41), + TOBN(0x3f59da0f, 0x4b3234da), TOBN(0xcf0b0235, 0xb4579ebe), + TOBN(0x6d1cbb25, 0x6d2476c7), TOBN(0x4f0837e6, 0x9dc30f08), + TOBN(0x9a4075bb, 0x906f6e98), TOBN(0x253bb434, 0xc761e7d1), + TOBN(0xde2e645f, 0x6e73af10), TOBN(0xb89a4060, 0x0c5f131c), + TOBN(0xd12840c5, 0xb8cc037f), TOBN(0x3d093a5b, 0x7405bb47), + TOBN(0x6202c253, 0x206348b8), TOBN(0xbf5d57fc, 0xc55a3ca7), + TOBN(0x89f6c90c, 0x8c3bef48), TOBN(0x23ac7623, 0x5a0a960a), + TOBN(0xdfbd3d6b, 0x552b42ab), TOBN(0x3ef22458, 0x132061f6), + TOBN(0xd74e9bda, 0xc97e6516), TOBN(0x88779360, 0xc230f49e), + TOBN(0xa6ec1de3, 0x1e74ea49), TOBN(0x581dcee5, 0x3fb645a2), + TOBN(0xbaef2391, 0x8f483f14), TOBN(0x6d2dddfc, 0xd137d13b), + TOBN(0x54cde50e, 0xd2743a42), TOBN(0x89a34fc5, 0xe4d97e67), + TOBN(0x13f1f5b3, 0x12e08ce5), TOBN(0xa80540b8, 0xa7f0b2ca), + TOBN(0x854bcf77, 0x01982805), TOBN(0xb8653ffd, 0x233bea04), + TOBN(0x8e7b8787, 0x02b0b4c9), TOBN(0x2675261f, 0x9acb170a), + TOBN(0x061a9d90, 0x930c14e5), TOBN(0xb59b30e0, 0xdef0abea), + TOBN(0x1dc19ea6, 0x0200ec7d), TOBN(0xb6f4a3f9, 0x0bce132b), + TOBN(0xb8d5de90, 0xf13e27e0), TOBN(0xbaee5ef0, 0x1fade16f), + TOBN(0x6f406aaa, 0xe4c6cf38), TOBN(0xab4cfe06, 0xd1369815), + TOBN(0x0dcffe87, 0xefd550c6), TOBN(0x9d4f59c7, 0x75ff7d39), + TOBN(0xb02553b1, 0x51deb6ad), TOBN(0x812399a4, 0xb1877749), + TOBN(0xce90f71f, 0xca6006e1), TOBN(0xc32363a6, 0xb02b6e77), + TOBN(0x02284fbe, 0xdc36c64d), TOBN(0x86c81e31, 0xa7e1ae61), + TOBN(0x2576c7e5, 0xb909d94a), TOBN(0x8b6f7d02, 0x818b2bb0), + TOBN(0xeca3ed07, 0x56faa38a), TOBN(0xa3790e6c, 0x9305bb54), + TOBN(0xd784eeda, 0x7bc73061), TOBN(0xbd56d369, 0x6dd50614), + TOBN(0xd6575949, 0x229a8aa9), TOBN(0xdcca8f47, 0x4595ec28), + TOBN(0x814305c1, 0x06ab4fe6), TOBN(0xc8c39768, 0x24f43f16), + TOBN(0xe2a45f36, 0x523f2b36), TOBN(0x995c6493, 0x920d93bb), + TOBN(0xf8afdab7, 0x90f1632b), TOBN(0x79ebbecd, 0x1c295954), + TOBN(0xc7bb3ddb, 0x79592f48), TOBN(0x67216a7b, 0x5f88e998), + TOBN(0xd91f098b, 0xbc01193e), TOBN(0xf7d928a5, 0xb1db83fc), + TOBN(0x55e38417, 0xe991f600), TOBN(0x2a91113e, 0x2981a934), + TOBN(0xcbc9d648, 0x06b13bde), TOBN(0xb011b6ac, 0x0755ff44), + TOBN(0x6f4cb518, 0x045ec613), TOBN(0x522d2d31, 0xc2f5930a), + TOBN(0x5acae1af, 0x382e65de), TOBN(0x57643067, 0x27bc966f), + TOBN(0x5e12705d, 0x1c7193f0), TOBN(0xf0f32f47, 0x3be8858e), + TOBN(0x785c3d7d, 0x96c6dfc7), TOBN(0xd75b4a20, 0xbf31795d), + TOBN(0x91acf17b, 0x342659d4), TOBN(0xe596ea34, 0x44f0378f), + TOBN(0x4515708f, 0xce52129d), TOBN(0x17387e1e, 0x79f2f585), + TOBN(0x72cfd2e9, 0x49dee168), TOBN(0x1ae05223, 0x3e2af239), + TOBN(0x009e75be, 0x1d94066a), TOBN(0x6cca31c7, 0x38abf413), + TOBN(0xb50bd61d, 0x9bc49908), TOBN(0x4a9b4a8c, 0xf5e2bc1e), + TOBN(0xeb6cc5f7, 0x946f83ac), TOBN(0x27da93fc, 0xebffab28), + TOBN(0xea314c96, 0x4821c8c5), TOBN(0x8de49ded, 0xa83c15f4), + TOBN(0x7a64cf20, 0x7af33004), TOBN(0x45f1bfeb, 0xc9627e10), + TOBN(0x878b0626, 0x54b9df60), TOBN(0x5e4fdc3c, 0xa95c0b33), + TOBN(0xe54a37ca, 0xc2035d8e), TOBN(0x9087cda9, 0x80f20b8c), + TOBN(0x36f61c23, 0x8319ade4), TOBN(0x766f287a, 0xde8cfdf8), + TOBN(0x48821948, 0x346f3705), TOBN(0x49a7b853, 0x16e4f4a2), + TOBN(0xb9b3f8a7, 0x5cedadfd), TOBN(0x8f562815, 0x8db2a815), + TOBN(0xc0b7d554, 0x01f68f95), TOBN(0x12971e27, 0x688a208e), + TOBN(0xc9f8b696, 0xd0ff34fc), TOBN(0x20824de2, 0x1222718c), + TOBN(0x7213cf9f, 0x0c95284d), TOBN(0xe2ad741b, 0xdc158240), + TOBN(0x0ee3a6df, 0x54043ccf), TOBN(0x16ff479b, 0xd84412b3), + TOBN(0xf6c74ee0, 0xdfc98af0), TOBN(0xa78a169f, 0x52fcd2fb), + TOBN(0xd8ae8746, 0x99c930e9), TOBN(0x1d33e858, 0x49e117a5), + TOBN(0x7581fcb4, 0x6624759f), TOBN(0xde50644f, 0x5bedc01d), + TOBN(0xbeec5d00, 0xcaf3155e), TOBN(0x672d66ac, 0xbc73e75f), + TOBN(0x86b9d8c6, 0x270b01db), TOBN(0xd249ef83, 0x50f55b79), + TOBN(0x6131d6d4, 0x73978fe3), TOBN(0xcc4e4542, 0x754b00a1), + TOBN(0x4e05df05, 0x57dfcfe9), TOBN(0x94b29cdd, 0x51ef6bf0), + TOBN(0xe4530cff, 0x9bc7edf2), TOBN(0x8ac236fd, 0xd3da65f3), + TOBN(0x0faf7d5f, 0xc8eb0b48), TOBN(0x4d2de14c, 0x660eb039), + TOBN(0xc006bba7, 0x60430e54), TOBN(0x10a2d0d6, 0xda3289ab), + TOBN(0x9c037a5d, 0xd7979c59), TOBN(0x04d1f3d3, 0xa116d944), + TOBN(0x9ff22473, 0x8a0983cd), TOBN(0x28e25b38, 0xc883cabb), + TOBN(0xe968dba5, 0x47a58995), TOBN(0x2c80b505, 0x774eebdf), + TOBN(0xee763b71, 0x4a953beb), TOBN(0x502e223f, 0x1642e7f6), + TOBN(0x6fe4b641, 0x61d5e722), TOBN(0x9d37c5b0, 0xdbef5316), + TOBN(0x0115ed70, 0xf8330bc7), TOBN(0x139850e6, 0x75a72789), + TOBN(0x27d7faec, 0xffceccc2), TOBN(0x3016a860, 0x4fd9f7f6), + TOBN(0xc492ec64, 0x4cd8f64c), TOBN(0x58a2d790, 0x279d7b51), + TOBN(0x0ced1fc5, 0x1fc75256), TOBN(0x3e658aed, 0x8f433017), + TOBN(0x0b61942e, 0x05da59eb), TOBN(0xba3d60a3, 0x0ddc3722), + TOBN(0x7c311cd1, 0x742e7f87), TOBN(0x6473ffee, 0xf6b01b6e),} + , + {TOBN(0x8303604f, 0x692ac542), TOBN(0xf079ffe1, 0x227b91d3), + TOBN(0x19f63e63, 0x15aaf9bd), TOBN(0xf99ee565, 0xf1f344fb), + TOBN(0x8a1d661f, 0xd6219199), TOBN(0x8c883bc6, 0xd48ce41c), + TOBN(0x1065118f, 0x3c74d904), TOBN(0x713889ee, 0x0faf8b1b), + TOBN(0x972b3f8f, 0x81a1b3be), TOBN(0x4f3ce145, 0xce2764a0), + TOBN(0xe2d0f1cc, 0x28c4f5f7), TOBN(0xdeee0c0d, 0xc7f3985b), + TOBN(0x7df4adc0, 0xd39e25c3), TOBN(0x40619820, 0xc467a080), + TOBN(0x440ebc93, 0x61cf5a58), TOBN(0x527729a6, 0x422ad600), + TOBN(0xca6c0937, 0xb1b76ba6), TOBN(0x1a2eab85, 0x4d2026dc), + TOBN(0xb1715e15, 0x19d9ae0a), TOBN(0xf1ad9199, 0xbac4a026), + TOBN(0x35b3dfb8, 0x07ea7b0e), TOBN(0xedf5496f, 0x3ed9eb89), + TOBN(0x8932e5ff, 0x2d6d08ab), TOBN(0xf314874e, 0x25bd2731), + TOBN(0xefb26a75, 0x3f73f449), TOBN(0x1d1c94f8, 0x8d44fc79), + TOBN(0x49f0fbc5, 0x3bc0dc4d), TOBN(0xb747ea0b, 0x3698a0d0), + TOBN(0x5218c3fe, 0x228d291e), TOBN(0x35b804b5, 0x43c129d6), + TOBN(0xfac859b8, 0xd1acc516), TOBN(0x6c10697d, 0x95d6e668), + TOBN(0xc38e438f, 0x0876fd4e), TOBN(0x45f0c307, 0x83d2f383), + TOBN(0x203cc2ec, 0xb10934cb), TOBN(0x6a8f2439, 0x2c9d46ee), + TOBN(0xf16b431b, 0x65ccde7b), TOBN(0x41e2cd18, 0x27e76a6f), + TOBN(0xb9c8cf8f, 0x4e3484d7), TOBN(0x64426efd, 0x8315244a), + TOBN(0x1c0a8e44, 0xfc94dea3), TOBN(0x34c8cdbf, 0xdad6a0b0), + TOBN(0x919c3840, 0x04113cef), TOBN(0xfd32fba4, 0x15490ffa), + TOBN(0x58d190f6, 0x795dcfb7), TOBN(0xfef01b03, 0x83588baf), + TOBN(0x9e6d1d63, 0xca1fc1c0), TOBN(0x53173f96, 0xf0a41ac9), + TOBN(0x2b1d402a, 0xba16f73b), TOBN(0x2fb31014, 0x8cf9b9fc), + TOBN(0x2d51e60e, 0x446ef7bf), TOBN(0xc731021b, 0xb91e1745), + TOBN(0x9d3b4724, 0x4fee99d4), TOBN(0x4bca48b6, 0xfac5c1ea), + TOBN(0x70f5f514, 0xbbea9af7), TOBN(0x751f55a5, 0x974c283a), + TOBN(0x6e30251a, 0xcb452fdb), TOBN(0x31ee6965, 0x50f30650), + TOBN(0xb0b3e508, 0x933548d9), TOBN(0xb8949a4f, 0xf4b0ef5b), + TOBN(0x208b8326, 0x3c88f3bd), TOBN(0xab147c30, 0xdb1d9989), + TOBN(0xed6515fd, 0x44d4df03), TOBN(0x17a12f75, 0xe72eb0c5), + TOBN(0x3b59796d, 0x36cf69db), TOBN(0x1219eee9, 0x56670c18), + TOBN(0xfe3341f7, 0x7a070d8e), TOBN(0x9b70130b, 0xa327f90c), + TOBN(0x36a32462, 0x0ae18e0e), TOBN(0x2021a623, 0x46c0a638), + TOBN(0x251b5817, 0xc62eb0d4), TOBN(0x87bfbcdf, 0x4c762293), + TOBN(0xf78ab505, 0xcdd61d64), TOBN(0x8c7a53fc, 0xc8c18857), + TOBN(0xa653ce6f, 0x16147515), TOBN(0x9c923aa5, 0xea7d52d5), + TOBN(0xc24709cb, 0x5c18871f), TOBN(0x7d53bec8, 0x73b3cc74), + TOBN(0x59264aff, 0xfdd1d4c4), TOBN(0x5555917e, 0x240da582), + TOBN(0xcae8bbda, 0x548f5a0e), TOBN(0x1910eaba, 0x3bbfbbe1), + TOBN(0xae579685, 0x7677afc3), TOBN(0x49ea61f1, 0x73ff0b5c), + TOBN(0x78655478, 0x4f7c3922), TOBN(0x95d337cd, 0x20c68eef), + TOBN(0x68f1e1e5, 0xdf779ab9), TOBN(0x14b491b0, 0xb5cf69a8), + TOBN(0x7a6cbbe0, 0x28e3fe89), TOBN(0xe7e1fee4, 0xc5aac0eb), + TOBN(0x7f47eda5, 0x697e5140), TOBN(0x4f450137, 0xb454921f), + TOBN(0xdb625f84, 0x95cd8185), TOBN(0x74be0ba1, 0xcdb2e583), + TOBN(0xaee4fd7c, 0xdd5e6de4), TOBN(0x4251437d, 0xe8101739), + TOBN(0x686d72a0, 0xac620366), TOBN(0x4be3fb9c, 0xb6d59344), + TOBN(0x6e8b44e7, 0xa1eb75b9), TOBN(0x84e39da3, 0x91a5c10c), + TOBN(0x37cc1490, 0xb38f0409), TOBN(0x02951943, 0x2c2ade82), + TOBN(0x9b688783, 0x1190a2d8), TOBN(0x25627d14, 0x231182ba), + TOBN(0x6eb550aa, 0x658a6d87), TOBN(0x1405aaa7, 0xcf9c7325), + TOBN(0xd147142e, 0x5c8748c9), TOBN(0x7f637e4f, 0x53ede0e0), + TOBN(0xf8ca2776, 0x14ffad2c), TOBN(0xe58fb1bd, 0xbafb6791), + TOBN(0x17158c23, 0xbf8f93fc), TOBN(0x7f15b373, 0x0a4a4655), + TOBN(0x39d4add2, 0xd842ca72), TOBN(0xa71e4391, 0x3ed96305), + TOBN(0x5bb09cbe, 0x6700be14), TOBN(0x68d69d54, 0xd8befcf6), + TOBN(0xa45f5367, 0x37183bcf), TOBN(0x7152b7bb, 0x3370dff7), + TOBN(0xcf887baa, 0xbf12525b), TOBN(0xe7ac7bdd, 0xd6d1e3cd), + TOBN(0x25914f78, 0x81fdad90), TOBN(0xcf638f56, 0x0d2cf6ab), + TOBN(0xb90bc03f, 0xcc054de5), TOBN(0x932811a7, 0x18b06350), + TOBN(0x2f00b330, 0x9bbd11ff), TOBN(0x76108a6f, 0xb4044974), + TOBN(0x801bb9e0, 0xa851d266), TOBN(0x0dd099be, 0xbf8990c1), + TOBN(0x58c5aaaa, 0xabe32986), TOBN(0x0fe9dd2a, 0x50d59c27), + TOBN(0x84951ff4, 0x8d307305), TOBN(0x6c23f829, 0x86529b78), + TOBN(0x50bb2218, 0x0b136a79), TOBN(0x7e2174de, 0x77a20996), + TOBN(0x6f00a4b9, 0xc0bb4da6), TOBN(0x89a25a17, 0xefdde8da), + TOBN(0xf728a27e, 0xc11ee01d), TOBN(0xf900553a, 0xe5f10dfb), + TOBN(0x189a83c8, 0x02ec893c), TOBN(0x3ca5bdc1, 0x23f66d77), + TOBN(0x98781537, 0x97eada9f), TOBN(0x59c50ab3, 0x10256230), + TOBN(0x346042d9, 0x323c69b3), TOBN(0x1b715a6d, 0x2c460449), + TOBN(0xa41dd476, 0x6ae06e0b), TOBN(0xcdd7888e, 0x9d42e25f), + TOBN(0x0f395f74, 0x56b25a20), TOBN(0xeadfe0ae, 0x8700e27e), + TOBN(0xb09d52a9, 0x69950093), TOBN(0x3525d9cb, 0x327f8d40), + TOBN(0xb8235a94, 0x67df886a), TOBN(0x77e4b0dd, 0x035faec2), + TOBN(0x115eb20a, 0x517d7061), TOBN(0x77fe3433, 0x6c2df683), + TOBN(0x6870ddc7, 0xcdc6fc67), TOBN(0xb1610588, 0x0b87de83), + TOBN(0x343584ca, 0xd9c4ddbe), TOBN(0xb3164f1c, 0x3d754be2), + TOBN(0x0731ed3a, 0xc1e6c894), TOBN(0x26327dec, 0x4f6b904c), + TOBN(0x9d49c6de, 0x97b5cd32), TOBN(0x40835dae, 0xb5eceecd), + TOBN(0xc66350ed, 0xd9ded7fe), TOBN(0x8aeebb5c, 0x7a678804), + TOBN(0x51d42fb7, 0x5b8ee9ec), TOBN(0xd7a17bdd, 0x8e3ca118), + TOBN(0x40d7511a, 0x2ef4400e), TOBN(0xc48990ac, 0x875a66f4), + TOBN(0x8de07d2a, 0x2199e347), TOBN(0xbee75556, 0x2a39e051), + TOBN(0x56918786, 0x916e51dc), TOBN(0xeb191313, 0x4a2d89ec), + TOBN(0x6679610d, 0x37d341ed), TOBN(0x434fbb41, 0x56d51c2b), + TOBN(0xe54b7ee7, 0xd7492dba), TOBN(0xaa33a79a, 0x59021493), + TOBN(0x49fc5054, 0xe4bd6d3d), TOBN(0x09540f04, 0x5ab551d0), + TOBN(0x8acc9085, 0x4942d3a6), TOBN(0x231af02f, 0x2d28323b), + TOBN(0x93458cac, 0x0992c163), TOBN(0x1fef8e71, 0x888e3bb4), + TOBN(0x27578da5, 0xbe8c268c), TOBN(0xcc8be792, 0xe805ec00), + TOBN(0x29267bae, 0xc61c3855), TOBN(0xebff429d, 0x58c1fd3b), + TOBN(0x22d886c0, 0x8c0b93b8), TOBN(0xca5e00b2, 0x2ddb8953), + TOBN(0xcf330117, 0xc3fed8b7), TOBN(0xd49ac6fa, 0x819c01f6), + TOBN(0x6ddaa6bd, 0x3c0fbd54), TOBN(0x91743068, 0x8049a2cf), + TOBN(0xd67f981e, 0xaff2ef81), TOBN(0xc3654d35, 0x2818ae80), + TOBN(0x81d05044, 0x1b2aa892), TOBN(0x2db067bf, 0x3d099328), + TOBN(0xe7c79e86, 0x703dcc97), TOBN(0xe66f9b37, 0xe133e215), + TOBN(0xcdf119a6, 0xe39a7a5c), TOBN(0x47c60de3, 0x876f1b61), + TOBN(0x6e405939, 0xd860f1b2), TOBN(0x3e9a1dbc, 0xf5ed4d4a), + TOBN(0x3f23619e, 0xc9b6bcbd), TOBN(0x5ee790cf, 0x734e4497), + TOBN(0xf0a834b1, 0x5bdaf9bb), TOBN(0x02cedda7, 0x4ca295f0), + TOBN(0x4619aa2b, 0xcb8e378c), TOBN(0xe5613244, 0xcc987ea4), + TOBN(0x0bc022cc, 0x76b23a50), TOBN(0x4a2793ad, 0x0a6c21ce), + TOBN(0x38328780, 0x89cac3f5), TOBN(0x29176f1b, 0xcba26d56), + TOBN(0x06296187, 0x4f6f59eb), TOBN(0x86e9bca9, 0x8bdc658e), + TOBN(0x2ca9c4d3, 0x57e30402), TOBN(0x5438b216, 0x516a09bb), + TOBN(0x0a6a063c, 0x7672765a), TOBN(0x37a3ce64, 0x0547b9bf), + TOBN(0x42c099c8, 0x98b1a633), TOBN(0xb5ab800d, 0x05ee6961), + TOBN(0xf1963f59, 0x11a5acd6), TOBN(0xbaee6157, 0x46201063), + TOBN(0x36d9a649, 0xa596210a), TOBN(0xaed04363, 0x1ba7138c), + TOBN(0xcf817d1c, 0xa4a82b76), TOBN(0x5586960e, 0xf3806be9), + TOBN(0x7ab67c89, 0x09dc6bb5), TOBN(0x52ace7a0, 0x114fe7eb), + TOBN(0xcd987618, 0xcbbc9b70), TOBN(0x4f06fd5a, 0x604ca5e1), + TOBN(0x90af14ca, 0x6dbde133), TOBN(0x1afe4322, 0x948a3264), + TOBN(0xa70d2ca6, 0xc44b2c6c), TOBN(0xab726799, 0x0ef87dfe), + TOBN(0x310f64dc, 0x2e696377), TOBN(0x49b42e68, 0x4c8126a0), + TOBN(0x0ea444c3, 0xcea0b176), TOBN(0x53a8ddf7, 0xcb269182), + TOBN(0xf3e674eb, 0xbbba9dcb), TOBN(0x0d2878a8, 0xd8669d33), + TOBN(0x04b935d5, 0xd019b6a3), TOBN(0xbb5cf88e, 0x406f1e46), + TOBN(0xa1912d16, 0x5b57c111), TOBN(0x9803fc21, 0x19ebfd78), + TOBN(0x4f231c9e, 0xc07764a9), TOBN(0xd93286ee, 0xb75bd055), + TOBN(0x83a9457d, 0x8ee6c9de), TOBN(0x04695915, 0x6087ec90), + TOBN(0x14c6dd8a, 0x58d6cd46), TOBN(0x9cb633b5, 0x8e6634d2), + TOBN(0xc1305047, 0xf81bc328), TOBN(0x12ede0e2, 0x26a177e5), + TOBN(0x332cca62, 0x065a6f4f), TOBN(0xc3a47ecd, 0x67be487b), + TOBN(0x741eb187, 0x0f47ed1c), TOBN(0x99e66e58, 0xe7598b14), + TOBN(0x6f0544ca, 0x63d0ff12), TOBN(0xe5efc784, 0xb610a05f), + TOBN(0xf72917b1, 0x7cad7b47), TOBN(0x3ff6ea20, 0xf2cac0c0), + TOBN(0xcc23791b, 0xf21db8b7), TOBN(0x7dac70b1, 0xd7d93565), + TOBN(0x682cda1d, 0x694bdaad), TOBN(0xeb88bb8c, 0x1023516d), + TOBN(0xc4c634b4, 0xdfdbeb1b), TOBN(0x22f5ca72, 0xb4ee4dea), + TOBN(0x1045a368, 0xe6524821), TOBN(0xed9e8a3f, 0x052b18b2), + TOBN(0x9b7f2cb1, 0xb961f49a), TOBN(0x7fee2ec1, 0x7b009670), + TOBN(0x350d8754, 0x22507a6d), TOBN(0x561bd711, 0x4db55f1d), + TOBN(0x4c189ccc, 0x320bbcaf), TOBN(0x568434cf, 0xdf1de48c), + TOBN(0x6af1b00e, 0x0fa8f128), TOBN(0xf0ba9d02, 0x8907583c), + TOBN(0x735a4004, 0x32ff9f60), TOBN(0x3dd8e4b6, 0xc25dcf33), + TOBN(0xf2230f16, 0x42c74cef), TOBN(0xd8117623, 0x013fa8ad), + TOBN(0x36822876, 0xf51fe76e), TOBN(0x8a6811cc, 0x11d62589), + TOBN(0xc3fc7e65, 0x46225718), TOBN(0xb7df2c9f, 0xc82fdbcd), + TOBN(0x3b1d4e52, 0xdd7b205b), TOBN(0xb6959478, 0x47a2e414), + TOBN(0x05e4d793, 0xefa91148), TOBN(0xb47ed446, 0xfd2e9675), + TOBN(0x1a7098b9, 0x04c9d9bf), TOBN(0x661e2881, 0x1b793048), + TOBN(0xb1a16966, 0xb01ee461), TOBN(0xbc521308, 0x2954746f), + TOBN(0xc909a0fc, 0x2477de50), TOBN(0xd80bb41c, 0x7dbd51ef), + TOBN(0xa85be7ec, 0x53294905), TOBN(0x6d465b18, 0x83958f97), + TOBN(0x16f6f330, 0xfb6840fd), TOBN(0xfaaeb214, 0x3401e6c8), + TOBN(0xaf83d30f, 0xccb5b4f8), TOBN(0x22885739, 0x266dec4b), + TOBN(0x51b4367c, 0x7bc467df), TOBN(0x926562e3, 0xd842d27a), + TOBN(0xdfcb6614, 0x0fea14a6), TOBN(0xeb394dae, 0xf2734cd9), + TOBN(0x3eeae5d2, 0x11c0be98), TOBN(0xb1e6ed11, 0x814e8165), + TOBN(0x191086bc, 0xe52bce1c), TOBN(0x14b74cc6, 0xa75a04da), + TOBN(0x63cf1186, 0x8c060985), TOBN(0x071047de, 0x2dbd7f7c), + TOBN(0x4e433b8b, 0xce0942ca), TOBN(0xecbac447, 0xd8fec61d), + TOBN(0x8f0ed0e2, 0xebf3232f), TOBN(0xfff80f9e, 0xc52a2edd), + TOBN(0xad9ab433, 0x75b55fdb), TOBN(0x73ca7820, 0xe42e0c11), + TOBN(0x6dace0a0, 0xe6251b46), TOBN(0x89bc6b5c, 0x4c0d932d), + TOBN(0x3438cd77, 0x095da19a), TOBN(0x2f24a939, 0x8d48bdfb), + TOBN(0x99b47e46, 0x766561b7), TOBN(0x736600e6, 0x0ed0322a), + TOBN(0x06a47cb1, 0x638e1865), TOBN(0x927c1c2d, 0xcb136000), + TOBN(0x29542337, 0x0cc5df69), TOBN(0x99b37c02, 0x09d649a9), + TOBN(0xc5f0043c, 0x6aefdb27), TOBN(0x6cdd9987, 0x1be95c27), + TOBN(0x69850931, 0x390420d2), TOBN(0x299c40ac, 0x0983efa4), + TOBN(0x3a05e778, 0xaf39aead), TOBN(0x84274408, 0x43a45193), + TOBN(0x6bcd0fb9, 0x91a711a0), TOBN(0x461592c8, 0x9f52ab17), + TOBN(0xb49302b4, 0xda3c6ed6), TOBN(0xc51fddc7, 0x330d7067), + TOBN(0x94babeb6, 0xda50d531), TOBN(0x521b840d, 0xa6a7b9da), + TOBN(0x5305151e, 0x404bdc89), TOBN(0x1bcde201, 0xd0d07449), + TOBN(0xf427a78b, 0x3b76a59a), TOBN(0xf84841ce, 0x07791a1b), + TOBN(0xebd314be, 0xbf91ed1c), TOBN(0x8e61d34c, 0xbf172943), + TOBN(0x1d5dc451, 0x5541b892), TOBN(0xb186ee41, 0xfc9d9e54), + TOBN(0x9d9f345e, 0xd5bf610d), TOBN(0x3e7ba65d, 0xf6acca9f), + TOBN(0x9dda787a, 0xa8369486), TOBN(0x09f9dab7, 0x8eb5ba53), + TOBN(0x5afb2033, 0xd6481bc3), TOBN(0x76f4ce30, 0xafa62104), + TOBN(0xa8fa00cf, 0xf4f066b5), TOBN(0x89ab5143, 0x461dafc2), + TOBN(0x44339ed7, 0xa3389998), TOBN(0x2ff862f1, 0xbc214903), + TOBN(0x2c88f985, 0xb05556e3), TOBN(0xcd96058e, 0x3467081e), + TOBN(0x7d6a4176, 0xedc637ea), TOBN(0xe1743d09, 0x36a5acdc), + TOBN(0x66fd72e2, 0x7eb37726), TOBN(0xf7fa264e, 0x1481a037), + TOBN(0x9fbd3bde, 0x45f4aa79), TOBN(0xed1e0147, 0x767c3e22), + TOBN(0x7621f979, 0x82e7abe2), TOBN(0x19eedc72, 0x45f633f8), + TOBN(0xe69b155e, 0x6137bf3a), TOBN(0xa0ad13ce, 0x414ee94e), + TOBN(0x93e3d524, 0x1c0e651a), TOBN(0xab1a6e2a, 0x02ce227e), + TOBN(0xe7af1797, 0x4ab27eca), TOBN(0x245446de, 0xbd444f39), + TOBN(0x59e22a21, 0x56c07613), TOBN(0x43deafce, 0xf4275498), + TOBN(0x10834ccb, 0x67fd0946), TOBN(0xa75841e5, 0x47406edf), + TOBN(0xebd6a677, 0x7b0ac93d), TOBN(0xa6e37b0d, 0x78f5e0d7), + TOBN(0x2516c096, 0x76f5492b), TOBN(0x1e4bf888, 0x9ac05f3a), + TOBN(0xcdb42ce0, 0x4df0ba2b), TOBN(0x935d5cfd, 0x5062341b), + TOBN(0x8a303333, 0x82acac20), TOBN(0x429438c4, 0x5198b00e), + TOBN(0x1d083bc9, 0x049d33fa), TOBN(0x58b82dda, 0x946f67ff), + TOBN(0xac3e2db8, 0x67a1d6a3), TOBN(0x62e6bead, 0x1798aac8), + TOBN(0xfc85980f, 0xde46c58c), TOBN(0xa7f69379, 0x69c8d7be), + TOBN(0x23557927, 0x837b35ec), TOBN(0x06a933d8, 0xe0790c0c), + TOBN(0x827c0e9b, 0x077ff55d), TOBN(0x53977798, 0xbb26e680), + TOBN(0x59530874, 0x1d9cb54f), TOBN(0xcca3f449, 0x4aac53ef), + TOBN(0x11dc5c87, 0xa07eda0f), TOBN(0xc138bccf, 0xfd6400c8), + TOBN(0x549680d3, 0x13e5da72), TOBN(0xc93eed82, 0x4540617e), + TOBN(0xfd3db157, 0x4d0b75c0), TOBN(0x9716eb42, 0x6386075b), + TOBN(0x0639605c, 0x817b2c16), TOBN(0x09915109, 0xf1e4f201), + TOBN(0x35c9a928, 0x5cca6c3b), TOBN(0xb25f7d1a, 0x3505c900), + TOBN(0xeb9f7d20, 0x630480c4), TOBN(0xc3c7b8c6, 0x2a1a501c), + TOBN(0x3f99183c, 0x5a1f8e24), TOBN(0xfdb118fa, 0x9dd255f0), + TOBN(0xb9b18b90, 0xc27f62a6), TOBN(0xe8f732f7, 0x396ec191), + TOBN(0x524a2d91, 0x0be786ab), TOBN(0x5d32adef, 0x0ac5a0f5), + TOBN(0x9b53d4d6, 0x9725f694), TOBN(0x032a76c6, 0x0510ba89), + TOBN(0x840391a3, 0xebeb1544), TOBN(0x44b7b88c, 0x3ed73ac3), + TOBN(0xd24bae7a, 0x256cb8b3), TOBN(0x7ceb151a, 0xe394cb12), + TOBN(0xbd6b66d0, 0x5bc1e6a8), TOBN(0xec70cecb, 0x090f07bf), + TOBN(0x270644ed, 0x7d937589), TOBN(0xee9e1a3d, 0x5f1dccfe), + TOBN(0xb0d40a84, 0x745b98d2), TOBN(0xda429a21, 0x2556ed40), + TOBN(0xf676eced, 0x85148cb9), TOBN(0x5a22d40c, 0xded18936), + TOBN(0x3bc4b9e5, 0x70e8a4ce), TOBN(0xbfd1445b, 0x9eae0379), + TOBN(0xf23f2c0c, 0x1a0bd47e), TOBN(0xa9c0bb31, 0xe1845531), + TOBN(0x9ddc4d60, 0x0a4c3f6b), TOBN(0xbdfaad79, 0x2c15ef44), + TOBN(0xce55a236, 0x7f484acc), TOBN(0x08653ca7, 0x055b1f15), + TOBN(0x2efa8724, 0x538873a3), TOBN(0x09299e5d, 0xace1c7e7), + TOBN(0x07afab66, 0xade332ba), TOBN(0x9be1fdf6, 0x92dd71b7), + TOBN(0xa49b5d59, 0x5758b11c), TOBN(0x0b852893, 0xc8654f40), + TOBN(0xb63ef6f4, 0x52379447), TOBN(0xd4957d29, 0x105e690c), + TOBN(0x7d484363, 0x646559b0), TOBN(0xf4a8273c, 0x49788a8e), + TOBN(0xee406cb8, 0x34ce54a9), TOBN(0x1e1c260f, 0xf86fda9b), + TOBN(0xe150e228, 0xcf6a4a81), TOBN(0x1fa3b6a3, 0x1b488772), + TOBN(0x1e6ff110, 0xc5a9c15b), TOBN(0xc6133b91, 0x8ad6aa47), + TOBN(0x8ac5d55c, 0x9dffa978), TOBN(0xba1d1c1d, 0x5f3965f2), + TOBN(0xf969f4e0, 0x7732b52f), TOBN(0xfceecdb5, 0xa5172a07), + TOBN(0xb0120a5f, 0x10f2b8f5), TOBN(0xc83a6cdf, 0x5c4c2f63), + TOBN(0x4d47a491, 0xf8f9c213), TOBN(0xd9e1cce5, 0xd3f1bbd5), + TOBN(0x0d91bc7c, 0xaba7e372), TOBN(0xfcdc74c8, 0xdfd1a2db), + TOBN(0x05efa800, 0x374618e5), TOBN(0x11216969, 0x15a7925e), + TOBN(0xd4c89823, 0xf6021c5d), TOBN(0x880d5e84, 0xeff14423), + TOBN(0x6523bc5a, 0x6dcd1396), TOBN(0xd1acfdfc, 0x113c978b), + TOBN(0xb0c164e8, 0xbbb66840), TOBN(0xf7f4301e, 0x72b58459), + TOBN(0xc29ad4a6, 0xa638e8ec), TOBN(0xf5ab8961, 0x46b78699), + TOBN(0x9dbd7974, 0x0e954750), TOBN(0x0121de88, 0x64f9d2c6), + TOBN(0x2e597b42, 0xd985232e), TOBN(0x55b6c3c5, 0x53451777), + TOBN(0xbb53e547, 0x519cb9fb), TOBN(0xf134019f, 0x8428600d), + TOBN(0x5a473176, 0xe081791a), TOBN(0x2f3e2263, 0x35fb0c08), + TOBN(0xb28c3017, 0x73d273b0), TOBN(0xccd21076, 0x7721ef9a), + TOBN(0x054cc292, 0xb650dc39), TOBN(0x662246de, 0x6188045e), + TOBN(0x904b52fa, 0x6b83c0d1), TOBN(0xa72df267, 0x97e9cd46), + TOBN(0x886b43cd, 0x899725e4), TOBN(0x2b651688, 0xd849ff22), + TOBN(0x60479b79, 0x02f34533), TOBN(0x5e354c14, 0x0c77c148), + TOBN(0xb4bb7581, 0xa8537c78), TOBN(0x188043d7, 0xefe1495f), + TOBN(0x9ba12f42, 0x8c1d5026), TOBN(0x2e0c8a26, 0x93d4aaab), + TOBN(0xbdba7b8b, 0xaa57c450), TOBN(0x140c9ad6, 0x9bbdafef), + TOBN(0x2067aa42, 0x25ac0f18), TOBN(0xf7b1295b, 0x04d1fbf3), + TOBN(0x14829111, 0xa4b04824), TOBN(0x2ce3f192, 0x33bd5e91), + TOBN(0x9c7a1d55, 0x8f2e1b72), TOBN(0xfe932286, 0x302aa243), + TOBN(0x497ca7b4, 0xd4be9554), TOBN(0xb8e821b8, 0xe0547a6e), + TOBN(0xfb2838be, 0x67e573e0), TOBN(0x05891db9, 0x4084c44b), + TOBN(0x91311373, 0x96c1c2c5), TOBN(0x6aebfa3f, 0xd958444b), + TOBN(0xac9cdce9, 0xe56e55c1), TOBN(0x7148ced3, 0x2caa46d0), + TOBN(0x2e10c7ef, 0xb61fe8eb), TOBN(0x9fd835da, 0xff97cf4d),} + , + {TOBN(0xa36da109, 0x081e9387), TOBN(0xfb9780d7, 0x8c935828), + TOBN(0xd5940332, 0xe540b015), TOBN(0xc9d7b51b, 0xe0f466fa), + TOBN(0xfaadcd41, 0xd6d9f671), TOBN(0xba6c1e28, 0xb1a2ac17), + TOBN(0x066a7833, 0xed201e5f), TOBN(0x19d99719, 0xf90f462b), + TOBN(0xf431f462, 0x060b5f61), TOBN(0xa56f46b4, 0x7bd057c2), + TOBN(0x348dca6c, 0x47e1bf65), TOBN(0x9a38783e, 0x41bcf1ff), + TOBN(0x7a5d33a9, 0xda710718), TOBN(0x5a779987, 0x2e0aeaf6), + TOBN(0xca87314d, 0x2d29d187), TOBN(0xfa0edc3e, 0xc687d733), + TOBN(0x9df33621, 0x6a31e09b), TOBN(0xde89e44d, 0xc1350e35), + TOBN(0x29214871, 0x4ca0cf52), TOBN(0xdf379672, 0x0b88a538), + TOBN(0xc92a510a, 0x2591d61b), TOBN(0x79aa87d7, 0x585b447b), + TOBN(0xf67db604, 0xe5287f77), TOBN(0x1697c8bf, 0x5efe7a80), + TOBN(0x1c894849, 0xcb198ac7), TOBN(0xa884a93d, 0x0f264665), + TOBN(0x2da964ef, 0x9b200678), TOBN(0x3c351b87, 0x009834e6), + TOBN(0xafb2ef9f, 0xe2c4b44b), TOBN(0x580f6c47, 0x3326790c), + TOBN(0xb8480521, 0x0b02264a), TOBN(0x8ba6f9e2, 0x42a194e2), + TOBN(0xfc87975f, 0x8fb54738), TOBN(0x35160788, 0x27c3ead3), + TOBN(0x834116d2, 0xb74a085a), TOBN(0x53c99a73, 0xa62fe996), + TOBN(0x87585be0, 0x5b81c51b), TOBN(0x925bafa8, 0xbe0852b7), + TOBN(0x76a4fafd, 0xa84d19a7), TOBN(0x39a45982, 0x585206d4), + TOBN(0x499b6ab6, 0x5eb03c0e), TOBN(0xf19b7954, 0x72bc3fde), + TOBN(0xa86b5b9c, 0x6e3a80d2), TOBN(0xe4377508, 0x6d42819f), + TOBN(0xc1663650, 0xbb3ee8a3), TOBN(0x75eb14fc, 0xb132075f), + TOBN(0xa8ccc906, 0x7ad834f6), TOBN(0xea6a2474, 0xe6e92ffd), + TOBN(0x9d72fd95, 0x0f8d6758), TOBN(0xcb84e101, 0x408c07dd), + TOBN(0xb9114bfd, 0xa5e23221), TOBN(0x358b5fe2, 0xe94e742c), + TOBN(0x1c0577ec, 0x95f40e75), TOBN(0xf0155451, 0x3d73f3d6), + TOBN(0x9d55cd67, 0xbd1b9b66), TOBN(0x63e86e78, 0xaf8d63c7), + TOBN(0x39d934ab, 0xd3c095f1), TOBN(0x04b261be, 0xe4b76d71), + TOBN(0x1d2e6970, 0xe73e6984), TOBN(0x879fb23b, 0x5e5fcb11), + TOBN(0x11506c72, 0xdfd75490), TOBN(0x3a97d085, 0x61bcf1c1), + TOBN(0x43201d82, 0xbf5e7007), TOBN(0x7f0ac52f, 0x798232a7), + TOBN(0x2715cbc4, 0x6eb564d4), TOBN(0x8d6c752c, 0x9e570e29), + TOBN(0xf80247c8, 0x9ef5fd5d), TOBN(0xc3c66b46, 0xd53eb514), + TOBN(0x9666b401, 0x0f87de56), TOBN(0xce62c06f, 0xc6c603b5), + TOBN(0xae7b4c60, 0x7e4fc942), TOBN(0x38ac0b77, 0x663a9c19), + TOBN(0xcb4d20ee, 0x4b049136), TOBN(0x8b63bf12, 0x356a4613), + TOBN(0x1221aef6, 0x70e08128), TOBN(0xe62d8c51, 0x4acb6b16), + TOBN(0x71f64a67, 0x379e7896), TOBN(0xb25237a2, 0xcafd7fa5), + TOBN(0xf077bd98, 0x3841ba6a), TOBN(0xc4ac0244, 0x3cd16e7e), + TOBN(0x548ba869, 0x21fea4ca), TOBN(0xd36d0817, 0xf3dfdac1), + TOBN(0x09d8d71f, 0xf4685faf), TOBN(0x8eff66be, 0xc52c459a), + TOBN(0x182faee7, 0x0b57235e), TOBN(0xee3c39b1, 0x0106712b), + TOBN(0x5107331f, 0xc0fcdcb0), TOBN(0x669fb9dc, 0xa51054ba), + TOBN(0xb25101fb, 0x319d7682), TOBN(0xb0293129, 0x0a982fee), + TOBN(0x51c1c9b9, 0x0261b344), TOBN(0x0e008c5b, 0xbfd371fa), + TOBN(0xd866dd1c, 0x0278ca33), TOBN(0x666f76a6, 0xe5aa53b1), + TOBN(0xe5cfb779, 0x6013a2cf), TOBN(0x1d3a1aad, 0xa3521836), + TOBN(0xcedd2531, 0x73faa485), TOBN(0xc8ee6c4f, 0xc0a76878), + TOBN(0xddbccfc9, 0x2a11667d), TOBN(0x1a418ea9, 0x1c2f695a), + TOBN(0xdb11bd92, 0x51f73971), TOBN(0x3e4b3c82, 0xda2ed89f), + TOBN(0x9a44f3f4, 0xe73e0319), TOBN(0xd1e3de0f, 0x303431af), + TOBN(0x3c5604ff, 0x50f75f9c), TOBN(0x1d8eddf3, 0x7e752b22), + TOBN(0x0ef074dd, 0x3c9a1118), TOBN(0xd0ffc172, 0xccb86d7b), + TOBN(0xabd1ece3, 0x037d90f2), TOBN(0xe3f307d6, 0x6055856c), + TOBN(0x422f9328, 0x7e4c6daf), TOBN(0x902aac66, 0x334879a0), + TOBN(0xb6a1e7bf, 0x94cdfade), TOBN(0x6c97e1ed, 0x7fc6d634), + TOBN(0x662ad24d, 0xa2fb63f8), TOBN(0xf81be1b9, 0xa5928405), + TOBN(0x86d765e4, 0xd14b4206), TOBN(0xbecc2e0e, 0x8fa0db65), + TOBN(0xa28838e0, 0xb17fc76c), TOBN(0xe49a602a, 0xe37cf24e), + TOBN(0x76b4131a, 0x567193ec), TOBN(0xaf3c305a, 0xe5f6e70b), + TOBN(0x9587bd39, 0x031eebdd), TOBN(0x5709def8, 0x71bbe831), + TOBN(0x57059983, 0x0eb2b669), TOBN(0x4d80ce1b, 0x875b7029), + TOBN(0x838a7da8, 0x0364ac16), TOBN(0x2f431d23, 0xbe1c83ab), + TOBN(0xe56812a6, 0xf9294dd3), TOBN(0xb448d01f, 0x9b4b0d77), + TOBN(0xf3ae6061, 0x04e8305c), TOBN(0x2bead645, 0x94d8c63e), + TOBN(0x0a85434d, 0x84fd8b07), TOBN(0x537b983f, 0xf7a9dee5), + TOBN(0xedcc5f18, 0xef55bd85), TOBN(0x2041af62, 0x21c6cf8b), + TOBN(0x8e52874c, 0xb940c71e), TOBN(0x211935a9, 0xdb5f4b3a), + TOBN(0x94350492, 0x301b1dc3), TOBN(0x33d2646d, 0x29958620), + TOBN(0x16b0d64b, 0xef911404), TOBN(0x9d1f25ea, 0x9a3c5ef4), + TOBN(0x20f200eb, 0x4a352c78), TOBN(0x43929f2c, 0x4bd0b428), + TOBN(0xa5656667, 0xc7196e29), TOBN(0x7992c2f0, 0x9391be48), + TOBN(0xaaa97cbd, 0x9ee0cd6e), TOBN(0x51b0310c, 0x3dc8c9bf), + TOBN(0x237f8acf, 0xdd9f22cb), TOBN(0xbb1d81a1, 0xb585d584), + TOBN(0x8d5d85f5, 0x8c416388), TOBN(0x0d6e5a5a, 0x42fe474f), + TOBN(0xe7812766, 0x38235d4e), TOBN(0x1c62bd67, 0x496e3298), + TOBN(0x8378660c, 0x3f175bc8), TOBN(0x4d04e189, 0x17afdd4d), + TOBN(0x32a81601, 0x85a8068c), TOBN(0xdb58e4e1, 0x92b29a85), + TOBN(0xe8a65b86, 0xc70d8a3b), TOBN(0x5f0e6f4e, 0x98a0403b), + TOBN(0x08129684, 0x69ed2370), TOBN(0x34dc30bd, 0x0871ee26), + TOBN(0x3a5ce948, 0x7c9c5b05), TOBN(0x7d487b80, 0x43a90c87), + TOBN(0x4089ba37, 0xdd0e7179), TOBN(0x45f80191, 0xb4041811), + TOBN(0x1c3e1058, 0x98747ba5), TOBN(0x98c4e13a, 0x6e1ae592), + TOBN(0xd44636e6, 0xe82c9f9e), TOBN(0x711db87c, 0xc33a1043), + TOBN(0x6f431263, 0xaa8aec05), TOBN(0x43ff120d, 0x2744a4aa), + TOBN(0xd3bd892f, 0xae77779b), TOBN(0xf0fe0cc9, 0x8cdc9f82), + TOBN(0xca5f7fe6, 0xf1c5b1bc), TOBN(0xcc63a682, 0x44929a72), + TOBN(0xc7eaba0c, 0x09dbe19a), TOBN(0x2f3585ad, 0x6b5c73c2), + TOBN(0x8ab8924b, 0x0ae50c30), TOBN(0x17fcd27a, 0x638b30ba), + TOBN(0xaf414d34, 0x10b3d5a5), TOBN(0x09c107d2, 0x2a9accf1), + TOBN(0x15dac49f, 0x946a6242), TOBN(0xaec3df2a, 0xd707d642), + TOBN(0x2c2492b7, 0x3f894ae0), TOBN(0xf59df3e5, 0xb75f18ce), + TOBN(0x7cb740d2, 0x8f53cad0), TOBN(0x3eb585fb, 0xc4f01294), + TOBN(0x17da0c86, 0x32c7f717), TOBN(0xeb8c795b, 0xaf943f4c), + TOBN(0x4ee23fb5, 0xf67c51d2), TOBN(0xef187575, 0x68889949), + TOBN(0xa6b4bdb2, 0x0389168b), TOBN(0xc4ecd258, 0xea577d03), + TOBN(0x3a63782b, 0x55743082), TOBN(0x6f678f4c, 0xc72f08cd), + TOBN(0x553511cf, 0x65e58dd8), TOBN(0xd53b4e3e, 0xd402c0cd), + TOBN(0x37de3e29, 0xa037c14c), TOBN(0x86b6c516, 0xc05712aa), + TOBN(0x2834da3e, 0xb38dff6f), TOBN(0xbe012c52, 0xea636be8), + TOBN(0x292d238c, 0x61dd37f8), TOBN(0x0e54523f, 0x8f8142db), + TOBN(0xe31eb436, 0x036a05d8), TOBN(0x83e3cdff, 0x1e93c0ff), + TOBN(0x3fd2fe0f, 0x50821ddf), TOBN(0xc8e19b0d, 0xff9eb33b), + TOBN(0xc8cc943f, 0xb569a5fe), TOBN(0xad0090d4, 0xd4342d75), + TOBN(0x82090b4b, 0xcaeca000), TOBN(0xca39687f, 0x1bd410eb), + TOBN(0xe7bb0df7, 0x65959d77), TOBN(0x39d78218, 0x9c964999), + TOBN(0xd87f62e8, 0xb2415451), TOBN(0xe5efb774, 0xbed76108), + TOBN(0x3ea011a4, 0xe822f0d0), TOBN(0xbc647ad1, 0x5a8704f8), + TOBN(0xbb315b35, 0x50c6820f), TOBN(0x863dec3d, 0xb7e76bec), + TOBN(0x01ff5d3a, 0xf017bfc7), TOBN(0x20054439, 0x976b8229), + TOBN(0x067fca37, 0x0bbd0d3b), TOBN(0xf63dde64, 0x7f5e3d0f), + TOBN(0x22dbefb3, 0x2a4c94e9), TOBN(0xafbff0fe, 0x96f8278a), + TOBN(0x80aea0b1, 0x3503793d), TOBN(0xb2238029, 0x5f06cd29), + TOBN(0x65703e57, 0x8ec3feca), TOBN(0x06c38314, 0x393e7053), + TOBN(0xa0b751eb, 0x7c6734c4), TOBN(0xd2e8a435, 0xc59f0f1e), + TOBN(0x147d9052, 0x5e9ca895), TOBN(0x2f4dd31e, 0x972072df), + TOBN(0xa16fda8e, 0xe6c6755c), TOBN(0xc66826ff, 0xcf196558), + TOBN(0x1f1a76a3, 0x0cf43895), TOBN(0xa9d604e0, 0x83c3097b), + TOBN(0xe1908309, 0x66390e0e), TOBN(0xa50bf753, 0xb3c85eff), + TOBN(0x0696bdde, 0xf6a70251), TOBN(0x548b801b, 0x3c6ab16a), + TOBN(0x37fcf704, 0xa4d08762), TOBN(0x090b3def, 0xdff76c4e), + TOBN(0x87e8cb89, 0x69cb9158), TOBN(0x44a90744, 0x995ece43), + TOBN(0xf85395f4, 0x0ad9fbf5), TOBN(0x49b0f6c5, 0x4fb0c82d), + TOBN(0x75d9bc15, 0xadf7cccf), TOBN(0x81a3e5d6, 0xdfa1e1b0), + TOBN(0x8c39e444, 0x249bc17e), TOBN(0xf37dccb2, 0x8ea7fd43), + TOBN(0xda654873, 0x907fba12), TOBN(0x35daa6da, 0x4a372904), + TOBN(0x0564cfc6, 0x6283a6c5), TOBN(0xd09fa4f6, 0x4a9395bf), + TOBN(0x688e9ec9, 0xaeb19a36), TOBN(0xd913f1ce, 0xc7bfbfb4), + TOBN(0x797b9a3c, 0x61c2faa6), TOBN(0x2f979bec, 0x6a0a9c12), + TOBN(0xb5969d0f, 0x359679ec), TOBN(0xebcf523d, 0x079b0460), + TOBN(0xfd6b0008, 0x10fab870), TOBN(0x3f2edcda, 0x9373a39c), + TOBN(0x0d64f9a7, 0x6f568431), TOBN(0xf848c27c, 0x02f8898c), + TOBN(0xf418ade1, 0x260b5bd5), TOBN(0xc1f3e323, 0x6973dee8), + TOBN(0x46e9319c, 0x26c185dd), TOBN(0x6d85b7d8, 0x546f0ac4), + TOBN(0x427965f2, 0x247f9d57), TOBN(0xb519b636, 0xb0035f48), + TOBN(0x6b6163a9, 0xab87d59c), TOBN(0xff9f58c3, 0x39caaa11), + TOBN(0x4ac39cde, 0x3177387b), TOBN(0x5f6557c2, 0x873e77f9), + TOBN(0x67504006, 0x36a83041), TOBN(0x9b1c96ca, 0x75ef196c), + TOBN(0xf34283de, 0xb08c7940), TOBN(0x7ea09644, 0x1128c316), + TOBN(0xb510b3b5, 0x6aa39dff), TOBN(0x59b43da2, 0x9f8e4d8c), + TOBN(0xa8ce31fd, 0x9e4c4b9f), TOBN(0x0e20be26, 0xc1303c01), + TOBN(0x18187182, 0xe8ee47c9), TOBN(0xd9687cdb, 0x7db98101), + TOBN(0x7a520e4d, 0xa1e14ff6), TOBN(0x429808ba, 0x8836d572), + TOBN(0xa37ca60d, 0x4944b663), TOBN(0xf901f7a9, 0xa3f91ae5), + TOBN(0xe4e3e76e, 0x9e36e3b1), TOBN(0x9aa219cf, 0x29d93250), + TOBN(0x347fe275, 0x056a2512), TOBN(0xa4d643d9, 0xde65d95c), + TOBN(0x9669d396, 0x699fc3ed), TOBN(0xb598dee2, 0xcf8c6bbe), + TOBN(0x682ac1e5, 0xdda9e5c6), TOBN(0x4e0d3c72, 0xcaa9fc95), + TOBN(0x17faaade, 0x772bea44), TOBN(0x5ef8428c, 0xab0009c8), + TOBN(0xcc4ce47a, 0x460ff016), TOBN(0xda6d12bf, 0x725281cb), + TOBN(0x44c67848, 0x0223aad2), TOBN(0x6e342afa, 0x36256e28), + TOBN(0x1400bb0b, 0x93a37c04), TOBN(0x62b1bc9b, 0xdd10bd96), + TOBN(0x7251adeb, 0x0dac46b7), TOBN(0x7d33b92e, 0x7be4ef51), + TOBN(0x28b2a94b, 0xe61fa29a), TOBN(0x4b2be13f, 0x06422233), + TOBN(0x36d6d062, 0x330d8d37), TOBN(0x5ef80e1e, 0xb28ca005), + TOBN(0x174d4699, 0x6d16768e), TOBN(0x9fc4ff6a, 0x628bf217), + TOBN(0x77705a94, 0x154e490d), TOBN(0x9d96dd28, 0x8d2d997a), + TOBN(0x77e2d9d8, 0xce5d72c4), TOBN(0x9d06c5a4, 0xc11c714f), + TOBN(0x02aa5136, 0x79e4a03e), TOBN(0x1386b3c2, 0x030ff28b), + TOBN(0xfe82e8a6, 0xfb283f61), TOBN(0x7df203e5, 0xf3abc3fb), + TOBN(0xeec7c351, 0x3a4d3622), TOBN(0xf7d17dbf, 0xdf762761), + TOBN(0xc3956e44, 0x522055f0), TOBN(0xde3012db, 0x8fa748db), + TOBN(0xca9fcb63, 0xbf1dcc14), TOBN(0xa56d9dcf, 0xbe4e2f3a), + TOBN(0xb86186b6, 0x8bcec9c2), TOBN(0x7cf24df9, 0x680b9f06), + TOBN(0xc46b45ea, 0xc0d29281), TOBN(0xfff42bc5, 0x07b10e12), + TOBN(0x12263c40, 0x4d289427), TOBN(0x3d5f1899, 0xb4848ec4), + TOBN(0x11f97010, 0xd040800c), TOBN(0xb4c5f529, 0x300feb20), + TOBN(0xcc543f8f, 0xde94fdcb), TOBN(0xe96af739, 0xc7c2f05e), + TOBN(0xaa5e0036, 0x882692e1), TOBN(0x09c75b68, 0x950d4ae9), + TOBN(0x62f63df2, 0xb5932a7a), TOBN(0x2658252e, 0xde0979ad), + TOBN(0x2a19343f, 0xb5e69631), TOBN(0x718c7501, 0x525b666b), + TOBN(0x26a42d69, 0xea40dc3a), TOBN(0xdc84ad22, 0xaecc018f), + TOBN(0x25c36c7b, 0x3270f04a), TOBN(0x46ba6d47, 0x50fa72ed), + TOBN(0x6c37d1c5, 0x93e58a8e), TOBN(0xa2394731, 0x120c088c), + TOBN(0xc3be4263, 0xcb6e86da), TOBN(0x2c417d36, 0x7126d038), + TOBN(0x5b70f9c5, 0x8b6f8efa), TOBN(0x671a2faa, 0x37718536), + TOBN(0xd3ced3c6, 0xb539c92b), TOBN(0xe56f1bd9, 0xa31203c2), + TOBN(0x8b096ec4, 0x9ff3c8eb), TOBN(0x2deae432, 0x43491cea), + TOBN(0x2465c6eb, 0x17943794), TOBN(0x5d267e66, 0x20586843), + TOBN(0x9d3d116d, 0xb07159d0), TOBN(0xae07a67f, 0xc1896210), + TOBN(0x8fc84d87, 0xbb961579), TOBN(0x30009e49, 0x1c1f8dd6), + TOBN(0x8a8caf22, 0xe3132819), TOBN(0xcffa197c, 0xf23ab4ff), + TOBN(0x58103a44, 0x205dd687), TOBN(0x57b796c3, 0x0ded67a2), + TOBN(0x0b9c3a6c, 0xa1779ad7), TOBN(0xa33cfe2e, 0x357c09c5), + TOBN(0x2ea29315, 0x3db4a57e), TOBN(0x91959695, 0x8ebeb52e), + TOBN(0x118db9a6, 0xe546c879), TOBN(0x8e996df4, 0x6295c8d6), + TOBN(0xdd990484, 0x55ec806b), TOBN(0x24f291ca, 0x165c1035), + TOBN(0xcca523bb, 0x440e2229), TOBN(0x324673a2, 0x73ef4d04), + TOBN(0xaf3adf34, 0x3e11ec39), TOBN(0x6136d7f1, 0xdc5968d3), + TOBN(0x7a7b2899, 0xb053a927), TOBN(0x3eaa2661, 0xae067ecd), + TOBN(0x8549b9c8, 0x02779cd9), TOBN(0x061d7940, 0xc53385ea), + TOBN(0x3e0ba883, 0xf06d18bd), TOBN(0x4ba6de53, 0xb2700843), + TOBN(0xb966b668, 0x591a9e4d), TOBN(0x93f67567, 0x7f4fa0ed), + TOBN(0x5a02711b, 0x4347237b), TOBN(0xbc041e2f, 0xe794608e), + TOBN(0x55af10f5, 0x70f73d8c), TOBN(0xd2d4d4f7, 0xbb7564f7), + TOBN(0xd7d27a89, 0xb3e93ce7), TOBN(0xf7b5a875, 0x5d3a2c1b), + TOBN(0xb29e68a0, 0x255b218a), TOBN(0xb533837e, 0x8af76754), + TOBN(0xd1b05a73, 0x579fab2e), TOBN(0xb41055a1, 0xecd74385), + TOBN(0xb2369274, 0x445e9115), TOBN(0x2972a7c4, 0xf520274e), + TOBN(0x6c08334e, 0xf678e68a), TOBN(0x4e4160f0, 0x99b057ed), + TOBN(0x3cfe11b8, 0x52ccb69a), TOBN(0x2fd1823a, 0x21c8f772), + TOBN(0xdf7f072f, 0x3298f055), TOBN(0x8c0566f9, 0xfec74a6e), + TOBN(0xe549e019, 0x5bb4d041), TOBN(0x7c3930ba, 0x9208d850), + TOBN(0xe07141fc, 0xaaa2902b), TOBN(0x539ad799, 0xe4f69ad3), + TOBN(0xa6453f94, 0x813f9ffd), TOBN(0xc58d3c48, 0x375bc2f7), + TOBN(0xb3326fad, 0x5dc64e96), TOBN(0x3aafcaa9, 0xb240e354), + TOBN(0x1d1b0903, 0xaca1e7a9), TOBN(0x4ceb9767, 0x1211b8a0), + TOBN(0xeca83e49, 0xe32a858e), TOBN(0x4c32892e, 0xae907bad), + TOBN(0xd5b42ab6, 0x2eb9b494), TOBN(0x7fde3ee2, 0x1eabae1b), + TOBN(0x13b5ab09, 0xcaf54957), TOBN(0xbfb028be, 0xe5f5d5d5), + TOBN(0x928a0650, 0x2003e2c0), TOBN(0x90793aac, 0x67476843), + TOBN(0x5e942e79, 0xc81710a0), TOBN(0x557e4a36, 0x27ccadd4), + TOBN(0x72a2bc56, 0x4bcf6d0c), TOBN(0x09ee5f43, 0x26d7b80c), + TOBN(0x6b70dbe9, 0xd4292f19), TOBN(0x56f74c26, 0x63f16b18), + TOBN(0xc23db0f7, 0x35fbb42a), TOBN(0xb606bdf6, 0x6ae10040), + TOBN(0x1eb15d4d, 0x044573ac), TOBN(0x7dc3cf86, 0x556b0ba4), + TOBN(0x97af9a33, 0xc60df6f7), TOBN(0x0b1ef85c, 0xa716ce8c), + TOBN(0x2922f884, 0xc96958be), TOBN(0x7c32fa94, 0x35690963), + TOBN(0x2d7f667c, 0xeaa00061), TOBN(0xeaaf7c17, 0x3547365c), + TOBN(0x1eb4de46, 0x87032d58), TOBN(0xc54f3d83, 0x5e2c79e0), + TOBN(0x07818df4, 0x5d04ef23), TOBN(0x55faa9c8, 0x673d41b4), + TOBN(0xced64f6f, 0x89b95355), TOBN(0x4860d2ea, 0xb7415c84), + TOBN(0x5fdb9bd2, 0x050ebad3), TOBN(0xdb53e0cc, 0x6685a5bf), + TOBN(0xb830c031, 0x9feb6593), TOBN(0xdd87f310, 0x6accff17), + TOBN(0x2303ebab, 0x9f555c10), TOBN(0x94603695, 0x287e7065), + TOBN(0xf88311c3, 0x2e83358c), TOBN(0x508dd9b4, 0xeefb0178), + TOBN(0x7ca23706, 0x2dba8652), TOBN(0x62aac5a3, 0x0047abe5), + TOBN(0x9a61d2a0, 0x8b1ea7b3), TOBN(0xd495ab63, 0xae8b1485), + TOBN(0x38740f84, 0x87052f99), TOBN(0x178ebe5b, 0xb2974eea), + TOBN(0x030bbcca, 0x5b36d17f), TOBN(0xb5e4cce3, 0xaaf86eea), + TOBN(0xb51a0220, 0x68f8e9e0), TOBN(0xa4348796, 0x09eb3e75), + TOBN(0xbe592309, 0xeef1a752), TOBN(0x5d7162d7, 0x6f2aa1ed), + TOBN(0xaebfb5ed, 0x0f007dd2), TOBN(0x255e14b2, 0xc89edd22), + TOBN(0xba85e072, 0x0303b697), TOBN(0xc5d17e25, 0xf05720ff), + TOBN(0x02b58d6e, 0x5128ebb6), TOBN(0x2c80242d, 0xd754e113), + TOBN(0x919fca5f, 0xabfae1ca), TOBN(0x937afaac, 0x1a21459b), + TOBN(0x9e0ca91c, 0x1f66a4d2), TOBN(0x194cc7f3, 0x23ec1331), + TOBN(0xad25143a, 0x8aa11690), TOBN(0xbe40ad8d, 0x09b59e08), + TOBN(0x37d60d9b, 0xe750860a), TOBN(0x6c53b008, 0xc6bf434c), + TOBN(0xb572415d, 0x1356eb80), TOBN(0xb8bf9da3, 0x9578ded8), + TOBN(0x22658e36, 0x5e8fb38b), TOBN(0x9b70ce22, 0x5af8cb22), + TOBN(0x7c00018a, 0x829a8180), TOBN(0x84329f93, 0xb81ed295), + TOBN(0x7c343ea2, 0x5f3cea83), TOBN(0x38f8655f, 0x67586536), + TOBN(0xa661a0d0, 0x1d3ec517), TOBN(0x98744652, 0x512321ae), + TOBN(0x084ca591, 0xeca92598), TOBN(0xa9bb9dc9, 0x1dcb3feb), + TOBN(0x14c54355, 0x78b4c240), TOBN(0x5ed62a3b, 0x610cafdc), + TOBN(0x07512f37, 0x1b38846b), TOBN(0x571bb70a, 0xb0e38161), + TOBN(0xb556b95b, 0x2da705d2), TOBN(0x3ef8ada6, 0xb1a08f98), + TOBN(0x85302ca7, 0xddecfbe5), TOBN(0x0e530573, 0x943105cd), + TOBN(0x60554d55, 0x21a9255d), TOBN(0x63a32fa1, 0xf2f3802a), + TOBN(0x35c8c5b0, 0xcd477875), TOBN(0x97f458ea, 0x6ad42da1), + TOBN(0x832d7080, 0xeb6b242d), TOBN(0xd30bd023, 0x3b71e246), + TOBN(0x7027991b, 0xbe31139d), TOBN(0x68797e91, 0x462e4e53), + TOBN(0x423fe20a, 0x6b4e185a), TOBN(0x82f2c67e, 0x42d9b707), + TOBN(0x25c81768, 0x4cf7811b), TOBN(0xbd53005e, 0x045bb95d),} + , + {TOBN(0xe5f649be, 0x9d8e68fd), TOBN(0xdb0f0533, 0x1b044320), + TOBN(0xf6fde9b3, 0xe0c33398), TOBN(0x92f4209b, 0x66c8cfae), + TOBN(0xe9d1afcc, 0x1a739d4b), TOBN(0x09aea75f, 0xa28ab8de), + TOBN(0x14375fb5, 0xeac6f1d0), TOBN(0x6420b560, 0x708f7aa5), + TOBN(0x9eae499c, 0x6254dc41), TOBN(0x7e293924, 0x7a837e7e), + TOBN(0x74aec08c, 0x090524a7), TOBN(0xf82b9219, 0x8d6f55f2), + TOBN(0x493c962e, 0x1402cec5), TOBN(0x9f17ca17, 0xfa2f30e7), + TOBN(0xbcd783e8, 0xe9b879cb), TOBN(0xea3d8c14, 0x5a6f145f), + TOBN(0xdede15e7, 0x5e0dee6e), TOBN(0x74f24872, 0xdc628aa2), + TOBN(0xd3e9c4fe, 0x7861bb93), TOBN(0x56d4822a, 0x6187b2e0), + TOBN(0xb66417cf, 0xc59826f9), TOBN(0xca260969, 0x2408169e), + TOBN(0xedf69d06, 0xc79ef885), TOBN(0x00031f8a, 0xdc7d138f), + TOBN(0x103c46e6, 0x0ebcf726), TOBN(0x4482b831, 0x6231470e), + TOBN(0x6f6dfaca, 0x487c2109), TOBN(0x2e0ace97, 0x62e666ef), + TOBN(0x3246a9d3, 0x1f8d1f42), TOBN(0x1b1e83f1, 0x574944d2), + TOBN(0x13dfa63a, 0xa57f334b), TOBN(0x0cf8daed, 0x9f025d81), + TOBN(0x30d78ea8, 0x00ee11c1), TOBN(0xeb053cd4, 0xb5e3dd75), + TOBN(0x9b65b13e, 0xd58c43c5), TOBN(0xc3ad49bd, 0xbd151663), + TOBN(0x99fd8e41, 0xb6427990), TOBN(0x12cf15bd, 0x707eae1e), + TOBN(0x29ad4f1b, 0x1aabb71e), TOBN(0x5143e74d, 0x07545d0e), + TOBN(0x30266336, 0xc88bdee1), TOBN(0x25f29306, 0x5876767c), + TOBN(0x9c078571, 0xc6731996), TOBN(0xc88690b2, 0xed552951), + TOBN(0x274f2c2d, 0x852705b4), TOBN(0xb0bf8d44, 0x4e09552d), + TOBN(0x7628beeb, 0x986575d1), TOBN(0x407be238, 0x7f864651), + TOBN(0x0e5e3049, 0xa639fc6b), TOBN(0xe75c35d9, 0x86003625), + TOBN(0x0cf35bd8, 0x5dcc1646), TOBN(0x8bcaced2, 0x6c26273a), + TOBN(0xe22ecf1d, 0xb5536742), TOBN(0x013dd897, 0x1a9e068b), + TOBN(0x17f411cb, 0x8a7909c5), TOBN(0x5757ac98, 0x861dd506), + TOBN(0x85de1f0d, 0x1e935abb), TOBN(0xdefd10b4, 0x154de37a), + TOBN(0xb8d9e392, 0x369cebb5), TOBN(0x54d5ef9b, 0x761324be), + TOBN(0x4d6341ba, 0x74f17e26), TOBN(0xc0a0e3c8, 0x78c1dde4), + TOBN(0xa6d77581, 0x87d918fd), TOBN(0x66876015, 0x02ca3a13), + TOBN(0xc7313e9c, 0xf36658f0), TOBN(0xc433ef1c, 0x71f8057e), + TOBN(0x85326246, 0x1b6a835a), TOBN(0xc8f05398, 0x7c86394c), + TOBN(0xff398cdf, 0xe983c4a1), TOBN(0xbf5e8162, 0x03b7b931), + TOBN(0x93193c46, 0xb7b9045b), TOBN(0x1e4ebf5d, 0xa4a6e46b), + TOBN(0xf9942a60, 0x43a24fe7), TOBN(0x29c1191e, 0xffb3492b), + TOBN(0x9f662449, 0x902fde05), TOBN(0xc792a7ac, 0x6713c32d), + TOBN(0x2fd88ad8, 0xb737982c), TOBN(0x7e3a0319, 0xa21e60e3), + TOBN(0x09b0de44, 0x7383591a), TOBN(0x6df141ee, 0x8310a456), + TOBN(0xaec1a039, 0xe6d6f471), TOBN(0x14b2ba0f, 0x1198d12e), + TOBN(0xebc1a160, 0x3aeee5ac), TOBN(0x401f4836, 0xe0b964ce), + TOBN(0x2ee43796, 0x4fd03f66), TOBN(0x3fdb4e49, 0xdd8f3f12), + TOBN(0x6ef267f6, 0x29380f18), TOBN(0x3e8e9670, 0x8da64d16), + TOBN(0xbc19180c, 0x207674f1), TOBN(0x112e09a7, 0x33ae8fdb), + TOBN(0x99667554, 0x6aaeb71e), TOBN(0x79432af1, 0xe101b1c7), + TOBN(0xd5eb558f, 0xde2ddec6), TOBN(0x81392d1f, 0x5357753f), + TOBN(0xa7a76b97, 0x3ae1158a), TOBN(0x416fbbff, 0x4a899991), + TOBN(0x9e65fdfd, 0x0d4a9dcf), TOBN(0x7bc29e48, 0x944ddf12), + TOBN(0xbc1a92d9, 0x3c856866), TOBN(0x273c6905, 0x6e98dfe2), + TOBN(0x69fce418, 0xcdfaa6b8), TOBN(0x606bd823, 0x5061c69f), + TOBN(0x42d495a0, 0x6af75e27), TOBN(0x8ed3d505, 0x6d873a1f), + TOBN(0xaf552841, 0x6ab25b6a), TOBN(0xc6c0ffc7, 0x2b1a4523), + TOBN(0xab18827b, 0x21c99e03), TOBN(0x060e8648, 0x9034691b), + TOBN(0x5207f90f, 0x93c7f398), TOBN(0x9f4a96cb, 0x82f8d10b), + TOBN(0xdd71cd79, 0x3ad0f9e3), TOBN(0x84f435d2, 0xfc3a54f5), + TOBN(0x4b03c55b, 0x8e33787f), TOBN(0xef42f975, 0xa6384673), + TOBN(0xff7304f7, 0x5051b9f0), TOBN(0x18aca1dc, 0x741c87c2), + TOBN(0x56f120a7, 0x2d4bfe80), TOBN(0xfd823b3d, 0x053e732c), + TOBN(0x11bccfe4, 0x7537ca16), TOBN(0xdf6c9c74, 0x1b5a996b), + TOBN(0xee7332c7, 0x904fc3fa), TOBN(0x14a23f45, 0xc7e3636a), + TOBN(0xc38659c3, 0xf091d9aa), TOBN(0x4a995e5d, 0xb12d8540), + TOBN(0x20a53bec, 0xf3a5598a), TOBN(0x56534b17, 0xb1eaa995), + TOBN(0x9ed3dca4, 0xbf04e03c), TOBN(0x716c563a, 0xd8d56268), + TOBN(0x27ba77a4, 0x1d6178e7), TOBN(0xe4c80c40, 0x68a1ff8e), + TOBN(0x75011099, 0x0a13f63d), TOBN(0x7bf33521, 0xa61d46f3), + TOBN(0x0aff218e, 0x10b365bb), TOBN(0x81021804, 0x0fd7ea75), + TOBN(0x05a3fd8a, 0xa4b3a925), TOBN(0xb829e75f, 0x9b3db4e6), + TOBN(0x6bdc75a5, 0x4d53e5fb), TOBN(0x04a5dc02, 0xd52717e3), + TOBN(0x86af502f, 0xe9a42ec2), TOBN(0x8867e8fb, 0x2630e382), + TOBN(0xbf845c6e, 0xbec9889b), TOBN(0x54f491f2, 0xcb47c98d), + TOBN(0xa3091fba, 0x790c2a12), TOBN(0xd7f6fd78, 0xc20f708b), + TOBN(0xa569ac30, 0xacde5e17), TOBN(0xd0f996d0, 0x6852b4d7), + TOBN(0xe51d4bb5, 0x4609ae54), TOBN(0x3fa37d17, 0x0daed061), + TOBN(0x62a88684, 0x34b8fb41), TOBN(0x99a2acbd, 0x9efb64f1), + TOBN(0xb75c1a5e, 0x6448e1f2), TOBN(0xfa99951a, 0x42b5a069), + TOBN(0x6d956e89, 0x2f3b26e7), TOBN(0xf4709860, 0xda875247), + TOBN(0x3ad15179, 0x2482dda3), TOBN(0xd64110e3, 0x017d82f0), + TOBN(0x14928d2c, 0xfad414e4), TOBN(0x2b155f58, 0x2ed02b24), + TOBN(0x481a141b, 0xcb821bf1), TOBN(0x12e3c770, 0x4f81f5da), + TOBN(0xe49c5de5, 0x9fff8381), TOBN(0x11053232, 0x5bbec894), + TOBN(0xa0d051cc, 0x454d88c4), TOBN(0x4f6db89c, 0x1f8e531b), + TOBN(0x34fe3fd6, 0xca563a44), TOBN(0x7f5c2215, 0x58da8ab9), + TOBN(0x8445016d, 0x9474f0a1), TOBN(0x17d34d61, 0xcb7d8a0a), + TOBN(0x8e9d3910, 0x1c474019), TOBN(0xcaff2629, 0xd52ceefb), + TOBN(0xf9cf3e32, 0xc1622c2b), TOBN(0xd4b95e3c, 0xe9071a05), + TOBN(0xfbbca61f, 0x1594438c), TOBN(0x1eb6e6a6, 0x04aadedf), + TOBN(0x853027f4, 0x68e14940), TOBN(0x221d322a, 0xdfabda9c), + TOBN(0xed8ea9f6, 0xb7cb179a), TOBN(0xdc7b764d, 0xb7934dcc), + TOBN(0xfcb13940, 0x5e09180d), TOBN(0x6629a6bf, 0xb47dc2dd), + TOBN(0xbfc55e4e, 0x9f5a915e), TOBN(0xb1db9d37, 0x6204441e), + TOBN(0xf82d68cf, 0x930c5f53), TOBN(0x17d3a142, 0xcbb605b1), + TOBN(0xdd5944ea, 0x308780f2), TOBN(0xdc8de761, 0x3845f5e4), + TOBN(0x6beaba7d, 0x7624d7a3), TOBN(0x1e709afd, 0x304df11e), + TOBN(0x95364376, 0x02170456), TOBN(0xbf204b3a, 0xc8f94b64), + TOBN(0x4e53af7c, 0x5680ca68), TOBN(0x0526074a, 0xe0c67574), + TOBN(0x95d8cef8, 0xecd92af6), TOBN(0xe6b9fa7a, 0x6cd1745a), + TOBN(0x3d546d3d, 0xa325c3e4), TOBN(0x1f57691d, 0x9ae93aae), + TOBN(0xe891f3fe, 0x9d2e1a33), TOBN(0xd430093f, 0xac063d35), + TOBN(0xeda59b12, 0x5513a327), TOBN(0xdc2134f3, 0x5536f18f), + TOBN(0xaa51fe2c, 0x5c210286), TOBN(0x3f68aaee, 0x1cab658c), + TOBN(0x5a23a00b, 0xf9357292), TOBN(0x9a626f39, 0x7efdabed), + TOBN(0xfe2b3bf3, 0x199d78e3), TOBN(0xb7a2af77, 0x71bbc345), + TOBN(0x3d19827a, 0x1e59802c), TOBN(0x823bbc15, 0xb487a51c), + TOBN(0x856139f2, 0x99d0a422), TOBN(0x9ac3df65, 0xf456c6fb), + TOBN(0xaddf65c6, 0x701f8bd6), TOBN(0x149f321e, 0x3758df87), + TOBN(0xb1ecf714, 0x721b7eba), TOBN(0xe17df098, 0x31a3312a), + TOBN(0xdb2fd6ec, 0xd5c4d581), TOBN(0xfd02996f, 0x8fcea1b3), + TOBN(0xe29fa63e, 0x7882f14f), TOBN(0xc9f6dc35, 0x07c6cadc), + TOBN(0x46f22d6f, 0xb882bed0), TOBN(0x1a45755b, 0xd118e52c), + TOBN(0x9f2c7c27, 0x7c4608cf), TOBN(0x7ccbdf32, 0x568012c2), + TOBN(0xfcb0aedd, 0x61729b0e), TOBN(0x7ca2ca9e, 0xf7d75dbf), + TOBN(0xf58fecb1, 0x6f640f62), TOBN(0xe274b92b, 0x39f51946), + TOBN(0x7f4dfc04, 0x6288af44), TOBN(0x0a91f32a, 0xeac329e5), + TOBN(0x43ad274b, 0xd6aaba31), TOBN(0x719a1640, 0x0f6884f9), + TOBN(0x685d29f6, 0xdaf91e20), TOBN(0x5ec1cc33, 0x27e49d52), + TOBN(0x38f4de96, 0x3b54a059), TOBN(0x0e0015e5, 0xefbcfdb3), + TOBN(0x177d23d9, 0x4dbb8da6), TOBN(0x98724aa2, 0x97a617ad), + TOBN(0x30f0885b, 0xfdb6558e), TOBN(0xf9f7a28a, 0xc7899a96), + TOBN(0xd2ae8ac8, 0x872dc112), TOBN(0xfa0642ca, 0x73c3c459), + TOBN(0x15296981, 0xe7dfc8d6), TOBN(0x67cd4450, 0x1fb5b94a), + TOBN(0x0ec71cf1, 0x0eddfd37), TOBN(0xc7e5eeb3, 0x9a8eddc7), + TOBN(0x02ac8e3d, 0x81d95028), TOBN(0x0088f172, 0x70b0e35d), + TOBN(0xec041fab, 0xe1881fe3), TOBN(0x62cf71b8, 0xd99e7faa), + TOBN(0x5043dea7, 0xe0f222c2), TOBN(0x309d42ac, 0x72e65142), + TOBN(0x94fe9ddd, 0x9216cd30), TOBN(0xd6539c7d, 0x0f87feec), + TOBN(0x03c5a57c, 0x432ac7d7), TOBN(0x72692cf0, 0x327fda10), + TOBN(0xec28c85f, 0x280698de), TOBN(0x2331fb46, 0x7ec283b1), + TOBN(0xd34bfa32, 0x2867e633), TOBN(0x78709a82, 0x0a9cc815), + TOBN(0xb7fe6964, 0x875e2fa5), TOBN(0x25cc064f, 0x9e98bfb5), + TOBN(0x9eb0151c, 0x493a65c5), TOBN(0x5fb5d941, 0x53182464), + TOBN(0x69e6f130, 0xf04618e2), TOBN(0xa8ecec22, 0xf89c8ab6), + TOBN(0xcd6ac88b, 0xb96209bd), TOBN(0x65fa8cdb, 0xb3e1c9e0), + TOBN(0xa47d22f5, 0x4a8d8eac), TOBN(0x83895cdf, 0x8d33f963), + TOBN(0xa8adca59, 0xb56cd3d1), TOBN(0x10c8350b, 0xdaf38232), + TOBN(0x2b161fb3, 0xa5080a9f), TOBN(0xbe7f5c64, 0x3af65b3a), + TOBN(0x2c754039, 0x97403a11), TOBN(0x94626cf7, 0x121b96af), + TOBN(0x431de7c4, 0x6a983ec2), TOBN(0x3780dd3a, 0x52cc3df7), + TOBN(0xe28a0e46, 0x2baf8e3b), TOBN(0xabe68aad, 0x51d299ae), + TOBN(0x603eb8f9, 0x647a2408), TOBN(0x14c61ed6, 0x5c750981), + TOBN(0x88b34414, 0xc53352e7), TOBN(0x5a34889c, 0x1337d46e), + TOBN(0x612c1560, 0xf95f2bc8), TOBN(0x8a3f8441, 0xd4807a3a), + TOBN(0x680d9e97, 0x5224da68), TOBN(0x60cd6e88, 0xc3eb00e9), + TOBN(0x3875a98e, 0x9a6bc375), TOBN(0xdc80f924, 0x4fd554c2), + TOBN(0x6c4b3415, 0x6ac77407), TOBN(0xa1e5ea8f, 0x25420681), + TOBN(0x541bfa14, 0x4607a458), TOBN(0x5dbc7e7a, 0x96d7fbf9), + TOBN(0x646a851b, 0x31590a47), TOBN(0x039e85ba, 0x15ee6df8), + TOBN(0xd19fa231, 0xd7b43fc0), TOBN(0x84bc8be8, 0x299a0e04), + TOBN(0x2b9d2936, 0xf20df03a), TOBN(0x24054382, 0x8608d472), + TOBN(0x76b6ba04, 0x9149202a), TOBN(0xb21c3831, 0x3670e7b7), + TOBN(0xddd93059, 0xd6fdee10), TOBN(0x9da47ad3, 0x78488e71), + TOBN(0x99cc1dfd, 0xa0fcfb25), TOBN(0x42abde10, 0x64696954), + TOBN(0x14cc15fc, 0x17eab9fe), TOBN(0xd6e863e4, 0xd3e70972), + TOBN(0x29a7765c, 0x6432112c), TOBN(0x88660001, 0x5b0774d8), + TOBN(0x3729175a, 0x2c088eae), TOBN(0x13afbcae, 0x8230b8d4), + TOBN(0x44768151, 0x915f4379), TOBN(0xf086431a, 0xd8d22812), + TOBN(0x37461955, 0xc298b974), TOBN(0x905fb5f0, 0xf8711e04), + TOBN(0x787abf3a, 0xfe969d18), TOBN(0x392167c2, 0x6f6a494e), + TOBN(0xfc7a0d2d, 0x28c511da), TOBN(0xf127c7dc, 0xb66a262d), + TOBN(0xf9c4bb95, 0xfd63fdf0), TOBN(0x90016589, 0x3913ef46), + TOBN(0x74d2a73c, 0x11aa600d), TOBN(0x2f5379bd, 0x9fb5ab52), + TOBN(0xe49e53a4, 0x7fb70068), TOBN(0x68dd39e5, 0x404aa9a7), + TOBN(0xb9b0cf57, 0x2ecaa9c3), TOBN(0xba0e103b, 0xe824826b), + TOBN(0x60c2198b, 0x4631a3c4), TOBN(0xc5ff84ab, 0xfa8966a2), + TOBN(0x2d6ebe22, 0xac95aff8), TOBN(0x1c9bb6db, 0xb5a46d09), + TOBN(0x419062da, 0x53ee4f8d), TOBN(0x7b9042d0, 0xbb97efef), + TOBN(0x0f87f080, 0x830cf6bd), TOBN(0x4861d19a, 0x6ec8a6c6), + TOBN(0xd3a0daa1, 0x202f01aa), TOBN(0xb0111674, 0xf25afbd5), + TOBN(0x6d00d6cf, 0x1afb20d9), TOBN(0x13695000, 0x40671bc5), + TOBN(0x913ab0dc, 0x2485ea9b), TOBN(0x1f2bed06, 0x9eef61ac), + TOBN(0x850c8217, 0x6d799e20), TOBN(0x93415f37, 0x3271c2de), + TOBN(0x5afb06e9, 0x6c4f5910), TOBN(0x688a52df, 0xc4e9e421), + TOBN(0x30495ba3, 0xe2a9a6db), TOBN(0x4601303d, 0x58f9268b), + TOBN(0xbe3b0dad, 0x7eb0f04f), TOBN(0x4ea47250, 0x4456936d), + TOBN(0x8caf8798, 0xd33fd3e7), TOBN(0x1ccd8a89, 0xeb433708), + TOBN(0x9effe3e8, 0x87fd50ad), TOBN(0xbe240a56, 0x6b29c4df), + TOBN(0xec4ffd98, 0xca0e7ebd), TOBN(0xf586783a, 0xe748616e), + TOBN(0xa5b00d8f, 0xc77baa99), TOBN(0x0acada29, 0xb4f34c9c), + TOBN(0x36dad67d, 0x0fe723ac), TOBN(0x1d8e53a5, 0x39c36c1e), + TOBN(0xe4dd342d, 0x1f4bea41), TOBN(0x64fd5e35, 0xebc9e4e0), + TOBN(0x96f01f90, 0x57908805), TOBN(0xb5b9ea3d, 0x5ed480dd), + TOBN(0x366c5dc2, 0x3efd2dd0), TOBN(0xed2fe305, 0x6e9dfa27), + TOBN(0x4575e892, 0x6e9197e2), TOBN(0x11719c09, 0xab502a5d), + TOBN(0x264c7bec, 0xe81f213f), TOBN(0x741b9241, 0x55f5c457), + TOBN(0x78ac7b68, 0x49a5f4f4), TOBN(0xf91d70a2, 0x9fc45b7d), + TOBN(0x39b05544, 0xb0f5f355), TOBN(0x11f06bce, 0xeef930d9), + TOBN(0xdb84d25d, 0x038d05e1), TOBN(0x04838ee5, 0xbacc1d51), + TOBN(0x9da3ce86, 0x9e8ee00b), TOBN(0xc3412057, 0xc36eda1f), + TOBN(0xae80b913, 0x64d9c2f4), TOBN(0x7468bac3, 0xa010a8ff), + TOBN(0xdfd20037, 0x37359d41), TOBN(0x1a0f5ab8, 0x15efeacc), + TOBN(0x7c25ad2f, 0x659d0ce0), TOBN(0x4011bcbb, 0x6785cff1), + TOBN(0x128b9912, 0x7e2192c7), TOBN(0xa549d8e1, 0x13ccb0e8), + TOBN(0x805588d8, 0xc85438b1), TOBN(0x5680332d, 0xbc25cb27), + TOBN(0xdcd1bc96, 0x1a4bfdf4), TOBN(0x779ff428, 0x706f6566), + TOBN(0x8bbee998, 0xf059987a), TOBN(0xf6ce8cf2, 0xcc686de7), + TOBN(0xf8ad3c4a, 0x953cfdb2), TOBN(0xd1d426d9, 0x2205da36), + TOBN(0xb3c0f13f, 0xc781a241), TOBN(0x3e89360e, 0xd75362a8), + TOBN(0xccd05863, 0xc8a91184), TOBN(0x9bd0c9b7, 0xefa8a7f4), + TOBN(0x97ee4d53, 0x8a912a4b), TOBN(0xde5e15f8, 0xbcf518fd), + TOBN(0x6a055bf8, 0xc467e1e0), TOBN(0x10be4b4b, 0x1587e256), + TOBN(0xd90c14f2, 0x668621c9), TOBN(0xd5518f51, 0xab9c92c1), + TOBN(0x8e6a0100, 0xd6d47b3c), TOBN(0xcbe980dd, 0x66716175), + TOBN(0x500d3f10, 0xddd83683), TOBN(0x3b6cb35d, 0x99cac73c), + TOBN(0x53730c8b, 0x6083d550), TOBN(0xcf159767, 0xdf0a1987), + TOBN(0x84bfcf53, 0x43ad73b3), TOBN(0x1b528c20, 0x4f035a94), + TOBN(0x4294edf7, 0x33eeac69), TOBN(0xb6283e83, 0x817f3240), + TOBN(0xc3fdc959, 0x0a5f25b1), TOBN(0xefaf8aa5, 0x5844ee22), + TOBN(0xde269ba5, 0xdbdde4de), TOBN(0xe3347160, 0xc56133bf), + TOBN(0xc1184219, 0x8d9ea9f8), TOBN(0x090de5db, 0xf3fc1ab5), + TOBN(0x404c37b1, 0x0bf22cda), TOBN(0x7de20ec8, 0xf5618894), + TOBN(0x754c588e, 0xecdaecab), TOBN(0x6ca4b0ed, 0x88342743), + TOBN(0x76f08bdd, 0xf4a938ec), TOBN(0xd182de89, 0x91493ccb), + TOBN(0xd652c53e, 0xc8a4186a), TOBN(0xb3e878db, 0x946d8e33), + TOBN(0x088453c0, 0x5f37663c), TOBN(0x5cd9daaa, 0xb407748b), + TOBN(0xa1f5197f, 0x586d5e72), TOBN(0x47500be8, 0xc443ca59), + TOBN(0x78ef35b2, 0xe2652424), TOBN(0x09c5d26f, 0x6dd7767d), + TOBN(0x7175a79a, 0xa74d3f7b), TOBN(0x0428fd8d, 0xcf5ea459), + TOBN(0x511cb97c, 0xa5d1746d), TOBN(0x36363939, 0xe71d1278), + TOBN(0xcf2df955, 0x10350bf4), TOBN(0xb3817439, 0x60aae782), + TOBN(0xa748c0e4, 0x3e688809), TOBN(0x98021fbf, 0xd7a5a006), + TOBN(0x9076a70c, 0x0e367a98), TOBN(0xbea1bc15, 0x0f62b7c2), + TOBN(0x2645a68c, 0x30fe0343), TOBN(0xacaffa78, 0x699dc14f), + TOBN(0xf4469964, 0x457bf9c4), TOBN(0x0db6407b, 0x0d2ead83), + TOBN(0x68d56cad, 0xb2c6f3eb), TOBN(0x3b512e73, 0xf376356c), + TOBN(0xe43b0e1f, 0xfce10408), TOBN(0x89ddc003, 0x5a5e257d), + TOBN(0xb0ae0d12, 0x0362e5b3), TOBN(0x07f983c7, 0xb0519161), + TOBN(0xc2e94d15, 0x5d5231e7), TOBN(0xcff22aed, 0x0b4f9513), + TOBN(0xb02588dd, 0x6ad0b0b5), TOBN(0xb967d1ac, 0x11d0dcd5), + TOBN(0x8dac6bc6, 0xcf777b6c), TOBN(0x0062bdbd, 0x4c6d1959), + TOBN(0x53da71b5, 0x0ef5cc85), TOBN(0x07012c7d, 0x4006f14f), + TOBN(0x4617f962, 0xac47800d), TOBN(0x53365f2b, 0xc102ed75), + TOBN(0xb422efcb, 0x4ab8c9d3), TOBN(0x195cb26b, 0x34af31c9), + TOBN(0x3a926e29, 0x05f2c4ce), TOBN(0xbd2bdecb, 0x9856966c), + TOBN(0x5d16ab3a, 0x85527015), TOBN(0x9f81609e, 0x4486c231), + TOBN(0xd8b96b2c, 0xda350002), TOBN(0xbd054690, 0xfa1b7d36), + TOBN(0xdc90ebf5, 0xe71d79bc), TOBN(0xf241b6f9, 0x08964e4e), + TOBN(0x7c838643, 0x2fe3cd4c), TOBN(0xe0f33acb, 0xb4bc633c), + TOBN(0xb4a9ecec, 0x3d139f1f), TOBN(0x05ce69cd, 0xdc4a1f49), + TOBN(0xa19d1b16, 0xf5f98aaf), TOBN(0x45bb71d6, 0x6f23e0ef), + TOBN(0x33789fcd, 0x46cdfdd3), TOBN(0x9b8e2978, 0xcee040ca), + TOBN(0x9c69b246, 0xae0a6828), TOBN(0xba533d24, 0x7078d5aa), + TOBN(0x7a2e42c0, 0x7bb4fbdb), TOBN(0xcfb4879a, 0x7035385c), + TOBN(0x8c3dd30b, 0x3281705b), TOBN(0x7e361c6c, 0x404fe081), + TOBN(0x7b21649c, 0x3f604edf), TOBN(0x5dbf6a3f, 0xe52ffe47), + TOBN(0xc41b7c23, 0x4b54d9bf), TOBN(0x1374e681, 0x3511c3d9), + TOBN(0x1863bf16, 0xc1b2b758), TOBN(0x90e78507, 0x1e9e6a96), + TOBN(0xab4bf98d, 0x5d86f174), TOBN(0xd74e0bd3, 0x85e96fe4), + TOBN(0x8afde39f, 0xcac5d344), TOBN(0x90946dbc, 0xbd91b847), + TOBN(0xf5b42358, 0xfe1a838c), TOBN(0x05aae6c5, 0x620ac9d8), + TOBN(0x8e193bd8, 0xa1ce5a0b), TOBN(0x8f710571, 0x4dabfd72), + TOBN(0x8d8fdd48, 0x182caaac), TOBN(0x8c4aeefa, 0x040745cf), + TOBN(0x73c6c30a, 0xf3b93e6d), TOBN(0x991241f3, 0x16f42011), + TOBN(0xa0158eea, 0xe457a477), TOBN(0xd19857db, 0xee6ddc05), + TOBN(0xb3265224, 0x18c41671), TOBN(0x3ffdfc7e, 0x3c2c0d58), + TOBN(0x3a3a5254, 0x26ee7cda), TOBN(0x341b0869, 0xdf02c3a8), + TOBN(0xa023bf42, 0x723bbfc8), TOBN(0x3d15002a, 0x14452691),} + , + {TOBN(0x5ef7324c, 0x85edfa30), TOBN(0x25976554, 0x87d4f3da), + TOBN(0x352f5bc0, 0xdcb50c86), TOBN(0x8f6927b0, 0x4832a96c), + TOBN(0xd08ee1ba, 0x55f2f94c), TOBN(0x6a996f99, 0x344b45fa), + TOBN(0xe133cb8d, 0xa8aa455d), TOBN(0x5d0721ec, 0x758dc1f7), + TOBN(0x6ba7a920, 0x79e5fb67), TOBN(0xe1331feb, 0x70aa725e), + TOBN(0x5080ccf5, 0x7df5d837), TOBN(0xe4cae01d, 0x7ff72e21), + TOBN(0xd9243ee6, 0x0412a77d), TOBN(0x06ff7cac, 0xdf449025), + TOBN(0xbe75f7cd, 0x23ef5a31), TOBN(0xbc957822, 0x0ddef7a8), + TOBN(0x8cf7230c, 0xb0ce1c55), TOBN(0x5b534d05, 0x0bbfb607), + TOBN(0xee1ef113, 0x0e16363b), TOBN(0x27e0aa7a, 0xb4999e82), + TOBN(0xce1dac2d, 0x79362c41), TOBN(0x67920c90, 0x91bb6cb0), + TOBN(0x1e648d63, 0x2223df24), TOBN(0x0f7d9eef, 0xe32e8f28), + TOBN(0x6943f39a, 0xfa833834), TOBN(0x22951722, 0xa6328562), + TOBN(0x81d63dd5, 0x4170fc10), TOBN(0x9f5fa58f, 0xaecc2e6d), + TOBN(0xb66c8725, 0xe77d9a3b), TOBN(0x11235cea, 0x6384ebe0), + TOBN(0x06a8c118, 0x5845e24a), TOBN(0x0137b286, 0xebd093b1), + TOBN(0xc589e1ce, 0x44ace150), TOBN(0xe0f8d3d9, 0x4381e97c), + TOBN(0x59e99b11, 0x62c5a4b8), TOBN(0x90d262f7, 0xfd0ec9f9), + TOBN(0xfbc854c9, 0x283e13c9), TOBN(0x2d04fde7, 0xaedc7085), + TOBN(0x057d7765, 0x47dcbecb), TOBN(0x8dbdf591, 0x9a76fa5f), + TOBN(0xd0150695, 0x0de1e578), TOBN(0x2e1463e7, 0xe9f72bc6), + TOBN(0xffa68441, 0x1b39eca5), TOBN(0x673c8530, 0x7c037f2f), + TOBN(0xd0d6a600, 0x747f91da), TOBN(0xb08d43e1, 0xc9cb78e9), + TOBN(0x0fc0c644, 0x27b5cef5), TOBN(0x5c1d160a, 0xa60a2fd6), + TOBN(0xf98cae53, 0x28c8e13b), TOBN(0x375f10c4, 0xb2eddcd1), + TOBN(0xd4eb8b7f, 0x5cce06ad), TOBN(0xb4669f45, 0x80a2e1ef), + TOBN(0xd593f9d0, 0x5bbd8699), TOBN(0x5528a4c9, 0xe7976d13), + TOBN(0x3923e095, 0x1c7e28d3), TOBN(0xb9293790, 0x3f6bb577), + TOBN(0xdb567d6a, 0xc42bd6d2), TOBN(0x6df86468, 0xbb1f96ae), + TOBN(0x0efe5b1a, 0x4843b28e), TOBN(0x961bbb05, 0x6379b240), + TOBN(0xb6caf5f0, 0x70a6a26b), TOBN(0x70686c0d, 0x328e6e39), + TOBN(0x80da06cf, 0x895fc8d3), TOBN(0x804d8810, 0xb363fdc9), + TOBN(0xbe22877b, 0x207f1670), TOBN(0x9b0dd188, 0x4e615291), + TOBN(0x625ae8dc, 0x97a3c2bf), TOBN(0x08584ef7, 0x439b86e8), + TOBN(0xde7190a5, 0xdcd898ff), TOBN(0x26286c40, 0x2058ee3d), + TOBN(0x3db0b217, 0x5f87b1c1), TOBN(0xcc334771, 0x102a6db5), + TOBN(0xd99de954, 0x2f770fb1), TOBN(0x97c1c620, 0x4cd7535e), + TOBN(0xd3b6c448, 0x3f09cefc), TOBN(0xd725af15, 0x5a63b4f8), + TOBN(0x0c95d24f, 0xc01e20ec), TOBN(0xdfd37494, 0x9ae7121f), + TOBN(0x7d6ddb72, 0xec77b7ec), TOBN(0xfe079d3b, 0x0353a4ae), + TOBN(0x3066e70a, 0x2e6ac8d2), TOBN(0x9c6b5a43, 0x106e5c05), + TOBN(0x52d3c6f5, 0xede59b8c), TOBN(0x30d6a5c3, 0xfccec9ae), + TOBN(0xedec7c22, 0x4fc0a9ef), TOBN(0x190ff083, 0x95c16ced), + TOBN(0xbe12ec8f, 0x94de0fde), TOBN(0x0d131ab8, 0x852d3433), + TOBN(0x42ace07e, 0x85701291), TOBN(0x94793ed9, 0x194061a8), + TOBN(0x30e83ed6, 0xd7f4a485), TOBN(0x9eec7269, 0xf9eeff4d), + TOBN(0x90acba59, 0x0c9d8005), TOBN(0x5feca458, 0x1e79b9d1), + TOBN(0x8fbe5427, 0x1d506a1e), TOBN(0xa32b2c8e, 0x2439cfa7), + TOBN(0x1671c173, 0x73dd0b4e), TOBN(0x37a28214, 0x44a054c6), + TOBN(0x81760a1b, 0x4e8b53f1), TOBN(0xa6c04224, 0xf9f93b9e), + TOBN(0x18784b34, 0xcf671e3c), TOBN(0x81bbecd2, 0xcda9b994), + TOBN(0x38831979, 0xb2ab3848), TOBN(0xef54feb7, 0xf2e03c2d), + TOBN(0xcf197ca7, 0xfb8088fa), TOBN(0x01427247, 0x4ddc96c5), + TOBN(0xa2d2550a, 0x30777176), TOBN(0x53469898, 0x4d0cf71d), + TOBN(0x6ce937b8, 0x3a2aaac6), TOBN(0xe9f91dc3, 0x5af38d9b), + TOBN(0x2598ad83, 0xc8bf2899), TOBN(0x8e706ac9, 0xb5536c16), + TOBN(0x40dc7495, 0xf688dc98), TOBN(0x26490cd7, 0x124c4afc), + TOBN(0xe651ec84, 0x1f18775c), TOBN(0x393ea6c3, 0xb4fdaf4a), + TOBN(0x1e1f3343, 0x7f338e0d), TOBN(0x39fb832b, 0x6053e7b5), + TOBN(0x46e702da, 0x619e14d5), TOBN(0x859cacd1, 0xcdeef6e0), + TOBN(0x63b99ce7, 0x4462007d), TOBN(0xb8ab48a5, 0x4cb5f5b7), + TOBN(0x9ec673d2, 0xf55edde7), TOBN(0xd1567f74, 0x8cfaefda), + TOBN(0x46381b6b, 0x0887bcec), TOBN(0x694497ce, 0xe178f3c2), + TOBN(0x5e6525e3, 0x1e6266cb), TOBN(0x5931de26, 0x697d6413), + TOBN(0x87f8df7c, 0x0e58d493), TOBN(0xb1ae5ed0, 0x58b73f12), + TOBN(0xc368f784, 0xdea0c34d), TOBN(0x9bd0a120, 0x859a91a0), + TOBN(0xb00d88b7, 0xcc863c68), TOBN(0x3a1cc11e, 0x3d1f4d65), + TOBN(0xea38e0e7, 0x0aa85593), TOBN(0x37f13e98, 0x7dc4aee8), + TOBN(0x10d38667, 0xbc947bad), TOBN(0x738e07ce, 0x2a36ee2e), + TOBN(0xc93470cd, 0xc577fcac), TOBN(0xdee1b616, 0x2782470d), + TOBN(0x36a25e67, 0x2e793d12), TOBN(0xd6aa6cae, 0xe0f186da), + TOBN(0x474d0fd9, 0x80e07af7), TOBN(0xf7cdc47d, 0xba8a5cd4), + TOBN(0x28af6d9d, 0xab15247f), TOBN(0x7c789c10, 0x493a537f), + TOBN(0x7ac9b110, 0x23a334e7), TOBN(0x0236ac09, 0x12c9c277), + TOBN(0xa7e5bd25, 0x1d7a5144), TOBN(0x098b9c2a, 0xf13ec4ec), + TOBN(0x3639daca, 0xd3f0abca), TOBN(0x642da81a, 0xa23960f9), + TOBN(0x7d2e5c05, 0x4f7269b1), TOBN(0xfcf30777, 0xe287c385), + TOBN(0x10edc84f, 0xf2a46f21), TOBN(0x35441757, 0x4f43fa36), + TOBN(0xf1327899, 0xfd703431), TOBN(0xa438d7a6, 0x16dd587a), + TOBN(0x65c34c57, 0xe9c8352d), TOBN(0xa728edab, 0x5cc5a24e), + TOBN(0xaed78abc, 0x42531689), TOBN(0x0a51a0e8, 0x010963ef), + TOBN(0x5776fa0a, 0xd717d9b3), TOBN(0xf356c239, 0x7dd3428b), + TOBN(0x29903fff, 0x8d3a3dac), TOBN(0x409597fa, 0x3d94491f), + TOBN(0x4cd7a5ff, 0xbf4a56a4), TOBN(0xe5096474, 0x8adab462), + TOBN(0xa97b5126, 0x5c3427b0), TOBN(0x6401405c, 0xd282c9bd), + TOBN(0x3629f8d7, 0x222c5c45), TOBN(0xb1c02c16, 0xe8d50aed), + TOBN(0xbea2ed75, 0xd9635bc9), TOBN(0x226790c7, 0x6e24552f), + TOBN(0x3c33f2a3, 0x65f1d066), TOBN(0x2a43463e, 0x6dfccc2e), + TOBN(0x8cc3453a, 0xdb483761), TOBN(0xe7cc6085, 0x65d5672b), + TOBN(0x277ed6cb, 0xde3efc87), TOBN(0x19f2f368, 0x69234eaf), + TOBN(0x9aaf4317, 0x5c0b800b), TOBN(0x1f1e7c89, 0x8b6da6e2), + TOBN(0x6cfb4715, 0xb94ec75e), TOBN(0xd590dd5f, 0x453118c2), + TOBN(0x14e49da1, 0x1f17a34c), TOBN(0x5420ab39, 0x235a1456), + TOBN(0xb7637241, 0x2f50363b), TOBN(0x7b15d623, 0xc3fabb6e), + TOBN(0xa0ef40b1, 0xe274e49c), TOBN(0x5cf50744, 0x96b1860a), + TOBN(0xd6583fbf, 0x66afe5a4), TOBN(0x44240510, 0xf47e3e9a), + TOBN(0x99254343, 0x11b2d595), TOBN(0xf1367499, 0xeec8df57), + TOBN(0x3cb12c61, 0x3e73dd05), TOBN(0xd248c033, 0x7dac102a), + TOBN(0xcf154f13, 0xa77739f5), TOBN(0xbf4288cb, 0x23d2af42), + TOBN(0xaa64c9b6, 0x32e4a1cf), TOBN(0xee8c07a8, 0xc8a208f3), + TOBN(0xe10d4999, 0x6fe8393f), TOBN(0x0f809a3f, 0xe91f3a32), + TOBN(0x61096d1c, 0x802f63c8), TOBN(0x289e1462, 0x57750d3d), + TOBN(0xed06167e, 0x9889feea), TOBN(0xd5c9c0e2, 0xe0993909), + TOBN(0x46fca0d8, 0x56508ac6), TOBN(0x91826047, 0x4f1b8e83), + TOBN(0x4f2c877a, 0x9a4a2751), TOBN(0x71bd0072, 0xcae6fead), + TOBN(0x38df8dcc, 0x06aa1941), TOBN(0x5a074b4c, 0x63beeaa8), + TOBN(0xd6d65934, 0xc1cec8ed), TOBN(0xa6ecb49e, 0xaabc03bd), + TOBN(0xaade91c2, 0xde8a8415), TOBN(0xcfb0efdf, 0x691136e0), + TOBN(0x11af45ee, 0x23ab3495), TOBN(0xa132df88, 0x0b77463d), + TOBN(0x8923c15c, 0x815d06f4), TOBN(0xc3ceb3f5, 0x0d61a436), + TOBN(0xaf52291d, 0xe88fb1da), TOBN(0xea057974, 0x1da12179), + TOBN(0xb0d7218c, 0xd2fef720), TOBN(0x6c0899c9, 0x8e1d8845), + TOBN(0x98157504, 0x752ddad7), TOBN(0xd60bd74f, 0xa1a68a97), + TOBN(0x7047a3a9, 0xf658fb99), TOBN(0x1f5d86d6, 0x5f8511e4), + TOBN(0xb8a4bc42, 0x4b5a6d88), TOBN(0x69eb2c33, 0x1abefa7d), + TOBN(0x95bf39e8, 0x13c9c510), TOBN(0xf571960a, 0xd48aab43), + TOBN(0x7e8cfbcf, 0x704e23c6), TOBN(0xc71b7d22, 0x28aaa65b), + TOBN(0xa041b2bd, 0x245e3c83), TOBN(0x69b98834, 0xd21854ff), + TOBN(0x89d227a3, 0x963bfeec), TOBN(0x99947aaa, 0xde7da7cb), + TOBN(0x1d9ee9db, 0xee68a9b1), TOBN(0x0a08f003, 0x698ec368), + TOBN(0xe9ea4094, 0x78ef2487), TOBN(0xc8d2d415, 0x02cfec26), + TOBN(0xc52f9a6e, 0xb7dcf328), TOBN(0x0ed489e3, 0x85b6a937), + TOBN(0x9b94986b, 0xbef3366e), TOBN(0x0de59c70, 0xedddddb8), + TOBN(0xffdb748c, 0xeadddbe2), TOBN(0x9b9784bb, 0x8266ea40), + TOBN(0x142b5502, 0x1a93507a), TOBN(0xb4cd1187, 0x8d3c06cf), + TOBN(0xdf70e76a, 0x91ec3f40), TOBN(0x484e81ad, 0x4e7553c2), + TOBN(0x830f87b5, 0x272e9d6e), TOBN(0xea1c93e5, 0xc6ff514a), + TOBN(0x67cc2adc, 0xc4192a8e), TOBN(0xc77e27e2, 0x42f4535a), + TOBN(0x9cdbab36, 0xd2b713c5), TOBN(0x86274ea0, 0xcf7b0cd3), + TOBN(0x784680f3, 0x09af826b), TOBN(0xbfcc837a, 0x0c72dea3), + TOBN(0xa8bdfe9d, 0xd6529b73), TOBN(0x708aa228, 0x63a88002), + TOBN(0x6c7a9a54, 0xc91d45b9), TOBN(0xdf1a38bb, 0xfd004f56), + TOBN(0x2e8c9a26, 0xb8bad853), TOBN(0x2d52cea3, 0x3723eae7), + TOBN(0x054d6d81, 0x56ca2830), TOBN(0xa3317d14, 0x9a8dc411), + TOBN(0xa08662fe, 0xfd4ddeda), TOBN(0xed2a153a, 0xb55d792b), + TOBN(0x7035c16a, 0xbfc6e944), TOBN(0xb6bc5834, 0x00171cf3), + TOBN(0xe27152b3, 0x83d102b6), TOBN(0xfe695a47, 0x0646b848), + TOBN(0xa5bb09d8, 0x916e6d37), TOBN(0xb4269d64, 0x0d17015e), + TOBN(0x8d8156a1, 0x0a1d2285), TOBN(0xfeef6c51, 0x46d26d72), + TOBN(0x9dac57c8, 0x4c5434a7), TOBN(0x0282e5be, 0x59d39e31), + TOBN(0xedfff181, 0x721c486d), TOBN(0x301baf10, 0xbc58824e), + TOBN(0x8136a6aa, 0x00570031), TOBN(0x55aaf78c, 0x1cddde68), + TOBN(0x26829371, 0x59c63952), TOBN(0x3a3bd274, 0x8bc25baf), + TOBN(0xecdf8657, 0xb7e52dc3), TOBN(0x2dd8c087, 0xfd78e6c8), + TOBN(0x20553274, 0xf5531461), TOBN(0x8b4a1281, 0x5d95499b), + TOBN(0xe2c8763a, 0x1a80f9d2), TOBN(0xd1dbe32b, 0x4ddec758), + TOBN(0xaf12210d, 0x30c34169), TOBN(0xba74a953, 0x78baa533), + TOBN(0x3d133c6e, 0xa438f254), TOBN(0xa431531a, 0x201bef5b), + TOBN(0x15295e22, 0xf669d7ec), TOBN(0xca374f64, 0x357fb515), + TOBN(0x8a8406ff, 0xeaa3fdb3), TOBN(0x106ae448, 0xdf3f2da8), + TOBN(0x8f9b0a90, 0x33c8e9a1), TOBN(0x234645e2, 0x71ad5885), + TOBN(0x3d083224, 0x1c0aed14), TOBN(0xf10a7d3e, 0x7a942d46), + TOBN(0x7c11deee, 0x40d5c9be), TOBN(0xb2bae7ff, 0xba84ed98), + TOBN(0x93e97139, 0xaad58ddd), TOBN(0x3d872796, 0x3f6d1fa3), + TOBN(0x483aca81, 0x8569ff13), TOBN(0x8b89a5fb, 0x9a600f72), + TOBN(0x4cbc27c3, 0xc06f2b86), TOBN(0x22130713, 0x63ad9c0b), + TOBN(0xb5358b1e, 0x48ac2840), TOBN(0x18311294, 0xecba9477), + TOBN(0xda58f990, 0xa6946b43), TOBN(0x3098baf9, 0x9ab41819), + TOBN(0x66c4c158, 0x4198da52), TOBN(0xab4fc17c, 0x146bfd1b), + TOBN(0x2f0a4c3c, 0xbf36a908), TOBN(0x2ae9e34b, 0x58cf7838), + TOBN(0xf411529e, 0x3fa11b1f), TOBN(0x21e43677, 0x974af2b4), + TOBN(0x7c20958e, 0xc230793b), TOBN(0x710ea885, 0x16e840f3), + TOBN(0xfc0b21fc, 0xc5dc67cf), TOBN(0x08d51647, 0x88405718), + TOBN(0xd955c21f, 0xcfe49eb7), TOBN(0x9722a5d5, 0x56dd4a1f), + TOBN(0xc9ef50e2, 0xc861baa5), TOBN(0xc0c21a5d, 0x9505ac3e), + TOBN(0xaf6b9a33, 0x8b7c063f), TOBN(0xc6370339, 0x2f4779c1), + TOBN(0x22df99c7, 0x638167c3), TOBN(0xfe6ffe76, 0x795db30c), + TOBN(0x2b822d33, 0xa4854989), TOBN(0xfef031dd, 0x30563aa5), + TOBN(0x16b09f82, 0xd57c667f), TOBN(0xc70312ce, 0xcc0b76f1), + TOBN(0xbf04a9e6, 0xc9118aec), TOBN(0x82fcb419, 0x3409d133), + TOBN(0x1a8ab385, 0xab45d44d), TOBN(0xfba07222, 0x617b83a3), + TOBN(0xb05f50dd, 0x58e81b52), TOBN(0x1d8db553, 0x21ce5aff), + TOBN(0x3097b8d4, 0xe344a873), TOBN(0x7d8d116d, 0xfe36d53e), + TOBN(0x6db22f58, 0x7875e750), TOBN(0x2dc5e373, 0x43e144ea), + TOBN(0xc05f32e6, 0xe799eb95), TOBN(0xe9e5f4df, 0x6899e6ec), + TOBN(0xbdc3bd68, 0x1fab23d5), TOBN(0xb72b8ab7, 0x73af60e6), + TOBN(0x8db27ae0, 0x2cecc84a), TOBN(0x600016d8, 0x7bdb871c), + TOBN(0x42a44b13, 0xd7c46f58), TOBN(0xb8919727, 0xc3a77d39), + TOBN(0xcfc6bbbd, 0xdafd6088), TOBN(0x1a740146, 0x6bd20d39), + TOBN(0x8c747abd, 0x98c41072), TOBN(0x4c91e765, 0xbdf68ea1), + TOBN(0x7c95e5ca, 0x08819a78), TOBN(0xcf48b729, 0xc9587921), + TOBN(0x091c7c5f, 0xdebbcc7d), TOBN(0x6f287404, 0xf0e05149), + TOBN(0xf83b5ac2, 0x26cd44ec), TOBN(0x88ae32a6, 0xcfea250e), + TOBN(0x6ac5047a, 0x1d06ebc5), TOBN(0xc7e550b4, 0xd434f781), + TOBN(0x61ab1cf2, 0x5c727bd2), TOBN(0x2e4badb1, 0x1cf915b0), + TOBN(0x1b4dadec, 0xf69d3920), TOBN(0xe61b1ca6, 0xf14c1dfe), + TOBN(0x90b479cc, 0xbd6bd51f), TOBN(0x8024e401, 0x8045ec30), + TOBN(0xcab29ca3, 0x25ef0e62), TOBN(0x4f2e9416, 0x49e4ebc0), + TOBN(0x45eb40ec, 0x0ccced58), TOBN(0x25cd4b9c, 0x0da44f98), + TOBN(0x43e06458, 0x871812c6), TOBN(0x99f80d55, 0x16cef651), + TOBN(0x571340c9, 0xce6dc153), TOBN(0x138d5117, 0xd8665521), + TOBN(0xacdb45bc, 0x4e07014d), TOBN(0x2f34bb38, 0x84b60b91), + TOBN(0xf44a4fd2, 0x2ae8921e), TOBN(0xb039288e, 0x892ba1e2), + TOBN(0x9da50174, 0xb1c180b2), TOBN(0x6b70ab66, 0x1693dc87), + TOBN(0x7e9babc9, 0xe7057481), TOBN(0x4581ddef, 0x9c80dc41), + TOBN(0x0c890da9, 0x51294682), TOBN(0x0b5629d3, 0x3f4736e5), + TOBN(0x2340c79e, 0xb06f5b41), TOBN(0xa42e84ce, 0x4e243469), + TOBN(0xf9a20135, 0x045a71a9), TOBN(0xefbfb415, 0xd27b6fb6), + TOBN(0x25ebea23, 0x9d33cd6f), TOBN(0x9caedb88, 0xaa6c0af8), + TOBN(0x53dc7e9a, 0xd9ce6f96), TOBN(0x3897f9fd, 0x51e0b15a), + TOBN(0xf51cb1f8, 0x8e5d788e), TOBN(0x1aec7ba8, 0xe1d490ee), + TOBN(0x265991e0, 0xcc58cb3c), TOBN(0x9f306e8c, 0x9fc3ad31), + TOBN(0x5fed006e, 0x5040a0ac), TOBN(0xca9d5043, 0xfb476f2e), + TOBN(0xa19c06e8, 0xbeea7a23), TOBN(0xd2865801, 0x0edabb63), + TOBN(0xdb92293f, 0x6967469a), TOBN(0x2894d839, 0x8d8a8ed8), + TOBN(0x87c9e406, 0xbbc77122), TOBN(0x8671c6f1, 0x2ea3a26a), + TOBN(0xe42df8d6, 0xd7de9853), TOBN(0x2e3ce346, 0xb1f2bcc7), + TOBN(0xda601dfc, 0x899d50cf), TOBN(0xbfc913de, 0xfb1b598f), + TOBN(0x81c4909f, 0xe61f7908), TOBN(0x192e304f, 0x9bbc7b29), + TOBN(0xc3ed8738, 0xc104b338), TOBN(0xedbe9e47, 0x783f5d61), + TOBN(0x0c06e9be, 0x2db30660), TOBN(0xda3e613f, 0xc0eb7d8e), + TOBN(0xd8fa3e97, 0x322e096e), TOBN(0xfebd91e8, 0xd336e247), + TOBN(0x8f13ccc4, 0xdf655a49), TOBN(0xa9e00dfc, 0x5eb20210), + TOBN(0x84631d0f, 0xc656b6ea), TOBN(0x93a058cd, 0xd8c0d947), + TOBN(0x6846904a, 0x67bd3448), TOBN(0x4a3d4e1a, 0xf394fd5c), + TOBN(0xc102c1a5, 0xdb225f52), TOBN(0xe3455bba, 0xfc4f5e9a), + TOBN(0x6b36985b, 0x4b9ad1ce), TOBN(0xa9818536, 0x5bb7f793), + TOBN(0x6c25e1d0, 0x48b1a416), TOBN(0x1381dd53, 0x3c81bee7), + TOBN(0xd2a30d61, 0x7a4a7620), TOBN(0xc8412926, 0x39b8944c), + TOBN(0x3c1c6fbe, 0x7a97c33a), TOBN(0x941e541d, 0x938664e7), + TOBN(0x417499e8, 0x4a34f239), TOBN(0x15fdb83c, 0xb90402d5), + TOBN(0xb75f46bf, 0x433aa832), TOBN(0xb61e15af, 0x63215db1), + TOBN(0xaabe59d4, 0xa127f89a), TOBN(0x5d541e0c, 0x07e816da), + TOBN(0xaaba0659, 0xa618b692), TOBN(0x55327733, 0x17266026), + TOBN(0xaf53a0fc, 0x95f57552), TOBN(0x32947650, 0x6cacb0c9), + TOBN(0x253ff58d, 0xc821be01), TOBN(0xb0309531, 0xa06f1146), + TOBN(0x59bbbdf5, 0x05c2e54d), TOBN(0x158f27ad, 0x26e8dd22), + TOBN(0xcc5b7ffb, 0x397e1e53), TOBN(0xae03f65b, 0x7fc1e50d), + TOBN(0xa9784ebd, 0x9c95f0f9), TOBN(0x5ed9deb2, 0x24640771), + TOBN(0x31244af7, 0x035561c4), TOBN(0x87332f3a, 0x7ee857de), + TOBN(0x09e16e9e, 0x2b9e0d88), TOBN(0x52d910f4, 0x56a06049), + TOBN(0x507ed477, 0xa9592f48), TOBN(0x85cb917b, 0x2365d678), + TOBN(0xf8511c93, 0x4c8998d1), TOBN(0x2186a3f1, 0x730ea58f), + TOBN(0x50189626, 0xb2029db0), TOBN(0x9137a6d9, 0x02ceb75a), + TOBN(0x2fe17f37, 0x748bc82c), TOBN(0x87c2e931, 0x80469f8c), + TOBN(0x850f71cd, 0xbf891aa2), TOBN(0x0ca1b89b, 0x75ec3d8d), + TOBN(0x516c43aa, 0x5e1cd3cd), TOBN(0x89397808, 0x9a887c28), + TOBN(0x0059c699, 0xddea1f9f), TOBN(0x7737d6fa, 0x8e6868f7), + TOBN(0x6d93746a, 0x60f1524b), TOBN(0x36985e55, 0xba052aa7), + TOBN(0x41b1d322, 0xed923ea5), TOBN(0x3429759f, 0x25852a11), + TOBN(0xbeca6ec3, 0x092e9f41), TOBN(0x3a238c66, 0x62256bbd), + TOBN(0xd82958ea, 0x70ad487d), TOBN(0x4ac8aaf9, 0x65610d93), + TOBN(0x3fa101b1, 0x5e4ccab0), TOBN(0x9bf430f2, 0x9de14bfb), + TOBN(0xa10f5cc6, 0x6531899d), TOBN(0x590005fb, 0xea8ce17d), + TOBN(0xc437912f, 0x24544cb6), TOBN(0x9987b71a, 0xd79ac2e3), + TOBN(0x13e3d9dd, 0xc058a212), TOBN(0x00075aac, 0xd2de9606), + TOBN(0x80ab508b, 0x6cac8369), TOBN(0x87842be7, 0xf54f6c89), + TOBN(0xa7ad663d, 0x6bc532a4), TOBN(0x67813de7, 0x78a91bc8), + TOBN(0x5dcb61ce, 0xc3427239), TOBN(0x5f3c7cf0, 0xc56934d9), + TOBN(0xc079e0fb, 0xe3191591), TOBN(0xe40896bd, 0xb01aada7), + TOBN(0x8d466791, 0x0492d25f), TOBN(0x8aeb30c9, 0xe7408276), + TOBN(0xe9437495, 0x9287aacc), TOBN(0x23d4708d, 0x79fe03d4), + TOBN(0x8cda9cf2, 0xd0c05199), TOBN(0x502fbc22, 0xfae78454), + TOBN(0xc0bda9df, 0xf572a182), TOBN(0x5f9b71b8, 0x6158b372), + TOBN(0xe0f33a59, 0x2b82dd07), TOBN(0x76302735, 0x9523032e), + TOBN(0x7fe1a721, 0xc4505a32), TOBN(0x7b6e3e82, 0xf796409f),} + , + {TOBN(0xe3417bc0, 0x35d0b34a), TOBN(0x440b386b, 0x8327c0a7), + TOBN(0x8fb7262d, 0xac0362d1), TOBN(0x2c41114c, 0xe0cdf943), + TOBN(0x2ba5cef1, 0xad95a0b1), TOBN(0xc09b37a8, 0x67d54362), + TOBN(0x26d6cdd2, 0x01e486c9), TOBN(0x20477abf, 0x42ff9297), + TOBN(0xa004dcb3, 0x292a9287), TOBN(0xddc15cf6, 0x77b092c7), + TOBN(0x083a8464, 0x806c0605), TOBN(0x4a68df70, 0x3db997b0), + TOBN(0x9c134e45, 0x05bf7dd0), TOBN(0xa4e63d39, 0x8ccf7f8c), + TOBN(0xa6e6517f, 0x41b5f8af), TOBN(0xaa8b9342, 0xad7bc1cc), + TOBN(0x126f35b5, 0x1e706ad9), TOBN(0xb99cebb4, 0xc3a9ebdf), + TOBN(0xa75389af, 0xbf608d90), TOBN(0x76113c4f, 0xc6c89858), + TOBN(0x80de8eb0, 0x97e2b5aa), TOBN(0x7e1022cc, 0x63b91304), + TOBN(0x3bdab605, 0x6ccc066c), TOBN(0x33cbb144, 0xb2edf900), + TOBN(0xc4176471, 0x7af715d2), TOBN(0xe2f7f594, 0xd0134a96), + TOBN(0x2c1873ef, 0xa41ec956), TOBN(0xe4e7b4f6, 0x77821304), + TOBN(0xe5c8ff97, 0x88d5374a), TOBN(0x2b915e63, 0x80823d5b), + TOBN(0xea6bc755, 0xb2ee8fe2), TOBN(0x6657624c, 0xe7112651), + TOBN(0x157af101, 0xdace5aca), TOBN(0xc4fdbcf2, 0x11a6a267), + TOBN(0xdaddf340, 0xc49c8609), TOBN(0x97e49f52, 0xe9604a65), + TOBN(0x9be8e790, 0x937e2ad5), TOBN(0x846e2508, 0x326e17f1), + TOBN(0x3f38007a, 0x0bbbc0dc), TOBN(0xcf03603f, 0xb11e16d6), + TOBN(0xd6f800e0, 0x7442f1d5), TOBN(0x475607d1, 0x66e0e3ab), + TOBN(0x82807f16, 0xb7c64047), TOBN(0x8858e1e3, 0xa749883d), + TOBN(0x5859120b, 0x8231ee10), TOBN(0x1b80e7eb, 0x638a1ece), + TOBN(0xcb72525a, 0xc6aa73a4), TOBN(0xa7cdea3d, 0x844423ac), + TOBN(0x5ed0c007, 0xf8ae7c38), TOBN(0x6db07a5c, 0x3d740192), + TOBN(0xbe5e9c2a, 0x5fe36db3), TOBN(0xd5b9d57a, 0x76e95046), + TOBN(0x54ac32e7, 0x8eba20f2), TOBN(0xef11ca8f, 0x71b9a352), + TOBN(0x305e373e, 0xff98a658), TOBN(0xffe5a100, 0x823eb667), + TOBN(0x57477b11, 0xe51732d2), TOBN(0xdfd6eb28, 0x2538fc0e), + TOBN(0x5c43b0cc, 0x3b39eec5), TOBN(0x6af12778, 0xcb36cc57), + TOBN(0x70b0852d, 0x06c425ae), TOBN(0x6df92f8c, 0x5c221b9b), + TOBN(0x6c8d4f9e, 0xce826d9c), TOBN(0xf59aba7b, 0xb49359c3), + TOBN(0x5c8ed8d5, 0xda64309d), TOBN(0x61a6de56, 0x91b30704), + TOBN(0xd6b52f6a, 0x2f9b5808), TOBN(0x0eee4194, 0x98c958a7), + TOBN(0xcddd9aab, 0x771e4caa), TOBN(0x83965dfd, 0x78bc21be), + TOBN(0x02affce3, 0xb3b504f5), TOBN(0x30847a21, 0x561c8291), + TOBN(0xd2eb2cf1, 0x52bfda05), TOBN(0xe0e4c4e9, 0x6197b98c), + TOBN(0x1d35076c, 0xf8a1726f), TOBN(0x6c06085b, 0x2db11e3d), + TOBN(0x15c0c4d7, 0x4463ba14), TOBN(0x9d292f83, 0x0030238c), + TOBN(0x1311ee8b, 0x3727536d), TOBN(0xfeea86ef, 0xbeaedc1e), + TOBN(0xb9d18cd3, 0x66131e2e), TOBN(0xf31d974f, 0x80fe2682), + TOBN(0xb6e49e0f, 0xe4160289), TOBN(0x7c48ec0b, 0x08e92799), + TOBN(0x818111d8, 0xd1989aa7), TOBN(0xb34fa0aa, 0xebf926f9), + TOBN(0xdb5fe2f5, 0xa245474a), TOBN(0xf80a6ebb, 0x3c7ca756), + TOBN(0xa7f96054, 0xafa05dd8), TOBN(0x26dfcf21, 0xfcaf119e), + TOBN(0xe20ef2e3, 0x0564bb59), TOBN(0xef4dca50, 0x61cb02b8), + TOBN(0xcda7838a, 0x65d30672), TOBN(0x8b08d534, 0xfd657e86), + TOBN(0x4c5b4395, 0x46d595c8), TOBN(0x39b58725, 0x425cb836), + TOBN(0x8ea61059, 0x3de9abe3), TOBN(0x40434881, 0x9cdc03be), + TOBN(0x9b261245, 0xcfedce8c), TOBN(0x78c318b4, 0xcf5234a1), + TOBN(0x510bcf16, 0xfde24c99), TOBN(0x2a77cb75, 0xa2c2ff5d), + TOBN(0x9c895c2b, 0x27960fb4), TOBN(0xd30ce975, 0xb0eda42b), + TOBN(0xfda85393, 0x1a62cc26), TOBN(0x23c69b96, 0x50c0e052), + TOBN(0xa227df15, 0xbfc633f3), TOBN(0x2ac78848, 0x1bae7d48), + TOBN(0x487878f9, 0x187d073d), TOBN(0x6c2be919, 0x967f807d), + TOBN(0x765861d8, 0x336e6d8f), TOBN(0x88b8974c, 0xce528a43), + TOBN(0x09521177, 0xff57d051), TOBN(0x2ff38037, 0xfb6a1961), + TOBN(0xfc0aba74, 0xa3d76ad4), TOBN(0x7c764803, 0x25a7ec17), + TOBN(0x7532d75f, 0x48879bc8), TOBN(0xea7eacc0, 0x58ce6bc1), + TOBN(0xc82176b4, 0x8e896c16), TOBN(0x9a30e0b2, 0x2c750fed), + TOBN(0xc37e2c2e, 0x421d3aa4), TOBN(0xf926407c, 0xe84fa840), + TOBN(0x18abc03d, 0x1454e41c), TOBN(0x26605ecd, 0x3f7af644), + TOBN(0x242341a6, 0xd6a5eabf), TOBN(0x1edb84f4, 0x216b668e), + TOBN(0xd836edb8, 0x04010102), TOBN(0x5b337ce7, 0x945e1d8c), + TOBN(0xd2075c77, 0xc055dc14), TOBN(0x2a0ffa25, 0x81d89cdf), + TOBN(0x8ce815ea, 0x6ffdcbaf), TOBN(0xa3428878, 0xfb648867), + TOBN(0x277699cf, 0x884655fb), TOBN(0xfa5b5bd6, 0x364d3e41), + TOBN(0x01f680c6, 0x441e1cb7), TOBN(0x3fd61e66, 0xb70a7d67), + TOBN(0x666ba2dc, 0xcc78cf66), TOBN(0xb3018174, 0x6fdbff77), + TOBN(0x8d4dd0db, 0x168d4668), TOBN(0x259455d0, 0x1dab3a2a), + TOBN(0xf58564c5, 0xcde3acec), TOBN(0x77141925, 0x13adb276), + TOBN(0x527d725d, 0x8a303f65), TOBN(0x55deb6c9, 0xe6f38f7b), + TOBN(0xfd5bb657, 0xb1fa70fb), TOBN(0xfa07f50f, 0xd8073a00), + TOBN(0xf72e3aa7, 0xbca02500), TOBN(0xf68f895d, 0x9975740d), + TOBN(0x30112060, 0x5cae2a6a), TOBN(0x01bd7218, 0x02874842), + TOBN(0x3d423891, 0x7ce47bd3), TOBN(0xa66663c1, 0x789544f6), + TOBN(0x864d05d7, 0x3272d838), TOBN(0xe22924f9, 0xfa6295c5), + TOBN(0x8189593f, 0x6c2fda32), TOBN(0x330d7189, 0xb184b544), + TOBN(0x79efa62c, 0xbde1f714), TOBN(0x35771c94, 0xe5cb1a63), + TOBN(0x2f4826b8, 0x641c8332), TOBN(0x00a894fb, 0xc8cee854), + TOBN(0xb4b9a39b, 0x36194d40), TOBN(0xe857a7c5, 0x77612601), + TOBN(0xf4209dd2, 0x4ecf2f58), TOBN(0x82b9e66d, 0x5a033487), + TOBN(0xc1e36934, 0xe4e8b9dd), TOBN(0xd2372c9d, 0xa42377d7), + TOBN(0x51dc94c7, 0x0e3ae43b), TOBN(0x4c57761e, 0x04474f6f), + TOBN(0xdcdacd0a, 0x1058a318), TOBN(0x369cf3f5, 0x78053a9a), + TOBN(0xc6c3de50, 0x31c68de2), TOBN(0x4653a576, 0x3c4b6d9f), + TOBN(0x1688dd5a, 0xaa4e5c97), TOBN(0x5be80aa1, 0xb7ab3c74), + TOBN(0x70cefe7c, 0xbc65c283), TOBN(0x57f95f13, 0x06867091), + TOBN(0xa39114e2, 0x4415503b), TOBN(0xc08ff7c6, 0x4cbb17e9), + TOBN(0x1eff674d, 0xd7dec966), TOBN(0x6d4690af, 0x53376f63), + TOBN(0xff6fe32e, 0xea74237b), TOBN(0xc436d17e, 0xcd57508e), + TOBN(0x15aa28e1, 0xedcc40fe), TOBN(0x0d769c04, 0x581bbb44), + TOBN(0xc240b6de, 0x34eaacda), TOBN(0xd9e116e8, 0x2ba0f1de), + TOBN(0xcbe45ec7, 0x79438e55), TOBN(0x91787c9d, 0x96f752d7), + TOBN(0x897f532b, 0xf129ac2f), TOBN(0xd307b7c8, 0x5a36e22c), + TOBN(0x91940675, 0x749fb8f3), TOBN(0xd14f95d0, 0x157fdb28), + TOBN(0xfe51d029, 0x6ae55043), TOBN(0x8931e98f, 0x44a87de1), + TOBN(0xe57f1cc6, 0x09e4fee2), TOBN(0x0d063b67, 0x4e072d92), + TOBN(0x70a998b9, 0xed0e4316), TOBN(0xe74a736b, 0x306aca46), + TOBN(0xecf0fbf2, 0x4fda97c7), TOBN(0xa40f65cb, 0x3e178d93), + TOBN(0x16253604, 0x16df4285), TOBN(0xb0c9babb, 0xd0c56ae2), + TOBN(0x73032b19, 0xcfc5cfc3), TOBN(0xe497e5c3, 0x09752056), + TOBN(0x12096bb4, 0x164bda96), TOBN(0x1ee42419, 0xa0b74da1), + TOBN(0x8fc36243, 0x403826ba), TOBN(0x0c8f0069, 0xdc09e660), + TOBN(0x8667e981, 0xc27253c9), TOBN(0x05a6aefb, 0x92b36a45), + TOBN(0xa62c4b36, 0x9cb7bb46), TOBN(0x8394f375, 0x11f7027b), + TOBN(0x747bc79c, 0x5f109d0f), TOBN(0xcad88a76, 0x5b8cc60a), + TOBN(0x80c5a66b, 0x58f09e68), TOBN(0xe753d451, 0xf6127eac), + TOBN(0xc44b74a1, 0x5b0ec6f5), TOBN(0x47989fe4, 0x5289b2b8), + TOBN(0x745f8484, 0x58d6fc73), TOBN(0xec362a6f, 0xf61c70ab), + TOBN(0x070c98a7, 0xb3a8ad41), TOBN(0x73a20fc0, 0x7b63db51), + TOBN(0xed2c2173, 0xf44c35f4), TOBN(0x8a56149d, 0x9acc9dca), + TOBN(0x98f17881, 0x9ac6e0f4), TOBN(0x360fdeaf, 0xa413b5ed), + TOBN(0x0625b8f4, 0xa300b0fd), TOBN(0xf1f4d76a, 0x5b3222d3), + TOBN(0x9d6f5109, 0x587f76b8), TOBN(0x8b4ee08d, 0x2317fdb5), + TOBN(0x88089bb7, 0x8c68b095), TOBN(0x95570e9a, 0x5808d9b9), + TOBN(0xa395c36f, 0x35d33ae7), TOBN(0x200ea123, 0x50bb5a94), + TOBN(0x20c789bd, 0x0bafe84b), TOBN(0x243ef52d, 0x0919276a), + TOBN(0x3934c577, 0xe23ae233), TOBN(0xb93807af, 0xa460d1ec), + TOBN(0xb72a53b1, 0xf8fa76a4), TOBN(0xd8914cb0, 0xc3ca4491), + TOBN(0x2e128494, 0x3fb42622), TOBN(0x3b2700ac, 0x500907d5), + TOBN(0xf370fb09, 0x1a95ec63), TOBN(0xf8f30be2, 0x31b6dfbd), + TOBN(0xf2b2f8d2, 0x69e55f15), TOBN(0x1fead851, 0xcc1323e9), + TOBN(0xfa366010, 0xd9e5eef6), TOBN(0x64d487b0, 0xe316107e), + TOBN(0x4c076b86, 0xd23ddc82), TOBN(0x03fd344c, 0x7e0143f0), + TOBN(0xa95362ff, 0x317af2c5), TOBN(0x0add3db7, 0xe18b7a4f), + TOBN(0x9c673e3f, 0x8260e01b), TOBN(0xfbeb49e5, 0x54a1cc91), + TOBN(0x91351bf2, 0x92f2e433), TOBN(0xc755e7ec, 0x851141eb), + TOBN(0xc9a95139, 0x29607745), TOBN(0x0ca07420, 0xa26f2b28), + TOBN(0xcb2790e7, 0x4bc6f9dd), TOBN(0x345bbb58, 0xadcaffc0), + TOBN(0xc65ea38c, 0xbe0f27a2), TOBN(0x67c24d7c, 0x641fcb56), + TOBN(0x2c25f0a7, 0xa9e2c757), TOBN(0x93f5cdb0, 0x16f16c49), + TOBN(0x2ca5a9d7, 0xc5ee30a1), TOBN(0xd1593635, 0xb909b729), + TOBN(0x804ce9f3, 0xdadeff48), TOBN(0xec464751, 0xb07c30c3), + TOBN(0x89d65ff3, 0x9e49af6a), TOBN(0xf2d6238a, 0x6f3d01bc), + TOBN(0x1095561e, 0x0bced843), TOBN(0x51789e12, 0xc8a13fd8), + TOBN(0xd633f929, 0x763231df), TOBN(0x46df9f7d, 0xe7cbddef), + TOBN(0x01c889c0, 0xcb265da8), TOBN(0xfce1ad10, 0xaf4336d2), + TOBN(0x8d110df6, 0xfc6a0a7e), TOBN(0xdd431b98, 0x6da425dc), + TOBN(0xcdc4aeab, 0x1834aabe), TOBN(0x84deb124, 0x8439b7fc), + TOBN(0x8796f169, 0x3c2a5998), TOBN(0x9b9247b4, 0x7947190d), + TOBN(0x55b9d9a5, 0x11597014), TOBN(0x7e9dd70d, 0x7b1566ee), + TOBN(0x94ad78f7, 0xcbcd5e64), TOBN(0x0359ac17, 0x9bd4c032), + TOBN(0x3b11baaf, 0x7cc222ae), TOBN(0xa6a6e284, 0xba78e812), + TOBN(0x8392053f, 0x24cea1a0), TOBN(0xc97bce4a, 0x33621491), + TOBN(0x7eb1db34, 0x35399ee9), TOBN(0x473f78ef, 0xece81ad1), + TOBN(0x41d72fe0, 0xf63d3d0d), TOBN(0xe620b880, 0xafab62fc), + TOBN(0x92096bc9, 0x93158383), TOBN(0x41a21357, 0x8f896f6c), + TOBN(0x1b5ee2fa, 0xc7dcfcab), TOBN(0x650acfde, 0x9546e007), + TOBN(0xc081b749, 0xb1b02e07), TOBN(0xda9e41a0, 0xf9eca03d), + TOBN(0x013ba727, 0x175a54ab), TOBN(0xca0cd190, 0xea5d8d10), + TOBN(0x85ea52c0, 0x95fd96a9), TOBN(0x2c591b9f, 0xbc5c3940), + TOBN(0x6fb4d4e4, 0x2bad4d5f), TOBN(0xfa4c3590, 0xfef0059b), + TOBN(0x6a10218a, 0xf5122294), TOBN(0x9a78a81a, 0xa85751d1), + TOBN(0x04f20579, 0xa98e84e7), TOBN(0xfe1242c0, 0x4997e5b5), + TOBN(0xe77a273b, 0xca21e1e4), TOBN(0xfcc8b1ef, 0x9411939d), + TOBN(0xe20ea302, 0x92d0487a), TOBN(0x1442dbec, 0x294b91fe), + TOBN(0x1f7a4afe, 0xbb6b0e8f), TOBN(0x1700ef74, 0x6889c318), + TOBN(0xf5bbffc3, 0x70f1fc62), TOBN(0x3b31d4b6, 0x69c79cca), + TOBN(0xe8bc2aab, 0xa7f6340d), TOBN(0xb0b08ab4, 0xa725e10a), + TOBN(0x44f05701, 0xae340050), TOBN(0xba4b3016, 0x1cf0c569), + TOBN(0x5aa29f83, 0xfbe19a51), TOBN(0x1b9ed428, 0xb71d752e), + TOBN(0x1666e54e, 0xeb4819f5), TOBN(0x616cdfed, 0x9e18b75b), + TOBN(0x112ed5be, 0x3ee27b0b), TOBN(0xfbf28319, 0x44c7de4d), + TOBN(0xd685ec85, 0xe0e60d84), TOBN(0x68037e30, 0x1db7ee78), + TOBN(0x5b65bdcd, 0x003c4d6e), TOBN(0x33e7363a, 0x93e29a6a), + TOBN(0x995b3a61, 0x08d0756c), TOBN(0xd727f85c, 0x2faf134b), + TOBN(0xfac6edf7, 0x1d337823), TOBN(0x99b9aa50, 0x0439b8b4), + TOBN(0x722eb104, 0xe2b4e075), TOBN(0x49987295, 0x437c4926), + TOBN(0xb1e4c0e4, 0x46a9b82d), TOBN(0xd0cb3197, 0x57a006f5), + TOBN(0xf3de0f7d, 0xd7808c56), TOBN(0xb5c54d8f, 0x51f89772), + TOBN(0x500a114a, 0xadbd31aa), TOBN(0x9afaaaa6, 0x295f6cab), + TOBN(0x94705e21, 0x04cf667a), TOBN(0xfc2a811b, 0x9d3935d7), + TOBN(0x560b0280, 0x6d09267c), TOBN(0xf19ed119, 0xf780e53b), + TOBN(0xf0227c09, 0x067b6269), TOBN(0x967b8533, 0x5caef599), + TOBN(0x155b9243, 0x68efeebc), TOBN(0xcd6d34f5, 0xc497bae6), + TOBN(0x1dd8d5d3, 0x6cceb370), TOBN(0x2aeac579, 0xa78d7bf9), + TOBN(0x5d65017d, 0x70b67a62), TOBN(0x70c8e44f, 0x17c53f67), + TOBN(0xd1fc0950, 0x86a34d09), TOBN(0xe0fca256, 0xe7134907), + TOBN(0xe24fa29c, 0x80fdd315), TOBN(0x2c4acd03, 0xd87499ad), + TOBN(0xbaaf7517, 0x3b5a9ba6), TOBN(0xb9cbe1f6, 0x12e51a51), + TOBN(0xd88edae3, 0x5e154897), TOBN(0xe4309c3c, 0x77b66ca0), + TOBN(0xf5555805, 0xf67f3746), TOBN(0x85fc37ba, 0xa36401ff), + TOBN(0xdf86e2ca, 0xd9499a53), TOBN(0x6270b2a3, 0xecbc955b), + TOBN(0xafae64f5, 0x974ad33b), TOBN(0x04d85977, 0xfe7b2df1), + TOBN(0x2a3db3ff, 0x4ab03f73), TOBN(0x0b87878a, 0x8702740a), + TOBN(0x6d263f01, 0x5a061732), TOBN(0xc25430ce, 0xa32a1901), + TOBN(0xf7ebab3d, 0xdb155018), TOBN(0x3a86f693, 0x63a9b78e), + TOBN(0x349ae368, 0xda9f3804), TOBN(0x470f07fe, 0xa164349c), + TOBN(0xd52f4cc9, 0x8562baa5), TOBN(0xc74a9e86, 0x2b290df3), + TOBN(0xd3a1aa35, 0x43471a24), TOBN(0x239446be, 0xb8194511), + TOBN(0xbec2dd00, 0x81dcd44d), TOBN(0xca3d7f0f, 0xc42ac82d), + TOBN(0x1f3db085, 0xfdaf4520), TOBN(0xbb6d3e80, 0x4549daf2), + TOBN(0xf5969d8a, 0x19ad5c42), TOBN(0x7052b13d, 0xdbfd1511), + TOBN(0x11890d1b, 0x682b9060), TOBN(0xa71d3883, 0xac34452c), + TOBN(0xa438055b, 0x783805b4), TOBN(0x43241277, 0x4725b23e), + TOBN(0xf20cf96e, 0x4901bbed), TOBN(0x6419c710, 0xf432a2bb), + TOBN(0x57a0fbb9, 0xdfa9cd7d), TOBN(0x589111e4, 0x00daa249), + TOBN(0x19809a33, 0x7b60554e), TOBN(0xea5f8887, 0xede283a4), + TOBN(0x2d713802, 0x503bfd35), TOBN(0x151bb0af, 0x585d2a53), + TOBN(0x40b08f74, 0x43b30ca8), TOBN(0xe10b5bba, 0xd9934583), + TOBN(0xe8a546d6, 0xb51110ad), TOBN(0x1dd50e66, 0x28e0b6c5), + TOBN(0x292e9d54, 0xcff2b821), TOBN(0x3882555d, 0x47281760), + TOBN(0x134838f8, 0x3724d6e3), TOBN(0xf2c679e0, 0x22ddcda1), + TOBN(0x40ee8815, 0x6d2a5768), TOBN(0x7f227bd2, 0x1c1e7e2d), + TOBN(0x487ba134, 0xd04ff443), TOBN(0x76e2ff3d, 0xc614e54b), + TOBN(0x36b88d6f, 0xa3177ec7), TOBN(0xbf731d51, 0x2328fff5), + TOBN(0x758caea2, 0x49ba158e), TOBN(0x5ab8ff4c, 0x02938188), + TOBN(0x33e16056, 0x35edc56d), TOBN(0x5a69d349, 0x7e940d79), + TOBN(0x6c4fd001, 0x03866dcb), TOBN(0x20a38f57, 0x4893cdef), + TOBN(0xfbf3e790, 0xfac3a15b), TOBN(0x6ed7ea2e, 0x7a4f8e6b), + TOBN(0xa663eb4f, 0xbc3aca86), TOBN(0x22061ea5, 0x080d53f7), + TOBN(0x2480dfe6, 0xf546783f), TOBN(0xd38bc6da, 0x5a0a641e), + TOBN(0xfb093cd1, 0x2ede8965), TOBN(0x89654db4, 0xacb455cf), + TOBN(0x413cbf9a, 0x26e1adee), TOBN(0x291f3764, 0x373294d4), + TOBN(0x00797257, 0x648083fe), TOBN(0x25f504d3, 0x208cc341), + TOBN(0x635a8e5e, 0xc3a0ee43), TOBN(0x70aaebca, 0x679898ff), + TOBN(0x9ee9f547, 0x5dc63d56), TOBN(0xce987966, 0xffb34d00), + TOBN(0xf9f86b19, 0x5e26310a), TOBN(0x9e435484, 0x382a8ca8), + TOBN(0x253bcb81, 0xc2352fe4), TOBN(0xa4eac8b0, 0x4474b571), + TOBN(0xc1b97512, 0xc1ad8cf8), TOBN(0x193b4e9e, 0x99e0b697), + TOBN(0x939d2716, 0x01e85df0), TOBN(0x4fb265b3, 0xcd44eafd), + TOBN(0x321e7dcd, 0xe51e1ae2), TOBN(0x8e3a8ca6, 0xe3d8b096), + TOBN(0x8de46cb0, 0x52604998), TOBN(0x91099ad8, 0x39072aa7), + TOBN(0x2617f91c, 0x93aa96b8), TOBN(0x0fc8716b, 0x7fca2e13), + TOBN(0xa7106f5e, 0x95328723), TOBN(0xd1c9c40b, 0x262e6522), + TOBN(0xb9bafe86, 0x42b7c094), TOBN(0x1873439d, 0x1543c021), + TOBN(0xe1baa5de, 0x5cbefd5d), TOBN(0xa363fc5e, 0x521e8aff), + TOBN(0xefe6320d, 0xf862eaac), TOBN(0x14419c63, 0x22c647dc), + TOBN(0x0e06707c, 0x4e46d428), TOBN(0xcb6c834f, 0x4a178f8f), + TOBN(0x0f993a45, 0xd30f917c), TOBN(0xd4c4b049, 0x9879afee), + TOBN(0xb6142a1e, 0x70500063), TOBN(0x7c9b41c3, 0xa5d9d605), + TOBN(0xbc00fc2f, 0x2f8ba2c7), TOBN(0x0966eb2f, 0x7c67aa28), + TOBN(0x13f7b516, 0x5a786972), TOBN(0x3bfb7557, 0x8a2fbba0), + TOBN(0x131c4f23, 0x5a2b9620), TOBN(0xbff3ed27, 0x6faf46be), + TOBN(0x9b4473d1, 0x7e172323), TOBN(0x421e8878, 0x339f6246), + TOBN(0x0fa8587a, 0x25a41632), TOBN(0xc0814124, 0xa35b6c93), + TOBN(0x2b18a9f5, 0x59ebb8db), TOBN(0x264e3357, 0x76edb29c), + TOBN(0xaf245ccd, 0xc87c51e2), TOBN(0x16b3015b, 0x501e6214), + TOBN(0xbb31c560, 0x0a3882ce), TOBN(0x6961bb94, 0xfec11e04), + TOBN(0x3b825b8d, 0xeff7a3a0), TOBN(0xbec33738, 0xb1df7326), + TOBN(0x68ad747c, 0x99604a1f), TOBN(0xd154c934, 0x9a3bd499), + TOBN(0xac33506f, 0x1cc7a906), TOBN(0x73bb5392, 0x6c560e8f), + TOBN(0x6428fcbe, 0x263e3944), TOBN(0xc11828d5, 0x1c387434), + TOBN(0x3cd04be1, 0x3e4b12ff), TOBN(0xc3aad9f9, 0x2d88667c), + TOBN(0xc52ddcf8, 0x248120cf), TOBN(0x985a892e, 0x2a389532), + TOBN(0xfbb4b21b, 0x3bb85fa0), TOBN(0xf95375e0, 0x8dfc6269), + TOBN(0xfb4fb06c, 0x7ee2acea), TOBN(0x6785426e, 0x309c4d1f), + TOBN(0x659b17c8, 0xd8ceb147), TOBN(0x9b649eee, 0xb70a5554), + TOBN(0x6b7fa0b5, 0xac6bc634), TOBN(0xd99fe2c7, 0x1d6e732f), + TOBN(0x30e6e762, 0x8d3abba2), TOBN(0x18fee6e7, 0xa797b799), + TOBN(0x5c9d360d, 0xc696464d), TOBN(0xe3baeb48, 0x27bfde12), + TOBN(0x2bf5db47, 0xf23206d5), TOBN(0x2f6d3420, 0x1d260152), + TOBN(0x17b87653, 0x3f8ff89a), TOBN(0x5157c30c, 0x378fa458), + TOBN(0x7517c5c5, 0x2d4fb936), TOBN(0xef22f7ac, 0xe6518cdc), + TOBN(0xdeb483e6, 0xbf847a64), TOBN(0xf5084558, 0x92e0fa89),} + , + {TOBN(0xab9659d8, 0xdf7304d4), TOBN(0xb71bcf1b, 0xff210e8e), + TOBN(0xa9a2438b, 0xd73fbd60), TOBN(0x4595cd1f, 0x5d11b4de), + TOBN(0x9c0d329a, 0x4835859d), TOBN(0x4a0f0d2d, 0x7dbb6e56), + TOBN(0xc6038e5e, 0xdf928a4e), TOBN(0xc9429621, 0x8f5ad154), + TOBN(0x91213462, 0xf23f2d92), TOBN(0x6cab71bd, 0x60b94078), + TOBN(0x6bdd0a63, 0x176cde20), TOBN(0x54c9b20c, 0xee4d54bc), + TOBN(0x3cd2d8aa, 0x9f2ac02f), TOBN(0x03f8e617, 0x206eedb0), + TOBN(0xc7f68e16, 0x93086434), TOBN(0x831469c5, 0x92dd3db9), + TOBN(0x8521df24, 0x8f981354), TOBN(0x587e23ec, 0x3588a259), + TOBN(0xcbedf281, 0xd7a0992c), TOBN(0x06930a55, 0x38961407), + TOBN(0x09320deb, 0xbe5bbe21), TOBN(0xa7ffa5b5, 0x2491817f), + TOBN(0xe6c8b4d9, 0x09065160), TOBN(0xac4f3992, 0xfff6d2a9), + TOBN(0x7aa7a158, 0x3ae9c1bd), TOBN(0xe0af6d98, 0xe37ce240), + TOBN(0xe54342d9, 0x28ab38b4), TOBN(0xe8b75007, 0x0a1c98ca), + TOBN(0xefce86af, 0xe02358f2), TOBN(0x31b8b856, 0xea921228), + TOBN(0x052a1912, 0x0a1c67fc), TOBN(0xb4069ea4, 0xe3aead59), + TOBN(0x3232d6e2, 0x7fa03cb3), TOBN(0xdb938e5b, 0x0fdd7d88), + TOBN(0x04c1d2cd, 0x2ccbfc5d), TOBN(0xd2f45c12, 0xaf3a580f), + TOBN(0x592620b5, 0x7883e614), TOBN(0x5fd27e68, 0xbe7c5f26), + TOBN(0x139e45a9, 0x1567e1e3), TOBN(0x2cc71d2d, 0x44d8aaaf), + TOBN(0x4a9090cd, 0xe36d0757), TOBN(0xf722d7b1, 0xd9a29382), + TOBN(0xfb7fb04c, 0x04b48ddf), TOBN(0x628ad2a7, 0xebe16f43), + TOBN(0xcd3fbfb5, 0x20226040), TOBN(0x6c34ecb1, 0x5104b6c4), + TOBN(0x30c0754e, 0xc903c188), TOBN(0xec336b08, 0x2d23cab0), + TOBN(0x473d62a2, 0x1e206ee5), TOBN(0xf1e27480, 0x8c49a633), + TOBN(0x87ab956c, 0xe9f6b2c3), TOBN(0x61830b48, 0x62b606ea), + TOBN(0x67cd6846, 0xe78e815f), TOBN(0xfe40139f, 0x4c02082a), + TOBN(0x52bbbfcb, 0x952ec365), TOBN(0x74c11642, 0x6b9836ab), + TOBN(0x9f51439e, 0x558df019), TOBN(0x230da4ba, 0xac712b27), + TOBN(0x518919e3, 0x55185a24), TOBN(0x4dcefcdd, 0x84b78f50), + TOBN(0xa7d90fb2, 0xa47d4c5a), TOBN(0x55ac9abf, 0xb30e009e), + TOBN(0xfd2fc359, 0x74eed273), TOBN(0xb72d824c, 0xdbea8faf), + TOBN(0xce721a74, 0x4513e2ca), TOBN(0x0b418612, 0x38240b2c), + TOBN(0x05199968, 0xd5baa450), TOBN(0xeb1757ed, 0x2b0e8c25), + TOBN(0x6ebc3e28, 0x3dfac6d5), TOBN(0xb2431e2e, 0x48a237f5), + TOBN(0x2acb5e23, 0x52f61499), TOBN(0x5558a2a7, 0xe06c936b), + TOBN(0xd213f923, 0xcbb13d1b), TOBN(0x98799f42, 0x5bfb9bfe), + TOBN(0x1ae8ddc9, 0x701144a9), TOBN(0x0b8b3bb6, 0x4c5595ee), + TOBN(0x0ea9ef2e, 0x3ecebb21), TOBN(0x17cb6c4b, 0x3671f9a7), + TOBN(0x47ef464f, 0x726f1d1f), TOBN(0x171b9484, 0x6943a276), + TOBN(0x51a4ae2d, 0x7ef0329c), TOBN(0x08509222, 0x91c4402a), + TOBN(0x64a61d35, 0xafd45bbc), TOBN(0x38f096fe, 0x3035a851), + TOBN(0xc7468b74, 0xa1dec027), TOBN(0xe8cf10e7, 0x4fc7dcba), + TOBN(0xea35ff40, 0xf4a06353), TOBN(0x0b4c0dfa, 0x8b77dd66), + TOBN(0x779b8552, 0xde7e5c19), TOBN(0xfab28609, 0xc1c0256c), + TOBN(0x64f58eee, 0xabd4743d), TOBN(0x4e8ef838, 0x7b6cc93b), + TOBN(0xee650d26, 0x4cb1bf3d), TOBN(0x4c1f9d09, 0x73dedf61), + TOBN(0xaef7c9d7, 0xbfb70ced), TOBN(0x1ec0507e, 0x1641de1e), + TOBN(0xcd7e5cc7, 0xcde45079), TOBN(0xde173c9a, 0x516ac9e4), + TOBN(0x517a8494, 0xc170315c), TOBN(0x438fd905, 0x91d8e8fb), + TOBN(0x5145c506, 0xc7d9630b), TOBN(0x6457a87b, 0xf47d4d75), + TOBN(0xd31646bf, 0x0d9a80e8), TOBN(0x453add2b, 0xcef3aabe), + TOBN(0xc9941109, 0xa607419d), TOBN(0xfaa71e62, 0xbb6bca80), + TOBN(0x34158c13, 0x07c431f3), TOBN(0x594abebc, 0x992bc47a), + TOBN(0x6dfea691, 0xeb78399f), TOBN(0x48aafb35, 0x3f42cba4), + TOBN(0xedcd65af, 0x077c04f0), TOBN(0x1a29a366, 0xe884491a), + TOBN(0x023a40e5, 0x1c21f2bf), TOBN(0xf99a513c, 0xa5057aee), + TOBN(0xa3fe7e25, 0xbcab072e), TOBN(0x8568d2e1, 0x40e32bcf), + TOBN(0x904594eb, 0xd3f69d9f), TOBN(0x181a9733, 0x07affab1), + TOBN(0xe4d68d76, 0xb6e330f4), TOBN(0x87a6dafb, 0xc75a7fc1), + TOBN(0x549db2b5, 0xef7d9289), TOBN(0x2480d4a8, 0x197f015a), + TOBN(0x61d5590b, 0xc40493b6), TOBN(0x3a55b52e, 0x6f780331), + TOBN(0x40eb8115, 0x309eadb0), TOBN(0xdea7de5a, 0x92e5c625), + TOBN(0x64d631f0, 0xcc6a3d5a), TOBN(0x9d5e9d7c, 0x93e8dd61), + TOBN(0xf297bef5, 0x206d3ffc), TOBN(0x23d5e033, 0x7d808bd4), + TOBN(0x4a4f6912, 0xd24cf5ba), TOBN(0xe4d8163b, 0x09cdaa8a), + TOBN(0x0e0de9ef, 0xd3082e8e), TOBN(0x4fe1246c, 0x0192f360), + TOBN(0x1f900150, 0x4b8eee0a), TOBN(0x5219da81, 0xf1da391b), + TOBN(0x7bf6a5c1, 0xf7ea25aa), TOBN(0xd165e6bf, 0xfbb07d5f), + TOBN(0xe3539361, 0x89e78671), TOBN(0xa3fcac89, 0x2bac4219), + TOBN(0xdfab6fd4, 0xf0baa8ab), TOBN(0x5a4adac1, 0xe2c1c2e5), + TOBN(0x6cd75e31, 0x40d85849), TOBN(0xce263fea, 0x19b39181), + TOBN(0xcb6803d3, 0x07032c72), TOBN(0x7f40d5ce, 0x790968c8), + TOBN(0xa6de86bd, 0xdce978f0), TOBN(0x25547c4f, 0x368f751c), + TOBN(0xb1e685fd, 0x65fb2a9e), TOBN(0xce69336f, 0x1eb9179c), + TOBN(0xb15d1c27, 0x12504442), TOBN(0xb7df465c, 0xb911a06b), + TOBN(0xb8d804a3, 0x315980cd), TOBN(0x693bc492, 0xfa3bebf7), + TOBN(0x3578aeee, 0x2253c504), TOBN(0x158de498, 0xcd2474a2), + TOBN(0x1331f5c7, 0xcfda8368), TOBN(0xd2d7bbb3, 0x78d7177e), + TOBN(0xdf61133a, 0xf3c1e46e), TOBN(0x5836ce7d, 0xd30e7be8), + TOBN(0x83084f19, 0x94f834cb), TOBN(0xd35653d4, 0x429ed782), + TOBN(0xa542f16f, 0x59e58243), TOBN(0xc2b52f65, 0x0470a22d), + TOBN(0xe3b6221b, 0x18f23d96), TOBN(0xcb05abac, 0x3f5252b4), + TOBN(0xca00938b, 0x87d61402), TOBN(0x2f186cdd, 0x411933e4), + TOBN(0xe042ece5, 0x9a29a5c5), TOBN(0xb19b3c07, 0x3b6c8402), + TOBN(0xc97667c7, 0x19d92684), TOBN(0xb5624622, 0xebc66372), + TOBN(0x0cb96e65, 0x3c04fa02), TOBN(0x83a7176c, 0x8eaa39aa), + TOBN(0x2033561d, 0xeaa1633f), TOBN(0x45a9d086, 0x4533df73), + TOBN(0xe0542c1d, 0x3dc090bc), TOBN(0x82c996ef, 0xaa59c167), + TOBN(0xe3f735e8, 0x0ee7fc4d), TOBN(0x7b179393, 0x7c35db79), + TOBN(0xb6419e25, 0xf8c5dbfd), TOBN(0x4d9d7a1e, 0x1f327b04), + TOBN(0x979f6f9b, 0x298dfca8), TOBN(0xc7c5dff1, 0x8de9366a), + TOBN(0x1b7a588d, 0x04c82bdd), TOBN(0x68005534, 0xf8319dfd), + TOBN(0xde8a55b5, 0xd8eb9580), TOBN(0x5ea886da, 0x8d5bca81), + TOBN(0xe8530a01, 0x252a0b4d), TOBN(0x1bffb4fe, 0x35eaa0a1), + TOBN(0x2ad828b1, 0xd8e99563), TOBN(0x7de96ef5, 0x95f9cd87), + TOBN(0x4abb2d0c, 0xd77d970c), TOBN(0x03cfb933, 0xd33ef9cb), + TOBN(0xb0547c01, 0x8b211fe9), TOBN(0x2fe64809, 0xa56ed1c6), + TOBN(0xcb7d5624, 0xc2ac98cc), TOBN(0x2a1372c0, 0x1a393e33), + TOBN(0xc8d1ec1c, 0x29660521), TOBN(0xf3d31b04, 0xb37ac3e9), + TOBN(0xa29ae9df, 0x5ece6e7c), TOBN(0x0603ac8f, 0x0facfb55), + TOBN(0xcfe85b7a, 0xdda233a5), TOBN(0xe618919f, 0xbd75f0b8), + TOBN(0xf555a3d2, 0x99bf1603), TOBN(0x1f43afc9, 0xf184255a), + TOBN(0xdcdaf341, 0x319a3e02), TOBN(0xd3b117ef, 0x03903a39), + TOBN(0xe095da13, 0x65d1d131), TOBN(0x86f16367, 0xc37ad03e), + TOBN(0x5f37389e, 0x462cd8dd), TOBN(0xc103fa04, 0xd67a60e6), + TOBN(0x57c34344, 0xf4b478f0), TOBN(0xce91edd8, 0xe117c98d), + TOBN(0x001777b0, 0x231fc12e), TOBN(0x11ae47f2, 0xb207bccb), + TOBN(0xd983cf8d, 0x20f8a242), TOBN(0x7aff5b1d, 0xf22e1ad8), + TOBN(0x68fd11d0, 0x7fc4feb3), TOBN(0x5d53ae90, 0xb0f1c3e1), + TOBN(0x50fb7905, 0xec041803), TOBN(0x85e3c977, 0x14404888), + TOBN(0x0e67faed, 0xac628d8f), TOBN(0x2e865150, 0x6668532c), + TOBN(0x15acaaa4, 0x6a67a6b0), TOBN(0xf4cdee25, 0xb25cec41), + TOBN(0x49ee565a, 0xe4c6701e), TOBN(0x2a04ca66, 0xfc7d63d8), + TOBN(0xeb105018, 0xef0543fb), TOBN(0xf709a4f5, 0xd1b0d81d), + TOBN(0x5b906ee6, 0x2915d333), TOBN(0xf4a87412, 0x96f1f0ab), + TOBN(0xb6b82fa7, 0x4d82f4c2), TOBN(0x90725a60, 0x6804efb3), + TOBN(0xbc82ec46, 0xadc3425e), TOBN(0xb7b80581, 0x2787843e), + TOBN(0xdf46d91c, 0xdd1fc74c), TOBN(0xdc1c62cb, 0xe783a6c4), + TOBN(0x59d1b9f3, 0x1a04cbba), TOBN(0xd87f6f72, 0x95e40764), + TOBN(0x02b4cfc1, 0x317f4a76), TOBN(0x8d2703eb, 0x91036bce), + TOBN(0x98206cc6, 0xa5e72a56), TOBN(0x57be9ed1, 0xcf53fb0f), + TOBN(0x09374571, 0xef0b17ac), TOBN(0x74b2655e, 0xd9181b38), + TOBN(0xc8f80ea8, 0x89935d0e), TOBN(0xc0d9e942, 0x91529936), + TOBN(0x19686041, 0x1e84e0e5), TOBN(0xa5db84d3, 0xaea34c93), + TOBN(0xf9d5bb19, 0x7073a732), TOBN(0xb8d2fe56, 0x6bcfd7c0), + TOBN(0x45775f36, 0xf3eb82fa), TOBN(0x8cb20ccc, 0xfdff8b58), + TOBN(0x1659b65f, 0x8374c110), TOBN(0xb8b4a422, 0x330c789a), + TOBN(0x75e3c3ea, 0x6fe8208b), TOBN(0xbd74b9e4, 0x286e78fe), + TOBN(0x0be2e81b, 0xd7d93a1a), TOBN(0x7ed06e27, 0xdd0a5aae), + TOBN(0x721f5a58, 0x6be8b800), TOBN(0x428299d1, 0xd846db28), + TOBN(0x95cb8e6b, 0x5be88ed3), TOBN(0xc3186b23, 0x1c034e11), + TOBN(0xa6312c9e, 0x8977d99b), TOBN(0xbe944331, 0x83f531e7), + TOBN(0x8232c0c2, 0x18d3b1d4), TOBN(0x617aae8b, 0xe1247b73), + TOBN(0x40153fc4, 0x282aec3b), TOBN(0xc6063d2f, 0xf7b8f823), + TOBN(0x68f10e58, 0x3304f94c), TOBN(0x31efae74, 0xee676346), + TOBN(0xbadb6c6d, 0x40a9b97c), TOBN(0x14702c63, 0x4f666256), + TOBN(0xdeb954f1, 0x5184b2e3), TOBN(0x5184a526, 0x94b6ca40), + TOBN(0xfff05337, 0x003c32ea), TOBN(0x5aa374dd, 0x205974c7), + TOBN(0x9a763854, 0x4b0dd71a), TOBN(0x459cd27f, 0xdeb947ec), + TOBN(0xa6e28161, 0x459c2b92), TOBN(0x2f020fa8, 0x75ee8ef5), + TOBN(0xb132ec2d, 0x30b06310), TOBN(0xc3e15899, 0xbc6a4530), + TOBN(0xdc5f53fe, 0xaa3f451a), TOBN(0x3a3c7f23, 0xc2d9acac), + TOBN(0x2ec2f892, 0x6b27e58b), TOBN(0x68466ee7, 0xd742799f), + TOBN(0x98324dd4, 0x1fa26613), TOBN(0xa2dc6dab, 0xbdc29d63), + TOBN(0xf9675faa, 0xd712d657), TOBN(0x813994be, 0x21fd8d15), + TOBN(0x5ccbb722, 0xfd4f7553), TOBN(0x5135ff8b, 0xf3a36b20), + TOBN(0x44be28af, 0x69559df5), TOBN(0x40b65bed, 0x9d41bf30), + TOBN(0xd98bf2a4, 0x3734e520), TOBN(0x5e3abbe3, 0x209bdcba), + TOBN(0x77c76553, 0xbc945b35), TOBN(0x5331c093, 0xc6ef14aa), + TOBN(0x518ffe29, 0x76b60c80), TOBN(0x2285593b, 0x7ace16f8), + TOBN(0xab1f64cc, 0xbe2b9784), TOBN(0xe8f2c0d9, 0xab2421b6), + TOBN(0x617d7174, 0xc1df065c), TOBN(0xafeeb5ab, 0x5f6578fa), + TOBN(0x16ff1329, 0x263b54a8), TOBN(0x45c55808, 0xc990dce3), + TOBN(0x42eab6c0, 0xecc8c177), TOBN(0x799ea9b5, 0x5982ecaa), + TOBN(0xf65da244, 0xb607ef8e), TOBN(0x8ab226ce, 0x32a3fc2c), + TOBN(0x745741e5, 0x7ea973dc), TOBN(0x5c00ca70, 0x20888f2e), + TOBN(0x7cdce3cf, 0x45fd9cf1), TOBN(0x8a741ef1, 0x5507f872), + TOBN(0x47c51c2f, 0x196b4cec), TOBN(0x70d08e43, 0xc97ea618), + TOBN(0x930da15c, 0x15b18a2b), TOBN(0x33b6c678, 0x2f610514), + TOBN(0xc662e4f8, 0x07ac9794), TOBN(0x1eccf050, 0xba06cb79), + TOBN(0x1ff08623, 0xe7d954e5), TOBN(0x6ef2c5fb, 0x24cf71c3), + TOBN(0xb2c063d2, 0x67978453), TOBN(0xa0cf3796, 0x1d654af8), + TOBN(0x7cb242ea, 0x7ebdaa37), TOBN(0x206e0b10, 0xb86747e0), + TOBN(0x481dae5f, 0xd5ecfefc), TOBN(0x07084fd8, 0xc2bff8fc), + TOBN(0x8040a01a, 0xea324596), TOBN(0x4c646980, 0xd4de4036), + TOBN(0x9eb8ab4e, 0xd65abfc3), TOBN(0xe01cb91f, 0x13541ec7), + TOBN(0x8f029adb, 0xfd695012), TOBN(0x9ae28483, 0x3c7569ec), + TOBN(0xa5614c9e, 0xa66d80a1), TOBN(0x680a3e44, 0x75f5f911), + TOBN(0x0c07b14d, 0xceba4fc1), TOBN(0x891c285b, 0xa13071c1), + TOBN(0xcac67ceb, 0x799ece3c), TOBN(0x29b910a9, 0x41e07e27), + TOBN(0x66bdb409, 0xf2e43123), TOBN(0x06f8b137, 0x7ac9ecbe), + TOBN(0x5981fafd, 0x38547090), TOBN(0x19ab8b9f, 0x85e3415d), + TOBN(0xfc28c194, 0xc7e31b27), TOBN(0x843be0aa, 0x6fbcbb42), + TOBN(0xf3b1ed43, 0xa6db836c), TOBN(0x2a1330e4, 0x01a45c05), + TOBN(0x4f19f3c5, 0x95c1a377), TOBN(0xa85f39d0, 0x44b5ee33), + TOBN(0x3da18e6d, 0x4ae52834), TOBN(0x5a403b39, 0x7423dcb0), + TOBN(0xbb555e0a, 0xf2374aef), TOBN(0x2ad599c4, 0x1e8ca111), + TOBN(0x1b3a2fb9, 0x014b3bf8), TOBN(0x73092684, 0xf66d5007), + TOBN(0x079f1426, 0xc4340102), TOBN(0x1827cf81, 0x8fddf4de), + TOBN(0xc83605f6, 0xf10ff927), TOBN(0xd3871451, 0x23739fc6), + TOBN(0x6d163450, 0xcac1c2cc), TOBN(0x6b521296, 0xa2ec1ac5), + TOBN(0x0606c4f9, 0x6e3cb4a5), TOBN(0xe47d3f41, 0x778abff7), + TOBN(0x425a8d5e, 0xbe8e3a45), TOBN(0x53ea9e97, 0xa6102160), + TOBN(0x477a106e, 0x39cbb688), TOBN(0x532401d2, 0xf3386d32), + TOBN(0x8e564f64, 0xb1b9b421), TOBN(0xca9b8388, 0x81dad33f), + TOBN(0xb1422b4e, 0x2093913e), TOBN(0x533d2f92, 0x69bc8112), + TOBN(0x3fa017be, 0xebe7b2c7), TOBN(0xb2767c4a, 0xcaf197c6), + TOBN(0xc925ff87, 0xaedbae9f), TOBN(0x7daf0eb9, 0x36880a54), + TOBN(0x9284ddf5, 0x9c4d0e71), TOBN(0x1581cf93, 0x316f8cf5), + TOBN(0x3eeca887, 0x3ac1f452), TOBN(0xb417fce9, 0xfb6aeffe), + TOBN(0xa5918046, 0xeefb8dc3), TOBN(0x73d318ac, 0x02209400), + TOBN(0xe800400f, 0x728693e5), TOBN(0xe87d814b, 0x339927ed), + TOBN(0x93e94d3b, 0x57ea9910), TOBN(0xff8a35b6, 0x2245fb69), + TOBN(0x043853d7, 0x7f200d34), TOBN(0x470f1e68, 0x0f653ce1), + TOBN(0x81ac05bd, 0x59a06379), TOBN(0xa14052c2, 0x03930c29), + TOBN(0x6b72fab5, 0x26bc2797), TOBN(0x13670d16, 0x99f16771), + TOBN(0x00170052, 0x1e3e48d1), TOBN(0x978fe401, 0xb7adf678), + TOBN(0x55ecfb92, 0xd41c5dd4), TOBN(0x5ff8e247, 0xc7b27da5), + TOBN(0xe7518272, 0x013fb606), TOBN(0x5768d7e5, 0x2f547a3c), + TOBN(0xbb24eaa3, 0x60017a5f), TOBN(0x6b18e6e4, 0x9c64ce9b), + TOBN(0xc225c655, 0x103dde07), TOBN(0xfc3672ae, 0x7592f7ea), + TOBN(0x9606ad77, 0xd06283a1), TOBN(0x542fc650, 0xe4d59d99), + TOBN(0xabb57c49, 0x2a40e7c2), TOBN(0xac948f13, 0xa8db9f55), + TOBN(0x6d4c9682, 0xb04465c3), TOBN(0xe3d062fa, 0x6468bd15), + TOBN(0xa51729ac, 0x5f318d7e), TOBN(0x1fc87df6, 0x9eb6fc95), + TOBN(0x63d146a8, 0x0591f652), TOBN(0xa861b8f7, 0x589621aa), + TOBN(0x59f5f15a, 0xce31348c), TOBN(0x8f663391, 0x440da6da), + TOBN(0xcfa778ac, 0xb591ffa3), TOBN(0x027ca9c5, 0x4cdfebce), + TOBN(0xbe8e05a5, 0x444ea6b3), TOBN(0x8aab4e69, 0xa78d8254), + TOBN(0x2437f04f, 0xb474d6b8), TOBN(0x6597ffd4, 0x045b3855), + TOBN(0xbb0aea4e, 0xca47ecaa), TOBN(0x568aae83, 0x85c7ebfc), + TOBN(0x0e966e64, 0xc73b2383), TOBN(0x49eb3447, 0xd17d8762), + TOBN(0xde107821, 0x8da05dab), TOBN(0x443d8baa, 0x016b7236), + TOBN(0x163b63a5, 0xea7610d6), TOBN(0xe47e4185, 0xce1ca979), + TOBN(0xae648b65, 0x80baa132), TOBN(0xebf53de2, 0x0e0d5b64), + TOBN(0x8d3bfcb4, 0xd3c8c1ca), TOBN(0x0d914ef3, 0x5d04b309), + TOBN(0x55ef6415, 0x3de7d395), TOBN(0xbde1666f, 0x26b850e8), + TOBN(0xdbe1ca6e, 0xd449ab19), TOBN(0x8902b322, 0xe89a2672), + TOBN(0xb1674b7e, 0xdacb7a53), TOBN(0x8e9faf6e, 0xf52523ff), + TOBN(0x6ba535da, 0x9a85788b), TOBN(0xd21f03ae, 0xbd0626d4), + TOBN(0x099f8c47, 0xe873dc64), TOBN(0xcda8564d, 0x018ec97e), + TOBN(0x3e8d7a5c, 0xde92c68c), TOBN(0x78e035a1, 0x73323cc4), + TOBN(0x3ef26275, 0xf880ff7c), TOBN(0xa4ee3dff, 0x273eedaa), + TOBN(0x58823507, 0xaf4e18f8), TOBN(0x967ec9b5, 0x0672f328), + TOBN(0x9ded19d9, 0x559d3186), TOBN(0x5e2ab3de, 0x6cdce39c), + TOBN(0xabad6e4d, 0x11c226df), TOBN(0xf9783f43, 0x87723014), + TOBN(0x9a49a0cf, 0x1a885719), TOBN(0xfc0c1a5a, 0x90da9dbf), + TOBN(0x8bbaec49, 0x571d92ac), TOBN(0x569e85fe, 0x4692517f), + TOBN(0x8333b014, 0xa14ea4af), TOBN(0x32f2a62f, 0x12e5c5ad), + TOBN(0x98c2ce3a, 0x06d89b85), TOBN(0xb90741aa, 0x2ff77a08), + TOBN(0x2530defc, 0x01f795a2), TOBN(0xd6e5ba0b, 0x84b3c199), + TOBN(0x7d8e8451, 0x12e4c936), TOBN(0xae419f7d, 0xbd0be17b), + TOBN(0xa583fc8c, 0x22262bc9), TOBN(0x6b842ac7, 0x91bfe2bd), + TOBN(0x33cef4e9, 0x440d6827), TOBN(0x5f69f4de, 0xef81fb14), + TOBN(0xf16cf6f6, 0x234fbb92), TOBN(0x76ae3fc3, 0xd9e7e158), + TOBN(0x4e89f6c2, 0xe9740b33), TOBN(0x677bc85d, 0x4962d6a1), + TOBN(0x6c6d8a7f, 0x68d10d15), TOBN(0x5f9a7224, 0x0257b1cd), + TOBN(0x7096b916, 0x4ad85961), TOBN(0x5f8c47f7, 0xe657ab4a), + TOBN(0xde57d7d0, 0xf7461d7e), TOBN(0x7eb6094d, 0x80ce5ee2), + TOBN(0x0b1e1dfd, 0x34190547), TOBN(0x8a394f43, 0xf05dd150), + TOBN(0x0a9eb24d, 0x97df44e6), TOBN(0x78ca06bf, 0x87675719), + TOBN(0x6f0b3462, 0x6ffeec22), TOBN(0x9d91bcea, 0x36cdd8fb), + TOBN(0xac83363c, 0xa105be47), TOBN(0x81ba76c1, 0x069710e3), + TOBN(0x3d1b24cb, 0x28c682c6), TOBN(0x27f25228, 0x8612575b), + TOBN(0xb587c779, 0xe8e66e98), TOBN(0x7b0c03e9, 0x405eb1fe), + TOBN(0xfdf0d030, 0x15b548e7), TOBN(0xa8be76e0, 0x38b36af7), + TOBN(0x4cdab04a, 0x4f310c40), TOBN(0x6287223e, 0xf47ecaec), + TOBN(0x678e6055, 0x8b399320), TOBN(0x61fe3fa6, 0xc01e4646), + TOBN(0xc482866b, 0x03261a5e), TOBN(0xdfcf45b8, 0x5c2f244a), + TOBN(0x8fab9a51, 0x2f684b43), TOBN(0xf796c654, 0xc7220a66), + TOBN(0x1d90707e, 0xf5afa58f), TOBN(0x2c421d97, 0x4fdbe0de), + TOBN(0xc4f4cda3, 0xaf2ebc2f), TOBN(0xa0af843d, 0xcb4efe24), + TOBN(0x53b857c1, 0x9ccd10b1), TOBN(0xddc9d1eb, 0x914d3e04), + TOBN(0x7bdec8bb, 0x62771deb), TOBN(0x829277aa, 0x91c5aa81), + TOBN(0x7af18dd6, 0x832391ae), TOBN(0x1740f316, 0xc71a84ca),} + , + {TOBN(0x8928e99a, 0xeeaf8c49), TOBN(0xee7aa73d, 0x6e24d728), + TOBN(0x4c5007c2, 0xe72b156c), TOBN(0x5fcf57c5, 0xed408a1d), + TOBN(0x9f719e39, 0xb6057604), TOBN(0x7d343c01, 0xc2868bbf), + TOBN(0x2cca254b, 0x7e103e2d), TOBN(0xe6eb38a9, 0xf131bea2), + TOBN(0xb33e624f, 0x8be762b4), TOBN(0x2a9ee4d1, 0x058e3413), + TOBN(0x968e6369, 0x67d805fa), TOBN(0x9848949b, 0x7db8bfd7), + TOBN(0x5308d7e5, 0xd23a8417), TOBN(0x892f3b1d, 0xf3e29da5), + TOBN(0xc95c139e, 0x3dee471f), TOBN(0x8631594d, 0xd757e089), + TOBN(0xe0c82a3c, 0xde918dcc), TOBN(0x2e7b5994, 0x26fdcf4b), + TOBN(0x82c50249, 0x32cb1b2d), TOBN(0xea613a9d, 0x7657ae07), + TOBN(0xc2eb5f6c, 0xf1fdc9f7), TOBN(0xb6eae8b8, 0x879fe682), + TOBN(0x253dfee0, 0x591cbc7f), TOBN(0x000da713, 0x3e1290e6), + TOBN(0x1083e2ea, 0x1f095615), TOBN(0x0a28ad77, 0x14e68c33), + TOBN(0x6bfc0252, 0x3d8818be), TOBN(0xb585113a, 0xf35850cd), + TOBN(0x7d935f0b, 0x30df8aa1), TOBN(0xaddda07c, 0x4ab7e3ac), + TOBN(0x92c34299, 0x552f00cb), TOBN(0xc33ed1de, 0x2909df6c), + TOBN(0x22c2195d, 0x80e87766), TOBN(0x9e99e6d8, 0x9ddf4ac0), + TOBN(0x09642e4e, 0x65e74934), TOBN(0x2610ffa2, 0xff1ff241), + TOBN(0x4d1d47d4, 0x751c8159), TOBN(0x697b4985, 0xaf3a9363), + TOBN(0x0318ca46, 0x87477c33), TOBN(0xa90cb565, 0x9441eff3), + TOBN(0x58bb3848, 0x36f024cb), TOBN(0x85be1f77, 0x36016168), + TOBN(0x6c59587c, 0xdc7e07f1), TOBN(0x191be071, 0xaf1d8f02), + TOBN(0xbf169fa5, 0xcca5e55c), TOBN(0x3864ba3c, 0xf7d04eac), + TOBN(0x915e367f, 0x8d7d05db), TOBN(0xb48a876d, 0xa6549e5d), + TOBN(0xef89c656, 0x580e40a2), TOBN(0xf194ed8c, 0x728068bc), + TOBN(0x74528045, 0xa47990c9), TOBN(0xf53fc7d7, 0x5e1a4649), + TOBN(0xbec5ae9b, 0x78593e7d), TOBN(0x2cac4ee3, 0x41db65d7), + TOBN(0xa8c1eb24, 0x04a3d39b), TOBN(0x53b7d634, 0x03f8f3ef), + TOBN(0x2dc40d48, 0x3e07113c), TOBN(0x6e4a5d39, 0x7d8b63ae), + TOBN(0x5582a94b, 0x79684c2b), TOBN(0x932b33d4, 0x622da26c), + TOBN(0xf534f651, 0x0dbbf08d), TOBN(0x211d07c9, 0x64c23a52), + TOBN(0x0eeece0f, 0xee5bdc9b), TOBN(0xdf178168, 0xf7015558), + TOBN(0xd4294635, 0x0a712229), TOBN(0x93cbe448, 0x09273f8c), + TOBN(0x00b095ef, 0x8f13bc83), TOBN(0xbb741972, 0x8798978c), + TOBN(0x9d7309a2, 0x56dbe6e7), TOBN(0xe578ec56, 0x5a5d39ec), + TOBN(0x3961151b, 0x851f9a31), TOBN(0x2da7715d, 0xe5709eb4), + TOBN(0x867f3017, 0x53dfabf0), TOBN(0x728d2078, 0xb8e39259), + TOBN(0x5c75a0cd, 0x815d9958), TOBN(0xf84867a6, 0x16603be1), + TOBN(0xc865b13d, 0x70e35b1c), TOBN(0x02414468, 0x19b03e2c), + TOBN(0xe46041da, 0xac1f3121), TOBN(0x7c9017ad, 0x6f028a7c), + TOBN(0xabc96de9, 0x0a482873), TOBN(0x4265d6b1, 0xb77e54d4), + TOBN(0x68c38e79, 0xa57d88e7), TOBN(0xd461d766, 0x9ce82de3), + TOBN(0x817a9ec5, 0x64a7e489), TOBN(0xcc5675cd, 0xa0def5f2), + TOBN(0x9a00e785, 0x985d494e), TOBN(0xc626833f, 0x1b03514a), + TOBN(0xabe7905a, 0x83cdd60e), TOBN(0x50602fb5, 0xa1170184), + TOBN(0x689886cd, 0xb023642a), TOBN(0xd568d090, 0xa6e1fb00), + TOBN(0x5b1922c7, 0x0259217f), TOBN(0x93831cd9, 0xc43141e4), + TOBN(0xdfca3587, 0x0c95f86e), TOBN(0xdec2057a, 0x568ae828), + TOBN(0xc44ea599, 0xf98a759a), TOBN(0x55a0a7a2, 0xf7c23c1d), + TOBN(0xd5ffb6e6, 0x94c4f687), TOBN(0x3563cce2, 0x12848478), + TOBN(0x812b3517, 0xe7b1fbe1), TOBN(0x8a7dc979, 0x4f7338e0), + TOBN(0x211ecee9, 0x52d048db), TOBN(0x2eea4056, 0xc86ea3b8), + TOBN(0xd8cb68a7, 0xba772b34), TOBN(0xe16ed341, 0x5f4e2541), + TOBN(0x9b32f6a6, 0x0fec14db), TOBN(0xeee376f7, 0x391698be), + TOBN(0xe9a7aa17, 0x83674c02), TOBN(0x65832f97, 0x5843022a), + TOBN(0x29f3a8da, 0x5ba4990f), TOBN(0x79a59c3a, 0xfb8e3216), + TOBN(0x9cdc4d2e, 0xbd19bb16), TOBN(0xc6c7cfd0, 0xb3262d86), + TOBN(0xd4ce14d0, 0x969c0b47), TOBN(0x1fa352b7, 0x13e56128), + TOBN(0x383d55b8, 0x973db6d3), TOBN(0x71836850, 0xe8e5b7bf), + TOBN(0xc7714596, 0xe6bb571f), TOBN(0x259df31f, 0x2d5b2dd2), + TOBN(0x568f8925, 0x913cc16d), TOBN(0x18bc5b6d, 0xe1a26f5a), + TOBN(0xdfa413be, 0xf5f499ae), TOBN(0xf8835dec, 0xc3f0ae84), + TOBN(0xb6e60bd8, 0x65a40ab0), TOBN(0x65596439, 0x194b377e), + TOBN(0xbcd85625, 0x92084a69), TOBN(0x5ce433b9, 0x4f23ede0), + TOBN(0xe8e8f04f, 0x6ad65143), TOBN(0x11511827, 0xd6e14af6), + TOBN(0x3d390a10, 0x8295c0c7), TOBN(0x71e29ee4, 0x621eba16), + TOBN(0xa588fc09, 0x63717b46), TOBN(0x02be02fe, 0xe06ad4a2), + TOBN(0x931558c6, 0x04c22b22), TOBN(0xbb4d4bd6, 0x12f3c849), + TOBN(0x54a4f496, 0x20efd662), TOBN(0x92ba6d20, 0xc5952d14), + TOBN(0x2db8ea1e, 0xcc9784c2), TOBN(0x81cc10ca, 0x4b353644), + TOBN(0x40b570ad, 0x4b4d7f6c), TOBN(0x5c9f1d96, 0x84a1dcd2), + TOBN(0x01379f81, 0x3147e797), TOBN(0xe5c6097b, 0x2bd499f5), + TOBN(0x40dcafa6, 0x328e5e20), TOBN(0xf7b5244a, 0x54815550), + TOBN(0xb9a4f118, 0x47bfc978), TOBN(0x0ea0e79f, 0xd25825b1), + TOBN(0xa50f96eb, 0x646c7ecf), TOBN(0xeb811493, 0x446dea9d), + TOBN(0x2af04677, 0xdfabcf69), TOBN(0xbe3a068f, 0xc713f6e8), + TOBN(0x860d523d, 0x42e06189), TOBN(0xbf077941, 0x4e3aff13), + TOBN(0x0b616dca, 0xc1b20650), TOBN(0xe66dd6d1, 0x2131300d), + TOBN(0xd4a0fd67, 0xff99abde), TOBN(0xc9903550, 0xc7aac50d), + TOBN(0x022ecf8b, 0x7c46b2d7), TOBN(0x3333b1e8, 0x3abf92af), + TOBN(0x11cc113c, 0x6c491c14), TOBN(0x05976688, 0x80dd3f88), + TOBN(0xf5b4d9e7, 0x29d932ed), TOBN(0xe982aad8, 0xa2c38b6d), + TOBN(0x6f925347, 0x8be0dcf0), TOBN(0x700080ae, 0x65ca53f2), + TOBN(0xd8131156, 0x443ca77f), TOBN(0xe92d6942, 0xec51f984), + TOBN(0xd2a08af8, 0x85dfe9ae), TOBN(0xd825d9a5, 0x4d2a86ca), + TOBN(0x2c53988d, 0x39dff020), TOBN(0xf38b135a, 0x430cdc40), + TOBN(0x0c918ae0, 0x62a7150b), TOBN(0xf31fd8de, 0x0c340e9b), + TOBN(0xafa0e7ae, 0x4dbbf02e), TOBN(0x5847fb2a, 0x5eba6239), + TOBN(0x6b1647dc, 0xdccbac8b), TOBN(0xb642aa78, 0x06f485c8), + TOBN(0x873f3765, 0x7038ecdf), TOBN(0x2ce5e865, 0xfa49d3fe), + TOBN(0xea223788, 0xc98c4400), TOBN(0x8104a8cd, 0xf1fa5279), + TOBN(0xbcf7cc7a, 0x06becfd7), TOBN(0x49424316, 0xc8f974ae), + TOBN(0xc0da65e7, 0x84d6365d), TOBN(0xbcb7443f, 0x8f759fb8), + TOBN(0x35c712b1, 0x7ae81930), TOBN(0x80428dff, 0x4c6e08ab), + TOBN(0xf19dafef, 0xa4faf843), TOBN(0xced8538d, 0xffa9855f), + TOBN(0x20ac409c, 0xbe3ac7ce), TOBN(0x358c1fb6, 0x882da71e), + TOBN(0xafa9c0e5, 0xfd349961), TOBN(0x2b2cfa51, 0x8421c2fc), + TOBN(0x2a80db17, 0xf3a28d38), TOBN(0xa8aba539, 0x5d138e7e), + TOBN(0x52012d1d, 0x6e96eb8d), TOBN(0x65d8dea0, 0xcbaf9622), + TOBN(0x57735447, 0xb264f56c), TOBN(0xbeebef3f, 0x1b6c8da2), + TOBN(0xfc346d98, 0xce785254), TOBN(0xd50e8d72, 0xbb64a161), + TOBN(0xc03567c7, 0x49794add), TOBN(0x15a76065, 0x752c7ef6), + TOBN(0x59f3a222, 0x961f23d6), TOBN(0x378e4438, 0x73ecc0b0), + TOBN(0xc74be434, 0x5a82fde4), TOBN(0xae509af2, 0xd8b9cf34), + TOBN(0x4a61ee46, 0x577f44a1), TOBN(0xe09b748c, 0xb611deeb), + TOBN(0xc0481b2c, 0xf5f7b884), TOBN(0x35626678, 0x61acfa6b), + TOBN(0x37f4c518, 0xbf8d21e6), TOBN(0x22d96531, 0xb205a76d), + TOBN(0x37fb85e1, 0x954073c0), TOBN(0xbceafe4f, 0x65b3a567), + TOBN(0xefecdef7, 0xbe42a582), TOBN(0xd3fc6080, 0x65046be6), + TOBN(0xc9af13c8, 0x09e8dba9), TOBN(0x1e6c9847, 0x641491ff), + TOBN(0x3b574925, 0xd30c31f7), TOBN(0xb7eb72ba, 0xac2a2122), + TOBN(0x776a0dac, 0xef0859e7), TOBN(0x06fec314, 0x21900942), + TOBN(0x2464bc10, 0xf8c22049), TOBN(0x9bfbcce7, 0x875ebf69), + TOBN(0xd7a88e2a, 0x4336326b), TOBN(0xda05261c, 0x5bc2acfa), + TOBN(0xc29f5bdc, 0xeba7efc8), TOBN(0x471237ca, 0x25dbbf2e), + TOBN(0xa72773f2, 0x2975f127), TOBN(0xdc744e8e, 0x04d0b326), + TOBN(0x38a7ed16, 0xa56edb73), TOBN(0x64357e37, 0x2c007e70), + TOBN(0xa167d15b, 0x5080b400), TOBN(0x07b41164, 0x23de4be1), + TOBN(0xb2d91e32, 0x74c89883), TOBN(0x3c162821, 0x2882e7ed), + TOBN(0xad6b36ba, 0x7503e482), TOBN(0x48434e8e, 0x0ea34331), + TOBN(0x79f4f24f, 0x2c7ae0b9), TOBN(0xc46fbf81, 0x1939b44a), + TOBN(0x76fefae8, 0x56595eb1), TOBN(0x417b66ab, 0xcd5f29c7), + TOBN(0x5f2332b2, 0xc5ceec20), TOBN(0xd69661ff, 0xe1a1cae2), + TOBN(0x5ede7e52, 0x9b0286e6), TOBN(0x9d062529, 0xe276b993), + TOBN(0x324794b0, 0x7e50122b), TOBN(0xdd744f8b, 0x4af07ca5), + TOBN(0x30a12f08, 0xd63fc97b), TOBN(0x39650f1a, 0x76626d9d), + TOBN(0x101b47f7, 0x1fa38477), TOBN(0x3d815f19, 0xd4dc124f), + TOBN(0x1569ae95, 0xb26eb58a), TOBN(0xc3cde188, 0x95fb1887), + TOBN(0x54e9f37b, 0xf9539a48), TOBN(0xb0100e06, 0x7408c1a5), + TOBN(0x821d9811, 0xea580cbb), TOBN(0x8af52d35, 0x86e50c56), + TOBN(0xdfbd9d47, 0xdbbf698b), TOBN(0x2961a1ea, 0x03dc1c73), + TOBN(0x203d38f8, 0xe76a5df8), TOBN(0x08a53a68, 0x6def707a), + TOBN(0x26eefb48, 0x1bee45d4), TOBN(0xb3cee346, 0x3c688036), + TOBN(0x463c5315, 0xc42f2469), TOBN(0x19d84d2e, 0x81378162), + TOBN(0x22d7c3c5, 0x1c4d349f), TOBN(0x65965844, 0x163d59c5), + TOBN(0xcf198c56, 0xb8abceae), TOBN(0x6fb1fb1b, 0x628559d5), + TOBN(0x8bbffd06, 0x07bf8fe3), TOBN(0x46259c58, 0x3467734b), + TOBN(0xd8953cea, 0x35f7f0d3), TOBN(0x1f0bece2, 0xd65b0ff1), + TOBN(0xf7d5b4b3, 0xf3c72914), TOBN(0x29e8ea95, 0x3cb53389), + TOBN(0x4a365626, 0x836b6d46), TOBN(0xe849f910, 0xea174fde), + TOBN(0x7ec62fbb, 0xf4737f21), TOBN(0xd8dba5ab, 0x6209f5ac), + TOBN(0x24b5d7a9, 0xa5f9adbe), TOBN(0x707d28f7, 0xa61dc768), + TOBN(0x7711460b, 0xcaa999ea), TOBN(0xba7b174d, 0x1c92e4cc), + TOBN(0x3c4bab66, 0x18d4bf2d), TOBN(0xb8f0c980, 0xeb8bd279), + TOBN(0x024bea9a, 0x324b4737), TOBN(0xfba9e423, 0x32a83bca), + TOBN(0x6e635643, 0xa232dced), TOBN(0x99619367, 0x2571c8ba), + TOBN(0xe8c9f357, 0x54b7032b), TOBN(0xf936b3ba, 0x2442d54a), + TOBN(0x2263f0f0, 0x8290c65a), TOBN(0x48989780, 0xee2c7fdb), + TOBN(0xadc5d55a, 0x13d4f95e), TOBN(0x737cff85, 0xad9b8500), + TOBN(0x271c557b, 0x8a73f43d), TOBN(0xbed617a4, 0xe18bc476), + TOBN(0x66245401, 0x7dfd8ab2), TOBN(0xae7b89ae, 0x3a2870aa), + TOBN(0x1b555f53, 0x23a7e545), TOBN(0x6791e247, 0xbe057e4c), + TOBN(0x860136ad, 0x324fa34d), TOBN(0xea111447, 0x4cbeae28), + TOBN(0x023a4270, 0xbedd3299), TOBN(0x3d5c3a7f, 0xc1c35c34), + TOBN(0xb0f6db67, 0x8d0412d2), TOBN(0xd92625e2, 0xfcdc6b9a), + TOBN(0x92ae5ccc, 0x4e28a982), TOBN(0xea251c36, 0x47a3ce7e), + TOBN(0x9d658932, 0x790691bf), TOBN(0xed610589, 0x06b736ae), + TOBN(0x712c2f04, 0xc0d63b6e), TOBN(0x5cf06fd5, 0xc63d488f), + TOBN(0x97363fac, 0xd9588e41), TOBN(0x1f9bf762, 0x2b93257e), + TOBN(0xa9d1ffc4, 0x667acace), TOBN(0x1cf4a1aa, 0x0a061ecf), + TOBN(0x40e48a49, 0xdc1818d0), TOBN(0x0643ff39, 0xa3621ab0), + TOBN(0x5768640c, 0xe39ef639), TOBN(0x1fc099ea, 0x04d86854), + TOBN(0x9130b9c3, 0xeccd28fd), TOBN(0xd743cbd2, 0x7eec54ab), + TOBN(0x052b146f, 0xe5b475b6), TOBN(0x058d9a82, 0x900a7d1f), + TOBN(0x65e02292, 0x91262b72), TOBN(0x96f924f9, 0xbb0edf03), + TOBN(0x5cfa59c8, 0xfe206842), TOBN(0xf6037004, 0x5eafa720), + TOBN(0x5f30699e, 0x18d7dd96), TOBN(0x381e8782, 0xcbab2495), + TOBN(0x91669b46, 0xdd8be949), TOBN(0xb40606f5, 0x26aae8ef), + TOBN(0x2812b839, 0xfc6751a4), TOBN(0x16196214, 0xfba800ef), + TOBN(0x4398d5ca, 0x4c1a2875), TOBN(0x720c00ee, 0x653d8349), + TOBN(0xc2699eb0, 0xd820007c), TOBN(0x880ee660, 0xa39b5825), + TOBN(0x70694694, 0x471f6984), TOBN(0xf7d16ea8, 0xe3dda99a), + TOBN(0x28d675b2, 0xc0519a23), TOBN(0x9ebf94fe, 0x4f6952e3), + TOBN(0xf28bb767, 0xa2294a8a), TOBN(0x85512b4d, 0xfe0af3f5), + TOBN(0x18958ba8, 0x99b16a0d), TOBN(0x95c2430c, 0xba7548a7), + TOBN(0xb30d1b10, 0xa16be615), TOBN(0xe3ebbb97, 0x85bfb74c), + TOBN(0xa3273cfe, 0x18549fdb), TOBN(0xf6e200bf, 0x4fcdb792), + TOBN(0x54a76e18, 0x83aba56c), TOBN(0x73ec66f6, 0x89ef6aa2), + TOBN(0x8d17add7, 0xd1b9a305), TOBN(0xa959c5b9, 0xb7ae1b9d), + TOBN(0x88643522, 0x6bcc094a), TOBN(0xcc5616c4, 0xd7d429b9), + TOBN(0xa6dada01, 0xe6a33f7c), TOBN(0xc6217a07, 0x9d4e70ad), + TOBN(0xd619a818, 0x09c15b7c), TOBN(0xea06b329, 0x0e80c854), + TOBN(0x174811ce, 0xa5f5e7b9), TOBN(0x66dfc310, 0x787c65f4), + TOBN(0x4ea7bd69, 0x3316ab54), TOBN(0xc12c4acb, 0x1dcc0f70), + TOBN(0xe4308d1a, 0x1e407dd9), TOBN(0xe8a3587c, 0x91afa997), + TOBN(0xea296c12, 0xab77b7a5), TOBN(0xb5ad49e4, 0x673c0d52), + TOBN(0x40f9b2b2, 0x7006085a), TOBN(0xa88ff340, 0x87bf6ec2), + TOBN(0x978603b1, 0x4e3066a6), TOBN(0xb3f99fc2, 0xb5e486e2), + TOBN(0x07b53f5e, 0xb2e63645), TOBN(0xbe57e547, 0x84c84232), + TOBN(0xd779c216, 0x7214d5cf), TOBN(0x617969cd, 0x029a3aca), + TOBN(0xd17668cd, 0x8a7017a0), TOBN(0x77b4d19a, 0xbe9b7ee8), + TOBN(0x58fd0e93, 0x9c161776), TOBN(0xa8c4f4ef, 0xd5968a72), + TOBN(0x296071cc, 0x67b3de77), TOBN(0xae3c0b8e, 0x634f7905), + TOBN(0x67e440c2, 0x8a7100c9), TOBN(0xbb8c3c1b, 0xeb4b9b42), + TOBN(0x6d71e8ea, 0xc51b3583), TOBN(0x7591f5af, 0x9525e642), + TOBN(0xf73a2f7b, 0x13f509f3), TOBN(0x618487aa, 0x5619ac9b), + TOBN(0x3a72e5f7, 0x9d61718a), TOBN(0x00413bcc, 0x7592d28c), + TOBN(0x7d9b11d3, 0x963c35cf), TOBN(0x77623bcf, 0xb90a46ed), + TOBN(0xdeef273b, 0xdcdd2a50), TOBN(0x4a741f9b, 0x0601846e), + TOBN(0x33b89e51, 0x0ec6e929), TOBN(0xcb02319f, 0x8b7f22cd), + TOBN(0xbbe1500d, 0x084bae24), TOBN(0x2f0ae8d7, 0x343d2693), + TOBN(0xacffb5f2, 0x7cdef811), TOBN(0xaa0c030a, 0x263fb94f), + TOBN(0x6eef0d61, 0xa0f442de), TOBN(0xf92e1817, 0x27b139d3), + TOBN(0x1ae6deb7, 0x0ad8bc28), TOBN(0xa89e38dc, 0xc0514130), + TOBN(0x81eeb865, 0xd2fdca23), TOBN(0x5a15ee08, 0xcc8ef895), + TOBN(0x768fa10a, 0x01905614), TOBN(0xeff5b8ef, 0x880ee19b), + TOBN(0xf0c0cabb, 0xcb1c8a0e), TOBN(0x2e1ee9cd, 0xb8c838f9), + TOBN(0x0587d8b8, 0x8a4a14c0), TOBN(0xf6f27896, 0x2ff698e5), + TOBN(0xed38ef1c, 0x89ee6256), TOBN(0xf44ee1fe, 0x6b353b45), + TOBN(0x9115c0c7, 0x70e903b3), TOBN(0xc78ec0a1, 0x818f31df), + TOBN(0x6c003324, 0xb7dccbc6), TOBN(0xd96dd1f3, 0x163bbc25), + TOBN(0x33aa82dd, 0x5cedd805), TOBN(0x123aae4f, 0x7f7eb2f1), + TOBN(0x1723fcf5, 0xa26262cd), TOBN(0x1f7f4d5d, 0x0060ebd5), + TOBN(0xf19c5c01, 0xb2eaa3af), TOBN(0x2ccb9b14, 0x9790accf), + TOBN(0x1f9c1cad, 0x52324aa6), TOBN(0x63200526, 0x7247df54), + TOBN(0x5732fe42, 0xbac96f82), TOBN(0x52fe771f, 0x01a1c384), + TOBN(0x546ca13d, 0xb1001684), TOBN(0xb56b4eee, 0xa1709f75), + TOBN(0x266545a9, 0xd5db8672), TOBN(0xed971c90, 0x1e8f3cfb), + TOBN(0x4e7d8691, 0xe3a07b29), TOBN(0x7570d9ec, 0xe4b696b9), + TOBN(0xdc5fa067, 0x7bc7e9ae), TOBN(0x68b44caf, 0xc82c4844), + TOBN(0x519d34b3, 0xbf44da80), TOBN(0x283834f9, 0x5ab32e66), + TOBN(0x6e608797, 0x6278a000), TOBN(0x1e62960e, 0x627312f6), + TOBN(0x9b87b27b, 0xe6901c55), TOBN(0x80e78538, 0x24fdbc1f), + TOBN(0xbbbc0951, 0x2facc27d), TOBN(0x06394239, 0xac143b5a), + TOBN(0x35bb4a40, 0x376c1944), TOBN(0x7cb62694, 0x63da1511), + TOBN(0xafd29161, 0xb7148a3b), TOBN(0xa6f9d9ed, 0x4e2ea2ee), + TOBN(0x15dc2ca2, 0x880dd212), TOBN(0x903c3813, 0xa61139a9), + TOBN(0x2aa7b46d, 0x6c0f8785), TOBN(0x36ce2871, 0x901c60ff), + TOBN(0xc683b028, 0xe10d9c12), TOBN(0x7573baa2, 0x032f33d3), + TOBN(0x87a9b1f6, 0x67a31b58), TOBN(0xfd3ed11a, 0xf4ffae12), + TOBN(0x83dcaa9a, 0x0cb2748e), TOBN(0x8239f018, 0x5d6fdf16), + TOBN(0xba67b49c, 0x72753941), TOBN(0x2beec455, 0xc321cb36), + TOBN(0x88015606, 0x3f8b84ce), TOBN(0x76417083, 0x8d38c86f), + TOBN(0x054f1ca7, 0x598953dd), TOBN(0xc939e110, 0x4e8e7429), + TOBN(0x9b1ac2b3, 0x5a914f2f), TOBN(0x39e35ed3, 0xe74b8f9c), + TOBN(0xd0debdb2, 0x781b2fb0), TOBN(0x1585638f, 0x2d997ba2), + TOBN(0x9c4b646e, 0x9e2fce99), TOBN(0x68a21081, 0x1e80857f), + TOBN(0x06d54e44, 0x3643b52a), TOBN(0xde8d6d63, 0x0d8eb843), + TOBN(0x70321563, 0x42146a0a), TOBN(0x8ba826f2, 0x5eaa3622), + TOBN(0x227a58bd, 0x86138787), TOBN(0x43b6c03c, 0x10281d37), + TOBN(0x6326afbb, 0xb54dde39), TOBN(0x744e5e8a, 0xdb6f2d5f), + TOBN(0x48b2a99a, 0xcff158e1), TOBN(0xa93c8fa0, 0xef87918f), + TOBN(0x2182f956, 0xde058c5c), TOBN(0x216235d2, 0x936f9e7a), + TOBN(0xace0c0db, 0xd2e31e67), TOBN(0xc96449bf, 0xf23ac3e7), + TOBN(0x7e9a2874, 0x170693bd), TOBN(0xa28e14fd, 0xa45e6335), + TOBN(0x5757f6b3, 0x56427344), TOBN(0x822e4556, 0xacf8edf9), + TOBN(0x2b7a6ee2, 0xe6a285cd), TOBN(0x5866f211, 0xa9df3af0), + TOBN(0x40dde2dd, 0xf845b844), TOBN(0x986c3726, 0x110e5e49), + TOBN(0x73680c2a, 0xf7172277), TOBN(0x57b94f0f, 0x0cccb244), + TOBN(0xbdff7267, 0x2d438ca7), TOBN(0xbad1ce11, 0xcf4663fd), + TOBN(0x9813ed9d, 0xd8f71cae), TOBN(0xf43272a6, 0x961fdaa6), + TOBN(0xbeff0119, 0xbd6d1637), TOBN(0xfebc4f91, 0x30361978), + TOBN(0x02b37a95, 0x2f41deff), TOBN(0x0e44a59a, 0xe63b89b7), + TOBN(0x673257dc, 0x143ff951), TOBN(0x19c02205, 0xd752baf4), + TOBN(0x46c23069, 0xc4b7d692), TOBN(0x2e6392c3, 0xfd1502ac), + TOBN(0x6057b1a2, 0x1b220846), TOBN(0xe51ff946, 0x0c1b5b63),} + , + {TOBN(0x6e85cb51, 0x566c5c43), TOBN(0xcff9c919, 0x3597f046), + TOBN(0x9354e90c, 0x4994d94a), TOBN(0xe0a39332, 0x2147927d), + TOBN(0x8427fac1, 0x0dc1eb2b), TOBN(0x88cfd8c2, 0x2ff319fa), + TOBN(0xe2d4e684, 0x01965274), TOBN(0xfa2e067d, 0x67aaa746), + TOBN(0xb6d92a7f, 0x3e5f9f11), TOBN(0x9afe153a, 0xd6cb3b8e), + TOBN(0x4d1a6dd7, 0xddf800bd), TOBN(0xf6c13cc0, 0xcaf17e19), + TOBN(0x15f6c58e, 0x325fc3ee), TOBN(0x71095400, 0xa31dc3b2), + TOBN(0x168e7c07, 0xafa3d3e7), TOBN(0x3f8417a1, 0x94c7ae2d), + TOBN(0xec234772, 0x813b230d), TOBN(0x634d0f5f, 0x17344427), + TOBN(0x11548ab1, 0xd77fc56a), TOBN(0x7fab1750, 0xce06af77), + TOBN(0xb62c10a7, 0x4f7c4f83), TOBN(0xa7d2edc4, 0x220a67d9), + TOBN(0x1c404170, 0x921209a0), TOBN(0x0b9815a0, 0xface59f0), + TOBN(0x2842589b, 0x319540c3), TOBN(0x18490f59, 0xa283d6f8), + TOBN(0xa2731f84, 0xdaae9fcb), TOBN(0x3db6d960, 0xc3683ba0), + TOBN(0xc85c63bb, 0x14611069), TOBN(0xb19436af, 0x0788bf05), + TOBN(0x905459df, 0x347460d2), TOBN(0x73f6e094, 0xe11a7db1), + TOBN(0xdc7f938e, 0xb6357f37), TOBN(0xc5d00f79, 0x2bd8aa62), + TOBN(0xc878dcb9, 0x2ca979fc), TOBN(0x37e83ed9, 0xeb023a99), + TOBN(0x6b23e273, 0x1560bf3d), TOBN(0x1086e459, 0x1d0fae61), + TOBN(0x78248316, 0x9a9414bd), TOBN(0x1b956bc0, 0xf0ea9ea1), + TOBN(0x7b85bb91, 0xc31b9c38), TOBN(0x0c5aa90b, 0x48ef57b5), + TOBN(0xdedeb169, 0xaf3bab6f), TOBN(0xe610ad73, 0x2d373685), + TOBN(0xf13870df, 0x02ba8e15), TOBN(0x0337edb6, 0x8ca7f771), + TOBN(0xe4acf747, 0xb62c036c), TOBN(0xd921d576, 0xb6b94e81), + TOBN(0xdbc86439, 0x2c422f7a), TOBN(0xfb635362, 0xed348898), + TOBN(0x83084668, 0xc45bfcd1), TOBN(0xc357c9e3, 0x2b315e11), + TOBN(0xb173b540, 0x5b2e5b8c), TOBN(0x7e946931, 0xe102b9a4), + TOBN(0x17c890eb, 0x7b0fb199), TOBN(0xec225a83, 0xd61b662b), + TOBN(0xf306a3c8, 0xee3c76cb), TOBN(0x3cf11623, 0xd32a1f6e), + TOBN(0xe6d5ab64, 0x6863e956), TOBN(0x3b8a4cbe, 0x5c005c26), + TOBN(0xdcd529a5, 0x9ce6bb27), TOBN(0xc4afaa52, 0x04d4b16f), + TOBN(0xb0624a26, 0x7923798d), TOBN(0x85e56df6, 0x6b307fab), + TOBN(0x0281893c, 0x2bf29698), TOBN(0x91fc19a4, 0xd7ce7603), + TOBN(0x75a5dca3, 0xad9a558f), TOBN(0x40ceb3fa, 0x4d50bf77), + TOBN(0x1baf6060, 0xbc9ba369), TOBN(0x927e1037, 0x597888c2), + TOBN(0xd936bf19, 0x86a34c07), TOBN(0xd4cf10c1, 0xc34ae980), + TOBN(0x3a3e5334, 0x859dd614), TOBN(0x9c475b5b, 0x18d0c8ee), + TOBN(0x63080d1f, 0x07cd51d5), TOBN(0xc9c0d0a6, 0xb88b4326), + TOBN(0x1ac98691, 0xc234296f), TOBN(0x2a0a83a4, 0x94887fb6), + TOBN(0x56511427, 0x0cea9cf2), TOBN(0x5230a6e8, 0xa24802f5), + TOBN(0xf7a2bf0f, 0x72e3d5c1), TOBN(0x37717446, 0x4f21439e), + TOBN(0xfedcbf25, 0x9ce30334), TOBN(0xe0030a78, 0x7ce202f9), + TOBN(0x6f2d9ebf, 0x1202e9ca), TOBN(0xe79dde6c, 0x75e6e591), + TOBN(0xf52072af, 0xf1dac4f8), TOBN(0x6c8d087e, 0xbb9b404d), + TOBN(0xad0fc73d, 0xbce913af), TOBN(0x909e587b, 0x458a07cb), + TOBN(0x1300da84, 0xd4f00c8a), TOBN(0x425cd048, 0xb54466ac), + TOBN(0xb59cb9be, 0x90e9d8bf), TOBN(0x991616db, 0x3e431b0e), + TOBN(0xd3aa117a, 0x531aecff), TOBN(0x91af92d3, 0x59f4dc3b), + TOBN(0x9b1ec292, 0xe93fda29), TOBN(0x76bb6c17, 0xe97d91bc), + TOBN(0x7509d95f, 0xaface1e6), TOBN(0x3653fe47, 0xbe855ae3), + TOBN(0x73180b28, 0x0f680e75), TOBN(0x75eefd1b, 0xeeb6c26c), + TOBN(0xa4cdf29f, 0xb66d4236), TOBN(0x2d70a997, 0x6b5821d8), + TOBN(0x7a3ee207, 0x20445c36), TOBN(0x71d1ac82, 0x59877174), + TOBN(0x0fc539f7, 0x949f73e9), TOBN(0xd05cf3d7, 0x982e3081), + TOBN(0x8758e20b, 0x7b1c7129), TOBN(0xffadcc20, 0x569e61f2), + TOBN(0xb05d3a2f, 0x59544c2d), TOBN(0xbe16f5c1, 0x9fff5e53), + TOBN(0x73cf65b8, 0xaad58135), TOBN(0x622c2119, 0x037aa5be), + TOBN(0x79373b3f, 0x646fd6a0), TOBN(0x0e029db5, 0x0d3978cf), + TOBN(0x8bdfc437, 0x94fba037), TOBN(0xaefbd687, 0x620797a6), + TOBN(0x3fa5382b, 0xbd30d38e), TOBN(0x7627cfbf, 0x585d7464), + TOBN(0xb2330fef, 0x4e4ca463), TOBN(0xbcef7287, 0x3566cc63), + TOBN(0xd161d2ca, 0xcf780900), TOBN(0x135dc539, 0x5b54827d), + TOBN(0x638f052e, 0x27bf1bc6), TOBN(0x10a224f0, 0x07dfa06c), + TOBN(0xe973586d, 0x6d3321da), TOBN(0x8b0c5738, 0x26152c8f), + TOBN(0x07ef4f2a, 0x34606074), TOBN(0x80fe7fe8, 0xa0f7047a), + TOBN(0x3d1a8152, 0xe1a0e306), TOBN(0x32cf43d8, 0x88da5222), + TOBN(0xbf89a95f, 0x5f02ffe6), TOBN(0x3d9eb9a4, 0x806ad3ea), + TOBN(0x012c17bb, 0x79c8e55e), TOBN(0xfdcd1a74, 0x99c81dac), + TOBN(0x7043178b, 0xb9556098), TOBN(0x4090a1df, 0x801c3886), + TOBN(0x759800ff, 0x9b67b912), TOBN(0x3e5c0304, 0x232620c8), + TOBN(0x4b9d3c4b, 0x70dceeca), TOBN(0xbb2d3c15, 0x181f648e), + TOBN(0xf981d837, 0x6e33345c), TOBN(0xb626289b, 0x0cf2297a), + TOBN(0x766ac659, 0x8baebdcf), TOBN(0x1a28ae09, 0x75df01e5), + TOBN(0xb71283da, 0x375876d8), TOBN(0x4865a96d, 0x607b9800), + TOBN(0x25dd1bcd, 0x237936b2), TOBN(0x332f4f4b, 0x60417494), + TOBN(0xd0923d68, 0x370a2147), TOBN(0x497f5dfb, 0xdc842203), + TOBN(0x9dc74cbd, 0x32be5e0f), TOBN(0x7475bcb7, 0x17a01375), + TOBN(0x438477c9, 0x50d872b1), TOBN(0xcec67879, 0xffe1d63d), + TOBN(0x9b006014, 0xd8578c70), TOBN(0xc9ad99a8, 0x78bb6b8b), + TOBN(0x6799008e, 0x11fb3806), TOBN(0xcfe81435, 0xcd44cab3), + TOBN(0xa2ee1582, 0x2f4fb344), TOBN(0xb8823450, 0x483fa6eb), + TOBN(0x622d323d, 0x652c7749), TOBN(0xd8474a98, 0xbeb0a15b), + TOBN(0xe43c154d, 0x5d1c00d0), TOBN(0x7fd581d9, 0x0e3e7aac), + TOBN(0x2b44c619, 0x2525ddf8), TOBN(0x67a033eb, 0xb8ae9739), + TOBN(0x113ffec1, 0x9ef2d2e4), TOBN(0x1bf6767e, 0xd5a0ea7f), + TOBN(0x57fff75e, 0x03714c0a), TOBN(0xa23c422e, 0x0a23e9ee), + TOBN(0xdd5f6b2d, 0x540f83af), TOBN(0xc2c2c27e, 0x55ea46a7), + TOBN(0xeb6b4246, 0x672a1208), TOBN(0xd13599f7, 0xae634f7a), + TOBN(0xcf914b5c, 0xd7b32c6e), TOBN(0x61a5a640, 0xeaf61814), + TOBN(0x8dc3df8b, 0x208a1bbb), TOBN(0xef627fd6, 0xb6d79aa5), + TOBN(0x44232ffc, 0xc4c86bc8), TOBN(0xe6f9231b, 0x061539fe), + TOBN(0x1d04f25a, 0x958b9533), TOBN(0x180cf934, 0x49e8c885), + TOBN(0x89689595, 0x9884aaf7), TOBN(0xb1959be3, 0x07b348a6), + TOBN(0x96250e57, 0x3c147c87), TOBN(0xae0efb3a, 0xdd0c61f8), + TOBN(0xed00745e, 0xca8c325e), TOBN(0x3c911696, 0xecff3f70), + TOBN(0x73acbc65, 0x319ad41d), TOBN(0x7b01a020, 0xf0b1c7ef), + TOBN(0xea32b293, 0x63a1483f), TOBN(0x89eabe71, 0x7a248f96), + TOBN(0x9c6231d3, 0x343157e5), TOBN(0x93a375e5, 0xdf3c546d), + TOBN(0xe76e9343, 0x6a2afe69), TOBN(0xc4f89100, 0xe166c88e), + TOBN(0x248efd0d, 0x4f872093), TOBN(0xae0eb3ea, 0x8fe0ea61), + TOBN(0xaf89790d, 0x9d79046e), TOBN(0x4d650f2d, 0x6cee0976), + TOBN(0xa3935d9a, 0x43071eca), TOBN(0x66fcd2c9, 0x283b0bfe), + TOBN(0x0e665eb5, 0x696605f1), TOBN(0xe77e5d07, 0xa54cd38d), + TOBN(0x90ee050a, 0x43d950cf), TOBN(0x86ddebda, 0xd32e69b5), + TOBN(0x6ad94a3d, 0xfddf7415), TOBN(0xf7fa1309, 0x3f6e8d5a), + TOBN(0xc4831d1d, 0xe9957f75), TOBN(0x7de28501, 0xd5817447), + TOBN(0x6f1d7078, 0x9e2aeb6b), TOBN(0xba2b9ff4, 0xf67a53c2), + TOBN(0x36963767, 0xdf9defc3), TOBN(0x479deed3, 0x0d38022c), + TOBN(0xd2edb89b, 0x3a8631e8), TOBN(0x8de855de, 0x7a213746), + TOBN(0xb2056cb7, 0xb00c5f11), TOBN(0xdeaefbd0, 0x2c9b85e4), + TOBN(0x03f39a8d, 0xd150892d), TOBN(0x37b84686, 0x218b7985), + TOBN(0x36296dd8, 0xb7375f1a), TOBN(0x472cd4b1, 0xb78e898e), + TOBN(0x15dff651, 0xe9f05de9), TOBN(0xd4045069, 0x2ce98ba9), + TOBN(0x8466a7ae, 0x9b38024c), TOBN(0xb910e700, 0xe5a6b5ef), + TOBN(0xae1c56ea, 0xb3aa8f0d), TOBN(0xbab2a507, 0x7eee74a6), + TOBN(0x0dca11e2, 0x4b4c4620), TOBN(0xfd896e2e, 0x4c47d1f4), + TOBN(0xeb45ae53, 0x308fbd93), TOBN(0x46cd5a2e, 0x02c36fda), + TOBN(0x6a3d4e90, 0xbaa48385), TOBN(0xdd55e62e, 0x9dbe9960), + TOBN(0xa1406aa0, 0x2a81ede7), TOBN(0x6860dd14, 0xf9274ea7), + TOBN(0xcfdcb0c2, 0x80414f86), TOBN(0xff410b10, 0x22f94327), + TOBN(0x5a33cc38, 0x49ad467b), TOBN(0xefb48b6c, 0x0a7335f1), + TOBN(0x14fb54a4, 0xb153a360), TOBN(0x604aa9d2, 0xb52469cc), + TOBN(0x5e9dc486, 0x754e48e9), TOBN(0x693cb455, 0x37471e8e), + TOBN(0xfb2fd7cd, 0x8d3b37b6), TOBN(0x63345e16, 0xcf09ff07), + TOBN(0x9910ba6b, 0x23a5d896), TOBN(0x1fe19e35, 0x7fe4364e), + TOBN(0x6e1da8c3, 0x9a33c677), TOBN(0x15b4488b, 0x29fd9fd0), + TOBN(0x1f439254, 0x1a1f22bf), TOBN(0x920a8a70, 0xab8163e8), + TOBN(0x3fd1b249, 0x07e5658e), TOBN(0xf2c4f79c, 0xb6ec839b), + TOBN(0x1abbc3d0, 0x4aa38d1b), TOBN(0x3b0db35c, 0xb5d9510e), + TOBN(0x1754ac78, 0x3e60dec0), TOBN(0x53272fd7, 0xea099b33), + TOBN(0x5fb0494f, 0x07a8e107), TOBN(0x4a89e137, 0x6a8191fa), + TOBN(0xa113b7f6, 0x3c4ad544), TOBN(0x88a2e909, 0x6cb9897b), + TOBN(0x17d55de3, 0xb44a3f84), TOBN(0xacb2f344, 0x17c6c690), + TOBN(0x32088168, 0x10232390), TOBN(0xf2e8a61f, 0x6c733bf7), + TOBN(0xa774aab6, 0x9c2d7652), TOBN(0xfb5307e3, 0xed95c5bc), + TOBN(0xa05c73c2, 0x4981f110), TOBN(0x1baae31c, 0xa39458c9), + TOBN(0x1def185b, 0xcbea62e7), TOBN(0xe8ac9eae, 0xeaf63059), + TOBN(0x098a8cfd, 0x9921851c), TOBN(0xd959c3f1, 0x3abe2f5b), + TOBN(0xa4f19525, 0x20e40ae5), TOBN(0x320789e3, 0x07a24aa1), + TOBN(0x259e6927, 0x7392b2bc), TOBN(0x58f6c667, 0x1918668b), + TOBN(0xce1db2bb, 0xc55d2d8b), TOBN(0x41d58bb7, 0xf4f6ca56), + TOBN(0x7650b680, 0x8f877614), TOBN(0x905e16ba, 0xf4c349ed), + TOBN(0xed415140, 0xf661acac), TOBN(0x3b8784f0, 0xcb2270af), + TOBN(0x3bc280ac, 0x8a402cba), TOBN(0xd53f7146, 0x0937921a), + TOBN(0xc03c8ee5, 0xe5681e83), TOBN(0x62126105, 0xf6ac9e4a), + TOBN(0x9503a53f, 0x936b1a38), TOBN(0x3d45e2d4, 0x782fecbd), + TOBN(0x69a5c439, 0x76e8ae98), TOBN(0xb53b2eeb, 0xbfb4b00e), + TOBN(0xf1674712, 0x72386c89), TOBN(0x30ca34a2, 0x4268bce4), + TOBN(0x7f1ed86c, 0x78341730), TOBN(0x8ef5beb8, 0xb525e248), + TOBN(0xbbc489fd, 0xb74fbf38), TOBN(0x38a92a0e, 0x91a0b382), + TOBN(0x7a77ba3f, 0x22433ccf), TOBN(0xde8362d6, 0xa29f05a9), + TOBN(0x7f6a30ea, 0x61189afc), TOBN(0x693b5505, 0x59ef114f), + TOBN(0x50266bc0, 0xcd1797a1), TOBN(0xea17b47e, 0xf4b7af2d), + TOBN(0xd6c4025c, 0x3df9483e), TOBN(0x8cbb9d9f, 0xa37b18c9), + TOBN(0x91cbfd9c, 0x4d8424cf), TOBN(0xdb7048f1, 0xab1c3506), + TOBN(0x9eaf641f, 0x028206a3), TOBN(0xf986f3f9, 0x25bdf6ce), + TOBN(0x262143b5, 0x224c08dc), TOBN(0x2bbb09b4, 0x81b50c91), + TOBN(0xc16ed709, 0xaca8c84f), TOBN(0xa6210d9d, 0xb2850ca8), + TOBN(0x6d8df67a, 0x09cb54d6), TOBN(0x91eef6e0, 0x500919a4), + TOBN(0x90f61381, 0x0f132857), TOBN(0x9acede47, 0xf8d5028b), + TOBN(0x844d1b71, 0x90b771c3), TOBN(0x563b71e4, 0xba6426be), + TOBN(0x2efa2e83, 0xbdb802ff), TOBN(0x3410cbab, 0xab5b4a41), + TOBN(0x555b2d26, 0x30da84dd), TOBN(0xd0711ae9, 0xee1cc29a), + TOBN(0xcf3e8c60, 0x2f547792), TOBN(0x03d7d5de, 0xdc678b35), + TOBN(0x071a2fa8, 0xced806b8), TOBN(0x222e6134, 0x697f1478), + TOBN(0xdc16fd5d, 0xabfcdbbf), TOBN(0x44912ebf, 0x121b53b8), + TOBN(0xac943674, 0x2496c27c), TOBN(0x8ea3176c, 0x1ffc26b0), + TOBN(0xb6e224ac, 0x13debf2c), TOBN(0x524cc235, 0xf372a832), + TOBN(0xd706e1d8, 0x9f6f1b18), TOBN(0x2552f005, 0x44cce35b), + TOBN(0x8c8326c2, 0xa88e31fc), TOBN(0xb5468b2c, 0xf9552047), + TOBN(0xce683e88, 0x3ff90f2b), TOBN(0x77947bdf, 0x2f0a5423), + TOBN(0xd0a1b28b, 0xed56e328), TOBN(0xaee35253, 0xc20134ac), + TOBN(0x7e98367d, 0x3567962f), TOBN(0x379ed61f, 0x8188bffb), + TOBN(0x73bba348, 0xfaf130a1), TOBN(0x6c1f75e1, 0x904ed734), + TOBN(0x18956642, 0x3b4a79fc), TOBN(0xf20bc83d, 0x54ef4493), + TOBN(0x836d425d, 0x9111eca1), TOBN(0xe5b5c318, 0x009a8dcf), + TOBN(0x3360b25d, 0x13221bc5), TOBN(0x707baad2, 0x6b3eeaf7), + TOBN(0xd7279ed8, 0x743a95a1), TOBN(0x7450a875, 0x969e809f), + TOBN(0x32b6bd53, 0xe5d0338f), TOBN(0x1e77f7af, 0x2b883bbc), + TOBN(0x90da12cc, 0x1063ecd0), TOBN(0xe2697b58, 0xc315be47), + TOBN(0x2771a5bd, 0xda85d534), TOBN(0x53e78c1f, 0xff980eea), + TOBN(0xadf1cf84, 0x900385e7), TOBN(0x7d3b14f6, 0xc9387b62), + TOBN(0x170e74b0, 0xcb8f2bd2), TOBN(0x2d50b486, 0x827fa993), + TOBN(0xcdbe8c9a, 0xf6f32bab), TOBN(0x55e906b0, 0xc3b93ab8), + TOBN(0x747f22fc, 0x8fe280d1), TOBN(0xcd8e0de5, 0xb2e114ab), + TOBN(0x5ab7dbeb, 0xe10b68b0), TOBN(0x9dc63a9c, 0xa480d4b2), + TOBN(0x78d4bc3b, 0x4be1495f), TOBN(0x25eb3db8, 0x9359122d), + TOBN(0x3f8ac05b, 0x0809cbdc), TOBN(0xbf4187bb, 0xd37c702f), + TOBN(0x84cea069, 0x1416a6a5), TOBN(0x8f860c79, 0x43ef881c), + TOBN(0x41311f8a, 0x38038a5d), TOBN(0xe78c2ec0, 0xfc612067), + TOBN(0x494d2e81, 0x5ad73581), TOBN(0xb4cc9e00, 0x59604097), + TOBN(0xff558aec, 0xf3612cba), TOBN(0x35beef7a, 0x9e36c39e), + TOBN(0x1845c7cf, 0xdbcf41b9), TOBN(0x5703662a, 0xaea997c0), + TOBN(0x8b925afe, 0xe402f6d8), TOBN(0xd0a1b1ae, 0x4dd72162), + TOBN(0x9f47b375, 0x03c41c4b), TOBN(0xa023829b, 0x0391d042), + TOBN(0x5f5045c3, 0x503b8b0a), TOBN(0x123c2688, 0x98c010e5), + TOBN(0x324ec0cc, 0x36ba06ee), TOBN(0xface3115, 0x3dd2cc0c), + TOBN(0xb364f3be, 0xf333e91f), TOBN(0xef8aff73, 0x28e832b0), + TOBN(0x1e9bad04, 0x2d05841b), TOBN(0x42f0e3df, 0x356a21e2), + TOBN(0xa3270bcb, 0x4add627e), TOBN(0xb09a8158, 0xd322e711), + TOBN(0x86e326a1, 0x0fee104a), TOBN(0xad7788f8, 0x3703f65d), + TOBN(0x7e765430, 0x47bc4833), TOBN(0x6cee582b, 0x2b9b893a), + TOBN(0x9cd2a167, 0xe8f55a7b), TOBN(0xefbee3c6, 0xd9e4190d), + TOBN(0x33ee7185, 0xd40c2e9d), TOBN(0x844cc9c5, 0xa380b548), + TOBN(0x323f8ecd, 0x66926e04), TOBN(0x0001e38f, 0x8110c1ba), + TOBN(0x8dbcac12, 0xfc6a7f07), TOBN(0xd65e1d58, 0x0cec0827), + TOBN(0xd2cd4141, 0xbe76ca2d), TOBN(0x7895cf5c, 0xe892f33a), + TOBN(0x956d230d, 0x367139d2), TOBN(0xa91abd3e, 0xd012c4c1), + TOBN(0x34fa4883, 0x87eb36bf), TOBN(0xc5f07102, 0x914b8fb4), + TOBN(0x90f0e579, 0xadb9c95f), TOBN(0xfe6ea8cb, 0x28888195), + TOBN(0x7b9b5065, 0xedfa9284), TOBN(0x6c510bd2, 0x2b8c8d65), + TOBN(0xd7b8ebef, 0xcbe8aafd), TOBN(0xedb3af98, 0x96b1da07), + TOBN(0x28ff779d, 0x6295d426), TOBN(0x0c4f6ac7, 0x3fa3ad7b), + TOBN(0xec44d054, 0x8b8e2604), TOBN(0x9b32a66d, 0x8b0050e1), + TOBN(0x1f943366, 0xf0476ce2), TOBN(0x7554d953, 0xa602c7b4), + TOBN(0xbe35aca6, 0x524f2809), TOBN(0xb6881229, 0xfd4edbea), + TOBN(0xe8cd0c8f, 0x508efb63), TOBN(0x9eb5b5c8, 0x6abcefc7), + TOBN(0xf5621f5f, 0xb441ab4f), TOBN(0x79e6c046, 0xb76a2b22), + TOBN(0x74a4792c, 0xe37a1f69), TOBN(0xcbd252cb, 0x03542b60), + TOBN(0x785f65d5, 0xb3c20bd3), TOBN(0x8dea6143, 0x4fabc60c), + TOBN(0x45e21446, 0xde673629), TOBN(0x57f7aa1e, 0x703c2d21), + TOBN(0xa0e99b7f, 0x98c868c7), TOBN(0x4e42f66d, 0x8b641676), + TOBN(0x602884dc, 0x91077896), TOBN(0xa0d690cf, 0xc2c9885b), + TOBN(0xfeb4da33, 0x3b9a5187), TOBN(0x5f789598, 0x153c87ee), + TOBN(0x2192dd47, 0x52b16dba), TOBN(0xdeefc0e6, 0x3524c1b1), + TOBN(0x465ea76e, 0xe4383693), TOBN(0x79401711, 0x361b8d98), + TOBN(0xa5f9ace9, 0xf21a15cb), TOBN(0x73d26163, 0xefee9aeb), + TOBN(0xcca844b3, 0xe677016c), TOBN(0x6c122b07, 0x57eaee06), + TOBN(0xb782dce7, 0x15f09690), TOBN(0x508b9b12, 0x2dfc0fc9), + TOBN(0x9015ab4b, 0x65d89fc6), TOBN(0x5e79dab7, 0xd6d5bb0f), + TOBN(0x64f021f0, 0x6c775aa2), TOBN(0xdf09d8cc, 0x37c7eca1), + TOBN(0x9a761367, 0xef2fa506), TOBN(0xed4ca476, 0x5b81eec6), + TOBN(0x262ede36, 0x10bbb8b5), TOBN(0x0737ce83, 0x0641ada3), + TOBN(0x4c94288a, 0xe9831ccc), TOBN(0x487fc1ce, 0x8065e635), + TOBN(0xb13d7ab3, 0xb8bb3659), TOBN(0xdea5df3e, 0x855e4120), + TOBN(0xb9a18573, 0x85eb0244), TOBN(0x1a1b8ea3, 0xa7cfe0a3), + TOBN(0x3b837119, 0x67b0867c), TOBN(0x8d5e0d08, 0x9d364520), + TOBN(0x52dccc1e, 0xd930f0e3), TOBN(0xefbbcec7, 0xbf20bbaf), + TOBN(0x99cffcab, 0x0263ad10), TOBN(0xd8199e6d, 0xfcd18f8a), + TOBN(0x64e2773f, 0xe9f10617), TOBN(0x0079e8e1, 0x08704848), + TOBN(0x1169989f, 0x8a342283), TOBN(0x8097799c, 0xa83012e6), + TOBN(0xece966cb, 0x8a6a9001), TOBN(0x93b3afef, 0x072ac7fc), + TOBN(0xe6893a2a, 0x2db3d5ba), TOBN(0x263dc462, 0x89bf4fdc), + TOBN(0x8852dfc9, 0xe0396673), TOBN(0x7ac70895, 0x3af362b6), + TOBN(0xbb9cce4d, 0x5c2f342b), TOBN(0xbf80907a, 0xb52d7aae), + TOBN(0x97f3d3cd, 0x2161bcd0), TOBN(0xb25b0834, 0x0962744d), + TOBN(0xc5b18ea5, 0x6c3a1dda), TOBN(0xfe4ec7eb, 0x06c92317), + TOBN(0xb787b890, 0xad1c4afe), TOBN(0xdccd9a92, 0x0ede801a), + TOBN(0x9ac6ddda, 0xdb58da1f), TOBN(0x22bbc12f, 0xb8cae6ee), + TOBN(0xc6f8bced, 0x815c4a43), TOBN(0x8105a92c, 0xf96480c7), + TOBN(0x0dc3dbf3, 0x7a859d51), TOBN(0xe3ec7ce6, 0x3041196b), + TOBN(0xd9f64b25, 0x0d1067c9), TOBN(0xf2321321, 0x3d1f8dd8), + TOBN(0x8b5c619c, 0x76497ee8), TOBN(0x5d2b0ac6, 0xc717370e), + TOBN(0x98204cb6, 0x4fcf68e1), TOBN(0x0bdec211, 0x62bc6792), + TOBN(0x6973ccef, 0xa63b1011), TOBN(0xf9e3fa97, 0xe0de1ac5), + TOBN(0x5efb693e, 0x3d0e0c8b), TOBN(0x037248e9, 0xd2d4fcb4),} + , + {TOBN(0x80802dc9, 0x1ec34f9e), TOBN(0xd8772d35, 0x33810603), + TOBN(0x3f06d66c, 0x530cb4f3), TOBN(0x7be5ed0d, 0xc475c129), + TOBN(0xcb9e3c19, 0x31e82b10), TOBN(0xc63d2857, 0xc9ff6b4c), + TOBN(0xb92118c6, 0x92a1b45e), TOBN(0x0aec4414, 0x7285bbca), + TOBN(0xfc189ae7, 0x1e29a3ef), TOBN(0xcbe906f0, 0x4c93302e), + TOBN(0xd0107914, 0xceaae10e), TOBN(0xb7a23f34, 0xb68e19f8), + TOBN(0xe9d875c2, 0xefd2119d), TOBN(0x03198c6e, 0xfcadc9c8), + TOBN(0x65591bf6, 0x4da17113), TOBN(0x3cf0bbf8, 0x3d443038), + TOBN(0xae485bb7, 0x2b724759), TOBN(0x945353e1, 0xb2d4c63a), + TOBN(0x82159d07, 0xde7d6f2c), TOBN(0x389caef3, 0x4ec5b109), + TOBN(0x4a8ebb53, 0xdb65ef14), TOBN(0x2dc2cb7e, 0xdd99de43), + TOBN(0x816fa3ed, 0x83f2405f), TOBN(0x73429bb9, 0xc14208a3), + TOBN(0xb618d590, 0xb01e6e27), TOBN(0x047e2ccd, 0xe180b2dc), + TOBN(0xd1b299b5, 0x04aea4a9), TOBN(0x412c9e1e, 0x9fa403a4), + TOBN(0x88d28a36, 0x79407552), TOBN(0x49c50136, 0xf332b8e3), + TOBN(0x3a1b6fcc, 0xe668de19), TOBN(0x178851bc, 0x75122b97), + TOBN(0xb1e13752, 0xfb85fa4c), TOBN(0xd61257ce, 0x383c8ce9), + TOBN(0xd43da670, 0xd2f74dae), TOBN(0xa35aa23f, 0xbf846bbb), + TOBN(0x5e74235d, 0x4421fc83), TOBN(0xf6df8ee0, 0xc363473b), + TOBN(0x34d7f52a, 0x3c4aa158), TOBN(0x50d05aab, 0x9bc6d22e), + TOBN(0x8c56e735, 0xa64785f4), TOBN(0xbc56637b, 0x5f29cd07), + TOBN(0x53b2bb80, 0x3ee35067), TOBN(0x50235a0f, 0xdc919270), + TOBN(0x191ab6d8, 0xf2c4aa65), TOBN(0xc3475831, 0x8396023b), + TOBN(0x80400ba5, 0xf0f805ba), TOBN(0x8881065b, 0x5ec0f80f), + TOBN(0xc370e522, 0xcc1b5e83), TOBN(0xde2d4ad1, 0x860b8bfb), + TOBN(0xad364df0, 0x67b256df), TOBN(0x8f12502e, 0xe0138997), + TOBN(0x503fa0dc, 0x7783920a), TOBN(0xe80014ad, 0xc0bc866a), + TOBN(0x3f89b744, 0xd3064ba6), TOBN(0x03511dcd, 0xcba5dba5), + TOBN(0x197dd46d, 0x95a7b1a2), TOBN(0x9c4e7ad6, 0x3c6341fb), + TOBN(0x426eca29, 0x484c2ece), TOBN(0x9211e489, 0xde7f4f8a), + TOBN(0x14997f6e, 0xc78ef1f4), TOBN(0x2b2c0910, 0x06574586), + TOBN(0x17286a6e, 0x1c3eede8), TOBN(0x25f92e47, 0x0f60e018), + TOBN(0x805c5646, 0x31890a36), TOBN(0x703ef600, 0x57feea5b), + TOBN(0x389f747c, 0xaf3c3030), TOBN(0xe0e5daeb, 0x54dd3739), + TOBN(0xfe24a4c3, 0xc9c9f155), TOBN(0x7e4bf176, 0xb5393962), + TOBN(0x37183de2, 0xaf20bf29), TOBN(0x4a1bd7b5, 0xf95a8c3b), + TOBN(0xa83b9699, 0x46191d3d), TOBN(0x281fc8dd, 0x7b87f257), + TOBN(0xb18e2c13, 0x54107588), TOBN(0x6372def7, 0x9b2bafe8), + TOBN(0xdaf4bb48, 0x0d8972ca), TOBN(0x3f2dd4b7, 0x56167a3f), + TOBN(0x1eace32d, 0x84310cf4), TOBN(0xe3bcefaf, 0xe42700aa), + TOBN(0x5fe5691e, 0xd785e73d), TOBN(0xa5db5ab6, 0x2ea60467), + TOBN(0x02e23d41, 0xdfc6514a), TOBN(0x35e8048e, 0xe03c3665), + TOBN(0x3f8b118f, 0x1adaa0f8), TOBN(0x28ec3b45, 0x84ce1a5a), + TOBN(0xe8cacc6e, 0x2c6646b8), TOBN(0x1343d185, 0xdbd0e40f), + TOBN(0xe5d7f844, 0xcaaa358c), TOBN(0x1a1db7e4, 0x9924182a), + TOBN(0xd64cd42d, 0x9c875d9a), TOBN(0xb37b515f, 0x042eeec8), + TOBN(0x4d4dd409, 0x7b165fbe), TOBN(0xfc322ed9, 0xe206eff3), + TOBN(0x7dee4102, 0x59b7e17e), TOBN(0x55a481c0, 0x8236ca00), + TOBN(0x8c885312, 0xc23fc975), TOBN(0x15715806, 0x05d6297b), + TOBN(0xa078868e, 0xf78edd39), TOBN(0x956b31e0, 0x03c45e52), + TOBN(0x470275d5, 0xff7b33a6), TOBN(0xc8d5dc3a, 0x0c7e673f), + TOBN(0x419227b4, 0x7e2f2598), TOBN(0x8b37b634, 0x4c14a975), + TOBN(0xd0667ed6, 0x8b11888c), TOBN(0x5e0e8c3e, 0x803e25dc), + TOBN(0x34e5d0dc, 0xb987a24a), TOBN(0x9f40ac3b, 0xae920323), + TOBN(0x5463de95, 0x34e0f63a), TOBN(0xa128bf92, 0x6b6328f9), + TOBN(0x491ccd7c, 0xda64f1b7), TOBN(0x7ef1ec27, 0xc47bde35), + TOBN(0xa857240f, 0xa36a2737), TOBN(0x35dc1366, 0x63621bc1), + TOBN(0x7a3a6453, 0xd4fb6897), TOBN(0x80f1a439, 0xc929319d), + TOBN(0xfc18274b, 0xf8cb0ba0), TOBN(0xb0b53766, 0x8078c5eb), + TOBN(0xfb0d4924, 0x1e01d0ef), TOBN(0x50d7c67d, 0x372ab09c), + TOBN(0xb4e370af, 0x3aeac968), TOBN(0xe4f7fee9, 0xc4b63266), + TOBN(0xb4acd4c2, 0xe3ac5664), TOBN(0xf8910bd2, 0xceb38cbf), + TOBN(0x1c3ae50c, 0xc9c0726e), TOBN(0x15309569, 0xd97b40bf), + TOBN(0x70884b7f, 0xfd5a5a1b), TOBN(0x3890896a, 0xef8314cd), + TOBN(0x58e1515c, 0xa5618c93), TOBN(0xe665432b, 0x77d942d1), + TOBN(0xb32181bf, 0xb6f767a8), TOBN(0x753794e8, 0x3a604110), + TOBN(0x09afeb7c, 0xe8c0dbcc), TOBN(0x31e02613, 0x598673a3), + TOBN(0x5d98e557, 0x7d46db00), TOBN(0xfc21fb8c, 0x9d985b28), + TOBN(0xc9040116, 0xb0843e0b), TOBN(0x53b1b3a8, 0x69b04531), + TOBN(0xdd1649f0, 0x85d7d830), TOBN(0xbb3bcc87, 0xcb7427e8), + TOBN(0x77261100, 0xc93dce83), TOBN(0x7e79da61, 0xa1922a2a), + TOBN(0x587a2b02, 0xf3149ce8), TOBN(0x147e1384, 0xde92ec83), + TOBN(0x484c83d3, 0xaf077f30), TOBN(0xea78f844, 0x0658b53a), + TOBN(0x912076c2, 0x027aec53), TOBN(0xf34714e3, 0x93c8177d), + TOBN(0x37ef5d15, 0xc2376c84), TOBN(0x8315b659, 0x3d1aa783), + TOBN(0x3a75c484, 0xef852a90), TOBN(0x0ba0c58a, 0x16086bd4), + TOBN(0x29688d7a, 0x529a6d48), TOBN(0x9c7f250d, 0xc2f19203), + TOBN(0x123042fb, 0x682e2df9), TOBN(0x2b7587e7, 0xad8121bc), + TOBN(0x30fc0233, 0xe0182a65), TOBN(0xb82ecf87, 0xe3e1128a), + TOBN(0x71682861, 0x93fb098f), TOBN(0x043e21ae, 0x85e9e6a7), + TOBN(0xab5b49d6, 0x66c834ea), TOBN(0x3be43e18, 0x47414287), + TOBN(0xf40fb859, 0x219a2a47), TOBN(0x0e6559e9, 0xcc58df3c), + TOBN(0xfe1dfe8e, 0x0c6615b4), TOBN(0x14abc8fd, 0x56459d70), + TOBN(0x7be0fa8e, 0x05de0386), TOBN(0x8e63ef68, 0xe9035c7c), + TOBN(0x116401b4, 0x53b31e91), TOBN(0x0cba7ad4, 0x4436b4d8), + TOBN(0x9151f9a0, 0x107afd66), TOBN(0xafaca8d0, 0x1f0ee4c4), + TOBN(0x75fe5c1d, 0x9ee9761c), TOBN(0x3497a16b, 0xf0c0588f), + TOBN(0x3ee2bebd, 0x0304804c), TOBN(0xa8fb9a60, 0xc2c990b9), + TOBN(0xd14d32fe, 0x39251114), TOBN(0x36bf25bc, 0xcac73366), + TOBN(0xc9562c66, 0xdba7495c), TOBN(0x324d301b, 0x46ad348b), + TOBN(0x9f46620c, 0xd670407e), TOBN(0x0ea8d4f1, 0xe3733a01), + TOBN(0xd396d532, 0xb0c324e0), TOBN(0x5b211a0e, 0x03c317cd), + TOBN(0x090d7d20, 0x5ffe7b37), TOBN(0x3b7f3efb, 0x1747d2da), + TOBN(0xa2cb525f, 0xb54fc519), TOBN(0x6e220932, 0xf66a971e), + TOBN(0xddc160df, 0xb486d440), TOBN(0x7fcfec46, 0x3fe13465), + TOBN(0x83da7e4e, 0x76e4c151), TOBN(0xd6fa48a1, 0xd8d302b5), + TOBN(0xc6304f26, 0x5872cd88), TOBN(0x806c1d3c, 0x278b90a1), + TOBN(0x3553e725, 0xcaf0bc1c), TOBN(0xff59e603, 0xbb9d8d5c), + TOBN(0xa4550f32, 0x7a0b85dd), TOBN(0xdec5720a, 0x93ecc217), + TOBN(0x0b88b741, 0x69d62213), TOBN(0x7212f245, 0x5b365955), + TOBN(0x20764111, 0xb5cae787), TOBN(0x13cb7f58, 0x1dfd3124), + TOBN(0x2dca77da, 0x1175aefb), TOBN(0xeb75466b, 0xffaae775), + TOBN(0x74d76f3b, 0xdb6cff32), TOBN(0x7440f37a, 0x61fcda9a), + TOBN(0x1bb3ac92, 0xb525028b), TOBN(0x20fbf8f7, 0xa1975f29), + TOBN(0x982692e1, 0xdf83097f), TOBN(0x28738f6c, 0x554b0800), + TOBN(0xdc703717, 0xa2ce2f2f), TOBN(0x7913b93c, 0x40814194), + TOBN(0x04924593, 0x1fe89636), TOBN(0x7b98443f, 0xf78834a6), + TOBN(0x11c6ab01, 0x5114a5a1), TOBN(0x60deb383, 0xffba5f4c), + TOBN(0x4caa54c6, 0x01a982e6), TOBN(0x1dd35e11, 0x3491cd26), + TOBN(0x973c315f, 0x7cbd6b05), TOBN(0xcab00775, 0x52494724), + TOBN(0x04659b1f, 0x6565e15a), TOBN(0xbf30f529, 0x8c8fb026), + TOBN(0xfc21641b, 0xa8a0de37), TOBN(0xe9c7a366, 0xfa5e5114), + TOBN(0xdb849ca5, 0x52f03ad8), TOBN(0xc7e8dbe9, 0x024e35c0), + TOBN(0xa1a2bbac, 0xcfc3c789), TOBN(0xbf733e7d, 0x9c26f262), + TOBN(0x882ffbf5, 0xb8444823), TOBN(0xb7224e88, 0x6bf8483b), + TOBN(0x53023b8b, 0x65bef640), TOBN(0xaabfec91, 0xd4d5f8cd), + TOBN(0xa40e1510, 0x079ea1bd), TOBN(0x1ad9addc, 0xd05d5d26), + TOBN(0xdb3f2eab, 0x13e68d4f), TOBN(0x1cff1ae2, 0x640f803f), + TOBN(0xe0e7b749, 0xd4cee117), TOBN(0x8e9f275b, 0x4036d909), + TOBN(0xce34e31d, 0x8f4d4c38), TOBN(0x22b37f69, 0xd75130fc), + TOBN(0x83e0f1fd, 0xb4014604), TOBN(0xa8ce9919, 0x89415078), + TOBN(0x82375b75, 0x41792efe), TOBN(0x4f59bf5c, 0x97d4515b), + TOBN(0xac4f324f, 0x923a277d), TOBN(0xd9bc9b7d, 0x650f3406), + TOBN(0xc6fa87d1, 0x8a39bc51), TOBN(0x82588530, 0x5ccc108f), + TOBN(0x5ced3c9f, 0x82e4c634), TOBN(0x8efb8314, 0x3a4464f8), + TOBN(0xe706381b, 0x7a1dca25), TOBN(0x6cd15a3c, 0x5a2a412b), + TOBN(0x9347a8fd, 0xbfcd8fb5), TOBN(0x31db2eef, 0x6e54cd22), + TOBN(0xc4aeb11e, 0xf8d8932f), TOBN(0x11e7c1ed, 0x344411af), + TOBN(0x2653050c, 0xdc9a151e), TOBN(0x9edbfc08, 0x3bb0a859), + TOBN(0x926c81c7, 0xfd5691e7), TOBN(0x9c1b2342, 0x6f39019a), + TOBN(0x64a81c8b, 0x7f8474b9), TOBN(0x90657c07, 0x01761819), + TOBN(0x390b3331, 0x55e0375a), TOBN(0xc676c626, 0xb6ebc47d), + TOBN(0x51623247, 0xb7d6dee8), TOBN(0x0948d927, 0x79659313), + TOBN(0x99700161, 0xe9ab35ed), TOBN(0x06cc32b4, 0x8ddde408), + TOBN(0x6f2fd664, 0x061ef338), TOBN(0x1606fa02, 0xc202e9ed), + TOBN(0x55388bc1, 0x929ba99b), TOBN(0xc4428c5e, 0x1e81df69), + TOBN(0xce2028ae, 0xf91b0b2a), TOBN(0xce870a23, 0xf03dfd3f), + TOBN(0x66ec2c87, 0x0affe8ed), TOBN(0xb205fb46, 0x284d0c00), + TOBN(0xbf5dffe7, 0x44cefa48), TOBN(0xb6fc37a8, 0xa19876d7), + TOBN(0xbecfa84c, 0x08b72863), TOBN(0xd7205ff5, 0x2576374f), + TOBN(0x80330d32, 0x8887de41), TOBN(0x5de0df0c, 0x869ea534), + TOBN(0x13f42753, 0x3c56ea17), TOBN(0xeb1f6069, 0x452b1a78), + TOBN(0x50474396, 0xe30ea15c), TOBN(0x575816a1, 0xc1494125), + TOBN(0xbe1ce55b, 0xfe6bb38f), TOBN(0xb901a948, 0x96ae30f7), + TOBN(0xe5af0f08, 0xd8fc3548), TOBN(0x5010b5d0, 0xd73bfd08), + TOBN(0x993d2880, 0x53fe655a), TOBN(0x99f2630b, 0x1c1309fd), + TOBN(0xd8677baf, 0xb4e3b76f), TOBN(0x14e51ddc, 0xb840784b), + TOBN(0x326c750c, 0xbf0092ce), TOBN(0xc83d306b, 0xf528320f), + TOBN(0xc4456715, 0x77d4715c), TOBN(0xd30019f9, 0x6b703235), + TOBN(0x207ccb2e, 0xd669e986), TOBN(0x57c824af, 0xf6dbfc28), + TOBN(0xf0eb532f, 0xd8f92a23), TOBN(0x4a557fd4, 0x9bb98fd2), + TOBN(0xa57acea7, 0xc1e6199a), TOBN(0x0c663820, 0x8b94b1ed), + TOBN(0x9b42be8f, 0xf83a9266), TOBN(0xc7741c97, 0x0101bd45), + TOBN(0x95770c11, 0x07bd9ceb), TOBN(0x1f50250a, 0x8b2e0744), + TOBN(0xf762eec8, 0x1477b654), TOBN(0xc65b900e, 0x15efe59a), + TOBN(0x88c96148, 0x9546a897), TOBN(0x7e8025b3, 0xc30b4d7c), + TOBN(0xae4065ef, 0x12045cf9), TOBN(0x6fcb2caf, 0x9ccce8bd), + TOBN(0x1fa0ba4e, 0xf2cf6525), TOBN(0xf683125d, 0xcb72c312), + TOBN(0xa01da4ea, 0xe312410e), TOBN(0x67e28677, 0x6cd8e830), + TOBN(0xabd95752, 0x98fb3f07), TOBN(0x05f11e11, 0xeef649a5), + TOBN(0xba47faef, 0x9d3472c2), TOBN(0x3adff697, 0xc77d1345), + TOBN(0x4761fa04, 0xdd15afee), TOBN(0x64f1f61a, 0xb9e69462), + TOBN(0xfa691fab, 0x9bfb9093), TOBN(0x3df8ae8f, 0xa1133dfe), + TOBN(0xcd5f8967, 0x58cc710d), TOBN(0xfbb88d50, 0x16c7fe79), + TOBN(0x8e011b4c, 0xe88c50d1), TOBN(0x7532e807, 0xa8771c4f), + TOBN(0x64c78a48, 0xe2278ee4), TOBN(0x0b283e83, 0x3845072a), + TOBN(0x98a6f291, 0x49e69274), TOBN(0xb96e9668, 0x1868b21c), + TOBN(0x38f0adc2, 0xb1a8908e), TOBN(0x90afcff7, 0x1feb829d), + TOBN(0x9915a383, 0x210b0856), TOBN(0xa5a80602, 0xdef04889), + TOBN(0x800e9af9, 0x7c64d509), TOBN(0x81382d0b, 0xb8996f6f), + TOBN(0x490eba53, 0x81927e27), TOBN(0x46c63b32, 0x4af50182), + TOBN(0x784c5fd9, 0xd3ad62ce), TOBN(0xe4fa1870, 0xf8ae8736), + TOBN(0x4ec9d0bc, 0xd7466b25), TOBN(0x84ddbe1a, 0xdb235c65), + TOBN(0x5e2645ee, 0x163c1688), TOBN(0x570bd00e, 0x00eba747), + TOBN(0xfa51b629, 0x128bfa0f), TOBN(0x92fce1bd, 0x6c1d3b68), + TOBN(0x3e7361dc, 0xb66778b1), TOBN(0x9c7d249d, 0x5561d2bb), + TOBN(0xa40b28bf, 0x0bbc6229), TOBN(0x1c83c05e, 0xdfd91497), + TOBN(0x5f9f5154, 0xf083df05), TOBN(0xbac38b3c, 0xeee66c9d), + TOBN(0xf71db7e3, 0xec0dfcfd), TOBN(0xf2ecda8e, 0x8b0a8416), + TOBN(0x52fddd86, 0x7812aa66), TOBN(0x2896ef10, 0x4e6f4272), + TOBN(0xff27186a, 0x0fe9a745), TOBN(0x08249fcd, 0x49ca70db), + TOBN(0x7425a2e6, 0x441cac49), TOBN(0xf4a0885a, 0xece5ff57), + TOBN(0x6e2cb731, 0x7d7ead58), TOBN(0xf96cf7d6, 0x1898d104), + TOBN(0xafe67c9d, 0x4f2c9a89), TOBN(0x89895a50, 0x1c7bf5bc), + TOBN(0xdc7cb8e5, 0x573cecfa), TOBN(0x66497eae, 0xd15f03e6), + TOBN(0x6bc0de69, 0x3f084420), TOBN(0x323b9b36, 0xacd532b0), + TOBN(0xcfed390a, 0x0115a3c1), TOBN(0x9414c40b, 0x2d65ca0e), + TOBN(0x641406bd, 0x2f530c78), TOBN(0x29369a44, 0x833438f2), + TOBN(0x996884f5, 0x903fa271), TOBN(0xe6da0fd2, 0xb9da921e), + TOBN(0xa6f2f269, 0x5db01e54), TOBN(0x1ee3e9bd, 0x6876214e), + TOBN(0xa26e181c, 0xe27a9497), TOBN(0x36d254e4, 0x8e215e04), + TOBN(0x42f32a6c, 0x252cabca), TOBN(0x99481487, 0x80b57614), + TOBN(0x4c4dfe69, 0x40d9cae1), TOBN(0x05869580, 0x11a10f09), + TOBN(0xca287b57, 0x3491b64b), TOBN(0x77862d5d, 0x3fd4a53b), + TOBN(0xbf94856e, 0x50349126), TOBN(0x2be30bd1, 0x71c5268f), + TOBN(0x10393f19, 0xcbb650a6), TOBN(0x639531fe, 0x778cf9fd), + TOBN(0x02556a11, 0xb2935359), TOBN(0xda38aa96, 0xaf8c126e), + TOBN(0x47dbe6c2, 0x0960167f), TOBN(0x37bbabb6, 0x501901cd), + TOBN(0xb6e979e0, 0x2c947778), TOBN(0xd69a5175, 0x7a1a1dc6), + TOBN(0xc3ed5095, 0x9d9faf0c), TOBN(0x4dd9c096, 0x1d5fa5f0), + TOBN(0xa0c4304d, 0x64f16ea8), TOBN(0x8b1cac16, 0x7e718623), + TOBN(0x0b576546, 0x7c67f03e), TOBN(0x559cf5ad, 0xcbd88c01), + TOBN(0x074877bb, 0x0e2af19a), TOBN(0x1f717ec1, 0xa1228c92), + TOBN(0x70bcb800, 0x326e8920), TOBN(0xec6e2c5c, 0x4f312804), + TOBN(0x426aea7d, 0x3fca4752), TOBN(0xf12c0949, 0x2211f62a), + TOBN(0x24beecd8, 0x7be7b6b5), TOBN(0xb77eaf4c, 0x36d7a27d), + TOBN(0x154c2781, 0xfda78fd3), TOBN(0x848a83b0, 0x264eeabe), + TOBN(0x81287ef0, 0x4ffe2bc4), TOBN(0x7b6d88c6, 0xb6b6fc2a), + TOBN(0x805fb947, 0xce417d99), TOBN(0x4b93dcc3, 0x8b916cc4), + TOBN(0x72e65bb3, 0x21273323), TOBN(0xbcc1badd, 0x6ea9886e), + TOBN(0x0e223011, 0x4bc5ee85), TOBN(0xa561be74, 0xc18ee1e4), + TOBN(0x762fd2d4, 0xa6bcf1f1), TOBN(0x50e6a5a4, 0x95231489), + TOBN(0xca96001f, 0xa00b500b), TOBN(0x5c098cfc, 0x5d7dcdf5), + TOBN(0xa64e2d2e, 0x8c446a85), TOBN(0xbae9bcf1, 0x971f3c62), + TOBN(0x4ec22683, 0x8435a2c5), TOBN(0x8ceaed6c, 0x4bad4643), + TOBN(0xe9f8fb47, 0xccccf4e3), TOBN(0xbd4f3fa4, 0x1ce3b21e), + TOBN(0xd79fb110, 0xa3db3292), TOBN(0xe28a37da, 0xb536c66a), + TOBN(0x279ce87b, 0x8e49e6a9), TOBN(0x70ccfe8d, 0xfdcec8e3), + TOBN(0x2193e4e0, 0x3ba464b2), TOBN(0x0f39d60e, 0xaca9a398), + TOBN(0x7d7932af, 0xf82c12ab), TOBN(0xd8ff50ed, 0x91e7e0f7), + TOBN(0xea961058, 0xfa28a7e0), TOBN(0xc726cf25, 0x0bf5ec74), + TOBN(0xe74d55c8, 0xdb229666), TOBN(0x0bd9abbf, 0xa57f5799), + TOBN(0x7479ef07, 0x4dfc47b3), TOBN(0xd9c65fc3, 0x0c52f91d), + TOBN(0x8e0283fe, 0x36a8bde2), TOBN(0xa32a8b5e, 0x7d4b7280), + TOBN(0x6a677c61, 0x12e83233), TOBN(0x0fbb3512, 0xdcc9bf28), + TOBN(0x562e8ea5, 0x0d780f61), TOBN(0x0db8b22b, 0x1dc4e89c), + TOBN(0x0a6fd1fb, 0x89be0144), TOBN(0x8c77d246, 0xca57113b), + TOBN(0x4639075d, 0xff09c91c), TOBN(0x5b47b17f, 0x5060824c), + TOBN(0x58aea2b0, 0x16287b52), TOBN(0xa1343520, 0xd0cd8eb0), + TOBN(0x6148b4d0, 0xc5d58573), TOBN(0xdd2b6170, 0x291c68ae), + TOBN(0xa61b3929, 0x1da3b3b7), TOBN(0x5f946d79, 0x08c4ac10), + TOBN(0x4105d4a5, 0x7217d583), TOBN(0x5061da3d, 0x25e6de5e), + TOBN(0x3113940d, 0xec1b4991), TOBN(0xf12195e1, 0x36f485ae), + TOBN(0xa7507fb2, 0x731a2ee0), TOBN(0x95057a8e, 0x6e9e196e), + TOBN(0xa3c2c911, 0x2e130136), TOBN(0x97dfbb36, 0x33c60d15), + TOBN(0xcaf3c581, 0xb300ee2b), TOBN(0x77f25d90, 0xf4bac8b8), + TOBN(0xdb1c4f98, 0x6d840cd6), TOBN(0x471d62c0, 0xe634288c), + TOBN(0x8ec2f85e, 0xcec8a161), TOBN(0x41f37cbc, 0xfa6f4ae2), + TOBN(0x6793a20f, 0x4b709985), TOBN(0x7a7bd33b, 0xefa8985b), + TOBN(0x2c6a3fbd, 0x938e6446), TOBN(0x19042619, 0x2a8d47c1), + TOBN(0x16848667, 0xcc36975f), TOBN(0x02acf168, 0x9d5f1dfb), + TOBN(0x62d41ad4, 0x613baa94), TOBN(0xb56fbb92, 0x9f684670), + TOBN(0xce610d0d, 0xe9e40569), TOBN(0x7b99c65f, 0x35489fef), + TOBN(0x0c88ad1b, 0x3df18b97), TOBN(0x81b7d9be, 0x5d0e9edb), + TOBN(0xd85218c0, 0xc716cc0a), TOBN(0xf4b5ff90, 0x85691c49), + TOBN(0xa4fd666b, 0xce356ac6), TOBN(0x17c72895, 0x4b327a7a), + TOBN(0xf93d5085, 0xda6be7de), TOBN(0xff71530e, 0x3301d34e), + TOBN(0x4cd96442, 0xd8f448e8), TOBN(0x9283d331, 0x2ed18ffa), + TOBN(0x4d33dd99, 0x2a849870), TOBN(0xa716964b, 0x41576335), + TOBN(0xff5e3a9b, 0x179be0e5), TOBN(0x5b9d6b1b, 0x83b13632), + TOBN(0x3b8bd7d4, 0xa52f313b), TOBN(0xc9dd95a0, 0x637a4660), + TOBN(0x30035962, 0x0b3e218f), TOBN(0xce1481a3, 0xc7b28a3c), + TOBN(0xab41b43a, 0x43228d83), TOBN(0x24ae1c30, 0x4ad63f99), + TOBN(0x8e525f1a, 0x46a51229), TOBN(0x14af860f, 0xcd26d2b4), + TOBN(0xd6baef61, 0x3f714aa1), TOBN(0xf51865ad, 0xeb78795e), + TOBN(0xd3e21fce, 0xe6a9d694), TOBN(0x82ceb1dd, 0x8a37b527)} +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_oct.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_oct.c new file mode 100644 index 000000000..7ade1b3d2 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_oct.c @@ -0,0 +1,366 @@ +/* + * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#include "ec_lcl.h" + +int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, + EC_POINT *point, + const BIGNUM *x_, int y_bit, + BN_CTX *ctx) +{ + BN_CTX *new_ctx = NULL; + BIGNUM *tmp1, *tmp2, *x, *y; + int ret = 0; + + /* clear error queue */ + ERR_clear_error(); + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + y_bit = (y_bit != 0); + + BN_CTX_start(ctx); + tmp1 = BN_CTX_get(ctx); + tmp2 = BN_CTX_get(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (y == NULL) + goto err; + + /*- + * Recover y. We have a Weierstrass equation + * y^2 = x^3 + a*x + b, + * so y is one of the square roots of x^3 + a*x + b. + */ + + /* tmp1 := x^3 */ + if (!BN_nnmod(x, x_, group->field, ctx)) + goto err; + if (group->meth->field_decode == 0) { + /* field_{sqr,mul} work on standard representation */ + if (!group->meth->field_sqr(group, tmp2, x_, ctx)) + goto err; + if (!group->meth->field_mul(group, tmp1, tmp2, x_, ctx)) + goto err; + } else { + if (!BN_mod_sqr(tmp2, x_, group->field, ctx)) + goto err; + if (!BN_mod_mul(tmp1, tmp2, x_, group->field, ctx)) + goto err; + } + + /* tmp1 := tmp1 + a*x */ + if (group->a_is_minus3) { + if (!BN_mod_lshift1_quick(tmp2, x, group->field)) + goto err; + if (!BN_mod_add_quick(tmp2, tmp2, x, group->field)) + goto err; + if (!BN_mod_sub_quick(tmp1, tmp1, tmp2, group->field)) + goto err; + } else { + if (group->meth->field_decode) { + if (!group->meth->field_decode(group, tmp2, group->a, ctx)) + goto err; + if (!BN_mod_mul(tmp2, tmp2, x, group->field, ctx)) + goto err; + } else { + /* field_mul works on standard representation */ + if (!group->meth->field_mul(group, tmp2, group->a, x, ctx)) + goto err; + } + + if (!BN_mod_add_quick(tmp1, tmp1, tmp2, group->field)) + goto err; + } + + /* tmp1 := tmp1 + b */ + if (group->meth->field_decode) { + if (!group->meth->field_decode(group, tmp2, group->b, ctx)) + goto err; + if (!BN_mod_add_quick(tmp1, tmp1, tmp2, group->field)) + goto err; + } else { + if (!BN_mod_add_quick(tmp1, tmp1, group->b, group->field)) + goto err; + } + + if (!BN_mod_sqrt(y, tmp1, group->field, ctx)) { + unsigned long err = ERR_peek_last_error(); + + if (ERR_GET_LIB(err) == ERR_LIB_BN + && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE) { + ERR_clear_error(); + ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, + EC_R_INVALID_COMPRESSED_POINT); + } else + ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, + ERR_R_BN_LIB); + goto err; + } + + if (y_bit != BN_is_odd(y)) { + if (BN_is_zero(y)) { + int kron; + + kron = BN_kronecker(x, group->field, ctx); + if (kron == -2) + goto err; + + if (kron == 1) + ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, + EC_R_INVALID_COMPRESSION_BIT); + else + /* + * BN_mod_sqrt() should have caught this error (not a square) + */ + ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, + EC_R_INVALID_COMPRESSED_POINT); + goto err; + } + if (!BN_usub(y, group->field, y)) + goto err; + } + if (y_bit != BN_is_odd(y)) { + ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, + ERR_R_INTERNAL_ERROR); + goto err; + } + + if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx)) + goto err; + + ret = 1; + + err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, + point_conversion_form_t form, + unsigned char *buf, size_t len, BN_CTX *ctx) +{ + size_t ret; + BN_CTX *new_ctx = NULL; + int used_ctx = 0; + BIGNUM *x, *y; + size_t field_len, i, skip; + + if ((form != POINT_CONVERSION_COMPRESSED) + && (form != POINT_CONVERSION_UNCOMPRESSED) + && (form != POINT_CONVERSION_HYBRID)) { + ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_INVALID_FORM); + goto err; + } + + if (EC_POINT_is_at_infinity(group, point)) { + /* encodes to a single 0 octet */ + if (buf != NULL) { + if (len < 1) { + ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); + return 0; + } + buf[0] = 0; + } + return 1; + } + + /* ret := required output buffer length */ + field_len = BN_num_bytes(group->field); + ret = + (form == + POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len; + + /* if 'buf' is NULL, just return required length */ + if (buf != NULL) { + if (len < ret) { + ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); + goto err; + } + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + BN_CTX_start(ctx); + used_ctx = 1; + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (y == NULL) + goto err; + + if (!EC_POINT_get_affine_coordinates(group, point, x, y, ctx)) + goto err; + + if ((form == POINT_CONVERSION_COMPRESSED + || form == POINT_CONVERSION_HYBRID) && BN_is_odd(y)) + buf[0] = form + 1; + else + buf[0] = form; + + i = 1; + + skip = field_len - BN_num_bytes(x); + if (skip > field_len) { + ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); + goto err; + } + while (skip > 0) { + buf[i++] = 0; + skip--; + } + skip = BN_bn2bin(x, buf + i); + i += skip; + if (i != 1 + field_len) { + ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); + goto err; + } + + if (form == POINT_CONVERSION_UNCOMPRESSED + || form == POINT_CONVERSION_HYBRID) { + skip = field_len - BN_num_bytes(y); + if (skip > field_len) { + ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); + goto err; + } + while (skip > 0) { + buf[i++] = 0; + skip--; + } + skip = BN_bn2bin(y, buf + i); + i += skip; + } + + if (i != ret) { + ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); + goto err; + } + } + + if (used_ctx) + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; + + err: + if (used_ctx) + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return 0; +} + +int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point, + const unsigned char *buf, size_t len, BN_CTX *ctx) +{ + point_conversion_form_t form; + int y_bit; + BN_CTX *new_ctx = NULL; + BIGNUM *x, *y; + size_t field_len, enc_len; + int ret = 0; + + if (len == 0) { + ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL); + return 0; + } + form = buf[0]; + y_bit = form & 1; + form = form & ~1U; + if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED) + && (form != POINT_CONVERSION_UNCOMPRESSED) + && (form != POINT_CONVERSION_HYBRID)) { + ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + return 0; + } + if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit) { + ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + return 0; + } + + if (form == 0) { + if (len != 1) { + ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + return 0; + } + + return EC_POINT_set_to_infinity(group, point); + } + + field_len = BN_num_bytes(group->field); + enc_len = + (form == + POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len; + + if (len != enc_len) { + ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + return 0; + } + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + BN_CTX_start(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (y == NULL) + goto err; + + if (!BN_bin2bn(buf + 1, field_len, x)) + goto err; + if (BN_ucmp(x, group->field) >= 0) { + ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + goto err; + } + + if (form == POINT_CONVERSION_COMPRESSED) { + if (!EC_POINT_set_compressed_coordinates(group, point, x, y_bit, ctx)) + goto err; + } else { + if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) + goto err; + if (BN_ucmp(y, group->field) >= 0) { + ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + goto err; + } + if (form == POINT_CONVERSION_HYBRID) { + if (y_bit != BN_is_odd(y)) { + ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + goto err; + } + } + + /* + * EC_POINT_set_affine_coordinates is responsible for checking that + * the point is on the curve. + */ + if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx)) + goto err; + } + + ret = 1; + + err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_smpl.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_smpl.c new file mode 100644 index 000000000..f6a6cedb0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecp_smpl.c @@ -0,0 +1,1689 @@ +/* + * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#include "ec_lcl.h" + +const EC_METHOD *EC_GFp_simple_method(void) +{ + static const EC_METHOD ret = { + EC_FLAGS_DEFAULT_OCT, + NID_X9_62_prime_field, + ec_GFp_simple_group_init, + ec_GFp_simple_group_finish, + ec_GFp_simple_group_clear_finish, + ec_GFp_simple_group_copy, + ec_GFp_simple_group_set_curve, + ec_GFp_simple_group_get_curve, + ec_GFp_simple_group_get_degree, + ec_group_simple_order_bits, + ec_GFp_simple_group_check_discriminant, + ec_GFp_simple_point_init, + ec_GFp_simple_point_finish, + ec_GFp_simple_point_clear_finish, + ec_GFp_simple_point_copy, + ec_GFp_simple_point_set_to_infinity, + ec_GFp_simple_set_Jprojective_coordinates_GFp, + ec_GFp_simple_get_Jprojective_coordinates_GFp, + ec_GFp_simple_point_set_affine_coordinates, + ec_GFp_simple_point_get_affine_coordinates, + 0, 0, 0, + ec_GFp_simple_add, + ec_GFp_simple_dbl, + ec_GFp_simple_invert, + ec_GFp_simple_is_at_infinity, + ec_GFp_simple_is_on_curve, + ec_GFp_simple_cmp, + ec_GFp_simple_make_affine, + ec_GFp_simple_points_make_affine, + 0 /* mul */ , + 0 /* precompute_mult */ , + 0 /* have_precompute_mult */ , + ec_GFp_simple_field_mul, + ec_GFp_simple_field_sqr, + 0 /* field_div */ , + ec_GFp_simple_field_inv, + 0 /* field_encode */ , + 0 /* field_decode */ , + 0, /* field_set_to_one */ + ec_key_simple_priv2oct, + ec_key_simple_oct2priv, + 0, /* set private */ + ec_key_simple_generate_key, + ec_key_simple_check_key, + ec_key_simple_generate_public_key, + 0, /* keycopy */ + 0, /* keyfinish */ + ecdh_simple_compute_key, + 0, /* field_inverse_mod_ord */ + ec_GFp_simple_blind_coordinates, + ec_GFp_simple_ladder_pre, + ec_GFp_simple_ladder_step, + ec_GFp_simple_ladder_post + }; + + return &ret; +} + +/* + * Most method functions in this file are designed to work with + * non-trivial representations of field elements if necessary + * (see ecp_mont.c): while standard modular addition and subtraction + * are used, the field_mul and field_sqr methods will be used for + * multiplication, and field_encode and field_decode (if defined) + * will be used for converting between representations. + * + * Functions ec_GFp_simple_points_make_affine() and + * ec_GFp_simple_point_get_affine_coordinates() specifically assume + * that if a non-trivial representation is used, it is a Montgomery + * representation (i.e. 'encoding' means multiplying by some factor R). + */ + +int ec_GFp_simple_group_init(EC_GROUP *group) +{ + group->field = BN_new(); + group->a = BN_new(); + group->b = BN_new(); + if (group->field == NULL || group->a == NULL || group->b == NULL) { + BN_free(group->field); + BN_free(group->a); + BN_free(group->b); + return 0; + } + group->a_is_minus3 = 0; + return 1; +} + +void ec_GFp_simple_group_finish(EC_GROUP *group) +{ + BN_free(group->field); + BN_free(group->a); + BN_free(group->b); +} + +void ec_GFp_simple_group_clear_finish(EC_GROUP *group) +{ + BN_clear_free(group->field); + BN_clear_free(group->a); + BN_clear_free(group->b); +} + +int ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src) +{ + if (!BN_copy(dest->field, src->field)) + return 0; + if (!BN_copy(dest->a, src->a)) + return 0; + if (!BN_copy(dest->b, src->b)) + return 0; + + dest->a_is_minus3 = src->a_is_minus3; + + return 1; +} + +int ec_GFp_simple_group_set_curve(EC_GROUP *group, + const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx) +{ + int ret = 0; + BN_CTX *new_ctx = NULL; + BIGNUM *tmp_a; + + /* p must be a prime > 3 */ + if (BN_num_bits(p) <= 2 || !BN_is_odd(p)) { + ECerr(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE, EC_R_INVALID_FIELD); + return 0; + } + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + BN_CTX_start(ctx); + tmp_a = BN_CTX_get(ctx); + if (tmp_a == NULL) + goto err; + + /* group->field */ + if (!BN_copy(group->field, p)) + goto err; + BN_set_negative(group->field, 0); + + /* group->a */ + if (!BN_nnmod(tmp_a, a, p, ctx)) + goto err; + if (group->meth->field_encode) { + if (!group->meth->field_encode(group, group->a, tmp_a, ctx)) + goto err; + } else if (!BN_copy(group->a, tmp_a)) + goto err; + + /* group->b */ + if (!BN_nnmod(group->b, b, p, ctx)) + goto err; + if (group->meth->field_encode) + if (!group->meth->field_encode(group, group->b, group->b, ctx)) + goto err; + + /* group->a_is_minus3 */ + if (!BN_add_word(tmp_a, 3)) + goto err; + group->a_is_minus3 = (0 == BN_cmp(tmp_a, group->field)); + + ret = 1; + + err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +int ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, + BIGNUM *b, BN_CTX *ctx) +{ + int ret = 0; + BN_CTX *new_ctx = NULL; + + if (p != NULL) { + if (!BN_copy(p, group->field)) + return 0; + } + + if (a != NULL || b != NULL) { + if (group->meth->field_decode) { + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + if (a != NULL) { + if (!group->meth->field_decode(group, a, group->a, ctx)) + goto err; + } + if (b != NULL) { + if (!group->meth->field_decode(group, b, group->b, ctx)) + goto err; + } + } else { + if (a != NULL) { + if (!BN_copy(a, group->a)) + goto err; + } + if (b != NULL) { + if (!BN_copy(b, group->b)) + goto err; + } + } + } + + ret = 1; + + err: + BN_CTX_free(new_ctx); + return ret; +} + +int ec_GFp_simple_group_get_degree(const EC_GROUP *group) +{ + return BN_num_bits(group->field); +} + +int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx) +{ + int ret = 0; + BIGNUM *a, *b, *order, *tmp_1, *tmp_2; + const BIGNUM *p = group->field; + BN_CTX *new_ctx = NULL; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) { + ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT, + ERR_R_MALLOC_FAILURE); + goto err; + } + } + BN_CTX_start(ctx); + a = BN_CTX_get(ctx); + b = BN_CTX_get(ctx); + tmp_1 = BN_CTX_get(ctx); + tmp_2 = BN_CTX_get(ctx); + order = BN_CTX_get(ctx); + if (order == NULL) + goto err; + + if (group->meth->field_decode) { + if (!group->meth->field_decode(group, a, group->a, ctx)) + goto err; + if (!group->meth->field_decode(group, b, group->b, ctx)) + goto err; + } else { + if (!BN_copy(a, group->a)) + goto err; + if (!BN_copy(b, group->b)) + goto err; + } + + /*- + * check the discriminant: + * y^2 = x^3 + a*x + b is an elliptic curve <=> 4*a^3 + 27*b^2 != 0 (mod p) + * 0 =< a, b < p + */ + if (BN_is_zero(a)) { + if (BN_is_zero(b)) + goto err; + } else if (!BN_is_zero(b)) { + if (!BN_mod_sqr(tmp_1, a, p, ctx)) + goto err; + if (!BN_mod_mul(tmp_2, tmp_1, a, p, ctx)) + goto err; + if (!BN_lshift(tmp_1, tmp_2, 2)) + goto err; + /* tmp_1 = 4*a^3 */ + + if (!BN_mod_sqr(tmp_2, b, p, ctx)) + goto err; + if (!BN_mul_word(tmp_2, 27)) + goto err; + /* tmp_2 = 27*b^2 */ + + if (!BN_mod_add(a, tmp_1, tmp_2, p, ctx)) + goto err; + if (BN_is_zero(a)) + goto err; + } + ret = 1; + + err: + if (ctx != NULL) + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +int ec_GFp_simple_point_init(EC_POINT *point) +{ + point->X = BN_new(); + point->Y = BN_new(); + point->Z = BN_new(); + point->Z_is_one = 0; + + if (point->X == NULL || point->Y == NULL || point->Z == NULL) { + BN_free(point->X); + BN_free(point->Y); + BN_free(point->Z); + return 0; + } + return 1; +} + +void ec_GFp_simple_point_finish(EC_POINT *point) +{ + BN_free(point->X); + BN_free(point->Y); + BN_free(point->Z); +} + +void ec_GFp_simple_point_clear_finish(EC_POINT *point) +{ + BN_clear_free(point->X); + BN_clear_free(point->Y); + BN_clear_free(point->Z); + point->Z_is_one = 0; +} + +int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src) +{ + if (!BN_copy(dest->X, src->X)) + return 0; + if (!BN_copy(dest->Y, src->Y)) + return 0; + if (!BN_copy(dest->Z, src->Z)) + return 0; + dest->Z_is_one = src->Z_is_one; + dest->curve_name = src->curve_name; + + return 1; +} + +int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group, + EC_POINT *point) +{ + point->Z_is_one = 0; + BN_zero(point->Z); + return 1; +} + +int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *group, + EC_POINT *point, + const BIGNUM *x, + const BIGNUM *y, + const BIGNUM *z, + BN_CTX *ctx) +{ + BN_CTX *new_ctx = NULL; + int ret = 0; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + if (x != NULL) { + if (!BN_nnmod(point->X, x, group->field, ctx)) + goto err; + if (group->meth->field_encode) { + if (!group->meth->field_encode(group, point->X, point->X, ctx)) + goto err; + } + } + + if (y != NULL) { + if (!BN_nnmod(point->Y, y, group->field, ctx)) + goto err; + if (group->meth->field_encode) { + if (!group->meth->field_encode(group, point->Y, point->Y, ctx)) + goto err; + } + } + + if (z != NULL) { + int Z_is_one; + + if (!BN_nnmod(point->Z, z, group->field, ctx)) + goto err; + Z_is_one = BN_is_one(point->Z); + if (group->meth->field_encode) { + if (Z_is_one && (group->meth->field_set_to_one != 0)) { + if (!group->meth->field_set_to_one(group, point->Z, ctx)) + goto err; + } else { + if (!group-> + meth->field_encode(group, point->Z, point->Z, ctx)) + goto err; + } + } + point->Z_is_one = Z_is_one; + } + + ret = 1; + + err: + BN_CTX_free(new_ctx); + return ret; +} + +int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BIGNUM *z, BN_CTX *ctx) +{ + BN_CTX *new_ctx = NULL; + int ret = 0; + + if (group->meth->field_decode != 0) { + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + if (x != NULL) { + if (!group->meth->field_decode(group, x, point->X, ctx)) + goto err; + } + if (y != NULL) { + if (!group->meth->field_decode(group, y, point->Y, ctx)) + goto err; + } + if (z != NULL) { + if (!group->meth->field_decode(group, z, point->Z, ctx)) + goto err; + } + } else { + if (x != NULL) { + if (!BN_copy(x, point->X)) + goto err; + } + if (y != NULL) { + if (!BN_copy(y, point->Y)) + goto err; + } + if (z != NULL) { + if (!BN_copy(z, point->Z)) + goto err; + } + } + + ret = 1; + + err: + BN_CTX_free(new_ctx); + return ret; +} + +int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group, + EC_POINT *point, + const BIGNUM *x, + const BIGNUM *y, BN_CTX *ctx) +{ + if (x == NULL || y == NULL) { + /* + * unlike for projective coordinates, we do not tolerate this + */ + ECerr(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + return EC_POINT_set_Jprojective_coordinates_GFp(group, point, x, y, + BN_value_one(), ctx); +} + +int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx) +{ + BN_CTX *new_ctx = NULL; + BIGNUM *Z, *Z_1, *Z_2, *Z_3; + const BIGNUM *Z_; + int ret = 0; + + if (EC_POINT_is_at_infinity(group, point)) { + ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, + EC_R_POINT_AT_INFINITY); + return 0; + } + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + BN_CTX_start(ctx); + Z = BN_CTX_get(ctx); + Z_1 = BN_CTX_get(ctx); + Z_2 = BN_CTX_get(ctx); + Z_3 = BN_CTX_get(ctx); + if (Z_3 == NULL) + goto err; + + /* transform (X, Y, Z) into (x, y) := (X/Z^2, Y/Z^3) */ + + if (group->meth->field_decode) { + if (!group->meth->field_decode(group, Z, point->Z, ctx)) + goto err; + Z_ = Z; + } else { + Z_ = point->Z; + } + + if (BN_is_one(Z_)) { + if (group->meth->field_decode) { + if (x != NULL) { + if (!group->meth->field_decode(group, x, point->X, ctx)) + goto err; + } + if (y != NULL) { + if (!group->meth->field_decode(group, y, point->Y, ctx)) + goto err; + } + } else { + if (x != NULL) { + if (!BN_copy(x, point->X)) + goto err; + } + if (y != NULL) { + if (!BN_copy(y, point->Y)) + goto err; + } + } + } else { + if (!group->meth->field_inv(group, Z_1, Z_, ctx)) { + ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, + ERR_R_BN_LIB); + goto err; + } + + if (group->meth->field_encode == 0) { + /* field_sqr works on standard representation */ + if (!group->meth->field_sqr(group, Z_2, Z_1, ctx)) + goto err; + } else { + if (!BN_mod_sqr(Z_2, Z_1, group->field, ctx)) + goto err; + } + + if (x != NULL) { + /* + * in the Montgomery case, field_mul will cancel out Montgomery + * factor in X: + */ + if (!group->meth->field_mul(group, x, point->X, Z_2, ctx)) + goto err; + } + + if (y != NULL) { + if (group->meth->field_encode == 0) { + /* + * field_mul works on standard representation + */ + if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx)) + goto err; + } else { + if (!BN_mod_mul(Z_3, Z_2, Z_1, group->field, ctx)) + goto err; + } + + /* + * in the Montgomery case, field_mul will cancel out Montgomery + * factor in Y: + */ + if (!group->meth->field_mul(group, y, point->Y, Z_3, ctx)) + goto err; + } + } + + ret = 1; + + err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, + const EC_POINT *b, BN_CTX *ctx) +{ + int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, + const BIGNUM *, BN_CTX *); + int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); + const BIGNUM *p; + BN_CTX *new_ctx = NULL; + BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6; + int ret = 0; + + if (a == b) + return EC_POINT_dbl(group, r, a, ctx); + if (EC_POINT_is_at_infinity(group, a)) + return EC_POINT_copy(r, b); + if (EC_POINT_is_at_infinity(group, b)) + return EC_POINT_copy(r, a); + + field_mul = group->meth->field_mul; + field_sqr = group->meth->field_sqr; + p = group->field; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + BN_CTX_start(ctx); + n0 = BN_CTX_get(ctx); + n1 = BN_CTX_get(ctx); + n2 = BN_CTX_get(ctx); + n3 = BN_CTX_get(ctx); + n4 = BN_CTX_get(ctx); + n5 = BN_CTX_get(ctx); + n6 = BN_CTX_get(ctx); + if (n6 == NULL) + goto end; + + /* + * Note that in this function we must not read components of 'a' or 'b' + * once we have written the corresponding components of 'r'. ('r' might + * be one of 'a' or 'b'.) + */ + + /* n1, n2 */ + if (b->Z_is_one) { + if (!BN_copy(n1, a->X)) + goto end; + if (!BN_copy(n2, a->Y)) + goto end; + /* n1 = X_a */ + /* n2 = Y_a */ + } else { + if (!field_sqr(group, n0, b->Z, ctx)) + goto end; + if (!field_mul(group, n1, a->X, n0, ctx)) + goto end; + /* n1 = X_a * Z_b^2 */ + + if (!field_mul(group, n0, n0, b->Z, ctx)) + goto end; + if (!field_mul(group, n2, a->Y, n0, ctx)) + goto end; + /* n2 = Y_a * Z_b^3 */ + } + + /* n3, n4 */ + if (a->Z_is_one) { + if (!BN_copy(n3, b->X)) + goto end; + if (!BN_copy(n4, b->Y)) + goto end; + /* n3 = X_b */ + /* n4 = Y_b */ + } else { + if (!field_sqr(group, n0, a->Z, ctx)) + goto end; + if (!field_mul(group, n3, b->X, n0, ctx)) + goto end; + /* n3 = X_b * Z_a^2 */ + + if (!field_mul(group, n0, n0, a->Z, ctx)) + goto end; + if (!field_mul(group, n4, b->Y, n0, ctx)) + goto end; + /* n4 = Y_b * Z_a^3 */ + } + + /* n5, n6 */ + if (!BN_mod_sub_quick(n5, n1, n3, p)) + goto end; + if (!BN_mod_sub_quick(n6, n2, n4, p)) + goto end; + /* n5 = n1 - n3 */ + /* n6 = n2 - n4 */ + + if (BN_is_zero(n5)) { + if (BN_is_zero(n6)) { + /* a is the same point as b */ + BN_CTX_end(ctx); + ret = EC_POINT_dbl(group, r, a, ctx); + ctx = NULL; + goto end; + } else { + /* a is the inverse of b */ + BN_zero(r->Z); + r->Z_is_one = 0; + ret = 1; + goto end; + } + } + + /* 'n7', 'n8' */ + if (!BN_mod_add_quick(n1, n1, n3, p)) + goto end; + if (!BN_mod_add_quick(n2, n2, n4, p)) + goto end; + /* 'n7' = n1 + n3 */ + /* 'n8' = n2 + n4 */ + + /* Z_r */ + if (a->Z_is_one && b->Z_is_one) { + if (!BN_copy(r->Z, n5)) + goto end; + } else { + if (a->Z_is_one) { + if (!BN_copy(n0, b->Z)) + goto end; + } else if (b->Z_is_one) { + if (!BN_copy(n0, a->Z)) + goto end; + } else { + if (!field_mul(group, n0, a->Z, b->Z, ctx)) + goto end; + } + if (!field_mul(group, r->Z, n0, n5, ctx)) + goto end; + } + r->Z_is_one = 0; + /* Z_r = Z_a * Z_b * n5 */ + + /* X_r */ + if (!field_sqr(group, n0, n6, ctx)) + goto end; + if (!field_sqr(group, n4, n5, ctx)) + goto end; + if (!field_mul(group, n3, n1, n4, ctx)) + goto end; + if (!BN_mod_sub_quick(r->X, n0, n3, p)) + goto end; + /* X_r = n6^2 - n5^2 * 'n7' */ + + /* 'n9' */ + if (!BN_mod_lshift1_quick(n0, r->X, p)) + goto end; + if (!BN_mod_sub_quick(n0, n3, n0, p)) + goto end; + /* n9 = n5^2 * 'n7' - 2 * X_r */ + + /* Y_r */ + if (!field_mul(group, n0, n0, n6, ctx)) + goto end; + if (!field_mul(group, n5, n4, n5, ctx)) + goto end; /* now n5 is n5^3 */ + if (!field_mul(group, n1, n2, n5, ctx)) + goto end; + if (!BN_mod_sub_quick(n0, n0, n1, p)) + goto end; + if (BN_is_odd(n0)) + if (!BN_add(n0, n0, p)) + goto end; + /* now 0 <= n0 < 2*p, and n0 is even */ + if (!BN_rshift1(r->Y, n0)) + goto end; + /* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */ + + ret = 1; + + end: + if (ctx) /* otherwise we already called BN_CTX_end */ + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, + BN_CTX *ctx) +{ + int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, + const BIGNUM *, BN_CTX *); + int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); + const BIGNUM *p; + BN_CTX *new_ctx = NULL; + BIGNUM *n0, *n1, *n2, *n3; + int ret = 0; + + if (EC_POINT_is_at_infinity(group, a)) { + BN_zero(r->Z); + r->Z_is_one = 0; + return 1; + } + + field_mul = group->meth->field_mul; + field_sqr = group->meth->field_sqr; + p = group->field; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + BN_CTX_start(ctx); + n0 = BN_CTX_get(ctx); + n1 = BN_CTX_get(ctx); + n2 = BN_CTX_get(ctx); + n3 = BN_CTX_get(ctx); + if (n3 == NULL) + goto err; + + /* + * Note that in this function we must not read components of 'a' once we + * have written the corresponding components of 'r'. ('r' might the same + * as 'a'.) + */ + + /* n1 */ + if (a->Z_is_one) { + if (!field_sqr(group, n0, a->X, ctx)) + goto err; + if (!BN_mod_lshift1_quick(n1, n0, p)) + goto err; + if (!BN_mod_add_quick(n0, n0, n1, p)) + goto err; + if (!BN_mod_add_quick(n1, n0, group->a, p)) + goto err; + /* n1 = 3 * X_a^2 + a_curve */ + } else if (group->a_is_minus3) { + if (!field_sqr(group, n1, a->Z, ctx)) + goto err; + if (!BN_mod_add_quick(n0, a->X, n1, p)) + goto err; + if (!BN_mod_sub_quick(n2, a->X, n1, p)) + goto err; + if (!field_mul(group, n1, n0, n2, ctx)) + goto err; + if (!BN_mod_lshift1_quick(n0, n1, p)) + goto err; + if (!BN_mod_add_quick(n1, n0, n1, p)) + goto err; + /*- + * n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2) + * = 3 * X_a^2 - 3 * Z_a^4 + */ + } else { + if (!field_sqr(group, n0, a->X, ctx)) + goto err; + if (!BN_mod_lshift1_quick(n1, n0, p)) + goto err; + if (!BN_mod_add_quick(n0, n0, n1, p)) + goto err; + if (!field_sqr(group, n1, a->Z, ctx)) + goto err; + if (!field_sqr(group, n1, n1, ctx)) + goto err; + if (!field_mul(group, n1, n1, group->a, ctx)) + goto err; + if (!BN_mod_add_quick(n1, n1, n0, p)) + goto err; + /* n1 = 3 * X_a^2 + a_curve * Z_a^4 */ + } + + /* Z_r */ + if (a->Z_is_one) { + if (!BN_copy(n0, a->Y)) + goto err; + } else { + if (!field_mul(group, n0, a->Y, a->Z, ctx)) + goto err; + } + if (!BN_mod_lshift1_quick(r->Z, n0, p)) + goto err; + r->Z_is_one = 0; + /* Z_r = 2 * Y_a * Z_a */ + + /* n2 */ + if (!field_sqr(group, n3, a->Y, ctx)) + goto err; + if (!field_mul(group, n2, a->X, n3, ctx)) + goto err; + if (!BN_mod_lshift_quick(n2, n2, 2, p)) + goto err; + /* n2 = 4 * X_a * Y_a^2 */ + + /* X_r */ + if (!BN_mod_lshift1_quick(n0, n2, p)) + goto err; + if (!field_sqr(group, r->X, n1, ctx)) + goto err; + if (!BN_mod_sub_quick(r->X, r->X, n0, p)) + goto err; + /* X_r = n1^2 - 2 * n2 */ + + /* n3 */ + if (!field_sqr(group, n0, n3, ctx)) + goto err; + if (!BN_mod_lshift_quick(n3, n0, 3, p)) + goto err; + /* n3 = 8 * Y_a^4 */ + + /* Y_r */ + if (!BN_mod_sub_quick(n0, n2, r->X, p)) + goto err; + if (!field_mul(group, n0, n1, n0, ctx)) + goto err; + if (!BN_mod_sub_quick(r->Y, n0, n3, p)) + goto err; + /* Y_r = n1 * (n2 - X_r) - n3 */ + + ret = 1; + + err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +int ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) +{ + if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(point->Y)) + /* point is its own inverse */ + return 1; + + return BN_usub(point->Y, group->field, point->Y); +} + +int ec_GFp_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) +{ + return BN_is_zero(point->Z); +} + +int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, + BN_CTX *ctx) +{ + int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, + const BIGNUM *, BN_CTX *); + int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); + const BIGNUM *p; + BN_CTX *new_ctx = NULL; + BIGNUM *rh, *tmp, *Z4, *Z6; + int ret = -1; + + if (EC_POINT_is_at_infinity(group, point)) + return 1; + + field_mul = group->meth->field_mul; + field_sqr = group->meth->field_sqr; + p = group->field; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return -1; + } + + BN_CTX_start(ctx); + rh = BN_CTX_get(ctx); + tmp = BN_CTX_get(ctx); + Z4 = BN_CTX_get(ctx); + Z6 = BN_CTX_get(ctx); + if (Z6 == NULL) + goto err; + + /*- + * We have a curve defined by a Weierstrass equation + * y^2 = x^3 + a*x + b. + * The point to consider is given in Jacobian projective coordinates + * where (X, Y, Z) represents (x, y) = (X/Z^2, Y/Z^3). + * Substituting this and multiplying by Z^6 transforms the above equation into + * Y^2 = X^3 + a*X*Z^4 + b*Z^6. + * To test this, we add up the right-hand side in 'rh'. + */ + + /* rh := X^2 */ + if (!field_sqr(group, rh, point->X, ctx)) + goto err; + + if (!point->Z_is_one) { + if (!field_sqr(group, tmp, point->Z, ctx)) + goto err; + if (!field_sqr(group, Z4, tmp, ctx)) + goto err; + if (!field_mul(group, Z6, Z4, tmp, ctx)) + goto err; + + /* rh := (rh + a*Z^4)*X */ + if (group->a_is_minus3) { + if (!BN_mod_lshift1_quick(tmp, Z4, p)) + goto err; + if (!BN_mod_add_quick(tmp, tmp, Z4, p)) + goto err; + if (!BN_mod_sub_quick(rh, rh, tmp, p)) + goto err; + if (!field_mul(group, rh, rh, point->X, ctx)) + goto err; + } else { + if (!field_mul(group, tmp, Z4, group->a, ctx)) + goto err; + if (!BN_mod_add_quick(rh, rh, tmp, p)) + goto err; + if (!field_mul(group, rh, rh, point->X, ctx)) + goto err; + } + + /* rh := rh + b*Z^6 */ + if (!field_mul(group, tmp, group->b, Z6, ctx)) + goto err; + if (!BN_mod_add_quick(rh, rh, tmp, p)) + goto err; + } else { + /* point->Z_is_one */ + + /* rh := (rh + a)*X */ + if (!BN_mod_add_quick(rh, rh, group->a, p)) + goto err; + if (!field_mul(group, rh, rh, point->X, ctx)) + goto err; + /* rh := rh + b */ + if (!BN_mod_add_quick(rh, rh, group->b, p)) + goto err; + } + + /* 'lh' := Y^2 */ + if (!field_sqr(group, tmp, point->Y, ctx)) + goto err; + + ret = (0 == BN_ucmp(tmp, rh)); + + err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a, + const EC_POINT *b, BN_CTX *ctx) +{ + /*- + * return values: + * -1 error + * 0 equal (in affine coordinates) + * 1 not equal + */ + + int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, + const BIGNUM *, BN_CTX *); + int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); + BN_CTX *new_ctx = NULL; + BIGNUM *tmp1, *tmp2, *Za23, *Zb23; + const BIGNUM *tmp1_, *tmp2_; + int ret = -1; + + if (EC_POINT_is_at_infinity(group, a)) { + return EC_POINT_is_at_infinity(group, b) ? 0 : 1; + } + + if (EC_POINT_is_at_infinity(group, b)) + return 1; + + if (a->Z_is_one && b->Z_is_one) { + return ((BN_cmp(a->X, b->X) == 0) && BN_cmp(a->Y, b->Y) == 0) ? 0 : 1; + } + + field_mul = group->meth->field_mul; + field_sqr = group->meth->field_sqr; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return -1; + } + + BN_CTX_start(ctx); + tmp1 = BN_CTX_get(ctx); + tmp2 = BN_CTX_get(ctx); + Za23 = BN_CTX_get(ctx); + Zb23 = BN_CTX_get(ctx); + if (Zb23 == NULL) + goto end; + + /*- + * We have to decide whether + * (X_a/Z_a^2, Y_a/Z_a^3) = (X_b/Z_b^2, Y_b/Z_b^3), + * or equivalently, whether + * (X_a*Z_b^2, Y_a*Z_b^3) = (X_b*Z_a^2, Y_b*Z_a^3). + */ + + if (!b->Z_is_one) { + if (!field_sqr(group, Zb23, b->Z, ctx)) + goto end; + if (!field_mul(group, tmp1, a->X, Zb23, ctx)) + goto end; + tmp1_ = tmp1; + } else + tmp1_ = a->X; + if (!a->Z_is_one) { + if (!field_sqr(group, Za23, a->Z, ctx)) + goto end; + if (!field_mul(group, tmp2, b->X, Za23, ctx)) + goto end; + tmp2_ = tmp2; + } else + tmp2_ = b->X; + + /* compare X_a*Z_b^2 with X_b*Z_a^2 */ + if (BN_cmp(tmp1_, tmp2_) != 0) { + ret = 1; /* points differ */ + goto end; + } + + if (!b->Z_is_one) { + if (!field_mul(group, Zb23, Zb23, b->Z, ctx)) + goto end; + if (!field_mul(group, tmp1, a->Y, Zb23, ctx)) + goto end; + /* tmp1_ = tmp1 */ + } else + tmp1_ = a->Y; + if (!a->Z_is_one) { + if (!field_mul(group, Za23, Za23, a->Z, ctx)) + goto end; + if (!field_mul(group, tmp2, b->Y, Za23, ctx)) + goto end; + /* tmp2_ = tmp2 */ + } else + tmp2_ = b->Y; + + /* compare Y_a*Z_b^3 with Y_b*Z_a^3 */ + if (BN_cmp(tmp1_, tmp2_) != 0) { + ret = 1; /* points differ */ + goto end; + } + + /* points are equal */ + ret = 0; + + end: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, + BN_CTX *ctx) +{ + BN_CTX *new_ctx = NULL; + BIGNUM *x, *y; + int ret = 0; + + if (point->Z_is_one || EC_POINT_is_at_infinity(group, point)) + return 1; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + BN_CTX_start(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (y == NULL) + goto err; + + if (!EC_POINT_get_affine_coordinates(group, point, x, y, ctx)) + goto err; + if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx)) + goto err; + if (!point->Z_is_one) { + ECerr(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE, ERR_R_INTERNAL_ERROR); + goto err; + } + + ret = 1; + + err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, + EC_POINT *points[], BN_CTX *ctx) +{ + BN_CTX *new_ctx = NULL; + BIGNUM *tmp, *tmp_Z; + BIGNUM **prod_Z = NULL; + size_t i; + int ret = 0; + + if (num == 0) + return 1; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + BN_CTX_start(ctx); + tmp = BN_CTX_get(ctx); + tmp_Z = BN_CTX_get(ctx); + if (tmp_Z == NULL) + goto err; + + prod_Z = OPENSSL_malloc(num * sizeof(prod_Z[0])); + if (prod_Z == NULL) + goto err; + for (i = 0; i < num; i++) { + prod_Z[i] = BN_new(); + if (prod_Z[i] == NULL) + goto err; + } + + /* + * Set each prod_Z[i] to the product of points[0]->Z .. points[i]->Z, + * skipping any zero-valued inputs (pretend that they're 1). + */ + + if (!BN_is_zero(points[0]->Z)) { + if (!BN_copy(prod_Z[0], points[0]->Z)) + goto err; + } else { + if (group->meth->field_set_to_one != 0) { + if (!group->meth->field_set_to_one(group, prod_Z[0], ctx)) + goto err; + } else { + if (!BN_one(prod_Z[0])) + goto err; + } + } + + for (i = 1; i < num; i++) { + if (!BN_is_zero(points[i]->Z)) { + if (!group-> + meth->field_mul(group, prod_Z[i], prod_Z[i - 1], points[i]->Z, + ctx)) + goto err; + } else { + if (!BN_copy(prod_Z[i], prod_Z[i - 1])) + goto err; + } + } + + /* + * Now use a single explicit inversion to replace every non-zero + * points[i]->Z by its inverse. + */ + + if (!group->meth->field_inv(group, tmp, prod_Z[num - 1], ctx)) { + ECerr(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE, ERR_R_BN_LIB); + goto err; + } + if (group->meth->field_encode != 0) { + /* + * In the Montgomery case, we just turned R*H (representing H) into + * 1/(R*H), but we need R*(1/H) (representing 1/H); i.e. we need to + * multiply by the Montgomery factor twice. + */ + if (!group->meth->field_encode(group, tmp, tmp, ctx)) + goto err; + if (!group->meth->field_encode(group, tmp, tmp, ctx)) + goto err; + } + + for (i = num - 1; i > 0; --i) { + /* + * Loop invariant: tmp is the product of the inverses of points[0]->Z + * .. points[i]->Z (zero-valued inputs skipped). + */ + if (!BN_is_zero(points[i]->Z)) { + /* + * Set tmp_Z to the inverse of points[i]->Z (as product of Z + * inverses 0 .. i, Z values 0 .. i - 1). + */ + if (!group-> + meth->field_mul(group, tmp_Z, prod_Z[i - 1], tmp, ctx)) + goto err; + /* + * Update tmp to satisfy the loop invariant for i - 1. + */ + if (!group->meth->field_mul(group, tmp, tmp, points[i]->Z, ctx)) + goto err; + /* Replace points[i]->Z by its inverse. */ + if (!BN_copy(points[i]->Z, tmp_Z)) + goto err; + } + } + + if (!BN_is_zero(points[0]->Z)) { + /* Replace points[0]->Z by its inverse. */ + if (!BN_copy(points[0]->Z, tmp)) + goto err; + } + + /* Finally, fix up the X and Y coordinates for all points. */ + + for (i = 0; i < num; i++) { + EC_POINT *p = points[i]; + + if (!BN_is_zero(p->Z)) { + /* turn (X, Y, 1/Z) into (X/Z^2, Y/Z^3, 1) */ + + if (!group->meth->field_sqr(group, tmp, p->Z, ctx)) + goto err; + if (!group->meth->field_mul(group, p->X, p->X, tmp, ctx)) + goto err; + + if (!group->meth->field_mul(group, tmp, tmp, p->Z, ctx)) + goto err; + if (!group->meth->field_mul(group, p->Y, p->Y, tmp, ctx)) + goto err; + + if (group->meth->field_set_to_one != 0) { + if (!group->meth->field_set_to_one(group, p->Z, ctx)) + goto err; + } else { + if (!BN_one(p->Z)) + goto err; + } + p->Z_is_one = 1; + } + } + + ret = 1; + + err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + if (prod_Z != NULL) { + for (i = 0; i < num; i++) { + if (prod_Z[i] == NULL) + break; + BN_clear_free(prod_Z[i]); + } + OPENSSL_free(prod_Z); + } + return ret; +} + +int ec_GFp_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx) +{ + return BN_mod_mul(r, a, b, group->field, ctx); +} + +int ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, + BN_CTX *ctx) +{ + return BN_mod_sqr(r, a, group->field, ctx); +} + +/*- + * Computes the multiplicative inverse of a in GF(p), storing the result in r. + * If a is zero (or equivalent), you'll get a EC_R_CANNOT_INVERT error. + * Since we don't have a Mont structure here, SCA hardening is with blinding. + */ +int ec_GFp_simple_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, + BN_CTX *ctx) +{ + BIGNUM *e = NULL; + BN_CTX *new_ctx = NULL; + int ret = 0; + + if (ctx == NULL && (ctx = new_ctx = BN_CTX_secure_new()) == NULL) + return 0; + + BN_CTX_start(ctx); + if ((e = BN_CTX_get(ctx)) == NULL) + goto err; + + do { + if (!BN_priv_rand_range(e, group->field)) + goto err; + } while (BN_is_zero(e)); + + /* r := a * e */ + if (!group->meth->field_mul(group, r, a, e, ctx)) + goto err; + /* r := 1/(a * e) */ + if (!BN_mod_inverse(r, r, group->field, ctx)) { + ECerr(EC_F_EC_GFP_SIMPLE_FIELD_INV, EC_R_CANNOT_INVERT); + goto err; + } + /* r := e/(a * e) = 1/a */ + if (!group->meth->field_mul(group, r, r, e, ctx)) + goto err; + + ret = 1; + + err: + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return ret; +} + +/*- + * Apply randomization of EC point projective coordinates: + * + * (X, Y ,Z ) = (lambda^2*X, lambda^3*Y, lambda*Z) + * lambda = [1,group->field) + * + */ +int ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p, + BN_CTX *ctx) +{ + int ret = 0; + BIGNUM *lambda = NULL; + BIGNUM *temp = NULL; + + BN_CTX_start(ctx); + lambda = BN_CTX_get(ctx); + temp = BN_CTX_get(ctx); + if (temp == NULL) { + ECerr(EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* make sure lambda is not zero */ + do { + if (!BN_priv_rand_range(lambda, group->field)) { + ECerr(EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES, ERR_R_BN_LIB); + goto err; + } + } while (BN_is_zero(lambda)); + + /* if field_encode defined convert between representations */ + if (group->meth->field_encode != NULL + && !group->meth->field_encode(group, lambda, lambda, ctx)) + goto err; + if (!group->meth->field_mul(group, p->Z, p->Z, lambda, ctx)) + goto err; + if (!group->meth->field_sqr(group, temp, lambda, ctx)) + goto err; + if (!group->meth->field_mul(group, p->X, p->X, temp, ctx)) + goto err; + if (!group->meth->field_mul(group, temp, temp, lambda, ctx)) + goto err; + if (!group->meth->field_mul(group, p->Y, p->Y, temp, ctx)) + goto err; + p->Z_is_one = 0; + + ret = 1; + + err: + BN_CTX_end(ctx); + return ret; +} + +/*- + * Set s := p, r := 2p. + * + * For doubling we use Formula 3 from Izu-Takagi "A fast parallel elliptic curve + * multiplication resistant against side channel attacks" appendix, as described + * at + * https://hyperelliptic.org/EFD/g1p/auto-shortw-xz.html#doubling-dbl-2002-it-2 + * + * The input point p will be in randomized Jacobian projective coords: + * x = X/Z**2, y=Y/Z**3 + * + * The output points p, s, and r are converted to standard (homogeneous) + * projective coords: + * x = X/Z, y=Y/Z + */ +int ec_GFp_simple_ladder_pre(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx) +{ + BIGNUM *t1, *t2, *t3, *t4, *t5, *t6 = NULL; + + t1 = r->Z; + t2 = r->Y; + t3 = s->X; + t4 = r->X; + t5 = s->Y; + t6 = s->Z; + + /* convert p: (X,Y,Z) -> (XZ,Y,Z**3) */ + if (!group->meth->field_mul(group, p->X, p->X, p->Z, ctx) + || !group->meth->field_sqr(group, t1, p->Z, ctx) + || !group->meth->field_mul(group, p->Z, p->Z, t1, ctx) + /* r := 2p */ + || !group->meth->field_sqr(group, t2, p->X, ctx) + || !group->meth->field_sqr(group, t3, p->Z, ctx) + || !group->meth->field_mul(group, t4, t3, group->a, ctx) + || !BN_mod_sub_quick(t5, t2, t4, group->field) + || !BN_mod_add_quick(t2, t2, t4, group->field) + || !group->meth->field_sqr(group, t5, t5, ctx) + || !group->meth->field_mul(group, t6, t3, group->b, ctx) + || !group->meth->field_mul(group, t1, p->X, p->Z, ctx) + || !group->meth->field_mul(group, t4, t1, t6, ctx) + || !BN_mod_lshift_quick(t4, t4, 3, group->field) + /* r->X coord output */ + || !BN_mod_sub_quick(r->X, t5, t4, group->field) + || !group->meth->field_mul(group, t1, t1, t2, ctx) + || !group->meth->field_mul(group, t2, t3, t6, ctx) + || !BN_mod_add_quick(t1, t1, t2, group->field) + /* r->Z coord output */ + || !BN_mod_lshift_quick(r->Z, t1, 2, group->field) + || !EC_POINT_copy(s, p)) + return 0; + + r->Z_is_one = 0; + s->Z_is_one = 0; + p->Z_is_one = 0; + + return 1; +} + +/*- + * Differential addition-and-doubling using Eq. (9) and (10) from Izu-Takagi + * "A fast parallel elliptic curve multiplication resistant against side channel + * attacks", as described at + * https://hyperelliptic.org/EFD/g1p/auto-shortw-xz.html#ladder-ladd-2002-it-4 + */ +int ec_GFp_simple_ladder_step(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx) +{ + int ret = 0; + BIGNUM *t0, *t1, *t2, *t3, *t4, *t5, *t6, *t7 = NULL; + + BN_CTX_start(ctx); + t0 = BN_CTX_get(ctx); + t1 = BN_CTX_get(ctx); + t2 = BN_CTX_get(ctx); + t3 = BN_CTX_get(ctx); + t4 = BN_CTX_get(ctx); + t5 = BN_CTX_get(ctx); + t6 = BN_CTX_get(ctx); + t7 = BN_CTX_get(ctx); + + if (t7 == NULL + || !group->meth->field_mul(group, t0, r->X, s->X, ctx) + || !group->meth->field_mul(group, t1, r->Z, s->Z, ctx) + || !group->meth->field_mul(group, t2, r->X, s->Z, ctx) + || !group->meth->field_mul(group, t3, r->Z, s->X, ctx) + || !group->meth->field_mul(group, t4, group->a, t1, ctx) + || !BN_mod_add_quick(t0, t0, t4, group->field) + || !BN_mod_add_quick(t4, t3, t2, group->field) + || !group->meth->field_mul(group, t0, t4, t0, ctx) + || !group->meth->field_sqr(group, t1, t1, ctx) + || !BN_mod_lshift_quick(t7, group->b, 2, group->field) + || !group->meth->field_mul(group, t1, t7, t1, ctx) + || !BN_mod_lshift1_quick(t0, t0, group->field) + || !BN_mod_add_quick(t0, t1, t0, group->field) + || !BN_mod_sub_quick(t1, t2, t3, group->field) + || !group->meth->field_sqr(group, t1, t1, ctx) + || !group->meth->field_mul(group, t3, t1, p->X, ctx) + || !group->meth->field_mul(group, t0, p->Z, t0, ctx) + /* s->X coord output */ + || !BN_mod_sub_quick(s->X, t0, t3, group->field) + /* s->Z coord output */ + || !group->meth->field_mul(group, s->Z, p->Z, t1, ctx) + || !group->meth->field_sqr(group, t3, r->X, ctx) + || !group->meth->field_sqr(group, t2, r->Z, ctx) + || !group->meth->field_mul(group, t4, t2, group->a, ctx) + || !BN_mod_add_quick(t5, r->X, r->Z, group->field) + || !group->meth->field_sqr(group, t5, t5, ctx) + || !BN_mod_sub_quick(t5, t5, t3, group->field) + || !BN_mod_sub_quick(t5, t5, t2, group->field) + || !BN_mod_sub_quick(t6, t3, t4, group->field) + || !group->meth->field_sqr(group, t6, t6, ctx) + || !group->meth->field_mul(group, t0, t2, t5, ctx) + || !group->meth->field_mul(group, t0, t7, t0, ctx) + /* r->X coord output */ + || !BN_mod_sub_quick(r->X, t6, t0, group->field) + || !BN_mod_add_quick(t6, t3, t4, group->field) + || !group->meth->field_sqr(group, t3, t2, ctx) + || !group->meth->field_mul(group, t7, t3, t7, ctx) + || !group->meth->field_mul(group, t5, t5, t6, ctx) + || !BN_mod_lshift1_quick(t5, t5, group->field) + /* r->Z coord output */ + || !BN_mod_add_quick(r->Z, t7, t5, group->field)) + goto err; + + ret = 1; + + err: + BN_CTX_end(ctx); + return ret; +} + +/*- + * Recovers the y-coordinate of r using Eq. (8) from Brier-Joye, "Weierstrass + * Elliptic Curves and Side-Channel Attacks", modified to work in projective + * coordinates and return r in Jacobian projective coordinates. + * + * X4 = two*Y1*X2*Z3*Z2*Z1; + * Y4 = two*b*Z3*SQR(Z2*Z1) + Z3*(a*Z2*Z1+X1*X2)*(X1*Z2+X2*Z1) - X3*SQR(X1*Z2-X2*Z1); + * Z4 = two*Y1*Z3*SQR(Z2)*Z1; + * + * Z4 != 0 because: + * - Z1==0 implies p is at infinity, which would have caused an early exit in + * the caller; + * - Z2==0 implies r is at infinity (handled by the BN_is_zero(r->Z) branch); + * - Z3==0 implies s is at infinity (handled by the BN_is_zero(s->Z) branch); + * - Y1==0 implies p has order 2, so either r or s are infinity and handled by + * one of the BN_is_zero(...) branches. + */ +int ec_GFp_simple_ladder_post(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx) +{ + int ret = 0; + BIGNUM *t0, *t1, *t2, *t3, *t4, *t5, *t6 = NULL; + + if (BN_is_zero(r->Z)) + return EC_POINT_set_to_infinity(group, r); + + if (BN_is_zero(s->Z)) { + /* (X,Y,Z) -> (XZ,YZ**2,Z) */ + if (!group->meth->field_mul(group, r->X, p->X, p->Z, ctx) + || !group->meth->field_sqr(group, r->Z, p->Z, ctx) + || !group->meth->field_mul(group, r->Y, p->Y, r->Z, ctx) + || !BN_copy(r->Z, p->Z) + || !EC_POINT_invert(group, r, ctx)) + return 0; + return 1; + } + + BN_CTX_start(ctx); + t0 = BN_CTX_get(ctx); + t1 = BN_CTX_get(ctx); + t2 = BN_CTX_get(ctx); + t3 = BN_CTX_get(ctx); + t4 = BN_CTX_get(ctx); + t5 = BN_CTX_get(ctx); + t6 = BN_CTX_get(ctx); + + if (t6 == NULL + || !BN_mod_lshift1_quick(t0, p->Y, group->field) + || !group->meth->field_mul(group, t1, r->X, p->Z, ctx) + || !group->meth->field_mul(group, t2, r->Z, s->Z, ctx) + || !group->meth->field_mul(group, t2, t1, t2, ctx) + || !group->meth->field_mul(group, t3, t2, t0, ctx) + || !group->meth->field_mul(group, t2, r->Z, p->Z, ctx) + || !group->meth->field_sqr(group, t4, t2, ctx) + || !BN_mod_lshift1_quick(t5, group->b, group->field) + || !group->meth->field_mul(group, t4, t4, t5, ctx) + || !group->meth->field_mul(group, t6, t2, group->a, ctx) + || !group->meth->field_mul(group, t5, r->X, p->X, ctx) + || !BN_mod_add_quick(t5, t6, t5, group->field) + || !group->meth->field_mul(group, t6, r->Z, p->X, ctx) + || !BN_mod_add_quick(t2, t6, t1, group->field) + || !group->meth->field_mul(group, t5, t5, t2, ctx) + || !BN_mod_sub_quick(t6, t6, t1, group->field) + || !group->meth->field_sqr(group, t6, t6, ctx) + || !group->meth->field_mul(group, t6, t6, s->X, ctx) + || !BN_mod_add_quick(t4, t5, t4, group->field) + || !group->meth->field_mul(group, t4, t4, s->Z, ctx) + || !BN_mod_sub_quick(t4, t4, t6, group->field) + || !group->meth->field_sqr(group, t5, r->Z, ctx) + || !group->meth->field_mul(group, r->Z, p->Z, s->Z, ctx) + || !group->meth->field_mul(group, r->Z, t5, r->Z, ctx) + || !group->meth->field_mul(group, r->Z, r->Z, t0, ctx) + /* t3 := X, t4 := Y */ + /* (X,Y,Z) -> (XZ,YZ**2,Z) */ + || !group->meth->field_mul(group, r->X, t3, r->Z, ctx) + || !group->meth->field_sqr(group, t3, r->Z, ctx) + || !group->meth->field_mul(group, r->Y, t4, t3, ctx)) + goto err; + + ret = 1; + + err: + BN_CTX_end(ctx); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecx_meth.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecx_meth.c new file mode 100644 index 000000000..e4cac99e2 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ec/ecx_meth.c @@ -0,0 +1,841 @@ +/* + * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include "internal/asn1_int.h" +#include "internal/evp_int.h" +#include "ec_lcl.h" +#include "curve448/curve448_lcl.h" + +#define X25519_BITS 253 +#define X25519_SECURITY_BITS 128 + +#define ED25519_SIGSIZE 64 + +#define X448_BITS 448 +#define ED448_BITS 456 +#define X448_SECURITY_BITS 224 + +#define ED448_SIGSIZE 114 + +#define ISX448(id) ((id) == EVP_PKEY_X448) +#define IS25519(id) ((id) == EVP_PKEY_X25519 || (id) == EVP_PKEY_ED25519) +#define KEYLENID(id) (IS25519(id) ? X25519_KEYLEN \ + : ((id) == EVP_PKEY_X448 ? X448_KEYLEN \ + : ED448_KEYLEN)) +#define KEYLEN(p) KEYLENID((p)->ameth->pkey_id) + + +typedef enum { + KEY_OP_PUBLIC, + KEY_OP_PRIVATE, + KEY_OP_KEYGEN +} ecx_key_op_t; + +/* Setup EVP_PKEY using public, private or generation */ +static int ecx_key_op(EVP_PKEY *pkey, int id, const X509_ALGOR *palg, + const unsigned char *p, int plen, ecx_key_op_t op) +{ + ECX_KEY *key = NULL; + unsigned char *privkey, *pubkey; + + if (op != KEY_OP_KEYGEN) { + if (palg != NULL) { + int ptype; + + /* Algorithm parameters must be absent */ + X509_ALGOR_get0(NULL, &ptype, NULL, palg); + if (ptype != V_ASN1_UNDEF) { + ECerr(EC_F_ECX_KEY_OP, EC_R_INVALID_ENCODING); + return 0; + } + } + + if (p == NULL || plen != KEYLENID(id)) { + ECerr(EC_F_ECX_KEY_OP, EC_R_INVALID_ENCODING); + return 0; + } + } + + key = OPENSSL_zalloc(sizeof(*key)); + if (key == NULL) { + ECerr(EC_F_ECX_KEY_OP, ERR_R_MALLOC_FAILURE); + return 0; + } + pubkey = key->pubkey; + + if (op == KEY_OP_PUBLIC) { + memcpy(pubkey, p, plen); + } else { + privkey = key->privkey = OPENSSL_secure_malloc(KEYLENID(id)); + if (privkey == NULL) { + ECerr(EC_F_ECX_KEY_OP, ERR_R_MALLOC_FAILURE); + goto err; + } + if (op == KEY_OP_KEYGEN) { + if (RAND_priv_bytes(privkey, KEYLENID(id)) <= 0) { + OPENSSL_secure_free(privkey); + key->privkey = NULL; + goto err; + } + if (id == EVP_PKEY_X25519) { + privkey[0] &= 248; + privkey[X25519_KEYLEN - 1] &= 127; + privkey[X25519_KEYLEN - 1] |= 64; + } else if (id == EVP_PKEY_X448) { + privkey[0] &= 252; + privkey[X448_KEYLEN - 1] |= 128; + } + } else { + memcpy(privkey, p, KEYLENID(id)); + } + switch (id) { + case EVP_PKEY_X25519: + X25519_public_from_private(pubkey, privkey); + break; + case EVP_PKEY_ED25519: + ED25519_public_from_private(pubkey, privkey); + break; + case EVP_PKEY_X448: + X448_public_from_private(pubkey, privkey); + break; + case EVP_PKEY_ED448: + ED448_public_from_private(pubkey, privkey); + break; + } + } + + EVP_PKEY_assign(pkey, id, key); + return 1; + err: + OPENSSL_free(key); + return 0; +} + +static int ecx_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) +{ + const ECX_KEY *ecxkey = pkey->pkey.ecx; + unsigned char *penc; + + if (ecxkey == NULL) { + ECerr(EC_F_ECX_PUB_ENCODE, EC_R_INVALID_KEY); + return 0; + } + + penc = OPENSSL_memdup(ecxkey->pubkey, KEYLEN(pkey)); + if (penc == NULL) { + ECerr(EC_F_ECX_PUB_ENCODE, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (!X509_PUBKEY_set0_param(pk, OBJ_nid2obj(pkey->ameth->pkey_id), + V_ASN1_UNDEF, NULL, penc, KEYLEN(pkey))) { + OPENSSL_free(penc); + ECerr(EC_F_ECX_PUB_ENCODE, ERR_R_MALLOC_FAILURE); + return 0; + } + return 1; +} + +static int ecx_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) +{ + const unsigned char *p; + int pklen; + X509_ALGOR *palg; + + if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey)) + return 0; + return ecx_key_op(pkey, pkey->ameth->pkey_id, palg, p, pklen, + KEY_OP_PUBLIC); +} + +static int ecx_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) +{ + const ECX_KEY *akey = a->pkey.ecx; + const ECX_KEY *bkey = b->pkey.ecx; + + if (akey == NULL || bkey == NULL) + return -2; + + return CRYPTO_memcmp(akey->pubkey, bkey->pubkey, KEYLEN(a)) == 0; +} + +static int ecx_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8) +{ + const unsigned char *p; + int plen; + ASN1_OCTET_STRING *oct = NULL; + const X509_ALGOR *palg; + int rv; + + if (!PKCS8_pkey_get0(NULL, &p, &plen, &palg, p8)) + return 0; + + oct = d2i_ASN1_OCTET_STRING(NULL, &p, plen); + if (oct == NULL) { + p = NULL; + plen = 0; + } else { + p = ASN1_STRING_get0_data(oct); + plen = ASN1_STRING_length(oct); + } + + rv = ecx_key_op(pkey, pkey->ameth->pkey_id, palg, p, plen, KEY_OP_PRIVATE); + ASN1_OCTET_STRING_free(oct); + return rv; +} + +static int ecx_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) +{ + const ECX_KEY *ecxkey = pkey->pkey.ecx; + ASN1_OCTET_STRING oct; + unsigned char *penc = NULL; + int penclen; + + if (ecxkey == NULL || ecxkey->privkey == NULL) { + ECerr(EC_F_ECX_PRIV_ENCODE, EC_R_INVALID_PRIVATE_KEY); + return 0; + } + + oct.data = ecxkey->privkey; + oct.length = KEYLEN(pkey); + oct.flags = 0; + + penclen = i2d_ASN1_OCTET_STRING(&oct, &penc); + if (penclen < 0) { + ECerr(EC_F_ECX_PRIV_ENCODE, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(pkey->ameth->pkey_id), 0, + V_ASN1_UNDEF, NULL, penc, penclen)) { + OPENSSL_clear_free(penc, penclen); + ECerr(EC_F_ECX_PRIV_ENCODE, ERR_R_MALLOC_FAILURE); + return 0; + } + + return 1; +} + +static int ecx_size(const EVP_PKEY *pkey) +{ + return KEYLEN(pkey); +} + +static int ecx_bits(const EVP_PKEY *pkey) +{ + if (IS25519(pkey->ameth->pkey_id)) { + return X25519_BITS; + } else if(ISX448(pkey->ameth->pkey_id)) { + return X448_BITS; + } else { + return ED448_BITS; + } +} + +static int ecx_security_bits(const EVP_PKEY *pkey) +{ + if (IS25519(pkey->ameth->pkey_id)) { + return X25519_SECURITY_BITS; + } else { + return X448_SECURITY_BITS; + } +} + +static void ecx_free(EVP_PKEY *pkey) +{ + if (pkey->pkey.ecx != NULL) + OPENSSL_secure_clear_free(pkey->pkey.ecx->privkey, KEYLEN(pkey)); + OPENSSL_free(pkey->pkey.ecx); +} + +/* "parameters" are always equal */ +static int ecx_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) +{ + return 1; +} + +static int ecx_key_print(BIO *bp, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *ctx, ecx_key_op_t op) +{ + const ECX_KEY *ecxkey = pkey->pkey.ecx; + const char *nm = OBJ_nid2ln(pkey->ameth->pkey_id); + + if (op == KEY_OP_PRIVATE) { + if (ecxkey == NULL || ecxkey->privkey == NULL) { + if (BIO_printf(bp, "%*s\n", indent, "") <= 0) + return 0; + return 1; + } + if (BIO_printf(bp, "%*s%s Private-Key:\n", indent, "", nm) <= 0) + return 0; + if (BIO_printf(bp, "%*spriv:\n", indent, "") <= 0) + return 0; + if (ASN1_buf_print(bp, ecxkey->privkey, KEYLEN(pkey), + indent + 4) == 0) + return 0; + } else { + if (ecxkey == NULL) { + if (BIO_printf(bp, "%*s\n", indent, "") <= 0) + return 0; + return 1; + } + if (BIO_printf(bp, "%*s%s Public-Key:\n", indent, "", nm) <= 0) + return 0; + } + if (BIO_printf(bp, "%*spub:\n", indent, "") <= 0) + return 0; + + if (ASN1_buf_print(bp, ecxkey->pubkey, KEYLEN(pkey), + indent + 4) == 0) + return 0; + return 1; +} + +static int ecx_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *ctx) +{ + return ecx_key_print(bp, pkey, indent, ctx, KEY_OP_PRIVATE); +} + +static int ecx_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *ctx) +{ + return ecx_key_print(bp, pkey, indent, ctx, KEY_OP_PUBLIC); +} + +static int ecx_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) +{ + switch (op) { + + case ASN1_PKEY_CTRL_SET1_TLS_ENCPT: + return ecx_key_op(pkey, pkey->ameth->pkey_id, NULL, arg2, arg1, + KEY_OP_PUBLIC); + + case ASN1_PKEY_CTRL_GET1_TLS_ENCPT: + if (pkey->pkey.ecx != NULL) { + unsigned char **ppt = arg2; + + *ppt = OPENSSL_memdup(pkey->pkey.ecx->pubkey, KEYLEN(pkey)); + if (*ppt != NULL) + return KEYLEN(pkey); + } + return 0; + + default: + return -2; + + } +} + +static int ecd_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) +{ + switch (op) { + case ASN1_PKEY_CTRL_DEFAULT_MD_NID: + /* We currently only support Pure EdDSA which takes no digest */ + *(int *)arg2 = NID_undef; + return 2; + + default: + return -2; + + } +} + +static int ecx_set_priv_key(EVP_PKEY *pkey, const unsigned char *priv, + size_t len) +{ + return ecx_key_op(pkey, pkey->ameth->pkey_id, NULL, priv, len, + KEY_OP_PRIVATE); +} + +static int ecx_set_pub_key(EVP_PKEY *pkey, const unsigned char *pub, size_t len) +{ + return ecx_key_op(pkey, pkey->ameth->pkey_id, NULL, pub, len, + KEY_OP_PUBLIC); +} + +static int ecx_get_priv_key(const EVP_PKEY *pkey, unsigned char *priv, + size_t *len) +{ + const ECX_KEY *key = pkey->pkey.ecx; + + if (priv == NULL) { + *len = KEYLENID(pkey->ameth->pkey_id); + return 1; + } + + if (key == NULL + || key->privkey == NULL + || *len < (size_t)KEYLENID(pkey->ameth->pkey_id)) + return 0; + + *len = KEYLENID(pkey->ameth->pkey_id); + memcpy(priv, key->privkey, *len); + + return 1; +} + +static int ecx_get_pub_key(const EVP_PKEY *pkey, unsigned char *pub, + size_t *len) +{ + const ECX_KEY *key = pkey->pkey.ecx; + + if (pub == NULL) { + *len = KEYLENID(pkey->ameth->pkey_id); + return 1; + } + + if (key == NULL + || *len < (size_t)KEYLENID(pkey->ameth->pkey_id)) + return 0; + + *len = KEYLENID(pkey->ameth->pkey_id); + memcpy(pub, key->pubkey, *len); + + return 1; +} + +const EVP_PKEY_ASN1_METHOD ecx25519_asn1_meth = { + EVP_PKEY_X25519, + EVP_PKEY_X25519, + 0, + "X25519", + "OpenSSL X25519 algorithm", + + ecx_pub_decode, + ecx_pub_encode, + ecx_pub_cmp, + ecx_pub_print, + + ecx_priv_decode, + ecx_priv_encode, + ecx_priv_print, + + ecx_size, + ecx_bits, + ecx_security_bits, + + 0, 0, 0, 0, + ecx_cmp_parameters, + 0, 0, + + ecx_free, + ecx_ctrl, + NULL, + NULL, + + NULL, + NULL, + NULL, + + NULL, + NULL, + NULL, + + ecx_set_priv_key, + ecx_set_pub_key, + ecx_get_priv_key, + ecx_get_pub_key, +}; + +const EVP_PKEY_ASN1_METHOD ecx448_asn1_meth = { + EVP_PKEY_X448, + EVP_PKEY_X448, + 0, + "X448", + "OpenSSL X448 algorithm", + + ecx_pub_decode, + ecx_pub_encode, + ecx_pub_cmp, + ecx_pub_print, + + ecx_priv_decode, + ecx_priv_encode, + ecx_priv_print, + + ecx_size, + ecx_bits, + ecx_security_bits, + + 0, 0, 0, 0, + ecx_cmp_parameters, + 0, 0, + + ecx_free, + ecx_ctrl, + NULL, + NULL, + + NULL, + NULL, + NULL, + + NULL, + NULL, + NULL, + + ecx_set_priv_key, + ecx_set_pub_key, + ecx_get_priv_key, + ecx_get_pub_key, +}; + +static int ecd_size25519(const EVP_PKEY *pkey) +{ + return ED25519_SIGSIZE; +} + +static int ecd_size448(const EVP_PKEY *pkey) +{ + return ED448_SIGSIZE; +} + +static int ecd_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn, + X509_ALGOR *sigalg, ASN1_BIT_STRING *str, + EVP_PKEY *pkey) +{ + const ASN1_OBJECT *obj; + int ptype; + int nid; + + /* Sanity check: make sure it is ED25519/ED448 with absent parameters */ + X509_ALGOR_get0(&obj, &ptype, NULL, sigalg); + nid = OBJ_obj2nid(obj); + if ((nid != NID_ED25519 && nid != NID_ED448) || ptype != V_ASN1_UNDEF) { + ECerr(EC_F_ECD_ITEM_VERIFY, EC_R_INVALID_ENCODING); + return 0; + } + + if (!EVP_DigestVerifyInit(ctx, NULL, NULL, NULL, pkey)) + return 0; + + return 2; +} + +static int ecd_item_sign25519(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn, + X509_ALGOR *alg1, X509_ALGOR *alg2, + ASN1_BIT_STRING *str) +{ + /* Set algorithms identifiers */ + X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_ED25519), V_ASN1_UNDEF, NULL); + if (alg2) + X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_ED25519), V_ASN1_UNDEF, NULL); + /* Algorithm idetifiers set: carry on as normal */ + return 3; +} + +static int ecd_sig_info_set25519(X509_SIG_INFO *siginf, const X509_ALGOR *alg, + const ASN1_STRING *sig) +{ + X509_SIG_INFO_set(siginf, NID_undef, NID_ED25519, X25519_SECURITY_BITS, + X509_SIG_INFO_TLS); + return 1; +} + +static int ecd_item_sign448(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn, + X509_ALGOR *alg1, X509_ALGOR *alg2, + ASN1_BIT_STRING *str) +{ + /* Set algorithm identifier */ + X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_ED448), V_ASN1_UNDEF, NULL); + if (alg2 != NULL) + X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_ED448), V_ASN1_UNDEF, NULL); + /* Algorithm identifier set: carry on as normal */ + return 3; +} + +static int ecd_sig_info_set448(X509_SIG_INFO *siginf, const X509_ALGOR *alg, + const ASN1_STRING *sig) +{ + X509_SIG_INFO_set(siginf, NID_undef, NID_ED448, X448_SECURITY_BITS, + X509_SIG_INFO_TLS); + return 1; +} + + +const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth = { + EVP_PKEY_ED25519, + EVP_PKEY_ED25519, + 0, + "ED25519", + "OpenSSL ED25519 algorithm", + + ecx_pub_decode, + ecx_pub_encode, + ecx_pub_cmp, + ecx_pub_print, + + ecx_priv_decode, + ecx_priv_encode, + ecx_priv_print, + + ecd_size25519, + ecx_bits, + ecx_security_bits, + + 0, 0, 0, 0, + ecx_cmp_parameters, + 0, 0, + + ecx_free, + ecd_ctrl, + NULL, + NULL, + ecd_item_verify, + ecd_item_sign25519, + ecd_sig_info_set25519, + + NULL, + NULL, + NULL, + + ecx_set_priv_key, + ecx_set_pub_key, + ecx_get_priv_key, + ecx_get_pub_key, +}; + +const EVP_PKEY_ASN1_METHOD ed448_asn1_meth = { + EVP_PKEY_ED448, + EVP_PKEY_ED448, + 0, + "ED448", + "OpenSSL ED448 algorithm", + + ecx_pub_decode, + ecx_pub_encode, + ecx_pub_cmp, + ecx_pub_print, + + ecx_priv_decode, + ecx_priv_encode, + ecx_priv_print, + + ecd_size448, + ecx_bits, + ecx_security_bits, + + 0, 0, 0, 0, + ecx_cmp_parameters, + 0, 0, + + ecx_free, + ecd_ctrl, + NULL, + NULL, + ecd_item_verify, + ecd_item_sign448, + ecd_sig_info_set448, + + NULL, + NULL, + NULL, + + ecx_set_priv_key, + ecx_set_pub_key, + ecx_get_priv_key, + ecx_get_pub_key, +}; + +static int pkey_ecx_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) +{ + return ecx_key_op(pkey, ctx->pmeth->pkey_id, NULL, NULL, 0, KEY_OP_KEYGEN); +} + +static int validate_ecx_derive(EVP_PKEY_CTX *ctx, unsigned char *key, + size_t *keylen, + const unsigned char **privkey, + const unsigned char **pubkey) +{ + const ECX_KEY *ecxkey, *peerkey; + + if (ctx->pkey == NULL || ctx->peerkey == NULL) { + ECerr(EC_F_VALIDATE_ECX_DERIVE, EC_R_KEYS_NOT_SET); + return 0; + } + ecxkey = ctx->pkey->pkey.ecx; + peerkey = ctx->peerkey->pkey.ecx; + if (ecxkey == NULL || ecxkey->privkey == NULL) { + ECerr(EC_F_VALIDATE_ECX_DERIVE, EC_R_INVALID_PRIVATE_KEY); + return 0; + } + if (peerkey == NULL) { + ECerr(EC_F_VALIDATE_ECX_DERIVE, EC_R_INVALID_PEER_KEY); + return 0; + } + *privkey = ecxkey->privkey; + *pubkey = peerkey->pubkey; + + return 1; +} + +static int pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key, + size_t *keylen) +{ + const unsigned char *privkey, *pubkey; + + if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey) + || (key != NULL + && X25519(key, privkey, pubkey) == 0)) + return 0; + *keylen = X25519_KEYLEN; + return 1; +} + +static int pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key, + size_t *keylen) +{ + const unsigned char *privkey, *pubkey; + + if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey) + || (key != NULL + && X448(key, privkey, pubkey) == 0)) + return 0; + *keylen = X448_KEYLEN; + return 1; +} + +static int pkey_ecx_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) +{ + /* Only need to handle peer key for derivation */ + if (type == EVP_PKEY_CTRL_PEER_KEY) + return 1; + return -2; +} + +const EVP_PKEY_METHOD ecx25519_pkey_meth = { + EVP_PKEY_X25519, + 0, 0, 0, 0, 0, 0, 0, + pkey_ecx_keygen, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + pkey_ecx_derive25519, + pkey_ecx_ctrl, + 0 +}; + +const EVP_PKEY_METHOD ecx448_pkey_meth = { + EVP_PKEY_X448, + 0, 0, 0, 0, 0, 0, 0, + pkey_ecx_keygen, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + pkey_ecx_derive448, + pkey_ecx_ctrl, + 0 +}; + +static int pkey_ecd_digestsign25519(EVP_MD_CTX *ctx, unsigned char *sig, + size_t *siglen, const unsigned char *tbs, + size_t tbslen) +{ + const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx; + + if (sig == NULL) { + *siglen = ED25519_SIGSIZE; + return 1; + } + if (*siglen < ED25519_SIGSIZE) { + ECerr(EC_F_PKEY_ECD_DIGESTSIGN25519, EC_R_BUFFER_TOO_SMALL); + return 0; + } + + if (ED25519_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey) == 0) + return 0; + *siglen = ED25519_SIGSIZE; + return 1; +} + +static int pkey_ecd_digestsign448(EVP_MD_CTX *ctx, unsigned char *sig, + size_t *siglen, const unsigned char *tbs, + size_t tbslen) +{ + const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx; + + if (sig == NULL) { + *siglen = ED448_SIGSIZE; + return 1; + } + if (*siglen < ED448_SIGSIZE) { + ECerr(EC_F_PKEY_ECD_DIGESTSIGN448, EC_R_BUFFER_TOO_SMALL); + return 0; + } + + if (ED448_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey, NULL, + 0) == 0) + return 0; + *siglen = ED448_SIGSIZE; + return 1; +} + +static int pkey_ecd_digestverify25519(EVP_MD_CTX *ctx, const unsigned char *sig, + size_t siglen, const unsigned char *tbs, + size_t tbslen) +{ + const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx; + + if (siglen != ED25519_SIGSIZE) + return 0; + + return ED25519_verify(tbs, tbslen, sig, edkey->pubkey); +} + +static int pkey_ecd_digestverify448(EVP_MD_CTX *ctx, const unsigned char *sig, + size_t siglen, const unsigned char *tbs, + size_t tbslen) +{ + const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx; + + if (siglen != ED448_SIGSIZE) + return 0; + + return ED448_verify(tbs, tbslen, sig, edkey->pubkey, NULL, 0); +} + +static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) +{ + switch (type) { + case EVP_PKEY_CTRL_MD: + /* Only NULL allowed as digest */ + if (p2 == NULL || (const EVP_MD *)p2 == EVP_md_null()) + return 1; + ECerr(EC_F_PKEY_ECD_CTRL, EC_R_INVALID_DIGEST_TYPE); + return 0; + + case EVP_PKEY_CTRL_DIGESTINIT: + return 1; + } + return -2; +} + +const EVP_PKEY_METHOD ed25519_pkey_meth = { + EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM, + 0, 0, 0, 0, 0, 0, + pkey_ecx_keygen, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + pkey_ecd_ctrl, + 0, + pkey_ecd_digestsign25519, + pkey_ecd_digestverify25519 +}; + +const EVP_PKEY_METHOD ed448_pkey_meth = { + EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM, + 0, 0, 0, 0, 0, 0, + pkey_ecx_keygen, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + pkey_ecd_ctrl, + 0, + pkey_ecd_digestsign448, + pkey_ecd_digestverify448 +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/engine/README b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/README new file mode 100644 index 000000000..c7a5696ca --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/README @@ -0,0 +1,211 @@ +Notes: 2001-09-24 +----------------- + +This "description" (if one chooses to call it that) needed some major updating +so here goes. This update addresses a change being made at the same time to +OpenSSL, and it pretty much completely restructures the underlying mechanics of +the "ENGINE" code. So it serves a double purpose of being a "ENGINE internals +for masochists" document *and* a rather extensive commit log message. (I'd get +lynched for sticking all this in CHANGES or the commit mails :-). + +ENGINE_TABLE underlies this restructuring, as described in the internal header +"eng_int.h", implemented in eng_table.c, and used in each of the "class" files; +tb_rsa.c, tb_dsa.c, etc. + +However, "EVP_CIPHER" underlies the motivation and design of ENGINE_TABLE so +I'll mention a bit about that first. EVP_CIPHER (and most of this applies +equally to EVP_MD for digests) is both a "method" and a algorithm/mode +identifier that, in the current API, "lingers". These cipher description + +implementation structures can be defined or obtained directly by applications, +or can be loaded "en masse" into EVP storage so that they can be catalogued and +searched in various ways, ie. two ways of encrypting with the "des_cbc" +algorithm/mode pair are; + +(i) directly; + const EVP_CIPHER *cipher = EVP_des_cbc(); + EVP_EncryptInit(&ctx, cipher, key, iv); + [ ... use EVP_EncryptUpdate() and EVP_EncryptFinal() ...] + +(ii) indirectly; + OpenSSL_add_all_ciphers(); + cipher = EVP_get_cipherbyname("des_cbc"); + EVP_EncryptInit(&ctx, cipher, key, iv); + [ ... etc ... ] + +The latter is more generally used because it also allows ciphers/digests to be +looked up based on other identifiers which can be useful for automatic cipher +selection, eg. in SSL/TLS, or by user-controllable configuration. + +The important point about this is that EVP_CIPHER definitions and structures are +passed around with impunity and there is no safe way, without requiring massive +rewrites of many applications, to assume that EVP_CIPHERs can be reference +counted. One an EVP_CIPHER is exposed to the caller, neither it nor anything it +comes from can "safely" be destroyed. Unless of course the way of getting to +such ciphers is via entirely distinct API calls that didn't exist before. +However existing API usage cannot be made to understand when an EVP_CIPHER +pointer, that has been passed to the caller, is no longer being used. + +The other problem with the existing API w.r.t. to hooking EVP_CIPHER support +into ENGINE is storage - the OBJ_NAME-based storage used by EVP to register +ciphers simultaneously registers cipher *types* and cipher *implementations* - +they are effectively the same thing, an "EVP_CIPHER" pointer. The problem with +hooking in ENGINEs is that multiple ENGINEs may implement the same ciphers. The +solution is necessarily that ENGINE-provided ciphers simply are not registered, +stored, or exposed to the caller in the same manner as existing ciphers. This is +especially necessary considering the fact ENGINE uses reference counts to allow +for cleanup, modularity, and DSO support - yet EVP_CIPHERs, as exposed to +callers in the current API, support no such controls. + +Another sticking point for integrating cipher support into ENGINE is linkage. +Already there is a problem with the way ENGINE supports RSA, DSA, etc whereby +they are available *because* they're part of a giant ENGINE called "openssl". +Ie. all implementations *have* to come from an ENGINE, but we get round that by +having a giant ENGINE with all the software support encapsulated. This creates +linker hassles if nothing else - linking a 1-line application that calls 2 basic +RSA functions (eg. "RSA_free(RSA_new());") will result in large quantities of +ENGINE code being linked in *and* because of that DSA, DH, and RAND also. If we +continue with this approach for EVP_CIPHER support (even if it *was* possible) +we would lose our ability to link selectively by selectively loading certain +implementations of certain functionality. Touching any part of any kind of +crypto would result in massive static linkage of everything else. So the +solution is to change the way ENGINE feeds existing "classes", ie. how the +hooking to ENGINE works from RSA, DSA, DH, RAND, as well as adding new hooking +for EVP_CIPHER, and EVP_MD. + +The way this is now being done is by mostly reverting back to how things used to +work prior to ENGINE :-). Ie. RSA now has a "RSA_METHOD" pointer again - this +was previously replaced by an "ENGINE" pointer and all RSA code that required +the RSA_METHOD would call ENGINE_get_RSA() each time on its ENGINE handle to +temporarily get and use the ENGINE's RSA implementation. Apart from being more +efficient, switching back to each RSA having an RSA_METHOD pointer also allows +us to conceivably operate with *no* ENGINE. As we'll see, this removes any need +for a fallback ENGINE that encapsulates default implementations - we can simply +have our RSA structure pointing its RSA_METHOD pointer to the software +implementation and have its ENGINE pointer set to NULL. + +A look at the EVP_CIPHER hooking is most explanatory, the RSA, DSA (etc) cases +turn out to be degenerate forms of the same thing. The EVP storage of ciphers, +and the existing EVP API functions that return "software" implementations and +descriptions remain untouched. However, the storage takes more meaning in terms +of "cipher description" and less meaning in terms of "implementation". When an +EVP_CIPHER_CTX is actually initialised with an EVP_CIPHER method and is about to +begin en/decryption, the hooking to ENGINE comes into play. What happens is that +cipher-specific ENGINE code is asked for an ENGINE pointer (a functional +reference) for any ENGINE that is registered to perform the algo/mode that the +provided EVP_CIPHER structure represents. Under normal circumstances, that +ENGINE code will return NULL because no ENGINEs will have had any cipher +implementations *registered*. As such, a NULL ENGINE pointer is stored in the +EVP_CIPHER_CTX context, and the EVP_CIPHER structure is left hooked into the +context and so is used as the implementation. Pretty much how things work now +except we'd have a redundant ENGINE pointer set to NULL and doing nothing. + +Conversely, if an ENGINE *has* been registered to perform the algorithm/mode +combination represented by the provided EVP_CIPHER, then a functional reference +to that ENGINE will be returned to the EVP_CIPHER_CTX during initialisation. +That functional reference will be stored in the context (and released on +cleanup) - and having that reference provides a *safe* way to use an EVP_CIPHER +definition that is private to the ENGINE. Ie. the EVP_CIPHER provided by the +application will actually be replaced by an EVP_CIPHER from the registered +ENGINE - it will support the same algorithm/mode as the original but will be a +completely different implementation. Because this EVP_CIPHER isn't stored in the +EVP storage, nor is it returned to applications from traditional API functions, +there is no associated problem with it not having reference counts. And of +course, when one of these "private" cipher implementations is hooked into +EVP_CIPHER_CTX, it is done whilst the EVP_CIPHER_CTX holds a functional +reference to the ENGINE that owns it, thus the use of the ENGINE's EVP_CIPHER is +safe. + +The "cipher-specific ENGINE code" I mentioned is implemented in tb_cipher.c but +in essence it is simply an instantiation of "ENGINE_TABLE" code for use by +EVP_CIPHER code. tb_digest.c is virtually identical but, of course, it is for +use by EVP_MD code. Ditto for tb_rsa.c, tb_dsa.c, etc. These instantiations of +ENGINE_TABLE essentially provide linker-separation of the classes so that even +if ENGINEs implement *all* possible algorithms, an application using only +EVP_CIPHER code will link at most code relating to EVP_CIPHER, tb_cipher.c, core +ENGINE code that is independent of class, and of course the ENGINE +implementation that the application loaded. It will *not* however link any +class-specific ENGINE code for digests, RSA, etc nor will it bleed over into +other APIs, such as the RSA/DSA/etc library code. + +ENGINE_TABLE is a little more complicated than may seem necessary but this is +mostly to avoid a lot of "init()"-thrashing on ENGINEs (that may have to load +DSOs, and other expensive setup that shouldn't be thrashed unnecessarily) *and* +to duplicate "default" behaviour. Basically an ENGINE_TABLE instantiation, for +example tb_cipher.c, implements a hash-table keyed by integer "nid" values. +These nids provide the uniquenness of an algorithm/mode - and each nid will hash +to a potentially NULL "ENGINE_PILE". An ENGINE_PILE is essentially a list of +pointers to ENGINEs that implement that particular 'nid'. Each "pile" uses some +caching tricks such that requests on that 'nid' will be cached and all future +requests will return immediately (well, at least with minimal operation) unless +a change is made to the pile, eg. perhaps an ENGINE was unloaded. The reason is +that an application could have support for 10 ENGINEs statically linked +in, and the machine in question may not have any of the hardware those 10 +ENGINEs support. If each of those ENGINEs has a "des_cbc" implementation, we +want to avoid every EVP_CIPHER_CTX setup from trying (and failing) to initialise +each of those 10 ENGINEs. Instead, the first such request will try to do that +and will either return (and cache) a NULL ENGINE pointer or will return a +functional reference to the first that successfully initialised. In the latter +case it will also cache an extra functional reference to the ENGINE as a +"default" for that 'nid'. The caching is acknowledged by a 'uptodate' variable +that is unset only if un/registration takes place on that pile. Ie. if +implementations of "des_cbc" are added or removed. This behaviour can be +tweaked; the ENGINE_TABLE_FLAG_NOINIT value can be passed to +ENGINE_set_table_flags(), in which case the only ENGINEs that tb_cipher.c will +try to initialise from the "pile" will be those that are already initialised +(ie. it's simply an increment of the functional reference count, and no real +"initialisation" will take place). + +RSA, DSA, DH, and RAND all have their own ENGINE_TABLE code as well, and the +difference is that they all use an implicit 'nid' of 1. Whereas EVP_CIPHERs are +actually qualitatively different depending on 'nid' (the "des_cbc" EVP_CIPHER is +not an interoperable implementation of "aes_256_cbc"), RSA_METHODs are +necessarily interoperable and don't have different flavours, only different +implementations. In other words, the ENGINE_TABLE for RSA will either be empty, +or will have a single ENGINE_PILE hashed to by the 'nid' 1 and that pile +represents ENGINEs that implement the single "type" of RSA there is. + +Cleanup - the registration and unregistration may pose questions about how +cleanup works with the ENGINE_PILE doing all this caching nonsense (ie. when the +application or EVP_CIPHER code releases its last reference to an ENGINE, the +ENGINE_PILE code may still have references and thus those ENGINEs will stay +hooked in forever). The way this is handled is via "unregistration". With these +new ENGINE changes, an abstract ENGINE can be loaded and initialised, but that +is an algorithm-agnostic process. Even if initialised, it will not have +registered any of its implementations (to do so would link all class "table" +code despite the fact the application may use only ciphers, for example). This +is deliberately a distinct step. Moreover, registration and unregistration has +nothing to do with whether an ENGINE is *functional* or not (ie. you can even +register an ENGINE and its implementations without it being operational, you may +not even have the drivers to make it operate). What actually happens with +respect to cleanup is managed inside eng_lib.c with the "engine_cleanup_***" +functions. These functions are internal-only and each part of ENGINE code that +could require cleanup will, upon performing its first allocation, register a +callback with the "engine_cleanup" code. The other part of this that makes it +tick is that the ENGINE_TABLE instantiations (tb_***.c) use NULL as their +initialised state. So if RSA code asks for an ENGINE and no ENGINE has +registered an implementation, the code will simply return NULL and the tb_rsa.c +state will be unchanged. Thus, no cleanup is required unless registration takes +place. ENGINE_cleanup() will simply iterate across a list of registered cleanup +callbacks calling each in turn, and will then internally delete its own storage +(a STACK). When a cleanup callback is next registered (eg. if the cleanup() is +part of a graceful restart and the application wants to cleanup all state then +start again), the internal STACK storage will be freshly allocated. This is much +the same as the situation in the ENGINE_TABLE instantiations ... NULL is the +initialised state, so only modification operations (not queries) will cause that +code to have to register a cleanup. + +What else? The bignum callbacks and associated ENGINE functions have been +removed for two obvious reasons; (i) there was no way to generalise them to the +mechanism now used by RSA/DSA/..., because there's no such thing as a BIGNUM +method, and (ii) because of (i), there was no meaningful way for library or +application code to automatically hook and use ENGINE supplied bignum functions +anyway. Also, ENGINE_cpy() has been removed (although an internal-only version +exists) - the idea of providing an ENGINE_cpy() function probably wasn't a good +one and now certainly doesn't make sense in any generalised way. Some of the +RSA, DSA, DH, and RAND functions that were fiddled during the original ENGINE +changes have now, as a consequence, been reverted back. This is because the +hooking of ENGINE is now automatic (and passive, it can internally use a NULL +ENGINE pointer to simply ignore ENGINE from then on). + +Hell, that should be enough for now ... comments welcome. + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/engine/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/build.info new file mode 100644 index 000000000..e00802a3f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/build.info @@ -0,0 +1,11 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + eng_err.c eng_lib.c eng_list.c eng_init.c eng_ctrl.c \ + eng_table.c eng_pkey.c eng_fat.c eng_all.c \ + tb_rsa.c tb_dsa.c tb_dh.c tb_rand.c \ + tb_cipher.c tb_digest.c tb_pkmeth.c tb_asnmth.c tb_eckey.c \ + eng_openssl.c eng_cnf.c eng_dyn.c \ + eng_rdrand.c +IF[{- !$disabled{devcryptoeng} -}] + SOURCE[../../libcrypto]=eng_devcrypto.c +ENDIF diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_all.c b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_all.c new file mode 100644 index 000000000..af306ccff --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_all.c @@ -0,0 +1,25 @@ +/* + * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include "eng_int.h" + +void ENGINE_load_builtin_engines(void) +{ + /* Some ENGINEs need this */ + OPENSSL_cpuid_setup(); + + OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_ALL_BUILTIN, NULL); +} + +#if (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)) && OPENSSL_API_COMPAT < 0x10100000L +void ENGINE_setup_bsd_cryptodev(void) +{ +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_cnf.c b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_cnf.c new file mode 100644 index 000000000..6f0a066d0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_cnf.c @@ -0,0 +1,192 @@ +/* + * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "eng_int.h" +#include + +/* #define ENGINE_CONF_DEBUG */ + +/* ENGINE config module */ + +static const char *skip_dot(const char *name) +{ + const char *p = strchr(name, '.'); + + if (p != NULL) + return p + 1; + return name; +} + +static STACK_OF(ENGINE) *initialized_engines = NULL; + +static int int_engine_init(ENGINE *e) +{ + if (!ENGINE_init(e)) + return 0; + if (!initialized_engines) + initialized_engines = sk_ENGINE_new_null(); + if (!initialized_engines || !sk_ENGINE_push(initialized_engines, e)) { + ENGINE_finish(e); + return 0; + } + return 1; +} + +static int int_engine_configure(const char *name, const char *value, const CONF *cnf) +{ + int i; + int ret = 0; + long do_init = -1; + STACK_OF(CONF_VALUE) *ecmds; + CONF_VALUE *ecmd = NULL; + const char *ctrlname, *ctrlvalue; + ENGINE *e = NULL; + int soft = 0; + + name = skip_dot(name); +#ifdef ENGINE_CONF_DEBUG + fprintf(stderr, "Configuring engine %s\n", name); +#endif + /* Value is a section containing ENGINE commands */ + ecmds = NCONF_get_section(cnf, value); + + if (!ecmds) { + ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE, + ENGINE_R_ENGINE_SECTION_ERROR); + return 0; + } + + for (i = 0; i < sk_CONF_VALUE_num(ecmds); i++) { + ecmd = sk_CONF_VALUE_value(ecmds, i); + ctrlname = skip_dot(ecmd->name); + ctrlvalue = ecmd->value; +#ifdef ENGINE_CONF_DEBUG + fprintf(stderr, "ENGINE conf: doing ctrl(%s,%s)\n", ctrlname, + ctrlvalue); +#endif + + /* First handle some special pseudo ctrls */ + + /* Override engine name to use */ + if (strcmp(ctrlname, "engine_id") == 0) + name = ctrlvalue; + else if (strcmp(ctrlname, "soft_load") == 0) + soft = 1; + /* Load a dynamic ENGINE */ + else if (strcmp(ctrlname, "dynamic_path") == 0) { + e = ENGINE_by_id("dynamic"); + if (!e) + goto err; + if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", ctrlvalue, 0)) + goto err; + if (!ENGINE_ctrl_cmd_string(e, "LIST_ADD", "2", 0)) + goto err; + if (!ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) + goto err; + } + /* ... add other pseudos here ... */ + else { + /* + * At this point we need an ENGINE structural reference if we + * don't already have one. + */ + if (!e) { + e = ENGINE_by_id(name); + if (!e && soft) { + ERR_clear_error(); + return 1; + } + if (!e) + goto err; + } + /* + * Allow "EMPTY" to mean no value: this allows a valid "value" to + * be passed to ctrls of type NO_INPUT + */ + if (strcmp(ctrlvalue, "EMPTY") == 0) + ctrlvalue = NULL; + if (strcmp(ctrlname, "init") == 0) { + if (!NCONF_get_number_e(cnf, value, "init", &do_init)) + goto err; + if (do_init == 1) { + if (!int_engine_init(e)) + goto err; + } else if (do_init != 0) { + ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE, + ENGINE_R_INVALID_INIT_VALUE); + goto err; + } + } else if (strcmp(ctrlname, "default_algorithms") == 0) { + if (!ENGINE_set_default_string(e, ctrlvalue)) + goto err; + } else if (!ENGINE_ctrl_cmd_string(e, ctrlname, ctrlvalue, 0)) + goto err; + } + + } + if (e && (do_init == -1) && !int_engine_init(e)) { + ecmd = NULL; + goto err; + } + ret = 1; + err: + if (ret != 1) { + ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE, + ENGINE_R_ENGINE_CONFIGURATION_ERROR); + if (ecmd) + ERR_add_error_data(6, "section=", ecmd->section, + ", name=", ecmd->name, + ", value=", ecmd->value); + } + ENGINE_free(e); + return ret; +} + +static int int_engine_module_init(CONF_IMODULE *md, const CONF *cnf) +{ + STACK_OF(CONF_VALUE) *elist; + CONF_VALUE *cval; + int i; +#ifdef ENGINE_CONF_DEBUG + fprintf(stderr, "Called engine module: name %s, value %s\n", + CONF_imodule_get_name(md), CONF_imodule_get_value(md)); +#endif + /* Value is a section containing ENGINEs to configure */ + elist = NCONF_get_section(cnf, CONF_imodule_get_value(md)); + + if (!elist) { + ENGINEerr(ENGINE_F_INT_ENGINE_MODULE_INIT, + ENGINE_R_ENGINES_SECTION_ERROR); + return 0; + } + + for (i = 0; i < sk_CONF_VALUE_num(elist); i++) { + cval = sk_CONF_VALUE_value(elist, i); + if (!int_engine_configure(cval->name, cval->value, cnf)) + return 0; + } + + return 1; +} + +static void int_engine_module_finish(CONF_IMODULE *md) +{ + ENGINE *e; + + while ((e = sk_ENGINE_pop(initialized_engines))) + ENGINE_finish(e); + sk_ENGINE_free(initialized_engines); + initialized_engines = NULL; +} + +void ENGINE_add_conf_module(void) +{ + CONF_module_add("engines", + int_engine_module_init, int_engine_module_finish); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_ctrl.c b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_ctrl.c new file mode 100644 index 000000000..3bc4aab16 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_ctrl.c @@ -0,0 +1,330 @@ +/* + * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "eng_int.h" + +/* + * When querying a ENGINE-specific control command's 'description', this + * string is used if the ENGINE_CMD_DEFN has cmd_desc set to NULL. + */ +static const char *int_no_description = ""; + +/* + * These internal functions handle 'CMD'-related control commands when the + * ENGINE in question has asked us to take care of it (ie. the ENGINE did not + * set the ENGINE_FLAGS_MANUAL_CMD_CTRL flag. + */ + +static int int_ctrl_cmd_is_null(const ENGINE_CMD_DEFN *defn) +{ + if ((defn->cmd_num == 0) || (defn->cmd_name == NULL)) + return 1; + return 0; +} + +static int int_ctrl_cmd_by_name(const ENGINE_CMD_DEFN *defn, const char *s) +{ + int idx = 0; + while (!int_ctrl_cmd_is_null(defn) && (strcmp(defn->cmd_name, s) != 0)) { + idx++; + defn++; + } + if (int_ctrl_cmd_is_null(defn)) + /* The given name wasn't found */ + return -1; + return idx; +} + +static int int_ctrl_cmd_by_num(const ENGINE_CMD_DEFN *defn, unsigned int num) +{ + int idx = 0; + /* + * NB: It is stipulated that 'cmd_defn' lists are ordered by cmd_num. So + * our searches don't need to take any longer than necessary. + */ + while (!int_ctrl_cmd_is_null(defn) && (defn->cmd_num < num)) { + idx++; + defn++; + } + if (defn->cmd_num == num) + return idx; + /* The given cmd_num wasn't found */ + return -1; +} + +static int int_ctrl_helper(ENGINE *e, int cmd, long i, void *p, + void (*f) (void)) +{ + int idx; + char *s = (char *)p; + const ENGINE_CMD_DEFN *cdp; + + /* Take care of the easy one first (eg. it requires no searches) */ + if (cmd == ENGINE_CTRL_GET_FIRST_CMD_TYPE) { + if ((e->cmd_defns == NULL) || int_ctrl_cmd_is_null(e->cmd_defns)) + return 0; + return e->cmd_defns->cmd_num; + } + /* One or two commands require that "p" be a valid string buffer */ + if ((cmd == ENGINE_CTRL_GET_CMD_FROM_NAME) || + (cmd == ENGINE_CTRL_GET_NAME_FROM_CMD) || + (cmd == ENGINE_CTRL_GET_DESC_FROM_CMD)) { + if (s == NULL) { + ENGINEerr(ENGINE_F_INT_CTRL_HELPER, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + } + /* Now handle cmd_name -> cmd_num conversion */ + if (cmd == ENGINE_CTRL_GET_CMD_FROM_NAME) { + if ((e->cmd_defns == NULL) + || ((idx = int_ctrl_cmd_by_name(e->cmd_defns, s)) < 0)) { + ENGINEerr(ENGINE_F_INT_CTRL_HELPER, ENGINE_R_INVALID_CMD_NAME); + return -1; + } + return e->cmd_defns[idx].cmd_num; + } + /* + * For the rest of the commands, the 'long' argument must specify a valid + * command number - so we need to conduct a search. + */ + if ((e->cmd_defns == NULL) + || ((idx = int_ctrl_cmd_by_num(e->cmd_defns, (unsigned int)i)) < 0)) { + ENGINEerr(ENGINE_F_INT_CTRL_HELPER, ENGINE_R_INVALID_CMD_NUMBER); + return -1; + } + /* Now the logic splits depending on command type */ + cdp = &e->cmd_defns[idx]; + switch (cmd) { + case ENGINE_CTRL_GET_NEXT_CMD_TYPE: + cdp++; + return int_ctrl_cmd_is_null(cdp) ? 0 : cdp->cmd_num; + case ENGINE_CTRL_GET_NAME_LEN_FROM_CMD: + return strlen(cdp->cmd_name); + case ENGINE_CTRL_GET_NAME_FROM_CMD: + return strlen(strcpy(s, cdp->cmd_name)); + case ENGINE_CTRL_GET_DESC_LEN_FROM_CMD: + return strlen(cdp->cmd_desc == NULL ? int_no_description + : cdp->cmd_desc); + case ENGINE_CTRL_GET_DESC_FROM_CMD: + return strlen(strcpy(s, cdp->cmd_desc == NULL ? int_no_description + : cdp->cmd_desc)); + case ENGINE_CTRL_GET_CMD_FLAGS: + return cdp->cmd_flags; + } + /* Shouldn't really be here ... */ + ENGINEerr(ENGINE_F_INT_CTRL_HELPER, ENGINE_R_INTERNAL_LIST_ERROR); + return -1; +} + +int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)) +{ + int ctrl_exists, ref_exists; + if (e == NULL) { + ENGINEerr(ENGINE_F_ENGINE_CTRL, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + CRYPTO_THREAD_write_lock(global_engine_lock); + ref_exists = ((e->struct_ref > 0) ? 1 : 0); + CRYPTO_THREAD_unlock(global_engine_lock); + ctrl_exists = ((e->ctrl == NULL) ? 0 : 1); + if (!ref_exists) { + ENGINEerr(ENGINE_F_ENGINE_CTRL, ENGINE_R_NO_REFERENCE); + return 0; + } + /* + * Intercept any "root-level" commands before trying to hand them on to + * ctrl() handlers. + */ + switch (cmd) { + case ENGINE_CTRL_HAS_CTRL_FUNCTION: + return ctrl_exists; + case ENGINE_CTRL_GET_FIRST_CMD_TYPE: + case ENGINE_CTRL_GET_NEXT_CMD_TYPE: + case ENGINE_CTRL_GET_CMD_FROM_NAME: + case ENGINE_CTRL_GET_NAME_LEN_FROM_CMD: + case ENGINE_CTRL_GET_NAME_FROM_CMD: + case ENGINE_CTRL_GET_DESC_LEN_FROM_CMD: + case ENGINE_CTRL_GET_DESC_FROM_CMD: + case ENGINE_CTRL_GET_CMD_FLAGS: + if (ctrl_exists && !(e->flags & ENGINE_FLAGS_MANUAL_CMD_CTRL)) + return int_ctrl_helper(e, cmd, i, p, f); + if (!ctrl_exists) { + ENGINEerr(ENGINE_F_ENGINE_CTRL, ENGINE_R_NO_CONTROL_FUNCTION); + /* + * For these cmd-related functions, failure is indicated by a -1 + * return value (because 0 is used as a valid return in some + * places). + */ + return -1; + } + default: + break; + } + /* Anything else requires a ctrl() handler to exist. */ + if (!ctrl_exists) { + ENGINEerr(ENGINE_F_ENGINE_CTRL, ENGINE_R_NO_CONTROL_FUNCTION); + return 0; + } + return e->ctrl(e, cmd, i, p, f); +} + +int ENGINE_cmd_is_executable(ENGINE *e, int cmd) +{ + int flags; + if ((flags = + ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, cmd, NULL, NULL)) < 0) { + ENGINEerr(ENGINE_F_ENGINE_CMD_IS_EXECUTABLE, + ENGINE_R_INVALID_CMD_NUMBER); + return 0; + } + if (!(flags & ENGINE_CMD_FLAG_NO_INPUT) && + !(flags & ENGINE_CMD_FLAG_NUMERIC) && + !(flags & ENGINE_CMD_FLAG_STRING)) + return 0; + return 1; +} + +int ENGINE_ctrl_cmd(ENGINE *e, const char *cmd_name, + long i, void *p, void (*f) (void), int cmd_optional) +{ + int num; + + if (e == NULL || cmd_name == NULL) { + ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (e->ctrl == NULL + || (num = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FROM_NAME, + 0, (void *)cmd_name, NULL)) <= 0) { + /* + * If the command didn't *have* to be supported, we fake success. + * This allows certain settings to be specified for multiple ENGINEs + * and only require a change of ENGINE id (without having to + * selectively apply settings). Eg. changing from a hardware device + * back to the regular software ENGINE without editing the config + * file, etc. + */ + if (cmd_optional) { + ERR_clear_error(); + return 1; + } + ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD, ENGINE_R_INVALID_CMD_NAME); + return 0; + } + /* + * Force the result of the control command to 0 or 1, for the reasons + * mentioned before. + */ + if (ENGINE_ctrl(e, num, i, p, f) > 0) + return 1; + return 0; +} + +int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg, + int cmd_optional) +{ + int num, flags; + long l; + char *ptr; + + if (e == NULL || cmd_name == NULL) { + ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (e->ctrl == NULL + || (num = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FROM_NAME, + 0, (void *)cmd_name, NULL)) <= 0) { + /* + * If the command didn't *have* to be supported, we fake success. + * This allows certain settings to be specified for multiple ENGINEs + * and only require a change of ENGINE id (without having to + * selectively apply settings). Eg. changing from a hardware device + * back to the regular software ENGINE without editing the config + * file, etc. + */ + if (cmd_optional) { + ERR_clear_error(); + return 1; + } + ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, ENGINE_R_INVALID_CMD_NAME); + return 0; + } + if (!ENGINE_cmd_is_executable(e, num)) { + ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, + ENGINE_R_CMD_NOT_EXECUTABLE); + return 0; + } + + flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, num, NULL, NULL); + if (flags < 0) { + /* + * Shouldn't happen, given that ENGINE_cmd_is_executable() returned + * success. + */ + ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, + ENGINE_R_INTERNAL_LIST_ERROR); + return 0; + } + /* + * If the command takes no input, there must be no input. And vice versa. + */ + if (flags & ENGINE_CMD_FLAG_NO_INPUT) { + if (arg != NULL) { + ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, + ENGINE_R_COMMAND_TAKES_NO_INPUT); + return 0; + } + /* + * We deliberately force the result of ENGINE_ctrl() to 0 or 1 rather + * than returning it as "return data". This is to ensure usage of + * these commands is consistent across applications and that certain + * applications don't understand it one way, and others another. + */ + if (ENGINE_ctrl(e, num, 0, (void *)arg, NULL) > 0) + return 1; + return 0; + } + /* So, we require input */ + if (arg == NULL) { + ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, + ENGINE_R_COMMAND_TAKES_INPUT); + return 0; + } + /* If it takes string input, that's easy */ + if (flags & ENGINE_CMD_FLAG_STRING) { + /* Same explanation as above */ + if (ENGINE_ctrl(e, num, 0, (void *)arg, NULL) > 0) + return 1; + return 0; + } + /* + * If it doesn't take numeric either, then it is unsupported for use in a + * config-setting situation, which is what this function is for. This + * should never happen though, because ENGINE_cmd_is_executable() was + * used. + */ + if (!(flags & ENGINE_CMD_FLAG_NUMERIC)) { + ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, + ENGINE_R_INTERNAL_LIST_ERROR); + return 0; + } + l = strtol(arg, &ptr, 10); + if ((arg == ptr) || (*ptr != '\0')) { + ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, + ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER); + return 0; + } + /* + * Force the result of the control command to 0 or 1, for the reasons + * mentioned before. + */ + if (ENGINE_ctrl(e, num, l, NULL, NULL) > 0) + return 1; + return 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_devcrypto.c b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_devcrypto.c new file mode 100644 index 000000000..717d7c277 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_devcrypto.c @@ -0,0 +1,836 @@ +/* + * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "e_os.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "internal/engine.h" + +/* #define ENGINE_DEVCRYPTO_DEBUG */ + +#ifdef CRYPTO_ALGORITHM_MIN +# define CHECK_BSD_STYLE_MACROS +#endif + +/* + * ONE global file descriptor for all sessions. This allows operations + * such as digest session data copying (see digest_copy()), but is also + * saner... why re-open /dev/crypto for every session? + */ +static int cfd; + +static int clean_devcrypto_session(struct session_op *sess) { + if (ioctl(cfd, CIOCFSESSION, &sess->ses) < 0) { + SYSerr(SYS_F_IOCTL, errno); + return 0; + } + memset(sess, 0, sizeof(struct session_op)); + return 1; +} + +/****************************************************************************** + * + * Ciphers + * + * Because they all do the same basic operation, we have only one set of + * method functions for them all to share, and a mapping table between + * NIDs and cryptodev IDs, with all the necessary size data. + * + *****/ + +struct cipher_ctx { + struct session_op sess; + int op; /* COP_ENCRYPT or COP_DECRYPT */ + unsigned long mode; /* EVP_CIPH_*_MODE */ + + /* to handle ctr mode being a stream cipher */ + unsigned char partial[EVP_MAX_BLOCK_LENGTH]; + unsigned int blocksize, num; +}; + +static const struct cipher_data_st { + int nid; + int blocksize; + int keylen; + int ivlen; + int flags; + int devcryptoid; +} cipher_data[] = { +#ifndef OPENSSL_NO_DES + { NID_des_cbc, 8, 8, 8, EVP_CIPH_CBC_MODE, CRYPTO_DES_CBC }, + { NID_des_ede3_cbc, 8, 24, 8, EVP_CIPH_CBC_MODE, CRYPTO_3DES_CBC }, +#endif +#ifndef OPENSSL_NO_BF + { NID_bf_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_BLF_CBC }, +#endif +#ifndef OPENSSL_NO_CAST + { NID_cast5_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_CAST_CBC }, +#endif + { NID_aes_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC }, + { NID_aes_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC }, + { NID_aes_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC }, +#ifndef OPENSSL_NO_RC4 + { NID_rc4, 1, 16, 0, EVP_CIPH_STREAM_CIPHER, CRYPTO_ARC4 }, +#endif +#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_CTR) + { NID_aes_128_ctr, 16, 128 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR }, + { NID_aes_192_ctr, 16, 192 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR }, + { NID_aes_256_ctr, 16, 256 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR }, +#endif +#if 0 /* Not yet supported */ + { NID_aes_128_xts, 16, 128 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS }, + { NID_aes_256_xts, 16, 256 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS }, +#endif +#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_ECB) + { NID_aes_128_ecb, 16, 128 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB }, + { NID_aes_192_ecb, 16, 192 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB }, + { NID_aes_256_ecb, 16, 256 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB }, +#endif +#if 0 /* Not yet supported */ + { NID_aes_128_gcm, 16, 128 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM }, + { NID_aes_192_gcm, 16, 192 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM }, + { NID_aes_256_gcm, 16, 256 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM }, +#endif +#ifndef OPENSSL_NO_CAMELLIA + { NID_camellia_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE, + CRYPTO_CAMELLIA_CBC }, + { NID_camellia_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE, + CRYPTO_CAMELLIA_CBC }, + { NID_camellia_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE, + CRYPTO_CAMELLIA_CBC }, +#endif +}; + +static size_t get_cipher_data_index(int nid) +{ + size_t i; + + for (i = 0; i < OSSL_NELEM(cipher_data); i++) + if (nid == cipher_data[i].nid) + return i; + + /* + * Code further down must make sure that only NIDs in the table above + * are used. If any other NID reaches this function, there's a grave + * coding error further down. + */ + assert("Code that never should be reached" == NULL); + return -1; +} + +static const struct cipher_data_st *get_cipher_data(int nid) +{ + return &cipher_data[get_cipher_data_index(nid)]; +} + +/* + * Following are the three necessary functions to map OpenSSL functionality + * with cryptodev. + */ + +static int cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + struct cipher_ctx *cipher_ctx = + (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); + const struct cipher_data_st *cipher_d = + get_cipher_data(EVP_CIPHER_CTX_nid(ctx)); + + /* cleanup a previous session */ + if (cipher_ctx->sess.ses != 0 && + clean_devcrypto_session(&cipher_ctx->sess) == 0) + return 0; + + cipher_ctx->sess.cipher = cipher_d->devcryptoid; + cipher_ctx->sess.keylen = cipher_d->keylen; + cipher_ctx->sess.key = (void *)key; + cipher_ctx->op = enc ? COP_ENCRYPT : COP_DECRYPT; + cipher_ctx->mode = cipher_d->flags & EVP_CIPH_MODE; + cipher_ctx->blocksize = cipher_d->blocksize; + if (ioctl(cfd, CIOCGSESSION, &cipher_ctx->sess) < 0) { + SYSerr(SYS_F_IOCTL, errno); + return 0; + } + + return 1; +} + +static int cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + struct cipher_ctx *cipher_ctx = + (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); + struct crypt_op cryp; + unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx); +#if !defined(COP_FLAG_WRITE_IV) + unsigned char saved_iv[EVP_MAX_IV_LENGTH]; + const unsigned char *ivptr; + size_t nblocks, ivlen; +#endif + + memset(&cryp, 0, sizeof(cryp)); + cryp.ses = cipher_ctx->sess.ses; + cryp.len = inl; + cryp.src = (void *)in; + cryp.dst = (void *)out; + cryp.iv = (void *)iv; + cryp.op = cipher_ctx->op; +#if !defined(COP_FLAG_WRITE_IV) + cryp.flags = 0; + + ivlen = EVP_CIPHER_CTX_iv_length(ctx); + if (ivlen > 0) + switch (cipher_ctx->mode) { + case EVP_CIPH_CBC_MODE: + assert(inl >= ivlen); + if (!EVP_CIPHER_CTX_encrypting(ctx)) { + ivptr = in + inl - ivlen; + memcpy(saved_iv, ivptr, ivlen); + } + break; + + case EVP_CIPH_CTR_MODE: + break; + + default: /* should not happen */ + return 0; + } +#else + cryp.flags = COP_FLAG_WRITE_IV; +#endif + + if (ioctl(cfd, CIOCCRYPT, &cryp) < 0) { + SYSerr(SYS_F_IOCTL, errno); + return 0; + } + +#if !defined(COP_FLAG_WRITE_IV) + if (ivlen > 0) + switch (cipher_ctx->mode) { + case EVP_CIPH_CBC_MODE: + assert(inl >= ivlen); + if (EVP_CIPHER_CTX_encrypting(ctx)) + ivptr = out + inl - ivlen; + else + ivptr = saved_iv; + + memcpy(iv, ivptr, ivlen); + break; + + case EVP_CIPH_CTR_MODE: + nblocks = (inl + cipher_ctx->blocksize - 1) + / cipher_ctx->blocksize; + do { + ivlen--; + nblocks += iv[ivlen]; + iv[ivlen] = (uint8_t) nblocks; + nblocks >>= 8; + } while (ivlen); + break; + + default: /* should not happen */ + return 0; + } +#endif + + return 1; +} + +static int ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + struct cipher_ctx *cipher_ctx = + (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); + size_t nblocks, len; + + /* initial partial block */ + while (cipher_ctx->num && inl) { + (*out++) = *(in++) ^ cipher_ctx->partial[cipher_ctx->num]; + --inl; + cipher_ctx->num = (cipher_ctx->num + 1) % cipher_ctx->blocksize; + } + + /* full blocks */ + if (inl > (unsigned int) cipher_ctx->blocksize) { + nblocks = inl/cipher_ctx->blocksize; + len = nblocks * cipher_ctx->blocksize; + if (cipher_do_cipher(ctx, out, in, len) < 1) + return 0; + inl -= len; + out += len; + in += len; + } + + /* final partial block */ + if (inl) { + memset(cipher_ctx->partial, 0, cipher_ctx->blocksize); + if (cipher_do_cipher(ctx, cipher_ctx->partial, cipher_ctx->partial, + cipher_ctx->blocksize) < 1) + return 0; + while (inl--) { + out[cipher_ctx->num] = in[cipher_ctx->num] + ^ cipher_ctx->partial[cipher_ctx->num]; + cipher_ctx->num++; + } + } + + return 1; +} + +static int cipher_ctrl(EVP_CIPHER_CTX *ctx, int type, int p1, void* p2) +{ + struct cipher_ctx *cipher_ctx = + (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); + EVP_CIPHER_CTX *to_ctx = (EVP_CIPHER_CTX *)p2; + struct cipher_ctx *to_cipher_ctx; + + switch (type) { + case EVP_CTRL_COPY: + if (cipher_ctx == NULL) + return 1; + /* when copying the context, a new session needs to be initialized */ + to_cipher_ctx = + (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(to_ctx); + memset(&to_cipher_ctx->sess, 0, sizeof(to_cipher_ctx->sess)); + return cipher_init(to_ctx, cipher_ctx->sess.key, EVP_CIPHER_CTX_iv(ctx), + (cipher_ctx->op == COP_ENCRYPT)); + + case EVP_CTRL_INIT: + memset(&cipher_ctx->sess, 0, sizeof(cipher_ctx->sess)); + return 1; + + default: + break; + } + + return -1; +} + +static int cipher_cleanup(EVP_CIPHER_CTX *ctx) +{ + struct cipher_ctx *cipher_ctx = + (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); + + return clean_devcrypto_session(&cipher_ctx->sess); +} + +/* + * Keep a table of known nids and associated methods. + * Note that known_cipher_nids[] isn't necessarily indexed the same way as + * cipher_data[] above, which known_cipher_methods[] is. + */ +static int known_cipher_nids[OSSL_NELEM(cipher_data)]; +static int known_cipher_nids_amount = -1; /* -1 indicates not yet initialised */ +static EVP_CIPHER *known_cipher_methods[OSSL_NELEM(cipher_data)] = { NULL, }; + +static void prepare_cipher_methods(void) +{ + size_t i; + struct session_op sess; + unsigned long cipher_mode; + + memset(&sess, 0, sizeof(sess)); + sess.key = (void *)"01234567890123456789012345678901234567890123456789"; + + for (i = 0, known_cipher_nids_amount = 0; + i < OSSL_NELEM(cipher_data); i++) { + + /* + * Check that the algo is really availably by trying to open and close + * a session. + */ + sess.cipher = cipher_data[i].devcryptoid; + sess.keylen = cipher_data[i].keylen; + if (ioctl(cfd, CIOCGSESSION, &sess) < 0 + || ioctl(cfd, CIOCFSESSION, &sess.ses) < 0) + continue; + + cipher_mode = cipher_data[i].flags & EVP_CIPH_MODE; + + if ((known_cipher_methods[i] = + EVP_CIPHER_meth_new(cipher_data[i].nid, + cipher_mode == EVP_CIPH_CTR_MODE ? 1 : + cipher_data[i].blocksize, + cipher_data[i].keylen)) == NULL + || !EVP_CIPHER_meth_set_iv_length(known_cipher_methods[i], + cipher_data[i].ivlen) + || !EVP_CIPHER_meth_set_flags(known_cipher_methods[i], + cipher_data[i].flags + | EVP_CIPH_CUSTOM_COPY + | EVP_CIPH_CTRL_INIT + | EVP_CIPH_FLAG_DEFAULT_ASN1) + || !EVP_CIPHER_meth_set_init(known_cipher_methods[i], cipher_init) + || !EVP_CIPHER_meth_set_do_cipher(known_cipher_methods[i], + cipher_mode == EVP_CIPH_CTR_MODE ? + ctr_do_cipher : + cipher_do_cipher) + || !EVP_CIPHER_meth_set_ctrl(known_cipher_methods[i], cipher_ctrl) + || !EVP_CIPHER_meth_set_cleanup(known_cipher_methods[i], + cipher_cleanup) + || !EVP_CIPHER_meth_set_impl_ctx_size(known_cipher_methods[i], + sizeof(struct cipher_ctx))) { + EVP_CIPHER_meth_free(known_cipher_methods[i]); + known_cipher_methods[i] = NULL; + } else { + known_cipher_nids[known_cipher_nids_amount++] = + cipher_data[i].nid; + } + } +} + +static const EVP_CIPHER *get_cipher_method(int nid) +{ + size_t i = get_cipher_data_index(nid); + + if (i == (size_t)-1) + return NULL; + return known_cipher_methods[i]; +} + +static int get_cipher_nids(const int **nids) +{ + *nids = known_cipher_nids; + return known_cipher_nids_amount; +} + +static void destroy_cipher_method(int nid) +{ + size_t i = get_cipher_data_index(nid); + + EVP_CIPHER_meth_free(known_cipher_methods[i]); + known_cipher_methods[i] = NULL; +} + +static void destroy_all_cipher_methods(void) +{ + size_t i; + + for (i = 0; i < OSSL_NELEM(cipher_data); i++) + destroy_cipher_method(cipher_data[i].nid); +} + +static int devcrypto_ciphers(ENGINE *e, const EVP_CIPHER **cipher, + const int **nids, int nid) +{ + if (cipher == NULL) + return get_cipher_nids(nids); + + *cipher = get_cipher_method(nid); + + return *cipher != NULL; +} + +/* + * We only support digests if the cryptodev implementation supports multiple + * data updates and session copying. Otherwise, we would be forced to maintain + * a cache, which is perilous if there's a lot of data coming in (if someone + * wants to checksum an OpenSSL tarball, for example). + */ +#if defined(CIOCCPHASH) && defined(COP_FLAG_UPDATE) && defined(COP_FLAG_FINAL) +#define IMPLEMENT_DIGEST + +/****************************************************************************** + * + * Digests + * + * Because they all do the same basic operation, we have only one set of + * method functions for them all to share, and a mapping table between + * NIDs and cryptodev IDs, with all the necessary size data. + * + *****/ + +struct digest_ctx { + struct session_op sess; + /* This signals that the init function was called, not that it succeeded. */ + int init_called; +}; + +static const struct digest_data_st { + int nid; + int blocksize; + int digestlen; + int devcryptoid; +} digest_data[] = { +#ifndef OPENSSL_NO_MD5 + { NID_md5, /* MD5_CBLOCK */ 64, 16, CRYPTO_MD5 }, +#endif + { NID_sha1, SHA_CBLOCK, 20, CRYPTO_SHA1 }, +#ifndef OPENSSL_NO_RMD160 +# if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_RIPEMD160) + { NID_ripemd160, /* RIPEMD160_CBLOCK */ 64, 20, CRYPTO_RIPEMD160 }, +# endif +#endif +#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_224) + { NID_sha224, SHA256_CBLOCK, 224 / 8, CRYPTO_SHA2_224 }, +#endif +#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_256) + { NID_sha256, SHA256_CBLOCK, 256 / 8, CRYPTO_SHA2_256 }, +#endif +#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_384) + { NID_sha384, SHA512_CBLOCK, 384 / 8, CRYPTO_SHA2_384 }, +#endif +#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_512) + { NID_sha512, SHA512_CBLOCK, 512 / 8, CRYPTO_SHA2_512 }, +#endif +}; + +static size_t get_digest_data_index(int nid) +{ + size_t i; + + for (i = 0; i < OSSL_NELEM(digest_data); i++) + if (nid == digest_data[i].nid) + return i; + + /* + * Code further down must make sure that only NIDs in the table above + * are used. If any other NID reaches this function, there's a grave + * coding error further down. + */ + assert("Code that never should be reached" == NULL); + return -1; +} + +static const struct digest_data_st *get_digest_data(int nid) +{ + return &digest_data[get_digest_data_index(nid)]; +} + +/* + * Following are the four necessary functions to map OpenSSL functionality + * with cryptodev. + */ + +static int digest_init(EVP_MD_CTX *ctx) +{ + struct digest_ctx *digest_ctx = + (struct digest_ctx *)EVP_MD_CTX_md_data(ctx); + const struct digest_data_st *digest_d = + get_digest_data(EVP_MD_CTX_type(ctx)); + + digest_ctx->init_called = 1; + + memset(&digest_ctx->sess, 0, sizeof(digest_ctx->sess)); + digest_ctx->sess.mac = digest_d->devcryptoid; + if (ioctl(cfd, CIOCGSESSION, &digest_ctx->sess) < 0) { + SYSerr(SYS_F_IOCTL, errno); + return 0; + } + + return 1; +} + +static int digest_op(struct digest_ctx *ctx, const void *src, size_t srclen, + void *res, unsigned int flags) +{ + struct crypt_op cryp; + + memset(&cryp, 0, sizeof(cryp)); + cryp.ses = ctx->sess.ses; + cryp.len = srclen; + cryp.src = (void *)src; + cryp.dst = NULL; + cryp.mac = res; + cryp.flags = flags; + return ioctl(cfd, CIOCCRYPT, &cryp); +} + +static int digest_update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ + struct digest_ctx *digest_ctx = + (struct digest_ctx *)EVP_MD_CTX_md_data(ctx); + + if (count == 0) + return 1; + + if (digest_ctx == NULL) + return 0; + + if (digest_op(digest_ctx, data, count, NULL, COP_FLAG_UPDATE) < 0) { + SYSerr(SYS_F_IOCTL, errno); + return 0; + } + + return 1; +} + +static int digest_final(EVP_MD_CTX *ctx, unsigned char *md) +{ + struct digest_ctx *digest_ctx = + (struct digest_ctx *)EVP_MD_CTX_md_data(ctx); + + if (md == NULL || digest_ctx == NULL) + return 0; + if (digest_op(digest_ctx, NULL, 0, md, COP_FLAG_FINAL) < 0) { + SYSerr(SYS_F_IOCTL, errno); + return 0; + } + + return 1; +} + +static int digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from) +{ + struct digest_ctx *digest_from = + (struct digest_ctx *)EVP_MD_CTX_md_data(from); + struct digest_ctx *digest_to = + (struct digest_ctx *)EVP_MD_CTX_md_data(to); + struct cphash_op cphash; + + if (digest_from == NULL || digest_from->init_called != 1) + return 1; + + if (!digest_init(to)) { + SYSerr(SYS_F_IOCTL, errno); + return 0; + } + + cphash.src_ses = digest_from->sess.ses; + cphash.dst_ses = digest_to->sess.ses; + if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) { + SYSerr(SYS_F_IOCTL, errno); + return 0; + } + return 1; +} + +static int digest_cleanup(EVP_MD_CTX *ctx) +{ + struct digest_ctx *digest_ctx = + (struct digest_ctx *)EVP_MD_CTX_md_data(ctx); + + if (digest_ctx == NULL) + return 1; + + return clean_devcrypto_session(&digest_ctx->sess); +} + +static int devcrypto_test_digest(size_t digest_data_index) +{ + struct session_op sess1, sess2; + struct cphash_op cphash; + int ret=0; + + memset(&sess1, 0, sizeof(sess1)); + memset(&sess2, 0, sizeof(sess2)); + sess1.mac = digest_data[digest_data_index].devcryptoid; + if (ioctl(cfd, CIOCGSESSION, &sess1) < 0) + return 0; + /* Make sure the driver is capable of hash state copy */ + sess2.mac = sess1.mac; + if (ioctl(cfd, CIOCGSESSION, &sess2) >= 0) { + cphash.src_ses = sess1.ses; + cphash.dst_ses = sess2.ses; + if (ioctl(cfd, CIOCCPHASH, &cphash) >= 0) + ret = 1; + ioctl(cfd, CIOCFSESSION, &sess2.ses); + } + ioctl(cfd, CIOCFSESSION, &sess1.ses); + return ret; +} + +/* + * Keep a table of known nids and associated methods. + * Note that known_digest_nids[] isn't necessarily indexed the same way as + * digest_data[] above, which known_digest_methods[] is. + */ +static int known_digest_nids[OSSL_NELEM(digest_data)]; +static int known_digest_nids_amount = -1; /* -1 indicates not yet initialised */ +static EVP_MD *known_digest_methods[OSSL_NELEM(digest_data)] = { NULL, }; + +static void prepare_digest_methods(void) +{ + size_t i; + + for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data); + i++) { + + /* + * Check that the algo is usable + */ + if (!devcrypto_test_digest(i)) + continue; + + if ((known_digest_methods[i] = EVP_MD_meth_new(digest_data[i].nid, + NID_undef)) == NULL + || !EVP_MD_meth_set_input_blocksize(known_digest_methods[i], + digest_data[i].blocksize) + || !EVP_MD_meth_set_result_size(known_digest_methods[i], + digest_data[i].digestlen) + || !EVP_MD_meth_set_init(known_digest_methods[i], digest_init) + || !EVP_MD_meth_set_update(known_digest_methods[i], digest_update) + || !EVP_MD_meth_set_final(known_digest_methods[i], digest_final) + || !EVP_MD_meth_set_copy(known_digest_methods[i], digest_copy) + || !EVP_MD_meth_set_cleanup(known_digest_methods[i], digest_cleanup) + || !EVP_MD_meth_set_app_datasize(known_digest_methods[i], + sizeof(struct digest_ctx))) { + EVP_MD_meth_free(known_digest_methods[i]); + known_digest_methods[i] = NULL; + } else { + known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid; + } + } +} + +static const EVP_MD *get_digest_method(int nid) +{ + size_t i = get_digest_data_index(nid); + + if (i == (size_t)-1) + return NULL; + return known_digest_methods[i]; +} + +static int get_digest_nids(const int **nids) +{ + *nids = known_digest_nids; + return known_digest_nids_amount; +} + +static void destroy_digest_method(int nid) +{ + size_t i = get_digest_data_index(nid); + + EVP_MD_meth_free(known_digest_methods[i]); + known_digest_methods[i] = NULL; +} + +static void destroy_all_digest_methods(void) +{ + size_t i; + + for (i = 0; i < OSSL_NELEM(digest_data); i++) + destroy_digest_method(digest_data[i].nid); +} + +static int devcrypto_digests(ENGINE *e, const EVP_MD **digest, + const int **nids, int nid) +{ + if (digest == NULL) + return get_digest_nids(nids); + + *digest = get_digest_method(nid); + + return *digest != NULL; +} + +#endif + +/****************************************************************************** + * + * LOAD / UNLOAD + * + *****/ + +static int devcrypto_unload(ENGINE *e) +{ + destroy_all_cipher_methods(); +#ifdef IMPLEMENT_DIGEST + destroy_all_digest_methods(); +#endif + + close(cfd); + + return 1; +} +/* + * This engine is always built into libcrypto, so it doesn't offer any + * ability to be dynamically loadable. + */ +void engine_load_devcrypto_int() +{ + ENGINE *e = NULL; + + if ((cfd = open("/dev/crypto", O_RDWR, 0)) < 0) { +#ifndef ENGINE_DEVCRYPTO_DEBUG + if (errno != ENOENT) +#endif + fprintf(stderr, "Could not open /dev/crypto: %s\n", strerror(errno)); + return; + } + + if ((e = ENGINE_new()) == NULL + || !ENGINE_set_destroy_function(e, devcrypto_unload)) { + ENGINE_free(e); + /* + * We know that devcrypto_unload() won't be called when one of the + * above two calls have failed, so we close cfd explicitly here to + * avoid leaking resources. + */ + close(cfd); + return; + } + + prepare_cipher_methods(); +#ifdef IMPLEMENT_DIGEST + prepare_digest_methods(); +#endif + + if (!ENGINE_set_id(e, "devcrypto") + || !ENGINE_set_name(e, "/dev/crypto engine") + +/* + * Asymmetric ciphers aren't well supported with /dev/crypto. Among the BSD + * implementations, it seems to only exist in FreeBSD, and regarding the + * parameters in its crypt_kop, the manual crypto(4) has this to say: + * + * The semantics of these arguments are currently undocumented. + * + * Reading through the FreeBSD source code doesn't give much more than + * their CRK_MOD_EXP implementation for ubsec. + * + * It doesn't look much better with cryptodev-linux. They have the crypt_kop + * structure as well as the command (CRK_*) in cryptodev.h, but no support + * seems to be implemented at all for the moment. + * + * At the time of writing, it seems impossible to write proper support for + * FreeBSD's asym features without some very deep knowledge and access to + * specific kernel modules. + * + * /Richard Levitte, 2017-05-11 + */ +#if 0 +# ifndef OPENSSL_NO_RSA + || !ENGINE_set_RSA(e, devcrypto_rsa) +# endif +# ifndef OPENSSL_NO_DSA + || !ENGINE_set_DSA(e, devcrypto_dsa) +# endif +# ifndef OPENSSL_NO_DH + || !ENGINE_set_DH(e, devcrypto_dh) +# endif +# ifndef OPENSSL_NO_EC + || !ENGINE_set_EC(e, devcrypto_ec) +# endif +#endif + || !ENGINE_set_ciphers(e, devcrypto_ciphers) +#ifdef IMPLEMENT_DIGEST + || !ENGINE_set_digests(e, devcrypto_digests) +#endif + ) { + ENGINE_free(e); + return; + } + + ENGINE_add(e); + ENGINE_free(e); /* Loose our local reference */ + ERR_clear_error(); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_dyn.c b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_dyn.c new file mode 100644 index 000000000..843226c07 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_dyn.c @@ -0,0 +1,510 @@ +/* + * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "eng_int.h" +#include "internal/dso.h" +#include + +/* + * Shared libraries implementing ENGINEs for use by the "dynamic" ENGINE + * loader should implement the hook-up functions with the following + * prototypes. + */ + +/* Our ENGINE handlers */ +static int dynamic_init(ENGINE *e); +static int dynamic_finish(ENGINE *e); +static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, + void (*f) (void)); +/* Predeclare our context type */ +typedef struct st_dynamic_data_ctx dynamic_data_ctx; +/* The implementation for the important control command */ +static int dynamic_load(ENGINE *e, dynamic_data_ctx *ctx); + +#define DYNAMIC_CMD_SO_PATH ENGINE_CMD_BASE +#define DYNAMIC_CMD_NO_VCHECK (ENGINE_CMD_BASE + 1) +#define DYNAMIC_CMD_ID (ENGINE_CMD_BASE + 2) +#define DYNAMIC_CMD_LIST_ADD (ENGINE_CMD_BASE + 3) +#define DYNAMIC_CMD_DIR_LOAD (ENGINE_CMD_BASE + 4) +#define DYNAMIC_CMD_DIR_ADD (ENGINE_CMD_BASE + 5) +#define DYNAMIC_CMD_LOAD (ENGINE_CMD_BASE + 6) + +/* The constants used when creating the ENGINE */ +static const char *engine_dynamic_id = "dynamic"; +static const char *engine_dynamic_name = "Dynamic engine loading support"; +static const ENGINE_CMD_DEFN dynamic_cmd_defns[] = { + {DYNAMIC_CMD_SO_PATH, + "SO_PATH", + "Specifies the path to the new ENGINE shared library", + ENGINE_CMD_FLAG_STRING}, + {DYNAMIC_CMD_NO_VCHECK, + "NO_VCHECK", + "Specifies to continue even if version checking fails (boolean)", + ENGINE_CMD_FLAG_NUMERIC}, + {DYNAMIC_CMD_ID, + "ID", + "Specifies an ENGINE id name for loading", + ENGINE_CMD_FLAG_STRING}, + {DYNAMIC_CMD_LIST_ADD, + "LIST_ADD", + "Whether to add a loaded ENGINE to the internal list (0=no,1=yes,2=mandatory)", + ENGINE_CMD_FLAG_NUMERIC}, + {DYNAMIC_CMD_DIR_LOAD, + "DIR_LOAD", + "Specifies whether to load from 'DIR_ADD' directories (0=no,1=yes,2=mandatory)", + ENGINE_CMD_FLAG_NUMERIC}, + {DYNAMIC_CMD_DIR_ADD, + "DIR_ADD", + "Adds a directory from which ENGINEs can be loaded", + ENGINE_CMD_FLAG_STRING}, + {DYNAMIC_CMD_LOAD, + "LOAD", + "Load up the ENGINE specified by other settings", + ENGINE_CMD_FLAG_NO_INPUT}, + {0, NULL, NULL, 0} +}; + +/* + * Loading code stores state inside the ENGINE structure via the "ex_data" + * element. We load all our state into a single structure and use that as a + * single context in the "ex_data" stack. + */ +struct st_dynamic_data_ctx { + /* The DSO object we load that supplies the ENGINE code */ + DSO *dynamic_dso; + /* + * The function pointer to the version checking shared library function + */ + dynamic_v_check_fn v_check; + /* + * The function pointer to the engine-binding shared library function + */ + dynamic_bind_engine bind_engine; + /* The default name/path for loading the shared library */ + char *DYNAMIC_LIBNAME; + /* Whether to continue loading on a version check failure */ + int no_vcheck; + /* If non-NULL, stipulates the 'id' of the ENGINE to be loaded */ + char *engine_id; + /* + * If non-zero, a successfully loaded ENGINE should be added to the + * internal ENGINE list. If 2, the add must succeed or the entire load + * should fail. + */ + int list_add_value; + /* The symbol name for the version checking function */ + const char *DYNAMIC_F1; + /* The symbol name for the "initialise ENGINE structure" function */ + const char *DYNAMIC_F2; + /* + * Whether to never use 'dirs', use 'dirs' as a fallback, or only use + * 'dirs' for loading. Default is to use 'dirs' as a fallback. + */ + int dir_load; + /* A stack of directories from which ENGINEs could be loaded */ + STACK_OF(OPENSSL_STRING) *dirs; +}; + +/* + * This is the "ex_data" index we obtain and reserve for use with our context + * structure. + */ +static int dynamic_ex_data_idx = -1; + +static void int_free_str(char *s) +{ + OPENSSL_free(s); +} + +/* + * Because our ex_data element may or may not get allocated depending on + * whether a "first-use" occurs before the ENGINE is freed, we have a memory + * leak problem to solve. We can't declare a "new" handler for the ex_data as + * we don't want a dynamic_data_ctx in *all* ENGINE structures of all types + * (this is a bug in the design of CRYPTO_EX_DATA). As such, we just declare + * a "free" handler and that will get called if an ENGINE is being destroyed + * and there was an ex_data element corresponding to our context type. + */ +static void dynamic_data_ctx_free_func(void *parent, void *ptr, + CRYPTO_EX_DATA *ad, int idx, long argl, + void *argp) +{ + if (ptr) { + dynamic_data_ctx *ctx = (dynamic_data_ctx *)ptr; + DSO_free(ctx->dynamic_dso); + OPENSSL_free(ctx->DYNAMIC_LIBNAME); + OPENSSL_free(ctx->engine_id); + sk_OPENSSL_STRING_pop_free(ctx->dirs, int_free_str); + OPENSSL_free(ctx); + } +} + +/* + * Construct the per-ENGINE context. We create it blindly and then use a lock + * to check for a race - if so, all but one of the threads "racing" will have + * wasted their time. The alternative involves creating everything inside the + * lock which is far worse. + */ +static int dynamic_set_data_ctx(ENGINE *e, dynamic_data_ctx **ctx) +{ + dynamic_data_ctx *c = OPENSSL_zalloc(sizeof(*c)); + int ret = 1; + + if (c == NULL) { + ENGINEerr(ENGINE_F_DYNAMIC_SET_DATA_CTX, ERR_R_MALLOC_FAILURE); + return 0; + } + c->dirs = sk_OPENSSL_STRING_new_null(); + if (c->dirs == NULL) { + ENGINEerr(ENGINE_F_DYNAMIC_SET_DATA_CTX, ERR_R_MALLOC_FAILURE); + OPENSSL_free(c); + return 0; + } + c->DYNAMIC_F1 = "v_check"; + c->DYNAMIC_F2 = "bind_engine"; + c->dir_load = 1; + CRYPTO_THREAD_write_lock(global_engine_lock); + if ((*ctx = (dynamic_data_ctx *)ENGINE_get_ex_data(e, + dynamic_ex_data_idx)) + == NULL) { + /* Good, we're the first */ + ret = ENGINE_set_ex_data(e, dynamic_ex_data_idx, c); + if (ret) { + *ctx = c; + c = NULL; + } + } + CRYPTO_THREAD_unlock(global_engine_lock); + /* + * If we lost the race to set the context, c is non-NULL and *ctx is the + * context of the thread that won. + */ + if (c) + sk_OPENSSL_STRING_free(c->dirs); + OPENSSL_free(c); + return ret; +} + +/* + * This function retrieves the context structure from an ENGINE's "ex_data", + * or if it doesn't exist yet, sets it up. + */ +static dynamic_data_ctx *dynamic_get_data_ctx(ENGINE *e) +{ + dynamic_data_ctx *ctx; + if (dynamic_ex_data_idx < 0) { + /* + * Create and register the ENGINE ex_data, and associate our "free" + * function with it to ensure any allocated contexts get freed when + * an ENGINE goes underground. + */ + int new_idx = ENGINE_get_ex_new_index(0, NULL, NULL, NULL, + dynamic_data_ctx_free_func); + if (new_idx == -1) { + ENGINEerr(ENGINE_F_DYNAMIC_GET_DATA_CTX, ENGINE_R_NO_INDEX); + return NULL; + } + CRYPTO_THREAD_write_lock(global_engine_lock); + /* Avoid a race by checking again inside this lock */ + if (dynamic_ex_data_idx < 0) { + /* Good, someone didn't beat us to it */ + dynamic_ex_data_idx = new_idx; + new_idx = -1; + } + CRYPTO_THREAD_unlock(global_engine_lock); + /* + * In theory we could "give back" the index here if (new_idx>-1), but + * it's not possible and wouldn't gain us much if it were. + */ + } + ctx = (dynamic_data_ctx *)ENGINE_get_ex_data(e, dynamic_ex_data_idx); + /* Check if the context needs to be created */ + if ((ctx == NULL) && !dynamic_set_data_ctx(e, &ctx)) + /* "set_data" will set errors if necessary */ + return NULL; + return ctx; +} + +static ENGINE *engine_dynamic(void) +{ + ENGINE *ret = ENGINE_new(); + if (ret == NULL) + return NULL; + if (!ENGINE_set_id(ret, engine_dynamic_id) || + !ENGINE_set_name(ret, engine_dynamic_name) || + !ENGINE_set_init_function(ret, dynamic_init) || + !ENGINE_set_finish_function(ret, dynamic_finish) || + !ENGINE_set_ctrl_function(ret, dynamic_ctrl) || + !ENGINE_set_flags(ret, ENGINE_FLAGS_BY_ID_COPY) || + !ENGINE_set_cmd_defns(ret, dynamic_cmd_defns)) { + ENGINE_free(ret); + return NULL; + } + return ret; +} + +void engine_load_dynamic_int(void) +{ + ENGINE *toadd = engine_dynamic(); + if (!toadd) + return; + ENGINE_add(toadd); + /* + * If the "add" worked, it gets a structural reference. So either way, we + * release our just-created reference. + */ + ENGINE_free(toadd); + /* + * If the "add" didn't work, it was probably a conflict because it was + * already added (eg. someone calling ENGINE_load_blah then calling + * ENGINE_load_builtin_engines() perhaps). + */ + ERR_clear_error(); +} + +static int dynamic_init(ENGINE *e) +{ + /* + * We always return failure - the "dynamic" engine itself can't be used + * for anything. + */ + return 0; +} + +static int dynamic_finish(ENGINE *e) +{ + /* + * This should never be called on account of "dynamic_init" always + * failing. + */ + return 0; +} + +static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)) +{ + dynamic_data_ctx *ctx = dynamic_get_data_ctx(e); + int initialised; + + if (!ctx) { + ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_NOT_LOADED); + return 0; + } + initialised = ((ctx->dynamic_dso == NULL) ? 0 : 1); + /* All our control commands require the ENGINE to be uninitialised */ + if (initialised) { + ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_ALREADY_LOADED); + return 0; + } + switch (cmd) { + case DYNAMIC_CMD_SO_PATH: + /* a NULL 'p' or a string of zero-length is the same thing */ + if (p && (strlen((const char *)p) < 1)) + p = NULL; + OPENSSL_free(ctx->DYNAMIC_LIBNAME); + if (p) + ctx->DYNAMIC_LIBNAME = OPENSSL_strdup(p); + else + ctx->DYNAMIC_LIBNAME = NULL; + return (ctx->DYNAMIC_LIBNAME ? 1 : 0); + case DYNAMIC_CMD_NO_VCHECK: + ctx->no_vcheck = ((i == 0) ? 0 : 1); + return 1; + case DYNAMIC_CMD_ID: + /* a NULL 'p' or a string of zero-length is the same thing */ + if (p && (strlen((const char *)p) < 1)) + p = NULL; + OPENSSL_free(ctx->engine_id); + if (p) + ctx->engine_id = OPENSSL_strdup(p); + else + ctx->engine_id = NULL; + return (ctx->engine_id ? 1 : 0); + case DYNAMIC_CMD_LIST_ADD: + if ((i < 0) || (i > 2)) { + ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_INVALID_ARGUMENT); + return 0; + } + ctx->list_add_value = (int)i; + return 1; + case DYNAMIC_CMD_LOAD: + return dynamic_load(e, ctx); + case DYNAMIC_CMD_DIR_LOAD: + if ((i < 0) || (i > 2)) { + ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_INVALID_ARGUMENT); + return 0; + } + ctx->dir_load = (int)i; + return 1; + case DYNAMIC_CMD_DIR_ADD: + /* a NULL 'p' or a string of zero-length is the same thing */ + if (!p || (strlen((const char *)p) < 1)) { + ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_INVALID_ARGUMENT); + return 0; + } + { + char *tmp_str = OPENSSL_strdup(p); + if (tmp_str == NULL) { + ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ERR_R_MALLOC_FAILURE); + return 0; + } + if (!sk_OPENSSL_STRING_push(ctx->dirs, tmp_str)) { + OPENSSL_free(tmp_str); + ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ERR_R_MALLOC_FAILURE); + return 0; + } + } + return 1; + default: + break; + } + ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED); + return 0; +} + +static int int_load(dynamic_data_ctx *ctx) +{ + int num, loop; + /* Unless told not to, try a direct load */ + if ((ctx->dir_load != 2) && (DSO_load(ctx->dynamic_dso, + ctx->DYNAMIC_LIBNAME, NULL, + 0)) != NULL) + return 1; + /* If we're not allowed to use 'dirs' or we have none, fail */ + if (!ctx->dir_load || (num = sk_OPENSSL_STRING_num(ctx->dirs)) < 1) + return 0; + for (loop = 0; loop < num; loop++) { + const char *s = sk_OPENSSL_STRING_value(ctx->dirs, loop); + char *merge = DSO_merge(ctx->dynamic_dso, ctx->DYNAMIC_LIBNAME, s); + if (!merge) + return 0; + if (DSO_load(ctx->dynamic_dso, merge, NULL, 0)) { + /* Found what we're looking for */ + OPENSSL_free(merge); + return 1; + } + OPENSSL_free(merge); + } + return 0; +} + +static int dynamic_load(ENGINE *e, dynamic_data_ctx *ctx) +{ + ENGINE cpy; + dynamic_fns fns; + + if (ctx->dynamic_dso == NULL) + ctx->dynamic_dso = DSO_new(); + if (ctx->dynamic_dso == NULL) + return 0; + if (!ctx->DYNAMIC_LIBNAME) { + if (!ctx->engine_id) + return 0; + DSO_ctrl(ctx->dynamic_dso, DSO_CTRL_SET_FLAGS, + DSO_FLAG_NAME_TRANSLATION_EXT_ONLY, NULL); + ctx->DYNAMIC_LIBNAME = + DSO_convert_filename(ctx->dynamic_dso, ctx->engine_id); + } + if (!int_load(ctx)) { + ENGINEerr(ENGINE_F_DYNAMIC_LOAD, ENGINE_R_DSO_NOT_FOUND); + DSO_free(ctx->dynamic_dso); + ctx->dynamic_dso = NULL; + return 0; + } + /* We have to find a bind function otherwise it'll always end badly */ + if (! + (ctx->bind_engine = + (dynamic_bind_engine) DSO_bind_func(ctx->dynamic_dso, + ctx->DYNAMIC_F2))) { + ctx->bind_engine = NULL; + DSO_free(ctx->dynamic_dso); + ctx->dynamic_dso = NULL; + ENGINEerr(ENGINE_F_DYNAMIC_LOAD, ENGINE_R_DSO_FAILURE); + return 0; + } + /* Do we perform version checking? */ + if (!ctx->no_vcheck) { + unsigned long vcheck_res = 0; + /* + * Now we try to find a version checking function and decide how to + * cope with failure if/when it fails. + */ + ctx->v_check = + (dynamic_v_check_fn) DSO_bind_func(ctx->dynamic_dso, + ctx->DYNAMIC_F1); + if (ctx->v_check) + vcheck_res = ctx->v_check(OSSL_DYNAMIC_VERSION); + /* + * We fail if the version checker veto'd the load *or* if it is + * deferring to us (by returning its version) and we think it is too + * old. + */ + if (vcheck_res < OSSL_DYNAMIC_OLDEST) { + /* Fail */ + ctx->bind_engine = NULL; + ctx->v_check = NULL; + DSO_free(ctx->dynamic_dso); + ctx->dynamic_dso = NULL; + ENGINEerr(ENGINE_F_DYNAMIC_LOAD, + ENGINE_R_VERSION_INCOMPATIBILITY); + return 0; + } + } + /* + * First binary copy the ENGINE structure so that we can roll back if the + * hand-over fails + */ + memcpy(&cpy, e, sizeof(ENGINE)); + /* + * Provide the ERR, "ex_data", memory, and locking callbacks so the + * loaded library uses our state rather than its own. FIXME: As noted in + * engine.h, much of this would be simplified if each area of code + * provided its own "summary" structure of all related callbacks. It + * would also increase opaqueness. + */ + fns.static_state = ENGINE_get_static_state(); + CRYPTO_get_mem_functions(&fns.mem_fns.malloc_fn, &fns.mem_fns.realloc_fn, + &fns.mem_fns.free_fn); + /* + * Now that we've loaded the dynamic engine, make sure no "dynamic" + * ENGINE elements will show through. + */ + engine_set_all_null(e); + + /* Try to bind the ENGINE onto our own ENGINE structure */ + if (!ctx->bind_engine(e, ctx->engine_id, &fns)) { + ctx->bind_engine = NULL; + ctx->v_check = NULL; + DSO_free(ctx->dynamic_dso); + ctx->dynamic_dso = NULL; + ENGINEerr(ENGINE_F_DYNAMIC_LOAD, ENGINE_R_INIT_FAILED); + /* Copy the original ENGINE structure back */ + memcpy(e, &cpy, sizeof(ENGINE)); + return 0; + } + /* Do we try to add this ENGINE to the internal list too? */ + if (ctx->list_add_value > 0) { + if (!ENGINE_add(e)) { + /* Do we tolerate this or fail? */ + if (ctx->list_add_value > 1) { + /* + * Fail - NB: By this time, it's too late to rollback, and + * trying to do so allows the bind_engine() code to have + * created leaks. We just have to fail where we are, after + * the ENGINE has changed. + */ + ENGINEerr(ENGINE_F_DYNAMIC_LOAD, + ENGINE_R_CONFLICTING_ENGINE_ID); + return 0; + } + /* Tolerate */ + ERR_clear_error(); + } + } + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_err.c new file mode 100644 index 000000000..bd1aefa18 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_err.c @@ -0,0 +1,154 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA ENGINE_str_functs[] = { + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_DIGEST_UPDATE, 0), "digest_update"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_DYNAMIC_CTRL, 0), "dynamic_ctrl"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_DYNAMIC_GET_DATA_CTX, 0), + "dynamic_get_data_ctx"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_DYNAMIC_LOAD, 0), "dynamic_load"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_DYNAMIC_SET_DATA_CTX, 0), + "dynamic_set_data_ctx"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_ADD, 0), "ENGINE_add"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_BY_ID, 0), "ENGINE_by_id"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_CMD_IS_EXECUTABLE, 0), + "ENGINE_cmd_is_executable"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_CTRL, 0), "ENGINE_ctrl"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_CTRL_CMD, 0), "ENGINE_ctrl_cmd"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_CTRL_CMD_STRING, 0), + "ENGINE_ctrl_cmd_string"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_FINISH, 0), "ENGINE_finish"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_GET_CIPHER, 0), + "ENGINE_get_cipher"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_GET_DIGEST, 0), + "ENGINE_get_digest"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_GET_FIRST, 0), + "ENGINE_get_first"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_GET_LAST, 0), "ENGINE_get_last"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_GET_NEXT, 0), "ENGINE_get_next"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_GET_PKEY_ASN1_METH, 0), + "ENGINE_get_pkey_asn1_meth"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_GET_PKEY_METH, 0), + "ENGINE_get_pkey_meth"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_GET_PREV, 0), "ENGINE_get_prev"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_INIT, 0), "ENGINE_init"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_LIST_ADD, 0), "engine_list_add"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_LIST_REMOVE, 0), + "engine_list_remove"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_LOAD_PRIVATE_KEY, 0), + "ENGINE_load_private_key"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_LOAD_PUBLIC_KEY, 0), + "ENGINE_load_public_key"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT, 0), + "ENGINE_load_ssl_client_cert"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_NEW, 0), "ENGINE_new"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_PKEY_ASN1_FIND_STR, 0), + "ENGINE_pkey_asn1_find_str"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_REMOVE, 0), "ENGINE_remove"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_SET_DEFAULT_STRING, 0), + "ENGINE_set_default_string"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_SET_ID, 0), "ENGINE_set_id"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_SET_NAME, 0), "ENGINE_set_name"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_TABLE_REGISTER, 0), + "engine_table_register"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_UNLOCKED_FINISH, 0), + "engine_unlocked_finish"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_ENGINE_UP_REF, 0), "ENGINE_up_ref"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_INT_CLEANUP_ITEM, 0), + "int_cleanup_item"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_INT_CTRL_HELPER, 0), "int_ctrl_helper"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_INT_ENGINE_CONFIGURE, 0), + "int_engine_configure"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_INT_ENGINE_MODULE_INIT, 0), + "int_engine_module_init"}, + {ERR_PACK(ERR_LIB_ENGINE, ENGINE_F_OSSL_HMAC_INIT, 0), "ossl_hmac_init"}, + {0, NULL} +}; + +static const ERR_STRING_DATA ENGINE_str_reasons[] = { + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_ALREADY_LOADED), "already loaded"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER), + "argument is not a number"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_CMD_NOT_EXECUTABLE), + "cmd not executable"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_COMMAND_TAKES_INPUT), + "command takes input"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_COMMAND_TAKES_NO_INPUT), + "command takes no input"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_CONFLICTING_ENGINE_ID), + "conflicting engine id"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED), + "ctrl command not implemented"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_DSO_FAILURE), "DSO failure"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_DSO_NOT_FOUND), "dso not found"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_ENGINES_SECTION_ERROR), + "engines section error"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_ENGINE_CONFIGURATION_ERROR), + "engine configuration error"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_ENGINE_IS_NOT_IN_LIST), + "engine is not in the list"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_ENGINE_SECTION_ERROR), + "engine section error"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_FAILED_LOADING_PRIVATE_KEY), + "failed loading private key"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_FAILED_LOADING_PUBLIC_KEY), + "failed loading public key"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_FINISH_FAILED), "finish failed"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_ID_OR_NAME_MISSING), + "'id' or 'name' missing"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_INIT_FAILED), "init failed"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_INTERNAL_LIST_ERROR), + "internal list error"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_INVALID_ARGUMENT), + "invalid argument"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_INVALID_CMD_NAME), + "invalid cmd name"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_INVALID_CMD_NUMBER), + "invalid cmd number"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_INVALID_INIT_VALUE), + "invalid init value"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_INVALID_STRING), "invalid string"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_NOT_INITIALISED), "not initialised"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_NOT_LOADED), "not loaded"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_NO_CONTROL_FUNCTION), + "no control function"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_NO_INDEX), "no index"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_NO_LOAD_FUNCTION), + "no load function"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_NO_REFERENCE), "no reference"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_NO_SUCH_ENGINE), "no such engine"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_UNIMPLEMENTED_CIPHER), + "unimplemented cipher"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_UNIMPLEMENTED_DIGEST), + "unimplemented digest"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD), + "unimplemented public key method"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_VERSION_INCOMPATIBILITY), + "version incompatibility"}, + {0, NULL} +}; + +#endif + +int ERR_load_ENGINE_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(ENGINE_str_functs[0].error) == NULL) { + ERR_load_strings_const(ENGINE_str_functs); + ERR_load_strings_const(ENGINE_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_fat.c b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_fat.c new file mode 100644 index 000000000..591fddc8e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_fat.c @@ -0,0 +1,123 @@ +/* + * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "eng_int.h" +#include + +int ENGINE_set_default(ENGINE *e, unsigned int flags) +{ + if ((flags & ENGINE_METHOD_CIPHERS) && !ENGINE_set_default_ciphers(e)) + return 0; + if ((flags & ENGINE_METHOD_DIGESTS) && !ENGINE_set_default_digests(e)) + return 0; +#ifndef OPENSSL_NO_RSA + if ((flags & ENGINE_METHOD_RSA) && !ENGINE_set_default_RSA(e)) + return 0; +#endif +#ifndef OPENSSL_NO_DSA + if ((flags & ENGINE_METHOD_DSA) && !ENGINE_set_default_DSA(e)) + return 0; +#endif +#ifndef OPENSSL_NO_DH + if ((flags & ENGINE_METHOD_DH) && !ENGINE_set_default_DH(e)) + return 0; +#endif +#ifndef OPENSSL_NO_EC + if ((flags & ENGINE_METHOD_EC) && !ENGINE_set_default_EC(e)) + return 0; +#endif + if ((flags & ENGINE_METHOD_RAND) && !ENGINE_set_default_RAND(e)) + return 0; + if ((flags & ENGINE_METHOD_PKEY_METHS) + && !ENGINE_set_default_pkey_meths(e)) + return 0; + if ((flags & ENGINE_METHOD_PKEY_ASN1_METHS) + && !ENGINE_set_default_pkey_asn1_meths(e)) + return 0; + return 1; +} + +/* Set default algorithms using a string */ + +static int int_def_cb(const char *alg, int len, void *arg) +{ + unsigned int *pflags = arg; + if (alg == NULL) + return 0; + if (strncmp(alg, "ALL", len) == 0) + *pflags |= ENGINE_METHOD_ALL; + else if (strncmp(alg, "RSA", len) == 0) + *pflags |= ENGINE_METHOD_RSA; + else if (strncmp(alg, "DSA", len) == 0) + *pflags |= ENGINE_METHOD_DSA; + else if (strncmp(alg, "DH", len) == 0) + *pflags |= ENGINE_METHOD_DH; + else if (strncmp(alg, "EC", len) == 0) + *pflags |= ENGINE_METHOD_EC; + else if (strncmp(alg, "RAND", len) == 0) + *pflags |= ENGINE_METHOD_RAND; + else if (strncmp(alg, "CIPHERS", len) == 0) + *pflags |= ENGINE_METHOD_CIPHERS; + else if (strncmp(alg, "DIGESTS", len) == 0) + *pflags |= ENGINE_METHOD_DIGESTS; + else if (strncmp(alg, "PKEY", len) == 0) + *pflags |= ENGINE_METHOD_PKEY_METHS | ENGINE_METHOD_PKEY_ASN1_METHS; + else if (strncmp(alg, "PKEY_CRYPTO", len) == 0) + *pflags |= ENGINE_METHOD_PKEY_METHS; + else if (strncmp(alg, "PKEY_ASN1", len) == 0) + *pflags |= ENGINE_METHOD_PKEY_ASN1_METHS; + else + return 0; + return 1; +} + +int ENGINE_set_default_string(ENGINE *e, const char *def_list) +{ + unsigned int flags = 0; + if (!CONF_parse_list(def_list, ',', 1, int_def_cb, &flags)) { + ENGINEerr(ENGINE_F_ENGINE_SET_DEFAULT_STRING, + ENGINE_R_INVALID_STRING); + ERR_add_error_data(2, "str=", def_list); + return 0; + } + return ENGINE_set_default(e, flags); +} + +int ENGINE_register_complete(ENGINE *e) +{ + ENGINE_register_ciphers(e); + ENGINE_register_digests(e); +#ifndef OPENSSL_NO_RSA + ENGINE_register_RSA(e); +#endif +#ifndef OPENSSL_NO_DSA + ENGINE_register_DSA(e); +#endif +#ifndef OPENSSL_NO_DH + ENGINE_register_DH(e); +#endif +#ifndef OPENSSL_NO_EC + ENGINE_register_EC(e); +#endif + ENGINE_register_RAND(e); + ENGINE_register_pkey_meths(e); + ENGINE_register_pkey_asn1_meths(e); + return 1; +} + +int ENGINE_register_all_complete(void) +{ + ENGINE *e; + + for (e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) + if (!(e->flags & ENGINE_FLAGS_NO_REGISTER_ALL)) + ENGINE_register_complete(e); + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_init.c b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_init.c new file mode 100644 index 000000000..7c235fc47 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_init.c @@ -0,0 +1,109 @@ +/* + * Copyright 2001-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "e_os.h" +#include "eng_int.h" + +/* + * Initialise a engine type for use (or up its functional reference count if + * it's already in use). This version is only used internally. + */ +int engine_unlocked_init(ENGINE *e) +{ + int to_return = 1; + + if ((e->funct_ref == 0) && e->init) + /* + * This is the first functional reference and the engine requires + * initialisation so we do it now. + */ + to_return = e->init(e); + if (to_return) { + /* + * OK, we return a functional reference which is also a structural + * reference. + */ + e->struct_ref++; + e->funct_ref++; + engine_ref_debug(e, 0, 1); + engine_ref_debug(e, 1, 1); + } + return to_return; +} + +/* + * Free a functional reference to a engine type. This version is only used + * internally. + */ +int engine_unlocked_finish(ENGINE *e, int unlock_for_handlers) +{ + int to_return = 1; + + /* + * Reduce the functional reference count here so if it's the terminating + * case, we can release the lock safely and call the finish() handler + * without risk of a race. We get a race if we leave the count until + * after and something else is calling "finish" at the same time - + * there's a chance that both threads will together take the count from 2 + * to 0 without either calling finish(). + */ + e->funct_ref--; + engine_ref_debug(e, 1, -1); + if ((e->funct_ref == 0) && e->finish) { + if (unlock_for_handlers) + CRYPTO_THREAD_unlock(global_engine_lock); + to_return = e->finish(e); + if (unlock_for_handlers) + CRYPTO_THREAD_write_lock(global_engine_lock); + if (!to_return) + return 0; + } + REF_ASSERT_ISNT(e->funct_ref < 0); + /* Release the structural reference too */ + if (!engine_free_util(e, 0)) { + ENGINEerr(ENGINE_F_ENGINE_UNLOCKED_FINISH, ENGINE_R_FINISH_FAILED); + return 0; + } + return to_return; +} + +/* The API (locked) version of "init" */ +int ENGINE_init(ENGINE *e) +{ + int ret; + if (e == NULL) { + ENGINEerr(ENGINE_F_ENGINE_INIT, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) { + ENGINEerr(ENGINE_F_ENGINE_INIT, ERR_R_MALLOC_FAILURE); + return 0; + } + CRYPTO_THREAD_write_lock(global_engine_lock); + ret = engine_unlocked_init(e); + CRYPTO_THREAD_unlock(global_engine_lock); + return ret; +} + +/* The API (locked) version of "finish" */ +int ENGINE_finish(ENGINE *e) +{ + int to_return = 1; + + if (e == NULL) + return 1; + CRYPTO_THREAD_write_lock(global_engine_lock); + to_return = engine_unlocked_finish(e, 1); + CRYPTO_THREAD_unlock(global_engine_lock); + if (!to_return) { + ENGINEerr(ENGINE_F_ENGINE_FINISH, ENGINE_R_FINISH_FAILED); + return 0; + } + return to_return; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_int.h b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_int.h new file mode 100644 index 000000000..b95483341 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_int.h @@ -0,0 +1,171 @@ +/* + * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_ENGINE_INT_H +# define HEADER_ENGINE_INT_H + +# include "internal/cryptlib.h" +# include "internal/engine.h" +# include "internal/thread_once.h" +# include "internal/refcount.h" + +extern CRYPTO_RWLOCK *global_engine_lock; + +/* + * If we compile with this symbol defined, then both reference counts in the + * ENGINE structure will be monitored with a line of output on stderr for + * each change. This prints the engine's pointer address (truncated to + * unsigned int), "struct" or "funct" to indicate the reference type, the + * before and after reference count, and the file:line-number pair. The + * "engine_ref_debug" statements must come *after* the change. + */ +# ifdef ENGINE_REF_COUNT_DEBUG + +# define engine_ref_debug(e, isfunct, diff) \ + fprintf(stderr, "engine: %08x %s from %d to %d (%s:%d)\n", \ + (unsigned int)(e), (isfunct ? "funct" : "struct"), \ + ((isfunct) ? ((e)->funct_ref - (diff)) : ((e)->struct_ref - (diff))), \ + ((isfunct) ? (e)->funct_ref : (e)->struct_ref), \ + (OPENSSL_FILE), (OPENSSL_LINE)) + +# else + +# define engine_ref_debug(e, isfunct, diff) + +# endif + +/* + * Any code that will need cleanup operations should use these functions to + * register callbacks. engine_cleanup_int() will call all registered + * callbacks in order. NB: both the "add" functions assume the engine lock to + * already be held (in "write" mode). + */ +typedef void (ENGINE_CLEANUP_CB) (void); +typedef struct st_engine_cleanup_item { + ENGINE_CLEANUP_CB *cb; +} ENGINE_CLEANUP_ITEM; +DEFINE_STACK_OF(ENGINE_CLEANUP_ITEM) +void engine_cleanup_add_first(ENGINE_CLEANUP_CB *cb); +void engine_cleanup_add_last(ENGINE_CLEANUP_CB *cb); + +/* We need stacks of ENGINEs for use in eng_table.c */ +DEFINE_STACK_OF(ENGINE) + +/* + * If this symbol is defined then engine_table_select(), the function that is + * used by RSA, DSA (etc) code to select registered ENGINEs, cache defaults + * and functional references (etc), will display debugging summaries to + * stderr. + */ +/* #define ENGINE_TABLE_DEBUG */ + +/* + * This represents an implementation table. Dependent code should instantiate + * it as a (ENGINE_TABLE *) pointer value set initially to NULL. + */ +typedef struct st_engine_table ENGINE_TABLE; +int engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup, + ENGINE *e, const int *nids, int num_nids, + int setdefault); +void engine_table_unregister(ENGINE_TABLE **table, ENGINE *e); +void engine_table_cleanup(ENGINE_TABLE **table); +# ifndef ENGINE_TABLE_DEBUG +ENGINE *engine_table_select(ENGINE_TABLE **table, int nid); +# else +ENGINE *engine_table_select_tmp(ENGINE_TABLE **table, int nid, const char *f, + int l); +# define engine_table_select(t,n) engine_table_select_tmp(t,n,OPENSSL_FILE,OPENSSL_LINE) +# endif +typedef void (engine_table_doall_cb) (int nid, STACK_OF(ENGINE) *sk, + ENGINE *def, void *arg); +void engine_table_doall(ENGINE_TABLE *table, engine_table_doall_cb *cb, + void *arg); + +/* + * Internal versions of API functions that have control over locking. These + * are used between C files when functionality needs to be shared but the + * caller may already be controlling of the engine lock. + */ +int engine_unlocked_init(ENGINE *e); +int engine_unlocked_finish(ENGINE *e, int unlock_for_handlers); +int engine_free_util(ENGINE *e, int not_locked); + +/* + * This function will reset all "set"able values in an ENGINE to NULL. This + * won't touch reference counts or ex_data, but is equivalent to calling all + * the ENGINE_set_***() functions with a NULL value. + */ +void engine_set_all_null(ENGINE *e); + +/* + * NB: Bitwise OR-able values for the "flags" variable in ENGINE are now + * exposed in engine.h. + */ + +/* Free up dynamically allocated public key methods associated with ENGINE */ + +void engine_pkey_meths_free(ENGINE *e); +void engine_pkey_asn1_meths_free(ENGINE *e); + +/* Once initialisation function */ +extern CRYPTO_ONCE engine_lock_init; +DECLARE_RUN_ONCE(do_engine_lock_init) + +/* + * This is a structure for storing implementations of various crypto + * algorithms and functions. + */ +struct engine_st { + const char *id; + const char *name; + const RSA_METHOD *rsa_meth; + const DSA_METHOD *dsa_meth; + const DH_METHOD *dh_meth; + const EC_KEY_METHOD *ec_meth; + const RAND_METHOD *rand_meth; + /* Cipher handling is via this callback */ + ENGINE_CIPHERS_PTR ciphers; + /* Digest handling is via this callback */ + ENGINE_DIGESTS_PTR digests; + /* Public key handling via this callback */ + ENGINE_PKEY_METHS_PTR pkey_meths; + /* ASN1 public key handling via this callback */ + ENGINE_PKEY_ASN1_METHS_PTR pkey_asn1_meths; + ENGINE_GEN_INT_FUNC_PTR destroy; + ENGINE_GEN_INT_FUNC_PTR init; + ENGINE_GEN_INT_FUNC_PTR finish; + ENGINE_CTRL_FUNC_PTR ctrl; + ENGINE_LOAD_KEY_PTR load_privkey; + ENGINE_LOAD_KEY_PTR load_pubkey; + ENGINE_SSL_CLIENT_CERT_PTR load_ssl_client_cert; + const ENGINE_CMD_DEFN *cmd_defns; + int flags; + /* reference count on the structure itself */ + CRYPTO_REF_COUNT struct_ref; + /* + * reference count on usability of the engine type. NB: This controls the + * loading and initialisation of any functionality required by this + * engine, whereas the previous count is simply to cope with + * (de)allocation of this structure. Hence, running_ref <= struct_ref at + * all times. + */ + int funct_ref; + /* A place to store per-ENGINE data */ + CRYPTO_EX_DATA ex_data; + /* Used to maintain the linked-list of engines. */ + struct engine_st *prev; + struct engine_st *next; +}; + +typedef struct st_engine_pile ENGINE_PILE; + +DEFINE_LHASH_OF(ENGINE_PILE); + +#endif /* HEADER_ENGINE_INT_H */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_lib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_lib.c new file mode 100644 index 000000000..d7f2026fa --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_lib.c @@ -0,0 +1,299 @@ +/* + * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "e_os.h" +#include "eng_int.h" +#include +#include "internal/refcount.h" + +CRYPTO_RWLOCK *global_engine_lock; + +CRYPTO_ONCE engine_lock_init = CRYPTO_ONCE_STATIC_INIT; + +/* The "new"/"free" stuff first */ + +DEFINE_RUN_ONCE(do_engine_lock_init) +{ + if (!OPENSSL_init_crypto(0, NULL)) + return 0; + global_engine_lock = CRYPTO_THREAD_lock_new(); + return global_engine_lock != NULL; +} + +ENGINE *ENGINE_new(void) +{ + ENGINE *ret; + + if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init) + || (ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) { + ENGINEerr(ENGINE_F_ENGINE_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + ret->struct_ref = 1; + engine_ref_debug(ret, 0, 1); + if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_ENGINE, ret, &ret->ex_data)) { + OPENSSL_free(ret); + return NULL; + } + return ret; +} + +/* + * Placed here (close proximity to ENGINE_new) so that modifications to the + * elements of the ENGINE structure are more likely to be caught and changed + * here. + */ +void engine_set_all_null(ENGINE *e) +{ + e->id = NULL; + e->name = NULL; + e->rsa_meth = NULL; + e->dsa_meth = NULL; + e->dh_meth = NULL; + e->rand_meth = NULL; + e->ciphers = NULL; + e->digests = NULL; + e->destroy = NULL; + e->init = NULL; + e->finish = NULL; + e->ctrl = NULL; + e->load_privkey = NULL; + e->load_pubkey = NULL; + e->cmd_defns = NULL; + e->flags = 0; +} + +int engine_free_util(ENGINE *e, int not_locked) +{ + int i; + + if (e == NULL) + return 1; + if (not_locked) + CRYPTO_DOWN_REF(&e->struct_ref, &i, global_engine_lock); + else + i = --e->struct_ref; + engine_ref_debug(e, 0, -1); + if (i > 0) + return 1; + REF_ASSERT_ISNT(i < 0); + /* Free up any dynamically allocated public key methods */ + engine_pkey_meths_free(e); + engine_pkey_asn1_meths_free(e); + /* + * Give the ENGINE a chance to do any structural cleanup corresponding to + * allocation it did in its constructor (eg. unload error strings) + */ + if (e->destroy) + e->destroy(e); + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_ENGINE, e, &e->ex_data); + OPENSSL_free(e); + return 1; +} + +int ENGINE_free(ENGINE *e) +{ + return engine_free_util(e, 1); +} + +/* Cleanup stuff */ + +/* + * engine_cleanup_int() is coded such that anything that does work that will + * need cleanup can register a "cleanup" callback here. That way we don't get + * linker bloat by referring to all *possible* cleanups, but any linker bloat + * into code "X" will cause X's cleanup function to end up here. + */ +static STACK_OF(ENGINE_CLEANUP_ITEM) *cleanup_stack = NULL; +static int int_cleanup_check(int create) +{ + if (cleanup_stack) + return 1; + if (!create) + return 0; + cleanup_stack = sk_ENGINE_CLEANUP_ITEM_new_null(); + return (cleanup_stack ? 1 : 0); +} + +static ENGINE_CLEANUP_ITEM *int_cleanup_item(ENGINE_CLEANUP_CB *cb) +{ + ENGINE_CLEANUP_ITEM *item; + + if ((item = OPENSSL_malloc(sizeof(*item))) == NULL) { + ENGINEerr(ENGINE_F_INT_CLEANUP_ITEM, ERR_R_MALLOC_FAILURE); + return NULL; + } + item->cb = cb; + return item; +} + +void engine_cleanup_add_first(ENGINE_CLEANUP_CB *cb) +{ + ENGINE_CLEANUP_ITEM *item; + + if (!int_cleanup_check(1)) + return; + item = int_cleanup_item(cb); + if (item) + sk_ENGINE_CLEANUP_ITEM_insert(cleanup_stack, item, 0); +} + +void engine_cleanup_add_last(ENGINE_CLEANUP_CB *cb) +{ + ENGINE_CLEANUP_ITEM *item; + if (!int_cleanup_check(1)) + return; + item = int_cleanup_item(cb); + if (item != NULL) { + if (sk_ENGINE_CLEANUP_ITEM_push(cleanup_stack, item) <= 0) + OPENSSL_free(item); + } +} + +/* The API function that performs all cleanup */ +static void engine_cleanup_cb_free(ENGINE_CLEANUP_ITEM *item) +{ + (*(item->cb)) (); + OPENSSL_free(item); +} + +void engine_cleanup_int(void) +{ + if (int_cleanup_check(0)) { + sk_ENGINE_CLEANUP_ITEM_pop_free(cleanup_stack, + engine_cleanup_cb_free); + cleanup_stack = NULL; + } + CRYPTO_THREAD_lock_free(global_engine_lock); +} + +/* Now the "ex_data" support */ + +int ENGINE_set_ex_data(ENGINE *e, int idx, void *arg) +{ + return CRYPTO_set_ex_data(&e->ex_data, idx, arg); +} + +void *ENGINE_get_ex_data(const ENGINE *e, int idx) +{ + return CRYPTO_get_ex_data(&e->ex_data, idx); +} + +/* + * Functions to get/set an ENGINE's elements - mainly to avoid exposing the + * ENGINE structure itself. + */ + +int ENGINE_set_id(ENGINE *e, const char *id) +{ + if (id == NULL) { + ENGINEerr(ENGINE_F_ENGINE_SET_ID, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + e->id = id; + return 1; +} + +int ENGINE_set_name(ENGINE *e, const char *name) +{ + if (name == NULL) { + ENGINEerr(ENGINE_F_ENGINE_SET_NAME, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + e->name = name; + return 1; +} + +int ENGINE_set_destroy_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR destroy_f) +{ + e->destroy = destroy_f; + return 1; +} + +int ENGINE_set_init_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR init_f) +{ + e->init = init_f; + return 1; +} + +int ENGINE_set_finish_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR finish_f) +{ + e->finish = finish_f; + return 1; +} + +int ENGINE_set_ctrl_function(ENGINE *e, ENGINE_CTRL_FUNC_PTR ctrl_f) +{ + e->ctrl = ctrl_f; + return 1; +} + +int ENGINE_set_flags(ENGINE *e, int flags) +{ + e->flags = flags; + return 1; +} + +int ENGINE_set_cmd_defns(ENGINE *e, const ENGINE_CMD_DEFN *defns) +{ + e->cmd_defns = defns; + return 1; +} + +const char *ENGINE_get_id(const ENGINE *e) +{ + return e->id; +} + +const char *ENGINE_get_name(const ENGINE *e) +{ + return e->name; +} + +ENGINE_GEN_INT_FUNC_PTR ENGINE_get_destroy_function(const ENGINE *e) +{ + return e->destroy; +} + +ENGINE_GEN_INT_FUNC_PTR ENGINE_get_init_function(const ENGINE *e) +{ + return e->init; +} + +ENGINE_GEN_INT_FUNC_PTR ENGINE_get_finish_function(const ENGINE *e) +{ + return e->finish; +} + +ENGINE_CTRL_FUNC_PTR ENGINE_get_ctrl_function(const ENGINE *e) +{ + return e->ctrl; +} + +int ENGINE_get_flags(const ENGINE *e) +{ + return e->flags; +} + +const ENGINE_CMD_DEFN *ENGINE_get_cmd_defns(const ENGINE *e) +{ + return e->cmd_defns; +} + +/* + * eng_lib.o is pretty much linked into anything that touches ENGINE already, + * so put the "static_state" hack here. + */ + +static int internal_static_hack = 0; + +void *ENGINE_get_static_state(void) +{ + return &internal_static_hack; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_list.c b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_list.c new file mode 100644 index 000000000..45c339c54 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_list.c @@ -0,0 +1,349 @@ +/* + * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "eng_int.h" + +/* + * The linked-list of pointers to engine types. engine_list_head incorporates + * an implicit structural reference but engine_list_tail does not - the + * latter is a computational optimization and only points to something that + * is already pointed to by its predecessor in the list (or engine_list_head + * itself). In the same way, the use of the "prev" pointer in each ENGINE is + * to save excessive list iteration, it doesn't correspond to an extra + * structural reference. Hence, engine_list_head, and each non-null "next" + * pointer account for the list itself assuming exactly 1 structural + * reference on each list member. + */ +static ENGINE *engine_list_head = NULL; +static ENGINE *engine_list_tail = NULL; + +/* + * This cleanup function is only needed internally. If it should be called, + * we register it with the "engine_cleanup_int()" stack to be called during + * cleanup. + */ + +static void engine_list_cleanup(void) +{ + ENGINE *iterator = engine_list_head; + + while (iterator != NULL) { + ENGINE_remove(iterator); + iterator = engine_list_head; + } + return; +} + +/* + * These static functions starting with a lower case "engine_" always take + * place when global_engine_lock has been locked up. + */ +static int engine_list_add(ENGINE *e) +{ + int conflict = 0; + ENGINE *iterator = NULL; + + if (e == NULL) { + ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + iterator = engine_list_head; + while (iterator && !conflict) { + conflict = (strcmp(iterator->id, e->id) == 0); + iterator = iterator->next; + } + if (conflict) { + ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, ENGINE_R_CONFLICTING_ENGINE_ID); + return 0; + } + if (engine_list_head == NULL) { + /* We are adding to an empty list. */ + if (engine_list_tail) { + ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, ENGINE_R_INTERNAL_LIST_ERROR); + return 0; + } + engine_list_head = e; + e->prev = NULL; + /* + * The first time the list allocates, we should register the cleanup. + */ + engine_cleanup_add_last(engine_list_cleanup); + } else { + /* We are adding to the tail of an existing list. */ + if ((engine_list_tail == NULL) || (engine_list_tail->next != NULL)) { + ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, ENGINE_R_INTERNAL_LIST_ERROR); + return 0; + } + engine_list_tail->next = e; + e->prev = engine_list_tail; + } + /* + * Having the engine in the list assumes a structural reference. + */ + e->struct_ref++; + engine_ref_debug(e, 0, 1); + /* However it came to be, e is the last item in the list. */ + engine_list_tail = e; + e->next = NULL; + return 1; +} + +static int engine_list_remove(ENGINE *e) +{ + ENGINE *iterator; + + if (e == NULL) { + ENGINEerr(ENGINE_F_ENGINE_LIST_REMOVE, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + /* We need to check that e is in our linked list! */ + iterator = engine_list_head; + while (iterator && (iterator != e)) + iterator = iterator->next; + if (iterator == NULL) { + ENGINEerr(ENGINE_F_ENGINE_LIST_REMOVE, + ENGINE_R_ENGINE_IS_NOT_IN_LIST); + return 0; + } + /* un-link e from the chain. */ + if (e->next) + e->next->prev = e->prev; + if (e->prev) + e->prev->next = e->next; + /* Correct our head/tail if necessary. */ + if (engine_list_head == e) + engine_list_head = e->next; + if (engine_list_tail == e) + engine_list_tail = e->prev; + engine_free_util(e, 0); + return 1; +} + +/* Get the first/last "ENGINE" type available. */ +ENGINE *ENGINE_get_first(void) +{ + ENGINE *ret; + + if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) { + ENGINEerr(ENGINE_F_ENGINE_GET_FIRST, ERR_R_MALLOC_FAILURE); + return NULL; + } + + CRYPTO_THREAD_write_lock(global_engine_lock); + ret = engine_list_head; + if (ret) { + ret->struct_ref++; + engine_ref_debug(ret, 0, 1); + } + CRYPTO_THREAD_unlock(global_engine_lock); + return ret; +} + +ENGINE *ENGINE_get_last(void) +{ + ENGINE *ret; + + if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) { + ENGINEerr(ENGINE_F_ENGINE_GET_LAST, ERR_R_MALLOC_FAILURE); + return NULL; + } + + CRYPTO_THREAD_write_lock(global_engine_lock); + ret = engine_list_tail; + if (ret) { + ret->struct_ref++; + engine_ref_debug(ret, 0, 1); + } + CRYPTO_THREAD_unlock(global_engine_lock); + return ret; +} + +/* Iterate to the next/previous "ENGINE" type (NULL = end of the list). */ +ENGINE *ENGINE_get_next(ENGINE *e) +{ + ENGINE *ret = NULL; + if (e == NULL) { + ENGINEerr(ENGINE_F_ENGINE_GET_NEXT, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + CRYPTO_THREAD_write_lock(global_engine_lock); + ret = e->next; + if (ret) { + /* Return a valid structural reference to the next ENGINE */ + ret->struct_ref++; + engine_ref_debug(ret, 0, 1); + } + CRYPTO_THREAD_unlock(global_engine_lock); + /* Release the structural reference to the previous ENGINE */ + ENGINE_free(e); + return ret; +} + +ENGINE *ENGINE_get_prev(ENGINE *e) +{ + ENGINE *ret = NULL; + if (e == NULL) { + ENGINEerr(ENGINE_F_ENGINE_GET_PREV, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + CRYPTO_THREAD_write_lock(global_engine_lock); + ret = e->prev; + if (ret) { + /* Return a valid structural reference to the next ENGINE */ + ret->struct_ref++; + engine_ref_debug(ret, 0, 1); + } + CRYPTO_THREAD_unlock(global_engine_lock); + /* Release the structural reference to the previous ENGINE */ + ENGINE_free(e); + return ret; +} + +/* Add another "ENGINE" type into the list. */ +int ENGINE_add(ENGINE *e) +{ + int to_return = 1; + if (e == NULL) { + ENGINEerr(ENGINE_F_ENGINE_ADD, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if ((e->id == NULL) || (e->name == NULL)) { + ENGINEerr(ENGINE_F_ENGINE_ADD, ENGINE_R_ID_OR_NAME_MISSING); + return 0; + } + CRYPTO_THREAD_write_lock(global_engine_lock); + if (!engine_list_add(e)) { + ENGINEerr(ENGINE_F_ENGINE_ADD, ENGINE_R_INTERNAL_LIST_ERROR); + to_return = 0; + } + CRYPTO_THREAD_unlock(global_engine_lock); + return to_return; +} + +/* Remove an existing "ENGINE" type from the array. */ +int ENGINE_remove(ENGINE *e) +{ + int to_return = 1; + if (e == NULL) { + ENGINEerr(ENGINE_F_ENGINE_REMOVE, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + CRYPTO_THREAD_write_lock(global_engine_lock); + if (!engine_list_remove(e)) { + ENGINEerr(ENGINE_F_ENGINE_REMOVE, ENGINE_R_INTERNAL_LIST_ERROR); + to_return = 0; + } + CRYPTO_THREAD_unlock(global_engine_lock); + return to_return; +} + +static void engine_cpy(ENGINE *dest, const ENGINE *src) +{ + dest->id = src->id; + dest->name = src->name; +#ifndef OPENSSL_NO_RSA + dest->rsa_meth = src->rsa_meth; +#endif +#ifndef OPENSSL_NO_DSA + dest->dsa_meth = src->dsa_meth; +#endif +#ifndef OPENSSL_NO_DH + dest->dh_meth = src->dh_meth; +#endif +#ifndef OPENSSL_NO_EC + dest->ec_meth = src->ec_meth; +#endif + dest->rand_meth = src->rand_meth; + dest->ciphers = src->ciphers; + dest->digests = src->digests; + dest->pkey_meths = src->pkey_meths; + dest->destroy = src->destroy; + dest->init = src->init; + dest->finish = src->finish; + dest->ctrl = src->ctrl; + dest->load_privkey = src->load_privkey; + dest->load_pubkey = src->load_pubkey; + dest->cmd_defns = src->cmd_defns; + dest->flags = src->flags; +} + +ENGINE *ENGINE_by_id(const char *id) +{ + ENGINE *iterator; + char *load_dir = NULL; + if (id == NULL) { + ENGINEerr(ENGINE_F_ENGINE_BY_ID, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) { + ENGINEerr(ENGINE_F_ENGINE_BY_ID, ERR_R_MALLOC_FAILURE); + return NULL; + } + + CRYPTO_THREAD_write_lock(global_engine_lock); + iterator = engine_list_head; + while (iterator && (strcmp(id, iterator->id) != 0)) + iterator = iterator->next; + if (iterator != NULL) { + /* + * We need to return a structural reference. If this is an ENGINE + * type that returns copies, make a duplicate - otherwise increment + * the existing ENGINE's reference count. + */ + if (iterator->flags & ENGINE_FLAGS_BY_ID_COPY) { + ENGINE *cp = ENGINE_new(); + if (cp == NULL) + iterator = NULL; + else { + engine_cpy(cp, iterator); + iterator = cp; + } + } else { + iterator->struct_ref++; + engine_ref_debug(iterator, 0, 1); + } + } + CRYPTO_THREAD_unlock(global_engine_lock); + if (iterator != NULL) + return iterator; + /* + * Prevent infinite recursion if we're looking for the dynamic engine. + */ + if (strcmp(id, "dynamic")) { + if ((load_dir = ossl_safe_getenv("OPENSSL_ENGINES")) == NULL) + load_dir = ENGINESDIR; + iterator = ENGINE_by_id("dynamic"); + if (!iterator || !ENGINE_ctrl_cmd_string(iterator, "ID", id, 0) || + !ENGINE_ctrl_cmd_string(iterator, "DIR_LOAD", "2", 0) || + !ENGINE_ctrl_cmd_string(iterator, "DIR_ADD", + load_dir, 0) || + !ENGINE_ctrl_cmd_string(iterator, "LIST_ADD", "1", 0) || + !ENGINE_ctrl_cmd_string(iterator, "LOAD", NULL, 0)) + goto notfound; + return iterator; + } + notfound: + ENGINE_free(iterator); + ENGINEerr(ENGINE_F_ENGINE_BY_ID, ENGINE_R_NO_SUCH_ENGINE); + ERR_add_error_data(2, "id=", id); + return NULL; + /* EEK! Experimental code ends */ +} + +int ENGINE_up_ref(ENGINE *e) +{ + int i; + if (e == NULL) { + ENGINEerr(ENGINE_F_ENGINE_UP_REF, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + CRYPTO_UP_REF(&e->struct_ref, &i, global_engine_lock); + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_openssl.c b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_openssl.c new file mode 100644 index 000000000..f7ad7a5f4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_openssl.c @@ -0,0 +1,648 @@ +/* + * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include "internal/engine.h" +#include +#include +#include +#include +#include +#include + +#include +#include + +/* + * This testing gunk is implemented (and explained) lower down. It also + * assumes the application explicitly calls "ENGINE_load_openssl()" because + * this is no longer automatic in ENGINE_load_builtin_engines(). + */ +#define TEST_ENG_OPENSSL_RC4 +#ifndef OPENSSL_NO_STDIO +#define TEST_ENG_OPENSSL_PKEY +#endif +/* #define TEST_ENG_OPENSSL_HMAC */ +/* #define TEST_ENG_OPENSSL_HMAC_INIT */ +/* #define TEST_ENG_OPENSSL_RC4_OTHERS */ +#define TEST_ENG_OPENSSL_RC4_P_INIT +/* #define TEST_ENG_OPENSSL_RC4_P_CIPHER */ +#define TEST_ENG_OPENSSL_SHA +/* #define TEST_ENG_OPENSSL_SHA_OTHERS */ +/* #define TEST_ENG_OPENSSL_SHA_P_INIT */ +/* #define TEST_ENG_OPENSSL_SHA_P_UPDATE */ +/* #define TEST_ENG_OPENSSL_SHA_P_FINAL */ + +/* Now check what of those algorithms are actually enabled */ +#ifdef OPENSSL_NO_RC4 +# undef TEST_ENG_OPENSSL_RC4 +# undef TEST_ENG_OPENSSL_RC4_OTHERS +# undef TEST_ENG_OPENSSL_RC4_P_INIT +# undef TEST_ENG_OPENSSL_RC4_P_CIPHER +#endif + +static int openssl_destroy(ENGINE *e); + +#ifdef TEST_ENG_OPENSSL_RC4 +static int openssl_ciphers(ENGINE *e, const EVP_CIPHER **cipher, + const int **nids, int nid); +#endif +#ifdef TEST_ENG_OPENSSL_SHA +static int openssl_digests(ENGINE *e, const EVP_MD **digest, + const int **nids, int nid); +#endif + +#ifdef TEST_ENG_OPENSSL_PKEY +static EVP_PKEY *openssl_load_privkey(ENGINE *eng, const char *key_id, + UI_METHOD *ui_method, + void *callback_data); +#endif + +#ifdef TEST_ENG_OPENSSL_HMAC +static int ossl_register_hmac_meth(void); +static int ossl_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth, + const int **nids, int nid); +#endif + +/* The constants used when creating the ENGINE */ +static const char *engine_openssl_id = "openssl"; +static const char *engine_openssl_name = "Software engine support"; + +/* + * This internal function is used by ENGINE_openssl() and possibly by the + * "dynamic" ENGINE support too + */ +static int bind_helper(ENGINE *e) +{ + if (!ENGINE_set_id(e, engine_openssl_id) + || !ENGINE_set_name(e, engine_openssl_name) + || !ENGINE_set_destroy_function(e, openssl_destroy) +#ifndef TEST_ENG_OPENSSL_NO_ALGORITHMS +# ifndef OPENSSL_NO_RSA + || !ENGINE_set_RSA(e, RSA_get_default_method()) +# endif +# ifndef OPENSSL_NO_DSA + || !ENGINE_set_DSA(e, DSA_get_default_method()) +# endif +# ifndef OPENSSL_NO_EC + || !ENGINE_set_EC(e, EC_KEY_OpenSSL()) +# endif +# ifndef OPENSSL_NO_DH + || !ENGINE_set_DH(e, DH_get_default_method()) +# endif + || !ENGINE_set_RAND(e, RAND_OpenSSL()) +# ifdef TEST_ENG_OPENSSL_RC4 + || !ENGINE_set_ciphers(e, openssl_ciphers) +# endif +# ifdef TEST_ENG_OPENSSL_SHA + || !ENGINE_set_digests(e, openssl_digests) +# endif +#endif +#ifdef TEST_ENG_OPENSSL_PKEY + || !ENGINE_set_load_privkey_function(e, openssl_load_privkey) +#endif +#ifdef TEST_ENG_OPENSSL_HMAC + || !ossl_register_hmac_meth() + || !ENGINE_set_pkey_meths(e, ossl_pkey_meths) +#endif + ) + return 0; + /* + * If we add errors to this ENGINE, ensure the error handling is setup + * here + */ + /* openssl_load_error_strings(); */ + return 1; +} + +static ENGINE *engine_openssl(void) +{ + ENGINE *ret = ENGINE_new(); + if (ret == NULL) + return NULL; + if (!bind_helper(ret)) { + ENGINE_free(ret); + return NULL; + } + return ret; +} + +void engine_load_openssl_int(void) +{ + ENGINE *toadd = engine_openssl(); + if (!toadd) + return; + ENGINE_add(toadd); + /* + * If the "add" worked, it gets a structural reference. So either way, we + * release our just-created reference. + */ + ENGINE_free(toadd); + ERR_clear_error(); +} + +/* + * This stuff is needed if this ENGINE is being compiled into a + * self-contained shared-library. + */ +#ifdef ENGINE_DYNAMIC_SUPPORT +static int bind_fn(ENGINE *e, const char *id) +{ + if (id && (strcmp(id, engine_openssl_id) != 0)) + return 0; + if (!bind_helper(e)) + return 0; + return 1; +} + +IMPLEMENT_DYNAMIC_CHECK_FN() + IMPLEMENT_DYNAMIC_BIND_FN(bind_fn) +#endif /* ENGINE_DYNAMIC_SUPPORT */ +#ifdef TEST_ENG_OPENSSL_RC4 +/*- + * This section of code compiles an "alternative implementation" of two modes of + * RC4 into this ENGINE. The result is that EVP_CIPHER operation for "rc4" + * should under normal circumstances go via this support rather than the default + * EVP support. There are other symbols to tweak the testing; + * TEST_ENC_OPENSSL_RC4_OTHERS - print a one line message to stderr each time + * we're asked for a cipher we don't support (should not happen). + * TEST_ENG_OPENSSL_RC4_P_INIT - print a one line message to stderr each time + * the "init_key" handler is called. + * TEST_ENG_OPENSSL_RC4_P_CIPHER - ditto for the "cipher" handler. + */ +# include +# define TEST_RC4_KEY_SIZE 16 +typedef struct { + unsigned char key[TEST_RC4_KEY_SIZE]; + RC4_KEY ks; +} TEST_RC4_KEY; +# define test(ctx) ((TEST_RC4_KEY *)EVP_CIPHER_CTX_get_cipher_data(ctx)) +static int test_rc4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ +# ifdef TEST_ENG_OPENSSL_RC4_P_INIT + fprintf(stderr, "(TEST_ENG_OPENSSL_RC4) test_init_key() called\n"); +# endif + memcpy(&test(ctx)->key[0], key, EVP_CIPHER_CTX_key_length(ctx)); + RC4_set_key(&test(ctx)->ks, EVP_CIPHER_CTX_key_length(ctx), + test(ctx)->key); + return 1; +} + +static int test_rc4_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ +# ifdef TEST_ENG_OPENSSL_RC4_P_CIPHER + fprintf(stderr, "(TEST_ENG_OPENSSL_RC4) test_cipher() called\n"); +# endif + RC4(&test(ctx)->ks, inl, in, out); + return 1; +} + +static EVP_CIPHER *r4_cipher = NULL; +static const EVP_CIPHER *test_r4_cipher(void) +{ + if (r4_cipher == NULL) { + EVP_CIPHER *cipher; + + if ((cipher = EVP_CIPHER_meth_new(NID_rc4, 1, TEST_RC4_KEY_SIZE)) == NULL + || !EVP_CIPHER_meth_set_iv_length(cipher, 0) + || !EVP_CIPHER_meth_set_flags(cipher, EVP_CIPH_VARIABLE_LENGTH) + || !EVP_CIPHER_meth_set_init(cipher, test_rc4_init_key) + || !EVP_CIPHER_meth_set_do_cipher(cipher, test_rc4_cipher) + || !EVP_CIPHER_meth_set_impl_ctx_size(cipher, sizeof(TEST_RC4_KEY))) { + EVP_CIPHER_meth_free(cipher); + cipher = NULL; + } + r4_cipher = cipher; + } + return r4_cipher; +} +static void test_r4_cipher_destroy(void) +{ + EVP_CIPHER_meth_free(r4_cipher); + r4_cipher = NULL; +} + +static EVP_CIPHER *r4_40_cipher = NULL; +static const EVP_CIPHER *test_r4_40_cipher(void) +{ + if (r4_40_cipher == NULL) { + EVP_CIPHER *cipher; + + if ((cipher = EVP_CIPHER_meth_new(NID_rc4, 1, 5 /* 40 bits */)) == NULL + || !EVP_CIPHER_meth_set_iv_length(cipher, 0) + || !EVP_CIPHER_meth_set_flags(cipher, EVP_CIPH_VARIABLE_LENGTH) + || !EVP_CIPHER_meth_set_init(cipher, test_rc4_init_key) + || !EVP_CIPHER_meth_set_do_cipher(cipher, test_rc4_cipher) + || !EVP_CIPHER_meth_set_impl_ctx_size(cipher, sizeof(TEST_RC4_KEY))) { + EVP_CIPHER_meth_free(cipher); + cipher = NULL; + } + r4_40_cipher = cipher; + } + return r4_40_cipher; +} +static void test_r4_40_cipher_destroy(void) +{ + EVP_CIPHER_meth_free(r4_40_cipher); + r4_40_cipher = NULL; +} +static int test_cipher_nids(const int **nids) +{ + static int cipher_nids[4] = { 0, 0, 0, 0 }; + static int pos = 0; + static int init = 0; + + if (!init) { + const EVP_CIPHER *cipher; + if ((cipher = test_r4_cipher()) != NULL) + cipher_nids[pos++] = EVP_CIPHER_nid(cipher); + if ((cipher = test_r4_40_cipher()) != NULL) + cipher_nids[pos++] = EVP_CIPHER_nid(cipher); + cipher_nids[pos] = 0; + init = 1; + } + *nids = cipher_nids; + return pos; +} + +static int openssl_ciphers(ENGINE *e, const EVP_CIPHER **cipher, + const int **nids, int nid) +{ + if (!cipher) { + /* We are returning a list of supported nids */ + return test_cipher_nids(nids); + } + /* We are being asked for a specific cipher */ + if (nid == NID_rc4) + *cipher = test_r4_cipher(); + else if (nid == NID_rc4_40) + *cipher = test_r4_40_cipher(); + else { +# ifdef TEST_ENG_OPENSSL_RC4_OTHERS + fprintf(stderr, "(TEST_ENG_OPENSSL_RC4) returning NULL for " + "nid %d\n", nid); +# endif + *cipher = NULL; + return 0; + } + return 1; +} +#endif + +#ifdef TEST_ENG_OPENSSL_SHA +/* Much the same sort of comment as for TEST_ENG_OPENSSL_RC4 */ +# include + +static int test_sha1_init(EVP_MD_CTX *ctx) +{ +# ifdef TEST_ENG_OPENSSL_SHA_P_INIT + fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) test_sha1_init() called\n"); +# endif + return SHA1_Init(EVP_MD_CTX_md_data(ctx)); +} + +static int test_sha1_update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ +# ifdef TEST_ENG_OPENSSL_SHA_P_UPDATE + fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) test_sha1_update() called\n"); +# endif + return SHA1_Update(EVP_MD_CTX_md_data(ctx), data, count); +} + +static int test_sha1_final(EVP_MD_CTX *ctx, unsigned char *md) +{ +# ifdef TEST_ENG_OPENSSL_SHA_P_FINAL + fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) test_sha1_final() called\n"); +# endif + return SHA1_Final(md, EVP_MD_CTX_md_data(ctx)); +} + +static EVP_MD *sha1_md = NULL; +static const EVP_MD *test_sha_md(void) +{ + if (sha1_md == NULL) { + EVP_MD *md; + + if ((md = EVP_MD_meth_new(NID_sha1, NID_sha1WithRSAEncryption)) == NULL + || !EVP_MD_meth_set_result_size(md, SHA_DIGEST_LENGTH) + || !EVP_MD_meth_set_input_blocksize(md, SHA_CBLOCK) + || !EVP_MD_meth_set_app_datasize(md, + sizeof(EVP_MD *) + sizeof(SHA_CTX)) + || !EVP_MD_meth_set_flags(md, 0) + || !EVP_MD_meth_set_init(md, test_sha1_init) + || !EVP_MD_meth_set_update(md, test_sha1_update) + || !EVP_MD_meth_set_final(md, test_sha1_final)) { + EVP_MD_meth_free(md); + md = NULL; + } + sha1_md = md; + } + return sha1_md; +} +static void test_sha_md_destroy(void) +{ + EVP_MD_meth_free(sha1_md); + sha1_md = NULL; +} +static int test_digest_nids(const int **nids) +{ + static int digest_nids[2] = { 0, 0 }; + static int pos = 0; + static int init = 0; + + if (!init) { + const EVP_MD *md; + if ((md = test_sha_md()) != NULL) + digest_nids[pos++] = EVP_MD_type(md); + digest_nids[pos] = 0; + init = 1; + } + *nids = digest_nids; + return pos; +} + +static int openssl_digests(ENGINE *e, const EVP_MD **digest, + const int **nids, int nid) +{ + if (!digest) { + /* We are returning a list of supported nids */ + return test_digest_nids(nids); + } + /* We are being asked for a specific digest */ + if (nid == NID_sha1) + *digest = test_sha_md(); + else { +# ifdef TEST_ENG_OPENSSL_SHA_OTHERS + fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) returning NULL for " + "nid %d\n", nid); +# endif + *digest = NULL; + return 0; + } + return 1; +} +#endif + +#ifdef TEST_ENG_OPENSSL_PKEY +static EVP_PKEY *openssl_load_privkey(ENGINE *eng, const char *key_id, + UI_METHOD *ui_method, + void *callback_data) +{ + BIO *in; + EVP_PKEY *key; + fprintf(stderr, "(TEST_ENG_OPENSSL_PKEY)Loading Private key %s\n", + key_id); + in = BIO_new_file(key_id, "r"); + if (!in) + return NULL; + key = PEM_read_bio_PrivateKey(in, NULL, 0, NULL); + BIO_free(in); + return key; +} +#endif + +#ifdef TEST_ENG_OPENSSL_HMAC + +/* + * Experimental HMAC redirection implementation: mainly copied from + * hm_pmeth.c + */ + +/* HMAC pkey context structure */ + +typedef struct { + const EVP_MD *md; /* MD for HMAC use */ + ASN1_OCTET_STRING ktmp; /* Temp storage for key */ + HMAC_CTX *ctx; +} OSSL_HMAC_PKEY_CTX; + +static int ossl_hmac_init(EVP_PKEY_CTX *ctx) +{ + OSSL_HMAC_PKEY_CTX *hctx; + + if ((hctx = OPENSSL_zalloc(sizeof(*hctx))) == NULL) { + ENGINEerr(ENGINE_F_OSSL_HMAC_INIT, ERR_R_MALLOC_FAILURE); + return 0; + } + hctx->ktmp.type = V_ASN1_OCTET_STRING; + hctx->ctx = HMAC_CTX_new(); + if (hctx->ctx == NULL) { + OPENSSL_free(hctx); + return 0; + } + EVP_PKEY_CTX_set_data(ctx, hctx); + EVP_PKEY_CTX_set0_keygen_info(ctx, NULL, 0); +# ifdef TEST_ENG_OPENSSL_HMAC_INIT + fprintf(stderr, "(TEST_ENG_OPENSSL_HMAC) ossl_hmac_init() called\n"); +# endif + return 1; +} + +static void ossl_hmac_cleanup(EVP_PKEY_CTX *ctx); + +static int ossl_hmac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) +{ + OSSL_HMAC_PKEY_CTX *sctx, *dctx; + + /* allocate memory for dst->data and a new HMAC_CTX in dst->data->ctx */ + if (!ossl_hmac_init(dst)) + return 0; + sctx = EVP_PKEY_CTX_get_data(src); + dctx = EVP_PKEY_CTX_get_data(dst); + dctx->md = sctx->md; + if (!HMAC_CTX_copy(dctx->ctx, sctx->ctx)) + goto err; + if (sctx->ktmp.data) { + if (!ASN1_OCTET_STRING_set(&dctx->ktmp, + sctx->ktmp.data, sctx->ktmp.length)) + goto err; + } + return 1; +err: + /* release HMAC_CTX in dst->data->ctx and memory allocated for dst->data */ + ossl_hmac_cleanup(dst); + return 0; +} + +static void ossl_hmac_cleanup(EVP_PKEY_CTX *ctx) +{ + OSSL_HMAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx); + + if (hctx) { + HMAC_CTX_free(hctx->ctx); + OPENSSL_clear_free(hctx->ktmp.data, hctx->ktmp.length); + OPENSSL_free(hctx); + EVP_PKEY_CTX_set_data(ctx, NULL); + } +} + +static int ossl_hmac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) +{ + ASN1_OCTET_STRING *hkey = NULL; + OSSL_HMAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx); + if (!hctx->ktmp.data) + return 0; + hkey = ASN1_OCTET_STRING_dup(&hctx->ktmp); + if (!hkey) + return 0; + EVP_PKEY_assign(pkey, EVP_PKEY_HMAC, hkey); + + return 1; +} + +static int ossl_int_update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ + OSSL_HMAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(EVP_MD_CTX_pkey_ctx(ctx)); + if (!HMAC_Update(hctx->ctx, data, count)) + return 0; + return 1; +} + +static int ossl_hmac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx) +{ + EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT); + EVP_MD_CTX_set_update_fn(mctx, ossl_int_update); + return 1; +} + +static int ossl_hmac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, + size_t *siglen, EVP_MD_CTX *mctx) +{ + unsigned int hlen; + OSSL_HMAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx); + int l = EVP_MD_CTX_size(mctx); + + if (l < 0) + return 0; + *siglen = l; + if (!sig) + return 1; + + if (!HMAC_Final(hctx->ctx, sig, &hlen)) + return 0; + *siglen = (size_t)hlen; + return 1; +} + +static int ossl_hmac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) +{ + OSSL_HMAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx); + EVP_PKEY *pk; + ASN1_OCTET_STRING *key; + switch (type) { + + case EVP_PKEY_CTRL_SET_MAC_KEY: + if ((!p2 && p1 > 0) || (p1 < -1)) + return 0; + if (!ASN1_OCTET_STRING_set(&hctx->ktmp, p2, p1)) + return 0; + break; + + case EVP_PKEY_CTRL_MD: + hctx->md = p2; + break; + + case EVP_PKEY_CTRL_DIGESTINIT: + pk = EVP_PKEY_CTX_get0_pkey(ctx); + key = EVP_PKEY_get0(pk); + if (!HMAC_Init_ex(hctx->ctx, key->data, key->length, hctx->md, NULL)) + return 0; + break; + + default: + return -2; + + } + return 1; +} + +static int ossl_hmac_ctrl_str(EVP_PKEY_CTX *ctx, + const char *type, const char *value) +{ + if (!value) { + return 0; + } + if (strcmp(type, "key") == 0) { + void *p = (void *)value; + return ossl_hmac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, -1, p); + } + if (strcmp(type, "hexkey") == 0) { + unsigned char *key; + int r; + long keylen; + key = OPENSSL_hexstr2buf(value, &keylen); + if (!key) + return 0; + r = ossl_hmac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, keylen, key); + OPENSSL_free(key); + return r; + } + return -2; +} + +static EVP_PKEY_METHOD *ossl_hmac_meth; + +static int ossl_register_hmac_meth(void) +{ + EVP_PKEY_METHOD *meth; + meth = EVP_PKEY_meth_new(EVP_PKEY_HMAC, 0); + if (meth == NULL) + return 0; + EVP_PKEY_meth_set_init(meth, ossl_hmac_init); + EVP_PKEY_meth_set_copy(meth, ossl_hmac_copy); + EVP_PKEY_meth_set_cleanup(meth, ossl_hmac_cleanup); + + EVP_PKEY_meth_set_keygen(meth, 0, ossl_hmac_keygen); + + EVP_PKEY_meth_set_signctx(meth, ossl_hmac_signctx_init, + ossl_hmac_signctx); + + EVP_PKEY_meth_set_ctrl(meth, ossl_hmac_ctrl, ossl_hmac_ctrl_str); + ossl_hmac_meth = meth; + return 1; +} + +static int ossl_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth, + const int **nids, int nid) +{ + static int ossl_pkey_nids[] = { + EVP_PKEY_HMAC, + 0 + }; + if (!pmeth) { + *nids = ossl_pkey_nids; + return 1; + } + + if (nid == EVP_PKEY_HMAC) { + *pmeth = ossl_hmac_meth; + return 1; + } + + *pmeth = NULL; + return 0; +} + +#endif + +int openssl_destroy(ENGINE *e) +{ + test_sha_md_destroy(); +#ifdef TEST_ENG_OPENSSL_RC4 + test_r4_cipher_destroy(); + test_r4_40_cipher_destroy(); +#endif + return 1; +} + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_pkey.c b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_pkey.c new file mode 100644 index 000000000..305a648fe --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_pkey.c @@ -0,0 +1,140 @@ +/* + * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "eng_int.h" + +/* Basic get/set stuff */ + +int ENGINE_set_load_privkey_function(ENGINE *e, + ENGINE_LOAD_KEY_PTR loadpriv_f) +{ + e->load_privkey = loadpriv_f; + return 1; +} + +int ENGINE_set_load_pubkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpub_f) +{ + e->load_pubkey = loadpub_f; + return 1; +} + +int ENGINE_set_load_ssl_client_cert_function(ENGINE *e, + ENGINE_SSL_CLIENT_CERT_PTR + loadssl_f) +{ + e->load_ssl_client_cert = loadssl_f; + return 1; +} + +ENGINE_LOAD_KEY_PTR ENGINE_get_load_privkey_function(const ENGINE *e) +{ + return e->load_privkey; +} + +ENGINE_LOAD_KEY_PTR ENGINE_get_load_pubkey_function(const ENGINE *e) +{ + return e->load_pubkey; +} + +ENGINE_SSL_CLIENT_CERT_PTR ENGINE_get_ssl_client_cert_function(const ENGINE + *e) +{ + return e->load_ssl_client_cert; +} + +/* API functions to load public/private keys */ + +EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id, + UI_METHOD *ui_method, void *callback_data) +{ + EVP_PKEY *pkey; + + if (e == NULL) { + ENGINEerr(ENGINE_F_ENGINE_LOAD_PRIVATE_KEY, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + CRYPTO_THREAD_write_lock(global_engine_lock); + if (e->funct_ref == 0) { + CRYPTO_THREAD_unlock(global_engine_lock); + ENGINEerr(ENGINE_F_ENGINE_LOAD_PRIVATE_KEY, ENGINE_R_NOT_INITIALISED); + return 0; + } + CRYPTO_THREAD_unlock(global_engine_lock); + if (!e->load_privkey) { + ENGINEerr(ENGINE_F_ENGINE_LOAD_PRIVATE_KEY, + ENGINE_R_NO_LOAD_FUNCTION); + return 0; + } + pkey = e->load_privkey(e, key_id, ui_method, callback_data); + if (!pkey) { + ENGINEerr(ENGINE_F_ENGINE_LOAD_PRIVATE_KEY, + ENGINE_R_FAILED_LOADING_PRIVATE_KEY); + return 0; + } + return pkey; +} + +EVP_PKEY *ENGINE_load_public_key(ENGINE *e, const char *key_id, + UI_METHOD *ui_method, void *callback_data) +{ + EVP_PKEY *pkey; + + if (e == NULL) { + ENGINEerr(ENGINE_F_ENGINE_LOAD_PUBLIC_KEY, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + CRYPTO_THREAD_write_lock(global_engine_lock); + if (e->funct_ref == 0) { + CRYPTO_THREAD_unlock(global_engine_lock); + ENGINEerr(ENGINE_F_ENGINE_LOAD_PUBLIC_KEY, ENGINE_R_NOT_INITIALISED); + return 0; + } + CRYPTO_THREAD_unlock(global_engine_lock); + if (!e->load_pubkey) { + ENGINEerr(ENGINE_F_ENGINE_LOAD_PUBLIC_KEY, ENGINE_R_NO_LOAD_FUNCTION); + return 0; + } + pkey = e->load_pubkey(e, key_id, ui_method, callback_data); + if (!pkey) { + ENGINEerr(ENGINE_F_ENGINE_LOAD_PUBLIC_KEY, + ENGINE_R_FAILED_LOADING_PUBLIC_KEY); + return 0; + } + return pkey; +} + +int ENGINE_load_ssl_client_cert(ENGINE *e, SSL *s, + STACK_OF(X509_NAME) *ca_dn, X509 **pcert, + EVP_PKEY **ppkey, STACK_OF(X509) **pother, + UI_METHOD *ui_method, void *callback_data) +{ + + if (e == NULL) { + ENGINEerr(ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + CRYPTO_THREAD_write_lock(global_engine_lock); + if (e->funct_ref == 0) { + CRYPTO_THREAD_unlock(global_engine_lock); + ENGINEerr(ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT, + ENGINE_R_NOT_INITIALISED); + return 0; + } + CRYPTO_THREAD_unlock(global_engine_lock); + if (!e->load_ssl_client_cert) { + ENGINEerr(ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT, + ENGINE_R_NO_LOAD_FUNCTION); + return 0; + } + return e->load_ssl_client_cert(e, s, ca_dn, pcert, ppkey, pother, + ui_method, callback_data); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_rdrand.c b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_rdrand.c new file mode 100644 index 000000000..261e5debb --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_rdrand.c @@ -0,0 +1,97 @@ +/* + * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#include +#include +#include "internal/engine.h" +#include +#include +#include + +#if (defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ + defined(__x86_64) || defined(__x86_64__) || \ + defined(_M_AMD64) || defined (_M_X64)) && defined(OPENSSL_CPUID_OBJ) + +size_t OPENSSL_ia32_rdrand_bytes(unsigned char *buf, size_t len); + +static int get_random_bytes(unsigned char *buf, int num) +{ + if (num < 0) { + return 0; + } + + return (size_t)num == OPENSSL_ia32_rdrand_bytes(buf, (size_t)num); +} + +static int random_status(void) +{ + return 1; +} + +static RAND_METHOD rdrand_meth = { + NULL, /* seed */ + get_random_bytes, + NULL, /* cleanup */ + NULL, /* add */ + get_random_bytes, + random_status, +}; + +static int rdrand_init(ENGINE *e) +{ + return 1; +} + +static const char *engine_e_rdrand_id = "rdrand"; +static const char *engine_e_rdrand_name = "Intel RDRAND engine"; + +static int bind_helper(ENGINE *e) +{ + if (!ENGINE_set_id(e, engine_e_rdrand_id) || + !ENGINE_set_name(e, engine_e_rdrand_name) || + !ENGINE_set_flags(e, ENGINE_FLAGS_NO_REGISTER_ALL) || + !ENGINE_set_init_function(e, rdrand_init) || + !ENGINE_set_RAND(e, &rdrand_meth)) + return 0; + + return 1; +} + +static ENGINE *ENGINE_rdrand(void) +{ + ENGINE *ret = ENGINE_new(); + if (ret == NULL) + return NULL; + if (!bind_helper(ret)) { + ENGINE_free(ret); + return NULL; + } + return ret; +} + +void engine_load_rdrand_int(void) +{ + extern unsigned int OPENSSL_ia32cap_P[]; + + if (OPENSSL_ia32cap_P[1] & (1 << (62 - 32))) { + ENGINE *toadd = ENGINE_rdrand(); + if (!toadd) + return; + ENGINE_add(toadd); + ENGINE_free(toadd); + ERR_clear_error(); + } +} +#else +void engine_load_rdrand_int(void) +{ +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_table.c b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_table.c new file mode 100644 index 000000000..ac4b02fc1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/eng_table.c @@ -0,0 +1,308 @@ +/* + * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include +#include +#include "eng_int.h" + +/* The type of the items in the table */ +struct st_engine_pile { + /* The 'nid' of this algorithm/mode */ + int nid; + /* ENGINEs that implement this algorithm/mode. */ + STACK_OF(ENGINE) *sk; + /* The default ENGINE to perform this algorithm/mode. */ + ENGINE *funct; + /* + * Zero if 'sk' is newer than the cached 'funct', non-zero otherwise + */ + int uptodate; +}; + +/* The type exposed in eng_int.h */ +struct st_engine_table { + LHASH_OF(ENGINE_PILE) piles; +}; /* ENGINE_TABLE */ + +typedef struct st_engine_pile_doall { + engine_table_doall_cb *cb; + void *arg; +} ENGINE_PILE_DOALL; + +/* Global flags (ENGINE_TABLE_FLAG_***). */ +static unsigned int table_flags = 0; + +/* API function manipulating 'table_flags' */ +unsigned int ENGINE_get_table_flags(void) +{ + return table_flags; +} + +void ENGINE_set_table_flags(unsigned int flags) +{ + table_flags = flags; +} + +/* Internal functions for the "piles" hash table */ +static unsigned long engine_pile_hash(const ENGINE_PILE *c) +{ + return c->nid; +} + +static int engine_pile_cmp(const ENGINE_PILE *a, const ENGINE_PILE *b) +{ + return a->nid - b->nid; +} + +static int int_table_check(ENGINE_TABLE **t, int create) +{ + LHASH_OF(ENGINE_PILE) *lh; + + if (*t) + return 1; + if (!create) + return 0; + if ((lh = lh_ENGINE_PILE_new(engine_pile_hash, engine_pile_cmp)) == NULL) + return 0; + *t = (ENGINE_TABLE *)lh; + return 1; +} + +/* + * Privately exposed (via eng_int.h) functions for adding and/or removing + * ENGINEs from the implementation table + */ +int engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup, + ENGINE *e, const int *nids, int num_nids, + int setdefault) +{ + int ret = 0, added = 0; + ENGINE_PILE tmplate, *fnd; + CRYPTO_THREAD_write_lock(global_engine_lock); + if (!(*table)) + added = 1; + if (!int_table_check(table, 1)) + goto end; + if (added) + /* The cleanup callback needs to be added */ + engine_cleanup_add_first(cleanup); + while (num_nids--) { + tmplate.nid = *nids; + fnd = lh_ENGINE_PILE_retrieve(&(*table)->piles, &tmplate); + if (!fnd) { + fnd = OPENSSL_malloc(sizeof(*fnd)); + if (fnd == NULL) + goto end; + fnd->uptodate = 1; + fnd->nid = *nids; + fnd->sk = sk_ENGINE_new_null(); + if (!fnd->sk) { + OPENSSL_free(fnd); + goto end; + } + fnd->funct = NULL; + (void)lh_ENGINE_PILE_insert(&(*table)->piles, fnd); + if (lh_ENGINE_PILE_retrieve(&(*table)->piles, &tmplate) != fnd) { + sk_ENGINE_free(fnd->sk); + OPENSSL_free(fnd); + goto end; + } + } + /* A registration shouldn't add duplicate entries */ + (void)sk_ENGINE_delete_ptr(fnd->sk, e); + /* + * if 'setdefault', this ENGINE goes to the head of the list + */ + if (!sk_ENGINE_push(fnd->sk, e)) + goto end; + /* "touch" this ENGINE_PILE */ + fnd->uptodate = 0; + if (setdefault) { + if (!engine_unlocked_init(e)) { + ENGINEerr(ENGINE_F_ENGINE_TABLE_REGISTER, + ENGINE_R_INIT_FAILED); + goto end; + } + if (fnd->funct) + engine_unlocked_finish(fnd->funct, 0); + fnd->funct = e; + fnd->uptodate = 1; + } + nids++; + } + ret = 1; + end: + CRYPTO_THREAD_unlock(global_engine_lock); + return ret; +} + +static void int_unregister_cb(ENGINE_PILE *pile, ENGINE *e) +{ + int n; + /* Iterate the 'c->sk' stack removing any occurrence of 'e' */ + while ((n = sk_ENGINE_find(pile->sk, e)) >= 0) { + (void)sk_ENGINE_delete(pile->sk, n); + pile->uptodate = 0; + } + if (pile->funct == e) { + engine_unlocked_finish(e, 0); + pile->funct = NULL; + } +} + +IMPLEMENT_LHASH_DOALL_ARG(ENGINE_PILE, ENGINE); + +void engine_table_unregister(ENGINE_TABLE **table, ENGINE *e) +{ + CRYPTO_THREAD_write_lock(global_engine_lock); + if (int_table_check(table, 0)) + lh_ENGINE_PILE_doall_ENGINE(&(*table)->piles, int_unregister_cb, e); + CRYPTO_THREAD_unlock(global_engine_lock); +} + +static void int_cleanup_cb_doall(ENGINE_PILE *p) +{ + if (!p) + return; + sk_ENGINE_free(p->sk); + if (p->funct) + engine_unlocked_finish(p->funct, 0); + OPENSSL_free(p); +} + +void engine_table_cleanup(ENGINE_TABLE **table) +{ + CRYPTO_THREAD_write_lock(global_engine_lock); + if (*table) { + lh_ENGINE_PILE_doall(&(*table)->piles, int_cleanup_cb_doall); + lh_ENGINE_PILE_free(&(*table)->piles); + *table = NULL; + } + CRYPTO_THREAD_unlock(global_engine_lock); +} + +/* return a functional reference for a given 'nid' */ +#ifndef ENGINE_TABLE_DEBUG +ENGINE *engine_table_select(ENGINE_TABLE **table, int nid) +#else +ENGINE *engine_table_select_tmp(ENGINE_TABLE **table, int nid, const char *f, + int l) +#endif +{ + ENGINE *ret = NULL; + ENGINE_PILE tmplate, *fnd = NULL; + int initres, loop = 0; + + if (!(*table)) { +#ifdef ENGINE_TABLE_DEBUG + fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, nothing " + "registered!\n", f, l, nid); +#endif + return NULL; + } + ERR_set_mark(); + CRYPTO_THREAD_write_lock(global_engine_lock); + /* + * Check again inside the lock otherwise we could race against cleanup + * operations. But don't worry about a fprintf(stderr). + */ + if (!int_table_check(table, 0)) + goto end; + tmplate.nid = nid; + fnd = lh_ENGINE_PILE_retrieve(&(*table)->piles, &tmplate); + if (!fnd) + goto end; + if (fnd->funct && engine_unlocked_init(fnd->funct)) { +#ifdef ENGINE_TABLE_DEBUG + fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, using " + "ENGINE '%s' cached\n", f, l, nid, fnd->funct->id); +#endif + ret = fnd->funct; + goto end; + } + if (fnd->uptodate) { + ret = fnd->funct; + goto end; + } + trynext: + ret = sk_ENGINE_value(fnd->sk, loop++); + if (!ret) { +#ifdef ENGINE_TABLE_DEBUG + fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, no " + "registered implementations would initialise\n", f, l, nid); +#endif + goto end; + } + /* Try to initialise the ENGINE? */ + if ((ret->funct_ref > 0) || !(table_flags & ENGINE_TABLE_FLAG_NOINIT)) + initres = engine_unlocked_init(ret); + else + initres = 0; + if (initres) { + /* Update 'funct' */ + if ((fnd->funct != ret) && engine_unlocked_init(ret)) { + /* If there was a previous default we release it. */ + if (fnd->funct) + engine_unlocked_finish(fnd->funct, 0); + fnd->funct = ret; +#ifdef ENGINE_TABLE_DEBUG + fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, " + "setting default to '%s'\n", f, l, nid, ret->id); +#endif + } +#ifdef ENGINE_TABLE_DEBUG + fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, using " + "newly initialised '%s'\n", f, l, nid, ret->id); +#endif + goto end; + } + goto trynext; + end: + /* + * If it failed, it is unlikely to succeed again until some future + * registrations have taken place. In all cases, we cache. + */ + if (fnd) + fnd->uptodate = 1; +#ifdef ENGINE_TABLE_DEBUG + if (ret) + fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, caching " + "ENGINE '%s'\n", f, l, nid, ret->id); + else + fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, caching " + "'no matching ENGINE'\n", f, l, nid); +#endif + CRYPTO_THREAD_unlock(global_engine_lock); + /* + * Whatever happened, any failed init()s are not failures in this + * context, so clear our error state. + */ + ERR_pop_to_mark(); + return ret; +} + +/* Table enumeration */ + +static void int_dall(const ENGINE_PILE *pile, ENGINE_PILE_DOALL *dall) +{ + dall->cb(pile->nid, pile->sk, pile->funct, dall->arg); +} + +IMPLEMENT_LHASH_DOALL_ARG_CONST(ENGINE_PILE, ENGINE_PILE_DOALL); + +void engine_table_doall(ENGINE_TABLE *table, engine_table_doall_cb *cb, + void *arg) +{ + ENGINE_PILE_DOALL dall; + dall.cb = cb; + dall.arg = arg; + if (table) + lh_ENGINE_PILE_doall_ENGINE_PILE_DOALL(&table->piles, int_dall, &dall); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_asnmth.c b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_asnmth.c new file mode 100644 index 000000000..4bcc76136 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_asnmth.c @@ -0,0 +1,209 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "e_os.h" +#include "eng_int.h" +#include +#include "internal/asn1_int.h" + +/* + * If this symbol is defined then ENGINE_get_pkey_asn1_meth_engine(), the + * function that is used by EVP to hook in pkey_asn1_meth code and cache + * defaults (etc), will display brief debugging summaries to stderr with the + * 'nid'. + */ +/* #define ENGINE_PKEY_ASN1_METH_DEBUG */ + +static ENGINE_TABLE *pkey_asn1_meth_table = NULL; + +void ENGINE_unregister_pkey_asn1_meths(ENGINE *e) +{ + engine_table_unregister(&pkey_asn1_meth_table, e); +} + +static void engine_unregister_all_pkey_asn1_meths(void) +{ + engine_table_cleanup(&pkey_asn1_meth_table); +} + +int ENGINE_register_pkey_asn1_meths(ENGINE *e) +{ + if (e->pkey_asn1_meths) { + const int *nids; + int num_nids = e->pkey_asn1_meths(e, NULL, &nids, 0); + if (num_nids > 0) + return engine_table_register(&pkey_asn1_meth_table, + engine_unregister_all_pkey_asn1_meths, + e, nids, num_nids, 0); + } + return 1; +} + +void ENGINE_register_all_pkey_asn1_meths(void) +{ + ENGINE *e; + + for (e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) + ENGINE_register_pkey_asn1_meths(e); +} + +int ENGINE_set_default_pkey_asn1_meths(ENGINE *e) +{ + if (e->pkey_asn1_meths) { + const int *nids; + int num_nids = e->pkey_asn1_meths(e, NULL, &nids, 0); + if (num_nids > 0) + return engine_table_register(&pkey_asn1_meth_table, + engine_unregister_all_pkey_asn1_meths, + e, nids, num_nids, 1); + } + return 1; +} + +/* + * Exposed API function to get a functional reference from the implementation + * table (ie. try to get a functional reference from the tabled structural + * references) for a given pkey_asn1_meth 'nid' + */ +ENGINE *ENGINE_get_pkey_asn1_meth_engine(int nid) +{ + return engine_table_select(&pkey_asn1_meth_table, nid); +} + +/* + * Obtains a pkey_asn1_meth implementation from an ENGINE functional + * reference + */ +const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth(ENGINE *e, int nid) +{ + EVP_PKEY_ASN1_METHOD *ret; + ENGINE_PKEY_ASN1_METHS_PTR fn = ENGINE_get_pkey_asn1_meths(e); + if (!fn || !fn(e, &ret, NULL, nid)) { + ENGINEerr(ENGINE_F_ENGINE_GET_PKEY_ASN1_METH, + ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD); + return NULL; + } + return ret; +} + +/* Gets the pkey_asn1_meth callback from an ENGINE structure */ +ENGINE_PKEY_ASN1_METHS_PTR ENGINE_get_pkey_asn1_meths(const ENGINE *e) +{ + return e->pkey_asn1_meths; +} + +/* Sets the pkey_asn1_meth callback in an ENGINE structure */ +int ENGINE_set_pkey_asn1_meths(ENGINE *e, ENGINE_PKEY_ASN1_METHS_PTR f) +{ + e->pkey_asn1_meths = f; + return 1; +} + +/* + * Internal function to free up EVP_PKEY_ASN1_METHOD structures before an + * ENGINE is destroyed + */ + +void engine_pkey_asn1_meths_free(ENGINE *e) +{ + int i; + EVP_PKEY_ASN1_METHOD *pkm; + if (e->pkey_asn1_meths) { + const int *pknids; + int npknids; + npknids = e->pkey_asn1_meths(e, NULL, &pknids, 0); + for (i = 0; i < npknids; i++) { + if (e->pkey_asn1_meths(e, &pkm, NULL, pknids[i])) { + EVP_PKEY_asn1_free(pkm); + } + } + } +} + +/* + * Find a method based on a string. This does a linear search through all + * implemented algorithms. This is OK in practice because only a small number + * of algorithms are likely to be implemented in an engine and it is not used + * for speed critical operations. + */ + +const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth_str(ENGINE *e, + const char *str, + int len) +{ + int i, nidcount; + const int *nids; + EVP_PKEY_ASN1_METHOD *ameth; + if (!e->pkey_asn1_meths) + return NULL; + if (len == -1) + len = strlen(str); + nidcount = e->pkey_asn1_meths(e, NULL, &nids, 0); + for (i = 0; i < nidcount; i++) { + e->pkey_asn1_meths(e, &ameth, NULL, nids[i]); + if (((int)strlen(ameth->pem_str) == len) + && strncasecmp(ameth->pem_str, str, len) == 0) + return ameth; + } + return NULL; +} + +typedef struct { + ENGINE *e; + const EVP_PKEY_ASN1_METHOD *ameth; + const char *str; + int len; +} ENGINE_FIND_STR; + +static void look_str_cb(int nid, STACK_OF(ENGINE) *sk, ENGINE *def, void *arg) +{ + ENGINE_FIND_STR *lk = arg; + int i; + if (lk->ameth) + return; + for (i = 0; i < sk_ENGINE_num(sk); i++) { + ENGINE *e = sk_ENGINE_value(sk, i); + EVP_PKEY_ASN1_METHOD *ameth; + e->pkey_asn1_meths(e, &ameth, NULL, nid); + if (ameth != NULL + && ((int)strlen(ameth->pem_str) == lk->len) + && strncasecmp(ameth->pem_str, lk->str, lk->len) == 0) { + lk->e = e; + lk->ameth = ameth; + return; + } + } +} + +const EVP_PKEY_ASN1_METHOD *ENGINE_pkey_asn1_find_str(ENGINE **pe, + const char *str, + int len) +{ + ENGINE_FIND_STR fstr; + fstr.e = NULL; + fstr.ameth = NULL; + fstr.str = str; + fstr.len = len; + + if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) { + ENGINEerr(ENGINE_F_ENGINE_PKEY_ASN1_FIND_STR, ERR_R_MALLOC_FAILURE); + return NULL; + } + + CRYPTO_THREAD_write_lock(global_engine_lock); + engine_table_doall(pkey_asn1_meth_table, look_str_cb, &fstr); + /* If found obtain a structural reference to engine */ + if (fstr.e) { + fstr.e->struct_ref++; + engine_ref_debug(fstr.e, 0, 1); + } + *pe = fstr.e; + CRYPTO_THREAD_unlock(global_engine_lock); + return fstr.ameth; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_cipher.c b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_cipher.c new file mode 100644 index 000000000..faa967c47 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_cipher.c @@ -0,0 +1,91 @@ +/* + * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "eng_int.h" + +static ENGINE_TABLE *cipher_table = NULL; + +void ENGINE_unregister_ciphers(ENGINE *e) +{ + engine_table_unregister(&cipher_table, e); +} + +static void engine_unregister_all_ciphers(void) +{ + engine_table_cleanup(&cipher_table); +} + +int ENGINE_register_ciphers(ENGINE *e) +{ + if (e->ciphers) { + const int *nids; + int num_nids = e->ciphers(e, NULL, &nids, 0); + if (num_nids > 0) + return engine_table_register(&cipher_table, + engine_unregister_all_ciphers, e, + nids, num_nids, 0); + } + return 1; +} + +void ENGINE_register_all_ciphers(void) +{ + ENGINE *e; + + for (e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) + ENGINE_register_ciphers(e); +} + +int ENGINE_set_default_ciphers(ENGINE *e) +{ + if (e->ciphers) { + const int *nids; + int num_nids = e->ciphers(e, NULL, &nids, 0); + if (num_nids > 0) + return engine_table_register(&cipher_table, + engine_unregister_all_ciphers, e, + nids, num_nids, 1); + } + return 1; +} + +/* + * Exposed API function to get a functional reference from the implementation + * table (ie. try to get a functional reference from the tabled structural + * references) for a given cipher 'nid' + */ +ENGINE *ENGINE_get_cipher_engine(int nid) +{ + return engine_table_select(&cipher_table, nid); +} + +/* Obtains a cipher implementation from an ENGINE functional reference */ +const EVP_CIPHER *ENGINE_get_cipher(ENGINE *e, int nid) +{ + const EVP_CIPHER *ret; + ENGINE_CIPHERS_PTR fn = ENGINE_get_ciphers(e); + if (!fn || !fn(e, &ret, NULL, nid)) { + ENGINEerr(ENGINE_F_ENGINE_GET_CIPHER, ENGINE_R_UNIMPLEMENTED_CIPHER); + return NULL; + } + return ret; +} + +/* Gets the cipher callback from an ENGINE structure */ +ENGINE_CIPHERS_PTR ENGINE_get_ciphers(const ENGINE *e) +{ + return e->ciphers; +} + +/* Sets the cipher callback in an ENGINE structure */ +int ENGINE_set_ciphers(ENGINE *e, ENGINE_CIPHERS_PTR f) +{ + e->ciphers = f; + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_dh.c b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_dh.c new file mode 100644 index 000000000..785119f65 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_dh.c @@ -0,0 +1,72 @@ +/* + * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "eng_int.h" + +static ENGINE_TABLE *dh_table = NULL; +static const int dummy_nid = 1; + +void ENGINE_unregister_DH(ENGINE *e) +{ + engine_table_unregister(&dh_table, e); +} + +static void engine_unregister_all_DH(void) +{ + engine_table_cleanup(&dh_table); +} + +int ENGINE_register_DH(ENGINE *e) +{ + if (e->dh_meth) + return engine_table_register(&dh_table, + engine_unregister_all_DH, e, &dummy_nid, + 1, 0); + return 1; +} + +void ENGINE_register_all_DH(void) +{ + ENGINE *e; + + for (e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) + ENGINE_register_DH(e); +} + +int ENGINE_set_default_DH(ENGINE *e) +{ + if (e->dh_meth) + return engine_table_register(&dh_table, + engine_unregister_all_DH, e, &dummy_nid, + 1, 1); + return 1; +} + +/* + * Exposed API function to get a functional reference from the implementation + * table (ie. try to get a functional reference from the tabled structural + * references). + */ +ENGINE *ENGINE_get_default_DH(void) +{ + return engine_table_select(&dh_table, dummy_nid); +} + +/* Obtains an DH implementation from an ENGINE functional reference */ +const DH_METHOD *ENGINE_get_DH(const ENGINE *e) +{ + return e->dh_meth; +} + +/* Sets an DH implementation in an ENGINE structure */ +int ENGINE_set_DH(ENGINE *e, const DH_METHOD *dh_meth) +{ + e->dh_meth = dh_meth; + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_digest.c b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_digest.c new file mode 100644 index 000000000..d644b1b0a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_digest.c @@ -0,0 +1,91 @@ +/* + * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "eng_int.h" + +static ENGINE_TABLE *digest_table = NULL; + +void ENGINE_unregister_digests(ENGINE *e) +{ + engine_table_unregister(&digest_table, e); +} + +static void engine_unregister_all_digests(void) +{ + engine_table_cleanup(&digest_table); +} + +int ENGINE_register_digests(ENGINE *e) +{ + if (e->digests) { + const int *nids; + int num_nids = e->digests(e, NULL, &nids, 0); + if (num_nids > 0) + return engine_table_register(&digest_table, + engine_unregister_all_digests, e, + nids, num_nids, 0); + } + return 1; +} + +void ENGINE_register_all_digests(void) +{ + ENGINE *e; + + for (e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) + ENGINE_register_digests(e); +} + +int ENGINE_set_default_digests(ENGINE *e) +{ + if (e->digests) { + const int *nids; + int num_nids = e->digests(e, NULL, &nids, 0); + if (num_nids > 0) + return engine_table_register(&digest_table, + engine_unregister_all_digests, e, + nids, num_nids, 1); + } + return 1; +} + +/* + * Exposed API function to get a functional reference from the implementation + * table (ie. try to get a functional reference from the tabled structural + * references) for a given digest 'nid' + */ +ENGINE *ENGINE_get_digest_engine(int nid) +{ + return engine_table_select(&digest_table, nid); +} + +/* Obtains a digest implementation from an ENGINE functional reference */ +const EVP_MD *ENGINE_get_digest(ENGINE *e, int nid) +{ + const EVP_MD *ret; + ENGINE_DIGESTS_PTR fn = ENGINE_get_digests(e); + if (!fn || !fn(e, &ret, NULL, nid)) { + ENGINEerr(ENGINE_F_ENGINE_GET_DIGEST, ENGINE_R_UNIMPLEMENTED_DIGEST); + return NULL; + } + return ret; +} + +/* Gets the digest callback from an ENGINE structure */ +ENGINE_DIGESTS_PTR ENGINE_get_digests(const ENGINE *e) +{ + return e->digests; +} + +/* Sets the digest callback in an ENGINE structure */ +int ENGINE_set_digests(ENGINE *e, ENGINE_DIGESTS_PTR f) +{ + e->digests = f; + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_dsa.c b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_dsa.c new file mode 100644 index 000000000..65b6ea8d3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_dsa.c @@ -0,0 +1,72 @@ +/* + * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "eng_int.h" + +static ENGINE_TABLE *dsa_table = NULL; +static const int dummy_nid = 1; + +void ENGINE_unregister_DSA(ENGINE *e) +{ + engine_table_unregister(&dsa_table, e); +} + +static void engine_unregister_all_DSA(void) +{ + engine_table_cleanup(&dsa_table); +} + +int ENGINE_register_DSA(ENGINE *e) +{ + if (e->dsa_meth) + return engine_table_register(&dsa_table, + engine_unregister_all_DSA, e, &dummy_nid, + 1, 0); + return 1; +} + +void ENGINE_register_all_DSA(void) +{ + ENGINE *e; + + for (e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) + ENGINE_register_DSA(e); +} + +int ENGINE_set_default_DSA(ENGINE *e) +{ + if (e->dsa_meth) + return engine_table_register(&dsa_table, + engine_unregister_all_DSA, e, &dummy_nid, + 1, 1); + return 1; +} + +/* + * Exposed API function to get a functional reference from the implementation + * table (ie. try to get a functional reference from the tabled structural + * references). + */ +ENGINE *ENGINE_get_default_DSA(void) +{ + return engine_table_select(&dsa_table, dummy_nid); +} + +/* Obtains an DSA implementation from an ENGINE functional reference */ +const DSA_METHOD *ENGINE_get_DSA(const ENGINE *e) +{ + return e->dsa_meth; +} + +/* Sets an DSA implementation in an ENGINE structure */ +int ENGINE_set_DSA(ENGINE *e, const DSA_METHOD *dsa_meth) +{ + e->dsa_meth = dsa_meth; + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_eckey.c b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_eckey.c new file mode 100644 index 000000000..1e5073685 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_eckey.c @@ -0,0 +1,72 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "eng_int.h" + +static ENGINE_TABLE *dh_table = NULL; +static const int dummy_nid = 1; + +void ENGINE_unregister_EC(ENGINE *e) +{ + engine_table_unregister(&dh_table, e); +} + +static void engine_unregister_all_EC(void) +{ + engine_table_cleanup(&dh_table); +} + +int ENGINE_register_EC(ENGINE *e) +{ + if (e->ec_meth != NULL) + return engine_table_register(&dh_table, + engine_unregister_all_EC, e, &dummy_nid, + 1, 0); + return 1; +} + +void ENGINE_register_all_EC(void) +{ + ENGINE *e; + + for (e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) + ENGINE_register_EC(e); +} + +int ENGINE_set_default_EC(ENGINE *e) +{ + if (e->ec_meth != NULL) + return engine_table_register(&dh_table, + engine_unregister_all_EC, e, &dummy_nid, + 1, 1); + return 1; +} + +/* + * Exposed API function to get a functional reference from the implementation + * table (ie. try to get a functional reference from the tabled structural + * references). + */ +ENGINE *ENGINE_get_default_EC(void) +{ + return engine_table_select(&dh_table, dummy_nid); +} + +/* Obtains an EC_KEY implementation from an ENGINE functional reference */ +const EC_KEY_METHOD *ENGINE_get_EC(const ENGINE *e) +{ + return e->ec_meth; +} + +/* Sets an EC_KEY implementation in an ENGINE structure */ +int ENGINE_set_EC(ENGINE *e, const EC_KEY_METHOD *ec_meth) +{ + e->ec_meth = ec_meth; + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_pkmeth.c b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_pkmeth.c new file mode 100644 index 000000000..03cd1e69d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_pkmeth.c @@ -0,0 +1,114 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "eng_int.h" +#include + +static ENGINE_TABLE *pkey_meth_table = NULL; + +void ENGINE_unregister_pkey_meths(ENGINE *e) +{ + engine_table_unregister(&pkey_meth_table, e); +} + +static void engine_unregister_all_pkey_meths(void) +{ + engine_table_cleanup(&pkey_meth_table); +} + +int ENGINE_register_pkey_meths(ENGINE *e) +{ + if (e->pkey_meths) { + const int *nids; + int num_nids = e->pkey_meths(e, NULL, &nids, 0); + if (num_nids > 0) + return engine_table_register(&pkey_meth_table, + engine_unregister_all_pkey_meths, e, + nids, num_nids, 0); + } + return 1; +} + +void ENGINE_register_all_pkey_meths(void) +{ + ENGINE *e; + + for (e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) + ENGINE_register_pkey_meths(e); +} + +int ENGINE_set_default_pkey_meths(ENGINE *e) +{ + if (e->pkey_meths) { + const int *nids; + int num_nids = e->pkey_meths(e, NULL, &nids, 0); + if (num_nids > 0) + return engine_table_register(&pkey_meth_table, + engine_unregister_all_pkey_meths, e, + nids, num_nids, 1); + } + return 1; +} + +/* + * Exposed API function to get a functional reference from the implementation + * table (ie. try to get a functional reference from the tabled structural + * references) for a given pkey_meth 'nid' + */ +ENGINE *ENGINE_get_pkey_meth_engine(int nid) +{ + return engine_table_select(&pkey_meth_table, nid); +} + +/* Obtains a pkey_meth implementation from an ENGINE functional reference */ +const EVP_PKEY_METHOD *ENGINE_get_pkey_meth(ENGINE *e, int nid) +{ + EVP_PKEY_METHOD *ret; + ENGINE_PKEY_METHS_PTR fn = ENGINE_get_pkey_meths(e); + if (!fn || !fn(e, &ret, NULL, nid)) { + ENGINEerr(ENGINE_F_ENGINE_GET_PKEY_METH, + ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD); + return NULL; + } + return ret; +} + +/* Gets the pkey_meth callback from an ENGINE structure */ +ENGINE_PKEY_METHS_PTR ENGINE_get_pkey_meths(const ENGINE *e) +{ + return e->pkey_meths; +} + +/* Sets the pkey_meth callback in an ENGINE structure */ +int ENGINE_set_pkey_meths(ENGINE *e, ENGINE_PKEY_METHS_PTR f) +{ + e->pkey_meths = f; + return 1; +} + +/* + * Internal function to free up EVP_PKEY_METHOD structures before an ENGINE + * is destroyed + */ + +void engine_pkey_meths_free(ENGINE *e) +{ + int i; + EVP_PKEY_METHOD *pkm; + if (e->pkey_meths) { + const int *pknids; + int npknids; + npknids = e->pkey_meths(e, NULL, &pknids, 0); + for (i = 0; i < npknids; i++) { + if (e->pkey_meths(e, &pkm, NULL, pknids[i])) { + EVP_PKEY_meth_free(pkm); + } + } + } +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_rand.c b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_rand.c new file mode 100644 index 000000000..98a98073c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_rand.c @@ -0,0 +1,72 @@ +/* + * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "eng_int.h" + +static ENGINE_TABLE *rand_table = NULL; +static const int dummy_nid = 1; + +void ENGINE_unregister_RAND(ENGINE *e) +{ + engine_table_unregister(&rand_table, e); +} + +static void engine_unregister_all_RAND(void) +{ + engine_table_cleanup(&rand_table); +} + +int ENGINE_register_RAND(ENGINE *e) +{ + if (e->rand_meth) + return engine_table_register(&rand_table, + engine_unregister_all_RAND, e, + &dummy_nid, 1, 0); + return 1; +} + +void ENGINE_register_all_RAND(void) +{ + ENGINE *e; + + for (e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) + ENGINE_register_RAND(e); +} + +int ENGINE_set_default_RAND(ENGINE *e) +{ + if (e->rand_meth) + return engine_table_register(&rand_table, + engine_unregister_all_RAND, e, + &dummy_nid, 1, 1); + return 1; +} + +/* + * Exposed API function to get a functional reference from the implementation + * table (ie. try to get a functional reference from the tabled structural + * references). + */ +ENGINE *ENGINE_get_default_RAND(void) +{ + return engine_table_select(&rand_table, dummy_nid); +} + +/* Obtains an RAND implementation from an ENGINE functional reference */ +const RAND_METHOD *ENGINE_get_RAND(const ENGINE *e) +{ + return e->rand_meth; +} + +/* Sets an RAND implementation in an ENGINE structure */ +int ENGINE_set_RAND(ENGINE *e, const RAND_METHOD *rand_meth) +{ + e->rand_meth = rand_meth; + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_rsa.c b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_rsa.c new file mode 100644 index 000000000..d8d2e34f8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/engine/tb_rsa.c @@ -0,0 +1,72 @@ +/* + * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "eng_int.h" + +static ENGINE_TABLE *rsa_table = NULL; +static const int dummy_nid = 1; + +void ENGINE_unregister_RSA(ENGINE *e) +{ + engine_table_unregister(&rsa_table, e); +} + +static void engine_unregister_all_RSA(void) +{ + engine_table_cleanup(&rsa_table); +} + +int ENGINE_register_RSA(ENGINE *e) +{ + if (e->rsa_meth) + return engine_table_register(&rsa_table, + engine_unregister_all_RSA, e, &dummy_nid, + 1, 0); + return 1; +} + +void ENGINE_register_all_RSA(void) +{ + ENGINE *e; + + for (e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) + ENGINE_register_RSA(e); +} + +int ENGINE_set_default_RSA(ENGINE *e) +{ + if (e->rsa_meth) + return engine_table_register(&rsa_table, + engine_unregister_all_RSA, e, &dummy_nid, + 1, 1); + return 1; +} + +/* + * Exposed API function to get a functional reference from the implementation + * table (ie. try to get a functional reference from the tabled structural + * references). + */ +ENGINE *ENGINE_get_default_RSA(void) +{ + return engine_table_select(&rsa_table, dummy_nid); +} + +/* Obtains an RSA implementation from an ENGINE functional reference */ +const RSA_METHOD *ENGINE_get_RSA(const ENGINE *e) +{ + return e->rsa_meth; +} + +/* Sets an RSA implementation in an ENGINE structure */ +int ENGINE_set_RSA(ENGINE *e, const RSA_METHOD *rsa_meth) +{ + e->rsa_meth = rsa_meth; + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/err/README b/trunk/3rdparty/openssl-1.1-fit/crypto/err/README new file mode 100644 index 000000000..6d2ce0cd0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/err/README @@ -0,0 +1,44 @@ +Adding new libraries +-------------------- + +When adding a new sub-library to OpenSSL, assign it a library number +ERR_LIB_XXX, define a macro XXXerr() (both in err.h), add its +name to ERR_str_libraries[] (in crypto/err/err.c), and add +ERR_load_XXX_strings() to the ERR_load_crypto_strings() function +(in crypto/err/err_all.c). Finally, add an entry: + + L XXX xxx.h xxx_err.c + +to crypto/err/openssl.ec, and add xxx_err.c to the Makefile. +Running make errors will then generate a file xxx_err.c, and +add all error codes used in the library to xxx.h. + +Additionally the library include file must have a certain form. +Typically it will initially look like this: + + #ifndef HEADER_XXX_H + #define HEADER_XXX_H + + #ifdef __cplusplus + extern "C" { + #endif + + /* Include files */ + + #include + #include + + /* Macros, structures and function prototypes */ + + + /* BEGIN ERROR CODES */ + +The BEGIN ERROR CODES sequence is used by the error code +generation script as the point to place new error codes, any text +after this point will be overwritten when make errors is run. +The closing #endif etc will be automatically added by the script. + +The generated C error code file xxx_err.c will load the header +files stdio.h, openssl/err.h and openssl/xxx.h so the +header file must load any additional header files containing any +definitions it uses. diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/err/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/err/build.info new file mode 100644 index 000000000..6163d95b7 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/err/build.info @@ -0,0 +1,3 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + err.c err_all.c err_prn.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/err/err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/err/err.c new file mode 100644 index 000000000..c737b2a9c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/err/err.c @@ -0,0 +1,953 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "internal/cryptlib_int.h" +#include "internal/err.h" +#include "internal/err_int.h" +#include +#include +#include +#include +#include +#include "internal/thread_once.h" +#include "internal/ctype.h" +#include "internal/constant_time_locl.h" +#include "e_os.h" + +static int err_load_strings(const ERR_STRING_DATA *str); + +static void ERR_STATE_free(ERR_STATE *s); +#ifndef OPENSSL_NO_ERR +static ERR_STRING_DATA ERR_str_libraries[] = { + {ERR_PACK(ERR_LIB_NONE, 0, 0), "unknown library"}, + {ERR_PACK(ERR_LIB_SYS, 0, 0), "system library"}, + {ERR_PACK(ERR_LIB_BN, 0, 0), "bignum routines"}, + {ERR_PACK(ERR_LIB_RSA, 0, 0), "rsa routines"}, + {ERR_PACK(ERR_LIB_DH, 0, 0), "Diffie-Hellman routines"}, + {ERR_PACK(ERR_LIB_EVP, 0, 0), "digital envelope routines"}, + {ERR_PACK(ERR_LIB_BUF, 0, 0), "memory buffer routines"}, + {ERR_PACK(ERR_LIB_OBJ, 0, 0), "object identifier routines"}, + {ERR_PACK(ERR_LIB_PEM, 0, 0), "PEM routines"}, + {ERR_PACK(ERR_LIB_DSA, 0, 0), "dsa routines"}, + {ERR_PACK(ERR_LIB_X509, 0, 0), "x509 certificate routines"}, + {ERR_PACK(ERR_LIB_ASN1, 0, 0), "asn1 encoding routines"}, + {ERR_PACK(ERR_LIB_CONF, 0, 0), "configuration file routines"}, + {ERR_PACK(ERR_LIB_CRYPTO, 0, 0), "common libcrypto routines"}, + {ERR_PACK(ERR_LIB_EC, 0, 0), "elliptic curve routines"}, + {ERR_PACK(ERR_LIB_ECDSA, 0, 0), "ECDSA routines"}, + {ERR_PACK(ERR_LIB_ECDH, 0, 0), "ECDH routines"}, + {ERR_PACK(ERR_LIB_SSL, 0, 0), "SSL routines"}, + {ERR_PACK(ERR_LIB_BIO, 0, 0), "BIO routines"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, 0), "PKCS7 routines"}, + {ERR_PACK(ERR_LIB_X509V3, 0, 0), "X509 V3 routines"}, + {ERR_PACK(ERR_LIB_PKCS12, 0, 0), "PKCS12 routines"}, + {ERR_PACK(ERR_LIB_RAND, 0, 0), "random number generator"}, + {ERR_PACK(ERR_LIB_DSO, 0, 0), "DSO support routines"}, + {ERR_PACK(ERR_LIB_TS, 0, 0), "time stamp routines"}, + {ERR_PACK(ERR_LIB_ENGINE, 0, 0), "engine routines"}, + {ERR_PACK(ERR_LIB_OCSP, 0, 0), "OCSP routines"}, + {ERR_PACK(ERR_LIB_UI, 0, 0), "UI routines"}, + {ERR_PACK(ERR_LIB_FIPS, 0, 0), "FIPS routines"}, + {ERR_PACK(ERR_LIB_CMS, 0, 0), "CMS routines"}, + {ERR_PACK(ERR_LIB_HMAC, 0, 0), "HMAC routines"}, + {ERR_PACK(ERR_LIB_CT, 0, 0), "CT routines"}, + {ERR_PACK(ERR_LIB_ASYNC, 0, 0), "ASYNC routines"}, + {ERR_PACK(ERR_LIB_KDF, 0, 0), "KDF routines"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, 0, 0), "STORE routines"}, + {ERR_PACK(ERR_LIB_SM2, 0, 0), "SM2 routines"}, + {0, NULL}, +}; + +static ERR_STRING_DATA ERR_str_functs[] = { + {ERR_PACK(0, SYS_F_FOPEN, 0), "fopen"}, + {ERR_PACK(0, SYS_F_CONNECT, 0), "connect"}, + {ERR_PACK(0, SYS_F_GETSERVBYNAME, 0), "getservbyname"}, + {ERR_PACK(0, SYS_F_SOCKET, 0), "socket"}, + {ERR_PACK(0, SYS_F_IOCTLSOCKET, 0), "ioctlsocket"}, + {ERR_PACK(0, SYS_F_BIND, 0), "bind"}, + {ERR_PACK(0, SYS_F_LISTEN, 0), "listen"}, + {ERR_PACK(0, SYS_F_ACCEPT, 0), "accept"}, +# ifdef OPENSSL_SYS_WINDOWS + {ERR_PACK(0, SYS_F_WSASTARTUP, 0), "WSAstartup"}, +# endif + {ERR_PACK(0, SYS_F_OPENDIR, 0), "opendir"}, + {ERR_PACK(0, SYS_F_FREAD, 0), "fread"}, + {ERR_PACK(0, SYS_F_GETADDRINFO, 0), "getaddrinfo"}, + {ERR_PACK(0, SYS_F_GETNAMEINFO, 0), "getnameinfo"}, + {ERR_PACK(0, SYS_F_SETSOCKOPT, 0), "setsockopt"}, + {ERR_PACK(0, SYS_F_GETSOCKOPT, 0), "getsockopt"}, + {ERR_PACK(0, SYS_F_GETSOCKNAME, 0), "getsockname"}, + {ERR_PACK(0, SYS_F_GETHOSTBYNAME, 0), "gethostbyname"}, + {ERR_PACK(0, SYS_F_FFLUSH, 0), "fflush"}, + {ERR_PACK(0, SYS_F_OPEN, 0), "open"}, + {ERR_PACK(0, SYS_F_CLOSE, 0), "close"}, + {ERR_PACK(0, SYS_F_IOCTL, 0), "ioctl"}, + {ERR_PACK(0, SYS_F_STAT, 0), "stat"}, + {ERR_PACK(0, SYS_F_FCNTL, 0), "fcntl"}, + {ERR_PACK(0, SYS_F_FSTAT, 0), "fstat"}, + {0, NULL}, +}; + +static ERR_STRING_DATA ERR_str_reasons[] = { + {ERR_R_SYS_LIB, "system lib"}, + {ERR_R_BN_LIB, "BN lib"}, + {ERR_R_RSA_LIB, "RSA lib"}, + {ERR_R_DH_LIB, "DH lib"}, + {ERR_R_EVP_LIB, "EVP lib"}, + {ERR_R_BUF_LIB, "BUF lib"}, + {ERR_R_OBJ_LIB, "OBJ lib"}, + {ERR_R_PEM_LIB, "PEM lib"}, + {ERR_R_DSA_LIB, "DSA lib"}, + {ERR_R_X509_LIB, "X509 lib"}, + {ERR_R_ASN1_LIB, "ASN1 lib"}, + {ERR_R_EC_LIB, "EC lib"}, + {ERR_R_BIO_LIB, "BIO lib"}, + {ERR_R_PKCS7_LIB, "PKCS7 lib"}, + {ERR_R_X509V3_LIB, "X509V3 lib"}, + {ERR_R_ENGINE_LIB, "ENGINE lib"}, + {ERR_R_UI_LIB, "UI lib"}, + {ERR_R_OSSL_STORE_LIB, "STORE lib"}, + {ERR_R_ECDSA_LIB, "ECDSA lib"}, + + {ERR_R_NESTED_ASN1_ERROR, "nested asn1 error"}, + {ERR_R_MISSING_ASN1_EOS, "missing asn1 eos"}, + + {ERR_R_FATAL, "fatal"}, + {ERR_R_MALLOC_FAILURE, "malloc failure"}, + {ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED, + "called a function you should not call"}, + {ERR_R_PASSED_NULL_PARAMETER, "passed a null parameter"}, + {ERR_R_INTERNAL_ERROR, "internal error"}, + {ERR_R_DISABLED, "called a function that was disabled at compile-time"}, + {ERR_R_INIT_FAIL, "init fail"}, + {ERR_R_OPERATION_FAIL, "operation fail"}, + + {0, NULL}, +}; +#endif + +static CRYPTO_ONCE err_init = CRYPTO_ONCE_STATIC_INIT; +static int set_err_thread_local; +static CRYPTO_THREAD_LOCAL err_thread_local; + +static CRYPTO_ONCE err_string_init = CRYPTO_ONCE_STATIC_INIT; +static CRYPTO_RWLOCK *err_string_lock; + +static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *); + +/* + * The internal state + */ + +static LHASH_OF(ERR_STRING_DATA) *int_error_hash = NULL; +static int int_err_library_number = ERR_LIB_USER; + +static unsigned long get_error_values(int inc, int top, const char **file, + int *line, const char **data, + int *flags); + +static unsigned long err_string_data_hash(const ERR_STRING_DATA *a) +{ + unsigned long ret, l; + + l = a->error; + ret = l ^ ERR_GET_LIB(l) ^ ERR_GET_FUNC(l); + return (ret ^ ret % 19 * 13); +} + +static int err_string_data_cmp(const ERR_STRING_DATA *a, + const ERR_STRING_DATA *b) +{ + if (a->error == b->error) + return 0; + return a->error > b->error ? 1 : -1; +} + +static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *d) +{ + ERR_STRING_DATA *p = NULL; + + CRYPTO_THREAD_read_lock(err_string_lock); + p = lh_ERR_STRING_DATA_retrieve(int_error_hash, d); + CRYPTO_THREAD_unlock(err_string_lock); + + return p; +} + +#ifndef OPENSSL_NO_ERR +/* A measurement on Linux 2018-11-21 showed about 3.5kib */ +# define SPACE_SYS_STR_REASONS 4 * 1024 +# define NUM_SYS_STR_REASONS 127 + +static ERR_STRING_DATA SYS_str_reasons[NUM_SYS_STR_REASONS + 1]; +/* + * SYS_str_reasons is filled with copies of strerror() results at + * initialization. 'errno' values up to 127 should cover all usual errors, + * others will be displayed numerically by ERR_error_string. It is crucial + * that we have something for each reason code that occurs in + * ERR_str_reasons, or bogus reason strings will be returned for SYSerr(), + * which always gets an errno value and never one of those 'standard' reason + * codes. + */ + +static void build_SYS_str_reasons(void) +{ + /* OPENSSL_malloc cannot be used here, use static storage instead */ + static char strerror_pool[SPACE_SYS_STR_REASONS]; + char *cur = strerror_pool; + size_t cnt = 0; + static int init = 1; + int i; + int saveerrno = get_last_sys_error(); + + CRYPTO_THREAD_write_lock(err_string_lock); + if (!init) { + CRYPTO_THREAD_unlock(err_string_lock); + return; + } + + for (i = 1; i <= NUM_SYS_STR_REASONS; i++) { + ERR_STRING_DATA *str = &SYS_str_reasons[i - 1]; + + str->error = ERR_PACK(ERR_LIB_SYS, 0, i); + if (str->string == NULL) { + if (openssl_strerror_r(i, cur, sizeof(strerror_pool) - cnt)) { + size_t l = strlen(cur); + + str->string = cur; + cnt += l; + if (cnt > sizeof(strerror_pool)) + cnt = sizeof(strerror_pool); + cur += l; + + /* + * VMS has an unusual quirk of adding spaces at the end of + * some (most? all?) messages. Lets trim them off. + */ + while (ossl_isspace(cur[-1])) { + cur--; + cnt--; + } + *cur++ = '\0'; + cnt++; + } + } + if (str->string == NULL) + str->string = "unknown"; + } + + /* + * Now we still have SYS_str_reasons[NUM_SYS_STR_REASONS] = {0, NULL}, as + * required by ERR_load_strings. + */ + + init = 0; + + CRYPTO_THREAD_unlock(err_string_lock); + /* openssl_strerror_r could change errno, but we want to preserve it */ + set_sys_error(saveerrno); + err_load_strings(SYS_str_reasons); +} +#endif + +#define err_clear_data(p, i) \ + do { \ + if ((p)->err_data_flags[i] & ERR_TXT_MALLOCED) {\ + OPENSSL_free((p)->err_data[i]); \ + (p)->err_data[i] = NULL; \ + } \ + (p)->err_data_flags[i] = 0; \ + } while (0) + +#define err_clear(p, i) \ + do { \ + err_clear_data(p, i); \ + (p)->err_flags[i] = 0; \ + (p)->err_buffer[i] = 0; \ + (p)->err_file[i] = NULL; \ + (p)->err_line[i] = -1; \ + } while (0) + +static void ERR_STATE_free(ERR_STATE *s) +{ + int i; + + if (s == NULL) + return; + for (i = 0; i < ERR_NUM_ERRORS; i++) { + err_clear_data(s, i); + } + OPENSSL_free(s); +} + +DEFINE_RUN_ONCE_STATIC(do_err_strings_init) +{ + if (!OPENSSL_init_crypto(0, NULL)) + return 0; + err_string_lock = CRYPTO_THREAD_lock_new(); + if (err_string_lock == NULL) + return 0; + int_error_hash = lh_ERR_STRING_DATA_new(err_string_data_hash, + err_string_data_cmp); + if (int_error_hash == NULL) { + CRYPTO_THREAD_lock_free(err_string_lock); + err_string_lock = NULL; + return 0; + } + return 1; +} + +void err_cleanup(void) +{ + if (set_err_thread_local != 0) + CRYPTO_THREAD_cleanup_local(&err_thread_local); + CRYPTO_THREAD_lock_free(err_string_lock); + err_string_lock = NULL; + lh_ERR_STRING_DATA_free(int_error_hash); + int_error_hash = NULL; +} + +/* + * Legacy; pack in the library. + */ +static void err_patch(int lib, ERR_STRING_DATA *str) +{ + unsigned long plib = ERR_PACK(lib, 0, 0); + + for (; str->error != 0; str++) + str->error |= plib; +} + +/* + * Hash in |str| error strings. Assumes the URN_ONCE was done. + */ +static int err_load_strings(const ERR_STRING_DATA *str) +{ + CRYPTO_THREAD_write_lock(err_string_lock); + for (; str->error; str++) + (void)lh_ERR_STRING_DATA_insert(int_error_hash, + (ERR_STRING_DATA *)str); + CRYPTO_THREAD_unlock(err_string_lock); + return 1; +} + +int ERR_load_ERR_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (!RUN_ONCE(&err_string_init, do_err_strings_init)) + return 0; + + err_load_strings(ERR_str_libraries); + err_load_strings(ERR_str_reasons); + err_patch(ERR_LIB_SYS, ERR_str_functs); + err_load_strings(ERR_str_functs); + build_SYS_str_reasons(); +#endif + return 1; +} + +int ERR_load_strings(int lib, ERR_STRING_DATA *str) +{ + if (ERR_load_ERR_strings() == 0) + return 0; + + err_patch(lib, str); + err_load_strings(str); + return 1; +} + +int ERR_load_strings_const(const ERR_STRING_DATA *str) +{ + if (ERR_load_ERR_strings() == 0) + return 0; + err_load_strings(str); + return 1; +} + +int ERR_unload_strings(int lib, ERR_STRING_DATA *str) +{ + if (!RUN_ONCE(&err_string_init, do_err_strings_init)) + return 0; + + CRYPTO_THREAD_write_lock(err_string_lock); + /* + * We don't need to ERR_PACK the lib, since that was done (to + * the table) when it was loaded. + */ + for (; str->error; str++) + (void)lh_ERR_STRING_DATA_delete(int_error_hash, str); + CRYPTO_THREAD_unlock(err_string_lock); + + return 1; +} + +void err_free_strings_int(void) +{ + if (!RUN_ONCE(&err_string_init, do_err_strings_init)) + return; +} + +/********************************************************/ + +void ERR_put_error(int lib, int func, int reason, const char *file, int line) +{ + ERR_STATE *es; + +#ifdef _OSD_POSIX + /* + * In the BS2000-OSD POSIX subsystem, the compiler generates path names + * in the form "*POSIX(/etc/passwd)". This dirty hack strips them to + * something sensible. @@@ We shouldn't modify a const string, though. + */ + if (strncmp(file, "*POSIX(", sizeof("*POSIX(") - 1) == 0) { + char *end; + + /* Skip the "*POSIX(" prefix */ + file += sizeof("*POSIX(") - 1; + end = &file[strlen(file) - 1]; + if (*end == ')') + *end = '\0'; + /* Optional: use the basename of the path only. */ + if ((end = strrchr(file, '/')) != NULL) + file = &end[1]; + } +#endif + es = ERR_get_state(); + if (es == NULL) + return; + + es->top = (es->top + 1) % ERR_NUM_ERRORS; + if (es->top == es->bottom) + es->bottom = (es->bottom + 1) % ERR_NUM_ERRORS; + es->err_flags[es->top] = 0; + es->err_buffer[es->top] = ERR_PACK(lib, func, reason); + es->err_file[es->top] = file; + es->err_line[es->top] = line; + err_clear_data(es, es->top); +} + +void ERR_clear_error(void) +{ + int i; + ERR_STATE *es; + + es = ERR_get_state(); + if (es == NULL) + return; + + for (i = 0; i < ERR_NUM_ERRORS; i++) { + err_clear(es, i); + } + es->top = es->bottom = 0; +} + +unsigned long ERR_get_error(void) +{ + return get_error_values(1, 0, NULL, NULL, NULL, NULL); +} + +unsigned long ERR_get_error_line(const char **file, int *line) +{ + return get_error_values(1, 0, file, line, NULL, NULL); +} + +unsigned long ERR_get_error_line_data(const char **file, int *line, + const char **data, int *flags) +{ + return get_error_values(1, 0, file, line, data, flags); +} + +unsigned long ERR_peek_error(void) +{ + return get_error_values(0, 0, NULL, NULL, NULL, NULL); +} + +unsigned long ERR_peek_error_line(const char **file, int *line) +{ + return get_error_values(0, 0, file, line, NULL, NULL); +} + +unsigned long ERR_peek_error_line_data(const char **file, int *line, + const char **data, int *flags) +{ + return get_error_values(0, 0, file, line, data, flags); +} + +unsigned long ERR_peek_last_error(void) +{ + return get_error_values(0, 1, NULL, NULL, NULL, NULL); +} + +unsigned long ERR_peek_last_error_line(const char **file, int *line) +{ + return get_error_values(0, 1, file, line, NULL, NULL); +} + +unsigned long ERR_peek_last_error_line_data(const char **file, int *line, + const char **data, int *flags) +{ + return get_error_values(0, 1, file, line, data, flags); +} + +static unsigned long get_error_values(int inc, int top, const char **file, + int *line, const char **data, + int *flags) +{ + int i = 0; + ERR_STATE *es; + unsigned long ret; + + es = ERR_get_state(); + if (es == NULL) + return 0; + + if (inc && top) { + if (file) + *file = ""; + if (line) + *line = 0; + if (data) + *data = ""; + if (flags) + *flags = 0; + + return ERR_R_INTERNAL_ERROR; + } + + if (es->bottom == es->top) + return 0; + if (top) + i = es->top; /* last error */ + else + i = (es->bottom + 1) % ERR_NUM_ERRORS; /* first error */ + + ret = es->err_buffer[i]; + if (inc) { + es->bottom = i; + es->err_buffer[i] = 0; + } + + if (file != NULL && line != NULL) { + if (es->err_file[i] == NULL) { + *file = "NA"; + *line = 0; + } else { + *file = es->err_file[i]; + *line = es->err_line[i]; + } + } + + if (data == NULL) { + if (inc) { + err_clear_data(es, i); + } + } else { + if (es->err_data[i] == NULL) { + *data = ""; + if (flags != NULL) + *flags = 0; + } else { + *data = es->err_data[i]; + if (flags != NULL) + *flags = es->err_data_flags[i]; + } + } + return ret; +} + +void ERR_error_string_n(unsigned long e, char *buf, size_t len) +{ + char lsbuf[64], fsbuf[64], rsbuf[64]; + const char *ls, *fs, *rs; + unsigned long l, f, r; + + if (len == 0) + return; + + l = ERR_GET_LIB(e); + ls = ERR_lib_error_string(e); + if (ls == NULL) { + BIO_snprintf(lsbuf, sizeof(lsbuf), "lib(%lu)", l); + ls = lsbuf; + } + + fs = ERR_func_error_string(e); + f = ERR_GET_FUNC(e); + if (fs == NULL) { + BIO_snprintf(fsbuf, sizeof(fsbuf), "func(%lu)", f); + fs = fsbuf; + } + + rs = ERR_reason_error_string(e); + r = ERR_GET_REASON(e); + if (rs == NULL) { + BIO_snprintf(rsbuf, sizeof(rsbuf), "reason(%lu)", r); + rs = rsbuf; + } + + BIO_snprintf(buf, len, "error:%08lX:%s:%s:%s", e, ls, fs, rs); + if (strlen(buf) == len - 1) { + /* Didn't fit; use a minimal format. */ + BIO_snprintf(buf, len, "err:%lx:%lx:%lx:%lx", e, l, f, r); + } +} + +/* + * ERR_error_string_n should be used instead for ret != NULL as + * ERR_error_string cannot know how large the buffer is + */ +char *ERR_error_string(unsigned long e, char *ret) +{ + static char buf[256]; + + if (ret == NULL) + ret = buf; + ERR_error_string_n(e, ret, (int)sizeof(buf)); + return ret; +} + +const char *ERR_lib_error_string(unsigned long e) +{ + ERR_STRING_DATA d, *p; + unsigned long l; + + if (!RUN_ONCE(&err_string_init, do_err_strings_init)) { + return NULL; + } + + l = ERR_GET_LIB(e); + d.error = ERR_PACK(l, 0, 0); + p = int_err_get_item(&d); + return ((p == NULL) ? NULL : p->string); +} + +const char *ERR_func_error_string(unsigned long e) +{ + ERR_STRING_DATA d, *p; + unsigned long l, f; + + if (!RUN_ONCE(&err_string_init, do_err_strings_init)) { + return NULL; + } + + l = ERR_GET_LIB(e); + f = ERR_GET_FUNC(e); + d.error = ERR_PACK(l, f, 0); + p = int_err_get_item(&d); + return ((p == NULL) ? NULL : p->string); +} + +const char *ERR_reason_error_string(unsigned long e) +{ + ERR_STRING_DATA d, *p = NULL; + unsigned long l, r; + + if (!RUN_ONCE(&err_string_init, do_err_strings_init)) { + return NULL; + } + + l = ERR_GET_LIB(e); + r = ERR_GET_REASON(e); + d.error = ERR_PACK(l, 0, r); + p = int_err_get_item(&d); + if (!p) { + d.error = ERR_PACK(0, 0, r); + p = int_err_get_item(&d); + } + return ((p == NULL) ? NULL : p->string); +} + +void err_delete_thread_state(void) +{ + ERR_STATE *state = CRYPTO_THREAD_get_local(&err_thread_local); + if (state == NULL) + return; + + CRYPTO_THREAD_set_local(&err_thread_local, NULL); + ERR_STATE_free(state); +} + +#if OPENSSL_API_COMPAT < 0x10100000L +void ERR_remove_thread_state(void *dummy) +{ +} +#endif + +#if OPENSSL_API_COMPAT < 0x10000000L +void ERR_remove_state(unsigned long pid) +{ +} +#endif + +DEFINE_RUN_ONCE_STATIC(err_do_init) +{ + set_err_thread_local = 1; + return CRYPTO_THREAD_init_local(&err_thread_local, NULL); +} + +ERR_STATE *ERR_get_state(void) +{ + ERR_STATE *state; + int saveerrno = get_last_sys_error(); + + if (!OPENSSL_init_crypto(OPENSSL_INIT_BASE_ONLY, NULL)) + return NULL; + + if (!RUN_ONCE(&err_init, err_do_init)) + return NULL; + + state = CRYPTO_THREAD_get_local(&err_thread_local); + if (state == (ERR_STATE*)-1) + return NULL; + + if (state == NULL) { + if (!CRYPTO_THREAD_set_local(&err_thread_local, (ERR_STATE*)-1)) + return NULL; + + if ((state = OPENSSL_zalloc(sizeof(*state))) == NULL) { + CRYPTO_THREAD_set_local(&err_thread_local, NULL); + return NULL; + } + + if (!ossl_init_thread_start(OPENSSL_INIT_THREAD_ERR_STATE) + || !CRYPTO_THREAD_set_local(&err_thread_local, state)) { + ERR_STATE_free(state); + CRYPTO_THREAD_set_local(&err_thread_local, NULL); + return NULL; + } + + /* Ignore failures from these */ + OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); + } + + set_sys_error(saveerrno); + return state; +} + +/* + * err_shelve_state returns the current thread local error state + * and freezes the error module until err_unshelve_state is called. + */ +int err_shelve_state(void **state) +{ + int saveerrno = get_last_sys_error(); + + /* + * Note, at present our only caller is OPENSSL_init_crypto(), indirectly + * via ossl_init_load_crypto_nodelete(), by which point the requested + * "base" initialization has already been performed, so the below call is a + * NOOP, that re-enters OPENSSL_init_crypto() only to quickly return. + * + * If are no other valid callers of this function, the call below can be + * removed, avoiding the re-entry into OPENSSL_init_crypto(). If there are + * potential uses that are not from inside OPENSSL_init_crypto(), then this + * call is needed, but some care is required to make sure that the re-entry + * remains a NOOP. + */ + if (!OPENSSL_init_crypto(OPENSSL_INIT_BASE_ONLY, NULL)) + return 0; + + if (!RUN_ONCE(&err_init, err_do_init)) + return 0; + + *state = CRYPTO_THREAD_get_local(&err_thread_local); + if (!CRYPTO_THREAD_set_local(&err_thread_local, (ERR_STATE*)-1)) + return 0; + + set_sys_error(saveerrno); + return 1; +} + +/* + * err_unshelve_state restores the error state that was returned + * by err_shelve_state previously. + */ +void err_unshelve_state(void* state) +{ + if (state != (void*)-1) + CRYPTO_THREAD_set_local(&err_thread_local, (ERR_STATE*)state); +} + +int ERR_get_next_error_library(void) +{ + int ret; + + if (!RUN_ONCE(&err_string_init, do_err_strings_init)) + return 0; + + CRYPTO_THREAD_write_lock(err_string_lock); + ret = int_err_library_number++; + CRYPTO_THREAD_unlock(err_string_lock); + return ret; +} + +static int err_set_error_data_int(char *data, int flags) +{ + ERR_STATE *es; + int i; + + es = ERR_get_state(); + if (es == NULL) + return 0; + + i = es->top; + + err_clear_data(es, i); + es->err_data[i] = data; + es->err_data_flags[i] = flags; + + return 1; +} + +void ERR_set_error_data(char *data, int flags) +{ + /* + * This function is void so we cannot propagate the error return. Since it + * is also in the public API we can't change the return type. + */ + err_set_error_data_int(data, flags); +} + +void ERR_add_error_data(int num, ...) +{ + va_list args; + va_start(args, num); + ERR_add_error_vdata(num, args); + va_end(args); +} + +void ERR_add_error_vdata(int num, va_list args) +{ + int i, n, s; + char *str, *p, *a; + + s = 80; + if ((str = OPENSSL_malloc(s + 1)) == NULL) { + /* ERRerr(ERR_F_ERR_ADD_ERROR_VDATA, ERR_R_MALLOC_FAILURE); */ + return; + } + str[0] = '\0'; + + n = 0; + for (i = 0; i < num; i++) { + a = va_arg(args, char *); + if (a == NULL) + a = ""; + n += strlen(a); + if (n > s) { + s = n + 20; + p = OPENSSL_realloc(str, s + 1); + if (p == NULL) { + OPENSSL_free(str); + return; + } + str = p; + } + OPENSSL_strlcat(str, a, (size_t)s + 1); + } + if (!err_set_error_data_int(str, ERR_TXT_MALLOCED | ERR_TXT_STRING)) + OPENSSL_free(str); +} + +int ERR_set_mark(void) +{ + ERR_STATE *es; + + es = ERR_get_state(); + if (es == NULL) + return 0; + + if (es->bottom == es->top) + return 0; + es->err_flags[es->top] |= ERR_FLAG_MARK; + return 1; +} + +int ERR_pop_to_mark(void) +{ + ERR_STATE *es; + + es = ERR_get_state(); + if (es == NULL) + return 0; + + while (es->bottom != es->top + && (es->err_flags[es->top] & ERR_FLAG_MARK) == 0) { + err_clear(es, es->top); + es->top = es->top > 0 ? es->top - 1 : ERR_NUM_ERRORS - 1; + } + + if (es->bottom == es->top) + return 0; + es->err_flags[es->top] &= ~ERR_FLAG_MARK; + return 1; +} + +int ERR_clear_last_mark(void) +{ + ERR_STATE *es; + int top; + + es = ERR_get_state(); + if (es == NULL) + return 0; + + top = es->top; + while (es->bottom != top + && (es->err_flags[top] & ERR_FLAG_MARK) == 0) { + top = top > 0 ? top - 1 : ERR_NUM_ERRORS - 1; + } + + if (es->bottom == top) + return 0; + es->err_flags[top] &= ~ERR_FLAG_MARK; + return 1; +} + +#ifdef UINTPTR_T +# undef UINTPTR_T +#endif +/* + * uintptr_t is the answer, but unfortunately C89, current "least common + * denominator" doesn't define it. Most legacy platforms typedef it anyway, + * so that attempt to fill the gaps means that one would have to identify + * that track these gaps, which would be undesirable. Macro it is... + */ +#if defined(__VMS) && __INITIAL_POINTER_SIZE==64 +/* + * But we can't use size_t on VMS, because it adheres to sizeof(size_t)==4 + * even in 64-bit builds, which means that it won't work as mask. + */ +# define UINTPTR_T unsigned long long +#else +# define UINTPTR_T size_t +#endif + +void err_clear_last_constant_time(int clear) +{ + ERR_STATE *es; + int top; + + es = ERR_get_state(); + if (es == NULL) + return; + + top = es->top; + + es->err_flags[top] &= ~(0 - clear); + es->err_buffer[top] &= ~(0UL - clear); + es->err_file[top] = (const char *)((UINTPTR_T)es->err_file[top] & + ~((UINTPTR_T)0 - clear)); + es->err_line[top] |= 0 - clear; + + es->top = (top + ERR_NUM_ERRORS - clear) % ERR_NUM_ERRORS; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/err/err_all.c b/trunk/3rdparty/openssl-1.1-fit/crypto/err/err_all.c new file mode 100644 index 000000000..d9ec04b60 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/err/err_all.c @@ -0,0 +1,101 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/err_int.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "internal/dso.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int err_load_crypto_strings_int(void) +{ + if ( +#ifndef OPENSSL_NO_ERR + ERR_load_ERR_strings() == 0 || /* include error strings for SYSerr */ + ERR_load_BN_strings() == 0 || +# ifndef OPENSSL_NO_RSA + ERR_load_RSA_strings() == 0 || +# endif +# ifndef OPENSSL_NO_DH + ERR_load_DH_strings() == 0 || +# endif + ERR_load_EVP_strings() == 0 || + ERR_load_BUF_strings() == 0 || + ERR_load_OBJ_strings() == 0 || + ERR_load_PEM_strings() == 0 || +# ifndef OPENSSL_NO_DSA + ERR_load_DSA_strings() == 0 || +# endif + ERR_load_X509_strings() == 0 || + ERR_load_ASN1_strings() == 0 || + ERR_load_CONF_strings() == 0 || + ERR_load_CRYPTO_strings() == 0 || +# ifndef OPENSSL_NO_COMP + ERR_load_COMP_strings() == 0 || +# endif +# ifndef OPENSSL_NO_EC + ERR_load_EC_strings() == 0 || +# endif + /* skip ERR_load_SSL_strings() because it is not in this library */ + ERR_load_BIO_strings() == 0 || + ERR_load_PKCS7_strings() == 0 || + ERR_load_X509V3_strings() == 0 || + ERR_load_PKCS12_strings() == 0 || + ERR_load_RAND_strings() == 0 || + ERR_load_DSO_strings() == 0 || +# ifndef OPENSSL_NO_TS + ERR_load_TS_strings() == 0 || +# endif +# ifndef OPENSSL_NO_ENGINE + ERR_load_ENGINE_strings() == 0 || +# endif +# ifndef OPENSSL_NO_OCSP + ERR_load_OCSP_strings() == 0 || +# endif + ERR_load_UI_strings() == 0 || +# ifndef OPENSSL_NO_CMS + ERR_load_CMS_strings() == 0 || +# endif +# ifndef OPENSSL_NO_CT + ERR_load_CT_strings() == 0 || +# endif + ERR_load_ASYNC_strings() == 0 || +#endif + ERR_load_KDF_strings() == 0 || + ERR_load_OSSL_STORE_strings() == 0) + return 0; + + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/err/err_prn.c b/trunk/3rdparty/openssl-1.1-fit/crypto/err/err_prn.c new file mode 100644 index 000000000..c82e62947 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/err/err_prn.c @@ -0,0 +1,65 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include + +void ERR_print_errors_cb(int (*cb) (const char *str, size_t len, void *u), + void *u) +{ + unsigned long l; + char buf[256]; + char buf2[4096]; + const char *file, *data; + int line, flags; + /* + * We don't know what kind of thing CRYPTO_THREAD_ID is. Here is our best + * attempt to convert it into something we can print. + */ + union { + CRYPTO_THREAD_ID tid; + unsigned long ltid; + } tid; + + tid.ltid = 0; + tid.tid = CRYPTO_THREAD_get_current_id(); + + while ((l = ERR_get_error_line_data(&file, &line, &data, &flags)) != 0) { + ERR_error_string_n(l, buf, sizeof(buf)); + BIO_snprintf(buf2, sizeof(buf2), "%lu:%s:%s:%d:%s\n", tid.ltid, buf, + file, line, (flags & ERR_TXT_STRING) ? data : ""); + if (cb(buf2, strlen(buf2), u) <= 0) + break; /* abort outputting the error report */ + } +} + +static int print_bio(const char *str, size_t len, void *bp) +{ + return BIO_write((BIO *)bp, str, len); +} + +void ERR_print_errors(BIO *bp) +{ + ERR_print_errors_cb(print_bio, bp); +} + +#ifndef OPENSSL_NO_STDIO +void ERR_print_errors_fp(FILE *fp) +{ + BIO *bio = BIO_new_fp(fp, BIO_NOCLOSE); + if (bio == NULL) + return; + + ERR_print_errors_cb(print_bio, bio); + BIO_free(bio); +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/err/openssl.ec b/trunk/3rdparty/openssl-1.1-fit/crypto/err/openssl.ec new file mode 100644 index 000000000..3e092eae0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/err/openssl.ec @@ -0,0 +1,78 @@ +# configuration file for util/mkerr.pl + +# The INPUT HEADER is scanned for declarations +# LIBNAME INPUT HEADER ERROR-TABLE FILE +L ERR NONE NONE +L BN include/openssl/bn.h crypto/bn/bn_err.c +L RSA include/openssl/rsa.h crypto/rsa/rsa_err.c +L DH include/openssl/dh.h crypto/dh/dh_err.c +L EVP include/openssl/evp.h crypto/evp/evp_err.c +L BUF include/openssl/buffer.h crypto/buffer/buf_err.c +L OBJ include/openssl/objects.h crypto/objects/obj_err.c +L PEM include/openssl/pem.h crypto/pem/pem_err.c +L DSA include/openssl/dsa.h crypto/dsa/dsa_err.c +L X509 include/openssl/x509.h crypto/x509/x509_err.c +L ASN1 include/openssl/asn1.h crypto/asn1/asn1_err.c +L CONF include/openssl/conf.h crypto/conf/conf_err.c +L CRYPTO include/openssl/crypto.h crypto/cpt_err.c +L EC include/openssl/ec.h crypto/ec/ec_err.c +L SSL include/openssl/ssl.h ssl/ssl_err.c +L BIO include/openssl/bio.h crypto/bio/bio_err.c +L PKCS7 include/openssl/pkcs7.h crypto/pkcs7/pkcs7err.c +L X509V3 include/openssl/x509v3.h crypto/x509v3/v3err.c +L PKCS12 include/openssl/pkcs12.h crypto/pkcs12/pk12err.c +L RAND include/openssl/rand.h crypto/rand/rand_err.c +L DSO include/internal/dso.h crypto/dso/dso_err.c +L ENGINE include/openssl/engine.h crypto/engine/eng_err.c +L OCSP include/openssl/ocsp.h crypto/ocsp/ocsp_err.c +L UI include/openssl/ui.h crypto/ui/ui_err.c +L COMP include/openssl/comp.h crypto/comp/comp_err.c +L TS include/openssl/ts.h crypto/ts/ts_err.c +L CMS include/openssl/cms.h crypto/cms/cms_err.c +L CT include/openssl/ct.h crypto/ct/ct_err.c +L ASYNC include/openssl/async.h crypto/async/async_err.c +L KDF include/openssl/kdf.h crypto/kdf/kdf_err.c +L SM2 crypto/include/internal/sm2.h crypto/sm2/sm2_err.c +L OSSL_STORE include/openssl/store.h crypto/store/store_err.c + +# additional header files to be scanned for function names +L NONE include/openssl/x509_vfy.h NONE +L NONE crypto/ec/ec_lcl.h NONE +L NONE crypto/cms/cms_lcl.h NONE +L NONE crypto/ct/ct_locl.h NONE +L NONE ssl/ssl_locl.h NONE + +# SSL/TLS alerts +R SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010 +R SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020 +R SSL_R_TLSV1_ALERT_DECRYPTION_FAILED 1021 +R SSL_R_TLSV1_ALERT_RECORD_OVERFLOW 1022 +R SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE 1030 +R SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE 1040 +R SSL_R_SSLV3_ALERT_NO_CERTIFICATE 1041 +R SSL_R_SSLV3_ALERT_BAD_CERTIFICATE 1042 +R SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE 1043 +R SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED 1044 +R SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED 1045 +R SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN 1046 +R SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER 1047 +R SSL_R_TLSV1_ALERT_UNKNOWN_CA 1048 +R SSL_R_TLSV1_ALERT_ACCESS_DENIED 1049 +R SSL_R_TLSV1_ALERT_DECODE_ERROR 1050 +R SSL_R_TLSV1_ALERT_DECRYPT_ERROR 1051 +R SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION 1060 +R SSL_R_TLSV1_ALERT_PROTOCOL_VERSION 1070 +R SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY 1071 +R SSL_R_TLSV1_ALERT_INTERNAL_ERROR 1080 +R SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK 1086 +R SSL_R_TLSV1_ALERT_USER_CANCELLED 1090 +R SSL_R_TLSV1_ALERT_NO_RENEGOTIATION 1100 +R SSL_R_TLSV13_ALERT_MISSING_EXTENSION 1109 +R SSL_R_TLSV1_UNSUPPORTED_EXTENSION 1110 +R SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE 1111 +R SSL_R_TLSV1_UNRECOGNIZED_NAME 1112 +R SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE 1113 +R SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE 1114 +R TLS1_AD_UNKNOWN_PSK_IDENTITY 1115 +R SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED 1116 +R TLS1_AD_NO_APPLICATION_PROTOCOL 1120 diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/err/openssl.txt b/trunk/3rdparty/openssl-1.1-fit/crypto/err/openssl.txt new file mode 100644 index 000000000..feff1dccd --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/err/openssl.txt @@ -0,0 +1,3033 @@ +# Copyright 1999-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# Function codes +ASN1_F_A2D_ASN1_OBJECT:100:a2d_ASN1_OBJECT +ASN1_F_A2I_ASN1_INTEGER:102:a2i_ASN1_INTEGER +ASN1_F_A2I_ASN1_STRING:103:a2i_ASN1_STRING +ASN1_F_APPEND_EXP:176:append_exp +ASN1_F_ASN1_BIO_INIT:113:asn1_bio_init +ASN1_F_ASN1_BIT_STRING_SET_BIT:183:ASN1_BIT_STRING_set_bit +ASN1_F_ASN1_CB:177:asn1_cb +ASN1_F_ASN1_CHECK_TLEN:104:asn1_check_tlen +ASN1_F_ASN1_COLLECT:106:asn1_collect +ASN1_F_ASN1_D2I_EX_PRIMITIVE:108:asn1_d2i_ex_primitive +ASN1_F_ASN1_D2I_FP:109:ASN1_d2i_fp +ASN1_F_ASN1_D2I_READ_BIO:107:asn1_d2i_read_bio +ASN1_F_ASN1_DIGEST:184:ASN1_digest +ASN1_F_ASN1_DO_ADB:110:asn1_do_adb +ASN1_F_ASN1_DO_LOCK:233:asn1_do_lock +ASN1_F_ASN1_DUP:111:ASN1_dup +ASN1_F_ASN1_ENC_SAVE:115:asn1_enc_save +ASN1_F_ASN1_EX_C2I:204:asn1_ex_c2i +ASN1_F_ASN1_FIND_END:190:asn1_find_end +ASN1_F_ASN1_GENERALIZEDTIME_ADJ:216:ASN1_GENERALIZEDTIME_adj +ASN1_F_ASN1_GENERATE_V3:178:ASN1_generate_v3 +ASN1_F_ASN1_GET_INT64:224:asn1_get_int64 +ASN1_F_ASN1_GET_OBJECT:114:ASN1_get_object +ASN1_F_ASN1_GET_UINT64:225:asn1_get_uint64 +ASN1_F_ASN1_I2D_BIO:116:ASN1_i2d_bio +ASN1_F_ASN1_I2D_FP:117:ASN1_i2d_fp +ASN1_F_ASN1_ITEM_D2I_FP:206:ASN1_item_d2i_fp +ASN1_F_ASN1_ITEM_DUP:191:ASN1_item_dup +ASN1_F_ASN1_ITEM_EMBED_D2I:120:asn1_item_embed_d2i +ASN1_F_ASN1_ITEM_EMBED_NEW:121:asn1_item_embed_new +ASN1_F_ASN1_ITEM_FLAGS_I2D:118:asn1_item_flags_i2d +ASN1_F_ASN1_ITEM_I2D_BIO:192:ASN1_item_i2d_bio +ASN1_F_ASN1_ITEM_I2D_FP:193:ASN1_item_i2d_fp +ASN1_F_ASN1_ITEM_PACK:198:ASN1_item_pack +ASN1_F_ASN1_ITEM_SIGN:195:ASN1_item_sign +ASN1_F_ASN1_ITEM_SIGN_CTX:220:ASN1_item_sign_ctx +ASN1_F_ASN1_ITEM_UNPACK:199:ASN1_item_unpack +ASN1_F_ASN1_ITEM_VERIFY:197:ASN1_item_verify +ASN1_F_ASN1_MBSTRING_NCOPY:122:ASN1_mbstring_ncopy +ASN1_F_ASN1_OBJECT_NEW:123:ASN1_OBJECT_new +ASN1_F_ASN1_OUTPUT_DATA:214:asn1_output_data +ASN1_F_ASN1_PCTX_NEW:205:ASN1_PCTX_new +ASN1_F_ASN1_PRIMITIVE_NEW:119:asn1_primitive_new +ASN1_F_ASN1_SCTX_NEW:221:ASN1_SCTX_new +ASN1_F_ASN1_SIGN:128:ASN1_sign +ASN1_F_ASN1_STR2TYPE:179:asn1_str2type +ASN1_F_ASN1_STRING_GET_INT64:227:asn1_string_get_int64 +ASN1_F_ASN1_STRING_GET_UINT64:230:asn1_string_get_uint64 +ASN1_F_ASN1_STRING_SET:186:ASN1_STRING_set +ASN1_F_ASN1_STRING_TABLE_ADD:129:ASN1_STRING_TABLE_add +ASN1_F_ASN1_STRING_TO_BN:228:asn1_string_to_bn +ASN1_F_ASN1_STRING_TYPE_NEW:130:ASN1_STRING_type_new +ASN1_F_ASN1_TEMPLATE_EX_D2I:132:asn1_template_ex_d2i +ASN1_F_ASN1_TEMPLATE_NEW:133:asn1_template_new +ASN1_F_ASN1_TEMPLATE_NOEXP_D2I:131:asn1_template_noexp_d2i +ASN1_F_ASN1_TIME_ADJ:217:ASN1_TIME_adj +ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING:134:ASN1_TYPE_get_int_octetstring +ASN1_F_ASN1_TYPE_GET_OCTETSTRING:135:ASN1_TYPE_get_octetstring +ASN1_F_ASN1_UTCTIME_ADJ:218:ASN1_UTCTIME_adj +ASN1_F_ASN1_VERIFY:137:ASN1_verify +ASN1_F_B64_READ_ASN1:209:b64_read_asn1 +ASN1_F_B64_WRITE_ASN1:210:B64_write_ASN1 +ASN1_F_BIO_NEW_NDEF:208:BIO_new_NDEF +ASN1_F_BITSTR_CB:180:bitstr_cb +ASN1_F_BN_TO_ASN1_STRING:229:bn_to_asn1_string +ASN1_F_C2I_ASN1_BIT_STRING:189:c2i_ASN1_BIT_STRING +ASN1_F_C2I_ASN1_INTEGER:194:c2i_ASN1_INTEGER +ASN1_F_C2I_ASN1_OBJECT:196:c2i_ASN1_OBJECT +ASN1_F_C2I_IBUF:226:c2i_ibuf +ASN1_F_C2I_UINT64_INT:101:c2i_uint64_int +ASN1_F_COLLECT_DATA:140:collect_data +ASN1_F_D2I_ASN1_OBJECT:147:d2i_ASN1_OBJECT +ASN1_F_D2I_ASN1_UINTEGER:150:d2i_ASN1_UINTEGER +ASN1_F_D2I_AUTOPRIVATEKEY:207:d2i_AutoPrivateKey +ASN1_F_D2I_PRIVATEKEY:154:d2i_PrivateKey +ASN1_F_D2I_PUBLICKEY:155:d2i_PublicKey +ASN1_F_DO_BUF:142:do_buf +ASN1_F_DO_CREATE:124:do_create +ASN1_F_DO_DUMP:125:do_dump +ASN1_F_DO_TCREATE:222:do_tcreate +ASN1_F_I2A_ASN1_OBJECT:126:i2a_ASN1_OBJECT +ASN1_F_I2D_ASN1_BIO_STREAM:211:i2d_ASN1_bio_stream +ASN1_F_I2D_ASN1_OBJECT:143:i2d_ASN1_OBJECT +ASN1_F_I2D_DSA_PUBKEY:161:i2d_DSA_PUBKEY +ASN1_F_I2D_EC_PUBKEY:181:i2d_EC_PUBKEY +ASN1_F_I2D_PRIVATEKEY:163:i2d_PrivateKey +ASN1_F_I2D_PUBLICKEY:164:i2d_PublicKey +ASN1_F_I2D_RSA_PUBKEY:165:i2d_RSA_PUBKEY +ASN1_F_LONG_C2I:166:long_c2i +ASN1_F_NDEF_PREFIX:127:ndef_prefix +ASN1_F_NDEF_SUFFIX:136:ndef_suffix +ASN1_F_OID_MODULE_INIT:174:oid_module_init +ASN1_F_PARSE_TAGGING:182:parse_tagging +ASN1_F_PKCS5_PBE2_SET_IV:167:PKCS5_pbe2_set_iv +ASN1_F_PKCS5_PBE2_SET_SCRYPT:231:PKCS5_pbe2_set_scrypt +ASN1_F_PKCS5_PBE_SET:202:PKCS5_pbe_set +ASN1_F_PKCS5_PBE_SET0_ALGOR:215:PKCS5_pbe_set0_algor +ASN1_F_PKCS5_PBKDF2_SET:219:PKCS5_pbkdf2_set +ASN1_F_PKCS5_SCRYPT_SET:232:pkcs5_scrypt_set +ASN1_F_SMIME_READ_ASN1:212:SMIME_read_ASN1 +ASN1_F_SMIME_TEXT:213:SMIME_text +ASN1_F_STABLE_GET:138:stable_get +ASN1_F_STBL_MODULE_INIT:223:stbl_module_init +ASN1_F_UINT32_C2I:105:uint32_c2i +ASN1_F_UINT32_NEW:139:uint32_new +ASN1_F_UINT64_C2I:112:uint64_c2i +ASN1_F_UINT64_NEW:141:uint64_new +ASN1_F_X509_CRL_ADD0_REVOKED:169:X509_CRL_add0_revoked +ASN1_F_X509_INFO_NEW:170:X509_INFO_new +ASN1_F_X509_NAME_ENCODE:203:x509_name_encode +ASN1_F_X509_NAME_EX_D2I:158:x509_name_ex_d2i +ASN1_F_X509_NAME_EX_NEW:171:x509_name_ex_new +ASN1_F_X509_PKEY_NEW:173:X509_PKEY_new +ASYNC_F_ASYNC_CTX_NEW:100:async_ctx_new +ASYNC_F_ASYNC_INIT_THREAD:101:ASYNC_init_thread +ASYNC_F_ASYNC_JOB_NEW:102:async_job_new +ASYNC_F_ASYNC_PAUSE_JOB:103:ASYNC_pause_job +ASYNC_F_ASYNC_START_FUNC:104:async_start_func +ASYNC_F_ASYNC_START_JOB:105:ASYNC_start_job +ASYNC_F_ASYNC_WAIT_CTX_SET_WAIT_FD:106:ASYNC_WAIT_CTX_set_wait_fd +BIO_F_ACPT_STATE:100:acpt_state +BIO_F_ADDRINFO_WRAP:148:addrinfo_wrap +BIO_F_ADDR_STRINGS:134:addr_strings +BIO_F_BIO_ACCEPT:101:BIO_accept +BIO_F_BIO_ACCEPT_EX:137:BIO_accept_ex +BIO_F_BIO_ACCEPT_NEW:152:BIO_ACCEPT_new +BIO_F_BIO_ADDR_NEW:144:BIO_ADDR_new +BIO_F_BIO_BIND:147:BIO_bind +BIO_F_BIO_CALLBACK_CTRL:131:BIO_callback_ctrl +BIO_F_BIO_CONNECT:138:BIO_connect +BIO_F_BIO_CONNECT_NEW:153:BIO_CONNECT_new +BIO_F_BIO_CTRL:103:BIO_ctrl +BIO_F_BIO_GETS:104:BIO_gets +BIO_F_BIO_GET_HOST_IP:106:BIO_get_host_ip +BIO_F_BIO_GET_NEW_INDEX:102:BIO_get_new_index +BIO_F_BIO_GET_PORT:107:BIO_get_port +BIO_F_BIO_LISTEN:139:BIO_listen +BIO_F_BIO_LOOKUP:135:BIO_lookup +BIO_F_BIO_LOOKUP_EX:143:BIO_lookup_ex +BIO_F_BIO_MAKE_PAIR:121:bio_make_pair +BIO_F_BIO_METH_NEW:146:BIO_meth_new +BIO_F_BIO_NEW:108:BIO_new +BIO_F_BIO_NEW_DGRAM_SCTP:145:BIO_new_dgram_sctp +BIO_F_BIO_NEW_FILE:109:BIO_new_file +BIO_F_BIO_NEW_MEM_BUF:126:BIO_new_mem_buf +BIO_F_BIO_NREAD:123:BIO_nread +BIO_F_BIO_NREAD0:124:BIO_nread0 +BIO_F_BIO_NWRITE:125:BIO_nwrite +BIO_F_BIO_NWRITE0:122:BIO_nwrite0 +BIO_F_BIO_PARSE_HOSTSERV:136:BIO_parse_hostserv +BIO_F_BIO_PUTS:110:BIO_puts +BIO_F_BIO_READ:111:BIO_read +BIO_F_BIO_READ_EX:105:BIO_read_ex +BIO_F_BIO_READ_INTERN:120:bio_read_intern +BIO_F_BIO_SOCKET:140:BIO_socket +BIO_F_BIO_SOCKET_NBIO:142:BIO_socket_nbio +BIO_F_BIO_SOCK_INFO:141:BIO_sock_info +BIO_F_BIO_SOCK_INIT:112:BIO_sock_init +BIO_F_BIO_WRITE:113:BIO_write +BIO_F_BIO_WRITE_EX:119:BIO_write_ex +BIO_F_BIO_WRITE_INTERN:128:bio_write_intern +BIO_F_BUFFER_CTRL:114:buffer_ctrl +BIO_F_CONN_CTRL:127:conn_ctrl +BIO_F_CONN_STATE:115:conn_state +BIO_F_DGRAM_SCTP_NEW:149:dgram_sctp_new +BIO_F_DGRAM_SCTP_READ:132:dgram_sctp_read +BIO_F_DGRAM_SCTP_WRITE:133:dgram_sctp_write +BIO_F_DOAPR_OUTCH:150:doapr_outch +BIO_F_FILE_CTRL:116:file_ctrl +BIO_F_FILE_READ:130:file_read +BIO_F_LINEBUFFER_CTRL:129:linebuffer_ctrl +BIO_F_LINEBUFFER_NEW:151:linebuffer_new +BIO_F_MEM_WRITE:117:mem_write +BIO_F_NBIOF_NEW:154:nbiof_new +BIO_F_SLG_WRITE:155:slg_write +BIO_F_SSL_NEW:118:SSL_new +BN_F_BNRAND:127:bnrand +BN_F_BNRAND_RANGE:138:bnrand_range +BN_F_BN_BLINDING_CONVERT_EX:100:BN_BLINDING_convert_ex +BN_F_BN_BLINDING_CREATE_PARAM:128:BN_BLINDING_create_param +BN_F_BN_BLINDING_INVERT_EX:101:BN_BLINDING_invert_ex +BN_F_BN_BLINDING_NEW:102:BN_BLINDING_new +BN_F_BN_BLINDING_UPDATE:103:BN_BLINDING_update +BN_F_BN_BN2DEC:104:BN_bn2dec +BN_F_BN_BN2HEX:105:BN_bn2hex +BN_F_BN_COMPUTE_WNAF:142:bn_compute_wNAF +BN_F_BN_CTX_GET:116:BN_CTX_get +BN_F_BN_CTX_NEW:106:BN_CTX_new +BN_F_BN_CTX_START:129:BN_CTX_start +BN_F_BN_DIV:107:BN_div +BN_F_BN_DIV_RECP:130:BN_div_recp +BN_F_BN_EXP:123:BN_exp +BN_F_BN_EXPAND_INTERNAL:120:bn_expand_internal +BN_F_BN_GENCB_NEW:143:BN_GENCB_new +BN_F_BN_GENERATE_DSA_NONCE:140:BN_generate_dsa_nonce +BN_F_BN_GENERATE_PRIME_EX:141:BN_generate_prime_ex +BN_F_BN_GF2M_MOD:131:BN_GF2m_mod +BN_F_BN_GF2M_MOD_EXP:132:BN_GF2m_mod_exp +BN_F_BN_GF2M_MOD_MUL:133:BN_GF2m_mod_mul +BN_F_BN_GF2M_MOD_SOLVE_QUAD:134:BN_GF2m_mod_solve_quad +BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR:135:BN_GF2m_mod_solve_quad_arr +BN_F_BN_GF2M_MOD_SQR:136:BN_GF2m_mod_sqr +BN_F_BN_GF2M_MOD_SQRT:137:BN_GF2m_mod_sqrt +BN_F_BN_LSHIFT:145:BN_lshift +BN_F_BN_MOD_EXP2_MONT:118:BN_mod_exp2_mont +BN_F_BN_MOD_EXP_MONT:109:BN_mod_exp_mont +BN_F_BN_MOD_EXP_MONT_CONSTTIME:124:BN_mod_exp_mont_consttime +BN_F_BN_MOD_EXP_MONT_WORD:117:BN_mod_exp_mont_word +BN_F_BN_MOD_EXP_RECP:125:BN_mod_exp_recp +BN_F_BN_MOD_EXP_SIMPLE:126:BN_mod_exp_simple +BN_F_BN_MOD_INVERSE:110:BN_mod_inverse +BN_F_BN_MOD_INVERSE_NO_BRANCH:139:BN_mod_inverse_no_branch +BN_F_BN_MOD_LSHIFT_QUICK:119:BN_mod_lshift_quick +BN_F_BN_MOD_SQRT:121:BN_mod_sqrt +BN_F_BN_MONT_CTX_NEW:149:BN_MONT_CTX_new +BN_F_BN_MPI2BN:112:BN_mpi2bn +BN_F_BN_NEW:113:BN_new +BN_F_BN_POOL_GET:147:BN_POOL_get +BN_F_BN_RAND:114:BN_rand +BN_F_BN_RAND_RANGE:122:BN_rand_range +BN_F_BN_RECP_CTX_NEW:150:BN_RECP_CTX_new +BN_F_BN_RSHIFT:146:BN_rshift +BN_F_BN_SET_WORDS:144:bn_set_words +BN_F_BN_STACK_PUSH:148:BN_STACK_push +BN_F_BN_USUB:115:BN_usub +BUF_F_BUF_MEM_GROW:100:BUF_MEM_grow +BUF_F_BUF_MEM_GROW_CLEAN:105:BUF_MEM_grow_clean +BUF_F_BUF_MEM_NEW:101:BUF_MEM_new +CMS_F_CHECK_CONTENT:99:check_content +CMS_F_CMS_ADD0_CERT:164:CMS_add0_cert +CMS_F_CMS_ADD0_RECIPIENT_KEY:100:CMS_add0_recipient_key +CMS_F_CMS_ADD0_RECIPIENT_PASSWORD:165:CMS_add0_recipient_password +CMS_F_CMS_ADD1_RECEIPTREQUEST:158:CMS_add1_ReceiptRequest +CMS_F_CMS_ADD1_RECIPIENT_CERT:101:CMS_add1_recipient_cert +CMS_F_CMS_ADD1_SIGNER:102:CMS_add1_signer +CMS_F_CMS_ADD1_SIGNINGTIME:103:cms_add1_signingTime +CMS_F_CMS_COMPRESS:104:CMS_compress +CMS_F_CMS_COMPRESSEDDATA_CREATE:105:cms_CompressedData_create +CMS_F_CMS_COMPRESSEDDATA_INIT_BIO:106:cms_CompressedData_init_bio +CMS_F_CMS_COPY_CONTENT:107:cms_copy_content +CMS_F_CMS_COPY_MESSAGEDIGEST:108:cms_copy_messageDigest +CMS_F_CMS_DATA:109:CMS_data +CMS_F_CMS_DATAFINAL:110:CMS_dataFinal +CMS_F_CMS_DATAINIT:111:CMS_dataInit +CMS_F_CMS_DECRYPT:112:CMS_decrypt +CMS_F_CMS_DECRYPT_SET1_KEY:113:CMS_decrypt_set1_key +CMS_F_CMS_DECRYPT_SET1_PASSWORD:166:CMS_decrypt_set1_password +CMS_F_CMS_DECRYPT_SET1_PKEY:114:CMS_decrypt_set1_pkey +CMS_F_CMS_DIGESTALGORITHM_FIND_CTX:115:cms_DigestAlgorithm_find_ctx +CMS_F_CMS_DIGESTALGORITHM_INIT_BIO:116:cms_DigestAlgorithm_init_bio +CMS_F_CMS_DIGESTEDDATA_DO_FINAL:117:cms_DigestedData_do_final +CMS_F_CMS_DIGEST_VERIFY:118:CMS_digest_verify +CMS_F_CMS_ENCODE_RECEIPT:161:cms_encode_Receipt +CMS_F_CMS_ENCRYPT:119:CMS_encrypt +CMS_F_CMS_ENCRYPTEDCONTENT_INIT:179:cms_EncryptedContent_init +CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO:120:cms_EncryptedContent_init_bio +CMS_F_CMS_ENCRYPTEDDATA_DECRYPT:121:CMS_EncryptedData_decrypt +CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT:122:CMS_EncryptedData_encrypt +CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY:123:CMS_EncryptedData_set1_key +CMS_F_CMS_ENVELOPEDDATA_CREATE:124:CMS_EnvelopedData_create +CMS_F_CMS_ENVELOPEDDATA_INIT_BIO:125:cms_EnvelopedData_init_bio +CMS_F_CMS_ENVELOPED_DATA_INIT:126:cms_enveloped_data_init +CMS_F_CMS_ENV_ASN1_CTRL:171:cms_env_asn1_ctrl +CMS_F_CMS_FINAL:127:CMS_final +CMS_F_CMS_GET0_CERTIFICATE_CHOICES:128:cms_get0_certificate_choices +CMS_F_CMS_GET0_CONTENT:129:CMS_get0_content +CMS_F_CMS_GET0_ECONTENT_TYPE:130:cms_get0_econtent_type +CMS_F_CMS_GET0_ENVELOPED:131:cms_get0_enveloped +CMS_F_CMS_GET0_REVOCATION_CHOICES:132:cms_get0_revocation_choices +CMS_F_CMS_GET0_SIGNED:133:cms_get0_signed +CMS_F_CMS_MSGSIGDIGEST_ADD1:162:cms_msgSigDigest_add1 +CMS_F_CMS_RECEIPTREQUEST_CREATE0:159:CMS_ReceiptRequest_create0 +CMS_F_CMS_RECEIPT_VERIFY:160:cms_Receipt_verify +CMS_F_CMS_RECIPIENTINFO_DECRYPT:134:CMS_RecipientInfo_decrypt +CMS_F_CMS_RECIPIENTINFO_ENCRYPT:169:CMS_RecipientInfo_encrypt +CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT:178:cms_RecipientInfo_kari_encrypt +CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ALG:175:CMS_RecipientInfo_kari_get0_alg +CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ORIG_ID:173:\ + CMS_RecipientInfo_kari_get0_orig_id +CMS_F_CMS_RECIPIENTINFO_KARI_GET0_REKS:172:CMS_RecipientInfo_kari_get0_reks +CMS_F_CMS_RECIPIENTINFO_KARI_ORIG_ID_CMP:174:CMS_RecipientInfo_kari_orig_id_cmp +CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT:135:cms_RecipientInfo_kekri_decrypt +CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT:136:cms_RecipientInfo_kekri_encrypt +CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID:137:CMS_RecipientInfo_kekri_get0_id +CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP:138:CMS_RecipientInfo_kekri_id_cmp +CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP:139:CMS_RecipientInfo_ktri_cert_cmp +CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT:140:cms_RecipientInfo_ktri_decrypt +CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT:141:cms_RecipientInfo_ktri_encrypt +CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS:142:CMS_RecipientInfo_ktri_get0_algs +CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID:143:\ + CMS_RecipientInfo_ktri_get0_signer_id +CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT:167:cms_RecipientInfo_pwri_crypt +CMS_F_CMS_RECIPIENTINFO_SET0_KEY:144:CMS_RecipientInfo_set0_key +CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD:168:CMS_RecipientInfo_set0_password +CMS_F_CMS_RECIPIENTINFO_SET0_PKEY:145:CMS_RecipientInfo_set0_pkey +CMS_F_CMS_SD_ASN1_CTRL:170:cms_sd_asn1_ctrl +CMS_F_CMS_SET1_IAS:176:cms_set1_ias +CMS_F_CMS_SET1_KEYID:177:cms_set1_keyid +CMS_F_CMS_SET1_SIGNERIDENTIFIER:146:cms_set1_SignerIdentifier +CMS_F_CMS_SET_DETACHED:147:CMS_set_detached +CMS_F_CMS_SIGN:148:CMS_sign +CMS_F_CMS_SIGNED_DATA_INIT:149:cms_signed_data_init +CMS_F_CMS_SIGNERINFO_CONTENT_SIGN:150:cms_SignerInfo_content_sign +CMS_F_CMS_SIGNERINFO_SIGN:151:CMS_SignerInfo_sign +CMS_F_CMS_SIGNERINFO_VERIFY:152:CMS_SignerInfo_verify +CMS_F_CMS_SIGNERINFO_VERIFY_CERT:153:cms_signerinfo_verify_cert +CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT:154:CMS_SignerInfo_verify_content +CMS_F_CMS_SIGN_RECEIPT:163:CMS_sign_receipt +CMS_F_CMS_STREAM:155:CMS_stream +CMS_F_CMS_UNCOMPRESS:156:CMS_uncompress +CMS_F_CMS_VERIFY:157:CMS_verify +CMS_F_KEK_UNWRAP_KEY:180:kek_unwrap_key +COMP_F_BIO_ZLIB_FLUSH:99:bio_zlib_flush +COMP_F_BIO_ZLIB_NEW:100:bio_zlib_new +COMP_F_BIO_ZLIB_READ:101:bio_zlib_read +COMP_F_BIO_ZLIB_WRITE:102:bio_zlib_write +COMP_F_COMP_CTX_NEW:103:COMP_CTX_new +CONF_F_CONF_DUMP_FP:104:CONF_dump_fp +CONF_F_CONF_LOAD:100:CONF_load +CONF_F_CONF_LOAD_FP:103:CONF_load_fp +CONF_F_CONF_PARSE_LIST:119:CONF_parse_list +CONF_F_DEF_LOAD:120:def_load +CONF_F_DEF_LOAD_BIO:121:def_load_bio +CONF_F_GET_NEXT_FILE:107:get_next_file +CONF_F_MODULE_ADD:122:module_add +CONF_F_MODULE_INIT:115:module_init +CONF_F_MODULE_LOAD_DSO:117:module_load_dso +CONF_F_MODULE_RUN:118:module_run +CONF_F_NCONF_DUMP_BIO:105:NCONF_dump_bio +CONF_F_NCONF_DUMP_FP:106:NCONF_dump_fp +CONF_F_NCONF_GET_NUMBER_E:112:NCONF_get_number_e +CONF_F_NCONF_GET_SECTION:108:NCONF_get_section +CONF_F_NCONF_GET_STRING:109:NCONF_get_string +CONF_F_NCONF_LOAD:113:NCONF_load +CONF_F_NCONF_LOAD_BIO:110:NCONF_load_bio +CONF_F_NCONF_LOAD_FP:114:NCONF_load_fp +CONF_F_NCONF_NEW:111:NCONF_new +CONF_F_PROCESS_INCLUDE:116:process_include +CONF_F_SSL_MODULE_INIT:123:ssl_module_init +CONF_F_STR_COPY:101:str_copy +CRYPTO_F_CMAC_CTX_NEW:120:CMAC_CTX_new +CRYPTO_F_CRYPTO_DUP_EX_DATA:110:CRYPTO_dup_ex_data +CRYPTO_F_CRYPTO_FREE_EX_DATA:111:CRYPTO_free_ex_data +CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX:100:CRYPTO_get_ex_new_index +CRYPTO_F_CRYPTO_MEMDUP:115:CRYPTO_memdup +CRYPTO_F_CRYPTO_NEW_EX_DATA:112:CRYPTO_new_ex_data +CRYPTO_F_CRYPTO_OCB128_COPY_CTX:121:CRYPTO_ocb128_copy_ctx +CRYPTO_F_CRYPTO_OCB128_INIT:122:CRYPTO_ocb128_init +CRYPTO_F_CRYPTO_SET_EX_DATA:102:CRYPTO_set_ex_data +CRYPTO_F_FIPS_MODE_SET:109:FIPS_mode_set +CRYPTO_F_GET_AND_LOCK:113:get_and_lock +CRYPTO_F_OPENSSL_ATEXIT:114:OPENSSL_atexit +CRYPTO_F_OPENSSL_BUF2HEXSTR:117:OPENSSL_buf2hexstr +CRYPTO_F_OPENSSL_FOPEN:119:openssl_fopen +CRYPTO_F_OPENSSL_HEXSTR2BUF:118:OPENSSL_hexstr2buf +CRYPTO_F_OPENSSL_INIT_CRYPTO:116:OPENSSL_init_crypto +CRYPTO_F_OPENSSL_LH_NEW:126:OPENSSL_LH_new +CRYPTO_F_OPENSSL_SK_DEEP_COPY:127:OPENSSL_sk_deep_copy +CRYPTO_F_OPENSSL_SK_DUP:128:OPENSSL_sk_dup +CRYPTO_F_PKEY_HMAC_INIT:123:pkey_hmac_init +CRYPTO_F_PKEY_POLY1305_INIT:124:pkey_poly1305_init +CRYPTO_F_PKEY_SIPHASH_INIT:125:pkey_siphash_init +CRYPTO_F_SK_RESERVE:129:sk_reserve +CT_F_CTLOG_NEW:117:CTLOG_new +CT_F_CTLOG_NEW_FROM_BASE64:118:CTLOG_new_from_base64 +CT_F_CTLOG_NEW_FROM_CONF:119:ctlog_new_from_conf +CT_F_CTLOG_STORE_LOAD_CTX_NEW:122:ctlog_store_load_ctx_new +CT_F_CTLOG_STORE_LOAD_FILE:123:CTLOG_STORE_load_file +CT_F_CTLOG_STORE_LOAD_LOG:130:ctlog_store_load_log +CT_F_CTLOG_STORE_NEW:131:CTLOG_STORE_new +CT_F_CT_BASE64_DECODE:124:ct_base64_decode +CT_F_CT_POLICY_EVAL_CTX_NEW:133:CT_POLICY_EVAL_CTX_new +CT_F_CT_V1_LOG_ID_FROM_PKEY:125:ct_v1_log_id_from_pkey +CT_F_I2O_SCT:107:i2o_SCT +CT_F_I2O_SCT_LIST:108:i2o_SCT_LIST +CT_F_I2O_SCT_SIGNATURE:109:i2o_SCT_signature +CT_F_O2I_SCT:110:o2i_SCT +CT_F_O2I_SCT_LIST:111:o2i_SCT_LIST +CT_F_O2I_SCT_SIGNATURE:112:o2i_SCT_signature +CT_F_SCT_CTX_NEW:126:SCT_CTX_new +CT_F_SCT_CTX_VERIFY:128:SCT_CTX_verify +CT_F_SCT_NEW:100:SCT_new +CT_F_SCT_NEW_FROM_BASE64:127:SCT_new_from_base64 +CT_F_SCT_SET0_LOG_ID:101:SCT_set0_log_id +CT_F_SCT_SET1_EXTENSIONS:114:SCT_set1_extensions +CT_F_SCT_SET1_LOG_ID:115:SCT_set1_log_id +CT_F_SCT_SET1_SIGNATURE:116:SCT_set1_signature +CT_F_SCT_SET_LOG_ENTRY_TYPE:102:SCT_set_log_entry_type +CT_F_SCT_SET_SIGNATURE_NID:103:SCT_set_signature_nid +CT_F_SCT_SET_VERSION:104:SCT_set_version +DH_F_COMPUTE_KEY:102:compute_key +DH_F_DHPARAMS_PRINT_FP:101:DHparams_print_fp +DH_F_DH_BUILTIN_GENPARAMS:106:dh_builtin_genparams +DH_F_DH_CHECK_EX:121:DH_check_ex +DH_F_DH_CHECK_PARAMS_EX:122:DH_check_params_ex +DH_F_DH_CHECK_PUB_KEY_EX:123:DH_check_pub_key_ex +DH_F_DH_CMS_DECRYPT:114:dh_cms_decrypt +DH_F_DH_CMS_SET_PEERKEY:115:dh_cms_set_peerkey +DH_F_DH_CMS_SET_SHARED_INFO:116:dh_cms_set_shared_info +DH_F_DH_METH_DUP:117:DH_meth_dup +DH_F_DH_METH_NEW:118:DH_meth_new +DH_F_DH_METH_SET1_NAME:119:DH_meth_set1_name +DH_F_DH_NEW_BY_NID:104:DH_new_by_nid +DH_F_DH_NEW_METHOD:105:DH_new_method +DH_F_DH_PARAM_DECODE:107:dh_param_decode +DH_F_DH_PKEY_PUBLIC_CHECK:124:dh_pkey_public_check +DH_F_DH_PRIV_DECODE:110:dh_priv_decode +DH_F_DH_PRIV_ENCODE:111:dh_priv_encode +DH_F_DH_PUB_DECODE:108:dh_pub_decode +DH_F_DH_PUB_ENCODE:109:dh_pub_encode +DH_F_DO_DH_PRINT:100:do_dh_print +DH_F_GENERATE_KEY:103:generate_key +DH_F_PKEY_DH_CTRL_STR:120:pkey_dh_ctrl_str +DH_F_PKEY_DH_DERIVE:112:pkey_dh_derive +DH_F_PKEY_DH_INIT:125:pkey_dh_init +DH_F_PKEY_DH_KEYGEN:113:pkey_dh_keygen +DSA_F_DSAPARAMS_PRINT:100:DSAparams_print +DSA_F_DSAPARAMS_PRINT_FP:101:DSAparams_print_fp +DSA_F_DSA_BUILTIN_PARAMGEN:125:dsa_builtin_paramgen +DSA_F_DSA_BUILTIN_PARAMGEN2:126:dsa_builtin_paramgen2 +DSA_F_DSA_DO_SIGN:112:DSA_do_sign +DSA_F_DSA_DO_VERIFY:113:DSA_do_verify +DSA_F_DSA_METH_DUP:127:DSA_meth_dup +DSA_F_DSA_METH_NEW:128:DSA_meth_new +DSA_F_DSA_METH_SET1_NAME:129:DSA_meth_set1_name +DSA_F_DSA_NEW_METHOD:103:DSA_new_method +DSA_F_DSA_PARAM_DECODE:119:dsa_param_decode +DSA_F_DSA_PRINT_FP:105:DSA_print_fp +DSA_F_DSA_PRIV_DECODE:115:dsa_priv_decode +DSA_F_DSA_PRIV_ENCODE:116:dsa_priv_encode +DSA_F_DSA_PUB_DECODE:117:dsa_pub_decode +DSA_F_DSA_PUB_ENCODE:118:dsa_pub_encode +DSA_F_DSA_SIGN:106:DSA_sign +DSA_F_DSA_SIGN_SETUP:107:DSA_sign_setup +DSA_F_DSA_SIG_NEW:102:DSA_SIG_new +DSA_F_OLD_DSA_PRIV_DECODE:122:old_dsa_priv_decode +DSA_F_PKEY_DSA_CTRL:120:pkey_dsa_ctrl +DSA_F_PKEY_DSA_CTRL_STR:104:pkey_dsa_ctrl_str +DSA_F_PKEY_DSA_KEYGEN:121:pkey_dsa_keygen +DSO_F_DLFCN_BIND_FUNC:100:dlfcn_bind_func +DSO_F_DLFCN_LOAD:102:dlfcn_load +DSO_F_DLFCN_MERGER:130:dlfcn_merger +DSO_F_DLFCN_NAME_CONVERTER:123:dlfcn_name_converter +DSO_F_DLFCN_UNLOAD:103:dlfcn_unload +DSO_F_DL_BIND_FUNC:104:dl_bind_func +DSO_F_DL_LOAD:106:dl_load +DSO_F_DL_MERGER:131:dl_merger +DSO_F_DL_NAME_CONVERTER:124:dl_name_converter +DSO_F_DL_UNLOAD:107:dl_unload +DSO_F_DSO_BIND_FUNC:108:DSO_bind_func +DSO_F_DSO_CONVERT_FILENAME:126:DSO_convert_filename +DSO_F_DSO_CTRL:110:DSO_ctrl +DSO_F_DSO_FREE:111:DSO_free +DSO_F_DSO_GET_FILENAME:127:DSO_get_filename +DSO_F_DSO_GLOBAL_LOOKUP:139:DSO_global_lookup +DSO_F_DSO_LOAD:112:DSO_load +DSO_F_DSO_MERGE:132:DSO_merge +DSO_F_DSO_NEW_METHOD:113:DSO_new_method +DSO_F_DSO_PATHBYADDR:105:DSO_pathbyaddr +DSO_F_DSO_SET_FILENAME:129:DSO_set_filename +DSO_F_DSO_UP_REF:114:DSO_up_ref +DSO_F_VMS_BIND_SYM:115:vms_bind_sym +DSO_F_VMS_LOAD:116:vms_load +DSO_F_VMS_MERGER:133:vms_merger +DSO_F_VMS_UNLOAD:117:vms_unload +DSO_F_WIN32_BIND_FUNC:101:win32_bind_func +DSO_F_WIN32_GLOBALLOOKUP:142:win32_globallookup +DSO_F_WIN32_JOINER:135:win32_joiner +DSO_F_WIN32_LOAD:120:win32_load +DSO_F_WIN32_MERGER:134:win32_merger +DSO_F_WIN32_NAME_CONVERTER:125:win32_name_converter +DSO_F_WIN32_PATHBYADDR:109:* +DSO_F_WIN32_SPLITTER:136:win32_splitter +DSO_F_WIN32_UNLOAD:121:win32_unload +EC_F_BN_TO_FELEM:224:BN_to_felem +EC_F_D2I_ECPARAMETERS:144:d2i_ECParameters +EC_F_D2I_ECPKPARAMETERS:145:d2i_ECPKParameters +EC_F_D2I_ECPRIVATEKEY:146:d2i_ECPrivateKey +EC_F_DO_EC_KEY_PRINT:221:do_EC_KEY_print +EC_F_ECDH_CMS_DECRYPT:238:ecdh_cms_decrypt +EC_F_ECDH_CMS_SET_SHARED_INFO:239:ecdh_cms_set_shared_info +EC_F_ECDH_COMPUTE_KEY:246:ECDH_compute_key +EC_F_ECDH_SIMPLE_COMPUTE_KEY:257:ecdh_simple_compute_key +EC_F_ECDSA_DO_SIGN_EX:251:ECDSA_do_sign_ex +EC_F_ECDSA_DO_VERIFY:252:ECDSA_do_verify +EC_F_ECDSA_SIGN_EX:254:ECDSA_sign_ex +EC_F_ECDSA_SIGN_SETUP:248:ECDSA_sign_setup +EC_F_ECDSA_SIG_NEW:265:ECDSA_SIG_new +EC_F_ECDSA_VERIFY:253:ECDSA_verify +EC_F_ECD_ITEM_VERIFY:270:ecd_item_verify +EC_F_ECKEY_PARAM2TYPE:223:eckey_param2type +EC_F_ECKEY_PARAM_DECODE:212:eckey_param_decode +EC_F_ECKEY_PRIV_DECODE:213:eckey_priv_decode +EC_F_ECKEY_PRIV_ENCODE:214:eckey_priv_encode +EC_F_ECKEY_PUB_DECODE:215:eckey_pub_decode +EC_F_ECKEY_PUB_ENCODE:216:eckey_pub_encode +EC_F_ECKEY_TYPE2PARAM:220:eckey_type2param +EC_F_ECPARAMETERS_PRINT:147:ECParameters_print +EC_F_ECPARAMETERS_PRINT_FP:148:ECParameters_print_fp +EC_F_ECPKPARAMETERS_PRINT:149:ECPKParameters_print +EC_F_ECPKPARAMETERS_PRINT_FP:150:ECPKParameters_print_fp +EC_F_ECP_NISTZ256_GET_AFFINE:240:ecp_nistz256_get_affine +EC_F_ECP_NISTZ256_INV_MOD_ORD:275:ecp_nistz256_inv_mod_ord +EC_F_ECP_NISTZ256_MULT_PRECOMPUTE:243:ecp_nistz256_mult_precompute +EC_F_ECP_NISTZ256_POINTS_MUL:241:ecp_nistz256_points_mul +EC_F_ECP_NISTZ256_PRE_COMP_NEW:244:ecp_nistz256_pre_comp_new +EC_F_ECP_NISTZ256_WINDOWED_MUL:242:ecp_nistz256_windowed_mul +EC_F_ECX_KEY_OP:266:ecx_key_op +EC_F_ECX_PRIV_ENCODE:267:ecx_priv_encode +EC_F_ECX_PUB_ENCODE:268:ecx_pub_encode +EC_F_EC_ASN1_GROUP2CURVE:153:ec_asn1_group2curve +EC_F_EC_ASN1_GROUP2FIELDID:154:ec_asn1_group2fieldid +EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY:208:ec_GF2m_montgomery_point_multiply +EC_F_EC_GF2M_SIMPLE_FIELD_INV:296:ec_GF2m_simple_field_inv +EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT:159:\ + ec_GF2m_simple_group_check_discriminant +EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE:195:ec_GF2m_simple_group_set_curve +EC_F_EC_GF2M_SIMPLE_LADDER_POST:285:ec_GF2m_simple_ladder_post +EC_F_EC_GF2M_SIMPLE_LADDER_PRE:288:ec_GF2m_simple_ladder_pre +EC_F_EC_GF2M_SIMPLE_OCT2POINT:160:ec_GF2m_simple_oct2point +EC_F_EC_GF2M_SIMPLE_POINT2OCT:161:ec_GF2m_simple_point2oct +EC_F_EC_GF2M_SIMPLE_POINTS_MUL:289:ec_GF2m_simple_points_mul +EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES:162:\ + ec_GF2m_simple_point_get_affine_coordinates +EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES:163:\ + ec_GF2m_simple_point_set_affine_coordinates +EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES:164:\ + ec_GF2m_simple_set_compressed_coordinates +EC_F_EC_GFP_MONT_FIELD_DECODE:133:ec_GFp_mont_field_decode +EC_F_EC_GFP_MONT_FIELD_ENCODE:134:ec_GFp_mont_field_encode +EC_F_EC_GFP_MONT_FIELD_INV:297:ec_GFp_mont_field_inv +EC_F_EC_GFP_MONT_FIELD_MUL:131:ec_GFp_mont_field_mul +EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE:209:ec_GFp_mont_field_set_to_one +EC_F_EC_GFP_MONT_FIELD_SQR:132:ec_GFp_mont_field_sqr +EC_F_EC_GFP_MONT_GROUP_SET_CURVE:189:ec_GFp_mont_group_set_curve +EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE:225:ec_GFp_nistp224_group_set_curve +EC_F_EC_GFP_NISTP224_POINTS_MUL:228:ec_GFp_nistp224_points_mul +EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES:226:\ + ec_GFp_nistp224_point_get_affine_coordinates +EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE:230:ec_GFp_nistp256_group_set_curve +EC_F_EC_GFP_NISTP256_POINTS_MUL:231:ec_GFp_nistp256_points_mul +EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES:232:\ + ec_GFp_nistp256_point_get_affine_coordinates +EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE:233:ec_GFp_nistp521_group_set_curve +EC_F_EC_GFP_NISTP521_POINTS_MUL:234:ec_GFp_nistp521_points_mul +EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES:235:\ + ec_GFp_nistp521_point_get_affine_coordinates +EC_F_EC_GFP_NIST_FIELD_MUL:200:ec_GFp_nist_field_mul +EC_F_EC_GFP_NIST_FIELD_SQR:201:ec_GFp_nist_field_sqr +EC_F_EC_GFP_NIST_GROUP_SET_CURVE:202:ec_GFp_nist_group_set_curve +EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES:287:ec_GFp_simple_blind_coordinates +EC_F_EC_GFP_SIMPLE_FIELD_INV:298:ec_GFp_simple_field_inv +EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT:165:\ + ec_GFp_simple_group_check_discriminant +EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE:166:ec_GFp_simple_group_set_curve +EC_F_EC_GFP_SIMPLE_MAKE_AFFINE:102:ec_GFp_simple_make_affine +EC_F_EC_GFP_SIMPLE_OCT2POINT:103:ec_GFp_simple_oct2point +EC_F_EC_GFP_SIMPLE_POINT2OCT:104:ec_GFp_simple_point2oct +EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE:137:ec_GFp_simple_points_make_affine +EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES:167:\ + ec_GFp_simple_point_get_affine_coordinates +EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES:168:\ + ec_GFp_simple_point_set_affine_coordinates +EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES:169:\ + ec_GFp_simple_set_compressed_coordinates +EC_F_EC_GROUP_CHECK:170:EC_GROUP_check +EC_F_EC_GROUP_CHECK_DISCRIMINANT:171:EC_GROUP_check_discriminant +EC_F_EC_GROUP_COPY:106:EC_GROUP_copy +EC_F_EC_GROUP_GET_CURVE:291:EC_GROUP_get_curve +EC_F_EC_GROUP_GET_CURVE_GF2M:172:EC_GROUP_get_curve_GF2m +EC_F_EC_GROUP_GET_CURVE_GFP:130:EC_GROUP_get_curve_GFp +EC_F_EC_GROUP_GET_DEGREE:173:EC_GROUP_get_degree +EC_F_EC_GROUP_GET_ECPARAMETERS:261:EC_GROUP_get_ecparameters +EC_F_EC_GROUP_GET_ECPKPARAMETERS:262:EC_GROUP_get_ecpkparameters +EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS:193:EC_GROUP_get_pentanomial_basis +EC_F_EC_GROUP_GET_TRINOMIAL_BASIS:194:EC_GROUP_get_trinomial_basis +EC_F_EC_GROUP_NEW:108:EC_GROUP_new +EC_F_EC_GROUP_NEW_BY_CURVE_NAME:174:EC_GROUP_new_by_curve_name +EC_F_EC_GROUP_NEW_FROM_DATA:175:ec_group_new_from_data +EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS:263:EC_GROUP_new_from_ecparameters +EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS:264:EC_GROUP_new_from_ecpkparameters +EC_F_EC_GROUP_SET_CURVE:292:EC_GROUP_set_curve +EC_F_EC_GROUP_SET_CURVE_GF2M:176:EC_GROUP_set_curve_GF2m +EC_F_EC_GROUP_SET_CURVE_GFP:109:EC_GROUP_set_curve_GFp +EC_F_EC_GROUP_SET_GENERATOR:111:EC_GROUP_set_generator +EC_F_EC_GROUP_SET_SEED:286:EC_GROUP_set_seed +EC_F_EC_KEY_CHECK_KEY:177:EC_KEY_check_key +EC_F_EC_KEY_COPY:178:EC_KEY_copy +EC_F_EC_KEY_GENERATE_KEY:179:EC_KEY_generate_key +EC_F_EC_KEY_NEW:182:EC_KEY_new +EC_F_EC_KEY_NEW_METHOD:245:EC_KEY_new_method +EC_F_EC_KEY_OCT2PRIV:255:EC_KEY_oct2priv +EC_F_EC_KEY_PRINT:180:EC_KEY_print +EC_F_EC_KEY_PRINT_FP:181:EC_KEY_print_fp +EC_F_EC_KEY_PRIV2BUF:279:EC_KEY_priv2buf +EC_F_EC_KEY_PRIV2OCT:256:EC_KEY_priv2oct +EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES:229:\ + EC_KEY_set_public_key_affine_coordinates +EC_F_EC_KEY_SIMPLE_CHECK_KEY:258:ec_key_simple_check_key +EC_F_EC_KEY_SIMPLE_OCT2PRIV:259:ec_key_simple_oct2priv +EC_F_EC_KEY_SIMPLE_PRIV2OCT:260:ec_key_simple_priv2oct +EC_F_EC_PKEY_CHECK:273:ec_pkey_check +EC_F_EC_PKEY_PARAM_CHECK:274:ec_pkey_param_check +EC_F_EC_POINTS_MAKE_AFFINE:136:EC_POINTs_make_affine +EC_F_EC_POINTS_MUL:290:EC_POINTs_mul +EC_F_EC_POINT_ADD:112:EC_POINT_add +EC_F_EC_POINT_BN2POINT:280:EC_POINT_bn2point +EC_F_EC_POINT_CMP:113:EC_POINT_cmp +EC_F_EC_POINT_COPY:114:EC_POINT_copy +EC_F_EC_POINT_DBL:115:EC_POINT_dbl +EC_F_EC_POINT_GET_AFFINE_COORDINATES:293:EC_POINT_get_affine_coordinates +EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M:183:\ + EC_POINT_get_affine_coordinates_GF2m +EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP:116:EC_POINT_get_affine_coordinates_GFp +EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP:117:\ + EC_POINT_get_Jprojective_coordinates_GFp +EC_F_EC_POINT_INVERT:210:EC_POINT_invert +EC_F_EC_POINT_IS_AT_INFINITY:118:EC_POINT_is_at_infinity +EC_F_EC_POINT_IS_ON_CURVE:119:EC_POINT_is_on_curve +EC_F_EC_POINT_MAKE_AFFINE:120:EC_POINT_make_affine +EC_F_EC_POINT_NEW:121:EC_POINT_new +EC_F_EC_POINT_OCT2POINT:122:EC_POINT_oct2point +EC_F_EC_POINT_POINT2BUF:281:EC_POINT_point2buf +EC_F_EC_POINT_POINT2OCT:123:EC_POINT_point2oct +EC_F_EC_POINT_SET_AFFINE_COORDINATES:294:EC_POINT_set_affine_coordinates +EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M:185:\ + EC_POINT_set_affine_coordinates_GF2m +EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP:124:EC_POINT_set_affine_coordinates_GFp +EC_F_EC_POINT_SET_COMPRESSED_COORDINATES:295:EC_POINT_set_compressed_coordinates +EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M:186:\ + EC_POINT_set_compressed_coordinates_GF2m +EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP:125:\ + EC_POINT_set_compressed_coordinates_GFp +EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP:126:\ + EC_POINT_set_Jprojective_coordinates_GFp +EC_F_EC_POINT_SET_TO_INFINITY:127:EC_POINT_set_to_infinity +EC_F_EC_PRE_COMP_NEW:196:ec_pre_comp_new +EC_F_EC_SCALAR_MUL_LADDER:284:ec_scalar_mul_ladder +EC_F_EC_WNAF_MUL:187:ec_wNAF_mul +EC_F_EC_WNAF_PRECOMPUTE_MULT:188:ec_wNAF_precompute_mult +EC_F_I2D_ECPARAMETERS:190:i2d_ECParameters +EC_F_I2D_ECPKPARAMETERS:191:i2d_ECPKParameters +EC_F_I2D_ECPRIVATEKEY:192:i2d_ECPrivateKey +EC_F_I2O_ECPUBLICKEY:151:i2o_ECPublicKey +EC_F_NISTP224_PRE_COMP_NEW:227:nistp224_pre_comp_new +EC_F_NISTP256_PRE_COMP_NEW:236:nistp256_pre_comp_new +EC_F_NISTP521_PRE_COMP_NEW:237:nistp521_pre_comp_new +EC_F_O2I_ECPUBLICKEY:152:o2i_ECPublicKey +EC_F_OLD_EC_PRIV_DECODE:222:old_ec_priv_decode +EC_F_OSSL_ECDH_COMPUTE_KEY:247:ossl_ecdh_compute_key +EC_F_OSSL_ECDSA_SIGN_SIG:249:ossl_ecdsa_sign_sig +EC_F_OSSL_ECDSA_VERIFY_SIG:250:ossl_ecdsa_verify_sig +EC_F_PKEY_ECD_CTRL:271:pkey_ecd_ctrl +EC_F_PKEY_ECD_DIGESTSIGN:272:pkey_ecd_digestsign +EC_F_PKEY_ECD_DIGESTSIGN25519:276:pkey_ecd_digestsign25519 +EC_F_PKEY_ECD_DIGESTSIGN448:277:pkey_ecd_digestsign448 +EC_F_PKEY_ECX_DERIVE:269:pkey_ecx_derive +EC_F_PKEY_EC_CTRL:197:pkey_ec_ctrl +EC_F_PKEY_EC_CTRL_STR:198:pkey_ec_ctrl_str +EC_F_PKEY_EC_DERIVE:217:pkey_ec_derive +EC_F_PKEY_EC_INIT:282:pkey_ec_init +EC_F_PKEY_EC_KDF_DERIVE:283:pkey_ec_kdf_derive +EC_F_PKEY_EC_KEYGEN:199:pkey_ec_keygen +EC_F_PKEY_EC_PARAMGEN:219:pkey_ec_paramgen +EC_F_PKEY_EC_SIGN:218:pkey_ec_sign +EC_F_VALIDATE_ECX_DERIVE:278:validate_ecx_derive +ENGINE_F_DIGEST_UPDATE:198:digest_update +ENGINE_F_DYNAMIC_CTRL:180:dynamic_ctrl +ENGINE_F_DYNAMIC_GET_DATA_CTX:181:dynamic_get_data_ctx +ENGINE_F_DYNAMIC_LOAD:182:dynamic_load +ENGINE_F_DYNAMIC_SET_DATA_CTX:183:dynamic_set_data_ctx +ENGINE_F_ENGINE_ADD:105:ENGINE_add +ENGINE_F_ENGINE_BY_ID:106:ENGINE_by_id +ENGINE_F_ENGINE_CMD_IS_EXECUTABLE:170:ENGINE_cmd_is_executable +ENGINE_F_ENGINE_CTRL:142:ENGINE_ctrl +ENGINE_F_ENGINE_CTRL_CMD:178:ENGINE_ctrl_cmd +ENGINE_F_ENGINE_CTRL_CMD_STRING:171:ENGINE_ctrl_cmd_string +ENGINE_F_ENGINE_FINISH:107:ENGINE_finish +ENGINE_F_ENGINE_GET_CIPHER:185:ENGINE_get_cipher +ENGINE_F_ENGINE_GET_DIGEST:186:ENGINE_get_digest +ENGINE_F_ENGINE_GET_FIRST:195:ENGINE_get_first +ENGINE_F_ENGINE_GET_LAST:196:ENGINE_get_last +ENGINE_F_ENGINE_GET_NEXT:115:ENGINE_get_next +ENGINE_F_ENGINE_GET_PKEY_ASN1_METH:193:ENGINE_get_pkey_asn1_meth +ENGINE_F_ENGINE_GET_PKEY_METH:192:ENGINE_get_pkey_meth +ENGINE_F_ENGINE_GET_PREV:116:ENGINE_get_prev +ENGINE_F_ENGINE_INIT:119:ENGINE_init +ENGINE_F_ENGINE_LIST_ADD:120:engine_list_add +ENGINE_F_ENGINE_LIST_REMOVE:121:engine_list_remove +ENGINE_F_ENGINE_LOAD_PRIVATE_KEY:150:ENGINE_load_private_key +ENGINE_F_ENGINE_LOAD_PUBLIC_KEY:151:ENGINE_load_public_key +ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT:194:ENGINE_load_ssl_client_cert +ENGINE_F_ENGINE_NEW:122:ENGINE_new +ENGINE_F_ENGINE_PKEY_ASN1_FIND_STR:197:ENGINE_pkey_asn1_find_str +ENGINE_F_ENGINE_REMOVE:123:ENGINE_remove +ENGINE_F_ENGINE_SET_DEFAULT_STRING:189:ENGINE_set_default_string +ENGINE_F_ENGINE_SET_ID:129:ENGINE_set_id +ENGINE_F_ENGINE_SET_NAME:130:ENGINE_set_name +ENGINE_F_ENGINE_TABLE_REGISTER:184:engine_table_register +ENGINE_F_ENGINE_UNLOCKED_FINISH:191:engine_unlocked_finish +ENGINE_F_ENGINE_UP_REF:190:ENGINE_up_ref +ENGINE_F_INT_CLEANUP_ITEM:199:int_cleanup_item +ENGINE_F_INT_CTRL_HELPER:172:int_ctrl_helper +ENGINE_F_INT_ENGINE_CONFIGURE:188:int_engine_configure +ENGINE_F_INT_ENGINE_MODULE_INIT:187:int_engine_module_init +ENGINE_F_OSSL_HMAC_INIT:200:ossl_hmac_init +EVP_F_AESNI_INIT_KEY:165:aesni_init_key +EVP_F_AES_GCM_CTRL:196:aes_gcm_ctrl +EVP_F_AES_INIT_KEY:133:aes_init_key +EVP_F_AES_OCB_CIPHER:169:aes_ocb_cipher +EVP_F_AES_T4_INIT_KEY:178:aes_t4_init_key +EVP_F_AES_WRAP_CIPHER:170:aes_wrap_cipher +EVP_F_ALG_MODULE_INIT:177:alg_module_init +EVP_F_ARIA_CCM_INIT_KEY:175:aria_ccm_init_key +EVP_F_ARIA_GCM_CTRL:197:aria_gcm_ctrl +EVP_F_ARIA_GCM_INIT_KEY:176:aria_gcm_init_key +EVP_F_ARIA_INIT_KEY:185:aria_init_key +EVP_F_B64_NEW:198:b64_new +EVP_F_CAMELLIA_INIT_KEY:159:camellia_init_key +EVP_F_CHACHA20_POLY1305_CTRL:182:chacha20_poly1305_ctrl +EVP_F_CMLL_T4_INIT_KEY:179:cmll_t4_init_key +EVP_F_DES_EDE3_WRAP_CIPHER:171:des_ede3_wrap_cipher +EVP_F_DO_SIGVER_INIT:161:do_sigver_init +EVP_F_ENC_NEW:199:enc_new +EVP_F_EVP_CIPHERINIT_EX:123:EVP_CipherInit_ex +EVP_F_EVP_CIPHER_ASN1_TO_PARAM:204:EVP_CIPHER_asn1_to_param +EVP_F_EVP_CIPHER_CTX_COPY:163:EVP_CIPHER_CTX_copy +EVP_F_EVP_CIPHER_CTX_CTRL:124:EVP_CIPHER_CTX_ctrl +EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH:122:EVP_CIPHER_CTX_set_key_length +EVP_F_EVP_CIPHER_PARAM_TO_ASN1:205:EVP_CIPHER_param_to_asn1 +EVP_F_EVP_DECRYPTFINAL_EX:101:EVP_DecryptFinal_ex +EVP_F_EVP_DECRYPTUPDATE:166:EVP_DecryptUpdate +EVP_F_EVP_DIGESTFINALXOF:174:EVP_DigestFinalXOF +EVP_F_EVP_DIGESTINIT_EX:128:EVP_DigestInit_ex +EVP_F_EVP_ENCRYPTDECRYPTUPDATE:219:evp_EncryptDecryptUpdate +EVP_F_EVP_ENCRYPTFINAL_EX:127:EVP_EncryptFinal_ex +EVP_F_EVP_ENCRYPTUPDATE:167:EVP_EncryptUpdate +EVP_F_EVP_MD_CTX_COPY_EX:110:EVP_MD_CTX_copy_ex +EVP_F_EVP_MD_SIZE:162:EVP_MD_size +EVP_F_EVP_OPENINIT:102:EVP_OpenInit +EVP_F_EVP_PBE_ALG_ADD:115:EVP_PBE_alg_add +EVP_F_EVP_PBE_ALG_ADD_TYPE:160:EVP_PBE_alg_add_type +EVP_F_EVP_PBE_CIPHERINIT:116:EVP_PBE_CipherInit +EVP_F_EVP_PBE_SCRYPT:181:EVP_PBE_scrypt +EVP_F_EVP_PKCS82PKEY:111:EVP_PKCS82PKEY +EVP_F_EVP_PKEY2PKCS8:113:EVP_PKEY2PKCS8 +EVP_F_EVP_PKEY_ASN1_ADD0:188:EVP_PKEY_asn1_add0 +EVP_F_EVP_PKEY_CHECK:186:EVP_PKEY_check +EVP_F_EVP_PKEY_COPY_PARAMETERS:103:EVP_PKEY_copy_parameters +EVP_F_EVP_PKEY_CTX_CTRL:137:EVP_PKEY_CTX_ctrl +EVP_F_EVP_PKEY_CTX_CTRL_STR:150:EVP_PKEY_CTX_ctrl_str +EVP_F_EVP_PKEY_CTX_DUP:156:EVP_PKEY_CTX_dup +EVP_F_EVP_PKEY_CTX_MD:168:EVP_PKEY_CTX_md +EVP_F_EVP_PKEY_DECRYPT:104:EVP_PKEY_decrypt +EVP_F_EVP_PKEY_DECRYPT_INIT:138:EVP_PKEY_decrypt_init +EVP_F_EVP_PKEY_DECRYPT_OLD:151:EVP_PKEY_decrypt_old +EVP_F_EVP_PKEY_DERIVE:153:EVP_PKEY_derive +EVP_F_EVP_PKEY_DERIVE_INIT:154:EVP_PKEY_derive_init +EVP_F_EVP_PKEY_DERIVE_SET_PEER:155:EVP_PKEY_derive_set_peer +EVP_F_EVP_PKEY_ENCRYPT:105:EVP_PKEY_encrypt +EVP_F_EVP_PKEY_ENCRYPT_INIT:139:EVP_PKEY_encrypt_init +EVP_F_EVP_PKEY_ENCRYPT_OLD:152:EVP_PKEY_encrypt_old +EVP_F_EVP_PKEY_GET0_DH:119:EVP_PKEY_get0_DH +EVP_F_EVP_PKEY_GET0_DSA:120:EVP_PKEY_get0_DSA +EVP_F_EVP_PKEY_GET0_EC_KEY:131:EVP_PKEY_get0_EC_KEY +EVP_F_EVP_PKEY_GET0_HMAC:183:EVP_PKEY_get0_hmac +EVP_F_EVP_PKEY_GET0_POLY1305:184:EVP_PKEY_get0_poly1305 +EVP_F_EVP_PKEY_GET0_RSA:121:EVP_PKEY_get0_RSA +EVP_F_EVP_PKEY_GET0_SIPHASH:172:EVP_PKEY_get0_siphash +EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY:202:EVP_PKEY_get_raw_private_key +EVP_F_EVP_PKEY_GET_RAW_PUBLIC_KEY:203:EVP_PKEY_get_raw_public_key +EVP_F_EVP_PKEY_KEYGEN:146:EVP_PKEY_keygen +EVP_F_EVP_PKEY_KEYGEN_INIT:147:EVP_PKEY_keygen_init +EVP_F_EVP_PKEY_METH_ADD0:194:EVP_PKEY_meth_add0 +EVP_F_EVP_PKEY_METH_NEW:195:EVP_PKEY_meth_new +EVP_F_EVP_PKEY_NEW:106:EVP_PKEY_new +EVP_F_EVP_PKEY_NEW_CMAC_KEY:193:EVP_PKEY_new_CMAC_key +EVP_F_EVP_PKEY_NEW_RAW_PRIVATE_KEY:191:EVP_PKEY_new_raw_private_key +EVP_F_EVP_PKEY_NEW_RAW_PUBLIC_KEY:192:EVP_PKEY_new_raw_public_key +EVP_F_EVP_PKEY_PARAMGEN:148:EVP_PKEY_paramgen +EVP_F_EVP_PKEY_PARAMGEN_INIT:149:EVP_PKEY_paramgen_init +EVP_F_EVP_PKEY_PARAM_CHECK:189:EVP_PKEY_param_check +EVP_F_EVP_PKEY_PUBLIC_CHECK:190:EVP_PKEY_public_check +EVP_F_EVP_PKEY_SET1_ENGINE:187:EVP_PKEY_set1_engine +EVP_F_EVP_PKEY_SET_ALIAS_TYPE:206:EVP_PKEY_set_alias_type +EVP_F_EVP_PKEY_SIGN:140:EVP_PKEY_sign +EVP_F_EVP_PKEY_SIGN_INIT:141:EVP_PKEY_sign_init +EVP_F_EVP_PKEY_VERIFY:142:EVP_PKEY_verify +EVP_F_EVP_PKEY_VERIFY_INIT:143:EVP_PKEY_verify_init +EVP_F_EVP_PKEY_VERIFY_RECOVER:144:EVP_PKEY_verify_recover +EVP_F_EVP_PKEY_VERIFY_RECOVER_INIT:145:EVP_PKEY_verify_recover_init +EVP_F_EVP_SIGNFINAL:107:EVP_SignFinal +EVP_F_EVP_VERIFYFINAL:108:EVP_VerifyFinal +EVP_F_INT_CTX_NEW:157:int_ctx_new +EVP_F_OK_NEW:200:ok_new +EVP_F_PKCS5_PBE_KEYIVGEN:117:PKCS5_PBE_keyivgen +EVP_F_PKCS5_V2_PBE_KEYIVGEN:118:PKCS5_v2_PBE_keyivgen +EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN:164:PKCS5_v2_PBKDF2_keyivgen +EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN:180:PKCS5_v2_scrypt_keyivgen +EVP_F_PKEY_SET_TYPE:158:pkey_set_type +EVP_F_RC2_MAGIC_TO_METH:109:rc2_magic_to_meth +EVP_F_RC5_CTRL:125:rc5_ctrl +EVP_F_S390X_AES_GCM_CTRL:201:s390x_aes_gcm_ctrl +EVP_F_UPDATE:173:update +KDF_F_PKEY_HKDF_CTRL_STR:103:pkey_hkdf_ctrl_str +KDF_F_PKEY_HKDF_DERIVE:102:pkey_hkdf_derive +KDF_F_PKEY_HKDF_INIT:108:pkey_hkdf_init +KDF_F_PKEY_SCRYPT_CTRL_STR:104:pkey_scrypt_ctrl_str +KDF_F_PKEY_SCRYPT_CTRL_UINT64:105:pkey_scrypt_ctrl_uint64 +KDF_F_PKEY_SCRYPT_DERIVE:109:pkey_scrypt_derive +KDF_F_PKEY_SCRYPT_INIT:106:pkey_scrypt_init +KDF_F_PKEY_SCRYPT_SET_MEMBUF:107:pkey_scrypt_set_membuf +KDF_F_PKEY_TLS1_PRF_CTRL_STR:100:pkey_tls1_prf_ctrl_str +KDF_F_PKEY_TLS1_PRF_DERIVE:101:pkey_tls1_prf_derive +KDF_F_PKEY_TLS1_PRF_INIT:110:pkey_tls1_prf_init +KDF_F_TLS1_PRF_ALG:111:tls1_prf_alg +OBJ_F_OBJ_ADD_OBJECT:105:OBJ_add_object +OBJ_F_OBJ_ADD_SIGID:107:OBJ_add_sigid +OBJ_F_OBJ_CREATE:100:OBJ_create +OBJ_F_OBJ_DUP:101:OBJ_dup +OBJ_F_OBJ_NAME_NEW_INDEX:106:OBJ_NAME_new_index +OBJ_F_OBJ_NID2LN:102:OBJ_nid2ln +OBJ_F_OBJ_NID2OBJ:103:OBJ_nid2obj +OBJ_F_OBJ_NID2SN:104:OBJ_nid2sn +OBJ_F_OBJ_TXT2OBJ:108:OBJ_txt2obj +OCSP_F_D2I_OCSP_NONCE:102:d2i_ocsp_nonce +OCSP_F_OCSP_BASIC_ADD1_STATUS:103:OCSP_basic_add1_status +OCSP_F_OCSP_BASIC_SIGN:104:OCSP_basic_sign +OCSP_F_OCSP_BASIC_SIGN_CTX:119:OCSP_basic_sign_ctx +OCSP_F_OCSP_BASIC_VERIFY:105:OCSP_basic_verify +OCSP_F_OCSP_CERT_ID_NEW:101:OCSP_cert_id_new +OCSP_F_OCSP_CHECK_DELEGATED:106:ocsp_check_delegated +OCSP_F_OCSP_CHECK_IDS:107:ocsp_check_ids +OCSP_F_OCSP_CHECK_ISSUER:108:ocsp_check_issuer +OCSP_F_OCSP_CHECK_VALIDITY:115:OCSP_check_validity +OCSP_F_OCSP_MATCH_ISSUERID:109:ocsp_match_issuerid +OCSP_F_OCSP_PARSE_URL:114:OCSP_parse_url +OCSP_F_OCSP_REQUEST_SIGN:110:OCSP_request_sign +OCSP_F_OCSP_REQUEST_VERIFY:116:OCSP_request_verify +OCSP_F_OCSP_RESPONSE_GET1_BASIC:111:OCSP_response_get1_basic +OCSP_F_PARSE_HTTP_LINE1:118:parse_http_line1 +OSSL_STORE_F_FILE_CTRL:129:file_ctrl +OSSL_STORE_F_FILE_FIND:138:file_find +OSSL_STORE_F_FILE_GET_PASS:118:file_get_pass +OSSL_STORE_F_FILE_LOAD:119:file_load +OSSL_STORE_F_FILE_LOAD_TRY_DECODE:124:file_load_try_decode +OSSL_STORE_F_FILE_NAME_TO_URI:126:file_name_to_uri +OSSL_STORE_F_FILE_OPEN:120:file_open +OSSL_STORE_F_OSSL_STORE_ATTACH_PEM_BIO:127:ossl_store_attach_pem_bio +OSSL_STORE_F_OSSL_STORE_EXPECT:130:OSSL_STORE_expect +OSSL_STORE_F_OSSL_STORE_FILE_ATTACH_PEM_BIO_INT:128:\ + ossl_store_file_attach_pem_bio_int +OSSL_STORE_F_OSSL_STORE_FIND:131:OSSL_STORE_find +OSSL_STORE_F_OSSL_STORE_GET0_LOADER_INT:100:ossl_store_get0_loader_int +OSSL_STORE_F_OSSL_STORE_INFO_GET1_CERT:101:OSSL_STORE_INFO_get1_CERT +OSSL_STORE_F_OSSL_STORE_INFO_GET1_CRL:102:OSSL_STORE_INFO_get1_CRL +OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME:103:OSSL_STORE_INFO_get1_NAME +OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME_DESCRIPTION:135:\ + OSSL_STORE_INFO_get1_NAME_description +OSSL_STORE_F_OSSL_STORE_INFO_GET1_PARAMS:104:OSSL_STORE_INFO_get1_PARAMS +OSSL_STORE_F_OSSL_STORE_INFO_GET1_PKEY:105:OSSL_STORE_INFO_get1_PKEY +OSSL_STORE_F_OSSL_STORE_INFO_NEW_CERT:106:OSSL_STORE_INFO_new_CERT +OSSL_STORE_F_OSSL_STORE_INFO_NEW_CRL:107:OSSL_STORE_INFO_new_CRL +OSSL_STORE_F_OSSL_STORE_INFO_NEW_EMBEDDED:123:ossl_store_info_new_EMBEDDED +OSSL_STORE_F_OSSL_STORE_INFO_NEW_NAME:109:OSSL_STORE_INFO_new_NAME +OSSL_STORE_F_OSSL_STORE_INFO_NEW_PARAMS:110:OSSL_STORE_INFO_new_PARAMS +OSSL_STORE_F_OSSL_STORE_INFO_NEW_PKEY:111:OSSL_STORE_INFO_new_PKEY +OSSL_STORE_F_OSSL_STORE_INFO_SET0_NAME_DESCRIPTION:134:\ + OSSL_STORE_INFO_set0_NAME_description +OSSL_STORE_F_OSSL_STORE_INIT_ONCE:112:ossl_store_init_once +OSSL_STORE_F_OSSL_STORE_LOADER_NEW:113:OSSL_STORE_LOADER_new +OSSL_STORE_F_OSSL_STORE_OPEN:114:OSSL_STORE_open +OSSL_STORE_F_OSSL_STORE_OPEN_INT:115:* +OSSL_STORE_F_OSSL_STORE_REGISTER_LOADER_INT:117:ossl_store_register_loader_int +OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ALIAS:132:OSSL_STORE_SEARCH_by_alias +OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ISSUER_SERIAL:133:\ + OSSL_STORE_SEARCH_by_issuer_serial +OSSL_STORE_F_OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT:136:\ + OSSL_STORE_SEARCH_by_key_fingerprint +OSSL_STORE_F_OSSL_STORE_SEARCH_BY_NAME:137:OSSL_STORE_SEARCH_by_name +OSSL_STORE_F_OSSL_STORE_UNREGISTER_LOADER_INT:116:\ + ossl_store_unregister_loader_int +OSSL_STORE_F_TRY_DECODE_PARAMS:121:try_decode_params +OSSL_STORE_F_TRY_DECODE_PKCS12:122:try_decode_PKCS12 +OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED:125:try_decode_PKCS8Encrypted +PEM_F_B2I_DSS:127:b2i_dss +PEM_F_B2I_PVK_BIO:128:b2i_PVK_bio +PEM_F_B2I_RSA:129:b2i_rsa +PEM_F_CHECK_BITLEN_DSA:130:check_bitlen_dsa +PEM_F_CHECK_BITLEN_RSA:131:check_bitlen_rsa +PEM_F_D2I_PKCS8PRIVATEKEY_BIO:120:d2i_PKCS8PrivateKey_bio +PEM_F_D2I_PKCS8PRIVATEKEY_FP:121:d2i_PKCS8PrivateKey_fp +PEM_F_DO_B2I:132:do_b2i +PEM_F_DO_B2I_BIO:133:do_b2i_bio +PEM_F_DO_BLOB_HEADER:134:do_blob_header +PEM_F_DO_I2B:146:do_i2b +PEM_F_DO_PK8PKEY:126:do_pk8pkey +PEM_F_DO_PK8PKEY_FP:125:do_pk8pkey_fp +PEM_F_DO_PVK_BODY:135:do_PVK_body +PEM_F_DO_PVK_HEADER:136:do_PVK_header +PEM_F_GET_HEADER_AND_DATA:143:get_header_and_data +PEM_F_GET_NAME:144:get_name +PEM_F_I2B_PVK:137:i2b_PVK +PEM_F_I2B_PVK_BIO:138:i2b_PVK_bio +PEM_F_LOAD_IV:101:load_iv +PEM_F_PEM_ASN1_READ:102:PEM_ASN1_read +PEM_F_PEM_ASN1_READ_BIO:103:PEM_ASN1_read_bio +PEM_F_PEM_ASN1_WRITE:104:PEM_ASN1_write +PEM_F_PEM_ASN1_WRITE_BIO:105:PEM_ASN1_write_bio +PEM_F_PEM_DEF_CALLBACK:100:PEM_def_callback +PEM_F_PEM_DO_HEADER:106:PEM_do_header +PEM_F_PEM_GET_EVP_CIPHER_INFO:107:PEM_get_EVP_CIPHER_INFO +PEM_F_PEM_READ:108:PEM_read +PEM_F_PEM_READ_BIO:109:PEM_read_bio +PEM_F_PEM_READ_BIO_DHPARAMS:141:PEM_read_bio_DHparams +PEM_F_PEM_READ_BIO_EX:145:PEM_read_bio_ex +PEM_F_PEM_READ_BIO_PARAMETERS:140:PEM_read_bio_Parameters +PEM_F_PEM_READ_BIO_PRIVATEKEY:123:PEM_read_bio_PrivateKey +PEM_F_PEM_READ_DHPARAMS:142:PEM_read_DHparams +PEM_F_PEM_READ_PRIVATEKEY:124:PEM_read_PrivateKey +PEM_F_PEM_SIGNFINAL:112:PEM_SignFinal +PEM_F_PEM_WRITE:113:PEM_write +PEM_F_PEM_WRITE_BIO:114:PEM_write_bio +PEM_F_PEM_WRITE_PRIVATEKEY:139:PEM_write_PrivateKey +PEM_F_PEM_X509_INFO_READ:115:PEM_X509_INFO_read +PEM_F_PEM_X509_INFO_READ_BIO:116:PEM_X509_INFO_read_bio +PEM_F_PEM_X509_INFO_WRITE_BIO:117:PEM_X509_INFO_write_bio +PKCS12_F_OPENSSL_ASC2UNI:121:OPENSSL_asc2uni +PKCS12_F_OPENSSL_UNI2ASC:124:OPENSSL_uni2asc +PKCS12_F_OPENSSL_UNI2UTF8:127:OPENSSL_uni2utf8 +PKCS12_F_OPENSSL_UTF82UNI:129:OPENSSL_utf82uni +PKCS12_F_PKCS12_CREATE:105:PKCS12_create +PKCS12_F_PKCS12_GEN_MAC:107:PKCS12_gen_mac +PKCS12_F_PKCS12_INIT:109:PKCS12_init +PKCS12_F_PKCS12_ITEM_DECRYPT_D2I:106:PKCS12_item_decrypt_d2i +PKCS12_F_PKCS12_ITEM_I2D_ENCRYPT:108:PKCS12_item_i2d_encrypt +PKCS12_F_PKCS12_ITEM_PACK_SAFEBAG:117:PKCS12_item_pack_safebag +PKCS12_F_PKCS12_KEY_GEN_ASC:110:PKCS12_key_gen_asc +PKCS12_F_PKCS12_KEY_GEN_UNI:111:PKCS12_key_gen_uni +PKCS12_F_PKCS12_KEY_GEN_UTF8:116:PKCS12_key_gen_utf8 +PKCS12_F_PKCS12_NEWPASS:128:PKCS12_newpass +PKCS12_F_PKCS12_PACK_P7DATA:114:PKCS12_pack_p7data +PKCS12_F_PKCS12_PACK_P7ENCDATA:115:PKCS12_pack_p7encdata +PKCS12_F_PKCS12_PARSE:118:PKCS12_parse +PKCS12_F_PKCS12_PBE_CRYPT:119:PKCS12_pbe_crypt +PKCS12_F_PKCS12_PBE_KEYIVGEN:120:PKCS12_PBE_keyivgen +PKCS12_F_PKCS12_SAFEBAG_CREATE0_P8INF:112:PKCS12_SAFEBAG_create0_p8inf +PKCS12_F_PKCS12_SAFEBAG_CREATE0_PKCS8:113:PKCS12_SAFEBAG_create0_pkcs8 +PKCS12_F_PKCS12_SAFEBAG_CREATE_PKCS8_ENCRYPT:133:\ + PKCS12_SAFEBAG_create_pkcs8_encrypt +PKCS12_F_PKCS12_SETUP_MAC:122:PKCS12_setup_mac +PKCS12_F_PKCS12_SET_MAC:123:PKCS12_set_mac +PKCS12_F_PKCS12_UNPACK_AUTHSAFES:130:PKCS12_unpack_authsafes +PKCS12_F_PKCS12_UNPACK_P7DATA:131:PKCS12_unpack_p7data +PKCS12_F_PKCS12_VERIFY_MAC:126:PKCS12_verify_mac +PKCS12_F_PKCS8_ENCRYPT:125:PKCS8_encrypt +PKCS12_F_PKCS8_SET0_PBE:132:PKCS8_set0_pbe +PKCS7_F_DO_PKCS7_SIGNED_ATTRIB:136:do_pkcs7_signed_attrib +PKCS7_F_PKCS7_ADD0_ATTRIB_SIGNING_TIME:135:PKCS7_add0_attrib_signing_time +PKCS7_F_PKCS7_ADD_ATTRIB_SMIMECAP:118:PKCS7_add_attrib_smimecap +PKCS7_F_PKCS7_ADD_CERTIFICATE:100:PKCS7_add_certificate +PKCS7_F_PKCS7_ADD_CRL:101:PKCS7_add_crl +PKCS7_F_PKCS7_ADD_RECIPIENT_INFO:102:PKCS7_add_recipient_info +PKCS7_F_PKCS7_ADD_SIGNATURE:131:PKCS7_add_signature +PKCS7_F_PKCS7_ADD_SIGNER:103:PKCS7_add_signer +PKCS7_F_PKCS7_BIO_ADD_DIGEST:125:PKCS7_bio_add_digest +PKCS7_F_PKCS7_COPY_EXISTING_DIGEST:138:pkcs7_copy_existing_digest +PKCS7_F_PKCS7_CTRL:104:PKCS7_ctrl +PKCS7_F_PKCS7_DATADECODE:112:PKCS7_dataDecode +PKCS7_F_PKCS7_DATAFINAL:128:PKCS7_dataFinal +PKCS7_F_PKCS7_DATAINIT:105:PKCS7_dataInit +PKCS7_F_PKCS7_DATAVERIFY:107:PKCS7_dataVerify +PKCS7_F_PKCS7_DECRYPT:114:PKCS7_decrypt +PKCS7_F_PKCS7_DECRYPT_RINFO:133:pkcs7_decrypt_rinfo +PKCS7_F_PKCS7_ENCODE_RINFO:132:pkcs7_encode_rinfo +PKCS7_F_PKCS7_ENCRYPT:115:PKCS7_encrypt +PKCS7_F_PKCS7_FINAL:134:PKCS7_final +PKCS7_F_PKCS7_FIND_DIGEST:127:PKCS7_find_digest +PKCS7_F_PKCS7_GET0_SIGNERS:124:PKCS7_get0_signers +PKCS7_F_PKCS7_RECIP_INFO_SET:130:PKCS7_RECIP_INFO_set +PKCS7_F_PKCS7_SET_CIPHER:108:PKCS7_set_cipher +PKCS7_F_PKCS7_SET_CONTENT:109:PKCS7_set_content +PKCS7_F_PKCS7_SET_DIGEST:126:PKCS7_set_digest +PKCS7_F_PKCS7_SET_TYPE:110:PKCS7_set_type +PKCS7_F_PKCS7_SIGN:116:PKCS7_sign +PKCS7_F_PKCS7_SIGNATUREVERIFY:113:PKCS7_signatureVerify +PKCS7_F_PKCS7_SIGNER_INFO_SET:129:PKCS7_SIGNER_INFO_set +PKCS7_F_PKCS7_SIGNER_INFO_SIGN:139:PKCS7_SIGNER_INFO_sign +PKCS7_F_PKCS7_SIGN_ADD_SIGNER:137:PKCS7_sign_add_signer +PKCS7_F_PKCS7_SIMPLE_SMIMECAP:119:PKCS7_simple_smimecap +PKCS7_F_PKCS7_VERIFY:117:PKCS7_verify +RAND_F_DRBG_BYTES:101:drbg_bytes +RAND_F_DRBG_GET_ENTROPY:105:drbg_get_entropy +RAND_F_DRBG_SETUP:117:drbg_setup +RAND_F_GET_ENTROPY:106:get_entropy +RAND_F_RAND_BYTES:100:RAND_bytes +RAND_F_RAND_DRBG_ENABLE_LOCKING:119:rand_drbg_enable_locking +RAND_F_RAND_DRBG_GENERATE:107:RAND_DRBG_generate +RAND_F_RAND_DRBG_GET_ENTROPY:120:rand_drbg_get_entropy +RAND_F_RAND_DRBG_GET_NONCE:123:rand_drbg_get_nonce +RAND_F_RAND_DRBG_INSTANTIATE:108:RAND_DRBG_instantiate +RAND_F_RAND_DRBG_NEW:109:RAND_DRBG_new +RAND_F_RAND_DRBG_RESEED:110:RAND_DRBG_reseed +RAND_F_RAND_DRBG_RESTART:102:rand_drbg_restart +RAND_F_RAND_DRBG_SET:104:RAND_DRBG_set +RAND_F_RAND_DRBG_SET_DEFAULTS:121:RAND_DRBG_set_defaults +RAND_F_RAND_DRBG_UNINSTANTIATE:118:RAND_DRBG_uninstantiate +RAND_F_RAND_LOAD_FILE:111:RAND_load_file +RAND_F_RAND_POOL_ACQUIRE_ENTROPY:122:rand_pool_acquire_entropy +RAND_F_RAND_POOL_ADD:103:rand_pool_add +RAND_F_RAND_POOL_ADD_BEGIN:113:rand_pool_add_begin +RAND_F_RAND_POOL_ADD_END:114:rand_pool_add_end +RAND_F_RAND_POOL_ATTACH:124:rand_pool_attach +RAND_F_RAND_POOL_BYTES_NEEDED:115:rand_pool_bytes_needed +RAND_F_RAND_POOL_NEW:116:rand_pool_new +RAND_F_RAND_WRITE_FILE:112:RAND_write_file +RSA_F_CHECK_PADDING_MD:140:check_padding_md +RSA_F_ENCODE_PKCS1:146:encode_pkcs1 +RSA_F_INT_RSA_VERIFY:145:int_rsa_verify +RSA_F_OLD_RSA_PRIV_DECODE:147:old_rsa_priv_decode +RSA_F_PKEY_PSS_INIT:165:pkey_pss_init +RSA_F_PKEY_RSA_CTRL:143:pkey_rsa_ctrl +RSA_F_PKEY_RSA_CTRL_STR:144:pkey_rsa_ctrl_str +RSA_F_PKEY_RSA_SIGN:142:pkey_rsa_sign +RSA_F_PKEY_RSA_VERIFY:149:pkey_rsa_verify +RSA_F_PKEY_RSA_VERIFYRECOVER:141:pkey_rsa_verifyrecover +RSA_F_RSA_ALGOR_TO_MD:156:rsa_algor_to_md +RSA_F_RSA_BUILTIN_KEYGEN:129:rsa_builtin_keygen +RSA_F_RSA_CHECK_KEY:123:RSA_check_key +RSA_F_RSA_CHECK_KEY_EX:160:RSA_check_key_ex +RSA_F_RSA_CMS_DECRYPT:159:rsa_cms_decrypt +RSA_F_RSA_CMS_VERIFY:158:rsa_cms_verify +RSA_F_RSA_ITEM_VERIFY:148:rsa_item_verify +RSA_F_RSA_METH_DUP:161:RSA_meth_dup +RSA_F_RSA_METH_NEW:162:RSA_meth_new +RSA_F_RSA_METH_SET1_NAME:163:RSA_meth_set1_name +RSA_F_RSA_MGF1_TO_MD:157:* +RSA_F_RSA_MULTIP_INFO_NEW:166:rsa_multip_info_new +RSA_F_RSA_NEW_METHOD:106:RSA_new_method +RSA_F_RSA_NULL:124:* +RSA_F_RSA_NULL_PRIVATE_DECRYPT:132:* +RSA_F_RSA_NULL_PRIVATE_ENCRYPT:133:* +RSA_F_RSA_NULL_PUBLIC_DECRYPT:134:* +RSA_F_RSA_NULL_PUBLIC_ENCRYPT:135:* +RSA_F_RSA_OSSL_PRIVATE_DECRYPT:101:rsa_ossl_private_decrypt +RSA_F_RSA_OSSL_PRIVATE_ENCRYPT:102:rsa_ossl_private_encrypt +RSA_F_RSA_OSSL_PUBLIC_DECRYPT:103:rsa_ossl_public_decrypt +RSA_F_RSA_OSSL_PUBLIC_ENCRYPT:104:rsa_ossl_public_encrypt +RSA_F_RSA_PADDING_ADD_NONE:107:RSA_padding_add_none +RSA_F_RSA_PADDING_ADD_PKCS1_OAEP:121:RSA_padding_add_PKCS1_OAEP +RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1:154:RSA_padding_add_PKCS1_OAEP_mgf1 +RSA_F_RSA_PADDING_ADD_PKCS1_PSS:125:RSA_padding_add_PKCS1_PSS +RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1:152:RSA_padding_add_PKCS1_PSS_mgf1 +RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1:108:RSA_padding_add_PKCS1_type_1 +RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2:109:RSA_padding_add_PKCS1_type_2 +RSA_F_RSA_PADDING_ADD_SSLV23:110:RSA_padding_add_SSLv23 +RSA_F_RSA_PADDING_ADD_X931:127:RSA_padding_add_X931 +RSA_F_RSA_PADDING_CHECK_NONE:111:RSA_padding_check_none +RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP:122:RSA_padding_check_PKCS1_OAEP +RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1:153:RSA_padding_check_PKCS1_OAEP_mgf1 +RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1:112:RSA_padding_check_PKCS1_type_1 +RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2:113:RSA_padding_check_PKCS1_type_2 +RSA_F_RSA_PADDING_CHECK_SSLV23:114:RSA_padding_check_SSLv23 +RSA_F_RSA_PADDING_CHECK_X931:128:RSA_padding_check_X931 +RSA_F_RSA_PARAM_DECODE:164:rsa_param_decode +RSA_F_RSA_PRINT:115:RSA_print +RSA_F_RSA_PRINT_FP:116:RSA_print_fp +RSA_F_RSA_PRIV_DECODE:150:rsa_priv_decode +RSA_F_RSA_PRIV_ENCODE:138:rsa_priv_encode +RSA_F_RSA_PSS_GET_PARAM:151:rsa_pss_get_param +RSA_F_RSA_PSS_TO_CTX:155:rsa_pss_to_ctx +RSA_F_RSA_PUB_DECODE:139:rsa_pub_decode +RSA_F_RSA_SETUP_BLINDING:136:RSA_setup_blinding +RSA_F_RSA_SIGN:117:RSA_sign +RSA_F_RSA_SIGN_ASN1_OCTET_STRING:118:RSA_sign_ASN1_OCTET_STRING +RSA_F_RSA_VERIFY:119:RSA_verify +RSA_F_RSA_VERIFY_ASN1_OCTET_STRING:120:RSA_verify_ASN1_OCTET_STRING +RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1:126:RSA_verify_PKCS1_PSS_mgf1 +RSA_F_SETUP_TBUF:167:setup_tbuf +SM2_F_PKEY_SM2_COPY:115:pkey_sm2_copy +SM2_F_PKEY_SM2_CTRL:109:pkey_sm2_ctrl +SM2_F_PKEY_SM2_CTRL_STR:110:pkey_sm2_ctrl_str +SM2_F_PKEY_SM2_DIGEST_CUSTOM:114:pkey_sm2_digest_custom +SM2_F_PKEY_SM2_INIT:111:pkey_sm2_init +SM2_F_PKEY_SM2_SIGN:112:pkey_sm2_sign +SM2_F_SM2_COMPUTE_MSG_HASH:100:sm2_compute_msg_hash +SM2_F_SM2_COMPUTE_USERID_DIGEST:101:sm2_compute_userid_digest +SM2_F_SM2_COMPUTE_Z_DIGEST:113:sm2_compute_z_digest +SM2_F_SM2_DECRYPT:102:sm2_decrypt +SM2_F_SM2_ENCRYPT:103:sm2_encrypt +SM2_F_SM2_PLAINTEXT_SIZE:104:sm2_plaintext_size +SM2_F_SM2_SIGN:105:sm2_sign +SM2_F_SM2_SIG_GEN:106:sm2_sig_gen +SM2_F_SM2_SIG_VERIFY:107:sm2_sig_verify +SM2_F_SM2_VERIFY:108:sm2_verify +SSL_F_ADD_CLIENT_KEY_SHARE_EXT:438:* +SSL_F_ADD_KEY_SHARE:512:add_key_share +SSL_F_BYTES_TO_CIPHER_LIST:519:bytes_to_cipher_list +SSL_F_CHECK_SUITEB_CIPHER_LIST:331:check_suiteb_cipher_list +SSL_F_CIPHERSUITE_CB:622:ciphersuite_cb +SSL_F_CONSTRUCT_CA_NAMES:552:construct_ca_names +SSL_F_CONSTRUCT_KEY_EXCHANGE_TBS:553:construct_key_exchange_tbs +SSL_F_CONSTRUCT_STATEFUL_TICKET:636:construct_stateful_ticket +SSL_F_CONSTRUCT_STATELESS_TICKET:637:construct_stateless_ticket +SSL_F_CREATE_SYNTHETIC_MESSAGE_HASH:539:create_synthetic_message_hash +SSL_F_CREATE_TICKET_PREQUEL:638:create_ticket_prequel +SSL_F_CT_MOVE_SCTS:345:ct_move_scts +SSL_F_CT_STRICT:349:ct_strict +SSL_F_CUSTOM_EXT_ADD:554:custom_ext_add +SSL_F_CUSTOM_EXT_PARSE:555:custom_ext_parse +SSL_F_D2I_SSL_SESSION:103:d2i_SSL_SESSION +SSL_F_DANE_CTX_ENABLE:347:dane_ctx_enable +SSL_F_DANE_MTYPE_SET:393:dane_mtype_set +SSL_F_DANE_TLSA_ADD:394:dane_tlsa_add +SSL_F_DERIVE_SECRET_KEY_AND_IV:514:derive_secret_key_and_iv +SSL_F_DO_DTLS1_WRITE:245:do_dtls1_write +SSL_F_DO_SSL3_WRITE:104:do_ssl3_write +SSL_F_DTLS1_BUFFER_RECORD:247:dtls1_buffer_record +SSL_F_DTLS1_CHECK_TIMEOUT_NUM:318:dtls1_check_timeout_num +SSL_F_DTLS1_HEARTBEAT:305:* +SSL_F_DTLS1_HM_FRAGMENT_NEW:623:dtls1_hm_fragment_new +SSL_F_DTLS1_PREPROCESS_FRAGMENT:288:dtls1_preprocess_fragment +SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS:424:dtls1_process_buffered_records +SSL_F_DTLS1_PROCESS_RECORD:257:dtls1_process_record +SSL_F_DTLS1_READ_BYTES:258:dtls1_read_bytes +SSL_F_DTLS1_READ_FAILED:339:dtls1_read_failed +SSL_F_DTLS1_RETRANSMIT_MESSAGE:390:dtls1_retransmit_message +SSL_F_DTLS1_WRITE_APP_DATA_BYTES:268:dtls1_write_app_data_bytes +SSL_F_DTLS1_WRITE_BYTES:545:dtls1_write_bytes +SSL_F_DTLSV1_LISTEN:350:DTLSv1_listen +SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC:371:dtls_construct_change_cipher_spec +SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST:385:\ + dtls_construct_hello_verify_request +SSL_F_DTLS_GET_REASSEMBLED_MESSAGE:370:dtls_get_reassembled_message +SSL_F_DTLS_PROCESS_HELLO_VERIFY:386:dtls_process_hello_verify +SSL_F_DTLS_RECORD_LAYER_NEW:635:DTLS_RECORD_LAYER_new +SSL_F_DTLS_WAIT_FOR_DRY:592:dtls_wait_for_dry +SSL_F_EARLY_DATA_COUNT_OK:532:early_data_count_ok +SSL_F_FINAL_EARLY_DATA:556:final_early_data +SSL_F_FINAL_EC_PT_FORMATS:485:final_ec_pt_formats +SSL_F_FINAL_EMS:486:final_ems +SSL_F_FINAL_KEY_SHARE:503:final_key_share +SSL_F_FINAL_MAXFRAGMENTLEN:557:final_maxfragmentlen +SSL_F_FINAL_RENEGOTIATE:483:final_renegotiate +SSL_F_FINAL_SERVER_NAME:558:final_server_name +SSL_F_FINAL_SIG_ALGS:497:final_sig_algs +SSL_F_GET_CERT_VERIFY_TBS_DATA:588:get_cert_verify_tbs_data +SSL_F_NSS_KEYLOG_INT:500:nss_keylog_int +SSL_F_OPENSSL_INIT_SSL:342:OPENSSL_init_ssl +SSL_F_OSSL_STATEM_CLIENT13_READ_TRANSITION:436:* +SSL_F_OSSL_STATEM_CLIENT13_WRITE_TRANSITION:598:\ + ossl_statem_client13_write_transition +SSL_F_OSSL_STATEM_CLIENT_CONSTRUCT_MESSAGE:430:* +SSL_F_OSSL_STATEM_CLIENT_POST_PROCESS_MESSAGE:593:\ + ossl_statem_client_post_process_message +SSL_F_OSSL_STATEM_CLIENT_PROCESS_MESSAGE:594:ossl_statem_client_process_message +SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION:417:ossl_statem_client_read_transition +SSL_F_OSSL_STATEM_CLIENT_WRITE_TRANSITION:599:\ + ossl_statem_client_write_transition +SSL_F_OSSL_STATEM_SERVER13_READ_TRANSITION:437:* +SSL_F_OSSL_STATEM_SERVER13_WRITE_TRANSITION:600:\ + ossl_statem_server13_write_transition +SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE:431:* +SSL_F_OSSL_STATEM_SERVER_POST_PROCESS_MESSAGE:601:\ + ossl_statem_server_post_process_message +SSL_F_OSSL_STATEM_SERVER_POST_WORK:602:ossl_statem_server_post_work +SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE:603:ossl_statem_server_process_message +SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION:418:ossl_statem_server_read_transition +SSL_F_OSSL_STATEM_SERVER_WRITE_TRANSITION:604:\ + ossl_statem_server_write_transition +SSL_F_PARSE_CA_NAMES:541:parse_ca_names +SSL_F_PITEM_NEW:624:pitem_new +SSL_F_PQUEUE_NEW:625:pqueue_new +SSL_F_PROCESS_KEY_SHARE_EXT:439:* +SSL_F_READ_STATE_MACHINE:352:read_state_machine +SSL_F_SET_CLIENT_CIPHERSUITE:540:set_client_ciphersuite +SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET:595:srp_generate_client_master_secret +SSL_F_SRP_GENERATE_SERVER_MASTER_SECRET:589:srp_generate_server_master_secret +SSL_F_SRP_VERIFY_SERVER_PARAM:596:srp_verify_server_param +SSL_F_SSL3_CHANGE_CIPHER_STATE:129:ssl3_change_cipher_state +SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM:130:ssl3_check_cert_and_algorithm +SSL_F_SSL3_CTRL:213:ssl3_ctrl +SSL_F_SSL3_CTX_CTRL:133:ssl3_ctx_ctrl +SSL_F_SSL3_DIGEST_CACHED_RECORDS:293:ssl3_digest_cached_records +SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC:292:ssl3_do_change_cipher_spec +SSL_F_SSL3_ENC:608:ssl3_enc +SSL_F_SSL3_FINAL_FINISH_MAC:285:ssl3_final_finish_mac +SSL_F_SSL3_FINISH_MAC:587:ssl3_finish_mac +SSL_F_SSL3_GENERATE_KEY_BLOCK:238:ssl3_generate_key_block +SSL_F_SSL3_GENERATE_MASTER_SECRET:388:ssl3_generate_master_secret +SSL_F_SSL3_GET_RECORD:143:ssl3_get_record +SSL_F_SSL3_INIT_FINISHED_MAC:397:ssl3_init_finished_mac +SSL_F_SSL3_OUTPUT_CERT_CHAIN:147:ssl3_output_cert_chain +SSL_F_SSL3_READ_BYTES:148:ssl3_read_bytes +SSL_F_SSL3_READ_N:149:ssl3_read_n +SSL_F_SSL3_SETUP_KEY_BLOCK:157:ssl3_setup_key_block +SSL_F_SSL3_SETUP_READ_BUFFER:156:ssl3_setup_read_buffer +SSL_F_SSL3_SETUP_WRITE_BUFFER:291:ssl3_setup_write_buffer +SSL_F_SSL3_WRITE_BYTES:158:ssl3_write_bytes +SSL_F_SSL3_WRITE_PENDING:159:ssl3_write_pending +SSL_F_SSL_ADD_CERT_CHAIN:316:ssl_add_cert_chain +SSL_F_SSL_ADD_CERT_TO_BUF:319:* +SSL_F_SSL_ADD_CERT_TO_WPACKET:493:ssl_add_cert_to_wpacket +SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT:298:* +SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT:277:* +SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT:307:* +SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK:215:SSL_add_dir_cert_subjects_to_stack +SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK:216:\ + SSL_add_file_cert_subjects_to_stack +SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT:299:* +SSL_F_SSL_ADD_SERVERHELLO_TLSEXT:278:* +SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT:308:* +SSL_F_SSL_BAD_METHOD:160:ssl_bad_method +SSL_F_SSL_BUILD_CERT_CHAIN:332:ssl_build_cert_chain +SSL_F_SSL_BYTES_TO_CIPHER_LIST:161:SSL_bytes_to_cipher_list +SSL_F_SSL_CACHE_CIPHERLIST:520:ssl_cache_cipherlist +SSL_F_SSL_CERT_ADD0_CHAIN_CERT:346:ssl_cert_add0_chain_cert +SSL_F_SSL_CERT_DUP:221:ssl_cert_dup +SSL_F_SSL_CERT_NEW:162:ssl_cert_new +SSL_F_SSL_CERT_SET0_CHAIN:340:ssl_cert_set0_chain +SSL_F_SSL_CHECK_PRIVATE_KEY:163:SSL_check_private_key +SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT:280:* +SSL_F_SSL_CHECK_SRP_EXT_CLIENTHELLO:606:ssl_check_srp_ext_ClientHello +SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG:279:ssl_check_srvr_ecc_cert_and_alg +SSL_F_SSL_CHOOSE_CLIENT_VERSION:607:ssl_choose_client_version +SSL_F_SSL_CIPHER_DESCRIPTION:626:SSL_CIPHER_description +SSL_F_SSL_CIPHER_LIST_TO_BYTES:425:ssl_cipher_list_to_bytes +SSL_F_SSL_CIPHER_PROCESS_RULESTR:230:ssl_cipher_process_rulestr +SSL_F_SSL_CIPHER_STRENGTH_SORT:231:ssl_cipher_strength_sort +SSL_F_SSL_CLEAR:164:SSL_clear +SSL_F_SSL_CLIENT_HELLO_GET1_EXTENSIONS_PRESENT:627:\ + SSL_client_hello_get1_extensions_present +SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD:165:SSL_COMP_add_compression_method +SSL_F_SSL_CONF_CMD:334:SSL_CONF_cmd +SSL_F_SSL_CREATE_CIPHER_LIST:166:ssl_create_cipher_list +SSL_F_SSL_CTRL:232:SSL_ctrl +SSL_F_SSL_CTX_CHECK_PRIVATE_KEY:168:SSL_CTX_check_private_key +SSL_F_SSL_CTX_ENABLE_CT:398:SSL_CTX_enable_ct +SSL_F_SSL_CTX_MAKE_PROFILES:309:ssl_ctx_make_profiles +SSL_F_SSL_CTX_NEW:169:SSL_CTX_new +SSL_F_SSL_CTX_SET_ALPN_PROTOS:343:SSL_CTX_set_alpn_protos +SSL_F_SSL_CTX_SET_CIPHER_LIST:269:SSL_CTX_set_cipher_list +SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE:290:SSL_CTX_set_client_cert_engine +SSL_F_SSL_CTX_SET_CT_VALIDATION_CALLBACK:396:SSL_CTX_set_ct_validation_callback +SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT:219:SSL_CTX_set_session_id_context +SSL_F_SSL_CTX_SET_SSL_VERSION:170:SSL_CTX_set_ssl_version +SSL_F_SSL_CTX_SET_TLSEXT_MAX_FRAGMENT_LENGTH:551:\ + SSL_CTX_set_tlsext_max_fragment_length +SSL_F_SSL_CTX_USE_CERTIFICATE:171:SSL_CTX_use_certificate +SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1:172:SSL_CTX_use_certificate_ASN1 +SSL_F_SSL_CTX_USE_CERTIFICATE_FILE:173:SSL_CTX_use_certificate_file +SSL_F_SSL_CTX_USE_PRIVATEKEY:174:SSL_CTX_use_PrivateKey +SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1:175:SSL_CTX_use_PrivateKey_ASN1 +SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE:176:SSL_CTX_use_PrivateKey_file +SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT:272:SSL_CTX_use_psk_identity_hint +SSL_F_SSL_CTX_USE_RSAPRIVATEKEY:177:SSL_CTX_use_RSAPrivateKey +SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1:178:SSL_CTX_use_RSAPrivateKey_ASN1 +SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE:179:SSL_CTX_use_RSAPrivateKey_file +SSL_F_SSL_CTX_USE_SERVERINFO:336:SSL_CTX_use_serverinfo +SSL_F_SSL_CTX_USE_SERVERINFO_EX:543:SSL_CTX_use_serverinfo_ex +SSL_F_SSL_CTX_USE_SERVERINFO_FILE:337:SSL_CTX_use_serverinfo_file +SSL_F_SSL_DANE_DUP:403:ssl_dane_dup +SSL_F_SSL_DANE_ENABLE:395:SSL_dane_enable +SSL_F_SSL_DERIVE:590:ssl_derive +SSL_F_SSL_DO_CONFIG:391:ssl_do_config +SSL_F_SSL_DO_HANDSHAKE:180:SSL_do_handshake +SSL_F_SSL_DUP_CA_LIST:408:SSL_dup_CA_list +SSL_F_SSL_ENABLE_CT:402:SSL_enable_ct +SSL_F_SSL_GENERATE_PKEY_GROUP:559:ssl_generate_pkey_group +SSL_F_SSL_GENERATE_SESSION_ID:547:ssl_generate_session_id +SSL_F_SSL_GET_NEW_SESSION:181:ssl_get_new_session +SSL_F_SSL_GET_PREV_SESSION:217:ssl_get_prev_session +SSL_F_SSL_GET_SERVER_CERT_INDEX:322:* +SSL_F_SSL_GET_SIGN_PKEY:183:* +SSL_F_SSL_HANDSHAKE_HASH:560:ssl_handshake_hash +SSL_F_SSL_INIT_WBIO_BUFFER:184:ssl_init_wbio_buffer +SSL_F_SSL_KEY_UPDATE:515:SSL_key_update +SSL_F_SSL_LOAD_CLIENT_CA_FILE:185:SSL_load_client_CA_file +SSL_F_SSL_LOG_MASTER_SECRET:498:* +SSL_F_SSL_LOG_RSA_CLIENT_KEY_EXCHANGE:499:ssl_log_rsa_client_key_exchange +SSL_F_SSL_MODULE_INIT:392:ssl_module_init +SSL_F_SSL_NEW:186:SSL_new +SSL_F_SSL_NEXT_PROTO_VALIDATE:565:ssl_next_proto_validate +SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT:300:* +SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT:302:* +SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT:310:* +SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT:301:* +SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT:303:* +SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT:311:* +SSL_F_SSL_PEEK:270:SSL_peek +SSL_F_SSL_PEEK_EX:432:SSL_peek_ex +SSL_F_SSL_PEEK_INTERNAL:522:ssl_peek_internal +SSL_F_SSL_READ:223:SSL_read +SSL_F_SSL_READ_EARLY_DATA:529:SSL_read_early_data +SSL_F_SSL_READ_EX:434:SSL_read_ex +SSL_F_SSL_READ_INTERNAL:523:ssl_read_internal +SSL_F_SSL_RENEGOTIATE:516:SSL_renegotiate +SSL_F_SSL_RENEGOTIATE_ABBREVIATED:546:SSL_renegotiate_abbreviated +SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT:320:* +SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT:321:* +SSL_F_SSL_SESSION_DUP:348:ssl_session_dup +SSL_F_SSL_SESSION_NEW:189:SSL_SESSION_new +SSL_F_SSL_SESSION_PRINT_FP:190:SSL_SESSION_print_fp +SSL_F_SSL_SESSION_SET1_ID:423:SSL_SESSION_set1_id +SSL_F_SSL_SESSION_SET1_ID_CONTEXT:312:SSL_SESSION_set1_id_context +SSL_F_SSL_SET_ALPN_PROTOS:344:SSL_set_alpn_protos +SSL_F_SSL_SET_CERT:191:ssl_set_cert +SSL_F_SSL_SET_CERT_AND_KEY:621:ssl_set_cert_and_key +SSL_F_SSL_SET_CIPHER_LIST:271:SSL_set_cipher_list +SSL_F_SSL_SET_CT_VALIDATION_CALLBACK:399:SSL_set_ct_validation_callback +SSL_F_SSL_SET_FD:192:SSL_set_fd +SSL_F_SSL_SET_PKEY:193:ssl_set_pkey +SSL_F_SSL_SET_RFD:194:SSL_set_rfd +SSL_F_SSL_SET_SESSION:195:SSL_set_session +SSL_F_SSL_SET_SESSION_ID_CONTEXT:218:SSL_set_session_id_context +SSL_F_SSL_SET_SESSION_TICKET_EXT:294:SSL_set_session_ticket_ext +SSL_F_SSL_SET_TLSEXT_MAX_FRAGMENT_LENGTH:550:SSL_set_tlsext_max_fragment_length +SSL_F_SSL_SET_WFD:196:SSL_set_wfd +SSL_F_SSL_SHUTDOWN:224:SSL_shutdown +SSL_F_SSL_SRP_CTX_INIT:313:SSL_SRP_CTX_init +SSL_F_SSL_START_ASYNC_JOB:389:ssl_start_async_job +SSL_F_SSL_UNDEFINED_FUNCTION:197:ssl_undefined_function +SSL_F_SSL_UNDEFINED_VOID_FUNCTION:244:ssl_undefined_void_function +SSL_F_SSL_USE_CERTIFICATE:198:SSL_use_certificate +SSL_F_SSL_USE_CERTIFICATE_ASN1:199:SSL_use_certificate_ASN1 +SSL_F_SSL_USE_CERTIFICATE_FILE:200:SSL_use_certificate_file +SSL_F_SSL_USE_PRIVATEKEY:201:SSL_use_PrivateKey +SSL_F_SSL_USE_PRIVATEKEY_ASN1:202:SSL_use_PrivateKey_ASN1 +SSL_F_SSL_USE_PRIVATEKEY_FILE:203:SSL_use_PrivateKey_file +SSL_F_SSL_USE_PSK_IDENTITY_HINT:273:SSL_use_psk_identity_hint +SSL_F_SSL_USE_RSAPRIVATEKEY:204:SSL_use_RSAPrivateKey +SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1:205:SSL_use_RSAPrivateKey_ASN1 +SSL_F_SSL_USE_RSAPRIVATEKEY_FILE:206:SSL_use_RSAPrivateKey_file +SSL_F_SSL_VALIDATE_CT:400:ssl_validate_ct +SSL_F_SSL_VERIFY_CERT_CHAIN:207:ssl_verify_cert_chain +SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE:616:SSL_verify_client_post_handshake +SSL_F_SSL_WRITE:208:SSL_write +SSL_F_SSL_WRITE_EARLY_DATA:526:SSL_write_early_data +SSL_F_SSL_WRITE_EARLY_FINISH:527:* +SSL_F_SSL_WRITE_EX:433:SSL_write_ex +SSL_F_SSL_WRITE_INTERNAL:524:ssl_write_internal +SSL_F_STATE_MACHINE:353:state_machine +SSL_F_TLS12_CHECK_PEER_SIGALG:333:tls12_check_peer_sigalg +SSL_F_TLS12_COPY_SIGALGS:533:tls12_copy_sigalgs +SSL_F_TLS13_CHANGE_CIPHER_STATE:440:tls13_change_cipher_state +SSL_F_TLS13_ENC:609:tls13_enc +SSL_F_TLS13_FINAL_FINISH_MAC:605:tls13_final_finish_mac +SSL_F_TLS13_GENERATE_SECRET:591:tls13_generate_secret +SSL_F_TLS13_HKDF_EXPAND:561:tls13_hkdf_expand +SSL_F_TLS13_RESTORE_HANDSHAKE_DIGEST_FOR_PHA:617:\ + tls13_restore_handshake_digest_for_pha +SSL_F_TLS13_SAVE_HANDSHAKE_DIGEST_FOR_PHA:618:\ + tls13_save_handshake_digest_for_pha +SSL_F_TLS13_SETUP_KEY_BLOCK:441:tls13_setup_key_block +SSL_F_TLS1_CHANGE_CIPHER_STATE:209:tls1_change_cipher_state +SSL_F_TLS1_CHECK_DUPLICATE_EXTENSIONS:341:* +SSL_F_TLS1_ENC:401:tls1_enc +SSL_F_TLS1_EXPORT_KEYING_MATERIAL:314:tls1_export_keying_material +SSL_F_TLS1_GET_CURVELIST:338:tls1_get_curvelist +SSL_F_TLS1_PRF:284:tls1_PRF +SSL_F_TLS1_SAVE_U16:628:tls1_save_u16 +SSL_F_TLS1_SETUP_KEY_BLOCK:211:tls1_setup_key_block +SSL_F_TLS1_SET_GROUPS:629:tls1_set_groups +SSL_F_TLS1_SET_RAW_SIGALGS:630:tls1_set_raw_sigalgs +SSL_F_TLS1_SET_SERVER_SIGALGS:335:tls1_set_server_sigalgs +SSL_F_TLS1_SET_SHARED_SIGALGS:631:tls1_set_shared_sigalgs +SSL_F_TLS1_SET_SIGALGS:632:tls1_set_sigalgs +SSL_F_TLS_CHOOSE_SIGALG:513:tls_choose_sigalg +SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK:354:tls_client_key_exchange_post_work +SSL_F_TLS_COLLECT_EXTENSIONS:435:tls_collect_extensions +SSL_F_TLS_CONSTRUCT_CERTIFICATE_AUTHORITIES:542:\ + tls_construct_certificate_authorities +SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST:372:tls_construct_certificate_request +SSL_F_TLS_CONSTRUCT_CERT_STATUS:429:* +SSL_F_TLS_CONSTRUCT_CERT_STATUS_BODY:494:tls_construct_cert_status_body +SSL_F_TLS_CONSTRUCT_CERT_VERIFY:496:tls_construct_cert_verify +SSL_F_TLS_CONSTRUCT_CHANGE_CIPHER_SPEC:427:tls_construct_change_cipher_spec +SSL_F_TLS_CONSTRUCT_CKE_DHE:404:tls_construct_cke_dhe +SSL_F_TLS_CONSTRUCT_CKE_ECDHE:405:tls_construct_cke_ecdhe +SSL_F_TLS_CONSTRUCT_CKE_GOST:406:tls_construct_cke_gost +SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE:407:tls_construct_cke_psk_preamble +SSL_F_TLS_CONSTRUCT_CKE_RSA:409:tls_construct_cke_rsa +SSL_F_TLS_CONSTRUCT_CKE_SRP:410:tls_construct_cke_srp +SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE:484:tls_construct_client_certificate +SSL_F_TLS_CONSTRUCT_CLIENT_HELLO:487:tls_construct_client_hello +SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE:488:tls_construct_client_key_exchange +SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY:489:* +SSL_F_TLS_CONSTRUCT_CTOS_ALPN:466:tls_construct_ctos_alpn +SSL_F_TLS_CONSTRUCT_CTOS_CERTIFICATE:355:* +SSL_F_TLS_CONSTRUCT_CTOS_COOKIE:535:tls_construct_ctos_cookie +SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA:530:tls_construct_ctos_early_data +SSL_F_TLS_CONSTRUCT_CTOS_EC_PT_FORMATS:467:tls_construct_ctos_ec_pt_formats +SSL_F_TLS_CONSTRUCT_CTOS_EMS:468:tls_construct_ctos_ems +SSL_F_TLS_CONSTRUCT_CTOS_ETM:469:tls_construct_ctos_etm +SSL_F_TLS_CONSTRUCT_CTOS_HELLO:356:* +SSL_F_TLS_CONSTRUCT_CTOS_KEY_EXCHANGE:357:* +SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE:470:tls_construct_ctos_key_share +SSL_F_TLS_CONSTRUCT_CTOS_MAXFRAGMENTLEN:549:tls_construct_ctos_maxfragmentlen +SSL_F_TLS_CONSTRUCT_CTOS_NPN:471:tls_construct_ctos_npn +SSL_F_TLS_CONSTRUCT_CTOS_PADDING:472:tls_construct_ctos_padding +SSL_F_TLS_CONSTRUCT_CTOS_POST_HANDSHAKE_AUTH:619:\ + tls_construct_ctos_post_handshake_auth +SSL_F_TLS_CONSTRUCT_CTOS_PSK:501:tls_construct_ctos_psk +SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES:509:tls_construct_ctos_psk_kex_modes +SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE:473:tls_construct_ctos_renegotiate +SSL_F_TLS_CONSTRUCT_CTOS_SCT:474:tls_construct_ctos_sct +SSL_F_TLS_CONSTRUCT_CTOS_SERVER_NAME:475:tls_construct_ctos_server_name +SSL_F_TLS_CONSTRUCT_CTOS_SESSION_TICKET:476:tls_construct_ctos_session_ticket +SSL_F_TLS_CONSTRUCT_CTOS_SIG_ALGS:477:tls_construct_ctos_sig_algs +SSL_F_TLS_CONSTRUCT_CTOS_SRP:478:tls_construct_ctos_srp +SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST:479:tls_construct_ctos_status_request +SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS:480:\ + tls_construct_ctos_supported_groups +SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS:481:\ + tls_construct_ctos_supported_versions +SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP:482:tls_construct_ctos_use_srtp +SSL_F_TLS_CONSTRUCT_CTOS_VERIFY:358:* +SSL_F_TLS_CONSTRUCT_ENCRYPTED_EXTENSIONS:443:tls_construct_encrypted_extensions +SSL_F_TLS_CONSTRUCT_END_OF_EARLY_DATA:536:tls_construct_end_of_early_data +SSL_F_TLS_CONSTRUCT_EXTENSIONS:447:tls_construct_extensions +SSL_F_TLS_CONSTRUCT_FINISHED:359:tls_construct_finished +SSL_F_TLS_CONSTRUCT_HELLO_REQUEST:373:* +SSL_F_TLS_CONSTRUCT_HELLO_RETRY_REQUEST:510:tls_construct_hello_retry_request +SSL_F_TLS_CONSTRUCT_KEY_UPDATE:517:tls_construct_key_update +SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET:428:tls_construct_new_session_ticket +SSL_F_TLS_CONSTRUCT_NEXT_PROTO:426:tls_construct_next_proto +SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE:490:tls_construct_server_certificate +SSL_F_TLS_CONSTRUCT_SERVER_HELLO:491:tls_construct_server_hello +SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE:492:tls_construct_server_key_exchange +SSL_F_TLS_CONSTRUCT_STOC_ALPN:451:tls_construct_stoc_alpn +SSL_F_TLS_CONSTRUCT_STOC_CERTIFICATE:374:* +SSL_F_TLS_CONSTRUCT_STOC_COOKIE:613:tls_construct_stoc_cookie +SSL_F_TLS_CONSTRUCT_STOC_CRYPTOPRO_BUG:452:tls_construct_stoc_cryptopro_bug +SSL_F_TLS_CONSTRUCT_STOC_DONE:375:* +SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA:531:tls_construct_stoc_early_data +SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA_INFO:525:* +SSL_F_TLS_CONSTRUCT_STOC_EC_PT_FORMATS:453:tls_construct_stoc_ec_pt_formats +SSL_F_TLS_CONSTRUCT_STOC_EMS:454:tls_construct_stoc_ems +SSL_F_TLS_CONSTRUCT_STOC_ETM:455:tls_construct_stoc_etm +SSL_F_TLS_CONSTRUCT_STOC_HELLO:376:* +SSL_F_TLS_CONSTRUCT_STOC_KEY_EXCHANGE:377:* +SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE:456:tls_construct_stoc_key_share +SSL_F_TLS_CONSTRUCT_STOC_MAXFRAGMENTLEN:548:tls_construct_stoc_maxfragmentlen +SSL_F_TLS_CONSTRUCT_STOC_NEXT_PROTO_NEG:457:tls_construct_stoc_next_proto_neg +SSL_F_TLS_CONSTRUCT_STOC_PSK:504:tls_construct_stoc_psk +SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE:458:tls_construct_stoc_renegotiate +SSL_F_TLS_CONSTRUCT_STOC_SERVER_NAME:459:tls_construct_stoc_server_name +SSL_F_TLS_CONSTRUCT_STOC_SESSION_TICKET:460:tls_construct_stoc_session_ticket +SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST:461:tls_construct_stoc_status_request +SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS:544:\ + tls_construct_stoc_supported_groups +SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS:611:\ + tls_construct_stoc_supported_versions +SSL_F_TLS_CONSTRUCT_STOC_USE_SRTP:462:tls_construct_stoc_use_srtp +SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO:521:\ + tls_early_post_process_client_hello +SSL_F_TLS_FINISH_HANDSHAKE:597:tls_finish_handshake +SSL_F_TLS_GET_MESSAGE_BODY:351:tls_get_message_body +SSL_F_TLS_GET_MESSAGE_HEADER:387:tls_get_message_header +SSL_F_TLS_HANDLE_ALPN:562:tls_handle_alpn +SSL_F_TLS_HANDLE_STATUS_REQUEST:563:tls_handle_status_request +SSL_F_TLS_PARSE_CERTIFICATE_AUTHORITIES:566:tls_parse_certificate_authorities +SSL_F_TLS_PARSE_CLIENTHELLO_TLSEXT:449:* +SSL_F_TLS_PARSE_CTOS_ALPN:567:tls_parse_ctos_alpn +SSL_F_TLS_PARSE_CTOS_COOKIE:614:tls_parse_ctos_cookie +SSL_F_TLS_PARSE_CTOS_EARLY_DATA:568:tls_parse_ctos_early_data +SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS:569:tls_parse_ctos_ec_pt_formats +SSL_F_TLS_PARSE_CTOS_EMS:570:tls_parse_ctos_ems +SSL_F_TLS_PARSE_CTOS_KEY_SHARE:463:tls_parse_ctos_key_share +SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN:571:tls_parse_ctos_maxfragmentlen +SSL_F_TLS_PARSE_CTOS_POST_HANDSHAKE_AUTH:620:tls_parse_ctos_post_handshake_auth +SSL_F_TLS_PARSE_CTOS_PSK:505:tls_parse_ctos_psk +SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES:572:tls_parse_ctos_psk_kex_modes +SSL_F_TLS_PARSE_CTOS_RENEGOTIATE:464:tls_parse_ctos_renegotiate +SSL_F_TLS_PARSE_CTOS_SERVER_NAME:573:tls_parse_ctos_server_name +SSL_F_TLS_PARSE_CTOS_SESSION_TICKET:574:tls_parse_ctos_session_ticket +SSL_F_TLS_PARSE_CTOS_SIG_ALGS:575:tls_parse_ctos_sig_algs +SSL_F_TLS_PARSE_CTOS_SIG_ALGS_CERT:615:tls_parse_ctos_sig_algs_cert +SSL_F_TLS_PARSE_CTOS_SRP:576:tls_parse_ctos_srp +SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST:577:tls_parse_ctos_status_request +SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS:578:tls_parse_ctos_supported_groups +SSL_F_TLS_PARSE_CTOS_USE_SRTP:465:tls_parse_ctos_use_srtp +SSL_F_TLS_PARSE_STOC_ALPN:579:tls_parse_stoc_alpn +SSL_F_TLS_PARSE_STOC_COOKIE:534:tls_parse_stoc_cookie +SSL_F_TLS_PARSE_STOC_EARLY_DATA:538:tls_parse_stoc_early_data +SSL_F_TLS_PARSE_STOC_EARLY_DATA_INFO:528:* +SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS:580:tls_parse_stoc_ec_pt_formats +SSL_F_TLS_PARSE_STOC_KEY_SHARE:445:tls_parse_stoc_key_share +SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN:581:tls_parse_stoc_maxfragmentlen +SSL_F_TLS_PARSE_STOC_NPN:582:tls_parse_stoc_npn +SSL_F_TLS_PARSE_STOC_PSK:502:tls_parse_stoc_psk +SSL_F_TLS_PARSE_STOC_RENEGOTIATE:448:tls_parse_stoc_renegotiate +SSL_F_TLS_PARSE_STOC_SCT:564:tls_parse_stoc_sct +SSL_F_TLS_PARSE_STOC_SERVER_NAME:583:tls_parse_stoc_server_name +SSL_F_TLS_PARSE_STOC_SESSION_TICKET:584:tls_parse_stoc_session_ticket +SSL_F_TLS_PARSE_STOC_STATUS_REQUEST:585:tls_parse_stoc_status_request +SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS:612:tls_parse_stoc_supported_versions +SSL_F_TLS_PARSE_STOC_USE_SRTP:446:tls_parse_stoc_use_srtp +SSL_F_TLS_POST_PROCESS_CLIENT_HELLO:378:tls_post_process_client_hello +SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE:384:\ + tls_post_process_client_key_exchange +SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE:360:tls_prepare_client_certificate +SSL_F_TLS_PROCESS_AS_HELLO_RETRY_REQUEST:610:tls_process_as_hello_retry_request +SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST:361:tls_process_certificate_request +SSL_F_TLS_PROCESS_CERT_STATUS:362:* +SSL_F_TLS_PROCESS_CERT_STATUS_BODY:495:tls_process_cert_status_body +SSL_F_TLS_PROCESS_CERT_VERIFY:379:tls_process_cert_verify +SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC:363:tls_process_change_cipher_spec +SSL_F_TLS_PROCESS_CKE_DHE:411:tls_process_cke_dhe +SSL_F_TLS_PROCESS_CKE_ECDHE:412:tls_process_cke_ecdhe +SSL_F_TLS_PROCESS_CKE_GOST:413:tls_process_cke_gost +SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE:414:tls_process_cke_psk_preamble +SSL_F_TLS_PROCESS_CKE_RSA:415:tls_process_cke_rsa +SSL_F_TLS_PROCESS_CKE_SRP:416:tls_process_cke_srp +SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE:380:tls_process_client_certificate +SSL_F_TLS_PROCESS_CLIENT_HELLO:381:tls_process_client_hello +SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE:382:tls_process_client_key_exchange +SSL_F_TLS_PROCESS_ENCRYPTED_EXTENSIONS:444:tls_process_encrypted_extensions +SSL_F_TLS_PROCESS_END_OF_EARLY_DATA:537:tls_process_end_of_early_data +SSL_F_TLS_PROCESS_FINISHED:364:tls_process_finished +SSL_F_TLS_PROCESS_HELLO_REQ:507:tls_process_hello_req +SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST:511:tls_process_hello_retry_request +SSL_F_TLS_PROCESS_INITIAL_SERVER_FLIGHT:442:tls_process_initial_server_flight +SSL_F_TLS_PROCESS_KEY_EXCHANGE:365:tls_process_key_exchange +SSL_F_TLS_PROCESS_KEY_UPDATE:518:tls_process_key_update +SSL_F_TLS_PROCESS_NEW_SESSION_TICKET:366:tls_process_new_session_ticket +SSL_F_TLS_PROCESS_NEXT_PROTO:383:tls_process_next_proto +SSL_F_TLS_PROCESS_SERVER_CERTIFICATE:367:tls_process_server_certificate +SSL_F_TLS_PROCESS_SERVER_DONE:368:tls_process_server_done +SSL_F_TLS_PROCESS_SERVER_HELLO:369:tls_process_server_hello +SSL_F_TLS_PROCESS_SKE_DHE:419:tls_process_ske_dhe +SSL_F_TLS_PROCESS_SKE_ECDHE:420:tls_process_ske_ecdhe +SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE:421:tls_process_ske_psk_preamble +SSL_F_TLS_PROCESS_SKE_SRP:422:tls_process_ske_srp +SSL_F_TLS_PSK_DO_BINDER:506:tls_psk_do_binder +SSL_F_TLS_SCAN_CLIENTHELLO_TLSEXT:450:* +SSL_F_TLS_SETUP_HANDSHAKE:508:tls_setup_handshake +SSL_F_USE_CERTIFICATE_CHAIN_FILE:220:use_certificate_chain_file +SSL_F_WPACKET_INTERN_INIT_LEN:633:wpacket_intern_init_len +SSL_F_WPACKET_START_SUB_PACKET_LEN__:634:WPACKET_start_sub_packet_len__ +SSL_F_WRITE_STATE_MACHINE:586:write_state_machine +TS_F_DEF_SERIAL_CB:110:def_serial_cb +TS_F_DEF_TIME_CB:111:def_time_cb +TS_F_ESS_ADD_SIGNING_CERT:112:ess_add_signing_cert +TS_F_ESS_ADD_SIGNING_CERT_V2:147:ess_add_signing_cert_v2 +TS_F_ESS_CERT_ID_NEW_INIT:113:ess_CERT_ID_new_init +TS_F_ESS_CERT_ID_V2_NEW_INIT:156:ess_cert_id_v2_new_init +TS_F_ESS_SIGNING_CERT_NEW_INIT:114:ess_SIGNING_CERT_new_init +TS_F_ESS_SIGNING_CERT_V2_NEW_INIT:157:ess_signing_cert_v2_new_init +TS_F_INT_TS_RESP_VERIFY_TOKEN:149:int_ts_RESP_verify_token +TS_F_PKCS7_TO_TS_TST_INFO:148:PKCS7_to_TS_TST_INFO +TS_F_TS_ACCURACY_SET_MICROS:115:TS_ACCURACY_set_micros +TS_F_TS_ACCURACY_SET_MILLIS:116:TS_ACCURACY_set_millis +TS_F_TS_ACCURACY_SET_SECONDS:117:TS_ACCURACY_set_seconds +TS_F_TS_CHECK_IMPRINTS:100:ts_check_imprints +TS_F_TS_CHECK_NONCES:101:ts_check_nonces +TS_F_TS_CHECK_POLICY:102:ts_check_policy +TS_F_TS_CHECK_SIGNING_CERTS:103:ts_check_signing_certs +TS_F_TS_CHECK_STATUS_INFO:104:ts_check_status_info +TS_F_TS_COMPUTE_IMPRINT:145:ts_compute_imprint +TS_F_TS_CONF_INVALID:151:ts_CONF_invalid +TS_F_TS_CONF_LOAD_CERT:153:TS_CONF_load_cert +TS_F_TS_CONF_LOAD_CERTS:154:TS_CONF_load_certs +TS_F_TS_CONF_LOAD_KEY:155:TS_CONF_load_key +TS_F_TS_CONF_LOOKUP_FAIL:152:ts_CONF_lookup_fail +TS_F_TS_CONF_SET_DEFAULT_ENGINE:146:TS_CONF_set_default_engine +TS_F_TS_GET_STATUS_TEXT:105:ts_get_status_text +TS_F_TS_MSG_IMPRINT_SET_ALGO:118:TS_MSG_IMPRINT_set_algo +TS_F_TS_REQ_SET_MSG_IMPRINT:119:TS_REQ_set_msg_imprint +TS_F_TS_REQ_SET_NONCE:120:TS_REQ_set_nonce +TS_F_TS_REQ_SET_POLICY_ID:121:TS_REQ_set_policy_id +TS_F_TS_RESP_CREATE_RESPONSE:122:TS_RESP_create_response +TS_F_TS_RESP_CREATE_TST_INFO:123:ts_RESP_create_tst_info +TS_F_TS_RESP_CTX_ADD_FAILURE_INFO:124:TS_RESP_CTX_add_failure_info +TS_F_TS_RESP_CTX_ADD_MD:125:TS_RESP_CTX_add_md +TS_F_TS_RESP_CTX_ADD_POLICY:126:TS_RESP_CTX_add_policy +TS_F_TS_RESP_CTX_NEW:127:TS_RESP_CTX_new +TS_F_TS_RESP_CTX_SET_ACCURACY:128:TS_RESP_CTX_set_accuracy +TS_F_TS_RESP_CTX_SET_CERTS:129:TS_RESP_CTX_set_certs +TS_F_TS_RESP_CTX_SET_DEF_POLICY:130:TS_RESP_CTX_set_def_policy +TS_F_TS_RESP_CTX_SET_SIGNER_CERT:131:TS_RESP_CTX_set_signer_cert +TS_F_TS_RESP_CTX_SET_STATUS_INFO:132:TS_RESP_CTX_set_status_info +TS_F_TS_RESP_GET_POLICY:133:ts_RESP_get_policy +TS_F_TS_RESP_SET_GENTIME_WITH_PRECISION:134:TS_RESP_set_genTime_with_precision +TS_F_TS_RESP_SET_STATUS_INFO:135:TS_RESP_set_status_info +TS_F_TS_RESP_SET_TST_INFO:150:TS_RESP_set_tst_info +TS_F_TS_RESP_SIGN:136:ts_RESP_sign +TS_F_TS_RESP_VERIFY_SIGNATURE:106:TS_RESP_verify_signature +TS_F_TS_TST_INFO_SET_ACCURACY:137:TS_TST_INFO_set_accuracy +TS_F_TS_TST_INFO_SET_MSG_IMPRINT:138:TS_TST_INFO_set_msg_imprint +TS_F_TS_TST_INFO_SET_NONCE:139:TS_TST_INFO_set_nonce +TS_F_TS_TST_INFO_SET_POLICY_ID:140:TS_TST_INFO_set_policy_id +TS_F_TS_TST_INFO_SET_SERIAL:141:TS_TST_INFO_set_serial +TS_F_TS_TST_INFO_SET_TIME:142:TS_TST_INFO_set_time +TS_F_TS_TST_INFO_SET_TSA:143:TS_TST_INFO_set_tsa +TS_F_TS_VERIFY:108:* +TS_F_TS_VERIFY_CERT:109:ts_verify_cert +TS_F_TS_VERIFY_CTX_NEW:144:TS_VERIFY_CTX_new +UI_F_CLOSE_CONSOLE:115:close_console +UI_F_ECHO_CONSOLE:116:echo_console +UI_F_GENERAL_ALLOCATE_BOOLEAN:108:general_allocate_boolean +UI_F_GENERAL_ALLOCATE_PROMPT:109:general_allocate_prompt +UI_F_NOECHO_CONSOLE:117:noecho_console +UI_F_OPEN_CONSOLE:114:open_console +UI_F_UI_CONSTRUCT_PROMPT:121:UI_construct_prompt +UI_F_UI_CREATE_METHOD:112:UI_create_method +UI_F_UI_CTRL:111:UI_ctrl +UI_F_UI_DUP_ERROR_STRING:101:UI_dup_error_string +UI_F_UI_DUP_INFO_STRING:102:UI_dup_info_string +UI_F_UI_DUP_INPUT_BOOLEAN:110:UI_dup_input_boolean +UI_F_UI_DUP_INPUT_STRING:103:UI_dup_input_string +UI_F_UI_DUP_USER_DATA:118:UI_dup_user_data +UI_F_UI_DUP_VERIFY_STRING:106:UI_dup_verify_string +UI_F_UI_GET0_RESULT:107:UI_get0_result +UI_F_UI_GET_RESULT_LENGTH:119:UI_get_result_length +UI_F_UI_NEW_METHOD:104:UI_new_method +UI_F_UI_PROCESS:113:UI_process +UI_F_UI_SET_RESULT:105:UI_set_result +UI_F_UI_SET_RESULT_EX:120:UI_set_result_ex +X509V3_F_A2I_GENERAL_NAME:164:a2i_GENERAL_NAME +X509V3_F_ADDR_VALIDATE_PATH_INTERNAL:166:addr_validate_path_internal +X509V3_F_ASIDENTIFIERCHOICE_CANONIZE:161:ASIdentifierChoice_canonize +X509V3_F_ASIDENTIFIERCHOICE_IS_CANONICAL:162:ASIdentifierChoice_is_canonical +X509V3_F_BIGNUM_TO_STRING:167:bignum_to_string +X509V3_F_COPY_EMAIL:122:copy_email +X509V3_F_COPY_ISSUER:123:copy_issuer +X509V3_F_DO_DIRNAME:144:do_dirname +X509V3_F_DO_EXT_I2D:135:do_ext_i2d +X509V3_F_DO_EXT_NCONF:151:do_ext_nconf +X509V3_F_GNAMES_FROM_SECTNAME:156:gnames_from_sectname +X509V3_F_I2S_ASN1_ENUMERATED:121:i2s_ASN1_ENUMERATED +X509V3_F_I2S_ASN1_IA5STRING:149:i2s_ASN1_IA5STRING +X509V3_F_I2S_ASN1_INTEGER:120:i2s_ASN1_INTEGER +X509V3_F_I2V_AUTHORITY_INFO_ACCESS:138:i2v_AUTHORITY_INFO_ACCESS +X509V3_F_LEVEL_ADD_NODE:168:level_add_node +X509V3_F_NOTICE_SECTION:132:notice_section +X509V3_F_NREF_NOS:133:nref_nos +X509V3_F_POLICY_CACHE_CREATE:169:policy_cache_create +X509V3_F_POLICY_CACHE_NEW:170:policy_cache_new +X509V3_F_POLICY_DATA_NEW:171:policy_data_new +X509V3_F_POLICY_SECTION:131:policy_section +X509V3_F_PROCESS_PCI_VALUE:150:process_pci_value +X509V3_F_R2I_CERTPOL:130:r2i_certpol +X509V3_F_R2I_PCI:155:r2i_pci +X509V3_F_S2I_ASN1_IA5STRING:100:s2i_ASN1_IA5STRING +X509V3_F_S2I_ASN1_INTEGER:108:s2i_ASN1_INTEGER +X509V3_F_S2I_ASN1_OCTET_STRING:112:s2i_ASN1_OCTET_STRING +X509V3_F_S2I_SKEY_ID:115:s2i_skey_id +X509V3_F_SET_DIST_POINT_NAME:158:set_dist_point_name +X509V3_F_SXNET_ADD_ID_ASC:125:SXNET_add_id_asc +X509V3_F_SXNET_ADD_ID_INTEGER:126:SXNET_add_id_INTEGER +X509V3_F_SXNET_ADD_ID_ULONG:127:SXNET_add_id_ulong +X509V3_F_SXNET_GET_ID_ASC:128:SXNET_get_id_asc +X509V3_F_SXNET_GET_ID_ULONG:129:SXNET_get_id_ulong +X509V3_F_TREE_INIT:172:tree_init +X509V3_F_V2I_ASIDENTIFIERS:163:v2i_ASIdentifiers +X509V3_F_V2I_ASN1_BIT_STRING:101:v2i_ASN1_BIT_STRING +X509V3_F_V2I_AUTHORITY_INFO_ACCESS:139:v2i_AUTHORITY_INFO_ACCESS +X509V3_F_V2I_AUTHORITY_KEYID:119:v2i_AUTHORITY_KEYID +X509V3_F_V2I_BASIC_CONSTRAINTS:102:v2i_BASIC_CONSTRAINTS +X509V3_F_V2I_CRLD:134:v2i_crld +X509V3_F_V2I_EXTENDED_KEY_USAGE:103:v2i_EXTENDED_KEY_USAGE +X509V3_F_V2I_GENERAL_NAMES:118:v2i_GENERAL_NAMES +X509V3_F_V2I_GENERAL_NAME_EX:117:v2i_GENERAL_NAME_ex +X509V3_F_V2I_IDP:157:v2i_idp +X509V3_F_V2I_IPADDRBLOCKS:159:v2i_IPAddrBlocks +X509V3_F_V2I_ISSUER_ALT:153:v2i_issuer_alt +X509V3_F_V2I_NAME_CONSTRAINTS:147:v2i_NAME_CONSTRAINTS +X509V3_F_V2I_POLICY_CONSTRAINTS:146:v2i_POLICY_CONSTRAINTS +X509V3_F_V2I_POLICY_MAPPINGS:145:v2i_POLICY_MAPPINGS +X509V3_F_V2I_SUBJECT_ALT:154:v2i_subject_alt +X509V3_F_V2I_TLS_FEATURE:165:v2i_TLS_FEATURE +X509V3_F_V3_GENERIC_EXTENSION:116:v3_generic_extension +X509V3_F_X509V3_ADD1_I2D:140:X509V3_add1_i2d +X509V3_F_X509V3_ADD_VALUE:105:X509V3_add_value +X509V3_F_X509V3_EXT_ADD:104:X509V3_EXT_add +X509V3_F_X509V3_EXT_ADD_ALIAS:106:X509V3_EXT_add_alias +X509V3_F_X509V3_EXT_I2D:136:X509V3_EXT_i2d +X509V3_F_X509V3_EXT_NCONF:152:X509V3_EXT_nconf +X509V3_F_X509V3_GET_SECTION:142:X509V3_get_section +X509V3_F_X509V3_GET_STRING:143:X509V3_get_string +X509V3_F_X509V3_GET_VALUE_BOOL:110:X509V3_get_value_bool +X509V3_F_X509V3_PARSE_LIST:109:X509V3_parse_list +X509V3_F_X509_PURPOSE_ADD:137:X509_PURPOSE_add +X509V3_F_X509_PURPOSE_SET:141:X509_PURPOSE_set +X509_F_ADD_CERT_DIR:100:add_cert_dir +X509_F_BUILD_CHAIN:106:build_chain +X509_F_BY_FILE_CTRL:101:by_file_ctrl +X509_F_CHECK_NAME_CONSTRAINTS:149:check_name_constraints +X509_F_CHECK_POLICY:145:check_policy +X509_F_DANE_I2D:107:dane_i2d +X509_F_DIR_CTRL:102:dir_ctrl +X509_F_GET_CERT_BY_SUBJECT:103:get_cert_by_subject +X509_F_I2D_X509_AUX:151:i2d_X509_AUX +X509_F_LOOKUP_CERTS_SK:152:lookup_certs_sk +X509_F_NETSCAPE_SPKI_B64_DECODE:129:NETSCAPE_SPKI_b64_decode +X509_F_NETSCAPE_SPKI_B64_ENCODE:130:NETSCAPE_SPKI_b64_encode +X509_F_NEW_DIR:153:new_dir +X509_F_X509AT_ADD1_ATTR:135:X509at_add1_attr +X509_F_X509V3_ADD_EXT:104:X509v3_add_ext +X509_F_X509_ATTRIBUTE_CREATE_BY_NID:136:X509_ATTRIBUTE_create_by_NID +X509_F_X509_ATTRIBUTE_CREATE_BY_OBJ:137:X509_ATTRIBUTE_create_by_OBJ +X509_F_X509_ATTRIBUTE_CREATE_BY_TXT:140:X509_ATTRIBUTE_create_by_txt +X509_F_X509_ATTRIBUTE_GET0_DATA:139:X509_ATTRIBUTE_get0_data +X509_F_X509_ATTRIBUTE_SET1_DATA:138:X509_ATTRIBUTE_set1_data +X509_F_X509_CHECK_PRIVATE_KEY:128:X509_check_private_key +X509_F_X509_CRL_DIFF:105:X509_CRL_diff +X509_F_X509_CRL_METHOD_NEW:154:X509_CRL_METHOD_new +X509_F_X509_CRL_PRINT_FP:147:X509_CRL_print_fp +X509_F_X509_EXTENSION_CREATE_BY_NID:108:X509_EXTENSION_create_by_NID +X509_F_X509_EXTENSION_CREATE_BY_OBJ:109:X509_EXTENSION_create_by_OBJ +X509_F_X509_GET_PUBKEY_PARAMETERS:110:X509_get_pubkey_parameters +X509_F_X509_LOAD_CERT_CRL_FILE:132:X509_load_cert_crl_file +X509_F_X509_LOAD_CERT_FILE:111:X509_load_cert_file +X509_F_X509_LOAD_CRL_FILE:112:X509_load_crl_file +X509_F_X509_LOOKUP_METH_NEW:160:X509_LOOKUP_meth_new +X509_F_X509_LOOKUP_NEW:155:X509_LOOKUP_new +X509_F_X509_NAME_ADD_ENTRY:113:X509_NAME_add_entry +X509_F_X509_NAME_CANON:156:x509_name_canon +X509_F_X509_NAME_ENTRY_CREATE_BY_NID:114:X509_NAME_ENTRY_create_by_NID +X509_F_X509_NAME_ENTRY_CREATE_BY_TXT:131:X509_NAME_ENTRY_create_by_txt +X509_F_X509_NAME_ENTRY_SET_OBJECT:115:X509_NAME_ENTRY_set_object +X509_F_X509_NAME_ONELINE:116:X509_NAME_oneline +X509_F_X509_NAME_PRINT:117:X509_NAME_print +X509_F_X509_OBJECT_NEW:150:X509_OBJECT_new +X509_F_X509_PRINT_EX_FP:118:X509_print_ex_fp +X509_F_X509_PUBKEY_DECODE:148:x509_pubkey_decode +X509_F_X509_PUBKEY_GET0:119:X509_PUBKEY_get0 +X509_F_X509_PUBKEY_SET:120:X509_PUBKEY_set +X509_F_X509_REQ_CHECK_PRIVATE_KEY:144:X509_REQ_check_private_key +X509_F_X509_REQ_PRINT_EX:121:X509_REQ_print_ex +X509_F_X509_REQ_PRINT_FP:122:X509_REQ_print_fp +X509_F_X509_REQ_TO_X509:123:X509_REQ_to_X509 +X509_F_X509_STORE_ADD_CERT:124:X509_STORE_add_cert +X509_F_X509_STORE_ADD_CRL:125:X509_STORE_add_crl +X509_F_X509_STORE_ADD_LOOKUP:157:X509_STORE_add_lookup +X509_F_X509_STORE_CTX_GET1_ISSUER:146:X509_STORE_CTX_get1_issuer +X509_F_X509_STORE_CTX_INIT:143:X509_STORE_CTX_init +X509_F_X509_STORE_CTX_NEW:142:X509_STORE_CTX_new +X509_F_X509_STORE_CTX_PURPOSE_INHERIT:134:X509_STORE_CTX_purpose_inherit +X509_F_X509_STORE_NEW:158:X509_STORE_new +X509_F_X509_TO_X509_REQ:126:X509_to_X509_REQ +X509_F_X509_TRUST_ADD:133:X509_TRUST_add +X509_F_X509_TRUST_SET:141:X509_TRUST_set +X509_F_X509_VERIFY_CERT:127:X509_verify_cert +X509_F_X509_VERIFY_PARAM_NEW:159:X509_VERIFY_PARAM_new + +#Reason codes +ASN1_R_ADDING_OBJECT:171:adding object +ASN1_R_ASN1_PARSE_ERROR:203:asn1 parse error +ASN1_R_ASN1_SIG_PARSE_ERROR:204:asn1 sig parse error +ASN1_R_AUX_ERROR:100:aux error +ASN1_R_BAD_OBJECT_HEADER:102:bad object header +ASN1_R_BMPSTRING_IS_WRONG_LENGTH:214:bmpstring is wrong length +ASN1_R_BN_LIB:105:bn lib +ASN1_R_BOOLEAN_IS_WRONG_LENGTH:106:boolean is wrong length +ASN1_R_BUFFER_TOO_SMALL:107:buffer too small +ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER:108:cipher has no object identifier +ASN1_R_CONTEXT_NOT_INITIALISED:217:context not initialised +ASN1_R_DATA_IS_WRONG:109:data is wrong +ASN1_R_DECODE_ERROR:110:decode error +ASN1_R_DEPTH_EXCEEDED:174:depth exceeded +ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED:198:digest and key type not supported +ASN1_R_ENCODE_ERROR:112:encode error +ASN1_R_ERROR_GETTING_TIME:173:error getting time +ASN1_R_ERROR_LOADING_SECTION:172:error loading section +ASN1_R_ERROR_SETTING_CIPHER_PARAMS:114:error setting cipher params +ASN1_R_EXPECTING_AN_INTEGER:115:expecting an integer +ASN1_R_EXPECTING_AN_OBJECT:116:expecting an object +ASN1_R_EXPLICIT_LENGTH_MISMATCH:119:explicit length mismatch +ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED:120:explicit tag not constructed +ASN1_R_FIELD_MISSING:121:field missing +ASN1_R_FIRST_NUM_TOO_LARGE:122:first num too large +ASN1_R_HEADER_TOO_LONG:123:header too long +ASN1_R_ILLEGAL_BITSTRING_FORMAT:175:illegal bitstring format +ASN1_R_ILLEGAL_BOOLEAN:176:illegal boolean +ASN1_R_ILLEGAL_CHARACTERS:124:illegal characters +ASN1_R_ILLEGAL_FORMAT:177:illegal format +ASN1_R_ILLEGAL_HEX:178:illegal hex +ASN1_R_ILLEGAL_IMPLICIT_TAG:179:illegal implicit tag +ASN1_R_ILLEGAL_INTEGER:180:illegal integer +ASN1_R_ILLEGAL_NEGATIVE_VALUE:226:illegal negative value +ASN1_R_ILLEGAL_NESTED_TAGGING:181:illegal nested tagging +ASN1_R_ILLEGAL_NULL:125:illegal null +ASN1_R_ILLEGAL_NULL_VALUE:182:illegal null value +ASN1_R_ILLEGAL_OBJECT:183:illegal object +ASN1_R_ILLEGAL_OPTIONAL_ANY:126:illegal optional any +ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE:170:illegal options on item template +ASN1_R_ILLEGAL_PADDING:221:illegal padding +ASN1_R_ILLEGAL_TAGGED_ANY:127:illegal tagged any +ASN1_R_ILLEGAL_TIME_VALUE:184:illegal time value +ASN1_R_ILLEGAL_ZERO_CONTENT:222:illegal zero content +ASN1_R_INTEGER_NOT_ASCII_FORMAT:185:integer not ascii format +ASN1_R_INTEGER_TOO_LARGE_FOR_LONG:128:integer too large for long +ASN1_R_INVALID_BIT_STRING_BITS_LEFT:220:invalid bit string bits left +ASN1_R_INVALID_BMPSTRING_LENGTH:129:invalid bmpstring length +ASN1_R_INVALID_DIGIT:130:invalid digit +ASN1_R_INVALID_MIME_TYPE:205:invalid mime type +ASN1_R_INVALID_MODIFIER:186:invalid modifier +ASN1_R_INVALID_NUMBER:187:invalid number +ASN1_R_INVALID_OBJECT_ENCODING:216:invalid object encoding +ASN1_R_INVALID_SCRYPT_PARAMETERS:227:invalid scrypt parameters +ASN1_R_INVALID_SEPARATOR:131:invalid separator +ASN1_R_INVALID_STRING_TABLE_VALUE:218:invalid string table value +ASN1_R_INVALID_UNIVERSALSTRING_LENGTH:133:invalid universalstring length +ASN1_R_INVALID_UTF8STRING:134:invalid utf8string +ASN1_R_INVALID_VALUE:219:invalid value +ASN1_R_LIST_ERROR:188:list error +ASN1_R_MIME_NO_CONTENT_TYPE:206:mime no content type +ASN1_R_MIME_PARSE_ERROR:207:mime parse error +ASN1_R_MIME_SIG_PARSE_ERROR:208:mime sig parse error +ASN1_R_MISSING_EOC:137:missing eoc +ASN1_R_MISSING_SECOND_NUMBER:138:missing second number +ASN1_R_MISSING_VALUE:189:missing value +ASN1_R_MSTRING_NOT_UNIVERSAL:139:mstring not universal +ASN1_R_MSTRING_WRONG_TAG:140:mstring wrong tag +ASN1_R_NESTED_ASN1_STRING:197:nested asn1 string +ASN1_R_NESTED_TOO_DEEP:201:nested too deep +ASN1_R_NON_HEX_CHARACTERS:141:non hex characters +ASN1_R_NOT_ASCII_FORMAT:190:not ascii format +ASN1_R_NOT_ENOUGH_DATA:142:not enough data +ASN1_R_NO_CONTENT_TYPE:209:no content type +ASN1_R_NO_MATCHING_CHOICE_TYPE:143:no matching choice type +ASN1_R_NO_MULTIPART_BODY_FAILURE:210:no multipart body failure +ASN1_R_NO_MULTIPART_BOUNDARY:211:no multipart boundary +ASN1_R_NO_SIG_CONTENT_TYPE:212:no sig content type +ASN1_R_NULL_IS_WRONG_LENGTH:144:null is wrong length +ASN1_R_OBJECT_NOT_ASCII_FORMAT:191:object not ascii format +ASN1_R_ODD_NUMBER_OF_CHARS:145:odd number of chars +ASN1_R_SECOND_NUMBER_TOO_LARGE:147:second number too large +ASN1_R_SEQUENCE_LENGTH_MISMATCH:148:sequence length mismatch +ASN1_R_SEQUENCE_NOT_CONSTRUCTED:149:sequence not constructed +ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG:192:sequence or set needs config +ASN1_R_SHORT_LINE:150:short line +ASN1_R_SIG_INVALID_MIME_TYPE:213:sig invalid mime type +ASN1_R_STREAMING_NOT_SUPPORTED:202:streaming not supported +ASN1_R_STRING_TOO_LONG:151:string too long +ASN1_R_STRING_TOO_SHORT:152:string too short +ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD:154:\ + the asn1 object identifier is not known for this md +ASN1_R_TIME_NOT_ASCII_FORMAT:193:time not ascii format +ASN1_R_TOO_LARGE:223:too large +ASN1_R_TOO_LONG:155:too long +ASN1_R_TOO_SMALL:224:too small +ASN1_R_TYPE_NOT_CONSTRUCTED:156:type not constructed +ASN1_R_TYPE_NOT_PRIMITIVE:195:type not primitive +ASN1_R_UNEXPECTED_EOC:159:unexpected eoc +ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH:215:universalstring is wrong length +ASN1_R_UNKNOWN_FORMAT:160:unknown format +ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM:161:unknown message digest algorithm +ASN1_R_UNKNOWN_OBJECT_TYPE:162:unknown object type +ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE:163:unknown public key type +ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM:199:unknown signature algorithm +ASN1_R_UNKNOWN_TAG:194:unknown tag +ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE:164:unsupported any defined by type +ASN1_R_UNSUPPORTED_CIPHER:228:unsupported cipher +ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE:167:unsupported public key type +ASN1_R_UNSUPPORTED_TYPE:196:unsupported type +ASN1_R_WRONG_INTEGER_TYPE:225:wrong integer type +ASN1_R_WRONG_PUBLIC_KEY_TYPE:200:wrong public key type +ASN1_R_WRONG_TAG:168:wrong tag +ASYNC_R_FAILED_TO_SET_POOL:101:failed to set pool +ASYNC_R_FAILED_TO_SWAP_CONTEXT:102:failed to swap context +ASYNC_R_INIT_FAILED:105:init failed +ASYNC_R_INVALID_POOL_SIZE:103:invalid pool size +BIO_R_ACCEPT_ERROR:100:accept error +BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET:141:addrinfo addr is not af inet +BIO_R_AMBIGUOUS_HOST_OR_SERVICE:129:ambiguous host or service +BIO_R_BAD_FOPEN_MODE:101:bad fopen mode +BIO_R_BROKEN_PIPE:124:broken pipe +BIO_R_CONNECT_ERROR:103:connect error +BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET:107:gethostbyname addr is not af inet +BIO_R_GETSOCKNAME_ERROR:132:getsockname error +BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS:133:getsockname truncated address +BIO_R_GETTING_SOCKTYPE:134:getting socktype +BIO_R_INVALID_ARGUMENT:125:invalid argument +BIO_R_INVALID_SOCKET:135:invalid socket +BIO_R_IN_USE:123:in use +BIO_R_LENGTH_TOO_LONG:102:length too long +BIO_R_LISTEN_V6_ONLY:136:listen v6 only +BIO_R_LOOKUP_RETURNED_NOTHING:142:lookup returned nothing +BIO_R_MALFORMED_HOST_OR_SERVICE:130:malformed host or service +BIO_R_NBIO_CONNECT_ERROR:110:nbio connect error +BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED:143:\ + no accept addr or service specified +BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED:144:no hostname or service specified +BIO_R_NO_PORT_DEFINED:113:no port defined +BIO_R_NO_SUCH_FILE:128:no such file +BIO_R_NULL_PARAMETER:115:null parameter +BIO_R_UNABLE_TO_BIND_SOCKET:117:unable to bind socket +BIO_R_UNABLE_TO_CREATE_SOCKET:118:unable to create socket +BIO_R_UNABLE_TO_KEEPALIVE:137:unable to keepalive +BIO_R_UNABLE_TO_LISTEN_SOCKET:119:unable to listen socket +BIO_R_UNABLE_TO_NODELAY:138:unable to nodelay +BIO_R_UNABLE_TO_REUSEADDR:139:unable to reuseaddr +BIO_R_UNAVAILABLE_IP_FAMILY:145:unavailable ip family +BIO_R_UNINITIALIZED:120:uninitialized +BIO_R_UNKNOWN_INFO_TYPE:140:unknown info type +BIO_R_UNSUPPORTED_IP_FAMILY:146:unsupported ip family +BIO_R_UNSUPPORTED_METHOD:121:unsupported method +BIO_R_UNSUPPORTED_PROTOCOL_FAMILY:131:unsupported protocol family +BIO_R_WRITE_TO_READ_ONLY_BIO:126:write to read only BIO +BIO_R_WSASTARTUP:122:WSAStartup +BN_R_ARG2_LT_ARG3:100:arg2 lt arg3 +BN_R_BAD_RECIPROCAL:101:bad reciprocal +BN_R_BIGNUM_TOO_LONG:114:bignum too long +BN_R_BITS_TOO_SMALL:118:bits too small +BN_R_CALLED_WITH_EVEN_MODULUS:102:called with even modulus +BN_R_DIV_BY_ZERO:103:div by zero +BN_R_ENCODING_ERROR:104:encoding error +BN_R_EXPAND_ON_STATIC_BIGNUM_DATA:105:expand on static bignum data +BN_R_INPUT_NOT_REDUCED:110:input not reduced +BN_R_INVALID_LENGTH:106:invalid length +BN_R_INVALID_RANGE:115:invalid range +BN_R_INVALID_SHIFT:119:invalid shift +BN_R_NOT_A_SQUARE:111:not a square +BN_R_NOT_INITIALIZED:107:not initialized +BN_R_NO_INVERSE:108:no inverse +BN_R_NO_SOLUTION:116:no solution +BN_R_PRIVATE_KEY_TOO_LARGE:117:private key too large +BN_R_P_IS_NOT_PRIME:112:p is not prime +BN_R_TOO_MANY_ITERATIONS:113:too many iterations +BN_R_TOO_MANY_TEMPORARY_VARIABLES:109:too many temporary variables +CMS_R_ADD_SIGNER_ERROR:99:add signer error +CMS_R_CERTIFICATE_ALREADY_PRESENT:175:certificate already present +CMS_R_CERTIFICATE_HAS_NO_KEYID:160:certificate has no keyid +CMS_R_CERTIFICATE_VERIFY_ERROR:100:certificate verify error +CMS_R_CIPHER_INITIALISATION_ERROR:101:cipher initialisation error +CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR:102:\ + cipher parameter initialisation error +CMS_R_CMS_DATAFINAL_ERROR:103:cms datafinal error +CMS_R_CMS_LIB:104:cms lib +CMS_R_CONTENTIDENTIFIER_MISMATCH:170:contentidentifier mismatch +CMS_R_CONTENT_NOT_FOUND:105:content not found +CMS_R_CONTENT_TYPE_MISMATCH:171:content type mismatch +CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA:106:content type not compressed data +CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA:107:content type not enveloped data +CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA:108:content type not signed data +CMS_R_CONTENT_VERIFY_ERROR:109:content verify error +CMS_R_CTRL_ERROR:110:ctrl error +CMS_R_CTRL_FAILURE:111:ctrl failure +CMS_R_DECRYPT_ERROR:112:decrypt error +CMS_R_ERROR_GETTING_PUBLIC_KEY:113:error getting public key +CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE:114:\ + error reading messagedigest attribute +CMS_R_ERROR_SETTING_KEY:115:error setting key +CMS_R_ERROR_SETTING_RECIPIENTINFO:116:error setting recipientinfo +CMS_R_INVALID_ENCRYPTED_KEY_LENGTH:117:invalid encrypted key length +CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER:176:invalid key encryption parameter +CMS_R_INVALID_KEY_LENGTH:118:invalid key length +CMS_R_MD_BIO_INIT_ERROR:119:md bio init error +CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH:120:\ + messagedigest attribute wrong length +CMS_R_MESSAGEDIGEST_WRONG_LENGTH:121:messagedigest wrong length +CMS_R_MSGSIGDIGEST_ERROR:172:msgsigdigest error +CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE:162:msgsigdigest verification failure +CMS_R_MSGSIGDIGEST_WRONG_LENGTH:163:msgsigdigest wrong length +CMS_R_NEED_ONE_SIGNER:164:need one signer +CMS_R_NOT_A_SIGNED_RECEIPT:165:not a signed receipt +CMS_R_NOT_ENCRYPTED_DATA:122:not encrypted data +CMS_R_NOT_KEK:123:not kek +CMS_R_NOT_KEY_AGREEMENT:181:not key agreement +CMS_R_NOT_KEY_TRANSPORT:124:not key transport +CMS_R_NOT_PWRI:177:not pwri +CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE:125:not supported for this key type +CMS_R_NO_CIPHER:126:no cipher +CMS_R_NO_CONTENT:127:no content +CMS_R_NO_CONTENT_TYPE:173:no content type +CMS_R_NO_DEFAULT_DIGEST:128:no default digest +CMS_R_NO_DIGEST_SET:129:no digest set +CMS_R_NO_KEY:130:no key +CMS_R_NO_KEY_OR_CERT:174:no key or cert +CMS_R_NO_MATCHING_DIGEST:131:no matching digest +CMS_R_NO_MATCHING_RECIPIENT:132:no matching recipient +CMS_R_NO_MATCHING_SIGNATURE:166:no matching signature +CMS_R_NO_MSGSIGDIGEST:167:no msgsigdigest +CMS_R_NO_PASSWORD:178:no password +CMS_R_NO_PRIVATE_KEY:133:no private key +CMS_R_NO_PUBLIC_KEY:134:no public key +CMS_R_NO_RECEIPT_REQUEST:168:no receipt request +CMS_R_NO_SIGNERS:135:no signers +CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE:136:\ + private key does not match certificate +CMS_R_RECEIPT_DECODE_ERROR:169:receipt decode error +CMS_R_RECIPIENT_ERROR:137:recipient error +CMS_R_SIGNER_CERTIFICATE_NOT_FOUND:138:signer certificate not found +CMS_R_SIGNFINAL_ERROR:139:signfinal error +CMS_R_SMIME_TEXT_ERROR:140:smime text error +CMS_R_STORE_INIT_ERROR:141:store init error +CMS_R_TYPE_NOT_COMPRESSED_DATA:142:type not compressed data +CMS_R_TYPE_NOT_DATA:143:type not data +CMS_R_TYPE_NOT_DIGESTED_DATA:144:type not digested data +CMS_R_TYPE_NOT_ENCRYPTED_DATA:145:type not encrypted data +CMS_R_TYPE_NOT_ENVELOPED_DATA:146:type not enveloped data +CMS_R_UNABLE_TO_FINALIZE_CONTEXT:147:unable to finalize context +CMS_R_UNKNOWN_CIPHER:148:unknown cipher +CMS_R_UNKNOWN_DIGEST_ALGORITHM:149:unknown digest algorithm +CMS_R_UNKNOWN_ID:150:unknown id +CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM:151:unsupported compression algorithm +CMS_R_UNSUPPORTED_CONTENT_TYPE:152:unsupported content type +CMS_R_UNSUPPORTED_KEK_ALGORITHM:153:unsupported kek algorithm +CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM:179:\ + unsupported key encryption algorithm +CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE:155:unsupported recipientinfo type +CMS_R_UNSUPPORTED_RECIPIENT_TYPE:154:unsupported recipient type +CMS_R_UNSUPPORTED_TYPE:156:unsupported type +CMS_R_UNWRAP_ERROR:157:unwrap error +CMS_R_UNWRAP_FAILURE:180:unwrap failure +CMS_R_VERIFICATION_FAILURE:158:verification failure +CMS_R_WRAP_ERROR:159:wrap error +COMP_R_ZLIB_DEFLATE_ERROR:99:zlib deflate error +COMP_R_ZLIB_INFLATE_ERROR:100:zlib inflate error +COMP_R_ZLIB_NOT_SUPPORTED:101:zlib not supported +CONF_R_ERROR_LOADING_DSO:110:error loading dso +CONF_R_LIST_CANNOT_BE_NULL:115:list cannot be null +CONF_R_MISSING_CLOSE_SQUARE_BRACKET:100:missing close square bracket +CONF_R_MISSING_EQUAL_SIGN:101:missing equal sign +CONF_R_MISSING_INIT_FUNCTION:112:missing init function +CONF_R_MODULE_INITIALIZATION_ERROR:109:module initialization error +CONF_R_NO_CLOSE_BRACE:102:no close brace +CONF_R_NO_CONF:105:no conf +CONF_R_NO_CONF_OR_ENVIRONMENT_VARIABLE:106:no conf or environment variable +CONF_R_NO_SECTION:107:no section +CONF_R_NO_SUCH_FILE:114:no such file +CONF_R_NO_VALUE:108:no value +CONF_R_NUMBER_TOO_LARGE:121:number too large +CONF_R_RECURSIVE_DIRECTORY_INCLUDE:111:recursive directory include +CONF_R_SSL_COMMAND_SECTION_EMPTY:117:ssl command section empty +CONF_R_SSL_COMMAND_SECTION_NOT_FOUND:118:ssl command section not found +CONF_R_SSL_SECTION_EMPTY:119:ssl section empty +CONF_R_SSL_SECTION_NOT_FOUND:120:ssl section not found +CONF_R_UNABLE_TO_CREATE_NEW_SECTION:103:unable to create new section +CONF_R_UNKNOWN_MODULE_NAME:113:unknown module name +CONF_R_VARIABLE_EXPANSION_TOO_LONG:116:variable expansion too long +CONF_R_VARIABLE_HAS_NO_VALUE:104:variable has no value +CRYPTO_R_FIPS_MODE_NOT_SUPPORTED:101:fips mode not supported +CRYPTO_R_ILLEGAL_HEX_DIGIT:102:illegal hex digit +CRYPTO_R_ODD_NUMBER_OF_DIGITS:103:odd number of digits +CT_R_BASE64_DECODE_ERROR:108:base64 decode error +CT_R_INVALID_LOG_ID_LENGTH:100:invalid log id length +CT_R_LOG_CONF_INVALID:109:log conf invalid +CT_R_LOG_CONF_INVALID_KEY:110:log conf invalid key +CT_R_LOG_CONF_MISSING_DESCRIPTION:111:log conf missing description +CT_R_LOG_CONF_MISSING_KEY:112:log conf missing key +CT_R_LOG_KEY_INVALID:113:log key invalid +CT_R_SCT_FUTURE_TIMESTAMP:116:sct future timestamp +CT_R_SCT_INVALID:104:sct invalid +CT_R_SCT_INVALID_SIGNATURE:107:sct invalid signature +CT_R_SCT_LIST_INVALID:105:sct list invalid +CT_R_SCT_LOG_ID_MISMATCH:114:sct log id mismatch +CT_R_SCT_NOT_SET:106:sct not set +CT_R_SCT_UNSUPPORTED_VERSION:115:sct unsupported version +CT_R_UNRECOGNIZED_SIGNATURE_NID:101:unrecognized signature nid +CT_R_UNSUPPORTED_ENTRY_TYPE:102:unsupported entry type +CT_R_UNSUPPORTED_VERSION:103:unsupported version +DH_R_BAD_GENERATOR:101:bad generator +DH_R_BN_DECODE_ERROR:109:bn decode error +DH_R_BN_ERROR:106:bn error +DH_R_CHECK_INVALID_J_VALUE:115:check invalid j value +DH_R_CHECK_INVALID_Q_VALUE:116:check invalid q value +DH_R_CHECK_PUBKEY_INVALID:122:check pubkey invalid +DH_R_CHECK_PUBKEY_TOO_LARGE:123:check pubkey too large +DH_R_CHECK_PUBKEY_TOO_SMALL:124:check pubkey too small +DH_R_CHECK_P_NOT_PRIME:117:check p not prime +DH_R_CHECK_P_NOT_SAFE_PRIME:118:check p not safe prime +DH_R_CHECK_Q_NOT_PRIME:119:check q not prime +DH_R_DECODE_ERROR:104:decode error +DH_R_INVALID_PARAMETER_NAME:110:invalid parameter name +DH_R_INVALID_PARAMETER_NID:114:invalid parameter nid +DH_R_INVALID_PUBKEY:102:invalid public key +DH_R_KDF_PARAMETER_ERROR:112:kdf parameter error +DH_R_KEYS_NOT_SET:108:keys not set +DH_R_MISSING_PUBKEY:125:missing pubkey +DH_R_MODULUS_TOO_LARGE:103:modulus too large +DH_R_NOT_SUITABLE_GENERATOR:120:not suitable generator +DH_R_NO_PARAMETERS_SET:107:no parameters set +DH_R_NO_PRIVATE_VALUE:100:no private value +DH_R_PARAMETER_ENCODING_ERROR:105:parameter encoding error +DH_R_PEER_KEY_ERROR:111:peer key error +DH_R_SHARED_INFO_ERROR:113:shared info error +DH_R_UNABLE_TO_CHECK_GENERATOR:121:unable to check generator +DSA_R_BAD_Q_VALUE:102:bad q value +DSA_R_BN_DECODE_ERROR:108:bn decode error +DSA_R_BN_ERROR:109:bn error +DSA_R_DECODE_ERROR:104:decode error +DSA_R_INVALID_DIGEST_TYPE:106:invalid digest type +DSA_R_INVALID_PARAMETERS:112:invalid parameters +DSA_R_MISSING_PARAMETERS:101:missing parameters +DSA_R_MODULUS_TOO_LARGE:103:modulus too large +DSA_R_NO_PARAMETERS_SET:107:no parameters set +DSA_R_PARAMETER_ENCODING_ERROR:105:parameter encoding error +DSA_R_Q_NOT_PRIME:113:q not prime +DSA_R_SEED_LEN_SMALL:110:seed_len is less than the length of q +DSO_R_CTRL_FAILED:100:control command failed +DSO_R_DSO_ALREADY_LOADED:110:dso already loaded +DSO_R_EMPTY_FILE_STRUCTURE:113:empty file structure +DSO_R_FAILURE:114:failure +DSO_R_FILENAME_TOO_BIG:101:filename too big +DSO_R_FINISH_FAILED:102:cleanup method function failed +DSO_R_INCORRECT_FILE_SYNTAX:115:incorrect file syntax +DSO_R_LOAD_FAILED:103:could not load the shared library +DSO_R_NAME_TRANSLATION_FAILED:109:name translation failed +DSO_R_NO_FILENAME:111:no filename +DSO_R_NULL_HANDLE:104:a null shared library handle was used +DSO_R_SET_FILENAME_FAILED:112:set filename failed +DSO_R_STACK_ERROR:105:the meth_data stack is corrupt +DSO_R_SYM_FAILURE:106:could not bind to the requested symbol name +DSO_R_UNLOAD_FAILED:107:could not unload the shared library +DSO_R_UNSUPPORTED:108:functionality not supported +EC_R_ASN1_ERROR:115:asn1 error +EC_R_BAD_SIGNATURE:156:bad signature +EC_R_BIGNUM_OUT_OF_RANGE:144:bignum out of range +EC_R_BUFFER_TOO_SMALL:100:buffer too small +EC_R_CANNOT_INVERT:165:cannot invert +EC_R_COORDINATES_OUT_OF_RANGE:146:coordinates out of range +EC_R_CURVE_DOES_NOT_SUPPORT_ECDH:160:curve does not support ecdh +EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING:159:curve does not support signing +EC_R_D2I_ECPKPARAMETERS_FAILURE:117:d2i ecpkparameters failure +EC_R_DECODE_ERROR:142:decode error +EC_R_DISCRIMINANT_IS_ZERO:118:discriminant is zero +EC_R_EC_GROUP_NEW_BY_NAME_FAILURE:119:ec group new by name failure +EC_R_FIELD_TOO_LARGE:143:field too large +EC_R_GF2M_NOT_SUPPORTED:147:gf2m not supported +EC_R_GROUP2PKPARAMETERS_FAILURE:120:group2pkparameters failure +EC_R_I2D_ECPKPARAMETERS_FAILURE:121:i2d ecpkparameters failure +EC_R_INCOMPATIBLE_OBJECTS:101:incompatible objects +EC_R_INVALID_ARGUMENT:112:invalid argument +EC_R_INVALID_COMPRESSED_POINT:110:invalid compressed point +EC_R_INVALID_COMPRESSION_BIT:109:invalid compression bit +EC_R_INVALID_CURVE:141:invalid curve +EC_R_INVALID_DIGEST:151:invalid digest +EC_R_INVALID_DIGEST_TYPE:138:invalid digest type +EC_R_INVALID_ENCODING:102:invalid encoding +EC_R_INVALID_FIELD:103:invalid field +EC_R_INVALID_FORM:104:invalid form +EC_R_INVALID_GROUP_ORDER:122:invalid group order +EC_R_INVALID_KEY:116:invalid key +EC_R_INVALID_OUTPUT_LENGTH:161:invalid output length +EC_R_INVALID_PEER_KEY:133:invalid peer key +EC_R_INVALID_PENTANOMIAL_BASIS:132:invalid pentanomial basis +EC_R_INVALID_PRIVATE_KEY:123:invalid private key +EC_R_INVALID_TRINOMIAL_BASIS:137:invalid trinomial basis +EC_R_KDF_PARAMETER_ERROR:148:kdf parameter error +EC_R_KEYS_NOT_SET:140:keys not set +EC_R_LADDER_POST_FAILURE:136:ladder post failure +EC_R_LADDER_PRE_FAILURE:153:ladder pre failure +EC_R_LADDER_STEP_FAILURE:162:ladder step failure +EC_R_MISSING_PARAMETERS:124:missing parameters +EC_R_MISSING_PRIVATE_KEY:125:missing private key +EC_R_NEED_NEW_SETUP_VALUES:157:need new setup values +EC_R_NOT_A_NIST_PRIME:135:not a NIST prime +EC_R_NOT_IMPLEMENTED:126:not implemented +EC_R_NOT_INITIALIZED:111:not initialized +EC_R_NO_PARAMETERS_SET:139:no parameters set +EC_R_NO_PRIVATE_VALUE:154:no private value +EC_R_OPERATION_NOT_SUPPORTED:152:operation not supported +EC_R_PASSED_NULL_PARAMETER:134:passed null parameter +EC_R_PEER_KEY_ERROR:149:peer key error +EC_R_PKPARAMETERS2GROUP_FAILURE:127:pkparameters2group failure +EC_R_POINT_ARITHMETIC_FAILURE:155:point arithmetic failure +EC_R_POINT_AT_INFINITY:106:point at infinity +EC_R_POINT_COORDINATES_BLIND_FAILURE:163:point coordinates blind failure +EC_R_POINT_IS_NOT_ON_CURVE:107:point is not on curve +EC_R_RANDOM_NUMBER_GENERATION_FAILED:158:random number generation failed +EC_R_SHARED_INFO_ERROR:150:shared info error +EC_R_SLOT_FULL:108:slot full +EC_R_UNDEFINED_GENERATOR:113:undefined generator +EC_R_UNDEFINED_ORDER:128:undefined order +EC_R_UNKNOWN_COFACTOR:164:unknown cofactor +EC_R_UNKNOWN_GROUP:129:unknown group +EC_R_UNKNOWN_ORDER:114:unknown order +EC_R_UNSUPPORTED_FIELD:131:unsupported field +EC_R_WRONG_CURVE_PARAMETERS:145:wrong curve parameters +EC_R_WRONG_ORDER:130:wrong order +ENGINE_R_ALREADY_LOADED:100:already loaded +ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER:133:argument is not a number +ENGINE_R_CMD_NOT_EXECUTABLE:134:cmd not executable +ENGINE_R_COMMAND_TAKES_INPUT:135:command takes input +ENGINE_R_COMMAND_TAKES_NO_INPUT:136:command takes no input +ENGINE_R_CONFLICTING_ENGINE_ID:103:conflicting engine id +ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED:119:ctrl command not implemented +ENGINE_R_DSO_FAILURE:104:DSO failure +ENGINE_R_DSO_NOT_FOUND:132:dso not found +ENGINE_R_ENGINES_SECTION_ERROR:148:engines section error +ENGINE_R_ENGINE_CONFIGURATION_ERROR:102:engine configuration error +ENGINE_R_ENGINE_IS_NOT_IN_LIST:105:engine is not in the list +ENGINE_R_ENGINE_SECTION_ERROR:149:engine section error +ENGINE_R_FAILED_LOADING_PRIVATE_KEY:128:failed loading private key +ENGINE_R_FAILED_LOADING_PUBLIC_KEY:129:failed loading public key +ENGINE_R_FINISH_FAILED:106:finish failed +ENGINE_R_ID_OR_NAME_MISSING:108:'id' or 'name' missing +ENGINE_R_INIT_FAILED:109:init failed +ENGINE_R_INTERNAL_LIST_ERROR:110:internal list error +ENGINE_R_INVALID_ARGUMENT:143:invalid argument +ENGINE_R_INVALID_CMD_NAME:137:invalid cmd name +ENGINE_R_INVALID_CMD_NUMBER:138:invalid cmd number +ENGINE_R_INVALID_INIT_VALUE:151:invalid init value +ENGINE_R_INVALID_STRING:150:invalid string +ENGINE_R_NOT_INITIALISED:117:not initialised +ENGINE_R_NOT_LOADED:112:not loaded +ENGINE_R_NO_CONTROL_FUNCTION:120:no control function +ENGINE_R_NO_INDEX:144:no index +ENGINE_R_NO_LOAD_FUNCTION:125:no load function +ENGINE_R_NO_REFERENCE:130:no reference +ENGINE_R_NO_SUCH_ENGINE:116:no such engine +ENGINE_R_UNIMPLEMENTED_CIPHER:146:unimplemented cipher +ENGINE_R_UNIMPLEMENTED_DIGEST:147:unimplemented digest +ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD:101:unimplemented public key method +ENGINE_R_VERSION_INCOMPATIBILITY:145:version incompatibility +EVP_R_AES_KEY_SETUP_FAILED:143:aes key setup failed +EVP_R_ARIA_KEY_SETUP_FAILED:176:aria key setup failed +EVP_R_BAD_DECRYPT:100:bad decrypt +EVP_R_BUFFER_TOO_SMALL:155:buffer too small +EVP_R_CAMELLIA_KEY_SETUP_FAILED:157:camellia key setup failed +EVP_R_CIPHER_PARAMETER_ERROR:122:cipher parameter error +EVP_R_COMMAND_NOT_SUPPORTED:147:command not supported +EVP_R_COPY_ERROR:173:copy error +EVP_R_CTRL_NOT_IMPLEMENTED:132:ctrl not implemented +EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED:133:ctrl operation not implemented +EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH:138:data not multiple of block length +EVP_R_DECODE_ERROR:114:decode error +EVP_R_DIFFERENT_KEY_TYPES:101:different key types +EVP_R_DIFFERENT_PARAMETERS:153:different parameters +EVP_R_ERROR_LOADING_SECTION:165:error loading section +EVP_R_ERROR_SETTING_FIPS_MODE:166:error setting fips mode +EVP_R_EXPECTING_AN_HMAC_KEY:174:expecting an hmac key +EVP_R_EXPECTING_AN_RSA_KEY:127:expecting an rsa key +EVP_R_EXPECTING_A_DH_KEY:128:expecting a dh key +EVP_R_EXPECTING_A_DSA_KEY:129:expecting a dsa key +EVP_R_EXPECTING_A_EC_KEY:142:expecting a ec key +EVP_R_EXPECTING_A_POLY1305_KEY:164:expecting a poly1305 key +EVP_R_EXPECTING_A_SIPHASH_KEY:175:expecting a siphash key +EVP_R_FIPS_MODE_NOT_SUPPORTED:167:fips mode not supported +EVP_R_GET_RAW_KEY_FAILED:182:get raw key failed +EVP_R_ILLEGAL_SCRYPT_PARAMETERS:171:illegal scrypt parameters +EVP_R_INITIALIZATION_ERROR:134:initialization error +EVP_R_INPUT_NOT_INITIALIZED:111:input not initialized +EVP_R_INVALID_DIGEST:152:invalid digest +EVP_R_INVALID_FIPS_MODE:168:invalid fips mode +EVP_R_INVALID_KEY:163:invalid key +EVP_R_INVALID_KEY_LENGTH:130:invalid key length +EVP_R_INVALID_OPERATION:148:invalid operation +EVP_R_KEYGEN_FAILURE:120:keygen failure +EVP_R_KEY_SETUP_FAILED:180:key setup failed +EVP_R_MEMORY_LIMIT_EXCEEDED:172:memory limit exceeded +EVP_R_MESSAGE_DIGEST_IS_NULL:159:message digest is null +EVP_R_METHOD_NOT_SUPPORTED:144:method not supported +EVP_R_MISSING_PARAMETERS:103:missing parameters +EVP_R_NOT_XOF_OR_INVALID_LENGTH:178:not XOF or invalid length +EVP_R_NO_CIPHER_SET:131:no cipher set +EVP_R_NO_DEFAULT_DIGEST:158:no default digest +EVP_R_NO_DIGEST_SET:139:no digest set +EVP_R_NO_KEY_SET:154:no key set +EVP_R_NO_OPERATION_SET:149:no operation set +EVP_R_ONLY_ONESHOT_SUPPORTED:177:only oneshot supported +EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE:150:\ + operation not supported for this keytype +EVP_R_OPERATON_NOT_INITIALIZED:151:operaton not initialized +EVP_R_PARTIALLY_OVERLAPPING:162:partially overlapping buffers +EVP_R_PBKDF2_ERROR:181:pbkdf2 error +EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED:179:\ + pkey application asn1 method already registered +EVP_R_PRIVATE_KEY_DECODE_ERROR:145:private key decode error +EVP_R_PRIVATE_KEY_ENCODE_ERROR:146:private key encode error +EVP_R_PUBLIC_KEY_NOT_RSA:106:public key not rsa +EVP_R_UNKNOWN_CIPHER:160:unknown cipher +EVP_R_UNKNOWN_DIGEST:161:unknown digest +EVP_R_UNKNOWN_OPTION:169:unknown option +EVP_R_UNKNOWN_PBE_ALGORITHM:121:unknown pbe algorithm +EVP_R_UNSUPPORTED_ALGORITHM:156:unsupported algorithm +EVP_R_UNSUPPORTED_CIPHER:107:unsupported cipher +EVP_R_UNSUPPORTED_KEYLENGTH:123:unsupported keylength +EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION:124:\ + unsupported key derivation function +EVP_R_UNSUPPORTED_KEY_SIZE:108:unsupported key size +EVP_R_UNSUPPORTED_NUMBER_OF_ROUNDS:135:unsupported number of rounds +EVP_R_UNSUPPORTED_PRF:125:unsupported prf +EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM:118:unsupported private key algorithm +EVP_R_UNSUPPORTED_SALT_TYPE:126:unsupported salt type +EVP_R_WRAP_MODE_NOT_ALLOWED:170:wrap mode not allowed +EVP_R_WRONG_FINAL_BLOCK_LENGTH:109:wrong final block length +KDF_R_INVALID_DIGEST:100:invalid digest +KDF_R_MISSING_ITERATION_COUNT:109:missing iteration count +KDF_R_MISSING_KEY:104:missing key +KDF_R_MISSING_MESSAGE_DIGEST:105:missing message digest +KDF_R_MISSING_PARAMETER:101:missing parameter +KDF_R_MISSING_PASS:110:missing pass +KDF_R_MISSING_SALT:111:missing salt +KDF_R_MISSING_SECRET:107:missing secret +KDF_R_MISSING_SEED:106:missing seed +KDF_R_UNKNOWN_PARAMETER_TYPE:103:unknown parameter type +KDF_R_VALUE_ERROR:108:value error +KDF_R_VALUE_MISSING:102:value missing +OBJ_R_OID_EXISTS:102:oid exists +OBJ_R_UNKNOWN_NID:101:unknown nid +OCSP_R_CERTIFICATE_VERIFY_ERROR:101:certificate verify error +OCSP_R_DIGEST_ERR:102:digest err +OCSP_R_ERROR_IN_NEXTUPDATE_FIELD:122:error in nextupdate field +OCSP_R_ERROR_IN_THISUPDATE_FIELD:123:error in thisupdate field +OCSP_R_ERROR_PARSING_URL:121:error parsing url +OCSP_R_MISSING_OCSPSIGNING_USAGE:103:missing ocspsigning usage +OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE:124:nextupdate before thisupdate +OCSP_R_NOT_BASIC_RESPONSE:104:not basic response +OCSP_R_NO_CERTIFICATES_IN_CHAIN:105:no certificates in chain +OCSP_R_NO_RESPONSE_DATA:108:no response data +OCSP_R_NO_REVOKED_TIME:109:no revoked time +OCSP_R_NO_SIGNER_KEY:130:no signer key +OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE:110:\ + private key does not match certificate +OCSP_R_REQUEST_NOT_SIGNED:128:request not signed +OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA:111:\ + response contains no revocation data +OCSP_R_ROOT_CA_NOT_TRUSTED:112:root ca not trusted +OCSP_R_SERVER_RESPONSE_ERROR:114:server response error +OCSP_R_SERVER_RESPONSE_PARSE_ERROR:115:server response parse error +OCSP_R_SIGNATURE_FAILURE:117:signature failure +OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND:118:signer certificate not found +OCSP_R_STATUS_EXPIRED:125:status expired +OCSP_R_STATUS_NOT_YET_VALID:126:status not yet valid +OCSP_R_STATUS_TOO_OLD:127:status too old +OCSP_R_UNKNOWN_MESSAGE_DIGEST:119:unknown message digest +OCSP_R_UNKNOWN_NID:120:unknown nid +OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE:129:unsupported requestorname type +OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE:107:ambiguous content type +OSSL_STORE_R_BAD_PASSWORD_READ:115:bad password read +OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC:113:error verifying pkcs12 mac +OSSL_STORE_R_FINGERPRINT_SIZE_DOES_NOT_MATCH_DIGEST:121:\ + fingerprint size does not match digest +OSSL_STORE_R_INVALID_SCHEME:106:invalid scheme +OSSL_STORE_R_IS_NOT_A:112:is not a +OSSL_STORE_R_LOADER_INCOMPLETE:116:loader incomplete +OSSL_STORE_R_LOADING_STARTED:117:loading started +OSSL_STORE_R_NOT_A_CERTIFICATE:100:not a certificate +OSSL_STORE_R_NOT_A_CRL:101:not a crl +OSSL_STORE_R_NOT_A_KEY:102:not a key +OSSL_STORE_R_NOT_A_NAME:103:not a name +OSSL_STORE_R_NOT_PARAMETERS:104:not parameters +OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR:114:passphrase callback error +OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE:108:path must be absolute +OSSL_STORE_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES:119:\ + search only supported for directories +OSSL_STORE_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED:109:\ + ui process interrupted or cancelled +OSSL_STORE_R_UNREGISTERED_SCHEME:105:unregistered scheme +OSSL_STORE_R_UNSUPPORTED_CONTENT_TYPE:110:unsupported content type +OSSL_STORE_R_UNSUPPORTED_OPERATION:118:unsupported operation +OSSL_STORE_R_UNSUPPORTED_SEARCH_TYPE:120:unsupported search type +OSSL_STORE_R_URI_AUTHORITY_UNSUPPORTED:111:uri authority unsupported +PEM_R_BAD_BASE64_DECODE:100:bad base64 decode +PEM_R_BAD_DECRYPT:101:bad decrypt +PEM_R_BAD_END_LINE:102:bad end line +PEM_R_BAD_IV_CHARS:103:bad iv chars +PEM_R_BAD_MAGIC_NUMBER:116:bad magic number +PEM_R_BAD_PASSWORD_READ:104:bad password read +PEM_R_BAD_VERSION_NUMBER:117:bad version number +PEM_R_BIO_WRITE_FAILURE:118:bio write failure +PEM_R_CIPHER_IS_NULL:127:cipher is null +PEM_R_ERROR_CONVERTING_PRIVATE_KEY:115:error converting private key +PEM_R_EXPECTING_PRIVATE_KEY_BLOB:119:expecting private key blob +PEM_R_EXPECTING_PUBLIC_KEY_BLOB:120:expecting public key blob +PEM_R_HEADER_TOO_LONG:128:header too long +PEM_R_INCONSISTENT_HEADER:121:inconsistent header +PEM_R_KEYBLOB_HEADER_PARSE_ERROR:122:keyblob header parse error +PEM_R_KEYBLOB_TOO_SHORT:123:keyblob too short +PEM_R_MISSING_DEK_IV:129:missing dek iv +PEM_R_NOT_DEK_INFO:105:not dek info +PEM_R_NOT_ENCRYPTED:106:not encrypted +PEM_R_NOT_PROC_TYPE:107:not proc type +PEM_R_NO_START_LINE:108:no start line +PEM_R_PROBLEMS_GETTING_PASSWORD:109:problems getting password +PEM_R_PVK_DATA_TOO_SHORT:124:pvk data too short +PEM_R_PVK_TOO_SHORT:125:pvk too short +PEM_R_READ_KEY:111:read key +PEM_R_SHORT_HEADER:112:short header +PEM_R_UNEXPECTED_DEK_IV:130:unexpected dek iv +PEM_R_UNSUPPORTED_CIPHER:113:unsupported cipher +PEM_R_UNSUPPORTED_ENCRYPTION:114:unsupported encryption +PEM_R_UNSUPPORTED_KEY_COMPONENTS:126:unsupported key components +PKCS12_R_CANT_PACK_STRUCTURE:100:cant pack structure +PKCS12_R_CONTENT_TYPE_NOT_DATA:121:content type not data +PKCS12_R_DECODE_ERROR:101:decode error +PKCS12_R_ENCODE_ERROR:102:encode error +PKCS12_R_ENCRYPT_ERROR:103:encrypt error +PKCS12_R_ERROR_SETTING_ENCRYPTED_DATA_TYPE:120:error setting encrypted data type +PKCS12_R_INVALID_NULL_ARGUMENT:104:invalid null argument +PKCS12_R_INVALID_NULL_PKCS12_POINTER:105:invalid null pkcs12 pointer +PKCS12_R_IV_GEN_ERROR:106:iv gen error +PKCS12_R_KEY_GEN_ERROR:107:key gen error +PKCS12_R_MAC_ABSENT:108:mac absent +PKCS12_R_MAC_GENERATION_ERROR:109:mac generation error +PKCS12_R_MAC_SETUP_ERROR:110:mac setup error +PKCS12_R_MAC_STRING_SET_ERROR:111:mac string set error +PKCS12_R_MAC_VERIFY_FAILURE:113:mac verify failure +PKCS12_R_PARSE_ERROR:114:parse error +PKCS12_R_PKCS12_ALGOR_CIPHERINIT_ERROR:115:pkcs12 algor cipherinit error +PKCS12_R_PKCS12_CIPHERFINAL_ERROR:116:pkcs12 cipherfinal error +PKCS12_R_PKCS12_PBE_CRYPT_ERROR:117:pkcs12 pbe crypt error +PKCS12_R_UNKNOWN_DIGEST_ALGORITHM:118:unknown digest algorithm +PKCS12_R_UNSUPPORTED_PKCS12_MODE:119:unsupported pkcs12 mode +PKCS7_R_CERTIFICATE_VERIFY_ERROR:117:certificate verify error +PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER:144:cipher has no object identifier +PKCS7_R_CIPHER_NOT_INITIALIZED:116:cipher not initialized +PKCS7_R_CONTENT_AND_DATA_PRESENT:118:content and data present +PKCS7_R_CTRL_ERROR:152:ctrl error +PKCS7_R_DECRYPT_ERROR:119:decrypt error +PKCS7_R_DIGEST_FAILURE:101:digest failure +PKCS7_R_ENCRYPTION_CTRL_FAILURE:149:encryption ctrl failure +PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE:150:\ + encryption not supported for this key type +PKCS7_R_ERROR_ADDING_RECIPIENT:120:error adding recipient +PKCS7_R_ERROR_SETTING_CIPHER:121:error setting cipher +PKCS7_R_INVALID_NULL_POINTER:143:invalid null pointer +PKCS7_R_INVALID_SIGNED_DATA_TYPE:155:invalid signed data type +PKCS7_R_NO_CONTENT:122:no content +PKCS7_R_NO_DEFAULT_DIGEST:151:no default digest +PKCS7_R_NO_MATCHING_DIGEST_TYPE_FOUND:154:no matching digest type found +PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE:115:no recipient matches certificate +PKCS7_R_NO_SIGNATURES_ON_DATA:123:no signatures on data +PKCS7_R_NO_SIGNERS:142:no signers +PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE:104:\ + operation not supported on this type +PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR:124:pkcs7 add signature error +PKCS7_R_PKCS7_ADD_SIGNER_ERROR:153:pkcs7 add signer error +PKCS7_R_PKCS7_DATASIGN:145:pkcs7 datasign +PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE:127:\ + private key does not match certificate +PKCS7_R_SIGNATURE_FAILURE:105:signature failure +PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND:128:signer certificate not found +PKCS7_R_SIGNING_CTRL_FAILURE:147:signing ctrl failure +PKCS7_R_SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE:148:\ + signing not supported for this key type +PKCS7_R_SMIME_TEXT_ERROR:129:smime text error +PKCS7_R_UNABLE_TO_FIND_CERTIFICATE:106:unable to find certificate +PKCS7_R_UNABLE_TO_FIND_MEM_BIO:107:unable to find mem bio +PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST:108:unable to find message digest +PKCS7_R_UNKNOWN_DIGEST_TYPE:109:unknown digest type +PKCS7_R_UNKNOWN_OPERATION:110:unknown operation +PKCS7_R_UNSUPPORTED_CIPHER_TYPE:111:unsupported cipher type +PKCS7_R_UNSUPPORTED_CONTENT_TYPE:112:unsupported content type +PKCS7_R_WRONG_CONTENT_TYPE:113:wrong content type +PKCS7_R_WRONG_PKCS7_TYPE:114:wrong pkcs7 type +RAND_R_ADDITIONAL_INPUT_TOO_LONG:102:additional input too long +RAND_R_ALREADY_INSTANTIATED:103:already instantiated +RAND_R_ARGUMENT_OUT_OF_RANGE:105:argument out of range +RAND_R_CANNOT_OPEN_FILE:121:Cannot open file +RAND_R_DRBG_ALREADY_INITIALIZED:129:drbg already initialized +RAND_R_DRBG_NOT_INITIALISED:104:drbg not initialised +RAND_R_ENTROPY_INPUT_TOO_LONG:106:entropy input too long +RAND_R_ENTROPY_OUT_OF_RANGE:124:entropy out of range +RAND_R_ERROR_ENTROPY_POOL_WAS_IGNORED:127:error entropy pool was ignored +RAND_R_ERROR_INITIALISING_DRBG:107:error initialising drbg +RAND_R_ERROR_INSTANTIATING_DRBG:108:error instantiating drbg +RAND_R_ERROR_RETRIEVING_ADDITIONAL_INPUT:109:error retrieving additional input +RAND_R_ERROR_RETRIEVING_ENTROPY:110:error retrieving entropy +RAND_R_ERROR_RETRIEVING_NONCE:111:error retrieving nonce +RAND_R_FAILED_TO_CREATE_LOCK:126:failed to create lock +RAND_R_FUNC_NOT_IMPLEMENTED:101:Function not implemented +RAND_R_FWRITE_ERROR:123:Error writing file +RAND_R_GENERATE_ERROR:112:generate error +RAND_R_INTERNAL_ERROR:113:internal error +RAND_R_IN_ERROR_STATE:114:in error state +RAND_R_NOT_A_REGULAR_FILE:122:Not a regular file +RAND_R_NOT_INSTANTIATED:115:not instantiated +RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED:128:no drbg implementation selected +RAND_R_PARENT_LOCKING_NOT_ENABLED:130:parent locking not enabled +RAND_R_PARENT_STRENGTH_TOO_WEAK:131:parent strength too weak +RAND_R_PERSONALISATION_STRING_TOO_LONG:116:personalisation string too long +RAND_R_PREDICTION_RESISTANCE_NOT_SUPPORTED:133:\ + prediction resistance not supported +RAND_R_PRNG_NOT_SEEDED:100:PRNG not seeded +RAND_R_RANDOM_POOL_OVERFLOW:125:random pool overflow +RAND_R_RANDOM_POOL_UNDERFLOW:134:random pool underflow +RAND_R_REQUEST_TOO_LARGE_FOR_DRBG:117:request too large for drbg +RAND_R_RESEED_ERROR:118:reseed error +RAND_R_SELFTEST_FAILURE:119:selftest failure +RAND_R_TOO_LITTLE_NONCE_REQUESTED:135:too little nonce requested +RAND_R_TOO_MUCH_NONCE_REQUESTED:136:too much nonce requested +RAND_R_UNSUPPORTED_DRBG_FLAGS:132:unsupported drbg flags +RAND_R_UNSUPPORTED_DRBG_TYPE:120:unsupported drbg type +RSA_R_ALGORITHM_MISMATCH:100:algorithm mismatch +RSA_R_BAD_E_VALUE:101:bad e value +RSA_R_BAD_FIXED_HEADER_DECRYPT:102:bad fixed header decrypt +RSA_R_BAD_PAD_BYTE_COUNT:103:bad pad byte count +RSA_R_BAD_SIGNATURE:104:bad signature +RSA_R_BLOCK_TYPE_IS_NOT_01:106:block type is not 01 +RSA_R_BLOCK_TYPE_IS_NOT_02:107:block type is not 02 +RSA_R_DATA_GREATER_THAN_MOD_LEN:108:data greater than mod len +RSA_R_DATA_TOO_LARGE:109:data too large +RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE:110:data too large for key size +RSA_R_DATA_TOO_LARGE_FOR_MODULUS:132:data too large for modulus +RSA_R_DATA_TOO_SMALL:111:data too small +RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE:122:data too small for key size +RSA_R_DIGEST_DOES_NOT_MATCH:158:digest does not match +RSA_R_DIGEST_NOT_ALLOWED:145:digest not allowed +RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY:112:digest too big for rsa key +RSA_R_DMP1_NOT_CONGRUENT_TO_D:124:dmp1 not congruent to d +RSA_R_DMQ1_NOT_CONGRUENT_TO_D:125:dmq1 not congruent to d +RSA_R_D_E_NOT_CONGRUENT_TO_1:123:d e not congruent to 1 +RSA_R_FIRST_OCTET_INVALID:133:first octet invalid +RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE:144:\ + illegal or unsupported padding mode +RSA_R_INVALID_DIGEST:157:invalid digest +RSA_R_INVALID_DIGEST_LENGTH:143:invalid digest length +RSA_R_INVALID_HEADER:137:invalid header +RSA_R_INVALID_LABEL:160:invalid label +RSA_R_INVALID_MESSAGE_LENGTH:131:invalid message length +RSA_R_INVALID_MGF1_MD:156:invalid mgf1 md +RSA_R_INVALID_MULTI_PRIME_KEY:167:invalid multi prime key +RSA_R_INVALID_OAEP_PARAMETERS:161:invalid oaep parameters +RSA_R_INVALID_PADDING:138:invalid padding +RSA_R_INVALID_PADDING_MODE:141:invalid padding mode +RSA_R_INVALID_PSS_PARAMETERS:149:invalid pss parameters +RSA_R_INVALID_PSS_SALTLEN:146:invalid pss saltlen +RSA_R_INVALID_SALT_LENGTH:150:invalid salt length +RSA_R_INVALID_TRAILER:139:invalid trailer +RSA_R_INVALID_X931_DIGEST:142:invalid x931 digest +RSA_R_IQMP_NOT_INVERSE_OF_Q:126:iqmp not inverse of q +RSA_R_KEY_PRIME_NUM_INVALID:165:key prime num invalid +RSA_R_KEY_SIZE_TOO_SMALL:120:key size too small +RSA_R_LAST_OCTET_INVALID:134:last octet invalid +RSA_R_MGF1_DIGEST_NOT_ALLOWED:152:mgf1 digest not allowed +RSA_R_MODULUS_TOO_LARGE:105:modulus too large +RSA_R_MP_COEFFICIENT_NOT_INVERSE_OF_R:168:mp coefficient not inverse of r +RSA_R_MP_EXPONENT_NOT_CONGRUENT_TO_D:169:mp exponent not congruent to d +RSA_R_MP_R_NOT_PRIME:170:mp r not prime +RSA_R_NO_PUBLIC_EXPONENT:140:no public exponent +RSA_R_NULL_BEFORE_BLOCK_MISSING:113:null before block missing +RSA_R_N_DOES_NOT_EQUAL_PRODUCT_OF_PRIMES:172:n does not equal product of primes +RSA_R_N_DOES_NOT_EQUAL_P_Q:127:n does not equal p q +RSA_R_OAEP_DECODING_ERROR:121:oaep decoding error +RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE:148:\ + operation not supported for this keytype +RSA_R_PADDING_CHECK_FAILED:114:padding check failed +RSA_R_PKCS_DECODING_ERROR:159:pkcs decoding error +RSA_R_PSS_SALTLEN_TOO_SMALL:164:pss saltlen too small +RSA_R_P_NOT_PRIME:128:p not prime +RSA_R_Q_NOT_PRIME:129:q not prime +RSA_R_RSA_OPERATIONS_NOT_SUPPORTED:130:rsa operations not supported +RSA_R_SLEN_CHECK_FAILED:136:salt length check failed +RSA_R_SLEN_RECOVERY_FAILED:135:salt length recovery failed +RSA_R_SSLV3_ROLLBACK_ATTACK:115:sslv3 rollback attack +RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD:116:\ + the asn1 object identifier is not known for this md +RSA_R_UNKNOWN_ALGORITHM_TYPE:117:unknown algorithm type +RSA_R_UNKNOWN_DIGEST:166:unknown digest +RSA_R_UNKNOWN_MASK_DIGEST:151:unknown mask digest +RSA_R_UNKNOWN_PADDING_TYPE:118:unknown padding type +RSA_R_UNSUPPORTED_ENCRYPTION_TYPE:162:unsupported encryption type +RSA_R_UNSUPPORTED_LABEL_SOURCE:163:unsupported label source +RSA_R_UNSUPPORTED_MASK_ALGORITHM:153:unsupported mask algorithm +RSA_R_UNSUPPORTED_MASK_PARAMETER:154:unsupported mask parameter +RSA_R_UNSUPPORTED_SIGNATURE_TYPE:155:unsupported signature type +RSA_R_VALUE_MISSING:147:value missing +RSA_R_WRONG_SIGNATURE_LENGTH:119:wrong signature length +SM2_R_ASN1_ERROR:100:asn1 error +SM2_R_BAD_SIGNATURE:101:bad signature +SM2_R_BUFFER_TOO_SMALL:107:buffer too small +SM2_R_DIST_ID_TOO_LARGE:110:dist id too large +SM2_R_ID_NOT_SET:112:id not set +SM2_R_ID_TOO_LARGE:111:id too large +SM2_R_INVALID_CURVE:108:invalid curve +SM2_R_INVALID_DIGEST:102:invalid digest +SM2_R_INVALID_DIGEST_TYPE:103:invalid digest type +SM2_R_INVALID_ENCODING:104:invalid encoding +SM2_R_INVALID_FIELD:105:invalid field +SM2_R_NO_PARAMETERS_SET:109:no parameters set +SM2_R_USER_ID_TOO_LARGE:106:user id too large +SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY:291:\ + application data after close notify +SSL_R_APP_DATA_IN_HANDSHAKE:100:app data in handshake +SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT:272:\ + attempt to reuse session in different context +SSL_R_AT_LEAST_TLS_1_0_NEEDED_IN_FIPS_MODE:143:\ + at least TLS 1.0 needed in FIPS mode +SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE:158:\ + at least (D)TLS 1.2 needed in Suite B mode +SSL_R_BAD_CHANGE_CIPHER_SPEC:103:bad change cipher spec +SSL_R_BAD_CIPHER:186:bad cipher +SSL_R_BAD_DATA:390:bad data +SSL_R_BAD_DATA_RETURNED_BY_CALLBACK:106:bad data returned by callback +SSL_R_BAD_DECOMPRESSION:107:bad decompression +SSL_R_BAD_DH_VALUE:102:bad dh value +SSL_R_BAD_DIGEST_LENGTH:111:bad digest length +SSL_R_BAD_EARLY_DATA:233:bad early data +SSL_R_BAD_ECC_CERT:304:bad ecc cert +SSL_R_BAD_ECPOINT:306:bad ecpoint +SSL_R_BAD_EXTENSION:110:bad extension +SSL_R_BAD_HANDSHAKE_LENGTH:332:bad handshake length +SSL_R_BAD_HANDSHAKE_STATE:236:bad handshake state +SSL_R_BAD_HELLO_REQUEST:105:bad hello request +SSL_R_BAD_HRR_VERSION:263:bad hrr version +SSL_R_BAD_KEY_SHARE:108:bad key share +SSL_R_BAD_KEY_UPDATE:122:bad key update +SSL_R_BAD_LEGACY_VERSION:292:bad legacy version +SSL_R_BAD_LENGTH:271:bad length +SSL_R_BAD_PACKET:240:bad packet +SSL_R_BAD_PACKET_LENGTH:115:bad packet length +SSL_R_BAD_PROTOCOL_VERSION_NUMBER:116:bad protocol version number +SSL_R_BAD_PSK:219:bad psk +SSL_R_BAD_PSK_IDENTITY:114:bad psk identity +SSL_R_BAD_RECORD_TYPE:443:bad record type +SSL_R_BAD_RSA_ENCRYPT:119:bad rsa encrypt +SSL_R_BAD_SIGNATURE:123:bad signature +SSL_R_BAD_SRP_A_LENGTH:347:bad srp a length +SSL_R_BAD_SRP_PARAMETERS:371:bad srp parameters +SSL_R_BAD_SRTP_MKI_VALUE:352:bad srtp mki value +SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST:353:bad srtp protection profile list +SSL_R_BAD_SSL_FILETYPE:124:bad ssl filetype +SSL_R_BAD_VALUE:384:bad value +SSL_R_BAD_WRITE_RETRY:127:bad write retry +SSL_R_BINDER_DOES_NOT_VERIFY:253:binder does not verify +SSL_R_BIO_NOT_SET:128:bio not set +SSL_R_BLOCK_CIPHER_PAD_IS_WRONG:129:block cipher pad is wrong +SSL_R_BN_LIB:130:bn lib +SSL_R_CALLBACK_FAILED:234:callback failed +SSL_R_CANNOT_CHANGE_CIPHER:109:cannot change cipher +SSL_R_CA_DN_LENGTH_MISMATCH:131:ca dn length mismatch +SSL_R_CA_KEY_TOO_SMALL:397:ca key too small +SSL_R_CA_MD_TOO_WEAK:398:ca md too weak +SSL_R_CCS_RECEIVED_EARLY:133:ccs received early +SSL_R_CERTIFICATE_VERIFY_FAILED:134:certificate verify failed +SSL_R_CERT_CB_ERROR:377:cert cb error +SSL_R_CERT_LENGTH_MISMATCH:135:cert length mismatch +SSL_R_CIPHERSUITE_DIGEST_HAS_CHANGED:218:ciphersuite digest has changed +SSL_R_CIPHER_CODE_WRONG_LENGTH:137:cipher code wrong length +SSL_R_CIPHER_OR_HASH_UNAVAILABLE:138:cipher or hash unavailable +SSL_R_CLIENTHELLO_TLSEXT:226:clienthello tlsext +SSL_R_COMPRESSED_LENGTH_TOO_LONG:140:compressed length too long +SSL_R_COMPRESSION_DISABLED:343:compression disabled +SSL_R_COMPRESSION_FAILURE:141:compression failure +SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE:307:\ + compression id not within private range +SSL_R_COMPRESSION_LIBRARY_ERROR:142:compression library error +SSL_R_CONNECTION_TYPE_NOT_SET:144:connection type not set +SSL_R_CONTEXT_NOT_DANE_ENABLED:167:context not dane enabled +SSL_R_COOKIE_GEN_CALLBACK_FAILURE:400:cookie gen callback failure +SSL_R_COOKIE_MISMATCH:308:cookie mismatch +SSL_R_CUSTOM_EXT_HANDLER_ALREADY_INSTALLED:206:\ + custom ext handler already installed +SSL_R_DANE_ALREADY_ENABLED:172:dane already enabled +SSL_R_DANE_CANNOT_OVERRIDE_MTYPE_FULL:173:dane cannot override mtype full +SSL_R_DANE_NOT_ENABLED:175:dane not enabled +SSL_R_DANE_TLSA_BAD_CERTIFICATE:180:dane tlsa bad certificate +SSL_R_DANE_TLSA_BAD_CERTIFICATE_USAGE:184:dane tlsa bad certificate usage +SSL_R_DANE_TLSA_BAD_DATA_LENGTH:189:dane tlsa bad data length +SSL_R_DANE_TLSA_BAD_DIGEST_LENGTH:192:dane tlsa bad digest length +SSL_R_DANE_TLSA_BAD_MATCHING_TYPE:200:dane tlsa bad matching type +SSL_R_DANE_TLSA_BAD_PUBLIC_KEY:201:dane tlsa bad public key +SSL_R_DANE_TLSA_BAD_SELECTOR:202:dane tlsa bad selector +SSL_R_DANE_TLSA_NULL_DATA:203:dane tlsa null data +SSL_R_DATA_BETWEEN_CCS_AND_FINISHED:145:data between ccs and finished +SSL_R_DATA_LENGTH_TOO_LONG:146:data length too long +SSL_R_DECRYPTION_FAILED:147:decryption failed +SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC:281:\ + decryption failed or bad record mac +SSL_R_DH_KEY_TOO_SMALL:394:dh key too small +SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG:148:dh public value length is wrong +SSL_R_DIGEST_CHECK_FAILED:149:digest check failed +SSL_R_DTLS_MESSAGE_TOO_BIG:334:dtls message too big +SSL_R_DUPLICATE_COMPRESSION_ID:309:duplicate compression id +SSL_R_ECC_CERT_NOT_FOR_SIGNING:318:ecc cert not for signing +SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE:374:ecdh required for suiteb mode +SSL_R_EE_KEY_TOO_SMALL:399:ee key too small +SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST:354:empty srtp protection profile list +SSL_R_ENCRYPTED_LENGTH_TOO_LONG:150:encrypted length too long +SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST:151:error in received cipher list +SSL_R_ERROR_SETTING_TLSA_BASE_DOMAIN:204:error setting tlsa base domain +SSL_R_EXCEEDS_MAX_FRAGMENT_SIZE:194:exceeds max fragment size +SSL_R_EXCESSIVE_MESSAGE_SIZE:152:excessive message size +SSL_R_EXTENSION_NOT_RECEIVED:279:extension not received +SSL_R_EXTRA_DATA_IN_MESSAGE:153:extra data in message +SSL_R_EXT_LENGTH_MISMATCH:163:ext length mismatch +SSL_R_FAILED_TO_INIT_ASYNC:405:failed to init async +SSL_R_FRAGMENTED_CLIENT_HELLO:401:fragmented client hello +SSL_R_GOT_A_FIN_BEFORE_A_CCS:154:got a fin before a ccs +SSL_R_HTTPS_PROXY_REQUEST:155:https proxy request +SSL_R_HTTP_REQUEST:156:http request +SSL_R_ILLEGAL_POINT_COMPRESSION:162:illegal point compression +SSL_R_ILLEGAL_SUITEB_DIGEST:380:illegal Suite B digest +SSL_R_INAPPROPRIATE_FALLBACK:373:inappropriate fallback +SSL_R_INCONSISTENT_COMPRESSION:340:inconsistent compression +SSL_R_INCONSISTENT_EARLY_DATA_ALPN:222:inconsistent early data alpn +SSL_R_INCONSISTENT_EARLY_DATA_SNI:231:inconsistent early data sni +SSL_R_INCONSISTENT_EXTMS:104:inconsistent extms +SSL_R_INSUFFICIENT_SECURITY:241:insufficient security +SSL_R_INVALID_ALERT:205:invalid alert +SSL_R_INVALID_CCS_MESSAGE:260:invalid ccs message +SSL_R_INVALID_CERTIFICATE_OR_ALG:238:invalid certificate or alg +SSL_R_INVALID_COMMAND:280:invalid command +SSL_R_INVALID_COMPRESSION_ALGORITHM:341:invalid compression algorithm +SSL_R_INVALID_CONFIG:283:invalid config +SSL_R_INVALID_CONFIGURATION_NAME:113:invalid configuration name +SSL_R_INVALID_CONTEXT:282:invalid context +SSL_R_INVALID_CT_VALIDATION_TYPE:212:invalid ct validation type +SSL_R_INVALID_KEY_UPDATE_TYPE:120:invalid key update type +SSL_R_INVALID_MAX_EARLY_DATA:174:invalid max early data +SSL_R_INVALID_NULL_CMD_NAME:385:invalid null cmd name +SSL_R_INVALID_SEQUENCE_NUMBER:402:invalid sequence number +SSL_R_INVALID_SERVERINFO_DATA:388:invalid serverinfo data +SSL_R_INVALID_SESSION_ID:999:invalid session id +SSL_R_INVALID_SRP_USERNAME:357:invalid srp username +SSL_R_INVALID_STATUS_RESPONSE:328:invalid status response +SSL_R_INVALID_TICKET_KEYS_LENGTH:325:invalid ticket keys length +SSL_R_LENGTH_MISMATCH:159:length mismatch +SSL_R_LENGTH_TOO_LONG:404:length too long +SSL_R_LENGTH_TOO_SHORT:160:length too short +SSL_R_LIBRARY_BUG:274:library bug +SSL_R_LIBRARY_HAS_NO_CIPHERS:161:library has no ciphers +SSL_R_MISSING_DSA_SIGNING_CERT:165:missing dsa signing cert +SSL_R_MISSING_ECDSA_SIGNING_CERT:381:missing ecdsa signing cert +SSL_R_MISSING_FATAL:256:missing fatal +SSL_R_MISSING_PARAMETERS:290:missing parameters +SSL_R_MISSING_RSA_CERTIFICATE:168:missing rsa certificate +SSL_R_MISSING_RSA_ENCRYPTING_CERT:169:missing rsa encrypting cert +SSL_R_MISSING_RSA_SIGNING_CERT:170:missing rsa signing cert +SSL_R_MISSING_SIGALGS_EXTENSION:112:missing sigalgs extension +SSL_R_MISSING_SIGNING_CERT:221:missing signing cert +SSL_R_MISSING_SRP_PARAM:358:can't find SRP server param +SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION:209:missing supported groups extension +SSL_R_MISSING_TMP_DH_KEY:171:missing tmp dh key +SSL_R_MISSING_TMP_ECDH_KEY:311:missing tmp ecdh key +SSL_R_MIXED_HANDSHAKE_AND_NON_HANDSHAKE_DATA:293:\ + mixed handshake and non handshake data +SSL_R_NOT_ON_RECORD_BOUNDARY:182:not on record boundary +SSL_R_NOT_REPLACING_CERTIFICATE:289:not replacing certificate +SSL_R_NOT_SERVER:284:not server +SSL_R_NO_APPLICATION_PROTOCOL:235:no application protocol +SSL_R_NO_CERTIFICATES_RETURNED:176:no certificates returned +SSL_R_NO_CERTIFICATE_ASSIGNED:177:no certificate assigned +SSL_R_NO_CERTIFICATE_SET:179:no certificate set +SSL_R_NO_CHANGE_FOLLOWING_HRR:214:no change following hrr +SSL_R_NO_CIPHERS_AVAILABLE:181:no ciphers available +SSL_R_NO_CIPHERS_SPECIFIED:183:no ciphers specified +SSL_R_NO_CIPHER_MATCH:185:no cipher match +SSL_R_NO_CLIENT_CERT_METHOD:331:no client cert method +SSL_R_NO_COMPRESSION_SPECIFIED:187:no compression specified +SSL_R_NO_COOKIE_CALLBACK_SET:287:no cookie callback set +SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER:330:\ + Peer haven't sent GOST certificate, required for selected ciphersuite +SSL_R_NO_METHOD_SPECIFIED:188:no method specified +SSL_R_NO_PEM_EXTENSIONS:389:no pem extensions +SSL_R_NO_PRIVATE_KEY_ASSIGNED:190:no private key assigned +SSL_R_NO_PROTOCOLS_AVAILABLE:191:no protocols available +SSL_R_NO_RENEGOTIATION:339:no renegotiation +SSL_R_NO_REQUIRED_DIGEST:324:no required digest +SSL_R_NO_SHARED_CIPHER:193:no shared cipher +SSL_R_NO_SHARED_GROUPS:410:no shared groups +SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS:376:no shared signature algorithms +SSL_R_NO_SRTP_PROFILES:359:no srtp profiles +SSL_R_NO_SUITABLE_KEY_SHARE:101:no suitable key share +SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM:118:no suitable signature algorithm +SSL_R_NO_VALID_SCTS:216:no valid scts +SSL_R_NO_VERIFY_COOKIE_CALLBACK:403:no verify cookie callback +SSL_R_NULL_SSL_CTX:195:null ssl ctx +SSL_R_NULL_SSL_METHOD_PASSED:196:null ssl method passed +SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED:197:old session cipher not returned +SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED:344:\ + old session compression algorithm not returned +SSL_R_OVERFLOW_ERROR:237:overflow error +SSL_R_PACKET_LENGTH_TOO_LONG:198:packet length too long +SSL_R_PARSE_TLSEXT:227:parse tlsext +SSL_R_PATH_TOO_LONG:270:path too long +SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE:199:peer did not return a certificate +SSL_R_PEM_NAME_BAD_PREFIX:391:pem name bad prefix +SSL_R_PEM_NAME_TOO_SHORT:392:pem name too short +SSL_R_PIPELINE_FAILURE:406:pipeline failure +SSL_R_POST_HANDSHAKE_AUTH_ENCODING_ERR:278:post handshake auth encoding err +SSL_R_PRIVATE_KEY_MISMATCH:288:private key mismatch +SSL_R_PROTOCOL_IS_SHUTDOWN:207:protocol is shutdown +SSL_R_PSK_IDENTITY_NOT_FOUND:223:psk identity not found +SSL_R_PSK_NO_CLIENT_CB:224:psk no client cb +SSL_R_PSK_NO_SERVER_CB:225:psk no server cb +SSL_R_READ_BIO_NOT_SET:211:read bio not set +SSL_R_READ_TIMEOUT_EXPIRED:312:read timeout expired +SSL_R_RECORD_LENGTH_MISMATCH:213:record length mismatch +SSL_R_RECORD_TOO_SMALL:298:record too small +SSL_R_RENEGOTIATE_EXT_TOO_LONG:335:renegotiate ext too long +SSL_R_RENEGOTIATION_ENCODING_ERR:336:renegotiation encoding err +SSL_R_RENEGOTIATION_MISMATCH:337:renegotiation mismatch +SSL_R_REQUEST_PENDING:285:request pending +SSL_R_REQUEST_SENT:286:request sent +SSL_R_REQUIRED_CIPHER_MISSING:215:required cipher missing +SSL_R_REQUIRED_COMPRESSION_ALGORITHM_MISSING:342:\ + required compression algorithm missing +SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING:345:scsv received when renegotiating +SSL_R_SCT_VERIFICATION_FAILED:208:sct verification failed +SSL_R_SERVERHELLO_TLSEXT:275:serverhello tlsext +SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED:277:session id context uninitialized +SSL_R_SHUTDOWN_WHILE_IN_INIT:407:shutdown while in init +SSL_R_SIGNATURE_ALGORITHMS_ERROR:360:signature algorithms error +SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE:220:\ + signature for non signing certificate +SSL_R_SRP_A_CALC:361:error with the srp params +SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES:362:srtp could not allocate profiles +SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG:363:\ + srtp protection profile list too long +SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE:364:srtp unknown protection profile +SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH:232:\ + ssl3 ext invalid max fragment length +SSL_R_SSL3_EXT_INVALID_SERVERNAME:319:ssl3 ext invalid servername +SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE:320:ssl3 ext invalid servername type +SSL_R_SSL3_SESSION_ID_TOO_LONG:300:ssl3 session id too long +SSL_R_SSL_COMMAND_SECTION_EMPTY:117:ssl command section empty +SSL_R_SSL_COMMAND_SECTION_NOT_FOUND:125:ssl command section not found +SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION:228:ssl ctx has no default ssl version +SSL_R_SSL_HANDSHAKE_FAILURE:229:ssl handshake failure +SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS:230:ssl library has no ciphers +SSL_R_SSL_NEGATIVE_LENGTH:372:ssl negative length +SSL_R_SSL_SECTION_EMPTY:126:ssl section empty +SSL_R_SSL_SECTION_NOT_FOUND:136:ssl section not found +SSL_R_SSL_SESSION_ID_CALLBACK_FAILED:301:ssl session id callback failed +SSL_R_SSL_SESSION_ID_CONFLICT:302:ssl session id conflict +SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG:273:ssl session id context too long +SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH:303:ssl session id has bad length +SSL_R_SSL_SESSION_ID_TOO_LONG:408:ssl session id too long +SSL_R_SSL_SESSION_VERSION_MISMATCH:210:ssl session version mismatch +SSL_R_STILL_IN_INIT:121:still in init +SSL_R_TLS_HEARTBEAT_PEER_DOESNT_ACCEPT:365:peer does not accept heartbeats +SSL_R_TLS_HEARTBEAT_PENDING:366:heartbeat request already pending +SSL_R_TLS_ILLEGAL_EXPORTER_LABEL:367:tls illegal exporter label +SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST:157:tls invalid ecpointformat list +SSL_R_TOO_MANY_KEY_UPDATES:132:too many key updates +SSL_R_TOO_MANY_WARN_ALERTS:409:too many warn alerts +SSL_R_TOO_MUCH_EARLY_DATA:164:too much early data +SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS:314:unable to find ecdh parameters +SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS:239:\ + unable to find public key parameters +SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES:242:unable to load ssl3 md5 routines +SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES:243:unable to load ssl3 sha1 routines +SSL_R_UNEXPECTED_CCS_MESSAGE:262:unexpected ccs message +SSL_R_UNEXPECTED_END_OF_EARLY_DATA:178:unexpected end of early data +SSL_R_UNEXPECTED_MESSAGE:244:unexpected message +SSL_R_UNEXPECTED_RECORD:245:unexpected record +SSL_R_UNINITIALIZED:276:uninitialized +SSL_R_UNKNOWN_ALERT_TYPE:246:unknown alert type +SSL_R_UNKNOWN_CERTIFICATE_TYPE:247:unknown certificate type +SSL_R_UNKNOWN_CIPHER_RETURNED:248:unknown cipher returned +SSL_R_UNKNOWN_CIPHER_TYPE:249:unknown cipher type +SSL_R_UNKNOWN_CMD_NAME:386:unknown cmd name +SSL_R_UNKNOWN_COMMAND:139:unknown command +SSL_R_UNKNOWN_DIGEST:368:unknown digest +SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE:250:unknown key exchange type +SSL_R_UNKNOWN_PKEY_TYPE:251:unknown pkey type +SSL_R_UNKNOWN_PROTOCOL:252:unknown protocol +SSL_R_UNKNOWN_SSL_VERSION:254:unknown ssl version +SSL_R_UNKNOWN_STATE:255:unknown state +SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED:338:\ + unsafe legacy renegotiation disabled +SSL_R_UNSOLICITED_EXTENSION:217:unsolicited extension +SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM:257:unsupported compression algorithm +SSL_R_UNSUPPORTED_ELLIPTIC_CURVE:315:unsupported elliptic curve +SSL_R_UNSUPPORTED_PROTOCOL:258:unsupported protocol +SSL_R_UNSUPPORTED_SSL_VERSION:259:unsupported ssl version +SSL_R_UNSUPPORTED_STATUS_TYPE:329:unsupported status type +SSL_R_USE_SRTP_NOT_NEGOTIATED:369:use srtp not negotiated +SSL_R_VERSION_TOO_HIGH:166:version too high +SSL_R_VERSION_TOO_LOW:396:version too low +SSL_R_WRONG_CERTIFICATE_TYPE:383:wrong certificate type +SSL_R_WRONG_CIPHER_RETURNED:261:wrong cipher returned +SSL_R_WRONG_CURVE:378:wrong curve +SSL_R_WRONG_SIGNATURE_LENGTH:264:wrong signature length +SSL_R_WRONG_SIGNATURE_SIZE:265:wrong signature size +SSL_R_WRONG_SIGNATURE_TYPE:370:wrong signature type +SSL_R_WRONG_SSL_VERSION:266:wrong ssl version +SSL_R_WRONG_VERSION_NUMBER:267:wrong version number +SSL_R_X509_LIB:268:x509 lib +SSL_R_X509_VERIFICATION_SETUP_PROBLEMS:269:x509 verification setup problems +TS_R_BAD_PKCS7_TYPE:132:bad pkcs7 type +TS_R_BAD_TYPE:133:bad type +TS_R_CANNOT_LOAD_CERT:137:cannot load certificate +TS_R_CANNOT_LOAD_KEY:138:cannot load private key +TS_R_CERTIFICATE_VERIFY_ERROR:100:certificate verify error +TS_R_COULD_NOT_SET_ENGINE:127:could not set engine +TS_R_COULD_NOT_SET_TIME:115:could not set time +TS_R_DETACHED_CONTENT:134:detached content +TS_R_ESS_ADD_SIGNING_CERT_ERROR:116:ess add signing cert error +TS_R_ESS_ADD_SIGNING_CERT_V2_ERROR:139:ess add signing cert v2 error +TS_R_ESS_SIGNING_CERTIFICATE_ERROR:101:ess signing certificate error +TS_R_INVALID_NULL_POINTER:102:invalid null pointer +TS_R_INVALID_SIGNER_CERTIFICATE_PURPOSE:117:invalid signer certificate purpose +TS_R_MESSAGE_IMPRINT_MISMATCH:103:message imprint mismatch +TS_R_NONCE_MISMATCH:104:nonce mismatch +TS_R_NONCE_NOT_RETURNED:105:nonce not returned +TS_R_NO_CONTENT:106:no content +TS_R_NO_TIME_STAMP_TOKEN:107:no time stamp token +TS_R_PKCS7_ADD_SIGNATURE_ERROR:118:pkcs7 add signature error +TS_R_PKCS7_ADD_SIGNED_ATTR_ERROR:119:pkcs7 add signed attr error +TS_R_PKCS7_TO_TS_TST_INFO_FAILED:129:pkcs7 to ts tst info failed +TS_R_POLICY_MISMATCH:108:policy mismatch +TS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE:120:\ + private key does not match certificate +TS_R_RESPONSE_SETUP_ERROR:121:response setup error +TS_R_SIGNATURE_FAILURE:109:signature failure +TS_R_THERE_MUST_BE_ONE_SIGNER:110:there must be one signer +TS_R_TIME_SYSCALL_ERROR:122:time syscall error +TS_R_TOKEN_NOT_PRESENT:130:token not present +TS_R_TOKEN_PRESENT:131:token present +TS_R_TSA_NAME_MISMATCH:111:tsa name mismatch +TS_R_TSA_UNTRUSTED:112:tsa untrusted +TS_R_TST_INFO_SETUP_ERROR:123:tst info setup error +TS_R_TS_DATASIGN:124:ts datasign +TS_R_UNACCEPTABLE_POLICY:125:unacceptable policy +TS_R_UNSUPPORTED_MD_ALGORITHM:126:unsupported md algorithm +TS_R_UNSUPPORTED_VERSION:113:unsupported version +TS_R_VAR_BAD_VALUE:135:var bad value +TS_R_VAR_LOOKUP_FAILURE:136:cannot find config variable +TS_R_WRONG_CONTENT_TYPE:114:wrong content type +UI_R_COMMON_OK_AND_CANCEL_CHARACTERS:104:common ok and cancel characters +UI_R_INDEX_TOO_LARGE:102:index too large +UI_R_INDEX_TOO_SMALL:103:index too small +UI_R_NO_RESULT_BUFFER:105:no result buffer +UI_R_PROCESSING_ERROR:107:processing error +UI_R_RESULT_TOO_LARGE:100:result too large +UI_R_RESULT_TOO_SMALL:101:result too small +UI_R_SYSASSIGN_ERROR:109:sys$assign error +UI_R_SYSDASSGN_ERROR:110:sys$dassgn error +UI_R_SYSQIOW_ERROR:111:sys$qiow error +UI_R_UNKNOWN_CONTROL_COMMAND:106:unknown control command +UI_R_UNKNOWN_TTYGET_ERRNO_VALUE:108:unknown ttyget errno value +UI_R_USER_DATA_DUPLICATION_UNSUPPORTED:112:user data duplication unsupported +X509V3_R_BAD_IP_ADDRESS:118:bad ip address +X509V3_R_BAD_OBJECT:119:bad object +X509V3_R_BN_DEC2BN_ERROR:100:bn dec2bn error +X509V3_R_BN_TO_ASN1_INTEGER_ERROR:101:bn to asn1 integer error +X509V3_R_DIRNAME_ERROR:149:dirname error +X509V3_R_DISTPOINT_ALREADY_SET:160:distpoint already set +X509V3_R_DUPLICATE_ZONE_ID:133:duplicate zone id +X509V3_R_ERROR_CONVERTING_ZONE:131:error converting zone +X509V3_R_ERROR_CREATING_EXTENSION:144:error creating extension +X509V3_R_ERROR_IN_EXTENSION:128:error in extension +X509V3_R_EXPECTED_A_SECTION_NAME:137:expected a section name +X509V3_R_EXTENSION_EXISTS:145:extension exists +X509V3_R_EXTENSION_NAME_ERROR:115:extension name error +X509V3_R_EXTENSION_NOT_FOUND:102:extension not found +X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED:103:extension setting not supported +X509V3_R_EXTENSION_VALUE_ERROR:116:extension value error +X509V3_R_ILLEGAL_EMPTY_EXTENSION:151:illegal empty extension +X509V3_R_INCORRECT_POLICY_SYNTAX_TAG:152:incorrect policy syntax tag +X509V3_R_INVALID_ASNUMBER:162:invalid asnumber +X509V3_R_INVALID_ASRANGE:163:invalid asrange +X509V3_R_INVALID_BOOLEAN_STRING:104:invalid boolean string +X509V3_R_INVALID_EXTENSION_STRING:105:invalid extension string +X509V3_R_INVALID_INHERITANCE:165:invalid inheritance +X509V3_R_INVALID_IPADDRESS:166:invalid ipaddress +X509V3_R_INVALID_MULTIPLE_RDNS:161:invalid multiple rdns +X509V3_R_INVALID_NAME:106:invalid name +X509V3_R_INVALID_NULL_ARGUMENT:107:invalid null argument +X509V3_R_INVALID_NULL_NAME:108:invalid null name +X509V3_R_INVALID_NULL_VALUE:109:invalid null value +X509V3_R_INVALID_NUMBER:140:invalid number +X509V3_R_INVALID_NUMBERS:141:invalid numbers +X509V3_R_INVALID_OBJECT_IDENTIFIER:110:invalid object identifier +X509V3_R_INVALID_OPTION:138:invalid option +X509V3_R_INVALID_POLICY_IDENTIFIER:134:invalid policy identifier +X509V3_R_INVALID_PROXY_POLICY_SETTING:153:invalid proxy policy setting +X509V3_R_INVALID_PURPOSE:146:invalid purpose +X509V3_R_INVALID_SAFI:164:invalid safi +X509V3_R_INVALID_SECTION:135:invalid section +X509V3_R_INVALID_SYNTAX:143:invalid syntax +X509V3_R_ISSUER_DECODE_ERROR:126:issuer decode error +X509V3_R_MISSING_VALUE:124:missing value +X509V3_R_NEED_ORGANIZATION_AND_NUMBERS:142:need organization and numbers +X509V3_R_NO_CONFIG_DATABASE:136:no config database +X509V3_R_NO_ISSUER_CERTIFICATE:121:no issuer certificate +X509V3_R_NO_ISSUER_DETAILS:127:no issuer details +X509V3_R_NO_POLICY_IDENTIFIER:139:no policy identifier +X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED:154:\ + no proxy cert policy language defined +X509V3_R_NO_PUBLIC_KEY:114:no public key +X509V3_R_NO_SUBJECT_DETAILS:125:no subject details +X509V3_R_OPERATION_NOT_DEFINED:148:operation not defined +X509V3_R_OTHERNAME_ERROR:147:othername error +X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED:155:policy language already defined +X509V3_R_POLICY_PATH_LENGTH:156:policy path length +X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED:157:\ + policy path length already defined +X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY:159:\ + policy when proxy language requires no policy +X509V3_R_SECTION_NOT_FOUND:150:section not found +X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS:122:unable to get issuer details +X509V3_R_UNABLE_TO_GET_ISSUER_KEYID:123:unable to get issuer keyid +X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT:111:unknown bit string argument +X509V3_R_UNKNOWN_EXTENSION:129:unknown extension +X509V3_R_UNKNOWN_EXTENSION_NAME:130:unknown extension name +X509V3_R_UNKNOWN_OPTION:120:unknown option +X509V3_R_UNSUPPORTED_OPTION:117:unsupported option +X509V3_R_UNSUPPORTED_TYPE:167:unsupported type +X509V3_R_USER_TOO_LONG:132:user too long +X509_R_AKID_MISMATCH:110:akid mismatch +X509_R_BAD_SELECTOR:133:bad selector +X509_R_BAD_X509_FILETYPE:100:bad x509 filetype +X509_R_BASE64_DECODE_ERROR:118:base64 decode error +X509_R_CANT_CHECK_DH_KEY:114:cant check dh key +X509_R_CERT_ALREADY_IN_HASH_TABLE:101:cert already in hash table +X509_R_CRL_ALREADY_DELTA:127:crl already delta +X509_R_CRL_VERIFY_FAILURE:131:crl verify failure +X509_R_IDP_MISMATCH:128:idp mismatch +X509_R_INVALID_DIRECTORY:113:invalid directory +X509_R_INVALID_FIELD_NAME:119:invalid field name +X509_R_INVALID_TRUST:123:invalid trust +X509_R_ISSUER_MISMATCH:129:issuer mismatch +X509_R_KEY_TYPE_MISMATCH:115:key type mismatch +X509_R_KEY_VALUES_MISMATCH:116:key values mismatch +X509_R_LOADING_CERT_DIR:103:loading cert dir +X509_R_LOADING_DEFAULTS:104:loading defaults +X509_R_METHOD_NOT_SUPPORTED:124:method not supported +X509_R_NAME_TOO_LONG:134:name too long +X509_R_NEWER_CRL_NOT_NEWER:132:newer crl not newer +X509_R_NO_CERTIFICATE_FOUND:135:no certificate found +X509_R_NO_CERTIFICATE_OR_CRL_FOUND:136:no certificate or crl found +X509_R_NO_CERT_SET_FOR_US_TO_VERIFY:105:no cert set for us to verify +X509_R_NO_CRL_FOUND:137:no crl found +X509_R_NO_CRL_NUMBER:130:no crl number +X509_R_PUBLIC_KEY_DECODE_ERROR:125:public key decode error +X509_R_PUBLIC_KEY_ENCODE_ERROR:126:public key encode error +X509_R_SHOULD_RETRY:106:should retry +X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN:107:unable to find parameters in chain +X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY:108:unable to get certs public key +X509_R_UNKNOWN_KEY_TYPE:117:unknown key type +X509_R_UNKNOWN_NID:109:unknown nid +X509_R_UNKNOWN_PURPOSE_ID:121:unknown purpose id +X509_R_UNKNOWN_TRUST_ID:120:unknown trust id +X509_R_UNSUPPORTED_ALGORITHM:111:unsupported algorithm +X509_R_WRONG_LOOKUP_TYPE:112:wrong lookup type +X509_R_WRONG_TYPE:122:wrong type diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/bio_b64.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/bio_b64.c new file mode 100644 index 000000000..9f891f762 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/bio_b64.c @@ -0,0 +1,553 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include +#include +#include "internal/bio.h" + +static int b64_write(BIO *h, const char *buf, int num); +static int b64_read(BIO *h, char *buf, int size); +static int b64_puts(BIO *h, const char *str); +static long b64_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int b64_new(BIO *h); +static int b64_free(BIO *data); +static long b64_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); +#define B64_BLOCK_SIZE 1024 +#define B64_BLOCK_SIZE2 768 +#define B64_NONE 0 +#define B64_ENCODE 1 +#define B64_DECODE 2 + +typedef struct b64_struct { + /* + * BIO *bio; moved to the BIO structure + */ + int buf_len; + int buf_off; + int tmp_len; /* used to find the start when decoding */ + int tmp_nl; /* If true, scan until '\n' */ + int encode; + int start; /* have we started decoding yet? */ + int cont; /* <= 0 when finished */ + EVP_ENCODE_CTX *base64; + char buf[EVP_ENCODE_LENGTH(B64_BLOCK_SIZE) + 10]; + char tmp[B64_BLOCK_SIZE]; +} BIO_B64_CTX; + +static const BIO_METHOD methods_b64 = { + BIO_TYPE_BASE64, + "base64 encoding", + /* TODO: Convert to new style write function */ + bwrite_conv, + b64_write, + /* TODO: Convert to new style read function */ + bread_conv, + b64_read, + b64_puts, + NULL, /* b64_gets, */ + b64_ctrl, + b64_new, + b64_free, + b64_callback_ctrl, +}; + + +const BIO_METHOD *BIO_f_base64(void) +{ + return &methods_b64; +} + +static int b64_new(BIO *bi) +{ + BIO_B64_CTX *ctx; + + if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) { + EVPerr(EVP_F_B64_NEW, ERR_R_MALLOC_FAILURE); + return 0; + } + + ctx->cont = 1; + ctx->start = 1; + ctx->base64 = EVP_ENCODE_CTX_new(); + if (ctx->base64 == NULL) { + OPENSSL_free(ctx); + return 0; + } + + BIO_set_data(bi, ctx); + BIO_set_init(bi, 1); + + return 1; +} + +static int b64_free(BIO *a) +{ + BIO_B64_CTX *ctx; + if (a == NULL) + return 0; + + ctx = BIO_get_data(a); + if (ctx == NULL) + return 0; + + EVP_ENCODE_CTX_free(ctx->base64); + OPENSSL_free(ctx); + BIO_set_data(a, NULL); + BIO_set_init(a, 0); + + return 1; +} + +static int b64_read(BIO *b, char *out, int outl) +{ + int ret = 0, i, ii, j, k, x, n, num, ret_code = 0; + BIO_B64_CTX *ctx; + unsigned char *p, *q; + BIO *next; + + if (out == NULL) + return 0; + ctx = (BIO_B64_CTX *)BIO_get_data(b); + + next = BIO_next(b); + if ((ctx == NULL) || (next == NULL)) + return 0; + + BIO_clear_retry_flags(b); + + if (ctx->encode != B64_DECODE) { + ctx->encode = B64_DECODE; + ctx->buf_len = 0; + ctx->buf_off = 0; + ctx->tmp_len = 0; + EVP_DecodeInit(ctx->base64); + } + + /* First check if there are bytes decoded/encoded */ + if (ctx->buf_len > 0) { + OPENSSL_assert(ctx->buf_len >= ctx->buf_off); + i = ctx->buf_len - ctx->buf_off; + if (i > outl) + i = outl; + OPENSSL_assert(ctx->buf_off + i < (int)sizeof(ctx->buf)); + memcpy(out, &(ctx->buf[ctx->buf_off]), i); + ret = i; + out += i; + outl -= i; + ctx->buf_off += i; + if (ctx->buf_len == ctx->buf_off) { + ctx->buf_len = 0; + ctx->buf_off = 0; + } + } + + /* + * At this point, we have room of outl bytes and an empty buffer, so we + * should read in some more. + */ + + ret_code = 0; + while (outl > 0) { + if (ctx->cont <= 0) + break; + + i = BIO_read(next, &(ctx->tmp[ctx->tmp_len]), + B64_BLOCK_SIZE - ctx->tmp_len); + + if (i <= 0) { + ret_code = i; + + /* Should we continue next time we are called? */ + if (!BIO_should_retry(next)) { + ctx->cont = i; + /* If buffer empty break */ + if (ctx->tmp_len == 0) + break; + /* Fall through and process what we have */ + else + i = 0; + } + /* else we retry and add more data to buffer */ + else + break; + } + i += ctx->tmp_len; + ctx->tmp_len = i; + + /* + * We need to scan, a line at a time until we have a valid line if we + * are starting. + */ + if (ctx->start && (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL)) { + /* ctx->start=1; */ + ctx->tmp_len = 0; + } else if (ctx->start) { + q = p = (unsigned char *)ctx->tmp; + num = 0; + for (j = 0; j < i; j++) { + if (*(q++) != '\n') + continue; + + /* + * due to a previous very long line, we need to keep on + * scanning for a '\n' before we even start looking for + * base64 encoded stuff. + */ + if (ctx->tmp_nl) { + p = q; + ctx->tmp_nl = 0; + continue; + } + + k = EVP_DecodeUpdate(ctx->base64, + (unsigned char *)ctx->buf, + &num, p, q - p); + if ((k <= 0) && (num == 0) && (ctx->start)) + EVP_DecodeInit(ctx->base64); + else { + if (p != (unsigned char *) + &(ctx->tmp[0])) { + i -= (p - (unsigned char *) + &(ctx->tmp[0])); + for (x = 0; x < i; x++) + ctx->tmp[x] = p[x]; + } + EVP_DecodeInit(ctx->base64); + ctx->start = 0; + break; + } + p = q; + } + + /* we fell off the end without starting */ + if ((j == i) && (num == 0)) { + /* + * Is this is one long chunk?, if so, keep on reading until a + * new line. + */ + if (p == (unsigned char *)&(ctx->tmp[0])) { + /* Check buffer full */ + if (i == B64_BLOCK_SIZE) { + ctx->tmp_nl = 1; + ctx->tmp_len = 0; + } + } else if (p != q) { /* finished on a '\n' */ + n = q - p; + for (ii = 0; ii < n; ii++) + ctx->tmp[ii] = p[ii]; + ctx->tmp_len = n; + } + /* else finished on a '\n' */ + continue; + } else { + ctx->tmp_len = 0; + } + } else if ((i < B64_BLOCK_SIZE) && (ctx->cont > 0)) { + /* + * If buffer isn't full and we can retry then restart to read in + * more data. + */ + continue; + } + + if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) { + int z, jj; + + jj = i & ~3; /* process per 4 */ + z = EVP_DecodeBlock((unsigned char *)ctx->buf, + (unsigned char *)ctx->tmp, jj); + if (jj > 2) { + if (ctx->tmp[jj - 1] == '=') { + z--; + if (ctx->tmp[jj - 2] == '=') + z--; + } + } + /* + * z is now number of output bytes and jj is the number consumed + */ + if (jj != i) { + memmove(ctx->tmp, &ctx->tmp[jj], i - jj); + ctx->tmp_len = i - jj; + } + ctx->buf_len = 0; + if (z > 0) { + ctx->buf_len = z; + } + i = z; + } else { + i = EVP_DecodeUpdate(ctx->base64, + (unsigned char *)ctx->buf, &ctx->buf_len, + (unsigned char *)ctx->tmp, i); + ctx->tmp_len = 0; + } + /* + * If eof or an error was signalled, then the condition + * 'ctx->cont <= 0' will prevent b64_read() from reading + * more data on subsequent calls. This assignment was + * deleted accidentally in commit 5562cfaca4f3. + */ + ctx->cont = i; + + ctx->buf_off = 0; + if (i < 0) { + ret_code = 0; + ctx->buf_len = 0; + break; + } + + if (ctx->buf_len <= outl) + i = ctx->buf_len; + else + i = outl; + + memcpy(out, ctx->buf, i); + ret += i; + ctx->buf_off = i; + if (ctx->buf_off == ctx->buf_len) { + ctx->buf_len = 0; + ctx->buf_off = 0; + } + outl -= i; + out += i; + } + /* BIO_clear_retry_flags(b); */ + BIO_copy_next_retry(b); + return ((ret == 0) ? ret_code : ret); +} + +static int b64_write(BIO *b, const char *in, int inl) +{ + int ret = 0; + int n; + int i; + BIO_B64_CTX *ctx; + BIO *next; + + ctx = (BIO_B64_CTX *)BIO_get_data(b); + next = BIO_next(b); + if ((ctx == NULL) || (next == NULL)) + return 0; + + BIO_clear_retry_flags(b); + + if (ctx->encode != B64_ENCODE) { + ctx->encode = B64_ENCODE; + ctx->buf_len = 0; + ctx->buf_off = 0; + ctx->tmp_len = 0; + EVP_EncodeInit(ctx->base64); + } + + OPENSSL_assert(ctx->buf_off < (int)sizeof(ctx->buf)); + OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf)); + OPENSSL_assert(ctx->buf_len >= ctx->buf_off); + n = ctx->buf_len - ctx->buf_off; + while (n > 0) { + i = BIO_write(next, &(ctx->buf[ctx->buf_off]), n); + if (i <= 0) { + BIO_copy_next_retry(b); + return i; + } + OPENSSL_assert(i <= n); + ctx->buf_off += i; + OPENSSL_assert(ctx->buf_off <= (int)sizeof(ctx->buf)); + OPENSSL_assert(ctx->buf_len >= ctx->buf_off); + n -= i; + } + /* at this point all pending data has been written */ + ctx->buf_off = 0; + ctx->buf_len = 0; + + if ((in == NULL) || (inl <= 0)) + return 0; + + while (inl > 0) { + n = (inl > B64_BLOCK_SIZE) ? B64_BLOCK_SIZE : inl; + + if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) { + if (ctx->tmp_len > 0) { + OPENSSL_assert(ctx->tmp_len <= 3); + n = 3 - ctx->tmp_len; + /* + * There's a theoretical possibility for this + */ + if (n > inl) + n = inl; + memcpy(&(ctx->tmp[ctx->tmp_len]), in, n); + ctx->tmp_len += n; + ret += n; + if (ctx->tmp_len < 3) + break; + ctx->buf_len = + EVP_EncodeBlock((unsigned char *)ctx->buf, + (unsigned char *)ctx->tmp, ctx->tmp_len); + OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf)); + OPENSSL_assert(ctx->buf_len >= ctx->buf_off); + /* + * Since we're now done using the temporary buffer, the + * length should be 0'd + */ + ctx->tmp_len = 0; + } else { + if (n < 3) { + memcpy(ctx->tmp, in, n); + ctx->tmp_len = n; + ret += n; + break; + } + n -= n % 3; + ctx->buf_len = + EVP_EncodeBlock((unsigned char *)ctx->buf, + (const unsigned char *)in, n); + OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf)); + OPENSSL_assert(ctx->buf_len >= ctx->buf_off); + ret += n; + } + } else { + if (!EVP_EncodeUpdate(ctx->base64, + (unsigned char *)ctx->buf, &ctx->buf_len, + (unsigned char *)in, n)) + return ((ret == 0) ? -1 : ret); + OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf)); + OPENSSL_assert(ctx->buf_len >= ctx->buf_off); + ret += n; + } + inl -= n; + in += n; + + ctx->buf_off = 0; + n = ctx->buf_len; + while (n > 0) { + i = BIO_write(next, &(ctx->buf[ctx->buf_off]), n); + if (i <= 0) { + BIO_copy_next_retry(b); + return ((ret == 0) ? i : ret); + } + OPENSSL_assert(i <= n); + n -= i; + ctx->buf_off += i; + OPENSSL_assert(ctx->buf_off <= (int)sizeof(ctx->buf)); + OPENSSL_assert(ctx->buf_len >= ctx->buf_off); + } + ctx->buf_len = 0; + ctx->buf_off = 0; + } + return ret; +} + +static long b64_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + BIO_B64_CTX *ctx; + long ret = 1; + int i; + BIO *next; + + ctx = (BIO_B64_CTX *)BIO_get_data(b); + next = BIO_next(b); + if ((ctx == NULL) || (next == NULL)) + return 0; + + switch (cmd) { + case BIO_CTRL_RESET: + ctx->cont = 1; + ctx->start = 1; + ctx->encode = B64_NONE; + ret = BIO_ctrl(next, cmd, num, ptr); + break; + case BIO_CTRL_EOF: /* More to read */ + if (ctx->cont <= 0) + ret = 1; + else + ret = BIO_ctrl(next, cmd, num, ptr); + break; + case BIO_CTRL_WPENDING: /* More to write in buffer */ + OPENSSL_assert(ctx->buf_len >= ctx->buf_off); + ret = ctx->buf_len - ctx->buf_off; + if ((ret == 0) && (ctx->encode != B64_NONE) + && (EVP_ENCODE_CTX_num(ctx->base64) != 0)) + ret = 1; + else if (ret <= 0) + ret = BIO_ctrl(next, cmd, num, ptr); + break; + case BIO_CTRL_PENDING: /* More to read in buffer */ + OPENSSL_assert(ctx->buf_len >= ctx->buf_off); + ret = ctx->buf_len - ctx->buf_off; + if (ret <= 0) + ret = BIO_ctrl(next, cmd, num, ptr); + break; + case BIO_CTRL_FLUSH: + /* do a final write */ + again: + while (ctx->buf_len != ctx->buf_off) { + i = b64_write(b, NULL, 0); + if (i < 0) + return i; + } + if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) { + if (ctx->tmp_len != 0) { + ctx->buf_len = EVP_EncodeBlock((unsigned char *)ctx->buf, + (unsigned char *)ctx->tmp, + ctx->tmp_len); + ctx->buf_off = 0; + ctx->tmp_len = 0; + goto again; + } + } else if (ctx->encode != B64_NONE + && EVP_ENCODE_CTX_num(ctx->base64) != 0) { + ctx->buf_off = 0; + EVP_EncodeFinal(ctx->base64, + (unsigned char *)ctx->buf, &(ctx->buf_len)); + /* push out the bytes */ + goto again; + } + /* Finally flush the underlying BIO */ + ret = BIO_ctrl(next, cmd, num, ptr); + break; + + case BIO_C_DO_STATE_MACHINE: + BIO_clear_retry_flags(b); + ret = BIO_ctrl(next, cmd, num, ptr); + BIO_copy_next_retry(b); + break; + + case BIO_CTRL_DUP: + break; + case BIO_CTRL_INFO: + case BIO_CTRL_GET: + case BIO_CTRL_SET: + default: + ret = BIO_ctrl(next, cmd, num, ptr); + break; + } + return ret; +} + +static long b64_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) +{ + long ret = 1; + BIO *next = BIO_next(b); + + if (next == NULL) + return 0; + switch (cmd) { + default: + ret = BIO_callback_ctrl(next, cmd, fp); + break; + } + return ret; +} + +static int b64_puts(BIO *b, const char *str) +{ + return b64_write(b, str, strlen(str)); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/bio_enc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/bio_enc.c new file mode 100644 index 000000000..6639061ea --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/bio_enc.c @@ -0,0 +1,429 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include +#include +#include "internal/bio.h" + +static int enc_write(BIO *h, const char *buf, int num); +static int enc_read(BIO *h, char *buf, int size); +static long enc_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int enc_new(BIO *h); +static int enc_free(BIO *data); +static long enc_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fps); +#define ENC_BLOCK_SIZE (1024*4) +#define ENC_MIN_CHUNK (256) +#define BUF_OFFSET (ENC_MIN_CHUNK + EVP_MAX_BLOCK_LENGTH) + +typedef struct enc_struct { + int buf_len; + int buf_off; + int cont; /* <= 0 when finished */ + int finished; + int ok; /* bad decrypt */ + EVP_CIPHER_CTX *cipher; + unsigned char *read_start, *read_end; + /* + * buf is larger than ENC_BLOCK_SIZE because EVP_DecryptUpdate can return + * up to a block more data than is presented to it + */ + unsigned char buf[BUF_OFFSET + ENC_BLOCK_SIZE]; +} BIO_ENC_CTX; + +static const BIO_METHOD methods_enc = { + BIO_TYPE_CIPHER, + "cipher", + /* TODO: Convert to new style write function */ + bwrite_conv, + enc_write, + /* TODO: Convert to new style read function */ + bread_conv, + enc_read, + NULL, /* enc_puts, */ + NULL, /* enc_gets, */ + enc_ctrl, + enc_new, + enc_free, + enc_callback_ctrl, +}; + +const BIO_METHOD *BIO_f_cipher(void) +{ + return &methods_enc; +} + +static int enc_new(BIO *bi) +{ + BIO_ENC_CTX *ctx; + + if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) { + EVPerr(EVP_F_ENC_NEW, ERR_R_MALLOC_FAILURE); + return 0; + } + + ctx->cipher = EVP_CIPHER_CTX_new(); + if (ctx->cipher == NULL) { + OPENSSL_free(ctx); + return 0; + } + ctx->cont = 1; + ctx->ok = 1; + ctx->read_end = ctx->read_start = &(ctx->buf[BUF_OFFSET]); + BIO_set_data(bi, ctx); + BIO_set_init(bi, 1); + + return 1; +} + +static int enc_free(BIO *a) +{ + BIO_ENC_CTX *b; + + if (a == NULL) + return 0; + + b = BIO_get_data(a); + if (b == NULL) + return 0; + + EVP_CIPHER_CTX_free(b->cipher); + OPENSSL_clear_free(b, sizeof(BIO_ENC_CTX)); + BIO_set_data(a, NULL); + BIO_set_init(a, 0); + + return 1; +} + +static int enc_read(BIO *b, char *out, int outl) +{ + int ret = 0, i, blocksize; + BIO_ENC_CTX *ctx; + BIO *next; + + if (out == NULL) + return 0; + ctx = BIO_get_data(b); + + next = BIO_next(b); + if ((ctx == NULL) || (next == NULL)) + return 0; + + /* First check if there are bytes decoded/encoded */ + if (ctx->buf_len > 0) { + i = ctx->buf_len - ctx->buf_off; + if (i > outl) + i = outl; + memcpy(out, &(ctx->buf[ctx->buf_off]), i); + ret = i; + out += i; + outl -= i; + ctx->buf_off += i; + if (ctx->buf_len == ctx->buf_off) { + ctx->buf_len = 0; + ctx->buf_off = 0; + } + } + + blocksize = EVP_CIPHER_CTX_block_size(ctx->cipher); + if (blocksize == 1) + blocksize = 0; + + /* + * At this point, we have room of outl bytes and an empty buffer, so we + * should read in some more. + */ + + while (outl > 0) { + if (ctx->cont <= 0) + break; + + if (ctx->read_start == ctx->read_end) { /* time to read more data */ + ctx->read_end = ctx->read_start = &(ctx->buf[BUF_OFFSET]); + i = BIO_read(next, ctx->read_start, ENC_BLOCK_SIZE); + if (i > 0) + ctx->read_end += i; + } else { + i = ctx->read_end - ctx->read_start; + } + + if (i <= 0) { + /* Should be continue next time we are called? */ + if (!BIO_should_retry(next)) { + ctx->cont = i; + i = EVP_CipherFinal_ex(ctx->cipher, + ctx->buf, &(ctx->buf_len)); + ctx->ok = i; + ctx->buf_off = 0; + } else { + ret = (ret == 0) ? i : ret; + break; + } + } else { + if (outl > ENC_MIN_CHUNK) { + /* + * Depending on flags block cipher decrypt can write + * one extra block and then back off, i.e. output buffer + * has to accommodate extra block... + */ + int j = outl - blocksize, buf_len; + + if (!EVP_CipherUpdate(ctx->cipher, + (unsigned char *)out, &buf_len, + ctx->read_start, i > j ? j : i)) { + BIO_clear_retry_flags(b); + return 0; + } + ret += buf_len; + out += buf_len; + outl -= buf_len; + + if ((i -= j) <= 0) { + ctx->read_start = ctx->read_end; + continue; + } + ctx->read_start += j; + } + if (i > ENC_MIN_CHUNK) + i = ENC_MIN_CHUNK; + if (!EVP_CipherUpdate(ctx->cipher, + ctx->buf, &ctx->buf_len, + ctx->read_start, i)) { + BIO_clear_retry_flags(b); + ctx->ok = 0; + return 0; + } + ctx->read_start += i; + ctx->cont = 1; + /* + * Note: it is possible for EVP_CipherUpdate to decrypt zero + * bytes because this is or looks like the final block: if this + * happens we should retry and either read more data or decrypt + * the final block + */ + if (ctx->buf_len == 0) + continue; + } + + if (ctx->buf_len <= outl) + i = ctx->buf_len; + else + i = outl; + if (i <= 0) + break; + memcpy(out, ctx->buf, i); + ret += i; + ctx->buf_off = i; + outl -= i; + out += i; + } + + BIO_clear_retry_flags(b); + BIO_copy_next_retry(b); + return ((ret == 0) ? ctx->cont : ret); +} + +static int enc_write(BIO *b, const char *in, int inl) +{ + int ret = 0, n, i; + BIO_ENC_CTX *ctx; + BIO *next; + + ctx = BIO_get_data(b); + next = BIO_next(b); + if ((ctx == NULL) || (next == NULL)) + return 0; + + ret = inl; + + BIO_clear_retry_flags(b); + n = ctx->buf_len - ctx->buf_off; + while (n > 0) { + i = BIO_write(next, &(ctx->buf[ctx->buf_off]), n); + if (i <= 0) { + BIO_copy_next_retry(b); + return i; + } + ctx->buf_off += i; + n -= i; + } + /* at this point all pending data has been written */ + + if ((in == NULL) || (inl <= 0)) + return 0; + + ctx->buf_off = 0; + while (inl > 0) { + n = (inl > ENC_BLOCK_SIZE) ? ENC_BLOCK_SIZE : inl; + if (!EVP_CipherUpdate(ctx->cipher, + ctx->buf, &ctx->buf_len, + (const unsigned char *)in, n)) { + BIO_clear_retry_flags(b); + ctx->ok = 0; + return 0; + } + inl -= n; + in += n; + + ctx->buf_off = 0; + n = ctx->buf_len; + while (n > 0) { + i = BIO_write(next, &(ctx->buf[ctx->buf_off]), n); + if (i <= 0) { + BIO_copy_next_retry(b); + return (ret == inl) ? i : ret - inl; + } + n -= i; + ctx->buf_off += i; + } + ctx->buf_len = 0; + ctx->buf_off = 0; + } + BIO_copy_next_retry(b); + return ret; +} + +static long enc_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + BIO *dbio; + BIO_ENC_CTX *ctx, *dctx; + long ret = 1; + int i; + EVP_CIPHER_CTX **c_ctx; + BIO *next; + + ctx = BIO_get_data(b); + next = BIO_next(b); + if (ctx == NULL) + return 0; + + switch (cmd) { + case BIO_CTRL_RESET: + ctx->ok = 1; + ctx->finished = 0; + if (!EVP_CipherInit_ex(ctx->cipher, NULL, NULL, NULL, NULL, + EVP_CIPHER_CTX_encrypting(ctx->cipher))) + return 0; + ret = BIO_ctrl(next, cmd, num, ptr); + break; + case BIO_CTRL_EOF: /* More to read */ + if (ctx->cont <= 0) + ret = 1; + else + ret = BIO_ctrl(next, cmd, num, ptr); + break; + case BIO_CTRL_WPENDING: + ret = ctx->buf_len - ctx->buf_off; + if (ret <= 0) + ret = BIO_ctrl(next, cmd, num, ptr); + break; + case BIO_CTRL_PENDING: /* More to read in buffer */ + ret = ctx->buf_len - ctx->buf_off; + if (ret <= 0) + ret = BIO_ctrl(next, cmd, num, ptr); + break; + case BIO_CTRL_FLUSH: + /* do a final write */ + again: + while (ctx->buf_len != ctx->buf_off) { + i = enc_write(b, NULL, 0); + if (i < 0) + return i; + } + + if (!ctx->finished) { + ctx->finished = 1; + ctx->buf_off = 0; + ret = EVP_CipherFinal_ex(ctx->cipher, + (unsigned char *)ctx->buf, + &(ctx->buf_len)); + ctx->ok = (int)ret; + if (ret <= 0) + break; + + /* push out the bytes */ + goto again; + } + + /* Finally flush the underlying BIO */ + ret = BIO_ctrl(next, cmd, num, ptr); + break; + case BIO_C_GET_CIPHER_STATUS: + ret = (long)ctx->ok; + break; + case BIO_C_DO_STATE_MACHINE: + BIO_clear_retry_flags(b); + ret = BIO_ctrl(next, cmd, num, ptr); + BIO_copy_next_retry(b); + break; + case BIO_C_GET_CIPHER_CTX: + c_ctx = (EVP_CIPHER_CTX **)ptr; + *c_ctx = ctx->cipher; + BIO_set_init(b, 1); + break; + case BIO_CTRL_DUP: + dbio = (BIO *)ptr; + dctx = BIO_get_data(dbio); + dctx->cipher = EVP_CIPHER_CTX_new(); + if (dctx->cipher == NULL) + return 0; + ret = EVP_CIPHER_CTX_copy(dctx->cipher, ctx->cipher); + if (ret) + BIO_set_init(dbio, 1); + break; + default: + ret = BIO_ctrl(next, cmd, num, ptr); + break; + } + return ret; +} + +static long enc_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) +{ + long ret = 1; + BIO *next = BIO_next(b); + + if (next == NULL) + return 0; + switch (cmd) { + default: + ret = BIO_callback_ctrl(next, cmd, fp); + break; + } + return ret; +} + +int BIO_set_cipher(BIO *b, const EVP_CIPHER *c, const unsigned char *k, + const unsigned char *i, int e) +{ + BIO_ENC_CTX *ctx; + long (*callback) (struct bio_st *, int, const char *, int, long, long); + + ctx = BIO_get_data(b); + if (ctx == NULL) + return 0; + + callback = BIO_get_callback(b); + + if ((callback != NULL) && + (callback(b, BIO_CB_CTRL, (const char *)c, BIO_CTRL_SET, e, + 0L) <= 0)) + return 0; + + BIO_set_init(b, 1); + + if (!EVP_CipherInit_ex(ctx->cipher, c, NULL, k, i, e)) + return 0; + + if (callback != NULL) + return callback(b, BIO_CB_CTRL, (const char *)c, BIO_CTRL_SET, e, 1L); + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/bio_md.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/bio_md.c new file mode 100644 index 000000000..288dee01b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/bio_md.c @@ -0,0 +1,233 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include +#include +#include "internal/evp_int.h" +#include "evp_locl.h" +#include "internal/bio.h" + +/* + * BIO_put and BIO_get both add to the digest, BIO_gets returns the digest + */ + +static int md_write(BIO *h, char const *buf, int num); +static int md_read(BIO *h, char *buf, int size); +static int md_gets(BIO *h, char *str, int size); +static long md_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int md_new(BIO *h); +static int md_free(BIO *data); +static long md_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); + +static const BIO_METHOD methods_md = { + BIO_TYPE_MD, + "message digest", + /* TODO: Convert to new style write function */ + bwrite_conv, + md_write, + /* TODO: Convert to new style read function */ + bread_conv, + md_read, + NULL, /* md_puts, */ + md_gets, + md_ctrl, + md_new, + md_free, + md_callback_ctrl, +}; + +const BIO_METHOD *BIO_f_md(void) +{ + return &methods_md; +} + +static int md_new(BIO *bi) +{ + EVP_MD_CTX *ctx; + + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) + return 0; + + BIO_set_init(bi, 1); + BIO_set_data(bi, ctx); + + return 1; +} + +static int md_free(BIO *a) +{ + if (a == NULL) + return 0; + EVP_MD_CTX_free(BIO_get_data(a)); + BIO_set_data(a, NULL); + BIO_set_init(a, 0); + + return 1; +} + +static int md_read(BIO *b, char *out, int outl) +{ + int ret = 0; + EVP_MD_CTX *ctx; + BIO *next; + + if (out == NULL) + return 0; + + ctx = BIO_get_data(b); + next = BIO_next(b); + + if ((ctx == NULL) || (next == NULL)) + return 0; + + ret = BIO_read(next, out, outl); + if (BIO_get_init(b)) { + if (ret > 0) { + if (EVP_DigestUpdate(ctx, (unsigned char *)out, + (unsigned int)ret) <= 0) + return -1; + } + } + BIO_clear_retry_flags(b); + BIO_copy_next_retry(b); + return ret; +} + +static int md_write(BIO *b, const char *in, int inl) +{ + int ret = 0; + EVP_MD_CTX *ctx; + BIO *next; + + if ((in == NULL) || (inl <= 0)) + return 0; + + ctx = BIO_get_data(b); + next = BIO_next(b); + if ((ctx != NULL) && (next != NULL)) + ret = BIO_write(next, in, inl); + + if (BIO_get_init(b)) { + if (ret > 0) { + if (!EVP_DigestUpdate(ctx, (const unsigned char *)in, + (unsigned int)ret)) { + BIO_clear_retry_flags(b); + return 0; + } + } + } + if (next != NULL) { + BIO_clear_retry_flags(b); + BIO_copy_next_retry(b); + } + return ret; +} + +static long md_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + EVP_MD_CTX *ctx, *dctx, **pctx; + const EVP_MD **ppmd; + EVP_MD *md; + long ret = 1; + BIO *dbio, *next; + + + ctx = BIO_get_data(b); + next = BIO_next(b); + + switch (cmd) { + case BIO_CTRL_RESET: + if (BIO_get_init(b)) + ret = EVP_DigestInit_ex(ctx, ctx->digest, NULL); + else + ret = 0; + if (ret > 0) + ret = BIO_ctrl(next, cmd, num, ptr); + break; + case BIO_C_GET_MD: + if (BIO_get_init(b)) { + ppmd = ptr; + *ppmd = ctx->digest; + } else + ret = 0; + break; + case BIO_C_GET_MD_CTX: + pctx = ptr; + *pctx = ctx; + BIO_set_init(b, 1); + break; + case BIO_C_SET_MD_CTX: + if (BIO_get_init(b)) + BIO_set_data(b, ptr); + else + ret = 0; + break; + case BIO_C_DO_STATE_MACHINE: + BIO_clear_retry_flags(b); + ret = BIO_ctrl(next, cmd, num, ptr); + BIO_copy_next_retry(b); + break; + + case BIO_C_SET_MD: + md = ptr; + ret = EVP_DigestInit_ex(ctx, md, NULL); + if (ret > 0) + BIO_set_init(b, 1); + break; + case BIO_CTRL_DUP: + dbio = ptr; + dctx = BIO_get_data(dbio); + if (!EVP_MD_CTX_copy_ex(dctx, ctx)) + return 0; + BIO_set_init(b, 1); + break; + default: + ret = BIO_ctrl(next, cmd, num, ptr); + break; + } + return ret; +} + +static long md_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) +{ + long ret = 1; + BIO *next; + + next = BIO_next(b); + + if (next == NULL) + return 0; + + switch (cmd) { + default: + ret = BIO_callback_ctrl(next, cmd, fp); + break; + } + return ret; +} + +static int md_gets(BIO *bp, char *buf, int size) +{ + EVP_MD_CTX *ctx; + unsigned int ret; + + ctx = BIO_get_data(bp); + + if (size < ctx->digest->md_size) + return 0; + + if (EVP_DigestFinal_ex(ctx, (unsigned char *)buf, &ret) <= 0) + return -1; + + return (int)ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/bio_ok.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/bio_ok.c new file mode 100644 index 000000000..a0462219b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/bio_ok.c @@ -0,0 +1,610 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + From: Arne Ansper + + Why BIO_f_reliable? + + I wrote function which took BIO* as argument, read data from it + and processed it. Then I wanted to store the input file in + encrypted form. OK I pushed BIO_f_cipher to the BIO stack + and everything was OK. BUT if user types wrong password + BIO_f_cipher outputs only garbage and my function crashes. Yes + I can and I should fix my function, but BIO_f_cipher is + easy way to add encryption support to many existing applications + and it's hard to debug and fix them all. + + So I wanted another BIO which would catch the incorrect passwords and + file damages which cause garbage on BIO_f_cipher's output. + + The easy way is to push the BIO_f_md and save the checksum at + the end of the file. However there are several problems with this + approach: + + 1) you must somehow separate checksum from actual data. + 2) you need lot's of memory when reading the file, because you + must read to the end of the file and verify the checksum before + letting the application to read the data. + + BIO_f_reliable tries to solve both problems, so that you can + read and write arbitrary long streams using only fixed amount + of memory. + + BIO_f_reliable splits data stream into blocks. Each block is prefixed + with it's length and suffixed with it's digest. So you need only + several Kbytes of memory to buffer single block before verifying + it's digest. + + BIO_f_reliable goes further and adds several important capabilities: + + 1) the digest of the block is computed over the whole stream + -- so nobody can rearrange the blocks or remove or replace them. + + 2) to detect invalid passwords right at the start BIO_f_reliable + adds special prefix to the stream. In order to avoid known plain-text + attacks this prefix is generated as follows: + + *) digest is initialized with random seed instead of + standardized one. + *) same seed is written to output + *) well-known text is then hashed and the output + of the digest is also written to output. + + reader can now read the seed from stream, hash the same string + and then compare the digest output. + + Bad things: BIO_f_reliable knows what's going on in EVP_Digest. I + initially wrote and tested this code on x86 machine and wrote the + digests out in machine-dependent order :( There are people using + this code and I cannot change this easily without making existing + data files unreadable. + +*/ + +#include +#include +#include +#include "internal/cryptlib.h" +#include +#include "internal/bio.h" +#include +#include +#include "internal/evp_int.h" + +static int ok_write(BIO *h, const char *buf, int num); +static int ok_read(BIO *h, char *buf, int size); +static long ok_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int ok_new(BIO *h); +static int ok_free(BIO *data); +static long ok_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); + +static __owur int sig_out(BIO *b); +static __owur int sig_in(BIO *b); +static __owur int block_out(BIO *b); +static __owur int block_in(BIO *b); +#define OK_BLOCK_SIZE (1024*4) +#define OK_BLOCK_BLOCK 4 +#define IOBS (OK_BLOCK_SIZE+ OK_BLOCK_BLOCK+ 3*EVP_MAX_MD_SIZE) +#define WELLKNOWN "The quick brown fox jumped over the lazy dog's back." + +typedef struct ok_struct { + size_t buf_len; + size_t buf_off; + size_t buf_len_save; + size_t buf_off_save; + int cont; /* <= 0 when finished */ + int finished; + EVP_MD_CTX *md; + int blockout; /* output block is ready */ + int sigio; /* must process signature */ + unsigned char buf[IOBS]; +} BIO_OK_CTX; + +static const BIO_METHOD methods_ok = { + BIO_TYPE_CIPHER, + "reliable", + /* TODO: Convert to new style write function */ + bwrite_conv, + ok_write, + /* TODO: Convert to new style read function */ + bread_conv, + ok_read, + NULL, /* ok_puts, */ + NULL, /* ok_gets, */ + ok_ctrl, + ok_new, + ok_free, + ok_callback_ctrl, +}; + +const BIO_METHOD *BIO_f_reliable(void) +{ + return &methods_ok; +} + +static int ok_new(BIO *bi) +{ + BIO_OK_CTX *ctx; + + if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) { + EVPerr(EVP_F_OK_NEW, ERR_R_MALLOC_FAILURE); + return 0; + } + + ctx->cont = 1; + ctx->sigio = 1; + ctx->md = EVP_MD_CTX_new(); + if (ctx->md == NULL) { + OPENSSL_free(ctx); + return 0; + } + BIO_set_init(bi, 0); + BIO_set_data(bi, ctx); + + return 1; +} + +static int ok_free(BIO *a) +{ + BIO_OK_CTX *ctx; + + if (a == NULL) + return 0; + + ctx = BIO_get_data(a); + + EVP_MD_CTX_free(ctx->md); + OPENSSL_clear_free(ctx, sizeof(BIO_OK_CTX)); + BIO_set_data(a, NULL); + BIO_set_init(a, 0); + + return 1; +} + +static int ok_read(BIO *b, char *out, int outl) +{ + int ret = 0, i, n; + BIO_OK_CTX *ctx; + BIO *next; + + if (out == NULL) + return 0; + + ctx = BIO_get_data(b); + next = BIO_next(b); + + if ((ctx == NULL) || (next == NULL) || (BIO_get_init(b) == 0)) + return 0; + + while (outl > 0) { + + /* copy clean bytes to output buffer */ + if (ctx->blockout) { + i = ctx->buf_len - ctx->buf_off; + if (i > outl) + i = outl; + memcpy(out, &(ctx->buf[ctx->buf_off]), i); + ret += i; + out += i; + outl -= i; + ctx->buf_off += i; + + /* all clean bytes are out */ + if (ctx->buf_len == ctx->buf_off) { + ctx->buf_off = 0; + + /* + * copy start of the next block into proper place + */ + if (ctx->buf_len_save - ctx->buf_off_save > 0) { + ctx->buf_len = ctx->buf_len_save - ctx->buf_off_save; + memmove(ctx->buf, &(ctx->buf[ctx->buf_off_save]), + ctx->buf_len); + } else { + ctx->buf_len = 0; + } + ctx->blockout = 0; + } + } + + /* output buffer full -- cancel */ + if (outl == 0) + break; + + /* no clean bytes in buffer -- fill it */ + n = IOBS - ctx->buf_len; + i = BIO_read(next, &(ctx->buf[ctx->buf_len]), n); + + if (i <= 0) + break; /* nothing new */ + + ctx->buf_len += i; + + /* no signature yet -- check if we got one */ + if (ctx->sigio == 1) { + if (!sig_in(b)) { + BIO_clear_retry_flags(b); + return 0; + } + } + + /* signature ok -- check if we got block */ + if (ctx->sigio == 0) { + if (!block_in(b)) { + BIO_clear_retry_flags(b); + return 0; + } + } + + /* invalid block -- cancel */ + if (ctx->cont <= 0) + break; + + } + + BIO_clear_retry_flags(b); + BIO_copy_next_retry(b); + return ret; +} + +static int ok_write(BIO *b, const char *in, int inl) +{ + int ret = 0, n, i; + BIO_OK_CTX *ctx; + BIO *next; + + if (inl <= 0) + return inl; + + ctx = BIO_get_data(b); + next = BIO_next(b); + ret = inl; + + if ((ctx == NULL) || (next == NULL) || (BIO_get_init(b) == 0)) + return 0; + + if (ctx->sigio && !sig_out(b)) + return 0; + + do { + BIO_clear_retry_flags(b); + n = ctx->buf_len - ctx->buf_off; + while (ctx->blockout && n > 0) { + i = BIO_write(next, &(ctx->buf[ctx->buf_off]), n); + if (i <= 0) { + BIO_copy_next_retry(b); + if (!BIO_should_retry(b)) + ctx->cont = 0; + return i; + } + ctx->buf_off += i; + n -= i; + } + + /* at this point all pending data has been written */ + ctx->blockout = 0; + if (ctx->buf_len == ctx->buf_off) { + ctx->buf_len = OK_BLOCK_BLOCK; + ctx->buf_off = 0; + } + + if ((in == NULL) || (inl <= 0)) + return 0; + + n = (inl + ctx->buf_len > OK_BLOCK_SIZE + OK_BLOCK_BLOCK) ? + (int)(OK_BLOCK_SIZE + OK_BLOCK_BLOCK - ctx->buf_len) : inl; + + memcpy(&ctx->buf[ctx->buf_len], in, n); + ctx->buf_len += n; + inl -= n; + in += n; + + if (ctx->buf_len >= OK_BLOCK_SIZE + OK_BLOCK_BLOCK) { + if (!block_out(b)) { + BIO_clear_retry_flags(b); + return 0; + } + } + } while (inl > 0); + + BIO_clear_retry_flags(b); + BIO_copy_next_retry(b); + return ret; +} + +static long ok_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + BIO_OK_CTX *ctx; + EVP_MD *md; + const EVP_MD **ppmd; + long ret = 1; + int i; + BIO *next; + + ctx = BIO_get_data(b); + next = BIO_next(b); + + switch (cmd) { + case BIO_CTRL_RESET: + ctx->buf_len = 0; + ctx->buf_off = 0; + ctx->buf_len_save = 0; + ctx->buf_off_save = 0; + ctx->cont = 1; + ctx->finished = 0; + ctx->blockout = 0; + ctx->sigio = 1; + ret = BIO_ctrl(next, cmd, num, ptr); + break; + case BIO_CTRL_EOF: /* More to read */ + if (ctx->cont <= 0) + ret = 1; + else + ret = BIO_ctrl(next, cmd, num, ptr); + break; + case BIO_CTRL_PENDING: /* More to read in buffer */ + case BIO_CTRL_WPENDING: /* More to read in buffer */ + ret = ctx->blockout ? ctx->buf_len - ctx->buf_off : 0; + if (ret <= 0) + ret = BIO_ctrl(next, cmd, num, ptr); + break; + case BIO_CTRL_FLUSH: + /* do a final write */ + if (ctx->blockout == 0) + if (!block_out(b)) + return 0; + + while (ctx->blockout) { + i = ok_write(b, NULL, 0); + if (i < 0) { + ret = i; + break; + } + } + + ctx->finished = 1; + ctx->buf_off = ctx->buf_len = 0; + ctx->cont = (int)ret; + + /* Finally flush the underlying BIO */ + ret = BIO_ctrl(next, cmd, num, ptr); + break; + case BIO_C_DO_STATE_MACHINE: + BIO_clear_retry_flags(b); + ret = BIO_ctrl(next, cmd, num, ptr); + BIO_copy_next_retry(b); + break; + case BIO_CTRL_INFO: + ret = (long)ctx->cont; + break; + case BIO_C_SET_MD: + md = ptr; + if (!EVP_DigestInit_ex(ctx->md, md, NULL)) + return 0; + BIO_set_init(b, 1); + break; + case BIO_C_GET_MD: + if (BIO_get_init(b)) { + ppmd = ptr; + *ppmd = EVP_MD_CTX_md(ctx->md); + } else + ret = 0; + break; + default: + ret = BIO_ctrl(next, cmd, num, ptr); + break; + } + return ret; +} + +static long ok_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) +{ + long ret = 1; + BIO *next; + + next = BIO_next(b); + + if (next == NULL) + return 0; + + switch (cmd) { + default: + ret = BIO_callback_ctrl(next, cmd, fp); + break; + } + + return ret; +} + +static void longswap(void *_ptr, size_t len) +{ + const union { + long one; + char little; + } is_endian = { + 1 + }; + + if (is_endian.little) { + size_t i; + unsigned char *p = _ptr, c; + + for (i = 0; i < len; i += 4) { + c = p[0], p[0] = p[3], p[3] = c; + c = p[1], p[1] = p[2], p[2] = c; + } + } +} + +static int sig_out(BIO *b) +{ + BIO_OK_CTX *ctx; + EVP_MD_CTX *md; + const EVP_MD *digest; + int md_size; + void *md_data; + + ctx = BIO_get_data(b); + md = ctx->md; + digest = EVP_MD_CTX_md(md); + md_size = EVP_MD_size(digest); + md_data = EVP_MD_CTX_md_data(md); + + if (ctx->buf_len + 2 * md_size > OK_BLOCK_SIZE) + return 1; + + if (!EVP_DigestInit_ex(md, digest, NULL)) + goto berr; + /* + * FIXME: there's absolutely no guarantee this makes any sense at all, + * particularly now EVP_MD_CTX has been restructured. + */ + if (RAND_bytes(md_data, md_size) <= 0) + goto berr; + memcpy(&(ctx->buf[ctx->buf_len]), md_data, md_size); + longswap(&(ctx->buf[ctx->buf_len]), md_size); + ctx->buf_len += md_size; + + if (!EVP_DigestUpdate(md, WELLKNOWN, strlen(WELLKNOWN))) + goto berr; + if (!EVP_DigestFinal_ex(md, &(ctx->buf[ctx->buf_len]), NULL)) + goto berr; + ctx->buf_len += md_size; + ctx->blockout = 1; + ctx->sigio = 0; + return 1; + berr: + BIO_clear_retry_flags(b); + return 0; +} + +static int sig_in(BIO *b) +{ + BIO_OK_CTX *ctx; + EVP_MD_CTX *md; + unsigned char tmp[EVP_MAX_MD_SIZE]; + int ret = 0; + const EVP_MD *digest; + int md_size; + void *md_data; + + ctx = BIO_get_data(b); + md = ctx->md; + digest = EVP_MD_CTX_md(md); + md_size = EVP_MD_size(digest); + md_data = EVP_MD_CTX_md_data(md); + + if ((int)(ctx->buf_len - ctx->buf_off) < 2 * md_size) + return 1; + + if (!EVP_DigestInit_ex(md, digest, NULL)) + goto berr; + memcpy(md_data, &(ctx->buf[ctx->buf_off]), md_size); + longswap(md_data, md_size); + ctx->buf_off += md_size; + + if (!EVP_DigestUpdate(md, WELLKNOWN, strlen(WELLKNOWN))) + goto berr; + if (!EVP_DigestFinal_ex(md, tmp, NULL)) + goto berr; + ret = memcmp(&(ctx->buf[ctx->buf_off]), tmp, md_size) == 0; + ctx->buf_off += md_size; + if (ret == 1) { + ctx->sigio = 0; + if (ctx->buf_len != ctx->buf_off) { + memmove(ctx->buf, &(ctx->buf[ctx->buf_off]), + ctx->buf_len - ctx->buf_off); + } + ctx->buf_len -= ctx->buf_off; + ctx->buf_off = 0; + } else { + ctx->cont = 0; + } + return 1; + berr: + BIO_clear_retry_flags(b); + return 0; +} + +static int block_out(BIO *b) +{ + BIO_OK_CTX *ctx; + EVP_MD_CTX *md; + unsigned long tl; + const EVP_MD *digest; + int md_size; + + ctx = BIO_get_data(b); + md = ctx->md; + digest = EVP_MD_CTX_md(md); + md_size = EVP_MD_size(digest); + + tl = ctx->buf_len - OK_BLOCK_BLOCK; + ctx->buf[0] = (unsigned char)(tl >> 24); + ctx->buf[1] = (unsigned char)(tl >> 16); + ctx->buf[2] = (unsigned char)(tl >> 8); + ctx->buf[3] = (unsigned char)(tl); + if (!EVP_DigestUpdate(md, + (unsigned char *)&(ctx->buf[OK_BLOCK_BLOCK]), tl)) + goto berr; + if (!EVP_DigestFinal_ex(md, &(ctx->buf[ctx->buf_len]), NULL)) + goto berr; + ctx->buf_len += md_size; + ctx->blockout = 1; + return 1; + berr: + BIO_clear_retry_flags(b); + return 0; +} + +static int block_in(BIO *b) +{ + BIO_OK_CTX *ctx; + EVP_MD_CTX *md; + unsigned long tl = 0; + unsigned char tmp[EVP_MAX_MD_SIZE]; + int md_size; + + ctx = BIO_get_data(b); + md = ctx->md; + md_size = EVP_MD_size(EVP_MD_CTX_md(md)); + + assert(sizeof(tl) >= OK_BLOCK_BLOCK); /* always true */ + tl = ctx->buf[0]; + tl <<= 8; + tl |= ctx->buf[1]; + tl <<= 8; + tl |= ctx->buf[2]; + tl <<= 8; + tl |= ctx->buf[3]; + + if (ctx->buf_len < tl + OK_BLOCK_BLOCK + md_size) + return 1; + + if (!EVP_DigestUpdate(md, + (unsigned char *)&(ctx->buf[OK_BLOCK_BLOCK]), tl)) + goto berr; + if (!EVP_DigestFinal_ex(md, tmp, NULL)) + goto berr; + if (memcmp(&(ctx->buf[tl + OK_BLOCK_BLOCK]), tmp, md_size) == 0) { + /* there might be parts from next block lurking around ! */ + ctx->buf_off_save = tl + OK_BLOCK_BLOCK + md_size; + ctx->buf_len_save = ctx->buf_len; + ctx->buf_off = OK_BLOCK_BLOCK; + ctx->buf_len = tl + OK_BLOCK_BLOCK; + ctx->blockout = 1; + } else { + ctx->cont = 0; + } + return 1; + berr: + BIO_clear_retry_flags(b); + return 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/build.info new file mode 100644 index 000000000..cc33ac3c4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/build.info @@ -0,0 +1,25 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + encode.c digest.c evp_enc.c evp_key.c evp_cnf.c \ + e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\ + e_rc4.c e_aes.c names.c e_seed.c e_aria.c e_sm4.c \ + e_xcbc_d.c e_rc2.c e_cast.c e_rc5.c \ + m_null.c m_md2.c m_md4.c m_md5.c m_sha1.c m_wp.c \ + m_md5_sha1.c m_mdc2.c m_ripemd.c m_sha3.c \ + p_open.c p_seal.c p_sign.c p_verify.c p_lib.c p_enc.c p_dec.c \ + bio_md.c bio_b64.c bio_enc.c evp_err.c e_null.c \ + c_allc.c c_alld.c evp_lib.c bio_ok.c \ + evp_pkey.c evp_pbe.c p5_crpt.c p5_crpt2.c pbe_scrypt.c \ + e_old.c pmeth_lib.c pmeth_fn.c pmeth_gn.c m_sigver.c \ + e_aes_cbc_hmac_sha1.c e_aes_cbc_hmac_sha256.c e_rc4_hmac_md5.c \ + e_chacha20_poly1305.c cmeth_lib.c + +INCLUDE[e_aes.o]=.. ../modes +INCLUDE[e_aes_cbc_hmac_sha1.o]=../modes +INCLUDE[e_aes_cbc_hmac_sha256.o]=../modes +INCLUDE[e_aria.o]=.. ../modes +INCLUDE[e_camellia.o]=.. ../modes +INCLUDE[e_sm4.o]=.. ../modes +INCLUDE[e_des.o]=.. +INCLUDE[e_des3.o]=.. +INCLUDE[m_sha3.o]=.. diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/c_allc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/c_allc.c new file mode 100644 index 000000000..086b3c4d5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/c_allc.c @@ -0,0 +1,266 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include "internal/evp_int.h" +#include +#include + +void openssl_add_all_ciphers_int(void) +{ + +#ifndef OPENSSL_NO_DES + EVP_add_cipher(EVP_des_cfb()); + EVP_add_cipher(EVP_des_cfb1()); + EVP_add_cipher(EVP_des_cfb8()); + EVP_add_cipher(EVP_des_ede_cfb()); + EVP_add_cipher(EVP_des_ede3_cfb()); + EVP_add_cipher(EVP_des_ede3_cfb1()); + EVP_add_cipher(EVP_des_ede3_cfb8()); + + EVP_add_cipher(EVP_des_ofb()); + EVP_add_cipher(EVP_des_ede_ofb()); + EVP_add_cipher(EVP_des_ede3_ofb()); + + EVP_add_cipher(EVP_desx_cbc()); + EVP_add_cipher_alias(SN_desx_cbc, "DESX"); + EVP_add_cipher_alias(SN_desx_cbc, "desx"); + + EVP_add_cipher(EVP_des_cbc()); + EVP_add_cipher_alias(SN_des_cbc, "DES"); + EVP_add_cipher_alias(SN_des_cbc, "des"); + EVP_add_cipher(EVP_des_ede_cbc()); + EVP_add_cipher(EVP_des_ede3_cbc()); + EVP_add_cipher_alias(SN_des_ede3_cbc, "DES3"); + EVP_add_cipher_alias(SN_des_ede3_cbc, "des3"); + + EVP_add_cipher(EVP_des_ecb()); + EVP_add_cipher(EVP_des_ede()); + EVP_add_cipher_alias(SN_des_ede_ecb, "DES-EDE-ECB"); + EVP_add_cipher_alias(SN_des_ede_ecb, "des-ede-ecb"); + EVP_add_cipher(EVP_des_ede3()); + EVP_add_cipher_alias(SN_des_ede3_ecb, "DES-EDE3-ECB"); + EVP_add_cipher_alias(SN_des_ede3_ecb, "des-ede3-ecb"); + EVP_add_cipher(EVP_des_ede3_wrap()); + EVP_add_cipher_alias(SN_id_smime_alg_CMS3DESwrap, "des3-wrap"); +#endif + +#ifndef OPENSSL_NO_RC4 + EVP_add_cipher(EVP_rc4()); + EVP_add_cipher(EVP_rc4_40()); +# ifndef OPENSSL_NO_MD5 + EVP_add_cipher(EVP_rc4_hmac_md5()); +# endif +#endif + +#ifndef OPENSSL_NO_IDEA + EVP_add_cipher(EVP_idea_ecb()); + EVP_add_cipher(EVP_idea_cfb()); + EVP_add_cipher(EVP_idea_ofb()); + EVP_add_cipher(EVP_idea_cbc()); + EVP_add_cipher_alias(SN_idea_cbc, "IDEA"); + EVP_add_cipher_alias(SN_idea_cbc, "idea"); +#endif + +#ifndef OPENSSL_NO_SEED + EVP_add_cipher(EVP_seed_ecb()); + EVP_add_cipher(EVP_seed_cfb()); + EVP_add_cipher(EVP_seed_ofb()); + EVP_add_cipher(EVP_seed_cbc()); + EVP_add_cipher_alias(SN_seed_cbc, "SEED"); + EVP_add_cipher_alias(SN_seed_cbc, "seed"); +#endif + +#ifndef OPENSSL_NO_SM4 + EVP_add_cipher(EVP_sm4_ecb()); + EVP_add_cipher(EVP_sm4_cbc()); + EVP_add_cipher(EVP_sm4_cfb()); + EVP_add_cipher(EVP_sm4_ofb()); + EVP_add_cipher(EVP_sm4_ctr()); + EVP_add_cipher_alias(SN_sm4_cbc, "SM4"); + EVP_add_cipher_alias(SN_sm4_cbc, "sm4"); +#endif + +#ifndef OPENSSL_NO_RC2 + EVP_add_cipher(EVP_rc2_ecb()); + EVP_add_cipher(EVP_rc2_cfb()); + EVP_add_cipher(EVP_rc2_ofb()); + EVP_add_cipher(EVP_rc2_cbc()); + EVP_add_cipher(EVP_rc2_40_cbc()); + EVP_add_cipher(EVP_rc2_64_cbc()); + EVP_add_cipher_alias(SN_rc2_cbc, "RC2"); + EVP_add_cipher_alias(SN_rc2_cbc, "rc2"); + EVP_add_cipher_alias(SN_rc2_cbc, "rc2-128"); + EVP_add_cipher_alias(SN_rc2_64_cbc, "rc2-64"); + EVP_add_cipher_alias(SN_rc2_40_cbc, "rc2-40"); +#endif + +#ifndef OPENSSL_NO_BF + EVP_add_cipher(EVP_bf_ecb()); + EVP_add_cipher(EVP_bf_cfb()); + EVP_add_cipher(EVP_bf_ofb()); + EVP_add_cipher(EVP_bf_cbc()); + EVP_add_cipher_alias(SN_bf_cbc, "BF"); + EVP_add_cipher_alias(SN_bf_cbc, "bf"); + EVP_add_cipher_alias(SN_bf_cbc, "blowfish"); +#endif + +#ifndef OPENSSL_NO_CAST + EVP_add_cipher(EVP_cast5_ecb()); + EVP_add_cipher(EVP_cast5_cfb()); + EVP_add_cipher(EVP_cast5_ofb()); + EVP_add_cipher(EVP_cast5_cbc()); + EVP_add_cipher_alias(SN_cast5_cbc, "CAST"); + EVP_add_cipher_alias(SN_cast5_cbc, "cast"); + EVP_add_cipher_alias(SN_cast5_cbc, "CAST-cbc"); + EVP_add_cipher_alias(SN_cast5_cbc, "cast-cbc"); +#endif + +#ifndef OPENSSL_NO_RC5 + EVP_add_cipher(EVP_rc5_32_12_16_ecb()); + EVP_add_cipher(EVP_rc5_32_12_16_cfb()); + EVP_add_cipher(EVP_rc5_32_12_16_ofb()); + EVP_add_cipher(EVP_rc5_32_12_16_cbc()); + EVP_add_cipher_alias(SN_rc5_cbc, "rc5"); + EVP_add_cipher_alias(SN_rc5_cbc, "RC5"); +#endif + + EVP_add_cipher(EVP_aes_128_ecb()); + EVP_add_cipher(EVP_aes_128_cbc()); + EVP_add_cipher(EVP_aes_128_cfb()); + EVP_add_cipher(EVP_aes_128_cfb1()); + EVP_add_cipher(EVP_aes_128_cfb8()); + EVP_add_cipher(EVP_aes_128_ofb()); + EVP_add_cipher(EVP_aes_128_ctr()); + EVP_add_cipher(EVP_aes_128_gcm()); +#ifndef OPENSSL_NO_OCB + EVP_add_cipher(EVP_aes_128_ocb()); +#endif + EVP_add_cipher(EVP_aes_128_xts()); + EVP_add_cipher(EVP_aes_128_ccm()); + EVP_add_cipher(EVP_aes_128_wrap()); + EVP_add_cipher_alias(SN_id_aes128_wrap, "aes128-wrap"); + EVP_add_cipher(EVP_aes_128_wrap_pad()); + EVP_add_cipher_alias(SN_aes_128_cbc, "AES128"); + EVP_add_cipher_alias(SN_aes_128_cbc, "aes128"); + EVP_add_cipher(EVP_aes_192_ecb()); + EVP_add_cipher(EVP_aes_192_cbc()); + EVP_add_cipher(EVP_aes_192_cfb()); + EVP_add_cipher(EVP_aes_192_cfb1()); + EVP_add_cipher(EVP_aes_192_cfb8()); + EVP_add_cipher(EVP_aes_192_ofb()); + EVP_add_cipher(EVP_aes_192_ctr()); + EVP_add_cipher(EVP_aes_192_gcm()); +#ifndef OPENSSL_NO_OCB + EVP_add_cipher(EVP_aes_192_ocb()); +#endif + EVP_add_cipher(EVP_aes_192_ccm()); + EVP_add_cipher(EVP_aes_192_wrap()); + EVP_add_cipher_alias(SN_id_aes192_wrap, "aes192-wrap"); + EVP_add_cipher(EVP_aes_192_wrap_pad()); + EVP_add_cipher_alias(SN_aes_192_cbc, "AES192"); + EVP_add_cipher_alias(SN_aes_192_cbc, "aes192"); + EVP_add_cipher(EVP_aes_256_ecb()); + EVP_add_cipher(EVP_aes_256_cbc()); + EVP_add_cipher(EVP_aes_256_cfb()); + EVP_add_cipher(EVP_aes_256_cfb1()); + EVP_add_cipher(EVP_aes_256_cfb8()); + EVP_add_cipher(EVP_aes_256_ofb()); + EVP_add_cipher(EVP_aes_256_ctr()); + EVP_add_cipher(EVP_aes_256_gcm()); +#ifndef OPENSSL_NO_OCB + EVP_add_cipher(EVP_aes_256_ocb()); +#endif + EVP_add_cipher(EVP_aes_256_xts()); + EVP_add_cipher(EVP_aes_256_ccm()); + EVP_add_cipher(EVP_aes_256_wrap()); + EVP_add_cipher_alias(SN_id_aes256_wrap, "aes256-wrap"); + EVP_add_cipher(EVP_aes_256_wrap_pad()); + EVP_add_cipher_alias(SN_aes_256_cbc, "AES256"); + EVP_add_cipher_alias(SN_aes_256_cbc, "aes256"); + EVP_add_cipher(EVP_aes_128_cbc_hmac_sha1()); + EVP_add_cipher(EVP_aes_256_cbc_hmac_sha1()); + EVP_add_cipher(EVP_aes_128_cbc_hmac_sha256()); + EVP_add_cipher(EVP_aes_256_cbc_hmac_sha256()); + +#ifndef OPENSSL_NO_ARIA + EVP_add_cipher(EVP_aria_128_ecb()); + EVP_add_cipher(EVP_aria_128_cbc()); + EVP_add_cipher(EVP_aria_128_cfb()); + EVP_add_cipher(EVP_aria_128_cfb1()); + EVP_add_cipher(EVP_aria_128_cfb8()); + EVP_add_cipher(EVP_aria_128_ctr()); + EVP_add_cipher(EVP_aria_128_ofb()); + EVP_add_cipher(EVP_aria_128_gcm()); + EVP_add_cipher(EVP_aria_128_ccm()); + EVP_add_cipher_alias(SN_aria_128_cbc, "ARIA128"); + EVP_add_cipher_alias(SN_aria_128_cbc, "aria128"); + EVP_add_cipher(EVP_aria_192_ecb()); + EVP_add_cipher(EVP_aria_192_cbc()); + EVP_add_cipher(EVP_aria_192_cfb()); + EVP_add_cipher(EVP_aria_192_cfb1()); + EVP_add_cipher(EVP_aria_192_cfb8()); + EVP_add_cipher(EVP_aria_192_ctr()); + EVP_add_cipher(EVP_aria_192_ofb()); + EVP_add_cipher(EVP_aria_192_gcm()); + EVP_add_cipher(EVP_aria_192_ccm()); + EVP_add_cipher_alias(SN_aria_192_cbc, "ARIA192"); + EVP_add_cipher_alias(SN_aria_192_cbc, "aria192"); + EVP_add_cipher(EVP_aria_256_ecb()); + EVP_add_cipher(EVP_aria_256_cbc()); + EVP_add_cipher(EVP_aria_256_cfb()); + EVP_add_cipher(EVP_aria_256_cfb1()); + EVP_add_cipher(EVP_aria_256_cfb8()); + EVP_add_cipher(EVP_aria_256_ctr()); + EVP_add_cipher(EVP_aria_256_ofb()); + EVP_add_cipher(EVP_aria_256_gcm()); + EVP_add_cipher(EVP_aria_256_ccm()); + EVP_add_cipher_alias(SN_aria_256_cbc, "ARIA256"); + EVP_add_cipher_alias(SN_aria_256_cbc, "aria256"); +#endif + +#ifndef OPENSSL_NO_CAMELLIA + EVP_add_cipher(EVP_camellia_128_ecb()); + EVP_add_cipher(EVP_camellia_128_cbc()); + EVP_add_cipher(EVP_camellia_128_cfb()); + EVP_add_cipher(EVP_camellia_128_cfb1()); + EVP_add_cipher(EVP_camellia_128_cfb8()); + EVP_add_cipher(EVP_camellia_128_ofb()); + EVP_add_cipher_alias(SN_camellia_128_cbc, "CAMELLIA128"); + EVP_add_cipher_alias(SN_camellia_128_cbc, "camellia128"); + EVP_add_cipher(EVP_camellia_192_ecb()); + EVP_add_cipher(EVP_camellia_192_cbc()); + EVP_add_cipher(EVP_camellia_192_cfb()); + EVP_add_cipher(EVP_camellia_192_cfb1()); + EVP_add_cipher(EVP_camellia_192_cfb8()); + EVP_add_cipher(EVP_camellia_192_ofb()); + EVP_add_cipher_alias(SN_camellia_192_cbc, "CAMELLIA192"); + EVP_add_cipher_alias(SN_camellia_192_cbc, "camellia192"); + EVP_add_cipher(EVP_camellia_256_ecb()); + EVP_add_cipher(EVP_camellia_256_cbc()); + EVP_add_cipher(EVP_camellia_256_cfb()); + EVP_add_cipher(EVP_camellia_256_cfb1()); + EVP_add_cipher(EVP_camellia_256_cfb8()); + EVP_add_cipher(EVP_camellia_256_ofb()); + EVP_add_cipher_alias(SN_camellia_256_cbc, "CAMELLIA256"); + EVP_add_cipher_alias(SN_camellia_256_cbc, "camellia256"); + EVP_add_cipher(EVP_camellia_128_ctr()); + EVP_add_cipher(EVP_camellia_192_ctr()); + EVP_add_cipher(EVP_camellia_256_ctr()); +#endif + +#ifndef OPENSSL_NO_CHACHA + EVP_add_cipher(EVP_chacha20()); +# ifndef OPENSSL_NO_POLY1305 + EVP_add_cipher(EVP_chacha20_poly1305()); +# endif +#endif +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/c_alld.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/c_alld.c new file mode 100644 index 000000000..1267531a7 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/c_alld.c @@ -0,0 +1,60 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include "internal/evp_int.h" +#include +#include + +void openssl_add_all_digests_int(void) +{ +#ifndef OPENSSL_NO_MD4 + EVP_add_digest(EVP_md4()); +#endif +#ifndef OPENSSL_NO_MD5 + EVP_add_digest(EVP_md5()); + EVP_add_digest_alias(SN_md5, "ssl3-md5"); + EVP_add_digest(EVP_md5_sha1()); +#endif + EVP_add_digest(EVP_sha1()); + EVP_add_digest_alias(SN_sha1, "ssl3-sha1"); + EVP_add_digest_alias(SN_sha1WithRSAEncryption, SN_sha1WithRSA); +#if !defined(OPENSSL_NO_MDC2) && !defined(OPENSSL_NO_DES) + EVP_add_digest(EVP_mdc2()); +#endif +#ifndef OPENSSL_NO_RMD160 + EVP_add_digest(EVP_ripemd160()); + EVP_add_digest_alias(SN_ripemd160, "ripemd"); + EVP_add_digest_alias(SN_ripemd160, "rmd160"); +#endif + EVP_add_digest(EVP_sha224()); + EVP_add_digest(EVP_sha256()); + EVP_add_digest(EVP_sha384()); + EVP_add_digest(EVP_sha512()); + EVP_add_digest(EVP_sha512_224()); + EVP_add_digest(EVP_sha512_256()); +#ifndef OPENSSL_NO_WHIRLPOOL + EVP_add_digest(EVP_whirlpool()); +#endif +#ifndef OPENSSL_NO_SM3 + EVP_add_digest(EVP_sm3()); +#endif +#ifndef OPENSSL_NO_BLAKE2 + EVP_add_digest(EVP_blake2b512()); + EVP_add_digest(EVP_blake2s256()); +#endif + EVP_add_digest(EVP_sha3_224()); + EVP_add_digest(EVP_sha3_256()); + EVP_add_digest(EVP_sha3_384()); + EVP_add_digest(EVP_sha3_512()); + EVP_add_digest(EVP_shake128()); + EVP_add_digest(EVP_shake256()); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/cmeth_lib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/cmeth_lib.c new file mode 100644 index 000000000..e2295c4dc --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/cmeth_lib.c @@ -0,0 +1,151 @@ +/* + * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#include +#include "internal/evp_int.h" +#include "evp_locl.h" + +EVP_CIPHER *EVP_CIPHER_meth_new(int cipher_type, int block_size, int key_len) +{ + EVP_CIPHER *cipher = OPENSSL_zalloc(sizeof(EVP_CIPHER)); + + if (cipher != NULL) { + cipher->nid = cipher_type; + cipher->block_size = block_size; + cipher->key_len = key_len; + } + return cipher; +} + +EVP_CIPHER *EVP_CIPHER_meth_dup(const EVP_CIPHER *cipher) +{ + EVP_CIPHER *to = EVP_CIPHER_meth_new(cipher->nid, cipher->block_size, + cipher->key_len); + + if (to != NULL) + memcpy(to, cipher, sizeof(*to)); + return to; +} + +void EVP_CIPHER_meth_free(EVP_CIPHER *cipher) +{ + OPENSSL_free(cipher); +} + +int EVP_CIPHER_meth_set_iv_length(EVP_CIPHER *cipher, int iv_len) +{ + cipher->iv_len = iv_len; + return 1; +} + +int EVP_CIPHER_meth_set_flags(EVP_CIPHER *cipher, unsigned long flags) +{ + cipher->flags = flags; + return 1; +} + +int EVP_CIPHER_meth_set_impl_ctx_size(EVP_CIPHER *cipher, int ctx_size) +{ + cipher->ctx_size = ctx_size; + return 1; +} + +int EVP_CIPHER_meth_set_init(EVP_CIPHER *cipher, + int (*init) (EVP_CIPHER_CTX *ctx, + const unsigned char *key, + const unsigned char *iv, + int enc)) +{ + cipher->init = init; + return 1; +} + +int EVP_CIPHER_meth_set_do_cipher(EVP_CIPHER *cipher, + int (*do_cipher) (EVP_CIPHER_CTX *ctx, + unsigned char *out, + const unsigned char *in, + size_t inl)) +{ + cipher->do_cipher = do_cipher; + return 1; +} + +int EVP_CIPHER_meth_set_cleanup(EVP_CIPHER *cipher, + int (*cleanup) (EVP_CIPHER_CTX *)) +{ + cipher->cleanup = cleanup; + return 1; +} + +int EVP_CIPHER_meth_set_set_asn1_params(EVP_CIPHER *cipher, + int (*set_asn1_parameters) (EVP_CIPHER_CTX *, + ASN1_TYPE *)) +{ + cipher->set_asn1_parameters = set_asn1_parameters; + return 1; +} + +int EVP_CIPHER_meth_set_get_asn1_params(EVP_CIPHER *cipher, + int (*get_asn1_parameters) (EVP_CIPHER_CTX *, + ASN1_TYPE *)) +{ + cipher->get_asn1_parameters = get_asn1_parameters; + return 1; +} + +int EVP_CIPHER_meth_set_ctrl(EVP_CIPHER *cipher, + int (*ctrl) (EVP_CIPHER_CTX *, int type, + int arg, void *ptr)) +{ + cipher->ctrl = ctrl; + return 1; +} + + +int (*EVP_CIPHER_meth_get_init(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *ctx, + const unsigned char *key, + const unsigned char *iv, + int enc) +{ + return cipher->init; +} +int (*EVP_CIPHER_meth_get_do_cipher(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *ctx, + unsigned char *out, + const unsigned char *in, + size_t inl) +{ + return cipher->do_cipher; +} + +int (*EVP_CIPHER_meth_get_cleanup(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *) +{ + return cipher->cleanup; +} + +int (*EVP_CIPHER_meth_get_set_asn1_params(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *, + ASN1_TYPE *) +{ + return cipher->set_asn1_parameters; +} + +int (*EVP_CIPHER_meth_get_get_asn1_params(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *, + ASN1_TYPE *) +{ + return cipher->get_asn1_parameters; +} + +int (*EVP_CIPHER_meth_get_ctrl(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *, + int type, int arg, + void *ptr) +{ + return cipher->ctrl; +} + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/digest.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/digest.c new file mode 100644 index 000000000..f78dab767 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/digest.c @@ -0,0 +1,298 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include "internal/evp_int.h" +#include "evp_locl.h" + +/* This call frees resources associated with the context */ +int EVP_MD_CTX_reset(EVP_MD_CTX *ctx) +{ + if (ctx == NULL) + return 1; + + /* + * Don't assume ctx->md_data was cleaned in EVP_Digest_Final, because + * sometimes only copies of the context are ever finalised. + */ + if (ctx->digest && ctx->digest->cleanup + && !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_CLEANED)) + ctx->digest->cleanup(ctx); + if (ctx->digest && ctx->digest->ctx_size && ctx->md_data + && !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_REUSE)) { + OPENSSL_clear_free(ctx->md_data, ctx->digest->ctx_size); + } + /* + * pctx should be freed by the user of EVP_MD_CTX + * if EVP_MD_CTX_FLAG_KEEP_PKEY_CTX is set + */ + if (!EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX)) + EVP_PKEY_CTX_free(ctx->pctx); +#ifndef OPENSSL_NO_ENGINE + ENGINE_finish(ctx->engine); +#endif + OPENSSL_cleanse(ctx, sizeof(*ctx)); + + return 1; +} + +EVP_MD_CTX *EVP_MD_CTX_new(void) +{ + return OPENSSL_zalloc(sizeof(EVP_MD_CTX)); +} + +void EVP_MD_CTX_free(EVP_MD_CTX *ctx) +{ + EVP_MD_CTX_reset(ctx); + OPENSSL_free(ctx); +} + +int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type) +{ + EVP_MD_CTX_reset(ctx); + return EVP_DigestInit_ex(ctx, type, NULL); +} + +int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) +{ + EVP_MD_CTX_clear_flags(ctx, EVP_MD_CTX_FLAG_CLEANED); +#ifndef OPENSSL_NO_ENGINE + /* + * Whether it's nice or not, "Inits" can be used on "Final"'d contexts so + * this context may already have an ENGINE! Try to avoid releasing the + * previous handle, re-querying for an ENGINE, and having a + * reinitialisation, when it may all be unnecessary. + */ + if (ctx->engine && ctx->digest && + (type == NULL || (type->type == ctx->digest->type))) + goto skip_to_init; + if (type) { + /* + * Ensure an ENGINE left lying around from last time is cleared (the + * previous check attempted to avoid this if the same ENGINE and + * EVP_MD could be used). + */ + ENGINE_finish(ctx->engine); + if (impl != NULL) { + if (!ENGINE_init(impl)) { + EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_INITIALIZATION_ERROR); + return 0; + } + } else { + /* Ask if an ENGINE is reserved for this job */ + impl = ENGINE_get_digest_engine(type->type); + } + if (impl != NULL) { + /* There's an ENGINE for this job ... (apparently) */ + const EVP_MD *d = ENGINE_get_digest(impl, type->type); + + if (d == NULL) { + EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_INITIALIZATION_ERROR); + ENGINE_finish(impl); + return 0; + } + /* We'll use the ENGINE's private digest definition */ + type = d; + /* + * Store the ENGINE functional reference so we know 'type' came + * from an ENGINE and we need to release it when done. + */ + ctx->engine = impl; + } else + ctx->engine = NULL; + } else { + if (!ctx->digest) { + EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_NO_DIGEST_SET); + return 0; + } + type = ctx->digest; + } +#endif + if (ctx->digest != type) { + if (ctx->digest && ctx->digest->ctx_size) { + OPENSSL_clear_free(ctx->md_data, ctx->digest->ctx_size); + ctx->md_data = NULL; + } + ctx->digest = type; + if (!(ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) && type->ctx_size) { + ctx->update = type->update; + ctx->md_data = OPENSSL_zalloc(type->ctx_size); + if (ctx->md_data == NULL) { + EVPerr(EVP_F_EVP_DIGESTINIT_EX, ERR_R_MALLOC_FAILURE); + return 0; + } + } + } +#ifndef OPENSSL_NO_ENGINE + skip_to_init: +#endif + if (ctx->pctx) { + int r; + r = EVP_PKEY_CTX_ctrl(ctx->pctx, -1, EVP_PKEY_OP_TYPE_SIG, + EVP_PKEY_CTRL_DIGESTINIT, 0, ctx); + if (r <= 0 && (r != -2)) + return 0; + } + if (ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) + return 1; + return ctx->digest->init(ctx); +} + +int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, size_t count) +{ + return ctx->update(ctx, data, count); +} + +/* The caller can assume that this removes any secret data from the context */ +int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size) +{ + int ret; + ret = EVP_DigestFinal_ex(ctx, md, size); + EVP_MD_CTX_reset(ctx); + return ret; +} + +/* The caller can assume that this removes any secret data from the context */ +int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size) +{ + int ret; + + OPENSSL_assert(ctx->digest->md_size <= EVP_MAX_MD_SIZE); + ret = ctx->digest->final(ctx, md); + if (size != NULL) + *size = ctx->digest->md_size; + if (ctx->digest->cleanup) { + ctx->digest->cleanup(ctx); + EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_CLEANED); + } + OPENSSL_cleanse(ctx->md_data, ctx->digest->ctx_size); + return ret; +} + +int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md, size_t size) +{ + int ret = 0; + + if (ctx->digest->flags & EVP_MD_FLAG_XOF + && size <= INT_MAX + && ctx->digest->md_ctrl(ctx, EVP_MD_CTRL_XOF_LEN, (int)size, NULL)) { + ret = ctx->digest->final(ctx, md); + + if (ctx->digest->cleanup != NULL) { + ctx->digest->cleanup(ctx); + EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_CLEANED); + } + OPENSSL_cleanse(ctx->md_data, ctx->digest->ctx_size); + } else { + EVPerr(EVP_F_EVP_DIGESTFINALXOF, EVP_R_NOT_XOF_OR_INVALID_LENGTH); + } + + return ret; +} + +int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in) +{ + EVP_MD_CTX_reset(out); + return EVP_MD_CTX_copy_ex(out, in); +} + +int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in) +{ + unsigned char *tmp_buf; + if ((in == NULL) || (in->digest == NULL)) { + EVPerr(EVP_F_EVP_MD_CTX_COPY_EX, EVP_R_INPUT_NOT_INITIALIZED); + return 0; + } +#ifndef OPENSSL_NO_ENGINE + /* Make sure it's safe to copy a digest context using an ENGINE */ + if (in->engine && !ENGINE_init(in->engine)) { + EVPerr(EVP_F_EVP_MD_CTX_COPY_EX, ERR_R_ENGINE_LIB); + return 0; + } +#endif + + if (out->digest == in->digest) { + tmp_buf = out->md_data; + EVP_MD_CTX_set_flags(out, EVP_MD_CTX_FLAG_REUSE); + } else + tmp_buf = NULL; + EVP_MD_CTX_reset(out); + memcpy(out, in, sizeof(*out)); + + /* copied EVP_MD_CTX should free the copied EVP_PKEY_CTX */ + EVP_MD_CTX_clear_flags(out, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX); + + /* Null these variables, since they are getting fixed up + * properly below. Anything else may cause a memleak and/or + * double free if any of the memory allocations below fail + */ + out->md_data = NULL; + out->pctx = NULL; + + if (in->md_data && out->digest->ctx_size) { + if (tmp_buf) + out->md_data = tmp_buf; + else { + out->md_data = OPENSSL_malloc(out->digest->ctx_size); + if (out->md_data == NULL) { + EVPerr(EVP_F_EVP_MD_CTX_COPY_EX, ERR_R_MALLOC_FAILURE); + return 0; + } + } + memcpy(out->md_data, in->md_data, out->digest->ctx_size); + } + + out->update = in->update; + + if (in->pctx) { + out->pctx = EVP_PKEY_CTX_dup(in->pctx); + if (!out->pctx) { + EVP_MD_CTX_reset(out); + return 0; + } + } + + if (out->digest->copy) + return out->digest->copy(out, in); + + return 1; +} + +int EVP_Digest(const void *data, size_t count, + unsigned char *md, unsigned int *size, const EVP_MD *type, + ENGINE *impl) +{ + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + int ret; + + if (ctx == NULL) + return 0; + EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT); + ret = EVP_DigestInit_ex(ctx, type, impl) + && EVP_DigestUpdate(ctx, data, count) + && EVP_DigestFinal_ex(ctx, md, size); + EVP_MD_CTX_free(ctx); + + return ret; +} + +int EVP_MD_CTX_ctrl(EVP_MD_CTX *ctx, int cmd, int p1, void *p2) +{ + if (ctx->digest && ctx->digest->md_ctrl) { + int ret = ctx->digest->md_ctrl(ctx, cmd, p1, p2); + if (ret <= 0) + return 0; + return 1; + } + return 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_aes.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_aes.c new file mode 100644 index 000000000..39eb4f379 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_aes.c @@ -0,0 +1,4210 @@ +/* + * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include "internal/evp_int.h" +#include "modes_lcl.h" +#include +#include "evp_locl.h" + +typedef struct { + union { + double align; + AES_KEY ks; + } ks; + block128_f block; + union { + cbc128_f cbc; + ctr128_f ctr; + } stream; +} EVP_AES_KEY; + +typedef struct { + union { + double align; + AES_KEY ks; + } ks; /* AES key schedule to use */ + int key_set; /* Set if key initialised */ + int iv_set; /* Set if an iv is set */ + GCM128_CONTEXT gcm; + unsigned char *iv; /* Temporary IV store */ + int ivlen; /* IV length */ + int taglen; + int iv_gen; /* It is OK to generate IVs */ + int tls_aad_len; /* TLS AAD length */ + ctr128_f ctr; +} EVP_AES_GCM_CTX; + +typedef struct { + union { + double align; + AES_KEY ks; + } ks1, ks2; /* AES key schedules to use */ + XTS128_CONTEXT xts; + void (*stream) (const unsigned char *in, + unsigned char *out, size_t length, + const AES_KEY *key1, const AES_KEY *key2, + const unsigned char iv[16]); +} EVP_AES_XTS_CTX; + +typedef struct { + union { + double align; + AES_KEY ks; + } ks; /* AES key schedule to use */ + int key_set; /* Set if key initialised */ + int iv_set; /* Set if an iv is set */ + int tag_set; /* Set if tag is valid */ + int len_set; /* Set if message length set */ + int L, M; /* L and M parameters from RFC3610 */ + int tls_aad_len; /* TLS AAD length */ + CCM128_CONTEXT ccm; + ccm128_f str; +} EVP_AES_CCM_CTX; + +#ifndef OPENSSL_NO_OCB +typedef struct { + union { + double align; + AES_KEY ks; + } ksenc; /* AES key schedule to use for encryption */ + union { + double align; + AES_KEY ks; + } ksdec; /* AES key schedule to use for decryption */ + int key_set; /* Set if key initialised */ + int iv_set; /* Set if an iv is set */ + OCB128_CONTEXT ocb; + unsigned char *iv; /* Temporary IV store */ + unsigned char tag[16]; + unsigned char data_buf[16]; /* Store partial data blocks */ + unsigned char aad_buf[16]; /* Store partial AAD blocks */ + int data_buf_len; + int aad_buf_len; + int ivlen; /* IV length */ + int taglen; +} EVP_AES_OCB_CTX; +#endif + +#define MAXBITCHUNK ((size_t)1<<(sizeof(size_t)*8-4)) + +#ifdef VPAES_ASM +int vpaes_set_encrypt_key(const unsigned char *userKey, int bits, + AES_KEY *key); +int vpaes_set_decrypt_key(const unsigned char *userKey, int bits, + AES_KEY *key); + +void vpaes_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key); +void vpaes_decrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key); + +void vpaes_cbc_encrypt(const unsigned char *in, + unsigned char *out, + size_t length, + const AES_KEY *key, unsigned char *ivec, int enc); +#endif +#ifdef BSAES_ASM +void bsaes_cbc_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char ivec[16], int enc); +void bsaes_ctr32_encrypt_blocks(const unsigned char *in, unsigned char *out, + size_t len, const AES_KEY *key, + const unsigned char ivec[16]); +void bsaes_xts_encrypt(const unsigned char *inp, unsigned char *out, + size_t len, const AES_KEY *key1, + const AES_KEY *key2, const unsigned char iv[16]); +void bsaes_xts_decrypt(const unsigned char *inp, unsigned char *out, + size_t len, const AES_KEY *key1, + const AES_KEY *key2, const unsigned char iv[16]); +#endif +#ifdef AES_CTR_ASM +void AES_ctr32_encrypt(const unsigned char *in, unsigned char *out, + size_t blocks, const AES_KEY *key, + const unsigned char ivec[AES_BLOCK_SIZE]); +#endif +#ifdef AES_XTS_ASM +void AES_xts_encrypt(const unsigned char *inp, unsigned char *out, size_t len, + const AES_KEY *key1, const AES_KEY *key2, + const unsigned char iv[16]); +void AES_xts_decrypt(const unsigned char *inp, unsigned char *out, size_t len, + const AES_KEY *key1, const AES_KEY *key2, + const unsigned char iv[16]); +#endif + +/* increment counter (64-bit int) by 1 */ +static void ctr64_inc(unsigned char *counter) +{ + int n = 8; + unsigned char c; + + do { + --n; + c = counter[n]; + ++c; + counter[n] = c; + if (c) + return; + } while (n); +} + +#if defined(OPENSSL_CPUID_OBJ) && (defined(__powerpc__) || defined(__ppc__) || defined(_ARCH_PPC)) +# include "ppc_arch.h" +# ifdef VPAES_ASM +# define VPAES_CAPABLE (OPENSSL_ppccap_P & PPC_ALTIVEC) +# endif +# define HWAES_CAPABLE (OPENSSL_ppccap_P & PPC_CRYPTO207) +# define HWAES_set_encrypt_key aes_p8_set_encrypt_key +# define HWAES_set_decrypt_key aes_p8_set_decrypt_key +# define HWAES_encrypt aes_p8_encrypt +# define HWAES_decrypt aes_p8_decrypt +# define HWAES_cbc_encrypt aes_p8_cbc_encrypt +# define HWAES_ctr32_encrypt_blocks aes_p8_ctr32_encrypt_blocks +# define HWAES_xts_encrypt aes_p8_xts_encrypt +# define HWAES_xts_decrypt aes_p8_xts_decrypt +#endif + +#if defined(AES_ASM) && !defined(I386_ONLY) && ( \ + ((defined(__i386) || defined(__i386__) || \ + defined(_M_IX86)) && defined(OPENSSL_IA32_SSE2))|| \ + defined(__x86_64) || defined(__x86_64__) || \ + defined(_M_AMD64) || defined(_M_X64) ) + +extern unsigned int OPENSSL_ia32cap_P[]; + +# ifdef VPAES_ASM +# define VPAES_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(41-32))) +# endif +# ifdef BSAES_ASM +# define BSAES_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(41-32))) +# endif +/* + * AES-NI section + */ +# define AESNI_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(57-32))) + +int aesni_set_encrypt_key(const unsigned char *userKey, int bits, + AES_KEY *key); +int aesni_set_decrypt_key(const unsigned char *userKey, int bits, + AES_KEY *key); + +void aesni_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key); +void aesni_decrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key); + +void aesni_ecb_encrypt(const unsigned char *in, + unsigned char *out, + size_t length, const AES_KEY *key, int enc); +void aesni_cbc_encrypt(const unsigned char *in, + unsigned char *out, + size_t length, + const AES_KEY *key, unsigned char *ivec, int enc); + +void aesni_ctr32_encrypt_blocks(const unsigned char *in, + unsigned char *out, + size_t blocks, + const void *key, const unsigned char *ivec); + +void aesni_xts_encrypt(const unsigned char *in, + unsigned char *out, + size_t length, + const AES_KEY *key1, const AES_KEY *key2, + const unsigned char iv[16]); + +void aesni_xts_decrypt(const unsigned char *in, + unsigned char *out, + size_t length, + const AES_KEY *key1, const AES_KEY *key2, + const unsigned char iv[16]); + +void aesni_ccm64_encrypt_blocks(const unsigned char *in, + unsigned char *out, + size_t blocks, + const void *key, + const unsigned char ivec[16], + unsigned char cmac[16]); + +void aesni_ccm64_decrypt_blocks(const unsigned char *in, + unsigned char *out, + size_t blocks, + const void *key, + const unsigned char ivec[16], + unsigned char cmac[16]); + +# if defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64) +size_t aesni_gcm_encrypt(const unsigned char *in, + unsigned char *out, + size_t len, + const void *key, unsigned char ivec[16], u64 *Xi); +# define AES_gcm_encrypt aesni_gcm_encrypt +size_t aesni_gcm_decrypt(const unsigned char *in, + unsigned char *out, + size_t len, + const void *key, unsigned char ivec[16], u64 *Xi); +# define AES_gcm_decrypt aesni_gcm_decrypt +void gcm_ghash_avx(u64 Xi[2], const u128 Htable[16], const u8 *in, + size_t len); +# define AES_GCM_ASM(gctx) (gctx->ctr==aesni_ctr32_encrypt_blocks && \ + gctx->gcm.ghash==gcm_ghash_avx) +# define AES_GCM_ASM2(gctx) (gctx->gcm.block==(block128_f)aesni_encrypt && \ + gctx->gcm.ghash==gcm_ghash_avx) +# undef AES_GCM_ASM2 /* minor size optimization */ +# endif + +static int aesni_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + int ret, mode; + EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx); + + mode = EVP_CIPHER_CTX_mode(ctx); + if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) + && !enc) { + ret = aesni_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, + &dat->ks.ks); + dat->block = (block128_f) aesni_decrypt; + dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? + (cbc128_f) aesni_cbc_encrypt : NULL; + } else { + ret = aesni_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, + &dat->ks.ks); + dat->block = (block128_f) aesni_encrypt; + if (mode == EVP_CIPH_CBC_MODE) + dat->stream.cbc = (cbc128_f) aesni_cbc_encrypt; + else if (mode == EVP_CIPH_CTR_MODE) + dat->stream.ctr = (ctr128_f) aesni_ctr32_encrypt_blocks; + else + dat->stream.cbc = NULL; + } + + if (ret < 0) { + EVPerr(EVP_F_AESNI_INIT_KEY, EVP_R_AES_KEY_SETUP_FAILED); + return 0; + } + + return 1; +} + +static int aesni_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + aesni_cbc_encrypt(in, out, len, &EVP_C_DATA(EVP_AES_KEY,ctx)->ks.ks, + EVP_CIPHER_CTX_iv_noconst(ctx), + EVP_CIPHER_CTX_encrypting(ctx)); + + return 1; +} + +static int aesni_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + size_t bl = EVP_CIPHER_CTX_block_size(ctx); + + if (len < bl) + return 1; + + aesni_ecb_encrypt(in, out, len, &EVP_C_DATA(EVP_AES_KEY,ctx)->ks.ks, + EVP_CIPHER_CTX_encrypting(ctx)); + + return 1; +} + +# define aesni_ofb_cipher aes_ofb_cipher +static int aesni_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +# define aesni_cfb_cipher aes_cfb_cipher +static int aesni_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +# define aesni_cfb8_cipher aes_cfb8_cipher +static int aesni_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +# define aesni_cfb1_cipher aes_cfb1_cipher +static int aesni_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +# define aesni_ctr_cipher aes_ctr_cipher +static int aesni_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +static int aesni_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx); + if (!iv && !key) + return 1; + if (key) { + aesni_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, + &gctx->ks.ks); + CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f) aesni_encrypt); + gctx->ctr = (ctr128_f) aesni_ctr32_encrypt_blocks; + /* + * If we have an iv can set it directly, otherwise use saved IV. + */ + if (iv == NULL && gctx->iv_set) + iv = gctx->iv; + if (iv) { + CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen); + gctx->iv_set = 1; + } + gctx->key_set = 1; + } else { + /* If key set use IV, otherwise copy */ + if (gctx->key_set) + CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen); + else + memcpy(gctx->iv, iv, gctx->ivlen); + gctx->iv_set = 1; + gctx->iv_gen = 0; + } + return 1; +} + +# define aesni_gcm_cipher aes_gcm_cipher +static int aesni_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +static int aesni_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx); + if (!iv && !key) + return 1; + + if (key) { + /* key_len is two AES keys */ + if (enc) { + aesni_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 4, + &xctx->ks1.ks); + xctx->xts.block1 = (block128_f) aesni_encrypt; + xctx->stream = aesni_xts_encrypt; + } else { + aesni_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 4, + &xctx->ks1.ks); + xctx->xts.block1 = (block128_f) aesni_decrypt; + xctx->stream = aesni_xts_decrypt; + } + + aesni_set_encrypt_key(key + EVP_CIPHER_CTX_key_length(ctx) / 2, + EVP_CIPHER_CTX_key_length(ctx) * 4, + &xctx->ks2.ks); + xctx->xts.block2 = (block128_f) aesni_encrypt; + + xctx->xts.key1 = &xctx->ks1; + } + + if (iv) { + xctx->xts.key2 = &xctx->ks2; + memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 16); + } + + return 1; +} + +# define aesni_xts_cipher aes_xts_cipher +static int aesni_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +static int aesni_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx); + if (!iv && !key) + return 1; + if (key) { + aesni_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, + &cctx->ks.ks); + CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L, + &cctx->ks, (block128_f) aesni_encrypt); + cctx->str = enc ? (ccm128_f) aesni_ccm64_encrypt_blocks : + (ccm128_f) aesni_ccm64_decrypt_blocks; + cctx->key_set = 1; + } + if (iv) { + memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 15 - cctx->L); + cctx->iv_set = 1; + } + return 1; +} + +# define aesni_ccm_cipher aes_ccm_cipher +static int aesni_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +# ifndef OPENSSL_NO_OCB +void aesni_ocb_encrypt(const unsigned char *in, unsigned char *out, + size_t blocks, const void *key, + size_t start_block_num, + unsigned char offset_i[16], + const unsigned char L_[][16], + unsigned char checksum[16]); +void aesni_ocb_decrypt(const unsigned char *in, unsigned char *out, + size_t blocks, const void *key, + size_t start_block_num, + unsigned char offset_i[16], + const unsigned char L_[][16], + unsigned char checksum[16]); + +static int aesni_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx); + if (!iv && !key) + return 1; + if (key) { + do { + /* + * We set both the encrypt and decrypt key here because decrypt + * needs both. We could possibly optimise to remove setting the + * decrypt for an encryption operation. + */ + aesni_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, + &octx->ksenc.ks); + aesni_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, + &octx->ksdec.ks); + if (!CRYPTO_ocb128_init(&octx->ocb, + &octx->ksenc.ks, &octx->ksdec.ks, + (block128_f) aesni_encrypt, + (block128_f) aesni_decrypt, + enc ? aesni_ocb_encrypt + : aesni_ocb_decrypt)) + return 0; + } + while (0); + + /* + * If we have an iv we can set it directly, otherwise use saved IV. + */ + if (iv == NULL && octx->iv_set) + iv = octx->iv; + if (iv) { + if (CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen) + != 1) + return 0; + octx->iv_set = 1; + } + octx->key_set = 1; + } else { + /* If key set use IV, otherwise copy */ + if (octx->key_set) + CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen); + else + memcpy(octx->iv, iv, octx->ivlen); + octx->iv_set = 1; + } + return 1; +} + +# define aesni_ocb_cipher aes_ocb_cipher +static int aesni_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); +# endif /* OPENSSL_NO_OCB */ + +# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \ +static const EVP_CIPHER aesni_##keylen##_##mode = { \ + nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \ + flags|EVP_CIPH_##MODE##_MODE, \ + aesni_init_key, \ + aesni_##mode##_cipher, \ + NULL, \ + sizeof(EVP_AES_KEY), \ + NULL,NULL,NULL,NULL }; \ +static const EVP_CIPHER aes_##keylen##_##mode = { \ + nid##_##keylen##_##nmode,blocksize, \ + keylen/8,ivlen, \ + flags|EVP_CIPH_##MODE##_MODE, \ + aes_init_key, \ + aes_##mode##_cipher, \ + NULL, \ + sizeof(EVP_AES_KEY), \ + NULL,NULL,NULL,NULL }; \ +const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \ +{ return AESNI_CAPABLE?&aesni_##keylen##_##mode:&aes_##keylen##_##mode; } + +# define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \ +static const EVP_CIPHER aesni_##keylen##_##mode = { \ + nid##_##keylen##_##mode,blocksize, \ + (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \ + flags|EVP_CIPH_##MODE##_MODE, \ + aesni_##mode##_init_key, \ + aesni_##mode##_cipher, \ + aes_##mode##_cleanup, \ + sizeof(EVP_AES_##MODE##_CTX), \ + NULL,NULL,aes_##mode##_ctrl,NULL }; \ +static const EVP_CIPHER aes_##keylen##_##mode = { \ + nid##_##keylen##_##mode,blocksize, \ + (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \ + flags|EVP_CIPH_##MODE##_MODE, \ + aes_##mode##_init_key, \ + aes_##mode##_cipher, \ + aes_##mode##_cleanup, \ + sizeof(EVP_AES_##MODE##_CTX), \ + NULL,NULL,aes_##mode##_ctrl,NULL }; \ +const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \ +{ return AESNI_CAPABLE?&aesni_##keylen##_##mode:&aes_##keylen##_##mode; } + +#elif defined(AES_ASM) && (defined(__sparc) || defined(__sparc__)) + +# include "sparc_arch.h" + +extern unsigned int OPENSSL_sparcv9cap_P[]; + +/* + * Initial Fujitsu SPARC64 X support + */ +# define HWAES_CAPABLE (OPENSSL_sparcv9cap_P[0] & SPARCV9_FJAESX) +# define HWAES_set_encrypt_key aes_fx_set_encrypt_key +# define HWAES_set_decrypt_key aes_fx_set_decrypt_key +# define HWAES_encrypt aes_fx_encrypt +# define HWAES_decrypt aes_fx_decrypt +# define HWAES_cbc_encrypt aes_fx_cbc_encrypt +# define HWAES_ctr32_encrypt_blocks aes_fx_ctr32_encrypt_blocks + +# define SPARC_AES_CAPABLE (OPENSSL_sparcv9cap_P[1] & CFR_AES) + +void aes_t4_set_encrypt_key(const unsigned char *key, int bits, AES_KEY *ks); +void aes_t4_set_decrypt_key(const unsigned char *key, int bits, AES_KEY *ks); +void aes_t4_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key); +void aes_t4_decrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key); +/* + * Key-length specific subroutines were chosen for following reason. + * Each SPARC T4 core can execute up to 8 threads which share core's + * resources. Loading as much key material to registers allows to + * minimize references to shared memory interface, as well as amount + * of instructions in inner loops [much needed on T4]. But then having + * non-key-length specific routines would require conditional branches + * either in inner loops or on subroutines' entries. Former is hardly + * acceptable, while latter means code size increase to size occupied + * by multiple key-length specific subroutines, so why fight? + */ +void aes128_t4_cbc_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const AES_KEY *key, + unsigned char *ivec); +void aes128_t4_cbc_decrypt(const unsigned char *in, unsigned char *out, + size_t len, const AES_KEY *key, + unsigned char *ivec); +void aes192_t4_cbc_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const AES_KEY *key, + unsigned char *ivec); +void aes192_t4_cbc_decrypt(const unsigned char *in, unsigned char *out, + size_t len, const AES_KEY *key, + unsigned char *ivec); +void aes256_t4_cbc_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const AES_KEY *key, + unsigned char *ivec); +void aes256_t4_cbc_decrypt(const unsigned char *in, unsigned char *out, + size_t len, const AES_KEY *key, + unsigned char *ivec); +void aes128_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out, + size_t blocks, const AES_KEY *key, + unsigned char *ivec); +void aes192_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out, + size_t blocks, const AES_KEY *key, + unsigned char *ivec); +void aes256_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out, + size_t blocks, const AES_KEY *key, + unsigned char *ivec); +void aes128_t4_xts_encrypt(const unsigned char *in, unsigned char *out, + size_t blocks, const AES_KEY *key1, + const AES_KEY *key2, const unsigned char *ivec); +void aes128_t4_xts_decrypt(const unsigned char *in, unsigned char *out, + size_t blocks, const AES_KEY *key1, + const AES_KEY *key2, const unsigned char *ivec); +void aes256_t4_xts_encrypt(const unsigned char *in, unsigned char *out, + size_t blocks, const AES_KEY *key1, + const AES_KEY *key2, const unsigned char *ivec); +void aes256_t4_xts_decrypt(const unsigned char *in, unsigned char *out, + size_t blocks, const AES_KEY *key1, + const AES_KEY *key2, const unsigned char *ivec); + +static int aes_t4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + int ret, mode, bits; + EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx); + + mode = EVP_CIPHER_CTX_mode(ctx); + bits = EVP_CIPHER_CTX_key_length(ctx) * 8; + if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) + && !enc) { + ret = 0; + aes_t4_set_decrypt_key(key, bits, &dat->ks.ks); + dat->block = (block128_f) aes_t4_decrypt; + switch (bits) { + case 128: + dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? + (cbc128_f) aes128_t4_cbc_decrypt : NULL; + break; + case 192: + dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? + (cbc128_f) aes192_t4_cbc_decrypt : NULL; + break; + case 256: + dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? + (cbc128_f) aes256_t4_cbc_decrypt : NULL; + break; + default: + ret = -1; + } + } else { + ret = 0; + aes_t4_set_encrypt_key(key, bits, &dat->ks.ks); + dat->block = (block128_f) aes_t4_encrypt; + switch (bits) { + case 128: + if (mode == EVP_CIPH_CBC_MODE) + dat->stream.cbc = (cbc128_f) aes128_t4_cbc_encrypt; + else if (mode == EVP_CIPH_CTR_MODE) + dat->stream.ctr = (ctr128_f) aes128_t4_ctr32_encrypt; + else + dat->stream.cbc = NULL; + break; + case 192: + if (mode == EVP_CIPH_CBC_MODE) + dat->stream.cbc = (cbc128_f) aes192_t4_cbc_encrypt; + else if (mode == EVP_CIPH_CTR_MODE) + dat->stream.ctr = (ctr128_f) aes192_t4_ctr32_encrypt; + else + dat->stream.cbc = NULL; + break; + case 256: + if (mode == EVP_CIPH_CBC_MODE) + dat->stream.cbc = (cbc128_f) aes256_t4_cbc_encrypt; + else if (mode == EVP_CIPH_CTR_MODE) + dat->stream.ctr = (ctr128_f) aes256_t4_ctr32_encrypt; + else + dat->stream.cbc = NULL; + break; + default: + ret = -1; + } + } + + if (ret < 0) { + EVPerr(EVP_F_AES_T4_INIT_KEY, EVP_R_AES_KEY_SETUP_FAILED); + return 0; + } + + return 1; +} + +# define aes_t4_cbc_cipher aes_cbc_cipher +static int aes_t4_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +# define aes_t4_ecb_cipher aes_ecb_cipher +static int aes_t4_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +# define aes_t4_ofb_cipher aes_ofb_cipher +static int aes_t4_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +# define aes_t4_cfb_cipher aes_cfb_cipher +static int aes_t4_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +# define aes_t4_cfb8_cipher aes_cfb8_cipher +static int aes_t4_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +# define aes_t4_cfb1_cipher aes_cfb1_cipher +static int aes_t4_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +# define aes_t4_ctr_cipher aes_ctr_cipher +static int aes_t4_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +static int aes_t4_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx); + if (!iv && !key) + return 1; + if (key) { + int bits = EVP_CIPHER_CTX_key_length(ctx) * 8; + aes_t4_set_encrypt_key(key, bits, &gctx->ks.ks); + CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, + (block128_f) aes_t4_encrypt); + switch (bits) { + case 128: + gctx->ctr = (ctr128_f) aes128_t4_ctr32_encrypt; + break; + case 192: + gctx->ctr = (ctr128_f) aes192_t4_ctr32_encrypt; + break; + case 256: + gctx->ctr = (ctr128_f) aes256_t4_ctr32_encrypt; + break; + default: + return 0; + } + /* + * If we have an iv can set it directly, otherwise use saved IV. + */ + if (iv == NULL && gctx->iv_set) + iv = gctx->iv; + if (iv) { + CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen); + gctx->iv_set = 1; + } + gctx->key_set = 1; + } else { + /* If key set use IV, otherwise copy */ + if (gctx->key_set) + CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen); + else + memcpy(gctx->iv, iv, gctx->ivlen); + gctx->iv_set = 1; + gctx->iv_gen = 0; + } + return 1; +} + +# define aes_t4_gcm_cipher aes_gcm_cipher +static int aes_t4_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +static int aes_t4_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx); + if (!iv && !key) + return 1; + + if (key) { + int bits = EVP_CIPHER_CTX_key_length(ctx) * 4; + xctx->stream = NULL; + /* key_len is two AES keys */ + if (enc) { + aes_t4_set_encrypt_key(key, bits, &xctx->ks1.ks); + xctx->xts.block1 = (block128_f) aes_t4_encrypt; + switch (bits) { + case 128: + xctx->stream = aes128_t4_xts_encrypt; + break; + case 256: + xctx->stream = aes256_t4_xts_encrypt; + break; + default: + return 0; + } + } else { + aes_t4_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 4, + &xctx->ks1.ks); + xctx->xts.block1 = (block128_f) aes_t4_decrypt; + switch (bits) { + case 128: + xctx->stream = aes128_t4_xts_decrypt; + break; + case 256: + xctx->stream = aes256_t4_xts_decrypt; + break; + default: + return 0; + } + } + + aes_t4_set_encrypt_key(key + EVP_CIPHER_CTX_key_length(ctx) / 2, + EVP_CIPHER_CTX_key_length(ctx) * 4, + &xctx->ks2.ks); + xctx->xts.block2 = (block128_f) aes_t4_encrypt; + + xctx->xts.key1 = &xctx->ks1; + } + + if (iv) { + xctx->xts.key2 = &xctx->ks2; + memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 16); + } + + return 1; +} + +# define aes_t4_xts_cipher aes_xts_cipher +static int aes_t4_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +static int aes_t4_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx); + if (!iv && !key) + return 1; + if (key) { + int bits = EVP_CIPHER_CTX_key_length(ctx) * 8; + aes_t4_set_encrypt_key(key, bits, &cctx->ks.ks); + CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L, + &cctx->ks, (block128_f) aes_t4_encrypt); + cctx->str = NULL; + cctx->key_set = 1; + } + if (iv) { + memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 15 - cctx->L); + cctx->iv_set = 1; + } + return 1; +} + +# define aes_t4_ccm_cipher aes_ccm_cipher +static int aes_t4_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +# ifndef OPENSSL_NO_OCB +static int aes_t4_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx); + if (!iv && !key) + return 1; + if (key) { + do { + /* + * We set both the encrypt and decrypt key here because decrypt + * needs both. We could possibly optimise to remove setting the + * decrypt for an encryption operation. + */ + aes_t4_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, + &octx->ksenc.ks); + aes_t4_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, + &octx->ksdec.ks); + if (!CRYPTO_ocb128_init(&octx->ocb, + &octx->ksenc.ks, &octx->ksdec.ks, + (block128_f) aes_t4_encrypt, + (block128_f) aes_t4_decrypt, + NULL)) + return 0; + } + while (0); + + /* + * If we have an iv we can set it directly, otherwise use saved IV. + */ + if (iv == NULL && octx->iv_set) + iv = octx->iv; + if (iv) { + if (CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen) + != 1) + return 0; + octx->iv_set = 1; + } + octx->key_set = 1; + } else { + /* If key set use IV, otherwise copy */ + if (octx->key_set) + CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen); + else + memcpy(octx->iv, iv, octx->ivlen); + octx->iv_set = 1; + } + return 1; +} + +# define aes_t4_ocb_cipher aes_ocb_cipher +static int aes_t4_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); +# endif /* OPENSSL_NO_OCB */ + +# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \ +static const EVP_CIPHER aes_t4_##keylen##_##mode = { \ + nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \ + flags|EVP_CIPH_##MODE##_MODE, \ + aes_t4_init_key, \ + aes_t4_##mode##_cipher, \ + NULL, \ + sizeof(EVP_AES_KEY), \ + NULL,NULL,NULL,NULL }; \ +static const EVP_CIPHER aes_##keylen##_##mode = { \ + nid##_##keylen##_##nmode,blocksize, \ + keylen/8,ivlen, \ + flags|EVP_CIPH_##MODE##_MODE, \ + aes_init_key, \ + aes_##mode##_cipher, \ + NULL, \ + sizeof(EVP_AES_KEY), \ + NULL,NULL,NULL,NULL }; \ +const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \ +{ return SPARC_AES_CAPABLE?&aes_t4_##keylen##_##mode:&aes_##keylen##_##mode; } + +# define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \ +static const EVP_CIPHER aes_t4_##keylen##_##mode = { \ + nid##_##keylen##_##mode,blocksize, \ + (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \ + flags|EVP_CIPH_##MODE##_MODE, \ + aes_t4_##mode##_init_key, \ + aes_t4_##mode##_cipher, \ + aes_##mode##_cleanup, \ + sizeof(EVP_AES_##MODE##_CTX), \ + NULL,NULL,aes_##mode##_ctrl,NULL }; \ +static const EVP_CIPHER aes_##keylen##_##mode = { \ + nid##_##keylen##_##mode,blocksize, \ + (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \ + flags|EVP_CIPH_##MODE##_MODE, \ + aes_##mode##_init_key, \ + aes_##mode##_cipher, \ + aes_##mode##_cleanup, \ + sizeof(EVP_AES_##MODE##_CTX), \ + NULL,NULL,aes_##mode##_ctrl,NULL }; \ +const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \ +{ return SPARC_AES_CAPABLE?&aes_t4_##keylen##_##mode:&aes_##keylen##_##mode; } + +#elif defined(OPENSSL_CPUID_OBJ) && defined(__s390__) +/* + * IBM S390X support + */ +# include "s390x_arch.h" + +typedef struct { + union { + double align; + /*- + * KM-AES parameter block - begin + * (see z/Architecture Principles of Operation >= SA22-7832-06) + */ + struct { + unsigned char k[32]; + } param; + /* KM-AES parameter block - end */ + } km; + unsigned int fc; +} S390X_AES_ECB_CTX; + +typedef struct { + union { + double align; + /*- + * KMO-AES parameter block - begin + * (see z/Architecture Principles of Operation >= SA22-7832-08) + */ + struct { + unsigned char cv[16]; + unsigned char k[32]; + } param; + /* KMO-AES parameter block - end */ + } kmo; + unsigned int fc; + + int res; +} S390X_AES_OFB_CTX; + +typedef struct { + union { + double align; + /*- + * KMF-AES parameter block - begin + * (see z/Architecture Principles of Operation >= SA22-7832-08) + */ + struct { + unsigned char cv[16]; + unsigned char k[32]; + } param; + /* KMF-AES parameter block - end */ + } kmf; + unsigned int fc; + + int res; +} S390X_AES_CFB_CTX; + +typedef struct { + union { + double align; + /*- + * KMA-GCM-AES parameter block - begin + * (see z/Architecture Principles of Operation >= SA22-7832-11) + */ + struct { + unsigned char reserved[12]; + union { + unsigned int w; + unsigned char b[4]; + } cv; + union { + unsigned long long g[2]; + unsigned char b[16]; + } t; + unsigned char h[16]; + unsigned long long taadl; + unsigned long long tpcl; + union { + unsigned long long g[2]; + unsigned int w[4]; + } j0; + unsigned char k[32]; + } param; + /* KMA-GCM-AES parameter block - end */ + } kma; + unsigned int fc; + int key_set; + + unsigned char *iv; + int ivlen; + int iv_set; + int iv_gen; + + int taglen; + + unsigned char ares[16]; + unsigned char mres[16]; + unsigned char kres[16]; + int areslen; + int mreslen; + int kreslen; + + int tls_aad_len; +} S390X_AES_GCM_CTX; + +typedef struct { + union { + double align; + /*- + * Padding is chosen so that ccm.kmac_param.k overlaps with key.k and + * ccm.fc with key.k.rounds. Remember that on s390x, an AES_KEY's + * rounds field is used to store the function code and that the key + * schedule is not stored (if aes hardware support is detected). + */ + struct { + unsigned char pad[16]; + AES_KEY k; + } key; + + struct { + /*- + * KMAC-AES parameter block - begin + * (see z/Architecture Principles of Operation >= SA22-7832-08) + */ + struct { + union { + unsigned long long g[2]; + unsigned char b[16]; + } icv; + unsigned char k[32]; + } kmac_param; + /* KMAC-AES paramater block - end */ + + union { + unsigned long long g[2]; + unsigned char b[16]; + } nonce; + union { + unsigned long long g[2]; + unsigned char b[16]; + } buf; + + unsigned long long blocks; + int l; + int m; + int tls_aad_len; + int iv_set; + int tag_set; + int len_set; + int key_set; + + unsigned char pad[140]; + unsigned int fc; + } ccm; + } aes; +} S390X_AES_CCM_CTX; + +/* Convert key size to function code: [16,24,32] -> [18,19,20]. */ +# define S390X_AES_FC(keylen) (S390X_AES_128 + ((((keylen) << 3) - 128) >> 6)) + +/* Most modes of operation need km for partial block processing. */ +# define S390X_aes_128_CAPABLE (OPENSSL_s390xcap_P.km[0] & \ + S390X_CAPBIT(S390X_AES_128)) +# define S390X_aes_192_CAPABLE (OPENSSL_s390xcap_P.km[0] & \ + S390X_CAPBIT(S390X_AES_192)) +# define S390X_aes_256_CAPABLE (OPENSSL_s390xcap_P.km[0] & \ + S390X_CAPBIT(S390X_AES_256)) + +# define s390x_aes_init_key aes_init_key +static int s390x_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); + +# define S390X_aes_128_cbc_CAPABLE 1 /* checked by callee */ +# define S390X_aes_192_cbc_CAPABLE 1 +# define S390X_aes_256_cbc_CAPABLE 1 +# define S390X_AES_CBC_CTX EVP_AES_KEY + +# define s390x_aes_cbc_init_key aes_init_key + +# define s390x_aes_cbc_cipher aes_cbc_cipher +static int s390x_aes_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +# define S390X_aes_128_ecb_CAPABLE S390X_aes_128_CAPABLE +# define S390X_aes_192_ecb_CAPABLE S390X_aes_192_CAPABLE +# define S390X_aes_256_ecb_CAPABLE S390X_aes_256_CAPABLE + +static int s390x_aes_ecb_init_key(EVP_CIPHER_CTX *ctx, + const unsigned char *key, + const unsigned char *iv, int enc) +{ + S390X_AES_ECB_CTX *cctx = EVP_C_DATA(S390X_AES_ECB_CTX, ctx); + const int keylen = EVP_CIPHER_CTX_key_length(ctx); + + cctx->fc = S390X_AES_FC(keylen); + if (!enc) + cctx->fc |= S390X_DECRYPT; + + memcpy(cctx->km.param.k, key, keylen); + return 1; +} + +static int s390x_aes_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + S390X_AES_ECB_CTX *cctx = EVP_C_DATA(S390X_AES_ECB_CTX, ctx); + + s390x_km(in, len, out, cctx->fc, &cctx->km.param); + return 1; +} + +# define S390X_aes_128_ofb_CAPABLE (S390X_aes_128_CAPABLE && \ + (OPENSSL_s390xcap_P.kmo[0] & \ + S390X_CAPBIT(S390X_AES_128))) +# define S390X_aes_192_ofb_CAPABLE (S390X_aes_192_CAPABLE && \ + (OPENSSL_s390xcap_P.kmo[0] & \ + S390X_CAPBIT(S390X_AES_192))) +# define S390X_aes_256_ofb_CAPABLE (S390X_aes_256_CAPABLE && \ + (OPENSSL_s390xcap_P.kmo[0] & \ + S390X_CAPBIT(S390X_AES_256))) + +static int s390x_aes_ofb_init_key(EVP_CIPHER_CTX *ctx, + const unsigned char *key, + const unsigned char *ivec, int enc) +{ + S390X_AES_OFB_CTX *cctx = EVP_C_DATA(S390X_AES_OFB_CTX, ctx); + const unsigned char *iv = EVP_CIPHER_CTX_original_iv(ctx); + const int keylen = EVP_CIPHER_CTX_key_length(ctx); + const int ivlen = EVP_CIPHER_CTX_iv_length(ctx); + + memcpy(cctx->kmo.param.cv, iv, ivlen); + memcpy(cctx->kmo.param.k, key, keylen); + cctx->fc = S390X_AES_FC(keylen); + cctx->res = 0; + return 1; +} + +static int s390x_aes_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + S390X_AES_OFB_CTX *cctx = EVP_C_DATA(S390X_AES_OFB_CTX, ctx); + int n = cctx->res; + int rem; + + while (n && len) { + *out = *in ^ cctx->kmo.param.cv[n]; + n = (n + 1) & 0xf; + --len; + ++in; + ++out; + } + + rem = len & 0xf; + + len &= ~(size_t)0xf; + if (len) { + s390x_kmo(in, len, out, cctx->fc, &cctx->kmo.param); + + out += len; + in += len; + } + + if (rem) { + s390x_km(cctx->kmo.param.cv, 16, cctx->kmo.param.cv, cctx->fc, + cctx->kmo.param.k); + + while (rem--) { + out[n] = in[n] ^ cctx->kmo.param.cv[n]; + ++n; + } + } + + cctx->res = n; + return 1; +} + +# define S390X_aes_128_cfb_CAPABLE (S390X_aes_128_CAPABLE && \ + (OPENSSL_s390xcap_P.kmf[0] & \ + S390X_CAPBIT(S390X_AES_128))) +# define S390X_aes_192_cfb_CAPABLE (S390X_aes_192_CAPABLE && \ + (OPENSSL_s390xcap_P.kmf[0] & \ + S390X_CAPBIT(S390X_AES_192))) +# define S390X_aes_256_cfb_CAPABLE (S390X_aes_256_CAPABLE && \ + (OPENSSL_s390xcap_P.kmf[0] & \ + S390X_CAPBIT(S390X_AES_256))) + +static int s390x_aes_cfb_init_key(EVP_CIPHER_CTX *ctx, + const unsigned char *key, + const unsigned char *ivec, int enc) +{ + S390X_AES_CFB_CTX *cctx = EVP_C_DATA(S390X_AES_CFB_CTX, ctx); + const unsigned char *iv = EVP_CIPHER_CTX_original_iv(ctx); + const int keylen = EVP_CIPHER_CTX_key_length(ctx); + const int ivlen = EVP_CIPHER_CTX_iv_length(ctx); + + cctx->fc = S390X_AES_FC(keylen); + cctx->fc |= 16 << 24; /* 16 bytes cipher feedback */ + if (!enc) + cctx->fc |= S390X_DECRYPT; + + cctx->res = 0; + memcpy(cctx->kmf.param.cv, iv, ivlen); + memcpy(cctx->kmf.param.k, key, keylen); + return 1; +} + +static int s390x_aes_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + S390X_AES_CFB_CTX *cctx = EVP_C_DATA(S390X_AES_CFB_CTX, ctx); + const int keylen = EVP_CIPHER_CTX_key_length(ctx); + const int enc = EVP_CIPHER_CTX_encrypting(ctx); + int n = cctx->res; + int rem; + unsigned char tmp; + + while (n && len) { + tmp = *in; + *out = cctx->kmf.param.cv[n] ^ tmp; + cctx->kmf.param.cv[n] = enc ? *out : tmp; + n = (n + 1) & 0xf; + --len; + ++in; + ++out; + } + + rem = len & 0xf; + + len &= ~(size_t)0xf; + if (len) { + s390x_kmf(in, len, out, cctx->fc, &cctx->kmf.param); + + out += len; + in += len; + } + + if (rem) { + s390x_km(cctx->kmf.param.cv, 16, cctx->kmf.param.cv, + S390X_AES_FC(keylen), cctx->kmf.param.k); + + while (rem--) { + tmp = in[n]; + out[n] = cctx->kmf.param.cv[n] ^ tmp; + cctx->kmf.param.cv[n] = enc ? out[n] : tmp; + ++n; + } + } + + cctx->res = n; + return 1; +} + +# define S390X_aes_128_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] & \ + S390X_CAPBIT(S390X_AES_128)) +# define S390X_aes_192_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] & \ + S390X_CAPBIT(S390X_AES_192)) +# define S390X_aes_256_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] & \ + S390X_CAPBIT(S390X_AES_256)) + +static int s390x_aes_cfb8_init_key(EVP_CIPHER_CTX *ctx, + const unsigned char *key, + const unsigned char *ivec, int enc) +{ + S390X_AES_CFB_CTX *cctx = EVP_C_DATA(S390X_AES_CFB_CTX, ctx); + const unsigned char *iv = EVP_CIPHER_CTX_original_iv(ctx); + const int keylen = EVP_CIPHER_CTX_key_length(ctx); + const int ivlen = EVP_CIPHER_CTX_iv_length(ctx); + + cctx->fc = S390X_AES_FC(keylen); + cctx->fc |= 1 << 24; /* 1 byte cipher feedback */ + if (!enc) + cctx->fc |= S390X_DECRYPT; + + memcpy(cctx->kmf.param.cv, iv, ivlen); + memcpy(cctx->kmf.param.k, key, keylen); + return 1; +} + +static int s390x_aes_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + S390X_AES_CFB_CTX *cctx = EVP_C_DATA(S390X_AES_CFB_CTX, ctx); + + s390x_kmf(in, len, out, cctx->fc, &cctx->kmf.param); + return 1; +} + +# define S390X_aes_128_cfb1_CAPABLE 0 +# define S390X_aes_192_cfb1_CAPABLE 0 +# define S390X_aes_256_cfb1_CAPABLE 0 + +# define s390x_aes_cfb1_init_key aes_init_key + +# define s390x_aes_cfb1_cipher aes_cfb1_cipher +static int s390x_aes_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +# define S390X_aes_128_ctr_CAPABLE 1 /* checked by callee */ +# define S390X_aes_192_ctr_CAPABLE 1 +# define S390X_aes_256_ctr_CAPABLE 1 +# define S390X_AES_CTR_CTX EVP_AES_KEY + +# define s390x_aes_ctr_init_key aes_init_key + +# define s390x_aes_ctr_cipher aes_ctr_cipher +static int s390x_aes_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +# define S390X_aes_128_gcm_CAPABLE (S390X_aes_128_CAPABLE && \ + (OPENSSL_s390xcap_P.kma[0] & \ + S390X_CAPBIT(S390X_AES_128))) +# define S390X_aes_192_gcm_CAPABLE (S390X_aes_192_CAPABLE && \ + (OPENSSL_s390xcap_P.kma[0] & \ + S390X_CAPBIT(S390X_AES_192))) +# define S390X_aes_256_gcm_CAPABLE (S390X_aes_256_CAPABLE && \ + (OPENSSL_s390xcap_P.kma[0] & \ + S390X_CAPBIT(S390X_AES_256))) + +/* iv + padding length for iv lenghts != 12 */ +# define S390X_gcm_ivpadlen(i) ((((i) + 15) >> 4 << 4) + 16) + +/*- + * Process additional authenticated data. Returns 0 on success. Code is + * big-endian. + */ +static int s390x_aes_gcm_aad(S390X_AES_GCM_CTX *ctx, const unsigned char *aad, + size_t len) +{ + unsigned long long alen; + int n, rem; + + if (ctx->kma.param.tpcl) + return -2; + + alen = ctx->kma.param.taadl + len; + if (alen > (U64(1) << 61) || (sizeof(len) == 8 && alen < len)) + return -1; + ctx->kma.param.taadl = alen; + + n = ctx->areslen; + if (n) { + while (n && len) { + ctx->ares[n] = *aad; + n = (n + 1) & 0xf; + ++aad; + --len; + } + /* ctx->ares contains a complete block if offset has wrapped around */ + if (!n) { + s390x_kma(ctx->ares, 16, NULL, 0, NULL, ctx->fc, &ctx->kma.param); + ctx->fc |= S390X_KMA_HS; + } + ctx->areslen = n; + } + + rem = len & 0xf; + + len &= ~(size_t)0xf; + if (len) { + s390x_kma(aad, len, NULL, 0, NULL, ctx->fc, &ctx->kma.param); + aad += len; + ctx->fc |= S390X_KMA_HS; + } + + if (rem) { + ctx->areslen = rem; + + do { + --rem; + ctx->ares[rem] = aad[rem]; + } while (rem); + } + return 0; +} + +/*- + * En/de-crypt plain/cipher-text and authenticate ciphertext. Returns 0 for + * success. Code is big-endian. + */ +static int s390x_aes_gcm(S390X_AES_GCM_CTX *ctx, const unsigned char *in, + unsigned char *out, size_t len) +{ + const unsigned char *inptr; + unsigned long long mlen; + union { + unsigned int w[4]; + unsigned char b[16]; + } buf; + size_t inlen; + int n, rem, i; + + mlen = ctx->kma.param.tpcl + len; + if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len)) + return -1; + ctx->kma.param.tpcl = mlen; + + n = ctx->mreslen; + if (n) { + inptr = in; + inlen = len; + while (n && inlen) { + ctx->mres[n] = *inptr; + n = (n + 1) & 0xf; + ++inptr; + --inlen; + } + /* ctx->mres contains a complete block if offset has wrapped around */ + if (!n) { + s390x_kma(ctx->ares, ctx->areslen, ctx->mres, 16, buf.b, + ctx->fc | S390X_KMA_LAAD, &ctx->kma.param); + ctx->fc |= S390X_KMA_HS; + ctx->areslen = 0; + + /* previous call already encrypted/decrypted its remainder, + * see comment below */ + n = ctx->mreslen; + while (n) { + *out = buf.b[n]; + n = (n + 1) & 0xf; + ++out; + ++in; + --len; + } + ctx->mreslen = 0; + } + } + + rem = len & 0xf; + + len &= ~(size_t)0xf; + if (len) { + s390x_kma(ctx->ares, ctx->areslen, in, len, out, + ctx->fc | S390X_KMA_LAAD, &ctx->kma.param); + in += len; + out += len; + ctx->fc |= S390X_KMA_HS; + ctx->areslen = 0; + } + + /*- + * If there is a remainder, it has to be saved such that it can be + * processed by kma later. However, we also have to do the for-now + * unauthenticated encryption/decryption part here and now... + */ + if (rem) { + if (!ctx->mreslen) { + buf.w[0] = ctx->kma.param.j0.w[0]; + buf.w[1] = ctx->kma.param.j0.w[1]; + buf.w[2] = ctx->kma.param.j0.w[2]; + buf.w[3] = ctx->kma.param.cv.w + 1; + s390x_km(buf.b, 16, ctx->kres, ctx->fc & 0x1f, &ctx->kma.param.k); + } + + n = ctx->mreslen; + for (i = 0; i < rem; i++) { + ctx->mres[n + i] = in[i]; + out[i] = in[i] ^ ctx->kres[n + i]; + } + + ctx->mreslen += rem; + } + return 0; +} + +/*- + * Initialize context structure. Code is big-endian. + */ +static void s390x_aes_gcm_setiv(S390X_AES_GCM_CTX *ctx, + const unsigned char *iv) +{ + ctx->kma.param.t.g[0] = 0; + ctx->kma.param.t.g[1] = 0; + ctx->kma.param.tpcl = 0; + ctx->kma.param.taadl = 0; + ctx->mreslen = 0; + ctx->areslen = 0; + ctx->kreslen = 0; + + if (ctx->ivlen == 12) { + memcpy(&ctx->kma.param.j0, iv, ctx->ivlen); + ctx->kma.param.j0.w[3] = 1; + ctx->kma.param.cv.w = 1; + } else { + /* ctx->iv has the right size and is already padded. */ + memcpy(ctx->iv, iv, ctx->ivlen); + s390x_kma(ctx->iv, S390X_gcm_ivpadlen(ctx->ivlen), NULL, 0, NULL, + ctx->fc, &ctx->kma.param); + ctx->fc |= S390X_KMA_HS; + + ctx->kma.param.j0.g[0] = ctx->kma.param.t.g[0]; + ctx->kma.param.j0.g[1] = ctx->kma.param.t.g[1]; + ctx->kma.param.cv.w = ctx->kma.param.j0.w[3]; + ctx->kma.param.t.g[0] = 0; + ctx->kma.param.t.g[1] = 0; + } +} + +/*- + * Performs various operations on the context structure depending on control + * type. Returns 1 for success, 0 for failure and -1 for unknown control type. + * Code is big-endian. + */ +static int s390x_aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) +{ + S390X_AES_GCM_CTX *gctx = EVP_C_DATA(S390X_AES_GCM_CTX, c); + S390X_AES_GCM_CTX *gctx_out; + EVP_CIPHER_CTX *out; + unsigned char *buf, *iv; + int ivlen, enc, len; + + switch (type) { + case EVP_CTRL_INIT: + ivlen = EVP_CIPHER_CTX_iv_length(c); + iv = EVP_CIPHER_CTX_iv_noconst(c); + gctx->key_set = 0; + gctx->iv_set = 0; + gctx->ivlen = ivlen; + gctx->iv = iv; + gctx->taglen = -1; + gctx->iv_gen = 0; + gctx->tls_aad_len = -1; + return 1; + + case EVP_CTRL_AEAD_SET_IVLEN: + if (arg <= 0) + return 0; + + if (arg != 12) { + iv = EVP_CIPHER_CTX_iv_noconst(c); + len = S390X_gcm_ivpadlen(arg); + + /* Allocate memory for iv if needed. */ + if (gctx->ivlen == 12 || len > S390X_gcm_ivpadlen(gctx->ivlen)) { + if (gctx->iv != iv) + OPENSSL_free(gctx->iv); + + if ((gctx->iv = OPENSSL_malloc(len)) == NULL) { + EVPerr(EVP_F_S390X_AES_GCM_CTRL, ERR_R_MALLOC_FAILURE); + return 0; + } + } + /* Add padding. */ + memset(gctx->iv + arg, 0, len - arg - 8); + *((unsigned long long *)(gctx->iv + len - 8)) = arg << 3; + } + gctx->ivlen = arg; + return 1; + + case EVP_CTRL_AEAD_SET_TAG: + buf = EVP_CIPHER_CTX_buf_noconst(c); + enc = EVP_CIPHER_CTX_encrypting(c); + if (arg <= 0 || arg > 16 || enc) + return 0; + + memcpy(buf, ptr, arg); + gctx->taglen = arg; + return 1; + + case EVP_CTRL_AEAD_GET_TAG: + enc = EVP_CIPHER_CTX_encrypting(c); + if (arg <= 0 || arg > 16 || !enc || gctx->taglen < 0) + return 0; + + memcpy(ptr, gctx->kma.param.t.b, arg); + return 1; + + case EVP_CTRL_GCM_SET_IV_FIXED: + /* Special case: -1 length restores whole iv */ + if (arg == -1) { + memcpy(gctx->iv, ptr, gctx->ivlen); + gctx->iv_gen = 1; + return 1; + } + /* + * Fixed field must be at least 4 bytes and invocation field at least + * 8. + */ + if ((arg < 4) || (gctx->ivlen - arg) < 8) + return 0; + + if (arg) + memcpy(gctx->iv, ptr, arg); + + enc = EVP_CIPHER_CTX_encrypting(c); + if (enc && RAND_bytes(gctx->iv + arg, gctx->ivlen - arg) <= 0) + return 0; + + gctx->iv_gen = 1; + return 1; + + case EVP_CTRL_GCM_IV_GEN: + if (gctx->iv_gen == 0 || gctx->key_set == 0) + return 0; + + s390x_aes_gcm_setiv(gctx, gctx->iv); + + if (arg <= 0 || arg > gctx->ivlen) + arg = gctx->ivlen; + + memcpy(ptr, gctx->iv + gctx->ivlen - arg, arg); + /* + * Invocation field will be at least 8 bytes in size and so no need + * to check wrap around or increment more than last 8 bytes. + */ + ctr64_inc(gctx->iv + gctx->ivlen - 8); + gctx->iv_set = 1; + return 1; + + case EVP_CTRL_GCM_SET_IV_INV: + enc = EVP_CIPHER_CTX_encrypting(c); + if (gctx->iv_gen == 0 || gctx->key_set == 0 || enc) + return 0; + + memcpy(gctx->iv + gctx->ivlen - arg, ptr, arg); + s390x_aes_gcm_setiv(gctx, gctx->iv); + gctx->iv_set = 1; + return 1; + + case EVP_CTRL_AEAD_TLS1_AAD: + /* Save the aad for later use. */ + if (arg != EVP_AEAD_TLS1_AAD_LEN) + return 0; + + buf = EVP_CIPHER_CTX_buf_noconst(c); + memcpy(buf, ptr, arg); + gctx->tls_aad_len = arg; + + len = buf[arg - 2] << 8 | buf[arg - 1]; + /* Correct length for explicit iv. */ + if (len < EVP_GCM_TLS_EXPLICIT_IV_LEN) + return 0; + len -= EVP_GCM_TLS_EXPLICIT_IV_LEN; + + /* If decrypting correct for tag too. */ + enc = EVP_CIPHER_CTX_encrypting(c); + if (!enc) { + if (len < EVP_GCM_TLS_TAG_LEN) + return 0; + len -= EVP_GCM_TLS_TAG_LEN; + } + buf[arg - 2] = len >> 8; + buf[arg - 1] = len & 0xff; + /* Extra padding: tag appended to record. */ + return EVP_GCM_TLS_TAG_LEN; + + case EVP_CTRL_COPY: + out = ptr; + gctx_out = EVP_C_DATA(S390X_AES_GCM_CTX, out); + iv = EVP_CIPHER_CTX_iv_noconst(c); + + if (gctx->iv == iv) { + gctx_out->iv = EVP_CIPHER_CTX_iv_noconst(out); + } else { + len = S390X_gcm_ivpadlen(gctx->ivlen); + + if ((gctx_out->iv = OPENSSL_malloc(len)) == NULL) { + EVPerr(EVP_F_S390X_AES_GCM_CTRL, ERR_R_MALLOC_FAILURE); + return 0; + } + + memcpy(gctx_out->iv, gctx->iv, len); + } + return 1; + + default: + return -1; + } +} + +/*- + * Set key and/or iv. Returns 1 on success. Otherwise 0 is returned. + */ +static int s390x_aes_gcm_init_key(EVP_CIPHER_CTX *ctx, + const unsigned char *key, + const unsigned char *iv, int enc) +{ + S390X_AES_GCM_CTX *gctx = EVP_C_DATA(S390X_AES_GCM_CTX, ctx); + int keylen; + + if (iv == NULL && key == NULL) + return 1; + + if (key != NULL) { + keylen = EVP_CIPHER_CTX_key_length(ctx); + memcpy(&gctx->kma.param.k, key, keylen); + + gctx->fc = S390X_AES_FC(keylen); + if (!enc) + gctx->fc |= S390X_DECRYPT; + + if (iv == NULL && gctx->iv_set) + iv = gctx->iv; + + if (iv != NULL) { + s390x_aes_gcm_setiv(gctx, iv); + gctx->iv_set = 1; + } + gctx->key_set = 1; + } else { + if (gctx->key_set) + s390x_aes_gcm_setiv(gctx, iv); + else + memcpy(gctx->iv, iv, gctx->ivlen); + + gctx->iv_set = 1; + gctx->iv_gen = 0; + } + return 1; +} + +/*- + * En/de-crypt and authenticate TLS packet. Returns the number of bytes written + * if successful. Otherwise -1 is returned. Code is big-endian. + */ +static int s390x_aes_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + S390X_AES_GCM_CTX *gctx = EVP_C_DATA(S390X_AES_GCM_CTX, ctx); + const unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx); + const int enc = EVP_CIPHER_CTX_encrypting(ctx); + int rv = -1; + + if (out != in || len < (EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN)) + return -1; + + if (EVP_CIPHER_CTX_ctrl(ctx, enc ? EVP_CTRL_GCM_IV_GEN + : EVP_CTRL_GCM_SET_IV_INV, + EVP_GCM_TLS_EXPLICIT_IV_LEN, out) <= 0) + goto err; + + in += EVP_GCM_TLS_EXPLICIT_IV_LEN; + out += EVP_GCM_TLS_EXPLICIT_IV_LEN; + len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN; + + gctx->kma.param.taadl = gctx->tls_aad_len << 3; + gctx->kma.param.tpcl = len << 3; + s390x_kma(buf, gctx->tls_aad_len, in, len, out, + gctx->fc | S390X_KMA_LAAD | S390X_KMA_LPC, &gctx->kma.param); + + if (enc) { + memcpy(out + len, gctx->kma.param.t.b, EVP_GCM_TLS_TAG_LEN); + rv = len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN; + } else { + if (CRYPTO_memcmp(gctx->kma.param.t.b, in + len, + EVP_GCM_TLS_TAG_LEN)) { + OPENSSL_cleanse(out, len); + goto err; + } + rv = len; + } +err: + gctx->iv_set = 0; + gctx->tls_aad_len = -1; + return rv; +} + +/*- + * Called from EVP layer to initialize context, process additional + * authenticated data, en/de-crypt plain/cipher-text and authenticate + * ciphertext or process a TLS packet, depending on context. Returns bytes + * written on success. Otherwise -1 is returned. Code is big-endian. + */ +static int s390x_aes_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + S390X_AES_GCM_CTX *gctx = EVP_C_DATA(S390X_AES_GCM_CTX, ctx); + unsigned char *buf, tmp[16]; + int enc; + + if (!gctx->key_set) + return -1; + + if (gctx->tls_aad_len >= 0) + return s390x_aes_gcm_tls_cipher(ctx, out, in, len); + + if (!gctx->iv_set) + return -1; + + if (in != NULL) { + if (out == NULL) { + if (s390x_aes_gcm_aad(gctx, in, len)) + return -1; + } else { + if (s390x_aes_gcm(gctx, in, out, len)) + return -1; + } + return len; + } else { + gctx->kma.param.taadl <<= 3; + gctx->kma.param.tpcl <<= 3; + s390x_kma(gctx->ares, gctx->areslen, gctx->mres, gctx->mreslen, tmp, + gctx->fc | S390X_KMA_LAAD | S390X_KMA_LPC, &gctx->kma.param); + /* recall that we already did en-/decrypt gctx->mres + * and returned it to caller... */ + OPENSSL_cleanse(tmp, gctx->mreslen); + gctx->iv_set = 0; + + enc = EVP_CIPHER_CTX_encrypting(ctx); + if (enc) { + gctx->taglen = 16; + } else { + if (gctx->taglen < 0) + return -1; + + buf = EVP_CIPHER_CTX_buf_noconst(ctx); + if (CRYPTO_memcmp(buf, gctx->kma.param.t.b, gctx->taglen)) + return -1; + } + return 0; + } +} + +static int s390x_aes_gcm_cleanup(EVP_CIPHER_CTX *c) +{ + S390X_AES_GCM_CTX *gctx = EVP_C_DATA(S390X_AES_GCM_CTX, c); + const unsigned char *iv; + + if (gctx == NULL) + return 0; + + iv = EVP_CIPHER_CTX_iv(c); + if (iv != gctx->iv) + OPENSSL_free(gctx->iv); + + OPENSSL_cleanse(gctx, sizeof(*gctx)); + return 1; +} + +# define S390X_AES_XTS_CTX EVP_AES_XTS_CTX +# define S390X_aes_128_xts_CAPABLE 1 /* checked by callee */ +# define S390X_aes_256_xts_CAPABLE 1 + +# define s390x_aes_xts_init_key aes_xts_init_key +static int s390x_aes_xts_init_key(EVP_CIPHER_CTX *ctx, + const unsigned char *key, + const unsigned char *iv, int enc); +# define s390x_aes_xts_cipher aes_xts_cipher +static int s390x_aes_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); +# define s390x_aes_xts_ctrl aes_xts_ctrl +static int s390x_aes_xts_ctrl(EVP_CIPHER_CTX *, int type, int arg, void *ptr); +# define s390x_aes_xts_cleanup aes_xts_cleanup + +# define S390X_aes_128_ccm_CAPABLE (S390X_aes_128_CAPABLE && \ + (OPENSSL_s390xcap_P.kmac[0] & \ + S390X_CAPBIT(S390X_AES_128))) +# define S390X_aes_192_ccm_CAPABLE (S390X_aes_192_CAPABLE && \ + (OPENSSL_s390xcap_P.kmac[0] & \ + S390X_CAPBIT(S390X_AES_192))) +# define S390X_aes_256_ccm_CAPABLE (S390X_aes_256_CAPABLE && \ + (OPENSSL_s390xcap_P.kmac[0] & \ + S390X_CAPBIT(S390X_AES_256))) + +# define S390X_CCM_AAD_FLAG 0x40 + +/*- + * Set nonce and length fields. Code is big-endian. + */ +static inline void s390x_aes_ccm_setiv(S390X_AES_CCM_CTX *ctx, + const unsigned char *nonce, + size_t mlen) +{ + ctx->aes.ccm.nonce.b[0] &= ~S390X_CCM_AAD_FLAG; + ctx->aes.ccm.nonce.g[1] = mlen; + memcpy(ctx->aes.ccm.nonce.b + 1, nonce, 15 - ctx->aes.ccm.l); +} + +/*- + * Process additional authenticated data. Code is big-endian. + */ +static void s390x_aes_ccm_aad(S390X_AES_CCM_CTX *ctx, const unsigned char *aad, + size_t alen) +{ + unsigned char *ptr; + int i, rem; + + if (!alen) + return; + + ctx->aes.ccm.nonce.b[0] |= S390X_CCM_AAD_FLAG; + + /* Suppress 'type-punned pointer dereference' warning. */ + ptr = ctx->aes.ccm.buf.b; + + if (alen < ((1 << 16) - (1 << 8))) { + *(uint16_t *)ptr = alen; + i = 2; + } else if (sizeof(alen) == 8 + && alen >= (size_t)1 << (32 % (sizeof(alen) * 8))) { + *(uint16_t *)ptr = 0xffff; + *(uint64_t *)(ptr + 2) = alen; + i = 10; + } else { + *(uint16_t *)ptr = 0xfffe; + *(uint32_t *)(ptr + 2) = alen; + i = 6; + } + + while (i < 16 && alen) { + ctx->aes.ccm.buf.b[i] = *aad; + ++aad; + --alen; + ++i; + } + while (i < 16) { + ctx->aes.ccm.buf.b[i] = 0; + ++i; + } + + ctx->aes.ccm.kmac_param.icv.g[0] = 0; + ctx->aes.ccm.kmac_param.icv.g[1] = 0; + s390x_kmac(ctx->aes.ccm.nonce.b, 32, ctx->aes.ccm.fc, + &ctx->aes.ccm.kmac_param); + ctx->aes.ccm.blocks += 2; + + rem = alen & 0xf; + alen &= ~(size_t)0xf; + if (alen) { + s390x_kmac(aad, alen, ctx->aes.ccm.fc, &ctx->aes.ccm.kmac_param); + ctx->aes.ccm.blocks += alen >> 4; + aad += alen; + } + if (rem) { + for (i = 0; i < rem; i++) + ctx->aes.ccm.kmac_param.icv.b[i] ^= aad[i]; + + s390x_km(ctx->aes.ccm.kmac_param.icv.b, 16, + ctx->aes.ccm.kmac_param.icv.b, ctx->aes.ccm.fc, + ctx->aes.ccm.kmac_param.k); + ctx->aes.ccm.blocks++; + } +} + +/*- + * En/de-crypt plain/cipher-text. Compute tag from plaintext. Returns 0 for + * success. + */ +static int s390x_aes_ccm(S390X_AES_CCM_CTX *ctx, const unsigned char *in, + unsigned char *out, size_t len, int enc) +{ + size_t n, rem; + unsigned int i, l, num; + unsigned char flags; + + flags = ctx->aes.ccm.nonce.b[0]; + if (!(flags & S390X_CCM_AAD_FLAG)) { + s390x_km(ctx->aes.ccm.nonce.b, 16, ctx->aes.ccm.kmac_param.icv.b, + ctx->aes.ccm.fc, ctx->aes.ccm.kmac_param.k); + ctx->aes.ccm.blocks++; + } + l = flags & 0x7; + ctx->aes.ccm.nonce.b[0] = l; + + /*- + * Reconstruct length from encoded length field + * and initialize it with counter value. + */ + n = 0; + for (i = 15 - l; i < 15; i++) { + n |= ctx->aes.ccm.nonce.b[i]; + ctx->aes.ccm.nonce.b[i] = 0; + n <<= 8; + } + n |= ctx->aes.ccm.nonce.b[15]; + ctx->aes.ccm.nonce.b[15] = 1; + + if (n != len) + return -1; /* length mismatch */ + + if (enc) { + /* Two operations per block plus one for tag encryption */ + ctx->aes.ccm.blocks += (((len + 15) >> 4) << 1) + 1; + if (ctx->aes.ccm.blocks > (1ULL << 61)) + return -2; /* too much data */ + } + + num = 0; + rem = len & 0xf; + len &= ~(size_t)0xf; + + if (enc) { + /* mac-then-encrypt */ + if (len) + s390x_kmac(in, len, ctx->aes.ccm.fc, &ctx->aes.ccm.kmac_param); + if (rem) { + for (i = 0; i < rem; i++) + ctx->aes.ccm.kmac_param.icv.b[i] ^= in[len + i]; + + s390x_km(ctx->aes.ccm.kmac_param.icv.b, 16, + ctx->aes.ccm.kmac_param.icv.b, ctx->aes.ccm.fc, + ctx->aes.ccm.kmac_param.k); + } + + CRYPTO_ctr128_encrypt_ctr32(in, out, len + rem, &ctx->aes.key.k, + ctx->aes.ccm.nonce.b, ctx->aes.ccm.buf.b, + &num, (ctr128_f)AES_ctr32_encrypt); + } else { + /* decrypt-then-mac */ + CRYPTO_ctr128_encrypt_ctr32(in, out, len + rem, &ctx->aes.key.k, + ctx->aes.ccm.nonce.b, ctx->aes.ccm.buf.b, + &num, (ctr128_f)AES_ctr32_encrypt); + + if (len) + s390x_kmac(out, len, ctx->aes.ccm.fc, &ctx->aes.ccm.kmac_param); + if (rem) { + for (i = 0; i < rem; i++) + ctx->aes.ccm.kmac_param.icv.b[i] ^= out[len + i]; + + s390x_km(ctx->aes.ccm.kmac_param.icv.b, 16, + ctx->aes.ccm.kmac_param.icv.b, ctx->aes.ccm.fc, + ctx->aes.ccm.kmac_param.k); + } + } + /* encrypt tag */ + for (i = 15 - l; i < 16; i++) + ctx->aes.ccm.nonce.b[i] = 0; + + s390x_km(ctx->aes.ccm.nonce.b, 16, ctx->aes.ccm.buf.b, ctx->aes.ccm.fc, + ctx->aes.ccm.kmac_param.k); + ctx->aes.ccm.kmac_param.icv.g[0] ^= ctx->aes.ccm.buf.g[0]; + ctx->aes.ccm.kmac_param.icv.g[1] ^= ctx->aes.ccm.buf.g[1]; + + ctx->aes.ccm.nonce.b[0] = flags; /* restore flags field */ + return 0; +} + +/*- + * En/de-crypt and authenticate TLS packet. Returns the number of bytes written + * if successful. Otherwise -1 is returned. + */ +static int s390x_aes_ccm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + S390X_AES_CCM_CTX *cctx = EVP_C_DATA(S390X_AES_CCM_CTX, ctx); + unsigned char *ivec = EVP_CIPHER_CTX_iv_noconst(ctx); + unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx); + const int enc = EVP_CIPHER_CTX_encrypting(ctx); + + if (out != in + || len < (EVP_CCM_TLS_EXPLICIT_IV_LEN + (size_t)cctx->aes.ccm.m)) + return -1; + + if (enc) { + /* Set explicit iv (sequence number). */ + memcpy(out, buf, EVP_CCM_TLS_EXPLICIT_IV_LEN); + } + + len -= EVP_CCM_TLS_EXPLICIT_IV_LEN + cctx->aes.ccm.m; + /*- + * Get explicit iv (sequence number). We already have fixed iv + * (server/client_write_iv) here. + */ + memcpy(ivec + EVP_CCM_TLS_FIXED_IV_LEN, in, EVP_CCM_TLS_EXPLICIT_IV_LEN); + s390x_aes_ccm_setiv(cctx, ivec, len); + + /* Process aad (sequence number|type|version|length) */ + s390x_aes_ccm_aad(cctx, buf, cctx->aes.ccm.tls_aad_len); + + in += EVP_CCM_TLS_EXPLICIT_IV_LEN; + out += EVP_CCM_TLS_EXPLICIT_IV_LEN; + + if (enc) { + if (s390x_aes_ccm(cctx, in, out, len, enc)) + return -1; + + memcpy(out + len, cctx->aes.ccm.kmac_param.icv.b, cctx->aes.ccm.m); + return len + EVP_CCM_TLS_EXPLICIT_IV_LEN + cctx->aes.ccm.m; + } else { + if (!s390x_aes_ccm(cctx, in, out, len, enc)) { + if (!CRYPTO_memcmp(cctx->aes.ccm.kmac_param.icv.b, in + len, + cctx->aes.ccm.m)) + return len; + } + + OPENSSL_cleanse(out, len); + return -1; + } +} + +/*- + * Set key and flag field and/or iv. Returns 1 if successful. Otherwise 0 is + * returned. + */ +static int s390x_aes_ccm_init_key(EVP_CIPHER_CTX *ctx, + const unsigned char *key, + const unsigned char *iv, int enc) +{ + S390X_AES_CCM_CTX *cctx = EVP_C_DATA(S390X_AES_CCM_CTX, ctx); + unsigned char *ivec; + int keylen; + + if (iv == NULL && key == NULL) + return 1; + + if (key != NULL) { + keylen = EVP_CIPHER_CTX_key_length(ctx); + cctx->aes.ccm.fc = S390X_AES_FC(keylen); + memcpy(cctx->aes.ccm.kmac_param.k, key, keylen); + + /* Store encoded m and l. */ + cctx->aes.ccm.nonce.b[0] = ((cctx->aes.ccm.l - 1) & 0x7) + | (((cctx->aes.ccm.m - 2) >> 1) & 0x7) << 3; + memset(cctx->aes.ccm.nonce.b + 1, 0, + sizeof(cctx->aes.ccm.nonce.b)); + cctx->aes.ccm.blocks = 0; + + cctx->aes.ccm.key_set = 1; + } + + if (iv != NULL) { + ivec = EVP_CIPHER_CTX_iv_noconst(ctx); + memcpy(ivec, iv, 15 - cctx->aes.ccm.l); + + cctx->aes.ccm.iv_set = 1; + } + + return 1; +} + +/*- + * Called from EVP layer to initialize context, process additional + * authenticated data, en/de-crypt plain/cipher-text and authenticate + * plaintext or process a TLS packet, depending on context. Returns bytes + * written on success. Otherwise -1 is returned. + */ +static int s390x_aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + S390X_AES_CCM_CTX *cctx = EVP_C_DATA(S390X_AES_CCM_CTX, ctx); + const int enc = EVP_CIPHER_CTX_encrypting(ctx); + int rv; + unsigned char *buf, *ivec; + + if (!cctx->aes.ccm.key_set) + return -1; + + if (cctx->aes.ccm.tls_aad_len >= 0) + return s390x_aes_ccm_tls_cipher(ctx, out, in, len); + + /*- + * Final(): Does not return any data. Recall that ccm is mac-then-encrypt + * so integrity must be checked already at Update() i.e., before + * potentially corrupted data is output. + */ + if (in == NULL && out != NULL) + return 0; + + if (!cctx->aes.ccm.iv_set) + return -1; + + if (!enc && !cctx->aes.ccm.tag_set) + return -1; + + if (out == NULL) { + /* Update(): Pass message length. */ + if (in == NULL) { + ivec = EVP_CIPHER_CTX_iv_noconst(ctx); + s390x_aes_ccm_setiv(cctx, ivec, len); + + cctx->aes.ccm.len_set = 1; + return len; + } + + /* Update(): Process aad. */ + if (!cctx->aes.ccm.len_set && len) + return -1; + + s390x_aes_ccm_aad(cctx, in, len); + return len; + } + + /* Update(): Process message. */ + + if (!cctx->aes.ccm.len_set) { + /*- + * In case message length was not previously set explicitly via + * Update(), set it now. + */ + ivec = EVP_CIPHER_CTX_iv_noconst(ctx); + s390x_aes_ccm_setiv(cctx, ivec, len); + + cctx->aes.ccm.len_set = 1; + } + + if (enc) { + if (s390x_aes_ccm(cctx, in, out, len, enc)) + return -1; + + cctx->aes.ccm.tag_set = 1; + return len; + } else { + rv = -1; + + if (!s390x_aes_ccm(cctx, in, out, len, enc)) { + buf = EVP_CIPHER_CTX_buf_noconst(ctx); + if (!CRYPTO_memcmp(cctx->aes.ccm.kmac_param.icv.b, buf, + cctx->aes.ccm.m)) + rv = len; + } + + if (rv == -1) + OPENSSL_cleanse(out, len); + + cctx->aes.ccm.iv_set = 0; + cctx->aes.ccm.tag_set = 0; + cctx->aes.ccm.len_set = 0; + return rv; + } +} + +/*- + * Performs various operations on the context structure depending on control + * type. Returns 1 for success, 0 for failure and -1 for unknown control type. + * Code is big-endian. + */ +static int s390x_aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) +{ + S390X_AES_CCM_CTX *cctx = EVP_C_DATA(S390X_AES_CCM_CTX, c); + unsigned char *buf, *iv; + int enc, len; + + switch (type) { + case EVP_CTRL_INIT: + cctx->aes.ccm.key_set = 0; + cctx->aes.ccm.iv_set = 0; + cctx->aes.ccm.l = 8; + cctx->aes.ccm.m = 12; + cctx->aes.ccm.tag_set = 0; + cctx->aes.ccm.len_set = 0; + cctx->aes.ccm.tls_aad_len = -1; + return 1; + + case EVP_CTRL_AEAD_TLS1_AAD: + if (arg != EVP_AEAD_TLS1_AAD_LEN) + return 0; + + /* Save the aad for later use. */ + buf = EVP_CIPHER_CTX_buf_noconst(c); + memcpy(buf, ptr, arg); + cctx->aes.ccm.tls_aad_len = arg; + + len = buf[arg - 2] << 8 | buf[arg - 1]; + if (len < EVP_CCM_TLS_EXPLICIT_IV_LEN) + return 0; + + /* Correct length for explicit iv. */ + len -= EVP_CCM_TLS_EXPLICIT_IV_LEN; + + enc = EVP_CIPHER_CTX_encrypting(c); + if (!enc) { + if (len < cctx->aes.ccm.m) + return 0; + + /* Correct length for tag. */ + len -= cctx->aes.ccm.m; + } + + buf[arg - 2] = len >> 8; + buf[arg - 1] = len & 0xff; + + /* Extra padding: tag appended to record. */ + return cctx->aes.ccm.m; + + case EVP_CTRL_CCM_SET_IV_FIXED: + if (arg != EVP_CCM_TLS_FIXED_IV_LEN) + return 0; + + /* Copy to first part of the iv. */ + iv = EVP_CIPHER_CTX_iv_noconst(c); + memcpy(iv, ptr, arg); + return 1; + + case EVP_CTRL_AEAD_SET_IVLEN: + arg = 15 - arg; + /* fall-through */ + + case EVP_CTRL_CCM_SET_L: + if (arg < 2 || arg > 8) + return 0; + + cctx->aes.ccm.l = arg; + return 1; + + case EVP_CTRL_AEAD_SET_TAG: + if ((arg & 1) || arg < 4 || arg > 16) + return 0; + + enc = EVP_CIPHER_CTX_encrypting(c); + if (enc && ptr) + return 0; + + if (ptr) { + cctx->aes.ccm.tag_set = 1; + buf = EVP_CIPHER_CTX_buf_noconst(c); + memcpy(buf, ptr, arg); + } + + cctx->aes.ccm.m = arg; + return 1; + + case EVP_CTRL_AEAD_GET_TAG: + enc = EVP_CIPHER_CTX_encrypting(c); + if (!enc || !cctx->aes.ccm.tag_set) + return 0; + + if(arg < cctx->aes.ccm.m) + return 0; + + memcpy(ptr, cctx->aes.ccm.kmac_param.icv.b, cctx->aes.ccm.m); + cctx->aes.ccm.tag_set = 0; + cctx->aes.ccm.iv_set = 0; + cctx->aes.ccm.len_set = 0; + return 1; + + case EVP_CTRL_COPY: + return 1; + + default: + return -1; + } +} + +# define s390x_aes_ccm_cleanup aes_ccm_cleanup + +# ifndef OPENSSL_NO_OCB +# define S390X_AES_OCB_CTX EVP_AES_OCB_CTX +# define S390X_aes_128_ocb_CAPABLE 0 +# define S390X_aes_192_ocb_CAPABLE 0 +# define S390X_aes_256_ocb_CAPABLE 0 + +# define s390x_aes_ocb_init_key aes_ocb_init_key +static int s390x_aes_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); +# define s390x_aes_ocb_cipher aes_ocb_cipher +static int s390x_aes_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); +# define s390x_aes_ocb_cleanup aes_ocb_cleanup +static int s390x_aes_ocb_cleanup(EVP_CIPHER_CTX *); +# define s390x_aes_ocb_ctrl aes_ocb_ctrl +static int s390x_aes_ocb_ctrl(EVP_CIPHER_CTX *, int type, int arg, void *ptr); +# endif + +# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode, \ + MODE,flags) \ +static const EVP_CIPHER s390x_aes_##keylen##_##mode = { \ + nid##_##keylen##_##nmode,blocksize, \ + keylen / 8, \ + ivlen, \ + flags | EVP_CIPH_##MODE##_MODE, \ + s390x_aes_##mode##_init_key, \ + s390x_aes_##mode##_cipher, \ + NULL, \ + sizeof(S390X_AES_##MODE##_CTX), \ + NULL, \ + NULL, \ + NULL, \ + NULL \ +}; \ +static const EVP_CIPHER aes_##keylen##_##mode = { \ + nid##_##keylen##_##nmode, \ + blocksize, \ + keylen / 8, \ + ivlen, \ + flags | EVP_CIPH_##MODE##_MODE, \ + aes_init_key, \ + aes_##mode##_cipher, \ + NULL, \ + sizeof(EVP_AES_KEY), \ + NULL, \ + NULL, \ + NULL, \ + NULL \ +}; \ +const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \ +{ \ + return S390X_aes_##keylen##_##mode##_CAPABLE ? \ + &s390x_aes_##keylen##_##mode : &aes_##keylen##_##mode; \ +} + +# define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags)\ +static const EVP_CIPHER s390x_aes_##keylen##_##mode = { \ + nid##_##keylen##_##mode, \ + blocksize, \ + (EVP_CIPH_##MODE##_MODE == EVP_CIPH_XTS_MODE ? 2 : 1) * keylen / 8, \ + ivlen, \ + flags | EVP_CIPH_##MODE##_MODE, \ + s390x_aes_##mode##_init_key, \ + s390x_aes_##mode##_cipher, \ + s390x_aes_##mode##_cleanup, \ + sizeof(S390X_AES_##MODE##_CTX), \ + NULL, \ + NULL, \ + s390x_aes_##mode##_ctrl, \ + NULL \ +}; \ +static const EVP_CIPHER aes_##keylen##_##mode = { \ + nid##_##keylen##_##mode,blocksize, \ + (EVP_CIPH_##MODE##_MODE == EVP_CIPH_XTS_MODE ? 2 : 1) * keylen / 8, \ + ivlen, \ + flags | EVP_CIPH_##MODE##_MODE, \ + aes_##mode##_init_key, \ + aes_##mode##_cipher, \ + aes_##mode##_cleanup, \ + sizeof(EVP_AES_##MODE##_CTX), \ + NULL, \ + NULL, \ + aes_##mode##_ctrl, \ + NULL \ +}; \ +const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \ +{ \ + return S390X_aes_##keylen##_##mode##_CAPABLE ? \ + &s390x_aes_##keylen##_##mode : &aes_##keylen##_##mode; \ +} + +#else + +# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \ +static const EVP_CIPHER aes_##keylen##_##mode = { \ + nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \ + flags|EVP_CIPH_##MODE##_MODE, \ + aes_init_key, \ + aes_##mode##_cipher, \ + NULL, \ + sizeof(EVP_AES_KEY), \ + NULL,NULL,NULL,NULL }; \ +const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \ +{ return &aes_##keylen##_##mode; } + +# define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \ +static const EVP_CIPHER aes_##keylen##_##mode = { \ + nid##_##keylen##_##mode,blocksize, \ + (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \ + flags|EVP_CIPH_##MODE##_MODE, \ + aes_##mode##_init_key, \ + aes_##mode##_cipher, \ + aes_##mode##_cleanup, \ + sizeof(EVP_AES_##MODE##_CTX), \ + NULL,NULL,aes_##mode##_ctrl,NULL }; \ +const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \ +{ return &aes_##keylen##_##mode; } + +#endif + +#if defined(OPENSSL_CPUID_OBJ) && (defined(__arm__) || defined(__arm) || defined(__aarch64__)) +# include "arm_arch.h" +# if __ARM_MAX_ARCH__>=7 +# if defined(BSAES_ASM) +# define BSAES_CAPABLE (OPENSSL_armcap_P & ARMV7_NEON) +# endif +# if defined(VPAES_ASM) +# define VPAES_CAPABLE (OPENSSL_armcap_P & ARMV7_NEON) +# endif +# define HWAES_CAPABLE (OPENSSL_armcap_P & ARMV8_AES) +# define HWAES_set_encrypt_key aes_v8_set_encrypt_key +# define HWAES_set_decrypt_key aes_v8_set_decrypt_key +# define HWAES_encrypt aes_v8_encrypt +# define HWAES_decrypt aes_v8_decrypt +# define HWAES_cbc_encrypt aes_v8_cbc_encrypt +# define HWAES_ctr32_encrypt_blocks aes_v8_ctr32_encrypt_blocks +# endif +#endif + +#if defined(HWAES_CAPABLE) +int HWAES_set_encrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key); +int HWAES_set_decrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key); +void HWAES_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key); +void HWAES_decrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key); +void HWAES_cbc_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, const int enc); +void HWAES_ctr32_encrypt_blocks(const unsigned char *in, unsigned char *out, + size_t len, const AES_KEY *key, + const unsigned char ivec[16]); +void HWAES_xts_encrypt(const unsigned char *inp, unsigned char *out, + size_t len, const AES_KEY *key1, + const AES_KEY *key2, const unsigned char iv[16]); +void HWAES_xts_decrypt(const unsigned char *inp, unsigned char *out, + size_t len, const AES_KEY *key1, + const AES_KEY *key2, const unsigned char iv[16]); +#endif + +#define BLOCK_CIPHER_generic_pack(nid,keylen,flags) \ + BLOCK_CIPHER_generic(nid,keylen,16,16,cbc,cbc,CBC,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \ + BLOCK_CIPHER_generic(nid,keylen,16,0,ecb,ecb,ECB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \ + BLOCK_CIPHER_generic(nid,keylen,1,16,ofb128,ofb,OFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \ + BLOCK_CIPHER_generic(nid,keylen,1,16,cfb128,cfb,CFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \ + BLOCK_CIPHER_generic(nid,keylen,1,16,cfb1,cfb1,CFB,flags) \ + BLOCK_CIPHER_generic(nid,keylen,1,16,cfb8,cfb8,CFB,flags) \ + BLOCK_CIPHER_generic(nid,keylen,1,16,ctr,ctr,CTR,flags) + +static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + int ret, mode; + EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx); + + mode = EVP_CIPHER_CTX_mode(ctx); + if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) + && !enc) { +#ifdef HWAES_CAPABLE + if (HWAES_CAPABLE) { + ret = HWAES_set_decrypt_key(key, + EVP_CIPHER_CTX_key_length(ctx) * 8, + &dat->ks.ks); + dat->block = (block128_f) HWAES_decrypt; + dat->stream.cbc = NULL; +# ifdef HWAES_cbc_encrypt + if (mode == EVP_CIPH_CBC_MODE) + dat->stream.cbc = (cbc128_f) HWAES_cbc_encrypt; +# endif + } else +#endif +#ifdef BSAES_CAPABLE + if (BSAES_CAPABLE && mode == EVP_CIPH_CBC_MODE) { + ret = AES_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, + &dat->ks.ks); + dat->block = (block128_f) AES_decrypt; + dat->stream.cbc = (cbc128_f) bsaes_cbc_encrypt; + } else +#endif +#ifdef VPAES_CAPABLE + if (VPAES_CAPABLE) { + ret = vpaes_set_decrypt_key(key, + EVP_CIPHER_CTX_key_length(ctx) * 8, + &dat->ks.ks); + dat->block = (block128_f) vpaes_decrypt; + dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? + (cbc128_f) vpaes_cbc_encrypt : NULL; + } else +#endif + { + ret = AES_set_decrypt_key(key, + EVP_CIPHER_CTX_key_length(ctx) * 8, + &dat->ks.ks); + dat->block = (block128_f) AES_decrypt; + dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? + (cbc128_f) AES_cbc_encrypt : NULL; + } + } else +#ifdef HWAES_CAPABLE + if (HWAES_CAPABLE) { + ret = HWAES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, + &dat->ks.ks); + dat->block = (block128_f) HWAES_encrypt; + dat->stream.cbc = NULL; +# ifdef HWAES_cbc_encrypt + if (mode == EVP_CIPH_CBC_MODE) + dat->stream.cbc = (cbc128_f) HWAES_cbc_encrypt; + else +# endif +# ifdef HWAES_ctr32_encrypt_blocks + if (mode == EVP_CIPH_CTR_MODE) + dat->stream.ctr = (ctr128_f) HWAES_ctr32_encrypt_blocks; + else +# endif + (void)0; /* terminate potentially open 'else' */ + } else +#endif +#ifdef BSAES_CAPABLE + if (BSAES_CAPABLE && mode == EVP_CIPH_CTR_MODE) { + ret = AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, + &dat->ks.ks); + dat->block = (block128_f) AES_encrypt; + dat->stream.ctr = (ctr128_f) bsaes_ctr32_encrypt_blocks; + } else +#endif +#ifdef VPAES_CAPABLE + if (VPAES_CAPABLE) { + ret = vpaes_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, + &dat->ks.ks); + dat->block = (block128_f) vpaes_encrypt; + dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? + (cbc128_f) vpaes_cbc_encrypt : NULL; + } else +#endif + { + ret = AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, + &dat->ks.ks); + dat->block = (block128_f) AES_encrypt; + dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? + (cbc128_f) AES_cbc_encrypt : NULL; +#ifdef AES_CTR_ASM + if (mode == EVP_CIPH_CTR_MODE) + dat->stream.ctr = (ctr128_f) AES_ctr32_encrypt; +#endif + } + + if (ret < 0) { + EVPerr(EVP_F_AES_INIT_KEY, EVP_R_AES_KEY_SETUP_FAILED); + return 0; + } + + return 1; +} + +static int aes_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx); + + if (dat->stream.cbc) + (*dat->stream.cbc) (in, out, len, &dat->ks, + EVP_CIPHER_CTX_iv_noconst(ctx), + EVP_CIPHER_CTX_encrypting(ctx)); + else if (EVP_CIPHER_CTX_encrypting(ctx)) + CRYPTO_cbc128_encrypt(in, out, len, &dat->ks, + EVP_CIPHER_CTX_iv_noconst(ctx), dat->block); + else + CRYPTO_cbc128_decrypt(in, out, len, &dat->ks, + EVP_CIPHER_CTX_iv_noconst(ctx), dat->block); + + return 1; +} + +static int aes_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + size_t bl = EVP_CIPHER_CTX_block_size(ctx); + size_t i; + EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx); + + if (len < bl) + return 1; + + for (i = 0, len -= bl; i <= len; i += bl) + (*dat->block) (in + i, out + i, &dat->ks); + + return 1; +} + +static int aes_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx); + + int num = EVP_CIPHER_CTX_num(ctx); + CRYPTO_ofb128_encrypt(in, out, len, &dat->ks, + EVP_CIPHER_CTX_iv_noconst(ctx), &num, dat->block); + EVP_CIPHER_CTX_set_num(ctx, num); + return 1; +} + +static int aes_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx); + + int num = EVP_CIPHER_CTX_num(ctx); + CRYPTO_cfb128_encrypt(in, out, len, &dat->ks, + EVP_CIPHER_CTX_iv_noconst(ctx), &num, + EVP_CIPHER_CTX_encrypting(ctx), dat->block); + EVP_CIPHER_CTX_set_num(ctx, num); + return 1; +} + +static int aes_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx); + + int num = EVP_CIPHER_CTX_num(ctx); + CRYPTO_cfb128_8_encrypt(in, out, len, &dat->ks, + EVP_CIPHER_CTX_iv_noconst(ctx), &num, + EVP_CIPHER_CTX_encrypting(ctx), dat->block); + EVP_CIPHER_CTX_set_num(ctx, num); + return 1; +} + +static int aes_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx); + + if (EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS)) { + int num = EVP_CIPHER_CTX_num(ctx); + CRYPTO_cfb128_1_encrypt(in, out, len, &dat->ks, + EVP_CIPHER_CTX_iv_noconst(ctx), &num, + EVP_CIPHER_CTX_encrypting(ctx), dat->block); + EVP_CIPHER_CTX_set_num(ctx, num); + return 1; + } + + while (len >= MAXBITCHUNK) { + int num = EVP_CIPHER_CTX_num(ctx); + CRYPTO_cfb128_1_encrypt(in, out, MAXBITCHUNK * 8, &dat->ks, + EVP_CIPHER_CTX_iv_noconst(ctx), &num, + EVP_CIPHER_CTX_encrypting(ctx), dat->block); + EVP_CIPHER_CTX_set_num(ctx, num); + len -= MAXBITCHUNK; + out += MAXBITCHUNK; + in += MAXBITCHUNK; + } + if (len) { + int num = EVP_CIPHER_CTX_num(ctx); + CRYPTO_cfb128_1_encrypt(in, out, len * 8, &dat->ks, + EVP_CIPHER_CTX_iv_noconst(ctx), &num, + EVP_CIPHER_CTX_encrypting(ctx), dat->block); + EVP_CIPHER_CTX_set_num(ctx, num); + } + + return 1; +} + +static int aes_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + unsigned int num = EVP_CIPHER_CTX_num(ctx); + EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx); + + if (dat->stream.ctr) + CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks, + EVP_CIPHER_CTX_iv_noconst(ctx), + EVP_CIPHER_CTX_buf_noconst(ctx), + &num, dat->stream.ctr); + else + CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, + EVP_CIPHER_CTX_iv_noconst(ctx), + EVP_CIPHER_CTX_buf_noconst(ctx), &num, + dat->block); + EVP_CIPHER_CTX_set_num(ctx, num); + return 1; +} + +BLOCK_CIPHER_generic_pack(NID_aes, 128, 0) + BLOCK_CIPHER_generic_pack(NID_aes, 192, 0) + BLOCK_CIPHER_generic_pack(NID_aes, 256, 0) + +static int aes_gcm_cleanup(EVP_CIPHER_CTX *c) +{ + EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,c); + if (gctx == NULL) + return 0; + OPENSSL_cleanse(&gctx->gcm, sizeof(gctx->gcm)); + if (gctx->iv != EVP_CIPHER_CTX_iv_noconst(c)) + OPENSSL_free(gctx->iv); + return 1; +} + +static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) +{ + EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,c); + switch (type) { + case EVP_CTRL_INIT: + gctx->key_set = 0; + gctx->iv_set = 0; + gctx->ivlen = c->cipher->iv_len; + gctx->iv = c->iv; + gctx->taglen = -1; + gctx->iv_gen = 0; + gctx->tls_aad_len = -1; + return 1; + + case EVP_CTRL_AEAD_SET_IVLEN: + if (arg <= 0) + return 0; + /* Allocate memory for IV if needed */ + if ((arg > EVP_MAX_IV_LENGTH) && (arg > gctx->ivlen)) { + if (gctx->iv != c->iv) + OPENSSL_free(gctx->iv); + if ((gctx->iv = OPENSSL_malloc(arg)) == NULL) { + EVPerr(EVP_F_AES_GCM_CTRL, ERR_R_MALLOC_FAILURE); + return 0; + } + } + gctx->ivlen = arg; + return 1; + + case EVP_CTRL_AEAD_SET_TAG: + if (arg <= 0 || arg > 16 || c->encrypt) + return 0; + memcpy(c->buf, ptr, arg); + gctx->taglen = arg; + return 1; + + case EVP_CTRL_AEAD_GET_TAG: + if (arg <= 0 || arg > 16 || !c->encrypt + || gctx->taglen < 0) + return 0; + memcpy(ptr, c->buf, arg); + return 1; + + case EVP_CTRL_GCM_SET_IV_FIXED: + /* Special case: -1 length restores whole IV */ + if (arg == -1) { + memcpy(gctx->iv, ptr, gctx->ivlen); + gctx->iv_gen = 1; + return 1; + } + /* + * Fixed field must be at least 4 bytes and invocation field at least + * 8. + */ + if ((arg < 4) || (gctx->ivlen - arg) < 8) + return 0; + if (arg) + memcpy(gctx->iv, ptr, arg); + if (c->encrypt && RAND_bytes(gctx->iv + arg, gctx->ivlen - arg) <= 0) + return 0; + gctx->iv_gen = 1; + return 1; + + case EVP_CTRL_GCM_IV_GEN: + if (gctx->iv_gen == 0 || gctx->key_set == 0) + return 0; + CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen); + if (arg <= 0 || arg > gctx->ivlen) + arg = gctx->ivlen; + memcpy(ptr, gctx->iv + gctx->ivlen - arg, arg); + /* + * Invocation field will be at least 8 bytes in size and so no need + * to check wrap around or increment more than last 8 bytes. + */ + ctr64_inc(gctx->iv + gctx->ivlen - 8); + gctx->iv_set = 1; + return 1; + + case EVP_CTRL_GCM_SET_IV_INV: + if (gctx->iv_gen == 0 || gctx->key_set == 0 || c->encrypt) + return 0; + memcpy(gctx->iv + gctx->ivlen - arg, ptr, arg); + CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen); + gctx->iv_set = 1; + return 1; + + case EVP_CTRL_AEAD_TLS1_AAD: + /* Save the AAD for later use */ + if (arg != EVP_AEAD_TLS1_AAD_LEN) + return 0; + memcpy(c->buf, ptr, arg); + gctx->tls_aad_len = arg; + { + unsigned int len = c->buf[arg - 2] << 8 | c->buf[arg - 1]; + /* Correct length for explicit IV */ + if (len < EVP_GCM_TLS_EXPLICIT_IV_LEN) + return 0; + len -= EVP_GCM_TLS_EXPLICIT_IV_LEN; + /* If decrypting correct for tag too */ + if (!c->encrypt) { + if (len < EVP_GCM_TLS_TAG_LEN) + return 0; + len -= EVP_GCM_TLS_TAG_LEN; + } + c->buf[arg - 2] = len >> 8; + c->buf[arg - 1] = len & 0xff; + } + /* Extra padding: tag appended to record */ + return EVP_GCM_TLS_TAG_LEN; + + case EVP_CTRL_COPY: + { + EVP_CIPHER_CTX *out = ptr; + EVP_AES_GCM_CTX *gctx_out = EVP_C_DATA(EVP_AES_GCM_CTX,out); + if (gctx->gcm.key) { + if (gctx->gcm.key != &gctx->ks) + return 0; + gctx_out->gcm.key = &gctx_out->ks; + } + if (gctx->iv == c->iv) + gctx_out->iv = out->iv; + else { + if ((gctx_out->iv = OPENSSL_malloc(gctx->ivlen)) == NULL) { + EVPerr(EVP_F_AES_GCM_CTRL, ERR_R_MALLOC_FAILURE); + return 0; + } + memcpy(gctx_out->iv, gctx->iv, gctx->ivlen); + } + return 1; + } + + default: + return -1; + + } +} + +static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx); + if (!iv && !key) + return 1; + if (key) { + do { +#ifdef HWAES_CAPABLE + if (HWAES_CAPABLE) { + HWAES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks); + CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, + (block128_f) HWAES_encrypt); +# ifdef HWAES_ctr32_encrypt_blocks + gctx->ctr = (ctr128_f) HWAES_ctr32_encrypt_blocks; +# else + gctx->ctr = NULL; +# endif + break; + } else +#endif +#ifdef BSAES_CAPABLE + if (BSAES_CAPABLE) { + AES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks); + CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, + (block128_f) AES_encrypt); + gctx->ctr = (ctr128_f) bsaes_ctr32_encrypt_blocks; + break; + } else +#endif +#ifdef VPAES_CAPABLE + if (VPAES_CAPABLE) { + vpaes_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks); + CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, + (block128_f) vpaes_encrypt); + gctx->ctr = NULL; + break; + } else +#endif + (void)0; /* terminate potentially open 'else' */ + + AES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks); + CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, + (block128_f) AES_encrypt); +#ifdef AES_CTR_ASM + gctx->ctr = (ctr128_f) AES_ctr32_encrypt; +#else + gctx->ctr = NULL; +#endif + } while (0); + + /* + * If we have an iv can set it directly, otherwise use saved IV. + */ + if (iv == NULL && gctx->iv_set) + iv = gctx->iv; + if (iv) { + CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen); + gctx->iv_set = 1; + } + gctx->key_set = 1; + } else { + /* If key set use IV, otherwise copy */ + if (gctx->key_set) + CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen); + else + memcpy(gctx->iv, iv, gctx->ivlen); + gctx->iv_set = 1; + gctx->iv_gen = 0; + } + return 1; +} + +/* + * Handle TLS GCM packet format. This consists of the last portion of the IV + * followed by the payload and finally the tag. On encrypt generate IV, + * encrypt payload and write the tag. On verify retrieve IV, decrypt payload + * and verify tag. + */ + +static int aes_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx); + int rv = -1; + /* Encrypt/decrypt must be performed in place */ + if (out != in + || len < (EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN)) + return -1; + /* + * Set IV from start of buffer or generate IV and write to start of + * buffer. + */ + if (EVP_CIPHER_CTX_ctrl(ctx, ctx->encrypt ? EVP_CTRL_GCM_IV_GEN + : EVP_CTRL_GCM_SET_IV_INV, + EVP_GCM_TLS_EXPLICIT_IV_LEN, out) <= 0) + goto err; + /* Use saved AAD */ + if (CRYPTO_gcm128_aad(&gctx->gcm, ctx->buf, gctx->tls_aad_len)) + goto err; + /* Fix buffer and length to point to payload */ + in += EVP_GCM_TLS_EXPLICIT_IV_LEN; + out += EVP_GCM_TLS_EXPLICIT_IV_LEN; + len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN; + if (ctx->encrypt) { + /* Encrypt payload */ + if (gctx->ctr) { + size_t bulk = 0; +#if defined(AES_GCM_ASM) + if (len >= 32 && AES_GCM_ASM(gctx)) { + if (CRYPTO_gcm128_encrypt(&gctx->gcm, NULL, NULL, 0)) + return -1; + + bulk = AES_gcm_encrypt(in, out, len, + gctx->gcm.key, + gctx->gcm.Yi.c, gctx->gcm.Xi.u); + gctx->gcm.len.u[1] += bulk; + } +#endif + if (CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm, + in + bulk, + out + bulk, + len - bulk, gctx->ctr)) + goto err; + } else { + size_t bulk = 0; +#if defined(AES_GCM_ASM2) + if (len >= 32 && AES_GCM_ASM2(gctx)) { + if (CRYPTO_gcm128_encrypt(&gctx->gcm, NULL, NULL, 0)) + return -1; + + bulk = AES_gcm_encrypt(in, out, len, + gctx->gcm.key, + gctx->gcm.Yi.c, gctx->gcm.Xi.u); + gctx->gcm.len.u[1] += bulk; + } +#endif + if (CRYPTO_gcm128_encrypt(&gctx->gcm, + in + bulk, out + bulk, len - bulk)) + goto err; + } + out += len; + /* Finally write tag */ + CRYPTO_gcm128_tag(&gctx->gcm, out, EVP_GCM_TLS_TAG_LEN); + rv = len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN; + } else { + /* Decrypt */ + if (gctx->ctr) { + size_t bulk = 0; +#if defined(AES_GCM_ASM) + if (len >= 16 && AES_GCM_ASM(gctx)) { + if (CRYPTO_gcm128_decrypt(&gctx->gcm, NULL, NULL, 0)) + return -1; + + bulk = AES_gcm_decrypt(in, out, len, + gctx->gcm.key, + gctx->gcm.Yi.c, gctx->gcm.Xi.u); + gctx->gcm.len.u[1] += bulk; + } +#endif + if (CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm, + in + bulk, + out + bulk, + len - bulk, gctx->ctr)) + goto err; + } else { + size_t bulk = 0; +#if defined(AES_GCM_ASM2) + if (len >= 16 && AES_GCM_ASM2(gctx)) { + if (CRYPTO_gcm128_decrypt(&gctx->gcm, NULL, NULL, 0)) + return -1; + + bulk = AES_gcm_decrypt(in, out, len, + gctx->gcm.key, + gctx->gcm.Yi.c, gctx->gcm.Xi.u); + gctx->gcm.len.u[1] += bulk; + } +#endif + if (CRYPTO_gcm128_decrypt(&gctx->gcm, + in + bulk, out + bulk, len - bulk)) + goto err; + } + /* Retrieve tag */ + CRYPTO_gcm128_tag(&gctx->gcm, ctx->buf, EVP_GCM_TLS_TAG_LEN); + /* If tag mismatch wipe buffer */ + if (CRYPTO_memcmp(ctx->buf, in + len, EVP_GCM_TLS_TAG_LEN)) { + OPENSSL_cleanse(out, len); + goto err; + } + rv = len; + } + + err: + gctx->iv_set = 0; + gctx->tls_aad_len = -1; + return rv; +} + +static int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx); + /* If not set up, return error */ + if (!gctx->key_set) + return -1; + + if (gctx->tls_aad_len >= 0) + return aes_gcm_tls_cipher(ctx, out, in, len); + + if (!gctx->iv_set) + return -1; + if (in) { + if (out == NULL) { + if (CRYPTO_gcm128_aad(&gctx->gcm, in, len)) + return -1; + } else if (ctx->encrypt) { + if (gctx->ctr) { + size_t bulk = 0; +#if defined(AES_GCM_ASM) + if (len >= 32 && AES_GCM_ASM(gctx)) { + size_t res = (16 - gctx->gcm.mres) % 16; + + if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, res)) + return -1; + + bulk = AES_gcm_encrypt(in + res, + out + res, len - res, + gctx->gcm.key, gctx->gcm.Yi.c, + gctx->gcm.Xi.u); + gctx->gcm.len.u[1] += bulk; + bulk += res; + } +#endif + if (CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm, + in + bulk, + out + bulk, + len - bulk, gctx->ctr)) + return -1; + } else { + size_t bulk = 0; +#if defined(AES_GCM_ASM2) + if (len >= 32 && AES_GCM_ASM2(gctx)) { + size_t res = (16 - gctx->gcm.mres) % 16; + + if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, res)) + return -1; + + bulk = AES_gcm_encrypt(in + res, + out + res, len - res, + gctx->gcm.key, gctx->gcm.Yi.c, + gctx->gcm.Xi.u); + gctx->gcm.len.u[1] += bulk; + bulk += res; + } +#endif + if (CRYPTO_gcm128_encrypt(&gctx->gcm, + in + bulk, out + bulk, len - bulk)) + return -1; + } + } else { + if (gctx->ctr) { + size_t bulk = 0; +#if defined(AES_GCM_ASM) + if (len >= 16 && AES_GCM_ASM(gctx)) { + size_t res = (16 - gctx->gcm.mres) % 16; + + if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, res)) + return -1; + + bulk = AES_gcm_decrypt(in + res, + out + res, len - res, + gctx->gcm.key, + gctx->gcm.Yi.c, gctx->gcm.Xi.u); + gctx->gcm.len.u[1] += bulk; + bulk += res; + } +#endif + if (CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm, + in + bulk, + out + bulk, + len - bulk, gctx->ctr)) + return -1; + } else { + size_t bulk = 0; +#if defined(AES_GCM_ASM2) + if (len >= 16 && AES_GCM_ASM2(gctx)) { + size_t res = (16 - gctx->gcm.mres) % 16; + + if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, res)) + return -1; + + bulk = AES_gcm_decrypt(in + res, + out + res, len - res, + gctx->gcm.key, + gctx->gcm.Yi.c, gctx->gcm.Xi.u); + gctx->gcm.len.u[1] += bulk; + bulk += res; + } +#endif + if (CRYPTO_gcm128_decrypt(&gctx->gcm, + in + bulk, out + bulk, len - bulk)) + return -1; + } + } + return len; + } else { + if (!ctx->encrypt) { + if (gctx->taglen < 0) + return -1; + if (CRYPTO_gcm128_finish(&gctx->gcm, ctx->buf, gctx->taglen) != 0) + return -1; + gctx->iv_set = 0; + return 0; + } + CRYPTO_gcm128_tag(&gctx->gcm, ctx->buf, 16); + gctx->taglen = 16; + /* Don't reuse the IV */ + gctx->iv_set = 0; + return 0; + } + +} + +#define CUSTOM_FLAGS (EVP_CIPH_FLAG_DEFAULT_ASN1 \ + | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \ + | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \ + | EVP_CIPH_CUSTOM_COPY) + +BLOCK_CIPHER_custom(NID_aes, 128, 1, 12, gcm, GCM, + EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS) + BLOCK_CIPHER_custom(NID_aes, 192, 1, 12, gcm, GCM, + EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS) + BLOCK_CIPHER_custom(NID_aes, 256, 1, 12, gcm, GCM, + EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS) + +static int aes_xts_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) +{ + EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,c); + if (type == EVP_CTRL_COPY) { + EVP_CIPHER_CTX *out = ptr; + EVP_AES_XTS_CTX *xctx_out = EVP_C_DATA(EVP_AES_XTS_CTX,out); + if (xctx->xts.key1) { + if (xctx->xts.key1 != &xctx->ks1) + return 0; + xctx_out->xts.key1 = &xctx_out->ks1; + } + if (xctx->xts.key2) { + if (xctx->xts.key2 != &xctx->ks2) + return 0; + xctx_out->xts.key2 = &xctx_out->ks2; + } + return 1; + } else if (type != EVP_CTRL_INIT) + return -1; + /* key1 and key2 are used as an indicator both key and IV are set */ + xctx->xts.key1 = NULL; + xctx->xts.key2 = NULL; + return 1; +} + +static int aes_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx); + if (!iv && !key) + return 1; + + if (key) + do { +#ifdef AES_XTS_ASM + xctx->stream = enc ? AES_xts_encrypt : AES_xts_decrypt; +#else + xctx->stream = NULL; +#endif + /* key_len is two AES keys */ +#ifdef HWAES_CAPABLE + if (HWAES_CAPABLE) { + if (enc) { + HWAES_set_encrypt_key(key, + EVP_CIPHER_CTX_key_length(ctx) * 4, + &xctx->ks1.ks); + xctx->xts.block1 = (block128_f) HWAES_encrypt; +# ifdef HWAES_xts_encrypt + xctx->stream = HWAES_xts_encrypt; +# endif + } else { + HWAES_set_decrypt_key(key, + EVP_CIPHER_CTX_key_length(ctx) * 4, + &xctx->ks1.ks); + xctx->xts.block1 = (block128_f) HWAES_decrypt; +# ifdef HWAES_xts_decrypt + xctx->stream = HWAES_xts_decrypt; +#endif + } + + HWAES_set_encrypt_key(key + EVP_CIPHER_CTX_key_length(ctx) / 2, + EVP_CIPHER_CTX_key_length(ctx) * 4, + &xctx->ks2.ks); + xctx->xts.block2 = (block128_f) HWAES_encrypt; + + xctx->xts.key1 = &xctx->ks1; + break; + } else +#endif +#ifdef BSAES_CAPABLE + if (BSAES_CAPABLE) + xctx->stream = enc ? bsaes_xts_encrypt : bsaes_xts_decrypt; + else +#endif +#ifdef VPAES_CAPABLE + if (VPAES_CAPABLE) { + if (enc) { + vpaes_set_encrypt_key(key, + EVP_CIPHER_CTX_key_length(ctx) * 4, + &xctx->ks1.ks); + xctx->xts.block1 = (block128_f) vpaes_encrypt; + } else { + vpaes_set_decrypt_key(key, + EVP_CIPHER_CTX_key_length(ctx) * 4, + &xctx->ks1.ks); + xctx->xts.block1 = (block128_f) vpaes_decrypt; + } + + vpaes_set_encrypt_key(key + EVP_CIPHER_CTX_key_length(ctx) / 2, + EVP_CIPHER_CTX_key_length(ctx) * 4, + &xctx->ks2.ks); + xctx->xts.block2 = (block128_f) vpaes_encrypt; + + xctx->xts.key1 = &xctx->ks1; + break; + } else +#endif + (void)0; /* terminate potentially open 'else' */ + + if (enc) { + AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 4, + &xctx->ks1.ks); + xctx->xts.block1 = (block128_f) AES_encrypt; + } else { + AES_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 4, + &xctx->ks1.ks); + xctx->xts.block1 = (block128_f) AES_decrypt; + } + + AES_set_encrypt_key(key + EVP_CIPHER_CTX_key_length(ctx) / 2, + EVP_CIPHER_CTX_key_length(ctx) * 4, + &xctx->ks2.ks); + xctx->xts.block2 = (block128_f) AES_encrypt; + + xctx->xts.key1 = &xctx->ks1; + } while (0); + + if (iv) { + xctx->xts.key2 = &xctx->ks2; + memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 16); + } + + return 1; +} + +static int aes_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx); + if (!xctx->xts.key1 || !xctx->xts.key2) + return 0; + if (!out || !in || len < AES_BLOCK_SIZE) + return 0; + if (xctx->stream) + (*xctx->stream) (in, out, len, + xctx->xts.key1, xctx->xts.key2, + EVP_CIPHER_CTX_iv_noconst(ctx)); + else if (CRYPTO_xts128_encrypt(&xctx->xts, EVP_CIPHER_CTX_iv_noconst(ctx), + in, out, len, + EVP_CIPHER_CTX_encrypting(ctx))) + return 0; + return 1; +} + +#define aes_xts_cleanup NULL + +#define XTS_FLAGS (EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CUSTOM_IV \ + | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \ + | EVP_CIPH_CUSTOM_COPY) + +BLOCK_CIPHER_custom(NID_aes, 128, 1, 16, xts, XTS, XTS_FLAGS) + BLOCK_CIPHER_custom(NID_aes, 256, 1, 16, xts, XTS, XTS_FLAGS) + +static int aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) +{ + EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,c); + switch (type) { + case EVP_CTRL_INIT: + cctx->key_set = 0; + cctx->iv_set = 0; + cctx->L = 8; + cctx->M = 12; + cctx->tag_set = 0; + cctx->len_set = 0; + cctx->tls_aad_len = -1; + return 1; + + case EVP_CTRL_AEAD_TLS1_AAD: + /* Save the AAD for later use */ + if (arg != EVP_AEAD_TLS1_AAD_LEN) + return 0; + memcpy(EVP_CIPHER_CTX_buf_noconst(c), ptr, arg); + cctx->tls_aad_len = arg; + { + uint16_t len = + EVP_CIPHER_CTX_buf_noconst(c)[arg - 2] << 8 + | EVP_CIPHER_CTX_buf_noconst(c)[arg - 1]; + /* Correct length for explicit IV */ + if (len < EVP_CCM_TLS_EXPLICIT_IV_LEN) + return 0; + len -= EVP_CCM_TLS_EXPLICIT_IV_LEN; + /* If decrypting correct for tag too */ + if (!EVP_CIPHER_CTX_encrypting(c)) { + if (len < cctx->M) + return 0; + len -= cctx->M; + } + EVP_CIPHER_CTX_buf_noconst(c)[arg - 2] = len >> 8; + EVP_CIPHER_CTX_buf_noconst(c)[arg - 1] = len & 0xff; + } + /* Extra padding: tag appended to record */ + return cctx->M; + + case EVP_CTRL_CCM_SET_IV_FIXED: + /* Sanity check length */ + if (arg != EVP_CCM_TLS_FIXED_IV_LEN) + return 0; + /* Just copy to first part of IV */ + memcpy(EVP_CIPHER_CTX_iv_noconst(c), ptr, arg); + return 1; + + case EVP_CTRL_AEAD_SET_IVLEN: + arg = 15 - arg; + /* fall thru */ + case EVP_CTRL_CCM_SET_L: + if (arg < 2 || arg > 8) + return 0; + cctx->L = arg; + return 1; + + case EVP_CTRL_AEAD_SET_TAG: + if ((arg & 1) || arg < 4 || arg > 16) + return 0; + if (EVP_CIPHER_CTX_encrypting(c) && ptr) + return 0; + if (ptr) { + cctx->tag_set = 1; + memcpy(EVP_CIPHER_CTX_buf_noconst(c), ptr, arg); + } + cctx->M = arg; + return 1; + + case EVP_CTRL_AEAD_GET_TAG: + if (!EVP_CIPHER_CTX_encrypting(c) || !cctx->tag_set) + return 0; + if (!CRYPTO_ccm128_tag(&cctx->ccm, ptr, (size_t)arg)) + return 0; + cctx->tag_set = 0; + cctx->iv_set = 0; + cctx->len_set = 0; + return 1; + + case EVP_CTRL_COPY: + { + EVP_CIPHER_CTX *out = ptr; + EVP_AES_CCM_CTX *cctx_out = EVP_C_DATA(EVP_AES_CCM_CTX,out); + if (cctx->ccm.key) { + if (cctx->ccm.key != &cctx->ks) + return 0; + cctx_out->ccm.key = &cctx_out->ks; + } + return 1; + } + + default: + return -1; + + } +} + +static int aes_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx); + if (!iv && !key) + return 1; + if (key) + do { +#ifdef HWAES_CAPABLE + if (HWAES_CAPABLE) { + HWAES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, + &cctx->ks.ks); + + CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L, + &cctx->ks, (block128_f) HWAES_encrypt); + cctx->str = NULL; + cctx->key_set = 1; + break; + } else +#endif +#ifdef VPAES_CAPABLE + if (VPAES_CAPABLE) { + vpaes_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, + &cctx->ks.ks); + CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L, + &cctx->ks, (block128_f) vpaes_encrypt); + cctx->str = NULL; + cctx->key_set = 1; + break; + } +#endif + AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, + &cctx->ks.ks); + CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L, + &cctx->ks, (block128_f) AES_encrypt); + cctx->str = NULL; + cctx->key_set = 1; + } while (0); + if (iv) { + memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 15 - cctx->L); + cctx->iv_set = 1; + } + return 1; +} + +static int aes_ccm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx); + CCM128_CONTEXT *ccm = &cctx->ccm; + /* Encrypt/decrypt must be performed in place */ + if (out != in || len < (EVP_CCM_TLS_EXPLICIT_IV_LEN + (size_t)cctx->M)) + return -1; + /* If encrypting set explicit IV from sequence number (start of AAD) */ + if (EVP_CIPHER_CTX_encrypting(ctx)) + memcpy(out, EVP_CIPHER_CTX_buf_noconst(ctx), + EVP_CCM_TLS_EXPLICIT_IV_LEN); + /* Get rest of IV from explicit IV */ + memcpy(EVP_CIPHER_CTX_iv_noconst(ctx) + EVP_CCM_TLS_FIXED_IV_LEN, in, + EVP_CCM_TLS_EXPLICIT_IV_LEN); + /* Correct length value */ + len -= EVP_CCM_TLS_EXPLICIT_IV_LEN + cctx->M; + if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx), 15 - cctx->L, + len)) + return -1; + /* Use saved AAD */ + CRYPTO_ccm128_aad(ccm, EVP_CIPHER_CTX_buf_noconst(ctx), cctx->tls_aad_len); + /* Fix buffer to point to payload */ + in += EVP_CCM_TLS_EXPLICIT_IV_LEN; + out += EVP_CCM_TLS_EXPLICIT_IV_LEN; + if (EVP_CIPHER_CTX_encrypting(ctx)) { + if (cctx->str ? CRYPTO_ccm128_encrypt_ccm64(ccm, in, out, len, + cctx->str) : + CRYPTO_ccm128_encrypt(ccm, in, out, len)) + return -1; + if (!CRYPTO_ccm128_tag(ccm, out + len, cctx->M)) + return -1; + return len + EVP_CCM_TLS_EXPLICIT_IV_LEN + cctx->M; + } else { + if (cctx->str ? !CRYPTO_ccm128_decrypt_ccm64(ccm, in, out, len, + cctx->str) : + !CRYPTO_ccm128_decrypt(ccm, in, out, len)) { + unsigned char tag[16]; + if (CRYPTO_ccm128_tag(ccm, tag, cctx->M)) { + if (!CRYPTO_memcmp(tag, in + len, cctx->M)) + return len; + } + } + OPENSSL_cleanse(out, len); + return -1; + } +} + +static int aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx); + CCM128_CONTEXT *ccm = &cctx->ccm; + /* If not set up, return error */ + if (!cctx->key_set) + return -1; + + if (cctx->tls_aad_len >= 0) + return aes_ccm_tls_cipher(ctx, out, in, len); + + /* EVP_*Final() doesn't return any data */ + if (in == NULL && out != NULL) + return 0; + + if (!cctx->iv_set) + return -1; + + if (!EVP_CIPHER_CTX_encrypting(ctx) && !cctx->tag_set) + return -1; + if (!out) { + if (!in) { + if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx), + 15 - cctx->L, len)) + return -1; + cctx->len_set = 1; + return len; + } + /* If have AAD need message length */ + if (!cctx->len_set && len) + return -1; + CRYPTO_ccm128_aad(ccm, in, len); + return len; + } + /* If not set length yet do it */ + if (!cctx->len_set) { + if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx), + 15 - cctx->L, len)) + return -1; + cctx->len_set = 1; + } + if (EVP_CIPHER_CTX_encrypting(ctx)) { + if (cctx->str ? CRYPTO_ccm128_encrypt_ccm64(ccm, in, out, len, + cctx->str) : + CRYPTO_ccm128_encrypt(ccm, in, out, len)) + return -1; + cctx->tag_set = 1; + return len; + } else { + int rv = -1; + if (cctx->str ? !CRYPTO_ccm128_decrypt_ccm64(ccm, in, out, len, + cctx->str) : + !CRYPTO_ccm128_decrypt(ccm, in, out, len)) { + unsigned char tag[16]; + if (CRYPTO_ccm128_tag(ccm, tag, cctx->M)) { + if (!CRYPTO_memcmp(tag, EVP_CIPHER_CTX_buf_noconst(ctx), + cctx->M)) + rv = len; + } + } + if (rv == -1) + OPENSSL_cleanse(out, len); + cctx->iv_set = 0; + cctx->tag_set = 0; + cctx->len_set = 0; + return rv; + } +} + +#define aes_ccm_cleanup NULL + +BLOCK_CIPHER_custom(NID_aes, 128, 1, 12, ccm, CCM, + EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS) + BLOCK_CIPHER_custom(NID_aes, 192, 1, 12, ccm, CCM, + EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS) + BLOCK_CIPHER_custom(NID_aes, 256, 1, 12, ccm, CCM, + EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS) + +typedef struct { + union { + double align; + AES_KEY ks; + } ks; + /* Indicates if IV has been set */ + unsigned char *iv; +} EVP_AES_WRAP_CTX; + +static int aes_wrap_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + EVP_AES_WRAP_CTX *wctx = EVP_C_DATA(EVP_AES_WRAP_CTX,ctx); + if (!iv && !key) + return 1; + if (key) { + if (EVP_CIPHER_CTX_encrypting(ctx)) + AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, + &wctx->ks.ks); + else + AES_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, + &wctx->ks.ks); + if (!iv) + wctx->iv = NULL; + } + if (iv) { + memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, EVP_CIPHER_CTX_iv_length(ctx)); + wctx->iv = EVP_CIPHER_CTX_iv_noconst(ctx); + } + return 1; +} + +static int aes_wrap_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inlen) +{ + EVP_AES_WRAP_CTX *wctx = EVP_C_DATA(EVP_AES_WRAP_CTX,ctx); + size_t rv; + /* AES wrap with padding has IV length of 4, without padding 8 */ + int pad = EVP_CIPHER_CTX_iv_length(ctx) == 4; + /* No final operation so always return zero length */ + if (!in) + return 0; + /* Input length must always be non-zero */ + if (!inlen) + return -1; + /* If decrypting need at least 16 bytes and multiple of 8 */ + if (!EVP_CIPHER_CTX_encrypting(ctx) && (inlen < 16 || inlen & 0x7)) + return -1; + /* If not padding input must be multiple of 8 */ + if (!pad && inlen & 0x7) + return -1; + if (is_partially_overlapping(out, in, inlen)) { + EVPerr(EVP_F_AES_WRAP_CIPHER, EVP_R_PARTIALLY_OVERLAPPING); + return 0; + } + if (!out) { + if (EVP_CIPHER_CTX_encrypting(ctx)) { + /* If padding round up to multiple of 8 */ + if (pad) + inlen = (inlen + 7) / 8 * 8; + /* 8 byte prefix */ + return inlen + 8; + } else { + /* + * If not padding output will be exactly 8 bytes smaller than + * input. If padding it will be at least 8 bytes smaller but we + * don't know how much. + */ + return inlen - 8; + } + } + if (pad) { + if (EVP_CIPHER_CTX_encrypting(ctx)) + rv = CRYPTO_128_wrap_pad(&wctx->ks.ks, wctx->iv, + out, in, inlen, + (block128_f) AES_encrypt); + else + rv = CRYPTO_128_unwrap_pad(&wctx->ks.ks, wctx->iv, + out, in, inlen, + (block128_f) AES_decrypt); + } else { + if (EVP_CIPHER_CTX_encrypting(ctx)) + rv = CRYPTO_128_wrap(&wctx->ks.ks, wctx->iv, + out, in, inlen, (block128_f) AES_encrypt); + else + rv = CRYPTO_128_unwrap(&wctx->ks.ks, wctx->iv, + out, in, inlen, (block128_f) AES_decrypt); + } + return rv ? (int)rv : -1; +} + +#define WRAP_FLAGS (EVP_CIPH_WRAP_MODE \ + | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \ + | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_FLAG_DEFAULT_ASN1) + +static const EVP_CIPHER aes_128_wrap = { + NID_id_aes128_wrap, + 8, 16, 8, WRAP_FLAGS, + aes_wrap_init_key, aes_wrap_cipher, + NULL, + sizeof(EVP_AES_WRAP_CTX), + NULL, NULL, NULL, NULL +}; + +const EVP_CIPHER *EVP_aes_128_wrap(void) +{ + return &aes_128_wrap; +} + +static const EVP_CIPHER aes_192_wrap = { + NID_id_aes192_wrap, + 8, 24, 8, WRAP_FLAGS, + aes_wrap_init_key, aes_wrap_cipher, + NULL, + sizeof(EVP_AES_WRAP_CTX), + NULL, NULL, NULL, NULL +}; + +const EVP_CIPHER *EVP_aes_192_wrap(void) +{ + return &aes_192_wrap; +} + +static const EVP_CIPHER aes_256_wrap = { + NID_id_aes256_wrap, + 8, 32, 8, WRAP_FLAGS, + aes_wrap_init_key, aes_wrap_cipher, + NULL, + sizeof(EVP_AES_WRAP_CTX), + NULL, NULL, NULL, NULL +}; + +const EVP_CIPHER *EVP_aes_256_wrap(void) +{ + return &aes_256_wrap; +} + +static const EVP_CIPHER aes_128_wrap_pad = { + NID_id_aes128_wrap_pad, + 8, 16, 4, WRAP_FLAGS, + aes_wrap_init_key, aes_wrap_cipher, + NULL, + sizeof(EVP_AES_WRAP_CTX), + NULL, NULL, NULL, NULL +}; + +const EVP_CIPHER *EVP_aes_128_wrap_pad(void) +{ + return &aes_128_wrap_pad; +} + +static const EVP_CIPHER aes_192_wrap_pad = { + NID_id_aes192_wrap_pad, + 8, 24, 4, WRAP_FLAGS, + aes_wrap_init_key, aes_wrap_cipher, + NULL, + sizeof(EVP_AES_WRAP_CTX), + NULL, NULL, NULL, NULL +}; + +const EVP_CIPHER *EVP_aes_192_wrap_pad(void) +{ + return &aes_192_wrap_pad; +} + +static const EVP_CIPHER aes_256_wrap_pad = { + NID_id_aes256_wrap_pad, + 8, 32, 4, WRAP_FLAGS, + aes_wrap_init_key, aes_wrap_cipher, + NULL, + sizeof(EVP_AES_WRAP_CTX), + NULL, NULL, NULL, NULL +}; + +const EVP_CIPHER *EVP_aes_256_wrap_pad(void) +{ + return &aes_256_wrap_pad; +} + +#ifndef OPENSSL_NO_OCB +static int aes_ocb_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) +{ + EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,c); + EVP_CIPHER_CTX *newc; + EVP_AES_OCB_CTX *new_octx; + + switch (type) { + case EVP_CTRL_INIT: + octx->key_set = 0; + octx->iv_set = 0; + octx->ivlen = EVP_CIPHER_CTX_iv_length(c); + octx->iv = EVP_CIPHER_CTX_iv_noconst(c); + octx->taglen = 16; + octx->data_buf_len = 0; + octx->aad_buf_len = 0; + return 1; + + case EVP_CTRL_AEAD_SET_IVLEN: + /* IV len must be 1 to 15 */ + if (arg <= 0 || arg > 15) + return 0; + + octx->ivlen = arg; + return 1; + + case EVP_CTRL_AEAD_SET_TAG: + if (!ptr) { + /* Tag len must be 0 to 16 */ + if (arg < 0 || arg > 16) + return 0; + + octx->taglen = arg; + return 1; + } + if (arg != octx->taglen || EVP_CIPHER_CTX_encrypting(c)) + return 0; + memcpy(octx->tag, ptr, arg); + return 1; + + case EVP_CTRL_AEAD_GET_TAG: + if (arg != octx->taglen || !EVP_CIPHER_CTX_encrypting(c)) + return 0; + + memcpy(ptr, octx->tag, arg); + return 1; + + case EVP_CTRL_COPY: + newc = (EVP_CIPHER_CTX *)ptr; + new_octx = EVP_C_DATA(EVP_AES_OCB_CTX,newc); + return CRYPTO_ocb128_copy_ctx(&new_octx->ocb, &octx->ocb, + &new_octx->ksenc.ks, + &new_octx->ksdec.ks); + + default: + return -1; + + } +} + +# ifdef HWAES_CAPABLE +# ifdef HWAES_ocb_encrypt +void HWAES_ocb_encrypt(const unsigned char *in, unsigned char *out, + size_t blocks, const void *key, + size_t start_block_num, + unsigned char offset_i[16], + const unsigned char L_[][16], + unsigned char checksum[16]); +# else +# define HWAES_ocb_encrypt ((ocb128_f)NULL) +# endif +# ifdef HWAES_ocb_decrypt +void HWAES_ocb_decrypt(const unsigned char *in, unsigned char *out, + size_t blocks, const void *key, + size_t start_block_num, + unsigned char offset_i[16], + const unsigned char L_[][16], + unsigned char checksum[16]); +# else +# define HWAES_ocb_decrypt ((ocb128_f)NULL) +# endif +# endif + +static int aes_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx); + if (!iv && !key) + return 1; + if (key) { + do { + /* + * We set both the encrypt and decrypt key here because decrypt + * needs both. We could possibly optimise to remove setting the + * decrypt for an encryption operation. + */ +# ifdef HWAES_CAPABLE + if (HWAES_CAPABLE) { + HWAES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, + &octx->ksenc.ks); + HWAES_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, + &octx->ksdec.ks); + if (!CRYPTO_ocb128_init(&octx->ocb, + &octx->ksenc.ks, &octx->ksdec.ks, + (block128_f) HWAES_encrypt, + (block128_f) HWAES_decrypt, + enc ? HWAES_ocb_encrypt + : HWAES_ocb_decrypt)) + return 0; + break; + } +# endif +# ifdef VPAES_CAPABLE + if (VPAES_CAPABLE) { + vpaes_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, + &octx->ksenc.ks); + vpaes_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, + &octx->ksdec.ks); + if (!CRYPTO_ocb128_init(&octx->ocb, + &octx->ksenc.ks, &octx->ksdec.ks, + (block128_f) vpaes_encrypt, + (block128_f) vpaes_decrypt, + NULL)) + return 0; + break; + } +# endif + AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, + &octx->ksenc.ks); + AES_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, + &octx->ksdec.ks); + if (!CRYPTO_ocb128_init(&octx->ocb, + &octx->ksenc.ks, &octx->ksdec.ks, + (block128_f) AES_encrypt, + (block128_f) AES_decrypt, + NULL)) + return 0; + } + while (0); + + /* + * If we have an iv we can set it directly, otherwise use saved IV. + */ + if (iv == NULL && octx->iv_set) + iv = octx->iv; + if (iv) { + if (CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen) + != 1) + return 0; + octx->iv_set = 1; + } + octx->key_set = 1; + } else { + /* If key set use IV, otherwise copy */ + if (octx->key_set) + CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen); + else + memcpy(octx->iv, iv, octx->ivlen); + octx->iv_set = 1; + } + return 1; +} + +static int aes_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + unsigned char *buf; + int *buf_len; + int written_len = 0; + size_t trailing_len; + EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx); + + /* If IV or Key not set then return error */ + if (!octx->iv_set) + return -1; + + if (!octx->key_set) + return -1; + + if (in != NULL) { + /* + * Need to ensure we are only passing full blocks to low level OCB + * routines. We do it here rather than in EVP_EncryptUpdate/ + * EVP_DecryptUpdate because we need to pass full blocks of AAD too + * and those routines don't support that + */ + + /* Are we dealing with AAD or normal data here? */ + if (out == NULL) { + buf = octx->aad_buf; + buf_len = &(octx->aad_buf_len); + } else { + buf = octx->data_buf; + buf_len = &(octx->data_buf_len); + + if (is_partially_overlapping(out + *buf_len, in, len)) { + EVPerr(EVP_F_AES_OCB_CIPHER, EVP_R_PARTIALLY_OVERLAPPING); + return 0; + } + } + + /* + * If we've got a partially filled buffer from a previous call then + * use that data first + */ + if (*buf_len > 0) { + unsigned int remaining; + + remaining = AES_BLOCK_SIZE - (*buf_len); + if (remaining > len) { + memcpy(buf + (*buf_len), in, len); + *(buf_len) += len; + return 0; + } + memcpy(buf + (*buf_len), in, remaining); + + /* + * If we get here we've filled the buffer, so process it + */ + len -= remaining; + in += remaining; + if (out == NULL) { + if (!CRYPTO_ocb128_aad(&octx->ocb, buf, AES_BLOCK_SIZE)) + return -1; + } else if (EVP_CIPHER_CTX_encrypting(ctx)) { + if (!CRYPTO_ocb128_encrypt(&octx->ocb, buf, out, + AES_BLOCK_SIZE)) + return -1; + } else { + if (!CRYPTO_ocb128_decrypt(&octx->ocb, buf, out, + AES_BLOCK_SIZE)) + return -1; + } + written_len = AES_BLOCK_SIZE; + *buf_len = 0; + if (out != NULL) + out += AES_BLOCK_SIZE; + } + + /* Do we have a partial block to handle at the end? */ + trailing_len = len % AES_BLOCK_SIZE; + + /* + * If we've got some full blocks to handle, then process these first + */ + if (len != trailing_len) { + if (out == NULL) { + if (!CRYPTO_ocb128_aad(&octx->ocb, in, len - trailing_len)) + return -1; + } else if (EVP_CIPHER_CTX_encrypting(ctx)) { + if (!CRYPTO_ocb128_encrypt + (&octx->ocb, in, out, len - trailing_len)) + return -1; + } else { + if (!CRYPTO_ocb128_decrypt + (&octx->ocb, in, out, len - trailing_len)) + return -1; + } + written_len += len - trailing_len; + in += len - trailing_len; + } + + /* Handle any trailing partial block */ + if (trailing_len > 0) { + memcpy(buf, in, trailing_len); + *buf_len = trailing_len; + } + + return written_len; + } else { + /* + * First of all empty the buffer of any partial block that we might + * have been provided - both for data and AAD + */ + if (octx->data_buf_len > 0) { + if (EVP_CIPHER_CTX_encrypting(ctx)) { + if (!CRYPTO_ocb128_encrypt(&octx->ocb, octx->data_buf, out, + octx->data_buf_len)) + return -1; + } else { + if (!CRYPTO_ocb128_decrypt(&octx->ocb, octx->data_buf, out, + octx->data_buf_len)) + return -1; + } + written_len = octx->data_buf_len; + octx->data_buf_len = 0; + } + if (octx->aad_buf_len > 0) { + if (!CRYPTO_ocb128_aad + (&octx->ocb, octx->aad_buf, octx->aad_buf_len)) + return -1; + octx->aad_buf_len = 0; + } + /* If decrypting then verify */ + if (!EVP_CIPHER_CTX_encrypting(ctx)) { + if (octx->taglen < 0) + return -1; + if (CRYPTO_ocb128_finish(&octx->ocb, + octx->tag, octx->taglen) != 0) + return -1; + octx->iv_set = 0; + return written_len; + } + /* If encrypting then just get the tag */ + if (CRYPTO_ocb128_tag(&octx->ocb, octx->tag, 16) != 1) + return -1; + /* Don't reuse the IV */ + octx->iv_set = 0; + return written_len; + } +} + +static int aes_ocb_cleanup(EVP_CIPHER_CTX *c) +{ + EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,c); + CRYPTO_ocb128_cleanup(&octx->ocb); + return 1; +} + +BLOCK_CIPHER_custom(NID_aes, 128, 16, 12, ocb, OCB, + EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS) +BLOCK_CIPHER_custom(NID_aes, 192, 16, 12, ocb, OCB, + EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS) +BLOCK_CIPHER_custom(NID_aes, 256, 16, 12, ocb, OCB, + EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS) +#endif /* OPENSSL_NO_OCB */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_aes_cbc_hmac_sha1.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_aes_cbc_hmac_sha1.c new file mode 100644 index 000000000..09d24dc3d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_aes_cbc_hmac_sha1.c @@ -0,0 +1,964 @@ +/* + * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include "modes_lcl.h" +#include "internal/evp_int.h" +#include "internal/constant_time_locl.h" + +typedef struct { + AES_KEY ks; + SHA_CTX head, tail, md; + size_t payload_length; /* AAD length in decrypt case */ + union { + unsigned int tls_ver; + unsigned char tls_aad[16]; /* 13 used */ + } aux; +} EVP_AES_HMAC_SHA1; + +#define NO_PAYLOAD_LENGTH ((size_t)-1) + +#if defined(AES_ASM) && ( \ + defined(__x86_64) || defined(__x86_64__) || \ + defined(_M_AMD64) || defined(_M_X64) ) + +extern unsigned int OPENSSL_ia32cap_P[]; +# define AESNI_CAPABLE (1<<(57-32)) + +int aesni_set_encrypt_key(const unsigned char *userKey, int bits, + AES_KEY *key); +int aesni_set_decrypt_key(const unsigned char *userKey, int bits, + AES_KEY *key); + +void aesni_cbc_encrypt(const unsigned char *in, + unsigned char *out, + size_t length, + const AES_KEY *key, unsigned char *ivec, int enc); + +void aesni_cbc_sha1_enc(const void *inp, void *out, size_t blocks, + const AES_KEY *key, unsigned char iv[16], + SHA_CTX *ctx, const void *in0); + +void aesni256_cbc_sha1_dec(const void *inp, void *out, size_t blocks, + const AES_KEY *key, unsigned char iv[16], + SHA_CTX *ctx, const void *in0); + +# define data(ctx) ((EVP_AES_HMAC_SHA1 *)EVP_CIPHER_CTX_get_cipher_data(ctx)) + +static int aesni_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX *ctx, + const unsigned char *inkey, + const unsigned char *iv, int enc) +{ + EVP_AES_HMAC_SHA1 *key = data(ctx); + int ret; + + if (enc) + ret = aesni_set_encrypt_key(inkey, + EVP_CIPHER_CTX_key_length(ctx) * 8, + &key->ks); + else + ret = aesni_set_decrypt_key(inkey, + EVP_CIPHER_CTX_key_length(ctx) * 8, + &key->ks); + + SHA1_Init(&key->head); /* handy when benchmarking */ + key->tail = key->head; + key->md = key->head; + + key->payload_length = NO_PAYLOAD_LENGTH; + + return ret < 0 ? 0 : 1; +} + +# define STITCHED_CALL +# undef STITCHED_DECRYPT_CALL + +# if !defined(STITCHED_CALL) +# define aes_off 0 +# endif + +void sha1_block_data_order(void *c, const void *p, size_t len); + +static void sha1_update(SHA_CTX *c, const void *data, size_t len) +{ + const unsigned char *ptr = data; + size_t res; + + if ((res = c->num)) { + res = SHA_CBLOCK - res; + if (len < res) + res = len; + SHA1_Update(c, ptr, res); + ptr += res; + len -= res; + } + + res = len % SHA_CBLOCK; + len -= res; + + if (len) { + sha1_block_data_order(c, ptr, len / SHA_CBLOCK); + + ptr += len; + c->Nh += len >> 29; + c->Nl += len <<= 3; + if (c->Nl < (unsigned int)len) + c->Nh++; + } + + if (res) + SHA1_Update(c, ptr, res); +} + +# ifdef SHA1_Update +# undef SHA1_Update +# endif +# define SHA1_Update sha1_update + +# if !defined(OPENSSL_NO_MULTIBLOCK) + +typedef struct { + unsigned int A[8], B[8], C[8], D[8], E[8]; +} SHA1_MB_CTX; +typedef struct { + const unsigned char *ptr; + int blocks; +} HASH_DESC; + +void sha1_multi_block(SHA1_MB_CTX *, const HASH_DESC *, int); + +typedef struct { + const unsigned char *inp; + unsigned char *out; + int blocks; + u64 iv[2]; +} CIPH_DESC; + +void aesni_multi_cbc_encrypt(CIPH_DESC *, void *, int); + +static size_t tls1_1_multi_block_encrypt(EVP_AES_HMAC_SHA1 *key, + unsigned char *out, + const unsigned char *inp, + size_t inp_len, int n4x) +{ /* n4x is 1 or 2 */ + HASH_DESC hash_d[8], edges[8]; + CIPH_DESC ciph_d[8]; + unsigned char storage[sizeof(SHA1_MB_CTX) + 32]; + union { + u64 q[16]; + u32 d[32]; + u8 c[128]; + } blocks[8]; + SHA1_MB_CTX *ctx; + unsigned int frag, last, packlen, i, x4 = 4 * n4x, minblocks, processed = + 0; + size_t ret = 0; + u8 *IVs; +# if defined(BSWAP8) + u64 seqnum; +# endif + + /* ask for IVs in bulk */ + if (RAND_bytes((IVs = blocks[0].c), 16 * x4) <= 0) + return 0; + + ctx = (SHA1_MB_CTX *) (storage + 32 - ((size_t)storage % 32)); /* align */ + + frag = (unsigned int)inp_len >> (1 + n4x); + last = (unsigned int)inp_len + frag - (frag << (1 + n4x)); + if (last > frag && ((last + 13 + 9) % 64) < (x4 - 1)) { + frag++; + last -= x4 - 1; + } + + packlen = 5 + 16 + ((frag + 20 + 16) & -16); + + /* populate descriptors with pointers and IVs */ + hash_d[0].ptr = inp; + ciph_d[0].inp = inp; + /* 5+16 is place for header and explicit IV */ + ciph_d[0].out = out + 5 + 16; + memcpy(ciph_d[0].out - 16, IVs, 16); + memcpy(ciph_d[0].iv, IVs, 16); + IVs += 16; + + for (i = 1; i < x4; i++) { + ciph_d[i].inp = hash_d[i].ptr = hash_d[i - 1].ptr + frag; + ciph_d[i].out = ciph_d[i - 1].out + packlen; + memcpy(ciph_d[i].out - 16, IVs, 16); + memcpy(ciph_d[i].iv, IVs, 16); + IVs += 16; + } + +# if defined(BSWAP8) + memcpy(blocks[0].c, key->md.data, 8); + seqnum = BSWAP8(blocks[0].q[0]); +# endif + for (i = 0; i < x4; i++) { + unsigned int len = (i == (x4 - 1) ? last : frag); +# if !defined(BSWAP8) + unsigned int carry, j; +# endif + + ctx->A[i] = key->md.h0; + ctx->B[i] = key->md.h1; + ctx->C[i] = key->md.h2; + ctx->D[i] = key->md.h3; + ctx->E[i] = key->md.h4; + + /* fix seqnum */ +# if defined(BSWAP8) + blocks[i].q[0] = BSWAP8(seqnum + i); +# else + for (carry = i, j = 8; j--;) { + blocks[i].c[j] = ((u8 *)key->md.data)[j] + carry; + carry = (blocks[i].c[j] - carry) >> (sizeof(carry) * 8 - 1); + } +# endif + blocks[i].c[8] = ((u8 *)key->md.data)[8]; + blocks[i].c[9] = ((u8 *)key->md.data)[9]; + blocks[i].c[10] = ((u8 *)key->md.data)[10]; + /* fix length */ + blocks[i].c[11] = (u8)(len >> 8); + blocks[i].c[12] = (u8)(len); + + memcpy(blocks[i].c + 13, hash_d[i].ptr, 64 - 13); + hash_d[i].ptr += 64 - 13; + hash_d[i].blocks = (len - (64 - 13)) / 64; + + edges[i].ptr = blocks[i].c; + edges[i].blocks = 1; + } + + /* hash 13-byte headers and first 64-13 bytes of inputs */ + sha1_multi_block(ctx, edges, n4x); + /* hash bulk inputs */ +# define MAXCHUNKSIZE 2048 +# if MAXCHUNKSIZE%64 +# error "MAXCHUNKSIZE is not divisible by 64" +# elif MAXCHUNKSIZE + /* + * goal is to minimize pressure on L1 cache by moving in shorter steps, + * so that hashed data is still in the cache by the time we encrypt it + */ + minblocks = ((frag <= last ? frag : last) - (64 - 13)) / 64; + if (minblocks > MAXCHUNKSIZE / 64) { + for (i = 0; i < x4; i++) { + edges[i].ptr = hash_d[i].ptr; + edges[i].blocks = MAXCHUNKSIZE / 64; + ciph_d[i].blocks = MAXCHUNKSIZE / 16; + } + do { + sha1_multi_block(ctx, edges, n4x); + aesni_multi_cbc_encrypt(ciph_d, &key->ks, n4x); + + for (i = 0; i < x4; i++) { + edges[i].ptr = hash_d[i].ptr += MAXCHUNKSIZE; + hash_d[i].blocks -= MAXCHUNKSIZE / 64; + edges[i].blocks = MAXCHUNKSIZE / 64; + ciph_d[i].inp += MAXCHUNKSIZE; + ciph_d[i].out += MAXCHUNKSIZE; + ciph_d[i].blocks = MAXCHUNKSIZE / 16; + memcpy(ciph_d[i].iv, ciph_d[i].out - 16, 16); + } + processed += MAXCHUNKSIZE; + minblocks -= MAXCHUNKSIZE / 64; + } while (minblocks > MAXCHUNKSIZE / 64); + } +# endif +# undef MAXCHUNKSIZE + sha1_multi_block(ctx, hash_d, n4x); + + memset(blocks, 0, sizeof(blocks)); + for (i = 0; i < x4; i++) { + unsigned int len = (i == (x4 - 1) ? last : frag), + off = hash_d[i].blocks * 64; + const unsigned char *ptr = hash_d[i].ptr + off; + + off = (len - processed) - (64 - 13) - off; /* remainder actually */ + memcpy(blocks[i].c, ptr, off); + blocks[i].c[off] = 0x80; + len += 64 + 13; /* 64 is HMAC header */ + len *= 8; /* convert to bits */ + if (off < (64 - 8)) { +# ifdef BSWAP4 + blocks[i].d[15] = BSWAP4(len); +# else + PUTU32(blocks[i].c + 60, len); +# endif + edges[i].blocks = 1; + } else { +# ifdef BSWAP4 + blocks[i].d[31] = BSWAP4(len); +# else + PUTU32(blocks[i].c + 124, len); +# endif + edges[i].blocks = 2; + } + edges[i].ptr = blocks[i].c; + } + + /* hash input tails and finalize */ + sha1_multi_block(ctx, edges, n4x); + + memset(blocks, 0, sizeof(blocks)); + for (i = 0; i < x4; i++) { +# ifdef BSWAP4 + blocks[i].d[0] = BSWAP4(ctx->A[i]); + ctx->A[i] = key->tail.h0; + blocks[i].d[1] = BSWAP4(ctx->B[i]); + ctx->B[i] = key->tail.h1; + blocks[i].d[2] = BSWAP4(ctx->C[i]); + ctx->C[i] = key->tail.h2; + blocks[i].d[3] = BSWAP4(ctx->D[i]); + ctx->D[i] = key->tail.h3; + blocks[i].d[4] = BSWAP4(ctx->E[i]); + ctx->E[i] = key->tail.h4; + blocks[i].c[20] = 0x80; + blocks[i].d[15] = BSWAP4((64 + 20) * 8); +# else + PUTU32(blocks[i].c + 0, ctx->A[i]); + ctx->A[i] = key->tail.h0; + PUTU32(blocks[i].c + 4, ctx->B[i]); + ctx->B[i] = key->tail.h1; + PUTU32(blocks[i].c + 8, ctx->C[i]); + ctx->C[i] = key->tail.h2; + PUTU32(blocks[i].c + 12, ctx->D[i]); + ctx->D[i] = key->tail.h3; + PUTU32(blocks[i].c + 16, ctx->E[i]); + ctx->E[i] = key->tail.h4; + blocks[i].c[20] = 0x80; + PUTU32(blocks[i].c + 60, (64 + 20) * 8); +# endif + edges[i].ptr = blocks[i].c; + edges[i].blocks = 1; + } + + /* finalize MACs */ + sha1_multi_block(ctx, edges, n4x); + + for (i = 0; i < x4; i++) { + unsigned int len = (i == (x4 - 1) ? last : frag), pad, j; + unsigned char *out0 = out; + + memcpy(ciph_d[i].out, ciph_d[i].inp, len - processed); + ciph_d[i].inp = ciph_d[i].out; + + out += 5 + 16 + len; + + /* write MAC */ + PUTU32(out + 0, ctx->A[i]); + PUTU32(out + 4, ctx->B[i]); + PUTU32(out + 8, ctx->C[i]); + PUTU32(out + 12, ctx->D[i]); + PUTU32(out + 16, ctx->E[i]); + out += 20; + len += 20; + + /* pad */ + pad = 15 - len % 16; + for (j = 0; j <= pad; j++) + *(out++) = pad; + len += pad + 1; + + ciph_d[i].blocks = (len - processed) / 16; + len += 16; /* account for explicit iv */ + + /* arrange header */ + out0[0] = ((u8 *)key->md.data)[8]; + out0[1] = ((u8 *)key->md.data)[9]; + out0[2] = ((u8 *)key->md.data)[10]; + out0[3] = (u8)(len >> 8); + out0[4] = (u8)(len); + + ret += len + 5; + inp += frag; + } + + aesni_multi_cbc_encrypt(ciph_d, &key->ks, n4x); + + OPENSSL_cleanse(blocks, sizeof(blocks)); + OPENSSL_cleanse(ctx, sizeof(*ctx)); + + return ret; +} +# endif + +static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_AES_HMAC_SHA1 *key = data(ctx); + unsigned int l; + size_t plen = key->payload_length, iv = 0, /* explicit IV in TLS 1.1 and + * later */ + sha_off = 0; +# if defined(STITCHED_CALL) + size_t aes_off = 0, blocks; + + sha_off = SHA_CBLOCK - key->md.num; +# endif + + key->payload_length = NO_PAYLOAD_LENGTH; + + if (len % AES_BLOCK_SIZE) + return 0; + + if (EVP_CIPHER_CTX_encrypting(ctx)) { + if (plen == NO_PAYLOAD_LENGTH) + plen = len; + else if (len != + ((plen + SHA_DIGEST_LENGTH + + AES_BLOCK_SIZE) & -AES_BLOCK_SIZE)) + return 0; + else if (key->aux.tls_ver >= TLS1_1_VERSION) + iv = AES_BLOCK_SIZE; + +# if defined(STITCHED_CALL) + if (plen > (sha_off + iv) + && (blocks = (plen - (sha_off + iv)) / SHA_CBLOCK)) { + SHA1_Update(&key->md, in + iv, sha_off); + + aesni_cbc_sha1_enc(in, out, blocks, &key->ks, + EVP_CIPHER_CTX_iv_noconst(ctx), + &key->md, in + iv + sha_off); + blocks *= SHA_CBLOCK; + aes_off += blocks; + sha_off += blocks; + key->md.Nh += blocks >> 29; + key->md.Nl += blocks <<= 3; + if (key->md.Nl < (unsigned int)blocks) + key->md.Nh++; + } else { + sha_off = 0; + } +# endif + sha_off += iv; + SHA1_Update(&key->md, in + sha_off, plen - sha_off); + + if (plen != len) { /* "TLS" mode of operation */ + if (in != out) + memcpy(out + aes_off, in + aes_off, plen - aes_off); + + /* calculate HMAC and append it to payload */ + SHA1_Final(out + plen, &key->md); + key->md = key->tail; + SHA1_Update(&key->md, out + plen, SHA_DIGEST_LENGTH); + SHA1_Final(out + plen, &key->md); + + /* pad the payload|hmac */ + plen += SHA_DIGEST_LENGTH; + for (l = len - plen - 1; plen < len; plen++) + out[plen] = l; + /* encrypt HMAC|padding at once */ + aesni_cbc_encrypt(out + aes_off, out + aes_off, len - aes_off, + &key->ks, EVP_CIPHER_CTX_iv_noconst(ctx), 1); + } else { + aesni_cbc_encrypt(in + aes_off, out + aes_off, len - aes_off, + &key->ks, EVP_CIPHER_CTX_iv_noconst(ctx), 1); + } + } else { + union { + unsigned int u[SHA_DIGEST_LENGTH / sizeof(unsigned int)]; + unsigned char c[32 + SHA_DIGEST_LENGTH]; + } mac, *pmac; + + /* arrange cache line alignment */ + pmac = (void *)(((size_t)mac.c + 31) & ((size_t)0 - 32)); + + if (plen != NO_PAYLOAD_LENGTH) { /* "TLS" mode of operation */ + size_t inp_len, mask, j, i; + unsigned int res, maxpad, pad, bitlen; + int ret = 1; + union { + unsigned int u[SHA_LBLOCK]; + unsigned char c[SHA_CBLOCK]; + } *data = (void *)key->md.data; +# if defined(STITCHED_DECRYPT_CALL) + unsigned char tail_iv[AES_BLOCK_SIZE]; + int stitch = 0; +# endif + + if ((key->aux.tls_aad[plen - 4] << 8 | key->aux.tls_aad[plen - 3]) + >= TLS1_1_VERSION) { + if (len < (AES_BLOCK_SIZE + SHA_DIGEST_LENGTH + 1)) + return 0; + + /* omit explicit iv */ + memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), in, AES_BLOCK_SIZE); + + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + len -= AES_BLOCK_SIZE; + } else if (len < (SHA_DIGEST_LENGTH + 1)) + return 0; + +# if defined(STITCHED_DECRYPT_CALL) + if (len >= 1024 && ctx->key_len == 32) { + /* decrypt last block */ + memcpy(tail_iv, in + len - 2 * AES_BLOCK_SIZE, + AES_BLOCK_SIZE); + aesni_cbc_encrypt(in + len - AES_BLOCK_SIZE, + out + len - AES_BLOCK_SIZE, AES_BLOCK_SIZE, + &key->ks, tail_iv, 0); + stitch = 1; + } else +# endif + /* decrypt HMAC|padding at once */ + aesni_cbc_encrypt(in, out, len, &key->ks, + EVP_CIPHER_CTX_iv_noconst(ctx), 0); + + /* figure out payload length */ + pad = out[len - 1]; + maxpad = len - (SHA_DIGEST_LENGTH + 1); + maxpad |= (255 - maxpad) >> (sizeof(maxpad) * 8 - 8); + maxpad &= 255; + + mask = constant_time_ge(maxpad, pad); + ret &= mask; + /* + * If pad is invalid then we will fail the above test but we must + * continue anyway because we are in constant time code. However, + * we'll use the maxpad value instead of the supplied pad to make + * sure we perform well defined pointer arithmetic. + */ + pad = constant_time_select(mask, pad, maxpad); + + inp_len = len - (SHA_DIGEST_LENGTH + pad + 1); + + key->aux.tls_aad[plen - 2] = inp_len >> 8; + key->aux.tls_aad[plen - 1] = inp_len; + + /* calculate HMAC */ + key->md = key->head; + SHA1_Update(&key->md, key->aux.tls_aad, plen); + +# if defined(STITCHED_DECRYPT_CALL) + if (stitch) { + blocks = (len - (256 + 32 + SHA_CBLOCK)) / SHA_CBLOCK; + aes_off = len - AES_BLOCK_SIZE - blocks * SHA_CBLOCK; + sha_off = SHA_CBLOCK - plen; + + aesni_cbc_encrypt(in, out, aes_off, &key->ks, ctx->iv, 0); + + SHA1_Update(&key->md, out, sha_off); + aesni256_cbc_sha1_dec(in + aes_off, + out + aes_off, blocks, &key->ks, + ctx->iv, &key->md, out + sha_off); + + sha_off += blocks *= SHA_CBLOCK; + out += sha_off; + len -= sha_off; + inp_len -= sha_off; + + key->md.Nl += (blocks << 3); /* at most 18 bits */ + memcpy(ctx->iv, tail_iv, AES_BLOCK_SIZE); + } +# endif + +# if 1 /* see original reference version in #else */ + len -= SHA_DIGEST_LENGTH; /* amend mac */ + if (len >= (256 + SHA_CBLOCK)) { + j = (len - (256 + SHA_CBLOCK)) & (0 - SHA_CBLOCK); + j += SHA_CBLOCK - key->md.num; + SHA1_Update(&key->md, out, j); + out += j; + len -= j; + inp_len -= j; + } + + /* but pretend as if we hashed padded payload */ + bitlen = key->md.Nl + (inp_len << 3); /* at most 18 bits */ +# ifdef BSWAP4 + bitlen = BSWAP4(bitlen); +# else + mac.c[0] = 0; + mac.c[1] = (unsigned char)(bitlen >> 16); + mac.c[2] = (unsigned char)(bitlen >> 8); + mac.c[3] = (unsigned char)bitlen; + bitlen = mac.u[0]; +# endif + + pmac->u[0] = 0; + pmac->u[1] = 0; + pmac->u[2] = 0; + pmac->u[3] = 0; + pmac->u[4] = 0; + + for (res = key->md.num, j = 0; j < len; j++) { + size_t c = out[j]; + mask = (j - inp_len) >> (sizeof(j) * 8 - 8); + c &= mask; + c |= 0x80 & ~mask & ~((inp_len - j) >> (sizeof(j) * 8 - 8)); + data->c[res++] = (unsigned char)c; + + if (res != SHA_CBLOCK) + continue; + + /* j is not incremented yet */ + mask = 0 - ((inp_len + 7 - j) >> (sizeof(j) * 8 - 1)); + data->u[SHA_LBLOCK - 1] |= bitlen & mask; + sha1_block_data_order(&key->md, data, 1); + mask &= 0 - ((j - inp_len - 72) >> (sizeof(j) * 8 - 1)); + pmac->u[0] |= key->md.h0 & mask; + pmac->u[1] |= key->md.h1 & mask; + pmac->u[2] |= key->md.h2 & mask; + pmac->u[3] |= key->md.h3 & mask; + pmac->u[4] |= key->md.h4 & mask; + res = 0; + } + + for (i = res; i < SHA_CBLOCK; i++, j++) + data->c[i] = 0; + + if (res > SHA_CBLOCK - 8) { + mask = 0 - ((inp_len + 8 - j) >> (sizeof(j) * 8 - 1)); + data->u[SHA_LBLOCK - 1] |= bitlen & mask; + sha1_block_data_order(&key->md, data, 1); + mask &= 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1)); + pmac->u[0] |= key->md.h0 & mask; + pmac->u[1] |= key->md.h1 & mask; + pmac->u[2] |= key->md.h2 & mask; + pmac->u[3] |= key->md.h3 & mask; + pmac->u[4] |= key->md.h4 & mask; + + memset(data, 0, SHA_CBLOCK); + j += 64; + } + data->u[SHA_LBLOCK - 1] = bitlen; + sha1_block_data_order(&key->md, data, 1); + mask = 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1)); + pmac->u[0] |= key->md.h0 & mask; + pmac->u[1] |= key->md.h1 & mask; + pmac->u[2] |= key->md.h2 & mask; + pmac->u[3] |= key->md.h3 & mask; + pmac->u[4] |= key->md.h4 & mask; + +# ifdef BSWAP4 + pmac->u[0] = BSWAP4(pmac->u[0]); + pmac->u[1] = BSWAP4(pmac->u[1]); + pmac->u[2] = BSWAP4(pmac->u[2]); + pmac->u[3] = BSWAP4(pmac->u[3]); + pmac->u[4] = BSWAP4(pmac->u[4]); +# else + for (i = 0; i < 5; i++) { + res = pmac->u[i]; + pmac->c[4 * i + 0] = (unsigned char)(res >> 24); + pmac->c[4 * i + 1] = (unsigned char)(res >> 16); + pmac->c[4 * i + 2] = (unsigned char)(res >> 8); + pmac->c[4 * i + 3] = (unsigned char)res; + } +# endif + len += SHA_DIGEST_LENGTH; +# else /* pre-lucky-13 reference version of above */ + SHA1_Update(&key->md, out, inp_len); + res = key->md.num; + SHA1_Final(pmac->c, &key->md); + + { + unsigned int inp_blocks, pad_blocks; + + /* but pretend as if we hashed padded payload */ + inp_blocks = + 1 + ((SHA_CBLOCK - 9 - res) >> (sizeof(res) * 8 - 1)); + res += (unsigned int)(len - inp_len); + pad_blocks = res / SHA_CBLOCK; + res %= SHA_CBLOCK; + pad_blocks += + 1 + ((SHA_CBLOCK - 9 - res) >> (sizeof(res) * 8 - 1)); + for (; inp_blocks < pad_blocks; inp_blocks++) + sha1_block_data_order(&key->md, data, 1); + } +# endif + key->md = key->tail; + SHA1_Update(&key->md, pmac->c, SHA_DIGEST_LENGTH); + SHA1_Final(pmac->c, &key->md); + + /* verify HMAC */ + out += inp_len; + len -= inp_len; +# if 1 /* see original reference version in #else */ + { + unsigned char *p = out + len - 1 - maxpad - SHA_DIGEST_LENGTH; + size_t off = out - p; + unsigned int c, cmask; + + maxpad += SHA_DIGEST_LENGTH; + for (res = 0, i = 0, j = 0; j < maxpad; j++) { + c = p[j]; + cmask = + ((int)(j - off - SHA_DIGEST_LENGTH)) >> (sizeof(int) * + 8 - 1); + res |= (c ^ pad) & ~cmask; /* ... and padding */ + cmask &= ((int)(off - 1 - j)) >> (sizeof(int) * 8 - 1); + res |= (c ^ pmac->c[i]) & cmask; + i += 1 & cmask; + } + maxpad -= SHA_DIGEST_LENGTH; + + res = 0 - ((0 - res) >> (sizeof(res) * 8 - 1)); + ret &= (int)~res; + } +# else /* pre-lucky-13 reference version of above */ + for (res = 0, i = 0; i < SHA_DIGEST_LENGTH; i++) + res |= out[i] ^ pmac->c[i]; + res = 0 - ((0 - res) >> (sizeof(res) * 8 - 1)); + ret &= (int)~res; + + /* verify padding */ + pad = (pad & ~res) | (maxpad & res); + out = out + len - 1 - pad; + for (res = 0, i = 0; i < pad; i++) + res |= out[i] ^ pad; + + res = (0 - res) >> (sizeof(res) * 8 - 1); + ret &= (int)~res; +# endif + return ret; + } else { +# if defined(STITCHED_DECRYPT_CALL) + if (len >= 1024 && ctx->key_len == 32) { + if (sha_off %= SHA_CBLOCK) + blocks = (len - 3 * SHA_CBLOCK) / SHA_CBLOCK; + else + blocks = (len - 2 * SHA_CBLOCK) / SHA_CBLOCK; + aes_off = len - blocks * SHA_CBLOCK; + + aesni_cbc_encrypt(in, out, aes_off, &key->ks, ctx->iv, 0); + SHA1_Update(&key->md, out, sha_off); + aesni256_cbc_sha1_dec(in + aes_off, + out + aes_off, blocks, &key->ks, + ctx->iv, &key->md, out + sha_off); + + sha_off += blocks *= SHA_CBLOCK; + out += sha_off; + len -= sha_off; + + key->md.Nh += blocks >> 29; + key->md.Nl += blocks <<= 3; + if (key->md.Nl < (unsigned int)blocks) + key->md.Nh++; + } else +# endif + /* decrypt HMAC|padding at once */ + aesni_cbc_encrypt(in, out, len, &key->ks, + EVP_CIPHER_CTX_iv_noconst(ctx), 0); + + SHA1_Update(&key->md, out, len); + } + } + + return 1; +} + +static int aesni_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, + void *ptr) +{ + EVP_AES_HMAC_SHA1 *key = data(ctx); + + switch (type) { + case EVP_CTRL_AEAD_SET_MAC_KEY: + { + unsigned int i; + unsigned char hmac_key[64]; + + memset(hmac_key, 0, sizeof(hmac_key)); + + if (arg > (int)sizeof(hmac_key)) { + SHA1_Init(&key->head); + SHA1_Update(&key->head, ptr, arg); + SHA1_Final(hmac_key, &key->head); + } else { + memcpy(hmac_key, ptr, arg); + } + + for (i = 0; i < sizeof(hmac_key); i++) + hmac_key[i] ^= 0x36; /* ipad */ + SHA1_Init(&key->head); + SHA1_Update(&key->head, hmac_key, sizeof(hmac_key)); + + for (i = 0; i < sizeof(hmac_key); i++) + hmac_key[i] ^= 0x36 ^ 0x5c; /* opad */ + SHA1_Init(&key->tail); + SHA1_Update(&key->tail, hmac_key, sizeof(hmac_key)); + + OPENSSL_cleanse(hmac_key, sizeof(hmac_key)); + + return 1; + } + case EVP_CTRL_AEAD_TLS1_AAD: + { + unsigned char *p = ptr; + unsigned int len; + + if (arg != EVP_AEAD_TLS1_AAD_LEN) + return -1; + + len = p[arg - 2] << 8 | p[arg - 1]; + + if (EVP_CIPHER_CTX_encrypting(ctx)) { + key->payload_length = len; + if ((key->aux.tls_ver = + p[arg - 4] << 8 | p[arg - 3]) >= TLS1_1_VERSION) { + if (len < AES_BLOCK_SIZE) + return 0; + len -= AES_BLOCK_SIZE; + p[arg - 2] = len >> 8; + p[arg - 1] = len; + } + key->md = key->head; + SHA1_Update(&key->md, p, arg); + + return (int)(((len + SHA_DIGEST_LENGTH + + AES_BLOCK_SIZE) & -AES_BLOCK_SIZE) + - len); + } else { + memcpy(key->aux.tls_aad, ptr, arg); + key->payload_length = arg; + + return SHA_DIGEST_LENGTH; + } + } +# if !defined(OPENSSL_NO_MULTIBLOCK) + case EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE: + return (int)(5 + 16 + ((arg + 20 + 16) & -16)); + case EVP_CTRL_TLS1_1_MULTIBLOCK_AAD: + { + EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param = + (EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *) ptr; + unsigned int n4x = 1, x4; + unsigned int frag, last, packlen, inp_len; + + if (arg < (int)sizeof(EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM)) + return -1; + + inp_len = param->inp[11] << 8 | param->inp[12]; + + if (EVP_CIPHER_CTX_encrypting(ctx)) { + if ((param->inp[9] << 8 | param->inp[10]) < TLS1_1_VERSION) + return -1; + + if (inp_len) { + if (inp_len < 4096) + return 0; /* too short */ + + if (inp_len >= 8192 && OPENSSL_ia32cap_P[2] & (1 << 5)) + n4x = 2; /* AVX2 */ + } else if ((n4x = param->interleave / 4) && n4x <= 2) + inp_len = param->len; + else + return -1; + + key->md = key->head; + SHA1_Update(&key->md, param->inp, 13); + + x4 = 4 * n4x; + n4x += 1; + + frag = inp_len >> n4x; + last = inp_len + frag - (frag << n4x); + if (last > frag && ((last + 13 + 9) % 64 < (x4 - 1))) { + frag++; + last -= x4 - 1; + } + + packlen = 5 + 16 + ((frag + 20 + 16) & -16); + packlen = (packlen << n4x) - packlen; + packlen += 5 + 16 + ((last + 20 + 16) & -16); + + param->interleave = x4; + + return (int)packlen; + } else + return -1; /* not yet */ + } + case EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT: + { + EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param = + (EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *) ptr; + + return (int)tls1_1_multi_block_encrypt(key, param->out, + param->inp, param->len, + param->interleave / 4); + } + case EVP_CTRL_TLS1_1_MULTIBLOCK_DECRYPT: +# endif + default: + return -1; + } +} + +static EVP_CIPHER aesni_128_cbc_hmac_sha1_cipher = { +# ifdef NID_aes_128_cbc_hmac_sha1 + NID_aes_128_cbc_hmac_sha1, +# else + NID_undef, +# endif + AES_BLOCK_SIZE, 16, AES_BLOCK_SIZE, + EVP_CIPH_CBC_MODE | EVP_CIPH_FLAG_DEFAULT_ASN1 | + EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK, + aesni_cbc_hmac_sha1_init_key, + aesni_cbc_hmac_sha1_cipher, + NULL, + sizeof(EVP_AES_HMAC_SHA1), + EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_set_asn1_iv, + EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_get_asn1_iv, + aesni_cbc_hmac_sha1_ctrl, + NULL +}; + +static EVP_CIPHER aesni_256_cbc_hmac_sha1_cipher = { +# ifdef NID_aes_256_cbc_hmac_sha1 + NID_aes_256_cbc_hmac_sha1, +# else + NID_undef, +# endif + AES_BLOCK_SIZE, 32, AES_BLOCK_SIZE, + EVP_CIPH_CBC_MODE | EVP_CIPH_FLAG_DEFAULT_ASN1 | + EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK, + aesni_cbc_hmac_sha1_init_key, + aesni_cbc_hmac_sha1_cipher, + NULL, + sizeof(EVP_AES_HMAC_SHA1), + EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_set_asn1_iv, + EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_get_asn1_iv, + aesni_cbc_hmac_sha1_ctrl, + NULL +}; + +const EVP_CIPHER *EVP_aes_128_cbc_hmac_sha1(void) +{ + return (OPENSSL_ia32cap_P[1] & AESNI_CAPABLE ? + &aesni_128_cbc_hmac_sha1_cipher : NULL); +} + +const EVP_CIPHER *EVP_aes_256_cbc_hmac_sha1(void) +{ + return (OPENSSL_ia32cap_P[1] & AESNI_CAPABLE ? + &aesni_256_cbc_hmac_sha1_cipher : NULL); +} +#else +const EVP_CIPHER *EVP_aes_128_cbc_hmac_sha1(void) +{ + return NULL; +} + +const EVP_CIPHER *EVP_aes_256_cbc_hmac_sha1(void) +{ + return NULL; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_aes_cbc_hmac_sha256.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_aes_cbc_hmac_sha256.c new file mode 100644 index 000000000..caac0c9d3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_aes_cbc_hmac_sha256.c @@ -0,0 +1,950 @@ +/* + * Copyright 2013-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#include +#include + + +#include +#include +#include +#include +#include +#include "modes_lcl.h" +#include "internal/constant_time_locl.h" +#include "internal/evp_int.h" + +typedef struct { + AES_KEY ks; + SHA256_CTX head, tail, md; + size_t payload_length; /* AAD length in decrypt case */ + union { + unsigned int tls_ver; + unsigned char tls_aad[16]; /* 13 used */ + } aux; +} EVP_AES_HMAC_SHA256; + +# define NO_PAYLOAD_LENGTH ((size_t)-1) + +#if defined(AES_ASM) && ( \ + defined(__x86_64) || defined(__x86_64__) || \ + defined(_M_AMD64) || defined(_M_X64) ) + +extern unsigned int OPENSSL_ia32cap_P[]; +# define AESNI_CAPABLE (1<<(57-32)) + +int aesni_set_encrypt_key(const unsigned char *userKey, int bits, + AES_KEY *key); +int aesni_set_decrypt_key(const unsigned char *userKey, int bits, + AES_KEY *key); + +void aesni_cbc_encrypt(const unsigned char *in, + unsigned char *out, + size_t length, + const AES_KEY *key, unsigned char *ivec, int enc); + +int aesni_cbc_sha256_enc(const void *inp, void *out, size_t blocks, + const AES_KEY *key, unsigned char iv[16], + SHA256_CTX *ctx, const void *in0); + +# define data(ctx) ((EVP_AES_HMAC_SHA256 *)EVP_CIPHER_CTX_get_cipher_data(ctx)) + +static int aesni_cbc_hmac_sha256_init_key(EVP_CIPHER_CTX *ctx, + const unsigned char *inkey, + const unsigned char *iv, int enc) +{ + EVP_AES_HMAC_SHA256 *key = data(ctx); + int ret; + + if (enc) + ret = aesni_set_encrypt_key(inkey, + EVP_CIPHER_CTX_key_length(ctx) * 8, + &key->ks); + else + ret = aesni_set_decrypt_key(inkey, + EVP_CIPHER_CTX_key_length(ctx) * 8, + &key->ks); + + SHA256_Init(&key->head); /* handy when benchmarking */ + key->tail = key->head; + key->md = key->head; + + key->payload_length = NO_PAYLOAD_LENGTH; + + return ret < 0 ? 0 : 1; +} + +# define STITCHED_CALL + +# if !defined(STITCHED_CALL) +# define aes_off 0 +# endif + +void sha256_block_data_order(void *c, const void *p, size_t len); + +static void sha256_update(SHA256_CTX *c, const void *data, size_t len) +{ + const unsigned char *ptr = data; + size_t res; + + if ((res = c->num)) { + res = SHA256_CBLOCK - res; + if (len < res) + res = len; + SHA256_Update(c, ptr, res); + ptr += res; + len -= res; + } + + res = len % SHA256_CBLOCK; + len -= res; + + if (len) { + sha256_block_data_order(c, ptr, len / SHA256_CBLOCK); + + ptr += len; + c->Nh += len >> 29; + c->Nl += len <<= 3; + if (c->Nl < (unsigned int)len) + c->Nh++; + } + + if (res) + SHA256_Update(c, ptr, res); +} + +# ifdef SHA256_Update +# undef SHA256_Update +# endif +# define SHA256_Update sha256_update + +# if !defined(OPENSSL_NO_MULTIBLOCK) + +typedef struct { + unsigned int A[8], B[8], C[8], D[8], E[8], F[8], G[8], H[8]; +} SHA256_MB_CTX; +typedef struct { + const unsigned char *ptr; + int blocks; +} HASH_DESC; + +void sha256_multi_block(SHA256_MB_CTX *, const HASH_DESC *, int); + +typedef struct { + const unsigned char *inp; + unsigned char *out; + int blocks; + u64 iv[2]; +} CIPH_DESC; + +void aesni_multi_cbc_encrypt(CIPH_DESC *, void *, int); + +static size_t tls1_1_multi_block_encrypt(EVP_AES_HMAC_SHA256 *key, + unsigned char *out, + const unsigned char *inp, + size_t inp_len, int n4x) +{ /* n4x is 1 or 2 */ + HASH_DESC hash_d[8], edges[8]; + CIPH_DESC ciph_d[8]; + unsigned char storage[sizeof(SHA256_MB_CTX) + 32]; + union { + u64 q[16]; + u32 d[32]; + u8 c[128]; + } blocks[8]; + SHA256_MB_CTX *ctx; + unsigned int frag, last, packlen, i, x4 = 4 * n4x, minblocks, processed = + 0; + size_t ret = 0; + u8 *IVs; +# if defined(BSWAP8) + u64 seqnum; +# endif + + /* ask for IVs in bulk */ + if (RAND_bytes((IVs = blocks[0].c), 16 * x4) <= 0) + return 0; + + /* align */ + ctx = (SHA256_MB_CTX *) (storage + 32 - ((size_t)storage % 32)); + + frag = (unsigned int)inp_len >> (1 + n4x); + last = (unsigned int)inp_len + frag - (frag << (1 + n4x)); + if (last > frag && ((last + 13 + 9) % 64) < (x4 - 1)) { + frag++; + last -= x4 - 1; + } + + packlen = 5 + 16 + ((frag + 32 + 16) & -16); + + /* populate descriptors with pointers and IVs */ + hash_d[0].ptr = inp; + ciph_d[0].inp = inp; + /* 5+16 is place for header and explicit IV */ + ciph_d[0].out = out + 5 + 16; + memcpy(ciph_d[0].out - 16, IVs, 16); + memcpy(ciph_d[0].iv, IVs, 16); + IVs += 16; + + for (i = 1; i < x4; i++) { + ciph_d[i].inp = hash_d[i].ptr = hash_d[i - 1].ptr + frag; + ciph_d[i].out = ciph_d[i - 1].out + packlen; + memcpy(ciph_d[i].out - 16, IVs, 16); + memcpy(ciph_d[i].iv, IVs, 16); + IVs += 16; + } + +# if defined(BSWAP8) + memcpy(blocks[0].c, key->md.data, 8); + seqnum = BSWAP8(blocks[0].q[0]); +# endif + for (i = 0; i < x4; i++) { + unsigned int len = (i == (x4 - 1) ? last : frag); +# if !defined(BSWAP8) + unsigned int carry, j; +# endif + + ctx->A[i] = key->md.h[0]; + ctx->B[i] = key->md.h[1]; + ctx->C[i] = key->md.h[2]; + ctx->D[i] = key->md.h[3]; + ctx->E[i] = key->md.h[4]; + ctx->F[i] = key->md.h[5]; + ctx->G[i] = key->md.h[6]; + ctx->H[i] = key->md.h[7]; + + /* fix seqnum */ +# if defined(BSWAP8) + blocks[i].q[0] = BSWAP8(seqnum + i); +# else + for (carry = i, j = 8; j--;) { + blocks[i].c[j] = ((u8 *)key->md.data)[j] + carry; + carry = (blocks[i].c[j] - carry) >> (sizeof(carry) * 8 - 1); + } +# endif + blocks[i].c[8] = ((u8 *)key->md.data)[8]; + blocks[i].c[9] = ((u8 *)key->md.data)[9]; + blocks[i].c[10] = ((u8 *)key->md.data)[10]; + /* fix length */ + blocks[i].c[11] = (u8)(len >> 8); + blocks[i].c[12] = (u8)(len); + + memcpy(blocks[i].c + 13, hash_d[i].ptr, 64 - 13); + hash_d[i].ptr += 64 - 13; + hash_d[i].blocks = (len - (64 - 13)) / 64; + + edges[i].ptr = blocks[i].c; + edges[i].blocks = 1; + } + + /* hash 13-byte headers and first 64-13 bytes of inputs */ + sha256_multi_block(ctx, edges, n4x); + /* hash bulk inputs */ +# define MAXCHUNKSIZE 2048 +# if MAXCHUNKSIZE%64 +# error "MAXCHUNKSIZE is not divisible by 64" +# elif MAXCHUNKSIZE + /* + * goal is to minimize pressure on L1 cache by moving in shorter steps, + * so that hashed data is still in the cache by the time we encrypt it + */ + minblocks = ((frag <= last ? frag : last) - (64 - 13)) / 64; + if (minblocks > MAXCHUNKSIZE / 64) { + for (i = 0; i < x4; i++) { + edges[i].ptr = hash_d[i].ptr; + edges[i].blocks = MAXCHUNKSIZE / 64; + ciph_d[i].blocks = MAXCHUNKSIZE / 16; + } + do { + sha256_multi_block(ctx, edges, n4x); + aesni_multi_cbc_encrypt(ciph_d, &key->ks, n4x); + + for (i = 0; i < x4; i++) { + edges[i].ptr = hash_d[i].ptr += MAXCHUNKSIZE; + hash_d[i].blocks -= MAXCHUNKSIZE / 64; + edges[i].blocks = MAXCHUNKSIZE / 64; + ciph_d[i].inp += MAXCHUNKSIZE; + ciph_d[i].out += MAXCHUNKSIZE; + ciph_d[i].blocks = MAXCHUNKSIZE / 16; + memcpy(ciph_d[i].iv, ciph_d[i].out - 16, 16); + } + processed += MAXCHUNKSIZE; + minblocks -= MAXCHUNKSIZE / 64; + } while (minblocks > MAXCHUNKSIZE / 64); + } +# endif +# undef MAXCHUNKSIZE + sha256_multi_block(ctx, hash_d, n4x); + + memset(blocks, 0, sizeof(blocks)); + for (i = 0; i < x4; i++) { + unsigned int len = (i == (x4 - 1) ? last : frag), + off = hash_d[i].blocks * 64; + const unsigned char *ptr = hash_d[i].ptr + off; + + off = (len - processed) - (64 - 13) - off; /* remainder actually */ + memcpy(blocks[i].c, ptr, off); + blocks[i].c[off] = 0x80; + len += 64 + 13; /* 64 is HMAC header */ + len *= 8; /* convert to bits */ + if (off < (64 - 8)) { +# ifdef BSWAP4 + blocks[i].d[15] = BSWAP4(len); +# else + PUTU32(blocks[i].c + 60, len); +# endif + edges[i].blocks = 1; + } else { +# ifdef BSWAP4 + blocks[i].d[31] = BSWAP4(len); +# else + PUTU32(blocks[i].c + 124, len); +# endif + edges[i].blocks = 2; + } + edges[i].ptr = blocks[i].c; + } + + /* hash input tails and finalize */ + sha256_multi_block(ctx, edges, n4x); + + memset(blocks, 0, sizeof(blocks)); + for (i = 0; i < x4; i++) { +# ifdef BSWAP4 + blocks[i].d[0] = BSWAP4(ctx->A[i]); + ctx->A[i] = key->tail.h[0]; + blocks[i].d[1] = BSWAP4(ctx->B[i]); + ctx->B[i] = key->tail.h[1]; + blocks[i].d[2] = BSWAP4(ctx->C[i]); + ctx->C[i] = key->tail.h[2]; + blocks[i].d[3] = BSWAP4(ctx->D[i]); + ctx->D[i] = key->tail.h[3]; + blocks[i].d[4] = BSWAP4(ctx->E[i]); + ctx->E[i] = key->tail.h[4]; + blocks[i].d[5] = BSWAP4(ctx->F[i]); + ctx->F[i] = key->tail.h[5]; + blocks[i].d[6] = BSWAP4(ctx->G[i]); + ctx->G[i] = key->tail.h[6]; + blocks[i].d[7] = BSWAP4(ctx->H[i]); + ctx->H[i] = key->tail.h[7]; + blocks[i].c[32] = 0x80; + blocks[i].d[15] = BSWAP4((64 + 32) * 8); +# else + PUTU32(blocks[i].c + 0, ctx->A[i]); + ctx->A[i] = key->tail.h[0]; + PUTU32(blocks[i].c + 4, ctx->B[i]); + ctx->B[i] = key->tail.h[1]; + PUTU32(blocks[i].c + 8, ctx->C[i]); + ctx->C[i] = key->tail.h[2]; + PUTU32(blocks[i].c + 12, ctx->D[i]); + ctx->D[i] = key->tail.h[3]; + PUTU32(blocks[i].c + 16, ctx->E[i]); + ctx->E[i] = key->tail.h[4]; + PUTU32(blocks[i].c + 20, ctx->F[i]); + ctx->F[i] = key->tail.h[5]; + PUTU32(blocks[i].c + 24, ctx->G[i]); + ctx->G[i] = key->tail.h[6]; + PUTU32(blocks[i].c + 28, ctx->H[i]); + ctx->H[i] = key->tail.h[7]; + blocks[i].c[32] = 0x80; + PUTU32(blocks[i].c + 60, (64 + 32) * 8); +# endif + edges[i].ptr = blocks[i].c; + edges[i].blocks = 1; + } + + /* finalize MACs */ + sha256_multi_block(ctx, edges, n4x); + + for (i = 0; i < x4; i++) { + unsigned int len = (i == (x4 - 1) ? last : frag), pad, j; + unsigned char *out0 = out; + + memcpy(ciph_d[i].out, ciph_d[i].inp, len - processed); + ciph_d[i].inp = ciph_d[i].out; + + out += 5 + 16 + len; + + /* write MAC */ + PUTU32(out + 0, ctx->A[i]); + PUTU32(out + 4, ctx->B[i]); + PUTU32(out + 8, ctx->C[i]); + PUTU32(out + 12, ctx->D[i]); + PUTU32(out + 16, ctx->E[i]); + PUTU32(out + 20, ctx->F[i]); + PUTU32(out + 24, ctx->G[i]); + PUTU32(out + 28, ctx->H[i]); + out += 32; + len += 32; + + /* pad */ + pad = 15 - len % 16; + for (j = 0; j <= pad; j++) + *(out++) = pad; + len += pad + 1; + + ciph_d[i].blocks = (len - processed) / 16; + len += 16; /* account for explicit iv */ + + /* arrange header */ + out0[0] = ((u8 *)key->md.data)[8]; + out0[1] = ((u8 *)key->md.data)[9]; + out0[2] = ((u8 *)key->md.data)[10]; + out0[3] = (u8)(len >> 8); + out0[4] = (u8)(len); + + ret += len + 5; + inp += frag; + } + + aesni_multi_cbc_encrypt(ciph_d, &key->ks, n4x); + + OPENSSL_cleanse(blocks, sizeof(blocks)); + OPENSSL_cleanse(ctx, sizeof(*ctx)); + + return ret; +} +# endif + +static int aesni_cbc_hmac_sha256_cipher(EVP_CIPHER_CTX *ctx, + unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_AES_HMAC_SHA256 *key = data(ctx); + unsigned int l; + size_t plen = key->payload_length, iv = 0, /* explicit IV in TLS 1.1 and + * later */ + sha_off = 0; +# if defined(STITCHED_CALL) + size_t aes_off = 0, blocks; + + sha_off = SHA256_CBLOCK - key->md.num; +# endif + + key->payload_length = NO_PAYLOAD_LENGTH; + + if (len % AES_BLOCK_SIZE) + return 0; + + if (EVP_CIPHER_CTX_encrypting(ctx)) { + if (plen == NO_PAYLOAD_LENGTH) + plen = len; + else if (len != + ((plen + SHA256_DIGEST_LENGTH + + AES_BLOCK_SIZE) & -AES_BLOCK_SIZE)) + return 0; + else if (key->aux.tls_ver >= TLS1_1_VERSION) + iv = AES_BLOCK_SIZE; + +# if defined(STITCHED_CALL) + /* + * Assembly stitch handles AVX-capable processors, but its + * performance is not optimal on AMD Jaguar, ~40% worse, for + * unknown reasons. Incidentally processor in question supports + * AVX, but not AMD-specific XOP extension, which can be used + * to identify it and avoid stitch invocation. So that after we + * establish that current CPU supports AVX, we even see if it's + * either even XOP-capable Bulldozer-based or GenuineIntel one. + * But SHAEXT-capable go ahead... + */ + if (((OPENSSL_ia32cap_P[2] & (1 << 29)) || /* SHAEXT? */ + ((OPENSSL_ia32cap_P[1] & (1 << (60 - 32))) && /* AVX? */ + ((OPENSSL_ia32cap_P[1] & (1 << (43 - 32))) /* XOP? */ + | (OPENSSL_ia32cap_P[0] & (1 << 30))))) && /* "Intel CPU"? */ + plen > (sha_off + iv) && + (blocks = (plen - (sha_off + iv)) / SHA256_CBLOCK)) { + SHA256_Update(&key->md, in + iv, sha_off); + + (void)aesni_cbc_sha256_enc(in, out, blocks, &key->ks, + EVP_CIPHER_CTX_iv_noconst(ctx), + &key->md, in + iv + sha_off); + blocks *= SHA256_CBLOCK; + aes_off += blocks; + sha_off += blocks; + key->md.Nh += blocks >> 29; + key->md.Nl += blocks <<= 3; + if (key->md.Nl < (unsigned int)blocks) + key->md.Nh++; + } else { + sha_off = 0; + } +# endif + sha_off += iv; + SHA256_Update(&key->md, in + sha_off, plen - sha_off); + + if (plen != len) { /* "TLS" mode of operation */ + if (in != out) + memcpy(out + aes_off, in + aes_off, plen - aes_off); + + /* calculate HMAC and append it to payload */ + SHA256_Final(out + plen, &key->md); + key->md = key->tail; + SHA256_Update(&key->md, out + plen, SHA256_DIGEST_LENGTH); + SHA256_Final(out + plen, &key->md); + + /* pad the payload|hmac */ + plen += SHA256_DIGEST_LENGTH; + for (l = len - plen - 1; plen < len; plen++) + out[plen] = l; + /* encrypt HMAC|padding at once */ + aesni_cbc_encrypt(out + aes_off, out + aes_off, len - aes_off, + &key->ks, EVP_CIPHER_CTX_iv_noconst(ctx), 1); + } else { + aesni_cbc_encrypt(in + aes_off, out + aes_off, len - aes_off, + &key->ks, EVP_CIPHER_CTX_iv_noconst(ctx), 1); + } + } else { + union { + unsigned int u[SHA256_DIGEST_LENGTH / sizeof(unsigned int)]; + unsigned char c[64 + SHA256_DIGEST_LENGTH]; + } mac, *pmac; + + /* arrange cache line alignment */ + pmac = (void *)(((size_t)mac.c + 63) & ((size_t)0 - 64)); + + /* decrypt HMAC|padding at once */ + aesni_cbc_encrypt(in, out, len, &key->ks, + EVP_CIPHER_CTX_iv_noconst(ctx), 0); + + if (plen != NO_PAYLOAD_LENGTH) { /* "TLS" mode of operation */ + size_t inp_len, mask, j, i; + unsigned int res, maxpad, pad, bitlen; + int ret = 1; + union { + unsigned int u[SHA_LBLOCK]; + unsigned char c[SHA256_CBLOCK]; + } *data = (void *)key->md.data; + + if ((key->aux.tls_aad[plen - 4] << 8 | key->aux.tls_aad[plen - 3]) + >= TLS1_1_VERSION) + iv = AES_BLOCK_SIZE; + + if (len < (iv + SHA256_DIGEST_LENGTH + 1)) + return 0; + + /* omit explicit iv */ + out += iv; + len -= iv; + + /* figure out payload length */ + pad = out[len - 1]; + maxpad = len - (SHA256_DIGEST_LENGTH + 1); + maxpad |= (255 - maxpad) >> (sizeof(maxpad) * 8 - 8); + maxpad &= 255; + + mask = constant_time_ge(maxpad, pad); + ret &= mask; + /* + * If pad is invalid then we will fail the above test but we must + * continue anyway because we are in constant time code. However, + * we'll use the maxpad value instead of the supplied pad to make + * sure we perform well defined pointer arithmetic. + */ + pad = constant_time_select(mask, pad, maxpad); + + inp_len = len - (SHA256_DIGEST_LENGTH + pad + 1); + + key->aux.tls_aad[plen - 2] = inp_len >> 8; + key->aux.tls_aad[plen - 1] = inp_len; + + /* calculate HMAC */ + key->md = key->head; + SHA256_Update(&key->md, key->aux.tls_aad, plen); + +# if 1 /* see original reference version in #else */ + len -= SHA256_DIGEST_LENGTH; /* amend mac */ + if (len >= (256 + SHA256_CBLOCK)) { + j = (len - (256 + SHA256_CBLOCK)) & (0 - SHA256_CBLOCK); + j += SHA256_CBLOCK - key->md.num; + SHA256_Update(&key->md, out, j); + out += j; + len -= j; + inp_len -= j; + } + + /* but pretend as if we hashed padded payload */ + bitlen = key->md.Nl + (inp_len << 3); /* at most 18 bits */ +# ifdef BSWAP4 + bitlen = BSWAP4(bitlen); +# else + mac.c[0] = 0; + mac.c[1] = (unsigned char)(bitlen >> 16); + mac.c[2] = (unsigned char)(bitlen >> 8); + mac.c[3] = (unsigned char)bitlen; + bitlen = mac.u[0]; +# endif + + pmac->u[0] = 0; + pmac->u[1] = 0; + pmac->u[2] = 0; + pmac->u[3] = 0; + pmac->u[4] = 0; + pmac->u[5] = 0; + pmac->u[6] = 0; + pmac->u[7] = 0; + + for (res = key->md.num, j = 0; j < len; j++) { + size_t c = out[j]; + mask = (j - inp_len) >> (sizeof(j) * 8 - 8); + c &= mask; + c |= 0x80 & ~mask & ~((inp_len - j) >> (sizeof(j) * 8 - 8)); + data->c[res++] = (unsigned char)c; + + if (res != SHA256_CBLOCK) + continue; + + /* j is not incremented yet */ + mask = 0 - ((inp_len + 7 - j) >> (sizeof(j) * 8 - 1)); + data->u[SHA_LBLOCK - 1] |= bitlen & mask; + sha256_block_data_order(&key->md, data, 1); + mask &= 0 - ((j - inp_len - 72) >> (sizeof(j) * 8 - 1)); + pmac->u[0] |= key->md.h[0] & mask; + pmac->u[1] |= key->md.h[1] & mask; + pmac->u[2] |= key->md.h[2] & mask; + pmac->u[3] |= key->md.h[3] & mask; + pmac->u[4] |= key->md.h[4] & mask; + pmac->u[5] |= key->md.h[5] & mask; + pmac->u[6] |= key->md.h[6] & mask; + pmac->u[7] |= key->md.h[7] & mask; + res = 0; + } + + for (i = res; i < SHA256_CBLOCK; i++, j++) + data->c[i] = 0; + + if (res > SHA256_CBLOCK - 8) { + mask = 0 - ((inp_len + 8 - j) >> (sizeof(j) * 8 - 1)); + data->u[SHA_LBLOCK - 1] |= bitlen & mask; + sha256_block_data_order(&key->md, data, 1); + mask &= 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1)); + pmac->u[0] |= key->md.h[0] & mask; + pmac->u[1] |= key->md.h[1] & mask; + pmac->u[2] |= key->md.h[2] & mask; + pmac->u[3] |= key->md.h[3] & mask; + pmac->u[4] |= key->md.h[4] & mask; + pmac->u[5] |= key->md.h[5] & mask; + pmac->u[6] |= key->md.h[6] & mask; + pmac->u[7] |= key->md.h[7] & mask; + + memset(data, 0, SHA256_CBLOCK); + j += 64; + } + data->u[SHA_LBLOCK - 1] = bitlen; + sha256_block_data_order(&key->md, data, 1); + mask = 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1)); + pmac->u[0] |= key->md.h[0] & mask; + pmac->u[1] |= key->md.h[1] & mask; + pmac->u[2] |= key->md.h[2] & mask; + pmac->u[3] |= key->md.h[3] & mask; + pmac->u[4] |= key->md.h[4] & mask; + pmac->u[5] |= key->md.h[5] & mask; + pmac->u[6] |= key->md.h[6] & mask; + pmac->u[7] |= key->md.h[7] & mask; + +# ifdef BSWAP4 + pmac->u[0] = BSWAP4(pmac->u[0]); + pmac->u[1] = BSWAP4(pmac->u[1]); + pmac->u[2] = BSWAP4(pmac->u[2]); + pmac->u[3] = BSWAP4(pmac->u[3]); + pmac->u[4] = BSWAP4(pmac->u[4]); + pmac->u[5] = BSWAP4(pmac->u[5]); + pmac->u[6] = BSWAP4(pmac->u[6]); + pmac->u[7] = BSWAP4(pmac->u[7]); +# else + for (i = 0; i < 8; i++) { + res = pmac->u[i]; + pmac->c[4 * i + 0] = (unsigned char)(res >> 24); + pmac->c[4 * i + 1] = (unsigned char)(res >> 16); + pmac->c[4 * i + 2] = (unsigned char)(res >> 8); + pmac->c[4 * i + 3] = (unsigned char)res; + } +# endif + len += SHA256_DIGEST_LENGTH; +# else + SHA256_Update(&key->md, out, inp_len); + res = key->md.num; + SHA256_Final(pmac->c, &key->md); + + { + unsigned int inp_blocks, pad_blocks; + + /* but pretend as if we hashed padded payload */ + inp_blocks = + 1 + ((SHA256_CBLOCK - 9 - res) >> (sizeof(res) * 8 - 1)); + res += (unsigned int)(len - inp_len); + pad_blocks = res / SHA256_CBLOCK; + res %= SHA256_CBLOCK; + pad_blocks += + 1 + ((SHA256_CBLOCK - 9 - res) >> (sizeof(res) * 8 - 1)); + for (; inp_blocks < pad_blocks; inp_blocks++) + sha1_block_data_order(&key->md, data, 1); + } +# endif /* pre-lucky-13 reference version of above */ + key->md = key->tail; + SHA256_Update(&key->md, pmac->c, SHA256_DIGEST_LENGTH); + SHA256_Final(pmac->c, &key->md); + + /* verify HMAC */ + out += inp_len; + len -= inp_len; +# if 1 /* see original reference version in #else */ + { + unsigned char *p = + out + len - 1 - maxpad - SHA256_DIGEST_LENGTH; + size_t off = out - p; + unsigned int c, cmask; + + maxpad += SHA256_DIGEST_LENGTH; + for (res = 0, i = 0, j = 0; j < maxpad; j++) { + c = p[j]; + cmask = + ((int)(j - off - SHA256_DIGEST_LENGTH)) >> + (sizeof(int) * 8 - 1); + res |= (c ^ pad) & ~cmask; /* ... and padding */ + cmask &= ((int)(off - 1 - j)) >> (sizeof(int) * 8 - 1); + res |= (c ^ pmac->c[i]) & cmask; + i += 1 & cmask; + } + maxpad -= SHA256_DIGEST_LENGTH; + + res = 0 - ((0 - res) >> (sizeof(res) * 8 - 1)); + ret &= (int)~res; + } +# else /* pre-lucky-13 reference version of above */ + for (res = 0, i = 0; i < SHA256_DIGEST_LENGTH; i++) + res |= out[i] ^ pmac->c[i]; + res = 0 - ((0 - res) >> (sizeof(res) * 8 - 1)); + ret &= (int)~res; + + /* verify padding */ + pad = (pad & ~res) | (maxpad & res); + out = out + len - 1 - pad; + for (res = 0, i = 0; i < pad; i++) + res |= out[i] ^ pad; + + res = (0 - res) >> (sizeof(res) * 8 - 1); + ret &= (int)~res; +# endif + return ret; + } else { + SHA256_Update(&key->md, out, len); + } + } + + return 1; +} + +static int aesni_cbc_hmac_sha256_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, + void *ptr) +{ + EVP_AES_HMAC_SHA256 *key = data(ctx); + unsigned int u_arg = (unsigned int)arg; + + switch (type) { + case EVP_CTRL_AEAD_SET_MAC_KEY: + { + unsigned int i; + unsigned char hmac_key[64]; + + memset(hmac_key, 0, sizeof(hmac_key)); + + if (arg < 0) + return -1; + + if (u_arg > sizeof(hmac_key)) { + SHA256_Init(&key->head); + SHA256_Update(&key->head, ptr, arg); + SHA256_Final(hmac_key, &key->head); + } else { + memcpy(hmac_key, ptr, arg); + } + + for (i = 0; i < sizeof(hmac_key); i++) + hmac_key[i] ^= 0x36; /* ipad */ + SHA256_Init(&key->head); + SHA256_Update(&key->head, hmac_key, sizeof(hmac_key)); + + for (i = 0; i < sizeof(hmac_key); i++) + hmac_key[i] ^= 0x36 ^ 0x5c; /* opad */ + SHA256_Init(&key->tail); + SHA256_Update(&key->tail, hmac_key, sizeof(hmac_key)); + + OPENSSL_cleanse(hmac_key, sizeof(hmac_key)); + + return 1; + } + case EVP_CTRL_AEAD_TLS1_AAD: + { + unsigned char *p = ptr; + unsigned int len; + + if (arg != EVP_AEAD_TLS1_AAD_LEN) + return -1; + + len = p[arg - 2] << 8 | p[arg - 1]; + + if (EVP_CIPHER_CTX_encrypting(ctx)) { + key->payload_length = len; + if ((key->aux.tls_ver = + p[arg - 4] << 8 | p[arg - 3]) >= TLS1_1_VERSION) { + if (len < AES_BLOCK_SIZE) + return 0; + len -= AES_BLOCK_SIZE; + p[arg - 2] = len >> 8; + p[arg - 1] = len; + } + key->md = key->head; + SHA256_Update(&key->md, p, arg); + + return (int)(((len + SHA256_DIGEST_LENGTH + + AES_BLOCK_SIZE) & -AES_BLOCK_SIZE) + - len); + } else { + memcpy(key->aux.tls_aad, ptr, arg); + key->payload_length = arg; + + return SHA256_DIGEST_LENGTH; + } + } +# if !defined(OPENSSL_NO_MULTIBLOCK) + case EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE: + return (int)(5 + 16 + ((arg + 32 + 16) & -16)); + case EVP_CTRL_TLS1_1_MULTIBLOCK_AAD: + { + EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param = + (EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *) ptr; + unsigned int n4x = 1, x4; + unsigned int frag, last, packlen, inp_len; + + if (arg < 0) + return -1; + + if (u_arg < sizeof(EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM)) + return -1; + + inp_len = param->inp[11] << 8 | param->inp[12]; + + if (EVP_CIPHER_CTX_encrypting(ctx)) { + if ((param->inp[9] << 8 | param->inp[10]) < TLS1_1_VERSION) + return -1; + + if (inp_len) { + if (inp_len < 4096) + return 0; /* too short */ + + if (inp_len >= 8192 && OPENSSL_ia32cap_P[2] & (1 << 5)) + n4x = 2; /* AVX2 */ + } else if ((n4x = param->interleave / 4) && n4x <= 2) + inp_len = param->len; + else + return -1; + + key->md = key->head; + SHA256_Update(&key->md, param->inp, 13); + + x4 = 4 * n4x; + n4x += 1; + + frag = inp_len >> n4x; + last = inp_len + frag - (frag << n4x); + if (last > frag && ((last + 13 + 9) % 64 < (x4 - 1))) { + frag++; + last -= x4 - 1; + } + + packlen = 5 + 16 + ((frag + 32 + 16) & -16); + packlen = (packlen << n4x) - packlen; + packlen += 5 + 16 + ((last + 32 + 16) & -16); + + param->interleave = x4; + + return (int)packlen; + } else + return -1; /* not yet */ + } + case EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT: + { + EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param = + (EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *) ptr; + + return (int)tls1_1_multi_block_encrypt(key, param->out, + param->inp, param->len, + param->interleave / 4); + } + case EVP_CTRL_TLS1_1_MULTIBLOCK_DECRYPT: +# endif + default: + return -1; + } +} + +static EVP_CIPHER aesni_128_cbc_hmac_sha256_cipher = { +# ifdef NID_aes_128_cbc_hmac_sha256 + NID_aes_128_cbc_hmac_sha256, +# else + NID_undef, +# endif + AES_BLOCK_SIZE, 16, AES_BLOCK_SIZE, + EVP_CIPH_CBC_MODE | EVP_CIPH_FLAG_DEFAULT_ASN1 | + EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK, + aesni_cbc_hmac_sha256_init_key, + aesni_cbc_hmac_sha256_cipher, + NULL, + sizeof(EVP_AES_HMAC_SHA256), + EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_set_asn1_iv, + EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_get_asn1_iv, + aesni_cbc_hmac_sha256_ctrl, + NULL +}; + +static EVP_CIPHER aesni_256_cbc_hmac_sha256_cipher = { +# ifdef NID_aes_256_cbc_hmac_sha256 + NID_aes_256_cbc_hmac_sha256, +# else + NID_undef, +# endif + AES_BLOCK_SIZE, 32, AES_BLOCK_SIZE, + EVP_CIPH_CBC_MODE | EVP_CIPH_FLAG_DEFAULT_ASN1 | + EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK, + aesni_cbc_hmac_sha256_init_key, + aesni_cbc_hmac_sha256_cipher, + NULL, + sizeof(EVP_AES_HMAC_SHA256), + EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_set_asn1_iv, + EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_get_asn1_iv, + aesni_cbc_hmac_sha256_ctrl, + NULL +}; + +const EVP_CIPHER *EVP_aes_128_cbc_hmac_sha256(void) +{ + return ((OPENSSL_ia32cap_P[1] & AESNI_CAPABLE) && + aesni_cbc_sha256_enc(NULL, NULL, 0, NULL, NULL, NULL, NULL) ? + &aesni_128_cbc_hmac_sha256_cipher : NULL); +} + +const EVP_CIPHER *EVP_aes_256_cbc_hmac_sha256(void) +{ + return ((OPENSSL_ia32cap_P[1] & AESNI_CAPABLE) && + aesni_cbc_sha256_enc(NULL, NULL, 0, NULL, NULL, NULL, NULL) ? + &aesni_256_cbc_hmac_sha256_cipher : NULL); +} +#else +const EVP_CIPHER *EVP_aes_128_cbc_hmac_sha256(void) +{ + return NULL; +} + +const EVP_CIPHER *EVP_aes_256_cbc_hmac_sha256(void) +{ + return NULL; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_aria.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_aria.c new file mode 100644 index 000000000..81c8a7eaf --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_aria.c @@ -0,0 +1,756 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#ifndef OPENSSL_NO_ARIA +# include +# include +# include +# include +# include "internal/aria.h" +# include "internal/evp_int.h" +# include "modes_lcl.h" +# include "evp_locl.h" + +/* ARIA subkey Structure */ +typedef struct { + ARIA_KEY ks; +} EVP_ARIA_KEY; + +/* ARIA GCM context */ +typedef struct { + union { + double align; + ARIA_KEY ks; + } ks; /* ARIA subkey to use */ + int key_set; /* Set if key initialised */ + int iv_set; /* Set if an iv is set */ + GCM128_CONTEXT gcm; + unsigned char *iv; /* Temporary IV store */ + int ivlen; /* IV length */ + int taglen; + int iv_gen; /* It is OK to generate IVs */ + int tls_aad_len; /* TLS AAD length */ +} EVP_ARIA_GCM_CTX; + +/* ARIA CCM context */ +typedef struct { + union { + double align; + ARIA_KEY ks; + } ks; /* ARIA key schedule to use */ + int key_set; /* Set if key initialised */ + int iv_set; /* Set if an iv is set */ + int tag_set; /* Set if tag is valid */ + int len_set; /* Set if message length set */ + int L, M; /* L and M parameters from RFC3610 */ + int tls_aad_len; /* TLS AAD length */ + CCM128_CONTEXT ccm; + ccm128_f str; +} EVP_ARIA_CCM_CTX; + +/* The subkey for ARIA is generated. */ +static int aria_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + int ret; + int mode = EVP_CIPHER_CTX_mode(ctx); + + if (enc || (mode != EVP_CIPH_ECB_MODE && mode != EVP_CIPH_CBC_MODE)) + ret = aria_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, + EVP_CIPHER_CTX_get_cipher_data(ctx)); + else + ret = aria_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, + EVP_CIPHER_CTX_get_cipher_data(ctx)); + if (ret < 0) { + EVPerr(EVP_F_ARIA_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED); + return 0; + } + return 1; +} + +static void aria_cbc_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const ARIA_KEY *key, + unsigned char *ivec, const int enc) +{ + + if (enc) + CRYPTO_cbc128_encrypt(in, out, len, key, ivec, + (block128_f) aria_encrypt); + else + CRYPTO_cbc128_decrypt(in, out, len, key, ivec, + (block128_f) aria_encrypt); +} + +static void aria_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const ARIA_KEY *key, + unsigned char *ivec, int *num, const int enc) +{ + + CRYPTO_cfb128_encrypt(in, out, length, key, ivec, num, enc, + (block128_f) aria_encrypt); +} + +static void aria_cfb1_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const ARIA_KEY *key, + unsigned char *ivec, int *num, const int enc) +{ + CRYPTO_cfb128_1_encrypt(in, out, length, key, ivec, num, enc, + (block128_f) aria_encrypt); +} + +static void aria_cfb8_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const ARIA_KEY *key, + unsigned char *ivec, int *num, const int enc) +{ + CRYPTO_cfb128_8_encrypt(in, out, length, key, ivec, num, enc, + (block128_f) aria_encrypt); +} + +static void aria_ecb_encrypt(const unsigned char *in, unsigned char *out, + const ARIA_KEY *key, const int enc) +{ + aria_encrypt(in, out, key); +} + +static void aria_ofb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const ARIA_KEY *key, + unsigned char *ivec, int *num) +{ + CRYPTO_ofb128_encrypt(in, out, length, key, ivec, num, + (block128_f) aria_encrypt); +} + +IMPLEMENT_BLOCK_CIPHER(aria_128, ks, aria, EVP_ARIA_KEY, + NID_aria_128, 16, 16, 16, 128, + 0, aria_init_key, NULL, + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL) +IMPLEMENT_BLOCK_CIPHER(aria_192, ks, aria, EVP_ARIA_KEY, + NID_aria_192, 16, 24, 16, 128, + 0, aria_init_key, NULL, + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL) +IMPLEMENT_BLOCK_CIPHER(aria_256, ks, aria, EVP_ARIA_KEY, + NID_aria_256, 16, 32, 16, 128, + 0, aria_init_key, NULL, + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL) + +# define IMPLEMENT_ARIA_CFBR(ksize,cbits) \ + IMPLEMENT_CFBR(aria,aria,EVP_ARIA_KEY,ks,ksize,cbits,16,0) +IMPLEMENT_ARIA_CFBR(128,1) +IMPLEMENT_ARIA_CFBR(192,1) +IMPLEMENT_ARIA_CFBR(256,1) +IMPLEMENT_ARIA_CFBR(128,8) +IMPLEMENT_ARIA_CFBR(192,8) +IMPLEMENT_ARIA_CFBR(256,8) + +# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \ +static const EVP_CIPHER aria_##keylen##_##mode = { \ + nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \ + flags|EVP_CIPH_##MODE##_MODE, \ + aria_init_key, \ + aria_##mode##_cipher, \ + NULL, \ + sizeof(EVP_ARIA_KEY), \ + NULL,NULL,NULL,NULL }; \ +const EVP_CIPHER *EVP_aria_##keylen##_##mode(void) \ +{ return &aria_##keylen##_##mode; } + +static int aria_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + unsigned int num = EVP_CIPHER_CTX_num(ctx); + EVP_ARIA_KEY *dat = EVP_C_DATA(EVP_ARIA_KEY,ctx); + + CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, + EVP_CIPHER_CTX_iv_noconst(ctx), + EVP_CIPHER_CTX_buf_noconst(ctx), &num, + (block128_f) aria_encrypt); + EVP_CIPHER_CTX_set_num(ctx, num); + return 1; +} + +BLOCK_CIPHER_generic(NID_aria, 128, 1, 16, ctr, ctr, CTR, 0) +BLOCK_CIPHER_generic(NID_aria, 192, 1, 16, ctr, ctr, CTR, 0) +BLOCK_CIPHER_generic(NID_aria, 256, 1, 16, ctr, ctr, CTR, 0) + +/* Authenticated cipher modes (GCM/CCM) */ + +/* increment counter (64-bit int) by 1 */ +static void ctr64_inc(unsigned char *counter) +{ + int n = 8; + unsigned char c; + + do { + --n; + c = counter[n]; + ++c; + counter[n] = c; + if (c) + return; + } while (n); +} + +static int aria_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + int ret; + EVP_ARIA_GCM_CTX *gctx = EVP_C_DATA(EVP_ARIA_GCM_CTX,ctx); + + if (!iv && !key) + return 1; + if (key) { + ret = aria_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, + &gctx->ks.ks); + CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, + (block128_f) aria_encrypt); + if (ret < 0) { + EVPerr(EVP_F_ARIA_GCM_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED); + return 0; + } + + /* + * If we have an iv can set it directly, otherwise use saved IV. + */ + if (iv == NULL && gctx->iv_set) + iv = gctx->iv; + if (iv) { + CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen); + gctx->iv_set = 1; + } + gctx->key_set = 1; + } else { + /* If key set use IV, otherwise copy */ + if (gctx->key_set) + CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen); + else + memcpy(gctx->iv, iv, gctx->ivlen); + gctx->iv_set = 1; + gctx->iv_gen = 0; + } + return 1; +} + +static int aria_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) +{ + EVP_ARIA_GCM_CTX *gctx = EVP_C_DATA(EVP_ARIA_GCM_CTX,c); + + switch (type) { + case EVP_CTRL_INIT: + gctx->key_set = 0; + gctx->iv_set = 0; + gctx->ivlen = EVP_CIPHER_CTX_iv_length(c); + gctx->iv = EVP_CIPHER_CTX_iv_noconst(c); + gctx->taglen = -1; + gctx->iv_gen = 0; + gctx->tls_aad_len = -1; + return 1; + + case EVP_CTRL_AEAD_SET_IVLEN: + if (arg <= 0) + return 0; + /* Allocate memory for IV if needed */ + if ((arg > EVP_MAX_IV_LENGTH) && (arg > gctx->ivlen)) { + if (gctx->iv != EVP_CIPHER_CTX_iv_noconst(c)) + OPENSSL_free(gctx->iv); + if ((gctx->iv = OPENSSL_malloc(arg)) == NULL) { + EVPerr(EVP_F_ARIA_GCM_CTRL, ERR_R_MALLOC_FAILURE); + return 0; + } + } + gctx->ivlen = arg; + return 1; + + case EVP_CTRL_AEAD_SET_TAG: + if (arg <= 0 || arg > 16 || EVP_CIPHER_CTX_encrypting(c)) + return 0; + memcpy(EVP_CIPHER_CTX_buf_noconst(c), ptr, arg); + gctx->taglen = arg; + return 1; + + case EVP_CTRL_AEAD_GET_TAG: + if (arg <= 0 || arg > 16 || !EVP_CIPHER_CTX_encrypting(c) + || gctx->taglen < 0) + return 0; + memcpy(ptr, EVP_CIPHER_CTX_buf_noconst(c), arg); + return 1; + + case EVP_CTRL_GCM_SET_IV_FIXED: + /* Special case: -1 length restores whole IV */ + if (arg == -1) { + memcpy(gctx->iv, ptr, gctx->ivlen); + gctx->iv_gen = 1; + return 1; + } + /* + * Fixed field must be at least 4 bytes and invocation field at least + * 8. + */ + if ((arg < 4) || (gctx->ivlen - arg) < 8) + return 0; + if (arg) + memcpy(gctx->iv, ptr, arg); + if (EVP_CIPHER_CTX_encrypting(c) + && RAND_bytes(gctx->iv + arg, gctx->ivlen - arg) <= 0) + return 0; + gctx->iv_gen = 1; + return 1; + + case EVP_CTRL_GCM_IV_GEN: + if (gctx->iv_gen == 0 || gctx->key_set == 0) + return 0; + CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen); + if (arg <= 0 || arg > gctx->ivlen) + arg = gctx->ivlen; + memcpy(ptr, gctx->iv + gctx->ivlen - arg, arg); + /* + * Invocation field will be at least 8 bytes in size and so no need + * to check wrap around or increment more than last 8 bytes. + */ + ctr64_inc(gctx->iv + gctx->ivlen - 8); + gctx->iv_set = 1; + return 1; + + case EVP_CTRL_GCM_SET_IV_INV: + if (gctx->iv_gen == 0 || gctx->key_set == 0 + || EVP_CIPHER_CTX_encrypting(c)) + return 0; + memcpy(gctx->iv + gctx->ivlen - arg, ptr, arg); + CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen); + gctx->iv_set = 1; + return 1; + + case EVP_CTRL_AEAD_TLS1_AAD: + /* Save the AAD for later use */ + if (arg != EVP_AEAD_TLS1_AAD_LEN) + return 0; + memcpy(EVP_CIPHER_CTX_buf_noconst(c), ptr, arg); + gctx->tls_aad_len = arg; + { + unsigned int len = + EVP_CIPHER_CTX_buf_noconst(c)[arg - 2] << 8 + | EVP_CIPHER_CTX_buf_noconst(c)[arg - 1]; + /* Correct length for explicit IV */ + if (len < EVP_GCM_TLS_EXPLICIT_IV_LEN) + return 0; + len -= EVP_GCM_TLS_EXPLICIT_IV_LEN; + /* If decrypting correct for tag too */ + if (!EVP_CIPHER_CTX_encrypting(c)) { + if (len < EVP_GCM_TLS_TAG_LEN) + return 0; + len -= EVP_GCM_TLS_TAG_LEN; + } + EVP_CIPHER_CTX_buf_noconst(c)[arg - 2] = len >> 8; + EVP_CIPHER_CTX_buf_noconst(c)[arg - 1] = len & 0xff; + } + /* Extra padding: tag appended to record */ + return EVP_GCM_TLS_TAG_LEN; + + case EVP_CTRL_COPY: + { + EVP_CIPHER_CTX *out = ptr; + EVP_ARIA_GCM_CTX *gctx_out = EVP_C_DATA(EVP_ARIA_GCM_CTX,out); + if (gctx->gcm.key) { + if (gctx->gcm.key != &gctx->ks) + return 0; + gctx_out->gcm.key = &gctx_out->ks; + } + if (gctx->iv == EVP_CIPHER_CTX_iv_noconst(c)) + gctx_out->iv = EVP_CIPHER_CTX_iv_noconst(out); + else { + if ((gctx_out->iv = OPENSSL_malloc(gctx->ivlen)) == NULL) { + EVPerr(EVP_F_ARIA_GCM_CTRL, ERR_R_MALLOC_FAILURE); + return 0; + } + memcpy(gctx_out->iv, gctx->iv, gctx->ivlen); + } + return 1; + } + + default: + return -1; + + } +} + +static int aria_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_ARIA_GCM_CTX *gctx = EVP_C_DATA(EVP_ARIA_GCM_CTX,ctx); + int rv = -1; + + /* Encrypt/decrypt must be performed in place */ + if (out != in + || len < (EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN)) + return -1; + /* + * Set IV from start of buffer or generate IV and write to start of + * buffer. + */ + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CIPHER_CTX_encrypting(ctx) ? + EVP_CTRL_GCM_IV_GEN : EVP_CTRL_GCM_SET_IV_INV, + EVP_GCM_TLS_EXPLICIT_IV_LEN, out) <= 0) + goto err; + /* Use saved AAD */ + if (CRYPTO_gcm128_aad(&gctx->gcm, EVP_CIPHER_CTX_buf_noconst(ctx), + gctx->tls_aad_len)) + goto err; + /* Fix buffer and length to point to payload */ + in += EVP_GCM_TLS_EXPLICIT_IV_LEN; + out += EVP_GCM_TLS_EXPLICIT_IV_LEN; + len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN; + if (EVP_CIPHER_CTX_encrypting(ctx)) { + /* Encrypt payload */ + if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, len)) + goto err; + out += len; + /* Finally write tag */ + CRYPTO_gcm128_tag(&gctx->gcm, out, EVP_GCM_TLS_TAG_LEN); + rv = len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN; + } else { + /* Decrypt */ + if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, len)) + goto err; + /* Retrieve tag */ + CRYPTO_gcm128_tag(&gctx->gcm, EVP_CIPHER_CTX_buf_noconst(ctx), + EVP_GCM_TLS_TAG_LEN); + /* If tag mismatch wipe buffer */ + if (CRYPTO_memcmp(EVP_CIPHER_CTX_buf_noconst(ctx), in + len, + EVP_GCM_TLS_TAG_LEN)) { + OPENSSL_cleanse(out, len); + goto err; + } + rv = len; + } + + err: + gctx->iv_set = 0; + gctx->tls_aad_len = -1; + return rv; +} + +static int aria_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_ARIA_GCM_CTX *gctx = EVP_C_DATA(EVP_ARIA_GCM_CTX,ctx); + + /* If not set up, return error */ + if (!gctx->key_set) + return -1; + + if (gctx->tls_aad_len >= 0) + return aria_gcm_tls_cipher(ctx, out, in, len); + + if (!gctx->iv_set) + return -1; + if (in) { + if (out == NULL) { + if (CRYPTO_gcm128_aad(&gctx->gcm, in, len)) + return -1; + } else if (EVP_CIPHER_CTX_encrypting(ctx)) { + if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, len)) + return -1; + } else { + if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, len)) + return -1; + } + return len; + } + if (!EVP_CIPHER_CTX_encrypting(ctx)) { + if (gctx->taglen < 0) + return -1; + if (CRYPTO_gcm128_finish(&gctx->gcm, + EVP_CIPHER_CTX_buf_noconst(ctx), + gctx->taglen) != 0) + return -1; + gctx->iv_set = 0; + return 0; + } + CRYPTO_gcm128_tag(&gctx->gcm, EVP_CIPHER_CTX_buf_noconst(ctx), 16); + gctx->taglen = 16; + /* Don't reuse the IV */ + gctx->iv_set = 0; + return 0; +} + +static int aria_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + int ret; + EVP_ARIA_CCM_CTX *cctx = EVP_C_DATA(EVP_ARIA_CCM_CTX,ctx); + + if (!iv && !key) + return 1; + + if (key) { + ret = aria_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, + &cctx->ks.ks); + CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L, + &cctx->ks, (block128_f) aria_encrypt); + if (ret < 0) { + EVPerr(EVP_F_ARIA_CCM_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED); + return 0; + } + cctx->str = NULL; + cctx->key_set = 1; + } + if (iv) { + memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 15 - cctx->L); + cctx->iv_set = 1; + } + return 1; +} + +static int aria_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) +{ + EVP_ARIA_CCM_CTX *cctx = EVP_C_DATA(EVP_ARIA_CCM_CTX,c); + + switch (type) { + case EVP_CTRL_INIT: + cctx->key_set = 0; + cctx->iv_set = 0; + cctx->L = 8; + cctx->M = 12; + cctx->tag_set = 0; + cctx->len_set = 0; + cctx->tls_aad_len = -1; + return 1; + + case EVP_CTRL_AEAD_TLS1_AAD: + /* Save the AAD for later use */ + if (arg != EVP_AEAD_TLS1_AAD_LEN) + return 0; + memcpy(EVP_CIPHER_CTX_buf_noconst(c), ptr, arg); + cctx->tls_aad_len = arg; + { + uint16_t len = + EVP_CIPHER_CTX_buf_noconst(c)[arg - 2] << 8 + | EVP_CIPHER_CTX_buf_noconst(c)[arg - 1]; + /* Correct length for explicit IV */ + if (len < EVP_CCM_TLS_EXPLICIT_IV_LEN) + return 0; + len -= EVP_CCM_TLS_EXPLICIT_IV_LEN; + /* If decrypting correct for tag too */ + if (!EVP_CIPHER_CTX_encrypting(c)) { + if (len < cctx->M) + return 0; + len -= cctx->M; + } + EVP_CIPHER_CTX_buf_noconst(c)[arg - 2] = len >> 8; + EVP_CIPHER_CTX_buf_noconst(c)[arg - 1] = len & 0xff; + } + /* Extra padding: tag appended to record */ + return cctx->M; + + case EVP_CTRL_CCM_SET_IV_FIXED: + /* Sanity check length */ + if (arg != EVP_CCM_TLS_FIXED_IV_LEN) + return 0; + /* Just copy to first part of IV */ + memcpy(EVP_CIPHER_CTX_iv_noconst(c), ptr, arg); + return 1; + + case EVP_CTRL_AEAD_SET_IVLEN: + arg = 15 - arg; + /* fall thru */ + case EVP_CTRL_CCM_SET_L: + if (arg < 2 || arg > 8) + return 0; + cctx->L = arg; + return 1; + case EVP_CTRL_AEAD_SET_TAG: + if ((arg & 1) || arg < 4 || arg > 16) + return 0; + if (EVP_CIPHER_CTX_encrypting(c) && ptr) + return 0; + if (ptr) { + cctx->tag_set = 1; + memcpy(EVP_CIPHER_CTX_buf_noconst(c), ptr, arg); + } + cctx->M = arg; + return 1; + + case EVP_CTRL_AEAD_GET_TAG: + if (!EVP_CIPHER_CTX_encrypting(c) || !cctx->tag_set) + return 0; + if (!CRYPTO_ccm128_tag(&cctx->ccm, ptr, (size_t)arg)) + return 0; + cctx->tag_set = 0; + cctx->iv_set = 0; + cctx->len_set = 0; + return 1; + + case EVP_CTRL_COPY: + { + EVP_CIPHER_CTX *out = ptr; + EVP_ARIA_CCM_CTX *cctx_out = EVP_C_DATA(EVP_ARIA_CCM_CTX,out); + if (cctx->ccm.key) { + if (cctx->ccm.key != &cctx->ks) + return 0; + cctx_out->ccm.key = &cctx_out->ks; + } + return 1; + } + + default: + return -1; + } +} + +static int aria_ccm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_ARIA_CCM_CTX *cctx = EVP_C_DATA(EVP_ARIA_CCM_CTX,ctx); + CCM128_CONTEXT *ccm = &cctx->ccm; + + /* Encrypt/decrypt must be performed in place */ + if (out != in || len < (EVP_CCM_TLS_EXPLICIT_IV_LEN + (size_t)cctx->M)) + return -1; + /* If encrypting set explicit IV from sequence number (start of AAD) */ + if (EVP_CIPHER_CTX_encrypting(ctx)) + memcpy(out, EVP_CIPHER_CTX_buf_noconst(ctx), + EVP_CCM_TLS_EXPLICIT_IV_LEN); + /* Get rest of IV from explicit IV */ + memcpy(EVP_CIPHER_CTX_iv_noconst(ctx) + EVP_CCM_TLS_FIXED_IV_LEN, in, + EVP_CCM_TLS_EXPLICIT_IV_LEN); + /* Correct length value */ + len -= EVP_CCM_TLS_EXPLICIT_IV_LEN + cctx->M; + if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx), 15 - cctx->L, + len)) + return -1; + /* Use saved AAD */ + CRYPTO_ccm128_aad(ccm, EVP_CIPHER_CTX_buf_noconst(ctx), cctx->tls_aad_len); + /* Fix buffer to point to payload */ + in += EVP_CCM_TLS_EXPLICIT_IV_LEN; + out += EVP_CCM_TLS_EXPLICIT_IV_LEN; + if (EVP_CIPHER_CTX_encrypting(ctx)) { + if (cctx->str ? CRYPTO_ccm128_encrypt_ccm64(ccm, in, out, len, cctx->str) + : CRYPTO_ccm128_encrypt(ccm, in, out, len)) + return -1; + if (!CRYPTO_ccm128_tag(ccm, out + len, cctx->M)) + return -1; + return len + EVP_CCM_TLS_EXPLICIT_IV_LEN + cctx->M; + } else { + if (cctx->str ? !CRYPTO_ccm128_decrypt_ccm64(ccm, in, out, len, cctx->str) + : !CRYPTO_ccm128_decrypt(ccm, in, out, len)) { + unsigned char tag[16]; + if (CRYPTO_ccm128_tag(ccm, tag, cctx->M)) { + if (!CRYPTO_memcmp(tag, in + len, cctx->M)) + return len; + } + } + OPENSSL_cleanse(out, len); + return -1; + } +} + +static int aria_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_ARIA_CCM_CTX *cctx = EVP_C_DATA(EVP_ARIA_CCM_CTX,ctx); + CCM128_CONTEXT *ccm = &cctx->ccm; + + /* If not set up, return error */ + if (!cctx->key_set) + return -1; + + if (cctx->tls_aad_len >= 0) + return aria_ccm_tls_cipher(ctx, out, in, len); + + /* EVP_*Final() doesn't return any data */ + if (in == NULL && out != NULL) + return 0; + + if (!cctx->iv_set) + return -1; + + if (!EVP_CIPHER_CTX_encrypting(ctx) && !cctx->tag_set) + return -1; + if (!out) { + if (!in) { + if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx), + 15 - cctx->L, len)) + return -1; + cctx->len_set = 1; + return len; + } + /* If have AAD need message length */ + if (!cctx->len_set && len) + return -1; + CRYPTO_ccm128_aad(ccm, in, len); + return len; + } + /* If not set length yet do it */ + if (!cctx->len_set) { + if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx), + 15 - cctx->L, len)) + return -1; + cctx->len_set = 1; + } + if (EVP_CIPHER_CTX_encrypting(ctx)) { + if (cctx->str ? CRYPTO_ccm128_encrypt_ccm64(ccm, in, out, len, cctx->str) + : CRYPTO_ccm128_encrypt(ccm, in, out, len)) + return -1; + cctx->tag_set = 1; + return len; + } else { + int rv = -1; + if (cctx->str ? !CRYPTO_ccm128_decrypt_ccm64(ccm, in, out, len, + cctx->str) : + !CRYPTO_ccm128_decrypt(ccm, in, out, len)) { + unsigned char tag[16]; + if (CRYPTO_ccm128_tag(ccm, tag, cctx->M)) { + if (!CRYPTO_memcmp(tag, EVP_CIPHER_CTX_buf_noconst(ctx), + cctx->M)) + rv = len; + } + } + if (rv == -1) + OPENSSL_cleanse(out, len); + cctx->iv_set = 0; + cctx->tag_set = 0; + cctx->len_set = 0; + return rv; + } +} + +#define ARIA_AUTH_FLAGS (EVP_CIPH_FLAG_DEFAULT_ASN1 \ + | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \ + | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \ + | EVP_CIPH_CUSTOM_COPY | EVP_CIPH_FLAG_AEAD_CIPHER) + +#define BLOCK_CIPHER_aead(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \ +static const EVP_CIPHER aria_##keylen##_##mode = { \ + nid##_##keylen##_##nmode, \ + blocksize, keylen/8, ivlen, \ + ARIA_AUTH_FLAGS|EVP_CIPH_##MODE##_MODE, \ + aria_##mode##_init_key, \ + aria_##mode##_cipher, \ + NULL, \ + sizeof(EVP_ARIA_##MODE##_CTX), \ + NULL,NULL,aria_##mode##_ctrl,NULL }; \ +const EVP_CIPHER *EVP_aria_##keylen##_##mode(void) \ +{ return (EVP_CIPHER*)&aria_##keylen##_##mode; } + +BLOCK_CIPHER_aead(NID_aria, 128, 1, 12, gcm, gcm, GCM, 0) +BLOCK_CIPHER_aead(NID_aria, 192, 1, 12, gcm, gcm, GCM, 0) +BLOCK_CIPHER_aead(NID_aria, 256, 1, 12, gcm, gcm, GCM, 0) + +BLOCK_CIPHER_aead(NID_aria, 128, 1, 12, ccm, ccm, CCM, 0) +BLOCK_CIPHER_aead(NID_aria, 192, 1, 12, ccm, ccm, CCM, 0) +BLOCK_CIPHER_aead(NID_aria, 256, 1, 12, ccm, ccm, CCM, 0) + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_bf.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_bf.c new file mode 100644 index 000000000..dc386905c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_bf.c @@ -0,0 +1,38 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#ifndef OPENSSL_NO_BF +# include +# include "internal/evp_int.h" +# include +# include + +static int bf_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); + +typedef struct { + BF_KEY ks; +} EVP_BF_KEY; + +# define data(ctx) EVP_C_DATA(EVP_BF_KEY,ctx) + +IMPLEMENT_BLOCK_CIPHER(bf, ks, BF, EVP_BF_KEY, NID_bf, 8, 16, 8, 64, + EVP_CIPH_VARIABLE_LENGTH, bf_init_key, NULL, + EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL) + +static int bf_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + BF_set_key(&data(ctx)->ks, EVP_CIPHER_CTX_key_length(ctx), key); + return 1; +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_camellia.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_camellia.c new file mode 100644 index 000000000..2df4a6e3e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_camellia.c @@ -0,0 +1,366 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#ifdef OPENSSL_NO_CAMELLIA +NON_EMPTY_TRANSLATION_UNIT +#else + +# include +# include +# include +# include +# include +# include "internal/evp_int.h" +# include "modes_lcl.h" + +static int camellia_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); + +/* Camellia subkey Structure */ +typedef struct { + CAMELLIA_KEY ks; + block128_f block; + union { + cbc128_f cbc; + ctr128_f ctr; + } stream; +} EVP_CAMELLIA_KEY; + +# define MAXBITCHUNK ((size_t)1<<(sizeof(size_t)*8-4)) + +/* Attribute operation for Camellia */ +# define data(ctx) EVP_C_DATA(EVP_CAMELLIA_KEY,ctx) + +# if defined(AES_ASM) && (defined(__sparc) || defined(__sparc__)) +/* ---------^^^ this is not a typo, just a way to detect that + * assembler support was in general requested... */ +# include "sparc_arch.h" + +extern unsigned int OPENSSL_sparcv9cap_P[]; + +# define SPARC_CMLL_CAPABLE (OPENSSL_sparcv9cap_P[1] & CFR_CAMELLIA) + +void cmll_t4_set_key(const unsigned char *key, int bits, CAMELLIA_KEY *ks); +void cmll_t4_encrypt(const unsigned char *in, unsigned char *out, + const CAMELLIA_KEY *key); +void cmll_t4_decrypt(const unsigned char *in, unsigned char *out, + const CAMELLIA_KEY *key); + +void cmll128_t4_cbc_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const CAMELLIA_KEY *key, + unsigned char *ivec); +void cmll128_t4_cbc_decrypt(const unsigned char *in, unsigned char *out, + size_t len, const CAMELLIA_KEY *key, + unsigned char *ivec); +void cmll256_t4_cbc_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const CAMELLIA_KEY *key, + unsigned char *ivec); +void cmll256_t4_cbc_decrypt(const unsigned char *in, unsigned char *out, + size_t len, const CAMELLIA_KEY *key, + unsigned char *ivec); +void cmll128_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out, + size_t blocks, const CAMELLIA_KEY *key, + unsigned char *ivec); +void cmll256_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out, + size_t blocks, const CAMELLIA_KEY *key, + unsigned char *ivec); + +static int cmll_t4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + int ret, mode, bits; + EVP_CAMELLIA_KEY *dat = + (EVP_CAMELLIA_KEY *)EVP_CIPHER_CTX_get_cipher_data(ctx); + + mode = EVP_CIPHER_CTX_mode(ctx); + bits = EVP_CIPHER_CTX_key_length(ctx) * 8; + + cmll_t4_set_key(key, bits, &dat->ks); + + if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) + && !enc) { + ret = 0; + dat->block = (block128_f) cmll_t4_decrypt; + switch (bits) { + case 128: + dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? + (cbc128_f) cmll128_t4_cbc_decrypt : NULL; + break; + case 192: + case 256: + dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? + (cbc128_f) cmll256_t4_cbc_decrypt : NULL; + break; + default: + ret = -1; + } + } else { + ret = 0; + dat->block = (block128_f) cmll_t4_encrypt; + switch (bits) { + case 128: + if (mode == EVP_CIPH_CBC_MODE) + dat->stream.cbc = (cbc128_f) cmll128_t4_cbc_encrypt; + else if (mode == EVP_CIPH_CTR_MODE) + dat->stream.ctr = (ctr128_f) cmll128_t4_ctr32_encrypt; + else + dat->stream.cbc = NULL; + break; + case 192: + case 256: + if (mode == EVP_CIPH_CBC_MODE) + dat->stream.cbc = (cbc128_f) cmll256_t4_cbc_encrypt; + else if (mode == EVP_CIPH_CTR_MODE) + dat->stream.ctr = (ctr128_f) cmll256_t4_ctr32_encrypt; + else + dat->stream.cbc = NULL; + break; + default: + ret = -1; + } + } + + if (ret < 0) { + EVPerr(EVP_F_CMLL_T4_INIT_KEY, EVP_R_CAMELLIA_KEY_SETUP_FAILED); + return 0; + } + + return 1; +} + +# define cmll_t4_cbc_cipher camellia_cbc_cipher +static int cmll_t4_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +# define cmll_t4_ecb_cipher camellia_ecb_cipher +static int cmll_t4_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +# define cmll_t4_ofb_cipher camellia_ofb_cipher +static int cmll_t4_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +# define cmll_t4_cfb_cipher camellia_cfb_cipher +static int cmll_t4_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +# define cmll_t4_cfb8_cipher camellia_cfb8_cipher +static int cmll_t4_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +# define cmll_t4_cfb1_cipher camellia_cfb1_cipher +static int cmll_t4_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +# define cmll_t4_ctr_cipher camellia_ctr_cipher +static int cmll_t4_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \ +static const EVP_CIPHER cmll_t4_##keylen##_##mode = { \ + nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \ + flags|EVP_CIPH_##MODE##_MODE, \ + cmll_t4_init_key, \ + cmll_t4_##mode##_cipher, \ + NULL, \ + sizeof(EVP_CAMELLIA_KEY), \ + NULL,NULL,NULL,NULL }; \ +static const EVP_CIPHER camellia_##keylen##_##mode = { \ + nid##_##keylen##_##nmode,blocksize, \ + keylen/8,ivlen, \ + flags|EVP_CIPH_##MODE##_MODE, \ + camellia_init_key, \ + camellia_##mode##_cipher, \ + NULL, \ + sizeof(EVP_CAMELLIA_KEY), \ + NULL,NULL,NULL,NULL }; \ +const EVP_CIPHER *EVP_camellia_##keylen##_##mode(void) \ +{ return SPARC_CMLL_CAPABLE?&cmll_t4_##keylen##_##mode:&camellia_##keylen##_##mode; } + +# else + +# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \ +static const EVP_CIPHER camellia_##keylen##_##mode = { \ + nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \ + flags|EVP_CIPH_##MODE##_MODE, \ + camellia_init_key, \ + camellia_##mode##_cipher, \ + NULL, \ + sizeof(EVP_CAMELLIA_KEY), \ + NULL,NULL,NULL,NULL }; \ +const EVP_CIPHER *EVP_camellia_##keylen##_##mode(void) \ +{ return &camellia_##keylen##_##mode; } + +# endif + +# define BLOCK_CIPHER_generic_pack(nid,keylen,flags) \ + BLOCK_CIPHER_generic(nid,keylen,16,16,cbc,cbc,CBC,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \ + BLOCK_CIPHER_generic(nid,keylen,16,0,ecb,ecb,ECB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \ + BLOCK_CIPHER_generic(nid,keylen,1,16,ofb128,ofb,OFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \ + BLOCK_CIPHER_generic(nid,keylen,1,16,cfb128,cfb,CFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \ + BLOCK_CIPHER_generic(nid,keylen,1,16,cfb1,cfb1,CFB,flags) \ + BLOCK_CIPHER_generic(nid,keylen,1,16,cfb8,cfb8,CFB,flags) \ + BLOCK_CIPHER_generic(nid, keylen, 1, 16, ctr, ctr, CTR, flags) + +/* The subkey for Camellia is generated. */ +static int camellia_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + int ret, mode; + EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx); + + ret = Camellia_set_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, &dat->ks); + if (ret < 0) { + EVPerr(EVP_F_CAMELLIA_INIT_KEY, EVP_R_CAMELLIA_KEY_SETUP_FAILED); + return 0; + } + + mode = EVP_CIPHER_CTX_mode(ctx); + if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) + && !enc) { + dat->block = (block128_f) Camellia_decrypt; + dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? + (cbc128_f) Camellia_cbc_encrypt : NULL; + } else { + dat->block = (block128_f) Camellia_encrypt; + dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? + (cbc128_f) Camellia_cbc_encrypt : NULL; + } + + return 1; +} + +static int camellia_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx); + + if (dat->stream.cbc) + (*dat->stream.cbc) (in, out, len, &dat->ks, + EVP_CIPHER_CTX_iv_noconst(ctx), + EVP_CIPHER_CTX_encrypting(ctx)); + else if (EVP_CIPHER_CTX_encrypting(ctx)) + CRYPTO_cbc128_encrypt(in, out, len, &dat->ks, + EVP_CIPHER_CTX_iv_noconst(ctx), dat->block); + else + CRYPTO_cbc128_decrypt(in, out, len, &dat->ks, + EVP_CIPHER_CTX_iv_noconst(ctx), dat->block); + + return 1; +} + +static int camellia_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + size_t bl = EVP_CIPHER_CTX_block_size(ctx); + size_t i; + EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx); + + if (len < bl) + return 1; + + for (i = 0, len -= bl; i <= len; i += bl) + (*dat->block) (in + i, out + i, &dat->ks); + + return 1; +} + +static int camellia_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx); + + int num = EVP_CIPHER_CTX_num(ctx); + CRYPTO_ofb128_encrypt(in, out, len, &dat->ks, + EVP_CIPHER_CTX_iv_noconst(ctx), &num, dat->block); + EVP_CIPHER_CTX_set_num(ctx, num); + return 1; +} + +static int camellia_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx); + + int num = EVP_CIPHER_CTX_num(ctx); + CRYPTO_cfb128_encrypt(in, out, len, &dat->ks, + EVP_CIPHER_CTX_iv_noconst(ctx), &num, EVP_CIPHER_CTX_encrypting(ctx), dat->block); + EVP_CIPHER_CTX_set_num(ctx, num); + return 1; +} + +static int camellia_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx); + + int num = EVP_CIPHER_CTX_num(ctx); + CRYPTO_cfb128_8_encrypt(in, out, len, &dat->ks, + EVP_CIPHER_CTX_iv_noconst(ctx), &num, EVP_CIPHER_CTX_encrypting(ctx), dat->block); + EVP_CIPHER_CTX_set_num(ctx, num); + return 1; +} + +static int camellia_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx); + + if (EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS)) { + int num = EVP_CIPHER_CTX_num(ctx); + CRYPTO_cfb128_1_encrypt(in, out, len, &dat->ks, + EVP_CIPHER_CTX_iv_noconst(ctx), &num, EVP_CIPHER_CTX_encrypting(ctx), dat->block); + EVP_CIPHER_CTX_set_num(ctx, num); + return 1; + } + + while (len >= MAXBITCHUNK) { + int num = EVP_CIPHER_CTX_num(ctx); + CRYPTO_cfb128_1_encrypt(in, out, MAXBITCHUNK * 8, &dat->ks, + EVP_CIPHER_CTX_iv_noconst(ctx), &num, EVP_CIPHER_CTX_encrypting(ctx), dat->block); + EVP_CIPHER_CTX_set_num(ctx, num); + len -= MAXBITCHUNK; + out += MAXBITCHUNK; + in += MAXBITCHUNK; + } + if (len) { + int num = EVP_CIPHER_CTX_num(ctx); + CRYPTO_cfb128_1_encrypt(in, out, len * 8, &dat->ks, + EVP_CIPHER_CTX_iv_noconst(ctx), &num, EVP_CIPHER_CTX_encrypting(ctx), dat->block); + EVP_CIPHER_CTX_set_num(ctx, num); + } + + return 1; +} + +static int camellia_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + unsigned int num = EVP_CIPHER_CTX_num(ctx); + EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx); + + if (dat->stream.ctr) + CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks, + EVP_CIPHER_CTX_iv_noconst(ctx), + EVP_CIPHER_CTX_buf_noconst(ctx), &num, + dat->stream.ctr); + else + CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, + EVP_CIPHER_CTX_iv_noconst(ctx), + EVP_CIPHER_CTX_buf_noconst(ctx), &num, + dat->block); + EVP_CIPHER_CTX_set_num(ctx, num); + return 1; +} + +BLOCK_CIPHER_generic_pack(NID_camellia, 128, 0) + BLOCK_CIPHER_generic_pack(NID_camellia, 192, 0) + BLOCK_CIPHER_generic_pack(NID_camellia, 256, 0) +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_cast.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_cast.c new file mode 100644 index 000000000..259d44059 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_cast.c @@ -0,0 +1,40 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" + +#ifndef OPENSSL_NO_CAST +# include +# include +# include "internal/evp_int.h" +# include + +static int cast_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); + +typedef struct { + CAST_KEY ks; +} EVP_CAST_KEY; + +# define data(ctx) EVP_C_DATA(EVP_CAST_KEY,ctx) + +IMPLEMENT_BLOCK_CIPHER(cast5, ks, CAST, EVP_CAST_KEY, + NID_cast5, 8, CAST_KEY_LENGTH, 8, 64, + EVP_CIPH_VARIABLE_LENGTH, cast_init_key, NULL, + EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL) + +static int cast_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + CAST_set_key(&data(ctx)->ks, EVP_CIPHER_CTX_key_length(ctx), key); + return 1; +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_chacha20_poly1305.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_chacha20_poly1305.c new file mode 100644 index 000000000..c1917bb86 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_chacha20_poly1305.c @@ -0,0 +1,630 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" + +#ifndef OPENSSL_NO_CHACHA + +# include +# include +# include "evp_locl.h" +# include "internal/evp_int.h" +# include "internal/chacha.h" + +typedef struct { + union { + double align; /* this ensures even sizeof(EVP_CHACHA_KEY)%8==0 */ + unsigned int d[CHACHA_KEY_SIZE / 4]; + } key; + unsigned int counter[CHACHA_CTR_SIZE / 4]; + unsigned char buf[CHACHA_BLK_SIZE]; + unsigned int partial_len; +} EVP_CHACHA_KEY; + +#define data(ctx) ((EVP_CHACHA_KEY *)(ctx)->cipher_data) + +static int chacha_init_key(EVP_CIPHER_CTX *ctx, + const unsigned char user_key[CHACHA_KEY_SIZE], + const unsigned char iv[CHACHA_CTR_SIZE], int enc) +{ + EVP_CHACHA_KEY *key = data(ctx); + unsigned int i; + + if (user_key) + for (i = 0; i < CHACHA_KEY_SIZE; i+=4) { + key->key.d[i/4] = CHACHA_U8TOU32(user_key+i); + } + + if (iv) + for (i = 0; i < CHACHA_CTR_SIZE; i+=4) { + key->counter[i/4] = CHACHA_U8TOU32(iv+i); + } + + key->partial_len = 0; + + return 1; +} + +static int chacha_cipher(EVP_CIPHER_CTX * ctx, unsigned char *out, + const unsigned char *inp, size_t len) +{ + EVP_CHACHA_KEY *key = data(ctx); + unsigned int n, rem, ctr32; + + if ((n = key->partial_len)) { + while (len && n < CHACHA_BLK_SIZE) { + *out++ = *inp++ ^ key->buf[n++]; + len--; + } + key->partial_len = n; + + if (len == 0) + return 1; + + if (n == CHACHA_BLK_SIZE) { + key->partial_len = 0; + key->counter[0]++; + if (key->counter[0] == 0) + key->counter[1]++; + } + } + + rem = (unsigned int)(len % CHACHA_BLK_SIZE); + len -= rem; + ctr32 = key->counter[0]; + while (len >= CHACHA_BLK_SIZE) { + size_t blocks = len / CHACHA_BLK_SIZE; + /* + * 1<<28 is just a not-so-small yet not-so-large number... + * Below condition is practically never met, but it has to + * be checked for code correctness. + */ + if (sizeof(size_t)>sizeof(unsigned int) && blocks>(1U<<28)) + blocks = (1U<<28); + + /* + * As ChaCha20_ctr32 operates on 32-bit counter, caller + * has to handle overflow. 'if' below detects the + * overflow, which is then handled by limiting the + * amount of blocks to the exact overflow point... + */ + ctr32 += (unsigned int)blocks; + if (ctr32 < blocks) { + blocks -= ctr32; + ctr32 = 0; + } + blocks *= CHACHA_BLK_SIZE; + ChaCha20_ctr32(out, inp, blocks, key->key.d, key->counter); + len -= blocks; + inp += blocks; + out += blocks; + + key->counter[0] = ctr32; + if (ctr32 == 0) key->counter[1]++; + } + + if (rem) { + memset(key->buf, 0, sizeof(key->buf)); + ChaCha20_ctr32(key->buf, key->buf, CHACHA_BLK_SIZE, + key->key.d, key->counter); + for (n = 0; n < rem; n++) + out[n] = inp[n] ^ key->buf[n]; + key->partial_len = rem; + } + + return 1; +} + +static const EVP_CIPHER chacha20 = { + NID_chacha20, + 1, /* block_size */ + CHACHA_KEY_SIZE, /* key_len */ + CHACHA_CTR_SIZE, /* iv_len, 128-bit counter in the context */ + EVP_CIPH_CUSTOM_IV | EVP_CIPH_ALWAYS_CALL_INIT, + chacha_init_key, + chacha_cipher, + NULL, + sizeof(EVP_CHACHA_KEY), + NULL, + NULL, + NULL, + NULL +}; + +const EVP_CIPHER *EVP_chacha20(void) +{ + return &chacha20; +} + +# ifndef OPENSSL_NO_POLY1305 +# include "internal/poly1305.h" + +typedef struct { + EVP_CHACHA_KEY key; + unsigned int nonce[12/4]; + unsigned char tag[POLY1305_BLOCK_SIZE]; + unsigned char tls_aad[POLY1305_BLOCK_SIZE]; + struct { uint64_t aad, text; } len; + int aad, mac_inited, tag_len, nonce_len; + size_t tls_payload_length; +} EVP_CHACHA_AEAD_CTX; + +# define NO_TLS_PAYLOAD_LENGTH ((size_t)-1) +# define aead_data(ctx) ((EVP_CHACHA_AEAD_CTX *)(ctx)->cipher_data) +# define POLY1305_ctx(actx) ((POLY1305 *)(actx + 1)) + +static int chacha20_poly1305_init_key(EVP_CIPHER_CTX *ctx, + const unsigned char *inkey, + const unsigned char *iv, int enc) +{ + EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx); + + if (!inkey && !iv) + return 1; + + actx->len.aad = 0; + actx->len.text = 0; + actx->aad = 0; + actx->mac_inited = 0; + actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH; + + if (iv != NULL) { + unsigned char temp[CHACHA_CTR_SIZE] = { 0 }; + + /* pad on the left */ + if (actx->nonce_len <= CHACHA_CTR_SIZE) + memcpy(temp + CHACHA_CTR_SIZE - actx->nonce_len, iv, + actx->nonce_len); + + chacha_init_key(ctx, inkey, temp, enc); + + actx->nonce[0] = actx->key.counter[1]; + actx->nonce[1] = actx->key.counter[2]; + actx->nonce[2] = actx->key.counter[3]; + } else { + chacha_init_key(ctx, inkey, NULL, enc); + } + + return 1; +} + +# if !defined(OPENSSL_SMALL_FOOTPRINT) + +# if defined(POLY1305_ASM) && (defined(__x86_64) || defined(__x86_64__) || \ + defined(_M_AMD64) || defined(_M_X64)) +# define XOR128_HELPERS +void *xor128_encrypt_n_pad(void *out, const void *inp, void *otp, size_t len); +void *xor128_decrypt_n_pad(void *out, const void *inp, void *otp, size_t len); +static const unsigned char zero[4 * CHACHA_BLK_SIZE] = { 0 }; +# else +static const unsigned char zero[2 * CHACHA_BLK_SIZE] = { 0 }; +# endif + +static int chacha20_poly1305_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx); + size_t tail, tohash_len, buf_len, plen = actx->tls_payload_length; + unsigned char *buf, *tohash, *ctr, storage[sizeof(zero) + 32]; + + if (len != plen + POLY1305_BLOCK_SIZE) + return -1; + + buf = storage + ((0 - (size_t)storage) & 15); /* align */ + ctr = buf + CHACHA_BLK_SIZE; + tohash = buf + CHACHA_BLK_SIZE - POLY1305_BLOCK_SIZE; + +# ifdef XOR128_HELPERS + if (plen <= 3 * CHACHA_BLK_SIZE) { + actx->key.counter[0] = 0; + buf_len = (plen + 2 * CHACHA_BLK_SIZE - 1) & (0 - CHACHA_BLK_SIZE); + ChaCha20_ctr32(buf, zero, buf_len, actx->key.key.d, + actx->key.counter); + Poly1305_Init(POLY1305_ctx(actx), buf); + actx->key.partial_len = 0; + memcpy(tohash, actx->tls_aad, POLY1305_BLOCK_SIZE); + tohash_len = POLY1305_BLOCK_SIZE; + actx->len.aad = EVP_AEAD_TLS1_AAD_LEN; + actx->len.text = plen; + + if (plen) { + if (ctx->encrypt) + ctr = xor128_encrypt_n_pad(out, in, ctr, plen); + else + ctr = xor128_decrypt_n_pad(out, in, ctr, plen); + + in += plen; + out += plen; + tohash_len = (size_t)(ctr - tohash); + } + } +# else + if (plen <= CHACHA_BLK_SIZE) { + size_t i; + + actx->key.counter[0] = 0; + ChaCha20_ctr32(buf, zero, (buf_len = 2 * CHACHA_BLK_SIZE), + actx->key.key.d, actx->key.counter); + Poly1305_Init(POLY1305_ctx(actx), buf); + actx->key.partial_len = 0; + memcpy(tohash, actx->tls_aad, POLY1305_BLOCK_SIZE); + tohash_len = POLY1305_BLOCK_SIZE; + actx->len.aad = EVP_AEAD_TLS1_AAD_LEN; + actx->len.text = plen; + + if (ctx->encrypt) { + for (i = 0; i < plen; i++) { + out[i] = ctr[i] ^= in[i]; + } + } else { + for (i = 0; i < plen; i++) { + unsigned char c = in[i]; + out[i] = ctr[i] ^ c; + ctr[i] = c; + } + } + + in += i; + out += i; + + tail = (0 - i) & (POLY1305_BLOCK_SIZE - 1); + memset(ctr + i, 0, tail); + ctr += i + tail; + tohash_len += i + tail; + } +# endif + else { + actx->key.counter[0] = 0; + ChaCha20_ctr32(buf, zero, (buf_len = CHACHA_BLK_SIZE), + actx->key.key.d, actx->key.counter); + Poly1305_Init(POLY1305_ctx(actx), buf); + actx->key.counter[0] = 1; + actx->key.partial_len = 0; + Poly1305_Update(POLY1305_ctx(actx), actx->tls_aad, POLY1305_BLOCK_SIZE); + tohash = ctr; + tohash_len = 0; + actx->len.aad = EVP_AEAD_TLS1_AAD_LEN; + actx->len.text = plen; + + if (ctx->encrypt) { + ChaCha20_ctr32(out, in, plen, actx->key.key.d, actx->key.counter); + Poly1305_Update(POLY1305_ctx(actx), out, plen); + } else { + Poly1305_Update(POLY1305_ctx(actx), in, plen); + ChaCha20_ctr32(out, in, plen, actx->key.key.d, actx->key.counter); + } + + in += plen; + out += plen; + tail = (0 - plen) & (POLY1305_BLOCK_SIZE - 1); + Poly1305_Update(POLY1305_ctx(actx), zero, tail); + } + + { + const union { + long one; + char little; + } is_endian = { 1 }; + + if (is_endian.little) { + memcpy(ctr, (unsigned char *)&actx->len, POLY1305_BLOCK_SIZE); + } else { + ctr[0] = (unsigned char)(actx->len.aad); + ctr[1] = (unsigned char)(actx->len.aad>>8); + ctr[2] = (unsigned char)(actx->len.aad>>16); + ctr[3] = (unsigned char)(actx->len.aad>>24); + ctr[4] = (unsigned char)(actx->len.aad>>32); + ctr[5] = (unsigned char)(actx->len.aad>>40); + ctr[6] = (unsigned char)(actx->len.aad>>48); + ctr[7] = (unsigned char)(actx->len.aad>>56); + + ctr[8] = (unsigned char)(actx->len.text); + ctr[9] = (unsigned char)(actx->len.text>>8); + ctr[10] = (unsigned char)(actx->len.text>>16); + ctr[11] = (unsigned char)(actx->len.text>>24); + ctr[12] = (unsigned char)(actx->len.text>>32); + ctr[13] = (unsigned char)(actx->len.text>>40); + ctr[14] = (unsigned char)(actx->len.text>>48); + ctr[15] = (unsigned char)(actx->len.text>>56); + } + tohash_len += POLY1305_BLOCK_SIZE; + } + + Poly1305_Update(POLY1305_ctx(actx), tohash, tohash_len); + OPENSSL_cleanse(buf, buf_len); + Poly1305_Final(POLY1305_ctx(actx), ctx->encrypt ? actx->tag + : tohash); + + actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH; + + if (ctx->encrypt) { + memcpy(out, actx->tag, POLY1305_BLOCK_SIZE); + } else { + if (CRYPTO_memcmp(tohash, in, POLY1305_BLOCK_SIZE)) { + memset(out - (len - POLY1305_BLOCK_SIZE), 0, + len - POLY1305_BLOCK_SIZE); + return -1; + } + } + + return len; +} +# else +static const unsigned char zero[CHACHA_BLK_SIZE] = { 0 }; +# endif + +static int chacha20_poly1305_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx); + size_t rem, plen = actx->tls_payload_length; + + if (!actx->mac_inited) { +# if !defined(OPENSSL_SMALL_FOOTPRINT) + if (plen != NO_TLS_PAYLOAD_LENGTH && out != NULL) + return chacha20_poly1305_tls_cipher(ctx, out, in, len); +# endif + actx->key.counter[0] = 0; + ChaCha20_ctr32(actx->key.buf, zero, CHACHA_BLK_SIZE, + actx->key.key.d, actx->key.counter); + Poly1305_Init(POLY1305_ctx(actx), actx->key.buf); + actx->key.counter[0] = 1; + actx->key.partial_len = 0; + actx->len.aad = actx->len.text = 0; + actx->mac_inited = 1; + if (plen != NO_TLS_PAYLOAD_LENGTH) { + Poly1305_Update(POLY1305_ctx(actx), actx->tls_aad, + EVP_AEAD_TLS1_AAD_LEN); + actx->len.aad = EVP_AEAD_TLS1_AAD_LEN; + actx->aad = 1; + } + } + + if (in) { /* aad or text */ + if (out == NULL) { /* aad */ + Poly1305_Update(POLY1305_ctx(actx), in, len); + actx->len.aad += len; + actx->aad = 1; + return len; + } else { /* plain- or ciphertext */ + if (actx->aad) { /* wrap up aad */ + if ((rem = (size_t)actx->len.aad % POLY1305_BLOCK_SIZE)) + Poly1305_Update(POLY1305_ctx(actx), zero, + POLY1305_BLOCK_SIZE - rem); + actx->aad = 0; + } + + actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH; + if (plen == NO_TLS_PAYLOAD_LENGTH) + plen = len; + else if (len != plen + POLY1305_BLOCK_SIZE) + return -1; + + if (ctx->encrypt) { /* plaintext */ + chacha_cipher(ctx, out, in, plen); + Poly1305_Update(POLY1305_ctx(actx), out, plen); + in += plen; + out += plen; + actx->len.text += plen; + } else { /* ciphertext */ + Poly1305_Update(POLY1305_ctx(actx), in, plen); + chacha_cipher(ctx, out, in, plen); + in += plen; + out += plen; + actx->len.text += plen; + } + } + } + if (in == NULL /* explicit final */ + || plen != len) { /* or tls mode */ + const union { + long one; + char little; + } is_endian = { 1 }; + unsigned char temp[POLY1305_BLOCK_SIZE]; + + if (actx->aad) { /* wrap up aad */ + if ((rem = (size_t)actx->len.aad % POLY1305_BLOCK_SIZE)) + Poly1305_Update(POLY1305_ctx(actx), zero, + POLY1305_BLOCK_SIZE - rem); + actx->aad = 0; + } + + if ((rem = (size_t)actx->len.text % POLY1305_BLOCK_SIZE)) + Poly1305_Update(POLY1305_ctx(actx), zero, + POLY1305_BLOCK_SIZE - rem); + + if (is_endian.little) { + Poly1305_Update(POLY1305_ctx(actx), + (unsigned char *)&actx->len, POLY1305_BLOCK_SIZE); + } else { + temp[0] = (unsigned char)(actx->len.aad); + temp[1] = (unsigned char)(actx->len.aad>>8); + temp[2] = (unsigned char)(actx->len.aad>>16); + temp[3] = (unsigned char)(actx->len.aad>>24); + temp[4] = (unsigned char)(actx->len.aad>>32); + temp[5] = (unsigned char)(actx->len.aad>>40); + temp[6] = (unsigned char)(actx->len.aad>>48); + temp[7] = (unsigned char)(actx->len.aad>>56); + + temp[8] = (unsigned char)(actx->len.text); + temp[9] = (unsigned char)(actx->len.text>>8); + temp[10] = (unsigned char)(actx->len.text>>16); + temp[11] = (unsigned char)(actx->len.text>>24); + temp[12] = (unsigned char)(actx->len.text>>32); + temp[13] = (unsigned char)(actx->len.text>>40); + temp[14] = (unsigned char)(actx->len.text>>48); + temp[15] = (unsigned char)(actx->len.text>>56); + + Poly1305_Update(POLY1305_ctx(actx), temp, POLY1305_BLOCK_SIZE); + } + Poly1305_Final(POLY1305_ctx(actx), ctx->encrypt ? actx->tag + : temp); + actx->mac_inited = 0; + + if (in != NULL && len != plen) { /* tls mode */ + if (ctx->encrypt) { + memcpy(out, actx->tag, POLY1305_BLOCK_SIZE); + } else { + if (CRYPTO_memcmp(temp, in, POLY1305_BLOCK_SIZE)) { + memset(out - plen, 0, plen); + return -1; + } + } + } + else if (!ctx->encrypt) { + if (CRYPTO_memcmp(temp, actx->tag, actx->tag_len)) + return -1; + } + } + return len; +} + +static int chacha20_poly1305_cleanup(EVP_CIPHER_CTX *ctx) +{ + EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx); + if (actx) + OPENSSL_cleanse(ctx->cipher_data, sizeof(*actx) + Poly1305_ctx_size()); + return 1; +} + +static int chacha20_poly1305_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, + void *ptr) +{ + EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx); + + switch(type) { + case EVP_CTRL_INIT: + if (actx == NULL) + actx = ctx->cipher_data + = OPENSSL_zalloc(sizeof(*actx) + Poly1305_ctx_size()); + if (actx == NULL) { + EVPerr(EVP_F_CHACHA20_POLY1305_CTRL, EVP_R_INITIALIZATION_ERROR); + return 0; + } + actx->len.aad = 0; + actx->len.text = 0; + actx->aad = 0; + actx->mac_inited = 0; + actx->tag_len = 0; + actx->nonce_len = 12; + actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH; + memset(actx->tls_aad, 0, POLY1305_BLOCK_SIZE); + return 1; + + case EVP_CTRL_COPY: + if (actx) { + EVP_CIPHER_CTX *dst = (EVP_CIPHER_CTX *)ptr; + + dst->cipher_data = + OPENSSL_memdup(actx, sizeof(*actx) + Poly1305_ctx_size()); + if (dst->cipher_data == NULL) { + EVPerr(EVP_F_CHACHA20_POLY1305_CTRL, EVP_R_COPY_ERROR); + return 0; + } + } + return 1; + + case EVP_CTRL_AEAD_SET_IVLEN: + if (arg <= 0 || arg > CHACHA_CTR_SIZE) + return 0; + actx->nonce_len = arg; + return 1; + + case EVP_CTRL_AEAD_SET_IV_FIXED: + if (arg != 12) + return 0; + actx->nonce[0] = actx->key.counter[1] + = CHACHA_U8TOU32((unsigned char *)ptr); + actx->nonce[1] = actx->key.counter[2] + = CHACHA_U8TOU32((unsigned char *)ptr+4); + actx->nonce[2] = actx->key.counter[3] + = CHACHA_U8TOU32((unsigned char *)ptr+8); + return 1; + + case EVP_CTRL_AEAD_SET_TAG: + if (arg <= 0 || arg > POLY1305_BLOCK_SIZE) + return 0; + if (ptr != NULL) { + memcpy(actx->tag, ptr, arg); + actx->tag_len = arg; + } + return 1; + + case EVP_CTRL_AEAD_GET_TAG: + if (arg <= 0 || arg > POLY1305_BLOCK_SIZE || !ctx->encrypt) + return 0; + memcpy(ptr, actx->tag, arg); + return 1; + + case EVP_CTRL_AEAD_TLS1_AAD: + if (arg != EVP_AEAD_TLS1_AAD_LEN) + return 0; + { + unsigned int len; + unsigned char *aad = ptr; + + memcpy(actx->tls_aad, ptr, EVP_AEAD_TLS1_AAD_LEN); + len = aad[EVP_AEAD_TLS1_AAD_LEN - 2] << 8 | + aad[EVP_AEAD_TLS1_AAD_LEN - 1]; + aad = actx->tls_aad; + if (!ctx->encrypt) { + if (len < POLY1305_BLOCK_SIZE) + return 0; + len -= POLY1305_BLOCK_SIZE; /* discount attached tag */ + aad[EVP_AEAD_TLS1_AAD_LEN - 2] = (unsigned char)(len >> 8); + aad[EVP_AEAD_TLS1_AAD_LEN - 1] = (unsigned char)len; + } + actx->tls_payload_length = len; + + /* + * merge record sequence number as per RFC7905 + */ + actx->key.counter[1] = actx->nonce[0]; + actx->key.counter[2] = actx->nonce[1] ^ CHACHA_U8TOU32(aad); + actx->key.counter[3] = actx->nonce[2] ^ CHACHA_U8TOU32(aad+4); + actx->mac_inited = 0; + + return POLY1305_BLOCK_SIZE; /* tag length */ + } + + case EVP_CTRL_AEAD_SET_MAC_KEY: + /* no-op */ + return 1; + + default: + return -1; + } +} + +static EVP_CIPHER chacha20_poly1305 = { + NID_chacha20_poly1305, + 1, /* block_size */ + CHACHA_KEY_SIZE, /* key_len */ + 12, /* iv_len, 96-bit nonce in the context */ + EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_CUSTOM_IV | + EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT | + EVP_CIPH_CUSTOM_COPY | EVP_CIPH_FLAG_CUSTOM_CIPHER, + chacha20_poly1305_init_key, + chacha20_poly1305_cipher, + chacha20_poly1305_cleanup, + 0, /* 0 moves context-specific structure allocation to ctrl */ + NULL, /* set_asn1_parameters */ + NULL, /* get_asn1_parameters */ + chacha20_poly1305_ctrl, + NULL /* app_data */ +}; + +const EVP_CIPHER *EVP_chacha20_poly1305(void) +{ + return(&chacha20_poly1305); +} +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_des.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_des.c new file mode 100644 index 000000000..c13fb3e25 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_des.c @@ -0,0 +1,242 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#ifndef OPENSSL_NO_DES +# include +# include +# include "internal/evp_int.h" +# include +# include + +typedef struct { + union { + double align; + DES_key_schedule ks; + } ks; + union { + void (*cbc) (const void *, void *, size_t, + const DES_key_schedule *, unsigned char *); + } stream; +} EVP_DES_KEY; + +# if defined(AES_ASM) && (defined(__sparc) || defined(__sparc__)) +/* ----------^^^ this is not a typo, just a way to detect that + * assembler support was in general requested... */ +# include "sparc_arch.h" + +extern unsigned int OPENSSL_sparcv9cap_P[]; + +# define SPARC_DES_CAPABLE (OPENSSL_sparcv9cap_P[1] & CFR_DES) + +void des_t4_key_expand(const void *key, DES_key_schedule *ks); +void des_t4_cbc_encrypt(const void *inp, void *out, size_t len, + const DES_key_schedule *ks, unsigned char iv[8]); +void des_t4_cbc_decrypt(const void *inp, void *out, size_t len, + const DES_key_schedule *ks, unsigned char iv[8]); +# endif + +static int des_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); +static int des_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr); + +/* + * Because of various casts and different names can't use + * IMPLEMENT_BLOCK_CIPHER + */ + +static int des_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + BLOCK_CIPHER_ecb_loop() + DES_ecb_encrypt((DES_cblock *)(in + i), (DES_cblock *)(out + i), + EVP_CIPHER_CTX_get_cipher_data(ctx), + EVP_CIPHER_CTX_encrypting(ctx)); + return 1; +} + +static int des_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + while (inl >= EVP_MAXCHUNK) { + int num = EVP_CIPHER_CTX_num(ctx); + DES_ofb64_encrypt(in, out, (long)EVP_MAXCHUNK, + EVP_CIPHER_CTX_get_cipher_data(ctx), + (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), &num); + EVP_CIPHER_CTX_set_num(ctx, num); + inl -= EVP_MAXCHUNK; + in += EVP_MAXCHUNK; + out += EVP_MAXCHUNK; + } + if (inl) { + int num = EVP_CIPHER_CTX_num(ctx); + DES_ofb64_encrypt(in, out, (long)inl, + EVP_CIPHER_CTX_get_cipher_data(ctx), + (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), &num); + EVP_CIPHER_CTX_set_num(ctx, num); + } + return 1; +} + +static int des_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + EVP_DES_KEY *dat = (EVP_DES_KEY *) EVP_CIPHER_CTX_get_cipher_data(ctx); + + if (dat->stream.cbc != NULL) { + (*dat->stream.cbc) (in, out, inl, &dat->ks.ks, + EVP_CIPHER_CTX_iv_noconst(ctx)); + return 1; + } + while (inl >= EVP_MAXCHUNK) { + DES_ncbc_encrypt(in, out, (long)EVP_MAXCHUNK, + EVP_CIPHER_CTX_get_cipher_data(ctx), + (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), + EVP_CIPHER_CTX_encrypting(ctx)); + inl -= EVP_MAXCHUNK; + in += EVP_MAXCHUNK; + out += EVP_MAXCHUNK; + } + if (inl) + DES_ncbc_encrypt(in, out, (long)inl, + EVP_CIPHER_CTX_get_cipher_data(ctx), + (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), + EVP_CIPHER_CTX_encrypting(ctx)); + return 1; +} + +static int des_cfb64_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + while (inl >= EVP_MAXCHUNK) { + int num = EVP_CIPHER_CTX_num(ctx); + DES_cfb64_encrypt(in, out, (long)EVP_MAXCHUNK, + EVP_CIPHER_CTX_get_cipher_data(ctx), + (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), &num, + EVP_CIPHER_CTX_encrypting(ctx)); + EVP_CIPHER_CTX_set_num(ctx, num); + inl -= EVP_MAXCHUNK; + in += EVP_MAXCHUNK; + out += EVP_MAXCHUNK; + } + if (inl) { + int num = EVP_CIPHER_CTX_num(ctx); + DES_cfb64_encrypt(in, out, (long)inl, + EVP_CIPHER_CTX_get_cipher_data(ctx), + (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), &num, + EVP_CIPHER_CTX_encrypting(ctx)); + EVP_CIPHER_CTX_set_num(ctx, num); + } + return 1; +} + +/* + * Although we have a CFB-r implementation for DES, it doesn't pack the right + * way, so wrap it here + */ +static int des_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + size_t n, chunk = EVP_MAXCHUNK / 8; + unsigned char c[1], d[1]; + + if (inl < chunk) + chunk = inl; + + while (inl && inl >= chunk) { + for (n = 0; n < chunk * 8; ++n) { + c[0] = (in[n / 8] & (1 << (7 - n % 8))) ? 0x80 : 0; + DES_cfb_encrypt(c, d, 1, 1, EVP_CIPHER_CTX_get_cipher_data(ctx), + (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), + EVP_CIPHER_CTX_encrypting(ctx)); + out[n / 8] = + (out[n / 8] & ~(0x80 >> (unsigned int)(n % 8))) | + ((d[0] & 0x80) >> (unsigned int)(n % 8)); + } + inl -= chunk; + in += chunk; + out += chunk; + if (inl < chunk) + chunk = inl; + } + + return 1; +} + +static int des_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + while (inl >= EVP_MAXCHUNK) { + DES_cfb_encrypt(in, out, 8, (long)EVP_MAXCHUNK, + EVP_CIPHER_CTX_get_cipher_data(ctx), + (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), + EVP_CIPHER_CTX_encrypting(ctx)); + inl -= EVP_MAXCHUNK; + in += EVP_MAXCHUNK; + out += EVP_MAXCHUNK; + } + if (inl) + DES_cfb_encrypt(in, out, 8, (long)inl, + EVP_CIPHER_CTX_get_cipher_data(ctx), + (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), + EVP_CIPHER_CTX_encrypting(ctx)); + return 1; +} + +BLOCK_CIPHER_defs(des, EVP_DES_KEY, NID_des, 8, 8, 8, 64, + EVP_CIPH_RAND_KEY, des_init_key, NULL, + EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, des_ctrl) + + BLOCK_CIPHER_def_cfb(des, EVP_DES_KEY, NID_des, 8, 8, 1, + EVP_CIPH_RAND_KEY, des_init_key, NULL, + EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, des_ctrl) + + BLOCK_CIPHER_def_cfb(des, EVP_DES_KEY, NID_des, 8, 8, 8, + EVP_CIPH_RAND_KEY, des_init_key, NULL, + EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, des_ctrl) + +static int des_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + DES_cblock *deskey = (DES_cblock *)key; + EVP_DES_KEY *dat = (EVP_DES_KEY *) EVP_CIPHER_CTX_get_cipher_data(ctx); + + dat->stream.cbc = NULL; +# if defined(SPARC_DES_CAPABLE) + if (SPARC_DES_CAPABLE) { + int mode = EVP_CIPHER_CTX_mode(ctx); + + if (mode == EVP_CIPH_CBC_MODE) { + des_t4_key_expand(key, &dat->ks.ks); + dat->stream.cbc = enc ? des_t4_cbc_encrypt : des_t4_cbc_decrypt; + return 1; + } + } +# endif + DES_set_key_unchecked(deskey, EVP_CIPHER_CTX_get_cipher_data(ctx)); + return 1; +} + +static int des_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) +{ + + switch (type) { + case EVP_CTRL_RAND_KEY: + if (RAND_priv_bytes(ptr, 8) <= 0) + return 0; + DES_set_odd_parity((DES_cblock *)ptr); + return 1; + + default: + return -1; + } +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_des3.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_des3.c new file mode 100644 index 000000000..6b492ce47 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_des3.c @@ -0,0 +1,424 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#ifndef OPENSSL_NO_DES +# include +# include +# include "internal/evp_int.h" +# include +# include +# include "evp_locl.h" + +typedef struct { + union { + double align; + DES_key_schedule ks[3]; + } ks; + union { + void (*cbc) (const void *, void *, size_t, + const DES_key_schedule *, unsigned char *); + } stream; +} DES_EDE_KEY; +# define ks1 ks.ks[0] +# define ks2 ks.ks[1] +# define ks3 ks.ks[2] + +# if defined(AES_ASM) && (defined(__sparc) || defined(__sparc__)) +/* ---------^^^ this is not a typo, just a way to detect that + * assembler support was in general requested... */ +# include "sparc_arch.h" + +extern unsigned int OPENSSL_sparcv9cap_P[]; + +# define SPARC_DES_CAPABLE (OPENSSL_sparcv9cap_P[1] & CFR_DES) + +void des_t4_key_expand(const void *key, DES_key_schedule *ks); +void des_t4_ede3_cbc_encrypt(const void *inp, void *out, size_t len, + const DES_key_schedule ks[3], unsigned char iv[8]); +void des_t4_ede3_cbc_decrypt(const void *inp, void *out, size_t len, + const DES_key_schedule ks[3], unsigned char iv[8]); +# endif + +static int des_ede_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); + +static int des_ede3_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); + +static int des3_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr); + +# define data(ctx) EVP_C_DATA(DES_EDE_KEY,ctx) + +/* + * Because of various casts and different args can't use + * IMPLEMENT_BLOCK_CIPHER + */ + +static int des_ede_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + BLOCK_CIPHER_ecb_loop() + DES_ecb3_encrypt((const_DES_cblock *)(in + i), + (DES_cblock *)(out + i), + &data(ctx)->ks1, &data(ctx)->ks2, + &data(ctx)->ks3, EVP_CIPHER_CTX_encrypting(ctx)); + return 1; +} + +static int des_ede_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + while (inl >= EVP_MAXCHUNK) { + int num = EVP_CIPHER_CTX_num(ctx); + DES_ede3_ofb64_encrypt(in, out, (long)EVP_MAXCHUNK, + &data(ctx)->ks1, &data(ctx)->ks2, + &data(ctx)->ks3, + (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), + &num); + EVP_CIPHER_CTX_set_num(ctx, num); + inl -= EVP_MAXCHUNK; + in += EVP_MAXCHUNK; + out += EVP_MAXCHUNK; + } + if (inl) { + int num = EVP_CIPHER_CTX_num(ctx); + DES_ede3_ofb64_encrypt(in, out, (long)inl, + &data(ctx)->ks1, &data(ctx)->ks2, + &data(ctx)->ks3, + (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), + &num); + EVP_CIPHER_CTX_set_num(ctx, num); + } + return 1; +} + +static int des_ede_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + DES_EDE_KEY *dat = data(ctx); + + if (dat->stream.cbc != NULL) { + (*dat->stream.cbc) (in, out, inl, dat->ks.ks, + EVP_CIPHER_CTX_iv_noconst(ctx)); + return 1; + } + + while (inl >= EVP_MAXCHUNK) { + DES_ede3_cbc_encrypt(in, out, (long)EVP_MAXCHUNK, + &dat->ks1, &dat->ks2, &dat->ks3, + (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), + EVP_CIPHER_CTX_encrypting(ctx)); + inl -= EVP_MAXCHUNK; + in += EVP_MAXCHUNK; + out += EVP_MAXCHUNK; + } + if (inl) + DES_ede3_cbc_encrypt(in, out, (long)inl, + &dat->ks1, &dat->ks2, &dat->ks3, + (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), + EVP_CIPHER_CTX_encrypting(ctx)); + return 1; +} + +static int des_ede_cfb64_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + while (inl >= EVP_MAXCHUNK) { + int num = EVP_CIPHER_CTX_num(ctx); + DES_ede3_cfb64_encrypt(in, out, (long)EVP_MAXCHUNK, + &data(ctx)->ks1, &data(ctx)->ks2, + &data(ctx)->ks3, + (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), + &num, EVP_CIPHER_CTX_encrypting(ctx)); + EVP_CIPHER_CTX_set_num(ctx, num); + inl -= EVP_MAXCHUNK; + in += EVP_MAXCHUNK; + out += EVP_MAXCHUNK; + } + if (inl) { + int num = EVP_CIPHER_CTX_num(ctx); + DES_ede3_cfb64_encrypt(in, out, (long)inl, + &data(ctx)->ks1, &data(ctx)->ks2, + &data(ctx)->ks3, + (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), + &num, EVP_CIPHER_CTX_encrypting(ctx)); + EVP_CIPHER_CTX_set_num(ctx, num); + } + return 1; +} + +/* + * Although we have a CFB-r implementation for 3-DES, it doesn't pack the + * right way, so wrap it here + */ +static int des_ede3_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + size_t n; + unsigned char c[1], d[1]; + + if (!EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS)) + inl *= 8; + for (n = 0; n < inl; ++n) { + c[0] = (in[n / 8] & (1 << (7 - n % 8))) ? 0x80 : 0; + DES_ede3_cfb_encrypt(c, d, 1, 1, + &data(ctx)->ks1, &data(ctx)->ks2, + &data(ctx)->ks3, + (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), + EVP_CIPHER_CTX_encrypting(ctx)); + out[n / 8] = (out[n / 8] & ~(0x80 >> (unsigned int)(n % 8))) + | ((d[0] & 0x80) >> (unsigned int)(n % 8)); + } + + return 1; +} + +static int des_ede3_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + while (inl >= EVP_MAXCHUNK) { + DES_ede3_cfb_encrypt(in, out, 8, (long)EVP_MAXCHUNK, + &data(ctx)->ks1, &data(ctx)->ks2, + &data(ctx)->ks3, + (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), + EVP_CIPHER_CTX_encrypting(ctx)); + inl -= EVP_MAXCHUNK; + in += EVP_MAXCHUNK; + out += EVP_MAXCHUNK; + } + if (inl) + DES_ede3_cfb_encrypt(in, out, 8, (long)inl, + &data(ctx)->ks1, &data(ctx)->ks2, + &data(ctx)->ks3, + (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), + EVP_CIPHER_CTX_encrypting(ctx)); + return 1; +} + +BLOCK_CIPHER_defs(des_ede, DES_EDE_KEY, NID_des_ede, 8, 16, 8, 64, + EVP_CIPH_RAND_KEY | EVP_CIPH_FLAG_DEFAULT_ASN1, + des_ede_init_key, NULL, NULL, NULL, des3_ctrl) +# define des_ede3_cfb64_cipher des_ede_cfb64_cipher +# define des_ede3_ofb_cipher des_ede_ofb_cipher +# define des_ede3_cbc_cipher des_ede_cbc_cipher +# define des_ede3_ecb_cipher des_ede_ecb_cipher + BLOCK_CIPHER_defs(des_ede3, DES_EDE_KEY, NID_des_ede3, 8, 24, 8, 64, + EVP_CIPH_RAND_KEY | EVP_CIPH_FLAG_DEFAULT_ASN1, + des_ede3_init_key, NULL, NULL, NULL, des3_ctrl) + + BLOCK_CIPHER_def_cfb(des_ede3, DES_EDE_KEY, NID_des_ede3, 24, 8, 1, + EVP_CIPH_RAND_KEY | EVP_CIPH_FLAG_DEFAULT_ASN1, + des_ede3_init_key, NULL, NULL, NULL, des3_ctrl) + + BLOCK_CIPHER_def_cfb(des_ede3, DES_EDE_KEY, NID_des_ede3, 24, 8, 8, + EVP_CIPH_RAND_KEY | EVP_CIPH_FLAG_DEFAULT_ASN1, + des_ede3_init_key, NULL, NULL, NULL, des3_ctrl) + +static int des_ede_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + DES_cblock *deskey = (DES_cblock *)key; + DES_EDE_KEY *dat = data(ctx); + + dat->stream.cbc = NULL; +# if defined(SPARC_DES_CAPABLE) + if (SPARC_DES_CAPABLE) { + int mode = EVP_CIPHER_CTX_mode(ctx); + + if (mode == EVP_CIPH_CBC_MODE) { + des_t4_key_expand(&deskey[0], &dat->ks1); + des_t4_key_expand(&deskey[1], &dat->ks2); + memcpy(&dat->ks3, &dat->ks1, sizeof(dat->ks1)); + dat->stream.cbc = enc ? des_t4_ede3_cbc_encrypt : + des_t4_ede3_cbc_decrypt; + return 1; + } + } +# endif + DES_set_key_unchecked(&deskey[0], &dat->ks1); + DES_set_key_unchecked(&deskey[1], &dat->ks2); + memcpy(&dat->ks3, &dat->ks1, sizeof(dat->ks1)); + return 1; +} + +static int des_ede3_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + DES_cblock *deskey = (DES_cblock *)key; + DES_EDE_KEY *dat = data(ctx); + + dat->stream.cbc = NULL; +# if defined(SPARC_DES_CAPABLE) + if (SPARC_DES_CAPABLE) { + int mode = EVP_CIPHER_CTX_mode(ctx); + + if (mode == EVP_CIPH_CBC_MODE) { + des_t4_key_expand(&deskey[0], &dat->ks1); + des_t4_key_expand(&deskey[1], &dat->ks2); + des_t4_key_expand(&deskey[2], &dat->ks3); + dat->stream.cbc = enc ? des_t4_ede3_cbc_encrypt : + des_t4_ede3_cbc_decrypt; + return 1; + } + } +# endif + DES_set_key_unchecked(&deskey[0], &dat->ks1); + DES_set_key_unchecked(&deskey[1], &dat->ks2); + DES_set_key_unchecked(&deskey[2], &dat->ks3); + return 1; +} + +static int des3_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) +{ + + DES_cblock *deskey = ptr; + + switch (type) { + case EVP_CTRL_RAND_KEY: + if (RAND_priv_bytes(ptr, EVP_CIPHER_CTX_key_length(ctx)) <= 0) + return 0; + DES_set_odd_parity(deskey); + if (EVP_CIPHER_CTX_key_length(ctx) >= 16) + DES_set_odd_parity(deskey + 1); + if (EVP_CIPHER_CTX_key_length(ctx) >= 24) + DES_set_odd_parity(deskey + 2); + return 1; + + default: + return -1; + } +} + +const EVP_CIPHER *EVP_des_ede(void) +{ + return &des_ede_ecb; +} + +const EVP_CIPHER *EVP_des_ede3(void) +{ + return &des_ede3_ecb; +} + + +# include + +static const unsigned char wrap_iv[8] = + { 0x4a, 0xdd, 0xa2, 0x2c, 0x79, 0xe8, 0x21, 0x05 }; + +static int des_ede3_unwrap(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + unsigned char icv[8], iv[8], sha1tmp[SHA_DIGEST_LENGTH]; + int rv = -1; + if (inl < 24) + return -1; + if (out == NULL) + return inl - 16; + memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), wrap_iv, 8); + /* Decrypt first block which will end up as icv */ + des_ede_cbc_cipher(ctx, icv, in, 8); + /* Decrypt central blocks */ + /* + * If decrypting in place move whole output along a block so the next + * des_ede_cbc_cipher is in place. + */ + if (out == in) { + memmove(out, out + 8, inl - 8); + in -= 8; + } + des_ede_cbc_cipher(ctx, out, in + 8, inl - 16); + /* Decrypt final block which will be IV */ + des_ede_cbc_cipher(ctx, iv, in + inl - 8, 8); + /* Reverse order of everything */ + BUF_reverse(icv, NULL, 8); + BUF_reverse(out, NULL, inl - 16); + BUF_reverse(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 8); + /* Decrypt again using new IV */ + des_ede_cbc_cipher(ctx, out, out, inl - 16); + des_ede_cbc_cipher(ctx, icv, icv, 8); + /* Work out SHA1 hash of first portion */ + SHA1(out, inl - 16, sha1tmp); + + if (!CRYPTO_memcmp(sha1tmp, icv, 8)) + rv = inl - 16; + OPENSSL_cleanse(icv, 8); + OPENSSL_cleanse(sha1tmp, SHA_DIGEST_LENGTH); + OPENSSL_cleanse(iv, 8); + OPENSSL_cleanse(EVP_CIPHER_CTX_iv_noconst(ctx), 8); + if (rv == -1) + OPENSSL_cleanse(out, inl - 16); + + return rv; +} + +static int des_ede3_wrap(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + unsigned char sha1tmp[SHA_DIGEST_LENGTH]; + if (out == NULL) + return inl + 16; + /* Copy input to output buffer + 8 so we have space for IV */ + memmove(out + 8, in, inl); + /* Work out ICV */ + SHA1(in, inl, sha1tmp); + memcpy(out + inl + 8, sha1tmp, 8); + OPENSSL_cleanse(sha1tmp, SHA_DIGEST_LENGTH); + /* Generate random IV */ + if (RAND_bytes(EVP_CIPHER_CTX_iv_noconst(ctx), 8) <= 0) + return -1; + memcpy(out, EVP_CIPHER_CTX_iv_noconst(ctx), 8); + /* Encrypt everything after IV in place */ + des_ede_cbc_cipher(ctx, out + 8, out + 8, inl + 8); + BUF_reverse(out, NULL, inl + 16); + memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), wrap_iv, 8); + des_ede_cbc_cipher(ctx, out, out, inl + 16); + return inl + 16; +} + +static int des_ede3_wrap_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + /* + * Sanity check input length: we typically only wrap keys so EVP_MAXCHUNK + * is more than will ever be needed. Also input length must be a multiple + * of 8 bits. + */ + if (inl >= EVP_MAXCHUNK || inl % 8) + return -1; + + if (is_partially_overlapping(out, in, inl)) { + EVPerr(EVP_F_DES_EDE3_WRAP_CIPHER, EVP_R_PARTIALLY_OVERLAPPING); + return 0; + } + + if (EVP_CIPHER_CTX_encrypting(ctx)) + return des_ede3_wrap(ctx, out, in, inl); + else + return des_ede3_unwrap(ctx, out, in, inl); +} + +static const EVP_CIPHER des3_wrap = { + NID_id_smime_alg_CMS3DESwrap, + 8, 24, 0, + EVP_CIPH_WRAP_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER + | EVP_CIPH_FLAG_DEFAULT_ASN1, + des_ede3_init_key, des_ede3_wrap_cipher, + NULL, + sizeof(DES_EDE_KEY), + NULL, NULL, NULL, NULL +}; + +const EVP_CIPHER *EVP_des_ede3_wrap(void) +{ + return &des3_wrap; +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_idea.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_idea.c new file mode 100644 index 000000000..93f6a4131 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_idea.c @@ -0,0 +1,70 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" + +#ifndef OPENSSL_NO_IDEA +# include +# include +# include "internal/evp_int.h" +# include + +/* Can't use IMPLEMENT_BLOCK_CIPHER because IDEA_ecb_encrypt is different */ + +typedef struct { + IDEA_KEY_SCHEDULE ks; +} EVP_IDEA_KEY; + +static int idea_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); + +/* + * NB IDEA_ecb_encrypt doesn't take an 'encrypt' argument so we treat it as a + * special case + */ + +static int idea_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + BLOCK_CIPHER_ecb_loop() + IDEA_ecb_encrypt(in + i, out + i, &EVP_C_DATA(EVP_IDEA_KEY,ctx)->ks); + return 1; +} + +BLOCK_CIPHER_func_cbc(idea, IDEA, EVP_IDEA_KEY, ks) +BLOCK_CIPHER_func_ofb(idea, IDEA, 64, EVP_IDEA_KEY, ks) +BLOCK_CIPHER_func_cfb(idea, IDEA, 64, EVP_IDEA_KEY, ks) + +BLOCK_CIPHER_defs(idea, IDEA_KEY_SCHEDULE, NID_idea, 8, 16, 8, 64, + 0, idea_init_key, NULL, + EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL) + +static int idea_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + if (!enc) { + if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_OFB_MODE) + enc = 1; + else if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CFB_MODE) + enc = 1; + } + if (enc) + IDEA_set_encrypt_key(key, &EVP_C_DATA(EVP_IDEA_KEY,ctx)->ks); + else { + IDEA_KEY_SCHEDULE tmp; + + IDEA_set_encrypt_key(key, &tmp); + IDEA_set_decrypt_key(&tmp, &EVP_C_DATA(EVP_IDEA_KEY,ctx)->ks); + OPENSSL_cleanse((unsigned char *)&tmp, sizeof(IDEA_KEY_SCHEDULE)); + } + return 1; +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_null.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_null.c new file mode 100644 index 000000000..18a846821 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_null.c @@ -0,0 +1,50 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include "internal/evp_int.h" + +static int null_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); +static int null_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl); +static const EVP_CIPHER n_cipher = { + NID_undef, + 1, 0, 0, 0, + null_init_key, + null_cipher, + NULL, + 0, + NULL, + NULL, + NULL, + NULL +}; + +const EVP_CIPHER *EVP_enc_null(void) +{ + return &n_cipher; +} + +static int null_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + return 1; +} + +static int null_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + if (in != out) + memcpy(out, in, inl); + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_old.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_old.c new file mode 100644 index 000000000..927908f87 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_old.c @@ -0,0 +1,113 @@ +/* + * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#if OPENSSL_API_COMPAT >= 0x00908000L +NON_EMPTY_TRANSLATION_UNIT +#else + +# include + +/* + * Define some deprecated functions, so older programs don't crash and burn + * too quickly. On Windows and VMS, these will never be used, since + * functions and variables in shared libraries are selected by entry point + * location, not by name. + */ + +# ifndef OPENSSL_NO_BF +# undef EVP_bf_cfb +const EVP_CIPHER *EVP_bf_cfb(void); +const EVP_CIPHER *EVP_bf_cfb(void) +{ + return EVP_bf_cfb64(); +} +# endif + +# ifndef OPENSSL_NO_DES +# undef EVP_des_cfb +const EVP_CIPHER *EVP_des_cfb(void); +const EVP_CIPHER *EVP_des_cfb(void) +{ + return EVP_des_cfb64(); +} + +# undef EVP_des_ede3_cfb +const EVP_CIPHER *EVP_des_ede3_cfb(void); +const EVP_CIPHER *EVP_des_ede3_cfb(void) +{ + return EVP_des_ede3_cfb64(); +} + +# undef EVP_des_ede_cfb +const EVP_CIPHER *EVP_des_ede_cfb(void); +const EVP_CIPHER *EVP_des_ede_cfb(void) +{ + return EVP_des_ede_cfb64(); +} +# endif + +# ifndef OPENSSL_NO_IDEA +# undef EVP_idea_cfb +const EVP_CIPHER *EVP_idea_cfb(void); +const EVP_CIPHER *EVP_idea_cfb(void) +{ + return EVP_idea_cfb64(); +} +# endif + +# ifndef OPENSSL_NO_RC2 +# undef EVP_rc2_cfb +const EVP_CIPHER *EVP_rc2_cfb(void); +const EVP_CIPHER *EVP_rc2_cfb(void) +{ + return EVP_rc2_cfb64(); +} +# endif + +# ifndef OPENSSL_NO_CAST +# undef EVP_cast5_cfb +const EVP_CIPHER *EVP_cast5_cfb(void); +const EVP_CIPHER *EVP_cast5_cfb(void) +{ + return EVP_cast5_cfb64(); +} +# endif + +# ifndef OPENSSL_NO_RC5 +# undef EVP_rc5_32_12_16_cfb +const EVP_CIPHER *EVP_rc5_32_12_16_cfb(void); +const EVP_CIPHER *EVP_rc5_32_12_16_cfb(void) +{ + return EVP_rc5_32_12_16_cfb64(); +} +# endif + +# undef EVP_aes_128_cfb +const EVP_CIPHER *EVP_aes_128_cfb(void); +const EVP_CIPHER *EVP_aes_128_cfb(void) +{ + return EVP_aes_128_cfb128(); +} + +# undef EVP_aes_192_cfb +const EVP_CIPHER *EVP_aes_192_cfb(void); +const EVP_CIPHER *EVP_aes_192_cfb(void) +{ + return EVP_aes_192_cfb128(); +} + +# undef EVP_aes_256_cfb +const EVP_CIPHER *EVP_aes_256_cfb(void); +const EVP_CIPHER *EVP_aes_256_cfb(void) +{ + return EVP_aes_256_cfb128(); +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_rc2.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_rc2.c new file mode 100644 index 000000000..aa0d14018 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_rc2.c @@ -0,0 +1,191 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" + +#ifndef OPENSSL_NO_RC2 + +# include +# include +# include "internal/evp_int.h" +# include + +static int rc2_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); +static int rc2_meth_to_magic(EVP_CIPHER_CTX *ctx); +static int rc2_magic_to_meth(int i); +static int rc2_set_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type); +static int rc2_get_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type); +static int rc2_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr); + +typedef struct { + int key_bits; /* effective key bits */ + RC2_KEY ks; /* key schedule */ +} EVP_RC2_KEY; + +# define data(ctx) EVP_C_DATA(EVP_RC2_KEY,ctx) + +IMPLEMENT_BLOCK_CIPHER(rc2, ks, RC2, EVP_RC2_KEY, NID_rc2, + 8, + RC2_KEY_LENGTH, 8, 64, + EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT, + rc2_init_key, NULL, + rc2_set_asn1_type_and_iv, rc2_get_asn1_type_and_iv, + rc2_ctrl) +# define RC2_40_MAGIC 0xa0 +# define RC2_64_MAGIC 0x78 +# define RC2_128_MAGIC 0x3a +static const EVP_CIPHER r2_64_cbc_cipher = { + NID_rc2_64_cbc, + 8, 8 /* 64 bit */ , 8, + EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT, + rc2_init_key, + rc2_cbc_cipher, + NULL, + sizeof(EVP_RC2_KEY), + rc2_set_asn1_type_and_iv, + rc2_get_asn1_type_and_iv, + rc2_ctrl, + NULL +}; + +static const EVP_CIPHER r2_40_cbc_cipher = { + NID_rc2_40_cbc, + 8, 5 /* 40 bit */ , 8, + EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT, + rc2_init_key, + rc2_cbc_cipher, + NULL, + sizeof(EVP_RC2_KEY), + rc2_set_asn1_type_and_iv, + rc2_get_asn1_type_and_iv, + rc2_ctrl, + NULL +}; + +const EVP_CIPHER *EVP_rc2_64_cbc(void) +{ + return &r2_64_cbc_cipher; +} + +const EVP_CIPHER *EVP_rc2_40_cbc(void) +{ + return &r2_40_cbc_cipher; +} + +static int rc2_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + RC2_set_key(&data(ctx)->ks, EVP_CIPHER_CTX_key_length(ctx), + key, data(ctx)->key_bits); + return 1; +} + +static int rc2_meth_to_magic(EVP_CIPHER_CTX *e) +{ + int i; + + if (EVP_CIPHER_CTX_ctrl(e, EVP_CTRL_GET_RC2_KEY_BITS, 0, &i) <= 0) + return 0; + if (i == 128) + return RC2_128_MAGIC; + else if (i == 64) + return RC2_64_MAGIC; + else if (i == 40) + return RC2_40_MAGIC; + else + return 0; +} + +static int rc2_magic_to_meth(int i) +{ + if (i == RC2_128_MAGIC) + return 128; + else if (i == RC2_64_MAGIC) + return 64; + else if (i == RC2_40_MAGIC) + return 40; + else { + EVPerr(EVP_F_RC2_MAGIC_TO_METH, EVP_R_UNSUPPORTED_KEY_SIZE); + return 0; + } +} + +static int rc2_get_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type) +{ + long num = 0; + int i = 0; + int key_bits; + unsigned int l; + unsigned char iv[EVP_MAX_IV_LENGTH]; + + if (type != NULL) { + l = EVP_CIPHER_CTX_iv_length(c); + OPENSSL_assert(l <= sizeof(iv)); + i = ASN1_TYPE_get_int_octetstring(type, &num, iv, l); + if (i != (int)l) + return -1; + key_bits = rc2_magic_to_meth((int)num); + if (!key_bits) + return -1; + if (i > 0 && !EVP_CipherInit_ex(c, NULL, NULL, NULL, iv, -1)) + return -1; + if (EVP_CIPHER_CTX_ctrl(c, EVP_CTRL_SET_RC2_KEY_BITS, key_bits, + NULL) <= 0 + || EVP_CIPHER_CTX_set_key_length(c, key_bits / 8) <= 0) + return -1; + } + return i; +} + +static int rc2_set_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type) +{ + long num; + int i = 0, j; + + if (type != NULL) { + num = rc2_meth_to_magic(c); + j = EVP_CIPHER_CTX_iv_length(c); + i = ASN1_TYPE_set_int_octetstring(type, num, + (unsigned char *)EVP_CIPHER_CTX_original_iv(c), + j); + } + return i; +} + +static int rc2_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) +{ + switch (type) { + case EVP_CTRL_INIT: + data(c)->key_bits = EVP_CIPHER_CTX_key_length(c) * 8; + return 1; + + case EVP_CTRL_GET_RC2_KEY_BITS: + *(int *)ptr = data(c)->key_bits; + return 1; + + case EVP_CTRL_SET_RC2_KEY_BITS: + if (arg > 0) { + data(c)->key_bits = arg; + return 1; + } + return 0; +# ifdef PBE_PRF_TEST + case EVP_CTRL_PBE_PRF_NID: + *(int *)ptr = NID_hmacWithMD5; + return 1; +# endif + + default: + return -1; + } +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_rc4.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_rc4.c new file mode 100644 index 000000000..d16abdd0d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_rc4.c @@ -0,0 +1,82 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" + +#ifndef OPENSSL_NO_RC4 + +# include +# include +# include + +# include "internal/evp_int.h" + +typedef struct { + RC4_KEY ks; /* working key */ +} EVP_RC4_KEY; + +# define data(ctx) ((EVP_RC4_KEY *)EVP_CIPHER_CTX_get_cipher_data(ctx)) + +static int rc4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); +static int rc4_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl); +static const EVP_CIPHER r4_cipher = { + NID_rc4, + 1, EVP_RC4_KEY_SIZE, 0, + EVP_CIPH_VARIABLE_LENGTH, + rc4_init_key, + rc4_cipher, + NULL, + sizeof(EVP_RC4_KEY), + NULL, + NULL, + NULL, + NULL +}; + +static const EVP_CIPHER r4_40_cipher = { + NID_rc4_40, + 1, 5 /* 40 bit */ , 0, + EVP_CIPH_VARIABLE_LENGTH, + rc4_init_key, + rc4_cipher, + NULL, + sizeof(EVP_RC4_KEY), + NULL, + NULL, + NULL, + NULL +}; + +const EVP_CIPHER *EVP_rc4(void) +{ + return &r4_cipher; +} + +const EVP_CIPHER *EVP_rc4_40(void) +{ + return &r4_40_cipher; +} + +static int rc4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + RC4_set_key(&data(ctx)->ks, EVP_CIPHER_CTX_key_length(ctx), key); + return 1; +} + +static int rc4_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + RC4(&data(ctx)->ks, inl, in, out); + return 1; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_rc4_hmac_md5.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_rc4_hmac_md5.c new file mode 100644 index 000000000..b1e8ccd6d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_rc4_hmac_md5.c @@ -0,0 +1,262 @@ +/* + * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#include +#include + +#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_MD5) + +# include +# include +# include +# include +# include +# include "internal/evp_int.h" + +typedef struct { + RC4_KEY ks; + MD5_CTX head, tail, md; + size_t payload_length; +} EVP_RC4_HMAC_MD5; + +# define NO_PAYLOAD_LENGTH ((size_t)-1) + +void rc4_md5_enc(RC4_KEY *key, const void *in0, void *out, + MD5_CTX *ctx, const void *inp, size_t blocks); + +# define data(ctx) ((EVP_RC4_HMAC_MD5 *)EVP_CIPHER_CTX_get_cipher_data(ctx)) + +static int rc4_hmac_md5_init_key(EVP_CIPHER_CTX *ctx, + const unsigned char *inkey, + const unsigned char *iv, int enc) +{ + EVP_RC4_HMAC_MD5 *key = data(ctx); + + RC4_set_key(&key->ks, EVP_CIPHER_CTX_key_length(ctx), inkey); + + MD5_Init(&key->head); /* handy when benchmarking */ + key->tail = key->head; + key->md = key->head; + + key->payload_length = NO_PAYLOAD_LENGTH; + + return 1; +} + +# if defined(RC4_ASM) && defined(MD5_ASM) && ( \ + defined(__x86_64) || defined(__x86_64__) || \ + defined(_M_AMD64) || defined(_M_X64) ) +# define STITCHED_CALL +# endif + +# if !defined(STITCHED_CALL) +# define rc4_off 0 +# define md5_off 0 +# endif + +static int rc4_hmac_md5_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_RC4_HMAC_MD5 *key = data(ctx); +# if defined(STITCHED_CALL) + size_t rc4_off = 32 - 1 - (key->ks.x & (32 - 1)), /* 32 is $MOD from + * rc4_md5-x86_64.pl */ + md5_off = MD5_CBLOCK - key->md.num, blocks; + unsigned int l; + extern unsigned int OPENSSL_ia32cap_P[]; +# endif + size_t plen = key->payload_length; + + if (plen != NO_PAYLOAD_LENGTH && len != (plen + MD5_DIGEST_LENGTH)) + return 0; + + if (EVP_CIPHER_CTX_encrypting(ctx)) { + if (plen == NO_PAYLOAD_LENGTH) + plen = len; +# if defined(STITCHED_CALL) + /* cipher has to "fall behind" */ + if (rc4_off > md5_off) + md5_off += MD5_CBLOCK; + + if (plen > md5_off && (blocks = (plen - md5_off) / MD5_CBLOCK) && + (OPENSSL_ia32cap_P[0] & (1 << 20)) == 0) { + MD5_Update(&key->md, in, md5_off); + RC4(&key->ks, rc4_off, in, out); + + rc4_md5_enc(&key->ks, in + rc4_off, out + rc4_off, + &key->md, in + md5_off, blocks); + blocks *= MD5_CBLOCK; + rc4_off += blocks; + md5_off += blocks; + key->md.Nh += blocks >> 29; + key->md.Nl += blocks <<= 3; + if (key->md.Nl < (unsigned int)blocks) + key->md.Nh++; + } else { + rc4_off = 0; + md5_off = 0; + } +# endif + MD5_Update(&key->md, in + md5_off, plen - md5_off); + + if (plen != len) { /* "TLS" mode of operation */ + if (in != out) + memcpy(out + rc4_off, in + rc4_off, plen - rc4_off); + + /* calculate HMAC and append it to payload */ + MD5_Final(out + plen, &key->md); + key->md = key->tail; + MD5_Update(&key->md, out + plen, MD5_DIGEST_LENGTH); + MD5_Final(out + plen, &key->md); + /* encrypt HMAC at once */ + RC4(&key->ks, len - rc4_off, out + rc4_off, out + rc4_off); + } else { + RC4(&key->ks, len - rc4_off, in + rc4_off, out + rc4_off); + } + } else { + unsigned char mac[MD5_DIGEST_LENGTH]; +# if defined(STITCHED_CALL) + /* digest has to "fall behind" */ + if (md5_off > rc4_off) + rc4_off += 2 * MD5_CBLOCK; + else + rc4_off += MD5_CBLOCK; + + if (len > rc4_off && (blocks = (len - rc4_off) / MD5_CBLOCK) && + (OPENSSL_ia32cap_P[0] & (1 << 20)) == 0) { + RC4(&key->ks, rc4_off, in, out); + MD5_Update(&key->md, out, md5_off); + + rc4_md5_enc(&key->ks, in + rc4_off, out + rc4_off, + &key->md, out + md5_off, blocks); + blocks *= MD5_CBLOCK; + rc4_off += blocks; + md5_off += blocks; + l = (key->md.Nl + (blocks << 3)) & 0xffffffffU; + if (l < key->md.Nl) + key->md.Nh++; + key->md.Nl = l; + key->md.Nh += blocks >> 29; + } else { + md5_off = 0; + rc4_off = 0; + } +# endif + /* decrypt HMAC at once */ + RC4(&key->ks, len - rc4_off, in + rc4_off, out + rc4_off); + if (plen != NO_PAYLOAD_LENGTH) { /* "TLS" mode of operation */ + MD5_Update(&key->md, out + md5_off, plen - md5_off); + + /* calculate HMAC and verify it */ + MD5_Final(mac, &key->md); + key->md = key->tail; + MD5_Update(&key->md, mac, MD5_DIGEST_LENGTH); + MD5_Final(mac, &key->md); + + if (CRYPTO_memcmp(out + plen, mac, MD5_DIGEST_LENGTH)) + return 0; + } else { + MD5_Update(&key->md, out + md5_off, len - md5_off); + } + } + + key->payload_length = NO_PAYLOAD_LENGTH; + + return 1; +} + +static int rc4_hmac_md5_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, + void *ptr) +{ + EVP_RC4_HMAC_MD5 *key = data(ctx); + + switch (type) { + case EVP_CTRL_AEAD_SET_MAC_KEY: + { + unsigned int i; + unsigned char hmac_key[64]; + + memset(hmac_key, 0, sizeof(hmac_key)); + + if (arg > (int)sizeof(hmac_key)) { + MD5_Init(&key->head); + MD5_Update(&key->head, ptr, arg); + MD5_Final(hmac_key, &key->head); + } else { + memcpy(hmac_key, ptr, arg); + } + + for (i = 0; i < sizeof(hmac_key); i++) + hmac_key[i] ^= 0x36; /* ipad */ + MD5_Init(&key->head); + MD5_Update(&key->head, hmac_key, sizeof(hmac_key)); + + for (i = 0; i < sizeof(hmac_key); i++) + hmac_key[i] ^= 0x36 ^ 0x5c; /* opad */ + MD5_Init(&key->tail); + MD5_Update(&key->tail, hmac_key, sizeof(hmac_key)); + + OPENSSL_cleanse(hmac_key, sizeof(hmac_key)); + + return 1; + } + case EVP_CTRL_AEAD_TLS1_AAD: + { + unsigned char *p = ptr; + unsigned int len; + + if (arg != EVP_AEAD_TLS1_AAD_LEN) + return -1; + + len = p[arg - 2] << 8 | p[arg - 1]; + + if (!EVP_CIPHER_CTX_encrypting(ctx)) { + if (len < MD5_DIGEST_LENGTH) + return -1; + len -= MD5_DIGEST_LENGTH; + p[arg - 2] = len >> 8; + p[arg - 1] = len; + } + key->payload_length = len; + key->md = key->head; + MD5_Update(&key->md, p, arg); + + return MD5_DIGEST_LENGTH; + } + default: + return -1; + } +} + +static EVP_CIPHER r4_hmac_md5_cipher = { +# ifdef NID_rc4_hmac_md5 + NID_rc4_hmac_md5, +# else + NID_undef, +# endif + 1, EVP_RC4_KEY_SIZE, 0, + EVP_CIPH_STREAM_CIPHER | EVP_CIPH_VARIABLE_LENGTH | + EVP_CIPH_FLAG_AEAD_CIPHER, + rc4_hmac_md5_init_key, + rc4_hmac_md5_cipher, + NULL, + sizeof(EVP_RC4_HMAC_MD5), + NULL, + NULL, + rc4_hmac_md5_ctrl, + NULL +}; + +const EVP_CIPHER *EVP_rc4_hmac_md5(void) +{ + return &r4_hmac_md5_cipher; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_rc5.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_rc5.c new file mode 100644 index 000000000..a2f26d8c5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_rc5.c @@ -0,0 +1,74 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" + +#ifndef OPENSSL_NO_RC5 + +# include +# include "internal/evp_int.h" +# include +# include "evp_locl.h" +# include + +static int r_32_12_16_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); +static int rc5_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr); + +typedef struct { + int rounds; /* number of rounds */ + RC5_32_KEY ks; /* key schedule */ +} EVP_RC5_KEY; + +# define data(ctx) EVP_C_DATA(EVP_RC5_KEY,ctx) + +IMPLEMENT_BLOCK_CIPHER(rc5_32_12_16, ks, RC5_32, EVP_RC5_KEY, NID_rc5, + 8, RC5_32_KEY_LENGTH, 8, 64, + EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT, + r_32_12_16_init_key, NULL, NULL, NULL, rc5_ctrl) + +static int rc5_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) +{ + switch (type) { + case EVP_CTRL_INIT: + data(c)->rounds = RC5_12_ROUNDS; + return 1; + + case EVP_CTRL_GET_RC5_ROUNDS: + *(int *)ptr = data(c)->rounds; + return 1; + + case EVP_CTRL_SET_RC5_ROUNDS: + switch (arg) { + case RC5_8_ROUNDS: + case RC5_12_ROUNDS: + case RC5_16_ROUNDS: + data(c)->rounds = arg; + return 1; + + default: + EVPerr(EVP_F_RC5_CTRL, EVP_R_UNSUPPORTED_NUMBER_OF_ROUNDS); + return 0; + } + + default: + return -1; + } +} + +static int r_32_12_16_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + RC5_32_set_key(&data(ctx)->ks, EVP_CIPHER_CTX_key_length(ctx), + key, data(ctx)->rounds); + return 1; +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_seed.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_seed.c new file mode 100644 index 000000000..40aec5fc6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_seed.c @@ -0,0 +1,39 @@ +/* + * Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#ifdef OPENSSL_NO_SEED +NON_EMPTY_TRANSLATION_UNIT +#else +# include +# include +# include +# include +# include +# include "internal/evp_int.h" + +static int seed_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); + +typedef struct { + SEED_KEY_SCHEDULE ks; +} EVP_SEED_KEY; + +IMPLEMENT_BLOCK_CIPHER(seed, ks, SEED, EVP_SEED_KEY, NID_seed, + 16, 16, 16, 128, EVP_CIPH_FLAG_DEFAULT_ASN1, + seed_init_key, 0, 0, 0, 0) + +static int seed_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + SEED_set_key(key, &EVP_C_DATA(EVP_SEED_KEY,ctx)->ks); + return 1; +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_sm4.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_sm4.c new file mode 100644 index 000000000..79deb6563 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_sm4.c @@ -0,0 +1,100 @@ +/* + * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017 Ribose Inc. All Rights Reserved. + * Ported from Ribose contributions from Botan. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#ifndef OPENSSL_NO_SM4 +# include +# include +# include "internal/sm4.h" +# include "internal/evp_int.h" + +typedef struct { + SM4_KEY ks; +} EVP_SM4_KEY; + +static int sm4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + SM4_set_key(key, EVP_CIPHER_CTX_get_cipher_data(ctx)); + return 1; +} + +static void sm4_cbc_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const SM4_KEY *key, + unsigned char *ivec, const int enc) +{ + if (enc) + CRYPTO_cbc128_encrypt(in, out, len, key, ivec, + (block128_f)SM4_encrypt); + else + CRYPTO_cbc128_decrypt(in, out, len, key, ivec, + (block128_f)SM4_decrypt); +} + +static void sm4_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const SM4_KEY *key, + unsigned char *ivec, int *num, const int enc) +{ + CRYPTO_cfb128_encrypt(in, out, length, key, ivec, num, enc, + (block128_f)SM4_encrypt); +} + +static void sm4_ecb_encrypt(const unsigned char *in, unsigned char *out, + const SM4_KEY *key, const int enc) +{ + if (enc) + SM4_encrypt(in, out, key); + else + SM4_decrypt(in, out, key); +} + +static void sm4_ofb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const SM4_KEY *key, + unsigned char *ivec, int *num) +{ + CRYPTO_ofb128_encrypt(in, out, length, key, ivec, num, + (block128_f)SM4_encrypt); +} + +IMPLEMENT_BLOCK_CIPHER(sm4, ks, sm4, EVP_SM4_KEY, NID_sm4, + 16, 16, 16, 128, EVP_CIPH_FLAG_DEFAULT_ASN1, + sm4_init_key, 0, 0, 0, 0) + +static int sm4_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + unsigned int num = EVP_CIPHER_CTX_num(ctx); + EVP_SM4_KEY *dat = EVP_C_DATA(EVP_SM4_KEY, ctx); + + CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, + EVP_CIPHER_CTX_iv_noconst(ctx), + EVP_CIPHER_CTX_buf_noconst(ctx), &num, + (block128_f)SM4_encrypt); + EVP_CIPHER_CTX_set_num(ctx, num); + return 1; +} + +static const EVP_CIPHER sm4_ctr_mode = { + NID_sm4_ctr, 1, 16, 16, + EVP_CIPH_CTR_MODE, + sm4_init_key, + sm4_ctr_cipher, + NULL, + sizeof(EVP_SM4_KEY), + NULL, NULL, NULL, NULL +}; + +const EVP_CIPHER *EVP_sm4_ctr(void) +{ + return &sm4_ctr_mode; +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_xcbc_d.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_xcbc_d.c new file mode 100644 index 000000000..57ce813da --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/e_xcbc_d.c @@ -0,0 +1,83 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" + +#ifndef OPENSSL_NO_DES + +# include +# include +# include "internal/evp_int.h" +# include + +static int desx_cbc_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); +static int desx_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl); + +typedef struct { + DES_key_schedule ks; /* key schedule */ + DES_cblock inw; + DES_cblock outw; +} DESX_CBC_KEY; + +# define data(ctx) EVP_C_DATA(DESX_CBC_KEY,ctx) + +static const EVP_CIPHER d_xcbc_cipher = { + NID_desx_cbc, + 8, 24, 8, + EVP_CIPH_CBC_MODE, + desx_cbc_init_key, + desx_cbc_cipher, + NULL, + sizeof(DESX_CBC_KEY), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL, + NULL +}; + +const EVP_CIPHER *EVP_desx_cbc(void) +{ + return &d_xcbc_cipher; +} + +static int desx_cbc_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + DES_cblock *deskey = (DES_cblock *)key; + + DES_set_key_unchecked(deskey, &data(ctx)->ks); + memcpy(&data(ctx)->inw[0], &key[8], 8); + memcpy(&data(ctx)->outw[0], &key[16], 8); + + return 1; +} + +static int desx_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + while (inl >= EVP_MAXCHUNK) { + DES_xcbc_encrypt(in, out, (long)EVP_MAXCHUNK, &data(ctx)->ks, + (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), + &data(ctx)->inw, &data(ctx)->outw, + EVP_CIPHER_CTX_encrypting(ctx)); + inl -= EVP_MAXCHUNK; + in += EVP_MAXCHUNK; + out += EVP_MAXCHUNK; + } + if (inl) + DES_xcbc_encrypt(in, out, (long)inl, &data(ctx)->ks, + (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), + &data(ctx)->inw, &data(ctx)->outw, + EVP_CIPHER_CTX_encrypting(ctx)); + return 1; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/encode.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/encode.c new file mode 100644 index 000000000..da32d4fd1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/encode.c @@ -0,0 +1,478 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include +#include "evp_locl.h" +#include "internal/evp_int.h" + +static unsigned char conv_ascii2bin(unsigned char a, + const unsigned char *table); +static int evp_encodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t, + const unsigned char *f, int dlen); +static int evp_decodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t, + const unsigned char *f, int n); + +#ifndef CHARSET_EBCDIC +# define conv_bin2ascii(a, table) ((table)[(a)&0x3f]) +#else +/* + * We assume that PEM encoded files are EBCDIC files (i.e., printable text + * files). Convert them here while decoding. When encoding, output is EBCDIC + * (text) format again. (No need for conversion in the conv_bin2ascii macro, + * as the underlying textstring data_bin2ascii[] is already EBCDIC) + */ +# define conv_bin2ascii(a, table) ((table)[(a)&0x3f]) +#endif + +/*- + * 64 char lines + * pad input with 0 + * left over chars are set to = + * 1 byte => xx== + * 2 bytes => xxx= + * 3 bytes => xxxx + */ +#define BIN_PER_LINE (64/4*3) +#define CHUNKS_PER_LINE (64/4) +#define CHAR_PER_LINE (64+1) + +static const unsigned char data_bin2ascii[65] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/* SRP uses a different base64 alphabet */ +static const unsigned char srpdata_bin2ascii[65] = + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./"; + + +/*- + * 0xF0 is a EOLN + * 0xF1 is ignore but next needs to be 0xF0 (for \r\n processing). + * 0xF2 is EOF + * 0xE0 is ignore at start of line. + * 0xFF is error + */ + +#define B64_EOLN 0xF0 +#define B64_CR 0xF1 +#define B64_EOF 0xF2 +#define B64_WS 0xE0 +#define B64_ERROR 0xFF +#define B64_NOT_BASE64(a) (((a)|0x13) == 0xF3) +#define B64_BASE64(a) (!B64_NOT_BASE64(a)) + +static const unsigned char data_ascii2bin[128] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xE0, 0xF0, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xF2, 0xFF, 0x3F, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, + 0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, + 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, + 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, + 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, + 0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +}; + +static const unsigned char srpdata_ascii2bin[128] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xE0, 0xF0, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF2, 0x3E, 0x3F, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, + 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, + 0x21, 0x22, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, + 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, + 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, + 0x3B, 0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +}; + +#ifndef CHARSET_EBCDIC +static unsigned char conv_ascii2bin(unsigned char a, const unsigned char *table) +{ + if (a & 0x80) + return B64_ERROR; + return table[a]; +} +#else +static unsigned char conv_ascii2bin(unsigned char a, const unsigned char *table) +{ + a = os_toascii[a]; + if (a & 0x80) + return B64_ERROR; + return table[a]; +} +#endif + +EVP_ENCODE_CTX *EVP_ENCODE_CTX_new(void) +{ + return OPENSSL_zalloc(sizeof(EVP_ENCODE_CTX)); +} + +void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx) +{ + OPENSSL_free(ctx); +} + +int EVP_ENCODE_CTX_copy(EVP_ENCODE_CTX *dctx, EVP_ENCODE_CTX *sctx) +{ + memcpy(dctx, sctx, sizeof(EVP_ENCODE_CTX)); + + return 1; +} + +int EVP_ENCODE_CTX_num(EVP_ENCODE_CTX *ctx) +{ + return ctx->num; +} + +void evp_encode_ctx_set_flags(EVP_ENCODE_CTX *ctx, unsigned int flags) +{ + ctx->flags = flags; +} + +void EVP_EncodeInit(EVP_ENCODE_CTX *ctx) +{ + ctx->length = 48; + ctx->num = 0; + ctx->line_num = 0; + ctx->flags = 0; +} + +int EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl) +{ + int i, j; + size_t total = 0; + + *outl = 0; + if (inl <= 0) + return 0; + OPENSSL_assert(ctx->length <= (int)sizeof(ctx->enc_data)); + if (ctx->length - ctx->num > inl) { + memcpy(&(ctx->enc_data[ctx->num]), in, inl); + ctx->num += inl; + return 1; + } + if (ctx->num != 0) { + i = ctx->length - ctx->num; + memcpy(&(ctx->enc_data[ctx->num]), in, i); + in += i; + inl -= i; + j = evp_encodeblock_int(ctx, out, ctx->enc_data, ctx->length); + ctx->num = 0; + out += j; + total = j; + if ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0) { + *(out++) = '\n'; + total++; + } + *out = '\0'; + } + while (inl >= ctx->length && total <= INT_MAX) { + j = evp_encodeblock_int(ctx, out, in, ctx->length); + in += ctx->length; + inl -= ctx->length; + out += j; + total += j; + if ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0) { + *(out++) = '\n'; + total++; + } + *out = '\0'; + } + if (total > INT_MAX) { + /* Too much output data! */ + *outl = 0; + return 0; + } + if (inl != 0) + memcpy(&(ctx->enc_data[0]), in, inl); + ctx->num = inl; + *outl = total; + + return 1; +} + +void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl) +{ + unsigned int ret = 0; + + if (ctx->num != 0) { + ret = evp_encodeblock_int(ctx, out, ctx->enc_data, ctx->num); + if ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0) + out[ret++] = '\n'; + out[ret] = '\0'; + ctx->num = 0; + } + *outl = ret; +} + +static int evp_encodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t, + const unsigned char *f, int dlen) +{ + int i, ret = 0; + unsigned long l; + const unsigned char *table; + + if (ctx != NULL && (ctx->flags & EVP_ENCODE_CTX_USE_SRP_ALPHABET) != 0) + table = srpdata_bin2ascii; + else + table = data_bin2ascii; + + for (i = dlen; i > 0; i -= 3) { + if (i >= 3) { + l = (((unsigned long)f[0]) << 16L) | + (((unsigned long)f[1]) << 8L) | f[2]; + *(t++) = conv_bin2ascii(l >> 18L, table); + *(t++) = conv_bin2ascii(l >> 12L, table); + *(t++) = conv_bin2ascii(l >> 6L, table); + *(t++) = conv_bin2ascii(l, table); + } else { + l = ((unsigned long)f[0]) << 16L; + if (i == 2) + l |= ((unsigned long)f[1] << 8L); + + *(t++) = conv_bin2ascii(l >> 18L, table); + *(t++) = conv_bin2ascii(l >> 12L, table); + *(t++) = (i == 1) ? '=' : conv_bin2ascii(l >> 6L, table); + *(t++) = '='; + } + ret += 4; + f += 3; + } + + *t = '\0'; + return ret; +} + +int EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int dlen) +{ + return evp_encodeblock_int(NULL, t, f, dlen); +} + +void EVP_DecodeInit(EVP_ENCODE_CTX *ctx) +{ + /* Only ctx->num and ctx->flags are used during decoding. */ + ctx->num = 0; + ctx->length = 0; + ctx->line_num = 0; + ctx->flags = 0; +} + +/*- + * -1 for error + * 0 for last line + * 1 for full line + * + * Note: even though EVP_DecodeUpdate attempts to detect and report end of + * content, the context doesn't currently remember it and will accept more data + * in the next call. Therefore, the caller is responsible for checking and + * rejecting a 0 return value in the middle of content. + * + * Note: even though EVP_DecodeUpdate has historically tried to detect end of + * content based on line length, this has never worked properly. Therefore, + * we now return 0 when one of the following is true: + * - Padding or B64_EOF was detected and the last block is complete. + * - Input has zero-length. + * -1 is returned if: + * - Invalid characters are detected. + * - There is extra trailing padding, or data after padding. + * - B64_EOF is detected after an incomplete base64 block. + */ +int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl) +{ + int seof = 0, eof = 0, rv = -1, ret = 0, i, v, tmp, n, decoded_len; + unsigned char *d; + const unsigned char *table; + + n = ctx->num; + d = ctx->enc_data; + + if (n > 0 && d[n - 1] == '=') { + eof++; + if (n > 1 && d[n - 2] == '=') + eof++; + } + + /* Legacy behaviour: an empty input chunk signals end of input. */ + if (inl == 0) { + rv = 0; + goto end; + } + + if ((ctx->flags & EVP_ENCODE_CTX_USE_SRP_ALPHABET) != 0) + table = srpdata_ascii2bin; + else + table = data_ascii2bin; + + for (i = 0; i < inl; i++) { + tmp = *(in++); + v = conv_ascii2bin(tmp, table); + if (v == B64_ERROR) { + rv = -1; + goto end; + } + + if (tmp == '=') { + eof++; + } else if (eof > 0 && B64_BASE64(v)) { + /* More data after padding. */ + rv = -1; + goto end; + } + + if (eof > 2) { + rv = -1; + goto end; + } + + if (v == B64_EOF) { + seof = 1; + goto tail; + } + + /* Only save valid base64 characters. */ + if (B64_BASE64(v)) { + if (n >= 64) { + /* + * We increment n once per loop, and empty the buffer as soon as + * we reach 64 characters, so this can only happen if someone's + * manually messed with the ctx. Refuse to write any more data. + */ + rv = -1; + goto end; + } + OPENSSL_assert(n < (int)sizeof(ctx->enc_data)); + d[n++] = tmp; + } + + if (n == 64) { + decoded_len = evp_decodeblock_int(ctx, out, d, n); + n = 0; + if (decoded_len < 0 || eof > decoded_len) { + rv = -1; + goto end; + } + ret += decoded_len - eof; + out += decoded_len - eof; + } + } + + /* + * Legacy behaviour: if the current line is a full base64-block (i.e., has + * 0 mod 4 base64 characters), it is processed immediately. We keep this + * behaviour as applications may not be calling EVP_DecodeFinal properly. + */ +tail: + if (n > 0) { + if ((n & 3) == 0) { + decoded_len = evp_decodeblock_int(ctx, out, d, n); + n = 0; + if (decoded_len < 0 || eof > decoded_len) { + rv = -1; + goto end; + } + ret += (decoded_len - eof); + } else if (seof) { + /* EOF in the middle of a base64 block. */ + rv = -1; + goto end; + } + } + + rv = seof || (n == 0 && eof) ? 0 : 1; +end: + /* Legacy behaviour. This should probably rather be zeroed on error. */ + *outl = ret; + ctx->num = n; + return rv; +} + +static int evp_decodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t, + const unsigned char *f, int n) +{ + int i, ret = 0, a, b, c, d; + unsigned long l; + const unsigned char *table; + + if (ctx != NULL && (ctx->flags & EVP_ENCODE_CTX_USE_SRP_ALPHABET) != 0) + table = srpdata_ascii2bin; + else + table = data_ascii2bin; + + /* trim white space from the start of the line. */ + while ((conv_ascii2bin(*f, table) == B64_WS) && (n > 0)) { + f++; + n--; + } + + /* + * strip off stuff at the end of the line ascii2bin values B64_WS, + * B64_EOLN, B64_EOLN and B64_EOF + */ + while ((n > 3) && (B64_NOT_BASE64(conv_ascii2bin(f[n - 1], table)))) + n--; + + if (n % 4 != 0) + return -1; + + for (i = 0; i < n; i += 4) { + a = conv_ascii2bin(*(f++), table); + b = conv_ascii2bin(*(f++), table); + c = conv_ascii2bin(*(f++), table); + d = conv_ascii2bin(*(f++), table); + if ((a & 0x80) || (b & 0x80) || (c & 0x80) || (d & 0x80)) + return -1; + l = ((((unsigned long)a) << 18L) | + (((unsigned long)b) << 12L) | + (((unsigned long)c) << 6L) | (((unsigned long)d))); + *(t++) = (unsigned char)(l >> 16L) & 0xff; + *(t++) = (unsigned char)(l >> 8L) & 0xff; + *(t++) = (unsigned char)(l) & 0xff; + ret += 3; + } + return ret; +} + +int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n) +{ + return evp_decodeblock_int(NULL, t, f, n); +} + +int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl) +{ + int i; + + *outl = 0; + if (ctx->num != 0) { + i = evp_decodeblock_int(ctx, out, ctx->enc_data, ctx->num); + if (i < 0) + return -1; + ctx->num = 0; + *outl = i; + return 1; + } else + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_cnf.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_cnf.c new file mode 100644 index 000000000..8df2c06e1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_cnf.c @@ -0,0 +1,56 @@ +/* + * Copyright 2012-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include +#include +#include + +/* Algorithm configuration module. */ + +static int alg_module_init(CONF_IMODULE *md, const CONF *cnf) +{ + int i; + const char *oid_section; + STACK_OF(CONF_VALUE) *sktmp; + CONF_VALUE *oval; + + oid_section = CONF_imodule_get_value(md); + if ((sktmp = NCONF_get_section(cnf, oid_section)) == NULL) { + EVPerr(EVP_F_ALG_MODULE_INIT, EVP_R_ERROR_LOADING_SECTION); + return 0; + } + for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) { + oval = sk_CONF_VALUE_value(sktmp, i); + if (strcmp(oval->name, "fips_mode") == 0) { + int m; + if (!X509V3_get_value_bool(oval, &m)) { + EVPerr(EVP_F_ALG_MODULE_INIT, EVP_R_INVALID_FIPS_MODE); + return 0; + } + if (m > 0) { + EVPerr(EVP_F_ALG_MODULE_INIT, EVP_R_FIPS_MODE_NOT_SUPPORTED); + return 0; + } + } else { + EVPerr(EVP_F_ALG_MODULE_INIT, EVP_R_UNKNOWN_OPTION); + ERR_add_error_data(4, "name=", oval->name, + ", value=", oval->value); + } + + } + return 1; +} + +void EVP_add_alg_module(void) +{ + CONF_module_add("alg_section", alg_module_init, 0); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_enc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_enc.c new file mode 100644 index 000000000..05dd791b6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_enc.c @@ -0,0 +1,677 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include "internal/evp_int.h" +#include "evp_locl.h" + +int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *c) +{ + if (c == NULL) + return 1; + if (c->cipher != NULL) { + if (c->cipher->cleanup && !c->cipher->cleanup(c)) + return 0; + /* Cleanse cipher context data */ + if (c->cipher_data && c->cipher->ctx_size) + OPENSSL_cleanse(c->cipher_data, c->cipher->ctx_size); + } + OPENSSL_free(c->cipher_data); +#ifndef OPENSSL_NO_ENGINE + ENGINE_finish(c->engine); +#endif + memset(c, 0, sizeof(*c)); + return 1; +} + +EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void) +{ + return OPENSSL_zalloc(sizeof(EVP_CIPHER_CTX)); +} + +void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx) +{ + EVP_CIPHER_CTX_reset(ctx); + OPENSSL_free(ctx); +} + +int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + const unsigned char *key, const unsigned char *iv, int enc) +{ + if (cipher != NULL) + EVP_CIPHER_CTX_reset(ctx); + return EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc); +} + +int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + ENGINE *impl, const unsigned char *key, + const unsigned char *iv, int enc) +{ + if (enc == -1) + enc = ctx->encrypt; + else { + if (enc) + enc = 1; + ctx->encrypt = enc; + } +#ifndef OPENSSL_NO_ENGINE + /* + * Whether it's nice or not, "Inits" can be used on "Final"'d contexts so + * this context may already have an ENGINE! Try to avoid releasing the + * previous handle, re-querying for an ENGINE, and having a + * reinitialisation, when it may all be unnecessary. + */ + if (ctx->engine && ctx->cipher + && (cipher == NULL || cipher->nid == ctx->cipher->nid)) + goto skip_to_init; +#endif + if (cipher) { + /* + * Ensure a context left lying around from last time is cleared (the + * previous check attempted to avoid this if the same ENGINE and + * EVP_CIPHER could be used). + */ + if (ctx->cipher) { + unsigned long flags = ctx->flags; + EVP_CIPHER_CTX_reset(ctx); + /* Restore encrypt and flags */ + ctx->encrypt = enc; + ctx->flags = flags; + } +#ifndef OPENSSL_NO_ENGINE + if (impl) { + if (!ENGINE_init(impl)) { + EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR); + return 0; + } + } else + /* Ask if an ENGINE is reserved for this job */ + impl = ENGINE_get_cipher_engine(cipher->nid); + if (impl) { + /* There's an ENGINE for this job ... (apparently) */ + const EVP_CIPHER *c = ENGINE_get_cipher(impl, cipher->nid); + if (!c) { + /* + * One positive side-effect of US's export control history, + * is that we should at least be able to avoid using US + * misspellings of "initialisation"? + */ + EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR); + return 0; + } + /* We'll use the ENGINE's private cipher definition */ + cipher = c; + /* + * Store the ENGINE functional reference so we know 'cipher' came + * from an ENGINE and we need to release it when done. + */ + ctx->engine = impl; + } else + ctx->engine = NULL; +#endif + + ctx->cipher = cipher; + if (ctx->cipher->ctx_size) { + ctx->cipher_data = OPENSSL_zalloc(ctx->cipher->ctx_size); + if (ctx->cipher_data == NULL) { + ctx->cipher = NULL; + EVPerr(EVP_F_EVP_CIPHERINIT_EX, ERR_R_MALLOC_FAILURE); + return 0; + } + } else { + ctx->cipher_data = NULL; + } + ctx->key_len = cipher->key_len; + /* Preserve wrap enable flag, zero everything else */ + ctx->flags &= EVP_CIPHER_CTX_FLAG_WRAP_ALLOW; + if (ctx->cipher->flags & EVP_CIPH_CTRL_INIT) { + if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_INIT, 0, NULL)) { + ctx->cipher = NULL; + EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR); + return 0; + } + } + } else if (!ctx->cipher) { + EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_NO_CIPHER_SET); + return 0; + } +#ifndef OPENSSL_NO_ENGINE + skip_to_init: +#endif + /* we assume block size is a power of 2 in *cryptUpdate */ + OPENSSL_assert(ctx->cipher->block_size == 1 + || ctx->cipher->block_size == 8 + || ctx->cipher->block_size == 16); + + if (!(ctx->flags & EVP_CIPHER_CTX_FLAG_WRAP_ALLOW) + && EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_WRAP_MODE) { + EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_WRAP_MODE_NOT_ALLOWED); + return 0; + } + + if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_CUSTOM_IV)) { + switch (EVP_CIPHER_CTX_mode(ctx)) { + + case EVP_CIPH_STREAM_CIPHER: + case EVP_CIPH_ECB_MODE: + break; + + case EVP_CIPH_CFB_MODE: + case EVP_CIPH_OFB_MODE: + + ctx->num = 0; + /* fall-through */ + + case EVP_CIPH_CBC_MODE: + + OPENSSL_assert(EVP_CIPHER_CTX_iv_length(ctx) <= + (int)sizeof(ctx->iv)); + if (iv) + memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx)); + memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx)); + break; + + case EVP_CIPH_CTR_MODE: + ctx->num = 0; + /* Don't reuse IV for CTR mode */ + if (iv) + memcpy(ctx->iv, iv, EVP_CIPHER_CTX_iv_length(ctx)); + break; + + default: + return 0; + } + } + + if (key || (ctx->cipher->flags & EVP_CIPH_ALWAYS_CALL_INIT)) { + if (!ctx->cipher->init(ctx, key, iv, enc)) + return 0; + } + ctx->buf_len = 0; + ctx->final_used = 0; + ctx->block_mask = ctx->cipher->block_size - 1; + return 1; +} + +int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl) +{ + if (ctx->encrypt) + return EVP_EncryptUpdate(ctx, out, outl, in, inl); + else + return EVP_DecryptUpdate(ctx, out, outl, in, inl); +} + +int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) +{ + if (ctx->encrypt) + return EVP_EncryptFinal_ex(ctx, out, outl); + else + return EVP_DecryptFinal_ex(ctx, out, outl); +} + +int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) +{ + if (ctx->encrypt) + return EVP_EncryptFinal(ctx, out, outl); + else + return EVP_DecryptFinal(ctx, out, outl); +} + +int EVP_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + const unsigned char *key, const unsigned char *iv) +{ + return EVP_CipherInit(ctx, cipher, key, iv, 1); +} + +int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + ENGINE *impl, const unsigned char *key, + const unsigned char *iv) +{ + return EVP_CipherInit_ex(ctx, cipher, impl, key, iv, 1); +} + +int EVP_DecryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + const unsigned char *key, const unsigned char *iv) +{ + return EVP_CipherInit(ctx, cipher, key, iv, 0); +} + +int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + ENGINE *impl, const unsigned char *key, + const unsigned char *iv) +{ + return EVP_CipherInit_ex(ctx, cipher, impl, key, iv, 0); +} + +/* + * According to the letter of standard difference between pointers + * is specified to be valid only within same object. This makes + * it formally challenging to determine if input and output buffers + * are not partially overlapping with standard pointer arithmetic. + */ +#ifdef PTRDIFF_T +# undef PTRDIFF_T +#endif +#if defined(OPENSSL_SYS_VMS) && __INITIAL_POINTER_SIZE==64 +/* + * Then we have VMS that distinguishes itself by adhering to + * sizeof(size_t)==4 even in 64-bit builds, which means that + * difference between two pointers might be truncated to 32 bits. + * In the context one can even wonder how comparison for + * equality is implemented. To be on the safe side we adhere to + * PTRDIFF_T even for comparison for equality. + */ +# define PTRDIFF_T uint64_t +#else +# define PTRDIFF_T size_t +#endif + +int is_partially_overlapping(const void *ptr1, const void *ptr2, int len) +{ + PTRDIFF_T diff = (PTRDIFF_T)ptr1-(PTRDIFF_T)ptr2; + /* + * Check for partially overlapping buffers. [Binary logical + * operations are used instead of boolean to minimize number + * of conditional branches.] + */ + int overlapped = (len > 0) & (diff != 0) & ((diff < (PTRDIFF_T)len) | + (diff > (0 - (PTRDIFF_T)len))); + + return overlapped; +} + +static int evp_EncryptDecryptUpdate(EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl, + const unsigned char *in, int inl) +{ + int i, j, bl, cmpl = inl; + + if (EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS)) + cmpl = (cmpl + 7) / 8; + + bl = ctx->cipher->block_size; + + if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) { + /* If block size > 1 then the cipher will have to do this check */ + if (bl == 1 && is_partially_overlapping(out, in, cmpl)) { + EVPerr(EVP_F_EVP_ENCRYPTDECRYPTUPDATE, EVP_R_PARTIALLY_OVERLAPPING); + return 0; + } + + i = ctx->cipher->do_cipher(ctx, out, in, inl); + if (i < 0) + return 0; + else + *outl = i; + return 1; + } + + if (inl <= 0) { + *outl = 0; + return inl == 0; + } + if (is_partially_overlapping(out + ctx->buf_len, in, cmpl)) { + EVPerr(EVP_F_EVP_ENCRYPTDECRYPTUPDATE, EVP_R_PARTIALLY_OVERLAPPING); + return 0; + } + + if (ctx->buf_len == 0 && (inl & (ctx->block_mask)) == 0) { + if (ctx->cipher->do_cipher(ctx, out, in, inl)) { + *outl = inl; + return 1; + } else { + *outl = 0; + return 0; + } + } + i = ctx->buf_len; + OPENSSL_assert(bl <= (int)sizeof(ctx->buf)); + if (i != 0) { + if (bl - i > inl) { + memcpy(&(ctx->buf[i]), in, inl); + ctx->buf_len += inl; + *outl = 0; + return 1; + } else { + j = bl - i; + memcpy(&(ctx->buf[i]), in, j); + inl -= j; + in += j; + if (!ctx->cipher->do_cipher(ctx, out, ctx->buf, bl)) + return 0; + out += bl; + *outl = bl; + } + } else + *outl = 0; + i = inl & (bl - 1); + inl -= i; + if (inl > 0) { + if (!ctx->cipher->do_cipher(ctx, out, in, inl)) + return 0; + *outl += inl; + } + + if (i != 0) + memcpy(ctx->buf, &(in[inl]), i); + ctx->buf_len = i; + return 1; +} + + +int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl) +{ + /* Prevent accidental use of decryption context when encrypting */ + if (!ctx->encrypt) { + EVPerr(EVP_F_EVP_ENCRYPTUPDATE, EVP_R_INVALID_OPERATION); + return 0; + } + + return evp_EncryptDecryptUpdate(ctx, out, outl, in, inl); +} + +int EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) +{ + int ret; + ret = EVP_EncryptFinal_ex(ctx, out, outl); + return ret; +} + +int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) +{ + int n, ret; + unsigned int i, b, bl; + + /* Prevent accidental use of decryption context when encrypting */ + if (!ctx->encrypt) { + EVPerr(EVP_F_EVP_ENCRYPTFINAL_EX, EVP_R_INVALID_OPERATION); + return 0; + } + + if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) { + ret = ctx->cipher->do_cipher(ctx, out, NULL, 0); + if (ret < 0) + return 0; + else + *outl = ret; + return 1; + } + + b = ctx->cipher->block_size; + OPENSSL_assert(b <= sizeof(ctx->buf)); + if (b == 1) { + *outl = 0; + return 1; + } + bl = ctx->buf_len; + if (ctx->flags & EVP_CIPH_NO_PADDING) { + if (bl) { + EVPerr(EVP_F_EVP_ENCRYPTFINAL_EX, + EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH); + return 0; + } + *outl = 0; + return 1; + } + + n = b - bl; + for (i = bl; i < b; i++) + ctx->buf[i] = n; + ret = ctx->cipher->do_cipher(ctx, out, ctx->buf, b); + + if (ret) + *outl = b; + + return ret; +} + +int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl) +{ + int fix_len, cmpl = inl; + unsigned int b; + + /* Prevent accidental use of encryption context when decrypting */ + if (ctx->encrypt) { + EVPerr(EVP_F_EVP_DECRYPTUPDATE, EVP_R_INVALID_OPERATION); + return 0; + } + + b = ctx->cipher->block_size; + + if (EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS)) + cmpl = (cmpl + 7) / 8; + + if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) { + if (b == 1 && is_partially_overlapping(out, in, cmpl)) { + EVPerr(EVP_F_EVP_DECRYPTUPDATE, EVP_R_PARTIALLY_OVERLAPPING); + return 0; + } + + fix_len = ctx->cipher->do_cipher(ctx, out, in, inl); + if (fix_len < 0) { + *outl = 0; + return 0; + } else + *outl = fix_len; + return 1; + } + + if (inl <= 0) { + *outl = 0; + return inl == 0; + } + + if (ctx->flags & EVP_CIPH_NO_PADDING) + return evp_EncryptDecryptUpdate(ctx, out, outl, in, inl); + + OPENSSL_assert(b <= sizeof(ctx->final)); + + if (ctx->final_used) { + /* see comment about PTRDIFF_T comparison above */ + if (((PTRDIFF_T)out == (PTRDIFF_T)in) + || is_partially_overlapping(out, in, b)) { + EVPerr(EVP_F_EVP_DECRYPTUPDATE, EVP_R_PARTIALLY_OVERLAPPING); + return 0; + } + memcpy(out, ctx->final, b); + out += b; + fix_len = 1; + } else + fix_len = 0; + + if (!evp_EncryptDecryptUpdate(ctx, out, outl, in, inl)) + return 0; + + /* + * if we have 'decrypted' a multiple of block size, make sure we have a + * copy of this last block + */ + if (b > 1 && !ctx->buf_len) { + *outl -= b; + ctx->final_used = 1; + memcpy(ctx->final, &out[*outl], b); + } else + ctx->final_used = 0; + + if (fix_len) + *outl += b; + + return 1; +} + +int EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) +{ + int ret; + ret = EVP_DecryptFinal_ex(ctx, out, outl); + return ret; +} + +int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) +{ + int i, n; + unsigned int b; + + /* Prevent accidental use of encryption context when decrypting */ + if (ctx->encrypt) { + EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_INVALID_OPERATION); + return 0; + } + + *outl = 0; + + if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) { + i = ctx->cipher->do_cipher(ctx, out, NULL, 0); + if (i < 0) + return 0; + else + *outl = i; + return 1; + } + + b = ctx->cipher->block_size; + if (ctx->flags & EVP_CIPH_NO_PADDING) { + if (ctx->buf_len) { + EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, + EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH); + return 0; + } + *outl = 0; + return 1; + } + if (b > 1) { + if (ctx->buf_len || !ctx->final_used) { + EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_WRONG_FINAL_BLOCK_LENGTH); + return 0; + } + OPENSSL_assert(b <= sizeof(ctx->final)); + + /* + * The following assumes that the ciphertext has been authenticated. + * Otherwise it provides a padding oracle. + */ + n = ctx->final[b - 1]; + if (n == 0 || n > (int)b) { + EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_BAD_DECRYPT); + return 0; + } + for (i = 0; i < n; i++) { + if (ctx->final[--b] != n) { + EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_BAD_DECRYPT); + return 0; + } + } + n = ctx->cipher->block_size - n; + for (i = 0; i < n; i++) + out[i] = ctx->final[i]; + *outl = n; + } else + *outl = 0; + return 1; +} + +int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, int keylen) +{ + if (c->cipher->flags & EVP_CIPH_CUSTOM_KEY_LENGTH) + return EVP_CIPHER_CTX_ctrl(c, EVP_CTRL_SET_KEY_LENGTH, keylen, NULL); + if (c->key_len == keylen) + return 1; + if ((keylen > 0) && (c->cipher->flags & EVP_CIPH_VARIABLE_LENGTH)) { + c->key_len = keylen; + return 1; + } + EVPerr(EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH, EVP_R_INVALID_KEY_LENGTH); + return 0; +} + +int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad) +{ + if (pad) + ctx->flags &= ~EVP_CIPH_NO_PADDING; + else + ctx->flags |= EVP_CIPH_NO_PADDING; + return 1; +} + +int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) +{ + int ret; + + if (!ctx->cipher) { + EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_NO_CIPHER_SET); + return 0; + } + + if (!ctx->cipher->ctrl) { + EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_CTRL_NOT_IMPLEMENTED); + return 0; + } + + ret = ctx->cipher->ctrl(ctx, type, arg, ptr); + if (ret == -1) { + EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, + EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED); + return 0; + } + return ret; +} + +int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key) +{ + if (ctx->cipher->flags & EVP_CIPH_RAND_KEY) + return EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_RAND_KEY, 0, key); + if (RAND_priv_bytes(key, ctx->key_len) <= 0) + return 0; + return 1; +} + +int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in) +{ + if ((in == NULL) || (in->cipher == NULL)) { + EVPerr(EVP_F_EVP_CIPHER_CTX_COPY, EVP_R_INPUT_NOT_INITIALIZED); + return 0; + } +#ifndef OPENSSL_NO_ENGINE + /* Make sure it's safe to copy a cipher context using an ENGINE */ + if (in->engine && !ENGINE_init(in->engine)) { + EVPerr(EVP_F_EVP_CIPHER_CTX_COPY, ERR_R_ENGINE_LIB); + return 0; + } +#endif + + EVP_CIPHER_CTX_reset(out); + memcpy(out, in, sizeof(*out)); + + if (in->cipher_data && in->cipher->ctx_size) { + out->cipher_data = OPENSSL_malloc(in->cipher->ctx_size); + if (out->cipher_data == NULL) { + out->cipher = NULL; + EVPerr(EVP_F_EVP_CIPHER_CTX_COPY, ERR_R_MALLOC_FAILURE); + return 0; + } + memcpy(out->cipher_data, in->cipher_data, in->cipher->ctx_size); + } + + if (in->cipher->flags & EVP_CIPH_CUSTOM_COPY) + if (!in->cipher->ctrl((EVP_CIPHER_CTX *)in, EVP_CTRL_COPY, 0, out)) { + out->cipher = NULL; + EVPerr(EVP_F_EVP_CIPHER_CTX_COPY, EVP_R_INITIALIZATION_ERROR); + return 0; + } + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_err.c new file mode 100644 index 000000000..60df27cbc --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_err.c @@ -0,0 +1,283 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA EVP_str_functs[] = { + {ERR_PACK(ERR_LIB_EVP, EVP_F_AESNI_INIT_KEY, 0), "aesni_init_key"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_AES_GCM_CTRL, 0), "aes_gcm_ctrl"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_AES_INIT_KEY, 0), "aes_init_key"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_AES_OCB_CIPHER, 0), "aes_ocb_cipher"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_AES_T4_INIT_KEY, 0), "aes_t4_init_key"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_AES_WRAP_CIPHER, 0), "aes_wrap_cipher"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_ALG_MODULE_INIT, 0), "alg_module_init"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_ARIA_CCM_INIT_KEY, 0), "aria_ccm_init_key"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_ARIA_GCM_CTRL, 0), "aria_gcm_ctrl"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_ARIA_GCM_INIT_KEY, 0), "aria_gcm_init_key"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_ARIA_INIT_KEY, 0), "aria_init_key"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_B64_NEW, 0), "b64_new"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_CAMELLIA_INIT_KEY, 0), "camellia_init_key"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_CHACHA20_POLY1305_CTRL, 0), + "chacha20_poly1305_ctrl"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_CMLL_T4_INIT_KEY, 0), "cmll_t4_init_key"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_DES_EDE3_WRAP_CIPHER, 0), + "des_ede3_wrap_cipher"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_DO_SIGVER_INIT, 0), "do_sigver_init"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_ENC_NEW, 0), "enc_new"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_CIPHERINIT_EX, 0), "EVP_CipherInit_ex"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_CIPHER_ASN1_TO_PARAM, 0), + "EVP_CIPHER_asn1_to_param"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_CIPHER_CTX_COPY, 0), + "EVP_CIPHER_CTX_copy"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_CIPHER_CTX_CTRL, 0), + "EVP_CIPHER_CTX_ctrl"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH, 0), + "EVP_CIPHER_CTX_set_key_length"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_CIPHER_PARAM_TO_ASN1, 0), + "EVP_CIPHER_param_to_asn1"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DECRYPTFINAL_EX, 0), + "EVP_DecryptFinal_ex"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DECRYPTUPDATE, 0), "EVP_DecryptUpdate"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DIGESTFINALXOF, 0), "EVP_DigestFinalXOF"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DIGESTINIT_EX, 0), "EVP_DigestInit_ex"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTDECRYPTUPDATE, 0), + "evp_EncryptDecryptUpdate"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTFINAL_EX, 0), + "EVP_EncryptFinal_ex"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTUPDATE, 0), "EVP_EncryptUpdate"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MD_CTX_COPY_EX, 0), "EVP_MD_CTX_copy_ex"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MD_SIZE, 0), "EVP_MD_size"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_OPENINIT, 0), "EVP_OpenInit"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PBE_ALG_ADD, 0), "EVP_PBE_alg_add"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PBE_ALG_ADD_TYPE, 0), + "EVP_PBE_alg_add_type"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PBE_CIPHERINIT, 0), "EVP_PBE_CipherInit"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PBE_SCRYPT, 0), "EVP_PBE_scrypt"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKCS82PKEY, 0), "EVP_PKCS82PKEY"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY2PKCS8, 0), "EVP_PKEY2PKCS8"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_ASN1_ADD0, 0), "EVP_PKEY_asn1_add0"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CHECK, 0), "EVP_PKEY_check"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_COPY_PARAMETERS, 0), + "EVP_PKEY_copy_parameters"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CTX_CTRL, 0), "EVP_PKEY_CTX_ctrl"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CTX_CTRL_STR, 0), + "EVP_PKEY_CTX_ctrl_str"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CTX_DUP, 0), "EVP_PKEY_CTX_dup"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CTX_MD, 0), "EVP_PKEY_CTX_md"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_DECRYPT, 0), "EVP_PKEY_decrypt"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_DECRYPT_INIT, 0), + "EVP_PKEY_decrypt_init"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_DECRYPT_OLD, 0), + "EVP_PKEY_decrypt_old"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_DERIVE, 0), "EVP_PKEY_derive"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_DERIVE_INIT, 0), + "EVP_PKEY_derive_init"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_DERIVE_SET_PEER, 0), + "EVP_PKEY_derive_set_peer"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_ENCRYPT, 0), "EVP_PKEY_encrypt"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_ENCRYPT_INIT, 0), + "EVP_PKEY_encrypt_init"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_ENCRYPT_OLD, 0), + "EVP_PKEY_encrypt_old"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_GET0_DH, 0), "EVP_PKEY_get0_DH"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_GET0_DSA, 0), "EVP_PKEY_get0_DSA"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_GET0_EC_KEY, 0), + "EVP_PKEY_get0_EC_KEY"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_GET0_HMAC, 0), "EVP_PKEY_get0_hmac"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_GET0_POLY1305, 0), + "EVP_PKEY_get0_poly1305"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_GET0_RSA, 0), "EVP_PKEY_get0_RSA"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_GET0_SIPHASH, 0), + "EVP_PKEY_get0_siphash"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY, 0), + "EVP_PKEY_get_raw_private_key"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_GET_RAW_PUBLIC_KEY, 0), + "EVP_PKEY_get_raw_public_key"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_KEYGEN, 0), "EVP_PKEY_keygen"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_KEYGEN_INIT, 0), + "EVP_PKEY_keygen_init"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_METH_ADD0, 0), "EVP_PKEY_meth_add0"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_METH_NEW, 0), "EVP_PKEY_meth_new"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_NEW, 0), "EVP_PKEY_new"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_NEW_CMAC_KEY, 0), + "EVP_PKEY_new_CMAC_key"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_NEW_RAW_PRIVATE_KEY, 0), + "EVP_PKEY_new_raw_private_key"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_NEW_RAW_PUBLIC_KEY, 0), + "EVP_PKEY_new_raw_public_key"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_PARAMGEN, 0), "EVP_PKEY_paramgen"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_PARAMGEN_INIT, 0), + "EVP_PKEY_paramgen_init"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_PARAM_CHECK, 0), + "EVP_PKEY_param_check"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_PUBLIC_CHECK, 0), + "EVP_PKEY_public_check"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_SET1_ENGINE, 0), + "EVP_PKEY_set1_engine"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_SET_ALIAS_TYPE, 0), + "EVP_PKEY_set_alias_type"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_SIGN, 0), "EVP_PKEY_sign"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_SIGN_INIT, 0), "EVP_PKEY_sign_init"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_VERIFY, 0), "EVP_PKEY_verify"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_VERIFY_INIT, 0), + "EVP_PKEY_verify_init"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_VERIFY_RECOVER, 0), + "EVP_PKEY_verify_recover"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_VERIFY_RECOVER_INIT, 0), + "EVP_PKEY_verify_recover_init"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_SIGNFINAL, 0), "EVP_SignFinal"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_VERIFYFINAL, 0), "EVP_VerifyFinal"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_INT_CTX_NEW, 0), "int_ctx_new"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_OK_NEW, 0), "ok_new"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_PKCS5_PBE_KEYIVGEN, 0), "PKCS5_PBE_keyivgen"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_PKCS5_V2_PBE_KEYIVGEN, 0), + "PKCS5_v2_PBE_keyivgen"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, 0), + "PKCS5_v2_PBKDF2_keyivgen"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, 0), + "PKCS5_v2_scrypt_keyivgen"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_PKEY_SET_TYPE, 0), "pkey_set_type"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_RC2_MAGIC_TO_METH, 0), "rc2_magic_to_meth"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_RC5_CTRL, 0), "rc5_ctrl"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_S390X_AES_GCM_CTRL, 0), "s390x_aes_gcm_ctrl"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_UPDATE, 0), "update"}, + {0, NULL} +}; + +static const ERR_STRING_DATA EVP_str_reasons[] = { + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_AES_KEY_SETUP_FAILED), + "aes key setup failed"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_ARIA_KEY_SETUP_FAILED), + "aria key setup failed"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_BAD_DECRYPT), "bad decrypt"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_BUFFER_TOO_SMALL), "buffer too small"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CAMELLIA_KEY_SETUP_FAILED), + "camellia key setup failed"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CIPHER_PARAMETER_ERROR), + "cipher parameter error"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_COMMAND_NOT_SUPPORTED), + "command not supported"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_COPY_ERROR), "copy error"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CTRL_NOT_IMPLEMENTED), + "ctrl not implemented"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED), + "ctrl operation not implemented"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH), + "data not multiple of block length"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DECODE_ERROR), "decode error"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DIFFERENT_KEY_TYPES), + "different key types"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DIFFERENT_PARAMETERS), + "different parameters"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_ERROR_LOADING_SECTION), + "error loading section"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_ERROR_SETTING_FIPS_MODE), + "error setting fips mode"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_AN_HMAC_KEY), + "expecting an hmac key"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_AN_RSA_KEY), + "expecting an rsa key"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_DH_KEY), "expecting a dh key"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_DSA_KEY), + "expecting a dsa key"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_EC_KEY), "expecting a ec key"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_POLY1305_KEY), + "expecting a poly1305 key"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_SIPHASH_KEY), + "expecting a siphash key"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_FIPS_MODE_NOT_SUPPORTED), + "fips mode not supported"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_GET_RAW_KEY_FAILED), "get raw key failed"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_ILLEGAL_SCRYPT_PARAMETERS), + "illegal scrypt parameters"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INITIALIZATION_ERROR), + "initialization error"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INPUT_NOT_INITIALIZED), + "input not initialized"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_DIGEST), "invalid digest"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_FIPS_MODE), "invalid fips mode"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_KEY), "invalid key"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_KEY_LENGTH), "invalid key length"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_OPERATION), "invalid operation"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_KEYGEN_FAILURE), "keygen failure"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_KEY_SETUP_FAILED), "key setup failed"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_MEMORY_LIMIT_EXCEEDED), + "memory limit exceeded"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_MESSAGE_DIGEST_IS_NULL), + "message digest is null"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_METHOD_NOT_SUPPORTED), + "method not supported"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_MISSING_PARAMETERS), "missing parameters"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NOT_XOF_OR_INVALID_LENGTH), + "not XOF or invalid length"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_CIPHER_SET), "no cipher set"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_DEFAULT_DIGEST), "no default digest"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_DIGEST_SET), "no digest set"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_KEY_SET), "no key set"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_OPERATION_SET), "no operation set"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_ONLY_ONESHOT_SUPPORTED), + "only oneshot supported"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE), + "operation not supported for this keytype"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_OPERATON_NOT_INITIALIZED), + "operaton not initialized"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PARTIALLY_OVERLAPPING), + "partially overlapping buffers"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PBKDF2_ERROR), "pbkdf2 error"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED), + "pkey application asn1 method already registered"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PRIVATE_KEY_DECODE_ERROR), + "private key decode error"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PRIVATE_KEY_ENCODE_ERROR), + "private key encode error"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PUBLIC_KEY_NOT_RSA), "public key not rsa"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_CIPHER), "unknown cipher"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_DIGEST), "unknown digest"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_OPTION), "unknown option"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_PBE_ALGORITHM), + "unknown pbe algorithm"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_ALGORITHM), + "unsupported algorithm"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_CIPHER), "unsupported cipher"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_KEYLENGTH), + "unsupported keylength"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION), + "unsupported key derivation function"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_KEY_SIZE), + "unsupported key size"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_NUMBER_OF_ROUNDS), + "unsupported number of rounds"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_PRF), "unsupported prf"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM), + "unsupported private key algorithm"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_SALT_TYPE), + "unsupported salt type"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_WRAP_MODE_NOT_ALLOWED), + "wrap mode not allowed"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_WRONG_FINAL_BLOCK_LENGTH), + "wrong final block length"}, + {0, NULL} +}; + +#endif + +int ERR_load_EVP_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(EVP_str_functs[0].error) == NULL) { + ERR_load_strings_const(EVP_str_functs); + ERR_load_strings_const(EVP_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_key.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_key.c new file mode 100644 index 000000000..e5ac107c3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_key.c @@ -0,0 +1,150 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include + +/* should be init to zeros. */ +static char prompt_string[80]; + +void EVP_set_pw_prompt(const char *prompt) +{ + if (prompt == NULL) + prompt_string[0] = '\0'; + else { + strncpy(prompt_string, prompt, 79); + prompt_string[79] = '\0'; + } +} + +char *EVP_get_pw_prompt(void) +{ + if (prompt_string[0] == '\0') + return NULL; + else + return prompt_string; +} + +/* + * For historical reasons, the standard function for reading passwords is in + * the DES library -- if someone ever wants to disable DES, this function + * will fail + */ +int EVP_read_pw_string(char *buf, int len, const char *prompt, int verify) +{ + return EVP_read_pw_string_min(buf, 0, len, prompt, verify); +} + +int EVP_read_pw_string_min(char *buf, int min, int len, const char *prompt, + int verify) +{ + int ret = -1; + char buff[BUFSIZ]; + UI *ui; + + if ((prompt == NULL) && (prompt_string[0] != '\0')) + prompt = prompt_string; + ui = UI_new(); + if (ui == NULL) + return ret; + if (UI_add_input_string(ui, prompt, 0, buf, min, + (len >= BUFSIZ) ? BUFSIZ - 1 : len) < 0 + || (verify + && UI_add_verify_string(ui, prompt, 0, buff, min, + (len >= BUFSIZ) ? BUFSIZ - 1 : len, + buf) < 0)) + goto end; + ret = UI_process(ui); + OPENSSL_cleanse(buff, BUFSIZ); + end: + UI_free(ui); + return ret; +} + +int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md, + const unsigned char *salt, const unsigned char *data, + int datal, int count, unsigned char *key, + unsigned char *iv) +{ + EVP_MD_CTX *c; + unsigned char md_buf[EVP_MAX_MD_SIZE]; + int niv, nkey, addmd = 0; + unsigned int mds = 0, i; + int rv = 0; + nkey = EVP_CIPHER_key_length(type); + niv = EVP_CIPHER_iv_length(type); + OPENSSL_assert(nkey <= EVP_MAX_KEY_LENGTH); + OPENSSL_assert(niv <= EVP_MAX_IV_LENGTH); + + if (data == NULL) + return nkey; + + c = EVP_MD_CTX_new(); + if (c == NULL) + goto err; + for (;;) { + if (!EVP_DigestInit_ex(c, md, NULL)) + goto err; + if (addmd++) + if (!EVP_DigestUpdate(c, &(md_buf[0]), mds)) + goto err; + if (!EVP_DigestUpdate(c, data, datal)) + goto err; + if (salt != NULL) + if (!EVP_DigestUpdate(c, salt, PKCS5_SALT_LEN)) + goto err; + if (!EVP_DigestFinal_ex(c, &(md_buf[0]), &mds)) + goto err; + + for (i = 1; i < (unsigned int)count; i++) { + if (!EVP_DigestInit_ex(c, md, NULL)) + goto err; + if (!EVP_DigestUpdate(c, &(md_buf[0]), mds)) + goto err; + if (!EVP_DigestFinal_ex(c, &(md_buf[0]), &mds)) + goto err; + } + i = 0; + if (nkey) { + for (;;) { + if (nkey == 0) + break; + if (i == mds) + break; + if (key != NULL) + *(key++) = md_buf[i]; + nkey--; + i++; + } + } + if (niv && (i != mds)) { + for (;;) { + if (niv == 0) + break; + if (i == mds) + break; + if (iv != NULL) + *(iv++) = md_buf[i]; + niv--; + i++; + } + } + if ((nkey == 0) && (niv == 0)) + break; + } + rv = EVP_CIPHER_key_length(type); + err: + EVP_MD_CTX_free(c); + OPENSSL_cleanse(md_buf, sizeof(md_buf)); + return rv; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_lib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_lib.c new file mode 100644 index 000000000..1b3c9840c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_lib.c @@ -0,0 +1,528 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include "internal/evp_int.h" +#include "evp_locl.h" + +int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type) +{ + int ret; + + if (c->cipher->set_asn1_parameters != NULL) + ret = c->cipher->set_asn1_parameters(c, type); + else if (c->cipher->flags & EVP_CIPH_FLAG_DEFAULT_ASN1) { + switch (EVP_CIPHER_CTX_mode(c)) { + case EVP_CIPH_WRAP_MODE: + if (EVP_CIPHER_CTX_nid(c) == NID_id_smime_alg_CMS3DESwrap) + ASN1_TYPE_set(type, V_ASN1_NULL, NULL); + ret = 1; + break; + + case EVP_CIPH_GCM_MODE: + case EVP_CIPH_CCM_MODE: + case EVP_CIPH_XTS_MODE: + case EVP_CIPH_OCB_MODE: + ret = -2; + break; + + default: + ret = EVP_CIPHER_set_asn1_iv(c, type); + } + } else + ret = -1; + if (ret <= 0) + EVPerr(EVP_F_EVP_CIPHER_PARAM_TO_ASN1, ret == -2 ? + ASN1_R_UNSUPPORTED_CIPHER : + EVP_R_CIPHER_PARAMETER_ERROR); + if (ret < -1) + ret = -1; + return ret; +} + +int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type) +{ + int ret; + + if (c->cipher->get_asn1_parameters != NULL) + ret = c->cipher->get_asn1_parameters(c, type); + else if (c->cipher->flags & EVP_CIPH_FLAG_DEFAULT_ASN1) { + switch (EVP_CIPHER_CTX_mode(c)) { + + case EVP_CIPH_WRAP_MODE: + ret = 1; + break; + + case EVP_CIPH_GCM_MODE: + case EVP_CIPH_CCM_MODE: + case EVP_CIPH_XTS_MODE: + case EVP_CIPH_OCB_MODE: + ret = -2; + break; + + default: + ret = EVP_CIPHER_get_asn1_iv(c, type); + break; + } + } else + ret = -1; + if (ret <= 0) + EVPerr(EVP_F_EVP_CIPHER_ASN1_TO_PARAM, ret == -2 ? + EVP_R_UNSUPPORTED_CIPHER : + EVP_R_CIPHER_PARAMETER_ERROR); + if (ret < -1) + ret = -1; + return ret; +} + +int EVP_CIPHER_get_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type) +{ + int i = 0; + unsigned int l; + + if (type != NULL) { + l = EVP_CIPHER_CTX_iv_length(c); + OPENSSL_assert(l <= sizeof(c->iv)); + i = ASN1_TYPE_get_octetstring(type, c->oiv, l); + if (i != (int)l) + return -1; + else if (i > 0) + memcpy(c->iv, c->oiv, l); + } + return i; +} + +int EVP_CIPHER_set_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type) +{ + int i = 0; + unsigned int j; + + if (type != NULL) { + j = EVP_CIPHER_CTX_iv_length(c); + OPENSSL_assert(j <= sizeof(c->iv)); + i = ASN1_TYPE_set_octetstring(type, c->oiv, j); + } + return i; +} + +/* Convert the various cipher NIDs and dummies to a proper OID NID */ +int EVP_CIPHER_type(const EVP_CIPHER *ctx) +{ + int nid; + ASN1_OBJECT *otmp; + nid = EVP_CIPHER_nid(ctx); + + switch (nid) { + + case NID_rc2_cbc: + case NID_rc2_64_cbc: + case NID_rc2_40_cbc: + + return NID_rc2_cbc; + + case NID_rc4: + case NID_rc4_40: + + return NID_rc4; + + case NID_aes_128_cfb128: + case NID_aes_128_cfb8: + case NID_aes_128_cfb1: + + return NID_aes_128_cfb128; + + case NID_aes_192_cfb128: + case NID_aes_192_cfb8: + case NID_aes_192_cfb1: + + return NID_aes_192_cfb128; + + case NID_aes_256_cfb128: + case NID_aes_256_cfb8: + case NID_aes_256_cfb1: + + return NID_aes_256_cfb128; + + case NID_des_cfb64: + case NID_des_cfb8: + case NID_des_cfb1: + + return NID_des_cfb64; + + case NID_des_ede3_cfb64: + case NID_des_ede3_cfb8: + case NID_des_ede3_cfb1: + + return NID_des_cfb64; + + default: + /* Check it has an OID and it is valid */ + otmp = OBJ_nid2obj(nid); + if (OBJ_get0_data(otmp) == NULL) + nid = NID_undef; + ASN1_OBJECT_free(otmp); + return nid; + } +} + +int EVP_CIPHER_block_size(const EVP_CIPHER *e) +{ + return e->block_size; +} + +int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx) +{ + return ctx->cipher->block_size; +} + +int EVP_CIPHER_impl_ctx_size(const EVP_CIPHER *e) +{ + return e->ctx_size; +} + +int EVP_Cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, unsigned int inl) +{ + return ctx->cipher->do_cipher(ctx, out, in, inl); +} + +const EVP_CIPHER *EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx) +{ + return ctx->cipher; +} + +int EVP_CIPHER_CTX_encrypting(const EVP_CIPHER_CTX *ctx) +{ + return ctx->encrypt; +} + +unsigned long EVP_CIPHER_flags(const EVP_CIPHER *cipher) +{ + return cipher->flags; +} + +void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx) +{ + return ctx->app_data; +} + +void EVP_CIPHER_CTX_set_app_data(EVP_CIPHER_CTX *ctx, void *data) +{ + ctx->app_data = data; +} + +void *EVP_CIPHER_CTX_get_cipher_data(const EVP_CIPHER_CTX *ctx) +{ + return ctx->cipher_data; +} + +void *EVP_CIPHER_CTX_set_cipher_data(EVP_CIPHER_CTX *ctx, void *cipher_data) +{ + void *old_cipher_data; + + old_cipher_data = ctx->cipher_data; + ctx->cipher_data = cipher_data; + + return old_cipher_data; +} + +int EVP_CIPHER_iv_length(const EVP_CIPHER *cipher) +{ + return cipher->iv_len; +} + +int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx) +{ + return ctx->cipher->iv_len; +} + +const unsigned char *EVP_CIPHER_CTX_original_iv(const EVP_CIPHER_CTX *ctx) +{ + return ctx->oiv; +} + +const unsigned char *EVP_CIPHER_CTX_iv(const EVP_CIPHER_CTX *ctx) +{ + return ctx->iv; +} + +unsigned char *EVP_CIPHER_CTX_iv_noconst(EVP_CIPHER_CTX *ctx) +{ + return ctx->iv; +} + +unsigned char *EVP_CIPHER_CTX_buf_noconst(EVP_CIPHER_CTX *ctx) +{ + return ctx->buf; +} + +int EVP_CIPHER_CTX_num(const EVP_CIPHER_CTX *ctx) +{ + return ctx->num; +} + +void EVP_CIPHER_CTX_set_num(EVP_CIPHER_CTX *ctx, int num) +{ + ctx->num = num; +} + +int EVP_CIPHER_key_length(const EVP_CIPHER *cipher) +{ + return cipher->key_len; +} + +int EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx) +{ + return ctx->key_len; +} + +int EVP_CIPHER_nid(const EVP_CIPHER *cipher) +{ + return cipher->nid; +} + +int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx) +{ + return ctx->cipher->nid; +} + +int EVP_MD_block_size(const EVP_MD *md) +{ + return md->block_size; +} + +int EVP_MD_type(const EVP_MD *md) +{ + return md->type; +} + +int EVP_MD_pkey_type(const EVP_MD *md) +{ + return md->pkey_type; +} + +int EVP_MD_size(const EVP_MD *md) +{ + if (!md) { + EVPerr(EVP_F_EVP_MD_SIZE, EVP_R_MESSAGE_DIGEST_IS_NULL); + return -1; + } + return md->md_size; +} + +unsigned long EVP_MD_flags(const EVP_MD *md) +{ + return md->flags; +} + +EVP_MD *EVP_MD_meth_new(int md_type, int pkey_type) +{ + EVP_MD *md = OPENSSL_zalloc(sizeof(*md)); + + if (md != NULL) { + md->type = md_type; + md->pkey_type = pkey_type; + } + return md; +} +EVP_MD *EVP_MD_meth_dup(const EVP_MD *md) +{ + EVP_MD *to = EVP_MD_meth_new(md->type, md->pkey_type); + + if (to != NULL) + memcpy(to, md, sizeof(*to)); + return to; +} +void EVP_MD_meth_free(EVP_MD *md) +{ + OPENSSL_free(md); +} +int EVP_MD_meth_set_input_blocksize(EVP_MD *md, int blocksize) +{ + md->block_size = blocksize; + return 1; +} +int EVP_MD_meth_set_result_size(EVP_MD *md, int resultsize) +{ + md->md_size = resultsize; + return 1; +} +int EVP_MD_meth_set_app_datasize(EVP_MD *md, int datasize) +{ + md->ctx_size = datasize; + return 1; +} +int EVP_MD_meth_set_flags(EVP_MD *md, unsigned long flags) +{ + md->flags = flags; + return 1; +} +int EVP_MD_meth_set_init(EVP_MD *md, int (*init)(EVP_MD_CTX *ctx)) +{ + md->init = init; + return 1; +} +int EVP_MD_meth_set_update(EVP_MD *md, int (*update)(EVP_MD_CTX *ctx, + const void *data, + size_t count)) +{ + md->update = update; + return 1; +} +int EVP_MD_meth_set_final(EVP_MD *md, int (*final)(EVP_MD_CTX *ctx, + unsigned char *md)) +{ + md->final = final; + return 1; +} +int EVP_MD_meth_set_copy(EVP_MD *md, int (*copy)(EVP_MD_CTX *to, + const EVP_MD_CTX *from)) +{ + md->copy = copy; + return 1; +} +int EVP_MD_meth_set_cleanup(EVP_MD *md, int (*cleanup)(EVP_MD_CTX *ctx)) +{ + md->cleanup = cleanup; + return 1; +} +int EVP_MD_meth_set_ctrl(EVP_MD *md, int (*ctrl)(EVP_MD_CTX *ctx, int cmd, + int p1, void *p2)) +{ + md->md_ctrl = ctrl; + return 1; +} + +int EVP_MD_meth_get_input_blocksize(const EVP_MD *md) +{ + return md->block_size; +} +int EVP_MD_meth_get_result_size(const EVP_MD *md) +{ + return md->md_size; +} +int EVP_MD_meth_get_app_datasize(const EVP_MD *md) +{ + return md->ctx_size; +} +unsigned long EVP_MD_meth_get_flags(const EVP_MD *md) +{ + return md->flags; +} +int (*EVP_MD_meth_get_init(const EVP_MD *md))(EVP_MD_CTX *ctx) +{ + return md->init; +} +int (*EVP_MD_meth_get_update(const EVP_MD *md))(EVP_MD_CTX *ctx, + const void *data, + size_t count) +{ + return md->update; +} +int (*EVP_MD_meth_get_final(const EVP_MD *md))(EVP_MD_CTX *ctx, + unsigned char *md) +{ + return md->final; +} +int (*EVP_MD_meth_get_copy(const EVP_MD *md))(EVP_MD_CTX *to, + const EVP_MD_CTX *from) +{ + return md->copy; +} +int (*EVP_MD_meth_get_cleanup(const EVP_MD *md))(EVP_MD_CTX *ctx) +{ + return md->cleanup; +} +int (*EVP_MD_meth_get_ctrl(const EVP_MD *md))(EVP_MD_CTX *ctx, int cmd, + int p1, void *p2) +{ + return md->md_ctrl; +} + +const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx) +{ + if (!ctx) + return NULL; + return ctx->digest; +} + +EVP_PKEY_CTX *EVP_MD_CTX_pkey_ctx(const EVP_MD_CTX *ctx) +{ + return ctx->pctx; +} + +void EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx) +{ + /* + * it's reasonable to set NULL pctx (a.k.a clear the ctx->pctx), so + * we have to deal with the cleanup job here. + */ + if (!EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX)) + EVP_PKEY_CTX_free(ctx->pctx); + + ctx->pctx = pctx; + + if (pctx != NULL) { + /* make sure pctx is not freed when destroying EVP_MD_CTX */ + EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX); + } else { + EVP_MD_CTX_clear_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX); + } +} + +void *EVP_MD_CTX_md_data(const EVP_MD_CTX *ctx) +{ + return ctx->md_data; +} + +int (*EVP_MD_CTX_update_fn(EVP_MD_CTX *ctx))(EVP_MD_CTX *ctx, + const void *data, size_t count) +{ + return ctx->update; +} + +void EVP_MD_CTX_set_update_fn(EVP_MD_CTX *ctx, + int (*update) (EVP_MD_CTX *ctx, + const void *data, size_t count)) +{ + ctx->update = update; +} + +void EVP_MD_CTX_set_flags(EVP_MD_CTX *ctx, int flags) +{ + ctx->flags |= flags; +} + +void EVP_MD_CTX_clear_flags(EVP_MD_CTX *ctx, int flags) +{ + ctx->flags &= ~flags; +} + +int EVP_MD_CTX_test_flags(const EVP_MD_CTX *ctx, int flags) +{ + return (ctx->flags & flags); +} + +void EVP_CIPHER_CTX_set_flags(EVP_CIPHER_CTX *ctx, int flags) +{ + ctx->flags |= flags; +} + +void EVP_CIPHER_CTX_clear_flags(EVP_CIPHER_CTX *ctx, int flags) +{ + ctx->flags &= ~flags; +} + +int EVP_CIPHER_CTX_test_flags(const EVP_CIPHER_CTX *ctx, int flags) +{ + return (ctx->flags & flags); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_locl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_locl.h new file mode 100644 index 000000000..f1589d682 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_locl.h @@ -0,0 +1,68 @@ +/* + * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* EVP_MD_CTX related stuff */ + +struct evp_md_ctx_st { + const EVP_MD *digest; + ENGINE *engine; /* functional reference if 'digest' is + * ENGINE-provided */ + unsigned long flags; + void *md_data; + /* Public key context for sign/verify */ + EVP_PKEY_CTX *pctx; + /* Update function: usually copied from EVP_MD */ + int (*update) (EVP_MD_CTX *ctx, const void *data, size_t count); +} /* EVP_MD_CTX */ ; + +struct evp_cipher_ctx_st { + const EVP_CIPHER *cipher; + ENGINE *engine; /* functional reference if 'cipher' is + * ENGINE-provided */ + int encrypt; /* encrypt or decrypt */ + int buf_len; /* number we have left */ + unsigned char oiv[EVP_MAX_IV_LENGTH]; /* original iv */ + unsigned char iv[EVP_MAX_IV_LENGTH]; /* working iv */ + unsigned char buf[EVP_MAX_BLOCK_LENGTH]; /* saved partial block */ + int num; /* used by cfb/ofb/ctr mode */ + /* FIXME: Should this even exist? It appears unused */ + void *app_data; /* application stuff */ + int key_len; /* May change for variable length cipher */ + unsigned long flags; /* Various flags */ + void *cipher_data; /* per EVP data */ + int final_used; + int block_mask; + unsigned char final[EVP_MAX_BLOCK_LENGTH]; /* possible final block */ +} /* EVP_CIPHER_CTX */ ; + +int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, + int passlen, ASN1_TYPE *param, + const EVP_CIPHER *c, const EVP_MD *md, + int en_de); + +struct evp_Encode_Ctx_st { + /* number saved in a partial encode/decode */ + int num; + /* + * The length is either the output line length (in input bytes) or the + * shortest input line length that is ok. Once decoding begins, the + * length is adjusted up each time a longer line is decoded + */ + int length; + /* data to encode */ + unsigned char enc_data[80]; + /* number read on current line */ + int line_num; + unsigned int flags; +}; + +typedef struct evp_pbe_st EVP_PBE_CTL; +DEFINE_STACK_OF(EVP_PBE_CTL) + +int is_partially_overlapping(const void *ptr1, const void *ptr2, int len); diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_pbe.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_pbe.c new file mode 100644 index 000000000..5a88817b4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_pbe.c @@ -0,0 +1,262 @@ +/* + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include "evp_locl.h" + +/* Password based encryption (PBE) functions */ + +/* Setup a cipher context from a PBE algorithm */ + +struct evp_pbe_st { + int pbe_type; + int pbe_nid; + int cipher_nid; + int md_nid; + EVP_PBE_KEYGEN *keygen; +}; + +static STACK_OF(EVP_PBE_CTL) *pbe_algs; + +static const EVP_PBE_CTL builtin_pbe[] = { + {EVP_PBE_TYPE_OUTER, NID_pbeWithMD2AndDES_CBC, + NID_des_cbc, NID_md2, PKCS5_PBE_keyivgen}, + {EVP_PBE_TYPE_OUTER, NID_pbeWithMD5AndDES_CBC, + NID_des_cbc, NID_md5, PKCS5_PBE_keyivgen}, + {EVP_PBE_TYPE_OUTER, NID_pbeWithSHA1AndRC2_CBC, + NID_rc2_64_cbc, NID_sha1, PKCS5_PBE_keyivgen}, + + {EVP_PBE_TYPE_OUTER, NID_id_pbkdf2, -1, -1, PKCS5_v2_PBKDF2_keyivgen}, + + {EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And128BitRC4, + NID_rc4, NID_sha1, PKCS12_PBE_keyivgen}, + {EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And40BitRC4, + NID_rc4_40, NID_sha1, PKCS12_PBE_keyivgen}, + {EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And3_Key_TripleDES_CBC, + NID_des_ede3_cbc, NID_sha1, PKCS12_PBE_keyivgen}, + {EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And2_Key_TripleDES_CBC, + NID_des_ede_cbc, NID_sha1, PKCS12_PBE_keyivgen}, + {EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And128BitRC2_CBC, + NID_rc2_cbc, NID_sha1, PKCS12_PBE_keyivgen}, + {EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And40BitRC2_CBC, + NID_rc2_40_cbc, NID_sha1, PKCS12_PBE_keyivgen}, + + {EVP_PBE_TYPE_OUTER, NID_pbes2, -1, -1, PKCS5_v2_PBE_keyivgen}, + + {EVP_PBE_TYPE_OUTER, NID_pbeWithMD2AndRC2_CBC, + NID_rc2_64_cbc, NID_md2, PKCS5_PBE_keyivgen}, + {EVP_PBE_TYPE_OUTER, NID_pbeWithMD5AndRC2_CBC, + NID_rc2_64_cbc, NID_md5, PKCS5_PBE_keyivgen}, + {EVP_PBE_TYPE_OUTER, NID_pbeWithSHA1AndDES_CBC, + NID_des_cbc, NID_sha1, PKCS5_PBE_keyivgen}, + + {EVP_PBE_TYPE_PRF, NID_hmacWithSHA1, -1, NID_sha1, 0}, + {EVP_PBE_TYPE_PRF, NID_hmac_md5, -1, NID_md5, 0}, + {EVP_PBE_TYPE_PRF, NID_hmac_sha1, -1, NID_sha1, 0}, + {EVP_PBE_TYPE_PRF, NID_hmacWithMD5, -1, NID_md5, 0}, + {EVP_PBE_TYPE_PRF, NID_hmacWithSHA224, -1, NID_sha224, 0}, + {EVP_PBE_TYPE_PRF, NID_hmacWithSHA256, -1, NID_sha256, 0}, + {EVP_PBE_TYPE_PRF, NID_hmacWithSHA384, -1, NID_sha384, 0}, + {EVP_PBE_TYPE_PRF, NID_hmacWithSHA512, -1, NID_sha512, 0}, + {EVP_PBE_TYPE_PRF, NID_id_HMACGostR3411_94, -1, NID_id_GostR3411_94, 0}, + {EVP_PBE_TYPE_PRF, NID_id_tc26_hmac_gost_3411_2012_256, -1, + NID_id_GostR3411_2012_256, 0}, + {EVP_PBE_TYPE_PRF, NID_id_tc26_hmac_gost_3411_2012_512, -1, + NID_id_GostR3411_2012_512, 0}, + {EVP_PBE_TYPE_PRF, NID_hmacWithSHA512_224, -1, NID_sha512_224, 0}, + {EVP_PBE_TYPE_PRF, NID_hmacWithSHA512_256, -1, NID_sha512_256, 0}, + {EVP_PBE_TYPE_KDF, NID_id_pbkdf2, -1, -1, PKCS5_v2_PBKDF2_keyivgen}, +#ifndef OPENSSL_NO_SCRYPT + {EVP_PBE_TYPE_KDF, NID_id_scrypt, -1, -1, PKCS5_v2_scrypt_keyivgen} +#endif +}; + +int EVP_PBE_CipherInit(ASN1_OBJECT *pbe_obj, const char *pass, int passlen, + ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de) +{ + const EVP_CIPHER *cipher; + const EVP_MD *md; + int cipher_nid, md_nid; + EVP_PBE_KEYGEN *keygen; + + if (!EVP_PBE_find(EVP_PBE_TYPE_OUTER, OBJ_obj2nid(pbe_obj), + &cipher_nid, &md_nid, &keygen)) { + char obj_tmp[80]; + EVPerr(EVP_F_EVP_PBE_CIPHERINIT, EVP_R_UNKNOWN_PBE_ALGORITHM); + if (!pbe_obj) + OPENSSL_strlcpy(obj_tmp, "NULL", sizeof(obj_tmp)); + else + i2t_ASN1_OBJECT(obj_tmp, sizeof(obj_tmp), pbe_obj); + ERR_add_error_data(2, "TYPE=", obj_tmp); + return 0; + } + + if (!pass) + passlen = 0; + else if (passlen == -1) + passlen = strlen(pass); + + if (cipher_nid == -1) + cipher = NULL; + else { + cipher = EVP_get_cipherbynid(cipher_nid); + if (!cipher) { + EVPerr(EVP_F_EVP_PBE_CIPHERINIT, EVP_R_UNKNOWN_CIPHER); + return 0; + } + } + + if (md_nid == -1) + md = NULL; + else { + md = EVP_get_digestbynid(md_nid); + if (!md) { + EVPerr(EVP_F_EVP_PBE_CIPHERINIT, EVP_R_UNKNOWN_DIGEST); + return 0; + } + } + + if (!keygen(ctx, pass, passlen, param, cipher, md, en_de)) { + EVPerr(EVP_F_EVP_PBE_CIPHERINIT, EVP_R_KEYGEN_FAILURE); + return 0; + } + return 1; +} + +DECLARE_OBJ_BSEARCH_CMP_FN(EVP_PBE_CTL, EVP_PBE_CTL, pbe2); + +static int pbe2_cmp(const EVP_PBE_CTL *pbe1, const EVP_PBE_CTL *pbe2) +{ + int ret = pbe1->pbe_type - pbe2->pbe_type; + if (ret) + return ret; + else + return pbe1->pbe_nid - pbe2->pbe_nid; +} + +IMPLEMENT_OBJ_BSEARCH_CMP_FN(EVP_PBE_CTL, EVP_PBE_CTL, pbe2); + +static int pbe_cmp(const EVP_PBE_CTL *const *a, const EVP_PBE_CTL *const *b) +{ + int ret = (*a)->pbe_type - (*b)->pbe_type; + if (ret) + return ret; + else + return (*a)->pbe_nid - (*b)->pbe_nid; +} + +/* Add a PBE algorithm */ + +int EVP_PBE_alg_add_type(int pbe_type, int pbe_nid, int cipher_nid, + int md_nid, EVP_PBE_KEYGEN *keygen) +{ + EVP_PBE_CTL *pbe_tmp; + + if (pbe_algs == NULL) { + pbe_algs = sk_EVP_PBE_CTL_new(pbe_cmp); + if (pbe_algs == NULL) + goto err; + } + + if ((pbe_tmp = OPENSSL_malloc(sizeof(*pbe_tmp))) == NULL) + goto err; + + pbe_tmp->pbe_type = pbe_type; + pbe_tmp->pbe_nid = pbe_nid; + pbe_tmp->cipher_nid = cipher_nid; + pbe_tmp->md_nid = md_nid; + pbe_tmp->keygen = keygen; + + if (!sk_EVP_PBE_CTL_push(pbe_algs, pbe_tmp)) { + OPENSSL_free(pbe_tmp); + goto err; + } + return 1; + + err: + EVPerr(EVP_F_EVP_PBE_ALG_ADD_TYPE, ERR_R_MALLOC_FAILURE); + return 0; +} + +int EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md, + EVP_PBE_KEYGEN *keygen) +{ + int cipher_nid, md_nid; + + if (cipher) + cipher_nid = EVP_CIPHER_nid(cipher); + else + cipher_nid = -1; + if (md) + md_nid = EVP_MD_type(md); + else + md_nid = -1; + + return EVP_PBE_alg_add_type(EVP_PBE_TYPE_OUTER, nid, + cipher_nid, md_nid, keygen); +} + +int EVP_PBE_find(int type, int pbe_nid, + int *pcnid, int *pmnid, EVP_PBE_KEYGEN **pkeygen) +{ + EVP_PBE_CTL *pbetmp = NULL, pbelu; + int i; + if (pbe_nid == NID_undef) + return 0; + + pbelu.pbe_type = type; + pbelu.pbe_nid = pbe_nid; + + if (pbe_algs != NULL) { + i = sk_EVP_PBE_CTL_find(pbe_algs, &pbelu); + pbetmp = sk_EVP_PBE_CTL_value(pbe_algs, i); + } + if (pbetmp == NULL) { + pbetmp = OBJ_bsearch_pbe2(&pbelu, builtin_pbe, OSSL_NELEM(builtin_pbe)); + } + if (pbetmp == NULL) + return 0; + if (pcnid) + *pcnid = pbetmp->cipher_nid; + if (pmnid) + *pmnid = pbetmp->md_nid; + if (pkeygen) + *pkeygen = pbetmp->keygen; + return 1; +} + +static void free_evp_pbe_ctl(EVP_PBE_CTL *pbe) +{ + OPENSSL_free(pbe); +} + +void EVP_PBE_cleanup(void) +{ + sk_EVP_PBE_CTL_pop_free(pbe_algs, free_evp_pbe_ctl); + pbe_algs = NULL; +} + +int EVP_PBE_get(int *ptype, int *ppbe_nid, size_t num) +{ + const EVP_PBE_CTL *tpbe; + + if (num >= OSSL_NELEM(builtin_pbe)) + return 0; + + tpbe = builtin_pbe + num; + if (ptype) + *ptype = tpbe->pbe_type; + if (ppbe_nid) + *ppbe_nid = tpbe->pbe_nid; + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_pkey.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_pkey.c new file mode 100644 index 000000000..e61a8761a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/evp_pkey.c @@ -0,0 +1,149 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include +#include +#include "internal/asn1_int.h" +#include "internal/evp_int.h" +#include "internal/x509_int.h" + +/* Extract a private key from a PKCS8 structure */ + +EVP_PKEY *EVP_PKCS82PKEY(const PKCS8_PRIV_KEY_INFO *p8) +{ + EVP_PKEY *pkey = NULL; + const ASN1_OBJECT *algoid; + char obj_tmp[80]; + + if (!PKCS8_pkey_get0(&algoid, NULL, NULL, NULL, p8)) + return NULL; + + if ((pkey = EVP_PKEY_new()) == NULL) { + EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (!EVP_PKEY_set_type(pkey, OBJ_obj2nid(algoid))) { + EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM); + i2t_ASN1_OBJECT(obj_tmp, 80, algoid); + ERR_add_error_data(2, "TYPE=", obj_tmp); + goto error; + } + + if (pkey->ameth->priv_decode) { + if (!pkey->ameth->priv_decode(pkey, p8)) { + EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_PRIVATE_KEY_DECODE_ERROR); + goto error; + } + } else { + EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_METHOD_NOT_SUPPORTED); + goto error; + } + + return pkey; + + error: + EVP_PKEY_free(pkey); + return NULL; +} + +/* Turn a private key into a PKCS8 structure */ + +PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey) +{ + PKCS8_PRIV_KEY_INFO *p8 = PKCS8_PRIV_KEY_INFO_new(); + if (p8 == NULL) { + EVPerr(EVP_F_EVP_PKEY2PKCS8, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (pkey->ameth) { + if (pkey->ameth->priv_encode) { + if (!pkey->ameth->priv_encode(p8, pkey)) { + EVPerr(EVP_F_EVP_PKEY2PKCS8, EVP_R_PRIVATE_KEY_ENCODE_ERROR); + goto error; + } + } else { + EVPerr(EVP_F_EVP_PKEY2PKCS8, EVP_R_METHOD_NOT_SUPPORTED); + goto error; + } + } else { + EVPerr(EVP_F_EVP_PKEY2PKCS8, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM); + goto error; + } + return p8; + error: + PKCS8_PRIV_KEY_INFO_free(p8); + return NULL; +} + +/* EVP_PKEY attribute functions */ + +int EVP_PKEY_get_attr_count(const EVP_PKEY *key) +{ + return X509at_get_attr_count(key->attributes); +} + +int EVP_PKEY_get_attr_by_NID(const EVP_PKEY *key, int nid, int lastpos) +{ + return X509at_get_attr_by_NID(key->attributes, nid, lastpos); +} + +int EVP_PKEY_get_attr_by_OBJ(const EVP_PKEY *key, const ASN1_OBJECT *obj, + int lastpos) +{ + return X509at_get_attr_by_OBJ(key->attributes, obj, lastpos); +} + +X509_ATTRIBUTE *EVP_PKEY_get_attr(const EVP_PKEY *key, int loc) +{ + return X509at_get_attr(key->attributes, loc); +} + +X509_ATTRIBUTE *EVP_PKEY_delete_attr(EVP_PKEY *key, int loc) +{ + return X509at_delete_attr(key->attributes, loc); +} + +int EVP_PKEY_add1_attr(EVP_PKEY *key, X509_ATTRIBUTE *attr) +{ + if (X509at_add1_attr(&key->attributes, attr)) + return 1; + return 0; +} + +int EVP_PKEY_add1_attr_by_OBJ(EVP_PKEY *key, + const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, int len) +{ + if (X509at_add1_attr_by_OBJ(&key->attributes, obj, type, bytes, len)) + return 1; + return 0; +} + +int EVP_PKEY_add1_attr_by_NID(EVP_PKEY *key, + int nid, int type, + const unsigned char *bytes, int len) +{ + if (X509at_add1_attr_by_NID(&key->attributes, nid, type, bytes, len)) + return 1; + return 0; +} + +int EVP_PKEY_add1_attr_by_txt(EVP_PKEY *key, + const char *attrname, int type, + const unsigned char *bytes, int len) +{ + if (X509at_add1_attr_by_txt(&key->attributes, attrname, type, bytes, len)) + return 1; + return 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_md2.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_md2.c new file mode 100644 index 000000000..c4e28ae17 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_md2.c @@ -0,0 +1,56 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" + +#ifndef OPENSSL_NO_MD2 + +# include +# include +# include +# include +# include + +#include "internal/evp_int.h" + +static int init(EVP_MD_CTX *ctx) +{ + return MD2_Init(EVP_MD_CTX_md_data(ctx)); +} + +static int update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ + return MD2_Update(EVP_MD_CTX_md_data(ctx), data, count); +} + +static int final(EVP_MD_CTX *ctx, unsigned char *md) +{ + return MD2_Final(md, EVP_MD_CTX_md_data(ctx)); +} + +static const EVP_MD md2_md = { + NID_md2, + NID_md2WithRSAEncryption, + MD2_DIGEST_LENGTH, + 0, + init, + update, + final, + NULL, + NULL, + MD2_BLOCK, + sizeof(EVP_MD *) + sizeof(MD2_CTX), +}; + +const EVP_MD *EVP_md2(void) +{ + return &md2_md; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_md4.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_md4.c new file mode 100644 index 000000000..0efc586db --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_md4.c @@ -0,0 +1,55 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" + +#ifndef OPENSSL_NO_MD4 + +# include +# include +# include +# include +# include +# include "internal/evp_int.h" + +static int init(EVP_MD_CTX *ctx) +{ + return MD4_Init(EVP_MD_CTX_md_data(ctx)); +} + +static int update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ + return MD4_Update(EVP_MD_CTX_md_data(ctx), data, count); +} + +static int final(EVP_MD_CTX *ctx, unsigned char *md) +{ + return MD4_Final(md, EVP_MD_CTX_md_data(ctx)); +} + +static const EVP_MD md4_md = { + NID_md4, + NID_md4WithRSAEncryption, + MD4_DIGEST_LENGTH, + 0, + init, + update, + final, + NULL, + NULL, + MD4_CBLOCK, + sizeof(EVP_MD *) + sizeof(MD4_CTX), +}; + +const EVP_MD *EVP_md4(void) +{ + return &md4_md; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_md5.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_md5.c new file mode 100644 index 000000000..3d96ae93b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_md5.c @@ -0,0 +1,55 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" + +#ifndef OPENSSL_NO_MD5 + +# include +# include +# include +# include +# include +# include "internal/evp_int.h" + +static int init(EVP_MD_CTX *ctx) +{ + return MD5_Init(EVP_MD_CTX_md_data(ctx)); +} + +static int update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ + return MD5_Update(EVP_MD_CTX_md_data(ctx), data, count); +} + +static int final(EVP_MD_CTX *ctx, unsigned char *md) +{ + return MD5_Final(md, EVP_MD_CTX_md_data(ctx)); +} + +static const EVP_MD md5_md = { + NID_md5, + NID_md5WithRSAEncryption, + MD5_DIGEST_LENGTH, + 0, + init, + update, + final, + NULL, + NULL, + MD5_CBLOCK, + sizeof(EVP_MD *) + sizeof(MD5_CTX), +}; + +const EVP_MD *EVP_md5(void) +{ + return &md5_md; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_md5_sha1.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_md5_sha1.c new file mode 100644 index 000000000..2d98886ba --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_md5_sha1.c @@ -0,0 +1,142 @@ +/* + * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#if !defined(OPENSSL_NO_MD5) + +# include +# include +# include +# include +# include +# include "internal/cryptlib.h" +# include "internal/evp_int.h" +# include + +struct md5_sha1_ctx { + MD5_CTX md5; + SHA_CTX sha1; +}; + +static int init(EVP_MD_CTX *ctx) +{ + struct md5_sha1_ctx *mctx = EVP_MD_CTX_md_data(ctx); + if (!MD5_Init(&mctx->md5)) + return 0; + return SHA1_Init(&mctx->sha1); +} + +static int update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ + struct md5_sha1_ctx *mctx = EVP_MD_CTX_md_data(ctx); + if (!MD5_Update(&mctx->md5, data, count)) + return 0; + return SHA1_Update(&mctx->sha1, data, count); +} + +static int final(EVP_MD_CTX *ctx, unsigned char *md) +{ + struct md5_sha1_ctx *mctx = EVP_MD_CTX_md_data(ctx); + if (!MD5_Final(md, &mctx->md5)) + return 0; + return SHA1_Final(md + MD5_DIGEST_LENGTH, &mctx->sha1); +} + +static int ctrl(EVP_MD_CTX *ctx, int cmd, int mslen, void *ms) +{ + unsigned char padtmp[48]; + unsigned char md5tmp[MD5_DIGEST_LENGTH]; + unsigned char sha1tmp[SHA_DIGEST_LENGTH]; + struct md5_sha1_ctx *mctx; + + if (cmd != EVP_CTRL_SSL3_MASTER_SECRET) + return -2; + + if (ctx == NULL) + return 0; + + mctx = EVP_MD_CTX_md_data(ctx); + + /* SSLv3 client auth handling: see RFC-6101 5.6.8 */ + if (mslen != 48) + return 0; + + /* At this point hash contains all handshake messages, update + * with master secret and pad_1. + */ + + if (update(ctx, ms, mslen) <= 0) + return 0; + + /* Set padtmp to pad_1 value */ + memset(padtmp, 0x36, sizeof(padtmp)); + + if (!MD5_Update(&mctx->md5, padtmp, sizeof(padtmp))) + return 0; + + if (!MD5_Final(md5tmp, &mctx->md5)) + return 0; + + if (!SHA1_Update(&mctx->sha1, padtmp, 40)) + return 0; + + if (!SHA1_Final(sha1tmp, &mctx->sha1)) + return 0; + + /* Reinitialise context */ + + if (!init(ctx)) + return 0; + + if (update(ctx, ms, mslen) <= 0) + return 0; + + /* Set padtmp to pad_2 value */ + memset(padtmp, 0x5c, sizeof(padtmp)); + + if (!MD5_Update(&mctx->md5, padtmp, sizeof(padtmp))) + return 0; + + if (!MD5_Update(&mctx->md5, md5tmp, sizeof(md5tmp))) + return 0; + + if (!SHA1_Update(&mctx->sha1, padtmp, 40)) + return 0; + + if (!SHA1_Update(&mctx->sha1, sha1tmp, sizeof(sha1tmp))) + return 0; + + /* Now when ctx is finalised it will return the SSL v3 hash value */ + + OPENSSL_cleanse(md5tmp, sizeof(md5tmp)); + OPENSSL_cleanse(sha1tmp, sizeof(sha1tmp)); + + return 1; + +} + +static const EVP_MD md5_sha1_md = { + NID_md5_sha1, + NID_md5_sha1, + MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH, + 0, + init, + update, + final, + NULL, + NULL, + MD5_CBLOCK, + sizeof(EVP_MD *) + sizeof(struct md5_sha1_ctx), + ctrl +}; + +const EVP_MD *EVP_md5_sha1(void) +{ + return &md5_sha1_md; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_mdc2.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_mdc2.c new file mode 100644 index 000000000..1051a9070 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_mdc2.c @@ -0,0 +1,55 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" + +#ifndef OPENSSL_NO_MDC2 + +# include +# include +# include +# include +# include +# include "internal/evp_int.h" + +static int init(EVP_MD_CTX *ctx) +{ + return MDC2_Init(EVP_MD_CTX_md_data(ctx)); +} + +static int update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ + return MDC2_Update(EVP_MD_CTX_md_data(ctx), data, count); +} + +static int final(EVP_MD_CTX *ctx, unsigned char *md) +{ + return MDC2_Final(md, EVP_MD_CTX_md_data(ctx)); +} + +static const EVP_MD mdc2_md = { + NID_mdc2, + NID_mdc2WithRSA, + MDC2_DIGEST_LENGTH, + 0, + init, + update, + final, + NULL, + NULL, + MDC2_BLOCK, + sizeof(EVP_MD *) + sizeof(MDC2_CTX), +}; + +const EVP_MD *EVP_mdc2(void) +{ + return &mdc2_md; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_null.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_null.c new file mode 100644 index 000000000..5dce1d510 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_null.c @@ -0,0 +1,49 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include "internal/evp_int.h" + +static int init(EVP_MD_CTX *ctx) +{ + return 1; +} + +static int update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ + return 1; +} + +static int final(EVP_MD_CTX *ctx, unsigned char *md) +{ + return 1; +} + +static const EVP_MD null_md = { + NID_undef, + NID_undef, + 0, + 0, + init, + update, + final, + NULL, + NULL, + 0, + sizeof(EVP_MD *), +}; + +const EVP_MD *EVP_md_null(void) +{ + return &null_md; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_ripemd.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_ripemd.c new file mode 100644 index 000000000..7ab320843 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_ripemd.c @@ -0,0 +1,55 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" + +#ifndef OPENSSL_NO_RMD160 + +# include +# include +# include +# include +# include +# include "internal/evp_int.h" + +static int init(EVP_MD_CTX *ctx) +{ + return RIPEMD160_Init(EVP_MD_CTX_md_data(ctx)); +} + +static int update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ + return RIPEMD160_Update(EVP_MD_CTX_md_data(ctx), data, count); +} + +static int final(EVP_MD_CTX *ctx, unsigned char *md) +{ + return RIPEMD160_Final(md, EVP_MD_CTX_md_data(ctx)); +} + +static const EVP_MD ripemd160_md = { + NID_ripemd160, + NID_ripemd160WithRSA, + RIPEMD160_DIGEST_LENGTH, + 0, + init, + update, + final, + NULL, + NULL, + RIPEMD160_CBLOCK, + sizeof(EVP_MD *) + sizeof(RIPEMD160_CTX), +}; + +const EVP_MD *EVP_ripemd160(void) +{ + return &ripemd160_md; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_sha1.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_sha1.c new file mode 100644 index 000000000..ac5241785 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_sha1.c @@ -0,0 +1,297 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" + +#include +#include +#include +#include +#include "internal/evp_int.h" +#include "internal/sha.h" + +static int init(EVP_MD_CTX *ctx) +{ + return SHA1_Init(EVP_MD_CTX_md_data(ctx)); +} + +static int update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ + return SHA1_Update(EVP_MD_CTX_md_data(ctx), data, count); +} + +static int final(EVP_MD_CTX *ctx, unsigned char *md) +{ + return SHA1_Final(md, EVP_MD_CTX_md_data(ctx)); +} + +static int ctrl(EVP_MD_CTX *ctx, int cmd, int mslen, void *ms) +{ + unsigned char padtmp[40]; + unsigned char sha1tmp[SHA_DIGEST_LENGTH]; + + SHA_CTX *sha1; + + if (cmd != EVP_CTRL_SSL3_MASTER_SECRET) + return -2; + + if (ctx == NULL) + return 0; + + sha1 = EVP_MD_CTX_md_data(ctx); + + /* SSLv3 client auth handling: see RFC-6101 5.6.8 */ + if (mslen != 48) + return 0; + + /* At this point hash contains all handshake messages, update + * with master secret and pad_1. + */ + + if (SHA1_Update(sha1, ms, mslen) <= 0) + return 0; + + /* Set padtmp to pad_1 value */ + memset(padtmp, 0x36, sizeof(padtmp)); + + if (!SHA1_Update(sha1, padtmp, sizeof(padtmp))) + return 0; + + if (!SHA1_Final(sha1tmp, sha1)) + return 0; + + /* Reinitialise context */ + + if (!SHA1_Init(sha1)) + return 0; + + if (SHA1_Update(sha1, ms, mslen) <= 0) + return 0; + + /* Set padtmp to pad_2 value */ + memset(padtmp, 0x5c, sizeof(padtmp)); + + if (!SHA1_Update(sha1, padtmp, sizeof(padtmp))) + return 0; + + if (!SHA1_Update(sha1, sha1tmp, sizeof(sha1tmp))) + return 0; + + /* Now when ctx is finalised it will return the SSL v3 hash value */ + OPENSSL_cleanse(sha1tmp, sizeof(sha1tmp)); + + return 1; + +} + +static const EVP_MD sha1_md = { + NID_sha1, + NID_sha1WithRSAEncryption, + SHA_DIGEST_LENGTH, + EVP_MD_FLAG_DIGALGID_ABSENT, + init, + update, + final, + NULL, + NULL, + SHA_CBLOCK, + sizeof(EVP_MD *) + sizeof(SHA_CTX), + ctrl +}; + +const EVP_MD *EVP_sha1(void) +{ + return &sha1_md; +} + +static int init224(EVP_MD_CTX *ctx) +{ + return SHA224_Init(EVP_MD_CTX_md_data(ctx)); +} + +static int update224(EVP_MD_CTX *ctx, const void *data, size_t count) +{ + return SHA224_Update(EVP_MD_CTX_md_data(ctx), data, count); +} + +static int final224(EVP_MD_CTX *ctx, unsigned char *md) +{ + return SHA224_Final(md, EVP_MD_CTX_md_data(ctx)); +} + +static int init256(EVP_MD_CTX *ctx) +{ + return SHA256_Init(EVP_MD_CTX_md_data(ctx)); +} + +static int update256(EVP_MD_CTX *ctx, const void *data, size_t count) +{ + return SHA256_Update(EVP_MD_CTX_md_data(ctx), data, count); +} + +static int final256(EVP_MD_CTX *ctx, unsigned char *md) +{ + return SHA256_Final(md, EVP_MD_CTX_md_data(ctx)); +} + +static const EVP_MD sha224_md = { + NID_sha224, + NID_sha224WithRSAEncryption, + SHA224_DIGEST_LENGTH, + EVP_MD_FLAG_DIGALGID_ABSENT, + init224, + update224, + final224, + NULL, + NULL, + SHA256_CBLOCK, + sizeof(EVP_MD *) + sizeof(SHA256_CTX), +}; + +const EVP_MD *EVP_sha224(void) +{ + return &sha224_md; +} + +static const EVP_MD sha256_md = { + NID_sha256, + NID_sha256WithRSAEncryption, + SHA256_DIGEST_LENGTH, + EVP_MD_FLAG_DIGALGID_ABSENT, + init256, + update256, + final256, + NULL, + NULL, + SHA256_CBLOCK, + sizeof(EVP_MD *) + sizeof(SHA256_CTX), +}; + +const EVP_MD *EVP_sha256(void) +{ + return &sha256_md; +} + +static int init512_224(EVP_MD_CTX *ctx) +{ + return sha512_224_init(EVP_MD_CTX_md_data(ctx)); +} + +static int init512_256(EVP_MD_CTX *ctx) +{ + return sha512_256_init(EVP_MD_CTX_md_data(ctx)); +} + +static int init384(EVP_MD_CTX *ctx) +{ + return SHA384_Init(EVP_MD_CTX_md_data(ctx)); +} + +static int update384(EVP_MD_CTX *ctx, const void *data, size_t count) +{ + return SHA384_Update(EVP_MD_CTX_md_data(ctx), data, count); +} + +static int final384(EVP_MD_CTX *ctx, unsigned char *md) +{ + return SHA384_Final(md, EVP_MD_CTX_md_data(ctx)); +} + +static int init512(EVP_MD_CTX *ctx) +{ + return SHA512_Init(EVP_MD_CTX_md_data(ctx)); +} + +/* See comment in SHA224/256 section */ +static int update512(EVP_MD_CTX *ctx, const void *data, size_t count) +{ + return SHA512_Update(EVP_MD_CTX_md_data(ctx), data, count); +} + +static int final512(EVP_MD_CTX *ctx, unsigned char *md) +{ + return SHA512_Final(md, EVP_MD_CTX_md_data(ctx)); +} + +static const EVP_MD sha512_224_md = { + NID_sha512_224, + NID_sha512_224WithRSAEncryption, + SHA224_DIGEST_LENGTH, + EVP_MD_FLAG_DIGALGID_ABSENT, + init512_224, + update512, + final512, + NULL, + NULL, + SHA512_CBLOCK, + sizeof(EVP_MD *) + sizeof(SHA512_CTX), +}; + +const EVP_MD *EVP_sha512_224(void) +{ + return &sha512_224_md; +} + +static const EVP_MD sha512_256_md = { + NID_sha512_256, + NID_sha512_256WithRSAEncryption, + SHA256_DIGEST_LENGTH, + EVP_MD_FLAG_DIGALGID_ABSENT, + init512_256, + update512, + final512, + NULL, + NULL, + SHA512_CBLOCK, + sizeof(EVP_MD *) + sizeof(SHA512_CTX), +}; + +const EVP_MD *EVP_sha512_256(void) +{ + return &sha512_256_md; +} + +static const EVP_MD sha384_md = { + NID_sha384, + NID_sha384WithRSAEncryption, + SHA384_DIGEST_LENGTH, + EVP_MD_FLAG_DIGALGID_ABSENT, + init384, + update384, + final384, + NULL, + NULL, + SHA512_CBLOCK, + sizeof(EVP_MD *) + sizeof(SHA512_CTX), +}; + +const EVP_MD *EVP_sha384(void) +{ + return &sha384_md; +} + +static const EVP_MD sha512_md = { + NID_sha512, + NID_sha512WithRSAEncryption, + SHA512_DIGEST_LENGTH, + EVP_MD_FLAG_DIGALGID_ABSENT, + init512, + update512, + final512, + NULL, + NULL, + SHA512_CBLOCK, + sizeof(EVP_MD *) + sizeof(SHA512_CTX), +}; + +const EVP_MD *EVP_sha512(void) +{ + return &sha512_md; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_sha3.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_sha3.c new file mode 100644 index 000000000..31379c0f6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_sha3.c @@ -0,0 +1,406 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#include +#include +#include "internal/evp_int.h" +#include "evp_locl.h" + +size_t SHA3_absorb(uint64_t A[5][5], const unsigned char *inp, size_t len, + size_t r); +void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len, size_t r); + +#define KECCAK1600_WIDTH 1600 + +typedef struct { + uint64_t A[5][5]; + size_t block_size; /* cached ctx->digest->block_size */ + size_t md_size; /* output length, variable in XOF */ + size_t num; /* used bytes in below buffer */ + unsigned char buf[KECCAK1600_WIDTH / 8 - 32]; + unsigned char pad; +} KECCAK1600_CTX; + +static int init(EVP_MD_CTX *evp_ctx, unsigned char pad) +{ + KECCAK1600_CTX *ctx = evp_ctx->md_data; + size_t bsz = evp_ctx->digest->block_size; + + if (bsz <= sizeof(ctx->buf)) { + memset(ctx->A, 0, sizeof(ctx->A)); + + ctx->num = 0; + ctx->block_size = bsz; + ctx->md_size = evp_ctx->digest->md_size; + ctx->pad = pad; + + return 1; + } + + return 0; +} + +static int sha3_init(EVP_MD_CTX *evp_ctx) +{ + return init(evp_ctx, '\x06'); +} + +static int shake_init(EVP_MD_CTX *evp_ctx) +{ + return init(evp_ctx, '\x1f'); +} + +static int sha3_update(EVP_MD_CTX *evp_ctx, const void *_inp, size_t len) +{ + KECCAK1600_CTX *ctx = evp_ctx->md_data; + const unsigned char *inp = _inp; + size_t bsz = ctx->block_size; + size_t num, rem; + + if (len == 0) + return 1; + + if ((num = ctx->num) != 0) { /* process intermediate buffer? */ + rem = bsz - num; + + if (len < rem) { + memcpy(ctx->buf + num, inp, len); + ctx->num += len; + return 1; + } + /* + * We have enough data to fill or overflow the intermediate + * buffer. So we append |rem| bytes and process the block, + * leaving the rest for later processing... + */ + memcpy(ctx->buf + num, inp, rem); + inp += rem, len -= rem; + (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz); + ctx->num = 0; + /* ctx->buf is processed, ctx->num is guaranteed to be zero */ + } + + if (len >= bsz) + rem = SHA3_absorb(ctx->A, inp, len, bsz); + else + rem = len; + + if (rem) { + memcpy(ctx->buf, inp + len - rem, rem); + ctx->num = rem; + } + + return 1; +} + +static int sha3_final(EVP_MD_CTX *evp_ctx, unsigned char *md) +{ + KECCAK1600_CTX *ctx = evp_ctx->md_data; + size_t bsz = ctx->block_size; + size_t num = ctx->num; + + /* + * Pad the data with 10*1. Note that |num| can be |bsz - 1| + * in which case both byte operations below are performed on + * same byte... + */ + memset(ctx->buf + num, 0, bsz - num); + ctx->buf[num] = ctx->pad; + ctx->buf[bsz - 1] |= 0x80; + + (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz); + + SHA3_squeeze(ctx->A, md, ctx->md_size, bsz); + + return 1; +} + +static int shake_ctrl(EVP_MD_CTX *evp_ctx, int cmd, int p1, void *p2) +{ + KECCAK1600_CTX *ctx = evp_ctx->md_data; + + switch (cmd) { + case EVP_MD_CTRL_XOF_LEN: + ctx->md_size = p1; + return 1; + default: + return 0; + } +} + +#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__) && defined(KECCAK1600_ASM) +/* + * IBM S390X support + */ +# include "s390x_arch.h" + +# define S390X_SHA3_FC(ctx) ((ctx)->pad) + +# define S390X_sha3_224_CAPABLE ((OPENSSL_s390xcap_P.kimd[0] & \ + S390X_CAPBIT(S390X_SHA3_224)) && \ + (OPENSSL_s390xcap_P.klmd[0] & \ + S390X_CAPBIT(S390X_SHA3_224))) +# define S390X_sha3_256_CAPABLE ((OPENSSL_s390xcap_P.kimd[0] & \ + S390X_CAPBIT(S390X_SHA3_256)) && \ + (OPENSSL_s390xcap_P.klmd[0] & \ + S390X_CAPBIT(S390X_SHA3_256))) +# define S390X_sha3_384_CAPABLE ((OPENSSL_s390xcap_P.kimd[0] & \ + S390X_CAPBIT(S390X_SHA3_384)) && \ + (OPENSSL_s390xcap_P.klmd[0] & \ + S390X_CAPBIT(S390X_SHA3_384))) +# define S390X_sha3_512_CAPABLE ((OPENSSL_s390xcap_P.kimd[0] & \ + S390X_CAPBIT(S390X_SHA3_512)) && \ + (OPENSSL_s390xcap_P.klmd[0] & \ + S390X_CAPBIT(S390X_SHA3_512))) +# define S390X_shake128_CAPABLE ((OPENSSL_s390xcap_P.kimd[0] & \ + S390X_CAPBIT(S390X_SHAKE_128)) && \ + (OPENSSL_s390xcap_P.klmd[0] & \ + S390X_CAPBIT(S390X_SHAKE_128))) +# define S390X_shake256_CAPABLE ((OPENSSL_s390xcap_P.kimd[0] & \ + S390X_CAPBIT(S390X_SHAKE_256)) && \ + (OPENSSL_s390xcap_P.klmd[0] & \ + S390X_CAPBIT(S390X_SHAKE_256))) + +/* Convert md-size to block-size. */ +# define S390X_KECCAK1600_BSZ(n) ((KECCAK1600_WIDTH - ((n) << 1)) >> 3) + +static int s390x_sha3_init(EVP_MD_CTX *evp_ctx) +{ + KECCAK1600_CTX *ctx = evp_ctx->md_data; + const size_t bsz = evp_ctx->digest->block_size; + + /*- + * KECCAK1600_CTX structure's pad field is used to store the KIMD/KLMD + * function code. + */ + switch (bsz) { + case S390X_KECCAK1600_BSZ(224): + ctx->pad = S390X_SHA3_224; + break; + case S390X_KECCAK1600_BSZ(256): + ctx->pad = S390X_SHA3_256; + break; + case S390X_KECCAK1600_BSZ(384): + ctx->pad = S390X_SHA3_384; + break; + case S390X_KECCAK1600_BSZ(512): + ctx->pad = S390X_SHA3_512; + break; + default: + return 0; + } + + memset(ctx->A, 0, sizeof(ctx->A)); + ctx->num = 0; + ctx->block_size = bsz; + ctx->md_size = evp_ctx->digest->md_size; + return 1; +} + +static int s390x_shake_init(EVP_MD_CTX *evp_ctx) +{ + KECCAK1600_CTX *ctx = evp_ctx->md_data; + const size_t bsz = evp_ctx->digest->block_size; + + /*- + * KECCAK1600_CTX structure's pad field is used to store the KIMD/KLMD + * function code. + */ + switch (bsz) { + case S390X_KECCAK1600_BSZ(128): + ctx->pad = S390X_SHAKE_128; + break; + case S390X_KECCAK1600_BSZ(256): + ctx->pad = S390X_SHAKE_256; + break; + default: + return 0; + } + + memset(ctx->A, 0, sizeof(ctx->A)); + ctx->num = 0; + ctx->block_size = bsz; + ctx->md_size = evp_ctx->digest->md_size; + return 1; +} + +static int s390x_sha3_update(EVP_MD_CTX *evp_ctx, const void *_inp, size_t len) +{ + KECCAK1600_CTX *ctx = evp_ctx->md_data; + const unsigned char *inp = _inp; + const size_t bsz = ctx->block_size; + size_t num, rem; + + if (len == 0) + return 1; + + if ((num = ctx->num) != 0) { + rem = bsz - num; + + if (len < rem) { + memcpy(ctx->buf + num, inp, len); + ctx->num += len; + return 1; + } + memcpy(ctx->buf + num, inp, rem); + inp += rem; + len -= rem; + s390x_kimd(ctx->buf, bsz, ctx->pad, ctx->A); + ctx->num = 0; + } + rem = len % bsz; + + s390x_kimd(inp, len - rem, ctx->pad, ctx->A); + + if (rem) { + memcpy(ctx->buf, inp + len - rem, rem); + ctx->num = rem; + } + return 1; +} + +static int s390x_sha3_final(EVP_MD_CTX *evp_ctx, unsigned char *md) +{ + KECCAK1600_CTX *ctx = evp_ctx->md_data; + + s390x_klmd(ctx->buf, ctx->num, NULL, 0, ctx->pad, ctx->A); + memcpy(md, ctx->A, ctx->md_size); + return 1; +} + +static int s390x_shake_final(EVP_MD_CTX *evp_ctx, unsigned char *md) +{ + KECCAK1600_CTX *ctx = evp_ctx->md_data; + + s390x_klmd(ctx->buf, ctx->num, md, ctx->md_size, ctx->pad, ctx->A); + return 1; +} + +# define EVP_MD_SHA3(bitlen) \ +const EVP_MD *EVP_sha3_##bitlen(void) \ +{ \ + static const EVP_MD s390x_sha3_##bitlen##_md = { \ + NID_sha3_##bitlen, \ + NID_RSA_SHA3_##bitlen, \ + bitlen / 8, \ + EVP_MD_FLAG_DIGALGID_ABSENT, \ + s390x_sha3_init, \ + s390x_sha3_update, \ + s390x_sha3_final, \ + NULL, \ + NULL, \ + (KECCAK1600_WIDTH - bitlen * 2) / 8, \ + sizeof(KECCAK1600_CTX), \ + }; \ + static const EVP_MD sha3_##bitlen##_md = { \ + NID_sha3_##bitlen, \ + NID_RSA_SHA3_##bitlen, \ + bitlen / 8, \ + EVP_MD_FLAG_DIGALGID_ABSENT, \ + sha3_init, \ + sha3_update, \ + sha3_final, \ + NULL, \ + NULL, \ + (KECCAK1600_WIDTH - bitlen * 2) / 8, \ + sizeof(KECCAK1600_CTX), \ + }; \ + return S390X_sha3_##bitlen##_CAPABLE ? \ + &s390x_sha3_##bitlen##_md : \ + &sha3_##bitlen##_md; \ +} + +# define EVP_MD_SHAKE(bitlen) \ +const EVP_MD *EVP_shake##bitlen(void) \ +{ \ + static const EVP_MD s390x_shake##bitlen##_md = { \ + NID_shake##bitlen, \ + 0, \ + bitlen / 8, \ + EVP_MD_FLAG_XOF, \ + s390x_shake_init, \ + s390x_sha3_update, \ + s390x_shake_final, \ + NULL, \ + NULL, \ + (KECCAK1600_WIDTH - bitlen * 2) / 8, \ + sizeof(KECCAK1600_CTX), \ + shake_ctrl \ + }; \ + static const EVP_MD shake##bitlen##_md = { \ + NID_shake##bitlen, \ + 0, \ + bitlen / 8, \ + EVP_MD_FLAG_XOF, \ + shake_init, \ + sha3_update, \ + sha3_final, \ + NULL, \ + NULL, \ + (KECCAK1600_WIDTH - bitlen * 2) / 8, \ + sizeof(KECCAK1600_CTX), \ + shake_ctrl \ + }; \ + return S390X_shake##bitlen##_CAPABLE ? \ + &s390x_shake##bitlen##_md : \ + &shake##bitlen##_md; \ +} + +#else + +# define EVP_MD_SHA3(bitlen) \ +const EVP_MD *EVP_sha3_##bitlen(void) \ +{ \ + static const EVP_MD sha3_##bitlen##_md = { \ + NID_sha3_##bitlen, \ + NID_RSA_SHA3_##bitlen, \ + bitlen / 8, \ + EVP_MD_FLAG_DIGALGID_ABSENT, \ + sha3_init, \ + sha3_update, \ + sha3_final, \ + NULL, \ + NULL, \ + (KECCAK1600_WIDTH - bitlen * 2) / 8, \ + sizeof(KECCAK1600_CTX), \ + }; \ + return &sha3_##bitlen##_md; \ +} + +# define EVP_MD_SHAKE(bitlen) \ +const EVP_MD *EVP_shake##bitlen(void) \ +{ \ + static const EVP_MD shake##bitlen##_md = { \ + NID_shake##bitlen, \ + 0, \ + bitlen / 8, \ + EVP_MD_FLAG_XOF, \ + shake_init, \ + sha3_update, \ + sha3_final, \ + NULL, \ + NULL, \ + (KECCAK1600_WIDTH - bitlen * 2) / 8, \ + sizeof(KECCAK1600_CTX), \ + shake_ctrl \ + }; \ + return &shake##bitlen##_md; \ +} +#endif + +EVP_MD_SHA3(224) +EVP_MD_SHA3(256) +EVP_MD_SHA3(384) +EVP_MD_SHA3(512) + +EVP_MD_SHAKE(128) +EVP_MD_SHAKE(256) diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_sigver.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_sigver.c new file mode 100644 index 000000000..94e37f02b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_sigver.c @@ -0,0 +1,218 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include "internal/evp_int.h" +#include "evp_locl.h" + +static int update(EVP_MD_CTX *ctx, const void *data, size_t datalen) +{ + EVPerr(EVP_F_UPDATE, EVP_R_ONLY_ONESHOT_SUPPORTED); + return 0; +} + +static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, + const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey, + int ver) +{ + if (ctx->pctx == NULL) + ctx->pctx = EVP_PKEY_CTX_new(pkey, e); + if (ctx->pctx == NULL) + return 0; + + if (!(ctx->pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM)) { + + if (type == NULL) { + int def_nid; + if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) > 0) + type = EVP_get_digestbynid(def_nid); + } + + if (type == NULL) { + EVPerr(EVP_F_DO_SIGVER_INIT, EVP_R_NO_DEFAULT_DIGEST); + return 0; + } + } + + if (ver) { + if (ctx->pctx->pmeth->verifyctx_init) { + if (ctx->pctx->pmeth->verifyctx_init(ctx->pctx, ctx) <= 0) + return 0; + ctx->pctx->operation = EVP_PKEY_OP_VERIFYCTX; + } else if (ctx->pctx->pmeth->digestverify != 0) { + ctx->pctx->operation = EVP_PKEY_OP_VERIFY; + ctx->update = update; + } else if (EVP_PKEY_verify_init(ctx->pctx) <= 0) { + return 0; + } + } else { + if (ctx->pctx->pmeth->signctx_init) { + if (ctx->pctx->pmeth->signctx_init(ctx->pctx, ctx) <= 0) + return 0; + ctx->pctx->operation = EVP_PKEY_OP_SIGNCTX; + } else if (ctx->pctx->pmeth->digestsign != 0) { + ctx->pctx->operation = EVP_PKEY_OP_SIGN; + ctx->update = update; + } else if (EVP_PKEY_sign_init(ctx->pctx) <= 0) { + return 0; + } + } + if (EVP_PKEY_CTX_set_signature_md(ctx->pctx, type) <= 0) + return 0; + if (pctx) + *pctx = ctx->pctx; + if (ctx->pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) + return 1; + if (!EVP_DigestInit_ex(ctx, type, e)) + return 0; + /* + * This indicates the current algorithm requires + * special treatment before hashing the tbs-message. + */ + if (ctx->pctx->pmeth->digest_custom != NULL) + return ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx); + + return 1; +} + +int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, + const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey) +{ + return do_sigver_init(ctx, pctx, type, e, pkey, 0); +} + +int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, + const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey) +{ + return do_sigver_init(ctx, pctx, type, e, pkey, 1); +} + +int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, + size_t *siglen) +{ + int sctx = 0, r = 0; + EVP_PKEY_CTX *pctx = ctx->pctx; + if (pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) { + if (!sigret) + return pctx->pmeth->signctx(pctx, sigret, siglen, ctx); + if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) + r = pctx->pmeth->signctx(pctx, sigret, siglen, ctx); + else { + EVP_PKEY_CTX *dctx = EVP_PKEY_CTX_dup(ctx->pctx); + if (!dctx) + return 0; + r = dctx->pmeth->signctx(dctx, sigret, siglen, ctx); + EVP_PKEY_CTX_free(dctx); + } + return r; + } + if (pctx->pmeth->signctx) + sctx = 1; + else + sctx = 0; + if (sigret) { + unsigned char md[EVP_MAX_MD_SIZE]; + unsigned int mdlen = 0; + if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) { + if (sctx) + r = ctx->pctx->pmeth->signctx(ctx->pctx, sigret, siglen, ctx); + else + r = EVP_DigestFinal_ex(ctx, md, &mdlen); + } else { + EVP_MD_CTX *tmp_ctx = EVP_MD_CTX_new(); + if (tmp_ctx == NULL) + return 0; + if (!EVP_MD_CTX_copy_ex(tmp_ctx, ctx)) { + EVP_MD_CTX_free(tmp_ctx); + return 0; + } + if (sctx) + r = tmp_ctx->pctx->pmeth->signctx(tmp_ctx->pctx, + sigret, siglen, tmp_ctx); + else + r = EVP_DigestFinal_ex(tmp_ctx, md, &mdlen); + EVP_MD_CTX_free(tmp_ctx); + } + if (sctx || !r) + return r; + if (EVP_PKEY_sign(ctx->pctx, sigret, siglen, md, mdlen) <= 0) + return 0; + } else { + if (sctx) { + if (pctx->pmeth->signctx(pctx, sigret, siglen, ctx) <= 0) + return 0; + } else { + int s = EVP_MD_size(ctx->digest); + if (s < 0 || EVP_PKEY_sign(pctx, sigret, siglen, NULL, s) <= 0) + return 0; + } + } + return 1; +} + +int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen, + const unsigned char *tbs, size_t tbslen) +{ + if (ctx->pctx->pmeth->digestsign != NULL) + return ctx->pctx->pmeth->digestsign(ctx, sigret, siglen, tbs, tbslen); + if (sigret != NULL && EVP_DigestSignUpdate(ctx, tbs, tbslen) <= 0) + return 0; + return EVP_DigestSignFinal(ctx, sigret, siglen); +} + +int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig, + size_t siglen) +{ + unsigned char md[EVP_MAX_MD_SIZE]; + int r = 0; + unsigned int mdlen = 0; + int vctx = 0; + + if (ctx->pctx->pmeth->verifyctx) + vctx = 1; + else + vctx = 0; + if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) { + if (vctx) + r = ctx->pctx->pmeth->verifyctx(ctx->pctx, sig, siglen, ctx); + else + r = EVP_DigestFinal_ex(ctx, md, &mdlen); + } else { + EVP_MD_CTX *tmp_ctx = EVP_MD_CTX_new(); + if (tmp_ctx == NULL) + return -1; + if (!EVP_MD_CTX_copy_ex(tmp_ctx, ctx)) { + EVP_MD_CTX_free(tmp_ctx); + return -1; + } + if (vctx) + r = tmp_ctx->pctx->pmeth->verifyctx(tmp_ctx->pctx, + sig, siglen, tmp_ctx); + else + r = EVP_DigestFinal_ex(tmp_ctx, md, &mdlen); + EVP_MD_CTX_free(tmp_ctx); + } + if (vctx || !r) + return r; + return EVP_PKEY_verify(ctx->pctx, sig, siglen, md, mdlen); +} + +int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret, + size_t siglen, const unsigned char *tbs, size_t tbslen) +{ + if (ctx->pctx->pmeth->digestverify != NULL) + return ctx->pctx->pmeth->digestverify(ctx, sigret, siglen, tbs, tbslen); + if (EVP_DigestVerifyUpdate(ctx, tbs, tbslen) <= 0) + return -1; + return EVP_DigestVerifyFinal(ctx, sigret, siglen); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_wp.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_wp.c new file mode 100644 index 000000000..27e2b3c5c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/m_wp.c @@ -0,0 +1,54 @@ +/* + * Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" + +#ifndef OPENSSL_NO_WHIRLPOOL + +# include +# include +# include +# include +# include "internal/evp_int.h" + +static int init(EVP_MD_CTX *ctx) +{ + return WHIRLPOOL_Init(EVP_MD_CTX_md_data(ctx)); +} + +static int update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ + return WHIRLPOOL_Update(EVP_MD_CTX_md_data(ctx), data, count); +} + +static int final(EVP_MD_CTX *ctx, unsigned char *md) +{ + return WHIRLPOOL_Final(md, EVP_MD_CTX_md_data(ctx)); +} + +static const EVP_MD whirlpool_md = { + NID_whirlpool, + 0, + WHIRLPOOL_DIGEST_LENGTH, + 0, + init, + update, + final, + NULL, + NULL, + WHIRLPOOL_BBLOCK / 8, + sizeof(EVP_MD *) + sizeof(WHIRLPOOL_CTX), +}; + +const EVP_MD *EVP_whirlpool(void) +{ + return &whirlpool_md; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/names.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/names.c new file mode 100644 index 000000000..077c2a6c4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/names.c @@ -0,0 +1,180 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include "internal/objects.h" +#include +#include "internal/evp_int.h" + +int EVP_add_cipher(const EVP_CIPHER *c) +{ + int r; + + if (c == NULL) + return 0; + + r = OBJ_NAME_add(OBJ_nid2sn(c->nid), OBJ_NAME_TYPE_CIPHER_METH, + (const char *)c); + if (r == 0) + return 0; + r = OBJ_NAME_add(OBJ_nid2ln(c->nid), OBJ_NAME_TYPE_CIPHER_METH, + (const char *)c); + return r; +} + +int EVP_add_digest(const EVP_MD *md) +{ + int r; + const char *name; + + name = OBJ_nid2sn(md->type); + r = OBJ_NAME_add(name, OBJ_NAME_TYPE_MD_METH, (const char *)md); + if (r == 0) + return 0; + r = OBJ_NAME_add(OBJ_nid2ln(md->type), OBJ_NAME_TYPE_MD_METH, + (const char *)md); + if (r == 0) + return 0; + + if (md->pkey_type && md->type != md->pkey_type) { + r = OBJ_NAME_add(OBJ_nid2sn(md->pkey_type), + OBJ_NAME_TYPE_MD_METH | OBJ_NAME_ALIAS, name); + if (r == 0) + return 0; + r = OBJ_NAME_add(OBJ_nid2ln(md->pkey_type), + OBJ_NAME_TYPE_MD_METH | OBJ_NAME_ALIAS, name); + } + return r; +} + +const EVP_CIPHER *EVP_get_cipherbyname(const char *name) +{ + const EVP_CIPHER *cp; + + if (!OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS, NULL)) + return NULL; + + cp = (const EVP_CIPHER *)OBJ_NAME_get(name, OBJ_NAME_TYPE_CIPHER_METH); + return cp; +} + +const EVP_MD *EVP_get_digestbyname(const char *name) +{ + const EVP_MD *cp; + + if (!OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_DIGESTS, NULL)) + return NULL; + + cp = (const EVP_MD *)OBJ_NAME_get(name, OBJ_NAME_TYPE_MD_METH); + return cp; +} + +void evp_cleanup_int(void) +{ + OBJ_NAME_cleanup(OBJ_NAME_TYPE_CIPHER_METH); + OBJ_NAME_cleanup(OBJ_NAME_TYPE_MD_METH); + /* + * The above calls will only clean out the contents of the name hash + * table, but not the hash table itself. The following line does that + * part. -- Richard Levitte + */ + OBJ_NAME_cleanup(-1); + + EVP_PBE_cleanup(); + OBJ_sigid_free(); + + evp_app_cleanup_int(); +} + +struct doall_cipher { + void *arg; + void (*fn) (const EVP_CIPHER *ciph, + const char *from, const char *to, void *arg); +}; + +static void do_all_cipher_fn(const OBJ_NAME *nm, void *arg) +{ + struct doall_cipher *dc = arg; + if (nm->alias) + dc->fn(NULL, nm->name, nm->data, dc->arg); + else + dc->fn((const EVP_CIPHER *)nm->data, nm->name, NULL, dc->arg); +} + +void EVP_CIPHER_do_all(void (*fn) (const EVP_CIPHER *ciph, + const char *from, const char *to, void *x), + void *arg) +{ + struct doall_cipher dc; + + /* Ignore errors */ + OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS, NULL); + + dc.fn = fn; + dc.arg = arg; + OBJ_NAME_do_all(OBJ_NAME_TYPE_CIPHER_METH, do_all_cipher_fn, &dc); +} + +void EVP_CIPHER_do_all_sorted(void (*fn) (const EVP_CIPHER *ciph, + const char *from, const char *to, + void *x), void *arg) +{ + struct doall_cipher dc; + + /* Ignore errors */ + OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS, NULL); + + dc.fn = fn; + dc.arg = arg; + OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, do_all_cipher_fn, &dc); +} + +struct doall_md { + void *arg; + void (*fn) (const EVP_MD *ciph, + const char *from, const char *to, void *arg); +}; + +static void do_all_md_fn(const OBJ_NAME *nm, void *arg) +{ + struct doall_md *dc = arg; + if (nm->alias) + dc->fn(NULL, nm->name, nm->data, dc->arg); + else + dc->fn((const EVP_MD *)nm->data, nm->name, NULL, dc->arg); +} + +void EVP_MD_do_all(void (*fn) (const EVP_MD *md, + const char *from, const char *to, void *x), + void *arg) +{ + struct doall_md dc; + + /* Ignore errors */ + OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_DIGESTS, NULL); + + dc.fn = fn; + dc.arg = arg; + OBJ_NAME_do_all(OBJ_NAME_TYPE_MD_METH, do_all_md_fn, &dc); +} + +void EVP_MD_do_all_sorted(void (*fn) (const EVP_MD *md, + const char *from, const char *to, + void *x), void *arg) +{ + struct doall_md dc; + + OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_DIGESTS, NULL); + + dc.fn = fn; + dc.arg = arg; + OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH, do_all_md_fn, &dc); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/p5_crpt.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/p5_crpt.c new file mode 100644 index 000000000..7e55d0bfb --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/p5_crpt.c @@ -0,0 +1,103 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include +#include + +/* + * Doesn't do anything now: Builtin PBE algorithms in static table. + */ + +void PKCS5_PBE_add(void) +{ +} + +int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *cctx, const char *pass, int passlen, + ASN1_TYPE *param, const EVP_CIPHER *cipher, + const EVP_MD *md, int en_de) +{ + EVP_MD_CTX *ctx; + unsigned char md_tmp[EVP_MAX_MD_SIZE]; + unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH]; + int i; + PBEPARAM *pbe; + int saltlen, iter; + unsigned char *salt; + int mdsize; + int rv = 0; + + /* Extract useful info from parameter */ + if (param == NULL || param->type != V_ASN1_SEQUENCE || + param->value.sequence == NULL) { + EVPerr(EVP_F_PKCS5_PBE_KEYIVGEN, EVP_R_DECODE_ERROR); + return 0; + } + + pbe = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBEPARAM), param); + if (pbe == NULL) { + EVPerr(EVP_F_PKCS5_PBE_KEYIVGEN, EVP_R_DECODE_ERROR); + return 0; + } + + if (!pbe->iter) + iter = 1; + else + iter = ASN1_INTEGER_get(pbe->iter); + salt = pbe->salt->data; + saltlen = pbe->salt->length; + + if (!pass) + passlen = 0; + else if (passlen == -1) + passlen = strlen(pass); + + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) { + EVPerr(EVP_F_PKCS5_PBE_KEYIVGEN, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!EVP_DigestInit_ex(ctx, md, NULL)) + goto err; + if (!EVP_DigestUpdate(ctx, pass, passlen)) + goto err; + if (!EVP_DigestUpdate(ctx, salt, saltlen)) + goto err; + PBEPARAM_free(pbe); + if (!EVP_DigestFinal_ex(ctx, md_tmp, NULL)) + goto err; + mdsize = EVP_MD_size(md); + if (mdsize < 0) + return 0; + for (i = 1; i < iter; i++) { + if (!EVP_DigestInit_ex(ctx, md, NULL)) + goto err; + if (!EVP_DigestUpdate(ctx, md_tmp, mdsize)) + goto err; + if (!EVP_DigestFinal_ex(ctx, md_tmp, NULL)) + goto err; + } + OPENSSL_assert(EVP_CIPHER_key_length(cipher) <= (int)sizeof(md_tmp)); + memcpy(key, md_tmp, EVP_CIPHER_key_length(cipher)); + OPENSSL_assert(EVP_CIPHER_iv_length(cipher) <= 16); + memcpy(iv, md_tmp + (16 - EVP_CIPHER_iv_length(cipher)), + EVP_CIPHER_iv_length(cipher)); + if (!EVP_CipherInit_ex(cctx, cipher, NULL, key, iv, en_de)) + goto err; + OPENSSL_cleanse(md_tmp, EVP_MAX_MD_SIZE); + OPENSSL_cleanse(key, EVP_MAX_KEY_LENGTH); + OPENSSL_cleanse(iv, EVP_MAX_IV_LENGTH); + rv = 1; + err: + EVP_MD_CTX_free(ctx); + return rv; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/p5_crpt2.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/p5_crpt2.c new file mode 100644 index 000000000..e819eb9b4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/p5_crpt2.c @@ -0,0 +1,265 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +# include +# include +# include +# include "evp_locl.h" + +/* set this to print out info about the keygen algorithm */ +/* #define OPENSSL_DEBUG_PKCS5V2 */ + +# ifdef OPENSSL_DEBUG_PKCS5V2 +static void h__dump(const unsigned char *p, int len); +# endif + +/* + * This is an implementation of PKCS#5 v2.0 password based encryption key + * derivation function PBKDF2. SHA1 version verified against test vectors + * posted by Peter Gutmann to the PKCS-TNG mailing list. + */ + +int PKCS5_PBKDF2_HMAC(const char *pass, int passlen, + const unsigned char *salt, int saltlen, int iter, + const EVP_MD *digest, int keylen, unsigned char *out) +{ + const char *empty = ""; + unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4]; + int cplen, j, k, tkeylen, mdlen; + unsigned long i = 1; + HMAC_CTX *hctx_tpl = NULL, *hctx = NULL; + + mdlen = EVP_MD_size(digest); + if (mdlen < 0) + return 0; + + hctx_tpl = HMAC_CTX_new(); + if (hctx_tpl == NULL) + return 0; + p = out; + tkeylen = keylen; + if (pass == NULL) { + pass = empty; + passlen = 0; + } else if (passlen == -1) { + passlen = strlen(pass); + } + if (!HMAC_Init_ex(hctx_tpl, pass, passlen, digest, NULL)) { + HMAC_CTX_free(hctx_tpl); + return 0; + } + hctx = HMAC_CTX_new(); + if (hctx == NULL) { + HMAC_CTX_free(hctx_tpl); + return 0; + } + while (tkeylen) { + if (tkeylen > mdlen) + cplen = mdlen; + else + cplen = tkeylen; + /* + * We are unlikely to ever use more than 256 blocks (5120 bits!) but + * just in case... + */ + itmp[0] = (unsigned char)((i >> 24) & 0xff); + itmp[1] = (unsigned char)((i >> 16) & 0xff); + itmp[2] = (unsigned char)((i >> 8) & 0xff); + itmp[3] = (unsigned char)(i & 0xff); + if (!HMAC_CTX_copy(hctx, hctx_tpl)) { + HMAC_CTX_free(hctx); + HMAC_CTX_free(hctx_tpl); + return 0; + } + if (!HMAC_Update(hctx, salt, saltlen) + || !HMAC_Update(hctx, itmp, 4) + || !HMAC_Final(hctx, digtmp, NULL)) { + HMAC_CTX_free(hctx); + HMAC_CTX_free(hctx_tpl); + return 0; + } + memcpy(p, digtmp, cplen); + for (j = 1; j < iter; j++) { + if (!HMAC_CTX_copy(hctx, hctx_tpl)) { + HMAC_CTX_free(hctx); + HMAC_CTX_free(hctx_tpl); + return 0; + } + if (!HMAC_Update(hctx, digtmp, mdlen) + || !HMAC_Final(hctx, digtmp, NULL)) { + HMAC_CTX_free(hctx); + HMAC_CTX_free(hctx_tpl); + return 0; + } + for (k = 0; k < cplen; k++) + p[k] ^= digtmp[k]; + } + tkeylen -= cplen; + i++; + p += cplen; + } + HMAC_CTX_free(hctx); + HMAC_CTX_free(hctx_tpl); +# ifdef OPENSSL_DEBUG_PKCS5V2 + fprintf(stderr, "Password:\n"); + h__dump(pass, passlen); + fprintf(stderr, "Salt:\n"); + h__dump(salt, saltlen); + fprintf(stderr, "Iteration count %d\n", iter); + fprintf(stderr, "Key:\n"); + h__dump(out, keylen); +# endif + return 1; +} + +int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, + const unsigned char *salt, int saltlen, int iter, + int keylen, unsigned char *out) +{ + return PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, EVP_sha1(), + keylen, out); +} + +/* + * Now the key derivation function itself. This is a bit evil because it has + * to check the ASN1 parameters are valid: and there are quite a few of + * them... + */ + +int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, + ASN1_TYPE *param, const EVP_CIPHER *c, + const EVP_MD *md, int en_de) +{ + PBE2PARAM *pbe2 = NULL; + const EVP_CIPHER *cipher; + EVP_PBE_KEYGEN *kdf; + + int rv = 0; + + pbe2 = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBE2PARAM), param); + if (pbe2 == NULL) { + EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, EVP_R_DECODE_ERROR); + goto err; + } + + /* See if we recognise the key derivation function */ + if (!EVP_PBE_find(EVP_PBE_TYPE_KDF, OBJ_obj2nid(pbe2->keyfunc->algorithm), + NULL, NULL, &kdf)) { + EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, + EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION); + goto err; + } + + /* + * lets see if we recognise the encryption algorithm. + */ + + cipher = EVP_get_cipherbyobj(pbe2->encryption->algorithm); + + if (!cipher) { + EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, EVP_R_UNSUPPORTED_CIPHER); + goto err; + } + + /* Fixup cipher based on AlgorithmIdentifier */ + if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, en_de)) + goto err; + if (EVP_CIPHER_asn1_to_param(ctx, pbe2->encryption->parameter) < 0) { + EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, EVP_R_CIPHER_PARAMETER_ERROR); + goto err; + } + rv = kdf(ctx, pass, passlen, pbe2->keyfunc->parameter, NULL, NULL, en_de); + err: + PBE2PARAM_free(pbe2); + return rv; +} + +int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, + int passlen, ASN1_TYPE *param, + const EVP_CIPHER *c, const EVP_MD *md, int en_de) +{ + unsigned char *salt, key[EVP_MAX_KEY_LENGTH]; + int saltlen, iter; + int rv = 0; + unsigned int keylen = 0; + int prf_nid, hmac_md_nid; + PBKDF2PARAM *kdf = NULL; + const EVP_MD *prfmd; + + if (EVP_CIPHER_CTX_cipher(ctx) == NULL) { + EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_NO_CIPHER_SET); + goto err; + } + keylen = EVP_CIPHER_CTX_key_length(ctx); + OPENSSL_assert(keylen <= sizeof(key)); + + /* Decode parameter */ + + kdf = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBKDF2PARAM), param); + + if (kdf == NULL) { + EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_DECODE_ERROR); + goto err; + } + + keylen = EVP_CIPHER_CTX_key_length(ctx); + + /* Now check the parameters of the kdf */ + + if (kdf->keylength && (ASN1_INTEGER_get(kdf->keylength) != (int)keylen)) { + EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_KEYLENGTH); + goto err; + } + + if (kdf->prf) + prf_nid = OBJ_obj2nid(kdf->prf->algorithm); + else + prf_nid = NID_hmacWithSHA1; + + if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, prf_nid, NULL, &hmac_md_nid, 0)) { + EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_PRF); + goto err; + } + + prfmd = EVP_get_digestbynid(hmac_md_nid); + if (prfmd == NULL) { + EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_PRF); + goto err; + } + + if (kdf->salt->type != V_ASN1_OCTET_STRING) { + EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_SALT_TYPE); + goto err; + } + + /* it seems that its all OK */ + salt = kdf->salt->value.octet_string->data; + saltlen = kdf->salt->value.octet_string->length; + iter = ASN1_INTEGER_get(kdf->iter); + if (!PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, prfmd, + keylen, key)) + goto err; + rv = EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, en_de); + err: + OPENSSL_cleanse(key, keylen); + PBKDF2PARAM_free(kdf); + return rv; +} + +# ifdef OPENSSL_DEBUG_PKCS5V2 +static void h__dump(const unsigned char *p, int len) +{ + for (; len--; p++) + fprintf(stderr, "%02X ", *p); + fprintf(stderr, "\n"); +} +# endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/p_dec.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/p_dec.c new file mode 100644 index 000000000..a150a26e0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/p_dec.c @@ -0,0 +1,36 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include + +int EVP_PKEY_decrypt_old(unsigned char *key, const unsigned char *ek, int ekl, + EVP_PKEY *priv) +{ + int ret = -1; + +#ifndef OPENSSL_NO_RSA + if (EVP_PKEY_id(priv) != EVP_PKEY_RSA) { +#endif + EVPerr(EVP_F_EVP_PKEY_DECRYPT_OLD, EVP_R_PUBLIC_KEY_NOT_RSA); +#ifndef OPENSSL_NO_RSA + goto err; + } + + ret = + RSA_private_decrypt(ekl, ek, key, EVP_PKEY_get0_RSA(priv), + RSA_PKCS1_PADDING); + err: +#endif + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/p_enc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/p_enc.c new file mode 100644 index 000000000..04d67cb50 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/p_enc.c @@ -0,0 +1,35 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include + +int EVP_PKEY_encrypt_old(unsigned char *ek, const unsigned char *key, + int key_len, EVP_PKEY *pubk) +{ + int ret = 0; + +#ifndef OPENSSL_NO_RSA + if (EVP_PKEY_id(pubk) != EVP_PKEY_RSA) { +#endif + EVPerr(EVP_F_EVP_PKEY_ENCRYPT_OLD, EVP_R_PUBLIC_KEY_NOT_RSA); +#ifndef OPENSSL_NO_RSA + goto err; + } + ret = + RSA_public_encrypt(key_len, key, ek, EVP_PKEY_get0_RSA(pubk), + RSA_PKCS1_PADDING); + err: +#endif + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/p_lib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/p_lib.c new file mode 100644 index 000000000..148df90f8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/p_lib.c @@ -0,0 +1,686 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include "internal/refcount.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "internal/asn1_int.h" +#include "internal/evp_int.h" + +static void EVP_PKEY_free_it(EVP_PKEY *x); + +int EVP_PKEY_bits(const EVP_PKEY *pkey) +{ + if (pkey && pkey->ameth && pkey->ameth->pkey_bits) + return pkey->ameth->pkey_bits(pkey); + return 0; +} + +int EVP_PKEY_security_bits(const EVP_PKEY *pkey) +{ + if (pkey == NULL) + return 0; + if (!pkey->ameth || !pkey->ameth->pkey_security_bits) + return -2; + return pkey->ameth->pkey_security_bits(pkey); +} + +int EVP_PKEY_size(const EVP_PKEY *pkey) +{ + if (pkey && pkey->ameth && pkey->ameth->pkey_size) + return pkey->ameth->pkey_size(pkey); + return 0; +} + +int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode) +{ +#ifndef OPENSSL_NO_DSA + if (pkey->type == EVP_PKEY_DSA) { + int ret = pkey->save_parameters; + + if (mode >= 0) + pkey->save_parameters = mode; + return ret; + } +#endif +#ifndef OPENSSL_NO_EC + if (pkey->type == EVP_PKEY_EC) { + int ret = pkey->save_parameters; + + if (mode >= 0) + pkey->save_parameters = mode; + return ret; + } +#endif + return 0; +} + +int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) +{ + if (to->type == EVP_PKEY_NONE) { + if (EVP_PKEY_set_type(to, from->type) == 0) + return 0; + } else if (to->type != from->type) { + EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS, EVP_R_DIFFERENT_KEY_TYPES); + goto err; + } + + if (EVP_PKEY_missing_parameters(from)) { + EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS, EVP_R_MISSING_PARAMETERS); + goto err; + } + + if (!EVP_PKEY_missing_parameters(to)) { + if (EVP_PKEY_cmp_parameters(to, from) == 1) + return 1; + EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS, EVP_R_DIFFERENT_PARAMETERS); + return 0; + } + + if (from->ameth && from->ameth->param_copy) + return from->ameth->param_copy(to, from); + err: + return 0; +} + +int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey) +{ + if (pkey->ameth && pkey->ameth->param_missing) + return pkey->ameth->param_missing(pkey); + return 0; +} + +int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) +{ + if (a->type != b->type) + return -1; + if (a->ameth && a->ameth->param_cmp) + return a->ameth->param_cmp(a, b); + return -2; +} + +int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b) +{ + if (a->type != b->type) + return -1; + + if (a->ameth) { + int ret; + /* Compare parameters if the algorithm has them */ + if (a->ameth->param_cmp) { + ret = a->ameth->param_cmp(a, b); + if (ret <= 0) + return ret; + } + + if (a->ameth->pub_cmp) + return a->ameth->pub_cmp(a, b); + } + + return -2; +} + +EVP_PKEY *EVP_PKEY_new(void) +{ + EVP_PKEY *ret = OPENSSL_zalloc(sizeof(*ret)); + + if (ret == NULL) { + EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + ret->type = EVP_PKEY_NONE; + ret->save_type = EVP_PKEY_NONE; + ret->references = 1; + ret->save_parameters = 1; + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) { + EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ret); + return NULL; + } + return ret; +} + +int EVP_PKEY_up_ref(EVP_PKEY *pkey) +{ + int i; + + if (CRYPTO_UP_REF(&pkey->references, &i, pkey->lock) <= 0) + return 0; + + REF_PRINT_COUNT("EVP_PKEY", pkey); + REF_ASSERT_ISNT(i < 2); + return ((i > 1) ? 1 : 0); +} + +/* + * Setup a public key ASN1 method and ENGINE from a NID or a string. If pkey + * is NULL just return 1 or 0 if the algorithm exists. + */ + +static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str, + int len) +{ + const EVP_PKEY_ASN1_METHOD *ameth; + ENGINE **eptr = (e == NULL) ? &e : NULL; + + if (pkey) { + if (pkey->pkey.ptr) + EVP_PKEY_free_it(pkey); + /* + * If key type matches and a method exists then this lookup has + * succeeded once so just indicate success. + */ + if ((type == pkey->save_type) && pkey->ameth) + return 1; +#ifndef OPENSSL_NO_ENGINE + /* If we have ENGINEs release them */ + ENGINE_finish(pkey->engine); + pkey->engine = NULL; + ENGINE_finish(pkey->pmeth_engine); + pkey->pmeth_engine = NULL; +#endif + } + if (str) + ameth = EVP_PKEY_asn1_find_str(eptr, str, len); + else + ameth = EVP_PKEY_asn1_find(eptr, type); +#ifndef OPENSSL_NO_ENGINE + if (pkey == NULL && eptr != NULL) + ENGINE_finish(e); +#endif + if (ameth == NULL) { + EVPerr(EVP_F_PKEY_SET_TYPE, EVP_R_UNSUPPORTED_ALGORITHM); + return 0; + } + if (pkey) { + pkey->ameth = ameth; + pkey->engine = e; + + pkey->type = pkey->ameth->pkey_id; + pkey->save_type = type; + } + return 1; +} + +EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e, + const unsigned char *priv, + size_t len) +{ + EVP_PKEY *ret = EVP_PKEY_new(); + + if (ret == NULL + || !pkey_set_type(ret, e, type, NULL, -1)) { + /* EVPerr already called */ + goto err; + } + + if (ret->ameth->set_priv_key == NULL) { + EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PRIVATE_KEY, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + goto err; + } + + if (!ret->ameth->set_priv_key(ret, priv, len)) { + EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PRIVATE_KEY, EVP_R_KEY_SETUP_FAILED); + goto err; + } + + return ret; + + err: + EVP_PKEY_free(ret); + return NULL; +} + +EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *e, + const unsigned char *pub, + size_t len) +{ + EVP_PKEY *ret = EVP_PKEY_new(); + + if (ret == NULL + || !pkey_set_type(ret, e, type, NULL, -1)) { + /* EVPerr already called */ + goto err; + } + + if (ret->ameth->set_pub_key == NULL) { + EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PUBLIC_KEY, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + goto err; + } + + if (!ret->ameth->set_pub_key(ret, pub, len)) { + EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PUBLIC_KEY, EVP_R_KEY_SETUP_FAILED); + goto err; + } + + return ret; + + err: + EVP_PKEY_free(ret); + return NULL; +} + +int EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey, unsigned char *priv, + size_t *len) +{ + if (pkey->ameth->get_priv_key == NULL) { + EVPerr(EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + + if (!pkey->ameth->get_priv_key(pkey, priv, len)) { + EVPerr(EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY, EVP_R_GET_RAW_KEY_FAILED); + return 0; + } + + return 1; +} + +int EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, unsigned char *pub, + size_t *len) +{ + if (pkey->ameth->get_pub_key == NULL) { + EVPerr(EVP_F_EVP_PKEY_GET_RAW_PUBLIC_KEY, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + + if (!pkey->ameth->get_pub_key(pkey, pub, len)) { + EVPerr(EVP_F_EVP_PKEY_GET_RAW_PUBLIC_KEY, EVP_R_GET_RAW_KEY_FAILED); + return 0; + } + + return 1; +} + +EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv, + size_t len, const EVP_CIPHER *cipher) +{ +#ifndef OPENSSL_NO_CMAC + EVP_PKEY *ret = EVP_PKEY_new(); + CMAC_CTX *cmctx = CMAC_CTX_new(); + + if (ret == NULL + || cmctx == NULL + || !pkey_set_type(ret, e, EVP_PKEY_CMAC, NULL, -1)) { + /* EVPerr already called */ + goto err; + } + + if (!CMAC_Init(cmctx, priv, len, cipher, e)) { + EVPerr(EVP_F_EVP_PKEY_NEW_CMAC_KEY, EVP_R_KEY_SETUP_FAILED); + goto err; + } + + ret->pkey.ptr = cmctx; + return ret; + + err: + EVP_PKEY_free(ret); + CMAC_CTX_free(cmctx); + return NULL; +#else + EVPerr(EVP_F_EVP_PKEY_NEW_CMAC_KEY, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return NULL; +#endif +} + +int EVP_PKEY_set_type(EVP_PKEY *pkey, int type) +{ + return pkey_set_type(pkey, NULL, type, NULL, -1); +} + +int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len) +{ + return pkey_set_type(pkey, NULL, EVP_PKEY_NONE, str, len); +} + +int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type) +{ + if (pkey->type == type) { + return 1; /* it already is that type */ + } + + /* + * The application is requesting to alias this to a different pkey type, + * but not one that resolves to the base type. + */ + if (EVP_PKEY_type(type) != EVP_PKEY_base_id(pkey)) { + EVPerr(EVP_F_EVP_PKEY_SET_ALIAS_TYPE, EVP_R_UNSUPPORTED_ALGORITHM); + return 0; + } + + pkey->type = type; + return 1; +} + +#ifndef OPENSSL_NO_ENGINE +int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *e) +{ + if (e != NULL) { + if (!ENGINE_init(e)) { + EVPerr(EVP_F_EVP_PKEY_SET1_ENGINE, ERR_R_ENGINE_LIB); + return 0; + } + if (ENGINE_get_pkey_meth(e, pkey->type) == NULL) { + ENGINE_finish(e); + EVPerr(EVP_F_EVP_PKEY_SET1_ENGINE, EVP_R_UNSUPPORTED_ALGORITHM); + return 0; + } + } + ENGINE_finish(pkey->pmeth_engine); + pkey->pmeth_engine = e; + return 1; +} +#endif +int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key) +{ + if (pkey == NULL || !EVP_PKEY_set_type(pkey, type)) + return 0; + pkey->pkey.ptr = key; + return (key != NULL); +} + +void *EVP_PKEY_get0(const EVP_PKEY *pkey) +{ + return pkey->pkey.ptr; +} + +const unsigned char *EVP_PKEY_get0_hmac(const EVP_PKEY *pkey, size_t *len) +{ + ASN1_OCTET_STRING *os = NULL; + if (pkey->type != EVP_PKEY_HMAC) { + EVPerr(EVP_F_EVP_PKEY_GET0_HMAC, EVP_R_EXPECTING_AN_HMAC_KEY); + return NULL; + } + os = EVP_PKEY_get0(pkey); + *len = os->length; + return os->data; +} + +#ifndef OPENSSL_NO_POLY1305 +const unsigned char *EVP_PKEY_get0_poly1305(const EVP_PKEY *pkey, size_t *len) +{ + ASN1_OCTET_STRING *os = NULL; + if (pkey->type != EVP_PKEY_POLY1305) { + EVPerr(EVP_F_EVP_PKEY_GET0_POLY1305, EVP_R_EXPECTING_A_POLY1305_KEY); + return NULL; + } + os = EVP_PKEY_get0(pkey); + *len = os->length; + return os->data; +} +#endif + +#ifndef OPENSSL_NO_SIPHASH +const unsigned char *EVP_PKEY_get0_siphash(const EVP_PKEY *pkey, size_t *len) +{ + ASN1_OCTET_STRING *os = NULL; + + if (pkey->type != EVP_PKEY_SIPHASH) { + EVPerr(EVP_F_EVP_PKEY_GET0_SIPHASH, EVP_R_EXPECTING_A_SIPHASH_KEY); + return NULL; + } + os = EVP_PKEY_get0(pkey); + *len = os->length; + return os->data; +} +#endif + +#ifndef OPENSSL_NO_RSA +int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key) +{ + int ret = EVP_PKEY_assign_RSA(pkey, key); + if (ret) + RSA_up_ref(key); + return ret; +} + +RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey) +{ + if (pkey->type != EVP_PKEY_RSA) { + EVPerr(EVP_F_EVP_PKEY_GET0_RSA, EVP_R_EXPECTING_AN_RSA_KEY); + return NULL; + } + return pkey->pkey.rsa; +} + +RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey) +{ + RSA *ret = EVP_PKEY_get0_RSA(pkey); + if (ret != NULL) + RSA_up_ref(ret); + return ret; +} +#endif + +#ifndef OPENSSL_NO_DSA +int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key) +{ + int ret = EVP_PKEY_assign_DSA(pkey, key); + if (ret) + DSA_up_ref(key); + return ret; +} + +DSA *EVP_PKEY_get0_DSA(EVP_PKEY *pkey) +{ + if (pkey->type != EVP_PKEY_DSA) { + EVPerr(EVP_F_EVP_PKEY_GET0_DSA, EVP_R_EXPECTING_A_DSA_KEY); + return NULL; + } + return pkey->pkey.dsa; +} + +DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey) +{ + DSA *ret = EVP_PKEY_get0_DSA(pkey); + if (ret != NULL) + DSA_up_ref(ret); + return ret; +} +#endif + +#ifndef OPENSSL_NO_EC + +int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) +{ + int ret = EVP_PKEY_assign_EC_KEY(pkey, key); + if (ret) + EC_KEY_up_ref(key); + return ret; +} + +EC_KEY *EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) +{ + if (pkey->type != EVP_PKEY_EC) { + EVPerr(EVP_F_EVP_PKEY_GET0_EC_KEY, EVP_R_EXPECTING_A_EC_KEY); + return NULL; + } + return pkey->pkey.ec; +} + +EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey) +{ + EC_KEY *ret = EVP_PKEY_get0_EC_KEY(pkey); + if (ret != NULL) + EC_KEY_up_ref(ret); + return ret; +} +#endif + +#ifndef OPENSSL_NO_DH + +int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key) +{ + int ret = EVP_PKEY_assign_DH(pkey, key); + if (ret) + DH_up_ref(key); + return ret; +} + +DH *EVP_PKEY_get0_DH(EVP_PKEY *pkey) +{ + if (pkey->type != EVP_PKEY_DH && pkey->type != EVP_PKEY_DHX) { + EVPerr(EVP_F_EVP_PKEY_GET0_DH, EVP_R_EXPECTING_A_DH_KEY); + return NULL; + } + return pkey->pkey.dh; +} + +DH *EVP_PKEY_get1_DH(EVP_PKEY *pkey) +{ + DH *ret = EVP_PKEY_get0_DH(pkey); + if (ret != NULL) + DH_up_ref(ret); + return ret; +} +#endif + +int EVP_PKEY_type(int type) +{ + int ret; + const EVP_PKEY_ASN1_METHOD *ameth; + ENGINE *e; + ameth = EVP_PKEY_asn1_find(&e, type); + if (ameth) + ret = ameth->pkey_id; + else + ret = NID_undef; +#ifndef OPENSSL_NO_ENGINE + ENGINE_finish(e); +#endif + return ret; +} + +int EVP_PKEY_id(const EVP_PKEY *pkey) +{ + return pkey->type; +} + +int EVP_PKEY_base_id(const EVP_PKEY *pkey) +{ + return EVP_PKEY_type(pkey->type); +} + +void EVP_PKEY_free(EVP_PKEY *x) +{ + int i; + + if (x == NULL) + return; + + CRYPTO_DOWN_REF(&x->references, &i, x->lock); + REF_PRINT_COUNT("EVP_PKEY", x); + if (i > 0) + return; + REF_ASSERT_ISNT(i < 0); + EVP_PKEY_free_it(x); + CRYPTO_THREAD_lock_free(x->lock); + sk_X509_ATTRIBUTE_pop_free(x->attributes, X509_ATTRIBUTE_free); + OPENSSL_free(x); +} + +static void EVP_PKEY_free_it(EVP_PKEY *x) +{ + /* internal function; x is never NULL */ + if (x->ameth && x->ameth->pkey_free) { + x->ameth->pkey_free(x); + x->pkey.ptr = NULL; + } +#ifndef OPENSSL_NO_ENGINE + ENGINE_finish(x->engine); + x->engine = NULL; + ENGINE_finish(x->pmeth_engine); + x->pmeth_engine = NULL; +#endif +} + +static int unsup_alg(BIO *out, const EVP_PKEY *pkey, int indent, + const char *kstr) +{ + BIO_indent(out, indent, 128); + BIO_printf(out, "%s algorithm \"%s\" unsupported\n", + kstr, OBJ_nid2ln(pkey->type)); + return 1; +} + +int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey, + int indent, ASN1_PCTX *pctx) +{ + if (pkey->ameth && pkey->ameth->pub_print) + return pkey->ameth->pub_print(out, pkey, indent, pctx); + + return unsup_alg(out, pkey, indent, "Public Key"); +} + +int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey, + int indent, ASN1_PCTX *pctx) +{ + if (pkey->ameth && pkey->ameth->priv_print) + return pkey->ameth->priv_print(out, pkey, indent, pctx); + + return unsup_alg(out, pkey, indent, "Private Key"); +} + +int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, + int indent, ASN1_PCTX *pctx) +{ + if (pkey->ameth && pkey->ameth->param_print) + return pkey->ameth->param_print(out, pkey, indent, pctx); + return unsup_alg(out, pkey, indent, "Parameters"); +} + +static int evp_pkey_asn1_ctrl(EVP_PKEY *pkey, int op, int arg1, void *arg2) +{ + if (pkey->ameth == NULL || pkey->ameth->pkey_ctrl == NULL) + return -2; + return pkey->ameth->pkey_ctrl(pkey, op, arg1, arg2); +} + +int EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid) +{ + return evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_DEFAULT_MD_NID, 0, pnid); +} + +int EVP_PKEY_set1_tls_encodedpoint(EVP_PKEY *pkey, + const unsigned char *pt, size_t ptlen) +{ + if (ptlen > INT_MAX) + return 0; + if (evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_SET1_TLS_ENCPT, ptlen, + (void *)pt) <= 0) + return 0; + return 1; +} + +size_t EVP_PKEY_get1_tls_encodedpoint(EVP_PKEY *pkey, unsigned char **ppt) +{ + int rv; + rv = evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_GET1_TLS_ENCPT, 0, ppt); + if (rv <= 0) + return 0; + return rv; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/p_open.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/p_open.c new file mode 100644 index 000000000..f2976f8a9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/p_open.c @@ -0,0 +1,73 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#ifdef OPENSSL_NO_RSA +NON_EMPTY_TRANSLATION_UNIT +#else + +# include +# include +# include +# include +# include + +int EVP_OpenInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, + const unsigned char *ek, int ekl, const unsigned char *iv, + EVP_PKEY *priv) +{ + unsigned char *key = NULL; + int i, size = 0, ret = 0; + + if (type) { + EVP_CIPHER_CTX_reset(ctx); + if (!EVP_DecryptInit_ex(ctx, type, NULL, NULL, NULL)) + return 0; + } + + if (!priv) + return 1; + + if (EVP_PKEY_id(priv) != EVP_PKEY_RSA) { + EVPerr(EVP_F_EVP_OPENINIT, EVP_R_PUBLIC_KEY_NOT_RSA); + goto err; + } + + size = EVP_PKEY_size(priv); + key = OPENSSL_malloc(size + 2); + if (key == NULL) { + /* ERROR */ + EVPerr(EVP_F_EVP_OPENINIT, ERR_R_MALLOC_FAILURE); + goto err; + } + + i = EVP_PKEY_decrypt_old(key, ek, ekl, priv); + if ((i <= 0) || !EVP_CIPHER_CTX_set_key_length(ctx, i)) { + /* ERROR */ + goto err; + } + if (!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) + goto err; + + ret = 1; + err: + OPENSSL_clear_free(key, size); + return ret; +} + +int EVP_OpenFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) +{ + int i; + + i = EVP_DecryptFinal_ex(ctx, out, outl); + if (i) + i = EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, NULL); + return i; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/p_seal.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/p_seal.c new file mode 100644 index 000000000..e851d7ab8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/p_seal.c @@ -0,0 +1,65 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include + +int EVP_SealInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, + unsigned char **ek, int *ekl, unsigned char *iv, + EVP_PKEY **pubk, int npubk) +{ + unsigned char key[EVP_MAX_KEY_LENGTH]; + int i; + int rv = 0; + + if (type) { + EVP_CIPHER_CTX_reset(ctx); + if (!EVP_EncryptInit_ex(ctx, type, NULL, NULL, NULL)) + return 0; + } + if ((npubk <= 0) || !pubk) + return 1; + if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0) + return 0; + + if (EVP_CIPHER_CTX_iv_length(ctx) + && RAND_bytes(iv, EVP_CIPHER_CTX_iv_length(ctx)) <= 0) + goto err; + + if (!EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) + goto err; + + for (i = 0; i < npubk; i++) { + ekl[i] = + EVP_PKEY_encrypt_old(ek[i], key, EVP_CIPHER_CTX_key_length(ctx), + pubk[i]); + if (ekl[i] <= 0) { + rv = -1; + goto err; + } + } + rv = npubk; +err: + OPENSSL_cleanse(key, sizeof(key)); + return rv; +} + +int EVP_SealFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) +{ + int i; + i = EVP_EncryptFinal_ex(ctx, out, outl); + if (i) + i = EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, NULL); + return i; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/p_sign.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/p_sign.c new file mode 100644 index 000000000..6cb442e4f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/p_sign.c @@ -0,0 +1,61 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include "internal/evp_int.h" + +int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, + unsigned int *siglen, EVP_PKEY *pkey) +{ + unsigned char m[EVP_MAX_MD_SIZE]; + unsigned int m_len = 0; + int i = 0; + size_t sltmp; + EVP_PKEY_CTX *pkctx = NULL; + + *siglen = 0; + if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_FINALISE)) { + if (!EVP_DigestFinal_ex(ctx, m, &m_len)) + goto err; + } else { + int rv = 0; + EVP_MD_CTX *tmp_ctx = EVP_MD_CTX_new(); + if (tmp_ctx == NULL) { + EVPerr(EVP_F_EVP_SIGNFINAL, ERR_R_MALLOC_FAILURE); + return 0; + } + rv = EVP_MD_CTX_copy_ex(tmp_ctx, ctx); + if (rv) + rv = EVP_DigestFinal_ex(tmp_ctx, m, &m_len); + EVP_MD_CTX_free(tmp_ctx); + if (!rv) + return 0; + } + + sltmp = (size_t)EVP_PKEY_size(pkey); + i = 0; + pkctx = EVP_PKEY_CTX_new(pkey, NULL); + if (pkctx == NULL) + goto err; + if (EVP_PKEY_sign_init(pkctx) <= 0) + goto err; + if (EVP_PKEY_CTX_set_signature_md(pkctx, EVP_MD_CTX_md(ctx)) <= 0) + goto err; + if (EVP_PKEY_sign(pkctx, sigret, &sltmp, m, m_len) <= 0) + goto err; + *siglen = sltmp; + i = 1; + err: + EVP_PKEY_CTX_free(pkctx); + return i; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/p_verify.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/p_verify.c new file mode 100644 index 000000000..6e8c565df --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/p_verify.c @@ -0,0 +1,55 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include "internal/evp_int.h" + +int EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf, + unsigned int siglen, EVP_PKEY *pkey) +{ + unsigned char m[EVP_MAX_MD_SIZE]; + unsigned int m_len = 0; + int i = 0; + EVP_PKEY_CTX *pkctx = NULL; + + if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_FINALISE)) { + if (!EVP_DigestFinal_ex(ctx, m, &m_len)) + goto err; + } else { + int rv = 0; + EVP_MD_CTX *tmp_ctx = EVP_MD_CTX_new(); + if (tmp_ctx == NULL) { + EVPerr(EVP_F_EVP_VERIFYFINAL, ERR_R_MALLOC_FAILURE); + return 0; + } + rv = EVP_MD_CTX_copy_ex(tmp_ctx, ctx); + if (rv) + rv = EVP_DigestFinal_ex(tmp_ctx, m, &m_len); + EVP_MD_CTX_free(tmp_ctx); + if (!rv) + return 0; + } + + i = -1; + pkctx = EVP_PKEY_CTX_new(pkey, NULL); + if (pkctx == NULL) + goto err; + if (EVP_PKEY_verify_init(pkctx) <= 0) + goto err; + if (EVP_PKEY_CTX_set_signature_md(pkctx, EVP_MD_CTX_md(ctx)) <= 0) + goto err; + i = EVP_PKEY_verify(pkctx, sigbuf, siglen, m, m_len); + err: + EVP_PKEY_CTX_free(pkctx); + return i; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/pbe_scrypt.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/pbe_scrypt.c new file mode 100644 index 000000000..57da82f3f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/pbe_scrypt.c @@ -0,0 +1,266 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include "internal/numbers.h" + +#ifndef OPENSSL_NO_SCRYPT + +#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b)))) +static void salsa208_word_specification(uint32_t inout[16]) +{ + int i; + uint32_t x[16]; + memcpy(x, inout, sizeof(x)); + for (i = 8; i > 0; i -= 2) { + x[4] ^= R(x[0] + x[12], 7); + x[8] ^= R(x[4] + x[0], 9); + x[12] ^= R(x[8] + x[4], 13); + x[0] ^= R(x[12] + x[8], 18); + x[9] ^= R(x[5] + x[1], 7); + x[13] ^= R(x[9] + x[5], 9); + x[1] ^= R(x[13] + x[9], 13); + x[5] ^= R(x[1] + x[13], 18); + x[14] ^= R(x[10] + x[6], 7); + x[2] ^= R(x[14] + x[10], 9); + x[6] ^= R(x[2] + x[14], 13); + x[10] ^= R(x[6] + x[2], 18); + x[3] ^= R(x[15] + x[11], 7); + x[7] ^= R(x[3] + x[15], 9); + x[11] ^= R(x[7] + x[3], 13); + x[15] ^= R(x[11] + x[7], 18); + x[1] ^= R(x[0] + x[3], 7); + x[2] ^= R(x[1] + x[0], 9); + x[3] ^= R(x[2] + x[1], 13); + x[0] ^= R(x[3] + x[2], 18); + x[6] ^= R(x[5] + x[4], 7); + x[7] ^= R(x[6] + x[5], 9); + x[4] ^= R(x[7] + x[6], 13); + x[5] ^= R(x[4] + x[7], 18); + x[11] ^= R(x[10] + x[9], 7); + x[8] ^= R(x[11] + x[10], 9); + x[9] ^= R(x[8] + x[11], 13); + x[10] ^= R(x[9] + x[8], 18); + x[12] ^= R(x[15] + x[14], 7); + x[13] ^= R(x[12] + x[15], 9); + x[14] ^= R(x[13] + x[12], 13); + x[15] ^= R(x[14] + x[13], 18); + } + for (i = 0; i < 16; ++i) + inout[i] += x[i]; + OPENSSL_cleanse(x, sizeof(x)); +} + +static void scryptBlockMix(uint32_t *B_, uint32_t *B, uint64_t r) +{ + uint64_t i, j; + uint32_t X[16], *pB; + + memcpy(X, B + (r * 2 - 1) * 16, sizeof(X)); + pB = B; + for (i = 0; i < r * 2; i++) { + for (j = 0; j < 16; j++) + X[j] ^= *pB++; + salsa208_word_specification(X); + memcpy(B_ + (i / 2 + (i & 1) * r) * 16, X, sizeof(X)); + } + OPENSSL_cleanse(X, sizeof(X)); +} + +static void scryptROMix(unsigned char *B, uint64_t r, uint64_t N, + uint32_t *X, uint32_t *T, uint32_t *V) +{ + unsigned char *pB; + uint32_t *pV; + uint64_t i, k; + + /* Convert from little endian input */ + for (pV = V, i = 0, pB = B; i < 32 * r; i++, pV++) { + *pV = *pB++; + *pV |= *pB++ << 8; + *pV |= *pB++ << 16; + *pV |= (uint32_t)*pB++ << 24; + } + + for (i = 1; i < N; i++, pV += 32 * r) + scryptBlockMix(pV, pV - 32 * r, r); + + scryptBlockMix(X, V + (N - 1) * 32 * r, r); + + for (i = 0; i < N; i++) { + uint32_t j; + j = X[16 * (2 * r - 1)] % N; + pV = V + 32 * r * j; + for (k = 0; k < 32 * r; k++) + T[k] = X[k] ^ *pV++; + scryptBlockMix(X, T, r); + } + /* Convert output to little endian */ + for (i = 0, pB = B; i < 32 * r; i++) { + uint32_t xtmp = X[i]; + *pB++ = xtmp & 0xff; + *pB++ = (xtmp >> 8) & 0xff; + *pB++ = (xtmp >> 16) & 0xff; + *pB++ = (xtmp >> 24) & 0xff; + } +} + +#ifndef SIZE_MAX +# define SIZE_MAX ((size_t)-1) +#endif + +/* + * Maximum power of two that will fit in uint64_t: this should work on + * most (all?) platforms. + */ + +#define LOG2_UINT64_MAX (sizeof(uint64_t) * 8 - 1) + +/* + * Maximum value of p * r: + * p <= ((2^32-1) * hLen) / MFLen => + * p <= ((2^32-1) * 32) / (128 * r) => + * p * r <= (2^30-1) + * + */ + +#define SCRYPT_PR_MAX ((1 << 30) - 1) + +/* + * Maximum permitted memory allow this to be overridden with Configuration + * option: e.g. -DSCRYPT_MAX_MEM=0 for maximum possible. + */ + +#ifdef SCRYPT_MAX_MEM +# if SCRYPT_MAX_MEM == 0 +# undef SCRYPT_MAX_MEM +/* + * Although we could theoretically allocate SIZE_MAX memory that would leave + * no memory available for anything else so set limit as half that. + */ +# define SCRYPT_MAX_MEM (SIZE_MAX/2) +# endif +#else +/* Default memory limit: 32 MB */ +# define SCRYPT_MAX_MEM (1024 * 1024 * 32) +#endif + +int EVP_PBE_scrypt(const char *pass, size_t passlen, + const unsigned char *salt, size_t saltlen, + uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem, + unsigned char *key, size_t keylen) +{ + int rv = 0; + unsigned char *B; + uint32_t *X, *V, *T; + uint64_t i, Blen, Vlen; + + /* Sanity check parameters */ + /* initial check, r,p must be non zero, N >= 2 and a power of 2 */ + if (r == 0 || p == 0 || N < 2 || (N & (N - 1))) + return 0; + /* Check p * r < SCRYPT_PR_MAX avoiding overflow */ + if (p > SCRYPT_PR_MAX / r) { + EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED); + return 0; + } + + /* + * Need to check N: if 2^(128 * r / 8) overflows limit this is + * automatically satisfied since N <= UINT64_MAX. + */ + + if (16 * r <= LOG2_UINT64_MAX) { + if (N >= (((uint64_t)1) << (16 * r))) { + EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED); + return 0; + } + } + + /* Memory checks: check total allocated buffer size fits in uint64_t */ + + /* + * B size in section 5 step 1.S + * Note: we know p * 128 * r < UINT64_MAX because we already checked + * p * r < SCRYPT_PR_MAX + */ + Blen = p * 128 * r; + /* + * Yet we pass it as integer to PKCS5_PBKDF2_HMAC... [This would + * have to be revised when/if PKCS5_PBKDF2_HMAC accepts size_t.] + */ + if (Blen > INT_MAX) { + EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED); + return 0; + } + + /* + * Check 32 * r * (N + 2) * sizeof(uint32_t) fits in uint64_t + * This is combined size V, X and T (section 4) + */ + i = UINT64_MAX / (32 * sizeof(uint32_t)); + if (N + 2 > i / r) { + EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED); + return 0; + } + Vlen = 32 * r * (N + 2) * sizeof(uint32_t); + + /* check total allocated size fits in uint64_t */ + if (Blen > UINT64_MAX - Vlen) { + EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED); + return 0; + } + + if (maxmem == 0) + maxmem = SCRYPT_MAX_MEM; + + /* Check that the maximum memory doesn't exceed a size_t limits */ + if (maxmem > SIZE_MAX) + maxmem = SIZE_MAX; + + if (Blen + Vlen > maxmem) { + EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED); + return 0; + } + + /* If no key return to indicate parameters are OK */ + if (key == NULL) + return 1; + + B = OPENSSL_malloc((size_t)(Blen + Vlen)); + if (B == NULL) { + EVPerr(EVP_F_EVP_PBE_SCRYPT, ERR_R_MALLOC_FAILURE); + return 0; + } + X = (uint32_t *)(B + Blen); + T = X + 32 * r; + V = T + 32 * r; + if (PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, 1, EVP_sha256(), + (int)Blen, B) == 0) + goto err; + + for (i = 0; i < p; i++) + scryptROMix(B + 128 * r * i, r, N, X, T, V); + + if (PKCS5_PBKDF2_HMAC(pass, passlen, B, (int)Blen, 1, EVP_sha256(), + keylen, key) == 0) + goto err; + rv = 1; + err: + if (rv == 0) + EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_PBKDF2_ERROR); + + OPENSSL_clear_free(B, (size_t)(Blen + Vlen)); + return rv; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/pmeth_fn.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/pmeth_fn.c new file mode 100644 index 000000000..de1c07e17 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/pmeth_fn.c @@ -0,0 +1,297 @@ +/* + * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include +#include +#include "internal/evp_int.h" + +#define M_check_autoarg(ctx, arg, arglen, err) \ + if (ctx->pmeth->flags & EVP_PKEY_FLAG_AUTOARGLEN) { \ + size_t pksize = (size_t)EVP_PKEY_size(ctx->pkey); \ + \ + if (pksize == 0) { \ + EVPerr(err, EVP_R_INVALID_KEY); /*ckerr_ignore*/ \ + return 0; \ + } \ + if (!arg) { \ + *arglen = pksize; \ + return 1; \ + } \ + if (*arglen < pksize) { \ + EVPerr(err, EVP_R_BUFFER_TOO_SMALL); /*ckerr_ignore*/ \ + return 0; \ + } \ + } + +int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx) +{ + int ret; + if (!ctx || !ctx->pmeth || !ctx->pmeth->sign) { + EVPerr(EVP_F_EVP_PKEY_SIGN_INIT, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + ctx->operation = EVP_PKEY_OP_SIGN; + if (!ctx->pmeth->sign_init) + return 1; + ret = ctx->pmeth->sign_init(ctx); + if (ret <= 0) + ctx->operation = EVP_PKEY_OP_UNDEFINED; + return ret; +} + +int EVP_PKEY_sign(EVP_PKEY_CTX *ctx, + unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbslen) +{ + if (!ctx || !ctx->pmeth || !ctx->pmeth->sign) { + EVPerr(EVP_F_EVP_PKEY_SIGN, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + if (ctx->operation != EVP_PKEY_OP_SIGN) { + EVPerr(EVP_F_EVP_PKEY_SIGN, EVP_R_OPERATON_NOT_INITIALIZED); + return -1; + } + M_check_autoarg(ctx, sig, siglen, EVP_F_EVP_PKEY_SIGN) + return ctx->pmeth->sign(ctx, sig, siglen, tbs, tbslen); +} + +int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx) +{ + int ret; + if (!ctx || !ctx->pmeth || !ctx->pmeth->verify) { + EVPerr(EVP_F_EVP_PKEY_VERIFY_INIT, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + ctx->operation = EVP_PKEY_OP_VERIFY; + if (!ctx->pmeth->verify_init) + return 1; + ret = ctx->pmeth->verify_init(ctx); + if (ret <= 0) + ctx->operation = EVP_PKEY_OP_UNDEFINED; + return ret; +} + +int EVP_PKEY_verify(EVP_PKEY_CTX *ctx, + const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen) +{ + if (!ctx || !ctx->pmeth || !ctx->pmeth->verify) { + EVPerr(EVP_F_EVP_PKEY_VERIFY, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + if (ctx->operation != EVP_PKEY_OP_VERIFY) { + EVPerr(EVP_F_EVP_PKEY_VERIFY, EVP_R_OPERATON_NOT_INITIALIZED); + return -1; + } + return ctx->pmeth->verify(ctx, sig, siglen, tbs, tbslen); +} + +int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx) +{ + int ret; + if (!ctx || !ctx->pmeth || !ctx->pmeth->verify_recover) { + EVPerr(EVP_F_EVP_PKEY_VERIFY_RECOVER_INIT, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + ctx->operation = EVP_PKEY_OP_VERIFYRECOVER; + if (!ctx->pmeth->verify_recover_init) + return 1; + ret = ctx->pmeth->verify_recover_init(ctx); + if (ret <= 0) + ctx->operation = EVP_PKEY_OP_UNDEFINED; + return ret; +} + +int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx, + unsigned char *rout, size_t *routlen, + const unsigned char *sig, size_t siglen) +{ + if (!ctx || !ctx->pmeth || !ctx->pmeth->verify_recover) { + EVPerr(EVP_F_EVP_PKEY_VERIFY_RECOVER, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + if (ctx->operation != EVP_PKEY_OP_VERIFYRECOVER) { + EVPerr(EVP_F_EVP_PKEY_VERIFY_RECOVER, EVP_R_OPERATON_NOT_INITIALIZED); + return -1; + } + M_check_autoarg(ctx, rout, routlen, EVP_F_EVP_PKEY_VERIFY_RECOVER) + return ctx->pmeth->verify_recover(ctx, rout, routlen, sig, siglen); +} + +int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx) +{ + int ret; + if (!ctx || !ctx->pmeth || !ctx->pmeth->encrypt) { + EVPerr(EVP_F_EVP_PKEY_ENCRYPT_INIT, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + ctx->operation = EVP_PKEY_OP_ENCRYPT; + if (!ctx->pmeth->encrypt_init) + return 1; + ret = ctx->pmeth->encrypt_init(ctx); + if (ret <= 0) + ctx->operation = EVP_PKEY_OP_UNDEFINED; + return ret; +} + +int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen) +{ + if (!ctx || !ctx->pmeth || !ctx->pmeth->encrypt) { + EVPerr(EVP_F_EVP_PKEY_ENCRYPT, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + if (ctx->operation != EVP_PKEY_OP_ENCRYPT) { + EVPerr(EVP_F_EVP_PKEY_ENCRYPT, EVP_R_OPERATON_NOT_INITIALIZED); + return -1; + } + M_check_autoarg(ctx, out, outlen, EVP_F_EVP_PKEY_ENCRYPT) + return ctx->pmeth->encrypt(ctx, out, outlen, in, inlen); +} + +int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx) +{ + int ret; + if (!ctx || !ctx->pmeth || !ctx->pmeth->decrypt) { + EVPerr(EVP_F_EVP_PKEY_DECRYPT_INIT, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + ctx->operation = EVP_PKEY_OP_DECRYPT; + if (!ctx->pmeth->decrypt_init) + return 1; + ret = ctx->pmeth->decrypt_init(ctx); + if (ret <= 0) + ctx->operation = EVP_PKEY_OP_UNDEFINED; + return ret; +} + +int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen) +{ + if (!ctx || !ctx->pmeth || !ctx->pmeth->decrypt) { + EVPerr(EVP_F_EVP_PKEY_DECRYPT, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + if (ctx->operation != EVP_PKEY_OP_DECRYPT) { + EVPerr(EVP_F_EVP_PKEY_DECRYPT, EVP_R_OPERATON_NOT_INITIALIZED); + return -1; + } + M_check_autoarg(ctx, out, outlen, EVP_F_EVP_PKEY_DECRYPT) + return ctx->pmeth->decrypt(ctx, out, outlen, in, inlen); +} + +int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx) +{ + int ret; + if (!ctx || !ctx->pmeth || !ctx->pmeth->derive) { + EVPerr(EVP_F_EVP_PKEY_DERIVE_INIT, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + ctx->operation = EVP_PKEY_OP_DERIVE; + if (!ctx->pmeth->derive_init) + return 1; + ret = ctx->pmeth->derive_init(ctx); + if (ret <= 0) + ctx->operation = EVP_PKEY_OP_UNDEFINED; + return ret; +} + +int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer) +{ + int ret; + if (!ctx || !ctx->pmeth + || !(ctx->pmeth->derive || ctx->pmeth->encrypt || ctx->pmeth->decrypt) + || !ctx->pmeth->ctrl) { + EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + if (ctx->operation != EVP_PKEY_OP_DERIVE + && ctx->operation != EVP_PKEY_OP_ENCRYPT + && ctx->operation != EVP_PKEY_OP_DECRYPT) { + EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, + EVP_R_OPERATON_NOT_INITIALIZED); + return -1; + } + + ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 0, peer); + + if (ret <= 0) + return ret; + + if (ret == 2) + return 1; + + if (!ctx->pkey) { + EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_NO_KEY_SET); + return -1; + } + + if (ctx->pkey->type != peer->type) { + EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_DIFFERENT_KEY_TYPES); + return -1; + } + + /* + * For clarity. The error is if parameters in peer are + * present (!missing) but don't match. EVP_PKEY_cmp_parameters may return + * 1 (match), 0 (don't match) and -2 (comparison is not defined). -1 + * (different key types) is impossible here because it is checked earlier. + * -2 is OK for us here, as well as 1, so we can check for 0 only. + */ + if (!EVP_PKEY_missing_parameters(peer) && + !EVP_PKEY_cmp_parameters(ctx->pkey, peer)) { + EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_DIFFERENT_PARAMETERS); + return -1; + } + + EVP_PKEY_free(ctx->peerkey); + ctx->peerkey = peer; + + ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 1, peer); + + if (ret <= 0) { + ctx->peerkey = NULL; + return ret; + } + + EVP_PKEY_up_ref(peer); + return 1; +} + +int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *pkeylen) +{ + if (!ctx || !ctx->pmeth || !ctx->pmeth->derive) { + EVPerr(EVP_F_EVP_PKEY_DERIVE, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + if (ctx->operation != EVP_PKEY_OP_DERIVE) { + EVPerr(EVP_F_EVP_PKEY_DERIVE, EVP_R_OPERATON_NOT_INITIALIZED); + return -1; + } + M_check_autoarg(ctx, key, pkeylen, EVP_F_EVP_PKEY_DERIVE) + return ctx->pmeth->derive(ctx, key, pkeylen); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/pmeth_gn.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/pmeth_gn.c new file mode 100644 index 000000000..e14965f33 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/pmeth_gn.c @@ -0,0 +1,239 @@ +/* + * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include +#include +#include "internal/bn_int.h" +#include "internal/asn1_int.h" +#include "internal/evp_int.h" + +int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx) +{ + int ret; + if (!ctx || !ctx->pmeth || !ctx->pmeth->paramgen) { + EVPerr(EVP_F_EVP_PKEY_PARAMGEN_INIT, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + ctx->operation = EVP_PKEY_OP_PARAMGEN; + if (!ctx->pmeth->paramgen_init) + return 1; + ret = ctx->pmeth->paramgen_init(ctx); + if (ret <= 0) + ctx->operation = EVP_PKEY_OP_UNDEFINED; + return ret; +} + +int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) +{ + int ret; + if (!ctx || !ctx->pmeth || !ctx->pmeth->paramgen) { + EVPerr(EVP_F_EVP_PKEY_PARAMGEN, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + + if (ctx->operation != EVP_PKEY_OP_PARAMGEN) { + EVPerr(EVP_F_EVP_PKEY_PARAMGEN, EVP_R_OPERATON_NOT_INITIALIZED); + return -1; + } + + if (ppkey == NULL) + return -1; + + if (*ppkey == NULL) + *ppkey = EVP_PKEY_new(); + + if (*ppkey == NULL) { + EVPerr(EVP_F_EVP_PKEY_PARAMGEN, ERR_R_MALLOC_FAILURE); + return -1; + } + + ret = ctx->pmeth->paramgen(ctx, *ppkey); + if (ret <= 0) { + EVP_PKEY_free(*ppkey); + *ppkey = NULL; + } + return ret; +} + +int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx) +{ + int ret; + if (!ctx || !ctx->pmeth || !ctx->pmeth->keygen) { + EVPerr(EVP_F_EVP_PKEY_KEYGEN_INIT, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + ctx->operation = EVP_PKEY_OP_KEYGEN; + if (!ctx->pmeth->keygen_init) + return 1; + ret = ctx->pmeth->keygen_init(ctx); + if (ret <= 0) + ctx->operation = EVP_PKEY_OP_UNDEFINED; + return ret; +} + +int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) +{ + int ret; + + if (!ctx || !ctx->pmeth || !ctx->pmeth->keygen) { + EVPerr(EVP_F_EVP_PKEY_KEYGEN, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + if (ctx->operation != EVP_PKEY_OP_KEYGEN) { + EVPerr(EVP_F_EVP_PKEY_KEYGEN, EVP_R_OPERATON_NOT_INITIALIZED); + return -1; + } + + if (ppkey == NULL) + return -1; + + if (*ppkey == NULL) + *ppkey = EVP_PKEY_new(); + if (*ppkey == NULL) + return -1; + + ret = ctx->pmeth->keygen(ctx, *ppkey); + if (ret <= 0) { + EVP_PKEY_free(*ppkey); + *ppkey = NULL; + } + return ret; +} + +void EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb) +{ + ctx->pkey_gencb = cb; +} + +EVP_PKEY_gen_cb *EVP_PKEY_CTX_get_cb(EVP_PKEY_CTX *ctx) +{ + return ctx->pkey_gencb; +} + +/* + * "translation callback" to call EVP_PKEY_CTX callbacks using BN_GENCB style + * callbacks. + */ + +static int trans_cb(int a, int b, BN_GENCB *gcb) +{ + EVP_PKEY_CTX *ctx = BN_GENCB_get_arg(gcb); + ctx->keygen_info[0] = a; + ctx->keygen_info[1] = b; + return ctx->pkey_gencb(ctx); +} + +void evp_pkey_set_cb_translate(BN_GENCB *cb, EVP_PKEY_CTX *ctx) +{ + BN_GENCB_set(cb, trans_cb, ctx); +} + +int EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx) +{ + if (idx == -1) + return ctx->keygen_info_count; + if (idx < 0 || idx > ctx->keygen_info_count) + return 0; + return ctx->keygen_info[idx]; +} + +EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e, + const unsigned char *key, int keylen) +{ + EVP_PKEY_CTX *mac_ctx = NULL; + EVP_PKEY *mac_key = NULL; + mac_ctx = EVP_PKEY_CTX_new_id(type, e); + if (!mac_ctx) + return NULL; + if (EVP_PKEY_keygen_init(mac_ctx) <= 0) + goto merr; + if (EVP_PKEY_CTX_set_mac_key(mac_ctx, key, keylen) <= 0) + goto merr; + if (EVP_PKEY_keygen(mac_ctx, &mac_key) <= 0) + goto merr; + merr: + EVP_PKEY_CTX_free(mac_ctx); + return mac_key; +} + +int EVP_PKEY_check(EVP_PKEY_CTX *ctx) +{ + EVP_PKEY *pkey = ctx->pkey; + + if (pkey == NULL) { + EVPerr(EVP_F_EVP_PKEY_CHECK, EVP_R_NO_KEY_SET); + return 0; + } + + /* call customized check function first */ + if (ctx->pmeth->check != NULL) + return ctx->pmeth->check(pkey); + + /* use default check function in ameth */ + if (pkey->ameth == NULL || pkey->ameth->pkey_check == NULL) { + EVPerr(EVP_F_EVP_PKEY_CHECK, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + + return pkey->ameth->pkey_check(pkey); +} + +int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx) +{ + EVP_PKEY *pkey = ctx->pkey; + + if (pkey == NULL) { + EVPerr(EVP_F_EVP_PKEY_PUBLIC_CHECK, EVP_R_NO_KEY_SET); + return 0; + } + + /* call customized public key check function first */ + if (ctx->pmeth->public_check != NULL) + return ctx->pmeth->public_check(pkey); + + /* use default public key check function in ameth */ + if (pkey->ameth == NULL || pkey->ameth->pkey_public_check == NULL) { + EVPerr(EVP_F_EVP_PKEY_PUBLIC_CHECK, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + + return pkey->ameth->pkey_public_check(pkey); +} + +int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx) +{ + EVP_PKEY *pkey = ctx->pkey; + + if (pkey == NULL) { + EVPerr(EVP_F_EVP_PKEY_PARAM_CHECK, EVP_R_NO_KEY_SET); + return 0; + } + + /* call customized param check function first */ + if (ctx->pmeth->param_check != NULL) + return ctx->pmeth->param_check(pkey); + + /* use default param check function in ameth */ + if (pkey->ameth == NULL || pkey->ameth->pkey_param_check == NULL) { + EVPerr(EVP_F_EVP_PKEY_PARAM_CHECK, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + + return pkey->ameth->pkey_param_check(pkey); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/evp/pmeth_lib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/pmeth_lib.c new file mode 100644 index 000000000..7fbf895e0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/evp/pmeth_lib.c @@ -0,0 +1,864 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include "internal/asn1_int.h" +#include "internal/evp_int.h" +#include "internal/numbers.h" + +typedef int sk_cmp_fn_type(const char *const *a, const char *const *b); + +static STACK_OF(EVP_PKEY_METHOD) *app_pkey_methods = NULL; + +/* This array needs to be in order of NIDs */ +static const EVP_PKEY_METHOD *standard_methods[] = { +#ifndef OPENSSL_NO_RSA + &rsa_pkey_meth, +#endif +#ifndef OPENSSL_NO_DH + &dh_pkey_meth, +#endif +#ifndef OPENSSL_NO_DSA + &dsa_pkey_meth, +#endif +#ifndef OPENSSL_NO_EC + &ec_pkey_meth, +#endif + &hmac_pkey_meth, +#ifndef OPENSSL_NO_CMAC + &cmac_pkey_meth, +#endif +#ifndef OPENSSL_NO_RSA + &rsa_pss_pkey_meth, +#endif +#ifndef OPENSSL_NO_DH + &dhx_pkey_meth, +#endif +#ifndef OPENSSL_NO_SCRYPT + &scrypt_pkey_meth, +#endif + &tls1_prf_pkey_meth, +#ifndef OPENSSL_NO_EC + &ecx25519_pkey_meth, + &ecx448_pkey_meth, +#endif + &hkdf_pkey_meth, +#ifndef OPENSSL_NO_POLY1305 + &poly1305_pkey_meth, +#endif +#ifndef OPENSSL_NO_SIPHASH + &siphash_pkey_meth, +#endif +#ifndef OPENSSL_NO_EC + &ed25519_pkey_meth, + &ed448_pkey_meth, +#endif +#ifndef OPENSSL_NO_SM2 + &sm2_pkey_meth, +#endif +}; + +DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, const EVP_PKEY_METHOD *, + pmeth); + +static int pmeth_cmp(const EVP_PKEY_METHOD *const *a, + const EVP_PKEY_METHOD *const *b) +{ + return ((*a)->pkey_id - (*b)->pkey_id); +} + +IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, const EVP_PKEY_METHOD *, + pmeth); + +const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type) +{ + EVP_PKEY_METHOD tmp; + const EVP_PKEY_METHOD *t = &tmp, **ret; + tmp.pkey_id = type; + if (app_pkey_methods) { + int idx; + idx = sk_EVP_PKEY_METHOD_find(app_pkey_methods, &tmp); + if (idx >= 0) + return sk_EVP_PKEY_METHOD_value(app_pkey_methods, idx); + } + ret = OBJ_bsearch_pmeth(&t, standard_methods, + sizeof(standard_methods) / + sizeof(EVP_PKEY_METHOD *)); + if (!ret || !*ret) + return NULL; + return *ret; +} + +static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id) +{ + EVP_PKEY_CTX *ret; + const EVP_PKEY_METHOD *pmeth; + + if (id == -1) { + if (pkey == NULL) + return 0; + id = pkey->type; + } +#ifndef OPENSSL_NO_ENGINE + if (e == NULL && pkey != NULL) + e = pkey->pmeth_engine != NULL ? pkey->pmeth_engine : pkey->engine; + /* Try to find an ENGINE which implements this method */ + if (e) { + if (!ENGINE_init(e)) { + EVPerr(EVP_F_INT_CTX_NEW, ERR_R_ENGINE_LIB); + return NULL; + } + } else { + e = ENGINE_get_pkey_meth_engine(id); + } + + /* + * If an ENGINE handled this method look it up. Otherwise use internal + * tables. + */ + if (e) + pmeth = ENGINE_get_pkey_meth(e, id); + else +#endif + pmeth = EVP_PKEY_meth_find(id); + + if (pmeth == NULL) { +#ifndef OPENSSL_NO_ENGINE + ENGINE_finish(e); +#endif + EVPerr(EVP_F_INT_CTX_NEW, EVP_R_UNSUPPORTED_ALGORITHM); + return NULL; + } + + ret = OPENSSL_zalloc(sizeof(*ret)); + if (ret == NULL) { +#ifndef OPENSSL_NO_ENGINE + ENGINE_finish(e); +#endif + EVPerr(EVP_F_INT_CTX_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + ret->engine = e; + ret->pmeth = pmeth; + ret->operation = EVP_PKEY_OP_UNDEFINED; + ret->pkey = pkey; + if (pkey != NULL) + EVP_PKEY_up_ref(pkey); + + if (pmeth->init) { + if (pmeth->init(ret) <= 0) { + ret->pmeth = NULL; + EVP_PKEY_CTX_free(ret); + return NULL; + } + } + + return ret; +} + +EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags) +{ + EVP_PKEY_METHOD *pmeth; + + pmeth = OPENSSL_zalloc(sizeof(*pmeth)); + if (pmeth == NULL) { + EVPerr(EVP_F_EVP_PKEY_METH_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + pmeth->pkey_id = id; + pmeth->flags = flags | EVP_PKEY_FLAG_DYNAMIC; + return pmeth; +} + +void EVP_PKEY_meth_get0_info(int *ppkey_id, int *pflags, + const EVP_PKEY_METHOD *meth) +{ + if (ppkey_id) + *ppkey_id = meth->pkey_id; + if (pflags) + *pflags = meth->flags; +} + +void EVP_PKEY_meth_copy(EVP_PKEY_METHOD *dst, const EVP_PKEY_METHOD *src) +{ + + dst->init = src->init; + dst->copy = src->copy; + dst->cleanup = src->cleanup; + + dst->paramgen_init = src->paramgen_init; + dst->paramgen = src->paramgen; + + dst->keygen_init = src->keygen_init; + dst->keygen = src->keygen; + + dst->sign_init = src->sign_init; + dst->sign = src->sign; + + dst->verify_init = src->verify_init; + dst->verify = src->verify; + + dst->verify_recover_init = src->verify_recover_init; + dst->verify_recover = src->verify_recover; + + dst->signctx_init = src->signctx_init; + dst->signctx = src->signctx; + + dst->verifyctx_init = src->verifyctx_init; + dst->verifyctx = src->verifyctx; + + dst->encrypt_init = src->encrypt_init; + dst->encrypt = src->encrypt; + + dst->decrypt_init = src->decrypt_init; + dst->decrypt = src->decrypt; + + dst->derive_init = src->derive_init; + dst->derive = src->derive; + + dst->ctrl = src->ctrl; + dst->ctrl_str = src->ctrl_str; + + dst->check = src->check; +} + +void EVP_PKEY_meth_free(EVP_PKEY_METHOD *pmeth) +{ + if (pmeth && (pmeth->flags & EVP_PKEY_FLAG_DYNAMIC)) + OPENSSL_free(pmeth); +} + +EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e) +{ + return int_ctx_new(pkey, e, -1); +} + +EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e) +{ + return int_ctx_new(NULL, e, id); +} + +EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *pctx) +{ + EVP_PKEY_CTX *rctx; + if (!pctx->pmeth || !pctx->pmeth->copy) + return NULL; +#ifndef OPENSSL_NO_ENGINE + /* Make sure it's safe to copy a pkey context using an ENGINE */ + if (pctx->engine && !ENGINE_init(pctx->engine)) { + EVPerr(EVP_F_EVP_PKEY_CTX_DUP, ERR_R_ENGINE_LIB); + return 0; + } +#endif + rctx = OPENSSL_malloc(sizeof(*rctx)); + if (rctx == NULL) { + EVPerr(EVP_F_EVP_PKEY_CTX_DUP, ERR_R_MALLOC_FAILURE); + return NULL; + } + + rctx->pmeth = pctx->pmeth; +#ifndef OPENSSL_NO_ENGINE + rctx->engine = pctx->engine; +#endif + + if (pctx->pkey) + EVP_PKEY_up_ref(pctx->pkey); + + rctx->pkey = pctx->pkey; + + if (pctx->peerkey) + EVP_PKEY_up_ref(pctx->peerkey); + + rctx->peerkey = pctx->peerkey; + + rctx->data = NULL; + rctx->app_data = NULL; + rctx->operation = pctx->operation; + + if (pctx->pmeth->copy(rctx, pctx) > 0) + return rctx; + + rctx->pmeth = NULL; + EVP_PKEY_CTX_free(rctx); + return NULL; + +} + +int EVP_PKEY_meth_add0(const EVP_PKEY_METHOD *pmeth) +{ + if (app_pkey_methods == NULL) { + app_pkey_methods = sk_EVP_PKEY_METHOD_new(pmeth_cmp); + if (app_pkey_methods == NULL){ + EVPerr(EVP_F_EVP_PKEY_METH_ADD0, ERR_R_MALLOC_FAILURE); + return 0; + } + } + if (!sk_EVP_PKEY_METHOD_push(app_pkey_methods, pmeth)) { + EVPerr(EVP_F_EVP_PKEY_METH_ADD0, ERR_R_MALLOC_FAILURE); + return 0; + } + sk_EVP_PKEY_METHOD_sort(app_pkey_methods); + return 1; +} + +void evp_app_cleanup_int(void) +{ + if (app_pkey_methods != NULL) + sk_EVP_PKEY_METHOD_pop_free(app_pkey_methods, EVP_PKEY_meth_free); +} + +int EVP_PKEY_meth_remove(const EVP_PKEY_METHOD *pmeth) +{ + const EVP_PKEY_METHOD *ret; + + ret = sk_EVP_PKEY_METHOD_delete_ptr(app_pkey_methods, pmeth); + + return ret == NULL ? 0 : 1; +} + +size_t EVP_PKEY_meth_get_count(void) +{ + size_t rv = OSSL_NELEM(standard_methods); + + if (app_pkey_methods) + rv += sk_EVP_PKEY_METHOD_num(app_pkey_methods); + return rv; +} + +const EVP_PKEY_METHOD *EVP_PKEY_meth_get0(size_t idx) +{ + if (idx < OSSL_NELEM(standard_methods)) + return standard_methods[idx]; + if (app_pkey_methods == NULL) + return NULL; + idx -= OSSL_NELEM(standard_methods); + if (idx >= (size_t)sk_EVP_PKEY_METHOD_num(app_pkey_methods)) + return NULL; + return sk_EVP_PKEY_METHOD_value(app_pkey_methods, idx); +} + +void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx) +{ + if (ctx == NULL) + return; + if (ctx->pmeth && ctx->pmeth->cleanup) + ctx->pmeth->cleanup(ctx); + EVP_PKEY_free(ctx->pkey); + EVP_PKEY_free(ctx->peerkey); +#ifndef OPENSSL_NO_ENGINE + ENGINE_finish(ctx->engine); +#endif + OPENSSL_free(ctx); +} + +int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, + int cmd, int p1, void *p2) +{ + int ret; + + if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl) { + EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED); + return -2; + } + if ((keytype != -1) && (ctx->pmeth->pkey_id != keytype)) + return -1; + + /* Skip the operation checks since this is called in a very early stage */ + if (ctx->pmeth->digest_custom != NULL) + goto doit; + + if (ctx->operation == EVP_PKEY_OP_UNDEFINED) { + EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_NO_OPERATION_SET); + return -1; + } + + if ((optype != -1) && !(ctx->operation & optype)) { + EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_INVALID_OPERATION); + return -1; + } + + doit: + ret = ctx->pmeth->ctrl(ctx, cmd, p1, p2); + + if (ret == -2) + EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED); + + return ret; +} + +int EVP_PKEY_CTX_ctrl_uint64(EVP_PKEY_CTX *ctx, int keytype, int optype, + int cmd, uint64_t value) +{ + return EVP_PKEY_CTX_ctrl(ctx, keytype, optype, cmd, 0, &value); +} + +int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, + const char *name, const char *value) +{ + if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl_str) { + EVPerr(EVP_F_EVP_PKEY_CTX_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED); + return -2; + } + if (strcmp(name, "digest") == 0) + return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_TYPE_SIG, EVP_PKEY_CTRL_MD, + value); + return ctx->pmeth->ctrl_str(ctx, name, value); +} + +/* Utility functions to send a string of hex string to a ctrl */ + +int EVP_PKEY_CTX_str2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *str) +{ + size_t len; + + len = strlen(str); + if (len > INT_MAX) + return -1; + return ctx->pmeth->ctrl(ctx, cmd, len, (void *)str); +} + +int EVP_PKEY_CTX_hex2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *hex) +{ + unsigned char *bin; + long binlen; + int rv = -1; + + bin = OPENSSL_hexstr2buf(hex, &binlen); + if (bin == NULL) + return 0; + if (binlen <= INT_MAX) + rv = ctx->pmeth->ctrl(ctx, cmd, binlen, bin); + OPENSSL_free(bin); + return rv; +} + +/* Pass a message digest to a ctrl */ +int EVP_PKEY_CTX_md(EVP_PKEY_CTX *ctx, int optype, int cmd, const char *md) +{ + const EVP_MD *m; + + if (md == NULL || (m = EVP_get_digestbyname(md)) == NULL) { + EVPerr(EVP_F_EVP_PKEY_CTX_MD, EVP_R_INVALID_DIGEST); + return 0; + } + return EVP_PKEY_CTX_ctrl(ctx, -1, optype, cmd, 0, (void *)m); +} + +int EVP_PKEY_CTX_get_operation(EVP_PKEY_CTX *ctx) +{ + return ctx->operation; +} + +void EVP_PKEY_CTX_set0_keygen_info(EVP_PKEY_CTX *ctx, int *dat, int datlen) +{ + ctx->keygen_info = dat; + ctx->keygen_info_count = datlen; +} + +void EVP_PKEY_CTX_set_data(EVP_PKEY_CTX *ctx, void *data) +{ + ctx->data = data; +} + +void *EVP_PKEY_CTX_get_data(EVP_PKEY_CTX *ctx) +{ + return ctx->data; +} + +EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx) +{ + return ctx->pkey; +} + +EVP_PKEY *EVP_PKEY_CTX_get0_peerkey(EVP_PKEY_CTX *ctx) +{ + return ctx->peerkey; +} + +void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data) +{ + ctx->app_data = data; +} + +void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx) +{ + return ctx->app_data; +} + +void EVP_PKEY_meth_set_init(EVP_PKEY_METHOD *pmeth, + int (*init) (EVP_PKEY_CTX *ctx)) +{ + pmeth->init = init; +} + +void EVP_PKEY_meth_set_copy(EVP_PKEY_METHOD *pmeth, + int (*copy) (EVP_PKEY_CTX *dst, + EVP_PKEY_CTX *src)) +{ + pmeth->copy = copy; +} + +void EVP_PKEY_meth_set_cleanup(EVP_PKEY_METHOD *pmeth, + void (*cleanup) (EVP_PKEY_CTX *ctx)) +{ + pmeth->cleanup = cleanup; +} + +void EVP_PKEY_meth_set_paramgen(EVP_PKEY_METHOD *pmeth, + int (*paramgen_init) (EVP_PKEY_CTX *ctx), + int (*paramgen) (EVP_PKEY_CTX *ctx, + EVP_PKEY *pkey)) +{ + pmeth->paramgen_init = paramgen_init; + pmeth->paramgen = paramgen; +} + +void EVP_PKEY_meth_set_keygen(EVP_PKEY_METHOD *pmeth, + int (*keygen_init) (EVP_PKEY_CTX *ctx), + int (*keygen) (EVP_PKEY_CTX *ctx, + EVP_PKEY *pkey)) +{ + pmeth->keygen_init = keygen_init; + pmeth->keygen = keygen; +} + +void EVP_PKEY_meth_set_sign(EVP_PKEY_METHOD *pmeth, + int (*sign_init) (EVP_PKEY_CTX *ctx), + int (*sign) (EVP_PKEY_CTX *ctx, + unsigned char *sig, size_t *siglen, + const unsigned char *tbs, + size_t tbslen)) +{ + pmeth->sign_init = sign_init; + pmeth->sign = sign; +} + +void EVP_PKEY_meth_set_verify(EVP_PKEY_METHOD *pmeth, + int (*verify_init) (EVP_PKEY_CTX *ctx), + int (*verify) (EVP_PKEY_CTX *ctx, + const unsigned char *sig, + size_t siglen, + const unsigned char *tbs, + size_t tbslen)) +{ + pmeth->verify_init = verify_init; + pmeth->verify = verify; +} + +void EVP_PKEY_meth_set_verify_recover(EVP_PKEY_METHOD *pmeth, + int (*verify_recover_init) (EVP_PKEY_CTX + *ctx), + int (*verify_recover) (EVP_PKEY_CTX + *ctx, + unsigned char + *sig, + size_t *siglen, + const unsigned + char *tbs, + size_t tbslen)) +{ + pmeth->verify_recover_init = verify_recover_init; + pmeth->verify_recover = verify_recover; +} + +void EVP_PKEY_meth_set_signctx(EVP_PKEY_METHOD *pmeth, + int (*signctx_init) (EVP_PKEY_CTX *ctx, + EVP_MD_CTX *mctx), + int (*signctx) (EVP_PKEY_CTX *ctx, + unsigned char *sig, + size_t *siglen, + EVP_MD_CTX *mctx)) +{ + pmeth->signctx_init = signctx_init; + pmeth->signctx = signctx; +} + +void EVP_PKEY_meth_set_verifyctx(EVP_PKEY_METHOD *pmeth, + int (*verifyctx_init) (EVP_PKEY_CTX *ctx, + EVP_MD_CTX *mctx), + int (*verifyctx) (EVP_PKEY_CTX *ctx, + const unsigned char *sig, + int siglen, + EVP_MD_CTX *mctx)) +{ + pmeth->verifyctx_init = verifyctx_init; + pmeth->verifyctx = verifyctx; +} + +void EVP_PKEY_meth_set_encrypt(EVP_PKEY_METHOD *pmeth, + int (*encrypt_init) (EVP_PKEY_CTX *ctx), + int (*encryptfn) (EVP_PKEY_CTX *ctx, + unsigned char *out, + size_t *outlen, + const unsigned char *in, + size_t inlen)) +{ + pmeth->encrypt_init = encrypt_init; + pmeth->encrypt = encryptfn; +} + +void EVP_PKEY_meth_set_decrypt(EVP_PKEY_METHOD *pmeth, + int (*decrypt_init) (EVP_PKEY_CTX *ctx), + int (*decrypt) (EVP_PKEY_CTX *ctx, + unsigned char *out, + size_t *outlen, + const unsigned char *in, + size_t inlen)) +{ + pmeth->decrypt_init = decrypt_init; + pmeth->decrypt = decrypt; +} + +void EVP_PKEY_meth_set_derive(EVP_PKEY_METHOD *pmeth, + int (*derive_init) (EVP_PKEY_CTX *ctx), + int (*derive) (EVP_PKEY_CTX *ctx, + unsigned char *key, + size_t *keylen)) +{ + pmeth->derive_init = derive_init; + pmeth->derive = derive; +} + +void EVP_PKEY_meth_set_ctrl(EVP_PKEY_METHOD *pmeth, + int (*ctrl) (EVP_PKEY_CTX *ctx, int type, int p1, + void *p2), + int (*ctrl_str) (EVP_PKEY_CTX *ctx, + const char *type, + const char *value)) +{ + pmeth->ctrl = ctrl; + pmeth->ctrl_str = ctrl_str; +} + +void EVP_PKEY_meth_set_check(EVP_PKEY_METHOD *pmeth, + int (*check) (EVP_PKEY *pkey)) +{ + pmeth->check = check; +} + +void EVP_PKEY_meth_set_public_check(EVP_PKEY_METHOD *pmeth, + int (*check) (EVP_PKEY *pkey)) +{ + pmeth->public_check = check; +} + +void EVP_PKEY_meth_set_param_check(EVP_PKEY_METHOD *pmeth, + int (*check) (EVP_PKEY *pkey)) +{ + pmeth->param_check = check; +} + +void EVP_PKEY_meth_set_digest_custom(EVP_PKEY_METHOD *pmeth, + int (*digest_custom) (EVP_PKEY_CTX *ctx, + EVP_MD_CTX *mctx)) +{ + pmeth->digest_custom = digest_custom; +} + +void EVP_PKEY_meth_get_init(const EVP_PKEY_METHOD *pmeth, + int (**pinit) (EVP_PKEY_CTX *ctx)) +{ + *pinit = pmeth->init; +} + +void EVP_PKEY_meth_get_copy(const EVP_PKEY_METHOD *pmeth, + int (**pcopy) (EVP_PKEY_CTX *dst, + EVP_PKEY_CTX *src)) +{ + *pcopy = pmeth->copy; +} + +void EVP_PKEY_meth_get_cleanup(const EVP_PKEY_METHOD *pmeth, + void (**pcleanup) (EVP_PKEY_CTX *ctx)) +{ + *pcleanup = pmeth->cleanup; +} + +void EVP_PKEY_meth_get_paramgen(const EVP_PKEY_METHOD *pmeth, + int (**pparamgen_init) (EVP_PKEY_CTX *ctx), + int (**pparamgen) (EVP_PKEY_CTX *ctx, + EVP_PKEY *pkey)) +{ + if (pparamgen_init) + *pparamgen_init = pmeth->paramgen_init; + if (pparamgen) + *pparamgen = pmeth->paramgen; +} + +void EVP_PKEY_meth_get_keygen(const EVP_PKEY_METHOD *pmeth, + int (**pkeygen_init) (EVP_PKEY_CTX *ctx), + int (**pkeygen) (EVP_PKEY_CTX *ctx, + EVP_PKEY *pkey)) +{ + if (pkeygen_init) + *pkeygen_init = pmeth->keygen_init; + if (pkeygen) + *pkeygen = pmeth->keygen; +} + +void EVP_PKEY_meth_get_sign(const EVP_PKEY_METHOD *pmeth, + int (**psign_init) (EVP_PKEY_CTX *ctx), + int (**psign) (EVP_PKEY_CTX *ctx, + unsigned char *sig, size_t *siglen, + const unsigned char *tbs, + size_t tbslen)) +{ + if (psign_init) + *psign_init = pmeth->sign_init; + if (psign) + *psign = pmeth->sign; +} + +void EVP_PKEY_meth_get_verify(const EVP_PKEY_METHOD *pmeth, + int (**pverify_init) (EVP_PKEY_CTX *ctx), + int (**pverify) (EVP_PKEY_CTX *ctx, + const unsigned char *sig, + size_t siglen, + const unsigned char *tbs, + size_t tbslen)) +{ + if (pverify_init) + *pverify_init = pmeth->verify_init; + if (pverify) + *pverify = pmeth->verify; +} + +void EVP_PKEY_meth_get_verify_recover(const EVP_PKEY_METHOD *pmeth, + int (**pverify_recover_init) (EVP_PKEY_CTX + *ctx), + int (**pverify_recover) (EVP_PKEY_CTX + *ctx, + unsigned char + *sig, + size_t *siglen, + const unsigned + char *tbs, + size_t tbslen)) +{ + if (pverify_recover_init) + *pverify_recover_init = pmeth->verify_recover_init; + if (pverify_recover) + *pverify_recover = pmeth->verify_recover; +} + +void EVP_PKEY_meth_get_signctx(const EVP_PKEY_METHOD *pmeth, + int (**psignctx_init) (EVP_PKEY_CTX *ctx, + EVP_MD_CTX *mctx), + int (**psignctx) (EVP_PKEY_CTX *ctx, + unsigned char *sig, + size_t *siglen, + EVP_MD_CTX *mctx)) +{ + if (psignctx_init) + *psignctx_init = pmeth->signctx_init; + if (psignctx) + *psignctx = pmeth->signctx; +} + +void EVP_PKEY_meth_get_verifyctx(const EVP_PKEY_METHOD *pmeth, + int (**pverifyctx_init) (EVP_PKEY_CTX *ctx, + EVP_MD_CTX *mctx), + int (**pverifyctx) (EVP_PKEY_CTX *ctx, + const unsigned char *sig, + int siglen, + EVP_MD_CTX *mctx)) +{ + if (pverifyctx_init) + *pverifyctx_init = pmeth->verifyctx_init; + if (pverifyctx) + *pverifyctx = pmeth->verifyctx; +} + +void EVP_PKEY_meth_get_encrypt(const EVP_PKEY_METHOD *pmeth, + int (**pencrypt_init) (EVP_PKEY_CTX *ctx), + int (**pencryptfn) (EVP_PKEY_CTX *ctx, + unsigned char *out, + size_t *outlen, + const unsigned char *in, + size_t inlen)) +{ + if (pencrypt_init) + *pencrypt_init = pmeth->encrypt_init; + if (pencryptfn) + *pencryptfn = pmeth->encrypt; +} + +void EVP_PKEY_meth_get_decrypt(const EVP_PKEY_METHOD *pmeth, + int (**pdecrypt_init) (EVP_PKEY_CTX *ctx), + int (**pdecrypt) (EVP_PKEY_CTX *ctx, + unsigned char *out, + size_t *outlen, + const unsigned char *in, + size_t inlen)) +{ + if (pdecrypt_init) + *pdecrypt_init = pmeth->decrypt_init; + if (pdecrypt) + *pdecrypt = pmeth->decrypt; +} + +void EVP_PKEY_meth_get_derive(const EVP_PKEY_METHOD *pmeth, + int (**pderive_init) (EVP_PKEY_CTX *ctx), + int (**pderive) (EVP_PKEY_CTX *ctx, + unsigned char *key, + size_t *keylen)) +{ + if (pderive_init) + *pderive_init = pmeth->derive_init; + if (pderive) + *pderive = pmeth->derive; +} + +void EVP_PKEY_meth_get_ctrl(const EVP_PKEY_METHOD *pmeth, + int (**pctrl) (EVP_PKEY_CTX *ctx, int type, int p1, + void *p2), + int (**pctrl_str) (EVP_PKEY_CTX *ctx, + const char *type, + const char *value)) +{ + if (pctrl) + *pctrl = pmeth->ctrl; + if (pctrl_str) + *pctrl_str = pmeth->ctrl_str; +} + +void EVP_PKEY_meth_get_check(const EVP_PKEY_METHOD *pmeth, + int (**pcheck) (EVP_PKEY *pkey)) +{ + if (pcheck != NULL) + *pcheck = pmeth->check; +} + +void EVP_PKEY_meth_get_public_check(const EVP_PKEY_METHOD *pmeth, + int (**pcheck) (EVP_PKEY *pkey)) +{ + if (pcheck != NULL) + *pcheck = pmeth->public_check; +} + +void EVP_PKEY_meth_get_param_check(const EVP_PKEY_METHOD *pmeth, + int (**pcheck) (EVP_PKEY *pkey)) +{ + if (pcheck != NULL) + *pcheck = pmeth->param_check; +} + +void EVP_PKEY_meth_get_digest_custom(EVP_PKEY_METHOD *pmeth, + int (**pdigest_custom) (EVP_PKEY_CTX *ctx, + EVP_MD_CTX *mctx)) +{ + if (pdigest_custom != NULL) + *pdigest_custom = pmeth->digest_custom; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ex_data.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ex_data.c new file mode 100644 index 000000000..08dc7c407 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ex_data.c @@ -0,0 +1,399 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib_int.h" +#include "internal/thread_once.h" + +/* + * Each structure type (sometimes called a class), that supports + * exdata has a stack of callbacks for each instance. + */ +struct ex_callback_st { + long argl; /* Arbitrary long */ + void *argp; /* Arbitrary void * */ + CRYPTO_EX_new *new_func; + CRYPTO_EX_free *free_func; + CRYPTO_EX_dup *dup_func; +}; + +/* + * The state for each class. This could just be a typedef, but + * a structure allows future changes. + */ +typedef struct ex_callbacks_st { + STACK_OF(EX_CALLBACK) *meth; +} EX_CALLBACKS; + +static EX_CALLBACKS ex_data[CRYPTO_EX_INDEX__COUNT]; + +static CRYPTO_RWLOCK *ex_data_lock = NULL; +static CRYPTO_ONCE ex_data_init = CRYPTO_ONCE_STATIC_INIT; + +DEFINE_RUN_ONCE_STATIC(do_ex_data_init) +{ + if (!OPENSSL_init_crypto(0, NULL)) + return 0; + ex_data_lock = CRYPTO_THREAD_lock_new(); + return ex_data_lock != NULL; +} + +/* + * Return the EX_CALLBACKS from the |ex_data| array that corresponds to + * a given class. On success, *holds the lock.* + */ +static EX_CALLBACKS *get_and_lock(int class_index) +{ + EX_CALLBACKS *ip; + + if (class_index < 0 || class_index >= CRYPTO_EX_INDEX__COUNT) { + CRYPTOerr(CRYPTO_F_GET_AND_LOCK, ERR_R_PASSED_INVALID_ARGUMENT); + return NULL; + } + + if (!RUN_ONCE(&ex_data_init, do_ex_data_init)) { + CRYPTOerr(CRYPTO_F_GET_AND_LOCK, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (ex_data_lock == NULL) { + /* + * This can happen in normal operation when using CRYPTO_mem_leaks(). + * The CRYPTO_mem_leaks() function calls OPENSSL_cleanup() which cleans + * up the locks. Subsequently the BIO that CRYPTO_mem_leaks() uses gets + * freed, which also attempts to free the ex_data. However + * CRYPTO_mem_leaks() ensures that the ex_data is freed early (i.e. + * before OPENSSL_cleanup() is called), so if we get here we can safely + * ignore this operation. We just treat it as an error. + */ + return NULL; + } + + ip = &ex_data[class_index]; + CRYPTO_THREAD_write_lock(ex_data_lock); + return ip; +} + +static void cleanup_cb(EX_CALLBACK *funcs) +{ + OPENSSL_free(funcs); +} + +/* + * Release all "ex_data" state to prevent memory leaks. This can't be made + * thread-safe without overhauling a lot of stuff, and shouldn't really be + * called under potential race-conditions anyway (it's for program shutdown + * after all). + */ +void crypto_cleanup_all_ex_data_int(void) +{ + int i; + + for (i = 0; i < CRYPTO_EX_INDEX__COUNT; ++i) { + EX_CALLBACKS *ip = &ex_data[i]; + + sk_EX_CALLBACK_pop_free(ip->meth, cleanup_cb); + ip->meth = NULL; + } + + CRYPTO_THREAD_lock_free(ex_data_lock); + ex_data_lock = NULL; +} + + +/* + * Unregister a new index by replacing the callbacks with no-ops. + * Any in-use instances are leaked. + */ +static void dummy_new(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, + long argl, void *argp) +{ +} + +static void dummy_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, + long argl, void *argp) +{ +} + +static int dummy_dup(CRYPTO_EX_DATA *to, const CRYPTO_EX_DATA *from, + void *from_d, int idx, + long argl, void *argp) +{ + return 1; +} + +int CRYPTO_free_ex_index(int class_index, int idx) +{ + EX_CALLBACKS *ip = get_and_lock(class_index); + EX_CALLBACK *a; + int toret = 0; + + if (ip == NULL) + return 0; + if (idx < 0 || idx >= sk_EX_CALLBACK_num(ip->meth)) + goto err; + a = sk_EX_CALLBACK_value(ip->meth, idx); + if (a == NULL) + goto err; + a->new_func = dummy_new; + a->dup_func = dummy_dup; + a->free_func = dummy_free; + toret = 1; +err: + CRYPTO_THREAD_unlock(ex_data_lock); + return toret; +} + +/* + * Register a new index. + */ +int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp, + CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func) +{ + int toret = -1; + EX_CALLBACK *a; + EX_CALLBACKS *ip = get_and_lock(class_index); + + if (ip == NULL) + return -1; + + if (ip->meth == NULL) { + ip->meth = sk_EX_CALLBACK_new_null(); + /* We push an initial value on the stack because the SSL + * "app_data" routines use ex_data index zero. See RT 3710. */ + if (ip->meth == NULL + || !sk_EX_CALLBACK_push(ip->meth, NULL)) { + CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + a = (EX_CALLBACK *)OPENSSL_malloc(sizeof(*a)); + if (a == NULL) { + CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX, ERR_R_MALLOC_FAILURE); + goto err; + } + a->argl = argl; + a->argp = argp; + a->new_func = new_func; + a->dup_func = dup_func; + a->free_func = free_func; + + if (!sk_EX_CALLBACK_push(ip->meth, NULL)) { + CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX, ERR_R_MALLOC_FAILURE); + OPENSSL_free(a); + goto err; + } + toret = sk_EX_CALLBACK_num(ip->meth) - 1; + (void)sk_EX_CALLBACK_set(ip->meth, toret, a); + + err: + CRYPTO_THREAD_unlock(ex_data_lock); + return toret; +} + +/* + * Initialise a new CRYPTO_EX_DATA for use in a particular class - including + * calling new() callbacks for each index in the class used by this variable + * Thread-safe by copying a class's array of "EX_CALLBACK" entries + * in the lock, then using them outside the lock. Note this only applies + * to the global "ex_data" state (ie. class definitions), not 'ad' itself. + */ +int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad) +{ + int mx, i; + void *ptr; + EX_CALLBACK **storage = NULL; + EX_CALLBACK *stack[10]; + EX_CALLBACKS *ip = get_and_lock(class_index); + + if (ip == NULL) + return 0; + + ad->sk = NULL; + + mx = sk_EX_CALLBACK_num(ip->meth); + if (mx > 0) { + if (mx < (int)OSSL_NELEM(stack)) + storage = stack; + else + storage = OPENSSL_malloc(sizeof(*storage) * mx); + if (storage != NULL) + for (i = 0; i < mx; i++) + storage[i] = sk_EX_CALLBACK_value(ip->meth, i); + } + CRYPTO_THREAD_unlock(ex_data_lock); + + if (mx > 0 && storage == NULL) { + CRYPTOerr(CRYPTO_F_CRYPTO_NEW_EX_DATA, ERR_R_MALLOC_FAILURE); + return 0; + } + for (i = 0; i < mx; i++) { + if (storage[i] && storage[i]->new_func) { + ptr = CRYPTO_get_ex_data(ad, i); + storage[i]->new_func(obj, ptr, ad, i, + storage[i]->argl, storage[i]->argp); + } + } + if (storage != stack) + OPENSSL_free(storage); + return 1; +} + +/* + * Duplicate a CRYPTO_EX_DATA variable - including calling dup() callbacks + * for each index in the class used by this variable + */ +int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to, + const CRYPTO_EX_DATA *from) +{ + int mx, j, i; + void *ptr; + EX_CALLBACK *stack[10]; + EX_CALLBACK **storage = NULL; + EX_CALLBACKS *ip; + int toret = 0; + + if (from->sk == NULL) + /* Nothing to copy over */ + return 1; + if ((ip = get_and_lock(class_index)) == NULL) + return 0; + + mx = sk_EX_CALLBACK_num(ip->meth); + j = sk_void_num(from->sk); + if (j < mx) + mx = j; + if (mx > 0) { + if (mx < (int)OSSL_NELEM(stack)) + storage = stack; + else + storage = OPENSSL_malloc(sizeof(*storage) * mx); + if (storage != NULL) + for (i = 0; i < mx; i++) + storage[i] = sk_EX_CALLBACK_value(ip->meth, i); + } + CRYPTO_THREAD_unlock(ex_data_lock); + + if (mx == 0) + return 1; + if (storage == NULL) { + CRYPTOerr(CRYPTO_F_CRYPTO_DUP_EX_DATA, ERR_R_MALLOC_FAILURE); + return 0; + } + /* + * Make sure the ex_data stack is at least |mx| elements long to avoid + * issues in the for loop that follows; so go get the |mx|'th element + * (if it does not exist CRYPTO_get_ex_data() returns NULL), and assign + * to itself. This is normally a no-op; but ensures the stack is the + * proper size + */ + if (!CRYPTO_set_ex_data(to, mx - 1, CRYPTO_get_ex_data(to, mx - 1))) + goto err; + + for (i = 0; i < mx; i++) { + ptr = CRYPTO_get_ex_data(from, i); + if (storage[i] && storage[i]->dup_func) + if (!storage[i]->dup_func(to, from, &ptr, i, + storage[i]->argl, storage[i]->argp)) + goto err; + CRYPTO_set_ex_data(to, i, ptr); + } + toret = 1; + err: + if (storage != stack) + OPENSSL_free(storage); + return toret; +} + + +/* + * Cleanup a CRYPTO_EX_DATA variable - including calling free() callbacks for + * each index in the class used by this variable + */ +void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad) +{ + int mx, i; + EX_CALLBACKS *ip; + void *ptr; + EX_CALLBACK *f; + EX_CALLBACK *stack[10]; + EX_CALLBACK **storage = NULL; + + if ((ip = get_and_lock(class_index)) == NULL) + goto err; + + mx = sk_EX_CALLBACK_num(ip->meth); + if (mx > 0) { + if (mx < (int)OSSL_NELEM(stack)) + storage = stack; + else + storage = OPENSSL_malloc(sizeof(*storage) * mx); + if (storage != NULL) + for (i = 0; i < mx; i++) + storage[i] = sk_EX_CALLBACK_value(ip->meth, i); + } + CRYPTO_THREAD_unlock(ex_data_lock); + + for (i = 0; i < mx; i++) { + if (storage != NULL) + f = storage[i]; + else { + CRYPTO_THREAD_write_lock(ex_data_lock); + f = sk_EX_CALLBACK_value(ip->meth, i); + CRYPTO_THREAD_unlock(ex_data_lock); + } + if (f != NULL && f->free_func != NULL) { + ptr = CRYPTO_get_ex_data(ad, i); + f->free_func(obj, ptr, ad, i, f->argl, f->argp); + } + } + + if (storage != stack) + OPENSSL_free(storage); + err: + sk_void_free(ad->sk); + ad->sk = NULL; +} + +/* + * For a given CRYPTO_EX_DATA variable, set the value corresponding to a + * particular index in the class used by this variable + */ +int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int idx, void *val) +{ + int i; + + if (ad->sk == NULL) { + if ((ad->sk = sk_void_new_null()) == NULL) { + CRYPTOerr(CRYPTO_F_CRYPTO_SET_EX_DATA, ERR_R_MALLOC_FAILURE); + return 0; + } + } + + for (i = sk_void_num(ad->sk); i <= idx; ++i) { + if (!sk_void_push(ad->sk, NULL)) { + CRYPTOerr(CRYPTO_F_CRYPTO_SET_EX_DATA, ERR_R_MALLOC_FAILURE); + return 0; + } + } + sk_void_set(ad->sk, idx, val); + return 1; +} + +/* + * For a given CRYPTO_EX_DATA_ variable, get the value corresponding to a + * particular index in the class used by this variable + */ +void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int idx) +{ + if (ad->sk == NULL || idx >= sk_void_num(ad->sk)) + return NULL; + return sk_void_value(ad->sk, idx); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/getenv.c b/trunk/3rdparty/openssl-1.1-fit/crypto/getenv.c new file mode 100644 index 000000000..7e98b645b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/getenv.c @@ -0,0 +1,31 @@ +/* + * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif + +#include +#include "internal/cryptlib.h" + +char *ossl_safe_getenv(const char *name) +{ +#if defined(__GLIBC__) && defined(__GLIBC_PREREQ) +# if __GLIBC_PREREQ(2, 17) +# define SECURE_GETENV + return secure_getenv(name); +# endif +#endif + +#ifndef SECURE_GETENV + if (OPENSSL_issetugid()) + return NULL; + return getenv(name); +#endif +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/hmac/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/hmac/build.info new file mode 100644 index 000000000..09f67c2a0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/hmac/build.info @@ -0,0 +1,3 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + hmac.c hm_ameth.c hm_pmeth.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/hmac/hm_ameth.c b/trunk/3rdparty/openssl-1.1-fit/crypto/hmac/hm_ameth.c new file mode 100644 index 000000000..fa204e906 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/hmac/hm_ameth.c @@ -0,0 +1,127 @@ +/* + * Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include "internal/asn1_int.h" +#include "internal/evp_int.h" + +/* + * HMAC "ASN1" method. This is just here to indicate the maximum HMAC output + * length and to free up an HMAC key. + */ + +static int hmac_size(const EVP_PKEY *pkey) +{ + return EVP_MAX_MD_SIZE; +} + +static void hmac_key_free(EVP_PKEY *pkey) +{ + ASN1_OCTET_STRING *os = EVP_PKEY_get0(pkey); + if (os) { + if (os->data) + OPENSSL_cleanse(os->data, os->length); + ASN1_OCTET_STRING_free(os); + } +} + +static int hmac_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) +{ + switch (op) { + case ASN1_PKEY_CTRL_DEFAULT_MD_NID: + *(int *)arg2 = NID_sha256; + return 1; + + default: + return -2; + } +} + +static int hmac_pkey_public_cmp(const EVP_PKEY *a, const EVP_PKEY *b) +{ + return ASN1_OCTET_STRING_cmp(EVP_PKEY_get0(a), EVP_PKEY_get0(b)); +} + +static int hmac_set_priv_key(EVP_PKEY *pkey, const unsigned char *priv, + size_t len) +{ + ASN1_OCTET_STRING *os; + + if (pkey->pkey.ptr != NULL) + return 0; + + os = ASN1_OCTET_STRING_new(); + if (os == NULL) + return 0; + + + if (!ASN1_OCTET_STRING_set(os, priv, len)) { + ASN1_OCTET_STRING_free(os); + return 0; + } + + pkey->pkey.ptr = os; + return 1; +} + +static int hmac_get_priv_key(const EVP_PKEY *pkey, unsigned char *priv, + size_t *len) +{ + ASN1_OCTET_STRING *os = (ASN1_OCTET_STRING *)pkey->pkey.ptr; + + if (priv == NULL) { + *len = ASN1_STRING_length(os); + return 1; + } + + if (os == NULL || *len < (size_t)ASN1_STRING_length(os)) + return 0; + + *len = ASN1_STRING_length(os); + memcpy(priv, ASN1_STRING_get0_data(os), *len); + + return 1; +} + +const EVP_PKEY_ASN1_METHOD hmac_asn1_meth = { + EVP_PKEY_HMAC, + EVP_PKEY_HMAC, + 0, + + "HMAC", + "OpenSSL HMAC method", + + 0, 0, hmac_pkey_public_cmp, 0, + + 0, 0, 0, + + hmac_size, + 0, 0, + 0, 0, 0, 0, 0, 0, 0, + + hmac_key_free, + hmac_pkey_ctrl, + NULL, + NULL, + + NULL, + NULL, + NULL, + + NULL, + NULL, + NULL, + + hmac_set_priv_key, + NULL, + hmac_get_priv_key, + NULL, +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/hmac/hm_pmeth.c b/trunk/3rdparty/openssl-1.1-fit/crypto/hmac/hm_pmeth.c new file mode 100644 index 000000000..55dd27d63 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/hmac/hm_pmeth.c @@ -0,0 +1,212 @@ +/* + * Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include "internal/evp_int.h" + +/* HMAC pkey context structure */ + +typedef struct { + const EVP_MD *md; /* MD for HMAC use */ + ASN1_OCTET_STRING ktmp; /* Temp storage for key */ + HMAC_CTX *ctx; +} HMAC_PKEY_CTX; + +static int pkey_hmac_init(EVP_PKEY_CTX *ctx) +{ + HMAC_PKEY_CTX *hctx; + + if ((hctx = OPENSSL_zalloc(sizeof(*hctx))) == NULL) { + CRYPTOerr(CRYPTO_F_PKEY_HMAC_INIT, ERR_R_MALLOC_FAILURE); + return 0; + } + hctx->ktmp.type = V_ASN1_OCTET_STRING; + hctx->ctx = HMAC_CTX_new(); + if (hctx->ctx == NULL) { + OPENSSL_free(hctx); + return 0; + } + + ctx->data = hctx; + ctx->keygen_info_count = 0; + + return 1; +} + +static void pkey_hmac_cleanup(EVP_PKEY_CTX *ctx); + +static int pkey_hmac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) +{ + HMAC_PKEY_CTX *sctx, *dctx; + + /* allocate memory for dst->data and a new HMAC_CTX in dst->data->ctx */ + if (!pkey_hmac_init(dst)) + return 0; + sctx = EVP_PKEY_CTX_get_data(src); + dctx = EVP_PKEY_CTX_get_data(dst); + dctx->md = sctx->md; + if (!HMAC_CTX_copy(dctx->ctx, sctx->ctx)) + goto err; + if (sctx->ktmp.data) { + if (!ASN1_OCTET_STRING_set(&dctx->ktmp, + sctx->ktmp.data, sctx->ktmp.length)) + goto err; + } + return 1; +err: + /* release HMAC_CTX in dst->data->ctx and memory allocated for dst->data */ + pkey_hmac_cleanup (dst); + return 0; +} + +static void pkey_hmac_cleanup(EVP_PKEY_CTX *ctx) +{ + HMAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx); + + if (hctx != NULL) { + HMAC_CTX_free(hctx->ctx); + OPENSSL_clear_free(hctx->ktmp.data, hctx->ktmp.length); + OPENSSL_free(hctx); + EVP_PKEY_CTX_set_data(ctx, NULL); + } +} + +static int pkey_hmac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) +{ + ASN1_OCTET_STRING *hkey = NULL; + HMAC_PKEY_CTX *hctx = ctx->data; + if (!hctx->ktmp.data) + return 0; + hkey = ASN1_OCTET_STRING_dup(&hctx->ktmp); + if (!hkey) + return 0; + EVP_PKEY_assign(pkey, EVP_PKEY_HMAC, hkey); + + return 1; +} + +static int int_update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ + HMAC_PKEY_CTX *hctx = EVP_MD_CTX_pkey_ctx(ctx)->data; + if (!HMAC_Update(hctx->ctx, data, count)) + return 0; + return 1; +} + +static int hmac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx) +{ + HMAC_PKEY_CTX *hctx = ctx->data; + HMAC_CTX_set_flags(hctx->ctx, + EVP_MD_CTX_test_flags(mctx, ~EVP_MD_CTX_FLAG_NO_INIT)); + EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT); + EVP_MD_CTX_set_update_fn(mctx, int_update); + return 1; +} + +static int hmac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, + EVP_MD_CTX *mctx) +{ + unsigned int hlen; + HMAC_PKEY_CTX *hctx = ctx->data; + int l = EVP_MD_CTX_size(mctx); + + if (l < 0) + return 0; + *siglen = l; + if (!sig) + return 1; + + if (!HMAC_Final(hctx->ctx, sig, &hlen)) + return 0; + *siglen = (size_t)hlen; + return 1; +} + +static int pkey_hmac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) +{ + HMAC_PKEY_CTX *hctx = ctx->data; + ASN1_OCTET_STRING *key; + switch (type) { + + case EVP_PKEY_CTRL_SET_MAC_KEY: + if ((!p2 && p1 > 0) || (p1 < -1)) + return 0; + if (!ASN1_OCTET_STRING_set(&hctx->ktmp, p2, p1)) + return 0; + break; + + case EVP_PKEY_CTRL_MD: + hctx->md = p2; + break; + + case EVP_PKEY_CTRL_DIGESTINIT: + key = (ASN1_OCTET_STRING *)ctx->pkey->pkey.ptr; + if (!HMAC_Init_ex(hctx->ctx, key->data, key->length, hctx->md, + ctx->engine)) + return 0; + break; + + default: + return -2; + + } + return 1; +} + +static int pkey_hmac_ctrl_str(EVP_PKEY_CTX *ctx, + const char *type, const char *value) +{ + if (!value) { + return 0; + } + if (strcmp(type, "key") == 0) + return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value); + if (strcmp(type, "hexkey") == 0) + return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value); + return -2; +} + +const EVP_PKEY_METHOD hmac_pkey_meth = { + EVP_PKEY_HMAC, + 0, + pkey_hmac_init, + pkey_hmac_copy, + pkey_hmac_cleanup, + + 0, 0, + + 0, + pkey_hmac_keygen, + + 0, 0, + + 0, 0, + + 0, 0, + + hmac_signctx_init, + hmac_signctx, + + 0, 0, + + 0, 0, + + 0, 0, + + 0, 0, + + pkey_hmac_ctrl, + pkey_hmac_ctrl_str +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/hmac/hmac.c b/trunk/3rdparty/openssl-1.1-fit/crypto/hmac/hmac.c new file mode 100644 index 000000000..e4031b44a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/hmac/hmac.c @@ -0,0 +1,247 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "internal/cryptlib.h" +#include +#include +#include "hmac_lcl.h" + +int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, + const EVP_MD *md, ENGINE *impl) +{ + int rv = 0; + int i, j, reset = 0; + unsigned char pad[HMAC_MAX_MD_CBLOCK_SIZE]; + + /* If we are changing MD then we must have a key */ + if (md != NULL && md != ctx->md && (key == NULL || len < 0)) + return 0; + + if (md != NULL) { + reset = 1; + ctx->md = md; + } else if (ctx->md) { + md = ctx->md; + } else { + return 0; + } + + if (key != NULL) { + reset = 1; + j = EVP_MD_block_size(md); + if (!ossl_assert(j <= (int)sizeof(ctx->key))) + return 0; + if (j < len) { + if (!EVP_DigestInit_ex(ctx->md_ctx, md, impl) + || !EVP_DigestUpdate(ctx->md_ctx, key, len) + || !EVP_DigestFinal_ex(ctx->md_ctx, ctx->key, + &ctx->key_length)) + return 0; + } else { + if (len < 0 || len > (int)sizeof(ctx->key)) + return 0; + memcpy(ctx->key, key, len); + ctx->key_length = len; + } + if (ctx->key_length != HMAC_MAX_MD_CBLOCK_SIZE) + memset(&ctx->key[ctx->key_length], 0, + HMAC_MAX_MD_CBLOCK_SIZE - ctx->key_length); + } + + if (reset) { + for (i = 0; i < HMAC_MAX_MD_CBLOCK_SIZE; i++) + pad[i] = 0x36 ^ ctx->key[i]; + if (!EVP_DigestInit_ex(ctx->i_ctx, md, impl) + || !EVP_DigestUpdate(ctx->i_ctx, pad, EVP_MD_block_size(md))) + goto err; + + for (i = 0; i < HMAC_MAX_MD_CBLOCK_SIZE; i++) + pad[i] = 0x5c ^ ctx->key[i]; + if (!EVP_DigestInit_ex(ctx->o_ctx, md, impl) + || !EVP_DigestUpdate(ctx->o_ctx, pad, EVP_MD_block_size(md))) + goto err; + } + if (!EVP_MD_CTX_copy_ex(ctx->md_ctx, ctx->i_ctx)) + goto err; + rv = 1; + err: + if (reset) + OPENSSL_cleanse(pad, sizeof(pad)); + return rv; +} + +#if OPENSSL_API_COMPAT < 0x10100000L +int HMAC_Init(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md) +{ + if (key && md) + HMAC_CTX_reset(ctx); + return HMAC_Init_ex(ctx, key, len, md, NULL); +} +#endif + +int HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len) +{ + if (!ctx->md) + return 0; + return EVP_DigestUpdate(ctx->md_ctx, data, len); +} + +int HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len) +{ + unsigned int i; + unsigned char buf[EVP_MAX_MD_SIZE]; + + if (!ctx->md) + goto err; + + if (!EVP_DigestFinal_ex(ctx->md_ctx, buf, &i)) + goto err; + if (!EVP_MD_CTX_copy_ex(ctx->md_ctx, ctx->o_ctx)) + goto err; + if (!EVP_DigestUpdate(ctx->md_ctx, buf, i)) + goto err; + if (!EVP_DigestFinal_ex(ctx->md_ctx, md, len)) + goto err; + return 1; + err: + return 0; +} + +size_t HMAC_size(const HMAC_CTX *ctx) +{ + int size = EVP_MD_size((ctx)->md); + + return (size < 0) ? 0 : size; +} + +HMAC_CTX *HMAC_CTX_new(void) +{ + HMAC_CTX *ctx = OPENSSL_zalloc(sizeof(HMAC_CTX)); + + if (ctx != NULL) { + if (!HMAC_CTX_reset(ctx)) { + HMAC_CTX_free(ctx); + return NULL; + } + } + return ctx; +} + +static void hmac_ctx_cleanup(HMAC_CTX *ctx) +{ + EVP_MD_CTX_reset(ctx->i_ctx); + EVP_MD_CTX_reset(ctx->o_ctx); + EVP_MD_CTX_reset(ctx->md_ctx); + ctx->md = NULL; + ctx->key_length = 0; + OPENSSL_cleanse(ctx->key, sizeof(ctx->key)); +} + +void HMAC_CTX_free(HMAC_CTX *ctx) +{ + if (ctx != NULL) { + hmac_ctx_cleanup(ctx); + EVP_MD_CTX_free(ctx->i_ctx); + EVP_MD_CTX_free(ctx->o_ctx); + EVP_MD_CTX_free(ctx->md_ctx); + OPENSSL_free(ctx); + } +} + +static int hmac_ctx_alloc_mds(HMAC_CTX *ctx) +{ + if (ctx->i_ctx == NULL) + ctx->i_ctx = EVP_MD_CTX_new(); + if (ctx->i_ctx == NULL) + return 0; + if (ctx->o_ctx == NULL) + ctx->o_ctx = EVP_MD_CTX_new(); + if (ctx->o_ctx == NULL) + return 0; + if (ctx->md_ctx == NULL) + ctx->md_ctx = EVP_MD_CTX_new(); + if (ctx->md_ctx == NULL) + return 0; + return 1; +} + +int HMAC_CTX_reset(HMAC_CTX *ctx) +{ + hmac_ctx_cleanup(ctx); + if (!hmac_ctx_alloc_mds(ctx)) { + hmac_ctx_cleanup(ctx); + return 0; + } + return 1; +} + +int HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx) +{ + if (!hmac_ctx_alloc_mds(dctx)) + goto err; + if (!EVP_MD_CTX_copy_ex(dctx->i_ctx, sctx->i_ctx)) + goto err; + if (!EVP_MD_CTX_copy_ex(dctx->o_ctx, sctx->o_ctx)) + goto err; + if (!EVP_MD_CTX_copy_ex(dctx->md_ctx, sctx->md_ctx)) + goto err; + memcpy(dctx->key, sctx->key, HMAC_MAX_MD_CBLOCK_SIZE); + dctx->key_length = sctx->key_length; + dctx->md = sctx->md; + return 1; + err: + hmac_ctx_cleanup(dctx); + return 0; +} + +unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len, + const unsigned char *d, size_t n, unsigned char *md, + unsigned int *md_len) +{ + HMAC_CTX *c = NULL; + static unsigned char m[EVP_MAX_MD_SIZE]; + static const unsigned char dummy_key[1] = {'\0'}; + + if (md == NULL) + md = m; + if ((c = HMAC_CTX_new()) == NULL) + goto err; + + /* For HMAC_Init_ex, NULL key signals reuse. */ + if (key == NULL && key_len == 0) { + key = dummy_key; + } + + if (!HMAC_Init_ex(c, key, key_len, evp_md, NULL)) + goto err; + if (!HMAC_Update(c, d, n)) + goto err; + if (!HMAC_Final(c, md, md_len)) + goto err; + HMAC_CTX_free(c); + return md; + err: + HMAC_CTX_free(c); + return NULL; +} + +void HMAC_CTX_set_flags(HMAC_CTX *ctx, unsigned long flags) +{ + EVP_MD_CTX_set_flags(ctx->i_ctx, flags); + EVP_MD_CTX_set_flags(ctx->o_ctx, flags); + EVP_MD_CTX_set_flags(ctx->md_ctx, flags); +} + +const EVP_MD *HMAC_CTX_get_md(const HMAC_CTX *ctx) +{ + return ctx->md; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/hmac/hmac_lcl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/hmac/hmac_lcl.h new file mode 100644 index 000000000..8fd834569 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/hmac/hmac_lcl.h @@ -0,0 +1,25 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_HMAC_LCL_H +# define HEADER_HMAC_LCL_H + +/* The current largest case is for SHA3-224 */ +#define HMAC_MAX_MD_CBLOCK_SIZE 144 + +struct hmac_ctx_st { + const EVP_MD *md; + EVP_MD_CTX *md_ctx; + EVP_MD_CTX *i_ctx; + EVP_MD_CTX *o_ctx; + unsigned int key_length; + unsigned char key[HMAC_MAX_MD_CBLOCK_SIZE]; +}; + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ia64cpuid.S b/trunk/3rdparty/openssl-1.1-fit/crypto/ia64cpuid.S new file mode 100644 index 000000000..92c55124b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ia64cpuid.S @@ -0,0 +1,297 @@ +// Copyright 2004-2017 The OpenSSL Project Authors. All Rights Reserved. +// +// Licensed under the OpenSSL license (the "License"). You may not use +// this file except in compliance with the License. You can obtain a copy +// in the file LICENSE in the source distribution or at +// https://www.openssl.org/source/license.html +// Works on all IA-64 platforms: Linux, HP-UX, Win64i... +// On Win64i compile with ias.exe. +.text + +#if defined(_HPUX_SOURCE) && !defined(_LP64) +#define ADDP addp4 +#else +#define ADDP add +#endif + +.global OPENSSL_cpuid_setup# +.proc OPENSSL_cpuid_setup# +OPENSSL_cpuid_setup: +{ .mib; br.ret.sptk.many b0 };; +.endp OPENSSL_cpuid_setup# + +.global OPENSSL_rdtsc# +.proc OPENSSL_rdtsc# +OPENSSL_rdtsc: +{ .mib; mov r8=ar.itc + br.ret.sptk.many b0 };; +.endp OPENSSL_rdtsc# + +.global OPENSSL_atomic_add# +.proc OPENSSL_atomic_add# +.align 32 +OPENSSL_atomic_add: +{ .mii; ld4 r2=[r32] + nop.i 0 + nop.i 0 };; +.Lspin: +{ .mii; mov ar.ccv=r2 + add r8=r2,r33 + mov r3=r2 };; +{ .mmi; mf;; + cmpxchg4.acq r2=[r32],r8,ar.ccv + nop.i 0 };; +{ .mib; cmp.ne p6,p0=r2,r3 + nop.i 0 +(p6) br.dpnt .Lspin };; +{ .mib; nop.m 0 + sxt4 r8=r8 + br.ret.sptk.many b0 };; +.endp OPENSSL_atomic_add# + +// Returns a structure comprising pointer to the top of stack of +// the caller and pointer beyond backing storage for the current +// register frame. The latter is required, because it might be +// insufficient to wipe backing storage for the current frame +// (as this procedure does), one might have to go further, toward +// higher addresses to reach for whole "retroactively" saved +// context... +.global OPENSSL_wipe_cpu# +.proc OPENSSL_wipe_cpu# +.align 32 +OPENSSL_wipe_cpu: + .prologue + .fframe 0 + .save ar.pfs,r2 + .save ar.lc,r3 +{ .mib; alloc r2=ar.pfs,0,96,0,96 + mov r3=ar.lc + brp.loop.imp .L_wipe_top,.L_wipe_end-16 + };; +{ .mii; mov r9=ar.bsp + mov r8=pr + mov ar.lc=96 };; + .body +{ .mii; add r9=96*8-8,r9 + mov ar.ec=1 };; + +// One can sweep double as fast, but then we can't guarantee +// that backing storage is wiped... +.L_wipe_top: +{ .mfi; st8 [r9]=r0,-8 + mov f127=f0 + mov r127=r0 } +{ .mfb; nop.m 0 + nop.f 0 + br.ctop.sptk .L_wipe_top };; +.L_wipe_end: + +{ .mfi; mov r11=r0 + mov f6=f0 + mov r14=r0 } +{ .mfi; mov r15=r0 + mov f7=f0 + mov r16=r0 } +{ .mfi; mov r17=r0 + mov f8=f0 + mov r18=r0 } +{ .mfi; mov r19=r0 + mov f9=f0 + mov r20=r0 } +{ .mfi; mov r21=r0 + mov f10=f0 + mov r22=r0 } +{ .mfi; mov r23=r0 + mov f11=f0 + mov r24=r0 } +{ .mfi; mov r25=r0 + mov f12=f0 + mov r26=r0 } +{ .mfi; mov r27=r0 + mov f13=f0 + mov r28=r0 } +{ .mfi; mov r29=r0 + mov f14=f0 + mov r30=r0 } +{ .mfi; mov r31=r0 + mov f15=f0 + nop.i 0 } +{ .mfi; mov f16=f0 } +{ .mfi; mov f17=f0 } +{ .mfi; mov f18=f0 } +{ .mfi; mov f19=f0 } +{ .mfi; mov f20=f0 } +{ .mfi; mov f21=f0 } +{ .mfi; mov f22=f0 } +{ .mfi; mov f23=f0 } +{ .mfi; mov f24=f0 } +{ .mfi; mov f25=f0 } +{ .mfi; mov f26=f0 } +{ .mfi; mov f27=f0 } +{ .mfi; mov f28=f0 } +{ .mfi; mov f29=f0 } +{ .mfi; mov f30=f0 } +{ .mfi; add r9=96*8+8,r9 + mov f31=f0 + mov pr=r8,0x1ffff } +{ .mib; mov r8=sp + mov ar.lc=r3 + br.ret.sptk b0 };; +.endp OPENSSL_wipe_cpu# + +.global OPENSSL_cleanse# +.proc OPENSSL_cleanse# +OPENSSL_cleanse: +{ .mib; cmp.eq p6,p0=0,r33 // len==0 + ADDP r32=0,r32 +(p6) br.ret.spnt b0 };; +{ .mib; and r2=7,r32 + cmp.leu p6,p0=15,r33 // len>=15 +(p6) br.cond.dptk .Lot };; + +.Little: +{ .mib; st1 [r32]=r0,1 + cmp.ltu p6,p7=1,r33 } // len>1 +{ .mbb; add r33=-1,r33 // len-- +(p6) br.cond.dptk .Little +(p7) br.ret.sptk.many b0 };; + +.Lot: +{ .mib; cmp.eq p6,p0=0,r2 +(p6) br.cond.dptk .Laligned };; +{ .mmi; st1 [r32]=r0,1;; + and r2=7,r32 } +{ .mib; add r33=-1,r33 + br .Lot };; + +.Laligned: +{ .mmi; st8 [r32]=r0,8 + and r2=-8,r33 // len&~7 + add r33=-8,r33 };; // len-=8 +{ .mib; cmp.ltu p6,p0=8,r2 // ((len+8)&~7)>8 +(p6) br.cond.dptk .Laligned };; + +{ .mbb; cmp.eq p6,p7=r0,r33 +(p7) br.cond.dpnt .Little +(p6) br.ret.sptk.many b0 };; +.endp OPENSSL_cleanse# + +.global CRYPTO_memcmp# +.proc CRYPTO_memcmp# +.align 32 +.skip 16 +CRYPTO_memcmp: + .prologue +{ .mib; mov r8=0 + cmp.eq p6,p0=0,r34 // len==0? +(p6) br.ret.spnt b0 };; + .save ar.pfs,r2 +{ .mib; alloc r2=ar.pfs,3,5,0,8 + .save ar.lc,r3 + mov r3=ar.lc + brp.loop.imp .Loop_cmp_ctop,.Loop_cmp_cend-16 + } +{ .mib; sub r10=r34,r0,1 + .save pr,r9 + mov r9=pr };; +{ .mii; ADDP r16=0,r32 + mov ar.lc=r10 + mov ar.ec=4 } +{ .mib; ADDP r17=0,r33 + mov pr.rot=1<<16 };; + +.Loop_cmp_ctop: +{ .mib; (p16) ld1 r32=[r16],1 + (p18) xor r34=r34,r38 } +{ .mib; (p16) ld1 r36=[r17],1 + (p19) or r8=r8,r35 + br.ctop.sptk .Loop_cmp_ctop };; +.Loop_cmp_cend: + +{ .mib; cmp.ne p6,p0=0,r8 + mov ar.lc=r3 };; +{ .mib; +(p6) mov r8=1 + mov pr=r9,0x1ffff + br.ret.sptk.many b0 };; +.endp CRYPTO_memcmp# + +.global OPENSSL_instrument_bus# +.proc OPENSSL_instrument_bus# +OPENSSL_instrument_bus: +{ .mmi; mov r2=r33 + ADDP r32=0,r32 } +{ .mmi; mov r8=ar.itc;; + mov r10=r0 + mov r9=r8 };; + +{ .mmi; fc r32;; + ld4 r8=[r32] };; +{ .mmi; mf + mov ar.ccv=r8 + add r8=r8,r10 };; +{ .mmi; cmpxchg4.acq r3=[r32],r8,ar.ccv + };; +.Loop: +{ .mmi; mov r8=ar.itc;; + sub r10=r8,r9 // diff=tick-lasttick + mov r9=r8 };; // lasttick=tick +{ .mmi; fc r32;; + ld4 r8=[r32] };; +{ .mmi; mf + mov ar.ccv=r8 + add r8=r8,r10 };; +{ .mmi; cmpxchg4.acq r3=[r32],r8,ar.ccv + add r33=-1,r33 + add r32=4,r32 };; +{ .mib; cmp4.ne p6,p0=0,r33 +(p6) br.cond.dptk .Loop };; + +{ .mib; sub r8=r2,r33 + br.ret.sptk.many b0 };; +.endp OPENSSL_instrument_bus# + +.global OPENSSL_instrument_bus2# +.proc OPENSSL_instrument_bus2# +OPENSSL_instrument_bus2: +{ .mmi; mov r2=r33 // put aside cnt + ADDP r32=0,r32 } +{ .mmi; mov r8=ar.itc;; + mov r10=r0 + mov r9=r8 };; + +{ .mmi; fc r32;; + ld4 r8=[r32] };; +{ .mmi; mf + mov ar.ccv=r8 + add r8=r8,r10 };; +{ .mmi; cmpxchg4.acq r3=[r32],r8,ar.ccv + };; + +{ .mmi; mov r8=ar.itc;; + sub r10=r8,r9 + mov r9=r8 };; +.Loop2: +{ .mmi; mov r11=r10 // lastdiff=diff + add r34=-1,r34 };; // --max +{ .mmi; fc r32;; + ld4 r8=[r32] + cmp4.eq p6,p0=0,r34 };; +{ .mmi; mf + mov ar.ccv=r8 + add r8=r8,r10 };; +{ .mmb; cmpxchg4.acq r3=[r32],r8,ar.ccv +(p6) br.cond.spnt .Ldone2 };; + +{ .mmi; mov r8=ar.itc;; + sub r10=r8,r9 // diff=tick-lasttick + mov r9=r8 };; // lasttick=tick +{ .mmi; cmp.ne p6,p0=r10,r11;; // diff!=lastdiff +(p6) add r33=-1,r33 };; // conditional --cnt +{ .mib; cmp4.ne p7,p0=0,r33 +(p6) add r32=4,r32 // conditional ++out +(p7) br.cond.dptk .Loop2 };; +.Ldone2: +{ .mib; sub r8=r2,r33 + br.ret.sptk.many b0 };; +.endp OPENSSL_instrument_bus2# diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/idea/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/idea/build.info new file mode 100644 index 000000000..232612379 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/idea/build.info @@ -0,0 +1,3 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + i_cbc.c i_cfb64.c i_ofb64.c i_ecb.c i_skey.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/idea/i_cbc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/idea/i_cbc.c new file mode 100644 index 000000000..a70a8682a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/idea/i_cbc.c @@ -0,0 +1,122 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "idea_lcl.h" + +void IDEA_cbc_encrypt(const unsigned char *in, unsigned char *out, + long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv, + int encrypt) +{ + register unsigned long tin0, tin1; + register unsigned long tout0, tout1, xor0, xor1; + register long l = length; + unsigned long tin[2]; + + if (encrypt) { + n2l(iv, tout0); + n2l(iv, tout1); + iv -= 8; + for (l -= 8; l >= 0; l -= 8) { + n2l(in, tin0); + n2l(in, tin1); + tin0 ^= tout0; + tin1 ^= tout1; + tin[0] = tin0; + tin[1] = tin1; + IDEA_encrypt(tin, ks); + tout0 = tin[0]; + l2n(tout0, out); + tout1 = tin[1]; + l2n(tout1, out); + } + if (l != -8) { + n2ln(in, tin0, tin1, l + 8); + tin0 ^= tout0; + tin1 ^= tout1; + tin[0] = tin0; + tin[1] = tin1; + IDEA_encrypt(tin, ks); + tout0 = tin[0]; + l2n(tout0, out); + tout1 = tin[1]; + l2n(tout1, out); + } + l2n(tout0, iv); + l2n(tout1, iv); + } else { + n2l(iv, xor0); + n2l(iv, xor1); + iv -= 8; + for (l -= 8; l >= 0; l -= 8) { + n2l(in, tin0); + tin[0] = tin0; + n2l(in, tin1); + tin[1] = tin1; + IDEA_encrypt(tin, ks); + tout0 = tin[0] ^ xor0; + tout1 = tin[1] ^ xor1; + l2n(tout0, out); + l2n(tout1, out); + xor0 = tin0; + xor1 = tin1; + } + if (l != -8) { + n2l(in, tin0); + tin[0] = tin0; + n2l(in, tin1); + tin[1] = tin1; + IDEA_encrypt(tin, ks); + tout0 = tin[0] ^ xor0; + tout1 = tin[1] ^ xor1; + l2nn(tout0, tout1, out, l + 8); + xor0 = tin0; + xor1 = tin1; + } + l2n(xor0, iv); + l2n(xor1, iv); + } + tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0; + tin[0] = tin[1] = 0; +} + +void IDEA_encrypt(unsigned long *d, IDEA_KEY_SCHEDULE *key) +{ + register IDEA_INT *p; + register unsigned long x1, x2, x3, x4, t0, t1, ul; + + x2 = d[0]; + x1 = (x2 >> 16); + x4 = d[1]; + x3 = (x4 >> 16); + + p = &(key->data[0][0]); + + E_IDEA(0); + E_IDEA(1); + E_IDEA(2); + E_IDEA(3); + E_IDEA(4); + E_IDEA(5); + E_IDEA(6); + E_IDEA(7); + + x1 &= 0xffff; + idea_mul(x1, x1, *p, ul); + p++; + + t0 = x3 + *(p++); + t1 = x2 + *(p++); + + x4 &= 0xffff; + idea_mul(x4, x4, *p, ul); + + d[0] = (t0 & 0xffff) | ((x1 & 0xffff) << 16); + d[1] = (x4 & 0xffff) | ((t1 & 0xffff) << 16); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/idea/i_cfb64.c b/trunk/3rdparty/openssl-1.1-fit/crypto/idea/i_cfb64.c new file mode 100644 index 000000000..daf467eb5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/idea/i_cfb64.c @@ -0,0 +1,74 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "idea_lcl.h" + +/* + * The input and output encrypted as though 64bit cfb mode is being used. + * The extra state information to record how much of the 64bit block we have + * used is contained in *num; + */ + +void IDEA_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, IDEA_KEY_SCHEDULE *schedule, + unsigned char *ivec, int *num, int encrypt) +{ + register unsigned long v0, v1, t; + register int n = *num; + register long l = length; + unsigned long ti[2]; + unsigned char *iv, c, cc; + + iv = (unsigned char *)ivec; + if (encrypt) { + while (l--) { + if (n == 0) { + n2l(iv, v0); + ti[0] = v0; + n2l(iv, v1); + ti[1] = v1; + IDEA_encrypt((unsigned long *)ti, schedule); + iv = (unsigned char *)ivec; + t = ti[0]; + l2n(t, iv); + t = ti[1]; + l2n(t, iv); + iv = (unsigned char *)ivec; + } + c = *(in++) ^ iv[n]; + *(out++) = c; + iv[n] = c; + n = (n + 1) & 0x07; + } + } else { + while (l--) { + if (n == 0) { + n2l(iv, v0); + ti[0] = v0; + n2l(iv, v1); + ti[1] = v1; + IDEA_encrypt((unsigned long *)ti, schedule); + iv = (unsigned char *)ivec; + t = ti[0]; + l2n(t, iv); + t = ti[1]; + l2n(t, iv); + iv = (unsigned char *)ivec; + } + cc = *(in++); + c = iv[n]; + iv[n] = cc; + *(out++) = c ^ cc; + n = (n + 1) & 0x07; + } + } + v0 = v1 = ti[0] = ti[1] = t = c = cc = 0; + *num = n; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/idea/i_ecb.c b/trunk/3rdparty/openssl-1.1-fit/crypto/idea/i_ecb.c new file mode 100644 index 000000000..058d0c14c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/idea/i_ecb.c @@ -0,0 +1,34 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "idea_lcl.h" +#include + +const char *IDEA_options(void) +{ + return "idea(int)"; +} + +void IDEA_ecb_encrypt(const unsigned char *in, unsigned char *out, + IDEA_KEY_SCHEDULE *ks) +{ + unsigned long l0, l1, d[2]; + + n2l(in, l0); + d[0] = l0; + n2l(in, l1); + d[1] = l1; + IDEA_encrypt(d, ks); + l0 = d[0]; + l2n(l0, out); + l1 = d[1]; + l2n(l1, out); + l0 = l1 = d[0] = d[1] = 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/idea/i_ofb64.c b/trunk/3rdparty/openssl-1.1-fit/crypto/idea/i_ofb64.c new file mode 100644 index 000000000..997a7b88e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/idea/i_ofb64.c @@ -0,0 +1,61 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "idea_lcl.h" + +/* + * The input and output encrypted as though 64bit ofb mode is being used. + * The extra state information to record how much of the 64bit block we have + * used is contained in *num; + */ +void IDEA_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, IDEA_KEY_SCHEDULE *schedule, + unsigned char *ivec, int *num) +{ + register unsigned long v0, v1, t; + register int n = *num; + register long l = length; + unsigned char d[8]; + register char *dp; + unsigned long ti[2]; + unsigned char *iv; + int save = 0; + + iv = (unsigned char *)ivec; + n2l(iv, v0); + n2l(iv, v1); + ti[0] = v0; + ti[1] = v1; + dp = (char *)d; + l2n(v0, dp); + l2n(v1, dp); + while (l--) { + if (n == 0) { + IDEA_encrypt((unsigned long *)ti, schedule); + dp = (char *)d; + t = ti[0]; + l2n(t, dp); + t = ti[1]; + l2n(t, dp); + save++; + } + *(out++) = *(in++) ^ d[n]; + n = (n + 1) & 0x07; + } + if (save) { + v0 = ti[0]; + v1 = ti[1]; + iv = (unsigned char *)ivec; + l2n(v0, iv); + l2n(v1, iv); + } + t = v0 = v1 = ti[0] = ti[1] = 0; + *num = n; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/idea/i_skey.c b/trunk/3rdparty/openssl-1.1-fit/crypto/idea/i_skey.c new file mode 100644 index 000000000..9d9145580 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/idea/i_skey.c @@ -0,0 +1,112 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "idea_lcl.h" + +static IDEA_INT inverse(unsigned int xin); +void IDEA_set_encrypt_key(const unsigned char *key, IDEA_KEY_SCHEDULE *ks) +{ + int i; + register IDEA_INT *kt, *kf, r0, r1, r2; + + kt = &(ks->data[0][0]); + n2s(key, kt[0]); + n2s(key, kt[1]); + n2s(key, kt[2]); + n2s(key, kt[3]); + n2s(key, kt[4]); + n2s(key, kt[5]); + n2s(key, kt[6]); + n2s(key, kt[7]); + + kf = kt; + kt += 8; + for (i = 0; i < 6; i++) { + r2 = kf[1]; + r1 = kf[2]; + *(kt++) = ((r2 << 9) | (r1 >> 7)) & 0xffff; + r0 = kf[3]; + *(kt++) = ((r1 << 9) | (r0 >> 7)) & 0xffff; + r1 = kf[4]; + *(kt++) = ((r0 << 9) | (r1 >> 7)) & 0xffff; + r0 = kf[5]; + *(kt++) = ((r1 << 9) | (r0 >> 7)) & 0xffff; + r1 = kf[6]; + *(kt++) = ((r0 << 9) | (r1 >> 7)) & 0xffff; + r0 = kf[7]; + *(kt++) = ((r1 << 9) | (r0 >> 7)) & 0xffff; + r1 = kf[0]; + if (i >= 5) + break; + *(kt++) = ((r0 << 9) | (r1 >> 7)) & 0xffff; + *(kt++) = ((r1 << 9) | (r2 >> 7)) & 0xffff; + kf += 8; + } +} + +void IDEA_set_decrypt_key(IDEA_KEY_SCHEDULE *ek, IDEA_KEY_SCHEDULE *dk) +{ + int r; + register IDEA_INT *fp, *tp, t; + + tp = &(dk->data[0][0]); + fp = &(ek->data[8][0]); + for (r = 0; r < 9; r++) { + *(tp++) = inverse(fp[0]); + *(tp++) = ((int)(0x10000L - fp[2]) & 0xffff); + *(tp++) = ((int)(0x10000L - fp[1]) & 0xffff); + *(tp++) = inverse(fp[3]); + if (r == 8) + break; + fp -= 6; + *(tp++) = fp[4]; + *(tp++) = fp[5]; + } + + tp = &(dk->data[0][0]); + t = tp[1]; + tp[1] = tp[2]; + tp[2] = t; + + t = tp[49]; + tp[49] = tp[50]; + tp[50] = t; +} + +/* taken directly from the 'paper' I'll have a look at it later */ +static IDEA_INT inverse(unsigned int xin) +{ + long n1, n2, q, r, b1, b2, t; + + if (xin == 0) + b2 = 0; + else { + n1 = 0x10001; + n2 = xin; + b2 = 1; + b1 = 0; + + do { + r = (n1 % n2); + q = (n1 - r) / n2; + if (r == 0) { + if (b2 < 0) + b2 = 0x10001 + b2; + } else { + n1 = n2; + n2 = r; + t = b2; + b2 = b1 - q * b2; + b1 = t; + } + } while (r != 0); + } + return (IDEA_INT)b2; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/idea/idea_lcl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/idea/idea_lcl.h new file mode 100644 index 000000000..50f81dfd8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/idea/idea_lcl.h @@ -0,0 +1,102 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#define idea_mul(r,a,b,ul) \ +ul=(unsigned long)a*b; \ +if (ul != 0) \ + { \ + r=(ul&0xffff)-(ul>>16); \ + r-=((r)>>16); \ + } \ +else \ + r=(-(int)a-b+1); /* assuming a or b is 0 and in range */ + +/* NOTE - c is not incremented as per n2l */ +#define n2ln(c,l1,l2,n) { \ + c+=n; \ + l1=l2=0; \ + switch (n) { \ + case 8: l2 =((unsigned long)(*(--(c)))) ; \ + /* fall thru */ \ + case 7: l2|=((unsigned long)(*(--(c))))<< 8; \ + /* fall thru */ \ + case 6: l2|=((unsigned long)(*(--(c))))<<16; \ + /* fall thru */ \ + case 5: l2|=((unsigned long)(*(--(c))))<<24; \ + /* fall thru */ \ + case 4: l1 =((unsigned long)(*(--(c)))) ; \ + /* fall thru */ \ + case 3: l1|=((unsigned long)(*(--(c))))<< 8; \ + /* fall thru */ \ + case 2: l1|=((unsigned long)(*(--(c))))<<16; \ + /* fall thru */ \ + case 1: l1|=((unsigned long)(*(--(c))))<<24; \ + } \ + } + +/* NOTE - c is not incremented as per l2n */ +#define l2nn(l1,l2,c,n) { \ + c+=n; \ + switch (n) { \ + case 8: *(--(c))=(unsigned char)(((l2) )&0xff); \ + /* fall thru */ \ + case 7: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \ + /* fall thru */ \ + case 6: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \ + /* fall thru */ \ + case 5: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \ + /* fall thru */ \ + case 4: *(--(c))=(unsigned char)(((l1) )&0xff); \ + /* fall thru */ \ + case 3: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \ + /* fall thru */ \ + case 2: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \ + /* fall thru */ \ + case 1: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \ + } \ + } + +#undef n2l +#define n2l(c,l) (l =((unsigned long)(*((c)++)))<<24L, \ + l|=((unsigned long)(*((c)++)))<<16L, \ + l|=((unsigned long)(*((c)++)))<< 8L, \ + l|=((unsigned long)(*((c)++)))) + +#undef l2n +#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +#undef s2n +#define s2n(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8L)&0xff)) + +#undef n2s +#define n2s(c,l) (l =((IDEA_INT)(*((c)++)))<< 8L, \ + l|=((IDEA_INT)(*((c)++))) ) + + +#define E_IDEA(num) \ + x1&=0xffff; \ + idea_mul(x1,x1,*p,ul); p++; \ + x2+= *(p++); \ + x3+= *(p++); \ + x4&=0xffff; \ + idea_mul(x4,x4,*p,ul); p++; \ + t0=(x1^x3)&0xffff; \ + idea_mul(t0,t0,*p,ul); p++; \ + t1=(t0+(x2^x4))&0xffff; \ + idea_mul(t1,t1,*p,ul); p++; \ + t0+=t1; \ + x1^=t1; \ + x4^=t0; \ + ul=x2^t0; /* do the swap to x3 */ \ + x2=x3^t1; \ + x3=ul; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/__DECC_INCLUDE_EPILOGUE.H b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/__DECC_INCLUDE_EPILOGUE.H new file mode 100644 index 000000000..c350018ad --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/__DECC_INCLUDE_EPILOGUE.H @@ -0,0 +1,16 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This file is only used by HP C on VMS, and is included automatically + * after each header file from this directory + */ + +/* restore state. Must correspond to the save in __decc_include_prologue.h */ +#pragma names restore diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/__DECC_INCLUDE_PROLOGUE.H b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/__DECC_INCLUDE_PROLOGUE.H new file mode 100644 index 000000000..9a9c777f9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/__DECC_INCLUDE_PROLOGUE.H @@ -0,0 +1,20 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This file is only used by HP C on VMS, and is included automatically + * after each header file from this directory + */ + +/* save state */ +#pragma names save +/* have the compiler shorten symbols larger than 31 chars to 23 chars + * followed by a 8 hex char CRC + */ +#pragma names as_is,shortened diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/aria.h b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/aria.h new file mode 100644 index 000000000..355abe539 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/aria.h @@ -0,0 +1,50 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + + /* Copyright (c) 2017 National Security Research Institute. All rights reserved. */ + +#ifndef HEADER_ARIA_H +# define HEADER_ARIA_H + +# include + +# ifdef OPENSSL_NO_ARIA +# error ARIA is disabled. +# endif + +# define ARIA_ENCRYPT 1 +# define ARIA_DECRYPT 0 + +# define ARIA_BLOCK_SIZE 16 /* Size of each encryption/decryption block */ +# define ARIA_MAX_KEYS 17 /* Number of keys needed in the worst case */ + +typedef union { + unsigned char c[ARIA_BLOCK_SIZE]; + unsigned int u[ARIA_BLOCK_SIZE / sizeof(unsigned int)]; +} ARIA_u128; + +typedef unsigned char ARIA_c128[ARIA_BLOCK_SIZE]; + +struct aria_key_st { + ARIA_u128 rd_key[ARIA_MAX_KEYS]; + unsigned int rounds; +}; +typedef struct aria_key_st ARIA_KEY; + + +int aria_set_encrypt_key(const unsigned char *userKey, const int bits, + ARIA_KEY *key); +int aria_set_decrypt_key(const unsigned char *userKey, const int bits, + ARIA_KEY *key); + +void aria_encrypt(const unsigned char *in, unsigned char *out, + const ARIA_KEY *key); + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/asn1_int.h b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/asn1_int.h new file mode 100644 index 000000000..9c9b4d897 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/asn1_int.h @@ -0,0 +1,113 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Internal ASN1 structures and functions: not for application use */ + +/* ASN1 public key method structure */ + +struct evp_pkey_asn1_method_st { + int pkey_id; + int pkey_base_id; + unsigned long pkey_flags; + char *pem_str; + char *info; + int (*pub_decode) (EVP_PKEY *pk, X509_PUBKEY *pub); + int (*pub_encode) (X509_PUBKEY *pub, const EVP_PKEY *pk); + int (*pub_cmp) (const EVP_PKEY *a, const EVP_PKEY *b); + int (*pub_print) (BIO *out, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *pctx); + int (*priv_decode) (EVP_PKEY *pk, const PKCS8_PRIV_KEY_INFO *p8inf); + int (*priv_encode) (PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk); + int (*priv_print) (BIO *out, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *pctx); + int (*pkey_size) (const EVP_PKEY *pk); + int (*pkey_bits) (const EVP_PKEY *pk); + int (*pkey_security_bits) (const EVP_PKEY *pk); + int (*param_decode) (EVP_PKEY *pkey, + const unsigned char **pder, int derlen); + int (*param_encode) (const EVP_PKEY *pkey, unsigned char **pder); + int (*param_missing) (const EVP_PKEY *pk); + int (*param_copy) (EVP_PKEY *to, const EVP_PKEY *from); + int (*param_cmp) (const EVP_PKEY *a, const EVP_PKEY *b); + int (*param_print) (BIO *out, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *pctx); + int (*sig_print) (BIO *out, + const X509_ALGOR *sigalg, const ASN1_STRING *sig, + int indent, ASN1_PCTX *pctx); + void (*pkey_free) (EVP_PKEY *pkey); + int (*pkey_ctrl) (EVP_PKEY *pkey, int op, long arg1, void *arg2); + /* Legacy functions for old PEM */ + int (*old_priv_decode) (EVP_PKEY *pkey, + const unsigned char **pder, int derlen); + int (*old_priv_encode) (const EVP_PKEY *pkey, unsigned char **pder); + /* Custom ASN1 signature verification */ + int (*item_verify) (EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn, + X509_ALGOR *a, ASN1_BIT_STRING *sig, EVP_PKEY *pkey); + int (*item_sign) (EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn, + X509_ALGOR *alg1, X509_ALGOR *alg2, + ASN1_BIT_STRING *sig); + int (*siginf_set) (X509_SIG_INFO *siginf, const X509_ALGOR *alg, + const ASN1_STRING *sig); + /* Check */ + int (*pkey_check) (const EVP_PKEY *pk); + int (*pkey_public_check) (const EVP_PKEY *pk); + int (*pkey_param_check) (const EVP_PKEY *pk); + /* Get/set raw private/public key data */ + int (*set_priv_key) (EVP_PKEY *pk, const unsigned char *priv, size_t len); + int (*set_pub_key) (EVP_PKEY *pk, const unsigned char *pub, size_t len); + int (*get_priv_key) (const EVP_PKEY *pk, unsigned char *priv, size_t *len); + int (*get_pub_key) (const EVP_PKEY *pk, unsigned char *pub, size_t *len); +} /* EVP_PKEY_ASN1_METHOD */ ; + +DEFINE_STACK_OF_CONST(EVP_PKEY_ASN1_METHOD) + +extern const EVP_PKEY_ASN1_METHOD cmac_asn1_meth; +extern const EVP_PKEY_ASN1_METHOD dh_asn1_meth; +extern const EVP_PKEY_ASN1_METHOD dhx_asn1_meth; +extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[5]; +extern const EVP_PKEY_ASN1_METHOD eckey_asn1_meth; +extern const EVP_PKEY_ASN1_METHOD ecx25519_asn1_meth; +extern const EVP_PKEY_ASN1_METHOD ecx448_asn1_meth; +extern const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth; +extern const EVP_PKEY_ASN1_METHOD ed448_asn1_meth; +extern const EVP_PKEY_ASN1_METHOD sm2_asn1_meth; +extern const EVP_PKEY_ASN1_METHOD poly1305_asn1_meth; + +extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth; +extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[2]; +extern const EVP_PKEY_ASN1_METHOD rsa_pss_asn1_meth; +extern const EVP_PKEY_ASN1_METHOD siphash_asn1_meth; + +/* + * These are used internally in the ASN1_OBJECT to keep track of whether the + * names and data need to be free()ed + */ +# define ASN1_OBJECT_FLAG_DYNAMIC 0x01/* internal use */ +# define ASN1_OBJECT_FLAG_CRITICAL 0x02/* critical x509v3 object id */ +# define ASN1_OBJECT_FLAG_DYNAMIC_STRINGS 0x04/* internal use */ +# define ASN1_OBJECT_FLAG_DYNAMIC_DATA 0x08/* internal use */ +struct asn1_object_st { + const char *sn, *ln; + int nid; + int length; + const unsigned char *data; /* data remains const after init */ + int flags; /* Should we free this one */ +}; + +/* ASN1 print context structure */ + +struct asn1_pctx_st { + unsigned long flags; + unsigned long nm_flags; + unsigned long cert_flags; + unsigned long oid_flags; + unsigned long str_flags; +} /* ASN1_PCTX */ ; + +int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb); diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/async.h b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/async.h new file mode 100644 index 000000000..dc8e937b0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/async.h @@ -0,0 +1,15 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +int async_init(void); +void async_deinit(void); +void async_delete_thread_state(void); + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/bn_conf.h.in b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/bn_conf.h.in new file mode 100644 index 000000000..ec6e4f6c1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/bn_conf.h.in @@ -0,0 +1,27 @@ +{- join("\n",map { "/* $_ */" } @autowarntext) -} +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_BN_CONF_H +# define HEADER_BN_CONF_H + +/* + * The contents of this file are not used in the UEFI build, as + * both 32-bit and 64-bit builds are supported from a single run + * of the Configure script. + */ + +/* Should we define BN_DIV2W here? */ + +/* Only one for the following should be defined */ +{- $config{b64l} ? "#define" : "#undef" -} SIXTY_FOUR_BIT_LONG +{- $config{b64} ? "#define" : "#undef" -} SIXTY_FOUR_BIT +{- $config{b32} ? "#define" : "#undef" -} THIRTY_TWO_BIT + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/bn_dh.h b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/bn_dh.h new file mode 100644 index 000000000..70ebca287 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/bn_dh.h @@ -0,0 +1,24 @@ +/* + * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#define declare_dh_bn(x) \ + extern const BIGNUM _bignum_dh##x##_p; \ + extern const BIGNUM _bignum_dh##x##_g; \ + extern const BIGNUM _bignum_dh##x##_q; + +declare_dh_bn(1024_160) +declare_dh_bn(2048_224) +declare_dh_bn(2048_256) + +extern const BIGNUM _bignum_ffdhe2048_p; +extern const BIGNUM _bignum_ffdhe3072_p; +extern const BIGNUM _bignum_ffdhe4096_p; +extern const BIGNUM _bignum_ffdhe6144_p; +extern const BIGNUM _bignum_ffdhe8192_p; +extern const BIGNUM _bignum_const_2; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/bn_int.h b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/bn_int.h new file mode 100644 index 000000000..30be7efe1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/bn_int.h @@ -0,0 +1,90 @@ +/* + * Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_BN_INT_H +# define HEADER_BN_INT_H + +# include +# include + +BIGNUM *bn_wexpand(BIGNUM *a, int words); +BIGNUM *bn_expand2(BIGNUM *a, int words); + +void bn_correct_top(BIGNUM *a); + +/* + * Determine the modified width-(w+1) Non-Adjacent Form (wNAF) of 'scalar'. + * This is an array r[] of values that are either zero or odd with an + * absolute value less than 2^w satisfying scalar = \sum_j r[j]*2^j where at + * most one of any w+1 consecutive digits is non-zero with the exception that + * the most significant digit may be only w-1 zeros away from that next + * non-zero digit. + */ +signed char *bn_compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len); + +int bn_get_top(const BIGNUM *a); + +int bn_get_dmax(const BIGNUM *a); + +/* Set all words to zero */ +void bn_set_all_zero(BIGNUM *a); + +/* + * Copy the internal BIGNUM words into out which holds size elements (and size + * must be bigger than top) + */ +int bn_copy_words(BN_ULONG *out, const BIGNUM *in, int size); + +BN_ULONG *bn_get_words(const BIGNUM *a); + +/* + * Set the internal data words in a to point to words which contains size + * elements. The BN_FLG_STATIC_DATA flag is set + */ +void bn_set_static_words(BIGNUM *a, const BN_ULONG *words, int size); + +/* + * Copy words into the BIGNUM |a|, reallocating space as necessary. + * The negative flag of |a| is not modified. + * Returns 1 on success and 0 on failure. + */ +/* + * |num_words| is int because bn_expand2 takes an int. This is an internal + * function so we simply trust callers not to pass negative values. + */ +int bn_set_words(BIGNUM *a, const BN_ULONG *words, int num_words); + +/* + * Some BIGNUM functions assume most significant limb to be non-zero, which + * is customarily arranged by bn_correct_top. Output from below functions + * is not processed with bn_correct_top, and for this reason it may not be + * returned out of public API. It may only be passed internally into other + * functions known to support non-minimal or zero-padded BIGNUMs. Even + * though the goal is to facilitate constant-time-ness, not each subroutine + * is constant-time by itself. They all have pre-conditions, consult source + * code... + */ +int bn_mul_mont_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + BN_MONT_CTX *mont, BN_CTX *ctx); +int bn_to_mont_fixed_top(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont, + BN_CTX *ctx); +int bn_from_mont_fixed_top(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont, + BN_CTX *ctx); +int bn_mod_add_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m); +int bn_mod_sub_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m); +int bn_mul_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); +int bn_sqr_fixed_top(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx); +int bn_lshift_fixed_top(BIGNUM *r, const BIGNUM *a, int n); +int bn_rshift_fixed_top(BIGNUM *r, const BIGNUM *a, int n); +int bn_div_fixed_top(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, + const BIGNUM *d, BN_CTX *ctx); + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/bn_srp.h b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/bn_srp.h new file mode 100644 index 000000000..d4b282a6b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/bn_srp.h @@ -0,0 +1,32 @@ +/* + * Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OPENSSL_NO_SRP + +extern const BIGNUM bn_group_1024; + +extern const BIGNUM bn_group_1536; + +extern const BIGNUM bn_group_2048; + +extern const BIGNUM bn_group_3072; + +extern const BIGNUM bn_group_4096; + +extern const BIGNUM bn_group_6144; + +extern const BIGNUM bn_group_8192; + +extern const BIGNUM bn_generator_19; + +extern const BIGNUM bn_generator_5; + +extern const BIGNUM bn_generator_2; + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/chacha.h b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/chacha.h new file mode 100644 index 000000000..67243f222 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/chacha.h @@ -0,0 +1,42 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_CHACHA_H +#define HEADER_CHACHA_H + +#include + +/* + * ChaCha20_ctr32 encrypts |len| bytes from |inp| with the given key and + * nonce and writes the result to |out|, which may be equal to |inp|. + * The |key| is not 32 bytes of verbatim key material though, but the + * said material collected into 8 32-bit elements array in host byte + * order. Same approach applies to nonce: the |counter| argument is + * pointer to concatenated nonce and counter values collected into 4 + * 32-bit elements. This, passing crypto material collected into 32-bit + * elements as opposite to passing verbatim byte vectors, is chosen for + * efficiency in multi-call scenarios. + */ +void ChaCha20_ctr32(unsigned char *out, const unsigned char *inp, + size_t len, const unsigned int key[8], + const unsigned int counter[4]); +/* + * You can notice that there is no key setup procedure. Because it's + * as trivial as collecting bytes into 32-bit elements, it's reckoned + * that below macro is sufficient. + */ +#define CHACHA_U8TOU32(p) ( \ + ((unsigned int)(p)[0]) | ((unsigned int)(p)[1]<<8) | \ + ((unsigned int)(p)[2]<<16) | ((unsigned int)(p)[3]<<24) ) + +#define CHACHA_KEY_SIZE 32 +#define CHACHA_CTR_SIZE 16 +#define CHACHA_BLK_SIZE 64 + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/cryptlib_int.h b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/cryptlib_int.h new file mode 100644 index 000000000..38b5dac9a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/cryptlib_int.h @@ -0,0 +1,35 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" + +/* This file is not scanned by mkdef.pl, whereas cryptlib.h is */ + +struct thread_local_inits_st { + int async; + int err_state; + int rand; +}; + +int ossl_init_thread_start(uint64_t opts); + +/* + * OPENSSL_INIT flags. The primary list of these is in crypto.h. Flags below + * are those omitted from crypto.h because they are "reserved for internal + * use". + */ +# define OPENSSL_INIT_ZLIB 0x00010000L +# define OPENSSL_INIT_BASE_ONLY 0x00040000L + +/* OPENSSL_INIT_THREAD flags */ +# define OPENSSL_INIT_THREAD_ASYNC 0x01 +# define OPENSSL_INIT_THREAD_ERR_STATE 0x02 +# define OPENSSL_INIT_THREAD_RAND 0x04 + +void ossl_malloc_setup_failures(void); diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/ctype.h b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/ctype.h new file mode 100644 index 000000000..a35b12bfb --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/ctype.h @@ -0,0 +1,80 @@ +/* + * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This version of ctype.h provides a standardised and platform + * independent implementation that supports seven bit ASCII characters. + * The specific intent is to not pass extended ASCII characters (> 127) + * even if the host operating system would. + * + * There is EBCDIC support included for machines which use this. However, + * there are a number of concerns about how well EBCDIC is supported + * throughout the rest of the source code. Refer to issue #4154 for + * details. + */ +#ifndef INTERNAL_CTYPE_H +# define INTERNAL_CTYPE_H + +# define CTYPE_MASK_lower 0x1 +# define CTYPE_MASK_upper 0x2 +# define CTYPE_MASK_digit 0x4 +# define CTYPE_MASK_space 0x8 +# define CTYPE_MASK_xdigit 0x10 +# define CTYPE_MASK_blank 0x20 +# define CTYPE_MASK_cntrl 0x40 +# define CTYPE_MASK_graph 0x80 +# define CTYPE_MASK_print 0x100 +# define CTYPE_MASK_punct 0x200 +# define CTYPE_MASK_base64 0x400 +# define CTYPE_MASK_asn1print 0x800 + +# define CTYPE_MASK_alpha (CTYPE_MASK_lower | CTYPE_MASK_upper) +# define CTYPE_MASK_alnum (CTYPE_MASK_alpha | CTYPE_MASK_digit) + +/* + * The ascii mask assumes that any other classification implies that + * the character is ASCII and that there are no ASCII characters + * that aren't in any of the classifications. + * + * This assumption holds at the moment, but it might not in the future. + */ +# define CTYPE_MASK_ascii (~0) + +# ifdef CHARSET_EBCDIC +int ossl_toascii(int c); +int ossl_fromascii(int c); +# else +# define ossl_toascii(c) (c) +# define ossl_fromascii(c) (c) +# endif +int ossl_ctype_check(int c, unsigned int mask); +int ossl_tolower(int c); +int ossl_toupper(int c); + +# define ossl_isalnum(c) (ossl_ctype_check((c), CTYPE_MASK_alnum)) +# define ossl_isalpha(c) (ossl_ctype_check((c), CTYPE_MASK_alpha)) +# ifdef CHARSET_EBCDIC +# define ossl_isascii(c) (ossl_ctype_check((c), CTYPE_MASK_ascii)) +# else +# define ossl_isascii(c) (((c) & ~127) == 0) +# endif +# define ossl_isblank(c) (ossl_ctype_check((c), CTYPE_MASK_blank)) +# define ossl_iscntrl(c) (ossl_ctype_check((c), CTYPE_MASK_cntrl)) +# define ossl_isdigit(c) (ossl_ctype_check((c), CTYPE_MASK_digit)) +# define ossl_isgraph(c) (ossl_ctype_check((c), CTYPE_MASK_graph)) +# define ossl_islower(c) (ossl_ctype_check((c), CTYPE_MASK_lower)) +# define ossl_isprint(c) (ossl_ctype_check((c), CTYPE_MASK_print)) +# define ossl_ispunct(c) (ossl_ctype_check((c), CTYPE_MASK_punct)) +# define ossl_isspace(c) (ossl_ctype_check((c), CTYPE_MASK_space)) +# define ossl_isupper(c) (ossl_ctype_check((c), CTYPE_MASK_upper)) +# define ossl_isxdigit(c) (ossl_ctype_check((c), CTYPE_MASK_xdigit)) +# define ossl_isbase64(c) (ossl_ctype_check((c), CTYPE_MASK_base64)) +# define ossl_isasn1print(c) (ossl_ctype_check((c), CTYPE_MASK_asn1print)) + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/dso_conf.h.in b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/dso_conf.h.in new file mode 100644 index 000000000..d6e9d1b1b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/dso_conf.h.in @@ -0,0 +1,30 @@ +{- join("\n",map { "/* $_ */" } @autowarntext) -} +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_DSO_CONF_H +# define HEADER_DSO_CONF_H +{- output_off() if $disabled{dso} -} +{- # The DSO code currently always implements all functions so that no + # applications will have to worry about that from a compilation point + # of view. However, the "method"s may return zero unless that platform + # has support compiled in for them. Currently each method is enabled + # by a define "DSO_" ... we translate the "dso_scheme" config + # string entry into using the following logic; + my $scheme = uc $target{dso_scheme}; + my @macros = ( "DSO_$scheme" ); + if ($scheme eq 'DLFCN') { + @macros = ( "DSO_DLFCN", "HAVE_DLFCN_H" ); + } elsif ($scheme eq "DLFCN_NO_H") { + @macros = ( "DSO_DLFCN" ); + } + join("\n", map { "# define $_" } @macros); -} +# define DSO_EXTENSION "{- $target{dso_extension} -}" +{- output_on() if $disabled{dso} -} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/ec_int.h b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/ec_int.h new file mode 100644 index 000000000..182c39cc8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/ec_int.h @@ -0,0 +1,53 @@ +/* + * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Internal EC functions for other submodules: not for application use */ + +#ifndef HEADER_OSSL_EC_INTERNAL_H +# define HEADER_OSSL_EC_INTERNAL_H +# include + +# ifndef OPENSSL_NO_EC + +# include + +/*- + * Computes the multiplicative inverse of x in the range + * [1,EC_GROUP::order), where EC_GROUP::order is the cardinality of the + * subgroup generated by the generator G: + * + * res := x^(-1) (mod EC_GROUP::order). + * + * This function expects the following two conditions to hold: + * - the EC_GROUP order is prime, and + * - x is included in the range [1, EC_GROUP::order). + * + * This function returns 1 on success, 0 on error. + * + * If the EC_GROUP order is even, this function explicitly returns 0 as + * an error. + * In case any of the two conditions stated above is not satisfied, + * the correctness of its output is not guaranteed, even if the return + * value could still be 1 (as primality testing and a conditional modular + * reduction round on the input can be omitted by the underlying + * implementations for better SCA properties on regular input values). + */ +__owur int ec_group_do_inverse_ord(const EC_GROUP *group, BIGNUM *res, + const BIGNUM *x, BN_CTX *ctx); + +/*- + * ECDH Key Derivation Function as defined in ANSI X9.63 + */ +int ecdh_KDF_X9_63(unsigned char *out, size_t outlen, + const unsigned char *Z, size_t Zlen, + const unsigned char *sinfo, size_t sinfolen, + const EVP_MD *md); + +# endif /* OPENSSL_NO_EC */ +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/engine.h b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/engine.h new file mode 100644 index 000000000..f80ae3ec3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/engine.h @@ -0,0 +1,20 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +void engine_load_openssl_int(void); +void engine_load_devcrypto_int(void); +void engine_load_rdrand_int(void); +void engine_load_dynamic_int(void); +void engine_load_padlock_int(void); +void engine_load_capi_int(void); +void engine_load_dasync_int(void); +void engine_load_afalg_int(void); +void engine_cleanup_int(void); diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/err_int.h b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/err_int.h new file mode 100644 index 000000000..44ac94462 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/err_int.h @@ -0,0 +1,19 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef INTERNAL_ERR_INT_H +# define INTERNAL_ERR_INT_H + +int err_load_crypto_strings_int(void); +void err_cleanup(void); +void err_delete_thread_state(void); +int err_shelve_state(void **); +void err_unshelve_state(void *); + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/evp_int.h b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/evp_int.h new file mode 100644 index 000000000..d86aed36f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/evp_int.h @@ -0,0 +1,442 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/refcount.h" + +/* + * Don't free up md_ctx->pctx in EVP_MD_CTX_reset, use the reserved flag + * values in evp.h + */ +#define EVP_MD_CTX_FLAG_KEEP_PKEY_CTX 0x0400 + +struct evp_pkey_ctx_st { + /* Method associated with this operation */ + const EVP_PKEY_METHOD *pmeth; + /* Engine that implements this method or NULL if builtin */ + ENGINE *engine; + /* Key: may be NULL */ + EVP_PKEY *pkey; + /* Peer key for key agreement, may be NULL */ + EVP_PKEY *peerkey; + /* Actual operation */ + int operation; + /* Algorithm specific data */ + void *data; + /* Application specific data */ + void *app_data; + /* Keygen callback */ + EVP_PKEY_gen_cb *pkey_gencb; + /* implementation specific keygen data */ + int *keygen_info; + int keygen_info_count; +} /* EVP_PKEY_CTX */ ; + +#define EVP_PKEY_FLAG_DYNAMIC 1 + +struct evp_pkey_method_st { + int pkey_id; + int flags; + int (*init) (EVP_PKEY_CTX *ctx); + int (*copy) (EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src); + void (*cleanup) (EVP_PKEY_CTX *ctx); + int (*paramgen_init) (EVP_PKEY_CTX *ctx); + int (*paramgen) (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey); + int (*keygen_init) (EVP_PKEY_CTX *ctx); + int (*keygen) (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey); + int (*sign_init) (EVP_PKEY_CTX *ctx); + int (*sign) (EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbslen); + int (*verify_init) (EVP_PKEY_CTX *ctx); + int (*verify) (EVP_PKEY_CTX *ctx, + const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen); + int (*verify_recover_init) (EVP_PKEY_CTX *ctx); + int (*verify_recover) (EVP_PKEY_CTX *ctx, + unsigned char *rout, size_t *routlen, + const unsigned char *sig, size_t siglen); + int (*signctx_init) (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx); + int (*signctx) (EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, + EVP_MD_CTX *mctx); + int (*verifyctx_init) (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx); + int (*verifyctx) (EVP_PKEY_CTX *ctx, const unsigned char *sig, int siglen, + EVP_MD_CTX *mctx); + int (*encrypt_init) (EVP_PKEY_CTX *ctx); + int (*encrypt) (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen); + int (*decrypt_init) (EVP_PKEY_CTX *ctx); + int (*decrypt) (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen); + int (*derive_init) (EVP_PKEY_CTX *ctx); + int (*derive) (EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen); + int (*ctrl) (EVP_PKEY_CTX *ctx, int type, int p1, void *p2); + int (*ctrl_str) (EVP_PKEY_CTX *ctx, const char *type, const char *value); + int (*digestsign) (EVP_MD_CTX *ctx, unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbslen); + int (*digestverify) (EVP_MD_CTX *ctx, const unsigned char *sig, + size_t siglen, const unsigned char *tbs, + size_t tbslen); + int (*check) (EVP_PKEY *pkey); + int (*public_check) (EVP_PKEY *pkey); + int (*param_check) (EVP_PKEY *pkey); + + int (*digest_custom) (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx); +} /* EVP_PKEY_METHOD */ ; + +DEFINE_STACK_OF_CONST(EVP_PKEY_METHOD) + +void evp_pkey_set_cb_translate(BN_GENCB *cb, EVP_PKEY_CTX *ctx); + +extern const EVP_PKEY_METHOD cmac_pkey_meth; +extern const EVP_PKEY_METHOD dh_pkey_meth; +extern const EVP_PKEY_METHOD dhx_pkey_meth; +extern const EVP_PKEY_METHOD dsa_pkey_meth; +extern const EVP_PKEY_METHOD ec_pkey_meth; +extern const EVP_PKEY_METHOD sm2_pkey_meth; +extern const EVP_PKEY_METHOD ecx25519_pkey_meth; +extern const EVP_PKEY_METHOD ecx448_pkey_meth; +extern const EVP_PKEY_METHOD ed25519_pkey_meth; +extern const EVP_PKEY_METHOD ed448_pkey_meth; +extern const EVP_PKEY_METHOD hmac_pkey_meth; +extern const EVP_PKEY_METHOD rsa_pkey_meth; +extern const EVP_PKEY_METHOD rsa_pss_pkey_meth; +extern const EVP_PKEY_METHOD scrypt_pkey_meth; +extern const EVP_PKEY_METHOD tls1_prf_pkey_meth; +extern const EVP_PKEY_METHOD hkdf_pkey_meth; +extern const EVP_PKEY_METHOD poly1305_pkey_meth; +extern const EVP_PKEY_METHOD siphash_pkey_meth; + +struct evp_md_st { + int type; + int pkey_type; + int md_size; + unsigned long flags; + int (*init) (EVP_MD_CTX *ctx); + int (*update) (EVP_MD_CTX *ctx, const void *data, size_t count); + int (*final) (EVP_MD_CTX *ctx, unsigned char *md); + int (*copy) (EVP_MD_CTX *to, const EVP_MD_CTX *from); + int (*cleanup) (EVP_MD_CTX *ctx); + int block_size; + int ctx_size; /* how big does the ctx->md_data need to be */ + /* control function */ + int (*md_ctrl) (EVP_MD_CTX *ctx, int cmd, int p1, void *p2); +} /* EVP_MD */ ; + +struct evp_cipher_st { + int nid; + int block_size; + /* Default value for variable length ciphers */ + int key_len; + int iv_len; + /* Various flags */ + unsigned long flags; + /* init key */ + int (*init) (EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); + /* encrypt/decrypt data */ + int (*do_cipher) (EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl); + /* cleanup ctx */ + int (*cleanup) (EVP_CIPHER_CTX *); + /* how big ctx->cipher_data needs to be */ + int ctx_size; + /* Populate a ASN1_TYPE with parameters */ + int (*set_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *); + /* Get parameters from a ASN1_TYPE */ + int (*get_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *); + /* Miscellaneous operations */ + int (*ctrl) (EVP_CIPHER_CTX *, int type, int arg, void *ptr); + /* Application data */ + void *app_data; +} /* EVP_CIPHER */ ; + +/* Macros to code block cipher wrappers */ + +/* Wrapper functions for each cipher mode */ + +#define EVP_C_DATA(kstruct, ctx) \ + ((kstruct *)EVP_CIPHER_CTX_get_cipher_data(ctx)) + +#define BLOCK_CIPHER_ecb_loop() \ + size_t i, bl; \ + bl = EVP_CIPHER_CTX_cipher(ctx)->block_size; \ + if (inl < bl) return 1;\ + inl -= bl; \ + for (i=0; i <= inl; i+=bl) + +#define BLOCK_CIPHER_func_ecb(cname, cprefix, kstruct, ksched) \ +static int cname##_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) \ +{\ + BLOCK_CIPHER_ecb_loop() \ + cprefix##_ecb_encrypt(in + i, out + i, &EVP_C_DATA(kstruct,ctx)->ksched, EVP_CIPHER_CTX_encrypting(ctx)); \ + return 1;\ +} + +#define EVP_MAXCHUNK ((size_t)1<<(sizeof(long)*8-2)) + +#define BLOCK_CIPHER_func_ofb(cname, cprefix, cbits, kstruct, ksched) \ + static int cname##_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) \ +{\ + while(inl>=EVP_MAXCHUNK) {\ + int num = EVP_CIPHER_CTX_num(ctx);\ + cprefix##_ofb##cbits##_encrypt(in, out, (long)EVP_MAXCHUNK, &EVP_C_DATA(kstruct,ctx)->ksched, EVP_CIPHER_CTX_iv_noconst(ctx), &num); \ + EVP_CIPHER_CTX_set_num(ctx, num);\ + inl-=EVP_MAXCHUNK;\ + in +=EVP_MAXCHUNK;\ + out+=EVP_MAXCHUNK;\ + }\ + if (inl) {\ + int num = EVP_CIPHER_CTX_num(ctx);\ + cprefix##_ofb##cbits##_encrypt(in, out, (long)inl, &EVP_C_DATA(kstruct,ctx)->ksched, EVP_CIPHER_CTX_iv_noconst(ctx), &num); \ + EVP_CIPHER_CTX_set_num(ctx, num);\ + }\ + return 1;\ +} + +#define BLOCK_CIPHER_func_cbc(cname, cprefix, kstruct, ksched) \ +static int cname##_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) \ +{\ + while(inl>=EVP_MAXCHUNK) \ + {\ + cprefix##_cbc_encrypt(in, out, (long)EVP_MAXCHUNK, &EVP_C_DATA(kstruct,ctx)->ksched, EVP_CIPHER_CTX_iv_noconst(ctx), EVP_CIPHER_CTX_encrypting(ctx));\ + inl-=EVP_MAXCHUNK;\ + in +=EVP_MAXCHUNK;\ + out+=EVP_MAXCHUNK;\ + }\ + if (inl)\ + cprefix##_cbc_encrypt(in, out, (long)inl, &EVP_C_DATA(kstruct,ctx)->ksched, EVP_CIPHER_CTX_iv_noconst(ctx), EVP_CIPHER_CTX_encrypting(ctx));\ + return 1;\ +} + +#define BLOCK_CIPHER_func_cfb(cname, cprefix, cbits, kstruct, ksched) \ +static int cname##_cfb##cbits##_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) \ +{\ + size_t chunk = EVP_MAXCHUNK;\ + if (cbits == 1) chunk >>= 3;\ + if (inl < chunk) chunk = inl;\ + while (inl && inl >= chunk)\ + {\ + int num = EVP_CIPHER_CTX_num(ctx);\ + cprefix##_cfb##cbits##_encrypt(in, out, (long) \ + ((cbits == 1) \ + && !EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS) \ + ? chunk*8 : chunk), \ + &EVP_C_DATA(kstruct, ctx)->ksched, EVP_CIPHER_CTX_iv_noconst(ctx),\ + &num, EVP_CIPHER_CTX_encrypting(ctx));\ + EVP_CIPHER_CTX_set_num(ctx, num);\ + inl -= chunk;\ + in += chunk;\ + out += chunk;\ + if (inl < chunk) chunk = inl;\ + }\ + return 1;\ +} + +#define BLOCK_CIPHER_all_funcs(cname, cprefix, cbits, kstruct, ksched) \ + BLOCK_CIPHER_func_cbc(cname, cprefix, kstruct, ksched) \ + BLOCK_CIPHER_func_cfb(cname, cprefix, cbits, kstruct, ksched) \ + BLOCK_CIPHER_func_ecb(cname, cprefix, kstruct, ksched) \ + BLOCK_CIPHER_func_ofb(cname, cprefix, cbits, kstruct, ksched) + +#define BLOCK_CIPHER_def1(cname, nmode, mode, MODE, kstruct, nid, block_size, \ + key_len, iv_len, flags, init_key, cleanup, \ + set_asn1, get_asn1, ctrl) \ +static const EVP_CIPHER cname##_##mode = { \ + nid##_##nmode, block_size, key_len, iv_len, \ + flags | EVP_CIPH_##MODE##_MODE, \ + init_key, \ + cname##_##mode##_cipher, \ + cleanup, \ + sizeof(kstruct), \ + set_asn1, get_asn1,\ + ctrl, \ + NULL \ +}; \ +const EVP_CIPHER *EVP_##cname##_##mode(void) { return &cname##_##mode; } + +#define BLOCK_CIPHER_def_cbc(cname, kstruct, nid, block_size, key_len, \ + iv_len, flags, init_key, cleanup, set_asn1, \ + get_asn1, ctrl) \ +BLOCK_CIPHER_def1(cname, cbc, cbc, CBC, kstruct, nid, block_size, key_len, \ + iv_len, flags, init_key, cleanup, set_asn1, get_asn1, ctrl) + +#define BLOCK_CIPHER_def_cfb(cname, kstruct, nid, key_len, \ + iv_len, cbits, flags, init_key, cleanup, \ + set_asn1, get_asn1, ctrl) \ +BLOCK_CIPHER_def1(cname, cfb##cbits, cfb##cbits, CFB, kstruct, nid, 1, \ + key_len, iv_len, flags, init_key, cleanup, set_asn1, \ + get_asn1, ctrl) + +#define BLOCK_CIPHER_def_ofb(cname, kstruct, nid, key_len, \ + iv_len, cbits, flags, init_key, cleanup, \ + set_asn1, get_asn1, ctrl) \ +BLOCK_CIPHER_def1(cname, ofb##cbits, ofb, OFB, kstruct, nid, 1, \ + key_len, iv_len, flags, init_key, cleanup, set_asn1, \ + get_asn1, ctrl) + +#define BLOCK_CIPHER_def_ecb(cname, kstruct, nid, block_size, key_len, \ + flags, init_key, cleanup, set_asn1, \ + get_asn1, ctrl) \ +BLOCK_CIPHER_def1(cname, ecb, ecb, ECB, kstruct, nid, block_size, key_len, \ + 0, flags, init_key, cleanup, set_asn1, get_asn1, ctrl) + +#define BLOCK_CIPHER_defs(cname, kstruct, \ + nid, block_size, key_len, iv_len, cbits, flags, \ + init_key, cleanup, set_asn1, get_asn1, ctrl) \ +BLOCK_CIPHER_def_cbc(cname, kstruct, nid, block_size, key_len, iv_len, flags, \ + init_key, cleanup, set_asn1, get_asn1, ctrl) \ +BLOCK_CIPHER_def_cfb(cname, kstruct, nid, key_len, iv_len, cbits, \ + flags, init_key, cleanup, set_asn1, get_asn1, ctrl) \ +BLOCK_CIPHER_def_ofb(cname, kstruct, nid, key_len, iv_len, cbits, \ + flags, init_key, cleanup, set_asn1, get_asn1, ctrl) \ +BLOCK_CIPHER_def_ecb(cname, kstruct, nid, block_size, key_len, flags, \ + init_key, cleanup, set_asn1, get_asn1, ctrl) + +/*- +#define BLOCK_CIPHER_defs(cname, kstruct, \ + nid, block_size, key_len, iv_len, flags,\ + init_key, cleanup, set_asn1, get_asn1, ctrl)\ +static const EVP_CIPHER cname##_cbc = {\ + nid##_cbc, block_size, key_len, iv_len, \ + flags | EVP_CIPH_CBC_MODE,\ + init_key,\ + cname##_cbc_cipher,\ + cleanup,\ + sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+\ + sizeof((((EVP_CIPHER_CTX *)NULL)->c.kstruct)),\ + set_asn1, get_asn1,\ + ctrl, \ + NULL \ +};\ +const EVP_CIPHER *EVP_##cname##_cbc(void) { return &cname##_cbc; }\ +static const EVP_CIPHER cname##_cfb = {\ + nid##_cfb64, 1, key_len, iv_len, \ + flags | EVP_CIPH_CFB_MODE,\ + init_key,\ + cname##_cfb_cipher,\ + cleanup,\ + sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+\ + sizeof((((EVP_CIPHER_CTX *)NULL)->c.kstruct)),\ + set_asn1, get_asn1,\ + ctrl,\ + NULL \ +};\ +const EVP_CIPHER *EVP_##cname##_cfb(void) { return &cname##_cfb; }\ +static const EVP_CIPHER cname##_ofb = {\ + nid##_ofb64, 1, key_len, iv_len, \ + flags | EVP_CIPH_OFB_MODE,\ + init_key,\ + cname##_ofb_cipher,\ + cleanup,\ + sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+\ + sizeof((((EVP_CIPHER_CTX *)NULL)->c.kstruct)),\ + set_asn1, get_asn1,\ + ctrl,\ + NULL \ +};\ +const EVP_CIPHER *EVP_##cname##_ofb(void) { return &cname##_ofb; }\ +static const EVP_CIPHER cname##_ecb = {\ + nid##_ecb, block_size, key_len, iv_len, \ + flags | EVP_CIPH_ECB_MODE,\ + init_key,\ + cname##_ecb_cipher,\ + cleanup,\ + sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+\ + sizeof((((EVP_CIPHER_CTX *)NULL)->c.kstruct)),\ + set_asn1, get_asn1,\ + ctrl,\ + NULL \ +};\ +const EVP_CIPHER *EVP_##cname##_ecb(void) { return &cname##_ecb; } +*/ + +#define IMPLEMENT_BLOCK_CIPHER(cname, ksched, cprefix, kstruct, nid, \ + block_size, key_len, iv_len, cbits, \ + flags, init_key, \ + cleanup, set_asn1, get_asn1, ctrl) \ + BLOCK_CIPHER_all_funcs(cname, cprefix, cbits, kstruct, ksched) \ + BLOCK_CIPHER_defs(cname, kstruct, nid, block_size, key_len, iv_len, \ + cbits, flags, init_key, cleanup, set_asn1, \ + get_asn1, ctrl) + +#define IMPLEMENT_CFBR(cipher,cprefix,kstruct,ksched,keysize,cbits,iv_len,fl) \ + BLOCK_CIPHER_func_cfb(cipher##_##keysize,cprefix,cbits,kstruct,ksched) \ + BLOCK_CIPHER_def_cfb(cipher##_##keysize,kstruct, \ + NID_##cipher##_##keysize, keysize/8, iv_len, cbits, \ + (fl)|EVP_CIPH_FLAG_DEFAULT_ASN1, \ + cipher##_init_key, NULL, NULL, NULL, NULL) + + +# ifndef OPENSSL_NO_EC + +#define X25519_KEYLEN 32 +#define X448_KEYLEN 56 +#define ED448_KEYLEN 57 + +#define MAX_KEYLEN ED448_KEYLEN + +typedef struct { + unsigned char pubkey[MAX_KEYLEN]; + unsigned char *privkey; +} ECX_KEY; + +#endif + +/* + * Type needs to be a bit field Sub-type needs to be for variations on the + * method, as in, can it do arbitrary encryption.... + */ +struct evp_pkey_st { + int type; + int save_type; + CRYPTO_REF_COUNT references; + const EVP_PKEY_ASN1_METHOD *ameth; + ENGINE *engine; + ENGINE *pmeth_engine; /* If not NULL public key ENGINE to use */ + union { + void *ptr; +# ifndef OPENSSL_NO_RSA + struct rsa_st *rsa; /* RSA */ +# endif +# ifndef OPENSSL_NO_DSA + struct dsa_st *dsa; /* DSA */ +# endif +# ifndef OPENSSL_NO_DH + struct dh_st *dh; /* DH */ +# endif +# ifndef OPENSSL_NO_EC + struct ec_key_st *ec; /* ECC */ + ECX_KEY *ecx; /* X25519, X448, Ed25519, Ed448 */ +# endif + } pkey; + int save_parameters; + STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */ + CRYPTO_RWLOCK *lock; +} /* EVP_PKEY */ ; + + +void openssl_add_all_ciphers_int(void); +void openssl_add_all_digests_int(void); +void evp_cleanup_int(void); +void evp_app_cleanup_int(void); + +/* Pulling defines out of C source files */ + +#define EVP_RC4_KEY_SIZE 16 +#ifndef TLS1_1_VERSION +# define TLS1_1_VERSION 0x0302 +#endif + +void evp_encode_ctx_set_flags(EVP_ENCODE_CTX *ctx, unsigned int flags); + +/* EVP_ENCODE_CTX flags */ +/* Don't generate new lines when encoding */ +#define EVP_ENCODE_CTX_NO_NEWLINES 1 +/* Use the SRP base64 alphabet instead of the standard one */ +#define EVP_ENCODE_CTX_USE_SRP_ALPHABET 2 diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/lhash.h b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/lhash.h new file mode 100644 index 000000000..200ba8685 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/lhash.h @@ -0,0 +1,15 @@ +/* + * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef INTERNAL_LHASH_H +# define INTERNAL_LHASH_H + +unsigned long openssl_lh_strcasehash(const char *); + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/md32_common.h b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/md32_common.h new file mode 100644 index 000000000..1124e9c24 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/md32_common.h @@ -0,0 +1,256 @@ +/* + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * This is a generic 32 bit "collector" for message digest algorithms. + * Whenever needed it collects input character stream into chunks of + * 32 bit values and invokes a block function that performs actual hash + * calculations. + * + * Porting guide. + * + * Obligatory macros: + * + * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN + * this macro defines byte order of input stream. + * HASH_CBLOCK + * size of a unit chunk HASH_BLOCK operates on. + * HASH_LONG + * has to be at least 32 bit wide. + * HASH_CTX + * context structure that at least contains following + * members: + * typedef struct { + * ... + * HASH_LONG Nl,Nh; + * either { + * HASH_LONG data[HASH_LBLOCK]; + * unsigned char data[HASH_CBLOCK]; + * }; + * unsigned int num; + * ... + * } HASH_CTX; + * data[] vector is expected to be zeroed upon first call to + * HASH_UPDATE. + * HASH_UPDATE + * name of "Update" function, implemented here. + * HASH_TRANSFORM + * name of "Transform" function, implemented here. + * HASH_FINAL + * name of "Final" function, implemented here. + * HASH_BLOCK_DATA_ORDER + * name of "block" function capable of treating *unaligned* input + * message in original (data) byte order, implemented externally. + * HASH_MAKE_STRING + * macro converting context variables to an ASCII hash string. + * + * MD5 example: + * + * #define DATA_ORDER_IS_LITTLE_ENDIAN + * + * #define HASH_LONG MD5_LONG + * #define HASH_CTX MD5_CTX + * #define HASH_CBLOCK MD5_CBLOCK + * #define HASH_UPDATE MD5_Update + * #define HASH_TRANSFORM MD5_Transform + * #define HASH_FINAL MD5_Final + * #define HASH_BLOCK_DATA_ORDER md5_block_data_order + */ + +#include + +#if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN) +# error "DATA_ORDER must be defined!" +#endif + +#ifndef HASH_CBLOCK +# error "HASH_CBLOCK must be defined!" +#endif +#ifndef HASH_LONG +# error "HASH_LONG must be defined!" +#endif +#ifndef HASH_CTX +# error "HASH_CTX must be defined!" +#endif + +#ifndef HASH_UPDATE +# error "HASH_UPDATE must be defined!" +#endif +#ifndef HASH_TRANSFORM +# error "HASH_TRANSFORM must be defined!" +#endif +#ifndef HASH_FINAL +# error "HASH_FINAL must be defined!" +#endif + +#ifndef HASH_BLOCK_DATA_ORDER +# error "HASH_BLOCK_DATA_ORDER must be defined!" +#endif + +#define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n)))) + +#if defined(DATA_ORDER_IS_BIG_ENDIAN) + +# define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++))) ) ) +# define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff), \ + l) + +#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) + +# define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<<24) ) +# define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24)&0xff), \ + l) + +#endif + +/* + * Time for some action :-) + */ + +int HASH_UPDATE(HASH_CTX *c, const void *data_, size_t len) +{ + const unsigned char *data = data_; + unsigned char *p; + HASH_LONG l; + size_t n; + + if (len == 0) + return 1; + + l = (c->Nl + (((HASH_LONG) len) << 3)) & 0xffffffffUL; + if (l < c->Nl) /* overflow */ + c->Nh++; + c->Nh += (HASH_LONG) (len >> 29); /* might cause compiler warning on + * 16-bit */ + c->Nl = l; + + n = c->num; + if (n != 0) { + p = (unsigned char *)c->data; + + if (len >= HASH_CBLOCK || len + n >= HASH_CBLOCK) { + memcpy(p + n, data, HASH_CBLOCK - n); + HASH_BLOCK_DATA_ORDER(c, p, 1); + n = HASH_CBLOCK - n; + data += n; + len -= n; + c->num = 0; + /* + * We use memset rather than OPENSSL_cleanse() here deliberately. + * Using OPENSSL_cleanse() here could be a performance issue. It + * will get properly cleansed on finalisation so this isn't a + * security problem. + */ + memset(p, 0, HASH_CBLOCK); /* keep it zeroed */ + } else { + memcpy(p + n, data, len); + c->num += (unsigned int)len; + return 1; + } + } + + n = len / HASH_CBLOCK; + if (n > 0) { + HASH_BLOCK_DATA_ORDER(c, data, n); + n *= HASH_CBLOCK; + data += n; + len -= n; + } + + if (len != 0) { + p = (unsigned char *)c->data; + c->num = (unsigned int)len; + memcpy(p, data, len); + } + return 1; +} + +void HASH_TRANSFORM(HASH_CTX *c, const unsigned char *data) +{ + HASH_BLOCK_DATA_ORDER(c, data, 1); +} + +int HASH_FINAL(unsigned char *md, HASH_CTX *c) +{ + unsigned char *p = (unsigned char *)c->data; + size_t n = c->num; + + p[n] = 0x80; /* there is always room for one */ + n++; + + if (n > (HASH_CBLOCK - 8)) { + memset(p + n, 0, HASH_CBLOCK - n); + n = 0; + HASH_BLOCK_DATA_ORDER(c, p, 1); + } + memset(p + n, 0, HASH_CBLOCK - 8 - n); + + p += HASH_CBLOCK - 8; +#if defined(DATA_ORDER_IS_BIG_ENDIAN) + (void)HOST_l2c(c->Nh, p); + (void)HOST_l2c(c->Nl, p); +#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) + (void)HOST_l2c(c->Nl, p); + (void)HOST_l2c(c->Nh, p); +#endif + p -= HASH_CBLOCK; + HASH_BLOCK_DATA_ORDER(c, p, 1); + c->num = 0; + OPENSSL_cleanse(p, HASH_CBLOCK); + +#ifndef HASH_MAKE_STRING +# error "HASH_MAKE_STRING must be defined!" +#else + HASH_MAKE_STRING(c, md); +#endif + + return 1; +} + +#ifndef MD32_REG_T +# if defined(__alpha) || defined(__sparcv9) || defined(__mips) +# define MD32_REG_T long +/* + * This comment was originally written for MD5, which is why it + * discusses A-D. But it basically applies to all 32-bit digests, + * which is why it was moved to common header file. + * + * In case you wonder why A-D are declared as long and not + * as MD5_LONG. Doing so results in slight performance + * boost on LP64 architectures. The catch is we don't + * really care if 32 MSBs of a 64-bit register get polluted + * with eventual overflows as we *save* only 32 LSBs in + * *either* case. Now declaring 'em long excuses the compiler + * from keeping 32 MSBs zeroed resulting in 13% performance + * improvement under SPARC Solaris7/64 and 5% under AlphaLinux. + * Well, to be honest it should say that this *prevents* + * performance degradation. + */ +# else +/* + * Above is not absolute and there are LP64 compilers that + * generate better code if MD32_REG_T is defined int. The above + * pre-processor condition reflects the circumstances under which + * the conclusion was made and is subject to further extension. + */ +# define MD32_REG_T int +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/objects.h b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/objects.h new file mode 100644 index 000000000..76e1b4d98 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/objects.h @@ -0,0 +1,12 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +void obj_cleanup_int(void); diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/poly1305.h b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/poly1305.h new file mode 100644 index 000000000..5fef239d0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/poly1305.h @@ -0,0 +1,21 @@ +/* + * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#define POLY1305_BLOCK_SIZE 16 +#define POLY1305_DIGEST_SIZE 16 +#define POLY1305_KEY_SIZE 32 + +typedef struct poly1305_context POLY1305; + +size_t Poly1305_ctx_size(void); +void Poly1305_Init(POLY1305 *ctx, const unsigned char key[32]); +void Poly1305_Update(POLY1305 *ctx, const unsigned char *inp, size_t len); +void Poly1305_Final(POLY1305 *ctx, unsigned char mac[16]); diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/rand_int.h b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/rand_int.h new file mode 100644 index 000000000..888cab1b8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/rand_int.h @@ -0,0 +1,134 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Licensed under the OpenSSL licenses, (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * https://www.openssl.org/source/license.html + * or in the file LICENSE in the source distribution. + */ + +#ifndef HEADER_RAND_INT_H +# define HEADER_RAND_INT_H + +# include + +/* forward declaration */ +typedef struct rand_pool_st RAND_POOL; + +void rand_cleanup_int(void); +void rand_drbg_cleanup_int(void); +void drbg_delete_thread_state(void); +void rand_fork(void); + +/* Hardware-based seeding functions. */ +size_t rand_acquire_entropy_from_tsc(RAND_POOL *pool); +size_t rand_acquire_entropy_from_cpu(RAND_POOL *pool); + +/* DRBG entropy callbacks. */ +size_t rand_drbg_get_entropy(RAND_DRBG *drbg, + unsigned char **pout, + int entropy, size_t min_len, size_t max_len, + int prediction_resistance); +void rand_drbg_cleanup_entropy(RAND_DRBG *drbg, + unsigned char *out, size_t outlen); +size_t rand_drbg_get_nonce(RAND_DRBG *drbg, + unsigned char **pout, + int entropy, size_t min_len, size_t max_len); +void rand_drbg_cleanup_nonce(RAND_DRBG *drbg, + unsigned char *out, size_t outlen); + +size_t rand_drbg_get_additional_data(RAND_POOL *pool, unsigned char **pout); + +void rand_drbg_cleanup_additional_data(RAND_POOL *pool, unsigned char *out); + +/* + * RAND_POOL functions + */ +RAND_POOL *rand_pool_new(int entropy_requested, size_t min_len, size_t max_len); +RAND_POOL *rand_pool_attach(const unsigned char *buffer, size_t len, + size_t entropy); +void rand_pool_free(RAND_POOL *pool); + +const unsigned char *rand_pool_buffer(RAND_POOL *pool); +unsigned char *rand_pool_detach(RAND_POOL *pool); +void rand_pool_reattach(RAND_POOL *pool, unsigned char *buffer); + +size_t rand_pool_entropy(RAND_POOL *pool); +size_t rand_pool_length(RAND_POOL *pool); + +size_t rand_pool_entropy_available(RAND_POOL *pool); +size_t rand_pool_entropy_needed(RAND_POOL *pool); +/* |entropy_factor| expresses how many bits of data contain 1 bit of entropy */ +size_t rand_pool_bytes_needed(RAND_POOL *pool, unsigned int entropy_factor); +size_t rand_pool_bytes_remaining(RAND_POOL *pool); + +int rand_pool_add(RAND_POOL *pool, + const unsigned char *buffer, size_t len, size_t entropy); +unsigned char *rand_pool_add_begin(RAND_POOL *pool, size_t len); +int rand_pool_add_end(RAND_POOL *pool, size_t len, size_t entropy); + + +/* + * Add random bytes to the pool to acquire requested amount of entropy + * + * This function is platform specific and tries to acquire the requested + * amount of entropy by polling platform specific entropy sources. + * + * If the function succeeds in acquiring at least |entropy_requested| bits + * of entropy, the total entropy count is returned. If it fails, it returns + * an entropy count of 0. + */ +size_t rand_pool_acquire_entropy(RAND_POOL *pool); + +/* + * Add some application specific nonce data + * + * This function is platform specific and adds some application specific + * data to the nonce used for instantiating the drbg. + * + * This data currently consists of the process and thread id, and a high + * resolution timestamp. The data does not include an atomic counter, + * because that is added by the calling function rand_drbg_get_nonce(). + * + * Returns 1 on success and 0 on failure. + */ +int rand_pool_add_nonce_data(RAND_POOL *pool); + + +/* + * Add some platform specific additional data + * + * This function is platform specific and adds some random noise to the + * additional data used for generating random bytes and for reseeding + * the drbg. + * + * Returns 1 on success and 0 on failure. + */ +int rand_pool_add_additional_data(RAND_POOL *pool); + +/* + * Initialise the random pool reseeding sources. + * + * Returns 1 on success and 0 on failure. + */ +int rand_pool_init(void); + +/* + * Finalise the random pool reseeding sources. + */ +void rand_pool_cleanup(void); + +/* + * Control the random pool use of open file descriptors. + */ +void rand_pool_keep_random_devices_open(int keep); + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/sha.h b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/sha.h new file mode 100644 index 000000000..458a75e89 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/sha.h @@ -0,0 +1,19 @@ +/* + * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_INTERNAL_SHA_H +# define HEADER_INTERNAL_SHA_H + +# include + +int sha512_224_init(SHA512_CTX *); +int sha512_256_init(SHA512_CTX *); + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/siphash.h b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/siphash.h new file mode 100644 index 000000000..9573680f0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/siphash.h @@ -0,0 +1,25 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#define SIPHASH_BLOCK_SIZE 8 +#define SIPHASH_KEY_SIZE 16 +#define SIPHASH_MIN_DIGEST_SIZE 8 +#define SIPHASH_MAX_DIGEST_SIZE 16 + +typedef struct siphash_st SIPHASH; + +size_t SipHash_ctx_size(void); +size_t SipHash_hash_size(SIPHASH *ctx); +int SipHash_set_hash_size(SIPHASH *ctx, size_t hash_size); +int SipHash_Init(SIPHASH *ctx, const unsigned char *k, + int crounds, int drounds); +void SipHash_Update(SIPHASH *ctx, const unsigned char *in, size_t inlen); +int SipHash_Final(SIPHASH *ctx, unsigned char *out, size_t outlen); diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/sm2.h b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/sm2.h new file mode 100644 index 000000000..5c5cd4b4f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/sm2.h @@ -0,0 +1,78 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017 Ribose Inc. All Rights Reserved. + * Ported from Ribose contributions from Botan. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_SM2_H +# define HEADER_SM2_H +# include + +# ifndef OPENSSL_NO_SM2 + +# include + +/* The default user id as specified in GM/T 0009-2012 */ +# define SM2_DEFAULT_USERID "1234567812345678" + +int sm2_compute_z_digest(uint8_t *out, + const EVP_MD *digest, + const uint8_t *id, + const size_t id_len, + const EC_KEY *key); + +/* + * SM2 signature operation. Computes Z and then signs H(Z || msg) using SM2 + */ +ECDSA_SIG *sm2_do_sign(const EC_KEY *key, + const EVP_MD *digest, + const uint8_t *id, + const size_t id_len, + const uint8_t *msg, size_t msg_len); + +int sm2_do_verify(const EC_KEY *key, + const EVP_MD *digest, + const ECDSA_SIG *signature, + const uint8_t *id, + const size_t id_len, + const uint8_t *msg, size_t msg_len); + +/* + * SM2 signature generation. + */ +int sm2_sign(const unsigned char *dgst, int dgstlen, + unsigned char *sig, unsigned int *siglen, EC_KEY *eckey); + +/* + * SM2 signature verification. + */ +int sm2_verify(const unsigned char *dgst, int dgstlen, + const unsigned char *sig, int siglen, EC_KEY *eckey); + +/* + * SM2 encryption + */ +int sm2_ciphertext_size(const EC_KEY *key, const EVP_MD *digest, size_t msg_len, + size_t *ct_size); + +int sm2_plaintext_size(const EC_KEY *key, const EVP_MD *digest, size_t msg_len, + size_t *pt_size); + +int sm2_encrypt(const EC_KEY *key, + const EVP_MD *digest, + const uint8_t *msg, + size_t msg_len, + uint8_t *ciphertext_buf, size_t *ciphertext_len); + +int sm2_decrypt(const EC_KEY *key, + const EVP_MD *digest, + const uint8_t *ciphertext, + size_t ciphertext_len, uint8_t *ptext_buf, size_t *ptext_len); + +# endif /* OPENSSL_NO_SM2 */ +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/sm2err.h b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/sm2err.h new file mode 100644 index 000000000..a4db1b73d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/sm2err.h @@ -0,0 +1,61 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_SM2ERR_H +# define HEADER_SM2ERR_H + +# include + +# ifndef OPENSSL_NO_SM2 + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_SM2_strings(void); + +/* + * SM2 function codes. + */ +# define SM2_F_PKEY_SM2_COPY 115 +# define SM2_F_PKEY_SM2_CTRL 109 +# define SM2_F_PKEY_SM2_CTRL_STR 110 +# define SM2_F_PKEY_SM2_DIGEST_CUSTOM 114 +# define SM2_F_PKEY_SM2_INIT 111 +# define SM2_F_PKEY_SM2_SIGN 112 +# define SM2_F_SM2_COMPUTE_MSG_HASH 100 +# define SM2_F_SM2_COMPUTE_USERID_DIGEST 101 +# define SM2_F_SM2_COMPUTE_Z_DIGEST 113 +# define SM2_F_SM2_DECRYPT 102 +# define SM2_F_SM2_ENCRYPT 103 +# define SM2_F_SM2_PLAINTEXT_SIZE 104 +# define SM2_F_SM2_SIGN 105 +# define SM2_F_SM2_SIG_GEN 106 +# define SM2_F_SM2_SIG_VERIFY 107 +# define SM2_F_SM2_VERIFY 108 + +/* + * SM2 reason codes. + */ +# define SM2_R_ASN1_ERROR 100 +# define SM2_R_BAD_SIGNATURE 101 +# define SM2_R_BUFFER_TOO_SMALL 107 +# define SM2_R_DIST_ID_TOO_LARGE 110 +# define SM2_R_ID_NOT_SET 112 +# define SM2_R_ID_TOO_LARGE 111 +# define SM2_R_INVALID_CURVE 108 +# define SM2_R_INVALID_DIGEST 102 +# define SM2_R_INVALID_DIGEST_TYPE 103 +# define SM2_R_INVALID_ENCODING 104 +# define SM2_R_INVALID_FIELD 105 +# define SM2_R_NO_PARAMETERS_SET 109 +# define SM2_R_USER_ID_TOO_LARGE 106 + +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/sm3.h b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/sm3.h new file mode 100644 index 000000000..27eb471c2 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/sm3.h @@ -0,0 +1,39 @@ +/* + * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017 Ribose Inc. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_SM3_H +# define HEADER_SM3_H + +# include + +# ifdef OPENSSL_NO_SM3 +# error SM3 is disabled. +# endif + +# define SM3_DIGEST_LENGTH 32 +# define SM3_WORD unsigned int + +# define SM3_CBLOCK 64 +# define SM3_LBLOCK (SM3_CBLOCK/4) + +typedef struct SM3state_st { + SM3_WORD A, B, C, D, E, F, G, H; + SM3_WORD Nl, Nh; + SM3_WORD data[SM3_LBLOCK]; + unsigned int num; +} SM3_CTX; + +int sm3_init(SM3_CTX *c); +int sm3_update(SM3_CTX *c, const void *data, size_t len); +int sm3_final(unsigned char *md, SM3_CTX *c); + +void sm3_block_data_order(SM3_CTX *c, const void *p, size_t num); + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/sm4.h b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/sm4.h new file mode 100644 index 000000000..f1f157ef5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/sm4.h @@ -0,0 +1,37 @@ +/* + * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017 Ribose Inc. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_SM4_H +# define HEADER_SM4_H + +# include +# include + +# ifdef OPENSSL_NO_SM4 +# error SM4 is disabled. +# endif + +# define SM4_ENCRYPT 1 +# define SM4_DECRYPT 0 + +# define SM4_BLOCK_SIZE 16 +# define SM4_KEY_SCHEDULE 32 + +typedef struct SM4_KEY_st { + uint32_t rk[SM4_KEY_SCHEDULE]; +} SM4_KEY; + +int SM4_set_key(const uint8_t *key, SM4_KEY *ks); + +void SM4_encrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks); + +void SM4_decrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks); + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/store.h b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/store.h new file mode 100644 index 000000000..f5013dc36 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/store.h @@ -0,0 +1,10 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +void ossl_store_cleanup_int(void); diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/store_int.h b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/store_int.h new file mode 100644 index 000000000..6f31e019e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/store_int.h @@ -0,0 +1,26 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_STORE_INT_H +# define HEADER_STORE_INT_H + +# include +# include +# include + +/* + * Two functions to read PEM data off an already opened BIO. To be used + * instead of OSSLSTORE_open() and OSSLSTORE_close(). Everything is done + * as usual with OSSLSTORE_load() and OSSLSTORE_eof(). + */ +OSSL_STORE_CTX *ossl_store_attach_pem_bio(BIO *bp, const UI_METHOD *ui_method, + void *ui_data); +int ossl_store_detach_pem_bio(OSSL_STORE_CTX *ctx); + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/x509_int.h b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/x509_int.h new file mode 100644 index 000000000..b53c2b03c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/include/internal/x509_int.h @@ -0,0 +1,286 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/refcount.h" + +/* Internal X509 structures and functions: not for application use */ + +/* Note: unless otherwise stated a field pointer is mandatory and should + * never be set to NULL: the ASN.1 code and accessors rely on mandatory + * fields never being NULL. + */ + +/* + * name entry structure, equivalent to AttributeTypeAndValue defined + * in RFC5280 et al. + */ +struct X509_name_entry_st { + ASN1_OBJECT *object; /* AttributeType */ + ASN1_STRING *value; /* AttributeValue */ + int set; /* index of RDNSequence for this entry */ + int size; /* temp variable */ +}; + +/* Name from RFC 5280. */ +struct X509_name_st { + STACK_OF(X509_NAME_ENTRY) *entries; /* DN components */ + int modified; /* true if 'bytes' needs to be built */ + BUF_MEM *bytes; /* cached encoding: cannot be NULL */ + /* canonical encoding used for rapid Name comparison */ + unsigned char *canon_enc; + int canon_enclen; +} /* X509_NAME */ ; + +/* Signature info structure */ + +struct x509_sig_info_st { + /* NID of message digest */ + int mdnid; + /* NID of public key algorithm */ + int pknid; + /* Security bits */ + int secbits; + /* Various flags */ + uint32_t flags; +}; + +/* PKCS#10 certificate request */ + +struct X509_req_info_st { + ASN1_ENCODING enc; /* cached encoding of signed part */ + ASN1_INTEGER *version; /* version, defaults to v1(0) so can be NULL */ + X509_NAME *subject; /* certificate request DN */ + X509_PUBKEY *pubkey; /* public key of request */ + /* + * Zero or more attributes. + * NB: although attributes is a mandatory field some broken + * encodings omit it so this may be NULL in that case. + */ + STACK_OF(X509_ATTRIBUTE) *attributes; +}; + +struct X509_req_st { + X509_REQ_INFO req_info; /* signed certificate request data */ + X509_ALGOR sig_alg; /* signature algorithm */ + ASN1_BIT_STRING *signature; /* signature */ + CRYPTO_REF_COUNT references; + CRYPTO_RWLOCK *lock; +}; + +struct X509_crl_info_st { + ASN1_INTEGER *version; /* version: defaults to v1(0) so may be NULL */ + X509_ALGOR sig_alg; /* signature algorithm */ + X509_NAME *issuer; /* CRL issuer name */ + ASN1_TIME *lastUpdate; /* lastUpdate field */ + ASN1_TIME *nextUpdate; /* nextUpdate field: optional */ + STACK_OF(X509_REVOKED) *revoked; /* revoked entries: optional */ + STACK_OF(X509_EXTENSION) *extensions; /* extensions: optional */ + ASN1_ENCODING enc; /* encoding of signed portion of CRL */ +}; + +struct X509_crl_st { + X509_CRL_INFO crl; /* signed CRL data */ + X509_ALGOR sig_alg; /* CRL signature algorithm */ + ASN1_BIT_STRING signature; /* CRL signature */ + CRYPTO_REF_COUNT references; + int flags; + /* + * Cached copies of decoded extension values, since extensions + * are optional any of these can be NULL. + */ + AUTHORITY_KEYID *akid; + ISSUING_DIST_POINT *idp; + /* Convenient breakdown of IDP */ + int idp_flags; + int idp_reasons; + /* CRL and base CRL numbers for delta processing */ + ASN1_INTEGER *crl_number; + ASN1_INTEGER *base_crl_number; + STACK_OF(GENERAL_NAMES) *issuers; + /* hash of CRL */ + unsigned char sha1_hash[SHA_DIGEST_LENGTH]; + /* alternative method to handle this CRL */ + const X509_CRL_METHOD *meth; + void *meth_data; + CRYPTO_RWLOCK *lock; +}; + +struct x509_revoked_st { + ASN1_INTEGER serialNumber; /* revoked entry serial number */ + ASN1_TIME *revocationDate; /* revocation date */ + STACK_OF(X509_EXTENSION) *extensions; /* CRL entry extensions: optional */ + /* decoded value of CRLissuer extension: set if indirect CRL */ + STACK_OF(GENERAL_NAME) *issuer; + /* revocation reason: set to CRL_REASON_NONE if reason extension absent */ + int reason; + /* + * CRL entries are reordered for faster lookup of serial numbers. This + * field contains the original load sequence for this entry. + */ + int sequence; +}; + +/* + * This stuff is certificate "auxiliary info": it contains details which are + * useful in certificate stores and databases. When used this is tagged onto + * the end of the certificate itself. OpenSSL specific structure not defined + * in any RFC. + */ + +struct x509_cert_aux_st { + STACK_OF(ASN1_OBJECT) *trust; /* trusted uses */ + STACK_OF(ASN1_OBJECT) *reject; /* rejected uses */ + ASN1_UTF8STRING *alias; /* "friendly name" */ + ASN1_OCTET_STRING *keyid; /* key id of private key */ + STACK_OF(X509_ALGOR) *other; /* other unspecified info */ +}; + +struct x509_cinf_st { + ASN1_INTEGER *version; /* [ 0 ] default of v1 */ + ASN1_INTEGER serialNumber; + X509_ALGOR signature; + X509_NAME *issuer; + X509_VAL validity; + X509_NAME *subject; + X509_PUBKEY *key; + ASN1_BIT_STRING *issuerUID; /* [ 1 ] optional in v2 */ + ASN1_BIT_STRING *subjectUID; /* [ 2 ] optional in v2 */ + STACK_OF(X509_EXTENSION) *extensions; /* [ 3 ] optional in v3 */ + ASN1_ENCODING enc; +}; + +struct x509_st { + X509_CINF cert_info; + X509_ALGOR sig_alg; + ASN1_BIT_STRING signature; + X509_SIG_INFO siginf; + CRYPTO_REF_COUNT references; + CRYPTO_EX_DATA ex_data; + /* These contain copies of various extension values */ + long ex_pathlen; + long ex_pcpathlen; + uint32_t ex_flags; + uint32_t ex_kusage; + uint32_t ex_xkusage; + uint32_t ex_nscert; + ASN1_OCTET_STRING *skid; + AUTHORITY_KEYID *akid; + X509_POLICY_CACHE *policy_cache; + STACK_OF(DIST_POINT) *crldp; + STACK_OF(GENERAL_NAME) *altname; + NAME_CONSTRAINTS *nc; +#ifndef OPENSSL_NO_RFC3779 + STACK_OF(IPAddressFamily) *rfc3779_addr; + struct ASIdentifiers_st *rfc3779_asid; +# endif + unsigned char sha1_hash[SHA_DIGEST_LENGTH]; + X509_CERT_AUX *aux; + CRYPTO_RWLOCK *lock; + volatile int ex_cached; +} /* X509 */ ; + +/* + * This is a used when verifying cert chains. Since the gathering of the + * cert chain can take some time (and have to be 'retried', this needs to be + * kept and passed around. + */ +struct x509_store_ctx_st { /* X509_STORE_CTX */ + X509_STORE *ctx; + /* The following are set by the caller */ + /* The cert to check */ + X509 *cert; + /* chain of X509s - untrusted - passed in */ + STACK_OF(X509) *untrusted; + /* set of CRLs passed in */ + STACK_OF(X509_CRL) *crls; + X509_VERIFY_PARAM *param; + /* Other info for use with get_issuer() */ + void *other_ctx; + /* Callbacks for various operations */ + /* called to verify a certificate */ + int (*verify) (X509_STORE_CTX *ctx); + /* error callback */ + int (*verify_cb) (int ok, X509_STORE_CTX *ctx); + /* get issuers cert from ctx */ + int (*get_issuer) (X509 **issuer, X509_STORE_CTX *ctx, X509 *x); + /* check issued */ + int (*check_issued) (X509_STORE_CTX *ctx, X509 *x, X509 *issuer); + /* Check revocation status of chain */ + int (*check_revocation) (X509_STORE_CTX *ctx); + /* retrieve CRL */ + int (*get_crl) (X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x); + /* Check CRL validity */ + int (*check_crl) (X509_STORE_CTX *ctx, X509_CRL *crl); + /* Check certificate against CRL */ + int (*cert_crl) (X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); + /* Check policy status of the chain */ + int (*check_policy) (X509_STORE_CTX *ctx); + STACK_OF(X509) *(*lookup_certs) (X509_STORE_CTX *ctx, X509_NAME *nm); + STACK_OF(X509_CRL) *(*lookup_crls) (X509_STORE_CTX *ctx, X509_NAME *nm); + int (*cleanup) (X509_STORE_CTX *ctx); + /* The following is built up */ + /* if 0, rebuild chain */ + int valid; + /* number of untrusted certs */ + int num_untrusted; + /* chain of X509s - built up and trusted */ + STACK_OF(X509) *chain; + /* Valid policy tree */ + X509_POLICY_TREE *tree; + /* Require explicit policy value */ + int explicit_policy; + /* When something goes wrong, this is why */ + int error_depth; + int error; + X509 *current_cert; + /* cert currently being tested as valid issuer */ + X509 *current_issuer; + /* current CRL */ + X509_CRL *current_crl; + /* score of current CRL */ + int current_crl_score; + /* Reason mask */ + unsigned int current_reasons; + /* For CRL path validation: parent context */ + X509_STORE_CTX *parent; + CRYPTO_EX_DATA ex_data; + SSL_DANE *dane; + /* signed via bare TA public key, rather than CA certificate */ + int bare_ta_signed; +}; + +/* PKCS#8 private key info structure */ + +struct pkcs8_priv_key_info_st { + ASN1_INTEGER *version; + X509_ALGOR *pkeyalg; + ASN1_OCTET_STRING *pkey; + STACK_OF(X509_ATTRIBUTE) *attributes; +}; + +struct X509_sig_st { + X509_ALGOR *algor; + ASN1_OCTET_STRING *digest; +}; + +struct x509_object_st { + /* one of the above types */ + X509_LOOKUP_TYPE type; + union { + char *ptr; + X509 *x509; + X509_CRL *crl; + EVP_PKEY *pkey; + } data; +}; + +int a2i_ipadd(unsigned char *ipout, const char *ipasc); +int x509_set1_time(ASN1_TIME **ptm, const ASN1_TIME *tm); + +void x509_init_sig_info(X509 *x); diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/init.c b/trunk/3rdparty/openssl-1.1-fit/crypto/init.c new file mode 100644 index 000000000..b9a7334a7 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/init.c @@ -0,0 +1,854 @@ +/* + * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "e_os.h" +#include "internal/cryptlib_int.h" +#include +#include "internal/rand_int.h" +#include "internal/bio.h" +#include +#include "internal/evp_int.h" +#include "internal/conf.h" +#include "internal/async.h" +#include "internal/engine.h" +#include "internal/comp.h" +#include "internal/err.h" +#include "internal/err_int.h" +#include "internal/objects.h" +#include +#include +#include "internal/thread_once.h" +#include "internal/dso_conf.h" +#include "internal/dso.h" +#include "internal/store.h" + +static int stopped = 0; + +/* + * Since per-thread-specific-data destructors are not universally + * available, i.e. not on Windows, only below CRYPTO_THREAD_LOCAL key + * is assumed to have destructor associated. And then an effort is made + * to call this single destructor on non-pthread platform[s]. + * + * Initial value is "impossible". It is used as guard value to shortcut + * destructor for threads terminating before libcrypto is initialized or + * after it's de-initialized. Access to the key doesn't have to be + * serialized for the said threads, because they didn't use libcrypto + * and it doesn't matter if they pick "impossible" or derefernce real + * key value and pull NULL past initialization in the first thread that + * intends to use libcrypto. + */ +static union { + long sane; + CRYPTO_THREAD_LOCAL value; +} destructor_key = { -1 }; + +static void ossl_init_thread_stop(struct thread_local_inits_st *locals); + +static void ossl_init_thread_destructor(void *local) +{ + ossl_init_thread_stop((struct thread_local_inits_st *)local); +} + +static struct thread_local_inits_st *ossl_init_get_thread_local(int alloc) +{ + struct thread_local_inits_st *local = + CRYPTO_THREAD_get_local(&destructor_key.value); + + if (alloc) { + if (local == NULL + && (local = OPENSSL_zalloc(sizeof(*local))) != NULL + && !CRYPTO_THREAD_set_local(&destructor_key.value, local)) { + OPENSSL_free(local); + return NULL; + } + } else { + CRYPTO_THREAD_set_local(&destructor_key.value, NULL); + } + + return local; +} + +typedef struct ossl_init_stop_st OPENSSL_INIT_STOP; +struct ossl_init_stop_st { + void (*handler)(void); + OPENSSL_INIT_STOP *next; +}; + +static OPENSSL_INIT_STOP *stop_handlers = NULL; +static CRYPTO_RWLOCK *init_lock = NULL; + +static CRYPTO_ONCE base = CRYPTO_ONCE_STATIC_INIT; +static int base_inited = 0; +DEFINE_RUN_ONCE_STATIC(ossl_init_base) +{ + CRYPTO_THREAD_LOCAL key; + +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_base: Setting up stop handlers\n"); +#endif +#ifndef OPENSSL_NO_CRYPTO_MDEBUG + ossl_malloc_setup_failures(); +#endif + if (!CRYPTO_THREAD_init_local(&key, ossl_init_thread_destructor)) + return 0; + if ((init_lock = CRYPTO_THREAD_lock_new()) == NULL) + goto err; + OPENSSL_cpuid_setup(); + + destructor_key.value = key; + base_inited = 1; + return 1; + +err: +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_base not ok!\n"); +#endif + CRYPTO_THREAD_lock_free(init_lock); + init_lock = NULL; + + CRYPTO_THREAD_cleanup_local(&key); + return 0; +} + +static CRYPTO_ONCE register_atexit = CRYPTO_ONCE_STATIC_INIT; +#if !defined(OPENSSL_SYS_UEFI) && defined(_WIN32) +static int win32atexit(void) +{ + OPENSSL_cleanup(); + return 0; +} +#endif + +DEFINE_RUN_ONCE_STATIC(ossl_init_register_atexit) +{ +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_register_atexit()\n"); +#endif +#ifndef OPENSSL_SYS_UEFI +# ifdef _WIN32 + /* We use _onexit() in preference because it gets called on DLL unload */ + if (_onexit(win32atexit) == NULL) + return 0; +# else + if (atexit(OPENSSL_cleanup) != 0) + return 0; +# endif +#endif + + return 1; +} + +DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_register_atexit, + ossl_init_register_atexit) +{ +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_no_register_atexit ok!\n"); +#endif + /* Do nothing in this case */ + return 1; +} + +static CRYPTO_ONCE load_crypto_nodelete = CRYPTO_ONCE_STATIC_INIT; +DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_nodelete) +{ +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_load_crypto_nodelete()\n"); +#endif +#if !defined(OPENSSL_NO_DSO) \ + && !defined(OPENSSL_USE_NODELETE) \ + && !defined(OPENSSL_NO_PINSHARED) +# ifdef DSO_WIN32 + { + HMODULE handle = NULL; + BOOL ret; + + /* We don't use the DSO route for WIN32 because there is a better way */ + ret = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS + | GET_MODULE_HANDLE_EX_FLAG_PIN, + (void *)&base_inited, &handle); + +# ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: obtained DSO reference? %s\n", + (ret == TRUE ? "No!" : "Yes.")); +# endif + return (ret == TRUE) ? 1 : 0; + } +# else + /* + * Deliberately leak a reference to ourselves. This will force the library + * to remain loaded until the atexit() handler is run at process exit. + */ + { + DSO *dso; + void *err; + + if (!err_shelve_state(&err)) + return 0; + + dso = DSO_dsobyaddr(&base_inited, DSO_FLAG_NO_UNLOAD_ON_FREE); +# ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: obtained DSO reference? %s\n", + (dso == NULL ? "No!" : "Yes.")); + /* + * In case of No!, it is uncertain our exit()-handlers can still be + * called. After dlclose() the whole library might have been unloaded + * already. + */ +# endif + DSO_free(dso); + err_unshelve_state(err); + } +# endif +#endif + + return 1; +} + +static CRYPTO_ONCE load_crypto_strings = CRYPTO_ONCE_STATIC_INIT; +static int load_crypto_strings_inited = 0; +DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_strings) +{ + int ret = 1; + /* + * OPENSSL_NO_AUTOERRINIT is provided here to prevent at compile time + * pulling in all the error strings during static linking + */ +#if !defined(OPENSSL_NO_ERR) && !defined(OPENSSL_NO_AUTOERRINIT) +# ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_load_crypto_strings: " + "err_load_crypto_strings_int()\n"); +# endif + ret = err_load_crypto_strings_int(); + load_crypto_strings_inited = 1; +#endif + return ret; +} + +DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_load_crypto_strings, + ossl_init_load_crypto_strings) +{ + /* Do nothing in this case */ + return 1; +} + +static CRYPTO_ONCE add_all_ciphers = CRYPTO_ONCE_STATIC_INIT; +DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_ciphers) +{ + /* + * OPENSSL_NO_AUTOALGINIT is provided here to prevent at compile time + * pulling in all the ciphers during static linking + */ +#ifndef OPENSSL_NO_AUTOALGINIT +# ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_add_all_ciphers: " + "openssl_add_all_ciphers_int()\n"); +# endif + openssl_add_all_ciphers_int(); +#endif + return 1; +} + +DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_add_all_ciphers, + ossl_init_add_all_ciphers) +{ + /* Do nothing */ + return 1; +} + +static CRYPTO_ONCE add_all_digests = CRYPTO_ONCE_STATIC_INIT; +DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_digests) +{ + /* + * OPENSSL_NO_AUTOALGINIT is provided here to prevent at compile time + * pulling in all the ciphers during static linking + */ +#ifndef OPENSSL_NO_AUTOALGINIT +# ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_add_all_digests: " + "openssl_add_all_digests()\n"); +# endif + openssl_add_all_digests_int(); +#endif + return 1; +} + +DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_add_all_digests, + ossl_init_add_all_digests) +{ + /* Do nothing */ + return 1; +} + +static CRYPTO_ONCE config = CRYPTO_ONCE_STATIC_INIT; +static int config_inited = 0; +static const OPENSSL_INIT_SETTINGS *conf_settings = NULL; +DEFINE_RUN_ONCE_STATIC(ossl_init_config) +{ + int ret = openssl_config_int(conf_settings); + config_inited = 1; + return ret; +} +DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_config, ossl_init_config) +{ +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, + "OPENSSL_INIT: ossl_init_config: openssl_no_config_int()\n"); +#endif + openssl_no_config_int(); + config_inited = 1; + return 1; +} + +static CRYPTO_ONCE async = CRYPTO_ONCE_STATIC_INIT; +static int async_inited = 0; +DEFINE_RUN_ONCE_STATIC(ossl_init_async) +{ +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_async: async_init()\n"); +#endif + if (!async_init()) + return 0; + async_inited = 1; + return 1; +} + +#ifndef OPENSSL_NO_ENGINE +static CRYPTO_ONCE engine_openssl = CRYPTO_ONCE_STATIC_INIT; +DEFINE_RUN_ONCE_STATIC(ossl_init_engine_openssl) +{ +# ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_openssl: " + "engine_load_openssl_int()\n"); +# endif + engine_load_openssl_int(); + return 1; +} +# ifndef OPENSSL_NO_DEVCRYPTOENG +static CRYPTO_ONCE engine_devcrypto = CRYPTO_ONCE_STATIC_INIT; +DEFINE_RUN_ONCE_STATIC(ossl_init_engine_devcrypto) +{ +# ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_devcrypto: " + "engine_load_devcrypto_int()\n"); +# endif + engine_load_devcrypto_int(); + return 1; +} +# endif + +# ifndef OPENSSL_NO_RDRAND +static CRYPTO_ONCE engine_rdrand = CRYPTO_ONCE_STATIC_INIT; +DEFINE_RUN_ONCE_STATIC(ossl_init_engine_rdrand) +{ +# ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_rdrand: " + "engine_load_rdrand_int()\n"); +# endif + engine_load_rdrand_int(); + return 1; +} +# endif +static CRYPTO_ONCE engine_dynamic = CRYPTO_ONCE_STATIC_INIT; +DEFINE_RUN_ONCE_STATIC(ossl_init_engine_dynamic) +{ +# ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_dynamic: " + "engine_load_dynamic_int()\n"); +# endif + engine_load_dynamic_int(); + return 1; +} +# ifndef OPENSSL_NO_STATIC_ENGINE +# if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK) +static CRYPTO_ONCE engine_padlock = CRYPTO_ONCE_STATIC_INIT; +DEFINE_RUN_ONCE_STATIC(ossl_init_engine_padlock) +{ +# ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_padlock: " + "engine_load_padlock_int()\n"); +# endif + engine_load_padlock_int(); + return 1; +} +# endif +# if defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_NO_CAPIENG) +static CRYPTO_ONCE engine_capi = CRYPTO_ONCE_STATIC_INIT; +DEFINE_RUN_ONCE_STATIC(ossl_init_engine_capi) +{ +# ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_capi: " + "engine_load_capi_int()\n"); +# endif + engine_load_capi_int(); + return 1; +} +# endif +# if !defined(OPENSSL_NO_AFALGENG) +static CRYPTO_ONCE engine_afalg = CRYPTO_ONCE_STATIC_INIT; +DEFINE_RUN_ONCE_STATIC(ossl_init_engine_afalg) +{ +# ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_afalg: " + "engine_load_afalg_int()\n"); +# endif + engine_load_afalg_int(); + return 1; +} +# endif +# endif +#endif + +#ifndef OPENSSL_NO_COMP +static CRYPTO_ONCE zlib = CRYPTO_ONCE_STATIC_INIT; + +static int zlib_inited = 0; +DEFINE_RUN_ONCE_STATIC(ossl_init_zlib) +{ + /* Do nothing - we need to know about this for the later cleanup */ + zlib_inited = 1; + return 1; +} +#endif + +static void ossl_init_thread_stop(struct thread_local_inits_st *locals) +{ + /* Can't do much about this */ + if (locals == NULL) + return; + + if (locals->async) { +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_stop: " + "async_delete_thread_state()\n"); +#endif + async_delete_thread_state(); + } + + if (locals->err_state) { +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_stop: " + "err_delete_thread_state()\n"); +#endif + err_delete_thread_state(); + } + + if (locals->rand) { +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_stop: " + "drbg_delete_thread_state()\n"); +#endif + drbg_delete_thread_state(); + } + + OPENSSL_free(locals); +} + +void OPENSSL_thread_stop(void) +{ + if (destructor_key.sane != -1) + ossl_init_thread_stop(ossl_init_get_thread_local(0)); +} + +int ossl_init_thread_start(uint64_t opts) +{ + struct thread_local_inits_st *locals; + + if (!OPENSSL_init_crypto(0, NULL)) + return 0; + + locals = ossl_init_get_thread_local(1); + + if (locals == NULL) + return 0; + + if (opts & OPENSSL_INIT_THREAD_ASYNC) { +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_start: " + "marking thread for async\n"); +#endif + locals->async = 1; + } + + if (opts & OPENSSL_INIT_THREAD_ERR_STATE) { +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_start: " + "marking thread for err_state\n"); +#endif + locals->err_state = 1; + } + + if (opts & OPENSSL_INIT_THREAD_RAND) { +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_start: " + "marking thread for rand\n"); +#endif + locals->rand = 1; + } + + return 1; +} + +void OPENSSL_cleanup(void) +{ + OPENSSL_INIT_STOP *currhandler, *lasthandler; + CRYPTO_THREAD_LOCAL key; + + /* If we've not been inited then no need to deinit */ + if (!base_inited) + return; + + /* Might be explicitly called and also by atexit */ + if (stopped) + return; + stopped = 1; + + /* + * Thread stop may not get automatically called by the thread library for + * the very last thread in some situations, so call it directly. + */ + ossl_init_thread_stop(ossl_init_get_thread_local(0)); + + currhandler = stop_handlers; + while (currhandler != NULL) { + currhandler->handler(); + lasthandler = currhandler; + currhandler = currhandler->next; + OPENSSL_free(lasthandler); + } + stop_handlers = NULL; + + CRYPTO_THREAD_lock_free(init_lock); + init_lock = NULL; + + /* + * We assume we are single-threaded for this function, i.e. no race + * conditions for the various "*_inited" vars below. + */ + +#ifndef OPENSSL_NO_COMP + if (zlib_inited) { +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: " + "comp_zlib_cleanup_int()\n"); +#endif + comp_zlib_cleanup_int(); + } +#endif + + if (async_inited) { +# ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: " + "async_deinit()\n"); +# endif + async_deinit(); + } + + if (load_crypto_strings_inited) { +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: " + "err_free_strings_int()\n"); +#endif + err_free_strings_int(); + } + + key = destructor_key.value; + destructor_key.sane = -1; + CRYPTO_THREAD_cleanup_local(&key); + +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: " + "rand_cleanup_int()\n"); + fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: " + "conf_modules_free_int()\n"); +#ifndef OPENSSL_NO_ENGINE + fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: " + "engine_cleanup_int()\n"); +#endif + fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: " + "crypto_cleanup_all_ex_data_int()\n"); + fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: " + "bio_sock_cleanup_int()\n"); + fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: " + "bio_cleanup()\n"); + fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: " + "evp_cleanup_int()\n"); + fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: " + "obj_cleanup_int()\n"); + fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: " + "err_cleanup()\n"); +#endif + /* + * Note that cleanup order is important: + * - rand_cleanup_int could call an ENGINE's RAND cleanup function so + * must be called before engine_cleanup_int() + * - ENGINEs use CRYPTO_EX_DATA and therefore, must be cleaned up + * before the ex data handlers are wiped in CRYPTO_cleanup_all_ex_data(). + * - conf_modules_free_int() can end up in ENGINE code so must be called + * before engine_cleanup_int() + * - ENGINEs and additional EVP algorithms might use added OIDs names so + * obj_cleanup_int() must be called last + */ + rand_cleanup_int(); + rand_drbg_cleanup_int(); + conf_modules_free_int(); +#ifndef OPENSSL_NO_ENGINE + engine_cleanup_int(); +#endif + ossl_store_cleanup_int(); + crypto_cleanup_all_ex_data_int(); + bio_cleanup(); + evp_cleanup_int(); + obj_cleanup_int(); + err_cleanup(); + + CRYPTO_secure_malloc_done(); + + base_inited = 0; +} + +/* + * If this function is called with a non NULL settings value then it must be + * called prior to any threads making calls to any OpenSSL functions, + * i.e. passing a non-null settings value is assumed to be single-threaded. + */ +int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) +{ + if (stopped) { + if (!(opts & OPENSSL_INIT_BASE_ONLY)) + CRYPTOerr(CRYPTO_F_OPENSSL_INIT_CRYPTO, ERR_R_INIT_FAIL); + return 0; + } + + /* + * When the caller specifies OPENSSL_INIT_BASE_ONLY, that should be the + * *only* option specified. With that option we return immediately after + * doing the requested limited initialization. Note that + * err_shelve_state() called by us via ossl_init_load_crypto_nodelete() + * re-enters OPENSSL_init_crypto() with OPENSSL_INIT_BASE_ONLY, but with + * base already initialized this is a harmless NOOP. + * + * If we remain the only caller of err_shelve_state() the recursion should + * perhaps be removed, but if in doubt, it can be left in place. + */ + if (!RUN_ONCE(&base, ossl_init_base)) + return 0; + if (opts & OPENSSL_INIT_BASE_ONLY) + return 1; + + /* + * Now we don't always set up exit handlers, the INIT_BASE_ONLY calls + * should not have the side-effect of setting up exit handlers, and + * therefore, this code block is below the INIT_BASE_ONLY-conditioned early + * return above. + */ + if ((opts & OPENSSL_INIT_NO_ATEXIT) != 0) { + if (!RUN_ONCE_ALT(®ister_atexit, ossl_init_no_register_atexit, + ossl_init_register_atexit)) + return 0; + } else if (!RUN_ONCE(®ister_atexit, ossl_init_register_atexit)) { + return 0; + } + + if (!RUN_ONCE(&load_crypto_nodelete, ossl_init_load_crypto_nodelete)) + return 0; + + if ((opts & OPENSSL_INIT_NO_LOAD_CRYPTO_STRINGS) + && !RUN_ONCE_ALT(&load_crypto_strings, + ossl_init_no_load_crypto_strings, + ossl_init_load_crypto_strings)) + return 0; + + if ((opts & OPENSSL_INIT_LOAD_CRYPTO_STRINGS) + && !RUN_ONCE(&load_crypto_strings, ossl_init_load_crypto_strings)) + return 0; + + if ((opts & OPENSSL_INIT_NO_ADD_ALL_CIPHERS) + && !RUN_ONCE_ALT(&add_all_ciphers, ossl_init_no_add_all_ciphers, + ossl_init_add_all_ciphers)) + return 0; + + if ((opts & OPENSSL_INIT_ADD_ALL_CIPHERS) + && !RUN_ONCE(&add_all_ciphers, ossl_init_add_all_ciphers)) + return 0; + + if ((opts & OPENSSL_INIT_NO_ADD_ALL_DIGESTS) + && !RUN_ONCE_ALT(&add_all_digests, ossl_init_no_add_all_digests, + ossl_init_add_all_digests)) + return 0; + + if ((opts & OPENSSL_INIT_ADD_ALL_DIGESTS) + && !RUN_ONCE(&add_all_digests, ossl_init_add_all_digests)) + return 0; + + if ((opts & OPENSSL_INIT_ATFORK) + && !openssl_init_fork_handlers()) + return 0; + + if ((opts & OPENSSL_INIT_NO_LOAD_CONFIG) + && !RUN_ONCE_ALT(&config, ossl_init_no_config, ossl_init_config)) + return 0; + + if (opts & OPENSSL_INIT_LOAD_CONFIG) { + int ret; + CRYPTO_THREAD_write_lock(init_lock); + conf_settings = settings; + ret = RUN_ONCE(&config, ossl_init_config); + conf_settings = NULL; + CRYPTO_THREAD_unlock(init_lock); + if (!ret) + return 0; + } + + if ((opts & OPENSSL_INIT_ASYNC) + && !RUN_ONCE(&async, ossl_init_async)) + return 0; + +#ifndef OPENSSL_NO_ENGINE + if ((opts & OPENSSL_INIT_ENGINE_OPENSSL) + && !RUN_ONCE(&engine_openssl, ossl_init_engine_openssl)) + return 0; +# if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_DEVCRYPTOENG) + if ((opts & OPENSSL_INIT_ENGINE_CRYPTODEV) + && !RUN_ONCE(&engine_devcrypto, ossl_init_engine_devcrypto)) + return 0; +# endif +# ifndef OPENSSL_NO_RDRAND + if ((opts & OPENSSL_INIT_ENGINE_RDRAND) + && !RUN_ONCE(&engine_rdrand, ossl_init_engine_rdrand)) + return 0; +# endif + if ((opts & OPENSSL_INIT_ENGINE_DYNAMIC) + && !RUN_ONCE(&engine_dynamic, ossl_init_engine_dynamic)) + return 0; +# ifndef OPENSSL_NO_STATIC_ENGINE +# if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK) + if ((opts & OPENSSL_INIT_ENGINE_PADLOCK) + && !RUN_ONCE(&engine_padlock, ossl_init_engine_padlock)) + return 0; +# endif +# if defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_NO_CAPIENG) + if ((opts & OPENSSL_INIT_ENGINE_CAPI) + && !RUN_ONCE(&engine_capi, ossl_init_engine_capi)) + return 0; +# endif +# if !defined(OPENSSL_NO_AFALGENG) + if ((opts & OPENSSL_INIT_ENGINE_AFALG) + && !RUN_ONCE(&engine_afalg, ossl_init_engine_afalg)) + return 0; +# endif +# endif + if (opts & (OPENSSL_INIT_ENGINE_ALL_BUILTIN + | OPENSSL_INIT_ENGINE_OPENSSL + | OPENSSL_INIT_ENGINE_AFALG)) { + ENGINE_register_all_complete(); + } +#endif + +#ifndef OPENSSL_NO_COMP + if ((opts & OPENSSL_INIT_ZLIB) + && !RUN_ONCE(&zlib, ossl_init_zlib)) + return 0; +#endif + + return 1; +} + +int OPENSSL_atexit(void (*handler)(void)) +{ + OPENSSL_INIT_STOP *newhand; + +#if !defined(OPENSSL_NO_DSO) \ + && !defined(OPENSSL_USE_NODELETE)\ + && !defined(OPENSSL_NO_PINSHARED) + { + union { + void *sym; + void (*func)(void); + } handlersym; + + handlersym.func = handler; +# ifdef DSO_WIN32 + { + HMODULE handle = NULL; + BOOL ret; + + /* + * We don't use the DSO route for WIN32 because there is a better + * way + */ + ret = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS + | GET_MODULE_HANDLE_EX_FLAG_PIN, + handlersym.sym, &handle); + + if (!ret) + return 0; + } +# else + /* + * Deliberately leak a reference to the handler. This will force the + * library/code containing the handler to remain loaded until we run the + * atexit handler. If -znodelete has been used then this is + * unnecessary. + */ + { + DSO *dso = NULL; + + ERR_set_mark(); + dso = DSO_dsobyaddr(handlersym.sym, DSO_FLAG_NO_UNLOAD_ON_FREE); +# ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, + "OPENSSL_INIT: OPENSSL_atexit: obtained DSO reference? %s\n", + (dso == NULL ? "No!" : "Yes.")); + /* See same code above in ossl_init_base() for an explanation. */ +# endif + DSO_free(dso); + ERR_pop_to_mark(); + } +# endif + } +#endif + + if ((newhand = OPENSSL_malloc(sizeof(*newhand))) == NULL) { + CRYPTOerr(CRYPTO_F_OPENSSL_ATEXIT, ERR_R_MALLOC_FAILURE); + return 0; + } + + newhand->handler = handler; + newhand->next = stop_handlers; + stop_handlers = newhand; + + return 1; +} + +#ifdef OPENSSL_SYS_UNIX +/* + * The following three functions are for OpenSSL developers. This is + * where we set/reset state across fork (called via pthread_atfork when + * it exists, or manually by the application when it doesn't). + * + * WARNING! If you put code in either OPENSSL_fork_parent or + * OPENSSL_fork_child, you MUST MAKE SURE that they are async-signal- + * safe. See this link, for example: + * http://man7.org/linux/man-pages/man7/signal-safety.7.html + */ + +void OPENSSL_fork_prepare(void) +{ +} + +void OPENSSL_fork_parent(void) +{ +} + +void OPENSSL_fork_child(void) +{ + rand_fork(); +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/kdf/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/kdf/build.info new file mode 100644 index 000000000..c166399d0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/kdf/build.info @@ -0,0 +1,3 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + tls1_prf.c kdf_err.c hkdf.c scrypt.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/kdf/hkdf.c b/trunk/3rdparty/openssl-1.1-fit/crypto/kdf/hkdf.c new file mode 100644 index 000000000..ae46fad60 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/kdf/hkdf.c @@ -0,0 +1,352 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include "internal/cryptlib.h" +#include "internal/evp_int.h" + +#define HKDF_MAXBUF 1024 + +static unsigned char *HKDF(const EVP_MD *evp_md, + const unsigned char *salt, size_t salt_len, + const unsigned char *key, size_t key_len, + const unsigned char *info, size_t info_len, + unsigned char *okm, size_t okm_len); + +static unsigned char *HKDF_Extract(const EVP_MD *evp_md, + const unsigned char *salt, size_t salt_len, + const unsigned char *key, size_t key_len, + unsigned char *prk, size_t *prk_len); + +static unsigned char *HKDF_Expand(const EVP_MD *evp_md, + const unsigned char *prk, size_t prk_len, + const unsigned char *info, size_t info_len, + unsigned char *okm, size_t okm_len); + +typedef struct { + int mode; + const EVP_MD *md; + unsigned char *salt; + size_t salt_len; + unsigned char *key; + size_t key_len; + unsigned char info[HKDF_MAXBUF]; + size_t info_len; +} HKDF_PKEY_CTX; + +static int pkey_hkdf_init(EVP_PKEY_CTX *ctx) +{ + HKDF_PKEY_CTX *kctx; + + if ((kctx = OPENSSL_zalloc(sizeof(*kctx))) == NULL) { + KDFerr(KDF_F_PKEY_HKDF_INIT, ERR_R_MALLOC_FAILURE); + return 0; + } + + ctx->data = kctx; + + return 1; +} + +static void pkey_hkdf_cleanup(EVP_PKEY_CTX *ctx) +{ + HKDF_PKEY_CTX *kctx = ctx->data; + OPENSSL_clear_free(kctx->salt, kctx->salt_len); + OPENSSL_clear_free(kctx->key, kctx->key_len); + OPENSSL_cleanse(kctx->info, kctx->info_len); + OPENSSL_free(kctx); +} + +static int pkey_hkdf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) +{ + HKDF_PKEY_CTX *kctx = ctx->data; + + switch (type) { + case EVP_PKEY_CTRL_HKDF_MD: + if (p2 == NULL) + return 0; + + kctx->md = p2; + return 1; + + case EVP_PKEY_CTRL_HKDF_MODE: + kctx->mode = p1; + return 1; + + case EVP_PKEY_CTRL_HKDF_SALT: + if (p1 == 0 || p2 == NULL) + return 1; + + if (p1 < 0) + return 0; + + if (kctx->salt != NULL) + OPENSSL_clear_free(kctx->salt, kctx->salt_len); + + kctx->salt = OPENSSL_memdup(p2, p1); + if (kctx->salt == NULL) + return 0; + + kctx->salt_len = p1; + return 1; + + case EVP_PKEY_CTRL_HKDF_KEY: + if (p1 < 0) + return 0; + + if (kctx->key != NULL) + OPENSSL_clear_free(kctx->key, kctx->key_len); + + kctx->key = OPENSSL_memdup(p2, p1); + if (kctx->key == NULL) + return 0; + + kctx->key_len = p1; + return 1; + + case EVP_PKEY_CTRL_HKDF_INFO: + if (p1 == 0 || p2 == NULL) + return 1; + + if (p1 < 0 || p1 > (int)(HKDF_MAXBUF - kctx->info_len)) + return 0; + + memcpy(kctx->info + kctx->info_len, p2, p1); + kctx->info_len += p1; + return 1; + + default: + return -2; + + } +} + +static int pkey_hkdf_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, + const char *value) +{ + if (strcmp(type, "mode") == 0) { + int mode; + + if (strcmp(value, "EXTRACT_AND_EXPAND") == 0) + mode = EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND; + else if (strcmp(value, "EXTRACT_ONLY") == 0) + mode = EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY; + else if (strcmp(value, "EXPAND_ONLY") == 0) + mode = EVP_PKEY_HKDEF_MODE_EXPAND_ONLY; + else + return 0; + + return EVP_PKEY_CTX_hkdf_mode(ctx, mode); + } + + if (strcmp(type, "md") == 0) + return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_DERIVE, + EVP_PKEY_CTRL_HKDF_MD, value); + + if (strcmp(type, "salt") == 0) + return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_SALT, value); + + if (strcmp(type, "hexsalt") == 0) + return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_SALT, value); + + if (strcmp(type, "key") == 0) + return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_KEY, value); + + if (strcmp(type, "hexkey") == 0) + return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_KEY, value); + + if (strcmp(type, "info") == 0) + return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_INFO, value); + + if (strcmp(type, "hexinfo") == 0) + return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_INFO, value); + + KDFerr(KDF_F_PKEY_HKDF_CTRL_STR, KDF_R_UNKNOWN_PARAMETER_TYPE); + return -2; +} + +static int pkey_hkdf_derive_init(EVP_PKEY_CTX *ctx) +{ + HKDF_PKEY_CTX *kctx = ctx->data; + + OPENSSL_clear_free(kctx->key, kctx->key_len); + OPENSSL_clear_free(kctx->salt, kctx->salt_len); + OPENSSL_cleanse(kctx->info, kctx->info_len); + memset(kctx, 0, sizeof(*kctx)); + + return 1; +} + +static int pkey_hkdf_derive(EVP_PKEY_CTX *ctx, unsigned char *key, + size_t *keylen) +{ + HKDF_PKEY_CTX *kctx = ctx->data; + + if (kctx->md == NULL) { + KDFerr(KDF_F_PKEY_HKDF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST); + return 0; + } + if (kctx->key == NULL) { + KDFerr(KDF_F_PKEY_HKDF_DERIVE, KDF_R_MISSING_KEY); + return 0; + } + + switch (kctx->mode) { + case EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND: + return HKDF(kctx->md, kctx->salt, kctx->salt_len, kctx->key, + kctx->key_len, kctx->info, kctx->info_len, key, + *keylen) != NULL; + + case EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY: + if (key == NULL) { + *keylen = EVP_MD_size(kctx->md); + return 1; + } + return HKDF_Extract(kctx->md, kctx->salt, kctx->salt_len, kctx->key, + kctx->key_len, key, keylen) != NULL; + + case EVP_PKEY_HKDEF_MODE_EXPAND_ONLY: + return HKDF_Expand(kctx->md, kctx->key, kctx->key_len, kctx->info, + kctx->info_len, key, *keylen) != NULL; + + default: + return 0; + } +} + +const EVP_PKEY_METHOD hkdf_pkey_meth = { + EVP_PKEY_HKDF, + 0, + pkey_hkdf_init, + 0, + pkey_hkdf_cleanup, + + 0, 0, + 0, 0, + + 0, + 0, + + 0, + 0, + + 0, 0, + + 0, 0, 0, 0, + + 0, 0, + + 0, 0, + + pkey_hkdf_derive_init, + pkey_hkdf_derive, + pkey_hkdf_ctrl, + pkey_hkdf_ctrl_str +}; + +static unsigned char *HKDF(const EVP_MD *evp_md, + const unsigned char *salt, size_t salt_len, + const unsigned char *key, size_t key_len, + const unsigned char *info, size_t info_len, + unsigned char *okm, size_t okm_len) +{ + unsigned char prk[EVP_MAX_MD_SIZE]; + unsigned char *ret; + size_t prk_len; + + if (!HKDF_Extract(evp_md, salt, salt_len, key, key_len, prk, &prk_len)) + return NULL; + + ret = HKDF_Expand(evp_md, prk, prk_len, info, info_len, okm, okm_len); + OPENSSL_cleanse(prk, sizeof(prk)); + + return ret; +} + +static unsigned char *HKDF_Extract(const EVP_MD *evp_md, + const unsigned char *salt, size_t salt_len, + const unsigned char *key, size_t key_len, + unsigned char *prk, size_t *prk_len) +{ + unsigned int tmp_len; + + if (!HMAC(evp_md, salt, salt_len, key, key_len, prk, &tmp_len)) + return NULL; + + *prk_len = tmp_len; + return prk; +} + +static unsigned char *HKDF_Expand(const EVP_MD *evp_md, + const unsigned char *prk, size_t prk_len, + const unsigned char *info, size_t info_len, + unsigned char *okm, size_t okm_len) +{ + HMAC_CTX *hmac; + unsigned char *ret = NULL; + + unsigned int i; + + unsigned char prev[EVP_MAX_MD_SIZE]; + + size_t done_len = 0, dig_len = EVP_MD_size(evp_md); + + size_t n = okm_len / dig_len; + if (okm_len % dig_len) + n++; + + if (n > 255 || okm == NULL) + return NULL; + + if ((hmac = HMAC_CTX_new()) == NULL) + return NULL; + + if (!HMAC_Init_ex(hmac, prk, prk_len, evp_md, NULL)) + goto err; + + for (i = 1; i <= n; i++) { + size_t copy_len; + const unsigned char ctr = i; + + if (i > 1) { + if (!HMAC_Init_ex(hmac, NULL, 0, NULL, NULL)) + goto err; + + if (!HMAC_Update(hmac, prev, dig_len)) + goto err; + } + + if (!HMAC_Update(hmac, info, info_len)) + goto err; + + if (!HMAC_Update(hmac, &ctr, 1)) + goto err; + + if (!HMAC_Final(hmac, prev, NULL)) + goto err; + + copy_len = (done_len + dig_len > okm_len) ? + okm_len - done_len : + dig_len; + + memcpy(okm + done_len, prev, copy_len); + + done_len += copy_len; + } + ret = okm; + + err: + OPENSSL_cleanse(prev, sizeof(prev)); + HMAC_CTX_free(hmac); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/kdf/kdf_err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/kdf/kdf_err.c new file mode 100644 index 000000000..1627c0a39 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/kdf/kdf_err.c @@ -0,0 +1,67 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA KDF_str_functs[] = { + {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_HKDF_CTRL_STR, 0), "pkey_hkdf_ctrl_str"}, + {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_HKDF_DERIVE, 0), "pkey_hkdf_derive"}, + {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_HKDF_INIT, 0), "pkey_hkdf_init"}, + {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_SCRYPT_CTRL_STR, 0), + "pkey_scrypt_ctrl_str"}, + {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_SCRYPT_CTRL_UINT64, 0), + "pkey_scrypt_ctrl_uint64"}, + {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_SCRYPT_DERIVE, 0), "pkey_scrypt_derive"}, + {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_SCRYPT_INIT, 0), "pkey_scrypt_init"}, + {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_SCRYPT_SET_MEMBUF, 0), + "pkey_scrypt_set_membuf"}, + {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_TLS1_PRF_CTRL_STR, 0), + "pkey_tls1_prf_ctrl_str"}, + {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_TLS1_PRF_DERIVE, 0), + "pkey_tls1_prf_derive"}, + {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_TLS1_PRF_INIT, 0), "pkey_tls1_prf_init"}, + {ERR_PACK(ERR_LIB_KDF, KDF_F_TLS1_PRF_ALG, 0), "tls1_prf_alg"}, + {0, NULL} +}; + +static const ERR_STRING_DATA KDF_str_reasons[] = { + {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_INVALID_DIGEST), "invalid digest"}, + {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_ITERATION_COUNT), + "missing iteration count"}, + {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_KEY), "missing key"}, + {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_MESSAGE_DIGEST), + "missing message digest"}, + {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_PARAMETER), "missing parameter"}, + {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_PASS), "missing pass"}, + {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_SALT), "missing salt"}, + {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_SECRET), "missing secret"}, + {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_SEED), "missing seed"}, + {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_UNKNOWN_PARAMETER_TYPE), + "unknown parameter type"}, + {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_VALUE_ERROR), "value error"}, + {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_VALUE_MISSING), "value missing"}, + {0, NULL} +}; + +#endif + +int ERR_load_KDF_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(KDF_str_functs[0].error) == NULL) { + ERR_load_strings_const(KDF_str_functs); + ERR_load_strings_const(KDF_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/kdf/scrypt.c b/trunk/3rdparty/openssl-1.1-fit/crypto/kdf/scrypt.c new file mode 100644 index 000000000..61fd390e9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/kdf/scrypt.c @@ -0,0 +1,266 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include "internal/cryptlib.h" +#include "internal/evp_int.h" + +#ifndef OPENSSL_NO_SCRYPT + +static int atou64(const char *nptr, uint64_t *result); + +typedef struct { + unsigned char *pass; + size_t pass_len; + unsigned char *salt; + size_t salt_len; + uint64_t N, r, p; + uint64_t maxmem_bytes; +} SCRYPT_PKEY_CTX; + +/* Custom uint64_t parser since we do not have strtoull */ +static int atou64(const char *nptr, uint64_t *result) +{ + uint64_t value = 0; + + while (*nptr) { + unsigned int digit; + uint64_t new_value; + + if ((*nptr < '0') || (*nptr > '9')) { + return 0; + } + digit = (unsigned int)(*nptr - '0'); + new_value = (value * 10) + digit; + if ((new_value < digit) || ((new_value - digit) / 10 != value)) { + /* Overflow */ + return 0; + } + value = new_value; + nptr++; + } + *result = value; + return 1; +} + +static int pkey_scrypt_init(EVP_PKEY_CTX *ctx) +{ + SCRYPT_PKEY_CTX *kctx; + + kctx = OPENSSL_zalloc(sizeof(*kctx)); + if (kctx == NULL) { + KDFerr(KDF_F_PKEY_SCRYPT_INIT, ERR_R_MALLOC_FAILURE); + return 0; + } + + /* Default values are the most conservative recommendation given in the + * original paper of C. Percival. Derivation uses roughly 1 GiB of memory + * for this parameter choice (approx. 128 * r * (N + p) bytes). + */ + kctx->N = 1 << 20; + kctx->r = 8; + kctx->p = 1; + kctx->maxmem_bytes = 1025 * 1024 * 1024; + + ctx->data = kctx; + + return 1; +} + +static void pkey_scrypt_cleanup(EVP_PKEY_CTX *ctx) +{ + SCRYPT_PKEY_CTX *kctx = ctx->data; + + OPENSSL_clear_free(kctx->salt, kctx->salt_len); + OPENSSL_clear_free(kctx->pass, kctx->pass_len); + OPENSSL_free(kctx); +} + +static int pkey_scrypt_set_membuf(unsigned char **buffer, size_t *buflen, + const unsigned char *new_buffer, + const int new_buflen) +{ + if (new_buffer == NULL) + return 1; + + if (new_buflen < 0) + return 0; + + if (*buffer != NULL) + OPENSSL_clear_free(*buffer, *buflen); + + if (new_buflen > 0) { + *buffer = OPENSSL_memdup(new_buffer, new_buflen); + } else { + *buffer = OPENSSL_malloc(1); + } + if (*buffer == NULL) { + KDFerr(KDF_F_PKEY_SCRYPT_SET_MEMBUF, ERR_R_MALLOC_FAILURE); + return 0; + } + + *buflen = new_buflen; + return 1; +} + +static int is_power_of_two(uint64_t value) +{ + return (value != 0) && ((value & (value - 1)) == 0); +} + +static int pkey_scrypt_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) +{ + SCRYPT_PKEY_CTX *kctx = ctx->data; + uint64_t u64_value; + + switch (type) { + case EVP_PKEY_CTRL_PASS: + return pkey_scrypt_set_membuf(&kctx->pass, &kctx->pass_len, p2, p1); + + case EVP_PKEY_CTRL_SCRYPT_SALT: + return pkey_scrypt_set_membuf(&kctx->salt, &kctx->salt_len, p2, p1); + + case EVP_PKEY_CTRL_SCRYPT_N: + u64_value = *((uint64_t *)p2); + if ((u64_value <= 1) || !is_power_of_two(u64_value)) + return 0; + kctx->N = u64_value; + return 1; + + case EVP_PKEY_CTRL_SCRYPT_R: + u64_value = *((uint64_t *)p2); + if (u64_value < 1) + return 0; + kctx->r = u64_value; + return 1; + + case EVP_PKEY_CTRL_SCRYPT_P: + u64_value = *((uint64_t *)p2); + if (u64_value < 1) + return 0; + kctx->p = u64_value; + return 1; + + case EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES: + u64_value = *((uint64_t *)p2); + if (u64_value < 1) + return 0; + kctx->maxmem_bytes = u64_value; + return 1; + + default: + return -2; + + } +} + +static int pkey_scrypt_ctrl_uint64(EVP_PKEY_CTX *ctx, int type, + const char *value) +{ + uint64_t int_value; + + if (!atou64(value, &int_value)) { + KDFerr(KDF_F_PKEY_SCRYPT_CTRL_UINT64, KDF_R_VALUE_ERROR); + return 0; + } + return pkey_scrypt_ctrl(ctx, type, 0, &int_value); +} + +static int pkey_scrypt_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, + const char *value) +{ + if (value == NULL) { + KDFerr(KDF_F_PKEY_SCRYPT_CTRL_STR, KDF_R_VALUE_MISSING); + return 0; + } + + if (strcmp(type, "pass") == 0) + return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_PASS, value); + + if (strcmp(type, "hexpass") == 0) + return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_PASS, value); + + if (strcmp(type, "salt") == 0) + return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_SCRYPT_SALT, value); + + if (strcmp(type, "hexsalt") == 0) + return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_SCRYPT_SALT, value); + + if (strcmp(type, "N") == 0) + return pkey_scrypt_ctrl_uint64(ctx, EVP_PKEY_CTRL_SCRYPT_N, value); + + if (strcmp(type, "r") == 0) + return pkey_scrypt_ctrl_uint64(ctx, EVP_PKEY_CTRL_SCRYPT_R, value); + + if (strcmp(type, "p") == 0) + return pkey_scrypt_ctrl_uint64(ctx, EVP_PKEY_CTRL_SCRYPT_P, value); + + if (strcmp(type, "maxmem_bytes") == 0) + return pkey_scrypt_ctrl_uint64(ctx, EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES, + value); + + KDFerr(KDF_F_PKEY_SCRYPT_CTRL_STR, KDF_R_UNKNOWN_PARAMETER_TYPE); + return -2; +} + +static int pkey_scrypt_derive(EVP_PKEY_CTX *ctx, unsigned char *key, + size_t *keylen) +{ + SCRYPT_PKEY_CTX *kctx = ctx->data; + + if (kctx->pass == NULL) { + KDFerr(KDF_F_PKEY_SCRYPT_DERIVE, KDF_R_MISSING_PASS); + return 0; + } + + if (kctx->salt == NULL) { + KDFerr(KDF_F_PKEY_SCRYPT_DERIVE, KDF_R_MISSING_SALT); + return 0; + } + + return EVP_PBE_scrypt((char *)kctx->pass, kctx->pass_len, kctx->salt, + kctx->salt_len, kctx->N, kctx->r, kctx->p, + kctx->maxmem_bytes, key, *keylen); +} + +const EVP_PKEY_METHOD scrypt_pkey_meth = { + EVP_PKEY_SCRYPT, + 0, + pkey_scrypt_init, + 0, + pkey_scrypt_cleanup, + + 0, 0, + 0, 0, + + 0, + 0, + + 0, + 0, + + 0, 0, + + 0, 0, 0, 0, + + 0, 0, + + 0, 0, + + 0, + pkey_scrypt_derive, + pkey_scrypt_ctrl, + pkey_scrypt_ctrl_str +}; + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/kdf/tls1_prf.c b/trunk/3rdparty/openssl-1.1-fit/crypto/kdf/tls1_prf.c new file mode 100644 index 000000000..49f7ecced --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/kdf/tls1_prf.c @@ -0,0 +1,278 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include "internal/evp_int.h" + +static int tls1_prf_alg(const EVP_MD *md, + const unsigned char *sec, size_t slen, + const unsigned char *seed, size_t seed_len, + unsigned char *out, size_t olen); + +#define TLS1_PRF_MAXBUF 1024 + +/* TLS KDF pkey context structure */ + +typedef struct { + /* Digest to use for PRF */ + const EVP_MD *md; + /* Secret value to use for PRF */ + unsigned char *sec; + size_t seclen; + /* Buffer of concatenated seed data */ + unsigned char seed[TLS1_PRF_MAXBUF]; + size_t seedlen; +} TLS1_PRF_PKEY_CTX; + +static int pkey_tls1_prf_init(EVP_PKEY_CTX *ctx) +{ + TLS1_PRF_PKEY_CTX *kctx; + + if ((kctx = OPENSSL_zalloc(sizeof(*kctx))) == NULL) { + KDFerr(KDF_F_PKEY_TLS1_PRF_INIT, ERR_R_MALLOC_FAILURE); + return 0; + } + ctx->data = kctx; + + return 1; +} + +static void pkey_tls1_prf_cleanup(EVP_PKEY_CTX *ctx) +{ + TLS1_PRF_PKEY_CTX *kctx = ctx->data; + OPENSSL_clear_free(kctx->sec, kctx->seclen); + OPENSSL_cleanse(kctx->seed, kctx->seedlen); + OPENSSL_free(kctx); +} + +static int pkey_tls1_prf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) +{ + TLS1_PRF_PKEY_CTX *kctx = ctx->data; + switch (type) { + case EVP_PKEY_CTRL_TLS_MD: + kctx->md = p2; + return 1; + + case EVP_PKEY_CTRL_TLS_SECRET: + if (p1 < 0) + return 0; + if (kctx->sec != NULL) + OPENSSL_clear_free(kctx->sec, kctx->seclen); + OPENSSL_cleanse(kctx->seed, kctx->seedlen); + kctx->seedlen = 0; + kctx->sec = OPENSSL_memdup(p2, p1); + if (kctx->sec == NULL) + return 0; + kctx->seclen = p1; + return 1; + + case EVP_PKEY_CTRL_TLS_SEED: + if (p1 == 0 || p2 == NULL) + return 1; + if (p1 < 0 || p1 > (int)(TLS1_PRF_MAXBUF - kctx->seedlen)) + return 0; + memcpy(kctx->seed + kctx->seedlen, p2, p1); + kctx->seedlen += p1; + return 1; + + default: + return -2; + + } +} + +static int pkey_tls1_prf_ctrl_str(EVP_PKEY_CTX *ctx, + const char *type, const char *value) +{ + if (value == NULL) { + KDFerr(KDF_F_PKEY_TLS1_PRF_CTRL_STR, KDF_R_VALUE_MISSING); + return 0; + } + if (strcmp(type, "md") == 0) { + TLS1_PRF_PKEY_CTX *kctx = ctx->data; + + const EVP_MD *md = EVP_get_digestbyname(value); + if (md == NULL) { + KDFerr(KDF_F_PKEY_TLS1_PRF_CTRL_STR, KDF_R_INVALID_DIGEST); + return 0; + } + kctx->md = md; + return 1; + } + if (strcmp(type, "secret") == 0) + return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_TLS_SECRET, value); + if (strcmp(type, "hexsecret") == 0) + return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_TLS_SECRET, value); + if (strcmp(type, "seed") == 0) + return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_TLS_SEED, value); + if (strcmp(type, "hexseed") == 0) + return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_TLS_SEED, value); + + KDFerr(KDF_F_PKEY_TLS1_PRF_CTRL_STR, KDF_R_UNKNOWN_PARAMETER_TYPE); + return -2; +} + +static int pkey_tls1_prf_derive(EVP_PKEY_CTX *ctx, unsigned char *key, + size_t *keylen) +{ + TLS1_PRF_PKEY_CTX *kctx = ctx->data; + if (kctx->md == NULL) { + KDFerr(KDF_F_PKEY_TLS1_PRF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST); + return 0; + } + if (kctx->sec == NULL) { + KDFerr(KDF_F_PKEY_TLS1_PRF_DERIVE, KDF_R_MISSING_SECRET); + return 0; + } + if (kctx->seedlen == 0) { + KDFerr(KDF_F_PKEY_TLS1_PRF_DERIVE, KDF_R_MISSING_SEED); + return 0; + } + return tls1_prf_alg(kctx->md, kctx->sec, kctx->seclen, + kctx->seed, kctx->seedlen, + key, *keylen); +} + +const EVP_PKEY_METHOD tls1_prf_pkey_meth = { + EVP_PKEY_TLS1_PRF, + 0, + pkey_tls1_prf_init, + 0, + pkey_tls1_prf_cleanup, + + 0, 0, + 0, 0, + + 0, + 0, + + 0, + 0, + + 0, 0, + + 0, 0, 0, 0, + + 0, 0, + + 0, 0, + + 0, + pkey_tls1_prf_derive, + pkey_tls1_prf_ctrl, + pkey_tls1_prf_ctrl_str +}; + +static int tls1_prf_P_hash(const EVP_MD *md, + const unsigned char *sec, size_t sec_len, + const unsigned char *seed, size_t seed_len, + unsigned char *out, size_t olen) +{ + int chunk; + EVP_MD_CTX *ctx = NULL, *ctx_tmp = NULL, *ctx_init = NULL; + EVP_PKEY *mac_key = NULL; + unsigned char A1[EVP_MAX_MD_SIZE]; + size_t A1_len; + int ret = 0; + + chunk = EVP_MD_size(md); + if (!ossl_assert(chunk > 0)) + goto err; + + ctx = EVP_MD_CTX_new(); + ctx_tmp = EVP_MD_CTX_new(); + ctx_init = EVP_MD_CTX_new(); + if (ctx == NULL || ctx_tmp == NULL || ctx_init == NULL) + goto err; + EVP_MD_CTX_set_flags(ctx_init, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); + mac_key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, sec, sec_len); + if (mac_key == NULL) + goto err; + if (!EVP_DigestSignInit(ctx_init, NULL, md, NULL, mac_key)) + goto err; + if (!EVP_MD_CTX_copy_ex(ctx, ctx_init)) + goto err; + if (seed != NULL && !EVP_DigestSignUpdate(ctx, seed, seed_len)) + goto err; + if (!EVP_DigestSignFinal(ctx, A1, &A1_len)) + goto err; + + for (;;) { + /* Reinit mac contexts */ + if (!EVP_MD_CTX_copy_ex(ctx, ctx_init)) + goto err; + if (!EVP_DigestSignUpdate(ctx, A1, A1_len)) + goto err; + if (olen > (size_t)chunk && !EVP_MD_CTX_copy_ex(ctx_tmp, ctx)) + goto err; + if (seed && !EVP_DigestSignUpdate(ctx, seed, seed_len)) + goto err; + + if (olen > (size_t)chunk) { + size_t mac_len; + if (!EVP_DigestSignFinal(ctx, out, &mac_len)) + goto err; + out += mac_len; + olen -= mac_len; + /* calc the next A1 value */ + if (!EVP_DigestSignFinal(ctx_tmp, A1, &A1_len)) + goto err; + } else { /* last one */ + + if (!EVP_DigestSignFinal(ctx, A1, &A1_len)) + goto err; + memcpy(out, A1, olen); + break; + } + } + ret = 1; + err: + EVP_PKEY_free(mac_key); + EVP_MD_CTX_free(ctx); + EVP_MD_CTX_free(ctx_tmp); + EVP_MD_CTX_free(ctx_init); + OPENSSL_cleanse(A1, sizeof(A1)); + return ret; +} + +static int tls1_prf_alg(const EVP_MD *md, + const unsigned char *sec, size_t slen, + const unsigned char *seed, size_t seed_len, + unsigned char *out, size_t olen) +{ + + if (EVP_MD_type(md) == NID_md5_sha1) { + size_t i; + unsigned char *tmp; + if (!tls1_prf_P_hash(EVP_md5(), sec, slen/2 + (slen & 1), + seed, seed_len, out, olen)) + return 0; + + if ((tmp = OPENSSL_malloc(olen)) == NULL) { + KDFerr(KDF_F_TLS1_PRF_ALG, ERR_R_MALLOC_FAILURE); + return 0; + } + if (!tls1_prf_P_hash(EVP_sha1(), sec + slen/2, slen/2 + (slen & 1), + seed, seed_len, tmp, olen)) { + OPENSSL_clear_free(tmp, olen); + return 0; + } + for (i = 0; i < olen; i++) + out[i] ^= tmp[i]; + OPENSSL_clear_free(tmp, olen); + return 1; + } + if (!tls1_prf_P_hash(md, sec, slen, seed, seed_len, out, olen)) + return 0; + + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/lhash/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/lhash/build.info new file mode 100644 index 000000000..30797f2ca --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/lhash/build.info @@ -0,0 +1,3 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + lhash.c lh_stats.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/lhash/lh_stats.c b/trunk/3rdparty/openssl-1.1-fit/crypto/lhash/lh_stats.c new file mode 100644 index 000000000..65b91e1ef --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/lhash/lh_stats.c @@ -0,0 +1,117 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +/* + * If you wish to build this outside of OpenSSL, remove the following lines + * and things should work as expected + */ +#include "internal/cryptlib.h" + +#include +#include +#include "lhash_lcl.h" + +# ifndef OPENSSL_NO_STDIO +void OPENSSL_LH_stats(const OPENSSL_LHASH *lh, FILE *fp) +{ + BIO *bp; + + bp = BIO_new(BIO_s_file()); + if (bp == NULL) + return; + BIO_set_fp(bp, fp, BIO_NOCLOSE); + OPENSSL_LH_stats_bio(lh, bp); + BIO_free(bp); +} + +void OPENSSL_LH_node_stats(const OPENSSL_LHASH *lh, FILE *fp) +{ + BIO *bp; + + bp = BIO_new(BIO_s_file()); + if (bp == NULL) + return; + BIO_set_fp(bp, fp, BIO_NOCLOSE); + OPENSSL_LH_node_stats_bio(lh, bp); + BIO_free(bp); +} + +void OPENSSL_LH_node_usage_stats(const OPENSSL_LHASH *lh, FILE *fp) +{ + BIO *bp; + + bp = BIO_new(BIO_s_file()); + if (bp == NULL) + return; + BIO_set_fp(bp, fp, BIO_NOCLOSE); + OPENSSL_LH_node_usage_stats_bio(lh, bp); + BIO_free(bp); +} + +# endif + +void OPENSSL_LH_stats_bio(const OPENSSL_LHASH *lh, BIO *out) +{ + BIO_printf(out, "num_items = %lu\n", lh->num_items); + BIO_printf(out, "num_nodes = %u\n", lh->num_nodes); + BIO_printf(out, "num_alloc_nodes = %u\n", lh->num_alloc_nodes); + BIO_printf(out, "num_expands = %lu\n", lh->num_expands); + BIO_printf(out, "num_expand_reallocs = %lu\n", lh->num_expand_reallocs); + BIO_printf(out, "num_contracts = %lu\n", lh->num_contracts); + BIO_printf(out, "num_contract_reallocs = %lu\n", lh->num_contract_reallocs); + BIO_printf(out, "num_hash_calls = %lu\n", lh->num_hash_calls); + BIO_printf(out, "num_comp_calls = %lu\n", lh->num_comp_calls); + BIO_printf(out, "num_insert = %lu\n", lh->num_insert); + BIO_printf(out, "num_replace = %lu\n", lh->num_replace); + BIO_printf(out, "num_delete = %lu\n", lh->num_delete); + BIO_printf(out, "num_no_delete = %lu\n", lh->num_no_delete); + BIO_printf(out, "num_retrieve = %lu\n", lh->num_retrieve); + BIO_printf(out, "num_retrieve_miss = %lu\n", lh->num_retrieve_miss); + BIO_printf(out, "num_hash_comps = %lu\n", lh->num_hash_comps); +} + +void OPENSSL_LH_node_stats_bio(const OPENSSL_LHASH *lh, BIO *out) +{ + OPENSSL_LH_NODE *n; + unsigned int i, num; + + for (i = 0; i < lh->num_nodes; i++) { + for (n = lh->b[i], num = 0; n != NULL; n = n->next) + num++; + BIO_printf(out, "node %6u -> %3u\n", i, num); + } +} + +void OPENSSL_LH_node_usage_stats_bio(const OPENSSL_LHASH *lh, BIO *out) +{ + OPENSSL_LH_NODE *n; + unsigned long num; + unsigned int i; + unsigned long total = 0, n_used = 0; + + for (i = 0; i < lh->num_nodes; i++) { + for (n = lh->b[i], num = 0; n != NULL; n = n->next) + num++; + if (num != 0) { + n_used++; + total += num; + } + } + BIO_printf(out, "%lu nodes used out of %u\n", n_used, lh->num_nodes); + BIO_printf(out, "%lu items\n", total); + if (n_used == 0) + return; + BIO_printf(out, "load %d.%02d actual load %d.%02d\n", + (int)(total / lh->num_nodes), + (int)((total % lh->num_nodes) * 100 / lh->num_nodes), + (int)(total / n_used), (int)((total % n_used) * 100 / n_used)); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/lhash/lhash.c b/trunk/3rdparty/openssl-1.1-fit/crypto/lhash/lhash.c new file mode 100644 index 000000000..8d9f933df --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/lhash/lhash.c @@ -0,0 +1,393 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include +#include "internal/ctype.h" +#include "internal/lhash.h" +#include "lhash_lcl.h" + +/* + * A hashing implementation that appears to be based on the linear hashing + * alogrithm: + * https://en.wikipedia.org/wiki/Linear_hashing + * + * Litwin, Witold (1980), "Linear hashing: A new tool for file and table + * addressing", Proc. 6th Conference on Very Large Databases: 212-223 + * http://hackthology.com/pdfs/Litwin-1980-Linear_Hashing.pdf + * + * From the wikipedia article "Linear hashing is used in the BDB Berkeley + * database system, which in turn is used by many software systems such as + * OpenLDAP, using a C implementation derived from the CACM article and first + * published on the Usenet in 1988 by Esmond Pitt." + * + * The CACM paper is available here: + * https://pdfs.semanticscholar.org/ff4d/1c5deca6269cc316bfd952172284dbf610ee.pdf + */ + +#undef MIN_NODES +#define MIN_NODES 16 +#define UP_LOAD (2*LH_LOAD_MULT) /* load times 256 (default 2) */ +#define DOWN_LOAD (LH_LOAD_MULT) /* load times 256 (default 1) */ + +static int expand(OPENSSL_LHASH *lh); +static void contract(OPENSSL_LHASH *lh); +static OPENSSL_LH_NODE **getrn(OPENSSL_LHASH *lh, const void *data, unsigned long *rhash); + +OPENSSL_LHASH *OPENSSL_LH_new(OPENSSL_LH_HASHFUNC h, OPENSSL_LH_COMPFUNC c) +{ + OPENSSL_LHASH *ret; + + if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) { + /* + * Do not set the error code, because the ERR code uses LHASH + * and we want to avoid possible endless error loop. + * CRYPTOerr(CRYPTO_F_OPENSSL_LH_NEW, ERR_R_MALLOC_FAILURE); + */ + return NULL; + } + if ((ret->b = OPENSSL_zalloc(sizeof(*ret->b) * MIN_NODES)) == NULL) + goto err; + ret->comp = ((c == NULL) ? (OPENSSL_LH_COMPFUNC)strcmp : c); + ret->hash = ((h == NULL) ? (OPENSSL_LH_HASHFUNC)OPENSSL_LH_strhash : h); + ret->num_nodes = MIN_NODES / 2; + ret->num_alloc_nodes = MIN_NODES; + ret->pmax = MIN_NODES / 2; + ret->up_load = UP_LOAD; + ret->down_load = DOWN_LOAD; + return ret; + +err: + OPENSSL_free(ret->b); + OPENSSL_free(ret); + return NULL; +} + +void OPENSSL_LH_free(OPENSSL_LHASH *lh) +{ + unsigned int i; + OPENSSL_LH_NODE *n, *nn; + + if (lh == NULL) + return; + + for (i = 0; i < lh->num_nodes; i++) { + n = lh->b[i]; + while (n != NULL) { + nn = n->next; + OPENSSL_free(n); + n = nn; + } + } + OPENSSL_free(lh->b); + OPENSSL_free(lh); +} + +void *OPENSSL_LH_insert(OPENSSL_LHASH *lh, void *data) +{ + unsigned long hash; + OPENSSL_LH_NODE *nn, **rn; + void *ret; + + lh->error = 0; + if ((lh->up_load <= (lh->num_items * LH_LOAD_MULT / lh->num_nodes)) && !expand(lh)) + return NULL; /* 'lh->error++' already done in 'expand' */ + + rn = getrn(lh, data, &hash); + + if (*rn == NULL) { + if ((nn = OPENSSL_malloc(sizeof(*nn))) == NULL) { + lh->error++; + return NULL; + } + nn->data = data; + nn->next = NULL; + nn->hash = hash; + *rn = nn; + ret = NULL; + lh->num_insert++; + lh->num_items++; + } else { /* replace same key */ + ret = (*rn)->data; + (*rn)->data = data; + lh->num_replace++; + } + return ret; +} + +void *OPENSSL_LH_delete(OPENSSL_LHASH *lh, const void *data) +{ + unsigned long hash; + OPENSSL_LH_NODE *nn, **rn; + void *ret; + + lh->error = 0; + rn = getrn(lh, data, &hash); + + if (*rn == NULL) { + lh->num_no_delete++; + return NULL; + } else { + nn = *rn; + *rn = nn->next; + ret = nn->data; + OPENSSL_free(nn); + lh->num_delete++; + } + + lh->num_items--; + if ((lh->num_nodes > MIN_NODES) && + (lh->down_load >= (lh->num_items * LH_LOAD_MULT / lh->num_nodes))) + contract(lh); + + return ret; +} + +void *OPENSSL_LH_retrieve(OPENSSL_LHASH *lh, const void *data) +{ + unsigned long hash; + OPENSSL_LH_NODE **rn; + void *ret; + + tsan_store((TSAN_QUALIFIER int *)&lh->error, 0); + + rn = getrn(lh, data, &hash); + + if (*rn == NULL) { + tsan_counter(&lh->num_retrieve_miss); + return NULL; + } else { + ret = (*rn)->data; + tsan_counter(&lh->num_retrieve); + } + + return ret; +} + +static void doall_util_fn(OPENSSL_LHASH *lh, int use_arg, + OPENSSL_LH_DOALL_FUNC func, + OPENSSL_LH_DOALL_FUNCARG func_arg, void *arg) +{ + int i; + OPENSSL_LH_NODE *a, *n; + + if (lh == NULL) + return; + + /* + * reverse the order so we search from 'top to bottom' We were having + * memory leaks otherwise + */ + for (i = lh->num_nodes - 1; i >= 0; i--) { + a = lh->b[i]; + while (a != NULL) { + n = a->next; + if (use_arg) + func_arg(a->data, arg); + else + func(a->data); + a = n; + } + } +} + +void OPENSSL_LH_doall(OPENSSL_LHASH *lh, OPENSSL_LH_DOALL_FUNC func) +{ + doall_util_fn(lh, 0, func, (OPENSSL_LH_DOALL_FUNCARG)0, NULL); +} + +void OPENSSL_LH_doall_arg(OPENSSL_LHASH *lh, OPENSSL_LH_DOALL_FUNCARG func, void *arg) +{ + doall_util_fn(lh, 1, (OPENSSL_LH_DOALL_FUNC)0, func, arg); +} + +static int expand(OPENSSL_LHASH *lh) +{ + OPENSSL_LH_NODE **n, **n1, **n2, *np; + unsigned int p, pmax, nni, j; + unsigned long hash; + + nni = lh->num_alloc_nodes; + p = lh->p; + pmax = lh->pmax; + if (p + 1 >= pmax) { + j = nni * 2; + n = OPENSSL_realloc(lh->b, sizeof(OPENSSL_LH_NODE *) * j); + if (n == NULL) { + lh->error++; + return 0; + } + lh->b = n; + memset(n + nni, 0, sizeof(*n) * (j - nni)); + lh->pmax = nni; + lh->num_alloc_nodes = j; + lh->num_expand_reallocs++; + lh->p = 0; + } else { + lh->p++; + } + + lh->num_nodes++; + lh->num_expands++; + n1 = &(lh->b[p]); + n2 = &(lh->b[p + pmax]); + *n2 = NULL; + + for (np = *n1; np != NULL;) { + hash = np->hash; + if ((hash % nni) != p) { /* move it */ + *n1 = (*n1)->next; + np->next = *n2; + *n2 = np; + } else + n1 = &((*n1)->next); + np = *n1; + } + + return 1; +} + +static void contract(OPENSSL_LHASH *lh) +{ + OPENSSL_LH_NODE **n, *n1, *np; + + np = lh->b[lh->p + lh->pmax - 1]; + lh->b[lh->p + lh->pmax - 1] = NULL; /* 24/07-92 - eay - weird but :-( */ + if (lh->p == 0) { + n = OPENSSL_realloc(lh->b, + (unsigned int)(sizeof(OPENSSL_LH_NODE *) * lh->pmax)); + if (n == NULL) { + /* fputs("realloc error in lhash",stderr); */ + lh->error++; + return; + } + lh->num_contract_reallocs++; + lh->num_alloc_nodes /= 2; + lh->pmax /= 2; + lh->p = lh->pmax - 1; + lh->b = n; + } else + lh->p--; + + lh->num_nodes--; + lh->num_contracts++; + + n1 = lh->b[(int)lh->p]; + if (n1 == NULL) + lh->b[(int)lh->p] = np; + else { + while (n1->next != NULL) + n1 = n1->next; + n1->next = np; + } +} + +static OPENSSL_LH_NODE **getrn(OPENSSL_LHASH *lh, + const void *data, unsigned long *rhash) +{ + OPENSSL_LH_NODE **ret, *n1; + unsigned long hash, nn; + OPENSSL_LH_COMPFUNC cf; + + hash = (*(lh->hash)) (data); + tsan_counter(&lh->num_hash_calls); + *rhash = hash; + + nn = hash % lh->pmax; + if (nn < lh->p) + nn = hash % lh->num_alloc_nodes; + + cf = lh->comp; + ret = &(lh->b[(int)nn]); + for (n1 = *ret; n1 != NULL; n1 = n1->next) { + tsan_counter(&lh->num_hash_comps); + if (n1->hash != hash) { + ret = &(n1->next); + continue; + } + tsan_counter(&lh->num_comp_calls); + if (cf(n1->data, data) == 0) + break; + ret = &(n1->next); + } + return ret; +} + +/* + * The following hash seems to work very well on normal text strings no + * collisions on /usr/dict/words and it distributes on %2^n quite well, not + * as good as MD5, but still good. + */ +unsigned long OPENSSL_LH_strhash(const char *c) +{ + unsigned long ret = 0; + long n; + unsigned long v; + int r; + + if ((c == NULL) || (*c == '\0')) + return ret; + + n = 0x100; + while (*c) { + v = n | (*c); + n += 0x100; + r = (int)((v >> 2) ^ v) & 0x0f; + ret = (ret << r) | (ret >> (32 - r)); + ret &= 0xFFFFFFFFL; + ret ^= v * v; + c++; + } + return (ret >> 16) ^ ret; +} + +unsigned long openssl_lh_strcasehash(const char *c) +{ + unsigned long ret = 0; + long n; + unsigned long v; + int r; + + if (c == NULL || *c == '\0') + return ret; + + for (n = 0x100; *c != '\0'; n += 0x100) { + v = n | ossl_tolower(*c); + r = (int)((v >> 2) ^ v) & 0x0f; + ret = (ret << r) | (ret >> (32 - r)); + ret &= 0xFFFFFFFFL; + ret ^= v * v; + c++; + } + return (ret >> 16) ^ ret; +} + +unsigned long OPENSSL_LH_num_items(const OPENSSL_LHASH *lh) +{ + return lh ? lh->num_items : 0; +} + +unsigned long OPENSSL_LH_get_down_load(const OPENSSL_LHASH *lh) +{ + return lh->down_load; +} + +void OPENSSL_LH_set_down_load(OPENSSL_LHASH *lh, unsigned long down_load) +{ + lh->down_load = down_load; +} + +int OPENSSL_LH_error(OPENSSL_LHASH *lh) +{ + return lh->error; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/lhash/lhash_lcl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/lhash/lhash_lcl.h new file mode 100644 index 000000000..678224acd --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/lhash/lhash_lcl.h @@ -0,0 +1,44 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ +#include + +#include "internal/tsan_assist.h" + +struct lhash_node_st { + void *data; + struct lhash_node_st *next; + unsigned long hash; +}; + +struct lhash_st { + OPENSSL_LH_NODE **b; + OPENSSL_LH_COMPFUNC comp; + OPENSSL_LH_HASHFUNC hash; + unsigned int num_nodes; + unsigned int num_alloc_nodes; + unsigned int p; + unsigned int pmax; + unsigned long up_load; /* load times 256 */ + unsigned long down_load; /* load times 256 */ + unsigned long num_items; + unsigned long num_expands; + unsigned long num_expand_reallocs; + unsigned long num_contracts; + unsigned long num_contract_reallocs; + TSAN_QUALIFIER unsigned long num_hash_calls; + TSAN_QUALIFIER unsigned long num_comp_calls; + unsigned long num_insert; + unsigned long num_replace; + unsigned long num_delete; + unsigned long num_no_delete; + TSAN_QUALIFIER unsigned long num_retrieve; + TSAN_QUALIFIER unsigned long num_retrieve_miss; + TSAN_QUALIFIER unsigned long num_hash_comps; + int error; +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/md2/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/md2/build.info new file mode 100644 index 000000000..e31948c23 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/md2/build.info @@ -0,0 +1,3 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + md2_dgst.c md2_one.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/md2/md2_dgst.c b/trunk/3rdparty/openssl-1.1-fit/crypto/md2/md2_dgst.c new file mode 100644 index 000000000..faa9393f2 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/md2/md2_dgst.c @@ -0,0 +1,173 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include + +/* + * Implemented from RFC1319 The MD2 Message-Digest Algorithm + */ + +#define UCHAR unsigned char + +static void md2_block(MD2_CTX *c, const unsigned char *d); +/* + * The magic S table - I have converted it to hex since it is basically just + * a random byte string. + */ +static const MD2_INT S[256] = { + 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, + 0x3D, 0x36, 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, + 0x62, 0xA7, 0x05, 0xF3, 0xC0, 0xC7, 0x73, 0x8C, + 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, 0x82, 0xCA, + 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, + 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, + 0xBE, 0x4E, 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, + 0xA0, 0xFB, 0xF5, 0x8E, 0xBB, 0x2F, 0xEE, 0x7A, + 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, 0x07, 0x3F, + 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21, + 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, + 0x35, 0x3E, 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, + 0xFF, 0x19, 0x30, 0xB3, 0x48, 0xA5, 0xB5, 0xD1, + 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, 0xAA, 0xC6, + 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, + 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, + 0x45, 0x9D, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, + 0x86, 0x5B, 0xCF, 0x65, 0xE6, 0x2D, 0xA8, 0x02, + 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, 0xB9, 0xF6, + 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F, + 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, + 0xC3, 0x5C, 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, + 0x2C, 0x53, 0x0D, 0x6E, 0x85, 0x28, 0x84, 0x09, + 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, 0x4D, 0x52, + 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, + 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, + 0x78, 0x88, 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, + 0xE9, 0xCB, 0xD5, 0xFE, 0x3B, 0x00, 0x1D, 0x39, + 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, 0xD0, 0xE4, + 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A, + 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, + 0xDB, 0x99, 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14, +}; + +const char *MD2_options(void) +{ + if (sizeof(MD2_INT) == 1) + return "md2(char)"; + else + return "md2(int)"; +} + +int MD2_Init(MD2_CTX *c) +{ + c->num = 0; + memset(c->state, 0, sizeof(c->state)); + memset(c->cksm, 0, sizeof(c->cksm)); + memset(c->data, 0, sizeof(c->data)); + return 1; +} + +int MD2_Update(MD2_CTX *c, const unsigned char *data, size_t len) +{ + register UCHAR *p; + + if (len == 0) + return 1; + + p = c->data; + if (c->num != 0) { + if ((c->num + len) >= MD2_BLOCK) { + memcpy(&(p[c->num]), data, MD2_BLOCK - c->num); + md2_block(c, c->data); + data += (MD2_BLOCK - c->num); + len -= (MD2_BLOCK - c->num); + c->num = 0; + /* drop through and do the rest */ + } else { + memcpy(&(p[c->num]), data, len); + /* data+=len; */ + c->num += (int)len; + return 1; + } + } + /* + * we now can process the input data in blocks of MD2_BLOCK chars and + * save the leftovers to c->data. + */ + while (len >= MD2_BLOCK) { + md2_block(c, data); + data += MD2_BLOCK; + len -= MD2_BLOCK; + } + memcpy(p, data, len); + c->num = (int)len; + return 1; +} + +static void md2_block(MD2_CTX *c, const unsigned char *d) +{ + register MD2_INT t, *sp1, *sp2; + register int i, j; + MD2_INT state[48]; + + sp1 = c->state; + sp2 = c->cksm; + j = sp2[MD2_BLOCK - 1]; + for (i = 0; i < 16; i++) { + state[i] = sp1[i]; + state[i + 16] = t = d[i]; + state[i + 32] = (t ^ sp1[i]); + j = sp2[i] ^= S[t ^ j]; + } + t = 0; + for (i = 0; i < 18; i++) { + for (j = 0; j < 48; j += 8) { + t = state[j + 0] ^= S[t]; + t = state[j + 1] ^= S[t]; + t = state[j + 2] ^= S[t]; + t = state[j + 3] ^= S[t]; + t = state[j + 4] ^= S[t]; + t = state[j + 5] ^= S[t]; + t = state[j + 6] ^= S[t]; + t = state[j + 7] ^= S[t]; + } + t = (t + i) & 0xff; + } + memcpy(sp1, state, 16 * sizeof(MD2_INT)); + OPENSSL_cleanse(state, 48 * sizeof(MD2_INT)); +} + +int MD2_Final(unsigned char *md, MD2_CTX *c) +{ + int i, v; + register UCHAR *cp; + register MD2_INT *p1, *p2; + + cp = c->data; + p1 = c->state; + p2 = c->cksm; + v = MD2_BLOCK - c->num; + for (i = c->num; i < MD2_BLOCK; i++) + cp[i] = (UCHAR) v; + + md2_block(c, cp); + + for (i = 0; i < MD2_BLOCK; i++) + cp[i] = (UCHAR) p2[i]; + md2_block(c, cp); + + for (i = 0; i < 16; i++) + md[i] = (UCHAR) (p1[i] & 0xff); + OPENSSL_cleanse(c, sizeof(*c)); + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/md2/md2_one.c b/trunk/3rdparty/openssl-1.1-fit/crypto/md2/md2_one.c new file mode 100644 index 000000000..5502b2169 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/md2/md2_one.c @@ -0,0 +1,47 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include + +/* + * This is a separate file so that #defines in cryptlib.h can map my MD + * functions to different names + */ + +unsigned char *MD2(const unsigned char *d, size_t n, unsigned char *md) +{ + MD2_CTX c; + static unsigned char m[MD2_DIGEST_LENGTH]; + + if (md == NULL) + md = m; + if (!MD2_Init(&c)) + return NULL; +#ifndef CHARSET_EBCDIC + MD2_Update(&c, d, n); +#else + { + char temp[1024]; + unsigned long chunk; + + while (n > 0) { + chunk = (n > sizeof(temp)) ? sizeof(temp) : n; + ebcdic2ascii(temp, d, chunk); + MD2_Update(&c, temp, chunk); + n -= chunk; + d += chunk; + } + } +#endif + MD2_Final(md, &c); + OPENSSL_cleanse(&c, sizeof(c)); /* Security consideration */ + return md; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/md4/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/md4/build.info new file mode 100644 index 000000000..20846e0dc --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/md4/build.info @@ -0,0 +1,3 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + md4_dgst.c md4_one.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/md4/md4_dgst.c b/trunk/3rdparty/openssl-1.1-fit/crypto/md4/md4_dgst.c new file mode 100644 index 000000000..531961861 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/md4/md4_dgst.c @@ -0,0 +1,147 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "md4_locl.h" + +/* + * Implemented from RFC1186 The MD4 Message-Digest Algorithm + */ + +#define INIT_DATA_A (unsigned long)0x67452301L +#define INIT_DATA_B (unsigned long)0xefcdab89L +#define INIT_DATA_C (unsigned long)0x98badcfeL +#define INIT_DATA_D (unsigned long)0x10325476L + +int MD4_Init(MD4_CTX *c) +{ + memset(c, 0, sizeof(*c)); + c->A = INIT_DATA_A; + c->B = INIT_DATA_B; + c->C = INIT_DATA_C; + c->D = INIT_DATA_D; + return 1; +} + +#ifndef md4_block_data_order +# ifdef X +# undef X +# endif +void md4_block_data_order(MD4_CTX *c, const void *data_, size_t num) +{ + const unsigned char *data = data_; + register unsigned MD32_REG_T A, B, C, D, l; +# ifndef MD32_XARRAY + /* See comment in crypto/sha/sha_locl.h for details. */ + unsigned MD32_REG_T XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, + XX8, XX9, XX10, XX11, XX12, XX13, XX14, XX15; +# define X(i) XX##i +# else + MD4_LONG XX[MD4_LBLOCK]; +# define X(i) XX[i] +# endif + + A = c->A; + B = c->B; + C = c->C; + D = c->D; + + for (; num--;) { + (void)HOST_c2l(data, l); + X(0) = l; + (void)HOST_c2l(data, l); + X(1) = l; + /* Round 0 */ + R0(A, B, C, D, X(0), 3, 0); + (void)HOST_c2l(data, l); + X(2) = l; + R0(D, A, B, C, X(1), 7, 0); + (void)HOST_c2l(data, l); + X(3) = l; + R0(C, D, A, B, X(2), 11, 0); + (void)HOST_c2l(data, l); + X(4) = l; + R0(B, C, D, A, X(3), 19, 0); + (void)HOST_c2l(data, l); + X(5) = l; + R0(A, B, C, D, X(4), 3, 0); + (void)HOST_c2l(data, l); + X(6) = l; + R0(D, A, B, C, X(5), 7, 0); + (void)HOST_c2l(data, l); + X(7) = l; + R0(C, D, A, B, X(6), 11, 0); + (void)HOST_c2l(data, l); + X(8) = l; + R0(B, C, D, A, X(7), 19, 0); + (void)HOST_c2l(data, l); + X(9) = l; + R0(A, B, C, D, X(8), 3, 0); + (void)HOST_c2l(data, l); + X(10) = l; + R0(D, A, B, C, X(9), 7, 0); + (void)HOST_c2l(data, l); + X(11) = l; + R0(C, D, A, B, X(10), 11, 0); + (void)HOST_c2l(data, l); + X(12) = l; + R0(B, C, D, A, X(11), 19, 0); + (void)HOST_c2l(data, l); + X(13) = l; + R0(A, B, C, D, X(12), 3, 0); + (void)HOST_c2l(data, l); + X(14) = l; + R0(D, A, B, C, X(13), 7, 0); + (void)HOST_c2l(data, l); + X(15) = l; + R0(C, D, A, B, X(14), 11, 0); + R0(B, C, D, A, X(15), 19, 0); + /* Round 1 */ + R1(A, B, C, D, X(0), 3, 0x5A827999L); + R1(D, A, B, C, X(4), 5, 0x5A827999L); + R1(C, D, A, B, X(8), 9, 0x5A827999L); + R1(B, C, D, A, X(12), 13, 0x5A827999L); + R1(A, B, C, D, X(1), 3, 0x5A827999L); + R1(D, A, B, C, X(5), 5, 0x5A827999L); + R1(C, D, A, B, X(9), 9, 0x5A827999L); + R1(B, C, D, A, X(13), 13, 0x5A827999L); + R1(A, B, C, D, X(2), 3, 0x5A827999L); + R1(D, A, B, C, X(6), 5, 0x5A827999L); + R1(C, D, A, B, X(10), 9, 0x5A827999L); + R1(B, C, D, A, X(14), 13, 0x5A827999L); + R1(A, B, C, D, X(3), 3, 0x5A827999L); + R1(D, A, B, C, X(7), 5, 0x5A827999L); + R1(C, D, A, B, X(11), 9, 0x5A827999L); + R1(B, C, D, A, X(15), 13, 0x5A827999L); + /* Round 2 */ + R2(A, B, C, D, X(0), 3, 0x6ED9EBA1L); + R2(D, A, B, C, X(8), 9, 0x6ED9EBA1L); + R2(C, D, A, B, X(4), 11, 0x6ED9EBA1L); + R2(B, C, D, A, X(12), 15, 0x6ED9EBA1L); + R2(A, B, C, D, X(2), 3, 0x6ED9EBA1L); + R2(D, A, B, C, X(10), 9, 0x6ED9EBA1L); + R2(C, D, A, B, X(6), 11, 0x6ED9EBA1L); + R2(B, C, D, A, X(14), 15, 0x6ED9EBA1L); + R2(A, B, C, D, X(1), 3, 0x6ED9EBA1L); + R2(D, A, B, C, X(9), 9, 0x6ED9EBA1L); + R2(C, D, A, B, X(5), 11, 0x6ED9EBA1L); + R2(B, C, D, A, X(13), 15, 0x6ED9EBA1L); + R2(A, B, C, D, X(3), 3, 0x6ED9EBA1L); + R2(D, A, B, C, X(11), 9, 0x6ED9EBA1L); + R2(C, D, A, B, X(7), 11, 0x6ED9EBA1L); + R2(B, C, D, A, X(15), 15, 0x6ED9EBA1L); + + A = c->A += A; + B = c->B += B; + C = c->C += C; + D = c->D += D; + } +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/md4/md4_locl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/md4/md4_locl.h new file mode 100644 index 000000000..a6c4003fd --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/md4/md4_locl.h @@ -0,0 +1,60 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include + +void md4_block_data_order(MD4_CTX *c, const void *p, size_t num); + +#define DATA_ORDER_IS_LITTLE_ENDIAN + +#define HASH_LONG MD4_LONG +#define HASH_CTX MD4_CTX +#define HASH_CBLOCK MD4_CBLOCK +#define HASH_UPDATE MD4_Update +#define HASH_TRANSFORM MD4_Transform +#define HASH_FINAL MD4_Final +#define HASH_MAKE_STRING(c,s) do { \ + unsigned long ll; \ + ll=(c)->A; (void)HOST_l2c(ll,(s)); \ + ll=(c)->B; (void)HOST_l2c(ll,(s)); \ + ll=(c)->C; (void)HOST_l2c(ll,(s)); \ + ll=(c)->D; (void)HOST_l2c(ll,(s)); \ + } while (0) +#define HASH_BLOCK_DATA_ORDER md4_block_data_order + +#include "internal/md32_common.h" + +/*- +#define F(x,y,z) (((x) & (y)) | ((~(x)) & (z))) +#define G(x,y,z) (((x) & (y)) | ((x) & ((z))) | ((y) & ((z)))) +*/ + +/* + * As pointed out by Wei Dai, the above can be simplified to the code + * below. Wei attributes these optimizations to Peter Gutmann's SHS code, + * and he attributes it to Rich Schroeppel. + */ +#define F(b,c,d) ((((c) ^ (d)) & (b)) ^ (d)) +#define G(b,c,d) (((b) & (c)) | ((b) & (d)) | ((c) & (d))) +#define H(b,c,d) ((b) ^ (c) ^ (d)) + +#define R0(a,b,c,d,k,s,t) { \ + a+=((k)+(t)+F((b),(c),(d))); \ + a=ROTATE(a,s); }; + +#define R1(a,b,c,d,k,s,t) { \ + a+=((k)+(t)+G((b),(c),(d))); \ + a=ROTATE(a,s); };\ + +#define R2(a,b,c,d,k,s,t) { \ + a+=((k)+(t)+H((b),(c),(d))); \ + a=ROTATE(a,s); }; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/md4/md4_one.c b/trunk/3rdparty/openssl-1.1-fit/crypto/md4/md4_one.c new file mode 100644 index 000000000..9e52303c2 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/md4/md4_one.c @@ -0,0 +1,47 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include + +#ifdef CHARSET_EBCDIC +# include +#endif + +unsigned char *MD4(const unsigned char *d, size_t n, unsigned char *md) +{ + MD4_CTX c; + static unsigned char m[MD4_DIGEST_LENGTH]; + + if (md == NULL) + md = m; + if (!MD4_Init(&c)) + return NULL; +#ifndef CHARSET_EBCDIC + MD4_Update(&c, d, n); +#else + { + char temp[1024]; + unsigned long chunk; + + while (n > 0) { + chunk = (n > sizeof(temp)) ? sizeof(temp) : n; + ebcdic2ascii(temp, d, chunk); + MD4_Update(&c, temp, chunk); + n -= chunk; + d += chunk; + } + } +#endif + MD4_Final(md, &c); + OPENSSL_cleanse(&c, sizeof(c)); /* security consideration */ + return md; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/md5/asm/md5-586.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/md5/asm/md5-586.pl new file mode 100644 index 000000000..15e14864d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/md5/asm/md5-586.pl @@ -0,0 +1,318 @@ +#! /usr/bin/env perl +# Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# Normal is the +# md5_block_x86(MD5_CTX *c, ULONG *X); +# version, non-normal is the +# md5_block_x86(MD5_CTX *c, ULONG *X,int blocks); + +$normal=0; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +$output=pop; +open STDOUT,">$output"; + +&asm_init($ARGV[0]); + +$A="eax"; +$B="ebx"; +$C="ecx"; +$D="edx"; +$tmp1="edi"; +$tmp2="ebp"; +$X="esi"; + +# What we need to load into $tmp for the next round +%Ltmp1=("R0",&Np($C), "R1",&Np($C), "R2",&Np($C), "R3",&Np($D)); +@xo=( + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, # R0 + 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, # R1 + 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, # R2 + 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9, # R3 + ); + +&md5_block("md5_block_asm_data_order"); +&asm_finish(); + +close STDOUT; + +sub Np + { + local($p)=@_; + local(%n)=($A,$D,$B,$A,$C,$B,$D,$C); + return($n{$p}); + } + +sub R0 + { + local($pos,$a,$b,$c,$d,$K,$ki,$s,$t)=@_; + + &mov($tmp1,$C) if $pos < 0; + &mov($tmp2,&DWP($xo[$ki]*4,$K,"",0)) if $pos < 0; # very first one + + # body proper + + &comment("R0 $ki"); + &xor($tmp1,$d); # F function - part 2 + + &and($tmp1,$b); # F function - part 3 + &lea($a,&DWP($t,$a,$tmp2,1)); + + &xor($tmp1,$d); # F function - part 4 + &mov($tmp2,&DWP($xo[$ki+1]*4,$K,"",0)) if ($pos != 2); + + &add($a,$tmp1); + + &rotl($a,$s); + + &mov($tmp1,&Np($c)) if $pos < 1; # next tmp1 for R0 + &mov($tmp1,&Np($c)) if $pos == 1; # next tmp1 for R1 + + &add($a,$b); + } + +sub R1 + { + local($pos,$a,$b,$c,$d,$K,$ki,$s,$t)=@_; + + &comment("R1 $ki"); + + &xor($tmp1,$b); # G function - part 2 + &and($tmp1,$d); # G function - part 3 + &lea($a,&DWP($t,$a,$tmp2,1)); + + &xor($tmp1,$c); # G function - part 4 + &mov($tmp2,&DWP($xo[$ki+1]*4,$K,"",0)) if ($pos != 2); + + &add($a,$tmp1); + &mov($tmp1,&Np($c)) if $pos < 1; # G function - part 1 + &mov($tmp1,&Np($c)) if $pos == 1; # G function - part 1 + + &rotl($a,$s); + + &add($a,$b); + } + +sub R2 + { + local($n,$pos,$a,$b,$c,$d,$K,$ki,$s,$t)=@_; + # This one is different, only 3 logical operations + +if (($n & 1) == 0) + { + &comment("R2 $ki"); + # make sure to do 'D' first, not 'B', else we clash with + # the last add from the previous round. + + &xor($tmp1,$d); # H function - part 2 + + &xor($tmp1,$b); # H function - part 3 + &lea($a,&DWP($t,$a,$tmp2,1)); + + &add($a,$tmp1); + &mov($tmp2,&DWP($xo[$ki+1]*4,$K,"",0)); + + &rotl($a,$s); + + &mov($tmp1,&Np($c)); + } +else + { + &comment("R2 $ki"); + # make sure to do 'D' first, not 'B', else we clash with + # the last add from the previous round. + + &add($b,$c); # MOVED FORWARD + &xor($tmp1,$d); # H function - part 2 + + &lea($a,&DWP($t,$a,$tmp2,1)); + + &xor($tmp1,$b); # H function - part 3 + &mov($tmp2,&DWP($xo[$ki+1]*4,$K,"",0)) if ($pos != 2); + + &add($a,$tmp1); + &mov($tmp1,&Np($c)) if $pos < 1; # H function - part 1 + &mov($tmp1,-1) if $pos == 1; # I function - part 1 + + &rotl($a,$s); + + &add($a,$b); + } + } + +sub R3 + { + local($pos,$a,$b,$c,$d,$K,$ki,$s,$t)=@_; + + &comment("R3 $ki"); + + # ¬($tmp1) + &xor($tmp1,$d) if $pos < 0; # I function - part 2 + + &or($tmp1,$b); # I function - part 3 + &lea($a,&DWP($t,$a,$tmp2,1)); + + &xor($tmp1,$c); # I function - part 4 + &mov($tmp2,&DWP($xo[$ki+1]*4,$K,"",0)) if $pos != 2; # load X/k value + &mov($tmp2,&wparam(0)) if $pos == 2; + + &add($a,$tmp1); + &mov($tmp1,-1) if $pos < 1; # H function - part 1 + &add($K,64) if $pos >=1 && !$normal; + + &rotl($a,$s); + + &xor($tmp1,&Np($d)) if $pos <= 0; # I function - part = first time + &mov($tmp1,&DWP( 0,$tmp2,"",0)) if $pos > 0; + &add($a,$b); + } + + +sub md5_block + { + local($name)=@_; + + &function_begin_B($name,"",3); + + # parameter 1 is the MD5_CTX structure. + # A 0 + # B 4 + # C 8 + # D 12 + + &push("esi"); + &push("edi"); + &mov($tmp1, &wparam(0)); # edi + &mov($X, &wparam(1)); # esi + &mov($C, &wparam(2)); + &push("ebp"); + &shl($C, 6); + &push("ebx"); + &add($C, $X); # offset we end at + &sub($C, 64); + &mov($A, &DWP( 0,$tmp1,"",0)); + &push($C); # Put on the TOS + &mov($B, &DWP( 4,$tmp1,"",0)); + &mov($C, &DWP( 8,$tmp1,"",0)); + &mov($D, &DWP(12,$tmp1,"",0)); + + &set_label("start") unless $normal; + &comment(""); + &comment("R0 section"); + + &R0(-2,$A,$B,$C,$D,$X, 0, 7,0xd76aa478); + &R0( 0,$D,$A,$B,$C,$X, 1,12,0xe8c7b756); + &R0( 0,$C,$D,$A,$B,$X, 2,17,0x242070db); + &R0( 0,$B,$C,$D,$A,$X, 3,22,0xc1bdceee); + &R0( 0,$A,$B,$C,$D,$X, 4, 7,0xf57c0faf); + &R0( 0,$D,$A,$B,$C,$X, 5,12,0x4787c62a); + &R0( 0,$C,$D,$A,$B,$X, 6,17,0xa8304613); + &R0( 0,$B,$C,$D,$A,$X, 7,22,0xfd469501); + &R0( 0,$A,$B,$C,$D,$X, 8, 7,0x698098d8); + &R0( 0,$D,$A,$B,$C,$X, 9,12,0x8b44f7af); + &R0( 0,$C,$D,$A,$B,$X,10,17,0xffff5bb1); + &R0( 0,$B,$C,$D,$A,$X,11,22,0x895cd7be); + &R0( 0,$A,$B,$C,$D,$X,12, 7,0x6b901122); + &R0( 0,$D,$A,$B,$C,$X,13,12,0xfd987193); + &R0( 0,$C,$D,$A,$B,$X,14,17,0xa679438e); + &R0( 1,$B,$C,$D,$A,$X,15,22,0x49b40821); + + &comment(""); + &comment("R1 section"); + &R1(-1,$A,$B,$C,$D,$X,16, 5,0xf61e2562); + &R1( 0,$D,$A,$B,$C,$X,17, 9,0xc040b340); + &R1( 0,$C,$D,$A,$B,$X,18,14,0x265e5a51); + &R1( 0,$B,$C,$D,$A,$X,19,20,0xe9b6c7aa); + &R1( 0,$A,$B,$C,$D,$X,20, 5,0xd62f105d); + &R1( 0,$D,$A,$B,$C,$X,21, 9,0x02441453); + &R1( 0,$C,$D,$A,$B,$X,22,14,0xd8a1e681); + &R1( 0,$B,$C,$D,$A,$X,23,20,0xe7d3fbc8); + &R1( 0,$A,$B,$C,$D,$X,24, 5,0x21e1cde6); + &R1( 0,$D,$A,$B,$C,$X,25, 9,0xc33707d6); + &R1( 0,$C,$D,$A,$B,$X,26,14,0xf4d50d87); + &R1( 0,$B,$C,$D,$A,$X,27,20,0x455a14ed); + &R1( 0,$A,$B,$C,$D,$X,28, 5,0xa9e3e905); + &R1( 0,$D,$A,$B,$C,$X,29, 9,0xfcefa3f8); + &R1( 0,$C,$D,$A,$B,$X,30,14,0x676f02d9); + &R1( 1,$B,$C,$D,$A,$X,31,20,0x8d2a4c8a); + + &comment(""); + &comment("R2 section"); + &R2( 0,-1,$A,$B,$C,$D,$X,32, 4,0xfffa3942); + &R2( 1, 0,$D,$A,$B,$C,$X,33,11,0x8771f681); + &R2( 2, 0,$C,$D,$A,$B,$X,34,16,0x6d9d6122); + &R2( 3, 0,$B,$C,$D,$A,$X,35,23,0xfde5380c); + &R2( 4, 0,$A,$B,$C,$D,$X,36, 4,0xa4beea44); + &R2( 5, 0,$D,$A,$B,$C,$X,37,11,0x4bdecfa9); + &R2( 6, 0,$C,$D,$A,$B,$X,38,16,0xf6bb4b60); + &R2( 7, 0,$B,$C,$D,$A,$X,39,23,0xbebfbc70); + &R2( 8, 0,$A,$B,$C,$D,$X,40, 4,0x289b7ec6); + &R2( 9, 0,$D,$A,$B,$C,$X,41,11,0xeaa127fa); + &R2(10, 0,$C,$D,$A,$B,$X,42,16,0xd4ef3085); + &R2(11, 0,$B,$C,$D,$A,$X,43,23,0x04881d05); + &R2(12, 0,$A,$B,$C,$D,$X,44, 4,0xd9d4d039); + &R2(13, 0,$D,$A,$B,$C,$X,45,11,0xe6db99e5); + &R2(14, 0,$C,$D,$A,$B,$X,46,16,0x1fa27cf8); + &R2(15, 1,$B,$C,$D,$A,$X,47,23,0xc4ac5665); + + &comment(""); + &comment("R3 section"); + &R3(-1,$A,$B,$C,$D,$X,48, 6,0xf4292244); + &R3( 0,$D,$A,$B,$C,$X,49,10,0x432aff97); + &R3( 0,$C,$D,$A,$B,$X,50,15,0xab9423a7); + &R3( 0,$B,$C,$D,$A,$X,51,21,0xfc93a039); + &R3( 0,$A,$B,$C,$D,$X,52, 6,0x655b59c3); + &R3( 0,$D,$A,$B,$C,$X,53,10,0x8f0ccc92); + &R3( 0,$C,$D,$A,$B,$X,54,15,0xffeff47d); + &R3( 0,$B,$C,$D,$A,$X,55,21,0x85845dd1); + &R3( 0,$A,$B,$C,$D,$X,56, 6,0x6fa87e4f); + &R3( 0,$D,$A,$B,$C,$X,57,10,0xfe2ce6e0); + &R3( 0,$C,$D,$A,$B,$X,58,15,0xa3014314); + &R3( 0,$B,$C,$D,$A,$X,59,21,0x4e0811a1); + &R3( 0,$A,$B,$C,$D,$X,60, 6,0xf7537e82); + &R3( 0,$D,$A,$B,$C,$X,61,10,0xbd3af235); + &R3( 0,$C,$D,$A,$B,$X,62,15,0x2ad7d2bb); + &R3( 2,$B,$C,$D,$A,$X,63,21,0xeb86d391); + + # &mov($tmp2,&wparam(0)); # done in the last R3 + # &mov($tmp1, &DWP( 0,$tmp2,"",0)); # done is the last R3 + + &add($A,$tmp1); + &mov($tmp1, &DWP( 4,$tmp2,"",0)); + + &add($B,$tmp1); + &mov($tmp1, &DWP( 8,$tmp2,"",0)); + + &add($C,$tmp1); + &mov($tmp1, &DWP(12,$tmp2,"",0)); + + &add($D,$tmp1); + &mov(&DWP( 0,$tmp2,"",0),$A); + + &mov(&DWP( 4,$tmp2,"",0),$B); + &mov($tmp1,&swtmp(0)) unless $normal; + + &mov(&DWP( 8,$tmp2,"",0),$C); + &mov(&DWP(12,$tmp2,"",0),$D); + + &cmp($tmp1,$X) unless $normal; # check count + &jae(&label("start")) unless $normal; + + &pop("eax"); # pop the temp variable off the stack + &pop("ebx"); + &pop("ebp"); + &pop("edi"); + &pop("esi"); + &ret(); + &function_end_B($name); + } + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/md5/asm/md5-sparcv9.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/md5/asm/md5-sparcv9.pl new file mode 100644 index 000000000..6a62c6253 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/md5/asm/md5-sparcv9.pl @@ -0,0 +1,437 @@ +#! /usr/bin/env perl +# Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# +# Hardware SPARC T4 support by David S. Miller. +# ==================================================================== + +# MD5 for SPARCv9, 6.9 cycles per byte on UltraSPARC, >40% faster than +# code generated by Sun C 5.2. + +# SPARC T4 MD5 hardware achieves 3.20 cycles per byte, which is 2.1x +# faster than software. Multi-process benchmark saturates at 12x +# single-process result on 8-core processor, or ~11GBps per 2.85GHz +# socket. + +$output=pop; +open STDOUT,">$output"; + +use integer; + +($ctx,$inp,$len)=("%i0","%i1","%i2"); # input arguments + +# 64-bit values +@X=("%o0","%o1","%o2","%o3","%o4","%o5","%o7","%g1","%g2"); +$tx="%g3"; +($AB,$CD)=("%g4","%g5"); + +# 32-bit values +@V=($A,$B,$C,$D)=map("%l$_",(0..3)); +($t1,$t2,$t3,$saved_asi)=map("%l$_",(4..7)); +($shr,$shl1,$shl2)=("%i3","%i4","%i5"); + +my @K=( 0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee, + 0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501, + 0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be, + 0x6b901122,0xfd987193,0xa679438e,0x49b40821, + + 0xf61e2562,0xc040b340,0x265e5a51,0xe9b6c7aa, + 0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8, + 0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed, + 0xa9e3e905,0xfcefa3f8,0x676f02d9,0x8d2a4c8a, + + 0xfffa3942,0x8771f681,0x6d9d6122,0xfde5380c, + 0xa4beea44,0x4bdecfa9,0xf6bb4b60,0xbebfbc70, + 0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05, + 0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665, + + 0xf4292244,0x432aff97,0xab9423a7,0xfc93a039, + 0x655b59c3,0x8f0ccc92,0xffeff47d,0x85845dd1, + 0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1, + 0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391, 0 ); + +sub R0 { + my ($i,$a,$b,$c,$d) = @_; + my $rot = (7,12,17,22)[$i%4]; + my $j = ($i+1)/2; + + if ($i&1) { + $code.=<<___; + srlx @X[$j],$shr,@X[$j] ! align X[`$i+1`] + and $b,$t1,$t1 ! round $i + sllx @X[$j+1],$shl1,$tx + add $t2,$a,$a + sllx $tx,$shl2,$tx + xor $d,$t1,$t1 + or $tx,@X[$j],@X[$j] + sethi %hi(@K[$i+1]),$t2 + add $t1,$a,$a + or $t2,%lo(@K[$i+1]),$t2 + sll $a,$rot,$t3 + add @X[$j],$t2,$t2 ! X[`$i+1`]+K[`$i+1`] + srl $a,32-$rot,$a + add $b,$t3,$t3 + xor $b,$c,$t1 + add $t3,$a,$a +___ + } else { + $code.=<<___; + srlx @X[$j],32,$tx ! extract X[`2*$j+1`] + and $b,$t1,$t1 ! round $i + add $t2,$a,$a + xor $d,$t1,$t1 + sethi %hi(@K[$i+1]),$t2 + add $t1,$a,$a + or $t2,%lo(@K[$i+1]),$t2 + sll $a,$rot,$t3 + add $tx,$t2,$t2 ! X[`2*$j+1`]+K[`$i+1`] + srl $a,32-$rot,$a + add $b,$t3,$t3 + xor $b,$c,$t1 + add $t3,$a,$a +___ + } +} + +sub R0_1 { + my ($i,$a,$b,$c,$d) = @_; + my $rot = (7,12,17,22)[$i%4]; + +$code.=<<___; + srlx @X[0],32,$tx ! extract X[1] + and $b,$t1,$t1 ! round $i + add $t2,$a,$a + xor $d,$t1,$t1 + sethi %hi(@K[$i+1]),$t2 + add $t1,$a,$a + or $t2,%lo(@K[$i+1]),$t2 + sll $a,$rot,$t3 + add $tx,$t2,$t2 ! X[1]+K[`$i+1`] + srl $a,32-$rot,$a + add $b,$t3,$t3 + andn $b,$c,$t1 + add $t3,$a,$a +___ +} + +sub R1 { + my ($i,$a,$b,$c,$d) = @_; + my $rot = (5,9,14,20)[$i%4]; + my $j = $i<31 ? (1+5*($i+1))%16 : (5+3*($i+1))%16; + my $xi = @X[$j/2]; + +$code.=<<___ if ($j&1 && ($xi=$tx)); + srlx @X[$j/2],32,$xi ! extract X[$j] +___ +$code.=<<___; + and $b,$d,$t3 ! round $i + add $t2,$a,$a + or $t3,$t1,$t1 + sethi %hi(@K[$i+1]),$t2 + add $t1,$a,$a + or $t2,%lo(@K[$i+1]),$t2 + sll $a,$rot,$t3 + add $xi,$t2,$t2 ! X[$j]+K[`$i+1`] + srl $a,32-$rot,$a + add $b,$t3,$t3 + `$i<31?"andn":"xor"` $b,$c,$t1 + add $t3,$a,$a +___ +} + +sub R2 { + my ($i,$a,$b,$c,$d) = @_; + my $rot = (4,11,16,23)[$i%4]; + my $j = $i<47 ? (5+3*($i+1))%16 : (0+7*($i+1))%16; + my $xi = @X[$j/2]; + +$code.=<<___ if ($j&1 && ($xi=$tx)); + srlx @X[$j/2],32,$xi ! extract X[$j] +___ +$code.=<<___; + add $t2,$a,$a ! round $i + xor $b,$t1,$t1 + sethi %hi(@K[$i+1]),$t2 + add $t1,$a,$a + or $t2,%lo(@K[$i+1]),$t2 + sll $a,$rot,$t3 + add $xi,$t2,$t2 ! X[$j]+K[`$i+1`] + srl $a,32-$rot,$a + add $b,$t3,$t3 + xor $b,$c,$t1 + add $t3,$a,$a +___ +} + +sub R3 { + my ($i,$a,$b,$c,$d) = @_; + my $rot = (6,10,15,21)[$i%4]; + my $j = (0+7*($i+1))%16; + my $xi = @X[$j/2]; + +$code.=<<___; + add $t2,$a,$a ! round $i +___ +$code.=<<___ if ($j&1 && ($xi=$tx)); + srlx @X[$j/2],32,$xi ! extract X[$j] +___ +$code.=<<___; + orn $b,$d,$t1 + sethi %hi(@K[$i+1]),$t2 + xor $c,$t1,$t1 + or $t2,%lo(@K[$i+1]),$t2 + add $t1,$a,$a + sll $a,$rot,$t3 + add $xi,$t2,$t2 ! X[$j]+K[`$i+1`] + srl $a,32-$rot,$a + add $b,$t3,$t3 + add $t3,$a,$a +___ +} + +$code.=<<___; +#include "sparc_arch.h" + +#ifdef __arch64__ +.register %g2,#scratch +.register %g3,#scratch +#endif + +.section ".text",#alloc,#execinstr + +#ifdef __PIC__ +SPARC_PIC_THUNK(%g1) +#endif + +.globl md5_block_asm_data_order +.align 32 +md5_block_asm_data_order: + SPARC_LOAD_ADDRESS_LEAF(OPENSSL_sparcv9cap_P,%g1,%g5) + ld [%g1+4],%g1 ! OPENSSL_sparcv9cap_P[1] + + andcc %g1, CFR_MD5, %g0 + be .Lsoftware + nop + + mov 4, %g1 + andcc %o1, 0x7, %g0 + lda [%o0 + %g0]0x88, %f0 ! load context + lda [%o0 + %g1]0x88, %f1 + add %o0, 8, %o0 + lda [%o0 + %g0]0x88, %f2 + lda [%o0 + %g1]0x88, %f3 + bne,pn %icc, .Lhwunaligned + sub %o0, 8, %o0 + +.Lhw_loop: + ldd [%o1 + 0x00], %f8 + ldd [%o1 + 0x08], %f10 + ldd [%o1 + 0x10], %f12 + ldd [%o1 + 0x18], %f14 + ldd [%o1 + 0x20], %f16 + ldd [%o1 + 0x28], %f18 + ldd [%o1 + 0x30], %f20 + subcc %o2, 1, %o2 ! done yet? + ldd [%o1 + 0x38], %f22 + add %o1, 0x40, %o1 + prefetch [%o1 + 63], 20 + + .word 0x81b02800 ! MD5 + + bne,pt SIZE_T_CC, .Lhw_loop + nop + +.Lhwfinish: + sta %f0, [%o0 + %g0]0x88 ! store context + sta %f1, [%o0 + %g1]0x88 + add %o0, 8, %o0 + sta %f2, [%o0 + %g0]0x88 + sta %f3, [%o0 + %g1]0x88 + retl + nop + +.align 8 +.Lhwunaligned: + alignaddr %o1, %g0, %o1 + + ldd [%o1 + 0x00], %f10 +.Lhwunaligned_loop: + ldd [%o1 + 0x08], %f12 + ldd [%o1 + 0x10], %f14 + ldd [%o1 + 0x18], %f16 + ldd [%o1 + 0x20], %f18 + ldd [%o1 + 0x28], %f20 + ldd [%o1 + 0x30], %f22 + ldd [%o1 + 0x38], %f24 + subcc %o2, 1, %o2 ! done yet? + ldd [%o1 + 0x40], %f26 + add %o1, 0x40, %o1 + prefetch [%o1 + 63], 20 + + faligndata %f10, %f12, %f8 + faligndata %f12, %f14, %f10 + faligndata %f14, %f16, %f12 + faligndata %f16, %f18, %f14 + faligndata %f18, %f20, %f16 + faligndata %f20, %f22, %f18 + faligndata %f22, %f24, %f20 + faligndata %f24, %f26, %f22 + + .word 0x81b02800 ! MD5 + + bne,pt SIZE_T_CC, .Lhwunaligned_loop + for %f26, %f26, %f10 ! %f10=%f26 + + ba .Lhwfinish + nop + +.align 16 +.Lsoftware: + save %sp,-STACK_FRAME,%sp + + rd %asi,$saved_asi + wr %g0,0x88,%asi ! ASI_PRIMARY_LITTLE + and $inp,7,$shr + andn $inp,7,$inp + + sll $shr,3,$shr ! *=8 + mov 56,$shl2 + ld [$ctx+0],$A + sub $shl2,$shr,$shl2 + ld [$ctx+4],$B + and $shl2,32,$shl1 + add $shl2,8,$shl2 + ld [$ctx+8],$C + sub $shl2,$shl1,$shl2 ! shr+shl1+shl2==64 + ld [$ctx+12],$D + nop + +.Loop: + cmp $shr,0 ! was inp aligned? + ldxa [$inp+0]%asi,@X[0] ! load little-endian input + ldxa [$inp+8]%asi,@X[1] + ldxa [$inp+16]%asi,@X[2] + ldxa [$inp+24]%asi,@X[3] + ldxa [$inp+32]%asi,@X[4] + sllx $A,32,$AB ! pack A,B + ldxa [$inp+40]%asi,@X[5] + sllx $C,32,$CD ! pack C,D + ldxa [$inp+48]%asi,@X[6] + or $B,$AB,$AB + ldxa [$inp+56]%asi,@X[7] + or $D,$CD,$CD + bnz,a,pn %icc,.+8 + ldxa [$inp+64]%asi,@X[8] + + srlx @X[0],$shr,@X[0] ! align X[0] + sllx @X[1],$shl1,$tx + sethi %hi(@K[0]),$t2 + sllx $tx,$shl2,$tx + or $t2,%lo(@K[0]),$t2 + or $tx,@X[0],@X[0] + xor $C,$D,$t1 + add @X[0],$t2,$t2 ! X[0]+K[0] +___ + for ($i=0;$i<15;$i++) { &R0($i,@V); unshift(@V,pop(@V)); } + for (;$i<16;$i++) { &R0_1($i,@V); unshift(@V,pop(@V)); } + for (;$i<32;$i++) { &R1($i,@V); unshift(@V,pop(@V)); } + for (;$i<48;$i++) { &R2($i,@V); unshift(@V,pop(@V)); } + for (;$i<64;$i++) { &R3($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + srlx $AB,32,$t1 ! unpack A,B,C,D and accumulate + add $inp,64,$inp ! advance inp + srlx $CD,32,$t2 + add $t1,$A,$A + subcc $len,1,$len ! done yet? + add $AB,$B,$B + add $t2,$C,$C + add $CD,$D,$D + srl $B,0,$B ! clruw $B + bne SIZE_T_CC,.Loop + srl $D,0,$D ! clruw $D + + st $A,[$ctx+0] ! write out ctx + st $B,[$ctx+4] + st $C,[$ctx+8] + st $D,[$ctx+12] + + wr %g0,$saved_asi,%asi + ret + restore +.type md5_block_asm_data_order,#function +.size md5_block_asm_data_order,(.-md5_block_asm_data_order) + +.asciz "MD5 block transform for SPARCv9, CRYPTOGAMS by " +.align 4 +___ + +# Purpose of these subroutines is to explicitly encode VIS instructions, +# so that one can compile the module without having to specify VIS +# extensions on compiler command line, e.g. -xarch=v9 vs. -xarch=v9a. +# Idea is to reserve for option to produce "universal" binary and let +# programmer detect if current CPU is VIS capable at run-time. +sub unvis { +my ($mnemonic,$rs1,$rs2,$rd)=@_; +my $ref,$opf; +my %visopf = ( "faligndata" => 0x048, + "for" => 0x07c ); + + $ref = "$mnemonic\t$rs1,$rs2,$rd"; + + if ($opf=$visopf{$mnemonic}) { + foreach ($rs1,$rs2,$rd) { + return $ref if (!/%f([0-9]{1,2})/); + $_=$1; + if ($1>=32) { + return $ref if ($1&1); + # re-encode for upper double register addressing + $_=($1|$1>>5)&31; + } + } + + return sprintf ".word\t0x%08x !%s", + 0x81b00000|$rd<<25|$rs1<<14|$opf<<5|$rs2, + $ref; + } else { + return $ref; + } +} +sub unalignaddr { +my ($mnemonic,$rs1,$rs2,$rd)=@_; +my %bias = ( "g" => 0, "o" => 8, "l" => 16, "i" => 24 ); +my $ref="$mnemonic\t$rs1,$rs2,$rd"; + + foreach ($rs1,$rs2,$rd) { + if (/%([goli])([0-7])/) { $_=$bias{$1}+$2; } + else { return $ref; } + } + return sprintf ".word\t0x%08x !%s", + 0x81b00300|$rd<<25|$rs1<<14|$rs2, + $ref; +} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/ge; + + s/\b(f[^\s]*)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*(%f[0-9]{1,2})/ + &unvis($1,$2,$3,$4) + /ge; + s/\b(alignaddr)\s+(%[goli][0-7]),\s*(%[goli][0-7]),\s*(%[goli][0-7])/ + &unalignaddr($1,$2,$3,$4) + /ge; + + print $_,"\n"; +} + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/md5/asm/md5-x86_64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/md5/asm/md5-x86_64.pl new file mode 100755 index 000000000..386d8048e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/md5/asm/md5-x86_64.pl @@ -0,0 +1,393 @@ +#! /usr/bin/env perl +# Author: Marc Bevand +# Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# MD5 optimized for AMD64. + +use strict; + +my $code; + +# round1_step() does: +# dst = x + ((dst + F(x,y,z) + X[k] + T_i) <<< s) +# %r10d = X[k_next] +# %r11d = z' (copy of z for the next step) +# Each round1_step() takes about 5.3 clocks (9 instructions, 1.7 IPC) +sub round1_step +{ + my ($pos, $dst, $x, $y, $z, $k_next, $T_i, $s) = @_; + $code .= " mov 0*4(%rsi), %r10d /* (NEXT STEP) X[0] */\n" if ($pos == -1); + $code .= " mov %edx, %r11d /* (NEXT STEP) z' = %edx */\n" if ($pos == -1); + $code .= <A + mov 1*4(%rbp), %ebx # ebx = ctx->B + mov 2*4(%rbp), %ecx # ecx = ctx->C + mov 3*4(%rbp), %edx # edx = ctx->D + # end is 'rdi' + # ptr is 'rsi' + # A is 'eax' + # B is 'ebx' + # C is 'ecx' + # D is 'edx' + + cmp %rdi, %rsi # cmp end with ptr + je .Lend # jmp if ptr == end + + # BEGIN of loop over 16-word blocks +.Lloop: # save old values of A, B, C, D + mov %eax, %r8d + mov %ebx, %r9d + mov %ecx, %r14d + mov %edx, %r15d +EOF +round1_step(-1,'%eax','%ebx','%ecx','%edx', '1','0xd76aa478', '7'); +round1_step( 0,'%edx','%eax','%ebx','%ecx', '2','0xe8c7b756','12'); +round1_step( 0,'%ecx','%edx','%eax','%ebx', '3','0x242070db','17'); +round1_step( 0,'%ebx','%ecx','%edx','%eax', '4','0xc1bdceee','22'); +round1_step( 0,'%eax','%ebx','%ecx','%edx', '5','0xf57c0faf', '7'); +round1_step( 0,'%edx','%eax','%ebx','%ecx', '6','0x4787c62a','12'); +round1_step( 0,'%ecx','%edx','%eax','%ebx', '7','0xa8304613','17'); +round1_step( 0,'%ebx','%ecx','%edx','%eax', '8','0xfd469501','22'); +round1_step( 0,'%eax','%ebx','%ecx','%edx', '9','0x698098d8', '7'); +round1_step( 0,'%edx','%eax','%ebx','%ecx','10','0x8b44f7af','12'); +round1_step( 0,'%ecx','%edx','%eax','%ebx','11','0xffff5bb1','17'); +round1_step( 0,'%ebx','%ecx','%edx','%eax','12','0x895cd7be','22'); +round1_step( 0,'%eax','%ebx','%ecx','%edx','13','0x6b901122', '7'); +round1_step( 0,'%edx','%eax','%ebx','%ecx','14','0xfd987193','12'); +round1_step( 0,'%ecx','%edx','%eax','%ebx','15','0xa679438e','17'); +round1_step( 1,'%ebx','%ecx','%edx','%eax', '1','0x49b40821','22'); + +round2_step(-1,'%eax','%ebx','%ecx','%edx', '6','0xf61e2562', '5'); +round2_step( 0,'%edx','%eax','%ebx','%ecx','11','0xc040b340', '9'); +round2_step( 0,'%ecx','%edx','%eax','%ebx', '0','0x265e5a51','14'); +round2_step( 0,'%ebx','%ecx','%edx','%eax', '5','0xe9b6c7aa','20'); +round2_step( 0,'%eax','%ebx','%ecx','%edx','10','0xd62f105d', '5'); +round2_step( 0,'%edx','%eax','%ebx','%ecx','15', '0x2441453', '9'); +round2_step( 0,'%ecx','%edx','%eax','%ebx', '4','0xd8a1e681','14'); +round2_step( 0,'%ebx','%ecx','%edx','%eax', '9','0xe7d3fbc8','20'); +round2_step( 0,'%eax','%ebx','%ecx','%edx','14','0x21e1cde6', '5'); +round2_step( 0,'%edx','%eax','%ebx','%ecx', '3','0xc33707d6', '9'); +round2_step( 0,'%ecx','%edx','%eax','%ebx', '8','0xf4d50d87','14'); +round2_step( 0,'%ebx','%ecx','%edx','%eax','13','0x455a14ed','20'); +round2_step( 0,'%eax','%ebx','%ecx','%edx', '2','0xa9e3e905', '5'); +round2_step( 0,'%edx','%eax','%ebx','%ecx', '7','0xfcefa3f8', '9'); +round2_step( 0,'%ecx','%edx','%eax','%ebx','12','0x676f02d9','14'); +round2_step( 1,'%ebx','%ecx','%edx','%eax', '5','0x8d2a4c8a','20'); + +round3_step(-1,'%eax','%ebx','%ecx','%edx', '8','0xfffa3942', '4'); +round3_step( 0,'%edx','%eax','%ebx','%ecx','11','0x8771f681','11'); +round3_step( 0,'%ecx','%edx','%eax','%ebx','14','0x6d9d6122','16'); +round3_step( 0,'%ebx','%ecx','%edx','%eax', '1','0xfde5380c','23'); +round3_step( 0,'%eax','%ebx','%ecx','%edx', '4','0xa4beea44', '4'); +round3_step( 0,'%edx','%eax','%ebx','%ecx', '7','0x4bdecfa9','11'); +round3_step( 0,'%ecx','%edx','%eax','%ebx','10','0xf6bb4b60','16'); +round3_step( 0,'%ebx','%ecx','%edx','%eax','13','0xbebfbc70','23'); +round3_step( 0,'%eax','%ebx','%ecx','%edx', '0','0x289b7ec6', '4'); +round3_step( 0,'%edx','%eax','%ebx','%ecx', '3','0xeaa127fa','11'); +round3_step( 0,'%ecx','%edx','%eax','%ebx', '6','0xd4ef3085','16'); +round3_step( 0,'%ebx','%ecx','%edx','%eax', '9', '0x4881d05','23'); +round3_step( 0,'%eax','%ebx','%ecx','%edx','12','0xd9d4d039', '4'); +round3_step( 0,'%edx','%eax','%ebx','%ecx','15','0xe6db99e5','11'); +round3_step( 0,'%ecx','%edx','%eax','%ebx', '2','0x1fa27cf8','16'); +round3_step( 1,'%ebx','%ecx','%edx','%eax', '0','0xc4ac5665','23'); + +round4_step(-1,'%eax','%ebx','%ecx','%edx', '7','0xf4292244', '6'); +round4_step( 0,'%edx','%eax','%ebx','%ecx','14','0x432aff97','10'); +round4_step( 0,'%ecx','%edx','%eax','%ebx', '5','0xab9423a7','15'); +round4_step( 0,'%ebx','%ecx','%edx','%eax','12','0xfc93a039','21'); +round4_step( 0,'%eax','%ebx','%ecx','%edx', '3','0x655b59c3', '6'); +round4_step( 0,'%edx','%eax','%ebx','%ecx','10','0x8f0ccc92','10'); +round4_step( 0,'%ecx','%edx','%eax','%ebx', '1','0xffeff47d','15'); +round4_step( 0,'%ebx','%ecx','%edx','%eax', '8','0x85845dd1','21'); +round4_step( 0,'%eax','%ebx','%ecx','%edx','15','0x6fa87e4f', '6'); +round4_step( 0,'%edx','%eax','%ebx','%ecx', '6','0xfe2ce6e0','10'); +round4_step( 0,'%ecx','%edx','%eax','%ebx','13','0xa3014314','15'); +round4_step( 0,'%ebx','%ecx','%edx','%eax', '4','0x4e0811a1','21'); +round4_step( 0,'%eax','%ebx','%ecx','%edx','11','0xf7537e82', '6'); +round4_step( 0,'%edx','%eax','%ebx','%ecx', '2','0xbd3af235','10'); +round4_step( 0,'%ecx','%edx','%eax','%ebx', '9','0x2ad7d2bb','15'); +round4_step( 1,'%ebx','%ecx','%edx','%eax', '0','0xeb86d391','21'); +$code .= <A = A + mov %ebx, 1*4(%rbp) # ctx->B = B + mov %ecx, 2*4(%rbp) # ctx->C = C + mov %edx, 3*4(%rbp) # ctx->D = D + + mov (%rsp),%r15 +.cfi_restore %r15 + mov 8(%rsp),%r14 +.cfi_restore %r14 + mov 16(%rsp),%r12 +.cfi_restore %r12 + mov 24(%rsp),%rbx +.cfi_restore %rbx + mov 32(%rsp),%rbp +.cfi_restore %rbp + add \$40,%rsp +.cfi_adjust_cfa_offset -40 +.Lepilogue: + ret +.cfi_endproc +.size md5_block_asm_data_order,.-md5_block_asm_data_order +EOF + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +my $rec="%rcx"; +my $frame="%rdx"; +my $context="%r8"; +my $disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type se_handler,\@abi-omnipotent +.align 16 +se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + lea .Lprologue(%rip),%r10 + cmp %r10,%rbx # context->Rip<.Lprologue + jb .Lin_prologue + + mov 152($context),%rax # pull context->Rsp + + lea .Lepilogue(%rip),%r10 + cmp %r10,%rbx # context->Rip>=.Lepilogue + jae .Lin_prologue + + lea 40(%rax),%rax + + mov -8(%rax),%rbp + mov -16(%rax),%rbx + mov -24(%rax),%r12 + mov -32(%rax),%r14 + mov -40(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + +.Lin_prologue: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size se_handler,.-se_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_md5_block_asm_data_order + .rva .LSEH_end_md5_block_asm_data_order + .rva .LSEH_info_md5_block_asm_data_order + +.section .xdata +.align 8 +.LSEH_info_md5_block_asm_data_order: + .byte 9,0,0,0 + .rva se_handler +___ +} + +print $code; + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/md5/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/md5/build.info new file mode 100644 index 000000000..e641fecd0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/md5/build.info @@ -0,0 +1,11 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + md5_dgst.c md5_one.c {- $target{md5_asm_src} -} + +GENERATE[md5-586.s]=asm/md5-586.pl \ + $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) + +GENERATE[md5-x86_64.s]=asm/md5-x86_64.pl $(PERLASM_SCHEME) + +GENERATE[md5-sparcv9.S]=asm/md5-sparcv9.pl $(PERLASM_SCHEME) +INCLUDE[md5-sparcv9.o]=.. diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/md5/md5_dgst.c b/trunk/3rdparty/openssl-1.1-fit/crypto/md5/md5_dgst.c new file mode 100644 index 000000000..fbede6742 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/md5/md5_dgst.c @@ -0,0 +1,164 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "md5_locl.h" +#include + +/* + * Implemented from RFC1321 The MD5 Message-Digest Algorithm + */ + +#define INIT_DATA_A (unsigned long)0x67452301L +#define INIT_DATA_B (unsigned long)0xefcdab89L +#define INIT_DATA_C (unsigned long)0x98badcfeL +#define INIT_DATA_D (unsigned long)0x10325476L + +int MD5_Init(MD5_CTX *c) +{ + memset(c, 0, sizeof(*c)); + c->A = INIT_DATA_A; + c->B = INIT_DATA_B; + c->C = INIT_DATA_C; + c->D = INIT_DATA_D; + return 1; +} + +#ifndef md5_block_data_order +# ifdef X +# undef X +# endif +void md5_block_data_order(MD5_CTX *c, const void *data_, size_t num) +{ + const unsigned char *data = data_; + register unsigned MD32_REG_T A, B, C, D, l; +# ifndef MD32_XARRAY + /* See comment in crypto/sha/sha_locl.h for details. */ + unsigned MD32_REG_T XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, + XX8, XX9, XX10, XX11, XX12, XX13, XX14, XX15; +# define X(i) XX##i +# else + MD5_LONG XX[MD5_LBLOCK]; +# define X(i) XX[i] +# endif + + A = c->A; + B = c->B; + C = c->C; + D = c->D; + + for (; num--;) { + (void)HOST_c2l(data, l); + X(0) = l; + (void)HOST_c2l(data, l); + X(1) = l; + /* Round 0 */ + R0(A, B, C, D, X(0), 7, 0xd76aa478L); + (void)HOST_c2l(data, l); + X(2) = l; + R0(D, A, B, C, X(1), 12, 0xe8c7b756L); + (void)HOST_c2l(data, l); + X(3) = l; + R0(C, D, A, B, X(2), 17, 0x242070dbL); + (void)HOST_c2l(data, l); + X(4) = l; + R0(B, C, D, A, X(3), 22, 0xc1bdceeeL); + (void)HOST_c2l(data, l); + X(5) = l; + R0(A, B, C, D, X(4), 7, 0xf57c0fafL); + (void)HOST_c2l(data, l); + X(6) = l; + R0(D, A, B, C, X(5), 12, 0x4787c62aL); + (void)HOST_c2l(data, l); + X(7) = l; + R0(C, D, A, B, X(6), 17, 0xa8304613L); + (void)HOST_c2l(data, l); + X(8) = l; + R0(B, C, D, A, X(7), 22, 0xfd469501L); + (void)HOST_c2l(data, l); + X(9) = l; + R0(A, B, C, D, X(8), 7, 0x698098d8L); + (void)HOST_c2l(data, l); + X(10) = l; + R0(D, A, B, C, X(9), 12, 0x8b44f7afL); + (void)HOST_c2l(data, l); + X(11) = l; + R0(C, D, A, B, X(10), 17, 0xffff5bb1L); + (void)HOST_c2l(data, l); + X(12) = l; + R0(B, C, D, A, X(11), 22, 0x895cd7beL); + (void)HOST_c2l(data, l); + X(13) = l; + R0(A, B, C, D, X(12), 7, 0x6b901122L); + (void)HOST_c2l(data, l); + X(14) = l; + R0(D, A, B, C, X(13), 12, 0xfd987193L); + (void)HOST_c2l(data, l); + X(15) = l; + R0(C, D, A, B, X(14), 17, 0xa679438eL); + R0(B, C, D, A, X(15), 22, 0x49b40821L); + /* Round 1 */ + R1(A, B, C, D, X(1), 5, 0xf61e2562L); + R1(D, A, B, C, X(6), 9, 0xc040b340L); + R1(C, D, A, B, X(11), 14, 0x265e5a51L); + R1(B, C, D, A, X(0), 20, 0xe9b6c7aaL); + R1(A, B, C, D, X(5), 5, 0xd62f105dL); + R1(D, A, B, C, X(10), 9, 0x02441453L); + R1(C, D, A, B, X(15), 14, 0xd8a1e681L); + R1(B, C, D, A, X(4), 20, 0xe7d3fbc8L); + R1(A, B, C, D, X(9), 5, 0x21e1cde6L); + R1(D, A, B, C, X(14), 9, 0xc33707d6L); + R1(C, D, A, B, X(3), 14, 0xf4d50d87L); + R1(B, C, D, A, X(8), 20, 0x455a14edL); + R1(A, B, C, D, X(13), 5, 0xa9e3e905L); + R1(D, A, B, C, X(2), 9, 0xfcefa3f8L); + R1(C, D, A, B, X(7), 14, 0x676f02d9L); + R1(B, C, D, A, X(12), 20, 0x8d2a4c8aL); + /* Round 2 */ + R2(A, B, C, D, X(5), 4, 0xfffa3942L); + R2(D, A, B, C, X(8), 11, 0x8771f681L); + R2(C, D, A, B, X(11), 16, 0x6d9d6122L); + R2(B, C, D, A, X(14), 23, 0xfde5380cL); + R2(A, B, C, D, X(1), 4, 0xa4beea44L); + R2(D, A, B, C, X(4), 11, 0x4bdecfa9L); + R2(C, D, A, B, X(7), 16, 0xf6bb4b60L); + R2(B, C, D, A, X(10), 23, 0xbebfbc70L); + R2(A, B, C, D, X(13), 4, 0x289b7ec6L); + R2(D, A, B, C, X(0), 11, 0xeaa127faL); + R2(C, D, A, B, X(3), 16, 0xd4ef3085L); + R2(B, C, D, A, X(6), 23, 0x04881d05L); + R2(A, B, C, D, X(9), 4, 0xd9d4d039L); + R2(D, A, B, C, X(12), 11, 0xe6db99e5L); + R2(C, D, A, B, X(15), 16, 0x1fa27cf8L); + R2(B, C, D, A, X(2), 23, 0xc4ac5665L); + /* Round 3 */ + R3(A, B, C, D, X(0), 6, 0xf4292244L); + R3(D, A, B, C, X(7), 10, 0x432aff97L); + R3(C, D, A, B, X(14), 15, 0xab9423a7L); + R3(B, C, D, A, X(5), 21, 0xfc93a039L); + R3(A, B, C, D, X(12), 6, 0x655b59c3L); + R3(D, A, B, C, X(3), 10, 0x8f0ccc92L); + R3(C, D, A, B, X(10), 15, 0xffeff47dL); + R3(B, C, D, A, X(1), 21, 0x85845dd1L); + R3(A, B, C, D, X(8), 6, 0x6fa87e4fL); + R3(D, A, B, C, X(15), 10, 0xfe2ce6e0L); + R3(C, D, A, B, X(6), 15, 0xa3014314L); + R3(B, C, D, A, X(13), 21, 0x4e0811a1L); + R3(A, B, C, D, X(4), 6, 0xf7537e82L); + R3(D, A, B, C, X(11), 10, 0xbd3af235L); + R3(C, D, A, B, X(2), 15, 0x2ad7d2bbL); + R3(B, C, D, A, X(9), 21, 0xeb86d391L); + + A = c->A += A; + B = c->B += B; + C = c->C += C; + D = c->D += D; + } +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/md5/md5_locl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/md5/md5_locl.h new file mode 100644 index 000000000..4eb7e50ef --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/md5/md5_locl.h @@ -0,0 +1,80 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include + +#ifdef MD5_ASM +# if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ + defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64) +# define md5_block_data_order md5_block_asm_data_order +# elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64) +# define md5_block_data_order md5_block_asm_data_order +# elif defined(__sparc) || defined(__sparc__) +# define md5_block_data_order md5_block_asm_data_order +# endif +#endif + +void md5_block_data_order(MD5_CTX *c, const void *p, size_t num); + +#define DATA_ORDER_IS_LITTLE_ENDIAN + +#define HASH_LONG MD5_LONG +#define HASH_CTX MD5_CTX +#define HASH_CBLOCK MD5_CBLOCK +#define HASH_UPDATE MD5_Update +#define HASH_TRANSFORM MD5_Transform +#define HASH_FINAL MD5_Final +#define HASH_MAKE_STRING(c,s) do { \ + unsigned long ll; \ + ll=(c)->A; (void)HOST_l2c(ll,(s)); \ + ll=(c)->B; (void)HOST_l2c(ll,(s)); \ + ll=(c)->C; (void)HOST_l2c(ll,(s)); \ + ll=(c)->D; (void)HOST_l2c(ll,(s)); \ + } while (0) +#define HASH_BLOCK_DATA_ORDER md5_block_data_order + +#include "internal/md32_common.h" + +/*- +#define F(x,y,z) (((x) & (y)) | ((~(x)) & (z))) +#define G(x,y,z) (((x) & (z)) | ((y) & (~(z)))) +*/ + +/* + * As pointed out by Wei Dai, the above can be simplified to the code + * below. Wei attributes these optimizations to Peter Gutmann's + * SHS code, and he attributes it to Rich Schroeppel. + */ +#define F(b,c,d) ((((c) ^ (d)) & (b)) ^ (d)) +#define G(b,c,d) ((((b) ^ (c)) & (d)) ^ (c)) +#define H(b,c,d) ((b) ^ (c) ^ (d)) +#define I(b,c,d) (((~(d)) | (b)) ^ (c)) + +#define R0(a,b,c,d,k,s,t) { \ + a+=((k)+(t)+F((b),(c),(d))); \ + a=ROTATE(a,s); \ + a+=b; };\ + +#define R1(a,b,c,d,k,s,t) { \ + a+=((k)+(t)+G((b),(c),(d))); \ + a=ROTATE(a,s); \ + a+=b; }; + +#define R2(a,b,c,d,k,s,t) { \ + a+=((k)+(t)+H((b),(c),(d))); \ + a=ROTATE(a,s); \ + a+=b; }; + +#define R3(a,b,c,d,k,s,t) { \ + a+=((k)+(t)+I((b),(c),(d))); \ + a=ROTATE(a,s); \ + a+=b; }; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/md5/md5_one.c b/trunk/3rdparty/openssl-1.1-fit/crypto/md5/md5_one.c new file mode 100644 index 000000000..c3bf2f88f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/md5/md5_one.c @@ -0,0 +1,47 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include + +#ifdef CHARSET_EBCDIC +# include +#endif + +unsigned char *MD5(const unsigned char *d, size_t n, unsigned char *md) +{ + MD5_CTX c; + static unsigned char m[MD5_DIGEST_LENGTH]; + + if (md == NULL) + md = m; + if (!MD5_Init(&c)) + return NULL; +#ifndef CHARSET_EBCDIC + MD5_Update(&c, d, n); +#else + { + char temp[1024]; + unsigned long chunk; + + while (n > 0) { + chunk = (n > sizeof(temp)) ? sizeof(temp) : n; + ebcdic2ascii(temp, d, chunk); + MD5_Update(&c, temp, chunk); + n -= chunk; + d += chunk; + } + } +#endif + MD5_Final(md, &c); + OPENSSL_cleanse(&c, sizeof(c)); /* security consideration */ + return md; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/mdc2/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/mdc2/build.info new file mode 100644 index 000000000..8fe6878d6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/mdc2/build.info @@ -0,0 +1,3 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + mdc2dgst.c mdc2_one.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/mdc2/mdc2_one.c b/trunk/3rdparty/openssl-1.1-fit/crypto/mdc2/mdc2_one.c new file mode 100644 index 000000000..58e1e0fdf --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/mdc2/mdc2_one.c @@ -0,0 +1,27 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include + +unsigned char *MDC2(const unsigned char *d, size_t n, unsigned char *md) +{ + MDC2_CTX c; + static unsigned char m[MDC2_DIGEST_LENGTH]; + + if (md == NULL) + md = m; + if (!MDC2_Init(&c)) + return NULL; + MDC2_Update(&c, d, n); + MDC2_Final(md, &c); + OPENSSL_cleanse(&c, sizeof(c)); /* security consideration */ + return md; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/mdc2/mdc2dgst.c b/trunk/3rdparty/openssl-1.1-fit/crypto/mdc2/mdc2dgst.c new file mode 100644 index 000000000..14233b9ab --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/mdc2/mdc2dgst.c @@ -0,0 +1,126 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include + +#undef c2l +#define c2l(c,l) (l =((DES_LONG)(*((c)++))) , \ + l|=((DES_LONG)(*((c)++)))<< 8L, \ + l|=((DES_LONG)(*((c)++)))<<16L, \ + l|=((DES_LONG)(*((c)++)))<<24L) + +#undef l2c +#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24L)&0xff)) + +static void mdc2_body(MDC2_CTX *c, const unsigned char *in, size_t len); +int MDC2_Init(MDC2_CTX *c) +{ + c->num = 0; + c->pad_type = 1; + memset(&(c->h[0]), 0x52, MDC2_BLOCK); + memset(&(c->hh[0]), 0x25, MDC2_BLOCK); + return 1; +} + +int MDC2_Update(MDC2_CTX *c, const unsigned char *in, size_t len) +{ + size_t i, j; + + i = c->num; + if (i != 0) { + if (len < MDC2_BLOCK - i) { + /* partial block */ + memcpy(&(c->data[i]), in, len); + c->num += (int)len; + return 1; + } else { + /* filled one */ + j = MDC2_BLOCK - i; + memcpy(&(c->data[i]), in, j); + len -= j; + in += j; + c->num = 0; + mdc2_body(c, &(c->data[0]), MDC2_BLOCK); + } + } + i = len & ~((size_t)MDC2_BLOCK - 1); + if (i > 0) + mdc2_body(c, in, i); + j = len - i; + if (j > 0) { + memcpy(&(c->data[0]), &(in[i]), j); + c->num = (int)j; + } + return 1; +} + +static void mdc2_body(MDC2_CTX *c, const unsigned char *in, size_t len) +{ + register DES_LONG tin0, tin1; + register DES_LONG ttin0, ttin1; + DES_LONG d[2], dd[2]; + DES_key_schedule k; + unsigned char *p; + size_t i; + + for (i = 0; i < len; i += 8) { + c2l(in, tin0); + d[0] = dd[0] = tin0; + c2l(in, tin1); + d[1] = dd[1] = tin1; + c->h[0] = (c->h[0] & 0x9f) | 0x40; + c->hh[0] = (c->hh[0] & 0x9f) | 0x20; + + DES_set_odd_parity(&c->h); + DES_set_key_unchecked(&c->h, &k); + DES_encrypt1(d, &k, 1); + + DES_set_odd_parity(&c->hh); + DES_set_key_unchecked(&c->hh, &k); + DES_encrypt1(dd, &k, 1); + + ttin0 = tin0 ^ dd[0]; + ttin1 = tin1 ^ dd[1]; + tin0 ^= d[0]; + tin1 ^= d[1]; + + p = c->h; + l2c(tin0, p); + l2c(ttin1, p); + p = c->hh; + l2c(ttin0, p); + l2c(tin1, p); + } +} + +int MDC2_Final(unsigned char *md, MDC2_CTX *c) +{ + unsigned int i; + int j; + + i = c->num; + j = c->pad_type; + if ((i > 0) || (j == 2)) { + if (j == 2) + c->data[i++] = 0x80; + memset(&(c->data[i]), 0, MDC2_BLOCK - i); + mdc2_body(c, c->data, MDC2_BLOCK); + } + memcpy(md, (char *)c->h, MDC2_BLOCK); + memcpy(&(md[MDC2_BLOCK]), (char *)c->hh, MDC2_BLOCK); + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/mem.c b/trunk/3rdparty/openssl-1.1-fit/crypto/mem.c new file mode 100644 index 000000000..780053ffe --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/mem.c @@ -0,0 +1,323 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "e_os.h" +#include "internal/cryptlib.h" +#include "internal/cryptlib_int.h" +#include +#include +#include +#include +#ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE +# include +#endif + +/* + * the following pointers may be changed as long as 'allow_customize' is set + */ +static int allow_customize = 1; + +static void *(*malloc_impl)(size_t, const char *, int) + = CRYPTO_malloc; +static void *(*realloc_impl)(void *, size_t, const char *, int) + = CRYPTO_realloc; +static void (*free_impl)(void *, const char *, int) + = CRYPTO_free; + +#ifndef OPENSSL_NO_CRYPTO_MDEBUG +# include "internal/tsan_assist.h" + +static TSAN_QUALIFIER int malloc_count; +static TSAN_QUALIFIER int realloc_count; +static TSAN_QUALIFIER int free_count; + +# define INCREMENT(x) tsan_counter(&(x)) + +static char *md_failstring; +static long md_count; +static int md_fail_percent = 0; +static int md_tracefd = -1; +static int call_malloc_debug = 1; + +static void parseit(void); +static int shouldfail(void); + +# define FAILTEST() if (shouldfail()) return NULL + +#else +static int call_malloc_debug = 0; + +# define INCREMENT(x) /* empty */ +# define FAILTEST() /* empty */ +#endif + +int CRYPTO_set_mem_functions( + void *(*m)(size_t, const char *, int), + void *(*r)(void *, size_t, const char *, int), + void (*f)(void *, const char *, int)) +{ + if (!allow_customize) + return 0; + if (m) + malloc_impl = m; + if (r) + realloc_impl = r; + if (f) + free_impl = f; + return 1; +} + +int CRYPTO_set_mem_debug(int flag) +{ + if (!allow_customize) + return 0; + call_malloc_debug = flag; + return 1; +} + +void CRYPTO_get_mem_functions( + void *(**m)(size_t, const char *, int), + void *(**r)(void *, size_t, const char *, int), + void (**f)(void *, const char *, int)) +{ + if (m != NULL) + *m = malloc_impl; + if (r != NULL) + *r = realloc_impl; + if (f != NULL) + *f = free_impl; +} + +#ifndef OPENSSL_NO_CRYPTO_MDEBUG +void CRYPTO_get_alloc_counts(int *mcount, int *rcount, int *fcount) +{ + if (mcount != NULL) + *mcount = tsan_load(&malloc_count); + if (rcount != NULL) + *rcount = tsan_load(&realloc_count); + if (fcount != NULL) + *fcount = tsan_load(&free_count); +} + +/* + * Parse a "malloc failure spec" string. This likes like a set of fields + * separated by semicolons. Each field has a count and an optional failure + * percentage. For example: + * 100@0;100@25;0@0 + * or 100;100@25;0 + * This means 100 mallocs succeed, then next 100 fail 25% of the time, and + * all remaining (count is zero) succeed. + */ +static void parseit(void) +{ + char *semi = strchr(md_failstring, ';'); + char *atsign; + + if (semi != NULL) + *semi++ = '\0'; + + /* Get the count (atol will stop at the @ if there), and percentage */ + md_count = atol(md_failstring); + atsign = strchr(md_failstring, '@'); + md_fail_percent = atsign == NULL ? 0 : atoi(atsign + 1); + + if (semi != NULL) + md_failstring = semi; +} + +/* + * Windows doesn't have random(), but it has rand() + * Some rand() implementations aren't good, but we're not + * dealing with secure randomness here. + */ +# ifdef _WIN32 +# define random() rand() +# endif +/* + * See if the current malloc should fail. + */ +static int shouldfail(void) +{ + int roll = (int)(random() % 100); + int shoulditfail = roll < md_fail_percent; +# ifndef _WIN32 +/* suppressed on Windows as POSIX-like file descriptors are non-inheritable */ + int len; + char buff[80]; + + if (md_tracefd > 0) { + BIO_snprintf(buff, sizeof(buff), + "%c C%ld %%%d R%d\n", + shoulditfail ? '-' : '+', md_count, md_fail_percent, roll); + len = strlen(buff); + if (write(md_tracefd, buff, len) != len) + perror("shouldfail write failed"); +# ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE + if (shoulditfail) { + void *addrs[30]; + int num = backtrace(addrs, OSSL_NELEM(addrs)); + + backtrace_symbols_fd(addrs, num, md_tracefd); + } +# endif + } +# endif + + if (md_count) { + /* If we used up this one, go to the next. */ + if (--md_count == 0) + parseit(); + } + + return shoulditfail; +} + +void ossl_malloc_setup_failures(void) +{ + const char *cp = getenv("OPENSSL_MALLOC_FAILURES"); + + if (cp != NULL && (md_failstring = strdup(cp)) != NULL) + parseit(); + if ((cp = getenv("OPENSSL_MALLOC_FD")) != NULL) + md_tracefd = atoi(cp); +} +#endif + +void *CRYPTO_malloc(size_t num, const char *file, int line) +{ + void *ret = NULL; + + INCREMENT(malloc_count); + if (malloc_impl != NULL && malloc_impl != CRYPTO_malloc) + return malloc_impl(num, file, line); + + if (num == 0) + return NULL; + + FAILTEST(); + if (allow_customize) { + /* + * Disallow customization after the first allocation. We only set this + * if necessary to avoid a store to the same cache line on every + * allocation. + */ + allow_customize = 0; + } +#ifndef OPENSSL_NO_CRYPTO_MDEBUG + if (call_malloc_debug) { + CRYPTO_mem_debug_malloc(NULL, num, 0, file, line); + ret = malloc(num); + CRYPTO_mem_debug_malloc(ret, num, 1, file, line); + } else { + ret = malloc(num); + } +#else + (void)(file); (void)(line); + ret = malloc(num); +#endif + + return ret; +} + +void *CRYPTO_zalloc(size_t num, const char *file, int line) +{ + void *ret = CRYPTO_malloc(num, file, line); + + FAILTEST(); + if (ret != NULL) + memset(ret, 0, num); + return ret; +} + +void *CRYPTO_realloc(void *str, size_t num, const char *file, int line) +{ + INCREMENT(realloc_count); + if (realloc_impl != NULL && realloc_impl != &CRYPTO_realloc) + return realloc_impl(str, num, file, line); + + FAILTEST(); + if (str == NULL) + return CRYPTO_malloc(num, file, line); + + if (num == 0) { + CRYPTO_free(str, file, line); + return NULL; + } + +#ifndef OPENSSL_NO_CRYPTO_MDEBUG + if (call_malloc_debug) { + void *ret; + CRYPTO_mem_debug_realloc(str, NULL, num, 0, file, line); + ret = realloc(str, num); + CRYPTO_mem_debug_realloc(str, ret, num, 1, file, line); + return ret; + } +#else + (void)(file); (void)(line); +#endif + return realloc(str, num); + +} + +void *CRYPTO_clear_realloc(void *str, size_t old_len, size_t num, + const char *file, int line) +{ + void *ret = NULL; + + if (str == NULL) + return CRYPTO_malloc(num, file, line); + + if (num == 0) { + CRYPTO_clear_free(str, old_len, file, line); + return NULL; + } + + /* Can't shrink the buffer since memcpy below copies |old_len| bytes. */ + if (num < old_len) { + OPENSSL_cleanse((char*)str + num, old_len - num); + return str; + } + + ret = CRYPTO_malloc(num, file, line); + if (ret != NULL) { + memcpy(ret, str, old_len); + CRYPTO_clear_free(str, old_len, file, line); + } + return ret; +} + +void CRYPTO_free(void *str, const char *file, int line) +{ + INCREMENT(free_count); + if (free_impl != NULL && free_impl != &CRYPTO_free) { + free_impl(str, file, line); + return; + } + +#ifndef OPENSSL_NO_CRYPTO_MDEBUG + if (call_malloc_debug) { + CRYPTO_mem_debug_free(str, 0, file, line); + free(str); + CRYPTO_mem_debug_free(str, 1, file, line); + } else { + free(str); + } +#else + free(str); +#endif +} + +void CRYPTO_clear_free(void *str, size_t num, const char *file, int line) +{ + if (str == NULL) + return; + if (num) + OPENSSL_cleanse(str, num); + CRYPTO_free(str, file, line); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/mem_clr.c b/trunk/3rdparty/openssl-1.1-fit/crypto/mem_clr.c new file mode 100644 index 000000000..35bfb74ea --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/mem_clr.c @@ -0,0 +1,25 @@ +/* + * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +/* + * Pointer to memset is volatile so that compiler must de-reference + * the pointer and can't assume that it points to any function in + * particular (such as memset, which it then might further "optimize") + */ +typedef void *(*memset_t)(void *, int, size_t); + +static volatile memset_t memset_func = memset; + +void OPENSSL_cleanse(void *ptr, size_t len) +{ + memset_func(ptr, 0, len); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/mem_dbg.c b/trunk/3rdparty/openssl-1.1-fit/crypto/mem_dbg.c new file mode 100644 index 000000000..0489e97ad --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/mem_dbg.c @@ -0,0 +1,670 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "internal/cryptlib.h" +#include "internal/thread_once.h" +#include +#include +#include "internal/bio.h" +#include + +#ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE +# include +#endif + +/* + * The state changes to CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE when + * the application asks for it (usually after library initialisation for + * which no book-keeping is desired). State CRYPTO_MEM_CHECK_ON exists only + * temporarily when the library thinks that certain allocations should not be + * checked (e.g. the data structures used for memory checking). It is not + * suitable as an initial state: the library will unexpectedly enable memory + * checking when it executes one of those sections that want to disable + * checking temporarily. State CRYPTO_MEM_CHECK_ENABLE without ..._ON makes + * no sense whatsoever. + */ +#ifndef OPENSSL_NO_CRYPTO_MDEBUG +static int mh_mode = CRYPTO_MEM_CHECK_OFF; +#endif + +#ifndef OPENSSL_NO_CRYPTO_MDEBUG +static unsigned long order = 0; /* number of memory requests */ + +/*- + * For application-defined information (static C-string `info') + * to be displayed in memory leak list. + * Each thread has its own stack. For applications, there is + * OPENSSL_mem_debug_push("...") to push an entry, + * OPENSSL_mem_debug_pop() to pop an entry, + */ +struct app_mem_info_st { + CRYPTO_THREAD_ID threadid; + const char *file; + int line; + const char *info; + struct app_mem_info_st *next; /* tail of thread's stack */ + int references; +}; + +static CRYPTO_ONCE memdbg_init = CRYPTO_ONCE_STATIC_INIT; +CRYPTO_RWLOCK *memdbg_lock; +static CRYPTO_RWLOCK *long_memdbg_lock; +static CRYPTO_THREAD_LOCAL appinfokey; + +/* memory-block description */ +struct mem_st { + void *addr; + int num; + const char *file; + int line; + CRYPTO_THREAD_ID threadid; + unsigned long order; + time_t time; + APP_INFO *app_info; +#ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE + void *array[30]; + size_t array_siz; +#endif +}; + +/* + * hash-table of memory requests (address as * key); access requires + * long_memdbg_lock lock + */ +static LHASH_OF(MEM) *mh = NULL; + +/* num_disable > 0 iff mh_mode == CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE) */ +static unsigned int num_disable = 0; + +/* + * Valid iff num_disable > 0. long_memdbg_lock is locked exactly in this + * case (by the thread named in disabling_thread). + */ +static CRYPTO_THREAD_ID disabling_threadid; + +DEFINE_RUN_ONCE_STATIC(do_memdbg_init) +{ + memdbg_lock = CRYPTO_THREAD_lock_new(); + long_memdbg_lock = CRYPTO_THREAD_lock_new(); + if (memdbg_lock == NULL || long_memdbg_lock == NULL + || !CRYPTO_THREAD_init_local(&appinfokey, NULL)) { + CRYPTO_THREAD_lock_free(memdbg_lock); + memdbg_lock = NULL; + CRYPTO_THREAD_lock_free(long_memdbg_lock); + long_memdbg_lock = NULL; + return 0; + } + return 1; +} + +static void app_info_free(APP_INFO *inf) +{ + if (inf == NULL) + return; + if (--(inf->references) <= 0) { + app_info_free(inf->next); + OPENSSL_free(inf); + } +} +#endif + +int CRYPTO_mem_ctrl(int mode) +{ +#ifdef OPENSSL_NO_CRYPTO_MDEBUG + return mode - mode; +#else + int ret = mh_mode; + + if (!RUN_ONCE(&memdbg_init, do_memdbg_init)) + return -1; + + CRYPTO_THREAD_write_lock(memdbg_lock); + switch (mode) { + default: + break; + + case CRYPTO_MEM_CHECK_ON: + mh_mode = CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE; + num_disable = 0; + break; + + case CRYPTO_MEM_CHECK_OFF: + mh_mode = 0; + num_disable = 0; + break; + + /* switch off temporarily (for library-internal use): */ + case CRYPTO_MEM_CHECK_DISABLE: + if (mh_mode & CRYPTO_MEM_CHECK_ON) { + CRYPTO_THREAD_ID cur = CRYPTO_THREAD_get_current_id(); + /* see if we don't have long_memdbg_lock already */ + if (!num_disable + || !CRYPTO_THREAD_compare_id(disabling_threadid, cur)) { + /* + * Long-time lock long_memdbg_lock must not be claimed + * while we're holding memdbg_lock, or we'll deadlock + * if somebody else holds long_memdbg_lock (and cannot + * release it because we block entry to this function). Give + * them a chance, first, and then claim the locks in + * appropriate order (long-time lock first). + */ + CRYPTO_THREAD_unlock(memdbg_lock); + /* + * Note that after we have waited for long_memdbg_lock and + * memdbg_lock, we'll still be in the right "case" and + * "if" branch because MemCheck_start and MemCheck_stop may + * never be used while there are multiple OpenSSL threads. + */ + CRYPTO_THREAD_write_lock(long_memdbg_lock); + CRYPTO_THREAD_write_lock(memdbg_lock); + mh_mode &= ~CRYPTO_MEM_CHECK_ENABLE; + disabling_threadid = cur; + } + num_disable++; + } + break; + + case CRYPTO_MEM_CHECK_ENABLE: + if (mh_mode & CRYPTO_MEM_CHECK_ON) { + if (num_disable) { /* always true, or something is going wrong */ + num_disable--; + if (num_disable == 0) { + mh_mode |= CRYPTO_MEM_CHECK_ENABLE; + CRYPTO_THREAD_unlock(long_memdbg_lock); + } + } + } + break; + } + CRYPTO_THREAD_unlock(memdbg_lock); + return ret; +#endif +} + +#ifndef OPENSSL_NO_CRYPTO_MDEBUG + +static int mem_check_on(void) +{ + int ret = 0; + CRYPTO_THREAD_ID cur; + + if (mh_mode & CRYPTO_MEM_CHECK_ON) { + if (!RUN_ONCE(&memdbg_init, do_memdbg_init)) + return 0; + + cur = CRYPTO_THREAD_get_current_id(); + CRYPTO_THREAD_read_lock(memdbg_lock); + + ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE) + || !CRYPTO_THREAD_compare_id(disabling_threadid, cur); + + CRYPTO_THREAD_unlock(memdbg_lock); + } + return ret; +} + +static int mem_cmp(const MEM *a, const MEM *b) +{ +#ifdef _WIN64 + const char *ap = (const char *)a->addr, *bp = (const char *)b->addr; + if (ap == bp) + return 0; + else if (ap > bp) + return 1; + else + return -1; +#else + return (const char *)a->addr - (const char *)b->addr; +#endif +} + +static unsigned long mem_hash(const MEM *a) +{ + size_t ret; + + ret = (size_t)a->addr; + + ret = ret * 17851 + (ret >> 14) * 7 + (ret >> 4) * 251; + return ret; +} + +/* returns 1 if there was an info to pop, 0 if the stack was empty. */ +static int pop_info(void) +{ + APP_INFO *current = NULL; + + if (!RUN_ONCE(&memdbg_init, do_memdbg_init)) + return 0; + + current = (APP_INFO *)CRYPTO_THREAD_get_local(&appinfokey); + if (current != NULL) { + APP_INFO *next = current->next; + + if (next != NULL) { + next->references++; + CRYPTO_THREAD_set_local(&appinfokey, next); + } else { + CRYPTO_THREAD_set_local(&appinfokey, NULL); + } + if (--(current->references) <= 0) { + current->next = NULL; + if (next != NULL) + next->references--; + OPENSSL_free(current); + } + return 1; + } + return 0; +} + +int CRYPTO_mem_debug_push(const char *info, const char *file, int line) +{ + APP_INFO *ami, *amim; + int ret = 0; + + if (mem_check_on()) { + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE); + + if (!RUN_ONCE(&memdbg_init, do_memdbg_init) + || (ami = OPENSSL_malloc(sizeof(*ami))) == NULL) + goto err; + + ami->threadid = CRYPTO_THREAD_get_current_id(); + ami->file = file; + ami->line = line; + ami->info = info; + ami->references = 1; + ami->next = NULL; + + amim = (APP_INFO *)CRYPTO_THREAD_get_local(&appinfokey); + CRYPTO_THREAD_set_local(&appinfokey, ami); + + if (amim != NULL) + ami->next = amim; + ret = 1; + err: + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE); + } + + return ret; +} + +int CRYPTO_mem_debug_pop(void) +{ + int ret = 0; + + if (mem_check_on()) { + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE); + ret = pop_info(); + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE); + } + return ret; +} + +static unsigned long break_order_num = 0; + +void CRYPTO_mem_debug_malloc(void *addr, size_t num, int before_p, + const char *file, int line) +{ + MEM *m, *mm; + APP_INFO *amim; + + switch (before_p & 127) { + case 0: + break; + case 1: + if (addr == NULL) + break; + + if (mem_check_on()) { + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE); + + if (!RUN_ONCE(&memdbg_init, do_memdbg_init) + || (m = OPENSSL_malloc(sizeof(*m))) == NULL) { + OPENSSL_free(addr); + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE); + return; + } + if (mh == NULL) { + if ((mh = lh_MEM_new(mem_hash, mem_cmp)) == NULL) { + OPENSSL_free(addr); + OPENSSL_free(m); + addr = NULL; + goto err; + } + } + + m->addr = addr; + m->file = file; + m->line = line; + m->num = num; + m->threadid = CRYPTO_THREAD_get_current_id(); + + if (order == break_order_num) { + /* BREAK HERE */ + m->order = order; + } + m->order = order++; +# ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE + m->array_siz = backtrace(m->array, OSSL_NELEM(m->array)); +# endif + m->time = time(NULL); + + amim = (APP_INFO *)CRYPTO_THREAD_get_local(&appinfokey); + m->app_info = amim; + if (amim != NULL) + amim->references++; + + if ((mm = lh_MEM_insert(mh, m)) != NULL) { + /* Not good, but don't sweat it */ + if (mm->app_info != NULL) { + mm->app_info->references--; + } + OPENSSL_free(mm); + } + err: + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE); + } + break; + } + return; +} + +void CRYPTO_mem_debug_free(void *addr, int before_p, + const char *file, int line) +{ + MEM m, *mp; + + switch (before_p) { + case 0: + if (addr == NULL) + break; + + if (mem_check_on() && (mh != NULL)) { + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE); + + m.addr = addr; + mp = lh_MEM_delete(mh, &m); + if (mp != NULL) { + app_info_free(mp->app_info); + OPENSSL_free(mp); + } + + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE); + } + break; + case 1: + break; + } +} + +void CRYPTO_mem_debug_realloc(void *addr1, void *addr2, size_t num, + int before_p, const char *file, int line) +{ + MEM m, *mp; + + switch (before_p) { + case 0: + break; + case 1: + if (addr2 == NULL) + break; + + if (addr1 == NULL) { + CRYPTO_mem_debug_malloc(addr2, num, 128 | before_p, file, line); + break; + } + + if (mem_check_on()) { + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE); + + m.addr = addr1; + mp = lh_MEM_delete(mh, &m); + if (mp != NULL) { + mp->addr = addr2; + mp->num = num; +#ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE + mp->array_siz = backtrace(mp->array, OSSL_NELEM(mp->array)); +#endif + (void)lh_MEM_insert(mh, mp); + } + + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE); + } + break; + } + return; +} + +typedef struct mem_leak_st { + int (*print_cb) (const char *str, size_t len, void *u); + void *print_cb_arg; + int chunks; + long bytes; +} MEM_LEAK; + +static void print_leak(const MEM *m, MEM_LEAK *l) +{ + char buf[1024]; + char *bufp = buf; + size_t len = sizeof(buf), ami_cnt; + APP_INFO *amip; + int n; + struct tm *lcl = NULL; + /* + * Convert between CRYPTO_THREAD_ID (which could be anything at all) and + * a long. This may not be meaningful depending on what CRYPTO_THREAD_ID is + * but hopefully should give something sensible on most platforms + */ + union { + CRYPTO_THREAD_ID tid; + unsigned long ltid; + } tid; + CRYPTO_THREAD_ID ti; + + lcl = localtime(&m->time); + n = BIO_snprintf(bufp, len, "[%02d:%02d:%02d] ", + lcl->tm_hour, lcl->tm_min, lcl->tm_sec); + if (n <= 0) { + bufp[0] = '\0'; + return; + } + bufp += n; + len -= n; + + n = BIO_snprintf(bufp, len, "%5lu file=%s, line=%d, ", + m->order, m->file, m->line); + if (n <= 0) + return; + bufp += n; + len -= n; + + tid.ltid = 0; + tid.tid = m->threadid; + n = BIO_snprintf(bufp, len, "thread=%lu, ", tid.ltid); + if (n <= 0) + return; + bufp += n; + len -= n; + + n = BIO_snprintf(bufp, len, "number=%d, address=%p\n", m->num, m->addr); + if (n <= 0) + return; + bufp += n; + len -= n; + + l->print_cb(buf, (size_t)(bufp - buf), l->print_cb_arg); + + l->chunks++; + l->bytes += m->num; + + amip = m->app_info; + ami_cnt = 0; + + if (amip) { + ti = amip->threadid; + + do { + int buf_len; + int info_len; + + ami_cnt++; + if (ami_cnt >= sizeof(buf) - 1) + break; + memset(buf, '>', ami_cnt); + buf[ami_cnt] = '\0'; + tid.ltid = 0; + tid.tid = amip->threadid; + n = BIO_snprintf(buf + ami_cnt, sizeof(buf) - ami_cnt, + " thread=%lu, file=%s, line=%d, info=\"", + tid.ltid, amip->file, amip->line); + if (n <= 0) + break; + buf_len = ami_cnt + n; + info_len = strlen(amip->info); + if (128 - buf_len - 3 < info_len) { + memcpy(buf + buf_len, amip->info, 128 - buf_len - 3); + buf_len = 128 - 3; + } else { + n = BIO_snprintf(buf + buf_len, sizeof(buf) - buf_len, "%s", + amip->info); + if (n < 0) + break; + buf_len += n; + } + n = BIO_snprintf(buf + buf_len, sizeof(buf) - buf_len, "\"\n"); + if (n <= 0) + break; + + l->print_cb(buf, buf_len + n, l->print_cb_arg); + + amip = amip->next; + } + while (amip && CRYPTO_THREAD_compare_id(amip->threadid, ti)); + } + +#ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE + { + size_t i; + char **strings = backtrace_symbols(m->array, m->array_siz); + + for (i = 0; i < m->array_siz; i++) + fprintf(stderr, "##> %s\n", strings[i]); + free(strings); + } +#endif +} + +IMPLEMENT_LHASH_DOALL_ARG_CONST(MEM, MEM_LEAK); + +int CRYPTO_mem_leaks_cb(int (*cb) (const char *str, size_t len, void *u), + void *u) +{ + MEM_LEAK ml; + + /* Ensure all resources are released */ + OPENSSL_cleanup(); + + if (!RUN_ONCE(&memdbg_init, do_memdbg_init)) + return -1; + + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE); + + ml.print_cb = cb; + ml.print_cb_arg = u; + ml.bytes = 0; + ml.chunks = 0; + if (mh != NULL) + lh_MEM_doall_MEM_LEAK(mh, print_leak, &ml); + + if (ml.chunks != 0) { + char buf[256]; + + BIO_snprintf(buf, sizeof(buf), "%ld bytes leaked in %d chunks\n", + ml.bytes, ml.chunks); + cb(buf, strlen(buf), u); + } else { + /* + * Make sure that, if we found no leaks, memory-leak debugging itself + * does not introduce memory leaks (which might irritate external + * debugging tools). (When someone enables leak checking, but does not + * call this function, we declare it to be their fault.) + */ + int old_mh_mode; + + CRYPTO_THREAD_write_lock(memdbg_lock); + + /* + * avoid deadlock when lh_free() uses CRYPTO_mem_debug_free(), which uses + * mem_check_on + */ + old_mh_mode = mh_mode; + mh_mode = CRYPTO_MEM_CHECK_OFF; + + lh_MEM_free(mh); + mh = NULL; + + mh_mode = old_mh_mode; + CRYPTO_THREAD_unlock(memdbg_lock); + } + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF); + + /* Clean up locks etc */ + CRYPTO_THREAD_cleanup_local(&appinfokey); + CRYPTO_THREAD_lock_free(memdbg_lock); + CRYPTO_THREAD_lock_free(long_memdbg_lock); + memdbg_lock = NULL; + long_memdbg_lock = NULL; + + return ml.chunks == 0 ? 1 : 0; +} + +static int print_bio(const char *str, size_t len, void *b) +{ + return BIO_write((BIO *)b, str, len); +} + +int CRYPTO_mem_leaks(BIO *b) +{ + /* + * OPENSSL_cleanup() will free the ex_data locks so we can't have any + * ex_data hanging around + */ + bio_free_ex_data(b); + + return CRYPTO_mem_leaks_cb(print_bio, b); +} + +# ifndef OPENSSL_NO_STDIO +int CRYPTO_mem_leaks_fp(FILE *fp) +{ + BIO *b; + int ret; + + /* + * Need to turn off memory checking when allocated BIOs ... especially as + * we're creating them at a time when we're trying to check we've not + * left anything un-free()'d!! + */ + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE); + b = BIO_new(BIO_s_file()); + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE); + if (b == NULL) + return -1; + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = CRYPTO_mem_leaks_cb(print_bio, b); + BIO_free(b); + return ret; +} +# endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/mem_sec.c b/trunk/3rdparty/openssl-1.1-fit/crypto/mem_sec.c new file mode 100644 index 000000000..9e0f6702f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/mem_sec.c @@ -0,0 +1,646 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2004-2014, Akamai Technologies. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This file is in two halves. The first half implements the public API + * to be used by external consumers, and to be used by OpenSSL to store + * data in a "secure arena." The second half implements the secure arena. + * For details on that implementation, see below (look for uppercase + * "SECURE HEAP IMPLEMENTATION"). + */ +#include "e_os.h" +#include + +#include + +/* e_os.h defines OPENSSL_SECURE_MEMORY if secure memory can be implemented */ +#ifdef OPENSSL_SECURE_MEMORY +# include +# include +# include +# include +# include +# if defined(OPENSSL_SYS_LINUX) +# include +# if defined(SYS_mlock2) +# include +# include +# endif +# endif +# include +# include +# include +#endif + +#define CLEAR(p, s) OPENSSL_cleanse(p, s) +#ifndef PAGE_SIZE +# define PAGE_SIZE 4096 +#endif +#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS) +# define MAP_ANON MAP_ANONYMOUS +#endif + +#ifdef OPENSSL_SECURE_MEMORY +static size_t secure_mem_used; + +static int secure_mem_initialized; + +static CRYPTO_RWLOCK *sec_malloc_lock = NULL; + +/* + * These are the functions that must be implemented by a secure heap (sh). + */ +static int sh_init(size_t size, int minsize); +static void *sh_malloc(size_t size); +static void sh_free(void *ptr); +static void sh_done(void); +static size_t sh_actual_size(char *ptr); +static int sh_allocated(const char *ptr); +#endif + +int CRYPTO_secure_malloc_init(size_t size, int minsize) +{ +#ifdef OPENSSL_SECURE_MEMORY + int ret = 0; + + if (!secure_mem_initialized) { + sec_malloc_lock = CRYPTO_THREAD_lock_new(); + if (sec_malloc_lock == NULL) + return 0; + if ((ret = sh_init(size, minsize)) != 0) { + secure_mem_initialized = 1; + } else { + CRYPTO_THREAD_lock_free(sec_malloc_lock); + sec_malloc_lock = NULL; + } + } + + return ret; +#else + return 0; +#endif /* OPENSSL_SECURE_MEMORY */ +} + +int CRYPTO_secure_malloc_done(void) +{ +#ifdef OPENSSL_SECURE_MEMORY + if (secure_mem_used == 0) { + sh_done(); + secure_mem_initialized = 0; + CRYPTO_THREAD_lock_free(sec_malloc_lock); + sec_malloc_lock = NULL; + return 1; + } +#endif /* OPENSSL_SECURE_MEMORY */ + return 0; +} + +int CRYPTO_secure_malloc_initialized(void) +{ +#ifdef OPENSSL_SECURE_MEMORY + return secure_mem_initialized; +#else + return 0; +#endif /* OPENSSL_SECURE_MEMORY */ +} + +void *CRYPTO_secure_malloc(size_t num, const char *file, int line) +{ +#ifdef OPENSSL_SECURE_MEMORY + void *ret; + size_t actual_size; + + if (!secure_mem_initialized) { + return CRYPTO_malloc(num, file, line); + } + CRYPTO_THREAD_write_lock(sec_malloc_lock); + ret = sh_malloc(num); + actual_size = ret ? sh_actual_size(ret) : 0; + secure_mem_used += actual_size; + CRYPTO_THREAD_unlock(sec_malloc_lock); + return ret; +#else + return CRYPTO_malloc(num, file, line); +#endif /* OPENSSL_SECURE_MEMORY */ +} + +void *CRYPTO_secure_zalloc(size_t num, const char *file, int line) +{ +#ifdef OPENSSL_SECURE_MEMORY + if (secure_mem_initialized) + /* CRYPTO_secure_malloc() zeroes allocations when it is implemented */ + return CRYPTO_secure_malloc(num, file, line); +#endif + return CRYPTO_zalloc(num, file, line); +} + +void CRYPTO_secure_free(void *ptr, const char *file, int line) +{ +#ifdef OPENSSL_SECURE_MEMORY + size_t actual_size; + + if (ptr == NULL) + return; + if (!CRYPTO_secure_allocated(ptr)) { + CRYPTO_free(ptr, file, line); + return; + } + CRYPTO_THREAD_write_lock(sec_malloc_lock); + actual_size = sh_actual_size(ptr); + CLEAR(ptr, actual_size); + secure_mem_used -= actual_size; + sh_free(ptr); + CRYPTO_THREAD_unlock(sec_malloc_lock); +#else + CRYPTO_free(ptr, file, line); +#endif /* OPENSSL_SECURE_MEMORY */ +} + +void CRYPTO_secure_clear_free(void *ptr, size_t num, + const char *file, int line) +{ +#ifdef OPENSSL_SECURE_MEMORY + size_t actual_size; + + if (ptr == NULL) + return; + if (!CRYPTO_secure_allocated(ptr)) { + OPENSSL_cleanse(ptr, num); + CRYPTO_free(ptr, file, line); + return; + } + CRYPTO_THREAD_write_lock(sec_malloc_lock); + actual_size = sh_actual_size(ptr); + CLEAR(ptr, actual_size); + secure_mem_used -= actual_size; + sh_free(ptr); + CRYPTO_THREAD_unlock(sec_malloc_lock); +#else + if (ptr == NULL) + return; + OPENSSL_cleanse(ptr, num); + CRYPTO_free(ptr, file, line); +#endif /* OPENSSL_SECURE_MEMORY */ +} + +int CRYPTO_secure_allocated(const void *ptr) +{ +#ifdef OPENSSL_SECURE_MEMORY + int ret; + + if (!secure_mem_initialized) + return 0; + CRYPTO_THREAD_write_lock(sec_malloc_lock); + ret = sh_allocated(ptr); + CRYPTO_THREAD_unlock(sec_malloc_lock); + return ret; +#else + return 0; +#endif /* OPENSSL_SECURE_MEMORY */ +} + +size_t CRYPTO_secure_used(void) +{ +#ifdef OPENSSL_SECURE_MEMORY + return secure_mem_used; +#else + return 0; +#endif /* OPENSSL_SECURE_MEMORY */ +} + +size_t CRYPTO_secure_actual_size(void *ptr) +{ +#ifdef OPENSSL_SECURE_MEMORY + size_t actual_size; + + CRYPTO_THREAD_write_lock(sec_malloc_lock); + actual_size = sh_actual_size(ptr); + CRYPTO_THREAD_unlock(sec_malloc_lock); + return actual_size; +#else + return 0; +#endif +} +/* END OF PAGE ... + + ... START OF PAGE */ + +/* + * SECURE HEAP IMPLEMENTATION + */ +#ifdef OPENSSL_SECURE_MEMORY + + +/* + * The implementation provided here uses a fixed-sized mmap() heap, + * which is locked into memory, not written to core files, and protected + * on either side by an unmapped page, which will catch pointer overruns + * (or underruns) and an attempt to read data out of the secure heap. + * Free'd memory is zero'd or otherwise cleansed. + * + * This is a pretty standard buddy allocator. We keep areas in a multiple + * of "sh.minsize" units. The freelist and bitmaps are kept separately, + * so all (and only) data is kept in the mmap'd heap. + * + * This code assumes eight-bit bytes. The numbers 3 and 7 are all over the + * place. + */ + +#define ONE ((size_t)1) + +# define TESTBIT(t, b) (t[(b) >> 3] & (ONE << ((b) & 7))) +# define SETBIT(t, b) (t[(b) >> 3] |= (ONE << ((b) & 7))) +# define CLEARBIT(t, b) (t[(b) >> 3] &= (0xFF & ~(ONE << ((b) & 7)))) + +#define WITHIN_ARENA(p) \ + ((char*)(p) >= sh.arena && (char*)(p) < &sh.arena[sh.arena_size]) +#define WITHIN_FREELIST(p) \ + ((char*)(p) >= (char*)sh.freelist && (char*)(p) < (char*)&sh.freelist[sh.freelist_size]) + + +typedef struct sh_list_st +{ + struct sh_list_st *next; + struct sh_list_st **p_next; +} SH_LIST; + +typedef struct sh_st +{ + char* map_result; + size_t map_size; + char *arena; + size_t arena_size; + char **freelist; + ossl_ssize_t freelist_size; + size_t minsize; + unsigned char *bittable; + unsigned char *bitmalloc; + size_t bittable_size; /* size in bits */ +} SH; + +static SH sh; + +static size_t sh_getlist(char *ptr) +{ + ossl_ssize_t list = sh.freelist_size - 1; + size_t bit = (sh.arena_size + ptr - sh.arena) / sh.minsize; + + for (; bit; bit >>= 1, list--) { + if (TESTBIT(sh.bittable, bit)) + break; + OPENSSL_assert((bit & 1) == 0); + } + + return list; +} + + +static int sh_testbit(char *ptr, int list, unsigned char *table) +{ + size_t bit; + + OPENSSL_assert(list >= 0 && list < sh.freelist_size); + OPENSSL_assert(((ptr - sh.arena) & ((sh.arena_size >> list) - 1)) == 0); + bit = (ONE << list) + ((ptr - sh.arena) / (sh.arena_size >> list)); + OPENSSL_assert(bit > 0 && bit < sh.bittable_size); + return TESTBIT(table, bit); +} + +static void sh_clearbit(char *ptr, int list, unsigned char *table) +{ + size_t bit; + + OPENSSL_assert(list >= 0 && list < sh.freelist_size); + OPENSSL_assert(((ptr - sh.arena) & ((sh.arena_size >> list) - 1)) == 0); + bit = (ONE << list) + ((ptr - sh.arena) / (sh.arena_size >> list)); + OPENSSL_assert(bit > 0 && bit < sh.bittable_size); + OPENSSL_assert(TESTBIT(table, bit)); + CLEARBIT(table, bit); +} + +static void sh_setbit(char *ptr, int list, unsigned char *table) +{ + size_t bit; + + OPENSSL_assert(list >= 0 && list < sh.freelist_size); + OPENSSL_assert(((ptr - sh.arena) & ((sh.arena_size >> list) - 1)) == 0); + bit = (ONE << list) + ((ptr - sh.arena) / (sh.arena_size >> list)); + OPENSSL_assert(bit > 0 && bit < sh.bittable_size); + OPENSSL_assert(!TESTBIT(table, bit)); + SETBIT(table, bit); +} + +static void sh_add_to_list(char **list, char *ptr) +{ + SH_LIST *temp; + + OPENSSL_assert(WITHIN_FREELIST(list)); + OPENSSL_assert(WITHIN_ARENA(ptr)); + + temp = (SH_LIST *)ptr; + temp->next = *(SH_LIST **)list; + OPENSSL_assert(temp->next == NULL || WITHIN_ARENA(temp->next)); + temp->p_next = (SH_LIST **)list; + + if (temp->next != NULL) { + OPENSSL_assert((char **)temp->next->p_next == list); + temp->next->p_next = &(temp->next); + } + + *list = ptr; +} + +static void sh_remove_from_list(char *ptr) +{ + SH_LIST *temp, *temp2; + + temp = (SH_LIST *)ptr; + if (temp->next != NULL) + temp->next->p_next = temp->p_next; + *temp->p_next = temp->next; + if (temp->next == NULL) + return; + + temp2 = temp->next; + OPENSSL_assert(WITHIN_FREELIST(temp2->p_next) || WITHIN_ARENA(temp2->p_next)); +} + + +static int sh_init(size_t size, int minsize) +{ + int ret; + size_t i; + size_t pgsize; + size_t aligned; + + memset(&sh, 0, sizeof(sh)); + + /* make sure size and minsize are powers of 2 */ + OPENSSL_assert(size > 0); + OPENSSL_assert((size & (size - 1)) == 0); + OPENSSL_assert(minsize > 0); + OPENSSL_assert((minsize & (minsize - 1)) == 0); + if (size <= 0 || (size & (size - 1)) != 0) + goto err; + if (minsize <= 0 || (minsize & (minsize - 1)) != 0) + goto err; + + while (minsize < (int)sizeof(SH_LIST)) + minsize *= 2; + + sh.arena_size = size; + sh.minsize = minsize; + sh.bittable_size = (sh.arena_size / sh.minsize) * 2; + + /* Prevent allocations of size 0 later on */ + if (sh.bittable_size >> 3 == 0) + goto err; + + sh.freelist_size = -1; + for (i = sh.bittable_size; i; i >>= 1) + sh.freelist_size++; + + sh.freelist = OPENSSL_zalloc(sh.freelist_size * sizeof(char *)); + OPENSSL_assert(sh.freelist != NULL); + if (sh.freelist == NULL) + goto err; + + sh.bittable = OPENSSL_zalloc(sh.bittable_size >> 3); + OPENSSL_assert(sh.bittable != NULL); + if (sh.bittable == NULL) + goto err; + + sh.bitmalloc = OPENSSL_zalloc(sh.bittable_size >> 3); + OPENSSL_assert(sh.bitmalloc != NULL); + if (sh.bitmalloc == NULL) + goto err; + + /* Allocate space for heap, and two extra pages as guards */ +#if defined(_SC_PAGE_SIZE) || defined (_SC_PAGESIZE) + { +# if defined(_SC_PAGE_SIZE) + long tmppgsize = sysconf(_SC_PAGE_SIZE); +# else + long tmppgsize = sysconf(_SC_PAGESIZE); +# endif + if (tmppgsize < 1) + pgsize = PAGE_SIZE; + else + pgsize = (size_t)tmppgsize; + } +#else + pgsize = PAGE_SIZE; +#endif + sh.map_size = pgsize + sh.arena_size + pgsize; + if (1) { +#ifdef MAP_ANON + sh.map_result = mmap(NULL, sh.map_size, + PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0); + } else { +#endif + int fd; + + sh.map_result = MAP_FAILED; + if ((fd = open("/dev/zero", O_RDWR)) >= 0) { + sh.map_result = mmap(NULL, sh.map_size, + PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); + close(fd); + } + } + if (sh.map_result == MAP_FAILED) + goto err; + sh.arena = (char *)(sh.map_result + pgsize); + sh_setbit(sh.arena, 0, sh.bittable); + sh_add_to_list(&sh.freelist[0], sh.arena); + + /* Now try to add guard pages and lock into memory. */ + ret = 1; + + /* Starting guard is already aligned from mmap. */ + if (mprotect(sh.map_result, pgsize, PROT_NONE) < 0) + ret = 2; + + /* Ending guard page - need to round up to page boundary */ + aligned = (pgsize + sh.arena_size + (pgsize - 1)) & ~(pgsize - 1); + if (mprotect(sh.map_result + aligned, pgsize, PROT_NONE) < 0) + ret = 2; + +#if defined(OPENSSL_SYS_LINUX) && defined(MLOCK_ONFAULT) && defined(SYS_mlock2) + if (syscall(SYS_mlock2, sh.arena, sh.arena_size, MLOCK_ONFAULT) < 0) { + if (errno == ENOSYS) { + if (mlock(sh.arena, sh.arena_size) < 0) + ret = 2; + } else { + ret = 2; + } + } +#else + if (mlock(sh.arena, sh.arena_size) < 0) + ret = 2; +#endif +#ifdef MADV_DONTDUMP + if (madvise(sh.arena, sh.arena_size, MADV_DONTDUMP) < 0) + ret = 2; +#endif + + return ret; + + err: + sh_done(); + return 0; +} + +static void sh_done(void) +{ + OPENSSL_free(sh.freelist); + OPENSSL_free(sh.bittable); + OPENSSL_free(sh.bitmalloc); + if (sh.map_result != NULL && sh.map_size) + munmap(sh.map_result, sh.map_size); + memset(&sh, 0, sizeof(sh)); +} + +static int sh_allocated(const char *ptr) +{ + return WITHIN_ARENA(ptr) ? 1 : 0; +} + +static char *sh_find_my_buddy(char *ptr, int list) +{ + size_t bit; + char *chunk = NULL; + + bit = (ONE << list) + (ptr - sh.arena) / (sh.arena_size >> list); + bit ^= 1; + + if (TESTBIT(sh.bittable, bit) && !TESTBIT(sh.bitmalloc, bit)) + chunk = sh.arena + ((bit & ((ONE << list) - 1)) * (sh.arena_size >> list)); + + return chunk; +} + +static void *sh_malloc(size_t size) +{ + ossl_ssize_t list, slist; + size_t i; + char *chunk; + + if (size > sh.arena_size) + return NULL; + + list = sh.freelist_size - 1; + for (i = sh.minsize; i < size; i <<= 1) + list--; + if (list < 0) + return NULL; + + /* try to find a larger entry to split */ + for (slist = list; slist >= 0; slist--) + if (sh.freelist[slist] != NULL) + break; + if (slist < 0) + return NULL; + + /* split larger entry */ + while (slist != list) { + char *temp = sh.freelist[slist]; + + /* remove from bigger list */ + OPENSSL_assert(!sh_testbit(temp, slist, sh.bitmalloc)); + sh_clearbit(temp, slist, sh.bittable); + sh_remove_from_list(temp); + OPENSSL_assert(temp != sh.freelist[slist]); + + /* done with bigger list */ + slist++; + + /* add to smaller list */ + OPENSSL_assert(!sh_testbit(temp, slist, sh.bitmalloc)); + sh_setbit(temp, slist, sh.bittable); + sh_add_to_list(&sh.freelist[slist], temp); + OPENSSL_assert(sh.freelist[slist] == temp); + + /* split in 2 */ + temp += sh.arena_size >> slist; + OPENSSL_assert(!sh_testbit(temp, slist, sh.bitmalloc)); + sh_setbit(temp, slist, sh.bittable); + sh_add_to_list(&sh.freelist[slist], temp); + OPENSSL_assert(sh.freelist[slist] == temp); + + OPENSSL_assert(temp-(sh.arena_size >> slist) == sh_find_my_buddy(temp, slist)); + } + + /* peel off memory to hand back */ + chunk = sh.freelist[list]; + OPENSSL_assert(sh_testbit(chunk, list, sh.bittable)); + sh_setbit(chunk, list, sh.bitmalloc); + sh_remove_from_list(chunk); + + OPENSSL_assert(WITHIN_ARENA(chunk)); + + /* zero the free list header as a precaution against information leakage */ + memset(chunk, 0, sizeof(SH_LIST)); + + return chunk; +} + +static void sh_free(void *ptr) +{ + size_t list; + void *buddy; + + if (ptr == NULL) + return; + OPENSSL_assert(WITHIN_ARENA(ptr)); + if (!WITHIN_ARENA(ptr)) + return; + + list = sh_getlist(ptr); + OPENSSL_assert(sh_testbit(ptr, list, sh.bittable)); + sh_clearbit(ptr, list, sh.bitmalloc); + sh_add_to_list(&sh.freelist[list], ptr); + + /* Try to coalesce two adjacent free areas. */ + while ((buddy = sh_find_my_buddy(ptr, list)) != NULL) { + OPENSSL_assert(ptr == sh_find_my_buddy(buddy, list)); + OPENSSL_assert(ptr != NULL); + OPENSSL_assert(!sh_testbit(ptr, list, sh.bitmalloc)); + sh_clearbit(ptr, list, sh.bittable); + sh_remove_from_list(ptr); + OPENSSL_assert(!sh_testbit(ptr, list, sh.bitmalloc)); + sh_clearbit(buddy, list, sh.bittable); + sh_remove_from_list(buddy); + + list--; + + /* Zero the higher addressed block's free list pointers */ + memset(ptr > buddy ? ptr : buddy, 0, sizeof(SH_LIST)); + if (ptr > buddy) + ptr = buddy; + + OPENSSL_assert(!sh_testbit(ptr, list, sh.bitmalloc)); + sh_setbit(ptr, list, sh.bittable); + sh_add_to_list(&sh.freelist[list], ptr); + OPENSSL_assert(sh.freelist[list] == ptr); + } +} + +static size_t sh_actual_size(char *ptr) +{ + int list; + + OPENSSL_assert(WITHIN_ARENA(ptr)); + if (!WITHIN_ARENA(ptr)) + return 0; + list = sh_getlist(ptr); + OPENSSL_assert(sh_testbit(ptr, list, sh.bittable)); + return sh.arena_size / (ONE << list); +} +#endif /* OPENSSL_SECURE_MEMORY */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/mips_arch.h b/trunk/3rdparty/openssl-1.1-fit/crypto/mips_arch.h new file mode 100644 index 000000000..75043e79d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/mips_arch.h @@ -0,0 +1,40 @@ +/* + * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef __MIPS_ARCH_H__ +# define __MIPS_ARCH_H__ + +# if (defined(__mips_smartmips) || defined(_MIPS_ARCH_MIPS32R3) || \ + defined(_MIPS_ARCH_MIPS32R5) || defined(_MIPS_ARCH_MIPS32R6)) + && !defined(_MIPS_ARCH_MIPS32R2) +# define _MIPS_ARCH_MIPS32R2 +# endif + +# if (defined(_MIPS_ARCH_MIPS64R3) || defined(_MIPS_ARCH_MIPS64R5) || \ + defined(_MIPS_ARCH_MIPS64R6)) \ + && !defined(_MIPS_ARCH_MIPS64R2) +# define _MIPS_ARCH_MIPS64R2 +# endif + +# if defined(_MIPS_ARCH_MIPS64R6) +# define dmultu(rs,rt) +# define mflo(rd,rs,rt) dmulu rd,rs,rt +# define mfhi(rd,rs,rt) dmuhu rd,rs,rt +# elif defined(_MIPS_ARCH_MIPS32R6) +# define multu(rs,rt) +# define mflo(rd,rs,rt) mulu rd,rs,rt +# define mfhi(rd,rs,rt) muhu rd,rs,rt +# else +# define dmultu(rs,rt) dmultu rs,rt +# define multu(rs,rt) multu rs,rt +# define mflo(rd,rs,rt) mflo rd +# define mfhi(rd,rs,rt) mfhi rd +# endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/aesni-gcm-x86_64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/aesni-gcm-x86_64.pl new file mode 100644 index 000000000..b42016101 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/aesni-gcm-x86_64.pl @@ -0,0 +1,1099 @@ +#! /usr/bin/env perl +# Copyright 2013-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# +# AES-NI-CTR+GHASH stitch. +# +# February 2013 +# +# OpenSSL GCM implementation is organized in such way that its +# performance is rather close to the sum of its streamed components, +# in the context parallelized AES-NI CTR and modulo-scheduled +# PCLMULQDQ-enabled GHASH. Unfortunately, as no stitch implementation +# was observed to perform significantly better than the sum of the +# components on contemporary CPUs, the effort was deemed impossible to +# justify. This module is based on combination of Intel submissions, +# [1] and [2], with MOVBE twist suggested by Ilya Albrekht and Max +# Locktyukhin of Intel Corp. who verified that it reduces shuffles +# pressure with notable relative improvement, achieving 1.0 cycle per +# byte processed with 128-bit key on Haswell processor, 0.74 - on +# Broadwell, 0.63 - on Skylake... [Mentioned results are raw profiled +# measurements for favourable packet size, one divisible by 96. +# Applications using the EVP interface will observe a few percent +# worse performance.] +# +# Knights Landing processes 1 byte in 1.25 cycles (measured with EVP). +# +# [1] http://rt.openssl.org/Ticket/Display.html?id=2900&user=guest&pass=guest +# [2] http://www.intel.com/content/dam/www/public/us/en/documents/software-support/enabling-high-performance-gcm.pdf + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler version ([2-9]\.[0-9]+)/) { + $avx = ($1>=2.20) + ($1>=2.22); +} + +if (!$avx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) && + `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) { + $avx = ($1>=2.09) + ($1>=2.10); +} + +if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && + `ml64 2>&1` =~ /Version ([0-9]+)\./) { + $avx = ($1>=10) + ($1>=11); +} + +if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9]\.[0-9]+)/) { + $avx = ($2>=3.0) + ($2>3.0); +} + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +*STDOUT=*OUT; + +if ($avx>1) {{{ + +($inp,$out,$len,$key,$ivp,$Xip)=("%rdi","%rsi","%rdx","%rcx","%r8","%r9"); + +($Ii,$T1,$T2,$Hkey, + $Z0,$Z1,$Z2,$Z3,$Xi) = map("%xmm$_",(0..8)); + +($inout0,$inout1,$inout2,$inout3,$inout4,$inout5,$rndkey) = map("%xmm$_",(9..15)); + +($counter,$rounds,$ret,$const,$in0,$end0)=("%ebx","%ebp","%r10","%r11","%r14","%r15"); + +$code=<<___; +.text + +.type _aesni_ctr32_ghash_6x,\@abi-omnipotent +.align 32 +_aesni_ctr32_ghash_6x: + vmovdqu 0x20($const),$T2 # borrow $T2, .Lone_msb + sub \$6,$len + vpxor $Z0,$Z0,$Z0 # $Z0 = 0 + vmovdqu 0x00-0x80($key),$rndkey + vpaddb $T2,$T1,$inout1 + vpaddb $T2,$inout1,$inout2 + vpaddb $T2,$inout2,$inout3 + vpaddb $T2,$inout3,$inout4 + vpaddb $T2,$inout4,$inout5 + vpxor $rndkey,$T1,$inout0 + vmovdqu $Z0,16+8(%rsp) # "$Z3" = 0 + jmp .Loop6x + +.align 32 +.Loop6x: + add \$`6<<24`,$counter + jc .Lhandle_ctr32 # discard $inout[1-5]? + vmovdqu 0x00-0x20($Xip),$Hkey # $Hkey^1 + vpaddb $T2,$inout5,$T1 # next counter value + vpxor $rndkey,$inout1,$inout1 + vpxor $rndkey,$inout2,$inout2 + +.Lresume_ctr32: + vmovdqu $T1,($ivp) # save next counter value + vpclmulqdq \$0x10,$Hkey,$Z3,$Z1 + vpxor $rndkey,$inout3,$inout3 + vmovups 0x10-0x80($key),$T2 # borrow $T2 for $rndkey + vpclmulqdq \$0x01,$Hkey,$Z3,$Z2 + xor %r12,%r12 + cmp $in0,$end0 + + vaesenc $T2,$inout0,$inout0 + vmovdqu 0x30+8(%rsp),$Ii # I[4] + vpxor $rndkey,$inout4,$inout4 + vpclmulqdq \$0x00,$Hkey,$Z3,$T1 + vaesenc $T2,$inout1,$inout1 + vpxor $rndkey,$inout5,$inout5 + setnc %r12b + vpclmulqdq \$0x11,$Hkey,$Z3,$Z3 + vaesenc $T2,$inout2,$inout2 + vmovdqu 0x10-0x20($Xip),$Hkey # $Hkey^2 + neg %r12 + vaesenc $T2,$inout3,$inout3 + vpxor $Z1,$Z2,$Z2 + vpclmulqdq \$0x00,$Hkey,$Ii,$Z1 + vpxor $Z0,$Xi,$Xi # modulo-scheduled + vaesenc $T2,$inout4,$inout4 + vpxor $Z1,$T1,$Z0 + and \$0x60,%r12 + vmovups 0x20-0x80($key),$rndkey + vpclmulqdq \$0x10,$Hkey,$Ii,$T1 + vaesenc $T2,$inout5,$inout5 + + vpclmulqdq \$0x01,$Hkey,$Ii,$T2 + lea ($in0,%r12),$in0 + vaesenc $rndkey,$inout0,$inout0 + vpxor 16+8(%rsp),$Xi,$Xi # modulo-scheduled [vpxor $Z3,$Xi,$Xi] + vpclmulqdq \$0x11,$Hkey,$Ii,$Hkey + vmovdqu 0x40+8(%rsp),$Ii # I[3] + vaesenc $rndkey,$inout1,$inout1 + movbe 0x58($in0),%r13 + vaesenc $rndkey,$inout2,$inout2 + movbe 0x50($in0),%r12 + vaesenc $rndkey,$inout3,$inout3 + mov %r13,0x20+8(%rsp) + vaesenc $rndkey,$inout4,$inout4 + mov %r12,0x28+8(%rsp) + vmovdqu 0x30-0x20($Xip),$Z1 # borrow $Z1 for $Hkey^3 + vaesenc $rndkey,$inout5,$inout5 + + vmovups 0x30-0x80($key),$rndkey + vpxor $T1,$Z2,$Z2 + vpclmulqdq \$0x00,$Z1,$Ii,$T1 + vaesenc $rndkey,$inout0,$inout0 + vpxor $T2,$Z2,$Z2 + vpclmulqdq \$0x10,$Z1,$Ii,$T2 + vaesenc $rndkey,$inout1,$inout1 + vpxor $Hkey,$Z3,$Z3 + vpclmulqdq \$0x01,$Z1,$Ii,$Hkey + vaesenc $rndkey,$inout2,$inout2 + vpclmulqdq \$0x11,$Z1,$Ii,$Z1 + vmovdqu 0x50+8(%rsp),$Ii # I[2] + vaesenc $rndkey,$inout3,$inout3 + vaesenc $rndkey,$inout4,$inout4 + vpxor $T1,$Z0,$Z0 + vmovdqu 0x40-0x20($Xip),$T1 # borrow $T1 for $Hkey^4 + vaesenc $rndkey,$inout5,$inout5 + + vmovups 0x40-0x80($key),$rndkey + vpxor $T2,$Z2,$Z2 + vpclmulqdq \$0x00,$T1,$Ii,$T2 + vaesenc $rndkey,$inout0,$inout0 + vpxor $Hkey,$Z2,$Z2 + vpclmulqdq \$0x10,$T1,$Ii,$Hkey + vaesenc $rndkey,$inout1,$inout1 + movbe 0x48($in0),%r13 + vpxor $Z1,$Z3,$Z3 + vpclmulqdq \$0x01,$T1,$Ii,$Z1 + vaesenc $rndkey,$inout2,$inout2 + movbe 0x40($in0),%r12 + vpclmulqdq \$0x11,$T1,$Ii,$T1 + vmovdqu 0x60+8(%rsp),$Ii # I[1] + vaesenc $rndkey,$inout3,$inout3 + mov %r13,0x30+8(%rsp) + vaesenc $rndkey,$inout4,$inout4 + mov %r12,0x38+8(%rsp) + vpxor $T2,$Z0,$Z0 + vmovdqu 0x60-0x20($Xip),$T2 # borrow $T2 for $Hkey^5 + vaesenc $rndkey,$inout5,$inout5 + + vmovups 0x50-0x80($key),$rndkey + vpxor $Hkey,$Z2,$Z2 + vpclmulqdq \$0x00,$T2,$Ii,$Hkey + vaesenc $rndkey,$inout0,$inout0 + vpxor $Z1,$Z2,$Z2 + vpclmulqdq \$0x10,$T2,$Ii,$Z1 + vaesenc $rndkey,$inout1,$inout1 + movbe 0x38($in0),%r13 + vpxor $T1,$Z3,$Z3 + vpclmulqdq \$0x01,$T2,$Ii,$T1 + vpxor 0x70+8(%rsp),$Xi,$Xi # accumulate I[0] + vaesenc $rndkey,$inout2,$inout2 + movbe 0x30($in0),%r12 + vpclmulqdq \$0x11,$T2,$Ii,$T2 + vaesenc $rndkey,$inout3,$inout3 + mov %r13,0x40+8(%rsp) + vaesenc $rndkey,$inout4,$inout4 + mov %r12,0x48+8(%rsp) + vpxor $Hkey,$Z0,$Z0 + vmovdqu 0x70-0x20($Xip),$Hkey # $Hkey^6 + vaesenc $rndkey,$inout5,$inout5 + + vmovups 0x60-0x80($key),$rndkey + vpxor $Z1,$Z2,$Z2 + vpclmulqdq \$0x10,$Hkey,$Xi,$Z1 + vaesenc $rndkey,$inout0,$inout0 + vpxor $T1,$Z2,$Z2 + vpclmulqdq \$0x01,$Hkey,$Xi,$T1 + vaesenc $rndkey,$inout1,$inout1 + movbe 0x28($in0),%r13 + vpxor $T2,$Z3,$Z3 + vpclmulqdq \$0x00,$Hkey,$Xi,$T2 + vaesenc $rndkey,$inout2,$inout2 + movbe 0x20($in0),%r12 + vpclmulqdq \$0x11,$Hkey,$Xi,$Xi + vaesenc $rndkey,$inout3,$inout3 + mov %r13,0x50+8(%rsp) + vaesenc $rndkey,$inout4,$inout4 + mov %r12,0x58+8(%rsp) + vpxor $Z1,$Z2,$Z2 + vaesenc $rndkey,$inout5,$inout5 + vpxor $T1,$Z2,$Z2 + + vmovups 0x70-0x80($key),$rndkey + vpslldq \$8,$Z2,$Z1 + vpxor $T2,$Z0,$Z0 + vmovdqu 0x10($const),$Hkey # .Lpoly + + vaesenc $rndkey,$inout0,$inout0 + vpxor $Xi,$Z3,$Z3 + vaesenc $rndkey,$inout1,$inout1 + vpxor $Z1,$Z0,$Z0 + movbe 0x18($in0),%r13 + vaesenc $rndkey,$inout2,$inout2 + movbe 0x10($in0),%r12 + vpalignr \$8,$Z0,$Z0,$Ii # 1st phase + vpclmulqdq \$0x10,$Hkey,$Z0,$Z0 + mov %r13,0x60+8(%rsp) + vaesenc $rndkey,$inout3,$inout3 + mov %r12,0x68+8(%rsp) + vaesenc $rndkey,$inout4,$inout4 + vmovups 0x80-0x80($key),$T1 # borrow $T1 for $rndkey + vaesenc $rndkey,$inout5,$inout5 + + vaesenc $T1,$inout0,$inout0 + vmovups 0x90-0x80($key),$rndkey + vaesenc $T1,$inout1,$inout1 + vpsrldq \$8,$Z2,$Z2 + vaesenc $T1,$inout2,$inout2 + vpxor $Z2,$Z3,$Z3 + vaesenc $T1,$inout3,$inout3 + vpxor $Ii,$Z0,$Z0 + movbe 0x08($in0),%r13 + vaesenc $T1,$inout4,$inout4 + movbe 0x00($in0),%r12 + vaesenc $T1,$inout5,$inout5 + vmovups 0xa0-0x80($key),$T1 + cmp \$11,$rounds + jb .Lenc_tail # 128-bit key + + vaesenc $rndkey,$inout0,$inout0 + vaesenc $rndkey,$inout1,$inout1 + vaesenc $rndkey,$inout2,$inout2 + vaesenc $rndkey,$inout3,$inout3 + vaesenc $rndkey,$inout4,$inout4 + vaesenc $rndkey,$inout5,$inout5 + + vaesenc $T1,$inout0,$inout0 + vaesenc $T1,$inout1,$inout1 + vaesenc $T1,$inout2,$inout2 + vaesenc $T1,$inout3,$inout3 + vaesenc $T1,$inout4,$inout4 + vmovups 0xb0-0x80($key),$rndkey + vaesenc $T1,$inout5,$inout5 + vmovups 0xc0-0x80($key),$T1 + je .Lenc_tail # 192-bit key + + vaesenc $rndkey,$inout0,$inout0 + vaesenc $rndkey,$inout1,$inout1 + vaesenc $rndkey,$inout2,$inout2 + vaesenc $rndkey,$inout3,$inout3 + vaesenc $rndkey,$inout4,$inout4 + vaesenc $rndkey,$inout5,$inout5 + + vaesenc $T1,$inout0,$inout0 + vaesenc $T1,$inout1,$inout1 + vaesenc $T1,$inout2,$inout2 + vaesenc $T1,$inout3,$inout3 + vaesenc $T1,$inout4,$inout4 + vmovups 0xd0-0x80($key),$rndkey + vaesenc $T1,$inout5,$inout5 + vmovups 0xe0-0x80($key),$T1 + jmp .Lenc_tail # 256-bit key + +.align 32 +.Lhandle_ctr32: + vmovdqu ($const),$Ii # borrow $Ii for .Lbswap_mask + vpshufb $Ii,$T1,$Z2 # byte-swap counter + vmovdqu 0x30($const),$Z1 # borrow $Z1, .Ltwo_lsb + vpaddd 0x40($const),$Z2,$inout1 # .Lone_lsb + vpaddd $Z1,$Z2,$inout2 + vmovdqu 0x00-0x20($Xip),$Hkey # $Hkey^1 + vpaddd $Z1,$inout1,$inout3 + vpshufb $Ii,$inout1,$inout1 + vpaddd $Z1,$inout2,$inout4 + vpshufb $Ii,$inout2,$inout2 + vpxor $rndkey,$inout1,$inout1 + vpaddd $Z1,$inout3,$inout5 + vpshufb $Ii,$inout3,$inout3 + vpxor $rndkey,$inout2,$inout2 + vpaddd $Z1,$inout4,$T1 # byte-swapped next counter value + vpshufb $Ii,$inout4,$inout4 + vpshufb $Ii,$inout5,$inout5 + vpshufb $Ii,$T1,$T1 # next counter value + jmp .Lresume_ctr32 + +.align 32 +.Lenc_tail: + vaesenc $rndkey,$inout0,$inout0 + vmovdqu $Z3,16+8(%rsp) # postpone vpxor $Z3,$Xi,$Xi + vpalignr \$8,$Z0,$Z0,$Xi # 2nd phase + vaesenc $rndkey,$inout1,$inout1 + vpclmulqdq \$0x10,$Hkey,$Z0,$Z0 + vpxor 0x00($inp),$T1,$T2 + vaesenc $rndkey,$inout2,$inout2 + vpxor 0x10($inp),$T1,$Ii + vaesenc $rndkey,$inout3,$inout3 + vpxor 0x20($inp),$T1,$Z1 + vaesenc $rndkey,$inout4,$inout4 + vpxor 0x30($inp),$T1,$Z2 + vaesenc $rndkey,$inout5,$inout5 + vpxor 0x40($inp),$T1,$Z3 + vpxor 0x50($inp),$T1,$Hkey + vmovdqu ($ivp),$T1 # load next counter value + + vaesenclast $T2,$inout0,$inout0 + vmovdqu 0x20($const),$T2 # borrow $T2, .Lone_msb + vaesenclast $Ii,$inout1,$inout1 + vpaddb $T2,$T1,$Ii + mov %r13,0x70+8(%rsp) + lea 0x60($inp),$inp + vaesenclast $Z1,$inout2,$inout2 + vpaddb $T2,$Ii,$Z1 + mov %r12,0x78+8(%rsp) + lea 0x60($out),$out + vmovdqu 0x00-0x80($key),$rndkey + vaesenclast $Z2,$inout3,$inout3 + vpaddb $T2,$Z1,$Z2 + vaesenclast $Z3, $inout4,$inout4 + vpaddb $T2,$Z2,$Z3 + vaesenclast $Hkey,$inout5,$inout5 + vpaddb $T2,$Z3,$Hkey + + add \$0x60,$ret + sub \$0x6,$len + jc .L6x_done + + vmovups $inout0,-0x60($out) # save output + vpxor $rndkey,$T1,$inout0 + vmovups $inout1,-0x50($out) + vmovdqa $Ii,$inout1 # 0 latency + vmovups $inout2,-0x40($out) + vmovdqa $Z1,$inout2 # 0 latency + vmovups $inout3,-0x30($out) + vmovdqa $Z2,$inout3 # 0 latency + vmovups $inout4,-0x20($out) + vmovdqa $Z3,$inout4 # 0 latency + vmovups $inout5,-0x10($out) + vmovdqa $Hkey,$inout5 # 0 latency + vmovdqu 0x20+8(%rsp),$Z3 # I[5] + jmp .Loop6x + +.L6x_done: + vpxor 16+8(%rsp),$Xi,$Xi # modulo-scheduled + vpxor $Z0,$Xi,$Xi # modulo-scheduled + + ret +.size _aesni_ctr32_ghash_6x,.-_aesni_ctr32_ghash_6x +___ +###################################################################### +# +# size_t aesni_gcm_[en|de]crypt(const void *inp, void *out, size_t len, +# const AES_KEY *key, unsigned char iv[16], +# struct { u128 Xi,H,Htbl[9]; } *Xip); +$code.=<<___; +.globl aesni_gcm_decrypt +.type aesni_gcm_decrypt,\@function,6 +.align 32 +aesni_gcm_decrypt: +.cfi_startproc + xor $ret,$ret + cmp \$0x60,$len # minimal accepted length + jb .Lgcm_dec_abort + + lea (%rsp),%rax # save stack pointer +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +___ +$code.=<<___ if ($win64); + lea -0xa8(%rsp),%rsp + movaps %xmm6,-0xd8(%rax) + movaps %xmm7,-0xc8(%rax) + movaps %xmm8,-0xb8(%rax) + movaps %xmm9,-0xa8(%rax) + movaps %xmm10,-0x98(%rax) + movaps %xmm11,-0x88(%rax) + movaps %xmm12,-0x78(%rax) + movaps %xmm13,-0x68(%rax) + movaps %xmm14,-0x58(%rax) + movaps %xmm15,-0x48(%rax) +.Lgcm_dec_body: +___ +$code.=<<___; + vzeroupper + + vmovdqu ($ivp),$T1 # input counter value + add \$-128,%rsp + mov 12($ivp),$counter + lea .Lbswap_mask(%rip),$const + lea -0x80($key),$in0 # borrow $in0 + mov \$0xf80,$end0 # borrow $end0 + vmovdqu ($Xip),$Xi # load Xi + and \$-128,%rsp # ensure stack alignment + vmovdqu ($const),$Ii # borrow $Ii for .Lbswap_mask + lea 0x80($key),$key # size optimization + lea 0x20+0x20($Xip),$Xip # size optimization + mov 0xf0-0x80($key),$rounds + vpshufb $Ii,$Xi,$Xi + + and $end0,$in0 + and %rsp,$end0 + sub $in0,$end0 + jc .Ldec_no_key_aliasing + cmp \$768,$end0 + jnc .Ldec_no_key_aliasing + sub $end0,%rsp # avoid aliasing with key +.Ldec_no_key_aliasing: + + vmovdqu 0x50($inp),$Z3 # I[5] + lea ($inp),$in0 + vmovdqu 0x40($inp),$Z0 + lea -0xc0($inp,$len),$end0 + vmovdqu 0x30($inp),$Z1 + shr \$4,$len + xor $ret,$ret + vmovdqu 0x20($inp),$Z2 + vpshufb $Ii,$Z3,$Z3 # passed to _aesni_ctr32_ghash_6x + vmovdqu 0x10($inp),$T2 + vpshufb $Ii,$Z0,$Z0 + vmovdqu ($inp),$Hkey + vpshufb $Ii,$Z1,$Z1 + vmovdqu $Z0,0x30(%rsp) + vpshufb $Ii,$Z2,$Z2 + vmovdqu $Z1,0x40(%rsp) + vpshufb $Ii,$T2,$T2 + vmovdqu $Z2,0x50(%rsp) + vpshufb $Ii,$Hkey,$Hkey + vmovdqu $T2,0x60(%rsp) + vmovdqu $Hkey,0x70(%rsp) + + call _aesni_ctr32_ghash_6x + + vmovups $inout0,-0x60($out) # save output + vmovups $inout1,-0x50($out) + vmovups $inout2,-0x40($out) + vmovups $inout3,-0x30($out) + vmovups $inout4,-0x20($out) + vmovups $inout5,-0x10($out) + + vpshufb ($const),$Xi,$Xi # .Lbswap_mask + vmovdqu $Xi,-0x40($Xip) # output Xi + + vzeroupper +___ +$code.=<<___ if ($win64); + movaps -0xd8(%rax),%xmm6 + movaps -0xc8(%rax),%xmm7 + movaps -0xb8(%rax),%xmm8 + movaps -0xa8(%rax),%xmm9 + movaps -0x98(%rax),%xmm10 + movaps -0x88(%rax),%xmm11 + movaps -0x78(%rax),%xmm12 + movaps -0x68(%rax),%xmm13 + movaps -0x58(%rax),%xmm14 + movaps -0x48(%rax),%xmm15 +___ +$code.=<<___; + mov -48(%rax),%r15 +.cfi_restore %r15 + mov -40(%rax),%r14 +.cfi_restore %r14 + mov -32(%rax),%r13 +.cfi_restore %r13 + mov -24(%rax),%r12 +.cfi_restore %r12 + mov -16(%rax),%rbp +.cfi_restore %rbp + mov -8(%rax),%rbx +.cfi_restore %rbx + lea (%rax),%rsp # restore %rsp +.cfi_def_cfa_register %rsp +.Lgcm_dec_abort: + mov $ret,%rax # return value + ret +.cfi_endproc +.size aesni_gcm_decrypt,.-aesni_gcm_decrypt +___ + +$code.=<<___; +.type _aesni_ctr32_6x,\@abi-omnipotent +.align 32 +_aesni_ctr32_6x: + vmovdqu 0x00-0x80($key),$Z0 # borrow $Z0 for $rndkey + vmovdqu 0x20($const),$T2 # borrow $T2, .Lone_msb + lea -1($rounds),%r13 + vmovups 0x10-0x80($key),$rndkey + lea 0x20-0x80($key),%r12 + vpxor $Z0,$T1,$inout0 + add \$`6<<24`,$counter + jc .Lhandle_ctr32_2 + vpaddb $T2,$T1,$inout1 + vpaddb $T2,$inout1,$inout2 + vpxor $Z0,$inout1,$inout1 + vpaddb $T2,$inout2,$inout3 + vpxor $Z0,$inout2,$inout2 + vpaddb $T2,$inout3,$inout4 + vpxor $Z0,$inout3,$inout3 + vpaddb $T2,$inout4,$inout5 + vpxor $Z0,$inout4,$inout4 + vpaddb $T2,$inout5,$T1 + vpxor $Z0,$inout5,$inout5 + jmp .Loop_ctr32 + +.align 16 +.Loop_ctr32: + vaesenc $rndkey,$inout0,$inout0 + vaesenc $rndkey,$inout1,$inout1 + vaesenc $rndkey,$inout2,$inout2 + vaesenc $rndkey,$inout3,$inout3 + vaesenc $rndkey,$inout4,$inout4 + vaesenc $rndkey,$inout5,$inout5 + vmovups (%r12),$rndkey + lea 0x10(%r12),%r12 + dec %r13d + jnz .Loop_ctr32 + + vmovdqu (%r12),$Hkey # last round key + vaesenc $rndkey,$inout0,$inout0 + vpxor 0x00($inp),$Hkey,$Z0 + vaesenc $rndkey,$inout1,$inout1 + vpxor 0x10($inp),$Hkey,$Z1 + vaesenc $rndkey,$inout2,$inout2 + vpxor 0x20($inp),$Hkey,$Z2 + vaesenc $rndkey,$inout3,$inout3 + vpxor 0x30($inp),$Hkey,$Xi + vaesenc $rndkey,$inout4,$inout4 + vpxor 0x40($inp),$Hkey,$T2 + vaesenc $rndkey,$inout5,$inout5 + vpxor 0x50($inp),$Hkey,$Hkey + lea 0x60($inp),$inp + + vaesenclast $Z0,$inout0,$inout0 + vaesenclast $Z1,$inout1,$inout1 + vaesenclast $Z2,$inout2,$inout2 + vaesenclast $Xi,$inout3,$inout3 + vaesenclast $T2,$inout4,$inout4 + vaesenclast $Hkey,$inout5,$inout5 + vmovups $inout0,0x00($out) + vmovups $inout1,0x10($out) + vmovups $inout2,0x20($out) + vmovups $inout3,0x30($out) + vmovups $inout4,0x40($out) + vmovups $inout5,0x50($out) + lea 0x60($out),$out + + ret +.align 32 +.Lhandle_ctr32_2: + vpshufb $Ii,$T1,$Z2 # byte-swap counter + vmovdqu 0x30($const),$Z1 # borrow $Z1, .Ltwo_lsb + vpaddd 0x40($const),$Z2,$inout1 # .Lone_lsb + vpaddd $Z1,$Z2,$inout2 + vpaddd $Z1,$inout1,$inout3 + vpshufb $Ii,$inout1,$inout1 + vpaddd $Z1,$inout2,$inout4 + vpshufb $Ii,$inout2,$inout2 + vpxor $Z0,$inout1,$inout1 + vpaddd $Z1,$inout3,$inout5 + vpshufb $Ii,$inout3,$inout3 + vpxor $Z0,$inout2,$inout2 + vpaddd $Z1,$inout4,$T1 # byte-swapped next counter value + vpshufb $Ii,$inout4,$inout4 + vpxor $Z0,$inout3,$inout3 + vpshufb $Ii,$inout5,$inout5 + vpxor $Z0,$inout4,$inout4 + vpshufb $Ii,$T1,$T1 # next counter value + vpxor $Z0,$inout5,$inout5 + jmp .Loop_ctr32 +.size _aesni_ctr32_6x,.-_aesni_ctr32_6x + +.globl aesni_gcm_encrypt +.type aesni_gcm_encrypt,\@function,6 +.align 32 +aesni_gcm_encrypt: +.cfi_startproc + xor $ret,$ret + cmp \$0x60*3,$len # minimal accepted length + jb .Lgcm_enc_abort + + lea (%rsp),%rax # save stack pointer +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +___ +$code.=<<___ if ($win64); + lea -0xa8(%rsp),%rsp + movaps %xmm6,-0xd8(%rax) + movaps %xmm7,-0xc8(%rax) + movaps %xmm8,-0xb8(%rax) + movaps %xmm9,-0xa8(%rax) + movaps %xmm10,-0x98(%rax) + movaps %xmm11,-0x88(%rax) + movaps %xmm12,-0x78(%rax) + movaps %xmm13,-0x68(%rax) + movaps %xmm14,-0x58(%rax) + movaps %xmm15,-0x48(%rax) +.Lgcm_enc_body: +___ +$code.=<<___; + vzeroupper + + vmovdqu ($ivp),$T1 # input counter value + add \$-128,%rsp + mov 12($ivp),$counter + lea .Lbswap_mask(%rip),$const + lea -0x80($key),$in0 # borrow $in0 + mov \$0xf80,$end0 # borrow $end0 + lea 0x80($key),$key # size optimization + vmovdqu ($const),$Ii # borrow $Ii for .Lbswap_mask + and \$-128,%rsp # ensure stack alignment + mov 0xf0-0x80($key),$rounds + + and $end0,$in0 + and %rsp,$end0 + sub $in0,$end0 + jc .Lenc_no_key_aliasing + cmp \$768,$end0 + jnc .Lenc_no_key_aliasing + sub $end0,%rsp # avoid aliasing with key +.Lenc_no_key_aliasing: + + lea ($out),$in0 + lea -0xc0($out,$len),$end0 + shr \$4,$len + + call _aesni_ctr32_6x + vpshufb $Ii,$inout0,$Xi # save bswapped output on stack + vpshufb $Ii,$inout1,$T2 + vmovdqu $Xi,0x70(%rsp) + vpshufb $Ii,$inout2,$Z0 + vmovdqu $T2,0x60(%rsp) + vpshufb $Ii,$inout3,$Z1 + vmovdqu $Z0,0x50(%rsp) + vpshufb $Ii,$inout4,$Z2 + vmovdqu $Z1,0x40(%rsp) + vpshufb $Ii,$inout5,$Z3 # passed to _aesni_ctr32_ghash_6x + vmovdqu $Z2,0x30(%rsp) + + call _aesni_ctr32_6x + + vmovdqu ($Xip),$Xi # load Xi + lea 0x20+0x20($Xip),$Xip # size optimization + sub \$12,$len + mov \$0x60*2,$ret + vpshufb $Ii,$Xi,$Xi + + call _aesni_ctr32_ghash_6x + vmovdqu 0x20(%rsp),$Z3 # I[5] + vmovdqu ($const),$Ii # borrow $Ii for .Lbswap_mask + vmovdqu 0x00-0x20($Xip),$Hkey # $Hkey^1 + vpunpckhqdq $Z3,$Z3,$T1 + vmovdqu 0x20-0x20($Xip),$rndkey # borrow $rndkey for $HK + vmovups $inout0,-0x60($out) # save output + vpshufb $Ii,$inout0,$inout0 # but keep bswapped copy + vpxor $Z3,$T1,$T1 + vmovups $inout1,-0x50($out) + vpshufb $Ii,$inout1,$inout1 + vmovups $inout2,-0x40($out) + vpshufb $Ii,$inout2,$inout2 + vmovups $inout3,-0x30($out) + vpshufb $Ii,$inout3,$inout3 + vmovups $inout4,-0x20($out) + vpshufb $Ii,$inout4,$inout4 + vmovups $inout5,-0x10($out) + vpshufb $Ii,$inout5,$inout5 + vmovdqu $inout0,0x10(%rsp) # free $inout0 +___ +{ my ($HK,$T3)=($rndkey,$inout0); + +$code.=<<___; + vmovdqu 0x30(%rsp),$Z2 # I[4] + vmovdqu 0x10-0x20($Xip),$Ii # borrow $Ii for $Hkey^2 + vpunpckhqdq $Z2,$Z2,$T2 + vpclmulqdq \$0x00,$Hkey,$Z3,$Z1 + vpxor $Z2,$T2,$T2 + vpclmulqdq \$0x11,$Hkey,$Z3,$Z3 + vpclmulqdq \$0x00,$HK,$T1,$T1 + + vmovdqu 0x40(%rsp),$T3 # I[3] + vpclmulqdq \$0x00,$Ii,$Z2,$Z0 + vmovdqu 0x30-0x20($Xip),$Hkey # $Hkey^3 + vpxor $Z1,$Z0,$Z0 + vpunpckhqdq $T3,$T3,$Z1 + vpclmulqdq \$0x11,$Ii,$Z2,$Z2 + vpxor $T3,$Z1,$Z1 + vpxor $Z3,$Z2,$Z2 + vpclmulqdq \$0x10,$HK,$T2,$T2 + vmovdqu 0x50-0x20($Xip),$HK + vpxor $T1,$T2,$T2 + + vmovdqu 0x50(%rsp),$T1 # I[2] + vpclmulqdq \$0x00,$Hkey,$T3,$Z3 + vmovdqu 0x40-0x20($Xip),$Ii # borrow $Ii for $Hkey^4 + vpxor $Z0,$Z3,$Z3 + vpunpckhqdq $T1,$T1,$Z0 + vpclmulqdq \$0x11,$Hkey,$T3,$T3 + vpxor $T1,$Z0,$Z0 + vpxor $Z2,$T3,$T3 + vpclmulqdq \$0x00,$HK,$Z1,$Z1 + vpxor $T2,$Z1,$Z1 + + vmovdqu 0x60(%rsp),$T2 # I[1] + vpclmulqdq \$0x00,$Ii,$T1,$Z2 + vmovdqu 0x60-0x20($Xip),$Hkey # $Hkey^5 + vpxor $Z3,$Z2,$Z2 + vpunpckhqdq $T2,$T2,$Z3 + vpclmulqdq \$0x11,$Ii,$T1,$T1 + vpxor $T2,$Z3,$Z3 + vpxor $T3,$T1,$T1 + vpclmulqdq \$0x10,$HK,$Z0,$Z0 + vmovdqu 0x80-0x20($Xip),$HK + vpxor $Z1,$Z0,$Z0 + + vpxor 0x70(%rsp),$Xi,$Xi # accumulate I[0] + vpclmulqdq \$0x00,$Hkey,$T2,$Z1 + vmovdqu 0x70-0x20($Xip),$Ii # borrow $Ii for $Hkey^6 + vpunpckhqdq $Xi,$Xi,$T3 + vpxor $Z2,$Z1,$Z1 + vpclmulqdq \$0x11,$Hkey,$T2,$T2 + vpxor $Xi,$T3,$T3 + vpxor $T1,$T2,$T2 + vpclmulqdq \$0x00,$HK,$Z3,$Z3 + vpxor $Z0,$Z3,$Z0 + + vpclmulqdq \$0x00,$Ii,$Xi,$Z2 + vmovdqu 0x00-0x20($Xip),$Hkey # $Hkey^1 + vpunpckhqdq $inout5,$inout5,$T1 + vpclmulqdq \$0x11,$Ii,$Xi,$Xi + vpxor $inout5,$T1,$T1 + vpxor $Z1,$Z2,$Z1 + vpclmulqdq \$0x10,$HK,$T3,$T3 + vmovdqu 0x20-0x20($Xip),$HK + vpxor $T2,$Xi,$Z3 + vpxor $Z0,$T3,$Z2 + + vmovdqu 0x10-0x20($Xip),$Ii # borrow $Ii for $Hkey^2 + vpxor $Z1,$Z3,$T3 # aggregated Karatsuba post-processing + vpclmulqdq \$0x00,$Hkey,$inout5,$Z0 + vpxor $T3,$Z2,$Z2 + vpunpckhqdq $inout4,$inout4,$T2 + vpclmulqdq \$0x11,$Hkey,$inout5,$inout5 + vpxor $inout4,$T2,$T2 + vpslldq \$8,$Z2,$T3 + vpclmulqdq \$0x00,$HK,$T1,$T1 + vpxor $T3,$Z1,$Xi + vpsrldq \$8,$Z2,$Z2 + vpxor $Z2,$Z3,$Z3 + + vpclmulqdq \$0x00,$Ii,$inout4,$Z1 + vmovdqu 0x30-0x20($Xip),$Hkey # $Hkey^3 + vpxor $Z0,$Z1,$Z1 + vpunpckhqdq $inout3,$inout3,$T3 + vpclmulqdq \$0x11,$Ii,$inout4,$inout4 + vpxor $inout3,$T3,$T3 + vpxor $inout5,$inout4,$inout4 + vpalignr \$8,$Xi,$Xi,$inout5 # 1st phase + vpclmulqdq \$0x10,$HK,$T2,$T2 + vmovdqu 0x50-0x20($Xip),$HK + vpxor $T1,$T2,$T2 + + vpclmulqdq \$0x00,$Hkey,$inout3,$Z0 + vmovdqu 0x40-0x20($Xip),$Ii # borrow $Ii for $Hkey^4 + vpxor $Z1,$Z0,$Z0 + vpunpckhqdq $inout2,$inout2,$T1 + vpclmulqdq \$0x11,$Hkey,$inout3,$inout3 + vpxor $inout2,$T1,$T1 + vpxor $inout4,$inout3,$inout3 + vxorps 0x10(%rsp),$Z3,$Z3 # accumulate $inout0 + vpclmulqdq \$0x00,$HK,$T3,$T3 + vpxor $T2,$T3,$T3 + + vpclmulqdq \$0x10,0x10($const),$Xi,$Xi + vxorps $inout5,$Xi,$Xi + + vpclmulqdq \$0x00,$Ii,$inout2,$Z1 + vmovdqu 0x60-0x20($Xip),$Hkey # $Hkey^5 + vpxor $Z0,$Z1,$Z1 + vpunpckhqdq $inout1,$inout1,$T2 + vpclmulqdq \$0x11,$Ii,$inout2,$inout2 + vpxor $inout1,$T2,$T2 + vpalignr \$8,$Xi,$Xi,$inout5 # 2nd phase + vpxor $inout3,$inout2,$inout2 + vpclmulqdq \$0x10,$HK,$T1,$T1 + vmovdqu 0x80-0x20($Xip),$HK + vpxor $T3,$T1,$T1 + + vxorps $Z3,$inout5,$inout5 + vpclmulqdq \$0x10,0x10($const),$Xi,$Xi + vxorps $inout5,$Xi,$Xi + + vpclmulqdq \$0x00,$Hkey,$inout1,$Z0 + vmovdqu 0x70-0x20($Xip),$Ii # borrow $Ii for $Hkey^6 + vpxor $Z1,$Z0,$Z0 + vpunpckhqdq $Xi,$Xi,$T3 + vpclmulqdq \$0x11,$Hkey,$inout1,$inout1 + vpxor $Xi,$T3,$T3 + vpxor $inout2,$inout1,$inout1 + vpclmulqdq \$0x00,$HK,$T2,$T2 + vpxor $T1,$T2,$T2 + + vpclmulqdq \$0x00,$Ii,$Xi,$Z1 + vpclmulqdq \$0x11,$Ii,$Xi,$Z3 + vpxor $Z0,$Z1,$Z1 + vpclmulqdq \$0x10,$HK,$T3,$Z2 + vpxor $inout1,$Z3,$Z3 + vpxor $T2,$Z2,$Z2 + + vpxor $Z1,$Z3,$Z0 # aggregated Karatsuba post-processing + vpxor $Z0,$Z2,$Z2 + vpslldq \$8,$Z2,$T1 + vmovdqu 0x10($const),$Hkey # .Lpoly + vpsrldq \$8,$Z2,$Z2 + vpxor $T1,$Z1,$Xi + vpxor $Z2,$Z3,$Z3 + + vpalignr \$8,$Xi,$Xi,$T2 # 1st phase + vpclmulqdq \$0x10,$Hkey,$Xi,$Xi + vpxor $T2,$Xi,$Xi + + vpalignr \$8,$Xi,$Xi,$T2 # 2nd phase + vpclmulqdq \$0x10,$Hkey,$Xi,$Xi + vpxor $Z3,$T2,$T2 + vpxor $T2,$Xi,$Xi +___ +} +$code.=<<___; + vpshufb ($const),$Xi,$Xi # .Lbswap_mask + vmovdqu $Xi,-0x40($Xip) # output Xi + + vzeroupper +___ +$code.=<<___ if ($win64); + movaps -0xd8(%rax),%xmm6 + movaps -0xc8(%rax),%xmm7 + movaps -0xb8(%rax),%xmm8 + movaps -0xa8(%rax),%xmm9 + movaps -0x98(%rax),%xmm10 + movaps -0x88(%rax),%xmm11 + movaps -0x78(%rax),%xmm12 + movaps -0x68(%rax),%xmm13 + movaps -0x58(%rax),%xmm14 + movaps -0x48(%rax),%xmm15 +___ +$code.=<<___; + mov -48(%rax),%r15 +.cfi_restore %r15 + mov -40(%rax),%r14 +.cfi_restore %r14 + mov -32(%rax),%r13 +.cfi_restore %r13 + mov -24(%rax),%r12 +.cfi_restore %r12 + mov -16(%rax),%rbp +.cfi_restore %rbp + mov -8(%rax),%rbx +.cfi_restore %rbx + lea (%rax),%rsp # restore %rsp +.cfi_def_cfa_register %rsp +.Lgcm_enc_abort: + mov $ret,%rax # return value + ret +.cfi_endproc +.size aesni_gcm_encrypt,.-aesni_gcm_encrypt +___ + +$code.=<<___; +.align 64 +.Lbswap_mask: + .byte 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 +.Lpoly: + .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc2 +.Lone_msb: + .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 +.Ltwo_lsb: + .byte 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +.Lone_lsb: + .byte 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +.asciz "AES-NI GCM module for x86_64, CRYPTOGAMS by " +.align 64 +___ +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___ +.extern __imp_RtlVirtualUnwind +.type gcm_se_handler,\@abi-omnipotent +.align 16 +gcm_se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lcommon_seh_tail + + mov 120($context),%rax # pull context->Rax + + mov -48(%rax),%r15 + mov -40(%rax),%r14 + mov -32(%rax),%r13 + mov -24(%rax),%r12 + mov -16(%rax),%rbp + mov -8(%rax),%rbx + mov %r15,240($context) + mov %r14,232($context) + mov %r13,224($context) + mov %r12,216($context) + mov %rbp,160($context) + mov %rbx,144($context) + + lea -0xd8(%rax),%rsi # %xmm save area + lea 512($context),%rdi # & context.Xmm6 + mov \$20,%ecx # 10*sizeof(%xmm0)/sizeof(%rax) + .long 0xa548f3fc # cld; rep movsq + +.Lcommon_seh_tail: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size gcm_se_handler,.-gcm_se_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_aesni_gcm_decrypt + .rva .LSEH_end_aesni_gcm_decrypt + .rva .LSEH_gcm_dec_info + + .rva .LSEH_begin_aesni_gcm_encrypt + .rva .LSEH_end_aesni_gcm_encrypt + .rva .LSEH_gcm_enc_info +.section .xdata +.align 8 +.LSEH_gcm_dec_info: + .byte 9,0,0,0 + .rva gcm_se_handler + .rva .Lgcm_dec_body,.Lgcm_dec_abort +.LSEH_gcm_enc_info: + .byte 9,0,0,0 + .rva gcm_se_handler + .rva .Lgcm_enc_body,.Lgcm_enc_abort +___ +} +}}} else {{{ +$code=<<___; # assembler is too old +.text + +.globl aesni_gcm_encrypt +.type aesni_gcm_encrypt,\@abi-omnipotent +aesni_gcm_encrypt: + xor %eax,%eax + ret +.size aesni_gcm_encrypt,.-aesni_gcm_encrypt + +.globl aesni_gcm_decrypt +.type aesni_gcm_decrypt,\@abi-omnipotent +aesni_gcm_decrypt: + xor %eax,%eax + ret +.size aesni_gcm_decrypt,.-aesni_gcm_decrypt +___ +}}} + +$code =~ s/\`([^\`]*)\`/eval($1)/gem; + +print $code; + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-alpha.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-alpha.pl new file mode 100644 index 000000000..ccf6b2bd6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-alpha.pl @@ -0,0 +1,467 @@ +#! /usr/bin/env perl +# Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# March 2010 +# +# The module implements "4-bit" GCM GHASH function and underlying +# single multiplication operation in GF(2^128). "4-bit" means that it +# uses 256 bytes per-key table [+128 bytes shared table]. Even though +# loops are aggressively modulo-scheduled in respect to references to +# Htbl and Z.hi updates for 8 cycles per byte, measured performance is +# ~12 cycles per processed byte on 21264 CPU. It seems to be a dynamic +# scheduling "glitch," because uprofile(1) indicates uniform sample +# distribution, as if all instruction bundles execute in 1.5 cycles. +# Meaning that it could have been even faster, yet 12 cycles is ~60% +# better than gcc-generated code and ~80% than code generated by vendor +# compiler. + +$cnt="v0"; # $0 +$t0="t0"; +$t1="t1"; +$t2="t2"; +$Thi0="t3"; # $4 +$Tlo0="t4"; +$Thi1="t5"; +$Tlo1="t6"; +$rem="t7"; # $8 +################# +$Xi="a0"; # $16, input argument block +$Htbl="a1"; +$inp="a2"; +$len="a3"; +$nlo="a4"; # $20 +$nhi="a5"; +$Zhi="t8"; +$Zlo="t9"; +$Xhi="t10"; # $24 +$Xlo="t11"; +$remp="t12"; +$rem_4bit="AT"; # $28 + +{ my $N; + sub loop() { + + $N++; +$code.=<<___; +.align 4 + extbl $Xlo,7,$nlo + and $nlo,0xf0,$nhi + sll $nlo,4,$nlo + and $nlo,0xf0,$nlo + + addq $nlo,$Htbl,$nlo + ldq $Zlo,8($nlo) + addq $nhi,$Htbl,$nhi + ldq $Zhi,0($nlo) + + and $Zlo,0x0f,$remp + sll $Zhi,60,$t0 + lda $cnt,6(zero) + extbl $Xlo,6,$nlo + + ldq $Tlo1,8($nhi) + s8addq $remp,$rem_4bit,$remp + ldq $Thi1,0($nhi) + srl $Zlo,4,$Zlo + + ldq $rem,0($remp) + srl $Zhi,4,$Zhi + xor $t0,$Zlo,$Zlo + and $nlo,0xf0,$nhi + + xor $Tlo1,$Zlo,$Zlo + sll $nlo,4,$nlo + xor $Thi1,$Zhi,$Zhi + and $nlo,0xf0,$nlo + + addq $nlo,$Htbl,$nlo + ldq $Tlo0,8($nlo) + addq $nhi,$Htbl,$nhi + ldq $Thi0,0($nlo) + +.Looplo$N: + and $Zlo,0x0f,$remp + sll $Zhi,60,$t0 + subq $cnt,1,$cnt + srl $Zlo,4,$Zlo + + ldq $Tlo1,8($nhi) + xor $rem,$Zhi,$Zhi + ldq $Thi1,0($nhi) + s8addq $remp,$rem_4bit,$remp + + ldq $rem,0($remp) + srl $Zhi,4,$Zhi + xor $t0,$Zlo,$Zlo + extbl $Xlo,$cnt,$nlo + + and $nlo,0xf0,$nhi + xor $Thi0,$Zhi,$Zhi + xor $Tlo0,$Zlo,$Zlo + sll $nlo,4,$nlo + + + and $Zlo,0x0f,$remp + sll $Zhi,60,$t0 + and $nlo,0xf0,$nlo + srl $Zlo,4,$Zlo + + s8addq $remp,$rem_4bit,$remp + xor $rem,$Zhi,$Zhi + addq $nlo,$Htbl,$nlo + addq $nhi,$Htbl,$nhi + + ldq $rem,0($remp) + srl $Zhi,4,$Zhi + ldq $Tlo0,8($nlo) + xor $t0,$Zlo,$Zlo + + xor $Tlo1,$Zlo,$Zlo + xor $Thi1,$Zhi,$Zhi + ldq $Thi0,0($nlo) + bne $cnt,.Looplo$N + + + and $Zlo,0x0f,$remp + sll $Zhi,60,$t0 + lda $cnt,7(zero) + srl $Zlo,4,$Zlo + + ldq $Tlo1,8($nhi) + xor $rem,$Zhi,$Zhi + ldq $Thi1,0($nhi) + s8addq $remp,$rem_4bit,$remp + + ldq $rem,0($remp) + srl $Zhi,4,$Zhi + xor $t0,$Zlo,$Zlo + extbl $Xhi,$cnt,$nlo + + and $nlo,0xf0,$nhi + xor $Thi0,$Zhi,$Zhi + xor $Tlo0,$Zlo,$Zlo + sll $nlo,4,$nlo + + and $Zlo,0x0f,$remp + sll $Zhi,60,$t0 + and $nlo,0xf0,$nlo + srl $Zlo,4,$Zlo + + s8addq $remp,$rem_4bit,$remp + xor $rem,$Zhi,$Zhi + addq $nlo,$Htbl,$nlo + addq $nhi,$Htbl,$nhi + + ldq $rem,0($remp) + srl $Zhi,4,$Zhi + ldq $Tlo0,8($nlo) + xor $t0,$Zlo,$Zlo + + xor $Tlo1,$Zlo,$Zlo + xor $Thi1,$Zhi,$Zhi + ldq $Thi0,0($nlo) + unop + + +.Loophi$N: + and $Zlo,0x0f,$remp + sll $Zhi,60,$t0 + subq $cnt,1,$cnt + srl $Zlo,4,$Zlo + + ldq $Tlo1,8($nhi) + xor $rem,$Zhi,$Zhi + ldq $Thi1,0($nhi) + s8addq $remp,$rem_4bit,$remp + + ldq $rem,0($remp) + srl $Zhi,4,$Zhi + xor $t0,$Zlo,$Zlo + extbl $Xhi,$cnt,$nlo + + and $nlo,0xf0,$nhi + xor $Thi0,$Zhi,$Zhi + xor $Tlo0,$Zlo,$Zlo + sll $nlo,4,$nlo + + + and $Zlo,0x0f,$remp + sll $Zhi,60,$t0 + and $nlo,0xf0,$nlo + srl $Zlo,4,$Zlo + + s8addq $remp,$rem_4bit,$remp + xor $rem,$Zhi,$Zhi + addq $nlo,$Htbl,$nlo + addq $nhi,$Htbl,$nhi + + ldq $rem,0($remp) + srl $Zhi,4,$Zhi + ldq $Tlo0,8($nlo) + xor $t0,$Zlo,$Zlo + + xor $Tlo1,$Zlo,$Zlo + xor $Thi1,$Zhi,$Zhi + ldq $Thi0,0($nlo) + bne $cnt,.Loophi$N + + + and $Zlo,0x0f,$remp + sll $Zhi,60,$t0 + srl $Zlo,4,$Zlo + + ldq $Tlo1,8($nhi) + xor $rem,$Zhi,$Zhi + ldq $Thi1,0($nhi) + s8addq $remp,$rem_4bit,$remp + + ldq $rem,0($remp) + srl $Zhi,4,$Zhi + xor $t0,$Zlo,$Zlo + + xor $Tlo0,$Zlo,$Zlo + xor $Thi0,$Zhi,$Zhi + + and $Zlo,0x0f,$remp + sll $Zhi,60,$t0 + srl $Zlo,4,$Zlo + + s8addq $remp,$rem_4bit,$remp + xor $rem,$Zhi,$Zhi + + ldq $rem,0($remp) + srl $Zhi,4,$Zhi + xor $Tlo1,$Zlo,$Zlo + xor $Thi1,$Zhi,$Zhi + xor $t0,$Zlo,$Zlo + xor $rem,$Zhi,$Zhi +___ +}} + +$code=<<___; +#ifdef __linux__ +#include +#else +#include +#include +#endif + +.text + +.set noat +.set noreorder +.globl gcm_gmult_4bit +.align 4 +.ent gcm_gmult_4bit +gcm_gmult_4bit: + .frame sp,0,ra + .prologue 0 + + ldq $Xlo,8($Xi) + ldq $Xhi,0($Xi) + + bsr $t0,picmeup + nop +___ + + &loop(); + +$code.=<<___; + srl $Zlo,24,$t0 # byte swap + srl $Zlo,8,$t1 + + sll $Zlo,8,$t2 + sll $Zlo,24,$Zlo + zapnot $t0,0x11,$t0 + zapnot $t1,0x22,$t1 + + zapnot $Zlo,0x88,$Zlo + or $t0,$t1,$t0 + zapnot $t2,0x44,$t2 + + or $Zlo,$t0,$Zlo + srl $Zhi,24,$t0 + srl $Zhi,8,$t1 + + or $Zlo,$t2,$Zlo + sll $Zhi,8,$t2 + sll $Zhi,24,$Zhi + + srl $Zlo,32,$Xlo + sll $Zlo,32,$Zlo + + zapnot $t0,0x11,$t0 + zapnot $t1,0x22,$t1 + or $Zlo,$Xlo,$Xlo + + zapnot $Zhi,0x88,$Zhi + or $t0,$t1,$t0 + zapnot $t2,0x44,$t2 + + or $Zhi,$t0,$Zhi + or $Zhi,$t2,$Zhi + + srl $Zhi,32,$Xhi + sll $Zhi,32,$Zhi + + or $Zhi,$Xhi,$Xhi + stq $Xlo,8($Xi) + stq $Xhi,0($Xi) + + ret (ra) +.end gcm_gmult_4bit +___ + +$inhi="s0"; +$inlo="s1"; + +$code.=<<___; +.globl gcm_ghash_4bit +.align 4 +.ent gcm_ghash_4bit +gcm_ghash_4bit: + lda sp,-32(sp) + stq ra,0(sp) + stq s0,8(sp) + stq s1,16(sp) + .mask 0x04000600,-32 + .frame sp,32,ra + .prologue 0 + + ldq_u $inhi,0($inp) + ldq_u $Thi0,7($inp) + ldq_u $inlo,8($inp) + ldq_u $Tlo0,15($inp) + ldq $Xhi,0($Xi) + ldq $Xlo,8($Xi) + + bsr $t0,picmeup + nop + +.Louter: + extql $inhi,$inp,$inhi + extqh $Thi0,$inp,$Thi0 + or $inhi,$Thi0,$inhi + lda $inp,16($inp) + + extql $inlo,$inp,$inlo + extqh $Tlo0,$inp,$Tlo0 + or $inlo,$Tlo0,$inlo + subq $len,16,$len + + xor $Xlo,$inlo,$Xlo + xor $Xhi,$inhi,$Xhi +___ + + &loop(); + +$code.=<<___; + srl $Zlo,24,$t0 # byte swap + srl $Zlo,8,$t1 + + sll $Zlo,8,$t2 + sll $Zlo,24,$Zlo + zapnot $t0,0x11,$t0 + zapnot $t1,0x22,$t1 + + zapnot $Zlo,0x88,$Zlo + or $t0,$t1,$t0 + zapnot $t2,0x44,$t2 + + or $Zlo,$t0,$Zlo + srl $Zhi,24,$t0 + srl $Zhi,8,$t1 + + or $Zlo,$t2,$Zlo + sll $Zhi,8,$t2 + sll $Zhi,24,$Zhi + + srl $Zlo,32,$Xlo + sll $Zlo,32,$Zlo + beq $len,.Ldone + + zapnot $t0,0x11,$t0 + zapnot $t1,0x22,$t1 + or $Zlo,$Xlo,$Xlo + ldq_u $inhi,0($inp) + + zapnot $Zhi,0x88,$Zhi + or $t0,$t1,$t0 + zapnot $t2,0x44,$t2 + ldq_u $Thi0,7($inp) + + or $Zhi,$t0,$Zhi + or $Zhi,$t2,$Zhi + ldq_u $inlo,8($inp) + ldq_u $Tlo0,15($inp) + + srl $Zhi,32,$Xhi + sll $Zhi,32,$Zhi + + or $Zhi,$Xhi,$Xhi + br zero,.Louter + +.Ldone: + zapnot $t0,0x11,$t0 + zapnot $t1,0x22,$t1 + or $Zlo,$Xlo,$Xlo + + zapnot $Zhi,0x88,$Zhi + or $t0,$t1,$t0 + zapnot $t2,0x44,$t2 + + or $Zhi,$t0,$Zhi + or $Zhi,$t2,$Zhi + + srl $Zhi,32,$Xhi + sll $Zhi,32,$Zhi + + or $Zhi,$Xhi,$Xhi + + stq $Xlo,8($Xi) + stq $Xhi,0($Xi) + + .set noreorder + /*ldq ra,0(sp)*/ + ldq s0,8(sp) + ldq s1,16(sp) + lda sp,32(sp) + ret (ra) +.end gcm_ghash_4bit + +.align 4 +.ent picmeup +picmeup: + .frame sp,0,$t0 + .prologue 0 + br $rem_4bit,.Lpic +.Lpic: lda $rem_4bit,12($rem_4bit) + ret ($t0) +.end picmeup + nop +rem_4bit: + .long 0,0x0000<<16, 0,0x1C20<<16, 0,0x3840<<16, 0,0x2460<<16 + .long 0,0x7080<<16, 0,0x6CA0<<16, 0,0x48C0<<16, 0,0x54E0<<16 + .long 0,0xE100<<16, 0,0xFD20<<16, 0,0xD940<<16, 0,0xC560<<16 + .long 0,0x9180<<16, 0,0x8DA0<<16, 0,0xA9C0<<16, 0,0xB5E0<<16 +.ascii "GHASH for Alpha, CRYPTOGAMS by " +.align 4 + +___ +$output=pop and open STDOUT,">$output"; +print $code; +close STDOUT; + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-armv4.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-armv4.pl new file mode 100644 index 000000000..dcc23f7d7 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-armv4.pl @@ -0,0 +1,551 @@ +#! /usr/bin/env perl +# Copyright 2010-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# April 2010 +# +# The module implements "4-bit" GCM GHASH function and underlying +# single multiplication operation in GF(2^128). "4-bit" means that it +# uses 256 bytes per-key table [+32 bytes shared table]. There is no +# experimental performance data available yet. The only approximation +# that can be made at this point is based on code size. Inner loop is +# 32 instructions long and on single-issue core should execute in <40 +# cycles. Having verified that gcc 3.4 didn't unroll corresponding +# loop, this assembler loop body was found to be ~3x smaller than +# compiler-generated one... +# +# July 2010 +# +# Rescheduling for dual-issue pipeline resulted in 8.5% improvement on +# Cortex A8 core and ~25 cycles per processed byte (which was observed +# to be ~3 times faster than gcc-generated code:-) +# +# February 2011 +# +# Profiler-assisted and platform-specific optimization resulted in 7% +# improvement on Cortex A8 core and ~23.5 cycles per byte. +# +# March 2011 +# +# Add NEON implementation featuring polynomial multiplication, i.e. no +# lookup tables involved. On Cortex A8 it was measured to process one +# byte in 15 cycles or 55% faster than integer-only code. +# +# April 2014 +# +# Switch to multiplication algorithm suggested in paper referred +# below and combine it with reduction algorithm from x86 module. +# Performance improvement over previous version varies from 65% on +# Snapdragon S4 to 110% on Cortex A9. In absolute terms Cortex A8 +# processes one byte in 8.45 cycles, A9 - in 10.2, A15 - in 7.63, +# Snapdragon S4 - in 9.33. +# +# Câmara, D.; Gouvêa, C. P. L.; López, J. & Dahab, R.: Fast Software +# Polynomial Multiplication on ARM Processors using the NEON Engine. +# +# http://conradoplg.cryptoland.net/files/2010/12/mocrysen13.pdf + +# ==================================================================== +# Note about "528B" variant. In ARM case it makes lesser sense to +# implement it for following reasons: +# +# - performance improvement won't be anywhere near 50%, because 128- +# bit shift operation is neatly fused with 128-bit xor here, and +# "538B" variant would eliminate only 4-5 instructions out of 32 +# in the inner loop (meaning that estimated improvement is ~15%); +# - ARM-based systems are often embedded ones and extra memory +# consumption might be unappreciated (for so little improvement); +# +# Byte order [in]dependence. ========================================= +# +# Caller is expected to maintain specific *dword* order in Htable, +# namely with *least* significant dword of 128-bit value at *lower* +# address. This differs completely from C code and has everything to +# do with ldm instruction and order in which dwords are "consumed" by +# algorithm. *Byte* order within these dwords in turn is whatever +# *native* byte order on current platform. See gcm128.c for working +# example... + +$flavour = shift; +if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + open STDOUT,">$output"; +} + +$Xi="r0"; # argument block +$Htbl="r1"; +$inp="r2"; +$len="r3"; + +$Zll="r4"; # variables +$Zlh="r5"; +$Zhl="r6"; +$Zhh="r7"; +$Tll="r8"; +$Tlh="r9"; +$Thl="r10"; +$Thh="r11"; +$nlo="r12"; +################# r13 is stack pointer +$nhi="r14"; +################# r15 is program counter + +$rem_4bit=$inp; # used in gcm_gmult_4bit +$cnt=$len; + +sub Zsmash() { + my $i=12; + my @args=@_; + for ($Zll,$Zlh,$Zhl,$Zhh) { + $code.=<<___; +#if __ARM_ARCH__>=7 && defined(__ARMEL__) + rev $_,$_ + str $_,[$Xi,#$i] +#elif defined(__ARMEB__) + str $_,[$Xi,#$i] +#else + mov $Tlh,$_,lsr#8 + strb $_,[$Xi,#$i+3] + mov $Thl,$_,lsr#16 + strb $Tlh,[$Xi,#$i+2] + mov $Thh,$_,lsr#24 + strb $Thl,[$Xi,#$i+1] + strb $Thh,[$Xi,#$i] +#endif +___ + $code.="\t".shift(@args)."\n"; + $i-=4; + } +} + +$code=<<___; +#include "arm_arch.h" + +.text +#if defined(__thumb2__) || defined(__clang__) +.syntax unified +#define ldrplb ldrbpl +#define ldrneb ldrbne +#endif +#if defined(__thumb2__) +.thumb +#else +.code 32 +#endif + +.type rem_4bit,%object +.align 5 +rem_4bit: +.short 0x0000,0x1C20,0x3840,0x2460 +.short 0x7080,0x6CA0,0x48C0,0x54E0 +.short 0xE100,0xFD20,0xD940,0xC560 +.short 0x9180,0x8DA0,0xA9C0,0xB5E0 +.size rem_4bit,.-rem_4bit + +.type rem_4bit_get,%function +rem_4bit_get: +#if defined(__thumb2__) + adr $rem_4bit,rem_4bit +#else + sub $rem_4bit,pc,#8+32 @ &rem_4bit +#endif + b .Lrem_4bit_got + nop + nop +.size rem_4bit_get,.-rem_4bit_get + +.global gcm_ghash_4bit +.type gcm_ghash_4bit,%function +.align 4 +gcm_ghash_4bit: +#if defined(__thumb2__) + adr r12,rem_4bit +#else + sub r12,pc,#8+48 @ &rem_4bit +#endif + add $len,$inp,$len @ $len to point at the end + stmdb sp!,{r3-r11,lr} @ save $len/end too + + ldmia r12,{r4-r11} @ copy rem_4bit ... + stmdb sp!,{r4-r11} @ ... to stack + + ldrb $nlo,[$inp,#15] + ldrb $nhi,[$Xi,#15] +.Louter: + eor $nlo,$nlo,$nhi + and $nhi,$nlo,#0xf0 + and $nlo,$nlo,#0x0f + mov $cnt,#14 + + add $Zhh,$Htbl,$nlo,lsl#4 + ldmia $Zhh,{$Zll-$Zhh} @ load Htbl[nlo] + add $Thh,$Htbl,$nhi + ldrb $nlo,[$inp,#14] + + and $nhi,$Zll,#0xf @ rem + ldmia $Thh,{$Tll-$Thh} @ load Htbl[nhi] + add $nhi,$nhi,$nhi + eor $Zll,$Tll,$Zll,lsr#4 + ldrh $Tll,[sp,$nhi] @ rem_4bit[rem] + eor $Zll,$Zll,$Zlh,lsl#28 + ldrb $nhi,[$Xi,#14] + eor $Zlh,$Tlh,$Zlh,lsr#4 + eor $Zlh,$Zlh,$Zhl,lsl#28 + eor $Zhl,$Thl,$Zhl,lsr#4 + eor $Zhl,$Zhl,$Zhh,lsl#28 + eor $Zhh,$Thh,$Zhh,lsr#4 + eor $nlo,$nlo,$nhi + and $nhi,$nlo,#0xf0 + and $nlo,$nlo,#0x0f + eor $Zhh,$Zhh,$Tll,lsl#16 + +.Linner: + add $Thh,$Htbl,$nlo,lsl#4 + and $nlo,$Zll,#0xf @ rem + subs $cnt,$cnt,#1 + add $nlo,$nlo,$nlo + ldmia $Thh,{$Tll-$Thh} @ load Htbl[nlo] + eor $Zll,$Tll,$Zll,lsr#4 + eor $Zll,$Zll,$Zlh,lsl#28 + eor $Zlh,$Tlh,$Zlh,lsr#4 + eor $Zlh,$Zlh,$Zhl,lsl#28 + ldrh $Tll,[sp,$nlo] @ rem_4bit[rem] + eor $Zhl,$Thl,$Zhl,lsr#4 +#ifdef __thumb2__ + it pl +#endif + ldrplb $nlo,[$inp,$cnt] + eor $Zhl,$Zhl,$Zhh,lsl#28 + eor $Zhh,$Thh,$Zhh,lsr#4 + + add $Thh,$Htbl,$nhi + and $nhi,$Zll,#0xf @ rem + eor $Zhh,$Zhh,$Tll,lsl#16 @ ^= rem_4bit[rem] + add $nhi,$nhi,$nhi + ldmia $Thh,{$Tll-$Thh} @ load Htbl[nhi] + eor $Zll,$Tll,$Zll,lsr#4 +#ifdef __thumb2__ + it pl +#endif + ldrplb $Tll,[$Xi,$cnt] + eor $Zll,$Zll,$Zlh,lsl#28 + eor $Zlh,$Tlh,$Zlh,lsr#4 + ldrh $Tlh,[sp,$nhi] + eor $Zlh,$Zlh,$Zhl,lsl#28 + eor $Zhl,$Thl,$Zhl,lsr#4 + eor $Zhl,$Zhl,$Zhh,lsl#28 +#ifdef __thumb2__ + it pl +#endif + eorpl $nlo,$nlo,$Tll + eor $Zhh,$Thh,$Zhh,lsr#4 +#ifdef __thumb2__ + itt pl +#endif + andpl $nhi,$nlo,#0xf0 + andpl $nlo,$nlo,#0x0f + eor $Zhh,$Zhh,$Tlh,lsl#16 @ ^= rem_4bit[rem] + bpl .Linner + + ldr $len,[sp,#32] @ re-load $len/end + add $inp,$inp,#16 + mov $nhi,$Zll +___ + &Zsmash("cmp\t$inp,$len","\n". + "#ifdef __thumb2__\n". + " it ne\n". + "#endif\n". + " ldrneb $nlo,[$inp,#15]"); +$code.=<<___; + bne .Louter + + add sp,sp,#36 +#if __ARM_ARCH__>=5 + ldmia sp!,{r4-r11,pc} +#else + ldmia sp!,{r4-r11,lr} + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.size gcm_ghash_4bit,.-gcm_ghash_4bit + +.global gcm_gmult_4bit +.type gcm_gmult_4bit,%function +gcm_gmult_4bit: + stmdb sp!,{r4-r11,lr} + ldrb $nlo,[$Xi,#15] + b rem_4bit_get +.Lrem_4bit_got: + and $nhi,$nlo,#0xf0 + and $nlo,$nlo,#0x0f + mov $cnt,#14 + + add $Zhh,$Htbl,$nlo,lsl#4 + ldmia $Zhh,{$Zll-$Zhh} @ load Htbl[nlo] + ldrb $nlo,[$Xi,#14] + + add $Thh,$Htbl,$nhi + and $nhi,$Zll,#0xf @ rem + ldmia $Thh,{$Tll-$Thh} @ load Htbl[nhi] + add $nhi,$nhi,$nhi + eor $Zll,$Tll,$Zll,lsr#4 + ldrh $Tll,[$rem_4bit,$nhi] @ rem_4bit[rem] + eor $Zll,$Zll,$Zlh,lsl#28 + eor $Zlh,$Tlh,$Zlh,lsr#4 + eor $Zlh,$Zlh,$Zhl,lsl#28 + eor $Zhl,$Thl,$Zhl,lsr#4 + eor $Zhl,$Zhl,$Zhh,lsl#28 + eor $Zhh,$Thh,$Zhh,lsr#4 + and $nhi,$nlo,#0xf0 + eor $Zhh,$Zhh,$Tll,lsl#16 + and $nlo,$nlo,#0x0f + +.Loop: + add $Thh,$Htbl,$nlo,lsl#4 + and $nlo,$Zll,#0xf @ rem + subs $cnt,$cnt,#1 + add $nlo,$nlo,$nlo + ldmia $Thh,{$Tll-$Thh} @ load Htbl[nlo] + eor $Zll,$Tll,$Zll,lsr#4 + eor $Zll,$Zll,$Zlh,lsl#28 + eor $Zlh,$Tlh,$Zlh,lsr#4 + eor $Zlh,$Zlh,$Zhl,lsl#28 + ldrh $Tll,[$rem_4bit,$nlo] @ rem_4bit[rem] + eor $Zhl,$Thl,$Zhl,lsr#4 +#ifdef __thumb2__ + it pl +#endif + ldrplb $nlo,[$Xi,$cnt] + eor $Zhl,$Zhl,$Zhh,lsl#28 + eor $Zhh,$Thh,$Zhh,lsr#4 + + add $Thh,$Htbl,$nhi + and $nhi,$Zll,#0xf @ rem + eor $Zhh,$Zhh,$Tll,lsl#16 @ ^= rem_4bit[rem] + add $nhi,$nhi,$nhi + ldmia $Thh,{$Tll-$Thh} @ load Htbl[nhi] + eor $Zll,$Tll,$Zll,lsr#4 + eor $Zll,$Zll,$Zlh,lsl#28 + eor $Zlh,$Tlh,$Zlh,lsr#4 + ldrh $Tll,[$rem_4bit,$nhi] @ rem_4bit[rem] + eor $Zlh,$Zlh,$Zhl,lsl#28 + eor $Zhl,$Thl,$Zhl,lsr#4 + eor $Zhl,$Zhl,$Zhh,lsl#28 + eor $Zhh,$Thh,$Zhh,lsr#4 +#ifdef __thumb2__ + itt pl +#endif + andpl $nhi,$nlo,#0xf0 + andpl $nlo,$nlo,#0x0f + eor $Zhh,$Zhh,$Tll,lsl#16 @ ^= rem_4bit[rem] + bpl .Loop +___ + &Zsmash(); +$code.=<<___; +#if __ARM_ARCH__>=5 + ldmia sp!,{r4-r11,pc} +#else + ldmia sp!,{r4-r11,lr} + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.size gcm_gmult_4bit,.-gcm_gmult_4bit +___ +{ +my ($Xl,$Xm,$Xh,$IN)=map("q$_",(0..3)); +my ($t0,$t1,$t2,$t3)=map("q$_",(8..12)); +my ($Hlo,$Hhi,$Hhl,$k48,$k32,$k16)=map("d$_",(26..31)); + +sub clmul64x64 { +my ($r,$a,$b)=@_; +$code.=<<___; + vext.8 $t0#lo, $a, $a, #1 @ A1 + vmull.p8 $t0, $t0#lo, $b @ F = A1*B + vext.8 $r#lo, $b, $b, #1 @ B1 + vmull.p8 $r, $a, $r#lo @ E = A*B1 + vext.8 $t1#lo, $a, $a, #2 @ A2 + vmull.p8 $t1, $t1#lo, $b @ H = A2*B + vext.8 $t3#lo, $b, $b, #2 @ B2 + vmull.p8 $t3, $a, $t3#lo @ G = A*B2 + vext.8 $t2#lo, $a, $a, #3 @ A3 + veor $t0, $t0, $r @ L = E + F + vmull.p8 $t2, $t2#lo, $b @ J = A3*B + vext.8 $r#lo, $b, $b, #3 @ B3 + veor $t1, $t1, $t3 @ M = G + H + vmull.p8 $r, $a, $r#lo @ I = A*B3 + veor $t0#lo, $t0#lo, $t0#hi @ t0 = (L) (P0 + P1) << 8 + vand $t0#hi, $t0#hi, $k48 + vext.8 $t3#lo, $b, $b, #4 @ B4 + veor $t1#lo, $t1#lo, $t1#hi @ t1 = (M) (P2 + P3) << 16 + vand $t1#hi, $t1#hi, $k32 + vmull.p8 $t3, $a, $t3#lo @ K = A*B4 + veor $t2, $t2, $r @ N = I + J + veor $t0#lo, $t0#lo, $t0#hi + veor $t1#lo, $t1#lo, $t1#hi + veor $t2#lo, $t2#lo, $t2#hi @ t2 = (N) (P4 + P5) << 24 + vand $t2#hi, $t2#hi, $k16 + vext.8 $t0, $t0, $t0, #15 + veor $t3#lo, $t3#lo, $t3#hi @ t3 = (K) (P6 + P7) << 32 + vmov.i64 $t3#hi, #0 + vext.8 $t1, $t1, $t1, #14 + veor $t2#lo, $t2#lo, $t2#hi + vmull.p8 $r, $a, $b @ D = A*B + vext.8 $t3, $t3, $t3, #12 + vext.8 $t2, $t2, $t2, #13 + veor $t0, $t0, $t1 + veor $t2, $t2, $t3 + veor $r, $r, $t0 + veor $r, $r, $t2 +___ +} + +$code.=<<___; +#if __ARM_MAX_ARCH__>=7 +.arch armv7-a +.fpu neon + +.global gcm_init_neon +.type gcm_init_neon,%function +.align 4 +gcm_init_neon: + vld1.64 $IN#hi,[r1]! @ load H + vmov.i8 $t0,#0xe1 + vld1.64 $IN#lo,[r1] + vshl.i64 $t0#hi,#57 + vshr.u64 $t0#lo,#63 @ t0=0xc2....01 + vdup.8 $t1,$IN#hi[7] + vshr.u64 $Hlo,$IN#lo,#63 + vshr.s8 $t1,#7 @ broadcast carry bit + vshl.i64 $IN,$IN,#1 + vand $t0,$t0,$t1 + vorr $IN#hi,$Hlo @ H<<<=1 + veor $IN,$IN,$t0 @ twisted H + vstmia r0,{$IN} + + ret @ bx lr +.size gcm_init_neon,.-gcm_init_neon + +.global gcm_gmult_neon +.type gcm_gmult_neon,%function +.align 4 +gcm_gmult_neon: + vld1.64 $IN#hi,[$Xi]! @ load Xi + vld1.64 $IN#lo,[$Xi]! + vmov.i64 $k48,#0x0000ffffffffffff + vldmia $Htbl,{$Hlo-$Hhi} @ load twisted H + vmov.i64 $k32,#0x00000000ffffffff +#ifdef __ARMEL__ + vrev64.8 $IN,$IN +#endif + vmov.i64 $k16,#0x000000000000ffff + veor $Hhl,$Hlo,$Hhi @ Karatsuba pre-processing + mov $len,#16 + b .Lgmult_neon +.size gcm_gmult_neon,.-gcm_gmult_neon + +.global gcm_ghash_neon +.type gcm_ghash_neon,%function +.align 4 +gcm_ghash_neon: + vld1.64 $Xl#hi,[$Xi]! @ load Xi + vld1.64 $Xl#lo,[$Xi]! + vmov.i64 $k48,#0x0000ffffffffffff + vldmia $Htbl,{$Hlo-$Hhi} @ load twisted H + vmov.i64 $k32,#0x00000000ffffffff +#ifdef __ARMEL__ + vrev64.8 $Xl,$Xl +#endif + vmov.i64 $k16,#0x000000000000ffff + veor $Hhl,$Hlo,$Hhi @ Karatsuba pre-processing + +.Loop_neon: + vld1.64 $IN#hi,[$inp]! @ load inp + vld1.64 $IN#lo,[$inp]! +#ifdef __ARMEL__ + vrev64.8 $IN,$IN +#endif + veor $IN,$Xl @ inp^=Xi +.Lgmult_neon: +___ + &clmul64x64 ($Xl,$Hlo,"$IN#lo"); # H.lo·Xi.lo +$code.=<<___; + veor $IN#lo,$IN#lo,$IN#hi @ Karatsuba pre-processing +___ + &clmul64x64 ($Xm,$Hhl,"$IN#lo"); # (H.lo+H.hi)·(Xi.lo+Xi.hi) + &clmul64x64 ($Xh,$Hhi,"$IN#hi"); # H.hi·Xi.hi +$code.=<<___; + veor $Xm,$Xm,$Xl @ Karatsuba post-processing + veor $Xm,$Xm,$Xh + veor $Xl#hi,$Xl#hi,$Xm#lo + veor $Xh#lo,$Xh#lo,$Xm#hi @ Xh|Xl - 256-bit result + + @ equivalent of reduction_avx from ghash-x86_64.pl + vshl.i64 $t1,$Xl,#57 @ 1st phase + vshl.i64 $t2,$Xl,#62 + veor $t2,$t2,$t1 @ + vshl.i64 $t1,$Xl,#63 + veor $t2, $t2, $t1 @ + veor $Xl#hi,$Xl#hi,$t2#lo @ + veor $Xh#lo,$Xh#lo,$t2#hi + + vshr.u64 $t2,$Xl,#1 @ 2nd phase + veor $Xh,$Xh,$Xl + veor $Xl,$Xl,$t2 @ + vshr.u64 $t2,$t2,#6 + vshr.u64 $Xl,$Xl,#1 @ + veor $Xl,$Xl,$Xh @ + veor $Xl,$Xl,$t2 @ + + subs $len,#16 + bne .Loop_neon + +#ifdef __ARMEL__ + vrev64.8 $Xl,$Xl +#endif + sub $Xi,#16 + vst1.64 $Xl#hi,[$Xi]! @ write out Xi + vst1.64 $Xl#lo,[$Xi] + + ret @ bx lr +.size gcm_ghash_neon,.-gcm_ghash_neon +#endif +___ +} +$code.=<<___; +.asciz "GHASH for ARMv4/NEON, CRYPTOGAMS by " +.align 2 +___ + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/geo; + + s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo or + s/\bret\b/bx lr/go or + s/\bbx\s+lr\b/.word\t0xe12fff1e/go; # make it possible to compile with -march=armv4 + + print $_,"\n"; +} +close STDOUT; # enforce flush diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-c64xplus.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-c64xplus.pl new file mode 100644 index 000000000..3cadda399 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-c64xplus.pl @@ -0,0 +1,247 @@ +#! /usr/bin/env perl +# Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# December 2011 +# +# The module implements GCM GHASH function and underlying single +# multiplication operation in GF(2^128). Even though subroutines +# have _4bit suffix, they are not using any tables, but rely on +# hardware Galois Field Multiply support. Streamed GHASH processes +# byte in ~7 cycles, which is >6x faster than "4-bit" table-driven +# code compiled with TI's cl6x 6.0 with -mv6400+ -o2 flags. We are +# comparing apples vs. oranges, but compiler surely could have done +# better, because theoretical [though not necessarily achievable] +# estimate for "4-bit" table-driven implementation is ~12 cycles. + +while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} +open STDOUT,">$output"; + +($Xip,$Htable,$inp,$len)=("A4","B4","A6","B6"); # arguments + +($Z0,$Z1,$Z2,$Z3, $H0, $H1, $H2, $H3, + $H0x,$H1x,$H2x,$H3x)=map("A$_",(16..27)); +($H01u,$H01y,$H2u,$H3u, $H0y,$H1y,$H2y,$H3y, + $H0z,$H1z,$H2z,$H3z)=map("B$_",(16..27)); +($FF000000,$E10000)=("B30","B31"); +($xip,$x0,$x1,$xib)=map("B$_",(6..9)); # $xip zaps $len + $xia="A9"; +($rem,$res)=("B4","B5"); # $rem zaps $Htable + +$code.=<<___; + .text + + .if .ASSEMBLER_VERSION<7000000 + .asg 0,__TI_EABI__ + .endif + .if __TI_EABI__ + .asg gcm_gmult_1bit,_gcm_gmult_1bit + .asg gcm_gmult_4bit,_gcm_gmult_4bit + .asg gcm_ghash_4bit,_gcm_ghash_4bit + .endif + + .asg B3,RA + + .if 0 + .global _gcm_gmult_1bit +_gcm_gmult_1bit: + ADDAD $Htable,2,$Htable + .endif + .global _gcm_gmult_4bit +_gcm_gmult_4bit: + .asmfunc + LDDW *${Htable}[-1],$H1:$H0 ; H.lo + LDDW *${Htable}[-2],$H3:$H2 ; H.hi +|| MV $Xip,${xip} ; reassign Xi +|| MVK 15,B1 ; SPLOOPD constant + + MVK 0xE1,$E10000 +|| LDBU *++${xip}[15],$x1 ; Xi[15] + MVK 0xFF,$FF000000 +|| LDBU *--${xip},$x0 ; Xi[14] + SHL $E10000,16,$E10000 ; [pre-shifted] reduction polynomial + SHL $FF000000,24,$FF000000 ; upper byte mask +|| BNOP ghash_loop? +|| MVK 1,B0 ; take a single spin + + PACKH2 $H0,$H1,$xia ; pack H0' and H1's upper bytes + AND $H2,$FF000000,$H2u ; H2's upper byte + AND $H3,$FF000000,$H3u ; H3's upper byte +|| SHRU $H2u,8,$H2u + SHRU $H3u,8,$H3u +|| ZERO $Z1:$Z0 + SHRU2 $xia,8,$H01u +|| ZERO $Z3:$Z2 + .endasmfunc + + .global _gcm_ghash_4bit +_gcm_ghash_4bit: + .asmfunc + LDDW *${Htable}[-1],$H1:$H0 ; H.lo +|| SHRU $len,4,B0 ; reassign len + LDDW *${Htable}[-2],$H3:$H2 ; H.hi +|| MV $Xip,${xip} ; reassign Xi +|| MVK 15,B1 ; SPLOOPD constant + + MVK 0xE1,$E10000 +|| [B0] LDNDW *${inp}[1],$H1x:$H0x + MVK 0xFF,$FF000000 +|| [B0] LDNDW *${inp}++[2],$H3x:$H2x + SHL $E10000,16,$E10000 ; [pre-shifted] reduction polynomial +|| LDDW *${xip}[1],$Z1:$Z0 + SHL $FF000000,24,$FF000000 ; upper byte mask +|| LDDW *${xip}[0],$Z3:$Z2 + + PACKH2 $H0,$H1,$xia ; pack H0' and H1's upper bytes + AND $H2,$FF000000,$H2u ; H2's upper byte + AND $H3,$FF000000,$H3u ; H3's upper byte +|| SHRU $H2u,8,$H2u + SHRU $H3u,8,$H3u + SHRU2 $xia,8,$H01u + +|| [B0] XOR $H0x,$Z0,$Z0 ; Xi^=inp +|| [B0] XOR $H1x,$Z1,$Z1 + .if .LITTLE_ENDIAN + [B0] XOR $H2x,$Z2,$Z2 +|| [B0] XOR $H3x,$Z3,$Z3 +|| [B0] SHRU $Z1,24,$xia ; Xi[15], avoid cross-path stall + STDW $Z1:$Z0,*${xip}[1] +|| [B0] SHRU $Z1,16,$x0 ; Xi[14] +|| [B0] ZERO $Z1:$Z0 + .else + [B0] XOR $H2x,$Z2,$Z2 +|| [B0] XOR $H3x,$Z3,$Z3 +|| [B0] MV $Z0,$xia ; Xi[15], avoid cross-path stall + STDW $Z1:$Z0,*${xip}[1] +|| [B0] SHRU $Z0,8,$x0 ; Xi[14] +|| [B0] ZERO $Z1:$Z0 + .endif + STDW $Z3:$Z2,*${xip}[0] +|| [B0] ZERO $Z3:$Z2 +|| [B0] MV $xia,$x1 + [B0] ADDK 14,${xip} + +ghash_loop?: + SPLOOPD 6 ; 6*16+7 +|| MVC B1,ILC +|| [B0] SUB B0,1,B0 +|| ZERO A0 +|| ADD $x1,$x1,$xib ; SHL $x1,1,$xib +|| SHL $x1,1,$xia +___ + +########____________________________ +# 0 D2. M1 M2 | +# 1 M1 | +# 2 M1 M2 | +# 3 D1. M1 M2 | +# 4 S1. L1 | +# 5 S2 S1x L1 D2 L2 |____________________________ +# 6/0 L1 S1 L2 S2x |D2. M1 M2 | +# 7/1 L1 S1 D1x S2 M2 | M1 | +# 8/2 S1 L1x S2 | M1 M2 | +# 9/3 S1 L1x | D1. M1 M2 | +# 10/4 D1x | S1. L1 | +# 11/5 |S2 S1x L1 D2 L2 |____________ +# 12/6/0 D1x __| L1 S1 L2 S2x |D2. .... +# 7/1 L1 S1 D1x S2 M2 | .... +# 8/2 S1 L1x S2 | .... +#####... ................|............ +$code.=<<___; + XORMPY $H0,$xia,$H0x ; 0 ; H·(Xi[i]<<1) +|| XORMPY $H01u,$xib,$H01y +|| [A0] LDBU *--${xip},$x0 + XORMPY $H1,$xia,$H1x ; 1 + XORMPY $H2,$xia,$H2x ; 2 +|| XORMPY $H2u,$xib,$H2y + XORMPY $H3,$xia,$H3x ; 3 +|| XORMPY $H3u,$xib,$H3y +||[!A0] MVK.D 15,A0 ; *--${xip} counter + XOR.L $H0x,$Z0,$Z0 ; 4 ; Z^=H·(Xi[i]<<1) +|| [A0] SUB.S A0,1,A0 + XOR.L $H1x,$Z1,$Z1 ; 5 +|| AND.D $H01y,$FF000000,$H0z +|| SWAP2.L $H01y,$H1y ; ; SHL $H01y,16,$H1y +|| SHL $x0,1,$xib +|| SHL $x0,1,$xia + + XOR.L $H2x,$Z2,$Z2 ; 6/0 ; [0,0] in epilogue +|| SHL $Z0,1,$rem ; ; rem=Z<<1 +|| SHRMB.S $Z1,$Z0,$Z0 ; ; Z>>=8 +|| AND.L $H1y,$FF000000,$H1z + XOR.L $H3x,$Z3,$Z3 ; 7/1 +|| SHRMB.S $Z2,$Z1,$Z1 +|| XOR.D $H0z,$Z0,$Z0 ; merge upper byte products +|| AND.S $H2y,$FF000000,$H2z +|| XORMPY $E10000,$rem,$res ; ; implicit rem&0x1FE + XOR.L $H1z,$Z1,$Z1 ; 8/2 +|| SHRMB.S $Z3,$Z2,$Z2 +|| AND.S $H3y,$FF000000,$H3z + XOR.L $H2z,$Z2,$Z2 ; 9/3 +|| SHRU $Z3,8,$Z3 + XOR.D $H3z,$Z3,$Z3 ; 10/4 + NOP ; 11/5 + + SPKERNEL 0,2 +|| XOR.D $res,$Z3,$Z3 ; 12/6/0; Z^=res + + ; input pre-fetch is possible where D1 slot is available... + [B0] LDNDW *${inp}[1],$H1x:$H0x ; 8/- + [B0] LDNDW *${inp}++[2],$H3x:$H2x ; 9/- + NOP ; 10/- + .if .LITTLE_ENDIAN + SWAP2 $Z0,$Z1 ; 11/- +|| SWAP4 $Z1,$Z0 + SWAP4 $Z1,$Z1 ; 12/- +|| SWAP2 $Z0,$Z0 + SWAP2 $Z2,$Z3 +|| SWAP4 $Z3,$Z2 +||[!B0] BNOP RA + SWAP4 $Z3,$Z3 +|| SWAP2 $Z2,$Z2 +|| [B0] BNOP ghash_loop? + [B0] XOR $H0x,$Z0,$Z0 ; Xi^=inp +|| [B0] XOR $H1x,$Z1,$Z1 + [B0] XOR $H2x,$Z2,$Z2 +|| [B0] XOR $H3x,$Z3,$Z3 +|| [B0] SHRU $Z1,24,$xia ; Xi[15], avoid cross-path stall + STDW $Z1:$Z0,*${xip}[1] +|| [B0] SHRU $Z1,16,$x0 ; Xi[14] +|| [B0] ZERO $Z1:$Z0 + .else + [!B0] BNOP RA ; 11/- + [B0] BNOP ghash_loop? ; 12/- + [B0] XOR $H0x,$Z0,$Z0 ; Xi^=inp +|| [B0] XOR $H1x,$Z1,$Z1 + [B0] XOR $H2x,$Z2,$Z2 +|| [B0] XOR $H3x,$Z3,$Z3 +|| [B0] MV $Z0,$xia ; Xi[15], avoid cross-path stall + STDW $Z1:$Z0,*${xip}[1] +|| [B0] SHRU $Z0,8,$x0 ; Xi[14] +|| [B0] ZERO $Z1:$Z0 + .endif + STDW $Z3:$Z2,*${xip}[0] +|| [B0] ZERO $Z3:$Z2 +|| [B0] MV $xia,$x1 + [B0] ADDK 14,${xip} + .endasmfunc + + .sect .const + .cstring "GHASH for C64x+, CRYPTOGAMS by " + .align 4 +___ + +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-ia64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-ia64.pl new file mode 100755 index 000000000..eb9ded91e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-ia64.pl @@ -0,0 +1,470 @@ +#! /usr/bin/env perl +# Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# March 2010 +# +# The module implements "4-bit" GCM GHASH function and underlying +# single multiplication operation in GF(2^128). "4-bit" means that it +# uses 256 bytes per-key table [+128 bytes shared table]. Streamed +# GHASH performance was measured to be 6.67 cycles per processed byte +# on Itanium 2, which is >90% better than Microsoft compiler generated +# code. To anchor to something else sha1-ia64.pl module processes one +# byte in 5.7 cycles. On Itanium GHASH should run at ~8.5 cycles per +# byte. + +# September 2010 +# +# It was originally thought that it makes lesser sense to implement +# "528B" variant on Itanium 2 for following reason. Because number of +# functional units is naturally limited, it appeared impossible to +# implement "528B" loop in 4 cycles, only in 5. This would mean that +# theoretically performance improvement couldn't be more than 20%. +# But occasionally you prove yourself wrong:-) I figured out a way to +# fold couple of instructions and having freed yet another instruction +# slot by unrolling the loop... Resulting performance is 4.45 cycles +# per processed byte and 50% better than "256B" version. On original +# Itanium performance should remain the same as the "256B" version, +# i.e. ~8.5 cycles. + +$output=pop and (open STDOUT,">$output" or die "can't open $output: $!"); + +if ($^O eq "hpux") { + $ADDP="addp4"; + for (@ARGV) { $ADDP="add" if (/[\+DD|\-mlp]64/); } +} else { $ADDP="add"; } +for (@ARGV) { $big_endian=1 if (/\-DB_ENDIAN/); + $big_endian=0 if (/\-DL_ENDIAN/); } +if (!defined($big_endian)) + { $big_endian=(unpack('L',pack('N',1))==1); } + +sub loop() { +my $label=shift; +my ($p16,$p17)=(shift)?("p63","p63"):("p16","p17"); # mask references to inp + +# Loop is scheduled for 6 ticks on Itanium 2 and 8 on Itanium, i.e. +# in scalable manner;-) Naturally assuming data in L1 cache... +# Special note about 'dep' instruction, which is used to construct +# &rem_4bit[Zlo&0xf]. It works, because rem_4bit is aligned at 128 +# bytes boundary and lower 7 bits of its address are guaranteed to +# be zero. +$code.=<<___; +$label: +{ .mfi; (p18) ld8 Hlo=[Hi[1]],-8 + (p19) dep rem=Zlo,rem_4bitp,3,4 } +{ .mfi; (p19) xor Zhi=Zhi,Hhi + ($p17) xor xi[1]=xi[1],in[1] };; +{ .mfi; (p18) ld8 Hhi=[Hi[1]] + (p19) shrp Zlo=Zhi,Zlo,4 } +{ .mfi; (p19) ld8 rem=[rem] + (p18) and Hi[1]=mask0xf0,xi[2] };; +{ .mmi; ($p16) ld1 in[0]=[inp],-1 + (p18) xor Zlo=Zlo,Hlo + (p19) shr.u Zhi=Zhi,4 } +{ .mib; (p19) xor Hhi=Hhi,rem + (p18) add Hi[1]=Htbl,Hi[1] };; + +{ .mfi; (p18) ld8 Hlo=[Hi[1]],-8 + (p18) dep rem=Zlo,rem_4bitp,3,4 } +{ .mfi; (p17) shladd Hi[0]=xi[1],4,r0 + (p18) xor Zhi=Zhi,Hhi };; +{ .mfi; (p18) ld8 Hhi=[Hi[1]] + (p18) shrp Zlo=Zhi,Zlo,4 } +{ .mfi; (p18) ld8 rem=[rem] + (p17) and Hi[0]=mask0xf0,Hi[0] };; +{ .mmi; (p16) ld1 xi[0]=[Xi],-1 + (p18) xor Zlo=Zlo,Hlo + (p18) shr.u Zhi=Zhi,4 } +{ .mib; (p18) xor Hhi=Hhi,rem + (p17) add Hi[0]=Htbl,Hi[0] + br.ctop.sptk $label };; +___ +} + +$code=<<___; +.explicit +.text + +prevfs=r2; prevlc=r3; prevpr=r8; +mask0xf0=r21; +rem=r22; rem_4bitp=r23; +Xi=r24; Htbl=r25; +inp=r26; end=r27; +Hhi=r28; Hlo=r29; +Zhi=r30; Zlo=r31; + +.align 128 +.skip 16 // aligns loop body +.global gcm_gmult_4bit# +.proc gcm_gmult_4bit# +gcm_gmult_4bit: + .prologue +{ .mmi; .save ar.pfs,prevfs + alloc prevfs=ar.pfs,2,6,0,8 + $ADDP Xi=15,in0 // &Xi[15] + mov rem_4bitp=ip } +{ .mii; $ADDP Htbl=8,in1 // &Htbl[0].lo + .save ar.lc,prevlc + mov prevlc=ar.lc + .save pr,prevpr + mov prevpr=pr };; + + .body + .rotr in[3],xi[3],Hi[2] + +{ .mib; ld1 xi[2]=[Xi],-1 // Xi[15] + mov mask0xf0=0xf0 + brp.loop.imp .Loop1,.Lend1-16};; +{ .mmi; ld1 xi[1]=[Xi],-1 // Xi[14] + };; +{ .mii; shladd Hi[1]=xi[2],4,r0 + mov pr.rot=0x7<<16 + mov ar.lc=13 };; +{ .mii; and Hi[1]=mask0xf0,Hi[1] + mov ar.ec=3 + xor Zlo=Zlo,Zlo };; +{ .mii; add Hi[1]=Htbl,Hi[1] // &Htbl[nlo].lo + add rem_4bitp=rem_4bit#-gcm_gmult_4bit#,rem_4bitp + xor Zhi=Zhi,Zhi };; +___ + &loop (".Loop1",1); +$code.=<<___; +.Lend1: +{ .mib; xor Zhi=Zhi,Hhi };; // modulo-scheduling artefact +{ .mib; mux1 Zlo=Zlo,\@rev };; +{ .mib; mux1 Zhi=Zhi,\@rev };; +{ .mmi; add Hlo=9,Xi;; // ;; is here to prevent + add Hhi=1,Xi };; // pipeline flush on Itanium +{ .mib; st8 [Hlo]=Zlo + mov pr=prevpr,0x1ffff };; +{ .mib; st8 [Hhi]=Zhi + mov ar.lc=prevlc + br.ret.sptk.many b0 };; +.endp gcm_gmult_4bit# +___ + +###################################################################### +# "528B" (well, "512B" actually) streamed GHASH +# +$Xip="in0"; +$Htbl="in1"; +$inp="in2"; +$len="in3"; +$rem_8bit="loc0"; +$mask0xff="loc1"; +($sum,$rum) = $big_endian ? ("nop.m","nop.m") : ("sum","rum"); + +sub load_htable() { + for (my $i=0;$i<8;$i++) { + $code.=<<___; +{ .mmi; ld8 r`16+2*$i+1`=[r8],16 // Htable[$i].hi + ld8 r`16+2*$i`=[r9],16 } // Htable[$i].lo +{ .mmi; ldf8 f`32+2*$i+1`=[r10],16 // Htable[`8+$i`].hi + ldf8 f`32+2*$i`=[r11],16 // Htable[`8+$i`].lo +___ + $code.=shift if (($i+$#_)==7); + $code.="\t};;\n" + } +} + +$code.=<<___; +prevsp=r3; + +.align 32 +.skip 16 // aligns loop body +.global gcm_ghash_4bit# +.proc gcm_ghash_4bit# +gcm_ghash_4bit: + .prologue +{ .mmi; .save ar.pfs,prevfs + alloc prevfs=ar.pfs,4,2,0,0 + .vframe prevsp + mov prevsp=sp + mov $rem_8bit=ip };; + .body +{ .mfi; $ADDP r8=0+0,$Htbl + $ADDP r9=0+8,$Htbl } +{ .mfi; $ADDP r10=128+0,$Htbl + $ADDP r11=128+8,$Htbl };; +___ + &load_htable( + " $ADDP $Xip=15,$Xip", # &Xi[15] + " $ADDP $len=$len,$inp", # &inp[len] + " $ADDP $inp=15,$inp", # &inp[15] + " mov $mask0xff=0xff", + " add sp=-512,sp", + " andcm sp=sp,$mask0xff", # align stack frame + " add r14=0,sp", + " add r15=8,sp"); +$code.=<<___; +{ .mmi; $sum 1<<1 // go big-endian + add r8=256+0,sp + add r9=256+8,sp } +{ .mmi; add r10=256+128+0,sp + add r11=256+128+8,sp + add $len=-17,$len };; +___ +for($i=0;$i<8;$i++) { # generate first half of Hshr4[] +my ($rlo,$rhi)=("r".eval(16+2*$i),"r".eval(16+2*$i+1)); +$code.=<<___; +{ .mmi; st8 [r8]=$rlo,16 // Htable[$i].lo + st8 [r9]=$rhi,16 // Htable[$i].hi + shrp $rlo=$rhi,$rlo,4 }//;; +{ .mmi; stf8 [r10]=f`32+2*$i`,16 // Htable[`8+$i`].lo + stf8 [r11]=f`32+2*$i+1`,16 // Htable[`8+$i`].hi + shr.u $rhi=$rhi,4 };; +{ .mmi; st8 [r14]=$rlo,16 // Htable[$i].lo>>4 + st8 [r15]=$rhi,16 }//;; // Htable[$i].hi>>4 +___ +} +$code.=<<___; +{ .mmi; ld8 r16=[r8],16 // Htable[8].lo + ld8 r17=[r9],16 };; // Htable[8].hi +{ .mmi; ld8 r18=[r8],16 // Htable[9].lo + ld8 r19=[r9],16 } // Htable[9].hi +{ .mmi; rum 1<<5 // clear um.mfh + shrp r16=r17,r16,4 };; +___ +for($i=0;$i<6;$i++) { # generate second half of Hshr4[] +$code.=<<___; +{ .mmi; ld8 r`20+2*$i`=[r8],16 // Htable[`10+$i`].lo + ld8 r`20+2*$i+1`=[r9],16 // Htable[`10+$i`].hi + shr.u r`16+2*$i+1`=r`16+2*$i+1`,4 };; +{ .mmi; st8 [r14]=r`16+2*$i`,16 // Htable[`8+$i`].lo>>4 + st8 [r15]=r`16+2*$i+1`,16 // Htable[`8+$i`].hi>>4 + shrp r`18+2*$i`=r`18+2*$i+1`,r`18+2*$i`,4 } +___ +} +$code.=<<___; +{ .mmi; shr.u r`16+2*$i+1`=r`16+2*$i+1`,4 };; +{ .mmi; st8 [r14]=r`16+2*$i`,16 // Htable[`8+$i`].lo>>4 + st8 [r15]=r`16+2*$i+1`,16 // Htable[`8+$i`].hi>>4 + shrp r`18+2*$i`=r`18+2*$i+1`,r`18+2*$i`,4 } +{ .mmi; add $Htbl=256,sp // &Htable[0] + add $rem_8bit=rem_8bit#-gcm_ghash_4bit#,$rem_8bit + shr.u r`18+2*$i+1`=r`18+2*$i+1`,4 };; +{ .mmi; st8 [r14]=r`18+2*$i` // Htable[`8+$i`].lo>>4 + st8 [r15]=r`18+2*$i+1` } // Htable[`8+$i`].hi>>4 +___ + +$in="r15"; +@xi=("r16","r17"); +@rem=("r18","r19"); +($Alo,$Ahi,$Blo,$Bhi,$Zlo,$Zhi)=("r20","r21","r22","r23","r24","r25"); +($Atbl,$Btbl)=("r26","r27"); + +$code.=<<___; # (p16) +{ .mmi; ld1 $in=[$inp],-1 //(p16) *inp-- + ld1 $xi[0]=[$Xip],-1 //(p16) *Xi-- + cmp.eq p0,p6=r0,r0 };; // clear p6 +___ +push (@xi,shift(@xi)); push (@rem,shift(@rem)); # "rotate" registers + +$code.=<<___; # (p16),(p17) +{ .mmi; ld1 $xi[0]=[$Xip],-1 //(p16) *Xi-- + xor $xi[1]=$xi[1],$in };; //(p17) xi=$xi[i]^inp[i] +{ .mii; ld1 $in=[$inp],-1 //(p16) *inp-- + dep $Atbl=$xi[1],$Htbl,4,4 //(p17) &Htable[nlo].lo + and $xi[1]=-16,$xi[1] };; //(p17) nhi=xi&0xf0 +.align 32 +.LOOP: +{ .mmi; +(p6) st8 [$Xip]=$Zhi,13 + xor $Zlo=$Zlo,$Zlo + add $Btbl=$xi[1],$Htbl };; //(p17) &Htable[nhi].lo +___ +push (@xi,shift(@xi)); push (@rem,shift(@rem)); # "rotate" registers + +$code.=<<___; # (p16),(p17),(p18) +{ .mmi; ld8 $Alo=[$Atbl],8 //(p18) Htable[nlo].lo,&Htable[nlo].hi + ld8 $rem[0]=[$Btbl],-256 //(p18) Htable[nhi].lo,&Hshr4[nhi].lo + xor $xi[1]=$xi[1],$in };; //(p17) xi=$xi[i]^inp[i] +{ .mfi; ld8 $Ahi=[$Atbl] //(p18) Htable[nlo].hi + dep $Atbl=$xi[1],$Htbl,4,4 } //(p17) &Htable[nlo].lo +{ .mfi; shladd $rem[0]=$rem[0],4,r0 //(p18) Htable[nhi].lo<<4 + xor $Zlo=$Zlo,$Alo };; //(p18) Z.lo^=Htable[nlo].lo +{ .mmi; ld8 $Blo=[$Btbl],8 //(p18) Hshr4[nhi].lo,&Hshr4[nhi].hi + ld1 $in=[$inp],-1 } //(p16) *inp-- +{ .mmi; xor $rem[0]=$rem[0],$Zlo //(p18) Z.lo^(Htable[nhi].lo<<4) + mov $Zhi=$Ahi //(p18) Z.hi^=Htable[nlo].hi + and $xi[1]=-16,$xi[1] };; //(p17) nhi=xi&0xf0 +{ .mmi; ld8 $Bhi=[$Btbl] //(p18) Hshr4[nhi].hi + ld1 $xi[0]=[$Xip],-1 //(p16) *Xi-- + shrp $Zlo=$Zhi,$Zlo,8 } //(p18) Z.lo=(Z.hi<<56)|(Z.lo>>8) +{ .mmi; and $rem[0]=$rem[0],$mask0xff //(p18) rem=($Zlo^(Htable[nhi].lo<<4))&0xff + add $Btbl=$xi[1],$Htbl };; //(p17) &Htable[nhi] +___ +push (@xi,shift(@xi)); push (@rem,shift(@rem)); # "rotate" registers + +for ($i=1;$i<14;$i++) { +# Above and below fragments are derived from this one by removing +# unsuitable (p??) instructions. +$code.=<<___; # (p16),(p17),(p18),(p19) +{ .mmi; ld8 $Alo=[$Atbl],8 //(p18) Htable[nlo].lo,&Htable[nlo].hi + ld8 $rem[0]=[$Btbl],-256 //(p18) Htable[nhi].lo,&Hshr4[nhi].lo + shr.u $Zhi=$Zhi,8 } //(p19) Z.hi>>=8 +{ .mmi; shladd $rem[1]=$rem[1],1,$rem_8bit //(p19) &rem_8bit[rem] + xor $Zlo=$Zlo,$Blo //(p19) Z.lo^=Hshr4[nhi].lo + xor $xi[1]=$xi[1],$in };; //(p17) xi=$xi[i]^inp[i] +{ .mmi; ld8 $Ahi=[$Atbl] //(p18) Htable[nlo].hi + ld2 $rem[1]=[$rem[1]] //(p19) rem_8bit[rem] + dep $Atbl=$xi[1],$Htbl,4,4 } //(p17) &Htable[nlo].lo +{ .mmi; shladd $rem[0]=$rem[0],4,r0 //(p18) Htable[nhi].lo<<4 + xor $Zlo=$Zlo,$Alo //(p18) Z.lo^=Htable[nlo].lo + xor $Zhi=$Zhi,$Bhi };; //(p19) Z.hi^=Hshr4[nhi].hi +{ .mmi; ld8 $Blo=[$Btbl],8 //(p18) Hshr4[nhi].lo,&Hshr4[nhi].hi + ld1 $in=[$inp],-1 //(p16) *inp-- + shl $rem[1]=$rem[1],48 } //(p19) rem_8bit[rem]<<48 +{ .mmi; xor $rem[0]=$rem[0],$Zlo //(p18) Z.lo^(Htable[nhi].lo<<4) + xor $Zhi=$Zhi,$Ahi //(p18) Z.hi^=Htable[nlo].hi + and $xi[1]=-16,$xi[1] };; //(p17) nhi=xi&0xf0 +{ .mmi; ld8 $Bhi=[$Btbl] //(p18) Hshr4[nhi].hi + ld1 $xi[0]=[$Xip],-1 //(p16) *Xi-- + shrp $Zlo=$Zhi,$Zlo,8 } //(p18) Z.lo=(Z.hi<<56)|(Z.lo>>8) +{ .mmi; and $rem[0]=$rem[0],$mask0xff //(p18) rem=($Zlo^(Htable[nhi].lo<<4))&0xff + xor $Zhi=$Zhi,$rem[1] //(p19) Z.hi^=rem_8bit[rem]<<48 + add $Btbl=$xi[1],$Htbl };; //(p17) &Htable[nhi] +___ +push (@xi,shift(@xi)); push (@rem,shift(@rem)); # "rotate" registers +} + +$code.=<<___; # (p17),(p18),(p19) +{ .mmi; ld8 $Alo=[$Atbl],8 //(p18) Htable[nlo].lo,&Htable[nlo].hi + ld8 $rem[0]=[$Btbl],-256 //(p18) Htable[nhi].lo,&Hshr4[nhi].lo + shr.u $Zhi=$Zhi,8 } //(p19) Z.hi>>=8 +{ .mmi; shladd $rem[1]=$rem[1],1,$rem_8bit //(p19) &rem_8bit[rem] + xor $Zlo=$Zlo,$Blo //(p19) Z.lo^=Hshr4[nhi].lo + xor $xi[1]=$xi[1],$in };; //(p17) xi=$xi[i]^inp[i] +{ .mmi; ld8 $Ahi=[$Atbl] //(p18) Htable[nlo].hi + ld2 $rem[1]=[$rem[1]] //(p19) rem_8bit[rem] + dep $Atbl=$xi[1],$Htbl,4,4 };; //(p17) &Htable[nlo].lo +{ .mmi; shladd $rem[0]=$rem[0],4,r0 //(p18) Htable[nhi].lo<<4 + xor $Zlo=$Zlo,$Alo //(p18) Z.lo^=Htable[nlo].lo + xor $Zhi=$Zhi,$Bhi };; //(p19) Z.hi^=Hshr4[nhi].hi +{ .mmi; ld8 $Blo=[$Btbl],8 //(p18) Hshr4[nhi].lo,&Hshr4[nhi].hi + shl $rem[1]=$rem[1],48 } //(p19) rem_8bit[rem]<<48 +{ .mmi; xor $rem[0]=$rem[0],$Zlo //(p18) Z.lo^(Htable[nhi].lo<<4) + xor $Zhi=$Zhi,$Ahi //(p18) Z.hi^=Htable[nlo].hi + and $xi[1]=-16,$xi[1] };; //(p17) nhi=xi&0xf0 +{ .mmi; ld8 $Bhi=[$Btbl] //(p18) Hshr4[nhi].hi + shrp $Zlo=$Zhi,$Zlo,8 } //(p18) Z.lo=(Z.hi<<56)|(Z.lo>>8) +{ .mmi; and $rem[0]=$rem[0],$mask0xff //(p18) rem=($Zlo^(Htable[nhi].lo<<4))&0xff + xor $Zhi=$Zhi,$rem[1] //(p19) Z.hi^=rem_8bit[rem]<<48 + add $Btbl=$xi[1],$Htbl };; //(p17) &Htable[nhi] +___ +push (@xi,shift(@xi)); push (@rem,shift(@rem)); # "rotate" registers + +$code.=<<___; # (p18),(p19) +{ .mfi; ld8 $Alo=[$Atbl],8 //(p18) Htable[nlo].lo,&Htable[nlo].hi + shr.u $Zhi=$Zhi,8 } //(p19) Z.hi>>=8 +{ .mfi; shladd $rem[1]=$rem[1],1,$rem_8bit //(p19) &rem_8bit[rem] + xor $Zlo=$Zlo,$Blo };; //(p19) Z.lo^=Hshr4[nhi].lo +{ .mfi; ld8 $Ahi=[$Atbl] //(p18) Htable[nlo].hi + xor $Zlo=$Zlo,$Alo } //(p18) Z.lo^=Htable[nlo].lo +{ .mfi; ld2 $rem[1]=[$rem[1]] //(p19) rem_8bit[rem] + xor $Zhi=$Zhi,$Bhi };; //(p19) Z.hi^=Hshr4[nhi].hi +{ .mfi; ld8 $Blo=[$Btbl],8 //(p18) Htable[nhi].lo,&Htable[nhi].hi + shl $rem[1]=$rem[1],48 } //(p19) rem_8bit[rem]<<48 +{ .mfi; shladd $rem[0]=$Zlo,4,r0 //(p18) Z.lo<<4 + xor $Zhi=$Zhi,$Ahi };; //(p18) Z.hi^=Htable[nlo].hi +{ .mfi; ld8 $Bhi=[$Btbl] //(p18) Htable[nhi].hi + shrp $Zlo=$Zhi,$Zlo,4 } //(p18) Z.lo=(Z.hi<<60)|(Z.lo>>4) +{ .mfi; and $rem[0]=$rem[0],$mask0xff //(p18) rem=($Zlo^(Htable[nhi].lo<<4))&0xff + xor $Zhi=$Zhi,$rem[1] };; //(p19) Z.hi^=rem_8bit[rem]<<48 +___ +push (@xi,shift(@xi)); push (@rem,shift(@rem)); # "rotate" registers + +$code.=<<___; # (p19) +{ .mmi; cmp.ltu p6,p0=$inp,$len + add $inp=32,$inp + shr.u $Zhi=$Zhi,4 } //(p19) Z.hi>>=4 +{ .mmi; shladd $rem[1]=$rem[1],1,$rem_8bit //(p19) &rem_8bit[rem] + xor $Zlo=$Zlo,$Blo //(p19) Z.lo^=Hshr4[nhi].lo + add $Xip=9,$Xip };; // &Xi.lo +{ .mmi; ld2 $rem[1]=[$rem[1]] //(p19) rem_8bit[rem] +(p6) ld1 $in=[$inp],-1 //[p16] *inp-- +(p6) extr.u $xi[1]=$Zlo,8,8 } //[p17] Xi[14] +{ .mmi; xor $Zhi=$Zhi,$Bhi //(p19) Z.hi^=Hshr4[nhi].hi +(p6) and $xi[0]=$Zlo,$mask0xff };; //[p16] Xi[15] +{ .mmi; st8 [$Xip]=$Zlo,-8 +(p6) xor $xi[0]=$xi[0],$in //[p17] xi=$xi[i]^inp[i] + shl $rem[1]=$rem[1],48 };; //(p19) rem_8bit[rem]<<48 +{ .mmi; +(p6) ld1 $in=[$inp],-1 //[p16] *inp-- + xor $Zhi=$Zhi,$rem[1] //(p19) Z.hi^=rem_8bit[rem]<<48 +(p6) dep $Atbl=$xi[0],$Htbl,4,4 } //[p17] &Htable[nlo].lo +{ .mib; +(p6) and $xi[0]=-16,$xi[0] //[p17] nhi=xi&0xf0 +(p6) br.cond.dptk.many .LOOP };; + +{ .mib; st8 [$Xip]=$Zhi };; +{ .mib; $rum 1<<1 // return to little-endian + .restore sp + mov sp=prevsp + br.ret.sptk.many b0 };; +.endp gcm_ghash_4bit# +___ +$code.=<<___; +.align 128 +.type rem_4bit#,\@object +rem_4bit: + data8 0x0000<<48, 0x1C20<<48, 0x3840<<48, 0x2460<<48 + data8 0x7080<<48, 0x6CA0<<48, 0x48C0<<48, 0x54E0<<48 + data8 0xE100<<48, 0xFD20<<48, 0xD940<<48, 0xC560<<48 + data8 0x9180<<48, 0x8DA0<<48, 0xA9C0<<48, 0xB5E0<<48 +.size rem_4bit#,128 +.type rem_8bit#,\@object +rem_8bit: + data1 0x00,0x00, 0x01,0xC2, 0x03,0x84, 0x02,0x46, 0x07,0x08, 0x06,0xCA, 0x04,0x8C, 0x05,0x4E + data1 0x0E,0x10, 0x0F,0xD2, 0x0D,0x94, 0x0C,0x56, 0x09,0x18, 0x08,0xDA, 0x0A,0x9C, 0x0B,0x5E + data1 0x1C,0x20, 0x1D,0xE2, 0x1F,0xA4, 0x1E,0x66, 0x1B,0x28, 0x1A,0xEA, 0x18,0xAC, 0x19,0x6E + data1 0x12,0x30, 0x13,0xF2, 0x11,0xB4, 0x10,0x76, 0x15,0x38, 0x14,0xFA, 0x16,0xBC, 0x17,0x7E + data1 0x38,0x40, 0x39,0x82, 0x3B,0xC4, 0x3A,0x06, 0x3F,0x48, 0x3E,0x8A, 0x3C,0xCC, 0x3D,0x0E + data1 0x36,0x50, 0x37,0x92, 0x35,0xD4, 0x34,0x16, 0x31,0x58, 0x30,0x9A, 0x32,0xDC, 0x33,0x1E + data1 0x24,0x60, 0x25,0xA2, 0x27,0xE4, 0x26,0x26, 0x23,0x68, 0x22,0xAA, 0x20,0xEC, 0x21,0x2E + data1 0x2A,0x70, 0x2B,0xB2, 0x29,0xF4, 0x28,0x36, 0x2D,0x78, 0x2C,0xBA, 0x2E,0xFC, 0x2F,0x3E + data1 0x70,0x80, 0x71,0x42, 0x73,0x04, 0x72,0xC6, 0x77,0x88, 0x76,0x4A, 0x74,0x0C, 0x75,0xCE + data1 0x7E,0x90, 0x7F,0x52, 0x7D,0x14, 0x7C,0xD6, 0x79,0x98, 0x78,0x5A, 0x7A,0x1C, 0x7B,0xDE + data1 0x6C,0xA0, 0x6D,0x62, 0x6F,0x24, 0x6E,0xE6, 0x6B,0xA8, 0x6A,0x6A, 0x68,0x2C, 0x69,0xEE + data1 0x62,0xB0, 0x63,0x72, 0x61,0x34, 0x60,0xF6, 0x65,0xB8, 0x64,0x7A, 0x66,0x3C, 0x67,0xFE + data1 0x48,0xC0, 0x49,0x02, 0x4B,0x44, 0x4A,0x86, 0x4F,0xC8, 0x4E,0x0A, 0x4C,0x4C, 0x4D,0x8E + data1 0x46,0xD0, 0x47,0x12, 0x45,0x54, 0x44,0x96, 0x41,0xD8, 0x40,0x1A, 0x42,0x5C, 0x43,0x9E + data1 0x54,0xE0, 0x55,0x22, 0x57,0x64, 0x56,0xA6, 0x53,0xE8, 0x52,0x2A, 0x50,0x6C, 0x51,0xAE + data1 0x5A,0xF0, 0x5B,0x32, 0x59,0x74, 0x58,0xB6, 0x5D,0xF8, 0x5C,0x3A, 0x5E,0x7C, 0x5F,0xBE + data1 0xE1,0x00, 0xE0,0xC2, 0xE2,0x84, 0xE3,0x46, 0xE6,0x08, 0xE7,0xCA, 0xE5,0x8C, 0xE4,0x4E + data1 0xEF,0x10, 0xEE,0xD2, 0xEC,0x94, 0xED,0x56, 0xE8,0x18, 0xE9,0xDA, 0xEB,0x9C, 0xEA,0x5E + data1 0xFD,0x20, 0xFC,0xE2, 0xFE,0xA4, 0xFF,0x66, 0xFA,0x28, 0xFB,0xEA, 0xF9,0xAC, 0xF8,0x6E + data1 0xF3,0x30, 0xF2,0xF2, 0xF0,0xB4, 0xF1,0x76, 0xF4,0x38, 0xF5,0xFA, 0xF7,0xBC, 0xF6,0x7E + data1 0xD9,0x40, 0xD8,0x82, 0xDA,0xC4, 0xDB,0x06, 0xDE,0x48, 0xDF,0x8A, 0xDD,0xCC, 0xDC,0x0E + data1 0xD7,0x50, 0xD6,0x92, 0xD4,0xD4, 0xD5,0x16, 0xD0,0x58, 0xD1,0x9A, 0xD3,0xDC, 0xD2,0x1E + data1 0xC5,0x60, 0xC4,0xA2, 0xC6,0xE4, 0xC7,0x26, 0xC2,0x68, 0xC3,0xAA, 0xC1,0xEC, 0xC0,0x2E + data1 0xCB,0x70, 0xCA,0xB2, 0xC8,0xF4, 0xC9,0x36, 0xCC,0x78, 0xCD,0xBA, 0xCF,0xFC, 0xCE,0x3E + data1 0x91,0x80, 0x90,0x42, 0x92,0x04, 0x93,0xC6, 0x96,0x88, 0x97,0x4A, 0x95,0x0C, 0x94,0xCE + data1 0x9F,0x90, 0x9E,0x52, 0x9C,0x14, 0x9D,0xD6, 0x98,0x98, 0x99,0x5A, 0x9B,0x1C, 0x9A,0xDE + data1 0x8D,0xA0, 0x8C,0x62, 0x8E,0x24, 0x8F,0xE6, 0x8A,0xA8, 0x8B,0x6A, 0x89,0x2C, 0x88,0xEE + data1 0x83,0xB0, 0x82,0x72, 0x80,0x34, 0x81,0xF6, 0x84,0xB8, 0x85,0x7A, 0x87,0x3C, 0x86,0xFE + data1 0xA9,0xC0, 0xA8,0x02, 0xAA,0x44, 0xAB,0x86, 0xAE,0xC8, 0xAF,0x0A, 0xAD,0x4C, 0xAC,0x8E + data1 0xA7,0xD0, 0xA6,0x12, 0xA4,0x54, 0xA5,0x96, 0xA0,0xD8, 0xA1,0x1A, 0xA3,0x5C, 0xA2,0x9E + data1 0xB5,0xE0, 0xB4,0x22, 0xB6,0x64, 0xB7,0xA6, 0xB2,0xE8, 0xB3,0x2A, 0xB1,0x6C, 0xB0,0xAE + data1 0xBB,0xF0, 0xBA,0x32, 0xB8,0x74, 0xB9,0xB6, 0xBC,0xF8, 0xBD,0x3A, 0xBF,0x7C, 0xBE,0xBE +.size rem_8bit#,512 +stringz "GHASH for IA64, CRYPTOGAMS by " +___ + +$code =~ s/mux1(\s+)\S+\@rev/nop.i$1 0x0/gm if ($big_endian); +$code =~ s/\`([^\`]*)\`/eval $1/gem; + +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-parisc.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-parisc.pl new file mode 100644 index 000000000..a614c99c2 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-parisc.pl @@ -0,0 +1,748 @@ +#! /usr/bin/env perl +# Copyright 2010-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# April 2010 +# +# The module implements "4-bit" GCM GHASH function and underlying +# single multiplication operation in GF(2^128). "4-bit" means that it +# uses 256 bytes per-key table [+128 bytes shared table]. On PA-7100LC +# it processes one byte in 19.6 cycles, which is more than twice as +# fast as code generated by gcc 3.2. PA-RISC 2.0 loop is scheduled for +# 8 cycles, but measured performance on PA-8600 system is ~9 cycles per +# processed byte. This is ~2.2x faster than 64-bit code generated by +# vendor compiler (which used to be very hard to beat:-). +# +# Special thanks to polarhome.com for providing HP-UX account. + +$flavour = shift; +$output = shift; +open STDOUT,">$output"; + +if ($flavour =~ /64/) { + $LEVEL ="2.0W"; + $SIZE_T =8; + $FRAME_MARKER =80; + $SAVED_RP =16; + $PUSH ="std"; + $PUSHMA ="std,ma"; + $POP ="ldd"; + $POPMB ="ldd,mb"; + $NREGS =6; +} else { + $LEVEL ="1.0"; #"\n\t.ALLOW\t2.0"; + $SIZE_T =4; + $FRAME_MARKER =48; + $SAVED_RP =20; + $PUSH ="stw"; + $PUSHMA ="stwm"; + $POP ="ldw"; + $POPMB ="ldwm"; + $NREGS =11; +} + +$FRAME=10*$SIZE_T+$FRAME_MARKER;# NREGS saved regs + frame marker + # [+ argument transfer] + +################# volatile registers +$Xi="%r26"; # argument block +$Htbl="%r25"; +$inp="%r24"; +$len="%r23"; +$Hhh=$Htbl; # variables +$Hll="%r22"; +$Zhh="%r21"; +$Zll="%r20"; +$cnt="%r19"; +$rem_4bit="%r28"; +$rem="%r29"; +$mask0xf0="%r31"; + +################# preserved registers +$Thh="%r1"; +$Tll="%r2"; +$nlo="%r3"; +$nhi="%r4"; +$byte="%r5"; +if ($SIZE_T==4) { + $Zhl="%r6"; + $Zlh="%r7"; + $Hhl="%r8"; + $Hlh="%r9"; + $Thl="%r10"; + $Tlh="%r11"; +} +$rem2="%r6"; # used in PA-RISC 2.0 code + +$code.=<<___; + .LEVEL $LEVEL + .SPACE \$TEXT\$ + .SUBSPA \$CODE\$,QUAD=0,ALIGN=8,ACCESS=0x2C,CODE_ONLY + + .EXPORT gcm_gmult_4bit,ENTRY,ARGW0=GR,ARGW1=GR + .ALIGN 64 +gcm_gmult_4bit + .PROC + .CALLINFO FRAME=`$FRAME-10*$SIZE_T`,NO_CALLS,SAVE_RP,ENTRY_GR=$NREGS + .ENTRY + $PUSH %r2,-$SAVED_RP(%sp) ; standard prologue + $PUSHMA %r3,$FRAME(%sp) + $PUSH %r4,`-$FRAME+1*$SIZE_T`(%sp) + $PUSH %r5,`-$FRAME+2*$SIZE_T`(%sp) + $PUSH %r6,`-$FRAME+3*$SIZE_T`(%sp) +___ +$code.=<<___ if ($SIZE_T==4); + $PUSH %r7,`-$FRAME+4*$SIZE_T`(%sp) + $PUSH %r8,`-$FRAME+5*$SIZE_T`(%sp) + $PUSH %r9,`-$FRAME+6*$SIZE_T`(%sp) + $PUSH %r10,`-$FRAME+7*$SIZE_T`(%sp) + $PUSH %r11,`-$FRAME+8*$SIZE_T`(%sp) +___ +$code.=<<___; + blr %r0,$rem_4bit + ldi 3,$rem +L\$pic_gmult + andcm $rem_4bit,$rem,$rem_4bit + addl $inp,$len,$len + ldo L\$rem_4bit-L\$pic_gmult($rem_4bit),$rem_4bit + ldi 0xf0,$mask0xf0 +___ +$code.=<<___ if ($SIZE_T==4); + ldi 31,$rem + mtctl $rem,%cr11 + extrd,u,*= $rem,%sar,1,$rem ; executes on PA-RISC 1.0 + b L\$parisc1_gmult + nop +___ + +$code.=<<___; + ldb 15($Xi),$nlo + ldo 8($Htbl),$Hll + + and $mask0xf0,$nlo,$nhi + depd,z $nlo,59,4,$nlo + + ldd $nlo($Hll),$Zll + ldd $nlo($Hhh),$Zhh + + depd,z $Zll,60,4,$rem + shrpd $Zhh,$Zll,4,$Zll + extrd,u $Zhh,59,60,$Zhh + ldb 14($Xi),$nlo + + ldd $nhi($Hll),$Tll + ldd $nhi($Hhh),$Thh + and $mask0xf0,$nlo,$nhi + depd,z $nlo,59,4,$nlo + + xor $Tll,$Zll,$Zll + xor $Thh,$Zhh,$Zhh + ldd $rem($rem_4bit),$rem + b L\$oop_gmult_pa2 + ldi 13,$cnt + + .ALIGN 8 +L\$oop_gmult_pa2 + xor $rem,$Zhh,$Zhh ; moved here to work around gas bug + depd,z $Zll,60,4,$rem + + shrpd $Zhh,$Zll,4,$Zll + extrd,u $Zhh,59,60,$Zhh + ldd $nlo($Hll),$Tll + ldd $nlo($Hhh),$Thh + + xor $Tll,$Zll,$Zll + xor $Thh,$Zhh,$Zhh + ldd $rem($rem_4bit),$rem + + xor $rem,$Zhh,$Zhh + depd,z $Zll,60,4,$rem + ldbx $cnt($Xi),$nlo + + shrpd $Zhh,$Zll,4,$Zll + extrd,u $Zhh,59,60,$Zhh + ldd $nhi($Hll),$Tll + ldd $nhi($Hhh),$Thh + + and $mask0xf0,$nlo,$nhi + depd,z $nlo,59,4,$nlo + ldd $rem($rem_4bit),$rem + + xor $Tll,$Zll,$Zll + addib,uv -1,$cnt,L\$oop_gmult_pa2 + xor $Thh,$Zhh,$Zhh + + xor $rem,$Zhh,$Zhh + depd,z $Zll,60,4,$rem + + shrpd $Zhh,$Zll,4,$Zll + extrd,u $Zhh,59,60,$Zhh + ldd $nlo($Hll),$Tll + ldd $nlo($Hhh),$Thh + + xor $Tll,$Zll,$Zll + xor $Thh,$Zhh,$Zhh + ldd $rem($rem_4bit),$rem + + xor $rem,$Zhh,$Zhh + depd,z $Zll,60,4,$rem + + shrpd $Zhh,$Zll,4,$Zll + extrd,u $Zhh,59,60,$Zhh + ldd $nhi($Hll),$Tll + ldd $nhi($Hhh),$Thh + + xor $Tll,$Zll,$Zll + xor $Thh,$Zhh,$Zhh + ldd $rem($rem_4bit),$rem + + xor $rem,$Zhh,$Zhh + std $Zll,8($Xi) + std $Zhh,0($Xi) +___ + +$code.=<<___ if ($SIZE_T==4); + b L\$done_gmult + nop + +L\$parisc1_gmult + ldb 15($Xi),$nlo + ldo 12($Htbl),$Hll + ldo 8($Htbl),$Hlh + ldo 4($Htbl),$Hhl + + and $mask0xf0,$nlo,$nhi + zdep $nlo,27,4,$nlo + + ldwx $nlo($Hll),$Zll + ldwx $nlo($Hlh),$Zlh + ldwx $nlo($Hhl),$Zhl + ldwx $nlo($Hhh),$Zhh + zdep $Zll,28,4,$rem + ldb 14($Xi),$nlo + ldwx $rem($rem_4bit),$rem + shrpw $Zlh,$Zll,4,$Zll + ldwx $nhi($Hll),$Tll + shrpw $Zhl,$Zlh,4,$Zlh + ldwx $nhi($Hlh),$Tlh + shrpw $Zhh,$Zhl,4,$Zhl + ldwx $nhi($Hhl),$Thl + extru $Zhh,27,28,$Zhh + ldwx $nhi($Hhh),$Thh + xor $rem,$Zhh,$Zhh + and $mask0xf0,$nlo,$nhi + zdep $nlo,27,4,$nlo + + xor $Tll,$Zll,$Zll + ldwx $nlo($Hll),$Tll + xor $Tlh,$Zlh,$Zlh + ldwx $nlo($Hlh),$Tlh + xor $Thl,$Zhl,$Zhl + b L\$oop_gmult_pa1 + ldi 13,$cnt + + .ALIGN 8 +L\$oop_gmult_pa1 + zdep $Zll,28,4,$rem + ldwx $nlo($Hhl),$Thl + xor $Thh,$Zhh,$Zhh + ldwx $rem($rem_4bit),$rem + shrpw $Zlh,$Zll,4,$Zll + ldwx $nlo($Hhh),$Thh + shrpw $Zhl,$Zlh,4,$Zlh + ldbx $cnt($Xi),$nlo + xor $Tll,$Zll,$Zll + ldwx $nhi($Hll),$Tll + shrpw $Zhh,$Zhl,4,$Zhl + xor $Tlh,$Zlh,$Zlh + ldwx $nhi($Hlh),$Tlh + extru $Zhh,27,28,$Zhh + xor $Thl,$Zhl,$Zhl + ldwx $nhi($Hhl),$Thl + xor $rem,$Zhh,$Zhh + zdep $Zll,28,4,$rem + xor $Thh,$Zhh,$Zhh + ldwx $nhi($Hhh),$Thh + shrpw $Zlh,$Zll,4,$Zll + ldwx $rem($rem_4bit),$rem + shrpw $Zhl,$Zlh,4,$Zlh + shrpw $Zhh,$Zhl,4,$Zhl + and $mask0xf0,$nlo,$nhi + extru $Zhh,27,28,$Zhh + zdep $nlo,27,4,$nlo + xor $Tll,$Zll,$Zll + ldwx $nlo($Hll),$Tll + xor $Tlh,$Zlh,$Zlh + ldwx $nlo($Hlh),$Tlh + xor $rem,$Zhh,$Zhh + addib,uv -1,$cnt,L\$oop_gmult_pa1 + xor $Thl,$Zhl,$Zhl + + zdep $Zll,28,4,$rem + ldwx $nlo($Hhl),$Thl + xor $Thh,$Zhh,$Zhh + ldwx $rem($rem_4bit),$rem + shrpw $Zlh,$Zll,4,$Zll + ldwx $nlo($Hhh),$Thh + shrpw $Zhl,$Zlh,4,$Zlh + xor $Tll,$Zll,$Zll + ldwx $nhi($Hll),$Tll + shrpw $Zhh,$Zhl,4,$Zhl + xor $Tlh,$Zlh,$Zlh + ldwx $nhi($Hlh),$Tlh + extru $Zhh,27,28,$Zhh + xor $rem,$Zhh,$Zhh + xor $Thl,$Zhl,$Zhl + ldwx $nhi($Hhl),$Thl + xor $Thh,$Zhh,$Zhh + ldwx $nhi($Hhh),$Thh + zdep $Zll,28,4,$rem + ldwx $rem($rem_4bit),$rem + shrpw $Zlh,$Zll,4,$Zll + shrpw $Zhl,$Zlh,4,$Zlh + shrpw $Zhh,$Zhl,4,$Zhl + extru $Zhh,27,28,$Zhh + xor $Tll,$Zll,$Zll + xor $Tlh,$Zlh,$Zlh + xor $rem,$Zhh,$Zhh + stw $Zll,12($Xi) + xor $Thl,$Zhl,$Zhl + stw $Zlh,8($Xi) + xor $Thh,$Zhh,$Zhh + stw $Zhl,4($Xi) + stw $Zhh,0($Xi) +___ +$code.=<<___; +L\$done_gmult + $POP `-$FRAME-$SAVED_RP`(%sp),%r2 ; standard epilogue + $POP `-$FRAME+1*$SIZE_T`(%sp),%r4 + $POP `-$FRAME+2*$SIZE_T`(%sp),%r5 + $POP `-$FRAME+3*$SIZE_T`(%sp),%r6 +___ +$code.=<<___ if ($SIZE_T==4); + $POP `-$FRAME+4*$SIZE_T`(%sp),%r7 + $POP `-$FRAME+5*$SIZE_T`(%sp),%r8 + $POP `-$FRAME+6*$SIZE_T`(%sp),%r9 + $POP `-$FRAME+7*$SIZE_T`(%sp),%r10 + $POP `-$FRAME+8*$SIZE_T`(%sp),%r11 +___ +$code.=<<___; + bv (%r2) + .EXIT + $POPMB -$FRAME(%sp),%r3 + .PROCEND + + .EXPORT gcm_ghash_4bit,ENTRY,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR + .ALIGN 64 +gcm_ghash_4bit + .PROC + .CALLINFO FRAME=`$FRAME-10*$SIZE_T`,NO_CALLS,SAVE_RP,ENTRY_GR=11 + .ENTRY + $PUSH %r2,-$SAVED_RP(%sp) ; standard prologue + $PUSHMA %r3,$FRAME(%sp) + $PUSH %r4,`-$FRAME+1*$SIZE_T`(%sp) + $PUSH %r5,`-$FRAME+2*$SIZE_T`(%sp) + $PUSH %r6,`-$FRAME+3*$SIZE_T`(%sp) +___ +$code.=<<___ if ($SIZE_T==4); + $PUSH %r7,`-$FRAME+4*$SIZE_T`(%sp) + $PUSH %r8,`-$FRAME+5*$SIZE_T`(%sp) + $PUSH %r9,`-$FRAME+6*$SIZE_T`(%sp) + $PUSH %r10,`-$FRAME+7*$SIZE_T`(%sp) + $PUSH %r11,`-$FRAME+8*$SIZE_T`(%sp) +___ +$code.=<<___; + blr %r0,$rem_4bit + ldi 3,$rem +L\$pic_ghash + andcm $rem_4bit,$rem,$rem_4bit + addl $inp,$len,$len + ldo L\$rem_4bit-L\$pic_ghash($rem_4bit),$rem_4bit + ldi 0xf0,$mask0xf0 +___ +$code.=<<___ if ($SIZE_T==4); + ldi 31,$rem + mtctl $rem,%cr11 + extrd,u,*= $rem,%sar,1,$rem ; executes on PA-RISC 1.0 + b L\$parisc1_ghash + nop +___ + +$code.=<<___; + ldb 15($Xi),$nlo + ldo 8($Htbl),$Hll + +L\$outer_ghash_pa2 + ldb 15($inp),$nhi + xor $nhi,$nlo,$nlo + and $mask0xf0,$nlo,$nhi + depd,z $nlo,59,4,$nlo + + ldd $nlo($Hll),$Zll + ldd $nlo($Hhh),$Zhh + + depd,z $Zll,60,4,$rem + shrpd $Zhh,$Zll,4,$Zll + extrd,u $Zhh,59,60,$Zhh + ldb 14($Xi),$nlo + ldb 14($inp),$byte + + ldd $nhi($Hll),$Tll + ldd $nhi($Hhh),$Thh + xor $byte,$nlo,$nlo + and $mask0xf0,$nlo,$nhi + depd,z $nlo,59,4,$nlo + + xor $Tll,$Zll,$Zll + xor $Thh,$Zhh,$Zhh + ldd $rem($rem_4bit),$rem + b L\$oop_ghash_pa2 + ldi 13,$cnt + + .ALIGN 8 +L\$oop_ghash_pa2 + xor $rem,$Zhh,$Zhh ; moved here to work around gas bug + depd,z $Zll,60,4,$rem2 + + shrpd $Zhh,$Zll,4,$Zll + extrd,u $Zhh,59,60,$Zhh + ldd $nlo($Hll),$Tll + ldd $nlo($Hhh),$Thh + + xor $Tll,$Zll,$Zll + xor $Thh,$Zhh,$Zhh + ldbx $cnt($Xi),$nlo + ldbx $cnt($inp),$byte + + depd,z $Zll,60,4,$rem + shrpd $Zhh,$Zll,4,$Zll + ldd $rem2($rem_4bit),$rem2 + + xor $rem2,$Zhh,$Zhh + xor $byte,$nlo,$nlo + ldd $nhi($Hll),$Tll + ldd $nhi($Hhh),$Thh + + and $mask0xf0,$nlo,$nhi + depd,z $nlo,59,4,$nlo + + extrd,u $Zhh,59,60,$Zhh + xor $Tll,$Zll,$Zll + + ldd $rem($rem_4bit),$rem + addib,uv -1,$cnt,L\$oop_ghash_pa2 + xor $Thh,$Zhh,$Zhh + + xor $rem,$Zhh,$Zhh + depd,z $Zll,60,4,$rem2 + + shrpd $Zhh,$Zll,4,$Zll + extrd,u $Zhh,59,60,$Zhh + ldd $nlo($Hll),$Tll + ldd $nlo($Hhh),$Thh + + xor $Tll,$Zll,$Zll + xor $Thh,$Zhh,$Zhh + + depd,z $Zll,60,4,$rem + shrpd $Zhh,$Zll,4,$Zll + ldd $rem2($rem_4bit),$rem2 + + xor $rem2,$Zhh,$Zhh + ldd $nhi($Hll),$Tll + ldd $nhi($Hhh),$Thh + + extrd,u $Zhh,59,60,$Zhh + xor $Tll,$Zll,$Zll + xor $Thh,$Zhh,$Zhh + ldd $rem($rem_4bit),$rem + + xor $rem,$Zhh,$Zhh + std $Zll,8($Xi) + ldo 16($inp),$inp + std $Zhh,0($Xi) + cmpb,*<> $inp,$len,L\$outer_ghash_pa2 + copy $Zll,$nlo +___ + +$code.=<<___ if ($SIZE_T==4); + b L\$done_ghash + nop + +L\$parisc1_ghash + ldb 15($Xi),$nlo + ldo 12($Htbl),$Hll + ldo 8($Htbl),$Hlh + ldo 4($Htbl),$Hhl + +L\$outer_ghash_pa1 + ldb 15($inp),$byte + xor $byte,$nlo,$nlo + and $mask0xf0,$nlo,$nhi + zdep $nlo,27,4,$nlo + + ldwx $nlo($Hll),$Zll + ldwx $nlo($Hlh),$Zlh + ldwx $nlo($Hhl),$Zhl + ldwx $nlo($Hhh),$Zhh + zdep $Zll,28,4,$rem + ldb 14($Xi),$nlo + ldb 14($inp),$byte + ldwx $rem($rem_4bit),$rem + shrpw $Zlh,$Zll,4,$Zll + ldwx $nhi($Hll),$Tll + shrpw $Zhl,$Zlh,4,$Zlh + ldwx $nhi($Hlh),$Tlh + shrpw $Zhh,$Zhl,4,$Zhl + ldwx $nhi($Hhl),$Thl + extru $Zhh,27,28,$Zhh + ldwx $nhi($Hhh),$Thh + xor $byte,$nlo,$nlo + xor $rem,$Zhh,$Zhh + and $mask0xf0,$nlo,$nhi + zdep $nlo,27,4,$nlo + + xor $Tll,$Zll,$Zll + ldwx $nlo($Hll),$Tll + xor $Tlh,$Zlh,$Zlh + ldwx $nlo($Hlh),$Tlh + xor $Thl,$Zhl,$Zhl + b L\$oop_ghash_pa1 + ldi 13,$cnt + + .ALIGN 8 +L\$oop_ghash_pa1 + zdep $Zll,28,4,$rem + ldwx $nlo($Hhl),$Thl + xor $Thh,$Zhh,$Zhh + ldwx $rem($rem_4bit),$rem + shrpw $Zlh,$Zll,4,$Zll + ldwx $nlo($Hhh),$Thh + shrpw $Zhl,$Zlh,4,$Zlh + ldbx $cnt($Xi),$nlo + xor $Tll,$Zll,$Zll + ldwx $nhi($Hll),$Tll + shrpw $Zhh,$Zhl,4,$Zhl + ldbx $cnt($inp),$byte + xor $Tlh,$Zlh,$Zlh + ldwx $nhi($Hlh),$Tlh + extru $Zhh,27,28,$Zhh + xor $Thl,$Zhl,$Zhl + ldwx $nhi($Hhl),$Thl + xor $rem,$Zhh,$Zhh + zdep $Zll,28,4,$rem + xor $Thh,$Zhh,$Zhh + ldwx $nhi($Hhh),$Thh + shrpw $Zlh,$Zll,4,$Zll + ldwx $rem($rem_4bit),$rem + shrpw $Zhl,$Zlh,4,$Zlh + xor $byte,$nlo,$nlo + shrpw $Zhh,$Zhl,4,$Zhl + and $mask0xf0,$nlo,$nhi + extru $Zhh,27,28,$Zhh + zdep $nlo,27,4,$nlo + xor $Tll,$Zll,$Zll + ldwx $nlo($Hll),$Tll + xor $Tlh,$Zlh,$Zlh + ldwx $nlo($Hlh),$Tlh + xor $rem,$Zhh,$Zhh + addib,uv -1,$cnt,L\$oop_ghash_pa1 + xor $Thl,$Zhl,$Zhl + + zdep $Zll,28,4,$rem + ldwx $nlo($Hhl),$Thl + xor $Thh,$Zhh,$Zhh + ldwx $rem($rem_4bit),$rem + shrpw $Zlh,$Zll,4,$Zll + ldwx $nlo($Hhh),$Thh + shrpw $Zhl,$Zlh,4,$Zlh + xor $Tll,$Zll,$Zll + ldwx $nhi($Hll),$Tll + shrpw $Zhh,$Zhl,4,$Zhl + xor $Tlh,$Zlh,$Zlh + ldwx $nhi($Hlh),$Tlh + extru $Zhh,27,28,$Zhh + xor $rem,$Zhh,$Zhh + xor $Thl,$Zhl,$Zhl + ldwx $nhi($Hhl),$Thl + xor $Thh,$Zhh,$Zhh + ldwx $nhi($Hhh),$Thh + zdep $Zll,28,4,$rem + ldwx $rem($rem_4bit),$rem + shrpw $Zlh,$Zll,4,$Zll + shrpw $Zhl,$Zlh,4,$Zlh + shrpw $Zhh,$Zhl,4,$Zhl + extru $Zhh,27,28,$Zhh + xor $Tll,$Zll,$Zll + xor $Tlh,$Zlh,$Zlh + xor $rem,$Zhh,$Zhh + stw $Zll,12($Xi) + xor $Thl,$Zhl,$Zhl + stw $Zlh,8($Xi) + xor $Thh,$Zhh,$Zhh + stw $Zhl,4($Xi) + ldo 16($inp),$inp + stw $Zhh,0($Xi) + comb,<> $inp,$len,L\$outer_ghash_pa1 + copy $Zll,$nlo +___ +$code.=<<___; +L\$done_ghash + $POP `-$FRAME-$SAVED_RP`(%sp),%r2 ; standard epilogue + $POP `-$FRAME+1*$SIZE_T`(%sp),%r4 + $POP `-$FRAME+2*$SIZE_T`(%sp),%r5 + $POP `-$FRAME+3*$SIZE_T`(%sp),%r6 +___ +$code.=<<___ if ($SIZE_T==4); + $POP `-$FRAME+4*$SIZE_T`(%sp),%r7 + $POP `-$FRAME+5*$SIZE_T`(%sp),%r8 + $POP `-$FRAME+6*$SIZE_T`(%sp),%r9 + $POP `-$FRAME+7*$SIZE_T`(%sp),%r10 + $POP `-$FRAME+8*$SIZE_T`(%sp),%r11 +___ +$code.=<<___; + bv (%r2) + .EXIT + $POPMB -$FRAME(%sp),%r3 + .PROCEND + + .ALIGN 64 +L\$rem_4bit + .WORD `0x0000<<16`,0,`0x1C20<<16`,0,`0x3840<<16`,0,`0x2460<<16`,0 + .WORD `0x7080<<16`,0,`0x6CA0<<16`,0,`0x48C0<<16`,0,`0x54E0<<16`,0 + .WORD `0xE100<<16`,0,`0xFD20<<16`,0,`0xD940<<16`,0,`0xC560<<16`,0 + .WORD `0x9180<<16`,0,`0x8DA0<<16`,0,`0xA9C0<<16`,0,`0xB5E0<<16`,0 + .STRINGZ "GHASH for PA-RISC, GRYPTOGAMS by " + .ALIGN 64 +___ + +# Explicitly encode PA-RISC 2.0 instructions used in this module, so +# that it can be compiled with .LEVEL 1.0. It should be noted that I +# wouldn't have to do this, if GNU assembler understood .ALLOW 2.0 +# directive... + +my $ldd = sub { + my ($mod,$args) = @_; + my $orig = "ldd$mod\t$args"; + + if ($args =~ /%r([0-9]+)\(%r([0-9]+)\),%r([0-9]+)/) # format 4 + { my $opcode=(0x03<<26)|($2<<21)|($1<<16)|(3<<6)|$3; + sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig; + } + elsif ($args =~ /(\-?[0-9]+)\(%r([0-9]+)\),%r([0-9]+)/) # format 5 + { my $opcode=(0x03<<26)|($2<<21)|(1<<12)|(3<<6)|$3; + $opcode|=(($1&0xF)<<17)|(($1&0x10)<<12); # encode offset + $opcode|=(1<<5) if ($mod =~ /^,m/); + $opcode|=(1<<13) if ($mod =~ /^,mb/); + sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig; + } + else { "\t".$orig; } +}; + +my $std = sub { + my ($mod,$args) = @_; + my $orig = "std$mod\t$args"; + + if ($args =~ /%r([0-9]+),(\-?[0-9]+)\(%r([0-9]+)\)/) # format 3 suffices + { my $opcode=(0x1c<<26)|($3<<21)|($1<<16)|(($2&0x1FF8)<<1)|(($2>>13)&1); + sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig; + } + else { "\t".$orig; } +}; + +my $extrd = sub { + my ($mod,$args) = @_; + my $orig = "extrd$mod\t$args"; + + # I only have ",u" completer, it's implicitly encoded... + if ($args =~ /%r([0-9]+),([0-9]+),([0-9]+),%r([0-9]+)/) # format 15 + { my $opcode=(0x36<<26)|($1<<21)|($4<<16); + my $len=32-$3; + $opcode |= (($2&0x20)<<6)|(($2&0x1f)<<5); # encode pos + $opcode |= (($len&0x20)<<7)|($len&0x1f); # encode len + sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig; + } + elsif ($args =~ /%r([0-9]+),%sar,([0-9]+),%r([0-9]+)/) # format 12 + { my $opcode=(0x34<<26)|($1<<21)|($3<<16)|(2<<11)|(1<<9); + my $len=32-$2; + $opcode |= (($len&0x20)<<3)|($len&0x1f); # encode len + $opcode |= (1<<13) if ($mod =~ /,\**=/); + sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig; + } + else { "\t".$orig; } +}; + +my $shrpd = sub { + my ($mod,$args) = @_; + my $orig = "shrpd$mod\t$args"; + + if ($args =~ /%r([0-9]+),%r([0-9]+),([0-9]+),%r([0-9]+)/) # format 14 + { my $opcode=(0x34<<26)|($2<<21)|($1<<16)|(1<<10)|$4; + my $cpos=63-$3; + $opcode |= (($cpos&0x20)<<6)|(($cpos&0x1f)<<5); # encode sa + sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig; + } + elsif ($args =~ /%r([0-9]+),%r([0-9]+),%sar,%r([0-9]+)/) # format 11 + { sprintf "\t.WORD\t0x%08x\t; %s", + (0x34<<26)|($2<<21)|($1<<16)|(1<<9)|$3,$orig; + } + else { "\t".$orig; } +}; + +my $depd = sub { + my ($mod,$args) = @_; + my $orig = "depd$mod\t$args"; + + # I only have ",z" completer, it's implicitly encoded... + if ($args =~ /%r([0-9]+),([0-9]+),([0-9]+),%r([0-9]+)/) # format 16 + { my $opcode=(0x3c<<26)|($4<<21)|($1<<16); + my $cpos=63-$2; + my $len=32-$3; + $opcode |= (($cpos&0x20)<<6)|(($cpos&0x1f)<<5); # encode pos + $opcode |= (($len&0x20)<<7)|($len&0x1f); # encode len + sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig; + } + else { "\t".$orig; } +}; + +sub assemble { + my ($mnemonic,$mod,$args)=@_; + my $opcode = eval("\$$mnemonic"); + + ref($opcode) eq 'CODE' ? &$opcode($mod,$args) : "\t$mnemonic$mod\t$args"; +} + +if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler/) { + $gnuas = 1; +} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/ge; + if ($SIZE_T==4) { + s/^\s+([a-z]+)([\S]*)\s+([\S]*)/&assemble($1,$2,$3)/e; + s/cmpb,\*/comb,/; + s/,\*/,/; + } + + s/(\.LEVEL\s+2\.0)W/$1w/ if ($gnuas && $SIZE_T==8); + s/\.SPACE\s+\$TEXT\$/.text/ if ($gnuas && $SIZE_T==8); + s/\.SUBSPA.*// if ($gnuas && $SIZE_T==8); + s/\bbv\b/bve/ if ($SIZE_T==8); + + print $_,"\n"; +} + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-s390x.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-s390x.pl new file mode 100644 index 000000000..17dc37505 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-s390x.pl @@ -0,0 +1,262 @@ +#! /usr/bin/env perl +# Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# September 2010. +# +# The module implements "4-bit" GCM GHASH function and underlying +# single multiplication operation in GF(2^128). "4-bit" means that it +# uses 256 bytes per-key table [+128 bytes shared table]. Performance +# was measured to be ~18 cycles per processed byte on z10, which is +# almost 40% better than gcc-generated code. It should be noted that +# 18 cycles is worse result than expected: loop is scheduled for 12 +# and the result should be close to 12. In the lack of instruction- +# level profiling data it's impossible to tell why... + +# November 2010. +# +# Adapt for -m31 build. If kernel supports what's called "highgprs" +# feature on Linux [see /proc/cpuinfo], it's possible to use 64-bit +# instructions and achieve "64-bit" performance even in 31-bit legacy +# application context. The feature is not specific to any particular +# processor, as long as it's "z-CPU". Latter implies that the code +# remains z/Architecture specific. On z990 it was measured to perform +# 2.8x better than 32-bit code generated by gcc 4.3. + +# March 2011. +# +# Support for hardware KIMD-GHASH is verified to produce correct +# result and therefore is engaged. On z196 it was measured to process +# 8KB buffer ~7 faster than software implementation. It's not as +# impressive for smaller buffer sizes and for smallest 16-bytes buffer +# it's actually almost 2 times slower. Which is the reason why +# KIMD-GHASH is not used in gcm_gmult_4bit. + +$flavour = shift; + +if ($flavour =~ /3[12]/) { + $SIZE_T=4; + $g=""; +} else { + $SIZE_T=8; + $g="g"; +} + +while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} +open STDOUT,">$output"; + +$softonly=0; + +$Zhi="%r0"; +$Zlo="%r1"; + +$Xi="%r2"; # argument block +$Htbl="%r3"; +$inp="%r4"; +$len="%r5"; + +$rem0="%r6"; # variables +$rem1="%r7"; +$nlo="%r8"; +$nhi="%r9"; +$xi="%r10"; +$cnt="%r11"; +$tmp="%r12"; +$x78="%r13"; +$rem_4bit="%r14"; + +$sp="%r15"; + +$code.=<<___; +#include "s390x_arch.h" + +.text + +.globl gcm_gmult_4bit +.align 32 +gcm_gmult_4bit: +___ +$code.=<<___ if(!$softonly && 0); # hardware is slow for single block... + larl %r1,OPENSSL_s390xcap_P + lghi %r0,0 + lg %r1,S390X_KIMD+8(%r1) # load second word of kimd capabilities + # vector + tmhh %r1,0x4000 # check for function 65 + jz .Lsoft_gmult + stg %r0,16($sp) # arrange 16 bytes of zero input + stg %r0,24($sp) + lghi %r0,S390X_GHASH # function 65 + la %r1,0($Xi) # H lies right after Xi in gcm128_context + la $inp,16($sp) + lghi $len,16 + .long 0xb93e0004 # kimd %r0,$inp + brc 1,.-4 # pay attention to "partial completion" + br %r14 +.align 32 +.Lsoft_gmult: +___ +$code.=<<___; + stm${g} %r6,%r14,6*$SIZE_T($sp) + + aghi $Xi,-1 + lghi $len,1 + lghi $x78,`0xf<<3` + larl $rem_4bit,rem_4bit + + lg $Zlo,8+1($Xi) # Xi + j .Lgmult_shortcut +.type gcm_gmult_4bit,\@function +.size gcm_gmult_4bit,(.-gcm_gmult_4bit) + +.globl gcm_ghash_4bit +.align 32 +gcm_ghash_4bit: +___ +$code.=<<___ if(!$softonly); + larl %r1,OPENSSL_s390xcap_P + lg %r0,S390X_KIMD+8(%r1) # load second word of kimd capabilities + # vector + tmhh %r0,0x4000 # check for function 65 + jz .Lsoft_ghash + lghi %r0,S390X_GHASH # function 65 + la %r1,0($Xi) # H lies right after Xi in gcm128_context + .long 0xb93e0004 # kimd %r0,$inp + brc 1,.-4 # pay attention to "partial completion" + br %r14 +.align 32 +.Lsoft_ghash: +___ +$code.=<<___ if ($flavour =~ /3[12]/); + llgfr $len,$len +___ +$code.=<<___; + stm${g} %r6,%r14,6*$SIZE_T($sp) + + aghi $Xi,-1 + srlg $len,$len,4 + lghi $x78,`0xf<<3` + larl $rem_4bit,rem_4bit + + lg $Zlo,8+1($Xi) # Xi + lg $Zhi,0+1($Xi) + lghi $tmp,0 +.Louter: + xg $Zhi,0($inp) # Xi ^= inp + xg $Zlo,8($inp) + xgr $Zhi,$tmp + stg $Zlo,8+1($Xi) + stg $Zhi,0+1($Xi) + +.Lgmult_shortcut: + lghi $tmp,0xf0 + sllg $nlo,$Zlo,4 + srlg $xi,$Zlo,8 # extract second byte + ngr $nlo,$tmp + lgr $nhi,$Zlo + lghi $cnt,14 + ngr $nhi,$tmp + + lg $Zlo,8($nlo,$Htbl) + lg $Zhi,0($nlo,$Htbl) + + sllg $nlo,$xi,4 + sllg $rem0,$Zlo,3 + ngr $nlo,$tmp + ngr $rem0,$x78 + ngr $xi,$tmp + + sllg $tmp,$Zhi,60 + srlg $Zlo,$Zlo,4 + srlg $Zhi,$Zhi,4 + xg $Zlo,8($nhi,$Htbl) + xg $Zhi,0($nhi,$Htbl) + lgr $nhi,$xi + sllg $rem1,$Zlo,3 + xgr $Zlo,$tmp + ngr $rem1,$x78 + sllg $tmp,$Zhi,60 + j .Lghash_inner +.align 16 +.Lghash_inner: + srlg $Zlo,$Zlo,4 + srlg $Zhi,$Zhi,4 + xg $Zlo,8($nlo,$Htbl) + llgc $xi,0($cnt,$Xi) + xg $Zhi,0($nlo,$Htbl) + sllg $nlo,$xi,4 + xg $Zhi,0($rem0,$rem_4bit) + nill $nlo,0xf0 + sllg $rem0,$Zlo,3 + xgr $Zlo,$tmp + ngr $rem0,$x78 + nill $xi,0xf0 + + sllg $tmp,$Zhi,60 + srlg $Zlo,$Zlo,4 + srlg $Zhi,$Zhi,4 + xg $Zlo,8($nhi,$Htbl) + xg $Zhi,0($nhi,$Htbl) + lgr $nhi,$xi + xg $Zhi,0($rem1,$rem_4bit) + sllg $rem1,$Zlo,3 + xgr $Zlo,$tmp + ngr $rem1,$x78 + sllg $tmp,$Zhi,60 + brct $cnt,.Lghash_inner + + srlg $Zlo,$Zlo,4 + srlg $Zhi,$Zhi,4 + xg $Zlo,8($nlo,$Htbl) + xg $Zhi,0($nlo,$Htbl) + sllg $xi,$Zlo,3 + xg $Zhi,0($rem0,$rem_4bit) + xgr $Zlo,$tmp + ngr $xi,$x78 + + sllg $tmp,$Zhi,60 + srlg $Zlo,$Zlo,4 + srlg $Zhi,$Zhi,4 + xg $Zlo,8($nhi,$Htbl) + xg $Zhi,0($nhi,$Htbl) + xgr $Zlo,$tmp + xg $Zhi,0($rem1,$rem_4bit) + + lg $tmp,0($xi,$rem_4bit) + la $inp,16($inp) + sllg $tmp,$tmp,4 # correct last rem_4bit[rem] + brctg $len,.Louter + + xgr $Zhi,$tmp + stg $Zlo,8+1($Xi) + stg $Zhi,0+1($Xi) + lm${g} %r6,%r14,6*$SIZE_T($sp) + br %r14 +.type gcm_ghash_4bit,\@function +.size gcm_ghash_4bit,(.-gcm_ghash_4bit) + +.align 64 +rem_4bit: + .long `0x0000<<12`,0,`0x1C20<<12`,0,`0x3840<<12`,0,`0x2460<<12`,0 + .long `0x7080<<12`,0,`0x6CA0<<12`,0,`0x48C0<<12`,0,`0x54E0<<12`,0 + .long `0xE100<<12`,0,`0xFD20<<12`,0,`0xD940<<12`,0,`0xC560<<12`,0 + .long `0x9180<<12`,0,`0x8DA0<<12`,0,`0xA9C0<<12`,0,`0xB5E0<<12`,0 +.type rem_4bit,\@object +.size rem_4bit,(.-rem_4bit) +.string "GHASH for s390x, CRYPTOGAMS by " +___ + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-sparcv9.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-sparcv9.pl new file mode 100644 index 000000000..c4eb3b1f0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-sparcv9.pl @@ -0,0 +1,581 @@ +#! /usr/bin/env perl +# Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# March 2010 +# +# The module implements "4-bit" GCM GHASH function and underlying +# single multiplication operation in GF(2^128). "4-bit" means that it +# uses 256 bytes per-key table [+128 bytes shared table]. Performance +# results are for streamed GHASH subroutine on UltraSPARC pre-Tx CPU +# and are expressed in cycles per processed byte, less is better: +# +# gcc 3.3.x cc 5.2 this assembler +# +# 32-bit build 81.4 43.3 12.6 (+546%/+244%) +# 64-bit build 20.2 21.2 12.6 (+60%/+68%) +# +# Here is data collected on UltraSPARC T1 system running Linux: +# +# gcc 4.4.1 this assembler +# +# 32-bit build 566 50 (+1000%) +# 64-bit build 56 50 (+12%) +# +# I don't quite understand why difference between 32-bit and 64-bit +# compiler-generated code is so big. Compilers *were* instructed to +# generate code for UltraSPARC and should have used 64-bit registers +# for Z vector (see C code) even in 32-bit build... Oh well, it only +# means more impressive improvement coefficients for this assembler +# module;-) Loops are aggressively modulo-scheduled in respect to +# references to input data and Z.hi updates to achieve 12 cycles +# timing. To anchor to something else, sha1-sparcv9.pl spends 11.6 +# cycles to process one byte on UltraSPARC pre-Tx CPU and ~24 on T1. +# +# October 2012 +# +# Add VIS3 lookup-table-free implementation using polynomial +# multiplication xmulx[hi] and extended addition addxc[cc] +# instructions. 4.52/7.63x improvement on T3/T4 or in absolute +# terms 7.90/2.14 cycles per byte. On T4 multi-process benchmark +# saturates at ~15.5x single-process result on 8-core processor, +# or ~20.5GBps per 2.85GHz socket. + +$output=pop; +open STDOUT,">$output"; + +$frame="STACK_FRAME"; +$bias="STACK_BIAS"; + +$Zhi="%o0"; # 64-bit values +$Zlo="%o1"; +$Thi="%o2"; +$Tlo="%o3"; +$rem="%o4"; +$tmp="%o5"; + +$nhi="%l0"; # small values and pointers +$nlo="%l1"; +$xi0="%l2"; +$xi1="%l3"; +$rem_4bit="%l4"; +$remi="%l5"; +$Htblo="%l6"; +$cnt="%l7"; + +$Xi="%i0"; # input argument block +$Htbl="%i1"; +$inp="%i2"; +$len="%i3"; + +$code.=<<___; +#include "sparc_arch.h" + +#ifdef __arch64__ +.register %g2,#scratch +.register %g3,#scratch +#endif + +.section ".text",#alloc,#execinstr + +.align 64 +rem_4bit: + .long `0x0000<<16`,0,`0x1C20<<16`,0,`0x3840<<16`,0,`0x2460<<16`,0 + .long `0x7080<<16`,0,`0x6CA0<<16`,0,`0x48C0<<16`,0,`0x54E0<<16`,0 + .long `0xE100<<16`,0,`0xFD20<<16`,0,`0xD940<<16`,0,`0xC560<<16`,0 + .long `0x9180<<16`,0,`0x8DA0<<16`,0,`0xA9C0<<16`,0,`0xB5E0<<16`,0 +.type rem_4bit,#object +.size rem_4bit,(.-rem_4bit) + +.globl gcm_ghash_4bit +.align 32 +gcm_ghash_4bit: + save %sp,-$frame,%sp + ldub [$inp+15],$nlo + ldub [$Xi+15],$xi0 + ldub [$Xi+14],$xi1 + add $len,$inp,$len + add $Htbl,8,$Htblo + +1: call .+8 + add %o7,rem_4bit-1b,$rem_4bit + +.Louter: + xor $xi0,$nlo,$nlo + and $nlo,0xf0,$nhi + and $nlo,0x0f,$nlo + sll $nlo,4,$nlo + ldx [$Htblo+$nlo],$Zlo + ldx [$Htbl+$nlo],$Zhi + + ldub [$inp+14],$nlo + + ldx [$Htblo+$nhi],$Tlo + and $Zlo,0xf,$remi + ldx [$Htbl+$nhi],$Thi + sll $remi,3,$remi + ldx [$rem_4bit+$remi],$rem + srlx $Zlo,4,$Zlo + mov 13,$cnt + sllx $Zhi,60,$tmp + xor $Tlo,$Zlo,$Zlo + srlx $Zhi,4,$Zhi + xor $Zlo,$tmp,$Zlo + + xor $xi1,$nlo,$nlo + and $Zlo,0xf,$remi + and $nlo,0xf0,$nhi + and $nlo,0x0f,$nlo + ba .Lghash_inner + sll $nlo,4,$nlo +.align 32 +.Lghash_inner: + ldx [$Htblo+$nlo],$Tlo + sll $remi,3,$remi + xor $Thi,$Zhi,$Zhi + ldx [$Htbl+$nlo],$Thi + srlx $Zlo,4,$Zlo + xor $rem,$Zhi,$Zhi + ldx [$rem_4bit+$remi],$rem + sllx $Zhi,60,$tmp + xor $Tlo,$Zlo,$Zlo + ldub [$inp+$cnt],$nlo + srlx $Zhi,4,$Zhi + xor $Zlo,$tmp,$Zlo + ldub [$Xi+$cnt],$xi1 + xor $Thi,$Zhi,$Zhi + and $Zlo,0xf,$remi + + ldx [$Htblo+$nhi],$Tlo + sll $remi,3,$remi + xor $rem,$Zhi,$Zhi + ldx [$Htbl+$nhi],$Thi + srlx $Zlo,4,$Zlo + ldx [$rem_4bit+$remi],$rem + sllx $Zhi,60,$tmp + xor $xi1,$nlo,$nlo + srlx $Zhi,4,$Zhi + and $nlo,0xf0,$nhi + addcc $cnt,-1,$cnt + xor $Zlo,$tmp,$Zlo + and $nlo,0x0f,$nlo + xor $Tlo,$Zlo,$Zlo + sll $nlo,4,$nlo + blu .Lghash_inner + and $Zlo,0xf,$remi + + ldx [$Htblo+$nlo],$Tlo + sll $remi,3,$remi + xor $Thi,$Zhi,$Zhi + ldx [$Htbl+$nlo],$Thi + srlx $Zlo,4,$Zlo + xor $rem,$Zhi,$Zhi + ldx [$rem_4bit+$remi],$rem + sllx $Zhi,60,$tmp + xor $Tlo,$Zlo,$Zlo + srlx $Zhi,4,$Zhi + xor $Zlo,$tmp,$Zlo + xor $Thi,$Zhi,$Zhi + + add $inp,16,$inp + cmp $inp,$len + be,pn SIZE_T_CC,.Ldone + and $Zlo,0xf,$remi + + ldx [$Htblo+$nhi],$Tlo + sll $remi,3,$remi + xor $rem,$Zhi,$Zhi + ldx [$Htbl+$nhi],$Thi + srlx $Zlo,4,$Zlo + ldx [$rem_4bit+$remi],$rem + sllx $Zhi,60,$tmp + xor $Tlo,$Zlo,$Zlo + ldub [$inp+15],$nlo + srlx $Zhi,4,$Zhi + xor $Zlo,$tmp,$Zlo + xor $Thi,$Zhi,$Zhi + stx $Zlo,[$Xi+8] + xor $rem,$Zhi,$Zhi + stx $Zhi,[$Xi] + srl $Zlo,8,$xi1 + and $Zlo,0xff,$xi0 + ba .Louter + and $xi1,0xff,$xi1 +.align 32 +.Ldone: + ldx [$Htblo+$nhi],$Tlo + sll $remi,3,$remi + xor $rem,$Zhi,$Zhi + ldx [$Htbl+$nhi],$Thi + srlx $Zlo,4,$Zlo + ldx [$rem_4bit+$remi],$rem + sllx $Zhi,60,$tmp + xor $Tlo,$Zlo,$Zlo + srlx $Zhi,4,$Zhi + xor $Zlo,$tmp,$Zlo + xor $Thi,$Zhi,$Zhi + stx $Zlo,[$Xi+8] + xor $rem,$Zhi,$Zhi + stx $Zhi,[$Xi] + + ret + restore +.type gcm_ghash_4bit,#function +.size gcm_ghash_4bit,(.-gcm_ghash_4bit) +___ + +undef $inp; +undef $len; + +$code.=<<___; +.globl gcm_gmult_4bit +.align 32 +gcm_gmult_4bit: + save %sp,-$frame,%sp + ldub [$Xi+15],$nlo + add $Htbl,8,$Htblo + +1: call .+8 + add %o7,rem_4bit-1b,$rem_4bit + + and $nlo,0xf0,$nhi + and $nlo,0x0f,$nlo + sll $nlo,4,$nlo + ldx [$Htblo+$nlo],$Zlo + ldx [$Htbl+$nlo],$Zhi + + ldub [$Xi+14],$nlo + + ldx [$Htblo+$nhi],$Tlo + and $Zlo,0xf,$remi + ldx [$Htbl+$nhi],$Thi + sll $remi,3,$remi + ldx [$rem_4bit+$remi],$rem + srlx $Zlo,4,$Zlo + mov 13,$cnt + sllx $Zhi,60,$tmp + xor $Tlo,$Zlo,$Zlo + srlx $Zhi,4,$Zhi + xor $Zlo,$tmp,$Zlo + + and $Zlo,0xf,$remi + and $nlo,0xf0,$nhi + and $nlo,0x0f,$nlo + ba .Lgmult_inner + sll $nlo,4,$nlo +.align 32 +.Lgmult_inner: + ldx [$Htblo+$nlo],$Tlo + sll $remi,3,$remi + xor $Thi,$Zhi,$Zhi + ldx [$Htbl+$nlo],$Thi + srlx $Zlo,4,$Zlo + xor $rem,$Zhi,$Zhi + ldx [$rem_4bit+$remi],$rem + sllx $Zhi,60,$tmp + xor $Tlo,$Zlo,$Zlo + ldub [$Xi+$cnt],$nlo + srlx $Zhi,4,$Zhi + xor $Zlo,$tmp,$Zlo + xor $Thi,$Zhi,$Zhi + and $Zlo,0xf,$remi + + ldx [$Htblo+$nhi],$Tlo + sll $remi,3,$remi + xor $rem,$Zhi,$Zhi + ldx [$Htbl+$nhi],$Thi + srlx $Zlo,4,$Zlo + ldx [$rem_4bit+$remi],$rem + sllx $Zhi,60,$tmp + srlx $Zhi,4,$Zhi + and $nlo,0xf0,$nhi + addcc $cnt,-1,$cnt + xor $Zlo,$tmp,$Zlo + and $nlo,0x0f,$nlo + xor $Tlo,$Zlo,$Zlo + sll $nlo,4,$nlo + blu .Lgmult_inner + and $Zlo,0xf,$remi + + ldx [$Htblo+$nlo],$Tlo + sll $remi,3,$remi + xor $Thi,$Zhi,$Zhi + ldx [$Htbl+$nlo],$Thi + srlx $Zlo,4,$Zlo + xor $rem,$Zhi,$Zhi + ldx [$rem_4bit+$remi],$rem + sllx $Zhi,60,$tmp + xor $Tlo,$Zlo,$Zlo + srlx $Zhi,4,$Zhi + xor $Zlo,$tmp,$Zlo + xor $Thi,$Zhi,$Zhi + and $Zlo,0xf,$remi + + ldx [$Htblo+$nhi],$Tlo + sll $remi,3,$remi + xor $rem,$Zhi,$Zhi + ldx [$Htbl+$nhi],$Thi + srlx $Zlo,4,$Zlo + ldx [$rem_4bit+$remi],$rem + sllx $Zhi,60,$tmp + xor $Tlo,$Zlo,$Zlo + srlx $Zhi,4,$Zhi + xor $Zlo,$tmp,$Zlo + xor $Thi,$Zhi,$Zhi + stx $Zlo,[$Xi+8] + xor $rem,$Zhi,$Zhi + stx $Zhi,[$Xi] + + ret + restore +.type gcm_gmult_4bit,#function +.size gcm_gmult_4bit,(.-gcm_gmult_4bit) +___ + +{{{ +# Straightforward 128x128-bit multiplication using Karatsuba algorithm +# followed by pair of 64-bit reductions [with a shortcut in first one, +# which allowed to break dependency between reductions and remove one +# multiplication from critical path]. While it might be suboptimal +# with regard to sheer number of multiplications, other methods [such +# as aggregate reduction] would require more 64-bit registers, which +# we don't have in 32-bit application context. + +($Xip,$Htable,$inp,$len)=map("%i$_",(0..3)); + +($Hhl,$Hlo,$Hhi,$Xlo,$Xhi,$xE1,$sqr, $C0,$C1,$C2,$C3,$V)= + (map("%o$_",(0..5,7)),map("%g$_",(1..5))); + +($shl,$shr)=map("%l$_",(0..7)); + +# For details regarding "twisted H" see ghash-x86.pl. +$code.=<<___; +.globl gcm_init_vis3 +.align 32 +gcm_init_vis3: + save %sp,-$frame,%sp + + ldx [%i1+0],$Hhi + ldx [%i1+8],$Hlo + mov 0xE1,$Xhi + mov 1,$Xlo + sllx $Xhi,57,$Xhi + srax $Hhi,63,$C0 ! broadcast carry + addcc $Hlo,$Hlo,$Hlo ! H<<=1 + addxc $Hhi,$Hhi,$Hhi + and $C0,$Xlo,$Xlo + and $C0,$Xhi,$Xhi + xor $Xlo,$Hlo,$Hlo + xor $Xhi,$Hhi,$Hhi + stx $Hlo,[%i0+8] ! save twisted H + stx $Hhi,[%i0+0] + + sethi %hi(0xA0406080),$V + sethi %hi(0x20C0E000),%l0 + or $V,%lo(0xA0406080),$V + or %l0,%lo(0x20C0E000),%l0 + sllx $V,32,$V + or %l0,$V,$V ! (0xE0·i)&0xff=0xA040608020C0E000 + stx $V,[%i0+16] + + ret + restore +.type gcm_init_vis3,#function +.size gcm_init_vis3,.-gcm_init_vis3 + +.globl gcm_gmult_vis3 +.align 32 +gcm_gmult_vis3: + save %sp,-$frame,%sp + + ldx [$Xip+8],$Xlo ! load Xi + ldx [$Xip+0],$Xhi + ldx [$Htable+8],$Hlo ! load twisted H + ldx [$Htable+0],$Hhi + + mov 0xE1,%l7 + sllx %l7,57,$xE1 ! 57 is not a typo + ldx [$Htable+16],$V ! (0xE0·i)&0xff=0xA040608020C0E000 + + xor $Hhi,$Hlo,$Hhl ! Karatsuba pre-processing + xmulx $Xlo,$Hlo,$C0 + xor $Xlo,$Xhi,$C2 ! Karatsuba pre-processing + xmulx $C2,$Hhl,$C1 + xmulxhi $Xlo,$Hlo,$Xlo + xmulxhi $C2,$Hhl,$C2 + xmulxhi $Xhi,$Hhi,$C3 + xmulx $Xhi,$Hhi,$Xhi + + sll $C0,3,$sqr + srlx $V,$sqr,$sqr ! ·0xE0 [implicit &(7<<3)] + xor $C0,$sqr,$sqr + sllx $sqr,57,$sqr ! ($C0·0xE1)<<1<<56 [implicit &0x7f] + + xor $C0,$C1,$C1 ! Karatsuba post-processing + xor $Xlo,$C2,$C2 + xor $sqr,$Xlo,$Xlo ! real destination is $C1 + xor $C3,$C2,$C2 + xor $Xlo,$C1,$C1 + xor $Xhi,$C2,$C2 + xor $Xhi,$C1,$C1 + + xmulxhi $C0,$xE1,$Xlo ! ·0xE1<<1<<56 + xor $C0,$C2,$C2 + xmulx $C1,$xE1,$C0 + xor $C1,$C3,$C3 + xmulxhi $C1,$xE1,$C1 + + xor $Xlo,$C2,$C2 + xor $C0,$C2,$C2 + xor $C1,$C3,$C3 + + stx $C2,[$Xip+8] ! save Xi + stx $C3,[$Xip+0] + + ret + restore +.type gcm_gmult_vis3,#function +.size gcm_gmult_vis3,.-gcm_gmult_vis3 + +.globl gcm_ghash_vis3 +.align 32 +gcm_ghash_vis3: + save %sp,-$frame,%sp + nop + srln $len,0,$len ! needed on v8+, "nop" on v9 + + ldx [$Xip+8],$C2 ! load Xi + ldx [$Xip+0],$C3 + ldx [$Htable+8],$Hlo ! load twisted H + ldx [$Htable+0],$Hhi + + mov 0xE1,%l7 + sllx %l7,57,$xE1 ! 57 is not a typo + ldx [$Htable+16],$V ! (0xE0·i)&0xff=0xA040608020C0E000 + + and $inp,7,$shl + andn $inp,7,$inp + sll $shl,3,$shl + prefetch [$inp+63], 20 + sub %g0,$shl,$shr + + xor $Hhi,$Hlo,$Hhl ! Karatsuba pre-processing +.Loop: + ldx [$inp+8],$Xlo + brz,pt $shl,1f + ldx [$inp+0],$Xhi + + ldx [$inp+16],$C1 ! align data + srlx $Xlo,$shr,$C0 + sllx $Xlo,$shl,$Xlo + sllx $Xhi,$shl,$Xhi + srlx $C1,$shr,$C1 + or $C0,$Xhi,$Xhi + or $C1,$Xlo,$Xlo +1: + add $inp,16,$inp + sub $len,16,$len + xor $C2,$Xlo,$Xlo + xor $C3,$Xhi,$Xhi + prefetch [$inp+63], 20 + + xmulx $Xlo,$Hlo,$C0 + xor $Xlo,$Xhi,$C2 ! Karatsuba pre-processing + xmulx $C2,$Hhl,$C1 + xmulxhi $Xlo,$Hlo,$Xlo + xmulxhi $C2,$Hhl,$C2 + xmulxhi $Xhi,$Hhi,$C3 + xmulx $Xhi,$Hhi,$Xhi + + sll $C0,3,$sqr + srlx $V,$sqr,$sqr ! ·0xE0 [implicit &(7<<3)] + xor $C0,$sqr,$sqr + sllx $sqr,57,$sqr ! ($C0·0xE1)<<1<<56 [implicit &0x7f] + + xor $C0,$C1,$C1 ! Karatsuba post-processing + xor $Xlo,$C2,$C2 + xor $sqr,$Xlo,$Xlo ! real destination is $C1 + xor $C3,$C2,$C2 + xor $Xlo,$C1,$C1 + xor $Xhi,$C2,$C2 + xor $Xhi,$C1,$C1 + + xmulxhi $C0,$xE1,$Xlo ! ·0xE1<<1<<56 + xor $C0,$C2,$C2 + xmulx $C1,$xE1,$C0 + xor $C1,$C3,$C3 + xmulxhi $C1,$xE1,$C1 + + xor $Xlo,$C2,$C2 + xor $C0,$C2,$C2 + brnz,pt $len,.Loop + xor $C1,$C3,$C3 + + stx $C2,[$Xip+8] ! save Xi + stx $C3,[$Xip+0] + + ret + restore +.type gcm_ghash_vis3,#function +.size gcm_ghash_vis3,.-gcm_ghash_vis3 +___ +}}} +$code.=<<___; +.asciz "GHASH for SPARCv9/VIS3, CRYPTOGAMS by " +.align 4 +___ + + +# Purpose of these subroutines is to explicitly encode VIS instructions, +# so that one can compile the module without having to specify VIS +# extensions on compiler command line, e.g. -xarch=v9 vs. -xarch=v9a. +# Idea is to reserve for option to produce "universal" binary and let +# programmer detect if current CPU is VIS capable at run-time. +sub unvis3 { +my ($mnemonic,$rs1,$rs2,$rd)=@_; +my %bias = ( "g" => 0, "o" => 8, "l" => 16, "i" => 24 ); +my ($ref,$opf); +my %visopf = ( "addxc" => 0x011, + "addxccc" => 0x013, + "xmulx" => 0x115, + "xmulxhi" => 0x116 ); + + $ref = "$mnemonic\t$rs1,$rs2,$rd"; + + if ($opf=$visopf{$mnemonic}) { + foreach ($rs1,$rs2,$rd) { + return $ref if (!/%([goli])([0-9])/); + $_=$bias{$1}+$2; + } + + return sprintf ".word\t0x%08x !%s", + 0x81b00000|$rd<<25|$rs1<<14|$opf<<5|$rs2, + $ref; + } else { + return $ref; + } +} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/ge; + + s/\b(xmulx[hi]*|addxc[c]{0,2})\s+(%[goli][0-7]),\s*(%[goli][0-7]),\s*(%[goli][0-7])/ + &unvis3($1,$2,$3,$4) + /ge; + + print $_,"\n"; +} + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-x86.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-x86.pl new file mode 100644 index 000000000..bcbe6e399 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-x86.pl @@ -0,0 +1,1404 @@ +#! /usr/bin/env perl +# Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# March, May, June 2010 +# +# The module implements "4-bit" GCM GHASH function and underlying +# single multiplication operation in GF(2^128). "4-bit" means that it +# uses 256 bytes per-key table [+64/128 bytes fixed table]. It has two +# code paths: vanilla x86 and vanilla SSE. Former will be executed on +# 486 and Pentium, latter on all others. SSE GHASH features so called +# "528B" variant of "4-bit" method utilizing additional 256+16 bytes +# of per-key storage [+512 bytes shared table]. Performance results +# are for streamed GHASH subroutine and are expressed in cycles per +# processed byte, less is better: +# +# gcc 2.95.3(*) SSE assembler x86 assembler +# +# Pentium 105/111(**) - 50 +# PIII 68 /75 12.2 24 +# P4 125/125 17.8 84(***) +# Opteron 66 /70 10.1 30 +# Core2 54 /67 8.4 18 +# Atom 105/105 16.8 53 +# VIA Nano 69 /71 13.0 27 +# +# (*) gcc 3.4.x was observed to generate few percent slower code, +# which is one of reasons why 2.95.3 results were chosen, +# another reason is lack of 3.4.x results for older CPUs; +# comparison with SSE results is not completely fair, because C +# results are for vanilla "256B" implementation, while +# assembler results are for "528B";-) +# (**) second number is result for code compiled with -fPIC flag, +# which is actually more relevant, because assembler code is +# position-independent; +# (***) see comment in non-MMX routine for further details; +# +# To summarize, it's >2-5 times faster than gcc-generated code. To +# anchor it to something else SHA1 assembler processes one byte in +# ~7 cycles on contemporary x86 cores. As for choice of MMX/SSE +# in particular, see comment at the end of the file... + +# May 2010 +# +# Add PCLMULQDQ version performing at 2.10 cycles per processed byte. +# The question is how close is it to theoretical limit? The pclmulqdq +# instruction latency appears to be 14 cycles and there can't be more +# than 2 of them executing at any given time. This means that single +# Karatsuba multiplication would take 28 cycles *plus* few cycles for +# pre- and post-processing. Then multiplication has to be followed by +# modulo-reduction. Given that aggregated reduction method [see +# "Carry-less Multiplication and Its Usage for Computing the GCM Mode" +# white paper by Intel] allows you to perform reduction only once in +# a while we can assume that asymptotic performance can be estimated +# as (28+Tmod/Naggr)/16, where Tmod is time to perform reduction +# and Naggr is the aggregation factor. +# +# Before we proceed to this implementation let's have closer look at +# the best-performing code suggested by Intel in their white paper. +# By tracing inter-register dependencies Tmod is estimated as ~19 +# cycles and Naggr chosen by Intel is 4, resulting in 2.05 cycles per +# processed byte. As implied, this is quite optimistic estimate, +# because it does not account for Karatsuba pre- and post-processing, +# which for a single multiplication is ~5 cycles. Unfortunately Intel +# does not provide performance data for GHASH alone. But benchmarking +# AES_GCM_encrypt ripped out of Fig. 15 of the white paper with aadt +# alone resulted in 2.46 cycles per byte of out 16KB buffer. Note that +# the result accounts even for pre-computing of degrees of the hash +# key H, but its portion is negligible at 16KB buffer size. +# +# Moving on to the implementation in question. Tmod is estimated as +# ~13 cycles and Naggr is 2, giving asymptotic performance of ... +# 2.16. How is it possible that measured performance is better than +# optimistic theoretical estimate? There is one thing Intel failed +# to recognize. By serializing GHASH with CTR in same subroutine +# former's performance is really limited to above (Tmul + Tmod/Naggr) +# equation. But if GHASH procedure is detached, the modulo-reduction +# can be interleaved with Naggr-1 multiplications at instruction level +# and under ideal conditions even disappear from the equation. So that +# optimistic theoretical estimate for this implementation is ... +# 28/16=1.75, and not 2.16. Well, it's probably way too optimistic, +# at least for such small Naggr. I'd argue that (28+Tproc/Naggr), +# where Tproc is time required for Karatsuba pre- and post-processing, +# is more realistic estimate. In this case it gives ... 1.91 cycles. +# Or in other words, depending on how well we can interleave reduction +# and one of the two multiplications the performance should be between +# 1.91 and 2.16. As already mentioned, this implementation processes +# one byte out of 8KB buffer in 2.10 cycles, while x86_64 counterpart +# - in 2.02. x86_64 performance is better, because larger register +# bank allows to interleave reduction and multiplication better. +# +# Does it make sense to increase Naggr? To start with it's virtually +# impossible in 32-bit mode, because of limited register bank +# capacity. Otherwise improvement has to be weighed against slower +# setup, as well as code size and complexity increase. As even +# optimistic estimate doesn't promise 30% performance improvement, +# there are currently no plans to increase Naggr. +# +# Special thanks to David Woodhouse for providing access to a +# Westmere-based system on behalf of Intel Open Source Technology Centre. + +# January 2010 +# +# Tweaked to optimize transitions between integer and FP operations +# on same XMM register, PCLMULQDQ subroutine was measured to process +# one byte in 2.07 cycles on Sandy Bridge, and in 2.12 - on Westmere. +# The minor regression on Westmere is outweighed by ~15% improvement +# on Sandy Bridge. Strangely enough attempt to modify 64-bit code in +# similar manner resulted in almost 20% degradation on Sandy Bridge, +# where original 64-bit code processes one byte in 1.95 cycles. + +##################################################################### +# For reference, AMD Bulldozer processes one byte in 1.98 cycles in +# 32-bit mode and 1.89 in 64-bit. + +# February 2013 +# +# Overhaul: aggregate Karatsuba post-processing, improve ILP in +# reduction_alg9. Resulting performance is 1.96 cycles per byte on +# Westmere, 1.95 - on Sandy/Ivy Bridge, 1.76 - on Bulldozer. + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +$output=pop; +open STDOUT,">$output"; + +&asm_init($ARGV[0],$x86only = $ARGV[$#ARGV] eq "386"); + +$sse2=0; +for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); } + +($Zhh,$Zhl,$Zlh,$Zll) = ("ebp","edx","ecx","ebx"); +$inp = "edi"; +$Htbl = "esi"; + +$unroll = 0; # Affects x86 loop. Folded loop performs ~7% worse + # than unrolled, which has to be weighted against + # 2.5x x86-specific code size reduction. + +sub x86_loop { + my $off = shift; + my $rem = "eax"; + + &mov ($Zhh,&DWP(4,$Htbl,$Zll)); + &mov ($Zhl,&DWP(0,$Htbl,$Zll)); + &mov ($Zlh,&DWP(12,$Htbl,$Zll)); + &mov ($Zll,&DWP(8,$Htbl,$Zll)); + &xor ($rem,$rem); # avoid partial register stalls on PIII + + # shrd practically kills P4, 2.5x deterioration, but P4 has + # MMX code-path to execute. shrd runs tad faster [than twice + # the shifts, move's and or's] on pre-MMX Pentium (as well as + # PIII and Core2), *but* minimizes code size, spares register + # and thus allows to fold the loop... + if (!$unroll) { + my $cnt = $inp; + &mov ($cnt,15); + &jmp (&label("x86_loop")); + &set_label("x86_loop",16); + for($i=1;$i<=2;$i++) { + &mov (&LB($rem),&LB($Zll)); + &shrd ($Zll,$Zlh,4); + &and (&LB($rem),0xf); + &shrd ($Zlh,$Zhl,4); + &shrd ($Zhl,$Zhh,4); + &shr ($Zhh,4); + &xor ($Zhh,&DWP($off+16,"esp",$rem,4)); + + &mov (&LB($rem),&BP($off,"esp",$cnt)); + if ($i&1) { + &and (&LB($rem),0xf0); + } else { + &shl (&LB($rem),4); + } + + &xor ($Zll,&DWP(8,$Htbl,$rem)); + &xor ($Zlh,&DWP(12,$Htbl,$rem)); + &xor ($Zhl,&DWP(0,$Htbl,$rem)); + &xor ($Zhh,&DWP(4,$Htbl,$rem)); + + if ($i&1) { + &dec ($cnt); + &js (&label("x86_break")); + } else { + &jmp (&label("x86_loop")); + } + } + &set_label("x86_break",16); + } else { + for($i=1;$i<32;$i++) { + &comment($i); + &mov (&LB($rem),&LB($Zll)); + &shrd ($Zll,$Zlh,4); + &and (&LB($rem),0xf); + &shrd ($Zlh,$Zhl,4); + &shrd ($Zhl,$Zhh,4); + &shr ($Zhh,4); + &xor ($Zhh,&DWP($off+16,"esp",$rem,4)); + + if ($i&1) { + &mov (&LB($rem),&BP($off+15-($i>>1),"esp")); + &and (&LB($rem),0xf0); + } else { + &mov (&LB($rem),&BP($off+15-($i>>1),"esp")); + &shl (&LB($rem),4); + } + + &xor ($Zll,&DWP(8,$Htbl,$rem)); + &xor ($Zlh,&DWP(12,$Htbl,$rem)); + &xor ($Zhl,&DWP(0,$Htbl,$rem)); + &xor ($Zhh,&DWP(4,$Htbl,$rem)); + } + } + &bswap ($Zll); + &bswap ($Zlh); + &bswap ($Zhl); + if (!$x86only) { + &bswap ($Zhh); + } else { + &mov ("eax",$Zhh); + &bswap ("eax"); + &mov ($Zhh,"eax"); + } +} + +if ($unroll) { + &function_begin_B("_x86_gmult_4bit_inner"); + &x86_loop(4); + &ret (); + &function_end_B("_x86_gmult_4bit_inner"); +} + +sub deposit_rem_4bit { + my $bias = shift; + + &mov (&DWP($bias+0, "esp"),0x0000<<16); + &mov (&DWP($bias+4, "esp"),0x1C20<<16); + &mov (&DWP($bias+8, "esp"),0x3840<<16); + &mov (&DWP($bias+12,"esp"),0x2460<<16); + &mov (&DWP($bias+16,"esp"),0x7080<<16); + &mov (&DWP($bias+20,"esp"),0x6CA0<<16); + &mov (&DWP($bias+24,"esp"),0x48C0<<16); + &mov (&DWP($bias+28,"esp"),0x54E0<<16); + &mov (&DWP($bias+32,"esp"),0xE100<<16); + &mov (&DWP($bias+36,"esp"),0xFD20<<16); + &mov (&DWP($bias+40,"esp"),0xD940<<16); + &mov (&DWP($bias+44,"esp"),0xC560<<16); + &mov (&DWP($bias+48,"esp"),0x9180<<16); + &mov (&DWP($bias+52,"esp"),0x8DA0<<16); + &mov (&DWP($bias+56,"esp"),0xA9C0<<16); + &mov (&DWP($bias+60,"esp"),0xB5E0<<16); +} + +$suffix = $x86only ? "" : "_x86"; + +&function_begin("gcm_gmult_4bit".$suffix); + &stack_push(16+4+1); # +1 for stack alignment + &mov ($inp,&wparam(0)); # load Xi + &mov ($Htbl,&wparam(1)); # load Htable + + &mov ($Zhh,&DWP(0,$inp)); # load Xi[16] + &mov ($Zhl,&DWP(4,$inp)); + &mov ($Zlh,&DWP(8,$inp)); + &mov ($Zll,&DWP(12,$inp)); + + &deposit_rem_4bit(16); + + &mov (&DWP(0,"esp"),$Zhh); # copy Xi[16] on stack + &mov (&DWP(4,"esp"),$Zhl); + &mov (&DWP(8,"esp"),$Zlh); + &mov (&DWP(12,"esp"),$Zll); + &shr ($Zll,20); + &and ($Zll,0xf0); + + if ($unroll) { + &call ("_x86_gmult_4bit_inner"); + } else { + &x86_loop(0); + &mov ($inp,&wparam(0)); + } + + &mov (&DWP(12,$inp),$Zll); + &mov (&DWP(8,$inp),$Zlh); + &mov (&DWP(4,$inp),$Zhl); + &mov (&DWP(0,$inp),$Zhh); + &stack_pop(16+4+1); +&function_end("gcm_gmult_4bit".$suffix); + +&function_begin("gcm_ghash_4bit".$suffix); + &stack_push(16+4+1); # +1 for 64-bit alignment + &mov ($Zll,&wparam(0)); # load Xi + &mov ($Htbl,&wparam(1)); # load Htable + &mov ($inp,&wparam(2)); # load in + &mov ("ecx",&wparam(3)); # load len + &add ("ecx",$inp); + &mov (&wparam(3),"ecx"); + + &mov ($Zhh,&DWP(0,$Zll)); # load Xi[16] + &mov ($Zhl,&DWP(4,$Zll)); + &mov ($Zlh,&DWP(8,$Zll)); + &mov ($Zll,&DWP(12,$Zll)); + + &deposit_rem_4bit(16); + + &set_label("x86_outer_loop",16); + &xor ($Zll,&DWP(12,$inp)); # xor with input + &xor ($Zlh,&DWP(8,$inp)); + &xor ($Zhl,&DWP(4,$inp)); + &xor ($Zhh,&DWP(0,$inp)); + &mov (&DWP(12,"esp"),$Zll); # dump it on stack + &mov (&DWP(8,"esp"),$Zlh); + &mov (&DWP(4,"esp"),$Zhl); + &mov (&DWP(0,"esp"),$Zhh); + + &shr ($Zll,20); + &and ($Zll,0xf0); + + if ($unroll) { + &call ("_x86_gmult_4bit_inner"); + } else { + &x86_loop(0); + &mov ($inp,&wparam(2)); + } + &lea ($inp,&DWP(16,$inp)); + &cmp ($inp,&wparam(3)); + &mov (&wparam(2),$inp) if (!$unroll); + &jb (&label("x86_outer_loop")); + + &mov ($inp,&wparam(0)); # load Xi + &mov (&DWP(12,$inp),$Zll); + &mov (&DWP(8,$inp),$Zlh); + &mov (&DWP(4,$inp),$Zhl); + &mov (&DWP(0,$inp),$Zhh); + &stack_pop(16+4+1); +&function_end("gcm_ghash_4bit".$suffix); + +if (!$x86only) {{{ + +&static_label("rem_4bit"); + +if (!$sse2) {{ # pure-MMX "May" version... + +$S=12; # shift factor for rem_4bit + +&function_begin_B("_mmx_gmult_4bit_inner"); +# MMX version performs 3.5 times better on P4 (see comment in non-MMX +# routine for further details), 100% better on Opteron, ~70% better +# on Core2 and PIII... In other words effort is considered to be well +# spent... Since initial release the loop was unrolled in order to +# "liberate" register previously used as loop counter. Instead it's +# used to optimize critical path in 'Z.hi ^= rem_4bit[Z.lo&0xf]'. +# The path involves move of Z.lo from MMX to integer register, +# effective address calculation and finally merge of value to Z.hi. +# Reference to rem_4bit is scheduled so late that I had to >>4 +# rem_4bit elements. This resulted in 20-45% procent improvement +# on contemporary µ-archs. +{ + my $cnt; + my $rem_4bit = "eax"; + my @rem = ($Zhh,$Zll); + my $nhi = $Zhl; + my $nlo = $Zlh; + + my ($Zlo,$Zhi) = ("mm0","mm1"); + my $tmp = "mm2"; + + &xor ($nlo,$nlo); # avoid partial register stalls on PIII + &mov ($nhi,$Zll); + &mov (&LB($nlo),&LB($nhi)); + &shl (&LB($nlo),4); + &and ($nhi,0xf0); + &movq ($Zlo,&QWP(8,$Htbl,$nlo)); + &movq ($Zhi,&QWP(0,$Htbl,$nlo)); + &movd ($rem[0],$Zlo); + + for ($cnt=28;$cnt>=-2;$cnt--) { + my $odd = $cnt&1; + my $nix = $odd ? $nlo : $nhi; + + &shl (&LB($nlo),4) if ($odd); + &psrlq ($Zlo,4); + &movq ($tmp,$Zhi); + &psrlq ($Zhi,4); + &pxor ($Zlo,&QWP(8,$Htbl,$nix)); + &mov (&LB($nlo),&BP($cnt/2,$inp)) if (!$odd && $cnt>=0); + &psllq ($tmp,60); + &and ($nhi,0xf0) if ($odd); + &pxor ($Zhi,&QWP(0,$rem_4bit,$rem[1],8)) if ($cnt<28); + &and ($rem[0],0xf); + &pxor ($Zhi,&QWP(0,$Htbl,$nix)); + &mov ($nhi,$nlo) if (!$odd && $cnt>=0); + &movd ($rem[1],$Zlo); + &pxor ($Zlo,$tmp); + + push (@rem,shift(@rem)); # "rotate" registers + } + + &mov ($inp,&DWP(4,$rem_4bit,$rem[1],8)); # last rem_4bit[rem] + + &psrlq ($Zlo,32); # lower part of Zlo is already there + &movd ($Zhl,$Zhi); + &psrlq ($Zhi,32); + &movd ($Zlh,$Zlo); + &movd ($Zhh,$Zhi); + &shl ($inp,4); # compensate for rem_4bit[i] being >>4 + + &bswap ($Zll); + &bswap ($Zhl); + &bswap ($Zlh); + &xor ($Zhh,$inp); + &bswap ($Zhh); + + &ret (); +} +&function_end_B("_mmx_gmult_4bit_inner"); + +&function_begin("gcm_gmult_4bit_mmx"); + &mov ($inp,&wparam(0)); # load Xi + &mov ($Htbl,&wparam(1)); # load Htable + + &call (&label("pic_point")); + &set_label("pic_point"); + &blindpop("eax"); + &lea ("eax",&DWP(&label("rem_4bit")."-".&label("pic_point"),"eax")); + + &movz ($Zll,&BP(15,$inp)); + + &call ("_mmx_gmult_4bit_inner"); + + &mov ($inp,&wparam(0)); # load Xi + &emms (); + &mov (&DWP(12,$inp),$Zll); + &mov (&DWP(4,$inp),$Zhl); + &mov (&DWP(8,$inp),$Zlh); + &mov (&DWP(0,$inp),$Zhh); +&function_end("gcm_gmult_4bit_mmx"); + +# Streamed version performs 20% better on P4, 7% on Opteron, +# 10% on Core2 and PIII... +&function_begin("gcm_ghash_4bit_mmx"); + &mov ($Zhh,&wparam(0)); # load Xi + &mov ($Htbl,&wparam(1)); # load Htable + &mov ($inp,&wparam(2)); # load in + &mov ($Zlh,&wparam(3)); # load len + + &call (&label("pic_point")); + &set_label("pic_point"); + &blindpop("eax"); + &lea ("eax",&DWP(&label("rem_4bit")."-".&label("pic_point"),"eax")); + + &add ($Zlh,$inp); + &mov (&wparam(3),$Zlh); # len to point at the end of input + &stack_push(4+1); # +1 for stack alignment + + &mov ($Zll,&DWP(12,$Zhh)); # load Xi[16] + &mov ($Zhl,&DWP(4,$Zhh)); + &mov ($Zlh,&DWP(8,$Zhh)); + &mov ($Zhh,&DWP(0,$Zhh)); + &jmp (&label("mmx_outer_loop")); + + &set_label("mmx_outer_loop",16); + &xor ($Zll,&DWP(12,$inp)); + &xor ($Zhl,&DWP(4,$inp)); + &xor ($Zlh,&DWP(8,$inp)); + &xor ($Zhh,&DWP(0,$inp)); + &mov (&wparam(2),$inp); + &mov (&DWP(12,"esp"),$Zll); + &mov (&DWP(4,"esp"),$Zhl); + &mov (&DWP(8,"esp"),$Zlh); + &mov (&DWP(0,"esp"),$Zhh); + + &mov ($inp,"esp"); + &shr ($Zll,24); + + &call ("_mmx_gmult_4bit_inner"); + + &mov ($inp,&wparam(2)); + &lea ($inp,&DWP(16,$inp)); + &cmp ($inp,&wparam(3)); + &jb (&label("mmx_outer_loop")); + + &mov ($inp,&wparam(0)); # load Xi + &emms (); + &mov (&DWP(12,$inp),$Zll); + &mov (&DWP(4,$inp),$Zhl); + &mov (&DWP(8,$inp),$Zlh); + &mov (&DWP(0,$inp),$Zhh); + + &stack_pop(4+1); +&function_end("gcm_ghash_4bit_mmx"); + +}} else {{ # "June" MMX version... + # ... has slower "April" gcm_gmult_4bit_mmx with folded + # loop. This is done to conserve code size... +$S=16; # shift factor for rem_4bit + +sub mmx_loop() { +# MMX version performs 2.8 times better on P4 (see comment in non-MMX +# routine for further details), 40% better on Opteron and Core2, 50% +# better on PIII... In other words effort is considered to be well +# spent... + my $inp = shift; + my $rem_4bit = shift; + my $cnt = $Zhh; + my $nhi = $Zhl; + my $nlo = $Zlh; + my $rem = $Zll; + + my ($Zlo,$Zhi) = ("mm0","mm1"); + my $tmp = "mm2"; + + &xor ($nlo,$nlo); # avoid partial register stalls on PIII + &mov ($nhi,$Zll); + &mov (&LB($nlo),&LB($nhi)); + &mov ($cnt,14); + &shl (&LB($nlo),4); + &and ($nhi,0xf0); + &movq ($Zlo,&QWP(8,$Htbl,$nlo)); + &movq ($Zhi,&QWP(0,$Htbl,$nlo)); + &movd ($rem,$Zlo); + &jmp (&label("mmx_loop")); + + &set_label("mmx_loop",16); + &psrlq ($Zlo,4); + &and ($rem,0xf); + &movq ($tmp,$Zhi); + &psrlq ($Zhi,4); + &pxor ($Zlo,&QWP(8,$Htbl,$nhi)); + &mov (&LB($nlo),&BP(0,$inp,$cnt)); + &psllq ($tmp,60); + &pxor ($Zhi,&QWP(0,$rem_4bit,$rem,8)); + &dec ($cnt); + &movd ($rem,$Zlo); + &pxor ($Zhi,&QWP(0,$Htbl,$nhi)); + &mov ($nhi,$nlo); + &pxor ($Zlo,$tmp); + &js (&label("mmx_break")); + + &shl (&LB($nlo),4); + &and ($rem,0xf); + &psrlq ($Zlo,4); + &and ($nhi,0xf0); + &movq ($tmp,$Zhi); + &psrlq ($Zhi,4); + &pxor ($Zlo,&QWP(8,$Htbl,$nlo)); + &psllq ($tmp,60); + &pxor ($Zhi,&QWP(0,$rem_4bit,$rem,8)); + &movd ($rem,$Zlo); + &pxor ($Zhi,&QWP(0,$Htbl,$nlo)); + &pxor ($Zlo,$tmp); + &jmp (&label("mmx_loop")); + + &set_label("mmx_break",16); + &shl (&LB($nlo),4); + &and ($rem,0xf); + &psrlq ($Zlo,4); + &and ($nhi,0xf0); + &movq ($tmp,$Zhi); + &psrlq ($Zhi,4); + &pxor ($Zlo,&QWP(8,$Htbl,$nlo)); + &psllq ($tmp,60); + &pxor ($Zhi,&QWP(0,$rem_4bit,$rem,8)); + &movd ($rem,$Zlo); + &pxor ($Zhi,&QWP(0,$Htbl,$nlo)); + &pxor ($Zlo,$tmp); + + &psrlq ($Zlo,4); + &and ($rem,0xf); + &movq ($tmp,$Zhi); + &psrlq ($Zhi,4); + &pxor ($Zlo,&QWP(8,$Htbl,$nhi)); + &psllq ($tmp,60); + &pxor ($Zhi,&QWP(0,$rem_4bit,$rem,8)); + &movd ($rem,$Zlo); + &pxor ($Zhi,&QWP(0,$Htbl,$nhi)); + &pxor ($Zlo,$tmp); + + &psrlq ($Zlo,32); # lower part of Zlo is already there + &movd ($Zhl,$Zhi); + &psrlq ($Zhi,32); + &movd ($Zlh,$Zlo); + &movd ($Zhh,$Zhi); + + &bswap ($Zll); + &bswap ($Zhl); + &bswap ($Zlh); + &bswap ($Zhh); +} + +&function_begin("gcm_gmult_4bit_mmx"); + &mov ($inp,&wparam(0)); # load Xi + &mov ($Htbl,&wparam(1)); # load Htable + + &call (&label("pic_point")); + &set_label("pic_point"); + &blindpop("eax"); + &lea ("eax",&DWP(&label("rem_4bit")."-".&label("pic_point"),"eax")); + + &movz ($Zll,&BP(15,$inp)); + + &mmx_loop($inp,"eax"); + + &emms (); + &mov (&DWP(12,$inp),$Zll); + &mov (&DWP(4,$inp),$Zhl); + &mov (&DWP(8,$inp),$Zlh); + &mov (&DWP(0,$inp),$Zhh); +&function_end("gcm_gmult_4bit_mmx"); + +###################################################################### +# Below subroutine is "528B" variant of "4-bit" GCM GHASH function +# (see gcm128.c for details). It provides further 20-40% performance +# improvement over above mentioned "May" version. + +&static_label("rem_8bit"); + +&function_begin("gcm_ghash_4bit_mmx"); +{ my ($Zlo,$Zhi) = ("mm7","mm6"); + my $rem_8bit = "esi"; + my $Htbl = "ebx"; + + # parameter block + &mov ("eax",&wparam(0)); # Xi + &mov ("ebx",&wparam(1)); # Htable + &mov ("ecx",&wparam(2)); # inp + &mov ("edx",&wparam(3)); # len + &mov ("ebp","esp"); # original %esp + &call (&label("pic_point")); + &set_label ("pic_point"); + &blindpop ($rem_8bit); + &lea ($rem_8bit,&DWP(&label("rem_8bit")."-".&label("pic_point"),$rem_8bit)); + + &sub ("esp",512+16+16); # allocate stack frame... + &and ("esp",-64); # ...and align it + &sub ("esp",16); # place for (u8)(H[]<<4) + + &add ("edx","ecx"); # pointer to the end of input + &mov (&DWP(528+16+0,"esp"),"eax"); # save Xi + &mov (&DWP(528+16+8,"esp"),"edx"); # save inp+len + &mov (&DWP(528+16+12,"esp"),"ebp"); # save original %esp + + { my @lo = ("mm0","mm1","mm2"); + my @hi = ("mm3","mm4","mm5"); + my @tmp = ("mm6","mm7"); + my ($off1,$off2,$i) = (0,0,); + + &add ($Htbl,128); # optimize for size + &lea ("edi",&DWP(16+128,"esp")); + &lea ("ebp",&DWP(16+256+128,"esp")); + + # decompose Htable (low and high parts are kept separately), + # generate Htable[]>>4, (u8)(Htable[]<<4), save to stack... + for ($i=0;$i<18;$i++) { + + &mov ("edx",&DWP(16*$i+8-128,$Htbl)) if ($i<16); + &movq ($lo[0],&QWP(16*$i+8-128,$Htbl)) if ($i<16); + &psllq ($tmp[1],60) if ($i>1); + &movq ($hi[0],&QWP(16*$i+0-128,$Htbl)) if ($i<16); + &por ($lo[2],$tmp[1]) if ($i>1); + &movq (&QWP($off1-128,"edi"),$lo[1]) if ($i>0 && $i<17); + &psrlq ($lo[1],4) if ($i>0 && $i<17); + &movq (&QWP($off1,"edi"),$hi[1]) if ($i>0 && $i<17); + &movq ($tmp[0],$hi[1]) if ($i>0 && $i<17); + &movq (&QWP($off2-128,"ebp"),$lo[2]) if ($i>1); + &psrlq ($hi[1],4) if ($i>0 && $i<17); + &movq (&QWP($off2,"ebp"),$hi[2]) if ($i>1); + &shl ("edx",4) if ($i<16); + &mov (&BP($i,"esp"),&LB("edx")) if ($i<16); + + unshift (@lo,pop(@lo)); # "rotate" registers + unshift (@hi,pop(@hi)); + unshift (@tmp,pop(@tmp)); + $off1 += 8 if ($i>0); + $off2 += 8 if ($i>1); + } + } + + &movq ($Zhi,&QWP(0,"eax")); + &mov ("ebx",&DWP(8,"eax")); + &mov ("edx",&DWP(12,"eax")); # load Xi + +&set_label("outer",16); + { my $nlo = "eax"; + my $dat = "edx"; + my @nhi = ("edi","ebp"); + my @rem = ("ebx","ecx"); + my @red = ("mm0","mm1","mm2"); + my $tmp = "mm3"; + + &xor ($dat,&DWP(12,"ecx")); # merge input data + &xor ("ebx",&DWP(8,"ecx")); + &pxor ($Zhi,&QWP(0,"ecx")); + &lea ("ecx",&DWP(16,"ecx")); # inp+=16 + #&mov (&DWP(528+12,"esp"),$dat); # save inp^Xi + &mov (&DWP(528+8,"esp"),"ebx"); + &movq (&QWP(528+0,"esp"),$Zhi); + &mov (&DWP(528+16+4,"esp"),"ecx"); # save inp + + &xor ($nlo,$nlo); + &rol ($dat,8); + &mov (&LB($nlo),&LB($dat)); + &mov ($nhi[1],$nlo); + &and (&LB($nlo),0x0f); + &shr ($nhi[1],4); + &pxor ($red[0],$red[0]); + &rol ($dat,8); # next byte + &pxor ($red[1],$red[1]); + &pxor ($red[2],$red[2]); + + # Just like in "May" version modulo-schedule for critical path in + # 'Z.hi ^= rem_8bit[Z.lo&0xff^((u8)H[nhi]<<4)]<<48'. Final 'pxor' + # is scheduled so late that rem_8bit[] has to be shifted *right* + # by 16, which is why last argument to pinsrw is 2, which + # corresponds to <<32=<<48>>16... + for ($j=11,$i=0;$i<15;$i++) { + + if ($i>0) { + &pxor ($Zlo,&QWP(16,"esp",$nlo,8)); # Z^=H[nlo] + &rol ($dat,8); # next byte + &pxor ($Zhi,&QWP(16+128,"esp",$nlo,8)); + + &pxor ($Zlo,$tmp); + &pxor ($Zhi,&QWP(16+256+128,"esp",$nhi[0],8)); + &xor (&LB($rem[1]),&BP(0,"esp",$nhi[0])); # rem^(H[nhi]<<4) + } else { + &movq ($Zlo,&QWP(16,"esp",$nlo,8)); + &movq ($Zhi,&QWP(16+128,"esp",$nlo,8)); + } + + &mov (&LB($nlo),&LB($dat)); + &mov ($dat,&DWP(528+$j,"esp")) if (--$j%4==0); + + &movd ($rem[0],$Zlo); + &movz ($rem[1],&LB($rem[1])) if ($i>0); + &psrlq ($Zlo,8); # Z>>=8 + + &movq ($tmp,$Zhi); + &mov ($nhi[0],$nlo); + &psrlq ($Zhi,8); + + &pxor ($Zlo,&QWP(16+256+0,"esp",$nhi[1],8)); # Z^=H[nhi]>>4 + &and (&LB($nlo),0x0f); + &psllq ($tmp,56); + + &pxor ($Zhi,$red[1]) if ($i>1); + &shr ($nhi[0],4); + &pinsrw ($red[0],&WP(0,$rem_8bit,$rem[1],2),2) if ($i>0); + + unshift (@red,pop(@red)); # "rotate" registers + unshift (@rem,pop(@rem)); + unshift (@nhi,pop(@nhi)); + } + + &pxor ($Zlo,&QWP(16,"esp",$nlo,8)); # Z^=H[nlo] + &pxor ($Zhi,&QWP(16+128,"esp",$nlo,8)); + &xor (&LB($rem[1]),&BP(0,"esp",$nhi[0])); # rem^(H[nhi]<<4) + + &pxor ($Zlo,$tmp); + &pxor ($Zhi,&QWP(16+256+128,"esp",$nhi[0],8)); + &movz ($rem[1],&LB($rem[1])); + + &pxor ($red[2],$red[2]); # clear 2nd word + &psllq ($red[1],4); + + &movd ($rem[0],$Zlo); + &psrlq ($Zlo,4); # Z>>=4 + + &movq ($tmp,$Zhi); + &psrlq ($Zhi,4); + &shl ($rem[0],4); # rem<<4 + + &pxor ($Zlo,&QWP(16,"esp",$nhi[1],8)); # Z^=H[nhi] + &psllq ($tmp,60); + &movz ($rem[0],&LB($rem[0])); + + &pxor ($Zlo,$tmp); + &pxor ($Zhi,&QWP(16+128,"esp",$nhi[1],8)); + + &pinsrw ($red[0],&WP(0,$rem_8bit,$rem[1],2),2); + &pxor ($Zhi,$red[1]); + + &movd ($dat,$Zlo); + &pinsrw ($red[2],&WP(0,$rem_8bit,$rem[0],2),3); # last is <<48 + + &psllq ($red[0],12); # correct by <<16>>4 + &pxor ($Zhi,$red[0]); + &psrlq ($Zlo,32); + &pxor ($Zhi,$red[2]); + + &mov ("ecx",&DWP(528+16+4,"esp")); # restore inp + &movd ("ebx",$Zlo); + &movq ($tmp,$Zhi); # 01234567 + &psllw ($Zhi,8); # 1.3.5.7. + &psrlw ($tmp,8); # .0.2.4.6 + &por ($Zhi,$tmp); # 10325476 + &bswap ($dat); + &pshufw ($Zhi,$Zhi,0b00011011); # 76543210 + &bswap ("ebx"); + + &cmp ("ecx",&DWP(528+16+8,"esp")); # are we done? + &jne (&label("outer")); + } + + &mov ("eax",&DWP(528+16+0,"esp")); # restore Xi + &mov (&DWP(12,"eax"),"edx"); + &mov (&DWP(8,"eax"),"ebx"); + &movq (&QWP(0,"eax"),$Zhi); + + &mov ("esp",&DWP(528+16+12,"esp")); # restore original %esp + &emms (); +} +&function_end("gcm_ghash_4bit_mmx"); +}} + +if ($sse2) {{ +###################################################################### +# PCLMULQDQ version. + +$Xip="eax"; +$Htbl="edx"; +$const="ecx"; +$inp="esi"; +$len="ebx"; + +($Xi,$Xhi)=("xmm0","xmm1"); $Hkey="xmm2"; +($T1,$T2,$T3)=("xmm3","xmm4","xmm5"); +($Xn,$Xhn)=("xmm6","xmm7"); + +&static_label("bswap"); + +sub clmul64x64_T2 { # minimal "register" pressure +my ($Xhi,$Xi,$Hkey,$HK)=@_; + + &movdqa ($Xhi,$Xi); # + &pshufd ($T1,$Xi,0b01001110); + &pshufd ($T2,$Hkey,0b01001110) if (!defined($HK)); + &pxor ($T1,$Xi); # + &pxor ($T2,$Hkey) if (!defined($HK)); + $HK=$T2 if (!defined($HK)); + + &pclmulqdq ($Xi,$Hkey,0x00); ####### + &pclmulqdq ($Xhi,$Hkey,0x11); ####### + &pclmulqdq ($T1,$HK,0x00); ####### + &xorps ($T1,$Xi); # + &xorps ($T1,$Xhi); # + + &movdqa ($T2,$T1); # + &psrldq ($T1,8); + &pslldq ($T2,8); # + &pxor ($Xhi,$T1); + &pxor ($Xi,$T2); # +} + +sub clmul64x64_T3 { +# Even though this subroutine offers visually better ILP, it +# was empirically found to be a tad slower than above version. +# At least in gcm_ghash_clmul context. But it's just as well, +# because loop modulo-scheduling is possible only thanks to +# minimized "register" pressure... +my ($Xhi,$Xi,$Hkey)=@_; + + &movdqa ($T1,$Xi); # + &movdqa ($Xhi,$Xi); + &pclmulqdq ($Xi,$Hkey,0x00); ####### + &pclmulqdq ($Xhi,$Hkey,0x11); ####### + &pshufd ($T2,$T1,0b01001110); # + &pshufd ($T3,$Hkey,0b01001110); + &pxor ($T2,$T1); # + &pxor ($T3,$Hkey); + &pclmulqdq ($T2,$T3,0x00); ####### + &pxor ($T2,$Xi); # + &pxor ($T2,$Xhi); # + + &movdqa ($T3,$T2); # + &psrldq ($T2,8); + &pslldq ($T3,8); # + &pxor ($Xhi,$T2); + &pxor ($Xi,$T3); # +} + +if (1) { # Algorithm 9 with <<1 twist. + # Reduction is shorter and uses only two + # temporary registers, which makes it better + # candidate for interleaving with 64x64 + # multiplication. Pre-modulo-scheduled loop + # was found to be ~20% faster than Algorithm 5 + # below. Algorithm 9 was therefore chosen for + # further optimization... + +sub reduction_alg9 { # 17/11 times faster than Intel version +my ($Xhi,$Xi) = @_; + + # 1st phase + &movdqa ($T2,$Xi); # + &movdqa ($T1,$Xi); + &psllq ($Xi,5); + &pxor ($T1,$Xi); # + &psllq ($Xi,1); + &pxor ($Xi,$T1); # + &psllq ($Xi,57); # + &movdqa ($T1,$Xi); # + &pslldq ($Xi,8); + &psrldq ($T1,8); # + &pxor ($Xi,$T2); + &pxor ($Xhi,$T1); # + + # 2nd phase + &movdqa ($T2,$Xi); + &psrlq ($Xi,1); + &pxor ($Xhi,$T2); # + &pxor ($T2,$Xi); + &psrlq ($Xi,5); + &pxor ($Xi,$T2); # + &psrlq ($Xi,1); # + &pxor ($Xi,$Xhi) # +} + +&function_begin_B("gcm_init_clmul"); + &mov ($Htbl,&wparam(0)); + &mov ($Xip,&wparam(1)); + + &call (&label("pic")); +&set_label("pic"); + &blindpop ($const); + &lea ($const,&DWP(&label("bswap")."-".&label("pic"),$const)); + + &movdqu ($Hkey,&QWP(0,$Xip)); + &pshufd ($Hkey,$Hkey,0b01001110);# dword swap + + # <<1 twist + &pshufd ($T2,$Hkey,0b11111111); # broadcast uppermost dword + &movdqa ($T1,$Hkey); + &psllq ($Hkey,1); + &pxor ($T3,$T3); # + &psrlq ($T1,63); + &pcmpgtd ($T3,$T2); # broadcast carry bit + &pslldq ($T1,8); + &por ($Hkey,$T1); # H<<=1 + + # magic reduction + &pand ($T3,&QWP(16,$const)); # 0x1c2_polynomial + &pxor ($Hkey,$T3); # if(carry) H^=0x1c2_polynomial + + # calculate H^2 + &movdqa ($Xi,$Hkey); + &clmul64x64_T2 ($Xhi,$Xi,$Hkey); + &reduction_alg9 ($Xhi,$Xi); + + &pshufd ($T1,$Hkey,0b01001110); + &pshufd ($T2,$Xi,0b01001110); + &pxor ($T1,$Hkey); # Karatsuba pre-processing + &movdqu (&QWP(0,$Htbl),$Hkey); # save H + &pxor ($T2,$Xi); # Karatsuba pre-processing + &movdqu (&QWP(16,$Htbl),$Xi); # save H^2 + &palignr ($T2,$T1,8); # low part is H.lo^H.hi + &movdqu (&QWP(32,$Htbl),$T2); # save Karatsuba "salt" + + &ret (); +&function_end_B("gcm_init_clmul"); + +&function_begin_B("gcm_gmult_clmul"); + &mov ($Xip,&wparam(0)); + &mov ($Htbl,&wparam(1)); + + &call (&label("pic")); +&set_label("pic"); + &blindpop ($const); + &lea ($const,&DWP(&label("bswap")."-".&label("pic"),$const)); + + &movdqu ($Xi,&QWP(0,$Xip)); + &movdqa ($T3,&QWP(0,$const)); + &movups ($Hkey,&QWP(0,$Htbl)); + &pshufb ($Xi,$T3); + &movups ($T2,&QWP(32,$Htbl)); + + &clmul64x64_T2 ($Xhi,$Xi,$Hkey,$T2); + &reduction_alg9 ($Xhi,$Xi); + + &pshufb ($Xi,$T3); + &movdqu (&QWP(0,$Xip),$Xi); + + &ret (); +&function_end_B("gcm_gmult_clmul"); + +&function_begin("gcm_ghash_clmul"); + &mov ($Xip,&wparam(0)); + &mov ($Htbl,&wparam(1)); + &mov ($inp,&wparam(2)); + &mov ($len,&wparam(3)); + + &call (&label("pic")); +&set_label("pic"); + &blindpop ($const); + &lea ($const,&DWP(&label("bswap")."-".&label("pic"),$const)); + + &movdqu ($Xi,&QWP(0,$Xip)); + &movdqa ($T3,&QWP(0,$const)); + &movdqu ($Hkey,&QWP(0,$Htbl)); + &pshufb ($Xi,$T3); + + &sub ($len,0x10); + &jz (&label("odd_tail")); + + ####### + # Xi+2 =[H*(Ii+1 + Xi+1)] mod P = + # [(H*Ii+1) + (H*Xi+1)] mod P = + # [(H*Ii+1) + H^2*(Ii+Xi)] mod P + # + &movdqu ($T1,&QWP(0,$inp)); # Ii + &movdqu ($Xn,&QWP(16,$inp)); # Ii+1 + &pshufb ($T1,$T3); + &pshufb ($Xn,$T3); + &movdqu ($T3,&QWP(32,$Htbl)); + &pxor ($Xi,$T1); # Ii+Xi + + &pshufd ($T1,$Xn,0b01001110); # H*Ii+1 + &movdqa ($Xhn,$Xn); + &pxor ($T1,$Xn); # + &lea ($inp,&DWP(32,$inp)); # i+=2 + + &pclmulqdq ($Xn,$Hkey,0x00); ####### + &pclmulqdq ($Xhn,$Hkey,0x11); ####### + &pclmulqdq ($T1,$T3,0x00); ####### + &movups ($Hkey,&QWP(16,$Htbl)); # load H^2 + &nop (); + + &sub ($len,0x20); + &jbe (&label("even_tail")); + &jmp (&label("mod_loop")); + +&set_label("mod_loop",32); + &pshufd ($T2,$Xi,0b01001110); # H^2*(Ii+Xi) + &movdqa ($Xhi,$Xi); + &pxor ($T2,$Xi); # + &nop (); + + &pclmulqdq ($Xi,$Hkey,0x00); ####### + &pclmulqdq ($Xhi,$Hkey,0x11); ####### + &pclmulqdq ($T2,$T3,0x10); ####### + &movups ($Hkey,&QWP(0,$Htbl)); # load H + + &xorps ($Xi,$Xn); # (H*Ii+1) + H^2*(Ii+Xi) + &movdqa ($T3,&QWP(0,$const)); + &xorps ($Xhi,$Xhn); + &movdqu ($Xhn,&QWP(0,$inp)); # Ii + &pxor ($T1,$Xi); # aggregated Karatsuba post-processing + &movdqu ($Xn,&QWP(16,$inp)); # Ii+1 + &pxor ($T1,$Xhi); # + + &pshufb ($Xhn,$T3); + &pxor ($T2,$T1); # + + &movdqa ($T1,$T2); # + &psrldq ($T2,8); + &pslldq ($T1,8); # + &pxor ($Xhi,$T2); + &pxor ($Xi,$T1); # + &pshufb ($Xn,$T3); + &pxor ($Xhi,$Xhn); # "Ii+Xi", consume early + + &movdqa ($Xhn,$Xn); #&clmul64x64_TX ($Xhn,$Xn,$Hkey); H*Ii+1 + &movdqa ($T2,$Xi); #&reduction_alg9($Xhi,$Xi); 1st phase + &movdqa ($T1,$Xi); + &psllq ($Xi,5); + &pxor ($T1,$Xi); # + &psllq ($Xi,1); + &pxor ($Xi,$T1); # + &pclmulqdq ($Xn,$Hkey,0x00); ####### + &movups ($T3,&QWP(32,$Htbl)); + &psllq ($Xi,57); # + &movdqa ($T1,$Xi); # + &pslldq ($Xi,8); + &psrldq ($T1,8); # + &pxor ($Xi,$T2); + &pxor ($Xhi,$T1); # + &pshufd ($T1,$Xhn,0b01001110); + &movdqa ($T2,$Xi); # 2nd phase + &psrlq ($Xi,1); + &pxor ($T1,$Xhn); + &pxor ($Xhi,$T2); # + &pclmulqdq ($Xhn,$Hkey,0x11); ####### + &movups ($Hkey,&QWP(16,$Htbl)); # load H^2 + &pxor ($T2,$Xi); + &psrlq ($Xi,5); + &pxor ($Xi,$T2); # + &psrlq ($Xi,1); # + &pxor ($Xi,$Xhi) # + &pclmulqdq ($T1,$T3,0x00); ####### + + &lea ($inp,&DWP(32,$inp)); + &sub ($len,0x20); + &ja (&label("mod_loop")); + +&set_label("even_tail"); + &pshufd ($T2,$Xi,0b01001110); # H^2*(Ii+Xi) + &movdqa ($Xhi,$Xi); + &pxor ($T2,$Xi); # + + &pclmulqdq ($Xi,$Hkey,0x00); ####### + &pclmulqdq ($Xhi,$Hkey,0x11); ####### + &pclmulqdq ($T2,$T3,0x10); ####### + &movdqa ($T3,&QWP(0,$const)); + + &xorps ($Xi,$Xn); # (H*Ii+1) + H^2*(Ii+Xi) + &xorps ($Xhi,$Xhn); + &pxor ($T1,$Xi); # aggregated Karatsuba post-processing + &pxor ($T1,$Xhi); # + + &pxor ($T2,$T1); # + + &movdqa ($T1,$T2); # + &psrldq ($T2,8); + &pslldq ($T1,8); # + &pxor ($Xhi,$T2); + &pxor ($Xi,$T1); # + + &reduction_alg9 ($Xhi,$Xi); + + &test ($len,$len); + &jnz (&label("done")); + + &movups ($Hkey,&QWP(0,$Htbl)); # load H +&set_label("odd_tail"); + &movdqu ($T1,&QWP(0,$inp)); # Ii + &pshufb ($T1,$T3); + &pxor ($Xi,$T1); # Ii+Xi + + &clmul64x64_T2 ($Xhi,$Xi,$Hkey); # H*(Ii+Xi) + &reduction_alg9 ($Xhi,$Xi); + +&set_label("done"); + &pshufb ($Xi,$T3); + &movdqu (&QWP(0,$Xip),$Xi); +&function_end("gcm_ghash_clmul"); + +} else { # Algorithm 5. Kept for reference purposes. + +sub reduction_alg5 { # 19/16 times faster than Intel version +my ($Xhi,$Xi)=@_; + + # <<1 + &movdqa ($T1,$Xi); # + &movdqa ($T2,$Xhi); + &pslld ($Xi,1); + &pslld ($Xhi,1); # + &psrld ($T1,31); + &psrld ($T2,31); # + &movdqa ($T3,$T1); + &pslldq ($T1,4); + &psrldq ($T3,12); # + &pslldq ($T2,4); + &por ($Xhi,$T3); # + &por ($Xi,$T1); + &por ($Xhi,$T2); # + + # 1st phase + &movdqa ($T1,$Xi); + &movdqa ($T2,$Xi); + &movdqa ($T3,$Xi); # + &pslld ($T1,31); + &pslld ($T2,30); + &pslld ($Xi,25); # + &pxor ($T1,$T2); + &pxor ($T1,$Xi); # + &movdqa ($T2,$T1); # + &pslldq ($T1,12); + &psrldq ($T2,4); # + &pxor ($T3,$T1); + + # 2nd phase + &pxor ($Xhi,$T3); # + &movdqa ($Xi,$T3); + &movdqa ($T1,$T3); + &psrld ($Xi,1); # + &psrld ($T1,2); + &psrld ($T3,7); # + &pxor ($Xi,$T1); + &pxor ($Xhi,$T2); + &pxor ($Xi,$T3); # + &pxor ($Xi,$Xhi); # +} + +&function_begin_B("gcm_init_clmul"); + &mov ($Htbl,&wparam(0)); + &mov ($Xip,&wparam(1)); + + &call (&label("pic")); +&set_label("pic"); + &blindpop ($const); + &lea ($const,&DWP(&label("bswap")."-".&label("pic"),$const)); + + &movdqu ($Hkey,&QWP(0,$Xip)); + &pshufd ($Hkey,$Hkey,0b01001110);# dword swap + + # calculate H^2 + &movdqa ($Xi,$Hkey); + &clmul64x64_T3 ($Xhi,$Xi,$Hkey); + &reduction_alg5 ($Xhi,$Xi); + + &movdqu (&QWP(0,$Htbl),$Hkey); # save H + &movdqu (&QWP(16,$Htbl),$Xi); # save H^2 + + &ret (); +&function_end_B("gcm_init_clmul"); + +&function_begin_B("gcm_gmult_clmul"); + &mov ($Xip,&wparam(0)); + &mov ($Htbl,&wparam(1)); + + &call (&label("pic")); +&set_label("pic"); + &blindpop ($const); + &lea ($const,&DWP(&label("bswap")."-".&label("pic"),$const)); + + &movdqu ($Xi,&QWP(0,$Xip)); + &movdqa ($Xn,&QWP(0,$const)); + &movdqu ($Hkey,&QWP(0,$Htbl)); + &pshufb ($Xi,$Xn); + + &clmul64x64_T3 ($Xhi,$Xi,$Hkey); + &reduction_alg5 ($Xhi,$Xi); + + &pshufb ($Xi,$Xn); + &movdqu (&QWP(0,$Xip),$Xi); + + &ret (); +&function_end_B("gcm_gmult_clmul"); + +&function_begin("gcm_ghash_clmul"); + &mov ($Xip,&wparam(0)); + &mov ($Htbl,&wparam(1)); + &mov ($inp,&wparam(2)); + &mov ($len,&wparam(3)); + + &call (&label("pic")); +&set_label("pic"); + &blindpop ($const); + &lea ($const,&DWP(&label("bswap")."-".&label("pic"),$const)); + + &movdqu ($Xi,&QWP(0,$Xip)); + &movdqa ($T3,&QWP(0,$const)); + &movdqu ($Hkey,&QWP(0,$Htbl)); + &pshufb ($Xi,$T3); + + &sub ($len,0x10); + &jz (&label("odd_tail")); + + ####### + # Xi+2 =[H*(Ii+1 + Xi+1)] mod P = + # [(H*Ii+1) + (H*Xi+1)] mod P = + # [(H*Ii+1) + H^2*(Ii+Xi)] mod P + # + &movdqu ($T1,&QWP(0,$inp)); # Ii + &movdqu ($Xn,&QWP(16,$inp)); # Ii+1 + &pshufb ($T1,$T3); + &pshufb ($Xn,$T3); + &pxor ($Xi,$T1); # Ii+Xi + + &clmul64x64_T3 ($Xhn,$Xn,$Hkey); # H*Ii+1 + &movdqu ($Hkey,&QWP(16,$Htbl)); # load H^2 + + &sub ($len,0x20); + &lea ($inp,&DWP(32,$inp)); # i+=2 + &jbe (&label("even_tail")); + +&set_label("mod_loop"); + &clmul64x64_T3 ($Xhi,$Xi,$Hkey); # H^2*(Ii+Xi) + &movdqu ($Hkey,&QWP(0,$Htbl)); # load H + + &pxor ($Xi,$Xn); # (H*Ii+1) + H^2*(Ii+Xi) + &pxor ($Xhi,$Xhn); + + &reduction_alg5 ($Xhi,$Xi); + + ####### + &movdqa ($T3,&QWP(0,$const)); + &movdqu ($T1,&QWP(0,$inp)); # Ii + &movdqu ($Xn,&QWP(16,$inp)); # Ii+1 + &pshufb ($T1,$T3); + &pshufb ($Xn,$T3); + &pxor ($Xi,$T1); # Ii+Xi + + &clmul64x64_T3 ($Xhn,$Xn,$Hkey); # H*Ii+1 + &movdqu ($Hkey,&QWP(16,$Htbl)); # load H^2 + + &sub ($len,0x20); + &lea ($inp,&DWP(32,$inp)); + &ja (&label("mod_loop")); + +&set_label("even_tail"); + &clmul64x64_T3 ($Xhi,$Xi,$Hkey); # H^2*(Ii+Xi) + + &pxor ($Xi,$Xn); # (H*Ii+1) + H^2*(Ii+Xi) + &pxor ($Xhi,$Xhn); + + &reduction_alg5 ($Xhi,$Xi); + + &movdqa ($T3,&QWP(0,$const)); + &test ($len,$len); + &jnz (&label("done")); + + &movdqu ($Hkey,&QWP(0,$Htbl)); # load H +&set_label("odd_tail"); + &movdqu ($T1,&QWP(0,$inp)); # Ii + &pshufb ($T1,$T3); + &pxor ($Xi,$T1); # Ii+Xi + + &clmul64x64_T3 ($Xhi,$Xi,$Hkey); # H*(Ii+Xi) + &reduction_alg5 ($Xhi,$Xi); + + &movdqa ($T3,&QWP(0,$const)); +&set_label("done"); + &pshufb ($Xi,$T3); + &movdqu (&QWP(0,$Xip),$Xi); +&function_end("gcm_ghash_clmul"); + +} + +&set_label("bswap",64); + &data_byte(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0); + &data_byte(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc2); # 0x1c2_polynomial +&set_label("rem_8bit",64); + &data_short(0x0000,0x01C2,0x0384,0x0246,0x0708,0x06CA,0x048C,0x054E); + &data_short(0x0E10,0x0FD2,0x0D94,0x0C56,0x0918,0x08DA,0x0A9C,0x0B5E); + &data_short(0x1C20,0x1DE2,0x1FA4,0x1E66,0x1B28,0x1AEA,0x18AC,0x196E); + &data_short(0x1230,0x13F2,0x11B4,0x1076,0x1538,0x14FA,0x16BC,0x177E); + &data_short(0x3840,0x3982,0x3BC4,0x3A06,0x3F48,0x3E8A,0x3CCC,0x3D0E); + &data_short(0x3650,0x3792,0x35D4,0x3416,0x3158,0x309A,0x32DC,0x331E); + &data_short(0x2460,0x25A2,0x27E4,0x2626,0x2368,0x22AA,0x20EC,0x212E); + &data_short(0x2A70,0x2BB2,0x29F4,0x2836,0x2D78,0x2CBA,0x2EFC,0x2F3E); + &data_short(0x7080,0x7142,0x7304,0x72C6,0x7788,0x764A,0x740C,0x75CE); + &data_short(0x7E90,0x7F52,0x7D14,0x7CD6,0x7998,0x785A,0x7A1C,0x7BDE); + &data_short(0x6CA0,0x6D62,0x6F24,0x6EE6,0x6BA8,0x6A6A,0x682C,0x69EE); + &data_short(0x62B0,0x6372,0x6134,0x60F6,0x65B8,0x647A,0x663C,0x67FE); + &data_short(0x48C0,0x4902,0x4B44,0x4A86,0x4FC8,0x4E0A,0x4C4C,0x4D8E); + &data_short(0x46D0,0x4712,0x4554,0x4496,0x41D8,0x401A,0x425C,0x439E); + &data_short(0x54E0,0x5522,0x5764,0x56A6,0x53E8,0x522A,0x506C,0x51AE); + &data_short(0x5AF0,0x5B32,0x5974,0x58B6,0x5DF8,0x5C3A,0x5E7C,0x5FBE); + &data_short(0xE100,0xE0C2,0xE284,0xE346,0xE608,0xE7CA,0xE58C,0xE44E); + &data_short(0xEF10,0xEED2,0xEC94,0xED56,0xE818,0xE9DA,0xEB9C,0xEA5E); + &data_short(0xFD20,0xFCE2,0xFEA4,0xFF66,0xFA28,0xFBEA,0xF9AC,0xF86E); + &data_short(0xF330,0xF2F2,0xF0B4,0xF176,0xF438,0xF5FA,0xF7BC,0xF67E); + &data_short(0xD940,0xD882,0xDAC4,0xDB06,0xDE48,0xDF8A,0xDDCC,0xDC0E); + &data_short(0xD750,0xD692,0xD4D4,0xD516,0xD058,0xD19A,0xD3DC,0xD21E); + &data_short(0xC560,0xC4A2,0xC6E4,0xC726,0xC268,0xC3AA,0xC1EC,0xC02E); + &data_short(0xCB70,0xCAB2,0xC8F4,0xC936,0xCC78,0xCDBA,0xCFFC,0xCE3E); + &data_short(0x9180,0x9042,0x9204,0x93C6,0x9688,0x974A,0x950C,0x94CE); + &data_short(0x9F90,0x9E52,0x9C14,0x9DD6,0x9898,0x995A,0x9B1C,0x9ADE); + &data_short(0x8DA0,0x8C62,0x8E24,0x8FE6,0x8AA8,0x8B6A,0x892C,0x88EE); + &data_short(0x83B0,0x8272,0x8034,0x81F6,0x84B8,0x857A,0x873C,0x86FE); + &data_short(0xA9C0,0xA802,0xAA44,0xAB86,0xAEC8,0xAF0A,0xAD4C,0xAC8E); + &data_short(0xA7D0,0xA612,0xA454,0xA596,0xA0D8,0xA11A,0xA35C,0xA29E); + &data_short(0xB5E0,0xB422,0xB664,0xB7A6,0xB2E8,0xB32A,0xB16C,0xB0AE); + &data_short(0xBBF0,0xBA32,0xB874,0xB9B6,0xBCF8,0xBD3A,0xBF7C,0xBEBE); +}} # $sse2 + +&set_label("rem_4bit",64); + &data_word(0,0x0000<<$S,0,0x1C20<<$S,0,0x3840<<$S,0,0x2460<<$S); + &data_word(0,0x7080<<$S,0,0x6CA0<<$S,0,0x48C0<<$S,0,0x54E0<<$S); + &data_word(0,0xE100<<$S,0,0xFD20<<$S,0,0xD940<<$S,0,0xC560<<$S); + &data_word(0,0x9180<<$S,0,0x8DA0<<$S,0,0xA9C0<<$S,0,0xB5E0<<$S); +}}} # !$x86only + +&asciz("GHASH for x86, CRYPTOGAMS by "); +&asm_finish(); + +close STDOUT; + +# A question was risen about choice of vanilla MMX. Or rather why wasn't +# SSE2 chosen instead? In addition to the fact that MMX runs on legacy +# CPUs such as PIII, "4-bit" MMX version was observed to provide better +# performance than *corresponding* SSE2 one even on contemporary CPUs. +# SSE2 results were provided by Peter-Michael Hager. He maintains SSE2 +# implementation featuring full range of lookup-table sizes, but with +# per-invocation lookup table setup. Latter means that table size is +# chosen depending on how much data is to be hashed in every given call, +# more data - larger table. Best reported result for Core2 is ~4 cycles +# per processed byte out of 64KB block. This number accounts even for +# 64KB table setup overhead. As discussed in gcm128.c we choose to be +# more conservative in respect to lookup table sizes, but how do the +# results compare? Minimalistic "256B" MMX version delivers ~11 cycles +# on same platform. As also discussed in gcm128.c, next in line "8-bit +# Shoup's" or "4KB" method should deliver twice the performance of +# "256B" one, in other words not worse than ~6 cycles per byte. It +# should be also be noted that in SSE2 case improvement can be "super- +# linear," i.e. more than twice, mostly because >>8 maps to single +# instruction on SSE2 register. This is unlike "4-bit" case when >>4 +# maps to same amount of instructions in both MMX and SSE2 cases. +# Bottom line is that switch to SSE2 is considered to be justifiable +# only in case we choose to implement "8-bit" method... diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-x86_64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-x86_64.pl new file mode 100644 index 000000000..30158aa07 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghash-x86_64.pl @@ -0,0 +1,1816 @@ +#! /usr/bin/env perl +# Copyright 2010-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# March, June 2010 +# +# The module implements "4-bit" GCM GHASH function and underlying +# single multiplication operation in GF(2^128). "4-bit" means that +# it uses 256 bytes per-key table [+128 bytes shared table]. GHASH +# function features so called "528B" variant utilizing additional +# 256+16 bytes of per-key storage [+512 bytes shared table]. +# Performance results are for this streamed GHASH subroutine and are +# expressed in cycles per processed byte, less is better: +# +# gcc 3.4.x(*) assembler +# +# P4 28.6 14.0 +100% +# Opteron 19.3 7.7 +150% +# Core2 17.8 8.1(**) +120% +# Atom 31.6 16.8 +88% +# VIA Nano 21.8 10.1 +115% +# +# (*) comparison is not completely fair, because C results are +# for vanilla "256B" implementation, while assembler results +# are for "528B";-) +# (**) it's mystery [to me] why Core2 result is not same as for +# Opteron; + +# May 2010 +# +# Add PCLMULQDQ version performing at 2.02 cycles per processed byte. +# See ghash-x86.pl for background information and details about coding +# techniques. +# +# Special thanks to David Woodhouse for providing access to a +# Westmere-based system on behalf of Intel Open Source Technology Centre. + +# December 2012 +# +# Overhaul: aggregate Karatsuba post-processing, improve ILP in +# reduction_alg9, increase reduction aggregate factor to 4x. As for +# the latter. ghash-x86.pl discusses that it makes lesser sense to +# increase aggregate factor. Then why increase here? Critical path +# consists of 3 independent pclmulqdq instructions, Karatsuba post- +# processing and reduction. "On top" of this we lay down aggregated +# multiplication operations, triplets of independent pclmulqdq's. As +# issue rate for pclmulqdq is limited, it makes lesser sense to +# aggregate more multiplications than it takes to perform remaining +# non-multiplication operations. 2x is near-optimal coefficient for +# contemporary Intel CPUs (therefore modest improvement coefficient), +# but not for Bulldozer. Latter is because logical SIMD operations +# are twice as slow in comparison to Intel, so that critical path is +# longer. A CPU with higher pclmulqdq issue rate would also benefit +# from higher aggregate factor... +# +# Westmere 1.78(+13%) +# Sandy Bridge 1.80(+8%) +# Ivy Bridge 1.80(+7%) +# Haswell 0.55(+93%) (if system doesn't support AVX) +# Broadwell 0.45(+110%)(if system doesn't support AVX) +# Skylake 0.44(+110%)(if system doesn't support AVX) +# Bulldozer 1.49(+27%) +# Silvermont 2.88(+13%) +# Knights L 2.12(-) (if system doesn't support AVX) +# Goldmont 1.08(+24%) + +# March 2013 +# +# ... 8x aggregate factor AVX code path is using reduction algorithm +# suggested by Shay Gueron[1]. Even though contemporary AVX-capable +# CPUs such as Sandy and Ivy Bridge can execute it, the code performs +# sub-optimally in comparison to above mentioned version. But thanks +# to Ilya Albrekht and Max Locktyukhin of Intel Corp. we knew that +# it performs in 0.41 cycles per byte on Haswell processor, in +# 0.29 on Broadwell, and in 0.36 on Skylake. +# +# Knights Landing achieves 1.09 cpb. +# +# [1] http://rt.openssl.org/Ticket/Display.html?id=2900&user=guest&pass=guest + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler version ([2-9]\.[0-9]+)/) { + $avx = ($1>=2.20) + ($1>=2.22); +} + +if (!$avx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) && + `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) { + $avx = ($1>=2.09) + ($1>=2.10); +} + +if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && + `ml64 2>&1` =~ /Version ([0-9]+)\./) { + $avx = ($1>=10) + ($1>=11); +} + +if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9]\.[0-9]+)/) { + $avx = ($2>=3.0) + ($2>3.0); +} + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +*STDOUT=*OUT; + +$do4xaggr=1; + +# common register layout +$nlo="%rax"; +$nhi="%rbx"; +$Zlo="%r8"; +$Zhi="%r9"; +$tmp="%r10"; +$rem_4bit = "%r11"; + +$Xi="%rdi"; +$Htbl="%rsi"; + +# per-function register layout +$cnt="%rcx"; +$rem="%rdx"; + +sub LB() { my $r=shift; $r =~ s/%[er]([a-d])x/%\1l/ or + $r =~ s/%[er]([sd]i)/%\1l/ or + $r =~ s/%[er](bp)/%\1l/ or + $r =~ s/%(r[0-9]+)[d]?/%\1b/; $r; } + +sub AUTOLOAD() # thunk [simplified] 32-bit style perlasm +{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; + my $arg = pop; + $arg = "\$$arg" if ($arg*1 eq $arg); + $code .= "\t$opcode\t".join(',',$arg,reverse @_)."\n"; +} + +{ my $N; + sub loop() { + my $inp = shift; + + $N++; +$code.=<<___; + xor $nlo,$nlo + xor $nhi,$nhi + mov `&LB("$Zlo")`,`&LB("$nlo")` + mov `&LB("$Zlo")`,`&LB("$nhi")` + shl \$4,`&LB("$nlo")` + mov \$14,$cnt + mov 8($Htbl,$nlo),$Zlo + mov ($Htbl,$nlo),$Zhi + and \$0xf0,`&LB("$nhi")` + mov $Zlo,$rem + jmp .Loop$N + +.align 16 +.Loop$N: + shr \$4,$Zlo + and \$0xf,$rem + mov $Zhi,$tmp + mov ($inp,$cnt),`&LB("$nlo")` + shr \$4,$Zhi + xor 8($Htbl,$nhi),$Zlo + shl \$60,$tmp + xor ($Htbl,$nhi),$Zhi + mov `&LB("$nlo")`,`&LB("$nhi")` + xor ($rem_4bit,$rem,8),$Zhi + mov $Zlo,$rem + shl \$4,`&LB("$nlo")` + xor $tmp,$Zlo + dec $cnt + js .Lbreak$N + + shr \$4,$Zlo + and \$0xf,$rem + mov $Zhi,$tmp + shr \$4,$Zhi + xor 8($Htbl,$nlo),$Zlo + shl \$60,$tmp + xor ($Htbl,$nlo),$Zhi + and \$0xf0,`&LB("$nhi")` + xor ($rem_4bit,$rem,8),$Zhi + mov $Zlo,$rem + xor $tmp,$Zlo + jmp .Loop$N + +.align 16 +.Lbreak$N: + shr \$4,$Zlo + and \$0xf,$rem + mov $Zhi,$tmp + shr \$4,$Zhi + xor 8($Htbl,$nlo),$Zlo + shl \$60,$tmp + xor ($Htbl,$nlo),$Zhi + and \$0xf0,`&LB("$nhi")` + xor ($rem_4bit,$rem,8),$Zhi + mov $Zlo,$rem + xor $tmp,$Zlo + + shr \$4,$Zlo + and \$0xf,$rem + mov $Zhi,$tmp + shr \$4,$Zhi + xor 8($Htbl,$nhi),$Zlo + shl \$60,$tmp + xor ($Htbl,$nhi),$Zhi + xor $tmp,$Zlo + xor ($rem_4bit,$rem,8),$Zhi + + bswap $Zlo + bswap $Zhi +___ +}} + +$code=<<___; +.text +.extern OPENSSL_ia32cap_P + +.globl gcm_gmult_4bit +.type gcm_gmult_4bit,\@function,2 +.align 16 +gcm_gmult_4bit: +.cfi_startproc + push %rbx +.cfi_push %rbx + push %rbp # %rbp and others are pushed exclusively in +.cfi_push %rbp + push %r12 # order to reuse Win64 exception handler... +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + sub \$280,%rsp +.cfi_adjust_cfa_offset 280 +.Lgmult_prologue: + + movzb 15($Xi),$Zlo + lea .Lrem_4bit(%rip),$rem_4bit +___ + &loop ($Xi); +$code.=<<___; + mov $Zlo,8($Xi) + mov $Zhi,($Xi) + + lea 280+48(%rsp),%rsi +.cfi_def_cfa %rsi,8 + mov -8(%rsi),%rbx +.cfi_restore %rbx + lea (%rsi),%rsp +.cfi_def_cfa_register %rsp +.Lgmult_epilogue: + ret +.cfi_endproc +.size gcm_gmult_4bit,.-gcm_gmult_4bit +___ + +# per-function register layout +$inp="%rdx"; +$len="%rcx"; +$rem_8bit=$rem_4bit; + +$code.=<<___; +.globl gcm_ghash_4bit +.type gcm_ghash_4bit,\@function,4 +.align 16 +gcm_ghash_4bit: +.cfi_startproc + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + sub \$280,%rsp +.cfi_adjust_cfa_offset 280 +.Lghash_prologue: + mov $inp,%r14 # reassign couple of args + mov $len,%r15 +___ +{ my $inp="%r14"; + my $dat="%edx"; + my $len="%r15"; + my @nhi=("%ebx","%ecx"); + my @rem=("%r12","%r13"); + my $Hshr4="%rbp"; + + &sub ($Htbl,-128); # size optimization + &lea ($Hshr4,"16+128(%rsp)"); + { my @lo =($nlo,$nhi); + my @hi =($Zlo,$Zhi); + + &xor ($dat,$dat); + for ($i=0,$j=-2;$i<18;$i++,$j++) { + &mov ("$j(%rsp)",&LB($dat)) if ($i>1); + &or ($lo[0],$tmp) if ($i>1); + &mov (&LB($dat),&LB($lo[1])) if ($i>0 && $i<17); + &shr ($lo[1],4) if ($i>0 && $i<17); + &mov ($tmp,$hi[1]) if ($i>0 && $i<17); + &shr ($hi[1],4) if ($i>0 && $i<17); + &mov ("8*$j($Hshr4)",$hi[0]) if ($i>1); + &mov ($hi[0],"16*$i+0-128($Htbl)") if ($i<16); + &shl (&LB($dat),4) if ($i>0 && $i<17); + &mov ("8*$j-128($Hshr4)",$lo[0]) if ($i>1); + &mov ($lo[0],"16*$i+8-128($Htbl)") if ($i<16); + &shl ($tmp,60) if ($i>0 && $i<17); + + push (@lo,shift(@lo)); + push (@hi,shift(@hi)); + } + } + &add ($Htbl,-128); + &mov ($Zlo,"8($Xi)"); + &mov ($Zhi,"0($Xi)"); + &add ($len,$inp); # pointer to the end of data + &lea ($rem_8bit,".Lrem_8bit(%rip)"); + &jmp (".Louter_loop"); + +$code.=".align 16\n.Louter_loop:\n"; + &xor ($Zhi,"($inp)"); + &mov ("%rdx","8($inp)"); + &lea ($inp,"16($inp)"); + &xor ("%rdx",$Zlo); + &mov ("($Xi)",$Zhi); + &mov ("8($Xi)","%rdx"); + &shr ("%rdx",32); + + &xor ($nlo,$nlo); + &rol ($dat,8); + &mov (&LB($nlo),&LB($dat)); + &movz ($nhi[0],&LB($dat)); + &shl (&LB($nlo),4); + &shr ($nhi[0],4); + + for ($j=11,$i=0;$i<15;$i++) { + &rol ($dat,8); + &xor ($Zlo,"8($Htbl,$nlo)") if ($i>0); + &xor ($Zhi,"($Htbl,$nlo)") if ($i>0); + &mov ($Zlo,"8($Htbl,$nlo)") if ($i==0); + &mov ($Zhi,"($Htbl,$nlo)") if ($i==0); + + &mov (&LB($nlo),&LB($dat)); + &xor ($Zlo,$tmp) if ($i>0); + &movzw ($rem[1],"($rem_8bit,$rem[1],2)") if ($i>0); + + &movz ($nhi[1],&LB($dat)); + &shl (&LB($nlo),4); + &movzb ($rem[0],"(%rsp,$nhi[0])"); + + &shr ($nhi[1],4) if ($i<14); + &and ($nhi[1],0xf0) if ($i==14); + &shl ($rem[1],48) if ($i>0); + &xor ($rem[0],$Zlo); + + &mov ($tmp,$Zhi); + &xor ($Zhi,$rem[1]) if ($i>0); + &shr ($Zlo,8); + + &movz ($rem[0],&LB($rem[0])); + &mov ($dat,"$j($Xi)") if (--$j%4==0); + &shr ($Zhi,8); + + &xor ($Zlo,"-128($Hshr4,$nhi[0],8)"); + &shl ($tmp,56); + &xor ($Zhi,"($Hshr4,$nhi[0],8)"); + + unshift (@nhi,pop(@nhi)); # "rotate" registers + unshift (@rem,pop(@rem)); + } + &movzw ($rem[1],"($rem_8bit,$rem[1],2)"); + &xor ($Zlo,"8($Htbl,$nlo)"); + &xor ($Zhi,"($Htbl,$nlo)"); + + &shl ($rem[1],48); + &xor ($Zlo,$tmp); + + &xor ($Zhi,$rem[1]); + &movz ($rem[0],&LB($Zlo)); + &shr ($Zlo,4); + + &mov ($tmp,$Zhi); + &shl (&LB($rem[0]),4); + &shr ($Zhi,4); + + &xor ($Zlo,"8($Htbl,$nhi[0])"); + &movzw ($rem[0],"($rem_8bit,$rem[0],2)"); + &shl ($tmp,60); + + &xor ($Zhi,"($Htbl,$nhi[0])"); + &xor ($Zlo,$tmp); + &shl ($rem[0],48); + + &bswap ($Zlo); + &xor ($Zhi,$rem[0]); + + &bswap ($Zhi); + &cmp ($inp,$len); + &jb (".Louter_loop"); +} +$code.=<<___; + mov $Zlo,8($Xi) + mov $Zhi,($Xi) + + lea 280+48(%rsp),%rsi +.cfi_def_cfa %rsi,8 + mov -48(%rsi),%r15 +.cfi_restore %r15 + mov -40(%rsi),%r14 +.cfi_restore %r14 + mov -32(%rsi),%r13 +.cfi_restore %r13 + mov -24(%rsi),%r12 +.cfi_restore %r12 + mov -16(%rsi),%rbp +.cfi_restore %rbp + mov -8(%rsi),%rbx +.cfi_restore %rbx + lea 0(%rsi),%rsp +.cfi_def_cfa_register %rsp +.Lghash_epilogue: + ret +.cfi_endproc +.size gcm_ghash_4bit,.-gcm_ghash_4bit +___ + +###################################################################### +# PCLMULQDQ version. + +@_4args=$win64? ("%rcx","%rdx","%r8", "%r9") : # Win64 order + ("%rdi","%rsi","%rdx","%rcx"); # Unix order + +($Xi,$Xhi)=("%xmm0","%xmm1"); $Hkey="%xmm2"; +($T1,$T2,$T3)=("%xmm3","%xmm4","%xmm5"); + +sub clmul64x64_T2 { # minimal register pressure +my ($Xhi,$Xi,$Hkey,$HK)=@_; + +if (!defined($HK)) { $HK = $T2; +$code.=<<___; + movdqa $Xi,$Xhi # + pshufd \$0b01001110,$Xi,$T1 + pshufd \$0b01001110,$Hkey,$T2 + pxor $Xi,$T1 # + pxor $Hkey,$T2 +___ +} else { +$code.=<<___; + movdqa $Xi,$Xhi # + pshufd \$0b01001110,$Xi,$T1 + pxor $Xi,$T1 # +___ +} +$code.=<<___; + pclmulqdq \$0x00,$Hkey,$Xi ####### + pclmulqdq \$0x11,$Hkey,$Xhi ####### + pclmulqdq \$0x00,$HK,$T1 ####### + pxor $Xi,$T1 # + pxor $Xhi,$T1 # + + movdqa $T1,$T2 # + psrldq \$8,$T1 + pslldq \$8,$T2 # + pxor $T1,$Xhi + pxor $T2,$Xi # +___ +} + +sub reduction_alg9 { # 17/11 times faster than Intel version +my ($Xhi,$Xi) = @_; + +$code.=<<___; + # 1st phase + movdqa $Xi,$T2 # + movdqa $Xi,$T1 + psllq \$5,$Xi + pxor $Xi,$T1 # + psllq \$1,$Xi + pxor $T1,$Xi # + psllq \$57,$Xi # + movdqa $Xi,$T1 # + pslldq \$8,$Xi + psrldq \$8,$T1 # + pxor $T2,$Xi + pxor $T1,$Xhi # + + # 2nd phase + movdqa $Xi,$T2 + psrlq \$1,$Xi + pxor $T2,$Xhi # + pxor $Xi,$T2 + psrlq \$5,$Xi + pxor $T2,$Xi # + psrlq \$1,$Xi # + pxor $Xhi,$Xi # +___ +} + +{ my ($Htbl,$Xip)=@_4args; + my $HK="%xmm6"; + +$code.=<<___; +.globl gcm_init_clmul +.type gcm_init_clmul,\@abi-omnipotent +.align 16 +gcm_init_clmul: +.cfi_startproc +.L_init_clmul: +___ +$code.=<<___ if ($win64); +.LSEH_begin_gcm_init_clmul: + # I can't trust assembler to use specific encoding:-( + .byte 0x48,0x83,0xec,0x18 #sub $0x18,%rsp + .byte 0x0f,0x29,0x34,0x24 #movaps %xmm6,(%rsp) +___ +$code.=<<___; + movdqu ($Xip),$Hkey + pshufd \$0b01001110,$Hkey,$Hkey # dword swap + + # <<1 twist + pshufd \$0b11111111,$Hkey,$T2 # broadcast uppermost dword + movdqa $Hkey,$T1 + psllq \$1,$Hkey + pxor $T3,$T3 # + psrlq \$63,$T1 + pcmpgtd $T2,$T3 # broadcast carry bit + pslldq \$8,$T1 + por $T1,$Hkey # H<<=1 + + # magic reduction + pand .L0x1c2_polynomial(%rip),$T3 + pxor $T3,$Hkey # if(carry) H^=0x1c2_polynomial + + # calculate H^2 + pshufd \$0b01001110,$Hkey,$HK + movdqa $Hkey,$Xi + pxor $Hkey,$HK +___ + &clmul64x64_T2 ($Xhi,$Xi,$Hkey,$HK); + &reduction_alg9 ($Xhi,$Xi); +$code.=<<___; + pshufd \$0b01001110,$Hkey,$T1 + pshufd \$0b01001110,$Xi,$T2 + pxor $Hkey,$T1 # Karatsuba pre-processing + movdqu $Hkey,0x00($Htbl) # save H + pxor $Xi,$T2 # Karatsuba pre-processing + movdqu $Xi,0x10($Htbl) # save H^2 + palignr \$8,$T1,$T2 # low part is H.lo^H.hi... + movdqu $T2,0x20($Htbl) # save Karatsuba "salt" +___ +if ($do4xaggr) { + &clmul64x64_T2 ($Xhi,$Xi,$Hkey,$HK); # H^3 + &reduction_alg9 ($Xhi,$Xi); +$code.=<<___; + movdqa $Xi,$T3 +___ + &clmul64x64_T2 ($Xhi,$Xi,$Hkey,$HK); # H^4 + &reduction_alg9 ($Xhi,$Xi); +$code.=<<___; + pshufd \$0b01001110,$T3,$T1 + pshufd \$0b01001110,$Xi,$T2 + pxor $T3,$T1 # Karatsuba pre-processing + movdqu $T3,0x30($Htbl) # save H^3 + pxor $Xi,$T2 # Karatsuba pre-processing + movdqu $Xi,0x40($Htbl) # save H^4 + palignr \$8,$T1,$T2 # low part is H^3.lo^H^3.hi... + movdqu $T2,0x50($Htbl) # save Karatsuba "salt" +___ +} +$code.=<<___ if ($win64); + movaps (%rsp),%xmm6 + lea 0x18(%rsp),%rsp +.LSEH_end_gcm_init_clmul: +___ +$code.=<<___; + ret +.cfi_endproc +.size gcm_init_clmul,.-gcm_init_clmul +___ +} + +{ my ($Xip,$Htbl)=@_4args; + +$code.=<<___; +.globl gcm_gmult_clmul +.type gcm_gmult_clmul,\@abi-omnipotent +.align 16 +gcm_gmult_clmul: +.cfi_startproc +.L_gmult_clmul: + movdqu ($Xip),$Xi + movdqa .Lbswap_mask(%rip),$T3 + movdqu ($Htbl),$Hkey + movdqu 0x20($Htbl),$T2 + pshufb $T3,$Xi +___ + &clmul64x64_T2 ($Xhi,$Xi,$Hkey,$T2); +$code.=<<___ if (0 || (&reduction_alg9($Xhi,$Xi)&&0)); + # experimental alternative. special thing about is that there + # no dependency between the two multiplications... + mov \$`0xE1<<1`,%eax + mov \$0xA040608020C0E000,%r10 # ((7..0)·0xE0)&0xff + mov \$0x07,%r11d + movq %rax,$T1 + movq %r10,$T2 + movq %r11,$T3 # borrow $T3 + pand $Xi,$T3 + pshufb $T3,$T2 # ($Xi&7)·0xE0 + movq %rax,$T3 + pclmulqdq \$0x00,$Xi,$T1 # ·(0xE1<<1) + pxor $Xi,$T2 + pslldq \$15,$T2 + paddd $T2,$T2 # <<(64+56+1) + pxor $T2,$Xi + pclmulqdq \$0x01,$T3,$Xi + movdqa .Lbswap_mask(%rip),$T3 # reload $T3 + psrldq \$1,$T1 + pxor $T1,$Xhi + pslldq \$7,$Xi + pxor $Xhi,$Xi +___ +$code.=<<___; + pshufb $T3,$Xi + movdqu $Xi,($Xip) + ret +.cfi_endproc +.size gcm_gmult_clmul,.-gcm_gmult_clmul +___ +} + +{ my ($Xip,$Htbl,$inp,$len)=@_4args; + my ($Xln,$Xmn,$Xhn,$Hkey2,$HK) = map("%xmm$_",(3..7)); + my ($T1,$T2,$T3)=map("%xmm$_",(8..10)); + +$code.=<<___; +.globl gcm_ghash_clmul +.type gcm_ghash_clmul,\@abi-omnipotent +.align 32 +gcm_ghash_clmul: +.cfi_startproc +.L_ghash_clmul: +___ +$code.=<<___ if ($win64); + lea -0x88(%rsp),%rax +.LSEH_begin_gcm_ghash_clmul: + # I can't trust assembler to use specific encoding:-( + .byte 0x48,0x8d,0x60,0xe0 #lea -0x20(%rax),%rsp + .byte 0x0f,0x29,0x70,0xe0 #movaps %xmm6,-0x20(%rax) + .byte 0x0f,0x29,0x78,0xf0 #movaps %xmm7,-0x10(%rax) + .byte 0x44,0x0f,0x29,0x00 #movaps %xmm8,0(%rax) + .byte 0x44,0x0f,0x29,0x48,0x10 #movaps %xmm9,0x10(%rax) + .byte 0x44,0x0f,0x29,0x50,0x20 #movaps %xmm10,0x20(%rax) + .byte 0x44,0x0f,0x29,0x58,0x30 #movaps %xmm11,0x30(%rax) + .byte 0x44,0x0f,0x29,0x60,0x40 #movaps %xmm12,0x40(%rax) + .byte 0x44,0x0f,0x29,0x68,0x50 #movaps %xmm13,0x50(%rax) + .byte 0x44,0x0f,0x29,0x70,0x60 #movaps %xmm14,0x60(%rax) + .byte 0x44,0x0f,0x29,0x78,0x70 #movaps %xmm15,0x70(%rax) +___ +$code.=<<___; + movdqa .Lbswap_mask(%rip),$T3 + + movdqu ($Xip),$Xi + movdqu ($Htbl),$Hkey + movdqu 0x20($Htbl),$HK + pshufb $T3,$Xi + + sub \$0x10,$len + jz .Lodd_tail + + movdqu 0x10($Htbl),$Hkey2 +___ +if ($do4xaggr) { +my ($Xl,$Xm,$Xh,$Hkey3,$Hkey4)=map("%xmm$_",(11..15)); + +$code.=<<___; + mov OPENSSL_ia32cap_P+4(%rip),%eax + cmp \$0x30,$len + jb .Lskip4x + + and \$`1<<26|1<<22`,%eax # isolate MOVBE+XSAVE + cmp \$`1<<22`,%eax # check for MOVBE without XSAVE + je .Lskip4x + + sub \$0x30,$len + mov \$0xA040608020C0E000,%rax # ((7..0)·0xE0)&0xff + movdqu 0x30($Htbl),$Hkey3 + movdqu 0x40($Htbl),$Hkey4 + + ####### + # Xi+4 =[(H*Ii+3) + (H^2*Ii+2) + (H^3*Ii+1) + H^4*(Ii+Xi)] mod P + # + movdqu 0x30($inp),$Xln + movdqu 0x20($inp),$Xl + pshufb $T3,$Xln + pshufb $T3,$Xl + movdqa $Xln,$Xhn + pshufd \$0b01001110,$Xln,$Xmn + pxor $Xln,$Xmn + pclmulqdq \$0x00,$Hkey,$Xln + pclmulqdq \$0x11,$Hkey,$Xhn + pclmulqdq \$0x00,$HK,$Xmn + + movdqa $Xl,$Xh + pshufd \$0b01001110,$Xl,$Xm + pxor $Xl,$Xm + pclmulqdq \$0x00,$Hkey2,$Xl + pclmulqdq \$0x11,$Hkey2,$Xh + pclmulqdq \$0x10,$HK,$Xm + xorps $Xl,$Xln + xorps $Xh,$Xhn + movups 0x50($Htbl),$HK + xorps $Xm,$Xmn + + movdqu 0x10($inp),$Xl + movdqu 0($inp),$T1 + pshufb $T3,$Xl + pshufb $T3,$T1 + movdqa $Xl,$Xh + pshufd \$0b01001110,$Xl,$Xm + pxor $T1,$Xi + pxor $Xl,$Xm + pclmulqdq \$0x00,$Hkey3,$Xl + movdqa $Xi,$Xhi + pshufd \$0b01001110,$Xi,$T1 + pxor $Xi,$T1 + pclmulqdq \$0x11,$Hkey3,$Xh + pclmulqdq \$0x00,$HK,$Xm + xorps $Xl,$Xln + xorps $Xh,$Xhn + + lea 0x40($inp),$inp + sub \$0x40,$len + jc .Ltail4x + + jmp .Lmod4_loop +.align 32 +.Lmod4_loop: + pclmulqdq \$0x00,$Hkey4,$Xi + xorps $Xm,$Xmn + movdqu 0x30($inp),$Xl + pshufb $T3,$Xl + pclmulqdq \$0x11,$Hkey4,$Xhi + xorps $Xln,$Xi + movdqu 0x20($inp),$Xln + movdqa $Xl,$Xh + pclmulqdq \$0x10,$HK,$T1 + pshufd \$0b01001110,$Xl,$Xm + xorps $Xhn,$Xhi + pxor $Xl,$Xm + pshufb $T3,$Xln + movups 0x20($Htbl),$HK + xorps $Xmn,$T1 + pclmulqdq \$0x00,$Hkey,$Xl + pshufd \$0b01001110,$Xln,$Xmn + + pxor $Xi,$T1 # aggregated Karatsuba post-processing + movdqa $Xln,$Xhn + pxor $Xhi,$T1 # + pxor $Xln,$Xmn + movdqa $T1,$T2 # + pclmulqdq \$0x11,$Hkey,$Xh + pslldq \$8,$T1 + psrldq \$8,$T2 # + pxor $T1,$Xi + movdqa .L7_mask(%rip),$T1 + pxor $T2,$Xhi # + movq %rax,$T2 + + pand $Xi,$T1 # 1st phase + pshufb $T1,$T2 # + pxor $Xi,$T2 # + pclmulqdq \$0x00,$HK,$Xm + psllq \$57,$T2 # + movdqa $T2,$T1 # + pslldq \$8,$T2 + pclmulqdq \$0x00,$Hkey2,$Xln + psrldq \$8,$T1 # + pxor $T2,$Xi + pxor $T1,$Xhi # + movdqu 0($inp),$T1 + + movdqa $Xi,$T2 # 2nd phase + psrlq \$1,$Xi + pclmulqdq \$0x11,$Hkey2,$Xhn + xorps $Xl,$Xln + movdqu 0x10($inp),$Xl + pshufb $T3,$Xl + pclmulqdq \$0x10,$HK,$Xmn + xorps $Xh,$Xhn + movups 0x50($Htbl),$HK + pshufb $T3,$T1 + pxor $T2,$Xhi # + pxor $Xi,$T2 + psrlq \$5,$Xi + + movdqa $Xl,$Xh + pxor $Xm,$Xmn + pshufd \$0b01001110,$Xl,$Xm + pxor $T2,$Xi # + pxor $T1,$Xhi + pxor $Xl,$Xm + pclmulqdq \$0x00,$Hkey3,$Xl + psrlq \$1,$Xi # + pxor $Xhi,$Xi # + movdqa $Xi,$Xhi + pclmulqdq \$0x11,$Hkey3,$Xh + xorps $Xl,$Xln + pshufd \$0b01001110,$Xi,$T1 + pxor $Xi,$T1 + + pclmulqdq \$0x00,$HK,$Xm + xorps $Xh,$Xhn + + lea 0x40($inp),$inp + sub \$0x40,$len + jnc .Lmod4_loop + +.Ltail4x: + pclmulqdq \$0x00,$Hkey4,$Xi + pclmulqdq \$0x11,$Hkey4,$Xhi + pclmulqdq \$0x10,$HK,$T1 + xorps $Xm,$Xmn + xorps $Xln,$Xi + xorps $Xhn,$Xhi + pxor $Xi,$Xhi # aggregated Karatsuba post-processing + pxor $Xmn,$T1 + + pxor $Xhi,$T1 # + pxor $Xi,$Xhi + + movdqa $T1,$T2 # + psrldq \$8,$T1 + pslldq \$8,$T2 # + pxor $T1,$Xhi + pxor $T2,$Xi # +___ + &reduction_alg9($Xhi,$Xi); +$code.=<<___; + add \$0x40,$len + jz .Ldone + movdqu 0x20($Htbl),$HK + sub \$0x10,$len + jz .Lodd_tail +.Lskip4x: +___ +} +$code.=<<___; + ####### + # Xi+2 =[H*(Ii+1 + Xi+1)] mod P = + # [(H*Ii+1) + (H*Xi+1)] mod P = + # [(H*Ii+1) + H^2*(Ii+Xi)] mod P + # + movdqu ($inp),$T1 # Ii + movdqu 16($inp),$Xln # Ii+1 + pshufb $T3,$T1 + pshufb $T3,$Xln + pxor $T1,$Xi # Ii+Xi + + movdqa $Xln,$Xhn + pshufd \$0b01001110,$Xln,$Xmn + pxor $Xln,$Xmn + pclmulqdq \$0x00,$Hkey,$Xln + pclmulqdq \$0x11,$Hkey,$Xhn + pclmulqdq \$0x00,$HK,$Xmn + + lea 32($inp),$inp # i+=2 + nop + sub \$0x20,$len + jbe .Leven_tail + nop + jmp .Lmod_loop + +.align 32 +.Lmod_loop: + movdqa $Xi,$Xhi + movdqa $Xmn,$T1 + pshufd \$0b01001110,$Xi,$Xmn # + pxor $Xi,$Xmn # + + pclmulqdq \$0x00,$Hkey2,$Xi + pclmulqdq \$0x11,$Hkey2,$Xhi + pclmulqdq \$0x10,$HK,$Xmn + + pxor $Xln,$Xi # (H*Ii+1) + H^2*(Ii+Xi) + pxor $Xhn,$Xhi + movdqu ($inp),$T2 # Ii + pxor $Xi,$T1 # aggregated Karatsuba post-processing + pshufb $T3,$T2 + movdqu 16($inp),$Xln # Ii+1 + + pxor $Xhi,$T1 + pxor $T2,$Xhi # "Ii+Xi", consume early + pxor $T1,$Xmn + pshufb $T3,$Xln + movdqa $Xmn,$T1 # + psrldq \$8,$T1 + pslldq \$8,$Xmn # + pxor $T1,$Xhi + pxor $Xmn,$Xi # + + movdqa $Xln,$Xhn # + + movdqa $Xi,$T2 # 1st phase + movdqa $Xi,$T1 + psllq \$5,$Xi + pxor $Xi,$T1 # + pclmulqdq \$0x00,$Hkey,$Xln ####### + psllq \$1,$Xi + pxor $T1,$Xi # + psllq \$57,$Xi # + movdqa $Xi,$T1 # + pslldq \$8,$Xi + psrldq \$8,$T1 # + pxor $T2,$Xi + pshufd \$0b01001110,$Xhn,$Xmn + pxor $T1,$Xhi # + pxor $Xhn,$Xmn # + + movdqa $Xi,$T2 # 2nd phase + psrlq \$1,$Xi + pclmulqdq \$0x11,$Hkey,$Xhn ####### + pxor $T2,$Xhi # + pxor $Xi,$T2 + psrlq \$5,$Xi + pxor $T2,$Xi # + lea 32($inp),$inp + psrlq \$1,$Xi # + pclmulqdq \$0x00,$HK,$Xmn ####### + pxor $Xhi,$Xi # + + sub \$0x20,$len + ja .Lmod_loop + +.Leven_tail: + movdqa $Xi,$Xhi + movdqa $Xmn,$T1 + pshufd \$0b01001110,$Xi,$Xmn # + pxor $Xi,$Xmn # + + pclmulqdq \$0x00,$Hkey2,$Xi + pclmulqdq \$0x11,$Hkey2,$Xhi + pclmulqdq \$0x10,$HK,$Xmn + + pxor $Xln,$Xi # (H*Ii+1) + H^2*(Ii+Xi) + pxor $Xhn,$Xhi + pxor $Xi,$T1 + pxor $Xhi,$T1 + pxor $T1,$Xmn + movdqa $Xmn,$T1 # + psrldq \$8,$T1 + pslldq \$8,$Xmn # + pxor $T1,$Xhi + pxor $Xmn,$Xi # +___ + &reduction_alg9 ($Xhi,$Xi); +$code.=<<___; + test $len,$len + jnz .Ldone + +.Lodd_tail: + movdqu ($inp),$T1 # Ii + pshufb $T3,$T1 + pxor $T1,$Xi # Ii+Xi +___ + &clmul64x64_T2 ($Xhi,$Xi,$Hkey,$HK); # H*(Ii+Xi) + &reduction_alg9 ($Xhi,$Xi); +$code.=<<___; +.Ldone: + pshufb $T3,$Xi + movdqu $Xi,($Xip) +___ +$code.=<<___ if ($win64); + movaps (%rsp),%xmm6 + movaps 0x10(%rsp),%xmm7 + movaps 0x20(%rsp),%xmm8 + movaps 0x30(%rsp),%xmm9 + movaps 0x40(%rsp),%xmm10 + movaps 0x50(%rsp),%xmm11 + movaps 0x60(%rsp),%xmm12 + movaps 0x70(%rsp),%xmm13 + movaps 0x80(%rsp),%xmm14 + movaps 0x90(%rsp),%xmm15 + lea 0xa8(%rsp),%rsp +.LSEH_end_gcm_ghash_clmul: +___ +$code.=<<___; + ret +.cfi_endproc +.size gcm_ghash_clmul,.-gcm_ghash_clmul +___ +} + +$code.=<<___; +.globl gcm_init_avx +.type gcm_init_avx,\@abi-omnipotent +.align 32 +gcm_init_avx: +.cfi_startproc +___ +if ($avx) { +my ($Htbl,$Xip)=@_4args; +my $HK="%xmm6"; + +$code.=<<___ if ($win64); +.LSEH_begin_gcm_init_avx: + # I can't trust assembler to use specific encoding:-( + .byte 0x48,0x83,0xec,0x18 #sub $0x18,%rsp + .byte 0x0f,0x29,0x34,0x24 #movaps %xmm6,(%rsp) +___ +$code.=<<___; + vzeroupper + + vmovdqu ($Xip),$Hkey + vpshufd \$0b01001110,$Hkey,$Hkey # dword swap + + # <<1 twist + vpshufd \$0b11111111,$Hkey,$T2 # broadcast uppermost dword + vpsrlq \$63,$Hkey,$T1 + vpsllq \$1,$Hkey,$Hkey + vpxor $T3,$T3,$T3 # + vpcmpgtd $T2,$T3,$T3 # broadcast carry bit + vpslldq \$8,$T1,$T1 + vpor $T1,$Hkey,$Hkey # H<<=1 + + # magic reduction + vpand .L0x1c2_polynomial(%rip),$T3,$T3 + vpxor $T3,$Hkey,$Hkey # if(carry) H^=0x1c2_polynomial + + vpunpckhqdq $Hkey,$Hkey,$HK + vmovdqa $Hkey,$Xi + vpxor $Hkey,$HK,$HK + mov \$4,%r10 # up to H^8 + jmp .Linit_start_avx +___ + +sub clmul64x64_avx { +my ($Xhi,$Xi,$Hkey,$HK)=@_; + +if (!defined($HK)) { $HK = $T2; +$code.=<<___; + vpunpckhqdq $Xi,$Xi,$T1 + vpunpckhqdq $Hkey,$Hkey,$T2 + vpxor $Xi,$T1,$T1 # + vpxor $Hkey,$T2,$T2 +___ +} else { +$code.=<<___; + vpunpckhqdq $Xi,$Xi,$T1 + vpxor $Xi,$T1,$T1 # +___ +} +$code.=<<___; + vpclmulqdq \$0x11,$Hkey,$Xi,$Xhi ####### + vpclmulqdq \$0x00,$Hkey,$Xi,$Xi ####### + vpclmulqdq \$0x00,$HK,$T1,$T1 ####### + vpxor $Xi,$Xhi,$T2 # + vpxor $T2,$T1,$T1 # + + vpslldq \$8,$T1,$T2 # + vpsrldq \$8,$T1,$T1 + vpxor $T2,$Xi,$Xi # + vpxor $T1,$Xhi,$Xhi +___ +} + +sub reduction_avx { +my ($Xhi,$Xi) = @_; + +$code.=<<___; + vpsllq \$57,$Xi,$T1 # 1st phase + vpsllq \$62,$Xi,$T2 + vpxor $T1,$T2,$T2 # + vpsllq \$63,$Xi,$T1 + vpxor $T1,$T2,$T2 # + vpslldq \$8,$T2,$T1 # + vpsrldq \$8,$T2,$T2 + vpxor $T1,$Xi,$Xi # + vpxor $T2,$Xhi,$Xhi + + vpsrlq \$1,$Xi,$T2 # 2nd phase + vpxor $Xi,$Xhi,$Xhi + vpxor $T2,$Xi,$Xi # + vpsrlq \$5,$T2,$T2 + vpxor $T2,$Xi,$Xi # + vpsrlq \$1,$Xi,$Xi # + vpxor $Xhi,$Xi,$Xi # +___ +} + +$code.=<<___; +.align 32 +.Linit_loop_avx: + vpalignr \$8,$T1,$T2,$T3 # low part is H.lo^H.hi... + vmovdqu $T3,-0x10($Htbl) # save Karatsuba "salt" +___ + &clmul64x64_avx ($Xhi,$Xi,$Hkey,$HK); # calculate H^3,5,7 + &reduction_avx ($Xhi,$Xi); +$code.=<<___; +.Linit_start_avx: + vmovdqa $Xi,$T3 +___ + &clmul64x64_avx ($Xhi,$Xi,$Hkey,$HK); # calculate H^2,4,6,8 + &reduction_avx ($Xhi,$Xi); +$code.=<<___; + vpshufd \$0b01001110,$T3,$T1 + vpshufd \$0b01001110,$Xi,$T2 + vpxor $T3,$T1,$T1 # Karatsuba pre-processing + vmovdqu $T3,0x00($Htbl) # save H^1,3,5,7 + vpxor $Xi,$T2,$T2 # Karatsuba pre-processing + vmovdqu $Xi,0x10($Htbl) # save H^2,4,6,8 + lea 0x30($Htbl),$Htbl + sub \$1,%r10 + jnz .Linit_loop_avx + + vpalignr \$8,$T2,$T1,$T3 # last "salt" is flipped + vmovdqu $T3,-0x10($Htbl) + + vzeroupper +___ +$code.=<<___ if ($win64); + movaps (%rsp),%xmm6 + lea 0x18(%rsp),%rsp +.LSEH_end_gcm_init_avx: +___ +$code.=<<___; + ret +.cfi_endproc +.size gcm_init_avx,.-gcm_init_avx +___ +} else { +$code.=<<___; + jmp .L_init_clmul +.size gcm_init_avx,.-gcm_init_avx +___ +} + +$code.=<<___; +.globl gcm_gmult_avx +.type gcm_gmult_avx,\@abi-omnipotent +.align 32 +gcm_gmult_avx: +.cfi_startproc + jmp .L_gmult_clmul +.cfi_endproc +.size gcm_gmult_avx,.-gcm_gmult_avx +___ + +$code.=<<___; +.globl gcm_ghash_avx +.type gcm_ghash_avx,\@abi-omnipotent +.align 32 +gcm_ghash_avx: +.cfi_startproc +___ +if ($avx) { +my ($Xip,$Htbl,$inp,$len)=@_4args; +my ($Xlo,$Xhi,$Xmi, + $Zlo,$Zhi,$Zmi, + $Hkey,$HK,$T1,$T2, + $Xi,$Xo,$Tred,$bswap,$Ii,$Ij) = map("%xmm$_",(0..15)); + +$code.=<<___ if ($win64); + lea -0x88(%rsp),%rax +.LSEH_begin_gcm_ghash_avx: + # I can't trust assembler to use specific encoding:-( + .byte 0x48,0x8d,0x60,0xe0 #lea -0x20(%rax),%rsp + .byte 0x0f,0x29,0x70,0xe0 #movaps %xmm6,-0x20(%rax) + .byte 0x0f,0x29,0x78,0xf0 #movaps %xmm7,-0x10(%rax) + .byte 0x44,0x0f,0x29,0x00 #movaps %xmm8,0(%rax) + .byte 0x44,0x0f,0x29,0x48,0x10 #movaps %xmm9,0x10(%rax) + .byte 0x44,0x0f,0x29,0x50,0x20 #movaps %xmm10,0x20(%rax) + .byte 0x44,0x0f,0x29,0x58,0x30 #movaps %xmm11,0x30(%rax) + .byte 0x44,0x0f,0x29,0x60,0x40 #movaps %xmm12,0x40(%rax) + .byte 0x44,0x0f,0x29,0x68,0x50 #movaps %xmm13,0x50(%rax) + .byte 0x44,0x0f,0x29,0x70,0x60 #movaps %xmm14,0x60(%rax) + .byte 0x44,0x0f,0x29,0x78,0x70 #movaps %xmm15,0x70(%rax) +___ +$code.=<<___; + vzeroupper + + vmovdqu ($Xip),$Xi # load $Xi + lea .L0x1c2_polynomial(%rip),%r10 + lea 0x40($Htbl),$Htbl # size optimization + vmovdqu .Lbswap_mask(%rip),$bswap + vpshufb $bswap,$Xi,$Xi + cmp \$0x80,$len + jb .Lshort_avx + sub \$0x80,$len + + vmovdqu 0x70($inp),$Ii # I[7] + vmovdqu 0x00-0x40($Htbl),$Hkey # $Hkey^1 + vpshufb $bswap,$Ii,$Ii + vmovdqu 0x20-0x40($Htbl),$HK + + vpunpckhqdq $Ii,$Ii,$T2 + vmovdqu 0x60($inp),$Ij # I[6] + vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo + vpxor $Ii,$T2,$T2 + vpshufb $bswap,$Ij,$Ij + vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi + vmovdqu 0x10-0x40($Htbl),$Hkey # $Hkey^2 + vpunpckhqdq $Ij,$Ij,$T1 + vmovdqu 0x50($inp),$Ii # I[5] + vpclmulqdq \$0x00,$HK,$T2,$Xmi + vpxor $Ij,$T1,$T1 + + vpshufb $bswap,$Ii,$Ii + vpclmulqdq \$0x00,$Hkey,$Ij,$Zlo + vpunpckhqdq $Ii,$Ii,$T2 + vpclmulqdq \$0x11,$Hkey,$Ij,$Zhi + vmovdqu 0x30-0x40($Htbl),$Hkey # $Hkey^3 + vpxor $Ii,$T2,$T2 + vmovdqu 0x40($inp),$Ij # I[4] + vpclmulqdq \$0x10,$HK,$T1,$Zmi + vmovdqu 0x50-0x40($Htbl),$HK + + vpshufb $bswap,$Ij,$Ij + vpxor $Xlo,$Zlo,$Zlo + vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo + vpxor $Xhi,$Zhi,$Zhi + vpunpckhqdq $Ij,$Ij,$T1 + vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi + vmovdqu 0x40-0x40($Htbl),$Hkey # $Hkey^4 + vpxor $Xmi,$Zmi,$Zmi + vpclmulqdq \$0x00,$HK,$T2,$Xmi + vpxor $Ij,$T1,$T1 + + vmovdqu 0x30($inp),$Ii # I[3] + vpxor $Zlo,$Xlo,$Xlo + vpclmulqdq \$0x00,$Hkey,$Ij,$Zlo + vpxor $Zhi,$Xhi,$Xhi + vpshufb $bswap,$Ii,$Ii + vpclmulqdq \$0x11,$Hkey,$Ij,$Zhi + vmovdqu 0x60-0x40($Htbl),$Hkey # $Hkey^5 + vpxor $Zmi,$Xmi,$Xmi + vpunpckhqdq $Ii,$Ii,$T2 + vpclmulqdq \$0x10,$HK,$T1,$Zmi + vmovdqu 0x80-0x40($Htbl),$HK + vpxor $Ii,$T2,$T2 + + vmovdqu 0x20($inp),$Ij # I[2] + vpxor $Xlo,$Zlo,$Zlo + vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo + vpxor $Xhi,$Zhi,$Zhi + vpshufb $bswap,$Ij,$Ij + vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi + vmovdqu 0x70-0x40($Htbl),$Hkey # $Hkey^6 + vpxor $Xmi,$Zmi,$Zmi + vpunpckhqdq $Ij,$Ij,$T1 + vpclmulqdq \$0x00,$HK,$T2,$Xmi + vpxor $Ij,$T1,$T1 + + vmovdqu 0x10($inp),$Ii # I[1] + vpxor $Zlo,$Xlo,$Xlo + vpclmulqdq \$0x00,$Hkey,$Ij,$Zlo + vpxor $Zhi,$Xhi,$Xhi + vpshufb $bswap,$Ii,$Ii + vpclmulqdq \$0x11,$Hkey,$Ij,$Zhi + vmovdqu 0x90-0x40($Htbl),$Hkey # $Hkey^7 + vpxor $Zmi,$Xmi,$Xmi + vpunpckhqdq $Ii,$Ii,$T2 + vpclmulqdq \$0x10,$HK,$T1,$Zmi + vmovdqu 0xb0-0x40($Htbl),$HK + vpxor $Ii,$T2,$T2 + + vmovdqu ($inp),$Ij # I[0] + vpxor $Xlo,$Zlo,$Zlo + vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo + vpxor $Xhi,$Zhi,$Zhi + vpshufb $bswap,$Ij,$Ij + vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi + vmovdqu 0xa0-0x40($Htbl),$Hkey # $Hkey^8 + vpxor $Xmi,$Zmi,$Zmi + vpclmulqdq \$0x10,$HK,$T2,$Xmi + + lea 0x80($inp),$inp + cmp \$0x80,$len + jb .Ltail_avx + + vpxor $Xi,$Ij,$Ij # accumulate $Xi + sub \$0x80,$len + jmp .Loop8x_avx + +.align 32 +.Loop8x_avx: + vpunpckhqdq $Ij,$Ij,$T1 + vmovdqu 0x70($inp),$Ii # I[7] + vpxor $Xlo,$Zlo,$Zlo + vpxor $Ij,$T1,$T1 + vpclmulqdq \$0x00,$Hkey,$Ij,$Xi + vpshufb $bswap,$Ii,$Ii + vpxor $Xhi,$Zhi,$Zhi + vpclmulqdq \$0x11,$Hkey,$Ij,$Xo + vmovdqu 0x00-0x40($Htbl),$Hkey # $Hkey^1 + vpunpckhqdq $Ii,$Ii,$T2 + vpxor $Xmi,$Zmi,$Zmi + vpclmulqdq \$0x00,$HK,$T1,$Tred + vmovdqu 0x20-0x40($Htbl),$HK + vpxor $Ii,$T2,$T2 + + vmovdqu 0x60($inp),$Ij # I[6] + vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo + vpxor $Zlo,$Xi,$Xi # collect result + vpshufb $bswap,$Ij,$Ij + vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi + vxorps $Zhi,$Xo,$Xo + vmovdqu 0x10-0x40($Htbl),$Hkey # $Hkey^2 + vpunpckhqdq $Ij,$Ij,$T1 + vpclmulqdq \$0x00,$HK, $T2,$Xmi + vpxor $Zmi,$Tred,$Tred + vxorps $Ij,$T1,$T1 + + vmovdqu 0x50($inp),$Ii # I[5] + vpxor $Xi,$Tred,$Tred # aggregated Karatsuba post-processing + vpclmulqdq \$0x00,$Hkey,$Ij,$Zlo + vpxor $Xo,$Tred,$Tred + vpslldq \$8,$Tred,$T2 + vpxor $Xlo,$Zlo,$Zlo + vpclmulqdq \$0x11,$Hkey,$Ij,$Zhi + vpsrldq \$8,$Tred,$Tred + vpxor $T2, $Xi, $Xi + vmovdqu 0x30-0x40($Htbl),$Hkey # $Hkey^3 + vpshufb $bswap,$Ii,$Ii + vxorps $Tred,$Xo, $Xo + vpxor $Xhi,$Zhi,$Zhi + vpunpckhqdq $Ii,$Ii,$T2 + vpclmulqdq \$0x10,$HK, $T1,$Zmi + vmovdqu 0x50-0x40($Htbl),$HK + vpxor $Ii,$T2,$T2 + vpxor $Xmi,$Zmi,$Zmi + + vmovdqu 0x40($inp),$Ij # I[4] + vpalignr \$8,$Xi,$Xi,$Tred # 1st phase + vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo + vpshufb $bswap,$Ij,$Ij + vpxor $Zlo,$Xlo,$Xlo + vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi + vmovdqu 0x40-0x40($Htbl),$Hkey # $Hkey^4 + vpunpckhqdq $Ij,$Ij,$T1 + vpxor $Zhi,$Xhi,$Xhi + vpclmulqdq \$0x00,$HK, $T2,$Xmi + vxorps $Ij,$T1,$T1 + vpxor $Zmi,$Xmi,$Xmi + + vmovdqu 0x30($inp),$Ii # I[3] + vpclmulqdq \$0x10,(%r10),$Xi,$Xi + vpclmulqdq \$0x00,$Hkey,$Ij,$Zlo + vpshufb $bswap,$Ii,$Ii + vpxor $Xlo,$Zlo,$Zlo + vpclmulqdq \$0x11,$Hkey,$Ij,$Zhi + vmovdqu 0x60-0x40($Htbl),$Hkey # $Hkey^5 + vpunpckhqdq $Ii,$Ii,$T2 + vpxor $Xhi,$Zhi,$Zhi + vpclmulqdq \$0x10,$HK, $T1,$Zmi + vmovdqu 0x80-0x40($Htbl),$HK + vpxor $Ii,$T2,$T2 + vpxor $Xmi,$Zmi,$Zmi + + vmovdqu 0x20($inp),$Ij # I[2] + vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo + vpshufb $bswap,$Ij,$Ij + vpxor $Zlo,$Xlo,$Xlo + vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi + vmovdqu 0x70-0x40($Htbl),$Hkey # $Hkey^6 + vpunpckhqdq $Ij,$Ij,$T1 + vpxor $Zhi,$Xhi,$Xhi + vpclmulqdq \$0x00,$HK, $T2,$Xmi + vpxor $Ij,$T1,$T1 + vpxor $Zmi,$Xmi,$Xmi + vxorps $Tred,$Xi,$Xi + + vmovdqu 0x10($inp),$Ii # I[1] + vpalignr \$8,$Xi,$Xi,$Tred # 2nd phase + vpclmulqdq \$0x00,$Hkey,$Ij,$Zlo + vpshufb $bswap,$Ii,$Ii + vpxor $Xlo,$Zlo,$Zlo + vpclmulqdq \$0x11,$Hkey,$Ij,$Zhi + vmovdqu 0x90-0x40($Htbl),$Hkey # $Hkey^7 + vpclmulqdq \$0x10,(%r10),$Xi,$Xi + vxorps $Xo,$Tred,$Tred + vpunpckhqdq $Ii,$Ii,$T2 + vpxor $Xhi,$Zhi,$Zhi + vpclmulqdq \$0x10,$HK, $T1,$Zmi + vmovdqu 0xb0-0x40($Htbl),$HK + vpxor $Ii,$T2,$T2 + vpxor $Xmi,$Zmi,$Zmi + + vmovdqu ($inp),$Ij # I[0] + vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo + vpshufb $bswap,$Ij,$Ij + vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi + vmovdqu 0xa0-0x40($Htbl),$Hkey # $Hkey^8 + vpxor $Tred,$Ij,$Ij + vpclmulqdq \$0x10,$HK, $T2,$Xmi + vpxor $Xi,$Ij,$Ij # accumulate $Xi + + lea 0x80($inp),$inp + sub \$0x80,$len + jnc .Loop8x_avx + + add \$0x80,$len + jmp .Ltail_no_xor_avx + +.align 32 +.Lshort_avx: + vmovdqu -0x10($inp,$len),$Ii # very last word + lea ($inp,$len),$inp + vmovdqu 0x00-0x40($Htbl),$Hkey # $Hkey^1 + vmovdqu 0x20-0x40($Htbl),$HK + vpshufb $bswap,$Ii,$Ij + + vmovdqa $Xlo,$Zlo # subtle way to zero $Zlo, + vmovdqa $Xhi,$Zhi # $Zhi and + vmovdqa $Xmi,$Zmi # $Zmi + sub \$0x10,$len + jz .Ltail_avx + + vpunpckhqdq $Ij,$Ij,$T1 + vpxor $Xlo,$Zlo,$Zlo + vpclmulqdq \$0x00,$Hkey,$Ij,$Xlo + vpxor $Ij,$T1,$T1 + vmovdqu -0x20($inp),$Ii + vpxor $Xhi,$Zhi,$Zhi + vpclmulqdq \$0x11,$Hkey,$Ij,$Xhi + vmovdqu 0x10-0x40($Htbl),$Hkey # $Hkey^2 + vpshufb $bswap,$Ii,$Ij + vpxor $Xmi,$Zmi,$Zmi + vpclmulqdq \$0x00,$HK,$T1,$Xmi + vpsrldq \$8,$HK,$HK + sub \$0x10,$len + jz .Ltail_avx + + vpunpckhqdq $Ij,$Ij,$T1 + vpxor $Xlo,$Zlo,$Zlo + vpclmulqdq \$0x00,$Hkey,$Ij,$Xlo + vpxor $Ij,$T1,$T1 + vmovdqu -0x30($inp),$Ii + vpxor $Xhi,$Zhi,$Zhi + vpclmulqdq \$0x11,$Hkey,$Ij,$Xhi + vmovdqu 0x30-0x40($Htbl),$Hkey # $Hkey^3 + vpshufb $bswap,$Ii,$Ij + vpxor $Xmi,$Zmi,$Zmi + vpclmulqdq \$0x00,$HK,$T1,$Xmi + vmovdqu 0x50-0x40($Htbl),$HK + sub \$0x10,$len + jz .Ltail_avx + + vpunpckhqdq $Ij,$Ij,$T1 + vpxor $Xlo,$Zlo,$Zlo + vpclmulqdq \$0x00,$Hkey,$Ij,$Xlo + vpxor $Ij,$T1,$T1 + vmovdqu -0x40($inp),$Ii + vpxor $Xhi,$Zhi,$Zhi + vpclmulqdq \$0x11,$Hkey,$Ij,$Xhi + vmovdqu 0x40-0x40($Htbl),$Hkey # $Hkey^4 + vpshufb $bswap,$Ii,$Ij + vpxor $Xmi,$Zmi,$Zmi + vpclmulqdq \$0x00,$HK,$T1,$Xmi + vpsrldq \$8,$HK,$HK + sub \$0x10,$len + jz .Ltail_avx + + vpunpckhqdq $Ij,$Ij,$T1 + vpxor $Xlo,$Zlo,$Zlo + vpclmulqdq \$0x00,$Hkey,$Ij,$Xlo + vpxor $Ij,$T1,$T1 + vmovdqu -0x50($inp),$Ii + vpxor $Xhi,$Zhi,$Zhi + vpclmulqdq \$0x11,$Hkey,$Ij,$Xhi + vmovdqu 0x60-0x40($Htbl),$Hkey # $Hkey^5 + vpshufb $bswap,$Ii,$Ij + vpxor $Xmi,$Zmi,$Zmi + vpclmulqdq \$0x00,$HK,$T1,$Xmi + vmovdqu 0x80-0x40($Htbl),$HK + sub \$0x10,$len + jz .Ltail_avx + + vpunpckhqdq $Ij,$Ij,$T1 + vpxor $Xlo,$Zlo,$Zlo + vpclmulqdq \$0x00,$Hkey,$Ij,$Xlo + vpxor $Ij,$T1,$T1 + vmovdqu -0x60($inp),$Ii + vpxor $Xhi,$Zhi,$Zhi + vpclmulqdq \$0x11,$Hkey,$Ij,$Xhi + vmovdqu 0x70-0x40($Htbl),$Hkey # $Hkey^6 + vpshufb $bswap,$Ii,$Ij + vpxor $Xmi,$Zmi,$Zmi + vpclmulqdq \$0x00,$HK,$T1,$Xmi + vpsrldq \$8,$HK,$HK + sub \$0x10,$len + jz .Ltail_avx + + vpunpckhqdq $Ij,$Ij,$T1 + vpxor $Xlo,$Zlo,$Zlo + vpclmulqdq \$0x00,$Hkey,$Ij,$Xlo + vpxor $Ij,$T1,$T1 + vmovdqu -0x70($inp),$Ii + vpxor $Xhi,$Zhi,$Zhi + vpclmulqdq \$0x11,$Hkey,$Ij,$Xhi + vmovdqu 0x90-0x40($Htbl),$Hkey # $Hkey^7 + vpshufb $bswap,$Ii,$Ij + vpxor $Xmi,$Zmi,$Zmi + vpclmulqdq \$0x00,$HK,$T1,$Xmi + vmovq 0xb8-0x40($Htbl),$HK + sub \$0x10,$len + jmp .Ltail_avx + +.align 32 +.Ltail_avx: + vpxor $Xi,$Ij,$Ij # accumulate $Xi +.Ltail_no_xor_avx: + vpunpckhqdq $Ij,$Ij,$T1 + vpxor $Xlo,$Zlo,$Zlo + vpclmulqdq \$0x00,$Hkey,$Ij,$Xlo + vpxor $Ij,$T1,$T1 + vpxor $Xhi,$Zhi,$Zhi + vpclmulqdq \$0x11,$Hkey,$Ij,$Xhi + vpxor $Xmi,$Zmi,$Zmi + vpclmulqdq \$0x00,$HK,$T1,$Xmi + + vmovdqu (%r10),$Tred + + vpxor $Xlo,$Zlo,$Xi + vpxor $Xhi,$Zhi,$Xo + vpxor $Xmi,$Zmi,$Zmi + + vpxor $Xi, $Zmi,$Zmi # aggregated Karatsuba post-processing + vpxor $Xo, $Zmi,$Zmi + vpslldq \$8, $Zmi,$T2 + vpsrldq \$8, $Zmi,$Zmi + vpxor $T2, $Xi, $Xi + vpxor $Zmi,$Xo, $Xo + + vpclmulqdq \$0x10,$Tred,$Xi,$T2 # 1st phase + vpalignr \$8,$Xi,$Xi,$Xi + vpxor $T2,$Xi,$Xi + + vpclmulqdq \$0x10,$Tred,$Xi,$T2 # 2nd phase + vpalignr \$8,$Xi,$Xi,$Xi + vpxor $Xo,$Xi,$Xi + vpxor $T2,$Xi,$Xi + + cmp \$0,$len + jne .Lshort_avx + + vpshufb $bswap,$Xi,$Xi + vmovdqu $Xi,($Xip) + vzeroupper +___ +$code.=<<___ if ($win64); + movaps (%rsp),%xmm6 + movaps 0x10(%rsp),%xmm7 + movaps 0x20(%rsp),%xmm8 + movaps 0x30(%rsp),%xmm9 + movaps 0x40(%rsp),%xmm10 + movaps 0x50(%rsp),%xmm11 + movaps 0x60(%rsp),%xmm12 + movaps 0x70(%rsp),%xmm13 + movaps 0x80(%rsp),%xmm14 + movaps 0x90(%rsp),%xmm15 + lea 0xa8(%rsp),%rsp +.LSEH_end_gcm_ghash_avx: +___ +$code.=<<___; + ret +.cfi_endproc +.size gcm_ghash_avx,.-gcm_ghash_avx +___ +} else { +$code.=<<___; + jmp .L_ghash_clmul +.size gcm_ghash_avx,.-gcm_ghash_avx +___ +} + +$code.=<<___; +.align 64 +.Lbswap_mask: + .byte 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 +.L0x1c2_polynomial: + .byte 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc2 +.L7_mask: + .long 7,0,7,0 +.L7_mask_poly: + .long 7,0,`0xE1<<1`,0 +.align 64 +.type .Lrem_4bit,\@object +.Lrem_4bit: + .long 0,`0x0000<<16`,0,`0x1C20<<16`,0,`0x3840<<16`,0,`0x2460<<16` + .long 0,`0x7080<<16`,0,`0x6CA0<<16`,0,`0x48C0<<16`,0,`0x54E0<<16` + .long 0,`0xE100<<16`,0,`0xFD20<<16`,0,`0xD940<<16`,0,`0xC560<<16` + .long 0,`0x9180<<16`,0,`0x8DA0<<16`,0,`0xA9C0<<16`,0,`0xB5E0<<16` +.type .Lrem_8bit,\@object +.Lrem_8bit: + .value 0x0000,0x01C2,0x0384,0x0246,0x0708,0x06CA,0x048C,0x054E + .value 0x0E10,0x0FD2,0x0D94,0x0C56,0x0918,0x08DA,0x0A9C,0x0B5E + .value 0x1C20,0x1DE2,0x1FA4,0x1E66,0x1B28,0x1AEA,0x18AC,0x196E + .value 0x1230,0x13F2,0x11B4,0x1076,0x1538,0x14FA,0x16BC,0x177E + .value 0x3840,0x3982,0x3BC4,0x3A06,0x3F48,0x3E8A,0x3CCC,0x3D0E + .value 0x3650,0x3792,0x35D4,0x3416,0x3158,0x309A,0x32DC,0x331E + .value 0x2460,0x25A2,0x27E4,0x2626,0x2368,0x22AA,0x20EC,0x212E + .value 0x2A70,0x2BB2,0x29F4,0x2836,0x2D78,0x2CBA,0x2EFC,0x2F3E + .value 0x7080,0x7142,0x7304,0x72C6,0x7788,0x764A,0x740C,0x75CE + .value 0x7E90,0x7F52,0x7D14,0x7CD6,0x7998,0x785A,0x7A1C,0x7BDE + .value 0x6CA0,0x6D62,0x6F24,0x6EE6,0x6BA8,0x6A6A,0x682C,0x69EE + .value 0x62B0,0x6372,0x6134,0x60F6,0x65B8,0x647A,0x663C,0x67FE + .value 0x48C0,0x4902,0x4B44,0x4A86,0x4FC8,0x4E0A,0x4C4C,0x4D8E + .value 0x46D0,0x4712,0x4554,0x4496,0x41D8,0x401A,0x425C,0x439E + .value 0x54E0,0x5522,0x5764,0x56A6,0x53E8,0x522A,0x506C,0x51AE + .value 0x5AF0,0x5B32,0x5974,0x58B6,0x5DF8,0x5C3A,0x5E7C,0x5FBE + .value 0xE100,0xE0C2,0xE284,0xE346,0xE608,0xE7CA,0xE58C,0xE44E + .value 0xEF10,0xEED2,0xEC94,0xED56,0xE818,0xE9DA,0xEB9C,0xEA5E + .value 0xFD20,0xFCE2,0xFEA4,0xFF66,0xFA28,0xFBEA,0xF9AC,0xF86E + .value 0xF330,0xF2F2,0xF0B4,0xF176,0xF438,0xF5FA,0xF7BC,0xF67E + .value 0xD940,0xD882,0xDAC4,0xDB06,0xDE48,0xDF8A,0xDDCC,0xDC0E + .value 0xD750,0xD692,0xD4D4,0xD516,0xD058,0xD19A,0xD3DC,0xD21E + .value 0xC560,0xC4A2,0xC6E4,0xC726,0xC268,0xC3AA,0xC1EC,0xC02E + .value 0xCB70,0xCAB2,0xC8F4,0xC936,0xCC78,0xCDBA,0xCFFC,0xCE3E + .value 0x9180,0x9042,0x9204,0x93C6,0x9688,0x974A,0x950C,0x94CE + .value 0x9F90,0x9E52,0x9C14,0x9DD6,0x9898,0x995A,0x9B1C,0x9ADE + .value 0x8DA0,0x8C62,0x8E24,0x8FE6,0x8AA8,0x8B6A,0x892C,0x88EE + .value 0x83B0,0x8272,0x8034,0x81F6,0x84B8,0x857A,0x873C,0x86FE + .value 0xA9C0,0xA802,0xAA44,0xAB86,0xAEC8,0xAF0A,0xAD4C,0xAC8E + .value 0xA7D0,0xA612,0xA454,0xA596,0xA0D8,0xA11A,0xA35C,0xA29E + .value 0xB5E0,0xB422,0xB664,0xB7A6,0xB2E8,0xB32A,0xB16C,0xB0AE + .value 0xBBF0,0xBA32,0xB874,0xB9B6,0xBCF8,0xBD3A,0xBF7C,0xBEBE + +.asciz "GHASH for x86_64, CRYPTOGAMS by " +.align 64 +___ + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type se_handler,\@abi-omnipotent +.align 16 +se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lin_prologue + + lea 48+280(%rax),%rax # adjust "rsp" + + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov -48(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + +.Lin_prologue: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$`1232/8`,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size se_handler,.-se_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_gcm_gmult_4bit + .rva .LSEH_end_gcm_gmult_4bit + .rva .LSEH_info_gcm_gmult_4bit + + .rva .LSEH_begin_gcm_ghash_4bit + .rva .LSEH_end_gcm_ghash_4bit + .rva .LSEH_info_gcm_ghash_4bit + + .rva .LSEH_begin_gcm_init_clmul + .rva .LSEH_end_gcm_init_clmul + .rva .LSEH_info_gcm_init_clmul + + .rva .LSEH_begin_gcm_ghash_clmul + .rva .LSEH_end_gcm_ghash_clmul + .rva .LSEH_info_gcm_ghash_clmul +___ +$code.=<<___ if ($avx); + .rva .LSEH_begin_gcm_init_avx + .rva .LSEH_end_gcm_init_avx + .rva .LSEH_info_gcm_init_clmul + + .rva .LSEH_begin_gcm_ghash_avx + .rva .LSEH_end_gcm_ghash_avx + .rva .LSEH_info_gcm_ghash_clmul +___ +$code.=<<___; +.section .xdata +.align 8 +.LSEH_info_gcm_gmult_4bit: + .byte 9,0,0,0 + .rva se_handler + .rva .Lgmult_prologue,.Lgmult_epilogue # HandlerData +.LSEH_info_gcm_ghash_4bit: + .byte 9,0,0,0 + .rva se_handler + .rva .Lghash_prologue,.Lghash_epilogue # HandlerData +.LSEH_info_gcm_init_clmul: + .byte 0x01,0x08,0x03,0x00 + .byte 0x08,0x68,0x00,0x00 #movaps 0x00(rsp),xmm6 + .byte 0x04,0x22,0x00,0x00 #sub rsp,0x18 +.LSEH_info_gcm_ghash_clmul: + .byte 0x01,0x33,0x16,0x00 + .byte 0x33,0xf8,0x09,0x00 #movaps 0x90(rsp),xmm15 + .byte 0x2e,0xe8,0x08,0x00 #movaps 0x80(rsp),xmm14 + .byte 0x29,0xd8,0x07,0x00 #movaps 0x70(rsp),xmm13 + .byte 0x24,0xc8,0x06,0x00 #movaps 0x60(rsp),xmm12 + .byte 0x1f,0xb8,0x05,0x00 #movaps 0x50(rsp),xmm11 + .byte 0x1a,0xa8,0x04,0x00 #movaps 0x40(rsp),xmm10 + .byte 0x15,0x98,0x03,0x00 #movaps 0x30(rsp),xmm9 + .byte 0x10,0x88,0x02,0x00 #movaps 0x20(rsp),xmm8 + .byte 0x0c,0x78,0x01,0x00 #movaps 0x10(rsp),xmm7 + .byte 0x08,0x68,0x00,0x00 #movaps 0x00(rsp),xmm6 + .byte 0x04,0x01,0x15,0x00 #sub rsp,0xa8 +___ +} + +$code =~ s/\`([^\`]*)\`/eval($1)/gem; + +print $code; + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghashp8-ppc.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghashp8-ppc.pl new file mode 100755 index 000000000..6a2ac7129 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghashp8-ppc.pl @@ -0,0 +1,671 @@ +#! /usr/bin/env perl +# Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# GHASH for for PowerISA v2.07. +# +# July 2014 +# +# Accurate performance measurements are problematic, because it's +# always virtualized setup with possibly throttled processor. +# Relative comparison is therefore more informative. This initial +# version is ~2.1x slower than hardware-assisted AES-128-CTR, ~12x +# faster than "4-bit" integer-only compiler-generated 64-bit code. +# "Initial version" means that there is room for further improvement. + +# May 2016 +# +# 2x aggregated reduction improves performance by 50% (resulting +# performance on POWER8 is 1 cycle per processed byte), and 4x +# aggregated reduction - by 170% or 2.7x (resulting in 0.55 cpb). +# POWER9 delivers 0.51 cpb. + +$flavour=shift; +$output =shift; + +if ($flavour =~ /64/) { + $SIZE_T=8; + $LRSAVE=2*$SIZE_T; + $STU="stdu"; + $POP="ld"; + $PUSH="std"; + $UCMP="cmpld"; + $SHRI="srdi"; +} elsif ($flavour =~ /32/) { + $SIZE_T=4; + $LRSAVE=$SIZE_T; + $STU="stwu"; + $POP="lwz"; + $PUSH="stw"; + $UCMP="cmplw"; + $SHRI="srwi"; +} else { die "nonsense $flavour"; } + +$sp="r1"; +$FRAME=6*$SIZE_T+13*16; # 13*16 is for v20-v31 offload + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or +die "can't locate ppc-xlate.pl"; + +open STDOUT,"| $^X $xlate $flavour $output" || die "can't call $xlate: $!"; + +my ($Xip,$Htbl,$inp,$len)=map("r$_",(3..6)); # argument block + +my ($Xl,$Xm,$Xh,$IN)=map("v$_",(0..3)); +my ($zero,$t0,$t1,$t2,$xC2,$H,$Hh,$Hl,$lemask)=map("v$_",(4..12)); +my ($Xl1,$Xm1,$Xh1,$IN1,$H2,$H2h,$H2l)=map("v$_",(13..19)); +my $vrsave="r12"; + +$code=<<___; +.machine "any" + +.text + +.globl .gcm_init_p8 +.align 5 +.gcm_init_p8: + li r0,-4096 + li r8,0x10 + mfspr $vrsave,256 + li r9,0x20 + mtspr 256,r0 + li r10,0x30 + lvx_u $H,0,r4 # load H + + vspltisb $xC2,-16 # 0xf0 + vspltisb $t0,1 # one + vaddubm $xC2,$xC2,$xC2 # 0xe0 + vxor $zero,$zero,$zero + vor $xC2,$xC2,$t0 # 0xe1 + vsldoi $xC2,$xC2,$zero,15 # 0xe1... + vsldoi $t1,$zero,$t0,1 # ...1 + vaddubm $xC2,$xC2,$xC2 # 0xc2... + vspltisb $t2,7 + vor $xC2,$xC2,$t1 # 0xc2....01 + vspltb $t1,$H,0 # most significant byte + vsl $H,$H,$t0 # H<<=1 + vsrab $t1,$t1,$t2 # broadcast carry bit + vand $t1,$t1,$xC2 + vxor $IN,$H,$t1 # twisted H + + vsldoi $H,$IN,$IN,8 # twist even more ... + vsldoi $xC2,$zero,$xC2,8 # 0xc2.0 + vsldoi $Hl,$zero,$H,8 # ... and split + vsldoi $Hh,$H,$zero,8 + + stvx_u $xC2,0,r3 # save pre-computed table + stvx_u $Hl,r8,r3 + li r8,0x40 + stvx_u $H, r9,r3 + li r9,0x50 + stvx_u $Hh,r10,r3 + li r10,0x60 + + vpmsumd $Xl,$IN,$Hl # H.lo·H.lo + vpmsumd $Xm,$IN,$H # H.hi·H.lo+H.lo·H.hi + vpmsumd $Xh,$IN,$Hh # H.hi·H.hi + + vpmsumd $t2,$Xl,$xC2 # 1st reduction phase + + vsldoi $t0,$Xm,$zero,8 + vsldoi $t1,$zero,$Xm,8 + vxor $Xl,$Xl,$t0 + vxor $Xh,$Xh,$t1 + + vsldoi $Xl,$Xl,$Xl,8 + vxor $Xl,$Xl,$t2 + + vsldoi $t1,$Xl,$Xl,8 # 2nd reduction phase + vpmsumd $Xl,$Xl,$xC2 + vxor $t1,$t1,$Xh + vxor $IN1,$Xl,$t1 + + vsldoi $H2,$IN1,$IN1,8 + vsldoi $H2l,$zero,$H2,8 + vsldoi $H2h,$H2,$zero,8 + + stvx_u $H2l,r8,r3 # save H^2 + li r8,0x70 + stvx_u $H2,r9,r3 + li r9,0x80 + stvx_u $H2h,r10,r3 + li r10,0x90 +___ +{ +my ($t4,$t5,$t6) = ($Hl,$H,$Hh); +$code.=<<___; + vpmsumd $Xl,$IN,$H2l # H.lo·H^2.lo + vpmsumd $Xl1,$IN1,$H2l # H^2.lo·H^2.lo + vpmsumd $Xm,$IN,$H2 # H.hi·H^2.lo+H.lo·H^2.hi + vpmsumd $Xm1,$IN1,$H2 # H^2.hi·H^2.lo+H^2.lo·H^2.hi + vpmsumd $Xh,$IN,$H2h # H.hi·H^2.hi + vpmsumd $Xh1,$IN1,$H2h # H^2.hi·H^2.hi + + vpmsumd $t2,$Xl,$xC2 # 1st reduction phase + vpmsumd $t6,$Xl1,$xC2 # 1st reduction phase + + vsldoi $t0,$Xm,$zero,8 + vsldoi $t1,$zero,$Xm,8 + vsldoi $t4,$Xm1,$zero,8 + vsldoi $t5,$zero,$Xm1,8 + vxor $Xl,$Xl,$t0 + vxor $Xh,$Xh,$t1 + vxor $Xl1,$Xl1,$t4 + vxor $Xh1,$Xh1,$t5 + + vsldoi $Xl,$Xl,$Xl,8 + vsldoi $Xl1,$Xl1,$Xl1,8 + vxor $Xl,$Xl,$t2 + vxor $Xl1,$Xl1,$t6 + + vsldoi $t1,$Xl,$Xl,8 # 2nd reduction phase + vsldoi $t5,$Xl1,$Xl1,8 # 2nd reduction phase + vpmsumd $Xl,$Xl,$xC2 + vpmsumd $Xl1,$Xl1,$xC2 + vxor $t1,$t1,$Xh + vxor $t5,$t5,$Xh1 + vxor $Xl,$Xl,$t1 + vxor $Xl1,$Xl1,$t5 + + vsldoi $H,$Xl,$Xl,8 + vsldoi $H2,$Xl1,$Xl1,8 + vsldoi $Hl,$zero,$H,8 + vsldoi $Hh,$H,$zero,8 + vsldoi $H2l,$zero,$H2,8 + vsldoi $H2h,$H2,$zero,8 + + stvx_u $Hl,r8,r3 # save H^3 + li r8,0xa0 + stvx_u $H,r9,r3 + li r9,0xb0 + stvx_u $Hh,r10,r3 + li r10,0xc0 + stvx_u $H2l,r8,r3 # save H^4 + stvx_u $H2,r9,r3 + stvx_u $H2h,r10,r3 + + mtspr 256,$vrsave + blr + .long 0 + .byte 0,12,0x14,0,0,0,2,0 + .long 0 +.size .gcm_init_p8,.-.gcm_init_p8 +___ +} +$code.=<<___; +.globl .gcm_gmult_p8 +.align 5 +.gcm_gmult_p8: + lis r0,0xfff8 + li r8,0x10 + mfspr $vrsave,256 + li r9,0x20 + mtspr 256,r0 + li r10,0x30 + lvx_u $IN,0,$Xip # load Xi + + lvx_u $Hl,r8,$Htbl # load pre-computed table + le?lvsl $lemask,r0,r0 + lvx_u $H, r9,$Htbl + le?vspltisb $t0,0x07 + lvx_u $Hh,r10,$Htbl + le?vxor $lemask,$lemask,$t0 + lvx_u $xC2,0,$Htbl + le?vperm $IN,$IN,$IN,$lemask + vxor $zero,$zero,$zero + + vpmsumd $Xl,$IN,$Hl # H.lo·Xi.lo + vpmsumd $Xm,$IN,$H # H.hi·Xi.lo+H.lo·Xi.hi + vpmsumd $Xh,$IN,$Hh # H.hi·Xi.hi + + vpmsumd $t2,$Xl,$xC2 # 1st reduction phase + + vsldoi $t0,$Xm,$zero,8 + vsldoi $t1,$zero,$Xm,8 + vxor $Xl,$Xl,$t0 + vxor $Xh,$Xh,$t1 + + vsldoi $Xl,$Xl,$Xl,8 + vxor $Xl,$Xl,$t2 + + vsldoi $t1,$Xl,$Xl,8 # 2nd reduction phase + vpmsumd $Xl,$Xl,$xC2 + vxor $t1,$t1,$Xh + vxor $Xl,$Xl,$t1 + + le?vperm $Xl,$Xl,$Xl,$lemask + stvx_u $Xl,0,$Xip # write out Xi + + mtspr 256,$vrsave + blr + .long 0 + .byte 0,12,0x14,0,0,0,2,0 + .long 0 +.size .gcm_gmult_p8,.-.gcm_gmult_p8 + +.globl .gcm_ghash_p8 +.align 5 +.gcm_ghash_p8: + li r0,-4096 + li r8,0x10 + mfspr $vrsave,256 + li r9,0x20 + mtspr 256,r0 + li r10,0x30 + lvx_u $Xl,0,$Xip # load Xi + + lvx_u $Hl,r8,$Htbl # load pre-computed table + li r8,0x40 + le?lvsl $lemask,r0,r0 + lvx_u $H, r9,$Htbl + li r9,0x50 + le?vspltisb $t0,0x07 + lvx_u $Hh,r10,$Htbl + li r10,0x60 + le?vxor $lemask,$lemask,$t0 + lvx_u $xC2,0,$Htbl + le?vperm $Xl,$Xl,$Xl,$lemask + vxor $zero,$zero,$zero + + ${UCMP}i $len,64 + bge Lgcm_ghash_p8_4x + + lvx_u $IN,0,$inp + addi $inp,$inp,16 + subic. $len,$len,16 + le?vperm $IN,$IN,$IN,$lemask + vxor $IN,$IN,$Xl + beq Lshort + + lvx_u $H2l,r8,$Htbl # load H^2 + li r8,16 + lvx_u $H2, r9,$Htbl + add r9,$inp,$len # end of input + lvx_u $H2h,r10,$Htbl + be?b Loop_2x + +.align 5 +Loop_2x: + lvx_u $IN1,0,$inp + le?vperm $IN1,$IN1,$IN1,$lemask + + subic $len,$len,32 + vpmsumd $Xl,$IN,$H2l # H^2.lo·Xi.lo + vpmsumd $Xl1,$IN1,$Hl # H.lo·Xi+1.lo + subfe r0,r0,r0 # borrow?-1:0 + vpmsumd $Xm,$IN,$H2 # H^2.hi·Xi.lo+H^2.lo·Xi.hi + vpmsumd $Xm1,$IN1,$H # H.hi·Xi+1.lo+H.lo·Xi+1.hi + and r0,r0,$len + vpmsumd $Xh,$IN,$H2h # H^2.hi·Xi.hi + vpmsumd $Xh1,$IN1,$Hh # H.hi·Xi+1.hi + add $inp,$inp,r0 + + vxor $Xl,$Xl,$Xl1 + vxor $Xm,$Xm,$Xm1 + + vpmsumd $t2,$Xl,$xC2 # 1st reduction phase + + vsldoi $t0,$Xm,$zero,8 + vsldoi $t1,$zero,$Xm,8 + vxor $Xh,$Xh,$Xh1 + vxor $Xl,$Xl,$t0 + vxor $Xh,$Xh,$t1 + + vsldoi $Xl,$Xl,$Xl,8 + vxor $Xl,$Xl,$t2 + lvx_u $IN,r8,$inp + addi $inp,$inp,32 + + vsldoi $t1,$Xl,$Xl,8 # 2nd reduction phase + vpmsumd $Xl,$Xl,$xC2 + le?vperm $IN,$IN,$IN,$lemask + vxor $t1,$t1,$Xh + vxor $IN,$IN,$t1 + vxor $IN,$IN,$Xl + $UCMP r9,$inp + bgt Loop_2x # done yet? + + cmplwi $len,0 + bne Leven + +Lshort: + vpmsumd $Xl,$IN,$Hl # H.lo·Xi.lo + vpmsumd $Xm,$IN,$H # H.hi·Xi.lo+H.lo·Xi.hi + vpmsumd $Xh,$IN,$Hh # H.hi·Xi.hi + + vpmsumd $t2,$Xl,$xC2 # 1st reduction phase + + vsldoi $t0,$Xm,$zero,8 + vsldoi $t1,$zero,$Xm,8 + vxor $Xl,$Xl,$t0 + vxor $Xh,$Xh,$t1 + + vsldoi $Xl,$Xl,$Xl,8 + vxor $Xl,$Xl,$t2 + + vsldoi $t1,$Xl,$Xl,8 # 2nd reduction phase + vpmsumd $Xl,$Xl,$xC2 + vxor $t1,$t1,$Xh + +Leven: + vxor $Xl,$Xl,$t1 + le?vperm $Xl,$Xl,$Xl,$lemask + stvx_u $Xl,0,$Xip # write out Xi + + mtspr 256,$vrsave + blr + .long 0 + .byte 0,12,0x14,0,0,0,4,0 + .long 0 +___ +{ +my ($Xl3,$Xm2,$IN2,$H3l,$H3,$H3h, + $Xh3,$Xm3,$IN3,$H4l,$H4,$H4h) = map("v$_",(20..31)); +my $IN0=$IN; +my ($H21l,$H21h,$loperm,$hiperm) = ($Hl,$Hh,$H2l,$H2h); + +$code.=<<___; +.align 5 +.gcm_ghash_p8_4x: +Lgcm_ghash_p8_4x: + $STU $sp,-$FRAME($sp) + li r10,`15+6*$SIZE_T` + li r11,`31+6*$SIZE_T` + stvx v20,r10,$sp + addi r10,r10,32 + stvx v21,r11,$sp + addi r11,r11,32 + stvx v22,r10,$sp + addi r10,r10,32 + stvx v23,r11,$sp + addi r11,r11,32 + stvx v24,r10,$sp + addi r10,r10,32 + stvx v25,r11,$sp + addi r11,r11,32 + stvx v26,r10,$sp + addi r10,r10,32 + stvx v27,r11,$sp + addi r11,r11,32 + stvx v28,r10,$sp + addi r10,r10,32 + stvx v29,r11,$sp + addi r11,r11,32 + stvx v30,r10,$sp + li r10,0x60 + stvx v31,r11,$sp + li r0,-1 + stw $vrsave,`$FRAME-4`($sp) # save vrsave + mtspr 256,r0 # preserve all AltiVec registers + + lvsl $t0,0,r8 # 0x0001..0e0f + #lvx_u $H2l,r8,$Htbl # load H^2 + li r8,0x70 + lvx_u $H2, r9,$Htbl + li r9,0x80 + vspltisb $t1,8 # 0x0808..0808 + #lvx_u $H2h,r10,$Htbl + li r10,0x90 + lvx_u $H3l,r8,$Htbl # load H^3 + li r8,0xa0 + lvx_u $H3, r9,$Htbl + li r9,0xb0 + lvx_u $H3h,r10,$Htbl + li r10,0xc0 + lvx_u $H4l,r8,$Htbl # load H^4 + li r8,0x10 + lvx_u $H4, r9,$Htbl + li r9,0x20 + lvx_u $H4h,r10,$Htbl + li r10,0x30 + + vsldoi $t2,$zero,$t1,8 # 0x0000..0808 + vaddubm $hiperm,$t0,$t2 # 0x0001..1617 + vaddubm $loperm,$t1,$hiperm # 0x0809..1e1f + + $SHRI $len,$len,4 # this allows to use sign bit + # as carry + lvx_u $IN0,0,$inp # load input + lvx_u $IN1,r8,$inp + subic. $len,$len,8 + lvx_u $IN2,r9,$inp + lvx_u $IN3,r10,$inp + addi $inp,$inp,0x40 + le?vperm $IN0,$IN0,$IN0,$lemask + le?vperm $IN1,$IN1,$IN1,$lemask + le?vperm $IN2,$IN2,$IN2,$lemask + le?vperm $IN3,$IN3,$IN3,$lemask + + vxor $Xh,$IN0,$Xl + + vpmsumd $Xl1,$IN1,$H3l + vpmsumd $Xm1,$IN1,$H3 + vpmsumd $Xh1,$IN1,$H3h + + vperm $H21l,$H2,$H,$hiperm + vperm $t0,$IN2,$IN3,$loperm + vperm $H21h,$H2,$H,$loperm + vperm $t1,$IN2,$IN3,$hiperm + vpmsumd $Xm2,$IN2,$H2 # H^2.lo·Xi+2.hi+H^2.hi·Xi+2.lo + vpmsumd $Xl3,$t0,$H21l # H^2.lo·Xi+2.lo+H.lo·Xi+3.lo + vpmsumd $Xm3,$IN3,$H # H.hi·Xi+3.lo +H.lo·Xi+3.hi + vpmsumd $Xh3,$t1,$H21h # H^2.hi·Xi+2.hi+H.hi·Xi+3.hi + + vxor $Xm2,$Xm2,$Xm1 + vxor $Xl3,$Xl3,$Xl1 + vxor $Xm3,$Xm3,$Xm2 + vxor $Xh3,$Xh3,$Xh1 + + blt Ltail_4x + +Loop_4x: + lvx_u $IN0,0,$inp + lvx_u $IN1,r8,$inp + subic. $len,$len,4 + lvx_u $IN2,r9,$inp + lvx_u $IN3,r10,$inp + addi $inp,$inp,0x40 + le?vperm $IN1,$IN1,$IN1,$lemask + le?vperm $IN2,$IN2,$IN2,$lemask + le?vperm $IN3,$IN3,$IN3,$lemask + le?vperm $IN0,$IN0,$IN0,$lemask + + vpmsumd $Xl,$Xh,$H4l # H^4.lo·Xi.lo + vpmsumd $Xm,$Xh,$H4 # H^4.hi·Xi.lo+H^4.lo·Xi.hi + vpmsumd $Xh,$Xh,$H4h # H^4.hi·Xi.hi + vpmsumd $Xl1,$IN1,$H3l + vpmsumd $Xm1,$IN1,$H3 + vpmsumd $Xh1,$IN1,$H3h + + vxor $Xl,$Xl,$Xl3 + vxor $Xm,$Xm,$Xm3 + vxor $Xh,$Xh,$Xh3 + vperm $t0,$IN2,$IN3,$loperm + vperm $t1,$IN2,$IN3,$hiperm + + vpmsumd $t2,$Xl,$xC2 # 1st reduction phase + vpmsumd $Xl3,$t0,$H21l # H.lo·Xi+3.lo +H^2.lo·Xi+2.lo + vpmsumd $Xh3,$t1,$H21h # H.hi·Xi+3.hi +H^2.hi·Xi+2.hi + + vsldoi $t0,$Xm,$zero,8 + vsldoi $t1,$zero,$Xm,8 + vxor $Xl,$Xl,$t0 + vxor $Xh,$Xh,$t1 + + vsldoi $Xl,$Xl,$Xl,8 + vxor $Xl,$Xl,$t2 + + vsldoi $t1,$Xl,$Xl,8 # 2nd reduction phase + vpmsumd $Xm2,$IN2,$H2 # H^2.hi·Xi+2.lo+H^2.lo·Xi+2.hi + vpmsumd $Xm3,$IN3,$H # H.hi·Xi+3.lo +H.lo·Xi+3.hi + vpmsumd $Xl,$Xl,$xC2 + + vxor $Xl3,$Xl3,$Xl1 + vxor $Xh3,$Xh3,$Xh1 + vxor $Xh,$Xh,$IN0 + vxor $Xm2,$Xm2,$Xm1 + vxor $Xh,$Xh,$t1 + vxor $Xm3,$Xm3,$Xm2 + vxor $Xh,$Xh,$Xl + bge Loop_4x + +Ltail_4x: + vpmsumd $Xl,$Xh,$H4l # H^4.lo·Xi.lo + vpmsumd $Xm,$Xh,$H4 # H^4.hi·Xi.lo+H^4.lo·Xi.hi + vpmsumd $Xh,$Xh,$H4h # H^4.hi·Xi.hi + + vxor $Xl,$Xl,$Xl3 + vxor $Xm,$Xm,$Xm3 + + vpmsumd $t2,$Xl,$xC2 # 1st reduction phase + + vsldoi $t0,$Xm,$zero,8 + vsldoi $t1,$zero,$Xm,8 + vxor $Xh,$Xh,$Xh3 + vxor $Xl,$Xl,$t0 + vxor $Xh,$Xh,$t1 + + vsldoi $Xl,$Xl,$Xl,8 + vxor $Xl,$Xl,$t2 + + vsldoi $t1,$Xl,$Xl,8 # 2nd reduction phase + vpmsumd $Xl,$Xl,$xC2 + vxor $t1,$t1,$Xh + vxor $Xl,$Xl,$t1 + + addic. $len,$len,4 + beq Ldone_4x + + lvx_u $IN0,0,$inp + ${UCMP}i $len,2 + li $len,-4 + blt Lone + lvx_u $IN1,r8,$inp + beq Ltwo + +Lthree: + lvx_u $IN2,r9,$inp + le?vperm $IN0,$IN0,$IN0,$lemask + le?vperm $IN1,$IN1,$IN1,$lemask + le?vperm $IN2,$IN2,$IN2,$lemask + + vxor $Xh,$IN0,$Xl + vmr $H4l,$H3l + vmr $H4, $H3 + vmr $H4h,$H3h + + vperm $t0,$IN1,$IN2,$loperm + vperm $t1,$IN1,$IN2,$hiperm + vpmsumd $Xm2,$IN1,$H2 # H^2.lo·Xi+1.hi+H^2.hi·Xi+1.lo + vpmsumd $Xm3,$IN2,$H # H.hi·Xi+2.lo +H.lo·Xi+2.hi + vpmsumd $Xl3,$t0,$H21l # H^2.lo·Xi+1.lo+H.lo·Xi+2.lo + vpmsumd $Xh3,$t1,$H21h # H^2.hi·Xi+1.hi+H.hi·Xi+2.hi + + vxor $Xm3,$Xm3,$Xm2 + b Ltail_4x + +.align 4 +Ltwo: + le?vperm $IN0,$IN0,$IN0,$lemask + le?vperm $IN1,$IN1,$IN1,$lemask + + vxor $Xh,$IN0,$Xl + vperm $t0,$zero,$IN1,$loperm + vperm $t1,$zero,$IN1,$hiperm + + vsldoi $H4l,$zero,$H2,8 + vmr $H4, $H2 + vsldoi $H4h,$H2,$zero,8 + + vpmsumd $Xl3,$t0, $H21l # H.lo·Xi+1.lo + vpmsumd $Xm3,$IN1,$H # H.hi·Xi+1.lo+H.lo·Xi+2.hi + vpmsumd $Xh3,$t1, $H21h # H.hi·Xi+1.hi + + b Ltail_4x + +.align 4 +Lone: + le?vperm $IN0,$IN0,$IN0,$lemask + + vsldoi $H4l,$zero,$H,8 + vmr $H4, $H + vsldoi $H4h,$H,$zero,8 + + vxor $Xh,$IN0,$Xl + vxor $Xl3,$Xl3,$Xl3 + vxor $Xm3,$Xm3,$Xm3 + vxor $Xh3,$Xh3,$Xh3 + + b Ltail_4x + +Ldone_4x: + le?vperm $Xl,$Xl,$Xl,$lemask + stvx_u $Xl,0,$Xip # write out Xi + + li r10,`15+6*$SIZE_T` + li r11,`31+6*$SIZE_T` + mtspr 256,$vrsave + lvx v20,r10,$sp + addi r10,r10,32 + lvx v21,r11,$sp + addi r11,r11,32 + lvx v22,r10,$sp + addi r10,r10,32 + lvx v23,r11,$sp + addi r11,r11,32 + lvx v24,r10,$sp + addi r10,r10,32 + lvx v25,r11,$sp + addi r11,r11,32 + lvx v26,r10,$sp + addi r10,r10,32 + lvx v27,r11,$sp + addi r11,r11,32 + lvx v28,r10,$sp + addi r10,r10,32 + lvx v29,r11,$sp + addi r11,r11,32 + lvx v30,r10,$sp + lvx v31,r11,$sp + addi $sp,$sp,$FRAME + blr + .long 0 + .byte 0,12,0x04,0,0x80,0,4,0 + .long 0 +___ +} +$code.=<<___; +.size .gcm_ghash_p8,.-.gcm_ghash_p8 + +.asciz "GHASH for PowerISA 2.07, CRYPTOGAMS by " +.align 2 +___ + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/geo; + + if ($flavour =~ /le$/o) { # little-endian + s/le\?//o or + s/be\?/#be#/o; + } else { + s/le\?/#le#/o or + s/be\?//o; + } + print $_,"\n"; +} + +close STDOUT; # enforce flush diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghashv8-armx.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghashv8-armx.pl new file mode 100644 index 000000000..47e882008 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/asm/ghashv8-armx.pl @@ -0,0 +1,781 @@ +#! /usr/bin/env perl +# Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# GHASH for ARMv8 Crypto Extension, 64-bit polynomial multiplication. +# +# June 2014 +# +# Initial version was developed in tight cooperation with Ard +# Biesheuvel of Linaro from bits-n-pieces from other assembly modules. +# Just like aesv8-armx.pl this module supports both AArch32 and +# AArch64 execution modes. +# +# July 2014 +# +# Implement 2x aggregated reduction [see ghash-x86.pl for background +# information]. +# +# November 2017 +# +# AArch64 register bank to "accommodate" 4x aggregated reduction and +# improve performance by 20-70% depending on processor. +# +# Current performance in cycles per processed byte: +# +# 64-bit PMULL 32-bit PMULL 32-bit NEON(*) +# Apple A7 0.58 0.92 5.62 +# Cortex-A53 0.85 1.01 8.39 +# Cortex-A57 0.73 1.17 7.61 +# Denver 0.51 0.65 6.02 +# Mongoose 0.65 1.10 8.06 +# Kryo 0.76 1.16 8.00 +# +# (*) presented for reference/comparison purposes; + +$flavour = shift; +$output = shift; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or +die "can't locate arm-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +$Xi="x0"; # argument block +$Htbl="x1"; +$inp="x2"; +$len="x3"; + +$inc="x12"; + +{ +my ($Xl,$Xm,$Xh,$IN)=map("q$_",(0..3)); +my ($t0,$t1,$t2,$xC2,$H,$Hhl,$H2)=map("q$_",(8..14)); + +$code=<<___; +#include "arm_arch.h" + +#if __ARM_MAX_ARCH__>=7 +.text +___ +$code.=".arch armv8-a+crypto\n" if ($flavour =~ /64/); +$code.=<<___ if ($flavour !~ /64/); +.fpu neon +.code 32 +#undef __thumb2__ +___ + +################################################################################ +# void gcm_init_v8(u128 Htable[16],const u64 H[2]); +# +# input: 128-bit H - secret parameter E(K,0^128) +# output: precomputed table filled with degrees of twisted H; +# H is twisted to handle reverse bitness of GHASH; +# only few of 16 slots of Htable[16] are used; +# data is opaque to outside world (which allows to +# optimize the code independently); +# +$code.=<<___; +.global gcm_init_v8 +.type gcm_init_v8,%function +.align 4 +gcm_init_v8: + vld1.64 {$t1},[x1] @ load input H + vmov.i8 $xC2,#0xe1 + vshl.i64 $xC2,$xC2,#57 @ 0xc2.0 + vext.8 $IN,$t1,$t1,#8 + vshr.u64 $t2,$xC2,#63 + vdup.32 $t1,${t1}[1] + vext.8 $t0,$t2,$xC2,#8 @ t0=0xc2....01 + vshr.u64 $t2,$IN,#63 + vshr.s32 $t1,$t1,#31 @ broadcast carry bit + vand $t2,$t2,$t0 + vshl.i64 $IN,$IN,#1 + vext.8 $t2,$t2,$t2,#8 + vand $t0,$t0,$t1 + vorr $IN,$IN,$t2 @ H<<<=1 + veor $H,$IN,$t0 @ twisted H + vst1.64 {$H},[x0],#16 @ store Htable[0] + + @ calculate H^2 + vext.8 $t0,$H,$H,#8 @ Karatsuba pre-processing + vpmull.p64 $Xl,$H,$H + veor $t0,$t0,$H + vpmull2.p64 $Xh,$H,$H + vpmull.p64 $Xm,$t0,$t0 + + vext.8 $t1,$Xl,$Xh,#8 @ Karatsuba post-processing + veor $t2,$Xl,$Xh + veor $Xm,$Xm,$t1 + veor $Xm,$Xm,$t2 + vpmull.p64 $t2,$Xl,$xC2 @ 1st phase + + vmov $Xh#lo,$Xm#hi @ Xh|Xm - 256-bit result + vmov $Xm#hi,$Xl#lo @ Xm is rotated Xl + veor $Xl,$Xm,$t2 + + vext.8 $t2,$Xl,$Xl,#8 @ 2nd phase + vpmull.p64 $Xl,$Xl,$xC2 + veor $t2,$t2,$Xh + veor $H2,$Xl,$t2 + + vext.8 $t1,$H2,$H2,#8 @ Karatsuba pre-processing + veor $t1,$t1,$H2 + vext.8 $Hhl,$t0,$t1,#8 @ pack Karatsuba pre-processed + vst1.64 {$Hhl-$H2},[x0],#32 @ store Htable[1..2] +___ +if ($flavour =~ /64/) { +my ($t3,$Yl,$Ym,$Yh) = map("q$_",(4..7)); + +$code.=<<___; + @ calculate H^3 and H^4 + vpmull.p64 $Xl,$H, $H2 + vpmull.p64 $Yl,$H2,$H2 + vpmull2.p64 $Xh,$H, $H2 + vpmull2.p64 $Yh,$H2,$H2 + vpmull.p64 $Xm,$t0,$t1 + vpmull.p64 $Ym,$t1,$t1 + + vext.8 $t0,$Xl,$Xh,#8 @ Karatsuba post-processing + vext.8 $t1,$Yl,$Yh,#8 + veor $t2,$Xl,$Xh + veor $Xm,$Xm,$t0 + veor $t3,$Yl,$Yh + veor $Ym,$Ym,$t1 + veor $Xm,$Xm,$t2 + vpmull.p64 $t2,$Xl,$xC2 @ 1st phase + veor $Ym,$Ym,$t3 + vpmull.p64 $t3,$Yl,$xC2 + + vmov $Xh#lo,$Xm#hi @ Xh|Xm - 256-bit result + vmov $Yh#lo,$Ym#hi + vmov $Xm#hi,$Xl#lo @ Xm is rotated Xl + vmov $Ym#hi,$Yl#lo + veor $Xl,$Xm,$t2 + veor $Yl,$Ym,$t3 + + vext.8 $t2,$Xl,$Xl,#8 @ 2nd phase + vext.8 $t3,$Yl,$Yl,#8 + vpmull.p64 $Xl,$Xl,$xC2 + vpmull.p64 $Yl,$Yl,$xC2 + veor $t2,$t2,$Xh + veor $t3,$t3,$Yh + veor $H, $Xl,$t2 @ H^3 + veor $H2,$Yl,$t3 @ H^4 + + vext.8 $t0,$H, $H,#8 @ Karatsuba pre-processing + vext.8 $t1,$H2,$H2,#8 + veor $t0,$t0,$H + veor $t1,$t1,$H2 + vext.8 $Hhl,$t0,$t1,#8 @ pack Karatsuba pre-processed + vst1.64 {$H-$H2},[x0] @ store Htable[3..5] +___ +} +$code.=<<___; + ret +.size gcm_init_v8,.-gcm_init_v8 +___ +################################################################################ +# void gcm_gmult_v8(u64 Xi[2],const u128 Htable[16]); +# +# input: Xi - current hash value; +# Htable - table precomputed in gcm_init_v8; +# output: Xi - next hash value Xi; +# +$code.=<<___; +.global gcm_gmult_v8 +.type gcm_gmult_v8,%function +.align 4 +gcm_gmult_v8: + vld1.64 {$t1},[$Xi] @ load Xi + vmov.i8 $xC2,#0xe1 + vld1.64 {$H-$Hhl},[$Htbl] @ load twisted H, ... + vshl.u64 $xC2,$xC2,#57 +#ifndef __ARMEB__ + vrev64.8 $t1,$t1 +#endif + vext.8 $IN,$t1,$t1,#8 + + vpmull.p64 $Xl,$H,$IN @ H.lo·Xi.lo + veor $t1,$t1,$IN @ Karatsuba pre-processing + vpmull2.p64 $Xh,$H,$IN @ H.hi·Xi.hi + vpmull.p64 $Xm,$Hhl,$t1 @ (H.lo+H.hi)·(Xi.lo+Xi.hi) + + vext.8 $t1,$Xl,$Xh,#8 @ Karatsuba post-processing + veor $t2,$Xl,$Xh + veor $Xm,$Xm,$t1 + veor $Xm,$Xm,$t2 + vpmull.p64 $t2,$Xl,$xC2 @ 1st phase of reduction + + vmov $Xh#lo,$Xm#hi @ Xh|Xm - 256-bit result + vmov $Xm#hi,$Xl#lo @ Xm is rotated Xl + veor $Xl,$Xm,$t2 + + vext.8 $t2,$Xl,$Xl,#8 @ 2nd phase of reduction + vpmull.p64 $Xl,$Xl,$xC2 + veor $t2,$t2,$Xh + veor $Xl,$Xl,$t2 + +#ifndef __ARMEB__ + vrev64.8 $Xl,$Xl +#endif + vext.8 $Xl,$Xl,$Xl,#8 + vst1.64 {$Xl},[$Xi] @ write out Xi + + ret +.size gcm_gmult_v8,.-gcm_gmult_v8 +___ +################################################################################ +# void gcm_ghash_v8(u64 Xi[2],const u128 Htable[16],const u8 *inp,size_t len); +# +# input: table precomputed in gcm_init_v8; +# current hash value Xi; +# pointer to input data; +# length of input data in bytes, but divisible by block size; +# output: next hash value Xi; +# +$code.=<<___; +.global gcm_ghash_v8 +.type gcm_ghash_v8,%function +.align 4 +gcm_ghash_v8: +___ +$code.=<<___ if ($flavour =~ /64/); + cmp $len,#64 + b.hs .Lgcm_ghash_v8_4x +___ +$code.=<<___ if ($flavour !~ /64/); + vstmdb sp!,{d8-d15} @ 32-bit ABI says so +___ +$code.=<<___; + vld1.64 {$Xl},[$Xi] @ load [rotated] Xi + @ "[rotated]" means that + @ loaded value would have + @ to be rotated in order to + @ make it appear as in + @ algorithm specification + subs $len,$len,#32 @ see if $len is 32 or larger + mov $inc,#16 @ $inc is used as post- + @ increment for input pointer; + @ as loop is modulo-scheduled + @ $inc is zeroed just in time + @ to preclude overstepping + @ inp[len], which means that + @ last block[s] are actually + @ loaded twice, but last + @ copy is not processed + vld1.64 {$H-$Hhl},[$Htbl],#32 @ load twisted H, ..., H^2 + vmov.i8 $xC2,#0xe1 + vld1.64 {$H2},[$Htbl] + cclr $inc,eq @ is it time to zero $inc? + vext.8 $Xl,$Xl,$Xl,#8 @ rotate Xi + vld1.64 {$t0},[$inp],#16 @ load [rotated] I[0] + vshl.u64 $xC2,$xC2,#57 @ compose 0xc2.0 constant +#ifndef __ARMEB__ + vrev64.8 $t0,$t0 + vrev64.8 $Xl,$Xl +#endif + vext.8 $IN,$t0,$t0,#8 @ rotate I[0] + b.lo .Lodd_tail_v8 @ $len was less than 32 +___ +{ my ($Xln,$Xmn,$Xhn,$In) = map("q$_",(4..7)); + ####### + # Xi+2 =[H*(Ii+1 + Xi+1)] mod P = + # [(H*Ii+1) + (H*Xi+1)] mod P = + # [(H*Ii+1) + H^2*(Ii+Xi)] mod P + # +$code.=<<___; + vld1.64 {$t1},[$inp],$inc @ load [rotated] I[1] +#ifndef __ARMEB__ + vrev64.8 $t1,$t1 +#endif + vext.8 $In,$t1,$t1,#8 + veor $IN,$IN,$Xl @ I[i]^=Xi + vpmull.p64 $Xln,$H,$In @ H·Ii+1 + veor $t1,$t1,$In @ Karatsuba pre-processing + vpmull2.p64 $Xhn,$H,$In + b .Loop_mod2x_v8 + +.align 4 +.Loop_mod2x_v8: + vext.8 $t2,$IN,$IN,#8 + subs $len,$len,#32 @ is there more data? + vpmull.p64 $Xl,$H2,$IN @ H^2.lo·Xi.lo + cclr $inc,lo @ is it time to zero $inc? + + vpmull.p64 $Xmn,$Hhl,$t1 + veor $t2,$t2,$IN @ Karatsuba pre-processing + vpmull2.p64 $Xh,$H2,$IN @ H^2.hi·Xi.hi + veor $Xl,$Xl,$Xln @ accumulate + vpmull2.p64 $Xm,$Hhl,$t2 @ (H^2.lo+H^2.hi)·(Xi.lo+Xi.hi) + vld1.64 {$t0},[$inp],$inc @ load [rotated] I[i+2] + + veor $Xh,$Xh,$Xhn + cclr $inc,eq @ is it time to zero $inc? + veor $Xm,$Xm,$Xmn + + vext.8 $t1,$Xl,$Xh,#8 @ Karatsuba post-processing + veor $t2,$Xl,$Xh + veor $Xm,$Xm,$t1 + vld1.64 {$t1},[$inp],$inc @ load [rotated] I[i+3] +#ifndef __ARMEB__ + vrev64.8 $t0,$t0 +#endif + veor $Xm,$Xm,$t2 + vpmull.p64 $t2,$Xl,$xC2 @ 1st phase of reduction + +#ifndef __ARMEB__ + vrev64.8 $t1,$t1 +#endif + vmov $Xh#lo,$Xm#hi @ Xh|Xm - 256-bit result + vmov $Xm#hi,$Xl#lo @ Xm is rotated Xl + vext.8 $In,$t1,$t1,#8 + vext.8 $IN,$t0,$t0,#8 + veor $Xl,$Xm,$t2 + vpmull.p64 $Xln,$H,$In @ H·Ii+1 + veor $IN,$IN,$Xh @ accumulate $IN early + + vext.8 $t2,$Xl,$Xl,#8 @ 2nd phase of reduction + vpmull.p64 $Xl,$Xl,$xC2 + veor $IN,$IN,$t2 + veor $t1,$t1,$In @ Karatsuba pre-processing + veor $IN,$IN,$Xl + vpmull2.p64 $Xhn,$H,$In + b.hs .Loop_mod2x_v8 @ there was at least 32 more bytes + + veor $Xh,$Xh,$t2 + vext.8 $IN,$t0,$t0,#8 @ re-construct $IN + adds $len,$len,#32 @ re-construct $len + veor $Xl,$Xl,$Xh @ re-construct $Xl + b.eq .Ldone_v8 @ is $len zero? +___ +} +$code.=<<___; +.Lodd_tail_v8: + vext.8 $t2,$Xl,$Xl,#8 + veor $IN,$IN,$Xl @ inp^=Xi + veor $t1,$t0,$t2 @ $t1 is rotated inp^Xi + + vpmull.p64 $Xl,$H,$IN @ H.lo·Xi.lo + veor $t1,$t1,$IN @ Karatsuba pre-processing + vpmull2.p64 $Xh,$H,$IN @ H.hi·Xi.hi + vpmull.p64 $Xm,$Hhl,$t1 @ (H.lo+H.hi)·(Xi.lo+Xi.hi) + + vext.8 $t1,$Xl,$Xh,#8 @ Karatsuba post-processing + veor $t2,$Xl,$Xh + veor $Xm,$Xm,$t1 + veor $Xm,$Xm,$t2 + vpmull.p64 $t2,$Xl,$xC2 @ 1st phase of reduction + + vmov $Xh#lo,$Xm#hi @ Xh|Xm - 256-bit result + vmov $Xm#hi,$Xl#lo @ Xm is rotated Xl + veor $Xl,$Xm,$t2 + + vext.8 $t2,$Xl,$Xl,#8 @ 2nd phase of reduction + vpmull.p64 $Xl,$Xl,$xC2 + veor $t2,$t2,$Xh + veor $Xl,$Xl,$t2 + +.Ldone_v8: +#ifndef __ARMEB__ + vrev64.8 $Xl,$Xl +#endif + vext.8 $Xl,$Xl,$Xl,#8 + vst1.64 {$Xl},[$Xi] @ write out Xi + +___ +$code.=<<___ if ($flavour !~ /64/); + vldmia sp!,{d8-d15} @ 32-bit ABI says so +___ +$code.=<<___; + ret +.size gcm_ghash_v8,.-gcm_ghash_v8 +___ + +if ($flavour =~ /64/) { # 4x subroutine +my ($I0,$j1,$j2,$j3, + $I1,$I2,$I3,$H3,$H34,$H4,$Yl,$Ym,$Yh) = map("q$_",(4..7,15..23)); + +$code.=<<___; +.type gcm_ghash_v8_4x,%function +.align 4 +gcm_ghash_v8_4x: +.Lgcm_ghash_v8_4x: + vld1.64 {$Xl},[$Xi] @ load [rotated] Xi + vld1.64 {$H-$H2},[$Htbl],#48 @ load twisted H, ..., H^2 + vmov.i8 $xC2,#0xe1 + vld1.64 {$H3-$H4},[$Htbl] @ load twisted H^3, ..., H^4 + vshl.u64 $xC2,$xC2,#57 @ compose 0xc2.0 constant + + vld1.64 {$I0-$j3},[$inp],#64 +#ifndef __ARMEB__ + vrev64.8 $Xl,$Xl + vrev64.8 $j1,$j1 + vrev64.8 $j2,$j2 + vrev64.8 $j3,$j3 + vrev64.8 $I0,$I0 +#endif + vext.8 $I3,$j3,$j3,#8 + vext.8 $I2,$j2,$j2,#8 + vext.8 $I1,$j1,$j1,#8 + + vpmull.p64 $Yl,$H,$I3 @ H·Ii+3 + veor $j3,$j3,$I3 + vpmull2.p64 $Yh,$H,$I3 + vpmull.p64 $Ym,$Hhl,$j3 + + vpmull.p64 $t0,$H2,$I2 @ H^2·Ii+2 + veor $j2,$j2,$I2 + vpmull2.p64 $I2,$H2,$I2 + vpmull2.p64 $j2,$Hhl,$j2 + + veor $Yl,$Yl,$t0 + veor $Yh,$Yh,$I2 + veor $Ym,$Ym,$j2 + + vpmull.p64 $j3,$H3,$I1 @ H^3·Ii+1 + veor $j1,$j1,$I1 + vpmull2.p64 $I1,$H3,$I1 + vpmull.p64 $j1,$H34,$j1 + + veor $Yl,$Yl,$j3 + veor $Yh,$Yh,$I1 + veor $Ym,$Ym,$j1 + + subs $len,$len,#128 + b.lo .Ltail4x + + b .Loop4x + +.align 4 +.Loop4x: + veor $t0,$I0,$Xl + vld1.64 {$I0-$j3},[$inp],#64 + vext.8 $IN,$t0,$t0,#8 +#ifndef __ARMEB__ + vrev64.8 $j1,$j1 + vrev64.8 $j2,$j2 + vrev64.8 $j3,$j3 + vrev64.8 $I0,$I0 +#endif + + vpmull.p64 $Xl,$H4,$IN @ H^4·(Xi+Ii) + veor $t0,$t0,$IN + vpmull2.p64 $Xh,$H4,$IN + vext.8 $I3,$j3,$j3,#8 + vpmull2.p64 $Xm,$H34,$t0 + + veor $Xl,$Xl,$Yl + veor $Xh,$Xh,$Yh + vext.8 $I2,$j2,$j2,#8 + veor $Xm,$Xm,$Ym + vext.8 $I1,$j1,$j1,#8 + + vext.8 $t1,$Xl,$Xh,#8 @ Karatsuba post-processing + veor $t2,$Xl,$Xh + vpmull.p64 $Yl,$H,$I3 @ H·Ii+3 + veor $j3,$j3,$I3 + veor $Xm,$Xm,$t1 + vpmull2.p64 $Yh,$H,$I3 + veor $Xm,$Xm,$t2 + vpmull.p64 $Ym,$Hhl,$j3 + + vpmull.p64 $t2,$Xl,$xC2 @ 1st phase of reduction + vmov $Xh#lo,$Xm#hi @ Xh|Xm - 256-bit result + vmov $Xm#hi,$Xl#lo @ Xm is rotated Xl + vpmull.p64 $t0,$H2,$I2 @ H^2·Ii+2 + veor $j2,$j2,$I2 + vpmull2.p64 $I2,$H2,$I2 + veor $Xl,$Xm,$t2 + vpmull2.p64 $j2,$Hhl,$j2 + + veor $Yl,$Yl,$t0 + veor $Yh,$Yh,$I2 + veor $Ym,$Ym,$j2 + + vext.8 $t2,$Xl,$Xl,#8 @ 2nd phase of reduction + vpmull.p64 $Xl,$Xl,$xC2 + vpmull.p64 $j3,$H3,$I1 @ H^3·Ii+1 + veor $j1,$j1,$I1 + veor $t2,$t2,$Xh + vpmull2.p64 $I1,$H3,$I1 + vpmull.p64 $j1,$H34,$j1 + + veor $Xl,$Xl,$t2 + veor $Yl,$Yl,$j3 + veor $Yh,$Yh,$I1 + vext.8 $Xl,$Xl,$Xl,#8 + veor $Ym,$Ym,$j1 + + subs $len,$len,#64 + b.hs .Loop4x + +.Ltail4x: + veor $t0,$I0,$Xl + vext.8 $IN,$t0,$t0,#8 + + vpmull.p64 $Xl,$H4,$IN @ H^4·(Xi+Ii) + veor $t0,$t0,$IN + vpmull2.p64 $Xh,$H4,$IN + vpmull2.p64 $Xm,$H34,$t0 + + veor $Xl,$Xl,$Yl + veor $Xh,$Xh,$Yh + veor $Xm,$Xm,$Ym + + adds $len,$len,#64 + b.eq .Ldone4x + + cmp $len,#32 + b.lo .Lone + b.eq .Ltwo +.Lthree: + vext.8 $t1,$Xl,$Xh,#8 @ Karatsuba post-processing + veor $t2,$Xl,$Xh + veor $Xm,$Xm,$t1 + vld1.64 {$I0-$j2},[$inp] + veor $Xm,$Xm,$t2 +#ifndef __ARMEB__ + vrev64.8 $j1,$j1 + vrev64.8 $j2,$j2 + vrev64.8 $I0,$I0 +#endif + + vpmull.p64 $t2,$Xl,$xC2 @ 1st phase of reduction + vmov $Xh#lo,$Xm#hi @ Xh|Xm - 256-bit result + vmov $Xm#hi,$Xl#lo @ Xm is rotated Xl + vext.8 $I2,$j2,$j2,#8 + vext.8 $I1,$j1,$j1,#8 + veor $Xl,$Xm,$t2 + + vpmull.p64 $Yl,$H,$I2 @ H·Ii+2 + veor $j2,$j2,$I2 + + vext.8 $t2,$Xl,$Xl,#8 @ 2nd phase of reduction + vpmull.p64 $Xl,$Xl,$xC2 + veor $t2,$t2,$Xh + vpmull2.p64 $Yh,$H,$I2 + vpmull.p64 $Ym,$Hhl,$j2 + veor $Xl,$Xl,$t2 + vpmull.p64 $j3,$H2,$I1 @ H^2·Ii+1 + veor $j1,$j1,$I1 + vext.8 $Xl,$Xl,$Xl,#8 + + vpmull2.p64 $I1,$H2,$I1 + veor $t0,$I0,$Xl + vpmull2.p64 $j1,$Hhl,$j1 + vext.8 $IN,$t0,$t0,#8 + + veor $Yl,$Yl,$j3 + veor $Yh,$Yh,$I1 + veor $Ym,$Ym,$j1 + + vpmull.p64 $Xl,$H3,$IN @ H^3·(Xi+Ii) + veor $t0,$t0,$IN + vpmull2.p64 $Xh,$H3,$IN + vpmull.p64 $Xm,$H34,$t0 + + veor $Xl,$Xl,$Yl + veor $Xh,$Xh,$Yh + veor $Xm,$Xm,$Ym + b .Ldone4x + +.align 4 +.Ltwo: + vext.8 $t1,$Xl,$Xh,#8 @ Karatsuba post-processing + veor $t2,$Xl,$Xh + veor $Xm,$Xm,$t1 + vld1.64 {$I0-$j1},[$inp] + veor $Xm,$Xm,$t2 +#ifndef __ARMEB__ + vrev64.8 $j1,$j1 + vrev64.8 $I0,$I0 +#endif + + vpmull.p64 $t2,$Xl,$xC2 @ 1st phase of reduction + vmov $Xh#lo,$Xm#hi @ Xh|Xm - 256-bit result + vmov $Xm#hi,$Xl#lo @ Xm is rotated Xl + vext.8 $I1,$j1,$j1,#8 + veor $Xl,$Xm,$t2 + + vext.8 $t2,$Xl,$Xl,#8 @ 2nd phase of reduction + vpmull.p64 $Xl,$Xl,$xC2 + veor $t2,$t2,$Xh + veor $Xl,$Xl,$t2 + vext.8 $Xl,$Xl,$Xl,#8 + + vpmull.p64 $Yl,$H,$I1 @ H·Ii+1 + veor $j1,$j1,$I1 + + veor $t0,$I0,$Xl + vext.8 $IN,$t0,$t0,#8 + + vpmull2.p64 $Yh,$H,$I1 + vpmull.p64 $Ym,$Hhl,$j1 + + vpmull.p64 $Xl,$H2,$IN @ H^2·(Xi+Ii) + veor $t0,$t0,$IN + vpmull2.p64 $Xh,$H2,$IN + vpmull2.p64 $Xm,$Hhl,$t0 + + veor $Xl,$Xl,$Yl + veor $Xh,$Xh,$Yh + veor $Xm,$Xm,$Ym + b .Ldone4x + +.align 4 +.Lone: + vext.8 $t1,$Xl,$Xh,#8 @ Karatsuba post-processing + veor $t2,$Xl,$Xh + veor $Xm,$Xm,$t1 + vld1.64 {$I0},[$inp] + veor $Xm,$Xm,$t2 +#ifndef __ARMEB__ + vrev64.8 $I0,$I0 +#endif + + vpmull.p64 $t2,$Xl,$xC2 @ 1st phase of reduction + vmov $Xh#lo,$Xm#hi @ Xh|Xm - 256-bit result + vmov $Xm#hi,$Xl#lo @ Xm is rotated Xl + veor $Xl,$Xm,$t2 + + vext.8 $t2,$Xl,$Xl,#8 @ 2nd phase of reduction + vpmull.p64 $Xl,$Xl,$xC2 + veor $t2,$t2,$Xh + veor $Xl,$Xl,$t2 + vext.8 $Xl,$Xl,$Xl,#8 + + veor $t0,$I0,$Xl + vext.8 $IN,$t0,$t0,#8 + + vpmull.p64 $Xl,$H,$IN + veor $t0,$t0,$IN + vpmull2.p64 $Xh,$H,$IN + vpmull.p64 $Xm,$Hhl,$t0 + +.Ldone4x: + vext.8 $t1,$Xl,$Xh,#8 @ Karatsuba post-processing + veor $t2,$Xl,$Xh + veor $Xm,$Xm,$t1 + veor $Xm,$Xm,$t2 + + vpmull.p64 $t2,$Xl,$xC2 @ 1st phase of reduction + vmov $Xh#lo,$Xm#hi @ Xh|Xm - 256-bit result + vmov $Xm#hi,$Xl#lo @ Xm is rotated Xl + veor $Xl,$Xm,$t2 + + vext.8 $t2,$Xl,$Xl,#8 @ 2nd phase of reduction + vpmull.p64 $Xl,$Xl,$xC2 + veor $t2,$t2,$Xh + veor $Xl,$Xl,$t2 + vext.8 $Xl,$Xl,$Xl,#8 + +#ifndef __ARMEB__ + vrev64.8 $Xl,$Xl +#endif + vst1.64 {$Xl},[$Xi] @ write out Xi + + ret +.size gcm_ghash_v8_4x,.-gcm_ghash_v8_4x +___ + +} +} + +$code.=<<___; +.asciz "GHASH for ARMv8, CRYPTOGAMS by " +.align 2 +#endif +___ + +if ($flavour =~ /64/) { ######## 64-bit code + sub unvmov { + my $arg=shift; + + $arg =~ m/q([0-9]+)#(lo|hi),\s*q([0-9]+)#(lo|hi)/o && + sprintf "ins v%d.d[%d],v%d.d[%d]",$1<8?$1:$1+8,($2 eq "lo")?0:1, + $3<8?$3:$3+8,($4 eq "lo")?0:1; + } + foreach(split("\n",$code)) { + s/cclr\s+([wx])([^,]+),\s*([a-z]+)/csel $1$2,$1zr,$1$2,$3/o or + s/vmov\.i8/movi/o or # fix up legacy mnemonics + s/vmov\s+(.*)/unvmov($1)/geo or + s/vext\.8/ext/o or + s/vshr\.s/sshr\.s/o or + s/vshr/ushr/o or + s/^(\s+)v/$1/o or # strip off v prefix + s/\bbx\s+lr\b/ret/o; + + s/\bq([0-9]+)\b/"v".($1<8?$1:$1+8).".16b"/geo; # old->new registers + s/@\s/\/\//o; # old->new style commentary + + # fix up remaining legacy suffixes + s/\.[ui]?8(\s)/$1/o; + s/\.[uis]?32//o and s/\.16b/\.4s/go; + m/\.p64/o and s/\.16b/\.1q/o; # 1st pmull argument + m/l\.p64/o and s/\.16b/\.1d/go; # 2nd and 3rd pmull arguments + s/\.[uisp]?64//o and s/\.16b/\.2d/go; + s/\.[42]([sd])\[([0-3])\]/\.$1\[$2\]/o; + + print $_,"\n"; + } +} else { ######## 32-bit code + sub unvdup32 { + my $arg=shift; + + $arg =~ m/q([0-9]+),\s*q([0-9]+)\[([0-3])\]/o && + sprintf "vdup.32 q%d,d%d[%d]",$1,2*$2+($3>>1),$3&1; + } + sub unvpmullp64 { + my ($mnemonic,$arg)=@_; + + if ($arg =~ m/q([0-9]+),\s*q([0-9]+),\s*q([0-9]+)/o) { + my $word = 0xf2a00e00|(($1&7)<<13)|(($1&8)<<19) + |(($2&7)<<17)|(($2&8)<<4) + |(($3&7)<<1) |(($3&8)<<2); + $word |= 0x00010001 if ($mnemonic =~ "2"); + # since ARMv7 instructions are always encoded little-endian. + # correct solution is to use .inst directive, but older + # assemblers don't implement it:-( + sprintf ".byte\t0x%02x,0x%02x,0x%02x,0x%02x\t@ %s %s", + $word&0xff,($word>>8)&0xff, + ($word>>16)&0xff,($word>>24)&0xff, + $mnemonic,$arg; + } + } + + foreach(split("\n",$code)) { + s/\b[wx]([0-9]+)\b/r$1/go; # new->old registers + s/\bv([0-9])\.[12468]+[bsd]\b/q$1/go; # new->old registers + s/\/\/\s?/@ /o; # new->old style commentary + + # fix up remaining new-style suffixes + s/\],#[0-9]+/]!/o; + + s/cclr\s+([^,]+),\s*([a-z]+)/mov$2 $1,#0/o or + s/vdup\.32\s+(.*)/unvdup32($1)/geo or + s/v?(pmull2?)\.p64\s+(.*)/unvpmullp64($1,$2)/geo or + s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo or + s/^(\s+)b\./$1b/o or + s/^(\s+)ret/$1bx\tlr/o; + + print $_,"\n"; + } +} + +close STDOUT; # enforce flush diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/modes/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/build.info new file mode 100644 index 000000000..821340eb9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/build.info @@ -0,0 +1,30 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + cbc128.c ctr128.c cts128.c cfb128.c ofb128.c gcm128.c \ + ccm128.c xts128.c wrap128.c ocb128.c \ + {- $target{modes_asm_src} -} + +INCLUDE[gcm128.o]=.. + +GENERATE[ghash-ia64.s]=asm/ghash-ia64.pl $(LIB_CFLAGS) $(LIB_CPPFLAGS) +GENERATE[ghash-x86.s]=asm/ghash-x86.pl \ + $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) +GENERATE[ghash-x86_64.s]=asm/ghash-x86_64.pl $(PERLASM_SCHEME) +GENERATE[aesni-gcm-x86_64.s]=asm/aesni-gcm-x86_64.pl $(PERLASM_SCHEME) +GENERATE[ghash-sparcv9.S]=asm/ghash-sparcv9.pl $(PERLASM_SCHEME) +INCLUDE[ghash-sparcv9.o]=.. +GENERATE[ghash-alpha.S]=asm/ghash-alpha.pl $(PERLASM_SCHEME) +GENERATE[ghash-parisc.s]=asm/ghash-parisc.pl $(PERLASM_SCHEME) +GENERATE[ghashp8-ppc.s]=asm/ghashp8-ppc.pl $(PERLASM_SCHEME) +GENERATE[ghash-armv4.S]=asm/ghash-armv4.pl $(PERLASM_SCHEME) +INCLUDE[ghash-armv4.o]=.. +GENERATE[ghashv8-armx.S]=asm/ghashv8-armx.pl $(PERLASM_SCHEME) +INCLUDE[ghashv8-armx.o]=.. +GENERATE[ghash-s390x.S]=asm/ghash-s390x.pl $(PERLASM_SCHEME) +INCLUDE[ghash-s390x.o]=.. + +BEGINRAW[Makefile] +# GNU make "catch all" +{- $builddir -}/ghash-%.S: {- $sourcedir -}/asm/ghash-%.pl + CC="$(CC)" $(PERL) $< $(PERLASM_SCHEME) $@ +ENDRAW[Makefile] diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/modes/cbc128.c b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/cbc128.c new file mode 100644 index 000000000..4ce5eb2ae --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/cbc128.c @@ -0,0 +1,161 @@ +/* + * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "modes_lcl.h" +#include + +#if !defined(STRICT_ALIGNMENT) && !defined(PEDANTIC) +# define STRICT_ALIGNMENT 0 +#endif + +void CRYPTO_cbc128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], block128_f block) +{ + size_t n; + const unsigned char *iv = ivec; + + if (len == 0) + return; + +#if !defined(OPENSSL_SMALL_FOOTPRINT) + if (STRICT_ALIGNMENT && + ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) { + while (len >= 16) { + for (n = 0; n < 16; ++n) + out[n] = in[n] ^ iv[n]; + (*block) (out, out, key); + iv = out; + len -= 16; + in += 16; + out += 16; + } + } else { + while (len >= 16) { + for (n = 0; n < 16; n += sizeof(size_t)) + *(size_t *)(out + n) = + *(size_t *)(in + n) ^ *(size_t *)(iv + n); + (*block) (out, out, key); + iv = out; + len -= 16; + in += 16; + out += 16; + } + } +#endif + while (len) { + for (n = 0; n < 16 && n < len; ++n) + out[n] = in[n] ^ iv[n]; + for (; n < 16; ++n) + out[n] = iv[n]; + (*block) (out, out, key); + iv = out; + if (len <= 16) + break; + len -= 16; + in += 16; + out += 16; + } + memcpy(ivec, iv, 16); +} + +void CRYPTO_cbc128_decrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], block128_f block) +{ + size_t n; + union { + size_t t[16 / sizeof(size_t)]; + unsigned char c[16]; + } tmp; + + if (len == 0) + return; + +#if !defined(OPENSSL_SMALL_FOOTPRINT) + if (in != out) { + const unsigned char *iv = ivec; + + if (STRICT_ALIGNMENT && + ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) { + while (len >= 16) { + (*block) (in, out, key); + for (n = 0; n < 16; ++n) + out[n] ^= iv[n]; + iv = in; + len -= 16; + in += 16; + out += 16; + } + } else if (16 % sizeof(size_t) == 0) { /* always true */ + while (len >= 16) { + size_t *out_t = (size_t *)out, *iv_t = (size_t *)iv; + + (*block) (in, out, key); + for (n = 0; n < 16 / sizeof(size_t); n++) + out_t[n] ^= iv_t[n]; + iv = in; + len -= 16; + in += 16; + out += 16; + } + } + memcpy(ivec, iv, 16); + } else { + if (STRICT_ALIGNMENT && + ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) { + unsigned char c; + while (len >= 16) { + (*block) (in, tmp.c, key); + for (n = 0; n < 16; ++n) { + c = in[n]; + out[n] = tmp.c[n] ^ ivec[n]; + ivec[n] = c; + } + len -= 16; + in += 16; + out += 16; + } + } else if (16 % sizeof(size_t) == 0) { /* always true */ + while (len >= 16) { + size_t c, *out_t = (size_t *)out, *ivec_t = (size_t *)ivec; + const size_t *in_t = (const size_t *)in; + + (*block) (in, tmp.c, key); + for (n = 0; n < 16 / sizeof(size_t); n++) { + c = in_t[n]; + out_t[n] = tmp.t[n] ^ ivec_t[n]; + ivec_t[n] = c; + } + len -= 16; + in += 16; + out += 16; + } + } + } +#endif + while (len) { + unsigned char c; + (*block) (in, tmp.c, key); + for (n = 0; n < 16 && n < len; ++n) { + c = in[n]; + out[n] = tmp.c[n] ^ ivec[n]; + ivec[n] = c; + } + if (len <= 16) { + for (; n < 16; ++n) + ivec[n] = in[n]; + break; + } + len -= 16; + in += 16; + out += 16; + } +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/modes/ccm128.c b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/ccm128.c new file mode 100644 index 000000000..85ce84f10 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/ccm128.c @@ -0,0 +1,432 @@ +/* + * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "modes_lcl.h" +#include + +/* + * First you setup M and L parameters and pass the key schedule. This is + * called once per session setup... + */ +void CRYPTO_ccm128_init(CCM128_CONTEXT *ctx, + unsigned int M, unsigned int L, void *key, + block128_f block) +{ + memset(ctx->nonce.c, 0, sizeof(ctx->nonce.c)); + ctx->nonce.c[0] = ((u8)(L - 1) & 7) | (u8)(((M - 2) / 2) & 7) << 3; + ctx->blocks = 0; + ctx->block = block; + ctx->key = key; +} + +/* !!! Following interfaces are to be called *once* per packet !!! */ + +/* Then you setup per-message nonce and pass the length of the message */ +int CRYPTO_ccm128_setiv(CCM128_CONTEXT *ctx, + const unsigned char *nonce, size_t nlen, size_t mlen) +{ + unsigned int L = ctx->nonce.c[0] & 7; /* the L parameter */ + + if (nlen < (14 - L)) + return -1; /* nonce is too short */ + + if (sizeof(mlen) == 8 && L >= 3) { + ctx->nonce.c[8] = (u8)(mlen >> (56 % (sizeof(mlen) * 8))); + ctx->nonce.c[9] = (u8)(mlen >> (48 % (sizeof(mlen) * 8))); + ctx->nonce.c[10] = (u8)(mlen >> (40 % (sizeof(mlen) * 8))); + ctx->nonce.c[11] = (u8)(mlen >> (32 % (sizeof(mlen) * 8))); + } else + ctx->nonce.u[1] = 0; + + ctx->nonce.c[12] = (u8)(mlen >> 24); + ctx->nonce.c[13] = (u8)(mlen >> 16); + ctx->nonce.c[14] = (u8)(mlen >> 8); + ctx->nonce.c[15] = (u8)mlen; + + ctx->nonce.c[0] &= ~0x40; /* clear Adata flag */ + memcpy(&ctx->nonce.c[1], nonce, 14 - L); + + return 0; +} + +/* Then you pass additional authentication data, this is optional */ +void CRYPTO_ccm128_aad(CCM128_CONTEXT *ctx, + const unsigned char *aad, size_t alen) +{ + unsigned int i; + block128_f block = ctx->block; + + if (alen == 0) + return; + + ctx->nonce.c[0] |= 0x40; /* set Adata flag */ + (*block) (ctx->nonce.c, ctx->cmac.c, ctx->key), ctx->blocks++; + + if (alen < (0x10000 - 0x100)) { + ctx->cmac.c[0] ^= (u8)(alen >> 8); + ctx->cmac.c[1] ^= (u8)alen; + i = 2; + } else if (sizeof(alen) == 8 + && alen >= (size_t)1 << (32 % (sizeof(alen) * 8))) { + ctx->cmac.c[0] ^= 0xFF; + ctx->cmac.c[1] ^= 0xFF; + ctx->cmac.c[2] ^= (u8)(alen >> (56 % (sizeof(alen) * 8))); + ctx->cmac.c[3] ^= (u8)(alen >> (48 % (sizeof(alen) * 8))); + ctx->cmac.c[4] ^= (u8)(alen >> (40 % (sizeof(alen) * 8))); + ctx->cmac.c[5] ^= (u8)(alen >> (32 % (sizeof(alen) * 8))); + ctx->cmac.c[6] ^= (u8)(alen >> 24); + ctx->cmac.c[7] ^= (u8)(alen >> 16); + ctx->cmac.c[8] ^= (u8)(alen >> 8); + ctx->cmac.c[9] ^= (u8)alen; + i = 10; + } else { + ctx->cmac.c[0] ^= 0xFF; + ctx->cmac.c[1] ^= 0xFE; + ctx->cmac.c[2] ^= (u8)(alen >> 24); + ctx->cmac.c[3] ^= (u8)(alen >> 16); + ctx->cmac.c[4] ^= (u8)(alen >> 8); + ctx->cmac.c[5] ^= (u8)alen; + i = 6; + } + + do { + for (; i < 16 && alen; ++i, ++aad, --alen) + ctx->cmac.c[i] ^= *aad; + (*block) (ctx->cmac.c, ctx->cmac.c, ctx->key), ctx->blocks++; + i = 0; + } while (alen); +} + +/* Finally you encrypt or decrypt the message */ + +/* + * counter part of nonce may not be larger than L*8 bits, L is not larger + * than 8, therefore 64-bit counter... + */ +static void ctr64_inc(unsigned char *counter) +{ + unsigned int n = 8; + u8 c; + + counter += 8; + do { + --n; + c = counter[n]; + ++c; + counter[n] = c; + if (c) + return; + } while (n); +} + +int CRYPTO_ccm128_encrypt(CCM128_CONTEXT *ctx, + const unsigned char *inp, unsigned char *out, + size_t len) +{ + size_t n; + unsigned int i, L; + unsigned char flags0 = ctx->nonce.c[0]; + block128_f block = ctx->block; + void *key = ctx->key; + union { + u64 u[2]; + u8 c[16]; + } scratch; + + if (!(flags0 & 0x40)) + (*block) (ctx->nonce.c, ctx->cmac.c, key), ctx->blocks++; + + ctx->nonce.c[0] = L = flags0 & 7; + for (n = 0, i = 15 - L; i < 15; ++i) { + n |= ctx->nonce.c[i]; + ctx->nonce.c[i] = 0; + n <<= 8; + } + n |= ctx->nonce.c[15]; /* reconstructed length */ + ctx->nonce.c[15] = 1; + + if (n != len) + return -1; /* length mismatch */ + + ctx->blocks += ((len + 15) >> 3) | 1; + if (ctx->blocks > (U64(1) << 61)) + return -2; /* too much data */ + + while (len >= 16) { +#if defined(STRICT_ALIGNMENT) + union { + u64 u[2]; + u8 c[16]; + } temp; + + memcpy(temp.c, inp, 16); + ctx->cmac.u[0] ^= temp.u[0]; + ctx->cmac.u[1] ^= temp.u[1]; +#else + ctx->cmac.u[0] ^= ((u64 *)inp)[0]; + ctx->cmac.u[1] ^= ((u64 *)inp)[1]; +#endif + (*block) (ctx->cmac.c, ctx->cmac.c, key); + (*block) (ctx->nonce.c, scratch.c, key); + ctr64_inc(ctx->nonce.c); +#if defined(STRICT_ALIGNMENT) + temp.u[0] ^= scratch.u[0]; + temp.u[1] ^= scratch.u[1]; + memcpy(out, temp.c, 16); +#else + ((u64 *)out)[0] = scratch.u[0] ^ ((u64 *)inp)[0]; + ((u64 *)out)[1] = scratch.u[1] ^ ((u64 *)inp)[1]; +#endif + inp += 16; + out += 16; + len -= 16; + } + + if (len) { + for (i = 0; i < len; ++i) + ctx->cmac.c[i] ^= inp[i]; + (*block) (ctx->cmac.c, ctx->cmac.c, key); + (*block) (ctx->nonce.c, scratch.c, key); + for (i = 0; i < len; ++i) + out[i] = scratch.c[i] ^ inp[i]; + } + + for (i = 15 - L; i < 16; ++i) + ctx->nonce.c[i] = 0; + + (*block) (ctx->nonce.c, scratch.c, key); + ctx->cmac.u[0] ^= scratch.u[0]; + ctx->cmac.u[1] ^= scratch.u[1]; + + ctx->nonce.c[0] = flags0; + + return 0; +} + +int CRYPTO_ccm128_decrypt(CCM128_CONTEXT *ctx, + const unsigned char *inp, unsigned char *out, + size_t len) +{ + size_t n; + unsigned int i, L; + unsigned char flags0 = ctx->nonce.c[0]; + block128_f block = ctx->block; + void *key = ctx->key; + union { + u64 u[2]; + u8 c[16]; + } scratch; + + if (!(flags0 & 0x40)) + (*block) (ctx->nonce.c, ctx->cmac.c, key); + + ctx->nonce.c[0] = L = flags0 & 7; + for (n = 0, i = 15 - L; i < 15; ++i) { + n |= ctx->nonce.c[i]; + ctx->nonce.c[i] = 0; + n <<= 8; + } + n |= ctx->nonce.c[15]; /* reconstructed length */ + ctx->nonce.c[15] = 1; + + if (n != len) + return -1; + + while (len >= 16) { +#if defined(STRICT_ALIGNMENT) + union { + u64 u[2]; + u8 c[16]; + } temp; +#endif + (*block) (ctx->nonce.c, scratch.c, key); + ctr64_inc(ctx->nonce.c); +#if defined(STRICT_ALIGNMENT) + memcpy(temp.c, inp, 16); + ctx->cmac.u[0] ^= (scratch.u[0] ^= temp.u[0]); + ctx->cmac.u[1] ^= (scratch.u[1] ^= temp.u[1]); + memcpy(out, scratch.c, 16); +#else + ctx->cmac.u[0] ^= (((u64 *)out)[0] = scratch.u[0] ^ ((u64 *)inp)[0]); + ctx->cmac.u[1] ^= (((u64 *)out)[1] = scratch.u[1] ^ ((u64 *)inp)[1]); +#endif + (*block) (ctx->cmac.c, ctx->cmac.c, key); + + inp += 16; + out += 16; + len -= 16; + } + + if (len) { + (*block) (ctx->nonce.c, scratch.c, key); + for (i = 0; i < len; ++i) + ctx->cmac.c[i] ^= (out[i] = scratch.c[i] ^ inp[i]); + (*block) (ctx->cmac.c, ctx->cmac.c, key); + } + + for (i = 15 - L; i < 16; ++i) + ctx->nonce.c[i] = 0; + + (*block) (ctx->nonce.c, scratch.c, key); + ctx->cmac.u[0] ^= scratch.u[0]; + ctx->cmac.u[1] ^= scratch.u[1]; + + ctx->nonce.c[0] = flags0; + + return 0; +} + +static void ctr64_add(unsigned char *counter, size_t inc) +{ + size_t n = 8, val = 0; + + counter += 8; + do { + --n; + val += counter[n] + (inc & 0xff); + counter[n] = (unsigned char)val; + val >>= 8; /* carry bit */ + inc >>= 8; + } while (n && (inc || val)); +} + +int CRYPTO_ccm128_encrypt_ccm64(CCM128_CONTEXT *ctx, + const unsigned char *inp, unsigned char *out, + size_t len, ccm128_f stream) +{ + size_t n; + unsigned int i, L; + unsigned char flags0 = ctx->nonce.c[0]; + block128_f block = ctx->block; + void *key = ctx->key; + union { + u64 u[2]; + u8 c[16]; + } scratch; + + if (!(flags0 & 0x40)) + (*block) (ctx->nonce.c, ctx->cmac.c, key), ctx->blocks++; + + ctx->nonce.c[0] = L = flags0 & 7; + for (n = 0, i = 15 - L; i < 15; ++i) { + n |= ctx->nonce.c[i]; + ctx->nonce.c[i] = 0; + n <<= 8; + } + n |= ctx->nonce.c[15]; /* reconstructed length */ + ctx->nonce.c[15] = 1; + + if (n != len) + return -1; /* length mismatch */ + + ctx->blocks += ((len + 15) >> 3) | 1; + if (ctx->blocks > (U64(1) << 61)) + return -2; /* too much data */ + + if ((n = len / 16)) { + (*stream) (inp, out, n, key, ctx->nonce.c, ctx->cmac.c); + n *= 16; + inp += n; + out += n; + len -= n; + if (len) + ctr64_add(ctx->nonce.c, n / 16); + } + + if (len) { + for (i = 0; i < len; ++i) + ctx->cmac.c[i] ^= inp[i]; + (*block) (ctx->cmac.c, ctx->cmac.c, key); + (*block) (ctx->nonce.c, scratch.c, key); + for (i = 0; i < len; ++i) + out[i] = scratch.c[i] ^ inp[i]; + } + + for (i = 15 - L; i < 16; ++i) + ctx->nonce.c[i] = 0; + + (*block) (ctx->nonce.c, scratch.c, key); + ctx->cmac.u[0] ^= scratch.u[0]; + ctx->cmac.u[1] ^= scratch.u[1]; + + ctx->nonce.c[0] = flags0; + + return 0; +} + +int CRYPTO_ccm128_decrypt_ccm64(CCM128_CONTEXT *ctx, + const unsigned char *inp, unsigned char *out, + size_t len, ccm128_f stream) +{ + size_t n; + unsigned int i, L; + unsigned char flags0 = ctx->nonce.c[0]; + block128_f block = ctx->block; + void *key = ctx->key; + union { + u64 u[2]; + u8 c[16]; + } scratch; + + if (!(flags0 & 0x40)) + (*block) (ctx->nonce.c, ctx->cmac.c, key); + + ctx->nonce.c[0] = L = flags0 & 7; + for (n = 0, i = 15 - L; i < 15; ++i) { + n |= ctx->nonce.c[i]; + ctx->nonce.c[i] = 0; + n <<= 8; + } + n |= ctx->nonce.c[15]; /* reconstructed length */ + ctx->nonce.c[15] = 1; + + if (n != len) + return -1; + + if ((n = len / 16)) { + (*stream) (inp, out, n, key, ctx->nonce.c, ctx->cmac.c); + n *= 16; + inp += n; + out += n; + len -= n; + if (len) + ctr64_add(ctx->nonce.c, n / 16); + } + + if (len) { + (*block) (ctx->nonce.c, scratch.c, key); + for (i = 0; i < len; ++i) + ctx->cmac.c[i] ^= (out[i] = scratch.c[i] ^ inp[i]); + (*block) (ctx->cmac.c, ctx->cmac.c, key); + } + + for (i = 15 - L; i < 16; ++i) + ctx->nonce.c[i] = 0; + + (*block) (ctx->nonce.c, scratch.c, key); + ctx->cmac.u[0] ^= scratch.u[0]; + ctx->cmac.u[1] ^= scratch.u[1]; + + ctx->nonce.c[0] = flags0; + + return 0; +} + +size_t CRYPTO_ccm128_tag(CCM128_CONTEXT *ctx, unsigned char *tag, size_t len) +{ + unsigned int M = (ctx->nonce.c[0] >> 3) & 7; /* the M parameter */ + + M *= 2; + M += 2; + if (len < M) + return 0; + memcpy(tag, ctx->cmac.c, M); + return M; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/modes/cfb128.c b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/cfb128.c new file mode 100644 index 000000000..e439567fe --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/cfb128.c @@ -0,0 +1,198 @@ +/* + * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "modes_lcl.h" +#include + +/* + * The input and output encrypted as though 128bit cfb mode is being used. + * The extra state information to record how much of the 128bit block we have + * used is contained in *num; + */ +void CRYPTO_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], int *num, + int enc, block128_f block) +{ + unsigned int n; + size_t l = 0; + + n = *num; + + if (enc) { +#if !defined(OPENSSL_SMALL_FOOTPRINT) + if (16 % sizeof(size_t) == 0) { /* always true actually */ + do { + while (n && len) { + *(out++) = ivec[n] ^= *(in++); + --len; + n = (n + 1) % 16; + } +# if defined(STRICT_ALIGNMENT) + if (((size_t)in | (size_t)out | (size_t)ivec) % + sizeof(size_t) != 0) + break; +# endif + while (len >= 16) { + (*block) (ivec, ivec, key); + for (; n < 16; n += sizeof(size_t)) { + *(size_t *)(out + n) = + *(size_t *)(ivec + n) ^= *(size_t *)(in + n); + } + len -= 16; + out += 16; + in += 16; + n = 0; + } + if (len) { + (*block) (ivec, ivec, key); + while (len--) { + out[n] = ivec[n] ^= in[n]; + ++n; + } + } + *num = n; + return; + } while (0); + } + /* the rest would be commonly eliminated by x86* compiler */ +#endif + while (l < len) { + if (n == 0) { + (*block) (ivec, ivec, key); + } + out[l] = ivec[n] ^= in[l]; + ++l; + n = (n + 1) % 16; + } + *num = n; + } else { +#if !defined(OPENSSL_SMALL_FOOTPRINT) + if (16 % sizeof(size_t) == 0) { /* always true actually */ + do { + while (n && len) { + unsigned char c; + *(out++) = ivec[n] ^ (c = *(in++)); + ivec[n] = c; + --len; + n = (n + 1) % 16; + } +# if defined(STRICT_ALIGNMENT) + if (((size_t)in | (size_t)out | (size_t)ivec) % + sizeof(size_t) != 0) + break; +# endif + while (len >= 16) { + (*block) (ivec, ivec, key); + for (; n < 16; n += sizeof(size_t)) { + size_t t = *(size_t *)(in + n); + *(size_t *)(out + n) = *(size_t *)(ivec + n) ^ t; + *(size_t *)(ivec + n) = t; + } + len -= 16; + out += 16; + in += 16; + n = 0; + } + if (len) { + (*block) (ivec, ivec, key); + while (len--) { + unsigned char c; + out[n] = ivec[n] ^ (c = in[n]); + ivec[n] = c; + ++n; + } + } + *num = n; + return; + } while (0); + } + /* the rest would be commonly eliminated by x86* compiler */ +#endif + while (l < len) { + unsigned char c; + if (n == 0) { + (*block) (ivec, ivec, key); + } + out[l] = ivec[n] ^ (c = in[l]); + ivec[n] = c; + ++l; + n = (n + 1) % 16; + } + *num = n; + } +} + +/* + * This expects a single block of size nbits for both in and out. Note that + * it corrupts any extra bits in the last byte of out + */ +static void cfbr_encrypt_block(const unsigned char *in, unsigned char *out, + int nbits, const void *key, + unsigned char ivec[16], int enc, + block128_f block) +{ + int n, rem, num; + unsigned char ovec[16 * 2 + 1]; /* +1 because we dereference (but don't + * use) one byte off the end */ + + if (nbits <= 0 || nbits > 128) + return; + + /* fill in the first half of the new IV with the current IV */ + memcpy(ovec, ivec, 16); + /* construct the new IV */ + (*block) (ivec, ivec, key); + num = (nbits + 7) / 8; + if (enc) /* encrypt the input */ + for (n = 0; n < num; ++n) + out[n] = (ovec[16 + n] = in[n] ^ ivec[n]); + else /* decrypt the input */ + for (n = 0; n < num; ++n) + out[n] = (ovec[16 + n] = in[n]) ^ ivec[n]; + /* shift ovec left... */ + rem = nbits % 8; + num = nbits / 8; + if (rem == 0) + memcpy(ivec, ovec + num, 16); + else + for (n = 0; n < 16; ++n) + ivec[n] = ovec[n + num] << rem | ovec[n + num + 1] >> (8 - rem); + + /* it is not necessary to cleanse ovec, since the IV is not secret */ +} + +/* N.B. This expects the input to be packed, MS bit first */ +void CRYPTO_cfb128_1_encrypt(const unsigned char *in, unsigned char *out, + size_t bits, const void *key, + unsigned char ivec[16], int *num, + int enc, block128_f block) +{ + size_t n; + unsigned char c[1], d[1]; + + for (n = 0; n < bits; ++n) { + c[0] = (in[n / 8] & (1 << (7 - n % 8))) ? 0x80 : 0; + cfbr_encrypt_block(c, d, 1, key, ivec, enc, block); + out[n / 8] = (out[n / 8] & ~(1 << (unsigned int)(7 - n % 8))) | + ((d[0] & 0x80) >> (unsigned int)(n % 8)); + } +} + +void CRYPTO_cfb128_8_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const void *key, + unsigned char ivec[16], int *num, + int enc, block128_f block) +{ + size_t n; + + for (n = 0; n < length; ++n) + cfbr_encrypt_block(&in[n], &out[n], 8, key, ivec, enc, block); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/modes/ctr128.c b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/ctr128.c new file mode 100644 index 000000000..03920b447 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/ctr128.c @@ -0,0 +1,209 @@ +/* + * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "modes_lcl.h" +#include + +/* + * NOTE: the IV/counter CTR mode is big-endian. The code itself is + * endian-neutral. + */ + +/* increment counter (128-bit int) by 1 */ +static void ctr128_inc(unsigned char *counter) +{ + u32 n = 16, c = 1; + + do { + --n; + c += counter[n]; + counter[n] = (u8)c; + c >>= 8; + } while (n); +} + +#if !defined(OPENSSL_SMALL_FOOTPRINT) +static void ctr128_inc_aligned(unsigned char *counter) +{ + size_t *data, c, d, n; + const union { + long one; + char little; + } is_endian = { + 1 + }; + + if (is_endian.little || ((size_t)counter % sizeof(size_t)) != 0) { + ctr128_inc(counter); + return; + } + + data = (size_t *)counter; + c = 1; + n = 16 / sizeof(size_t); + do { + --n; + d = data[n] += c; + /* did addition carry? */ + c = ((d - c) & ~d) >> (sizeof(size_t) * 8 - 1); + } while (n); +} +#endif + +/* + * The input encrypted as though 128bit counter mode is being used. The + * extra state information to record how much of the 128bit block we have + * used is contained in *num, and the encrypted counter is kept in + * ecount_buf. Both *num and ecount_buf must be initialised with zeros + * before the first call to CRYPTO_ctr128_encrypt(). This algorithm assumes + * that the counter is in the x lower bits of the IV (ivec), and that the + * application has full control over overflow and the rest of the IV. This + * implementation takes NO responsibility for checking that the counter + * doesn't overflow into the rest of the IV when incremented. + */ +void CRYPTO_ctr128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], + unsigned char ecount_buf[16], unsigned int *num, + block128_f block) +{ + unsigned int n; + size_t l = 0; + + n = *num; + +#if !defined(OPENSSL_SMALL_FOOTPRINT) + if (16 % sizeof(size_t) == 0) { /* always true actually */ + do { + while (n && len) { + *(out++) = *(in++) ^ ecount_buf[n]; + --len; + n = (n + 1) % 16; + } + +# if defined(STRICT_ALIGNMENT) + if (((size_t)in | (size_t)out | (size_t)ecount_buf) + % sizeof(size_t) != 0) + break; +# endif + while (len >= 16) { + (*block) (ivec, ecount_buf, key); + ctr128_inc_aligned(ivec); + for (n = 0; n < 16; n += sizeof(size_t)) + *(size_t *)(out + n) = + *(size_t *)(in + n) ^ *(size_t *)(ecount_buf + n); + len -= 16; + out += 16; + in += 16; + n = 0; + } + if (len) { + (*block) (ivec, ecount_buf, key); + ctr128_inc_aligned(ivec); + while (len--) { + out[n] = in[n] ^ ecount_buf[n]; + ++n; + } + } + *num = n; + return; + } while (0); + } + /* the rest would be commonly eliminated by x86* compiler */ +#endif + while (l < len) { + if (n == 0) { + (*block) (ivec, ecount_buf, key); + ctr128_inc(ivec); + } + out[l] = in[l] ^ ecount_buf[n]; + ++l; + n = (n + 1) % 16; + } + + *num = n; +} + +/* increment upper 96 bits of 128-bit counter by 1 */ +static void ctr96_inc(unsigned char *counter) +{ + u32 n = 12, c = 1; + + do { + --n; + c += counter[n]; + counter[n] = (u8)c; + c >>= 8; + } while (n); +} + +void CRYPTO_ctr128_encrypt_ctr32(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], + unsigned char ecount_buf[16], + unsigned int *num, ctr128_f func) +{ + unsigned int n, ctr32; + + n = *num; + + while (n && len) { + *(out++) = *(in++) ^ ecount_buf[n]; + --len; + n = (n + 1) % 16; + } + + ctr32 = GETU32(ivec + 12); + while (len >= 16) { + size_t blocks = len / 16; + /* + * 1<<28 is just a not-so-small yet not-so-large number... + * Below condition is practically never met, but it has to + * be checked for code correctness. + */ + if (sizeof(size_t) > sizeof(unsigned int) && blocks > (1U << 28)) + blocks = (1U << 28); + /* + * As (*func) operates on 32-bit counter, caller + * has to handle overflow. 'if' below detects the + * overflow, which is then handled by limiting the + * amount of blocks to the exact overflow point... + */ + ctr32 += (u32)blocks; + if (ctr32 < blocks) { + blocks -= ctr32; + ctr32 = 0; + } + (*func) (in, out, blocks, key, ivec); + /* (*ctr) does not update ivec, caller does: */ + PUTU32(ivec + 12, ctr32); + /* ... overflow was detected, propagate carry. */ + if (ctr32 == 0) + ctr96_inc(ivec); + blocks *= 16; + len -= blocks; + out += blocks; + in += blocks; + } + if (len) { + memset(ecount_buf, 0, 16); + (*func) (ecount_buf, ecount_buf, 1, key, ivec); + ++ctr32; + PUTU32(ivec + 12, ctr32); + if (ctr32 == 0) + ctr96_inc(ivec); + while (len--) { + out[n] = in[n] ^ ecount_buf[n]; + ++n; + } + } + + *num = n; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/modes/cts128.c b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/cts128.c new file mode 100644 index 000000000..93826a1e2 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/cts128.c @@ -0,0 +1,330 @@ +/* + * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "modes_lcl.h" +#include + +/* + * Trouble with Ciphertext Stealing, CTS, mode is that there is no + * common official specification, but couple of cipher/application + * specific ones: RFC2040 and RFC3962. Then there is 'Proposal to + * Extend CBC Mode By "Ciphertext Stealing"' at NIST site, which + * deviates from mentioned RFCs. Most notably it allows input to be + * of block length and it doesn't flip the order of the last two + * blocks. CTS is being discussed even in ECB context, but it's not + * adopted for any known application. This implementation provides + * two interfaces: one compliant with above mentioned RFCs and one + * compliant with the NIST proposal, both extending CBC mode. + */ + +size_t CRYPTO_cts128_encrypt_block(const unsigned char *in, + unsigned char *out, size_t len, + const void *key, unsigned char ivec[16], + block128_f block) +{ + size_t residue, n; + + if (len <= 16) + return 0; + + if ((residue = len % 16) == 0) + residue = 16; + + len -= residue; + + CRYPTO_cbc128_encrypt(in, out, len, key, ivec, block); + + in += len; + out += len; + + for (n = 0; n < residue; ++n) + ivec[n] ^= in[n]; + (*block) (ivec, ivec, key); + memcpy(out, out - 16, residue); + memcpy(out - 16, ivec, 16); + + return len + residue; +} + +size_t CRYPTO_nistcts128_encrypt_block(const unsigned char *in, + unsigned char *out, size_t len, + const void *key, + unsigned char ivec[16], + block128_f block) +{ + size_t residue, n; + + if (len < 16) + return 0; + + residue = len % 16; + + len -= residue; + + CRYPTO_cbc128_encrypt(in, out, len, key, ivec, block); + + if (residue == 0) + return len; + + in += len; + out += len; + + for (n = 0; n < residue; ++n) + ivec[n] ^= in[n]; + (*block) (ivec, ivec, key); + memcpy(out - 16 + residue, ivec, 16); + + return len + residue; +} + +size_t CRYPTO_cts128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], cbc128_f cbc) +{ + size_t residue; + union { + size_t align; + unsigned char c[16]; + } tmp; + + if (len <= 16) + return 0; + + if ((residue = len % 16) == 0) + residue = 16; + + len -= residue; + + (*cbc) (in, out, len, key, ivec, 1); + + in += len; + out += len; + +#if defined(CBC_HANDLES_TRUNCATED_IO) + memcpy(tmp.c, out - 16, 16); + (*cbc) (in, out - 16, residue, key, ivec, 1); + memcpy(out, tmp.c, residue); +#else + memset(tmp.c, 0, sizeof(tmp)); + memcpy(tmp.c, in, residue); + memcpy(out, out - 16, residue); + (*cbc) (tmp.c, out - 16, 16, key, ivec, 1); +#endif + return len + residue; +} + +size_t CRYPTO_nistcts128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], cbc128_f cbc) +{ + size_t residue; + union { + size_t align; + unsigned char c[16]; + } tmp; + + if (len < 16) + return 0; + + residue = len % 16; + + len -= residue; + + (*cbc) (in, out, len, key, ivec, 1); + + if (residue == 0) + return len; + + in += len; + out += len; + +#if defined(CBC_HANDLES_TRUNCATED_IO) + (*cbc) (in, out - 16 + residue, residue, key, ivec, 1); +#else + memset(tmp.c, 0, sizeof(tmp)); + memcpy(tmp.c, in, residue); + (*cbc) (tmp.c, out - 16 + residue, 16, key, ivec, 1); +#endif + return len + residue; +} + +size_t CRYPTO_cts128_decrypt_block(const unsigned char *in, + unsigned char *out, size_t len, + const void *key, unsigned char ivec[16], + block128_f block) +{ + size_t residue, n; + union { + size_t align; + unsigned char c[32]; + } tmp; + + if (len <= 16) + return 0; + + if ((residue = len % 16) == 0) + residue = 16; + + len -= 16 + residue; + + if (len) { + CRYPTO_cbc128_decrypt(in, out, len, key, ivec, block); + in += len; + out += len; + } + + (*block) (in, tmp.c + 16, key); + + memcpy(tmp.c, tmp.c + 16, 16); + memcpy(tmp.c, in + 16, residue); + (*block) (tmp.c, tmp.c, key); + + for (n = 0; n < 16; ++n) { + unsigned char c = in[n]; + out[n] = tmp.c[n] ^ ivec[n]; + ivec[n] = c; + } + for (residue += 16; n < residue; ++n) + out[n] = tmp.c[n] ^ in[n]; + + return 16 + len + residue; +} + +size_t CRYPTO_nistcts128_decrypt_block(const unsigned char *in, + unsigned char *out, size_t len, + const void *key, + unsigned char ivec[16], + block128_f block) +{ + size_t residue, n; + union { + size_t align; + unsigned char c[32]; + } tmp; + + if (len < 16) + return 0; + + residue = len % 16; + + if (residue == 0) { + CRYPTO_cbc128_decrypt(in, out, len, key, ivec, block); + return len; + } + + len -= 16 + residue; + + if (len) { + CRYPTO_cbc128_decrypt(in, out, len, key, ivec, block); + in += len; + out += len; + } + + (*block) (in + residue, tmp.c + 16, key); + + memcpy(tmp.c, tmp.c + 16, 16); + memcpy(tmp.c, in, residue); + (*block) (tmp.c, tmp.c, key); + + for (n = 0; n < 16; ++n) { + unsigned char c = in[n]; + out[n] = tmp.c[n] ^ ivec[n]; + ivec[n] = in[n + residue]; + tmp.c[n] = c; + } + for (residue += 16; n < residue; ++n) + out[n] = tmp.c[n] ^ tmp.c[n - 16]; + + return 16 + len + residue; +} + +size_t CRYPTO_cts128_decrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], cbc128_f cbc) +{ + size_t residue; + union { + size_t align; + unsigned char c[32]; + } tmp; + + if (len <= 16) + return 0; + + if ((residue = len % 16) == 0) + residue = 16; + + len -= 16 + residue; + + if (len) { + (*cbc) (in, out, len, key, ivec, 0); + in += len; + out += len; + } + + memset(tmp.c, 0, sizeof(tmp)); + /* + * this places in[16] at &tmp.c[16] and decrypted block at &tmp.c[0] + */ + (*cbc) (in, tmp.c, 16, key, tmp.c + 16, 0); + + memcpy(tmp.c, in + 16, residue); +#if defined(CBC_HANDLES_TRUNCATED_IO) + (*cbc) (tmp.c, out, 16 + residue, key, ivec, 0); +#else + (*cbc) (tmp.c, tmp.c, 32, key, ivec, 0); + memcpy(out, tmp.c, 16 + residue); +#endif + return 16 + len + residue; +} + +size_t CRYPTO_nistcts128_decrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], cbc128_f cbc) +{ + size_t residue; + union { + size_t align; + unsigned char c[32]; + } tmp; + + if (len < 16) + return 0; + + residue = len % 16; + + if (residue == 0) { + (*cbc) (in, out, len, key, ivec, 0); + return len; + } + + len -= 16 + residue; + + if (len) { + (*cbc) (in, out, len, key, ivec, 0); + in += len; + out += len; + } + + memset(tmp.c, 0, sizeof(tmp)); + /* + * this places in[16] at &tmp.c[16] and decrypted block at &tmp.c[0] + */ + (*cbc) (in + residue, tmp.c, 16, key, tmp.c + 16, 0); + + memcpy(tmp.c, in, residue); +#if defined(CBC_HANDLES_TRUNCATED_IO) + (*cbc) (tmp.c, out, 16 + residue, key, ivec, 0); +#else + (*cbc) (tmp.c, tmp.c, 32, key, ivec, 0); + memcpy(out, tmp.c, 16 + residue); +#endif + return 16 + len + residue; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/modes/gcm128.c b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/gcm128.c new file mode 100644 index 000000000..15f76e3e8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/gcm128.c @@ -0,0 +1,1888 @@ +/* + * Copyright 2010-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "modes_lcl.h" +#include + +#if defined(BSWAP4) && defined(STRICT_ALIGNMENT) +/* redefine, because alignment is ensured */ +# undef GETU32 +# define GETU32(p) BSWAP4(*(const u32 *)(p)) +# undef PUTU32 +# define PUTU32(p,v) *(u32 *)(p) = BSWAP4(v) +#endif + +#define PACK(s) ((size_t)(s)<<(sizeof(size_t)*8-16)) +#define REDUCE1BIT(V) do { \ + if (sizeof(size_t)==8) { \ + u64 T = U64(0xe100000000000000) & (0-(V.lo&1)); \ + V.lo = (V.hi<<63)|(V.lo>>1); \ + V.hi = (V.hi>>1 )^T; \ + } \ + else { \ + u32 T = 0xe1000000U & (0-(u32)(V.lo&1)); \ + V.lo = (V.hi<<63)|(V.lo>>1); \ + V.hi = (V.hi>>1 )^((u64)T<<32); \ + } \ +} while(0) + +/*- + * Even though permitted values for TABLE_BITS are 8, 4 and 1, it should + * never be set to 8. 8 is effectively reserved for testing purposes. + * TABLE_BITS>1 are lookup-table-driven implementations referred to as + * "Shoup's" in GCM specification. In other words OpenSSL does not cover + * whole spectrum of possible table driven implementations. Why? In + * non-"Shoup's" case memory access pattern is segmented in such manner, + * that it's trivial to see that cache timing information can reveal + * fair portion of intermediate hash value. Given that ciphertext is + * always available to attacker, it's possible for him to attempt to + * deduce secret parameter H and if successful, tamper with messages + * [which is nothing but trivial in CTR mode]. In "Shoup's" case it's + * not as trivial, but there is no reason to believe that it's resistant + * to cache-timing attack. And the thing about "8-bit" implementation is + * that it consumes 16 (sixteen) times more memory, 4KB per individual + * key + 1KB shared. Well, on pros side it should be twice as fast as + * "4-bit" version. And for gcc-generated x86[_64] code, "8-bit" version + * was observed to run ~75% faster, closer to 100% for commercial + * compilers... Yet "4-bit" procedure is preferred, because it's + * believed to provide better security-performance balance and adequate + * all-round performance. "All-round" refers to things like: + * + * - shorter setup time effectively improves overall timing for + * handling short messages; + * - larger table allocation can become unbearable because of VM + * subsystem penalties (for example on Windows large enough free + * results in VM working set trimming, meaning that consequent + * malloc would immediately incur working set expansion); + * - larger table has larger cache footprint, which can affect + * performance of other code paths (not necessarily even from same + * thread in Hyper-Threading world); + * + * Value of 1 is not appropriate for performance reasons. + */ +#if TABLE_BITS==8 + +static void gcm_init_8bit(u128 Htable[256], u64 H[2]) +{ + int i, j; + u128 V; + + Htable[0].hi = 0; + Htable[0].lo = 0; + V.hi = H[0]; + V.lo = H[1]; + + for (Htable[128] = V, i = 64; i > 0; i >>= 1) { + REDUCE1BIT(V); + Htable[i] = V; + } + + for (i = 2; i < 256; i <<= 1) { + u128 *Hi = Htable + i, H0 = *Hi; + for (j = 1; j < i; ++j) { + Hi[j].hi = H0.hi ^ Htable[j].hi; + Hi[j].lo = H0.lo ^ Htable[j].lo; + } + } +} + +static void gcm_gmult_8bit(u64 Xi[2], const u128 Htable[256]) +{ + u128 Z = { 0, 0 }; + const u8 *xi = (const u8 *)Xi + 15; + size_t rem, n = *xi; + const union { + long one; + char little; + } is_endian = { 1 }; + static const size_t rem_8bit[256] = { + PACK(0x0000), PACK(0x01C2), PACK(0x0384), PACK(0x0246), + PACK(0x0708), PACK(0x06CA), PACK(0x048C), PACK(0x054E), + PACK(0x0E10), PACK(0x0FD2), PACK(0x0D94), PACK(0x0C56), + PACK(0x0918), PACK(0x08DA), PACK(0x0A9C), PACK(0x0B5E), + PACK(0x1C20), PACK(0x1DE2), PACK(0x1FA4), PACK(0x1E66), + PACK(0x1B28), PACK(0x1AEA), PACK(0x18AC), PACK(0x196E), + PACK(0x1230), PACK(0x13F2), PACK(0x11B4), PACK(0x1076), + PACK(0x1538), PACK(0x14FA), PACK(0x16BC), PACK(0x177E), + PACK(0x3840), PACK(0x3982), PACK(0x3BC4), PACK(0x3A06), + PACK(0x3F48), PACK(0x3E8A), PACK(0x3CCC), PACK(0x3D0E), + PACK(0x3650), PACK(0x3792), PACK(0x35D4), PACK(0x3416), + PACK(0x3158), PACK(0x309A), PACK(0x32DC), PACK(0x331E), + PACK(0x2460), PACK(0x25A2), PACK(0x27E4), PACK(0x2626), + PACK(0x2368), PACK(0x22AA), PACK(0x20EC), PACK(0x212E), + PACK(0x2A70), PACK(0x2BB2), PACK(0x29F4), PACK(0x2836), + PACK(0x2D78), PACK(0x2CBA), PACK(0x2EFC), PACK(0x2F3E), + PACK(0x7080), PACK(0x7142), PACK(0x7304), PACK(0x72C6), + PACK(0x7788), PACK(0x764A), PACK(0x740C), PACK(0x75CE), + PACK(0x7E90), PACK(0x7F52), PACK(0x7D14), PACK(0x7CD6), + PACK(0x7998), PACK(0x785A), PACK(0x7A1C), PACK(0x7BDE), + PACK(0x6CA0), PACK(0x6D62), PACK(0x6F24), PACK(0x6EE6), + PACK(0x6BA8), PACK(0x6A6A), PACK(0x682C), PACK(0x69EE), + PACK(0x62B0), PACK(0x6372), PACK(0x6134), PACK(0x60F6), + PACK(0x65B8), PACK(0x647A), PACK(0x663C), PACK(0x67FE), + PACK(0x48C0), PACK(0x4902), PACK(0x4B44), PACK(0x4A86), + PACK(0x4FC8), PACK(0x4E0A), PACK(0x4C4C), PACK(0x4D8E), + PACK(0x46D0), PACK(0x4712), PACK(0x4554), PACK(0x4496), + PACK(0x41D8), PACK(0x401A), PACK(0x425C), PACK(0x439E), + PACK(0x54E0), PACK(0x5522), PACK(0x5764), PACK(0x56A6), + PACK(0x53E8), PACK(0x522A), PACK(0x506C), PACK(0x51AE), + PACK(0x5AF0), PACK(0x5B32), PACK(0x5974), PACK(0x58B6), + PACK(0x5DF8), PACK(0x5C3A), PACK(0x5E7C), PACK(0x5FBE), + PACK(0xE100), PACK(0xE0C2), PACK(0xE284), PACK(0xE346), + PACK(0xE608), PACK(0xE7CA), PACK(0xE58C), PACK(0xE44E), + PACK(0xEF10), PACK(0xEED2), PACK(0xEC94), PACK(0xED56), + PACK(0xE818), PACK(0xE9DA), PACK(0xEB9C), PACK(0xEA5E), + PACK(0xFD20), PACK(0xFCE2), PACK(0xFEA4), PACK(0xFF66), + PACK(0xFA28), PACK(0xFBEA), PACK(0xF9AC), PACK(0xF86E), + PACK(0xF330), PACK(0xF2F2), PACK(0xF0B4), PACK(0xF176), + PACK(0xF438), PACK(0xF5FA), PACK(0xF7BC), PACK(0xF67E), + PACK(0xD940), PACK(0xD882), PACK(0xDAC4), PACK(0xDB06), + PACK(0xDE48), PACK(0xDF8A), PACK(0xDDCC), PACK(0xDC0E), + PACK(0xD750), PACK(0xD692), PACK(0xD4D4), PACK(0xD516), + PACK(0xD058), PACK(0xD19A), PACK(0xD3DC), PACK(0xD21E), + PACK(0xC560), PACK(0xC4A2), PACK(0xC6E4), PACK(0xC726), + PACK(0xC268), PACK(0xC3AA), PACK(0xC1EC), PACK(0xC02E), + PACK(0xCB70), PACK(0xCAB2), PACK(0xC8F4), PACK(0xC936), + PACK(0xCC78), PACK(0xCDBA), PACK(0xCFFC), PACK(0xCE3E), + PACK(0x9180), PACK(0x9042), PACK(0x9204), PACK(0x93C6), + PACK(0x9688), PACK(0x974A), PACK(0x950C), PACK(0x94CE), + PACK(0x9F90), PACK(0x9E52), PACK(0x9C14), PACK(0x9DD6), + PACK(0x9898), PACK(0x995A), PACK(0x9B1C), PACK(0x9ADE), + PACK(0x8DA0), PACK(0x8C62), PACK(0x8E24), PACK(0x8FE6), + PACK(0x8AA8), PACK(0x8B6A), PACK(0x892C), PACK(0x88EE), + PACK(0x83B0), PACK(0x8272), PACK(0x8034), PACK(0x81F6), + PACK(0x84B8), PACK(0x857A), PACK(0x873C), PACK(0x86FE), + PACK(0xA9C0), PACK(0xA802), PACK(0xAA44), PACK(0xAB86), + PACK(0xAEC8), PACK(0xAF0A), PACK(0xAD4C), PACK(0xAC8E), + PACK(0xA7D0), PACK(0xA612), PACK(0xA454), PACK(0xA596), + PACK(0xA0D8), PACK(0xA11A), PACK(0xA35C), PACK(0xA29E), + PACK(0xB5E0), PACK(0xB422), PACK(0xB664), PACK(0xB7A6), + PACK(0xB2E8), PACK(0xB32A), PACK(0xB16C), PACK(0xB0AE), + PACK(0xBBF0), PACK(0xBA32), PACK(0xB874), PACK(0xB9B6), + PACK(0xBCF8), PACK(0xBD3A), PACK(0xBF7C), PACK(0xBEBE) + }; + + while (1) { + Z.hi ^= Htable[n].hi; + Z.lo ^= Htable[n].lo; + + if ((u8 *)Xi == xi) + break; + + n = *(--xi); + + rem = (size_t)Z.lo & 0xff; + Z.lo = (Z.hi << 56) | (Z.lo >> 8); + Z.hi = (Z.hi >> 8); + if (sizeof(size_t) == 8) + Z.hi ^= rem_8bit[rem]; + else + Z.hi ^= (u64)rem_8bit[rem] << 32; + } + + if (is_endian.little) { +# ifdef BSWAP8 + Xi[0] = BSWAP8(Z.hi); + Xi[1] = BSWAP8(Z.lo); +# else + u8 *p = (u8 *)Xi; + u32 v; + v = (u32)(Z.hi >> 32); + PUTU32(p, v); + v = (u32)(Z.hi); + PUTU32(p + 4, v); + v = (u32)(Z.lo >> 32); + PUTU32(p + 8, v); + v = (u32)(Z.lo); + PUTU32(p + 12, v); +# endif + } else { + Xi[0] = Z.hi; + Xi[1] = Z.lo; + } +} + +# define GCM_MUL(ctx) gcm_gmult_8bit(ctx->Xi.u,ctx->Htable) + +#elif TABLE_BITS==4 + +static void gcm_init_4bit(u128 Htable[16], u64 H[2]) +{ + u128 V; +# if defined(OPENSSL_SMALL_FOOTPRINT) + int i; +# endif + + Htable[0].hi = 0; + Htable[0].lo = 0; + V.hi = H[0]; + V.lo = H[1]; + +# if defined(OPENSSL_SMALL_FOOTPRINT) + for (Htable[8] = V, i = 4; i > 0; i >>= 1) { + REDUCE1BIT(V); + Htable[i] = V; + } + + for (i = 2; i < 16; i <<= 1) { + u128 *Hi = Htable + i; + int j; + for (V = *Hi, j = 1; j < i; ++j) { + Hi[j].hi = V.hi ^ Htable[j].hi; + Hi[j].lo = V.lo ^ Htable[j].lo; + } + } +# else + Htable[8] = V; + REDUCE1BIT(V); + Htable[4] = V; + REDUCE1BIT(V); + Htable[2] = V; + REDUCE1BIT(V); + Htable[1] = V; + Htable[3].hi = V.hi ^ Htable[2].hi, Htable[3].lo = V.lo ^ Htable[2].lo; + V = Htable[4]; + Htable[5].hi = V.hi ^ Htable[1].hi, Htable[5].lo = V.lo ^ Htable[1].lo; + Htable[6].hi = V.hi ^ Htable[2].hi, Htable[6].lo = V.lo ^ Htable[2].lo; + Htable[7].hi = V.hi ^ Htable[3].hi, Htable[7].lo = V.lo ^ Htable[3].lo; + V = Htable[8]; + Htable[9].hi = V.hi ^ Htable[1].hi, Htable[9].lo = V.lo ^ Htable[1].lo; + Htable[10].hi = V.hi ^ Htable[2].hi, Htable[10].lo = V.lo ^ Htable[2].lo; + Htable[11].hi = V.hi ^ Htable[3].hi, Htable[11].lo = V.lo ^ Htable[3].lo; + Htable[12].hi = V.hi ^ Htable[4].hi, Htable[12].lo = V.lo ^ Htable[4].lo; + Htable[13].hi = V.hi ^ Htable[5].hi, Htable[13].lo = V.lo ^ Htable[5].lo; + Htable[14].hi = V.hi ^ Htable[6].hi, Htable[14].lo = V.lo ^ Htable[6].lo; + Htable[15].hi = V.hi ^ Htable[7].hi, Htable[15].lo = V.lo ^ Htable[7].lo; +# endif +# if defined(GHASH_ASM) && (defined(__arm__) || defined(__arm)) + /* + * ARM assembler expects specific dword order in Htable. + */ + { + int j; + const union { + long one; + char little; + } is_endian = { 1 }; + + if (is_endian.little) + for (j = 0; j < 16; ++j) { + V = Htable[j]; + Htable[j].hi = V.lo; + Htable[j].lo = V.hi; + } else + for (j = 0; j < 16; ++j) { + V = Htable[j]; + Htable[j].hi = V.lo << 32 | V.lo >> 32; + Htable[j].lo = V.hi << 32 | V.hi >> 32; + } + } +# endif +} + +# ifndef GHASH_ASM +static const size_t rem_4bit[16] = { + PACK(0x0000), PACK(0x1C20), PACK(0x3840), PACK(0x2460), + PACK(0x7080), PACK(0x6CA0), PACK(0x48C0), PACK(0x54E0), + PACK(0xE100), PACK(0xFD20), PACK(0xD940), PACK(0xC560), + PACK(0x9180), PACK(0x8DA0), PACK(0xA9C0), PACK(0xB5E0) +}; + +static void gcm_gmult_4bit(u64 Xi[2], const u128 Htable[16]) +{ + u128 Z; + int cnt = 15; + size_t rem, nlo, nhi; + const union { + long one; + char little; + } is_endian = { 1 }; + + nlo = ((const u8 *)Xi)[15]; + nhi = nlo >> 4; + nlo &= 0xf; + + Z.hi = Htable[nlo].hi; + Z.lo = Htable[nlo].lo; + + while (1) { + rem = (size_t)Z.lo & 0xf; + Z.lo = (Z.hi << 60) | (Z.lo >> 4); + Z.hi = (Z.hi >> 4); + if (sizeof(size_t) == 8) + Z.hi ^= rem_4bit[rem]; + else + Z.hi ^= (u64)rem_4bit[rem] << 32; + + Z.hi ^= Htable[nhi].hi; + Z.lo ^= Htable[nhi].lo; + + if (--cnt < 0) + break; + + nlo = ((const u8 *)Xi)[cnt]; + nhi = nlo >> 4; + nlo &= 0xf; + + rem = (size_t)Z.lo & 0xf; + Z.lo = (Z.hi << 60) | (Z.lo >> 4); + Z.hi = (Z.hi >> 4); + if (sizeof(size_t) == 8) + Z.hi ^= rem_4bit[rem]; + else + Z.hi ^= (u64)rem_4bit[rem] << 32; + + Z.hi ^= Htable[nlo].hi; + Z.lo ^= Htable[nlo].lo; + } + + if (is_endian.little) { +# ifdef BSWAP8 + Xi[0] = BSWAP8(Z.hi); + Xi[1] = BSWAP8(Z.lo); +# else + u8 *p = (u8 *)Xi; + u32 v; + v = (u32)(Z.hi >> 32); + PUTU32(p, v); + v = (u32)(Z.hi); + PUTU32(p + 4, v); + v = (u32)(Z.lo >> 32); + PUTU32(p + 8, v); + v = (u32)(Z.lo); + PUTU32(p + 12, v); +# endif + } else { + Xi[0] = Z.hi; + Xi[1] = Z.lo; + } +} + +# if !defined(OPENSSL_SMALL_FOOTPRINT) +/* + * Streamed gcm_mult_4bit, see CRYPTO_gcm128_[en|de]crypt for + * details... Compiler-generated code doesn't seem to give any + * performance improvement, at least not on x86[_64]. It's here + * mostly as reference and a placeholder for possible future + * non-trivial optimization[s]... + */ +static void gcm_ghash_4bit(u64 Xi[2], const u128 Htable[16], + const u8 *inp, size_t len) +{ + u128 Z; + int cnt; + size_t rem, nlo, nhi; + const union { + long one; + char little; + } is_endian = { 1 }; + +# if 1 + do { + cnt = 15; + nlo = ((const u8 *)Xi)[15]; + nlo ^= inp[15]; + nhi = nlo >> 4; + nlo &= 0xf; + + Z.hi = Htable[nlo].hi; + Z.lo = Htable[nlo].lo; + + while (1) { + rem = (size_t)Z.lo & 0xf; + Z.lo = (Z.hi << 60) | (Z.lo >> 4); + Z.hi = (Z.hi >> 4); + if (sizeof(size_t) == 8) + Z.hi ^= rem_4bit[rem]; + else + Z.hi ^= (u64)rem_4bit[rem] << 32; + + Z.hi ^= Htable[nhi].hi; + Z.lo ^= Htable[nhi].lo; + + if (--cnt < 0) + break; + + nlo = ((const u8 *)Xi)[cnt]; + nlo ^= inp[cnt]; + nhi = nlo >> 4; + nlo &= 0xf; + + rem = (size_t)Z.lo & 0xf; + Z.lo = (Z.hi << 60) | (Z.lo >> 4); + Z.hi = (Z.hi >> 4); + if (sizeof(size_t) == 8) + Z.hi ^= rem_4bit[rem]; + else + Z.hi ^= (u64)rem_4bit[rem] << 32; + + Z.hi ^= Htable[nlo].hi; + Z.lo ^= Htable[nlo].lo; + } +# else + /* + * Extra 256+16 bytes per-key plus 512 bytes shared tables + * [should] give ~50% improvement... One could have PACK()-ed + * the rem_8bit even here, but the priority is to minimize + * cache footprint... + */ + u128 Hshr4[16]; /* Htable shifted right by 4 bits */ + u8 Hshl4[16]; /* Htable shifted left by 4 bits */ + static const unsigned short rem_8bit[256] = { + 0x0000, 0x01C2, 0x0384, 0x0246, 0x0708, 0x06CA, 0x048C, 0x054E, + 0x0E10, 0x0FD2, 0x0D94, 0x0C56, 0x0918, 0x08DA, 0x0A9C, 0x0B5E, + 0x1C20, 0x1DE2, 0x1FA4, 0x1E66, 0x1B28, 0x1AEA, 0x18AC, 0x196E, + 0x1230, 0x13F2, 0x11B4, 0x1076, 0x1538, 0x14FA, 0x16BC, 0x177E, + 0x3840, 0x3982, 0x3BC4, 0x3A06, 0x3F48, 0x3E8A, 0x3CCC, 0x3D0E, + 0x3650, 0x3792, 0x35D4, 0x3416, 0x3158, 0x309A, 0x32DC, 0x331E, + 0x2460, 0x25A2, 0x27E4, 0x2626, 0x2368, 0x22AA, 0x20EC, 0x212E, + 0x2A70, 0x2BB2, 0x29F4, 0x2836, 0x2D78, 0x2CBA, 0x2EFC, 0x2F3E, + 0x7080, 0x7142, 0x7304, 0x72C6, 0x7788, 0x764A, 0x740C, 0x75CE, + 0x7E90, 0x7F52, 0x7D14, 0x7CD6, 0x7998, 0x785A, 0x7A1C, 0x7BDE, + 0x6CA0, 0x6D62, 0x6F24, 0x6EE6, 0x6BA8, 0x6A6A, 0x682C, 0x69EE, + 0x62B0, 0x6372, 0x6134, 0x60F6, 0x65B8, 0x647A, 0x663C, 0x67FE, + 0x48C0, 0x4902, 0x4B44, 0x4A86, 0x4FC8, 0x4E0A, 0x4C4C, 0x4D8E, + 0x46D0, 0x4712, 0x4554, 0x4496, 0x41D8, 0x401A, 0x425C, 0x439E, + 0x54E0, 0x5522, 0x5764, 0x56A6, 0x53E8, 0x522A, 0x506C, 0x51AE, + 0x5AF0, 0x5B32, 0x5974, 0x58B6, 0x5DF8, 0x5C3A, 0x5E7C, 0x5FBE, + 0xE100, 0xE0C2, 0xE284, 0xE346, 0xE608, 0xE7CA, 0xE58C, 0xE44E, + 0xEF10, 0xEED2, 0xEC94, 0xED56, 0xE818, 0xE9DA, 0xEB9C, 0xEA5E, + 0xFD20, 0xFCE2, 0xFEA4, 0xFF66, 0xFA28, 0xFBEA, 0xF9AC, 0xF86E, + 0xF330, 0xF2F2, 0xF0B4, 0xF176, 0xF438, 0xF5FA, 0xF7BC, 0xF67E, + 0xD940, 0xD882, 0xDAC4, 0xDB06, 0xDE48, 0xDF8A, 0xDDCC, 0xDC0E, + 0xD750, 0xD692, 0xD4D4, 0xD516, 0xD058, 0xD19A, 0xD3DC, 0xD21E, + 0xC560, 0xC4A2, 0xC6E4, 0xC726, 0xC268, 0xC3AA, 0xC1EC, 0xC02E, + 0xCB70, 0xCAB2, 0xC8F4, 0xC936, 0xCC78, 0xCDBA, 0xCFFC, 0xCE3E, + 0x9180, 0x9042, 0x9204, 0x93C6, 0x9688, 0x974A, 0x950C, 0x94CE, + 0x9F90, 0x9E52, 0x9C14, 0x9DD6, 0x9898, 0x995A, 0x9B1C, 0x9ADE, + 0x8DA0, 0x8C62, 0x8E24, 0x8FE6, 0x8AA8, 0x8B6A, 0x892C, 0x88EE, + 0x83B0, 0x8272, 0x8034, 0x81F6, 0x84B8, 0x857A, 0x873C, 0x86FE, + 0xA9C0, 0xA802, 0xAA44, 0xAB86, 0xAEC8, 0xAF0A, 0xAD4C, 0xAC8E, + 0xA7D0, 0xA612, 0xA454, 0xA596, 0xA0D8, 0xA11A, 0xA35C, 0xA29E, + 0xB5E0, 0xB422, 0xB664, 0xB7A6, 0xB2E8, 0xB32A, 0xB16C, 0xB0AE, + 0xBBF0, 0xBA32, 0xB874, 0xB9B6, 0xBCF8, 0xBD3A, 0xBF7C, 0xBEBE + }; + /* + * This pre-processing phase slows down procedure by approximately + * same time as it makes each loop spin faster. In other words + * single block performance is approximately same as straightforward + * "4-bit" implementation, and then it goes only faster... + */ + for (cnt = 0; cnt < 16; ++cnt) { + Z.hi = Htable[cnt].hi; + Z.lo = Htable[cnt].lo; + Hshr4[cnt].lo = (Z.hi << 60) | (Z.lo >> 4); + Hshr4[cnt].hi = (Z.hi >> 4); + Hshl4[cnt] = (u8)(Z.lo << 4); + } + + do { + for (Z.lo = 0, Z.hi = 0, cnt = 15; cnt; --cnt) { + nlo = ((const u8 *)Xi)[cnt]; + nlo ^= inp[cnt]; + nhi = nlo >> 4; + nlo &= 0xf; + + Z.hi ^= Htable[nlo].hi; + Z.lo ^= Htable[nlo].lo; + + rem = (size_t)Z.lo & 0xff; + + Z.lo = (Z.hi << 56) | (Z.lo >> 8); + Z.hi = (Z.hi >> 8); + + Z.hi ^= Hshr4[nhi].hi; + Z.lo ^= Hshr4[nhi].lo; + Z.hi ^= (u64)rem_8bit[rem ^ Hshl4[nhi]] << 48; + } + + nlo = ((const u8 *)Xi)[0]; + nlo ^= inp[0]; + nhi = nlo >> 4; + nlo &= 0xf; + + Z.hi ^= Htable[nlo].hi; + Z.lo ^= Htable[nlo].lo; + + rem = (size_t)Z.lo & 0xf; + + Z.lo = (Z.hi << 60) | (Z.lo >> 4); + Z.hi = (Z.hi >> 4); + + Z.hi ^= Htable[nhi].hi; + Z.lo ^= Htable[nhi].lo; + Z.hi ^= ((u64)rem_8bit[rem << 4]) << 48; +# endif + + if (is_endian.little) { +# ifdef BSWAP8 + Xi[0] = BSWAP8(Z.hi); + Xi[1] = BSWAP8(Z.lo); +# else + u8 *p = (u8 *)Xi; + u32 v; + v = (u32)(Z.hi >> 32); + PUTU32(p, v); + v = (u32)(Z.hi); + PUTU32(p + 4, v); + v = (u32)(Z.lo >> 32); + PUTU32(p + 8, v); + v = (u32)(Z.lo); + PUTU32(p + 12, v); +# endif + } else { + Xi[0] = Z.hi; + Xi[1] = Z.lo; + } + } while (inp += 16, len -= 16); +} +# endif +# else +void gcm_gmult_4bit(u64 Xi[2], const u128 Htable[16]); +void gcm_ghash_4bit(u64 Xi[2], const u128 Htable[16], const u8 *inp, + size_t len); +# endif + +# define GCM_MUL(ctx) gcm_gmult_4bit(ctx->Xi.u,ctx->Htable) +# if defined(GHASH_ASM) || !defined(OPENSSL_SMALL_FOOTPRINT) +# define GHASH(ctx,in,len) gcm_ghash_4bit((ctx)->Xi.u,(ctx)->Htable,in,len) +/* + * GHASH_CHUNK is "stride parameter" missioned to mitigate cache trashing + * effect. In other words idea is to hash data while it's still in L1 cache + * after encryption pass... + */ +# define GHASH_CHUNK (3*1024) +# endif + +#else /* TABLE_BITS */ + +static void gcm_gmult_1bit(u64 Xi[2], const u64 H[2]) +{ + u128 V, Z = { 0, 0 }; + long X; + int i, j; + const long *xi = (const long *)Xi; + const union { + long one; + char little; + } is_endian = { 1 }; + + V.hi = H[0]; /* H is in host byte order, no byte swapping */ + V.lo = H[1]; + + for (j = 0; j < 16 / sizeof(long); ++j) { + if (is_endian.little) { + if (sizeof(long) == 8) { +# ifdef BSWAP8 + X = (long)(BSWAP8(xi[j])); +# else + const u8 *p = (const u8 *)(xi + j); + X = (long)((u64)GETU32(p) << 32 | GETU32(p + 4)); +# endif + } else { + const u8 *p = (const u8 *)(xi + j); + X = (long)GETU32(p); + } + } else + X = xi[j]; + + for (i = 0; i < 8 * sizeof(long); ++i, X <<= 1) { + u64 M = (u64)(X >> (8 * sizeof(long) - 1)); + Z.hi ^= V.hi & M; + Z.lo ^= V.lo & M; + + REDUCE1BIT(V); + } + } + + if (is_endian.little) { +# ifdef BSWAP8 + Xi[0] = BSWAP8(Z.hi); + Xi[1] = BSWAP8(Z.lo); +# else + u8 *p = (u8 *)Xi; + u32 v; + v = (u32)(Z.hi >> 32); + PUTU32(p, v); + v = (u32)(Z.hi); + PUTU32(p + 4, v); + v = (u32)(Z.lo >> 32); + PUTU32(p + 8, v); + v = (u32)(Z.lo); + PUTU32(p + 12, v); +# endif + } else { + Xi[0] = Z.hi; + Xi[1] = Z.lo; + } +} + +# define GCM_MUL(ctx) gcm_gmult_1bit(ctx->Xi.u,ctx->H.u) + +#endif + +#if TABLE_BITS==4 && (defined(GHASH_ASM) || defined(OPENSSL_CPUID_OBJ)) +# if !defined(I386_ONLY) && \ + (defined(__i386) || defined(__i386__) || \ + defined(__x86_64) || defined(__x86_64__) || \ + defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64)) +# define GHASH_ASM_X86_OR_64 +# define GCM_FUNCREF_4BIT +extern unsigned int OPENSSL_ia32cap_P[]; + +void gcm_init_clmul(u128 Htable[16], const u64 Xi[2]); +void gcm_gmult_clmul(u64 Xi[2], const u128 Htable[16]); +void gcm_ghash_clmul(u64 Xi[2], const u128 Htable[16], const u8 *inp, + size_t len); + +# if defined(__i386) || defined(__i386__) || defined(_M_IX86) +# define gcm_init_avx gcm_init_clmul +# define gcm_gmult_avx gcm_gmult_clmul +# define gcm_ghash_avx gcm_ghash_clmul +# else +void gcm_init_avx(u128 Htable[16], const u64 Xi[2]); +void gcm_gmult_avx(u64 Xi[2], const u128 Htable[16]); +void gcm_ghash_avx(u64 Xi[2], const u128 Htable[16], const u8 *inp, + size_t len); +# endif + +# if defined(__i386) || defined(__i386__) || defined(_M_IX86) +# define GHASH_ASM_X86 +void gcm_gmult_4bit_mmx(u64 Xi[2], const u128 Htable[16]); +void gcm_ghash_4bit_mmx(u64 Xi[2], const u128 Htable[16], const u8 *inp, + size_t len); + +void gcm_gmult_4bit_x86(u64 Xi[2], const u128 Htable[16]); +void gcm_ghash_4bit_x86(u64 Xi[2], const u128 Htable[16], const u8 *inp, + size_t len); +# endif +# elif defined(__arm__) || defined(__arm) || defined(__aarch64__) +# include "arm_arch.h" +# if __ARM_MAX_ARCH__>=7 +# define GHASH_ASM_ARM +# define GCM_FUNCREF_4BIT +# define PMULL_CAPABLE (OPENSSL_armcap_P & ARMV8_PMULL) +# if defined(__arm__) || defined(__arm) +# define NEON_CAPABLE (OPENSSL_armcap_P & ARMV7_NEON) +# endif +void gcm_init_neon(u128 Htable[16], const u64 Xi[2]); +void gcm_gmult_neon(u64 Xi[2], const u128 Htable[16]); +void gcm_ghash_neon(u64 Xi[2], const u128 Htable[16], const u8 *inp, + size_t len); +void gcm_init_v8(u128 Htable[16], const u64 Xi[2]); +void gcm_gmult_v8(u64 Xi[2], const u128 Htable[16]); +void gcm_ghash_v8(u64 Xi[2], const u128 Htable[16], const u8 *inp, + size_t len); +# endif +# elif defined(__sparc__) || defined(__sparc) +# include "sparc_arch.h" +# define GHASH_ASM_SPARC +# define GCM_FUNCREF_4BIT +extern unsigned int OPENSSL_sparcv9cap_P[]; +void gcm_init_vis3(u128 Htable[16], const u64 Xi[2]); +void gcm_gmult_vis3(u64 Xi[2], const u128 Htable[16]); +void gcm_ghash_vis3(u64 Xi[2], const u128 Htable[16], const u8 *inp, + size_t len); +# elif defined(OPENSSL_CPUID_OBJ) && (defined(__powerpc__) || defined(__ppc__) || defined(_ARCH_PPC)) +# include "ppc_arch.h" +# define GHASH_ASM_PPC +# define GCM_FUNCREF_4BIT +void gcm_init_p8(u128 Htable[16], const u64 Xi[2]); +void gcm_gmult_p8(u64 Xi[2], const u128 Htable[16]); +void gcm_ghash_p8(u64 Xi[2], const u128 Htable[16], const u8 *inp, + size_t len); +# endif +#endif + +#ifdef GCM_FUNCREF_4BIT +# undef GCM_MUL +# define GCM_MUL(ctx) (*gcm_gmult_p)(ctx->Xi.u,ctx->Htable) +# ifdef GHASH +# undef GHASH +# define GHASH(ctx,in,len) (*gcm_ghash_p)(ctx->Xi.u,ctx->Htable,in,len) +# endif +#endif + +void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, void *key, block128_f block) +{ + const union { + long one; + char little; + } is_endian = { 1 }; + + memset(ctx, 0, sizeof(*ctx)); + ctx->block = block; + ctx->key = key; + + (*block) (ctx->H.c, ctx->H.c, key); + + if (is_endian.little) { + /* H is stored in host byte order */ +#ifdef BSWAP8 + ctx->H.u[0] = BSWAP8(ctx->H.u[0]); + ctx->H.u[1] = BSWAP8(ctx->H.u[1]); +#else + u8 *p = ctx->H.c; + u64 hi, lo; + hi = (u64)GETU32(p) << 32 | GETU32(p + 4); + lo = (u64)GETU32(p + 8) << 32 | GETU32(p + 12); + ctx->H.u[0] = hi; + ctx->H.u[1] = lo; +#endif + } +#if TABLE_BITS==8 + gcm_init_8bit(ctx->Htable, ctx->H.u); +#elif TABLE_BITS==4 +# if defined(GHASH) +# define CTX__GHASH(f) (ctx->ghash = (f)) +# else +# define CTX__GHASH(f) (ctx->ghash = NULL) +# endif +# if defined(GHASH_ASM_X86_OR_64) +# if !defined(GHASH_ASM_X86) || defined(OPENSSL_IA32_SSE2) + if (OPENSSL_ia32cap_P[1] & (1 << 1)) { /* check PCLMULQDQ bit */ + if (((OPENSSL_ia32cap_P[1] >> 22) & 0x41) == 0x41) { /* AVX+MOVBE */ + gcm_init_avx(ctx->Htable, ctx->H.u); + ctx->gmult = gcm_gmult_avx; + CTX__GHASH(gcm_ghash_avx); + } else { + gcm_init_clmul(ctx->Htable, ctx->H.u); + ctx->gmult = gcm_gmult_clmul; + CTX__GHASH(gcm_ghash_clmul); + } + return; + } +# endif + gcm_init_4bit(ctx->Htable, ctx->H.u); +# if defined(GHASH_ASM_X86) /* x86 only */ +# if defined(OPENSSL_IA32_SSE2) + if (OPENSSL_ia32cap_P[0] & (1 << 25)) { /* check SSE bit */ +# else + if (OPENSSL_ia32cap_P[0] & (1 << 23)) { /* check MMX bit */ +# endif + ctx->gmult = gcm_gmult_4bit_mmx; + CTX__GHASH(gcm_ghash_4bit_mmx); + } else { + ctx->gmult = gcm_gmult_4bit_x86; + CTX__GHASH(gcm_ghash_4bit_x86); + } +# else + ctx->gmult = gcm_gmult_4bit; + CTX__GHASH(gcm_ghash_4bit); +# endif +# elif defined(GHASH_ASM_ARM) +# ifdef PMULL_CAPABLE + if (PMULL_CAPABLE) { + gcm_init_v8(ctx->Htable, ctx->H.u); + ctx->gmult = gcm_gmult_v8; + CTX__GHASH(gcm_ghash_v8); + } else +# endif +# ifdef NEON_CAPABLE + if (NEON_CAPABLE) { + gcm_init_neon(ctx->Htable, ctx->H.u); + ctx->gmult = gcm_gmult_neon; + CTX__GHASH(gcm_ghash_neon); + } else +# endif + { + gcm_init_4bit(ctx->Htable, ctx->H.u); + ctx->gmult = gcm_gmult_4bit; + CTX__GHASH(gcm_ghash_4bit); + } +# elif defined(GHASH_ASM_SPARC) + if (OPENSSL_sparcv9cap_P[0] & SPARCV9_VIS3) { + gcm_init_vis3(ctx->Htable, ctx->H.u); + ctx->gmult = gcm_gmult_vis3; + CTX__GHASH(gcm_ghash_vis3); + } else { + gcm_init_4bit(ctx->Htable, ctx->H.u); + ctx->gmult = gcm_gmult_4bit; + CTX__GHASH(gcm_ghash_4bit); + } +# elif defined(GHASH_ASM_PPC) + if (OPENSSL_ppccap_P & PPC_CRYPTO207) { + gcm_init_p8(ctx->Htable, ctx->H.u); + ctx->gmult = gcm_gmult_p8; + CTX__GHASH(gcm_ghash_p8); + } else { + gcm_init_4bit(ctx->Htable, ctx->H.u); + ctx->gmult = gcm_gmult_4bit; + CTX__GHASH(gcm_ghash_4bit); + } +# else + gcm_init_4bit(ctx->Htable, ctx->H.u); +# endif +# undef CTX__GHASH +#endif +} + +void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const unsigned char *iv, + size_t len) +{ + const union { + long one; + char little; + } is_endian = { 1 }; + unsigned int ctr; +#ifdef GCM_FUNCREF_4BIT + void (*gcm_gmult_p) (u64 Xi[2], const u128 Htable[16]) = ctx->gmult; +#endif + + ctx->len.u[0] = 0; /* AAD length */ + ctx->len.u[1] = 0; /* message length */ + ctx->ares = 0; + ctx->mres = 0; + + if (len == 12) { + memcpy(ctx->Yi.c, iv, 12); + ctx->Yi.c[12] = 0; + ctx->Yi.c[13] = 0; + ctx->Yi.c[14] = 0; + ctx->Yi.c[15] = 1; + ctr = 1; + } else { + size_t i; + u64 len0 = len; + + /* Borrow ctx->Xi to calculate initial Yi */ + ctx->Xi.u[0] = 0; + ctx->Xi.u[1] = 0; + + while (len >= 16) { + for (i = 0; i < 16; ++i) + ctx->Xi.c[i] ^= iv[i]; + GCM_MUL(ctx); + iv += 16; + len -= 16; + } + if (len) { + for (i = 0; i < len; ++i) + ctx->Xi.c[i] ^= iv[i]; + GCM_MUL(ctx); + } + len0 <<= 3; + if (is_endian.little) { +#ifdef BSWAP8 + ctx->Xi.u[1] ^= BSWAP8(len0); +#else + ctx->Xi.c[8] ^= (u8)(len0 >> 56); + ctx->Xi.c[9] ^= (u8)(len0 >> 48); + ctx->Xi.c[10] ^= (u8)(len0 >> 40); + ctx->Xi.c[11] ^= (u8)(len0 >> 32); + ctx->Xi.c[12] ^= (u8)(len0 >> 24); + ctx->Xi.c[13] ^= (u8)(len0 >> 16); + ctx->Xi.c[14] ^= (u8)(len0 >> 8); + ctx->Xi.c[15] ^= (u8)(len0); +#endif + } else { + ctx->Xi.u[1] ^= len0; + } + + GCM_MUL(ctx); + + if (is_endian.little) +#ifdef BSWAP4 + ctr = BSWAP4(ctx->Xi.d[3]); +#else + ctr = GETU32(ctx->Xi.c + 12); +#endif + else + ctr = ctx->Xi.d[3]; + + /* Copy borrowed Xi to Yi */ + ctx->Yi.u[0] = ctx->Xi.u[0]; + ctx->Yi.u[1] = ctx->Xi.u[1]; + } + + ctx->Xi.u[0] = 0; + ctx->Xi.u[1] = 0; + + (*ctx->block) (ctx->Yi.c, ctx->EK0.c, ctx->key); + ++ctr; + if (is_endian.little) +#ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +#else + PUTU32(ctx->Yi.c + 12, ctr); +#endif + else + ctx->Yi.d[3] = ctr; +} + +int CRYPTO_gcm128_aad(GCM128_CONTEXT *ctx, const unsigned char *aad, + size_t len) +{ + size_t i; + unsigned int n; + u64 alen = ctx->len.u[0]; +#ifdef GCM_FUNCREF_4BIT + void (*gcm_gmult_p) (u64 Xi[2], const u128 Htable[16]) = ctx->gmult; +# ifdef GHASH + void (*gcm_ghash_p) (u64 Xi[2], const u128 Htable[16], + const u8 *inp, size_t len) = ctx->ghash; +# endif +#endif + + if (ctx->len.u[1]) + return -2; + + alen += len; + if (alen > (U64(1) << 61) || (sizeof(len) == 8 && alen < len)) + return -1; + ctx->len.u[0] = alen; + + n = ctx->ares; + if (n) { + while (n && len) { + ctx->Xi.c[n] ^= *(aad++); + --len; + n = (n + 1) % 16; + } + if (n == 0) + GCM_MUL(ctx); + else { + ctx->ares = n; + return 0; + } + } +#ifdef GHASH + if ((i = (len & (size_t)-16))) { + GHASH(ctx, aad, i); + aad += i; + len -= i; + } +#else + while (len >= 16) { + for (i = 0; i < 16; ++i) + ctx->Xi.c[i] ^= aad[i]; + GCM_MUL(ctx); + aad += 16; + len -= 16; + } +#endif + if (len) { + n = (unsigned int)len; + for (i = 0; i < len; ++i) + ctx->Xi.c[i] ^= aad[i]; + } + + ctx->ares = n; + return 0; +} + +int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, + const unsigned char *in, unsigned char *out, + size_t len) +{ + const union { + long one; + char little; + } is_endian = { 1 }; + unsigned int n, ctr, mres; + size_t i; + u64 mlen = ctx->len.u[1]; + block128_f block = ctx->block; + void *key = ctx->key; +#ifdef GCM_FUNCREF_4BIT + void (*gcm_gmult_p) (u64 Xi[2], const u128 Htable[16]) = ctx->gmult; +# if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT) + void (*gcm_ghash_p) (u64 Xi[2], const u128 Htable[16], + const u8 *inp, size_t len) = ctx->ghash; +# endif +#endif + + mlen += len; + if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len)) + return -1; + ctx->len.u[1] = mlen; + + mres = ctx->mres; + + if (ctx->ares) { + /* First call to encrypt finalizes GHASH(AAD) */ +#if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT) + if (len == 0) { + GCM_MUL(ctx); + ctx->ares = 0; + return 0; + } + memcpy(ctx->Xn, ctx->Xi.c, sizeof(ctx->Xi)); + ctx->Xi.u[0] = 0; + ctx->Xi.u[1] = 0; + mres = sizeof(ctx->Xi); +#else + GCM_MUL(ctx); +#endif + ctx->ares = 0; + } + + if (is_endian.little) +#ifdef BSWAP4 + ctr = BSWAP4(ctx->Yi.d[3]); +#else + ctr = GETU32(ctx->Yi.c + 12); +#endif + else + ctr = ctx->Yi.d[3]; + + n = mres % 16; +#if !defined(OPENSSL_SMALL_FOOTPRINT) + if (16 % sizeof(size_t) == 0) { /* always true actually */ + do { + if (n) { +# if defined(GHASH) + while (n && len) { + ctx->Xn[mres++] = *(out++) = *(in++) ^ ctx->EKi.c[n]; + --len; + n = (n + 1) % 16; + } + if (n == 0) { + GHASH(ctx, ctx->Xn, mres); + mres = 0; + } else { + ctx->mres = mres; + return 0; + } +# else + while (n && len) { + ctx->Xi.c[n] ^= *(out++) = *(in++) ^ ctx->EKi.c[n]; + --len; + n = (n + 1) % 16; + } + if (n == 0) { + GCM_MUL(ctx); + mres = 0; + } else { + ctx->mres = n; + return 0; + } +# endif + } +# if defined(STRICT_ALIGNMENT) + if (((size_t)in | (size_t)out) % sizeof(size_t) != 0) + break; +# endif +# if defined(GHASH) + if (len >= 16 && mres) { + GHASH(ctx, ctx->Xn, mres); + mres = 0; + } +# if defined(GHASH_CHUNK) + while (len >= GHASH_CHUNK) { + size_t j = GHASH_CHUNK; + + while (j) { + size_t *out_t = (size_t *)out; + const size_t *in_t = (const size_t *)in; + + (*block) (ctx->Yi.c, ctx->EKi.c, key); + ++ctr; + if (is_endian.little) +# ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +# else + PUTU32(ctx->Yi.c + 12, ctr); +# endif + else + ctx->Yi.d[3] = ctr; + for (i = 0; i < 16 / sizeof(size_t); ++i) + out_t[i] = in_t[i] ^ ctx->EKi.t[i]; + out += 16; + in += 16; + j -= 16; + } + GHASH(ctx, out - GHASH_CHUNK, GHASH_CHUNK); + len -= GHASH_CHUNK; + } +# endif + if ((i = (len & (size_t)-16))) { + size_t j = i; + + while (len >= 16) { + size_t *out_t = (size_t *)out; + const size_t *in_t = (const size_t *)in; + + (*block) (ctx->Yi.c, ctx->EKi.c, key); + ++ctr; + if (is_endian.little) +# ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +# else + PUTU32(ctx->Yi.c + 12, ctr); +# endif + else + ctx->Yi.d[3] = ctr; + for (i = 0; i < 16 / sizeof(size_t); ++i) + out_t[i] = in_t[i] ^ ctx->EKi.t[i]; + out += 16; + in += 16; + len -= 16; + } + GHASH(ctx, out - j, j); + } +# else + while (len >= 16) { + size_t *out_t = (size_t *)out; + const size_t *in_t = (const size_t *)in; + + (*block) (ctx->Yi.c, ctx->EKi.c, key); + ++ctr; + if (is_endian.little) +# ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +# else + PUTU32(ctx->Yi.c + 12, ctr); +# endif + else + ctx->Yi.d[3] = ctr; + for (i = 0; i < 16 / sizeof(size_t); ++i) + ctx->Xi.t[i] ^= out_t[i] = in_t[i] ^ ctx->EKi.t[i]; + GCM_MUL(ctx); + out += 16; + in += 16; + len -= 16; + } +# endif + if (len) { + (*block) (ctx->Yi.c, ctx->EKi.c, key); + ++ctr; + if (is_endian.little) +# ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +# else + PUTU32(ctx->Yi.c + 12, ctr); +# endif + else + ctx->Yi.d[3] = ctr; +# if defined(GHASH) + while (len--) { + ctx->Xn[mres++] = out[n] = in[n] ^ ctx->EKi.c[n]; + ++n; + } +# else + while (len--) { + ctx->Xi.c[n] ^= out[n] = in[n] ^ ctx->EKi.c[n]; + ++n; + } + mres = n; +# endif + } + + ctx->mres = mres; + return 0; + } while (0); + } +#endif + for (i = 0; i < len; ++i) { + if (n == 0) { + (*block) (ctx->Yi.c, ctx->EKi.c, key); + ++ctr; + if (is_endian.little) +#ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +#else + PUTU32(ctx->Yi.c + 12, ctr); +#endif + else + ctx->Yi.d[3] = ctr; + } +#if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT) + ctx->Xn[mres++] = out[i] = in[i] ^ ctx->EKi.c[n]; + n = (n + 1) % 16; + if (mres == sizeof(ctx->Xn)) { + GHASH(ctx,ctx->Xn,sizeof(ctx->Xn)); + mres = 0; + } +#else + ctx->Xi.c[n] ^= out[i] = in[i] ^ ctx->EKi.c[n]; + mres = n = (n + 1) % 16; + if (n == 0) + GCM_MUL(ctx); +#endif + } + + ctx->mres = mres; + return 0; +} + +int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, + const unsigned char *in, unsigned char *out, + size_t len) +{ + const union { + long one; + char little; + } is_endian = { 1 }; + unsigned int n, ctr, mres; + size_t i; + u64 mlen = ctx->len.u[1]; + block128_f block = ctx->block; + void *key = ctx->key; +#ifdef GCM_FUNCREF_4BIT + void (*gcm_gmult_p) (u64 Xi[2], const u128 Htable[16]) = ctx->gmult; +# if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT) + void (*gcm_ghash_p) (u64 Xi[2], const u128 Htable[16], + const u8 *inp, size_t len) = ctx->ghash; +# endif +#endif + + mlen += len; + if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len)) + return -1; + ctx->len.u[1] = mlen; + + mres = ctx->mres; + + if (ctx->ares) { + /* First call to decrypt finalizes GHASH(AAD) */ +#if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT) + if (len == 0) { + GCM_MUL(ctx); + ctx->ares = 0; + return 0; + } + memcpy(ctx->Xn, ctx->Xi.c, sizeof(ctx->Xi)); + ctx->Xi.u[0] = 0; + ctx->Xi.u[1] = 0; + mres = sizeof(ctx->Xi); +#else + GCM_MUL(ctx); +#endif + ctx->ares = 0; + } + + if (is_endian.little) +#ifdef BSWAP4 + ctr = BSWAP4(ctx->Yi.d[3]); +#else + ctr = GETU32(ctx->Yi.c + 12); +#endif + else + ctr = ctx->Yi.d[3]; + + n = mres % 16; +#if !defined(OPENSSL_SMALL_FOOTPRINT) + if (16 % sizeof(size_t) == 0) { /* always true actually */ + do { + if (n) { +# if defined(GHASH) + while (n && len) { + *(out++) = (ctx->Xn[mres++] = *(in++)) ^ ctx->EKi.c[n]; + --len; + n = (n + 1) % 16; + } + if (n == 0) { + GHASH(ctx, ctx->Xn, mres); + mres = 0; + } else { + ctx->mres = mres; + return 0; + } +# else + while (n && len) { + u8 c = *(in++); + *(out++) = c ^ ctx->EKi.c[n]; + ctx->Xi.c[n] ^= c; + --len; + n = (n + 1) % 16; + } + if (n == 0) { + GCM_MUL(ctx); + mres = 0; + } else { + ctx->mres = n; + return 0; + } +# endif + } +# if defined(STRICT_ALIGNMENT) + if (((size_t)in | (size_t)out) % sizeof(size_t) != 0) + break; +# endif +# if defined(GHASH) + if (len >= 16 && mres) { + GHASH(ctx, ctx->Xn, mres); + mres = 0; + } +# if defined(GHASH_CHUNK) + while (len >= GHASH_CHUNK) { + size_t j = GHASH_CHUNK; + + GHASH(ctx, in, GHASH_CHUNK); + while (j) { + size_t *out_t = (size_t *)out; + const size_t *in_t = (const size_t *)in; + + (*block) (ctx->Yi.c, ctx->EKi.c, key); + ++ctr; + if (is_endian.little) +# ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +# else + PUTU32(ctx->Yi.c + 12, ctr); +# endif + else + ctx->Yi.d[3] = ctr; + for (i = 0; i < 16 / sizeof(size_t); ++i) + out_t[i] = in_t[i] ^ ctx->EKi.t[i]; + out += 16; + in += 16; + j -= 16; + } + len -= GHASH_CHUNK; + } +# endif + if ((i = (len & (size_t)-16))) { + GHASH(ctx, in, i); + while (len >= 16) { + size_t *out_t = (size_t *)out; + const size_t *in_t = (const size_t *)in; + + (*block) (ctx->Yi.c, ctx->EKi.c, key); + ++ctr; + if (is_endian.little) +# ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +# else + PUTU32(ctx->Yi.c + 12, ctr); +# endif + else + ctx->Yi.d[3] = ctr; + for (i = 0; i < 16 / sizeof(size_t); ++i) + out_t[i] = in_t[i] ^ ctx->EKi.t[i]; + out += 16; + in += 16; + len -= 16; + } + } +# else + while (len >= 16) { + size_t *out_t = (size_t *)out; + const size_t *in_t = (const size_t *)in; + + (*block) (ctx->Yi.c, ctx->EKi.c, key); + ++ctr; + if (is_endian.little) +# ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +# else + PUTU32(ctx->Yi.c + 12, ctr); +# endif + else + ctx->Yi.d[3] = ctr; + for (i = 0; i < 16 / sizeof(size_t); ++i) { + size_t c = in[i]; + out[i] = c ^ ctx->EKi.t[i]; + ctx->Xi.t[i] ^= c; + } + GCM_MUL(ctx); + out += 16; + in += 16; + len -= 16; + } +# endif + if (len) { + (*block) (ctx->Yi.c, ctx->EKi.c, key); + ++ctr; + if (is_endian.little) +# ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +# else + PUTU32(ctx->Yi.c + 12, ctr); +# endif + else + ctx->Yi.d[3] = ctr; +# if defined(GHASH) + while (len--) { + out[n] = (ctx->Xn[mres++] = in[n]) ^ ctx->EKi.c[n]; + ++n; + } +# else + while (len--) { + u8 c = in[n]; + ctx->Xi.c[n] ^= c; + out[n] = c ^ ctx->EKi.c[n]; + ++n; + } + mres = n; +# endif + } + + ctx->mres = mres; + return 0; + } while (0); + } +#endif + for (i = 0; i < len; ++i) { + u8 c; + if (n == 0) { + (*block) (ctx->Yi.c, ctx->EKi.c, key); + ++ctr; + if (is_endian.little) +#ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +#else + PUTU32(ctx->Yi.c + 12, ctr); +#endif + else + ctx->Yi.d[3] = ctr; + } +#if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT) + out[i] = (ctx->Xn[mres++] = c = in[i]) ^ ctx->EKi.c[n]; + n = (n + 1) % 16; + if (mres == sizeof(ctx->Xn)) { + GHASH(ctx,ctx->Xn,sizeof(ctx->Xn)); + mres = 0; + } +#else + c = in[i]; + out[i] = c ^ ctx->EKi.c[n]; + ctx->Xi.c[n] ^= c; + mres = n = (n + 1) % 16; + if (n == 0) + GCM_MUL(ctx); +#endif + } + + ctx->mres = mres; + return 0; +} + +int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, + const unsigned char *in, unsigned char *out, + size_t len, ctr128_f stream) +{ +#if defined(OPENSSL_SMALL_FOOTPRINT) + return CRYPTO_gcm128_encrypt(ctx, in, out, len); +#else + const union { + long one; + char little; + } is_endian = { 1 }; + unsigned int n, ctr, mres; + size_t i; + u64 mlen = ctx->len.u[1]; + void *key = ctx->key; +# ifdef GCM_FUNCREF_4BIT + void (*gcm_gmult_p) (u64 Xi[2], const u128 Htable[16]) = ctx->gmult; +# ifdef GHASH + void (*gcm_ghash_p) (u64 Xi[2], const u128 Htable[16], + const u8 *inp, size_t len) = ctx->ghash; +# endif +# endif + + mlen += len; + if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len)) + return -1; + ctx->len.u[1] = mlen; + + mres = ctx->mres; + + if (ctx->ares) { + /* First call to encrypt finalizes GHASH(AAD) */ +#if defined(GHASH) + if (len == 0) { + GCM_MUL(ctx); + ctx->ares = 0; + return 0; + } + memcpy(ctx->Xn, ctx->Xi.c, sizeof(ctx->Xi)); + ctx->Xi.u[0] = 0; + ctx->Xi.u[1] = 0; + mres = sizeof(ctx->Xi); +#else + GCM_MUL(ctx); +#endif + ctx->ares = 0; + } + + if (is_endian.little) +# ifdef BSWAP4 + ctr = BSWAP4(ctx->Yi.d[3]); +# else + ctr = GETU32(ctx->Yi.c + 12); +# endif + else + ctr = ctx->Yi.d[3]; + + n = mres % 16; + if (n) { +# if defined(GHASH) + while (n && len) { + ctx->Xn[mres++] = *(out++) = *(in++) ^ ctx->EKi.c[n]; + --len; + n = (n + 1) % 16; + } + if (n == 0) { + GHASH(ctx, ctx->Xn, mres); + mres = 0; + } else { + ctx->mres = mres; + return 0; + } +# else + while (n && len) { + ctx->Xi.c[n] ^= *(out++) = *(in++) ^ ctx->EKi.c[n]; + --len; + n = (n + 1) % 16; + } + if (n == 0) { + GCM_MUL(ctx); + mres = 0; + } else { + ctx->mres = n; + return 0; + } +# endif + } +# if defined(GHASH) + if (len >= 16 && mres) { + GHASH(ctx, ctx->Xn, mres); + mres = 0; + } +# if defined(GHASH_CHUNK) + while (len >= GHASH_CHUNK) { + (*stream) (in, out, GHASH_CHUNK / 16, key, ctx->Yi.c); + ctr += GHASH_CHUNK / 16; + if (is_endian.little) +# ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +# else + PUTU32(ctx->Yi.c + 12, ctr); +# endif + else + ctx->Yi.d[3] = ctr; + GHASH(ctx, out, GHASH_CHUNK); + out += GHASH_CHUNK; + in += GHASH_CHUNK; + len -= GHASH_CHUNK; + } +# endif +# endif + if ((i = (len & (size_t)-16))) { + size_t j = i / 16; + + (*stream) (in, out, j, key, ctx->Yi.c); + ctr += (unsigned int)j; + if (is_endian.little) +# ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +# else + PUTU32(ctx->Yi.c + 12, ctr); +# endif + else + ctx->Yi.d[3] = ctr; + in += i; + len -= i; +# if defined(GHASH) + GHASH(ctx, out, i); + out += i; +# else + while (j--) { + for (i = 0; i < 16; ++i) + ctx->Xi.c[i] ^= out[i]; + GCM_MUL(ctx); + out += 16; + } +# endif + } + if (len) { + (*ctx->block) (ctx->Yi.c, ctx->EKi.c, key); + ++ctr; + if (is_endian.little) +# ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +# else + PUTU32(ctx->Yi.c + 12, ctr); +# endif + else + ctx->Yi.d[3] = ctr; + while (len--) { +# if defined(GHASH) + ctx->Xn[mres++] = out[n] = in[n] ^ ctx->EKi.c[n]; +# else + ctx->Xi.c[mres++] ^= out[n] = in[n] ^ ctx->EKi.c[n]; +# endif + ++n; + } + } + + ctx->mres = mres; + return 0; +#endif +} + +int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, + const unsigned char *in, unsigned char *out, + size_t len, ctr128_f stream) +{ +#if defined(OPENSSL_SMALL_FOOTPRINT) + return CRYPTO_gcm128_decrypt(ctx, in, out, len); +#else + const union { + long one; + char little; + } is_endian = { 1 }; + unsigned int n, ctr, mres; + size_t i; + u64 mlen = ctx->len.u[1]; + void *key = ctx->key; +# ifdef GCM_FUNCREF_4BIT + void (*gcm_gmult_p) (u64 Xi[2], const u128 Htable[16]) = ctx->gmult; +# ifdef GHASH + void (*gcm_ghash_p) (u64 Xi[2], const u128 Htable[16], + const u8 *inp, size_t len) = ctx->ghash; +# endif +# endif + + mlen += len; + if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len)) + return -1; + ctx->len.u[1] = mlen; + + mres = ctx->mres; + + if (ctx->ares) { + /* First call to decrypt finalizes GHASH(AAD) */ +# if defined(GHASH) + if (len == 0) { + GCM_MUL(ctx); + ctx->ares = 0; + return 0; + } + memcpy(ctx->Xn, ctx->Xi.c, sizeof(ctx->Xi)); + ctx->Xi.u[0] = 0; + ctx->Xi.u[1] = 0; + mres = sizeof(ctx->Xi); +# else + GCM_MUL(ctx); +# endif + ctx->ares = 0; + } + + if (is_endian.little) +# ifdef BSWAP4 + ctr = BSWAP4(ctx->Yi.d[3]); +# else + ctr = GETU32(ctx->Yi.c + 12); +# endif + else + ctr = ctx->Yi.d[3]; + + n = mres % 16; + if (n) { +# if defined(GHASH) + while (n && len) { + *(out++) = (ctx->Xn[mres++] = *(in++)) ^ ctx->EKi.c[n]; + --len; + n = (n + 1) % 16; + } + if (n == 0) { + GHASH(ctx, ctx->Xn, mres); + mres = 0; + } else { + ctx->mres = mres; + return 0; + } +# else + while (n && len) { + u8 c = *(in++); + *(out++) = c ^ ctx->EKi.c[n]; + ctx->Xi.c[n] ^= c; + --len; + n = (n + 1) % 16; + } + if (n == 0) { + GCM_MUL(ctx); + mres = 0; + } else { + ctx->mres = n; + return 0; + } +# endif + } +# if defined(GHASH) + if (len >= 16 && mres) { + GHASH(ctx, ctx->Xn, mres); + mres = 0; + } +# if defined(GHASH_CHUNK) + while (len >= GHASH_CHUNK) { + GHASH(ctx, in, GHASH_CHUNK); + (*stream) (in, out, GHASH_CHUNK / 16, key, ctx->Yi.c); + ctr += GHASH_CHUNK / 16; + if (is_endian.little) +# ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +# else + PUTU32(ctx->Yi.c + 12, ctr); +# endif + else + ctx->Yi.d[3] = ctr; + out += GHASH_CHUNK; + in += GHASH_CHUNK; + len -= GHASH_CHUNK; + } +# endif +# endif + if ((i = (len & (size_t)-16))) { + size_t j = i / 16; + +# if defined(GHASH) + GHASH(ctx, in, i); +# else + while (j--) { + size_t k; + for (k = 0; k < 16; ++k) + ctx->Xi.c[k] ^= in[k]; + GCM_MUL(ctx); + in += 16; + } + j = i / 16; + in -= i; +# endif + (*stream) (in, out, j, key, ctx->Yi.c); + ctr += (unsigned int)j; + if (is_endian.little) +# ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +# else + PUTU32(ctx->Yi.c + 12, ctr); +# endif + else + ctx->Yi.d[3] = ctr; + out += i; + in += i; + len -= i; + } + if (len) { + (*ctx->block) (ctx->Yi.c, ctx->EKi.c, key); + ++ctr; + if (is_endian.little) +# ifdef BSWAP4 + ctx->Yi.d[3] = BSWAP4(ctr); +# else + PUTU32(ctx->Yi.c + 12, ctr); +# endif + else + ctx->Yi.d[3] = ctr; + while (len--) { +# if defined(GHASH) + out[n] = (ctx->Xn[mres++] = in[n]) ^ ctx->EKi.c[n]; +# else + u8 c = in[n]; + ctx->Xi.c[mres++] ^= c; + out[n] = c ^ ctx->EKi.c[n]; +# endif + ++n; + } + } + + ctx->mres = mres; + return 0; +#endif +} + +int CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx, const unsigned char *tag, + size_t len) +{ + const union { + long one; + char little; + } is_endian = { 1 }; + u64 alen = ctx->len.u[0] << 3; + u64 clen = ctx->len.u[1] << 3; +#ifdef GCM_FUNCREF_4BIT + void (*gcm_gmult_p) (u64 Xi[2], const u128 Htable[16]) = ctx->gmult; +# if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT) + void (*gcm_ghash_p) (u64 Xi[2], const u128 Htable[16], + const u8 *inp, size_t len) = ctx->ghash; +# endif +#endif + +#if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT) + u128 bitlen; + unsigned int mres = ctx->mres; + + if (mres) { + unsigned blocks = (mres + 15) & -16; + + memset(ctx->Xn + mres, 0, blocks - mres); + mres = blocks; + if (mres == sizeof(ctx->Xn)) { + GHASH(ctx, ctx->Xn, mres); + mres = 0; + } + } else if (ctx->ares) { + GCM_MUL(ctx); + } +#else + if (ctx->mres || ctx->ares) + GCM_MUL(ctx); +#endif + + if (is_endian.little) { +#ifdef BSWAP8 + alen = BSWAP8(alen); + clen = BSWAP8(clen); +#else + u8 *p = ctx->len.c; + + ctx->len.u[0] = alen; + ctx->len.u[1] = clen; + + alen = (u64)GETU32(p) << 32 | GETU32(p + 4); + clen = (u64)GETU32(p + 8) << 32 | GETU32(p + 12); +#endif + } + +#if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT) + bitlen.hi = alen; + bitlen.lo = clen; + memcpy(ctx->Xn + mres, &bitlen, sizeof(bitlen)); + mres += sizeof(bitlen); + GHASH(ctx, ctx->Xn, mres); +#else + ctx->Xi.u[0] ^= alen; + ctx->Xi.u[1] ^= clen; + GCM_MUL(ctx); +#endif + + ctx->Xi.u[0] ^= ctx->EK0.u[0]; + ctx->Xi.u[1] ^= ctx->EK0.u[1]; + + if (tag && len <= sizeof(ctx->Xi)) + return CRYPTO_memcmp(ctx->Xi.c, tag, len); + else + return -1; +} + +void CRYPTO_gcm128_tag(GCM128_CONTEXT *ctx, unsigned char *tag, size_t len) +{ + CRYPTO_gcm128_finish(ctx, NULL, 0); + memcpy(tag, ctx->Xi.c, + len <= sizeof(ctx->Xi.c) ? len : sizeof(ctx->Xi.c)); +} + +GCM128_CONTEXT *CRYPTO_gcm128_new(void *key, block128_f block) +{ + GCM128_CONTEXT *ret; + + if ((ret = OPENSSL_malloc(sizeof(*ret))) != NULL) + CRYPTO_gcm128_init(ret, key, block); + + return ret; +} + +void CRYPTO_gcm128_release(GCM128_CONTEXT *ctx) +{ + OPENSSL_clear_free(ctx, sizeof(*ctx)); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/modes/modes_lcl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/modes_lcl.h new file mode 100644 index 000000000..f2ae01d11 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/modes_lcl.h @@ -0,0 +1,190 @@ +/* + * Copyright 2010-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__) +typedef __int64 i64; +typedef unsigned __int64 u64; +# define U64(C) C##UI64 +#elif defined(__arch64__) +typedef long i64; +typedef unsigned long u64; +# define U64(C) C##UL +#else +typedef long long i64; +typedef unsigned long long u64; +# define U64(C) C##ULL +#endif + +typedef unsigned int u32; +typedef unsigned char u8; + +#define STRICT_ALIGNMENT 1 +#ifndef PEDANTIC +# if defined(__i386) || defined(__i386__) || \ + defined(__x86_64) || defined(__x86_64__) || \ + defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64) || \ + defined(__aarch64__) || \ + defined(__s390__) || defined(__s390x__) +# undef STRICT_ALIGNMENT +# endif +#endif + +#if !defined(PEDANTIC) && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) +# if defined(__GNUC__) && __GNUC__>=2 +# if defined(__x86_64) || defined(__x86_64__) +# define BSWAP8(x) ({ u64 ret_=(x); \ + asm ("bswapq %0" \ + : "+r"(ret_)); ret_; }) +# define BSWAP4(x) ({ u32 ret_=(x); \ + asm ("bswapl %0" \ + : "+r"(ret_)); ret_; }) +# elif (defined(__i386) || defined(__i386__)) && !defined(I386_ONLY) +# define BSWAP8(x) ({ u32 lo_=(u64)(x)>>32,hi_=(x); \ + asm ("bswapl %0; bswapl %1" \ + : "+r"(hi_),"+r"(lo_)); \ + (u64)hi_<<32|lo_; }) +# define BSWAP4(x) ({ u32 ret_=(x); \ + asm ("bswapl %0" \ + : "+r"(ret_)); ret_; }) +# elif defined(__aarch64__) +# define BSWAP8(x) ({ u64 ret_; \ + asm ("rev %0,%1" \ + : "=r"(ret_) : "r"(x)); ret_; }) +# define BSWAP4(x) ({ u32 ret_; \ + asm ("rev %w0,%w1" \ + : "=r"(ret_) : "r"(x)); ret_; }) +# elif (defined(__arm__) || defined(__arm)) && !defined(STRICT_ALIGNMENT) +# define BSWAP8(x) ({ u32 lo_=(u64)(x)>>32,hi_=(x); \ + asm ("rev %0,%0; rev %1,%1" \ + : "+r"(hi_),"+r"(lo_)); \ + (u64)hi_<<32|lo_; }) +# define BSWAP4(x) ({ u32 ret_; \ + asm ("rev %0,%1" \ + : "=r"(ret_) : "r"((u32)(x))); \ + ret_; }) +# endif +# elif defined(_MSC_VER) +# if _MSC_VER>=1300 +# include +# pragma intrinsic(_byteswap_uint64,_byteswap_ulong) +# define BSWAP8(x) _byteswap_uint64((u64)(x)) +# define BSWAP4(x) _byteswap_ulong((u32)(x)) +# elif defined(_M_IX86) +__inline u32 _bswap4(u32 val) +{ +_asm mov eax, val _asm bswap eax} +# define BSWAP4(x) _bswap4(x) +# endif +# endif +#endif +#if defined(BSWAP4) && !defined(STRICT_ALIGNMENT) +# define GETU32(p) BSWAP4(*(const u32 *)(p)) +# define PUTU32(p,v) *(u32 *)(p) = BSWAP4(v) +#else +# define GETU32(p) ((u32)(p)[0]<<24|(u32)(p)[1]<<16|(u32)(p)[2]<<8|(u32)(p)[3]) +# define PUTU32(p,v) ((p)[0]=(u8)((v)>>24),(p)[1]=(u8)((v)>>16),(p)[2]=(u8)((v)>>8),(p)[3]=(u8)(v)) +#endif +/*- GCM definitions */ typedef struct { + u64 hi, lo; +} u128; + +#ifdef TABLE_BITS +# undef TABLE_BITS +#endif +/* + * Even though permitted values for TABLE_BITS are 8, 4 and 1, it should + * never be set to 8 [or 1]. For further information see gcm128.c. + */ +#define TABLE_BITS 4 + +struct gcm128_context { + /* Following 6 names follow names in GCM specification */ + union { + u64 u[2]; + u32 d[4]; + u8 c[16]; + size_t t[16 / sizeof(size_t)]; + } Yi, EKi, EK0, len, Xi, H; + /* + * Relative position of Xi, H and pre-computed Htable is used in some + * assembler modules, i.e. don't change the order! + */ +#if TABLE_BITS==8 + u128 Htable[256]; +#else + u128 Htable[16]; + void (*gmult) (u64 Xi[2], const u128 Htable[16]); + void (*ghash) (u64 Xi[2], const u128 Htable[16], const u8 *inp, + size_t len); +#endif + unsigned int mres, ares; + block128_f block; + void *key; +#if !defined(OPENSSL_SMALL_FOOTPRINT) + unsigned char Xn[48]; +#endif +}; + +struct xts128_context { + void *key1, *key2; + block128_f block1, block2; +}; + +struct ccm128_context { + union { + u64 u[2]; + u8 c[16]; + } nonce, cmac; + u64 blocks; + block128_f block; + void *key; +}; + +#ifndef OPENSSL_NO_OCB + +typedef union { + u64 a[2]; + unsigned char c[16]; +} OCB_BLOCK; +# define ocb_block16_xor(in1,in2,out) \ + ( (out)->a[0]=(in1)->a[0]^(in2)->a[0], \ + (out)->a[1]=(in1)->a[1]^(in2)->a[1] ) +# if STRICT_ALIGNMENT +# define ocb_block16_xor_misaligned(in1,in2,out) \ + ocb_block_xor((in1)->c,(in2)->c,16,(out)->c) +# else +# define ocb_block16_xor_misaligned ocb_block16_xor +# endif + +struct ocb128_context { + /* Need both encrypt and decrypt key schedules for decryption */ + block128_f encrypt; + block128_f decrypt; + void *keyenc; + void *keydec; + ocb128_f stream; /* direction dependent */ + /* Key dependent variables. Can be reused if key remains the same */ + size_t l_index; + size_t max_l_index; + OCB_BLOCK l_star; + OCB_BLOCK l_dollar; + OCB_BLOCK *l; + /* Must be reset for each session */ + struct { + u64 blocks_hashed; + u64 blocks_processed; + OCB_BLOCK offset_aad; + OCB_BLOCK sum; + OCB_BLOCK offset; + OCB_BLOCK checksum; + } sess; +}; +#endif /* OPENSSL_NO_OCB */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/modes/ocb128.c b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/ocb128.c new file mode 100644 index 000000000..713b9aaf1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/ocb128.c @@ -0,0 +1,562 @@ +/* + * Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "modes_lcl.h" + +#ifndef OPENSSL_NO_OCB + +/* + * Calculate the number of binary trailing zero's in any given number + */ +static u32 ocb_ntz(u64 n) +{ + u32 cnt = 0; + + /* + * We do a right-to-left simple sequential search. This is surprisingly + * efficient as the distribution of trailing zeros is not uniform, + * e.g. the number of possible inputs with no trailing zeros is equal to + * the number with 1 or more; the number with exactly 1 is equal to the + * number with 2 or more, etc. Checking the last two bits covers 75% of + * all numbers. Checking the last three covers 87.5% + */ + while (!(n & 1)) { + n >>= 1; + cnt++; + } + return cnt; +} + +/* + * Shift a block of 16 bytes left by shift bits + */ +static void ocb_block_lshift(const unsigned char *in, size_t shift, + unsigned char *out) +{ + int i; + unsigned char carry = 0, carry_next; + + for (i = 15; i >= 0; i--) { + carry_next = in[i] >> (8 - shift); + out[i] = (in[i] << shift) | carry; + carry = carry_next; + } +} + +/* + * Perform a "double" operation as per OCB spec + */ +static void ocb_double(OCB_BLOCK *in, OCB_BLOCK *out) +{ + unsigned char mask; + + /* + * Calculate the mask based on the most significant bit. There are more + * efficient ways to do this - but this way is constant time + */ + mask = in->c[0] & 0x80; + mask >>= 7; + mask = (0 - mask) & 0x87; + + ocb_block_lshift(in->c, 1, out->c); + + out->c[15] ^= mask; +} + +/* + * Perform an xor on in1 and in2 - each of len bytes. Store result in out + */ +static void ocb_block_xor(const unsigned char *in1, + const unsigned char *in2, size_t len, + unsigned char *out) +{ + size_t i; + for (i = 0; i < len; i++) { + out[i] = in1[i] ^ in2[i]; + } +} + +/* + * Lookup L_index in our lookup table. If we haven't already got it we need to + * calculate it + */ +static OCB_BLOCK *ocb_lookup_l(OCB128_CONTEXT *ctx, size_t idx) +{ + size_t l_index = ctx->l_index; + + if (idx <= l_index) { + return ctx->l + idx; + } + + /* We don't have it - so calculate it */ + if (idx >= ctx->max_l_index) { + void *tmp_ptr; + /* + * Each additional entry allows to process almost double as + * much data, so that in linear world the table will need to + * be expanded with smaller and smaller increments. Originally + * it was doubling in size, which was a waste. Growing it + * linearly is not formally optimal, but is simpler to implement. + * We grow table by minimally required 4*n that would accommodate + * the index. + */ + ctx->max_l_index += (idx - ctx->max_l_index + 4) & ~3; + tmp_ptr = OPENSSL_realloc(ctx->l, ctx->max_l_index * sizeof(OCB_BLOCK)); + if (tmp_ptr == NULL) /* prevent ctx->l from being clobbered */ + return NULL; + ctx->l = tmp_ptr; + } + while (l_index < idx) { + ocb_double(ctx->l + l_index, ctx->l + l_index + 1); + l_index++; + } + ctx->l_index = l_index; + + return ctx->l + idx; +} + +/* + * Create a new OCB128_CONTEXT + */ +OCB128_CONTEXT *CRYPTO_ocb128_new(void *keyenc, void *keydec, + block128_f encrypt, block128_f decrypt, + ocb128_f stream) +{ + OCB128_CONTEXT *octx; + int ret; + + if ((octx = OPENSSL_malloc(sizeof(*octx))) != NULL) { + ret = CRYPTO_ocb128_init(octx, keyenc, keydec, encrypt, decrypt, + stream); + if (ret) + return octx; + OPENSSL_free(octx); + } + + return NULL; +} + +/* + * Initialise an existing OCB128_CONTEXT + */ +int CRYPTO_ocb128_init(OCB128_CONTEXT *ctx, void *keyenc, void *keydec, + block128_f encrypt, block128_f decrypt, + ocb128_f stream) +{ + memset(ctx, 0, sizeof(*ctx)); + ctx->l_index = 0; + ctx->max_l_index = 5; + if ((ctx->l = OPENSSL_malloc(ctx->max_l_index * 16)) == NULL) { + CRYPTOerr(CRYPTO_F_CRYPTO_OCB128_INIT, ERR_R_MALLOC_FAILURE); + return 0; + } + + /* + * We set both the encryption and decryption key schedules - decryption + * needs both. Don't really need decryption schedule if only doing + * encryption - but it simplifies things to take it anyway + */ + ctx->encrypt = encrypt; + ctx->decrypt = decrypt; + ctx->stream = stream; + ctx->keyenc = keyenc; + ctx->keydec = keydec; + + /* L_* = ENCIPHER(K, zeros(128)) */ + ctx->encrypt(ctx->l_star.c, ctx->l_star.c, ctx->keyenc); + + /* L_$ = double(L_*) */ + ocb_double(&ctx->l_star, &ctx->l_dollar); + + /* L_0 = double(L_$) */ + ocb_double(&ctx->l_dollar, ctx->l); + + /* L_{i} = double(L_{i-1}) */ + ocb_double(ctx->l, ctx->l+1); + ocb_double(ctx->l+1, ctx->l+2); + ocb_double(ctx->l+2, ctx->l+3); + ocb_double(ctx->l+3, ctx->l+4); + ctx->l_index = 4; /* enough to process up to 496 bytes */ + + return 1; +} + +/* + * Copy an OCB128_CONTEXT object + */ +int CRYPTO_ocb128_copy_ctx(OCB128_CONTEXT *dest, OCB128_CONTEXT *src, + void *keyenc, void *keydec) +{ + memcpy(dest, src, sizeof(OCB128_CONTEXT)); + if (keyenc) + dest->keyenc = keyenc; + if (keydec) + dest->keydec = keydec; + if (src->l) { + if ((dest->l = OPENSSL_malloc(src->max_l_index * 16)) == NULL) { + CRYPTOerr(CRYPTO_F_CRYPTO_OCB128_COPY_CTX, ERR_R_MALLOC_FAILURE); + return 0; + } + memcpy(dest->l, src->l, (src->l_index + 1) * 16); + } + return 1; +} + +/* + * Set the IV to be used for this operation. Must be 1 - 15 bytes. + */ +int CRYPTO_ocb128_setiv(OCB128_CONTEXT *ctx, const unsigned char *iv, + size_t len, size_t taglen) +{ + unsigned char ktop[16], tmp[16], mask; + unsigned char stretch[24], nonce[16]; + size_t bottom, shift; + + /* + * Spec says IV is 120 bits or fewer - it allows non byte aligned lengths. + * We don't support this at this stage + */ + if ((len > 15) || (len < 1) || (taglen > 16) || (taglen < 1)) { + return -1; + } + + /* Reset nonce-dependent variables */ + memset(&ctx->sess, 0, sizeof(ctx->sess)); + + /* Nonce = num2str(TAGLEN mod 128,7) || zeros(120-bitlen(N)) || 1 || N */ + nonce[0] = ((taglen * 8) % 128) << 1; + memset(nonce + 1, 0, 15); + memcpy(nonce + 16 - len, iv, len); + nonce[15 - len] |= 1; + + /* Ktop = ENCIPHER(K, Nonce[1..122] || zeros(6)) */ + memcpy(tmp, nonce, 16); + tmp[15] &= 0xc0; + ctx->encrypt(tmp, ktop, ctx->keyenc); + + /* Stretch = Ktop || (Ktop[1..64] xor Ktop[9..72]) */ + memcpy(stretch, ktop, 16); + ocb_block_xor(ktop, ktop + 1, 8, stretch + 16); + + /* bottom = str2num(Nonce[123..128]) */ + bottom = nonce[15] & 0x3f; + + /* Offset_0 = Stretch[1+bottom..128+bottom] */ + shift = bottom % 8; + ocb_block_lshift(stretch + (bottom / 8), shift, ctx->sess.offset.c); + mask = 0xff; + mask <<= 8 - shift; + ctx->sess.offset.c[15] |= + (*(stretch + (bottom / 8) + 16) & mask) >> (8 - shift); + + return 1; +} + +/* + * Provide any AAD. This can be called multiple times. Only the final time can + * have a partial block + */ +int CRYPTO_ocb128_aad(OCB128_CONTEXT *ctx, const unsigned char *aad, + size_t len) +{ + u64 i, all_num_blocks; + size_t num_blocks, last_len; + OCB_BLOCK tmp; + + /* Calculate the number of blocks of AAD provided now, and so far */ + num_blocks = len / 16; + all_num_blocks = num_blocks + ctx->sess.blocks_hashed; + + /* Loop through all full blocks of AAD */ + for (i = ctx->sess.blocks_hashed + 1; i <= all_num_blocks; i++) { + OCB_BLOCK *lookup; + + /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ + lookup = ocb_lookup_l(ctx, ocb_ntz(i)); + if (lookup == NULL) + return 0; + ocb_block16_xor(&ctx->sess.offset_aad, lookup, &ctx->sess.offset_aad); + + memcpy(tmp.c, aad, 16); + aad += 16; + + /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i) */ + ocb_block16_xor(&ctx->sess.offset_aad, &tmp, &tmp); + ctx->encrypt(tmp.c, tmp.c, ctx->keyenc); + ocb_block16_xor(&tmp, &ctx->sess.sum, &ctx->sess.sum); + } + + /* + * Check if we have any partial blocks left over. This is only valid in the + * last call to this function + */ + last_len = len % 16; + + if (last_len > 0) { + /* Offset_* = Offset_m xor L_* */ + ocb_block16_xor(&ctx->sess.offset_aad, &ctx->l_star, + &ctx->sess.offset_aad); + + /* CipherInput = (A_* || 1 || zeros(127-bitlen(A_*))) xor Offset_* */ + memset(tmp.c, 0, 16); + memcpy(tmp.c, aad, last_len); + tmp.c[last_len] = 0x80; + ocb_block16_xor(&ctx->sess.offset_aad, &tmp, &tmp); + + /* Sum = Sum_m xor ENCIPHER(K, CipherInput) */ + ctx->encrypt(tmp.c, tmp.c, ctx->keyenc); + ocb_block16_xor(&tmp, &ctx->sess.sum, &ctx->sess.sum); + } + + ctx->sess.blocks_hashed = all_num_blocks; + + return 1; +} + +/* + * Provide any data to be encrypted. This can be called multiple times. Only + * the final time can have a partial block + */ +int CRYPTO_ocb128_encrypt(OCB128_CONTEXT *ctx, + const unsigned char *in, unsigned char *out, + size_t len) +{ + u64 i, all_num_blocks; + size_t num_blocks, last_len; + + /* + * Calculate the number of blocks of data to be encrypted provided now, and + * so far + */ + num_blocks = len / 16; + all_num_blocks = num_blocks + ctx->sess.blocks_processed; + + if (num_blocks && all_num_blocks == (size_t)all_num_blocks + && ctx->stream != NULL) { + size_t max_idx = 0, top = (size_t)all_num_blocks; + + /* + * See how many L_{i} entries we need to process data at hand + * and pre-compute missing entries in the table [if any]... + */ + while (top >>= 1) + max_idx++; + if (ocb_lookup_l(ctx, max_idx) == NULL) + return 0; + + ctx->stream(in, out, num_blocks, ctx->keyenc, + (size_t)ctx->sess.blocks_processed + 1, ctx->sess.offset.c, + (const unsigned char (*)[16])ctx->l, ctx->sess.checksum.c); + } else { + /* Loop through all full blocks to be encrypted */ + for (i = ctx->sess.blocks_processed + 1; i <= all_num_blocks; i++) { + OCB_BLOCK *lookup; + OCB_BLOCK tmp; + + /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ + lookup = ocb_lookup_l(ctx, ocb_ntz(i)); + if (lookup == NULL) + return 0; + ocb_block16_xor(&ctx->sess.offset, lookup, &ctx->sess.offset); + + memcpy(tmp.c, in, 16); + in += 16; + + /* Checksum_i = Checksum_{i-1} xor P_i */ + ocb_block16_xor(&tmp, &ctx->sess.checksum, &ctx->sess.checksum); + + /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */ + ocb_block16_xor(&ctx->sess.offset, &tmp, &tmp); + ctx->encrypt(tmp.c, tmp.c, ctx->keyenc); + ocb_block16_xor(&ctx->sess.offset, &tmp, &tmp); + + memcpy(out, tmp.c, 16); + out += 16; + } + } + + /* + * Check if we have any partial blocks left over. This is only valid in the + * last call to this function + */ + last_len = len % 16; + + if (last_len > 0) { + OCB_BLOCK pad; + + /* Offset_* = Offset_m xor L_* */ + ocb_block16_xor(&ctx->sess.offset, &ctx->l_star, &ctx->sess.offset); + + /* Pad = ENCIPHER(K, Offset_*) */ + ctx->encrypt(ctx->sess.offset.c, pad.c, ctx->keyenc); + + /* C_* = P_* xor Pad[1..bitlen(P_*)] */ + ocb_block_xor(in, pad.c, last_len, out); + + /* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*))) */ + memset(pad.c, 0, 16); /* borrow pad */ + memcpy(pad.c, in, last_len); + pad.c[last_len] = 0x80; + ocb_block16_xor(&pad, &ctx->sess.checksum, &ctx->sess.checksum); + } + + ctx->sess.blocks_processed = all_num_blocks; + + return 1; +} + +/* + * Provide any data to be decrypted. This can be called multiple times. Only + * the final time can have a partial block + */ +int CRYPTO_ocb128_decrypt(OCB128_CONTEXT *ctx, + const unsigned char *in, unsigned char *out, + size_t len) +{ + u64 i, all_num_blocks; + size_t num_blocks, last_len; + + /* + * Calculate the number of blocks of data to be decrypted provided now, and + * so far + */ + num_blocks = len / 16; + all_num_blocks = num_blocks + ctx->sess.blocks_processed; + + if (num_blocks && all_num_blocks == (size_t)all_num_blocks + && ctx->stream != NULL) { + size_t max_idx = 0, top = (size_t)all_num_blocks; + + /* + * See how many L_{i} entries we need to process data at hand + * and pre-compute missing entries in the table [if any]... + */ + while (top >>= 1) + max_idx++; + if (ocb_lookup_l(ctx, max_idx) == NULL) + return 0; + + ctx->stream(in, out, num_blocks, ctx->keydec, + (size_t)ctx->sess.blocks_processed + 1, ctx->sess.offset.c, + (const unsigned char (*)[16])ctx->l, ctx->sess.checksum.c); + } else { + OCB_BLOCK tmp; + + /* Loop through all full blocks to be decrypted */ + for (i = ctx->sess.blocks_processed + 1; i <= all_num_blocks; i++) { + + /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ + OCB_BLOCK *lookup = ocb_lookup_l(ctx, ocb_ntz(i)); + if (lookup == NULL) + return 0; + ocb_block16_xor(&ctx->sess.offset, lookup, &ctx->sess.offset); + + memcpy(tmp.c, in, 16); + in += 16; + + /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i) */ + ocb_block16_xor(&ctx->sess.offset, &tmp, &tmp); + ctx->decrypt(tmp.c, tmp.c, ctx->keydec); + ocb_block16_xor(&ctx->sess.offset, &tmp, &tmp); + + /* Checksum_i = Checksum_{i-1} xor P_i */ + ocb_block16_xor(&tmp, &ctx->sess.checksum, &ctx->sess.checksum); + + memcpy(out, tmp.c, 16); + out += 16; + } + } + + /* + * Check if we have any partial blocks left over. This is only valid in the + * last call to this function + */ + last_len = len % 16; + + if (last_len > 0) { + OCB_BLOCK pad; + + /* Offset_* = Offset_m xor L_* */ + ocb_block16_xor(&ctx->sess.offset, &ctx->l_star, &ctx->sess.offset); + + /* Pad = ENCIPHER(K, Offset_*) */ + ctx->encrypt(ctx->sess.offset.c, pad.c, ctx->keyenc); + + /* P_* = C_* xor Pad[1..bitlen(C_*)] */ + ocb_block_xor(in, pad.c, last_len, out); + + /* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*))) */ + memset(pad.c, 0, 16); /* borrow pad */ + memcpy(pad.c, out, last_len); + pad.c[last_len] = 0x80; + ocb_block16_xor(&pad, &ctx->sess.checksum, &ctx->sess.checksum); + } + + ctx->sess.blocks_processed = all_num_blocks; + + return 1; +} + +static int ocb_finish(OCB128_CONTEXT *ctx, unsigned char *tag, size_t len, + int write) +{ + OCB_BLOCK tmp; + + if (len > 16 || len < 1) { + return -1; + } + + /* + * Tag = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) xor HASH(K,A) + */ + ocb_block16_xor(&ctx->sess.checksum, &ctx->sess.offset, &tmp); + ocb_block16_xor(&ctx->l_dollar, &tmp, &tmp); + ctx->encrypt(tmp.c, tmp.c, ctx->keyenc); + ocb_block16_xor(&tmp, &ctx->sess.sum, &tmp); + + if (write) { + memcpy(tag, &tmp, len); + return 1; + } else { + return CRYPTO_memcmp(&tmp, tag, len); + } +} + +/* + * Calculate the tag and verify it against the supplied tag + */ +int CRYPTO_ocb128_finish(OCB128_CONTEXT *ctx, const unsigned char *tag, + size_t len) +{ + return ocb_finish(ctx, (unsigned char*)tag, len, 0); +} + +/* + * Retrieve the calculated tag + */ +int CRYPTO_ocb128_tag(OCB128_CONTEXT *ctx, unsigned char *tag, size_t len) +{ + return ocb_finish(ctx, tag, len, 1); +} + +/* + * Release all resources + */ +void CRYPTO_ocb128_cleanup(OCB128_CONTEXT *ctx) +{ + if (ctx) { + OPENSSL_clear_free(ctx->l, ctx->max_l_index * 16); + OPENSSL_cleanse(ctx, sizeof(*ctx)); + } +} + +#endif /* OPENSSL_NO_OCB */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/modes/ofb128.c b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/ofb128.c new file mode 100644 index 000000000..83092564c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/ofb128.c @@ -0,0 +1,74 @@ +/* + * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "modes_lcl.h" +#include + +/* + * The input and output encrypted as though 128bit ofb mode is being used. + * The extra state information to record how much of the 128bit block we have + * used is contained in *num; + */ +void CRYPTO_ofb128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], int *num, block128_f block) +{ + unsigned int n; + size_t l = 0; + + n = *num; + +#if !defined(OPENSSL_SMALL_FOOTPRINT) + if (16 % sizeof(size_t) == 0) { /* always true actually */ + do { + while (n && len) { + *(out++) = *(in++) ^ ivec[n]; + --len; + n = (n + 1) % 16; + } +# if defined(STRICT_ALIGNMENT) + if (((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != + 0) + break; +# endif + while (len >= 16) { + (*block) (ivec, ivec, key); + for (; n < 16; n += sizeof(size_t)) + *(size_t *)(out + n) = + *(size_t *)(in + n) ^ *(size_t *)(ivec + n); + len -= 16; + out += 16; + in += 16; + n = 0; + } + if (len) { + (*block) (ivec, ivec, key); + while (len--) { + out[n] = in[n] ^ ivec[n]; + ++n; + } + } + *num = n; + return; + } while (0); + } + /* the rest would be commonly eliminated by x86* compiler */ +#endif + while (l < len) { + if (n == 0) { + (*block) (ivec, ivec, key); + } + out[l] = in[l] ^ ivec[n]; + ++l; + n = (n + 1) % 16; + } + + *num = n; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/modes/wrap128.c b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/wrap128.c new file mode 100644 index 000000000..d7e56cc26 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/wrap128.c @@ -0,0 +1,331 @@ +/* + * Copyright 2013-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/** Beware! + * + * Following wrapping modes were designed for AES but this implementation + * allows you to use them for any 128 bit block cipher. + */ + +#include "internal/cryptlib.h" +#include + +/** RFC 3394 section 2.2.3.1 Default Initial Value */ +static const unsigned char default_iv[] = { + 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, +}; + +/** RFC 5649 section 3 Alternative Initial Value 32-bit constant */ +static const unsigned char default_aiv[] = { + 0xA6, 0x59, 0x59, 0xA6 +}; + +/** Input size limit: lower than maximum of standards but far larger than + * anything that will be used in practice. + */ +#define CRYPTO128_WRAP_MAX (1UL << 31) + +/** Wrapping according to RFC 3394 section 2.2.1. + * + * @param[in] key Key value. + * @param[in] iv IV value. Length = 8 bytes. NULL = use default_iv. + * @param[in] in Plaintext as n 64-bit blocks, n >= 2. + * @param[in] inlen Length of in. + * @param[out] out Ciphertext. Minimal buffer length = (inlen + 8) bytes. + * Input and output buffers can overlap if block function + * supports that. + * @param[in] block Block processing function. + * @return 0 if inlen does not consist of n 64-bit blocks, n >= 2. + * or if inlen > CRYPTO128_WRAP_MAX. + * Output length if wrapping succeeded. + */ +size_t CRYPTO_128_wrap(void *key, const unsigned char *iv, + unsigned char *out, + const unsigned char *in, size_t inlen, + block128_f block) +{ + unsigned char *A, B[16], *R; + size_t i, j, t; + if ((inlen & 0x7) || (inlen < 16) || (inlen > CRYPTO128_WRAP_MAX)) + return 0; + A = B; + t = 1; + memmove(out + 8, in, inlen); + if (!iv) + iv = default_iv; + + memcpy(A, iv, 8); + + for (j = 0; j < 6; j++) { + R = out + 8; + for (i = 0; i < inlen; i += 8, t++, R += 8) { + memcpy(B + 8, R, 8); + block(B, B, key); + A[7] ^= (unsigned char)(t & 0xff); + if (t > 0xff) { + A[6] ^= (unsigned char)((t >> 8) & 0xff); + A[5] ^= (unsigned char)((t >> 16) & 0xff); + A[4] ^= (unsigned char)((t >> 24) & 0xff); + } + memcpy(R, B + 8, 8); + } + } + memcpy(out, A, 8); + return inlen + 8; +} + +/** Unwrapping according to RFC 3394 section 2.2.2 steps 1-2. + * The IV check (step 3) is responsibility of the caller. + * + * @param[in] key Key value. + * @param[out] iv Unchecked IV value. Minimal buffer length = 8 bytes. + * @param[out] out Plaintext without IV. + * Minimal buffer length = (inlen - 8) bytes. + * Input and output buffers can overlap if block function + * supports that. + * @param[in] in Ciphertext as n 64-bit blocks. + * @param[in] inlen Length of in. + * @param[in] block Block processing function. + * @return 0 if inlen is out of range [24, CRYPTO128_WRAP_MAX] + * or if inlen is not a multiple of 8. + * Output length otherwise. + */ +static size_t crypto_128_unwrap_raw(void *key, unsigned char *iv, + unsigned char *out, + const unsigned char *in, size_t inlen, + block128_f block) +{ + unsigned char *A, B[16], *R; + size_t i, j, t; + inlen -= 8; + if ((inlen & 0x7) || (inlen < 16) || (inlen > CRYPTO128_WRAP_MAX)) + return 0; + A = B; + t = 6 * (inlen >> 3); + memcpy(A, in, 8); + memmove(out, in + 8, inlen); + for (j = 0; j < 6; j++) { + R = out + inlen - 8; + for (i = 0; i < inlen; i += 8, t--, R -= 8) { + A[7] ^= (unsigned char)(t & 0xff); + if (t > 0xff) { + A[6] ^= (unsigned char)((t >> 8) & 0xff); + A[5] ^= (unsigned char)((t >> 16) & 0xff); + A[4] ^= (unsigned char)((t >> 24) & 0xff); + } + memcpy(B + 8, R, 8); + block(B, B, key); + memcpy(R, B + 8, 8); + } + } + memcpy(iv, A, 8); + return inlen; +} + +/** Unwrapping according to RFC 3394 section 2.2.2, including the IV check. + * The first block of plaintext has to match the supplied IV, otherwise an + * error is returned. + * + * @param[in] key Key value. + * @param[out] iv IV value to match against. Length = 8 bytes. + * NULL = use default_iv. + * @param[out] out Plaintext without IV. + * Minimal buffer length = (inlen - 8) bytes. + * Input and output buffers can overlap if block function + * supports that. + * @param[in] in Ciphertext as n 64-bit blocks. + * @param[in] inlen Length of in. + * @param[in] block Block processing function. + * @return 0 if inlen is out of range [24, CRYPTO128_WRAP_MAX] + * or if inlen is not a multiple of 8 + * or if IV doesn't match expected value. + * Output length otherwise. + */ +size_t CRYPTO_128_unwrap(void *key, const unsigned char *iv, + unsigned char *out, const unsigned char *in, + size_t inlen, block128_f block) +{ + size_t ret; + unsigned char got_iv[8]; + + ret = crypto_128_unwrap_raw(key, got_iv, out, in, inlen, block); + if (ret == 0) + return 0; + + if (!iv) + iv = default_iv; + if (CRYPTO_memcmp(got_iv, iv, 8)) { + OPENSSL_cleanse(out, ret); + return 0; + } + return ret; +} + +/** Wrapping according to RFC 5649 section 4.1. + * + * @param[in] key Key value. + * @param[in] icv (Non-standard) IV, 4 bytes. NULL = use default_aiv. + * @param[out] out Ciphertext. Minimal buffer length = (inlen + 15) bytes. + * Input and output buffers can overlap if block function + * supports that. + * @param[in] in Plaintext as n 64-bit blocks, n >= 2. + * @param[in] inlen Length of in. + * @param[in] block Block processing function. + * @return 0 if inlen is out of range [1, CRYPTO128_WRAP_MAX]. + * Output length if wrapping succeeded. + */ +size_t CRYPTO_128_wrap_pad(void *key, const unsigned char *icv, + unsigned char *out, + const unsigned char *in, size_t inlen, + block128_f block) +{ + /* n: number of 64-bit blocks in the padded key data + * + * If length of plain text is not a multiple of 8, pad the plain text octet + * string on the right with octets of zeros, where final length is the + * smallest multiple of 8 that is greater than length of plain text. + * If length of plain text is a multiple of 8, then there is no padding. */ + const size_t blocks_padded = (inlen + 7) / 8; /* CEILING(m/8) */ + const size_t padded_len = blocks_padded * 8; + const size_t padding_len = padded_len - inlen; + /* RFC 5649 section 3: Alternative Initial Value */ + unsigned char aiv[8]; + int ret; + + /* Section 1: use 32-bit fixed field for plaintext octet length */ + if (inlen == 0 || inlen >= CRYPTO128_WRAP_MAX) + return 0; + + /* Section 3: Alternative Initial Value */ + if (!icv) + memcpy(aiv, default_aiv, 4); + else + memcpy(aiv, icv, 4); /* Standard doesn't mention this. */ + + aiv[4] = (inlen >> 24) & 0xFF; + aiv[5] = (inlen >> 16) & 0xFF; + aiv[6] = (inlen >> 8) & 0xFF; + aiv[7] = inlen & 0xFF; + + if (padded_len == 8) { + /* + * Section 4.1 - special case in step 2: If the padded plaintext + * contains exactly eight octets, then prepend the AIV and encrypt + * the resulting 128-bit block using AES in ECB mode. + */ + memmove(out + 8, in, inlen); + memcpy(out, aiv, 8); + memset(out + 8 + inlen, 0, padding_len); + block(out, out, key); + ret = 16; /* AIV + padded input */ + } else { + memmove(out, in, inlen); + memset(out + inlen, 0, padding_len); /* Section 4.1 step 1 */ + ret = CRYPTO_128_wrap(key, aiv, out, out, padded_len, block); + } + + return ret; +} + +/** Unwrapping according to RFC 5649 section 4.2. + * + * @param[in] key Key value. + * @param[in] icv (Non-standard) IV, 4 bytes. NULL = use default_aiv. + * @param[out] out Plaintext. Minimal buffer length = (inlen - 8) bytes. + * Input and output buffers can overlap if block function + * supports that. + * @param[in] in Ciphertext as n 64-bit blocks. + * @param[in] inlen Length of in. + * @param[in] block Block processing function. + * @return 0 if inlen is out of range [16, CRYPTO128_WRAP_MAX], + * or if inlen is not a multiple of 8 + * or if IV and message length indicator doesn't match. + * Output length if unwrapping succeeded and IV matches. + */ +size_t CRYPTO_128_unwrap_pad(void *key, const unsigned char *icv, + unsigned char *out, + const unsigned char *in, size_t inlen, + block128_f block) +{ + /* n: number of 64-bit blocks in the padded key data */ + size_t n = inlen / 8 - 1; + size_t padded_len; + size_t padding_len; + size_t ptext_len; + /* RFC 5649 section 3: Alternative Initial Value */ + unsigned char aiv[8]; + static unsigned char zeros[8] = { 0x0 }; + size_t ret; + + /* Section 4.2: Ciphertext length has to be (n+1) 64-bit blocks. */ + if ((inlen & 0x7) != 0 || inlen < 16 || inlen >= CRYPTO128_WRAP_MAX) + return 0; + + if (inlen == 16) { + /* + * Section 4.2 - special case in step 1: When n=1, the ciphertext + * contains exactly two 64-bit blocks and they are decrypted as a + * single AES block using AES in ECB mode: AIV | P[1] = DEC(K, C[0] | + * C[1]) + */ + unsigned char buff[16]; + + block(in, buff, key); + memcpy(aiv, buff, 8); + /* Remove AIV */ + memcpy(out, buff + 8, 8); + padded_len = 8; + OPENSSL_cleanse(buff, inlen); + } else { + padded_len = inlen - 8; + ret = crypto_128_unwrap_raw(key, aiv, out, in, inlen, block); + if (padded_len != ret) { + OPENSSL_cleanse(out, inlen); + return 0; + } + } + + /* + * Section 3: AIV checks: Check that MSB(32,A) = A65959A6. Optionally a + * user-supplied value can be used (even if standard doesn't mention + * this). + */ + if ((!icv && CRYPTO_memcmp(aiv, default_aiv, 4)) + || (icv && CRYPTO_memcmp(aiv, icv, 4))) { + OPENSSL_cleanse(out, inlen); + return 0; + } + + /* + * Check that 8*(n-1) < LSB(32,AIV) <= 8*n. If so, let ptext_len = + * LSB(32,AIV). + */ + + ptext_len = ((unsigned int)aiv[4] << 24) + | ((unsigned int)aiv[5] << 16) + | ((unsigned int)aiv[6] << 8) + | (unsigned int)aiv[7]; + if (8 * (n - 1) >= ptext_len || ptext_len > 8 * n) { + OPENSSL_cleanse(out, inlen); + return 0; + } + + /* + * Check that the rightmost padding_len octets of the output data are + * zero. + */ + padding_len = padded_len - ptext_len; + if (CRYPTO_memcmp(out + ptext_len, zeros, padding_len) != 0) { + OPENSSL_cleanse(out, inlen); + return 0; + } + + /* Section 4.2 step 3: Remove padding */ + return ptext_len; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/modes/xts128.c b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/xts128.c new file mode 100644 index 000000000..81b1eacd5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/modes/xts128.c @@ -0,0 +1,157 @@ +/* + * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "modes_lcl.h" +#include + +int CRYPTO_xts128_encrypt(const XTS128_CONTEXT *ctx, + const unsigned char iv[16], + const unsigned char *inp, unsigned char *out, + size_t len, int enc) +{ + const union { + long one; + char little; + } is_endian = { + 1 + }; + union { + u64 u[2]; + u32 d[4]; + u8 c[16]; + } tweak, scratch; + unsigned int i; + + if (len < 16) + return -1; + + memcpy(tweak.c, iv, 16); + + (*ctx->block2) (tweak.c, tweak.c, ctx->key2); + + if (!enc && (len % 16)) + len -= 16; + + while (len >= 16) { +#if defined(STRICT_ALIGNMENT) + memcpy(scratch.c, inp, 16); + scratch.u[0] ^= tweak.u[0]; + scratch.u[1] ^= tweak.u[1]; +#else + scratch.u[0] = ((u64 *)inp)[0] ^ tweak.u[0]; + scratch.u[1] = ((u64 *)inp)[1] ^ tweak.u[1]; +#endif + (*ctx->block1) (scratch.c, scratch.c, ctx->key1); +#if defined(STRICT_ALIGNMENT) + scratch.u[0] ^= tweak.u[0]; + scratch.u[1] ^= tweak.u[1]; + memcpy(out, scratch.c, 16); +#else + ((u64 *)out)[0] = scratch.u[0] ^= tweak.u[0]; + ((u64 *)out)[1] = scratch.u[1] ^= tweak.u[1]; +#endif + inp += 16; + out += 16; + len -= 16; + + if (len == 0) + return 0; + + if (is_endian.little) { + unsigned int carry, res; + + res = 0x87 & (((int)tweak.d[3]) >> 31); + carry = (unsigned int)(tweak.u[0] >> 63); + tweak.u[0] = (tweak.u[0] << 1) ^ res; + tweak.u[1] = (tweak.u[1] << 1) | carry; + } else { + size_t c; + + for (c = 0, i = 0; i < 16; ++i) { + /* + * + substitutes for |, because c is 1 bit + */ + c += ((size_t)tweak.c[i]) << 1; + tweak.c[i] = (u8)c; + c = c >> 8; + } + tweak.c[0] ^= (u8)(0x87 & (0 - c)); + } + } + if (enc) { + for (i = 0; i < len; ++i) { + u8 c = inp[i]; + out[i] = scratch.c[i]; + scratch.c[i] = c; + } + scratch.u[0] ^= tweak.u[0]; + scratch.u[1] ^= tweak.u[1]; + (*ctx->block1) (scratch.c, scratch.c, ctx->key1); + scratch.u[0] ^= tweak.u[0]; + scratch.u[1] ^= tweak.u[1]; + memcpy(out - 16, scratch.c, 16); + } else { + union { + u64 u[2]; + u8 c[16]; + } tweak1; + + if (is_endian.little) { + unsigned int carry, res; + + res = 0x87 & (((int)tweak.d[3]) >> 31); + carry = (unsigned int)(tweak.u[0] >> 63); + tweak1.u[0] = (tweak.u[0] << 1) ^ res; + tweak1.u[1] = (tweak.u[1] << 1) | carry; + } else { + size_t c; + + for (c = 0, i = 0; i < 16; ++i) { + /* + * + substitutes for |, because c is 1 bit + */ + c += ((size_t)tweak.c[i]) << 1; + tweak1.c[i] = (u8)c; + c = c >> 8; + } + tweak1.c[0] ^= (u8)(0x87 & (0 - c)); + } +#if defined(STRICT_ALIGNMENT) + memcpy(scratch.c, inp, 16); + scratch.u[0] ^= tweak1.u[0]; + scratch.u[1] ^= tweak1.u[1]; +#else + scratch.u[0] = ((u64 *)inp)[0] ^ tweak1.u[0]; + scratch.u[1] = ((u64 *)inp)[1] ^ tweak1.u[1]; +#endif + (*ctx->block1) (scratch.c, scratch.c, ctx->key1); + scratch.u[0] ^= tweak1.u[0]; + scratch.u[1] ^= tweak1.u[1]; + + for (i = 0; i < len; ++i) { + u8 c = inp[16 + i]; + out[16 + i] = scratch.c[i]; + scratch.c[i] = c; + } + scratch.u[0] ^= tweak.u[0]; + scratch.u[1] ^= tweak.u[1]; + (*ctx->block1) (scratch.c, scratch.c, ctx->key1); +#if defined(STRICT_ALIGNMENT) + scratch.u[0] ^= tweak.u[0]; + scratch.u[1] ^= tweak.u[1]; + memcpy(out, scratch.c, 16); +#else + ((u64 *)out)[0] = scratch.u[0] ^ tweak.u[0]; + ((u64 *)out)[1] = scratch.u[1] ^ tweak.u[1]; +#endif + } + + return 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/o_dir.c b/trunk/3rdparty/openssl-1.1-fit/crypto/o_dir.c new file mode 100644 index 000000000..fca9c75e0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/o_dir.c @@ -0,0 +1,37 @@ +/* + * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "e_os.h" +#include + +/* + * The routines really come from the Levitte Programming, so to make life + * simple, let's just use the raw files and hack the symbols to fit our + * namespace. + */ +#define LP_DIR_CTX OPENSSL_DIR_CTX +#define LP_dir_context_st OPENSSL_dir_context_st +#define LP_find_file OPENSSL_DIR_read +#define LP_find_file_end OPENSSL_DIR_end + +#include "internal/o_dir.h" + +#define LPDIR_H +#if defined OPENSSL_SYS_UNIX || defined DJGPP \ + || (defined __VMS_VER && __VMS_VER >= 70000000) +# include "LPdir_unix.c" +#elif defined OPENSSL_SYS_VMS +# include "LPdir_vms.c" +#elif defined OPENSSL_SYS_WIN32 +# include "LPdir_win32.c" +#elif defined OPENSSL_SYS_WINCE +# include "LPdir_wince.c" +#else +# include "LPdir_nyi.c" +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/o_fips.c b/trunk/3rdparty/openssl-1.1-fit/crypto/o_fips.c new file mode 100644 index 000000000..050ea9c21 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/o_fips.c @@ -0,0 +1,24 @@ +/* + * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" + +int FIPS_mode(void) +{ + /* This version of the library does not support FIPS mode. */ + return 0; +} + +int FIPS_mode_set(int r) +{ + if (r == 0) + return 1; + CRYPTOerr(CRYPTO_F_FIPS_MODE_SET, CRYPTO_R_FIPS_MODE_NOT_SUPPORTED); + return 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/o_fopen.c b/trunk/3rdparty/openssl-1.1-fit/crypto/o_fopen.c new file mode 100644 index 000000000..7d51ad725 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/o_fopen.c @@ -0,0 +1,126 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +# if defined(__linux) || defined(__sun) || defined(__hpux) +/* + * Following definition aliases fopen to fopen64 on above mentioned + * platforms. This makes it possible to open and sequentially access files + * larger than 2GB from 32-bit application. It does not allow to traverse + * them beyond 2GB with fseek/ftell, but on the other hand *no* 32-bit + * platform permits that, not with fseek/ftell. Not to mention that breaking + * 2GB limit for seeking would require surgery to *our* API. But sequential + * access suffices for practical cases when you can run into large files, + * such as fingerprinting, so we can let API alone. For reference, the list + * of 32-bit platforms which allow for sequential access of large files + * without extra "magic" comprise *BSD, Darwin, IRIX... + */ +# ifndef _FILE_OFFSET_BITS +# define _FILE_OFFSET_BITS 64 +# endif +# endif + +#include "e_os.h" +#include "internal/cryptlib.h" + +#if !defined(OPENSSL_NO_STDIO) + +# include +# ifdef __DJGPP__ +# include +# endif + +FILE *openssl_fopen(const char *filename, const char *mode) +{ + FILE *file = NULL; +# if defined(_WIN32) && defined(CP_UTF8) + int sz, len_0 = (int)strlen(filename) + 1; + DWORD flags; + + /* + * Basically there are three cases to cover: a) filename is + * pure ASCII string; b) actual UTF-8 encoded string and + * c) locale-ized string, i.e. one containing 8-bit + * characters that are meaningful in current system locale. + * If filename is pure ASCII or real UTF-8 encoded string, + * MultiByteToWideChar succeeds and _wfopen works. If + * filename is locale-ized string, chances are that + * MultiByteToWideChar fails reporting + * ERROR_NO_UNICODE_TRANSLATION, in which case we fall + * back to fopen... + */ + if ((sz = MultiByteToWideChar(CP_UTF8, (flags = MB_ERR_INVALID_CHARS), + filename, len_0, NULL, 0)) > 0 || + (GetLastError() == ERROR_INVALID_FLAGS && + (sz = MultiByteToWideChar(CP_UTF8, (flags = 0), + filename, len_0, NULL, 0)) > 0) + ) { + WCHAR wmode[8]; + WCHAR *wfilename = _alloca(sz * sizeof(WCHAR)); + + if (MultiByteToWideChar(CP_UTF8, flags, + filename, len_0, wfilename, sz) && + MultiByteToWideChar(CP_UTF8, 0, mode, strlen(mode) + 1, + wmode, OSSL_NELEM(wmode)) && + (file = _wfopen(wfilename, wmode)) == NULL && + (errno == ENOENT || errno == EBADF) + ) { + /* + * UTF-8 decode succeeded, but no file, filename + * could still have been locale-ized... + */ + file = fopen(filename, mode); + } + } else if (GetLastError() == ERROR_NO_UNICODE_TRANSLATION) { + file = fopen(filename, mode); + } +# elif defined(__DJGPP__) + { + char *newname = NULL; + + if (pathconf(filename, _PC_NAME_MAX) <= 12) { /* 8.3 file system? */ + char *iterator; + char lastchar; + + if ((newname = OPENSSL_malloc(strlen(filename) + 1)) == NULL) { + CRYPTOerr(CRYPTO_F_OPENSSL_FOPEN, ERR_R_MALLOC_FAILURE); + return NULL; + } + + for (iterator = newname, lastchar = '\0'; + *filename; filename++, iterator++) { + if (lastchar == '/' && filename[0] == '.' + && filename[1] != '.' && filename[1] != '/') { + /* Leading dots are not permitted in plain DOS. */ + *iterator = '_'; + } else { + *iterator = *filename; + } + lastchar = *filename; + } + *iterator = '\0'; + filename = newname; + } + file = fopen(filename, mode); + + OPENSSL_free(newname); + } +# else + file = fopen(filename, mode); +# endif + return file; +} + +#else + +void *openssl_fopen(const char *filename, const char *mode) +{ + return NULL; +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/o_init.c b/trunk/3rdparty/openssl-1.1-fit/crypto/o_init.c new file mode 100644 index 000000000..ed6b1303d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/o_init.c @@ -0,0 +1,21 @@ +/* + * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "e_os.h" +#include + +/* + * Perform any essential OpenSSL initialization operations. Currently does + * nothing. + */ + +void OPENSSL_init(void) +{ + return; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/o_str.c b/trunk/3rdparty/openssl-1.1-fit/crypto/o_str.c new file mode 100644 index 000000000..a8357691a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/o_str.c @@ -0,0 +1,248 @@ +/* + * Copyright 2003-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "e_os.h" +#include +#include +#include "internal/cryptlib.h" +#include "internal/o_str.h" + +int OPENSSL_memcmp(const void *v1, const void *v2, size_t n) +{ + const unsigned char *c1 = v1, *c2 = v2; + int ret = 0; + + while (n && (ret = *c1 - *c2) == 0) + n--, c1++, c2++; + + return ret; +} + +char *CRYPTO_strdup(const char *str, const char* file, int line) +{ + char *ret; + + if (str == NULL) + return NULL; + ret = CRYPTO_malloc(strlen(str) + 1, file, line); + if (ret != NULL) + strcpy(ret, str); + return ret; +} + +char *CRYPTO_strndup(const char *str, size_t s, const char* file, int line) +{ + size_t maxlen; + char *ret; + + if (str == NULL) + return NULL; + + maxlen = OPENSSL_strnlen(str, s); + + ret = CRYPTO_malloc(maxlen + 1, file, line); + if (ret) { + memcpy(ret, str, maxlen); + ret[maxlen] = '\0'; + } + return ret; +} + +void *CRYPTO_memdup(const void *data, size_t siz, const char* file, int line) +{ + void *ret; + + if (data == NULL || siz >= INT_MAX) + return NULL; + + ret = CRYPTO_malloc(siz, file, line); + if (ret == NULL) { + CRYPTOerr(CRYPTO_F_CRYPTO_MEMDUP, ERR_R_MALLOC_FAILURE); + return NULL; + } + return memcpy(ret, data, siz); +} + +size_t OPENSSL_strnlen(const char *str, size_t maxlen) +{ + const char *p; + + for (p = str; maxlen-- != 0 && *p != '\0'; ++p) ; + + return p - str; +} + +size_t OPENSSL_strlcpy(char *dst, const char *src, size_t size) +{ + size_t l = 0; + for (; size > 1 && *src; size--) { + *dst++ = *src++; + l++; + } + if (size) + *dst = '\0'; + return l + strlen(src); +} + +size_t OPENSSL_strlcat(char *dst, const char *src, size_t size) +{ + size_t l = 0; + for (; size > 0 && *dst; size--, dst++) + l++; + return l + OPENSSL_strlcpy(dst, src, size); +} + +int OPENSSL_hexchar2int(unsigned char c) +{ +#ifdef CHARSET_EBCDIC + c = os_toebcdic[c]; +#endif + + switch (c) { + case '0': + return 0; + case '1': + return 1; + case '2': + return 2; + case '3': + return 3; + case '4': + return 4; + case '5': + return 5; + case '6': + return 6; + case '7': + return 7; + case '8': + return 8; + case '9': + return 9; + case 'a': case 'A': + return 0x0A; + case 'b': case 'B': + return 0x0B; + case 'c': case 'C': + return 0x0C; + case 'd': case 'D': + return 0x0D; + case 'e': case 'E': + return 0x0E; + case 'f': case 'F': + return 0x0F; + } + return -1; +} + +/* + * Give a string of hex digits convert to a buffer + */ +unsigned char *OPENSSL_hexstr2buf(const char *str, long *len) +{ + unsigned char *hexbuf, *q; + unsigned char ch, cl; + int chi, cli; + const unsigned char *p; + size_t s; + + s = strlen(str); + if ((hexbuf = OPENSSL_malloc(s >> 1)) == NULL) { + CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF, ERR_R_MALLOC_FAILURE); + return NULL; + } + for (p = (const unsigned char *)str, q = hexbuf; *p; ) { + ch = *p++; + if (ch == ':') + continue; + cl = *p++; + if (!cl) { + CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF, + CRYPTO_R_ODD_NUMBER_OF_DIGITS); + OPENSSL_free(hexbuf); + return NULL; + } + cli = OPENSSL_hexchar2int(cl); + chi = OPENSSL_hexchar2int(ch); + if (cli < 0 || chi < 0) { + OPENSSL_free(hexbuf); + CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF, CRYPTO_R_ILLEGAL_HEX_DIGIT); + return NULL; + } + *q++ = (unsigned char)((chi << 4) | cli); + } + + if (len) + *len = q - hexbuf; + return hexbuf; +} + +/* + * Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its + * hex representation @@@ (Contents of buffer are always kept in ASCII, also + * on EBCDIC machines) + */ +char *OPENSSL_buf2hexstr(const unsigned char *buffer, long len) +{ + static const char hexdig[] = "0123456789ABCDEF"; + char *tmp, *q; + const unsigned char *p; + int i; + + if (len == 0) + { + return OPENSSL_zalloc(1); + } + + if ((tmp = OPENSSL_malloc(len * 3)) == NULL) { + CRYPTOerr(CRYPTO_F_OPENSSL_BUF2HEXSTR, ERR_R_MALLOC_FAILURE); + return NULL; + } + q = tmp; + for (i = 0, p = buffer; i < len; i++, p++) { + *q++ = hexdig[(*p >> 4) & 0xf]; + *q++ = hexdig[*p & 0xf]; + *q++ = ':'; + } + q[-1] = 0; +#ifdef CHARSET_EBCDIC + ebcdic2ascii(tmp, tmp, q - tmp - 1); +#endif + + return tmp; +} + +int openssl_strerror_r(int errnum, char *buf, size_t buflen) +{ +#if defined(_MSC_VER) && _MSC_VER>=1400 + return !strerror_s(buf, buflen, errnum); +#elif defined(_GNU_SOURCE) + return strerror_r(errnum, buf, buflen) != NULL; +#elif (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || \ + (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600) + /* + * We can use "real" strerror_r. The OpenSSL version differs in that it + * gives 1 on success and 0 on failure for consistency with other OpenSSL + * functions. Real strerror_r does it the other way around + */ + return !strerror_r(errnum, buf, buflen); +#else + char *err; + /* Fall back to non-thread safe strerror()...its all we can do */ + if (buflen < 2) + return 0; + err = strerror(errnum); + /* Can this ever happen? */ + if (err == NULL) + return 0; + strncpy(buf, err, buflen - 1); + buf[buflen - 1] = '\0'; + return 1; +#endif +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/o_time.c b/trunk/3rdparty/openssl-1.1-fit/crypto/o_time.c new file mode 100644 index 000000000..6d764f55e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/o_time.c @@ -0,0 +1,200 @@ +/* + * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include + +struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result) +{ + struct tm *ts = NULL; + +#if defined(OPENSSL_THREADS) && defined(OPENSSL_SYS_VMS) + { + /* + * On VMS, gmtime_r() takes a 32-bit pointer as second argument. + * Since we can't know that |result| is in a space that can easily + * translate to a 32-bit pointer, we must store temporarily on stack + * and copy the result. The stack is always reachable with 32-bit + * pointers. + */ +#if defined(OPENSSL_SYS_VMS) && __INITIAL_POINTER_SIZE +# pragma pointer_size save +# pragma pointer_size 32 +#endif + struct tm data, *ts2 = &data; +#if defined OPENSSL_SYS_VMS && __INITIAL_POINTER_SIZE +# pragma pointer_size restore +#endif + if (gmtime_r(timer, ts2) == NULL) + return NULL; + memcpy(result, ts2, sizeof(struct tm)); + ts = result; + } +#elif defined(OPENSSL_THREADS) && !defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_SYS_MACOSX) + if (gmtime_r(timer, result) == NULL) + return NULL; + ts = result; +#elif defined (OPENSSL_SYS_WINDOWS) && defined(_MSC_VER) && _MSC_VER >= 1400 + if (gmtime_s(result, timer)) + return NULL; + ts = result; +#else + ts = gmtime(timer); + if (ts == NULL) + return NULL; + + memcpy(result, ts, sizeof(struct tm)); + ts = result; +#endif + return ts; +} + +/* + * Take a tm structure and add an offset to it. This avoids any OS issues + * with restricted date types and overflows which cause the year 2038 + * problem. + */ + +#define SECS_PER_DAY (24 * 60 * 60) + +static long date_to_julian(int y, int m, int d); +static void julian_to_date(long jd, int *y, int *m, int *d); +static int julian_adj(const struct tm *tm, int off_day, long offset_sec, + long *pday, int *psec); + +int OPENSSL_gmtime_adj(struct tm *tm, int off_day, long offset_sec) +{ + int time_sec, time_year, time_month, time_day; + long time_jd; + + /* Convert time and offset into Julian day and seconds */ + if (!julian_adj(tm, off_day, offset_sec, &time_jd, &time_sec)) + return 0; + + /* Convert Julian day back to date */ + + julian_to_date(time_jd, &time_year, &time_month, &time_day); + + if (time_year < 1900 || time_year > 9999) + return 0; + + /* Update tm structure */ + + tm->tm_year = time_year - 1900; + tm->tm_mon = time_month - 1; + tm->tm_mday = time_day; + + tm->tm_hour = time_sec / 3600; + tm->tm_min = (time_sec / 60) % 60; + tm->tm_sec = time_sec % 60; + + return 1; + +} + +int OPENSSL_gmtime_diff(int *pday, int *psec, + const struct tm *from, const struct tm *to) +{ + int from_sec, to_sec, diff_sec; + long from_jd, to_jd, diff_day; + if (!julian_adj(from, 0, 0, &from_jd, &from_sec)) + return 0; + if (!julian_adj(to, 0, 0, &to_jd, &to_sec)) + return 0; + diff_day = to_jd - from_jd; + diff_sec = to_sec - from_sec; + /* Adjust differences so both positive or both negative */ + if (diff_day > 0 && diff_sec < 0) { + diff_day--; + diff_sec += SECS_PER_DAY; + } + if (diff_day < 0 && diff_sec > 0) { + diff_day++; + diff_sec -= SECS_PER_DAY; + } + + if (pday) + *pday = (int)diff_day; + if (psec) + *psec = diff_sec; + + return 1; + +} + +/* Convert tm structure and offset into julian day and seconds */ +static int julian_adj(const struct tm *tm, int off_day, long offset_sec, + long *pday, int *psec) +{ + int offset_hms, offset_day; + long time_jd; + int time_year, time_month, time_day; + /* split offset into days and day seconds */ + offset_day = offset_sec / SECS_PER_DAY; + /* Avoid sign issues with % operator */ + offset_hms = offset_sec - (offset_day * SECS_PER_DAY); + offset_day += off_day; + /* Add current time seconds to offset */ + offset_hms += tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec; + /* Adjust day seconds if overflow */ + if (offset_hms >= SECS_PER_DAY) { + offset_day++; + offset_hms -= SECS_PER_DAY; + } else if (offset_hms < 0) { + offset_day--; + offset_hms += SECS_PER_DAY; + } + + /* + * Convert date of time structure into a Julian day number. + */ + + time_year = tm->tm_year + 1900; + time_month = tm->tm_mon + 1; + time_day = tm->tm_mday; + + time_jd = date_to_julian(time_year, time_month, time_day); + + /* Work out Julian day of new date */ + time_jd += offset_day; + + if (time_jd < 0) + return 0; + + *pday = time_jd; + *psec = offset_hms; + return 1; +} + +/* + * Convert date to and from julian day Uses Fliegel & Van Flandern algorithm + */ +static long date_to_julian(int y, int m, int d) +{ + return (1461 * (y + 4800 + (m - 14) / 12)) / 4 + + (367 * (m - 2 - 12 * ((m - 14) / 12))) / 12 - + (3 * ((y + 4900 + (m - 14) / 12) / 100)) / 4 + d - 32075; +} + +static void julian_to_date(long jd, int *y, int *m, int *d) +{ + long L = jd + 68569; + long n = (4 * L) / 146097; + long i, j; + + L = L - (146097 * n + 3) / 4; + i = (4000 * (L + 1)) / 1461001; + L = L - (1461 * i) / 4 + 31; + j = (80 * L) / 2447; + *d = L - (2447 * j) / 80; + L = j / 11; + *m = j + 2 - (12 * L); + *y = 100 * (n - 49) + i + L; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/objects/README b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/README new file mode 100644 index 000000000..700f9c5e5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/README @@ -0,0 +1,44 @@ +objects.txt syntax +------------------ + +To cover all the naming hacks that were previously in objects.h needed some +kind of hacks in objects.txt. + +The basic syntax for adding an object is as follows: + + 1 2 3 4 : shortName : Long Name + + If Long Name contains only word characters and hyphen-minus + (0x2D) or full stop (0x2E) then Long Name is used as basis + for the base name in C. Otherwise, the shortName is used. + + The base name (let's call it 'base') will then be used to + create the C macros SN_base, LN_base, NID_base and OBJ_base. + + Note that if the base name contains spaces, dashes or periods, + those will be converted to underscore. + +Then there are some extra commands: + + !Alias foo 1 2 3 4 + + This just makes a name foo for an OID. The C macro + OBJ_foo will be created as a result. + + !Cname foo + + This makes sure that the name foo will be used as base name + in C. + + !module foo + 1 2 3 4 : shortName : Long Name + !global + + The !module command was meant to define a kind of modularity. + What it does is to make sure the module name is prepended + to the base name. !global turns this off. This construction + is not recursive. + +Lines starting with # are treated as comments, as well as any line starting +with ! and not matching the commands above. + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/objects/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/build.info new file mode 100644 index 000000000..38e290756 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/build.info @@ -0,0 +1,3 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + o_names.c obj_dat.c obj_lib.c obj_err.c obj_xref.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/objects/o_names.c b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/o_names.c new file mode 100644 index 000000000..c4355370c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/o_names.c @@ -0,0 +1,406 @@ +/* + * Copyright 1998-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include "internal/thread_once.h" +#include "internal/lhash.h" +#include "obj_lcl.h" +#include "e_os.h" + +/* + * We define this wrapper for two reasons. Firstly, later versions of + * DEC C add linkage information to certain functions, which makes it + * tricky to use them as values to regular function pointers. + * Secondly, in the EDK2 build environment, the strcasecmp function is + * actually an external function with the Microsoft ABI, so we can't + * transparently assign function pointers to it. + */ +#if defined(OPENSSL_SYS_VMS_DECC) || defined(OPENSSL_SYS_UEFI) +static int obj_strcasecmp(const char *a, const char *b) +{ + return strcasecmp(a, b); +} +#else +#define obj_strcasecmp strcasecmp +#endif + +/* + * I use the ex_data stuff to manage the identifiers for the obj_name_types + * that applications may define. I only really use the free function field. + */ +static LHASH_OF(OBJ_NAME) *names_lh = NULL; +static int names_type_num = OBJ_NAME_TYPE_NUM; +static CRYPTO_RWLOCK *obj_lock = NULL; + +struct name_funcs_st { + unsigned long (*hash_func) (const char *name); + int (*cmp_func) (const char *a, const char *b); + void (*free_func) (const char *, int, const char *); +}; + +static STACK_OF(NAME_FUNCS) *name_funcs_stack; + +/* + * The LHASH callbacks now use the raw "void *" prototypes and do + * per-variable casting in the functions. This prevents function pointer + * casting without the need for macro-generated wrapper functions. + */ + +static unsigned long obj_name_hash(const OBJ_NAME *a); +static int obj_name_cmp(const OBJ_NAME *a, const OBJ_NAME *b); + +static CRYPTO_ONCE init = CRYPTO_ONCE_STATIC_INIT; +DEFINE_RUN_ONCE_STATIC(o_names_init) +{ + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE); + names_lh = lh_OBJ_NAME_new(obj_name_hash, obj_name_cmp); + obj_lock = CRYPTO_THREAD_lock_new(); + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE); + return names_lh != NULL && obj_lock != NULL; +} + +int OBJ_NAME_init(void) +{ + return RUN_ONCE(&init, o_names_init); +} + +int OBJ_NAME_new_index(unsigned long (*hash_func) (const char *), + int (*cmp_func) (const char *, const char *), + void (*free_func) (const char *, int, const char *)) +{ + int ret = 0, i, push; + NAME_FUNCS *name_funcs; + + if (!OBJ_NAME_init()) + return 0; + + CRYPTO_THREAD_write_lock(obj_lock); + + if (name_funcs_stack == NULL) { + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE); + name_funcs_stack = sk_NAME_FUNCS_new_null(); + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE); + } + if (name_funcs_stack == NULL) { + /* ERROR */ + goto out; + } + ret = names_type_num; + names_type_num++; + for (i = sk_NAME_FUNCS_num(name_funcs_stack); i < names_type_num; i++) { + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE); + name_funcs = OPENSSL_zalloc(sizeof(*name_funcs)); + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE); + if (name_funcs == NULL) { + OBJerr(OBJ_F_OBJ_NAME_NEW_INDEX, ERR_R_MALLOC_FAILURE); + ret = 0; + goto out; + } + name_funcs->hash_func = openssl_lh_strcasehash; + name_funcs->cmp_func = obj_strcasecmp; + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE); + + push = sk_NAME_FUNCS_push(name_funcs_stack, name_funcs); + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE); + + if (!push) { + OBJerr(OBJ_F_OBJ_NAME_NEW_INDEX, ERR_R_MALLOC_FAILURE); + OPENSSL_free(name_funcs); + ret = 0; + goto out; + } + } + name_funcs = sk_NAME_FUNCS_value(name_funcs_stack, ret); + if (hash_func != NULL) + name_funcs->hash_func = hash_func; + if (cmp_func != NULL) + name_funcs->cmp_func = cmp_func; + if (free_func != NULL) + name_funcs->free_func = free_func; + +out: + CRYPTO_THREAD_unlock(obj_lock); + return ret; +} + +static int obj_name_cmp(const OBJ_NAME *a, const OBJ_NAME *b) +{ + int ret; + + ret = a->type - b->type; + if (ret == 0) { + if ((name_funcs_stack != NULL) + && (sk_NAME_FUNCS_num(name_funcs_stack) > a->type)) { + ret = sk_NAME_FUNCS_value(name_funcs_stack, + a->type)->cmp_func(a->name, b->name); + } else + ret = strcasecmp(a->name, b->name); + } + return ret; +} + +static unsigned long obj_name_hash(const OBJ_NAME *a) +{ + unsigned long ret; + + if ((name_funcs_stack != NULL) + && (sk_NAME_FUNCS_num(name_funcs_stack) > a->type)) { + ret = + sk_NAME_FUNCS_value(name_funcs_stack, + a->type)->hash_func(a->name); + } else { + ret = openssl_lh_strcasehash(a->name); + } + ret ^= a->type; + return ret; +} + +const char *OBJ_NAME_get(const char *name, int type) +{ + OBJ_NAME on, *ret; + int num = 0, alias; + const char *value = NULL; + + if (name == NULL) + return NULL; + if (!OBJ_NAME_init()) + return NULL; + CRYPTO_THREAD_read_lock(obj_lock); + + alias = type & OBJ_NAME_ALIAS; + type &= ~OBJ_NAME_ALIAS; + + on.name = name; + on.type = type; + + for (;;) { + ret = lh_OBJ_NAME_retrieve(names_lh, &on); + if (ret == NULL) + break; + if ((ret->alias) && !alias) { + if (++num > 10) + break; + on.name = ret->data; + } else { + value = ret->data; + break; + } + } + + CRYPTO_THREAD_unlock(obj_lock); + return value; +} + +int OBJ_NAME_add(const char *name, int type, const char *data) +{ + OBJ_NAME *onp, *ret; + int alias, ok = 0; + + if (!OBJ_NAME_init()) + return 0; + + alias = type & OBJ_NAME_ALIAS; + type &= ~OBJ_NAME_ALIAS; + + onp = OPENSSL_malloc(sizeof(*onp)); + if (onp == NULL) { + /* ERROR */ + goto unlock; + } + + onp->name = name; + onp->alias = alias; + onp->type = type; + onp->data = data; + + CRYPTO_THREAD_write_lock(obj_lock); + + ret = lh_OBJ_NAME_insert(names_lh, onp); + if (ret != NULL) { + /* free things */ + if ((name_funcs_stack != NULL) + && (sk_NAME_FUNCS_num(name_funcs_stack) > ret->type)) { + /* + * XXX: I'm not sure I understand why the free function should + * get three arguments... -- Richard Levitte + */ + sk_NAME_FUNCS_value(name_funcs_stack, + ret->type)->free_func(ret->name, ret->type, + ret->data); + } + OPENSSL_free(ret); + } else { + if (lh_OBJ_NAME_error(names_lh)) { + /* ERROR */ + OPENSSL_free(onp); + goto unlock; + } + } + + ok = 1; + +unlock: + CRYPTO_THREAD_unlock(obj_lock); + return ok; +} + +int OBJ_NAME_remove(const char *name, int type) +{ + OBJ_NAME on, *ret; + int ok = 0; + + if (!OBJ_NAME_init()) + return 0; + + CRYPTO_THREAD_write_lock(obj_lock); + + type &= ~OBJ_NAME_ALIAS; + on.name = name; + on.type = type; + ret = lh_OBJ_NAME_delete(names_lh, &on); + if (ret != NULL) { + /* free things */ + if ((name_funcs_stack != NULL) + && (sk_NAME_FUNCS_num(name_funcs_stack) > ret->type)) { + /* + * XXX: I'm not sure I understand why the free function should + * get three arguments... -- Richard Levitte + */ + sk_NAME_FUNCS_value(name_funcs_stack, + ret->type)->free_func(ret->name, ret->type, + ret->data); + } + OPENSSL_free(ret); + ok = 1; + } + + CRYPTO_THREAD_unlock(obj_lock); + return ok; +} + +typedef struct { + int type; + void (*fn) (const OBJ_NAME *, void *arg); + void *arg; +} OBJ_DOALL; + +static void do_all_fn(const OBJ_NAME *name, OBJ_DOALL *d) +{ + if (name->type == d->type) + d->fn(name, d->arg); +} + +IMPLEMENT_LHASH_DOALL_ARG_CONST(OBJ_NAME, OBJ_DOALL); + +void OBJ_NAME_do_all(int type, void (*fn) (const OBJ_NAME *, void *arg), + void *arg) +{ + OBJ_DOALL d; + + d.type = type; + d.fn = fn; + d.arg = arg; + + lh_OBJ_NAME_doall_OBJ_DOALL(names_lh, do_all_fn, &d); +} + +struct doall_sorted { + int type; + int n; + const OBJ_NAME **names; +}; + +static void do_all_sorted_fn(const OBJ_NAME *name, void *d_) +{ + struct doall_sorted *d = d_; + + if (name->type != d->type) + return; + + d->names[d->n++] = name; +} + +static int do_all_sorted_cmp(const void *n1_, const void *n2_) +{ + const OBJ_NAME *const *n1 = n1_; + const OBJ_NAME *const *n2 = n2_; + + return strcmp((*n1)->name, (*n2)->name); +} + +void OBJ_NAME_do_all_sorted(int type, + void (*fn) (const OBJ_NAME *, void *arg), + void *arg) +{ + struct doall_sorted d; + int n; + + d.type = type; + d.names = + OPENSSL_malloc(sizeof(*d.names) * lh_OBJ_NAME_num_items(names_lh)); + /* Really should return an error if !d.names...but its a void function! */ + if (d.names != NULL) { + d.n = 0; + OBJ_NAME_do_all(type, do_all_sorted_fn, &d); + + qsort((void *)d.names, d.n, sizeof(*d.names), do_all_sorted_cmp); + + for (n = 0; n < d.n; ++n) + fn(d.names[n], arg); + + OPENSSL_free((void *)d.names); + } +} + +static int free_type; + +static void names_lh_free_doall(OBJ_NAME *onp) +{ + if (onp == NULL) + return; + + if (free_type < 0 || free_type == onp->type) + OBJ_NAME_remove(onp->name, onp->type); +} + +static void name_funcs_free(NAME_FUNCS *ptr) +{ + OPENSSL_free(ptr); +} + +void OBJ_NAME_cleanup(int type) +{ + unsigned long down_load; + + if (names_lh == NULL) + return; + + free_type = type; + down_load = lh_OBJ_NAME_get_down_load(names_lh); + lh_OBJ_NAME_set_down_load(names_lh, 0); + + lh_OBJ_NAME_doall(names_lh, names_lh_free_doall); + if (type < 0) { + lh_OBJ_NAME_free(names_lh); + sk_NAME_FUNCS_pop_free(name_funcs_stack, name_funcs_free); + CRYPTO_THREAD_lock_free(obj_lock); + names_lh = NULL; + name_funcs_stack = NULL; + obj_lock = NULL; + } else + lh_OBJ_NAME_set_down_load(names_lh, down_load); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_dat.c b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_dat.c new file mode 100644 index 000000000..ef2d1e0dd --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_dat.c @@ -0,0 +1,739 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/ctype.h" +#include +#include "internal/cryptlib.h" +#include +#include +#include "internal/objects.h" +#include +#include "internal/asn1_int.h" +#include "obj_lcl.h" + +/* obj_dat.h is generated from objects.h by obj_dat.pl */ +#include "obj_dat.h" + +DECLARE_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, sn); +DECLARE_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, ln); +DECLARE_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, obj); + +#define ADDED_DATA 0 +#define ADDED_SNAME 1 +#define ADDED_LNAME 2 +#define ADDED_NID 3 + +struct added_obj_st { + int type; + ASN1_OBJECT *obj; +}; + +static int new_nid = NUM_NID; +static LHASH_OF(ADDED_OBJ) *added = NULL; + +static int sn_cmp(const ASN1_OBJECT *const *a, const unsigned int *b) +{ + return strcmp((*a)->sn, nid_objs[*b].sn); +} + +IMPLEMENT_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, sn); + +static int ln_cmp(const ASN1_OBJECT *const *a, const unsigned int *b) +{ + return strcmp((*a)->ln, nid_objs[*b].ln); +} + +IMPLEMENT_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, ln); + +static unsigned long added_obj_hash(const ADDED_OBJ *ca) +{ + const ASN1_OBJECT *a; + int i; + unsigned long ret = 0; + unsigned char *p; + + a = ca->obj; + switch (ca->type) { + case ADDED_DATA: + ret = a->length << 20L; + p = (unsigned char *)a->data; + for (i = 0; i < a->length; i++) + ret ^= p[i] << ((i * 3) % 24); + break; + case ADDED_SNAME: + ret = OPENSSL_LH_strhash(a->sn); + break; + case ADDED_LNAME: + ret = OPENSSL_LH_strhash(a->ln); + break; + case ADDED_NID: + ret = a->nid; + break; + default: + /* abort(); */ + return 0; + } + ret &= 0x3fffffffL; + ret |= ((unsigned long)ca->type) << 30L; + return ret; +} + +static int added_obj_cmp(const ADDED_OBJ *ca, const ADDED_OBJ *cb) +{ + ASN1_OBJECT *a, *b; + int i; + + i = ca->type - cb->type; + if (i) + return i; + a = ca->obj; + b = cb->obj; + switch (ca->type) { + case ADDED_DATA: + i = (a->length - b->length); + if (i) + return i; + return memcmp(a->data, b->data, (size_t)a->length); + case ADDED_SNAME: + if (a->sn == NULL) + return -1; + else if (b->sn == NULL) + return 1; + else + return strcmp(a->sn, b->sn); + case ADDED_LNAME: + if (a->ln == NULL) + return -1; + else if (b->ln == NULL) + return 1; + else + return strcmp(a->ln, b->ln); + case ADDED_NID: + return a->nid - b->nid; + default: + /* abort(); */ + return 0; + } +} + +static int init_added(void) +{ + if (added != NULL) + return 1; + added = lh_ADDED_OBJ_new(added_obj_hash, added_obj_cmp); + return added != NULL; +} + +static void cleanup1_doall(ADDED_OBJ *a) +{ + a->obj->nid = 0; + a->obj->flags |= ASN1_OBJECT_FLAG_DYNAMIC | + ASN1_OBJECT_FLAG_DYNAMIC_STRINGS | ASN1_OBJECT_FLAG_DYNAMIC_DATA; +} + +static void cleanup2_doall(ADDED_OBJ *a) +{ + a->obj->nid++; +} + +static void cleanup3_doall(ADDED_OBJ *a) +{ + if (--a->obj->nid == 0) + ASN1_OBJECT_free(a->obj); + OPENSSL_free(a); +} + +void obj_cleanup_int(void) +{ + if (added == NULL) + return; + lh_ADDED_OBJ_set_down_load(added, 0); + lh_ADDED_OBJ_doall(added, cleanup1_doall); /* zero counters */ + lh_ADDED_OBJ_doall(added, cleanup2_doall); /* set counters */ + lh_ADDED_OBJ_doall(added, cleanup3_doall); /* free objects */ + lh_ADDED_OBJ_free(added); + added = NULL; +} + +int OBJ_new_nid(int num) +{ + int i; + + i = new_nid; + new_nid += num; + return i; +} + +int OBJ_add_object(const ASN1_OBJECT *obj) +{ + ASN1_OBJECT *o; + ADDED_OBJ *ao[4] = { NULL, NULL, NULL, NULL }, *aop; + int i; + + if (added == NULL) + if (!init_added()) + return 0; + if ((o = OBJ_dup(obj)) == NULL) + goto err; + if ((ao[ADDED_NID] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL) + goto err2; + if ((o->length != 0) && (obj->data != NULL)) + if ((ao[ADDED_DATA] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL) + goto err2; + if (o->sn != NULL) + if ((ao[ADDED_SNAME] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL) + goto err2; + if (o->ln != NULL) + if ((ao[ADDED_LNAME] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL) + goto err2; + + for (i = ADDED_DATA; i <= ADDED_NID; i++) { + if (ao[i] != NULL) { + ao[i]->type = i; + ao[i]->obj = o; + aop = lh_ADDED_OBJ_insert(added, ao[i]); + /* memory leak, but should not normally matter */ + OPENSSL_free(aop); + } + } + o->flags &= + ~(ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS | + ASN1_OBJECT_FLAG_DYNAMIC_DATA); + + return o->nid; + err2: + OBJerr(OBJ_F_OBJ_ADD_OBJECT, ERR_R_MALLOC_FAILURE); + err: + for (i = ADDED_DATA; i <= ADDED_NID; i++) + OPENSSL_free(ao[i]); + ASN1_OBJECT_free(o); + return NID_undef; +} + +ASN1_OBJECT *OBJ_nid2obj(int n) +{ + ADDED_OBJ ad, *adp; + ASN1_OBJECT ob; + + if ((n >= 0) && (n < NUM_NID)) { + if ((n != NID_undef) && (nid_objs[n].nid == NID_undef)) { + OBJerr(OBJ_F_OBJ_NID2OBJ, OBJ_R_UNKNOWN_NID); + return NULL; + } + return (ASN1_OBJECT *)&(nid_objs[n]); + } else if (added == NULL) + return NULL; + else { + ad.type = ADDED_NID; + ad.obj = &ob; + ob.nid = n; + adp = lh_ADDED_OBJ_retrieve(added, &ad); + if (adp != NULL) + return adp->obj; + else { + OBJerr(OBJ_F_OBJ_NID2OBJ, OBJ_R_UNKNOWN_NID); + return NULL; + } + } +} + +const char *OBJ_nid2sn(int n) +{ + ADDED_OBJ ad, *adp; + ASN1_OBJECT ob; + + if ((n >= 0) && (n < NUM_NID)) { + if ((n != NID_undef) && (nid_objs[n].nid == NID_undef)) { + OBJerr(OBJ_F_OBJ_NID2SN, OBJ_R_UNKNOWN_NID); + return NULL; + } + return nid_objs[n].sn; + } else if (added == NULL) + return NULL; + else { + ad.type = ADDED_NID; + ad.obj = &ob; + ob.nid = n; + adp = lh_ADDED_OBJ_retrieve(added, &ad); + if (adp != NULL) + return adp->obj->sn; + else { + OBJerr(OBJ_F_OBJ_NID2SN, OBJ_R_UNKNOWN_NID); + return NULL; + } + } +} + +const char *OBJ_nid2ln(int n) +{ + ADDED_OBJ ad, *adp; + ASN1_OBJECT ob; + + if ((n >= 0) && (n < NUM_NID)) { + if ((n != NID_undef) && (nid_objs[n].nid == NID_undef)) { + OBJerr(OBJ_F_OBJ_NID2LN, OBJ_R_UNKNOWN_NID); + return NULL; + } + return nid_objs[n].ln; + } else if (added == NULL) + return NULL; + else { + ad.type = ADDED_NID; + ad.obj = &ob; + ob.nid = n; + adp = lh_ADDED_OBJ_retrieve(added, &ad); + if (adp != NULL) + return adp->obj->ln; + else { + OBJerr(OBJ_F_OBJ_NID2LN, OBJ_R_UNKNOWN_NID); + return NULL; + } + } +} + +static int obj_cmp(const ASN1_OBJECT *const *ap, const unsigned int *bp) +{ + int j; + const ASN1_OBJECT *a = *ap; + const ASN1_OBJECT *b = &nid_objs[*bp]; + + j = (a->length - b->length); + if (j) + return j; + if (a->length == 0) + return 0; + return memcmp(a->data, b->data, a->length); +} + +IMPLEMENT_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, obj); + +int OBJ_obj2nid(const ASN1_OBJECT *a) +{ + const unsigned int *op; + ADDED_OBJ ad, *adp; + + if (a == NULL) + return NID_undef; + if (a->nid != 0) + return a->nid; + + if (a->length == 0) + return NID_undef; + + if (added != NULL) { + ad.type = ADDED_DATA; + ad.obj = (ASN1_OBJECT *)a; /* XXX: ugly but harmless */ + adp = lh_ADDED_OBJ_retrieve(added, &ad); + if (adp != NULL) + return adp->obj->nid; + } + op = OBJ_bsearch_obj(&a, obj_objs, NUM_OBJ); + if (op == NULL) + return NID_undef; + return nid_objs[*op].nid; +} + +/* + * Convert an object name into an ASN1_OBJECT if "noname" is not set then + * search for short and long names first. This will convert the "dotted" form + * into an object: unlike OBJ_txt2nid it can be used with any objects, not + * just registered ones. + */ + +ASN1_OBJECT *OBJ_txt2obj(const char *s, int no_name) +{ + int nid = NID_undef; + ASN1_OBJECT *op; + unsigned char *buf; + unsigned char *p; + const unsigned char *cp; + int i, j; + + if (!no_name) { + if (((nid = OBJ_sn2nid(s)) != NID_undef) || + ((nid = OBJ_ln2nid(s)) != NID_undef)) + return OBJ_nid2obj(nid); + } + + /* Work out size of content octets */ + i = a2d_ASN1_OBJECT(NULL, 0, s, -1); + if (i <= 0) { + /* Don't clear the error */ + /* + * ERR_clear_error(); + */ + return NULL; + } + /* Work out total size */ + j = ASN1_object_size(0, i, V_ASN1_OBJECT); + if (j < 0) + return NULL; + + if ((buf = OPENSSL_malloc(j)) == NULL) { + OBJerr(OBJ_F_OBJ_TXT2OBJ, ERR_R_MALLOC_FAILURE); + return NULL; + } + + p = buf; + /* Write out tag+length */ + ASN1_put_object(&p, 0, i, V_ASN1_OBJECT, V_ASN1_UNIVERSAL); + /* Write out contents */ + a2d_ASN1_OBJECT(p, i, s, -1); + + cp = buf; + op = d2i_ASN1_OBJECT(NULL, &cp, j); + OPENSSL_free(buf); + return op; +} + +int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name) +{ + int i, n = 0, len, nid, first, use_bn; + BIGNUM *bl; + unsigned long l; + const unsigned char *p; + char tbuf[DECIMAL_SIZE(i) + DECIMAL_SIZE(l) + 2]; + + /* Ensure that, at every state, |buf| is NUL-terminated. */ + if (buf && buf_len > 0) + buf[0] = '\0'; + + if ((a == NULL) || (a->data == NULL)) + return 0; + + if (!no_name && (nid = OBJ_obj2nid(a)) != NID_undef) { + const char *s; + s = OBJ_nid2ln(nid); + if (s == NULL) + s = OBJ_nid2sn(nid); + if (s) { + if (buf) + OPENSSL_strlcpy(buf, s, buf_len); + n = strlen(s); + return n; + } + } + + len = a->length; + p = a->data; + + first = 1; + bl = NULL; + + while (len > 0) { + l = 0; + use_bn = 0; + for (;;) { + unsigned char c = *p++; + len--; + if ((len == 0) && (c & 0x80)) + goto err; + if (use_bn) { + if (!BN_add_word(bl, c & 0x7f)) + goto err; + } else + l |= c & 0x7f; + if (!(c & 0x80)) + break; + if (!use_bn && (l > (ULONG_MAX >> 7L))) { + if (bl == NULL && (bl = BN_new()) == NULL) + goto err; + if (!BN_set_word(bl, l)) + goto err; + use_bn = 1; + } + if (use_bn) { + if (!BN_lshift(bl, bl, 7)) + goto err; + } else + l <<= 7L; + } + + if (first) { + first = 0; + if (l >= 80) { + i = 2; + if (use_bn) { + if (!BN_sub_word(bl, 80)) + goto err; + } else + l -= 80; + } else { + i = (int)(l / 40); + l -= (long)(i * 40); + } + if (buf && (buf_len > 1)) { + *buf++ = i + '0'; + *buf = '\0'; + buf_len--; + } + n++; + } + + if (use_bn) { + char *bndec; + bndec = BN_bn2dec(bl); + if (!bndec) + goto err; + i = strlen(bndec); + if (buf) { + if (buf_len > 1) { + *buf++ = '.'; + *buf = '\0'; + buf_len--; + } + OPENSSL_strlcpy(buf, bndec, buf_len); + if (i > buf_len) { + buf += buf_len; + buf_len = 0; + } else { + buf += i; + buf_len -= i; + } + } + n++; + n += i; + OPENSSL_free(bndec); + } else { + BIO_snprintf(tbuf, sizeof(tbuf), ".%lu", l); + i = strlen(tbuf); + if (buf && (buf_len > 0)) { + OPENSSL_strlcpy(buf, tbuf, buf_len); + if (i > buf_len) { + buf += buf_len; + buf_len = 0; + } else { + buf += i; + buf_len -= i; + } + } + n += i; + l = 0; + } + } + + BN_free(bl); + return n; + + err: + BN_free(bl); + return -1; +} + +int OBJ_txt2nid(const char *s) +{ + ASN1_OBJECT *obj; + int nid; + obj = OBJ_txt2obj(s, 0); + nid = OBJ_obj2nid(obj); + ASN1_OBJECT_free(obj); + return nid; +} + +int OBJ_ln2nid(const char *s) +{ + ASN1_OBJECT o; + const ASN1_OBJECT *oo = &o; + ADDED_OBJ ad, *adp; + const unsigned int *op; + + o.ln = s; + if (added != NULL) { + ad.type = ADDED_LNAME; + ad.obj = &o; + adp = lh_ADDED_OBJ_retrieve(added, &ad); + if (adp != NULL) + return adp->obj->nid; + } + op = OBJ_bsearch_ln(&oo, ln_objs, NUM_LN); + if (op == NULL) + return NID_undef; + return nid_objs[*op].nid; +} + +int OBJ_sn2nid(const char *s) +{ + ASN1_OBJECT o; + const ASN1_OBJECT *oo = &o; + ADDED_OBJ ad, *adp; + const unsigned int *op; + + o.sn = s; + if (added != NULL) { + ad.type = ADDED_SNAME; + ad.obj = &o; + adp = lh_ADDED_OBJ_retrieve(added, &ad); + if (adp != NULL) + return adp->obj->nid; + } + op = OBJ_bsearch_sn(&oo, sn_objs, NUM_SN); + if (op == NULL) + return NID_undef; + return nid_objs[*op].nid; +} + +const void *OBJ_bsearch_(const void *key, const void *base, int num, int size, + int (*cmp) (const void *, const void *)) +{ + return OBJ_bsearch_ex_(key, base, num, size, cmp, 0); +} + +const void *OBJ_bsearch_ex_(const void *key, const void *base_, int num, + int size, + int (*cmp) (const void *, const void *), + int flags) +{ + const char *base = base_; + int l, h, i = 0, c = 0; + const char *p = NULL; + + if (num == 0) + return NULL; + l = 0; + h = num; + while (l < h) { + i = (l + h) / 2; + p = &(base[i * size]); + c = (*cmp) (key, p); + if (c < 0) + h = i; + else if (c > 0) + l = i + 1; + else + break; + } +#ifdef CHARSET_EBCDIC + /* + * THIS IS A KLUDGE - Because the *_obj is sorted in ASCII order, and I + * don't have perl (yet), we revert to a *LINEAR* search when the object + * wasn't found in the binary search. + */ + if (c != 0) { + for (i = 0; i < num; ++i) { + p = &(base[i * size]); + c = (*cmp) (key, p); + if (c == 0 || (c < 0 && (flags & OBJ_BSEARCH_VALUE_ON_NOMATCH))) + return p; + } + } +#endif + if (c != 0 && !(flags & OBJ_BSEARCH_VALUE_ON_NOMATCH)) + p = NULL; + else if (c == 0 && (flags & OBJ_BSEARCH_FIRST_VALUE_ON_MATCH)) { + while (i > 0 && (*cmp) (key, &(base[(i - 1) * size])) == 0) + i--; + p = &(base[i * size]); + } + return p; +} + +/* + * Parse a BIO sink to create some extra oid's objects. + * Line format: + */ +int OBJ_create_objects(BIO *in) +{ + char buf[512]; + int i, num = 0; + char *o, *s, *l = NULL; + + for (;;) { + s = o = NULL; + i = BIO_gets(in, buf, 512); + if (i <= 0) + return num; + buf[i - 1] = '\0'; + if (!ossl_isalnum(buf[0])) + return num; + o = s = buf; + while (ossl_isdigit(*s) || *s == '.') + s++; + if (*s != '\0') { + *(s++) = '\0'; + while (ossl_isspace(*s)) + s++; + if (*s == '\0') { + s = NULL; + } else { + l = s; + while (*l != '\0' && !ossl_isspace(*l)) + l++; + if (*l != '\0') { + *(l++) = '\0'; + while (ossl_isspace(*l)) + l++; + if (*l == '\0') { + l = NULL; + } + } else { + l = NULL; + } + } + } else { + s = NULL; + } + if (*o == '\0') + return num; + if (!OBJ_create(o, s, l)) + return num; + num++; + } +} + +int OBJ_create(const char *oid, const char *sn, const char *ln) +{ + ASN1_OBJECT *tmpoid = NULL; + int ok = 0; + + /* Check to see if short or long name already present */ + if ((sn != NULL && OBJ_sn2nid(sn) != NID_undef) + || (ln != NULL && OBJ_ln2nid(ln) != NID_undef)) { + OBJerr(OBJ_F_OBJ_CREATE, OBJ_R_OID_EXISTS); + return 0; + } + + /* Convert numerical OID string to an ASN1_OBJECT structure */ + tmpoid = OBJ_txt2obj(oid, 1); + if (tmpoid == NULL) + return 0; + + /* If NID is not NID_undef then object already exists */ + if (OBJ_obj2nid(tmpoid) != NID_undef) { + OBJerr(OBJ_F_OBJ_CREATE, OBJ_R_OID_EXISTS); + goto err; + } + + tmpoid->nid = OBJ_new_nid(1); + tmpoid->sn = (char *)sn; + tmpoid->ln = (char *)ln; + + ok = OBJ_add_object(tmpoid); + + tmpoid->sn = NULL; + tmpoid->ln = NULL; + + err: + ASN1_OBJECT_free(tmpoid); + return ok; +} + +size_t OBJ_length(const ASN1_OBJECT *obj) +{ + if (obj == NULL) + return 0; + return obj->length; +} + +const unsigned char *OBJ_get0_data(const ASN1_OBJECT *obj) +{ + if (obj == NULL) + return NULL; + return obj->data; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_dat.h b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_dat.h new file mode 100644 index 000000000..9ab1a14b9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_dat.h @@ -0,0 +1,5733 @@ +/* + * WARNING: do not edit! + * Generated by crypto/objects/obj_dat.pl + * + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Serialized OID's */ +static const unsigned char so[7762] = { + 0x2A,0x86,0x48,0x86,0xF7,0x0D, /* [ 0] OBJ_rsadsi */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, /* [ 6] OBJ_pkcs */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x02, /* [ 13] OBJ_md2 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x05, /* [ 21] OBJ_md5 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x03,0x04, /* [ 29] OBJ_rc4 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01, /* [ 37] OBJ_rsaEncryption */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x02, /* [ 46] OBJ_md2WithRSAEncryption */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x04, /* [ 55] OBJ_md5WithRSAEncryption */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x01, /* [ 64] OBJ_pbeWithMD2AndDES_CBC */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x03, /* [ 73] OBJ_pbeWithMD5AndDES_CBC */ + 0x55, /* [ 82] OBJ_X500 */ + 0x55,0x04, /* [ 83] OBJ_X509 */ + 0x55,0x04,0x03, /* [ 85] OBJ_commonName */ + 0x55,0x04,0x06, /* [ 88] OBJ_countryName */ + 0x55,0x04,0x07, /* [ 91] OBJ_localityName */ + 0x55,0x04,0x08, /* [ 94] OBJ_stateOrProvinceName */ + 0x55,0x04,0x0A, /* [ 97] OBJ_organizationName */ + 0x55,0x04,0x0B, /* [ 100] OBJ_organizationalUnitName */ + 0x55,0x08,0x01,0x01, /* [ 103] OBJ_rsa */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07, /* [ 107] OBJ_pkcs7 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x01, /* [ 115] OBJ_pkcs7_data */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x02, /* [ 124] OBJ_pkcs7_signed */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x03, /* [ 133] OBJ_pkcs7_enveloped */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x04, /* [ 142] OBJ_pkcs7_signedAndEnveloped */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x05, /* [ 151] OBJ_pkcs7_digest */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x06, /* [ 160] OBJ_pkcs7_encrypted */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x03, /* [ 169] OBJ_pkcs3 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x03,0x01, /* [ 177] OBJ_dhKeyAgreement */ + 0x2B,0x0E,0x03,0x02,0x06, /* [ 186] OBJ_des_ecb */ + 0x2B,0x0E,0x03,0x02,0x09, /* [ 191] OBJ_des_cfb64 */ + 0x2B,0x0E,0x03,0x02,0x07, /* [ 196] OBJ_des_cbc */ + 0x2B,0x0E,0x03,0x02,0x11, /* [ 201] OBJ_des_ede_ecb */ + 0x2B,0x06,0x01,0x04,0x01,0x81,0x3C,0x07,0x01,0x01,0x02, /* [ 206] OBJ_idea_cbc */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x03,0x02, /* [ 217] OBJ_rc2_cbc */ + 0x2B,0x0E,0x03,0x02,0x12, /* [ 225] OBJ_sha */ + 0x2B,0x0E,0x03,0x02,0x0F, /* [ 230] OBJ_shaWithRSAEncryption */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x03,0x07, /* [ 235] OBJ_des_ede3_cbc */ + 0x2B,0x0E,0x03,0x02,0x08, /* [ 243] OBJ_des_ofb64 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09, /* [ 248] OBJ_pkcs9 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x01, /* [ 256] OBJ_pkcs9_emailAddress */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x02, /* [ 265] OBJ_pkcs9_unstructuredName */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x03, /* [ 274] OBJ_pkcs9_contentType */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x04, /* [ 283] OBJ_pkcs9_messageDigest */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x05, /* [ 292] OBJ_pkcs9_signingTime */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x06, /* [ 301] OBJ_pkcs9_countersignature */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x07, /* [ 310] OBJ_pkcs9_challengePassword */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x08, /* [ 319] OBJ_pkcs9_unstructuredAddress */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x09, /* [ 328] OBJ_pkcs9_extCertAttributes */ + 0x60,0x86,0x48,0x01,0x86,0xF8,0x42, /* [ 337] OBJ_netscape */ + 0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01, /* [ 344] OBJ_netscape_cert_extension */ + 0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x02, /* [ 352] OBJ_netscape_data_type */ + 0x2B,0x0E,0x03,0x02,0x1A, /* [ 360] OBJ_sha1 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05, /* [ 365] OBJ_sha1WithRSAEncryption */ + 0x2B,0x0E,0x03,0x02,0x0D, /* [ 374] OBJ_dsaWithSHA */ + 0x2B,0x0E,0x03,0x02,0x0C, /* [ 379] OBJ_dsa_2 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x0B, /* [ 384] OBJ_pbeWithSHA1AndRC2_CBC */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x0C, /* [ 393] OBJ_id_pbkdf2 */ + 0x2B,0x0E,0x03,0x02,0x1B, /* [ 402] OBJ_dsaWithSHA1_2 */ + 0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x01, /* [ 407] OBJ_netscape_cert_type */ + 0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x02, /* [ 416] OBJ_netscape_base_url */ + 0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x03, /* [ 425] OBJ_netscape_revocation_url */ + 0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x04, /* [ 434] OBJ_netscape_ca_revocation_url */ + 0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x07, /* [ 443] OBJ_netscape_renewal_url */ + 0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x08, /* [ 452] OBJ_netscape_ca_policy_url */ + 0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x0C, /* [ 461] OBJ_netscape_ssl_server_name */ + 0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x0D, /* [ 470] OBJ_netscape_comment */ + 0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x02,0x05, /* [ 479] OBJ_netscape_cert_sequence */ + 0x55,0x1D, /* [ 488] OBJ_id_ce */ + 0x55,0x1D,0x0E, /* [ 490] OBJ_subject_key_identifier */ + 0x55,0x1D,0x0F, /* [ 493] OBJ_key_usage */ + 0x55,0x1D,0x10, /* [ 496] OBJ_private_key_usage_period */ + 0x55,0x1D,0x11, /* [ 499] OBJ_subject_alt_name */ + 0x55,0x1D,0x12, /* [ 502] OBJ_issuer_alt_name */ + 0x55,0x1D,0x13, /* [ 505] OBJ_basic_constraints */ + 0x55,0x1D,0x14, /* [ 508] OBJ_crl_number */ + 0x55,0x1D,0x20, /* [ 511] OBJ_certificate_policies */ + 0x55,0x1D,0x23, /* [ 514] OBJ_authority_key_identifier */ + 0x2B,0x06,0x01,0x04,0x01,0x97,0x55,0x01,0x02, /* [ 517] OBJ_bf_cbc */ + 0x55,0x08,0x03,0x65, /* [ 526] OBJ_mdc2 */ + 0x55,0x08,0x03,0x64, /* [ 530] OBJ_mdc2WithRSA */ + 0x55,0x04,0x2A, /* [ 534] OBJ_givenName */ + 0x55,0x04,0x04, /* [ 537] OBJ_surname */ + 0x55,0x04,0x2B, /* [ 540] OBJ_initials */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x2C, /* [ 543] OBJ_uniqueIdentifier */ + 0x55,0x1D,0x1F, /* [ 553] OBJ_crl_distribution_points */ + 0x2B,0x0E,0x03,0x02,0x03, /* [ 556] OBJ_md5WithRSA */ + 0x55,0x04,0x05, /* [ 561] OBJ_serialNumber */ + 0x55,0x04,0x0C, /* [ 564] OBJ_title */ + 0x55,0x04,0x0D, /* [ 567] OBJ_description */ + 0x2A,0x86,0x48,0x86,0xF6,0x7D,0x07,0x42,0x0A, /* [ 570] OBJ_cast5_cbc */ + 0x2A,0x86,0x48,0x86,0xF6,0x7D,0x07,0x42,0x0C, /* [ 579] OBJ_pbeWithMD5AndCast5_CBC */ + 0x2A,0x86,0x48,0xCE,0x38,0x04,0x03, /* [ 588] OBJ_dsaWithSHA1 */ + 0x2B,0x0E,0x03,0x02,0x1D, /* [ 595] OBJ_sha1WithRSA */ + 0x2A,0x86,0x48,0xCE,0x38,0x04,0x01, /* [ 600] OBJ_dsa */ + 0x2B,0x24,0x03,0x02,0x01, /* [ 607] OBJ_ripemd160 */ + 0x2B,0x24,0x03,0x03,0x01,0x02, /* [ 612] OBJ_ripemd160WithRSA */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x03,0x08, /* [ 618] OBJ_rc5_cbc */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x08, /* [ 626] OBJ_zlib_compression */ + 0x55,0x1D,0x25, /* [ 637] OBJ_ext_key_usage */ + 0x2B,0x06,0x01,0x05,0x05,0x07, /* [ 640] OBJ_id_pkix */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x03, /* [ 646] OBJ_id_kp */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01, /* [ 653] OBJ_server_auth */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02, /* [ 661] OBJ_client_auth */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x03, /* [ 669] OBJ_code_sign */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x04, /* [ 677] OBJ_email_protect */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x08, /* [ 685] OBJ_time_stamp */ + 0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x02,0x01,0x15, /* [ 693] OBJ_ms_code_ind */ + 0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x02,0x01,0x16, /* [ 703] OBJ_ms_code_com */ + 0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x0A,0x03,0x01, /* [ 713] OBJ_ms_ctl_sign */ + 0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x0A,0x03,0x03, /* [ 723] OBJ_ms_sgc */ + 0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x0A,0x03,0x04, /* [ 733] OBJ_ms_efs */ + 0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x04,0x01, /* [ 743] OBJ_ns_sgc */ + 0x55,0x1D,0x1B, /* [ 752] OBJ_delta_crl */ + 0x55,0x1D,0x15, /* [ 755] OBJ_crl_reason */ + 0x55,0x1D,0x18, /* [ 758] OBJ_invalidity_date */ + 0x2B,0x65,0x01,0x04,0x01, /* [ 761] OBJ_sxnet */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x01,0x01, /* [ 766] OBJ_pbe_WithSHA1And128BitRC4 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x01,0x02, /* [ 776] OBJ_pbe_WithSHA1And40BitRC4 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x01,0x03, /* [ 786] OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x01,0x04, /* [ 796] OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x01,0x05, /* [ 806] OBJ_pbe_WithSHA1And128BitRC2_CBC */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x01,0x06, /* [ 816] OBJ_pbe_WithSHA1And40BitRC2_CBC */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x0A,0x01,0x01, /* [ 826] OBJ_keyBag */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x0A,0x01,0x02, /* [ 837] OBJ_pkcs8ShroudedKeyBag */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x0A,0x01,0x03, /* [ 848] OBJ_certBag */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x0A,0x01,0x04, /* [ 859] OBJ_crlBag */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x0A,0x01,0x05, /* [ 870] OBJ_secretBag */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x0A,0x01,0x06, /* [ 881] OBJ_safeContentsBag */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x14, /* [ 892] OBJ_friendlyName */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x15, /* [ 901] OBJ_localKeyID */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x16,0x01, /* [ 910] OBJ_x509Certificate */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x16,0x02, /* [ 920] OBJ_sdsiCertificate */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x17,0x01, /* [ 930] OBJ_x509Crl */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x0D, /* [ 940] OBJ_pbes2 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x0E, /* [ 949] OBJ_pbmac1 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x07, /* [ 958] OBJ_hmacWithSHA1 */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01, /* [ 966] OBJ_id_qt_cps */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x02, /* [ 974] OBJ_id_qt_unotice */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x0F, /* [ 982] OBJ_SMIMECapabilities */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x04, /* [ 991] OBJ_pbeWithMD2AndRC2_CBC */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x06, /* [ 1000] OBJ_pbeWithMD5AndRC2_CBC */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x0A, /* [ 1009] OBJ_pbeWithSHA1AndDES_CBC */ + 0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x02,0x01,0x0E, /* [ 1018] OBJ_ms_ext_req */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x0E, /* [ 1028] OBJ_ext_req */ + 0x55,0x04,0x29, /* [ 1037] OBJ_name */ + 0x55,0x04,0x2E, /* [ 1040] OBJ_dnQualifier */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x01, /* [ 1043] OBJ_id_pe */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x30, /* [ 1050] OBJ_id_ad */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01, /* [ 1057] OBJ_info_access */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01, /* [ 1065] OBJ_ad_OCSP */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x02, /* [ 1073] OBJ_ad_ca_issuers */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x09, /* [ 1081] OBJ_OCSP_sign */ + 0x2A, /* [ 1089] OBJ_member_body */ + 0x2A,0x86,0x48, /* [ 1090] OBJ_ISO_US */ + 0x2A,0x86,0x48,0xCE,0x38, /* [ 1093] OBJ_X9_57 */ + 0x2A,0x86,0x48,0xCE,0x38,0x04, /* [ 1098] OBJ_X9cm */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01, /* [ 1104] OBJ_pkcs1 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05, /* [ 1112] OBJ_pkcs5 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10, /* [ 1120] OBJ_SMIME */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00, /* [ 1129] OBJ_id_smime_mod */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01, /* [ 1139] OBJ_id_smime_ct */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02, /* [ 1149] OBJ_id_smime_aa */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03, /* [ 1159] OBJ_id_smime_alg */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x04, /* [ 1169] OBJ_id_smime_cd */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x05, /* [ 1179] OBJ_id_smime_spq */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x06, /* [ 1189] OBJ_id_smime_cti */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x01, /* [ 1199] OBJ_id_smime_mod_cms */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x02, /* [ 1210] OBJ_id_smime_mod_ess */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x03, /* [ 1221] OBJ_id_smime_mod_oid */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x04, /* [ 1232] OBJ_id_smime_mod_msg_v3 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x05, /* [ 1243] OBJ_id_smime_mod_ets_eSignature_88 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x06, /* [ 1254] OBJ_id_smime_mod_ets_eSignature_97 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x07, /* [ 1265] OBJ_id_smime_mod_ets_eSigPolicy_88 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x08, /* [ 1276] OBJ_id_smime_mod_ets_eSigPolicy_97 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x01, /* [ 1287] OBJ_id_smime_ct_receipt */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x02, /* [ 1298] OBJ_id_smime_ct_authData */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x03, /* [ 1309] OBJ_id_smime_ct_publishCert */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x04, /* [ 1320] OBJ_id_smime_ct_TSTInfo */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x05, /* [ 1331] OBJ_id_smime_ct_TDTInfo */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x06, /* [ 1342] OBJ_id_smime_ct_contentInfo */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x07, /* [ 1353] OBJ_id_smime_ct_DVCSRequestData */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x08, /* [ 1364] OBJ_id_smime_ct_DVCSResponseData */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x01, /* [ 1375] OBJ_id_smime_aa_receiptRequest */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x02, /* [ 1386] OBJ_id_smime_aa_securityLabel */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x03, /* [ 1397] OBJ_id_smime_aa_mlExpandHistory */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x04, /* [ 1408] OBJ_id_smime_aa_contentHint */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x05, /* [ 1419] OBJ_id_smime_aa_msgSigDigest */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x06, /* [ 1430] OBJ_id_smime_aa_encapContentType */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x07, /* [ 1441] OBJ_id_smime_aa_contentIdentifier */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x08, /* [ 1452] OBJ_id_smime_aa_macValue */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x09, /* [ 1463] OBJ_id_smime_aa_equivalentLabels */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x0A, /* [ 1474] OBJ_id_smime_aa_contentReference */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x0B, /* [ 1485] OBJ_id_smime_aa_encrypKeyPref */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x0C, /* [ 1496] OBJ_id_smime_aa_signingCertificate */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x0D, /* [ 1507] OBJ_id_smime_aa_smimeEncryptCerts */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x0E, /* [ 1518] OBJ_id_smime_aa_timeStampToken */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x0F, /* [ 1529] OBJ_id_smime_aa_ets_sigPolicyId */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x10, /* [ 1540] OBJ_id_smime_aa_ets_commitmentType */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x11, /* [ 1551] OBJ_id_smime_aa_ets_signerLocation */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x12, /* [ 1562] OBJ_id_smime_aa_ets_signerAttr */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x13, /* [ 1573] OBJ_id_smime_aa_ets_otherSigCert */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x14, /* [ 1584] OBJ_id_smime_aa_ets_contentTimestamp */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x15, /* [ 1595] OBJ_id_smime_aa_ets_CertificateRefs */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x16, /* [ 1606] OBJ_id_smime_aa_ets_RevocationRefs */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x17, /* [ 1617] OBJ_id_smime_aa_ets_certValues */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x18, /* [ 1628] OBJ_id_smime_aa_ets_revocationValues */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x19, /* [ 1639] OBJ_id_smime_aa_ets_escTimeStamp */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x1A, /* [ 1650] OBJ_id_smime_aa_ets_certCRLTimestamp */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x1B, /* [ 1661] OBJ_id_smime_aa_ets_archiveTimeStamp */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x1C, /* [ 1672] OBJ_id_smime_aa_signatureType */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x1D, /* [ 1683] OBJ_id_smime_aa_dvcs_dvc */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x01, /* [ 1694] OBJ_id_smime_alg_ESDHwith3DES */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x02, /* [ 1705] OBJ_id_smime_alg_ESDHwithRC2 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x03, /* [ 1716] OBJ_id_smime_alg_3DESwrap */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x04, /* [ 1727] OBJ_id_smime_alg_RC2wrap */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x05, /* [ 1738] OBJ_id_smime_alg_ESDH */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x06, /* [ 1749] OBJ_id_smime_alg_CMS3DESwrap */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x07, /* [ 1760] OBJ_id_smime_alg_CMSRC2wrap */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x04,0x01, /* [ 1771] OBJ_id_smime_cd_ldap */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x05,0x01, /* [ 1782] OBJ_id_smime_spq_ets_sqt_uri */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x05,0x02, /* [ 1793] OBJ_id_smime_spq_ets_sqt_unotice */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x06,0x01, /* [ 1804] OBJ_id_smime_cti_ets_proofOfOrigin */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x06,0x02, /* [ 1815] OBJ_id_smime_cti_ets_proofOfReceipt */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x06,0x03, /* [ 1826] OBJ_id_smime_cti_ets_proofOfDelivery */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x06,0x04, /* [ 1837] OBJ_id_smime_cti_ets_proofOfSender */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x06,0x05, /* [ 1848] OBJ_id_smime_cti_ets_proofOfApproval */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x06,0x06, /* [ 1859] OBJ_id_smime_cti_ets_proofOfCreation */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x04, /* [ 1870] OBJ_md4 */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x00, /* [ 1878] OBJ_id_pkix_mod */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x02, /* [ 1885] OBJ_id_qt */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x04, /* [ 1892] OBJ_id_it */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x05, /* [ 1899] OBJ_id_pkip */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x06, /* [ 1906] OBJ_id_alg */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x07, /* [ 1913] OBJ_id_cmc */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x08, /* [ 1920] OBJ_id_on */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x09, /* [ 1927] OBJ_id_pda */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x0A, /* [ 1934] OBJ_id_aca */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x0B, /* [ 1941] OBJ_id_qcs */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x0C, /* [ 1948] OBJ_id_cct */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x01, /* [ 1955] OBJ_id_pkix1_explicit_88 */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x02, /* [ 1963] OBJ_id_pkix1_implicit_88 */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x03, /* [ 1971] OBJ_id_pkix1_explicit_93 */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x04, /* [ 1979] OBJ_id_pkix1_implicit_93 */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x05, /* [ 1987] OBJ_id_mod_crmf */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x06, /* [ 1995] OBJ_id_mod_cmc */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x07, /* [ 2003] OBJ_id_mod_kea_profile_88 */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x08, /* [ 2011] OBJ_id_mod_kea_profile_93 */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x09, /* [ 2019] OBJ_id_mod_cmp */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x0A, /* [ 2027] OBJ_id_mod_qualified_cert_88 */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x0B, /* [ 2035] OBJ_id_mod_qualified_cert_93 */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x0C, /* [ 2043] OBJ_id_mod_attribute_cert */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x0D, /* [ 2051] OBJ_id_mod_timestamp_protocol */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x0E, /* [ 2059] OBJ_id_mod_ocsp */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x0F, /* [ 2067] OBJ_id_mod_dvcs */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x10, /* [ 2075] OBJ_id_mod_cmp2000 */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x02, /* [ 2083] OBJ_biometricInfo */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x03, /* [ 2091] OBJ_qcStatements */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x04, /* [ 2099] OBJ_ac_auditEntity */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x05, /* [ 2107] OBJ_ac_targeting */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x06, /* [ 2115] OBJ_aaControls */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x07, /* [ 2123] OBJ_sbgp_ipAddrBlock */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x08, /* [ 2131] OBJ_sbgp_autonomousSysNum */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x09, /* [ 2139] OBJ_sbgp_routerIdentifier */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x03, /* [ 2147] OBJ_textNotice */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x05, /* [ 2155] OBJ_ipsecEndSystem */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x06, /* [ 2163] OBJ_ipsecTunnel */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x07, /* [ 2171] OBJ_ipsecUser */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x0A, /* [ 2179] OBJ_dvcs */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x01, /* [ 2187] OBJ_id_it_caProtEncCert */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x02, /* [ 2195] OBJ_id_it_signKeyPairTypes */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x03, /* [ 2203] OBJ_id_it_encKeyPairTypes */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x04, /* [ 2211] OBJ_id_it_preferredSymmAlg */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x05, /* [ 2219] OBJ_id_it_caKeyUpdateInfo */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x06, /* [ 2227] OBJ_id_it_currentCRL */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x07, /* [ 2235] OBJ_id_it_unsupportedOIDs */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x08, /* [ 2243] OBJ_id_it_subscriptionRequest */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x09, /* [ 2251] OBJ_id_it_subscriptionResponse */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x0A, /* [ 2259] OBJ_id_it_keyPairParamReq */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x0B, /* [ 2267] OBJ_id_it_keyPairParamRep */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x0C, /* [ 2275] OBJ_id_it_revPassphrase */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x0D, /* [ 2283] OBJ_id_it_implicitConfirm */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x0E, /* [ 2291] OBJ_id_it_confirmWaitTime */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x0F, /* [ 2299] OBJ_id_it_origPKIMessage */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01, /* [ 2307] OBJ_id_regCtrl */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x02, /* [ 2315] OBJ_id_regInfo */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01,0x01, /* [ 2323] OBJ_id_regCtrl_regToken */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01,0x02, /* [ 2332] OBJ_id_regCtrl_authenticator */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01,0x03, /* [ 2341] OBJ_id_regCtrl_pkiPublicationInfo */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01,0x04, /* [ 2350] OBJ_id_regCtrl_pkiArchiveOptions */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01,0x05, /* [ 2359] OBJ_id_regCtrl_oldCertID */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01,0x06, /* [ 2368] OBJ_id_regCtrl_protocolEncrKey */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x02,0x01, /* [ 2377] OBJ_id_regInfo_utf8Pairs */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x02,0x02, /* [ 2386] OBJ_id_regInfo_certReq */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x06,0x01, /* [ 2395] OBJ_id_alg_des40 */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x06,0x02, /* [ 2403] OBJ_id_alg_noSignature */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x06,0x03, /* [ 2411] OBJ_id_alg_dh_sig_hmac_sha1 */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x06,0x04, /* [ 2419] OBJ_id_alg_dh_pop */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x01, /* [ 2427] OBJ_id_cmc_statusInfo */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x02, /* [ 2435] OBJ_id_cmc_identification */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x03, /* [ 2443] OBJ_id_cmc_identityProof */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x04, /* [ 2451] OBJ_id_cmc_dataReturn */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x05, /* [ 2459] OBJ_id_cmc_transactionId */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x06, /* [ 2467] OBJ_id_cmc_senderNonce */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x07, /* [ 2475] OBJ_id_cmc_recipientNonce */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x08, /* [ 2483] OBJ_id_cmc_addExtensions */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x09, /* [ 2491] OBJ_id_cmc_encryptedPOP */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x0A, /* [ 2499] OBJ_id_cmc_decryptedPOP */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x0B, /* [ 2507] OBJ_id_cmc_lraPOPWitness */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x0F, /* [ 2515] OBJ_id_cmc_getCert */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x10, /* [ 2523] OBJ_id_cmc_getCRL */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x11, /* [ 2531] OBJ_id_cmc_revokeRequest */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x12, /* [ 2539] OBJ_id_cmc_regInfo */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x13, /* [ 2547] OBJ_id_cmc_responseInfo */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x15, /* [ 2555] OBJ_id_cmc_queryPending */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x16, /* [ 2563] OBJ_id_cmc_popLinkRandom */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x17, /* [ 2571] OBJ_id_cmc_popLinkWitness */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x18, /* [ 2579] OBJ_id_cmc_confirmCertAcceptance */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x08,0x01, /* [ 2587] OBJ_id_on_personalData */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x09,0x01, /* [ 2595] OBJ_id_pda_dateOfBirth */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x09,0x02, /* [ 2603] OBJ_id_pda_placeOfBirth */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x09,0x03, /* [ 2611] OBJ_id_pda_gender */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x09,0x04, /* [ 2619] OBJ_id_pda_countryOfCitizenship */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x09,0x05, /* [ 2627] OBJ_id_pda_countryOfResidence */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x0A,0x01, /* [ 2635] OBJ_id_aca_authenticationInfo */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x0A,0x02, /* [ 2643] OBJ_id_aca_accessIdentity */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x0A,0x03, /* [ 2651] OBJ_id_aca_chargingIdentity */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x0A,0x04, /* [ 2659] OBJ_id_aca_group */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x0A,0x05, /* [ 2667] OBJ_id_aca_role */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x0B,0x01, /* [ 2675] OBJ_id_qcs_pkixQCSyntax_v1 */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x0C,0x01, /* [ 2683] OBJ_id_cct_crs */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x0C,0x02, /* [ 2691] OBJ_id_cct_PKIData */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x0C,0x03, /* [ 2699] OBJ_id_cct_PKIResponse */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x03, /* [ 2707] OBJ_ad_timeStamping */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x04, /* [ 2715] OBJ_ad_dvcs */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x01, /* [ 2723] OBJ_id_pkix_OCSP_basic */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x02, /* [ 2732] OBJ_id_pkix_OCSP_Nonce */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x03, /* [ 2741] OBJ_id_pkix_OCSP_CrlID */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x04, /* [ 2750] OBJ_id_pkix_OCSP_acceptableResponses */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x05, /* [ 2759] OBJ_id_pkix_OCSP_noCheck */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x06, /* [ 2768] OBJ_id_pkix_OCSP_archiveCutoff */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x07, /* [ 2777] OBJ_id_pkix_OCSP_serviceLocator */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x08, /* [ 2786] OBJ_id_pkix_OCSP_extendedStatus */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x09, /* [ 2795] OBJ_id_pkix_OCSP_valid */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x0A, /* [ 2804] OBJ_id_pkix_OCSP_path */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x0B, /* [ 2813] OBJ_id_pkix_OCSP_trustRoot */ + 0x2B,0x0E,0x03,0x02, /* [ 2822] OBJ_algorithm */ + 0x2B,0x0E,0x03,0x02,0x0B, /* [ 2826] OBJ_rsaSignature */ + 0x55,0x08, /* [ 2831] OBJ_X500algorithms */ + 0x2B, /* [ 2833] OBJ_org */ + 0x2B,0x06, /* [ 2834] OBJ_dod */ + 0x2B,0x06,0x01, /* [ 2836] OBJ_iana */ + 0x2B,0x06,0x01,0x01, /* [ 2839] OBJ_Directory */ + 0x2B,0x06,0x01,0x02, /* [ 2843] OBJ_Management */ + 0x2B,0x06,0x01,0x03, /* [ 2847] OBJ_Experimental */ + 0x2B,0x06,0x01,0x04, /* [ 2851] OBJ_Private */ + 0x2B,0x06,0x01,0x05, /* [ 2855] OBJ_Security */ + 0x2B,0x06,0x01,0x06, /* [ 2859] OBJ_SNMPv2 */ + 0x2B,0x06,0x01,0x07, /* [ 2863] OBJ_Mail */ + 0x2B,0x06,0x01,0x04,0x01, /* [ 2867] OBJ_Enterprises */ + 0x2B,0x06,0x01,0x04,0x01,0x8B,0x3A,0x82,0x58, /* [ 2872] OBJ_dcObject */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x19, /* [ 2881] OBJ_domainComponent */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x0D, /* [ 2891] OBJ_Domain */ + 0x55,0x01,0x05, /* [ 2901] OBJ_selected_attribute_types */ + 0x55,0x01,0x05,0x37, /* [ 2904] OBJ_clearance */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x03, /* [ 2908] OBJ_md4WithRSAEncryption */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x0A, /* [ 2917] OBJ_ac_proxying */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x0B, /* [ 2925] OBJ_sinfo_access */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x0A,0x06, /* [ 2933] OBJ_id_aca_encAttrs */ + 0x55,0x04,0x48, /* [ 2941] OBJ_role */ + 0x55,0x1D,0x24, /* [ 2944] OBJ_policy_constraints */ + 0x55,0x1D,0x37, /* [ 2947] OBJ_target_information */ + 0x55,0x1D,0x38, /* [ 2950] OBJ_no_rev_avail */ + 0x2A,0x86,0x48,0xCE,0x3D, /* [ 2953] OBJ_ansi_X9_62 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x01,0x01, /* [ 2958] OBJ_X9_62_prime_field */ + 0x2A,0x86,0x48,0xCE,0x3D,0x01,0x02, /* [ 2965] OBJ_X9_62_characteristic_two_field */ + 0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01, /* [ 2972] OBJ_X9_62_id_ecPublicKey */ + 0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x01, /* [ 2979] OBJ_X9_62_prime192v1 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x02, /* [ 2987] OBJ_X9_62_prime192v2 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x03, /* [ 2995] OBJ_X9_62_prime192v3 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x04, /* [ 3003] OBJ_X9_62_prime239v1 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x05, /* [ 3011] OBJ_X9_62_prime239v2 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x06, /* [ 3019] OBJ_X9_62_prime239v3 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07, /* [ 3027] OBJ_X9_62_prime256v1 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x04,0x01, /* [ 3035] OBJ_ecdsa_with_SHA1 */ + 0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x11,0x01, /* [ 3042] OBJ_ms_csp_name */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x01, /* [ 3051] OBJ_aes_128_ecb */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x02, /* [ 3060] OBJ_aes_128_cbc */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x03, /* [ 3069] OBJ_aes_128_ofb128 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x04, /* [ 3078] OBJ_aes_128_cfb128 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x15, /* [ 3087] OBJ_aes_192_ecb */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x16, /* [ 3096] OBJ_aes_192_cbc */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x17, /* [ 3105] OBJ_aes_192_ofb128 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x18, /* [ 3114] OBJ_aes_192_cfb128 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x29, /* [ 3123] OBJ_aes_256_ecb */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x2A, /* [ 3132] OBJ_aes_256_cbc */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x2B, /* [ 3141] OBJ_aes_256_ofb128 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x2C, /* [ 3150] OBJ_aes_256_cfb128 */ + 0x55,0x1D,0x17, /* [ 3159] OBJ_hold_instruction_code */ + 0x2A,0x86,0x48,0xCE,0x38,0x02,0x01, /* [ 3162] OBJ_hold_instruction_none */ + 0x2A,0x86,0x48,0xCE,0x38,0x02,0x02, /* [ 3169] OBJ_hold_instruction_call_issuer */ + 0x2A,0x86,0x48,0xCE,0x38,0x02,0x03, /* [ 3176] OBJ_hold_instruction_reject */ + 0x09, /* [ 3183] OBJ_data */ + 0x09,0x92,0x26, /* [ 3184] OBJ_pss */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C, /* [ 3187] OBJ_ucl */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64, /* [ 3194] OBJ_pilot */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01, /* [ 3202] OBJ_pilotAttributeType */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x03, /* [ 3211] OBJ_pilotAttributeSyntax */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04, /* [ 3220] OBJ_pilotObjectClass */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x0A, /* [ 3229] OBJ_pilotGroups */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x03,0x04, /* [ 3238] OBJ_iA5StringSyntax */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x03,0x05, /* [ 3248] OBJ_caseIgnoreIA5StringSyntax */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x03, /* [ 3258] OBJ_pilotObject */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x04, /* [ 3268] OBJ_pilotPerson */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x05, /* [ 3278] OBJ_account */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x06, /* [ 3288] OBJ_document */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x07, /* [ 3298] OBJ_room */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x09, /* [ 3308] OBJ_documentSeries */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x0E, /* [ 3318] OBJ_rFC822localPart */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x0F, /* [ 3328] OBJ_dNSDomain */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x11, /* [ 3338] OBJ_domainRelatedObject */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x12, /* [ 3348] OBJ_friendlyCountry */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x13, /* [ 3358] OBJ_simpleSecurityObject */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x14, /* [ 3368] OBJ_pilotOrganization */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x15, /* [ 3378] OBJ_pilotDSA */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x16, /* [ 3388] OBJ_qualityLabelledData */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x01, /* [ 3398] OBJ_userId */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x02, /* [ 3408] OBJ_textEncodedORAddress */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x03, /* [ 3418] OBJ_rfc822Mailbox */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x04, /* [ 3428] OBJ_info */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x05, /* [ 3438] OBJ_favouriteDrink */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x06, /* [ 3448] OBJ_roomNumber */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x07, /* [ 3458] OBJ_photo */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x08, /* [ 3468] OBJ_userClass */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x09, /* [ 3478] OBJ_host */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x0A, /* [ 3488] OBJ_manager */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x0B, /* [ 3498] OBJ_documentIdentifier */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x0C, /* [ 3508] OBJ_documentTitle */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x0D, /* [ 3518] OBJ_documentVersion */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x0E, /* [ 3528] OBJ_documentAuthor */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x0F, /* [ 3538] OBJ_documentLocation */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x14, /* [ 3548] OBJ_homeTelephoneNumber */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x15, /* [ 3558] OBJ_secretary */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x16, /* [ 3568] OBJ_otherMailbox */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x17, /* [ 3578] OBJ_lastModifiedTime */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x18, /* [ 3588] OBJ_lastModifiedBy */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x1A, /* [ 3598] OBJ_aRecord */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x1B, /* [ 3608] OBJ_pilotAttributeType27 */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x1C, /* [ 3618] OBJ_mXRecord */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x1D, /* [ 3628] OBJ_nSRecord */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x1E, /* [ 3638] OBJ_sOARecord */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x1F, /* [ 3648] OBJ_cNAMERecord */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x25, /* [ 3658] OBJ_associatedDomain */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x26, /* [ 3668] OBJ_associatedName */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x27, /* [ 3678] OBJ_homePostalAddress */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x28, /* [ 3688] OBJ_personalTitle */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x29, /* [ 3698] OBJ_mobileTelephoneNumber */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x2A, /* [ 3708] OBJ_pagerTelephoneNumber */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x2B, /* [ 3718] OBJ_friendlyCountryName */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x2D, /* [ 3728] OBJ_organizationalStatus */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x2E, /* [ 3738] OBJ_janetMailbox */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x2F, /* [ 3748] OBJ_mailPreferenceOption */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x30, /* [ 3758] OBJ_buildingName */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x31, /* [ 3768] OBJ_dSAQuality */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x32, /* [ 3778] OBJ_singleLevelQuality */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x33, /* [ 3788] OBJ_subtreeMinimumQuality */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x34, /* [ 3798] OBJ_subtreeMaximumQuality */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x35, /* [ 3808] OBJ_personalSignature */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x36, /* [ 3818] OBJ_dITRedirect */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x37, /* [ 3828] OBJ_audio */ + 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x38, /* [ 3838] OBJ_documentPublisher */ + 0x55,0x04,0x2D, /* [ 3848] OBJ_x500UniqueIdentifier */ + 0x2B,0x06,0x01,0x07,0x01, /* [ 3851] OBJ_mime_mhs */ + 0x2B,0x06,0x01,0x07,0x01,0x01, /* [ 3856] OBJ_mime_mhs_headings */ + 0x2B,0x06,0x01,0x07,0x01,0x02, /* [ 3862] OBJ_mime_mhs_bodies */ + 0x2B,0x06,0x01,0x07,0x01,0x01,0x01, /* [ 3868] OBJ_id_hex_partial_message */ + 0x2B,0x06,0x01,0x07,0x01,0x01,0x02, /* [ 3875] OBJ_id_hex_multipart_message */ + 0x55,0x04,0x2C, /* [ 3882] OBJ_generationQualifier */ + 0x55,0x04,0x41, /* [ 3885] OBJ_pseudonym */ + 0x67,0x2A, /* [ 3888] OBJ_id_set */ + 0x67,0x2A,0x00, /* [ 3890] OBJ_set_ctype */ + 0x67,0x2A,0x01, /* [ 3893] OBJ_set_msgExt */ + 0x67,0x2A,0x03, /* [ 3896] OBJ_set_attr */ + 0x67,0x2A,0x05, /* [ 3899] OBJ_set_policy */ + 0x67,0x2A,0x07, /* [ 3902] OBJ_set_certExt */ + 0x67,0x2A,0x08, /* [ 3905] OBJ_set_brand */ + 0x67,0x2A,0x00,0x00, /* [ 3908] OBJ_setct_PANData */ + 0x67,0x2A,0x00,0x01, /* [ 3912] OBJ_setct_PANToken */ + 0x67,0x2A,0x00,0x02, /* [ 3916] OBJ_setct_PANOnly */ + 0x67,0x2A,0x00,0x03, /* [ 3920] OBJ_setct_OIData */ + 0x67,0x2A,0x00,0x04, /* [ 3924] OBJ_setct_PI */ + 0x67,0x2A,0x00,0x05, /* [ 3928] OBJ_setct_PIData */ + 0x67,0x2A,0x00,0x06, /* [ 3932] OBJ_setct_PIDataUnsigned */ + 0x67,0x2A,0x00,0x07, /* [ 3936] OBJ_setct_HODInput */ + 0x67,0x2A,0x00,0x08, /* [ 3940] OBJ_setct_AuthResBaggage */ + 0x67,0x2A,0x00,0x09, /* [ 3944] OBJ_setct_AuthRevReqBaggage */ + 0x67,0x2A,0x00,0x0A, /* [ 3948] OBJ_setct_AuthRevResBaggage */ + 0x67,0x2A,0x00,0x0B, /* [ 3952] OBJ_setct_CapTokenSeq */ + 0x67,0x2A,0x00,0x0C, /* [ 3956] OBJ_setct_PInitResData */ + 0x67,0x2A,0x00,0x0D, /* [ 3960] OBJ_setct_PI_TBS */ + 0x67,0x2A,0x00,0x0E, /* [ 3964] OBJ_setct_PResData */ + 0x67,0x2A,0x00,0x10, /* [ 3968] OBJ_setct_AuthReqTBS */ + 0x67,0x2A,0x00,0x11, /* [ 3972] OBJ_setct_AuthResTBS */ + 0x67,0x2A,0x00,0x12, /* [ 3976] OBJ_setct_AuthResTBSX */ + 0x67,0x2A,0x00,0x13, /* [ 3980] OBJ_setct_AuthTokenTBS */ + 0x67,0x2A,0x00,0x14, /* [ 3984] OBJ_setct_CapTokenData */ + 0x67,0x2A,0x00,0x15, /* [ 3988] OBJ_setct_CapTokenTBS */ + 0x67,0x2A,0x00,0x16, /* [ 3992] OBJ_setct_AcqCardCodeMsg */ + 0x67,0x2A,0x00,0x17, /* [ 3996] OBJ_setct_AuthRevReqTBS */ + 0x67,0x2A,0x00,0x18, /* [ 4000] OBJ_setct_AuthRevResData */ + 0x67,0x2A,0x00,0x19, /* [ 4004] OBJ_setct_AuthRevResTBS */ + 0x67,0x2A,0x00,0x1A, /* [ 4008] OBJ_setct_CapReqTBS */ + 0x67,0x2A,0x00,0x1B, /* [ 4012] OBJ_setct_CapReqTBSX */ + 0x67,0x2A,0x00,0x1C, /* [ 4016] OBJ_setct_CapResData */ + 0x67,0x2A,0x00,0x1D, /* [ 4020] OBJ_setct_CapRevReqTBS */ + 0x67,0x2A,0x00,0x1E, /* [ 4024] OBJ_setct_CapRevReqTBSX */ + 0x67,0x2A,0x00,0x1F, /* [ 4028] OBJ_setct_CapRevResData */ + 0x67,0x2A,0x00,0x20, /* [ 4032] OBJ_setct_CredReqTBS */ + 0x67,0x2A,0x00,0x21, /* [ 4036] OBJ_setct_CredReqTBSX */ + 0x67,0x2A,0x00,0x22, /* [ 4040] OBJ_setct_CredResData */ + 0x67,0x2A,0x00,0x23, /* [ 4044] OBJ_setct_CredRevReqTBS */ + 0x67,0x2A,0x00,0x24, /* [ 4048] OBJ_setct_CredRevReqTBSX */ + 0x67,0x2A,0x00,0x25, /* [ 4052] OBJ_setct_CredRevResData */ + 0x67,0x2A,0x00,0x26, /* [ 4056] OBJ_setct_PCertReqData */ + 0x67,0x2A,0x00,0x27, /* [ 4060] OBJ_setct_PCertResTBS */ + 0x67,0x2A,0x00,0x28, /* [ 4064] OBJ_setct_BatchAdminReqData */ + 0x67,0x2A,0x00,0x29, /* [ 4068] OBJ_setct_BatchAdminResData */ + 0x67,0x2A,0x00,0x2A, /* [ 4072] OBJ_setct_CardCInitResTBS */ + 0x67,0x2A,0x00,0x2B, /* [ 4076] OBJ_setct_MeAqCInitResTBS */ + 0x67,0x2A,0x00,0x2C, /* [ 4080] OBJ_setct_RegFormResTBS */ + 0x67,0x2A,0x00,0x2D, /* [ 4084] OBJ_setct_CertReqData */ + 0x67,0x2A,0x00,0x2E, /* [ 4088] OBJ_setct_CertReqTBS */ + 0x67,0x2A,0x00,0x2F, /* [ 4092] OBJ_setct_CertResData */ + 0x67,0x2A,0x00,0x30, /* [ 4096] OBJ_setct_CertInqReqTBS */ + 0x67,0x2A,0x00,0x31, /* [ 4100] OBJ_setct_ErrorTBS */ + 0x67,0x2A,0x00,0x32, /* [ 4104] OBJ_setct_PIDualSignedTBE */ + 0x67,0x2A,0x00,0x33, /* [ 4108] OBJ_setct_PIUnsignedTBE */ + 0x67,0x2A,0x00,0x34, /* [ 4112] OBJ_setct_AuthReqTBE */ + 0x67,0x2A,0x00,0x35, /* [ 4116] OBJ_setct_AuthResTBE */ + 0x67,0x2A,0x00,0x36, /* [ 4120] OBJ_setct_AuthResTBEX */ + 0x67,0x2A,0x00,0x37, /* [ 4124] OBJ_setct_AuthTokenTBE */ + 0x67,0x2A,0x00,0x38, /* [ 4128] OBJ_setct_CapTokenTBE */ + 0x67,0x2A,0x00,0x39, /* [ 4132] OBJ_setct_CapTokenTBEX */ + 0x67,0x2A,0x00,0x3A, /* [ 4136] OBJ_setct_AcqCardCodeMsgTBE */ + 0x67,0x2A,0x00,0x3B, /* [ 4140] OBJ_setct_AuthRevReqTBE */ + 0x67,0x2A,0x00,0x3C, /* [ 4144] OBJ_setct_AuthRevResTBE */ + 0x67,0x2A,0x00,0x3D, /* [ 4148] OBJ_setct_AuthRevResTBEB */ + 0x67,0x2A,0x00,0x3E, /* [ 4152] OBJ_setct_CapReqTBE */ + 0x67,0x2A,0x00,0x3F, /* [ 4156] OBJ_setct_CapReqTBEX */ + 0x67,0x2A,0x00,0x40, /* [ 4160] OBJ_setct_CapResTBE */ + 0x67,0x2A,0x00,0x41, /* [ 4164] OBJ_setct_CapRevReqTBE */ + 0x67,0x2A,0x00,0x42, /* [ 4168] OBJ_setct_CapRevReqTBEX */ + 0x67,0x2A,0x00,0x43, /* [ 4172] OBJ_setct_CapRevResTBE */ + 0x67,0x2A,0x00,0x44, /* [ 4176] OBJ_setct_CredReqTBE */ + 0x67,0x2A,0x00,0x45, /* [ 4180] OBJ_setct_CredReqTBEX */ + 0x67,0x2A,0x00,0x46, /* [ 4184] OBJ_setct_CredResTBE */ + 0x67,0x2A,0x00,0x47, /* [ 4188] OBJ_setct_CredRevReqTBE */ + 0x67,0x2A,0x00,0x48, /* [ 4192] OBJ_setct_CredRevReqTBEX */ + 0x67,0x2A,0x00,0x49, /* [ 4196] OBJ_setct_CredRevResTBE */ + 0x67,0x2A,0x00,0x4A, /* [ 4200] OBJ_setct_BatchAdminReqTBE */ + 0x67,0x2A,0x00,0x4B, /* [ 4204] OBJ_setct_BatchAdminResTBE */ + 0x67,0x2A,0x00,0x4C, /* [ 4208] OBJ_setct_RegFormReqTBE */ + 0x67,0x2A,0x00,0x4D, /* [ 4212] OBJ_setct_CertReqTBE */ + 0x67,0x2A,0x00,0x4E, /* [ 4216] OBJ_setct_CertReqTBEX */ + 0x67,0x2A,0x00,0x4F, /* [ 4220] OBJ_setct_CertResTBE */ + 0x67,0x2A,0x00,0x50, /* [ 4224] OBJ_setct_CRLNotificationTBS */ + 0x67,0x2A,0x00,0x51, /* [ 4228] OBJ_setct_CRLNotificationResTBS */ + 0x67,0x2A,0x00,0x52, /* [ 4232] OBJ_setct_BCIDistributionTBS */ + 0x67,0x2A,0x01,0x01, /* [ 4236] OBJ_setext_genCrypt */ + 0x67,0x2A,0x01,0x03, /* [ 4240] OBJ_setext_miAuth */ + 0x67,0x2A,0x01,0x04, /* [ 4244] OBJ_setext_pinSecure */ + 0x67,0x2A,0x01,0x05, /* [ 4248] OBJ_setext_pinAny */ + 0x67,0x2A,0x01,0x07, /* [ 4252] OBJ_setext_track2 */ + 0x67,0x2A,0x01,0x08, /* [ 4256] OBJ_setext_cv */ + 0x67,0x2A,0x05,0x00, /* [ 4260] OBJ_set_policy_root */ + 0x67,0x2A,0x07,0x00, /* [ 4264] OBJ_setCext_hashedRoot */ + 0x67,0x2A,0x07,0x01, /* [ 4268] OBJ_setCext_certType */ + 0x67,0x2A,0x07,0x02, /* [ 4272] OBJ_setCext_merchData */ + 0x67,0x2A,0x07,0x03, /* [ 4276] OBJ_setCext_cCertRequired */ + 0x67,0x2A,0x07,0x04, /* [ 4280] OBJ_setCext_tunneling */ + 0x67,0x2A,0x07,0x05, /* [ 4284] OBJ_setCext_setExt */ + 0x67,0x2A,0x07,0x06, /* [ 4288] OBJ_setCext_setQualf */ + 0x67,0x2A,0x07,0x07, /* [ 4292] OBJ_setCext_PGWYcapabilities */ + 0x67,0x2A,0x07,0x08, /* [ 4296] OBJ_setCext_TokenIdentifier */ + 0x67,0x2A,0x07,0x09, /* [ 4300] OBJ_setCext_Track2Data */ + 0x67,0x2A,0x07,0x0A, /* [ 4304] OBJ_setCext_TokenType */ + 0x67,0x2A,0x07,0x0B, /* [ 4308] OBJ_setCext_IssuerCapabilities */ + 0x67,0x2A,0x03,0x00, /* [ 4312] OBJ_setAttr_Cert */ + 0x67,0x2A,0x03,0x01, /* [ 4316] OBJ_setAttr_PGWYcap */ + 0x67,0x2A,0x03,0x02, /* [ 4320] OBJ_setAttr_TokenType */ + 0x67,0x2A,0x03,0x03, /* [ 4324] OBJ_setAttr_IssCap */ + 0x67,0x2A,0x03,0x00,0x00, /* [ 4328] OBJ_set_rootKeyThumb */ + 0x67,0x2A,0x03,0x00,0x01, /* [ 4333] OBJ_set_addPolicy */ + 0x67,0x2A,0x03,0x02,0x01, /* [ 4338] OBJ_setAttr_Token_EMV */ + 0x67,0x2A,0x03,0x02,0x02, /* [ 4343] OBJ_setAttr_Token_B0Prime */ + 0x67,0x2A,0x03,0x03,0x03, /* [ 4348] OBJ_setAttr_IssCap_CVM */ + 0x67,0x2A,0x03,0x03,0x04, /* [ 4353] OBJ_setAttr_IssCap_T2 */ + 0x67,0x2A,0x03,0x03,0x05, /* [ 4358] OBJ_setAttr_IssCap_Sig */ + 0x67,0x2A,0x03,0x03,0x03,0x01, /* [ 4363] OBJ_setAttr_GenCryptgrm */ + 0x67,0x2A,0x03,0x03,0x04,0x01, /* [ 4369] OBJ_setAttr_T2Enc */ + 0x67,0x2A,0x03,0x03,0x04,0x02, /* [ 4375] OBJ_setAttr_T2cleartxt */ + 0x67,0x2A,0x03,0x03,0x05,0x01, /* [ 4381] OBJ_setAttr_TokICCsig */ + 0x67,0x2A,0x03,0x03,0x05,0x02, /* [ 4387] OBJ_setAttr_SecDevSig */ + 0x67,0x2A,0x08,0x01, /* [ 4393] OBJ_set_brand_IATA_ATA */ + 0x67,0x2A,0x08,0x1E, /* [ 4397] OBJ_set_brand_Diners */ + 0x67,0x2A,0x08,0x22, /* [ 4401] OBJ_set_brand_AmericanExpress */ + 0x67,0x2A,0x08,0x23, /* [ 4405] OBJ_set_brand_JCB */ + 0x67,0x2A,0x08,0x04, /* [ 4409] OBJ_set_brand_Visa */ + 0x67,0x2A,0x08,0x05, /* [ 4413] OBJ_set_brand_MasterCard */ + 0x67,0x2A,0x08,0xAE,0x7B, /* [ 4417] OBJ_set_brand_Novus */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x03,0x0A, /* [ 4422] OBJ_des_cdmf */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x06, /* [ 4430] OBJ_rsaOAEPEncryptionSET */ + 0x67, /* [ 4439] OBJ_international_organizations */ + 0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x14,0x02,0x02, /* [ 4440] OBJ_ms_smartcard_login */ + 0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x14,0x02,0x03, /* [ 4450] OBJ_ms_upn */ + 0x55,0x04,0x09, /* [ 4460] OBJ_streetAddress */ + 0x55,0x04,0x11, /* [ 4463] OBJ_postalCode */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x15, /* [ 4466] OBJ_id_ppl */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x0E, /* [ 4473] OBJ_proxyCertInfo */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x15,0x00, /* [ 4481] OBJ_id_ppl_anyLanguage */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x15,0x01, /* [ 4489] OBJ_id_ppl_inheritAll */ + 0x55,0x1D,0x1E, /* [ 4497] OBJ_name_constraints */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x15,0x02, /* [ 4500] OBJ_Independent */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B, /* [ 4508] OBJ_sha256WithRSAEncryption */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0C, /* [ 4517] OBJ_sha384WithRSAEncryption */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0D, /* [ 4526] OBJ_sha512WithRSAEncryption */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0E, /* [ 4535] OBJ_sha224WithRSAEncryption */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01, /* [ 4544] OBJ_sha256 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02, /* [ 4553] OBJ_sha384 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03, /* [ 4562] OBJ_sha512 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x04, /* [ 4571] OBJ_sha224 */ + 0x2B, /* [ 4580] OBJ_identified_organization */ + 0x2B,0x81,0x04, /* [ 4581] OBJ_certicom_arc */ + 0x67,0x2B, /* [ 4584] OBJ_wap */ + 0x67,0x2B,0x01, /* [ 4586] OBJ_wap_wsg */ + 0x2A,0x86,0x48,0xCE,0x3D,0x01,0x02,0x03, /* [ 4589] OBJ_X9_62_id_characteristic_two_basis */ + 0x2A,0x86,0x48,0xCE,0x3D,0x01,0x02,0x03,0x01, /* [ 4597] OBJ_X9_62_onBasis */ + 0x2A,0x86,0x48,0xCE,0x3D,0x01,0x02,0x03,0x02, /* [ 4606] OBJ_X9_62_tpBasis */ + 0x2A,0x86,0x48,0xCE,0x3D,0x01,0x02,0x03,0x03, /* [ 4615] OBJ_X9_62_ppBasis */ + 0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x01, /* [ 4624] OBJ_X9_62_c2pnb163v1 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x02, /* [ 4632] OBJ_X9_62_c2pnb163v2 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x03, /* [ 4640] OBJ_X9_62_c2pnb163v3 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x04, /* [ 4648] OBJ_X9_62_c2pnb176v1 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x05, /* [ 4656] OBJ_X9_62_c2tnb191v1 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x06, /* [ 4664] OBJ_X9_62_c2tnb191v2 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x07, /* [ 4672] OBJ_X9_62_c2tnb191v3 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x08, /* [ 4680] OBJ_X9_62_c2onb191v4 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x09, /* [ 4688] OBJ_X9_62_c2onb191v5 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x0A, /* [ 4696] OBJ_X9_62_c2pnb208w1 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x0B, /* [ 4704] OBJ_X9_62_c2tnb239v1 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x0C, /* [ 4712] OBJ_X9_62_c2tnb239v2 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x0D, /* [ 4720] OBJ_X9_62_c2tnb239v3 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x0E, /* [ 4728] OBJ_X9_62_c2onb239v4 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x0F, /* [ 4736] OBJ_X9_62_c2onb239v5 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x10, /* [ 4744] OBJ_X9_62_c2pnb272w1 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x11, /* [ 4752] OBJ_X9_62_c2pnb304w1 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x12, /* [ 4760] OBJ_X9_62_c2tnb359v1 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x13, /* [ 4768] OBJ_X9_62_c2pnb368w1 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x14, /* [ 4776] OBJ_X9_62_c2tnb431r1 */ + 0x2B,0x81,0x04,0x00,0x06, /* [ 4784] OBJ_secp112r1 */ + 0x2B,0x81,0x04,0x00,0x07, /* [ 4789] OBJ_secp112r2 */ + 0x2B,0x81,0x04,0x00,0x1C, /* [ 4794] OBJ_secp128r1 */ + 0x2B,0x81,0x04,0x00,0x1D, /* [ 4799] OBJ_secp128r2 */ + 0x2B,0x81,0x04,0x00,0x09, /* [ 4804] OBJ_secp160k1 */ + 0x2B,0x81,0x04,0x00,0x08, /* [ 4809] OBJ_secp160r1 */ + 0x2B,0x81,0x04,0x00,0x1E, /* [ 4814] OBJ_secp160r2 */ + 0x2B,0x81,0x04,0x00,0x1F, /* [ 4819] OBJ_secp192k1 */ + 0x2B,0x81,0x04,0x00,0x20, /* [ 4824] OBJ_secp224k1 */ + 0x2B,0x81,0x04,0x00,0x21, /* [ 4829] OBJ_secp224r1 */ + 0x2B,0x81,0x04,0x00,0x0A, /* [ 4834] OBJ_secp256k1 */ + 0x2B,0x81,0x04,0x00,0x22, /* [ 4839] OBJ_secp384r1 */ + 0x2B,0x81,0x04,0x00,0x23, /* [ 4844] OBJ_secp521r1 */ + 0x2B,0x81,0x04,0x00,0x04, /* [ 4849] OBJ_sect113r1 */ + 0x2B,0x81,0x04,0x00,0x05, /* [ 4854] OBJ_sect113r2 */ + 0x2B,0x81,0x04,0x00,0x16, /* [ 4859] OBJ_sect131r1 */ + 0x2B,0x81,0x04,0x00,0x17, /* [ 4864] OBJ_sect131r2 */ + 0x2B,0x81,0x04,0x00,0x01, /* [ 4869] OBJ_sect163k1 */ + 0x2B,0x81,0x04,0x00,0x02, /* [ 4874] OBJ_sect163r1 */ + 0x2B,0x81,0x04,0x00,0x0F, /* [ 4879] OBJ_sect163r2 */ + 0x2B,0x81,0x04,0x00,0x18, /* [ 4884] OBJ_sect193r1 */ + 0x2B,0x81,0x04,0x00,0x19, /* [ 4889] OBJ_sect193r2 */ + 0x2B,0x81,0x04,0x00,0x1A, /* [ 4894] OBJ_sect233k1 */ + 0x2B,0x81,0x04,0x00,0x1B, /* [ 4899] OBJ_sect233r1 */ + 0x2B,0x81,0x04,0x00,0x03, /* [ 4904] OBJ_sect239k1 */ + 0x2B,0x81,0x04,0x00,0x10, /* [ 4909] OBJ_sect283k1 */ + 0x2B,0x81,0x04,0x00,0x11, /* [ 4914] OBJ_sect283r1 */ + 0x2B,0x81,0x04,0x00,0x24, /* [ 4919] OBJ_sect409k1 */ + 0x2B,0x81,0x04,0x00,0x25, /* [ 4924] OBJ_sect409r1 */ + 0x2B,0x81,0x04,0x00,0x26, /* [ 4929] OBJ_sect571k1 */ + 0x2B,0x81,0x04,0x00,0x27, /* [ 4934] OBJ_sect571r1 */ + 0x67,0x2B,0x01,0x04,0x01, /* [ 4939] OBJ_wap_wsg_idm_ecid_wtls1 */ + 0x67,0x2B,0x01,0x04,0x03, /* [ 4944] OBJ_wap_wsg_idm_ecid_wtls3 */ + 0x67,0x2B,0x01,0x04,0x04, /* [ 4949] OBJ_wap_wsg_idm_ecid_wtls4 */ + 0x67,0x2B,0x01,0x04,0x05, /* [ 4954] OBJ_wap_wsg_idm_ecid_wtls5 */ + 0x67,0x2B,0x01,0x04,0x06, /* [ 4959] OBJ_wap_wsg_idm_ecid_wtls6 */ + 0x67,0x2B,0x01,0x04,0x07, /* [ 4964] OBJ_wap_wsg_idm_ecid_wtls7 */ + 0x67,0x2B,0x01,0x04,0x08, /* [ 4969] OBJ_wap_wsg_idm_ecid_wtls8 */ + 0x67,0x2B,0x01,0x04,0x09, /* [ 4974] OBJ_wap_wsg_idm_ecid_wtls9 */ + 0x67,0x2B,0x01,0x04,0x0A, /* [ 4979] OBJ_wap_wsg_idm_ecid_wtls10 */ + 0x67,0x2B,0x01,0x04,0x0B, /* [ 4984] OBJ_wap_wsg_idm_ecid_wtls11 */ + 0x67,0x2B,0x01,0x04,0x0C, /* [ 4989] OBJ_wap_wsg_idm_ecid_wtls12 */ + 0x55,0x1D,0x20,0x00, /* [ 4994] OBJ_any_policy */ + 0x55,0x1D,0x21, /* [ 4998] OBJ_policy_mappings */ + 0x55,0x1D,0x36, /* [ 5001] OBJ_inhibit_any_policy */ + 0x2A,0x83,0x08,0x8C,0x9A,0x4B,0x3D,0x01,0x01,0x01,0x02, /* [ 5004] OBJ_camellia_128_cbc */ + 0x2A,0x83,0x08,0x8C,0x9A,0x4B,0x3D,0x01,0x01,0x01,0x03, /* [ 5015] OBJ_camellia_192_cbc */ + 0x2A,0x83,0x08,0x8C,0x9A,0x4B,0x3D,0x01,0x01,0x01,0x04, /* [ 5026] OBJ_camellia_256_cbc */ + 0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x01, /* [ 5037] OBJ_camellia_128_ecb */ + 0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x15, /* [ 5045] OBJ_camellia_192_ecb */ + 0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x29, /* [ 5053] OBJ_camellia_256_ecb */ + 0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x04, /* [ 5061] OBJ_camellia_128_cfb128 */ + 0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x18, /* [ 5069] OBJ_camellia_192_cfb128 */ + 0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x2C, /* [ 5077] OBJ_camellia_256_cfb128 */ + 0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x03, /* [ 5085] OBJ_camellia_128_ofb128 */ + 0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x17, /* [ 5093] OBJ_camellia_192_ofb128 */ + 0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x2B, /* [ 5101] OBJ_camellia_256_ofb128 */ + 0x55,0x1D,0x09, /* [ 5109] OBJ_subject_directory_attributes */ + 0x55,0x1D,0x1C, /* [ 5112] OBJ_issuing_distribution_point */ + 0x55,0x1D,0x1D, /* [ 5115] OBJ_certificate_issuer */ + 0x2A,0x83,0x1A,0x8C,0x9A,0x44, /* [ 5118] OBJ_kisa */ + 0x2A,0x83,0x1A,0x8C,0x9A,0x44,0x01,0x03, /* [ 5124] OBJ_seed_ecb */ + 0x2A,0x83,0x1A,0x8C,0x9A,0x44,0x01,0x04, /* [ 5132] OBJ_seed_cbc */ + 0x2A,0x83,0x1A,0x8C,0x9A,0x44,0x01,0x06, /* [ 5140] OBJ_seed_ofb128 */ + 0x2A,0x83,0x1A,0x8C,0x9A,0x44,0x01,0x05, /* [ 5148] OBJ_seed_cfb128 */ + 0x2B,0x06,0x01,0x05,0x05,0x08,0x01,0x01, /* [ 5156] OBJ_hmac_md5 */ + 0x2B,0x06,0x01,0x05,0x05,0x08,0x01,0x02, /* [ 5164] OBJ_hmac_sha1 */ + 0x2A,0x86,0x48,0x86,0xF6,0x7D,0x07,0x42,0x0D, /* [ 5172] OBJ_id_PasswordBasedMAC */ + 0x2A,0x86,0x48,0x86,0xF6,0x7D,0x07,0x42,0x1E, /* [ 5181] OBJ_id_DHBasedMac */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x10, /* [ 5190] OBJ_id_it_suppLangTags */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x05, /* [ 5198] OBJ_caRepository */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x09, /* [ 5206] OBJ_id_smime_ct_compressedData */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x1B, /* [ 5217] OBJ_id_ct_asciiTextWithCRLF */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x05, /* [ 5228] OBJ_id_aes128_wrap */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x19, /* [ 5237] OBJ_id_aes192_wrap */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x2D, /* [ 5246] OBJ_id_aes256_wrap */ + 0x2A,0x86,0x48,0xCE,0x3D,0x04,0x02, /* [ 5255] OBJ_ecdsa_with_Recommended */ + 0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03, /* [ 5262] OBJ_ecdsa_with_Specified */ + 0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x01, /* [ 5269] OBJ_ecdsa_with_SHA224 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02, /* [ 5277] OBJ_ecdsa_with_SHA256 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x03, /* [ 5285] OBJ_ecdsa_with_SHA384 */ + 0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x04, /* [ 5293] OBJ_ecdsa_with_SHA512 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x06, /* [ 5301] OBJ_hmacWithMD5 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x08, /* [ 5309] OBJ_hmacWithSHA224 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x09, /* [ 5317] OBJ_hmacWithSHA256 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x0A, /* [ 5325] OBJ_hmacWithSHA384 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x0B, /* [ 5333] OBJ_hmacWithSHA512 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x01, /* [ 5341] OBJ_dsa_with_SHA224 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x02, /* [ 5350] OBJ_dsa_with_SHA256 */ + 0x28,0xCF,0x06,0x03,0x00,0x37, /* [ 5359] OBJ_whirlpool */ + 0x2A,0x85,0x03,0x02,0x02, /* [ 5365] OBJ_cryptopro */ + 0x2A,0x85,0x03,0x02,0x09, /* [ 5370] OBJ_cryptocom */ + 0x2A,0x85,0x03,0x02,0x02,0x03, /* [ 5375] OBJ_id_GostR3411_94_with_GostR3410_2001 */ + 0x2A,0x85,0x03,0x02,0x02,0x04, /* [ 5381] OBJ_id_GostR3411_94_with_GostR3410_94 */ + 0x2A,0x85,0x03,0x02,0x02,0x09, /* [ 5387] OBJ_id_GostR3411_94 */ + 0x2A,0x85,0x03,0x02,0x02,0x0A, /* [ 5393] OBJ_id_HMACGostR3411_94 */ + 0x2A,0x85,0x03,0x02,0x02,0x13, /* [ 5399] OBJ_id_GostR3410_2001 */ + 0x2A,0x85,0x03,0x02,0x02,0x14, /* [ 5405] OBJ_id_GostR3410_94 */ + 0x2A,0x85,0x03,0x02,0x02,0x15, /* [ 5411] OBJ_id_Gost28147_89 */ + 0x2A,0x85,0x03,0x02,0x02,0x16, /* [ 5417] OBJ_id_Gost28147_89_MAC */ + 0x2A,0x85,0x03,0x02,0x02,0x17, /* [ 5423] OBJ_id_GostR3411_94_prf */ + 0x2A,0x85,0x03,0x02,0x02,0x62, /* [ 5429] OBJ_id_GostR3410_2001DH */ + 0x2A,0x85,0x03,0x02,0x02,0x63, /* [ 5435] OBJ_id_GostR3410_94DH */ + 0x2A,0x85,0x03,0x02,0x02,0x0E,0x01, /* [ 5441] OBJ_id_Gost28147_89_CryptoPro_KeyMeshing */ + 0x2A,0x85,0x03,0x02,0x02,0x0E,0x00, /* [ 5448] OBJ_id_Gost28147_89_None_KeyMeshing */ + 0x2A,0x85,0x03,0x02,0x02,0x1E,0x00, /* [ 5455] OBJ_id_GostR3411_94_TestParamSet */ + 0x2A,0x85,0x03,0x02,0x02,0x1E,0x01, /* [ 5462] OBJ_id_GostR3411_94_CryptoProParamSet */ + 0x2A,0x85,0x03,0x02,0x02,0x1F,0x00, /* [ 5469] OBJ_id_Gost28147_89_TestParamSet */ + 0x2A,0x85,0x03,0x02,0x02,0x1F,0x01, /* [ 5476] OBJ_id_Gost28147_89_CryptoPro_A_ParamSet */ + 0x2A,0x85,0x03,0x02,0x02,0x1F,0x02, /* [ 5483] OBJ_id_Gost28147_89_CryptoPro_B_ParamSet */ + 0x2A,0x85,0x03,0x02,0x02,0x1F,0x03, /* [ 5490] OBJ_id_Gost28147_89_CryptoPro_C_ParamSet */ + 0x2A,0x85,0x03,0x02,0x02,0x1F,0x04, /* [ 5497] OBJ_id_Gost28147_89_CryptoPro_D_ParamSet */ + 0x2A,0x85,0x03,0x02,0x02,0x1F,0x05, /* [ 5504] OBJ_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet */ + 0x2A,0x85,0x03,0x02,0x02,0x1F,0x06, /* [ 5511] OBJ_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet */ + 0x2A,0x85,0x03,0x02,0x02,0x1F,0x07, /* [ 5518] OBJ_id_Gost28147_89_CryptoPro_RIC_1_ParamSet */ + 0x2A,0x85,0x03,0x02,0x02,0x20,0x00, /* [ 5525] OBJ_id_GostR3410_94_TestParamSet */ + 0x2A,0x85,0x03,0x02,0x02,0x20,0x02, /* [ 5532] OBJ_id_GostR3410_94_CryptoPro_A_ParamSet */ + 0x2A,0x85,0x03,0x02,0x02,0x20,0x03, /* [ 5539] OBJ_id_GostR3410_94_CryptoPro_B_ParamSet */ + 0x2A,0x85,0x03,0x02,0x02,0x20,0x04, /* [ 5546] OBJ_id_GostR3410_94_CryptoPro_C_ParamSet */ + 0x2A,0x85,0x03,0x02,0x02,0x20,0x05, /* [ 5553] OBJ_id_GostR3410_94_CryptoPro_D_ParamSet */ + 0x2A,0x85,0x03,0x02,0x02,0x21,0x01, /* [ 5560] OBJ_id_GostR3410_94_CryptoPro_XchA_ParamSet */ + 0x2A,0x85,0x03,0x02,0x02,0x21,0x02, /* [ 5567] OBJ_id_GostR3410_94_CryptoPro_XchB_ParamSet */ + 0x2A,0x85,0x03,0x02,0x02,0x21,0x03, /* [ 5574] OBJ_id_GostR3410_94_CryptoPro_XchC_ParamSet */ + 0x2A,0x85,0x03,0x02,0x02,0x23,0x00, /* [ 5581] OBJ_id_GostR3410_2001_TestParamSet */ + 0x2A,0x85,0x03,0x02,0x02,0x23,0x01, /* [ 5588] OBJ_id_GostR3410_2001_CryptoPro_A_ParamSet */ + 0x2A,0x85,0x03,0x02,0x02,0x23,0x02, /* [ 5595] OBJ_id_GostR3410_2001_CryptoPro_B_ParamSet */ + 0x2A,0x85,0x03,0x02,0x02,0x23,0x03, /* [ 5602] OBJ_id_GostR3410_2001_CryptoPro_C_ParamSet */ + 0x2A,0x85,0x03,0x02,0x02,0x24,0x00, /* [ 5609] OBJ_id_GostR3410_2001_CryptoPro_XchA_ParamSet */ + 0x2A,0x85,0x03,0x02,0x02,0x24,0x01, /* [ 5616] OBJ_id_GostR3410_2001_CryptoPro_XchB_ParamSet */ + 0x2A,0x85,0x03,0x02,0x02,0x14,0x01, /* [ 5623] OBJ_id_GostR3410_94_a */ + 0x2A,0x85,0x03,0x02,0x02,0x14,0x02, /* [ 5630] OBJ_id_GostR3410_94_aBis */ + 0x2A,0x85,0x03,0x02,0x02,0x14,0x03, /* [ 5637] OBJ_id_GostR3410_94_b */ + 0x2A,0x85,0x03,0x02,0x02,0x14,0x04, /* [ 5644] OBJ_id_GostR3410_94_bBis */ + 0x2A,0x85,0x03,0x02,0x09,0x01,0x06,0x01, /* [ 5651] OBJ_id_Gost28147_89_cc */ + 0x2A,0x85,0x03,0x02,0x09,0x01,0x05,0x03, /* [ 5659] OBJ_id_GostR3410_94_cc */ + 0x2A,0x85,0x03,0x02,0x09,0x01,0x05,0x04, /* [ 5667] OBJ_id_GostR3410_2001_cc */ + 0x2A,0x85,0x03,0x02,0x09,0x01,0x03,0x03, /* [ 5675] OBJ_id_GostR3411_94_with_GostR3410_94_cc */ + 0x2A,0x85,0x03,0x02,0x09,0x01,0x03,0x04, /* [ 5683] OBJ_id_GostR3411_94_with_GostR3410_2001_cc */ + 0x2A,0x85,0x03,0x02,0x09,0x01,0x08,0x01, /* [ 5691] OBJ_id_GostR3410_2001_ParamSet_cc */ + 0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x11,0x02, /* [ 5699] OBJ_LocalKeySet */ + 0x55,0x1D,0x2E, /* [ 5708] OBJ_freshest_crl */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x08,0x03, /* [ 5711] OBJ_id_on_permanentIdentifier */ + 0x55,0x04,0x0E, /* [ 5719] OBJ_searchGuide */ + 0x55,0x04,0x0F, /* [ 5722] OBJ_businessCategory */ + 0x55,0x04,0x10, /* [ 5725] OBJ_postalAddress */ + 0x55,0x04,0x12, /* [ 5728] OBJ_postOfficeBox */ + 0x55,0x04,0x13, /* [ 5731] OBJ_physicalDeliveryOfficeName */ + 0x55,0x04,0x14, /* [ 5734] OBJ_telephoneNumber */ + 0x55,0x04,0x15, /* [ 5737] OBJ_telexNumber */ + 0x55,0x04,0x16, /* [ 5740] OBJ_teletexTerminalIdentifier */ + 0x55,0x04,0x17, /* [ 5743] OBJ_facsimileTelephoneNumber */ + 0x55,0x04,0x18, /* [ 5746] OBJ_x121Address */ + 0x55,0x04,0x19, /* [ 5749] OBJ_internationaliSDNNumber */ + 0x55,0x04,0x1A, /* [ 5752] OBJ_registeredAddress */ + 0x55,0x04,0x1B, /* [ 5755] OBJ_destinationIndicator */ + 0x55,0x04,0x1C, /* [ 5758] OBJ_preferredDeliveryMethod */ + 0x55,0x04,0x1D, /* [ 5761] OBJ_presentationAddress */ + 0x55,0x04,0x1E, /* [ 5764] OBJ_supportedApplicationContext */ + 0x55,0x04,0x1F, /* [ 5767] OBJ_member */ + 0x55,0x04,0x20, /* [ 5770] OBJ_owner */ + 0x55,0x04,0x21, /* [ 5773] OBJ_roleOccupant */ + 0x55,0x04,0x22, /* [ 5776] OBJ_seeAlso */ + 0x55,0x04,0x23, /* [ 5779] OBJ_userPassword */ + 0x55,0x04,0x24, /* [ 5782] OBJ_userCertificate */ + 0x55,0x04,0x25, /* [ 5785] OBJ_cACertificate */ + 0x55,0x04,0x26, /* [ 5788] OBJ_authorityRevocationList */ + 0x55,0x04,0x27, /* [ 5791] OBJ_certificateRevocationList */ + 0x55,0x04,0x28, /* [ 5794] OBJ_crossCertificatePair */ + 0x55,0x04,0x2F, /* [ 5797] OBJ_enhancedSearchGuide */ + 0x55,0x04,0x30, /* [ 5800] OBJ_protocolInformation */ + 0x55,0x04,0x31, /* [ 5803] OBJ_distinguishedName */ + 0x55,0x04,0x32, /* [ 5806] OBJ_uniqueMember */ + 0x55,0x04,0x33, /* [ 5809] OBJ_houseIdentifier */ + 0x55,0x04,0x34, /* [ 5812] OBJ_supportedAlgorithms */ + 0x55,0x04,0x35, /* [ 5815] OBJ_deltaRevocationList */ + 0x55,0x04,0x36, /* [ 5818] OBJ_dmdName */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x09, /* [ 5821] OBJ_id_alg_PWRI_KEK */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x06, /* [ 5832] OBJ_aes_128_gcm */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x07, /* [ 5841] OBJ_aes_128_ccm */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x08, /* [ 5850] OBJ_id_aes128_wrap_pad */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x1A, /* [ 5859] OBJ_aes_192_gcm */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x1B, /* [ 5868] OBJ_aes_192_ccm */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x1C, /* [ 5877] OBJ_id_aes192_wrap_pad */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x2E, /* [ 5886] OBJ_aes_256_gcm */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x2F, /* [ 5895] OBJ_aes_256_ccm */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x30, /* [ 5904] OBJ_id_aes256_wrap_pad */ + 0x2A,0x83,0x08,0x8C,0x9A,0x4B,0x3D,0x01,0x01,0x03,0x02, /* [ 5913] OBJ_id_camellia128_wrap */ + 0x2A,0x83,0x08,0x8C,0x9A,0x4B,0x3D,0x01,0x01,0x03,0x03, /* [ 5924] OBJ_id_camellia192_wrap */ + 0x2A,0x83,0x08,0x8C,0x9A,0x4B,0x3D,0x01,0x01,0x03,0x04, /* [ 5935] OBJ_id_camellia256_wrap */ + 0x55,0x1D,0x25,0x00, /* [ 5946] OBJ_anyExtendedKeyUsage */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x08, /* [ 5950] OBJ_mgf1 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0A, /* [ 5959] OBJ_rsassaPss */ + 0x2B,0x6F,0x02,0x8C,0x53,0x00,0x01,0x01, /* [ 5968] OBJ_aes_128_xts */ + 0x2B,0x6F,0x02,0x8C,0x53,0x00,0x01,0x02, /* [ 5976] OBJ_aes_256_xts */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x07, /* [ 5984] OBJ_rsaesOaep */ + 0x2A,0x86,0x48,0xCE,0x3E,0x02,0x01, /* [ 5993] OBJ_dhpublicnumber */ + 0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x01, /* [ 6000] OBJ_brainpoolP160r1 */ + 0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x02, /* [ 6009] OBJ_brainpoolP160t1 */ + 0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x03, /* [ 6018] OBJ_brainpoolP192r1 */ + 0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x04, /* [ 6027] OBJ_brainpoolP192t1 */ + 0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x05, /* [ 6036] OBJ_brainpoolP224r1 */ + 0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x06, /* [ 6045] OBJ_brainpoolP224t1 */ + 0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x07, /* [ 6054] OBJ_brainpoolP256r1 */ + 0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x08, /* [ 6063] OBJ_brainpoolP256t1 */ + 0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x09, /* [ 6072] OBJ_brainpoolP320r1 */ + 0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0A, /* [ 6081] OBJ_brainpoolP320t1 */ + 0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0B, /* [ 6090] OBJ_brainpoolP384r1 */ + 0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0C, /* [ 6099] OBJ_brainpoolP384t1 */ + 0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0D, /* [ 6108] OBJ_brainpoolP512r1 */ + 0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0E, /* [ 6117] OBJ_brainpoolP512t1 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x09, /* [ 6126] OBJ_pSpecified */ + 0x2B,0x81,0x05,0x10,0x86,0x48,0x3F,0x00,0x02, /* [ 6135] OBJ_dhSinglePass_stdDH_sha1kdf_scheme */ + 0x2B,0x81,0x04,0x01,0x0B,0x00, /* [ 6144] OBJ_dhSinglePass_stdDH_sha224kdf_scheme */ + 0x2B,0x81,0x04,0x01,0x0B,0x01, /* [ 6150] OBJ_dhSinglePass_stdDH_sha256kdf_scheme */ + 0x2B,0x81,0x04,0x01,0x0B,0x02, /* [ 6156] OBJ_dhSinglePass_stdDH_sha384kdf_scheme */ + 0x2B,0x81,0x04,0x01,0x0B,0x03, /* [ 6162] OBJ_dhSinglePass_stdDH_sha512kdf_scheme */ + 0x2B,0x81,0x05,0x10,0x86,0x48,0x3F,0x00,0x03, /* [ 6168] OBJ_dhSinglePass_cofactorDH_sha1kdf_scheme */ + 0x2B,0x81,0x04,0x01,0x0E,0x00, /* [ 6177] OBJ_dhSinglePass_cofactorDH_sha224kdf_scheme */ + 0x2B,0x81,0x04,0x01,0x0E,0x01, /* [ 6183] OBJ_dhSinglePass_cofactorDH_sha256kdf_scheme */ + 0x2B,0x81,0x04,0x01,0x0E,0x02, /* [ 6189] OBJ_dhSinglePass_cofactorDH_sha384kdf_scheme */ + 0x2B,0x81,0x04,0x01,0x0E,0x03, /* [ 6195] OBJ_dhSinglePass_cofactorDH_sha512kdf_scheme */ + 0x2B,0x06,0x01,0x04,0x01,0xD6,0x79,0x02,0x04,0x02, /* [ 6201] OBJ_ct_precert_scts */ + 0x2B,0x06,0x01,0x04,0x01,0xD6,0x79,0x02,0x04,0x03, /* [ 6211] OBJ_ct_precert_poison */ + 0x2B,0x06,0x01,0x04,0x01,0xD6,0x79,0x02,0x04,0x04, /* [ 6221] OBJ_ct_precert_signer */ + 0x2B,0x06,0x01,0x04,0x01,0xD6,0x79,0x02,0x04,0x05, /* [ 6231] OBJ_ct_cert_scts */ + 0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x3C,0x02,0x01,0x01, /* [ 6241] OBJ_jurisdictionLocalityName */ + 0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x3C,0x02,0x01,0x02, /* [ 6252] OBJ_jurisdictionStateOrProvinceName */ + 0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x3C,0x02,0x01,0x03, /* [ 6263] OBJ_jurisdictionCountryName */ + 0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x06, /* [ 6274] OBJ_camellia_128_gcm */ + 0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x07, /* [ 6282] OBJ_camellia_128_ccm */ + 0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x09, /* [ 6290] OBJ_camellia_128_ctr */ + 0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x0A, /* [ 6298] OBJ_camellia_128_cmac */ + 0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x1A, /* [ 6306] OBJ_camellia_192_gcm */ + 0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x1B, /* [ 6314] OBJ_camellia_192_ccm */ + 0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x1D, /* [ 6322] OBJ_camellia_192_ctr */ + 0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x1E, /* [ 6330] OBJ_camellia_192_cmac */ + 0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x2E, /* [ 6338] OBJ_camellia_256_gcm */ + 0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x2F, /* [ 6346] OBJ_camellia_256_ccm */ + 0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x31, /* [ 6354] OBJ_camellia_256_ctr */ + 0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x32, /* [ 6362] OBJ_camellia_256_cmac */ + 0x2B,0x06,0x01,0x04,0x01,0xDA,0x47,0x04,0x0B, /* [ 6370] OBJ_id_scrypt */ + 0x2A,0x85,0x03,0x07,0x01, /* [ 6379] OBJ_id_tc26 */ + 0x2A,0x85,0x03,0x07,0x01,0x01, /* [ 6384] OBJ_id_tc26_algorithms */ + 0x2A,0x85,0x03,0x07,0x01,0x01,0x01, /* [ 6390] OBJ_id_tc26_sign */ + 0x2A,0x85,0x03,0x07,0x01,0x01,0x01,0x01, /* [ 6397] OBJ_id_GostR3410_2012_256 */ + 0x2A,0x85,0x03,0x07,0x01,0x01,0x01,0x02, /* [ 6405] OBJ_id_GostR3410_2012_512 */ + 0x2A,0x85,0x03,0x07,0x01,0x01,0x02, /* [ 6413] OBJ_id_tc26_digest */ + 0x2A,0x85,0x03,0x07,0x01,0x01,0x02,0x02, /* [ 6420] OBJ_id_GostR3411_2012_256 */ + 0x2A,0x85,0x03,0x07,0x01,0x01,0x02,0x03, /* [ 6428] OBJ_id_GostR3411_2012_512 */ + 0x2A,0x85,0x03,0x07,0x01,0x01,0x03, /* [ 6436] OBJ_id_tc26_signwithdigest */ + 0x2A,0x85,0x03,0x07,0x01,0x01,0x03,0x02, /* [ 6443] OBJ_id_tc26_signwithdigest_gost3410_2012_256 */ + 0x2A,0x85,0x03,0x07,0x01,0x01,0x03,0x03, /* [ 6451] OBJ_id_tc26_signwithdigest_gost3410_2012_512 */ + 0x2A,0x85,0x03,0x07,0x01,0x01,0x04, /* [ 6459] OBJ_id_tc26_mac */ + 0x2A,0x85,0x03,0x07,0x01,0x01,0x04,0x01, /* [ 6466] OBJ_id_tc26_hmac_gost_3411_2012_256 */ + 0x2A,0x85,0x03,0x07,0x01,0x01,0x04,0x02, /* [ 6474] OBJ_id_tc26_hmac_gost_3411_2012_512 */ + 0x2A,0x85,0x03,0x07,0x01,0x01,0x05, /* [ 6482] OBJ_id_tc26_cipher */ + 0x2A,0x85,0x03,0x07,0x01,0x01,0x06, /* [ 6489] OBJ_id_tc26_agreement */ + 0x2A,0x85,0x03,0x07,0x01,0x01,0x06,0x01, /* [ 6496] OBJ_id_tc26_agreement_gost_3410_2012_256 */ + 0x2A,0x85,0x03,0x07,0x01,0x01,0x06,0x02, /* [ 6504] OBJ_id_tc26_agreement_gost_3410_2012_512 */ + 0x2A,0x85,0x03,0x07,0x01,0x02, /* [ 6512] OBJ_id_tc26_constants */ + 0x2A,0x85,0x03,0x07,0x01,0x02,0x01, /* [ 6518] OBJ_id_tc26_sign_constants */ + 0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x02, /* [ 6525] OBJ_id_tc26_gost_3410_2012_512_constants */ + 0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x02,0x00, /* [ 6533] OBJ_id_tc26_gost_3410_2012_512_paramSetTest */ + 0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x02,0x01, /* [ 6542] OBJ_id_tc26_gost_3410_2012_512_paramSetA */ + 0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x02,0x02, /* [ 6551] OBJ_id_tc26_gost_3410_2012_512_paramSetB */ + 0x2A,0x85,0x03,0x07,0x01,0x02,0x02, /* [ 6560] OBJ_id_tc26_digest_constants */ + 0x2A,0x85,0x03,0x07,0x01,0x02,0x05, /* [ 6567] OBJ_id_tc26_cipher_constants */ + 0x2A,0x85,0x03,0x07,0x01,0x02,0x05,0x01, /* [ 6574] OBJ_id_tc26_gost_28147_constants */ + 0x2A,0x85,0x03,0x07,0x01,0x02,0x05,0x01,0x01, /* [ 6582] OBJ_id_tc26_gost_28147_param_Z */ + 0x2A,0x85,0x03,0x03,0x81,0x03,0x01,0x01, /* [ 6591] OBJ_INN */ + 0x2A,0x85,0x03,0x64,0x01, /* [ 6599] OBJ_OGRN */ + 0x2A,0x85,0x03,0x64,0x03, /* [ 6604] OBJ_SNILS */ + 0x2A,0x85,0x03,0x64,0x6F, /* [ 6609] OBJ_subjectSignTool */ + 0x2A,0x85,0x03,0x64,0x70, /* [ 6614] OBJ_issuerSignTool */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x18, /* [ 6619] OBJ_tlsfeature */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x11, /* [ 6627] OBJ_ipsec_IKE */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x12, /* [ 6635] OBJ_capwapAC */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x13, /* [ 6643] OBJ_capwapWTP */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x15, /* [ 6651] OBJ_sshClient */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x16, /* [ 6659] OBJ_sshServer */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x17, /* [ 6667] OBJ_sendRouter */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x18, /* [ 6675] OBJ_sendProxiedRouter */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x19, /* [ 6683] OBJ_sendOwner */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x1A, /* [ 6691] OBJ_sendProxiedOwner */ + 0x2B,0x06,0x01,0x05,0x02,0x03, /* [ 6699] OBJ_id_pkinit */ + 0x2B,0x06,0x01,0x05,0x02,0x03,0x04, /* [ 6705] OBJ_pkInitClientAuth */ + 0x2B,0x06,0x01,0x05,0x02,0x03,0x05, /* [ 6712] OBJ_pkInitKDC */ + 0x2B,0x65,0x6E, /* [ 6719] OBJ_X25519 */ + 0x2B,0x65,0x6F, /* [ 6722] OBJ_X448 */ + 0x2B,0x06,0x01,0x04,0x01,0x8D,0x3A,0x0C,0x02,0x01,0x10, /* [ 6725] OBJ_blake2b512 */ + 0x2B,0x06,0x01,0x04,0x01,0x8D,0x3A,0x0C,0x02,0x02,0x08, /* [ 6736] OBJ_blake2s256 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x13, /* [ 6747] OBJ_id_smime_ct_contentCollection */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x17, /* [ 6758] OBJ_id_smime_ct_authEnvelopedData */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x1C, /* [ 6769] OBJ_id_ct_xml */ + 0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x01, /* [ 6780] OBJ_aria_128_ecb */ + 0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x02, /* [ 6789] OBJ_aria_128_cbc */ + 0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x03, /* [ 6798] OBJ_aria_128_cfb128 */ + 0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x04, /* [ 6807] OBJ_aria_128_ofb128 */ + 0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x05, /* [ 6816] OBJ_aria_128_ctr */ + 0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x06, /* [ 6825] OBJ_aria_192_ecb */ + 0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x07, /* [ 6834] OBJ_aria_192_cbc */ + 0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x08, /* [ 6843] OBJ_aria_192_cfb128 */ + 0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x09, /* [ 6852] OBJ_aria_192_ofb128 */ + 0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x0A, /* [ 6861] OBJ_aria_192_ctr */ + 0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x0B, /* [ 6870] OBJ_aria_256_ecb */ + 0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x0C, /* [ 6879] OBJ_aria_256_cbc */ + 0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x0D, /* [ 6888] OBJ_aria_256_cfb128 */ + 0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x0E, /* [ 6897] OBJ_aria_256_ofb128 */ + 0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x0F, /* [ 6906] OBJ_aria_256_ctr */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x2F, /* [ 6915] OBJ_id_smime_aa_signingCertificateV2 */ + 0x2B,0x65,0x70, /* [ 6926] OBJ_ED25519 */ + 0x2B,0x65,0x71, /* [ 6929] OBJ_ED448 */ + 0x55,0x04,0x61, /* [ 6932] OBJ_organizationIdentifier */ + 0x55,0x04,0x62, /* [ 6935] OBJ_countryCode3c */ + 0x55,0x04,0x63, /* [ 6938] OBJ_countryCode3n */ + 0x55,0x04,0x64, /* [ 6941] OBJ_dnsName */ + 0x2B,0x24,0x08,0x03,0x03, /* [ 6944] OBJ_x509ExtAdmission */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x05, /* [ 6949] OBJ_sha512_224 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x06, /* [ 6958] OBJ_sha512_256 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x07, /* [ 6967] OBJ_sha3_224 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x08, /* [ 6976] OBJ_sha3_256 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x09, /* [ 6985] OBJ_sha3_384 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x0A, /* [ 6994] OBJ_sha3_512 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x0B, /* [ 7003] OBJ_shake128 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x0C, /* [ 7012] OBJ_shake256 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x0D, /* [ 7021] OBJ_hmac_sha3_224 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x0E, /* [ 7030] OBJ_hmac_sha3_256 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x0F, /* [ 7039] OBJ_hmac_sha3_384 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x10, /* [ 7048] OBJ_hmac_sha3_512 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x03, /* [ 7057] OBJ_dsa_with_SHA384 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x04, /* [ 7066] OBJ_dsa_with_SHA512 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x05, /* [ 7075] OBJ_dsa_with_SHA3_224 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x06, /* [ 7084] OBJ_dsa_with_SHA3_256 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x07, /* [ 7093] OBJ_dsa_with_SHA3_384 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x08, /* [ 7102] OBJ_dsa_with_SHA3_512 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x09, /* [ 7111] OBJ_ecdsa_with_SHA3_224 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x0A, /* [ 7120] OBJ_ecdsa_with_SHA3_256 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x0B, /* [ 7129] OBJ_ecdsa_with_SHA3_384 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x0C, /* [ 7138] OBJ_ecdsa_with_SHA3_512 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x0D, /* [ 7147] OBJ_RSA_SHA3_224 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x0E, /* [ 7156] OBJ_RSA_SHA3_256 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x0F, /* [ 7165] OBJ_RSA_SHA3_384 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x10, /* [ 7174] OBJ_RSA_SHA3_512 */ + 0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x25, /* [ 7183] OBJ_aria_128_ccm */ + 0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x26, /* [ 7192] OBJ_aria_192_ccm */ + 0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x27, /* [ 7201] OBJ_aria_256_ccm */ + 0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x22, /* [ 7210] OBJ_aria_128_gcm */ + 0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x23, /* [ 7219] OBJ_aria_192_gcm */ + 0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x24, /* [ 7228] OBJ_aria_256_gcm */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x1B, /* [ 7237] OBJ_cmcCA */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x1C, /* [ 7245] OBJ_cmcRA */ + 0x2A,0x81,0x1C,0xCF,0x55,0x01,0x68,0x01, /* [ 7253] OBJ_sm4_ecb */ + 0x2A,0x81,0x1C,0xCF,0x55,0x01,0x68,0x02, /* [ 7261] OBJ_sm4_cbc */ + 0x2A,0x81,0x1C,0xCF,0x55,0x01,0x68,0x03, /* [ 7269] OBJ_sm4_ofb128 */ + 0x2A,0x81,0x1C,0xCF,0x55,0x01,0x68,0x05, /* [ 7277] OBJ_sm4_cfb1 */ + 0x2A,0x81,0x1C,0xCF,0x55,0x01,0x68,0x04, /* [ 7285] OBJ_sm4_cfb128 */ + 0x2A,0x81,0x1C,0xCF,0x55,0x01,0x68,0x06, /* [ 7293] OBJ_sm4_cfb8 */ + 0x2A,0x81,0x1C,0xCF,0x55,0x01,0x68,0x07, /* [ 7301] OBJ_sm4_ctr */ + 0x2A,0x81,0x1C, /* [ 7309] OBJ_ISO_CN */ + 0x2A,0x81,0x1C,0xCF,0x55, /* [ 7312] OBJ_oscca */ + 0x2A,0x81,0x1C,0xCF,0x55,0x01, /* [ 7317] OBJ_sm_scheme */ + 0x2A,0x81,0x1C,0xCF,0x55,0x01,0x83,0x11, /* [ 7323] OBJ_sm3 */ + 0x2A,0x81,0x1C,0xCF,0x55,0x01,0x83,0x78, /* [ 7331] OBJ_sm3WithRSAEncryption */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0F, /* [ 7339] OBJ_sha512_224WithRSAEncryption */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x10, /* [ 7348] OBJ_sha512_256WithRSAEncryption */ + 0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x01, /* [ 7357] OBJ_id_tc26_gost_3410_2012_256_constants */ + 0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x01,0x01, /* [ 7365] OBJ_id_tc26_gost_3410_2012_256_paramSetA */ + 0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x02,0x03, /* [ 7374] OBJ_id_tc26_gost_3410_2012_512_paramSetC */ + 0x2A,0x86,0x24, /* [ 7383] OBJ_ISO_UA */ + 0x2A,0x86,0x24,0x02,0x01,0x01,0x01, /* [ 7386] OBJ_ua_pki */ + 0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x01,0x01, /* [ 7393] OBJ_dstu28147 */ + 0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x01,0x01,0x02, /* [ 7403] OBJ_dstu28147_ofb */ + 0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x01,0x01,0x03, /* [ 7414] OBJ_dstu28147_cfb */ + 0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x01,0x01,0x05, /* [ 7425] OBJ_dstu28147_wrap */ + 0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x01,0x02, /* [ 7436] OBJ_hmacWithDstu34311 */ + 0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x02,0x01, /* [ 7446] OBJ_dstu34311 */ + 0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x03,0x01,0x01, /* [ 7456] OBJ_dstu4145le */ + 0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x03,0x01,0x01,0x01,0x01, /* [ 7467] OBJ_dstu4145be */ + 0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x03,0x01,0x01,0x02,0x00, /* [ 7480] OBJ_uacurve0 */ + 0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x03,0x01,0x01,0x02,0x01, /* [ 7493] OBJ_uacurve1 */ + 0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x03,0x01,0x01,0x02,0x02, /* [ 7506] OBJ_uacurve2 */ + 0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x03,0x01,0x01,0x02,0x03, /* [ 7519] OBJ_uacurve3 */ + 0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x03,0x01,0x01,0x02,0x04, /* [ 7532] OBJ_uacurve4 */ + 0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x03,0x01,0x01,0x02,0x05, /* [ 7545] OBJ_uacurve5 */ + 0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x03,0x01,0x01,0x02,0x06, /* [ 7558] OBJ_uacurve6 */ + 0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x03,0x01,0x01,0x02,0x07, /* [ 7571] OBJ_uacurve7 */ + 0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x03,0x01,0x01,0x02,0x08, /* [ 7584] OBJ_uacurve8 */ + 0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x03,0x01,0x01,0x02,0x09, /* [ 7597] OBJ_uacurve9 */ + 0x2B,0x6F, /* [ 7610] OBJ_ieee */ + 0x2B,0x6F,0x02,0x8C,0x53, /* [ 7612] OBJ_ieee_siswg */ + 0x2A,0x81,0x1C,0xCF,0x55,0x01,0x82,0x2D, /* [ 7617] OBJ_sm2 */ + 0x2A,0x85,0x03,0x07,0x01,0x01,0x05,0x01, /* [ 7625] OBJ_id_tc26_cipher_gostr3412_2015_magma */ + 0x2A,0x85,0x03,0x07,0x01,0x01,0x05,0x01,0x01, /* [ 7633] OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm */ + 0x2A,0x85,0x03,0x07,0x01,0x01,0x05,0x01,0x02, /* [ 7642] OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac */ + 0x2A,0x85,0x03,0x07,0x01,0x01,0x05,0x02, /* [ 7651] OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik */ + 0x2A,0x85,0x03,0x07,0x01,0x01,0x05,0x02,0x01, /* [ 7659] OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm */ + 0x2A,0x85,0x03,0x07,0x01,0x01,0x05,0x02,0x02, /* [ 7668] OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac */ + 0x2A,0x85,0x03,0x07,0x01,0x01,0x07, /* [ 7677] OBJ_id_tc26_wrap */ + 0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x01, /* [ 7684] OBJ_id_tc26_wrap_gostr3412_2015_magma */ + 0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x01,0x01, /* [ 7692] OBJ_id_tc26_wrap_gostr3412_2015_magma_kexp15 */ + 0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x02, /* [ 7701] OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik */ + 0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x01,0x01, /* [ 7709] OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 */ + 0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x01,0x02, /* [ 7718] OBJ_id_tc26_gost_3410_2012_256_paramSetB */ + 0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x01,0x03, /* [ 7727] OBJ_id_tc26_gost_3410_2012_256_paramSetC */ + 0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x01,0x04, /* [ 7736] OBJ_id_tc26_gost_3410_2012_256_paramSetD */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x0C, /* [ 7745] OBJ_hmacWithSHA512_224 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x0D, /* [ 7753] OBJ_hmacWithSHA512_256 */ +}; + +#define NUM_NID 1195 +static const ASN1_OBJECT nid_objs[NUM_NID] = { + {"UNDEF", "undefined", NID_undef}, + {"rsadsi", "RSA Data Security, Inc.", NID_rsadsi, 6, &so[0]}, + {"pkcs", "RSA Data Security, Inc. PKCS", NID_pkcs, 7, &so[6]}, + {"MD2", "md2", NID_md2, 8, &so[13]}, + {"MD5", "md5", NID_md5, 8, &so[21]}, + {"RC4", "rc4", NID_rc4, 8, &so[29]}, + {"rsaEncryption", "rsaEncryption", NID_rsaEncryption, 9, &so[37]}, + {"RSA-MD2", "md2WithRSAEncryption", NID_md2WithRSAEncryption, 9, &so[46]}, + {"RSA-MD5", "md5WithRSAEncryption", NID_md5WithRSAEncryption, 9, &so[55]}, + {"PBE-MD2-DES", "pbeWithMD2AndDES-CBC", NID_pbeWithMD2AndDES_CBC, 9, &so[64]}, + {"PBE-MD5-DES", "pbeWithMD5AndDES-CBC", NID_pbeWithMD5AndDES_CBC, 9, &so[73]}, + {"X500", "directory services (X.500)", NID_X500, 1, &so[82]}, + {"X509", "X509", NID_X509, 2, &so[83]}, + {"CN", "commonName", NID_commonName, 3, &so[85]}, + {"C", "countryName", NID_countryName, 3, &so[88]}, + {"L", "localityName", NID_localityName, 3, &so[91]}, + {"ST", "stateOrProvinceName", NID_stateOrProvinceName, 3, &so[94]}, + {"O", "organizationName", NID_organizationName, 3, &so[97]}, + {"OU", "organizationalUnitName", NID_organizationalUnitName, 3, &so[100]}, + {"RSA", "rsa", NID_rsa, 4, &so[103]}, + {"pkcs7", "pkcs7", NID_pkcs7, 8, &so[107]}, + {"pkcs7-data", "pkcs7-data", NID_pkcs7_data, 9, &so[115]}, + {"pkcs7-signedData", "pkcs7-signedData", NID_pkcs7_signed, 9, &so[124]}, + {"pkcs7-envelopedData", "pkcs7-envelopedData", NID_pkcs7_enveloped, 9, &so[133]}, + {"pkcs7-signedAndEnvelopedData", "pkcs7-signedAndEnvelopedData", NID_pkcs7_signedAndEnveloped, 9, &so[142]}, + {"pkcs7-digestData", "pkcs7-digestData", NID_pkcs7_digest, 9, &so[151]}, + {"pkcs7-encryptedData", "pkcs7-encryptedData", NID_pkcs7_encrypted, 9, &so[160]}, + {"pkcs3", "pkcs3", NID_pkcs3, 8, &so[169]}, + {"dhKeyAgreement", "dhKeyAgreement", NID_dhKeyAgreement, 9, &so[177]}, + {"DES-ECB", "des-ecb", NID_des_ecb, 5, &so[186]}, + {"DES-CFB", "des-cfb", NID_des_cfb64, 5, &so[191]}, + {"DES-CBC", "des-cbc", NID_des_cbc, 5, &so[196]}, + {"DES-EDE", "des-ede", NID_des_ede_ecb, 5, &so[201]}, + {"DES-EDE3", "des-ede3", NID_des_ede3_ecb}, + {"IDEA-CBC", "idea-cbc", NID_idea_cbc, 11, &so[206]}, + {"IDEA-CFB", "idea-cfb", NID_idea_cfb64}, + {"IDEA-ECB", "idea-ecb", NID_idea_ecb}, + {"RC2-CBC", "rc2-cbc", NID_rc2_cbc, 8, &so[217]}, + {"RC2-ECB", "rc2-ecb", NID_rc2_ecb}, + {"RC2-CFB", "rc2-cfb", NID_rc2_cfb64}, + {"RC2-OFB", "rc2-ofb", NID_rc2_ofb64}, + {"SHA", "sha", NID_sha, 5, &so[225]}, + {"RSA-SHA", "shaWithRSAEncryption", NID_shaWithRSAEncryption, 5, &so[230]}, + {"DES-EDE-CBC", "des-ede-cbc", NID_des_ede_cbc}, + {"DES-EDE3-CBC", "des-ede3-cbc", NID_des_ede3_cbc, 8, &so[235]}, + {"DES-OFB", "des-ofb", NID_des_ofb64, 5, &so[243]}, + {"IDEA-OFB", "idea-ofb", NID_idea_ofb64}, + {"pkcs9", "pkcs9", NID_pkcs9, 8, &so[248]}, + {"emailAddress", "emailAddress", NID_pkcs9_emailAddress, 9, &so[256]}, + {"unstructuredName", "unstructuredName", NID_pkcs9_unstructuredName, 9, &so[265]}, + {"contentType", "contentType", NID_pkcs9_contentType, 9, &so[274]}, + {"messageDigest", "messageDigest", NID_pkcs9_messageDigest, 9, &so[283]}, + {"signingTime", "signingTime", NID_pkcs9_signingTime, 9, &so[292]}, + {"countersignature", "countersignature", NID_pkcs9_countersignature, 9, &so[301]}, + {"challengePassword", "challengePassword", NID_pkcs9_challengePassword, 9, &so[310]}, + {"unstructuredAddress", "unstructuredAddress", NID_pkcs9_unstructuredAddress, 9, &so[319]}, + {"extendedCertificateAttributes", "extendedCertificateAttributes", NID_pkcs9_extCertAttributes, 9, &so[328]}, + {"Netscape", "Netscape Communications Corp.", NID_netscape, 7, &so[337]}, + {"nsCertExt", "Netscape Certificate Extension", NID_netscape_cert_extension, 8, &so[344]}, + {"nsDataType", "Netscape Data Type", NID_netscape_data_type, 8, &so[352]}, + {"DES-EDE-CFB", "des-ede-cfb", NID_des_ede_cfb64}, + {"DES-EDE3-CFB", "des-ede3-cfb", NID_des_ede3_cfb64}, + {"DES-EDE-OFB", "des-ede-ofb", NID_des_ede_ofb64}, + {"DES-EDE3-OFB", "des-ede3-ofb", NID_des_ede3_ofb64}, + {"SHA1", "sha1", NID_sha1, 5, &so[360]}, + {"RSA-SHA1", "sha1WithRSAEncryption", NID_sha1WithRSAEncryption, 9, &so[365]}, + {"DSA-SHA", "dsaWithSHA", NID_dsaWithSHA, 5, &so[374]}, + {"DSA-old", "dsaEncryption-old", NID_dsa_2, 5, &so[379]}, + {"PBE-SHA1-RC2-64", "pbeWithSHA1AndRC2-CBC", NID_pbeWithSHA1AndRC2_CBC, 9, &so[384]}, + {"PBKDF2", "PBKDF2", NID_id_pbkdf2, 9, &so[393]}, + {"DSA-SHA1-old", "dsaWithSHA1-old", NID_dsaWithSHA1_2, 5, &so[402]}, + {"nsCertType", "Netscape Cert Type", NID_netscape_cert_type, 9, &so[407]}, + {"nsBaseUrl", "Netscape Base Url", NID_netscape_base_url, 9, &so[416]}, + {"nsRevocationUrl", "Netscape Revocation Url", NID_netscape_revocation_url, 9, &so[425]}, + {"nsCaRevocationUrl", "Netscape CA Revocation Url", NID_netscape_ca_revocation_url, 9, &so[434]}, + {"nsRenewalUrl", "Netscape Renewal Url", NID_netscape_renewal_url, 9, &so[443]}, + {"nsCaPolicyUrl", "Netscape CA Policy Url", NID_netscape_ca_policy_url, 9, &so[452]}, + {"nsSslServerName", "Netscape SSL Server Name", NID_netscape_ssl_server_name, 9, &so[461]}, + {"nsComment", "Netscape Comment", NID_netscape_comment, 9, &so[470]}, + {"nsCertSequence", "Netscape Certificate Sequence", NID_netscape_cert_sequence, 9, &so[479]}, + {"DESX-CBC", "desx-cbc", NID_desx_cbc}, + {"id-ce", "id-ce", NID_id_ce, 2, &so[488]}, + {"subjectKeyIdentifier", "X509v3 Subject Key Identifier", NID_subject_key_identifier, 3, &so[490]}, + {"keyUsage", "X509v3 Key Usage", NID_key_usage, 3, &so[493]}, + {"privateKeyUsagePeriod", "X509v3 Private Key Usage Period", NID_private_key_usage_period, 3, &so[496]}, + {"subjectAltName", "X509v3 Subject Alternative Name", NID_subject_alt_name, 3, &so[499]}, + {"issuerAltName", "X509v3 Issuer Alternative Name", NID_issuer_alt_name, 3, &so[502]}, + {"basicConstraints", "X509v3 Basic Constraints", NID_basic_constraints, 3, &so[505]}, + {"crlNumber", "X509v3 CRL Number", NID_crl_number, 3, &so[508]}, + {"certificatePolicies", "X509v3 Certificate Policies", NID_certificate_policies, 3, &so[511]}, + {"authorityKeyIdentifier", "X509v3 Authority Key Identifier", NID_authority_key_identifier, 3, &so[514]}, + {"BF-CBC", "bf-cbc", NID_bf_cbc, 9, &so[517]}, + {"BF-ECB", "bf-ecb", NID_bf_ecb}, + {"BF-CFB", "bf-cfb", NID_bf_cfb64}, + {"BF-OFB", "bf-ofb", NID_bf_ofb64}, + {"MDC2", "mdc2", NID_mdc2, 4, &so[526]}, + {"RSA-MDC2", "mdc2WithRSA", NID_mdc2WithRSA, 4, &so[530]}, + {"RC4-40", "rc4-40", NID_rc4_40}, + {"RC2-40-CBC", "rc2-40-cbc", NID_rc2_40_cbc}, + {"GN", "givenName", NID_givenName, 3, &so[534]}, + {"SN", "surname", NID_surname, 3, &so[537]}, + {"initials", "initials", NID_initials, 3, &so[540]}, + {"uid", "uniqueIdentifier", NID_uniqueIdentifier, 10, &so[543]}, + {"crlDistributionPoints", "X509v3 CRL Distribution Points", NID_crl_distribution_points, 3, &so[553]}, + {"RSA-NP-MD5", "md5WithRSA", NID_md5WithRSA, 5, &so[556]}, + {"serialNumber", "serialNumber", NID_serialNumber, 3, &so[561]}, + {"title", "title", NID_title, 3, &so[564]}, + {"description", "description", NID_description, 3, &so[567]}, + {"CAST5-CBC", "cast5-cbc", NID_cast5_cbc, 9, &so[570]}, + {"CAST5-ECB", "cast5-ecb", NID_cast5_ecb}, + {"CAST5-CFB", "cast5-cfb", NID_cast5_cfb64}, + {"CAST5-OFB", "cast5-ofb", NID_cast5_ofb64}, + {"pbeWithMD5AndCast5CBC", "pbeWithMD5AndCast5CBC", NID_pbeWithMD5AndCast5_CBC, 9, &so[579]}, + {"DSA-SHA1", "dsaWithSHA1", NID_dsaWithSHA1, 7, &so[588]}, + {"MD5-SHA1", "md5-sha1", NID_md5_sha1}, + {"RSA-SHA1-2", "sha1WithRSA", NID_sha1WithRSA, 5, &so[595]}, + {"DSA", "dsaEncryption", NID_dsa, 7, &so[600]}, + {"RIPEMD160", "ripemd160", NID_ripemd160, 5, &so[607]}, + { NULL, NULL, NID_undef }, + {"RSA-RIPEMD160", "ripemd160WithRSA", NID_ripemd160WithRSA, 6, &so[612]}, + {"RC5-CBC", "rc5-cbc", NID_rc5_cbc, 8, &so[618]}, + {"RC5-ECB", "rc5-ecb", NID_rc5_ecb}, + {"RC5-CFB", "rc5-cfb", NID_rc5_cfb64}, + {"RC5-OFB", "rc5-ofb", NID_rc5_ofb64}, + { NULL, NULL, NID_undef }, + {"ZLIB", "zlib compression", NID_zlib_compression, 11, &so[626]}, + {"extendedKeyUsage", "X509v3 Extended Key Usage", NID_ext_key_usage, 3, &so[637]}, + {"PKIX", "PKIX", NID_id_pkix, 6, &so[640]}, + {"id-kp", "id-kp", NID_id_kp, 7, &so[646]}, + {"serverAuth", "TLS Web Server Authentication", NID_server_auth, 8, &so[653]}, + {"clientAuth", "TLS Web Client Authentication", NID_client_auth, 8, &so[661]}, + {"codeSigning", "Code Signing", NID_code_sign, 8, &so[669]}, + {"emailProtection", "E-mail Protection", NID_email_protect, 8, &so[677]}, + {"timeStamping", "Time Stamping", NID_time_stamp, 8, &so[685]}, + {"msCodeInd", "Microsoft Individual Code Signing", NID_ms_code_ind, 10, &so[693]}, + {"msCodeCom", "Microsoft Commercial Code Signing", NID_ms_code_com, 10, &so[703]}, + {"msCTLSign", "Microsoft Trust List Signing", NID_ms_ctl_sign, 10, &so[713]}, + {"msSGC", "Microsoft Server Gated Crypto", NID_ms_sgc, 10, &so[723]}, + {"msEFS", "Microsoft Encrypted File System", NID_ms_efs, 10, &so[733]}, + {"nsSGC", "Netscape Server Gated Crypto", NID_ns_sgc, 9, &so[743]}, + {"deltaCRL", "X509v3 Delta CRL Indicator", NID_delta_crl, 3, &so[752]}, + {"CRLReason", "X509v3 CRL Reason Code", NID_crl_reason, 3, &so[755]}, + {"invalidityDate", "Invalidity Date", NID_invalidity_date, 3, &so[758]}, + {"SXNetID", "Strong Extranet ID", NID_sxnet, 5, &so[761]}, + {"PBE-SHA1-RC4-128", "pbeWithSHA1And128BitRC4", NID_pbe_WithSHA1And128BitRC4, 10, &so[766]}, + {"PBE-SHA1-RC4-40", "pbeWithSHA1And40BitRC4", NID_pbe_WithSHA1And40BitRC4, 10, &so[776]}, + {"PBE-SHA1-3DES", "pbeWithSHA1And3-KeyTripleDES-CBC", NID_pbe_WithSHA1And3_Key_TripleDES_CBC, 10, &so[786]}, + {"PBE-SHA1-2DES", "pbeWithSHA1And2-KeyTripleDES-CBC", NID_pbe_WithSHA1And2_Key_TripleDES_CBC, 10, &so[796]}, + {"PBE-SHA1-RC2-128", "pbeWithSHA1And128BitRC2-CBC", NID_pbe_WithSHA1And128BitRC2_CBC, 10, &so[806]}, + {"PBE-SHA1-RC2-40", "pbeWithSHA1And40BitRC2-CBC", NID_pbe_WithSHA1And40BitRC2_CBC, 10, &so[816]}, + {"keyBag", "keyBag", NID_keyBag, 11, &so[826]}, + {"pkcs8ShroudedKeyBag", "pkcs8ShroudedKeyBag", NID_pkcs8ShroudedKeyBag, 11, &so[837]}, + {"certBag", "certBag", NID_certBag, 11, &so[848]}, + {"crlBag", "crlBag", NID_crlBag, 11, &so[859]}, + {"secretBag", "secretBag", NID_secretBag, 11, &so[870]}, + {"safeContentsBag", "safeContentsBag", NID_safeContentsBag, 11, &so[881]}, + {"friendlyName", "friendlyName", NID_friendlyName, 9, &so[892]}, + {"localKeyID", "localKeyID", NID_localKeyID, 9, &so[901]}, + {"x509Certificate", "x509Certificate", NID_x509Certificate, 10, &so[910]}, + {"sdsiCertificate", "sdsiCertificate", NID_sdsiCertificate, 10, &so[920]}, + {"x509Crl", "x509Crl", NID_x509Crl, 10, &so[930]}, + {"PBES2", "PBES2", NID_pbes2, 9, &so[940]}, + {"PBMAC1", "PBMAC1", NID_pbmac1, 9, &so[949]}, + {"hmacWithSHA1", "hmacWithSHA1", NID_hmacWithSHA1, 8, &so[958]}, + {"id-qt-cps", "Policy Qualifier CPS", NID_id_qt_cps, 8, &so[966]}, + {"id-qt-unotice", "Policy Qualifier User Notice", NID_id_qt_unotice, 8, &so[974]}, + {"RC2-64-CBC", "rc2-64-cbc", NID_rc2_64_cbc}, + {"SMIME-CAPS", "S/MIME Capabilities", NID_SMIMECapabilities, 9, &so[982]}, + {"PBE-MD2-RC2-64", "pbeWithMD2AndRC2-CBC", NID_pbeWithMD2AndRC2_CBC, 9, &so[991]}, + {"PBE-MD5-RC2-64", "pbeWithMD5AndRC2-CBC", NID_pbeWithMD5AndRC2_CBC, 9, &so[1000]}, + {"PBE-SHA1-DES", "pbeWithSHA1AndDES-CBC", NID_pbeWithSHA1AndDES_CBC, 9, &so[1009]}, + {"msExtReq", "Microsoft Extension Request", NID_ms_ext_req, 10, &so[1018]}, + {"extReq", "Extension Request", NID_ext_req, 9, &so[1028]}, + {"name", "name", NID_name, 3, &so[1037]}, + {"dnQualifier", "dnQualifier", NID_dnQualifier, 3, &so[1040]}, + {"id-pe", "id-pe", NID_id_pe, 7, &so[1043]}, + {"id-ad", "id-ad", NID_id_ad, 7, &so[1050]}, + {"authorityInfoAccess", "Authority Information Access", NID_info_access, 8, &so[1057]}, + {"OCSP", "OCSP", NID_ad_OCSP, 8, &so[1065]}, + {"caIssuers", "CA Issuers", NID_ad_ca_issuers, 8, &so[1073]}, + {"OCSPSigning", "OCSP Signing", NID_OCSP_sign, 8, &so[1081]}, + {"ISO", "iso", NID_iso}, + {"member-body", "ISO Member Body", NID_member_body, 1, &so[1089]}, + {"ISO-US", "ISO US Member Body", NID_ISO_US, 3, &so[1090]}, + {"X9-57", "X9.57", NID_X9_57, 5, &so[1093]}, + {"X9cm", "X9.57 CM ?", NID_X9cm, 6, &so[1098]}, + {"pkcs1", "pkcs1", NID_pkcs1, 8, &so[1104]}, + {"pkcs5", "pkcs5", NID_pkcs5, 8, &so[1112]}, + {"SMIME", "S/MIME", NID_SMIME, 9, &so[1120]}, + {"id-smime-mod", "id-smime-mod", NID_id_smime_mod, 10, &so[1129]}, + {"id-smime-ct", "id-smime-ct", NID_id_smime_ct, 10, &so[1139]}, + {"id-smime-aa", "id-smime-aa", NID_id_smime_aa, 10, &so[1149]}, + {"id-smime-alg", "id-smime-alg", NID_id_smime_alg, 10, &so[1159]}, + {"id-smime-cd", "id-smime-cd", NID_id_smime_cd, 10, &so[1169]}, + {"id-smime-spq", "id-smime-spq", NID_id_smime_spq, 10, &so[1179]}, + {"id-smime-cti", "id-smime-cti", NID_id_smime_cti, 10, &so[1189]}, + {"id-smime-mod-cms", "id-smime-mod-cms", NID_id_smime_mod_cms, 11, &so[1199]}, + {"id-smime-mod-ess", "id-smime-mod-ess", NID_id_smime_mod_ess, 11, &so[1210]}, + {"id-smime-mod-oid", "id-smime-mod-oid", NID_id_smime_mod_oid, 11, &so[1221]}, + {"id-smime-mod-msg-v3", "id-smime-mod-msg-v3", NID_id_smime_mod_msg_v3, 11, &so[1232]}, + {"id-smime-mod-ets-eSignature-88", "id-smime-mod-ets-eSignature-88", NID_id_smime_mod_ets_eSignature_88, 11, &so[1243]}, + {"id-smime-mod-ets-eSignature-97", "id-smime-mod-ets-eSignature-97", NID_id_smime_mod_ets_eSignature_97, 11, &so[1254]}, + {"id-smime-mod-ets-eSigPolicy-88", "id-smime-mod-ets-eSigPolicy-88", NID_id_smime_mod_ets_eSigPolicy_88, 11, &so[1265]}, + {"id-smime-mod-ets-eSigPolicy-97", "id-smime-mod-ets-eSigPolicy-97", NID_id_smime_mod_ets_eSigPolicy_97, 11, &so[1276]}, + {"id-smime-ct-receipt", "id-smime-ct-receipt", NID_id_smime_ct_receipt, 11, &so[1287]}, + {"id-smime-ct-authData", "id-smime-ct-authData", NID_id_smime_ct_authData, 11, &so[1298]}, + {"id-smime-ct-publishCert", "id-smime-ct-publishCert", NID_id_smime_ct_publishCert, 11, &so[1309]}, + {"id-smime-ct-TSTInfo", "id-smime-ct-TSTInfo", NID_id_smime_ct_TSTInfo, 11, &so[1320]}, + {"id-smime-ct-TDTInfo", "id-smime-ct-TDTInfo", NID_id_smime_ct_TDTInfo, 11, &so[1331]}, + {"id-smime-ct-contentInfo", "id-smime-ct-contentInfo", NID_id_smime_ct_contentInfo, 11, &so[1342]}, + {"id-smime-ct-DVCSRequestData", "id-smime-ct-DVCSRequestData", NID_id_smime_ct_DVCSRequestData, 11, &so[1353]}, + {"id-smime-ct-DVCSResponseData", "id-smime-ct-DVCSResponseData", NID_id_smime_ct_DVCSResponseData, 11, &so[1364]}, + {"id-smime-aa-receiptRequest", "id-smime-aa-receiptRequest", NID_id_smime_aa_receiptRequest, 11, &so[1375]}, + {"id-smime-aa-securityLabel", "id-smime-aa-securityLabel", NID_id_smime_aa_securityLabel, 11, &so[1386]}, + {"id-smime-aa-mlExpandHistory", "id-smime-aa-mlExpandHistory", NID_id_smime_aa_mlExpandHistory, 11, &so[1397]}, + {"id-smime-aa-contentHint", "id-smime-aa-contentHint", NID_id_smime_aa_contentHint, 11, &so[1408]}, + {"id-smime-aa-msgSigDigest", "id-smime-aa-msgSigDigest", NID_id_smime_aa_msgSigDigest, 11, &so[1419]}, + {"id-smime-aa-encapContentType", "id-smime-aa-encapContentType", NID_id_smime_aa_encapContentType, 11, &so[1430]}, + {"id-smime-aa-contentIdentifier", "id-smime-aa-contentIdentifier", NID_id_smime_aa_contentIdentifier, 11, &so[1441]}, + {"id-smime-aa-macValue", "id-smime-aa-macValue", NID_id_smime_aa_macValue, 11, &so[1452]}, + {"id-smime-aa-equivalentLabels", "id-smime-aa-equivalentLabels", NID_id_smime_aa_equivalentLabels, 11, &so[1463]}, + {"id-smime-aa-contentReference", "id-smime-aa-contentReference", NID_id_smime_aa_contentReference, 11, &so[1474]}, + {"id-smime-aa-encrypKeyPref", "id-smime-aa-encrypKeyPref", NID_id_smime_aa_encrypKeyPref, 11, &so[1485]}, + {"id-smime-aa-signingCertificate", "id-smime-aa-signingCertificate", NID_id_smime_aa_signingCertificate, 11, &so[1496]}, + {"id-smime-aa-smimeEncryptCerts", "id-smime-aa-smimeEncryptCerts", NID_id_smime_aa_smimeEncryptCerts, 11, &so[1507]}, + {"id-smime-aa-timeStampToken", "id-smime-aa-timeStampToken", NID_id_smime_aa_timeStampToken, 11, &so[1518]}, + {"id-smime-aa-ets-sigPolicyId", "id-smime-aa-ets-sigPolicyId", NID_id_smime_aa_ets_sigPolicyId, 11, &so[1529]}, + {"id-smime-aa-ets-commitmentType", "id-smime-aa-ets-commitmentType", NID_id_smime_aa_ets_commitmentType, 11, &so[1540]}, + {"id-smime-aa-ets-signerLocation", "id-smime-aa-ets-signerLocation", NID_id_smime_aa_ets_signerLocation, 11, &so[1551]}, + {"id-smime-aa-ets-signerAttr", "id-smime-aa-ets-signerAttr", NID_id_smime_aa_ets_signerAttr, 11, &so[1562]}, + {"id-smime-aa-ets-otherSigCert", "id-smime-aa-ets-otherSigCert", NID_id_smime_aa_ets_otherSigCert, 11, &so[1573]}, + {"id-smime-aa-ets-contentTimestamp", "id-smime-aa-ets-contentTimestamp", NID_id_smime_aa_ets_contentTimestamp, 11, &so[1584]}, + {"id-smime-aa-ets-CertificateRefs", "id-smime-aa-ets-CertificateRefs", NID_id_smime_aa_ets_CertificateRefs, 11, &so[1595]}, + {"id-smime-aa-ets-RevocationRefs", "id-smime-aa-ets-RevocationRefs", NID_id_smime_aa_ets_RevocationRefs, 11, &so[1606]}, + {"id-smime-aa-ets-certValues", "id-smime-aa-ets-certValues", NID_id_smime_aa_ets_certValues, 11, &so[1617]}, + {"id-smime-aa-ets-revocationValues", "id-smime-aa-ets-revocationValues", NID_id_smime_aa_ets_revocationValues, 11, &so[1628]}, + {"id-smime-aa-ets-escTimeStamp", "id-smime-aa-ets-escTimeStamp", NID_id_smime_aa_ets_escTimeStamp, 11, &so[1639]}, + {"id-smime-aa-ets-certCRLTimestamp", "id-smime-aa-ets-certCRLTimestamp", NID_id_smime_aa_ets_certCRLTimestamp, 11, &so[1650]}, + {"id-smime-aa-ets-archiveTimeStamp", "id-smime-aa-ets-archiveTimeStamp", NID_id_smime_aa_ets_archiveTimeStamp, 11, &so[1661]}, + {"id-smime-aa-signatureType", "id-smime-aa-signatureType", NID_id_smime_aa_signatureType, 11, &so[1672]}, + {"id-smime-aa-dvcs-dvc", "id-smime-aa-dvcs-dvc", NID_id_smime_aa_dvcs_dvc, 11, &so[1683]}, + {"id-smime-alg-ESDHwith3DES", "id-smime-alg-ESDHwith3DES", NID_id_smime_alg_ESDHwith3DES, 11, &so[1694]}, + {"id-smime-alg-ESDHwithRC2", "id-smime-alg-ESDHwithRC2", NID_id_smime_alg_ESDHwithRC2, 11, &so[1705]}, + {"id-smime-alg-3DESwrap", "id-smime-alg-3DESwrap", NID_id_smime_alg_3DESwrap, 11, &so[1716]}, + {"id-smime-alg-RC2wrap", "id-smime-alg-RC2wrap", NID_id_smime_alg_RC2wrap, 11, &so[1727]}, + {"id-smime-alg-ESDH", "id-smime-alg-ESDH", NID_id_smime_alg_ESDH, 11, &so[1738]}, + {"id-smime-alg-CMS3DESwrap", "id-smime-alg-CMS3DESwrap", NID_id_smime_alg_CMS3DESwrap, 11, &so[1749]}, + {"id-smime-alg-CMSRC2wrap", "id-smime-alg-CMSRC2wrap", NID_id_smime_alg_CMSRC2wrap, 11, &so[1760]}, + {"id-smime-cd-ldap", "id-smime-cd-ldap", NID_id_smime_cd_ldap, 11, &so[1771]}, + {"id-smime-spq-ets-sqt-uri", "id-smime-spq-ets-sqt-uri", NID_id_smime_spq_ets_sqt_uri, 11, &so[1782]}, + {"id-smime-spq-ets-sqt-unotice", "id-smime-spq-ets-sqt-unotice", NID_id_smime_spq_ets_sqt_unotice, 11, &so[1793]}, + {"id-smime-cti-ets-proofOfOrigin", "id-smime-cti-ets-proofOfOrigin", NID_id_smime_cti_ets_proofOfOrigin, 11, &so[1804]}, + {"id-smime-cti-ets-proofOfReceipt", "id-smime-cti-ets-proofOfReceipt", NID_id_smime_cti_ets_proofOfReceipt, 11, &so[1815]}, + {"id-smime-cti-ets-proofOfDelivery", "id-smime-cti-ets-proofOfDelivery", NID_id_smime_cti_ets_proofOfDelivery, 11, &so[1826]}, + {"id-smime-cti-ets-proofOfSender", "id-smime-cti-ets-proofOfSender", NID_id_smime_cti_ets_proofOfSender, 11, &so[1837]}, + {"id-smime-cti-ets-proofOfApproval", "id-smime-cti-ets-proofOfApproval", NID_id_smime_cti_ets_proofOfApproval, 11, &so[1848]}, + {"id-smime-cti-ets-proofOfCreation", "id-smime-cti-ets-proofOfCreation", NID_id_smime_cti_ets_proofOfCreation, 11, &so[1859]}, + {"MD4", "md4", NID_md4, 8, &so[1870]}, + {"id-pkix-mod", "id-pkix-mod", NID_id_pkix_mod, 7, &so[1878]}, + {"id-qt", "id-qt", NID_id_qt, 7, &so[1885]}, + {"id-it", "id-it", NID_id_it, 7, &so[1892]}, + {"id-pkip", "id-pkip", NID_id_pkip, 7, &so[1899]}, + {"id-alg", "id-alg", NID_id_alg, 7, &so[1906]}, + {"id-cmc", "id-cmc", NID_id_cmc, 7, &so[1913]}, + {"id-on", "id-on", NID_id_on, 7, &so[1920]}, + {"id-pda", "id-pda", NID_id_pda, 7, &so[1927]}, + {"id-aca", "id-aca", NID_id_aca, 7, &so[1934]}, + {"id-qcs", "id-qcs", NID_id_qcs, 7, &so[1941]}, + {"id-cct", "id-cct", NID_id_cct, 7, &so[1948]}, + {"id-pkix1-explicit-88", "id-pkix1-explicit-88", NID_id_pkix1_explicit_88, 8, &so[1955]}, + {"id-pkix1-implicit-88", "id-pkix1-implicit-88", NID_id_pkix1_implicit_88, 8, &so[1963]}, + {"id-pkix1-explicit-93", "id-pkix1-explicit-93", NID_id_pkix1_explicit_93, 8, &so[1971]}, + {"id-pkix1-implicit-93", "id-pkix1-implicit-93", NID_id_pkix1_implicit_93, 8, &so[1979]}, + {"id-mod-crmf", "id-mod-crmf", NID_id_mod_crmf, 8, &so[1987]}, + {"id-mod-cmc", "id-mod-cmc", NID_id_mod_cmc, 8, &so[1995]}, + {"id-mod-kea-profile-88", "id-mod-kea-profile-88", NID_id_mod_kea_profile_88, 8, &so[2003]}, + {"id-mod-kea-profile-93", "id-mod-kea-profile-93", NID_id_mod_kea_profile_93, 8, &so[2011]}, + {"id-mod-cmp", "id-mod-cmp", NID_id_mod_cmp, 8, &so[2019]}, + {"id-mod-qualified-cert-88", "id-mod-qualified-cert-88", NID_id_mod_qualified_cert_88, 8, &so[2027]}, + {"id-mod-qualified-cert-93", "id-mod-qualified-cert-93", NID_id_mod_qualified_cert_93, 8, &so[2035]}, + {"id-mod-attribute-cert", "id-mod-attribute-cert", NID_id_mod_attribute_cert, 8, &so[2043]}, + {"id-mod-timestamp-protocol", "id-mod-timestamp-protocol", NID_id_mod_timestamp_protocol, 8, &so[2051]}, + {"id-mod-ocsp", "id-mod-ocsp", NID_id_mod_ocsp, 8, &so[2059]}, + {"id-mod-dvcs", "id-mod-dvcs", NID_id_mod_dvcs, 8, &so[2067]}, + {"id-mod-cmp2000", "id-mod-cmp2000", NID_id_mod_cmp2000, 8, &so[2075]}, + {"biometricInfo", "Biometric Info", NID_biometricInfo, 8, &so[2083]}, + {"qcStatements", "qcStatements", NID_qcStatements, 8, &so[2091]}, + {"ac-auditEntity", "ac-auditEntity", NID_ac_auditEntity, 8, &so[2099]}, + {"ac-targeting", "ac-targeting", NID_ac_targeting, 8, &so[2107]}, + {"aaControls", "aaControls", NID_aaControls, 8, &so[2115]}, + {"sbgp-ipAddrBlock", "sbgp-ipAddrBlock", NID_sbgp_ipAddrBlock, 8, &so[2123]}, + {"sbgp-autonomousSysNum", "sbgp-autonomousSysNum", NID_sbgp_autonomousSysNum, 8, &so[2131]}, + {"sbgp-routerIdentifier", "sbgp-routerIdentifier", NID_sbgp_routerIdentifier, 8, &so[2139]}, + {"textNotice", "textNotice", NID_textNotice, 8, &so[2147]}, + {"ipsecEndSystem", "IPSec End System", NID_ipsecEndSystem, 8, &so[2155]}, + {"ipsecTunnel", "IPSec Tunnel", NID_ipsecTunnel, 8, &so[2163]}, + {"ipsecUser", "IPSec User", NID_ipsecUser, 8, &so[2171]}, + {"DVCS", "dvcs", NID_dvcs, 8, &so[2179]}, + {"id-it-caProtEncCert", "id-it-caProtEncCert", NID_id_it_caProtEncCert, 8, &so[2187]}, + {"id-it-signKeyPairTypes", "id-it-signKeyPairTypes", NID_id_it_signKeyPairTypes, 8, &so[2195]}, + {"id-it-encKeyPairTypes", "id-it-encKeyPairTypes", NID_id_it_encKeyPairTypes, 8, &so[2203]}, + {"id-it-preferredSymmAlg", "id-it-preferredSymmAlg", NID_id_it_preferredSymmAlg, 8, &so[2211]}, + {"id-it-caKeyUpdateInfo", "id-it-caKeyUpdateInfo", NID_id_it_caKeyUpdateInfo, 8, &so[2219]}, + {"id-it-currentCRL", "id-it-currentCRL", NID_id_it_currentCRL, 8, &so[2227]}, + {"id-it-unsupportedOIDs", "id-it-unsupportedOIDs", NID_id_it_unsupportedOIDs, 8, &so[2235]}, + {"id-it-subscriptionRequest", "id-it-subscriptionRequest", NID_id_it_subscriptionRequest, 8, &so[2243]}, + {"id-it-subscriptionResponse", "id-it-subscriptionResponse", NID_id_it_subscriptionResponse, 8, &so[2251]}, + {"id-it-keyPairParamReq", "id-it-keyPairParamReq", NID_id_it_keyPairParamReq, 8, &so[2259]}, + {"id-it-keyPairParamRep", "id-it-keyPairParamRep", NID_id_it_keyPairParamRep, 8, &so[2267]}, + {"id-it-revPassphrase", "id-it-revPassphrase", NID_id_it_revPassphrase, 8, &so[2275]}, + {"id-it-implicitConfirm", "id-it-implicitConfirm", NID_id_it_implicitConfirm, 8, &so[2283]}, + {"id-it-confirmWaitTime", "id-it-confirmWaitTime", NID_id_it_confirmWaitTime, 8, &so[2291]}, + {"id-it-origPKIMessage", "id-it-origPKIMessage", NID_id_it_origPKIMessage, 8, &so[2299]}, + {"id-regCtrl", "id-regCtrl", NID_id_regCtrl, 8, &so[2307]}, + {"id-regInfo", "id-regInfo", NID_id_regInfo, 8, &so[2315]}, + {"id-regCtrl-regToken", "id-regCtrl-regToken", NID_id_regCtrl_regToken, 9, &so[2323]}, + {"id-regCtrl-authenticator", "id-regCtrl-authenticator", NID_id_regCtrl_authenticator, 9, &so[2332]}, + {"id-regCtrl-pkiPublicationInfo", "id-regCtrl-pkiPublicationInfo", NID_id_regCtrl_pkiPublicationInfo, 9, &so[2341]}, + {"id-regCtrl-pkiArchiveOptions", "id-regCtrl-pkiArchiveOptions", NID_id_regCtrl_pkiArchiveOptions, 9, &so[2350]}, + {"id-regCtrl-oldCertID", "id-regCtrl-oldCertID", NID_id_regCtrl_oldCertID, 9, &so[2359]}, + {"id-regCtrl-protocolEncrKey", "id-regCtrl-protocolEncrKey", NID_id_regCtrl_protocolEncrKey, 9, &so[2368]}, + {"id-regInfo-utf8Pairs", "id-regInfo-utf8Pairs", NID_id_regInfo_utf8Pairs, 9, &so[2377]}, + {"id-regInfo-certReq", "id-regInfo-certReq", NID_id_regInfo_certReq, 9, &so[2386]}, + {"id-alg-des40", "id-alg-des40", NID_id_alg_des40, 8, &so[2395]}, + {"id-alg-noSignature", "id-alg-noSignature", NID_id_alg_noSignature, 8, &so[2403]}, + {"id-alg-dh-sig-hmac-sha1", "id-alg-dh-sig-hmac-sha1", NID_id_alg_dh_sig_hmac_sha1, 8, &so[2411]}, + {"id-alg-dh-pop", "id-alg-dh-pop", NID_id_alg_dh_pop, 8, &so[2419]}, + {"id-cmc-statusInfo", "id-cmc-statusInfo", NID_id_cmc_statusInfo, 8, &so[2427]}, + {"id-cmc-identification", "id-cmc-identification", NID_id_cmc_identification, 8, &so[2435]}, + {"id-cmc-identityProof", "id-cmc-identityProof", NID_id_cmc_identityProof, 8, &so[2443]}, + {"id-cmc-dataReturn", "id-cmc-dataReturn", NID_id_cmc_dataReturn, 8, &so[2451]}, + {"id-cmc-transactionId", "id-cmc-transactionId", NID_id_cmc_transactionId, 8, &so[2459]}, + {"id-cmc-senderNonce", "id-cmc-senderNonce", NID_id_cmc_senderNonce, 8, &so[2467]}, + {"id-cmc-recipientNonce", "id-cmc-recipientNonce", NID_id_cmc_recipientNonce, 8, &so[2475]}, + {"id-cmc-addExtensions", "id-cmc-addExtensions", NID_id_cmc_addExtensions, 8, &so[2483]}, + {"id-cmc-encryptedPOP", "id-cmc-encryptedPOP", NID_id_cmc_encryptedPOP, 8, &so[2491]}, + {"id-cmc-decryptedPOP", "id-cmc-decryptedPOP", NID_id_cmc_decryptedPOP, 8, &so[2499]}, + {"id-cmc-lraPOPWitness", "id-cmc-lraPOPWitness", NID_id_cmc_lraPOPWitness, 8, &so[2507]}, + {"id-cmc-getCert", "id-cmc-getCert", NID_id_cmc_getCert, 8, &so[2515]}, + {"id-cmc-getCRL", "id-cmc-getCRL", NID_id_cmc_getCRL, 8, &so[2523]}, + {"id-cmc-revokeRequest", "id-cmc-revokeRequest", NID_id_cmc_revokeRequest, 8, &so[2531]}, + {"id-cmc-regInfo", "id-cmc-regInfo", NID_id_cmc_regInfo, 8, &so[2539]}, + {"id-cmc-responseInfo", "id-cmc-responseInfo", NID_id_cmc_responseInfo, 8, &so[2547]}, + {"id-cmc-queryPending", "id-cmc-queryPending", NID_id_cmc_queryPending, 8, &so[2555]}, + {"id-cmc-popLinkRandom", "id-cmc-popLinkRandom", NID_id_cmc_popLinkRandom, 8, &so[2563]}, + {"id-cmc-popLinkWitness", "id-cmc-popLinkWitness", NID_id_cmc_popLinkWitness, 8, &so[2571]}, + {"id-cmc-confirmCertAcceptance", "id-cmc-confirmCertAcceptance", NID_id_cmc_confirmCertAcceptance, 8, &so[2579]}, + {"id-on-personalData", "id-on-personalData", NID_id_on_personalData, 8, &so[2587]}, + {"id-pda-dateOfBirth", "id-pda-dateOfBirth", NID_id_pda_dateOfBirth, 8, &so[2595]}, + {"id-pda-placeOfBirth", "id-pda-placeOfBirth", NID_id_pda_placeOfBirth, 8, &so[2603]}, + { NULL, NULL, NID_undef }, + {"id-pda-gender", "id-pda-gender", NID_id_pda_gender, 8, &so[2611]}, + {"id-pda-countryOfCitizenship", "id-pda-countryOfCitizenship", NID_id_pda_countryOfCitizenship, 8, &so[2619]}, + {"id-pda-countryOfResidence", "id-pda-countryOfResidence", NID_id_pda_countryOfResidence, 8, &so[2627]}, + {"id-aca-authenticationInfo", "id-aca-authenticationInfo", NID_id_aca_authenticationInfo, 8, &so[2635]}, + {"id-aca-accessIdentity", "id-aca-accessIdentity", NID_id_aca_accessIdentity, 8, &so[2643]}, + {"id-aca-chargingIdentity", "id-aca-chargingIdentity", NID_id_aca_chargingIdentity, 8, &so[2651]}, + {"id-aca-group", "id-aca-group", NID_id_aca_group, 8, &so[2659]}, + {"id-aca-role", "id-aca-role", NID_id_aca_role, 8, &so[2667]}, + {"id-qcs-pkixQCSyntax-v1", "id-qcs-pkixQCSyntax-v1", NID_id_qcs_pkixQCSyntax_v1, 8, &so[2675]}, + {"id-cct-crs", "id-cct-crs", NID_id_cct_crs, 8, &so[2683]}, + {"id-cct-PKIData", "id-cct-PKIData", NID_id_cct_PKIData, 8, &so[2691]}, + {"id-cct-PKIResponse", "id-cct-PKIResponse", NID_id_cct_PKIResponse, 8, &so[2699]}, + {"ad_timestamping", "AD Time Stamping", NID_ad_timeStamping, 8, &so[2707]}, + {"AD_DVCS", "ad dvcs", NID_ad_dvcs, 8, &so[2715]}, + {"basicOCSPResponse", "Basic OCSP Response", NID_id_pkix_OCSP_basic, 9, &so[2723]}, + {"Nonce", "OCSP Nonce", NID_id_pkix_OCSP_Nonce, 9, &so[2732]}, + {"CrlID", "OCSP CRL ID", NID_id_pkix_OCSP_CrlID, 9, &so[2741]}, + {"acceptableResponses", "Acceptable OCSP Responses", NID_id_pkix_OCSP_acceptableResponses, 9, &so[2750]}, + {"noCheck", "OCSP No Check", NID_id_pkix_OCSP_noCheck, 9, &so[2759]}, + {"archiveCutoff", "OCSP Archive Cutoff", NID_id_pkix_OCSP_archiveCutoff, 9, &so[2768]}, + {"serviceLocator", "OCSP Service Locator", NID_id_pkix_OCSP_serviceLocator, 9, &so[2777]}, + {"extendedStatus", "Extended OCSP Status", NID_id_pkix_OCSP_extendedStatus, 9, &so[2786]}, + {"valid", "valid", NID_id_pkix_OCSP_valid, 9, &so[2795]}, + {"path", "path", NID_id_pkix_OCSP_path, 9, &so[2804]}, + {"trustRoot", "Trust Root", NID_id_pkix_OCSP_trustRoot, 9, &so[2813]}, + {"algorithm", "algorithm", NID_algorithm, 4, &so[2822]}, + {"rsaSignature", "rsaSignature", NID_rsaSignature, 5, &so[2826]}, + {"X500algorithms", "directory services - algorithms", NID_X500algorithms, 2, &so[2831]}, + {"ORG", "org", NID_org, 1, &so[2833]}, + {"DOD", "dod", NID_dod, 2, &so[2834]}, + {"IANA", "iana", NID_iana, 3, &so[2836]}, + {"directory", "Directory", NID_Directory, 4, &so[2839]}, + {"mgmt", "Management", NID_Management, 4, &so[2843]}, + {"experimental", "Experimental", NID_Experimental, 4, &so[2847]}, + {"private", "Private", NID_Private, 4, &so[2851]}, + {"security", "Security", NID_Security, 4, &so[2855]}, + {"snmpv2", "SNMPv2", NID_SNMPv2, 4, &so[2859]}, + {"Mail", "Mail", NID_Mail, 4, &so[2863]}, + {"enterprises", "Enterprises", NID_Enterprises, 5, &so[2867]}, + {"dcobject", "dcObject", NID_dcObject, 9, &so[2872]}, + {"DC", "domainComponent", NID_domainComponent, 10, &so[2881]}, + {"domain", "Domain", NID_Domain, 10, &so[2891]}, + {"NULL", "NULL", NID_joint_iso_ccitt}, + {"selected-attribute-types", "Selected Attribute Types", NID_selected_attribute_types, 3, &so[2901]}, + {"clearance", "clearance", NID_clearance, 4, &so[2904]}, + {"RSA-MD4", "md4WithRSAEncryption", NID_md4WithRSAEncryption, 9, &so[2908]}, + {"ac-proxying", "ac-proxying", NID_ac_proxying, 8, &so[2917]}, + {"subjectInfoAccess", "Subject Information Access", NID_sinfo_access, 8, &so[2925]}, + {"id-aca-encAttrs", "id-aca-encAttrs", NID_id_aca_encAttrs, 8, &so[2933]}, + {"role", "role", NID_role, 3, &so[2941]}, + {"policyConstraints", "X509v3 Policy Constraints", NID_policy_constraints, 3, &so[2944]}, + {"targetInformation", "X509v3 AC Targeting", NID_target_information, 3, &so[2947]}, + {"noRevAvail", "X509v3 No Revocation Available", NID_no_rev_avail, 3, &so[2950]}, + {"NULL", "NULL", NID_ccitt}, + {"ansi-X9-62", "ANSI X9.62", NID_ansi_X9_62, 5, &so[2953]}, + {"prime-field", "prime-field", NID_X9_62_prime_field, 7, &so[2958]}, + {"characteristic-two-field", "characteristic-two-field", NID_X9_62_characteristic_two_field, 7, &so[2965]}, + {"id-ecPublicKey", "id-ecPublicKey", NID_X9_62_id_ecPublicKey, 7, &so[2972]}, + {"prime192v1", "prime192v1", NID_X9_62_prime192v1, 8, &so[2979]}, + {"prime192v2", "prime192v2", NID_X9_62_prime192v2, 8, &so[2987]}, + {"prime192v3", "prime192v3", NID_X9_62_prime192v3, 8, &so[2995]}, + {"prime239v1", "prime239v1", NID_X9_62_prime239v1, 8, &so[3003]}, + {"prime239v2", "prime239v2", NID_X9_62_prime239v2, 8, &so[3011]}, + {"prime239v3", "prime239v3", NID_X9_62_prime239v3, 8, &so[3019]}, + {"prime256v1", "prime256v1", NID_X9_62_prime256v1, 8, &so[3027]}, + {"ecdsa-with-SHA1", "ecdsa-with-SHA1", NID_ecdsa_with_SHA1, 7, &so[3035]}, + {"CSPName", "Microsoft CSP Name", NID_ms_csp_name, 9, &so[3042]}, + {"AES-128-ECB", "aes-128-ecb", NID_aes_128_ecb, 9, &so[3051]}, + {"AES-128-CBC", "aes-128-cbc", NID_aes_128_cbc, 9, &so[3060]}, + {"AES-128-OFB", "aes-128-ofb", NID_aes_128_ofb128, 9, &so[3069]}, + {"AES-128-CFB", "aes-128-cfb", NID_aes_128_cfb128, 9, &so[3078]}, + {"AES-192-ECB", "aes-192-ecb", NID_aes_192_ecb, 9, &so[3087]}, + {"AES-192-CBC", "aes-192-cbc", NID_aes_192_cbc, 9, &so[3096]}, + {"AES-192-OFB", "aes-192-ofb", NID_aes_192_ofb128, 9, &so[3105]}, + {"AES-192-CFB", "aes-192-cfb", NID_aes_192_cfb128, 9, &so[3114]}, + {"AES-256-ECB", "aes-256-ecb", NID_aes_256_ecb, 9, &so[3123]}, + {"AES-256-CBC", "aes-256-cbc", NID_aes_256_cbc, 9, &so[3132]}, + {"AES-256-OFB", "aes-256-ofb", NID_aes_256_ofb128, 9, &so[3141]}, + {"AES-256-CFB", "aes-256-cfb", NID_aes_256_cfb128, 9, &so[3150]}, + {"holdInstructionCode", "Hold Instruction Code", NID_hold_instruction_code, 3, &so[3159]}, + {"holdInstructionNone", "Hold Instruction None", NID_hold_instruction_none, 7, &so[3162]}, + {"holdInstructionCallIssuer", "Hold Instruction Call Issuer", NID_hold_instruction_call_issuer, 7, &so[3169]}, + {"holdInstructionReject", "Hold Instruction Reject", NID_hold_instruction_reject, 7, &so[3176]}, + {"data", "data", NID_data, 1, &so[3183]}, + {"pss", "pss", NID_pss, 3, &so[3184]}, + {"ucl", "ucl", NID_ucl, 7, &so[3187]}, + {"pilot", "pilot", NID_pilot, 8, &so[3194]}, + {"pilotAttributeType", "pilotAttributeType", NID_pilotAttributeType, 9, &so[3202]}, + {"pilotAttributeSyntax", "pilotAttributeSyntax", NID_pilotAttributeSyntax, 9, &so[3211]}, + {"pilotObjectClass", "pilotObjectClass", NID_pilotObjectClass, 9, &so[3220]}, + {"pilotGroups", "pilotGroups", NID_pilotGroups, 9, &so[3229]}, + {"iA5StringSyntax", "iA5StringSyntax", NID_iA5StringSyntax, 10, &so[3238]}, + {"caseIgnoreIA5StringSyntax", "caseIgnoreIA5StringSyntax", NID_caseIgnoreIA5StringSyntax, 10, &so[3248]}, + {"pilotObject", "pilotObject", NID_pilotObject, 10, &so[3258]}, + {"pilotPerson", "pilotPerson", NID_pilotPerson, 10, &so[3268]}, + {"account", "account", NID_account, 10, &so[3278]}, + {"document", "document", NID_document, 10, &so[3288]}, + {"room", "room", NID_room, 10, &so[3298]}, + {"documentSeries", "documentSeries", NID_documentSeries, 10, &so[3308]}, + {"rFC822localPart", "rFC822localPart", NID_rFC822localPart, 10, &so[3318]}, + {"dNSDomain", "dNSDomain", NID_dNSDomain, 10, &so[3328]}, + {"domainRelatedObject", "domainRelatedObject", NID_domainRelatedObject, 10, &so[3338]}, + {"friendlyCountry", "friendlyCountry", NID_friendlyCountry, 10, &so[3348]}, + {"simpleSecurityObject", "simpleSecurityObject", NID_simpleSecurityObject, 10, &so[3358]}, + {"pilotOrganization", "pilotOrganization", NID_pilotOrganization, 10, &so[3368]}, + {"pilotDSA", "pilotDSA", NID_pilotDSA, 10, &so[3378]}, + {"qualityLabelledData", "qualityLabelledData", NID_qualityLabelledData, 10, &so[3388]}, + {"UID", "userId", NID_userId, 10, &so[3398]}, + {"textEncodedORAddress", "textEncodedORAddress", NID_textEncodedORAddress, 10, &so[3408]}, + {"mail", "rfc822Mailbox", NID_rfc822Mailbox, 10, &so[3418]}, + {"info", "info", NID_info, 10, &so[3428]}, + {"favouriteDrink", "favouriteDrink", NID_favouriteDrink, 10, &so[3438]}, + {"roomNumber", "roomNumber", NID_roomNumber, 10, &so[3448]}, + {"photo", "photo", NID_photo, 10, &so[3458]}, + {"userClass", "userClass", NID_userClass, 10, &so[3468]}, + {"host", "host", NID_host, 10, &so[3478]}, + {"manager", "manager", NID_manager, 10, &so[3488]}, + {"documentIdentifier", "documentIdentifier", NID_documentIdentifier, 10, &so[3498]}, + {"documentTitle", "documentTitle", NID_documentTitle, 10, &so[3508]}, + {"documentVersion", "documentVersion", NID_documentVersion, 10, &so[3518]}, + {"documentAuthor", "documentAuthor", NID_documentAuthor, 10, &so[3528]}, + {"documentLocation", "documentLocation", NID_documentLocation, 10, &so[3538]}, + {"homeTelephoneNumber", "homeTelephoneNumber", NID_homeTelephoneNumber, 10, &so[3548]}, + {"secretary", "secretary", NID_secretary, 10, &so[3558]}, + {"otherMailbox", "otherMailbox", NID_otherMailbox, 10, &so[3568]}, + {"lastModifiedTime", "lastModifiedTime", NID_lastModifiedTime, 10, &so[3578]}, + {"lastModifiedBy", "lastModifiedBy", NID_lastModifiedBy, 10, &so[3588]}, + {"aRecord", "aRecord", NID_aRecord, 10, &so[3598]}, + {"pilotAttributeType27", "pilotAttributeType27", NID_pilotAttributeType27, 10, &so[3608]}, + {"mXRecord", "mXRecord", NID_mXRecord, 10, &so[3618]}, + {"nSRecord", "nSRecord", NID_nSRecord, 10, &so[3628]}, + {"sOARecord", "sOARecord", NID_sOARecord, 10, &so[3638]}, + {"cNAMERecord", "cNAMERecord", NID_cNAMERecord, 10, &so[3648]}, + {"associatedDomain", "associatedDomain", NID_associatedDomain, 10, &so[3658]}, + {"associatedName", "associatedName", NID_associatedName, 10, &so[3668]}, + {"homePostalAddress", "homePostalAddress", NID_homePostalAddress, 10, &so[3678]}, + {"personalTitle", "personalTitle", NID_personalTitle, 10, &so[3688]}, + {"mobileTelephoneNumber", "mobileTelephoneNumber", NID_mobileTelephoneNumber, 10, &so[3698]}, + {"pagerTelephoneNumber", "pagerTelephoneNumber", NID_pagerTelephoneNumber, 10, &so[3708]}, + {"friendlyCountryName", "friendlyCountryName", NID_friendlyCountryName, 10, &so[3718]}, + {"organizationalStatus", "organizationalStatus", NID_organizationalStatus, 10, &so[3728]}, + {"janetMailbox", "janetMailbox", NID_janetMailbox, 10, &so[3738]}, + {"mailPreferenceOption", "mailPreferenceOption", NID_mailPreferenceOption, 10, &so[3748]}, + {"buildingName", "buildingName", NID_buildingName, 10, &so[3758]}, + {"dSAQuality", "dSAQuality", NID_dSAQuality, 10, &so[3768]}, + {"singleLevelQuality", "singleLevelQuality", NID_singleLevelQuality, 10, &so[3778]}, + {"subtreeMinimumQuality", "subtreeMinimumQuality", NID_subtreeMinimumQuality, 10, &so[3788]}, + {"subtreeMaximumQuality", "subtreeMaximumQuality", NID_subtreeMaximumQuality, 10, &so[3798]}, + {"personalSignature", "personalSignature", NID_personalSignature, 10, &so[3808]}, + {"dITRedirect", "dITRedirect", NID_dITRedirect, 10, &so[3818]}, + {"audio", "audio", NID_audio, 10, &so[3828]}, + {"documentPublisher", "documentPublisher", NID_documentPublisher, 10, &so[3838]}, + {"x500UniqueIdentifier", "x500UniqueIdentifier", NID_x500UniqueIdentifier, 3, &so[3848]}, + {"mime-mhs", "MIME MHS", NID_mime_mhs, 5, &so[3851]}, + {"mime-mhs-headings", "mime-mhs-headings", NID_mime_mhs_headings, 6, &so[3856]}, + {"mime-mhs-bodies", "mime-mhs-bodies", NID_mime_mhs_bodies, 6, &so[3862]}, + {"id-hex-partial-message", "id-hex-partial-message", NID_id_hex_partial_message, 7, &so[3868]}, + {"id-hex-multipart-message", "id-hex-multipart-message", NID_id_hex_multipart_message, 7, &so[3875]}, + {"generationQualifier", "generationQualifier", NID_generationQualifier, 3, &so[3882]}, + {"pseudonym", "pseudonym", NID_pseudonym, 3, &so[3885]}, + { NULL, NULL, NID_undef }, + {"id-set", "Secure Electronic Transactions", NID_id_set, 2, &so[3888]}, + {"set-ctype", "content types", NID_set_ctype, 3, &so[3890]}, + {"set-msgExt", "message extensions", NID_set_msgExt, 3, &so[3893]}, + {"set-attr", "set-attr", NID_set_attr, 3, &so[3896]}, + {"set-policy", "set-policy", NID_set_policy, 3, &so[3899]}, + {"set-certExt", "certificate extensions", NID_set_certExt, 3, &so[3902]}, + {"set-brand", "set-brand", NID_set_brand, 3, &so[3905]}, + {"setct-PANData", "setct-PANData", NID_setct_PANData, 4, &so[3908]}, + {"setct-PANToken", "setct-PANToken", NID_setct_PANToken, 4, &so[3912]}, + {"setct-PANOnly", "setct-PANOnly", NID_setct_PANOnly, 4, &so[3916]}, + {"setct-OIData", "setct-OIData", NID_setct_OIData, 4, &so[3920]}, + {"setct-PI", "setct-PI", NID_setct_PI, 4, &so[3924]}, + {"setct-PIData", "setct-PIData", NID_setct_PIData, 4, &so[3928]}, + {"setct-PIDataUnsigned", "setct-PIDataUnsigned", NID_setct_PIDataUnsigned, 4, &so[3932]}, + {"setct-HODInput", "setct-HODInput", NID_setct_HODInput, 4, &so[3936]}, + {"setct-AuthResBaggage", "setct-AuthResBaggage", NID_setct_AuthResBaggage, 4, &so[3940]}, + {"setct-AuthRevReqBaggage", "setct-AuthRevReqBaggage", NID_setct_AuthRevReqBaggage, 4, &so[3944]}, + {"setct-AuthRevResBaggage", "setct-AuthRevResBaggage", NID_setct_AuthRevResBaggage, 4, &so[3948]}, + {"setct-CapTokenSeq", "setct-CapTokenSeq", NID_setct_CapTokenSeq, 4, &so[3952]}, + {"setct-PInitResData", "setct-PInitResData", NID_setct_PInitResData, 4, &so[3956]}, + {"setct-PI-TBS", "setct-PI-TBS", NID_setct_PI_TBS, 4, &so[3960]}, + {"setct-PResData", "setct-PResData", NID_setct_PResData, 4, &so[3964]}, + {"setct-AuthReqTBS", "setct-AuthReqTBS", NID_setct_AuthReqTBS, 4, &so[3968]}, + {"setct-AuthResTBS", "setct-AuthResTBS", NID_setct_AuthResTBS, 4, &so[3972]}, + {"setct-AuthResTBSX", "setct-AuthResTBSX", NID_setct_AuthResTBSX, 4, &so[3976]}, + {"setct-AuthTokenTBS", "setct-AuthTokenTBS", NID_setct_AuthTokenTBS, 4, &so[3980]}, + {"setct-CapTokenData", "setct-CapTokenData", NID_setct_CapTokenData, 4, &so[3984]}, + {"setct-CapTokenTBS", "setct-CapTokenTBS", NID_setct_CapTokenTBS, 4, &so[3988]}, + {"setct-AcqCardCodeMsg", "setct-AcqCardCodeMsg", NID_setct_AcqCardCodeMsg, 4, &so[3992]}, + {"setct-AuthRevReqTBS", "setct-AuthRevReqTBS", NID_setct_AuthRevReqTBS, 4, &so[3996]}, + {"setct-AuthRevResData", "setct-AuthRevResData", NID_setct_AuthRevResData, 4, &so[4000]}, + {"setct-AuthRevResTBS", "setct-AuthRevResTBS", NID_setct_AuthRevResTBS, 4, &so[4004]}, + {"setct-CapReqTBS", "setct-CapReqTBS", NID_setct_CapReqTBS, 4, &so[4008]}, + {"setct-CapReqTBSX", "setct-CapReqTBSX", NID_setct_CapReqTBSX, 4, &so[4012]}, + {"setct-CapResData", "setct-CapResData", NID_setct_CapResData, 4, &so[4016]}, + {"setct-CapRevReqTBS", "setct-CapRevReqTBS", NID_setct_CapRevReqTBS, 4, &so[4020]}, + {"setct-CapRevReqTBSX", "setct-CapRevReqTBSX", NID_setct_CapRevReqTBSX, 4, &so[4024]}, + {"setct-CapRevResData", "setct-CapRevResData", NID_setct_CapRevResData, 4, &so[4028]}, + {"setct-CredReqTBS", "setct-CredReqTBS", NID_setct_CredReqTBS, 4, &so[4032]}, + {"setct-CredReqTBSX", "setct-CredReqTBSX", NID_setct_CredReqTBSX, 4, &so[4036]}, + {"setct-CredResData", "setct-CredResData", NID_setct_CredResData, 4, &so[4040]}, + {"setct-CredRevReqTBS", "setct-CredRevReqTBS", NID_setct_CredRevReqTBS, 4, &so[4044]}, + {"setct-CredRevReqTBSX", "setct-CredRevReqTBSX", NID_setct_CredRevReqTBSX, 4, &so[4048]}, + {"setct-CredRevResData", "setct-CredRevResData", NID_setct_CredRevResData, 4, &so[4052]}, + {"setct-PCertReqData", "setct-PCertReqData", NID_setct_PCertReqData, 4, &so[4056]}, + {"setct-PCertResTBS", "setct-PCertResTBS", NID_setct_PCertResTBS, 4, &so[4060]}, + {"setct-BatchAdminReqData", "setct-BatchAdminReqData", NID_setct_BatchAdminReqData, 4, &so[4064]}, + {"setct-BatchAdminResData", "setct-BatchAdminResData", NID_setct_BatchAdminResData, 4, &so[4068]}, + {"setct-CardCInitResTBS", "setct-CardCInitResTBS", NID_setct_CardCInitResTBS, 4, &so[4072]}, + {"setct-MeAqCInitResTBS", "setct-MeAqCInitResTBS", NID_setct_MeAqCInitResTBS, 4, &so[4076]}, + {"setct-RegFormResTBS", "setct-RegFormResTBS", NID_setct_RegFormResTBS, 4, &so[4080]}, + {"setct-CertReqData", "setct-CertReqData", NID_setct_CertReqData, 4, &so[4084]}, + {"setct-CertReqTBS", "setct-CertReqTBS", NID_setct_CertReqTBS, 4, &so[4088]}, + {"setct-CertResData", "setct-CertResData", NID_setct_CertResData, 4, &so[4092]}, + {"setct-CertInqReqTBS", "setct-CertInqReqTBS", NID_setct_CertInqReqTBS, 4, &so[4096]}, + {"setct-ErrorTBS", "setct-ErrorTBS", NID_setct_ErrorTBS, 4, &so[4100]}, + {"setct-PIDualSignedTBE", "setct-PIDualSignedTBE", NID_setct_PIDualSignedTBE, 4, &so[4104]}, + {"setct-PIUnsignedTBE", "setct-PIUnsignedTBE", NID_setct_PIUnsignedTBE, 4, &so[4108]}, + {"setct-AuthReqTBE", "setct-AuthReqTBE", NID_setct_AuthReqTBE, 4, &so[4112]}, + {"setct-AuthResTBE", "setct-AuthResTBE", NID_setct_AuthResTBE, 4, &so[4116]}, + {"setct-AuthResTBEX", "setct-AuthResTBEX", NID_setct_AuthResTBEX, 4, &so[4120]}, + {"setct-AuthTokenTBE", "setct-AuthTokenTBE", NID_setct_AuthTokenTBE, 4, &so[4124]}, + {"setct-CapTokenTBE", "setct-CapTokenTBE", NID_setct_CapTokenTBE, 4, &so[4128]}, + {"setct-CapTokenTBEX", "setct-CapTokenTBEX", NID_setct_CapTokenTBEX, 4, &so[4132]}, + {"setct-AcqCardCodeMsgTBE", "setct-AcqCardCodeMsgTBE", NID_setct_AcqCardCodeMsgTBE, 4, &so[4136]}, + {"setct-AuthRevReqTBE", "setct-AuthRevReqTBE", NID_setct_AuthRevReqTBE, 4, &so[4140]}, + {"setct-AuthRevResTBE", "setct-AuthRevResTBE", NID_setct_AuthRevResTBE, 4, &so[4144]}, + {"setct-AuthRevResTBEB", "setct-AuthRevResTBEB", NID_setct_AuthRevResTBEB, 4, &so[4148]}, + {"setct-CapReqTBE", "setct-CapReqTBE", NID_setct_CapReqTBE, 4, &so[4152]}, + {"setct-CapReqTBEX", "setct-CapReqTBEX", NID_setct_CapReqTBEX, 4, &so[4156]}, + {"setct-CapResTBE", "setct-CapResTBE", NID_setct_CapResTBE, 4, &so[4160]}, + {"setct-CapRevReqTBE", "setct-CapRevReqTBE", NID_setct_CapRevReqTBE, 4, &so[4164]}, + {"setct-CapRevReqTBEX", "setct-CapRevReqTBEX", NID_setct_CapRevReqTBEX, 4, &so[4168]}, + {"setct-CapRevResTBE", "setct-CapRevResTBE", NID_setct_CapRevResTBE, 4, &so[4172]}, + {"setct-CredReqTBE", "setct-CredReqTBE", NID_setct_CredReqTBE, 4, &so[4176]}, + {"setct-CredReqTBEX", "setct-CredReqTBEX", NID_setct_CredReqTBEX, 4, &so[4180]}, + {"setct-CredResTBE", "setct-CredResTBE", NID_setct_CredResTBE, 4, &so[4184]}, + {"setct-CredRevReqTBE", "setct-CredRevReqTBE", NID_setct_CredRevReqTBE, 4, &so[4188]}, + {"setct-CredRevReqTBEX", "setct-CredRevReqTBEX", NID_setct_CredRevReqTBEX, 4, &so[4192]}, + {"setct-CredRevResTBE", "setct-CredRevResTBE", NID_setct_CredRevResTBE, 4, &so[4196]}, + {"setct-BatchAdminReqTBE", "setct-BatchAdminReqTBE", NID_setct_BatchAdminReqTBE, 4, &so[4200]}, + {"setct-BatchAdminResTBE", "setct-BatchAdminResTBE", NID_setct_BatchAdminResTBE, 4, &so[4204]}, + {"setct-RegFormReqTBE", "setct-RegFormReqTBE", NID_setct_RegFormReqTBE, 4, &so[4208]}, + {"setct-CertReqTBE", "setct-CertReqTBE", NID_setct_CertReqTBE, 4, &so[4212]}, + {"setct-CertReqTBEX", "setct-CertReqTBEX", NID_setct_CertReqTBEX, 4, &so[4216]}, + {"setct-CertResTBE", "setct-CertResTBE", NID_setct_CertResTBE, 4, &so[4220]}, + {"setct-CRLNotificationTBS", "setct-CRLNotificationTBS", NID_setct_CRLNotificationTBS, 4, &so[4224]}, + {"setct-CRLNotificationResTBS", "setct-CRLNotificationResTBS", NID_setct_CRLNotificationResTBS, 4, &so[4228]}, + {"setct-BCIDistributionTBS", "setct-BCIDistributionTBS", NID_setct_BCIDistributionTBS, 4, &so[4232]}, + {"setext-genCrypt", "generic cryptogram", NID_setext_genCrypt, 4, &so[4236]}, + {"setext-miAuth", "merchant initiated auth", NID_setext_miAuth, 4, &so[4240]}, + {"setext-pinSecure", "setext-pinSecure", NID_setext_pinSecure, 4, &so[4244]}, + {"setext-pinAny", "setext-pinAny", NID_setext_pinAny, 4, &so[4248]}, + {"setext-track2", "setext-track2", NID_setext_track2, 4, &so[4252]}, + {"setext-cv", "additional verification", NID_setext_cv, 4, &so[4256]}, + {"set-policy-root", "set-policy-root", NID_set_policy_root, 4, &so[4260]}, + {"setCext-hashedRoot", "setCext-hashedRoot", NID_setCext_hashedRoot, 4, &so[4264]}, + {"setCext-certType", "setCext-certType", NID_setCext_certType, 4, &so[4268]}, + {"setCext-merchData", "setCext-merchData", NID_setCext_merchData, 4, &so[4272]}, + {"setCext-cCertRequired", "setCext-cCertRequired", NID_setCext_cCertRequired, 4, &so[4276]}, + {"setCext-tunneling", "setCext-tunneling", NID_setCext_tunneling, 4, &so[4280]}, + {"setCext-setExt", "setCext-setExt", NID_setCext_setExt, 4, &so[4284]}, + {"setCext-setQualf", "setCext-setQualf", NID_setCext_setQualf, 4, &so[4288]}, + {"setCext-PGWYcapabilities", "setCext-PGWYcapabilities", NID_setCext_PGWYcapabilities, 4, &so[4292]}, + {"setCext-TokenIdentifier", "setCext-TokenIdentifier", NID_setCext_TokenIdentifier, 4, &so[4296]}, + {"setCext-Track2Data", "setCext-Track2Data", NID_setCext_Track2Data, 4, &so[4300]}, + {"setCext-TokenType", "setCext-TokenType", NID_setCext_TokenType, 4, &so[4304]}, + {"setCext-IssuerCapabilities", "setCext-IssuerCapabilities", NID_setCext_IssuerCapabilities, 4, &so[4308]}, + {"setAttr-Cert", "setAttr-Cert", NID_setAttr_Cert, 4, &so[4312]}, + {"setAttr-PGWYcap", "payment gateway capabilities", NID_setAttr_PGWYcap, 4, &so[4316]}, + {"setAttr-TokenType", "setAttr-TokenType", NID_setAttr_TokenType, 4, &so[4320]}, + {"setAttr-IssCap", "issuer capabilities", NID_setAttr_IssCap, 4, &so[4324]}, + {"set-rootKeyThumb", "set-rootKeyThumb", NID_set_rootKeyThumb, 5, &so[4328]}, + {"set-addPolicy", "set-addPolicy", NID_set_addPolicy, 5, &so[4333]}, + {"setAttr-Token-EMV", "setAttr-Token-EMV", NID_setAttr_Token_EMV, 5, &so[4338]}, + {"setAttr-Token-B0Prime", "setAttr-Token-B0Prime", NID_setAttr_Token_B0Prime, 5, &so[4343]}, + {"setAttr-IssCap-CVM", "setAttr-IssCap-CVM", NID_setAttr_IssCap_CVM, 5, &so[4348]}, + {"setAttr-IssCap-T2", "setAttr-IssCap-T2", NID_setAttr_IssCap_T2, 5, &so[4353]}, + {"setAttr-IssCap-Sig", "setAttr-IssCap-Sig", NID_setAttr_IssCap_Sig, 5, &so[4358]}, + {"setAttr-GenCryptgrm", "generate cryptogram", NID_setAttr_GenCryptgrm, 6, &so[4363]}, + {"setAttr-T2Enc", "encrypted track 2", NID_setAttr_T2Enc, 6, &so[4369]}, + {"setAttr-T2cleartxt", "cleartext track 2", NID_setAttr_T2cleartxt, 6, &so[4375]}, + {"setAttr-TokICCsig", "ICC or token signature", NID_setAttr_TokICCsig, 6, &so[4381]}, + {"setAttr-SecDevSig", "secure device signature", NID_setAttr_SecDevSig, 6, &so[4387]}, + {"set-brand-IATA-ATA", "set-brand-IATA-ATA", NID_set_brand_IATA_ATA, 4, &so[4393]}, + {"set-brand-Diners", "set-brand-Diners", NID_set_brand_Diners, 4, &so[4397]}, + {"set-brand-AmericanExpress", "set-brand-AmericanExpress", NID_set_brand_AmericanExpress, 4, &so[4401]}, + {"set-brand-JCB", "set-brand-JCB", NID_set_brand_JCB, 4, &so[4405]}, + {"set-brand-Visa", "set-brand-Visa", NID_set_brand_Visa, 4, &so[4409]}, + {"set-brand-MasterCard", "set-brand-MasterCard", NID_set_brand_MasterCard, 4, &so[4413]}, + {"set-brand-Novus", "set-brand-Novus", NID_set_brand_Novus, 5, &so[4417]}, + {"DES-CDMF", "des-cdmf", NID_des_cdmf, 8, &so[4422]}, + {"rsaOAEPEncryptionSET", "rsaOAEPEncryptionSET", NID_rsaOAEPEncryptionSET, 9, &so[4430]}, + {"ITU-T", "itu-t", NID_itu_t}, + {"JOINT-ISO-ITU-T", "joint-iso-itu-t", NID_joint_iso_itu_t}, + {"international-organizations", "International Organizations", NID_international_organizations, 1, &so[4439]}, + {"msSmartcardLogin", "Microsoft Smartcardlogin", NID_ms_smartcard_login, 10, &so[4440]}, + {"msUPN", "Microsoft Universal Principal Name", NID_ms_upn, 10, &so[4450]}, + {"AES-128-CFB1", "aes-128-cfb1", NID_aes_128_cfb1}, + {"AES-192-CFB1", "aes-192-cfb1", NID_aes_192_cfb1}, + {"AES-256-CFB1", "aes-256-cfb1", NID_aes_256_cfb1}, + {"AES-128-CFB8", "aes-128-cfb8", NID_aes_128_cfb8}, + {"AES-192-CFB8", "aes-192-cfb8", NID_aes_192_cfb8}, + {"AES-256-CFB8", "aes-256-cfb8", NID_aes_256_cfb8}, + {"DES-CFB1", "des-cfb1", NID_des_cfb1}, + {"DES-CFB8", "des-cfb8", NID_des_cfb8}, + {"DES-EDE3-CFB1", "des-ede3-cfb1", NID_des_ede3_cfb1}, + {"DES-EDE3-CFB8", "des-ede3-cfb8", NID_des_ede3_cfb8}, + {"street", "streetAddress", NID_streetAddress, 3, &so[4460]}, + {"postalCode", "postalCode", NID_postalCode, 3, &so[4463]}, + {"id-ppl", "id-ppl", NID_id_ppl, 7, &so[4466]}, + {"proxyCertInfo", "Proxy Certificate Information", NID_proxyCertInfo, 8, &so[4473]}, + {"id-ppl-anyLanguage", "Any language", NID_id_ppl_anyLanguage, 8, &so[4481]}, + {"id-ppl-inheritAll", "Inherit all", NID_id_ppl_inheritAll, 8, &so[4489]}, + {"nameConstraints", "X509v3 Name Constraints", NID_name_constraints, 3, &so[4497]}, + {"id-ppl-independent", "Independent", NID_Independent, 8, &so[4500]}, + {"RSA-SHA256", "sha256WithRSAEncryption", NID_sha256WithRSAEncryption, 9, &so[4508]}, + {"RSA-SHA384", "sha384WithRSAEncryption", NID_sha384WithRSAEncryption, 9, &so[4517]}, + {"RSA-SHA512", "sha512WithRSAEncryption", NID_sha512WithRSAEncryption, 9, &so[4526]}, + {"RSA-SHA224", "sha224WithRSAEncryption", NID_sha224WithRSAEncryption, 9, &so[4535]}, + {"SHA256", "sha256", NID_sha256, 9, &so[4544]}, + {"SHA384", "sha384", NID_sha384, 9, &so[4553]}, + {"SHA512", "sha512", NID_sha512, 9, &so[4562]}, + {"SHA224", "sha224", NID_sha224, 9, &so[4571]}, + {"identified-organization", "identified-organization", NID_identified_organization, 1, &so[4580]}, + {"certicom-arc", "certicom-arc", NID_certicom_arc, 3, &so[4581]}, + {"wap", "wap", NID_wap, 2, &so[4584]}, + {"wap-wsg", "wap-wsg", NID_wap_wsg, 3, &so[4586]}, + {"id-characteristic-two-basis", "id-characteristic-two-basis", NID_X9_62_id_characteristic_two_basis, 8, &so[4589]}, + {"onBasis", "onBasis", NID_X9_62_onBasis, 9, &so[4597]}, + {"tpBasis", "tpBasis", NID_X9_62_tpBasis, 9, &so[4606]}, + {"ppBasis", "ppBasis", NID_X9_62_ppBasis, 9, &so[4615]}, + {"c2pnb163v1", "c2pnb163v1", NID_X9_62_c2pnb163v1, 8, &so[4624]}, + {"c2pnb163v2", "c2pnb163v2", NID_X9_62_c2pnb163v2, 8, &so[4632]}, + {"c2pnb163v3", "c2pnb163v3", NID_X9_62_c2pnb163v3, 8, &so[4640]}, + {"c2pnb176v1", "c2pnb176v1", NID_X9_62_c2pnb176v1, 8, &so[4648]}, + {"c2tnb191v1", "c2tnb191v1", NID_X9_62_c2tnb191v1, 8, &so[4656]}, + {"c2tnb191v2", "c2tnb191v2", NID_X9_62_c2tnb191v2, 8, &so[4664]}, + {"c2tnb191v3", "c2tnb191v3", NID_X9_62_c2tnb191v3, 8, &so[4672]}, + {"c2onb191v4", "c2onb191v4", NID_X9_62_c2onb191v4, 8, &so[4680]}, + {"c2onb191v5", "c2onb191v5", NID_X9_62_c2onb191v5, 8, &so[4688]}, + {"c2pnb208w1", "c2pnb208w1", NID_X9_62_c2pnb208w1, 8, &so[4696]}, + {"c2tnb239v1", "c2tnb239v1", NID_X9_62_c2tnb239v1, 8, &so[4704]}, + {"c2tnb239v2", "c2tnb239v2", NID_X9_62_c2tnb239v2, 8, &so[4712]}, + {"c2tnb239v3", "c2tnb239v3", NID_X9_62_c2tnb239v3, 8, &so[4720]}, + {"c2onb239v4", "c2onb239v4", NID_X9_62_c2onb239v4, 8, &so[4728]}, + {"c2onb239v5", "c2onb239v5", NID_X9_62_c2onb239v5, 8, &so[4736]}, + {"c2pnb272w1", "c2pnb272w1", NID_X9_62_c2pnb272w1, 8, &so[4744]}, + {"c2pnb304w1", "c2pnb304w1", NID_X9_62_c2pnb304w1, 8, &so[4752]}, + {"c2tnb359v1", "c2tnb359v1", NID_X9_62_c2tnb359v1, 8, &so[4760]}, + {"c2pnb368w1", "c2pnb368w1", NID_X9_62_c2pnb368w1, 8, &so[4768]}, + {"c2tnb431r1", "c2tnb431r1", NID_X9_62_c2tnb431r1, 8, &so[4776]}, + {"secp112r1", "secp112r1", NID_secp112r1, 5, &so[4784]}, + {"secp112r2", "secp112r2", NID_secp112r2, 5, &so[4789]}, + {"secp128r1", "secp128r1", NID_secp128r1, 5, &so[4794]}, + {"secp128r2", "secp128r2", NID_secp128r2, 5, &so[4799]}, + {"secp160k1", "secp160k1", NID_secp160k1, 5, &so[4804]}, + {"secp160r1", "secp160r1", NID_secp160r1, 5, &so[4809]}, + {"secp160r2", "secp160r2", NID_secp160r2, 5, &so[4814]}, + {"secp192k1", "secp192k1", NID_secp192k1, 5, &so[4819]}, + {"secp224k1", "secp224k1", NID_secp224k1, 5, &so[4824]}, + {"secp224r1", "secp224r1", NID_secp224r1, 5, &so[4829]}, + {"secp256k1", "secp256k1", NID_secp256k1, 5, &so[4834]}, + {"secp384r1", "secp384r1", NID_secp384r1, 5, &so[4839]}, + {"secp521r1", "secp521r1", NID_secp521r1, 5, &so[4844]}, + {"sect113r1", "sect113r1", NID_sect113r1, 5, &so[4849]}, + {"sect113r2", "sect113r2", NID_sect113r2, 5, &so[4854]}, + {"sect131r1", "sect131r1", NID_sect131r1, 5, &so[4859]}, + {"sect131r2", "sect131r2", NID_sect131r2, 5, &so[4864]}, + {"sect163k1", "sect163k1", NID_sect163k1, 5, &so[4869]}, + {"sect163r1", "sect163r1", NID_sect163r1, 5, &so[4874]}, + {"sect163r2", "sect163r2", NID_sect163r2, 5, &so[4879]}, + {"sect193r1", "sect193r1", NID_sect193r1, 5, &so[4884]}, + {"sect193r2", "sect193r2", NID_sect193r2, 5, &so[4889]}, + {"sect233k1", "sect233k1", NID_sect233k1, 5, &so[4894]}, + {"sect233r1", "sect233r1", NID_sect233r1, 5, &so[4899]}, + {"sect239k1", "sect239k1", NID_sect239k1, 5, &so[4904]}, + {"sect283k1", "sect283k1", NID_sect283k1, 5, &so[4909]}, + {"sect283r1", "sect283r1", NID_sect283r1, 5, &so[4914]}, + {"sect409k1", "sect409k1", NID_sect409k1, 5, &so[4919]}, + {"sect409r1", "sect409r1", NID_sect409r1, 5, &so[4924]}, + {"sect571k1", "sect571k1", NID_sect571k1, 5, &so[4929]}, + {"sect571r1", "sect571r1", NID_sect571r1, 5, &so[4934]}, + {"wap-wsg-idm-ecid-wtls1", "wap-wsg-idm-ecid-wtls1", NID_wap_wsg_idm_ecid_wtls1, 5, &so[4939]}, + {"wap-wsg-idm-ecid-wtls3", "wap-wsg-idm-ecid-wtls3", NID_wap_wsg_idm_ecid_wtls3, 5, &so[4944]}, + {"wap-wsg-idm-ecid-wtls4", "wap-wsg-idm-ecid-wtls4", NID_wap_wsg_idm_ecid_wtls4, 5, &so[4949]}, + {"wap-wsg-idm-ecid-wtls5", "wap-wsg-idm-ecid-wtls5", NID_wap_wsg_idm_ecid_wtls5, 5, &so[4954]}, + {"wap-wsg-idm-ecid-wtls6", "wap-wsg-idm-ecid-wtls6", NID_wap_wsg_idm_ecid_wtls6, 5, &so[4959]}, + {"wap-wsg-idm-ecid-wtls7", "wap-wsg-idm-ecid-wtls7", NID_wap_wsg_idm_ecid_wtls7, 5, &so[4964]}, + {"wap-wsg-idm-ecid-wtls8", "wap-wsg-idm-ecid-wtls8", NID_wap_wsg_idm_ecid_wtls8, 5, &so[4969]}, + {"wap-wsg-idm-ecid-wtls9", "wap-wsg-idm-ecid-wtls9", NID_wap_wsg_idm_ecid_wtls9, 5, &so[4974]}, + {"wap-wsg-idm-ecid-wtls10", "wap-wsg-idm-ecid-wtls10", NID_wap_wsg_idm_ecid_wtls10, 5, &so[4979]}, + {"wap-wsg-idm-ecid-wtls11", "wap-wsg-idm-ecid-wtls11", NID_wap_wsg_idm_ecid_wtls11, 5, &so[4984]}, + {"wap-wsg-idm-ecid-wtls12", "wap-wsg-idm-ecid-wtls12", NID_wap_wsg_idm_ecid_wtls12, 5, &so[4989]}, + {"anyPolicy", "X509v3 Any Policy", NID_any_policy, 4, &so[4994]}, + {"policyMappings", "X509v3 Policy Mappings", NID_policy_mappings, 3, &so[4998]}, + {"inhibitAnyPolicy", "X509v3 Inhibit Any Policy", NID_inhibit_any_policy, 3, &so[5001]}, + {"Oakley-EC2N-3", "ipsec3", NID_ipsec3}, + {"Oakley-EC2N-4", "ipsec4", NID_ipsec4}, + {"CAMELLIA-128-CBC", "camellia-128-cbc", NID_camellia_128_cbc, 11, &so[5004]}, + {"CAMELLIA-192-CBC", "camellia-192-cbc", NID_camellia_192_cbc, 11, &so[5015]}, + {"CAMELLIA-256-CBC", "camellia-256-cbc", NID_camellia_256_cbc, 11, &so[5026]}, + {"CAMELLIA-128-ECB", "camellia-128-ecb", NID_camellia_128_ecb, 8, &so[5037]}, + {"CAMELLIA-192-ECB", "camellia-192-ecb", NID_camellia_192_ecb, 8, &so[5045]}, + {"CAMELLIA-256-ECB", "camellia-256-ecb", NID_camellia_256_ecb, 8, &so[5053]}, + {"CAMELLIA-128-CFB", "camellia-128-cfb", NID_camellia_128_cfb128, 8, &so[5061]}, + {"CAMELLIA-192-CFB", "camellia-192-cfb", NID_camellia_192_cfb128, 8, &so[5069]}, + {"CAMELLIA-256-CFB", "camellia-256-cfb", NID_camellia_256_cfb128, 8, &so[5077]}, + {"CAMELLIA-128-CFB1", "camellia-128-cfb1", NID_camellia_128_cfb1}, + {"CAMELLIA-192-CFB1", "camellia-192-cfb1", NID_camellia_192_cfb1}, + {"CAMELLIA-256-CFB1", "camellia-256-cfb1", NID_camellia_256_cfb1}, + {"CAMELLIA-128-CFB8", "camellia-128-cfb8", NID_camellia_128_cfb8}, + {"CAMELLIA-192-CFB8", "camellia-192-cfb8", NID_camellia_192_cfb8}, + {"CAMELLIA-256-CFB8", "camellia-256-cfb8", NID_camellia_256_cfb8}, + {"CAMELLIA-128-OFB", "camellia-128-ofb", NID_camellia_128_ofb128, 8, &so[5085]}, + {"CAMELLIA-192-OFB", "camellia-192-ofb", NID_camellia_192_ofb128, 8, &so[5093]}, + {"CAMELLIA-256-OFB", "camellia-256-ofb", NID_camellia_256_ofb128, 8, &so[5101]}, + {"subjectDirectoryAttributes", "X509v3 Subject Directory Attributes", NID_subject_directory_attributes, 3, &so[5109]}, + {"issuingDistributionPoint", "X509v3 Issuing Distribution Point", NID_issuing_distribution_point, 3, &so[5112]}, + {"certificateIssuer", "X509v3 Certificate Issuer", NID_certificate_issuer, 3, &so[5115]}, + { NULL, NULL, NID_undef }, + {"KISA", "kisa", NID_kisa, 6, &so[5118]}, + { NULL, NULL, NID_undef }, + { NULL, NULL, NID_undef }, + {"SEED-ECB", "seed-ecb", NID_seed_ecb, 8, &so[5124]}, + {"SEED-CBC", "seed-cbc", NID_seed_cbc, 8, &so[5132]}, + {"SEED-OFB", "seed-ofb", NID_seed_ofb128, 8, &so[5140]}, + {"SEED-CFB", "seed-cfb", NID_seed_cfb128, 8, &so[5148]}, + {"HMAC-MD5", "hmac-md5", NID_hmac_md5, 8, &so[5156]}, + {"HMAC-SHA1", "hmac-sha1", NID_hmac_sha1, 8, &so[5164]}, + {"id-PasswordBasedMAC", "password based MAC", NID_id_PasswordBasedMAC, 9, &so[5172]}, + {"id-DHBasedMac", "Diffie-Hellman based MAC", NID_id_DHBasedMac, 9, &so[5181]}, + {"id-it-suppLangTags", "id-it-suppLangTags", NID_id_it_suppLangTags, 8, &so[5190]}, + {"caRepository", "CA Repository", NID_caRepository, 8, &so[5198]}, + {"id-smime-ct-compressedData", "id-smime-ct-compressedData", NID_id_smime_ct_compressedData, 11, &so[5206]}, + {"id-ct-asciiTextWithCRLF", "id-ct-asciiTextWithCRLF", NID_id_ct_asciiTextWithCRLF, 11, &so[5217]}, + {"id-aes128-wrap", "id-aes128-wrap", NID_id_aes128_wrap, 9, &so[5228]}, + {"id-aes192-wrap", "id-aes192-wrap", NID_id_aes192_wrap, 9, &so[5237]}, + {"id-aes256-wrap", "id-aes256-wrap", NID_id_aes256_wrap, 9, &so[5246]}, + {"ecdsa-with-Recommended", "ecdsa-with-Recommended", NID_ecdsa_with_Recommended, 7, &so[5255]}, + {"ecdsa-with-Specified", "ecdsa-with-Specified", NID_ecdsa_with_Specified, 7, &so[5262]}, + {"ecdsa-with-SHA224", "ecdsa-with-SHA224", NID_ecdsa_with_SHA224, 8, &so[5269]}, + {"ecdsa-with-SHA256", "ecdsa-with-SHA256", NID_ecdsa_with_SHA256, 8, &so[5277]}, + {"ecdsa-with-SHA384", "ecdsa-with-SHA384", NID_ecdsa_with_SHA384, 8, &so[5285]}, + {"ecdsa-with-SHA512", "ecdsa-with-SHA512", NID_ecdsa_with_SHA512, 8, &so[5293]}, + {"hmacWithMD5", "hmacWithMD5", NID_hmacWithMD5, 8, &so[5301]}, + {"hmacWithSHA224", "hmacWithSHA224", NID_hmacWithSHA224, 8, &so[5309]}, + {"hmacWithSHA256", "hmacWithSHA256", NID_hmacWithSHA256, 8, &so[5317]}, + {"hmacWithSHA384", "hmacWithSHA384", NID_hmacWithSHA384, 8, &so[5325]}, + {"hmacWithSHA512", "hmacWithSHA512", NID_hmacWithSHA512, 8, &so[5333]}, + {"dsa_with_SHA224", "dsa_with_SHA224", NID_dsa_with_SHA224, 9, &so[5341]}, + {"dsa_with_SHA256", "dsa_with_SHA256", NID_dsa_with_SHA256, 9, &so[5350]}, + {"whirlpool", "whirlpool", NID_whirlpool, 6, &so[5359]}, + {"cryptopro", "cryptopro", NID_cryptopro, 5, &so[5365]}, + {"cryptocom", "cryptocom", NID_cryptocom, 5, &so[5370]}, + {"id-GostR3411-94-with-GostR3410-2001", "GOST R 34.11-94 with GOST R 34.10-2001", NID_id_GostR3411_94_with_GostR3410_2001, 6, &so[5375]}, + {"id-GostR3411-94-with-GostR3410-94", "GOST R 34.11-94 with GOST R 34.10-94", NID_id_GostR3411_94_with_GostR3410_94, 6, &so[5381]}, + {"md_gost94", "GOST R 34.11-94", NID_id_GostR3411_94, 6, &so[5387]}, + {"id-HMACGostR3411-94", "HMAC GOST 34.11-94", NID_id_HMACGostR3411_94, 6, &so[5393]}, + {"gost2001", "GOST R 34.10-2001", NID_id_GostR3410_2001, 6, &so[5399]}, + {"gost94", "GOST R 34.10-94", NID_id_GostR3410_94, 6, &so[5405]}, + {"gost89", "GOST 28147-89", NID_id_Gost28147_89, 6, &so[5411]}, + {"gost89-cnt", "gost89-cnt", NID_gost89_cnt}, + {"gost-mac", "GOST 28147-89 MAC", NID_id_Gost28147_89_MAC, 6, &so[5417]}, + {"prf-gostr3411-94", "GOST R 34.11-94 PRF", NID_id_GostR3411_94_prf, 6, &so[5423]}, + {"id-GostR3410-2001DH", "GOST R 34.10-2001 DH", NID_id_GostR3410_2001DH, 6, &so[5429]}, + {"id-GostR3410-94DH", "GOST R 34.10-94 DH", NID_id_GostR3410_94DH, 6, &so[5435]}, + {"id-Gost28147-89-CryptoPro-KeyMeshing", "id-Gost28147-89-CryptoPro-KeyMeshing", NID_id_Gost28147_89_CryptoPro_KeyMeshing, 7, &so[5441]}, + {"id-Gost28147-89-None-KeyMeshing", "id-Gost28147-89-None-KeyMeshing", NID_id_Gost28147_89_None_KeyMeshing, 7, &so[5448]}, + {"id-GostR3411-94-TestParamSet", "id-GostR3411-94-TestParamSet", NID_id_GostR3411_94_TestParamSet, 7, &so[5455]}, + {"id-GostR3411-94-CryptoProParamSet", "id-GostR3411-94-CryptoProParamSet", NID_id_GostR3411_94_CryptoProParamSet, 7, &so[5462]}, + {"id-Gost28147-89-TestParamSet", "id-Gost28147-89-TestParamSet", NID_id_Gost28147_89_TestParamSet, 7, &so[5469]}, + {"id-Gost28147-89-CryptoPro-A-ParamSet", "id-Gost28147-89-CryptoPro-A-ParamSet", NID_id_Gost28147_89_CryptoPro_A_ParamSet, 7, &so[5476]}, + {"id-Gost28147-89-CryptoPro-B-ParamSet", "id-Gost28147-89-CryptoPro-B-ParamSet", NID_id_Gost28147_89_CryptoPro_B_ParamSet, 7, &so[5483]}, + {"id-Gost28147-89-CryptoPro-C-ParamSet", "id-Gost28147-89-CryptoPro-C-ParamSet", NID_id_Gost28147_89_CryptoPro_C_ParamSet, 7, &so[5490]}, + {"id-Gost28147-89-CryptoPro-D-ParamSet", "id-Gost28147-89-CryptoPro-D-ParamSet", NID_id_Gost28147_89_CryptoPro_D_ParamSet, 7, &so[5497]}, + {"id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet", "id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet", NID_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet, 7, &so[5504]}, + {"id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet", "id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet", NID_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet, 7, &so[5511]}, + {"id-Gost28147-89-CryptoPro-RIC-1-ParamSet", "id-Gost28147-89-CryptoPro-RIC-1-ParamSet", NID_id_Gost28147_89_CryptoPro_RIC_1_ParamSet, 7, &so[5518]}, + {"id-GostR3410-94-TestParamSet", "id-GostR3410-94-TestParamSet", NID_id_GostR3410_94_TestParamSet, 7, &so[5525]}, + {"id-GostR3410-94-CryptoPro-A-ParamSet", "id-GostR3410-94-CryptoPro-A-ParamSet", NID_id_GostR3410_94_CryptoPro_A_ParamSet, 7, &so[5532]}, + {"id-GostR3410-94-CryptoPro-B-ParamSet", "id-GostR3410-94-CryptoPro-B-ParamSet", NID_id_GostR3410_94_CryptoPro_B_ParamSet, 7, &so[5539]}, + {"id-GostR3410-94-CryptoPro-C-ParamSet", "id-GostR3410-94-CryptoPro-C-ParamSet", NID_id_GostR3410_94_CryptoPro_C_ParamSet, 7, &so[5546]}, + {"id-GostR3410-94-CryptoPro-D-ParamSet", "id-GostR3410-94-CryptoPro-D-ParamSet", NID_id_GostR3410_94_CryptoPro_D_ParamSet, 7, &so[5553]}, + {"id-GostR3410-94-CryptoPro-XchA-ParamSet", "id-GostR3410-94-CryptoPro-XchA-ParamSet", NID_id_GostR3410_94_CryptoPro_XchA_ParamSet, 7, &so[5560]}, + {"id-GostR3410-94-CryptoPro-XchB-ParamSet", "id-GostR3410-94-CryptoPro-XchB-ParamSet", NID_id_GostR3410_94_CryptoPro_XchB_ParamSet, 7, &so[5567]}, + {"id-GostR3410-94-CryptoPro-XchC-ParamSet", "id-GostR3410-94-CryptoPro-XchC-ParamSet", NID_id_GostR3410_94_CryptoPro_XchC_ParamSet, 7, &so[5574]}, + {"id-GostR3410-2001-TestParamSet", "id-GostR3410-2001-TestParamSet", NID_id_GostR3410_2001_TestParamSet, 7, &so[5581]}, + {"id-GostR3410-2001-CryptoPro-A-ParamSet", "id-GostR3410-2001-CryptoPro-A-ParamSet", NID_id_GostR3410_2001_CryptoPro_A_ParamSet, 7, &so[5588]}, + {"id-GostR3410-2001-CryptoPro-B-ParamSet", "id-GostR3410-2001-CryptoPro-B-ParamSet", NID_id_GostR3410_2001_CryptoPro_B_ParamSet, 7, &so[5595]}, + {"id-GostR3410-2001-CryptoPro-C-ParamSet", "id-GostR3410-2001-CryptoPro-C-ParamSet", NID_id_GostR3410_2001_CryptoPro_C_ParamSet, 7, &so[5602]}, + {"id-GostR3410-2001-CryptoPro-XchA-ParamSet", "id-GostR3410-2001-CryptoPro-XchA-ParamSet", NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet, 7, &so[5609]}, + {"id-GostR3410-2001-CryptoPro-XchB-ParamSet", "id-GostR3410-2001-CryptoPro-XchB-ParamSet", NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet, 7, &so[5616]}, + {"id-GostR3410-94-a", "id-GostR3410-94-a", NID_id_GostR3410_94_a, 7, &so[5623]}, + {"id-GostR3410-94-aBis", "id-GostR3410-94-aBis", NID_id_GostR3410_94_aBis, 7, &so[5630]}, + {"id-GostR3410-94-b", "id-GostR3410-94-b", NID_id_GostR3410_94_b, 7, &so[5637]}, + {"id-GostR3410-94-bBis", "id-GostR3410-94-bBis", NID_id_GostR3410_94_bBis, 7, &so[5644]}, + {"id-Gost28147-89-cc", "GOST 28147-89 Cryptocom ParamSet", NID_id_Gost28147_89_cc, 8, &so[5651]}, + {"gost94cc", "GOST 34.10-94 Cryptocom", NID_id_GostR3410_94_cc, 8, &so[5659]}, + {"gost2001cc", "GOST 34.10-2001 Cryptocom", NID_id_GostR3410_2001_cc, 8, &so[5667]}, + {"id-GostR3411-94-with-GostR3410-94-cc", "GOST R 34.11-94 with GOST R 34.10-94 Cryptocom", NID_id_GostR3411_94_with_GostR3410_94_cc, 8, &so[5675]}, + {"id-GostR3411-94-with-GostR3410-2001-cc", "GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom", NID_id_GostR3411_94_with_GostR3410_2001_cc, 8, &so[5683]}, + {"id-GostR3410-2001-ParamSet-cc", "GOST R 3410-2001 Parameter Set Cryptocom", NID_id_GostR3410_2001_ParamSet_cc, 8, &so[5691]}, + {"HMAC", "hmac", NID_hmac}, + {"LocalKeySet", "Microsoft Local Key set", NID_LocalKeySet, 9, &so[5699]}, + {"freshestCRL", "X509v3 Freshest CRL", NID_freshest_crl, 3, &so[5708]}, + {"id-on-permanentIdentifier", "Permanent Identifier", NID_id_on_permanentIdentifier, 8, &so[5711]}, + {"searchGuide", "searchGuide", NID_searchGuide, 3, &so[5719]}, + {"businessCategory", "businessCategory", NID_businessCategory, 3, &so[5722]}, + {"postalAddress", "postalAddress", NID_postalAddress, 3, &so[5725]}, + {"postOfficeBox", "postOfficeBox", NID_postOfficeBox, 3, &so[5728]}, + {"physicalDeliveryOfficeName", "physicalDeliveryOfficeName", NID_physicalDeliveryOfficeName, 3, &so[5731]}, + {"telephoneNumber", "telephoneNumber", NID_telephoneNumber, 3, &so[5734]}, + {"telexNumber", "telexNumber", NID_telexNumber, 3, &so[5737]}, + {"teletexTerminalIdentifier", "teletexTerminalIdentifier", NID_teletexTerminalIdentifier, 3, &so[5740]}, + {"facsimileTelephoneNumber", "facsimileTelephoneNumber", NID_facsimileTelephoneNumber, 3, &so[5743]}, + {"x121Address", "x121Address", NID_x121Address, 3, &so[5746]}, + {"internationaliSDNNumber", "internationaliSDNNumber", NID_internationaliSDNNumber, 3, &so[5749]}, + {"registeredAddress", "registeredAddress", NID_registeredAddress, 3, &so[5752]}, + {"destinationIndicator", "destinationIndicator", NID_destinationIndicator, 3, &so[5755]}, + {"preferredDeliveryMethod", "preferredDeliveryMethod", NID_preferredDeliveryMethod, 3, &so[5758]}, + {"presentationAddress", "presentationAddress", NID_presentationAddress, 3, &so[5761]}, + {"supportedApplicationContext", "supportedApplicationContext", NID_supportedApplicationContext, 3, &so[5764]}, + {"member", "member", NID_member, 3, &so[5767]}, + {"owner", "owner", NID_owner, 3, &so[5770]}, + {"roleOccupant", "roleOccupant", NID_roleOccupant, 3, &so[5773]}, + {"seeAlso", "seeAlso", NID_seeAlso, 3, &so[5776]}, + {"userPassword", "userPassword", NID_userPassword, 3, &so[5779]}, + {"userCertificate", "userCertificate", NID_userCertificate, 3, &so[5782]}, + {"cACertificate", "cACertificate", NID_cACertificate, 3, &so[5785]}, + {"authorityRevocationList", "authorityRevocationList", NID_authorityRevocationList, 3, &so[5788]}, + {"certificateRevocationList", "certificateRevocationList", NID_certificateRevocationList, 3, &so[5791]}, + {"crossCertificatePair", "crossCertificatePair", NID_crossCertificatePair, 3, &so[5794]}, + {"enhancedSearchGuide", "enhancedSearchGuide", NID_enhancedSearchGuide, 3, &so[5797]}, + {"protocolInformation", "protocolInformation", NID_protocolInformation, 3, &so[5800]}, + {"distinguishedName", "distinguishedName", NID_distinguishedName, 3, &so[5803]}, + {"uniqueMember", "uniqueMember", NID_uniqueMember, 3, &so[5806]}, + {"houseIdentifier", "houseIdentifier", NID_houseIdentifier, 3, &so[5809]}, + {"supportedAlgorithms", "supportedAlgorithms", NID_supportedAlgorithms, 3, &so[5812]}, + {"deltaRevocationList", "deltaRevocationList", NID_deltaRevocationList, 3, &so[5815]}, + {"dmdName", "dmdName", NID_dmdName, 3, &so[5818]}, + {"id-alg-PWRI-KEK", "id-alg-PWRI-KEK", NID_id_alg_PWRI_KEK, 11, &so[5821]}, + {"CMAC", "cmac", NID_cmac}, + {"id-aes128-GCM", "aes-128-gcm", NID_aes_128_gcm, 9, &so[5832]}, + {"id-aes128-CCM", "aes-128-ccm", NID_aes_128_ccm, 9, &so[5841]}, + {"id-aes128-wrap-pad", "id-aes128-wrap-pad", NID_id_aes128_wrap_pad, 9, &so[5850]}, + {"id-aes192-GCM", "aes-192-gcm", NID_aes_192_gcm, 9, &so[5859]}, + {"id-aes192-CCM", "aes-192-ccm", NID_aes_192_ccm, 9, &so[5868]}, + {"id-aes192-wrap-pad", "id-aes192-wrap-pad", NID_id_aes192_wrap_pad, 9, &so[5877]}, + {"id-aes256-GCM", "aes-256-gcm", NID_aes_256_gcm, 9, &so[5886]}, + {"id-aes256-CCM", "aes-256-ccm", NID_aes_256_ccm, 9, &so[5895]}, + {"id-aes256-wrap-pad", "id-aes256-wrap-pad", NID_id_aes256_wrap_pad, 9, &so[5904]}, + {"AES-128-CTR", "aes-128-ctr", NID_aes_128_ctr}, + {"AES-192-CTR", "aes-192-ctr", NID_aes_192_ctr}, + {"AES-256-CTR", "aes-256-ctr", NID_aes_256_ctr}, + {"id-camellia128-wrap", "id-camellia128-wrap", NID_id_camellia128_wrap, 11, &so[5913]}, + {"id-camellia192-wrap", "id-camellia192-wrap", NID_id_camellia192_wrap, 11, &so[5924]}, + {"id-camellia256-wrap", "id-camellia256-wrap", NID_id_camellia256_wrap, 11, &so[5935]}, + {"anyExtendedKeyUsage", "Any Extended Key Usage", NID_anyExtendedKeyUsage, 4, &so[5946]}, + {"MGF1", "mgf1", NID_mgf1, 9, &so[5950]}, + {"RSASSA-PSS", "rsassaPss", NID_rsassaPss, 9, &so[5959]}, + {"AES-128-XTS", "aes-128-xts", NID_aes_128_xts, 8, &so[5968]}, + {"AES-256-XTS", "aes-256-xts", NID_aes_256_xts, 8, &so[5976]}, + {"RC4-HMAC-MD5", "rc4-hmac-md5", NID_rc4_hmac_md5}, + {"AES-128-CBC-HMAC-SHA1", "aes-128-cbc-hmac-sha1", NID_aes_128_cbc_hmac_sha1}, + {"AES-192-CBC-HMAC-SHA1", "aes-192-cbc-hmac-sha1", NID_aes_192_cbc_hmac_sha1}, + {"AES-256-CBC-HMAC-SHA1", "aes-256-cbc-hmac-sha1", NID_aes_256_cbc_hmac_sha1}, + {"RSAES-OAEP", "rsaesOaep", NID_rsaesOaep, 9, &so[5984]}, + {"dhpublicnumber", "X9.42 DH", NID_dhpublicnumber, 7, &so[5993]}, + {"brainpoolP160r1", "brainpoolP160r1", NID_brainpoolP160r1, 9, &so[6000]}, + {"brainpoolP160t1", "brainpoolP160t1", NID_brainpoolP160t1, 9, &so[6009]}, + {"brainpoolP192r1", "brainpoolP192r1", NID_brainpoolP192r1, 9, &so[6018]}, + {"brainpoolP192t1", "brainpoolP192t1", NID_brainpoolP192t1, 9, &so[6027]}, + {"brainpoolP224r1", "brainpoolP224r1", NID_brainpoolP224r1, 9, &so[6036]}, + {"brainpoolP224t1", "brainpoolP224t1", NID_brainpoolP224t1, 9, &so[6045]}, + {"brainpoolP256r1", "brainpoolP256r1", NID_brainpoolP256r1, 9, &so[6054]}, + {"brainpoolP256t1", "brainpoolP256t1", NID_brainpoolP256t1, 9, &so[6063]}, + {"brainpoolP320r1", "brainpoolP320r1", NID_brainpoolP320r1, 9, &so[6072]}, + {"brainpoolP320t1", "brainpoolP320t1", NID_brainpoolP320t1, 9, &so[6081]}, + {"brainpoolP384r1", "brainpoolP384r1", NID_brainpoolP384r1, 9, &so[6090]}, + {"brainpoolP384t1", "brainpoolP384t1", NID_brainpoolP384t1, 9, &so[6099]}, + {"brainpoolP512r1", "brainpoolP512r1", NID_brainpoolP512r1, 9, &so[6108]}, + {"brainpoolP512t1", "brainpoolP512t1", NID_brainpoolP512t1, 9, &so[6117]}, + {"PSPECIFIED", "pSpecified", NID_pSpecified, 9, &so[6126]}, + {"dhSinglePass-stdDH-sha1kdf-scheme", "dhSinglePass-stdDH-sha1kdf-scheme", NID_dhSinglePass_stdDH_sha1kdf_scheme, 9, &so[6135]}, + {"dhSinglePass-stdDH-sha224kdf-scheme", "dhSinglePass-stdDH-sha224kdf-scheme", NID_dhSinglePass_stdDH_sha224kdf_scheme, 6, &so[6144]}, + {"dhSinglePass-stdDH-sha256kdf-scheme", "dhSinglePass-stdDH-sha256kdf-scheme", NID_dhSinglePass_stdDH_sha256kdf_scheme, 6, &so[6150]}, + {"dhSinglePass-stdDH-sha384kdf-scheme", "dhSinglePass-stdDH-sha384kdf-scheme", NID_dhSinglePass_stdDH_sha384kdf_scheme, 6, &so[6156]}, + {"dhSinglePass-stdDH-sha512kdf-scheme", "dhSinglePass-stdDH-sha512kdf-scheme", NID_dhSinglePass_stdDH_sha512kdf_scheme, 6, &so[6162]}, + {"dhSinglePass-cofactorDH-sha1kdf-scheme", "dhSinglePass-cofactorDH-sha1kdf-scheme", NID_dhSinglePass_cofactorDH_sha1kdf_scheme, 9, &so[6168]}, + {"dhSinglePass-cofactorDH-sha224kdf-scheme", "dhSinglePass-cofactorDH-sha224kdf-scheme", NID_dhSinglePass_cofactorDH_sha224kdf_scheme, 6, &so[6177]}, + {"dhSinglePass-cofactorDH-sha256kdf-scheme", "dhSinglePass-cofactorDH-sha256kdf-scheme", NID_dhSinglePass_cofactorDH_sha256kdf_scheme, 6, &so[6183]}, + {"dhSinglePass-cofactorDH-sha384kdf-scheme", "dhSinglePass-cofactorDH-sha384kdf-scheme", NID_dhSinglePass_cofactorDH_sha384kdf_scheme, 6, &so[6189]}, + {"dhSinglePass-cofactorDH-sha512kdf-scheme", "dhSinglePass-cofactorDH-sha512kdf-scheme", NID_dhSinglePass_cofactorDH_sha512kdf_scheme, 6, &so[6195]}, + {"dh-std-kdf", "dh-std-kdf", NID_dh_std_kdf}, + {"dh-cofactor-kdf", "dh-cofactor-kdf", NID_dh_cofactor_kdf}, + {"AES-128-CBC-HMAC-SHA256", "aes-128-cbc-hmac-sha256", NID_aes_128_cbc_hmac_sha256}, + {"AES-192-CBC-HMAC-SHA256", "aes-192-cbc-hmac-sha256", NID_aes_192_cbc_hmac_sha256}, + {"AES-256-CBC-HMAC-SHA256", "aes-256-cbc-hmac-sha256", NID_aes_256_cbc_hmac_sha256}, + {"ct_precert_scts", "CT Precertificate SCTs", NID_ct_precert_scts, 10, &so[6201]}, + {"ct_precert_poison", "CT Precertificate Poison", NID_ct_precert_poison, 10, &so[6211]}, + {"ct_precert_signer", "CT Precertificate Signer", NID_ct_precert_signer, 10, &so[6221]}, + {"ct_cert_scts", "CT Certificate SCTs", NID_ct_cert_scts, 10, &so[6231]}, + {"jurisdictionL", "jurisdictionLocalityName", NID_jurisdictionLocalityName, 11, &so[6241]}, + {"jurisdictionST", "jurisdictionStateOrProvinceName", NID_jurisdictionStateOrProvinceName, 11, &so[6252]}, + {"jurisdictionC", "jurisdictionCountryName", NID_jurisdictionCountryName, 11, &so[6263]}, + {"AES-128-OCB", "aes-128-ocb", NID_aes_128_ocb}, + {"AES-192-OCB", "aes-192-ocb", NID_aes_192_ocb}, + {"AES-256-OCB", "aes-256-ocb", NID_aes_256_ocb}, + {"CAMELLIA-128-GCM", "camellia-128-gcm", NID_camellia_128_gcm, 8, &so[6274]}, + {"CAMELLIA-128-CCM", "camellia-128-ccm", NID_camellia_128_ccm, 8, &so[6282]}, + {"CAMELLIA-128-CTR", "camellia-128-ctr", NID_camellia_128_ctr, 8, &so[6290]}, + {"CAMELLIA-128-CMAC", "camellia-128-cmac", NID_camellia_128_cmac, 8, &so[6298]}, + {"CAMELLIA-192-GCM", "camellia-192-gcm", NID_camellia_192_gcm, 8, &so[6306]}, + {"CAMELLIA-192-CCM", "camellia-192-ccm", NID_camellia_192_ccm, 8, &so[6314]}, + {"CAMELLIA-192-CTR", "camellia-192-ctr", NID_camellia_192_ctr, 8, &so[6322]}, + {"CAMELLIA-192-CMAC", "camellia-192-cmac", NID_camellia_192_cmac, 8, &so[6330]}, + {"CAMELLIA-256-GCM", "camellia-256-gcm", NID_camellia_256_gcm, 8, &so[6338]}, + {"CAMELLIA-256-CCM", "camellia-256-ccm", NID_camellia_256_ccm, 8, &so[6346]}, + {"CAMELLIA-256-CTR", "camellia-256-ctr", NID_camellia_256_ctr, 8, &so[6354]}, + {"CAMELLIA-256-CMAC", "camellia-256-cmac", NID_camellia_256_cmac, 8, &so[6362]}, + {"id-scrypt", "scrypt", NID_id_scrypt, 9, &so[6370]}, + {"id-tc26", "id-tc26", NID_id_tc26, 5, &so[6379]}, + {"gost89-cnt-12", "gost89-cnt-12", NID_gost89_cnt_12}, + {"gost-mac-12", "gost-mac-12", NID_gost_mac_12}, + {"id-tc26-algorithms", "id-tc26-algorithms", NID_id_tc26_algorithms, 6, &so[6384]}, + {"id-tc26-sign", "id-tc26-sign", NID_id_tc26_sign, 7, &so[6390]}, + {"gost2012_256", "GOST R 34.10-2012 with 256 bit modulus", NID_id_GostR3410_2012_256, 8, &so[6397]}, + {"gost2012_512", "GOST R 34.10-2012 with 512 bit modulus", NID_id_GostR3410_2012_512, 8, &so[6405]}, + {"id-tc26-digest", "id-tc26-digest", NID_id_tc26_digest, 7, &so[6413]}, + {"md_gost12_256", "GOST R 34.11-2012 with 256 bit hash", NID_id_GostR3411_2012_256, 8, &so[6420]}, + {"md_gost12_512", "GOST R 34.11-2012 with 512 bit hash", NID_id_GostR3411_2012_512, 8, &so[6428]}, + {"id-tc26-signwithdigest", "id-tc26-signwithdigest", NID_id_tc26_signwithdigest, 7, &so[6436]}, + {"id-tc26-signwithdigest-gost3410-2012-256", "GOST R 34.10-2012 with GOST R 34.11-2012 (256 bit)", NID_id_tc26_signwithdigest_gost3410_2012_256, 8, &so[6443]}, + {"id-tc26-signwithdigest-gost3410-2012-512", "GOST R 34.10-2012 with GOST R 34.11-2012 (512 bit)", NID_id_tc26_signwithdigest_gost3410_2012_512, 8, &so[6451]}, + {"id-tc26-mac", "id-tc26-mac", NID_id_tc26_mac, 7, &so[6459]}, + {"id-tc26-hmac-gost-3411-2012-256", "HMAC GOST 34.11-2012 256 bit", NID_id_tc26_hmac_gost_3411_2012_256, 8, &so[6466]}, + {"id-tc26-hmac-gost-3411-2012-512", "HMAC GOST 34.11-2012 512 bit", NID_id_tc26_hmac_gost_3411_2012_512, 8, &so[6474]}, + {"id-tc26-cipher", "id-tc26-cipher", NID_id_tc26_cipher, 7, &so[6482]}, + {"id-tc26-agreement", "id-tc26-agreement", NID_id_tc26_agreement, 7, &so[6489]}, + {"id-tc26-agreement-gost-3410-2012-256", "id-tc26-agreement-gost-3410-2012-256", NID_id_tc26_agreement_gost_3410_2012_256, 8, &so[6496]}, + {"id-tc26-agreement-gost-3410-2012-512", "id-tc26-agreement-gost-3410-2012-512", NID_id_tc26_agreement_gost_3410_2012_512, 8, &so[6504]}, + {"id-tc26-constants", "id-tc26-constants", NID_id_tc26_constants, 6, &so[6512]}, + {"id-tc26-sign-constants", "id-tc26-sign-constants", NID_id_tc26_sign_constants, 7, &so[6518]}, + {"id-tc26-gost-3410-2012-512-constants", "id-tc26-gost-3410-2012-512-constants", NID_id_tc26_gost_3410_2012_512_constants, 8, &so[6525]}, + {"id-tc26-gost-3410-2012-512-paramSetTest", "GOST R 34.10-2012 (512 bit) testing parameter set", NID_id_tc26_gost_3410_2012_512_paramSetTest, 9, &so[6533]}, + {"id-tc26-gost-3410-2012-512-paramSetA", "GOST R 34.10-2012 (512 bit) ParamSet A", NID_id_tc26_gost_3410_2012_512_paramSetA, 9, &so[6542]}, + {"id-tc26-gost-3410-2012-512-paramSetB", "GOST R 34.10-2012 (512 bit) ParamSet B", NID_id_tc26_gost_3410_2012_512_paramSetB, 9, &so[6551]}, + {"id-tc26-digest-constants", "id-tc26-digest-constants", NID_id_tc26_digest_constants, 7, &so[6560]}, + {"id-tc26-cipher-constants", "id-tc26-cipher-constants", NID_id_tc26_cipher_constants, 7, &so[6567]}, + {"id-tc26-gost-28147-constants", "id-tc26-gost-28147-constants", NID_id_tc26_gost_28147_constants, 8, &so[6574]}, + {"id-tc26-gost-28147-param-Z", "GOST 28147-89 TC26 parameter set", NID_id_tc26_gost_28147_param_Z, 9, &so[6582]}, + {"INN", "INN", NID_INN, 8, &so[6591]}, + {"OGRN", "OGRN", NID_OGRN, 5, &so[6599]}, + {"SNILS", "SNILS", NID_SNILS, 5, &so[6604]}, + {"subjectSignTool", "Signing Tool of Subject", NID_subjectSignTool, 5, &so[6609]}, + {"issuerSignTool", "Signing Tool of Issuer", NID_issuerSignTool, 5, &so[6614]}, + {"gost89-cbc", "gost89-cbc", NID_gost89_cbc}, + {"gost89-ecb", "gost89-ecb", NID_gost89_ecb}, + {"gost89-ctr", "gost89-ctr", NID_gost89_ctr}, + {"grasshopper-ecb", "grasshopper-ecb", NID_grasshopper_ecb}, + {"grasshopper-ctr", "grasshopper-ctr", NID_grasshopper_ctr}, + {"grasshopper-ofb", "grasshopper-ofb", NID_grasshopper_ofb}, + {"grasshopper-cbc", "grasshopper-cbc", NID_grasshopper_cbc}, + {"grasshopper-cfb", "grasshopper-cfb", NID_grasshopper_cfb}, + {"grasshopper-mac", "grasshopper-mac", NID_grasshopper_mac}, + {"ChaCha20-Poly1305", "chacha20-poly1305", NID_chacha20_poly1305}, + {"ChaCha20", "chacha20", NID_chacha20}, + {"tlsfeature", "TLS Feature", NID_tlsfeature, 8, &so[6619]}, + {"TLS1-PRF", "tls1-prf", NID_tls1_prf}, + {"ipsecIKE", "ipsec Internet Key Exchange", NID_ipsec_IKE, 8, &so[6627]}, + {"capwapAC", "Ctrl/provision WAP Access", NID_capwapAC, 8, &so[6635]}, + {"capwapWTP", "Ctrl/Provision WAP Termination", NID_capwapWTP, 8, &so[6643]}, + {"secureShellClient", "SSH Client", NID_sshClient, 8, &so[6651]}, + {"secureShellServer", "SSH Server", NID_sshServer, 8, &so[6659]}, + {"sendRouter", "Send Router", NID_sendRouter, 8, &so[6667]}, + {"sendProxiedRouter", "Send Proxied Router", NID_sendProxiedRouter, 8, &so[6675]}, + {"sendOwner", "Send Owner", NID_sendOwner, 8, &so[6683]}, + {"sendProxiedOwner", "Send Proxied Owner", NID_sendProxiedOwner, 8, &so[6691]}, + {"id-pkinit", "id-pkinit", NID_id_pkinit, 6, &so[6699]}, + {"pkInitClientAuth", "PKINIT Client Auth", NID_pkInitClientAuth, 7, &so[6705]}, + {"pkInitKDC", "Signing KDC Response", NID_pkInitKDC, 7, &so[6712]}, + {"X25519", "X25519", NID_X25519, 3, &so[6719]}, + {"X448", "X448", NID_X448, 3, &so[6722]}, + {"HKDF", "hkdf", NID_hkdf}, + {"KxRSA", "kx-rsa", NID_kx_rsa}, + {"KxECDHE", "kx-ecdhe", NID_kx_ecdhe}, + {"KxDHE", "kx-dhe", NID_kx_dhe}, + {"KxECDHE-PSK", "kx-ecdhe-psk", NID_kx_ecdhe_psk}, + {"KxDHE-PSK", "kx-dhe-psk", NID_kx_dhe_psk}, + {"KxRSA_PSK", "kx-rsa-psk", NID_kx_rsa_psk}, + {"KxPSK", "kx-psk", NID_kx_psk}, + {"KxSRP", "kx-srp", NID_kx_srp}, + {"KxGOST", "kx-gost", NID_kx_gost}, + {"AuthRSA", "auth-rsa", NID_auth_rsa}, + {"AuthECDSA", "auth-ecdsa", NID_auth_ecdsa}, + {"AuthPSK", "auth-psk", NID_auth_psk}, + {"AuthDSS", "auth-dss", NID_auth_dss}, + {"AuthGOST01", "auth-gost01", NID_auth_gost01}, + {"AuthGOST12", "auth-gost12", NID_auth_gost12}, + {"AuthSRP", "auth-srp", NID_auth_srp}, + {"AuthNULL", "auth-null", NID_auth_null}, + { NULL, NULL, NID_undef }, + { NULL, NULL, NID_undef }, + {"BLAKE2b512", "blake2b512", NID_blake2b512, 11, &so[6725]}, + {"BLAKE2s256", "blake2s256", NID_blake2s256, 11, &so[6736]}, + {"id-smime-ct-contentCollection", "id-smime-ct-contentCollection", NID_id_smime_ct_contentCollection, 11, &so[6747]}, + {"id-smime-ct-authEnvelopedData", "id-smime-ct-authEnvelopedData", NID_id_smime_ct_authEnvelopedData, 11, &so[6758]}, + {"id-ct-xml", "id-ct-xml", NID_id_ct_xml, 11, &so[6769]}, + {"Poly1305", "poly1305", NID_poly1305}, + {"SipHash", "siphash", NID_siphash}, + {"KxANY", "kx-any", NID_kx_any}, + {"AuthANY", "auth-any", NID_auth_any}, + {"ARIA-128-ECB", "aria-128-ecb", NID_aria_128_ecb, 9, &so[6780]}, + {"ARIA-128-CBC", "aria-128-cbc", NID_aria_128_cbc, 9, &so[6789]}, + {"ARIA-128-CFB", "aria-128-cfb", NID_aria_128_cfb128, 9, &so[6798]}, + {"ARIA-128-OFB", "aria-128-ofb", NID_aria_128_ofb128, 9, &so[6807]}, + {"ARIA-128-CTR", "aria-128-ctr", NID_aria_128_ctr, 9, &so[6816]}, + {"ARIA-192-ECB", "aria-192-ecb", NID_aria_192_ecb, 9, &so[6825]}, + {"ARIA-192-CBC", "aria-192-cbc", NID_aria_192_cbc, 9, &so[6834]}, + {"ARIA-192-CFB", "aria-192-cfb", NID_aria_192_cfb128, 9, &so[6843]}, + {"ARIA-192-OFB", "aria-192-ofb", NID_aria_192_ofb128, 9, &so[6852]}, + {"ARIA-192-CTR", "aria-192-ctr", NID_aria_192_ctr, 9, &so[6861]}, + {"ARIA-256-ECB", "aria-256-ecb", NID_aria_256_ecb, 9, &so[6870]}, + {"ARIA-256-CBC", "aria-256-cbc", NID_aria_256_cbc, 9, &so[6879]}, + {"ARIA-256-CFB", "aria-256-cfb", NID_aria_256_cfb128, 9, &so[6888]}, + {"ARIA-256-OFB", "aria-256-ofb", NID_aria_256_ofb128, 9, &so[6897]}, + {"ARIA-256-CTR", "aria-256-ctr", NID_aria_256_ctr, 9, &so[6906]}, + {"ARIA-128-CFB1", "aria-128-cfb1", NID_aria_128_cfb1}, + {"ARIA-192-CFB1", "aria-192-cfb1", NID_aria_192_cfb1}, + {"ARIA-256-CFB1", "aria-256-cfb1", NID_aria_256_cfb1}, + {"ARIA-128-CFB8", "aria-128-cfb8", NID_aria_128_cfb8}, + {"ARIA-192-CFB8", "aria-192-cfb8", NID_aria_192_cfb8}, + {"ARIA-256-CFB8", "aria-256-cfb8", NID_aria_256_cfb8}, + {"id-smime-aa-signingCertificateV2", "id-smime-aa-signingCertificateV2", NID_id_smime_aa_signingCertificateV2, 11, &so[6915]}, + {"ED25519", "ED25519", NID_ED25519, 3, &so[6926]}, + {"ED448", "ED448", NID_ED448, 3, &so[6929]}, + {"organizationIdentifier", "organizationIdentifier", NID_organizationIdentifier, 3, &so[6932]}, + {"c3", "countryCode3c", NID_countryCode3c, 3, &so[6935]}, + {"n3", "countryCode3n", NID_countryCode3n, 3, &so[6938]}, + {"dnsName", "dnsName", NID_dnsName, 3, &so[6941]}, + {"x509ExtAdmission", "Professional Information or basis for Admission", NID_x509ExtAdmission, 5, &so[6944]}, + {"SHA512-224", "sha512-224", NID_sha512_224, 9, &so[6949]}, + {"SHA512-256", "sha512-256", NID_sha512_256, 9, &so[6958]}, + {"SHA3-224", "sha3-224", NID_sha3_224, 9, &so[6967]}, + {"SHA3-256", "sha3-256", NID_sha3_256, 9, &so[6976]}, + {"SHA3-384", "sha3-384", NID_sha3_384, 9, &so[6985]}, + {"SHA3-512", "sha3-512", NID_sha3_512, 9, &so[6994]}, + {"SHAKE128", "shake128", NID_shake128, 9, &so[7003]}, + {"SHAKE256", "shake256", NID_shake256, 9, &so[7012]}, + {"id-hmacWithSHA3-224", "hmac-sha3-224", NID_hmac_sha3_224, 9, &so[7021]}, + {"id-hmacWithSHA3-256", "hmac-sha3-256", NID_hmac_sha3_256, 9, &so[7030]}, + {"id-hmacWithSHA3-384", "hmac-sha3-384", NID_hmac_sha3_384, 9, &so[7039]}, + {"id-hmacWithSHA3-512", "hmac-sha3-512", NID_hmac_sha3_512, 9, &so[7048]}, + {"id-dsa-with-sha384", "dsa_with_SHA384", NID_dsa_with_SHA384, 9, &so[7057]}, + {"id-dsa-with-sha512", "dsa_with_SHA512", NID_dsa_with_SHA512, 9, &so[7066]}, + {"id-dsa-with-sha3-224", "dsa_with_SHA3-224", NID_dsa_with_SHA3_224, 9, &so[7075]}, + {"id-dsa-with-sha3-256", "dsa_with_SHA3-256", NID_dsa_with_SHA3_256, 9, &so[7084]}, + {"id-dsa-with-sha3-384", "dsa_with_SHA3-384", NID_dsa_with_SHA3_384, 9, &so[7093]}, + {"id-dsa-with-sha3-512", "dsa_with_SHA3-512", NID_dsa_with_SHA3_512, 9, &so[7102]}, + {"id-ecdsa-with-sha3-224", "ecdsa_with_SHA3-224", NID_ecdsa_with_SHA3_224, 9, &so[7111]}, + {"id-ecdsa-with-sha3-256", "ecdsa_with_SHA3-256", NID_ecdsa_with_SHA3_256, 9, &so[7120]}, + {"id-ecdsa-with-sha3-384", "ecdsa_with_SHA3-384", NID_ecdsa_with_SHA3_384, 9, &so[7129]}, + {"id-ecdsa-with-sha3-512", "ecdsa_with_SHA3-512", NID_ecdsa_with_SHA3_512, 9, &so[7138]}, + {"id-rsassa-pkcs1-v1_5-with-sha3-224", "RSA-SHA3-224", NID_RSA_SHA3_224, 9, &so[7147]}, + {"id-rsassa-pkcs1-v1_5-with-sha3-256", "RSA-SHA3-256", NID_RSA_SHA3_256, 9, &so[7156]}, + {"id-rsassa-pkcs1-v1_5-with-sha3-384", "RSA-SHA3-384", NID_RSA_SHA3_384, 9, &so[7165]}, + {"id-rsassa-pkcs1-v1_5-with-sha3-512", "RSA-SHA3-512", NID_RSA_SHA3_512, 9, &so[7174]}, + {"ARIA-128-CCM", "aria-128-ccm", NID_aria_128_ccm, 9, &so[7183]}, + {"ARIA-192-CCM", "aria-192-ccm", NID_aria_192_ccm, 9, &so[7192]}, + {"ARIA-256-CCM", "aria-256-ccm", NID_aria_256_ccm, 9, &so[7201]}, + {"ARIA-128-GCM", "aria-128-gcm", NID_aria_128_gcm, 9, &so[7210]}, + {"ARIA-192-GCM", "aria-192-gcm", NID_aria_192_gcm, 9, &so[7219]}, + {"ARIA-256-GCM", "aria-256-gcm", NID_aria_256_gcm, 9, &so[7228]}, + {"ffdhe2048", "ffdhe2048", NID_ffdhe2048}, + {"ffdhe3072", "ffdhe3072", NID_ffdhe3072}, + {"ffdhe4096", "ffdhe4096", NID_ffdhe4096}, + {"ffdhe6144", "ffdhe6144", NID_ffdhe6144}, + {"ffdhe8192", "ffdhe8192", NID_ffdhe8192}, + {"cmcCA", "CMC Certificate Authority", NID_cmcCA, 8, &so[7237]}, + {"cmcRA", "CMC Registration Authority", NID_cmcRA, 8, &so[7245]}, + {"SM4-ECB", "sm4-ecb", NID_sm4_ecb, 8, &so[7253]}, + {"SM4-CBC", "sm4-cbc", NID_sm4_cbc, 8, &so[7261]}, + {"SM4-OFB", "sm4-ofb", NID_sm4_ofb128, 8, &so[7269]}, + {"SM4-CFB1", "sm4-cfb1", NID_sm4_cfb1, 8, &so[7277]}, + {"SM4-CFB", "sm4-cfb", NID_sm4_cfb128, 8, &so[7285]}, + {"SM4-CFB8", "sm4-cfb8", NID_sm4_cfb8, 8, &so[7293]}, + {"SM4-CTR", "sm4-ctr", NID_sm4_ctr, 8, &so[7301]}, + {"ISO-CN", "ISO CN Member Body", NID_ISO_CN, 3, &so[7309]}, + {"oscca", "oscca", NID_oscca, 5, &so[7312]}, + {"sm-scheme", "sm-scheme", NID_sm_scheme, 6, &so[7317]}, + {"SM3", "sm3", NID_sm3, 8, &so[7323]}, + {"RSA-SM3", "sm3WithRSAEncryption", NID_sm3WithRSAEncryption, 8, &so[7331]}, + {"RSA-SHA512/224", "sha512-224WithRSAEncryption", NID_sha512_224WithRSAEncryption, 9, &so[7339]}, + {"RSA-SHA512/256", "sha512-256WithRSAEncryption", NID_sha512_256WithRSAEncryption, 9, &so[7348]}, + {"id-tc26-gost-3410-2012-256-constants", "id-tc26-gost-3410-2012-256-constants", NID_id_tc26_gost_3410_2012_256_constants, 8, &so[7357]}, + {"id-tc26-gost-3410-2012-256-paramSetA", "GOST R 34.10-2012 (256 bit) ParamSet A", NID_id_tc26_gost_3410_2012_256_paramSetA, 9, &so[7365]}, + {"id-tc26-gost-3410-2012-512-paramSetC", "GOST R 34.10-2012 (512 bit) ParamSet C", NID_id_tc26_gost_3410_2012_512_paramSetC, 9, &so[7374]}, + {"ISO-UA", "ISO-UA", NID_ISO_UA, 3, &so[7383]}, + {"ua-pki", "ua-pki", NID_ua_pki, 7, &so[7386]}, + {"dstu28147", "DSTU Gost 28147-2009", NID_dstu28147, 10, &so[7393]}, + {"dstu28147-ofb", "DSTU Gost 28147-2009 OFB mode", NID_dstu28147_ofb, 11, &so[7403]}, + {"dstu28147-cfb", "DSTU Gost 28147-2009 CFB mode", NID_dstu28147_cfb, 11, &so[7414]}, + {"dstu28147-wrap", "DSTU Gost 28147-2009 key wrap", NID_dstu28147_wrap, 11, &so[7425]}, + {"hmacWithDstu34311", "HMAC DSTU Gost 34311-95", NID_hmacWithDstu34311, 10, &so[7436]}, + {"dstu34311", "DSTU Gost 34311-95", NID_dstu34311, 10, &so[7446]}, + {"dstu4145le", "DSTU 4145-2002 little endian", NID_dstu4145le, 11, &so[7456]}, + {"dstu4145be", "DSTU 4145-2002 big endian", NID_dstu4145be, 13, &so[7467]}, + {"uacurve0", "DSTU curve 0", NID_uacurve0, 13, &so[7480]}, + {"uacurve1", "DSTU curve 1", NID_uacurve1, 13, &so[7493]}, + {"uacurve2", "DSTU curve 2", NID_uacurve2, 13, &so[7506]}, + {"uacurve3", "DSTU curve 3", NID_uacurve3, 13, &so[7519]}, + {"uacurve4", "DSTU curve 4", NID_uacurve4, 13, &so[7532]}, + {"uacurve5", "DSTU curve 5", NID_uacurve5, 13, &so[7545]}, + {"uacurve6", "DSTU curve 6", NID_uacurve6, 13, &so[7558]}, + {"uacurve7", "DSTU curve 7", NID_uacurve7, 13, &so[7571]}, + {"uacurve8", "DSTU curve 8", NID_uacurve8, 13, &so[7584]}, + {"uacurve9", "DSTU curve 9", NID_uacurve9, 13, &so[7597]}, + {"ieee", "ieee", NID_ieee, 2, &so[7610]}, + {"ieee-siswg", "IEEE Security in Storage Working Group", NID_ieee_siswg, 5, &so[7612]}, + {"SM2", "sm2", NID_sm2, 8, &so[7617]}, + {"id-tc26-cipher-gostr3412-2015-magma", "id-tc26-cipher-gostr3412-2015-magma", NID_id_tc26_cipher_gostr3412_2015_magma, 8, &so[7625]}, + {"id-tc26-cipher-gostr3412-2015-magma-ctracpkm", "id-tc26-cipher-gostr3412-2015-magma-ctracpkm", NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm, 9, &so[7633]}, + {"id-tc26-cipher-gostr3412-2015-magma-ctracpkm-omac", "id-tc26-cipher-gostr3412-2015-magma-ctracpkm-omac", NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac, 9, &so[7642]}, + {"id-tc26-cipher-gostr3412-2015-kuznyechik", "id-tc26-cipher-gostr3412-2015-kuznyechik", NID_id_tc26_cipher_gostr3412_2015_kuznyechik, 8, &so[7651]}, + {"id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm", "id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm", NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm, 9, &so[7659]}, + {"id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm-omac", "id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm-omac", NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac, 9, &so[7668]}, + {"id-tc26-wrap", "id-tc26-wrap", NID_id_tc26_wrap, 7, &so[7677]}, + {"id-tc26-wrap-gostr3412-2015-magma", "id-tc26-wrap-gostr3412-2015-magma", NID_id_tc26_wrap_gostr3412_2015_magma, 8, &so[7684]}, + {"id-tc26-wrap-gostr3412-2015-magma-kexp15", "id-tc26-wrap-gostr3412-2015-magma-kexp15", NID_id_tc26_wrap_gostr3412_2015_magma_kexp15, 9, &so[7692]}, + {"id-tc26-wrap-gostr3412-2015-kuznyechik", "id-tc26-wrap-gostr3412-2015-kuznyechik", NID_id_tc26_wrap_gostr3412_2015_kuznyechik, 8, &so[7701]}, + {"id-tc26-wrap-gostr3412-2015-kuznyechik-kexp15", "id-tc26-wrap-gostr3412-2015-kuznyechik-kexp15", NID_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15, 9, &so[7709]}, + {"id-tc26-gost-3410-2012-256-paramSetB", "GOST R 34.10-2012 (256 bit) ParamSet B", NID_id_tc26_gost_3410_2012_256_paramSetB, 9, &so[7718]}, + {"id-tc26-gost-3410-2012-256-paramSetC", "GOST R 34.10-2012 (256 bit) ParamSet C", NID_id_tc26_gost_3410_2012_256_paramSetC, 9, &so[7727]}, + {"id-tc26-gost-3410-2012-256-paramSetD", "GOST R 34.10-2012 (256 bit) ParamSet D", NID_id_tc26_gost_3410_2012_256_paramSetD, 9, &so[7736]}, + {"magma-ecb", "magma-ecb", NID_magma_ecb}, + {"magma-ctr", "magma-ctr", NID_magma_ctr}, + {"magma-ofb", "magma-ofb", NID_magma_ofb}, + {"magma-cbc", "magma-cbc", NID_magma_cbc}, + {"magma-cfb", "magma-cfb", NID_magma_cfb}, + {"magma-mac", "magma-mac", NID_magma_mac}, + {"hmacWithSHA512-224", "hmacWithSHA512-224", NID_hmacWithSHA512_224, 8, &so[7745]}, + {"hmacWithSHA512-256", "hmacWithSHA512-256", NID_hmacWithSHA512_256, 8, &so[7753]}, +}; + +#define NUM_SN 1186 +static const unsigned int sn_objs[NUM_SN] = { + 364, /* "AD_DVCS" */ + 419, /* "AES-128-CBC" */ + 916, /* "AES-128-CBC-HMAC-SHA1" */ + 948, /* "AES-128-CBC-HMAC-SHA256" */ + 421, /* "AES-128-CFB" */ + 650, /* "AES-128-CFB1" */ + 653, /* "AES-128-CFB8" */ + 904, /* "AES-128-CTR" */ + 418, /* "AES-128-ECB" */ + 958, /* "AES-128-OCB" */ + 420, /* "AES-128-OFB" */ + 913, /* "AES-128-XTS" */ + 423, /* "AES-192-CBC" */ + 917, /* "AES-192-CBC-HMAC-SHA1" */ + 949, /* "AES-192-CBC-HMAC-SHA256" */ + 425, /* "AES-192-CFB" */ + 651, /* "AES-192-CFB1" */ + 654, /* "AES-192-CFB8" */ + 905, /* "AES-192-CTR" */ + 422, /* "AES-192-ECB" */ + 959, /* "AES-192-OCB" */ + 424, /* "AES-192-OFB" */ + 427, /* "AES-256-CBC" */ + 918, /* "AES-256-CBC-HMAC-SHA1" */ + 950, /* "AES-256-CBC-HMAC-SHA256" */ + 429, /* "AES-256-CFB" */ + 652, /* "AES-256-CFB1" */ + 655, /* "AES-256-CFB8" */ + 906, /* "AES-256-CTR" */ + 426, /* "AES-256-ECB" */ + 960, /* "AES-256-OCB" */ + 428, /* "AES-256-OFB" */ + 914, /* "AES-256-XTS" */ + 1066, /* "ARIA-128-CBC" */ + 1120, /* "ARIA-128-CCM" */ + 1067, /* "ARIA-128-CFB" */ + 1080, /* "ARIA-128-CFB1" */ + 1083, /* "ARIA-128-CFB8" */ + 1069, /* "ARIA-128-CTR" */ + 1065, /* "ARIA-128-ECB" */ + 1123, /* "ARIA-128-GCM" */ + 1068, /* "ARIA-128-OFB" */ + 1071, /* "ARIA-192-CBC" */ + 1121, /* "ARIA-192-CCM" */ + 1072, /* "ARIA-192-CFB" */ + 1081, /* "ARIA-192-CFB1" */ + 1084, /* "ARIA-192-CFB8" */ + 1074, /* "ARIA-192-CTR" */ + 1070, /* "ARIA-192-ECB" */ + 1124, /* "ARIA-192-GCM" */ + 1073, /* "ARIA-192-OFB" */ + 1076, /* "ARIA-256-CBC" */ + 1122, /* "ARIA-256-CCM" */ + 1077, /* "ARIA-256-CFB" */ + 1082, /* "ARIA-256-CFB1" */ + 1085, /* "ARIA-256-CFB8" */ + 1079, /* "ARIA-256-CTR" */ + 1075, /* "ARIA-256-ECB" */ + 1125, /* "ARIA-256-GCM" */ + 1078, /* "ARIA-256-OFB" */ + 1064, /* "AuthANY" */ + 1049, /* "AuthDSS" */ + 1047, /* "AuthECDSA" */ + 1050, /* "AuthGOST01" */ + 1051, /* "AuthGOST12" */ + 1053, /* "AuthNULL" */ + 1048, /* "AuthPSK" */ + 1046, /* "AuthRSA" */ + 1052, /* "AuthSRP" */ + 91, /* "BF-CBC" */ + 93, /* "BF-CFB" */ + 92, /* "BF-ECB" */ + 94, /* "BF-OFB" */ + 1056, /* "BLAKE2b512" */ + 1057, /* "BLAKE2s256" */ + 14, /* "C" */ + 751, /* "CAMELLIA-128-CBC" */ + 962, /* "CAMELLIA-128-CCM" */ + 757, /* "CAMELLIA-128-CFB" */ + 760, /* "CAMELLIA-128-CFB1" */ + 763, /* "CAMELLIA-128-CFB8" */ + 964, /* "CAMELLIA-128-CMAC" */ + 963, /* "CAMELLIA-128-CTR" */ + 754, /* "CAMELLIA-128-ECB" */ + 961, /* "CAMELLIA-128-GCM" */ + 766, /* "CAMELLIA-128-OFB" */ + 752, /* "CAMELLIA-192-CBC" */ + 966, /* "CAMELLIA-192-CCM" */ + 758, /* "CAMELLIA-192-CFB" */ + 761, /* "CAMELLIA-192-CFB1" */ + 764, /* "CAMELLIA-192-CFB8" */ + 968, /* "CAMELLIA-192-CMAC" */ + 967, /* "CAMELLIA-192-CTR" */ + 755, /* "CAMELLIA-192-ECB" */ + 965, /* "CAMELLIA-192-GCM" */ + 767, /* "CAMELLIA-192-OFB" */ + 753, /* "CAMELLIA-256-CBC" */ + 970, /* "CAMELLIA-256-CCM" */ + 759, /* "CAMELLIA-256-CFB" */ + 762, /* "CAMELLIA-256-CFB1" */ + 765, /* "CAMELLIA-256-CFB8" */ + 972, /* "CAMELLIA-256-CMAC" */ + 971, /* "CAMELLIA-256-CTR" */ + 756, /* "CAMELLIA-256-ECB" */ + 969, /* "CAMELLIA-256-GCM" */ + 768, /* "CAMELLIA-256-OFB" */ + 108, /* "CAST5-CBC" */ + 110, /* "CAST5-CFB" */ + 109, /* "CAST5-ECB" */ + 111, /* "CAST5-OFB" */ + 894, /* "CMAC" */ + 13, /* "CN" */ + 141, /* "CRLReason" */ + 417, /* "CSPName" */ + 1019, /* "ChaCha20" */ + 1018, /* "ChaCha20-Poly1305" */ + 367, /* "CrlID" */ + 391, /* "DC" */ + 31, /* "DES-CBC" */ + 643, /* "DES-CDMF" */ + 30, /* "DES-CFB" */ + 656, /* "DES-CFB1" */ + 657, /* "DES-CFB8" */ + 29, /* "DES-ECB" */ + 32, /* "DES-EDE" */ + 43, /* "DES-EDE-CBC" */ + 60, /* "DES-EDE-CFB" */ + 62, /* "DES-EDE-OFB" */ + 33, /* "DES-EDE3" */ + 44, /* "DES-EDE3-CBC" */ + 61, /* "DES-EDE3-CFB" */ + 658, /* "DES-EDE3-CFB1" */ + 659, /* "DES-EDE3-CFB8" */ + 63, /* "DES-EDE3-OFB" */ + 45, /* "DES-OFB" */ + 80, /* "DESX-CBC" */ + 380, /* "DOD" */ + 116, /* "DSA" */ + 66, /* "DSA-SHA" */ + 113, /* "DSA-SHA1" */ + 70, /* "DSA-SHA1-old" */ + 67, /* "DSA-old" */ + 297, /* "DVCS" */ + 1087, /* "ED25519" */ + 1088, /* "ED448" */ + 99, /* "GN" */ + 1036, /* "HKDF" */ + 855, /* "HMAC" */ + 780, /* "HMAC-MD5" */ + 781, /* "HMAC-SHA1" */ + 381, /* "IANA" */ + 34, /* "IDEA-CBC" */ + 35, /* "IDEA-CFB" */ + 36, /* "IDEA-ECB" */ + 46, /* "IDEA-OFB" */ + 1004, /* "INN" */ + 181, /* "ISO" */ + 1140, /* "ISO-CN" */ + 1150, /* "ISO-UA" */ + 183, /* "ISO-US" */ + 645, /* "ITU-T" */ + 646, /* "JOINT-ISO-ITU-T" */ + 773, /* "KISA" */ + 1063, /* "KxANY" */ + 1039, /* "KxDHE" */ + 1041, /* "KxDHE-PSK" */ + 1038, /* "KxECDHE" */ + 1040, /* "KxECDHE-PSK" */ + 1045, /* "KxGOST" */ + 1043, /* "KxPSK" */ + 1037, /* "KxRSA" */ + 1042, /* "KxRSA_PSK" */ + 1044, /* "KxSRP" */ + 15, /* "L" */ + 856, /* "LocalKeySet" */ + 3, /* "MD2" */ + 257, /* "MD4" */ + 4, /* "MD5" */ + 114, /* "MD5-SHA1" */ + 95, /* "MDC2" */ + 911, /* "MGF1" */ + 388, /* "Mail" */ + 393, /* "NULL" */ + 404, /* "NULL" */ + 57, /* "Netscape" */ + 366, /* "Nonce" */ + 17, /* "O" */ + 178, /* "OCSP" */ + 180, /* "OCSPSigning" */ + 1005, /* "OGRN" */ + 379, /* "ORG" */ + 18, /* "OU" */ + 749, /* "Oakley-EC2N-3" */ + 750, /* "Oakley-EC2N-4" */ + 9, /* "PBE-MD2-DES" */ + 168, /* "PBE-MD2-RC2-64" */ + 10, /* "PBE-MD5-DES" */ + 169, /* "PBE-MD5-RC2-64" */ + 147, /* "PBE-SHA1-2DES" */ + 146, /* "PBE-SHA1-3DES" */ + 170, /* "PBE-SHA1-DES" */ + 148, /* "PBE-SHA1-RC2-128" */ + 149, /* "PBE-SHA1-RC2-40" */ + 68, /* "PBE-SHA1-RC2-64" */ + 144, /* "PBE-SHA1-RC4-128" */ + 145, /* "PBE-SHA1-RC4-40" */ + 161, /* "PBES2" */ + 69, /* "PBKDF2" */ + 162, /* "PBMAC1" */ + 127, /* "PKIX" */ + 935, /* "PSPECIFIED" */ + 1061, /* "Poly1305" */ + 98, /* "RC2-40-CBC" */ + 166, /* "RC2-64-CBC" */ + 37, /* "RC2-CBC" */ + 39, /* "RC2-CFB" */ + 38, /* "RC2-ECB" */ + 40, /* "RC2-OFB" */ + 5, /* "RC4" */ + 97, /* "RC4-40" */ + 915, /* "RC4-HMAC-MD5" */ + 120, /* "RC5-CBC" */ + 122, /* "RC5-CFB" */ + 121, /* "RC5-ECB" */ + 123, /* "RC5-OFB" */ + 117, /* "RIPEMD160" */ + 19, /* "RSA" */ + 7, /* "RSA-MD2" */ + 396, /* "RSA-MD4" */ + 8, /* "RSA-MD5" */ + 96, /* "RSA-MDC2" */ + 104, /* "RSA-NP-MD5" */ + 119, /* "RSA-RIPEMD160" */ + 42, /* "RSA-SHA" */ + 65, /* "RSA-SHA1" */ + 115, /* "RSA-SHA1-2" */ + 671, /* "RSA-SHA224" */ + 668, /* "RSA-SHA256" */ + 669, /* "RSA-SHA384" */ + 670, /* "RSA-SHA512" */ + 1145, /* "RSA-SHA512/224" */ + 1146, /* "RSA-SHA512/256" */ + 1144, /* "RSA-SM3" */ + 919, /* "RSAES-OAEP" */ + 912, /* "RSASSA-PSS" */ + 777, /* "SEED-CBC" */ + 779, /* "SEED-CFB" */ + 776, /* "SEED-ECB" */ + 778, /* "SEED-OFB" */ + 41, /* "SHA" */ + 64, /* "SHA1" */ + 675, /* "SHA224" */ + 672, /* "SHA256" */ + 1096, /* "SHA3-224" */ + 1097, /* "SHA3-256" */ + 1098, /* "SHA3-384" */ + 1099, /* "SHA3-512" */ + 673, /* "SHA384" */ + 674, /* "SHA512" */ + 1094, /* "SHA512-224" */ + 1095, /* "SHA512-256" */ + 1100, /* "SHAKE128" */ + 1101, /* "SHAKE256" */ + 1172, /* "SM2" */ + 1143, /* "SM3" */ + 1134, /* "SM4-CBC" */ + 1137, /* "SM4-CFB" */ + 1136, /* "SM4-CFB1" */ + 1138, /* "SM4-CFB8" */ + 1139, /* "SM4-CTR" */ + 1133, /* "SM4-ECB" */ + 1135, /* "SM4-OFB" */ + 188, /* "SMIME" */ + 167, /* "SMIME-CAPS" */ + 100, /* "SN" */ + 1006, /* "SNILS" */ + 16, /* "ST" */ + 143, /* "SXNetID" */ + 1062, /* "SipHash" */ + 1021, /* "TLS1-PRF" */ + 458, /* "UID" */ + 0, /* "UNDEF" */ + 1034, /* "X25519" */ + 1035, /* "X448" */ + 11, /* "X500" */ + 378, /* "X500algorithms" */ + 12, /* "X509" */ + 184, /* "X9-57" */ + 185, /* "X9cm" */ + 125, /* "ZLIB" */ + 478, /* "aRecord" */ + 289, /* "aaControls" */ + 287, /* "ac-auditEntity" */ + 397, /* "ac-proxying" */ + 288, /* "ac-targeting" */ + 368, /* "acceptableResponses" */ + 446, /* "account" */ + 363, /* "ad_timestamping" */ + 376, /* "algorithm" */ + 405, /* "ansi-X9-62" */ + 910, /* "anyExtendedKeyUsage" */ + 746, /* "anyPolicy" */ + 370, /* "archiveCutoff" */ + 484, /* "associatedDomain" */ + 485, /* "associatedName" */ + 501, /* "audio" */ + 177, /* "authorityInfoAccess" */ + 90, /* "authorityKeyIdentifier" */ + 882, /* "authorityRevocationList" */ + 87, /* "basicConstraints" */ + 365, /* "basicOCSPResponse" */ + 285, /* "biometricInfo" */ + 921, /* "brainpoolP160r1" */ + 922, /* "brainpoolP160t1" */ + 923, /* "brainpoolP192r1" */ + 924, /* "brainpoolP192t1" */ + 925, /* "brainpoolP224r1" */ + 926, /* "brainpoolP224t1" */ + 927, /* "brainpoolP256r1" */ + 928, /* "brainpoolP256t1" */ + 929, /* "brainpoolP320r1" */ + 930, /* "brainpoolP320t1" */ + 931, /* "brainpoolP384r1" */ + 932, /* "brainpoolP384t1" */ + 933, /* "brainpoolP512r1" */ + 934, /* "brainpoolP512t1" */ + 494, /* "buildingName" */ + 860, /* "businessCategory" */ + 691, /* "c2onb191v4" */ + 692, /* "c2onb191v5" */ + 697, /* "c2onb239v4" */ + 698, /* "c2onb239v5" */ + 684, /* "c2pnb163v1" */ + 685, /* "c2pnb163v2" */ + 686, /* "c2pnb163v3" */ + 687, /* "c2pnb176v1" */ + 693, /* "c2pnb208w1" */ + 699, /* "c2pnb272w1" */ + 700, /* "c2pnb304w1" */ + 702, /* "c2pnb368w1" */ + 688, /* "c2tnb191v1" */ + 689, /* "c2tnb191v2" */ + 690, /* "c2tnb191v3" */ + 694, /* "c2tnb239v1" */ + 695, /* "c2tnb239v2" */ + 696, /* "c2tnb239v3" */ + 701, /* "c2tnb359v1" */ + 703, /* "c2tnb431r1" */ + 1090, /* "c3" */ + 881, /* "cACertificate" */ + 483, /* "cNAMERecord" */ + 179, /* "caIssuers" */ + 785, /* "caRepository" */ + 1023, /* "capwapAC" */ + 1024, /* "capwapWTP" */ + 443, /* "caseIgnoreIA5StringSyntax" */ + 152, /* "certBag" */ + 677, /* "certicom-arc" */ + 771, /* "certificateIssuer" */ + 89, /* "certificatePolicies" */ + 883, /* "certificateRevocationList" */ + 54, /* "challengePassword" */ + 407, /* "characteristic-two-field" */ + 395, /* "clearance" */ + 130, /* "clientAuth" */ + 1131, /* "cmcCA" */ + 1132, /* "cmcRA" */ + 131, /* "codeSigning" */ + 50, /* "contentType" */ + 53, /* "countersignature" */ + 153, /* "crlBag" */ + 103, /* "crlDistributionPoints" */ + 88, /* "crlNumber" */ + 884, /* "crossCertificatePair" */ + 806, /* "cryptocom" */ + 805, /* "cryptopro" */ + 954, /* "ct_cert_scts" */ + 952, /* "ct_precert_poison" */ + 951, /* "ct_precert_scts" */ + 953, /* "ct_precert_signer" */ + 500, /* "dITRedirect" */ + 451, /* "dNSDomain" */ + 495, /* "dSAQuality" */ + 434, /* "data" */ + 390, /* "dcobject" */ + 140, /* "deltaCRL" */ + 891, /* "deltaRevocationList" */ + 107, /* "description" */ + 871, /* "destinationIndicator" */ + 947, /* "dh-cofactor-kdf" */ + 946, /* "dh-std-kdf" */ + 28, /* "dhKeyAgreement" */ + 941, /* "dhSinglePass-cofactorDH-sha1kdf-scheme" */ + 942, /* "dhSinglePass-cofactorDH-sha224kdf-scheme" */ + 943, /* "dhSinglePass-cofactorDH-sha256kdf-scheme" */ + 944, /* "dhSinglePass-cofactorDH-sha384kdf-scheme" */ + 945, /* "dhSinglePass-cofactorDH-sha512kdf-scheme" */ + 936, /* "dhSinglePass-stdDH-sha1kdf-scheme" */ + 937, /* "dhSinglePass-stdDH-sha224kdf-scheme" */ + 938, /* "dhSinglePass-stdDH-sha256kdf-scheme" */ + 939, /* "dhSinglePass-stdDH-sha384kdf-scheme" */ + 940, /* "dhSinglePass-stdDH-sha512kdf-scheme" */ + 920, /* "dhpublicnumber" */ + 382, /* "directory" */ + 887, /* "distinguishedName" */ + 892, /* "dmdName" */ + 174, /* "dnQualifier" */ + 1092, /* "dnsName" */ + 447, /* "document" */ + 471, /* "documentAuthor" */ + 468, /* "documentIdentifier" */ + 472, /* "documentLocation" */ + 502, /* "documentPublisher" */ + 449, /* "documentSeries" */ + 469, /* "documentTitle" */ + 470, /* "documentVersion" */ + 392, /* "domain" */ + 452, /* "domainRelatedObject" */ + 802, /* "dsa_with_SHA224" */ + 803, /* "dsa_with_SHA256" */ + 1152, /* "dstu28147" */ + 1154, /* "dstu28147-cfb" */ + 1153, /* "dstu28147-ofb" */ + 1155, /* "dstu28147-wrap" */ + 1157, /* "dstu34311" */ + 1159, /* "dstu4145be" */ + 1158, /* "dstu4145le" */ + 791, /* "ecdsa-with-Recommended" */ + 416, /* "ecdsa-with-SHA1" */ + 793, /* "ecdsa-with-SHA224" */ + 794, /* "ecdsa-with-SHA256" */ + 795, /* "ecdsa-with-SHA384" */ + 796, /* "ecdsa-with-SHA512" */ + 792, /* "ecdsa-with-Specified" */ + 48, /* "emailAddress" */ + 132, /* "emailProtection" */ + 885, /* "enhancedSearchGuide" */ + 389, /* "enterprises" */ + 384, /* "experimental" */ + 172, /* "extReq" */ + 56, /* "extendedCertificateAttributes" */ + 126, /* "extendedKeyUsage" */ + 372, /* "extendedStatus" */ + 867, /* "facsimileTelephoneNumber" */ + 462, /* "favouriteDrink" */ + 1126, /* "ffdhe2048" */ + 1127, /* "ffdhe3072" */ + 1128, /* "ffdhe4096" */ + 1129, /* "ffdhe6144" */ + 1130, /* "ffdhe8192" */ + 857, /* "freshestCRL" */ + 453, /* "friendlyCountry" */ + 490, /* "friendlyCountryName" */ + 156, /* "friendlyName" */ + 509, /* "generationQualifier" */ + 815, /* "gost-mac" */ + 976, /* "gost-mac-12" */ + 811, /* "gost2001" */ + 851, /* "gost2001cc" */ + 979, /* "gost2012_256" */ + 980, /* "gost2012_512" */ + 813, /* "gost89" */ + 1009, /* "gost89-cbc" */ + 814, /* "gost89-cnt" */ + 975, /* "gost89-cnt-12" */ + 1011, /* "gost89-ctr" */ + 1010, /* "gost89-ecb" */ + 812, /* "gost94" */ + 850, /* "gost94cc" */ + 1015, /* "grasshopper-cbc" */ + 1016, /* "grasshopper-cfb" */ + 1013, /* "grasshopper-ctr" */ + 1012, /* "grasshopper-ecb" */ + 1017, /* "grasshopper-mac" */ + 1014, /* "grasshopper-ofb" */ + 1156, /* "hmacWithDstu34311" */ + 797, /* "hmacWithMD5" */ + 163, /* "hmacWithSHA1" */ + 798, /* "hmacWithSHA224" */ + 799, /* "hmacWithSHA256" */ + 800, /* "hmacWithSHA384" */ + 801, /* "hmacWithSHA512" */ + 1193, /* "hmacWithSHA512-224" */ + 1194, /* "hmacWithSHA512-256" */ + 432, /* "holdInstructionCallIssuer" */ + 430, /* "holdInstructionCode" */ + 431, /* "holdInstructionNone" */ + 433, /* "holdInstructionReject" */ + 486, /* "homePostalAddress" */ + 473, /* "homeTelephoneNumber" */ + 466, /* "host" */ + 889, /* "houseIdentifier" */ + 442, /* "iA5StringSyntax" */ + 783, /* "id-DHBasedMac" */ + 824, /* "id-Gost28147-89-CryptoPro-A-ParamSet" */ + 825, /* "id-Gost28147-89-CryptoPro-B-ParamSet" */ + 826, /* "id-Gost28147-89-CryptoPro-C-ParamSet" */ + 827, /* "id-Gost28147-89-CryptoPro-D-ParamSet" */ + 819, /* "id-Gost28147-89-CryptoPro-KeyMeshing" */ + 829, /* "id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet" */ + 828, /* "id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet" */ + 830, /* "id-Gost28147-89-CryptoPro-RIC-1-ParamSet" */ + 820, /* "id-Gost28147-89-None-KeyMeshing" */ + 823, /* "id-Gost28147-89-TestParamSet" */ + 849, /* "id-Gost28147-89-cc" */ + 840, /* "id-GostR3410-2001-CryptoPro-A-ParamSet" */ + 841, /* "id-GostR3410-2001-CryptoPro-B-ParamSet" */ + 842, /* "id-GostR3410-2001-CryptoPro-C-ParamSet" */ + 843, /* "id-GostR3410-2001-CryptoPro-XchA-ParamSet" */ + 844, /* "id-GostR3410-2001-CryptoPro-XchB-ParamSet" */ + 854, /* "id-GostR3410-2001-ParamSet-cc" */ + 839, /* "id-GostR3410-2001-TestParamSet" */ + 817, /* "id-GostR3410-2001DH" */ + 832, /* "id-GostR3410-94-CryptoPro-A-ParamSet" */ + 833, /* "id-GostR3410-94-CryptoPro-B-ParamSet" */ + 834, /* "id-GostR3410-94-CryptoPro-C-ParamSet" */ + 835, /* "id-GostR3410-94-CryptoPro-D-ParamSet" */ + 836, /* "id-GostR3410-94-CryptoPro-XchA-ParamSet" */ + 837, /* "id-GostR3410-94-CryptoPro-XchB-ParamSet" */ + 838, /* "id-GostR3410-94-CryptoPro-XchC-ParamSet" */ + 831, /* "id-GostR3410-94-TestParamSet" */ + 845, /* "id-GostR3410-94-a" */ + 846, /* "id-GostR3410-94-aBis" */ + 847, /* "id-GostR3410-94-b" */ + 848, /* "id-GostR3410-94-bBis" */ + 818, /* "id-GostR3410-94DH" */ + 822, /* "id-GostR3411-94-CryptoProParamSet" */ + 821, /* "id-GostR3411-94-TestParamSet" */ + 807, /* "id-GostR3411-94-with-GostR3410-2001" */ + 853, /* "id-GostR3411-94-with-GostR3410-2001-cc" */ + 808, /* "id-GostR3411-94-with-GostR3410-94" */ + 852, /* "id-GostR3411-94-with-GostR3410-94-cc" */ + 810, /* "id-HMACGostR3411-94" */ + 782, /* "id-PasswordBasedMAC" */ + 266, /* "id-aca" */ + 355, /* "id-aca-accessIdentity" */ + 354, /* "id-aca-authenticationInfo" */ + 356, /* "id-aca-chargingIdentity" */ + 399, /* "id-aca-encAttrs" */ + 357, /* "id-aca-group" */ + 358, /* "id-aca-role" */ + 176, /* "id-ad" */ + 896, /* "id-aes128-CCM" */ + 895, /* "id-aes128-GCM" */ + 788, /* "id-aes128-wrap" */ + 897, /* "id-aes128-wrap-pad" */ + 899, /* "id-aes192-CCM" */ + 898, /* "id-aes192-GCM" */ + 789, /* "id-aes192-wrap" */ + 900, /* "id-aes192-wrap-pad" */ + 902, /* "id-aes256-CCM" */ + 901, /* "id-aes256-GCM" */ + 790, /* "id-aes256-wrap" */ + 903, /* "id-aes256-wrap-pad" */ + 262, /* "id-alg" */ + 893, /* "id-alg-PWRI-KEK" */ + 323, /* "id-alg-des40" */ + 326, /* "id-alg-dh-pop" */ + 325, /* "id-alg-dh-sig-hmac-sha1" */ + 324, /* "id-alg-noSignature" */ + 907, /* "id-camellia128-wrap" */ + 908, /* "id-camellia192-wrap" */ + 909, /* "id-camellia256-wrap" */ + 268, /* "id-cct" */ + 361, /* "id-cct-PKIData" */ + 362, /* "id-cct-PKIResponse" */ + 360, /* "id-cct-crs" */ + 81, /* "id-ce" */ + 680, /* "id-characteristic-two-basis" */ + 263, /* "id-cmc" */ + 334, /* "id-cmc-addExtensions" */ + 346, /* "id-cmc-confirmCertAcceptance" */ + 330, /* "id-cmc-dataReturn" */ + 336, /* "id-cmc-decryptedPOP" */ + 335, /* "id-cmc-encryptedPOP" */ + 339, /* "id-cmc-getCRL" */ + 338, /* "id-cmc-getCert" */ + 328, /* "id-cmc-identification" */ + 329, /* "id-cmc-identityProof" */ + 337, /* "id-cmc-lraPOPWitness" */ + 344, /* "id-cmc-popLinkRandom" */ + 345, /* "id-cmc-popLinkWitness" */ + 343, /* "id-cmc-queryPending" */ + 333, /* "id-cmc-recipientNonce" */ + 341, /* "id-cmc-regInfo" */ + 342, /* "id-cmc-responseInfo" */ + 340, /* "id-cmc-revokeRequest" */ + 332, /* "id-cmc-senderNonce" */ + 327, /* "id-cmc-statusInfo" */ + 331, /* "id-cmc-transactionId" */ + 787, /* "id-ct-asciiTextWithCRLF" */ + 1060, /* "id-ct-xml" */ + 1108, /* "id-dsa-with-sha3-224" */ + 1109, /* "id-dsa-with-sha3-256" */ + 1110, /* "id-dsa-with-sha3-384" */ + 1111, /* "id-dsa-with-sha3-512" */ + 1106, /* "id-dsa-with-sha384" */ + 1107, /* "id-dsa-with-sha512" */ + 408, /* "id-ecPublicKey" */ + 1112, /* "id-ecdsa-with-sha3-224" */ + 1113, /* "id-ecdsa-with-sha3-256" */ + 1114, /* "id-ecdsa-with-sha3-384" */ + 1115, /* "id-ecdsa-with-sha3-512" */ + 508, /* "id-hex-multipart-message" */ + 507, /* "id-hex-partial-message" */ + 1102, /* "id-hmacWithSHA3-224" */ + 1103, /* "id-hmacWithSHA3-256" */ + 1104, /* "id-hmacWithSHA3-384" */ + 1105, /* "id-hmacWithSHA3-512" */ + 260, /* "id-it" */ + 302, /* "id-it-caKeyUpdateInfo" */ + 298, /* "id-it-caProtEncCert" */ + 311, /* "id-it-confirmWaitTime" */ + 303, /* "id-it-currentCRL" */ + 300, /* "id-it-encKeyPairTypes" */ + 310, /* "id-it-implicitConfirm" */ + 308, /* "id-it-keyPairParamRep" */ + 307, /* "id-it-keyPairParamReq" */ + 312, /* "id-it-origPKIMessage" */ + 301, /* "id-it-preferredSymmAlg" */ + 309, /* "id-it-revPassphrase" */ + 299, /* "id-it-signKeyPairTypes" */ + 305, /* "id-it-subscriptionRequest" */ + 306, /* "id-it-subscriptionResponse" */ + 784, /* "id-it-suppLangTags" */ + 304, /* "id-it-unsupportedOIDs" */ + 128, /* "id-kp" */ + 280, /* "id-mod-attribute-cert" */ + 274, /* "id-mod-cmc" */ + 277, /* "id-mod-cmp" */ + 284, /* "id-mod-cmp2000" */ + 273, /* "id-mod-crmf" */ + 283, /* "id-mod-dvcs" */ + 275, /* "id-mod-kea-profile-88" */ + 276, /* "id-mod-kea-profile-93" */ + 282, /* "id-mod-ocsp" */ + 278, /* "id-mod-qualified-cert-88" */ + 279, /* "id-mod-qualified-cert-93" */ + 281, /* "id-mod-timestamp-protocol" */ + 264, /* "id-on" */ + 858, /* "id-on-permanentIdentifier" */ + 347, /* "id-on-personalData" */ + 265, /* "id-pda" */ + 352, /* "id-pda-countryOfCitizenship" */ + 353, /* "id-pda-countryOfResidence" */ + 348, /* "id-pda-dateOfBirth" */ + 351, /* "id-pda-gender" */ + 349, /* "id-pda-placeOfBirth" */ + 175, /* "id-pe" */ + 1031, /* "id-pkinit" */ + 261, /* "id-pkip" */ + 258, /* "id-pkix-mod" */ + 269, /* "id-pkix1-explicit-88" */ + 271, /* "id-pkix1-explicit-93" */ + 270, /* "id-pkix1-implicit-88" */ + 272, /* "id-pkix1-implicit-93" */ + 662, /* "id-ppl" */ + 664, /* "id-ppl-anyLanguage" */ + 667, /* "id-ppl-independent" */ + 665, /* "id-ppl-inheritAll" */ + 267, /* "id-qcs" */ + 359, /* "id-qcs-pkixQCSyntax-v1" */ + 259, /* "id-qt" */ + 164, /* "id-qt-cps" */ + 165, /* "id-qt-unotice" */ + 313, /* "id-regCtrl" */ + 316, /* "id-regCtrl-authenticator" */ + 319, /* "id-regCtrl-oldCertID" */ + 318, /* "id-regCtrl-pkiArchiveOptions" */ + 317, /* "id-regCtrl-pkiPublicationInfo" */ + 320, /* "id-regCtrl-protocolEncrKey" */ + 315, /* "id-regCtrl-regToken" */ + 314, /* "id-regInfo" */ + 322, /* "id-regInfo-certReq" */ + 321, /* "id-regInfo-utf8Pairs" */ + 1116, /* "id-rsassa-pkcs1-v1_5-with-sha3-224" */ + 1117, /* "id-rsassa-pkcs1-v1_5-with-sha3-256" */ + 1118, /* "id-rsassa-pkcs1-v1_5-with-sha3-384" */ + 1119, /* "id-rsassa-pkcs1-v1_5-with-sha3-512" */ + 973, /* "id-scrypt" */ + 512, /* "id-set" */ + 191, /* "id-smime-aa" */ + 215, /* "id-smime-aa-contentHint" */ + 218, /* "id-smime-aa-contentIdentifier" */ + 221, /* "id-smime-aa-contentReference" */ + 240, /* "id-smime-aa-dvcs-dvc" */ + 217, /* "id-smime-aa-encapContentType" */ + 222, /* "id-smime-aa-encrypKeyPref" */ + 220, /* "id-smime-aa-equivalentLabels" */ + 232, /* "id-smime-aa-ets-CertificateRefs" */ + 233, /* "id-smime-aa-ets-RevocationRefs" */ + 238, /* "id-smime-aa-ets-archiveTimeStamp" */ + 237, /* "id-smime-aa-ets-certCRLTimestamp" */ + 234, /* "id-smime-aa-ets-certValues" */ + 227, /* "id-smime-aa-ets-commitmentType" */ + 231, /* "id-smime-aa-ets-contentTimestamp" */ + 236, /* "id-smime-aa-ets-escTimeStamp" */ + 230, /* "id-smime-aa-ets-otherSigCert" */ + 235, /* "id-smime-aa-ets-revocationValues" */ + 226, /* "id-smime-aa-ets-sigPolicyId" */ + 229, /* "id-smime-aa-ets-signerAttr" */ + 228, /* "id-smime-aa-ets-signerLocation" */ + 219, /* "id-smime-aa-macValue" */ + 214, /* "id-smime-aa-mlExpandHistory" */ + 216, /* "id-smime-aa-msgSigDigest" */ + 212, /* "id-smime-aa-receiptRequest" */ + 213, /* "id-smime-aa-securityLabel" */ + 239, /* "id-smime-aa-signatureType" */ + 223, /* "id-smime-aa-signingCertificate" */ + 1086, /* "id-smime-aa-signingCertificateV2" */ + 224, /* "id-smime-aa-smimeEncryptCerts" */ + 225, /* "id-smime-aa-timeStampToken" */ + 192, /* "id-smime-alg" */ + 243, /* "id-smime-alg-3DESwrap" */ + 246, /* "id-smime-alg-CMS3DESwrap" */ + 247, /* "id-smime-alg-CMSRC2wrap" */ + 245, /* "id-smime-alg-ESDH" */ + 241, /* "id-smime-alg-ESDHwith3DES" */ + 242, /* "id-smime-alg-ESDHwithRC2" */ + 244, /* "id-smime-alg-RC2wrap" */ + 193, /* "id-smime-cd" */ + 248, /* "id-smime-cd-ldap" */ + 190, /* "id-smime-ct" */ + 210, /* "id-smime-ct-DVCSRequestData" */ + 211, /* "id-smime-ct-DVCSResponseData" */ + 208, /* "id-smime-ct-TDTInfo" */ + 207, /* "id-smime-ct-TSTInfo" */ + 205, /* "id-smime-ct-authData" */ + 1059, /* "id-smime-ct-authEnvelopedData" */ + 786, /* "id-smime-ct-compressedData" */ + 1058, /* "id-smime-ct-contentCollection" */ + 209, /* "id-smime-ct-contentInfo" */ + 206, /* "id-smime-ct-publishCert" */ + 204, /* "id-smime-ct-receipt" */ + 195, /* "id-smime-cti" */ + 255, /* "id-smime-cti-ets-proofOfApproval" */ + 256, /* "id-smime-cti-ets-proofOfCreation" */ + 253, /* "id-smime-cti-ets-proofOfDelivery" */ + 251, /* "id-smime-cti-ets-proofOfOrigin" */ + 252, /* "id-smime-cti-ets-proofOfReceipt" */ + 254, /* "id-smime-cti-ets-proofOfSender" */ + 189, /* "id-smime-mod" */ + 196, /* "id-smime-mod-cms" */ + 197, /* "id-smime-mod-ess" */ + 202, /* "id-smime-mod-ets-eSigPolicy-88" */ + 203, /* "id-smime-mod-ets-eSigPolicy-97" */ + 200, /* "id-smime-mod-ets-eSignature-88" */ + 201, /* "id-smime-mod-ets-eSignature-97" */ + 199, /* "id-smime-mod-msg-v3" */ + 198, /* "id-smime-mod-oid" */ + 194, /* "id-smime-spq" */ + 250, /* "id-smime-spq-ets-sqt-unotice" */ + 249, /* "id-smime-spq-ets-sqt-uri" */ + 974, /* "id-tc26" */ + 991, /* "id-tc26-agreement" */ + 992, /* "id-tc26-agreement-gost-3410-2012-256" */ + 993, /* "id-tc26-agreement-gost-3410-2012-512" */ + 977, /* "id-tc26-algorithms" */ + 990, /* "id-tc26-cipher" */ + 1001, /* "id-tc26-cipher-constants" */ + 1176, /* "id-tc26-cipher-gostr3412-2015-kuznyechik" */ + 1177, /* "id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm" */ + 1178, /* "id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm-omac" */ + 1173, /* "id-tc26-cipher-gostr3412-2015-magma" */ + 1174, /* "id-tc26-cipher-gostr3412-2015-magma-ctracpkm" */ + 1175, /* "id-tc26-cipher-gostr3412-2015-magma-ctracpkm-omac" */ + 994, /* "id-tc26-constants" */ + 981, /* "id-tc26-digest" */ + 1000, /* "id-tc26-digest-constants" */ + 1002, /* "id-tc26-gost-28147-constants" */ + 1003, /* "id-tc26-gost-28147-param-Z" */ + 1147, /* "id-tc26-gost-3410-2012-256-constants" */ + 1148, /* "id-tc26-gost-3410-2012-256-paramSetA" */ + 1184, /* "id-tc26-gost-3410-2012-256-paramSetB" */ + 1185, /* "id-tc26-gost-3410-2012-256-paramSetC" */ + 1186, /* "id-tc26-gost-3410-2012-256-paramSetD" */ + 996, /* "id-tc26-gost-3410-2012-512-constants" */ + 998, /* "id-tc26-gost-3410-2012-512-paramSetA" */ + 999, /* "id-tc26-gost-3410-2012-512-paramSetB" */ + 1149, /* "id-tc26-gost-3410-2012-512-paramSetC" */ + 997, /* "id-tc26-gost-3410-2012-512-paramSetTest" */ + 988, /* "id-tc26-hmac-gost-3411-2012-256" */ + 989, /* "id-tc26-hmac-gost-3411-2012-512" */ + 987, /* "id-tc26-mac" */ + 978, /* "id-tc26-sign" */ + 995, /* "id-tc26-sign-constants" */ + 984, /* "id-tc26-signwithdigest" */ + 985, /* "id-tc26-signwithdigest-gost3410-2012-256" */ + 986, /* "id-tc26-signwithdigest-gost3410-2012-512" */ + 1179, /* "id-tc26-wrap" */ + 1182, /* "id-tc26-wrap-gostr3412-2015-kuznyechik" */ + 1183, /* "id-tc26-wrap-gostr3412-2015-kuznyechik-kexp15" */ + 1180, /* "id-tc26-wrap-gostr3412-2015-magma" */ + 1181, /* "id-tc26-wrap-gostr3412-2015-magma-kexp15" */ + 676, /* "identified-organization" */ + 1170, /* "ieee" */ + 1171, /* "ieee-siswg" */ + 461, /* "info" */ + 748, /* "inhibitAnyPolicy" */ + 101, /* "initials" */ + 647, /* "international-organizations" */ + 869, /* "internationaliSDNNumber" */ + 142, /* "invalidityDate" */ + 294, /* "ipsecEndSystem" */ + 1022, /* "ipsecIKE" */ + 295, /* "ipsecTunnel" */ + 296, /* "ipsecUser" */ + 86, /* "issuerAltName" */ + 1008, /* "issuerSignTool" */ + 770, /* "issuingDistributionPoint" */ + 492, /* "janetMailbox" */ + 957, /* "jurisdictionC" */ + 955, /* "jurisdictionL" */ + 956, /* "jurisdictionST" */ + 150, /* "keyBag" */ + 83, /* "keyUsage" */ + 477, /* "lastModifiedBy" */ + 476, /* "lastModifiedTime" */ + 157, /* "localKeyID" */ + 480, /* "mXRecord" */ + 1190, /* "magma-cbc" */ + 1191, /* "magma-cfb" */ + 1188, /* "magma-ctr" */ + 1187, /* "magma-ecb" */ + 1192, /* "magma-mac" */ + 1189, /* "magma-ofb" */ + 460, /* "mail" */ + 493, /* "mailPreferenceOption" */ + 467, /* "manager" */ + 982, /* "md_gost12_256" */ + 983, /* "md_gost12_512" */ + 809, /* "md_gost94" */ + 875, /* "member" */ + 182, /* "member-body" */ + 51, /* "messageDigest" */ + 383, /* "mgmt" */ + 504, /* "mime-mhs" */ + 506, /* "mime-mhs-bodies" */ + 505, /* "mime-mhs-headings" */ + 488, /* "mobileTelephoneNumber" */ + 136, /* "msCTLSign" */ + 135, /* "msCodeCom" */ + 134, /* "msCodeInd" */ + 138, /* "msEFS" */ + 171, /* "msExtReq" */ + 137, /* "msSGC" */ + 648, /* "msSmartcardLogin" */ + 649, /* "msUPN" */ + 1091, /* "n3" */ + 481, /* "nSRecord" */ + 173, /* "name" */ + 666, /* "nameConstraints" */ + 369, /* "noCheck" */ + 403, /* "noRevAvail" */ + 72, /* "nsBaseUrl" */ + 76, /* "nsCaPolicyUrl" */ + 74, /* "nsCaRevocationUrl" */ + 58, /* "nsCertExt" */ + 79, /* "nsCertSequence" */ + 71, /* "nsCertType" */ + 78, /* "nsComment" */ + 59, /* "nsDataType" */ + 75, /* "nsRenewalUrl" */ + 73, /* "nsRevocationUrl" */ + 139, /* "nsSGC" */ + 77, /* "nsSslServerName" */ + 681, /* "onBasis" */ + 1089, /* "organizationIdentifier" */ + 491, /* "organizationalStatus" */ + 1141, /* "oscca" */ + 475, /* "otherMailbox" */ + 876, /* "owner" */ + 489, /* "pagerTelephoneNumber" */ + 374, /* "path" */ + 112, /* "pbeWithMD5AndCast5CBC" */ + 499, /* "personalSignature" */ + 487, /* "personalTitle" */ + 464, /* "photo" */ + 863, /* "physicalDeliveryOfficeName" */ + 437, /* "pilot" */ + 439, /* "pilotAttributeSyntax" */ + 438, /* "pilotAttributeType" */ + 479, /* "pilotAttributeType27" */ + 456, /* "pilotDSA" */ + 441, /* "pilotGroups" */ + 444, /* "pilotObject" */ + 440, /* "pilotObjectClass" */ + 455, /* "pilotOrganization" */ + 445, /* "pilotPerson" */ + 1032, /* "pkInitClientAuth" */ + 1033, /* "pkInitKDC" */ + 2, /* "pkcs" */ + 186, /* "pkcs1" */ + 27, /* "pkcs3" */ + 187, /* "pkcs5" */ + 20, /* "pkcs7" */ + 21, /* "pkcs7-data" */ + 25, /* "pkcs7-digestData" */ + 26, /* "pkcs7-encryptedData" */ + 23, /* "pkcs7-envelopedData" */ + 24, /* "pkcs7-signedAndEnvelopedData" */ + 22, /* "pkcs7-signedData" */ + 151, /* "pkcs8ShroudedKeyBag" */ + 47, /* "pkcs9" */ + 401, /* "policyConstraints" */ + 747, /* "policyMappings" */ + 862, /* "postOfficeBox" */ + 861, /* "postalAddress" */ + 661, /* "postalCode" */ + 683, /* "ppBasis" */ + 872, /* "preferredDeliveryMethod" */ + 873, /* "presentationAddress" */ + 816, /* "prf-gostr3411-94" */ + 406, /* "prime-field" */ + 409, /* "prime192v1" */ + 410, /* "prime192v2" */ + 411, /* "prime192v3" */ + 412, /* "prime239v1" */ + 413, /* "prime239v2" */ + 414, /* "prime239v3" */ + 415, /* "prime256v1" */ + 385, /* "private" */ + 84, /* "privateKeyUsagePeriod" */ + 886, /* "protocolInformation" */ + 663, /* "proxyCertInfo" */ + 510, /* "pseudonym" */ + 435, /* "pss" */ + 286, /* "qcStatements" */ + 457, /* "qualityLabelledData" */ + 450, /* "rFC822localPart" */ + 870, /* "registeredAddress" */ + 400, /* "role" */ + 877, /* "roleOccupant" */ + 448, /* "room" */ + 463, /* "roomNumber" */ + 6, /* "rsaEncryption" */ + 644, /* "rsaOAEPEncryptionSET" */ + 377, /* "rsaSignature" */ + 1, /* "rsadsi" */ + 482, /* "sOARecord" */ + 155, /* "safeContentsBag" */ + 291, /* "sbgp-autonomousSysNum" */ + 290, /* "sbgp-ipAddrBlock" */ + 292, /* "sbgp-routerIdentifier" */ + 159, /* "sdsiCertificate" */ + 859, /* "searchGuide" */ + 704, /* "secp112r1" */ + 705, /* "secp112r2" */ + 706, /* "secp128r1" */ + 707, /* "secp128r2" */ + 708, /* "secp160k1" */ + 709, /* "secp160r1" */ + 710, /* "secp160r2" */ + 711, /* "secp192k1" */ + 712, /* "secp224k1" */ + 713, /* "secp224r1" */ + 714, /* "secp256k1" */ + 715, /* "secp384r1" */ + 716, /* "secp521r1" */ + 154, /* "secretBag" */ + 474, /* "secretary" */ + 717, /* "sect113r1" */ + 718, /* "sect113r2" */ + 719, /* "sect131r1" */ + 720, /* "sect131r2" */ + 721, /* "sect163k1" */ + 722, /* "sect163r1" */ + 723, /* "sect163r2" */ + 724, /* "sect193r1" */ + 725, /* "sect193r2" */ + 726, /* "sect233k1" */ + 727, /* "sect233r1" */ + 728, /* "sect239k1" */ + 729, /* "sect283k1" */ + 730, /* "sect283r1" */ + 731, /* "sect409k1" */ + 732, /* "sect409r1" */ + 733, /* "sect571k1" */ + 734, /* "sect571r1" */ + 1025, /* "secureShellClient" */ + 1026, /* "secureShellServer" */ + 386, /* "security" */ + 878, /* "seeAlso" */ + 394, /* "selected-attribute-types" */ + 1029, /* "sendOwner" */ + 1030, /* "sendProxiedOwner" */ + 1028, /* "sendProxiedRouter" */ + 1027, /* "sendRouter" */ + 105, /* "serialNumber" */ + 129, /* "serverAuth" */ + 371, /* "serviceLocator" */ + 625, /* "set-addPolicy" */ + 515, /* "set-attr" */ + 518, /* "set-brand" */ + 638, /* "set-brand-AmericanExpress" */ + 637, /* "set-brand-Diners" */ + 636, /* "set-brand-IATA-ATA" */ + 639, /* "set-brand-JCB" */ + 641, /* "set-brand-MasterCard" */ + 642, /* "set-brand-Novus" */ + 640, /* "set-brand-Visa" */ + 517, /* "set-certExt" */ + 513, /* "set-ctype" */ + 514, /* "set-msgExt" */ + 516, /* "set-policy" */ + 607, /* "set-policy-root" */ + 624, /* "set-rootKeyThumb" */ + 620, /* "setAttr-Cert" */ + 631, /* "setAttr-GenCryptgrm" */ + 623, /* "setAttr-IssCap" */ + 628, /* "setAttr-IssCap-CVM" */ + 630, /* "setAttr-IssCap-Sig" */ + 629, /* "setAttr-IssCap-T2" */ + 621, /* "setAttr-PGWYcap" */ + 635, /* "setAttr-SecDevSig" */ + 632, /* "setAttr-T2Enc" */ + 633, /* "setAttr-T2cleartxt" */ + 634, /* "setAttr-TokICCsig" */ + 627, /* "setAttr-Token-B0Prime" */ + 626, /* "setAttr-Token-EMV" */ + 622, /* "setAttr-TokenType" */ + 619, /* "setCext-IssuerCapabilities" */ + 615, /* "setCext-PGWYcapabilities" */ + 616, /* "setCext-TokenIdentifier" */ + 618, /* "setCext-TokenType" */ + 617, /* "setCext-Track2Data" */ + 611, /* "setCext-cCertRequired" */ + 609, /* "setCext-certType" */ + 608, /* "setCext-hashedRoot" */ + 610, /* "setCext-merchData" */ + 613, /* "setCext-setExt" */ + 614, /* "setCext-setQualf" */ + 612, /* "setCext-tunneling" */ + 540, /* "setct-AcqCardCodeMsg" */ + 576, /* "setct-AcqCardCodeMsgTBE" */ + 570, /* "setct-AuthReqTBE" */ + 534, /* "setct-AuthReqTBS" */ + 527, /* "setct-AuthResBaggage" */ + 571, /* "setct-AuthResTBE" */ + 572, /* "setct-AuthResTBEX" */ + 535, /* "setct-AuthResTBS" */ + 536, /* "setct-AuthResTBSX" */ + 528, /* "setct-AuthRevReqBaggage" */ + 577, /* "setct-AuthRevReqTBE" */ + 541, /* "setct-AuthRevReqTBS" */ + 529, /* "setct-AuthRevResBaggage" */ + 542, /* "setct-AuthRevResData" */ + 578, /* "setct-AuthRevResTBE" */ + 579, /* "setct-AuthRevResTBEB" */ + 543, /* "setct-AuthRevResTBS" */ + 573, /* "setct-AuthTokenTBE" */ + 537, /* "setct-AuthTokenTBS" */ + 600, /* "setct-BCIDistributionTBS" */ + 558, /* "setct-BatchAdminReqData" */ + 592, /* "setct-BatchAdminReqTBE" */ + 559, /* "setct-BatchAdminResData" */ + 593, /* "setct-BatchAdminResTBE" */ + 599, /* "setct-CRLNotificationResTBS" */ + 598, /* "setct-CRLNotificationTBS" */ + 580, /* "setct-CapReqTBE" */ + 581, /* "setct-CapReqTBEX" */ + 544, /* "setct-CapReqTBS" */ + 545, /* "setct-CapReqTBSX" */ + 546, /* "setct-CapResData" */ + 582, /* "setct-CapResTBE" */ + 583, /* "setct-CapRevReqTBE" */ + 584, /* "setct-CapRevReqTBEX" */ + 547, /* "setct-CapRevReqTBS" */ + 548, /* "setct-CapRevReqTBSX" */ + 549, /* "setct-CapRevResData" */ + 585, /* "setct-CapRevResTBE" */ + 538, /* "setct-CapTokenData" */ + 530, /* "setct-CapTokenSeq" */ + 574, /* "setct-CapTokenTBE" */ + 575, /* "setct-CapTokenTBEX" */ + 539, /* "setct-CapTokenTBS" */ + 560, /* "setct-CardCInitResTBS" */ + 566, /* "setct-CertInqReqTBS" */ + 563, /* "setct-CertReqData" */ + 595, /* "setct-CertReqTBE" */ + 596, /* "setct-CertReqTBEX" */ + 564, /* "setct-CertReqTBS" */ + 565, /* "setct-CertResData" */ + 597, /* "setct-CertResTBE" */ + 586, /* "setct-CredReqTBE" */ + 587, /* "setct-CredReqTBEX" */ + 550, /* "setct-CredReqTBS" */ + 551, /* "setct-CredReqTBSX" */ + 552, /* "setct-CredResData" */ + 588, /* "setct-CredResTBE" */ + 589, /* "setct-CredRevReqTBE" */ + 590, /* "setct-CredRevReqTBEX" */ + 553, /* "setct-CredRevReqTBS" */ + 554, /* "setct-CredRevReqTBSX" */ + 555, /* "setct-CredRevResData" */ + 591, /* "setct-CredRevResTBE" */ + 567, /* "setct-ErrorTBS" */ + 526, /* "setct-HODInput" */ + 561, /* "setct-MeAqCInitResTBS" */ + 522, /* "setct-OIData" */ + 519, /* "setct-PANData" */ + 521, /* "setct-PANOnly" */ + 520, /* "setct-PANToken" */ + 556, /* "setct-PCertReqData" */ + 557, /* "setct-PCertResTBS" */ + 523, /* "setct-PI" */ + 532, /* "setct-PI-TBS" */ + 524, /* "setct-PIData" */ + 525, /* "setct-PIDataUnsigned" */ + 568, /* "setct-PIDualSignedTBE" */ + 569, /* "setct-PIUnsignedTBE" */ + 531, /* "setct-PInitResData" */ + 533, /* "setct-PResData" */ + 594, /* "setct-RegFormReqTBE" */ + 562, /* "setct-RegFormResTBS" */ + 606, /* "setext-cv" */ + 601, /* "setext-genCrypt" */ + 602, /* "setext-miAuth" */ + 604, /* "setext-pinAny" */ + 603, /* "setext-pinSecure" */ + 605, /* "setext-track2" */ + 52, /* "signingTime" */ + 454, /* "simpleSecurityObject" */ + 496, /* "singleLevelQuality" */ + 1142, /* "sm-scheme" */ + 387, /* "snmpv2" */ + 660, /* "street" */ + 85, /* "subjectAltName" */ + 769, /* "subjectDirectoryAttributes" */ + 398, /* "subjectInfoAccess" */ + 82, /* "subjectKeyIdentifier" */ + 1007, /* "subjectSignTool" */ + 498, /* "subtreeMaximumQuality" */ + 497, /* "subtreeMinimumQuality" */ + 890, /* "supportedAlgorithms" */ + 874, /* "supportedApplicationContext" */ + 402, /* "targetInformation" */ + 864, /* "telephoneNumber" */ + 866, /* "teletexTerminalIdentifier" */ + 865, /* "telexNumber" */ + 459, /* "textEncodedORAddress" */ + 293, /* "textNotice" */ + 133, /* "timeStamping" */ + 106, /* "title" */ + 1020, /* "tlsfeature" */ + 682, /* "tpBasis" */ + 375, /* "trustRoot" */ + 1151, /* "ua-pki" */ + 1160, /* "uacurve0" */ + 1161, /* "uacurve1" */ + 1162, /* "uacurve2" */ + 1163, /* "uacurve3" */ + 1164, /* "uacurve4" */ + 1165, /* "uacurve5" */ + 1166, /* "uacurve6" */ + 1167, /* "uacurve7" */ + 1168, /* "uacurve8" */ + 1169, /* "uacurve9" */ + 436, /* "ucl" */ + 102, /* "uid" */ + 888, /* "uniqueMember" */ + 55, /* "unstructuredAddress" */ + 49, /* "unstructuredName" */ + 880, /* "userCertificate" */ + 465, /* "userClass" */ + 879, /* "userPassword" */ + 373, /* "valid" */ + 678, /* "wap" */ + 679, /* "wap-wsg" */ + 735, /* "wap-wsg-idm-ecid-wtls1" */ + 743, /* "wap-wsg-idm-ecid-wtls10" */ + 744, /* "wap-wsg-idm-ecid-wtls11" */ + 745, /* "wap-wsg-idm-ecid-wtls12" */ + 736, /* "wap-wsg-idm-ecid-wtls3" */ + 737, /* "wap-wsg-idm-ecid-wtls4" */ + 738, /* "wap-wsg-idm-ecid-wtls5" */ + 739, /* "wap-wsg-idm-ecid-wtls6" */ + 740, /* "wap-wsg-idm-ecid-wtls7" */ + 741, /* "wap-wsg-idm-ecid-wtls8" */ + 742, /* "wap-wsg-idm-ecid-wtls9" */ + 804, /* "whirlpool" */ + 868, /* "x121Address" */ + 503, /* "x500UniqueIdentifier" */ + 158, /* "x509Certificate" */ + 160, /* "x509Crl" */ + 1093, /* "x509ExtAdmission" */ +}; + +#define NUM_LN 1186 +static const unsigned int ln_objs[NUM_LN] = { + 363, /* "AD Time Stamping" */ + 405, /* "ANSI X9.62" */ + 368, /* "Acceptable OCSP Responses" */ + 910, /* "Any Extended Key Usage" */ + 664, /* "Any language" */ + 177, /* "Authority Information Access" */ + 365, /* "Basic OCSP Response" */ + 285, /* "Biometric Info" */ + 179, /* "CA Issuers" */ + 785, /* "CA Repository" */ + 1131, /* "CMC Certificate Authority" */ + 1132, /* "CMC Registration Authority" */ + 954, /* "CT Certificate SCTs" */ + 952, /* "CT Precertificate Poison" */ + 951, /* "CT Precertificate SCTs" */ + 953, /* "CT Precertificate Signer" */ + 131, /* "Code Signing" */ + 1024, /* "Ctrl/Provision WAP Termination" */ + 1023, /* "Ctrl/provision WAP Access" */ + 1159, /* "DSTU 4145-2002 big endian" */ + 1158, /* "DSTU 4145-2002 little endian" */ + 1152, /* "DSTU Gost 28147-2009" */ + 1154, /* "DSTU Gost 28147-2009 CFB mode" */ + 1153, /* "DSTU Gost 28147-2009 OFB mode" */ + 1155, /* "DSTU Gost 28147-2009 key wrap" */ + 1157, /* "DSTU Gost 34311-95" */ + 1160, /* "DSTU curve 0" */ + 1161, /* "DSTU curve 1" */ + 1162, /* "DSTU curve 2" */ + 1163, /* "DSTU curve 3" */ + 1164, /* "DSTU curve 4" */ + 1165, /* "DSTU curve 5" */ + 1166, /* "DSTU curve 6" */ + 1167, /* "DSTU curve 7" */ + 1168, /* "DSTU curve 8" */ + 1169, /* "DSTU curve 9" */ + 783, /* "Diffie-Hellman based MAC" */ + 382, /* "Directory" */ + 392, /* "Domain" */ + 132, /* "E-mail Protection" */ + 1087, /* "ED25519" */ + 1088, /* "ED448" */ + 389, /* "Enterprises" */ + 384, /* "Experimental" */ + 372, /* "Extended OCSP Status" */ + 172, /* "Extension Request" */ + 813, /* "GOST 28147-89" */ + 849, /* "GOST 28147-89 Cryptocom ParamSet" */ + 815, /* "GOST 28147-89 MAC" */ + 1003, /* "GOST 28147-89 TC26 parameter set" */ + 851, /* "GOST 34.10-2001 Cryptocom" */ + 850, /* "GOST 34.10-94 Cryptocom" */ + 811, /* "GOST R 34.10-2001" */ + 817, /* "GOST R 34.10-2001 DH" */ + 1148, /* "GOST R 34.10-2012 (256 bit) ParamSet A" */ + 1184, /* "GOST R 34.10-2012 (256 bit) ParamSet B" */ + 1185, /* "GOST R 34.10-2012 (256 bit) ParamSet C" */ + 1186, /* "GOST R 34.10-2012 (256 bit) ParamSet D" */ + 998, /* "GOST R 34.10-2012 (512 bit) ParamSet A" */ + 999, /* "GOST R 34.10-2012 (512 bit) ParamSet B" */ + 1149, /* "GOST R 34.10-2012 (512 bit) ParamSet C" */ + 997, /* "GOST R 34.10-2012 (512 bit) testing parameter set" */ + 979, /* "GOST R 34.10-2012 with 256 bit modulus" */ + 980, /* "GOST R 34.10-2012 with 512 bit modulus" */ + 985, /* "GOST R 34.10-2012 with GOST R 34.11-2012 (256 bit)" */ + 986, /* "GOST R 34.10-2012 with GOST R 34.11-2012 (512 bit)" */ + 812, /* "GOST R 34.10-94" */ + 818, /* "GOST R 34.10-94 DH" */ + 982, /* "GOST R 34.11-2012 with 256 bit hash" */ + 983, /* "GOST R 34.11-2012 with 512 bit hash" */ + 809, /* "GOST R 34.11-94" */ + 816, /* "GOST R 34.11-94 PRF" */ + 807, /* "GOST R 34.11-94 with GOST R 34.10-2001" */ + 853, /* "GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom" */ + 808, /* "GOST R 34.11-94 with GOST R 34.10-94" */ + 852, /* "GOST R 34.11-94 with GOST R 34.10-94 Cryptocom" */ + 854, /* "GOST R 3410-2001 Parameter Set Cryptocom" */ + 1156, /* "HMAC DSTU Gost 34311-95" */ + 988, /* "HMAC GOST 34.11-2012 256 bit" */ + 989, /* "HMAC GOST 34.11-2012 512 bit" */ + 810, /* "HMAC GOST 34.11-94" */ + 432, /* "Hold Instruction Call Issuer" */ + 430, /* "Hold Instruction Code" */ + 431, /* "Hold Instruction None" */ + 433, /* "Hold Instruction Reject" */ + 634, /* "ICC or token signature" */ + 1171, /* "IEEE Security in Storage Working Group" */ + 1004, /* "INN" */ + 294, /* "IPSec End System" */ + 295, /* "IPSec Tunnel" */ + 296, /* "IPSec User" */ + 1140, /* "ISO CN Member Body" */ + 182, /* "ISO Member Body" */ + 183, /* "ISO US Member Body" */ + 1150, /* "ISO-UA" */ + 667, /* "Independent" */ + 665, /* "Inherit all" */ + 647, /* "International Organizations" */ + 142, /* "Invalidity Date" */ + 504, /* "MIME MHS" */ + 388, /* "Mail" */ + 383, /* "Management" */ + 417, /* "Microsoft CSP Name" */ + 135, /* "Microsoft Commercial Code Signing" */ + 138, /* "Microsoft Encrypted File System" */ + 171, /* "Microsoft Extension Request" */ + 134, /* "Microsoft Individual Code Signing" */ + 856, /* "Microsoft Local Key set" */ + 137, /* "Microsoft Server Gated Crypto" */ + 648, /* "Microsoft Smartcardlogin" */ + 136, /* "Microsoft Trust List Signing" */ + 649, /* "Microsoft Universal Principal Name" */ + 393, /* "NULL" */ + 404, /* "NULL" */ + 72, /* "Netscape Base Url" */ + 76, /* "Netscape CA Policy Url" */ + 74, /* "Netscape CA Revocation Url" */ + 71, /* "Netscape Cert Type" */ + 58, /* "Netscape Certificate Extension" */ + 79, /* "Netscape Certificate Sequence" */ + 78, /* "Netscape Comment" */ + 57, /* "Netscape Communications Corp." */ + 59, /* "Netscape Data Type" */ + 75, /* "Netscape Renewal Url" */ + 73, /* "Netscape Revocation Url" */ + 77, /* "Netscape SSL Server Name" */ + 139, /* "Netscape Server Gated Crypto" */ + 178, /* "OCSP" */ + 370, /* "OCSP Archive Cutoff" */ + 367, /* "OCSP CRL ID" */ + 369, /* "OCSP No Check" */ + 366, /* "OCSP Nonce" */ + 371, /* "OCSP Service Locator" */ + 180, /* "OCSP Signing" */ + 1005, /* "OGRN" */ + 161, /* "PBES2" */ + 69, /* "PBKDF2" */ + 162, /* "PBMAC1" */ + 1032, /* "PKINIT Client Auth" */ + 127, /* "PKIX" */ + 858, /* "Permanent Identifier" */ + 164, /* "Policy Qualifier CPS" */ + 165, /* "Policy Qualifier User Notice" */ + 385, /* "Private" */ + 1093, /* "Professional Information or basis for Admission" */ + 663, /* "Proxy Certificate Information" */ + 1, /* "RSA Data Security, Inc." */ + 2, /* "RSA Data Security, Inc. PKCS" */ + 1116, /* "RSA-SHA3-224" */ + 1117, /* "RSA-SHA3-256" */ + 1118, /* "RSA-SHA3-384" */ + 1119, /* "RSA-SHA3-512" */ + 188, /* "S/MIME" */ + 167, /* "S/MIME Capabilities" */ + 1006, /* "SNILS" */ + 387, /* "SNMPv2" */ + 1025, /* "SSH Client" */ + 1026, /* "SSH Server" */ + 512, /* "Secure Electronic Transactions" */ + 386, /* "Security" */ + 394, /* "Selected Attribute Types" */ + 1029, /* "Send Owner" */ + 1030, /* "Send Proxied Owner" */ + 1028, /* "Send Proxied Router" */ + 1027, /* "Send Router" */ + 1033, /* "Signing KDC Response" */ + 1008, /* "Signing Tool of Issuer" */ + 1007, /* "Signing Tool of Subject" */ + 143, /* "Strong Extranet ID" */ + 398, /* "Subject Information Access" */ + 1020, /* "TLS Feature" */ + 130, /* "TLS Web Client Authentication" */ + 129, /* "TLS Web Server Authentication" */ + 133, /* "Time Stamping" */ + 375, /* "Trust Root" */ + 1034, /* "X25519" */ + 1035, /* "X448" */ + 12, /* "X509" */ + 402, /* "X509v3 AC Targeting" */ + 746, /* "X509v3 Any Policy" */ + 90, /* "X509v3 Authority Key Identifier" */ + 87, /* "X509v3 Basic Constraints" */ + 103, /* "X509v3 CRL Distribution Points" */ + 88, /* "X509v3 CRL Number" */ + 141, /* "X509v3 CRL Reason Code" */ + 771, /* "X509v3 Certificate Issuer" */ + 89, /* "X509v3 Certificate Policies" */ + 140, /* "X509v3 Delta CRL Indicator" */ + 126, /* "X509v3 Extended Key Usage" */ + 857, /* "X509v3 Freshest CRL" */ + 748, /* "X509v3 Inhibit Any Policy" */ + 86, /* "X509v3 Issuer Alternative Name" */ + 770, /* "X509v3 Issuing Distribution Point" */ + 83, /* "X509v3 Key Usage" */ + 666, /* "X509v3 Name Constraints" */ + 403, /* "X509v3 No Revocation Available" */ + 401, /* "X509v3 Policy Constraints" */ + 747, /* "X509v3 Policy Mappings" */ + 84, /* "X509v3 Private Key Usage Period" */ + 85, /* "X509v3 Subject Alternative Name" */ + 769, /* "X509v3 Subject Directory Attributes" */ + 82, /* "X509v3 Subject Key Identifier" */ + 920, /* "X9.42 DH" */ + 184, /* "X9.57" */ + 185, /* "X9.57 CM ?" */ + 478, /* "aRecord" */ + 289, /* "aaControls" */ + 287, /* "ac-auditEntity" */ + 397, /* "ac-proxying" */ + 288, /* "ac-targeting" */ + 446, /* "account" */ + 364, /* "ad dvcs" */ + 606, /* "additional verification" */ + 419, /* "aes-128-cbc" */ + 916, /* "aes-128-cbc-hmac-sha1" */ + 948, /* "aes-128-cbc-hmac-sha256" */ + 896, /* "aes-128-ccm" */ + 421, /* "aes-128-cfb" */ + 650, /* "aes-128-cfb1" */ + 653, /* "aes-128-cfb8" */ + 904, /* "aes-128-ctr" */ + 418, /* "aes-128-ecb" */ + 895, /* "aes-128-gcm" */ + 958, /* "aes-128-ocb" */ + 420, /* "aes-128-ofb" */ + 913, /* "aes-128-xts" */ + 423, /* "aes-192-cbc" */ + 917, /* "aes-192-cbc-hmac-sha1" */ + 949, /* "aes-192-cbc-hmac-sha256" */ + 899, /* "aes-192-ccm" */ + 425, /* "aes-192-cfb" */ + 651, /* "aes-192-cfb1" */ + 654, /* "aes-192-cfb8" */ + 905, /* "aes-192-ctr" */ + 422, /* "aes-192-ecb" */ + 898, /* "aes-192-gcm" */ + 959, /* "aes-192-ocb" */ + 424, /* "aes-192-ofb" */ + 427, /* "aes-256-cbc" */ + 918, /* "aes-256-cbc-hmac-sha1" */ + 950, /* "aes-256-cbc-hmac-sha256" */ + 902, /* "aes-256-ccm" */ + 429, /* "aes-256-cfb" */ + 652, /* "aes-256-cfb1" */ + 655, /* "aes-256-cfb8" */ + 906, /* "aes-256-ctr" */ + 426, /* "aes-256-ecb" */ + 901, /* "aes-256-gcm" */ + 960, /* "aes-256-ocb" */ + 428, /* "aes-256-ofb" */ + 914, /* "aes-256-xts" */ + 376, /* "algorithm" */ + 1066, /* "aria-128-cbc" */ + 1120, /* "aria-128-ccm" */ + 1067, /* "aria-128-cfb" */ + 1080, /* "aria-128-cfb1" */ + 1083, /* "aria-128-cfb8" */ + 1069, /* "aria-128-ctr" */ + 1065, /* "aria-128-ecb" */ + 1123, /* "aria-128-gcm" */ + 1068, /* "aria-128-ofb" */ + 1071, /* "aria-192-cbc" */ + 1121, /* "aria-192-ccm" */ + 1072, /* "aria-192-cfb" */ + 1081, /* "aria-192-cfb1" */ + 1084, /* "aria-192-cfb8" */ + 1074, /* "aria-192-ctr" */ + 1070, /* "aria-192-ecb" */ + 1124, /* "aria-192-gcm" */ + 1073, /* "aria-192-ofb" */ + 1076, /* "aria-256-cbc" */ + 1122, /* "aria-256-ccm" */ + 1077, /* "aria-256-cfb" */ + 1082, /* "aria-256-cfb1" */ + 1085, /* "aria-256-cfb8" */ + 1079, /* "aria-256-ctr" */ + 1075, /* "aria-256-ecb" */ + 1125, /* "aria-256-gcm" */ + 1078, /* "aria-256-ofb" */ + 484, /* "associatedDomain" */ + 485, /* "associatedName" */ + 501, /* "audio" */ + 1064, /* "auth-any" */ + 1049, /* "auth-dss" */ + 1047, /* "auth-ecdsa" */ + 1050, /* "auth-gost01" */ + 1051, /* "auth-gost12" */ + 1053, /* "auth-null" */ + 1048, /* "auth-psk" */ + 1046, /* "auth-rsa" */ + 1052, /* "auth-srp" */ + 882, /* "authorityRevocationList" */ + 91, /* "bf-cbc" */ + 93, /* "bf-cfb" */ + 92, /* "bf-ecb" */ + 94, /* "bf-ofb" */ + 1056, /* "blake2b512" */ + 1057, /* "blake2s256" */ + 921, /* "brainpoolP160r1" */ + 922, /* "brainpoolP160t1" */ + 923, /* "brainpoolP192r1" */ + 924, /* "brainpoolP192t1" */ + 925, /* "brainpoolP224r1" */ + 926, /* "brainpoolP224t1" */ + 927, /* "brainpoolP256r1" */ + 928, /* "brainpoolP256t1" */ + 929, /* "brainpoolP320r1" */ + 930, /* "brainpoolP320t1" */ + 931, /* "brainpoolP384r1" */ + 932, /* "brainpoolP384t1" */ + 933, /* "brainpoolP512r1" */ + 934, /* "brainpoolP512t1" */ + 494, /* "buildingName" */ + 860, /* "businessCategory" */ + 691, /* "c2onb191v4" */ + 692, /* "c2onb191v5" */ + 697, /* "c2onb239v4" */ + 698, /* "c2onb239v5" */ + 684, /* "c2pnb163v1" */ + 685, /* "c2pnb163v2" */ + 686, /* "c2pnb163v3" */ + 687, /* "c2pnb176v1" */ + 693, /* "c2pnb208w1" */ + 699, /* "c2pnb272w1" */ + 700, /* "c2pnb304w1" */ + 702, /* "c2pnb368w1" */ + 688, /* "c2tnb191v1" */ + 689, /* "c2tnb191v2" */ + 690, /* "c2tnb191v3" */ + 694, /* "c2tnb239v1" */ + 695, /* "c2tnb239v2" */ + 696, /* "c2tnb239v3" */ + 701, /* "c2tnb359v1" */ + 703, /* "c2tnb431r1" */ + 881, /* "cACertificate" */ + 483, /* "cNAMERecord" */ + 751, /* "camellia-128-cbc" */ + 962, /* "camellia-128-ccm" */ + 757, /* "camellia-128-cfb" */ + 760, /* "camellia-128-cfb1" */ + 763, /* "camellia-128-cfb8" */ + 964, /* "camellia-128-cmac" */ + 963, /* "camellia-128-ctr" */ + 754, /* "camellia-128-ecb" */ + 961, /* "camellia-128-gcm" */ + 766, /* "camellia-128-ofb" */ + 752, /* "camellia-192-cbc" */ + 966, /* "camellia-192-ccm" */ + 758, /* "camellia-192-cfb" */ + 761, /* "camellia-192-cfb1" */ + 764, /* "camellia-192-cfb8" */ + 968, /* "camellia-192-cmac" */ + 967, /* "camellia-192-ctr" */ + 755, /* "camellia-192-ecb" */ + 965, /* "camellia-192-gcm" */ + 767, /* "camellia-192-ofb" */ + 753, /* "camellia-256-cbc" */ + 970, /* "camellia-256-ccm" */ + 759, /* "camellia-256-cfb" */ + 762, /* "camellia-256-cfb1" */ + 765, /* "camellia-256-cfb8" */ + 972, /* "camellia-256-cmac" */ + 971, /* "camellia-256-ctr" */ + 756, /* "camellia-256-ecb" */ + 969, /* "camellia-256-gcm" */ + 768, /* "camellia-256-ofb" */ + 443, /* "caseIgnoreIA5StringSyntax" */ + 108, /* "cast5-cbc" */ + 110, /* "cast5-cfb" */ + 109, /* "cast5-ecb" */ + 111, /* "cast5-ofb" */ + 152, /* "certBag" */ + 677, /* "certicom-arc" */ + 517, /* "certificate extensions" */ + 883, /* "certificateRevocationList" */ + 1019, /* "chacha20" */ + 1018, /* "chacha20-poly1305" */ + 54, /* "challengePassword" */ + 407, /* "characteristic-two-field" */ + 395, /* "clearance" */ + 633, /* "cleartext track 2" */ + 894, /* "cmac" */ + 13, /* "commonName" */ + 513, /* "content types" */ + 50, /* "contentType" */ + 53, /* "countersignature" */ + 1090, /* "countryCode3c" */ + 1091, /* "countryCode3n" */ + 14, /* "countryName" */ + 153, /* "crlBag" */ + 884, /* "crossCertificatePair" */ + 806, /* "cryptocom" */ + 805, /* "cryptopro" */ + 500, /* "dITRedirect" */ + 451, /* "dNSDomain" */ + 495, /* "dSAQuality" */ + 434, /* "data" */ + 390, /* "dcObject" */ + 891, /* "deltaRevocationList" */ + 31, /* "des-cbc" */ + 643, /* "des-cdmf" */ + 30, /* "des-cfb" */ + 656, /* "des-cfb1" */ + 657, /* "des-cfb8" */ + 29, /* "des-ecb" */ + 32, /* "des-ede" */ + 43, /* "des-ede-cbc" */ + 60, /* "des-ede-cfb" */ + 62, /* "des-ede-ofb" */ + 33, /* "des-ede3" */ + 44, /* "des-ede3-cbc" */ + 61, /* "des-ede3-cfb" */ + 658, /* "des-ede3-cfb1" */ + 659, /* "des-ede3-cfb8" */ + 63, /* "des-ede3-ofb" */ + 45, /* "des-ofb" */ + 107, /* "description" */ + 871, /* "destinationIndicator" */ + 80, /* "desx-cbc" */ + 947, /* "dh-cofactor-kdf" */ + 946, /* "dh-std-kdf" */ + 28, /* "dhKeyAgreement" */ + 941, /* "dhSinglePass-cofactorDH-sha1kdf-scheme" */ + 942, /* "dhSinglePass-cofactorDH-sha224kdf-scheme" */ + 943, /* "dhSinglePass-cofactorDH-sha256kdf-scheme" */ + 944, /* "dhSinglePass-cofactorDH-sha384kdf-scheme" */ + 945, /* "dhSinglePass-cofactorDH-sha512kdf-scheme" */ + 936, /* "dhSinglePass-stdDH-sha1kdf-scheme" */ + 937, /* "dhSinglePass-stdDH-sha224kdf-scheme" */ + 938, /* "dhSinglePass-stdDH-sha256kdf-scheme" */ + 939, /* "dhSinglePass-stdDH-sha384kdf-scheme" */ + 940, /* "dhSinglePass-stdDH-sha512kdf-scheme" */ + 11, /* "directory services (X.500)" */ + 378, /* "directory services - algorithms" */ + 887, /* "distinguishedName" */ + 892, /* "dmdName" */ + 174, /* "dnQualifier" */ + 1092, /* "dnsName" */ + 447, /* "document" */ + 471, /* "documentAuthor" */ + 468, /* "documentIdentifier" */ + 472, /* "documentLocation" */ + 502, /* "documentPublisher" */ + 449, /* "documentSeries" */ + 469, /* "documentTitle" */ + 470, /* "documentVersion" */ + 380, /* "dod" */ + 391, /* "domainComponent" */ + 452, /* "domainRelatedObject" */ + 116, /* "dsaEncryption" */ + 67, /* "dsaEncryption-old" */ + 66, /* "dsaWithSHA" */ + 113, /* "dsaWithSHA1" */ + 70, /* "dsaWithSHA1-old" */ + 802, /* "dsa_with_SHA224" */ + 803, /* "dsa_with_SHA256" */ + 1108, /* "dsa_with_SHA3-224" */ + 1109, /* "dsa_with_SHA3-256" */ + 1110, /* "dsa_with_SHA3-384" */ + 1111, /* "dsa_with_SHA3-512" */ + 1106, /* "dsa_with_SHA384" */ + 1107, /* "dsa_with_SHA512" */ + 297, /* "dvcs" */ + 791, /* "ecdsa-with-Recommended" */ + 416, /* "ecdsa-with-SHA1" */ + 793, /* "ecdsa-with-SHA224" */ + 794, /* "ecdsa-with-SHA256" */ + 795, /* "ecdsa-with-SHA384" */ + 796, /* "ecdsa-with-SHA512" */ + 792, /* "ecdsa-with-Specified" */ + 1112, /* "ecdsa_with_SHA3-224" */ + 1113, /* "ecdsa_with_SHA3-256" */ + 1114, /* "ecdsa_with_SHA3-384" */ + 1115, /* "ecdsa_with_SHA3-512" */ + 48, /* "emailAddress" */ + 632, /* "encrypted track 2" */ + 885, /* "enhancedSearchGuide" */ + 56, /* "extendedCertificateAttributes" */ + 867, /* "facsimileTelephoneNumber" */ + 462, /* "favouriteDrink" */ + 1126, /* "ffdhe2048" */ + 1127, /* "ffdhe3072" */ + 1128, /* "ffdhe4096" */ + 1129, /* "ffdhe6144" */ + 1130, /* "ffdhe8192" */ + 453, /* "friendlyCountry" */ + 490, /* "friendlyCountryName" */ + 156, /* "friendlyName" */ + 631, /* "generate cryptogram" */ + 509, /* "generationQualifier" */ + 601, /* "generic cryptogram" */ + 99, /* "givenName" */ + 976, /* "gost-mac-12" */ + 1009, /* "gost89-cbc" */ + 814, /* "gost89-cnt" */ + 975, /* "gost89-cnt-12" */ + 1011, /* "gost89-ctr" */ + 1010, /* "gost89-ecb" */ + 1015, /* "grasshopper-cbc" */ + 1016, /* "grasshopper-cfb" */ + 1013, /* "grasshopper-ctr" */ + 1012, /* "grasshopper-ecb" */ + 1017, /* "grasshopper-mac" */ + 1014, /* "grasshopper-ofb" */ + 1036, /* "hkdf" */ + 855, /* "hmac" */ + 780, /* "hmac-md5" */ + 781, /* "hmac-sha1" */ + 1102, /* "hmac-sha3-224" */ + 1103, /* "hmac-sha3-256" */ + 1104, /* "hmac-sha3-384" */ + 1105, /* "hmac-sha3-512" */ + 797, /* "hmacWithMD5" */ + 163, /* "hmacWithSHA1" */ + 798, /* "hmacWithSHA224" */ + 799, /* "hmacWithSHA256" */ + 800, /* "hmacWithSHA384" */ + 801, /* "hmacWithSHA512" */ + 1193, /* "hmacWithSHA512-224" */ + 1194, /* "hmacWithSHA512-256" */ + 486, /* "homePostalAddress" */ + 473, /* "homeTelephoneNumber" */ + 466, /* "host" */ + 889, /* "houseIdentifier" */ + 442, /* "iA5StringSyntax" */ + 381, /* "iana" */ + 824, /* "id-Gost28147-89-CryptoPro-A-ParamSet" */ + 825, /* "id-Gost28147-89-CryptoPro-B-ParamSet" */ + 826, /* "id-Gost28147-89-CryptoPro-C-ParamSet" */ + 827, /* "id-Gost28147-89-CryptoPro-D-ParamSet" */ + 819, /* "id-Gost28147-89-CryptoPro-KeyMeshing" */ + 829, /* "id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet" */ + 828, /* "id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet" */ + 830, /* "id-Gost28147-89-CryptoPro-RIC-1-ParamSet" */ + 820, /* "id-Gost28147-89-None-KeyMeshing" */ + 823, /* "id-Gost28147-89-TestParamSet" */ + 840, /* "id-GostR3410-2001-CryptoPro-A-ParamSet" */ + 841, /* "id-GostR3410-2001-CryptoPro-B-ParamSet" */ + 842, /* "id-GostR3410-2001-CryptoPro-C-ParamSet" */ + 843, /* "id-GostR3410-2001-CryptoPro-XchA-ParamSet" */ + 844, /* "id-GostR3410-2001-CryptoPro-XchB-ParamSet" */ + 839, /* "id-GostR3410-2001-TestParamSet" */ + 832, /* "id-GostR3410-94-CryptoPro-A-ParamSet" */ + 833, /* "id-GostR3410-94-CryptoPro-B-ParamSet" */ + 834, /* "id-GostR3410-94-CryptoPro-C-ParamSet" */ + 835, /* "id-GostR3410-94-CryptoPro-D-ParamSet" */ + 836, /* "id-GostR3410-94-CryptoPro-XchA-ParamSet" */ + 837, /* "id-GostR3410-94-CryptoPro-XchB-ParamSet" */ + 838, /* "id-GostR3410-94-CryptoPro-XchC-ParamSet" */ + 831, /* "id-GostR3410-94-TestParamSet" */ + 845, /* "id-GostR3410-94-a" */ + 846, /* "id-GostR3410-94-aBis" */ + 847, /* "id-GostR3410-94-b" */ + 848, /* "id-GostR3410-94-bBis" */ + 822, /* "id-GostR3411-94-CryptoProParamSet" */ + 821, /* "id-GostR3411-94-TestParamSet" */ + 266, /* "id-aca" */ + 355, /* "id-aca-accessIdentity" */ + 354, /* "id-aca-authenticationInfo" */ + 356, /* "id-aca-chargingIdentity" */ + 399, /* "id-aca-encAttrs" */ + 357, /* "id-aca-group" */ + 358, /* "id-aca-role" */ + 176, /* "id-ad" */ + 788, /* "id-aes128-wrap" */ + 897, /* "id-aes128-wrap-pad" */ + 789, /* "id-aes192-wrap" */ + 900, /* "id-aes192-wrap-pad" */ + 790, /* "id-aes256-wrap" */ + 903, /* "id-aes256-wrap-pad" */ + 262, /* "id-alg" */ + 893, /* "id-alg-PWRI-KEK" */ + 323, /* "id-alg-des40" */ + 326, /* "id-alg-dh-pop" */ + 325, /* "id-alg-dh-sig-hmac-sha1" */ + 324, /* "id-alg-noSignature" */ + 907, /* "id-camellia128-wrap" */ + 908, /* "id-camellia192-wrap" */ + 909, /* "id-camellia256-wrap" */ + 268, /* "id-cct" */ + 361, /* "id-cct-PKIData" */ + 362, /* "id-cct-PKIResponse" */ + 360, /* "id-cct-crs" */ + 81, /* "id-ce" */ + 680, /* "id-characteristic-two-basis" */ + 263, /* "id-cmc" */ + 334, /* "id-cmc-addExtensions" */ + 346, /* "id-cmc-confirmCertAcceptance" */ + 330, /* "id-cmc-dataReturn" */ + 336, /* "id-cmc-decryptedPOP" */ + 335, /* "id-cmc-encryptedPOP" */ + 339, /* "id-cmc-getCRL" */ + 338, /* "id-cmc-getCert" */ + 328, /* "id-cmc-identification" */ + 329, /* "id-cmc-identityProof" */ + 337, /* "id-cmc-lraPOPWitness" */ + 344, /* "id-cmc-popLinkRandom" */ + 345, /* "id-cmc-popLinkWitness" */ + 343, /* "id-cmc-queryPending" */ + 333, /* "id-cmc-recipientNonce" */ + 341, /* "id-cmc-regInfo" */ + 342, /* "id-cmc-responseInfo" */ + 340, /* "id-cmc-revokeRequest" */ + 332, /* "id-cmc-senderNonce" */ + 327, /* "id-cmc-statusInfo" */ + 331, /* "id-cmc-transactionId" */ + 787, /* "id-ct-asciiTextWithCRLF" */ + 1060, /* "id-ct-xml" */ + 408, /* "id-ecPublicKey" */ + 508, /* "id-hex-multipart-message" */ + 507, /* "id-hex-partial-message" */ + 260, /* "id-it" */ + 302, /* "id-it-caKeyUpdateInfo" */ + 298, /* "id-it-caProtEncCert" */ + 311, /* "id-it-confirmWaitTime" */ + 303, /* "id-it-currentCRL" */ + 300, /* "id-it-encKeyPairTypes" */ + 310, /* "id-it-implicitConfirm" */ + 308, /* "id-it-keyPairParamRep" */ + 307, /* "id-it-keyPairParamReq" */ + 312, /* "id-it-origPKIMessage" */ + 301, /* "id-it-preferredSymmAlg" */ + 309, /* "id-it-revPassphrase" */ + 299, /* "id-it-signKeyPairTypes" */ + 305, /* "id-it-subscriptionRequest" */ + 306, /* "id-it-subscriptionResponse" */ + 784, /* "id-it-suppLangTags" */ + 304, /* "id-it-unsupportedOIDs" */ + 128, /* "id-kp" */ + 280, /* "id-mod-attribute-cert" */ + 274, /* "id-mod-cmc" */ + 277, /* "id-mod-cmp" */ + 284, /* "id-mod-cmp2000" */ + 273, /* "id-mod-crmf" */ + 283, /* "id-mod-dvcs" */ + 275, /* "id-mod-kea-profile-88" */ + 276, /* "id-mod-kea-profile-93" */ + 282, /* "id-mod-ocsp" */ + 278, /* "id-mod-qualified-cert-88" */ + 279, /* "id-mod-qualified-cert-93" */ + 281, /* "id-mod-timestamp-protocol" */ + 264, /* "id-on" */ + 347, /* "id-on-personalData" */ + 265, /* "id-pda" */ + 352, /* "id-pda-countryOfCitizenship" */ + 353, /* "id-pda-countryOfResidence" */ + 348, /* "id-pda-dateOfBirth" */ + 351, /* "id-pda-gender" */ + 349, /* "id-pda-placeOfBirth" */ + 175, /* "id-pe" */ + 1031, /* "id-pkinit" */ + 261, /* "id-pkip" */ + 258, /* "id-pkix-mod" */ + 269, /* "id-pkix1-explicit-88" */ + 271, /* "id-pkix1-explicit-93" */ + 270, /* "id-pkix1-implicit-88" */ + 272, /* "id-pkix1-implicit-93" */ + 662, /* "id-ppl" */ + 267, /* "id-qcs" */ + 359, /* "id-qcs-pkixQCSyntax-v1" */ + 259, /* "id-qt" */ + 313, /* "id-regCtrl" */ + 316, /* "id-regCtrl-authenticator" */ + 319, /* "id-regCtrl-oldCertID" */ + 318, /* "id-regCtrl-pkiArchiveOptions" */ + 317, /* "id-regCtrl-pkiPublicationInfo" */ + 320, /* "id-regCtrl-protocolEncrKey" */ + 315, /* "id-regCtrl-regToken" */ + 314, /* "id-regInfo" */ + 322, /* "id-regInfo-certReq" */ + 321, /* "id-regInfo-utf8Pairs" */ + 191, /* "id-smime-aa" */ + 215, /* "id-smime-aa-contentHint" */ + 218, /* "id-smime-aa-contentIdentifier" */ + 221, /* "id-smime-aa-contentReference" */ + 240, /* "id-smime-aa-dvcs-dvc" */ + 217, /* "id-smime-aa-encapContentType" */ + 222, /* "id-smime-aa-encrypKeyPref" */ + 220, /* "id-smime-aa-equivalentLabels" */ + 232, /* "id-smime-aa-ets-CertificateRefs" */ + 233, /* "id-smime-aa-ets-RevocationRefs" */ + 238, /* "id-smime-aa-ets-archiveTimeStamp" */ + 237, /* "id-smime-aa-ets-certCRLTimestamp" */ + 234, /* "id-smime-aa-ets-certValues" */ + 227, /* "id-smime-aa-ets-commitmentType" */ + 231, /* "id-smime-aa-ets-contentTimestamp" */ + 236, /* "id-smime-aa-ets-escTimeStamp" */ + 230, /* "id-smime-aa-ets-otherSigCert" */ + 235, /* "id-smime-aa-ets-revocationValues" */ + 226, /* "id-smime-aa-ets-sigPolicyId" */ + 229, /* "id-smime-aa-ets-signerAttr" */ + 228, /* "id-smime-aa-ets-signerLocation" */ + 219, /* "id-smime-aa-macValue" */ + 214, /* "id-smime-aa-mlExpandHistory" */ + 216, /* "id-smime-aa-msgSigDigest" */ + 212, /* "id-smime-aa-receiptRequest" */ + 213, /* "id-smime-aa-securityLabel" */ + 239, /* "id-smime-aa-signatureType" */ + 223, /* "id-smime-aa-signingCertificate" */ + 1086, /* "id-smime-aa-signingCertificateV2" */ + 224, /* "id-smime-aa-smimeEncryptCerts" */ + 225, /* "id-smime-aa-timeStampToken" */ + 192, /* "id-smime-alg" */ + 243, /* "id-smime-alg-3DESwrap" */ + 246, /* "id-smime-alg-CMS3DESwrap" */ + 247, /* "id-smime-alg-CMSRC2wrap" */ + 245, /* "id-smime-alg-ESDH" */ + 241, /* "id-smime-alg-ESDHwith3DES" */ + 242, /* "id-smime-alg-ESDHwithRC2" */ + 244, /* "id-smime-alg-RC2wrap" */ + 193, /* "id-smime-cd" */ + 248, /* "id-smime-cd-ldap" */ + 190, /* "id-smime-ct" */ + 210, /* "id-smime-ct-DVCSRequestData" */ + 211, /* "id-smime-ct-DVCSResponseData" */ + 208, /* "id-smime-ct-TDTInfo" */ + 207, /* "id-smime-ct-TSTInfo" */ + 205, /* "id-smime-ct-authData" */ + 1059, /* "id-smime-ct-authEnvelopedData" */ + 786, /* "id-smime-ct-compressedData" */ + 1058, /* "id-smime-ct-contentCollection" */ + 209, /* "id-smime-ct-contentInfo" */ + 206, /* "id-smime-ct-publishCert" */ + 204, /* "id-smime-ct-receipt" */ + 195, /* "id-smime-cti" */ + 255, /* "id-smime-cti-ets-proofOfApproval" */ + 256, /* "id-smime-cti-ets-proofOfCreation" */ + 253, /* "id-smime-cti-ets-proofOfDelivery" */ + 251, /* "id-smime-cti-ets-proofOfOrigin" */ + 252, /* "id-smime-cti-ets-proofOfReceipt" */ + 254, /* "id-smime-cti-ets-proofOfSender" */ + 189, /* "id-smime-mod" */ + 196, /* "id-smime-mod-cms" */ + 197, /* "id-smime-mod-ess" */ + 202, /* "id-smime-mod-ets-eSigPolicy-88" */ + 203, /* "id-smime-mod-ets-eSigPolicy-97" */ + 200, /* "id-smime-mod-ets-eSignature-88" */ + 201, /* "id-smime-mod-ets-eSignature-97" */ + 199, /* "id-smime-mod-msg-v3" */ + 198, /* "id-smime-mod-oid" */ + 194, /* "id-smime-spq" */ + 250, /* "id-smime-spq-ets-sqt-unotice" */ + 249, /* "id-smime-spq-ets-sqt-uri" */ + 974, /* "id-tc26" */ + 991, /* "id-tc26-agreement" */ + 992, /* "id-tc26-agreement-gost-3410-2012-256" */ + 993, /* "id-tc26-agreement-gost-3410-2012-512" */ + 977, /* "id-tc26-algorithms" */ + 990, /* "id-tc26-cipher" */ + 1001, /* "id-tc26-cipher-constants" */ + 1176, /* "id-tc26-cipher-gostr3412-2015-kuznyechik" */ + 1177, /* "id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm" */ + 1178, /* "id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm-omac" */ + 1173, /* "id-tc26-cipher-gostr3412-2015-magma" */ + 1174, /* "id-tc26-cipher-gostr3412-2015-magma-ctracpkm" */ + 1175, /* "id-tc26-cipher-gostr3412-2015-magma-ctracpkm-omac" */ + 994, /* "id-tc26-constants" */ + 981, /* "id-tc26-digest" */ + 1000, /* "id-tc26-digest-constants" */ + 1002, /* "id-tc26-gost-28147-constants" */ + 1147, /* "id-tc26-gost-3410-2012-256-constants" */ + 996, /* "id-tc26-gost-3410-2012-512-constants" */ + 987, /* "id-tc26-mac" */ + 978, /* "id-tc26-sign" */ + 995, /* "id-tc26-sign-constants" */ + 984, /* "id-tc26-signwithdigest" */ + 1179, /* "id-tc26-wrap" */ + 1182, /* "id-tc26-wrap-gostr3412-2015-kuznyechik" */ + 1183, /* "id-tc26-wrap-gostr3412-2015-kuznyechik-kexp15" */ + 1180, /* "id-tc26-wrap-gostr3412-2015-magma" */ + 1181, /* "id-tc26-wrap-gostr3412-2015-magma-kexp15" */ + 34, /* "idea-cbc" */ + 35, /* "idea-cfb" */ + 36, /* "idea-ecb" */ + 46, /* "idea-ofb" */ + 676, /* "identified-organization" */ + 1170, /* "ieee" */ + 461, /* "info" */ + 101, /* "initials" */ + 869, /* "internationaliSDNNumber" */ + 1022, /* "ipsec Internet Key Exchange" */ + 749, /* "ipsec3" */ + 750, /* "ipsec4" */ + 181, /* "iso" */ + 623, /* "issuer capabilities" */ + 645, /* "itu-t" */ + 492, /* "janetMailbox" */ + 646, /* "joint-iso-itu-t" */ + 957, /* "jurisdictionCountryName" */ + 955, /* "jurisdictionLocalityName" */ + 956, /* "jurisdictionStateOrProvinceName" */ + 150, /* "keyBag" */ + 773, /* "kisa" */ + 1063, /* "kx-any" */ + 1039, /* "kx-dhe" */ + 1041, /* "kx-dhe-psk" */ + 1038, /* "kx-ecdhe" */ + 1040, /* "kx-ecdhe-psk" */ + 1045, /* "kx-gost" */ + 1043, /* "kx-psk" */ + 1037, /* "kx-rsa" */ + 1042, /* "kx-rsa-psk" */ + 1044, /* "kx-srp" */ + 477, /* "lastModifiedBy" */ + 476, /* "lastModifiedTime" */ + 157, /* "localKeyID" */ + 15, /* "localityName" */ + 480, /* "mXRecord" */ + 1190, /* "magma-cbc" */ + 1191, /* "magma-cfb" */ + 1188, /* "magma-ctr" */ + 1187, /* "magma-ecb" */ + 1192, /* "magma-mac" */ + 1189, /* "magma-ofb" */ + 493, /* "mailPreferenceOption" */ + 467, /* "manager" */ + 3, /* "md2" */ + 7, /* "md2WithRSAEncryption" */ + 257, /* "md4" */ + 396, /* "md4WithRSAEncryption" */ + 4, /* "md5" */ + 114, /* "md5-sha1" */ + 104, /* "md5WithRSA" */ + 8, /* "md5WithRSAEncryption" */ + 95, /* "mdc2" */ + 96, /* "mdc2WithRSA" */ + 875, /* "member" */ + 602, /* "merchant initiated auth" */ + 514, /* "message extensions" */ + 51, /* "messageDigest" */ + 911, /* "mgf1" */ + 506, /* "mime-mhs-bodies" */ + 505, /* "mime-mhs-headings" */ + 488, /* "mobileTelephoneNumber" */ + 481, /* "nSRecord" */ + 173, /* "name" */ + 681, /* "onBasis" */ + 379, /* "org" */ + 1089, /* "organizationIdentifier" */ + 17, /* "organizationName" */ + 491, /* "organizationalStatus" */ + 18, /* "organizationalUnitName" */ + 1141, /* "oscca" */ + 475, /* "otherMailbox" */ + 876, /* "owner" */ + 935, /* "pSpecified" */ + 489, /* "pagerTelephoneNumber" */ + 782, /* "password based MAC" */ + 374, /* "path" */ + 621, /* "payment gateway capabilities" */ + 9, /* "pbeWithMD2AndDES-CBC" */ + 168, /* "pbeWithMD2AndRC2-CBC" */ + 112, /* "pbeWithMD5AndCast5CBC" */ + 10, /* "pbeWithMD5AndDES-CBC" */ + 169, /* "pbeWithMD5AndRC2-CBC" */ + 148, /* "pbeWithSHA1And128BitRC2-CBC" */ + 144, /* "pbeWithSHA1And128BitRC4" */ + 147, /* "pbeWithSHA1And2-KeyTripleDES-CBC" */ + 146, /* "pbeWithSHA1And3-KeyTripleDES-CBC" */ + 149, /* "pbeWithSHA1And40BitRC2-CBC" */ + 145, /* "pbeWithSHA1And40BitRC4" */ + 170, /* "pbeWithSHA1AndDES-CBC" */ + 68, /* "pbeWithSHA1AndRC2-CBC" */ + 499, /* "personalSignature" */ + 487, /* "personalTitle" */ + 464, /* "photo" */ + 863, /* "physicalDeliveryOfficeName" */ + 437, /* "pilot" */ + 439, /* "pilotAttributeSyntax" */ + 438, /* "pilotAttributeType" */ + 479, /* "pilotAttributeType27" */ + 456, /* "pilotDSA" */ + 441, /* "pilotGroups" */ + 444, /* "pilotObject" */ + 440, /* "pilotObjectClass" */ + 455, /* "pilotOrganization" */ + 445, /* "pilotPerson" */ + 186, /* "pkcs1" */ + 27, /* "pkcs3" */ + 187, /* "pkcs5" */ + 20, /* "pkcs7" */ + 21, /* "pkcs7-data" */ + 25, /* "pkcs7-digestData" */ + 26, /* "pkcs7-encryptedData" */ + 23, /* "pkcs7-envelopedData" */ + 24, /* "pkcs7-signedAndEnvelopedData" */ + 22, /* "pkcs7-signedData" */ + 151, /* "pkcs8ShroudedKeyBag" */ + 47, /* "pkcs9" */ + 1061, /* "poly1305" */ + 862, /* "postOfficeBox" */ + 861, /* "postalAddress" */ + 661, /* "postalCode" */ + 683, /* "ppBasis" */ + 872, /* "preferredDeliveryMethod" */ + 873, /* "presentationAddress" */ + 406, /* "prime-field" */ + 409, /* "prime192v1" */ + 410, /* "prime192v2" */ + 411, /* "prime192v3" */ + 412, /* "prime239v1" */ + 413, /* "prime239v2" */ + 414, /* "prime239v3" */ + 415, /* "prime256v1" */ + 886, /* "protocolInformation" */ + 510, /* "pseudonym" */ + 435, /* "pss" */ + 286, /* "qcStatements" */ + 457, /* "qualityLabelledData" */ + 450, /* "rFC822localPart" */ + 98, /* "rc2-40-cbc" */ + 166, /* "rc2-64-cbc" */ + 37, /* "rc2-cbc" */ + 39, /* "rc2-cfb" */ + 38, /* "rc2-ecb" */ + 40, /* "rc2-ofb" */ + 5, /* "rc4" */ + 97, /* "rc4-40" */ + 915, /* "rc4-hmac-md5" */ + 120, /* "rc5-cbc" */ + 122, /* "rc5-cfb" */ + 121, /* "rc5-ecb" */ + 123, /* "rc5-ofb" */ + 870, /* "registeredAddress" */ + 460, /* "rfc822Mailbox" */ + 117, /* "ripemd160" */ + 119, /* "ripemd160WithRSA" */ + 400, /* "role" */ + 877, /* "roleOccupant" */ + 448, /* "room" */ + 463, /* "roomNumber" */ + 19, /* "rsa" */ + 6, /* "rsaEncryption" */ + 644, /* "rsaOAEPEncryptionSET" */ + 377, /* "rsaSignature" */ + 919, /* "rsaesOaep" */ + 912, /* "rsassaPss" */ + 482, /* "sOARecord" */ + 155, /* "safeContentsBag" */ + 291, /* "sbgp-autonomousSysNum" */ + 290, /* "sbgp-ipAddrBlock" */ + 292, /* "sbgp-routerIdentifier" */ + 973, /* "scrypt" */ + 159, /* "sdsiCertificate" */ + 859, /* "searchGuide" */ + 704, /* "secp112r1" */ + 705, /* "secp112r2" */ + 706, /* "secp128r1" */ + 707, /* "secp128r2" */ + 708, /* "secp160k1" */ + 709, /* "secp160r1" */ + 710, /* "secp160r2" */ + 711, /* "secp192k1" */ + 712, /* "secp224k1" */ + 713, /* "secp224r1" */ + 714, /* "secp256k1" */ + 715, /* "secp384r1" */ + 716, /* "secp521r1" */ + 154, /* "secretBag" */ + 474, /* "secretary" */ + 717, /* "sect113r1" */ + 718, /* "sect113r2" */ + 719, /* "sect131r1" */ + 720, /* "sect131r2" */ + 721, /* "sect163k1" */ + 722, /* "sect163r1" */ + 723, /* "sect163r2" */ + 724, /* "sect193r1" */ + 725, /* "sect193r2" */ + 726, /* "sect233k1" */ + 727, /* "sect233r1" */ + 728, /* "sect239k1" */ + 729, /* "sect283k1" */ + 730, /* "sect283r1" */ + 731, /* "sect409k1" */ + 732, /* "sect409r1" */ + 733, /* "sect571k1" */ + 734, /* "sect571r1" */ + 635, /* "secure device signature" */ + 878, /* "seeAlso" */ + 777, /* "seed-cbc" */ + 779, /* "seed-cfb" */ + 776, /* "seed-ecb" */ + 778, /* "seed-ofb" */ + 105, /* "serialNumber" */ + 625, /* "set-addPolicy" */ + 515, /* "set-attr" */ + 518, /* "set-brand" */ + 638, /* "set-brand-AmericanExpress" */ + 637, /* "set-brand-Diners" */ + 636, /* "set-brand-IATA-ATA" */ + 639, /* "set-brand-JCB" */ + 641, /* "set-brand-MasterCard" */ + 642, /* "set-brand-Novus" */ + 640, /* "set-brand-Visa" */ + 516, /* "set-policy" */ + 607, /* "set-policy-root" */ + 624, /* "set-rootKeyThumb" */ + 620, /* "setAttr-Cert" */ + 628, /* "setAttr-IssCap-CVM" */ + 630, /* "setAttr-IssCap-Sig" */ + 629, /* "setAttr-IssCap-T2" */ + 627, /* "setAttr-Token-B0Prime" */ + 626, /* "setAttr-Token-EMV" */ + 622, /* "setAttr-TokenType" */ + 619, /* "setCext-IssuerCapabilities" */ + 615, /* "setCext-PGWYcapabilities" */ + 616, /* "setCext-TokenIdentifier" */ + 618, /* "setCext-TokenType" */ + 617, /* "setCext-Track2Data" */ + 611, /* "setCext-cCertRequired" */ + 609, /* "setCext-certType" */ + 608, /* "setCext-hashedRoot" */ + 610, /* "setCext-merchData" */ + 613, /* "setCext-setExt" */ + 614, /* "setCext-setQualf" */ + 612, /* "setCext-tunneling" */ + 540, /* "setct-AcqCardCodeMsg" */ + 576, /* "setct-AcqCardCodeMsgTBE" */ + 570, /* "setct-AuthReqTBE" */ + 534, /* "setct-AuthReqTBS" */ + 527, /* "setct-AuthResBaggage" */ + 571, /* "setct-AuthResTBE" */ + 572, /* "setct-AuthResTBEX" */ + 535, /* "setct-AuthResTBS" */ + 536, /* "setct-AuthResTBSX" */ + 528, /* "setct-AuthRevReqBaggage" */ + 577, /* "setct-AuthRevReqTBE" */ + 541, /* "setct-AuthRevReqTBS" */ + 529, /* "setct-AuthRevResBaggage" */ + 542, /* "setct-AuthRevResData" */ + 578, /* "setct-AuthRevResTBE" */ + 579, /* "setct-AuthRevResTBEB" */ + 543, /* "setct-AuthRevResTBS" */ + 573, /* "setct-AuthTokenTBE" */ + 537, /* "setct-AuthTokenTBS" */ + 600, /* "setct-BCIDistributionTBS" */ + 558, /* "setct-BatchAdminReqData" */ + 592, /* "setct-BatchAdminReqTBE" */ + 559, /* "setct-BatchAdminResData" */ + 593, /* "setct-BatchAdminResTBE" */ + 599, /* "setct-CRLNotificationResTBS" */ + 598, /* "setct-CRLNotificationTBS" */ + 580, /* "setct-CapReqTBE" */ + 581, /* "setct-CapReqTBEX" */ + 544, /* "setct-CapReqTBS" */ + 545, /* "setct-CapReqTBSX" */ + 546, /* "setct-CapResData" */ + 582, /* "setct-CapResTBE" */ + 583, /* "setct-CapRevReqTBE" */ + 584, /* "setct-CapRevReqTBEX" */ + 547, /* "setct-CapRevReqTBS" */ + 548, /* "setct-CapRevReqTBSX" */ + 549, /* "setct-CapRevResData" */ + 585, /* "setct-CapRevResTBE" */ + 538, /* "setct-CapTokenData" */ + 530, /* "setct-CapTokenSeq" */ + 574, /* "setct-CapTokenTBE" */ + 575, /* "setct-CapTokenTBEX" */ + 539, /* "setct-CapTokenTBS" */ + 560, /* "setct-CardCInitResTBS" */ + 566, /* "setct-CertInqReqTBS" */ + 563, /* "setct-CertReqData" */ + 595, /* "setct-CertReqTBE" */ + 596, /* "setct-CertReqTBEX" */ + 564, /* "setct-CertReqTBS" */ + 565, /* "setct-CertResData" */ + 597, /* "setct-CertResTBE" */ + 586, /* "setct-CredReqTBE" */ + 587, /* "setct-CredReqTBEX" */ + 550, /* "setct-CredReqTBS" */ + 551, /* "setct-CredReqTBSX" */ + 552, /* "setct-CredResData" */ + 588, /* "setct-CredResTBE" */ + 589, /* "setct-CredRevReqTBE" */ + 590, /* "setct-CredRevReqTBEX" */ + 553, /* "setct-CredRevReqTBS" */ + 554, /* "setct-CredRevReqTBSX" */ + 555, /* "setct-CredRevResData" */ + 591, /* "setct-CredRevResTBE" */ + 567, /* "setct-ErrorTBS" */ + 526, /* "setct-HODInput" */ + 561, /* "setct-MeAqCInitResTBS" */ + 522, /* "setct-OIData" */ + 519, /* "setct-PANData" */ + 521, /* "setct-PANOnly" */ + 520, /* "setct-PANToken" */ + 556, /* "setct-PCertReqData" */ + 557, /* "setct-PCertResTBS" */ + 523, /* "setct-PI" */ + 532, /* "setct-PI-TBS" */ + 524, /* "setct-PIData" */ + 525, /* "setct-PIDataUnsigned" */ + 568, /* "setct-PIDualSignedTBE" */ + 569, /* "setct-PIUnsignedTBE" */ + 531, /* "setct-PInitResData" */ + 533, /* "setct-PResData" */ + 594, /* "setct-RegFormReqTBE" */ + 562, /* "setct-RegFormResTBS" */ + 604, /* "setext-pinAny" */ + 603, /* "setext-pinSecure" */ + 605, /* "setext-track2" */ + 41, /* "sha" */ + 64, /* "sha1" */ + 115, /* "sha1WithRSA" */ + 65, /* "sha1WithRSAEncryption" */ + 675, /* "sha224" */ + 671, /* "sha224WithRSAEncryption" */ + 672, /* "sha256" */ + 668, /* "sha256WithRSAEncryption" */ + 1096, /* "sha3-224" */ + 1097, /* "sha3-256" */ + 1098, /* "sha3-384" */ + 1099, /* "sha3-512" */ + 673, /* "sha384" */ + 669, /* "sha384WithRSAEncryption" */ + 674, /* "sha512" */ + 1094, /* "sha512-224" */ + 1145, /* "sha512-224WithRSAEncryption" */ + 1095, /* "sha512-256" */ + 1146, /* "sha512-256WithRSAEncryption" */ + 670, /* "sha512WithRSAEncryption" */ + 42, /* "shaWithRSAEncryption" */ + 1100, /* "shake128" */ + 1101, /* "shake256" */ + 52, /* "signingTime" */ + 454, /* "simpleSecurityObject" */ + 496, /* "singleLevelQuality" */ + 1062, /* "siphash" */ + 1142, /* "sm-scheme" */ + 1172, /* "sm2" */ + 1143, /* "sm3" */ + 1144, /* "sm3WithRSAEncryption" */ + 1134, /* "sm4-cbc" */ + 1137, /* "sm4-cfb" */ + 1136, /* "sm4-cfb1" */ + 1138, /* "sm4-cfb8" */ + 1139, /* "sm4-ctr" */ + 1133, /* "sm4-ecb" */ + 1135, /* "sm4-ofb" */ + 16, /* "stateOrProvinceName" */ + 660, /* "streetAddress" */ + 498, /* "subtreeMaximumQuality" */ + 497, /* "subtreeMinimumQuality" */ + 890, /* "supportedAlgorithms" */ + 874, /* "supportedApplicationContext" */ + 100, /* "surname" */ + 864, /* "telephoneNumber" */ + 866, /* "teletexTerminalIdentifier" */ + 865, /* "telexNumber" */ + 459, /* "textEncodedORAddress" */ + 293, /* "textNotice" */ + 106, /* "title" */ + 1021, /* "tls1-prf" */ + 682, /* "tpBasis" */ + 1151, /* "ua-pki" */ + 436, /* "ucl" */ + 0, /* "undefined" */ + 102, /* "uniqueIdentifier" */ + 888, /* "uniqueMember" */ + 55, /* "unstructuredAddress" */ + 49, /* "unstructuredName" */ + 880, /* "userCertificate" */ + 465, /* "userClass" */ + 458, /* "userId" */ + 879, /* "userPassword" */ + 373, /* "valid" */ + 678, /* "wap" */ + 679, /* "wap-wsg" */ + 735, /* "wap-wsg-idm-ecid-wtls1" */ + 743, /* "wap-wsg-idm-ecid-wtls10" */ + 744, /* "wap-wsg-idm-ecid-wtls11" */ + 745, /* "wap-wsg-idm-ecid-wtls12" */ + 736, /* "wap-wsg-idm-ecid-wtls3" */ + 737, /* "wap-wsg-idm-ecid-wtls4" */ + 738, /* "wap-wsg-idm-ecid-wtls5" */ + 739, /* "wap-wsg-idm-ecid-wtls6" */ + 740, /* "wap-wsg-idm-ecid-wtls7" */ + 741, /* "wap-wsg-idm-ecid-wtls8" */ + 742, /* "wap-wsg-idm-ecid-wtls9" */ + 804, /* "whirlpool" */ + 868, /* "x121Address" */ + 503, /* "x500UniqueIdentifier" */ + 158, /* "x509Certificate" */ + 160, /* "x509Crl" */ + 125, /* "zlib compression" */ +}; + +#define NUM_OBJ 1071 +static const unsigned int obj_objs[NUM_OBJ] = { + 0, /* OBJ_undef 0 */ + 181, /* OBJ_iso 1 */ + 393, /* OBJ_joint_iso_ccitt OBJ_joint_iso_itu_t */ + 404, /* OBJ_ccitt OBJ_itu_t */ + 645, /* OBJ_itu_t 0 */ + 646, /* OBJ_joint_iso_itu_t 2 */ + 434, /* OBJ_data 0 9 */ + 182, /* OBJ_member_body 1 2 */ + 379, /* OBJ_org 1 3 */ + 676, /* OBJ_identified_organization 1 3 */ + 11, /* OBJ_X500 2 5 */ + 647, /* OBJ_international_organizations 2 23 */ + 380, /* OBJ_dod 1 3 6 */ + 1170, /* OBJ_ieee 1 3 111 */ + 12, /* OBJ_X509 2 5 4 */ + 378, /* OBJ_X500algorithms 2 5 8 */ + 81, /* OBJ_id_ce 2 5 29 */ + 512, /* OBJ_id_set 2 23 42 */ + 678, /* OBJ_wap 2 23 43 */ + 435, /* OBJ_pss 0 9 2342 */ + 1140, /* OBJ_ISO_CN 1 2 156 */ + 1150, /* OBJ_ISO_UA 1 2 804 */ + 183, /* OBJ_ISO_US 1 2 840 */ + 381, /* OBJ_iana 1 3 6 1 */ + 1034, /* OBJ_X25519 1 3 101 110 */ + 1035, /* OBJ_X448 1 3 101 111 */ + 1087, /* OBJ_ED25519 1 3 101 112 */ + 1088, /* OBJ_ED448 1 3 101 113 */ + 677, /* OBJ_certicom_arc 1 3 132 */ + 394, /* OBJ_selected_attribute_types 2 5 1 5 */ + 13, /* OBJ_commonName 2 5 4 3 */ + 100, /* OBJ_surname 2 5 4 4 */ + 105, /* OBJ_serialNumber 2 5 4 5 */ + 14, /* OBJ_countryName 2 5 4 6 */ + 15, /* OBJ_localityName 2 5 4 7 */ + 16, /* OBJ_stateOrProvinceName 2 5 4 8 */ + 660, /* OBJ_streetAddress 2 5 4 9 */ + 17, /* OBJ_organizationName 2 5 4 10 */ + 18, /* OBJ_organizationalUnitName 2 5 4 11 */ + 106, /* OBJ_title 2 5 4 12 */ + 107, /* OBJ_description 2 5 4 13 */ + 859, /* OBJ_searchGuide 2 5 4 14 */ + 860, /* OBJ_businessCategory 2 5 4 15 */ + 861, /* OBJ_postalAddress 2 5 4 16 */ + 661, /* OBJ_postalCode 2 5 4 17 */ + 862, /* OBJ_postOfficeBox 2 5 4 18 */ + 863, /* OBJ_physicalDeliveryOfficeName 2 5 4 19 */ + 864, /* OBJ_telephoneNumber 2 5 4 20 */ + 865, /* OBJ_telexNumber 2 5 4 21 */ + 866, /* OBJ_teletexTerminalIdentifier 2 5 4 22 */ + 867, /* OBJ_facsimileTelephoneNumber 2 5 4 23 */ + 868, /* OBJ_x121Address 2 5 4 24 */ + 869, /* OBJ_internationaliSDNNumber 2 5 4 25 */ + 870, /* OBJ_registeredAddress 2 5 4 26 */ + 871, /* OBJ_destinationIndicator 2 5 4 27 */ + 872, /* OBJ_preferredDeliveryMethod 2 5 4 28 */ + 873, /* OBJ_presentationAddress 2 5 4 29 */ + 874, /* OBJ_supportedApplicationContext 2 5 4 30 */ + 875, /* OBJ_member 2 5 4 31 */ + 876, /* OBJ_owner 2 5 4 32 */ + 877, /* OBJ_roleOccupant 2 5 4 33 */ + 878, /* OBJ_seeAlso 2 5 4 34 */ + 879, /* OBJ_userPassword 2 5 4 35 */ + 880, /* OBJ_userCertificate 2 5 4 36 */ + 881, /* OBJ_cACertificate 2 5 4 37 */ + 882, /* OBJ_authorityRevocationList 2 5 4 38 */ + 883, /* OBJ_certificateRevocationList 2 5 4 39 */ + 884, /* OBJ_crossCertificatePair 2 5 4 40 */ + 173, /* OBJ_name 2 5 4 41 */ + 99, /* OBJ_givenName 2 5 4 42 */ + 101, /* OBJ_initials 2 5 4 43 */ + 509, /* OBJ_generationQualifier 2 5 4 44 */ + 503, /* OBJ_x500UniqueIdentifier 2 5 4 45 */ + 174, /* OBJ_dnQualifier 2 5 4 46 */ + 885, /* OBJ_enhancedSearchGuide 2 5 4 47 */ + 886, /* OBJ_protocolInformation 2 5 4 48 */ + 887, /* OBJ_distinguishedName 2 5 4 49 */ + 888, /* OBJ_uniqueMember 2 5 4 50 */ + 889, /* OBJ_houseIdentifier 2 5 4 51 */ + 890, /* OBJ_supportedAlgorithms 2 5 4 52 */ + 891, /* OBJ_deltaRevocationList 2 5 4 53 */ + 892, /* OBJ_dmdName 2 5 4 54 */ + 510, /* OBJ_pseudonym 2 5 4 65 */ + 400, /* OBJ_role 2 5 4 72 */ + 1089, /* OBJ_organizationIdentifier 2 5 4 97 */ + 1090, /* OBJ_countryCode3c 2 5 4 98 */ + 1091, /* OBJ_countryCode3n 2 5 4 99 */ + 1092, /* OBJ_dnsName 2 5 4 100 */ + 769, /* OBJ_subject_directory_attributes 2 5 29 9 */ + 82, /* OBJ_subject_key_identifier 2 5 29 14 */ + 83, /* OBJ_key_usage 2 5 29 15 */ + 84, /* OBJ_private_key_usage_period 2 5 29 16 */ + 85, /* OBJ_subject_alt_name 2 5 29 17 */ + 86, /* OBJ_issuer_alt_name 2 5 29 18 */ + 87, /* OBJ_basic_constraints 2 5 29 19 */ + 88, /* OBJ_crl_number 2 5 29 20 */ + 141, /* OBJ_crl_reason 2 5 29 21 */ + 430, /* OBJ_hold_instruction_code 2 5 29 23 */ + 142, /* OBJ_invalidity_date 2 5 29 24 */ + 140, /* OBJ_delta_crl 2 5 29 27 */ + 770, /* OBJ_issuing_distribution_point 2 5 29 28 */ + 771, /* OBJ_certificate_issuer 2 5 29 29 */ + 666, /* OBJ_name_constraints 2 5 29 30 */ + 103, /* OBJ_crl_distribution_points 2 5 29 31 */ + 89, /* OBJ_certificate_policies 2 5 29 32 */ + 747, /* OBJ_policy_mappings 2 5 29 33 */ + 90, /* OBJ_authority_key_identifier 2 5 29 35 */ + 401, /* OBJ_policy_constraints 2 5 29 36 */ + 126, /* OBJ_ext_key_usage 2 5 29 37 */ + 857, /* OBJ_freshest_crl 2 5 29 46 */ + 748, /* OBJ_inhibit_any_policy 2 5 29 54 */ + 402, /* OBJ_target_information 2 5 29 55 */ + 403, /* OBJ_no_rev_avail 2 5 29 56 */ + 513, /* OBJ_set_ctype 2 23 42 0 */ + 514, /* OBJ_set_msgExt 2 23 42 1 */ + 515, /* OBJ_set_attr 2 23 42 3 */ + 516, /* OBJ_set_policy 2 23 42 5 */ + 517, /* OBJ_set_certExt 2 23 42 7 */ + 518, /* OBJ_set_brand 2 23 42 8 */ + 679, /* OBJ_wap_wsg 2 23 43 1 */ + 382, /* OBJ_Directory 1 3 6 1 1 */ + 383, /* OBJ_Management 1 3 6 1 2 */ + 384, /* OBJ_Experimental 1 3 6 1 3 */ + 385, /* OBJ_Private 1 3 6 1 4 */ + 386, /* OBJ_Security 1 3 6 1 5 */ + 387, /* OBJ_SNMPv2 1 3 6 1 6 */ + 388, /* OBJ_Mail 1 3 6 1 7 */ + 376, /* OBJ_algorithm 1 3 14 3 2 */ + 395, /* OBJ_clearance 2 5 1 5 55 */ + 19, /* OBJ_rsa 2 5 8 1 1 */ + 96, /* OBJ_mdc2WithRSA 2 5 8 3 100 */ + 95, /* OBJ_mdc2 2 5 8 3 101 */ + 746, /* OBJ_any_policy 2 5 29 32 0 */ + 910, /* OBJ_anyExtendedKeyUsage 2 5 29 37 0 */ + 519, /* OBJ_setct_PANData 2 23 42 0 0 */ + 520, /* OBJ_setct_PANToken 2 23 42 0 1 */ + 521, /* OBJ_setct_PANOnly 2 23 42 0 2 */ + 522, /* OBJ_setct_OIData 2 23 42 0 3 */ + 523, /* OBJ_setct_PI 2 23 42 0 4 */ + 524, /* OBJ_setct_PIData 2 23 42 0 5 */ + 525, /* OBJ_setct_PIDataUnsigned 2 23 42 0 6 */ + 526, /* OBJ_setct_HODInput 2 23 42 0 7 */ + 527, /* OBJ_setct_AuthResBaggage 2 23 42 0 8 */ + 528, /* OBJ_setct_AuthRevReqBaggage 2 23 42 0 9 */ + 529, /* OBJ_setct_AuthRevResBaggage 2 23 42 0 10 */ + 530, /* OBJ_setct_CapTokenSeq 2 23 42 0 11 */ + 531, /* OBJ_setct_PInitResData 2 23 42 0 12 */ + 532, /* OBJ_setct_PI_TBS 2 23 42 0 13 */ + 533, /* OBJ_setct_PResData 2 23 42 0 14 */ + 534, /* OBJ_setct_AuthReqTBS 2 23 42 0 16 */ + 535, /* OBJ_setct_AuthResTBS 2 23 42 0 17 */ + 536, /* OBJ_setct_AuthResTBSX 2 23 42 0 18 */ + 537, /* OBJ_setct_AuthTokenTBS 2 23 42 0 19 */ + 538, /* OBJ_setct_CapTokenData 2 23 42 0 20 */ + 539, /* OBJ_setct_CapTokenTBS 2 23 42 0 21 */ + 540, /* OBJ_setct_AcqCardCodeMsg 2 23 42 0 22 */ + 541, /* OBJ_setct_AuthRevReqTBS 2 23 42 0 23 */ + 542, /* OBJ_setct_AuthRevResData 2 23 42 0 24 */ + 543, /* OBJ_setct_AuthRevResTBS 2 23 42 0 25 */ + 544, /* OBJ_setct_CapReqTBS 2 23 42 0 26 */ + 545, /* OBJ_setct_CapReqTBSX 2 23 42 0 27 */ + 546, /* OBJ_setct_CapResData 2 23 42 0 28 */ + 547, /* OBJ_setct_CapRevReqTBS 2 23 42 0 29 */ + 548, /* OBJ_setct_CapRevReqTBSX 2 23 42 0 30 */ + 549, /* OBJ_setct_CapRevResData 2 23 42 0 31 */ + 550, /* OBJ_setct_CredReqTBS 2 23 42 0 32 */ + 551, /* OBJ_setct_CredReqTBSX 2 23 42 0 33 */ + 552, /* OBJ_setct_CredResData 2 23 42 0 34 */ + 553, /* OBJ_setct_CredRevReqTBS 2 23 42 0 35 */ + 554, /* OBJ_setct_CredRevReqTBSX 2 23 42 0 36 */ + 555, /* OBJ_setct_CredRevResData 2 23 42 0 37 */ + 556, /* OBJ_setct_PCertReqData 2 23 42 0 38 */ + 557, /* OBJ_setct_PCertResTBS 2 23 42 0 39 */ + 558, /* OBJ_setct_BatchAdminReqData 2 23 42 0 40 */ + 559, /* OBJ_setct_BatchAdminResData 2 23 42 0 41 */ + 560, /* OBJ_setct_CardCInitResTBS 2 23 42 0 42 */ + 561, /* OBJ_setct_MeAqCInitResTBS 2 23 42 0 43 */ + 562, /* OBJ_setct_RegFormResTBS 2 23 42 0 44 */ + 563, /* OBJ_setct_CertReqData 2 23 42 0 45 */ + 564, /* OBJ_setct_CertReqTBS 2 23 42 0 46 */ + 565, /* OBJ_setct_CertResData 2 23 42 0 47 */ + 566, /* OBJ_setct_CertInqReqTBS 2 23 42 0 48 */ + 567, /* OBJ_setct_ErrorTBS 2 23 42 0 49 */ + 568, /* OBJ_setct_PIDualSignedTBE 2 23 42 0 50 */ + 569, /* OBJ_setct_PIUnsignedTBE 2 23 42 0 51 */ + 570, /* OBJ_setct_AuthReqTBE 2 23 42 0 52 */ + 571, /* OBJ_setct_AuthResTBE 2 23 42 0 53 */ + 572, /* OBJ_setct_AuthResTBEX 2 23 42 0 54 */ + 573, /* OBJ_setct_AuthTokenTBE 2 23 42 0 55 */ + 574, /* OBJ_setct_CapTokenTBE 2 23 42 0 56 */ + 575, /* OBJ_setct_CapTokenTBEX 2 23 42 0 57 */ + 576, /* OBJ_setct_AcqCardCodeMsgTBE 2 23 42 0 58 */ + 577, /* OBJ_setct_AuthRevReqTBE 2 23 42 0 59 */ + 578, /* OBJ_setct_AuthRevResTBE 2 23 42 0 60 */ + 579, /* OBJ_setct_AuthRevResTBEB 2 23 42 0 61 */ + 580, /* OBJ_setct_CapReqTBE 2 23 42 0 62 */ + 581, /* OBJ_setct_CapReqTBEX 2 23 42 0 63 */ + 582, /* OBJ_setct_CapResTBE 2 23 42 0 64 */ + 583, /* OBJ_setct_CapRevReqTBE 2 23 42 0 65 */ + 584, /* OBJ_setct_CapRevReqTBEX 2 23 42 0 66 */ + 585, /* OBJ_setct_CapRevResTBE 2 23 42 0 67 */ + 586, /* OBJ_setct_CredReqTBE 2 23 42 0 68 */ + 587, /* OBJ_setct_CredReqTBEX 2 23 42 0 69 */ + 588, /* OBJ_setct_CredResTBE 2 23 42 0 70 */ + 589, /* OBJ_setct_CredRevReqTBE 2 23 42 0 71 */ + 590, /* OBJ_setct_CredRevReqTBEX 2 23 42 0 72 */ + 591, /* OBJ_setct_CredRevResTBE 2 23 42 0 73 */ + 592, /* OBJ_setct_BatchAdminReqTBE 2 23 42 0 74 */ + 593, /* OBJ_setct_BatchAdminResTBE 2 23 42 0 75 */ + 594, /* OBJ_setct_RegFormReqTBE 2 23 42 0 76 */ + 595, /* OBJ_setct_CertReqTBE 2 23 42 0 77 */ + 596, /* OBJ_setct_CertReqTBEX 2 23 42 0 78 */ + 597, /* OBJ_setct_CertResTBE 2 23 42 0 79 */ + 598, /* OBJ_setct_CRLNotificationTBS 2 23 42 0 80 */ + 599, /* OBJ_setct_CRLNotificationResTBS 2 23 42 0 81 */ + 600, /* OBJ_setct_BCIDistributionTBS 2 23 42 0 82 */ + 601, /* OBJ_setext_genCrypt 2 23 42 1 1 */ + 602, /* OBJ_setext_miAuth 2 23 42 1 3 */ + 603, /* OBJ_setext_pinSecure 2 23 42 1 4 */ + 604, /* OBJ_setext_pinAny 2 23 42 1 5 */ + 605, /* OBJ_setext_track2 2 23 42 1 7 */ + 606, /* OBJ_setext_cv 2 23 42 1 8 */ + 620, /* OBJ_setAttr_Cert 2 23 42 3 0 */ + 621, /* OBJ_setAttr_PGWYcap 2 23 42 3 1 */ + 622, /* OBJ_setAttr_TokenType 2 23 42 3 2 */ + 623, /* OBJ_setAttr_IssCap 2 23 42 3 3 */ + 607, /* OBJ_set_policy_root 2 23 42 5 0 */ + 608, /* OBJ_setCext_hashedRoot 2 23 42 7 0 */ + 609, /* OBJ_setCext_certType 2 23 42 7 1 */ + 610, /* OBJ_setCext_merchData 2 23 42 7 2 */ + 611, /* OBJ_setCext_cCertRequired 2 23 42 7 3 */ + 612, /* OBJ_setCext_tunneling 2 23 42 7 4 */ + 613, /* OBJ_setCext_setExt 2 23 42 7 5 */ + 614, /* OBJ_setCext_setQualf 2 23 42 7 6 */ + 615, /* OBJ_setCext_PGWYcapabilities 2 23 42 7 7 */ + 616, /* OBJ_setCext_TokenIdentifier 2 23 42 7 8 */ + 617, /* OBJ_setCext_Track2Data 2 23 42 7 9 */ + 618, /* OBJ_setCext_TokenType 2 23 42 7 10 */ + 619, /* OBJ_setCext_IssuerCapabilities 2 23 42 7 11 */ + 636, /* OBJ_set_brand_IATA_ATA 2 23 42 8 1 */ + 640, /* OBJ_set_brand_Visa 2 23 42 8 4 */ + 641, /* OBJ_set_brand_MasterCard 2 23 42 8 5 */ + 637, /* OBJ_set_brand_Diners 2 23 42 8 30 */ + 638, /* OBJ_set_brand_AmericanExpress 2 23 42 8 34 */ + 639, /* OBJ_set_brand_JCB 2 23 42 8 35 */ + 1141, /* OBJ_oscca 1 2 156 10197 */ + 805, /* OBJ_cryptopro 1 2 643 2 2 */ + 806, /* OBJ_cryptocom 1 2 643 2 9 */ + 974, /* OBJ_id_tc26 1 2 643 7 1 */ + 1005, /* OBJ_OGRN 1 2 643 100 1 */ + 1006, /* OBJ_SNILS 1 2 643 100 3 */ + 1007, /* OBJ_subjectSignTool 1 2 643 100 111 */ + 1008, /* OBJ_issuerSignTool 1 2 643 100 112 */ + 184, /* OBJ_X9_57 1 2 840 10040 */ + 405, /* OBJ_ansi_X9_62 1 2 840 10045 */ + 389, /* OBJ_Enterprises 1 3 6 1 4 1 */ + 504, /* OBJ_mime_mhs 1 3 6 1 7 1 */ + 104, /* OBJ_md5WithRSA 1 3 14 3 2 3 */ + 29, /* OBJ_des_ecb 1 3 14 3 2 6 */ + 31, /* OBJ_des_cbc 1 3 14 3 2 7 */ + 45, /* OBJ_des_ofb64 1 3 14 3 2 8 */ + 30, /* OBJ_des_cfb64 1 3 14 3 2 9 */ + 377, /* OBJ_rsaSignature 1 3 14 3 2 11 */ + 67, /* OBJ_dsa_2 1 3 14 3 2 12 */ + 66, /* OBJ_dsaWithSHA 1 3 14 3 2 13 */ + 42, /* OBJ_shaWithRSAEncryption 1 3 14 3 2 15 */ + 32, /* OBJ_des_ede_ecb 1 3 14 3 2 17 */ + 41, /* OBJ_sha 1 3 14 3 2 18 */ + 64, /* OBJ_sha1 1 3 14 3 2 26 */ + 70, /* OBJ_dsaWithSHA1_2 1 3 14 3 2 27 */ + 115, /* OBJ_sha1WithRSA 1 3 14 3 2 29 */ + 117, /* OBJ_ripemd160 1 3 36 3 2 1 */ + 1093, /* OBJ_x509ExtAdmission 1 3 36 8 3 3 */ + 143, /* OBJ_sxnet 1 3 101 1 4 1 */ + 1171, /* OBJ_ieee_siswg 1 3 111 2 1619 */ + 721, /* OBJ_sect163k1 1 3 132 0 1 */ + 722, /* OBJ_sect163r1 1 3 132 0 2 */ + 728, /* OBJ_sect239k1 1 3 132 0 3 */ + 717, /* OBJ_sect113r1 1 3 132 0 4 */ + 718, /* OBJ_sect113r2 1 3 132 0 5 */ + 704, /* OBJ_secp112r1 1 3 132 0 6 */ + 705, /* OBJ_secp112r2 1 3 132 0 7 */ + 709, /* OBJ_secp160r1 1 3 132 0 8 */ + 708, /* OBJ_secp160k1 1 3 132 0 9 */ + 714, /* OBJ_secp256k1 1 3 132 0 10 */ + 723, /* OBJ_sect163r2 1 3 132 0 15 */ + 729, /* OBJ_sect283k1 1 3 132 0 16 */ + 730, /* OBJ_sect283r1 1 3 132 0 17 */ + 719, /* OBJ_sect131r1 1 3 132 0 22 */ + 720, /* OBJ_sect131r2 1 3 132 0 23 */ + 724, /* OBJ_sect193r1 1 3 132 0 24 */ + 725, /* OBJ_sect193r2 1 3 132 0 25 */ + 726, /* OBJ_sect233k1 1 3 132 0 26 */ + 727, /* OBJ_sect233r1 1 3 132 0 27 */ + 706, /* OBJ_secp128r1 1 3 132 0 28 */ + 707, /* OBJ_secp128r2 1 3 132 0 29 */ + 710, /* OBJ_secp160r2 1 3 132 0 30 */ + 711, /* OBJ_secp192k1 1 3 132 0 31 */ + 712, /* OBJ_secp224k1 1 3 132 0 32 */ + 713, /* OBJ_secp224r1 1 3 132 0 33 */ + 715, /* OBJ_secp384r1 1 3 132 0 34 */ + 716, /* OBJ_secp521r1 1 3 132 0 35 */ + 731, /* OBJ_sect409k1 1 3 132 0 36 */ + 732, /* OBJ_sect409r1 1 3 132 0 37 */ + 733, /* OBJ_sect571k1 1 3 132 0 38 */ + 734, /* OBJ_sect571r1 1 3 132 0 39 */ + 624, /* OBJ_set_rootKeyThumb 2 23 42 3 0 0 */ + 625, /* OBJ_set_addPolicy 2 23 42 3 0 1 */ + 626, /* OBJ_setAttr_Token_EMV 2 23 42 3 2 1 */ + 627, /* OBJ_setAttr_Token_B0Prime 2 23 42 3 2 2 */ + 628, /* OBJ_setAttr_IssCap_CVM 2 23 42 3 3 3 */ + 629, /* OBJ_setAttr_IssCap_T2 2 23 42 3 3 4 */ + 630, /* OBJ_setAttr_IssCap_Sig 2 23 42 3 3 5 */ + 642, /* OBJ_set_brand_Novus 2 23 42 8 6011 */ + 735, /* OBJ_wap_wsg_idm_ecid_wtls1 2 23 43 1 4 1 */ + 736, /* OBJ_wap_wsg_idm_ecid_wtls3 2 23 43 1 4 3 */ + 737, /* OBJ_wap_wsg_idm_ecid_wtls4 2 23 43 1 4 4 */ + 738, /* OBJ_wap_wsg_idm_ecid_wtls5 2 23 43 1 4 5 */ + 739, /* OBJ_wap_wsg_idm_ecid_wtls6 2 23 43 1 4 6 */ + 740, /* OBJ_wap_wsg_idm_ecid_wtls7 2 23 43 1 4 7 */ + 741, /* OBJ_wap_wsg_idm_ecid_wtls8 2 23 43 1 4 8 */ + 742, /* OBJ_wap_wsg_idm_ecid_wtls9 2 23 43 1 4 9 */ + 743, /* OBJ_wap_wsg_idm_ecid_wtls10 2 23 43 1 4 10 */ + 744, /* OBJ_wap_wsg_idm_ecid_wtls11 2 23 43 1 4 11 */ + 745, /* OBJ_wap_wsg_idm_ecid_wtls12 2 23 43 1 4 12 */ + 804, /* OBJ_whirlpool 1 0 10118 3 0 55 */ + 1142, /* OBJ_sm_scheme 1 2 156 10197 1 */ + 773, /* OBJ_kisa 1 2 410 200004 */ + 807, /* OBJ_id_GostR3411_94_with_GostR3410_2001 1 2 643 2 2 3 */ + 808, /* OBJ_id_GostR3411_94_with_GostR3410_94 1 2 643 2 2 4 */ + 809, /* OBJ_id_GostR3411_94 1 2 643 2 2 9 */ + 810, /* OBJ_id_HMACGostR3411_94 1 2 643 2 2 10 */ + 811, /* OBJ_id_GostR3410_2001 1 2 643 2 2 19 */ + 812, /* OBJ_id_GostR3410_94 1 2 643 2 2 20 */ + 813, /* OBJ_id_Gost28147_89 1 2 643 2 2 21 */ + 815, /* OBJ_id_Gost28147_89_MAC 1 2 643 2 2 22 */ + 816, /* OBJ_id_GostR3411_94_prf 1 2 643 2 2 23 */ + 817, /* OBJ_id_GostR3410_2001DH 1 2 643 2 2 98 */ + 818, /* OBJ_id_GostR3410_94DH 1 2 643 2 2 99 */ + 977, /* OBJ_id_tc26_algorithms 1 2 643 7 1 1 */ + 994, /* OBJ_id_tc26_constants 1 2 643 7 1 2 */ + 1, /* OBJ_rsadsi 1 2 840 113549 */ + 185, /* OBJ_X9cm 1 2 840 10040 4 */ + 1031, /* OBJ_id_pkinit 1 3 6 1 5 2 3 */ + 127, /* OBJ_id_pkix 1 3 6 1 5 5 7 */ + 505, /* OBJ_mime_mhs_headings 1 3 6 1 7 1 1 */ + 506, /* OBJ_mime_mhs_bodies 1 3 6 1 7 1 2 */ + 119, /* OBJ_ripemd160WithRSA 1 3 36 3 3 1 2 */ + 937, /* OBJ_dhSinglePass_stdDH_sha224kdf_scheme 1 3 132 1 11 0 */ + 938, /* OBJ_dhSinglePass_stdDH_sha256kdf_scheme 1 3 132 1 11 1 */ + 939, /* OBJ_dhSinglePass_stdDH_sha384kdf_scheme 1 3 132 1 11 2 */ + 940, /* OBJ_dhSinglePass_stdDH_sha512kdf_scheme 1 3 132 1 11 3 */ + 942, /* OBJ_dhSinglePass_cofactorDH_sha224kdf_scheme 1 3 132 1 14 0 */ + 943, /* OBJ_dhSinglePass_cofactorDH_sha256kdf_scheme 1 3 132 1 14 1 */ + 944, /* OBJ_dhSinglePass_cofactorDH_sha384kdf_scheme 1 3 132 1 14 2 */ + 945, /* OBJ_dhSinglePass_cofactorDH_sha512kdf_scheme 1 3 132 1 14 3 */ + 631, /* OBJ_setAttr_GenCryptgrm 2 23 42 3 3 3 1 */ + 632, /* OBJ_setAttr_T2Enc 2 23 42 3 3 4 1 */ + 633, /* OBJ_setAttr_T2cleartxt 2 23 42 3 3 4 2 */ + 634, /* OBJ_setAttr_TokICCsig 2 23 42 3 3 5 1 */ + 635, /* OBJ_setAttr_SecDevSig 2 23 42 3 3 5 2 */ + 436, /* OBJ_ucl 0 9 2342 19200300 */ + 820, /* OBJ_id_Gost28147_89_None_KeyMeshing 1 2 643 2 2 14 0 */ + 819, /* OBJ_id_Gost28147_89_CryptoPro_KeyMeshing 1 2 643 2 2 14 1 */ + 845, /* OBJ_id_GostR3410_94_a 1 2 643 2 2 20 1 */ + 846, /* OBJ_id_GostR3410_94_aBis 1 2 643 2 2 20 2 */ + 847, /* OBJ_id_GostR3410_94_b 1 2 643 2 2 20 3 */ + 848, /* OBJ_id_GostR3410_94_bBis 1 2 643 2 2 20 4 */ + 821, /* OBJ_id_GostR3411_94_TestParamSet 1 2 643 2 2 30 0 */ + 822, /* OBJ_id_GostR3411_94_CryptoProParamSet 1 2 643 2 2 30 1 */ + 823, /* OBJ_id_Gost28147_89_TestParamSet 1 2 643 2 2 31 0 */ + 824, /* OBJ_id_Gost28147_89_CryptoPro_A_ParamSet 1 2 643 2 2 31 1 */ + 825, /* OBJ_id_Gost28147_89_CryptoPro_B_ParamSet 1 2 643 2 2 31 2 */ + 826, /* OBJ_id_Gost28147_89_CryptoPro_C_ParamSet 1 2 643 2 2 31 3 */ + 827, /* OBJ_id_Gost28147_89_CryptoPro_D_ParamSet 1 2 643 2 2 31 4 */ + 828, /* OBJ_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet 1 2 643 2 2 31 5 */ + 829, /* OBJ_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet 1 2 643 2 2 31 6 */ + 830, /* OBJ_id_Gost28147_89_CryptoPro_RIC_1_ParamSet 1 2 643 2 2 31 7 */ + 831, /* OBJ_id_GostR3410_94_TestParamSet 1 2 643 2 2 32 0 */ + 832, /* OBJ_id_GostR3410_94_CryptoPro_A_ParamSet 1 2 643 2 2 32 2 */ + 833, /* OBJ_id_GostR3410_94_CryptoPro_B_ParamSet 1 2 643 2 2 32 3 */ + 834, /* OBJ_id_GostR3410_94_CryptoPro_C_ParamSet 1 2 643 2 2 32 4 */ + 835, /* OBJ_id_GostR3410_94_CryptoPro_D_ParamSet 1 2 643 2 2 32 5 */ + 836, /* OBJ_id_GostR3410_94_CryptoPro_XchA_ParamSet 1 2 643 2 2 33 1 */ + 837, /* OBJ_id_GostR3410_94_CryptoPro_XchB_ParamSet 1 2 643 2 2 33 2 */ + 838, /* OBJ_id_GostR3410_94_CryptoPro_XchC_ParamSet 1 2 643 2 2 33 3 */ + 839, /* OBJ_id_GostR3410_2001_TestParamSet 1 2 643 2 2 35 0 */ + 840, /* OBJ_id_GostR3410_2001_CryptoPro_A_ParamSet 1 2 643 2 2 35 1 */ + 841, /* OBJ_id_GostR3410_2001_CryptoPro_B_ParamSet 1 2 643 2 2 35 2 */ + 842, /* OBJ_id_GostR3410_2001_CryptoPro_C_ParamSet 1 2 643 2 2 35 3 */ + 843, /* OBJ_id_GostR3410_2001_CryptoPro_XchA_ParamSet 1 2 643 2 2 36 0 */ + 844, /* OBJ_id_GostR3410_2001_CryptoPro_XchB_ParamSet 1 2 643 2 2 36 1 */ + 978, /* OBJ_id_tc26_sign 1 2 643 7 1 1 1 */ + 981, /* OBJ_id_tc26_digest 1 2 643 7 1 1 2 */ + 984, /* OBJ_id_tc26_signwithdigest 1 2 643 7 1 1 3 */ + 987, /* OBJ_id_tc26_mac 1 2 643 7 1 1 4 */ + 990, /* OBJ_id_tc26_cipher 1 2 643 7 1 1 5 */ + 991, /* OBJ_id_tc26_agreement 1 2 643 7 1 1 6 */ + 1179, /* OBJ_id_tc26_wrap 1 2 643 7 1 1 7 */ + 995, /* OBJ_id_tc26_sign_constants 1 2 643 7 1 2 1 */ + 1000, /* OBJ_id_tc26_digest_constants 1 2 643 7 1 2 2 */ + 1001, /* OBJ_id_tc26_cipher_constants 1 2 643 7 1 2 5 */ + 1151, /* OBJ_ua_pki 1 2 804 2 1 1 1 */ + 2, /* OBJ_pkcs 1 2 840 113549 1 */ + 431, /* OBJ_hold_instruction_none 1 2 840 10040 2 1 */ + 432, /* OBJ_hold_instruction_call_issuer 1 2 840 10040 2 2 */ + 433, /* OBJ_hold_instruction_reject 1 2 840 10040 2 3 */ + 116, /* OBJ_dsa 1 2 840 10040 4 1 */ + 113, /* OBJ_dsaWithSHA1 1 2 840 10040 4 3 */ + 406, /* OBJ_X9_62_prime_field 1 2 840 10045 1 1 */ + 407, /* OBJ_X9_62_characteristic_two_field 1 2 840 10045 1 2 */ + 408, /* OBJ_X9_62_id_ecPublicKey 1 2 840 10045 2 1 */ + 416, /* OBJ_ecdsa_with_SHA1 1 2 840 10045 4 1 */ + 791, /* OBJ_ecdsa_with_Recommended 1 2 840 10045 4 2 */ + 792, /* OBJ_ecdsa_with_Specified 1 2 840 10045 4 3 */ + 920, /* OBJ_dhpublicnumber 1 2 840 10046 2 1 */ + 1032, /* OBJ_pkInitClientAuth 1 3 6 1 5 2 3 4 */ + 1033, /* OBJ_pkInitKDC 1 3 6 1 5 2 3 5 */ + 258, /* OBJ_id_pkix_mod 1 3 6 1 5 5 7 0 */ + 175, /* OBJ_id_pe 1 3 6 1 5 5 7 1 */ + 259, /* OBJ_id_qt 1 3 6 1 5 5 7 2 */ + 128, /* OBJ_id_kp 1 3 6 1 5 5 7 3 */ + 260, /* OBJ_id_it 1 3 6 1 5 5 7 4 */ + 261, /* OBJ_id_pkip 1 3 6 1 5 5 7 5 */ + 262, /* OBJ_id_alg 1 3 6 1 5 5 7 6 */ + 263, /* OBJ_id_cmc 1 3 6 1 5 5 7 7 */ + 264, /* OBJ_id_on 1 3 6 1 5 5 7 8 */ + 265, /* OBJ_id_pda 1 3 6 1 5 5 7 9 */ + 266, /* OBJ_id_aca 1 3 6 1 5 5 7 10 */ + 267, /* OBJ_id_qcs 1 3 6 1 5 5 7 11 */ + 268, /* OBJ_id_cct 1 3 6 1 5 5 7 12 */ + 662, /* OBJ_id_ppl 1 3 6 1 5 5 7 21 */ + 176, /* OBJ_id_ad 1 3 6 1 5 5 7 48 */ + 507, /* OBJ_id_hex_partial_message 1 3 6 1 7 1 1 1 */ + 508, /* OBJ_id_hex_multipart_message 1 3 6 1 7 1 1 2 */ + 57, /* OBJ_netscape 2 16 840 1 113730 */ + 754, /* OBJ_camellia_128_ecb 0 3 4401 5 3 1 9 1 */ + 766, /* OBJ_camellia_128_ofb128 0 3 4401 5 3 1 9 3 */ + 757, /* OBJ_camellia_128_cfb128 0 3 4401 5 3 1 9 4 */ + 961, /* OBJ_camellia_128_gcm 0 3 4401 5 3 1 9 6 */ + 962, /* OBJ_camellia_128_ccm 0 3 4401 5 3 1 9 7 */ + 963, /* OBJ_camellia_128_ctr 0 3 4401 5 3 1 9 9 */ + 964, /* OBJ_camellia_128_cmac 0 3 4401 5 3 1 9 10 */ + 755, /* OBJ_camellia_192_ecb 0 3 4401 5 3 1 9 21 */ + 767, /* OBJ_camellia_192_ofb128 0 3 4401 5 3 1 9 23 */ + 758, /* OBJ_camellia_192_cfb128 0 3 4401 5 3 1 9 24 */ + 965, /* OBJ_camellia_192_gcm 0 3 4401 5 3 1 9 26 */ + 966, /* OBJ_camellia_192_ccm 0 3 4401 5 3 1 9 27 */ + 967, /* OBJ_camellia_192_ctr 0 3 4401 5 3 1 9 29 */ + 968, /* OBJ_camellia_192_cmac 0 3 4401 5 3 1 9 30 */ + 756, /* OBJ_camellia_256_ecb 0 3 4401 5 3 1 9 41 */ + 768, /* OBJ_camellia_256_ofb128 0 3 4401 5 3 1 9 43 */ + 759, /* OBJ_camellia_256_cfb128 0 3 4401 5 3 1 9 44 */ + 969, /* OBJ_camellia_256_gcm 0 3 4401 5 3 1 9 46 */ + 970, /* OBJ_camellia_256_ccm 0 3 4401 5 3 1 9 47 */ + 971, /* OBJ_camellia_256_ctr 0 3 4401 5 3 1 9 49 */ + 972, /* OBJ_camellia_256_cmac 0 3 4401 5 3 1 9 50 */ + 437, /* OBJ_pilot 0 9 2342 19200300 100 */ + 1133, /* OBJ_sm4_ecb 1 2 156 10197 1 104 1 */ + 1134, /* OBJ_sm4_cbc 1 2 156 10197 1 104 2 */ + 1135, /* OBJ_sm4_ofb128 1 2 156 10197 1 104 3 */ + 1137, /* OBJ_sm4_cfb128 1 2 156 10197 1 104 4 */ + 1136, /* OBJ_sm4_cfb1 1 2 156 10197 1 104 5 */ + 1138, /* OBJ_sm4_cfb8 1 2 156 10197 1 104 6 */ + 1139, /* OBJ_sm4_ctr 1 2 156 10197 1 104 7 */ + 1172, /* OBJ_sm2 1 2 156 10197 1 301 */ + 1143, /* OBJ_sm3 1 2 156 10197 1 401 */ + 1144, /* OBJ_sm3WithRSAEncryption 1 2 156 10197 1 504 */ + 776, /* OBJ_seed_ecb 1 2 410 200004 1 3 */ + 777, /* OBJ_seed_cbc 1 2 410 200004 1 4 */ + 779, /* OBJ_seed_cfb128 1 2 410 200004 1 5 */ + 778, /* OBJ_seed_ofb128 1 2 410 200004 1 6 */ + 852, /* OBJ_id_GostR3411_94_with_GostR3410_94_cc 1 2 643 2 9 1 3 3 */ + 853, /* OBJ_id_GostR3411_94_with_GostR3410_2001_cc 1 2 643 2 9 1 3 4 */ + 850, /* OBJ_id_GostR3410_94_cc 1 2 643 2 9 1 5 3 */ + 851, /* OBJ_id_GostR3410_2001_cc 1 2 643 2 9 1 5 4 */ + 849, /* OBJ_id_Gost28147_89_cc 1 2 643 2 9 1 6 1 */ + 854, /* OBJ_id_GostR3410_2001_ParamSet_cc 1 2 643 2 9 1 8 1 */ + 1004, /* OBJ_INN 1 2 643 3 131 1 1 */ + 979, /* OBJ_id_GostR3410_2012_256 1 2 643 7 1 1 1 1 */ + 980, /* OBJ_id_GostR3410_2012_512 1 2 643 7 1 1 1 2 */ + 982, /* OBJ_id_GostR3411_2012_256 1 2 643 7 1 1 2 2 */ + 983, /* OBJ_id_GostR3411_2012_512 1 2 643 7 1 1 2 3 */ + 985, /* OBJ_id_tc26_signwithdigest_gost3410_2012_256 1 2 643 7 1 1 3 2 */ + 986, /* OBJ_id_tc26_signwithdigest_gost3410_2012_512 1 2 643 7 1 1 3 3 */ + 988, /* OBJ_id_tc26_hmac_gost_3411_2012_256 1 2 643 7 1 1 4 1 */ + 989, /* OBJ_id_tc26_hmac_gost_3411_2012_512 1 2 643 7 1 1 4 2 */ + 1173, /* OBJ_id_tc26_cipher_gostr3412_2015_magma 1 2 643 7 1 1 5 1 */ + 1176, /* OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik 1 2 643 7 1 1 5 2 */ + 992, /* OBJ_id_tc26_agreement_gost_3410_2012_256 1 2 643 7 1 1 6 1 */ + 993, /* OBJ_id_tc26_agreement_gost_3410_2012_512 1 2 643 7 1 1 6 2 */ + 1180, /* OBJ_id_tc26_wrap_gostr3412_2015_magma 1 2 643 7 1 1 7 1 */ + 1182, /* OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik 1 2 643 7 1 1 7 2 */ + 1147, /* OBJ_id_tc26_gost_3410_2012_256_constants 1 2 643 7 1 2 1 1 */ + 996, /* OBJ_id_tc26_gost_3410_2012_512_constants 1 2 643 7 1 2 1 2 */ + 1002, /* OBJ_id_tc26_gost_28147_constants 1 2 643 7 1 2 5 1 */ + 186, /* OBJ_pkcs1 1 2 840 113549 1 1 */ + 27, /* OBJ_pkcs3 1 2 840 113549 1 3 */ + 187, /* OBJ_pkcs5 1 2 840 113549 1 5 */ + 20, /* OBJ_pkcs7 1 2 840 113549 1 7 */ + 47, /* OBJ_pkcs9 1 2 840 113549 1 9 */ + 3, /* OBJ_md2 1 2 840 113549 2 2 */ + 257, /* OBJ_md4 1 2 840 113549 2 4 */ + 4, /* OBJ_md5 1 2 840 113549 2 5 */ + 797, /* OBJ_hmacWithMD5 1 2 840 113549 2 6 */ + 163, /* OBJ_hmacWithSHA1 1 2 840 113549 2 7 */ + 798, /* OBJ_hmacWithSHA224 1 2 840 113549 2 8 */ + 799, /* OBJ_hmacWithSHA256 1 2 840 113549 2 9 */ + 800, /* OBJ_hmacWithSHA384 1 2 840 113549 2 10 */ + 801, /* OBJ_hmacWithSHA512 1 2 840 113549 2 11 */ + 1193, /* OBJ_hmacWithSHA512_224 1 2 840 113549 2 12 */ + 1194, /* OBJ_hmacWithSHA512_256 1 2 840 113549 2 13 */ + 37, /* OBJ_rc2_cbc 1 2 840 113549 3 2 */ + 5, /* OBJ_rc4 1 2 840 113549 3 4 */ + 44, /* OBJ_des_ede3_cbc 1 2 840 113549 3 7 */ + 120, /* OBJ_rc5_cbc 1 2 840 113549 3 8 */ + 643, /* OBJ_des_cdmf 1 2 840 113549 3 10 */ + 680, /* OBJ_X9_62_id_characteristic_two_basis 1 2 840 10045 1 2 3 */ + 684, /* OBJ_X9_62_c2pnb163v1 1 2 840 10045 3 0 1 */ + 685, /* OBJ_X9_62_c2pnb163v2 1 2 840 10045 3 0 2 */ + 686, /* OBJ_X9_62_c2pnb163v3 1 2 840 10045 3 0 3 */ + 687, /* OBJ_X9_62_c2pnb176v1 1 2 840 10045 3 0 4 */ + 688, /* OBJ_X9_62_c2tnb191v1 1 2 840 10045 3 0 5 */ + 689, /* OBJ_X9_62_c2tnb191v2 1 2 840 10045 3 0 6 */ + 690, /* OBJ_X9_62_c2tnb191v3 1 2 840 10045 3 0 7 */ + 691, /* OBJ_X9_62_c2onb191v4 1 2 840 10045 3 0 8 */ + 692, /* OBJ_X9_62_c2onb191v5 1 2 840 10045 3 0 9 */ + 693, /* OBJ_X9_62_c2pnb208w1 1 2 840 10045 3 0 10 */ + 694, /* OBJ_X9_62_c2tnb239v1 1 2 840 10045 3 0 11 */ + 695, /* OBJ_X9_62_c2tnb239v2 1 2 840 10045 3 0 12 */ + 696, /* OBJ_X9_62_c2tnb239v3 1 2 840 10045 3 0 13 */ + 697, /* OBJ_X9_62_c2onb239v4 1 2 840 10045 3 0 14 */ + 698, /* OBJ_X9_62_c2onb239v5 1 2 840 10045 3 0 15 */ + 699, /* OBJ_X9_62_c2pnb272w1 1 2 840 10045 3 0 16 */ + 700, /* OBJ_X9_62_c2pnb304w1 1 2 840 10045 3 0 17 */ + 701, /* OBJ_X9_62_c2tnb359v1 1 2 840 10045 3 0 18 */ + 702, /* OBJ_X9_62_c2pnb368w1 1 2 840 10045 3 0 19 */ + 703, /* OBJ_X9_62_c2tnb431r1 1 2 840 10045 3 0 20 */ + 409, /* OBJ_X9_62_prime192v1 1 2 840 10045 3 1 1 */ + 410, /* OBJ_X9_62_prime192v2 1 2 840 10045 3 1 2 */ + 411, /* OBJ_X9_62_prime192v3 1 2 840 10045 3 1 3 */ + 412, /* OBJ_X9_62_prime239v1 1 2 840 10045 3 1 4 */ + 413, /* OBJ_X9_62_prime239v2 1 2 840 10045 3 1 5 */ + 414, /* OBJ_X9_62_prime239v3 1 2 840 10045 3 1 6 */ + 415, /* OBJ_X9_62_prime256v1 1 2 840 10045 3 1 7 */ + 793, /* OBJ_ecdsa_with_SHA224 1 2 840 10045 4 3 1 */ + 794, /* OBJ_ecdsa_with_SHA256 1 2 840 10045 4 3 2 */ + 795, /* OBJ_ecdsa_with_SHA384 1 2 840 10045 4 3 3 */ + 796, /* OBJ_ecdsa_with_SHA512 1 2 840 10045 4 3 4 */ + 269, /* OBJ_id_pkix1_explicit_88 1 3 6 1 5 5 7 0 1 */ + 270, /* OBJ_id_pkix1_implicit_88 1 3 6 1 5 5 7 0 2 */ + 271, /* OBJ_id_pkix1_explicit_93 1 3 6 1 5 5 7 0 3 */ + 272, /* OBJ_id_pkix1_implicit_93 1 3 6 1 5 5 7 0 4 */ + 273, /* OBJ_id_mod_crmf 1 3 6 1 5 5 7 0 5 */ + 274, /* OBJ_id_mod_cmc 1 3 6 1 5 5 7 0 6 */ + 275, /* OBJ_id_mod_kea_profile_88 1 3 6 1 5 5 7 0 7 */ + 276, /* OBJ_id_mod_kea_profile_93 1 3 6 1 5 5 7 0 8 */ + 277, /* OBJ_id_mod_cmp 1 3 6 1 5 5 7 0 9 */ + 278, /* OBJ_id_mod_qualified_cert_88 1 3 6 1 5 5 7 0 10 */ + 279, /* OBJ_id_mod_qualified_cert_93 1 3 6 1 5 5 7 0 11 */ + 280, /* OBJ_id_mod_attribute_cert 1 3 6 1 5 5 7 0 12 */ + 281, /* OBJ_id_mod_timestamp_protocol 1 3 6 1 5 5 7 0 13 */ + 282, /* OBJ_id_mod_ocsp 1 3 6 1 5 5 7 0 14 */ + 283, /* OBJ_id_mod_dvcs 1 3 6 1 5 5 7 0 15 */ + 284, /* OBJ_id_mod_cmp2000 1 3 6 1 5 5 7 0 16 */ + 177, /* OBJ_info_access 1 3 6 1 5 5 7 1 1 */ + 285, /* OBJ_biometricInfo 1 3 6 1 5 5 7 1 2 */ + 286, /* OBJ_qcStatements 1 3 6 1 5 5 7 1 3 */ + 287, /* OBJ_ac_auditEntity 1 3 6 1 5 5 7 1 4 */ + 288, /* OBJ_ac_targeting 1 3 6 1 5 5 7 1 5 */ + 289, /* OBJ_aaControls 1 3 6 1 5 5 7 1 6 */ + 290, /* OBJ_sbgp_ipAddrBlock 1 3 6 1 5 5 7 1 7 */ + 291, /* OBJ_sbgp_autonomousSysNum 1 3 6 1 5 5 7 1 8 */ + 292, /* OBJ_sbgp_routerIdentifier 1 3 6 1 5 5 7 1 9 */ + 397, /* OBJ_ac_proxying 1 3 6 1 5 5 7 1 10 */ + 398, /* OBJ_sinfo_access 1 3 6 1 5 5 7 1 11 */ + 663, /* OBJ_proxyCertInfo 1 3 6 1 5 5 7 1 14 */ + 1020, /* OBJ_tlsfeature 1 3 6 1 5 5 7 1 24 */ + 164, /* OBJ_id_qt_cps 1 3 6 1 5 5 7 2 1 */ + 165, /* OBJ_id_qt_unotice 1 3 6 1 5 5 7 2 2 */ + 293, /* OBJ_textNotice 1 3 6 1 5 5 7 2 3 */ + 129, /* OBJ_server_auth 1 3 6 1 5 5 7 3 1 */ + 130, /* OBJ_client_auth 1 3 6 1 5 5 7 3 2 */ + 131, /* OBJ_code_sign 1 3 6 1 5 5 7 3 3 */ + 132, /* OBJ_email_protect 1 3 6 1 5 5 7 3 4 */ + 294, /* OBJ_ipsecEndSystem 1 3 6 1 5 5 7 3 5 */ + 295, /* OBJ_ipsecTunnel 1 3 6 1 5 5 7 3 6 */ + 296, /* OBJ_ipsecUser 1 3 6 1 5 5 7 3 7 */ + 133, /* OBJ_time_stamp 1 3 6 1 5 5 7 3 8 */ + 180, /* OBJ_OCSP_sign 1 3 6 1 5 5 7 3 9 */ + 297, /* OBJ_dvcs 1 3 6 1 5 5 7 3 10 */ + 1022, /* OBJ_ipsec_IKE 1 3 6 1 5 5 7 3 17 */ + 1023, /* OBJ_capwapAC 1 3 6 1 5 5 7 3 18 */ + 1024, /* OBJ_capwapWTP 1 3 6 1 5 5 7 3 19 */ + 1025, /* OBJ_sshClient 1 3 6 1 5 5 7 3 21 */ + 1026, /* OBJ_sshServer 1 3 6 1 5 5 7 3 22 */ + 1027, /* OBJ_sendRouter 1 3 6 1 5 5 7 3 23 */ + 1028, /* OBJ_sendProxiedRouter 1 3 6 1 5 5 7 3 24 */ + 1029, /* OBJ_sendOwner 1 3 6 1 5 5 7 3 25 */ + 1030, /* OBJ_sendProxiedOwner 1 3 6 1 5 5 7 3 26 */ + 1131, /* OBJ_cmcCA 1 3 6 1 5 5 7 3 27 */ + 1132, /* OBJ_cmcRA 1 3 6 1 5 5 7 3 28 */ + 298, /* OBJ_id_it_caProtEncCert 1 3 6 1 5 5 7 4 1 */ + 299, /* OBJ_id_it_signKeyPairTypes 1 3 6 1 5 5 7 4 2 */ + 300, /* OBJ_id_it_encKeyPairTypes 1 3 6 1 5 5 7 4 3 */ + 301, /* OBJ_id_it_preferredSymmAlg 1 3 6 1 5 5 7 4 4 */ + 302, /* OBJ_id_it_caKeyUpdateInfo 1 3 6 1 5 5 7 4 5 */ + 303, /* OBJ_id_it_currentCRL 1 3 6 1 5 5 7 4 6 */ + 304, /* OBJ_id_it_unsupportedOIDs 1 3 6 1 5 5 7 4 7 */ + 305, /* OBJ_id_it_subscriptionRequest 1 3 6 1 5 5 7 4 8 */ + 306, /* OBJ_id_it_subscriptionResponse 1 3 6 1 5 5 7 4 9 */ + 307, /* OBJ_id_it_keyPairParamReq 1 3 6 1 5 5 7 4 10 */ + 308, /* OBJ_id_it_keyPairParamRep 1 3 6 1 5 5 7 4 11 */ + 309, /* OBJ_id_it_revPassphrase 1 3 6 1 5 5 7 4 12 */ + 310, /* OBJ_id_it_implicitConfirm 1 3 6 1 5 5 7 4 13 */ + 311, /* OBJ_id_it_confirmWaitTime 1 3 6 1 5 5 7 4 14 */ + 312, /* OBJ_id_it_origPKIMessage 1 3 6 1 5 5 7 4 15 */ + 784, /* OBJ_id_it_suppLangTags 1 3 6 1 5 5 7 4 16 */ + 313, /* OBJ_id_regCtrl 1 3 6 1 5 5 7 5 1 */ + 314, /* OBJ_id_regInfo 1 3 6 1 5 5 7 5 2 */ + 323, /* OBJ_id_alg_des40 1 3 6 1 5 5 7 6 1 */ + 324, /* OBJ_id_alg_noSignature 1 3 6 1 5 5 7 6 2 */ + 325, /* OBJ_id_alg_dh_sig_hmac_sha1 1 3 6 1 5 5 7 6 3 */ + 326, /* OBJ_id_alg_dh_pop 1 3 6 1 5 5 7 6 4 */ + 327, /* OBJ_id_cmc_statusInfo 1 3 6 1 5 5 7 7 1 */ + 328, /* OBJ_id_cmc_identification 1 3 6 1 5 5 7 7 2 */ + 329, /* OBJ_id_cmc_identityProof 1 3 6 1 5 5 7 7 3 */ + 330, /* OBJ_id_cmc_dataReturn 1 3 6 1 5 5 7 7 4 */ + 331, /* OBJ_id_cmc_transactionId 1 3 6 1 5 5 7 7 5 */ + 332, /* OBJ_id_cmc_senderNonce 1 3 6 1 5 5 7 7 6 */ + 333, /* OBJ_id_cmc_recipientNonce 1 3 6 1 5 5 7 7 7 */ + 334, /* OBJ_id_cmc_addExtensions 1 3 6 1 5 5 7 7 8 */ + 335, /* OBJ_id_cmc_encryptedPOP 1 3 6 1 5 5 7 7 9 */ + 336, /* OBJ_id_cmc_decryptedPOP 1 3 6 1 5 5 7 7 10 */ + 337, /* OBJ_id_cmc_lraPOPWitness 1 3 6 1 5 5 7 7 11 */ + 338, /* OBJ_id_cmc_getCert 1 3 6 1 5 5 7 7 15 */ + 339, /* OBJ_id_cmc_getCRL 1 3 6 1 5 5 7 7 16 */ + 340, /* OBJ_id_cmc_revokeRequest 1 3 6 1 5 5 7 7 17 */ + 341, /* OBJ_id_cmc_regInfo 1 3 6 1 5 5 7 7 18 */ + 342, /* OBJ_id_cmc_responseInfo 1 3 6 1 5 5 7 7 19 */ + 343, /* OBJ_id_cmc_queryPending 1 3 6 1 5 5 7 7 21 */ + 344, /* OBJ_id_cmc_popLinkRandom 1 3 6 1 5 5 7 7 22 */ + 345, /* OBJ_id_cmc_popLinkWitness 1 3 6 1 5 5 7 7 23 */ + 346, /* OBJ_id_cmc_confirmCertAcceptance 1 3 6 1 5 5 7 7 24 */ + 347, /* OBJ_id_on_personalData 1 3 6 1 5 5 7 8 1 */ + 858, /* OBJ_id_on_permanentIdentifier 1 3 6 1 5 5 7 8 3 */ + 348, /* OBJ_id_pda_dateOfBirth 1 3 6 1 5 5 7 9 1 */ + 349, /* OBJ_id_pda_placeOfBirth 1 3 6 1 5 5 7 9 2 */ + 351, /* OBJ_id_pda_gender 1 3 6 1 5 5 7 9 3 */ + 352, /* OBJ_id_pda_countryOfCitizenship 1 3 6 1 5 5 7 9 4 */ + 353, /* OBJ_id_pda_countryOfResidence 1 3 6 1 5 5 7 9 5 */ + 354, /* OBJ_id_aca_authenticationInfo 1 3 6 1 5 5 7 10 1 */ + 355, /* OBJ_id_aca_accessIdentity 1 3 6 1 5 5 7 10 2 */ + 356, /* OBJ_id_aca_chargingIdentity 1 3 6 1 5 5 7 10 3 */ + 357, /* OBJ_id_aca_group 1 3 6 1 5 5 7 10 4 */ + 358, /* OBJ_id_aca_role 1 3 6 1 5 5 7 10 5 */ + 399, /* OBJ_id_aca_encAttrs 1 3 6 1 5 5 7 10 6 */ + 359, /* OBJ_id_qcs_pkixQCSyntax_v1 1 3 6 1 5 5 7 11 1 */ + 360, /* OBJ_id_cct_crs 1 3 6 1 5 5 7 12 1 */ + 361, /* OBJ_id_cct_PKIData 1 3 6 1 5 5 7 12 2 */ + 362, /* OBJ_id_cct_PKIResponse 1 3 6 1 5 5 7 12 3 */ + 664, /* OBJ_id_ppl_anyLanguage 1 3 6 1 5 5 7 21 0 */ + 665, /* OBJ_id_ppl_inheritAll 1 3 6 1 5 5 7 21 1 */ + 667, /* OBJ_Independent 1 3 6 1 5 5 7 21 2 */ + 178, /* OBJ_ad_OCSP 1 3 6 1 5 5 7 48 1 */ + 179, /* OBJ_ad_ca_issuers 1 3 6 1 5 5 7 48 2 */ + 363, /* OBJ_ad_timeStamping 1 3 6 1 5 5 7 48 3 */ + 364, /* OBJ_ad_dvcs 1 3 6 1 5 5 7 48 4 */ + 785, /* OBJ_caRepository 1 3 6 1 5 5 7 48 5 */ + 780, /* OBJ_hmac_md5 1 3 6 1 5 5 8 1 1 */ + 781, /* OBJ_hmac_sha1 1 3 6 1 5 5 8 1 2 */ + 913, /* OBJ_aes_128_xts 1 3 111 2 1619 0 1 1 */ + 914, /* OBJ_aes_256_xts 1 3 111 2 1619 0 1 2 */ + 58, /* OBJ_netscape_cert_extension 2 16 840 1 113730 1 */ + 59, /* OBJ_netscape_data_type 2 16 840 1 113730 2 */ + 438, /* OBJ_pilotAttributeType 0 9 2342 19200300 100 1 */ + 439, /* OBJ_pilotAttributeSyntax 0 9 2342 19200300 100 3 */ + 440, /* OBJ_pilotObjectClass 0 9 2342 19200300 100 4 */ + 441, /* OBJ_pilotGroups 0 9 2342 19200300 100 10 */ + 1065, /* OBJ_aria_128_ecb 1 2 410 200046 1 1 1 */ + 1066, /* OBJ_aria_128_cbc 1 2 410 200046 1 1 2 */ + 1067, /* OBJ_aria_128_cfb128 1 2 410 200046 1 1 3 */ + 1068, /* OBJ_aria_128_ofb128 1 2 410 200046 1 1 4 */ + 1069, /* OBJ_aria_128_ctr 1 2 410 200046 1 1 5 */ + 1070, /* OBJ_aria_192_ecb 1 2 410 200046 1 1 6 */ + 1071, /* OBJ_aria_192_cbc 1 2 410 200046 1 1 7 */ + 1072, /* OBJ_aria_192_cfb128 1 2 410 200046 1 1 8 */ + 1073, /* OBJ_aria_192_ofb128 1 2 410 200046 1 1 9 */ + 1074, /* OBJ_aria_192_ctr 1 2 410 200046 1 1 10 */ + 1075, /* OBJ_aria_256_ecb 1 2 410 200046 1 1 11 */ + 1076, /* OBJ_aria_256_cbc 1 2 410 200046 1 1 12 */ + 1077, /* OBJ_aria_256_cfb128 1 2 410 200046 1 1 13 */ + 1078, /* OBJ_aria_256_ofb128 1 2 410 200046 1 1 14 */ + 1079, /* OBJ_aria_256_ctr 1 2 410 200046 1 1 15 */ + 1123, /* OBJ_aria_128_gcm 1 2 410 200046 1 1 34 */ + 1124, /* OBJ_aria_192_gcm 1 2 410 200046 1 1 35 */ + 1125, /* OBJ_aria_256_gcm 1 2 410 200046 1 1 36 */ + 1120, /* OBJ_aria_128_ccm 1 2 410 200046 1 1 37 */ + 1121, /* OBJ_aria_192_ccm 1 2 410 200046 1 1 38 */ + 1122, /* OBJ_aria_256_ccm 1 2 410 200046 1 1 39 */ + 1174, /* OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm 1 2 643 7 1 1 5 1 1 */ + 1175, /* OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac 1 2 643 7 1 1 5 1 2 */ + 1177, /* OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm 1 2 643 7 1 1 5 2 1 */ + 1178, /* OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac 1 2 643 7 1 1 5 2 2 */ + 1181, /* OBJ_id_tc26_wrap_gostr3412_2015_magma_kexp15 1 2 643 7 1 1 7 1 1 */ + 1183, /* OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 1 2 643 7 1 1 7 1 1 */ + 1148, /* OBJ_id_tc26_gost_3410_2012_256_paramSetA 1 2 643 7 1 2 1 1 1 */ + 1184, /* OBJ_id_tc26_gost_3410_2012_256_paramSetB 1 2 643 7 1 2 1 1 2 */ + 1185, /* OBJ_id_tc26_gost_3410_2012_256_paramSetC 1 2 643 7 1 2 1 1 3 */ + 1186, /* OBJ_id_tc26_gost_3410_2012_256_paramSetD 1 2 643 7 1 2 1 1 4 */ + 997, /* OBJ_id_tc26_gost_3410_2012_512_paramSetTest 1 2 643 7 1 2 1 2 0 */ + 998, /* OBJ_id_tc26_gost_3410_2012_512_paramSetA 1 2 643 7 1 2 1 2 1 */ + 999, /* OBJ_id_tc26_gost_3410_2012_512_paramSetB 1 2 643 7 1 2 1 2 2 */ + 1149, /* OBJ_id_tc26_gost_3410_2012_512_paramSetC 1 2 643 7 1 2 1 2 3 */ + 1003, /* OBJ_id_tc26_gost_28147_param_Z 1 2 643 7 1 2 5 1 1 */ + 108, /* OBJ_cast5_cbc 1 2 840 113533 7 66 10 */ + 112, /* OBJ_pbeWithMD5AndCast5_CBC 1 2 840 113533 7 66 12 */ + 782, /* OBJ_id_PasswordBasedMAC 1 2 840 113533 7 66 13 */ + 783, /* OBJ_id_DHBasedMac 1 2 840 113533 7 66 30 */ + 6, /* OBJ_rsaEncryption 1 2 840 113549 1 1 1 */ + 7, /* OBJ_md2WithRSAEncryption 1 2 840 113549 1 1 2 */ + 396, /* OBJ_md4WithRSAEncryption 1 2 840 113549 1 1 3 */ + 8, /* OBJ_md5WithRSAEncryption 1 2 840 113549 1 1 4 */ + 65, /* OBJ_sha1WithRSAEncryption 1 2 840 113549 1 1 5 */ + 644, /* OBJ_rsaOAEPEncryptionSET 1 2 840 113549 1 1 6 */ + 919, /* OBJ_rsaesOaep 1 2 840 113549 1 1 7 */ + 911, /* OBJ_mgf1 1 2 840 113549 1 1 8 */ + 935, /* OBJ_pSpecified 1 2 840 113549 1 1 9 */ + 912, /* OBJ_rsassaPss 1 2 840 113549 1 1 10 */ + 668, /* OBJ_sha256WithRSAEncryption 1 2 840 113549 1 1 11 */ + 669, /* OBJ_sha384WithRSAEncryption 1 2 840 113549 1 1 12 */ + 670, /* OBJ_sha512WithRSAEncryption 1 2 840 113549 1 1 13 */ + 671, /* OBJ_sha224WithRSAEncryption 1 2 840 113549 1 1 14 */ + 1145, /* OBJ_sha512_224WithRSAEncryption 1 2 840 113549 1 1 15 */ + 1146, /* OBJ_sha512_256WithRSAEncryption 1 2 840 113549 1 1 16 */ + 28, /* OBJ_dhKeyAgreement 1 2 840 113549 1 3 1 */ + 9, /* OBJ_pbeWithMD2AndDES_CBC 1 2 840 113549 1 5 1 */ + 10, /* OBJ_pbeWithMD5AndDES_CBC 1 2 840 113549 1 5 3 */ + 168, /* OBJ_pbeWithMD2AndRC2_CBC 1 2 840 113549 1 5 4 */ + 169, /* OBJ_pbeWithMD5AndRC2_CBC 1 2 840 113549 1 5 6 */ + 170, /* OBJ_pbeWithSHA1AndDES_CBC 1 2 840 113549 1 5 10 */ + 68, /* OBJ_pbeWithSHA1AndRC2_CBC 1 2 840 113549 1 5 11 */ + 69, /* OBJ_id_pbkdf2 1 2 840 113549 1 5 12 */ + 161, /* OBJ_pbes2 1 2 840 113549 1 5 13 */ + 162, /* OBJ_pbmac1 1 2 840 113549 1 5 14 */ + 21, /* OBJ_pkcs7_data 1 2 840 113549 1 7 1 */ + 22, /* OBJ_pkcs7_signed 1 2 840 113549 1 7 2 */ + 23, /* OBJ_pkcs7_enveloped 1 2 840 113549 1 7 3 */ + 24, /* OBJ_pkcs7_signedAndEnveloped 1 2 840 113549 1 7 4 */ + 25, /* OBJ_pkcs7_digest 1 2 840 113549 1 7 5 */ + 26, /* OBJ_pkcs7_encrypted 1 2 840 113549 1 7 6 */ + 48, /* OBJ_pkcs9_emailAddress 1 2 840 113549 1 9 1 */ + 49, /* OBJ_pkcs9_unstructuredName 1 2 840 113549 1 9 2 */ + 50, /* OBJ_pkcs9_contentType 1 2 840 113549 1 9 3 */ + 51, /* OBJ_pkcs9_messageDigest 1 2 840 113549 1 9 4 */ + 52, /* OBJ_pkcs9_signingTime 1 2 840 113549 1 9 5 */ + 53, /* OBJ_pkcs9_countersignature 1 2 840 113549 1 9 6 */ + 54, /* OBJ_pkcs9_challengePassword 1 2 840 113549 1 9 7 */ + 55, /* OBJ_pkcs9_unstructuredAddress 1 2 840 113549 1 9 8 */ + 56, /* OBJ_pkcs9_extCertAttributes 1 2 840 113549 1 9 9 */ + 172, /* OBJ_ext_req 1 2 840 113549 1 9 14 */ + 167, /* OBJ_SMIMECapabilities 1 2 840 113549 1 9 15 */ + 188, /* OBJ_SMIME 1 2 840 113549 1 9 16 */ + 156, /* OBJ_friendlyName 1 2 840 113549 1 9 20 */ + 157, /* OBJ_localKeyID 1 2 840 113549 1 9 21 */ + 681, /* OBJ_X9_62_onBasis 1 2 840 10045 1 2 3 1 */ + 682, /* OBJ_X9_62_tpBasis 1 2 840 10045 1 2 3 2 */ + 683, /* OBJ_X9_62_ppBasis 1 2 840 10045 1 2 3 3 */ + 417, /* OBJ_ms_csp_name 1 3 6 1 4 1 311 17 1 */ + 856, /* OBJ_LocalKeySet 1 3 6 1 4 1 311 17 2 */ + 390, /* OBJ_dcObject 1 3 6 1 4 1 1466 344 */ + 91, /* OBJ_bf_cbc 1 3 6 1 4 1 3029 1 2 */ + 973, /* OBJ_id_scrypt 1 3 6 1 4 1 11591 4 11 */ + 315, /* OBJ_id_regCtrl_regToken 1 3 6 1 5 5 7 5 1 1 */ + 316, /* OBJ_id_regCtrl_authenticator 1 3 6 1 5 5 7 5 1 2 */ + 317, /* OBJ_id_regCtrl_pkiPublicationInfo 1 3 6 1 5 5 7 5 1 3 */ + 318, /* OBJ_id_regCtrl_pkiArchiveOptions 1 3 6 1 5 5 7 5 1 4 */ + 319, /* OBJ_id_regCtrl_oldCertID 1 3 6 1 5 5 7 5 1 5 */ + 320, /* OBJ_id_regCtrl_protocolEncrKey 1 3 6 1 5 5 7 5 1 6 */ + 321, /* OBJ_id_regInfo_utf8Pairs 1 3 6 1 5 5 7 5 2 1 */ + 322, /* OBJ_id_regInfo_certReq 1 3 6 1 5 5 7 5 2 2 */ + 365, /* OBJ_id_pkix_OCSP_basic 1 3 6 1 5 5 7 48 1 1 */ + 366, /* OBJ_id_pkix_OCSP_Nonce 1 3 6 1 5 5 7 48 1 2 */ + 367, /* OBJ_id_pkix_OCSP_CrlID 1 3 6 1 5 5 7 48 1 3 */ + 368, /* OBJ_id_pkix_OCSP_acceptableResponses 1 3 6 1 5 5 7 48 1 4 */ + 369, /* OBJ_id_pkix_OCSP_noCheck 1 3 6 1 5 5 7 48 1 5 */ + 370, /* OBJ_id_pkix_OCSP_archiveCutoff 1 3 6 1 5 5 7 48 1 6 */ + 371, /* OBJ_id_pkix_OCSP_serviceLocator 1 3 6 1 5 5 7 48 1 7 */ + 372, /* OBJ_id_pkix_OCSP_extendedStatus 1 3 6 1 5 5 7 48 1 8 */ + 373, /* OBJ_id_pkix_OCSP_valid 1 3 6 1 5 5 7 48 1 9 */ + 374, /* OBJ_id_pkix_OCSP_path 1 3 6 1 5 5 7 48 1 10 */ + 375, /* OBJ_id_pkix_OCSP_trustRoot 1 3 6 1 5 5 7 48 1 11 */ + 921, /* OBJ_brainpoolP160r1 1 3 36 3 3 2 8 1 1 1 */ + 922, /* OBJ_brainpoolP160t1 1 3 36 3 3 2 8 1 1 2 */ + 923, /* OBJ_brainpoolP192r1 1 3 36 3 3 2 8 1 1 3 */ + 924, /* OBJ_brainpoolP192t1 1 3 36 3 3 2 8 1 1 4 */ + 925, /* OBJ_brainpoolP224r1 1 3 36 3 3 2 8 1 1 5 */ + 926, /* OBJ_brainpoolP224t1 1 3 36 3 3 2 8 1 1 6 */ + 927, /* OBJ_brainpoolP256r1 1 3 36 3 3 2 8 1 1 7 */ + 928, /* OBJ_brainpoolP256t1 1 3 36 3 3 2 8 1 1 8 */ + 929, /* OBJ_brainpoolP320r1 1 3 36 3 3 2 8 1 1 9 */ + 930, /* OBJ_brainpoolP320t1 1 3 36 3 3 2 8 1 1 10 */ + 931, /* OBJ_brainpoolP384r1 1 3 36 3 3 2 8 1 1 11 */ + 932, /* OBJ_brainpoolP384t1 1 3 36 3 3 2 8 1 1 12 */ + 933, /* OBJ_brainpoolP512r1 1 3 36 3 3 2 8 1 1 13 */ + 934, /* OBJ_brainpoolP512t1 1 3 36 3 3 2 8 1 1 14 */ + 936, /* OBJ_dhSinglePass_stdDH_sha1kdf_scheme 1 3 133 16 840 63 0 2 */ + 941, /* OBJ_dhSinglePass_cofactorDH_sha1kdf_scheme 1 3 133 16 840 63 0 3 */ + 418, /* OBJ_aes_128_ecb 2 16 840 1 101 3 4 1 1 */ + 419, /* OBJ_aes_128_cbc 2 16 840 1 101 3 4 1 2 */ + 420, /* OBJ_aes_128_ofb128 2 16 840 1 101 3 4 1 3 */ + 421, /* OBJ_aes_128_cfb128 2 16 840 1 101 3 4 1 4 */ + 788, /* OBJ_id_aes128_wrap 2 16 840 1 101 3 4 1 5 */ + 895, /* OBJ_aes_128_gcm 2 16 840 1 101 3 4 1 6 */ + 896, /* OBJ_aes_128_ccm 2 16 840 1 101 3 4 1 7 */ + 897, /* OBJ_id_aes128_wrap_pad 2 16 840 1 101 3 4 1 8 */ + 422, /* OBJ_aes_192_ecb 2 16 840 1 101 3 4 1 21 */ + 423, /* OBJ_aes_192_cbc 2 16 840 1 101 3 4 1 22 */ + 424, /* OBJ_aes_192_ofb128 2 16 840 1 101 3 4 1 23 */ + 425, /* OBJ_aes_192_cfb128 2 16 840 1 101 3 4 1 24 */ + 789, /* OBJ_id_aes192_wrap 2 16 840 1 101 3 4 1 25 */ + 898, /* OBJ_aes_192_gcm 2 16 840 1 101 3 4 1 26 */ + 899, /* OBJ_aes_192_ccm 2 16 840 1 101 3 4 1 27 */ + 900, /* OBJ_id_aes192_wrap_pad 2 16 840 1 101 3 4 1 28 */ + 426, /* OBJ_aes_256_ecb 2 16 840 1 101 3 4 1 41 */ + 427, /* OBJ_aes_256_cbc 2 16 840 1 101 3 4 1 42 */ + 428, /* OBJ_aes_256_ofb128 2 16 840 1 101 3 4 1 43 */ + 429, /* OBJ_aes_256_cfb128 2 16 840 1 101 3 4 1 44 */ + 790, /* OBJ_id_aes256_wrap 2 16 840 1 101 3 4 1 45 */ + 901, /* OBJ_aes_256_gcm 2 16 840 1 101 3 4 1 46 */ + 902, /* OBJ_aes_256_ccm 2 16 840 1 101 3 4 1 47 */ + 903, /* OBJ_id_aes256_wrap_pad 2 16 840 1 101 3 4 1 48 */ + 672, /* OBJ_sha256 2 16 840 1 101 3 4 2 1 */ + 673, /* OBJ_sha384 2 16 840 1 101 3 4 2 2 */ + 674, /* OBJ_sha512 2 16 840 1 101 3 4 2 3 */ + 675, /* OBJ_sha224 2 16 840 1 101 3 4 2 4 */ + 1094, /* OBJ_sha512_224 2 16 840 1 101 3 4 2 5 */ + 1095, /* OBJ_sha512_256 2 16 840 1 101 3 4 2 6 */ + 1096, /* OBJ_sha3_224 2 16 840 1 101 3 4 2 7 */ + 1097, /* OBJ_sha3_256 2 16 840 1 101 3 4 2 8 */ + 1098, /* OBJ_sha3_384 2 16 840 1 101 3 4 2 9 */ + 1099, /* OBJ_sha3_512 2 16 840 1 101 3 4 2 10 */ + 1100, /* OBJ_shake128 2 16 840 1 101 3 4 2 11 */ + 1101, /* OBJ_shake256 2 16 840 1 101 3 4 2 12 */ + 1102, /* OBJ_hmac_sha3_224 2 16 840 1 101 3 4 2 13 */ + 1103, /* OBJ_hmac_sha3_256 2 16 840 1 101 3 4 2 14 */ + 1104, /* OBJ_hmac_sha3_384 2 16 840 1 101 3 4 2 15 */ + 1105, /* OBJ_hmac_sha3_512 2 16 840 1 101 3 4 2 16 */ + 802, /* OBJ_dsa_with_SHA224 2 16 840 1 101 3 4 3 1 */ + 803, /* OBJ_dsa_with_SHA256 2 16 840 1 101 3 4 3 2 */ + 1106, /* OBJ_dsa_with_SHA384 2 16 840 1 101 3 4 3 3 */ + 1107, /* OBJ_dsa_with_SHA512 2 16 840 1 101 3 4 3 4 */ + 1108, /* OBJ_dsa_with_SHA3_224 2 16 840 1 101 3 4 3 5 */ + 1109, /* OBJ_dsa_with_SHA3_256 2 16 840 1 101 3 4 3 6 */ + 1110, /* OBJ_dsa_with_SHA3_384 2 16 840 1 101 3 4 3 7 */ + 1111, /* OBJ_dsa_with_SHA3_512 2 16 840 1 101 3 4 3 8 */ + 1112, /* OBJ_ecdsa_with_SHA3_224 2 16 840 1 101 3 4 3 9 */ + 1113, /* OBJ_ecdsa_with_SHA3_256 2 16 840 1 101 3 4 3 10 */ + 1114, /* OBJ_ecdsa_with_SHA3_384 2 16 840 1 101 3 4 3 11 */ + 1115, /* OBJ_ecdsa_with_SHA3_512 2 16 840 1 101 3 4 3 12 */ + 1116, /* OBJ_RSA_SHA3_224 2 16 840 1 101 3 4 3 13 */ + 1117, /* OBJ_RSA_SHA3_256 2 16 840 1 101 3 4 3 14 */ + 1118, /* OBJ_RSA_SHA3_384 2 16 840 1 101 3 4 3 15 */ + 1119, /* OBJ_RSA_SHA3_512 2 16 840 1 101 3 4 3 16 */ + 71, /* OBJ_netscape_cert_type 2 16 840 1 113730 1 1 */ + 72, /* OBJ_netscape_base_url 2 16 840 1 113730 1 2 */ + 73, /* OBJ_netscape_revocation_url 2 16 840 1 113730 1 3 */ + 74, /* OBJ_netscape_ca_revocation_url 2 16 840 1 113730 1 4 */ + 75, /* OBJ_netscape_renewal_url 2 16 840 1 113730 1 7 */ + 76, /* OBJ_netscape_ca_policy_url 2 16 840 1 113730 1 8 */ + 77, /* OBJ_netscape_ssl_server_name 2 16 840 1 113730 1 12 */ + 78, /* OBJ_netscape_comment 2 16 840 1 113730 1 13 */ + 79, /* OBJ_netscape_cert_sequence 2 16 840 1 113730 2 5 */ + 139, /* OBJ_ns_sgc 2 16 840 1 113730 4 1 */ + 458, /* OBJ_userId 0 9 2342 19200300 100 1 1 */ + 459, /* OBJ_textEncodedORAddress 0 9 2342 19200300 100 1 2 */ + 460, /* OBJ_rfc822Mailbox 0 9 2342 19200300 100 1 3 */ + 461, /* OBJ_info 0 9 2342 19200300 100 1 4 */ + 462, /* OBJ_favouriteDrink 0 9 2342 19200300 100 1 5 */ + 463, /* OBJ_roomNumber 0 9 2342 19200300 100 1 6 */ + 464, /* OBJ_photo 0 9 2342 19200300 100 1 7 */ + 465, /* OBJ_userClass 0 9 2342 19200300 100 1 8 */ + 466, /* OBJ_host 0 9 2342 19200300 100 1 9 */ + 467, /* OBJ_manager 0 9 2342 19200300 100 1 10 */ + 468, /* OBJ_documentIdentifier 0 9 2342 19200300 100 1 11 */ + 469, /* OBJ_documentTitle 0 9 2342 19200300 100 1 12 */ + 470, /* OBJ_documentVersion 0 9 2342 19200300 100 1 13 */ + 471, /* OBJ_documentAuthor 0 9 2342 19200300 100 1 14 */ + 472, /* OBJ_documentLocation 0 9 2342 19200300 100 1 15 */ + 473, /* OBJ_homeTelephoneNumber 0 9 2342 19200300 100 1 20 */ + 474, /* OBJ_secretary 0 9 2342 19200300 100 1 21 */ + 475, /* OBJ_otherMailbox 0 9 2342 19200300 100 1 22 */ + 476, /* OBJ_lastModifiedTime 0 9 2342 19200300 100 1 23 */ + 477, /* OBJ_lastModifiedBy 0 9 2342 19200300 100 1 24 */ + 391, /* OBJ_domainComponent 0 9 2342 19200300 100 1 25 */ + 478, /* OBJ_aRecord 0 9 2342 19200300 100 1 26 */ + 479, /* OBJ_pilotAttributeType27 0 9 2342 19200300 100 1 27 */ + 480, /* OBJ_mXRecord 0 9 2342 19200300 100 1 28 */ + 481, /* OBJ_nSRecord 0 9 2342 19200300 100 1 29 */ + 482, /* OBJ_sOARecord 0 9 2342 19200300 100 1 30 */ + 483, /* OBJ_cNAMERecord 0 9 2342 19200300 100 1 31 */ + 484, /* OBJ_associatedDomain 0 9 2342 19200300 100 1 37 */ + 485, /* OBJ_associatedName 0 9 2342 19200300 100 1 38 */ + 486, /* OBJ_homePostalAddress 0 9 2342 19200300 100 1 39 */ + 487, /* OBJ_personalTitle 0 9 2342 19200300 100 1 40 */ + 488, /* OBJ_mobileTelephoneNumber 0 9 2342 19200300 100 1 41 */ + 489, /* OBJ_pagerTelephoneNumber 0 9 2342 19200300 100 1 42 */ + 490, /* OBJ_friendlyCountryName 0 9 2342 19200300 100 1 43 */ + 102, /* OBJ_uniqueIdentifier 0 9 2342 19200300 100 1 44 */ + 491, /* OBJ_organizationalStatus 0 9 2342 19200300 100 1 45 */ + 492, /* OBJ_janetMailbox 0 9 2342 19200300 100 1 46 */ + 493, /* OBJ_mailPreferenceOption 0 9 2342 19200300 100 1 47 */ + 494, /* OBJ_buildingName 0 9 2342 19200300 100 1 48 */ + 495, /* OBJ_dSAQuality 0 9 2342 19200300 100 1 49 */ + 496, /* OBJ_singleLevelQuality 0 9 2342 19200300 100 1 50 */ + 497, /* OBJ_subtreeMinimumQuality 0 9 2342 19200300 100 1 51 */ + 498, /* OBJ_subtreeMaximumQuality 0 9 2342 19200300 100 1 52 */ + 499, /* OBJ_personalSignature 0 9 2342 19200300 100 1 53 */ + 500, /* OBJ_dITRedirect 0 9 2342 19200300 100 1 54 */ + 501, /* OBJ_audio 0 9 2342 19200300 100 1 55 */ + 502, /* OBJ_documentPublisher 0 9 2342 19200300 100 1 56 */ + 442, /* OBJ_iA5StringSyntax 0 9 2342 19200300 100 3 4 */ + 443, /* OBJ_caseIgnoreIA5StringSyntax 0 9 2342 19200300 100 3 5 */ + 444, /* OBJ_pilotObject 0 9 2342 19200300 100 4 3 */ + 445, /* OBJ_pilotPerson 0 9 2342 19200300 100 4 4 */ + 446, /* OBJ_account 0 9 2342 19200300 100 4 5 */ + 447, /* OBJ_document 0 9 2342 19200300 100 4 6 */ + 448, /* OBJ_room 0 9 2342 19200300 100 4 7 */ + 449, /* OBJ_documentSeries 0 9 2342 19200300 100 4 9 */ + 392, /* OBJ_Domain 0 9 2342 19200300 100 4 13 */ + 450, /* OBJ_rFC822localPart 0 9 2342 19200300 100 4 14 */ + 451, /* OBJ_dNSDomain 0 9 2342 19200300 100 4 15 */ + 452, /* OBJ_domainRelatedObject 0 9 2342 19200300 100 4 17 */ + 453, /* OBJ_friendlyCountry 0 9 2342 19200300 100 4 18 */ + 454, /* OBJ_simpleSecurityObject 0 9 2342 19200300 100 4 19 */ + 455, /* OBJ_pilotOrganization 0 9 2342 19200300 100 4 20 */ + 456, /* OBJ_pilotDSA 0 9 2342 19200300 100 4 21 */ + 457, /* OBJ_qualityLabelledData 0 9 2342 19200300 100 4 22 */ + 1152, /* OBJ_dstu28147 1 2 804 2 1 1 1 1 1 1 */ + 1156, /* OBJ_hmacWithDstu34311 1 2 804 2 1 1 1 1 1 2 */ + 1157, /* OBJ_dstu34311 1 2 804 2 1 1 1 1 2 1 */ + 189, /* OBJ_id_smime_mod 1 2 840 113549 1 9 16 0 */ + 190, /* OBJ_id_smime_ct 1 2 840 113549 1 9 16 1 */ + 191, /* OBJ_id_smime_aa 1 2 840 113549 1 9 16 2 */ + 192, /* OBJ_id_smime_alg 1 2 840 113549 1 9 16 3 */ + 193, /* OBJ_id_smime_cd 1 2 840 113549 1 9 16 4 */ + 194, /* OBJ_id_smime_spq 1 2 840 113549 1 9 16 5 */ + 195, /* OBJ_id_smime_cti 1 2 840 113549 1 9 16 6 */ + 158, /* OBJ_x509Certificate 1 2 840 113549 1 9 22 1 */ + 159, /* OBJ_sdsiCertificate 1 2 840 113549 1 9 22 2 */ + 160, /* OBJ_x509Crl 1 2 840 113549 1 9 23 1 */ + 144, /* OBJ_pbe_WithSHA1And128BitRC4 1 2 840 113549 1 12 1 1 */ + 145, /* OBJ_pbe_WithSHA1And40BitRC4 1 2 840 113549 1 12 1 2 */ + 146, /* OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC 1 2 840 113549 1 12 1 3 */ + 147, /* OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC 1 2 840 113549 1 12 1 4 */ + 148, /* OBJ_pbe_WithSHA1And128BitRC2_CBC 1 2 840 113549 1 12 1 5 */ + 149, /* OBJ_pbe_WithSHA1And40BitRC2_CBC 1 2 840 113549 1 12 1 6 */ + 171, /* OBJ_ms_ext_req 1 3 6 1 4 1 311 2 1 14 */ + 134, /* OBJ_ms_code_ind 1 3 6 1 4 1 311 2 1 21 */ + 135, /* OBJ_ms_code_com 1 3 6 1 4 1 311 2 1 22 */ + 136, /* OBJ_ms_ctl_sign 1 3 6 1 4 1 311 10 3 1 */ + 137, /* OBJ_ms_sgc 1 3 6 1 4 1 311 10 3 3 */ + 138, /* OBJ_ms_efs 1 3 6 1 4 1 311 10 3 4 */ + 648, /* OBJ_ms_smartcard_login 1 3 6 1 4 1 311 20 2 2 */ + 649, /* OBJ_ms_upn 1 3 6 1 4 1 311 20 2 3 */ + 951, /* OBJ_ct_precert_scts 1 3 6 1 4 1 11129 2 4 2 */ + 952, /* OBJ_ct_precert_poison 1 3 6 1 4 1 11129 2 4 3 */ + 953, /* OBJ_ct_precert_signer 1 3 6 1 4 1 11129 2 4 4 */ + 954, /* OBJ_ct_cert_scts 1 3 6 1 4 1 11129 2 4 5 */ + 751, /* OBJ_camellia_128_cbc 1 2 392 200011 61 1 1 1 2 */ + 752, /* OBJ_camellia_192_cbc 1 2 392 200011 61 1 1 1 3 */ + 753, /* OBJ_camellia_256_cbc 1 2 392 200011 61 1 1 1 4 */ + 907, /* OBJ_id_camellia128_wrap 1 2 392 200011 61 1 1 3 2 */ + 908, /* OBJ_id_camellia192_wrap 1 2 392 200011 61 1 1 3 3 */ + 909, /* OBJ_id_camellia256_wrap 1 2 392 200011 61 1 1 3 4 */ + 1153, /* OBJ_dstu28147_ofb 1 2 804 2 1 1 1 1 1 1 2 */ + 1154, /* OBJ_dstu28147_cfb 1 2 804 2 1 1 1 1 1 1 3 */ + 1155, /* OBJ_dstu28147_wrap 1 2 804 2 1 1 1 1 1 1 5 */ + 1158, /* OBJ_dstu4145le 1 2 804 2 1 1 1 1 3 1 1 */ + 196, /* OBJ_id_smime_mod_cms 1 2 840 113549 1 9 16 0 1 */ + 197, /* OBJ_id_smime_mod_ess 1 2 840 113549 1 9 16 0 2 */ + 198, /* OBJ_id_smime_mod_oid 1 2 840 113549 1 9 16 0 3 */ + 199, /* OBJ_id_smime_mod_msg_v3 1 2 840 113549 1 9 16 0 4 */ + 200, /* OBJ_id_smime_mod_ets_eSignature_88 1 2 840 113549 1 9 16 0 5 */ + 201, /* OBJ_id_smime_mod_ets_eSignature_97 1 2 840 113549 1 9 16 0 6 */ + 202, /* OBJ_id_smime_mod_ets_eSigPolicy_88 1 2 840 113549 1 9 16 0 7 */ + 203, /* OBJ_id_smime_mod_ets_eSigPolicy_97 1 2 840 113549 1 9 16 0 8 */ + 204, /* OBJ_id_smime_ct_receipt 1 2 840 113549 1 9 16 1 1 */ + 205, /* OBJ_id_smime_ct_authData 1 2 840 113549 1 9 16 1 2 */ + 206, /* OBJ_id_smime_ct_publishCert 1 2 840 113549 1 9 16 1 3 */ + 207, /* OBJ_id_smime_ct_TSTInfo 1 2 840 113549 1 9 16 1 4 */ + 208, /* OBJ_id_smime_ct_TDTInfo 1 2 840 113549 1 9 16 1 5 */ + 209, /* OBJ_id_smime_ct_contentInfo 1 2 840 113549 1 9 16 1 6 */ + 210, /* OBJ_id_smime_ct_DVCSRequestData 1 2 840 113549 1 9 16 1 7 */ + 211, /* OBJ_id_smime_ct_DVCSResponseData 1 2 840 113549 1 9 16 1 8 */ + 786, /* OBJ_id_smime_ct_compressedData 1 2 840 113549 1 9 16 1 9 */ + 1058, /* OBJ_id_smime_ct_contentCollection 1 2 840 113549 1 9 16 1 19 */ + 1059, /* OBJ_id_smime_ct_authEnvelopedData 1 2 840 113549 1 9 16 1 23 */ + 787, /* OBJ_id_ct_asciiTextWithCRLF 1 2 840 113549 1 9 16 1 27 */ + 1060, /* OBJ_id_ct_xml 1 2 840 113549 1 9 16 1 28 */ + 212, /* OBJ_id_smime_aa_receiptRequest 1 2 840 113549 1 9 16 2 1 */ + 213, /* OBJ_id_smime_aa_securityLabel 1 2 840 113549 1 9 16 2 2 */ + 214, /* OBJ_id_smime_aa_mlExpandHistory 1 2 840 113549 1 9 16 2 3 */ + 215, /* OBJ_id_smime_aa_contentHint 1 2 840 113549 1 9 16 2 4 */ + 216, /* OBJ_id_smime_aa_msgSigDigest 1 2 840 113549 1 9 16 2 5 */ + 217, /* OBJ_id_smime_aa_encapContentType 1 2 840 113549 1 9 16 2 6 */ + 218, /* OBJ_id_smime_aa_contentIdentifier 1 2 840 113549 1 9 16 2 7 */ + 219, /* OBJ_id_smime_aa_macValue 1 2 840 113549 1 9 16 2 8 */ + 220, /* OBJ_id_smime_aa_equivalentLabels 1 2 840 113549 1 9 16 2 9 */ + 221, /* OBJ_id_smime_aa_contentReference 1 2 840 113549 1 9 16 2 10 */ + 222, /* OBJ_id_smime_aa_encrypKeyPref 1 2 840 113549 1 9 16 2 11 */ + 223, /* OBJ_id_smime_aa_signingCertificate 1 2 840 113549 1 9 16 2 12 */ + 224, /* OBJ_id_smime_aa_smimeEncryptCerts 1 2 840 113549 1 9 16 2 13 */ + 225, /* OBJ_id_smime_aa_timeStampToken 1 2 840 113549 1 9 16 2 14 */ + 226, /* OBJ_id_smime_aa_ets_sigPolicyId 1 2 840 113549 1 9 16 2 15 */ + 227, /* OBJ_id_smime_aa_ets_commitmentType 1 2 840 113549 1 9 16 2 16 */ + 228, /* OBJ_id_smime_aa_ets_signerLocation 1 2 840 113549 1 9 16 2 17 */ + 229, /* OBJ_id_smime_aa_ets_signerAttr 1 2 840 113549 1 9 16 2 18 */ + 230, /* OBJ_id_smime_aa_ets_otherSigCert 1 2 840 113549 1 9 16 2 19 */ + 231, /* OBJ_id_smime_aa_ets_contentTimestamp 1 2 840 113549 1 9 16 2 20 */ + 232, /* OBJ_id_smime_aa_ets_CertificateRefs 1 2 840 113549 1 9 16 2 21 */ + 233, /* OBJ_id_smime_aa_ets_RevocationRefs 1 2 840 113549 1 9 16 2 22 */ + 234, /* OBJ_id_smime_aa_ets_certValues 1 2 840 113549 1 9 16 2 23 */ + 235, /* OBJ_id_smime_aa_ets_revocationValues 1 2 840 113549 1 9 16 2 24 */ + 236, /* OBJ_id_smime_aa_ets_escTimeStamp 1 2 840 113549 1 9 16 2 25 */ + 237, /* OBJ_id_smime_aa_ets_certCRLTimestamp 1 2 840 113549 1 9 16 2 26 */ + 238, /* OBJ_id_smime_aa_ets_archiveTimeStamp 1 2 840 113549 1 9 16 2 27 */ + 239, /* OBJ_id_smime_aa_signatureType 1 2 840 113549 1 9 16 2 28 */ + 240, /* OBJ_id_smime_aa_dvcs_dvc 1 2 840 113549 1 9 16 2 29 */ + 1086, /* OBJ_id_smime_aa_signingCertificateV2 1 2 840 113549 1 9 16 2 47 */ + 241, /* OBJ_id_smime_alg_ESDHwith3DES 1 2 840 113549 1 9 16 3 1 */ + 242, /* OBJ_id_smime_alg_ESDHwithRC2 1 2 840 113549 1 9 16 3 2 */ + 243, /* OBJ_id_smime_alg_3DESwrap 1 2 840 113549 1 9 16 3 3 */ + 244, /* OBJ_id_smime_alg_RC2wrap 1 2 840 113549 1 9 16 3 4 */ + 245, /* OBJ_id_smime_alg_ESDH 1 2 840 113549 1 9 16 3 5 */ + 246, /* OBJ_id_smime_alg_CMS3DESwrap 1 2 840 113549 1 9 16 3 6 */ + 247, /* OBJ_id_smime_alg_CMSRC2wrap 1 2 840 113549 1 9 16 3 7 */ + 125, /* OBJ_zlib_compression 1 2 840 113549 1 9 16 3 8 */ + 893, /* OBJ_id_alg_PWRI_KEK 1 2 840 113549 1 9 16 3 9 */ + 248, /* OBJ_id_smime_cd_ldap 1 2 840 113549 1 9 16 4 1 */ + 249, /* OBJ_id_smime_spq_ets_sqt_uri 1 2 840 113549 1 9 16 5 1 */ + 250, /* OBJ_id_smime_spq_ets_sqt_unotice 1 2 840 113549 1 9 16 5 2 */ + 251, /* OBJ_id_smime_cti_ets_proofOfOrigin 1 2 840 113549 1 9 16 6 1 */ + 252, /* OBJ_id_smime_cti_ets_proofOfReceipt 1 2 840 113549 1 9 16 6 2 */ + 253, /* OBJ_id_smime_cti_ets_proofOfDelivery 1 2 840 113549 1 9 16 6 3 */ + 254, /* OBJ_id_smime_cti_ets_proofOfSender 1 2 840 113549 1 9 16 6 4 */ + 255, /* OBJ_id_smime_cti_ets_proofOfApproval 1 2 840 113549 1 9 16 6 5 */ + 256, /* OBJ_id_smime_cti_ets_proofOfCreation 1 2 840 113549 1 9 16 6 6 */ + 150, /* OBJ_keyBag 1 2 840 113549 1 12 10 1 1 */ + 151, /* OBJ_pkcs8ShroudedKeyBag 1 2 840 113549 1 12 10 1 2 */ + 152, /* OBJ_certBag 1 2 840 113549 1 12 10 1 3 */ + 153, /* OBJ_crlBag 1 2 840 113549 1 12 10 1 4 */ + 154, /* OBJ_secretBag 1 2 840 113549 1 12 10 1 5 */ + 155, /* OBJ_safeContentsBag 1 2 840 113549 1 12 10 1 6 */ + 34, /* OBJ_idea_cbc 1 3 6 1 4 1 188 7 1 1 2 */ + 955, /* OBJ_jurisdictionLocalityName 1 3 6 1 4 1 311 60 2 1 1 */ + 956, /* OBJ_jurisdictionStateOrProvinceName 1 3 6 1 4 1 311 60 2 1 2 */ + 957, /* OBJ_jurisdictionCountryName 1 3 6 1 4 1 311 60 2 1 3 */ + 1056, /* OBJ_blake2b512 1 3 6 1 4 1 1722 12 2 1 16 */ + 1057, /* OBJ_blake2s256 1 3 6 1 4 1 1722 12 2 2 8 */ + 1159, /* OBJ_dstu4145be 1 2 804 2 1 1 1 1 3 1 1 1 1 */ + 1160, /* OBJ_uacurve0 1 2 804 2 1 1 1 1 3 1 1 2 0 */ + 1161, /* OBJ_uacurve1 1 2 804 2 1 1 1 1 3 1 1 2 1 */ + 1162, /* OBJ_uacurve2 1 2 804 2 1 1 1 1 3 1 1 2 2 */ + 1163, /* OBJ_uacurve3 1 2 804 2 1 1 1 1 3 1 1 2 3 */ + 1164, /* OBJ_uacurve4 1 2 804 2 1 1 1 1 3 1 1 2 4 */ + 1165, /* OBJ_uacurve5 1 2 804 2 1 1 1 1 3 1 1 2 5 */ + 1166, /* OBJ_uacurve6 1 2 804 2 1 1 1 1 3 1 1 2 6 */ + 1167, /* OBJ_uacurve7 1 2 804 2 1 1 1 1 3 1 1 2 7 */ + 1168, /* OBJ_uacurve8 1 2 804 2 1 1 1 1 3 1 1 2 8 */ + 1169, /* OBJ_uacurve9 1 2 804 2 1 1 1 1 3 1 1 2 9 */ +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_dat.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_dat.pl new file mode 100644 index 000000000..e5d38147e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_dat.pl @@ -0,0 +1,228 @@ +#! /usr/bin/env perl +# Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use integer; +use strict; +use warnings; + +# Generate the DER encoding for the given OID. +sub der_it +{ + # Prologue + my ($v) = @_; + my @a = split(/\s+/, $v); + my $ret = pack("C*", $a[0] * 40 + $a[1]); + shift @a; + shift @a; + + # Loop over rest of bytes; or in 0x80 for multi-byte numbers. + my $t; + foreach (@a) { + my @r = (); + $t = 0; + while ($_ >= 128) { + my $x = $_ % 128; + $_ /= 128; + push(@r, ($t++ ? 0x80 : 0) | $x); + } + push(@r, ($t++ ? 0x80 : 0) | $_); + $ret .= pack("C*", reverse(@r)); + } + return $ret; +} + +# Output year depends on the year of the script and the input file. +my $YEAR = [localtime([stat($0)]->[9])]->[5] + 1900; +my $iYEAR = [localtime([stat($ARGV[0])]->[9])]->[5] + 1900; +$YEAR = $iYEAR if $iYEAR > $YEAR; + +# Read input, parse all #define's into OID name and value. +# Populate %ln and %sn with long and short names (%dupln and %dupsn) +# are used to watch for duplicates. Also %nid and %obj get the +# NID and OBJ entries. +my %ln; +my %sn; +my %dupln; +my %dupsn; +my %nid; +my %obj; +my %objd; +open(IN, "$ARGV[0]") || die "Can't open input file $ARGV[0], $!"; +while () { + next unless /^\#define\s+(\S+)\s+(.*)$/; + my $v = $1; + my $d = $2; + $d =~ s/^\"//; + $d =~ s/\"$//; + if ($v =~ /^SN_(.*)$/) { + if (defined $dupsn{$d}) { + print "WARNING: Duplicate short name \"$d\"\n"; + } else { + $dupsn{$d} = 1; + } + $sn{$1} = $d; + } + elsif ($v =~ /^LN_(.*)$/) { + if (defined $dupln{$d}) { + print "WARNING: Duplicate long name \"$d\"\n"; + } else { + $dupln{$d} = 1; + } + $ln{$1} = $d; + } + elsif ($v =~ /^NID_(.*)$/) { + $nid{$d} = $1; + } + elsif ($v =~ /^OBJ_(.*)$/) { + $obj{$1} = $v; + $objd{$v} = $d; + } +} +close IN; + +# For every value in %obj, recursively expand OBJ_xxx values. That is: +# #define OBJ_iso 1L +# #define OBJ_identified_organization OBJ_iso,3L +# Modify %objd values in-place. Create an %objn array that has +my $changed; +do { + $changed = 0; + foreach my $k (keys %objd) { + $changed = 1 if $objd{$k} =~ s/(OBJ_[^,]+),/$objd{$1},/; + } +} while ($changed); + +my @a = sort { $a <=> $b } keys %nid; +my $n = $a[$#a] + 1; +my @lvalues = (); +my $lvalues = 0; + +# Scan all defined objects, building up the @out array. +# %obj_der holds the DER encoding as an array of bytes, and %obj_len +# holds the length in bytes. +my @out; +my %obj_der; +my %obj_len; +for (my $i = 0; $i < $n; $i++) { + if (!defined $nid{$i}) { + push(@out, " { NULL, NULL, NID_undef },\n"); + next; + } + + my $sn = defined $sn{$nid{$i}} ? "$sn{$nid{$i}}" : "NULL"; + my $ln = defined $ln{$nid{$i}} ? "$ln{$nid{$i}}" : "NULL"; + if ($sn eq "NULL") { + $sn = $ln; + $sn{$nid{$i}} = $ln; + } + if ($ln eq "NULL") { + $ln = $sn; + $ln{$nid{$i}} = $sn; + } + + my $out = " {\"$sn\", \"$ln\", NID_$nid{$i}"; + if (defined $obj{$nid{$i}} && $objd{$obj{$nid{$i}}} =~ /,/) { + my $v = $objd{$obj{$nid{$i}}}; + $v =~ s/L//g; + $v =~ s/,/ /g; + my $r = &der_it($v); + my $z = ""; + my $length = 0; + # Format using fixed-with because we use strcmp later. + foreach (unpack("C*",$r)) { + $z .= sprintf("0x%02X,", $_); + $length++; + } + $obj_der{$obj{$nid{$i}}} = $z; + $obj_len{$obj{$nid{$i}}} = $length; + + push(@lvalues, + sprintf(" %-45s /* [%5d] %s */\n", + $z, $lvalues, $obj{$nid{$i}})); + $out .= ", $length, &so[$lvalues]"; + $lvalues += $length; + } + $out .= "},\n"; + push(@out, $out); +} + +# Finally ready to generate the output. +print <<"EOF"; +/* + * WARNING: do not edit! + * Generated by crypto/objects/obj_dat.pl + * + * Copyright 1995-$YEAR The OpenSSL Project Authors. All Rights Reserved. + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +EOF + +print "/* Serialized OID's */\n"; +printf "static const unsigned char so[%d] = {\n", $lvalues + 1; +print @lvalues; +print "};\n\n"; + +printf "#define NUM_NID %d\n", $n; +printf "static const ASN1_OBJECT nid_objs[NUM_NID] = {\n"; +print @out; +print "};\n\n"; + +{ + no warnings "uninitialized"; + @a = grep(defined $sn{$nid{$_}}, 0 .. $n); +} +printf "#define NUM_SN %d\n", $#a + 1; +printf "static const unsigned int sn_objs[NUM_SN] = {\n"; +foreach (sort { $sn{$nid{$a}} cmp $sn{$nid{$b}} } @a) { + printf " %4d, /* \"$sn{$nid{$_}}\" */\n", $_; +} +print "};\n\n"; + +{ + no warnings "uninitialized"; + @a = grep(defined $ln{$nid{$_}}, 0 .. $n); +} +printf "#define NUM_LN %d\n", $#a + 1; +printf "static const unsigned int ln_objs[NUM_LN] = {\n"; +foreach (sort { $ln{$nid{$a}} cmp $ln{$nid{$b}} } @a) { + printf " %4d, /* \"$ln{$nid{$_}}\" */\n", $_; +} +print "};\n\n"; + +{ + no warnings "uninitialized"; + @a = grep(defined $obj{$nid{$_}}, 0 .. $n); +} +printf "#define NUM_OBJ %d\n", $#a + 1; +printf "static const unsigned int obj_objs[NUM_OBJ] = {\n"; + +# Compare DER; prefer shorter; if some length, use the "smaller" encoding. +sub obj_cmp +{ + no warnings "uninitialized"; + my $A = $obj_len{$obj{$nid{$a}}}; + my $B = $obj_len{$obj{$nid{$b}}}; + my $r = $A - $B; + return $r if $r != 0; + + $A = $obj_der{$obj{$nid{$a}}}; + $B = $obj_der{$obj{$nid{$b}}}; + return $A cmp $B; +} +foreach (sort obj_cmp @a) { + my $m = $obj{$nid{$_}}; + my $v = $objd{$m}; + $v =~ s/L//g; + $v =~ s/,/ /g; + printf " %4d, /* %-32s %s */\n", $_, $m, $v; +} +print "};\n"; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_err.c new file mode 100644 index 000000000..be4f11ca2 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_err.c @@ -0,0 +1,46 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA OBJ_str_functs[] = { + {ERR_PACK(ERR_LIB_OBJ, OBJ_F_OBJ_ADD_OBJECT, 0), "OBJ_add_object"}, + {ERR_PACK(ERR_LIB_OBJ, OBJ_F_OBJ_ADD_SIGID, 0), "OBJ_add_sigid"}, + {ERR_PACK(ERR_LIB_OBJ, OBJ_F_OBJ_CREATE, 0), "OBJ_create"}, + {ERR_PACK(ERR_LIB_OBJ, OBJ_F_OBJ_DUP, 0), "OBJ_dup"}, + {ERR_PACK(ERR_LIB_OBJ, OBJ_F_OBJ_NAME_NEW_INDEX, 0), "OBJ_NAME_new_index"}, + {ERR_PACK(ERR_LIB_OBJ, OBJ_F_OBJ_NID2LN, 0), "OBJ_nid2ln"}, + {ERR_PACK(ERR_LIB_OBJ, OBJ_F_OBJ_NID2OBJ, 0), "OBJ_nid2obj"}, + {ERR_PACK(ERR_LIB_OBJ, OBJ_F_OBJ_NID2SN, 0), "OBJ_nid2sn"}, + {ERR_PACK(ERR_LIB_OBJ, OBJ_F_OBJ_TXT2OBJ, 0), "OBJ_txt2obj"}, + {0, NULL} +}; + +static const ERR_STRING_DATA OBJ_str_reasons[] = { + {ERR_PACK(ERR_LIB_OBJ, 0, OBJ_R_OID_EXISTS), "oid exists"}, + {ERR_PACK(ERR_LIB_OBJ, 0, OBJ_R_UNKNOWN_NID), "unknown nid"}, + {0, NULL} +}; + +#endif + +int ERR_load_OBJ_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(OBJ_str_functs[0].error) == NULL) { + ERR_load_strings_const(OBJ_str_functs); + ERR_load_strings_const(OBJ_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_lcl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_lcl.h new file mode 100644 index 000000000..a417f7c46 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_lcl.h @@ -0,0 +1,14 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +typedef struct name_funcs_st NAME_FUNCS; +DEFINE_STACK_OF(NAME_FUNCS) +DEFINE_LHASH_OF(OBJ_NAME); +typedef struct added_obj_st ADDED_OBJ; +DEFINE_LHASH_OF(ADDED_OBJ); diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_lib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_lib.c new file mode 100644 index 000000000..acbdeec2c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_lib.c @@ -0,0 +1,65 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include "internal/asn1_int.h" + +ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *o) +{ + ASN1_OBJECT *r; + + if (o == NULL) + return NULL; + /* If object isn't dynamic it's an internal OID which is never freed */ + if (!(o->flags & ASN1_OBJECT_FLAG_DYNAMIC)) + return (ASN1_OBJECT *)o; + + r = ASN1_OBJECT_new(); + if (r == NULL) { + OBJerr(OBJ_F_OBJ_DUP, ERR_R_ASN1_LIB); + return NULL; + } + + /* Set dynamic flags so everything gets freed up on error */ + + r->flags = o->flags | (ASN1_OBJECT_FLAG_DYNAMIC | + ASN1_OBJECT_FLAG_DYNAMIC_STRINGS | + ASN1_OBJECT_FLAG_DYNAMIC_DATA); + + if (o->length > 0 && (r->data = OPENSSL_memdup(o->data, o->length)) == NULL) + goto err; + + r->length = o->length; + r->nid = o->nid; + + if (o->ln != NULL && (r->ln = OPENSSL_strdup(o->ln)) == NULL) + goto err; + + if (o->sn != NULL && (r->sn = OPENSSL_strdup(o->sn)) == NULL) + goto err; + + return r; + err: + ASN1_OBJECT_free(r); + OBJerr(OBJ_F_OBJ_DUP, ERR_R_MALLOC_FAILURE); + return NULL; +} + +int OBJ_cmp(const ASN1_OBJECT *a, const ASN1_OBJECT *b) +{ + int ret; + + ret = (a->length - b->length); + if (ret) + return ret; + return memcmp(a->data, b->data, a->length); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_mac.num b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_mac.num new file mode 100644 index 000000000..1b6a9c61a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_mac.num @@ -0,0 +1,1194 @@ +undef 0 +rsadsi 1 +pkcs 2 +md2 3 +md5 4 +rc4 5 +rsaEncryption 6 +md2WithRSAEncryption 7 +md5WithRSAEncryption 8 +pbeWithMD2AndDES_CBC 9 +pbeWithMD5AndDES_CBC 10 +X500 11 +X509 12 +commonName 13 +countryName 14 +localityName 15 +stateOrProvinceName 16 +organizationName 17 +organizationalUnitName 18 +rsa 19 +pkcs7 20 +pkcs7_data 21 +pkcs7_signed 22 +pkcs7_enveloped 23 +pkcs7_signedAndEnveloped 24 +pkcs7_digest 25 +pkcs7_encrypted 26 +pkcs3 27 +dhKeyAgreement 28 +des_ecb 29 +des_cfb64 30 +des_cbc 31 +des_ede_ecb 32 +des_ede3_ecb 33 +idea_cbc 34 +idea_cfb64 35 +idea_ecb 36 +rc2_cbc 37 +rc2_ecb 38 +rc2_cfb64 39 +rc2_ofb64 40 +sha 41 +shaWithRSAEncryption 42 +des_ede_cbc 43 +des_ede3_cbc 44 +des_ofb64 45 +idea_ofb64 46 +pkcs9 47 +pkcs9_emailAddress 48 +pkcs9_unstructuredName 49 +pkcs9_contentType 50 +pkcs9_messageDigest 51 +pkcs9_signingTime 52 +pkcs9_countersignature 53 +pkcs9_challengePassword 54 +pkcs9_unstructuredAddress 55 +pkcs9_extCertAttributes 56 +netscape 57 +netscape_cert_extension 58 +netscape_data_type 59 +des_ede_cfb64 60 +des_ede3_cfb64 61 +des_ede_ofb64 62 +des_ede3_ofb64 63 +sha1 64 +sha1WithRSAEncryption 65 +dsaWithSHA 66 +dsa_2 67 +pbeWithSHA1AndRC2_CBC 68 +id_pbkdf2 69 +dsaWithSHA1_2 70 +netscape_cert_type 71 +netscape_base_url 72 +netscape_revocation_url 73 +netscape_ca_revocation_url 74 +netscape_renewal_url 75 +netscape_ca_policy_url 76 +netscape_ssl_server_name 77 +netscape_comment 78 +netscape_cert_sequence 79 +desx_cbc 80 +id_ce 81 +subject_key_identifier 82 +key_usage 83 +private_key_usage_period 84 +subject_alt_name 85 +issuer_alt_name 86 +basic_constraints 87 +crl_number 88 +certificate_policies 89 +authority_key_identifier 90 +bf_cbc 91 +bf_ecb 92 +bf_cfb64 93 +bf_ofb64 94 +mdc2 95 +mdc2WithRSA 96 +rc4_40 97 +rc2_40_cbc 98 +givenName 99 +surname 100 +initials 101 +uniqueIdentifier 102 +crl_distribution_points 103 +md5WithRSA 104 +serialNumber 105 +title 106 +description 107 +cast5_cbc 108 +cast5_ecb 109 +cast5_cfb64 110 +cast5_ofb64 111 +pbeWithMD5AndCast5_CBC 112 +dsaWithSHA1 113 +md5_sha1 114 +sha1WithRSA 115 +dsa 116 +ripemd160 117 +ripemd160WithRSA 119 +rc5_cbc 120 +rc5_ecb 121 +rc5_cfb64 122 +rc5_ofb64 123 +rle_compression 124 +zlib_compression 125 +ext_key_usage 126 +id_pkix 127 +id_kp 128 +server_auth 129 +client_auth 130 +code_sign 131 +email_protect 132 +time_stamp 133 +ms_code_ind 134 +ms_code_com 135 +ms_ctl_sign 136 +ms_sgc 137 +ms_efs 138 +ns_sgc 139 +delta_crl 140 +crl_reason 141 +invalidity_date 142 +sxnet 143 +pbe_WithSHA1And128BitRC4 144 +pbe_WithSHA1And40BitRC4 145 +pbe_WithSHA1And3_Key_TripleDES_CBC 146 +pbe_WithSHA1And2_Key_TripleDES_CBC 147 +pbe_WithSHA1And128BitRC2_CBC 148 +pbe_WithSHA1And40BitRC2_CBC 149 +keyBag 150 +pkcs8ShroudedKeyBag 151 +certBag 152 +crlBag 153 +secretBag 154 +safeContentsBag 155 +friendlyName 156 +localKeyID 157 +x509Certificate 158 +sdsiCertificate 159 +x509Crl 160 +pbes2 161 +pbmac1 162 +hmacWithSHA1 163 +id_qt_cps 164 +id_qt_unotice 165 +rc2_64_cbc 166 +SMIMECapabilities 167 +pbeWithMD2AndRC2_CBC 168 +pbeWithMD5AndRC2_CBC 169 +pbeWithSHA1AndDES_CBC 170 +ms_ext_req 171 +ext_req 172 +name 173 +dnQualifier 174 +id_pe 175 +id_ad 176 +info_access 177 +ad_OCSP 178 +ad_ca_issuers 179 +OCSP_sign 180 +iso 181 +member_body 182 +ISO_US 183 +X9_57 184 +X9cm 185 +pkcs1 186 +pkcs5 187 +SMIME 188 +id_smime_mod 189 +id_smime_ct 190 +id_smime_aa 191 +id_smime_alg 192 +id_smime_cd 193 +id_smime_spq 194 +id_smime_cti 195 +id_smime_mod_cms 196 +id_smime_mod_ess 197 +id_smime_mod_oid 198 +id_smime_mod_msg_v3 199 +id_smime_mod_ets_eSignature_88 200 +id_smime_mod_ets_eSignature_97 201 +id_smime_mod_ets_eSigPolicy_88 202 +id_smime_mod_ets_eSigPolicy_97 203 +id_smime_ct_receipt 204 +id_smime_ct_authData 205 +id_smime_ct_publishCert 206 +id_smime_ct_TSTInfo 207 +id_smime_ct_TDTInfo 208 +id_smime_ct_contentInfo 209 +id_smime_ct_DVCSRequestData 210 +id_smime_ct_DVCSResponseData 211 +id_smime_aa_receiptRequest 212 +id_smime_aa_securityLabel 213 +id_smime_aa_mlExpandHistory 214 +id_smime_aa_contentHint 215 +id_smime_aa_msgSigDigest 216 +id_smime_aa_encapContentType 217 +id_smime_aa_contentIdentifier 218 +id_smime_aa_macValue 219 +id_smime_aa_equivalentLabels 220 +id_smime_aa_contentReference 221 +id_smime_aa_encrypKeyPref 222 +id_smime_aa_signingCertificate 223 +id_smime_aa_smimeEncryptCerts 224 +id_smime_aa_timeStampToken 225 +id_smime_aa_ets_sigPolicyId 226 +id_smime_aa_ets_commitmentType 227 +id_smime_aa_ets_signerLocation 228 +id_smime_aa_ets_signerAttr 229 +id_smime_aa_ets_otherSigCert 230 +id_smime_aa_ets_contentTimestamp 231 +id_smime_aa_ets_CertificateRefs 232 +id_smime_aa_ets_RevocationRefs 233 +id_smime_aa_ets_certValues 234 +id_smime_aa_ets_revocationValues 235 +id_smime_aa_ets_escTimeStamp 236 +id_smime_aa_ets_certCRLTimestamp 237 +id_smime_aa_ets_archiveTimeStamp 238 +id_smime_aa_signatureType 239 +id_smime_aa_dvcs_dvc 240 +id_smime_alg_ESDHwith3DES 241 +id_smime_alg_ESDHwithRC2 242 +id_smime_alg_3DESwrap 243 +id_smime_alg_RC2wrap 244 +id_smime_alg_ESDH 245 +id_smime_alg_CMS3DESwrap 246 +id_smime_alg_CMSRC2wrap 247 +id_smime_cd_ldap 248 +id_smime_spq_ets_sqt_uri 249 +id_smime_spq_ets_sqt_unotice 250 +id_smime_cti_ets_proofOfOrigin 251 +id_smime_cti_ets_proofOfReceipt 252 +id_smime_cti_ets_proofOfDelivery 253 +id_smime_cti_ets_proofOfSender 254 +id_smime_cti_ets_proofOfApproval 255 +id_smime_cti_ets_proofOfCreation 256 +md4 257 +id_pkix_mod 258 +id_qt 259 +id_it 260 +id_pkip 261 +id_alg 262 +id_cmc 263 +id_on 264 +id_pda 265 +id_aca 266 +id_qcs 267 +id_cct 268 +id_pkix1_explicit_88 269 +id_pkix1_implicit_88 270 +id_pkix1_explicit_93 271 +id_pkix1_implicit_93 272 +id_mod_crmf 273 +id_mod_cmc 274 +id_mod_kea_profile_88 275 +id_mod_kea_profile_93 276 +id_mod_cmp 277 +id_mod_qualified_cert_88 278 +id_mod_qualified_cert_93 279 +id_mod_attribute_cert 280 +id_mod_timestamp_protocol 281 +id_mod_ocsp 282 +id_mod_dvcs 283 +id_mod_cmp2000 284 +biometricInfo 285 +qcStatements 286 +ac_auditEntity 287 +ac_targeting 288 +aaControls 289 +sbgp_ipAddrBlock 290 +sbgp_autonomousSysNum 291 +sbgp_routerIdentifier 292 +textNotice 293 +ipsecEndSystem 294 +ipsecTunnel 295 +ipsecUser 296 +dvcs 297 +id_it_caProtEncCert 298 +id_it_signKeyPairTypes 299 +id_it_encKeyPairTypes 300 +id_it_preferredSymmAlg 301 +id_it_caKeyUpdateInfo 302 +id_it_currentCRL 303 +id_it_unsupportedOIDs 304 +id_it_subscriptionRequest 305 +id_it_subscriptionResponse 306 +id_it_keyPairParamReq 307 +id_it_keyPairParamRep 308 +id_it_revPassphrase 309 +id_it_implicitConfirm 310 +id_it_confirmWaitTime 311 +id_it_origPKIMessage 312 +id_regCtrl 313 +id_regInfo 314 +id_regCtrl_regToken 315 +id_regCtrl_authenticator 316 +id_regCtrl_pkiPublicationInfo 317 +id_regCtrl_pkiArchiveOptions 318 +id_regCtrl_oldCertID 319 +id_regCtrl_protocolEncrKey 320 +id_regInfo_utf8Pairs 321 +id_regInfo_certReq 322 +id_alg_des40 323 +id_alg_noSignature 324 +id_alg_dh_sig_hmac_sha1 325 +id_alg_dh_pop 326 +id_cmc_statusInfo 327 +id_cmc_identification 328 +id_cmc_identityProof 329 +id_cmc_dataReturn 330 +id_cmc_transactionId 331 +id_cmc_senderNonce 332 +id_cmc_recipientNonce 333 +id_cmc_addExtensions 334 +id_cmc_encryptedPOP 335 +id_cmc_decryptedPOP 336 +id_cmc_lraPOPWitness 337 +id_cmc_getCert 338 +id_cmc_getCRL 339 +id_cmc_revokeRequest 340 +id_cmc_regInfo 341 +id_cmc_responseInfo 342 +id_cmc_queryPending 343 +id_cmc_popLinkRandom 344 +id_cmc_popLinkWitness 345 +id_cmc_confirmCertAcceptance 346 +id_on_personalData 347 +id_pda_dateOfBirth 348 +id_pda_placeOfBirth 349 +id_pda_pseudonym 350 +id_pda_gender 351 +id_pda_countryOfCitizenship 352 +id_pda_countryOfResidence 353 +id_aca_authenticationInfo 354 +id_aca_accessIdentity 355 +id_aca_chargingIdentity 356 +id_aca_group 357 +id_aca_role 358 +id_qcs_pkixQCSyntax_v1 359 +id_cct_crs 360 +id_cct_PKIData 361 +id_cct_PKIResponse 362 +ad_timeStamping 363 +ad_dvcs 364 +id_pkix_OCSP_basic 365 +id_pkix_OCSP_Nonce 366 +id_pkix_OCSP_CrlID 367 +id_pkix_OCSP_acceptableResponses 368 +id_pkix_OCSP_noCheck 369 +id_pkix_OCSP_archiveCutoff 370 +id_pkix_OCSP_serviceLocator 371 +id_pkix_OCSP_extendedStatus 372 +id_pkix_OCSP_valid 373 +id_pkix_OCSP_path 374 +id_pkix_OCSP_trustRoot 375 +algorithm 376 +rsaSignature 377 +X500algorithms 378 +org 379 +dod 380 +iana 381 +Directory 382 +Management 383 +Experimental 384 +Private 385 +Security 386 +SNMPv2 387 +Mail 388 +Enterprises 389 +dcObject 390 +domainComponent 391 +Domain 392 +joint_iso_ccitt 393 +selected_attribute_types 394 +clearance 395 +md4WithRSAEncryption 396 +ac_proxying 397 +sinfo_access 398 +id_aca_encAttrs 399 +role 400 +policy_constraints 401 +target_information 402 +no_rev_avail 403 +ccitt 404 +ansi_X9_62 405 +X9_62_prime_field 406 +X9_62_characteristic_two_field 407 +X9_62_id_ecPublicKey 408 +X9_62_prime192v1 409 +X9_62_prime192v2 410 +X9_62_prime192v3 411 +X9_62_prime239v1 412 +X9_62_prime239v2 413 +X9_62_prime239v3 414 +X9_62_prime256v1 415 +ecdsa_with_SHA1 416 +ms_csp_name 417 +aes_128_ecb 418 +aes_128_cbc 419 +aes_128_ofb128 420 +aes_128_cfb128 421 +aes_192_ecb 422 +aes_192_cbc 423 +aes_192_ofb128 424 +aes_192_cfb128 425 +aes_256_ecb 426 +aes_256_cbc 427 +aes_256_ofb128 428 +aes_256_cfb128 429 +hold_instruction_code 430 +hold_instruction_none 431 +hold_instruction_call_issuer 432 +hold_instruction_reject 433 +data 434 +pss 435 +ucl 436 +pilot 437 +pilotAttributeType 438 +pilotAttributeSyntax 439 +pilotObjectClass 440 +pilotGroups 441 +iA5StringSyntax 442 +caseIgnoreIA5StringSyntax 443 +pilotObject 444 +pilotPerson 445 +account 446 +document 447 +room 448 +documentSeries 449 +rFC822localPart 450 +dNSDomain 451 +domainRelatedObject 452 +friendlyCountry 453 +simpleSecurityObject 454 +pilotOrganization 455 +pilotDSA 456 +qualityLabelledData 457 +userId 458 +textEncodedORAddress 459 +rfc822Mailbox 460 +info 461 +favouriteDrink 462 +roomNumber 463 +photo 464 +userClass 465 +host 466 +manager 467 +documentIdentifier 468 +documentTitle 469 +documentVersion 470 +documentAuthor 471 +documentLocation 472 +homeTelephoneNumber 473 +secretary 474 +otherMailbox 475 +lastModifiedTime 476 +lastModifiedBy 477 +aRecord 478 +pilotAttributeType27 479 +mXRecord 480 +nSRecord 481 +sOARecord 482 +cNAMERecord 483 +associatedDomain 484 +associatedName 485 +homePostalAddress 486 +personalTitle 487 +mobileTelephoneNumber 488 +pagerTelephoneNumber 489 +friendlyCountryName 490 +organizationalStatus 491 +janetMailbox 492 +mailPreferenceOption 493 +buildingName 494 +dSAQuality 495 +singleLevelQuality 496 +subtreeMinimumQuality 497 +subtreeMaximumQuality 498 +personalSignature 499 +dITRedirect 500 +audio 501 +documentPublisher 502 +x500UniqueIdentifier 503 +mime_mhs 504 +mime_mhs_headings 505 +mime_mhs_bodies 506 +id_hex_partial_message 507 +id_hex_multipart_message 508 +generationQualifier 509 +pseudonym 510 +InternationalRA 511 +id_set 512 +set_ctype 513 +set_msgExt 514 +set_attr 515 +set_policy 516 +set_certExt 517 +set_brand 518 +setct_PANData 519 +setct_PANToken 520 +setct_PANOnly 521 +setct_OIData 522 +setct_PI 523 +setct_PIData 524 +setct_PIDataUnsigned 525 +setct_HODInput 526 +setct_AuthResBaggage 527 +setct_AuthRevReqBaggage 528 +setct_AuthRevResBaggage 529 +setct_CapTokenSeq 530 +setct_PInitResData 531 +setct_PI_TBS 532 +setct_PResData 533 +setct_AuthReqTBS 534 +setct_AuthResTBS 535 +setct_AuthResTBSX 536 +setct_AuthTokenTBS 537 +setct_CapTokenData 538 +setct_CapTokenTBS 539 +setct_AcqCardCodeMsg 540 +setct_AuthRevReqTBS 541 +setct_AuthRevResData 542 +setct_AuthRevResTBS 543 +setct_CapReqTBS 544 +setct_CapReqTBSX 545 +setct_CapResData 546 +setct_CapRevReqTBS 547 +setct_CapRevReqTBSX 548 +setct_CapRevResData 549 +setct_CredReqTBS 550 +setct_CredReqTBSX 551 +setct_CredResData 552 +setct_CredRevReqTBS 553 +setct_CredRevReqTBSX 554 +setct_CredRevResData 555 +setct_PCertReqData 556 +setct_PCertResTBS 557 +setct_BatchAdminReqData 558 +setct_BatchAdminResData 559 +setct_CardCInitResTBS 560 +setct_MeAqCInitResTBS 561 +setct_RegFormResTBS 562 +setct_CertReqData 563 +setct_CertReqTBS 564 +setct_CertResData 565 +setct_CertInqReqTBS 566 +setct_ErrorTBS 567 +setct_PIDualSignedTBE 568 +setct_PIUnsignedTBE 569 +setct_AuthReqTBE 570 +setct_AuthResTBE 571 +setct_AuthResTBEX 572 +setct_AuthTokenTBE 573 +setct_CapTokenTBE 574 +setct_CapTokenTBEX 575 +setct_AcqCardCodeMsgTBE 576 +setct_AuthRevReqTBE 577 +setct_AuthRevResTBE 578 +setct_AuthRevResTBEB 579 +setct_CapReqTBE 580 +setct_CapReqTBEX 581 +setct_CapResTBE 582 +setct_CapRevReqTBE 583 +setct_CapRevReqTBEX 584 +setct_CapRevResTBE 585 +setct_CredReqTBE 586 +setct_CredReqTBEX 587 +setct_CredResTBE 588 +setct_CredRevReqTBE 589 +setct_CredRevReqTBEX 590 +setct_CredRevResTBE 591 +setct_BatchAdminReqTBE 592 +setct_BatchAdminResTBE 593 +setct_RegFormReqTBE 594 +setct_CertReqTBE 595 +setct_CertReqTBEX 596 +setct_CertResTBE 597 +setct_CRLNotificationTBS 598 +setct_CRLNotificationResTBS 599 +setct_BCIDistributionTBS 600 +setext_genCrypt 601 +setext_miAuth 602 +setext_pinSecure 603 +setext_pinAny 604 +setext_track2 605 +setext_cv 606 +set_policy_root 607 +setCext_hashedRoot 608 +setCext_certType 609 +setCext_merchData 610 +setCext_cCertRequired 611 +setCext_tunneling 612 +setCext_setExt 613 +setCext_setQualf 614 +setCext_PGWYcapabilities 615 +setCext_TokenIdentifier 616 +setCext_Track2Data 617 +setCext_TokenType 618 +setCext_IssuerCapabilities 619 +setAttr_Cert 620 +setAttr_PGWYcap 621 +setAttr_TokenType 622 +setAttr_IssCap 623 +set_rootKeyThumb 624 +set_addPolicy 625 +setAttr_Token_EMV 626 +setAttr_Token_B0Prime 627 +setAttr_IssCap_CVM 628 +setAttr_IssCap_T2 629 +setAttr_IssCap_Sig 630 +setAttr_GenCryptgrm 631 +setAttr_T2Enc 632 +setAttr_T2cleartxt 633 +setAttr_TokICCsig 634 +setAttr_SecDevSig 635 +set_brand_IATA_ATA 636 +set_brand_Diners 637 +set_brand_AmericanExpress 638 +set_brand_JCB 639 +set_brand_Visa 640 +set_brand_MasterCard 641 +set_brand_Novus 642 +des_cdmf 643 +rsaOAEPEncryptionSET 644 +itu_t 645 +joint_iso_itu_t 646 +international_organizations 647 +ms_smartcard_login 648 +ms_upn 649 +aes_128_cfb1 650 +aes_192_cfb1 651 +aes_256_cfb1 652 +aes_128_cfb8 653 +aes_192_cfb8 654 +aes_256_cfb8 655 +des_cfb1 656 +des_cfb8 657 +des_ede3_cfb1 658 +des_ede3_cfb8 659 +streetAddress 660 +postalCode 661 +id_ppl 662 +proxyCertInfo 663 +id_ppl_anyLanguage 664 +id_ppl_inheritAll 665 +name_constraints 666 +Independent 667 +sha256WithRSAEncryption 668 +sha384WithRSAEncryption 669 +sha512WithRSAEncryption 670 +sha224WithRSAEncryption 671 +sha256 672 +sha384 673 +sha512 674 +sha224 675 +identified_organization 676 +certicom_arc 677 +wap 678 +wap_wsg 679 +X9_62_id_characteristic_two_basis 680 +X9_62_onBasis 681 +X9_62_tpBasis 682 +X9_62_ppBasis 683 +X9_62_c2pnb163v1 684 +X9_62_c2pnb163v2 685 +X9_62_c2pnb163v3 686 +X9_62_c2pnb176v1 687 +X9_62_c2tnb191v1 688 +X9_62_c2tnb191v2 689 +X9_62_c2tnb191v3 690 +X9_62_c2onb191v4 691 +X9_62_c2onb191v5 692 +X9_62_c2pnb208w1 693 +X9_62_c2tnb239v1 694 +X9_62_c2tnb239v2 695 +X9_62_c2tnb239v3 696 +X9_62_c2onb239v4 697 +X9_62_c2onb239v5 698 +X9_62_c2pnb272w1 699 +X9_62_c2pnb304w1 700 +X9_62_c2tnb359v1 701 +X9_62_c2pnb368w1 702 +X9_62_c2tnb431r1 703 +secp112r1 704 +secp112r2 705 +secp128r1 706 +secp128r2 707 +secp160k1 708 +secp160r1 709 +secp160r2 710 +secp192k1 711 +secp224k1 712 +secp224r1 713 +secp256k1 714 +secp384r1 715 +secp521r1 716 +sect113r1 717 +sect113r2 718 +sect131r1 719 +sect131r2 720 +sect163k1 721 +sect163r1 722 +sect163r2 723 +sect193r1 724 +sect193r2 725 +sect233k1 726 +sect233r1 727 +sect239k1 728 +sect283k1 729 +sect283r1 730 +sect409k1 731 +sect409r1 732 +sect571k1 733 +sect571r1 734 +wap_wsg_idm_ecid_wtls1 735 +wap_wsg_idm_ecid_wtls3 736 +wap_wsg_idm_ecid_wtls4 737 +wap_wsg_idm_ecid_wtls5 738 +wap_wsg_idm_ecid_wtls6 739 +wap_wsg_idm_ecid_wtls7 740 +wap_wsg_idm_ecid_wtls8 741 +wap_wsg_idm_ecid_wtls9 742 +wap_wsg_idm_ecid_wtls10 743 +wap_wsg_idm_ecid_wtls11 744 +wap_wsg_idm_ecid_wtls12 745 +any_policy 746 +policy_mappings 747 +inhibit_any_policy 748 +ipsec3 749 +ipsec4 750 +camellia_128_cbc 751 +camellia_192_cbc 752 +camellia_256_cbc 753 +camellia_128_ecb 754 +camellia_192_ecb 755 +camellia_256_ecb 756 +camellia_128_cfb128 757 +camellia_192_cfb128 758 +camellia_256_cfb128 759 +camellia_128_cfb1 760 +camellia_192_cfb1 761 +camellia_256_cfb1 762 +camellia_128_cfb8 763 +camellia_192_cfb8 764 +camellia_256_cfb8 765 +camellia_128_ofb128 766 +camellia_192_ofb128 767 +camellia_256_ofb128 768 +subject_directory_attributes 769 +issuing_distribution_point 770 +certificate_issuer 771 +korea 772 +kisa 773 +kftc 774 +npki_alg 775 +seed_ecb 776 +seed_cbc 777 +seed_ofb128 778 +seed_cfb128 779 +hmac_md5 780 +hmac_sha1 781 +id_PasswordBasedMAC 782 +id_DHBasedMac 783 +id_it_suppLangTags 784 +caRepository 785 +id_smime_ct_compressedData 786 +id_ct_asciiTextWithCRLF 787 +id_aes128_wrap 788 +id_aes192_wrap 789 +id_aes256_wrap 790 +ecdsa_with_Recommended 791 +ecdsa_with_Specified 792 +ecdsa_with_SHA224 793 +ecdsa_with_SHA256 794 +ecdsa_with_SHA384 795 +ecdsa_with_SHA512 796 +hmacWithMD5 797 +hmacWithSHA224 798 +hmacWithSHA256 799 +hmacWithSHA384 800 +hmacWithSHA512 801 +dsa_with_SHA224 802 +dsa_with_SHA256 803 +whirlpool 804 +cryptopro 805 +cryptocom 806 +id_GostR3411_94_with_GostR3410_2001 807 +id_GostR3411_94_with_GostR3410_94 808 +id_GostR3411_94 809 +id_HMACGostR3411_94 810 +id_GostR3410_2001 811 +id_GostR3410_94 812 +id_Gost28147_89 813 +gost89_cnt 814 +id_Gost28147_89_MAC 815 +id_GostR3411_94_prf 816 +id_GostR3410_2001DH 817 +id_GostR3410_94DH 818 +id_Gost28147_89_CryptoPro_KeyMeshing 819 +id_Gost28147_89_None_KeyMeshing 820 +id_GostR3411_94_TestParamSet 821 +id_GostR3411_94_CryptoProParamSet 822 +id_Gost28147_89_TestParamSet 823 +id_Gost28147_89_CryptoPro_A_ParamSet 824 +id_Gost28147_89_CryptoPro_B_ParamSet 825 +id_Gost28147_89_CryptoPro_C_ParamSet 826 +id_Gost28147_89_CryptoPro_D_ParamSet 827 +id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet 828 +id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet 829 +id_Gost28147_89_CryptoPro_RIC_1_ParamSet 830 +id_GostR3410_94_TestParamSet 831 +id_GostR3410_94_CryptoPro_A_ParamSet 832 +id_GostR3410_94_CryptoPro_B_ParamSet 833 +id_GostR3410_94_CryptoPro_C_ParamSet 834 +id_GostR3410_94_CryptoPro_D_ParamSet 835 +id_GostR3410_94_CryptoPro_XchA_ParamSet 836 +id_GostR3410_94_CryptoPro_XchB_ParamSet 837 +id_GostR3410_94_CryptoPro_XchC_ParamSet 838 +id_GostR3410_2001_TestParamSet 839 +id_GostR3410_2001_CryptoPro_A_ParamSet 840 +id_GostR3410_2001_CryptoPro_B_ParamSet 841 +id_GostR3410_2001_CryptoPro_C_ParamSet 842 +id_GostR3410_2001_CryptoPro_XchA_ParamSet 843 +id_GostR3410_2001_CryptoPro_XchB_ParamSet 844 +id_GostR3410_94_a 845 +id_GostR3410_94_aBis 846 +id_GostR3410_94_b 847 +id_GostR3410_94_bBis 848 +id_Gost28147_89_cc 849 +id_GostR3410_94_cc 850 +id_GostR3410_2001_cc 851 +id_GostR3411_94_with_GostR3410_94_cc 852 +id_GostR3411_94_with_GostR3410_2001_cc 853 +id_GostR3410_2001_ParamSet_cc 854 +hmac 855 +LocalKeySet 856 +freshest_crl 857 +id_on_permanentIdentifier 858 +searchGuide 859 +businessCategory 860 +postalAddress 861 +postOfficeBox 862 +physicalDeliveryOfficeName 863 +telephoneNumber 864 +telexNumber 865 +teletexTerminalIdentifier 866 +facsimileTelephoneNumber 867 +x121Address 868 +internationaliSDNNumber 869 +registeredAddress 870 +destinationIndicator 871 +preferredDeliveryMethod 872 +presentationAddress 873 +supportedApplicationContext 874 +member 875 +owner 876 +roleOccupant 877 +seeAlso 878 +userPassword 879 +userCertificate 880 +cACertificate 881 +authorityRevocationList 882 +certificateRevocationList 883 +crossCertificatePair 884 +enhancedSearchGuide 885 +protocolInformation 886 +distinguishedName 887 +uniqueMember 888 +houseIdentifier 889 +supportedAlgorithms 890 +deltaRevocationList 891 +dmdName 892 +id_alg_PWRI_KEK 893 +cmac 894 +aes_128_gcm 895 +aes_128_ccm 896 +id_aes128_wrap_pad 897 +aes_192_gcm 898 +aes_192_ccm 899 +id_aes192_wrap_pad 900 +aes_256_gcm 901 +aes_256_ccm 902 +id_aes256_wrap_pad 903 +aes_128_ctr 904 +aes_192_ctr 905 +aes_256_ctr 906 +id_camellia128_wrap 907 +id_camellia192_wrap 908 +id_camellia256_wrap 909 +anyExtendedKeyUsage 910 +mgf1 911 +rsassaPss 912 +aes_128_xts 913 +aes_256_xts 914 +rc4_hmac_md5 915 +aes_128_cbc_hmac_sha1 916 +aes_192_cbc_hmac_sha1 917 +aes_256_cbc_hmac_sha1 918 +rsaesOaep 919 +dhpublicnumber 920 +brainpoolP160r1 921 +brainpoolP160t1 922 +brainpoolP192r1 923 +brainpoolP192t1 924 +brainpoolP224r1 925 +brainpoolP224t1 926 +brainpoolP256r1 927 +brainpoolP256t1 928 +brainpoolP320r1 929 +brainpoolP320t1 930 +brainpoolP384r1 931 +brainpoolP384t1 932 +brainpoolP512r1 933 +brainpoolP512t1 934 +pSpecified 935 +dhSinglePass_stdDH_sha1kdf_scheme 936 +dhSinglePass_stdDH_sha224kdf_scheme 937 +dhSinglePass_stdDH_sha256kdf_scheme 938 +dhSinglePass_stdDH_sha384kdf_scheme 939 +dhSinglePass_stdDH_sha512kdf_scheme 940 +dhSinglePass_cofactorDH_sha1kdf_scheme 941 +dhSinglePass_cofactorDH_sha224kdf_scheme 942 +dhSinglePass_cofactorDH_sha256kdf_scheme 943 +dhSinglePass_cofactorDH_sha384kdf_scheme 944 +dhSinglePass_cofactorDH_sha512kdf_scheme 945 +dh_std_kdf 946 +dh_cofactor_kdf 947 +aes_128_cbc_hmac_sha256 948 +aes_192_cbc_hmac_sha256 949 +aes_256_cbc_hmac_sha256 950 +ct_precert_scts 951 +ct_precert_poison 952 +ct_precert_signer 953 +ct_cert_scts 954 +jurisdictionLocalityName 955 +jurisdictionStateOrProvinceName 956 +jurisdictionCountryName 957 +aes_128_ocb 958 +aes_192_ocb 959 +aes_256_ocb 960 +camellia_128_gcm 961 +camellia_128_ccm 962 +camellia_128_ctr 963 +camellia_128_cmac 964 +camellia_192_gcm 965 +camellia_192_ccm 966 +camellia_192_ctr 967 +camellia_192_cmac 968 +camellia_256_gcm 969 +camellia_256_ccm 970 +camellia_256_ctr 971 +camellia_256_cmac 972 +id_scrypt 973 +id_tc26 974 +gost89_cnt_12 975 +gost_mac_12 976 +id_tc26_algorithms 977 +id_tc26_sign 978 +id_GostR3410_2012_256 979 +id_GostR3410_2012_512 980 +id_tc26_digest 981 +id_GostR3411_2012_256 982 +id_GostR3411_2012_512 983 +id_tc26_signwithdigest 984 +id_tc26_signwithdigest_gost3410_2012_256 985 +id_tc26_signwithdigest_gost3410_2012_512 986 +id_tc26_mac 987 +id_tc26_hmac_gost_3411_2012_256 988 +id_tc26_hmac_gost_3411_2012_512 989 +id_tc26_cipher 990 +id_tc26_agreement 991 +id_tc26_agreement_gost_3410_2012_256 992 +id_tc26_agreement_gost_3410_2012_512 993 +id_tc26_constants 994 +id_tc26_sign_constants 995 +id_tc26_gost_3410_2012_512_constants 996 +id_tc26_gost_3410_2012_512_paramSetTest 997 +id_tc26_gost_3410_2012_512_paramSetA 998 +id_tc26_gost_3410_2012_512_paramSetB 999 +id_tc26_digest_constants 1000 +id_tc26_cipher_constants 1001 +id_tc26_gost_28147_constants 1002 +id_tc26_gost_28147_param_Z 1003 +INN 1004 +OGRN 1005 +SNILS 1006 +subjectSignTool 1007 +issuerSignTool 1008 +gost89_cbc 1009 +gost89_ecb 1010 +gost89_ctr 1011 +grasshopper_ecb 1012 +grasshopper_ctr 1013 +grasshopper_ofb 1014 +grasshopper_cbc 1015 +grasshopper_cfb 1016 +grasshopper_mac 1017 +chacha20_poly1305 1018 +chacha20 1019 +tlsfeature 1020 +tls1_prf 1021 +ipsec_IKE 1022 +capwapAC 1023 +capwapWTP 1024 +sshClient 1025 +sshServer 1026 +sendRouter 1027 +sendProxiedRouter 1028 +sendOwner 1029 +sendProxiedOwner 1030 +id_pkinit 1031 +pkInitClientAuth 1032 +pkInitKDC 1033 +X25519 1034 +X448 1035 +hkdf 1036 +kx_rsa 1037 +kx_ecdhe 1038 +kx_dhe 1039 +kx_ecdhe_psk 1040 +kx_dhe_psk 1041 +kx_rsa_psk 1042 +kx_psk 1043 +kx_srp 1044 +kx_gost 1045 +auth_rsa 1046 +auth_ecdsa 1047 +auth_psk 1048 +auth_dss 1049 +auth_gost01 1050 +auth_gost12 1051 +auth_srp 1052 +auth_null 1053 +fips_none 1054 +fips_140_2 1055 +blake2b512 1056 +blake2s256 1057 +id_smime_ct_contentCollection 1058 +id_smime_ct_authEnvelopedData 1059 +id_ct_xml 1060 +poly1305 1061 +siphash 1062 +kx_any 1063 +auth_any 1064 +aria_128_ecb 1065 +aria_128_cbc 1066 +aria_128_cfb128 1067 +aria_128_ofb128 1068 +aria_128_ctr 1069 +aria_192_ecb 1070 +aria_192_cbc 1071 +aria_192_cfb128 1072 +aria_192_ofb128 1073 +aria_192_ctr 1074 +aria_256_ecb 1075 +aria_256_cbc 1076 +aria_256_cfb128 1077 +aria_256_ofb128 1078 +aria_256_ctr 1079 +aria_128_cfb1 1080 +aria_192_cfb1 1081 +aria_256_cfb1 1082 +aria_128_cfb8 1083 +aria_192_cfb8 1084 +aria_256_cfb8 1085 +id_smime_aa_signingCertificateV2 1086 +ED25519 1087 +ED448 1088 +organizationIdentifier 1089 +countryCode3c 1090 +countryCode3n 1091 +dnsName 1092 +x509ExtAdmission 1093 +sha512_224 1094 +sha512_256 1095 +sha3_224 1096 +sha3_256 1097 +sha3_384 1098 +sha3_512 1099 +shake128 1100 +shake256 1101 +hmac_sha3_224 1102 +hmac_sha3_256 1103 +hmac_sha3_384 1104 +hmac_sha3_512 1105 +dsa_with_SHA384 1106 +dsa_with_SHA512 1107 +dsa_with_SHA3_224 1108 +dsa_with_SHA3_256 1109 +dsa_with_SHA3_384 1110 +dsa_with_SHA3_512 1111 +ecdsa_with_SHA3_224 1112 +ecdsa_with_SHA3_256 1113 +ecdsa_with_SHA3_384 1114 +ecdsa_with_SHA3_512 1115 +RSA_SHA3_224 1116 +RSA_SHA3_256 1117 +RSA_SHA3_384 1118 +RSA_SHA3_512 1119 +aria_128_ccm 1120 +aria_192_ccm 1121 +aria_256_ccm 1122 +aria_128_gcm 1123 +aria_192_gcm 1124 +aria_256_gcm 1125 +ffdhe2048 1126 +ffdhe3072 1127 +ffdhe4096 1128 +ffdhe6144 1129 +ffdhe8192 1130 +cmcCA 1131 +cmcRA 1132 +sm4_ecb 1133 +sm4_cbc 1134 +sm4_ofb128 1135 +sm4_cfb1 1136 +sm4_cfb128 1137 +sm4_cfb8 1138 +sm4_ctr 1139 +ISO_CN 1140 +oscca 1141 +sm_scheme 1142 +sm3 1143 +sm3WithRSAEncryption 1144 +sha512_224WithRSAEncryption 1145 +sha512_256WithRSAEncryption 1146 +id_tc26_gost_3410_2012_256_constants 1147 +id_tc26_gost_3410_2012_256_paramSetA 1148 +id_tc26_gost_3410_2012_512_paramSetC 1149 +ISO_UA 1150 +ua_pki 1151 +dstu28147 1152 +dstu28147_ofb 1153 +dstu28147_cfb 1154 +dstu28147_wrap 1155 +hmacWithDstu34311 1156 +dstu34311 1157 +dstu4145le 1158 +dstu4145be 1159 +uacurve0 1160 +uacurve1 1161 +uacurve2 1162 +uacurve3 1163 +uacurve4 1164 +uacurve5 1165 +uacurve6 1166 +uacurve7 1167 +uacurve8 1168 +uacurve9 1169 +ieee 1170 +ieee_siswg 1171 +sm2 1172 +id_tc26_cipher_gostr3412_2015_magma 1173 +id_tc26_cipher_gostr3412_2015_magma_ctracpkm 1174 +id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac 1175 +id_tc26_cipher_gostr3412_2015_kuznyechik 1176 +id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm 1177 +id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac 1178 +id_tc26_wrap 1179 +id_tc26_wrap_gostr3412_2015_magma 1180 +id_tc26_wrap_gostr3412_2015_magma_kexp15 1181 +id_tc26_wrap_gostr3412_2015_kuznyechik 1182 +id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 1183 +id_tc26_gost_3410_2012_256_paramSetB 1184 +id_tc26_gost_3410_2012_256_paramSetC 1185 +id_tc26_gost_3410_2012_256_paramSetD 1186 +magma_ecb 1187 +magma_ctr 1188 +magma_ofb 1189 +magma_cbc 1190 +magma_cfb 1191 +magma_mac 1192 +hmacWithSHA512_224 1193 +hmacWithSHA512_256 1194 diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_xref.c b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_xref.c new file mode 100644 index 000000000..faf59eb20 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_xref.c @@ -0,0 +1,139 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "obj_xref.h" +#include "internal/nelem.h" +#include + +static STACK_OF(nid_triple) *sig_app, *sigx_app; + +static int sig_cmp(const nid_triple *a, const nid_triple *b) +{ + return a->sign_id - b->sign_id; +} + +DECLARE_OBJ_BSEARCH_CMP_FN(nid_triple, nid_triple, sig); +IMPLEMENT_OBJ_BSEARCH_CMP_FN(nid_triple, nid_triple, sig); + +static int sig_sk_cmp(const nid_triple *const *a, const nid_triple *const *b) +{ + return (*a)->sign_id - (*b)->sign_id; +} + +DECLARE_OBJ_BSEARCH_CMP_FN(const nid_triple *, const nid_triple *, sigx); + +static int sigx_cmp(const nid_triple *const *a, const nid_triple *const *b) +{ + int ret; + ret = (*a)->hash_id - (*b)->hash_id; + if (ret) + return ret; + return (*a)->pkey_id - (*b)->pkey_id; +} + +IMPLEMENT_OBJ_BSEARCH_CMP_FN(const nid_triple *, const nid_triple *, sigx); + +int OBJ_find_sigid_algs(int signid, int *pdig_nid, int *ppkey_nid) +{ + nid_triple tmp; + const nid_triple *rv = NULL; + tmp.sign_id = signid; + + if (sig_app != NULL) { + int idx = sk_nid_triple_find(sig_app, &tmp); + rv = sk_nid_triple_value(sig_app, idx); + } +#ifndef OBJ_XREF_TEST2 + if (rv == NULL) { + rv = OBJ_bsearch_sig(&tmp, sigoid_srt, OSSL_NELEM(sigoid_srt)); + } +#endif + if (rv == NULL) + return 0; + if (pdig_nid) + *pdig_nid = rv->hash_id; + if (ppkey_nid) + *ppkey_nid = rv->pkey_id; + return 1; +} + +int OBJ_find_sigid_by_algs(int *psignid, int dig_nid, int pkey_nid) +{ + nid_triple tmp; + const nid_triple *t = &tmp; + const nid_triple **rv = NULL; + + tmp.hash_id = dig_nid; + tmp.pkey_id = pkey_nid; + + if (sigx_app) { + int idx = sk_nid_triple_find(sigx_app, &tmp); + if (idx >= 0) { + t = sk_nid_triple_value(sigx_app, idx); + rv = &t; + } + } +#ifndef OBJ_XREF_TEST2 + if (rv == NULL) { + rv = OBJ_bsearch_sigx(&t, sigoid_srt_xref, OSSL_NELEM(sigoid_srt_xref)); + } +#endif + if (rv == NULL) + return 0; + if (psignid) + *psignid = (*rv)->sign_id; + return 1; +} + +int OBJ_add_sigid(int signid, int dig_id, int pkey_id) +{ + nid_triple *ntr; + if (sig_app == NULL) + sig_app = sk_nid_triple_new(sig_sk_cmp); + if (sig_app == NULL) + return 0; + if (sigx_app == NULL) + sigx_app = sk_nid_triple_new(sigx_cmp); + if (sigx_app == NULL) + return 0; + if ((ntr = OPENSSL_malloc(sizeof(*ntr))) == NULL) { + OBJerr(OBJ_F_OBJ_ADD_SIGID, ERR_R_MALLOC_FAILURE); + return 0; + } + ntr->sign_id = signid; + ntr->hash_id = dig_id; + ntr->pkey_id = pkey_id; + + if (!sk_nid_triple_push(sig_app, ntr)) { + OPENSSL_free(ntr); + return 0; + } + + if (!sk_nid_triple_push(sigx_app, ntr)) + return 0; + + sk_nid_triple_sort(sig_app); + sk_nid_triple_sort(sigx_app); + + return 1; +} + +static void sid_free(nid_triple *tt) +{ + OPENSSL_free(tt); +} + +void OBJ_sigid_free(void) +{ + sk_nid_triple_pop_free(sig_app, sid_free); + sig_app = NULL; + sk_nid_triple_free(sigx_app); + sigx_app = NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_xref.h b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_xref.h new file mode 100644 index 000000000..9144d569d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_xref.h @@ -0,0 +1,128 @@ +/* + * WARNING: do not edit! + * Generated by objxref.pl + * + * Copyright 1998-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + + +typedef struct { + int sign_id; + int hash_id; + int pkey_id; +} nid_triple; + +DEFINE_STACK_OF(nid_triple) + +static const nid_triple sigoid_srt[] = { + {NID_md2WithRSAEncryption, NID_md2, NID_rsaEncryption}, + {NID_md5WithRSAEncryption, NID_md5, NID_rsaEncryption}, + {NID_shaWithRSAEncryption, NID_sha, NID_rsaEncryption}, + {NID_sha1WithRSAEncryption, NID_sha1, NID_rsaEncryption}, + {NID_dsaWithSHA, NID_sha, NID_dsa}, + {NID_dsaWithSHA1_2, NID_sha1, NID_dsa_2}, + {NID_mdc2WithRSA, NID_mdc2, NID_rsaEncryption}, + {NID_md5WithRSA, NID_md5, NID_rsa}, + {NID_dsaWithSHA1, NID_sha1, NID_dsa}, + {NID_sha1WithRSA, NID_sha1, NID_rsa}, + {NID_ripemd160WithRSA, NID_ripemd160, NID_rsaEncryption}, + {NID_md4WithRSAEncryption, NID_md4, NID_rsaEncryption}, + {NID_ecdsa_with_SHA1, NID_sha1, NID_X9_62_id_ecPublicKey}, + {NID_sha256WithRSAEncryption, NID_sha256, NID_rsaEncryption}, + {NID_sha384WithRSAEncryption, NID_sha384, NID_rsaEncryption}, + {NID_sha512WithRSAEncryption, NID_sha512, NID_rsaEncryption}, + {NID_sha224WithRSAEncryption, NID_sha224, NID_rsaEncryption}, + {NID_ecdsa_with_Recommended, NID_undef, NID_X9_62_id_ecPublicKey}, + {NID_ecdsa_with_Specified, NID_undef, NID_X9_62_id_ecPublicKey}, + {NID_ecdsa_with_SHA224, NID_sha224, NID_X9_62_id_ecPublicKey}, + {NID_ecdsa_with_SHA256, NID_sha256, NID_X9_62_id_ecPublicKey}, + {NID_ecdsa_with_SHA384, NID_sha384, NID_X9_62_id_ecPublicKey}, + {NID_ecdsa_with_SHA512, NID_sha512, NID_X9_62_id_ecPublicKey}, + {NID_dsa_with_SHA224, NID_sha224, NID_dsa}, + {NID_dsa_with_SHA256, NID_sha256, NID_dsa}, + {NID_id_GostR3411_94_with_GostR3410_2001, NID_id_GostR3411_94, + NID_id_GostR3410_2001}, + {NID_id_GostR3411_94_with_GostR3410_94, NID_id_GostR3411_94, + NID_id_GostR3410_94}, + {NID_id_GostR3411_94_with_GostR3410_94_cc, NID_id_GostR3411_94, + NID_id_GostR3410_94_cc}, + {NID_id_GostR3411_94_with_GostR3410_2001_cc, NID_id_GostR3411_94, + NID_id_GostR3410_2001_cc}, + {NID_rsassaPss, NID_undef, NID_rsaEncryption}, + {NID_dhSinglePass_stdDH_sha1kdf_scheme, NID_sha1, NID_dh_std_kdf}, + {NID_dhSinglePass_stdDH_sha224kdf_scheme, NID_sha224, NID_dh_std_kdf}, + {NID_dhSinglePass_stdDH_sha256kdf_scheme, NID_sha256, NID_dh_std_kdf}, + {NID_dhSinglePass_stdDH_sha384kdf_scheme, NID_sha384, NID_dh_std_kdf}, + {NID_dhSinglePass_stdDH_sha512kdf_scheme, NID_sha512, NID_dh_std_kdf}, + {NID_dhSinglePass_cofactorDH_sha1kdf_scheme, NID_sha1, + NID_dh_cofactor_kdf}, + {NID_dhSinglePass_cofactorDH_sha224kdf_scheme, NID_sha224, + NID_dh_cofactor_kdf}, + {NID_dhSinglePass_cofactorDH_sha256kdf_scheme, NID_sha256, + NID_dh_cofactor_kdf}, + {NID_dhSinglePass_cofactorDH_sha384kdf_scheme, NID_sha384, + NID_dh_cofactor_kdf}, + {NID_dhSinglePass_cofactorDH_sha512kdf_scheme, NID_sha512, + NID_dh_cofactor_kdf}, + {NID_id_tc26_signwithdigest_gost3410_2012_256, NID_id_GostR3411_2012_256, + NID_id_GostR3410_2012_256}, + {NID_id_tc26_signwithdigest_gost3410_2012_512, NID_id_GostR3411_2012_512, + NID_id_GostR3410_2012_512}, + {NID_ED25519, NID_undef, NID_ED25519}, + {NID_ED448, NID_undef, NID_ED448}, + {NID_RSA_SHA3_224, NID_sha3_224, NID_rsaEncryption}, + {NID_RSA_SHA3_256, NID_sha3_256, NID_rsaEncryption}, + {NID_RSA_SHA3_384, NID_sha3_384, NID_rsaEncryption}, + {NID_RSA_SHA3_512, NID_sha3_512, NID_rsaEncryption}, +}; + +static const nid_triple *const sigoid_srt_xref[] = { + &sigoid_srt[0], + &sigoid_srt[1], + &sigoid_srt[7], + &sigoid_srt[2], + &sigoid_srt[4], + &sigoid_srt[3], + &sigoid_srt[9], + &sigoid_srt[5], + &sigoid_srt[8], + &sigoid_srt[12], + &sigoid_srt[30], + &sigoid_srt[35], + &sigoid_srt[6], + &sigoid_srt[10], + &sigoid_srt[11], + &sigoid_srt[13], + &sigoid_srt[24], + &sigoid_srt[20], + &sigoid_srt[32], + &sigoid_srt[37], + &sigoid_srt[14], + &sigoid_srt[21], + &sigoid_srt[33], + &sigoid_srt[38], + &sigoid_srt[15], + &sigoid_srt[22], + &sigoid_srt[34], + &sigoid_srt[39], + &sigoid_srt[16], + &sigoid_srt[23], + &sigoid_srt[19], + &sigoid_srt[31], + &sigoid_srt[36], + &sigoid_srt[25], + &sigoid_srt[26], + &sigoid_srt[27], + &sigoid_srt[28], + &sigoid_srt[40], + &sigoid_srt[41], + &sigoid_srt[44], + &sigoid_srt[45], + &sigoid_srt[46], + &sigoid_srt[47], +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_xref.txt b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_xref.txt new file mode 100644 index 000000000..ca3e74461 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/obj_xref.txt @@ -0,0 +1,66 @@ +# OID cross reference table. +# Links signatures OIDs to their corresponding public key algorithms +# and digests. + +md2WithRSAEncryption md2 rsaEncryption +md5WithRSAEncryption md5 rsaEncryption +shaWithRSAEncryption sha rsaEncryption +sha1WithRSAEncryption sha1 rsaEncryption +md4WithRSAEncryption md4 rsaEncryption +sha256WithRSAEncryption sha256 rsaEncryption +sha384WithRSAEncryption sha384 rsaEncryption +sha512WithRSAEncryption sha512 rsaEncryption +sha224WithRSAEncryption sha224 rsaEncryption +mdc2WithRSA mdc2 rsaEncryption +ripemd160WithRSA ripemd160 rsaEncryption +RSA_SHA3_224 sha3_224 rsaEncryption +RSA_SHA3_256 sha3_256 rsaEncryption +RSA_SHA3_384 sha3_384 rsaEncryption +RSA_SHA3_512 sha3_512 rsaEncryption +# For PSS the digest algorithm can vary and depends on the included +# AlgorithmIdentifier. The digest "undef" indicates the public key +# method should handle this explicitly. +rsassaPss undef rsaEncryption +ED25519 undef ED25519 +ED448 undef ED448 + +# Alternative deprecated OIDs. By using the older "rsa" OID this +# type will be recognized by not normally used. + +md5WithRSA md5 rsa +sha1WithRSA sha1 rsa + +dsaWithSHA sha dsa +dsaWithSHA1 sha1 dsa + +dsaWithSHA1_2 sha1 dsa_2 + +ecdsa_with_SHA1 sha1 X9_62_id_ecPublicKey +ecdsa_with_SHA224 sha224 X9_62_id_ecPublicKey +ecdsa_with_SHA256 sha256 X9_62_id_ecPublicKey +ecdsa_with_SHA384 sha384 X9_62_id_ecPublicKey +ecdsa_with_SHA512 sha512 X9_62_id_ecPublicKey +ecdsa_with_Recommended undef X9_62_id_ecPublicKey +ecdsa_with_Specified undef X9_62_id_ecPublicKey + +dsa_with_SHA224 sha224 dsa +dsa_with_SHA256 sha256 dsa + +id_GostR3411_94_with_GostR3410_2001 id_GostR3411_94 id_GostR3410_2001 +id_GostR3411_94_with_GostR3410_94 id_GostR3411_94 id_GostR3410_94 +id_GostR3411_94_with_GostR3410_94_cc id_GostR3411_94 id_GostR3410_94_cc +id_GostR3411_94_with_GostR3410_2001_cc id_GostR3411_94 id_GostR3410_2001_cc +id_tc26_signwithdigest_gost3410_2012_256 id_GostR3411_2012_256 id_GostR3410_2012_256 +id_tc26_signwithdigest_gost3410_2012_512 id_GostR3411_2012_512 id_GostR3410_2012_512 +# ECDH KDFs and their corresponding message digests and schemes +dhSinglePass_stdDH_sha1kdf_scheme sha1 dh_std_kdf +dhSinglePass_stdDH_sha224kdf_scheme sha224 dh_std_kdf +dhSinglePass_stdDH_sha256kdf_scheme sha256 dh_std_kdf +dhSinglePass_stdDH_sha384kdf_scheme sha384 dh_std_kdf +dhSinglePass_stdDH_sha512kdf_scheme sha512 dh_std_kdf + +dhSinglePass_cofactorDH_sha1kdf_scheme sha1 dh_cofactor_kdf +dhSinglePass_cofactorDH_sha224kdf_scheme sha224 dh_cofactor_kdf +dhSinglePass_cofactorDH_sha256kdf_scheme sha256 dh_cofactor_kdf +dhSinglePass_cofactorDH_sha384kdf_scheme sha384 dh_cofactor_kdf +dhSinglePass_cofactorDH_sha512kdf_scheme sha512 dh_cofactor_kdf diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/objects/objects.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/objects.pl new file mode 100644 index 000000000..d7d1962c9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/objects.pl @@ -0,0 +1,203 @@ +#! /usr/bin/env perl +# Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use Getopt::Std; + +our($opt_n); +getopts('n'); + +# Output year depends on the year of the script and the input file. +my $YEAR = [localtime([stat($0)]->[9])]->[5] + 1900; +my $iYEAR = [localtime([stat($ARGV[0])]->[9])]->[5] + 1900; +$YEAR = $iYEAR if $iYEAR > $YEAR; +$iYEAR = [localtime([stat($ARGV[1])]->[9])]->[5] + 1900; +$YEAR = $iYEAR if $iYEAR > $YEAR; + +open (NUMIN,"$ARGV[1]") || die "Can't open number file $ARGV[1]"; +$max_nid=0; +$o=0; +while() + { + s|\R$||; + $o++; + s/#.*$//; + next if /^\s*$/; + $_ = 'X'.$_; + ($Cname,$mynum) = split; + $Cname =~ s/^X//; + if (defined($nidn{$mynum})) + { die "$ARGV[1]:$o:There's already an object with NID ",$mynum," on line ",$order{$mynum},"\n"; } + if (defined($nid{$Cname})) + { die "$ARGV[1]:$o:There's already an object with name ",$Cname," on line ",$order{$nid{$Cname}},"\n"; } + $nid{$Cname} = $mynum; + $nidn{$mynum} = $Cname; + $order{$mynum} = $o; + $max_nid = $mynum if $mynum > $max_nid; + } +close NUMIN; + +open (IN,"$ARGV[0]") || die "Can't open input file $ARGV[0]"; +$Cname=""; +$o=0; +while () + { + s|\R$||; + $o++; + if (/^!module\s+(.*)$/) + { + $module = $1."-"; + $module =~ s/\./_/g; + $module =~ s/-/_/g; + } + if (/^!global$/) + { $module = ""; } + if (/^!Cname\s+(.*)$/) + { $Cname = $1; } + if (/^!Alias\s+(.+?)\s+(.*)$/) + { + $Cname = $module.$1; + $myoid = $2; + $myoid = &process_oid($myoid); + $Cname =~ s/-/_/g; + $ordern{$o} = $Cname; + $order{$Cname} = $o; + $obj{$Cname} = $myoid; + $_ = ""; + $Cname = ""; + } + s/!.*$//; + s/#.*$//; + next if /^\s*$/; + ($myoid,$mysn,$myln) = split ':'; + $mysn =~ s/^\s*//; + $mysn =~ s/\s*$//; + $myln =~ s/^\s*//; + $myln =~ s/\s*$//; + $myoid =~ s/^\s*//; + $myoid =~ s/\s*$//; + if ($myoid ne "") + { + $myoid = &process_oid($myoid); + } + + if ($Cname eq "" && ($myln =~ /^[_A-Za-z][\w.-]*$/ )) + { + $Cname = $myln; + $Cname =~ s/\./_/g; + $Cname =~ s/-/_/g; + if ($Cname ne "" && defined($ln{$module.$Cname})) + { die "objects.txt:$o:There's already an object with long name ",$ln{$module.$Cname}," on line ",$order{$module.$Cname},"\n"; } + } + if ($Cname eq "") + { + $Cname = $mysn; + $Cname =~ s/-/_/g; + if ($Cname ne "" && defined($sn{$module.$Cname})) + { die "objects.txt:$o:There's already an object with short name ",$sn{$module.$Cname}," on line ",$order{$module.$Cname},"\n"; } + } + if ($Cname eq "") + { + $Cname = $myln; + $Cname =~ s/-/_/g; + $Cname =~ s/\./_/g; + $Cname =~ s/ /_/g; + if ($Cname ne "" && defined($ln{$module.$Cname})) + { die "objects.txt:$o:There's already an object with long name ",$ln{$module.$Cname}," on line ",$order{$module.$Cname},"\n"; } + } + $Cname =~ s/\./_/g; + $Cname =~ s/-/_/g; + $Cname = $module.$Cname; + $ordern{$o} = $Cname; + $order{$Cname} = $o; + $sn{$Cname} = $mysn; + $ln{$Cname} = $myln; + $obj{$Cname} = $myoid; + if (!defined($nid{$Cname})) + { + $max_nid++; + $nid{$Cname} = $max_nid; + $nidn{$max_nid} = $Cname; +print STDERR "Added OID $Cname\n"; + } + $Cname=""; + } +close IN; + +if ( $opt_n ) { + foreach (sort { $a <=> $b } keys %nidn) + { + print $nidn{$_},"\t\t",$_,"\n"; + } + exit; +} + +print <<"EOF"; +/* + * WARNING: do not edit! + * Generated by crypto/objects/objects.pl + * + * Copyright 2000-$YEAR The OpenSSL Project Authors. All Rights Reserved. + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#define SN_undef "UNDEF" +#define LN_undef "undefined" +#define NID_undef 0 +#define OBJ_undef 0L +EOF + +sub expand + { + my $string = shift; + + 1 while $string =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e; + + return $string; + } + +foreach (sort { $a <=> $b } keys %ordern) + { + $Cname=$ordern{$_}; + print "\n"; + print expand("#define SN_$Cname\t\t\"$sn{$Cname}\"\n") if $sn{$Cname} ne ""; + print expand("#define LN_$Cname\t\t\"$ln{$Cname}\"\n") if $ln{$Cname} ne ""; + print expand("#define NID_$Cname\t\t$nid{$Cname}\n") if $nid{$Cname} ne ""; + print expand("#define OBJ_$Cname\t\t$obj{$Cname}\n") if $obj{$Cname} ne ""; + } + +sub process_oid + { + local($oid)=@_; + local(@a,$oid_pref); + + @a = split(/\s+/,$myoid); + $pref_oid = ""; + $pref_sep = ""; + if (!($a[0] =~ /^[0-9]+$/)) + { + $a[0] =~ s/-/_/g; + if (!defined($obj{$a[0]})) + { die "$ARGV[0]:$o:Undefined identifier ",$a[0],"\n"; } + $pref_oid = "OBJ_" . $a[0]; + $pref_sep = ","; + shift @a; + } + $oids = join('L,',@a) . "L"; + if ($oids ne "L") + { + $oids = $pref_oid . $pref_sep . $oids; + } + else + { + $oids = $pref_oid; + } + return($oids); + } diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/objects/objects.txt b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/objects.txt new file mode 100644 index 000000000..6dbc41ce3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/objects.txt @@ -0,0 +1,1677 @@ +# CCITT was renamed to ITU-T quite some time ago +0 : ITU-T : itu-t +!Alias ccitt itu-t + +1 : ISO : iso + +2 : JOINT-ISO-ITU-T : joint-iso-itu-t +!Alias joint-iso-ccitt joint-iso-itu-t + +iso 2 : member-body : ISO Member Body + +iso 3 : identified-organization + +# HMAC OIDs +identified-organization 6 1 5 5 8 1 1 : HMAC-MD5 : hmac-md5 +identified-organization 6 1 5 5 8 1 2 : HMAC-SHA1 : hmac-sha1 + +# "1.3.36.8.3.3" +identified-organization 36 8 3 3 : x509ExtAdmission : Professional Information or basis for Admission + +identified-organization 132 : certicom-arc + +identified-organization 111 : ieee +ieee 2 1619 : ieee-siswg : IEEE Security in Storage Working Group + +joint-iso-itu-t 23 : international-organizations : International Organizations + +international-organizations 43 : wap +wap 1 : wap-wsg + +joint-iso-itu-t 5 1 5 : selected-attribute-types : Selected Attribute Types + +selected-attribute-types 55 : clearance + +member-body 840 : ISO-US : ISO US Member Body +ISO-US 10040 : X9-57 : X9.57 +X9-57 4 : X9cm : X9.57 CM ? + +member-body 156 : ISO-CN : ISO CN Member Body +ISO-CN 10197 : oscca +oscca 1 : sm-scheme + +!Cname dsa +X9cm 1 : DSA : dsaEncryption +X9cm 3 : DSA-SHA1 : dsaWithSHA1 + + +ISO-US 10045 : ansi-X9-62 : ANSI X9.62 +!module X9-62 +!Alias id-fieldType ansi-X9-62 1 +X9-62_id-fieldType 1 : prime-field +X9-62_id-fieldType 2 : characteristic-two-field +X9-62_characteristic-two-field 3 : id-characteristic-two-basis +X9-62_id-characteristic-two-basis 1 : onBasis +X9-62_id-characteristic-two-basis 2 : tpBasis +X9-62_id-characteristic-two-basis 3 : ppBasis +!Alias id-publicKeyType ansi-X9-62 2 +X9-62_id-publicKeyType 1 : id-ecPublicKey +!Alias ellipticCurve ansi-X9-62 3 +!Alias c-TwoCurve X9-62_ellipticCurve 0 +X9-62_c-TwoCurve 1 : c2pnb163v1 +X9-62_c-TwoCurve 2 : c2pnb163v2 +X9-62_c-TwoCurve 3 : c2pnb163v3 +X9-62_c-TwoCurve 4 : c2pnb176v1 +X9-62_c-TwoCurve 5 : c2tnb191v1 +X9-62_c-TwoCurve 6 : c2tnb191v2 +X9-62_c-TwoCurve 7 : c2tnb191v3 +X9-62_c-TwoCurve 8 : c2onb191v4 +X9-62_c-TwoCurve 9 : c2onb191v5 +X9-62_c-TwoCurve 10 : c2pnb208w1 +X9-62_c-TwoCurve 11 : c2tnb239v1 +X9-62_c-TwoCurve 12 : c2tnb239v2 +X9-62_c-TwoCurve 13 : c2tnb239v3 +X9-62_c-TwoCurve 14 : c2onb239v4 +X9-62_c-TwoCurve 15 : c2onb239v5 +X9-62_c-TwoCurve 16 : c2pnb272w1 +X9-62_c-TwoCurve 17 : c2pnb304w1 +X9-62_c-TwoCurve 18 : c2tnb359v1 +X9-62_c-TwoCurve 19 : c2pnb368w1 +X9-62_c-TwoCurve 20 : c2tnb431r1 +!Alias primeCurve X9-62_ellipticCurve 1 +X9-62_primeCurve 1 : prime192v1 +X9-62_primeCurve 2 : prime192v2 +X9-62_primeCurve 3 : prime192v3 +X9-62_primeCurve 4 : prime239v1 +X9-62_primeCurve 5 : prime239v2 +X9-62_primeCurve 6 : prime239v3 +X9-62_primeCurve 7 : prime256v1 +!Alias id-ecSigType ansi-X9-62 4 +!global +X9-62_id-ecSigType 1 : ecdsa-with-SHA1 +X9-62_id-ecSigType 2 : ecdsa-with-Recommended +X9-62_id-ecSigType 3 : ecdsa-with-Specified +ecdsa-with-Specified 1 : ecdsa-with-SHA224 +ecdsa-with-Specified 2 : ecdsa-with-SHA256 +ecdsa-with-Specified 3 : ecdsa-with-SHA384 +ecdsa-with-Specified 4 : ecdsa-with-SHA512 + +# SECG curve OIDs from "SEC 2: Recommended Elliptic Curve Domain Parameters" +# (http://www.secg.org/) +!Alias secg_ellipticCurve certicom-arc 0 +# SECG prime curves OIDs +secg-ellipticCurve 6 : secp112r1 +secg-ellipticCurve 7 : secp112r2 +secg-ellipticCurve 28 : secp128r1 +secg-ellipticCurve 29 : secp128r2 +secg-ellipticCurve 9 : secp160k1 +secg-ellipticCurve 8 : secp160r1 +secg-ellipticCurve 30 : secp160r2 +secg-ellipticCurve 31 : secp192k1 +# NOTE: the curve secp192r1 is the same as prime192v1 defined above +# and is therefore omitted +secg-ellipticCurve 32 : secp224k1 +secg-ellipticCurve 33 : secp224r1 +secg-ellipticCurve 10 : secp256k1 +# NOTE: the curve secp256r1 is the same as prime256v1 defined above +# and is therefore omitted +secg-ellipticCurve 34 : secp384r1 +secg-ellipticCurve 35 : secp521r1 +# SECG characteristic two curves OIDs +secg-ellipticCurve 4 : sect113r1 +secg-ellipticCurve 5 : sect113r2 +secg-ellipticCurve 22 : sect131r1 +secg-ellipticCurve 23 : sect131r2 +secg-ellipticCurve 1 : sect163k1 +secg-ellipticCurve 2 : sect163r1 +secg-ellipticCurve 15 : sect163r2 +secg-ellipticCurve 24 : sect193r1 +secg-ellipticCurve 25 : sect193r2 +secg-ellipticCurve 26 : sect233k1 +secg-ellipticCurve 27 : sect233r1 +secg-ellipticCurve 3 : sect239k1 +secg-ellipticCurve 16 : sect283k1 +secg-ellipticCurve 17 : sect283r1 +secg-ellipticCurve 36 : sect409k1 +secg-ellipticCurve 37 : sect409r1 +secg-ellipticCurve 38 : sect571k1 +secg-ellipticCurve 39 : sect571r1 + +# WAP/TLS curve OIDs (http://www.wapforum.org/) +!Alias wap-wsg-idm-ecid wap-wsg 4 +wap-wsg-idm-ecid 1 : wap-wsg-idm-ecid-wtls1 +wap-wsg-idm-ecid 3 : wap-wsg-idm-ecid-wtls3 +wap-wsg-idm-ecid 4 : wap-wsg-idm-ecid-wtls4 +wap-wsg-idm-ecid 5 : wap-wsg-idm-ecid-wtls5 +wap-wsg-idm-ecid 6 : wap-wsg-idm-ecid-wtls6 +wap-wsg-idm-ecid 7 : wap-wsg-idm-ecid-wtls7 +wap-wsg-idm-ecid 8 : wap-wsg-idm-ecid-wtls8 +wap-wsg-idm-ecid 9 : wap-wsg-idm-ecid-wtls9 +wap-wsg-idm-ecid 10 : wap-wsg-idm-ecid-wtls10 +wap-wsg-idm-ecid 11 : wap-wsg-idm-ecid-wtls11 +wap-wsg-idm-ecid 12 : wap-wsg-idm-ecid-wtls12 + + +ISO-US 113533 7 66 10 : CAST5-CBC : cast5-cbc + : CAST5-ECB : cast5-ecb +!Cname cast5-cfb64 + : CAST5-CFB : cast5-cfb +!Cname cast5-ofb64 + : CAST5-OFB : cast5-ofb +!Cname pbeWithMD5AndCast5-CBC +ISO-US 113533 7 66 12 : : pbeWithMD5AndCast5CBC + +# Macs for CMP and CRMF +ISO-US 113533 7 66 13 : id-PasswordBasedMAC : password based MAC +ISO-US 113533 7 66 30 : id-DHBasedMac : Diffie-Hellman based MAC + +ISO-US 113549 : rsadsi : RSA Data Security, Inc. + +rsadsi 1 : pkcs : RSA Data Security, Inc. PKCS + +pkcs 1 : pkcs1 +pkcs1 1 : : rsaEncryption +pkcs1 2 : RSA-MD2 : md2WithRSAEncryption +pkcs1 3 : RSA-MD4 : md4WithRSAEncryption +pkcs1 4 : RSA-MD5 : md5WithRSAEncryption +pkcs1 5 : RSA-SHA1 : sha1WithRSAEncryption +# According to PKCS #1 version 2.1 +pkcs1 7 : RSAES-OAEP : rsaesOaep +pkcs1 8 : MGF1 : mgf1 +pkcs1 9 : PSPECIFIED : pSpecified +pkcs1 10 : RSASSA-PSS : rsassaPss + +pkcs1 11 : RSA-SHA256 : sha256WithRSAEncryption +pkcs1 12 : RSA-SHA384 : sha384WithRSAEncryption +pkcs1 13 : RSA-SHA512 : sha512WithRSAEncryption +pkcs1 14 : RSA-SHA224 : sha224WithRSAEncryption +pkcs1 15 : RSA-SHA512/224 : sha512-224WithRSAEncryption +pkcs1 16 : RSA-SHA512/256 : sha512-256WithRSAEncryption + +pkcs 3 : pkcs3 +pkcs3 1 : : dhKeyAgreement + +pkcs 5 : pkcs5 +pkcs5 1 : PBE-MD2-DES : pbeWithMD2AndDES-CBC +pkcs5 3 : PBE-MD5-DES : pbeWithMD5AndDES-CBC +pkcs5 4 : PBE-MD2-RC2-64 : pbeWithMD2AndRC2-CBC +pkcs5 6 : PBE-MD5-RC2-64 : pbeWithMD5AndRC2-CBC +pkcs5 10 : PBE-SHA1-DES : pbeWithSHA1AndDES-CBC +pkcs5 11 : PBE-SHA1-RC2-64 : pbeWithSHA1AndRC2-CBC +!Cname id_pbkdf2 +pkcs5 12 : : PBKDF2 +!Cname pbes2 +pkcs5 13 : : PBES2 +!Cname pbmac1 +pkcs5 14 : : PBMAC1 + +pkcs 7 : pkcs7 +pkcs7 1 : : pkcs7-data +!Cname pkcs7-signed +pkcs7 2 : : pkcs7-signedData +!Cname pkcs7-enveloped +pkcs7 3 : : pkcs7-envelopedData +!Cname pkcs7-signedAndEnveloped +pkcs7 4 : : pkcs7-signedAndEnvelopedData +!Cname pkcs7-digest +pkcs7 5 : : pkcs7-digestData +!Cname pkcs7-encrypted +pkcs7 6 : : pkcs7-encryptedData + +pkcs 9 : pkcs9 +!module pkcs9 +pkcs9 1 : : emailAddress +pkcs9 2 : : unstructuredName +pkcs9 3 : : contentType +pkcs9 4 : : messageDigest +pkcs9 5 : : signingTime +pkcs9 6 : : countersignature +pkcs9 7 : : challengePassword +pkcs9 8 : : unstructuredAddress +!Cname extCertAttributes +pkcs9 9 : : extendedCertificateAttributes +!global + +!Cname ext-req +pkcs9 14 : extReq : Extension Request + +!Cname SMIMECapabilities +pkcs9 15 : SMIME-CAPS : S/MIME Capabilities + +# S/MIME +!Cname SMIME +pkcs9 16 : SMIME : S/MIME +SMIME 0 : id-smime-mod +SMIME 1 : id-smime-ct +SMIME 2 : id-smime-aa +SMIME 3 : id-smime-alg +SMIME 4 : id-smime-cd +SMIME 5 : id-smime-spq +SMIME 6 : id-smime-cti + +# S/MIME Modules +id-smime-mod 1 : id-smime-mod-cms +id-smime-mod 2 : id-smime-mod-ess +id-smime-mod 3 : id-smime-mod-oid +id-smime-mod 4 : id-smime-mod-msg-v3 +id-smime-mod 5 : id-smime-mod-ets-eSignature-88 +id-smime-mod 6 : id-smime-mod-ets-eSignature-97 +id-smime-mod 7 : id-smime-mod-ets-eSigPolicy-88 +id-smime-mod 8 : id-smime-mod-ets-eSigPolicy-97 + +# S/MIME Content Types +id-smime-ct 1 : id-smime-ct-receipt +id-smime-ct 2 : id-smime-ct-authData +id-smime-ct 3 : id-smime-ct-publishCert +id-smime-ct 4 : id-smime-ct-TSTInfo +id-smime-ct 5 : id-smime-ct-TDTInfo +id-smime-ct 6 : id-smime-ct-contentInfo +id-smime-ct 7 : id-smime-ct-DVCSRequestData +id-smime-ct 8 : id-smime-ct-DVCSResponseData +id-smime-ct 9 : id-smime-ct-compressedData +id-smime-ct 19 : id-smime-ct-contentCollection +id-smime-ct 23 : id-smime-ct-authEnvelopedData +id-smime-ct 27 : id-ct-asciiTextWithCRLF +id-smime-ct 28 : id-ct-xml + +# S/MIME Attributes +id-smime-aa 1 : id-smime-aa-receiptRequest +id-smime-aa 2 : id-smime-aa-securityLabel +id-smime-aa 3 : id-smime-aa-mlExpandHistory +id-smime-aa 4 : id-smime-aa-contentHint +id-smime-aa 5 : id-smime-aa-msgSigDigest +# obsolete +id-smime-aa 6 : id-smime-aa-encapContentType +id-smime-aa 7 : id-smime-aa-contentIdentifier +# obsolete +id-smime-aa 8 : id-smime-aa-macValue +id-smime-aa 9 : id-smime-aa-equivalentLabels +id-smime-aa 10 : id-smime-aa-contentReference +id-smime-aa 11 : id-smime-aa-encrypKeyPref +id-smime-aa 12 : id-smime-aa-signingCertificate +id-smime-aa 13 : id-smime-aa-smimeEncryptCerts +id-smime-aa 14 : id-smime-aa-timeStampToken +id-smime-aa 15 : id-smime-aa-ets-sigPolicyId +id-smime-aa 16 : id-smime-aa-ets-commitmentType +id-smime-aa 17 : id-smime-aa-ets-signerLocation +id-smime-aa 18 : id-smime-aa-ets-signerAttr +id-smime-aa 19 : id-smime-aa-ets-otherSigCert +id-smime-aa 20 : id-smime-aa-ets-contentTimestamp +id-smime-aa 21 : id-smime-aa-ets-CertificateRefs +id-smime-aa 22 : id-smime-aa-ets-RevocationRefs +id-smime-aa 23 : id-smime-aa-ets-certValues +id-smime-aa 24 : id-smime-aa-ets-revocationValues +id-smime-aa 25 : id-smime-aa-ets-escTimeStamp +id-smime-aa 26 : id-smime-aa-ets-certCRLTimestamp +id-smime-aa 27 : id-smime-aa-ets-archiveTimeStamp +id-smime-aa 28 : id-smime-aa-signatureType +id-smime-aa 29 : id-smime-aa-dvcs-dvc +id-smime-aa 47 : id-smime-aa-signingCertificateV2 + +# S/MIME Algorithm Identifiers +# obsolete +id-smime-alg 1 : id-smime-alg-ESDHwith3DES +# obsolete +id-smime-alg 2 : id-smime-alg-ESDHwithRC2 +# obsolete +id-smime-alg 3 : id-smime-alg-3DESwrap +# obsolete +id-smime-alg 4 : id-smime-alg-RC2wrap +id-smime-alg 5 : id-smime-alg-ESDH +id-smime-alg 6 : id-smime-alg-CMS3DESwrap +id-smime-alg 7 : id-smime-alg-CMSRC2wrap +id-smime-alg 9 : id-alg-PWRI-KEK + +# S/MIME Certificate Distribution +id-smime-cd 1 : id-smime-cd-ldap + +# S/MIME Signature Policy Qualifier +id-smime-spq 1 : id-smime-spq-ets-sqt-uri +id-smime-spq 2 : id-smime-spq-ets-sqt-unotice + +# S/MIME Commitment Type Identifier +id-smime-cti 1 : id-smime-cti-ets-proofOfOrigin +id-smime-cti 2 : id-smime-cti-ets-proofOfReceipt +id-smime-cti 3 : id-smime-cti-ets-proofOfDelivery +id-smime-cti 4 : id-smime-cti-ets-proofOfSender +id-smime-cti 5 : id-smime-cti-ets-proofOfApproval +id-smime-cti 6 : id-smime-cti-ets-proofOfCreation + +pkcs9 20 : : friendlyName +pkcs9 21 : : localKeyID +!Cname ms-csp-name +1 3 6 1 4 1 311 17 1 : CSPName : Microsoft CSP Name +1 3 6 1 4 1 311 17 2 : LocalKeySet : Microsoft Local Key set +!Alias certTypes pkcs9 22 +certTypes 1 : : x509Certificate +certTypes 2 : : sdsiCertificate +!Alias crlTypes pkcs9 23 +crlTypes 1 : : x509Crl + +!Alias pkcs12 pkcs 12 +!Alias pkcs12-pbeids pkcs12 1 + +!Cname pbe-WithSHA1And128BitRC4 +pkcs12-pbeids 1 : PBE-SHA1-RC4-128 : pbeWithSHA1And128BitRC4 +!Cname pbe-WithSHA1And40BitRC4 +pkcs12-pbeids 2 : PBE-SHA1-RC4-40 : pbeWithSHA1And40BitRC4 +!Cname pbe-WithSHA1And3_Key_TripleDES-CBC +pkcs12-pbeids 3 : PBE-SHA1-3DES : pbeWithSHA1And3-KeyTripleDES-CBC +!Cname pbe-WithSHA1And2_Key_TripleDES-CBC +pkcs12-pbeids 4 : PBE-SHA1-2DES : pbeWithSHA1And2-KeyTripleDES-CBC +!Cname pbe-WithSHA1And128BitRC2-CBC +pkcs12-pbeids 5 : PBE-SHA1-RC2-128 : pbeWithSHA1And128BitRC2-CBC +!Cname pbe-WithSHA1And40BitRC2-CBC +pkcs12-pbeids 6 : PBE-SHA1-RC2-40 : pbeWithSHA1And40BitRC2-CBC + +!Alias pkcs12-Version1 pkcs12 10 +!Alias pkcs12-BagIds pkcs12-Version1 1 +pkcs12-BagIds 1 : : keyBag +pkcs12-BagIds 2 : : pkcs8ShroudedKeyBag +pkcs12-BagIds 3 : : certBag +pkcs12-BagIds 4 : : crlBag +pkcs12-BagIds 5 : : secretBag +pkcs12-BagIds 6 : : safeContentsBag + +rsadsi 2 2 : MD2 : md2 +rsadsi 2 4 : MD4 : md4 +rsadsi 2 5 : MD5 : md5 + : MD5-SHA1 : md5-sha1 +rsadsi 2 6 : : hmacWithMD5 +rsadsi 2 7 : : hmacWithSHA1 + +sm-scheme 301 : SM2 : sm2 + +sm-scheme 401 : SM3 : sm3 +sm-scheme 504 : RSA-SM3 : sm3WithRSAEncryption + +# From RFC4231 +rsadsi 2 8 : : hmacWithSHA224 +rsadsi 2 9 : : hmacWithSHA256 +rsadsi 2 10 : : hmacWithSHA384 +rsadsi 2 11 : : hmacWithSHA512 + +# From RFC8018 +rsadsi 2 12 : : hmacWithSHA512-224 +rsadsi 2 13 : : hmacWithSHA512-256 + +rsadsi 3 2 : RC2-CBC : rc2-cbc + : RC2-ECB : rc2-ecb +!Cname rc2-cfb64 + : RC2-CFB : rc2-cfb +!Cname rc2-ofb64 + : RC2-OFB : rc2-ofb + : RC2-40-CBC : rc2-40-cbc + : RC2-64-CBC : rc2-64-cbc +rsadsi 3 4 : RC4 : rc4 + : RC4-40 : rc4-40 +rsadsi 3 7 : DES-EDE3-CBC : des-ede3-cbc +rsadsi 3 8 : RC5-CBC : rc5-cbc + : RC5-ECB : rc5-ecb +!Cname rc5-cfb64 + : RC5-CFB : rc5-cfb +!Cname rc5-ofb64 + : RC5-OFB : rc5-ofb + +!Cname ms-ext-req +1 3 6 1 4 1 311 2 1 14 : msExtReq : Microsoft Extension Request +!Cname ms-code-ind +1 3 6 1 4 1 311 2 1 21 : msCodeInd : Microsoft Individual Code Signing +!Cname ms-code-com +1 3 6 1 4 1 311 2 1 22 : msCodeCom : Microsoft Commercial Code Signing +!Cname ms-ctl-sign +1 3 6 1 4 1 311 10 3 1 : msCTLSign : Microsoft Trust List Signing +!Cname ms-sgc +1 3 6 1 4 1 311 10 3 3 : msSGC : Microsoft Server Gated Crypto +!Cname ms-efs +1 3 6 1 4 1 311 10 3 4 : msEFS : Microsoft Encrypted File System +!Cname ms-smartcard-login +1 3 6 1 4 1 311 20 2 2 : msSmartcardLogin : Microsoft Smartcardlogin +!Cname ms-upn +1 3 6 1 4 1 311 20 2 3 : msUPN : Microsoft Universal Principal Name + +1 3 6 1 4 1 188 7 1 1 2 : IDEA-CBC : idea-cbc + : IDEA-ECB : idea-ecb +!Cname idea-cfb64 + : IDEA-CFB : idea-cfb +!Cname idea-ofb64 + : IDEA-OFB : idea-ofb + +1 3 6 1 4 1 3029 1 2 : BF-CBC : bf-cbc + : BF-ECB : bf-ecb +!Cname bf-cfb64 + : BF-CFB : bf-cfb +!Cname bf-ofb64 + : BF-OFB : bf-ofb + +!Cname id-pkix +1 3 6 1 5 5 7 : PKIX + +# PKIX Arcs +id-pkix 0 : id-pkix-mod +id-pkix 1 : id-pe +id-pkix 2 : id-qt +id-pkix 3 : id-kp +id-pkix 4 : id-it +id-pkix 5 : id-pkip +id-pkix 6 : id-alg +id-pkix 7 : id-cmc +id-pkix 8 : id-on +id-pkix 9 : id-pda +id-pkix 10 : id-aca +id-pkix 11 : id-qcs +id-pkix 12 : id-cct +id-pkix 21 : id-ppl +id-pkix 48 : id-ad + +# PKIX Modules +id-pkix-mod 1 : id-pkix1-explicit-88 +id-pkix-mod 2 : id-pkix1-implicit-88 +id-pkix-mod 3 : id-pkix1-explicit-93 +id-pkix-mod 4 : id-pkix1-implicit-93 +id-pkix-mod 5 : id-mod-crmf +id-pkix-mod 6 : id-mod-cmc +id-pkix-mod 7 : id-mod-kea-profile-88 +id-pkix-mod 8 : id-mod-kea-profile-93 +id-pkix-mod 9 : id-mod-cmp +id-pkix-mod 10 : id-mod-qualified-cert-88 +id-pkix-mod 11 : id-mod-qualified-cert-93 +id-pkix-mod 12 : id-mod-attribute-cert +id-pkix-mod 13 : id-mod-timestamp-protocol +id-pkix-mod 14 : id-mod-ocsp +id-pkix-mod 15 : id-mod-dvcs +id-pkix-mod 16 : id-mod-cmp2000 + +# PKIX Private Extensions +!Cname info-access +id-pe 1 : authorityInfoAccess : Authority Information Access +id-pe 2 : biometricInfo : Biometric Info +id-pe 3 : qcStatements +id-pe 4 : ac-auditEntity +id-pe 5 : ac-targeting +id-pe 6 : aaControls +id-pe 7 : sbgp-ipAddrBlock +id-pe 8 : sbgp-autonomousSysNum +id-pe 9 : sbgp-routerIdentifier +id-pe 10 : ac-proxying +!Cname sinfo-access +id-pe 11 : subjectInfoAccess : Subject Information Access +id-pe 14 : proxyCertInfo : Proxy Certificate Information +id-pe 24 : tlsfeature : TLS Feature + +# PKIX policyQualifiers for Internet policy qualifiers +id-qt 1 : id-qt-cps : Policy Qualifier CPS +id-qt 2 : id-qt-unotice : Policy Qualifier User Notice +id-qt 3 : textNotice + +# PKIX key purpose identifiers +!Cname server-auth +id-kp 1 : serverAuth : TLS Web Server Authentication +!Cname client-auth +id-kp 2 : clientAuth : TLS Web Client Authentication +!Cname code-sign +id-kp 3 : codeSigning : Code Signing +!Cname email-protect +id-kp 4 : emailProtection : E-mail Protection +id-kp 5 : ipsecEndSystem : IPSec End System +id-kp 6 : ipsecTunnel : IPSec Tunnel +id-kp 7 : ipsecUser : IPSec User +!Cname time-stamp +id-kp 8 : timeStamping : Time Stamping +# From OCSP spec RFC2560 +!Cname OCSP-sign +id-kp 9 : OCSPSigning : OCSP Signing +id-kp 10 : DVCS : dvcs +!Cname ipsec-IKE +id-kp 17 : ipsecIKE : ipsec Internet Key Exchange +id-kp 18 : capwapAC : Ctrl/provision WAP Access +id-kp 19 : capwapWTP : Ctrl/Provision WAP Termination +!Cname sshClient +id-kp 21 : secureShellClient : SSH Client +!Cname sshServer +id-kp 22 : secureShellServer : SSH Server +id-kp 23 : sendRouter : Send Router +id-kp 24 : sendProxiedRouter : Send Proxied Router +id-kp 25 : sendOwner : Send Owner +id-kp 26 : sendProxiedOwner : Send Proxied Owner +id-kp 27 : cmcCA : CMC Certificate Authority +id-kp 28 : cmcRA : CMC Registration Authority + +# CMP information types +id-it 1 : id-it-caProtEncCert +id-it 2 : id-it-signKeyPairTypes +id-it 3 : id-it-encKeyPairTypes +id-it 4 : id-it-preferredSymmAlg +id-it 5 : id-it-caKeyUpdateInfo +id-it 6 : id-it-currentCRL +id-it 7 : id-it-unsupportedOIDs +# obsolete +id-it 8 : id-it-subscriptionRequest +# obsolete +id-it 9 : id-it-subscriptionResponse +id-it 10 : id-it-keyPairParamReq +id-it 11 : id-it-keyPairParamRep +id-it 12 : id-it-revPassphrase +id-it 13 : id-it-implicitConfirm +id-it 14 : id-it-confirmWaitTime +id-it 15 : id-it-origPKIMessage +id-it 16 : id-it-suppLangTags + +# CRMF registration +id-pkip 1 : id-regCtrl +id-pkip 2 : id-regInfo + +# CRMF registration controls +id-regCtrl 1 : id-regCtrl-regToken +id-regCtrl 2 : id-regCtrl-authenticator +id-regCtrl 3 : id-regCtrl-pkiPublicationInfo +id-regCtrl 4 : id-regCtrl-pkiArchiveOptions +id-regCtrl 5 : id-regCtrl-oldCertID +id-regCtrl 6 : id-regCtrl-protocolEncrKey + +# CRMF registration information +id-regInfo 1 : id-regInfo-utf8Pairs +id-regInfo 2 : id-regInfo-certReq + +# algorithms +id-alg 1 : id-alg-des40 +id-alg 2 : id-alg-noSignature +id-alg 3 : id-alg-dh-sig-hmac-sha1 +id-alg 4 : id-alg-dh-pop + +# CMC controls +id-cmc 1 : id-cmc-statusInfo +id-cmc 2 : id-cmc-identification +id-cmc 3 : id-cmc-identityProof +id-cmc 4 : id-cmc-dataReturn +id-cmc 5 : id-cmc-transactionId +id-cmc 6 : id-cmc-senderNonce +id-cmc 7 : id-cmc-recipientNonce +id-cmc 8 : id-cmc-addExtensions +id-cmc 9 : id-cmc-encryptedPOP +id-cmc 10 : id-cmc-decryptedPOP +id-cmc 11 : id-cmc-lraPOPWitness +id-cmc 15 : id-cmc-getCert +id-cmc 16 : id-cmc-getCRL +id-cmc 17 : id-cmc-revokeRequest +id-cmc 18 : id-cmc-regInfo +id-cmc 19 : id-cmc-responseInfo +id-cmc 21 : id-cmc-queryPending +id-cmc 22 : id-cmc-popLinkRandom +id-cmc 23 : id-cmc-popLinkWitness +id-cmc 24 : id-cmc-confirmCertAcceptance + +# other names +id-on 1 : id-on-personalData +id-on 3 : id-on-permanentIdentifier : Permanent Identifier + +# personal data attributes +id-pda 1 : id-pda-dateOfBirth +id-pda 2 : id-pda-placeOfBirth +id-pda 3 : id-pda-gender +id-pda 4 : id-pda-countryOfCitizenship +id-pda 5 : id-pda-countryOfResidence + +# attribute certificate attributes +id-aca 1 : id-aca-authenticationInfo +id-aca 2 : id-aca-accessIdentity +id-aca 3 : id-aca-chargingIdentity +id-aca 4 : id-aca-group +# attention : the following seems to be obsolete, replace by 'role' +id-aca 5 : id-aca-role +id-aca 6 : id-aca-encAttrs + +# qualified certificate statements +id-qcs 1 : id-qcs-pkixQCSyntax-v1 + +# CMC content types +id-cct 1 : id-cct-crs +id-cct 2 : id-cct-PKIData +id-cct 3 : id-cct-PKIResponse + +# Predefined Proxy Certificate policy languages +id-ppl 0 : id-ppl-anyLanguage : Any language +id-ppl 1 : id-ppl-inheritAll : Inherit all +id-ppl 2 : id-ppl-independent : Independent + +# access descriptors for authority info access extension +!Cname ad-OCSP +id-ad 1 : OCSP : OCSP +!Cname ad-ca-issuers +id-ad 2 : caIssuers : CA Issuers +!Cname ad-timeStamping +id-ad 3 : ad_timestamping : AD Time Stamping +!Cname ad-dvcs +id-ad 4 : AD_DVCS : ad dvcs +id-ad 5 : caRepository : CA Repository + + +!Alias id-pkix-OCSP ad-OCSP +!module id-pkix-OCSP +!Cname basic +id-pkix-OCSP 1 : basicOCSPResponse : Basic OCSP Response +id-pkix-OCSP 2 : Nonce : OCSP Nonce +id-pkix-OCSP 3 : CrlID : OCSP CRL ID +id-pkix-OCSP 4 : acceptableResponses : Acceptable OCSP Responses +id-pkix-OCSP 5 : noCheck : OCSP No Check +id-pkix-OCSP 6 : archiveCutoff : OCSP Archive Cutoff +id-pkix-OCSP 7 : serviceLocator : OCSP Service Locator +id-pkix-OCSP 8 : extendedStatus : Extended OCSP Status +id-pkix-OCSP 9 : valid +id-pkix-OCSP 10 : path +id-pkix-OCSP 11 : trustRoot : Trust Root +!global + +1 3 14 3 2 : algorithm : algorithm +algorithm 3 : RSA-NP-MD5 : md5WithRSA +algorithm 6 : DES-ECB : des-ecb +algorithm 7 : DES-CBC : des-cbc +!Cname des-ofb64 +algorithm 8 : DES-OFB : des-ofb +!Cname des-cfb64 +algorithm 9 : DES-CFB : des-cfb +algorithm 11 : rsaSignature +!Cname dsa-2 +algorithm 12 : DSA-old : dsaEncryption-old +algorithm 13 : DSA-SHA : dsaWithSHA +algorithm 15 : RSA-SHA : shaWithRSAEncryption +!Cname des-ede-ecb +algorithm 17 : DES-EDE : des-ede +!Cname des-ede3-ecb + : DES-EDE3 : des-ede3 + : DES-EDE-CBC : des-ede-cbc +!Cname des-ede-cfb64 + : DES-EDE-CFB : des-ede-cfb +!Cname des-ede3-cfb64 + : DES-EDE3-CFB : des-ede3-cfb +!Cname des-ede-ofb64 + : DES-EDE-OFB : des-ede-ofb +!Cname des-ede3-ofb64 + : DES-EDE3-OFB : des-ede3-ofb + : DESX-CBC : desx-cbc +algorithm 18 : SHA : sha +algorithm 26 : SHA1 : sha1 +!Cname dsaWithSHA1-2 +algorithm 27 : DSA-SHA1-old : dsaWithSHA1-old +algorithm 29 : RSA-SHA1-2 : sha1WithRSA + +1 3 36 3 2 1 : RIPEMD160 : ripemd160 +1 3 36 3 3 1 2 : RSA-RIPEMD160 : ripemd160WithRSA + +1 3 6 1 4 1 1722 12 2 1 16 : BLAKE2b512 : blake2b512 +1 3 6 1 4 1 1722 12 2 2 8 : BLAKE2s256 : blake2s256 + +!Cname sxnet +1 3 101 1 4 1 : SXNetID : Strong Extranet ID + +2 5 : X500 : directory services (X.500) + +X500 4 : X509 +X509 3 : CN : commonName +X509 4 : SN : surname +X509 5 : : serialNumber +X509 6 : C : countryName +X509 7 : L : localityName +X509 8 : ST : stateOrProvinceName +X509 9 : street : streetAddress +X509 10 : O : organizationName +X509 11 : OU : organizationalUnitName +X509 12 : title : title +X509 13 : : description +X509 14 : : searchGuide +X509 15 : : businessCategory +X509 16 : : postalAddress +X509 17 : : postalCode +X509 18 : : postOfficeBox +X509 19 : : physicalDeliveryOfficeName +X509 20 : : telephoneNumber +X509 21 : : telexNumber +X509 22 : : teletexTerminalIdentifier +X509 23 : : facsimileTelephoneNumber +X509 24 : : x121Address +X509 25 : : internationaliSDNNumber +X509 26 : : registeredAddress +X509 27 : : destinationIndicator +X509 28 : : preferredDeliveryMethod +X509 29 : : presentationAddress +X509 30 : : supportedApplicationContext +X509 31 : member : +X509 32 : owner : +X509 33 : : roleOccupant +X509 34 : seeAlso : +X509 35 : : userPassword +X509 36 : : userCertificate +X509 37 : : cACertificate +X509 38 : : authorityRevocationList +X509 39 : : certificateRevocationList +X509 40 : : crossCertificatePair +X509 41 : name : name +X509 42 : GN : givenName +X509 43 : initials : initials +X509 44 : : generationQualifier +X509 45 : : x500UniqueIdentifier +X509 46 : dnQualifier : dnQualifier +X509 47 : : enhancedSearchGuide +X509 48 : : protocolInformation +X509 49 : : distinguishedName +X509 50 : : uniqueMember +X509 51 : : houseIdentifier +X509 52 : : supportedAlgorithms +X509 53 : : deltaRevocationList +X509 54 : dmdName : +X509 65 : : pseudonym +X509 72 : role : role +X509 97 : : organizationIdentifier +X509 98 : c3 : countryCode3c +X509 99 : n3 : countryCode3n +X509 100 : : dnsName + + +X500 8 : X500algorithms : directory services - algorithms +X500algorithms 1 1 : RSA : rsa +X500algorithms 3 100 : RSA-MDC2 : mdc2WithRSA +X500algorithms 3 101 : MDC2 : mdc2 + +X500 29 : id-ce +!Cname subject-directory-attributes +id-ce 9 : subjectDirectoryAttributes : X509v3 Subject Directory Attributes +!Cname subject-key-identifier +id-ce 14 : subjectKeyIdentifier : X509v3 Subject Key Identifier +!Cname key-usage +id-ce 15 : keyUsage : X509v3 Key Usage +!Cname private-key-usage-period +id-ce 16 : privateKeyUsagePeriod : X509v3 Private Key Usage Period +!Cname subject-alt-name +id-ce 17 : subjectAltName : X509v3 Subject Alternative Name +!Cname issuer-alt-name +id-ce 18 : issuerAltName : X509v3 Issuer Alternative Name +!Cname basic-constraints +id-ce 19 : basicConstraints : X509v3 Basic Constraints +!Cname crl-number +id-ce 20 : crlNumber : X509v3 CRL Number +!Cname crl-reason +id-ce 21 : CRLReason : X509v3 CRL Reason Code +!Cname invalidity-date +id-ce 24 : invalidityDate : Invalidity Date +!Cname delta-crl +id-ce 27 : deltaCRL : X509v3 Delta CRL Indicator +!Cname issuing-distribution-point +id-ce 28 : issuingDistributionPoint : X509v3 Issuing Distribution Point +!Cname certificate-issuer +id-ce 29 : certificateIssuer : X509v3 Certificate Issuer +!Cname name-constraints +id-ce 30 : nameConstraints : X509v3 Name Constraints +!Cname crl-distribution-points +id-ce 31 : crlDistributionPoints : X509v3 CRL Distribution Points +!Cname certificate-policies +id-ce 32 : certificatePolicies : X509v3 Certificate Policies +!Cname any-policy +certificate-policies 0 : anyPolicy : X509v3 Any Policy +!Cname policy-mappings +id-ce 33 : policyMappings : X509v3 Policy Mappings +!Cname authority-key-identifier +id-ce 35 : authorityKeyIdentifier : X509v3 Authority Key Identifier +!Cname policy-constraints +id-ce 36 : policyConstraints : X509v3 Policy Constraints +!Cname ext-key-usage +id-ce 37 : extendedKeyUsage : X509v3 Extended Key Usage +!Cname freshest-crl +id-ce 46 : freshestCRL : X509v3 Freshest CRL +!Cname inhibit-any-policy +id-ce 54 : inhibitAnyPolicy : X509v3 Inhibit Any Policy +!Cname target-information +id-ce 55 : targetInformation : X509v3 AC Targeting +!Cname no-rev-avail +id-ce 56 : noRevAvail : X509v3 No Revocation Available + +# From RFC5280 +ext-key-usage 0 : anyExtendedKeyUsage : Any Extended Key Usage + + +!Cname netscape +2 16 840 1 113730 : Netscape : Netscape Communications Corp. +!Cname netscape-cert-extension +netscape 1 : nsCertExt : Netscape Certificate Extension +!Cname netscape-data-type +netscape 2 : nsDataType : Netscape Data Type +!Cname netscape-cert-type +netscape-cert-extension 1 : nsCertType : Netscape Cert Type +!Cname netscape-base-url +netscape-cert-extension 2 : nsBaseUrl : Netscape Base Url +!Cname netscape-revocation-url +netscape-cert-extension 3 : nsRevocationUrl : Netscape Revocation Url +!Cname netscape-ca-revocation-url +netscape-cert-extension 4 : nsCaRevocationUrl : Netscape CA Revocation Url +!Cname netscape-renewal-url +netscape-cert-extension 7 : nsRenewalUrl : Netscape Renewal Url +!Cname netscape-ca-policy-url +netscape-cert-extension 8 : nsCaPolicyUrl : Netscape CA Policy Url +!Cname netscape-ssl-server-name +netscape-cert-extension 12 : nsSslServerName : Netscape SSL Server Name +!Cname netscape-comment +netscape-cert-extension 13 : nsComment : Netscape Comment +!Cname netscape-cert-sequence +netscape-data-type 5 : nsCertSequence : Netscape Certificate Sequence +!Cname ns-sgc +netscape 4 1 : nsSGC : Netscape Server Gated Crypto + +# iso(1) +iso 3 : ORG : org +org 6 : DOD : dod +dod 1 : IANA : iana +!Alias internet iana + +internet 1 : directory : Directory +internet 2 : mgmt : Management +internet 3 : experimental : Experimental +internet 4 : private : Private +internet 5 : security : Security +internet 6 : snmpv2 : SNMPv2 +# Documents refer to "internet 7" as "mail". This however leads to ambiguities +# with RFC2798, Section 9.1.3, where "mail" is defined as the short name for +# rfc822Mailbox. The short name is therefore here left out for a reason. +# Subclasses of "mail", e.g. "MIME MHS" don't constitute a problem, as +# references are realized via long name "Mail" (with capital M). +internet 7 : : Mail + +Private 1 : enterprises : Enterprises + +# RFC 2247 +Enterprises 1466 344 : dcobject : dcObject + +# RFC 1495 +Mail 1 : mime-mhs : MIME MHS +mime-mhs 1 : mime-mhs-headings : mime-mhs-headings +mime-mhs 2 : mime-mhs-bodies : mime-mhs-bodies +mime-mhs-headings 1 : id-hex-partial-message : id-hex-partial-message +mime-mhs-headings 2 : id-hex-multipart-message : id-hex-multipart-message + +# RFC 3274 +!Cname zlib-compression +id-smime-alg 8 : ZLIB : zlib compression + +# AES aka Rijndael + +!Alias csor 2 16 840 1 101 3 +!Alias nistAlgorithms csor 4 +!Alias aes nistAlgorithms 1 + +aes 1 : AES-128-ECB : aes-128-ecb +aes 2 : AES-128-CBC : aes-128-cbc +!Cname aes-128-ofb128 +aes 3 : AES-128-OFB : aes-128-ofb +!Cname aes-128-cfb128 +aes 4 : AES-128-CFB : aes-128-cfb +aes 5 : id-aes128-wrap +aes 6 : id-aes128-GCM : aes-128-gcm +aes 7 : id-aes128-CCM : aes-128-ccm +aes 8 : id-aes128-wrap-pad + +aes 21 : AES-192-ECB : aes-192-ecb +aes 22 : AES-192-CBC : aes-192-cbc +!Cname aes-192-ofb128 +aes 23 : AES-192-OFB : aes-192-ofb +!Cname aes-192-cfb128 +aes 24 : AES-192-CFB : aes-192-cfb +aes 25 : id-aes192-wrap +aes 26 : id-aes192-GCM : aes-192-gcm +aes 27 : id-aes192-CCM : aes-192-ccm +aes 28 : id-aes192-wrap-pad + +aes 41 : AES-256-ECB : aes-256-ecb +aes 42 : AES-256-CBC : aes-256-cbc +!Cname aes-256-ofb128 +aes 43 : AES-256-OFB : aes-256-ofb +!Cname aes-256-cfb128 +aes 44 : AES-256-CFB : aes-256-cfb +aes 45 : id-aes256-wrap +aes 46 : id-aes256-GCM : aes-256-gcm +aes 47 : id-aes256-CCM : aes-256-ccm +aes 48 : id-aes256-wrap-pad + +ieee-siswg 0 1 1 : AES-128-XTS : aes-128-xts +ieee-siswg 0 1 2 : AES-256-XTS : aes-256-xts + +# There are no OIDs for these modes... + + : AES-128-CFB1 : aes-128-cfb1 + : AES-192-CFB1 : aes-192-cfb1 + : AES-256-CFB1 : aes-256-cfb1 + : AES-128-CFB8 : aes-128-cfb8 + : AES-192-CFB8 : aes-192-cfb8 + : AES-256-CFB8 : aes-256-cfb8 + : AES-128-CTR : aes-128-ctr + : AES-192-CTR : aes-192-ctr + : AES-256-CTR : aes-256-ctr + : AES-128-OCB : aes-128-ocb + : AES-192-OCB : aes-192-ocb + : AES-256-OCB : aes-256-ocb + : DES-CFB1 : des-cfb1 + : DES-CFB8 : des-cfb8 + : DES-EDE3-CFB1 : des-ede3-cfb1 + : DES-EDE3-CFB8 : des-ede3-cfb8 + +# OIDs for SHA224, SHA256, SHA385 and SHA512, according to x9.84 and +# http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html +# "Middle" names are specified to be id-sha256, id-sha384, etc., but +# we adhere to unprefixed capitals for backward compatibility... +!Alias nist_hashalgs nistAlgorithms 2 +nist_hashalgs 1 : SHA256 : sha256 +nist_hashalgs 2 : SHA384 : sha384 +nist_hashalgs 3 : SHA512 : sha512 +nist_hashalgs 4 : SHA224 : sha224 +nist_hashalgs 5 : SHA512-224 : sha512-224 +nist_hashalgs 6 : SHA512-256 : sha512-256 +nist_hashalgs 7 : SHA3-224 : sha3-224 +nist_hashalgs 8 : SHA3-256 : sha3-256 +nist_hashalgs 9 : SHA3-384 : sha3-384 +nist_hashalgs 10 : SHA3-512 : sha3-512 +nist_hashalgs 11 : SHAKE128 : shake128 +nist_hashalgs 12 : SHAKE256 : shake256 +nist_hashalgs 13 : id-hmacWithSHA3-224 : hmac-sha3-224 +nist_hashalgs 14 : id-hmacWithSHA3-256 : hmac-sha3-256 +nist_hashalgs 15 : id-hmacWithSHA3-384 : hmac-sha3-384 +nist_hashalgs 16 : id-hmacWithSHA3-512 : hmac-sha3-512 +# Below two are incomplete OIDs, to be uncommented when we figure out +# how to handle them... +# nist_hashalgs 17 : id-shake128-len : shake128-len +# nist_hashalgs 18 : id-shake256-len : shake256-len + +# OIDs for dsa-with-sha224 and dsa-with-sha256 +!Alias dsa_with_sha2 nistAlgorithms 3 +dsa_with_sha2 1 : dsa_with_SHA224 +dsa_with_sha2 2 : dsa_with_SHA256 +# Above two belong below, but kept as they are for backward compatibility +!Alias sigAlgs nistAlgorithms 3 +sigAlgs 3 : id-dsa-with-sha384 : dsa_with_SHA384 +sigAlgs 4 : id-dsa-with-sha512 : dsa_with_SHA512 +sigAlgs 5 : id-dsa-with-sha3-224 : dsa_with_SHA3-224 +sigAlgs 6 : id-dsa-with-sha3-256 : dsa_with_SHA3-256 +sigAlgs 7 : id-dsa-with-sha3-384 : dsa_with_SHA3-384 +sigAlgs 8 : id-dsa-with-sha3-512 : dsa_with_SHA3-512 +sigAlgs 9 : id-ecdsa-with-sha3-224 : ecdsa_with_SHA3-224 +sigAlgs 10 : id-ecdsa-with-sha3-256 : ecdsa_with_SHA3-256 +sigAlgs 11 : id-ecdsa-with-sha3-384 : ecdsa_with_SHA3-384 +sigAlgs 12 : id-ecdsa-with-sha3-512 : ecdsa_with_SHA3-512 +sigAlgs 13 : id-rsassa-pkcs1-v1_5-with-sha3-224 : RSA-SHA3-224 +sigAlgs 14 : id-rsassa-pkcs1-v1_5-with-sha3-256 : RSA-SHA3-256 +sigAlgs 15 : id-rsassa-pkcs1-v1_5-with-sha3-384 : RSA-SHA3-384 +sigAlgs 16 : id-rsassa-pkcs1-v1_5-with-sha3-512 : RSA-SHA3-512 + +# Hold instruction CRL entry extension +!Cname hold-instruction-code +id-ce 23 : holdInstructionCode : Hold Instruction Code +!Alias holdInstruction X9-57 2 +!Cname hold-instruction-none +holdInstruction 1 : holdInstructionNone : Hold Instruction None +!Cname hold-instruction-call-issuer +holdInstruction 2 : holdInstructionCallIssuer : Hold Instruction Call Issuer +!Cname hold-instruction-reject +holdInstruction 3 : holdInstructionReject : Hold Instruction Reject + +# OID's from ITU-T. Most of this is defined in RFC 1274. A couple of +# them are also mentioned in RFC 2247 +itu-t 9 : data +data 2342 : pss +pss 19200300 : ucl +ucl 100 : pilot +pilot 1 : : pilotAttributeType +pilot 3 : : pilotAttributeSyntax +pilot 4 : : pilotObjectClass +pilot 10 : : pilotGroups +pilotAttributeSyntax 4 : : iA5StringSyntax +pilotAttributeSyntax 5 : : caseIgnoreIA5StringSyntax +pilotObjectClass 3 : : pilotObject +pilotObjectClass 4 : : pilotPerson +pilotObjectClass 5 : account +pilotObjectClass 6 : document +pilotObjectClass 7 : room +pilotObjectClass 9 : : documentSeries +pilotObjectClass 13 : domain : Domain +pilotObjectClass 14 : : rFC822localPart +pilotObjectClass 15 : : dNSDomain +pilotObjectClass 17 : : domainRelatedObject +pilotObjectClass 18 : : friendlyCountry +pilotObjectClass 19 : : simpleSecurityObject +pilotObjectClass 20 : : pilotOrganization +pilotObjectClass 21 : : pilotDSA +pilotObjectClass 22 : : qualityLabelledData +pilotAttributeType 1 : UID : userId +pilotAttributeType 2 : : textEncodedORAddress +pilotAttributeType 3 : mail : rfc822Mailbox +pilotAttributeType 4 : info +pilotAttributeType 5 : : favouriteDrink +pilotAttributeType 6 : : roomNumber +pilotAttributeType 7 : photo +pilotAttributeType 8 : : userClass +pilotAttributeType 9 : host +pilotAttributeType 10 : manager +pilotAttributeType 11 : : documentIdentifier +pilotAttributeType 12 : : documentTitle +pilotAttributeType 13 : : documentVersion +pilotAttributeType 14 : : documentAuthor +pilotAttributeType 15 : : documentLocation +pilotAttributeType 20 : : homeTelephoneNumber +pilotAttributeType 21 : secretary +pilotAttributeType 22 : : otherMailbox +pilotAttributeType 23 : : lastModifiedTime +pilotAttributeType 24 : : lastModifiedBy +pilotAttributeType 25 : DC : domainComponent +pilotAttributeType 26 : : aRecord +pilotAttributeType 27 : : pilotAttributeType27 +pilotAttributeType 28 : : mXRecord +pilotAttributeType 29 : : nSRecord +pilotAttributeType 30 : : sOARecord +pilotAttributeType 31 : : cNAMERecord +pilotAttributeType 37 : : associatedDomain +pilotAttributeType 38 : : associatedName +pilotAttributeType 39 : : homePostalAddress +pilotAttributeType 40 : : personalTitle +pilotAttributeType 41 : : mobileTelephoneNumber +pilotAttributeType 42 : : pagerTelephoneNumber +pilotAttributeType 43 : : friendlyCountryName +pilotAttributeType 44 : uid : uniqueIdentifier +pilotAttributeType 45 : : organizationalStatus +pilotAttributeType 46 : : janetMailbox +pilotAttributeType 47 : : mailPreferenceOption +pilotAttributeType 48 : : buildingName +pilotAttributeType 49 : : dSAQuality +pilotAttributeType 50 : : singleLevelQuality +pilotAttributeType 51 : : subtreeMinimumQuality +pilotAttributeType 52 : : subtreeMaximumQuality +pilotAttributeType 53 : : personalSignature +pilotAttributeType 54 : : dITRedirect +pilotAttributeType 55 : audio +pilotAttributeType 56 : : documentPublisher + +international-organizations 42 : id-set : Secure Electronic Transactions + +id-set 0 : set-ctype : content types +id-set 1 : set-msgExt : message extensions +id-set 3 : set-attr +id-set 5 : set-policy +id-set 7 : set-certExt : certificate extensions +id-set 8 : set-brand + +set-ctype 0 : setct-PANData +set-ctype 1 : setct-PANToken +set-ctype 2 : setct-PANOnly +set-ctype 3 : setct-OIData +set-ctype 4 : setct-PI +set-ctype 5 : setct-PIData +set-ctype 6 : setct-PIDataUnsigned +set-ctype 7 : setct-HODInput +set-ctype 8 : setct-AuthResBaggage +set-ctype 9 : setct-AuthRevReqBaggage +set-ctype 10 : setct-AuthRevResBaggage +set-ctype 11 : setct-CapTokenSeq +set-ctype 12 : setct-PInitResData +set-ctype 13 : setct-PI-TBS +set-ctype 14 : setct-PResData +set-ctype 16 : setct-AuthReqTBS +set-ctype 17 : setct-AuthResTBS +set-ctype 18 : setct-AuthResTBSX +set-ctype 19 : setct-AuthTokenTBS +set-ctype 20 : setct-CapTokenData +set-ctype 21 : setct-CapTokenTBS +set-ctype 22 : setct-AcqCardCodeMsg +set-ctype 23 : setct-AuthRevReqTBS +set-ctype 24 : setct-AuthRevResData +set-ctype 25 : setct-AuthRevResTBS +set-ctype 26 : setct-CapReqTBS +set-ctype 27 : setct-CapReqTBSX +set-ctype 28 : setct-CapResData +set-ctype 29 : setct-CapRevReqTBS +set-ctype 30 : setct-CapRevReqTBSX +set-ctype 31 : setct-CapRevResData +set-ctype 32 : setct-CredReqTBS +set-ctype 33 : setct-CredReqTBSX +set-ctype 34 : setct-CredResData +set-ctype 35 : setct-CredRevReqTBS +set-ctype 36 : setct-CredRevReqTBSX +set-ctype 37 : setct-CredRevResData +set-ctype 38 : setct-PCertReqData +set-ctype 39 : setct-PCertResTBS +set-ctype 40 : setct-BatchAdminReqData +set-ctype 41 : setct-BatchAdminResData +set-ctype 42 : setct-CardCInitResTBS +set-ctype 43 : setct-MeAqCInitResTBS +set-ctype 44 : setct-RegFormResTBS +set-ctype 45 : setct-CertReqData +set-ctype 46 : setct-CertReqTBS +set-ctype 47 : setct-CertResData +set-ctype 48 : setct-CertInqReqTBS +set-ctype 49 : setct-ErrorTBS +set-ctype 50 : setct-PIDualSignedTBE +set-ctype 51 : setct-PIUnsignedTBE +set-ctype 52 : setct-AuthReqTBE +set-ctype 53 : setct-AuthResTBE +set-ctype 54 : setct-AuthResTBEX +set-ctype 55 : setct-AuthTokenTBE +set-ctype 56 : setct-CapTokenTBE +set-ctype 57 : setct-CapTokenTBEX +set-ctype 58 : setct-AcqCardCodeMsgTBE +set-ctype 59 : setct-AuthRevReqTBE +set-ctype 60 : setct-AuthRevResTBE +set-ctype 61 : setct-AuthRevResTBEB +set-ctype 62 : setct-CapReqTBE +set-ctype 63 : setct-CapReqTBEX +set-ctype 64 : setct-CapResTBE +set-ctype 65 : setct-CapRevReqTBE +set-ctype 66 : setct-CapRevReqTBEX +set-ctype 67 : setct-CapRevResTBE +set-ctype 68 : setct-CredReqTBE +set-ctype 69 : setct-CredReqTBEX +set-ctype 70 : setct-CredResTBE +set-ctype 71 : setct-CredRevReqTBE +set-ctype 72 : setct-CredRevReqTBEX +set-ctype 73 : setct-CredRevResTBE +set-ctype 74 : setct-BatchAdminReqTBE +set-ctype 75 : setct-BatchAdminResTBE +set-ctype 76 : setct-RegFormReqTBE +set-ctype 77 : setct-CertReqTBE +set-ctype 78 : setct-CertReqTBEX +set-ctype 79 : setct-CertResTBE +set-ctype 80 : setct-CRLNotificationTBS +set-ctype 81 : setct-CRLNotificationResTBS +set-ctype 82 : setct-BCIDistributionTBS + +set-msgExt 1 : setext-genCrypt : generic cryptogram +set-msgExt 3 : setext-miAuth : merchant initiated auth +set-msgExt 4 : setext-pinSecure +set-msgExt 5 : setext-pinAny +set-msgExt 7 : setext-track2 +set-msgExt 8 : setext-cv : additional verification + +set-policy 0 : set-policy-root + +set-certExt 0 : setCext-hashedRoot +set-certExt 1 : setCext-certType +set-certExt 2 : setCext-merchData +set-certExt 3 : setCext-cCertRequired +set-certExt 4 : setCext-tunneling +set-certExt 5 : setCext-setExt +set-certExt 6 : setCext-setQualf +set-certExt 7 : setCext-PGWYcapabilities +set-certExt 8 : setCext-TokenIdentifier +set-certExt 9 : setCext-Track2Data +set-certExt 10 : setCext-TokenType +set-certExt 11 : setCext-IssuerCapabilities + +set-attr 0 : setAttr-Cert +set-attr 1 : setAttr-PGWYcap : payment gateway capabilities +set-attr 2 : setAttr-TokenType +set-attr 3 : setAttr-IssCap : issuer capabilities + +setAttr-Cert 0 : set-rootKeyThumb +setAttr-Cert 1 : set-addPolicy + +setAttr-TokenType 1 : setAttr-Token-EMV +setAttr-TokenType 2 : setAttr-Token-B0Prime + +setAttr-IssCap 3 : setAttr-IssCap-CVM +setAttr-IssCap 4 : setAttr-IssCap-T2 +setAttr-IssCap 5 : setAttr-IssCap-Sig + +setAttr-IssCap-CVM 1 : setAttr-GenCryptgrm : generate cryptogram +setAttr-IssCap-T2 1 : setAttr-T2Enc : encrypted track 2 +setAttr-IssCap-T2 2 : setAttr-T2cleartxt : cleartext track 2 + +setAttr-IssCap-Sig 1 : setAttr-TokICCsig : ICC or token signature +setAttr-IssCap-Sig 2 : setAttr-SecDevSig : secure device signature + +set-brand 1 : set-brand-IATA-ATA +set-brand 30 : set-brand-Diners +set-brand 34 : set-brand-AmericanExpress +set-brand 35 : set-brand-JCB +set-brand 4 : set-brand-Visa +set-brand 5 : set-brand-MasterCard +set-brand 6011 : set-brand-Novus + +rsadsi 3 10 : DES-CDMF : des-cdmf +rsadsi 1 1 6 : rsaOAEPEncryptionSET + + : Oakley-EC2N-3 : ipsec3 + : Oakley-EC2N-4 : ipsec4 + +iso 0 10118 3 0 55 : whirlpool + +# GOST OIDs + +member-body 643 2 2 : cryptopro +member-body 643 2 9 : cryptocom +member-body 643 7 1 : id-tc26 + +cryptopro 3 : id-GostR3411-94-with-GostR3410-2001 : GOST R 34.11-94 with GOST R 34.10-2001 +cryptopro 4 : id-GostR3411-94-with-GostR3410-94 : GOST R 34.11-94 with GOST R 34.10-94 +!Cname id-GostR3411-94 +cryptopro 9 : md_gost94 : GOST R 34.11-94 +cryptopro 10 : id-HMACGostR3411-94 : HMAC GOST 34.11-94 +!Cname id-GostR3410-2001 +cryptopro 19 : gost2001 : GOST R 34.10-2001 +!Cname id-GostR3410-94 +cryptopro 20 : gost94 : GOST R 34.10-94 +!Cname id-Gost28147-89 +cryptopro 21 : gost89 : GOST 28147-89 + : gost89-cnt + : gost89-cnt-12 + : gost89-cbc + : gost89-ecb + : gost89-ctr +!Cname id-Gost28147-89-MAC +cryptopro 22 : gost-mac : GOST 28147-89 MAC + : gost-mac-12 +!Cname id-GostR3411-94-prf +cryptopro 23 : prf-gostr3411-94 : GOST R 34.11-94 PRF +cryptopro 98 : id-GostR3410-2001DH : GOST R 34.10-2001 DH +cryptopro 99 : id-GostR3410-94DH : GOST R 34.10-94 DH + +cryptopro 14 1 : id-Gost28147-89-CryptoPro-KeyMeshing +cryptopro 14 0 : id-Gost28147-89-None-KeyMeshing + +# GOST parameter set OIDs + +cryptopro 30 0 : id-GostR3411-94-TestParamSet +cryptopro 30 1 : id-GostR3411-94-CryptoProParamSet + +cryptopro 31 0 : id-Gost28147-89-TestParamSet +cryptopro 31 1 : id-Gost28147-89-CryptoPro-A-ParamSet +cryptopro 31 2 : id-Gost28147-89-CryptoPro-B-ParamSet +cryptopro 31 3 : id-Gost28147-89-CryptoPro-C-ParamSet +cryptopro 31 4 : id-Gost28147-89-CryptoPro-D-ParamSet +cryptopro 31 5 : id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet +cryptopro 31 6 : id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet +cryptopro 31 7 : id-Gost28147-89-CryptoPro-RIC-1-ParamSet + +cryptopro 32 0 : id-GostR3410-94-TestParamSet +cryptopro 32 2 : id-GostR3410-94-CryptoPro-A-ParamSet +cryptopro 32 3 : id-GostR3410-94-CryptoPro-B-ParamSet +cryptopro 32 4 : id-GostR3410-94-CryptoPro-C-ParamSet +cryptopro 32 5 : id-GostR3410-94-CryptoPro-D-ParamSet + +cryptopro 33 1 : id-GostR3410-94-CryptoPro-XchA-ParamSet +cryptopro 33 2 : id-GostR3410-94-CryptoPro-XchB-ParamSet +cryptopro 33 3 : id-GostR3410-94-CryptoPro-XchC-ParamSet + +cryptopro 35 0 : id-GostR3410-2001-TestParamSet +cryptopro 35 1 : id-GostR3410-2001-CryptoPro-A-ParamSet +cryptopro 35 2 : id-GostR3410-2001-CryptoPro-B-ParamSet +cryptopro 35 3 : id-GostR3410-2001-CryptoPro-C-ParamSet + +cryptopro 36 0 : id-GostR3410-2001-CryptoPro-XchA-ParamSet +cryptopro 36 1 : id-GostR3410-2001-CryptoPro-XchB-ParamSet + +id-GostR3410-94 1 : id-GostR3410-94-a +id-GostR3410-94 2 : id-GostR3410-94-aBis +id-GostR3410-94 3 : id-GostR3410-94-b +id-GostR3410-94 4 : id-GostR3410-94-bBis + +# Cryptocom LTD GOST OIDs + +cryptocom 1 6 1 : id-Gost28147-89-cc : GOST 28147-89 Cryptocom ParamSet +!Cname id-GostR3410-94-cc +cryptocom 1 5 3 : gost94cc : GOST 34.10-94 Cryptocom +!Cname id-GostR3410-2001-cc +cryptocom 1 5 4 : gost2001cc : GOST 34.10-2001 Cryptocom + +cryptocom 1 3 3 : id-GostR3411-94-with-GostR3410-94-cc : GOST R 34.11-94 with GOST R 34.10-94 Cryptocom +cryptocom 1 3 4 : id-GostR3411-94-with-GostR3410-2001-cc : GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom + +cryptocom 1 8 1 : id-GostR3410-2001-ParamSet-cc : GOST R 3410-2001 Parameter Set Cryptocom + +# TC26 GOST OIDs + +id-tc26 1 : id-tc26-algorithms +id-tc26-algorithms 1 : id-tc26-sign +!Cname id-GostR3410-2012-256 +id-tc26-sign 1 : gost2012_256: GOST R 34.10-2012 with 256 bit modulus +!Cname id-GostR3410-2012-512 +id-tc26-sign 2 : gost2012_512: GOST R 34.10-2012 with 512 bit modulus + +id-tc26-algorithms 2 : id-tc26-digest +!Cname id-GostR3411-2012-256 +id-tc26-digest 2 : md_gost12_256: GOST R 34.11-2012 with 256 bit hash +!Cname id-GostR3411-2012-512 +id-tc26-digest 3 : md_gost12_512: GOST R 34.11-2012 with 512 bit hash + +id-tc26-algorithms 3 : id-tc26-signwithdigest +id-tc26-signwithdigest 2: id-tc26-signwithdigest-gost3410-2012-256: GOST R 34.10-2012 with GOST R 34.11-2012 (256 bit) +id-tc26-signwithdigest 3: id-tc26-signwithdigest-gost3410-2012-512: GOST R 34.10-2012 with GOST R 34.11-2012 (512 bit) + +id-tc26-algorithms 4 : id-tc26-mac +id-tc26-mac 1 : id-tc26-hmac-gost-3411-2012-256 : HMAC GOST 34.11-2012 256 bit +id-tc26-mac 2 : id-tc26-hmac-gost-3411-2012-512 : HMAC GOST 34.11-2012 512 bit + +id-tc26-algorithms 5 : id-tc26-cipher +id-tc26-cipher 1 : id-tc26-cipher-gostr3412-2015-magma +id-tc26-cipher-gostr3412-2015-magma 1 : id-tc26-cipher-gostr3412-2015-magma-ctracpkm +id-tc26-cipher-gostr3412-2015-magma 2 : id-tc26-cipher-gostr3412-2015-magma-ctracpkm-omac +id-tc26-cipher 2 : id-tc26-cipher-gostr3412-2015-kuznyechik +id-tc26-cipher-gostr3412-2015-kuznyechik 1 : id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm +id-tc26-cipher-gostr3412-2015-kuznyechik 2 : id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm-omac + +id-tc26-algorithms 6 : id-tc26-agreement +id-tc26-agreement 1 : id-tc26-agreement-gost-3410-2012-256 +id-tc26-agreement 2 : id-tc26-agreement-gost-3410-2012-512 + +id-tc26-algorithms 7 : id-tc26-wrap +id-tc26-wrap 1 : id-tc26-wrap-gostr3412-2015-magma +id-tc26-wrap-gostr3412-2015-magma 1 : id-tc26-wrap-gostr3412-2015-magma-kexp15 +id-tc26-wrap 2 : id-tc26-wrap-gostr3412-2015-kuznyechik +id-tc26-wrap-gostr3412-2015-magma 1 : id-tc26-wrap-gostr3412-2015-kuznyechik-kexp15 + +id-tc26 2 : id-tc26-constants + +id-tc26-constants 1 : id-tc26-sign-constants +id-tc26-sign-constants 1: id-tc26-gost-3410-2012-256-constants +id-tc26-gost-3410-2012-256-constants 1 : id-tc26-gost-3410-2012-256-paramSetA: GOST R 34.10-2012 (256 bit) ParamSet A +id-tc26-gost-3410-2012-256-constants 2 : id-tc26-gost-3410-2012-256-paramSetB: GOST R 34.10-2012 (256 bit) ParamSet B +id-tc26-gost-3410-2012-256-constants 3 : id-tc26-gost-3410-2012-256-paramSetC: GOST R 34.10-2012 (256 bit) ParamSet C +id-tc26-gost-3410-2012-256-constants 4 : id-tc26-gost-3410-2012-256-paramSetD: GOST R 34.10-2012 (256 bit) ParamSet D +id-tc26-sign-constants 2: id-tc26-gost-3410-2012-512-constants +id-tc26-gost-3410-2012-512-constants 0 : id-tc26-gost-3410-2012-512-paramSetTest: GOST R 34.10-2012 (512 bit) testing parameter set +id-tc26-gost-3410-2012-512-constants 1 : id-tc26-gost-3410-2012-512-paramSetA: GOST R 34.10-2012 (512 bit) ParamSet A +id-tc26-gost-3410-2012-512-constants 2 : id-tc26-gost-3410-2012-512-paramSetB: GOST R 34.10-2012 (512 bit) ParamSet B +id-tc26-gost-3410-2012-512-constants 3 : id-tc26-gost-3410-2012-512-paramSetC: GOST R 34.10-2012 (512 bit) ParamSet C + +id-tc26-constants 2 : id-tc26-digest-constants +id-tc26-constants 5 : id-tc26-cipher-constants +id-tc26-cipher-constants 1 : id-tc26-gost-28147-constants +id-tc26-gost-28147-constants 1 : id-tc26-gost-28147-param-Z : GOST 28147-89 TC26 parameter set + +member-body 643 3 131 1 1 : INN : INN +member-body 643 100 1 : OGRN : OGRN +member-body 643 100 3 : SNILS : SNILS +member-body 643 100 111 : subjectSignTool : Signing Tool of Subject +member-body 643 100 112 : issuerSignTool : Signing Tool of Issuer + +#GOST R34.13-2015 Grasshopper "Kuznechik" + : grasshopper-ecb + : grasshopper-ctr + : grasshopper-ofb + : grasshopper-cbc + : grasshopper-cfb + : grasshopper-mac + +#GOST R34.13-2015 Magma + : magma-ecb + : magma-ctr + : magma-ofb + : magma-cbc + : magma-cfb + : magma-mac + +# Definitions for Camellia cipher - CBC MODE + +1 2 392 200011 61 1 1 1 2 : CAMELLIA-128-CBC : camellia-128-cbc +1 2 392 200011 61 1 1 1 3 : CAMELLIA-192-CBC : camellia-192-cbc +1 2 392 200011 61 1 1 1 4 : CAMELLIA-256-CBC : camellia-256-cbc +1 2 392 200011 61 1 1 3 2 : id-camellia128-wrap +1 2 392 200011 61 1 1 3 3 : id-camellia192-wrap +1 2 392 200011 61 1 1 3 4 : id-camellia256-wrap + +# Definitions for Camellia cipher - ECB, CFB, OFB MODE + +!Alias ntt-ds 0 3 4401 5 +!Alias camellia ntt-ds 3 1 9 + +camellia 1 : CAMELLIA-128-ECB : camellia-128-ecb +!Cname camellia-128-ofb128 +camellia 3 : CAMELLIA-128-OFB : camellia-128-ofb +!Cname camellia-128-cfb128 +camellia 4 : CAMELLIA-128-CFB : camellia-128-cfb +camellia 6 : CAMELLIA-128-GCM : camellia-128-gcm +camellia 7 : CAMELLIA-128-CCM : camellia-128-ccm +camellia 9 : CAMELLIA-128-CTR : camellia-128-ctr +camellia 10 : CAMELLIA-128-CMAC : camellia-128-cmac + +camellia 21 : CAMELLIA-192-ECB : camellia-192-ecb +!Cname camellia-192-ofb128 +camellia 23 : CAMELLIA-192-OFB : camellia-192-ofb +!Cname camellia-192-cfb128 +camellia 24 : CAMELLIA-192-CFB : camellia-192-cfb +camellia 26 : CAMELLIA-192-GCM : camellia-192-gcm +camellia 27 : CAMELLIA-192-CCM : camellia-192-ccm +camellia 29 : CAMELLIA-192-CTR : camellia-192-ctr +camellia 30 : CAMELLIA-192-CMAC : camellia-192-cmac + +camellia 41 : CAMELLIA-256-ECB : camellia-256-ecb +!Cname camellia-256-ofb128 +camellia 43 : CAMELLIA-256-OFB : camellia-256-ofb +!Cname camellia-256-cfb128 +camellia 44 : CAMELLIA-256-CFB : camellia-256-cfb +camellia 46 : CAMELLIA-256-GCM : camellia-256-gcm +camellia 47 : CAMELLIA-256-CCM : camellia-256-ccm +camellia 49 : CAMELLIA-256-CTR : camellia-256-ctr +camellia 50 : CAMELLIA-256-CMAC : camellia-256-cmac + +# There are no OIDs for these modes... + + : CAMELLIA-128-CFB1 : camellia-128-cfb1 + : CAMELLIA-192-CFB1 : camellia-192-cfb1 + : CAMELLIA-256-CFB1 : camellia-256-cfb1 + : CAMELLIA-128-CFB8 : camellia-128-cfb8 + : CAMELLIA-192-CFB8 : camellia-192-cfb8 + : CAMELLIA-256-CFB8 : camellia-256-cfb8 + +# Definitions for ARIA cipher + +!Alias aria 1 2 410 200046 1 1 +aria 1 : ARIA-128-ECB : aria-128-ecb +aria 2 : ARIA-128-CBC : aria-128-cbc +!Cname aria-128-cfb128 +aria 3 : ARIA-128-CFB : aria-128-cfb +!Cname aria-128-ofb128 +aria 4 : ARIA-128-OFB : aria-128-ofb +aria 5 : ARIA-128-CTR : aria-128-ctr + +aria 6 : ARIA-192-ECB : aria-192-ecb +aria 7 : ARIA-192-CBC : aria-192-cbc +!Cname aria-192-cfb128 +aria 8 : ARIA-192-CFB : aria-192-cfb +!Cname aria-192-ofb128 +aria 9 : ARIA-192-OFB : aria-192-ofb +aria 10 : ARIA-192-CTR : aria-192-ctr + +aria 11 : ARIA-256-ECB : aria-256-ecb +aria 12 : ARIA-256-CBC : aria-256-cbc +!Cname aria-256-cfb128 +aria 13 : ARIA-256-CFB : aria-256-cfb +!Cname aria-256-ofb128 +aria 14 : ARIA-256-OFB : aria-256-ofb +aria 15 : ARIA-256-CTR : aria-256-ctr + +# There are no OIDs for these ARIA modes... + : ARIA-128-CFB1 : aria-128-cfb1 + : ARIA-192-CFB1 : aria-192-cfb1 + : ARIA-256-CFB1 : aria-256-cfb1 + : ARIA-128-CFB8 : aria-128-cfb8 + : ARIA-192-CFB8 : aria-192-cfb8 + : ARIA-256-CFB8 : aria-256-cfb8 + +aria 37 : ARIA-128-CCM : aria-128-ccm +aria 38 : ARIA-192-CCM : aria-192-ccm +aria 39 : ARIA-256-CCM : aria-256-ccm +aria 34 : ARIA-128-GCM : aria-128-gcm +aria 35 : ARIA-192-GCM : aria-192-gcm +aria 36 : ARIA-256-GCM : aria-256-gcm + +# Definitions for SEED cipher - ECB, CBC, OFB mode + +member-body 410 200004 : KISA : kisa +kisa 1 3 : SEED-ECB : seed-ecb +kisa 1 4 : SEED-CBC : seed-cbc +!Cname seed-cfb128 +kisa 1 5 : SEED-CFB : seed-cfb +!Cname seed-ofb128 +kisa 1 6 : SEED-OFB : seed-ofb + + +# Definitions for SM4 cipher + +sm-scheme 104 1 : SM4-ECB : sm4-ecb +sm-scheme 104 2 : SM4-CBC : sm4-cbc +!Cname sm4-ofb128 +sm-scheme 104 3 : SM4-OFB : sm4-ofb +!Cname sm4-cfb128 +sm-scheme 104 4 : SM4-CFB : sm4-cfb +sm-scheme 104 5 : SM4-CFB1 : sm4-cfb1 +sm-scheme 104 6 : SM4-CFB8 : sm4-cfb8 +sm-scheme 104 7 : SM4-CTR : sm4-ctr + +# There is no OID that just denotes "HMAC" oddly enough... + + : HMAC : hmac +# Nor CMAC either + : CMAC : cmac + +# Synthetic composite ciphersuites + : RC4-HMAC-MD5 : rc4-hmac-md5 + : AES-128-CBC-HMAC-SHA1 : aes-128-cbc-hmac-sha1 + : AES-192-CBC-HMAC-SHA1 : aes-192-cbc-hmac-sha1 + : AES-256-CBC-HMAC-SHA1 : aes-256-cbc-hmac-sha1 + : AES-128-CBC-HMAC-SHA256 : aes-128-cbc-hmac-sha256 + : AES-192-CBC-HMAC-SHA256 : aes-192-cbc-hmac-sha256 + : AES-256-CBC-HMAC-SHA256 : aes-256-cbc-hmac-sha256 + : ChaCha20-Poly1305 : chacha20-poly1305 + : ChaCha20 : chacha20 + +ISO-US 10046 2 1 : dhpublicnumber : X9.42 DH + +# RFC 5639 curve OIDs (see http://www.ietf.org/rfc/rfc5639.txt) +# versionOne OBJECT IDENTIFIER ::= { +# iso(1) identified-organization(3) teletrust(36) algorithm(3) +# signature-algorithm(3) ecSign(2) ecStdCurvesAndGeneration(8) +# ellipticCurve(1) 1 } +1 3 36 3 3 2 8 1 1 1 : brainpoolP160r1 +1 3 36 3 3 2 8 1 1 2 : brainpoolP160t1 +1 3 36 3 3 2 8 1 1 3 : brainpoolP192r1 +1 3 36 3 3 2 8 1 1 4 : brainpoolP192t1 +1 3 36 3 3 2 8 1 1 5 : brainpoolP224r1 +1 3 36 3 3 2 8 1 1 6 : brainpoolP224t1 +1 3 36 3 3 2 8 1 1 7 : brainpoolP256r1 +1 3 36 3 3 2 8 1 1 8 : brainpoolP256t1 +1 3 36 3 3 2 8 1 1 9 : brainpoolP320r1 +1 3 36 3 3 2 8 1 1 10 : brainpoolP320t1 +1 3 36 3 3 2 8 1 1 11 : brainpoolP384r1 +1 3 36 3 3 2 8 1 1 12 : brainpoolP384t1 +1 3 36 3 3 2 8 1 1 13 : brainpoolP512r1 +1 3 36 3 3 2 8 1 1 14 : brainpoolP512t1 + +# ECDH schemes from RFC5753 +!Alias x9-63-scheme 1 3 133 16 840 63 0 +!Alias secg-scheme certicom-arc 1 + +x9-63-scheme 2 : dhSinglePass-stdDH-sha1kdf-scheme +secg-scheme 11 0 : dhSinglePass-stdDH-sha224kdf-scheme +secg-scheme 11 1 : dhSinglePass-stdDH-sha256kdf-scheme +secg-scheme 11 2 : dhSinglePass-stdDH-sha384kdf-scheme +secg-scheme 11 3 : dhSinglePass-stdDH-sha512kdf-scheme + +x9-63-scheme 3 : dhSinglePass-cofactorDH-sha1kdf-scheme +secg-scheme 14 0 : dhSinglePass-cofactorDH-sha224kdf-scheme +secg-scheme 14 1 : dhSinglePass-cofactorDH-sha256kdf-scheme +secg-scheme 14 2 : dhSinglePass-cofactorDH-sha384kdf-scheme +secg-scheme 14 3 : dhSinglePass-cofactorDH-sha512kdf-scheme +# NIDs for use with lookup tables. + : dh-std-kdf + : dh-cofactor-kdf + +# RFC 6962 Extension OIDs (see http://www.ietf.org/rfc/rfc6962.txt) +1 3 6 1 4 1 11129 2 4 2 : ct_precert_scts : CT Precertificate SCTs +1 3 6 1 4 1 11129 2 4 3 : ct_precert_poison : CT Precertificate Poison +1 3 6 1 4 1 11129 2 4 4 : ct_precert_signer : CT Precertificate Signer +1 3 6 1 4 1 11129 2 4 5 : ct_cert_scts : CT Certificate SCTs + +# CABForum EV SSL Certificate Guidelines +# (see https://cabforum.org/extended-validation/) +# OIDs for Subject Jurisdiction of Incorporation or Registration +1 3 6 1 4 1 311 60 2 1 1 : jurisdictionL : jurisdictionLocalityName +1 3 6 1 4 1 311 60 2 1 2 : jurisdictionST : jurisdictionStateOrProvinceName +1 3 6 1 4 1 311 60 2 1 3 : jurisdictionC : jurisdictionCountryName + +# SCRYPT algorithm +!Cname id-scrypt +1 3 6 1 4 1 11591 4 11 : id-scrypt : scrypt + +# NID for TLS1 PRF + : TLS1-PRF : tls1-prf + +# NID for HKDF + : HKDF : hkdf + +# RFC 4556 +1 3 6 1 5 2 3 : id-pkinit +id-pkinit 4 : pkInitClientAuth : PKINIT Client Auth +id-pkinit 5 : pkInitKDC : Signing KDC Response + +# From RFC8410 +1 3 101 110 : X25519 +1 3 101 111 : X448 +1 3 101 112 : ED25519 +1 3 101 113 : ED448 + + +# NIDs for cipher key exchange + : KxRSA : kx-rsa + : KxECDHE : kx-ecdhe + : KxDHE : kx-dhe + : KxECDHE-PSK : kx-ecdhe-psk + : KxDHE-PSK : kx-dhe-psk + : KxRSA_PSK : kx-rsa-psk + : KxPSK : kx-psk + : KxSRP : kx-srp + : KxGOST : kx-gost + : KxANY : kx-any + +# NIDs for cipher authentication + : AuthRSA : auth-rsa + : AuthECDSA : auth-ecdsa + : AuthPSK : auth-psk + : AuthDSS : auth-dss + : AuthGOST01 : auth-gost01 + : AuthGOST12 : auth-gost12 + : AuthSRP : auth-srp + : AuthNULL : auth-null + : AuthANY : auth-any +# NID for Poly1305 + : Poly1305 : poly1305 +# NID for SipHash + : SipHash : siphash + +# NIDs for RFC7919 DH parameters + : ffdhe2048 + : ffdhe3072 + : ffdhe4096 + : ffdhe6144 + : ffdhe8192 + +# OIDs for DSTU-4145/DSTU-7564 (http://zakon2.rada.gov.ua/laws/show/z0423-17) + +# DSTU OIDs +member-body 804 : ISO-UA +ISO-UA 2 1 1 1 : ua-pki +ua-pki 1 1 1 : dstu28147 : DSTU Gost 28147-2009 +dstu28147 2 : dstu28147-ofb : DSTU Gost 28147-2009 OFB mode +dstu28147 3 : dstu28147-cfb : DSTU Gost 28147-2009 CFB mode +dstu28147 5 : dstu28147-wrap : DSTU Gost 28147-2009 key wrap + +ua-pki 1 1 2 : hmacWithDstu34311 : HMAC DSTU Gost 34311-95 +ua-pki 1 2 1 : dstu34311 : DSTU Gost 34311-95 + +ua-pki 1 3 1 1 : dstu4145le : DSTU 4145-2002 little endian +dstu4145le 1 1 : dstu4145be : DSTU 4145-2002 big endian + +# 1.2.804. 2.1.1.1 1.3.1.1 .2.6 +# UA ua-pki 4145 le +# DSTU named curves +dstu4145le 2 0 : uacurve0 : DSTU curve 0 +dstu4145le 2 1 : uacurve1 : DSTU curve 1 +dstu4145le 2 2 : uacurve2 : DSTU curve 2 +dstu4145le 2 3 : uacurve3 : DSTU curve 3 +dstu4145le 2 4 : uacurve4 : DSTU curve 4 +dstu4145le 2 5 : uacurve5 : DSTU curve 5 +dstu4145le 2 6 : uacurve6 : DSTU curve 6 +dstu4145le 2 7 : uacurve7 : DSTU curve 7 +dstu4145le 2 8 : uacurve8 : DSTU curve 8 +dstu4145le 2 9 : uacurve9 : DSTU curve 9 diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/objects/objxref.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/objxref.pl new file mode 100644 index 000000000..ce76cadae --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/objects/objxref.pl @@ -0,0 +1,142 @@ +#! /usr/bin/env perl +# Copyright 1998-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +use strict; + +my %xref_tbl; +my %oid_tbl; + +my ($mac_file, $xref_file) = @ARGV; + +# Output year depends on the year of the script and the input file. +my $YEAR = [localtime([stat($0)]->[9])]->[5] + 1900; +my $iYEAR = [localtime([stat($mac_file)]->[9])]->[5] + 1900; +$YEAR = $iYEAR if $iYEAR > $YEAR; +$iYEAR = [localtime([stat($xref_file)]->[9])]->[5] + 1900; +$YEAR = $iYEAR if $iYEAR > $YEAR; + +open(IN, $mac_file) || die "Can't open $mac_file, $!\n"; + +# Read in OID nid values for a lookup table. + +while () + { + s|\R$||; # Better chomp + my ($name, $num) = /^(\S+)\s+(\S+)$/; + $oid_tbl{$name} = $num; + } +close IN; + +open(IN, $xref_file) || die "Can't open $xref_file, $!\n"; + +my $ln = 1; + +while () + { + s|\R$||; # Better chomp + s/#.*$//; + next if (/^\S*$/); + my ($xr, $p1, $p2) = /^(\S+)\s+(\S+)\s+(\S+)/; + check_oid($xr); + check_oid($p1); + check_oid($p2); + $xref_tbl{$xr} = [$p1, $p2, $ln]; + } + +my @xrkeys = keys %xref_tbl; + +my @srt1 = sort { $oid_tbl{$a} <=> $oid_tbl{$b}} @xrkeys; + +my $i; +for($i = 0; $i <= $#srt1; $i++) + { + $xref_tbl{$srt1[$i]}[2] = $i; + } + +my @srt2 = sort + { + my$ap1 = $oid_tbl{$xref_tbl{$a}[0]}; + my$bp1 = $oid_tbl{$xref_tbl{$b}[0]}; + return $ap1 - $bp1 if ($ap1 != $bp1); + my$ap2 = $oid_tbl{$xref_tbl{$a}[1]}; + my$bp2 = $oid_tbl{$xref_tbl{$b}[1]}; + + return $ap2 - $bp2; + } @xrkeys; + +my $pname = $0; +$pname =~ s|.*/||; + +print < +#include +#include +#include "ocsp_lcl.h" + +ASN1_SEQUENCE(OCSP_SIGNATURE) = { + ASN1_EMBED(OCSP_SIGNATURE, signatureAlgorithm, X509_ALGOR), + ASN1_SIMPLE(OCSP_SIGNATURE, signature, ASN1_BIT_STRING), + ASN1_EXP_SEQUENCE_OF_OPT(OCSP_SIGNATURE, certs, X509, 0) +} ASN1_SEQUENCE_END(OCSP_SIGNATURE) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_SIGNATURE) + +ASN1_SEQUENCE(OCSP_CERTID) = { + ASN1_EMBED(OCSP_CERTID, hashAlgorithm, X509_ALGOR), + ASN1_EMBED(OCSP_CERTID, issuerNameHash, ASN1_OCTET_STRING), + ASN1_EMBED(OCSP_CERTID, issuerKeyHash, ASN1_OCTET_STRING), + ASN1_EMBED(OCSP_CERTID, serialNumber, ASN1_INTEGER) +} ASN1_SEQUENCE_END(OCSP_CERTID) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_CERTID) + +ASN1_SEQUENCE(OCSP_ONEREQ) = { + ASN1_SIMPLE(OCSP_ONEREQ, reqCert, OCSP_CERTID), + ASN1_EXP_SEQUENCE_OF_OPT(OCSP_ONEREQ, singleRequestExtensions, X509_EXTENSION, 0) +} ASN1_SEQUENCE_END(OCSP_ONEREQ) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_ONEREQ) + +ASN1_SEQUENCE(OCSP_REQINFO) = { + ASN1_EXP_OPT(OCSP_REQINFO, version, ASN1_INTEGER, 0), + ASN1_EXP_OPT(OCSP_REQINFO, requestorName, GENERAL_NAME, 1), + ASN1_SEQUENCE_OF(OCSP_REQINFO, requestList, OCSP_ONEREQ), + ASN1_EXP_SEQUENCE_OF_OPT(OCSP_REQINFO, requestExtensions, X509_EXTENSION, 2) +} ASN1_SEQUENCE_END(OCSP_REQINFO) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_REQINFO) + +ASN1_SEQUENCE(OCSP_REQUEST) = { + ASN1_EMBED(OCSP_REQUEST, tbsRequest, OCSP_REQINFO), + ASN1_EXP_OPT(OCSP_REQUEST, optionalSignature, OCSP_SIGNATURE, 0) +} ASN1_SEQUENCE_END(OCSP_REQUEST) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_REQUEST) + +/* OCSP_RESPONSE templates */ + +ASN1_SEQUENCE(OCSP_RESPBYTES) = { + ASN1_SIMPLE(OCSP_RESPBYTES, responseType, ASN1_OBJECT), + ASN1_SIMPLE(OCSP_RESPBYTES, response, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(OCSP_RESPBYTES) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_RESPBYTES) + +ASN1_SEQUENCE(OCSP_RESPONSE) = { + ASN1_SIMPLE(OCSP_RESPONSE, responseStatus, ASN1_ENUMERATED), + ASN1_EXP_OPT(OCSP_RESPONSE, responseBytes, OCSP_RESPBYTES, 0) +} ASN1_SEQUENCE_END(OCSP_RESPONSE) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_RESPONSE) + +ASN1_CHOICE(OCSP_RESPID) = { + ASN1_EXP(OCSP_RESPID, value.byName, X509_NAME, 1), + ASN1_EXP(OCSP_RESPID, value.byKey, ASN1_OCTET_STRING, 2) +} ASN1_CHOICE_END(OCSP_RESPID) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_RESPID) + +ASN1_SEQUENCE(OCSP_REVOKEDINFO) = { + ASN1_SIMPLE(OCSP_REVOKEDINFO, revocationTime, ASN1_GENERALIZEDTIME), + ASN1_EXP_OPT(OCSP_REVOKEDINFO, revocationReason, ASN1_ENUMERATED, 0) +} ASN1_SEQUENCE_END(OCSP_REVOKEDINFO) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_REVOKEDINFO) + +ASN1_CHOICE(OCSP_CERTSTATUS) = { + ASN1_IMP(OCSP_CERTSTATUS, value.good, ASN1_NULL, 0), + ASN1_IMP(OCSP_CERTSTATUS, value.revoked, OCSP_REVOKEDINFO, 1), + ASN1_IMP(OCSP_CERTSTATUS, value.unknown, ASN1_NULL, 2) +} ASN1_CHOICE_END(OCSP_CERTSTATUS) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_CERTSTATUS) + +ASN1_SEQUENCE(OCSP_SINGLERESP) = { + ASN1_SIMPLE(OCSP_SINGLERESP, certId, OCSP_CERTID), + ASN1_SIMPLE(OCSP_SINGLERESP, certStatus, OCSP_CERTSTATUS), + ASN1_SIMPLE(OCSP_SINGLERESP, thisUpdate, ASN1_GENERALIZEDTIME), + ASN1_EXP_OPT(OCSP_SINGLERESP, nextUpdate, ASN1_GENERALIZEDTIME, 0), + ASN1_EXP_SEQUENCE_OF_OPT(OCSP_SINGLERESP, singleExtensions, X509_EXTENSION, 1) +} ASN1_SEQUENCE_END(OCSP_SINGLERESP) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_SINGLERESP) + +ASN1_SEQUENCE(OCSP_RESPDATA) = { + ASN1_EXP_OPT(OCSP_RESPDATA, version, ASN1_INTEGER, 0), + ASN1_EMBED(OCSP_RESPDATA, responderId, OCSP_RESPID), + ASN1_SIMPLE(OCSP_RESPDATA, producedAt, ASN1_GENERALIZEDTIME), + ASN1_SEQUENCE_OF(OCSP_RESPDATA, responses, OCSP_SINGLERESP), + ASN1_EXP_SEQUENCE_OF_OPT(OCSP_RESPDATA, responseExtensions, X509_EXTENSION, 1) +} ASN1_SEQUENCE_END(OCSP_RESPDATA) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_RESPDATA) + +ASN1_SEQUENCE(OCSP_BASICRESP) = { + ASN1_EMBED(OCSP_BASICRESP, tbsResponseData, OCSP_RESPDATA), + ASN1_EMBED(OCSP_BASICRESP, signatureAlgorithm, X509_ALGOR), + ASN1_SIMPLE(OCSP_BASICRESP, signature, ASN1_BIT_STRING), + ASN1_EXP_SEQUENCE_OF_OPT(OCSP_BASICRESP, certs, X509, 0) +} ASN1_SEQUENCE_END(OCSP_BASICRESP) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_BASICRESP) + +ASN1_SEQUENCE(OCSP_CRLID) = { + ASN1_EXP_OPT(OCSP_CRLID, crlUrl, ASN1_IA5STRING, 0), + ASN1_EXP_OPT(OCSP_CRLID, crlNum, ASN1_INTEGER, 1), + ASN1_EXP_OPT(OCSP_CRLID, crlTime, ASN1_GENERALIZEDTIME, 2) +} ASN1_SEQUENCE_END(OCSP_CRLID) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_CRLID) + +ASN1_SEQUENCE(OCSP_SERVICELOC) = { + ASN1_SIMPLE(OCSP_SERVICELOC, issuer, X509_NAME), + ASN1_SEQUENCE_OF_OPT(OCSP_SERVICELOC, locator, ACCESS_DESCRIPTION) +} ASN1_SEQUENCE_END(OCSP_SERVICELOC) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_SERVICELOC) diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_cl.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_cl.c new file mode 100644 index 000000000..739ac0180 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_cl.c @@ -0,0 +1,396 @@ +/* + * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include +#include "ocsp_lcl.h" + +/* + * Utility functions related to sending OCSP requests and extracting relevant + * information from the response. + */ + +/* + * Add an OCSP_CERTID to an OCSP request. Return new OCSP_ONEREQ pointer: + * useful if we want to add extensions. + */ + +OCSP_ONEREQ *OCSP_request_add0_id(OCSP_REQUEST *req, OCSP_CERTID *cid) +{ + OCSP_ONEREQ *one = NULL; + + if ((one = OCSP_ONEREQ_new()) == NULL) + return NULL; + OCSP_CERTID_free(one->reqCert); + one->reqCert = cid; + if (req && !sk_OCSP_ONEREQ_push(req->tbsRequest.requestList, one)) { + one->reqCert = NULL; /* do not free on error */ + goto err; + } + return one; + err: + OCSP_ONEREQ_free(one); + return NULL; +} + +/* Set requestorName from an X509_NAME structure */ + +int OCSP_request_set1_name(OCSP_REQUEST *req, X509_NAME *nm) +{ + GENERAL_NAME *gen; + + gen = GENERAL_NAME_new(); + if (gen == NULL) + return 0; + if (!X509_NAME_set(&gen->d.directoryName, nm)) { + GENERAL_NAME_free(gen); + return 0; + } + gen->type = GEN_DIRNAME; + GENERAL_NAME_free(req->tbsRequest.requestorName); + req->tbsRequest.requestorName = gen; + return 1; +} + +/* Add a certificate to an OCSP request */ + +int OCSP_request_add1_cert(OCSP_REQUEST *req, X509 *cert) +{ + OCSP_SIGNATURE *sig; + if (req->optionalSignature == NULL) + req->optionalSignature = OCSP_SIGNATURE_new(); + sig = req->optionalSignature; + if (sig == NULL) + return 0; + if (cert == NULL) + return 1; + if (sig->certs == NULL + && (sig->certs = sk_X509_new_null()) == NULL) + return 0; + + if (!sk_X509_push(sig->certs, cert)) + return 0; + X509_up_ref(cert); + return 1; +} + +/* + * Sign an OCSP request set the requestorName to the subject name of an + * optional signers certificate and include one or more optional certificates + * in the request. Behaves like PKCS7_sign(). + */ + +int OCSP_request_sign(OCSP_REQUEST *req, + X509 *signer, + EVP_PKEY *key, + const EVP_MD *dgst, + STACK_OF(X509) *certs, unsigned long flags) +{ + int i; + X509 *x; + + if (!OCSP_request_set1_name(req, X509_get_subject_name(signer))) + goto err; + + if ((req->optionalSignature = OCSP_SIGNATURE_new()) == NULL) + goto err; + if (key) { + if (!X509_check_private_key(signer, key)) { + OCSPerr(OCSP_F_OCSP_REQUEST_SIGN, + OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); + goto err; + } + if (!OCSP_REQUEST_sign(req, key, dgst)) + goto err; + } + + if (!(flags & OCSP_NOCERTS)) { + if (!OCSP_request_add1_cert(req, signer)) + goto err; + for (i = 0; i < sk_X509_num(certs); i++) { + x = sk_X509_value(certs, i); + if (!OCSP_request_add1_cert(req, x)) + goto err; + } + } + + return 1; + err: + OCSP_SIGNATURE_free(req->optionalSignature); + req->optionalSignature = NULL; + return 0; +} + +/* Get response status */ + +int OCSP_response_status(OCSP_RESPONSE *resp) +{ + return ASN1_ENUMERATED_get(resp->responseStatus); +} + +/* + * Extract basic response from OCSP_RESPONSE or NULL if no basic response + * present. + */ + +OCSP_BASICRESP *OCSP_response_get1_basic(OCSP_RESPONSE *resp) +{ + OCSP_RESPBYTES *rb; + rb = resp->responseBytes; + if (!rb) { + OCSPerr(OCSP_F_OCSP_RESPONSE_GET1_BASIC, OCSP_R_NO_RESPONSE_DATA); + return NULL; + } + if (OBJ_obj2nid(rb->responseType) != NID_id_pkix_OCSP_basic) { + OCSPerr(OCSP_F_OCSP_RESPONSE_GET1_BASIC, OCSP_R_NOT_BASIC_RESPONSE); + return NULL; + } + + return ASN1_item_unpack(rb->response, ASN1_ITEM_rptr(OCSP_BASICRESP)); +} + +const ASN1_OCTET_STRING *OCSP_resp_get0_signature(const OCSP_BASICRESP *bs) +{ + return bs->signature; +} + +const X509_ALGOR *OCSP_resp_get0_tbs_sigalg(const OCSP_BASICRESP *bs) +{ + return &bs->signatureAlgorithm; +} + +const OCSP_RESPDATA *OCSP_resp_get0_respdata(const OCSP_BASICRESP *bs) +{ + return &bs->tbsResponseData; +} + +/* + * Return number of OCSP_SINGLERESP responses present in a basic response. + */ + +int OCSP_resp_count(OCSP_BASICRESP *bs) +{ + if (!bs) + return -1; + return sk_OCSP_SINGLERESP_num(bs->tbsResponseData.responses); +} + +/* Extract an OCSP_SINGLERESP response with a given index */ + +OCSP_SINGLERESP *OCSP_resp_get0(OCSP_BASICRESP *bs, int idx) +{ + if (!bs) + return NULL; + return sk_OCSP_SINGLERESP_value(bs->tbsResponseData.responses, idx); +} + +const ASN1_GENERALIZEDTIME *OCSP_resp_get0_produced_at(const OCSP_BASICRESP* bs) +{ + return bs->tbsResponseData.producedAt; +} + +const STACK_OF(X509) *OCSP_resp_get0_certs(const OCSP_BASICRESP *bs) +{ + return bs->certs; +} + +int OCSP_resp_get0_id(const OCSP_BASICRESP *bs, + const ASN1_OCTET_STRING **pid, + const X509_NAME **pname) +{ + const OCSP_RESPID *rid = &bs->tbsResponseData.responderId; + + if (rid->type == V_OCSP_RESPID_NAME) { + *pname = rid->value.byName; + *pid = NULL; + } else if (rid->type == V_OCSP_RESPID_KEY) { + *pid = rid->value.byKey; + *pname = NULL; + } else { + return 0; + } + return 1; +} + +int OCSP_resp_get1_id(const OCSP_BASICRESP *bs, + ASN1_OCTET_STRING **pid, + X509_NAME **pname) +{ + const OCSP_RESPID *rid = &bs->tbsResponseData.responderId; + + if (rid->type == V_OCSP_RESPID_NAME) { + *pname = X509_NAME_dup(rid->value.byName); + *pid = NULL; + } else if (rid->type == V_OCSP_RESPID_KEY) { + *pid = ASN1_OCTET_STRING_dup(rid->value.byKey); + *pname = NULL; + } else { + return 0; + } + if (*pname == NULL && *pid == NULL) + return 0; + return 1; +} + +/* Look single response matching a given certificate ID */ + +int OCSP_resp_find(OCSP_BASICRESP *bs, OCSP_CERTID *id, int last) +{ + int i; + STACK_OF(OCSP_SINGLERESP) *sresp; + OCSP_SINGLERESP *single; + if (!bs) + return -1; + if (last < 0) + last = 0; + else + last++; + sresp = bs->tbsResponseData.responses; + for (i = last; i < sk_OCSP_SINGLERESP_num(sresp); i++) { + single = sk_OCSP_SINGLERESP_value(sresp, i); + if (!OCSP_id_cmp(id, single->certId)) + return i; + } + return -1; +} + +/* + * Extract status information from an OCSP_SINGLERESP structure. Note: the + * revtime and reason values are only set if the certificate status is + * revoked. Returns numerical value of status. + */ + +int OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason, + ASN1_GENERALIZEDTIME **revtime, + ASN1_GENERALIZEDTIME **thisupd, + ASN1_GENERALIZEDTIME **nextupd) +{ + int ret; + OCSP_CERTSTATUS *cst; + if (!single) + return -1; + cst = single->certStatus; + ret = cst->type; + if (ret == V_OCSP_CERTSTATUS_REVOKED) { + OCSP_REVOKEDINFO *rev = cst->value.revoked; + if (revtime) + *revtime = rev->revocationTime; + if (reason) { + if (rev->revocationReason) + *reason = ASN1_ENUMERATED_get(rev->revocationReason); + else + *reason = -1; + } + } + if (thisupd) + *thisupd = single->thisUpdate; + if (nextupd) + *nextupd = single->nextUpdate; + return ret; +} + +/* + * This function combines the previous ones: look up a certificate ID and if + * found extract status information. Return 0 is successful. + */ + +int OCSP_resp_find_status(OCSP_BASICRESP *bs, OCSP_CERTID *id, int *status, + int *reason, + ASN1_GENERALIZEDTIME **revtime, + ASN1_GENERALIZEDTIME **thisupd, + ASN1_GENERALIZEDTIME **nextupd) +{ + int i; + OCSP_SINGLERESP *single; + i = OCSP_resp_find(bs, id, -1); + /* Maybe check for multiple responses and give an error? */ + if (i < 0) + return 0; + single = OCSP_resp_get0(bs, i); + i = OCSP_single_get0_status(single, reason, revtime, thisupd, nextupd); + if (status) + *status = i; + return 1; +} + +/* + * Check validity of thisUpdate and nextUpdate fields. It is possible that + * the request will take a few seconds to process and/or the time won't be + * totally accurate. Therefore to avoid rejecting otherwise valid time we + * allow the times to be within 'nsec' of the current time. Also to avoid + * accepting very old responses without a nextUpdate field an optional maxage + * parameter specifies the maximum age the thisUpdate field can be. + */ + +int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd, + ASN1_GENERALIZEDTIME *nextupd, long nsec, long maxsec) +{ + int ret = 1; + time_t t_now, t_tmp; + time(&t_now); + /* Check thisUpdate is valid and not more than nsec in the future */ + if (!ASN1_GENERALIZEDTIME_check(thisupd)) { + OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY, OCSP_R_ERROR_IN_THISUPDATE_FIELD); + ret = 0; + } else { + t_tmp = t_now + nsec; + if (X509_cmp_time(thisupd, &t_tmp) > 0) { + OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY, OCSP_R_STATUS_NOT_YET_VALID); + ret = 0; + } + + /* + * If maxsec specified check thisUpdate is not more than maxsec in + * the past + */ + if (maxsec >= 0) { + t_tmp = t_now - maxsec; + if (X509_cmp_time(thisupd, &t_tmp) < 0) { + OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY, OCSP_R_STATUS_TOO_OLD); + ret = 0; + } + } + } + + if (!nextupd) + return ret; + + /* Check nextUpdate is valid and not more than nsec in the past */ + if (!ASN1_GENERALIZEDTIME_check(nextupd)) { + OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY, OCSP_R_ERROR_IN_NEXTUPDATE_FIELD); + ret = 0; + } else { + t_tmp = t_now - nsec; + if (X509_cmp_time(nextupd, &t_tmp) < 0) { + OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY, OCSP_R_STATUS_EXPIRED); + ret = 0; + } + } + + /* Also don't allow nextUpdate to precede thisUpdate */ + if (ASN1_STRING_cmp(nextupd, thisupd) < 0) { + OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY, + OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE); + ret = 0; + } + + return ret; +} + +const OCSP_CERTID *OCSP_SINGLERESP_get0_id(const OCSP_SINGLERESP *single) +{ + return single->certId; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_err.c new file mode 100644 index 000000000..660e19366 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_err.c @@ -0,0 +1,101 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA OCSP_str_functs[] = { + {ERR_PACK(ERR_LIB_OCSP, OCSP_F_D2I_OCSP_NONCE, 0), "d2i_ocsp_nonce"}, + {ERR_PACK(ERR_LIB_OCSP, OCSP_F_OCSP_BASIC_ADD1_STATUS, 0), + "OCSP_basic_add1_status"}, + {ERR_PACK(ERR_LIB_OCSP, OCSP_F_OCSP_BASIC_SIGN, 0), "OCSP_basic_sign"}, + {ERR_PACK(ERR_LIB_OCSP, OCSP_F_OCSP_BASIC_SIGN_CTX, 0), + "OCSP_basic_sign_ctx"}, + {ERR_PACK(ERR_LIB_OCSP, OCSP_F_OCSP_BASIC_VERIFY, 0), "OCSP_basic_verify"}, + {ERR_PACK(ERR_LIB_OCSP, OCSP_F_OCSP_CERT_ID_NEW, 0), "OCSP_cert_id_new"}, + {ERR_PACK(ERR_LIB_OCSP, OCSP_F_OCSP_CHECK_DELEGATED, 0), + "ocsp_check_delegated"}, + {ERR_PACK(ERR_LIB_OCSP, OCSP_F_OCSP_CHECK_IDS, 0), "ocsp_check_ids"}, + {ERR_PACK(ERR_LIB_OCSP, OCSP_F_OCSP_CHECK_ISSUER, 0), "ocsp_check_issuer"}, + {ERR_PACK(ERR_LIB_OCSP, OCSP_F_OCSP_CHECK_VALIDITY, 0), + "OCSP_check_validity"}, + {ERR_PACK(ERR_LIB_OCSP, OCSP_F_OCSP_MATCH_ISSUERID, 0), + "ocsp_match_issuerid"}, + {ERR_PACK(ERR_LIB_OCSP, OCSP_F_OCSP_PARSE_URL, 0), "OCSP_parse_url"}, + {ERR_PACK(ERR_LIB_OCSP, OCSP_F_OCSP_REQUEST_SIGN, 0), "OCSP_request_sign"}, + {ERR_PACK(ERR_LIB_OCSP, OCSP_F_OCSP_REQUEST_VERIFY, 0), + "OCSP_request_verify"}, + {ERR_PACK(ERR_LIB_OCSP, OCSP_F_OCSP_RESPONSE_GET1_BASIC, 0), + "OCSP_response_get1_basic"}, + {ERR_PACK(ERR_LIB_OCSP, OCSP_F_PARSE_HTTP_LINE1, 0), "parse_http_line1"}, + {0, NULL} +}; + +static const ERR_STRING_DATA OCSP_str_reasons[] = { + {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_CERTIFICATE_VERIFY_ERROR), + "certificate verify error"}, + {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_DIGEST_ERR), "digest err"}, + {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_ERROR_IN_NEXTUPDATE_FIELD), + "error in nextupdate field"}, + {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_ERROR_IN_THISUPDATE_FIELD), + "error in thisupdate field"}, + {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_ERROR_PARSING_URL), "error parsing url"}, + {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_MISSING_OCSPSIGNING_USAGE), + "missing ocspsigning usage"}, + {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE), + "nextupdate before thisupdate"}, + {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_NOT_BASIC_RESPONSE), + "not basic response"}, + {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_NO_CERTIFICATES_IN_CHAIN), + "no certificates in chain"}, + {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_NO_RESPONSE_DATA), "no response data"}, + {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_NO_REVOKED_TIME), "no revoked time"}, + {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_NO_SIGNER_KEY), "no signer key"}, + {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE), + "private key does not match certificate"}, + {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_REQUEST_NOT_SIGNED), + "request not signed"}, + {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA), + "response contains no revocation data"}, + {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_ROOT_CA_NOT_TRUSTED), + "root ca not trusted"}, + {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_SERVER_RESPONSE_ERROR), + "server response error"}, + {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_SERVER_RESPONSE_PARSE_ERROR), + "server response parse error"}, + {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_SIGNATURE_FAILURE), "signature failure"}, + {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND), + "signer certificate not found"}, + {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_STATUS_EXPIRED), "status expired"}, + {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_STATUS_NOT_YET_VALID), + "status not yet valid"}, + {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_STATUS_TOO_OLD), "status too old"}, + {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_UNKNOWN_MESSAGE_DIGEST), + "unknown message digest"}, + {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_UNKNOWN_NID), "unknown nid"}, + {ERR_PACK(ERR_LIB_OCSP, 0, OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE), + "unsupported requestorname type"}, + {0, NULL} +}; + +#endif + +int ERR_load_OCSP_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(OCSP_str_functs[0].error) == NULL) { + ERR_load_strings_const(OCSP_str_functs); + ERR_load_strings_const(OCSP_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_ext.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_ext.c new file mode 100644 index 000000000..27ee21245 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_ext.c @@ -0,0 +1,472 @@ +/* + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include "ocsp_lcl.h" +#include +#include + +/* Standard wrapper functions for extensions */ + +/* OCSP request extensions */ + +int OCSP_REQUEST_get_ext_count(OCSP_REQUEST *x) +{ + return X509v3_get_ext_count(x->tbsRequest.requestExtensions); +} + +int OCSP_REQUEST_get_ext_by_NID(OCSP_REQUEST *x, int nid, int lastpos) +{ + return (X509v3_get_ext_by_NID + (x->tbsRequest.requestExtensions, nid, lastpos)); +} + +int OCSP_REQUEST_get_ext_by_OBJ(OCSP_REQUEST *x, const ASN1_OBJECT *obj, + int lastpos) +{ + return (X509v3_get_ext_by_OBJ + (x->tbsRequest.requestExtensions, obj, lastpos)); +} + +int OCSP_REQUEST_get_ext_by_critical(OCSP_REQUEST *x, int crit, int lastpos) +{ + return (X509v3_get_ext_by_critical + (x->tbsRequest.requestExtensions, crit, lastpos)); +} + +X509_EXTENSION *OCSP_REQUEST_get_ext(OCSP_REQUEST *x, int loc) +{ + return X509v3_get_ext(x->tbsRequest.requestExtensions, loc); +} + +X509_EXTENSION *OCSP_REQUEST_delete_ext(OCSP_REQUEST *x, int loc) +{ + return X509v3_delete_ext(x->tbsRequest.requestExtensions, loc); +} + +void *OCSP_REQUEST_get1_ext_d2i(OCSP_REQUEST *x, int nid, int *crit, int *idx) +{ + return X509V3_get_d2i(x->tbsRequest.requestExtensions, nid, crit, idx); +} + +int OCSP_REQUEST_add1_ext_i2d(OCSP_REQUEST *x, int nid, void *value, int crit, + unsigned long flags) +{ + return X509V3_add1_i2d(&x->tbsRequest.requestExtensions, nid, value, + crit, flags); +} + +int OCSP_REQUEST_add_ext(OCSP_REQUEST *x, X509_EXTENSION *ex, int loc) +{ + return (X509v3_add_ext(&(x->tbsRequest.requestExtensions), ex, loc) != + NULL); +} + +/* Single extensions */ + +int OCSP_ONEREQ_get_ext_count(OCSP_ONEREQ *x) +{ + return X509v3_get_ext_count(x->singleRequestExtensions); +} + +int OCSP_ONEREQ_get_ext_by_NID(OCSP_ONEREQ *x, int nid, int lastpos) +{ + return X509v3_get_ext_by_NID(x->singleRequestExtensions, nid, lastpos); +} + +int OCSP_ONEREQ_get_ext_by_OBJ(OCSP_ONEREQ *x, const ASN1_OBJECT *obj, + int lastpos) +{ + return X509v3_get_ext_by_OBJ(x->singleRequestExtensions, obj, lastpos); +} + +int OCSP_ONEREQ_get_ext_by_critical(OCSP_ONEREQ *x, int crit, int lastpos) +{ + return (X509v3_get_ext_by_critical + (x->singleRequestExtensions, crit, lastpos)); +} + +X509_EXTENSION *OCSP_ONEREQ_get_ext(OCSP_ONEREQ *x, int loc) +{ + return X509v3_get_ext(x->singleRequestExtensions, loc); +} + +X509_EXTENSION *OCSP_ONEREQ_delete_ext(OCSP_ONEREQ *x, int loc) +{ + return X509v3_delete_ext(x->singleRequestExtensions, loc); +} + +void *OCSP_ONEREQ_get1_ext_d2i(OCSP_ONEREQ *x, int nid, int *crit, int *idx) +{ + return X509V3_get_d2i(x->singleRequestExtensions, nid, crit, idx); +} + +int OCSP_ONEREQ_add1_ext_i2d(OCSP_ONEREQ *x, int nid, void *value, int crit, + unsigned long flags) +{ + return X509V3_add1_i2d(&x->singleRequestExtensions, nid, value, crit, + flags); +} + +int OCSP_ONEREQ_add_ext(OCSP_ONEREQ *x, X509_EXTENSION *ex, int loc) +{ + return (X509v3_add_ext(&(x->singleRequestExtensions), ex, loc) != NULL); +} + +/* OCSP Basic response */ + +int OCSP_BASICRESP_get_ext_count(OCSP_BASICRESP *x) +{ + return X509v3_get_ext_count(x->tbsResponseData.responseExtensions); +} + +int OCSP_BASICRESP_get_ext_by_NID(OCSP_BASICRESP *x, int nid, int lastpos) +{ + return (X509v3_get_ext_by_NID + (x->tbsResponseData.responseExtensions, nid, lastpos)); +} + +int OCSP_BASICRESP_get_ext_by_OBJ(OCSP_BASICRESP *x, const ASN1_OBJECT *obj, + int lastpos) +{ + return (X509v3_get_ext_by_OBJ + (x->tbsResponseData.responseExtensions, obj, lastpos)); +} + +int OCSP_BASICRESP_get_ext_by_critical(OCSP_BASICRESP *x, int crit, + int lastpos) +{ + return (X509v3_get_ext_by_critical + (x->tbsResponseData.responseExtensions, crit, lastpos)); +} + +X509_EXTENSION *OCSP_BASICRESP_get_ext(OCSP_BASICRESP *x, int loc) +{ + return X509v3_get_ext(x->tbsResponseData.responseExtensions, loc); +} + +X509_EXTENSION *OCSP_BASICRESP_delete_ext(OCSP_BASICRESP *x, int loc) +{ + return X509v3_delete_ext(x->tbsResponseData.responseExtensions, loc); +} + +void *OCSP_BASICRESP_get1_ext_d2i(OCSP_BASICRESP *x, int nid, int *crit, + int *idx) +{ + return X509V3_get_d2i(x->tbsResponseData.responseExtensions, nid, crit, + idx); +} + +int OCSP_BASICRESP_add1_ext_i2d(OCSP_BASICRESP *x, int nid, void *value, + int crit, unsigned long flags) +{ + return X509V3_add1_i2d(&x->tbsResponseData.responseExtensions, nid, + value, crit, flags); +} + +int OCSP_BASICRESP_add_ext(OCSP_BASICRESP *x, X509_EXTENSION *ex, int loc) +{ + return (X509v3_add_ext(&(x->tbsResponseData.responseExtensions), ex, loc) + != NULL); +} + +/* OCSP single response extensions */ + +int OCSP_SINGLERESP_get_ext_count(OCSP_SINGLERESP *x) +{ + return X509v3_get_ext_count(x->singleExtensions); +} + +int OCSP_SINGLERESP_get_ext_by_NID(OCSP_SINGLERESP *x, int nid, int lastpos) +{ + return X509v3_get_ext_by_NID(x->singleExtensions, nid, lastpos); +} + +int OCSP_SINGLERESP_get_ext_by_OBJ(OCSP_SINGLERESP *x, const ASN1_OBJECT *obj, + int lastpos) +{ + return X509v3_get_ext_by_OBJ(x->singleExtensions, obj, lastpos); +} + +int OCSP_SINGLERESP_get_ext_by_critical(OCSP_SINGLERESP *x, int crit, + int lastpos) +{ + return X509v3_get_ext_by_critical(x->singleExtensions, crit, lastpos); +} + +X509_EXTENSION *OCSP_SINGLERESP_get_ext(OCSP_SINGLERESP *x, int loc) +{ + return X509v3_get_ext(x->singleExtensions, loc); +} + +X509_EXTENSION *OCSP_SINGLERESP_delete_ext(OCSP_SINGLERESP *x, int loc) +{ + return X509v3_delete_ext(x->singleExtensions, loc); +} + +void *OCSP_SINGLERESP_get1_ext_d2i(OCSP_SINGLERESP *x, int nid, int *crit, + int *idx) +{ + return X509V3_get_d2i(x->singleExtensions, nid, crit, idx); +} + +int OCSP_SINGLERESP_add1_ext_i2d(OCSP_SINGLERESP *x, int nid, void *value, + int crit, unsigned long flags) +{ + return X509V3_add1_i2d(&x->singleExtensions, nid, value, crit, flags); +} + +int OCSP_SINGLERESP_add_ext(OCSP_SINGLERESP *x, X509_EXTENSION *ex, int loc) +{ + return (X509v3_add_ext(&(x->singleExtensions), ex, loc) != NULL); +} + +/* also CRL Entry Extensions */ + +/* Nonce handling functions */ + +/* + * Add a nonce to an extension stack. A nonce can be specified or if NULL a + * random nonce will be generated. Note: OpenSSL 0.9.7d and later create an + * OCTET STRING containing the nonce, previous versions used the raw nonce. + */ + +static int ocsp_add1_nonce(STACK_OF(X509_EXTENSION) **exts, + unsigned char *val, int len) +{ + unsigned char *tmpval; + ASN1_OCTET_STRING os; + int ret = 0; + if (len <= 0) + len = OCSP_DEFAULT_NONCE_LENGTH; + /* + * Create the OCTET STRING manually by writing out the header and + * appending the content octets. This avoids an extra memory allocation + * operation in some cases. Applications should *NOT* do this because it + * relies on library internals. + */ + os.length = ASN1_object_size(0, len, V_ASN1_OCTET_STRING); + if (os.length < 0) + return 0; + + os.data = OPENSSL_malloc(os.length); + if (os.data == NULL) + goto err; + tmpval = os.data; + ASN1_put_object(&tmpval, 0, len, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL); + if (val) + memcpy(tmpval, val, len); + else if (RAND_bytes(tmpval, len) <= 0) + goto err; + if (!X509V3_add1_i2d(exts, NID_id_pkix_OCSP_Nonce, + &os, 0, X509V3_ADD_REPLACE)) + goto err; + ret = 1; + err: + OPENSSL_free(os.data); + return ret; +} + +/* Add nonce to an OCSP request */ + +int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len) +{ + return ocsp_add1_nonce(&req->tbsRequest.requestExtensions, val, len); +} + +/* Same as above but for a response */ + +int OCSP_basic_add1_nonce(OCSP_BASICRESP *resp, unsigned char *val, int len) +{ + return ocsp_add1_nonce(&resp->tbsResponseData.responseExtensions, val, + len); +} + +/*- + * Check nonce validity in a request and response. + * Return value reflects result: + * 1: nonces present and equal. + * 2: nonces both absent. + * 3: nonce present in response only. + * 0: nonces both present and not equal. + * -1: nonce in request only. + * + * For most responders clients can check return > 0. + * If responder doesn't handle nonces return != 0 may be + * necessary. return == 0 is always an error. + */ + +int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs) +{ + /* + * Since we are only interested in the presence or absence of + * the nonce and comparing its value there is no need to use + * the X509V3 routines: this way we can avoid them allocating an + * ASN1_OCTET_STRING structure for the value which would be + * freed immediately anyway. + */ + + int req_idx, resp_idx; + X509_EXTENSION *req_ext, *resp_ext; + req_idx = OCSP_REQUEST_get_ext_by_NID(req, NID_id_pkix_OCSP_Nonce, -1); + resp_idx = OCSP_BASICRESP_get_ext_by_NID(bs, NID_id_pkix_OCSP_Nonce, -1); + /* Check both absent */ + if ((req_idx < 0) && (resp_idx < 0)) + return 2; + /* Check in request only */ + if ((req_idx >= 0) && (resp_idx < 0)) + return -1; + /* Check in response but not request */ + if ((req_idx < 0) && (resp_idx >= 0)) + return 3; + /* + * Otherwise nonce in request and response so retrieve the extensions + */ + req_ext = OCSP_REQUEST_get_ext(req, req_idx); + resp_ext = OCSP_BASICRESP_get_ext(bs, resp_idx); + if (ASN1_OCTET_STRING_cmp(X509_EXTENSION_get_data(req_ext), + X509_EXTENSION_get_data(resp_ext))) + return 0; + return 1; +} + +/* + * Copy the nonce value (if any) from an OCSP request to a response. + */ + +int OCSP_copy_nonce(OCSP_BASICRESP *resp, OCSP_REQUEST *req) +{ + X509_EXTENSION *req_ext; + int req_idx; + /* Check for nonce in request */ + req_idx = OCSP_REQUEST_get_ext_by_NID(req, NID_id_pkix_OCSP_Nonce, -1); + /* If no nonce that's OK */ + if (req_idx < 0) + return 2; + req_ext = OCSP_REQUEST_get_ext(req, req_idx); + return OCSP_BASICRESP_add_ext(resp, req_ext, -1); +} + +X509_EXTENSION *OCSP_crlID_new(const char *url, long *n, char *tim) +{ + X509_EXTENSION *x = NULL; + OCSP_CRLID *cid = NULL; + + if ((cid = OCSP_CRLID_new()) == NULL) + goto err; + if (url) { + if ((cid->crlUrl = ASN1_IA5STRING_new()) == NULL) + goto err; + if (!(ASN1_STRING_set(cid->crlUrl, url, -1))) + goto err; + } + if (n) { + if ((cid->crlNum = ASN1_INTEGER_new()) == NULL) + goto err; + if (!(ASN1_INTEGER_set(cid->crlNum, *n))) + goto err; + } + if (tim) { + if ((cid->crlTime = ASN1_GENERALIZEDTIME_new()) == NULL) + goto err; + if (!(ASN1_GENERALIZEDTIME_set_string(cid->crlTime, tim))) + goto err; + } + x = X509V3_EXT_i2d(NID_id_pkix_OCSP_CrlID, 0, cid); + err: + OCSP_CRLID_free(cid); + return x; +} + +/* AcceptableResponses ::= SEQUENCE OF OBJECT IDENTIFIER */ +X509_EXTENSION *OCSP_accept_responses_new(char **oids) +{ + int nid; + STACK_OF(ASN1_OBJECT) *sk = NULL; + ASN1_OBJECT *o = NULL; + X509_EXTENSION *x = NULL; + + if ((sk = sk_ASN1_OBJECT_new_null()) == NULL) + goto err; + while (oids && *oids) { + if ((nid = OBJ_txt2nid(*oids)) != NID_undef && (o = OBJ_nid2obj(nid))) + sk_ASN1_OBJECT_push(sk, o); + oids++; + } + x = X509V3_EXT_i2d(NID_id_pkix_OCSP_acceptableResponses, 0, sk); + err: + sk_ASN1_OBJECT_pop_free(sk, ASN1_OBJECT_free); + return x; +} + +/* ArchiveCutoff ::= GeneralizedTime */ +X509_EXTENSION *OCSP_archive_cutoff_new(char *tim) +{ + X509_EXTENSION *x = NULL; + ASN1_GENERALIZEDTIME *gt = NULL; + + if ((gt = ASN1_GENERALIZEDTIME_new()) == NULL) + goto err; + if (!(ASN1_GENERALIZEDTIME_set_string(gt, tim))) + goto err; + x = X509V3_EXT_i2d(NID_id_pkix_OCSP_archiveCutoff, 0, gt); + err: + ASN1_GENERALIZEDTIME_free(gt); + return x; +} + +/* + * per ACCESS_DESCRIPTION parameter are oids, of which there are currently + * two--NID_ad_ocsp, NID_id_ad_caIssuers--and GeneralName value. This method + * forces NID_ad_ocsp and uniformResourceLocator [6] IA5String. + */ +X509_EXTENSION *OCSP_url_svcloc_new(X509_NAME *issuer, const char **urls) +{ + X509_EXTENSION *x = NULL; + ASN1_IA5STRING *ia5 = NULL; + OCSP_SERVICELOC *sloc = NULL; + ACCESS_DESCRIPTION *ad = NULL; + + if ((sloc = OCSP_SERVICELOC_new()) == NULL) + goto err; + if ((sloc->issuer = X509_NAME_dup(issuer)) == NULL) + goto err; + if (urls && *urls + && (sloc->locator = sk_ACCESS_DESCRIPTION_new_null()) == NULL) + goto err; + while (urls && *urls) { + if ((ad = ACCESS_DESCRIPTION_new()) == NULL) + goto err; + if ((ad->method = OBJ_nid2obj(NID_ad_OCSP)) == NULL) + goto err; + if ((ad->location = GENERAL_NAME_new()) == NULL) + goto err; + if ((ia5 = ASN1_IA5STRING_new()) == NULL) + goto err; + if (!ASN1_STRING_set((ASN1_STRING *)ia5, *urls, -1)) + goto err; + ad->location->type = GEN_URI; + ad->location->d.ia5 = ia5; + ia5 = NULL; + if (!sk_ACCESS_DESCRIPTION_push(sloc->locator, ad)) + goto err; + ad = NULL; + urls++; + } + x = X509V3_EXT_i2d(NID_id_pkix_OCSP_serviceLocator, 0, sloc); + err: + ASN1_IA5STRING_free(ia5); + ACCESS_DESCRIPTION_free(ad); + OCSP_SERVICELOC_free(sloc); + return x; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_ht.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_ht.c new file mode 100644 index 000000000..42c368643 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_ht.c @@ -0,0 +1,502 @@ +/* + * Copyright 2001-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "e_os.h" +#include +#include +#include "internal/ctype.h" +#include +#include +#include +#include +#include + +/* Stateful OCSP request code, supporting non-blocking I/O */ + +/* Opaque OCSP request status structure */ + +struct ocsp_req_ctx_st { + int state; /* Current I/O state */ + unsigned char *iobuf; /* Line buffer */ + int iobuflen; /* Line buffer length */ + BIO *io; /* BIO to perform I/O with */ + BIO *mem; /* Memory BIO response is built into */ + unsigned long asn1_len; /* ASN1 length of response */ + unsigned long max_resp_len; /* Maximum length of response */ +}; + +#define OCSP_MAX_RESP_LENGTH (100 * 1024) +#define OCSP_MAX_LINE_LEN 4096; + +/* OCSP states */ + +/* If set no reading should be performed */ +#define OHS_NOREAD 0x1000 +/* Error condition */ +#define OHS_ERROR (0 | OHS_NOREAD) +/* First line being read */ +#define OHS_FIRSTLINE 1 +/* MIME headers being read */ +#define OHS_HEADERS 2 +/* OCSP initial header (tag + length) being read */ +#define OHS_ASN1_HEADER 3 +/* OCSP content octets being read */ +#define OHS_ASN1_CONTENT 4 +/* First call: ready to start I/O */ +#define OHS_ASN1_WRITE_INIT (5 | OHS_NOREAD) +/* Request being sent */ +#define OHS_ASN1_WRITE (6 | OHS_NOREAD) +/* Request being flushed */ +#define OHS_ASN1_FLUSH (7 | OHS_NOREAD) +/* Completed */ +#define OHS_DONE (8 | OHS_NOREAD) +/* Headers set, no final \r\n included */ +#define OHS_HTTP_HEADER (9 | OHS_NOREAD) + +static int parse_http_line1(char *line); + +OCSP_REQ_CTX *OCSP_REQ_CTX_new(BIO *io, int maxline) +{ + OCSP_REQ_CTX *rctx = OPENSSL_zalloc(sizeof(*rctx)); + + if (rctx == NULL) + return NULL; + rctx->state = OHS_ERROR; + rctx->max_resp_len = OCSP_MAX_RESP_LENGTH; + rctx->mem = BIO_new(BIO_s_mem()); + rctx->io = io; + if (maxline > 0) + rctx->iobuflen = maxline; + else + rctx->iobuflen = OCSP_MAX_LINE_LEN; + rctx->iobuf = OPENSSL_malloc(rctx->iobuflen); + if (rctx->iobuf == NULL || rctx->mem == NULL) { + OCSP_REQ_CTX_free(rctx); + return NULL; + } + return rctx; +} + +void OCSP_REQ_CTX_free(OCSP_REQ_CTX *rctx) +{ + if (!rctx) + return; + BIO_free(rctx->mem); + OPENSSL_free(rctx->iobuf); + OPENSSL_free(rctx); +} + +BIO *OCSP_REQ_CTX_get0_mem_bio(OCSP_REQ_CTX *rctx) +{ + return rctx->mem; +} + +void OCSP_set_max_response_length(OCSP_REQ_CTX *rctx, unsigned long len) +{ + if (len == 0) + rctx->max_resp_len = OCSP_MAX_RESP_LENGTH; + else + rctx->max_resp_len = len; +} + +int OCSP_REQ_CTX_i2d(OCSP_REQ_CTX *rctx, const ASN1_ITEM *it, ASN1_VALUE *val) +{ + static const char req_hdr[] = + "Content-Type: application/ocsp-request\r\n" + "Content-Length: %d\r\n\r\n"; + int reqlen = ASN1_item_i2d(val, NULL, it); + if (BIO_printf(rctx->mem, req_hdr, reqlen) <= 0) + return 0; + if (ASN1_item_i2d_bio(it, rctx->mem, val) <= 0) + return 0; + rctx->state = OHS_ASN1_WRITE_INIT; + return 1; +} + +int OCSP_REQ_CTX_nbio_d2i(OCSP_REQ_CTX *rctx, + ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + int rv, len; + const unsigned char *p; + + rv = OCSP_REQ_CTX_nbio(rctx); + if (rv != 1) + return rv; + + len = BIO_get_mem_data(rctx->mem, &p); + *pval = ASN1_item_d2i(NULL, &p, len, it); + if (*pval == NULL) { + rctx->state = OHS_ERROR; + return 0; + } + return 1; +} + +int OCSP_REQ_CTX_http(OCSP_REQ_CTX *rctx, const char *op, const char *path) +{ + static const char http_hdr[] = "%s %s HTTP/1.0\r\n"; + + if (!path) + path = "/"; + + if (BIO_printf(rctx->mem, http_hdr, op, path) <= 0) + return 0; + rctx->state = OHS_HTTP_HEADER; + return 1; +} + +int OCSP_REQ_CTX_set1_req(OCSP_REQ_CTX *rctx, OCSP_REQUEST *req) +{ + return OCSP_REQ_CTX_i2d(rctx, ASN1_ITEM_rptr(OCSP_REQUEST), + (ASN1_VALUE *)req); +} + +int OCSP_REQ_CTX_add1_header(OCSP_REQ_CTX *rctx, + const char *name, const char *value) +{ + if (!name) + return 0; + if (BIO_puts(rctx->mem, name) <= 0) + return 0; + if (value) { + if (BIO_write(rctx->mem, ": ", 2) != 2) + return 0; + if (BIO_puts(rctx->mem, value) <= 0) + return 0; + } + if (BIO_write(rctx->mem, "\r\n", 2) != 2) + return 0; + rctx->state = OHS_HTTP_HEADER; + return 1; +} + +OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, const char *path, OCSP_REQUEST *req, + int maxline) +{ + + OCSP_REQ_CTX *rctx = NULL; + rctx = OCSP_REQ_CTX_new(io, maxline); + if (rctx == NULL) + return NULL; + + if (!OCSP_REQ_CTX_http(rctx, "POST", path)) + goto err; + + if (req && !OCSP_REQ_CTX_set1_req(rctx, req)) + goto err; + + return rctx; + + err: + OCSP_REQ_CTX_free(rctx); + return NULL; +} + +/* + * Parse the HTTP response. This will look like this: "HTTP/1.0 200 OK". We + * need to obtain the numeric code and (optional) informational message. + */ + +static int parse_http_line1(char *line) +{ + int retcode; + char *p, *q, *r; + /* Skip to first white space (passed protocol info) */ + + for (p = line; *p && !ossl_isspace(*p); p++) + continue; + if (!*p) { + OCSPerr(OCSP_F_PARSE_HTTP_LINE1, OCSP_R_SERVER_RESPONSE_PARSE_ERROR); + return 0; + } + + /* Skip past white space to start of response code */ + while (*p && ossl_isspace(*p)) + p++; + + if (!*p) { + OCSPerr(OCSP_F_PARSE_HTTP_LINE1, OCSP_R_SERVER_RESPONSE_PARSE_ERROR); + return 0; + } + + /* Find end of response code: first whitespace after start of code */ + for (q = p; *q && !ossl_isspace(*q); q++) + continue; + + if (!*q) { + OCSPerr(OCSP_F_PARSE_HTTP_LINE1, OCSP_R_SERVER_RESPONSE_PARSE_ERROR); + return 0; + } + + /* Set end of response code and start of message */ + *q++ = 0; + + /* Attempt to parse numeric code */ + retcode = strtoul(p, &r, 10); + + if (*r) + return 0; + + /* Skip over any leading white space in message */ + while (*q && ossl_isspace(*q)) + q++; + + if (*q) { + /* + * Finally zap any trailing white space in message (include CRLF) + */ + + /* We know q has a non white space character so this is OK */ + for (r = q + strlen(q) - 1; ossl_isspace(*r); r--) + *r = 0; + } + if (retcode != 200) { + OCSPerr(OCSP_F_PARSE_HTTP_LINE1, OCSP_R_SERVER_RESPONSE_ERROR); + if (!*q) + ERR_add_error_data(2, "Code=", p); + else + ERR_add_error_data(4, "Code=", p, ",Reason=", q); + return 0; + } + + return 1; + +} + +int OCSP_REQ_CTX_nbio(OCSP_REQ_CTX *rctx) +{ + int i, n; + const unsigned char *p; + next_io: + if (!(rctx->state & OHS_NOREAD)) { + n = BIO_read(rctx->io, rctx->iobuf, rctx->iobuflen); + + if (n <= 0) { + if (BIO_should_retry(rctx->io)) + return -1; + return 0; + } + + /* Write data to memory BIO */ + + if (BIO_write(rctx->mem, rctx->iobuf, n) != n) + return 0; + } + + switch (rctx->state) { + case OHS_HTTP_HEADER: + /* Last operation was adding headers: need a final \r\n */ + if (BIO_write(rctx->mem, "\r\n", 2) != 2) { + rctx->state = OHS_ERROR; + return 0; + } + rctx->state = OHS_ASN1_WRITE_INIT; + + /* fall thru */ + case OHS_ASN1_WRITE_INIT: + rctx->asn1_len = BIO_get_mem_data(rctx->mem, NULL); + rctx->state = OHS_ASN1_WRITE; + + /* fall thru */ + case OHS_ASN1_WRITE: + n = BIO_get_mem_data(rctx->mem, &p); + + i = BIO_write(rctx->io, p + (n - rctx->asn1_len), rctx->asn1_len); + + if (i <= 0) { + if (BIO_should_retry(rctx->io)) + return -1; + rctx->state = OHS_ERROR; + return 0; + } + + rctx->asn1_len -= i; + + if (rctx->asn1_len > 0) + goto next_io; + + rctx->state = OHS_ASN1_FLUSH; + + (void)BIO_reset(rctx->mem); + + /* fall thru */ + case OHS_ASN1_FLUSH: + + i = BIO_flush(rctx->io); + + if (i > 0) { + rctx->state = OHS_FIRSTLINE; + goto next_io; + } + + if (BIO_should_retry(rctx->io)) + return -1; + + rctx->state = OHS_ERROR; + return 0; + + case OHS_ERROR: + return 0; + + case OHS_FIRSTLINE: + case OHS_HEADERS: + + /* Attempt to read a line in */ + + next_line: + /* + * Due to &%^*$" memory BIO behaviour with BIO_gets we have to check + * there's a complete line in there before calling BIO_gets or we'll + * just get a partial read. + */ + n = BIO_get_mem_data(rctx->mem, &p); + if ((n <= 0) || !memchr(p, '\n', n)) { + if (n >= rctx->iobuflen) { + rctx->state = OHS_ERROR; + return 0; + } + goto next_io; + } + n = BIO_gets(rctx->mem, (char *)rctx->iobuf, rctx->iobuflen); + + if (n <= 0) { + if (BIO_should_retry(rctx->mem)) + goto next_io; + rctx->state = OHS_ERROR; + return 0; + } + + /* Don't allow excessive lines */ + if (n == rctx->iobuflen) { + rctx->state = OHS_ERROR; + return 0; + } + + /* First line */ + if (rctx->state == OHS_FIRSTLINE) { + if (parse_http_line1((char *)rctx->iobuf)) { + rctx->state = OHS_HEADERS; + goto next_line; + } else { + rctx->state = OHS_ERROR; + return 0; + } + } else { + /* Look for blank line: end of headers */ + for (p = rctx->iobuf; *p; p++) { + if ((*p != '\r') && (*p != '\n')) + break; + } + if (*p) + goto next_line; + + rctx->state = OHS_ASN1_HEADER; + + } + + /* Fall thru */ + + case OHS_ASN1_HEADER: + /* + * Now reading ASN1 header: can read at least 2 bytes which is enough + * for ASN1 SEQUENCE header and either length field or at least the + * length of the length field. + */ + n = BIO_get_mem_data(rctx->mem, &p); + if (n < 2) + goto next_io; + + /* Check it is an ASN1 SEQUENCE */ + if (*p++ != (V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED)) { + rctx->state = OHS_ERROR; + return 0; + } + + /* Check out length field */ + if (*p & 0x80) { + /* + * If MSB set on initial length octet we can now always read 6 + * octets: make sure we have them. + */ + if (n < 6) + goto next_io; + n = *p & 0x7F; + /* Not NDEF or excessive length */ + if (!n || (n > 4)) { + rctx->state = OHS_ERROR; + return 0; + } + p++; + rctx->asn1_len = 0; + for (i = 0; i < n; i++) { + rctx->asn1_len <<= 8; + rctx->asn1_len |= *p++; + } + + if (rctx->asn1_len > rctx->max_resp_len) { + rctx->state = OHS_ERROR; + return 0; + } + + rctx->asn1_len += n + 2; + } else + rctx->asn1_len = *p + 2; + + rctx->state = OHS_ASN1_CONTENT; + + /* Fall thru */ + + case OHS_ASN1_CONTENT: + n = BIO_get_mem_data(rctx->mem, NULL); + if (n < (int)rctx->asn1_len) + goto next_io; + + rctx->state = OHS_DONE; + return 1; + + case OHS_DONE: + return 1; + + } + + return 0; + +} + +int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx) +{ + return OCSP_REQ_CTX_nbio_d2i(rctx, + (ASN1_VALUE **)presp, + ASN1_ITEM_rptr(OCSP_RESPONSE)); +} + +/* Blocking OCSP request handler: now a special case of non-blocking I/O */ + +OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, const char *path, OCSP_REQUEST *req) +{ + OCSP_RESPONSE *resp = NULL; + OCSP_REQ_CTX *ctx; + int rv; + + ctx = OCSP_sendreq_new(b, path, req, -1); + + if (ctx == NULL) + return NULL; + + do { + rv = OCSP_sendreq_nbio(&resp, ctx); + } while ((rv == -1) && BIO_should_retry(b)); + + OCSP_REQ_CTX_free(ctx); + + if (rv) + return resp; + + return NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_lcl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_lcl.h new file mode 100644 index 000000000..36646fdfc --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_lcl.h @@ -0,0 +1,236 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- CertID ::= SEQUENCE { + * hashAlgorithm AlgorithmIdentifier, + * issuerNameHash OCTET STRING, -- Hash of Issuer's DN + * issuerKeyHash OCTET STRING, -- Hash of Issuers public key (excluding the tag & length fields) + * serialNumber CertificateSerialNumber } + */ +struct ocsp_cert_id_st { + X509_ALGOR hashAlgorithm; + ASN1_OCTET_STRING issuerNameHash; + ASN1_OCTET_STRING issuerKeyHash; + ASN1_INTEGER serialNumber; +}; + +/*- Request ::= SEQUENCE { + * reqCert CertID, + * singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL } + */ +struct ocsp_one_request_st { + OCSP_CERTID *reqCert; + STACK_OF(X509_EXTENSION) *singleRequestExtensions; +}; + +/*- TBSRequest ::= SEQUENCE { + * version [0] EXPLICIT Version DEFAULT v1, + * requestorName [1] EXPLICIT GeneralName OPTIONAL, + * requestList SEQUENCE OF Request, + * requestExtensions [2] EXPLICIT Extensions OPTIONAL } + */ +struct ocsp_req_info_st { + ASN1_INTEGER *version; + GENERAL_NAME *requestorName; + STACK_OF(OCSP_ONEREQ) *requestList; + STACK_OF(X509_EXTENSION) *requestExtensions; +}; + +/*- Signature ::= SEQUENCE { + * signatureAlgorithm AlgorithmIdentifier, + * signature BIT STRING, + * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } + */ +struct ocsp_signature_st { + X509_ALGOR signatureAlgorithm; + ASN1_BIT_STRING *signature; + STACK_OF(X509) *certs; +}; + +/*- OCSPRequest ::= SEQUENCE { + * tbsRequest TBSRequest, + * optionalSignature [0] EXPLICIT Signature OPTIONAL } + */ +struct ocsp_request_st { + OCSP_REQINFO tbsRequest; + OCSP_SIGNATURE *optionalSignature; /* OPTIONAL */ +}; + +/*- OCSPResponseStatus ::= ENUMERATED { + * successful (0), --Response has valid confirmations + * malformedRequest (1), --Illegal confirmation request + * internalError (2), --Internal error in issuer + * tryLater (3), --Try again later + * --(4) is not used + * sigRequired (5), --Must sign the request + * unauthorized (6) --Request unauthorized + * } + */ + +/*- ResponseBytes ::= SEQUENCE { + * responseType OBJECT IDENTIFIER, + * response OCTET STRING } + */ +struct ocsp_resp_bytes_st { + ASN1_OBJECT *responseType; + ASN1_OCTET_STRING *response; +}; + +/*- OCSPResponse ::= SEQUENCE { + * responseStatus OCSPResponseStatus, + * responseBytes [0] EXPLICIT ResponseBytes OPTIONAL } + */ +struct ocsp_response_st { + ASN1_ENUMERATED *responseStatus; + OCSP_RESPBYTES *responseBytes; +}; + +/*- ResponderID ::= CHOICE { + * byName [1] Name, + * byKey [2] KeyHash } + */ +struct ocsp_responder_id_st { + int type; + union { + X509_NAME *byName; + ASN1_OCTET_STRING *byKey; + } value; +}; + +/*- KeyHash ::= OCTET STRING --SHA-1 hash of responder's public key + * --(excluding the tag and length fields) + */ + +/*- RevokedInfo ::= SEQUENCE { + * revocationTime GeneralizedTime, + * revocationReason [0] EXPLICIT CRLReason OPTIONAL } + */ +struct ocsp_revoked_info_st { + ASN1_GENERALIZEDTIME *revocationTime; + ASN1_ENUMERATED *revocationReason; +}; + +/*- CertStatus ::= CHOICE { + * good [0] IMPLICIT NULL, + * revoked [1] IMPLICIT RevokedInfo, + * unknown [2] IMPLICIT UnknownInfo } + */ +struct ocsp_cert_status_st { + int type; + union { + ASN1_NULL *good; + OCSP_REVOKEDINFO *revoked; + ASN1_NULL *unknown; + } value; +}; + +/*- SingleResponse ::= SEQUENCE { + * certID CertID, + * certStatus CertStatus, + * thisUpdate GeneralizedTime, + * nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL, + * singleExtensions [1] EXPLICIT Extensions OPTIONAL } + */ +struct ocsp_single_response_st { + OCSP_CERTID *certId; + OCSP_CERTSTATUS *certStatus; + ASN1_GENERALIZEDTIME *thisUpdate; + ASN1_GENERALIZEDTIME *nextUpdate; + STACK_OF(X509_EXTENSION) *singleExtensions; +}; + +/*- ResponseData ::= SEQUENCE { + * version [0] EXPLICIT Version DEFAULT v1, + * responderID ResponderID, + * producedAt GeneralizedTime, + * responses SEQUENCE OF SingleResponse, + * responseExtensions [1] EXPLICIT Extensions OPTIONAL } + */ +struct ocsp_response_data_st { + ASN1_INTEGER *version; + OCSP_RESPID responderId; + ASN1_GENERALIZEDTIME *producedAt; + STACK_OF(OCSP_SINGLERESP) *responses; + STACK_OF(X509_EXTENSION) *responseExtensions; +}; + +/*- BasicOCSPResponse ::= SEQUENCE { + * tbsResponseData ResponseData, + * signatureAlgorithm AlgorithmIdentifier, + * signature BIT STRING, + * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } + */ + /* + * Note 1: The value for "signature" is specified in the OCSP rfc2560 as + * follows: "The value for the signature SHALL be computed on the hash of + * the DER encoding ResponseData." This means that you must hash the + * DER-encoded tbsResponseData, and then run it through a crypto-signing + * function, which will (at least w/RSA) do a hash-'n'-private-encrypt + * operation. This seems a bit odd, but that's the spec. Also note that + * the data structures do not leave anywhere to independently specify the + * algorithm used for the initial hash. So, we look at the + * signature-specification algorithm, and try to do something intelligent. + * -- Kathy Weinhold, CertCo + */ + /* + * Note 2: It seems that the mentioned passage from RFC 2560 (section + * 4.2.1) is open for interpretation. I've done tests against another + * responder, and found that it doesn't do the double hashing that the RFC + * seems to say one should. Therefore, all relevant functions take a flag + * saying which variant should be used. -- Richard Levitte, OpenSSL team + * and CeloCom + */ +struct ocsp_basic_response_st { + OCSP_RESPDATA tbsResponseData; + X509_ALGOR signatureAlgorithm; + ASN1_BIT_STRING *signature; + STACK_OF(X509) *certs; +}; + +/*- + * CrlID ::= SEQUENCE { + * crlUrl [0] EXPLICIT IA5String OPTIONAL, + * crlNum [1] EXPLICIT INTEGER OPTIONAL, + * crlTime [2] EXPLICIT GeneralizedTime OPTIONAL } + */ +struct ocsp_crl_id_st { + ASN1_IA5STRING *crlUrl; + ASN1_INTEGER *crlNum; + ASN1_GENERALIZEDTIME *crlTime; +}; + +/*- + * ServiceLocator ::= SEQUENCE { + * issuer Name, + * locator AuthorityInfoAccessSyntax OPTIONAL } + */ +struct ocsp_service_locator_st { + X509_NAME *issuer; + STACK_OF(ACCESS_DESCRIPTION) *locator; +}; + +# define OCSP_REQUEST_sign(o,pkey,md) \ + ASN1_item_sign(ASN1_ITEM_rptr(OCSP_REQINFO),\ + &(o)->optionalSignature->signatureAlgorithm,NULL,\ + (o)->optionalSignature->signature,&(o)->tbsRequest,pkey,md) + +# define OCSP_BASICRESP_sign(o,pkey,md,d) \ + ASN1_item_sign(ASN1_ITEM_rptr(OCSP_RESPDATA),&(o)->signatureAlgorithm,\ + NULL,(o)->signature,&(o)->tbsResponseData,pkey,md) + +# define OCSP_BASICRESP_sign_ctx(o,ctx,d) \ + ASN1_item_sign_ctx(ASN1_ITEM_rptr(OCSP_RESPDATA),&(o)->signatureAlgorithm,\ + NULL,(o)->signature,&(o)->tbsResponseData,ctx) + +# define OCSP_REQUEST_verify(a,r) ASN1_item_verify(ASN1_ITEM_rptr(OCSP_REQINFO),\ + &(a)->optionalSignature->signatureAlgorithm,\ + (a)->optionalSignature->signature,&(a)->tbsRequest,r) + +# define OCSP_BASICRESP_verify(a,r,d) ASN1_item_verify(ASN1_ITEM_rptr(OCSP_RESPDATA),\ + &(a)->signatureAlgorithm,(a)->signature,&(a)->tbsResponseData,r) diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_lib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_lib.c new file mode 100644 index 000000000..8edd70ac8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_lib.c @@ -0,0 +1,222 @@ +/* + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include "ocsp_lcl.h" +#include + +/* Convert a certificate and its issuer to an OCSP_CERTID */ + +OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, const X509 *subject, + const X509 *issuer) +{ + X509_NAME *iname; + const ASN1_INTEGER *serial; + ASN1_BIT_STRING *ikey; + if (!dgst) + dgst = EVP_sha1(); + if (subject) { + iname = X509_get_issuer_name(subject); + serial = X509_get0_serialNumber(subject); + } else { + iname = X509_get_subject_name(issuer); + serial = NULL; + } + ikey = X509_get0_pubkey_bitstr(issuer); + return OCSP_cert_id_new(dgst, iname, ikey, serial); +} + +OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst, + const X509_NAME *issuerName, + const ASN1_BIT_STRING *issuerKey, + const ASN1_INTEGER *serialNumber) +{ + int nid; + unsigned int i; + X509_ALGOR *alg; + OCSP_CERTID *cid = NULL; + unsigned char md[EVP_MAX_MD_SIZE]; + + if ((cid = OCSP_CERTID_new()) == NULL) + goto err; + + alg = &cid->hashAlgorithm; + ASN1_OBJECT_free(alg->algorithm); + if ((nid = EVP_MD_type(dgst)) == NID_undef) { + OCSPerr(OCSP_F_OCSP_CERT_ID_NEW, OCSP_R_UNKNOWN_NID); + goto err; + } + if ((alg->algorithm = OBJ_nid2obj(nid)) == NULL) + goto err; + if ((alg->parameter = ASN1_TYPE_new()) == NULL) + goto err; + alg->parameter->type = V_ASN1_NULL; + + if (!X509_NAME_digest(issuerName, dgst, md, &i)) + goto digerr; + if (!(ASN1_OCTET_STRING_set(&cid->issuerNameHash, md, i))) + goto err; + + /* Calculate the issuerKey hash, excluding tag and length */ + if (!EVP_Digest(issuerKey->data, issuerKey->length, md, &i, dgst, NULL)) + goto err; + + if (!(ASN1_OCTET_STRING_set(&cid->issuerKeyHash, md, i))) + goto err; + + if (serialNumber) { + if (ASN1_STRING_copy(&cid->serialNumber, serialNumber) == 0) + goto err; + } + return cid; + digerr: + OCSPerr(OCSP_F_OCSP_CERT_ID_NEW, OCSP_R_DIGEST_ERR); + err: + OCSP_CERTID_free(cid); + return NULL; +} + +int OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b) +{ + int ret; + ret = OBJ_cmp(a->hashAlgorithm.algorithm, b->hashAlgorithm.algorithm); + if (ret) + return ret; + ret = ASN1_OCTET_STRING_cmp(&a->issuerNameHash, &b->issuerNameHash); + if (ret) + return ret; + return ASN1_OCTET_STRING_cmp(&a->issuerKeyHash, &b->issuerKeyHash); +} + +int OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b) +{ + int ret; + ret = OCSP_id_issuer_cmp(a, b); + if (ret) + return ret; + return ASN1_INTEGER_cmp(&a->serialNumber, &b->serialNumber); +} + +/* + * Parse a URL and split it up into host, port and path components and + * whether it is SSL. + */ + +int OCSP_parse_url(const char *url, char **phost, char **pport, char **ppath, + int *pssl) +{ + char *p, *buf; + + char *host, *port; + + *phost = NULL; + *pport = NULL; + *ppath = NULL; + + /* dup the buffer since we are going to mess with it */ + buf = OPENSSL_strdup(url); + if (!buf) + goto mem_err; + + /* Check for initial colon */ + p = strchr(buf, ':'); + + if (!p) + goto parse_err; + + *(p++) = '\0'; + + if (strcmp(buf, "http") == 0) { + *pssl = 0; + port = "80"; + } else if (strcmp(buf, "https") == 0) { + *pssl = 1; + port = "443"; + } else + goto parse_err; + + /* Check for double slash */ + if ((p[0] != '/') || (p[1] != '/')) + goto parse_err; + + p += 2; + + host = p; + + /* Check for trailing part of path */ + + p = strchr(p, '/'); + + if (!p) + *ppath = OPENSSL_strdup("/"); + else { + *ppath = OPENSSL_strdup(p); + /* Set start of path to 0 so hostname is valid */ + *p = '\0'; + } + + if (!*ppath) + goto mem_err; + + p = host; + if (host[0] == '[') { + /* ipv6 literal */ + host++; + p = strchr(host, ']'); + if (!p) + goto parse_err; + *p = '\0'; + p++; + } + + /* Look for optional ':' for port number */ + if ((p = strchr(p, ':'))) { + *p = 0; + port = p + 1; + } + + *pport = OPENSSL_strdup(port); + if (!*pport) + goto mem_err; + + *phost = OPENSSL_strdup(host); + + if (!*phost) + goto mem_err; + + OPENSSL_free(buf); + + return 1; + + mem_err: + OCSPerr(OCSP_F_OCSP_PARSE_URL, ERR_R_MALLOC_FAILURE); + goto err; + + parse_err: + OCSPerr(OCSP_F_OCSP_PARSE_URL, OCSP_R_ERROR_PARSING_URL); + + err: + OPENSSL_free(buf); + OPENSSL_free(*ppath); + *ppath = NULL; + OPENSSL_free(*pport); + *pport = NULL; + OPENSSL_free(*phost); + *phost = NULL; + return 0; + +} + +IMPLEMENT_ASN1_DUP_FUNCTION(OCSP_CERTID) diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_prn.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_prn.c new file mode 100644 index 000000000..5605812ef --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_prn.c @@ -0,0 +1,246 @@ +/* + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "ocsp_lcl.h" +#include "internal/cryptlib.h" +#include + +static int ocsp_certid_print(BIO *bp, OCSP_CERTID *a, int indent) +{ + BIO_printf(bp, "%*sCertificate ID:\n", indent, ""); + indent += 2; + BIO_printf(bp, "%*sHash Algorithm: ", indent, ""); + i2a_ASN1_OBJECT(bp, a->hashAlgorithm.algorithm); + BIO_printf(bp, "\n%*sIssuer Name Hash: ", indent, ""); + i2a_ASN1_STRING(bp, &a->issuerNameHash, 0); + BIO_printf(bp, "\n%*sIssuer Key Hash: ", indent, ""); + i2a_ASN1_STRING(bp, &a->issuerKeyHash, 0); + BIO_printf(bp, "\n%*sSerial Number: ", indent, ""); + i2a_ASN1_INTEGER(bp, &a->serialNumber); + BIO_printf(bp, "\n"); + return 1; +} + +typedef struct { + long t; + const char *m; +} OCSP_TBLSTR; + +static const char *do_table2string(long s, const OCSP_TBLSTR *ts, size_t len) +{ + size_t i; + for (i = 0; i < len; i++, ts++) + if (ts->t == s) + return ts->m; + return "(UNKNOWN)"; +} + +#define table2string(s, tbl) do_table2string(s, tbl, OSSL_NELEM(tbl)) + +const char *OCSP_response_status_str(long s) +{ + static const OCSP_TBLSTR rstat_tbl[] = { + {OCSP_RESPONSE_STATUS_SUCCESSFUL, "successful"}, + {OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, "malformedrequest"}, + {OCSP_RESPONSE_STATUS_INTERNALERROR, "internalerror"}, + {OCSP_RESPONSE_STATUS_TRYLATER, "trylater"}, + {OCSP_RESPONSE_STATUS_SIGREQUIRED, "sigrequired"}, + {OCSP_RESPONSE_STATUS_UNAUTHORIZED, "unauthorized"} + }; + return table2string(s, rstat_tbl); +} + +const char *OCSP_cert_status_str(long s) +{ + static const OCSP_TBLSTR cstat_tbl[] = { + {V_OCSP_CERTSTATUS_GOOD, "good"}, + {V_OCSP_CERTSTATUS_REVOKED, "revoked"}, + {V_OCSP_CERTSTATUS_UNKNOWN, "unknown"} + }; + return table2string(s, cstat_tbl); +} + +const char *OCSP_crl_reason_str(long s) +{ + static const OCSP_TBLSTR reason_tbl[] = { + {OCSP_REVOKED_STATUS_UNSPECIFIED, "unspecified"}, + {OCSP_REVOKED_STATUS_KEYCOMPROMISE, "keyCompromise"}, + {OCSP_REVOKED_STATUS_CACOMPROMISE, "cACompromise"}, + {OCSP_REVOKED_STATUS_AFFILIATIONCHANGED, "affiliationChanged"}, + {OCSP_REVOKED_STATUS_SUPERSEDED, "superseded"}, + {OCSP_REVOKED_STATUS_CESSATIONOFOPERATION, "cessationOfOperation"}, + {OCSP_REVOKED_STATUS_CERTIFICATEHOLD, "certificateHold"}, + {OCSP_REVOKED_STATUS_REMOVEFROMCRL, "removeFromCRL"} + }; + return table2string(s, reason_tbl); +} + +int OCSP_REQUEST_print(BIO *bp, OCSP_REQUEST *o, unsigned long flags) +{ + int i; + long l; + OCSP_CERTID *cid = NULL; + OCSP_ONEREQ *one = NULL; + OCSP_REQINFO *inf = &o->tbsRequest; + OCSP_SIGNATURE *sig = o->optionalSignature; + + if (BIO_write(bp, "OCSP Request Data:\n", 19) <= 0) + goto err; + l = ASN1_INTEGER_get(inf->version); + if (BIO_printf(bp, " Version: %lu (0x%lx)", l + 1, l) <= 0) + goto err; + if (inf->requestorName != NULL) { + if (BIO_write(bp, "\n Requestor Name: ", 21) <= 0) + goto err; + GENERAL_NAME_print(bp, inf->requestorName); + } + if (BIO_write(bp, "\n Requestor List:\n", 21) <= 0) + goto err; + for (i = 0; i < sk_OCSP_ONEREQ_num(inf->requestList); i++) { + one = sk_OCSP_ONEREQ_value(inf->requestList, i); + cid = one->reqCert; + ocsp_certid_print(bp, cid, 8); + if (!X509V3_extensions_print(bp, + "Request Single Extensions", + one->singleRequestExtensions, flags, 8)) + goto err; + } + if (!X509V3_extensions_print(bp, "Request Extensions", + inf->requestExtensions, flags, 4)) + goto err; + if (sig) { + X509_signature_print(bp, &sig->signatureAlgorithm, sig->signature); + for (i = 0; i < sk_X509_num(sig->certs); i++) { + X509_print(bp, sk_X509_value(sig->certs, i)); + PEM_write_bio_X509(bp, sk_X509_value(sig->certs, i)); + } + } + return 1; + err: + return 0; +} + +int OCSP_RESPONSE_print(BIO *bp, OCSP_RESPONSE *o, unsigned long flags) +{ + int i, ret = 0; + long l; + OCSP_CERTID *cid = NULL; + OCSP_BASICRESP *br = NULL; + OCSP_RESPID *rid = NULL; + OCSP_RESPDATA *rd = NULL; + OCSP_CERTSTATUS *cst = NULL; + OCSP_REVOKEDINFO *rev = NULL; + OCSP_SINGLERESP *single = NULL; + OCSP_RESPBYTES *rb = o->responseBytes; + + if (BIO_puts(bp, "OCSP Response Data:\n") <= 0) + goto err; + l = ASN1_ENUMERATED_get(o->responseStatus); + if (BIO_printf(bp, " OCSP Response Status: %s (0x%lx)\n", + OCSP_response_status_str(l), l) <= 0) + goto err; + if (rb == NULL) + return 1; + if (BIO_puts(bp, " Response Type: ") <= 0) + goto err; + if (i2a_ASN1_OBJECT(bp, rb->responseType) <= 0) + goto err; + if (OBJ_obj2nid(rb->responseType) != NID_id_pkix_OCSP_basic) { + BIO_puts(bp, " (unknown response type)\n"); + return 1; + } + + if ((br = OCSP_response_get1_basic(o)) == NULL) + goto err; + rd = &br->tbsResponseData; + l = ASN1_INTEGER_get(rd->version); + if (BIO_printf(bp, "\n Version: %lu (0x%lx)\n", l + 1, l) <= 0) + goto err; + if (BIO_puts(bp, " Responder Id: ") <= 0) + goto err; + + rid = &rd->responderId; + switch (rid->type) { + case V_OCSP_RESPID_NAME: + X509_NAME_print_ex(bp, rid->value.byName, 0, XN_FLAG_ONELINE); + break; + case V_OCSP_RESPID_KEY: + i2a_ASN1_STRING(bp, rid->value.byKey, 0); + break; + } + + if (BIO_printf(bp, "\n Produced At: ") <= 0) + goto err; + if (!ASN1_GENERALIZEDTIME_print(bp, rd->producedAt)) + goto err; + if (BIO_printf(bp, "\n Responses:\n") <= 0) + goto err; + for (i = 0; i < sk_OCSP_SINGLERESP_num(rd->responses); i++) { + if (!sk_OCSP_SINGLERESP_value(rd->responses, i)) + continue; + single = sk_OCSP_SINGLERESP_value(rd->responses, i); + cid = single->certId; + if (ocsp_certid_print(bp, cid, 4) <= 0) + goto err; + cst = single->certStatus; + if (BIO_printf(bp, " Cert Status: %s", + OCSP_cert_status_str(cst->type)) <= 0) + goto err; + if (cst->type == V_OCSP_CERTSTATUS_REVOKED) { + rev = cst->value.revoked; + if (BIO_printf(bp, "\n Revocation Time: ") <= 0) + goto err; + if (!ASN1_GENERALIZEDTIME_print(bp, rev->revocationTime)) + goto err; + if (rev->revocationReason) { + l = ASN1_ENUMERATED_get(rev->revocationReason); + if (BIO_printf(bp, + "\n Revocation Reason: %s (0x%lx)", + OCSP_crl_reason_str(l), l) <= 0) + goto err; + } + } + if (BIO_printf(bp, "\n This Update: ") <= 0) + goto err; + if (!ASN1_GENERALIZEDTIME_print(bp, single->thisUpdate)) + goto err; + if (single->nextUpdate) { + if (BIO_printf(bp, "\n Next Update: ") <= 0) + goto err; + if (!ASN1_GENERALIZEDTIME_print(bp, single->nextUpdate)) + goto err; + } + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + if (!X509V3_extensions_print(bp, + "Response Single Extensions", + single->singleExtensions, flags, 8)) + goto err; + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + } + if (!X509V3_extensions_print(bp, "Response Extensions", + rd->responseExtensions, flags, 4)) + goto err; + if (X509_signature_print(bp, &br->signatureAlgorithm, br->signature) <= 0) + goto err; + + for (i = 0; i < sk_X509_num(br->certs); i++) { + X509_print(bp, sk_X509_value(br->certs, i)); + PEM_write_bio_X509(bp, sk_X509_value(br->certs, i)); + } + + ret = 1; + err: + OCSP_BASICRESP_free(br); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_srv.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_srv.c new file mode 100644 index 000000000..6bd6f7b6d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_srv.c @@ -0,0 +1,310 @@ +/* + * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include "ocsp_lcl.h" + +/* + * Utility functions related to sending OCSP responses and extracting + * relevant information from the request. + */ + +int OCSP_request_onereq_count(OCSP_REQUEST *req) +{ + return sk_OCSP_ONEREQ_num(req->tbsRequest.requestList); +} + +OCSP_ONEREQ *OCSP_request_onereq_get0(OCSP_REQUEST *req, int i) +{ + return sk_OCSP_ONEREQ_value(req->tbsRequest.requestList, i); +} + +OCSP_CERTID *OCSP_onereq_get0_id(OCSP_ONEREQ *one) +{ + return one->reqCert; +} + +int OCSP_id_get0_info(ASN1_OCTET_STRING **piNameHash, ASN1_OBJECT **pmd, + ASN1_OCTET_STRING **pikeyHash, + ASN1_INTEGER **pserial, OCSP_CERTID *cid) +{ + if (!cid) + return 0; + if (pmd) + *pmd = cid->hashAlgorithm.algorithm; + if (piNameHash) + *piNameHash = &cid->issuerNameHash; + if (pikeyHash) + *pikeyHash = &cid->issuerKeyHash; + if (pserial) + *pserial = &cid->serialNumber; + return 1; +} + +int OCSP_request_is_signed(OCSP_REQUEST *req) +{ + if (req->optionalSignature) + return 1; + return 0; +} + +/* Create an OCSP response and encode an optional basic response */ +OCSP_RESPONSE *OCSP_response_create(int status, OCSP_BASICRESP *bs) +{ + OCSP_RESPONSE *rsp = NULL; + + if ((rsp = OCSP_RESPONSE_new()) == NULL) + goto err; + if (!(ASN1_ENUMERATED_set(rsp->responseStatus, status))) + goto err; + if (!bs) + return rsp; + if ((rsp->responseBytes = OCSP_RESPBYTES_new()) == NULL) + goto err; + rsp->responseBytes->responseType = OBJ_nid2obj(NID_id_pkix_OCSP_basic); + if (!ASN1_item_pack + (bs, ASN1_ITEM_rptr(OCSP_BASICRESP), &rsp->responseBytes->response)) + goto err; + return rsp; + err: + OCSP_RESPONSE_free(rsp); + return NULL; +} + +OCSP_SINGLERESP *OCSP_basic_add1_status(OCSP_BASICRESP *rsp, + OCSP_CERTID *cid, + int status, int reason, + ASN1_TIME *revtime, + ASN1_TIME *thisupd, + ASN1_TIME *nextupd) +{ + OCSP_SINGLERESP *single = NULL; + OCSP_CERTSTATUS *cs; + OCSP_REVOKEDINFO *ri; + + if (rsp->tbsResponseData.responses == NULL + && (rsp->tbsResponseData.responses + = sk_OCSP_SINGLERESP_new_null()) == NULL) + goto err; + + if ((single = OCSP_SINGLERESP_new()) == NULL) + goto err; + + if (!ASN1_TIME_to_generalizedtime(thisupd, &single->thisUpdate)) + goto err; + if (nextupd && + !ASN1_TIME_to_generalizedtime(nextupd, &single->nextUpdate)) + goto err; + + OCSP_CERTID_free(single->certId); + + if ((single->certId = OCSP_CERTID_dup(cid)) == NULL) + goto err; + + cs = single->certStatus; + switch (cs->type = status) { + case V_OCSP_CERTSTATUS_REVOKED: + if (!revtime) { + OCSPerr(OCSP_F_OCSP_BASIC_ADD1_STATUS, OCSP_R_NO_REVOKED_TIME); + goto err; + } + if ((cs->value.revoked = ri = OCSP_REVOKEDINFO_new()) == NULL) + goto err; + if (!ASN1_TIME_to_generalizedtime(revtime, &ri->revocationTime)) + goto err; + if (reason != OCSP_REVOKED_STATUS_NOSTATUS) { + if ((ri->revocationReason = ASN1_ENUMERATED_new()) == NULL) + goto err; + if (!(ASN1_ENUMERATED_set(ri->revocationReason, reason))) + goto err; + } + break; + + case V_OCSP_CERTSTATUS_GOOD: + if ((cs->value.good = ASN1_NULL_new()) == NULL) + goto err; + break; + + case V_OCSP_CERTSTATUS_UNKNOWN: + if ((cs->value.unknown = ASN1_NULL_new()) == NULL) + goto err; + break; + + default: + goto err; + + } + if (!(sk_OCSP_SINGLERESP_push(rsp->tbsResponseData.responses, single))) + goto err; + return single; + err: + OCSP_SINGLERESP_free(single); + return NULL; +} + +/* Add a certificate to an OCSP request */ + +int OCSP_basic_add1_cert(OCSP_BASICRESP *resp, X509 *cert) +{ + if (resp->certs == NULL + && (resp->certs = sk_X509_new_null()) == NULL) + return 0; + + if (!sk_X509_push(resp->certs, cert)) + return 0; + X509_up_ref(cert); + return 1; +} + +/* + * Sign an OCSP response using the parameters contained in the digest context, + * set the responderID to the subject name in the signer's certificate, and + * include one or more optional certificates in the response. + */ + +int OCSP_basic_sign_ctx(OCSP_BASICRESP *brsp, + X509 *signer, EVP_MD_CTX *ctx, + STACK_OF(X509) *certs, unsigned long flags) +{ + int i; + OCSP_RESPID *rid; + EVP_PKEY *pkey; + + if (ctx == NULL || EVP_MD_CTX_pkey_ctx(ctx) == NULL) { + OCSPerr(OCSP_F_OCSP_BASIC_SIGN_CTX, OCSP_R_NO_SIGNER_KEY); + goto err; + } + + pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_pkey_ctx(ctx)); + if (pkey == NULL || !X509_check_private_key(signer, pkey)) { + OCSPerr(OCSP_F_OCSP_BASIC_SIGN_CTX, + OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); + goto err; + } + + if (!(flags & OCSP_NOCERTS)) { + if (!OCSP_basic_add1_cert(brsp, signer)) + goto err; + for (i = 0; i < sk_X509_num(certs); i++) { + X509 *tmpcert = sk_X509_value(certs, i); + if (!OCSP_basic_add1_cert(brsp, tmpcert)) + goto err; + } + } + + rid = &brsp->tbsResponseData.responderId; + if (flags & OCSP_RESPID_KEY) { + if (!OCSP_RESPID_set_by_key(rid, signer)) + goto err; + } else if (!OCSP_RESPID_set_by_name(rid, signer)) { + goto err; + } + + if (!(flags & OCSP_NOTIME) && + !X509_gmtime_adj(brsp->tbsResponseData.producedAt, 0)) + goto err; + + /* + * Right now, I think that not doing double hashing is the right thing. + * -- Richard Levitte + */ + + if (!OCSP_BASICRESP_sign_ctx(brsp, ctx, 0)) + goto err; + + return 1; + err: + return 0; +} + +int OCSP_basic_sign(OCSP_BASICRESP *brsp, + X509 *signer, EVP_PKEY *key, const EVP_MD *dgst, + STACK_OF(X509) *certs, unsigned long flags) +{ + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + EVP_PKEY_CTX *pkctx = NULL; + int i; + + if (ctx == NULL) + return 0; + + if (!EVP_DigestSignInit(ctx, &pkctx, dgst, NULL, key)) { + EVP_MD_CTX_free(ctx); + return 0; + } + i = OCSP_basic_sign_ctx(brsp, signer, ctx, certs, flags); + EVP_MD_CTX_free(ctx); + return i; +} + +int OCSP_RESPID_set_by_name(OCSP_RESPID *respid, X509 *cert) +{ + if (!X509_NAME_set(&respid->value.byName, X509_get_subject_name(cert))) + return 0; + + respid->type = V_OCSP_RESPID_NAME; + + return 1; +} + +int OCSP_RESPID_set_by_key(OCSP_RESPID *respid, X509 *cert) +{ + ASN1_OCTET_STRING *byKey = NULL; + unsigned char md[SHA_DIGEST_LENGTH]; + + /* RFC2560 requires SHA1 */ + if (!X509_pubkey_digest(cert, EVP_sha1(), md, NULL)) + return 0; + + byKey = ASN1_OCTET_STRING_new(); + if (byKey == NULL) + return 0; + + if (!(ASN1_OCTET_STRING_set(byKey, md, SHA_DIGEST_LENGTH))) { + ASN1_OCTET_STRING_free(byKey); + return 0; + } + + respid->type = V_OCSP_RESPID_KEY; + respid->value.byKey = byKey; + + return 1; +} + +int OCSP_RESPID_match(OCSP_RESPID *respid, X509 *cert) +{ + if (respid->type == V_OCSP_RESPID_KEY) { + unsigned char md[SHA_DIGEST_LENGTH]; + + if (respid->value.byKey == NULL) + return 0; + + /* RFC2560 requires SHA1 */ + if (!X509_pubkey_digest(cert, EVP_sha1(), md, NULL)) + return 0; + + return (ASN1_STRING_length(respid->value.byKey) == SHA_DIGEST_LENGTH) + && (memcmp(ASN1_STRING_get0_data(respid->value.byKey), md, + SHA_DIGEST_LENGTH) == 0); + } else if (respid->type == V_OCSP_RESPID_NAME) { + if (respid->value.byName == NULL) + return 0; + + return X509_NAME_cmp(respid->value.byName, + X509_get_subject_name(cert)) == 0; + } + + return 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_vfy.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_vfy.c new file mode 100644 index 000000000..9a8d34386 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/ocsp_vfy.c @@ -0,0 +1,435 @@ +/* + * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "ocsp_lcl.h" +#include +#include + +static int ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, + STACK_OF(X509) *certs, unsigned long flags); +static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id); +static int ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain); +static int ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, + OCSP_CERTID **ret); +static int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid, + STACK_OF(OCSP_SINGLERESP) *sresp); +static int ocsp_check_delegated(X509 *x); +static int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req, + X509_NAME *nm, STACK_OF(X509) *certs, + unsigned long flags); + +/* Verify a basic response message */ + +int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, + X509_STORE *st, unsigned long flags) +{ + X509 *signer, *x; + STACK_OF(X509) *chain = NULL; + STACK_OF(X509) *untrusted = NULL; + X509_STORE_CTX *ctx = NULL; + int i, ret = ocsp_find_signer(&signer, bs, certs, flags); + + if (!ret) { + OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, + OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND); + goto end; + } + ctx = X509_STORE_CTX_new(); + if (ctx == NULL) { + OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, ERR_R_MALLOC_FAILURE); + goto f_err; + } + if ((ret == 2) && (flags & OCSP_TRUSTOTHER)) + flags |= OCSP_NOVERIFY; + if (!(flags & OCSP_NOSIGS)) { + EVP_PKEY *skey; + skey = X509_get0_pubkey(signer); + if (skey == NULL) { + OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, OCSP_R_NO_SIGNER_KEY); + goto err; + } + ret = OCSP_BASICRESP_verify(bs, skey, 0); + if (ret <= 0) { + OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, OCSP_R_SIGNATURE_FAILURE); + goto end; + } + } + if (!(flags & OCSP_NOVERIFY)) { + int init_res; + if (flags & OCSP_NOCHAIN) { + untrusted = NULL; + } else if (bs->certs && certs) { + untrusted = sk_X509_dup(bs->certs); + for (i = 0; i < sk_X509_num(certs); i++) { + if (!sk_X509_push(untrusted, sk_X509_value(certs, i))) { + OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, ERR_R_MALLOC_FAILURE); + goto f_err; + } + } + } else if (certs != NULL) { + untrusted = certs; + } else { + untrusted = bs->certs; + } + init_res = X509_STORE_CTX_init(ctx, st, signer, untrusted); + if (!init_res) { + OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, ERR_R_X509_LIB); + goto f_err; + } + + X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_OCSP_HELPER); + ret = X509_verify_cert(ctx); + chain = X509_STORE_CTX_get1_chain(ctx); + if (ret <= 0) { + i = X509_STORE_CTX_get_error(ctx); + OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, + OCSP_R_CERTIFICATE_VERIFY_ERROR); + ERR_add_error_data(2, "Verify error:", + X509_verify_cert_error_string(i)); + goto end; + } + if (flags & OCSP_NOCHECKS) { + ret = 1; + goto end; + } + /* + * At this point we have a valid certificate chain need to verify it + * against the OCSP issuer criteria. + */ + ret = ocsp_check_issuer(bs, chain); + + /* If fatal error or valid match then finish */ + if (ret != 0) + goto end; + + /* + * Easy case: explicitly trusted. Get root CA and check for explicit + * trust + */ + if (flags & OCSP_NOEXPLICIT) + goto end; + + x = sk_X509_value(chain, sk_X509_num(chain) - 1); + if (X509_check_trust(x, NID_OCSP_sign, 0) != X509_TRUST_TRUSTED) { + OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, OCSP_R_ROOT_CA_NOT_TRUSTED); + goto err; + } + ret = 1; + } + end: + X509_STORE_CTX_free(ctx); + sk_X509_pop_free(chain, X509_free); + if (bs->certs && certs) + sk_X509_free(untrusted); + return ret; + + err: + ret = 0; + goto end; + f_err: + ret = -1; + goto end; +} + +int OCSP_resp_get0_signer(OCSP_BASICRESP *bs, X509 **signer, + STACK_OF(X509) *extra_certs) +{ + int ret; + + ret = ocsp_find_signer(signer, bs, extra_certs, 0); + return (ret > 0) ? 1 : 0; +} + +static int ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, + STACK_OF(X509) *certs, unsigned long flags) +{ + X509 *signer; + OCSP_RESPID *rid = &bs->tbsResponseData.responderId; + if ((signer = ocsp_find_signer_sk(certs, rid))) { + *psigner = signer; + return 2; + } + if (!(flags & OCSP_NOINTERN) && + (signer = ocsp_find_signer_sk(bs->certs, rid))) { + *psigner = signer; + return 1; + } + /* Maybe lookup from store if by subject name */ + + *psigner = NULL; + return 0; +} + +static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id) +{ + int i; + unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash; + X509 *x; + + /* Easy if lookup by name */ + if (id->type == V_OCSP_RESPID_NAME) + return X509_find_by_subject(certs, id->value.byName); + + /* Lookup by key hash */ + + /* If key hash isn't SHA1 length then forget it */ + if (id->value.byKey->length != SHA_DIGEST_LENGTH) + return NULL; + keyhash = id->value.byKey->data; + /* Calculate hash of each key and compare */ + for (i = 0; i < sk_X509_num(certs); i++) { + x = sk_X509_value(certs, i); + X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL); + if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH)) + return x; + } + return NULL; +} + +static int ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain) +{ + STACK_OF(OCSP_SINGLERESP) *sresp; + X509 *signer, *sca; + OCSP_CERTID *caid = NULL; + int i; + sresp = bs->tbsResponseData.responses; + + if (sk_X509_num(chain) <= 0) { + OCSPerr(OCSP_F_OCSP_CHECK_ISSUER, OCSP_R_NO_CERTIFICATES_IN_CHAIN); + return -1; + } + + /* See if the issuer IDs match. */ + i = ocsp_check_ids(sresp, &caid); + + /* If ID mismatch or other error then return */ + if (i <= 0) + return i; + + signer = sk_X509_value(chain, 0); + /* Check to see if OCSP responder CA matches request CA */ + if (sk_X509_num(chain) > 1) { + sca = sk_X509_value(chain, 1); + i = ocsp_match_issuerid(sca, caid, sresp); + if (i < 0) + return i; + if (i) { + /* We have a match, if extensions OK then success */ + if (ocsp_check_delegated(signer)) + return 1; + return 0; + } + } + + /* Otherwise check if OCSP request signed directly by request CA */ + return ocsp_match_issuerid(signer, caid, sresp); +} + +/* + * Check the issuer certificate IDs for equality. If there is a mismatch with + * the same algorithm then there's no point trying to match any certificates + * against the issuer. If the issuer IDs all match then we just need to check + * equality against one of them. + */ + +static int ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, OCSP_CERTID **ret) +{ + OCSP_CERTID *tmpid, *cid; + int i, idcount; + + idcount = sk_OCSP_SINGLERESP_num(sresp); + if (idcount <= 0) { + OCSPerr(OCSP_F_OCSP_CHECK_IDS, + OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA); + return -1; + } + + cid = sk_OCSP_SINGLERESP_value(sresp, 0)->certId; + + *ret = NULL; + + for (i = 1; i < idcount; i++) { + tmpid = sk_OCSP_SINGLERESP_value(sresp, i)->certId; + /* Check to see if IDs match */ + if (OCSP_id_issuer_cmp(cid, tmpid)) { + /* If algorithm mismatch let caller deal with it */ + if (OBJ_cmp(tmpid->hashAlgorithm.algorithm, + cid->hashAlgorithm.algorithm)) + return 2; + /* Else mismatch */ + return 0; + } + } + + /* All IDs match: only need to check one ID */ + *ret = cid; + return 1; +} + +static int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid, + STACK_OF(OCSP_SINGLERESP) *sresp) +{ + /* If only one ID to match then do it */ + if (cid) { + const EVP_MD *dgst; + X509_NAME *iname; + int mdlen; + unsigned char md[EVP_MAX_MD_SIZE]; + if ((dgst = EVP_get_digestbyobj(cid->hashAlgorithm.algorithm)) + == NULL) { + OCSPerr(OCSP_F_OCSP_MATCH_ISSUERID, + OCSP_R_UNKNOWN_MESSAGE_DIGEST); + return -1; + } + + mdlen = EVP_MD_size(dgst); + if (mdlen < 0) + return -1; + if ((cid->issuerNameHash.length != mdlen) || + (cid->issuerKeyHash.length != mdlen)) + return 0; + iname = X509_get_subject_name(cert); + if (!X509_NAME_digest(iname, dgst, md, NULL)) + return -1; + if (memcmp(md, cid->issuerNameHash.data, mdlen)) + return 0; + X509_pubkey_digest(cert, dgst, md, NULL); + if (memcmp(md, cid->issuerKeyHash.data, mdlen)) + return 0; + + return 1; + + } else { + /* We have to match the whole lot */ + int i, ret; + OCSP_CERTID *tmpid; + for (i = 0; i < sk_OCSP_SINGLERESP_num(sresp); i++) { + tmpid = sk_OCSP_SINGLERESP_value(sresp, i)->certId; + ret = ocsp_match_issuerid(cert, tmpid, NULL); + if (ret <= 0) + return ret; + } + return 1; + } + +} + +static int ocsp_check_delegated(X509 *x) +{ + if ((X509_get_extension_flags(x) & EXFLAG_XKUSAGE) + && (X509_get_extended_key_usage(x) & XKU_OCSP_SIGN)) + return 1; + OCSPerr(OCSP_F_OCSP_CHECK_DELEGATED, OCSP_R_MISSING_OCSPSIGNING_USAGE); + return 0; +} + +/* + * Verify an OCSP request. This is fortunately much easier than OCSP response + * verify. Just find the signers certificate and verify it against a given + * trust value. + */ + +int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs, + X509_STORE *store, unsigned long flags) +{ + X509 *signer; + X509_NAME *nm; + GENERAL_NAME *gen; + int ret = 0; + X509_STORE_CTX *ctx = X509_STORE_CTX_new(); + + if (ctx == NULL) { + OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!req->optionalSignature) { + OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_REQUEST_NOT_SIGNED); + goto err; + } + gen = req->tbsRequest.requestorName; + if (!gen || gen->type != GEN_DIRNAME) { + OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, + OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE); + goto err; + } + nm = gen->d.directoryName; + ret = ocsp_req_find_signer(&signer, req, nm, certs, flags); + if (ret <= 0) { + OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, + OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND); + goto err; + } + if ((ret == 2) && (flags & OCSP_TRUSTOTHER)) + flags |= OCSP_NOVERIFY; + if (!(flags & OCSP_NOSIGS)) { + EVP_PKEY *skey; + skey = X509_get0_pubkey(signer); + ret = OCSP_REQUEST_verify(req, skey); + if (ret <= 0) { + OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_SIGNATURE_FAILURE); + goto err; + } + } + if (!(flags & OCSP_NOVERIFY)) { + int init_res; + if (flags & OCSP_NOCHAIN) + init_res = X509_STORE_CTX_init(ctx, store, signer, NULL); + else + init_res = X509_STORE_CTX_init(ctx, store, signer, + req->optionalSignature->certs); + if (!init_res) { + OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, ERR_R_X509_LIB); + goto err; + } + + X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_OCSP_HELPER); + X509_STORE_CTX_set_trust(ctx, X509_TRUST_OCSP_REQUEST); + ret = X509_verify_cert(ctx); + if (ret <= 0) { + ret = X509_STORE_CTX_get_error(ctx); + OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, + OCSP_R_CERTIFICATE_VERIFY_ERROR); + ERR_add_error_data(2, "Verify error:", + X509_verify_cert_error_string(ret)); + goto err; + } + } + ret = 1; + goto end; + +err: + ret = 0; +end: + X509_STORE_CTX_free(ctx); + return ret; + +} + +static int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req, + X509_NAME *nm, STACK_OF(X509) *certs, + unsigned long flags) +{ + X509 *signer; + if (!(flags & OCSP_NOINTERN)) { + signer = X509_find_by_subject(req->optionalSignature->certs, nm); + if (signer) { + *psigner = signer; + return 1; + } + } + + signer = X509_find_by_subject(certs, nm); + if (signer) { + *psigner = signer; + return 2; + } + return 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/v3_ocsp.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/v3_ocsp.c new file mode 100644 index 000000000..2d425a895 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ocsp/v3_ocsp.c @@ -0,0 +1,264 @@ +/* + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +# include +# include "internal/cryptlib.h" +# include +# include +# include +# include "ocsp_lcl.h" +# include +# include "../x509v3/ext_dat.h" + +/* + * OCSP extensions and a couple of CRL entry extensions + */ + +static int i2r_ocsp_crlid(const X509V3_EXT_METHOD *method, void *nonce, + BIO *out, int indent); +static int i2r_ocsp_acutoff(const X509V3_EXT_METHOD *method, void *nonce, + BIO *out, int indent); +static int i2r_object(const X509V3_EXT_METHOD *method, void *obj, BIO *out, + int indent); + +static void *ocsp_nonce_new(void); +static int i2d_ocsp_nonce(void *a, unsigned char **pp); +static void *d2i_ocsp_nonce(void *a, const unsigned char **pp, long length); +static void ocsp_nonce_free(void *a); +static int i2r_ocsp_nonce(const X509V3_EXT_METHOD *method, void *nonce, + BIO *out, int indent); + +static int i2r_ocsp_nocheck(const X509V3_EXT_METHOD *method, + void *nocheck, BIO *out, int indent); +static void *s2i_ocsp_nocheck(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, const char *str); +static int i2r_ocsp_serviceloc(const X509V3_EXT_METHOD *method, void *in, + BIO *bp, int ind); + +const X509V3_EXT_METHOD v3_ocsp_crlid = { + NID_id_pkix_OCSP_CrlID, 0, ASN1_ITEM_ref(OCSP_CRLID), + 0, 0, 0, 0, + 0, 0, + 0, 0, + i2r_ocsp_crlid, 0, + NULL +}; + +const X509V3_EXT_METHOD v3_ocsp_acutoff = { + NID_id_pkix_OCSP_archiveCutoff, 0, ASN1_ITEM_ref(ASN1_GENERALIZEDTIME), + 0, 0, 0, 0, + 0, 0, + 0, 0, + i2r_ocsp_acutoff, 0, + NULL +}; + +const X509V3_EXT_METHOD v3_crl_invdate = { + NID_invalidity_date, 0, ASN1_ITEM_ref(ASN1_GENERALIZEDTIME), + 0, 0, 0, 0, + 0, 0, + 0, 0, + i2r_ocsp_acutoff, 0, + NULL +}; + +const X509V3_EXT_METHOD v3_crl_hold = { + NID_hold_instruction_code, 0, ASN1_ITEM_ref(ASN1_OBJECT), + 0, 0, 0, 0, + 0, 0, + 0, 0, + i2r_object, 0, + NULL +}; + +const X509V3_EXT_METHOD v3_ocsp_nonce = { + NID_id_pkix_OCSP_Nonce, 0, NULL, + ocsp_nonce_new, + ocsp_nonce_free, + d2i_ocsp_nonce, + i2d_ocsp_nonce, + 0, 0, + 0, 0, + i2r_ocsp_nonce, 0, + NULL +}; + +const X509V3_EXT_METHOD v3_ocsp_nocheck = { + NID_id_pkix_OCSP_noCheck, 0, ASN1_ITEM_ref(ASN1_NULL), + 0, 0, 0, 0, + 0, s2i_ocsp_nocheck, + 0, 0, + i2r_ocsp_nocheck, 0, + NULL +}; + +const X509V3_EXT_METHOD v3_ocsp_serviceloc = { + NID_id_pkix_OCSP_serviceLocator, 0, ASN1_ITEM_ref(OCSP_SERVICELOC), + 0, 0, 0, 0, + 0, 0, + 0, 0, + i2r_ocsp_serviceloc, 0, + NULL +}; + +static int i2r_ocsp_crlid(const X509V3_EXT_METHOD *method, void *in, BIO *bp, + int ind) +{ + OCSP_CRLID *a = in; + if (a->crlUrl) { + if (BIO_printf(bp, "%*scrlUrl: ", ind, "") <= 0) + goto err; + if (!ASN1_STRING_print(bp, (ASN1_STRING *)a->crlUrl)) + goto err; + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + } + if (a->crlNum) { + if (BIO_printf(bp, "%*scrlNum: ", ind, "") <= 0) + goto err; + if (i2a_ASN1_INTEGER(bp, a->crlNum) <= 0) + goto err; + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + } + if (a->crlTime) { + if (BIO_printf(bp, "%*scrlTime: ", ind, "") <= 0) + goto err; + if (!ASN1_GENERALIZEDTIME_print(bp, a->crlTime)) + goto err; + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + } + return 1; + err: + return 0; +} + +static int i2r_ocsp_acutoff(const X509V3_EXT_METHOD *method, void *cutoff, + BIO *bp, int ind) +{ + if (BIO_printf(bp, "%*s", ind, "") <= 0) + return 0; + if (!ASN1_GENERALIZEDTIME_print(bp, cutoff)) + return 0; + return 1; +} + +static int i2r_object(const X509V3_EXT_METHOD *method, void *oid, BIO *bp, + int ind) +{ + if (BIO_printf(bp, "%*s", ind, "") <= 0) + return 0; + if (i2a_ASN1_OBJECT(bp, oid) <= 0) + return 0; + return 1; +} + +/* + * OCSP nonce. This is needs special treatment because it doesn't have an + * ASN1 encoding at all: it just contains arbitrary data. + */ + +static void *ocsp_nonce_new(void) +{ + return ASN1_OCTET_STRING_new(); +} + +static int i2d_ocsp_nonce(void *a, unsigned char **pp) +{ + ASN1_OCTET_STRING *os = a; + if (pp) { + memcpy(*pp, os->data, os->length); + *pp += os->length; + } + return os->length; +} + +static void *d2i_ocsp_nonce(void *a, const unsigned char **pp, long length) +{ + ASN1_OCTET_STRING *os, **pos; + pos = a; + if (pos == NULL || *pos == NULL) { + os = ASN1_OCTET_STRING_new(); + if (os == NULL) + goto err; + } else { + os = *pos; + } + if (!ASN1_OCTET_STRING_set(os, *pp, length)) + goto err; + + *pp += length; + + if (pos) + *pos = os; + return os; + + err: + if ((pos == NULL) || (*pos != os)) + ASN1_OCTET_STRING_free(os); + OCSPerr(OCSP_F_D2I_OCSP_NONCE, ERR_R_MALLOC_FAILURE); + return NULL; +} + +static void ocsp_nonce_free(void *a) +{ + ASN1_OCTET_STRING_free(a); +} + +static int i2r_ocsp_nonce(const X509V3_EXT_METHOD *method, void *nonce, + BIO *out, int indent) +{ + if (BIO_printf(out, "%*s", indent, "") <= 0) + return 0; + if (i2a_ASN1_STRING(out, nonce, V_ASN1_OCTET_STRING) <= 0) + return 0; + return 1; +} + +/* Nocheck is just a single NULL. Don't print anything and always set it */ + +static int i2r_ocsp_nocheck(const X509V3_EXT_METHOD *method, void *nocheck, + BIO *out, int indent) +{ + return 1; +} + +static void *s2i_ocsp_nocheck(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, const char *str) +{ + return ASN1_NULL_new(); +} + +static int i2r_ocsp_serviceloc(const X509V3_EXT_METHOD *method, void *in, + BIO *bp, int ind) +{ + int i; + OCSP_SERVICELOC *a = in; + ACCESS_DESCRIPTION *ad; + + if (BIO_printf(bp, "%*sIssuer: ", ind, "") <= 0) + goto err; + if (X509_NAME_print_ex(bp, a->issuer, 0, XN_FLAG_ONELINE) <= 0) + goto err; + for (i = 0; i < sk_ACCESS_DESCRIPTION_num(a->locator); i++) { + ad = sk_ACCESS_DESCRIPTION_value(a->locator, i); + if (BIO_printf(bp, "\n%*s", (2 * ind), "") <= 0) + goto err; + if (i2a_ASN1_OBJECT(bp, ad->method) <= 0) + goto err; + if (BIO_puts(bp, " - ") <= 0) + goto err; + if (GENERAL_NAME_print(bp, ad->location) <= 0) + goto err; + } + return 1; + err: + return 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pariscid.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/pariscid.pl new file mode 100644 index 000000000..5a231c49f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pariscid.pl @@ -0,0 +1,276 @@ +#! /usr/bin/env perl +# Copyright 2009-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +$flavour = shift; +$output = shift; +open STDOUT,">$output"; + +if ($flavour =~ /64/) { + $LEVEL ="2.0W"; + $SIZE_T =8; + $ST ="std"; +} else { + $LEVEL ="1.1"; + $SIZE_T =4; + $ST ="stw"; +} + +$rp="%r2"; +$sp="%r30"; +$rv="%r28"; + +$code=<<___; + .LEVEL $LEVEL + .SPACE \$TEXT\$ + .SUBSPA \$CODE\$,QUAD=0,ALIGN=8,ACCESS=0x2C,CODE_ONLY + + .EXPORT OPENSSL_cpuid_setup,ENTRY + .ALIGN 8 +OPENSSL_cpuid_setup + .PROC + .CALLINFO NO_CALLS + .ENTRY + bv ($rp) + .EXIT + nop + .PROCEND + + .EXPORT OPENSSL_rdtsc,ENTRY + .ALIGN 8 +OPENSSL_rdtsc + .PROC + .CALLINFO NO_CALLS + .ENTRY + mfctl %cr16,$rv + bv ($rp) + .EXIT + nop + .PROCEND + + .EXPORT OPENSSL_wipe_cpu,ENTRY + .ALIGN 8 +OPENSSL_wipe_cpu + .PROC + .CALLINFO NO_CALLS + .ENTRY + xor %r0,%r0,%r1 + fcpy,dbl %fr0,%fr4 + xor %r0,%r0,%r19 + fcpy,dbl %fr0,%fr5 + xor %r0,%r0,%r20 + fcpy,dbl %fr0,%fr6 + xor %r0,%r0,%r21 + fcpy,dbl %fr0,%fr7 + xor %r0,%r0,%r22 + fcpy,dbl %fr0,%fr8 + xor %r0,%r0,%r23 + fcpy,dbl %fr0,%fr9 + xor %r0,%r0,%r24 + fcpy,dbl %fr0,%fr10 + xor %r0,%r0,%r25 + fcpy,dbl %fr0,%fr11 + xor %r0,%r0,%r26 + fcpy,dbl %fr0,%fr22 + xor %r0,%r0,%r29 + fcpy,dbl %fr0,%fr23 + xor %r0,%r0,%r31 + fcpy,dbl %fr0,%fr24 + fcpy,dbl %fr0,%fr25 + fcpy,dbl %fr0,%fr26 + fcpy,dbl %fr0,%fr27 + fcpy,dbl %fr0,%fr28 + fcpy,dbl %fr0,%fr29 + fcpy,dbl %fr0,%fr30 + fcpy,dbl %fr0,%fr31 + bv ($rp) + .EXIT + ldo 0($sp),$rv + .PROCEND +___ +{ +my $inp="%r26"; +my $len="%r25"; + +$code.=<<___; + .EXPORT OPENSSL_cleanse,ENTRY,ARGW0=GR,ARGW1=GR + .ALIGN 8 +OPENSSL_cleanse + .PROC + .CALLINFO NO_CALLS + .ENTRY + cmpib,*= 0,$len,L\$done + nop + cmpib,*>>= 15,$len,L\$ittle + ldi $SIZE_T-1,%r1 + +L\$align + and,*<> $inp,%r1,%r28 + b,n L\$aligned + stb %r0,0($inp) + ldo -1($len),$len + b L\$align + ldo 1($inp),$inp + +L\$aligned + andcm $len,%r1,%r28 +L\$ot + $ST %r0,0($inp) + addib,*<> -$SIZE_T,%r28,L\$ot + ldo $SIZE_T($inp),$inp + + and,*<> $len,%r1,$len + b,n L\$done +L\$ittle + stb %r0,0($inp) + addib,*<> -1,$len,L\$ittle + ldo 1($inp),$inp +L\$done + bv ($rp) + .EXIT + nop + .PROCEND +___ +} +{ +my ($in1,$in2,$len)=("%r26","%r25","%r24"); + +$code.=<<___; + .EXPORT CRYPTO_memcmp,ENTRY,ARGW0=GR,ARGW1=GR,ARGW1=GR + .ALIGN 8 +CRYPTO_memcmp + .PROC + .CALLINFO NO_CALLS + .ENTRY + cmpib,*= 0,$len,L\$no_data + xor $rv,$rv,$rv + +L\$oop_cmp + ldb 0($in1),%r19 + ldb 0($in2),%r20 + ldo 1($in1),$in1 + ldo 1($in2),$in2 + xor %r19,%r20,%r29 + addib,*<> -1,$len,L\$oop_cmp + or %r29,$rv,$rv + + sub %r0,$rv,%r29 + extru %r29,0,1,$rv +L\$no_data + bv ($rp) + .EXIT + nop + .PROCEND +___ +} +{ +my ($out,$cnt,$max)=("%r26","%r25","%r24"); +my ($tick,$lasttick)=("%r23","%r22"); +my ($diff,$lastdiff)=("%r21","%r20"); + +$code.=<<___; + .EXPORT OPENSSL_instrument_bus,ENTRY,ARGW0=GR,ARGW1=GR + .ALIGN 8 +OPENSSL_instrument_bus + .PROC + .CALLINFO NO_CALLS + .ENTRY + copy $cnt,$rv + mfctl %cr16,$tick + copy $tick,$lasttick + ldi 0,$diff + + fdc 0($out) + ldw 0($out),$tick + add $diff,$tick,$tick + stw $tick,0($out) +L\$oop + mfctl %cr16,$tick + sub $tick,$lasttick,$diff + copy $tick,$lasttick + + fdc 0($out) + ldw 0($out),$tick + add $diff,$tick,$tick + stw $tick,0($out) + + addib,<> -1,$cnt,L\$oop + addi 4,$out,$out + + bv ($rp) + .EXIT + sub $rv,$cnt,$rv + .PROCEND + + .EXPORT OPENSSL_instrument_bus2,ENTRY,ARGW0=GR,ARGW1=GR + .ALIGN 8 +OPENSSL_instrument_bus2 + .PROC + .CALLINFO NO_CALLS + .ENTRY + copy $cnt,$rv + sub %r0,$cnt,$cnt + + mfctl %cr16,$tick + copy $tick,$lasttick + ldi 0,$diff + + fdc 0($out) + ldw 0($out),$tick + add $diff,$tick,$tick + stw $tick,0($out) + + mfctl %cr16,$tick + sub $tick,$lasttick,$diff + copy $tick,$lasttick +L\$oop2 + copy $diff,$lastdiff + fdc 0($out) + ldw 0($out),$tick + add $diff,$tick,$tick + stw $tick,0($out) + + addib,= -1,$max,L\$done2 + nop + + mfctl %cr16,$tick + sub $tick,$lasttick,$diff + copy $tick,$lasttick + cmpclr,<> $lastdiff,$diff,$tick + ldi 1,$tick + + ldi 1,%r1 + xor %r1,$tick,$tick + addb,<> $tick,$cnt,L\$oop2 + shladd,l $tick,2,$out,$out +L\$done2 + bv ($rp) + .EXIT + add $rv,$cnt,$rv + .PROCEND +___ +} + +if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler/) { + $gnuas = 1; +} + +foreach(split("\n",$code)) { + + s/(\.LEVEL\s+2\.0)W/$1w/ if ($gnuas && $SIZE_T==8); + s/\.SPACE\s+\$TEXT\$/.text/ if ($gnuas && $SIZE_T==8); + s/\.SUBSPA.*// if ($gnuas && $SIZE_T==8); + s/cmpib,\*/comib,/ if ($SIZE_T==4); + s/,\*/,/ if ($SIZE_T==4); + s/\bbv\b/bve/ if ($SIZE_T==8); + + print $_,"\n"; +} +close STDOUT; + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pem/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/pem/build.info new file mode 100644 index 000000000..357b32833 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pem/build.info @@ -0,0 +1,4 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + pem_sign.c pem_info.c pem_lib.c pem_all.c pem_err.c \ + pem_x509.c pem_xaux.c pem_oth.c pem_pk8.c pem_pkey.c pvkfmt.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_all.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_all.c new file mode 100644 index 000000000..0e7181311 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_all.c @@ -0,0 +1,181 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef OPENSSL_NO_RSA +static RSA *pkey_get_rsa(EVP_PKEY *key, RSA **rsa); +#endif +#ifndef OPENSSL_NO_DSA +static DSA *pkey_get_dsa(EVP_PKEY *key, DSA **dsa); +#endif + +#ifndef OPENSSL_NO_EC +static EC_KEY *pkey_get_eckey(EVP_PKEY *key, EC_KEY **eckey); +#endif + +IMPLEMENT_PEM_rw(X509_REQ, X509_REQ, PEM_STRING_X509_REQ, X509_REQ) + +IMPLEMENT_PEM_write(X509_REQ_NEW, X509_REQ, PEM_STRING_X509_REQ_OLD, X509_REQ) +IMPLEMENT_PEM_rw(X509_CRL, X509_CRL, PEM_STRING_X509_CRL, X509_CRL) +IMPLEMENT_PEM_rw(PKCS7, PKCS7, PEM_STRING_PKCS7, PKCS7) + +IMPLEMENT_PEM_rw(NETSCAPE_CERT_SEQUENCE, NETSCAPE_CERT_SEQUENCE, + PEM_STRING_X509, NETSCAPE_CERT_SEQUENCE) +#ifndef OPENSSL_NO_RSA +/* + * We treat RSA or DSA private keys as a special case. For private keys we + * read in an EVP_PKEY structure with PEM_read_bio_PrivateKey() and extract + * the relevant private key: this means can handle "traditional" and PKCS#8 + * formats transparently. + */ +static RSA *pkey_get_rsa(EVP_PKEY *key, RSA **rsa) +{ + RSA *rtmp; + if (!key) + return NULL; + rtmp = EVP_PKEY_get1_RSA(key); + EVP_PKEY_free(key); + if (!rtmp) + return NULL; + if (rsa) { + RSA_free(*rsa); + *rsa = rtmp; + } + return rtmp; +} + +RSA *PEM_read_bio_RSAPrivateKey(BIO *bp, RSA **rsa, pem_password_cb *cb, + void *u) +{ + EVP_PKEY *pktmp; + pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u); + return pkey_get_rsa(pktmp, rsa); +} + +# ifndef OPENSSL_NO_STDIO + +RSA *PEM_read_RSAPrivateKey(FILE *fp, RSA **rsa, pem_password_cb *cb, void *u) +{ + EVP_PKEY *pktmp; + pktmp = PEM_read_PrivateKey(fp, NULL, cb, u); + return pkey_get_rsa(pktmp, rsa); +} + +# endif + +IMPLEMENT_PEM_write_cb_const(RSAPrivateKey, RSA, PEM_STRING_RSA, + RSAPrivateKey) + + +IMPLEMENT_PEM_rw_const(RSAPublicKey, RSA, PEM_STRING_RSA_PUBLIC, + RSAPublicKey) IMPLEMENT_PEM_rw(RSA_PUBKEY, RSA, + PEM_STRING_PUBLIC, + RSA_PUBKEY) +#endif +#ifndef OPENSSL_NO_DSA +static DSA *pkey_get_dsa(EVP_PKEY *key, DSA **dsa) +{ + DSA *dtmp; + if (!key) + return NULL; + dtmp = EVP_PKEY_get1_DSA(key); + EVP_PKEY_free(key); + if (!dtmp) + return NULL; + if (dsa) { + DSA_free(*dsa); + *dsa = dtmp; + } + return dtmp; +} + +DSA *PEM_read_bio_DSAPrivateKey(BIO *bp, DSA **dsa, pem_password_cb *cb, + void *u) +{ + EVP_PKEY *pktmp; + pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u); + return pkey_get_dsa(pktmp, dsa); /* will free pktmp */ +} + +IMPLEMENT_PEM_write_cb_const(DSAPrivateKey, DSA, PEM_STRING_DSA, + DSAPrivateKey) + IMPLEMENT_PEM_rw(DSA_PUBKEY, DSA, PEM_STRING_PUBLIC, DSA_PUBKEY) +# ifndef OPENSSL_NO_STDIO +DSA *PEM_read_DSAPrivateKey(FILE *fp, DSA **dsa, pem_password_cb *cb, void *u) +{ + EVP_PKEY *pktmp; + pktmp = PEM_read_PrivateKey(fp, NULL, cb, u); + return pkey_get_dsa(pktmp, dsa); /* will free pktmp */ +} + +# endif + +IMPLEMENT_PEM_rw_const(DSAparams, DSA, PEM_STRING_DSAPARAMS, DSAparams) +#endif +#ifndef OPENSSL_NO_EC +static EC_KEY *pkey_get_eckey(EVP_PKEY *key, EC_KEY **eckey) +{ + EC_KEY *dtmp; + if (!key) + return NULL; + dtmp = EVP_PKEY_get1_EC_KEY(key); + EVP_PKEY_free(key); + if (!dtmp) + return NULL; + if (eckey) { + EC_KEY_free(*eckey); + *eckey = dtmp; + } + return dtmp; +} + +EC_KEY *PEM_read_bio_ECPrivateKey(BIO *bp, EC_KEY **key, pem_password_cb *cb, + void *u) +{ + EVP_PKEY *pktmp; + pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u); + return pkey_get_eckey(pktmp, key); /* will free pktmp */ +} + +IMPLEMENT_PEM_rw_const(ECPKParameters, EC_GROUP, PEM_STRING_ECPARAMETERS, + ECPKParameters) + + +IMPLEMENT_PEM_write_cb(ECPrivateKey, EC_KEY, PEM_STRING_ECPRIVATEKEY, + ECPrivateKey) +IMPLEMENT_PEM_rw(EC_PUBKEY, EC_KEY, PEM_STRING_PUBLIC, EC_PUBKEY) +# ifndef OPENSSL_NO_STDIO +EC_KEY *PEM_read_ECPrivateKey(FILE *fp, EC_KEY **eckey, pem_password_cb *cb, + void *u) +{ + EVP_PKEY *pktmp; + pktmp = PEM_read_PrivateKey(fp, NULL, cb, u); + return pkey_get_eckey(pktmp, eckey); /* will free pktmp */ +} + +# endif + +#endif + +#ifndef OPENSSL_NO_DH + +IMPLEMENT_PEM_write_const(DHparams, DH, PEM_STRING_DHPARAMS, DHparams) + IMPLEMENT_PEM_write_const(DHxparams, DH, PEM_STRING_DHXPARAMS, DHxparams) +#endif +IMPLEMENT_PEM_rw(PUBKEY, EVP_PKEY, PEM_STRING_PUBLIC, PUBKEY) diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_err.c new file mode 100644 index 000000000..f642030aa --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_err.c @@ -0,0 +1,126 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA PEM_str_functs[] = { + {ERR_PACK(ERR_LIB_PEM, PEM_F_B2I_DSS, 0), "b2i_dss"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_B2I_PVK_BIO, 0), "b2i_PVK_bio"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_B2I_RSA, 0), "b2i_rsa"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_CHECK_BITLEN_DSA, 0), "check_bitlen_dsa"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_CHECK_BITLEN_RSA, 0), "check_bitlen_rsa"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_D2I_PKCS8PRIVATEKEY_BIO, 0), + "d2i_PKCS8PrivateKey_bio"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_D2I_PKCS8PRIVATEKEY_FP, 0), + "d2i_PKCS8PrivateKey_fp"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_DO_B2I, 0), "do_b2i"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_DO_B2I_BIO, 0), "do_b2i_bio"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_DO_BLOB_HEADER, 0), "do_blob_header"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_DO_I2B, 0), "do_i2b"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_DO_PK8PKEY, 0), "do_pk8pkey"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_DO_PK8PKEY_FP, 0), "do_pk8pkey_fp"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_DO_PVK_BODY, 0), "do_PVK_body"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_DO_PVK_HEADER, 0), "do_PVK_header"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_GET_HEADER_AND_DATA, 0), + "get_header_and_data"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_GET_NAME, 0), "get_name"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_I2B_PVK, 0), "i2b_PVK"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_I2B_PVK_BIO, 0), "i2b_PVK_bio"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_LOAD_IV, 0), "load_iv"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_ASN1_READ, 0), "PEM_ASN1_read"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_ASN1_READ_BIO, 0), "PEM_ASN1_read_bio"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_ASN1_WRITE, 0), "PEM_ASN1_write"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_ASN1_WRITE_BIO, 0), "PEM_ASN1_write_bio"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_DEF_CALLBACK, 0), "PEM_def_callback"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_DO_HEADER, 0), "PEM_do_header"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_GET_EVP_CIPHER_INFO, 0), + "PEM_get_EVP_CIPHER_INFO"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_READ, 0), "PEM_read"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_READ_BIO, 0), "PEM_read_bio"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_READ_BIO_DHPARAMS, 0), + "PEM_read_bio_DHparams"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_READ_BIO_EX, 0), "PEM_read_bio_ex"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_READ_BIO_PARAMETERS, 0), + "PEM_read_bio_Parameters"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_READ_BIO_PRIVATEKEY, 0), + "PEM_read_bio_PrivateKey"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_READ_DHPARAMS, 0), "PEM_read_DHparams"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_READ_PRIVATEKEY, 0), + "PEM_read_PrivateKey"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_SIGNFINAL, 0), "PEM_SignFinal"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_WRITE, 0), "PEM_write"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_WRITE_BIO, 0), "PEM_write_bio"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_WRITE_PRIVATEKEY, 0), + "PEM_write_PrivateKey"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_X509_INFO_READ, 0), "PEM_X509_INFO_read"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_X509_INFO_READ_BIO, 0), + "PEM_X509_INFO_read_bio"}, + {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_X509_INFO_WRITE_BIO, 0), + "PEM_X509_INFO_write_bio"}, + {0, NULL} +}; + +static const ERR_STRING_DATA PEM_str_reasons[] = { + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BAD_BASE64_DECODE), "bad base64 decode"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BAD_DECRYPT), "bad decrypt"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BAD_END_LINE), "bad end line"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BAD_IV_CHARS), "bad iv chars"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BAD_MAGIC_NUMBER), "bad magic number"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BAD_PASSWORD_READ), "bad password read"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BAD_VERSION_NUMBER), "bad version number"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BIO_WRITE_FAILURE), "bio write failure"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_CIPHER_IS_NULL), "cipher is null"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_ERROR_CONVERTING_PRIVATE_KEY), + "error converting private key"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_EXPECTING_PRIVATE_KEY_BLOB), + "expecting private key blob"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_EXPECTING_PUBLIC_KEY_BLOB), + "expecting public key blob"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_HEADER_TOO_LONG), "header too long"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_INCONSISTENT_HEADER), + "inconsistent header"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_KEYBLOB_HEADER_PARSE_ERROR), + "keyblob header parse error"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_KEYBLOB_TOO_SHORT), "keyblob too short"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_MISSING_DEK_IV), "missing dek iv"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_NOT_DEK_INFO), "not dek info"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_NOT_ENCRYPTED), "not encrypted"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_NOT_PROC_TYPE), "not proc type"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_NO_START_LINE), "no start line"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_PROBLEMS_GETTING_PASSWORD), + "problems getting password"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_PVK_DATA_TOO_SHORT), "pvk data too short"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_PVK_TOO_SHORT), "pvk too short"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_READ_KEY), "read key"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_SHORT_HEADER), "short header"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_UNEXPECTED_DEK_IV), "unexpected dek iv"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_UNSUPPORTED_CIPHER), "unsupported cipher"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_UNSUPPORTED_ENCRYPTION), + "unsupported encryption"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_UNSUPPORTED_KEY_COMPONENTS), + "unsupported key components"}, + {0, NULL} +}; + +#endif + +int ERR_load_PEM_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(PEM_str_functs[0].error) == NULL) { + ERR_load_strings_const(PEM_str_functs); + ERR_load_strings_const(PEM_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_info.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_info.c new file mode 100644 index 000000000..f90cb4465 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_info.c @@ -0,0 +1,337 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include +#include + +#ifndef OPENSSL_NO_STDIO +STACK_OF(X509_INFO) *PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk, + pem_password_cb *cb, void *u) +{ + BIO *b; + STACK_OF(X509_INFO) *ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + PEMerr(PEM_F_PEM_X509_INFO_READ, ERR_R_BUF_LIB); + return 0; + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = PEM_X509_INFO_read_bio(b, sk, cb, u); + BIO_free(b); + return ret; +} +#endif + +STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk, + pem_password_cb *cb, void *u) +{ + X509_INFO *xi = NULL; + char *name = NULL, *header = NULL; + void *pp; + unsigned char *data = NULL; + const unsigned char *p; + long len, error = 0; + int ok = 0; + STACK_OF(X509_INFO) *ret = NULL; + unsigned int i, raw, ptype; + d2i_of_void *d2i = 0; + + if (sk == NULL) { + if ((ret = sk_X509_INFO_new_null()) == NULL) { + PEMerr(PEM_F_PEM_X509_INFO_READ_BIO, ERR_R_MALLOC_FAILURE); + goto err; + } + } else + ret = sk; + + if ((xi = X509_INFO_new()) == NULL) + goto err; + for (;;) { + raw = 0; + ptype = 0; + i = PEM_read_bio(bp, &name, &header, &data, &len); + if (i == 0) { + error = ERR_GET_REASON(ERR_peek_last_error()); + if (error == PEM_R_NO_START_LINE) { + ERR_clear_error(); + break; + } + goto err; + } + start: + if ((strcmp(name, PEM_STRING_X509) == 0) || + (strcmp(name, PEM_STRING_X509_OLD) == 0)) { + d2i = (D2I_OF(void)) d2i_X509; + if (xi->x509 != NULL) { + if (!sk_X509_INFO_push(ret, xi)) + goto err; + if ((xi = X509_INFO_new()) == NULL) + goto err; + goto start; + } + pp = &(xi->x509); + } else if ((strcmp(name, PEM_STRING_X509_TRUSTED) == 0)) { + d2i = (D2I_OF(void)) d2i_X509_AUX; + if (xi->x509 != NULL) { + if (!sk_X509_INFO_push(ret, xi)) + goto err; + if ((xi = X509_INFO_new()) == NULL) + goto err; + goto start; + } + pp = &(xi->x509); + } else if (strcmp(name, PEM_STRING_X509_CRL) == 0) { + d2i = (D2I_OF(void)) d2i_X509_CRL; + if (xi->crl != NULL) { + if (!sk_X509_INFO_push(ret, xi)) + goto err; + if ((xi = X509_INFO_new()) == NULL) + goto err; + goto start; + } + pp = &(xi->crl); + } else +#ifndef OPENSSL_NO_RSA + if (strcmp(name, PEM_STRING_RSA) == 0) { + d2i = (D2I_OF(void)) d2i_RSAPrivateKey; + if (xi->x_pkey != NULL) { + if (!sk_X509_INFO_push(ret, xi)) + goto err; + if ((xi = X509_INFO_new()) == NULL) + goto err; + goto start; + } + + xi->enc_data = NULL; + xi->enc_len = 0; + + xi->x_pkey = X509_PKEY_new(); + if (xi->x_pkey == NULL) + goto err; + ptype = EVP_PKEY_RSA; + pp = &xi->x_pkey->dec_pkey; + if ((int)strlen(header) > 10) /* assume encrypted */ + raw = 1; + } else +#endif +#ifndef OPENSSL_NO_DSA + if (strcmp(name, PEM_STRING_DSA) == 0) { + d2i = (D2I_OF(void)) d2i_DSAPrivateKey; + if (xi->x_pkey != NULL) { + if (!sk_X509_INFO_push(ret, xi)) + goto err; + if ((xi = X509_INFO_new()) == NULL) + goto err; + goto start; + } + + xi->enc_data = NULL; + xi->enc_len = 0; + + xi->x_pkey = X509_PKEY_new(); + if (xi->x_pkey == NULL) + goto err; + ptype = EVP_PKEY_DSA; + pp = &xi->x_pkey->dec_pkey; + if ((int)strlen(header) > 10) /* assume encrypted */ + raw = 1; + } else +#endif +#ifndef OPENSSL_NO_EC + if (strcmp(name, PEM_STRING_ECPRIVATEKEY) == 0) { + d2i = (D2I_OF(void)) d2i_ECPrivateKey; + if (xi->x_pkey != NULL) { + if (!sk_X509_INFO_push(ret, xi)) + goto err; + if ((xi = X509_INFO_new()) == NULL) + goto err; + goto start; + } + + xi->enc_data = NULL; + xi->enc_len = 0; + + xi->x_pkey = X509_PKEY_new(); + if (xi->x_pkey == NULL) + goto err; + ptype = EVP_PKEY_EC; + pp = &xi->x_pkey->dec_pkey; + if ((int)strlen(header) > 10) /* assume encrypted */ + raw = 1; + } else +#endif + { + d2i = NULL; + pp = NULL; + } + + if (d2i != NULL) { + if (!raw) { + EVP_CIPHER_INFO cipher; + + if (!PEM_get_EVP_CIPHER_INFO(header, &cipher)) + goto err; + if (!PEM_do_header(&cipher, data, &len, cb, u)) + goto err; + p = data; + if (ptype) { + if (!d2i_PrivateKey(ptype, pp, &p, len)) { + PEMerr(PEM_F_PEM_X509_INFO_READ_BIO, ERR_R_ASN1_LIB); + goto err; + } + } else if (d2i(pp, &p, len) == NULL) { + PEMerr(PEM_F_PEM_X509_INFO_READ_BIO, ERR_R_ASN1_LIB); + goto err; + } + } else { /* encrypted RSA data */ + if (!PEM_get_EVP_CIPHER_INFO(header, &xi->enc_cipher)) + goto err; + xi->enc_data = (char *)data; + xi->enc_len = (int)len; + data = NULL; + } + } else { + /* unknown */ + } + OPENSSL_free(name); + name = NULL; + OPENSSL_free(header); + header = NULL; + OPENSSL_free(data); + data = NULL; + } + + /* + * if the last one hasn't been pushed yet and there is anything in it + * then add it to the stack ... + */ + if ((xi->x509 != NULL) || (xi->crl != NULL) || + (xi->x_pkey != NULL) || (xi->enc_data != NULL)) { + if (!sk_X509_INFO_push(ret, xi)) + goto err; + xi = NULL; + } + ok = 1; + err: + X509_INFO_free(xi); + if (!ok) { + for (i = 0; ((int)i) < sk_X509_INFO_num(ret); i++) { + xi = sk_X509_INFO_value(ret, i); + X509_INFO_free(xi); + } + if (ret != sk) + sk_X509_INFO_free(ret); + ret = NULL; + } + + OPENSSL_free(name); + OPENSSL_free(header); + OPENSSL_free(data); + return ret; +} + +/* A TJH addition */ +int PEM_X509_INFO_write_bio(BIO *bp, X509_INFO *xi, EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + int i, ret = 0; + unsigned char *data = NULL; + const char *objstr = NULL; + char buf[PEM_BUFSIZE]; + unsigned char *iv = NULL; + + if (enc != NULL) { + objstr = OBJ_nid2sn(EVP_CIPHER_nid(enc)); + if (objstr == NULL + /* + * Check "Proc-Type: 4,Encrypted\nDEK-Info: objstr,hex-iv\n" + * fits into buf + */ + || (strlen(objstr) + 23 + 2 * EVP_CIPHER_iv_length(enc) + 13) + > sizeof(buf)) { + PEMerr(PEM_F_PEM_X509_INFO_WRITE_BIO, PEM_R_UNSUPPORTED_CIPHER); + goto err; + } + } + + /* + * now for the fun part ... if we have a private key then we have to be + * able to handle a not-yet-decrypted key being written out correctly ... + * if it is decrypted or it is non-encrypted then we use the base code + */ + if (xi->x_pkey != NULL) { + if ((xi->enc_data != NULL) && (xi->enc_len > 0)) { + if (enc == NULL) { + PEMerr(PEM_F_PEM_X509_INFO_WRITE_BIO, PEM_R_CIPHER_IS_NULL); + goto err; + } + + /* copy from weirdo names into more normal things */ + iv = xi->enc_cipher.iv; + data = (unsigned char *)xi->enc_data; + i = xi->enc_len; + + /* + * we take the encryption data from the internal stuff rather + * than what the user has passed us ... as we have to match + * exactly for some strange reason + */ + objstr = OBJ_nid2sn(EVP_CIPHER_nid(xi->enc_cipher.cipher)); + if (objstr == NULL) { + PEMerr(PEM_F_PEM_X509_INFO_WRITE_BIO, + PEM_R_UNSUPPORTED_CIPHER); + goto err; + } + + /* Create the right magic header stuff */ + buf[0] = '\0'; + PEM_proc_type(buf, PEM_TYPE_ENCRYPTED); + PEM_dek_info(buf, objstr, EVP_CIPHER_iv_length(enc), + (char *)iv); + + /* use the normal code to write things out */ + i = PEM_write_bio(bp, PEM_STRING_RSA, buf, data, i); + if (i <= 0) + goto err; + } else { + /* Add DSA/DH */ +#ifndef OPENSSL_NO_RSA + /* normal optionally encrypted stuff */ + if (PEM_write_bio_RSAPrivateKey(bp, + EVP_PKEY_get0_RSA(xi->x_pkey->dec_pkey), + enc, kstr, klen, cb, u) <= 0) + goto err; +#endif + } + } + + /* if we have a certificate then write it out now */ + if ((xi->x509 != NULL) && (PEM_write_bio_X509(bp, xi->x509) <= 0)) + goto err; + + /* + * we are ignoring anything else that is loaded into the X509_INFO + * structure for the moment ... as I don't need it so I'm not coding it + * here and Eric can do it when this makes it into the base library --tjh + */ + + ret = 1; + + err: + OPENSSL_cleanse(buf, PEM_BUFSIZE); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_lib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_lib.c new file mode 100644 index 000000000..4bb86463f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_lib.c @@ -0,0 +1,988 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/ctype.h" +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include +#include +#include "internal/asn1_int.h" +#include +#include + +#define MIN_LENGTH 4 + +static int load_iv(char **fromp, unsigned char *to, int num); +static int check_pem(const char *nm, const char *name); +int pem_check_suffix(const char *pem_str, const char *suffix); + +int PEM_def_callback(char *buf, int num, int rwflag, void *userdata) +{ + int i, min_len; + const char *prompt; + + /* We assume that the user passes a default password as userdata */ + if (userdata) { + i = strlen(userdata); + i = (i > num) ? num : i; + memcpy(buf, userdata, i); + return i; + } + + prompt = EVP_get_pw_prompt(); + if (prompt == NULL) + prompt = "Enter PEM pass phrase:"; + + /* + * rwflag == 0 means decryption + * rwflag == 1 means encryption + * + * We assume that for encryption, we want a minimum length, while for + * decryption, we cannot know any minimum length, so we assume zero. + */ + min_len = rwflag ? MIN_LENGTH : 0; + + i = EVP_read_pw_string_min(buf, min_len, num, prompt, rwflag); + if (i != 0) { + PEMerr(PEM_F_PEM_DEF_CALLBACK, PEM_R_PROBLEMS_GETTING_PASSWORD); + memset(buf, 0, (unsigned int)num); + return -1; + } + return strlen(buf); +} + +void PEM_proc_type(char *buf, int type) +{ + const char *str; + char *p = buf + strlen(buf); + + if (type == PEM_TYPE_ENCRYPTED) + str = "ENCRYPTED"; + else if (type == PEM_TYPE_MIC_CLEAR) + str = "MIC-CLEAR"; + else if (type == PEM_TYPE_MIC_ONLY) + str = "MIC-ONLY"; + else + str = "BAD-TYPE"; + + BIO_snprintf(p, PEM_BUFSIZE - (size_t)(p - buf), "Proc-Type: 4,%s\n", str); +} + +void PEM_dek_info(char *buf, const char *type, int len, char *str) +{ + long i; + char *p = buf + strlen(buf); + int j = PEM_BUFSIZE - (size_t)(p - buf), n; + + n = BIO_snprintf(p, j, "DEK-Info: %s,", type); + if (n > 0) { + j -= n; + p += n; + for (i = 0; i < len; i++) { + n = BIO_snprintf(p, j, "%02X", 0xff & str[i]); + if (n <= 0) + return; + j -= n; + p += n; + } + if (j > 1) + strcpy(p, "\n"); + } +} + +#ifndef OPENSSL_NO_STDIO +void *PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, void **x, + pem_password_cb *cb, void *u) +{ + BIO *b; + void *ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + PEMerr(PEM_F_PEM_ASN1_READ, ERR_R_BUF_LIB); + return 0; + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = PEM_ASN1_read_bio(d2i, name, b, x, cb, u); + BIO_free(b); + return ret; +} +#endif + +static int check_pem(const char *nm, const char *name) +{ + /* Normal matching nm and name */ + if (strcmp(nm, name) == 0) + return 1; + + /* Make PEM_STRING_EVP_PKEY match any private key */ + + if (strcmp(name, PEM_STRING_EVP_PKEY) == 0) { + int slen; + const EVP_PKEY_ASN1_METHOD *ameth; + if (strcmp(nm, PEM_STRING_PKCS8) == 0) + return 1; + if (strcmp(nm, PEM_STRING_PKCS8INF) == 0) + return 1; + slen = pem_check_suffix(nm, "PRIVATE KEY"); + if (slen > 0) { + /* + * NB: ENGINE implementations won't contain a deprecated old + * private key decode function so don't look for them. + */ + ameth = EVP_PKEY_asn1_find_str(NULL, nm, slen); + if (ameth && ameth->old_priv_decode) + return 1; + } + return 0; + } + + if (strcmp(name, PEM_STRING_PARAMETERS) == 0) { + int slen; + const EVP_PKEY_ASN1_METHOD *ameth; + slen = pem_check_suffix(nm, "PARAMETERS"); + if (slen > 0) { + ENGINE *e; + ameth = EVP_PKEY_asn1_find_str(&e, nm, slen); + if (ameth) { + int r; + if (ameth->param_decode) + r = 1; + else + r = 0; +#ifndef OPENSSL_NO_ENGINE + ENGINE_finish(e); +#endif + return r; + } + } + return 0; + } + /* If reading DH parameters handle X9.42 DH format too */ + if (strcmp(nm, PEM_STRING_DHXPARAMS) == 0 + && strcmp(name, PEM_STRING_DHPARAMS) == 0) + return 1; + + /* Permit older strings */ + + if (strcmp(nm, PEM_STRING_X509_OLD) == 0 + && strcmp(name, PEM_STRING_X509) == 0) + return 1; + + if (strcmp(nm, PEM_STRING_X509_REQ_OLD) == 0 + && strcmp(name, PEM_STRING_X509_REQ) == 0) + return 1; + + /* Allow normal certs to be read as trusted certs */ + if (strcmp(nm, PEM_STRING_X509) == 0 + && strcmp(name, PEM_STRING_X509_TRUSTED) == 0) + return 1; + + if (strcmp(nm, PEM_STRING_X509_OLD) == 0 + && strcmp(name, PEM_STRING_X509_TRUSTED) == 0) + return 1; + + /* Some CAs use PKCS#7 with CERTIFICATE headers */ + if (strcmp(nm, PEM_STRING_X509) == 0 + && strcmp(name, PEM_STRING_PKCS7) == 0) + return 1; + + if (strcmp(nm, PEM_STRING_PKCS7_SIGNED) == 0 + && strcmp(name, PEM_STRING_PKCS7) == 0) + return 1; + +#ifndef OPENSSL_NO_CMS + if (strcmp(nm, PEM_STRING_X509) == 0 + && strcmp(name, PEM_STRING_CMS) == 0) + return 1; + /* Allow CMS to be read from PKCS#7 headers */ + if (strcmp(nm, PEM_STRING_PKCS7) == 0 + && strcmp(name, PEM_STRING_CMS) == 0) + return 1; +#endif + + return 0; +} + +static void pem_free(void *p, unsigned int flags, size_t num) +{ + if (flags & PEM_FLAG_SECURE) + OPENSSL_secure_clear_free(p, num); + else + OPENSSL_free(p); +} + +static void *pem_malloc(int num, unsigned int flags) +{ + return (flags & PEM_FLAG_SECURE) ? OPENSSL_secure_malloc(num) + : OPENSSL_malloc(num); +} + +static int pem_bytes_read_bio_flags(unsigned char **pdata, long *plen, + char **pnm, const char *name, BIO *bp, + pem_password_cb *cb, void *u, + unsigned int flags) +{ + EVP_CIPHER_INFO cipher; + char *nm = NULL, *header = NULL; + unsigned char *data = NULL; + long len = 0; + int ret = 0; + + do { + pem_free(nm, flags, 0); + pem_free(header, flags, 0); + pem_free(data, flags, len); + if (!PEM_read_bio_ex(bp, &nm, &header, &data, &len, flags)) { + if (ERR_GET_REASON(ERR_peek_error()) == PEM_R_NO_START_LINE) + ERR_add_error_data(2, "Expecting: ", name); + return 0; + } + } while (!check_pem(nm, name)); + if (!PEM_get_EVP_CIPHER_INFO(header, &cipher)) + goto err; + if (!PEM_do_header(&cipher, data, &len, cb, u)) + goto err; + + *pdata = data; + *plen = len; + + if (pnm != NULL) + *pnm = nm; + + ret = 1; + + err: + if (!ret || pnm == NULL) + pem_free(nm, flags, 0); + pem_free(header, flags, 0); + if (!ret) + pem_free(data, flags, len); + return ret; +} + +int PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm, + const char *name, BIO *bp, pem_password_cb *cb, + void *u) { + return pem_bytes_read_bio_flags(pdata, plen, pnm, name, bp, cb, u, + PEM_FLAG_EAY_COMPATIBLE); +} + +int PEM_bytes_read_bio_secmem(unsigned char **pdata, long *plen, char **pnm, + const char *name, BIO *bp, pem_password_cb *cb, + void *u) { + return pem_bytes_read_bio_flags(pdata, plen, pnm, name, bp, cb, u, + PEM_FLAG_SECURE | PEM_FLAG_EAY_COMPATIBLE); +} + +#ifndef OPENSSL_NO_STDIO +int PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp, + void *x, const EVP_CIPHER *enc, unsigned char *kstr, + int klen, pem_password_cb *callback, void *u) +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + PEMerr(PEM_F_PEM_ASN1_WRITE, ERR_R_BUF_LIB); + return 0; + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = PEM_ASN1_write_bio(i2d, name, b, x, enc, kstr, klen, callback, u); + BIO_free(b); + return ret; +} +#endif + +int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, + void *x, const EVP_CIPHER *enc, unsigned char *kstr, + int klen, pem_password_cb *callback, void *u) +{ + EVP_CIPHER_CTX *ctx = NULL; + int dsize = 0, i = 0, j = 0, ret = 0; + unsigned char *p, *data = NULL; + const char *objstr = NULL; + char buf[PEM_BUFSIZE]; + unsigned char key[EVP_MAX_KEY_LENGTH]; + unsigned char iv[EVP_MAX_IV_LENGTH]; + + if (enc != NULL) { + objstr = OBJ_nid2sn(EVP_CIPHER_nid(enc)); + if (objstr == NULL || EVP_CIPHER_iv_length(enc) == 0 + || EVP_CIPHER_iv_length(enc) > (int)sizeof(iv) + /* + * Check "Proc-Type: 4,Encrypted\nDEK-Info: objstr,hex-iv\n" + * fits into buf + */ + || (strlen(objstr) + 23 + 2 * EVP_CIPHER_iv_length(enc) + 13) + > sizeof(buf)) { + PEMerr(PEM_F_PEM_ASN1_WRITE_BIO, PEM_R_UNSUPPORTED_CIPHER); + goto err; + } + } + + if ((dsize = i2d(x, NULL)) < 0) { + PEMerr(PEM_F_PEM_ASN1_WRITE_BIO, ERR_R_ASN1_LIB); + dsize = 0; + goto err; + } + /* dsize + 8 bytes are needed */ + /* actually it needs the cipher block size extra... */ + data = OPENSSL_malloc((unsigned int)dsize + 20); + if (data == NULL) { + PEMerr(PEM_F_PEM_ASN1_WRITE_BIO, ERR_R_MALLOC_FAILURE); + goto err; + } + p = data; + i = i2d(x, &p); + + if (enc != NULL) { + if (kstr == NULL) { + if (callback == NULL) + klen = PEM_def_callback(buf, PEM_BUFSIZE, 1, u); + else + klen = (*callback) (buf, PEM_BUFSIZE, 1, u); + if (klen <= 0) { + PEMerr(PEM_F_PEM_ASN1_WRITE_BIO, PEM_R_READ_KEY); + goto err; + } +#ifdef CHARSET_EBCDIC + /* Convert the pass phrase from EBCDIC */ + ebcdic2ascii(buf, buf, klen); +#endif + kstr = (unsigned char *)buf; + } + if (RAND_bytes(iv, EVP_CIPHER_iv_length(enc)) <= 0) /* Generate a salt */ + goto err; + /* + * The 'iv' is used as the iv and as a salt. It is NOT taken from + * the BytesToKey function + */ + if (!EVP_BytesToKey(enc, EVP_md5(), iv, kstr, klen, 1, key, NULL)) + goto err; + + if (kstr == (unsigned char *)buf) + OPENSSL_cleanse(buf, PEM_BUFSIZE); + + buf[0] = '\0'; + PEM_proc_type(buf, PEM_TYPE_ENCRYPTED); + PEM_dek_info(buf, objstr, EVP_CIPHER_iv_length(enc), (char *)iv); + /* k=strlen(buf); */ + + ret = 1; + if ((ctx = EVP_CIPHER_CTX_new()) == NULL + || !EVP_EncryptInit_ex(ctx, enc, NULL, key, iv) + || !EVP_EncryptUpdate(ctx, data, &j, data, i) + || !EVP_EncryptFinal_ex(ctx, &(data[j]), &i)) + ret = 0; + if (ret == 0) + goto err; + i += j; + } else { + ret = 1; + buf[0] = '\0'; + } + i = PEM_write_bio(bp, name, buf, data, i); + if (i <= 0) + ret = 0; + err: + OPENSSL_cleanse(key, sizeof(key)); + OPENSSL_cleanse(iv, sizeof(iv)); + EVP_CIPHER_CTX_free(ctx); + OPENSSL_cleanse(buf, PEM_BUFSIZE); + OPENSSL_clear_free(data, (unsigned int)dsize); + return ret; +} + +int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *plen, + pem_password_cb *callback, void *u) +{ + int ok; + int keylen; + long len = *plen; + int ilen = (int) len; /* EVP_DecryptUpdate etc. take int lengths */ + EVP_CIPHER_CTX *ctx; + unsigned char key[EVP_MAX_KEY_LENGTH]; + char buf[PEM_BUFSIZE]; + +#if LONG_MAX > INT_MAX + /* Check that we did not truncate the length */ + if (len > INT_MAX) { + PEMerr(PEM_F_PEM_DO_HEADER, PEM_R_HEADER_TOO_LONG); + return 0; + } +#endif + + if (cipher->cipher == NULL) + return 1; + if (callback == NULL) + keylen = PEM_def_callback(buf, PEM_BUFSIZE, 0, u); + else + keylen = callback(buf, PEM_BUFSIZE, 0, u); + if (keylen < 0) { + PEMerr(PEM_F_PEM_DO_HEADER, PEM_R_BAD_PASSWORD_READ); + return 0; + } +#ifdef CHARSET_EBCDIC + /* Convert the pass phrase from EBCDIC */ + ebcdic2ascii(buf, buf, keylen); +#endif + + if (!EVP_BytesToKey(cipher->cipher, EVP_md5(), &(cipher->iv[0]), + (unsigned char *)buf, keylen, 1, key, NULL)) + return 0; + + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) + return 0; + + ok = EVP_DecryptInit_ex(ctx, cipher->cipher, NULL, key, &(cipher->iv[0])); + if (ok) + ok = EVP_DecryptUpdate(ctx, data, &ilen, data, ilen); + if (ok) { + /* Squirrel away the length of data decrypted so far. */ + *plen = ilen; + ok = EVP_DecryptFinal_ex(ctx, &(data[ilen]), &ilen); + } + if (ok) + *plen += ilen; + else + PEMerr(PEM_F_PEM_DO_HEADER, PEM_R_BAD_DECRYPT); + + EVP_CIPHER_CTX_free(ctx); + OPENSSL_cleanse((char *)buf, sizeof(buf)); + OPENSSL_cleanse((char *)key, sizeof(key)); + return ok; +} + +/* + * This implements a very limited PEM header parser that does not support the + * full grammar of rfc1421. In particular, folded headers are not supported, + * nor is additional whitespace. + * + * A robust implementation would make use of a library that turns the headers + * into a BIO from which one folded line is read at a time, and is then split + * into a header label and content. We would then parse the content of the + * headers we care about. This is overkill for just this limited use-case, but + * presumably we also parse rfc822-style headers for S/MIME, so a common + * abstraction might well be more generally useful. + */ +int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher) +{ + static const char ProcType[] = "Proc-Type:"; + static const char ENCRYPTED[] = "ENCRYPTED"; + static const char DEKInfo[] = "DEK-Info:"; + const EVP_CIPHER *enc = NULL; + int ivlen; + char *dekinfostart, c; + + cipher->cipher = NULL; + memset(cipher->iv, 0, sizeof(cipher->iv)); + if ((header == NULL) || (*header == '\0') || (*header == '\n')) + return 1; + + if (strncmp(header, ProcType, sizeof(ProcType)-1) != 0) { + PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO, PEM_R_NOT_PROC_TYPE); + return 0; + } + header += sizeof(ProcType)-1; + header += strspn(header, " \t"); + + if (*header++ != '4' || *header++ != ',') + return 0; + header += strspn(header, " \t"); + + /* We expect "ENCRYPTED" followed by optional white-space + line break */ + if (strncmp(header, ENCRYPTED, sizeof(ENCRYPTED)-1) != 0 || + strspn(header+sizeof(ENCRYPTED)-1, " \t\r\n") == 0) { + PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO, PEM_R_NOT_ENCRYPTED); + return 0; + } + header += sizeof(ENCRYPTED)-1; + header += strspn(header, " \t\r"); + if (*header++ != '\n') { + PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO, PEM_R_SHORT_HEADER); + return 0; + } + + /*- + * https://tools.ietf.org/html/rfc1421#section-4.6.1.3 + * We expect "DEK-Info: algo[,hex-parameters]" + */ + if (strncmp(header, DEKInfo, sizeof(DEKInfo)-1) != 0) { + PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO, PEM_R_NOT_DEK_INFO); + return 0; + } + header += sizeof(DEKInfo)-1; + header += strspn(header, " \t"); + + /* + * DEK-INFO is a comma-separated combination of algorithm name and optional + * parameters. + */ + dekinfostart = header; + header += strcspn(header, " \t,"); + c = *header; + *header = '\0'; + cipher->cipher = enc = EVP_get_cipherbyname(dekinfostart); + *header = c; + header += strspn(header, " \t"); + + if (enc == NULL) { + PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO, PEM_R_UNSUPPORTED_ENCRYPTION); + return 0; + } + ivlen = EVP_CIPHER_iv_length(enc); + if (ivlen > 0 && *header++ != ',') { + PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO, PEM_R_MISSING_DEK_IV); + return 0; + } else if (ivlen == 0 && *header == ',') { + PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO, PEM_R_UNEXPECTED_DEK_IV); + return 0; + } + + if (!load_iv(&header, cipher->iv, EVP_CIPHER_iv_length(enc))) + return 0; + + return 1; +} + +static int load_iv(char **fromp, unsigned char *to, int num) +{ + int v, i; + char *from; + + from = *fromp; + for (i = 0; i < num; i++) + to[i] = 0; + num *= 2; + for (i = 0; i < num; i++) { + v = OPENSSL_hexchar2int(*from); + if (v < 0) { + PEMerr(PEM_F_LOAD_IV, PEM_R_BAD_IV_CHARS); + return 0; + } + from++; + to[i / 2] |= v << (long)((!(i & 1)) * 4); + } + + *fromp = from; + return 1; +} + +#ifndef OPENSSL_NO_STDIO +int PEM_write(FILE *fp, const char *name, const char *header, + const unsigned char *data, long len) +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + PEMerr(PEM_F_PEM_WRITE, ERR_R_BUF_LIB); + return 0; + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = PEM_write_bio(b, name, header, data, len); + BIO_free(b); + return ret; +} +#endif + +int PEM_write_bio(BIO *bp, const char *name, const char *header, + const unsigned char *data, long len) +{ + int nlen, n, i, j, outl; + unsigned char *buf = NULL; + EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new(); + int reason = ERR_R_BUF_LIB; + int retval = 0; + + if (ctx == NULL) { + reason = ERR_R_MALLOC_FAILURE; + goto err; + } + + EVP_EncodeInit(ctx); + nlen = strlen(name); + + if ((BIO_write(bp, "-----BEGIN ", 11) != 11) || + (BIO_write(bp, name, nlen) != nlen) || + (BIO_write(bp, "-----\n", 6) != 6)) + goto err; + + i = strlen(header); + if (i > 0) { + if ((BIO_write(bp, header, i) != i) || (BIO_write(bp, "\n", 1) != 1)) + goto err; + } + + buf = OPENSSL_malloc(PEM_BUFSIZE * 8); + if (buf == NULL) { + reason = ERR_R_MALLOC_FAILURE; + goto err; + } + + i = j = 0; + while (len > 0) { + n = (int)((len > (PEM_BUFSIZE * 5)) ? (PEM_BUFSIZE * 5) : len); + if (!EVP_EncodeUpdate(ctx, buf, &outl, &(data[j]), n)) + goto err; + if ((outl) && (BIO_write(bp, (char *)buf, outl) != outl)) + goto err; + i += outl; + len -= n; + j += n; + } + EVP_EncodeFinal(ctx, buf, &outl); + if ((outl > 0) && (BIO_write(bp, (char *)buf, outl) != outl)) + goto err; + if ((BIO_write(bp, "-----END ", 9) != 9) || + (BIO_write(bp, name, nlen) != nlen) || + (BIO_write(bp, "-----\n", 6) != 6)) + goto err; + retval = i + outl; + + err: + if (retval == 0) + PEMerr(PEM_F_PEM_WRITE_BIO, reason); + EVP_ENCODE_CTX_free(ctx); + OPENSSL_clear_free(buf, PEM_BUFSIZE * 8); + return retval; +} + +#ifndef OPENSSL_NO_STDIO +int PEM_read(FILE *fp, char **name, char **header, unsigned char **data, + long *len) +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + PEMerr(PEM_F_PEM_READ, ERR_R_BUF_LIB); + return 0; + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = PEM_read_bio(b, name, header, data, len); + BIO_free(b); + return ret; +} +#endif + +/* Some helpers for PEM_read_bio_ex(). */ +static int sanitize_line(char *linebuf, int len, unsigned int flags) +{ + int i; + + if (flags & PEM_FLAG_EAY_COMPATIBLE) { + /* Strip trailing whitespace */ + while ((len >= 0) && (linebuf[len] <= ' ')) + len--; + /* Go back to whitespace before applying uniform line ending. */ + len++; + } else if (flags & PEM_FLAG_ONLY_B64) { + for (i = 0; i < len; ++i) { + if (!ossl_isbase64(linebuf[i]) || linebuf[i] == '\n' + || linebuf[i] == '\r') + break; + } + len = i; + } else { + /* EVP_DecodeBlock strips leading and trailing whitespace, so just strip + * control characters in-place and let everything through. */ + for (i = 0; i < len; ++i) { + if (linebuf[i] == '\n' || linebuf[i] == '\r') + break; + if (ossl_iscntrl(linebuf[i])) + linebuf[i] = ' '; + } + len = i; + } + /* The caller allocated LINESIZE+1, so this is safe. */ + linebuf[len++] = '\n'; + linebuf[len] = '\0'; + return len; +} + +#define LINESIZE 255 +/* Note trailing spaces for begin and end. */ +static const char beginstr[] = "-----BEGIN "; +static const char endstr[] = "-----END "; +static const char tailstr[] = "-----\n"; +#define BEGINLEN ((int)(sizeof(beginstr) - 1)) +#define ENDLEN ((int)(sizeof(endstr) - 1)) +#define TAILLEN ((int)(sizeof(tailstr) - 1)) +static int get_name(BIO *bp, char **name, unsigned int flags) +{ + char *linebuf; + int ret = 0; + int len; + + /* + * Need to hold trailing NUL (accounted for by BIO_gets() and the newline + * that will be added by sanitize_line() (the extra '1'). + */ + linebuf = pem_malloc(LINESIZE + 1, flags); + if (linebuf == NULL) { + PEMerr(PEM_F_GET_NAME, ERR_R_MALLOC_FAILURE); + return 0; + } + + do { + len = BIO_gets(bp, linebuf, LINESIZE); + + if (len <= 0) { + PEMerr(PEM_F_GET_NAME, PEM_R_NO_START_LINE); + goto err; + } + + /* Strip trailing garbage and standardize ending. */ + len = sanitize_line(linebuf, len, flags & ~PEM_FLAG_ONLY_B64); + + /* Allow leading empty or non-matching lines. */ + } while (strncmp(linebuf, beginstr, BEGINLEN) != 0 + || len < TAILLEN + || strncmp(linebuf + len - TAILLEN, tailstr, TAILLEN) != 0); + linebuf[len - TAILLEN] = '\0'; + len = len - BEGINLEN - TAILLEN + 1; + *name = pem_malloc(len, flags); + if (*name == NULL) { + PEMerr(PEM_F_GET_NAME, ERR_R_MALLOC_FAILURE); + goto err; + } + memcpy(*name, linebuf + BEGINLEN, len); + ret = 1; + +err: + pem_free(linebuf, flags, LINESIZE + 1); + return ret; +} + +/* Keep track of how much of a header we've seen. */ +enum header_status { + MAYBE_HEADER, + IN_HEADER, + POST_HEADER +}; + +/** + * Extract the optional PEM header, with details on the type of content and + * any encryption used on the contents, and the bulk of the data from the bio. + * The end of the header is marked by a blank line; if the end-of-input marker + * is reached prior to a blank line, there is no header. + * + * The header and data arguments are BIO** since we may have to swap them + * if there is no header, for efficiency. + * + * We need the name of the PEM-encoded type to verify the end string. + */ +static int get_header_and_data(BIO *bp, BIO **header, BIO **data, char *name, + unsigned int flags) +{ + BIO *tmp = *header; + char *linebuf, *p; + int len, line, ret = 0, end = 0; + /* 0 if not seen (yet), 1 if reading header, 2 if finished header */ + enum header_status got_header = MAYBE_HEADER; + unsigned int flags_mask; + size_t namelen; + + /* Need to hold trailing NUL (accounted for by BIO_gets() and the newline + * that will be added by sanitize_line() (the extra '1'). */ + linebuf = pem_malloc(LINESIZE + 1, flags); + if (linebuf == NULL) { + PEMerr(PEM_F_GET_HEADER_AND_DATA, ERR_R_MALLOC_FAILURE); + return 0; + } + + for (line = 0; ; line++) { + flags_mask = ~0u; + len = BIO_gets(bp, linebuf, LINESIZE); + if (len <= 0) { + PEMerr(PEM_F_GET_HEADER_AND_DATA, PEM_R_SHORT_HEADER); + goto err; + } + + if (got_header == MAYBE_HEADER) { + if (memchr(linebuf, ':', len) != NULL) + got_header = IN_HEADER; + } + if (!strncmp(linebuf, endstr, ENDLEN) || got_header == IN_HEADER) + flags_mask &= ~PEM_FLAG_ONLY_B64; + len = sanitize_line(linebuf, len, flags & flags_mask); + + /* Check for end of header. */ + if (linebuf[0] == '\n') { + if (got_header == POST_HEADER) { + /* Another blank line is an error. */ + PEMerr(PEM_F_GET_HEADER_AND_DATA, PEM_R_BAD_END_LINE); + goto err; + } + got_header = POST_HEADER; + tmp = *data; + continue; + } + + /* Check for end of stream (which means there is no header). */ + if (strncmp(linebuf, endstr, ENDLEN) == 0) { + p = linebuf + ENDLEN; + namelen = strlen(name); + if (strncmp(p, name, namelen) != 0 || + strncmp(p + namelen, tailstr, TAILLEN) != 0) { + PEMerr(PEM_F_GET_HEADER_AND_DATA, PEM_R_BAD_END_LINE); + goto err; + } + if (got_header == MAYBE_HEADER) { + *header = *data; + *data = tmp; + } + break; + } else if (end) { + /* Malformed input; short line not at end of data. */ + PEMerr(PEM_F_GET_HEADER_AND_DATA, PEM_R_BAD_END_LINE); + goto err; + } + /* + * Else, a line of text -- could be header or data; we don't + * know yet. Just pass it through. + */ + if (BIO_puts(tmp, linebuf) < 0) + goto err; + /* + * Only encrypted files need the line length check applied. + */ + if (got_header == POST_HEADER) { + /* 65 includes the trailing newline */ + if (len > 65) + goto err; + if (len < 65) + end = 1; + } + } + + ret = 1; +err: + pem_free(linebuf, flags, LINESIZE + 1); + return ret; +} + +/** + * Read in PEM-formatted data from the given BIO. + * + * By nature of the PEM format, all content must be printable ASCII (except + * for line endings). Other characters are malformed input and will be rejected. + */ +int PEM_read_bio_ex(BIO *bp, char **name_out, char **header, + unsigned char **data, long *len_out, unsigned int flags) +{ + EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new(); + const BIO_METHOD *bmeth; + BIO *headerB = NULL, *dataB = NULL; + char *name = NULL; + int len, taillen, headerlen, ret = 0; + BUF_MEM * buf_mem; + + if (ctx == NULL) { + PEMerr(PEM_F_PEM_READ_BIO_EX, ERR_R_MALLOC_FAILURE); + return 0; + } + + *len_out = 0; + *name_out = *header = NULL; + *data = NULL; + if ((flags & PEM_FLAG_EAY_COMPATIBLE) && (flags & PEM_FLAG_ONLY_B64)) { + /* These two are mutually incompatible; bail out. */ + PEMerr(PEM_F_PEM_READ_BIO_EX, ERR_R_PASSED_INVALID_ARGUMENT); + goto end; + } + bmeth = (flags & PEM_FLAG_SECURE) ? BIO_s_secmem() : BIO_s_mem(); + + headerB = BIO_new(bmeth); + dataB = BIO_new(bmeth); + if (headerB == NULL || dataB == NULL) { + PEMerr(PEM_F_PEM_READ_BIO_EX, ERR_R_MALLOC_FAILURE); + goto end; + } + + if (!get_name(bp, &name, flags)) + goto end; + if (!get_header_and_data(bp, &headerB, &dataB, name, flags)) + goto end; + + EVP_DecodeInit(ctx); + BIO_get_mem_ptr(dataB, &buf_mem); + len = buf_mem->length; + if (EVP_DecodeUpdate(ctx, (unsigned char*)buf_mem->data, &len, + (unsigned char*)buf_mem->data, len) < 0 + || EVP_DecodeFinal(ctx, (unsigned char*)&(buf_mem->data[len]), + &taillen) < 0) { + PEMerr(PEM_F_PEM_READ_BIO_EX, PEM_R_BAD_BASE64_DECODE); + goto end; + } + len += taillen; + buf_mem->length = len; + + /* There was no data in the PEM file; avoid malloc(0). */ + if (len == 0) + goto end; + headerlen = BIO_get_mem_data(headerB, NULL); + *header = pem_malloc(headerlen + 1, flags); + *data = pem_malloc(len, flags); + if (*header == NULL || *data == NULL) { + pem_free(*header, flags, 0); + pem_free(*data, flags, 0); + goto end; + } + BIO_read(headerB, *header, headerlen); + (*header)[headerlen] = '\0'; + BIO_read(dataB, *data, len); + *len_out = len; + *name_out = name; + name = NULL; + ret = 1; + +end: + EVP_ENCODE_CTX_free(ctx); + pem_free(name, flags, 0); + BIO_free(headerB); + BIO_free(dataB); + return ret; +} + +int PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data, + long *len) +{ + return PEM_read_bio_ex(bp, name, header, data, len, PEM_FLAG_EAY_COMPATIBLE); +} + +/* + * Check pem string and return prefix length. If for example the pem_str == + * "RSA PRIVATE KEY" and suffix = "PRIVATE KEY" the return value is 3 for the + * string "RSA". + */ + +int pem_check_suffix(const char *pem_str, const char *suffix) +{ + int pem_len = strlen(pem_str); + int suffix_len = strlen(suffix); + const char *p; + if (suffix_len + 1 >= pem_len) + return 0; + p = pem_str + pem_len - suffix_len; + if (strcmp(p, suffix)) + return 0; + p--; + if (*p != ' ') + return 0; + return p - pem_str; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_oth.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_oth.c new file mode 100644 index 000000000..566205331 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_oth.c @@ -0,0 +1,36 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include + +/* Handle 'other' PEMs: not private keys */ + +void *PEM_ASN1_read_bio(d2i_of_void *d2i, const char *name, BIO *bp, void **x, + pem_password_cb *cb, void *u) +{ + const unsigned char *p = NULL; + unsigned char *data = NULL; + long len; + char *ret = NULL; + + if (!PEM_bytes_read_bio(&data, &len, NULL, name, bp, cb, u)) + return NULL; + p = data; + ret = d2i(x, &p, len); + if (ret == NULL) + PEMerr(PEM_F_PEM_ASN1_READ_BIO, ERR_R_ASN1_LIB); + OPENSSL_free(data); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_pk8.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_pk8.c new file mode 100644 index 000000000..ab6c4c6bd --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_pk8.c @@ -0,0 +1,214 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include + +static int do_pk8pkey(BIO *bp, EVP_PKEY *x, int isder, + int nid, const EVP_CIPHER *enc, + char *kstr, int klen, pem_password_cb *cb, void *u); + +#ifndef OPENSSL_NO_STDIO +static int do_pk8pkey_fp(FILE *bp, EVP_PKEY *x, int isder, + int nid, const EVP_CIPHER *enc, + char *kstr, int klen, pem_password_cb *cb, void *u); +#endif +/* + * These functions write a private key in PKCS#8 format: it is a "drop in" + * replacement for PEM_write_bio_PrivateKey() and friends. As usual if 'enc' + * is NULL then it uses the unencrypted private key form. The 'nid' versions + * uses PKCS#5 v1.5 PBE algorithms whereas the others use PKCS#5 v2.0. + */ + +int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + return do_pk8pkey(bp, x, 0, nid, NULL, kstr, klen, cb, u); +} + +int PEM_write_bio_PKCS8PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc, + char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + return do_pk8pkey(bp, x, 0, -1, enc, kstr, klen, cb, u); +} + +int i2d_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc, + char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + return do_pk8pkey(bp, x, 1, -1, enc, kstr, klen, cb, u); +} + +int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + return do_pk8pkey(bp, x, 1, nid, NULL, kstr, klen, cb, u); +} + +static int do_pk8pkey(BIO *bp, EVP_PKEY *x, int isder, int nid, + const EVP_CIPHER *enc, char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + X509_SIG *p8; + PKCS8_PRIV_KEY_INFO *p8inf; + char buf[PEM_BUFSIZE]; + int ret; + + if ((p8inf = EVP_PKEY2PKCS8(x)) == NULL) { + PEMerr(PEM_F_DO_PK8PKEY, PEM_R_ERROR_CONVERTING_PRIVATE_KEY); + return 0; + } + if (enc || (nid != -1)) { + if (!kstr) { + if (!cb) + klen = PEM_def_callback(buf, PEM_BUFSIZE, 1, u); + else + klen = cb(buf, PEM_BUFSIZE, 1, u); + if (klen <= 0) { + PEMerr(PEM_F_DO_PK8PKEY, PEM_R_READ_KEY); + PKCS8_PRIV_KEY_INFO_free(p8inf); + return 0; + } + + kstr = buf; + } + p8 = PKCS8_encrypt(nid, enc, kstr, klen, NULL, 0, 0, p8inf); + if (kstr == buf) + OPENSSL_cleanse(buf, klen); + PKCS8_PRIV_KEY_INFO_free(p8inf); + if (p8 == NULL) + return 0; + if (isder) + ret = i2d_PKCS8_bio(bp, p8); + else + ret = PEM_write_bio_PKCS8(bp, p8); + X509_SIG_free(p8); + return ret; + } else { + if (isder) + ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf); + else + ret = PEM_write_bio_PKCS8_PRIV_KEY_INFO(bp, p8inf); + PKCS8_PRIV_KEY_INFO_free(p8inf); + return ret; + } +} + +EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, + void *u) +{ + PKCS8_PRIV_KEY_INFO *p8inf = NULL; + X509_SIG *p8 = NULL; + int klen; + EVP_PKEY *ret; + char psbuf[PEM_BUFSIZE]; + p8 = d2i_PKCS8_bio(bp, NULL); + if (!p8) + return NULL; + if (cb) + klen = cb(psbuf, PEM_BUFSIZE, 0, u); + else + klen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u); + if (klen < 0) { + PEMerr(PEM_F_D2I_PKCS8PRIVATEKEY_BIO, PEM_R_BAD_PASSWORD_READ); + X509_SIG_free(p8); + return NULL; + } + p8inf = PKCS8_decrypt(p8, psbuf, klen); + X509_SIG_free(p8); + OPENSSL_cleanse(psbuf, klen); + if (!p8inf) + return NULL; + ret = EVP_PKCS82PKEY(p8inf); + PKCS8_PRIV_KEY_INFO_free(p8inf); + if (!ret) + return NULL; + if (x) { + EVP_PKEY_free(*x); + *x = ret; + } + return ret; +} + +#ifndef OPENSSL_NO_STDIO + +int i2d_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, + char *kstr, int klen, pem_password_cb *cb, void *u) +{ + return do_pk8pkey_fp(fp, x, 1, -1, enc, kstr, klen, cb, u); +} + +int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + return do_pk8pkey_fp(fp, x, 1, nid, NULL, kstr, klen, cb, u); +} + +int PEM_write_PKCS8PrivateKey_nid(FILE *fp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + return do_pk8pkey_fp(fp, x, 0, nid, NULL, kstr, klen, cb, u); +} + +int PEM_write_PKCS8PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, + char *kstr, int klen, pem_password_cb *cb, + void *u) +{ + return do_pk8pkey_fp(fp, x, 0, -1, enc, kstr, klen, cb, u); +} + +static int do_pk8pkey_fp(FILE *fp, EVP_PKEY *x, int isder, int nid, + const EVP_CIPHER *enc, char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + BIO *bp; + int ret; + + if ((bp = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) { + PEMerr(PEM_F_DO_PK8PKEY_FP, ERR_R_BUF_LIB); + return 0; + } + ret = do_pk8pkey(bp, x, isder, nid, enc, kstr, klen, cb, u); + BIO_free(bp); + return ret; +} + +EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, + void *u) +{ + BIO *bp; + EVP_PKEY *ret; + + if ((bp = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) { + PEMerr(PEM_F_D2I_PKCS8PRIVATEKEY_FP, ERR_R_BUF_LIB); + return NULL; + } + ret = d2i_PKCS8PrivateKey_bio(bp, x, cb, u); + BIO_free(bp); + return ret; +} + +#endif + +IMPLEMENT_PEM_rw(PKCS8, X509_SIG, PEM_STRING_PKCS8, X509_SIG) + + +IMPLEMENT_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO, PEM_STRING_PKCS8INF, + PKCS8_PRIV_KEY_INFO) diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_pkey.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_pkey.c new file mode 100644 index 000000000..aa032d2b1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_pkey.c @@ -0,0 +1,245 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "internal/asn1_int.h" +#include "internal/evp_int.h" + +int pem_check_suffix(const char *pem_str, const char *suffix); + +EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, + void *u) +{ + char *nm = NULL; + const unsigned char *p = NULL; + unsigned char *data = NULL; + long len; + int slen; + EVP_PKEY *ret = NULL; + + if (!PEM_bytes_read_bio_secmem(&data, &len, &nm, PEM_STRING_EVP_PKEY, bp, + cb, u)) + return NULL; + p = data; + + if (strcmp(nm, PEM_STRING_PKCS8INF) == 0) { + PKCS8_PRIV_KEY_INFO *p8inf; + p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len); + if (!p8inf) + goto p8err; + ret = EVP_PKCS82PKEY(p8inf); + if (x) { + EVP_PKEY_free((EVP_PKEY *)*x); + *x = ret; + } + PKCS8_PRIV_KEY_INFO_free(p8inf); + } else if (strcmp(nm, PEM_STRING_PKCS8) == 0) { + PKCS8_PRIV_KEY_INFO *p8inf; + X509_SIG *p8; + int klen; + char psbuf[PEM_BUFSIZE]; + p8 = d2i_X509_SIG(NULL, &p, len); + if (!p8) + goto p8err; + if (cb) + klen = cb(psbuf, PEM_BUFSIZE, 0, u); + else + klen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u); + if (klen < 0) { + PEMerr(PEM_F_PEM_READ_BIO_PRIVATEKEY, PEM_R_BAD_PASSWORD_READ); + X509_SIG_free(p8); + goto err; + } + p8inf = PKCS8_decrypt(p8, psbuf, klen); + X509_SIG_free(p8); + OPENSSL_cleanse(psbuf, klen); + if (!p8inf) + goto p8err; + ret = EVP_PKCS82PKEY(p8inf); + if (x) { + EVP_PKEY_free((EVP_PKEY *)*x); + *x = ret; + } + PKCS8_PRIV_KEY_INFO_free(p8inf); + } else if ((slen = pem_check_suffix(nm, "PRIVATE KEY")) > 0) { + const EVP_PKEY_ASN1_METHOD *ameth; + ameth = EVP_PKEY_asn1_find_str(NULL, nm, slen); + if (!ameth || !ameth->old_priv_decode) + goto p8err; + ret = d2i_PrivateKey(ameth->pkey_id, x, &p, len); + } + p8err: + if (ret == NULL) + PEMerr(PEM_F_PEM_READ_BIO_PRIVATEKEY, ERR_R_ASN1_LIB); + err: + OPENSSL_secure_free(nm); + OPENSSL_secure_clear_free(data, len); + return ret; +} + +int PEM_write_bio_PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + if (x->ameth == NULL || x->ameth->priv_encode != NULL) + return PEM_write_bio_PKCS8PrivateKey(bp, x, enc, + (char *)kstr, klen, cb, u); + return PEM_write_bio_PrivateKey_traditional(bp, x, enc, kstr, klen, cb, u); +} + +int PEM_write_bio_PrivateKey_traditional(BIO *bp, EVP_PKEY *x, + const EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + char pem_str[80]; + BIO_snprintf(pem_str, 80, "%s PRIVATE KEY", x->ameth->pem_str); + return PEM_ASN1_write_bio((i2d_of_void *)i2d_PrivateKey, + pem_str, bp, x, enc, kstr, klen, cb, u); +} + +EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x) +{ + char *nm = NULL; + const unsigned char *p = NULL; + unsigned char *data = NULL; + long len; + int slen; + EVP_PKEY *ret = NULL; + + if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_PARAMETERS, + bp, 0, NULL)) + return NULL; + p = data; + + if ((slen = pem_check_suffix(nm, "PARAMETERS")) > 0) { + ret = EVP_PKEY_new(); + if (ret == NULL) + goto err; + if (!EVP_PKEY_set_type_str(ret, nm, slen) + || !ret->ameth->param_decode + || !ret->ameth->param_decode(ret, &p, len)) { + EVP_PKEY_free(ret); + ret = NULL; + goto err; + } + if (x) { + EVP_PKEY_free((EVP_PKEY *)*x); + *x = ret; + } + } + err: + if (ret == NULL) + PEMerr(PEM_F_PEM_READ_BIO_PARAMETERS, ERR_R_ASN1_LIB); + OPENSSL_free(nm); + OPENSSL_free(data); + return ret; +} + +int PEM_write_bio_Parameters(BIO *bp, EVP_PKEY *x) +{ + char pem_str[80]; + if (!x->ameth || !x->ameth->param_encode) + return 0; + + BIO_snprintf(pem_str, 80, "%s PARAMETERS", x->ameth->pem_str); + return PEM_ASN1_write_bio((i2d_of_void *)x->ameth->param_encode, + pem_str, bp, x, NULL, NULL, 0, 0, NULL); +} + +#ifndef OPENSSL_NO_STDIO +EVP_PKEY *PEM_read_PrivateKey(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, + void *u) +{ + BIO *b; + EVP_PKEY *ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + PEMerr(PEM_F_PEM_READ_PRIVATEKEY, ERR_R_BUF_LIB); + return 0; + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = PEM_read_bio_PrivateKey(b, x, cb, u); + BIO_free(b); + return ret; +} + +int PEM_write_PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + BIO *b; + int ret; + + if ((b = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) { + PEMerr(PEM_F_PEM_WRITE_PRIVATEKEY, ERR_R_BUF_LIB); + return 0; + } + ret = PEM_write_bio_PrivateKey(b, x, enc, kstr, klen, cb, u); + BIO_free(b); + return ret; +} + +#endif + +#ifndef OPENSSL_NO_DH + +/* Transparently read in PKCS#3 or X9.42 DH parameters */ + +DH *PEM_read_bio_DHparams(BIO *bp, DH **x, pem_password_cb *cb, void *u) +{ + char *nm = NULL; + const unsigned char *p = NULL; + unsigned char *data = NULL; + long len; + DH *ret = NULL; + + if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_DHPARAMS, bp, cb, u)) + return NULL; + p = data; + + if (strcmp(nm, PEM_STRING_DHXPARAMS) == 0) + ret = d2i_DHxparams(x, &p, len); + else + ret = d2i_DHparams(x, &p, len); + + if (ret == NULL) + PEMerr(PEM_F_PEM_READ_BIO_DHPARAMS, ERR_R_ASN1_LIB); + OPENSSL_free(nm); + OPENSSL_free(data); + return ret; +} + +# ifndef OPENSSL_NO_STDIO +DH *PEM_read_DHparams(FILE *fp, DH **x, pem_password_cb *cb, void *u) +{ + BIO *b; + DH *ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + PEMerr(PEM_F_PEM_READ_DHPARAMS, ERR_R_BUF_LIB); + return 0; + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = PEM_read_bio_DHparams(b, x, cb, u); + BIO_free(b); + return ret; +} +# endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_sign.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_sign.c new file mode 100644 index 000000000..9662eb14d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_sign.c @@ -0,0 +1,50 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include + +int PEM_SignInit(EVP_MD_CTX *ctx, EVP_MD *type) +{ + return EVP_DigestInit_ex(ctx, type, NULL); +} + +int PEM_SignUpdate(EVP_MD_CTX *ctx, unsigned char *data, unsigned int count) +{ + return EVP_DigestUpdate(ctx, data, count); +} + +int PEM_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, + unsigned int *siglen, EVP_PKEY *pkey) +{ + unsigned char *m; + int i, ret = 0; + unsigned int m_len; + + m = OPENSSL_malloc(EVP_PKEY_size(pkey) + 2); + if (m == NULL) { + PEMerr(PEM_F_PEM_SIGNFINAL, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (EVP_SignFinal(ctx, m, &m_len, pkey) <= 0) + goto err; + + i = EVP_EncodeBlock(sigret, m, m_len); + *siglen = i; + ret = 1; + err: + /* ctx has been zeroed by EVP_SignFinal() */ + OPENSSL_free(m); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_x509.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_x509.c new file mode 100644 index 000000000..3a997564a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_x509.c @@ -0,0 +1,18 @@ +/* + * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include + +IMPLEMENT_PEM_rw(X509, X509, PEM_STRING_X509, X509) diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_xaux.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_xaux.c new file mode 100644 index 000000000..6d7e1db21 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pem_xaux.c @@ -0,0 +1,18 @@ +/* + * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include + +IMPLEMENT_PEM_rw(X509_AUX, X509, PEM_STRING_X509_TRUSTED, X509_AUX) diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pvkfmt.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pvkfmt.c new file mode 100644 index 000000000..e39c24381 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pem/pvkfmt.c @@ -0,0 +1,883 @@ +/* + * Copyright 2005-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Support for PVK format keys and related structures (such a PUBLICKEYBLOB + * and PRIVATEKEYBLOB). + */ + +#include "internal/cryptlib.h" +#include +#include +#include +#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) +# include +# include + +/* + * Utility function: read a DWORD (4 byte unsigned integer) in little endian + * format + */ + +static unsigned int read_ledword(const unsigned char **in) +{ + const unsigned char *p = *in; + unsigned int ret; + ret = *p++; + ret |= (*p++ << 8); + ret |= (*p++ << 16); + ret |= (*p++ << 24); + *in = p; + return ret; +} + +/* + * Read a BIGNUM in little endian format. The docs say that this should take + * up bitlen/8 bytes. + */ + +static int read_lebn(const unsigned char **in, unsigned int nbyte, BIGNUM **r) +{ + *r = BN_lebin2bn(*in, nbyte, NULL); + if (*r == NULL) + return 0; + *in += nbyte; + return 1; +} + +/* Convert private key blob to EVP_PKEY: RSA and DSA keys supported */ + +# define MS_PUBLICKEYBLOB 0x6 +# define MS_PRIVATEKEYBLOB 0x7 +# define MS_RSA1MAGIC 0x31415352L +# define MS_RSA2MAGIC 0x32415352L +# define MS_DSS1MAGIC 0x31535344L +# define MS_DSS2MAGIC 0x32535344L + +# define MS_KEYALG_RSA_KEYX 0xa400 +# define MS_KEYALG_DSS_SIGN 0x2200 + +# define MS_KEYTYPE_KEYX 0x1 +# define MS_KEYTYPE_SIGN 0x2 + +/* Maximum length of a blob after header */ +# define BLOB_MAX_LENGTH 102400 + +/* The PVK file magic number: seems to spell out "bobsfile", who is Bob? */ +# define MS_PVKMAGIC 0xb0b5f11eL +/* Salt length for PVK files */ +# define PVK_SALTLEN 0x10 +/* Maximum length in PVK header */ +# define PVK_MAX_KEYLEN 102400 +/* Maximum salt length */ +# define PVK_MAX_SALTLEN 10240 + +static EVP_PKEY *b2i_rsa(const unsigned char **in, + unsigned int bitlen, int ispub); +static EVP_PKEY *b2i_dss(const unsigned char **in, + unsigned int bitlen, int ispub); + +static int do_blob_header(const unsigned char **in, unsigned int length, + unsigned int *pmagic, unsigned int *pbitlen, + int *pisdss, int *pispub) +{ + const unsigned char *p = *in; + if (length < 16) + return 0; + /* bType */ + if (*p == MS_PUBLICKEYBLOB) { + if (*pispub == 0) { + PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_EXPECTING_PRIVATE_KEY_BLOB); + return 0; + } + *pispub = 1; + } else if (*p == MS_PRIVATEKEYBLOB) { + if (*pispub == 1) { + PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_EXPECTING_PUBLIC_KEY_BLOB); + return 0; + } + *pispub = 0; + } else + return 0; + p++; + /* Version */ + if (*p++ != 0x2) { + PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_BAD_VERSION_NUMBER); + return 0; + } + /* Ignore reserved, aiKeyAlg */ + p += 6; + *pmagic = read_ledword(&p); + *pbitlen = read_ledword(&p); + *pisdss = 0; + switch (*pmagic) { + + case MS_DSS1MAGIC: + *pisdss = 1; + /* fall thru */ + case MS_RSA1MAGIC: + if (*pispub == 0) { + PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_EXPECTING_PRIVATE_KEY_BLOB); + return 0; + } + break; + + case MS_DSS2MAGIC: + *pisdss = 1; + /* fall thru */ + case MS_RSA2MAGIC: + if (*pispub == 1) { + PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_EXPECTING_PUBLIC_KEY_BLOB); + return 0; + } + break; + + default: + PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_BAD_MAGIC_NUMBER); + return -1; + } + *in = p; + return 1; +} + +static unsigned int blob_length(unsigned bitlen, int isdss, int ispub) +{ + unsigned int nbyte, hnbyte; + nbyte = (bitlen + 7) >> 3; + hnbyte = (bitlen + 15) >> 4; + if (isdss) { + + /* + * Expected length: 20 for q + 3 components bitlen each + 24 for seed + * structure. + */ + if (ispub) + return 44 + 3 * nbyte; + /* + * Expected length: 20 for q, priv, 2 bitlen components + 24 for seed + * structure. + */ + else + return 64 + 2 * nbyte; + } else { + /* Expected length: 4 for 'e' + 'n' */ + if (ispub) + return 4 + nbyte; + else + /* + * Expected length: 4 for 'e' and 7 other components. 2 + * components are bitlen size, 5 are bitlen/2 + */ + return 4 + 2 * nbyte + 5 * hnbyte; + } + +} + +static EVP_PKEY *do_b2i(const unsigned char **in, unsigned int length, + int ispub) +{ + const unsigned char *p = *in; + unsigned int bitlen, magic; + int isdss; + if (do_blob_header(&p, length, &magic, &bitlen, &isdss, &ispub) <= 0) { + PEMerr(PEM_F_DO_B2I, PEM_R_KEYBLOB_HEADER_PARSE_ERROR); + return NULL; + } + length -= 16; + if (length < blob_length(bitlen, isdss, ispub)) { + PEMerr(PEM_F_DO_B2I, PEM_R_KEYBLOB_TOO_SHORT); + return NULL; + } + if (isdss) + return b2i_dss(&p, bitlen, ispub); + else + return b2i_rsa(&p, bitlen, ispub); +} + +static EVP_PKEY *do_b2i_bio(BIO *in, int ispub) +{ + const unsigned char *p; + unsigned char hdr_buf[16], *buf = NULL; + unsigned int bitlen, magic, length; + int isdss; + EVP_PKEY *ret = NULL; + if (BIO_read(in, hdr_buf, 16) != 16) { + PEMerr(PEM_F_DO_B2I_BIO, PEM_R_KEYBLOB_TOO_SHORT); + return NULL; + } + p = hdr_buf; + if (do_blob_header(&p, 16, &magic, &bitlen, &isdss, &ispub) <= 0) + return NULL; + + length = blob_length(bitlen, isdss, ispub); + if (length > BLOB_MAX_LENGTH) { + PEMerr(PEM_F_DO_B2I_BIO, PEM_R_HEADER_TOO_LONG); + return NULL; + } + buf = OPENSSL_malloc(length); + if (buf == NULL) { + PEMerr(PEM_F_DO_B2I_BIO, ERR_R_MALLOC_FAILURE); + goto err; + } + p = buf; + if (BIO_read(in, buf, length) != (int)length) { + PEMerr(PEM_F_DO_B2I_BIO, PEM_R_KEYBLOB_TOO_SHORT); + goto err; + } + + if (isdss) + ret = b2i_dss(&p, bitlen, ispub); + else + ret = b2i_rsa(&p, bitlen, ispub); + + err: + OPENSSL_free(buf); + return ret; +} + +static EVP_PKEY *b2i_dss(const unsigned char **in, + unsigned int bitlen, int ispub) +{ + const unsigned char *p = *in; + EVP_PKEY *ret = NULL; + DSA *dsa = NULL; + BN_CTX *ctx = NULL; + unsigned int nbyte; + BIGNUM *pbn = NULL, *qbn = NULL, *gbn = NULL, *priv_key = NULL; + BIGNUM *pub_key = NULL; + + nbyte = (bitlen + 7) >> 3; + + dsa = DSA_new(); + ret = EVP_PKEY_new(); + if (dsa == NULL || ret == NULL) + goto memerr; + if (!read_lebn(&p, nbyte, &pbn)) + goto memerr; + + if (!read_lebn(&p, 20, &qbn)) + goto memerr; + + if (!read_lebn(&p, nbyte, &gbn)) + goto memerr; + + if (ispub) { + if (!read_lebn(&p, nbyte, &pub_key)) + goto memerr; + } else { + if (!read_lebn(&p, 20, &priv_key)) + goto memerr; + + /* Calculate public key */ + pub_key = BN_new(); + if (pub_key == NULL) + goto memerr; + if ((ctx = BN_CTX_new()) == NULL) + goto memerr; + + if (!BN_mod_exp(pub_key, gbn, priv_key, pbn, ctx)) + goto memerr; + + BN_CTX_free(ctx); + ctx = NULL; + } + if (!DSA_set0_pqg(dsa, pbn, qbn, gbn)) + goto memerr; + pbn = qbn = gbn = NULL; + if (!DSA_set0_key(dsa, pub_key, priv_key)) + goto memerr; + pub_key = priv_key = NULL; + + if (!EVP_PKEY_set1_DSA(ret, dsa)) + goto memerr; + DSA_free(dsa); + *in = p; + return ret; + + memerr: + PEMerr(PEM_F_B2I_DSS, ERR_R_MALLOC_FAILURE); + DSA_free(dsa); + BN_free(pbn); + BN_free(qbn); + BN_free(gbn); + BN_free(pub_key); + BN_free(priv_key); + EVP_PKEY_free(ret); + BN_CTX_free(ctx); + return NULL; +} + +static EVP_PKEY *b2i_rsa(const unsigned char **in, + unsigned int bitlen, int ispub) +{ + const unsigned char *pin = *in; + EVP_PKEY *ret = NULL; + BIGNUM *e = NULL, *n = NULL, *d = NULL; + BIGNUM *p = NULL, *q = NULL, *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL; + RSA *rsa = NULL; + unsigned int nbyte, hnbyte; + nbyte = (bitlen + 7) >> 3; + hnbyte = (bitlen + 15) >> 4; + rsa = RSA_new(); + ret = EVP_PKEY_new(); + if (rsa == NULL || ret == NULL) + goto memerr; + e = BN_new(); + if (e == NULL) + goto memerr; + if (!BN_set_word(e, read_ledword(&pin))) + goto memerr; + if (!read_lebn(&pin, nbyte, &n)) + goto memerr; + if (!ispub) { + if (!read_lebn(&pin, hnbyte, &p)) + goto memerr; + if (!read_lebn(&pin, hnbyte, &q)) + goto memerr; + if (!read_lebn(&pin, hnbyte, &dmp1)) + goto memerr; + if (!read_lebn(&pin, hnbyte, &dmq1)) + goto memerr; + if (!read_lebn(&pin, hnbyte, &iqmp)) + goto memerr; + if (!read_lebn(&pin, nbyte, &d)) + goto memerr; + if (!RSA_set0_factors(rsa, p, q)) + goto memerr; + p = q = NULL; + if (!RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp)) + goto memerr; + dmp1 = dmq1 = iqmp = NULL; + } + if (!RSA_set0_key(rsa, n, e, d)) + goto memerr; + n = e = d = NULL; + + if (!EVP_PKEY_set1_RSA(ret, rsa)) + goto memerr; + RSA_free(rsa); + *in = pin; + return ret; + memerr: + PEMerr(PEM_F_B2I_RSA, ERR_R_MALLOC_FAILURE); + BN_free(e); + BN_free(n); + BN_free(p); + BN_free(q); + BN_free(dmp1); + BN_free(dmq1); + BN_free(iqmp); + BN_free(d); + RSA_free(rsa); + EVP_PKEY_free(ret); + return NULL; +} + +EVP_PKEY *b2i_PrivateKey(const unsigned char **in, long length) +{ + return do_b2i(in, length, 0); +} + +EVP_PKEY *b2i_PublicKey(const unsigned char **in, long length) +{ + return do_b2i(in, length, 1); +} + +EVP_PKEY *b2i_PrivateKey_bio(BIO *in) +{ + return do_b2i_bio(in, 0); +} + +EVP_PKEY *b2i_PublicKey_bio(BIO *in) +{ + return do_b2i_bio(in, 1); +} + +static void write_ledword(unsigned char **out, unsigned int dw) +{ + unsigned char *p = *out; + *p++ = dw & 0xff; + *p++ = (dw >> 8) & 0xff; + *p++ = (dw >> 16) & 0xff; + *p++ = (dw >> 24) & 0xff; + *out = p; +} + +static void write_lebn(unsigned char **out, const BIGNUM *bn, int len) +{ + BN_bn2lebinpad(bn, *out, len); + *out += len; +} + +static int check_bitlen_rsa(RSA *rsa, int ispub, unsigned int *magic); +static int check_bitlen_dsa(DSA *dsa, int ispub, unsigned int *magic); + +static void write_rsa(unsigned char **out, RSA *rsa, int ispub); +static void write_dsa(unsigned char **out, DSA *dsa, int ispub); + +static int do_i2b(unsigned char **out, EVP_PKEY *pk, int ispub) +{ + unsigned char *p; + unsigned int bitlen, magic = 0, keyalg; + int outlen, noinc = 0; + int pktype = EVP_PKEY_id(pk); + if (pktype == EVP_PKEY_DSA) { + bitlen = check_bitlen_dsa(EVP_PKEY_get0_DSA(pk), ispub, &magic); + keyalg = MS_KEYALG_DSS_SIGN; + } else if (pktype == EVP_PKEY_RSA) { + bitlen = check_bitlen_rsa(EVP_PKEY_get0_RSA(pk), ispub, &magic); + keyalg = MS_KEYALG_RSA_KEYX; + } else + return -1; + if (bitlen == 0) + return -1; + outlen = 16 + blob_length(bitlen, + keyalg == MS_KEYALG_DSS_SIGN ? 1 : 0, ispub); + if (out == NULL) + return outlen; + if (*out) + p = *out; + else { + if ((p = OPENSSL_malloc(outlen)) == NULL) { + PEMerr(PEM_F_DO_I2B, ERR_R_MALLOC_FAILURE); + return -1; + } + *out = p; + noinc = 1; + } + if (ispub) + *p++ = MS_PUBLICKEYBLOB; + else + *p++ = MS_PRIVATEKEYBLOB; + *p++ = 0x2; + *p++ = 0; + *p++ = 0; + write_ledword(&p, keyalg); + write_ledword(&p, magic); + write_ledword(&p, bitlen); + if (keyalg == MS_KEYALG_DSS_SIGN) + write_dsa(&p, EVP_PKEY_get0_DSA(pk), ispub); + else + write_rsa(&p, EVP_PKEY_get0_RSA(pk), ispub); + if (!noinc) + *out += outlen; + return outlen; +} + +static int do_i2b_bio(BIO *out, EVP_PKEY *pk, int ispub) +{ + unsigned char *tmp = NULL; + int outlen, wrlen; + outlen = do_i2b(&tmp, pk, ispub); + if (outlen < 0) + return -1; + wrlen = BIO_write(out, tmp, outlen); + OPENSSL_free(tmp); + if (wrlen == outlen) + return outlen; + return -1; +} + +static int check_bitlen_dsa(DSA *dsa, int ispub, unsigned int *pmagic) +{ + int bitlen; + const BIGNUM *p = NULL, *q = NULL, *g = NULL; + const BIGNUM *pub_key = NULL, *priv_key = NULL; + + DSA_get0_pqg(dsa, &p, &q, &g); + DSA_get0_key(dsa, &pub_key, &priv_key); + bitlen = BN_num_bits(p); + if ((bitlen & 7) || (BN_num_bits(q) != 160) + || (BN_num_bits(g) > bitlen)) + goto badkey; + if (ispub) { + if (BN_num_bits(pub_key) > bitlen) + goto badkey; + *pmagic = MS_DSS1MAGIC; + } else { + if (BN_num_bits(priv_key) > 160) + goto badkey; + *pmagic = MS_DSS2MAGIC; + } + + return bitlen; + badkey: + PEMerr(PEM_F_CHECK_BITLEN_DSA, PEM_R_UNSUPPORTED_KEY_COMPONENTS); + return 0; +} + +static int check_bitlen_rsa(RSA *rsa, int ispub, unsigned int *pmagic) +{ + int nbyte, hnbyte, bitlen; + const BIGNUM *e; + + RSA_get0_key(rsa, NULL, &e, NULL); + if (BN_num_bits(e) > 32) + goto badkey; + bitlen = RSA_bits(rsa); + nbyte = RSA_size(rsa); + hnbyte = (bitlen + 15) >> 4; + if (ispub) { + *pmagic = MS_RSA1MAGIC; + return bitlen; + } else { + const BIGNUM *d, *p, *q, *iqmp, *dmp1, *dmq1; + + *pmagic = MS_RSA2MAGIC; + + /* + * For private key each component must fit within nbyte or hnbyte. + */ + RSA_get0_key(rsa, NULL, NULL, &d); + if (BN_num_bytes(d) > nbyte) + goto badkey; + RSA_get0_factors(rsa, &p, &q); + RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp); + if ((BN_num_bytes(iqmp) > hnbyte) + || (BN_num_bytes(p) > hnbyte) + || (BN_num_bytes(q) > hnbyte) + || (BN_num_bytes(dmp1) > hnbyte) + || (BN_num_bytes(dmq1) > hnbyte)) + goto badkey; + } + return bitlen; + badkey: + PEMerr(PEM_F_CHECK_BITLEN_RSA, PEM_R_UNSUPPORTED_KEY_COMPONENTS); + return 0; +} + +static void write_rsa(unsigned char **out, RSA *rsa, int ispub) +{ + int nbyte, hnbyte; + const BIGNUM *n, *d, *e, *p, *q, *iqmp, *dmp1, *dmq1; + + nbyte = RSA_size(rsa); + hnbyte = (RSA_bits(rsa) + 15) >> 4; + RSA_get0_key(rsa, &n, &e, &d); + write_lebn(out, e, 4); + write_lebn(out, n, nbyte); + if (ispub) + return; + RSA_get0_factors(rsa, &p, &q); + RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp); + write_lebn(out, p, hnbyte); + write_lebn(out, q, hnbyte); + write_lebn(out, dmp1, hnbyte); + write_lebn(out, dmq1, hnbyte); + write_lebn(out, iqmp, hnbyte); + write_lebn(out, d, nbyte); +} + +static void write_dsa(unsigned char **out, DSA *dsa, int ispub) +{ + int nbyte; + const BIGNUM *p = NULL, *q = NULL, *g = NULL; + const BIGNUM *pub_key = NULL, *priv_key = NULL; + + DSA_get0_pqg(dsa, &p, &q, &g); + DSA_get0_key(dsa, &pub_key, &priv_key); + nbyte = BN_num_bytes(p); + write_lebn(out, p, nbyte); + write_lebn(out, q, 20); + write_lebn(out, g, nbyte); + if (ispub) + write_lebn(out, pub_key, nbyte); + else + write_lebn(out, priv_key, 20); + /* Set "invalid" for seed structure values */ + memset(*out, 0xff, 24); + *out += 24; + return; +} + +int i2b_PrivateKey_bio(BIO *out, EVP_PKEY *pk) +{ + return do_i2b_bio(out, pk, 0); +} + +int i2b_PublicKey_bio(BIO *out, EVP_PKEY *pk) +{ + return do_i2b_bio(out, pk, 1); +} + +# ifndef OPENSSL_NO_RC4 + +static int do_PVK_header(const unsigned char **in, unsigned int length, + int skip_magic, + unsigned int *psaltlen, unsigned int *pkeylen) +{ + const unsigned char *p = *in; + unsigned int pvk_magic, is_encrypted; + if (skip_magic) { + if (length < 20) { + PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_PVK_TOO_SHORT); + return 0; + } + } else { + if (length < 24) { + PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_PVK_TOO_SHORT); + return 0; + } + pvk_magic = read_ledword(&p); + if (pvk_magic != MS_PVKMAGIC) { + PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_BAD_MAGIC_NUMBER); + return 0; + } + } + /* Skip reserved */ + p += 4; + /* + * keytype = + */ read_ledword(&p); + is_encrypted = read_ledword(&p); + *psaltlen = read_ledword(&p); + *pkeylen = read_ledword(&p); + + if (*pkeylen > PVK_MAX_KEYLEN || *psaltlen > PVK_MAX_SALTLEN) + return 0; + + if (is_encrypted && !*psaltlen) { + PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_INCONSISTENT_HEADER); + return 0; + } + + *in = p; + return 1; +} + +static int derive_pvk_key(unsigned char *key, + const unsigned char *salt, unsigned int saltlen, + const unsigned char *pass, int passlen) +{ + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); + int rv = 1; + if (mctx == NULL + || !EVP_DigestInit_ex(mctx, EVP_sha1(), NULL) + || !EVP_DigestUpdate(mctx, salt, saltlen) + || !EVP_DigestUpdate(mctx, pass, passlen) + || !EVP_DigestFinal_ex(mctx, key, NULL)) + rv = 0; + + EVP_MD_CTX_free(mctx); + return rv; +} + +static EVP_PKEY *do_PVK_body(const unsigned char **in, + unsigned int saltlen, unsigned int keylen, + pem_password_cb *cb, void *u) +{ + EVP_PKEY *ret = NULL; + const unsigned char *p = *in; + unsigned int magic; + unsigned char *enctmp = NULL, *q; + unsigned char keybuf[20]; + + EVP_CIPHER_CTX *cctx = EVP_CIPHER_CTX_new(); + if (saltlen) { + char psbuf[PEM_BUFSIZE]; + int enctmplen, inlen; + if (cb) + inlen = cb(psbuf, PEM_BUFSIZE, 0, u); + else + inlen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u); + if (inlen < 0) { + PEMerr(PEM_F_DO_PVK_BODY, PEM_R_BAD_PASSWORD_READ); + goto err; + } + enctmp = OPENSSL_malloc(keylen + 8); + if (enctmp == NULL) { + PEMerr(PEM_F_DO_PVK_BODY, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!derive_pvk_key(keybuf, p, saltlen, + (unsigned char *)psbuf, inlen)) + goto err; + p += saltlen; + /* Copy BLOBHEADER across, decrypt rest */ + memcpy(enctmp, p, 8); + p += 8; + if (keylen < 8) { + PEMerr(PEM_F_DO_PVK_BODY, PEM_R_PVK_TOO_SHORT); + goto err; + } + inlen = keylen - 8; + q = enctmp + 8; + if (!EVP_DecryptInit_ex(cctx, EVP_rc4(), NULL, keybuf, NULL)) + goto err; + if (!EVP_DecryptUpdate(cctx, q, &enctmplen, p, inlen)) + goto err; + if (!EVP_DecryptFinal_ex(cctx, q + enctmplen, &enctmplen)) + goto err; + magic = read_ledword((const unsigned char **)&q); + if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC) { + q = enctmp + 8; + memset(keybuf + 5, 0, 11); + if (!EVP_DecryptInit_ex(cctx, EVP_rc4(), NULL, keybuf, NULL)) + goto err; + if (!EVP_DecryptUpdate(cctx, q, &enctmplen, p, inlen)) + goto err; + if (!EVP_DecryptFinal_ex(cctx, q + enctmplen, &enctmplen)) + goto err; + magic = read_ledword((const unsigned char **)&q); + if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC) { + PEMerr(PEM_F_DO_PVK_BODY, PEM_R_BAD_DECRYPT); + goto err; + } + } + p = enctmp; + } + + ret = b2i_PrivateKey(&p, keylen); + err: + EVP_CIPHER_CTX_free(cctx); + if (enctmp != NULL) { + OPENSSL_cleanse(keybuf, sizeof(keybuf)); + OPENSSL_free(enctmp); + } + return ret; +} + +EVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u) +{ + unsigned char pvk_hdr[24], *buf = NULL; + const unsigned char *p; + int buflen; + EVP_PKEY *ret = NULL; + unsigned int saltlen, keylen; + if (BIO_read(in, pvk_hdr, 24) != 24) { + PEMerr(PEM_F_B2I_PVK_BIO, PEM_R_PVK_DATA_TOO_SHORT); + return NULL; + } + p = pvk_hdr; + + if (!do_PVK_header(&p, 24, 0, &saltlen, &keylen)) + return 0; + buflen = (int)keylen + saltlen; + buf = OPENSSL_malloc(buflen); + if (buf == NULL) { + PEMerr(PEM_F_B2I_PVK_BIO, ERR_R_MALLOC_FAILURE); + return 0; + } + p = buf; + if (BIO_read(in, buf, buflen) != buflen) { + PEMerr(PEM_F_B2I_PVK_BIO, PEM_R_PVK_DATA_TOO_SHORT); + goto err; + } + ret = do_PVK_body(&p, saltlen, keylen, cb, u); + + err: + OPENSSL_clear_free(buf, buflen); + return ret; +} + +static int i2b_PVK(unsigned char **out, EVP_PKEY *pk, int enclevel, + pem_password_cb *cb, void *u) +{ + int outlen = 24, pklen; + unsigned char *p = NULL, *start = NULL, *salt = NULL; + EVP_CIPHER_CTX *cctx = NULL; + if (enclevel) + outlen += PVK_SALTLEN; + pklen = do_i2b(NULL, pk, 0); + if (pklen < 0) + return -1; + outlen += pklen; + if (out == NULL) + return outlen; + if (*out != NULL) { + p = *out; + } else { + start = p = OPENSSL_malloc(outlen); + if (p == NULL) { + PEMerr(PEM_F_I2B_PVK, ERR_R_MALLOC_FAILURE); + return -1; + } + } + + cctx = EVP_CIPHER_CTX_new(); + if (cctx == NULL) + goto error; + + write_ledword(&p, MS_PVKMAGIC); + write_ledword(&p, 0); + if (EVP_PKEY_id(pk) == EVP_PKEY_DSA) + write_ledword(&p, MS_KEYTYPE_SIGN); + else + write_ledword(&p, MS_KEYTYPE_KEYX); + write_ledword(&p, enclevel ? 1 : 0); + write_ledword(&p, enclevel ? PVK_SALTLEN : 0); + write_ledword(&p, pklen); + if (enclevel) { + if (RAND_bytes(p, PVK_SALTLEN) <= 0) + goto error; + salt = p; + p += PVK_SALTLEN; + } + do_i2b(&p, pk, 0); + if (enclevel != 0) { + char psbuf[PEM_BUFSIZE]; + unsigned char keybuf[20]; + int enctmplen, inlen; + if (cb) + inlen = cb(psbuf, PEM_BUFSIZE, 1, u); + else + inlen = PEM_def_callback(psbuf, PEM_BUFSIZE, 1, u); + if (inlen <= 0) { + PEMerr(PEM_F_I2B_PVK, PEM_R_BAD_PASSWORD_READ); + goto error; + } + if (!derive_pvk_key(keybuf, salt, PVK_SALTLEN, + (unsigned char *)psbuf, inlen)) + goto error; + if (enclevel == 1) + memset(keybuf + 5, 0, 11); + p = salt + PVK_SALTLEN + 8; + if (!EVP_EncryptInit_ex(cctx, EVP_rc4(), NULL, keybuf, NULL)) + goto error; + OPENSSL_cleanse(keybuf, 20); + if (!EVP_DecryptUpdate(cctx, p, &enctmplen, p, pklen - 8)) + goto error; + if (!EVP_DecryptFinal_ex(cctx, p + enctmplen, &enctmplen)) + goto error; + } + + EVP_CIPHER_CTX_free(cctx); + + if (*out == NULL) + *out = start; + + return outlen; + + error: + EVP_CIPHER_CTX_free(cctx); + if (*out == NULL) + OPENSSL_free(start); + return -1; +} + +int i2b_PVK_bio(BIO *out, EVP_PKEY *pk, int enclevel, + pem_password_cb *cb, void *u) +{ + unsigned char *tmp = NULL; + int outlen, wrlen; + outlen = i2b_PVK(&tmp, pk, enclevel, cb, u); + if (outlen < 0) + return -1; + wrlen = BIO_write(out, tmp, outlen); + OPENSSL_free(tmp); + if (wrlen == outlen) { + PEMerr(PEM_F_I2B_PVK_BIO, PEM_R_BIO_WRITE_FAILURE); + return outlen; + } + return -1; +} + +# endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/README b/trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/README new file mode 100644 index 000000000..3177c3716 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/README @@ -0,0 +1,124 @@ +The perl scripts in this directory are my 'hack' to generate +multiple different assembler formats via the one original script. + +The way to use this library is to start with adding the path to this directory +and then include it. + +push(@INC,"perlasm","../../perlasm"); +require "x86asm.pl"; + +The first thing we do is setup the file and type of assembler + +&asm_init($ARGV[0]); + +The first argument is the 'type'. Currently +'cpp', 'sol', 'a.out', 'elf' or 'win32'. +Argument 2 is the file name. + +The reciprocal function is +&asm_finish() which should be called at the end. + +There are 2 main 'packages'. x86ms.pl, which is the Microsoft assembler, +and x86unix.pl which is the unix (gas) version. + +Functions of interest are: +&external_label("des_SPtrans"); declare and external variable +&LB(reg); Low byte for a register +&HB(reg); High byte for a register +&BP(off,base,index,scale) Byte pointer addressing +&DWP(off,base,index,scale) Word pointer addressing +&stack_push(num) Basically a 'sub esp, num*4' with extra +&stack_pop(num) inverse of stack_push +&function_begin(name,extra) Start a function with pushing of + edi, esi, ebx and ebp. extra is extra win32 + external info that may be required. +&function_begin_B(name,extra) Same as normal function_begin but no pushing. +&function_end(name) Call at end of function. +&function_end_A(name) Standard pop and ret, for use inside functions +&function_end_B(name) Call at end but with poping or 'ret'. +&swtmp(num) Address on stack temp word. +&wparam(num) Parameter number num, that was push + in C convention. This all works over pushes + and pops. +&comment("hello there") Put in a comment. +&label("loop") Refer to a label, normally a jmp target. +&set_label("loop") Set a label at this point. +&data_word(word) Put in a word of data. + +So how does this all hold together? Given + +int calc(int len, int *data) + { + int i,j=0; + + for (i=0; i$output" || die "can't open $output: $!"; + +$flavour = "linux32" if (!$flavour or $flavour eq "void"); + +my %GLOBALS; +my $dotinlocallabels=($flavour=~/linux/)?1:0; + +################################################################ +# directives which need special treatment on different platforms +################################################################ +my $arch = sub { + if ($flavour =~ /linux/) { ".arch\t".join(',',@_); } + else { ""; } +}; +my $fpu = sub { + if ($flavour =~ /linux/) { ".fpu\t".join(',',@_); } + else { ""; } +}; +my $hidden = sub { + if ($flavour =~ /ios/) { ".private_extern\t".join(',',@_); } + else { ".hidden\t".join(',',@_); } +}; +my $comm = sub { + my @args = split(/,\s*/,shift); + my $name = @args[0]; + my $global = \$GLOBALS{$name}; + my $ret; + + if ($flavour =~ /ios32/) { + $ret = ".comm\t_$name,@args[1]\n"; + $ret .= ".non_lazy_symbol_pointer\n"; + $ret .= "$name:\n"; + $ret .= ".indirect_symbol\t_$name\n"; + $ret .= ".long\t0"; + $name = "_$name"; + } else { $ret = ".comm\t".join(',',@args); } + + $$global = $name; + $ret; +}; +my $globl = sub { + my $name = shift; + my $global = \$GLOBALS{$name}; + my $ret; + + SWITCH: for ($flavour) { + /ios/ && do { $name = "_$name"; + last; + }; + } + + $ret = ".globl $name" if (!$ret); + $$global = $name; + $ret; +}; +my $global = $globl; +my $extern = sub { + &$globl(@_); + return; # return nothing +}; +my $type = sub { + if ($flavour =~ /linux/) { ".type\t".join(',',@_); } + elsif ($flavour =~ /ios32/) { if (join(',',@_) =~ /(\w+),%function/) { + "#ifdef __thumb2__\n". + ".thumb_func $1\n". + "#endif"; + } + } + else { ""; } +}; +my $size = sub { + if ($flavour =~ /linux/) { ".size\t".join(',',@_); } + else { ""; } +}; +my $inst = sub { + if ($flavour =~ /linux/) { ".inst\t".join(',',@_); } + else { ".long\t".join(',',@_); } +}; +my $asciz = sub { + my $line = join(",",@_); + if ($line =~ /^"(.*)"$/) + { ".byte " . join(",",unpack("C*",$1),0) . "\n.align 2"; } + else + { ""; } +}; + +sub range { + my ($r,$sfx,$start,$end) = @_; + + join(",",map("$r$_$sfx",($start..$end))); +} + +sub expand_line { + my $line = shift; + my @ret = (); + + pos($line)=0; + + while ($line =~ m/\G[^@\/\{\"]*/g) { + if ($line =~ m/\G(@|\/\/|$)/gc) { + last; + } + elsif ($line =~ m/\G\{/gc) { + my $saved_pos = pos($line); + $line =~ s/\G([rdqv])([0-9]+)([^\-]*)\-\1([0-9]+)\3/range($1,$3,$2,$4)/e; + pos($line) = $saved_pos; + $line =~ m/\G[^\}]*\}/g; + } + elsif ($line =~ m/\G\"/gc) { + $line =~ m/\G[^\"]*\"/g; + } + } + + $line =~ s/\b(\w+)/$GLOBALS{$1} or $1/ge; + + return $line; +} + +while(my $line=<>) { + + if ($line =~ m/^\s*(#|@|\/\/)/) { print $line; next; } + + $line =~ s|/\*.*\*/||; # get rid of C-style comments... + $line =~ s|^\s+||; # ... and skip white spaces in beginning... + $line =~ s|\s+$||; # ... and at the end + + { + $line =~ s|[\b\.]L(\w{2,})|L$1|g; # common denominator for Locallabel + $line =~ s|\bL(\w{2,})|\.L$1|g if ($dotinlocallabels); + } + + { + $line =~ s|(^[\.\w]+)\:\s*||; + my $label = $1; + if ($label) { + printf "%s:",($GLOBALS{$label} or $label); + } + } + + if ($line !~ m/^[#@]/) { + $line =~ s|^\s*(\.?)(\S+)\s*||; + my $c = $1; $c = "\t" if ($c eq ""); + my $mnemonic = $2; + my $opcode; + if ($mnemonic =~ m/([^\.]+)\.([^\.]+)/) { + $opcode = eval("\$$1_$2"); + } else { + $opcode = eval("\$$mnemonic"); + } + + my $arg=expand_line($line); + + if (ref($opcode) eq 'CODE') { + $line = &$opcode($arg); + } elsif ($mnemonic) { + $line = $c.$mnemonic; + $line.= "\t$arg" if ($arg ne ""); + } + } + + print $line if ($line); + print "\n"; +} + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/cbc.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/cbc.pl new file mode 100644 index 000000000..01bafe457 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/cbc.pl @@ -0,0 +1,356 @@ +#! /usr/bin/env perl +# Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# void des_ncbc_encrypt(input, output, length, schedule, ivec, enc) +# des_cblock (*input); +# des_cblock (*output); +# long length; +# des_key_schedule schedule; +# des_cblock (*ivec); +# int enc; +# +# calls +# des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); +# + +#&cbc("des_ncbc_encrypt","des_encrypt",0); +#&cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt", +# 1,4,5,3,5,-1); +#&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt", +# 0,4,5,3,5,-1); +#&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3", +# 0,6,7,3,4,5); +# +# When doing a cipher that needs bigendian order, +# for encrypt, the iv is kept in bigendian form, +# while for decrypt, it is kept in little endian. +sub cbc + { + local($name,$enc_func,$dec_func,$swap,$iv_off,$enc_off,$p1,$p2,$p3)=@_; + # name is the function name + # enc_func and dec_func and the functions to call for encrypt/decrypt + # swap is true if byte order needs to be reversed + # iv_off is parameter number for the iv + # enc_off is parameter number for the encrypt/decrypt flag + # p1,p2,p3 are the offsets for parameters to be passed to the + # underlying calls. + + &function_begin_B($name,""); + &comment(""); + + $in="esi"; + $out="edi"; + $count="ebp"; + + &push("ebp"); + &push("ebx"); + &push("esi"); + &push("edi"); + + $data_off=4; + $data_off+=4 if ($p1 > 0); + $data_off+=4 if ($p2 > 0); + $data_off+=4 if ($p3 > 0); + + &mov($count, &wparam(2)); # length + + &comment("getting iv ptr from parameter $iv_off"); + &mov("ebx", &wparam($iv_off)); # Get iv ptr + + &mov($in, &DWP(0,"ebx","",0));# iv[0] + &mov($out, &DWP(4,"ebx","",0));# iv[1] + + &push($out); + &push($in); + &push($out); # used in decrypt for iv[1] + &push($in); # used in decrypt for iv[0] + + &mov("ebx", "esp"); # This is the address of tin[2] + + &mov($in, &wparam(0)); # in + &mov($out, &wparam(1)); # out + + # We have loaded them all, how lets push things + &comment("getting encrypt flag from parameter $enc_off"); + &mov("ecx", &wparam($enc_off)); # Get enc flag + if ($p3 > 0) + { + &comment("get and push parameter $p3"); + if ($enc_off != $p3) + { &mov("eax", &wparam($p3)); &push("eax"); } + else { &push("ecx"); } + } + if ($p2 > 0) + { + &comment("get and push parameter $p2"); + if ($enc_off != $p2) + { &mov("eax", &wparam($p2)); &push("eax"); } + else { &push("ecx"); } + } + if ($p1 > 0) + { + &comment("get and push parameter $p1"); + if ($enc_off != $p1) + { &mov("eax", &wparam($p1)); &push("eax"); } + else { &push("ecx"); } + } + &push("ebx"); # push data/iv + + &cmp("ecx",0); + &jz(&label("decrypt")); + + &and($count,0xfffffff8); + &mov("eax", &DWP($data_off,"esp","",0)); # load iv[0] + &mov("ebx", &DWP($data_off+4,"esp","",0)); # load iv[1] + + &jz(&label("encrypt_finish")); + + ############################################################# + + &set_label("encrypt_loop"); + # encrypt start + # "eax" and "ebx" hold iv (or the last cipher text) + + &mov("ecx", &DWP(0,$in,"",0)); # load first 4 bytes + &mov("edx", &DWP(4,$in,"",0)); # second 4 bytes + + &xor("eax", "ecx"); + &xor("ebx", "edx"); + + &bswap("eax") if $swap; + &bswap("ebx") if $swap; + + &mov(&DWP($data_off,"esp","",0), "eax"); # put in array for call + &mov(&DWP($data_off+4,"esp","",0), "ebx"); # + + &call($enc_func); + + &mov("eax", &DWP($data_off,"esp","",0)); + &mov("ebx", &DWP($data_off+4,"esp","",0)); + + &bswap("eax") if $swap; + &bswap("ebx") if $swap; + + &mov(&DWP(0,$out,"",0),"eax"); + &mov(&DWP(4,$out,"",0),"ebx"); + + # eax and ebx are the next iv. + + &add($in, 8); + &add($out, 8); + + &sub($count, 8); + &jnz(&label("encrypt_loop")); + +###################################################################3 + &set_label("encrypt_finish"); + &mov($count, &wparam(2)); # length + &and($count, 7); + &jz(&label("finish")); + &call(&label("PIC_point")); +&set_label("PIC_point"); + &blindpop("edx"); + &lea("ecx",&DWP(&label("cbc_enc_jmp_table")."-".&label("PIC_point"),"edx")); + &mov($count,&DWP(0,"ecx",$count,4)); + &add($count,"edx"); + &xor("ecx","ecx"); + &xor("edx","edx"); + #&mov($count,&DWP(&label("cbc_enc_jmp_table"),"",$count,4)); + &jmp_ptr($count); + +&set_label("ej7"); + &movb(&HB("edx"), &BP(6,$in,"",0)); + &shl("edx",8); +&set_label("ej6"); + &movb(&HB("edx"), &BP(5,$in,"",0)); +&set_label("ej5"); + &movb(&LB("edx"), &BP(4,$in,"",0)); +&set_label("ej4"); + &mov("ecx", &DWP(0,$in,"",0)); + &jmp(&label("ejend")); +&set_label("ej3"); + &movb(&HB("ecx"), &BP(2,$in,"",0)); + &shl("ecx",8); +&set_label("ej2"); + &movb(&HB("ecx"), &BP(1,$in,"",0)); +&set_label("ej1"); + &movb(&LB("ecx"), &BP(0,$in,"",0)); +&set_label("ejend"); + + &xor("eax", "ecx"); + &xor("ebx", "edx"); + + &bswap("eax") if $swap; + &bswap("ebx") if $swap; + + &mov(&DWP($data_off,"esp","",0), "eax"); # put in array for call + &mov(&DWP($data_off+4,"esp","",0), "ebx"); # + + &call($enc_func); + + &mov("eax", &DWP($data_off,"esp","",0)); + &mov("ebx", &DWP($data_off+4,"esp","",0)); + + &bswap("eax") if $swap; + &bswap("ebx") if $swap; + + &mov(&DWP(0,$out,"",0),"eax"); + &mov(&DWP(4,$out,"",0),"ebx"); + + &jmp(&label("finish")); + + ############################################################# + ############################################################# + &set_label("decrypt",1); + # decrypt start + &and($count,0xfffffff8); + # The next 2 instructions are only for if the jz is taken + &mov("eax", &DWP($data_off+8,"esp","",0)); # get iv[0] + &mov("ebx", &DWP($data_off+12,"esp","",0)); # get iv[1] + &jz(&label("decrypt_finish")); + + &set_label("decrypt_loop"); + &mov("eax", &DWP(0,$in,"",0)); # load first 4 bytes + &mov("ebx", &DWP(4,$in,"",0)); # second 4 bytes + + &bswap("eax") if $swap; + &bswap("ebx") if $swap; + + &mov(&DWP($data_off,"esp","",0), "eax"); # put back + &mov(&DWP($data_off+4,"esp","",0), "ebx"); # + + &call($dec_func); + + &mov("eax", &DWP($data_off,"esp","",0)); # get return + &mov("ebx", &DWP($data_off+4,"esp","",0)); # + + &bswap("eax") if $swap; + &bswap("ebx") if $swap; + + &mov("ecx", &DWP($data_off+8,"esp","",0)); # get iv[0] + &mov("edx", &DWP($data_off+12,"esp","",0)); # get iv[1] + + &xor("ecx", "eax"); + &xor("edx", "ebx"); + + &mov("eax", &DWP(0,$in,"",0)); # get old cipher text, + &mov("ebx", &DWP(4,$in,"",0)); # next iv actually + + &mov(&DWP(0,$out,"",0),"ecx"); + &mov(&DWP(4,$out,"",0),"edx"); + + &mov(&DWP($data_off+8,"esp","",0), "eax"); # save iv + &mov(&DWP($data_off+12,"esp","",0), "ebx"); # + + &add($in, 8); + &add($out, 8); + + &sub($count, 8); + &jnz(&label("decrypt_loop")); +############################ ENDIT #######################3 + &set_label("decrypt_finish"); + &mov($count, &wparam(2)); # length + &and($count, 7); + &jz(&label("finish")); + + &mov("eax", &DWP(0,$in,"",0)); # load first 4 bytes + &mov("ebx", &DWP(4,$in,"",0)); # second 4 bytes + + &bswap("eax") if $swap; + &bswap("ebx") if $swap; + + &mov(&DWP($data_off,"esp","",0), "eax"); # put back + &mov(&DWP($data_off+4,"esp","",0), "ebx"); # + + &call($dec_func); + + &mov("eax", &DWP($data_off,"esp","",0)); # get return + &mov("ebx", &DWP($data_off+4,"esp","",0)); # + + &bswap("eax") if $swap; + &bswap("ebx") if $swap; + + &mov("ecx", &DWP($data_off+8,"esp","",0)); # get iv[0] + &mov("edx", &DWP($data_off+12,"esp","",0)); # get iv[1] + + &xor("ecx", "eax"); + &xor("edx", "ebx"); + + # this is for when we exit + &mov("eax", &DWP(0,$in,"",0)); # get old cipher text, + &mov("ebx", &DWP(4,$in,"",0)); # next iv actually + +&set_label("dj7"); + &rotr("edx", 16); + &movb(&BP(6,$out,"",0), &LB("edx")); + &shr("edx",16); +&set_label("dj6"); + &movb(&BP(5,$out,"",0), &HB("edx")); +&set_label("dj5"); + &movb(&BP(4,$out,"",0), &LB("edx")); +&set_label("dj4"); + &mov(&DWP(0,$out,"",0), "ecx"); + &jmp(&label("djend")); +&set_label("dj3"); + &rotr("ecx", 16); + &movb(&BP(2,$out,"",0), &LB("ecx")); + &shl("ecx",16); +&set_label("dj2"); + &movb(&BP(1,$in,"",0), &HB("ecx")); +&set_label("dj1"); + &movb(&BP(0,$in,"",0), &LB("ecx")); +&set_label("djend"); + + # final iv is still in eax:ebx + &jmp(&label("finish")); + + +############################ FINISH #######################3 + &set_label("finish",1); + &mov("ecx", &wparam($iv_off)); # Get iv ptr + + ################################################# + $total=16+4; + $total+=4 if ($p1 > 0); + $total+=4 if ($p2 > 0); + $total+=4 if ($p3 > 0); + &add("esp",$total); + + &mov(&DWP(0,"ecx","",0), "eax"); # save iv + &mov(&DWP(4,"ecx","",0), "ebx"); # save iv + + &function_end_A($name); + + &align(64); + &set_label("cbc_enc_jmp_table"); + &data_word("0"); + &data_word(&label("ej1")."-".&label("PIC_point")); + &data_word(&label("ej2")."-".&label("PIC_point")); + &data_word(&label("ej3")."-".&label("PIC_point")); + &data_word(&label("ej4")."-".&label("PIC_point")); + &data_word(&label("ej5")."-".&label("PIC_point")); + &data_word(&label("ej6")."-".&label("PIC_point")); + &data_word(&label("ej7")."-".&label("PIC_point")); + # not used + #&set_label("cbc_dec_jmp_table",1); + #&data_word("0"); + #&data_word(&label("dj1")."-".&label("PIC_point")); + #&data_word(&label("dj2")."-".&label("PIC_point")); + #&data_word(&label("dj3")."-".&label("PIC_point")); + #&data_word(&label("dj4")."-".&label("PIC_point")); + #&data_word(&label("dj5")."-".&label("PIC_point")); + #&data_word(&label("dj6")."-".&label("PIC_point")); + #&data_word(&label("dj7")."-".&label("PIC_point")); + &align(64); + + &function_end_B($name); + + } + +1; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/ppc-xlate.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/ppc-xlate.pl new file mode 100755 index 000000000..d220c6245 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/ppc-xlate.pl @@ -0,0 +1,344 @@ +#! /usr/bin/env perl +# Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +my $flavour = shift; +my $output = shift; +open STDOUT,">$output" || die "can't open $output: $!"; + +my %GLOBALS; +my %TYPES; +my $dotinlocallabels=($flavour=~/linux/)?1:0; + +################################################################ +# directives which need special treatment on different platforms +################################################################ +my $type = sub { + my ($dir,$name,$type) = @_; + + $TYPES{$name} = $type; + if ($flavour =~ /linux/) { + $name =~ s|^\.||; + ".type $name,$type"; + } else { + ""; + } +}; +my $globl = sub { + my $junk = shift; + my $name = shift; + my $global = \$GLOBALS{$name}; + my $type = \$TYPES{$name}; + my $ret; + + $name =~ s|^\.||; + + SWITCH: for ($flavour) { + /aix/ && do { if (!$$type) { + $$type = "\@function"; + } + if ($$type =~ /function/) { + $name = ".$name"; + } + last; + }; + /osx/ && do { $name = "_$name"; + last; + }; + /linux.*(32|64le)/ + && do { $ret .= ".globl $name"; + if (!$$type) { + $ret .= "\n.type $name,\@function"; + $$type = "\@function"; + } + last; + }; + /linux.*64/ && do { $ret .= ".globl $name"; + if (!$$type) { + $ret .= "\n.type $name,\@function"; + $$type = "\@function"; + } + if ($$type =~ /function/) { + $ret .= "\n.section \".opd\",\"aw\""; + $ret .= "\n.align 3"; + $ret .= "\n$name:"; + $ret .= "\n.quad .$name,.TOC.\@tocbase,0"; + $ret .= "\n.previous"; + $name = ".$name"; + } + last; + }; + } + + $ret = ".globl $name" if (!$ret); + $$global = $name; + $ret; +}; +my $text = sub { + my $ret = ($flavour =~ /aix/) ? ".csect\t.text[PR],7" : ".text"; + $ret = ".abiversion 2\n".$ret if ($flavour =~ /linux.*64le/); + $ret; +}; +my $machine = sub { + my $junk = shift; + my $arch = shift; + if ($flavour =~ /osx/) + { $arch =~ s/\"//g; + $arch = ($flavour=~/64/) ? "ppc970-64" : "ppc970" if ($arch eq "any"); + } + ".machine $arch"; +}; +my $size = sub { + if ($flavour =~ /linux/) + { shift; + my $name = shift; + my $real = $GLOBALS{$name} ? \$GLOBALS{$name} : \$name; + my $ret = ".size $$real,.-$$real"; + $name =~ s|^\.||; + if ($$real ne $name) { + $ret .= "\n.size $name,.-$$real"; + } + $ret; + } + else + { ""; } +}; +my $asciz = sub { + shift; + my $line = join(",",@_); + if ($line =~ /^"(.*)"$/) + { ".byte " . join(",",unpack("C*",$1),0) . "\n.align 2"; } + else + { ""; } +}; +my $quad = sub { + shift; + my @ret; + my ($hi,$lo); + for (@_) { + if (/^0x([0-9a-f]*?)([0-9a-f]{1,8})$/io) + { $hi=$1?"0x$1":"0"; $lo="0x$2"; } + elsif (/^([0-9]+)$/o) + { $hi=$1>>32; $lo=$1&0xffffffff; } # error-prone with 32-bit perl + else + { $hi=undef; $lo=$_; } + + if (defined($hi)) + { push(@ret,$flavour=~/le$/o?".long\t$lo,$hi":".long\t$hi,$lo"); } + else + { push(@ret,".quad $lo"); } + } + join("\n",@ret); +}; + +################################################################ +# simplified mnemonics not handled by at least one assembler +################################################################ +my $cmplw = sub { + my $f = shift; + my $cr = 0; $cr = shift if ($#_>1); + # Some out-of-date 32-bit GNU assembler just can't handle cmplw... + ($flavour =~ /linux.*32/) ? + " .long ".sprintf "0x%x",31<<26|$cr<<23|$_[0]<<16|$_[1]<<11|64 : + " cmplw ".join(',',$cr,@_); +}; +my $bdnz = sub { + my $f = shift; + my $bo = $f=~/[\+\-]/ ? 16+9 : 16; # optional "to be taken" hint + " bc $bo,0,".shift; +} if ($flavour!~/linux/); +my $bltlr = sub { + my $f = shift; + my $bo = $f=~/\-/ ? 12+2 : 12; # optional "not to be taken" hint + ($flavour =~ /linux/) ? # GNU as doesn't allow most recent hints + " .long ".sprintf "0x%x",19<<26|$bo<<21|16<<1 : + " bclr $bo,0"; +}; +my $bnelr = sub { + my $f = shift; + my $bo = $f=~/\-/ ? 4+2 : 4; # optional "not to be taken" hint + ($flavour =~ /linux/) ? # GNU as doesn't allow most recent hints + " .long ".sprintf "0x%x",19<<26|$bo<<21|2<<16|16<<1 : + " bclr $bo,2"; +}; +my $beqlr = sub { + my $f = shift; + my $bo = $f=~/-/ ? 12+2 : 12; # optional "not to be taken" hint + ($flavour =~ /linux/) ? # GNU as doesn't allow most recent hints + " .long ".sprintf "0x%X",19<<26|$bo<<21|2<<16|16<<1 : + " bclr $bo,2"; +}; +# GNU assembler can't handle extrdi rA,rS,16,48, or when sum of last two +# arguments is 64, with "operand out of range" error. +my $extrdi = sub { + my ($f,$ra,$rs,$n,$b) = @_; + $b = ($b+$n)&63; $n = 64-$n; + " rldicl $ra,$rs,$b,$n"; +}; +my $vmr = sub { + my ($f,$vx,$vy) = @_; + " vor $vx,$vy,$vy"; +}; + +# Some ABIs specify vrsave, special-purpose register #256, as reserved +# for system use. +my $no_vrsave = ($flavour =~ /aix|linux64le/); +my $mtspr = sub { + my ($f,$idx,$ra) = @_; + if ($idx == 256 && $no_vrsave) { + " or $ra,$ra,$ra"; + } else { + " mtspr $idx,$ra"; + } +}; +my $mfspr = sub { + my ($f,$rd,$idx) = @_; + if ($idx == 256 && $no_vrsave) { + " li $rd,-1"; + } else { + " mfspr $rd,$idx"; + } +}; + +# PowerISA 2.06 stuff +sub vsxmem_op { + my ($f, $vrt, $ra, $rb, $op) = @_; + " .long ".sprintf "0x%X",(31<<26)|($vrt<<21)|($ra<<16)|($rb<<11)|($op*2+1); +} +# made-up unaligned memory reference AltiVec/VMX instructions +my $lvx_u = sub { vsxmem_op(@_, 844); }; # lxvd2x +my $stvx_u = sub { vsxmem_op(@_, 972); }; # stxvd2x +my $lvdx_u = sub { vsxmem_op(@_, 588); }; # lxsdx +my $stvdx_u = sub { vsxmem_op(@_, 716); }; # stxsdx +my $lvx_4w = sub { vsxmem_op(@_, 780); }; # lxvw4x +my $stvx_4w = sub { vsxmem_op(@_, 908); }; # stxvw4x +my $lvx_splt = sub { vsxmem_op(@_, 332); }; # lxvdsx +# VSX instruction[s] masqueraded as made-up AltiVec/VMX +my $vpermdi = sub { # xxpermdi + my ($f, $vrt, $vra, $vrb, $dm) = @_; + $dm = oct($dm) if ($dm =~ /^0/); + " .long ".sprintf "0x%X",(60<<26)|($vrt<<21)|($vra<<16)|($vrb<<11)|($dm<<8)|(10<<3)|7; +}; + +# PowerISA 2.07 stuff +sub vcrypto_op { + my ($f, $vrt, $vra, $vrb, $op) = @_; + " .long ".sprintf "0x%X",(4<<26)|($vrt<<21)|($vra<<16)|($vrb<<11)|$op; +} +sub vfour { + my ($f, $vrt, $vra, $vrb, $vrc, $op) = @_; + " .long ".sprintf "0x%X",(4<<26)|($vrt<<21)|($vra<<16)|($vrb<<11)|($vrc<<6)|$op; +}; +my $vcipher = sub { vcrypto_op(@_, 1288); }; +my $vcipherlast = sub { vcrypto_op(@_, 1289); }; +my $vncipher = sub { vcrypto_op(@_, 1352); }; +my $vncipherlast= sub { vcrypto_op(@_, 1353); }; +my $vsbox = sub { vcrypto_op(@_, 0, 1480); }; +my $vshasigmad = sub { my ($st,$six)=splice(@_,-2); vcrypto_op(@_, $st<<4|$six, 1730); }; +my $vshasigmaw = sub { my ($st,$six)=splice(@_,-2); vcrypto_op(@_, $st<<4|$six, 1666); }; +my $vpmsumb = sub { vcrypto_op(@_, 1032); }; +my $vpmsumd = sub { vcrypto_op(@_, 1224); }; +my $vpmsubh = sub { vcrypto_op(@_, 1096); }; +my $vpmsumw = sub { vcrypto_op(@_, 1160); }; +# These are not really crypto, but vcrypto_op template works +my $vaddudm = sub { vcrypto_op(@_, 192); }; +my $vadduqm = sub { vcrypto_op(@_, 256); }; +my $vmuleuw = sub { vcrypto_op(@_, 648); }; +my $vmulouw = sub { vcrypto_op(@_, 136); }; +my $vrld = sub { vcrypto_op(@_, 196); }; +my $vsld = sub { vcrypto_op(@_, 1476); }; +my $vsrd = sub { vcrypto_op(@_, 1732); }; +my $vsubudm = sub { vcrypto_op(@_, 1216); }; +my $vaddcuq = sub { vcrypto_op(@_, 320); }; +my $vaddeuqm = sub { vfour(@_,60); }; +my $vaddecuq = sub { vfour(@_,61); }; +my $vmrgew = sub { vfour(@_,0,1932); }; +my $vmrgow = sub { vfour(@_,0,1676); }; + +my $mtsle = sub { + my ($f, $arg) = @_; + " .long ".sprintf "0x%X",(31<<26)|($arg<<21)|(147*2); +}; + +# VSX instructions masqueraded as AltiVec/VMX +my $mtvrd = sub { + my ($f, $vrt, $ra) = @_; + " .long ".sprintf "0x%X",(31<<26)|($vrt<<21)|($ra<<16)|(179<<1)|1; +}; +my $mtvrwz = sub { + my ($f, $vrt, $ra) = @_; + " .long ".sprintf "0x%X",(31<<26)|($vrt<<21)|($ra<<16)|(243<<1)|1; +}; + +# PowerISA 3.0 stuff +my $maddhdu = sub { vfour(@_,49); }; +my $maddld = sub { vfour(@_,51); }; +my $darn = sub { + my ($f, $rt, $l) = @_; + " .long ".sprintf "0x%X",(31<<26)|($rt<<21)|($l<<16)|(755<<1); +}; +my $iseleq = sub { + my ($f, $rt, $ra, $rb) = @_; + " .long ".sprintf "0x%X",(31<<26)|($rt<<21)|($ra<<16)|($rb<<11)|(2<<6)|30; +}; +# VSX instruction[s] masqueraded as made-up AltiVec/VMX +my $vspltib = sub { # xxspltib + my ($f, $vrt, $imm8) = @_; + $imm8 = oct($imm8) if ($imm8 =~ /^0/); + $imm8 &= 0xff; + " .long ".sprintf "0x%X",(60<<26)|($vrt<<21)|($imm8<<11)|(360<<1)|1; +}; + +# PowerISA 3.0B stuff +my $addex = sub { + my ($f, $rt, $ra, $rb, $cy) = @_; # only cy==0 is specified in 3.0B + " .long ".sprintf "0x%X",(31<<26)|($rt<<21)|($ra<<16)|($rb<<11)|($cy<<9)|(170<<1); +}; +my $vmsumudm = sub { vfour(@_,35); }; + +while($line=<>) { + + $line =~ s|[#!;].*$||; # get rid of asm-style comments... + $line =~ s|/\*.*\*/||; # ... and C-style comments... + $line =~ s|^\s+||; # ... and skip white spaces in beginning... + $line =~ s|\s+$||; # ... and at the end + + { + $line =~ s|\.L(\w+)|L$1|g; # common denominator for Locallabel + $line =~ s|\bL(\w+)|\.L$1|g if ($dotinlocallabels); + } + + { + $line =~ s|(^[\.\w]+)\:\s*||; + my $label = $1; + if ($label) { + my $xlated = ($GLOBALS{$label} or $label); + print "$xlated:"; + if ($flavour =~ /linux.*64le/) { + if ($TYPES{$label} =~ /function/) { + printf "\n.localentry %s,0\n",$xlated; + } + } + } + } + + { + $line =~ s|^\s*(\.?)(\w+)([\.\+\-]?)\s*||; + my $c = $1; $c = "\t" if ($c eq ""); + my $mnemonic = $2; + my $f = $3; + my $opcode = eval("\$$mnemonic"); + $line =~ s/\b(c?[rf]|v|vs)([0-9]+)\b/$2/g if ($c ne "." and $flavour !~ /osx/); + if (ref($opcode) eq 'CODE') { $line = &$opcode($f,split(/,\s*/,$line)); } + elsif ($mnemonic) { $line = $c.$mnemonic.$f."\t".$line; } + } + + print $line if ($line); + print "\n"; +} + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/sparcv9_modes.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/sparcv9_modes.pl new file mode 100644 index 000000000..b9922e031 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/sparcv9_modes.pl @@ -0,0 +1,1702 @@ +#! /usr/bin/env perl +# Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# Specific modes implementations for SPARC Architecture 2011. There +# is T4 dependency though, an ASI value that is not specified in the +# Architecture Manual. But as SPARC universe is rather monocultural, +# we imply that processor capable of executing crypto instructions +# can handle the ASI in question as well. This means that we ought to +# keep eyes open when new processors emerge... +# +# As for above mentioned ASI. It's so called "block initializing +# store" which cancels "read" in "read-update-write" on cache lines. +# This is "cooperative" optimization, as it reduces overall pressure +# on memory interface. Benefits can't be observed/quantified with +# usual benchmarks, on the contrary you can notice that single-thread +# performance for parallelizable modes is ~1.5% worse for largest +# block sizes [though few percent better for not so long ones]. All +# this based on suggestions from David Miller. + +$::bias="STACK_BIAS"; +$::frame="STACK_FRAME"; +$::size_t_cc="SIZE_T_CC"; + +sub asm_init { # to be called with @ARGV as argument + for (@_) { $::abibits=64 if (/\-m64/ || /\-xarch\=v9/); } + if ($::abibits==64) { $::bias=2047; $::frame=192; $::size_t_cc="%xcc"; } + else { $::bias=0; $::frame=112; $::size_t_cc="%icc"; } +} + +# unified interface +my ($inp,$out,$len,$key,$ivec)=map("%i$_",(0..5)); +# local variables +my ($ileft,$iright,$ooff,$omask,$ivoff,$blk_init)=map("%l$_",(0..7)); + +sub alg_cbc_encrypt_implement { +my ($alg,$bits) = @_; + +$::code.=<<___; +.globl ${alg}${bits}_t4_cbc_encrypt +.align 32 +${alg}${bits}_t4_cbc_encrypt: + save %sp, -$::frame, %sp + cmp $len, 0 + be,pn $::size_t_cc, .L${bits}_cbc_enc_abort + srln $len, 0, $len ! needed on v8+, "nop" on v9 + sub $inp, $out, $blk_init ! $inp!=$out +___ +$::code.=<<___ if (!$::evp); + andcc $ivec, 7, $ivoff + alignaddr $ivec, %g0, $ivec + + ldd [$ivec + 0], %f0 ! load ivec + bz,pt %icc, 1f + ldd [$ivec + 8], %f2 + ldd [$ivec + 16], %f4 + faligndata %f0, %f2, %f0 + faligndata %f2, %f4, %f2 +1: +___ +$::code.=<<___ if ($::evp); + ld [$ivec + 0], %f0 + ld [$ivec + 4], %f1 + ld [$ivec + 8], %f2 + ld [$ivec + 12], %f3 +___ +$::code.=<<___; + prefetch [$inp], 20 + prefetch [$inp + 63], 20 + call _${alg}${bits}_load_enckey + and $inp, 7, $ileft + andn $inp, 7, $inp + sll $ileft, 3, $ileft + mov 64, $iright + mov 0xff, $omask + sub $iright, $ileft, $iright + and $out, 7, $ooff + cmp $len, 127 + movrnz $ooff, 0, $blk_init ! if ( $out&7 || + movleu $::size_t_cc, 0, $blk_init ! $len<128 || + brnz,pn $blk_init, .L${bits}cbc_enc_blk ! $inp==$out) + srl $omask, $ooff, $omask + + alignaddrl $out, %g0, $out + srlx $len, 4, $len + prefetch [$out], 22 + +.L${bits}_cbc_enc_loop: + ldx [$inp + 0], %o0 + brz,pt $ileft, 4f + ldx [$inp + 8], %o1 + + ldx [$inp + 16], %o2 + sllx %o0, $ileft, %o0 + srlx %o1, $iright, %g1 + sllx %o1, $ileft, %o1 + or %g1, %o0, %o0 + srlx %o2, $iright, %o2 + or %o2, %o1, %o1 +4: + xor %g4, %o0, %o0 ! ^= rk[0] + xor %g5, %o1, %o1 + movxtod %o0, %f12 + movxtod %o1, %f14 + + fxor %f12, %f0, %f0 ! ^= ivec + fxor %f14, %f2, %f2 + prefetch [$out + 63], 22 + prefetch [$inp + 16+63], 20 + call _${alg}${bits}_encrypt_1x + add $inp, 16, $inp + + brnz,pn $ooff, 2f + sub $len, 1, $len + + std %f0, [$out + 0] + std %f2, [$out + 8] + brnz,pt $len, .L${bits}_cbc_enc_loop + add $out, 16, $out +___ +$::code.=<<___ if ($::evp); + st %f0, [$ivec + 0] + st %f1, [$ivec + 4] + st %f2, [$ivec + 8] + st %f3, [$ivec + 12] +___ +$::code.=<<___ if (!$::evp); + brnz,pn $ivoff, 3f + nop + + std %f0, [$ivec + 0] ! write out ivec + std %f2, [$ivec + 8] +___ +$::code.=<<___; +.L${bits}_cbc_enc_abort: + ret + restore + +.align 16 +2: ldxa [$inp]0x82, %o0 ! avoid read-after-write hazard + ! and ~3x deterioration + ! in inp==out case + faligndata %f0, %f0, %f4 ! handle unaligned output + faligndata %f0, %f2, %f6 + faligndata %f2, %f2, %f8 + + stda %f4, [$out + $omask]0xc0 ! partial store + std %f6, [$out + 8] + add $out, 16, $out + orn %g0, $omask, $omask + stda %f8, [$out + $omask]0xc0 ! partial store + + brnz,pt $len, .L${bits}_cbc_enc_loop+4 + orn %g0, $omask, $omask +___ +$::code.=<<___ if ($::evp); + st %f0, [$ivec + 0] + st %f1, [$ivec + 4] + st %f2, [$ivec + 8] + st %f3, [$ivec + 12] +___ +$::code.=<<___ if (!$::evp); + brnz,pn $ivoff, 3f + nop + + std %f0, [$ivec + 0] ! write out ivec + std %f2, [$ivec + 8] + ret + restore + +.align 16 +3: alignaddrl $ivec, $ivoff, %g0 ! handle unaligned ivec + mov 0xff, $omask + srl $omask, $ivoff, $omask + faligndata %f0, %f0, %f4 + faligndata %f0, %f2, %f6 + faligndata %f2, %f2, %f8 + stda %f4, [$ivec + $omask]0xc0 + std %f6, [$ivec + 8] + add $ivec, 16, $ivec + orn %g0, $omask, $omask + stda %f8, [$ivec + $omask]0xc0 +___ +$::code.=<<___; + ret + restore + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +.align 32 +.L${bits}cbc_enc_blk: + add $out, $len, $blk_init + and $blk_init, 63, $blk_init ! tail + sub $len, $blk_init, $len + add $blk_init, 15, $blk_init ! round up to 16n + srlx $len, 4, $len + srl $blk_init, 4, $blk_init + +.L${bits}_cbc_enc_blk_loop: + ldx [$inp + 0], %o0 + brz,pt $ileft, 5f + ldx [$inp + 8], %o1 + + ldx [$inp + 16], %o2 + sllx %o0, $ileft, %o0 + srlx %o1, $iright, %g1 + sllx %o1, $ileft, %o1 + or %g1, %o0, %o0 + srlx %o2, $iright, %o2 + or %o2, %o1, %o1 +5: + xor %g4, %o0, %o0 ! ^= rk[0] + xor %g5, %o1, %o1 + movxtod %o0, %f12 + movxtod %o1, %f14 + + fxor %f12, %f0, %f0 ! ^= ivec + fxor %f14, %f2, %f2 + prefetch [$inp + 16+63], 20 + call _${alg}${bits}_encrypt_1x + add $inp, 16, $inp + sub $len, 1, $len + + stda %f0, [$out]0xe2 ! ASI_BLK_INIT, T4-specific + add $out, 8, $out + stda %f2, [$out]0xe2 ! ASI_BLK_INIT, T4-specific + brnz,pt $len, .L${bits}_cbc_enc_blk_loop + add $out, 8, $out + + membar #StoreLoad|#StoreStore + brnz,pt $blk_init, .L${bits}_cbc_enc_loop + mov $blk_init, $len +___ +$::code.=<<___ if ($::evp); + st %f0, [$ivec + 0] + st %f1, [$ivec + 4] + st %f2, [$ivec + 8] + st %f3, [$ivec + 12] +___ +$::code.=<<___ if (!$::evp); + brnz,pn $ivoff, 3b + nop + + std %f0, [$ivec + 0] ! write out ivec + std %f2, [$ivec + 8] +___ +$::code.=<<___; + ret + restore +.type ${alg}${bits}_t4_cbc_encrypt,#function +.size ${alg}${bits}_t4_cbc_encrypt,.-${alg}${bits}_t4_cbc_encrypt +___ +} + +sub alg_cbc_decrypt_implement { +my ($alg,$bits) = @_; + +$::code.=<<___; +.globl ${alg}${bits}_t4_cbc_decrypt +.align 32 +${alg}${bits}_t4_cbc_decrypt: + save %sp, -$::frame, %sp + cmp $len, 0 + be,pn $::size_t_cc, .L${bits}_cbc_dec_abort + srln $len, 0, $len ! needed on v8+, "nop" on v9 + sub $inp, $out, $blk_init ! $inp!=$out +___ +$::code.=<<___ if (!$::evp); + andcc $ivec, 7, $ivoff + alignaddr $ivec, %g0, $ivec + + ldd [$ivec + 0], %f12 ! load ivec + bz,pt %icc, 1f + ldd [$ivec + 8], %f14 + ldd [$ivec + 16], %f0 + faligndata %f12, %f14, %f12 + faligndata %f14, %f0, %f14 +1: +___ +$::code.=<<___ if ($::evp); + ld [$ivec + 0], %f12 ! load ivec + ld [$ivec + 4], %f13 + ld [$ivec + 8], %f14 + ld [$ivec + 12], %f15 +___ +$::code.=<<___; + prefetch [$inp], 20 + prefetch [$inp + 63], 20 + call _${alg}${bits}_load_deckey + and $inp, 7, $ileft + andn $inp, 7, $inp + sll $ileft, 3, $ileft + mov 64, $iright + mov 0xff, $omask + sub $iright, $ileft, $iright + and $out, 7, $ooff + cmp $len, 255 + movrnz $ooff, 0, $blk_init ! if ( $out&7 || + movleu $::size_t_cc, 0, $blk_init ! $len<256 || + brnz,pn $blk_init, .L${bits}cbc_dec_blk ! $inp==$out) + srl $omask, $ooff, $omask + + andcc $len, 16, %g0 ! is number of blocks even? + srlx $len, 4, $len + alignaddrl $out, %g0, $out + bz %icc, .L${bits}_cbc_dec_loop2x + prefetch [$out], 22 +.L${bits}_cbc_dec_loop: + ldx [$inp + 0], %o0 + brz,pt $ileft, 4f + ldx [$inp + 8], %o1 + + ldx [$inp + 16], %o2 + sllx %o0, $ileft, %o0 + srlx %o1, $iright, %g1 + sllx %o1, $ileft, %o1 + or %g1, %o0, %o0 + srlx %o2, $iright, %o2 + or %o2, %o1, %o1 +4: + xor %g4, %o0, %o2 ! ^= rk[0] + xor %g5, %o1, %o3 + movxtod %o2, %f0 + movxtod %o3, %f2 + + prefetch [$out + 63], 22 + prefetch [$inp + 16+63], 20 + call _${alg}${bits}_decrypt_1x + add $inp, 16, $inp + + fxor %f12, %f0, %f0 ! ^= ivec + fxor %f14, %f2, %f2 + movxtod %o0, %f12 + movxtod %o1, %f14 + + brnz,pn $ooff, 2f + sub $len, 1, $len + + std %f0, [$out + 0] + std %f2, [$out + 8] + brnz,pt $len, .L${bits}_cbc_dec_loop2x + add $out, 16, $out +___ +$::code.=<<___ if ($::evp); + st %f12, [$ivec + 0] + st %f13, [$ivec + 4] + st %f14, [$ivec + 8] + st %f15, [$ivec + 12] +___ +$::code.=<<___ if (!$::evp); + brnz,pn $ivoff, .L${bits}_cbc_dec_unaligned_ivec + nop + + std %f12, [$ivec + 0] ! write out ivec + std %f14, [$ivec + 8] +___ +$::code.=<<___; +.L${bits}_cbc_dec_abort: + ret + restore + +.align 16 +2: ldxa [$inp]0x82, %o0 ! avoid read-after-write hazard + ! and ~3x deterioration + ! in inp==out case + faligndata %f0, %f0, %f4 ! handle unaligned output + faligndata %f0, %f2, %f6 + faligndata %f2, %f2, %f8 + + stda %f4, [$out + $omask]0xc0 ! partial store + std %f6, [$out + 8] + add $out, 16, $out + orn %g0, $omask, $omask + stda %f8, [$out + $omask]0xc0 ! partial store + + brnz,pt $len, .L${bits}_cbc_dec_loop2x+4 + orn %g0, $omask, $omask +___ +$::code.=<<___ if ($::evp); + st %f12, [$ivec + 0] + st %f13, [$ivec + 4] + st %f14, [$ivec + 8] + st %f15, [$ivec + 12] +___ +$::code.=<<___ if (!$::evp); + brnz,pn $ivoff, .L${bits}_cbc_dec_unaligned_ivec + nop + + std %f12, [$ivec + 0] ! write out ivec + std %f14, [$ivec + 8] +___ +$::code.=<<___; + ret + restore + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +.align 32 +.L${bits}_cbc_dec_loop2x: + ldx [$inp + 0], %o0 + ldx [$inp + 8], %o1 + ldx [$inp + 16], %o2 + brz,pt $ileft, 4f + ldx [$inp + 24], %o3 + + ldx [$inp + 32], %o4 + sllx %o0, $ileft, %o0 + srlx %o1, $iright, %g1 + or %g1, %o0, %o0 + sllx %o1, $ileft, %o1 + srlx %o2, $iright, %g1 + or %g1, %o1, %o1 + sllx %o2, $ileft, %o2 + srlx %o3, $iright, %g1 + or %g1, %o2, %o2 + sllx %o3, $ileft, %o3 + srlx %o4, $iright, %o4 + or %o4, %o3, %o3 +4: + xor %g4, %o0, %o4 ! ^= rk[0] + xor %g5, %o1, %o5 + movxtod %o4, %f0 + movxtod %o5, %f2 + xor %g4, %o2, %o4 + xor %g5, %o3, %o5 + movxtod %o4, %f4 + movxtod %o5, %f6 + + prefetch [$out + 63], 22 + prefetch [$inp + 32+63], 20 + call _${alg}${bits}_decrypt_2x + add $inp, 32, $inp + + movxtod %o0, %f8 + movxtod %o1, %f10 + fxor %f12, %f0, %f0 ! ^= ivec + fxor %f14, %f2, %f2 + movxtod %o2, %f12 + movxtod %o3, %f14 + fxor %f8, %f4, %f4 + fxor %f10, %f6, %f6 + + brnz,pn $ooff, 2f + sub $len, 2, $len + + std %f0, [$out + 0] + std %f2, [$out + 8] + std %f4, [$out + 16] + std %f6, [$out + 24] + brnz,pt $len, .L${bits}_cbc_dec_loop2x + add $out, 32, $out +___ +$::code.=<<___ if ($::evp); + st %f12, [$ivec + 0] + st %f13, [$ivec + 4] + st %f14, [$ivec + 8] + st %f15, [$ivec + 12] +___ +$::code.=<<___ if (!$::evp); + brnz,pn $ivoff, .L${bits}_cbc_dec_unaligned_ivec + nop + + std %f12, [$ivec + 0] ! write out ivec + std %f14, [$ivec + 8] +___ +$::code.=<<___; + ret + restore + +.align 16 +2: ldxa [$inp]0x82, %o0 ! avoid read-after-write hazard + ! and ~3x deterioration + ! in inp==out case + faligndata %f0, %f0, %f8 ! handle unaligned output + faligndata %f0, %f2, %f0 + faligndata %f2, %f4, %f2 + faligndata %f4, %f6, %f4 + faligndata %f6, %f6, %f6 + stda %f8, [$out + $omask]0xc0 ! partial store + std %f0, [$out + 8] + std %f2, [$out + 16] + std %f4, [$out + 24] + add $out, 32, $out + orn %g0, $omask, $omask + stda %f6, [$out + $omask]0xc0 ! partial store + + brnz,pt $len, .L${bits}_cbc_dec_loop2x+4 + orn %g0, $omask, $omask +___ +$::code.=<<___ if ($::evp); + st %f12, [$ivec + 0] + st %f13, [$ivec + 4] + st %f14, [$ivec + 8] + st %f15, [$ivec + 12] +___ +$::code.=<<___ if (!$::evp); + brnz,pn $ivoff, .L${bits}_cbc_dec_unaligned_ivec + nop + + std %f12, [$ivec + 0] ! write out ivec + std %f14, [$ivec + 8] + ret + restore + +.align 16 +.L${bits}_cbc_dec_unaligned_ivec: + alignaddrl $ivec, $ivoff, %g0 ! handle unaligned ivec + mov 0xff, $omask + srl $omask, $ivoff, $omask + faligndata %f12, %f12, %f0 + faligndata %f12, %f14, %f2 + faligndata %f14, %f14, %f4 + stda %f0, [$ivec + $omask]0xc0 + std %f2, [$ivec + 8] + add $ivec, 16, $ivec + orn %g0, $omask, $omask + stda %f4, [$ivec + $omask]0xc0 +___ +$::code.=<<___; + ret + restore + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +.align 32 +.L${bits}cbc_dec_blk: + add $out, $len, $blk_init + and $blk_init, 63, $blk_init ! tail + sub $len, $blk_init, $len + add $blk_init, 15, $blk_init ! round up to 16n + srlx $len, 4, $len + srl $blk_init, 4, $blk_init + sub $len, 1, $len + add $blk_init, 1, $blk_init + +.L${bits}_cbc_dec_blk_loop2x: + ldx [$inp + 0], %o0 + ldx [$inp + 8], %o1 + ldx [$inp + 16], %o2 + brz,pt $ileft, 5f + ldx [$inp + 24], %o3 + + ldx [$inp + 32], %o4 + sllx %o0, $ileft, %o0 + srlx %o1, $iright, %g1 + or %g1, %o0, %o0 + sllx %o1, $ileft, %o1 + srlx %o2, $iright, %g1 + or %g1, %o1, %o1 + sllx %o2, $ileft, %o2 + srlx %o3, $iright, %g1 + or %g1, %o2, %o2 + sllx %o3, $ileft, %o3 + srlx %o4, $iright, %o4 + or %o4, %o3, %o3 +5: + xor %g4, %o0, %o4 ! ^= rk[0] + xor %g5, %o1, %o5 + movxtod %o4, %f0 + movxtod %o5, %f2 + xor %g4, %o2, %o4 + xor %g5, %o3, %o5 + movxtod %o4, %f4 + movxtod %o5, %f6 + + prefetch [$inp + 32+63], 20 + call _${alg}${bits}_decrypt_2x + add $inp, 32, $inp + subcc $len, 2, $len + + movxtod %o0, %f8 + movxtod %o1, %f10 + fxor %f12, %f0, %f0 ! ^= ivec + fxor %f14, %f2, %f2 + movxtod %o2, %f12 + movxtod %o3, %f14 + fxor %f8, %f4, %f4 + fxor %f10, %f6, %f6 + + stda %f0, [$out]0xe2 ! ASI_BLK_INIT, T4-specific + add $out, 8, $out + stda %f2, [$out]0xe2 ! ASI_BLK_INIT, T4-specific + add $out, 8, $out + stda %f4, [$out]0xe2 ! ASI_BLK_INIT, T4-specific + add $out, 8, $out + stda %f6, [$out]0xe2 ! ASI_BLK_INIT, T4-specific + bgu,pt $::size_t_cc, .L${bits}_cbc_dec_blk_loop2x + add $out, 8, $out + + add $blk_init, $len, $len + andcc $len, 1, %g0 ! is number of blocks even? + membar #StoreLoad|#StoreStore + bnz,pt %icc, .L${bits}_cbc_dec_loop + srl $len, 0, $len + brnz,pn $len, .L${bits}_cbc_dec_loop2x + nop +___ +$::code.=<<___ if ($::evp); + st %f12, [$ivec + 0] ! write out ivec + st %f13, [$ivec + 4] + st %f14, [$ivec + 8] + st %f15, [$ivec + 12] +___ +$::code.=<<___ if (!$::evp); + brnz,pn $ivoff, 3b + nop + + std %f12, [$ivec + 0] ! write out ivec + std %f14, [$ivec + 8] +___ +$::code.=<<___; + ret + restore +.type ${alg}${bits}_t4_cbc_decrypt,#function +.size ${alg}${bits}_t4_cbc_decrypt,.-${alg}${bits}_t4_cbc_decrypt +___ +} + +sub alg_ctr32_implement { +my ($alg,$bits) = @_; + +$::code.=<<___; +.globl ${alg}${bits}_t4_ctr32_encrypt +.align 32 +${alg}${bits}_t4_ctr32_encrypt: + save %sp, -$::frame, %sp + srln $len, 0, $len ! needed on v8+, "nop" on v9 + + prefetch [$inp], 20 + prefetch [$inp + 63], 20 + call _${alg}${bits}_load_enckey + sllx $len, 4, $len + + ld [$ivec + 0], %l4 ! counter + ld [$ivec + 4], %l5 + ld [$ivec + 8], %l6 + ld [$ivec + 12], %l7 + + sllx %l4, 32, %o5 + or %l5, %o5, %o5 + sllx %l6, 32, %g1 + xor %o5, %g4, %g4 ! ^= rk[0] + xor %g1, %g5, %g5 + movxtod %g4, %f14 ! most significant 64 bits + + sub $inp, $out, $blk_init ! $inp!=$out + and $inp, 7, $ileft + andn $inp, 7, $inp + sll $ileft, 3, $ileft + mov 64, $iright + mov 0xff, $omask + sub $iright, $ileft, $iright + and $out, 7, $ooff + cmp $len, 255 + movrnz $ooff, 0, $blk_init ! if ( $out&7 || + movleu $::size_t_cc, 0, $blk_init ! $len<256 || + brnz,pn $blk_init, .L${bits}_ctr32_blk ! $inp==$out) + srl $omask, $ooff, $omask + + andcc $len, 16, %g0 ! is number of blocks even? + alignaddrl $out, %g0, $out + bz %icc, .L${bits}_ctr32_loop2x + srlx $len, 4, $len +.L${bits}_ctr32_loop: + ldx [$inp + 0], %o0 + brz,pt $ileft, 4f + ldx [$inp + 8], %o1 + + ldx [$inp + 16], %o2 + sllx %o0, $ileft, %o0 + srlx %o1, $iright, %g1 + sllx %o1, $ileft, %o1 + or %g1, %o0, %o0 + srlx %o2, $iright, %o2 + or %o2, %o1, %o1 +4: + xor %g5, %l7, %g1 ! ^= rk[0] + add %l7, 1, %l7 + movxtod %g1, %f2 + srl %l7, 0, %l7 ! clruw + prefetch [$out + 63], 22 + prefetch [$inp + 16+63], 20 +___ +$::code.=<<___ if ($alg eq "aes"); + aes_eround01 %f16, %f14, %f2, %f4 + aes_eround23 %f18, %f14, %f2, %f2 +___ +$::code.=<<___ if ($alg eq "cmll"); + camellia_f %f16, %f2, %f14, %f2 + camellia_f %f18, %f14, %f2, %f0 +___ +$::code.=<<___; + call _${alg}${bits}_encrypt_1x+8 + add $inp, 16, $inp + + movxtod %o0, %f10 + movxtod %o1, %f12 + fxor %f10, %f0, %f0 ! ^= inp + fxor %f12, %f2, %f2 + + brnz,pn $ooff, 2f + sub $len, 1, $len + + std %f0, [$out + 0] + std %f2, [$out + 8] + brnz,pt $len, .L${bits}_ctr32_loop2x + add $out, 16, $out + + ret + restore + +.align 16 +2: ldxa [$inp]0x82, %o0 ! avoid read-after-write hazard + ! and ~3x deterioration + ! in inp==out case + faligndata %f0, %f0, %f4 ! handle unaligned output + faligndata %f0, %f2, %f6 + faligndata %f2, %f2, %f8 + stda %f4, [$out + $omask]0xc0 ! partial store + std %f6, [$out + 8] + add $out, 16, $out + orn %g0, $omask, $omask + stda %f8, [$out + $omask]0xc0 ! partial store + + brnz,pt $len, .L${bits}_ctr32_loop2x+4 + orn %g0, $omask, $omask + + ret + restore + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +.align 32 +.L${bits}_ctr32_loop2x: + ldx [$inp + 0], %o0 + ldx [$inp + 8], %o1 + ldx [$inp + 16], %o2 + brz,pt $ileft, 4f + ldx [$inp + 24], %o3 + + ldx [$inp + 32], %o4 + sllx %o0, $ileft, %o0 + srlx %o1, $iright, %g1 + or %g1, %o0, %o0 + sllx %o1, $ileft, %o1 + srlx %o2, $iright, %g1 + or %g1, %o1, %o1 + sllx %o2, $ileft, %o2 + srlx %o3, $iright, %g1 + or %g1, %o2, %o2 + sllx %o3, $ileft, %o3 + srlx %o4, $iright, %o4 + or %o4, %o3, %o3 +4: + xor %g5, %l7, %g1 ! ^= rk[0] + add %l7, 1, %l7 + movxtod %g1, %f2 + srl %l7, 0, %l7 ! clruw + xor %g5, %l7, %g1 + add %l7, 1, %l7 + movxtod %g1, %f6 + srl %l7, 0, %l7 ! clruw + prefetch [$out + 63], 22 + prefetch [$inp + 32+63], 20 +___ +$::code.=<<___ if ($alg eq "aes"); + aes_eround01 %f16, %f14, %f2, %f8 + aes_eround23 %f18, %f14, %f2, %f2 + aes_eround01 %f16, %f14, %f6, %f10 + aes_eround23 %f18, %f14, %f6, %f6 +___ +$::code.=<<___ if ($alg eq "cmll"); + camellia_f %f16, %f2, %f14, %f2 + camellia_f %f16, %f6, %f14, %f6 + camellia_f %f18, %f14, %f2, %f0 + camellia_f %f18, %f14, %f6, %f4 +___ +$::code.=<<___; + call _${alg}${bits}_encrypt_2x+16 + add $inp, 32, $inp + + movxtod %o0, %f8 + movxtod %o1, %f10 + movxtod %o2, %f12 + fxor %f8, %f0, %f0 ! ^= inp + movxtod %o3, %f8 + fxor %f10, %f2, %f2 + fxor %f12, %f4, %f4 + fxor %f8, %f6, %f6 + + brnz,pn $ooff, 2f + sub $len, 2, $len + + std %f0, [$out + 0] + std %f2, [$out + 8] + std %f4, [$out + 16] + std %f6, [$out + 24] + brnz,pt $len, .L${bits}_ctr32_loop2x + add $out, 32, $out + + ret + restore + +.align 16 +2: ldxa [$inp]0x82, %o0 ! avoid read-after-write hazard + ! and ~3x deterioration + ! in inp==out case + faligndata %f0, %f0, %f8 ! handle unaligned output + faligndata %f0, %f2, %f0 + faligndata %f2, %f4, %f2 + faligndata %f4, %f6, %f4 + faligndata %f6, %f6, %f6 + + stda %f8, [$out + $omask]0xc0 ! partial store + std %f0, [$out + 8] + std %f2, [$out + 16] + std %f4, [$out + 24] + add $out, 32, $out + orn %g0, $omask, $omask + stda %f6, [$out + $omask]0xc0 ! partial store + + brnz,pt $len, .L${bits}_ctr32_loop2x+4 + orn %g0, $omask, $omask + + ret + restore + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +.align 32 +.L${bits}_ctr32_blk: + add $out, $len, $blk_init + and $blk_init, 63, $blk_init ! tail + sub $len, $blk_init, $len + add $blk_init, 15, $blk_init ! round up to 16n + srlx $len, 4, $len + srl $blk_init, 4, $blk_init + sub $len, 1, $len + add $blk_init, 1, $blk_init + +.L${bits}_ctr32_blk_loop2x: + ldx [$inp + 0], %o0 + ldx [$inp + 8], %o1 + ldx [$inp + 16], %o2 + brz,pt $ileft, 5f + ldx [$inp + 24], %o3 + + ldx [$inp + 32], %o4 + sllx %o0, $ileft, %o0 + srlx %o1, $iright, %g1 + or %g1, %o0, %o0 + sllx %o1, $ileft, %o1 + srlx %o2, $iright, %g1 + or %g1, %o1, %o1 + sllx %o2, $ileft, %o2 + srlx %o3, $iright, %g1 + or %g1, %o2, %o2 + sllx %o3, $ileft, %o3 + srlx %o4, $iright, %o4 + or %o4, %o3, %o3 +5: + xor %g5, %l7, %g1 ! ^= rk[0] + add %l7, 1, %l7 + movxtod %g1, %f2 + srl %l7, 0, %l7 ! clruw + xor %g5, %l7, %g1 + add %l7, 1, %l7 + movxtod %g1, %f6 + srl %l7, 0, %l7 ! clruw + prefetch [$inp + 32+63], 20 +___ +$::code.=<<___ if ($alg eq "aes"); + aes_eround01 %f16, %f14, %f2, %f8 + aes_eround23 %f18, %f14, %f2, %f2 + aes_eround01 %f16, %f14, %f6, %f10 + aes_eround23 %f18, %f14, %f6, %f6 +___ +$::code.=<<___ if ($alg eq "cmll"); + camellia_f %f16, %f2, %f14, %f2 + camellia_f %f16, %f6, %f14, %f6 + camellia_f %f18, %f14, %f2, %f0 + camellia_f %f18, %f14, %f6, %f4 +___ +$::code.=<<___; + call _${alg}${bits}_encrypt_2x+16 + add $inp, 32, $inp + subcc $len, 2, $len + + movxtod %o0, %f8 + movxtod %o1, %f10 + movxtod %o2, %f12 + fxor %f8, %f0, %f0 ! ^= inp + movxtod %o3, %f8 + fxor %f10, %f2, %f2 + fxor %f12, %f4, %f4 + fxor %f8, %f6, %f6 + + stda %f0, [$out]0xe2 ! ASI_BLK_INIT, T4-specific + add $out, 8, $out + stda %f2, [$out]0xe2 ! ASI_BLK_INIT, T4-specific + add $out, 8, $out + stda %f4, [$out]0xe2 ! ASI_BLK_INIT, T4-specific + add $out, 8, $out + stda %f6, [$out]0xe2 ! ASI_BLK_INIT, T4-specific + bgu,pt $::size_t_cc, .L${bits}_ctr32_blk_loop2x + add $out, 8, $out + + add $blk_init, $len, $len + andcc $len, 1, %g0 ! is number of blocks even? + membar #StoreLoad|#StoreStore + bnz,pt %icc, .L${bits}_ctr32_loop + srl $len, 0, $len + brnz,pn $len, .L${bits}_ctr32_loop2x + nop + + ret + restore +.type ${alg}${bits}_t4_ctr32_encrypt,#function +.size ${alg}${bits}_t4_ctr32_encrypt,.-${alg}${bits}_t4_ctr32_encrypt +___ +} + +sub alg_xts_implement { +my ($alg,$bits,$dir) = @_; +my ($inp,$out,$len,$key1,$key2,$ivec)=map("%i$_",(0..5)); +my $rem=$ivec; + +$::code.=<<___; +.globl ${alg}${bits}_t4_xts_${dir}crypt +.align 32 +${alg}${bits}_t4_xts_${dir}crypt: + save %sp, -$::frame-16, %sp + srln $len, 0, $len ! needed on v8+, "nop" on v9 + + mov $ivec, %o0 + add %fp, $::bias-16, %o1 + call ${alg}_t4_encrypt + mov $key2, %o2 + + add %fp, $::bias-16, %l7 + ldxa [%l7]0x88, %g2 + add %fp, $::bias-8, %l7 + ldxa [%l7]0x88, %g3 ! %g3:%g2 is tweak + + sethi %hi(0x76543210), %l7 + or %l7, %lo(0x76543210), %l7 + bmask %l7, %g0, %g0 ! byte swap mask + + prefetch [$inp], 20 + prefetch [$inp + 63], 20 + call _${alg}${bits}_load_${dir}ckey + and $len, 15, $rem + and $len, -16, $len +___ +$code.=<<___ if ($dir eq "de"); + mov 0, %l7 + movrnz $rem, 16, %l7 + sub $len, %l7, $len +___ +$code.=<<___; + + sub $inp, $out, $blk_init ! $inp!=$out + and $inp, 7, $ileft + andn $inp, 7, $inp + sll $ileft, 3, $ileft + mov 64, $iright + mov 0xff, $omask + sub $iright, $ileft, $iright + and $out, 7, $ooff + cmp $len, 255 + movrnz $ooff, 0, $blk_init ! if ( $out&7 || + movleu $::size_t_cc, 0, $blk_init ! $len<256 || + brnz,pn $blk_init, .L${bits}_xts_${dir}blk ! $inp==$out) + srl $omask, $ooff, $omask + + andcc $len, 16, %g0 ! is number of blocks even? +___ +$code.=<<___ if ($dir eq "de"); + brz,pn $len, .L${bits}_xts_${dir}steal +___ +$code.=<<___; + alignaddrl $out, %g0, $out + bz %icc, .L${bits}_xts_${dir}loop2x + srlx $len, 4, $len +.L${bits}_xts_${dir}loop: + ldx [$inp + 0], %o0 + brz,pt $ileft, 4f + ldx [$inp + 8], %o1 + + ldx [$inp + 16], %o2 + sllx %o0, $ileft, %o0 + srlx %o1, $iright, %g1 + sllx %o1, $ileft, %o1 + or %g1, %o0, %o0 + srlx %o2, $iright, %o2 + or %o2, %o1, %o1 +4: + movxtod %g2, %f12 + movxtod %g3, %f14 + bshuffle %f12, %f12, %f12 + bshuffle %f14, %f14, %f14 + + xor %g4, %o0, %o0 ! ^= rk[0] + xor %g5, %o1, %o1 + movxtod %o0, %f0 + movxtod %o1, %f2 + + fxor %f12, %f0, %f0 ! ^= tweak[0] + fxor %f14, %f2, %f2 + + prefetch [$out + 63], 22 + prefetch [$inp + 16+63], 20 + call _${alg}${bits}_${dir}crypt_1x + add $inp, 16, $inp + + fxor %f12, %f0, %f0 ! ^= tweak[0] + fxor %f14, %f2, %f2 + + srax %g3, 63, %l7 ! next tweak value + addcc %g2, %g2, %g2 + and %l7, 0x87, %l7 + addxc %g3, %g3, %g3 + xor %l7, %g2, %g2 + + brnz,pn $ooff, 2f + sub $len, 1, $len + + std %f0, [$out + 0] + std %f2, [$out + 8] + brnz,pt $len, .L${bits}_xts_${dir}loop2x + add $out, 16, $out + + brnz,pn $rem, .L${bits}_xts_${dir}steal + nop + + ret + restore + +.align 16 +2: ldxa [$inp]0x82, %o0 ! avoid read-after-write hazard + ! and ~3x deterioration + ! in inp==out case + faligndata %f0, %f0, %f4 ! handle unaligned output + faligndata %f0, %f2, %f6 + faligndata %f2, %f2, %f8 + stda %f4, [$out + $omask]0xc0 ! partial store + std %f6, [$out + 8] + add $out, 16, $out + orn %g0, $omask, $omask + stda %f8, [$out + $omask]0xc0 ! partial store + + brnz,pt $len, .L${bits}_xts_${dir}loop2x+4 + orn %g0, $omask, $omask + + brnz,pn $rem, .L${bits}_xts_${dir}steal + nop + + ret + restore + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +.align 32 +.L${bits}_xts_${dir}loop2x: + ldx [$inp + 0], %o0 + ldx [$inp + 8], %o1 + ldx [$inp + 16], %o2 + brz,pt $ileft, 4f + ldx [$inp + 24], %o3 + + ldx [$inp + 32], %o4 + sllx %o0, $ileft, %o0 + srlx %o1, $iright, %g1 + or %g1, %o0, %o0 + sllx %o1, $ileft, %o1 + srlx %o2, $iright, %g1 + or %g1, %o1, %o1 + sllx %o2, $ileft, %o2 + srlx %o3, $iright, %g1 + or %g1, %o2, %o2 + sllx %o3, $ileft, %o3 + srlx %o4, $iright, %o4 + or %o4, %o3, %o3 +4: + movxtod %g2, %f12 + movxtod %g3, %f14 + bshuffle %f12, %f12, %f12 + bshuffle %f14, %f14, %f14 + + srax %g3, 63, %l7 ! next tweak value + addcc %g2, %g2, %g2 + and %l7, 0x87, %l7 + addxc %g3, %g3, %g3 + xor %l7, %g2, %g2 + + movxtod %g2, %f8 + movxtod %g3, %f10 + bshuffle %f8, %f8, %f8 + bshuffle %f10, %f10, %f10 + + xor %g4, %o0, %o0 ! ^= rk[0] + xor %g5, %o1, %o1 + xor %g4, %o2, %o2 ! ^= rk[0] + xor %g5, %o3, %o3 + movxtod %o0, %f0 + movxtod %o1, %f2 + movxtod %o2, %f4 + movxtod %o3, %f6 + + fxor %f12, %f0, %f0 ! ^= tweak[0] + fxor %f14, %f2, %f2 + fxor %f8, %f4, %f4 ! ^= tweak[0] + fxor %f10, %f6, %f6 + + prefetch [$out + 63], 22 + prefetch [$inp + 32+63], 20 + call _${alg}${bits}_${dir}crypt_2x + add $inp, 32, $inp + + movxtod %g2, %f8 + movxtod %g3, %f10 + + srax %g3, 63, %l7 ! next tweak value + addcc %g2, %g2, %g2 + and %l7, 0x87, %l7 + addxc %g3, %g3, %g3 + xor %l7, %g2, %g2 + + bshuffle %f8, %f8, %f8 + bshuffle %f10, %f10, %f10 + + fxor %f12, %f0, %f0 ! ^= tweak[0] + fxor %f14, %f2, %f2 + fxor %f8, %f4, %f4 + fxor %f10, %f6, %f6 + + brnz,pn $ooff, 2f + sub $len, 2, $len + + std %f0, [$out + 0] + std %f2, [$out + 8] + std %f4, [$out + 16] + std %f6, [$out + 24] + brnz,pt $len, .L${bits}_xts_${dir}loop2x + add $out, 32, $out + + fsrc2 %f4, %f0 + fsrc2 %f6, %f2 + brnz,pn $rem, .L${bits}_xts_${dir}steal + nop + + ret + restore + +.align 16 +2: ldxa [$inp]0x82, %o0 ! avoid read-after-write hazard + ! and ~3x deterioration + ! in inp==out case + faligndata %f0, %f0, %f8 ! handle unaligned output + faligndata %f0, %f2, %f10 + faligndata %f2, %f4, %f12 + faligndata %f4, %f6, %f14 + faligndata %f6, %f6, %f0 + + stda %f8, [$out + $omask]0xc0 ! partial store + std %f10, [$out + 8] + std %f12, [$out + 16] + std %f14, [$out + 24] + add $out, 32, $out + orn %g0, $omask, $omask + stda %f0, [$out + $omask]0xc0 ! partial store + + brnz,pt $len, .L${bits}_xts_${dir}loop2x+4 + orn %g0, $omask, $omask + + fsrc2 %f4, %f0 + fsrc2 %f6, %f2 + brnz,pn $rem, .L${bits}_xts_${dir}steal + nop + + ret + restore + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +.align 32 +.L${bits}_xts_${dir}blk: + add $out, $len, $blk_init + and $blk_init, 63, $blk_init ! tail + sub $len, $blk_init, $len + add $blk_init, 15, $blk_init ! round up to 16n + srlx $len, 4, $len + srl $blk_init, 4, $blk_init + sub $len, 1, $len + add $blk_init, 1, $blk_init + +.L${bits}_xts_${dir}blk2x: + ldx [$inp + 0], %o0 + ldx [$inp + 8], %o1 + ldx [$inp + 16], %o2 + brz,pt $ileft, 5f + ldx [$inp + 24], %o3 + + ldx [$inp + 32], %o4 + sllx %o0, $ileft, %o0 + srlx %o1, $iright, %g1 + or %g1, %o0, %o0 + sllx %o1, $ileft, %o1 + srlx %o2, $iright, %g1 + or %g1, %o1, %o1 + sllx %o2, $ileft, %o2 + srlx %o3, $iright, %g1 + or %g1, %o2, %o2 + sllx %o3, $ileft, %o3 + srlx %o4, $iright, %o4 + or %o4, %o3, %o3 +5: + movxtod %g2, %f12 + movxtod %g3, %f14 + bshuffle %f12, %f12, %f12 + bshuffle %f14, %f14, %f14 + + srax %g3, 63, %l7 ! next tweak value + addcc %g2, %g2, %g2 + and %l7, 0x87, %l7 + addxc %g3, %g3, %g3 + xor %l7, %g2, %g2 + + movxtod %g2, %f8 + movxtod %g3, %f10 + bshuffle %f8, %f8, %f8 + bshuffle %f10, %f10, %f10 + + xor %g4, %o0, %o0 ! ^= rk[0] + xor %g5, %o1, %o1 + xor %g4, %o2, %o2 ! ^= rk[0] + xor %g5, %o3, %o3 + movxtod %o0, %f0 + movxtod %o1, %f2 + movxtod %o2, %f4 + movxtod %o3, %f6 + + fxor %f12, %f0, %f0 ! ^= tweak[0] + fxor %f14, %f2, %f2 + fxor %f8, %f4, %f4 ! ^= tweak[0] + fxor %f10, %f6, %f6 + + prefetch [$inp + 32+63], 20 + call _${alg}${bits}_${dir}crypt_2x + add $inp, 32, $inp + + movxtod %g2, %f8 + movxtod %g3, %f10 + + srax %g3, 63, %l7 ! next tweak value + addcc %g2, %g2, %g2 + and %l7, 0x87, %l7 + addxc %g3, %g3, %g3 + xor %l7, %g2, %g2 + + bshuffle %f8, %f8, %f8 + bshuffle %f10, %f10, %f10 + + fxor %f12, %f0, %f0 ! ^= tweak[0] + fxor %f14, %f2, %f2 + fxor %f8, %f4, %f4 + fxor %f10, %f6, %f6 + + subcc $len, 2, $len + stda %f0, [$out]0xe2 ! ASI_BLK_INIT, T4-specific + add $out, 8, $out + stda %f2, [$out]0xe2 ! ASI_BLK_INIT, T4-specific + add $out, 8, $out + stda %f4, [$out]0xe2 ! ASI_BLK_INIT, T4-specific + add $out, 8, $out + stda %f6, [$out]0xe2 ! ASI_BLK_INIT, T4-specific + bgu,pt $::size_t_cc, .L${bits}_xts_${dir}blk2x + add $out, 8, $out + + add $blk_init, $len, $len + andcc $len, 1, %g0 ! is number of blocks even? + membar #StoreLoad|#StoreStore + bnz,pt %icc, .L${bits}_xts_${dir}loop + srl $len, 0, $len + brnz,pn $len, .L${bits}_xts_${dir}loop2x + nop + + fsrc2 %f4, %f0 + fsrc2 %f6, %f2 + brnz,pn $rem, .L${bits}_xts_${dir}steal + nop + + ret + restore +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +___ +$code.=<<___ if ($dir eq "en"); +.align 32 +.L${bits}_xts_${dir}steal: + std %f0, [%fp + $::bias-16] ! copy of output + std %f2, [%fp + $::bias-8] + + srl $ileft, 3, $ileft + add %fp, $::bias-16, %l7 + add $inp, $ileft, $inp ! original $inp+$len&-15 + add $out, $ooff, $out ! original $out+$len&-15 + mov 0, $ileft + nop ! align + +.L${bits}_xts_${dir}stealing: + ldub [$inp + $ileft], %o0 + ldub [%l7 + $ileft], %o1 + dec $rem + stb %o0, [%l7 + $ileft] + stb %o1, [$out + $ileft] + brnz $rem, .L${bits}_xts_${dir}stealing + inc $ileft + + mov %l7, $inp + sub $out, 16, $out + mov 0, $ileft + sub $out, $ooff, $out + ba .L${bits}_xts_${dir}loop ! one more time + mov 1, $len ! $rem is 0 +___ +$code.=<<___ if ($dir eq "de"); +.align 32 +.L${bits}_xts_${dir}steal: + ldx [$inp + 0], %o0 + brz,pt $ileft, 8f + ldx [$inp + 8], %o1 + + ldx [$inp + 16], %o2 + sllx %o0, $ileft, %o0 + srlx %o1, $iright, %g1 + sllx %o1, $ileft, %o1 + or %g1, %o0, %o0 + srlx %o2, $iright, %o2 + or %o2, %o1, %o1 +8: + srax %g3, 63, %l7 ! next tweak value + addcc %g2, %g2, %o2 + and %l7, 0x87, %l7 + addxc %g3, %g3, %o3 + xor %l7, %o2, %o2 + + movxtod %o2, %f12 + movxtod %o3, %f14 + bshuffle %f12, %f12, %f12 + bshuffle %f14, %f14, %f14 + + xor %g4, %o0, %o0 ! ^= rk[0] + xor %g5, %o1, %o1 + movxtod %o0, %f0 + movxtod %o1, %f2 + + fxor %f12, %f0, %f0 ! ^= tweak[0] + fxor %f14, %f2, %f2 + + call _${alg}${bits}_${dir}crypt_1x + add $inp, 16, $inp + + fxor %f12, %f0, %f0 ! ^= tweak[0] + fxor %f14, %f2, %f2 + + std %f0, [%fp + $::bias-16] + std %f2, [%fp + $::bias-8] + + srl $ileft, 3, $ileft + add %fp, $::bias-16, %l7 + add $inp, $ileft, $inp ! original $inp+$len&-15 + add $out, $ooff, $out ! original $out+$len&-15 + mov 0, $ileft + add $out, 16, $out + nop ! align + +.L${bits}_xts_${dir}stealing: + ldub [$inp + $ileft], %o0 + ldub [%l7 + $ileft], %o1 + dec $rem + stb %o0, [%l7 + $ileft] + stb %o1, [$out + $ileft] + brnz $rem, .L${bits}_xts_${dir}stealing + inc $ileft + + mov %l7, $inp + sub $out, 16, $out + mov 0, $ileft + sub $out, $ooff, $out + ba .L${bits}_xts_${dir}loop ! one more time + mov 1, $len ! $rem is 0 +___ +$code.=<<___; + ret + restore +.type ${alg}${bits}_t4_xts_${dir}crypt,#function +.size ${alg}${bits}_t4_xts_${dir}crypt,.-${alg}${bits}_t4_xts_${dir}crypt +___ +} + +# Purpose of these subroutines is to explicitly encode VIS instructions, +# so that one can compile the module without having to specify VIS +# extensions on compiler command line, e.g. -xarch=v9 vs. -xarch=v9a. +# Idea is to reserve for option to produce "universal" binary and let +# programmer detect if current CPU is VIS capable at run-time. +sub unvis { +my ($mnemonic,$rs1,$rs2,$rd)=@_; +my ($ref,$opf); +my %visopf = ( "faligndata" => 0x048, + "bshuffle" => 0x04c, + "fnot2" => 0x066, + "fxor" => 0x06c, + "fsrc2" => 0x078 ); + + $ref = "$mnemonic\t$rs1,$rs2,$rd"; + + if ($opf=$visopf{$mnemonic}) { + foreach ($rs1,$rs2,$rd) { + return $ref if (!/%f([0-9]{1,2})/); + $_=$1; + if ($1>=32) { + return $ref if ($1&1); + # re-encode for upper double register addressing + $_=($1|$1>>5)&31; + } + } + + return sprintf ".word\t0x%08x !%s", + 0x81b00000|$rd<<25|$rs1<<14|$opf<<5|$rs2, + $ref; + } else { + return $ref; + } +} + +sub unvis3 { +my ($mnemonic,$rs1,$rs2,$rd)=@_; +my %bias = ( "g" => 0, "o" => 8, "l" => 16, "i" => 24 ); +my ($ref,$opf); +my %visopf = ( "addxc" => 0x011, + "addxccc" => 0x013, + "umulxhi" => 0x016, + "alignaddr" => 0x018, + "bmask" => 0x019, + "alignaddrl" => 0x01a ); + + $ref = "$mnemonic\t$rs1,$rs2,$rd"; + + if ($opf=$visopf{$mnemonic}) { + foreach ($rs1,$rs2,$rd) { + return $ref if (!/%([goli])([0-9])/); + $_=$bias{$1}+$2; + } + + return sprintf ".word\t0x%08x !%s", + 0x81b00000|$rd<<25|$rs1<<14|$opf<<5|$rs2, + $ref; + } else { + return $ref; + } +} + +sub unaes_round { # 4-argument instructions +my ($mnemonic,$rs1,$rs2,$rs3,$rd)=@_; +my ($ref,$opf); +my %aesopf = ( "aes_eround01" => 0, + "aes_eround23" => 1, + "aes_dround01" => 2, + "aes_dround23" => 3, + "aes_eround01_l"=> 4, + "aes_eround23_l"=> 5, + "aes_dround01_l"=> 6, + "aes_dround23_l"=> 7, + "aes_kexpand1" => 8 ); + + $ref = "$mnemonic\t$rs1,$rs2,$rs3,$rd"; + + if (defined($opf=$aesopf{$mnemonic})) { + $rs3 = ($rs3 =~ /%f([0-6]*[02468])/) ? (($1|$1>>5)&31) : $rs3; + foreach ($rs1,$rs2,$rd) { + return $ref if (!/%f([0-9]{1,2})/); + $_=$1; + if ($1>=32) { + return $ref if ($1&1); + # re-encode for upper double register addressing + $_=($1|$1>>5)&31; + } + } + + return sprintf ".word\t0x%08x !%s", + 2<<30|$rd<<25|0x19<<19|$rs1<<14|$rs3<<9|$opf<<5|$rs2, + $ref; + } else { + return $ref; + } +} + +sub unaes_kexpand { # 3-argument instructions +my ($mnemonic,$rs1,$rs2,$rd)=@_; +my ($ref,$opf); +my %aesopf = ( "aes_kexpand0" => 0x130, + "aes_kexpand2" => 0x131 ); + + $ref = "$mnemonic\t$rs1,$rs2,$rd"; + + if (defined($opf=$aesopf{$mnemonic})) { + foreach ($rs1,$rs2,$rd) { + return $ref if (!/%f([0-9]{1,2})/); + $_=$1; + if ($1>=32) { + return $ref if ($1&1); + # re-encode for upper double register addressing + $_=($1|$1>>5)&31; + } + } + + return sprintf ".word\t0x%08x !%s", + 2<<30|$rd<<25|0x36<<19|$rs1<<14|$opf<<5|$rs2, + $ref; + } else { + return $ref; + } +} + +sub uncamellia_f { # 4-argument instructions +my ($mnemonic,$rs1,$rs2,$rs3,$rd)=@_; +my ($ref,$opf); + + $ref = "$mnemonic\t$rs1,$rs2,$rs3,$rd"; + + if (1) { + $rs3 = ($rs3 =~ /%f([0-6]*[02468])/) ? (($1|$1>>5)&31) : $rs3; + foreach ($rs1,$rs2,$rd) { + return $ref if (!/%f([0-9]{1,2})/); + $_=$1; + if ($1>=32) { + return $ref if ($1&1); + # re-encode for upper double register addressing + $_=($1|$1>>5)&31; + } + } + + return sprintf ".word\t0x%08x !%s", + 2<<30|$rd<<25|0x19<<19|$rs1<<14|$rs3<<9|0xc<<5|$rs2, + $ref; + } else { + return $ref; + } +} + +sub uncamellia3 { # 3-argument instructions +my ($mnemonic,$rs1,$rs2,$rd)=@_; +my ($ref,$opf); +my %cmllopf = ( "camellia_fl" => 0x13c, + "camellia_fli" => 0x13d ); + + $ref = "$mnemonic\t$rs1,$rs2,$rd"; + + if (defined($opf=$cmllopf{$mnemonic})) { + foreach ($rs1,$rs2,$rd) { + return $ref if (!/%f([0-9]{1,2})/); + $_=$1; + if ($1>=32) { + return $ref if ($1&1); + # re-encode for upper double register addressing + $_=($1|$1>>5)&31; + } + } + + return sprintf ".word\t0x%08x !%s", + 2<<30|$rd<<25|0x36<<19|$rs1<<14|$opf<<5|$rs2, + $ref; + } else { + return $ref; + } +} + +sub unmovxtox { # 2-argument instructions +my ($mnemonic,$rs,$rd)=@_; +my %bias = ( "g" => 0, "o" => 8, "l" => 16, "i" => 24, "f" => 0 ); +my ($ref,$opf); +my %movxopf = ( "movdtox" => 0x110, + "movstouw" => 0x111, + "movstosw" => 0x113, + "movxtod" => 0x118, + "movwtos" => 0x119 ); + + $ref = "$mnemonic\t$rs,$rd"; + + if (defined($opf=$movxopf{$mnemonic})) { + foreach ($rs,$rd) { + return $ref if (!/%([fgoli])([0-9]{1,2})/); + $_=$bias{$1}+$2; + if ($2>=32) { + return $ref if ($2&1); + # re-encode for upper double register addressing + $_=($2|$2>>5)&31; + } + } + + return sprintf ".word\t0x%08x !%s", + 2<<30|$rd<<25|0x36<<19|$opf<<5|$rs, + $ref; + } else { + return $ref; + } +} + +sub undes { +my ($mnemonic)=shift; +my @args=@_; +my ($ref,$opf); +my %desopf = ( "des_round" => 0b1001, + "des_ip" => 0b100110100, + "des_iip" => 0b100110101, + "des_kexpand" => 0b100110110 ); + + $ref = "$mnemonic\t".join(",",@_); + + if (defined($opf=$desopf{$mnemonic})) { # 4-arg + if ($mnemonic eq "des_round") { + foreach (@args[0..3]) { + return $ref if (!/%f([0-9]{1,2})/); + $_=$1; + if ($1>=32) { + return $ref if ($1&1); + # re-encode for upper double register addressing + $_=($1|$1>>5)&31; + } + } + return sprintf ".word\t0x%08x !%s", + 2<<30|0b011001<<19|$opf<<5|$args[0]<<14|$args[1]|$args[2]<<9|$args[3]<<25, + $ref; + } elsif ($mnemonic eq "des_kexpand") { # 3-arg + foreach (@args[0..2]) { + return $ref if (!/(%f)?([0-9]{1,2})/); + $_=$2; + if ($2>=32) { + return $ref if ($2&1); + # re-encode for upper double register addressing + $_=($2|$2>>5)&31; + } + } + return sprintf ".word\t0x%08x !%s", + 2<<30|0b110110<<19|$opf<<5|$args[0]<<14|$args[1]|$args[2]<<25, + $ref; + } else { # 2-arg + foreach (@args[0..1]) { + return $ref if (!/%f([0-9]{1,2})/); + $_=$1; + if ($1>=32) { + return $ref if ($2&1); + # re-encode for upper double register addressing + $_=($1|$1>>5)&31; + } + } + return sprintf ".word\t0x%08x !%s", + 2<<30|0b110110<<19|$opf<<5|$args[0]<<14|$args[1]<<25, + $ref; + } + } else { + return $ref; + } +} + +sub emit_assembler { + foreach (split("\n",$::code)) { + s/\`([^\`]*)\`/eval $1/ge; + + s/\b(f[a-z]+2[sd]*)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2})\s*$/$1\t%f0,$2,$3/go; + + s/\b(aes_[edk][^\s]*)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*([%fx0-9]+),\s*(%f[0-9]{1,2})/ + &unaes_round($1,$2,$3,$4,$5) + /geo or + s/\b(aes_kexpand[02])\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*(%f[0-9]{1,2})/ + &unaes_kexpand($1,$2,$3,$4) + /geo or + s/\b(camellia_f)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*([%fx0-9]+),\s*(%f[0-9]{1,2})/ + &uncamellia_f($1,$2,$3,$4,$5) + /geo or + s/\b(camellia_[^s]+)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*(%f[0-9]{1,2})/ + &uncamellia3($1,$2,$3,$4) + /geo or + s/\b(des_\w+)\s+(%f[0-9]{1,2}),\s*([%fx0-9]+)(?:,\s*(%f[0-9]{1,2})(?:,\s*(%f[0-9]{1,2}))?)?/ + &undes($1,$2,$3,$4,$5) + /geo or + s/\b(mov[ds]to\w+)\s+(%f[0-9]{1,2}),\s*(%[goli][0-7])/ + &unmovxtox($1,$2,$3) + /geo or + s/\b(mov[xw]to[ds])\s+(%[goli][0-7]),\s*(%f[0-9]{1,2})/ + &unmovxtox($1,$2,$3) + /geo or + s/\b([fb][^\s]*)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*(%f[0-9]{1,2})/ + &unvis($1,$2,$3,$4) + /geo or + s/\b(umulxhi|bmask|addxc[c]{0,2}|alignaddr[l]*)\s+(%[goli][0-7]),\s*(%[goli][0-7]),\s*(%[goli][0-7])/ + &unvis3($1,$2,$3,$4) + /geo; + + print $_,"\n"; + } +} + +1; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/x86_64-xlate.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/x86_64-xlate.pl new file mode 100755 index 000000000..29a0eacfd --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/x86_64-xlate.pl @@ -0,0 +1,1447 @@ +#! /usr/bin/env perl +# Copyright 2005-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# Ascetic x86_64 AT&T to MASM/NASM assembler translator by . +# +# Why AT&T to MASM and not vice versa? Several reasons. Because AT&T +# format is way easier to parse. Because it's simpler to "gear" from +# Unix ABI to Windows one [see cross-reference "card" at the end of +# file]. Because Linux targets were available first... +# +# In addition the script also "distills" code suitable for GNU +# assembler, so that it can be compiled with more rigid assemblers, +# such as Solaris /usr/ccs/bin/as. +# +# This translator is not designed to convert *arbitrary* assembler +# code from AT&T format to MASM one. It's designed to convert just +# enough to provide for dual-ABI OpenSSL modules development... +# There *are* limitations and you might have to modify your assembler +# code or this script to achieve the desired result... +# +# Currently recognized limitations: +# +# - can't use multiple ops per line; +# +# Dual-ABI styling rules. +# +# 1. Adhere to Unix register and stack layout [see cross-reference +# ABI "card" at the end for explanation]. +# 2. Forget about "red zone," stick to more traditional blended +# stack frame allocation. If volatile storage is actually required +# that is. If not, just leave the stack as is. +# 3. Functions tagged with ".type name,@function" get crafted with +# unified Win64 prologue and epilogue automatically. If you want +# to take care of ABI differences yourself, tag functions as +# ".type name,@abi-omnipotent" instead. +# 4. To optimize the Win64 prologue you can specify number of input +# arguments as ".type name,@function,N." Keep in mind that if N is +# larger than 6, then you *have to* write "abi-omnipotent" code, +# because >6 cases can't be addressed with unified prologue. +# 5. Name local labels as .L*, do *not* use dynamic labels such as 1: +# (sorry about latter). +# 6. Don't use [or hand-code with .byte] "rep ret." "ret" mnemonic is +# required to identify the spots, where to inject Win64 epilogue! +# But on the pros, it's then prefixed with rep automatically:-) +# 7. Stick to explicit ip-relative addressing. If you have to use +# GOTPCREL addressing, stick to mov symbol@GOTPCREL(%rip),%r??. +# Both are recognized and translated to proper Win64 addressing +# modes. +# +# 8. In order to provide for structured exception handling unified +# Win64 prologue copies %rsp value to %rax. For further details +# see SEH paragraph at the end. +# 9. .init segment is allowed to contain calls to functions only. +# a. If function accepts more than 4 arguments *and* >4th argument +# is declared as non 64-bit value, do clear its upper part. + + +use strict; + +my $flavour = shift; +my $output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +open STDOUT,">$output" || die "can't open $output: $!" + if (defined($output)); + +my $gas=1; $gas=0 if ($output =~ /\.asm$/); +my $elf=1; $elf=0 if (!$gas); +my $win64=0; +my $prefix=""; +my $decor=".L"; + +my $masmref=8 + 50727*2**-32; # 8.00.50727 shipped with VS2005 +my $masm=0; +my $PTR=" PTR"; + +my $nasmref=2.03; +my $nasm=0; + +if ($flavour eq "mingw64") { $gas=1; $elf=0; $win64=1; + $prefix=`echo __USER_LABEL_PREFIX__ | $ENV{CC} -E -P -`; + $prefix =~ s|\R$||; # Better chomp + } +elsif ($flavour eq "macosx") { $gas=1; $elf=0; $prefix="_"; $decor="L\$"; } +elsif ($flavour eq "masm") { $gas=0; $elf=0; $masm=$masmref; $win64=1; $decor="\$L\$"; } +elsif ($flavour eq "nasm") { $gas=0; $elf=0; $nasm=$nasmref; $win64=1; $decor="\$L\$"; $PTR=""; } +elsif (!$gas) +{ if ($ENV{ASM} =~ m/nasm/ && `nasm -v` =~ m/version ([0-9]+)\.([0-9]+)/i) + { $nasm = $1 + $2*0.01; $PTR=""; } + elsif (`ml64 2>&1` =~ m/Version ([0-9]+)\.([0-9]+)(\.([0-9]+))?/) + { $masm = $1 + $2*2**-16 + $4*2**-32; } + die "no assembler found on %PATH%" if (!($nasm || $masm)); + $win64=1; + $elf=0; + $decor="\$L\$"; +} + +my $current_segment; +my $current_function; +my %globals; + +{ package opcode; # pick up opcodes + sub re { + my ($class, $line) = @_; + my $self = {}; + my $ret; + + if ($$line =~ /^([a-z][a-z0-9]*)/i) { + bless $self,$class; + $self->{op} = $1; + $ret = $self; + $$line = substr($$line,@+[0]); $$line =~ s/^\s+//; + + undef $self->{sz}; + if ($self->{op} =~ /^(movz)x?([bw]).*/) { # movz is pain... + $self->{op} = $1; + $self->{sz} = $2; + } elsif ($self->{op} =~ /call|jmp/) { + $self->{sz} = ""; + } elsif ($self->{op} =~ /^p/ && $' !~ /^(ush|op|insrw)/) { # SSEn + $self->{sz} = ""; + } elsif ($self->{op} =~ /^[vk]/) { # VEX or k* such as kmov + $self->{sz} = ""; + } elsif ($self->{op} =~ /mov[dq]/ && $$line =~ /%xmm/) { + $self->{sz} = ""; + } elsif ($self->{op} =~ /([a-z]{3,})([qlwb])$/) { + $self->{op} = $1; + $self->{sz} = $2; + } + } + $ret; + } + sub size { + my ($self, $sz) = @_; + $self->{sz} = $sz if (defined($sz) && !defined($self->{sz})); + $self->{sz}; + } + sub out { + my $self = shift; + if ($gas) { + if ($self->{op} eq "movz") { # movz is pain... + sprintf "%s%s%s",$self->{op},$self->{sz},shift; + } elsif ($self->{op} =~ /^set/) { + "$self->{op}"; + } elsif ($self->{op} eq "ret") { + my $epilogue = ""; + if ($win64 && $current_function->{abi} eq "svr4") { + $epilogue = "movq 8(%rsp),%rdi\n\t" . + "movq 16(%rsp),%rsi\n\t"; + } + $epilogue . ".byte 0xf3,0xc3"; + } elsif ($self->{op} eq "call" && !$elf && $current_segment eq ".init") { + ".p2align\t3\n\t.quad"; + } else { + "$self->{op}$self->{sz}"; + } + } else { + $self->{op} =~ s/^movz/movzx/; + if ($self->{op} eq "ret") { + $self->{op} = ""; + if ($win64 && $current_function->{abi} eq "svr4") { + $self->{op} = "mov rdi,QWORD$PTR\[8+rsp\]\t;WIN64 epilogue\n\t". + "mov rsi,QWORD$PTR\[16+rsp\]\n\t"; + } + $self->{op} .= "DB\t0F3h,0C3h\t\t;repret"; + } elsif ($self->{op} =~ /^(pop|push)f/) { + $self->{op} .= $self->{sz}; + } elsif ($self->{op} eq "call" && $current_segment eq ".CRT\$XCU") { + $self->{op} = "\tDQ"; + } + $self->{op}; + } + } + sub mnemonic { + my ($self, $op) = @_; + $self->{op}=$op if (defined($op)); + $self->{op}; + } +} +{ package const; # pick up constants, which start with $ + sub re { + my ($class, $line) = @_; + my $self = {}; + my $ret; + + if ($$line =~ /^\$([^,]+)/) { + bless $self, $class; + $self->{value} = $1; + $ret = $self; + $$line = substr($$line,@+[0]); $$line =~ s/^\s+//; + } + $ret; + } + sub out { + my $self = shift; + + $self->{value} =~ s/\b(0b[0-1]+)/oct($1)/eig; + if ($gas) { + # Solaris /usr/ccs/bin/as can't handle multiplications + # in $self->{value} + my $value = $self->{value}; + no warnings; # oct might complain about overflow, ignore here... + $value =~ s/(?{value} = $value; + } + sprintf "\$%s",$self->{value}; + } else { + my $value = $self->{value}; + $value =~ s/0x([0-9a-f]+)/0$1h/ig if ($masm); + sprintf "%s",$value; + } + } +} +{ package ea; # pick up effective addresses: expr(%reg,%reg,scale) + + my %szmap = ( b=>"BYTE$PTR", w=>"WORD$PTR", + l=>"DWORD$PTR", d=>"DWORD$PTR", + q=>"QWORD$PTR", o=>"OWORD$PTR", + x=>"XMMWORD$PTR", y=>"YMMWORD$PTR", + z=>"ZMMWORD$PTR" ) if (!$gas); + + sub re { + my ($class, $line, $opcode) = @_; + my $self = {}; + my $ret; + + # optional * ----vvv--- appears in indirect jmp/call + if ($$line =~ /^(\*?)([^\(,]*)\(([%\w,]+)\)((?:{[^}]+})*)/) { + bless $self, $class; + $self->{asterisk} = $1; + $self->{label} = $2; + ($self->{base},$self->{index},$self->{scale})=split(/,/,$3); + $self->{scale} = 1 if (!defined($self->{scale})); + $self->{opmask} = $4; + $ret = $self; + $$line = substr($$line,@+[0]); $$line =~ s/^\s+//; + + if ($win64 && $self->{label} =~ s/\@GOTPCREL//) { + die if ($opcode->mnemonic() ne "mov"); + $opcode->mnemonic("lea"); + } + $self->{base} =~ s/^%//; + $self->{index} =~ s/^%// if (defined($self->{index})); + $self->{opcode} = $opcode; + } + $ret; + } + sub size {} + sub out { + my ($self, $sz) = @_; + + $self->{label} =~ s/([_a-z][_a-z0-9]*)/$globals{$1} or $1/gei; + $self->{label} =~ s/\.L/$decor/g; + + # Silently convert all EAs to 64-bit. This is required for + # elder GNU assembler and results in more compact code, + # *but* most importantly AES module depends on this feature! + $self->{index} =~ s/^[er](.?[0-9xpi])[d]?$/r\1/; + $self->{base} =~ s/^[er](.?[0-9xpi])[d]?$/r\1/; + + # Solaris /usr/ccs/bin/as can't handle multiplications + # in $self->{label}... + use integer; + $self->{label} =~ s/(?{label} =~ s/\b([0-9]+\s*[\*\/\%]\s*[0-9]+)\b/eval($1)/eg; + + # Some assemblers insist on signed presentation of 32-bit + # offsets, but sign extension is a tricky business in perl... + if ((1<<31)<<1) { + $self->{label} =~ s/\b([0-9]+)\b/$1<<32>>32/eg; + } else { + $self->{label} =~ s/\b([0-9]+)\b/$1>>0/eg; + } + + # if base register is %rbp or %r13, see if it's possible to + # flip base and index registers [for better performance] + if (!$self->{label} && $self->{index} && $self->{scale}==1 && + $self->{base} =~ /(rbp|r13)/) { + $self->{base} = $self->{index}; $self->{index} = $1; + } + + if ($gas) { + $self->{label} =~ s/^___imp_/__imp__/ if ($flavour eq "mingw64"); + + if (defined($self->{index})) { + sprintf "%s%s(%s,%%%s,%d)%s", + $self->{asterisk},$self->{label}, + $self->{base}?"%$self->{base}":"", + $self->{index},$self->{scale}, + $self->{opmask}; + } else { + sprintf "%s%s(%%%s)%s", $self->{asterisk},$self->{label}, + $self->{base},$self->{opmask}; + } + } else { + $self->{label} =~ s/\./\$/g; + $self->{label} =~ s/(?{label} = "($self->{label})" if ($self->{label} =~ /[\*\+\-\/]/); + + my $mnemonic = $self->{opcode}->mnemonic(); + ($self->{asterisk}) && ($sz="q") || + ($mnemonic =~ /^v?mov([qd])$/) && ($sz=$1) || + ($mnemonic =~ /^v?pinsr([qdwb])$/) && ($sz=$1) || + ($mnemonic =~ /^vpbroadcast([qdwb])$/) && ($sz=$1) || + ($mnemonic =~ /^v(?!perm)[a-z]+[fi]128$/) && ($sz="x"); + + $self->{opmask} =~ s/%(k[0-7])/$1/; + + if (defined($self->{index})) { + sprintf "%s[%s%s*%d%s]%s",$szmap{$sz}, + $self->{label}?"$self->{label}+":"", + $self->{index},$self->{scale}, + $self->{base}?"+$self->{base}":"", + $self->{opmask}; + } elsif ($self->{base} eq "rip") { + sprintf "%s[%s]",$szmap{$sz},$self->{label}; + } else { + sprintf "%s[%s%s]%s", $szmap{$sz}, + $self->{label}?"$self->{label}+":"", + $self->{base},$self->{opmask}; + } + } + } +} +{ package register; # pick up registers, which start with %. + sub re { + my ($class, $line, $opcode) = @_; + my $self = {}; + my $ret; + + # optional * ----vvv--- appears in indirect jmp/call + if ($$line =~ /^(\*?)%(\w+)((?:{[^}]+})*)/) { + bless $self,$class; + $self->{asterisk} = $1; + $self->{value} = $2; + $self->{opmask} = $3; + $opcode->size($self->size()); + $ret = $self; + $$line = substr($$line,@+[0]); $$line =~ s/^\s+//; + } + $ret; + } + sub size { + my $self = shift; + my $ret; + + if ($self->{value} =~ /^r[\d]+b$/i) { $ret="b"; } + elsif ($self->{value} =~ /^r[\d]+w$/i) { $ret="w"; } + elsif ($self->{value} =~ /^r[\d]+d$/i) { $ret="l"; } + elsif ($self->{value} =~ /^r[\w]+$/i) { $ret="q"; } + elsif ($self->{value} =~ /^[a-d][hl]$/i){ $ret="b"; } + elsif ($self->{value} =~ /^[\w]{2}l$/i) { $ret="b"; } + elsif ($self->{value} =~ /^[\w]{2}$/i) { $ret="w"; } + elsif ($self->{value} =~ /^e[a-z]{2}$/i){ $ret="l"; } + + $ret; + } + sub out { + my $self = shift; + if ($gas) { sprintf "%s%%%s%s", $self->{asterisk}, + $self->{value}, + $self->{opmask}; } + else { $self->{opmask} =~ s/%(k[0-7])/$1/; + $self->{value}.$self->{opmask}; } + } +} +{ package label; # pick up labels, which end with : + sub re { + my ($class, $line) = @_; + my $self = {}; + my $ret; + + if ($$line =~ /(^[\.\w]+)\:/) { + bless $self,$class; + $self->{value} = $1; + $ret = $self; + $$line = substr($$line,@+[0]); $$line =~ s/^\s+//; + + $self->{value} =~ s/^\.L/$decor/; + } + $ret; + } + sub out { + my $self = shift; + + if ($gas) { + my $func = ($globals{$self->{value}} or $self->{value}) . ":"; + if ($win64 && $current_function->{name} eq $self->{value} + && $current_function->{abi} eq "svr4") { + $func .= "\n"; + $func .= " movq %rdi,8(%rsp)\n"; + $func .= " movq %rsi,16(%rsp)\n"; + $func .= " movq %rsp,%rax\n"; + $func .= "${decor}SEH_begin_$current_function->{name}:\n"; + my $narg = $current_function->{narg}; + $narg=6 if (!defined($narg)); + $func .= " movq %rcx,%rdi\n" if ($narg>0); + $func .= " movq %rdx,%rsi\n" if ($narg>1); + $func .= " movq %r8,%rdx\n" if ($narg>2); + $func .= " movq %r9,%rcx\n" if ($narg>3); + $func .= " movq 40(%rsp),%r8\n" if ($narg>4); + $func .= " movq 48(%rsp),%r9\n" if ($narg>5); + } + $func; + } elsif ($self->{value} ne "$current_function->{name}") { + # Make all labels in masm global. + $self->{value} .= ":" if ($masm); + $self->{value} . ":"; + } elsif ($win64 && $current_function->{abi} eq "svr4") { + my $func = "$current_function->{name}" . + ($nasm ? ":" : "\tPROC $current_function->{scope}") . + "\n"; + $func .= " mov QWORD$PTR\[8+rsp\],rdi\t;WIN64 prologue\n"; + $func .= " mov QWORD$PTR\[16+rsp\],rsi\n"; + $func .= " mov rax,rsp\n"; + $func .= "${decor}SEH_begin_$current_function->{name}:"; + $func .= ":" if ($masm); + $func .= "\n"; + my $narg = $current_function->{narg}; + $narg=6 if (!defined($narg)); + $func .= " mov rdi,rcx\n" if ($narg>0); + $func .= " mov rsi,rdx\n" if ($narg>1); + $func .= " mov rdx,r8\n" if ($narg>2); + $func .= " mov rcx,r9\n" if ($narg>3); + $func .= " mov r8,QWORD$PTR\[40+rsp\]\n" if ($narg>4); + $func .= " mov r9,QWORD$PTR\[48+rsp\]\n" if ($narg>5); + $func .= "\n"; + } else { + "$current_function->{name}". + ($nasm ? ":" : "\tPROC $current_function->{scope}"); + } + } +} +{ package expr; # pick up expressions + sub re { + my ($class, $line, $opcode) = @_; + my $self = {}; + my $ret; + + if ($$line =~ /(^[^,]+)/) { + bless $self,$class; + $self->{value} = $1; + $ret = $self; + $$line = substr($$line,@+[0]); $$line =~ s/^\s+//; + + $self->{value} =~ s/\@PLT// if (!$elf); + $self->{value} =~ s/([_a-z][_a-z0-9]*)/$globals{$1} or $1/gei; + $self->{value} =~ s/\.L/$decor/g; + $self->{opcode} = $opcode; + } + $ret; + } + sub out { + my $self = shift; + if ($nasm && $self->{opcode}->mnemonic()=~m/^j(?![re]cxz)/) { + "NEAR ".$self->{value}; + } else { + $self->{value}; + } + } +} +{ package cfi_directive; + # CFI directives annotate instructions that are significant for + # stack unwinding procedure compliant with DWARF specification, + # see http://dwarfstd.org/. Besides naturally expected for this + # script platform-specific filtering function, this module adds + # three auxiliary synthetic directives not recognized by [GNU] + # assembler: + # + # - .cfi_push to annotate push instructions in prologue, which + # translates to .cfi_adjust_cfa_offset (if needed) and + # .cfi_offset; + # - .cfi_pop to annotate pop instructions in epilogue, which + # translates to .cfi_adjust_cfa_offset (if needed) and + # .cfi_restore; + # - [and most notably] .cfi_cfa_expression which encodes + # DW_CFA_def_cfa_expression and passes it to .cfi_escape as + # byte vector; + # + # CFA expressions were introduced in DWARF specification version + # 3 and describe how to deduce CFA, Canonical Frame Address. This + # becomes handy if your stack frame is variable and you can't + # spare register for [previous] frame pointer. Suggested directive + # syntax is made-up mix of DWARF operator suffixes [subset of] + # and references to registers with optional bias. Following example + # describes offloaded *original* stack pointer at specific offset + # from *current* stack pointer: + # + # .cfi_cfa_expression %rsp+40,deref,+8 + # + # Final +8 has everything to do with the fact that CFA is defined + # as reference to top of caller's stack, and on x86_64 call to + # subroutine pushes 8-byte return address. In other words original + # stack pointer upon entry to a subroutine is 8 bytes off from CFA. + + # Below constants are taken from "DWARF Expressions" section of the + # DWARF specification, section is numbered 7.7 in versions 3 and 4. + my %DW_OP_simple = ( # no-arg operators, mapped directly + deref => 0x06, dup => 0x12, + drop => 0x13, over => 0x14, + pick => 0x15, swap => 0x16, + rot => 0x17, xderef => 0x18, + + abs => 0x19, and => 0x1a, + div => 0x1b, minus => 0x1c, + mod => 0x1d, mul => 0x1e, + neg => 0x1f, not => 0x20, + or => 0x21, plus => 0x22, + shl => 0x24, shr => 0x25, + shra => 0x26, xor => 0x27, + ); + + my %DW_OP_complex = ( # used in specific subroutines + constu => 0x10, # uleb128 + consts => 0x11, # sleb128 + plus_uconst => 0x23, # uleb128 + lit0 => 0x30, # add 0-31 to opcode + reg0 => 0x50, # add 0-31 to opcode + breg0 => 0x70, # add 0-31 to opcole, sleb128 + regx => 0x90, # uleb28 + fbreg => 0x91, # sleb128 + bregx => 0x92, # uleb128, sleb128 + piece => 0x93, # uleb128 + ); + + # Following constants are defined in x86_64 ABI supplement, for + # example available at https://www.uclibc.org/docs/psABI-x86_64.pdf, + # see section 3.7 "Stack Unwind Algorithm". + my %DW_reg_idx = ( + "%rax"=>0, "%rdx"=>1, "%rcx"=>2, "%rbx"=>3, + "%rsi"=>4, "%rdi"=>5, "%rbp"=>6, "%rsp"=>7, + "%r8" =>8, "%r9" =>9, "%r10"=>10, "%r11"=>11, + "%r12"=>12, "%r13"=>13, "%r14"=>14, "%r15"=>15 + ); + + my ($cfa_reg, $cfa_rsp); + my @cfa_stack; + + # [us]leb128 format is variable-length integer representation base + # 2^128, with most significant bit of each byte being 0 denoting + # *last* most significant digit. See "Variable Length Data" in the + # DWARF specification, numbered 7.6 at least in versions 3 and 4. + sub sleb128 { + use integer; # get right shift extend sign + + my $val = shift; + my $sign = ($val < 0) ? -1 : 0; + my @ret = (); + + while(1) { + push @ret, $val&0x7f; + + # see if remaining bits are same and equal to most + # significant bit of the current digit, if so, it's + # last digit... + last if (($val>>6) == $sign); + + @ret[-1] |= 0x80; + $val >>= 7; + } + + return @ret; + } + sub uleb128 { + my $val = shift; + my @ret = (); + + while(1) { + push @ret, $val&0x7f; + + # see if it's last significant digit... + last if (($val >>= 7) == 0); + + @ret[-1] |= 0x80; + } + + return @ret; + } + sub const { + my $val = shift; + + if ($val >= 0 && $val < 32) { + return ($DW_OP_complex{lit0}+$val); + } + return ($DW_OP_complex{consts}, sleb128($val)); + } + sub reg { + my $val = shift; + + return if ($val !~ m/^(%r\w+)(?:([\+\-])((?:0x)?[0-9a-f]+))?/); + + my $reg = $DW_reg_idx{$1}; + my $off = eval ("0 $2 $3"); + + return (($DW_OP_complex{breg0} + $reg), sleb128($off)); + # Yes, we use DW_OP_bregX+0 to push register value and not + # DW_OP_regX, because latter would require even DW_OP_piece, + # which would be a waste under the circumstances. If you have + # to use DWP_OP_reg, use "regx:N"... + } + sub cfa_expression { + my $line = shift; + my @ret; + + foreach my $token (split(/,\s*/,$line)) { + if ($token =~ /^%r/) { + push @ret,reg($token); + } elsif ($token =~ /((?:0x)?[0-9a-f]+)\((%r\w+)\)/) { + push @ret,reg("$2+$1"); + } elsif ($token =~ /(\w+):(\-?(?:0x)?[0-9a-f]+)(U?)/i) { + my $i = 1*eval($2); + push @ret,$DW_OP_complex{$1}, ($3 ? uleb128($i) : sleb128($i)); + } elsif (my $i = 1*eval($token) or $token eq "0") { + if ($token =~ /^\+/) { + push @ret,$DW_OP_complex{plus_uconst},uleb128($i); + } else { + push @ret,const($i); + } + } else { + push @ret,$DW_OP_simple{$token}; + } + } + + # Finally we return DW_CFA_def_cfa_expression, 15, followed by + # length of the expression and of course the expression itself. + return (15,scalar(@ret),@ret); + } + sub re { + my ($class, $line) = @_; + my $self = {}; + my $ret; + + if ($$line =~ s/^\s*\.cfi_(\w+)\s*//) { + bless $self,$class; + $ret = $self; + undef $self->{value}; + my $dir = $1; + + SWITCH: for ($dir) { + # What is $cfa_rsp? Effectively it's difference between %rsp + # value and current CFA, Canonical Frame Address, which is + # why it starts with -8. Recall that CFA is top of caller's + # stack... + /startproc/ && do { ($cfa_reg, $cfa_rsp) = ("%rsp", -8); last; }; + /endproc/ && do { ($cfa_reg, $cfa_rsp) = ("%rsp", 0); + # .cfi_remember_state directives that are not + # matched with .cfi_restore_state are + # unnecessary. + die "unpaired .cfi_remember_state" if (@cfa_stack); + last; + }; + /def_cfa_register/ + && do { $cfa_reg = $$line; last; }; + /def_cfa_offset/ + && do { $cfa_rsp = -1*eval($$line) if ($cfa_reg eq "%rsp"); + last; + }; + /adjust_cfa_offset/ + && do { $cfa_rsp -= 1*eval($$line) if ($cfa_reg eq "%rsp"); + last; + }; + /def_cfa/ && do { if ($$line =~ /(%r\w+)\s*,\s*(.+)/) { + $cfa_reg = $1; + $cfa_rsp = -1*eval($2) if ($cfa_reg eq "%rsp"); + } + last; + }; + /push/ && do { $dir = undef; + $cfa_rsp -= 8; + if ($cfa_reg eq "%rsp") { + $self->{value} = ".cfi_adjust_cfa_offset\t8\n"; + } + $self->{value} .= ".cfi_offset\t$$line,$cfa_rsp"; + last; + }; + /pop/ && do { $dir = undef; + $cfa_rsp += 8; + if ($cfa_reg eq "%rsp") { + $self->{value} = ".cfi_adjust_cfa_offset\t-8\n"; + } + $self->{value} .= ".cfi_restore\t$$line"; + last; + }; + /cfa_expression/ + && do { $dir = undef; + $self->{value} = ".cfi_escape\t" . + join(",", map(sprintf("0x%02x", $_), + cfa_expression($$line))); + last; + }; + /remember_state/ + && do { push @cfa_stack, [$cfa_reg, $cfa_rsp]; + last; + }; + /restore_state/ + && do { ($cfa_reg, $cfa_rsp) = @{pop @cfa_stack}; + last; + }; + } + + $self->{value} = ".cfi_$dir\t$$line" if ($dir); + + $$line = ""; + } + + return $ret; + } + sub out { + my $self = shift; + return ($elf ? $self->{value} : undef); + } +} +{ package directive; # pick up directives, which start with . + sub re { + my ($class, $line) = @_; + my $self = {}; + my $ret; + my $dir; + + # chain-call to cfi_directive + $ret = cfi_directive->re($line) and return $ret; + + if ($$line =~ /^\s*(\.\w+)/) { + bless $self,$class; + $dir = $1; + $ret = $self; + undef $self->{value}; + $$line = substr($$line,@+[0]); $$line =~ s/^\s+//; + + SWITCH: for ($dir) { + /\.global|\.globl|\.extern/ + && do { $globals{$$line} = $prefix . $$line; + $$line = $globals{$$line} if ($prefix); + last; + }; + /\.type/ && do { my ($sym,$type,$narg) = split(',',$$line); + if ($type eq "\@function") { + undef $current_function; + $current_function->{name} = $sym; + $current_function->{abi} = "svr4"; + $current_function->{narg} = $narg; + $current_function->{scope} = defined($globals{$sym})?"PUBLIC":"PRIVATE"; + } elsif ($type eq "\@abi-omnipotent") { + undef $current_function; + $current_function->{name} = $sym; + $current_function->{scope} = defined($globals{$sym})?"PUBLIC":"PRIVATE"; + } + $$line =~ s/\@abi\-omnipotent/\@function/; + $$line =~ s/\@function.*/\@function/; + last; + }; + /\.asciz/ && do { if ($$line =~ /^"(.*)"$/) { + $dir = ".byte"; + $$line = join(",",unpack("C*",$1),0); + } + last; + }; + /\.rva|\.long|\.quad/ + && do { $$line =~ s/([_a-z][_a-z0-9]*)/$globals{$1} or $1/gei; + $$line =~ s/\.L/$decor/g; + last; + }; + } + + if ($gas) { + $self->{value} = $dir . "\t" . $$line; + + if ($dir =~ /\.extern/) { + $self->{value} = ""; # swallow extern + } elsif (!$elf && $dir =~ /\.type/) { + $self->{value} = ""; + $self->{value} = ".def\t" . ($globals{$1} or $1) . ";\t" . + (defined($globals{$1})?".scl 2;":".scl 3;") . + "\t.type 32;\t.endef" + if ($win64 && $$line =~ /([^,]+),\@function/); + } elsif (!$elf && $dir =~ /\.size/) { + $self->{value} = ""; + if (defined($current_function)) { + $self->{value} .= "${decor}SEH_end_$current_function->{name}:" + if ($win64 && $current_function->{abi} eq "svr4"); + undef $current_function; + } + } elsif (!$elf && $dir =~ /\.align/) { + $self->{value} = ".p2align\t" . (log($$line)/log(2)); + } elsif ($dir eq ".section") { + $current_segment=$$line; + if (!$elf && $current_segment eq ".init") { + if ($flavour eq "macosx") { $self->{value} = ".mod_init_func"; } + elsif ($flavour eq "mingw64") { $self->{value} = ".section\t.ctors"; } + } + } elsif ($dir =~ /\.(text|data)/) { + $current_segment=".$1"; + } elsif ($dir =~ /\.hidden/) { + if ($flavour eq "macosx") { $self->{value} = ".private_extern\t$prefix$$line"; } + elsif ($flavour eq "mingw64") { $self->{value} = ""; } + } elsif ($dir =~ /\.comm/) { + $self->{value} = "$dir\t$prefix$$line"; + $self->{value} =~ s|,([0-9]+),([0-9]+)$|",$1,".log($2)/log(2)|e if ($flavour eq "macosx"); + } + $$line = ""; + return $self; + } + + # non-gas case or nasm/masm + SWITCH: for ($dir) { + /\.text/ && do { my $v=undef; + if ($nasm) { + $v="section .text code align=64\n"; + } else { + $v="$current_segment\tENDS\n" if ($current_segment); + $current_segment = ".text\$"; + $v.="$current_segment\tSEGMENT "; + $v.=$masm>=$masmref ? "ALIGN(256)" : "PAGE"; + $v.=" 'CODE'"; + } + $self->{value} = $v; + last; + }; + /\.data/ && do { my $v=undef; + if ($nasm) { + $v="section .data data align=8\n"; + } else { + $v="$current_segment\tENDS\n" if ($current_segment); + $current_segment = "_DATA"; + $v.="$current_segment\tSEGMENT"; + } + $self->{value} = $v; + last; + }; + /\.section/ && do { my $v=undef; + $$line =~ s/([^,]*).*/$1/; + $$line = ".CRT\$XCU" if ($$line eq ".init"); + if ($nasm) { + $v="section $$line"; + if ($$line=~/\.([px])data/) { + $v.=" rdata align="; + $v.=$1 eq "p"? 4 : 8; + } elsif ($$line=~/\.CRT\$/i) { + $v.=" rdata align=8"; + } + } else { + $v="$current_segment\tENDS\n" if ($current_segment); + $v.="$$line\tSEGMENT"; + if ($$line=~/\.([px])data/) { + $v.=" READONLY"; + $v.=" ALIGN(".($1 eq "p" ? 4 : 8).")" if ($masm>=$masmref); + } elsif ($$line=~/\.CRT\$/i) { + $v.=" READONLY "; + $v.=$masm>=$masmref ? "ALIGN(8)" : "DWORD"; + } + } + $current_segment = $$line; + $self->{value} = $v; + last; + }; + /\.extern/ && do { $self->{value} = "EXTERN\t".$$line; + $self->{value} .= ":NEAR" if ($masm); + last; + }; + /\.globl|.global/ + && do { $self->{value} = $masm?"PUBLIC":"global"; + $self->{value} .= "\t".$$line; + last; + }; + /\.size/ && do { if (defined($current_function)) { + undef $self->{value}; + if ($current_function->{abi} eq "svr4") { + $self->{value}="${decor}SEH_end_$current_function->{name}:"; + $self->{value}.=":\n" if($masm); + } + $self->{value}.="$current_function->{name}\tENDP" if($masm && $current_function->{name}); + undef $current_function; + } + last; + }; + /\.align/ && do { my $max = ($masm && $masm>=$masmref) ? 256 : 4096; + $self->{value} = "ALIGN\t".($$line>$max?$max:$$line); + last; + }; + /\.(value|long|rva|quad)/ + && do { my $sz = substr($1,0,1); + my @arr = split(/,\s*/,$$line); + my $last = pop(@arr); + my $conv = sub { my $var=shift; + $var=~s/^(0b[0-1]+)/oct($1)/eig; + $var=~s/^0x([0-9a-f]+)/0$1h/ig if ($masm); + if ($sz eq "D" && ($current_segment=~/.[px]data/ || $dir eq ".rva")) + { $var=~s/^([_a-z\$\@][_a-z0-9\$\@]*)/$nasm?"$1 wrt ..imagebase":"imagerel $1"/egi; } + $var; + }; + + $sz =~ tr/bvlrq/BWDDQ/; + $self->{value} = "\tD$sz\t"; + for (@arr) { $self->{value} .= &$conv($_).","; } + $self->{value} .= &$conv($last); + last; + }; + /\.byte/ && do { my @str=split(/,\s*/,$$line); + map(s/(0b[0-1]+)/oct($1)/eig,@str); + map(s/0x([0-9a-f]+)/0$1h/ig,@str) if ($masm); + while ($#str>15) { + $self->{value}.="DB\t" + .join(",",@str[0..15])."\n"; + foreach (0..15) { shift @str; } + } + $self->{value}.="DB\t" + .join(",",@str) if (@str); + last; + }; + /\.comm/ && do { my @str=split(/,\s*/,$$line); + my $v=undef; + if ($nasm) { + $v.="common $prefix@str[0] @str[1]"; + } else { + $v="$current_segment\tENDS\n" if ($current_segment); + $current_segment = "_DATA"; + $v.="$current_segment\tSEGMENT\n"; + $v.="COMM @str[0]:DWORD:".@str[1]/4; + } + $self->{value} = $v; + last; + }; + } + $$line = ""; + } + + $ret; + } + sub out { + my $self = shift; + $self->{value}; + } +} + +# Upon initial x86_64 introduction SSE>2 extensions were not introduced +# yet. In order not to be bothered by tracing exact assembler versions, +# but at the same time to provide a bare security minimum of AES-NI, we +# hard-code some instructions. Extensions past AES-NI on the other hand +# are traced by examining assembler version in individual perlasm +# modules... + +my %regrm = ( "%eax"=>0, "%ecx"=>1, "%edx"=>2, "%ebx"=>3, + "%esp"=>4, "%ebp"=>5, "%esi"=>6, "%edi"=>7 ); + +sub rex { + my $opcode=shift; + my ($dst,$src,$rex)=@_; + + $rex|=0x04 if($dst>=8); + $rex|=0x01 if($src>=8); + push @$opcode,($rex|0x40) if ($rex); +} + +my $movq = sub { # elderly gas can't handle inter-register movq + my $arg = shift; + my @opcode=(0x66); + if ($arg =~ /%xmm([0-9]+),\s*%r(\w+)/) { + my ($src,$dst)=($1,$2); + if ($dst !~ /[0-9]+/) { $dst = $regrm{"%e$dst"}; } + rex(\@opcode,$src,$dst,0x8); + push @opcode,0x0f,0x7e; + push @opcode,0xc0|(($src&7)<<3)|($dst&7); # ModR/M + @opcode; + } elsif ($arg =~ /%r(\w+),\s*%xmm([0-9]+)/) { + my ($src,$dst)=($2,$1); + if ($dst !~ /[0-9]+/) { $dst = $regrm{"%e$dst"}; } + rex(\@opcode,$src,$dst,0x8); + push @opcode,0x0f,0x6e; + push @opcode,0xc0|(($src&7)<<3)|($dst&7); # ModR/M + @opcode; + } else { + (); + } +}; + +my $pextrd = sub { + if (shift =~ /\$([0-9]+),\s*%xmm([0-9]+),\s*(%\w+)/) { + my @opcode=(0x66); + my $imm=$1; + my $src=$2; + my $dst=$3; + if ($dst =~ /%r([0-9]+)d/) { $dst = $1; } + elsif ($dst =~ /%e/) { $dst = $regrm{$dst}; } + rex(\@opcode,$src,$dst); + push @opcode,0x0f,0x3a,0x16; + push @opcode,0xc0|(($src&7)<<3)|($dst&7); # ModR/M + push @opcode,$imm; + @opcode; + } else { + (); + } +}; + +my $pinsrd = sub { + if (shift =~ /\$([0-9]+),\s*(%\w+),\s*%xmm([0-9]+)/) { + my @opcode=(0x66); + my $imm=$1; + my $src=$2; + my $dst=$3; + if ($src =~ /%r([0-9]+)/) { $src = $1; } + elsif ($src =~ /%e/) { $src = $regrm{$src}; } + rex(\@opcode,$dst,$src); + push @opcode,0x0f,0x3a,0x22; + push @opcode,0xc0|(($dst&7)<<3)|($src&7); # ModR/M + push @opcode,$imm; + @opcode; + } else { + (); + } +}; + +my $pshufb = sub { + if (shift =~ /%xmm([0-9]+),\s*%xmm([0-9]+)/) { + my @opcode=(0x66); + rex(\@opcode,$2,$1); + push @opcode,0x0f,0x38,0x00; + push @opcode,0xc0|($1&7)|(($2&7)<<3); # ModR/M + @opcode; + } else { + (); + } +}; + +my $palignr = sub { + if (shift =~ /\$([0-9]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) { + my @opcode=(0x66); + rex(\@opcode,$3,$2); + push @opcode,0x0f,0x3a,0x0f; + push @opcode,0xc0|($2&7)|(($3&7)<<3); # ModR/M + push @opcode,$1; + @opcode; + } else { + (); + } +}; + +my $pclmulqdq = sub { + if (shift =~ /\$([x0-9a-f]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) { + my @opcode=(0x66); + rex(\@opcode,$3,$2); + push @opcode,0x0f,0x3a,0x44; + push @opcode,0xc0|($2&7)|(($3&7)<<3); # ModR/M + my $c=$1; + push @opcode,$c=~/^0/?oct($c):$c; + @opcode; + } else { + (); + } +}; + +my $rdrand = sub { + if (shift =~ /%[er](\w+)/) { + my @opcode=(); + my $dst=$1; + if ($dst !~ /[0-9]+/) { $dst = $regrm{"%e$dst"}; } + rex(\@opcode,0,$dst,8); + push @opcode,0x0f,0xc7,0xf0|($dst&7); + @opcode; + } else { + (); + } +}; + +my $rdseed = sub { + if (shift =~ /%[er](\w+)/) { + my @opcode=(); + my $dst=$1; + if ($dst !~ /[0-9]+/) { $dst = $regrm{"%e$dst"}; } + rex(\@opcode,0,$dst,8); + push @opcode,0x0f,0xc7,0xf8|($dst&7); + @opcode; + } else { + (); + } +}; + +# Not all AVX-capable assemblers recognize AMD XOP extension. Since we +# are using only two instructions hand-code them in order to be excused +# from chasing assembler versions... + +sub rxb { + my $opcode=shift; + my ($dst,$src1,$src2,$rxb)=@_; + + $rxb|=0x7<<5; + $rxb&=~(0x04<<5) if($dst>=8); + $rxb&=~(0x01<<5) if($src1>=8); + $rxb&=~(0x02<<5) if($src2>=8); + push @$opcode,$rxb; +} + +my $vprotd = sub { + if (shift =~ /\$([x0-9a-f]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) { + my @opcode=(0x8f); + rxb(\@opcode,$3,$2,-1,0x08); + push @opcode,0x78,0xc2; + push @opcode,0xc0|($2&7)|(($3&7)<<3); # ModR/M + my $c=$1; + push @opcode,$c=~/^0/?oct($c):$c; + @opcode; + } else { + (); + } +}; + +my $vprotq = sub { + if (shift =~ /\$([x0-9a-f]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) { + my @opcode=(0x8f); + rxb(\@opcode,$3,$2,-1,0x08); + push @opcode,0x78,0xc3; + push @opcode,0xc0|($2&7)|(($3&7)<<3); # ModR/M + my $c=$1; + push @opcode,$c=~/^0/?oct($c):$c; + @opcode; + } else { + (); + } +}; + +# Intel Control-flow Enforcement Technology extension. All functions and +# indirect branch targets will have to start with this instruction... + +my $endbranch = sub { + (0xf3,0x0f,0x1e,0xfa); +}; + +######################################################################## + +if ($nasm) { + print <<___; +default rel +%define XMMWORD +%define YMMWORD +%define ZMMWORD +___ +} elsif ($masm) { + print <<___; +OPTION DOTNAME +___ +} +while(defined(my $line=<>)) { + + $line =~ s|\R$||; # Better chomp + + $line =~ s|[#!].*$||; # get rid of asm-style comments... + $line =~ s|/\*.*\*/||; # ... and C-style comments... + $line =~ s|^\s+||; # ... and skip white spaces in beginning + $line =~ s|\s+$||; # ... and at the end + + if (my $label=label->re(\$line)) { print $label->out(); } + + if (my $directive=directive->re(\$line)) { + printf "%s",$directive->out(); + } elsif (my $opcode=opcode->re(\$line)) { + my $asm = eval("\$".$opcode->mnemonic()); + + if ((ref($asm) eq 'CODE') && scalar(my @bytes=&$asm($line))) { + print $gas?".byte\t":"DB\t",join(',',@bytes),"\n"; + next; + } + + my @args; + ARGUMENT: while (1) { + my $arg; + + ($arg=register->re(\$line, $opcode))|| + ($arg=const->re(\$line)) || + ($arg=ea->re(\$line, $opcode)) || + ($arg=expr->re(\$line, $opcode)) || + last ARGUMENT; + + push @args,$arg; + + last ARGUMENT if ($line !~ /^,/); + + $line =~ s/^,\s*//; + } # ARGUMENT: + + if ($#args>=0) { + my $insn; + my $sz=$opcode->size(); + + if ($gas) { + $insn = $opcode->out($#args>=1?$args[$#args]->size():$sz); + @args = map($_->out($sz),@args); + printf "\t%s\t%s",$insn,join(",",@args); + } else { + $insn = $opcode->out(); + foreach (@args) { + my $arg = $_->out(); + # $insn.=$sz compensates for movq, pinsrw, ... + if ($arg =~ /^xmm[0-9]+$/) { $insn.=$sz; $sz="x" if(!$sz); last; } + if ($arg =~ /^ymm[0-9]+$/) { $insn.=$sz; $sz="y" if(!$sz); last; } + if ($arg =~ /^zmm[0-9]+$/) { $insn.=$sz; $sz="z" if(!$sz); last; } + if ($arg =~ /^mm[0-9]+$/) { $insn.=$sz; $sz="q" if(!$sz); last; } + } + @args = reverse(@args); + undef $sz if ($nasm && $opcode->mnemonic() eq "lea"); + printf "\t%s\t%s",$insn,join(",",map($_->out($sz),@args)); + } + } else { + printf "\t%s",$opcode->out(); + } + } + + print $line,"\n"; +} + +print "\n$current_segment\tENDS\n" if ($current_segment && $masm); +print "END\n" if ($masm); + +close STDOUT; + + ################################################# +# Cross-reference x86_64 ABI "card" +# +# Unix Win64 +# %rax * * +# %rbx - - +# %rcx #4 #1 +# %rdx #3 #2 +# %rsi #2 - +# %rdi #1 - +# %rbp - - +# %rsp - - +# %r8 #5 #3 +# %r9 #6 #4 +# %r10 * * +# %r11 * * +# %r12 - - +# %r13 - - +# %r14 - - +# %r15 - - +# +# (*) volatile register +# (-) preserved by callee +# (#) Nth argument, volatile +# +# In Unix terms top of stack is argument transfer area for arguments +# which could not be accommodated in registers. Or in other words 7th +# [integer] argument resides at 8(%rsp) upon function entry point. +# 128 bytes above %rsp constitute a "red zone" which is not touched +# by signal handlers and can be used as temporal storage without +# allocating a frame. +# +# In Win64 terms N*8 bytes on top of stack is argument transfer area, +# which belongs to/can be overwritten by callee. N is the number of +# arguments passed to callee, *but* not less than 4! This means that +# upon function entry point 5th argument resides at 40(%rsp), as well +# as that 32 bytes from 8(%rsp) can always be used as temporal +# storage [without allocating a frame]. One can actually argue that +# one can assume a "red zone" above stack pointer under Win64 as well. +# Point is that at apparently no occasion Windows kernel would alter +# the area above user stack pointer in true asynchronous manner... +# +# All the above means that if assembler programmer adheres to Unix +# register and stack layout, but disregards the "red zone" existence, +# it's possible to use following prologue and epilogue to "gear" from +# Unix to Win64 ABI in leaf functions with not more than 6 arguments. +# +# omnipotent_function: +# ifdef WIN64 +# movq %rdi,8(%rsp) +# movq %rsi,16(%rsp) +# movq %rcx,%rdi ; if 1st argument is actually present +# movq %rdx,%rsi ; if 2nd argument is actually ... +# movq %r8,%rdx ; if 3rd argument is ... +# movq %r9,%rcx ; if 4th argument ... +# movq 40(%rsp),%r8 ; if 5th ... +# movq 48(%rsp),%r9 ; if 6th ... +# endif +# ... +# ifdef WIN64 +# movq 8(%rsp),%rdi +# movq 16(%rsp),%rsi +# endif +# ret +# + ################################################# +# Win64 SEH, Structured Exception Handling. +# +# Unlike on Unix systems(*) lack of Win64 stack unwinding information +# has undesired side-effect at run-time: if an exception is raised in +# assembler subroutine such as those in question (basically we're +# referring to segmentation violations caused by malformed input +# parameters), the application is briskly terminated without invoking +# any exception handlers, most notably without generating memory dump +# or any user notification whatsoever. This poses a problem. It's +# possible to address it by registering custom language-specific +# handler that would restore processor context to the state at +# subroutine entry point and return "exception is not handled, keep +# unwinding" code. Writing such handler can be a challenge... But it's +# doable, though requires certain coding convention. Consider following +# snippet: +# +# .type function,@function +# function: +# movq %rsp,%rax # copy rsp to volatile register +# pushq %r15 # save non-volatile registers +# pushq %rbx +# pushq %rbp +# movq %rsp,%r11 +# subq %rdi,%r11 # prepare [variable] stack frame +# andq $-64,%r11 +# movq %rax,0(%r11) # check for exceptions +# movq %r11,%rsp # allocate [variable] stack frame +# movq %rax,0(%rsp) # save original rsp value +# magic_point: +# ... +# movq 0(%rsp),%rcx # pull original rsp value +# movq -24(%rcx),%rbp # restore non-volatile registers +# movq -16(%rcx),%rbx +# movq -8(%rcx),%r15 +# movq %rcx,%rsp # restore original rsp +# magic_epilogue: +# ret +# .size function,.-function +# +# The key is that up to magic_point copy of original rsp value remains +# in chosen volatile register and no non-volatile register, except for +# rsp, is modified. While past magic_point rsp remains constant till +# the very end of the function. In this case custom language-specific +# exception handler would look like this: +# +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +# { ULONG64 *rsp = (ULONG64 *)context->Rax; +# ULONG64 rip = context->Rip; +# +# if (rip >= magic_point) +# { rsp = (ULONG64 *)context->Rsp; +# if (rip < magic_epilogue) +# { rsp = (ULONG64 *)rsp[0]; +# context->Rbp = rsp[-3]; +# context->Rbx = rsp[-2]; +# context->R15 = rsp[-1]; +# } +# } +# context->Rsp = (ULONG64)rsp; +# context->Rdi = rsp[1]; +# context->Rsi = rsp[2]; +# +# memcpy (disp->ContextRecord,context,sizeof(CONTEXT)); +# RtlVirtualUnwind(UNW_FLAG_NHANDLER,disp->ImageBase, +# dips->ControlPc,disp->FunctionEntry,disp->ContextRecord, +# &disp->HandlerData,&disp->EstablisherFrame,NULL); +# return ExceptionContinueSearch; +# } +# +# It's appropriate to implement this handler in assembler, directly in +# function's module. In order to do that one has to know members' +# offsets in CONTEXT and DISPATCHER_CONTEXT structures and some constant +# values. Here they are: +# +# CONTEXT.Rax 120 +# CONTEXT.Rcx 128 +# CONTEXT.Rdx 136 +# CONTEXT.Rbx 144 +# CONTEXT.Rsp 152 +# CONTEXT.Rbp 160 +# CONTEXT.Rsi 168 +# CONTEXT.Rdi 176 +# CONTEXT.R8 184 +# CONTEXT.R9 192 +# CONTEXT.R10 200 +# CONTEXT.R11 208 +# CONTEXT.R12 216 +# CONTEXT.R13 224 +# CONTEXT.R14 232 +# CONTEXT.R15 240 +# CONTEXT.Rip 248 +# CONTEXT.Xmm6 512 +# sizeof(CONTEXT) 1232 +# DISPATCHER_CONTEXT.ControlPc 0 +# DISPATCHER_CONTEXT.ImageBase 8 +# DISPATCHER_CONTEXT.FunctionEntry 16 +# DISPATCHER_CONTEXT.EstablisherFrame 24 +# DISPATCHER_CONTEXT.TargetIp 32 +# DISPATCHER_CONTEXT.ContextRecord 40 +# DISPATCHER_CONTEXT.LanguageHandler 48 +# DISPATCHER_CONTEXT.HandlerData 56 +# UNW_FLAG_NHANDLER 0 +# ExceptionContinueSearch 1 +# +# In order to tie the handler to the function one has to compose +# couple of structures: one for .xdata segment and one for .pdata. +# +# UNWIND_INFO structure for .xdata segment would be +# +# function_unwind_info: +# .byte 9,0,0,0 +# .rva handler +# +# This structure designates exception handler for a function with +# zero-length prologue, no stack frame or frame register. +# +# To facilitate composing of .pdata structures, auto-generated "gear" +# prologue copies rsp value to rax and denotes next instruction with +# .LSEH_begin_{function_name} label. This essentially defines the SEH +# styling rule mentioned in the beginning. Position of this label is +# chosen in such manner that possible exceptions raised in the "gear" +# prologue would be accounted to caller and unwound from latter's frame. +# End of function is marked with respective .LSEH_end_{function_name} +# label. To summarize, .pdata segment would contain +# +# .rva .LSEH_begin_function +# .rva .LSEH_end_function +# .rva function_unwind_info +# +# Reference to function_unwind_info from .xdata segment is the anchor. +# In case you wonder why references are 32-bit .rvas and not 64-bit +# .quads. References put into these two segments are required to be +# *relative* to the base address of the current binary module, a.k.a. +# image base. No Win64 module, be it .exe or .dll, can be larger than +# 2GB and thus such relative references can be and are accommodated in +# 32 bits. +# +# Having reviewed the example function code, one can argue that "movq +# %rsp,%rax" above is redundant. It is not! Keep in mind that on Unix +# rax would contain an undefined value. If this "offends" you, use +# another register and refrain from modifying rax till magic_point is +# reached, i.e. as if it was a non-volatile register. If more registers +# are required prior [variable] frame setup is completed, note that +# nobody says that you can have only one "magic point." You can +# "liberate" non-volatile registers by denoting last stack off-load +# instruction and reflecting it in finer grade unwind logic in handler. +# After all, isn't it why it's called *language-specific* handler... +# +# SE handlers are also involved in unwinding stack when executable is +# profiled or debugged. Profiling implies additional limitations that +# are too subtle to discuss here. For now it's sufficient to say that +# in order to simplify handlers one should either a) offload original +# %rsp to stack (like discussed above); or b) if you have a register to +# spare for frame pointer, choose volatile one. +# +# (*) Note that we're talking about run-time, not debug-time. Lack of +# unwind information makes debugging hard on both Windows and +# Unix. "Unlike" refers to the fact that on Unix signal handler +# will always be invoked, core dumped and appropriate exit code +# returned to parent (for user notification). diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/x86asm.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/x86asm.pl new file mode 100644 index 000000000..29dc1a2cf --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/x86asm.pl @@ -0,0 +1,303 @@ +#! /usr/bin/env perl +# Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# require 'x86asm.pl'; +# &asm_init([,$i386only]); +# &function_begin("foo"); +# ... +# &function_end("foo"); +# &asm_finish + +$out=(); +$i386=0; + +# AUTOLOAD is this context has quite unpleasant side effect, namely +# that typos in function calls effectively go to assembler output, +# but on the pros side we don't have to implement one subroutine per +# each opcode... +sub ::AUTOLOAD +{ my $opcode = $AUTOLOAD; + + die "more than 4 arguments passed to $opcode" if ($#_>3); + + $opcode =~ s/.*:://; + if ($opcode =~ /^push/) { $stack+=4; } + elsif ($opcode =~ /^pop/) { $stack-=4; } + + &generic($opcode,@_) or die "undefined subroutine \&$AUTOLOAD"; +} + +sub ::emit +{ my $opcode=shift; + + if ($#_==-1) { push(@out,"\t$opcode\n"); } + else { push(@out,"\t$opcode\t".join(',',@_)."\n"); } +} + +sub ::LB +{ $_[0] =~ m/^e?([a-d])x$/o or die "$_[0] does not have a 'low byte'"; + $1."l"; +} +sub ::HB +{ $_[0] =~ m/^e?([a-d])x$/o or die "$_[0] does not have a 'high byte'"; + $1."h"; +} +sub ::stack_push{ my $num=$_[0]*4; $stack+=$num; &sub("esp",$num); } +sub ::stack_pop { my $num=$_[0]*4; $stack-=$num; &add("esp",$num); } +sub ::blindpop { &pop($_[0]); $stack+=4; } +sub ::wparam { &DWP($stack+4*$_[0],"esp"); } +sub ::swtmp { &DWP(4*$_[0],"esp"); } + +sub ::bswap +{ if ($i386) # emulate bswap for i386 + { &comment("bswap @_"); + &xchg(&HB(@_),&LB(@_)); + &ror (@_,16); + &xchg(&HB(@_),&LB(@_)); + } + else + { &generic("bswap",@_); } +} +# These are made-up opcodes introduced over the years essentially +# by ignorance, just alias them to real ones... +sub ::movb { &mov(@_); } +sub ::xorb { &xor(@_); } +sub ::rotl { &rol(@_); } +sub ::rotr { &ror(@_); } +sub ::exch { &xchg(@_); } +sub ::halt { &hlt; } +sub ::movz { &movzx(@_); } +sub ::pushf { &pushfd; } +sub ::popf { &popfd; } + +# 3 argument instructions +sub ::movq +{ my($p1,$p2,$optimize)=@_; + + if ($optimize && $p1=~/^mm[0-7]$/ && $p2=~/^mm[0-7]$/) + # movq between mmx registers can sink Intel CPUs + { &::pshufw($p1,$p2,0xe4); } + else + { &::generic("movq",@_); } +} + +# SSE>2 instructions +my %regrm = ( "eax"=>0, "ecx"=>1, "edx"=>2, "ebx"=>3, + "esp"=>4, "ebp"=>5, "esi"=>6, "edi"=>7 ); +sub ::pextrd +{ my($dst,$src,$imm)=@_; + if ("$dst:$src" =~ /(e[a-dsd][ixp]):xmm([0-7])/) + { &::data_byte(0x66,0x0f,0x3a,0x16,0xc0|($2<<3)|$regrm{$1},$imm); } + else + { &::generic("pextrd",@_); } +} + +sub ::pinsrd +{ my($dst,$src,$imm)=@_; + if ("$dst:$src" =~ /xmm([0-7]):(e[a-dsd][ixp])/) + { &::data_byte(0x66,0x0f,0x3a,0x22,0xc0|($1<<3)|$regrm{$2},$imm); } + else + { &::generic("pinsrd",@_); } +} + +sub ::pshufb +{ my($dst,$src)=@_; + if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/) + { &data_byte(0x66,0x0f,0x38,0x00,0xc0|($1<<3)|$2); } + else + { &::generic("pshufb",@_); } +} + +sub ::palignr +{ my($dst,$src,$imm)=@_; + if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/) + { &::data_byte(0x66,0x0f,0x3a,0x0f,0xc0|($1<<3)|$2,$imm); } + else + { &::generic("palignr",@_); } +} + +sub ::pclmulqdq +{ my($dst,$src,$imm)=@_; + if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/) + { &::data_byte(0x66,0x0f,0x3a,0x44,0xc0|($1<<3)|$2,$imm); } + else + { &::generic("pclmulqdq",@_); } +} + +sub ::rdrand +{ my ($dst)=@_; + if ($dst =~ /(e[a-dsd][ixp])/) + { &::data_byte(0x0f,0xc7,0xf0|$regrm{$dst}); } + else + { &::generic("rdrand",@_); } +} + +sub ::rdseed +{ my ($dst)=@_; + if ($dst =~ /(e[a-dsd][ixp])/) + { &::data_byte(0x0f,0xc7,0xf8|$regrm{$dst}); } + else + { &::generic("rdrand",@_); } +} + +sub rxb { + local *opcode=shift; + my ($dst,$src1,$src2,$rxb)=@_; + + $rxb|=0x7<<5; + $rxb&=~(0x04<<5) if($dst>=8); + $rxb&=~(0x01<<5) if($src1>=8); + $rxb&=~(0x02<<5) if($src2>=8); + push @opcode,$rxb; +} + +sub ::vprotd +{ my $args=join(',',@_); + if ($args =~ /xmm([0-7]),xmm([0-7]),([x0-9a-f]+)/) + { my @opcode=(0x8f); + rxb(\@opcode,$1,$2,-1,0x08); + push @opcode,0x78,0xc2; + push @opcode,0xc0|($2&7)|(($1&7)<<3); # ModR/M + my $c=$3; + push @opcode,$c=~/^0/?oct($c):$c; + &::data_byte(@opcode); + } + else + { &::generic("vprotd",@_); } +} + +sub ::endbranch +{ + &::data_byte(0xf3,0x0f,0x1e,0xfb); +} + +# label management +$lbdecor="L"; # local label decoration, set by package +$label="000"; + +sub ::islabel # see is argument is a known label +{ my $i; + foreach $i (values %label) { return $i if ($i eq $_[0]); } + $label{$_[0]}; # can be undef +} + +sub ::label # instantiate a function-scope label +{ if (!defined($label{$_[0]})) + { $label{$_[0]}="${lbdecor}${label}${_[0]}"; $label++; } + $label{$_[0]}; +} + +sub ::LABEL # instantiate a file-scope label +{ $label{$_[0]}=$_[1] if (!defined($label{$_[0]})); + $label{$_[0]}; +} + +sub ::static_label { &::LABEL($_[0],$lbdecor.$_[0]); } + +sub ::set_label_B { push(@out,"@_:\n"); } +sub ::set_label +{ my $label=&::label($_[0]); + &::align($_[1]) if ($_[1]>1); + &::set_label_B($label); + $label; +} + +sub ::wipe_labels # wipes function-scope labels +{ foreach $i (keys %label) + { delete $label{$i} if ($label{$i} =~ /^\Q${lbdecor}\E[0-9]{3}/); } +} + +# subroutine management +sub ::function_begin +{ &function_begin_B(@_); + $stack=4; + &push("ebp"); + &push("ebx"); + &push("esi"); + &push("edi"); +} + +sub ::function_end +{ &pop("edi"); + &pop("esi"); + &pop("ebx"); + &pop("ebp"); + &ret(); + &function_end_B(@_); + $stack=0; + &wipe_labels(); +} + +sub ::function_end_A +{ &pop("edi"); + &pop("esi"); + &pop("ebx"); + &pop("ebp"); + &ret(); + $stack+=16; # readjust esp as if we didn't pop anything +} + +sub ::asciz +{ my @str=unpack("C*",shift); + push @str,0; + while ($#str>15) { + &data_byte(@str[0..15]); + foreach (0..15) { shift @str; } + } + &data_byte(@str) if (@str); +} + +sub ::asm_finish +{ &file_end(); + print @out; +} + +sub ::asm_init +{ my ($type,$cpu)=@_; + + $i386=$cpu; + + $elf=$cpp=$coff=$aout=$macosx=$win32=$mwerks=$android=0; + if (($type eq "elf")) + { $elf=1; require "x86gas.pl"; } + elsif (($type eq "elf-1")) + { $elf=-1; require "x86gas.pl"; } + elsif (($type eq "a\.out")) + { $aout=1; require "x86gas.pl"; } + elsif (($type eq "coff" or $type eq "gaswin")) + { $coff=1; require "x86gas.pl"; } + elsif (($type eq "win32n")) + { $win32=1; require "x86nasm.pl"; } + elsif (($type eq "win32")) + { $win32=1; require "x86masm.pl"; } + elsif (($type eq "macosx")) + { $aout=1; $macosx=1; require "x86gas.pl"; } + elsif (($type eq "android")) + { $elf=1; $android=1; require "x86gas.pl"; } + else + { print STDERR <<"EOF"; +Pick one target type from + elf - Linux, FreeBSD, Solaris x86, etc. + a.out - DJGPP, elder OpenBSD, etc. + coff - GAS/COFF such as Win32 targets + win32n - Windows 95/Windows NT NASM format + macosx - Mac OS X +EOF + exit(1); + } + + $pic=0; + for (@ARGV) { $pic=1 if (/\-[fK]PIC/i); } + + &file(); +} + +sub ::hidden {} + +1; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/x86gas.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/x86gas.pl new file mode 100644 index 000000000..5c7ea3880 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/x86gas.pl @@ -0,0 +1,265 @@ +#! /usr/bin/env perl +# Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +package x86gas; + +*out=\@::out; + +$::lbdecor=$::aout?"L":".L"; # local label decoration +$nmdecor=($::aout or $::coff)?"_":""; # external name decoration + +$initseg=""; + +$align=16; +$align=log($align)/log(2) if ($::aout); +$com_start="#" if ($::aout or $::coff); + +sub opsize() +{ my $reg=shift; + if ($reg =~ m/^%e/o) { "l"; } + elsif ($reg =~ m/^%[a-d][hl]$/o) { "b"; } + elsif ($reg =~ m/^%[yxm]/o) { undef; } + else { "w"; } +} + +# swap arguments; +# expand opcode with size suffix; +# prefix numeric constants with $; +sub ::generic +{ my($opcode,@arg)=@_; + my($suffix,$dst,$src); + + @arg=reverse(@arg); + + for (@arg) + { s/^(\*?)(e?[a-dsixphl]{2})$/$1%$2/o; # gp registers + s/^([xy]?mm[0-7])$/%$1/o; # xmm/mmx registers + s/^(\-?[0-9]+)$/\$$1/o; # constants + s/^(\-?0x[0-9a-f]+)$/\$$1/o; # constants + } + + $dst = $arg[$#arg] if ($#arg>=0); + $src = $arg[$#arg-1] if ($#arg>=1); + if ($dst =~ m/^%/o) { $suffix=&opsize($dst); } + elsif ($src =~ m/^%/o) { $suffix=&opsize($src); } + else { $suffix="l"; } + undef $suffix if ($dst =~ m/^%[xm]/o || $src =~ m/^%[xm]/o); + + if ($#_==0) { &::emit($opcode); } + elsif ($#_==1 && $opcode =~ m/^(call|clflush|j|loop|set)/o) + { &::emit($opcode,@arg); } + else { &::emit($opcode.$suffix,@arg);} + + 1; +} +# +# opcodes not covered by ::generic above, mostly inconsistent namings... +# +sub ::movzx { &::movzb(@_); } +sub ::pushfd { &::pushfl; } +sub ::popfd { &::popfl; } +sub ::cpuid { &::emit(".byte\t0x0f,0xa2"); } +sub ::rdtsc { &::emit(".byte\t0x0f,0x31"); } + +sub ::call { &::emit("call",(&::islabel($_[0]) or "$nmdecor$_[0]")); } +sub ::call_ptr { &::generic("call","*$_[0]"); } +sub ::jmp_ptr { &::generic("jmp","*$_[0]"); } + +*::bswap = sub { &::emit("bswap","%$_[0]"); } if (!$::i386); + +sub ::DWP +{ my($addr,$reg1,$reg2,$idx)=@_; + my $ret=""; + + if (!defined($idx) && 1*$reg2) { $idx=$reg2; $reg2=$reg1; undef $reg1; } + + $addr =~ s/^\s+//; + # prepend global references with optional underscore + $addr =~ s/^([^\+\-0-9][^\+\-]*)/&::islabel($1) or "$nmdecor$1"/ige; + + $reg1 = "%$reg1" if ($reg1); + $reg2 = "%$reg2" if ($reg2); + + $ret .= $addr if (($addr ne "") && ($addr ne 0)); + + if ($reg2) + { $idx!= 0 or $idx=1; + $ret .= "($reg1,$reg2,$idx)"; + } + elsif ($reg1) + { $ret .= "($reg1)"; } + + $ret; +} +sub ::QWP { &::DWP(@_); } +sub ::BP { &::DWP(@_); } +sub ::WP { &::DWP(@_); } +sub ::BC { @_; } +sub ::DWC { @_; } + +sub ::file +{ push(@out,".text\n"); } + +sub ::function_begin_B +{ my $func=shift; + my $global=($func !~ /^_/); + my $begin="${::lbdecor}_${func}_begin"; + + &::LABEL($func,$global?"$begin":"$nmdecor$func"); + $func=$nmdecor.$func; + + push(@out,".globl\t$func\n") if ($global); + if ($::coff) + { push(@out,".def\t$func;\t.scl\t".(3-$global).";\t.type\t32;\t.endef\n"); } + elsif (($::aout and !$::pic) or $::macosx) + { } + else + { push(@out,".type $func,\@function\n"); } + push(@out,".align\t$align\n"); + push(@out,"$func:\n"); + push(@out,"$begin:\n") if ($global); + $::stack=4; +} + +sub ::function_end_B +{ my $func=shift; + push(@out,".size\t$nmdecor$func,.-".&::LABEL($func)."\n") if ($::elf); + $::stack=0; + &::wipe_labels(); +} + +sub ::comment + { + if (!defined($com_start) or $::elf) + { # Regarding $::elf above... + # GNU and SVR4 as'es use different comment delimiters, + push(@out,"\n"); # so we just skip ELF comments... + return; + } + foreach (@_) + { + if (/^\s*$/) + { push(@out,"\n"); } + else + { push(@out,"\t$com_start $_ $com_end\n"); } + } + } + +sub ::external_label +{ foreach(@_) { &::LABEL($_,$nmdecor.$_); } } + +sub ::public_label +{ push(@out,".globl\t".&::LABEL($_[0],$nmdecor.$_[0])."\n"); } + +sub ::file_end +{ if ($::macosx) + { if (%non_lazy_ptr) + { push(@out,".section __IMPORT,__pointers,non_lazy_symbol_pointers\n"); + foreach $i (keys %non_lazy_ptr) + { push(@out,"$non_lazy_ptr{$i}:\n.indirect_symbol\t$i\n.long\t0\n"); } + } + } + if (grep {/\b${nmdecor}OPENSSL_ia32cap_P\b/i} @out) { + my $tmp=".comm\t${nmdecor}OPENSSL_ia32cap_P,16"; + if ($::macosx) { push (@out,"$tmp,2\n"); } + elsif ($::elf) { push (@out,"$tmp,4\n"); } + else { push (@out,"$tmp\n"); } + } + push(@out,$initseg) if ($initseg); +} + +sub ::data_byte { push(@out,".byte\t".join(',',@_)."\n"); } +sub ::data_short{ push(@out,".value\t".join(',',@_)."\n"); } +sub ::data_word { push(@out,".long\t".join(',',@_)."\n"); } + +sub ::align +{ my $val=$_[0]; + if ($::aout) + { $val=int(log($val)/log(2)); + $val.=",0x90"; + } + push(@out,".align\t$val\n"); +} + +sub ::picmeup +{ my($dst,$sym,$base,$reflabel)=@_; + + if (($::pic && ($::elf || $::aout)) || $::macosx) + { if (!defined($base)) + { &::call(&::label("PIC_me_up")); + &::set_label("PIC_me_up"); + &::blindpop($dst); + $base=$dst; + $reflabel=&::label("PIC_me_up"); + } + if ($::macosx) + { my $indirect=&::static_label("$nmdecor$sym\$non_lazy_ptr"); + &::mov($dst,&::DWP("$indirect-$reflabel",$base)); + $non_lazy_ptr{"$nmdecor$sym"}=$indirect; + } + elsif ($sym eq "OPENSSL_ia32cap_P" && $::elf>0) + { &::lea($dst,&::DWP("$sym-$reflabel",$base)); } + else + { &::lea($dst,&::DWP("_GLOBAL_OFFSET_TABLE_+[.-$reflabel]", + $base)); + &::mov($dst,&::DWP("$sym\@GOT",$dst)); + } + } + else + { &::lea($dst,&::DWP($sym)); } +} + +sub ::initseg +{ my $f=$nmdecor.shift; + + if ($::android) + { $initseg.=<<___; +.section .init_array +.align 4 +.long $f +___ + } + elsif ($::elf) + { $initseg.=<<___; +.section .init + call $f +___ + } + elsif ($::coff) + { $initseg.=<<___; # applies to both Cygwin and Mingw +.section .ctors +.long $f +___ + } + elsif ($::macosx) + { $initseg.=<<___; +.mod_init_func +.align 2 +.long $f +___ + } + elsif ($::aout) + { my $ctor="${nmdecor}_GLOBAL_\$I\$$f"; + $initseg.=".text\n"; + $initseg.=".type $ctor,\@function\n" if ($::pic); + $initseg.=<<___; # OpenBSD way... +.globl $ctor +.align 2 +$ctor: + jmp $f +___ + } +} + +sub ::dataseg +{ push(@out,".data\n"); } + +*::hidden = sub { push(@out,".hidden\t$nmdecor$_[0]\n"); } if ($::elf); + +1; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/x86masm.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/x86masm.pl new file mode 100644 index 000000000..dffee7621 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/perlasm/x86masm.pl @@ -0,0 +1,206 @@ +#! /usr/bin/env perl +# Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +package x86masm; + +*out=\@::out; + +$::lbdecor="\$L"; # local label decoration +$nmdecor="_"; # external name decoration + +$initseg=""; +$segment=""; + +sub ::generic +{ my ($opcode,@arg)=@_; + + # fix hexadecimal constants + for (@arg) { s/(?= 0x02030000\n"); + push(@out,"safeseh ".&::LABEL($nm,$nmdecor.$nm)."\n"); + push(@out,"%endif\n"); +} + +1; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/build.info new file mode 100644 index 000000000..b87299e6c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/build.info @@ -0,0 +1,5 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + p12_add.c p12_asn.c p12_attr.c p12_crpt.c p12_crt.c p12_decr.c \ + p12_init.c p12_key.c p12_kiss.c p12_mutl.c p12_sbag.c \ + p12_utl.c p12_npas.c pk12err.c p12_p8d.c p12_p8e.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_add.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_add.c new file mode 100644 index 000000000..193ed8097 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_add.c @@ -0,0 +1,164 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include "p12_lcl.h" + +/* Pack an object into an OCTET STRING and turn into a safebag */ + +PKCS12_SAFEBAG *PKCS12_item_pack_safebag(void *obj, const ASN1_ITEM *it, + int nid1, int nid2) +{ + PKCS12_BAGS *bag; + PKCS12_SAFEBAG *safebag; + + if ((bag = PKCS12_BAGS_new()) == NULL) { + PKCS12err(PKCS12_F_PKCS12_ITEM_PACK_SAFEBAG, ERR_R_MALLOC_FAILURE); + return NULL; + } + bag->type = OBJ_nid2obj(nid1); + if (!ASN1_item_pack(obj, it, &bag->value.octet)) { + PKCS12err(PKCS12_F_PKCS12_ITEM_PACK_SAFEBAG, ERR_R_MALLOC_FAILURE); + goto err; + } + if ((safebag = PKCS12_SAFEBAG_new()) == NULL) { + PKCS12err(PKCS12_F_PKCS12_ITEM_PACK_SAFEBAG, ERR_R_MALLOC_FAILURE); + goto err; + } + safebag->value.bag = bag; + safebag->type = OBJ_nid2obj(nid2); + return safebag; + + err: + PKCS12_BAGS_free(bag); + return NULL; +} + +/* Turn a stack of SAFEBAGS into a PKCS#7 data Contentinfo */ +PKCS7 *PKCS12_pack_p7data(STACK_OF(PKCS12_SAFEBAG) *sk) +{ + PKCS7 *p7; + + if ((p7 = PKCS7_new()) == NULL) { + PKCS12err(PKCS12_F_PKCS12_PACK_P7DATA, ERR_R_MALLOC_FAILURE); + return NULL; + } + p7->type = OBJ_nid2obj(NID_pkcs7_data); + if ((p7->d.data = ASN1_OCTET_STRING_new()) == NULL) { + PKCS12err(PKCS12_F_PKCS12_PACK_P7DATA, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!ASN1_item_pack(sk, ASN1_ITEM_rptr(PKCS12_SAFEBAGS), &p7->d.data)) { + PKCS12err(PKCS12_F_PKCS12_PACK_P7DATA, PKCS12_R_CANT_PACK_STRUCTURE); + goto err; + } + return p7; + + err: + PKCS7_free(p7); + return NULL; +} + +/* Unpack SAFEBAGS from PKCS#7 data ContentInfo */ +STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7data(PKCS7 *p7) +{ + if (!PKCS7_type_is_data(p7)) { + PKCS12err(PKCS12_F_PKCS12_UNPACK_P7DATA, + PKCS12_R_CONTENT_TYPE_NOT_DATA); + return NULL; + } + return ASN1_item_unpack(p7->d.data, ASN1_ITEM_rptr(PKCS12_SAFEBAGS)); +} + +/* Turn a stack of SAFEBAGS into a PKCS#7 encrypted data ContentInfo */ + +PKCS7 *PKCS12_pack_p7encdata(int pbe_nid, const char *pass, int passlen, + unsigned char *salt, int saltlen, int iter, + STACK_OF(PKCS12_SAFEBAG) *bags) +{ + PKCS7 *p7; + X509_ALGOR *pbe; + const EVP_CIPHER *pbe_ciph; + + if ((p7 = PKCS7_new()) == NULL) { + PKCS12err(PKCS12_F_PKCS12_PACK_P7ENCDATA, ERR_R_MALLOC_FAILURE); + return NULL; + } + if (!PKCS7_set_type(p7, NID_pkcs7_encrypted)) { + PKCS12err(PKCS12_F_PKCS12_PACK_P7ENCDATA, + PKCS12_R_ERROR_SETTING_ENCRYPTED_DATA_TYPE); + goto err; + } + + pbe_ciph = EVP_get_cipherbynid(pbe_nid); + + if (pbe_ciph) + pbe = PKCS5_pbe2_set(pbe_ciph, iter, salt, saltlen); + else + pbe = PKCS5_pbe_set(pbe_nid, iter, salt, saltlen); + + if (!pbe) { + PKCS12err(PKCS12_F_PKCS12_PACK_P7ENCDATA, ERR_R_MALLOC_FAILURE); + goto err; + } + X509_ALGOR_free(p7->d.encrypted->enc_data->algorithm); + p7->d.encrypted->enc_data->algorithm = pbe; + ASN1_OCTET_STRING_free(p7->d.encrypted->enc_data->enc_data); + if (!(p7->d.encrypted->enc_data->enc_data = + PKCS12_item_i2d_encrypt(pbe, ASN1_ITEM_rptr(PKCS12_SAFEBAGS), pass, + passlen, bags, 1))) { + PKCS12err(PKCS12_F_PKCS12_PACK_P7ENCDATA, PKCS12_R_ENCRYPT_ERROR); + goto err; + } + + return p7; + + err: + PKCS7_free(p7); + return NULL; +} + +STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7encdata(PKCS7 *p7, const char *pass, + int passlen) +{ + if (!PKCS7_type_is_encrypted(p7)) + return NULL; + return PKCS12_item_decrypt_d2i(p7->d.encrypted->enc_data->algorithm, + ASN1_ITEM_rptr(PKCS12_SAFEBAGS), + pass, passlen, + p7->d.encrypted->enc_data->enc_data, 1); +} + +PKCS8_PRIV_KEY_INFO *PKCS12_decrypt_skey(const PKCS12_SAFEBAG *bag, + const char *pass, int passlen) +{ + return PKCS8_decrypt(bag->value.shkeybag, pass, passlen); +} + +int PKCS12_pack_authsafes(PKCS12 *p12, STACK_OF(PKCS7) *safes) +{ + if (ASN1_item_pack(safes, ASN1_ITEM_rptr(PKCS12_AUTHSAFES), + &p12->authsafes->d.data)) + return 1; + return 0; +} + +STACK_OF(PKCS7) *PKCS12_unpack_authsafes(const PKCS12 *p12) +{ + if (!PKCS7_type_is_data(p12->authsafes)) { + PKCS12err(PKCS12_F_PKCS12_UNPACK_AUTHSAFES, + PKCS12_R_CONTENT_TYPE_NOT_DATA); + return NULL; + } + return ASN1_item_unpack(p12->authsafes->d.data, + ASN1_ITEM_rptr(PKCS12_AUTHSAFES)); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_asn.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_asn.c new file mode 100644 index 000000000..422dfc398 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_asn.c @@ -0,0 +1,76 @@ +/* + * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include "p12_lcl.h" + +/* PKCS#12 ASN1 module */ + +ASN1_SEQUENCE(PKCS12) = { + ASN1_SIMPLE(PKCS12, version, ASN1_INTEGER), + ASN1_SIMPLE(PKCS12, authsafes, PKCS7), + ASN1_OPT(PKCS12, mac, PKCS12_MAC_DATA) +} ASN1_SEQUENCE_END(PKCS12) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS12) + +ASN1_SEQUENCE(PKCS12_MAC_DATA) = { + ASN1_SIMPLE(PKCS12_MAC_DATA, dinfo, X509_SIG), + ASN1_SIMPLE(PKCS12_MAC_DATA, salt, ASN1_OCTET_STRING), + ASN1_OPT(PKCS12_MAC_DATA, iter, ASN1_INTEGER) +} ASN1_SEQUENCE_END(PKCS12_MAC_DATA) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS12_MAC_DATA) + +ASN1_ADB_TEMPLATE(bag_default) = ASN1_EXP(PKCS12_BAGS, value.other, ASN1_ANY, 0); + +ASN1_ADB(PKCS12_BAGS) = { + ADB_ENTRY(NID_x509Certificate, ASN1_EXP(PKCS12_BAGS, value.x509cert, ASN1_OCTET_STRING, 0)), + ADB_ENTRY(NID_x509Crl, ASN1_EXP(PKCS12_BAGS, value.x509crl, ASN1_OCTET_STRING, 0)), + ADB_ENTRY(NID_sdsiCertificate, ASN1_EXP(PKCS12_BAGS, value.sdsicert, ASN1_IA5STRING, 0)), +} ASN1_ADB_END(PKCS12_BAGS, 0, type, 0, &bag_default_tt, NULL); + +ASN1_SEQUENCE(PKCS12_BAGS) = { + ASN1_SIMPLE(PKCS12_BAGS, type, ASN1_OBJECT), + ASN1_ADB_OBJECT(PKCS12_BAGS), +} ASN1_SEQUENCE_END(PKCS12_BAGS) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS12_BAGS) + +ASN1_ADB_TEMPLATE(safebag_default) = ASN1_EXP(PKCS12_SAFEBAG, value.other, ASN1_ANY, 0); + +ASN1_ADB(PKCS12_SAFEBAG) = { + ADB_ENTRY(NID_keyBag, ASN1_EXP(PKCS12_SAFEBAG, value.keybag, PKCS8_PRIV_KEY_INFO, 0)), + ADB_ENTRY(NID_pkcs8ShroudedKeyBag, ASN1_EXP(PKCS12_SAFEBAG, value.shkeybag, X509_SIG, 0)), + ADB_ENTRY(NID_safeContentsBag, ASN1_EXP_SEQUENCE_OF(PKCS12_SAFEBAG, value.safes, PKCS12_SAFEBAG, 0)), + ADB_ENTRY(NID_certBag, ASN1_EXP(PKCS12_SAFEBAG, value.bag, PKCS12_BAGS, 0)), + ADB_ENTRY(NID_crlBag, ASN1_EXP(PKCS12_SAFEBAG, value.bag, PKCS12_BAGS, 0)), + ADB_ENTRY(NID_secretBag, ASN1_EXP(PKCS12_SAFEBAG, value.bag, PKCS12_BAGS, 0)) +} ASN1_ADB_END(PKCS12_SAFEBAG, 0, type, 0, &safebag_default_tt, NULL); + +ASN1_SEQUENCE(PKCS12_SAFEBAG) = { + ASN1_SIMPLE(PKCS12_SAFEBAG, type, ASN1_OBJECT), + ASN1_ADB_OBJECT(PKCS12_SAFEBAG), + ASN1_SET_OF_OPT(PKCS12_SAFEBAG, attrib, X509_ATTRIBUTE) +} ASN1_SEQUENCE_END(PKCS12_SAFEBAG) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS12_SAFEBAG) + +/* SEQUENCE OF SafeBag */ +ASN1_ITEM_TEMPLATE(PKCS12_SAFEBAGS) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, PKCS12_SAFEBAGS, PKCS12_SAFEBAG) +ASN1_ITEM_TEMPLATE_END(PKCS12_SAFEBAGS) + +/* Authsafes: SEQUENCE OF PKCS7 */ +ASN1_ITEM_TEMPLATE(PKCS12_AUTHSAFES) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, PKCS12_AUTHSAFES, PKCS7) +ASN1_ITEM_TEMPLATE_END(PKCS12_AUTHSAFES) diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_attr.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_attr.c new file mode 100644 index 000000000..c324f5051 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_attr.c @@ -0,0 +1,103 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include "p12_lcl.h" + +/* Add a local keyid to a safebag */ + +int PKCS12_add_localkeyid(PKCS12_SAFEBAG *bag, unsigned char *name, + int namelen) +{ + if (X509at_add1_attr_by_NID(&bag->attrib, NID_localKeyID, + V_ASN1_OCTET_STRING, name, namelen)) + return 1; + else + return 0; +} + +/* Add key usage to PKCS#8 structure */ + +int PKCS8_add_keyusage(PKCS8_PRIV_KEY_INFO *p8, int usage) +{ + unsigned char us_val = (unsigned char)usage; + return PKCS8_pkey_add1_attr_by_NID(p8, NID_key_usage, + V_ASN1_BIT_STRING, &us_val, 1); +} + +/* Add a friendlyname to a safebag */ + +int PKCS12_add_friendlyname_asc(PKCS12_SAFEBAG *bag, const char *name, + int namelen) +{ + if (X509at_add1_attr_by_NID(&bag->attrib, NID_friendlyName, + MBSTRING_ASC, (unsigned char *)name, namelen)) + return 1; + else + return 0; +} + +int PKCS12_add_friendlyname_utf8(PKCS12_SAFEBAG *bag, const char *name, + int namelen) +{ + if (X509at_add1_attr_by_NID(&bag->attrib, NID_friendlyName, + MBSTRING_UTF8, (unsigned char *)name, namelen)) + return 1; + else + return 0; +} + +int PKCS12_add_friendlyname_uni(PKCS12_SAFEBAG *bag, + const unsigned char *name, int namelen) +{ + if (X509at_add1_attr_by_NID(&bag->attrib, NID_friendlyName, + MBSTRING_BMP, name, namelen)) + return 1; + else + return 0; +} + +int PKCS12_add_CSPName_asc(PKCS12_SAFEBAG *bag, const char *name, int namelen) +{ + if (X509at_add1_attr_by_NID(&bag->attrib, NID_ms_csp_name, + MBSTRING_ASC, (unsigned char *)name, namelen)) + return 1; + else + return 0; +} + +ASN1_TYPE *PKCS12_get_attr_gen(const STACK_OF(X509_ATTRIBUTE) *attrs, + int attr_nid) +{ + X509_ATTRIBUTE *attrib; + int i; + i = X509at_get_attr_by_NID(attrs, attr_nid, -1); + attrib = X509at_get_attr(attrs, i); + return X509_ATTRIBUTE_get0_type(attrib, 0); +} + +char *PKCS12_get_friendlyname(PKCS12_SAFEBAG *bag) +{ + const ASN1_TYPE *atype; + + if ((atype = PKCS12_SAFEBAG_get0_attr(bag, NID_friendlyName)) == NULL) + return NULL; + if (atype->type != V_ASN1_BMPSTRING) + return NULL; + return OPENSSL_uni2utf8(atype->value.bmpstring->data, + atype->value.bmpstring->length); +} + +const STACK_OF(X509_ATTRIBUTE) * +PKCS12_SAFEBAG_get0_attrs(const PKCS12_SAFEBAG *bag) +{ + return bag->attrib; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_crpt.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_crpt.c new file mode 100644 index 000000000..feef9d1fc --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_crpt.c @@ -0,0 +1,70 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include + +/* PKCS#12 PBE algorithms now in static table */ + +void PKCS12_PBE_add(void) +{ +} + +int PKCS12_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, + ASN1_TYPE *param, const EVP_CIPHER *cipher, + const EVP_MD *md, int en_de) +{ + PBEPARAM *pbe; + int saltlen, iter, ret; + unsigned char *salt; + unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH]; + int (*pkcs12_key_gen)(const char *pass, int passlen, + unsigned char *salt, int slen, + int id, int iter, int n, + unsigned char *out, + const EVP_MD *md_type); + + pkcs12_key_gen = PKCS12_key_gen_utf8; + + if (cipher == NULL) + return 0; + + /* Extract useful info from parameter */ + + pbe = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBEPARAM), param); + if (pbe == NULL) { + PKCS12err(PKCS12_F_PKCS12_PBE_KEYIVGEN, PKCS12_R_DECODE_ERROR); + return 0; + } + + if (!pbe->iter) + iter = 1; + else + iter = ASN1_INTEGER_get(pbe->iter); + salt = pbe->salt->data; + saltlen = pbe->salt->length; + if (!(*pkcs12_key_gen)(pass, passlen, salt, saltlen, PKCS12_KEY_ID, + iter, EVP_CIPHER_key_length(cipher), key, md)) { + PKCS12err(PKCS12_F_PKCS12_PBE_KEYIVGEN, PKCS12_R_KEY_GEN_ERROR); + PBEPARAM_free(pbe); + return 0; + } + if (!(*pkcs12_key_gen)(pass, passlen, salt, saltlen, PKCS12_IV_ID, + iter, EVP_CIPHER_iv_length(cipher), iv, md)) { + PKCS12err(PKCS12_F_PKCS12_PBE_KEYIVGEN, PKCS12_R_IV_GEN_ERROR); + PBEPARAM_free(pbe); + return 0; + } + PBEPARAM_free(pbe); + ret = EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, en_de); + OPENSSL_cleanse(key, EVP_MAX_KEY_LENGTH); + OPENSSL_cleanse(iv, EVP_MAX_IV_LENGTH); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_crt.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_crt.c new file mode 100644 index 000000000..10cf8dd58 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_crt.c @@ -0,0 +1,291 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include "p12_lcl.h" + +static int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags, + PKCS12_SAFEBAG *bag); + +static int copy_bag_attr(PKCS12_SAFEBAG *bag, EVP_PKEY *pkey, int nid) +{ + int idx; + X509_ATTRIBUTE *attr; + idx = EVP_PKEY_get_attr_by_NID(pkey, nid, -1); + if (idx < 0) + return 1; + attr = EVP_PKEY_get_attr(pkey, idx); + if (!X509at_add1_attr(&bag->attrib, attr)) + return 0; + return 1; +} + +PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, X509 *cert, + STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter, + int mac_iter, int keytype) +{ + PKCS12 *p12 = NULL; + STACK_OF(PKCS7) *safes = NULL; + STACK_OF(PKCS12_SAFEBAG) *bags = NULL; + PKCS12_SAFEBAG *bag = NULL; + int i; + unsigned char keyid[EVP_MAX_MD_SIZE]; + unsigned int keyidlen = 0; + + /* Set defaults */ + if (!nid_cert) +#ifdef OPENSSL_NO_RC2 + nid_cert = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; +#else + nid_cert = NID_pbe_WithSHA1And40BitRC2_CBC; +#endif + if (!nid_key) + nid_key = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; + if (!iter) + iter = PKCS12_DEFAULT_ITER; + if (!mac_iter) + mac_iter = 1; + + if (!pkey && !cert && !ca) { + PKCS12err(PKCS12_F_PKCS12_CREATE, PKCS12_R_INVALID_NULL_ARGUMENT); + return NULL; + } + + if (pkey && cert) { + if (!X509_check_private_key(cert, pkey)) + return NULL; + X509_digest(cert, EVP_sha1(), keyid, &keyidlen); + } + + if (cert) { + bag = PKCS12_add_cert(&bags, cert); + if (name && !PKCS12_add_friendlyname(bag, name, -1)) + goto err; + if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) + goto err; + } + + /* Add all other certificates */ + for (i = 0; i < sk_X509_num(ca); i++) { + if (!PKCS12_add_cert(&bags, sk_X509_value(ca, i))) + goto err; + } + + if (bags && !PKCS12_add_safe(&safes, bags, nid_cert, iter, pass)) + goto err; + + sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); + bags = NULL; + + if (pkey) { + bag = PKCS12_add_key(&bags, pkey, keytype, iter, nid_key, pass); + + if (!bag) + goto err; + + if (!copy_bag_attr(bag, pkey, NID_ms_csp_name)) + goto err; + if (!copy_bag_attr(bag, pkey, NID_LocalKeySet)) + goto err; + + if (name && !PKCS12_add_friendlyname(bag, name, -1)) + goto err; + if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) + goto err; + } + + if (bags && !PKCS12_add_safe(&safes, bags, -1, 0, NULL)) + goto err; + + sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); + bags = NULL; + + p12 = PKCS12_add_safes(safes, 0); + + if (!p12) + goto err; + + sk_PKCS7_pop_free(safes, PKCS7_free); + + safes = NULL; + + if ((mac_iter != -1) && + !PKCS12_set_mac(p12, pass, -1, NULL, 0, mac_iter, NULL)) + goto err; + + return p12; + + err: + PKCS12_free(p12); + sk_PKCS7_pop_free(safes, PKCS7_free); + sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); + return NULL; + +} + +PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert) +{ + PKCS12_SAFEBAG *bag = NULL; + char *name; + int namelen = -1; + unsigned char *keyid; + int keyidlen = -1; + + /* Add user certificate */ + if ((bag = PKCS12_SAFEBAG_create_cert(cert)) == NULL) + goto err; + + /* + * Use friendlyName and localKeyID in certificate. (if present) + */ + + name = (char *)X509_alias_get0(cert, &namelen); + + if (name && !PKCS12_add_friendlyname(bag, name, namelen)) + goto err; + + keyid = X509_keyid_get0(cert, &keyidlen); + + if (keyid && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) + goto err; + + if (!pkcs12_add_bag(pbags, bag)) + goto err; + + return bag; + + err: + PKCS12_SAFEBAG_free(bag); + return NULL; + +} + +PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags, + EVP_PKEY *key, int key_usage, int iter, + int nid_key, const char *pass) +{ + + PKCS12_SAFEBAG *bag = NULL; + PKCS8_PRIV_KEY_INFO *p8 = NULL; + + /* Make a PKCS#8 structure */ + if ((p8 = EVP_PKEY2PKCS8(key)) == NULL) + goto err; + if (key_usage && !PKCS8_add_keyusage(p8, key_usage)) + goto err; + if (nid_key != -1) { + bag = PKCS12_SAFEBAG_create_pkcs8_encrypt(nid_key, pass, -1, NULL, 0, + iter, p8); + PKCS8_PRIV_KEY_INFO_free(p8); + } else + bag = PKCS12_SAFEBAG_create0_p8inf(p8); + + if (!bag) + goto err; + + if (!pkcs12_add_bag(pbags, bag)) + goto err; + + return bag; + + err: + PKCS12_SAFEBAG_free(bag); + return NULL; + +} + +int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags, + int nid_safe, int iter, const char *pass) +{ + PKCS7 *p7 = NULL; + int free_safes = 0; + + if (!*psafes) { + *psafes = sk_PKCS7_new_null(); + if (!*psafes) + return 0; + free_safes = 1; + } else + free_safes = 0; + + if (nid_safe == 0) +#ifdef OPENSSL_NO_RC2 + nid_safe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; +#else + nid_safe = NID_pbe_WithSHA1And40BitRC2_CBC; +#endif + + if (nid_safe == -1) + p7 = PKCS12_pack_p7data(bags); + else + p7 = PKCS12_pack_p7encdata(nid_safe, pass, -1, NULL, 0, iter, bags); + if (!p7) + goto err; + + if (!sk_PKCS7_push(*psafes, p7)) + goto err; + + return 1; + + err: + if (free_safes) { + sk_PKCS7_free(*psafes); + *psafes = NULL; + } + PKCS7_free(p7); + return 0; + +} + +static int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags, + PKCS12_SAFEBAG *bag) +{ + int free_bags; + if (!pbags) + return 1; + if (!*pbags) { + *pbags = sk_PKCS12_SAFEBAG_new_null(); + if (!*pbags) + return 0; + free_bags = 1; + } else + free_bags = 0; + + if (!sk_PKCS12_SAFEBAG_push(*pbags, bag)) { + if (free_bags) { + sk_PKCS12_SAFEBAG_free(*pbags); + *pbags = NULL; + } + return 0; + } + + return 1; + +} + +PKCS12 *PKCS12_add_safes(STACK_OF(PKCS7) *safes, int nid_p7) +{ + PKCS12 *p12; + if (nid_p7 <= 0) + nid_p7 = NID_pkcs7_data; + p12 = PKCS12_init(nid_p7); + + if (!p12) + return NULL; + + if (!PKCS12_pack_authsafes(p12, safes)) { + PKCS12_free(p12); + return NULL; + } + + return p12; + +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_decr.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_decr.c new file mode 100644 index 000000000..3c860584e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_decr.c @@ -0,0 +1,155 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include + +/* Define this to dump decrypted output to files called DERnnn */ +/* + * #define OPENSSL_DEBUG_DECRYPT + */ + +/* + * Encrypt/Decrypt a buffer based on password and algor, result in a + * OPENSSL_malloc'ed buffer + */ +unsigned char *PKCS12_pbe_crypt(const X509_ALGOR *algor, + const char *pass, int passlen, + const unsigned char *in, int inlen, + unsigned char **data, int *datalen, int en_de) +{ + unsigned char *out = NULL; + int outlen, i; + EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); + + if (ctx == NULL) { + PKCS12err(PKCS12_F_PKCS12_PBE_CRYPT, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* Decrypt data */ + if (!EVP_PBE_CipherInit(algor->algorithm, pass, passlen, + algor->parameter, ctx, en_de)) { + PKCS12err(PKCS12_F_PKCS12_PBE_CRYPT, + PKCS12_R_PKCS12_ALGOR_CIPHERINIT_ERROR); + goto err; + } + + if ((out = OPENSSL_malloc(inlen + EVP_CIPHER_CTX_block_size(ctx))) + == NULL) { + PKCS12err(PKCS12_F_PKCS12_PBE_CRYPT, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!EVP_CipherUpdate(ctx, out, &i, in, inlen)) { + OPENSSL_free(out); + out = NULL; + PKCS12err(PKCS12_F_PKCS12_PBE_CRYPT, ERR_R_EVP_LIB); + goto err; + } + + outlen = i; + if (!EVP_CipherFinal_ex(ctx, out + i, &i)) { + OPENSSL_free(out); + out = NULL; + PKCS12err(PKCS12_F_PKCS12_PBE_CRYPT, + PKCS12_R_PKCS12_CIPHERFINAL_ERROR); + goto err; + } + outlen += i; + if (datalen) + *datalen = outlen; + if (data) + *data = out; + err: + EVP_CIPHER_CTX_free(ctx); + return out; + +} + +/* + * Decrypt an OCTET STRING and decode ASN1 structure if zbuf set zero buffer + * after use. + */ + +void *PKCS12_item_decrypt_d2i(const X509_ALGOR *algor, const ASN1_ITEM *it, + const char *pass, int passlen, + const ASN1_OCTET_STRING *oct, int zbuf) +{ + unsigned char *out; + const unsigned char *p; + void *ret; + int outlen; + + if (!PKCS12_pbe_crypt(algor, pass, passlen, oct->data, oct->length, + &out, &outlen, 0)) { + PKCS12err(PKCS12_F_PKCS12_ITEM_DECRYPT_D2I, + PKCS12_R_PKCS12_PBE_CRYPT_ERROR); + return NULL; + } + p = out; +#ifdef OPENSSL_DEBUG_DECRYPT + { + FILE *op; + + char fname[30]; + static int fnm = 1; + sprintf(fname, "DER%d", fnm++); + op = fopen(fname, "wb"); + fwrite(p, 1, outlen, op); + fclose(op); + } +#endif + ret = ASN1_item_d2i(NULL, &p, outlen, it); + if (zbuf) + OPENSSL_cleanse(out, outlen); + if (!ret) + PKCS12err(PKCS12_F_PKCS12_ITEM_DECRYPT_D2I, PKCS12_R_DECODE_ERROR); + OPENSSL_free(out); + return ret; +} + +/* + * Encode ASN1 structure and encrypt, return OCTET STRING if zbuf set zero + * encoding. + */ + +ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt(X509_ALGOR *algor, + const ASN1_ITEM *it, + const char *pass, int passlen, + void *obj, int zbuf) +{ + ASN1_OCTET_STRING *oct = NULL; + unsigned char *in = NULL; + int inlen; + + if ((oct = ASN1_OCTET_STRING_new()) == NULL) { + PKCS12err(PKCS12_F_PKCS12_ITEM_I2D_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto err; + } + inlen = ASN1_item_i2d(obj, &in, it); + if (!in) { + PKCS12err(PKCS12_F_PKCS12_ITEM_I2D_ENCRYPT, PKCS12_R_ENCODE_ERROR); + goto err; + } + if (!PKCS12_pbe_crypt(algor, pass, passlen, in, inlen, &oct->data, + &oct->length, 1)) { + PKCS12err(PKCS12_F_PKCS12_ITEM_I2D_ENCRYPT, PKCS12_R_ENCRYPT_ERROR); + OPENSSL_free(in); + goto err; + } + if (zbuf) + OPENSSL_cleanse(in, inlen); + OPENSSL_free(in); + return oct; + err: + ASN1_OCTET_STRING_free(oct); + return NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_init.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_init.c new file mode 100644 index 000000000..88db0f2dc --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_init.c @@ -0,0 +1,44 @@ +/* + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include "p12_lcl.h" + +/* Initialise a PKCS12 structure to take data */ + +PKCS12 *PKCS12_init(int mode) +{ + PKCS12 *pkcs12; + + if ((pkcs12 = PKCS12_new()) == NULL) { + PKCS12err(PKCS12_F_PKCS12_INIT, ERR_R_MALLOC_FAILURE); + return NULL; + } + if (!ASN1_INTEGER_set(pkcs12->version, 3)) + goto err; + pkcs12->authsafes->type = OBJ_nid2obj(mode); + switch (mode) { + case NID_pkcs7_data: + if ((pkcs12->authsafes->d.data = ASN1_OCTET_STRING_new()) == NULL) { + PKCS12err(PKCS12_F_PKCS12_INIT, ERR_R_MALLOC_FAILURE); + goto err; + } + break; + default: + PKCS12err(PKCS12_F_PKCS12_INIT, PKCS12_R_UNSUPPORTED_PKCS12_MODE); + goto err; + } + return pkcs12; + + err: + PKCS12_free(pkcs12); + return NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_key.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_key.c new file mode 100644 index 000000000..ab31a6129 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_key.c @@ -0,0 +1,183 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include + +/* Uncomment out this line to get debugging info about key generation */ +/* + * #define OPENSSL_DEBUG_KEYGEN + */ +#ifdef OPENSSL_DEBUG_KEYGEN +# include +extern BIO *bio_err; +void h__dump(unsigned char *p, int len); +#endif + +/* PKCS12 compatible key/IV generation */ +#ifndef min +# define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt, + int saltlen, int id, int iter, int n, + unsigned char *out, const EVP_MD *md_type) +{ + int ret; + unsigned char *unipass; + int uniplen; + + if (!pass) { + unipass = NULL; + uniplen = 0; + } else if (!OPENSSL_asc2uni(pass, passlen, &unipass, &uniplen)) { + PKCS12err(PKCS12_F_PKCS12_KEY_GEN_ASC, ERR_R_MALLOC_FAILURE); + return 0; + } + ret = PKCS12_key_gen_uni(unipass, uniplen, salt, saltlen, + id, iter, n, out, md_type); + if (ret <= 0) + return 0; + OPENSSL_clear_free(unipass, uniplen); + return ret; +} + +int PKCS12_key_gen_utf8(const char *pass, int passlen, unsigned char *salt, + int saltlen, int id, int iter, int n, + unsigned char *out, const EVP_MD *md_type) +{ + int ret; + unsigned char *unipass; + int uniplen; + + if (!pass) { + unipass = NULL; + uniplen = 0; + } else if (!OPENSSL_utf82uni(pass, passlen, &unipass, &uniplen)) { + PKCS12err(PKCS12_F_PKCS12_KEY_GEN_UTF8, ERR_R_MALLOC_FAILURE); + return 0; + } + ret = PKCS12_key_gen_uni(unipass, uniplen, salt, saltlen, + id, iter, n, out, md_type); + if (ret <= 0) + return 0; + OPENSSL_clear_free(unipass, uniplen); + return ret; +} + +int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt, + int saltlen, int id, int iter, int n, + unsigned char *out, const EVP_MD *md_type) +{ + unsigned char *B = NULL, *D = NULL, *I = NULL, *p = NULL, *Ai = NULL; + int Slen, Plen, Ilen; + int i, j, u, v; + int ret = 0; + EVP_MD_CTX *ctx = NULL; +#ifdef OPENSSL_DEBUG_KEYGEN + unsigned char *tmpout = out; + int tmpn = n; +#endif + + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) + goto err; + +#ifdef OPENSSL_DEBUG_KEYGEN + fprintf(stderr, "KEYGEN DEBUG\n"); + fprintf(stderr, "ID %d, ITER %d\n", id, iter); + fprintf(stderr, "Password (length %d):\n", passlen); + h__dump(pass, passlen); + fprintf(stderr, "Salt (length %d):\n", saltlen); + h__dump(salt, saltlen); +#endif + v = EVP_MD_block_size(md_type); + u = EVP_MD_size(md_type); + if (u < 0 || v <= 0) + goto err; + D = OPENSSL_malloc(v); + Ai = OPENSSL_malloc(u); + B = OPENSSL_malloc(v + 1); + Slen = v * ((saltlen + v - 1) / v); + if (passlen) + Plen = v * ((passlen + v - 1) / v); + else + Plen = 0; + Ilen = Slen + Plen; + I = OPENSSL_malloc(Ilen); + if (D == NULL || Ai == NULL || B == NULL || I == NULL) + goto err; + for (i = 0; i < v; i++) + D[i] = id; + p = I; + for (i = 0; i < Slen; i++) + *p++ = salt[i % saltlen]; + for (i = 0; i < Plen; i++) + *p++ = pass[i % passlen]; + for (;;) { + if (!EVP_DigestInit_ex(ctx, md_type, NULL) + || !EVP_DigestUpdate(ctx, D, v) + || !EVP_DigestUpdate(ctx, I, Ilen) + || !EVP_DigestFinal_ex(ctx, Ai, NULL)) + goto err; + for (j = 1; j < iter; j++) { + if (!EVP_DigestInit_ex(ctx, md_type, NULL) + || !EVP_DigestUpdate(ctx, Ai, u) + || !EVP_DigestFinal_ex(ctx, Ai, NULL)) + goto err; + } + memcpy(out, Ai, min(n, u)); + if (u >= n) { +#ifdef OPENSSL_DEBUG_KEYGEN + fprintf(stderr, "Output KEY (length %d)\n", tmpn); + h__dump(tmpout, tmpn); +#endif + ret = 1; + goto end; + } + n -= u; + out += u; + for (j = 0; j < v; j++) + B[j] = Ai[j % u]; + for (j = 0; j < Ilen; j += v) { + int k; + unsigned char *Ij = I + j; + uint16_t c = 1; + + /* Work out Ij = Ij + B + 1 */ + for (k = v - 1; k >= 0; k--) { + c += Ij[k] + B[k]; + Ij[k] = (unsigned char)c; + c >>= 8; + } + } + } + + err: + PKCS12err(PKCS12_F_PKCS12_KEY_GEN_UNI, ERR_R_MALLOC_FAILURE); + + end: + OPENSSL_free(Ai); + OPENSSL_free(B); + OPENSSL_free(D); + OPENSSL_free(I); + EVP_MD_CTX_free(ctx); + return ret; +} + +#ifdef OPENSSL_DEBUG_KEYGEN +void h__dump(unsigned char *p, int len) +{ + for (; len--; p++) + fprintf(stderr, "%02X", *p); + fprintf(stderr, "\n"); +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_kiss.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_kiss.c new file mode 100644 index 000000000..7ab98385a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_kiss.c @@ -0,0 +1,250 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include + +/* Simplified PKCS#12 routines */ + +static int parse_pk12(PKCS12 *p12, const char *pass, int passlen, + EVP_PKEY **pkey, STACK_OF(X509) *ocerts); + +static int parse_bags(const STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass, + int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts); + +static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen, + EVP_PKEY **pkey, STACK_OF(X509) *ocerts); + +/* + * Parse and decrypt a PKCS#12 structure returning user key, user cert and + * other (CA) certs. Note either ca should be NULL, *ca should be NULL, or it + * should point to a valid STACK structure. pkey and cert can be passed + * uninitialised. + */ + +int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, + STACK_OF(X509) **ca) +{ + STACK_OF(X509) *ocerts = NULL; + X509 *x = NULL; + + if (pkey) + *pkey = NULL; + if (cert) + *cert = NULL; + + /* Check for NULL PKCS12 structure */ + + if (!p12) { + PKCS12err(PKCS12_F_PKCS12_PARSE, + PKCS12_R_INVALID_NULL_PKCS12_POINTER); + return 0; + } + + /* Check the mac */ + + /* + * If password is zero length or NULL then try verifying both cases to + * determine which password is correct. The reason for this is that under + * PKCS#12 password based encryption no password and a zero length + * password are two different things... + */ + + if (!pass || !*pass) { + if (PKCS12_verify_mac(p12, NULL, 0)) + pass = NULL; + else if (PKCS12_verify_mac(p12, "", 0)) + pass = ""; + else { + PKCS12err(PKCS12_F_PKCS12_PARSE, PKCS12_R_MAC_VERIFY_FAILURE); + goto err; + } + } else if (!PKCS12_verify_mac(p12, pass, -1)) { + PKCS12err(PKCS12_F_PKCS12_PARSE, PKCS12_R_MAC_VERIFY_FAILURE); + goto err; + } + + /* Allocate stack for other certificates */ + ocerts = sk_X509_new_null(); + + if (!ocerts) { + PKCS12err(PKCS12_F_PKCS12_PARSE, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!parse_pk12(p12, pass, -1, pkey, ocerts)) { + PKCS12err(PKCS12_F_PKCS12_PARSE, PKCS12_R_PARSE_ERROR); + goto err; + } + + while ((x = sk_X509_pop(ocerts))) { + if (pkey && *pkey && cert && !*cert) { + ERR_set_mark(); + if (X509_check_private_key(x, *pkey)) { + *cert = x; + x = NULL; + } + ERR_pop_to_mark(); + } + + if (ca && x) { + if (!*ca) + *ca = sk_X509_new_null(); + if (!*ca) + goto err; + if (!sk_X509_push(*ca, x)) + goto err; + x = NULL; + } + X509_free(x); + } + + sk_X509_pop_free(ocerts, X509_free); + + return 1; + + err: + + if (pkey) { + EVP_PKEY_free(*pkey); + *pkey = NULL; + } + if (cert) { + X509_free(*cert); + *cert = NULL; + } + X509_free(x); + sk_X509_pop_free(ocerts, X509_free); + return 0; + +} + +/* Parse the outer PKCS#12 structure */ + +static int parse_pk12(PKCS12 *p12, const char *pass, int passlen, + EVP_PKEY **pkey, STACK_OF(X509) *ocerts) +{ + STACK_OF(PKCS7) *asafes; + STACK_OF(PKCS12_SAFEBAG) *bags; + int i, bagnid; + PKCS7 *p7; + + if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL) + return 0; + for (i = 0; i < sk_PKCS7_num(asafes); i++) { + p7 = sk_PKCS7_value(asafes, i); + bagnid = OBJ_obj2nid(p7->type); + if (bagnid == NID_pkcs7_data) { + bags = PKCS12_unpack_p7data(p7); + } else if (bagnid == NID_pkcs7_encrypted) { + bags = PKCS12_unpack_p7encdata(p7, pass, passlen); + } else + continue; + if (!bags) { + sk_PKCS7_pop_free(asafes, PKCS7_free); + return 0; + } + if (!parse_bags(bags, pass, passlen, pkey, ocerts)) { + sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); + sk_PKCS7_pop_free(asafes, PKCS7_free); + return 0; + } + sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); + } + sk_PKCS7_pop_free(asafes, PKCS7_free); + return 1; +} + +static int parse_bags(const STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass, + int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts) +{ + int i; + for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) { + if (!parse_bag(sk_PKCS12_SAFEBAG_value(bags, i), + pass, passlen, pkey, ocerts)) + return 0; + } + return 1; +} + +static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen, + EVP_PKEY **pkey, STACK_OF(X509) *ocerts) +{ + PKCS8_PRIV_KEY_INFO *p8; + X509 *x509; + const ASN1_TYPE *attrib; + ASN1_BMPSTRING *fname = NULL; + ASN1_OCTET_STRING *lkid = NULL; + + if ((attrib = PKCS12_SAFEBAG_get0_attr(bag, NID_friendlyName))) + fname = attrib->value.bmpstring; + + if ((attrib = PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID))) + lkid = attrib->value.octet_string; + + switch (PKCS12_SAFEBAG_get_nid(bag)) { + case NID_keyBag: + if (!pkey || *pkey) + return 1; + *pkey = EVP_PKCS82PKEY(PKCS12_SAFEBAG_get0_p8inf(bag)); + if (*pkey == NULL) + return 0; + break; + + case NID_pkcs8ShroudedKeyBag: + if (!pkey || *pkey) + return 1; + if ((p8 = PKCS12_decrypt_skey(bag, pass, passlen)) == NULL) + return 0; + *pkey = EVP_PKCS82PKEY(p8); + PKCS8_PRIV_KEY_INFO_free(p8); + if (!(*pkey)) + return 0; + break; + + case NID_certBag: + if (PKCS12_SAFEBAG_get_bag_nid(bag) != NID_x509Certificate) + return 1; + if ((x509 = PKCS12_SAFEBAG_get1_cert(bag)) == NULL) + return 0; + if (lkid && !X509_keyid_set1(x509, lkid->data, lkid->length)) { + X509_free(x509); + return 0; + } + if (fname) { + int len, r; + unsigned char *data; + len = ASN1_STRING_to_UTF8(&data, fname); + if (len >= 0) { + r = X509_alias_set1(x509, data, len); + OPENSSL_free(data); + if (!r) { + X509_free(x509); + return 0; + } + } + } + + if (!sk_X509_push(ocerts, x509)) { + X509_free(x509); + return 0; + } + + break; + + case NID_safeContentsBag: + return parse_bags(PKCS12_SAFEBAG_get0_safes(bag), pass, passlen, pkey, + ocerts); + + default: + return 1; + } + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_lcl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_lcl.h new file mode 100644 index 000000000..0b52f1e1f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_lcl.h @@ -0,0 +1,43 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +struct PKCS12_MAC_DATA_st { + X509_SIG *dinfo; + ASN1_OCTET_STRING *salt; + ASN1_INTEGER *iter; /* defaults to 1 */ +}; + +struct PKCS12_st { + ASN1_INTEGER *version; + PKCS12_MAC_DATA *mac; + PKCS7 *authsafes; +}; + +struct PKCS12_SAFEBAG_st { + ASN1_OBJECT *type; + union { + struct pkcs12_bag_st *bag; /* secret, crl and certbag */ + struct pkcs8_priv_key_info_st *keybag; /* keybag */ + X509_SIG *shkeybag; /* shrouded key bag */ + STACK_OF(PKCS12_SAFEBAG) *safes; + ASN1_TYPE *other; + } value; + STACK_OF(X509_ATTRIBUTE) *attrib; +}; + +struct pkcs12_bag_st { + ASN1_OBJECT *type; + union { + ASN1_OCTET_STRING *x509cert; + ASN1_OCTET_STRING *x509crl; + ASN1_OCTET_STRING *octet; + ASN1_IA5STRING *sdsicert; + ASN1_TYPE *other; /* Secret or other bag */ + } value; +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_mutl.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_mutl.c new file mode 100644 index 000000000..0cbbed364 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_mutl.c @@ -0,0 +1,246 @@ +/* + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "p12_lcl.h" + +int PKCS12_mac_present(const PKCS12 *p12) +{ + return p12->mac ? 1 : 0; +} + +void PKCS12_get0_mac(const ASN1_OCTET_STRING **pmac, + const X509_ALGOR **pmacalg, + const ASN1_OCTET_STRING **psalt, + const ASN1_INTEGER **piter, + const PKCS12 *p12) +{ + if (p12->mac) { + X509_SIG_get0(p12->mac->dinfo, pmacalg, pmac); + if (psalt) + *psalt = p12->mac->salt; + if (piter) + *piter = p12->mac->iter; + } else { + if (pmac) + *pmac = NULL; + if (pmacalg) + *pmacalg = NULL; + if (psalt) + *psalt = NULL; + if (piter) + *piter = NULL; + } +} + +#define TK26_MAC_KEY_LEN 32 + +static int pkcs12_gen_gost_mac_key(const char *pass, int passlen, + const unsigned char *salt, int saltlen, + int iter, int keylen, unsigned char *key, + const EVP_MD *digest) +{ + unsigned char out[96]; + + if (keylen != TK26_MAC_KEY_LEN) { + return 0; + } + + if (!PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, + digest, sizeof(out), out)) { + return 0; + } + memcpy(key, out + sizeof(out) - TK26_MAC_KEY_LEN, TK26_MAC_KEY_LEN); + OPENSSL_cleanse(out, sizeof(out)); + return 1; +} + +/* Generate a MAC */ +static int pkcs12_gen_mac(PKCS12 *p12, const char *pass, int passlen, + unsigned char *mac, unsigned int *maclen, + int (*pkcs12_key_gen)(const char *pass, int passlen, + unsigned char *salt, int slen, + int id, int iter, int n, + unsigned char *out, + const EVP_MD *md_type)) +{ + int ret = 0; + const EVP_MD *md_type; + HMAC_CTX *hmac = NULL; + unsigned char key[EVP_MAX_MD_SIZE], *salt; + int saltlen, iter; + int md_size = 0; + int md_type_nid; + const X509_ALGOR *macalg; + const ASN1_OBJECT *macoid; + + if (pkcs12_key_gen == NULL) + pkcs12_key_gen = PKCS12_key_gen_utf8; + + if (!PKCS7_type_is_data(p12->authsafes)) { + PKCS12err(PKCS12_F_PKCS12_GEN_MAC, PKCS12_R_CONTENT_TYPE_NOT_DATA); + return 0; + } + + salt = p12->mac->salt->data; + saltlen = p12->mac->salt->length; + if (!p12->mac->iter) + iter = 1; + else + iter = ASN1_INTEGER_get(p12->mac->iter); + X509_SIG_get0(p12->mac->dinfo, &macalg, NULL); + X509_ALGOR_get0(&macoid, NULL, NULL, macalg); + if ((md_type = EVP_get_digestbyobj(macoid)) == NULL) { + PKCS12err(PKCS12_F_PKCS12_GEN_MAC, PKCS12_R_UNKNOWN_DIGEST_ALGORITHM); + return 0; + } + md_size = EVP_MD_size(md_type); + md_type_nid = EVP_MD_type(md_type); + if (md_size < 0) + return 0; + if ((md_type_nid == NID_id_GostR3411_94 + || md_type_nid == NID_id_GostR3411_2012_256 + || md_type_nid == NID_id_GostR3411_2012_512) + && ossl_safe_getenv("LEGACY_GOST_PKCS12") == NULL) { + md_size = TK26_MAC_KEY_LEN; + if (!pkcs12_gen_gost_mac_key(pass, passlen, salt, saltlen, iter, + md_size, key, md_type)) { + PKCS12err(PKCS12_F_PKCS12_GEN_MAC, PKCS12_R_KEY_GEN_ERROR); + goto err; + } + } else + if (!(*pkcs12_key_gen)(pass, passlen, salt, saltlen, PKCS12_MAC_ID, + iter, md_size, key, md_type)) { + PKCS12err(PKCS12_F_PKCS12_GEN_MAC, PKCS12_R_KEY_GEN_ERROR); + goto err; + } + if ((hmac = HMAC_CTX_new()) == NULL + || !HMAC_Init_ex(hmac, key, md_size, md_type, NULL) + || !HMAC_Update(hmac, p12->authsafes->d.data->data, + p12->authsafes->d.data->length) + || !HMAC_Final(hmac, mac, maclen)) { + goto err; + } + ret = 1; + +err: + OPENSSL_cleanse(key, sizeof(key)); + HMAC_CTX_free(hmac); + return ret; +} + +int PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen, + unsigned char *mac, unsigned int *maclen) +{ + return pkcs12_gen_mac(p12, pass, passlen, mac, maclen, NULL); +} + +/* Verify the mac */ +int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen) +{ + unsigned char mac[EVP_MAX_MD_SIZE]; + unsigned int maclen; + const ASN1_OCTET_STRING *macoct; + + if (p12->mac == NULL) { + PKCS12err(PKCS12_F_PKCS12_VERIFY_MAC, PKCS12_R_MAC_ABSENT); + return 0; + } + if (!pkcs12_gen_mac(p12, pass, passlen, mac, &maclen, + PKCS12_key_gen_utf8)) { + PKCS12err(PKCS12_F_PKCS12_VERIFY_MAC, PKCS12_R_MAC_GENERATION_ERROR); + return 0; + } + X509_SIG_get0(p12->mac->dinfo, NULL, &macoct); + if ((maclen != (unsigned int)ASN1_STRING_length(macoct)) + || CRYPTO_memcmp(mac, ASN1_STRING_get0_data(macoct), maclen) != 0) + return 0; + + return 1; +} + +/* Set a mac */ + +int PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen, + unsigned char *salt, int saltlen, int iter, + const EVP_MD *md_type) +{ + unsigned char mac[EVP_MAX_MD_SIZE]; + unsigned int maclen; + ASN1_OCTET_STRING *macoct; + + if (!md_type) + md_type = EVP_sha1(); + if (PKCS12_setup_mac(p12, iter, salt, saltlen, md_type) == PKCS12_ERROR) { + PKCS12err(PKCS12_F_PKCS12_SET_MAC, PKCS12_R_MAC_SETUP_ERROR); + return 0; + } + /* + * Note that output mac is forced to UTF-8... + */ + if (!pkcs12_gen_mac(p12, pass, passlen, mac, &maclen, + PKCS12_key_gen_utf8)) { + PKCS12err(PKCS12_F_PKCS12_SET_MAC, PKCS12_R_MAC_GENERATION_ERROR); + return 0; + } + X509_SIG_getm(p12->mac->dinfo, NULL, &macoct); + if (!ASN1_OCTET_STRING_set(macoct, mac, maclen)) { + PKCS12err(PKCS12_F_PKCS12_SET_MAC, PKCS12_R_MAC_STRING_SET_ERROR); + return 0; + } + return 1; +} + +/* Set up a mac structure */ +int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt, int saltlen, + const EVP_MD *md_type) +{ + X509_ALGOR *macalg; + + PKCS12_MAC_DATA_free(p12->mac); + p12->mac = NULL; + + if ((p12->mac = PKCS12_MAC_DATA_new()) == NULL) + return PKCS12_ERROR; + if (iter > 1) { + if ((p12->mac->iter = ASN1_INTEGER_new()) == NULL) { + PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE); + return 0; + } + if (!ASN1_INTEGER_set(p12->mac->iter, iter)) { + PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE); + return 0; + } + } + if (!saltlen) + saltlen = PKCS12_SALT_LEN; + if ((p12->mac->salt->data = OPENSSL_malloc(saltlen)) == NULL) { + PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE); + return 0; + } + p12->mac->salt->length = saltlen; + if (!salt) { + if (RAND_bytes(p12->mac->salt->data, saltlen) <= 0) + return 0; + } else + memcpy(p12->mac->salt->data, salt, saltlen); + X509_SIG_getm(p12->mac->dinfo, &macalg, NULL); + if (!X509_ALGOR_set0(macalg, OBJ_nid2obj(EVP_MD_type(md_type)), + V_ASN1_NULL, NULL)) { + PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE); + return 0; + } + + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_npas.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_npas.c new file mode 100644 index 000000000..0ce75ed33 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_npas.c @@ -0,0 +1,184 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include +#include "p12_lcl.h" + +/* PKCS#12 password change routine */ + +static int newpass_p12(PKCS12 *p12, const char *oldpass, const char *newpass); +static int newpass_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *oldpass, + const char *newpass); +static int newpass_bag(PKCS12_SAFEBAG *bag, const char *oldpass, + const char *newpass); +static int alg_get(const X509_ALGOR *alg, int *pnid, int *piter, + int *psaltlen); + +/* + * Change the password on a PKCS#12 structure. + */ + +int PKCS12_newpass(PKCS12 *p12, const char *oldpass, const char *newpass) +{ + /* Check for NULL PKCS12 structure */ + + if (!p12) { + PKCS12err(PKCS12_F_PKCS12_NEWPASS, + PKCS12_R_INVALID_NULL_PKCS12_POINTER); + return 0; + } + + /* Check the mac */ + + if (!PKCS12_verify_mac(p12, oldpass, -1)) { + PKCS12err(PKCS12_F_PKCS12_NEWPASS, PKCS12_R_MAC_VERIFY_FAILURE); + return 0; + } + + if (!newpass_p12(p12, oldpass, newpass)) { + PKCS12err(PKCS12_F_PKCS12_NEWPASS, PKCS12_R_PARSE_ERROR); + return 0; + } + + return 1; +} + +/* Parse the outer PKCS#12 structure */ + +static int newpass_p12(PKCS12 *p12, const char *oldpass, const char *newpass) +{ + STACK_OF(PKCS7) *asafes = NULL, *newsafes = NULL; + STACK_OF(PKCS12_SAFEBAG) *bags = NULL; + int i, bagnid, pbe_nid = 0, pbe_iter = 0, pbe_saltlen = 0; + PKCS7 *p7, *p7new; + ASN1_OCTET_STRING *p12_data_tmp = NULL, *macoct = NULL; + unsigned char mac[EVP_MAX_MD_SIZE]; + unsigned int maclen; + int rv = 0; + + if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL) + goto err; + if ((newsafes = sk_PKCS7_new_null()) == NULL) + goto err; + for (i = 0; i < sk_PKCS7_num(asafes); i++) { + p7 = sk_PKCS7_value(asafes, i); + bagnid = OBJ_obj2nid(p7->type); + if (bagnid == NID_pkcs7_data) { + bags = PKCS12_unpack_p7data(p7); + } else if (bagnid == NID_pkcs7_encrypted) { + bags = PKCS12_unpack_p7encdata(p7, oldpass, -1); + if (!alg_get(p7->d.encrypted->enc_data->algorithm, + &pbe_nid, &pbe_iter, &pbe_saltlen)) + goto err; + } else { + continue; + } + if (bags == NULL) + goto err; + if (!newpass_bags(bags, oldpass, newpass)) + goto err; + /* Repack bag in same form with new password */ + if (bagnid == NID_pkcs7_data) + p7new = PKCS12_pack_p7data(bags); + else + p7new = PKCS12_pack_p7encdata(pbe_nid, newpass, -1, NULL, + pbe_saltlen, pbe_iter, bags); + if (!p7new || !sk_PKCS7_push(newsafes, p7new)) + goto err; + sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); + bags = NULL; + } + + /* Repack safe: save old safe in case of error */ + + p12_data_tmp = p12->authsafes->d.data; + if ((p12->authsafes->d.data = ASN1_OCTET_STRING_new()) == NULL) + goto err; + if (!PKCS12_pack_authsafes(p12, newsafes)) + goto err; + + if (!PKCS12_gen_mac(p12, newpass, -1, mac, &maclen)) + goto err; + X509_SIG_getm(p12->mac->dinfo, NULL, &macoct); + if (!ASN1_OCTET_STRING_set(macoct, mac, maclen)) + goto err; + + rv = 1; + +err: + /* Restore old safe if necessary */ + if (rv == 1) { + ASN1_OCTET_STRING_free(p12_data_tmp); + } else if (p12_data_tmp != NULL) { + ASN1_OCTET_STRING_free(p12->authsafes->d.data); + p12->authsafes->d.data = p12_data_tmp; + } + sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); + sk_PKCS7_pop_free(asafes, PKCS7_free); + sk_PKCS7_pop_free(newsafes, PKCS7_free); + return rv; +} + +static int newpass_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *oldpass, + const char *newpass) +{ + int i; + for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) { + if (!newpass_bag(sk_PKCS12_SAFEBAG_value(bags, i), oldpass, newpass)) + return 0; + } + return 1; +} + +/* Change password of safebag: only needs handle shrouded keybags */ + +static int newpass_bag(PKCS12_SAFEBAG *bag, const char *oldpass, + const char *newpass) +{ + PKCS8_PRIV_KEY_INFO *p8; + X509_SIG *p8new; + int p8_nid, p8_saltlen, p8_iter; + const X509_ALGOR *shalg; + + if (PKCS12_SAFEBAG_get_nid(bag) != NID_pkcs8ShroudedKeyBag) + return 1; + + if ((p8 = PKCS8_decrypt(bag->value.shkeybag, oldpass, -1)) == NULL) + return 0; + X509_SIG_get0(bag->value.shkeybag, &shalg, NULL); + if (!alg_get(shalg, &p8_nid, &p8_iter, &p8_saltlen)) + return 0; + p8new = PKCS8_encrypt(p8_nid, NULL, newpass, -1, NULL, p8_saltlen, + p8_iter, p8); + PKCS8_PRIV_KEY_INFO_free(p8); + if (p8new == NULL) + return 0; + X509_SIG_free(bag->value.shkeybag); + bag->value.shkeybag = p8new; + return 1; +} + +static int alg_get(const X509_ALGOR *alg, int *pnid, int *piter, + int *psaltlen) +{ + PBEPARAM *pbe; + pbe = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBEPARAM), alg->parameter); + if (!pbe) + return 0; + *pnid = OBJ_obj2nid(alg->algorithm); + *piter = ASN1_INTEGER_get(pbe->iter); + *psaltlen = pbe->salt->length; + PBEPARAM_free(pbe); + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_p8d.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_p8d.c new file mode 100644 index 000000000..d926a77df --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_p8d.c @@ -0,0 +1,23 @@ +/* + * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include + +PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(const X509_SIG *p8, const char *pass, + int passlen) +{ + const X509_ALGOR *dalg; + const ASN1_OCTET_STRING *doct; + X509_SIG_get0(p8, &dalg, &doct); + return PKCS12_item_decrypt_d2i(dalg, + ASN1_ITEM_rptr(PKCS8_PRIV_KEY_INFO), pass, + passlen, doct, 1); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_p8e.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_p8e.c new file mode 100644 index 000000000..86a07e133 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_p8e.c @@ -0,0 +1,69 @@ +/* + * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include "internal/x509_int.h" + +X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher, + const char *pass, int passlen, + unsigned char *salt, int saltlen, int iter, + PKCS8_PRIV_KEY_INFO *p8inf) +{ + X509_SIG *p8 = NULL; + X509_ALGOR *pbe; + + if (pbe_nid == -1) + pbe = PKCS5_pbe2_set(cipher, iter, salt, saltlen); + else if (EVP_PBE_find(EVP_PBE_TYPE_PRF, pbe_nid, NULL, NULL, 0)) + pbe = PKCS5_pbe2_set_iv(cipher, iter, salt, saltlen, NULL, pbe_nid); + else { + ERR_clear_error(); + pbe = PKCS5_pbe_set(pbe_nid, iter, salt, saltlen); + } + if (!pbe) { + PKCS12err(PKCS12_F_PKCS8_ENCRYPT, ERR_R_ASN1_LIB); + return NULL; + } + p8 = PKCS8_set0_pbe(pass, passlen, p8inf, pbe); + if (p8 == NULL) { + X509_ALGOR_free(pbe); + return NULL; + } + + return p8; +} + +X509_SIG *PKCS8_set0_pbe(const char *pass, int passlen, + PKCS8_PRIV_KEY_INFO *p8inf, X509_ALGOR *pbe) +{ + X509_SIG *p8; + ASN1_OCTET_STRING *enckey; + + enckey = + PKCS12_item_i2d_encrypt(pbe, ASN1_ITEM_rptr(PKCS8_PRIV_KEY_INFO), + pass, passlen, p8inf, 1); + if (!enckey) { + PKCS12err(PKCS12_F_PKCS8_SET0_PBE, PKCS12_R_ENCRYPT_ERROR); + return NULL; + } + + p8 = OPENSSL_zalloc(sizeof(*p8)); + + if (p8 == NULL) { + PKCS12err(PKCS12_F_PKCS8_SET0_PBE, ERR_R_MALLOC_FAILURE); + ASN1_OCTET_STRING_free(enckey); + return NULL; + } + p8->algor = pbe; + p8->digest = enckey; + + return p8; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_sbag.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_sbag.c new file mode 100644 index 000000000..a09c5b931 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_sbag.c @@ -0,0 +1,162 @@ +/* + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include "p12_lcl.h" + +#if OPENSSL_API_COMPAT < 0x10100000L +ASN1_TYPE *PKCS12_get_attr(const PKCS12_SAFEBAG *bag, int attr_nid) +{ + return PKCS12_get_attr_gen(bag->attrib, attr_nid); +} +#endif + +const ASN1_TYPE *PKCS12_SAFEBAG_get0_attr(const PKCS12_SAFEBAG *bag, + int attr_nid) +{ + return PKCS12_get_attr_gen(bag->attrib, attr_nid); +} + +ASN1_TYPE *PKCS8_get_attr(PKCS8_PRIV_KEY_INFO *p8, int attr_nid) +{ + return PKCS12_get_attr_gen(PKCS8_pkey_get0_attrs(p8), attr_nid); +} + +const PKCS8_PRIV_KEY_INFO *PKCS12_SAFEBAG_get0_p8inf(const PKCS12_SAFEBAG *bag) +{ + if (PKCS12_SAFEBAG_get_nid(bag) != NID_keyBag) + return NULL; + return bag->value.keybag; +} + +const X509_SIG *PKCS12_SAFEBAG_get0_pkcs8(const PKCS12_SAFEBAG *bag) +{ + if (OBJ_obj2nid(bag->type) != NID_pkcs8ShroudedKeyBag) + return NULL; + return bag->value.shkeybag; +} + +const STACK_OF(PKCS12_SAFEBAG) * +PKCS12_SAFEBAG_get0_safes(const PKCS12_SAFEBAG *bag) +{ + if (OBJ_obj2nid(bag->type) != NID_safeContentsBag) + return NULL; + return bag->value.safes; +} + +const ASN1_OBJECT *PKCS12_SAFEBAG_get0_type(const PKCS12_SAFEBAG *bag) +{ + return bag->type; +} + +int PKCS12_SAFEBAG_get_nid(const PKCS12_SAFEBAG *bag) +{ + return OBJ_obj2nid(bag->type); +} + +int PKCS12_SAFEBAG_get_bag_nid(const PKCS12_SAFEBAG *bag) +{ + int btype = PKCS12_SAFEBAG_get_nid(bag); + + if (btype != NID_certBag && btype != NID_crlBag && btype != NID_secretBag) + return -1; + return OBJ_obj2nid(bag->value.bag->type); +} + +X509 *PKCS12_SAFEBAG_get1_cert(const PKCS12_SAFEBAG *bag) +{ + if (PKCS12_SAFEBAG_get_nid(bag) != NID_certBag) + return NULL; + if (OBJ_obj2nid(bag->value.bag->type) != NID_x509Certificate) + return NULL; + return ASN1_item_unpack(bag->value.bag->value.octet, + ASN1_ITEM_rptr(X509)); +} + +X509_CRL *PKCS12_SAFEBAG_get1_crl(const PKCS12_SAFEBAG *bag) +{ + if (PKCS12_SAFEBAG_get_nid(bag) != NID_crlBag) + return NULL; + if (OBJ_obj2nid(bag->value.bag->type) != NID_x509Crl) + return NULL; + return ASN1_item_unpack(bag->value.bag->value.octet, + ASN1_ITEM_rptr(X509_CRL)); +} + +PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_cert(X509 *x509) +{ + return PKCS12_item_pack_safebag(x509, ASN1_ITEM_rptr(X509), + NID_x509Certificate, NID_certBag); +} + +PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_crl(X509_CRL *crl) +{ + return PKCS12_item_pack_safebag(crl, ASN1_ITEM_rptr(X509_CRL), + NID_x509Crl, NID_crlBag); +} + +/* Turn PKCS8 object into a keybag */ + +PKCS12_SAFEBAG *PKCS12_SAFEBAG_create0_p8inf(PKCS8_PRIV_KEY_INFO *p8) +{ + PKCS12_SAFEBAG *bag = PKCS12_SAFEBAG_new(); + + if (bag == NULL) { + PKCS12err(PKCS12_F_PKCS12_SAFEBAG_CREATE0_P8INF, ERR_R_MALLOC_FAILURE); + return NULL; + } + bag->type = OBJ_nid2obj(NID_keyBag); + bag->value.keybag = p8; + return bag; +} + +/* Turn PKCS8 object into a shrouded keybag */ + +PKCS12_SAFEBAG *PKCS12_SAFEBAG_create0_pkcs8(X509_SIG *p8) +{ + PKCS12_SAFEBAG *bag = PKCS12_SAFEBAG_new(); + + /* Set up the safe bag */ + if (bag == NULL) { + PKCS12err(PKCS12_F_PKCS12_SAFEBAG_CREATE0_PKCS8, ERR_R_MALLOC_FAILURE); + return NULL; + } + bag->type = OBJ_nid2obj(NID_pkcs8ShroudedKeyBag); + bag->value.shkeybag = p8; + return bag; +} + +PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_pkcs8_encrypt(int pbe_nid, + const char *pass, + int passlen, + unsigned char *salt, + int saltlen, int iter, + PKCS8_PRIV_KEY_INFO *p8inf) +{ + PKCS12_SAFEBAG *bag; + const EVP_CIPHER *pbe_ciph; + X509_SIG *p8; + + pbe_ciph = EVP_get_cipherbynid(pbe_nid); + if (pbe_ciph) + pbe_nid = -1; + + p8 = PKCS8_encrypt(pbe_nid, pbe_ciph, pass, passlen, salt, saltlen, iter, + p8inf); + if (p8 == NULL) + return NULL; + + bag = PKCS12_SAFEBAG_create0_pkcs8(p8); + if (bag == NULL) + X509_SIG_free(p8); + + return bag; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_utl.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_utl.c new file mode 100644 index 000000000..43b9e3a59 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/p12_utl.c @@ -0,0 +1,244 @@ +/* + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include + +/* Cheap and nasty Unicode stuff */ + +unsigned char *OPENSSL_asc2uni(const char *asc, int asclen, + unsigned char **uni, int *unilen) +{ + int ulen, i; + unsigned char *unitmp; + + if (asclen == -1) + asclen = strlen(asc); + ulen = asclen * 2 + 2; + if ((unitmp = OPENSSL_malloc(ulen)) == NULL) { + PKCS12err(PKCS12_F_OPENSSL_ASC2UNI, ERR_R_MALLOC_FAILURE); + return NULL; + } + for (i = 0; i < ulen - 2; i += 2) { + unitmp[i] = 0; + unitmp[i + 1] = asc[i >> 1]; + } + /* Make result double null terminated */ + unitmp[ulen - 2] = 0; + unitmp[ulen - 1] = 0; + if (unilen) + *unilen = ulen; + if (uni) + *uni = unitmp; + return unitmp; +} + +char *OPENSSL_uni2asc(const unsigned char *uni, int unilen) +{ + int asclen, i; + char *asctmp; + /* string must contain an even number of bytes */ + if (unilen & 1) + return NULL; + asclen = unilen / 2; + /* If no terminating zero allow for one */ + if (!unilen || uni[unilen - 1]) + asclen++; + uni++; + if ((asctmp = OPENSSL_malloc(asclen)) == NULL) { + PKCS12err(PKCS12_F_OPENSSL_UNI2ASC, ERR_R_MALLOC_FAILURE); + return NULL; + } + for (i = 0; i < unilen; i += 2) + asctmp[i >> 1] = uni[i]; + asctmp[asclen - 1] = 0; + return asctmp; +} + +/* + * OPENSSL_{utf82uni|uni2utf8} perform conversion between UTF-8 and + * PKCS#12 BMPString format, which is specified as big-endian UTF-16. + * One should keep in mind that even though BMPString is passed as + * unsigned char *, it's not the kind of string you can exercise e.g. + * strlen on. Caller also has to keep in mind that its length is + * expressed not in number of UTF-16 characters, but in number of + * bytes the string occupies, and treat it, the length, accordingly. + */ +unsigned char *OPENSSL_utf82uni(const char *asc, int asclen, + unsigned char **uni, int *unilen) +{ + int ulen, i, j; + unsigned char *unitmp, *ret; + unsigned long utf32chr = 0; + + if (asclen == -1) + asclen = strlen(asc); + + for (ulen = 0, i = 0; i < asclen; i += j) { + j = UTF8_getc((const unsigned char *)asc+i, asclen-i, &utf32chr); + + /* + * Following condition is somewhat opportunistic is sense that + * decoding failure is used as *indirect* indication that input + * string might in fact be extended ASCII/ANSI/ISO-8859-X. The + * fallback is taken in hope that it would allow to process + * files created with previous OpenSSL version, which used the + * naive OPENSSL_asc2uni all along. It might be worth noting + * that probability of false positive depends on language. In + * cases covered by ISO Latin 1 probability is very low, because + * any printable non-ASCII alphabet letter followed by another + * or any ASCII character will trigger failure and fallback. + * In other cases situation can be intensified by the fact that + * English letters are not part of alternative keyboard layout, + * but even then there should be plenty of pairs that trigger + * decoding failure... + */ + if (j < 0) + return OPENSSL_asc2uni(asc, asclen, uni, unilen); + + if (utf32chr > 0x10FFFF) /* UTF-16 cap */ + return NULL; + + if (utf32chr >= 0x10000) /* pair of UTF-16 characters */ + ulen += 2*2; + else /* or just one */ + ulen += 2; + } + + ulen += 2; /* for trailing UTF16 zero */ + + if ((ret = OPENSSL_malloc(ulen)) == NULL) { + PKCS12err(PKCS12_F_OPENSSL_UTF82UNI, ERR_R_MALLOC_FAILURE); + return NULL; + } + /* re-run the loop writing down UTF-16 characters in big-endian order */ + for (unitmp = ret, i = 0; i < asclen; i += j) { + j = UTF8_getc((const unsigned char *)asc+i, asclen-i, &utf32chr); + if (utf32chr >= 0x10000) { /* pair if UTF-16 characters */ + unsigned int hi, lo; + + utf32chr -= 0x10000; + hi = 0xD800 + (utf32chr>>10); + lo = 0xDC00 + (utf32chr&0x3ff); + *unitmp++ = (unsigned char)(hi>>8); + *unitmp++ = (unsigned char)(hi); + *unitmp++ = (unsigned char)(lo>>8); + *unitmp++ = (unsigned char)(lo); + } else { /* or just one */ + *unitmp++ = (unsigned char)(utf32chr>>8); + *unitmp++ = (unsigned char)(utf32chr); + } + } + /* Make result double null terminated */ + *unitmp++ = 0; + *unitmp++ = 0; + if (unilen) + *unilen = ulen; + if (uni) + *uni = ret; + return ret; +} + +static int bmp_to_utf8(char *str, const unsigned char *utf16, int len) +{ + unsigned long utf32chr; + + if (len == 0) return 0; + + if (len < 2) return -1; + + /* pull UTF-16 character in big-endian order */ + utf32chr = (utf16[0]<<8) | utf16[1]; + + if (utf32chr >= 0xD800 && utf32chr < 0xE000) { /* two chars */ + unsigned int lo; + + if (len < 4) return -1; + + utf32chr -= 0xD800; + utf32chr <<= 10; + lo = (utf16[2]<<8) | utf16[3]; + if (lo < 0xDC00 || lo >= 0xE000) return -1; + utf32chr |= lo-0xDC00; + utf32chr += 0x10000; + } + + return UTF8_putc((unsigned char *)str, len > 4 ? 4 : len, utf32chr); +} + +char *OPENSSL_uni2utf8(const unsigned char *uni, int unilen) +{ + int asclen, i, j; + char *asctmp; + + /* string must contain an even number of bytes */ + if (unilen & 1) + return NULL; + + for (asclen = 0, i = 0; i < unilen; ) { + j = bmp_to_utf8(NULL, uni+i, unilen-i); + /* + * falling back to OPENSSL_uni2asc makes lesser sense [than + * falling back to OPENSSL_asc2uni in OPENSSL_utf82uni above], + * it's done rather to maintain symmetry... + */ + if (j < 0) return OPENSSL_uni2asc(uni, unilen); + if (j == 4) i += 4; + else i += 2; + asclen += j; + } + + /* If no terminating zero allow for one */ + if (!unilen || (uni[unilen-2]||uni[unilen - 1])) + asclen++; + + if ((asctmp = OPENSSL_malloc(asclen)) == NULL) { + PKCS12err(PKCS12_F_OPENSSL_UNI2UTF8, ERR_R_MALLOC_FAILURE); + return NULL; + } + + /* re-run the loop emitting UTF-8 string */ + for (asclen = 0, i = 0; i < unilen; ) { + j = bmp_to_utf8(asctmp+asclen, uni+i, unilen-i); + if (j == 4) i += 4; + else i += 2; + asclen += j; + } + + /* If no terminating zero write one */ + if (!unilen || (uni[unilen-2]||uni[unilen - 1])) + asctmp[asclen] = '\0'; + + return asctmp; +} + +int i2d_PKCS12_bio(BIO *bp, PKCS12 *p12) +{ + return ASN1_item_i2d_bio(ASN1_ITEM_rptr(PKCS12), bp, p12); +} + +#ifndef OPENSSL_NO_STDIO +int i2d_PKCS12_fp(FILE *fp, PKCS12 *p12) +{ + return ASN1_item_i2d_fp(ASN1_ITEM_rptr(PKCS12), fp, p12); +} +#endif + +PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **p12) +{ + return ASN1_item_d2i_bio(ASN1_ITEM_rptr(PKCS12), bp, p12); +} + +#ifndef OPENSSL_NO_STDIO +PKCS12 *d2i_PKCS12_fp(FILE *fp, PKCS12 **p12) +{ + return ASN1_item_d2i_fp(ASN1_ITEM_rptr(PKCS12), fp, p12); +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/pk12err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/pk12err.c new file mode 100644 index 000000000..38ce5197e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs12/pk12err.c @@ -0,0 +1,117 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA PKCS12_str_functs[] = { + {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_OPENSSL_ASC2UNI, 0), "OPENSSL_asc2uni"}, + {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_OPENSSL_UNI2ASC, 0), "OPENSSL_uni2asc"}, + {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_OPENSSL_UNI2UTF8, 0), + "OPENSSL_uni2utf8"}, + {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_OPENSSL_UTF82UNI, 0), + "OPENSSL_utf82uni"}, + {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_CREATE, 0), "PKCS12_create"}, + {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_GEN_MAC, 0), "PKCS12_gen_mac"}, + {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_INIT, 0), "PKCS12_init"}, + {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_ITEM_DECRYPT_D2I, 0), + "PKCS12_item_decrypt_d2i"}, + {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_ITEM_I2D_ENCRYPT, 0), + "PKCS12_item_i2d_encrypt"}, + {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_ITEM_PACK_SAFEBAG, 0), + "PKCS12_item_pack_safebag"}, + {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_KEY_GEN_ASC, 0), + "PKCS12_key_gen_asc"}, + {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_KEY_GEN_UNI, 0), + "PKCS12_key_gen_uni"}, + {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_KEY_GEN_UTF8, 0), + "PKCS12_key_gen_utf8"}, + {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_NEWPASS, 0), "PKCS12_newpass"}, + {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_PACK_P7DATA, 0), + "PKCS12_pack_p7data"}, + {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_PACK_P7ENCDATA, 0), + "PKCS12_pack_p7encdata"}, + {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_PARSE, 0), "PKCS12_parse"}, + {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_PBE_CRYPT, 0), + "PKCS12_pbe_crypt"}, + {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_PBE_KEYIVGEN, 0), + "PKCS12_PBE_keyivgen"}, + {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_SAFEBAG_CREATE0_P8INF, 0), + "PKCS12_SAFEBAG_create0_p8inf"}, + {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_SAFEBAG_CREATE0_PKCS8, 0), + "PKCS12_SAFEBAG_create0_pkcs8"}, + {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_SAFEBAG_CREATE_PKCS8_ENCRYPT, 0), + "PKCS12_SAFEBAG_create_pkcs8_encrypt"}, + {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_SETUP_MAC, 0), + "PKCS12_setup_mac"}, + {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_SET_MAC, 0), "PKCS12_set_mac"}, + {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_UNPACK_AUTHSAFES, 0), + "PKCS12_unpack_authsafes"}, + {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_UNPACK_P7DATA, 0), + "PKCS12_unpack_p7data"}, + {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_VERIFY_MAC, 0), + "PKCS12_verify_mac"}, + {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS8_ENCRYPT, 0), "PKCS8_encrypt"}, + {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS8_SET0_PBE, 0), "PKCS8_set0_pbe"}, + {0, NULL} +}; + +static const ERR_STRING_DATA PKCS12_str_reasons[] = { + {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_CANT_PACK_STRUCTURE), + "cant pack structure"}, + {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_CONTENT_TYPE_NOT_DATA), + "content type not data"}, + {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_DECODE_ERROR), "decode error"}, + {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_ENCODE_ERROR), "encode error"}, + {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_ENCRYPT_ERROR), "encrypt error"}, + {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_ERROR_SETTING_ENCRYPTED_DATA_TYPE), + "error setting encrypted data type"}, + {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_INVALID_NULL_ARGUMENT), + "invalid null argument"}, + {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_INVALID_NULL_PKCS12_POINTER), + "invalid null pkcs12 pointer"}, + {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_IV_GEN_ERROR), "iv gen error"}, + {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_KEY_GEN_ERROR), "key gen error"}, + {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_MAC_ABSENT), "mac absent"}, + {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_MAC_GENERATION_ERROR), + "mac generation error"}, + {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_MAC_SETUP_ERROR), "mac setup error"}, + {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_MAC_STRING_SET_ERROR), + "mac string set error"}, + {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_MAC_VERIFY_FAILURE), + "mac verify failure"}, + {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_PARSE_ERROR), "parse error"}, + {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_PKCS12_ALGOR_CIPHERINIT_ERROR), + "pkcs12 algor cipherinit error"}, + {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_PKCS12_CIPHERFINAL_ERROR), + "pkcs12 cipherfinal error"}, + {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_PKCS12_PBE_CRYPT_ERROR), + "pkcs12 pbe crypt error"}, + {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_UNKNOWN_DIGEST_ALGORITHM), + "unknown digest algorithm"}, + {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_UNSUPPORTED_PKCS12_MODE), + "unsupported pkcs12 mode"}, + {0, NULL} +}; + +#endif + +int ERR_load_PKCS12_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(PKCS12_str_functs[0].error) == NULL) { + ERR_load_strings_const(PKCS12_str_functs); + ERR_load_strings_const(PKCS12_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/bio_pk7.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/bio_pk7.c new file mode 100644 index 000000000..29feaa354 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/bio_pk7.c @@ -0,0 +1,24 @@ +/* + * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include + +#if !defined(OPENSSL_SYS_VXWORKS) +# include +#endif +#include + +/* Streaming encode support for PKCS#7 */ + +BIO *BIO_new_PKCS7(BIO *out, PKCS7 *p7) +{ + return BIO_new_NDEF(out, (ASN1_VALUE *)p7, ASN1_ITEM_rptr(PKCS7)); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/build.info new file mode 100644 index 000000000..2029d538f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/build.info @@ -0,0 +1,4 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + pk7_asn1.c pk7_lib.c pkcs7err.c pk7_doit.c pk7_smime.c pk7_attr.c \ + pk7_mime.c bio_pk7.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/pk7_asn1.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/pk7_asn1.c new file mode 100644 index 000000000..cd9fb4f50 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/pk7_asn1.c @@ -0,0 +1,202 @@ +/* + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include + +/* PKCS#7 ASN1 module */ + +/* This is the ANY DEFINED BY table for the top level PKCS#7 structure */ + +ASN1_ADB_TEMPLATE(p7default) = ASN1_EXP_OPT(PKCS7, d.other, ASN1_ANY, 0); + +ASN1_ADB(PKCS7) = { + ADB_ENTRY(NID_pkcs7_data, ASN1_NDEF_EXP_OPT(PKCS7, d.data, ASN1_OCTET_STRING_NDEF, 0)), + ADB_ENTRY(NID_pkcs7_signed, ASN1_NDEF_EXP_OPT(PKCS7, d.sign, PKCS7_SIGNED, 0)), + ADB_ENTRY(NID_pkcs7_enveloped, ASN1_NDEF_EXP_OPT(PKCS7, d.enveloped, PKCS7_ENVELOPE, 0)), + ADB_ENTRY(NID_pkcs7_signedAndEnveloped, ASN1_NDEF_EXP_OPT(PKCS7, d.signed_and_enveloped, PKCS7_SIGN_ENVELOPE, 0)), + ADB_ENTRY(NID_pkcs7_digest, ASN1_NDEF_EXP_OPT(PKCS7, d.digest, PKCS7_DIGEST, 0)), + ADB_ENTRY(NID_pkcs7_encrypted, ASN1_NDEF_EXP_OPT(PKCS7, d.encrypted, PKCS7_ENCRYPT, 0)) +} ASN1_ADB_END(PKCS7, 0, type, 0, &p7default_tt, NULL); + +/* PKCS#7 streaming support */ +static int pk7_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + ASN1_STREAM_ARG *sarg = exarg; + PKCS7 **pp7 = (PKCS7 **)pval; + + switch (operation) { + + case ASN1_OP_STREAM_PRE: + if (PKCS7_stream(&sarg->boundary, *pp7) <= 0) + return 0; + /* fall thru */ + case ASN1_OP_DETACHED_PRE: + sarg->ndef_bio = PKCS7_dataInit(*pp7, sarg->out); + if (!sarg->ndef_bio) + return 0; + break; + + case ASN1_OP_STREAM_POST: + case ASN1_OP_DETACHED_POST: + if (PKCS7_dataFinal(*pp7, sarg->ndef_bio) <= 0) + return 0; + break; + + } + return 1; +} + +ASN1_NDEF_SEQUENCE_cb(PKCS7, pk7_cb) = { + ASN1_SIMPLE(PKCS7, type, ASN1_OBJECT), + ASN1_ADB_OBJECT(PKCS7) +}ASN1_NDEF_SEQUENCE_END_cb(PKCS7, PKCS7) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS7) + +IMPLEMENT_ASN1_NDEF_FUNCTION(PKCS7) + +IMPLEMENT_ASN1_DUP_FUNCTION(PKCS7) + +ASN1_NDEF_SEQUENCE(PKCS7_SIGNED) = { + ASN1_SIMPLE(PKCS7_SIGNED, version, ASN1_INTEGER), + ASN1_SET_OF(PKCS7_SIGNED, md_algs, X509_ALGOR), + ASN1_SIMPLE(PKCS7_SIGNED, contents, PKCS7), + ASN1_IMP_SEQUENCE_OF_OPT(PKCS7_SIGNED, cert, X509, 0), + ASN1_IMP_SET_OF_OPT(PKCS7_SIGNED, crl, X509_CRL, 1), + ASN1_SET_OF(PKCS7_SIGNED, signer_info, PKCS7_SIGNER_INFO) +} ASN1_NDEF_SEQUENCE_END(PKCS7_SIGNED) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS7_SIGNED) + +/* Minor tweak to operation: free up EVP_PKEY */ +static int si_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + if (operation == ASN1_OP_FREE_POST) { + PKCS7_SIGNER_INFO *si = (PKCS7_SIGNER_INFO *)*pval; + EVP_PKEY_free(si->pkey); + } + return 1; +} + +ASN1_SEQUENCE_cb(PKCS7_SIGNER_INFO, si_cb) = { + ASN1_SIMPLE(PKCS7_SIGNER_INFO, version, ASN1_INTEGER), + ASN1_SIMPLE(PKCS7_SIGNER_INFO, issuer_and_serial, PKCS7_ISSUER_AND_SERIAL), + ASN1_SIMPLE(PKCS7_SIGNER_INFO, digest_alg, X509_ALGOR), + /* NB this should be a SET OF but we use a SEQUENCE OF so the + * original order * is retained when the structure is reencoded. + * Since the attributes are implicitly tagged this will not affect + * the encoding. + */ + ASN1_IMP_SEQUENCE_OF_OPT(PKCS7_SIGNER_INFO, auth_attr, X509_ATTRIBUTE, 0), + ASN1_SIMPLE(PKCS7_SIGNER_INFO, digest_enc_alg, X509_ALGOR), + ASN1_SIMPLE(PKCS7_SIGNER_INFO, enc_digest, ASN1_OCTET_STRING), + ASN1_IMP_SET_OF_OPT(PKCS7_SIGNER_INFO, unauth_attr, X509_ATTRIBUTE, 1) +} ASN1_SEQUENCE_END_cb(PKCS7_SIGNER_INFO, PKCS7_SIGNER_INFO) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS7_SIGNER_INFO) + +ASN1_SEQUENCE(PKCS7_ISSUER_AND_SERIAL) = { + ASN1_SIMPLE(PKCS7_ISSUER_AND_SERIAL, issuer, X509_NAME), + ASN1_SIMPLE(PKCS7_ISSUER_AND_SERIAL, serial, ASN1_INTEGER) +} ASN1_SEQUENCE_END(PKCS7_ISSUER_AND_SERIAL) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS7_ISSUER_AND_SERIAL) + +ASN1_NDEF_SEQUENCE(PKCS7_ENVELOPE) = { + ASN1_SIMPLE(PKCS7_ENVELOPE, version, ASN1_INTEGER), + ASN1_SET_OF(PKCS7_ENVELOPE, recipientinfo, PKCS7_RECIP_INFO), + ASN1_SIMPLE(PKCS7_ENVELOPE, enc_data, PKCS7_ENC_CONTENT) +} ASN1_NDEF_SEQUENCE_END(PKCS7_ENVELOPE) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS7_ENVELOPE) + +/* Minor tweak to operation: free up X509 */ +static int ri_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + if (operation == ASN1_OP_FREE_POST) { + PKCS7_RECIP_INFO *ri = (PKCS7_RECIP_INFO *)*pval; + X509_free(ri->cert); + } + return 1; +} + +ASN1_SEQUENCE_cb(PKCS7_RECIP_INFO, ri_cb) = { + ASN1_SIMPLE(PKCS7_RECIP_INFO, version, ASN1_INTEGER), + ASN1_SIMPLE(PKCS7_RECIP_INFO, issuer_and_serial, PKCS7_ISSUER_AND_SERIAL), + ASN1_SIMPLE(PKCS7_RECIP_INFO, key_enc_algor, X509_ALGOR), + ASN1_SIMPLE(PKCS7_RECIP_INFO, enc_key, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END_cb(PKCS7_RECIP_INFO, PKCS7_RECIP_INFO) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS7_RECIP_INFO) + +ASN1_NDEF_SEQUENCE(PKCS7_ENC_CONTENT) = { + ASN1_SIMPLE(PKCS7_ENC_CONTENT, content_type, ASN1_OBJECT), + ASN1_SIMPLE(PKCS7_ENC_CONTENT, algorithm, X509_ALGOR), + ASN1_IMP_OPT(PKCS7_ENC_CONTENT, enc_data, ASN1_OCTET_STRING_NDEF, 0) +} ASN1_NDEF_SEQUENCE_END(PKCS7_ENC_CONTENT) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS7_ENC_CONTENT) + +ASN1_NDEF_SEQUENCE(PKCS7_SIGN_ENVELOPE) = { + ASN1_SIMPLE(PKCS7_SIGN_ENVELOPE, version, ASN1_INTEGER), + ASN1_SET_OF(PKCS7_SIGN_ENVELOPE, recipientinfo, PKCS7_RECIP_INFO), + ASN1_SET_OF(PKCS7_SIGN_ENVELOPE, md_algs, X509_ALGOR), + ASN1_SIMPLE(PKCS7_SIGN_ENVELOPE, enc_data, PKCS7_ENC_CONTENT), + ASN1_IMP_SET_OF_OPT(PKCS7_SIGN_ENVELOPE, cert, X509, 0), + ASN1_IMP_SET_OF_OPT(PKCS7_SIGN_ENVELOPE, crl, X509_CRL, 1), + ASN1_SET_OF(PKCS7_SIGN_ENVELOPE, signer_info, PKCS7_SIGNER_INFO) +} ASN1_NDEF_SEQUENCE_END(PKCS7_SIGN_ENVELOPE) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS7_SIGN_ENVELOPE) + +ASN1_NDEF_SEQUENCE(PKCS7_ENCRYPT) = { + ASN1_SIMPLE(PKCS7_ENCRYPT, version, ASN1_INTEGER), + ASN1_SIMPLE(PKCS7_ENCRYPT, enc_data, PKCS7_ENC_CONTENT) +} ASN1_NDEF_SEQUENCE_END(PKCS7_ENCRYPT) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS7_ENCRYPT) + +ASN1_NDEF_SEQUENCE(PKCS7_DIGEST) = { + ASN1_SIMPLE(PKCS7_DIGEST, version, ASN1_INTEGER), + ASN1_SIMPLE(PKCS7_DIGEST, md, X509_ALGOR), + ASN1_SIMPLE(PKCS7_DIGEST, contents, PKCS7), + ASN1_SIMPLE(PKCS7_DIGEST, digest, ASN1_OCTET_STRING) +} ASN1_NDEF_SEQUENCE_END(PKCS7_DIGEST) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS7_DIGEST) + +/* Specials for authenticated attributes */ + +/* + * When signing attributes we want to reorder them to match the sorted + * encoding. + */ + +ASN1_ITEM_TEMPLATE(PKCS7_ATTR_SIGN) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_ORDER, 0, PKCS7_ATTRIBUTES, X509_ATTRIBUTE) +ASN1_ITEM_TEMPLATE_END(PKCS7_ATTR_SIGN) + +/* + * When verifying attributes we need to use the received order. So we use + * SEQUENCE OF and tag it to SET OF + */ + +ASN1_ITEM_TEMPLATE(PKCS7_ATTR_VERIFY) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_IMPTAG | ASN1_TFLG_UNIVERSAL, + V_ASN1_SET, PKCS7_ATTRIBUTES, X509_ATTRIBUTE) +ASN1_ITEM_TEMPLATE_END(PKCS7_ATTR_VERIFY) + +IMPLEMENT_ASN1_PRINT_FUNCTION(PKCS7) diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/pk7_attr.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/pk7_attr.c new file mode 100644 index 000000000..e90bf03c5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/pk7_attr.c @@ -0,0 +1,121 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int PKCS7_add_attrib_smimecap(PKCS7_SIGNER_INFO *si, + STACK_OF(X509_ALGOR) *cap) +{ + ASN1_STRING *seq; + + if ((seq = ASN1_STRING_new()) == NULL) { + PKCS7err(PKCS7_F_PKCS7_ADD_ATTRIB_SMIMECAP, ERR_R_MALLOC_FAILURE); + return 0; + } + seq->length = ASN1_item_i2d((ASN1_VALUE *)cap, &seq->data, + ASN1_ITEM_rptr(X509_ALGORS)); + return PKCS7_add_signed_attribute(si, NID_SMIMECapabilities, + V_ASN1_SEQUENCE, seq); +} + +STACK_OF(X509_ALGOR) *PKCS7_get_smimecap(PKCS7_SIGNER_INFO *si) +{ + ASN1_TYPE *cap; + const unsigned char *p; + + cap = PKCS7_get_signed_attribute(si, NID_SMIMECapabilities); + if (cap == NULL || (cap->type != V_ASN1_SEQUENCE)) + return NULL; + p = cap->value.sequence->data; + return (STACK_OF(X509_ALGOR) *) + ASN1_item_d2i(NULL, &p, cap->value.sequence->length, + ASN1_ITEM_rptr(X509_ALGORS)); +} + +/* Basic smime-capabilities OID and optional integer arg */ +int PKCS7_simple_smimecap(STACK_OF(X509_ALGOR) *sk, int nid, int arg) +{ + ASN1_INTEGER *nbit = NULL; + X509_ALGOR *alg; + + if ((alg = X509_ALGOR_new()) == NULL) { + PKCS7err(PKCS7_F_PKCS7_SIMPLE_SMIMECAP, ERR_R_MALLOC_FAILURE); + return 0; + } + ASN1_OBJECT_free(alg->algorithm); + alg->algorithm = OBJ_nid2obj(nid); + if (arg > 0) { + if ((alg->parameter = ASN1_TYPE_new()) == NULL) { + goto err; + } + if ((nbit = ASN1_INTEGER_new()) == NULL) { + goto err; + } + if (!ASN1_INTEGER_set(nbit, arg)) { + goto err; + } + alg->parameter->value.integer = nbit; + alg->parameter->type = V_ASN1_INTEGER; + nbit = NULL; + } + if (!sk_X509_ALGOR_push(sk, alg)) { + goto err; + } + return 1; +err: + PKCS7err(PKCS7_F_PKCS7_SIMPLE_SMIMECAP, ERR_R_MALLOC_FAILURE); + ASN1_INTEGER_free(nbit); + X509_ALGOR_free(alg); + return 0; +} + +int PKCS7_add_attrib_content_type(PKCS7_SIGNER_INFO *si, ASN1_OBJECT *coid) +{ + if (PKCS7_get_signed_attribute(si, NID_pkcs9_contentType)) + return 0; + if (!coid) + coid = OBJ_nid2obj(NID_pkcs7_data); + return PKCS7_add_signed_attribute(si, NID_pkcs9_contentType, + V_ASN1_OBJECT, coid); +} + +int PKCS7_add0_attrib_signing_time(PKCS7_SIGNER_INFO *si, ASN1_TIME *t) +{ + if (t == NULL && (t = X509_gmtime_adj(NULL, 0)) == NULL) { + PKCS7err(PKCS7_F_PKCS7_ADD0_ATTRIB_SIGNING_TIME, + ERR_R_MALLOC_FAILURE); + return 0; + } + return PKCS7_add_signed_attribute(si, NID_pkcs9_signingTime, + V_ASN1_UTCTIME, t); +} + +int PKCS7_add1_attrib_digest(PKCS7_SIGNER_INFO *si, + const unsigned char *md, int mdlen) +{ + ASN1_OCTET_STRING *os; + os = ASN1_OCTET_STRING_new(); + if (os == NULL) + return 0; + if (!ASN1_STRING_set(os, md, mdlen) + || !PKCS7_add_signed_attribute(si, NID_pkcs9_messageDigest, + V_ASN1_OCTET_STRING, os)) { + ASN1_OCTET_STRING_free(os); + return 0; + } + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/pk7_doit.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/pk7_doit.c new file mode 100644 index 000000000..ee08e602a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/pk7_doit.c @@ -0,0 +1,1180 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include + +static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype, + void *value); +static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid); + +static int PKCS7_type_is_other(PKCS7 *p7) +{ + int isOther = 1; + + int nid = OBJ_obj2nid(p7->type); + + switch (nid) { + case NID_pkcs7_data: + case NID_pkcs7_signed: + case NID_pkcs7_enveloped: + case NID_pkcs7_signedAndEnveloped: + case NID_pkcs7_digest: + case NID_pkcs7_encrypted: + isOther = 0; + break; + default: + isOther = 1; + } + + return isOther; + +} + +static ASN1_OCTET_STRING *PKCS7_get_octet_string(PKCS7 *p7) +{ + if (PKCS7_type_is_data(p7)) + return p7->d.data; + if (PKCS7_type_is_other(p7) && p7->d.other + && (p7->d.other->type == V_ASN1_OCTET_STRING)) + return p7->d.other->value.octet_string; + return NULL; +} + +static int PKCS7_bio_add_digest(BIO **pbio, X509_ALGOR *alg) +{ + BIO *btmp; + const EVP_MD *md; + if ((btmp = BIO_new(BIO_f_md())) == NULL) { + PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST, ERR_R_BIO_LIB); + goto err; + } + + md = EVP_get_digestbyobj(alg->algorithm); + if (md == NULL) { + PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST, PKCS7_R_UNKNOWN_DIGEST_TYPE); + goto err; + } + + BIO_set_md(btmp, md); + if (*pbio == NULL) + *pbio = btmp; + else if (!BIO_push(*pbio, btmp)) { + PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST, ERR_R_BIO_LIB); + goto err; + } + btmp = NULL; + + return 1; + + err: + BIO_free(btmp); + return 0; + +} + +static int pkcs7_encode_rinfo(PKCS7_RECIP_INFO *ri, + unsigned char *key, int keylen) +{ + EVP_PKEY_CTX *pctx = NULL; + EVP_PKEY *pkey = NULL; + unsigned char *ek = NULL; + int ret = 0; + size_t eklen; + + pkey = X509_get0_pubkey(ri->cert); + + if (!pkey) + return 0; + + pctx = EVP_PKEY_CTX_new(pkey, NULL); + if (!pctx) + return 0; + + if (EVP_PKEY_encrypt_init(pctx) <= 0) + goto err; + + if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT, + EVP_PKEY_CTRL_PKCS7_ENCRYPT, 0, ri) <= 0) { + PKCS7err(PKCS7_F_PKCS7_ENCODE_RINFO, PKCS7_R_CTRL_ERROR); + goto err; + } + + if (EVP_PKEY_encrypt(pctx, NULL, &eklen, key, keylen) <= 0) + goto err; + + ek = OPENSSL_malloc(eklen); + + if (ek == NULL) { + PKCS7err(PKCS7_F_PKCS7_ENCODE_RINFO, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (EVP_PKEY_encrypt(pctx, ek, &eklen, key, keylen) <= 0) + goto err; + + ASN1_STRING_set0(ri->enc_key, ek, eklen); + ek = NULL; + + ret = 1; + + err: + EVP_PKEY_CTX_free(pctx); + OPENSSL_free(ek); + return ret; + +} + +static int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen, + PKCS7_RECIP_INFO *ri, EVP_PKEY *pkey) +{ + EVP_PKEY_CTX *pctx = NULL; + unsigned char *ek = NULL; + size_t eklen; + + int ret = -1; + + pctx = EVP_PKEY_CTX_new(pkey, NULL); + if (!pctx) + return -1; + + if (EVP_PKEY_decrypt_init(pctx) <= 0) + goto err; + + if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DECRYPT, + EVP_PKEY_CTRL_PKCS7_DECRYPT, 0, ri) <= 0) { + PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, PKCS7_R_CTRL_ERROR); + goto err; + } + + if (EVP_PKEY_decrypt(pctx, NULL, &eklen, + ri->enc_key->data, ri->enc_key->length) <= 0) + goto err; + + ek = OPENSSL_malloc(eklen); + + if (ek == NULL) { + PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (EVP_PKEY_decrypt(pctx, ek, &eklen, + ri->enc_key->data, ri->enc_key->length) <= 0) { + ret = 0; + PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_EVP_LIB); + goto err; + } + + ret = 1; + + OPENSSL_clear_free(*pek, *peklen); + *pek = ek; + *peklen = eklen; + + err: + EVP_PKEY_CTX_free(pctx); + if (!ret) + OPENSSL_free(ek); + + return ret; +} + +BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) +{ + int i; + BIO *out = NULL, *btmp = NULL; + X509_ALGOR *xa = NULL; + const EVP_CIPHER *evp_cipher = NULL; + STACK_OF(X509_ALGOR) *md_sk = NULL; + STACK_OF(PKCS7_RECIP_INFO) *rsk = NULL; + X509_ALGOR *xalg = NULL; + PKCS7_RECIP_INFO *ri = NULL; + ASN1_OCTET_STRING *os = NULL; + + if (p7 == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_INVALID_NULL_POINTER); + return NULL; + } + /* + * The content field in the PKCS7 ContentInfo is optional, but that really + * only applies to inner content (precisely, detached signatures). + * + * When reading content, missing outer content is therefore treated as an + * error. + * + * When creating content, PKCS7_content_new() must be called before + * calling this method, so a NULL p7->d is always an error. + */ + if (p7->d.ptr == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_NO_CONTENT); + return NULL; + } + + i = OBJ_obj2nid(p7->type); + p7->state = PKCS7_S_HEADER; + + switch (i) { + case NID_pkcs7_signed: + md_sk = p7->d.sign->md_algs; + os = PKCS7_get_octet_string(p7->d.sign->contents); + break; + case NID_pkcs7_signedAndEnveloped: + rsk = p7->d.signed_and_enveloped->recipientinfo; + md_sk = p7->d.signed_and_enveloped->md_algs; + xalg = p7->d.signed_and_enveloped->enc_data->algorithm; + evp_cipher = p7->d.signed_and_enveloped->enc_data->cipher; + if (evp_cipher == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_CIPHER_NOT_INITIALIZED); + goto err; + } + break; + case NID_pkcs7_enveloped: + rsk = p7->d.enveloped->recipientinfo; + xalg = p7->d.enveloped->enc_data->algorithm; + evp_cipher = p7->d.enveloped->enc_data->cipher; + if (evp_cipher == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_CIPHER_NOT_INITIALIZED); + goto err; + } + break; + case NID_pkcs7_digest: + xa = p7->d.digest->md; + os = PKCS7_get_octet_string(p7->d.digest->contents); + break; + case NID_pkcs7_data: + break; + default: + PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_UNSUPPORTED_CONTENT_TYPE); + goto err; + } + + for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++) + if (!PKCS7_bio_add_digest(&out, sk_X509_ALGOR_value(md_sk, i))) + goto err; + + if (xa && !PKCS7_bio_add_digest(&out, xa)) + goto err; + + if (evp_cipher != NULL) { + unsigned char key[EVP_MAX_KEY_LENGTH]; + unsigned char iv[EVP_MAX_IV_LENGTH]; + int keylen, ivlen; + EVP_CIPHER_CTX *ctx; + + if ((btmp = BIO_new(BIO_f_cipher())) == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATAINIT, ERR_R_BIO_LIB); + goto err; + } + BIO_get_cipher_ctx(btmp, &ctx); + keylen = EVP_CIPHER_key_length(evp_cipher); + ivlen = EVP_CIPHER_iv_length(evp_cipher); + xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher)); + if (ivlen > 0) + if (RAND_bytes(iv, ivlen) <= 0) + goto err; + if (EVP_CipherInit_ex(ctx, evp_cipher, NULL, NULL, NULL, 1) <= 0) + goto err; + if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0) + goto err; + if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) <= 0) + goto err; + + if (ivlen > 0) { + if (xalg->parameter == NULL) { + xalg->parameter = ASN1_TYPE_new(); + if (xalg->parameter == NULL) + goto err; + } + if (EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0) + goto err; + } + + /* Lets do the pub key stuff :-) */ + for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) { + ri = sk_PKCS7_RECIP_INFO_value(rsk, i); + if (pkcs7_encode_rinfo(ri, key, keylen) <= 0) + goto err; + } + OPENSSL_cleanse(key, keylen); + + if (out == NULL) + out = btmp; + else + BIO_push(out, btmp); + btmp = NULL; + } + + if (bio == NULL) { + if (PKCS7_is_detached(p7)) { + bio = BIO_new(BIO_s_null()); + } else if (os && os->length > 0) { + bio = BIO_new_mem_buf(os->data, os->length); + } else { + bio = BIO_new(BIO_s_mem()); + if (bio == NULL) + goto err; + BIO_set_mem_eof_return(bio, 0); + } + if (bio == NULL) + goto err; + } + if (out) + BIO_push(out, bio); + else + out = bio; + return out; + + err: + BIO_free_all(out); + BIO_free_all(btmp); + return NULL; +} + +static int pkcs7_cmp_ri(PKCS7_RECIP_INFO *ri, X509 *pcert) +{ + int ret; + ret = X509_NAME_cmp(ri->issuer_and_serial->issuer, + X509_get_issuer_name(pcert)); + if (ret) + return ret; + return ASN1_INTEGER_cmp(X509_get_serialNumber(pcert), + ri->issuer_and_serial->serial); +} + +/* int */ +BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) +{ + int i, j; + BIO *out = NULL, *btmp = NULL, *etmp = NULL, *bio = NULL; + X509_ALGOR *xa; + ASN1_OCTET_STRING *data_body = NULL; + const EVP_MD *evp_md; + const EVP_CIPHER *evp_cipher = NULL; + EVP_CIPHER_CTX *evp_ctx = NULL; + X509_ALGOR *enc_alg = NULL; + STACK_OF(X509_ALGOR) *md_sk = NULL; + STACK_OF(PKCS7_RECIP_INFO) *rsk = NULL; + PKCS7_RECIP_INFO *ri = NULL; + unsigned char *ek = NULL, *tkey = NULL; + int eklen = 0, tkeylen = 0; + + if (p7 == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_INVALID_NULL_POINTER); + return NULL; + } + + if (p7->d.ptr == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT); + return NULL; + } + + i = OBJ_obj2nid(p7->type); + p7->state = PKCS7_S_HEADER; + + switch (i) { + case NID_pkcs7_signed: + /* + * p7->d.sign->contents is a PKCS7 structure consisting of a contentType + * field and optional content. + * data_body is NULL if that structure has no (=detached) content + * or if the contentType is wrong (i.e., not "data"). + */ + data_body = PKCS7_get_octet_string(p7->d.sign->contents); + if (!PKCS7_is_detached(p7) && data_body == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATADECODE, + PKCS7_R_INVALID_SIGNED_DATA_TYPE); + goto err; + } + md_sk = p7->d.sign->md_algs; + break; + case NID_pkcs7_signedAndEnveloped: + rsk = p7->d.signed_and_enveloped->recipientinfo; + md_sk = p7->d.signed_and_enveloped->md_algs; + /* data_body is NULL if the optional EncryptedContent is missing. */ + data_body = p7->d.signed_and_enveloped->enc_data->enc_data; + enc_alg = p7->d.signed_and_enveloped->enc_data->algorithm; + evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm); + if (evp_cipher == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATADECODE, + PKCS7_R_UNSUPPORTED_CIPHER_TYPE); + goto err; + } + break; + case NID_pkcs7_enveloped: + rsk = p7->d.enveloped->recipientinfo; + enc_alg = p7->d.enveloped->enc_data->algorithm; + /* data_body is NULL if the optional EncryptedContent is missing. */ + data_body = p7->d.enveloped->enc_data->enc_data; + evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm); + if (evp_cipher == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATADECODE, + PKCS7_R_UNSUPPORTED_CIPHER_TYPE); + goto err; + } + break; + default: + PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_UNSUPPORTED_CONTENT_TYPE); + goto err; + } + + /* Detached content must be supplied via in_bio instead. */ + if (data_body == NULL && in_bio == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT); + goto err; + } + + /* We will be checking the signature */ + if (md_sk != NULL) { + for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++) { + xa = sk_X509_ALGOR_value(md_sk, i); + if ((btmp = BIO_new(BIO_f_md())) == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_BIO_LIB); + goto err; + } + + j = OBJ_obj2nid(xa->algorithm); + evp_md = EVP_get_digestbynid(j); + if (evp_md == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATADECODE, + PKCS7_R_UNKNOWN_DIGEST_TYPE); + goto err; + } + + BIO_set_md(btmp, evp_md); + if (out == NULL) + out = btmp; + else + BIO_push(out, btmp); + btmp = NULL; + } + } + + if (evp_cipher != NULL) { + if ((etmp = BIO_new(BIO_f_cipher())) == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_BIO_LIB); + goto err; + } + + /* + * It was encrypted, we need to decrypt the secret key with the + * private key + */ + + /* + * Find the recipientInfo which matches the passed certificate (if + * any) + */ + + if (pcert) { + for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) { + ri = sk_PKCS7_RECIP_INFO_value(rsk, i); + if (!pkcs7_cmp_ri(ri, pcert)) + break; + ri = NULL; + } + if (ri == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATADECODE, + PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE); + goto err; + } + } + + /* If we haven't got a certificate try each ri in turn */ + if (pcert == NULL) { + /* + * Always attempt to decrypt all rinfo even after success as a + * defence against MMA timing attacks. + */ + for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) { + ri = sk_PKCS7_RECIP_INFO_value(rsk, i); + + if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey) < 0) + goto err; + ERR_clear_error(); + } + } else { + /* Only exit on fatal errors, not decrypt failure */ + if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey) < 0) + goto err; + ERR_clear_error(); + } + + evp_ctx = NULL; + BIO_get_cipher_ctx(etmp, &evp_ctx); + if (EVP_CipherInit_ex(evp_ctx, evp_cipher, NULL, NULL, NULL, 0) <= 0) + goto err; + if (EVP_CIPHER_asn1_to_param(evp_ctx, enc_alg->parameter) < 0) + goto err; + /* Generate random key as MMA defence */ + tkeylen = EVP_CIPHER_CTX_key_length(evp_ctx); + tkey = OPENSSL_malloc(tkeylen); + if (tkey == NULL) + goto err; + if (EVP_CIPHER_CTX_rand_key(evp_ctx, tkey) <= 0) + goto err; + if (ek == NULL) { + ek = tkey; + eklen = tkeylen; + tkey = NULL; + } + + if (eklen != EVP_CIPHER_CTX_key_length(evp_ctx)) { + /* + * Some S/MIME clients don't use the same key and effective key + * length. The key length is determined by the size of the + * decrypted RSA key. + */ + if (!EVP_CIPHER_CTX_set_key_length(evp_ctx, eklen)) { + /* Use random key as MMA defence */ + OPENSSL_clear_free(ek, eklen); + ek = tkey; + eklen = tkeylen; + tkey = NULL; + } + } + /* Clear errors so we don't leak information useful in MMA */ + ERR_clear_error(); + if (EVP_CipherInit_ex(evp_ctx, NULL, NULL, ek, NULL, 0) <= 0) + goto err; + + OPENSSL_clear_free(ek, eklen); + ek = NULL; + OPENSSL_clear_free(tkey, tkeylen); + tkey = NULL; + + if (out == NULL) + out = etmp; + else + BIO_push(out, etmp); + etmp = NULL; + } + if (in_bio != NULL) { + bio = in_bio; + } else { + if (data_body->length > 0) + bio = BIO_new_mem_buf(data_body->data, data_body->length); + else { + bio = BIO_new(BIO_s_mem()); + if (bio == NULL) + goto err; + BIO_set_mem_eof_return(bio, 0); + } + if (bio == NULL) + goto err; + } + BIO_push(out, bio); + bio = NULL; + return out; + + err: + OPENSSL_clear_free(ek, eklen); + OPENSSL_clear_free(tkey, tkeylen); + BIO_free_all(out); + BIO_free_all(btmp); + BIO_free_all(etmp); + BIO_free_all(bio); + return NULL; +} + +static BIO *PKCS7_find_digest(EVP_MD_CTX **pmd, BIO *bio, int nid) +{ + for (;;) { + bio = BIO_find_type(bio, BIO_TYPE_MD); + if (bio == NULL) { + PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST, + PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); + return NULL; + } + BIO_get_md_ctx(bio, pmd); + if (*pmd == NULL) { + PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST, ERR_R_INTERNAL_ERROR); + return NULL; + } + if (EVP_MD_CTX_type(*pmd) == nid) + return bio; + bio = BIO_next(bio); + } + return NULL; +} + +static int do_pkcs7_signed_attrib(PKCS7_SIGNER_INFO *si, EVP_MD_CTX *mctx) +{ + unsigned char md_data[EVP_MAX_MD_SIZE]; + unsigned int md_len; + + /* Add signing time if not already present */ + if (!PKCS7_get_signed_attribute(si, NID_pkcs9_signingTime)) { + if (!PKCS7_add0_attrib_signing_time(si, NULL)) { + PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, ERR_R_MALLOC_FAILURE); + return 0; + } + } + + /* Add digest */ + if (!EVP_DigestFinal_ex(mctx, md_data, &md_len)) { + PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, ERR_R_EVP_LIB); + return 0; + } + if (!PKCS7_add1_attrib_digest(si, md_data, md_len)) { + PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, ERR_R_MALLOC_FAILURE); + return 0; + } + + /* Now sign the attributes */ + if (!PKCS7_SIGNER_INFO_sign(si)) + return 0; + + return 1; +} + +int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) +{ + int ret = 0; + int i, j; + BIO *btmp; + PKCS7_SIGNER_INFO *si; + EVP_MD_CTX *mdc, *ctx_tmp; + STACK_OF(X509_ATTRIBUTE) *sk; + STACK_OF(PKCS7_SIGNER_INFO) *si_sk = NULL; + ASN1_OCTET_STRING *os = NULL; + + if (p7 == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_INVALID_NULL_POINTER); + return 0; + } + + if (p7->d.ptr == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_NO_CONTENT); + return 0; + } + + ctx_tmp = EVP_MD_CTX_new(); + if (ctx_tmp == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE); + return 0; + } + + i = OBJ_obj2nid(p7->type); + p7->state = PKCS7_S_HEADER; + + switch (i) { + case NID_pkcs7_data: + os = p7->d.data; + break; + case NID_pkcs7_signedAndEnveloped: + /* XXXXXXXXXXXXXXXX */ + si_sk = p7->d.signed_and_enveloped->signer_info; + os = p7->d.signed_and_enveloped->enc_data->enc_data; + if (os == NULL) { + os = ASN1_OCTET_STRING_new(); + if (os == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE); + goto err; + } + p7->d.signed_and_enveloped->enc_data->enc_data = os; + } + break; + case NID_pkcs7_enveloped: + /* XXXXXXXXXXXXXXXX */ + os = p7->d.enveloped->enc_data->enc_data; + if (os == NULL) { + os = ASN1_OCTET_STRING_new(); + if (os == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE); + goto err; + } + p7->d.enveloped->enc_data->enc_data = os; + } + break; + case NID_pkcs7_signed: + si_sk = p7->d.sign->signer_info; + os = PKCS7_get_octet_string(p7->d.sign->contents); + /* If detached data then the content is excluded */ + if (PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) { + ASN1_OCTET_STRING_free(os); + os = NULL; + p7->d.sign->contents->d.data = NULL; + } + break; + + case NID_pkcs7_digest: + os = PKCS7_get_octet_string(p7->d.digest->contents); + /* If detached data then the content is excluded */ + if (PKCS7_type_is_data(p7->d.digest->contents) && p7->detached) { + ASN1_OCTET_STRING_free(os); + os = NULL; + p7->d.digest->contents->d.data = NULL; + } + break; + + default: + PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_UNSUPPORTED_CONTENT_TYPE); + goto err; + } + + if (si_sk != NULL) { + for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(si_sk); i++) { + si = sk_PKCS7_SIGNER_INFO_value(si_sk, i); + if (si->pkey == NULL) + continue; + + j = OBJ_obj2nid(si->digest_alg->algorithm); + + btmp = bio; + + btmp = PKCS7_find_digest(&mdc, btmp, j); + + if (btmp == NULL) + goto err; + + /* + * We now have the EVP_MD_CTX, lets do the signing. + */ + if (!EVP_MD_CTX_copy_ex(ctx_tmp, mdc)) + goto err; + + sk = si->auth_attr; + + /* + * If there are attributes, we add the digest attribute and only + * sign the attributes + */ + if (sk_X509_ATTRIBUTE_num(sk) > 0) { + if (!do_pkcs7_signed_attrib(si, ctx_tmp)) + goto err; + } else { + unsigned char *abuf = NULL; + unsigned int abuflen; + abuflen = EVP_PKEY_size(si->pkey); + abuf = OPENSSL_malloc(abuflen); + if (abuf == NULL) + goto err; + + if (!EVP_SignFinal(ctx_tmp, abuf, &abuflen, si->pkey)) { + OPENSSL_free(abuf); + PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_EVP_LIB); + goto err; + } + ASN1_STRING_set0(si->enc_digest, abuf, abuflen); + } + } + } else if (i == NID_pkcs7_digest) { + unsigned char md_data[EVP_MAX_MD_SIZE]; + unsigned int md_len; + if (!PKCS7_find_digest(&mdc, bio, + OBJ_obj2nid(p7->d.digest->md->algorithm))) + goto err; + if (!EVP_DigestFinal_ex(mdc, md_data, &md_len)) + goto err; + if (!ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len)) + goto err; + } + + if (!PKCS7_is_detached(p7)) { + /* + * NOTE(emilia): I think we only reach os == NULL here because detached + * digested data support is broken. + */ + if (os == NULL) + goto err; + if (!(os->flags & ASN1_STRING_FLAG_NDEF)) { + char *cont; + long contlen; + btmp = BIO_find_type(bio, BIO_TYPE_MEM); + if (btmp == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_UNABLE_TO_FIND_MEM_BIO); + goto err; + } + contlen = BIO_get_mem_data(btmp, &cont); + /* + * Mark the BIO read only then we can use its copy of the data + * instead of making an extra copy. + */ + BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY); + BIO_set_mem_eof_return(btmp, 0); + ASN1_STRING_set0(os, (unsigned char *)cont, contlen); + } + } + ret = 1; + err: + EVP_MD_CTX_free(ctx_tmp); + return ret; +} + +int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si) +{ + EVP_MD_CTX *mctx; + EVP_PKEY_CTX *pctx = NULL; + unsigned char *abuf = NULL; + int alen; + size_t siglen; + const EVP_MD *md = NULL; + + md = EVP_get_digestbyobj(si->digest_alg->algorithm); + if (md == NULL) + return 0; + + mctx = EVP_MD_CTX_new(); + if (mctx == NULL) { + PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (EVP_DigestSignInit(mctx, &pctx, md, NULL, si->pkey) <= 0) + goto err; + + if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, + EVP_PKEY_CTRL_PKCS7_SIGN, 0, si) <= 0) { + PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR); + goto err; + } + + alen = ASN1_item_i2d((ASN1_VALUE *)si->auth_attr, &abuf, + ASN1_ITEM_rptr(PKCS7_ATTR_SIGN)); + if (!abuf) + goto err; + if (EVP_DigestSignUpdate(mctx, abuf, alen) <= 0) + goto err; + OPENSSL_free(abuf); + abuf = NULL; + if (EVP_DigestSignFinal(mctx, NULL, &siglen) <= 0) + goto err; + abuf = OPENSSL_malloc(siglen); + if (abuf == NULL) + goto err; + if (EVP_DigestSignFinal(mctx, abuf, &siglen) <= 0) + goto err; + + if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, + EVP_PKEY_CTRL_PKCS7_SIGN, 1, si) <= 0) { + PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR); + goto err; + } + + EVP_MD_CTX_free(mctx); + + ASN1_STRING_set0(si->enc_digest, abuf, siglen); + + return 1; + + err: + OPENSSL_free(abuf); + EVP_MD_CTX_free(mctx); + return 0; + +} + +int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio, + PKCS7 *p7, PKCS7_SIGNER_INFO *si) +{ + PKCS7_ISSUER_AND_SERIAL *ias; + int ret = 0, i; + STACK_OF(X509) *cert; + X509 *x509; + + if (p7 == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_INVALID_NULL_POINTER); + return 0; + } + + if (p7->d.ptr == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_NO_CONTENT); + return 0; + } + + if (PKCS7_type_is_signed(p7)) { + cert = p7->d.sign->cert; + } else if (PKCS7_type_is_signedAndEnveloped(p7)) { + cert = p7->d.signed_and_enveloped->cert; + } else { + PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_WRONG_PKCS7_TYPE); + goto err; + } + /* XXXXXXXXXXXXXXXXXXXXXXX */ + ias = si->issuer_and_serial; + + x509 = X509_find_by_issuer_and_serial(cert, ias->issuer, ias->serial); + + /* were we able to find the cert in passed to us */ + if (x509 == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, + PKCS7_R_UNABLE_TO_FIND_CERTIFICATE); + goto err; + } + + /* Lets verify */ + if (!X509_STORE_CTX_init(ctx, cert_store, x509, cert)) { + PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, ERR_R_X509_LIB); + goto err; + } + X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SMIME_SIGN); + i = X509_verify_cert(ctx); + if (i <= 0) { + PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, ERR_R_X509_LIB); + X509_STORE_CTX_cleanup(ctx); + goto err; + } + X509_STORE_CTX_cleanup(ctx); + + return PKCS7_signatureVerify(bio, p7, si, x509); + err: + return ret; +} + +int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, + X509 *x509) +{ + ASN1_OCTET_STRING *os; + EVP_MD_CTX *mdc_tmp, *mdc; + int ret = 0, i; + int md_type; + STACK_OF(X509_ATTRIBUTE) *sk; + BIO *btmp; + EVP_PKEY *pkey; + + mdc_tmp = EVP_MD_CTX_new(); + if (mdc_tmp == NULL) { + PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!PKCS7_type_is_signed(p7) && !PKCS7_type_is_signedAndEnveloped(p7)) { + PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_WRONG_PKCS7_TYPE); + goto err; + } + + md_type = OBJ_obj2nid(si->digest_alg->algorithm); + + btmp = bio; + for (;;) { + if ((btmp == NULL) || + ((btmp = BIO_find_type(btmp, BIO_TYPE_MD)) == NULL)) { + PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, + PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); + goto err; + } + BIO_get_md_ctx(btmp, &mdc); + if (mdc == NULL) { + PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, ERR_R_INTERNAL_ERROR); + goto err; + } + if (EVP_MD_CTX_type(mdc) == md_type) + break; + /* + * Workaround for some broken clients that put the signature OID + * instead of the digest OID in digest_alg->algorithm + */ + if (EVP_MD_pkey_type(EVP_MD_CTX_md(mdc)) == md_type) + break; + btmp = BIO_next(btmp); + } + + /* + * mdc is the digest ctx that we want, unless there are attributes, in + * which case the digest is the signed attributes + */ + if (!EVP_MD_CTX_copy_ex(mdc_tmp, mdc)) + goto err; + + sk = si->auth_attr; + if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) { + unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL; + unsigned int md_len; + int alen; + ASN1_OCTET_STRING *message_digest; + + if (!EVP_DigestFinal_ex(mdc_tmp, md_dat, &md_len)) + goto err; + message_digest = PKCS7_digest_from_attributes(sk); + if (!message_digest) { + PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, + PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); + goto err; + } + if ((message_digest->length != (int)md_len) || + (memcmp(message_digest->data, md_dat, md_len))) { + PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_DIGEST_FAILURE); + ret = -1; + goto err; + } + + if (!EVP_VerifyInit_ex(mdc_tmp, EVP_get_digestbynid(md_type), NULL)) + goto err; + + alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf, + ASN1_ITEM_rptr(PKCS7_ATTR_VERIFY)); + if (alen <= 0) { + PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, ERR_R_ASN1_LIB); + ret = -1; + goto err; + } + if (!EVP_VerifyUpdate(mdc_tmp, abuf, alen)) + goto err; + + OPENSSL_free(abuf); + } + + os = si->enc_digest; + pkey = X509_get0_pubkey(x509); + if (!pkey) { + ret = -1; + goto err; + } + + i = EVP_VerifyFinal(mdc_tmp, os->data, os->length, pkey); + if (i <= 0) { + PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_SIGNATURE_FAILURE); + ret = -1; + goto err; + } + ret = 1; + err: + EVP_MD_CTX_free(mdc_tmp); + return ret; +} + +PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx) +{ + STACK_OF(PKCS7_RECIP_INFO) *rsk; + PKCS7_RECIP_INFO *ri; + int i; + + i = OBJ_obj2nid(p7->type); + if (i != NID_pkcs7_signedAndEnveloped) + return NULL; + if (p7->d.signed_and_enveloped == NULL) + return NULL; + rsk = p7->d.signed_and_enveloped->recipientinfo; + if (rsk == NULL) + return NULL; + if (sk_PKCS7_RECIP_INFO_num(rsk) <= idx) + return NULL; + ri = sk_PKCS7_RECIP_INFO_value(rsk, idx); + return ri->issuer_and_serial; +} + +ASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid) +{ + return get_attribute(si->auth_attr, nid); +} + +ASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid) +{ + return get_attribute(si->unauth_attr, nid); +} + +static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid) +{ + int idx; + X509_ATTRIBUTE *xa; + idx = X509at_get_attr_by_NID(sk, nid, -1); + xa = X509at_get_attr(sk, idx); + return X509_ATTRIBUTE_get0_type(xa, 0); +} + +ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk) +{ + ASN1_TYPE *astype; + if ((astype = get_attribute(sk, NID_pkcs9_messageDigest)) == NULL) + return NULL; + return astype->value.octet_string; +} + +int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si, + STACK_OF(X509_ATTRIBUTE) *sk) +{ + int i; + + sk_X509_ATTRIBUTE_pop_free(p7si->auth_attr, X509_ATTRIBUTE_free); + p7si->auth_attr = sk_X509_ATTRIBUTE_dup(sk); + if (p7si->auth_attr == NULL) + return 0; + for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) { + if ((sk_X509_ATTRIBUTE_set(p7si->auth_attr, i, + X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value + (sk, i)))) + == NULL) + return 0; + } + return 1; +} + +int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, + STACK_OF(X509_ATTRIBUTE) *sk) +{ + int i; + + sk_X509_ATTRIBUTE_pop_free(p7si->unauth_attr, X509_ATTRIBUTE_free); + p7si->unauth_attr = sk_X509_ATTRIBUTE_dup(sk); + if (p7si->unauth_attr == NULL) + return 0; + for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) { + if ((sk_X509_ATTRIBUTE_set(p7si->unauth_attr, i, + X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value + (sk, i)))) + == NULL) + return 0; + } + return 1; +} + +int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype, + void *value) +{ + return add_attribute(&(p7si->auth_attr), nid, atrtype, value); +} + +int PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype, + void *value) +{ + return add_attribute(&(p7si->unauth_attr), nid, atrtype, value); +} + +static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype, + void *value) +{ + X509_ATTRIBUTE *attr = NULL; + + if (*sk == NULL) { + if ((*sk = sk_X509_ATTRIBUTE_new_null()) == NULL) + return 0; + new_attrib: + if ((attr = X509_ATTRIBUTE_create(nid, atrtype, value)) == NULL) + return 0; + if (!sk_X509_ATTRIBUTE_push(*sk, attr)) { + X509_ATTRIBUTE_free(attr); + return 0; + } + } else { + int i; + + for (i = 0; i < sk_X509_ATTRIBUTE_num(*sk); i++) { + attr = sk_X509_ATTRIBUTE_value(*sk, i); + if (OBJ_obj2nid(X509_ATTRIBUTE_get0_object(attr)) == nid) { + X509_ATTRIBUTE_free(attr); + attr = X509_ATTRIBUTE_create(nid, atrtype, value); + if (attr == NULL) + return 0; + if (!sk_X509_ATTRIBUTE_set(*sk, i, attr)) { + X509_ATTRIBUTE_free(attr); + return 0; + } + goto end; + } + } + goto new_attrib; + } + end: + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/pk7_lib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/pk7_lib.c new file mode 100644 index 000000000..16b76431d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/pk7_lib.c @@ -0,0 +1,588 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include "internal/asn1_int.h" +#include "internal/evp_int.h" + +long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg) +{ + int nid; + long ret; + + nid = OBJ_obj2nid(p7->type); + + switch (cmd) { + /* NOTE(emilia): does not support detached digested data. */ + case PKCS7_OP_SET_DETACHED_SIGNATURE: + if (nid == NID_pkcs7_signed) { + ret = p7->detached = (int)larg; + if (ret && PKCS7_type_is_data(p7->d.sign->contents)) { + ASN1_OCTET_STRING *os; + os = p7->d.sign->contents->d.data; + ASN1_OCTET_STRING_free(os); + p7->d.sign->contents->d.data = NULL; + } + } else { + PKCS7err(PKCS7_F_PKCS7_CTRL, + PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE); + ret = 0; + } + break; + case PKCS7_OP_GET_DETACHED_SIGNATURE: + if (nid == NID_pkcs7_signed) { + if (!p7->d.sign || !p7->d.sign->contents->d.ptr) + ret = 1; + else + ret = 0; + + p7->detached = ret; + } else { + PKCS7err(PKCS7_F_PKCS7_CTRL, + PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE); + ret = 0; + } + + break; + default: + PKCS7err(PKCS7_F_PKCS7_CTRL, PKCS7_R_UNKNOWN_OPERATION); + ret = 0; + } + return ret; +} + +int PKCS7_content_new(PKCS7 *p7, int type) +{ + PKCS7 *ret = NULL; + + if ((ret = PKCS7_new()) == NULL) + goto err; + if (!PKCS7_set_type(ret, type)) + goto err; + if (!PKCS7_set_content(p7, ret)) + goto err; + + return 1; + err: + PKCS7_free(ret); + return 0; +} + +int PKCS7_set_content(PKCS7 *p7, PKCS7 *p7_data) +{ + int i; + + i = OBJ_obj2nid(p7->type); + switch (i) { + case NID_pkcs7_signed: + PKCS7_free(p7->d.sign->contents); + p7->d.sign->contents = p7_data; + break; + case NID_pkcs7_digest: + PKCS7_free(p7->d.digest->contents); + p7->d.digest->contents = p7_data; + break; + case NID_pkcs7_data: + case NID_pkcs7_enveloped: + case NID_pkcs7_signedAndEnveloped: + case NID_pkcs7_encrypted: + default: + PKCS7err(PKCS7_F_PKCS7_SET_CONTENT, PKCS7_R_UNSUPPORTED_CONTENT_TYPE); + goto err; + } + return 1; + err: + return 0; +} + +int PKCS7_set_type(PKCS7 *p7, int type) +{ + ASN1_OBJECT *obj; + + /* + * PKCS7_content_free(p7); + */ + obj = OBJ_nid2obj(type); /* will not fail */ + + switch (type) { + case NID_pkcs7_signed: + p7->type = obj; + if ((p7->d.sign = PKCS7_SIGNED_new()) == NULL) + goto err; + if (!ASN1_INTEGER_set(p7->d.sign->version, 1)) { + PKCS7_SIGNED_free(p7->d.sign); + p7->d.sign = NULL; + goto err; + } + break; + case NID_pkcs7_data: + p7->type = obj; + if ((p7->d.data = ASN1_OCTET_STRING_new()) == NULL) + goto err; + break; + case NID_pkcs7_signedAndEnveloped: + p7->type = obj; + if ((p7->d.signed_and_enveloped = PKCS7_SIGN_ENVELOPE_new()) + == NULL) + goto err; + if (!ASN1_INTEGER_set(p7->d.signed_and_enveloped->version, 1)) + goto err; + p7->d.signed_and_enveloped->enc_data->content_type + = OBJ_nid2obj(NID_pkcs7_data); + break; + case NID_pkcs7_enveloped: + p7->type = obj; + if ((p7->d.enveloped = PKCS7_ENVELOPE_new()) + == NULL) + goto err; + if (!ASN1_INTEGER_set(p7->d.enveloped->version, 0)) + goto err; + p7->d.enveloped->enc_data->content_type = OBJ_nid2obj(NID_pkcs7_data); + break; + case NID_pkcs7_encrypted: + p7->type = obj; + if ((p7->d.encrypted = PKCS7_ENCRYPT_new()) + == NULL) + goto err; + if (!ASN1_INTEGER_set(p7->d.encrypted->version, 0)) + goto err; + p7->d.encrypted->enc_data->content_type = OBJ_nid2obj(NID_pkcs7_data); + break; + + case NID_pkcs7_digest: + p7->type = obj; + if ((p7->d.digest = PKCS7_DIGEST_new()) + == NULL) + goto err; + if (!ASN1_INTEGER_set(p7->d.digest->version, 0)) + goto err; + break; + default: + PKCS7err(PKCS7_F_PKCS7_SET_TYPE, PKCS7_R_UNSUPPORTED_CONTENT_TYPE); + goto err; + } + return 1; + err: + return 0; +} + +int PKCS7_set0_type_other(PKCS7 *p7, int type, ASN1_TYPE *other) +{ + p7->type = OBJ_nid2obj(type); + p7->d.other = other; + return 1; +} + +int PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *psi) +{ + int i, j, nid; + X509_ALGOR *alg; + STACK_OF(PKCS7_SIGNER_INFO) *signer_sk; + STACK_OF(X509_ALGOR) *md_sk; + + i = OBJ_obj2nid(p7->type); + switch (i) { + case NID_pkcs7_signed: + signer_sk = p7->d.sign->signer_info; + md_sk = p7->d.sign->md_algs; + break; + case NID_pkcs7_signedAndEnveloped: + signer_sk = p7->d.signed_and_enveloped->signer_info; + md_sk = p7->d.signed_and_enveloped->md_algs; + break; + default: + PKCS7err(PKCS7_F_PKCS7_ADD_SIGNER, PKCS7_R_WRONG_CONTENT_TYPE); + return 0; + } + + nid = OBJ_obj2nid(psi->digest_alg->algorithm); + + /* If the digest is not currently listed, add it */ + j = 0; + for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++) { + alg = sk_X509_ALGOR_value(md_sk, i); + if (OBJ_obj2nid(alg->algorithm) == nid) { + j = 1; + break; + } + } + if (!j) { /* we need to add another algorithm */ + if ((alg = X509_ALGOR_new()) == NULL + || (alg->parameter = ASN1_TYPE_new()) == NULL) { + X509_ALGOR_free(alg); + PKCS7err(PKCS7_F_PKCS7_ADD_SIGNER, ERR_R_MALLOC_FAILURE); + return 0; + } + alg->algorithm = OBJ_nid2obj(nid); + alg->parameter->type = V_ASN1_NULL; + if (!sk_X509_ALGOR_push(md_sk, alg)) { + X509_ALGOR_free(alg); + return 0; + } + } + + if (!sk_PKCS7_SIGNER_INFO_push(signer_sk, psi)) + return 0; + return 1; +} + +int PKCS7_add_certificate(PKCS7 *p7, X509 *x509) +{ + int i; + STACK_OF(X509) **sk; + + i = OBJ_obj2nid(p7->type); + switch (i) { + case NID_pkcs7_signed: + sk = &(p7->d.sign->cert); + break; + case NID_pkcs7_signedAndEnveloped: + sk = &(p7->d.signed_and_enveloped->cert); + break; + default: + PKCS7err(PKCS7_F_PKCS7_ADD_CERTIFICATE, PKCS7_R_WRONG_CONTENT_TYPE); + return 0; + } + + if (*sk == NULL) + *sk = sk_X509_new_null(); + if (*sk == NULL) { + PKCS7err(PKCS7_F_PKCS7_ADD_CERTIFICATE, ERR_R_MALLOC_FAILURE); + return 0; + } + X509_up_ref(x509); + if (!sk_X509_push(*sk, x509)) { + X509_free(x509); + return 0; + } + return 1; +} + +int PKCS7_add_crl(PKCS7 *p7, X509_CRL *crl) +{ + int i; + STACK_OF(X509_CRL) **sk; + + i = OBJ_obj2nid(p7->type); + switch (i) { + case NID_pkcs7_signed: + sk = &(p7->d.sign->crl); + break; + case NID_pkcs7_signedAndEnveloped: + sk = &(p7->d.signed_and_enveloped->crl); + break; + default: + PKCS7err(PKCS7_F_PKCS7_ADD_CRL, PKCS7_R_WRONG_CONTENT_TYPE); + return 0; + } + + if (*sk == NULL) + *sk = sk_X509_CRL_new_null(); + if (*sk == NULL) { + PKCS7err(PKCS7_F_PKCS7_ADD_CRL, ERR_R_MALLOC_FAILURE); + return 0; + } + + X509_CRL_up_ref(crl); + if (!sk_X509_CRL_push(*sk, crl)) { + X509_CRL_free(crl); + return 0; + } + return 1; +} + +int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey, + const EVP_MD *dgst) +{ + int ret; + + /* We now need to add another PKCS7_SIGNER_INFO entry */ + if (!ASN1_INTEGER_set(p7i->version, 1)) + goto err; + if (!X509_NAME_set(&p7i->issuer_and_serial->issuer, + X509_get_issuer_name(x509))) + goto err; + + /* + * because ASN1_INTEGER_set is used to set a 'long' we will do things the + * ugly way. + */ + ASN1_INTEGER_free(p7i->issuer_and_serial->serial); + if (!(p7i->issuer_and_serial->serial = + ASN1_INTEGER_dup(X509_get_serialNumber(x509)))) + goto err; + + /* lets keep the pkey around for a while */ + EVP_PKEY_up_ref(pkey); + p7i->pkey = pkey; + + /* Set the algorithms */ + + X509_ALGOR_set0(p7i->digest_alg, OBJ_nid2obj(EVP_MD_type(dgst)), + V_ASN1_NULL, NULL); + + if (pkey->ameth && pkey->ameth->pkey_ctrl) { + ret = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_PKCS7_SIGN, 0, p7i); + if (ret > 0) + return 1; + if (ret != -2) { + PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SET, + PKCS7_R_SIGNING_CTRL_FAILURE); + return 0; + } + } + PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SET, + PKCS7_R_SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); + err: + return 0; +} + +PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509, EVP_PKEY *pkey, + const EVP_MD *dgst) +{ + PKCS7_SIGNER_INFO *si = NULL; + + if (dgst == NULL) { + int def_nid; + if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) <= 0) + goto err; + dgst = EVP_get_digestbynid(def_nid); + if (dgst == NULL) { + PKCS7err(PKCS7_F_PKCS7_ADD_SIGNATURE, PKCS7_R_NO_DEFAULT_DIGEST); + goto err; + } + } + + if ((si = PKCS7_SIGNER_INFO_new()) == NULL) + goto err; + if (!PKCS7_SIGNER_INFO_set(si, x509, pkey, dgst)) + goto err; + if (!PKCS7_add_signer(p7, si)) + goto err; + return si; + err: + PKCS7_SIGNER_INFO_free(si); + return NULL; +} + +int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md) +{ + if (PKCS7_type_is_digest(p7)) { + if ((p7->d.digest->md->parameter = ASN1_TYPE_new()) == NULL) { + PKCS7err(PKCS7_F_PKCS7_SET_DIGEST, ERR_R_MALLOC_FAILURE); + return 0; + } + p7->d.digest->md->parameter->type = V_ASN1_NULL; + p7->d.digest->md->algorithm = OBJ_nid2obj(EVP_MD_nid(md)); + return 1; + } + + PKCS7err(PKCS7_F_PKCS7_SET_DIGEST, PKCS7_R_WRONG_CONTENT_TYPE); + return 1; +} + +STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7) +{ + if (p7 == NULL || p7->d.ptr == NULL) + return NULL; + if (PKCS7_type_is_signed(p7)) { + return p7->d.sign->signer_info; + } else if (PKCS7_type_is_signedAndEnveloped(p7)) { + return p7->d.signed_and_enveloped->signer_info; + } else + return NULL; +} + +void PKCS7_SIGNER_INFO_get0_algs(PKCS7_SIGNER_INFO *si, EVP_PKEY **pk, + X509_ALGOR **pdig, X509_ALGOR **psig) +{ + if (pk) + *pk = si->pkey; + if (pdig) + *pdig = si->digest_alg; + if (psig) + *psig = si->digest_enc_alg; +} + +void PKCS7_RECIP_INFO_get0_alg(PKCS7_RECIP_INFO *ri, X509_ALGOR **penc) +{ + if (penc) + *penc = ri->key_enc_algor; +} + +PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509) +{ + PKCS7_RECIP_INFO *ri; + + if ((ri = PKCS7_RECIP_INFO_new()) == NULL) + goto err; + if (!PKCS7_RECIP_INFO_set(ri, x509)) + goto err; + if (!PKCS7_add_recipient_info(p7, ri)) + goto err; + return ri; + err: + PKCS7_RECIP_INFO_free(ri); + return NULL; +} + +int PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri) +{ + int i; + STACK_OF(PKCS7_RECIP_INFO) *sk; + + i = OBJ_obj2nid(p7->type); + switch (i) { + case NID_pkcs7_signedAndEnveloped: + sk = p7->d.signed_and_enveloped->recipientinfo; + break; + case NID_pkcs7_enveloped: + sk = p7->d.enveloped->recipientinfo; + break; + default: + PKCS7err(PKCS7_F_PKCS7_ADD_RECIPIENT_INFO, + PKCS7_R_WRONG_CONTENT_TYPE); + return 0; + } + + if (!sk_PKCS7_RECIP_INFO_push(sk, ri)) + return 0; + return 1; +} + +int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509) +{ + int ret; + EVP_PKEY *pkey = NULL; + if (!ASN1_INTEGER_set(p7i->version, 0)) + return 0; + if (!X509_NAME_set(&p7i->issuer_and_serial->issuer, + X509_get_issuer_name(x509))) + return 0; + + ASN1_INTEGER_free(p7i->issuer_and_serial->serial); + if (!(p7i->issuer_and_serial->serial = + ASN1_INTEGER_dup(X509_get_serialNumber(x509)))) + return 0; + + pkey = X509_get0_pubkey(x509); + + if (!pkey || !pkey->ameth || !pkey->ameth->pkey_ctrl) { + PKCS7err(PKCS7_F_PKCS7_RECIP_INFO_SET, + PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); + goto err; + } + + ret = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_PKCS7_ENCRYPT, 0, p7i); + if (ret == -2) { + PKCS7err(PKCS7_F_PKCS7_RECIP_INFO_SET, + PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); + goto err; + } + if (ret <= 0) { + PKCS7err(PKCS7_F_PKCS7_RECIP_INFO_SET, + PKCS7_R_ENCRYPTION_CTRL_FAILURE); + goto err; + } + + X509_up_ref(x509); + p7i->cert = x509; + + return 1; + + err: + return 0; +} + +X509 *PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si) +{ + if (PKCS7_type_is_signed(p7)) + return (X509_find_by_issuer_and_serial(p7->d.sign->cert, + si->issuer_and_serial->issuer, + si-> + issuer_and_serial->serial)); + else + return NULL; +} + +int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher) +{ + int i; + PKCS7_ENC_CONTENT *ec; + + i = OBJ_obj2nid(p7->type); + switch (i) { + case NID_pkcs7_signedAndEnveloped: + ec = p7->d.signed_and_enveloped->enc_data; + break; + case NID_pkcs7_enveloped: + ec = p7->d.enveloped->enc_data; + break; + default: + PKCS7err(PKCS7_F_PKCS7_SET_CIPHER, PKCS7_R_WRONG_CONTENT_TYPE); + return 0; + } + + /* Check cipher OID exists and has data in it */ + i = EVP_CIPHER_type(cipher); + if (i == NID_undef) { + PKCS7err(PKCS7_F_PKCS7_SET_CIPHER, + PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER); + return 0; + } + + ec->cipher = cipher; + return 1; +} + +int PKCS7_stream(unsigned char ***boundary, PKCS7 *p7) +{ + ASN1_OCTET_STRING *os = NULL; + + switch (OBJ_obj2nid(p7->type)) { + case NID_pkcs7_data: + os = p7->d.data; + break; + + case NID_pkcs7_signedAndEnveloped: + os = p7->d.signed_and_enveloped->enc_data->enc_data; + if (os == NULL) { + os = ASN1_OCTET_STRING_new(); + p7->d.signed_and_enveloped->enc_data->enc_data = os; + } + break; + + case NID_pkcs7_enveloped: + os = p7->d.enveloped->enc_data->enc_data; + if (os == NULL) { + os = ASN1_OCTET_STRING_new(); + p7->d.enveloped->enc_data->enc_data = os; + } + break; + + case NID_pkcs7_signed: + os = p7->d.sign->contents->d.data; + break; + + default: + os = NULL; + break; + } + + if (os == NULL) + return 0; + + os->flags |= ASN1_STRING_FLAG_NDEF; + *boundary = &os->data; + + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/pk7_mime.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/pk7_mime.c new file mode 100644 index 000000000..19e686814 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/pk7_mime.c @@ -0,0 +1,48 @@ +/* + * Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include + +/* PKCS#7 wrappers round generalised stream and MIME routines */ + +int i2d_PKCS7_bio_stream(BIO *out, PKCS7 *p7, BIO *in, int flags) +{ + return i2d_ASN1_bio_stream(out, (ASN1_VALUE *)p7, in, flags, + ASN1_ITEM_rptr(PKCS7)); +} + +int PEM_write_bio_PKCS7_stream(BIO *out, PKCS7 *p7, BIO *in, int flags) +{ + return PEM_write_bio_ASN1_stream(out, (ASN1_VALUE *)p7, in, flags, + "PKCS7", ASN1_ITEM_rptr(PKCS7)); +} + +int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags) +{ + STACK_OF(X509_ALGOR) *mdalgs; + int ctype_nid = OBJ_obj2nid(p7->type); + if (ctype_nid == NID_pkcs7_signed) + mdalgs = p7->d.sign->md_algs; + else + mdalgs = NULL; + + flags ^= SMIME_OLDMIME; + + return SMIME_write_ASN1(bio, (ASN1_VALUE *)p7, data, flags, + ctype_nid, NID_undef, mdalgs, + ASN1_ITEM_rptr(PKCS7)); +} + +PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont) +{ + return (PKCS7 *)SMIME_read_ASN1(bio, bcont, ASN1_ITEM_rptr(PKCS7)); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/pk7_smime.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/pk7_smime.c new file mode 100644 index 000000000..44187230e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/pk7_smime.c @@ -0,0 +1,549 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Simple PKCS#7 processing functions */ + +#include +#include "internal/cryptlib.h" +#include +#include + + +#define BUFFERSIZE 4096 + +static int pkcs7_copy_existing_digest(PKCS7 *p7, PKCS7_SIGNER_INFO *si); + +PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, + BIO *data, int flags) +{ + PKCS7 *p7; + int i; + + if ((p7 = PKCS7_new()) == NULL) { + PKCS7err(PKCS7_F_PKCS7_SIGN, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (!PKCS7_set_type(p7, NID_pkcs7_signed)) + goto err; + + if (!PKCS7_content_new(p7, NID_pkcs7_data)) + goto err; + + if (pkey && !PKCS7_sign_add_signer(p7, signcert, pkey, NULL, flags)) { + PKCS7err(PKCS7_F_PKCS7_SIGN, PKCS7_R_PKCS7_ADD_SIGNER_ERROR); + goto err; + } + + if (!(flags & PKCS7_NOCERTS)) { + for (i = 0; i < sk_X509_num(certs); i++) { + if (!PKCS7_add_certificate(p7, sk_X509_value(certs, i))) + goto err; + } + } + + if (flags & PKCS7_DETACHED) + PKCS7_set_detached(p7, 1); + + if (flags & (PKCS7_STREAM | PKCS7_PARTIAL)) + return p7; + + if (PKCS7_final(p7, data, flags)) + return p7; + + err: + PKCS7_free(p7); + return NULL; +} + +int PKCS7_final(PKCS7 *p7, BIO *data, int flags) +{ + BIO *p7bio; + int ret = 0; + + if ((p7bio = PKCS7_dataInit(p7, NULL)) == NULL) { + PKCS7err(PKCS7_F_PKCS7_FINAL, ERR_R_MALLOC_FAILURE); + return 0; + } + + SMIME_crlf_copy(data, p7bio, flags); + + (void)BIO_flush(p7bio); + + if (!PKCS7_dataFinal(p7, p7bio)) { + PKCS7err(PKCS7_F_PKCS7_FINAL, PKCS7_R_PKCS7_DATASIGN); + goto err; + } + + ret = 1; + + err: + BIO_free_all(p7bio); + + return ret; + +} + +/* Check to see if a cipher exists and if so add S/MIME capabilities */ + +static int add_cipher_smcap(STACK_OF(X509_ALGOR) *sk, int nid, int arg) +{ + if (EVP_get_cipherbynid(nid)) + return PKCS7_simple_smimecap(sk, nid, arg); + return 1; +} + +static int add_digest_smcap(STACK_OF(X509_ALGOR) *sk, int nid, int arg) +{ + if (EVP_get_digestbynid(nid)) + return PKCS7_simple_smimecap(sk, nid, arg); + return 1; +} + +PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, X509 *signcert, + EVP_PKEY *pkey, const EVP_MD *md, + int flags) +{ + PKCS7_SIGNER_INFO *si = NULL; + STACK_OF(X509_ALGOR) *smcap = NULL; + if (!X509_check_private_key(signcert, pkey)) { + PKCS7err(PKCS7_F_PKCS7_SIGN_ADD_SIGNER, + PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); + return NULL; + } + + if ((si = PKCS7_add_signature(p7, signcert, pkey, md)) == NULL) { + PKCS7err(PKCS7_F_PKCS7_SIGN_ADD_SIGNER, + PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR); + return NULL; + } + + if (!(flags & PKCS7_NOCERTS)) { + if (!PKCS7_add_certificate(p7, signcert)) + goto err; + } + + if (!(flags & PKCS7_NOATTR)) { + if (!PKCS7_add_attrib_content_type(si, NULL)) + goto err; + /* Add SMIMECapabilities */ + if (!(flags & PKCS7_NOSMIMECAP)) { + if ((smcap = sk_X509_ALGOR_new_null()) == NULL) { + PKCS7err(PKCS7_F_PKCS7_SIGN_ADD_SIGNER, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!add_cipher_smcap(smcap, NID_aes_256_cbc, -1) + || !add_digest_smcap(smcap, NID_id_GostR3411_2012_256, -1) + || !add_digest_smcap(smcap, NID_id_GostR3411_2012_512, -1) + || !add_digest_smcap(smcap, NID_id_GostR3411_94, -1) + || !add_cipher_smcap(smcap, NID_id_Gost28147_89, -1) + || !add_cipher_smcap(smcap, NID_aes_192_cbc, -1) + || !add_cipher_smcap(smcap, NID_aes_128_cbc, -1) + || !add_cipher_smcap(smcap, NID_des_ede3_cbc, -1) + || !add_cipher_smcap(smcap, NID_rc2_cbc, 128) + || !add_cipher_smcap(smcap, NID_rc2_cbc, 64) + || !add_cipher_smcap(smcap, NID_des_cbc, -1) + || !add_cipher_smcap(smcap, NID_rc2_cbc, 40) + || !PKCS7_add_attrib_smimecap(si, smcap)) + goto err; + sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free); + smcap = NULL; + } + if (flags & PKCS7_REUSE_DIGEST) { + if (!pkcs7_copy_existing_digest(p7, si)) + goto err; + if (!(flags & PKCS7_PARTIAL) && !PKCS7_SIGNER_INFO_sign(si)) + goto err; + } + } + return si; + err: + sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free); + return NULL; +} + +/* + * Search for a digest matching SignerInfo digest type and if found copy + * across. + */ + +static int pkcs7_copy_existing_digest(PKCS7 *p7, PKCS7_SIGNER_INFO *si) +{ + int i; + STACK_OF(PKCS7_SIGNER_INFO) *sinfos; + PKCS7_SIGNER_INFO *sitmp; + ASN1_OCTET_STRING *osdig = NULL; + sinfos = PKCS7_get_signer_info(p7); + for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++) { + sitmp = sk_PKCS7_SIGNER_INFO_value(sinfos, i); + if (si == sitmp) + break; + if (sk_X509_ATTRIBUTE_num(sitmp->auth_attr) <= 0) + continue; + if (!OBJ_cmp(si->digest_alg->algorithm, sitmp->digest_alg->algorithm)) { + osdig = PKCS7_digest_from_attributes(sitmp->auth_attr); + break; + } + + } + + if (osdig) + return PKCS7_add1_attrib_digest(si, osdig->data, osdig->length); + + PKCS7err(PKCS7_F_PKCS7_COPY_EXISTING_DIGEST, + PKCS7_R_NO_MATCHING_DIGEST_TYPE_FOUND); + return 0; +} + +int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, + BIO *indata, BIO *out, int flags) +{ + STACK_OF(X509) *signers; + X509 *signer; + STACK_OF(PKCS7_SIGNER_INFO) *sinfos; + PKCS7_SIGNER_INFO *si; + X509_STORE_CTX *cert_ctx = NULL; + char *buf = NULL; + int i, j = 0, k, ret = 0; + BIO *p7bio = NULL; + BIO *tmpin = NULL, *tmpout = NULL; + + if (!p7) { + PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_INVALID_NULL_POINTER); + return 0; + } + + if (!PKCS7_type_is_signed(p7)) { + PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_WRONG_CONTENT_TYPE); + return 0; + } + + /* Check for no data and no content: no data to verify signature */ + if (PKCS7_get_detached(p7) && !indata) { + PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_NO_CONTENT); + return 0; + } + + if (flags & PKCS7_NO_DUAL_CONTENT) { + /* + * This was originally "#if 0" because we thought that only old broken + * Netscape did this. It turns out that Authenticode uses this kind + * of "extended" PKCS7 format, and things like UEFI secure boot and + * tools like osslsigncode need it. In Authenticode the verification + * process is different, but the existing PKCs7 verification works. + */ + if (!PKCS7_get_detached(p7) && indata) { + PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_CONTENT_AND_DATA_PRESENT); + return 0; + } + } + + sinfos = PKCS7_get_signer_info(p7); + + if (!sinfos || !sk_PKCS7_SIGNER_INFO_num(sinfos)) { + PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_NO_SIGNATURES_ON_DATA); + return 0; + } + + signers = PKCS7_get0_signers(p7, certs, flags); + if (!signers) + return 0; + + /* Now verify the certificates */ + + cert_ctx = X509_STORE_CTX_new(); + if (cert_ctx == NULL) + goto err; + if (!(flags & PKCS7_NOVERIFY)) + for (k = 0; k < sk_X509_num(signers); k++) { + signer = sk_X509_value(signers, k); + if (!(flags & PKCS7_NOCHAIN)) { + if (!X509_STORE_CTX_init(cert_ctx, store, signer, + p7->d.sign->cert)) { + PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_X509_LIB); + goto err; + } + X509_STORE_CTX_set_default(cert_ctx, "smime_sign"); + } else if (!X509_STORE_CTX_init(cert_ctx, store, signer, NULL)) { + PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_X509_LIB); + goto err; + } + if (!(flags & PKCS7_NOCRL)) + X509_STORE_CTX_set0_crls(cert_ctx, p7->d.sign->crl); + i = X509_verify_cert(cert_ctx); + if (i <= 0) + j = X509_STORE_CTX_get_error(cert_ctx); + X509_STORE_CTX_cleanup(cert_ctx); + if (i <= 0) { + PKCS7err(PKCS7_F_PKCS7_VERIFY, + PKCS7_R_CERTIFICATE_VERIFY_ERROR); + ERR_add_error_data(2, "Verify error:", + X509_verify_cert_error_string(j)); + goto err; + } + /* Check for revocation status here */ + } + + /* + * Performance optimization: if the content is a memory BIO then store + * its contents in a temporary read only memory BIO. This avoids + * potentially large numbers of slow copies of data which will occur when + * reading from a read write memory BIO when signatures are calculated. + */ + + if (indata && (BIO_method_type(indata) == BIO_TYPE_MEM)) { + char *ptr; + long len; + len = BIO_get_mem_data(indata, &ptr); + tmpin = BIO_new_mem_buf(ptr, len); + if (tmpin == NULL) { + PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_MALLOC_FAILURE); + goto err; + } + } else + tmpin = indata; + + if ((p7bio = PKCS7_dataInit(p7, tmpin)) == NULL) + goto err; + + if (flags & PKCS7_TEXT) { + if ((tmpout = BIO_new(BIO_s_mem())) == NULL) { + PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_MALLOC_FAILURE); + goto err; + } + BIO_set_mem_eof_return(tmpout, 0); + } else + tmpout = out; + + /* We now have to 'read' from p7bio to calculate digests etc. */ + if ((buf = OPENSSL_malloc(BUFFERSIZE)) == NULL) { + PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_MALLOC_FAILURE); + goto err; + } + for (;;) { + i = BIO_read(p7bio, buf, BUFFERSIZE); + if (i <= 0) + break; + if (tmpout) + BIO_write(tmpout, buf, i); + } + + if (flags & PKCS7_TEXT) { + if (!SMIME_text(tmpout, out)) { + PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_SMIME_TEXT_ERROR); + BIO_free(tmpout); + goto err; + } + BIO_free(tmpout); + } + + /* Now Verify All Signatures */ + if (!(flags & PKCS7_NOSIGS)) + for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++) { + si = sk_PKCS7_SIGNER_INFO_value(sinfos, i); + signer = sk_X509_value(signers, i); + j = PKCS7_signatureVerify(p7bio, p7, si, signer); + if (j <= 0) { + PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_SIGNATURE_FAILURE); + goto err; + } + } + + ret = 1; + + err: + X509_STORE_CTX_free(cert_ctx); + OPENSSL_free(buf); + if (tmpin == indata) { + if (indata) + BIO_pop(p7bio); + } + BIO_free_all(p7bio); + sk_X509_free(signers); + return ret; +} + +STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, + int flags) +{ + STACK_OF(X509) *signers; + STACK_OF(PKCS7_SIGNER_INFO) *sinfos; + PKCS7_SIGNER_INFO *si; + PKCS7_ISSUER_AND_SERIAL *ias; + X509 *signer; + int i; + + if (!p7) { + PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS, PKCS7_R_INVALID_NULL_POINTER); + return NULL; + } + + if (!PKCS7_type_is_signed(p7)) { + PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS, PKCS7_R_WRONG_CONTENT_TYPE); + return NULL; + } + + /* Collect all the signers together */ + + sinfos = PKCS7_get_signer_info(p7); + + if (sk_PKCS7_SIGNER_INFO_num(sinfos) <= 0) { + PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS, PKCS7_R_NO_SIGNERS); + return 0; + } + + if ((signers = sk_X509_new_null()) == NULL) { + PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS, ERR_R_MALLOC_FAILURE); + return NULL; + } + + for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++) { + si = sk_PKCS7_SIGNER_INFO_value(sinfos, i); + ias = si->issuer_and_serial; + signer = NULL; + /* If any certificates passed they take priority */ + if (certs) + signer = X509_find_by_issuer_and_serial(certs, + ias->issuer, ias->serial); + if (!signer && !(flags & PKCS7_NOINTERN) + && p7->d.sign->cert) + signer = + X509_find_by_issuer_and_serial(p7->d.sign->cert, + ias->issuer, ias->serial); + if (!signer) { + PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS, + PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND); + sk_X509_free(signers); + return 0; + } + + if (!sk_X509_push(signers, signer)) { + sk_X509_free(signers); + return NULL; + } + } + return signers; +} + +/* Build a complete PKCS#7 enveloped data */ + +PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher, + int flags) +{ + PKCS7 *p7; + BIO *p7bio = NULL; + int i; + X509 *x509; + if ((p7 = PKCS7_new()) == NULL) { + PKCS7err(PKCS7_F_PKCS7_ENCRYPT, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (!PKCS7_set_type(p7, NID_pkcs7_enveloped)) + goto err; + if (!PKCS7_set_cipher(p7, cipher)) { + PKCS7err(PKCS7_F_PKCS7_ENCRYPT, PKCS7_R_ERROR_SETTING_CIPHER); + goto err; + } + + for (i = 0; i < sk_X509_num(certs); i++) { + x509 = sk_X509_value(certs, i); + if (!PKCS7_add_recipient(p7, x509)) { + PKCS7err(PKCS7_F_PKCS7_ENCRYPT, PKCS7_R_ERROR_ADDING_RECIPIENT); + goto err; + } + } + + if (flags & PKCS7_STREAM) + return p7; + + if (PKCS7_final(p7, in, flags)) + return p7; + + err: + + BIO_free_all(p7bio); + PKCS7_free(p7); + return NULL; + +} + +int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags) +{ + BIO *tmpmem; + int ret = 0, i; + char *buf = NULL; + + if (!p7) { + PKCS7err(PKCS7_F_PKCS7_DECRYPT, PKCS7_R_INVALID_NULL_POINTER); + return 0; + } + + if (!PKCS7_type_is_enveloped(p7)) { + PKCS7err(PKCS7_F_PKCS7_DECRYPT, PKCS7_R_WRONG_CONTENT_TYPE); + return 0; + } + + if (cert && !X509_check_private_key(cert, pkey)) { + PKCS7err(PKCS7_F_PKCS7_DECRYPT, + PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); + return 0; + } + + if ((tmpmem = PKCS7_dataDecode(p7, pkey, NULL, cert)) == NULL) { + PKCS7err(PKCS7_F_PKCS7_DECRYPT, PKCS7_R_DECRYPT_ERROR); + return 0; + } + + if (flags & PKCS7_TEXT) { + BIO *tmpbuf, *bread; + /* Encrypt BIOs can't do BIO_gets() so add a buffer BIO */ + if ((tmpbuf = BIO_new(BIO_f_buffer())) == NULL) { + PKCS7err(PKCS7_F_PKCS7_DECRYPT, ERR_R_MALLOC_FAILURE); + BIO_free_all(tmpmem); + return 0; + } + if ((bread = BIO_push(tmpbuf, tmpmem)) == NULL) { + PKCS7err(PKCS7_F_PKCS7_DECRYPT, ERR_R_MALLOC_FAILURE); + BIO_free_all(tmpbuf); + BIO_free_all(tmpmem); + return 0; + } + ret = SMIME_text(bread, data); + if (ret > 0 && BIO_method_type(tmpmem) == BIO_TYPE_CIPHER) { + if (!BIO_get_cipher_status(tmpmem)) + ret = 0; + } + BIO_free_all(bread); + return ret; + } + if ((buf = OPENSSL_malloc(BUFFERSIZE)) == NULL) { + PKCS7err(PKCS7_F_PKCS7_DECRYPT, ERR_R_MALLOC_FAILURE); + goto err; + } + for (;;) { + i = BIO_read(tmpmem, buf, BUFFERSIZE); + if (i <= 0) { + ret = 1; + if (BIO_method_type(tmpmem) == BIO_TYPE_CIPHER) { + if (!BIO_get_cipher_status(tmpmem)) + ret = 0; + } + + break; + } + if (BIO_write(data, buf, i) != i) { + break; + } + } +err: + OPENSSL_free(buf); + BIO_free_all(tmpmem); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/pkcs7err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/pkcs7err.c new file mode 100644 index 000000000..07490c1a5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/pkcs7/pkcs7err.c @@ -0,0 +1,156 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA PKCS7_str_functs[] = { + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, 0), + "do_pkcs7_signed_attrib"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_ADD0_ATTRIB_SIGNING_TIME, 0), + "PKCS7_add0_attrib_signing_time"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_ADD_ATTRIB_SMIMECAP, 0), + "PKCS7_add_attrib_smimecap"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_ADD_CERTIFICATE, 0), + "PKCS7_add_certificate"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_ADD_CRL, 0), "PKCS7_add_crl"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_ADD_RECIPIENT_INFO, 0), + "PKCS7_add_recipient_info"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_ADD_SIGNATURE, 0), + "PKCS7_add_signature"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_ADD_SIGNER, 0), "PKCS7_add_signer"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_BIO_ADD_DIGEST, 0), + "PKCS7_bio_add_digest"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_COPY_EXISTING_DIGEST, 0), + "pkcs7_copy_existing_digest"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_CTRL, 0), "PKCS7_ctrl"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_DATADECODE, 0), "PKCS7_dataDecode"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_DATAFINAL, 0), "PKCS7_dataFinal"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_DATAINIT, 0), "PKCS7_dataInit"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_DATAVERIFY, 0), "PKCS7_dataVerify"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_DECRYPT, 0), "PKCS7_decrypt"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_DECRYPT_RINFO, 0), + "pkcs7_decrypt_rinfo"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_ENCODE_RINFO, 0), + "pkcs7_encode_rinfo"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_ENCRYPT, 0), "PKCS7_encrypt"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_FINAL, 0), "PKCS7_final"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_FIND_DIGEST, 0), + "PKCS7_find_digest"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_GET0_SIGNERS, 0), + "PKCS7_get0_signers"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_RECIP_INFO_SET, 0), + "PKCS7_RECIP_INFO_set"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_SET_CIPHER, 0), "PKCS7_set_cipher"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_SET_CONTENT, 0), + "PKCS7_set_content"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_SET_DIGEST, 0), "PKCS7_set_digest"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_SET_TYPE, 0), "PKCS7_set_type"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_SIGN, 0), "PKCS7_sign"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_SIGNATUREVERIFY, 0), + "PKCS7_signatureVerify"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_SIGNER_INFO_SET, 0), + "PKCS7_SIGNER_INFO_set"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_SIGNER_INFO_SIGN, 0), + "PKCS7_SIGNER_INFO_sign"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_SIGN_ADD_SIGNER, 0), + "PKCS7_sign_add_signer"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_SIMPLE_SMIMECAP, 0), + "PKCS7_simple_smimecap"}, + {ERR_PACK(ERR_LIB_PKCS7, PKCS7_F_PKCS7_VERIFY, 0), "PKCS7_verify"}, + {0, NULL} +}; + +static const ERR_STRING_DATA PKCS7_str_reasons[] = { + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_CERTIFICATE_VERIFY_ERROR), + "certificate verify error"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER), + "cipher has no object identifier"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_CIPHER_NOT_INITIALIZED), + "cipher not initialized"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_CONTENT_AND_DATA_PRESENT), + "content and data present"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_CTRL_ERROR), "ctrl error"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_DECRYPT_ERROR), "decrypt error"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_DIGEST_FAILURE), "digest failure"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_ENCRYPTION_CTRL_FAILURE), + "encryption ctrl failure"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE), + "encryption not supported for this key type"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_ERROR_ADDING_RECIPIENT), + "error adding recipient"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_ERROR_SETTING_CIPHER), + "error setting cipher"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_INVALID_NULL_POINTER), + "invalid null pointer"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_INVALID_SIGNED_DATA_TYPE), + "invalid signed data type"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_NO_CONTENT), "no content"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_NO_DEFAULT_DIGEST), + "no default digest"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_NO_MATCHING_DIGEST_TYPE_FOUND), + "no matching digest type found"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE), + "no recipient matches certificate"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_NO_SIGNATURES_ON_DATA), + "no signatures on data"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_NO_SIGNERS), "no signers"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE), + "operation not supported on this type"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR), + "pkcs7 add signature error"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_PKCS7_ADD_SIGNER_ERROR), + "pkcs7 add signer error"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_PKCS7_DATASIGN), "pkcs7 datasign"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE), + "private key does not match certificate"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_SIGNATURE_FAILURE), + "signature failure"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND), + "signer certificate not found"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_SIGNING_CTRL_FAILURE), + "signing ctrl failure"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE), + "signing not supported for this key type"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_SMIME_TEXT_ERROR), "smime text error"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_UNABLE_TO_FIND_CERTIFICATE), + "unable to find certificate"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_UNABLE_TO_FIND_MEM_BIO), + "unable to find mem bio"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST), + "unable to find message digest"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_UNKNOWN_DIGEST_TYPE), + "unknown digest type"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_UNKNOWN_OPERATION), + "unknown operation"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_UNSUPPORTED_CIPHER_TYPE), + "unsupported cipher type"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_UNSUPPORTED_CONTENT_TYPE), + "unsupported content type"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_WRONG_CONTENT_TYPE), + "wrong content type"}, + {ERR_PACK(ERR_LIB_PKCS7, 0, PKCS7_R_WRONG_PKCS7_TYPE), "wrong pkcs7 type"}, + {0, NULL} +}; + +#endif + +int ERR_load_PKCS7_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(PKCS7_str_functs[0].error) == NULL) { + ERR_load_strings_const(PKCS7_str_functs); + ERR_load_strings_const(PKCS7_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-armv4.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-armv4.pl new file mode 100755 index 000000000..5cdb6be05 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-armv4.pl @@ -0,0 +1,1253 @@ +#! /usr/bin/env perl +# Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# IALU(*)/gcc-4.4 NEON +# +# ARM11xx(ARMv6) 7.78/+100% - +# Cortex-A5 6.35/+130% 3.00 +# Cortex-A8 6.25/+115% 2.36 +# Cortex-A9 5.10/+95% 2.55 +# Cortex-A15 3.85/+85% 1.25(**) +# Snapdragon S4 5.70/+100% 1.48(**) +# +# (*) this is for -march=armv6, i.e. with bunch of ldrb loading data; +# (**) these are trade-off results, they can be improved by ~8% but at +# the cost of 15/12% regression on Cortex-A5/A7, it's even possible +# to improve Cortex-A9 result, but then A5/A7 loose more than 20%; + +$flavour = shift; +if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + open STDOUT,">$output"; +} + +($ctx,$inp,$len,$padbit)=map("r$_",(0..3)); + +$code.=<<___; +#include "arm_arch.h" + +.text +#if defined(__thumb2__) +.syntax unified +.thumb +#else +.code 32 +#endif + +.globl poly1305_emit +.globl poly1305_blocks +.globl poly1305_init +.type poly1305_init,%function +.align 5 +poly1305_init: +.Lpoly1305_init: + stmdb sp!,{r4-r11} + + eor r3,r3,r3 + cmp $inp,#0 + str r3,[$ctx,#0] @ zero hash value + str r3,[$ctx,#4] + str r3,[$ctx,#8] + str r3,[$ctx,#12] + str r3,[$ctx,#16] + str r3,[$ctx,#36] @ is_base2_26 + add $ctx,$ctx,#20 + +#ifdef __thumb2__ + it eq +#endif + moveq r0,#0 + beq .Lno_key + +#if __ARM_MAX_ARCH__>=7 + adr r11,.Lpoly1305_init + ldr r12,.LOPENSSL_armcap +#endif + ldrb r4,[$inp,#0] + mov r10,#0x0fffffff + ldrb r5,[$inp,#1] + and r3,r10,#-4 @ 0x0ffffffc + ldrb r6,[$inp,#2] + ldrb r7,[$inp,#3] + orr r4,r4,r5,lsl#8 + ldrb r5,[$inp,#4] + orr r4,r4,r6,lsl#16 + ldrb r6,[$inp,#5] + orr r4,r4,r7,lsl#24 + ldrb r7,[$inp,#6] + and r4,r4,r10 + +#if __ARM_MAX_ARCH__>=7 + ldr r12,[r11,r12] @ OPENSSL_armcap_P +# ifdef __APPLE__ + ldr r12,[r12] +# endif +#endif + ldrb r8,[$inp,#7] + orr r5,r5,r6,lsl#8 + ldrb r6,[$inp,#8] + orr r5,r5,r7,lsl#16 + ldrb r7,[$inp,#9] + orr r5,r5,r8,lsl#24 + ldrb r8,[$inp,#10] + and r5,r5,r3 + +#if __ARM_MAX_ARCH__>=7 + tst r12,#ARMV7_NEON @ check for NEON +# ifdef __APPLE__ + adr r9,poly1305_blocks_neon + adr r11,poly1305_blocks +# ifdef __thumb2__ + it ne +# endif + movne r11,r9 + adr r12,poly1305_emit + adr r10,poly1305_emit_neon +# ifdef __thumb2__ + it ne +# endif + movne r12,r10 +# else +# ifdef __thumb2__ + itete eq +# endif + addeq r12,r11,#(poly1305_emit-.Lpoly1305_init) + addne r12,r11,#(poly1305_emit_neon-.Lpoly1305_init) + addeq r11,r11,#(poly1305_blocks-.Lpoly1305_init) + addne r11,r11,#(poly1305_blocks_neon-.Lpoly1305_init) +# endif +# ifdef __thumb2__ + orr r12,r12,#1 @ thumb-ify address + orr r11,r11,#1 +# endif +#endif + ldrb r9,[$inp,#11] + orr r6,r6,r7,lsl#8 + ldrb r7,[$inp,#12] + orr r6,r6,r8,lsl#16 + ldrb r8,[$inp,#13] + orr r6,r6,r9,lsl#24 + ldrb r9,[$inp,#14] + and r6,r6,r3 + + ldrb r10,[$inp,#15] + orr r7,r7,r8,lsl#8 + str r4,[$ctx,#0] + orr r7,r7,r9,lsl#16 + str r5,[$ctx,#4] + orr r7,r7,r10,lsl#24 + str r6,[$ctx,#8] + and r7,r7,r3 + str r7,[$ctx,#12] +#if __ARM_MAX_ARCH__>=7 + stmia r2,{r11,r12} @ fill functions table + mov r0,#1 +#else + mov r0,#0 +#endif +.Lno_key: + ldmia sp!,{r4-r11} +#if __ARM_ARCH__>=5 + ret @ bx lr +#else + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.size poly1305_init,.-poly1305_init +___ +{ +my ($h0,$h1,$h2,$h3,$h4,$r0,$r1,$r2,$r3)=map("r$_",(4..12)); +my ($s1,$s2,$s3)=($r1,$r2,$r3); + +$code.=<<___; +.type poly1305_blocks,%function +.align 5 +poly1305_blocks: +.Lpoly1305_blocks: + stmdb sp!,{r3-r11,lr} + + ands $len,$len,#-16 + beq .Lno_data + + cmp $padbit,#0 + add $len,$len,$inp @ end pointer + sub sp,sp,#32 + + ldmia $ctx,{$h0-$r3} @ load context + + str $ctx,[sp,#12] @ offload stuff + mov lr,$inp + str $len,[sp,#16] + str $r1,[sp,#20] + str $r2,[sp,#24] + str $r3,[sp,#28] + b .Loop + +.Loop: +#if __ARM_ARCH__<7 + ldrb r0,[lr],#16 @ load input +# ifdef __thumb2__ + it hi +# endif + addhi $h4,$h4,#1 @ 1<<128 + ldrb r1,[lr,#-15] + ldrb r2,[lr,#-14] + ldrb r3,[lr,#-13] + orr r1,r0,r1,lsl#8 + ldrb r0,[lr,#-12] + orr r2,r1,r2,lsl#16 + ldrb r1,[lr,#-11] + orr r3,r2,r3,lsl#24 + ldrb r2,[lr,#-10] + adds $h0,$h0,r3 @ accumulate input + + ldrb r3,[lr,#-9] + orr r1,r0,r1,lsl#8 + ldrb r0,[lr,#-8] + orr r2,r1,r2,lsl#16 + ldrb r1,[lr,#-7] + orr r3,r2,r3,lsl#24 + ldrb r2,[lr,#-6] + adcs $h1,$h1,r3 + + ldrb r3,[lr,#-5] + orr r1,r0,r1,lsl#8 + ldrb r0,[lr,#-4] + orr r2,r1,r2,lsl#16 + ldrb r1,[lr,#-3] + orr r3,r2,r3,lsl#24 + ldrb r2,[lr,#-2] + adcs $h2,$h2,r3 + + ldrb r3,[lr,#-1] + orr r1,r0,r1,lsl#8 + str lr,[sp,#8] @ offload input pointer + orr r2,r1,r2,lsl#16 + add $s1,$r1,$r1,lsr#2 + orr r3,r2,r3,lsl#24 +#else + ldr r0,[lr],#16 @ load input +# ifdef __thumb2__ + it hi +# endif + addhi $h4,$h4,#1 @ padbit + ldr r1,[lr,#-12] + ldr r2,[lr,#-8] + ldr r3,[lr,#-4] +# ifdef __ARMEB__ + rev r0,r0 + rev r1,r1 + rev r2,r2 + rev r3,r3 +# endif + adds $h0,$h0,r0 @ accumulate input + str lr,[sp,#8] @ offload input pointer + adcs $h1,$h1,r1 + add $s1,$r1,$r1,lsr#2 + adcs $h2,$h2,r2 +#endif + add $s2,$r2,$r2,lsr#2 + adcs $h3,$h3,r3 + add $s3,$r3,$r3,lsr#2 + + umull r2,r3,$h1,$r0 + adc $h4,$h4,#0 + umull r0,r1,$h0,$r0 + umlal r2,r3,$h4,$s1 + umlal r0,r1,$h3,$s1 + ldr $r1,[sp,#20] @ reload $r1 + umlal r2,r3,$h2,$s3 + umlal r0,r1,$h1,$s3 + umlal r2,r3,$h3,$s2 + umlal r0,r1,$h2,$s2 + umlal r2,r3,$h0,$r1 + str r0,[sp,#0] @ future $h0 + mul r0,$s2,$h4 + ldr $r2,[sp,#24] @ reload $r2 + adds r2,r2,r1 @ d1+=d0>>32 + eor r1,r1,r1 + adc lr,r3,#0 @ future $h2 + str r2,[sp,#4] @ future $h1 + + mul r2,$s3,$h4 + eor r3,r3,r3 + umlal r0,r1,$h3,$s3 + ldr $r3,[sp,#28] @ reload $r3 + umlal r2,r3,$h3,$r0 + umlal r0,r1,$h2,$r0 + umlal r2,r3,$h2,$r1 + umlal r0,r1,$h1,$r1 + umlal r2,r3,$h1,$r2 + umlal r0,r1,$h0,$r2 + umlal r2,r3,$h0,$r3 + ldr $h0,[sp,#0] + mul $h4,$r0,$h4 + ldr $h1,[sp,#4] + + adds $h2,lr,r0 @ d2+=d1>>32 + ldr lr,[sp,#8] @ reload input pointer + adc r1,r1,#0 + adds $h3,r2,r1 @ d3+=d2>>32 + ldr r0,[sp,#16] @ reload end pointer + adc r3,r3,#0 + add $h4,$h4,r3 @ h4+=d3>>32 + + and r1,$h4,#-4 + and $h4,$h4,#3 + add r1,r1,r1,lsr#2 @ *=5 + adds $h0,$h0,r1 + adcs $h1,$h1,#0 + adcs $h2,$h2,#0 + adcs $h3,$h3,#0 + adc $h4,$h4,#0 + + cmp r0,lr @ done yet? + bhi .Loop + + ldr $ctx,[sp,#12] + add sp,sp,#32 + stmia $ctx,{$h0-$h4} @ store the result + +.Lno_data: +#if __ARM_ARCH__>=5 + ldmia sp!,{r3-r11,pc} +#else + ldmia sp!,{r3-r11,lr} + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.size poly1305_blocks,.-poly1305_blocks +___ +} +{ +my ($ctx,$mac,$nonce)=map("r$_",(0..2)); +my ($h0,$h1,$h2,$h3,$h4,$g0,$g1,$g2,$g3)=map("r$_",(3..11)); +my $g4=$h4; + +$code.=<<___; +.type poly1305_emit,%function +.align 5 +poly1305_emit: + stmdb sp!,{r4-r11} +.Lpoly1305_emit_enter: + + ldmia $ctx,{$h0-$h4} + adds $g0,$h0,#5 @ compare to modulus + adcs $g1,$h1,#0 + adcs $g2,$h2,#0 + adcs $g3,$h3,#0 + adc $g4,$h4,#0 + tst $g4,#4 @ did it carry/borrow? + +#ifdef __thumb2__ + it ne +#endif + movne $h0,$g0 + ldr $g0,[$nonce,#0] +#ifdef __thumb2__ + it ne +#endif + movne $h1,$g1 + ldr $g1,[$nonce,#4] +#ifdef __thumb2__ + it ne +#endif + movne $h2,$g2 + ldr $g2,[$nonce,#8] +#ifdef __thumb2__ + it ne +#endif + movne $h3,$g3 + ldr $g3,[$nonce,#12] + + adds $h0,$h0,$g0 + adcs $h1,$h1,$g1 + adcs $h2,$h2,$g2 + adc $h3,$h3,$g3 + +#if __ARM_ARCH__>=7 +# ifdef __ARMEB__ + rev $h0,$h0 + rev $h1,$h1 + rev $h2,$h2 + rev $h3,$h3 +# endif + str $h0,[$mac,#0] + str $h1,[$mac,#4] + str $h2,[$mac,#8] + str $h3,[$mac,#12] +#else + strb $h0,[$mac,#0] + mov $h0,$h0,lsr#8 + strb $h1,[$mac,#4] + mov $h1,$h1,lsr#8 + strb $h2,[$mac,#8] + mov $h2,$h2,lsr#8 + strb $h3,[$mac,#12] + mov $h3,$h3,lsr#8 + + strb $h0,[$mac,#1] + mov $h0,$h0,lsr#8 + strb $h1,[$mac,#5] + mov $h1,$h1,lsr#8 + strb $h2,[$mac,#9] + mov $h2,$h2,lsr#8 + strb $h3,[$mac,#13] + mov $h3,$h3,lsr#8 + + strb $h0,[$mac,#2] + mov $h0,$h0,lsr#8 + strb $h1,[$mac,#6] + mov $h1,$h1,lsr#8 + strb $h2,[$mac,#10] + mov $h2,$h2,lsr#8 + strb $h3,[$mac,#14] + mov $h3,$h3,lsr#8 + + strb $h0,[$mac,#3] + strb $h1,[$mac,#7] + strb $h2,[$mac,#11] + strb $h3,[$mac,#15] +#endif + ldmia sp!,{r4-r11} +#if __ARM_ARCH__>=5 + ret @ bx lr +#else + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.size poly1305_emit,.-poly1305_emit +___ +{ +my ($R0,$R1,$S1,$R2,$S2,$R3,$S3,$R4,$S4) = map("d$_",(0..9)); +my ($D0,$D1,$D2,$D3,$D4, $H0,$H1,$H2,$H3,$H4) = map("q$_",(5..14)); +my ($T0,$T1,$MASK) = map("q$_",(15,4,0)); + +my ($in2,$zeros,$tbl0,$tbl1) = map("r$_",(4..7)); + +$code.=<<___; +#if __ARM_MAX_ARCH__>=7 +.fpu neon + +.type poly1305_init_neon,%function +.align 5 +poly1305_init_neon: + ldr r4,[$ctx,#20] @ load key base 2^32 + ldr r5,[$ctx,#24] + ldr r6,[$ctx,#28] + ldr r7,[$ctx,#32] + + and r2,r4,#0x03ffffff @ base 2^32 -> base 2^26 + mov r3,r4,lsr#26 + mov r4,r5,lsr#20 + orr r3,r3,r5,lsl#6 + mov r5,r6,lsr#14 + orr r4,r4,r6,lsl#12 + mov r6,r7,lsr#8 + orr r5,r5,r7,lsl#18 + and r3,r3,#0x03ffffff + and r4,r4,#0x03ffffff + and r5,r5,#0x03ffffff + + vdup.32 $R0,r2 @ r^1 in both lanes + add r2,r3,r3,lsl#2 @ *5 + vdup.32 $R1,r3 + add r3,r4,r4,lsl#2 + vdup.32 $S1,r2 + vdup.32 $R2,r4 + add r4,r5,r5,lsl#2 + vdup.32 $S2,r3 + vdup.32 $R3,r5 + add r5,r6,r6,lsl#2 + vdup.32 $S3,r4 + vdup.32 $R4,r6 + vdup.32 $S4,r5 + + mov $zeros,#2 @ counter + +.Lsquare_neon: + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + @ d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + @ d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + @ d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + @ d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + + vmull.u32 $D0,$R0,${R0}[1] + vmull.u32 $D1,$R1,${R0}[1] + vmull.u32 $D2,$R2,${R0}[1] + vmull.u32 $D3,$R3,${R0}[1] + vmull.u32 $D4,$R4,${R0}[1] + + vmlal.u32 $D0,$R4,${S1}[1] + vmlal.u32 $D1,$R0,${R1}[1] + vmlal.u32 $D2,$R1,${R1}[1] + vmlal.u32 $D3,$R2,${R1}[1] + vmlal.u32 $D4,$R3,${R1}[1] + + vmlal.u32 $D0,$R3,${S2}[1] + vmlal.u32 $D1,$R4,${S2}[1] + vmlal.u32 $D3,$R1,${R2}[1] + vmlal.u32 $D2,$R0,${R2}[1] + vmlal.u32 $D4,$R2,${R2}[1] + + vmlal.u32 $D0,$R2,${S3}[1] + vmlal.u32 $D3,$R0,${R3}[1] + vmlal.u32 $D1,$R3,${S3}[1] + vmlal.u32 $D2,$R4,${S3}[1] + vmlal.u32 $D4,$R1,${R3}[1] + + vmlal.u32 $D3,$R4,${S4}[1] + vmlal.u32 $D0,$R1,${S4}[1] + vmlal.u32 $D1,$R2,${S4}[1] + vmlal.u32 $D2,$R3,${S4}[1] + vmlal.u32 $D4,$R0,${R4}[1] + + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ lazy reduction as discussed in "NEON crypto" by D.J. Bernstein + @ and P. Schwabe + @ + @ H0>>+H1>>+H2>>+H3>>+H4 + @ H3>>+H4>>*5+H0>>+H1 + @ + @ Trivia. + @ + @ Result of multiplication of n-bit number by m-bit number is + @ n+m bits wide. However! Even though 2^n is a n+1-bit number, + @ m-bit number multiplied by 2^n is still n+m bits wide. + @ + @ Sum of two n-bit numbers is n+1 bits wide, sum of three - n+2, + @ and so is sum of four. Sum of 2^m n-m-bit numbers and n-bit + @ one is n+1 bits wide. + @ + @ >>+ denotes Hnext += Hn>>26, Hn &= 0x3ffffff. This means that + @ H0, H2, H3 are guaranteed to be 26 bits wide, while H1 and H4 + @ can be 27. However! In cases when their width exceeds 26 bits + @ they are limited by 2^26+2^6. This in turn means that *sum* + @ of the products with these values can still be viewed as sum + @ of 52-bit numbers as long as the amount of addends is not a + @ power of 2. For example, + @ + @ H4 = H4*R0 + H3*R1 + H2*R2 + H1*R3 + H0 * R4, + @ + @ which can't be larger than 5 * (2^26 + 2^6) * (2^26 + 2^6), or + @ 5 * (2^52 + 2*2^32 + 2^12), which in turn is smaller than + @ 8 * (2^52) or 2^55. However, the value is then multiplied by + @ by 5, so we should be looking at 5 * 5 * (2^52 + 2^33 + 2^12), + @ which is less than 32 * (2^52) or 2^57. And when processing + @ data we are looking at triple as many addends... + @ + @ In key setup procedure pre-reduced H0 is limited by 5*4+1 and + @ 5*H4 - by 5*5 52-bit addends, or 57 bits. But when hashing the + @ input H0 is limited by (5*4+1)*3 addends, or 58 bits, while + @ 5*H4 by 5*5*3, or 59[!] bits. How is this relevant? vmlal.u32 + @ instruction accepts 2x32-bit input and writes 2x64-bit result. + @ This means that result of reduction have to be compressed upon + @ loop wrap-around. This can be done in the process of reduction + @ to minimize amount of instructions [as well as amount of + @ 128-bit instructions, which benefits low-end processors], but + @ one has to watch for H2 (which is narrower than H0) and 5*H4 + @ not being wider than 58 bits, so that result of right shift + @ by 26 bits fits in 32 bits. This is also useful on x86, + @ because it allows to use paddd in place for paddq, which + @ benefits Atom, where paddq is ridiculously slow. + + vshr.u64 $T0,$D3,#26 + vmovn.i64 $D3#lo,$D3 + vshr.u64 $T1,$D0,#26 + vmovn.i64 $D0#lo,$D0 + vadd.i64 $D4,$D4,$T0 @ h3 -> h4 + vbic.i32 $D3#lo,#0xfc000000 @ &=0x03ffffff + vadd.i64 $D1,$D1,$T1 @ h0 -> h1 + vbic.i32 $D0#lo,#0xfc000000 + + vshrn.u64 $T0#lo,$D4,#26 + vmovn.i64 $D4#lo,$D4 + vshr.u64 $T1,$D1,#26 + vmovn.i64 $D1#lo,$D1 + vadd.i64 $D2,$D2,$T1 @ h1 -> h2 + vbic.i32 $D4#lo,#0xfc000000 + vbic.i32 $D1#lo,#0xfc000000 + + vadd.i32 $D0#lo,$D0#lo,$T0#lo + vshl.u32 $T0#lo,$T0#lo,#2 + vshrn.u64 $T1#lo,$D2,#26 + vmovn.i64 $D2#lo,$D2 + vadd.i32 $D0#lo,$D0#lo,$T0#lo @ h4 -> h0 + vadd.i32 $D3#lo,$D3#lo,$T1#lo @ h2 -> h3 + vbic.i32 $D2#lo,#0xfc000000 + + vshr.u32 $T0#lo,$D0#lo,#26 + vbic.i32 $D0#lo,#0xfc000000 + vshr.u32 $T1#lo,$D3#lo,#26 + vbic.i32 $D3#lo,#0xfc000000 + vadd.i32 $D1#lo,$D1#lo,$T0#lo @ h0 -> h1 + vadd.i32 $D4#lo,$D4#lo,$T1#lo @ h3 -> h4 + + subs $zeros,$zeros,#1 + beq .Lsquare_break_neon + + add $tbl0,$ctx,#(48+0*9*4) + add $tbl1,$ctx,#(48+1*9*4) + + vtrn.32 $R0,$D0#lo @ r^2:r^1 + vtrn.32 $R2,$D2#lo + vtrn.32 $R3,$D3#lo + vtrn.32 $R1,$D1#lo + vtrn.32 $R4,$D4#lo + + vshl.u32 $S2,$R2,#2 @ *5 + vshl.u32 $S3,$R3,#2 + vshl.u32 $S1,$R1,#2 + vshl.u32 $S4,$R4,#2 + vadd.i32 $S2,$S2,$R2 + vadd.i32 $S1,$S1,$R1 + vadd.i32 $S3,$S3,$R3 + vadd.i32 $S4,$S4,$R4 + + vst4.32 {${R0}[0],${R1}[0],${S1}[0],${R2}[0]},[$tbl0]! + vst4.32 {${R0}[1],${R1}[1],${S1}[1],${R2}[1]},[$tbl1]! + vst4.32 {${S2}[0],${R3}[0],${S3}[0],${R4}[0]},[$tbl0]! + vst4.32 {${S2}[1],${R3}[1],${S3}[1],${R4}[1]},[$tbl1]! + vst1.32 {${S4}[0]},[$tbl0,:32] + vst1.32 {${S4}[1]},[$tbl1,:32] + + b .Lsquare_neon + +.align 4 +.Lsquare_break_neon: + add $tbl0,$ctx,#(48+2*4*9) + add $tbl1,$ctx,#(48+3*4*9) + + vmov $R0,$D0#lo @ r^4:r^3 + vshl.u32 $S1,$D1#lo,#2 @ *5 + vmov $R1,$D1#lo + vshl.u32 $S2,$D2#lo,#2 + vmov $R2,$D2#lo + vshl.u32 $S3,$D3#lo,#2 + vmov $R3,$D3#lo + vshl.u32 $S4,$D4#lo,#2 + vmov $R4,$D4#lo + vadd.i32 $S1,$S1,$D1#lo + vadd.i32 $S2,$S2,$D2#lo + vadd.i32 $S3,$S3,$D3#lo + vadd.i32 $S4,$S4,$D4#lo + + vst4.32 {${R0}[0],${R1}[0],${S1}[0],${R2}[0]},[$tbl0]! + vst4.32 {${R0}[1],${R1}[1],${S1}[1],${R2}[1]},[$tbl1]! + vst4.32 {${S2}[0],${R3}[0],${S3}[0],${R4}[0]},[$tbl0]! + vst4.32 {${S2}[1],${R3}[1],${S3}[1],${R4}[1]},[$tbl1]! + vst1.32 {${S4}[0]},[$tbl0] + vst1.32 {${S4}[1]},[$tbl1] + + ret @ bx lr +.size poly1305_init_neon,.-poly1305_init_neon + +.type poly1305_blocks_neon,%function +.align 5 +poly1305_blocks_neon: + ldr ip,[$ctx,#36] @ is_base2_26 + ands $len,$len,#-16 + beq .Lno_data_neon + + cmp $len,#64 + bhs .Lenter_neon + tst ip,ip @ is_base2_26? + beq .Lpoly1305_blocks + +.Lenter_neon: + stmdb sp!,{r4-r7} + vstmdb sp!,{d8-d15} @ ABI specification says so + + tst ip,ip @ is_base2_26? + bne .Lbase2_26_neon + + stmdb sp!,{r1-r3,lr} + bl poly1305_init_neon + + ldr r4,[$ctx,#0] @ load hash value base 2^32 + ldr r5,[$ctx,#4] + ldr r6,[$ctx,#8] + ldr r7,[$ctx,#12] + ldr ip,[$ctx,#16] + + and r2,r4,#0x03ffffff @ base 2^32 -> base 2^26 + mov r3,r4,lsr#26 + veor $D0#lo,$D0#lo,$D0#lo + mov r4,r5,lsr#20 + orr r3,r3,r5,lsl#6 + veor $D1#lo,$D1#lo,$D1#lo + mov r5,r6,lsr#14 + orr r4,r4,r6,lsl#12 + veor $D2#lo,$D2#lo,$D2#lo + mov r6,r7,lsr#8 + orr r5,r5,r7,lsl#18 + veor $D3#lo,$D3#lo,$D3#lo + and r3,r3,#0x03ffffff + orr r6,r6,ip,lsl#24 + veor $D4#lo,$D4#lo,$D4#lo + and r4,r4,#0x03ffffff + mov r1,#1 + and r5,r5,#0x03ffffff + str r1,[$ctx,#36] @ is_base2_26 + + vmov.32 $D0#lo[0],r2 + vmov.32 $D1#lo[0],r3 + vmov.32 $D2#lo[0],r4 + vmov.32 $D3#lo[0],r5 + vmov.32 $D4#lo[0],r6 + adr $zeros,.Lzeros + + ldmia sp!,{r1-r3,lr} + b .Lbase2_32_neon + +.align 4 +.Lbase2_26_neon: + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ load hash value + + veor $D0#lo,$D0#lo,$D0#lo + veor $D1#lo,$D1#lo,$D1#lo + veor $D2#lo,$D2#lo,$D2#lo + veor $D3#lo,$D3#lo,$D3#lo + veor $D4#lo,$D4#lo,$D4#lo + vld4.32 {$D0#lo[0],$D1#lo[0],$D2#lo[0],$D3#lo[0]},[$ctx]! + adr $zeros,.Lzeros + vld1.32 {$D4#lo[0]},[$ctx] + sub $ctx,$ctx,#16 @ rewind + +.Lbase2_32_neon: + add $in2,$inp,#32 + mov $padbit,$padbit,lsl#24 + tst $len,#31 + beq .Leven + + vld4.32 {$H0#lo[0],$H1#lo[0],$H2#lo[0],$H3#lo[0]},[$inp]! + vmov.32 $H4#lo[0],$padbit + sub $len,$len,#16 + add $in2,$inp,#32 + +# ifdef __ARMEB__ + vrev32.8 $H0,$H0 + vrev32.8 $H3,$H3 + vrev32.8 $H1,$H1 + vrev32.8 $H2,$H2 +# endif + vsri.u32 $H4#lo,$H3#lo,#8 @ base 2^32 -> base 2^26 + vshl.u32 $H3#lo,$H3#lo,#18 + + vsri.u32 $H3#lo,$H2#lo,#14 + vshl.u32 $H2#lo,$H2#lo,#12 + vadd.i32 $H4#hi,$H4#lo,$D4#lo @ add hash value and move to #hi + + vbic.i32 $H3#lo,#0xfc000000 + vsri.u32 $H2#lo,$H1#lo,#20 + vshl.u32 $H1#lo,$H1#lo,#6 + + vbic.i32 $H2#lo,#0xfc000000 + vsri.u32 $H1#lo,$H0#lo,#26 + vadd.i32 $H3#hi,$H3#lo,$D3#lo + + vbic.i32 $H0#lo,#0xfc000000 + vbic.i32 $H1#lo,#0xfc000000 + vadd.i32 $H2#hi,$H2#lo,$D2#lo + + vadd.i32 $H0#hi,$H0#lo,$D0#lo + vadd.i32 $H1#hi,$H1#lo,$D1#lo + + mov $tbl1,$zeros + add $tbl0,$ctx,#48 + + cmp $len,$len + b .Long_tail + +.align 4 +.Leven: + subs $len,$len,#64 + it lo + movlo $in2,$zeros + + vmov.i32 $H4,#1<<24 @ padbit, yes, always + vld4.32 {$H0#lo,$H1#lo,$H2#lo,$H3#lo},[$inp] @ inp[0:1] + add $inp,$inp,#64 + vld4.32 {$H0#hi,$H1#hi,$H2#hi,$H3#hi},[$in2] @ inp[2:3] (or 0) + add $in2,$in2,#64 + itt hi + addhi $tbl1,$ctx,#(48+1*9*4) + addhi $tbl0,$ctx,#(48+3*9*4) + +# ifdef __ARMEB__ + vrev32.8 $H0,$H0 + vrev32.8 $H3,$H3 + vrev32.8 $H1,$H1 + vrev32.8 $H2,$H2 +# endif + vsri.u32 $H4,$H3,#8 @ base 2^32 -> base 2^26 + vshl.u32 $H3,$H3,#18 + + vsri.u32 $H3,$H2,#14 + vshl.u32 $H2,$H2,#12 + + vbic.i32 $H3,#0xfc000000 + vsri.u32 $H2,$H1,#20 + vshl.u32 $H1,$H1,#6 + + vbic.i32 $H2,#0xfc000000 + vsri.u32 $H1,$H0,#26 + + vbic.i32 $H0,#0xfc000000 + vbic.i32 $H1,#0xfc000000 + + bls .Lskip_loop + + vld4.32 {${R0}[1],${R1}[1],${S1}[1],${R2}[1]},[$tbl1]! @ load r^2 + vld4.32 {${R0}[0],${R1}[0],${S1}[0],${R2}[0]},[$tbl0]! @ load r^4 + vld4.32 {${S2}[1],${R3}[1],${S3}[1],${R4}[1]},[$tbl1]! + vld4.32 {${S2}[0],${R3}[0],${S3}[0],${R4}[0]},[$tbl0]! + b .Loop_neon + +.align 5 +.Loop_neon: + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2 + @ ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^3+inp[7]*r + @ \___________________/ + @ ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2+inp[8])*r^2 + @ ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^4+inp[7]*r^2+inp[9])*r + @ \___________________/ \____________________/ + @ + @ Note that we start with inp[2:3]*r^2. This is because it + @ doesn't depend on reduction in previous iteration. + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + @ d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + @ d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + @ d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + @ d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ inp[2:3]*r^2 + + vadd.i32 $H2#lo,$H2#lo,$D2#lo @ accumulate inp[0:1] + vmull.u32 $D2,$H2#hi,${R0}[1] + vadd.i32 $H0#lo,$H0#lo,$D0#lo + vmull.u32 $D0,$H0#hi,${R0}[1] + vadd.i32 $H3#lo,$H3#lo,$D3#lo + vmull.u32 $D3,$H3#hi,${R0}[1] + vmlal.u32 $D2,$H1#hi,${R1}[1] + vadd.i32 $H1#lo,$H1#lo,$D1#lo + vmull.u32 $D1,$H1#hi,${R0}[1] + + vadd.i32 $H4#lo,$H4#lo,$D4#lo + vmull.u32 $D4,$H4#hi,${R0}[1] + subs $len,$len,#64 + vmlal.u32 $D0,$H4#hi,${S1}[1] + it lo + movlo $in2,$zeros + vmlal.u32 $D3,$H2#hi,${R1}[1] + vld1.32 ${S4}[1],[$tbl1,:32] + vmlal.u32 $D1,$H0#hi,${R1}[1] + vmlal.u32 $D4,$H3#hi,${R1}[1] + + vmlal.u32 $D0,$H3#hi,${S2}[1] + vmlal.u32 $D3,$H1#hi,${R2}[1] + vmlal.u32 $D4,$H2#hi,${R2}[1] + vmlal.u32 $D1,$H4#hi,${S2}[1] + vmlal.u32 $D2,$H0#hi,${R2}[1] + + vmlal.u32 $D3,$H0#hi,${R3}[1] + vmlal.u32 $D0,$H2#hi,${S3}[1] + vmlal.u32 $D4,$H1#hi,${R3}[1] + vmlal.u32 $D1,$H3#hi,${S3}[1] + vmlal.u32 $D2,$H4#hi,${S3}[1] + + vmlal.u32 $D3,$H4#hi,${S4}[1] + vmlal.u32 $D0,$H1#hi,${S4}[1] + vmlal.u32 $D4,$H0#hi,${R4}[1] + vmlal.u32 $D1,$H2#hi,${S4}[1] + vmlal.u32 $D2,$H3#hi,${S4}[1] + + vld4.32 {$H0#hi,$H1#hi,$H2#hi,$H3#hi},[$in2] @ inp[2:3] (or 0) + add $in2,$in2,#64 + + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ (hash+inp[0:1])*r^4 and accumulate + + vmlal.u32 $D3,$H3#lo,${R0}[0] + vmlal.u32 $D0,$H0#lo,${R0}[0] + vmlal.u32 $D4,$H4#lo,${R0}[0] + vmlal.u32 $D1,$H1#lo,${R0}[0] + vmlal.u32 $D2,$H2#lo,${R0}[0] + vld1.32 ${S4}[0],[$tbl0,:32] + + vmlal.u32 $D3,$H2#lo,${R1}[0] + vmlal.u32 $D0,$H4#lo,${S1}[0] + vmlal.u32 $D4,$H3#lo,${R1}[0] + vmlal.u32 $D1,$H0#lo,${R1}[0] + vmlal.u32 $D2,$H1#lo,${R1}[0] + + vmlal.u32 $D3,$H1#lo,${R2}[0] + vmlal.u32 $D0,$H3#lo,${S2}[0] + vmlal.u32 $D4,$H2#lo,${R2}[0] + vmlal.u32 $D1,$H4#lo,${S2}[0] + vmlal.u32 $D2,$H0#lo,${R2}[0] + + vmlal.u32 $D3,$H0#lo,${R3}[0] + vmlal.u32 $D0,$H2#lo,${S3}[0] + vmlal.u32 $D4,$H1#lo,${R3}[0] + vmlal.u32 $D1,$H3#lo,${S3}[0] + vmlal.u32 $D3,$H4#lo,${S4}[0] + + vmlal.u32 $D2,$H4#lo,${S3}[0] + vmlal.u32 $D0,$H1#lo,${S4}[0] + vmlal.u32 $D4,$H0#lo,${R4}[0] + vmov.i32 $H4,#1<<24 @ padbit, yes, always + vmlal.u32 $D1,$H2#lo,${S4}[0] + vmlal.u32 $D2,$H3#lo,${S4}[0] + + vld4.32 {$H0#lo,$H1#lo,$H2#lo,$H3#lo},[$inp] @ inp[0:1] + add $inp,$inp,#64 +# ifdef __ARMEB__ + vrev32.8 $H0,$H0 + vrev32.8 $H1,$H1 + vrev32.8 $H2,$H2 + vrev32.8 $H3,$H3 +# endif + + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ lazy reduction interleaved with base 2^32 -> base 2^26 of + @ inp[0:3] previously loaded to $H0-$H3 and smashed to $H0-$H4. + + vshr.u64 $T0,$D3,#26 + vmovn.i64 $D3#lo,$D3 + vshr.u64 $T1,$D0,#26 + vmovn.i64 $D0#lo,$D0 + vadd.i64 $D4,$D4,$T0 @ h3 -> h4 + vbic.i32 $D3#lo,#0xfc000000 + vsri.u32 $H4,$H3,#8 @ base 2^32 -> base 2^26 + vadd.i64 $D1,$D1,$T1 @ h0 -> h1 + vshl.u32 $H3,$H3,#18 + vbic.i32 $D0#lo,#0xfc000000 + + vshrn.u64 $T0#lo,$D4,#26 + vmovn.i64 $D4#lo,$D4 + vshr.u64 $T1,$D1,#26 + vmovn.i64 $D1#lo,$D1 + vadd.i64 $D2,$D2,$T1 @ h1 -> h2 + vsri.u32 $H3,$H2,#14 + vbic.i32 $D4#lo,#0xfc000000 + vshl.u32 $H2,$H2,#12 + vbic.i32 $D1#lo,#0xfc000000 + + vadd.i32 $D0#lo,$D0#lo,$T0#lo + vshl.u32 $T0#lo,$T0#lo,#2 + vbic.i32 $H3,#0xfc000000 + vshrn.u64 $T1#lo,$D2,#26 + vmovn.i64 $D2#lo,$D2 + vaddl.u32 $D0,$D0#lo,$T0#lo @ h4 -> h0 [widen for a sec] + vsri.u32 $H2,$H1,#20 + vadd.i32 $D3#lo,$D3#lo,$T1#lo @ h2 -> h3 + vshl.u32 $H1,$H1,#6 + vbic.i32 $D2#lo,#0xfc000000 + vbic.i32 $H2,#0xfc000000 + + vshrn.u64 $T0#lo,$D0,#26 @ re-narrow + vmovn.i64 $D0#lo,$D0 + vsri.u32 $H1,$H0,#26 + vbic.i32 $H0,#0xfc000000 + vshr.u32 $T1#lo,$D3#lo,#26 + vbic.i32 $D3#lo,#0xfc000000 + vbic.i32 $D0#lo,#0xfc000000 + vadd.i32 $D1#lo,$D1#lo,$T0#lo @ h0 -> h1 + vadd.i32 $D4#lo,$D4#lo,$T1#lo @ h3 -> h4 + vbic.i32 $H1,#0xfc000000 + + bhi .Loop_neon + +.Lskip_loop: + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ multiply (inp[0:1]+hash) or inp[2:3] by r^2:r^1 + + add $tbl1,$ctx,#(48+0*9*4) + add $tbl0,$ctx,#(48+1*9*4) + adds $len,$len,#32 + it ne + movne $len,#0 + bne .Long_tail + + vadd.i32 $H2#hi,$H2#lo,$D2#lo @ add hash value and move to #hi + vadd.i32 $H0#hi,$H0#lo,$D0#lo + vadd.i32 $H3#hi,$H3#lo,$D3#lo + vadd.i32 $H1#hi,$H1#lo,$D1#lo + vadd.i32 $H4#hi,$H4#lo,$D4#lo + +.Long_tail: + vld4.32 {${R0}[1],${R1}[1],${S1}[1],${R2}[1]},[$tbl1]! @ load r^1 + vld4.32 {${R0}[0],${R1}[0],${S1}[0],${R2}[0]},[$tbl0]! @ load r^2 + + vadd.i32 $H2#lo,$H2#lo,$D2#lo @ can be redundant + vmull.u32 $D2,$H2#hi,$R0 + vadd.i32 $H0#lo,$H0#lo,$D0#lo + vmull.u32 $D0,$H0#hi,$R0 + vadd.i32 $H3#lo,$H3#lo,$D3#lo + vmull.u32 $D3,$H3#hi,$R0 + vadd.i32 $H1#lo,$H1#lo,$D1#lo + vmull.u32 $D1,$H1#hi,$R0 + vadd.i32 $H4#lo,$H4#lo,$D4#lo + vmull.u32 $D4,$H4#hi,$R0 + + vmlal.u32 $D0,$H4#hi,$S1 + vld4.32 {${S2}[1],${R3}[1],${S3}[1],${R4}[1]},[$tbl1]! + vmlal.u32 $D3,$H2#hi,$R1 + vld4.32 {${S2}[0],${R3}[0],${S3}[0],${R4}[0]},[$tbl0]! + vmlal.u32 $D1,$H0#hi,$R1 + vmlal.u32 $D4,$H3#hi,$R1 + vmlal.u32 $D2,$H1#hi,$R1 + + vmlal.u32 $D3,$H1#hi,$R2 + vld1.32 ${S4}[1],[$tbl1,:32] + vmlal.u32 $D0,$H3#hi,$S2 + vld1.32 ${S4}[0],[$tbl0,:32] + vmlal.u32 $D4,$H2#hi,$R2 + vmlal.u32 $D1,$H4#hi,$S2 + vmlal.u32 $D2,$H0#hi,$R2 + + vmlal.u32 $D3,$H0#hi,$R3 + it ne + addne $tbl1,$ctx,#(48+2*9*4) + vmlal.u32 $D0,$H2#hi,$S3 + it ne + addne $tbl0,$ctx,#(48+3*9*4) + vmlal.u32 $D4,$H1#hi,$R3 + vmlal.u32 $D1,$H3#hi,$S3 + vmlal.u32 $D2,$H4#hi,$S3 + + vmlal.u32 $D3,$H4#hi,$S4 + vorn $MASK,$MASK,$MASK @ all-ones, can be redundant + vmlal.u32 $D0,$H1#hi,$S4 + vshr.u64 $MASK,$MASK,#38 + vmlal.u32 $D4,$H0#hi,$R4 + vmlal.u32 $D1,$H2#hi,$S4 + vmlal.u32 $D2,$H3#hi,$S4 + + beq .Lshort_tail + + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ (hash+inp[0:1])*r^4:r^3 and accumulate + + vld4.32 {${R0}[1],${R1}[1],${S1}[1],${R2}[1]},[$tbl1]! @ load r^3 + vld4.32 {${R0}[0],${R1}[0],${S1}[0],${R2}[0]},[$tbl0]! @ load r^4 + + vmlal.u32 $D2,$H2#lo,$R0 + vmlal.u32 $D0,$H0#lo,$R0 + vmlal.u32 $D3,$H3#lo,$R0 + vmlal.u32 $D1,$H1#lo,$R0 + vmlal.u32 $D4,$H4#lo,$R0 + + vmlal.u32 $D0,$H4#lo,$S1 + vld4.32 {${S2}[1],${R3}[1],${S3}[1],${R4}[1]},[$tbl1]! + vmlal.u32 $D3,$H2#lo,$R1 + vld4.32 {${S2}[0],${R3}[0],${S3}[0],${R4}[0]},[$tbl0]! + vmlal.u32 $D1,$H0#lo,$R1 + vmlal.u32 $D4,$H3#lo,$R1 + vmlal.u32 $D2,$H1#lo,$R1 + + vmlal.u32 $D3,$H1#lo,$R2 + vld1.32 ${S4}[1],[$tbl1,:32] + vmlal.u32 $D0,$H3#lo,$S2 + vld1.32 ${S4}[0],[$tbl0,:32] + vmlal.u32 $D4,$H2#lo,$R2 + vmlal.u32 $D1,$H4#lo,$S2 + vmlal.u32 $D2,$H0#lo,$R2 + + vmlal.u32 $D3,$H0#lo,$R3 + vmlal.u32 $D0,$H2#lo,$S3 + vmlal.u32 $D4,$H1#lo,$R3 + vmlal.u32 $D1,$H3#lo,$S3 + vmlal.u32 $D2,$H4#lo,$S3 + + vmlal.u32 $D3,$H4#lo,$S4 + vorn $MASK,$MASK,$MASK @ all-ones + vmlal.u32 $D0,$H1#lo,$S4 + vshr.u64 $MASK,$MASK,#38 + vmlal.u32 $D4,$H0#lo,$R4 + vmlal.u32 $D1,$H2#lo,$S4 + vmlal.u32 $D2,$H3#lo,$S4 + +.Lshort_tail: + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ horizontal addition + + vadd.i64 $D3#lo,$D3#lo,$D3#hi + vadd.i64 $D0#lo,$D0#lo,$D0#hi + vadd.i64 $D4#lo,$D4#lo,$D4#hi + vadd.i64 $D1#lo,$D1#lo,$D1#hi + vadd.i64 $D2#lo,$D2#lo,$D2#hi + + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ lazy reduction, but without narrowing + + vshr.u64 $T0,$D3,#26 + vand.i64 $D3,$D3,$MASK + vshr.u64 $T1,$D0,#26 + vand.i64 $D0,$D0,$MASK + vadd.i64 $D4,$D4,$T0 @ h3 -> h4 + vadd.i64 $D1,$D1,$T1 @ h0 -> h1 + + vshr.u64 $T0,$D4,#26 + vand.i64 $D4,$D4,$MASK + vshr.u64 $T1,$D1,#26 + vand.i64 $D1,$D1,$MASK + vadd.i64 $D2,$D2,$T1 @ h1 -> h2 + + vadd.i64 $D0,$D0,$T0 + vshl.u64 $T0,$T0,#2 + vshr.u64 $T1,$D2,#26 + vand.i64 $D2,$D2,$MASK + vadd.i64 $D0,$D0,$T0 @ h4 -> h0 + vadd.i64 $D3,$D3,$T1 @ h2 -> h3 + + vshr.u64 $T0,$D0,#26 + vand.i64 $D0,$D0,$MASK + vshr.u64 $T1,$D3,#26 + vand.i64 $D3,$D3,$MASK + vadd.i64 $D1,$D1,$T0 @ h0 -> h1 + vadd.i64 $D4,$D4,$T1 @ h3 -> h4 + + cmp $len,#0 + bne .Leven + + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ store hash value + + vst4.32 {$D0#lo[0],$D1#lo[0],$D2#lo[0],$D3#lo[0]},[$ctx]! + vst1.32 {$D4#lo[0]},[$ctx] + + vldmia sp!,{d8-d15} @ epilogue + ldmia sp!,{r4-r7} +.Lno_data_neon: + ret @ bx lr +.size poly1305_blocks_neon,.-poly1305_blocks_neon + +.type poly1305_emit_neon,%function +.align 5 +poly1305_emit_neon: + ldr ip,[$ctx,#36] @ is_base2_26 + + stmdb sp!,{r4-r11} + + tst ip,ip + beq .Lpoly1305_emit_enter + + ldmia $ctx,{$h0-$h4} + eor $g0,$g0,$g0 + + adds $h0,$h0,$h1,lsl#26 @ base 2^26 -> base 2^32 + mov $h1,$h1,lsr#6 + adcs $h1,$h1,$h2,lsl#20 + mov $h2,$h2,lsr#12 + adcs $h2,$h2,$h3,lsl#14 + mov $h3,$h3,lsr#18 + adcs $h3,$h3,$h4,lsl#8 + adc $h4,$g0,$h4,lsr#24 @ can be partially reduced ... + + and $g0,$h4,#-4 @ ... so reduce + and $h4,$h3,#3 + add $g0,$g0,$g0,lsr#2 @ *= 5 + adds $h0,$h0,$g0 + adcs $h1,$h1,#0 + adcs $h2,$h2,#0 + adcs $h3,$h3,#0 + adc $h4,$h4,#0 + + adds $g0,$h0,#5 @ compare to modulus + adcs $g1,$h1,#0 + adcs $g2,$h2,#0 + adcs $g3,$h3,#0 + adc $g4,$h4,#0 + tst $g4,#4 @ did it carry/borrow? + + it ne + movne $h0,$g0 + ldr $g0,[$nonce,#0] + it ne + movne $h1,$g1 + ldr $g1,[$nonce,#4] + it ne + movne $h2,$g2 + ldr $g2,[$nonce,#8] + it ne + movne $h3,$g3 + ldr $g3,[$nonce,#12] + + adds $h0,$h0,$g0 @ accumulate nonce + adcs $h1,$h1,$g1 + adcs $h2,$h2,$g2 + adc $h3,$h3,$g3 + +# ifdef __ARMEB__ + rev $h0,$h0 + rev $h1,$h1 + rev $h2,$h2 + rev $h3,$h3 +# endif + str $h0,[$mac,#0] @ store the result + str $h1,[$mac,#4] + str $h2,[$mac,#8] + str $h3,[$mac,#12] + + ldmia sp!,{r4-r11} + ret @ bx lr +.size poly1305_emit_neon,.-poly1305_emit_neon + +.align 5 +.Lzeros: +.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +.LOPENSSL_armcap: +.word OPENSSL_armcap_P-.Lpoly1305_init +#endif +___ +} } +$code.=<<___; +.asciz "Poly1305 for ARMv4/NEON, CRYPTOGAMS by " +.align 2 +#if __ARM_MAX_ARCH__>=7 +.comm OPENSSL_armcap_P,4,4 +#endif +___ + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/geo; + + s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo or + s/\bret\b/bx lr/go or + s/\bbx\s+lr\b/.word\t0xe12fff1e/go; # make it possible to compile with -march=armv4 + + print $_,"\n"; +} +close STDOUT; # enforce flush diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-armv8.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-armv8.pl new file mode 100755 index 000000000..6c6c9bb05 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-armv8.pl @@ -0,0 +1,946 @@ +#! /usr/bin/env perl +# Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# This module implements Poly1305 hash for ARMv8. +# +# June 2015 +# +# Numbers are cycles per processed byte with poly1305_blocks alone. +# +# IALU/gcc-4.9 NEON +# +# Apple A7 1.86/+5% 0.72 +# Cortex-A53 2.69/+58% 1.47 +# Cortex-A57 2.70/+7% 1.14 +# Denver 1.64/+50% 1.18(*) +# X-Gene 2.13/+68% 2.27 +# Mongoose 1.77/+75% 1.12 +# Kryo 2.70/+55% 1.13 +# +# (*) estimate based on resources availability is less than 1.0, +# i.e. measured result is worse than expected, presumably binary +# translator is not almighty; + +$flavour=shift; +$output=shift; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or +die "can't locate arm-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +my ($ctx,$inp,$len,$padbit) = map("x$_",(0..3)); +my ($mac,$nonce)=($inp,$len); + +my ($h0,$h1,$h2,$r0,$r1,$s1,$t0,$t1,$d0,$d1,$d2) = map("x$_",(4..14)); + +$code.=<<___; +#include "arm_arch.h" + +.text + +// forward "declarations" are required for Apple +.extern OPENSSL_armcap_P +.globl poly1305_blocks +.globl poly1305_emit + +.globl poly1305_init +.type poly1305_init,%function +.align 5 +poly1305_init: + cmp $inp,xzr + stp xzr,xzr,[$ctx] // zero hash value + stp xzr,xzr,[$ctx,#16] // [along with is_base2_26] + + csel x0,xzr,x0,eq + b.eq .Lno_key + +#ifdef __ILP32__ + ldrsw $t1,.LOPENSSL_armcap_P +#else + ldr $t1,.LOPENSSL_armcap_P +#endif + adr $t0,.LOPENSSL_armcap_P + + ldp $r0,$r1,[$inp] // load key + mov $s1,#0xfffffffc0fffffff + movk $s1,#0x0fff,lsl#48 + ldr w17,[$t0,$t1] +#ifdef __ARMEB__ + rev $r0,$r0 // flip bytes + rev $r1,$r1 +#endif + and $r0,$r0,$s1 // &=0ffffffc0fffffff + and $s1,$s1,#-4 + and $r1,$r1,$s1 // &=0ffffffc0ffffffc + stp $r0,$r1,[$ctx,#32] // save key value + + tst w17,#ARMV7_NEON + + adr $d0,poly1305_blocks + adr $r0,poly1305_blocks_neon + adr $d1,poly1305_emit + adr $r1,poly1305_emit_neon + + csel $d0,$d0,$r0,eq + csel $d1,$d1,$r1,eq + +#ifdef __ILP32__ + stp w12,w13,[$len] +#else + stp $d0,$d1,[$len] +#endif + + mov x0,#1 +.Lno_key: + ret +.size poly1305_init,.-poly1305_init + +.type poly1305_blocks,%function +.align 5 +poly1305_blocks: + ands $len,$len,#-16 + b.eq .Lno_data + + ldp $h0,$h1,[$ctx] // load hash value + ldp $r0,$r1,[$ctx,#32] // load key value + ldr $h2,[$ctx,#16] + add $s1,$r1,$r1,lsr#2 // s1 = r1 + (r1 >> 2) + b .Loop + +.align 5 +.Loop: + ldp $t0,$t1,[$inp],#16 // load input + sub $len,$len,#16 +#ifdef __ARMEB__ + rev $t0,$t0 + rev $t1,$t1 +#endif + adds $h0,$h0,$t0 // accumulate input + adcs $h1,$h1,$t1 + + mul $d0,$h0,$r0 // h0*r0 + adc $h2,$h2,$padbit + umulh $d1,$h0,$r0 + + mul $t0,$h1,$s1 // h1*5*r1 + umulh $t1,$h1,$s1 + + adds $d0,$d0,$t0 + mul $t0,$h0,$r1 // h0*r1 + adc $d1,$d1,$t1 + umulh $d2,$h0,$r1 + + adds $d1,$d1,$t0 + mul $t0,$h1,$r0 // h1*r0 + adc $d2,$d2,xzr + umulh $t1,$h1,$r0 + + adds $d1,$d1,$t0 + mul $t0,$h2,$s1 // h2*5*r1 + adc $d2,$d2,$t1 + mul $t1,$h2,$r0 // h2*r0 + + adds $d1,$d1,$t0 + adc $d2,$d2,$t1 + + and $t0,$d2,#-4 // final reduction + and $h2,$d2,#3 + add $t0,$t0,$d2,lsr#2 + adds $h0,$d0,$t0 + adcs $h1,$d1,xzr + adc $h2,$h2,xzr + + cbnz $len,.Loop + + stp $h0,$h1,[$ctx] // store hash value + str $h2,[$ctx,#16] + +.Lno_data: + ret +.size poly1305_blocks,.-poly1305_blocks + +.type poly1305_emit,%function +.align 5 +poly1305_emit: + ldp $h0,$h1,[$ctx] // load hash base 2^64 + ldr $h2,[$ctx,#16] + ldp $t0,$t1,[$nonce] // load nonce + + adds $d0,$h0,#5 // compare to modulus + adcs $d1,$h1,xzr + adc $d2,$h2,xzr + + tst $d2,#-4 // see if it's carried/borrowed + + csel $h0,$h0,$d0,eq + csel $h1,$h1,$d1,eq + +#ifdef __ARMEB__ + ror $t0,$t0,#32 // flip nonce words + ror $t1,$t1,#32 +#endif + adds $h0,$h0,$t0 // accumulate nonce + adc $h1,$h1,$t1 +#ifdef __ARMEB__ + rev $h0,$h0 // flip output bytes + rev $h1,$h1 +#endif + stp $h0,$h1,[$mac] // write result + + ret +.size poly1305_emit,.-poly1305_emit +___ +my ($R0,$R1,$S1,$R2,$S2,$R3,$S3,$R4,$S4) = map("v$_.4s",(0..8)); +my ($IN01_0,$IN01_1,$IN01_2,$IN01_3,$IN01_4) = map("v$_.2s",(9..13)); +my ($IN23_0,$IN23_1,$IN23_2,$IN23_3,$IN23_4) = map("v$_.2s",(14..18)); +my ($ACC0,$ACC1,$ACC2,$ACC3,$ACC4) = map("v$_.2d",(19..23)); +my ($H0,$H1,$H2,$H3,$H4) = map("v$_.2s",(24..28)); +my ($T0,$T1,$MASK) = map("v$_",(29..31)); + +my ($in2,$zeros)=("x16","x17"); +my $is_base2_26 = $zeros; # borrow + +$code.=<<___; +.type poly1305_mult,%function +.align 5 +poly1305_mult: + mul $d0,$h0,$r0 // h0*r0 + umulh $d1,$h0,$r0 + + mul $t0,$h1,$s1 // h1*5*r1 + umulh $t1,$h1,$s1 + + adds $d0,$d0,$t0 + mul $t0,$h0,$r1 // h0*r1 + adc $d1,$d1,$t1 + umulh $d2,$h0,$r1 + + adds $d1,$d1,$t0 + mul $t0,$h1,$r0 // h1*r0 + adc $d2,$d2,xzr + umulh $t1,$h1,$r0 + + adds $d1,$d1,$t0 + mul $t0,$h2,$s1 // h2*5*r1 + adc $d2,$d2,$t1 + mul $t1,$h2,$r0 // h2*r0 + + adds $d1,$d1,$t0 + adc $d2,$d2,$t1 + + and $t0,$d2,#-4 // final reduction + and $h2,$d2,#3 + add $t0,$t0,$d2,lsr#2 + adds $h0,$d0,$t0 + adcs $h1,$d1,xzr + adc $h2,$h2,xzr + + ret +.size poly1305_mult,.-poly1305_mult + +.type poly1305_splat,%function +.align 5 +poly1305_splat: + and x12,$h0,#0x03ffffff // base 2^64 -> base 2^26 + ubfx x13,$h0,#26,#26 + extr x14,$h1,$h0,#52 + and x14,x14,#0x03ffffff + ubfx x15,$h1,#14,#26 + extr x16,$h2,$h1,#40 + + str w12,[$ctx,#16*0] // r0 + add w12,w13,w13,lsl#2 // r1*5 + str w13,[$ctx,#16*1] // r1 + add w13,w14,w14,lsl#2 // r2*5 + str w12,[$ctx,#16*2] // s1 + str w14,[$ctx,#16*3] // r2 + add w14,w15,w15,lsl#2 // r3*5 + str w13,[$ctx,#16*4] // s2 + str w15,[$ctx,#16*5] // r3 + add w15,w16,w16,lsl#2 // r4*5 + str w14,[$ctx,#16*6] // s3 + str w16,[$ctx,#16*7] // r4 + str w15,[$ctx,#16*8] // s4 + + ret +.size poly1305_splat,.-poly1305_splat + +.type poly1305_blocks_neon,%function +.align 5 +poly1305_blocks_neon: + ldr $is_base2_26,[$ctx,#24] + cmp $len,#128 + b.hs .Lblocks_neon + cbz $is_base2_26,poly1305_blocks + +.Lblocks_neon: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-80]! + add x29,sp,#0 + + ands $len,$len,#-16 + b.eq .Lno_data_neon + + cbz $is_base2_26,.Lbase2_64_neon + + ldp w10,w11,[$ctx] // load hash value base 2^26 + ldp w12,w13,[$ctx,#8] + ldr w14,[$ctx,#16] + + tst $len,#31 + b.eq .Leven_neon + + ldp $r0,$r1,[$ctx,#32] // load key value + + add $h0,x10,x11,lsl#26 // base 2^26 -> base 2^64 + lsr $h1,x12,#12 + adds $h0,$h0,x12,lsl#52 + add $h1,$h1,x13,lsl#14 + adc $h1,$h1,xzr + lsr $h2,x14,#24 + adds $h1,$h1,x14,lsl#40 + adc $d2,$h2,xzr // can be partially reduced... + + ldp $d0,$d1,[$inp],#16 // load input + sub $len,$len,#16 + add $s1,$r1,$r1,lsr#2 // s1 = r1 + (r1 >> 2) + + and $t0,$d2,#-4 // ... so reduce + and $h2,$d2,#3 + add $t0,$t0,$d2,lsr#2 + adds $h0,$h0,$t0 + adcs $h1,$h1,xzr + adc $h2,$h2,xzr + +#ifdef __ARMEB__ + rev $d0,$d0 + rev $d1,$d1 +#endif + adds $h0,$h0,$d0 // accumulate input + adcs $h1,$h1,$d1 + adc $h2,$h2,$padbit + + bl poly1305_mult + ldr x30,[sp,#8] + + cbz $padbit,.Lstore_base2_64_neon + + and x10,$h0,#0x03ffffff // base 2^64 -> base 2^26 + ubfx x11,$h0,#26,#26 + extr x12,$h1,$h0,#52 + and x12,x12,#0x03ffffff + ubfx x13,$h1,#14,#26 + extr x14,$h2,$h1,#40 + + cbnz $len,.Leven_neon + + stp w10,w11,[$ctx] // store hash value base 2^26 + stp w12,w13,[$ctx,#8] + str w14,[$ctx,#16] + b .Lno_data_neon + +.align 4 +.Lstore_base2_64_neon: + stp $h0,$h1,[$ctx] // store hash value base 2^64 + stp $h2,xzr,[$ctx,#16] // note that is_base2_26 is zeroed + b .Lno_data_neon + +.align 4 +.Lbase2_64_neon: + ldp $r0,$r1,[$ctx,#32] // load key value + + ldp $h0,$h1,[$ctx] // load hash value base 2^64 + ldr $h2,[$ctx,#16] + + tst $len,#31 + b.eq .Linit_neon + + ldp $d0,$d1,[$inp],#16 // load input + sub $len,$len,#16 + add $s1,$r1,$r1,lsr#2 // s1 = r1 + (r1 >> 2) +#ifdef __ARMEB__ + rev $d0,$d0 + rev $d1,$d1 +#endif + adds $h0,$h0,$d0 // accumulate input + adcs $h1,$h1,$d1 + adc $h2,$h2,$padbit + + bl poly1305_mult + +.Linit_neon: + and x10,$h0,#0x03ffffff // base 2^64 -> base 2^26 + ubfx x11,$h0,#26,#26 + extr x12,$h1,$h0,#52 + and x12,x12,#0x03ffffff + ubfx x13,$h1,#14,#26 + extr x14,$h2,$h1,#40 + + stp d8,d9,[sp,#16] // meet ABI requirements + stp d10,d11,[sp,#32] + stp d12,d13,[sp,#48] + stp d14,d15,[sp,#64] + + fmov ${H0},x10 + fmov ${H1},x11 + fmov ${H2},x12 + fmov ${H3},x13 + fmov ${H4},x14 + + ////////////////////////////////// initialize r^n table + mov $h0,$r0 // r^1 + add $s1,$r1,$r1,lsr#2 // s1 = r1 + (r1 >> 2) + mov $h1,$r1 + mov $h2,xzr + add $ctx,$ctx,#48+12 + bl poly1305_splat + + bl poly1305_mult // r^2 + sub $ctx,$ctx,#4 + bl poly1305_splat + + bl poly1305_mult // r^3 + sub $ctx,$ctx,#4 + bl poly1305_splat + + bl poly1305_mult // r^4 + sub $ctx,$ctx,#4 + bl poly1305_splat + ldr x30,[sp,#8] + + add $in2,$inp,#32 + adr $zeros,.Lzeros + subs $len,$len,#64 + csel $in2,$zeros,$in2,lo + + mov x4,#1 + str x4,[$ctx,#-24] // set is_base2_26 + sub $ctx,$ctx,#48 // restore original $ctx + b .Ldo_neon + +.align 4 +.Leven_neon: + add $in2,$inp,#32 + adr $zeros,.Lzeros + subs $len,$len,#64 + csel $in2,$zeros,$in2,lo + + stp d8,d9,[sp,#16] // meet ABI requirements + stp d10,d11,[sp,#32] + stp d12,d13,[sp,#48] + stp d14,d15,[sp,#64] + + fmov ${H0},x10 + fmov ${H1},x11 + fmov ${H2},x12 + fmov ${H3},x13 + fmov ${H4},x14 + +.Ldo_neon: + ldp x8,x12,[$in2],#16 // inp[2:3] (or zero) + ldp x9,x13,[$in2],#48 + + lsl $padbit,$padbit,#24 + add x15,$ctx,#48 + +#ifdef __ARMEB__ + rev x8,x8 + rev x12,x12 + rev x9,x9 + rev x13,x13 +#endif + and x4,x8,#0x03ffffff // base 2^64 -> base 2^26 + and x5,x9,#0x03ffffff + ubfx x6,x8,#26,#26 + ubfx x7,x9,#26,#26 + add x4,x4,x5,lsl#32 // bfi x4,x5,#32,#32 + extr x8,x12,x8,#52 + extr x9,x13,x9,#52 + add x6,x6,x7,lsl#32 // bfi x6,x7,#32,#32 + fmov $IN23_0,x4 + and x8,x8,#0x03ffffff + and x9,x9,#0x03ffffff + ubfx x10,x12,#14,#26 + ubfx x11,x13,#14,#26 + add x12,$padbit,x12,lsr#40 + add x13,$padbit,x13,lsr#40 + add x8,x8,x9,lsl#32 // bfi x8,x9,#32,#32 + fmov $IN23_1,x6 + add x10,x10,x11,lsl#32 // bfi x10,x11,#32,#32 + add x12,x12,x13,lsl#32 // bfi x12,x13,#32,#32 + fmov $IN23_2,x8 + fmov $IN23_3,x10 + fmov $IN23_4,x12 + + ldp x8,x12,[$inp],#16 // inp[0:1] + ldp x9,x13,[$inp],#48 + + ld1 {$R0,$R1,$S1,$R2},[x15],#64 + ld1 {$S2,$R3,$S3,$R4},[x15],#64 + ld1 {$S4},[x15] + +#ifdef __ARMEB__ + rev x8,x8 + rev x12,x12 + rev x9,x9 + rev x13,x13 +#endif + and x4,x8,#0x03ffffff // base 2^64 -> base 2^26 + and x5,x9,#0x03ffffff + ubfx x6,x8,#26,#26 + ubfx x7,x9,#26,#26 + add x4,x4,x5,lsl#32 // bfi x4,x5,#32,#32 + extr x8,x12,x8,#52 + extr x9,x13,x9,#52 + add x6,x6,x7,lsl#32 // bfi x6,x7,#32,#32 + fmov $IN01_0,x4 + and x8,x8,#0x03ffffff + and x9,x9,#0x03ffffff + ubfx x10,x12,#14,#26 + ubfx x11,x13,#14,#26 + add x12,$padbit,x12,lsr#40 + add x13,$padbit,x13,lsr#40 + add x8,x8,x9,lsl#32 // bfi x8,x9,#32,#32 + fmov $IN01_1,x6 + add x10,x10,x11,lsl#32 // bfi x10,x11,#32,#32 + add x12,x12,x13,lsl#32 // bfi x12,x13,#32,#32 + movi $MASK.2d,#-1 + fmov $IN01_2,x8 + fmov $IN01_3,x10 + fmov $IN01_4,x12 + ushr $MASK.2d,$MASK.2d,#38 + + b.ls .Lskip_loop + +.align 4 +.Loop_neon: + //////////////////////////////////////////////////////////////// + // ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2 + // ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^3+inp[7]*r + // \___________________/ + // ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2+inp[8])*r^2 + // ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^4+inp[7]*r^2+inp[9])*r + // \___________________/ \____________________/ + // + // Note that we start with inp[2:3]*r^2. This is because it + // doesn't depend on reduction in previous iteration. + //////////////////////////////////////////////////////////////// + // d4 = h0*r4 + h1*r3 + h2*r2 + h3*r1 + h4*r0 + // d3 = h0*r3 + h1*r2 + h2*r1 + h3*r0 + h4*5*r4 + // d2 = h0*r2 + h1*r1 + h2*r0 + h3*5*r4 + h4*5*r3 + // d1 = h0*r1 + h1*r0 + h2*5*r4 + h3*5*r3 + h4*5*r2 + // d0 = h0*r0 + h1*5*r4 + h2*5*r3 + h3*5*r2 + h4*5*r1 + + subs $len,$len,#64 + umull $ACC4,$IN23_0,${R4}[2] + csel $in2,$zeros,$in2,lo + umull $ACC3,$IN23_0,${R3}[2] + umull $ACC2,$IN23_0,${R2}[2] + ldp x8,x12,[$in2],#16 // inp[2:3] (or zero) + umull $ACC1,$IN23_0,${R1}[2] + ldp x9,x13,[$in2],#48 + umull $ACC0,$IN23_0,${R0}[2] +#ifdef __ARMEB__ + rev x8,x8 + rev x12,x12 + rev x9,x9 + rev x13,x13 +#endif + + umlal $ACC4,$IN23_1,${R3}[2] + and x4,x8,#0x03ffffff // base 2^64 -> base 2^26 + umlal $ACC3,$IN23_1,${R2}[2] + and x5,x9,#0x03ffffff + umlal $ACC2,$IN23_1,${R1}[2] + ubfx x6,x8,#26,#26 + umlal $ACC1,$IN23_1,${R0}[2] + ubfx x7,x9,#26,#26 + umlal $ACC0,$IN23_1,${S4}[2] + add x4,x4,x5,lsl#32 // bfi x4,x5,#32,#32 + + umlal $ACC4,$IN23_2,${R2}[2] + extr x8,x12,x8,#52 + umlal $ACC3,$IN23_2,${R1}[2] + extr x9,x13,x9,#52 + umlal $ACC2,$IN23_2,${R0}[2] + add x6,x6,x7,lsl#32 // bfi x6,x7,#32,#32 + umlal $ACC1,$IN23_2,${S4}[2] + fmov $IN23_0,x4 + umlal $ACC0,$IN23_2,${S3}[2] + and x8,x8,#0x03ffffff + + umlal $ACC4,$IN23_3,${R1}[2] + and x9,x9,#0x03ffffff + umlal $ACC3,$IN23_3,${R0}[2] + ubfx x10,x12,#14,#26 + umlal $ACC2,$IN23_3,${S4}[2] + ubfx x11,x13,#14,#26 + umlal $ACC1,$IN23_3,${S3}[2] + add x8,x8,x9,lsl#32 // bfi x8,x9,#32,#32 + umlal $ACC0,$IN23_3,${S2}[2] + fmov $IN23_1,x6 + + add $IN01_2,$IN01_2,$H2 + add x12,$padbit,x12,lsr#40 + umlal $ACC4,$IN23_4,${R0}[2] + add x13,$padbit,x13,lsr#40 + umlal $ACC3,$IN23_4,${S4}[2] + add x10,x10,x11,lsl#32 // bfi x10,x11,#32,#32 + umlal $ACC2,$IN23_4,${S3}[2] + add x12,x12,x13,lsl#32 // bfi x12,x13,#32,#32 + umlal $ACC1,$IN23_4,${S2}[2] + fmov $IN23_2,x8 + umlal $ACC0,$IN23_4,${S1}[2] + fmov $IN23_3,x10 + + //////////////////////////////////////////////////////////////// + // (hash+inp[0:1])*r^4 and accumulate + + add $IN01_0,$IN01_0,$H0 + fmov $IN23_4,x12 + umlal $ACC3,$IN01_2,${R1}[0] + ldp x8,x12,[$inp],#16 // inp[0:1] + umlal $ACC0,$IN01_2,${S3}[0] + ldp x9,x13,[$inp],#48 + umlal $ACC4,$IN01_2,${R2}[0] + umlal $ACC1,$IN01_2,${S4}[0] + umlal $ACC2,$IN01_2,${R0}[0] +#ifdef __ARMEB__ + rev x8,x8 + rev x12,x12 + rev x9,x9 + rev x13,x13 +#endif + + add $IN01_1,$IN01_1,$H1 + umlal $ACC3,$IN01_0,${R3}[0] + umlal $ACC4,$IN01_0,${R4}[0] + and x4,x8,#0x03ffffff // base 2^64 -> base 2^26 + umlal $ACC2,$IN01_0,${R2}[0] + and x5,x9,#0x03ffffff + umlal $ACC0,$IN01_0,${R0}[0] + ubfx x6,x8,#26,#26 + umlal $ACC1,$IN01_0,${R1}[0] + ubfx x7,x9,#26,#26 + + add $IN01_3,$IN01_3,$H3 + add x4,x4,x5,lsl#32 // bfi x4,x5,#32,#32 + umlal $ACC3,$IN01_1,${R2}[0] + extr x8,x12,x8,#52 + umlal $ACC4,$IN01_1,${R3}[0] + extr x9,x13,x9,#52 + umlal $ACC0,$IN01_1,${S4}[0] + add x6,x6,x7,lsl#32 // bfi x6,x7,#32,#32 + umlal $ACC2,$IN01_1,${R1}[0] + fmov $IN01_0,x4 + umlal $ACC1,$IN01_1,${R0}[0] + and x8,x8,#0x03ffffff + + add $IN01_4,$IN01_4,$H4 + and x9,x9,#0x03ffffff + umlal $ACC3,$IN01_3,${R0}[0] + ubfx x10,x12,#14,#26 + umlal $ACC0,$IN01_3,${S2}[0] + ubfx x11,x13,#14,#26 + umlal $ACC4,$IN01_3,${R1}[0] + add x8,x8,x9,lsl#32 // bfi x8,x9,#32,#32 + umlal $ACC1,$IN01_3,${S3}[0] + fmov $IN01_1,x6 + umlal $ACC2,$IN01_3,${S4}[0] + add x12,$padbit,x12,lsr#40 + + umlal $ACC3,$IN01_4,${S4}[0] + add x13,$padbit,x13,lsr#40 + umlal $ACC0,$IN01_4,${S1}[0] + add x10,x10,x11,lsl#32 // bfi x10,x11,#32,#32 + umlal $ACC4,$IN01_4,${R0}[0] + add x12,x12,x13,lsl#32 // bfi x12,x13,#32,#32 + umlal $ACC1,$IN01_4,${S2}[0] + fmov $IN01_2,x8 + umlal $ACC2,$IN01_4,${S3}[0] + fmov $IN01_3,x10 + fmov $IN01_4,x12 + + ///////////////////////////////////////////////////////////////// + // lazy reduction as discussed in "NEON crypto" by D.J. Bernstein + // and P. Schwabe + // + // [see discussion in poly1305-armv4 module] + + ushr $T0.2d,$ACC3,#26 + xtn $H3,$ACC3 + ushr $T1.2d,$ACC0,#26 + and $ACC0,$ACC0,$MASK.2d + add $ACC4,$ACC4,$T0.2d // h3 -> h4 + bic $H3,#0xfc,lsl#24 // &=0x03ffffff + add $ACC1,$ACC1,$T1.2d // h0 -> h1 + + ushr $T0.2d,$ACC4,#26 + xtn $H4,$ACC4 + ushr $T1.2d,$ACC1,#26 + xtn $H1,$ACC1 + bic $H4,#0xfc,lsl#24 + add $ACC2,$ACC2,$T1.2d // h1 -> h2 + + add $ACC0,$ACC0,$T0.2d + shl $T0.2d,$T0.2d,#2 + shrn $T1.2s,$ACC2,#26 + xtn $H2,$ACC2 + add $ACC0,$ACC0,$T0.2d // h4 -> h0 + bic $H1,#0xfc,lsl#24 + add $H3,$H3,$T1.2s // h2 -> h3 + bic $H2,#0xfc,lsl#24 + + shrn $T0.2s,$ACC0,#26 + xtn $H0,$ACC0 + ushr $T1.2s,$H3,#26 + bic $H3,#0xfc,lsl#24 + bic $H0,#0xfc,lsl#24 + add $H1,$H1,$T0.2s // h0 -> h1 + add $H4,$H4,$T1.2s // h3 -> h4 + + b.hi .Loop_neon + +.Lskip_loop: + dup $IN23_2,${IN23_2}[0] + add $IN01_2,$IN01_2,$H2 + + //////////////////////////////////////////////////////////////// + // multiply (inp[0:1]+hash) or inp[2:3] by r^2:r^1 + + adds $len,$len,#32 + b.ne .Long_tail + + dup $IN23_2,${IN01_2}[0] + add $IN23_0,$IN01_0,$H0 + add $IN23_3,$IN01_3,$H3 + add $IN23_1,$IN01_1,$H1 + add $IN23_4,$IN01_4,$H4 + +.Long_tail: + dup $IN23_0,${IN23_0}[0] + umull2 $ACC0,$IN23_2,${S3} + umull2 $ACC3,$IN23_2,${R1} + umull2 $ACC4,$IN23_2,${R2} + umull2 $ACC2,$IN23_2,${R0} + umull2 $ACC1,$IN23_2,${S4} + + dup $IN23_1,${IN23_1}[0] + umlal2 $ACC0,$IN23_0,${R0} + umlal2 $ACC2,$IN23_0,${R2} + umlal2 $ACC3,$IN23_0,${R3} + umlal2 $ACC4,$IN23_0,${R4} + umlal2 $ACC1,$IN23_0,${R1} + + dup $IN23_3,${IN23_3}[0] + umlal2 $ACC0,$IN23_1,${S4} + umlal2 $ACC3,$IN23_1,${R2} + umlal2 $ACC2,$IN23_1,${R1} + umlal2 $ACC4,$IN23_1,${R3} + umlal2 $ACC1,$IN23_1,${R0} + + dup $IN23_4,${IN23_4}[0] + umlal2 $ACC3,$IN23_3,${R0} + umlal2 $ACC4,$IN23_3,${R1} + umlal2 $ACC0,$IN23_3,${S2} + umlal2 $ACC1,$IN23_3,${S3} + umlal2 $ACC2,$IN23_3,${S4} + + umlal2 $ACC3,$IN23_4,${S4} + umlal2 $ACC0,$IN23_4,${S1} + umlal2 $ACC4,$IN23_4,${R0} + umlal2 $ACC1,$IN23_4,${S2} + umlal2 $ACC2,$IN23_4,${S3} + + b.eq .Lshort_tail + + //////////////////////////////////////////////////////////////// + // (hash+inp[0:1])*r^4:r^3 and accumulate + + add $IN01_0,$IN01_0,$H0 + umlal $ACC3,$IN01_2,${R1} + umlal $ACC0,$IN01_2,${S3} + umlal $ACC4,$IN01_2,${R2} + umlal $ACC1,$IN01_2,${S4} + umlal $ACC2,$IN01_2,${R0} + + add $IN01_1,$IN01_1,$H1 + umlal $ACC3,$IN01_0,${R3} + umlal $ACC0,$IN01_0,${R0} + umlal $ACC4,$IN01_0,${R4} + umlal $ACC1,$IN01_0,${R1} + umlal $ACC2,$IN01_0,${R2} + + add $IN01_3,$IN01_3,$H3 + umlal $ACC3,$IN01_1,${R2} + umlal $ACC0,$IN01_1,${S4} + umlal $ACC4,$IN01_1,${R3} + umlal $ACC1,$IN01_1,${R0} + umlal $ACC2,$IN01_1,${R1} + + add $IN01_4,$IN01_4,$H4 + umlal $ACC3,$IN01_3,${R0} + umlal $ACC0,$IN01_3,${S2} + umlal $ACC4,$IN01_3,${R1} + umlal $ACC1,$IN01_3,${S3} + umlal $ACC2,$IN01_3,${S4} + + umlal $ACC3,$IN01_4,${S4} + umlal $ACC0,$IN01_4,${S1} + umlal $ACC4,$IN01_4,${R0} + umlal $ACC1,$IN01_4,${S2} + umlal $ACC2,$IN01_4,${S3} + +.Lshort_tail: + //////////////////////////////////////////////////////////////// + // horizontal add + + addp $ACC3,$ACC3,$ACC3 + ldp d8,d9,[sp,#16] // meet ABI requirements + addp $ACC0,$ACC0,$ACC0 + ldp d10,d11,[sp,#32] + addp $ACC4,$ACC4,$ACC4 + ldp d12,d13,[sp,#48] + addp $ACC1,$ACC1,$ACC1 + ldp d14,d15,[sp,#64] + addp $ACC2,$ACC2,$ACC2 + + //////////////////////////////////////////////////////////////// + // lazy reduction, but without narrowing + + ushr $T0.2d,$ACC3,#26 + and $ACC3,$ACC3,$MASK.2d + ushr $T1.2d,$ACC0,#26 + and $ACC0,$ACC0,$MASK.2d + + add $ACC4,$ACC4,$T0.2d // h3 -> h4 + add $ACC1,$ACC1,$T1.2d // h0 -> h1 + + ushr $T0.2d,$ACC4,#26 + and $ACC4,$ACC4,$MASK.2d + ushr $T1.2d,$ACC1,#26 + and $ACC1,$ACC1,$MASK.2d + add $ACC2,$ACC2,$T1.2d // h1 -> h2 + + add $ACC0,$ACC0,$T0.2d + shl $T0.2d,$T0.2d,#2 + ushr $T1.2d,$ACC2,#26 + and $ACC2,$ACC2,$MASK.2d + add $ACC0,$ACC0,$T0.2d // h4 -> h0 + add $ACC3,$ACC3,$T1.2d // h2 -> h3 + + ushr $T0.2d,$ACC0,#26 + and $ACC0,$ACC0,$MASK.2d + ushr $T1.2d,$ACC3,#26 + and $ACC3,$ACC3,$MASK.2d + add $ACC1,$ACC1,$T0.2d // h0 -> h1 + add $ACC4,$ACC4,$T1.2d // h3 -> h4 + + //////////////////////////////////////////////////////////////// + // write the result, can be partially reduced + + st4 {$ACC0,$ACC1,$ACC2,$ACC3}[0],[$ctx],#16 + st1 {$ACC4}[0],[$ctx] + +.Lno_data_neon: + .inst 0xd50323bf // autiasp + ldr x29,[sp],#80 + ret +.size poly1305_blocks_neon,.-poly1305_blocks_neon + +.type poly1305_emit_neon,%function +.align 5 +poly1305_emit_neon: + ldr $is_base2_26,[$ctx,#24] + cbz $is_base2_26,poly1305_emit + + ldp w10,w11,[$ctx] // load hash value base 2^26 + ldp w12,w13,[$ctx,#8] + ldr w14,[$ctx,#16] + + add $h0,x10,x11,lsl#26 // base 2^26 -> base 2^64 + lsr $h1,x12,#12 + adds $h0,$h0,x12,lsl#52 + add $h1,$h1,x13,lsl#14 + adc $h1,$h1,xzr + lsr $h2,x14,#24 + adds $h1,$h1,x14,lsl#40 + adc $h2,$h2,xzr // can be partially reduced... + + ldp $t0,$t1,[$nonce] // load nonce + + and $d0,$h2,#-4 // ... so reduce + add $d0,$d0,$h2,lsr#2 + and $h2,$h2,#3 + adds $h0,$h0,$d0 + adcs $h1,$h1,xzr + adc $h2,$h2,xzr + + adds $d0,$h0,#5 // compare to modulus + adcs $d1,$h1,xzr + adc $d2,$h2,xzr + + tst $d2,#-4 // see if it's carried/borrowed + + csel $h0,$h0,$d0,eq + csel $h1,$h1,$d1,eq + +#ifdef __ARMEB__ + ror $t0,$t0,#32 // flip nonce words + ror $t1,$t1,#32 +#endif + adds $h0,$h0,$t0 // accumulate nonce + adc $h1,$h1,$t1 +#ifdef __ARMEB__ + rev $h0,$h0 // flip output bytes + rev $h1,$h1 +#endif + stp $h0,$h1,[$mac] // write result + + ret +.size poly1305_emit_neon,.-poly1305_emit_neon + +.align 5 +.Lzeros: +.long 0,0,0,0,0,0,0,0 +.LOPENSSL_armcap_P: +#ifdef __ILP32__ +.long OPENSSL_armcap_P-. +#else +.quad OPENSSL_armcap_P-. +#endif +.asciz "Poly1305 for ARMv8, CRYPTOGAMS by " +.align 2 +___ + +foreach (split("\n",$code)) { + s/\b(shrn\s+v[0-9]+)\.[24]d/$1.2s/ or + s/\b(fmov\s+)v([0-9]+)[^,]*,\s*x([0-9]+)/$1d$2,x$3/ or + (m/\bdup\b/ and (s/\.[24]s/.2d/g or 1)) or + (m/\b(eor|and)/ and (s/\.[248][sdh]/.16b/g or 1)) or + (m/\bum(ul|la)l\b/ and (s/\.4s/.2s/g or 1)) or + (m/\bum(ul|la)l2\b/ and (s/\.2s/.4s/g or 1)) or + (m/\bst[1-4]\s+{[^}]+}\[/ and (s/\.[24]d/.s/g or 1)); + + s/\.[124]([sd])\[/.$1\[/; + + print $_,"\n"; +} +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-c64xplus.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-c64xplus.pl new file mode 100755 index 000000000..93fef37e6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-c64xplus.pl @@ -0,0 +1,331 @@ +#! /usr/bin/env perl +# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# Poly1305 hash for C64x+. +# +# October 2015 +# +# Performance is [incredible for a 32-bit processor] 1.82 cycles per +# processed byte. Comparison to compiler-generated code is problematic, +# because results were observed to vary from 2.1 to 7.6 cpb depending +# on compiler's ability to inline small functions. Compiler also +# disables interrupts for some reason, thus making interrupt response +# time dependent on input length. This module on the other hand is free +# from such limitation. + +$output=pop; +open STDOUT,">$output"; + +($CTXA,$INPB,$LEN,$PADBIT)=("A4","B4","A6","B6"); +($H0,$H1,$H2,$H3,$H4,$H4a)=("A8","B8","A10","B10","B2",$LEN); +($D0,$D1,$D2,$D3)= ("A9","B9","A11","B11"); +($R0,$R1,$R2,$R3,$S1,$S2,$S3,$S3b)=("A0","B0","A1","B1","A12","B12","A13","B13"); +($THREE,$R0b,$S2a)=("B7","B5","A5"); + +$code.=<<___; + .text + + .if .ASSEMBLER_VERSION<7000000 + .asg 0,__TI_EABI__ + .endif + .if __TI_EABI__ + .asg poly1305_init,_poly1305_init + .asg poly1305_blocks,_poly1305_blocks + .asg poly1305_emit,_poly1305_emit + .endif + + .asg B3,RA + .asg A15,FP + .asg B15,SP + + .if .LITTLE_ENDIAN + .asg MV,SWAP2 + .asg MV.L,SWAP4 + .endif + + .global _poly1305_init +_poly1305_init: + .asmfunc + LDNDW *${INPB}[0],B17:B16 ; load key material + LDNDW *${INPB}[1],A17:A16 + +|| ZERO B9:B8 +|| MVK -1,B0 + STDW B9:B8,*${CTXA}[0] ; initialize h1:h0 +|| SHRU B0,4,B0 ; 0x0fffffff +|| MVK -4,B1 + STDW B9:B8,*${CTXA}[1] ; initialize h3:h2 +|| AND B0,B1,B1 ; 0x0ffffffc + STW B8,*${CTXA}[4] ; initialize h4 + + .if .BIG_ENDIAN + SWAP2 B16,B17 +|| SWAP2 B17,B16 + SWAP2 A16,A17 +|| SWAP2 A17,A16 + SWAP4 B16,B16 +|| SWAP4 A16,A16 + SWAP4 B17,B17 +|| SWAP4 A17,A17 + .endif + + AND B16,B0,B20 ; r0 = key[0] & 0x0fffffff +|| AND B17,B1,B22 ; r1 = key[1] & 0x0ffffffc +|| EXTU B17,4,6,B16 ; r1>>2 + AND A16,B1,B21 ; r2 = key[2] & 0x0ffffffc +|| AND A17,B1,A23 ; r3 = key[3] & 0x0ffffffc +|| BNOP RA + SHRU B21,2,B18 +|| ADD B22,B16,B16 ; s1 = r1 + r1>>2 + + STDW B21:B20,*${CTXA}[3] ; save r2:r0 +|| ADD B21,B18,B18 ; s2 = r2 + r2>>2 +|| SHRU A23,2,B17 +|| MV A23,B23 + STDW B23:B22,*${CTXA}[4] ; save r3:r1 +|| ADD B23,B17,B19 ; s3 = r3 + r3>>2 +|| ADD B23,B17,B17 ; s3 = r3 + r3>>2 + STDW B17:B16,*${CTXA}[5] ; save s3:s1 + STDW B19:B18,*${CTXA}[6] ; save s3:s2 +|| ZERO A4 ; return 0 + .endasmfunc + + .global _poly1305_blocks + .align 32 +_poly1305_blocks: + .asmfunc stack_usage(40) + SHRU $LEN,4,A2 ; A2 is loop counter, number of blocks + [!A2] BNOP RA ; no data +|| [A2] STW FP,*SP--(40) ; save frame pointer and alloca(40) +|| [A2] MV SP,FP + [A2] STDW B13:B12,*SP[4] ; ABI says so +|| [A2] MV $CTXA,$S3b ; borrow $S3b + [A2] STDW B11:B10,*SP[3] +|| [A2] STDW A13:A12,*FP[-3] + [A2] STDW A11:A10,*FP[-4] + +|| [A2] LDDW *${S3b}[0],B25:B24 ; load h1:h0 + [A2] LDNW *${INPB}++[4],$D0 ; load inp[0] + [A2] LDNW *${INPB}[-3],$D1 ; load inp[1] + + LDDW *${CTXA}[1],B29:B28 ; load h3:h2, B28 is h2 + LDNW *${INPB}[-2],$D2 ; load inp[2] + LDNW *${INPB}[-1],$D3 ; load inp[3] + + LDDW *${CTXA}[3],$R2:$R0 ; load r2:r0 +|| LDDW *${S3b}[4],$R3:$R1 ; load r3:r1 +|| SWAP2 $D0,$D0 + + LDDW *${CTXA}[5],$S3:$S1 ; load s3:s1 +|| LDDW *${S3b}[6],$S3b:$S2 ; load s3:s2 +|| SWAP4 $D0,$D0 +|| SWAP2 $D1,$D1 + + ADDU $D0,B24,$D0:$H0 ; h0+=inp[0] +|| ADD $D0,B24,B27 ; B-copy of h0+inp[0] +|| SWAP4 $D1,$D1 + ADDU $D1,B25,$D1:$H1 ; h1+=inp[1] +|| MVK 3,$THREE +|| SWAP2 $D2,$D2 + LDW *${CTXA}[4],$H4 ; load h4 +|| SWAP4 $D2,$D2 +|| MV B29,B30 ; B30 is h3 + MV $R0,$R0b + +loop?: + MPY32U $H0,$R0,A17:A16 +|| MPY32U B27,$R1,B17:B16 ; MPY32U $H0,$R1,B17:B16 +|| ADDU $D0,$D1:$H1,B25:B24 ; ADDU $D0,$D1:$H1,$D1:$H1 +|| ADDU $D2,B28,$D2:$H2 ; h2+=inp[2] +|| SWAP2 $D3,$D3 + MPY32U $H0,$R2,A19:A18 +|| MPY32U B27,$R3,B19:B18 ; MPY32U $H0,$R3,B19:B18 +|| ADD $D0,$H1,A24 ; A-copy of B24 +|| SWAP4 $D3,$D3 +|| [A2] SUB A2,1,A2 ; decrement loop counter + + MPY32U A24,$S3,A21:A20 ; MPY32U $H1,$S3,A21:A20 +|| MPY32U B24,$R0b,B21:B20 ; MPY32U $H1,$R0,B21:B20 +|| ADDU B25,$D2:$H2,$D2:$H2 ; ADDU $D1,$D2:$H2,$D2:$H2 +|| ADDU $D3,B30,$D3:$H3 ; h3+=inp[3] +|| ADD B25,$H2,B25 ; B-copy of $H2 + MPY32U A24,$R1,A23:A22 ; MPY32U $H1,$R1,A23:A22 +|| MPY32U B24,$R2,B23:B22 ; MPY32U $H1,$R2,B23:B22 + + MPY32U $H2,$S2,A25:A24 +|| MPY32U B25,$S3b,B25:B24 ; MPY32U $H2,$S3,B25:B24 +|| ADDU $D2,$D3:$H3,$D3:$H3 +|| ADD $PADBIT,$H4,$H4 ; h4+=padbit + MPY32U $H2,$R0,A27:A26 +|| MPY32U $H2,$R1,B27:B26 +|| ADD $D3,$H4,$H4 +|| MV $S2,$S2a + + MPY32U $H3,$S1,A29:A28 +|| MPY32U $H3,$S2,B29:B28 +|| ADD A21,A17,A21 ; start accumulating "d3:d0" +|| ADD B21,B17,B21 +|| ADDU A20,A16,A17:A16 +|| ADDU B20,B16,B17:B16 +|| [A2] LDNW *${INPB}++[4],$D0 ; load inp[0] + MPY32U $H3,$S3,A31:A30 +|| MPY32U $H3,$R0b,B31:B30 +|| ADD A23,A19,A23 +|| ADD B23,B19,B23 +|| ADDU A22,A18,A19:A18 +|| ADDU B22,B18,B19:B18 +|| [A2] LDNW *${INPB}[-3],$D1 ; load inp[1] + + MPY32 $H4,$S1,B20 +|| MPY32 $H4,$S2a,A20 +|| ADD A25,A21,A21 +|| ADD B25,B21,B21 +|| ADDU A24,A17:A16,A17:A16 +|| ADDU B24,B17:B16,B17:B16 +|| [A2] LDNW *${INPB}[-2],$D2 ; load inp[2] + MPY32 $H4,$S3b,B22 +|| ADD A27,A23,A23 +|| ADD B27,B23,B23 +|| ADDU A26,A19:A18,A19:A18 +|| ADDU B26,B19:B18,B19:B18 +|| [A2] LDNW *${INPB}[-1],$D3 ; load inp[3] + + MPY32 $H4,$R0b,$H4 +|| ADD A29,A21,A21 ; final hi("d0") +|| ADD B29,B21,B21 ; final hi("d1") +|| ADDU A28,A17:A16,A17:A16 ; final lo("d0") +|| ADDU B28,B17:B16,B17:B16 + ADD A31,A23,A23 ; final hi("d2") +|| ADD B31,B23,B23 ; final hi("d3") +|| ADDU A30,A19:A18,A19:A18 +|| ADDU B30,B19:B18,B19:B18 + ADDU B20,B17:B16,B17:B16 ; final lo("d1") +|| ADDU A20,A19:A18,A19:A18 ; final lo("d2") + ADDU B22,B19:B18,B19:B18 ; final lo("d3") + +|| ADD A17,A21,A21 ; "flatten" "d3:d0" + MV A19,B29 ; move to avoid cross-path stalls + ADDU A21,B17:B16,B27:B26 ; B26 is h1 + ADD B21,B27,B27 +|| DMV B29,A18,B29:B28 ; move to avoid cross-path stalls + ADDU B27,B29:B28,B29:B28 ; B28 is h2 +|| [A2] SWAP2 $D0,$D0 + ADD A23,B29,B29 +|| [A2] SWAP4 $D0,$D0 + ADDU B29,B19:B18,B31:B30 ; B30 is h3 + ADD B23,B31,B31 +|| MV A16,B24 ; B24 is h0 +|| [A2] SWAP2 $D1,$D1 + ADD B31,$H4,$H4 +|| [A2] SWAP4 $D1,$D1 + + SHRU $H4,2,B16 ; last reduction step +|| AND $H4,$THREE,$H4 + ADDAW B16,B16,B16 ; 5*(h4>>2) +|| [A2] BNOP loop? + + ADDU B24,B16,B25:B24 ; B24 is h0 +|| [A2] SWAP2 $D2,$D2 + ADDU B26,B25,B27:B26 ; B26 is h1 +|| [A2] SWAP4 $D2,$D2 + ADDU B28,B27,B29:B28 ; B28 is h2 +|| [A2] ADDU $D0,B24,$D0:$H0 ; h0+=inp[0] +|| [A2] ADD $D0,B24,B27 ; B-copy of h0+inp[0] + ADDU B30,B29,B31:B30 ; B30 is h3 + ADD B31,$H4,$H4 +|| [A2] ADDU $D1,B26,$D1:$H1 ; h1+=inp[1] +;;===== branch to loop? is taken here + + LDDW *FP[-4],A11:A10 ; ABI says so + LDDW *FP[-3],A13:A12 +|| LDDW *SP[3],B11:B10 + LDDW *SP[4],B13:B12 +|| MV B26,B25 +|| BNOP RA + LDW *++SP(40),FP ; restore frame pointer +|| MV B30,B29 + STDW B25:B24,*${CTXA}[0] ; save h1:h0 + STDW B29:B28,*${CTXA}[1] ; save h3:h2 + STW $H4,*${CTXA}[4] ; save h4 + NOP 1 + .endasmfunc +___ +{ +my ($MAC,$NONCEA,$NONCEB)=($INPB,$LEN,$PADBIT); + +$code.=<<___; + .global _poly1305_emit + .align 32 +_poly1305_emit: + .asmfunc + LDDW *${CTXA}[0],A17:A16 ; load h1:h0 + LDDW *${CTXA}[1],A19:A18 ; load h3:h2 + LDW *${CTXA}[4],A20 ; load h4 + MV $NONCEA,$NONCEB + + MVK 5,A22 ; compare to modulus + ADDU A16,A22,A23:A22 +|| LDW *${NONCEA}[0],A8 +|| LDW *${NONCEB}[1],B8 + ADDU A17,A23,A25:A24 +|| LDW *${NONCEA}[2],A9 +|| LDW *${NONCEB}[3],B9 + ADDU A19,A25,A27:A26 + ADDU A19,A27,A29:A28 + ADD A20,A29,A29 + + SHRU A29,2,A2 ; check for overflow in 130-th bit + + [A2] MV A22,A16 ; select +|| [A2] MV A24,A17 + [A2] MV A26,A18 +|| [A2] MV A28,A19 + +|| ADDU A8,A16,A23:A22 ; accumulate nonce + ADDU B8,A17,A25:A24 +|| SWAP2 A22,A22 + ADDU A23,A25:A24,A25:A24 + ADDU A9,A18,A27:A26 +|| SWAP2 A24,A24 + ADDU A25,A27:A26,A27:A26 +|| ADD B9,A19,A28 + ADD A27,A28,A28 +|| SWAP2 A26,A26 + + .if .BIG_ENDIAN + SWAP2 A28,A28 +|| SWAP4 A22,A22 +|| SWAP4 A24,B24 + SWAP4 A26,A26 + SWAP4 A28,A28 +|| MV B24,A24 + .endif + + BNOP RA,1 + STNW A22,*${MAC}[0] ; write the result + STNW A24,*${MAC}[1] + STNW A26,*${MAC}[2] + STNW A28,*${MAC}[3] + .endasmfunc +___ +} +$code.=<<___; + .sect .const + .cstring "Poly1305 for C64x+, CRYPTOGAMS by " + .align 4 +___ + +print $code; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-mips.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-mips.pl new file mode 100755 index 000000000..28b6772ee --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-mips.pl @@ -0,0 +1,437 @@ +#! /usr/bin/env perl +# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# Poly1305 hash for MIPS64. +# +# May 2016 +# +# Numbers are cycles per processed byte with poly1305_blocks alone. +# +# IALU/gcc +# R1x000 5.64/+120% (big-endian) +# Octeon II 3.80/+280% (little-endian) + +###################################################################### +# There is a number of MIPS ABI in use, O32 and N32/64 are most +# widely used. Then there is a new contender: NUBI. It appears that if +# one picks the latter, it's possible to arrange code in ABI neutral +# manner. Therefore let's stick to NUBI register layout: +# +($zero,$at,$t0,$t1,$t2)=map("\$$_",(0..2,24,25)); +($a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7)=map("\$$_",(4..11)); +($s0,$s1,$s2,$s3,$s4,$s5,$s6,$s7,$s8,$s9,$s10,$s11)=map("\$$_",(12..23)); +($gp,$tp,$sp,$fp,$ra)=map("\$$_",(3,28..31)); +# +# The return value is placed in $a0. Following coding rules facilitate +# interoperability: +# +# - never ever touch $tp, "thread pointer", former $gp [o32 can be +# excluded from the rule, because it's specified volatile]; +# - copy return value to $t0, former $v0 [or to $a0 if you're adapting +# old code]; +# - on O32 populate $a4-$a7 with 'lw $aN,4*N($sp)' if necessary; +# +# For reference here is register layout for N32/64 MIPS ABIs: +# +# ($zero,$at,$v0,$v1)=map("\$$_",(0..3)); +# ($a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7)=map("\$$_",(4..11)); +# ($t0,$t1,$t2,$t3,$t8,$t9)=map("\$$_",(12..15,24,25)); +# ($s0,$s1,$s2,$s3,$s4,$s5,$s6,$s7)=map("\$$_",(16..23)); +# ($gp,$sp,$fp,$ra)=map("\$$_",(28..31)); +# +# +# +###################################################################### + +$flavour = shift || "o32"; # supported flavours are o32,n32,64,nubi32,nubi64 + +die "MIPS64 only" unless ($flavour =~ /64|n32/i); + +$v0 = ($flavour =~ /nubi/i) ? $a0 : $t0; +$SAVED_REGS_MASK = ($flavour =~ /nubi/i) ? "0x0003f000" : "0x00030000"; + +($ctx,$inp,$len,$padbit) = ($a0,$a1,$a2,$a3); +($in0,$in1,$tmp0,$tmp1,$tmp2,$tmp3,$tmp4) = ($a4,$a5,$a6,$a7,$at,$t0,$t1); + +$code.=<<___; +#include "mips_arch.h" + +#ifdef MIPSEB +# define MSB 0 +# define LSB 7 +#else +# define MSB 7 +# define LSB 0 +#endif + +.text +.set noat +.set noreorder + +.align 5 +.globl poly1305_init +.ent poly1305_init +poly1305_init: + .frame $sp,0,$ra + .set reorder + + sd $zero,0($ctx) + sd $zero,8($ctx) + sd $zero,16($ctx) + + beqz $inp,.Lno_key + +#if defined(_MIPS_ARCH_MIPS64R6) + ld $in0,0($inp) + ld $in1,8($inp) +#else + ldl $in0,0+MSB($inp) + ldl $in1,8+MSB($inp) + ldr $in0,0+LSB($inp) + ldr $in1,8+LSB($inp) +#endif +#ifdef MIPSEB +# if defined(_MIPS_ARCH_MIPS64R2) + dsbh $in0,$in0 # byte swap + dsbh $in1,$in1 + dshd $in0,$in0 + dshd $in1,$in1 +# else + ori $tmp0,$zero,0xFF + dsll $tmp2,$tmp0,32 + or $tmp0,$tmp2 # 0x000000FF000000FF + + and $tmp1,$in0,$tmp0 # byte swap + and $tmp3,$in1,$tmp0 + dsrl $tmp2,$in0,24 + dsrl $tmp4,$in1,24 + dsll $tmp1,24 + dsll $tmp3,24 + and $tmp2,$tmp0 + and $tmp4,$tmp0 + dsll $tmp0,8 # 0x0000FF000000FF00 + or $tmp1,$tmp2 + or $tmp3,$tmp4 + and $tmp2,$in0,$tmp0 + and $tmp4,$in1,$tmp0 + dsrl $in0,8 + dsrl $in1,8 + dsll $tmp2,8 + dsll $tmp4,8 + and $in0,$tmp0 + and $in1,$tmp0 + or $tmp1,$tmp2 + or $tmp3,$tmp4 + or $in0,$tmp1 + or $in1,$tmp3 + dsrl $tmp1,$in0,32 + dsrl $tmp3,$in1,32 + dsll $in0,32 + dsll $in1,32 + or $in0,$tmp1 + or $in1,$tmp3 +# endif +#endif + li $tmp0,1 + dsll $tmp0,32 + daddiu $tmp0,-63 + dsll $tmp0,28 + daddiu $tmp0,-1 # 0ffffffc0fffffff + + and $in0,$tmp0 + daddiu $tmp0,-3 # 0ffffffc0ffffffc + and $in1,$tmp0 + + sd $in0,24($ctx) + dsrl $tmp0,$in1,2 + sd $in1,32($ctx) + daddu $tmp0,$in1 # s1 = r1 + (r1 >> 2) + sd $tmp0,40($ctx) + +.Lno_key: + li $v0,0 # return 0 + jr $ra +.end poly1305_init +___ +{ +my ($h0,$h1,$h2,$r0,$r1,$s1,$d0,$d1,$d2) = + ($s0,$s1,$s2,$s3,$s4,$s5,$in0,$in1,$t2); + +$code.=<<___; +.align 5 +.globl poly1305_blocks +.ent poly1305_blocks +poly1305_blocks: + .set noreorder + dsrl $len,4 # number of complete blocks + bnez $len,poly1305_blocks_internal + nop + jr $ra + nop +.end poly1305_blocks + +.align 5 +.ent poly1305_blocks_internal +poly1305_blocks_internal: + .frame $sp,6*8,$ra + .mask $SAVED_REGS_MASK,-8 + .set noreorder + dsubu $sp,6*8 + sd $s5,40($sp) + sd $s4,32($sp) +___ +$code.=<<___ if ($flavour =~ /nubi/i); # optimize non-nubi prologue + sd $s3,24($sp) + sd $s2,16($sp) + sd $s1,8($sp) + sd $s0,0($sp) +___ +$code.=<<___; + .set reorder + + ld $h0,0($ctx) # load hash value + ld $h1,8($ctx) + ld $h2,16($ctx) + + ld $r0,24($ctx) # load key + ld $r1,32($ctx) + ld $s1,40($ctx) + +.Loop: +#if defined(_MIPS_ARCH_MIPS64R6) + ld $in0,0($inp) # load input + ld $in1,8($inp) +#else + ldl $in0,0+MSB($inp) # load input + ldl $in1,8+MSB($inp) + ldr $in0,0+LSB($inp) + ldr $in1,8+LSB($inp) +#endif + daddiu $len,-1 + daddiu $inp,16 +#ifdef MIPSEB +# if defined(_MIPS_ARCH_MIPS64R2) + dsbh $in0,$in0 # byte swap + dsbh $in1,$in1 + dshd $in0,$in0 + dshd $in1,$in1 +# else + ori $tmp0,$zero,0xFF + dsll $tmp2,$tmp0,32 + or $tmp0,$tmp2 # 0x000000FF000000FF + + and $tmp1,$in0,$tmp0 # byte swap + and $tmp3,$in1,$tmp0 + dsrl $tmp2,$in0,24 + dsrl $tmp4,$in1,24 + dsll $tmp1,24 + dsll $tmp3,24 + and $tmp2,$tmp0 + and $tmp4,$tmp0 + dsll $tmp0,8 # 0x0000FF000000FF00 + or $tmp1,$tmp2 + or $tmp3,$tmp4 + and $tmp2,$in0,$tmp0 + and $tmp4,$in1,$tmp0 + dsrl $in0,8 + dsrl $in1,8 + dsll $tmp2,8 + dsll $tmp4,8 + and $in0,$tmp0 + and $in1,$tmp0 + or $tmp1,$tmp2 + or $tmp3,$tmp4 + or $in0,$tmp1 + or $in1,$tmp3 + dsrl $tmp1,$in0,32 + dsrl $tmp3,$in1,32 + dsll $in0,32 + dsll $in1,32 + or $in0,$tmp1 + or $in1,$tmp3 +# endif +#endif + daddu $h0,$in0 # accumulate input + daddu $h1,$in1 + sltu $tmp0,$h0,$in0 + sltu $tmp1,$h1,$in1 + daddu $h1,$tmp0 + + dmultu ($r0,$h0) # h0*r0 + daddu $h2,$padbit + sltu $tmp0,$h1,$tmp0 + mflo ($d0,$r0,$h0) + mfhi ($d1,$r0,$h0) + + dmultu ($s1,$h1) # h1*5*r1 + daddu $tmp0,$tmp1 + daddu $h2,$tmp0 + mflo ($tmp0,$s1,$h1) + mfhi ($tmp1,$s1,$h1) + + dmultu ($r1,$h0) # h0*r1 + daddu $d0,$tmp0 + daddu $d1,$tmp1 + mflo ($tmp2,$r1,$h0) + mfhi ($d2,$r1,$h0) + sltu $tmp0,$d0,$tmp0 + daddu $d1,$tmp0 + + dmultu ($r0,$h1) # h1*r0 + daddu $d1,$tmp2 + sltu $tmp2,$d1,$tmp2 + mflo ($tmp0,$r0,$h1) + mfhi ($tmp1,$r0,$h1) + daddu $d2,$tmp2 + + dmultu ($s1,$h2) # h2*5*r1 + daddu $d1,$tmp0 + daddu $d2,$tmp1 + mflo ($tmp2,$s1,$h2) + + dmultu ($r0,$h2) # h2*r0 + sltu $tmp0,$d1,$tmp0 + daddu $d2,$tmp0 + mflo ($tmp3,$r0,$h2) + + daddu $d1,$tmp2 + daddu $d2,$tmp3 + sltu $tmp2,$d1,$tmp2 + daddu $d2,$tmp2 + + li $tmp0,-4 # final reduction + and $tmp0,$d2 + dsrl $tmp1,$d2,2 + andi $h2,$d2,3 + daddu $tmp0,$tmp1 + daddu $h0,$d0,$tmp0 + sltu $tmp0,$h0,$tmp0 + daddu $h1,$d1,$tmp0 + sltu $tmp0,$h1,$tmp0 + daddu $h2,$h2,$tmp0 + + bnez $len,.Loop + + sd $h0,0($ctx) # store hash value + sd $h1,8($ctx) + sd $h2,16($ctx) + + .set noreorder + ld $s5,40($sp) # epilogue + ld $s4,32($sp) +___ +$code.=<<___ if ($flavour =~ /nubi/i); # optimize non-nubi epilogue + ld $s3,24($sp) + ld $s2,16($sp) + ld $s1,8($sp) + ld $s0,0($sp) +___ +$code.=<<___; + jr $ra + daddu $sp,6*8 +.end poly1305_blocks_internal +___ +} +{ +my ($ctx,$mac,$nonce) = ($a0,$a1,$a2); + +$code.=<<___; +.align 5 +.globl poly1305_emit +.ent poly1305_emit +poly1305_emit: + .frame $sp,0,$ra + .set reorder + + ld $tmp0,0($ctx) + ld $tmp1,8($ctx) + ld $tmp2,16($ctx) + + daddiu $in0,$tmp0,5 # compare to modulus + sltiu $tmp3,$in0,5 + daddu $in1,$tmp1,$tmp3 + sltu $tmp3,$in1,$tmp3 + daddu $tmp2,$tmp2,$tmp3 + + dsrl $tmp2,2 # see if it carried/borrowed + dsubu $tmp2,$zero,$tmp2 + nor $tmp3,$zero,$tmp2 + + and $in0,$tmp2 + and $tmp0,$tmp3 + and $in1,$tmp2 + and $tmp1,$tmp3 + or $in0,$tmp0 + or $in1,$tmp1 + + lwu $tmp0,0($nonce) # load nonce + lwu $tmp1,4($nonce) + lwu $tmp2,8($nonce) + lwu $tmp3,12($nonce) + dsll $tmp1,32 + dsll $tmp3,32 + or $tmp0,$tmp1 + or $tmp2,$tmp3 + + daddu $in0,$tmp0 # accumulate nonce + daddu $in1,$tmp2 + sltu $tmp0,$in0,$tmp0 + daddu $in1,$tmp0 + + dsrl $tmp0,$in0,8 # write mac value + dsrl $tmp1,$in0,16 + dsrl $tmp2,$in0,24 + sb $in0,0($mac) + dsrl $tmp3,$in0,32 + sb $tmp0,1($mac) + dsrl $tmp0,$in0,40 + sb $tmp1,2($mac) + dsrl $tmp1,$in0,48 + sb $tmp2,3($mac) + dsrl $tmp2,$in0,56 + sb $tmp3,4($mac) + dsrl $tmp3,$in1,8 + sb $tmp0,5($mac) + dsrl $tmp0,$in1,16 + sb $tmp1,6($mac) + dsrl $tmp1,$in1,24 + sb $tmp2,7($mac) + + sb $in1,8($mac) + dsrl $tmp2,$in1,32 + sb $tmp3,9($mac) + dsrl $tmp3,$in1,40 + sb $tmp0,10($mac) + dsrl $tmp0,$in1,48 + sb $tmp1,11($mac) + dsrl $tmp1,$in1,56 + sb $tmp2,12($mac) + sb $tmp3,13($mac) + sb $tmp0,14($mac) + sb $tmp1,15($mac) + + jr $ra +.end poly1305_emit +.rdata +.asciiz "Poly1305 for MIPS64, CRYPTOGAMS by " +.align 2 +___ +} + +$output=pop and open STDOUT,">$output"; +print $code; +close STDOUT; + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-ppc.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-ppc.pl new file mode 100755 index 000000000..0c6d015d5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-ppc.pl @@ -0,0 +1,645 @@ +#! /usr/bin/env perl +# Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# This module implements Poly1305 hash for PowerPC. +# +# June 2015 +# +# Numbers are cycles per processed byte with poly1305_blocks alone, +# and improvement coefficients relative to gcc-generated code. +# +# -m32 -m64 +# +# Freescale e300 14.8/+80% - +# PPC74x0 7.60/+60% - +# PPC970 7.00/+114% 3.51/+205% +# POWER7 3.75/+260% 1.93/+100% +# POWER8 - 2.03/+200% +# POWER9 - 2.00/+150% +# +# Do we need floating-point implementation for PPC? Results presented +# in poly1305_ieee754.c are tricky to compare to, because they are for +# compiler-generated code. On the other hand it's known that floating- +# point performance can be dominated by FPU latency, which means that +# there is limit even for ideally optimized (and even vectorized) code. +# And this limit is estimated to be higher than above -m64 results. Or +# in other words floating-point implementation can be meaningful to +# consider only in 32-bit application context. We probably have to +# recognize that 32-bit builds are getting less popular on high-end +# systems and therefore tend to target embedded ones, which might not +# even have FPU... +# +# On side note, Power ISA 2.07 enables vector base 2^26 implementation, +# and POWER8 might have capacity to break 1.0 cycle per byte barrier... + +$flavour = shift; + +if ($flavour =~ /64/) { + $SIZE_T =8; + $LRSAVE =2*$SIZE_T; + $UCMP ="cmpld"; + $STU ="stdu"; + $POP ="ld"; + $PUSH ="std"; +} elsif ($flavour =~ /32/) { + $SIZE_T =4; + $LRSAVE =$SIZE_T; + $UCMP ="cmplw"; + $STU ="stwu"; + $POP ="lwz"; + $PUSH ="stw"; +} else { die "nonsense $flavour"; } + +# Define endianness based on flavour +# i.e.: linux64le +$LITTLE_ENDIAN = ($flavour=~/le$/) ? $SIZE_T : 0; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or +die "can't locate ppc-xlate.pl"; + +open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!"; + +$FRAME=24*$SIZE_T; + +$sp="r1"; +my ($ctx,$inp,$len,$padbit) = map("r$_",(3..6)); +my ($mac,$nonce)=($inp,$len); +my $mask = "r0"; + +$code=<<___; +.machine "any" +.text +___ + if ($flavour =~ /64/) { +############################################################################### +# base 2^64 implementation + +my ($h0,$h1,$h2,$d0,$d1,$d2, $r0,$r1,$s1, $t0,$t1) = map("r$_",(7..12,27..31)); + +$code.=<<___; +.globl .poly1305_init_int +.align 4 +.poly1305_init_int: + xor r0,r0,r0 + std r0,0($ctx) # zero hash value + std r0,8($ctx) + std r0,16($ctx) + + $UCMP $inp,r0 + beq- Lno_key +___ +$code.=<<___ if ($LITTLE_ENDIAN); + ld $d0,0($inp) # load key material + ld $d1,8($inp) +___ +$code.=<<___ if (!$LITTLE_ENDIAN); + li $h0,4 + lwbrx $d0,0,$inp # load key material + li $d1,8 + lwbrx $h0,$h0,$inp + li $h1,12 + lwbrx $d1,$d1,$inp + lwbrx $h1,$h1,$inp + insrdi $d0,$h0,32,0 + insrdi $d1,$h1,32,0 +___ +$code.=<<___; + lis $h1,0xfff # 0x0fff0000 + ori $h1,$h1,0xfffc # 0x0ffffffc + insrdi $h1,$h1,32,0 # 0x0ffffffc0ffffffc + ori $h0,$h1,3 # 0x0ffffffc0fffffff + + and $d0,$d0,$h0 + and $d1,$d1,$h1 + + std $d0,32($ctx) # store key + std $d1,40($ctx) + +Lno_key: + xor r3,r3,r3 + blr + .long 0 + .byte 0,12,0x14,0,0,0,2,0 +.size .poly1305_init_int,.-.poly1305_init_int + +.globl .poly1305_blocks +.align 4 +.poly1305_blocks: + srdi. $len,$len,4 + beq- Labort + + $STU $sp,-$FRAME($sp) + mflr r0 + $PUSH r27,`$FRAME-$SIZE_T*5`($sp) + $PUSH r28,`$FRAME-$SIZE_T*4`($sp) + $PUSH r29,`$FRAME-$SIZE_T*3`($sp) + $PUSH r30,`$FRAME-$SIZE_T*2`($sp) + $PUSH r31,`$FRAME-$SIZE_T*1`($sp) + $PUSH r0,`$FRAME+$LRSAVE`($sp) + + ld $r0,32($ctx) # load key + ld $r1,40($ctx) + + ld $h0,0($ctx) # load hash value + ld $h1,8($ctx) + ld $h2,16($ctx) + + srdi $s1,$r1,2 + mtctr $len + add $s1,$s1,$r1 # s1 = r1 + r1>>2 + li $mask,3 + b Loop + +.align 4 +Loop: +___ +$code.=<<___ if ($LITTLE_ENDIAN); + ld $t0,0($inp) # load input + ld $t1,8($inp) +___ +$code.=<<___ if (!$LITTLE_ENDIAN); + li $d0,4 + lwbrx $t0,0,$inp # load input + li $t1,8 + lwbrx $d0,$d0,$inp + li $d1,12 + lwbrx $t1,$t1,$inp + lwbrx $d1,$d1,$inp + insrdi $t0,$d0,32,0 + insrdi $t1,$d1,32,0 +___ +$code.=<<___; + addi $inp,$inp,16 + + addc $h0,$h0,$t0 # accumulate input + adde $h1,$h1,$t1 + + mulld $d0,$h0,$r0 # h0*r0 + mulhdu $d1,$h0,$r0 + adde $h2,$h2,$padbit + + mulld $t0,$h1,$s1 # h1*5*r1 + mulhdu $t1,$h1,$s1 + addc $d0,$d0,$t0 + adde $d1,$d1,$t1 + + mulld $t0,$h0,$r1 # h0*r1 + mulhdu $d2,$h0,$r1 + addc $d1,$d1,$t0 + addze $d2,$d2 + + mulld $t0,$h1,$r0 # h1*r0 + mulhdu $t1,$h1,$r0 + addc $d1,$d1,$t0 + adde $d2,$d2,$t1 + + mulld $t0,$h2,$s1 # h2*5*r1 + mulld $t1,$h2,$r0 # h2*r0 + addc $d1,$d1,$t0 + adde $d2,$d2,$t1 + + andc $t0,$d2,$mask # final reduction step + and $h2,$d2,$mask + srdi $t1,$t0,2 + add $t0,$t0,$t1 + addc $h0,$d0,$t0 + addze $h1,$d1 + addze $h2,$h2 + + bdnz Loop + + std $h0,0($ctx) # store hash value + std $h1,8($ctx) + std $h2,16($ctx) + + $POP r27,`$FRAME-$SIZE_T*5`($sp) + $POP r28,`$FRAME-$SIZE_T*4`($sp) + $POP r29,`$FRAME-$SIZE_T*3`($sp) + $POP r30,`$FRAME-$SIZE_T*2`($sp) + $POP r31,`$FRAME-$SIZE_T*1`($sp) + addi $sp,$sp,$FRAME +Labort: + blr + .long 0 + .byte 0,12,4,1,0x80,5,4,0 +.size .poly1305_blocks,.-.poly1305_blocks + +.globl .poly1305_emit +.align 4 +.poly1305_emit: + ld $h0,0($ctx) # load hash + ld $h1,8($ctx) + ld $h2,16($ctx) + ld $padbit,0($nonce) # load nonce + ld $nonce,8($nonce) + + addic $d0,$h0,5 # compare to modulus + addze $d1,$h1 + addze $d2,$h2 + + srdi $mask,$d2,2 # did it carry/borrow? + neg $mask,$mask + + andc $h0,$h0,$mask + and $d0,$d0,$mask + andc $h1,$h1,$mask + and $d1,$d1,$mask + or $h0,$h0,$d0 + or $h1,$h1,$d1 +___ +$code.=<<___ if (!$LITTLE_ENDIAN); + rotldi $padbit,$padbit,32 # flip nonce words + rotldi $nonce,$nonce,32 +___ +$code.=<<___; + addc $h0,$h0,$padbit # accumulate nonce + adde $h1,$h1,$nonce +___ +$code.=<<___ if ($LITTLE_ENDIAN); + std $h0,0($mac) # write result + std $h1,8($mac) +___ +$code.=<<___ if (!$LITTLE_ENDIAN); + extrdi r0,$h0,32,0 + li $d0,4 + stwbrx $h0,0,$mac # write result + extrdi $h0,$h1,32,0 + li $d1,8 + stwbrx r0,$d0,$mac + li $d2,12 + stwbrx $h1,$d1,$mac + stwbrx $h0,$d2,$mac +___ +$code.=<<___; + blr + .long 0 + .byte 0,12,0x14,0,0,0,3,0 +.size .poly1305_emit,.-.poly1305_emit +___ + } else { +############################################################################### +# base 2^32 implementation + +my ($h0,$h1,$h2,$h3,$h4, $r0,$r1,$r2,$r3, $s1,$s2,$s3, + $t0,$t1,$t2,$t3, $D0,$D1,$D2,$D3, $d0,$d1,$d2,$d3 + ) = map("r$_",(7..12,14..31)); + +$code.=<<___; +.globl .poly1305_init_int +.align 4 +.poly1305_init_int: + xor r0,r0,r0 + stw r0,0($ctx) # zero hash value + stw r0,4($ctx) + stw r0,8($ctx) + stw r0,12($ctx) + stw r0,16($ctx) + + $UCMP $inp,r0 + beq- Lno_key +___ +$code.=<<___ if ($LITTLE_ENDIAN); + lw $h0,0($inp) # load key material + lw $h1,4($inp) + lw $h2,8($inp) + lw $h3,12($inp) +___ +$code.=<<___ if (!$LITTLE_ENDIAN); + li $h1,4 + lwbrx $h0,0,$inp # load key material + li $h2,8 + lwbrx $h1,$h1,$inp + li $h3,12 + lwbrx $h2,$h2,$inp + lwbrx $h3,$h3,$inp +___ +$code.=<<___; + lis $mask,0xf000 # 0xf0000000 + li $r0,-4 + andc $r0,$r0,$mask # 0x0ffffffc + + andc $h0,$h0,$mask + and $h1,$h1,$r0 + and $h2,$h2,$r0 + and $h3,$h3,$r0 + + stw $h0,32($ctx) # store key + stw $h1,36($ctx) + stw $h2,40($ctx) + stw $h3,44($ctx) + +Lno_key: + xor r3,r3,r3 + blr + .long 0 + .byte 0,12,0x14,0,0,0,2,0 +.size .poly1305_init_int,.-.poly1305_init_int + +.globl .poly1305_blocks +.align 4 +.poly1305_blocks: + srwi. $len,$len,4 + beq- Labort + + $STU $sp,-$FRAME($sp) + mflr r0 + $PUSH r14,`$FRAME-$SIZE_T*18`($sp) + $PUSH r15,`$FRAME-$SIZE_T*17`($sp) + $PUSH r16,`$FRAME-$SIZE_T*16`($sp) + $PUSH r17,`$FRAME-$SIZE_T*15`($sp) + $PUSH r18,`$FRAME-$SIZE_T*14`($sp) + $PUSH r19,`$FRAME-$SIZE_T*13`($sp) + $PUSH r20,`$FRAME-$SIZE_T*12`($sp) + $PUSH r21,`$FRAME-$SIZE_T*11`($sp) + $PUSH r22,`$FRAME-$SIZE_T*10`($sp) + $PUSH r23,`$FRAME-$SIZE_T*9`($sp) + $PUSH r24,`$FRAME-$SIZE_T*8`($sp) + $PUSH r25,`$FRAME-$SIZE_T*7`($sp) + $PUSH r26,`$FRAME-$SIZE_T*6`($sp) + $PUSH r27,`$FRAME-$SIZE_T*5`($sp) + $PUSH r28,`$FRAME-$SIZE_T*4`($sp) + $PUSH r29,`$FRAME-$SIZE_T*3`($sp) + $PUSH r30,`$FRAME-$SIZE_T*2`($sp) + $PUSH r31,`$FRAME-$SIZE_T*1`($sp) + $PUSH r0,`$FRAME+$LRSAVE`($sp) + + lwz $r0,32($ctx) # load key + lwz $r1,36($ctx) + lwz $r2,40($ctx) + lwz $r3,44($ctx) + + lwz $h0,0($ctx) # load hash value + lwz $h1,4($ctx) + lwz $h2,8($ctx) + lwz $h3,12($ctx) + lwz $h4,16($ctx) + + srwi $s1,$r1,2 + srwi $s2,$r2,2 + srwi $s3,$r3,2 + add $s1,$s1,$r1 # si = ri + ri>>2 + add $s2,$s2,$r2 + add $s3,$s3,$r3 + mtctr $len + li $mask,3 + b Loop + +.align 4 +Loop: +___ +$code.=<<___ if ($LITTLE_ENDIAN); + lwz $d0,0($inp) # load input + lwz $d1,4($inp) + lwz $d2,8($inp) + lwz $d3,12($inp) +___ +$code.=<<___ if (!$LITTLE_ENDIAN); + li $d1,4 + lwbrx $d0,0,$inp # load input + li $d2,8 + lwbrx $d1,$d1,$inp + li $d3,12 + lwbrx $d2,$d2,$inp + lwbrx $d3,$d3,$inp +___ +$code.=<<___; + addi $inp,$inp,16 + + addc $h0,$h0,$d0 # accumulate input + adde $h1,$h1,$d1 + adde $h2,$h2,$d2 + + mullw $d0,$h0,$r0 # h0*r0 + mulhwu $D0,$h0,$r0 + + mullw $d1,$h0,$r1 # h0*r1 + mulhwu $D1,$h0,$r1 + + mullw $d2,$h0,$r2 # h0*r2 + mulhwu $D2,$h0,$r2 + + adde $h3,$h3,$d3 + adde $h4,$h4,$padbit + + mullw $d3,$h0,$r3 # h0*r3 + mulhwu $D3,$h0,$r3 + + mullw $t0,$h1,$s3 # h1*s3 + mulhwu $t1,$h1,$s3 + + mullw $t2,$h1,$r0 # h1*r0 + mulhwu $t3,$h1,$r0 + addc $d0,$d0,$t0 + adde $D0,$D0,$t1 + + mullw $t0,$h1,$r1 # h1*r1 + mulhwu $t1,$h1,$r1 + addc $d1,$d1,$t2 + adde $D1,$D1,$t3 + + mullw $t2,$h1,$r2 # h1*r2 + mulhwu $t3,$h1,$r2 + addc $d2,$d2,$t0 + adde $D2,$D2,$t1 + + mullw $t0,$h2,$s2 # h2*s2 + mulhwu $t1,$h2,$s2 + addc $d3,$d3,$t2 + adde $D3,$D3,$t3 + + mullw $t2,$h2,$s3 # h2*s3 + mulhwu $t3,$h2,$s3 + addc $d0,$d0,$t0 + adde $D0,$D0,$t1 + + mullw $t0,$h2,$r0 # h2*r0 + mulhwu $t1,$h2,$r0 + addc $d1,$d1,$t2 + adde $D1,$D1,$t3 + + mullw $t2,$h2,$r1 # h2*r1 + mulhwu $t3,$h2,$r1 + addc $d2,$d2,$t0 + adde $D2,$D2,$t1 + + mullw $t0,$h3,$s1 # h3*s1 + mulhwu $t1,$h3,$s1 + addc $d3,$d3,$t2 + adde $D3,$D3,$t3 + + mullw $t2,$h3,$s2 # h3*s2 + mulhwu $t3,$h3,$s2 + addc $d0,$d0,$t0 + adde $D0,$D0,$t1 + + mullw $t0,$h3,$s3 # h3*s3 + mulhwu $t1,$h3,$s3 + addc $d1,$d1,$t2 + adde $D1,$D1,$t3 + + mullw $t2,$h3,$r0 # h3*r0 + mulhwu $t3,$h3,$r0 + addc $d2,$d2,$t0 + adde $D2,$D2,$t1 + + mullw $t0,$h4,$s1 # h4*s1 + addc $d3,$d3,$t2 + adde $D3,$D3,$t3 + addc $d1,$d1,$t0 + + mullw $t1,$h4,$s2 # h4*s2 + addze $D1,$D1 + addc $d2,$d2,$t1 + addze $D2,$D2 + + mullw $t2,$h4,$s3 # h4*s3 + addc $d3,$d3,$t2 + addze $D3,$D3 + + mullw $h4,$h4,$r0 # h4*r0 + + addc $h1,$d1,$D0 + adde $h2,$d2,$D1 + adde $h3,$d3,$D2 + adde $h4,$h4,$D3 + + andc $D0,$h4,$mask # final reduction step + and $h4,$h4,$mask + srwi $D1,$D0,2 + add $D0,$D0,$D1 + addc $h0,$d0,$D0 + addze $h1,$h1 + addze $h2,$h2 + addze $h3,$h3 + addze $h4,$h4 + + bdnz Loop + + stw $h0,0($ctx) # store hash value + stw $h1,4($ctx) + stw $h2,8($ctx) + stw $h3,12($ctx) + stw $h4,16($ctx) + + $POP r14,`$FRAME-$SIZE_T*18`($sp) + $POP r15,`$FRAME-$SIZE_T*17`($sp) + $POP r16,`$FRAME-$SIZE_T*16`($sp) + $POP r17,`$FRAME-$SIZE_T*15`($sp) + $POP r18,`$FRAME-$SIZE_T*14`($sp) + $POP r19,`$FRAME-$SIZE_T*13`($sp) + $POP r20,`$FRAME-$SIZE_T*12`($sp) + $POP r21,`$FRAME-$SIZE_T*11`($sp) + $POP r22,`$FRAME-$SIZE_T*10`($sp) + $POP r23,`$FRAME-$SIZE_T*9`($sp) + $POP r24,`$FRAME-$SIZE_T*8`($sp) + $POP r25,`$FRAME-$SIZE_T*7`($sp) + $POP r26,`$FRAME-$SIZE_T*6`($sp) + $POP r27,`$FRAME-$SIZE_T*5`($sp) + $POP r28,`$FRAME-$SIZE_T*4`($sp) + $POP r29,`$FRAME-$SIZE_T*3`($sp) + $POP r30,`$FRAME-$SIZE_T*2`($sp) + $POP r31,`$FRAME-$SIZE_T*1`($sp) + addi $sp,$sp,$FRAME +Labort: + blr + .long 0 + .byte 0,12,4,1,0x80,18,4,0 +.size .poly1305_blocks,.-.poly1305_blocks + +.globl .poly1305_emit +.align 4 +.poly1305_emit: + $STU $sp,-$FRAME($sp) + mflr r0 + $PUSH r28,`$FRAME-$SIZE_T*4`($sp) + $PUSH r29,`$FRAME-$SIZE_T*3`($sp) + $PUSH r30,`$FRAME-$SIZE_T*2`($sp) + $PUSH r31,`$FRAME-$SIZE_T*1`($sp) + $PUSH r0,`$FRAME+$LRSAVE`($sp) + + lwz $h0,0($ctx) # load hash + lwz $h1,4($ctx) + lwz $h2,8($ctx) + lwz $h3,12($ctx) + lwz $h4,16($ctx) + + addic $d0,$h0,5 # compare to modulus + addze $d1,$h1 + addze $d2,$h2 + addze $d3,$h3 + addze $mask,$h4 + + srwi $mask,$mask,2 # did it carry/borrow? + neg $mask,$mask + + andc $h0,$h0,$mask + and $d0,$d0,$mask + andc $h1,$h1,$mask + and $d1,$d1,$mask + or $h0,$h0,$d0 + lwz $d0,0($nonce) # load nonce + andc $h2,$h2,$mask + and $d2,$d2,$mask + or $h1,$h1,$d1 + lwz $d1,4($nonce) + andc $h3,$h3,$mask + and $d3,$d3,$mask + or $h2,$h2,$d2 + lwz $d2,8($nonce) + or $h3,$h3,$d3 + lwz $d3,12($nonce) + + addc $h0,$h0,$d0 # accumulate nonce + adde $h1,$h1,$d1 + adde $h2,$h2,$d2 + adde $h3,$h3,$d3 +___ +$code.=<<___ if ($LITTLE_ENDIAN); + stw $h0,0($mac) # write result + stw $h1,4($mac) + stw $h2,8($mac) + stw $h3,12($mac) +___ +$code.=<<___ if (!$LITTLE_ENDIAN); + li $d1,4 + stwbrx $h0,0,$mac # write result + li $d2,8 + stwbrx $h1,$d1,$mac + li $d3,12 + stwbrx $h2,$d2,$mac + stwbrx $h3,$d3,$mac +___ +$code.=<<___; + $POP r28,`$FRAME-$SIZE_T*4`($sp) + $POP r29,`$FRAME-$SIZE_T*3`($sp) + $POP r30,`$FRAME-$SIZE_T*2`($sp) + $POP r31,`$FRAME-$SIZE_T*1`($sp) + addi $sp,$sp,$FRAME + blr + .long 0 + .byte 0,12,4,1,0x80,4,3,0 +.size .poly1305_emit,.-.poly1305_emit +___ + } +$code.=<<___; +.asciz "Poly1305 for PPC, CRYPTOGAMS by " +___ + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-ppcfp.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-ppcfp.pl new file mode 100755 index 000000000..09f818584 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-ppcfp.pl @@ -0,0 +1,739 @@ +#! /usr/bin/env perl +# Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# This module implements Poly1305 hash for PowerPC FPU. +# +# June 2015 +# +# Numbers are cycles per processed byte with poly1305_blocks alone, +# and improvement coefficients relative to gcc-generated code. +# +# Freescale e300 9.78/+30% +# PPC74x0 6.92/+50% +# PPC970 6.03/+80% +# POWER7 3.50/+30% +# POWER8 3.75/+10% + +$flavour = shift; + +if ($flavour =~ /64/) { + $SIZE_T =8; + $LRSAVE =2*$SIZE_T; + $UCMP ="cmpld"; + $STU ="stdu"; + $POP ="ld"; + $PUSH ="std"; +} elsif ($flavour =~ /32/) { + $SIZE_T =4; + $LRSAVE =$SIZE_T; + $UCMP ="cmplw"; + $STU ="stwu"; + $POP ="lwz"; + $PUSH ="stw"; +} else { die "nonsense $flavour"; } + +$LITTLE_ENDIAN = ($flavour=~/le$/) ? 4 : 0; + +$LWXLE = $LITTLE_ENDIAN ? "lwzx" : "lwbrx"; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or +die "can't locate ppc-xlate.pl"; + +open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!"; + +$LOCALS=6*$SIZE_T; +$FRAME=$LOCALS+6*8+18*8; + +my $sp="r1"; + +my ($ctx,$inp,$len,$padbit) = map("r$_",(3..6)); +my ($in0,$in1,$in2,$in3,$i1,$i2,$i3) = map("r$_",(7..12,6)); + +my ($h0lo,$h0hi,$h1lo,$h1hi,$h2lo,$h2hi,$h3lo,$h3hi, + $two0,$two32,$two64,$two96,$two130,$five_two130, + $r0lo,$r0hi,$r1lo,$r1hi,$r2lo,$r2hi, + $s2lo,$s2hi,$s3lo,$s3hi, + $c0lo,$c0hi,$c1lo,$c1hi,$c2lo,$c2hi,$c3lo,$c3hi) = map("f$_",(0..31)); +# borrowings +my ($r3lo,$r3hi,$s1lo,$s1hi) = ($c0lo,$c0hi,$c1lo,$c1hi); +my ($x0,$x1,$x2,$x3) = ($c2lo,$c2hi,$c3lo,$c3hi); +my ($y0,$y1,$y2,$y3) = ($c3lo,$c3hi,$c1lo,$c1hi); + +$code.=<<___; +.machine "any" +.text + +.globl .poly1305_init_fpu +.align 6 +.poly1305_init_fpu: + $STU $sp,-$LOCALS($sp) # minimal frame + mflr $padbit + $PUSH $padbit,`$LOCALS+$LRSAVE`($sp) + + bl LPICmeup + + xor r0,r0,r0 + mtlr $padbit # restore lr + + lfd $two0,8*0($len) # load constants + lfd $two32,8*1($len) + lfd $two64,8*2($len) + lfd $two96,8*3($len) + lfd $two130,8*4($len) + lfd $five_two130,8*5($len) + + stfd $two0,8*0($ctx) # initial hash value, biased 0 + stfd $two32,8*1($ctx) + stfd $two64,8*2($ctx) + stfd $two96,8*3($ctx) + + $UCMP $inp,r0 + beq- Lno_key + + lfd $h3lo,8*13($len) # new fpscr + mffs $h3hi # old fpscr + + stfd $two0,8*4($ctx) # key "template" + stfd $two32,8*5($ctx) + stfd $two64,8*6($ctx) + stfd $two96,8*7($ctx) + + li $in1,4 + li $in2,8 + li $in3,12 + $LWXLE $in0,0,$inp # load key + $LWXLE $in1,$in1,$inp + $LWXLE $in2,$in2,$inp + $LWXLE $in3,$in3,$inp + + lis $i1,0xf000 # 0xf0000000 + ori $i2,$i1,3 # 0xf0000003 + andc $in0,$in0,$i1 # &=0x0fffffff + andc $in1,$in1,$i2 # &=0x0ffffffc + andc $in2,$in2,$i2 + andc $in3,$in3,$i2 + + stw $in0,`8*4+(4^$LITTLE_ENDIAN)`($ctx) # fill "template" + stw $in1,`8*5+(4^$LITTLE_ENDIAN)`($ctx) + stw $in2,`8*6+(4^$LITTLE_ENDIAN)`($ctx) + stw $in3,`8*7+(4^$LITTLE_ENDIAN)`($ctx) + + mtfsf 255,$h3lo # fpscr + stfd $two0,8*18($ctx) # copy constants to context + stfd $two32,8*19($ctx) + stfd $two64,8*20($ctx) + stfd $two96,8*21($ctx) + stfd $two130,8*22($ctx) + stfd $five_two130,8*23($ctx) + + lfd $h0lo,8*4($ctx) # load [biased] key + lfd $h1lo,8*5($ctx) + lfd $h2lo,8*6($ctx) + lfd $h3lo,8*7($ctx) + + fsub $h0lo,$h0lo,$two0 # r0 + fsub $h1lo,$h1lo,$two32 # r1 + fsub $h2lo,$h2lo,$two64 # r2 + fsub $h3lo,$h3lo,$two96 # r3 + + lfd $two0,8*6($len) # more constants + lfd $two32,8*7($len) + lfd $two64,8*8($len) + lfd $two96,8*9($len) + + fmul $h1hi,$h1lo,$five_two130 # s1 + fmul $h2hi,$h2lo,$five_two130 # s2 + stfd $h3hi,8*15($ctx) # borrow slot for original fpscr + fmul $h3hi,$h3lo,$five_two130 # s3 + + fadd $h0hi,$h0lo,$two0 + stfd $h1hi,8*12($ctx) # put aside for now + fadd $h1hi,$h1lo,$two32 + stfd $h2hi,8*13($ctx) + fadd $h2hi,$h2lo,$two64 + stfd $h3hi,8*14($ctx) + fadd $h3hi,$h3lo,$two96 + + fsub $h0hi,$h0hi,$two0 + fsub $h1hi,$h1hi,$two32 + fsub $h2hi,$h2hi,$two64 + fsub $h3hi,$h3hi,$two96 + + lfd $two0,8*10($len) # more constants + lfd $two32,8*11($len) + lfd $two64,8*12($len) + + fsub $h0lo,$h0lo,$h0hi + fsub $h1lo,$h1lo,$h1hi + fsub $h2lo,$h2lo,$h2hi + fsub $h3lo,$h3lo,$h3hi + + stfd $h0hi,8*5($ctx) # r0hi + stfd $h1hi,8*7($ctx) # r1hi + stfd $h2hi,8*9($ctx) # r2hi + stfd $h3hi,8*11($ctx) # r3hi + + stfd $h0lo,8*4($ctx) # r0lo + stfd $h1lo,8*6($ctx) # r1lo + stfd $h2lo,8*8($ctx) # r2lo + stfd $h3lo,8*10($ctx) # r3lo + + lfd $h1lo,8*12($ctx) # s1 + lfd $h2lo,8*13($ctx) # s2 + lfd $h3lo,8*14($ctx) # s3 + lfd $h0lo,8*15($ctx) # pull original fpscr + + fadd $h1hi,$h1lo,$two0 + fadd $h2hi,$h2lo,$two32 + fadd $h3hi,$h3lo,$two64 + + fsub $h1hi,$h1hi,$two0 + fsub $h2hi,$h2hi,$two32 + fsub $h3hi,$h3hi,$two64 + + fsub $h1lo,$h1lo,$h1hi + fsub $h2lo,$h2lo,$h2hi + fsub $h3lo,$h3lo,$h3hi + + stfd $h1hi,8*13($ctx) # s1hi + stfd $h2hi,8*15($ctx) # s2hi + stfd $h3hi,8*17($ctx) # s3hi + + stfd $h1lo,8*12($ctx) # s1lo + stfd $h2lo,8*14($ctx) # s2lo + stfd $h3lo,8*16($ctx) # s3lo + + mtfsf 255,$h0lo # restore fpscr +Lno_key: + xor r3,r3,r3 + addi $sp,$sp,$LOCALS + blr + .long 0 + .byte 0,12,4,1,0x80,0,2,0 +.size .poly1305_init_fpu,.-.poly1305_init_fpu + +.globl .poly1305_blocks_fpu +.align 4 +.poly1305_blocks_fpu: + srwi. $len,$len,4 + beq- Labort + + $STU $sp,-$FRAME($sp) + mflr r0 + stfd f14,`$FRAME-8*18`($sp) + stfd f15,`$FRAME-8*17`($sp) + stfd f16,`$FRAME-8*16`($sp) + stfd f17,`$FRAME-8*15`($sp) + stfd f18,`$FRAME-8*14`($sp) + stfd f19,`$FRAME-8*13`($sp) + stfd f20,`$FRAME-8*12`($sp) + stfd f21,`$FRAME-8*11`($sp) + stfd f22,`$FRAME-8*10`($sp) + stfd f23,`$FRAME-8*9`($sp) + stfd f24,`$FRAME-8*8`($sp) + stfd f25,`$FRAME-8*7`($sp) + stfd f26,`$FRAME-8*6`($sp) + stfd f27,`$FRAME-8*5`($sp) + stfd f28,`$FRAME-8*4`($sp) + stfd f29,`$FRAME-8*3`($sp) + stfd f30,`$FRAME-8*2`($sp) + stfd f31,`$FRAME-8*1`($sp) + $PUSH r0,`$FRAME+$LRSAVE`($sp) + + xor r0,r0,r0 + li $in3,1 + mtctr $len + neg $len,$len + stw r0,`$LOCALS+8*4+(0^$LITTLE_ENDIAN)`($sp) + stw $in3,`$LOCALS+8*4+(4^$LITTLE_ENDIAN)`($sp) + + lfd $two0,8*18($ctx) # load constants + lfd $two32,8*19($ctx) + lfd $two64,8*20($ctx) + lfd $two96,8*21($ctx) + lfd $two130,8*22($ctx) + lfd $five_two130,8*23($ctx) + + lfd $h0lo,8*0($ctx) # load [biased] hash value + lfd $h1lo,8*1($ctx) + lfd $h2lo,8*2($ctx) + lfd $h3lo,8*3($ctx) + + stfd $two0,`$LOCALS+8*0`($sp) # input "template" + oris $in3,$padbit,`(1023+52+96)<<4` + stfd $two32,`$LOCALS+8*1`($sp) + stfd $two64,`$LOCALS+8*2`($sp) + stw $in3,`$LOCALS+8*3+(0^$LITTLE_ENDIAN)`($sp) + + li $i1,4 + li $i2,8 + li $i3,12 + $LWXLE $in0,0,$inp # load input + $LWXLE $in1,$i1,$inp + $LWXLE $in2,$i2,$inp + $LWXLE $in3,$i3,$inp + addi $inp,$inp,16 + + stw $in0,`$LOCALS+8*0+(4^$LITTLE_ENDIAN)`($sp) # fill "template" + stw $in1,`$LOCALS+8*1+(4^$LITTLE_ENDIAN)`($sp) + stw $in2,`$LOCALS+8*2+(4^$LITTLE_ENDIAN)`($sp) + stw $in3,`$LOCALS+8*3+(4^$LITTLE_ENDIAN)`($sp) + + mffs $x0 # original fpscr + lfd $x1,`$LOCALS+8*4`($sp) # new fpscr + lfd $r0lo,8*4($ctx) # load key + lfd $r0hi,8*5($ctx) + lfd $r1lo,8*6($ctx) + lfd $r1hi,8*7($ctx) + lfd $r2lo,8*8($ctx) + lfd $r2hi,8*9($ctx) + lfd $r3lo,8*10($ctx) + lfd $r3hi,8*11($ctx) + lfd $s1lo,8*12($ctx) + lfd $s1hi,8*13($ctx) + lfd $s2lo,8*14($ctx) + lfd $s2hi,8*15($ctx) + lfd $s3lo,8*16($ctx) + lfd $s3hi,8*17($ctx) + + stfd $x0,`$LOCALS+8*4`($sp) # save original fpscr + mtfsf 255,$x1 + + addic $len,$len,1 + addze r0,r0 + slwi. r0,r0,4 + sub $inp,$inp,r0 # conditional rewind + + lfd $x0,`$LOCALS+8*0`($sp) + lfd $x1,`$LOCALS+8*1`($sp) + lfd $x2,`$LOCALS+8*2`($sp) + lfd $x3,`$LOCALS+8*3`($sp) + + fsub $h0lo,$h0lo,$two0 # de-bias hash value + $LWXLE $in0,0,$inp # modulo-scheduled input load + fsub $h1lo,$h1lo,$two32 + $LWXLE $in1,$i1,$inp + fsub $h2lo,$h2lo,$two64 + $LWXLE $in2,$i2,$inp + fsub $h3lo,$h3lo,$two96 + $LWXLE $in3,$i3,$inp + + fsub $x0,$x0,$two0 # de-bias input + addi $inp,$inp,16 + fsub $x1,$x1,$two32 + fsub $x2,$x2,$two64 + fsub $x3,$x3,$two96 + + fadd $x0,$x0,$h0lo # accumulate input + stw $in0,`$LOCALS+8*0+(4^$LITTLE_ENDIAN)`($sp) + fadd $x1,$x1,$h1lo + stw $in1,`$LOCALS+8*1+(4^$LITTLE_ENDIAN)`($sp) + fadd $x2,$x2,$h2lo + stw $in2,`$LOCALS+8*2+(4^$LITTLE_ENDIAN)`($sp) + fadd $x3,$x3,$h3lo + stw $in3,`$LOCALS+8*3+(4^$LITTLE_ENDIAN)`($sp) + + b Lentry + +.align 4 +Loop: + fsub $y0,$y0,$two0 # de-bias input + addic $len,$len,1 + fsub $y1,$y1,$two32 + addze r0,r0 + fsub $y2,$y2,$two64 + slwi. r0,r0,4 + fsub $y3,$y3,$two96 + sub $inp,$inp,r0 # conditional rewind + + fadd $h0lo,$h0lo,$y0 # accumulate input + fadd $h0hi,$h0hi,$y1 + fadd $h2lo,$h2lo,$y2 + fadd $h2hi,$h2hi,$y3 + + ######################################### base 2^48 -> base 2^32 + fadd $c1lo,$h1lo,$two64 + $LWXLE $in0,0,$inp # modulo-scheduled input load + fadd $c1hi,$h1hi,$two64 + $LWXLE $in1,$i1,$inp + fadd $c3lo,$h3lo,$two130 + $LWXLE $in2,$i2,$inp + fadd $c3hi,$h3hi,$two130 + $LWXLE $in3,$i3,$inp + fadd $c0lo,$h0lo,$two32 + addi $inp,$inp,16 + fadd $c0hi,$h0hi,$two32 + fadd $c2lo,$h2lo,$two96 + fadd $c2hi,$h2hi,$two96 + + fsub $c1lo,$c1lo,$two64 + stw $in0,`$LOCALS+8*0+(4^$LITTLE_ENDIAN)`($sp) # fill "template" + fsub $c1hi,$c1hi,$two64 + stw $in1,`$LOCALS+8*1+(4^$LITTLE_ENDIAN)`($sp) + fsub $c3lo,$c3lo,$two130 + stw $in2,`$LOCALS+8*2+(4^$LITTLE_ENDIAN)`($sp) + fsub $c3hi,$c3hi,$two130 + stw $in3,`$LOCALS+8*3+(4^$LITTLE_ENDIAN)`($sp) + fsub $c0lo,$c0lo,$two32 + fsub $c0hi,$c0hi,$two32 + fsub $c2lo,$c2lo,$two96 + fsub $c2hi,$c2hi,$two96 + + fsub $h1lo,$h1lo,$c1lo + fsub $h1hi,$h1hi,$c1hi + fsub $h3lo,$h3lo,$c3lo + fsub $h3hi,$h3hi,$c3hi + fsub $h2lo,$h2lo,$c2lo + fsub $h2hi,$h2hi,$c2hi + fsub $h0lo,$h0lo,$c0lo + fsub $h0hi,$h0hi,$c0hi + + fadd $h1lo,$h1lo,$c0lo + fadd $h1hi,$h1hi,$c0hi + fadd $h3lo,$h3lo,$c2lo + fadd $h3hi,$h3hi,$c2hi + fadd $h2lo,$h2lo,$c1lo + fadd $h2hi,$h2hi,$c1hi + fmadd $h0lo,$c3lo,$five_two130,$h0lo + fmadd $h0hi,$c3hi,$five_two130,$h0hi + + fadd $x1,$h1lo,$h1hi + lfd $s1lo,8*12($ctx) # reload constants + fadd $x3,$h3lo,$h3hi + lfd $s1hi,8*13($ctx) + fadd $x2,$h2lo,$h2hi + lfd $r3lo,8*10($ctx) + fadd $x0,$h0lo,$h0hi + lfd $r3hi,8*11($ctx) +Lentry: + fmul $h0lo,$s3lo,$x1 + fmul $h0hi,$s3hi,$x1 + fmul $h2lo,$r1lo,$x1 + fmul $h2hi,$r1hi,$x1 + fmul $h1lo,$r0lo,$x1 + fmul $h1hi,$r0hi,$x1 + fmul $h3lo,$r2lo,$x1 + fmul $h3hi,$r2hi,$x1 + + fmadd $h0lo,$s1lo,$x3,$h0lo + fmadd $h0hi,$s1hi,$x3,$h0hi + fmadd $h2lo,$s3lo,$x3,$h2lo + fmadd $h2hi,$s3hi,$x3,$h2hi + fmadd $h1lo,$s2lo,$x3,$h1lo + fmadd $h1hi,$s2hi,$x3,$h1hi + fmadd $h3lo,$r0lo,$x3,$h3lo + fmadd $h3hi,$r0hi,$x3,$h3hi + + fmadd $h0lo,$s2lo,$x2,$h0lo + fmadd $h0hi,$s2hi,$x2,$h0hi + fmadd $h2lo,$r0lo,$x2,$h2lo + fmadd $h2hi,$r0hi,$x2,$h2hi + fmadd $h1lo,$s3lo,$x2,$h1lo + fmadd $h1hi,$s3hi,$x2,$h1hi + fmadd $h3lo,$r1lo,$x2,$h3lo + fmadd $h3hi,$r1hi,$x2,$h3hi + + fmadd $h0lo,$r0lo,$x0,$h0lo + lfd $y0,`$LOCALS+8*0`($sp) # load [biased] input + fmadd $h0hi,$r0hi,$x0,$h0hi + lfd $y1,`$LOCALS+8*1`($sp) + fmadd $h2lo,$r2lo,$x0,$h2lo + lfd $y2,`$LOCALS+8*2`($sp) + fmadd $h2hi,$r2hi,$x0,$h2hi + lfd $y3,`$LOCALS+8*3`($sp) + fmadd $h1lo,$r1lo,$x0,$h1lo + fmadd $h1hi,$r1hi,$x0,$h1hi + fmadd $h3lo,$r3lo,$x0,$h3lo + fmadd $h3hi,$r3hi,$x0,$h3hi + + bdnz Loop + + ######################################### base 2^48 -> base 2^32 + fadd $c0lo,$h0lo,$two32 + fadd $c0hi,$h0hi,$two32 + fadd $c2lo,$h2lo,$two96 + fadd $c2hi,$h2hi,$two96 + fadd $c1lo,$h1lo,$two64 + fadd $c1hi,$h1hi,$two64 + fadd $c3lo,$h3lo,$two130 + fadd $c3hi,$h3hi,$two130 + + fsub $c0lo,$c0lo,$two32 + fsub $c0hi,$c0hi,$two32 + fsub $c2lo,$c2lo,$two96 + fsub $c2hi,$c2hi,$two96 + fsub $c1lo,$c1lo,$two64 + fsub $c1hi,$c1hi,$two64 + fsub $c3lo,$c3lo,$two130 + fsub $c3hi,$c3hi,$two130 + + fsub $h1lo,$h1lo,$c1lo + fsub $h1hi,$h1hi,$c1hi + fsub $h3lo,$h3lo,$c3lo + fsub $h3hi,$h3hi,$c3hi + fsub $h2lo,$h2lo,$c2lo + fsub $h2hi,$h2hi,$c2hi + fsub $h0lo,$h0lo,$c0lo + fsub $h0hi,$h0hi,$c0hi + + fadd $h1lo,$h1lo,$c0lo + fadd $h1hi,$h1hi,$c0hi + fadd $h3lo,$h3lo,$c2lo + fadd $h3hi,$h3hi,$c2hi + fadd $h2lo,$h2lo,$c1lo + fadd $h2hi,$h2hi,$c1hi + fmadd $h0lo,$c3lo,$five_two130,$h0lo + fmadd $h0hi,$c3hi,$five_two130,$h0hi + + fadd $x1,$h1lo,$h1hi + fadd $x3,$h3lo,$h3hi + fadd $x2,$h2lo,$h2hi + fadd $x0,$h0lo,$h0hi + + lfd $h0lo,`$LOCALS+8*4`($sp) # pull saved fpscr + fadd $x1,$x1,$two32 # bias + fadd $x3,$x3,$two96 + fadd $x2,$x2,$two64 + fadd $x0,$x0,$two0 + + stfd $x1,8*1($ctx) # store [biased] hash value + stfd $x3,8*3($ctx) + stfd $x2,8*2($ctx) + stfd $x0,8*0($ctx) + + mtfsf 255,$h0lo # restore original fpscr + lfd f14,`$FRAME-8*18`($sp) + lfd f15,`$FRAME-8*17`($sp) + lfd f16,`$FRAME-8*16`($sp) + lfd f17,`$FRAME-8*15`($sp) + lfd f18,`$FRAME-8*14`($sp) + lfd f19,`$FRAME-8*13`($sp) + lfd f20,`$FRAME-8*12`($sp) + lfd f21,`$FRAME-8*11`($sp) + lfd f22,`$FRAME-8*10`($sp) + lfd f23,`$FRAME-8*9`($sp) + lfd f24,`$FRAME-8*8`($sp) + lfd f25,`$FRAME-8*7`($sp) + lfd f26,`$FRAME-8*6`($sp) + lfd f27,`$FRAME-8*5`($sp) + lfd f28,`$FRAME-8*4`($sp) + lfd f29,`$FRAME-8*3`($sp) + lfd f30,`$FRAME-8*2`($sp) + lfd f31,`$FRAME-8*1`($sp) + addi $sp,$sp,$FRAME +Labort: + blr + .long 0 + .byte 0,12,4,1,0x80,0,4,0 +.size .poly1305_blocks_fpu,.-.poly1305_blocks_fpu +___ +{ +my ($mac,$nonce)=($inp,$len); + +my ($h0,$h1,$h2,$h3,$h4, $d0,$d1,$d2,$d3 + ) = map("r$_",(7..11,28..31)); +my $mask = "r0"; +my $FRAME = (6+4)*$SIZE_T; + +$code.=<<___; +.globl .poly1305_emit_fpu +.align 4 +.poly1305_emit_fpu: + $STU $sp,-$FRAME($sp) + mflr r0 + $PUSH r28,`$FRAME-$SIZE_T*4`($sp) + $PUSH r29,`$FRAME-$SIZE_T*3`($sp) + $PUSH r30,`$FRAME-$SIZE_T*2`($sp) + $PUSH r31,`$FRAME-$SIZE_T*1`($sp) + $PUSH r0,`$FRAME+$LRSAVE`($sp) + + lwz $d0,`8*0+(0^$LITTLE_ENDIAN)`($ctx) # load hash + lwz $h0,`8*0+(4^$LITTLE_ENDIAN)`($ctx) + lwz $d1,`8*1+(0^$LITTLE_ENDIAN)`($ctx) + lwz $h1,`8*1+(4^$LITTLE_ENDIAN)`($ctx) + lwz $d2,`8*2+(0^$LITTLE_ENDIAN)`($ctx) + lwz $h2,`8*2+(4^$LITTLE_ENDIAN)`($ctx) + lwz $d3,`8*3+(0^$LITTLE_ENDIAN)`($ctx) + lwz $h3,`8*3+(4^$LITTLE_ENDIAN)`($ctx) + + lis $mask,0xfff0 + andc $d0,$d0,$mask # mask exponent + andc $d1,$d1,$mask + andc $d2,$d2,$mask + andc $d3,$d3,$mask # can be partially reduced... + li $mask,3 + + srwi $padbit,$d3,2 # ... so reduce + and $h4,$d3,$mask + andc $d3,$d3,$mask + add $d3,$d3,$padbit +___ + if ($SIZE_T==4) { +$code.=<<___; + addc $h0,$h0,$d3 + adde $h1,$h1,$d0 + adde $h2,$h2,$d1 + adde $h3,$h3,$d2 + addze $h4,$h4 + + addic $d0,$h0,5 # compare to modulus + addze $d1,$h1 + addze $d2,$h2 + addze $d3,$h3 + addze $mask,$h4 + + srwi $mask,$mask,2 # did it carry/borrow? + neg $mask,$mask + srawi $mask,$mask,31 # mask + + andc $h0,$h0,$mask + and $d0,$d0,$mask + andc $h1,$h1,$mask + and $d1,$d1,$mask + or $h0,$h0,$d0 + lwz $d0,0($nonce) # load nonce + andc $h2,$h2,$mask + and $d2,$d2,$mask + or $h1,$h1,$d1 + lwz $d1,4($nonce) + andc $h3,$h3,$mask + and $d3,$d3,$mask + or $h2,$h2,$d2 + lwz $d2,8($nonce) + or $h3,$h3,$d3 + lwz $d3,12($nonce) + + addc $h0,$h0,$d0 # accumulate nonce + adde $h1,$h1,$d1 + adde $h2,$h2,$d2 + adde $h3,$h3,$d3 +___ + } else { +$code.=<<___; + add $h0,$h0,$d3 + add $h1,$h1,$d0 + add $h2,$h2,$d1 + add $h3,$h3,$d2 + + srdi $d0,$h0,32 + add $h1,$h1,$d0 + srdi $d1,$h1,32 + add $h2,$h2,$d1 + srdi $d2,$h2,32 + add $h3,$h3,$d2 + srdi $d3,$h3,32 + add $h4,$h4,$d3 + + insrdi $h0,$h1,32,0 + insrdi $h2,$h3,32,0 + + addic $d0,$h0,5 # compare to modulus + addze $d1,$h2 + addze $d2,$h4 + + srdi $mask,$d2,2 # did it carry/borrow? + neg $mask,$mask + sradi $mask,$mask,63 # mask + ld $d2,0($nonce) # load nonce + ld $d3,8($nonce) + + andc $h0,$h0,$mask + and $d0,$d0,$mask + andc $h2,$h2,$mask + and $d1,$d1,$mask + or $h0,$h0,$d0 + or $h2,$h2,$d1 +___ +$code.=<<___ if (!$LITTLE_ENDIAN); + rotldi $d2,$d2,32 # flip nonce words + rotldi $d3,$d3,32 +___ +$code.=<<___; + addc $h0,$h0,$d2 # accumulate nonce + adde $h2,$h2,$d3 + + srdi $h1,$h0,32 + srdi $h3,$h2,32 +___ + } +$code.=<<___ if ($LITTLE_ENDIAN); + stw $h0,0($mac) # write result + stw $h1,4($mac) + stw $h2,8($mac) + stw $h3,12($mac) +___ +$code.=<<___ if (!$LITTLE_ENDIAN); + li $d1,4 + stwbrx $h0,0,$mac # write result + li $d2,8 + stwbrx $h1,$d1,$mac + li $d3,12 + stwbrx $h2,$d2,$mac + stwbrx $h3,$d3,$mac +___ +$code.=<<___; + $POP r28,`$FRAME-$SIZE_T*4`($sp) + $POP r29,`$FRAME-$SIZE_T*3`($sp) + $POP r30,`$FRAME-$SIZE_T*2`($sp) + $POP r31,`$FRAME-$SIZE_T*1`($sp) + addi $sp,$sp,$FRAME + blr + .long 0 + .byte 0,12,4,1,0x80,4,3,0 +.size .poly1305_emit_fpu,.-.poly1305_emit_fpu +___ +} +# Ugly hack here, because PPC assembler syntax seem to vary too +# much from platforms to platform... +$code.=<<___; +.align 6 +LPICmeup: + mflr r0 + bcl 20,31,\$+4 + mflr $len # vvvvvv "distance" between . and 1st data entry + addi $len,$len,`64-8` # borrow $len + mtlr r0 + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 + .space `64-9*4` + +.quad 0x4330000000000000 # 2^(52+0) +.quad 0x4530000000000000 # 2^(52+32) +.quad 0x4730000000000000 # 2^(52+64) +.quad 0x4930000000000000 # 2^(52+96) +.quad 0x4b50000000000000 # 2^(52+130) + +.quad 0x37f4000000000000 # 5/2^130 + +.quad 0x4430000000000000 # 2^(52+16+0) +.quad 0x4630000000000000 # 2^(52+16+32) +.quad 0x4830000000000000 # 2^(52+16+64) +.quad 0x4a30000000000000 # 2^(52+16+96) +.quad 0x3e30000000000000 # 2^(52+16+0-96) +.quad 0x4030000000000000 # 2^(52+16+32-96) +.quad 0x4230000000000000 # 2^(52+16+64-96) + +.quad 0x0000000000000001 # fpscr: truncate, no exceptions +.asciz "Poly1305 for PPC FPU, CRYPTOGAMS by " +.align 4 +___ + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-s390x.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-s390x.pl new file mode 100755 index 000000000..82d757d9a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-s390x.pl @@ -0,0 +1,227 @@ +#! /usr/bin/env perl +# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# This module implements Poly1305 hash for s390x. +# +# June 2015 +# +# ~6.6/2.3 cpb on z10/z196+, >2x improvement over compiler-generated +# code. For older compiler improvement coefficient is >3x, because +# then base 2^64 and base 2^32 implementations are compared. +# +# On side note, z13 enables vector base 2^26 implementation... + +$flavour = shift; + +if ($flavour =~ /3[12]/) { + $SIZE_T=4; + $g=""; +} else { + $SIZE_T=8; + $g="g"; +} + +while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} +open STDOUT,">$output"; + +$sp="%r15"; + +my ($ctx,$inp,$len,$padbit) = map("%r$_",(2..5)); + +$code.=<<___; +.text + +.globl poly1305_init +.type poly1305_init,\@function +.align 16 +poly1305_init: + lghi %r0,0 + lghi %r1,-1 + stg %r0,0($ctx) # zero hash value + stg %r0,8($ctx) + stg %r0,16($ctx) + + cl${g}r $inp,%r0 + je .Lno_key + + lrvg %r4,0($inp) # load little-endian key + lrvg %r5,8($inp) + + nihl %r1,0xffc0 # 0xffffffc0ffffffff + srlg %r0,%r1,4 # 0x0ffffffc0fffffff + srlg %r1,%r1,4 + nill %r1,0xfffc # 0x0ffffffc0ffffffc + + ngr %r4,%r0 + ngr %r5,%r1 + + stg %r4,32($ctx) + stg %r5,40($ctx) + +.Lno_key: + lghi %r2,0 + br %r14 +.size poly1305_init,.-poly1305_init +___ +{ +my ($d0hi,$d0lo,$d1hi,$d1lo,$t0,$h0,$t1,$h1,$h2) = map("%r$_",(6..14)); +my ($r0,$r1,$s1) = map("%r$_",(0..2)); + +$code.=<<___; +.globl poly1305_blocks +.type poly1305_blocks,\@function +.align 16 +poly1305_blocks: + srl${g} $len,4 # fixed-up in 64-bit build + lghi %r0,0 + cl${g}r $len,%r0 + je .Lno_data + + stm${g} %r6,%r14,`6*$SIZE_T`($sp) + + llgfr $padbit,$padbit # clear upper half, much needed with + # non-64-bit ABI + lg $r0,32($ctx) # load key + lg $r1,40($ctx) + + lg $h0,0($ctx) # load hash value + lg $h1,8($ctx) + lg $h2,16($ctx) + + st$g $ctx,`2*$SIZE_T`($sp) # off-load $ctx + srlg $s1,$r1,2 + algr $s1,$r1 # s1 = r1 + r1>>2 + j .Loop + +.align 16 +.Loop: + lrvg $d0lo,0($inp) # load little-endian input + lrvg $d1lo,8($inp) + la $inp,16($inp) + + algr $d0lo,$h0 # accumulate input + alcgr $d1lo,$h1 + + lgr $h0,$d0lo + mlgr $d0hi,$r0 # h0*r0 -> $d0hi:$d0lo + lgr $h1,$d1lo + mlgr $d1hi,$s1 # h1*5*r1 -> $d1hi:$d1lo + + mlgr $t0,$r1 # h0*r1 -> $t0:$h0 + mlgr $t1,$r0 # h1*r0 -> $t1:$h1 + alcgr $h2,$padbit + + algr $d0lo,$d1lo + lgr $d1lo,$h2 + alcgr $d0hi,$d1hi + lghi $d1hi,0 + + algr $h1,$h0 + alcgr $t1,$t0 + + msgr $d1lo,$s1 # h2*s1 + msgr $h2,$r0 # h2*r0 + + algr $h1,$d1lo + alcgr $t1,$d1hi # $d1hi is zero + + algr $h1,$d0hi + alcgr $h2,$t1 + + lghi $h0,-4 # final reduction step + ngr $h0,$h2 + srlg $t0,$h2,2 + algr $h0,$t0 + lghi $t1,3 + ngr $h2,$t1 + + algr $h0,$d0lo + alcgr $h1,$d1hi # $d1hi is still zero + alcgr $h2,$d1hi # $d1hi is still zero + + brct$g $len,.Loop + + l$g $ctx,`2*$SIZE_T`($sp) # restore $ctx + + stg $h0,0($ctx) # store hash value + stg $h1,8($ctx) + stg $h2,16($ctx) + + lm${g} %r6,%r14,`6*$SIZE_T`($sp) +.Lno_data: + br %r14 +.size poly1305_blocks,.-poly1305_blocks +___ +} +{ +my ($mac,$nonce)=($inp,$len); +my ($h0,$h1,$h2,$d0,$d1)=map("%r$_",(5..9)); + +$code.=<<___; +.globl poly1305_emit +.type poly1305_emit,\@function +.align 16 +poly1305_emit: + stm${g} %r6,%r9,`6*$SIZE_T`($sp) + + lg $h0,0($ctx) + lg $h1,8($ctx) + lg $h2,16($ctx) + + lghi %r0,5 + lghi %r1,0 + lgr $d0,$h0 + lgr $d1,$h1 + + algr $h0,%r0 # compare to modulus + alcgr $h1,%r1 + alcgr $h2,%r1 + + srlg $h2,$h2,2 # did it borrow/carry? + slgr %r1,$h2 # 0-$h2>>2 + lg $h2,0($nonce) # load nonce + lghi %r0,-1 + lg $ctx,8($nonce) + xgr %r0,%r1 # ~%r1 + + ngr $h0,%r1 + ngr $d0,%r0 + ngr $h1,%r1 + ngr $d1,%r0 + ogr $h0,$d0 + rllg $d0,$h2,32 # flip nonce words + ogr $h1,$d1 + rllg $d1,$ctx,32 + + algr $h0,$d0 # accumulate nonce + alcgr $h1,$d1 + + strvg $h0,0($mac) # write little-endian result + strvg $h1,8($mac) + + lm${g} %r6,%r9,`6*$SIZE_T`($sp) + br %r14 +.size poly1305_emit,.-poly1305_emit + +.string "Poly1305 for s390x, CRYPTOGAMS by " +___ +} + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +$code =~ s/\b(srlg\s+)(%r[0-9]+\s*,)\s*([0-9]+)/$1$2$2$3/gm; + +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-sparcv9.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-sparcv9.pl new file mode 100755 index 000000000..0bdd04892 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-sparcv9.pl @@ -0,0 +1,1120 @@ +#! /usr/bin/env perl +# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# This module implements Poly1305 hash for SPARCv9, vanilla, as well +# as VIS3 and FMA extensions. +# +# May, August 2015 +# +# Numbers are cycles per processed byte with poly1305_blocks alone. +# +# IALU(*) FMA +# +# UltraSPARC III 12.3(**) +# SPARC T3 7.92 +# SPARC T4 1.70(***) 6.55 +# SPARC64 X 5.60 3.64 +# +# (*) Comparison to compiler-generated code is really problematic, +# because latter's performance varies too much depending on too +# many variables. For example, one can measure from 5x to 15x +# improvement on T4 for gcc-4.6. Well, in T4 case it's a bit +# unfair comparison, because compiler doesn't use VIS3, but +# given same initial conditions coefficient varies from 3x to 9x. +# (**) Pre-III performance should be even worse; floating-point +# performance for UltraSPARC I-IV on the other hand is reported +# to be 4.25 for hand-coded assembly, but they are just too old +# to care about. +# (***) Multi-process benchmark saturates at ~12.5x single-process +# result on 8-core processor, or ~21GBps per 2.85GHz socket. + +my $output = pop; +open STDOUT,">$output"; + +my ($ctx,$inp,$len,$padbit,$shl,$shr) = map("%i$_",(0..5)); +my ($r0,$r1,$r2,$r3,$s1,$s2,$s3,$h4) = map("%l$_",(0..7)); +my ($h0,$h1,$h2,$h3, $t0,$t1,$t2) = map("%o$_",(0..5,7)); +my ($d0,$d1,$d2,$d3) = map("%g$_",(1..4)); + +my $output = pop; +open STDOUT,">$stdout"; + +$code.=<<___; +#include "sparc_arch.h" + +#ifdef __arch64__ +.register %g2,#scratch +.register %g3,#scratch +# define STPTR stx +# define SIZE_T 8 +#else +# define STPTR st +# define SIZE_T 4 +#endif +#define LOCALS (STACK_BIAS+STACK_FRAME) + +.section ".text",#alloc,#execinstr + +#ifdef __PIC__ +SPARC_PIC_THUNK(%g1) +#endif + +.globl poly1305_init +.align 32 +poly1305_init: + save %sp,-STACK_FRAME-16,%sp + nop + + SPARC_LOAD_ADDRESS(OPENSSL_sparcv9cap_P,%g1) + ld [%g1],%g1 + + and %g1,SPARCV9_FMADD|SPARCV9_VIS3,%g1 + cmp %g1,SPARCV9_FMADD + be .Lpoly1305_init_fma + nop + + stx %g0,[$ctx+0] + stx %g0,[$ctx+8] ! zero hash value + brz,pn $inp,.Lno_key + stx %g0,[$ctx+16] + + and $inp,7,$shr ! alignment factor + andn $inp,7,$inp + sll $shr,3,$shr ! *8 + neg $shr,$shl + + sethi %hi(0x0ffffffc),$t0 + set 8,$h1 + or $t0,%lo(0x0ffffffc),$t0 + set 16,$h2 + sllx $t0,32,$t1 + or $t0,$t1,$t1 ! 0x0ffffffc0ffffffc + or $t1,3,$t0 ! 0x0ffffffc0fffffff + + ldxa [$inp+%g0]0x88,$h0 ! load little-endian key + brz,pt $shr,.Lkey_aligned + ldxa [$inp+$h1]0x88,$h1 + + ldxa [$inp+$h2]0x88,$h2 + srlx $h0,$shr,$h0 + sllx $h1,$shl,$t2 + srlx $h1,$shr,$h1 + or $t2,$h0,$h0 + sllx $h2,$shl,$h2 + or $h2,$h1,$h1 + +.Lkey_aligned: + and $t0,$h0,$h0 + and $t1,$h1,$h1 + stx $h0,[$ctx+32+0] ! store key + stx $h1,[$ctx+32+8] + + andcc %g1,SPARCV9_VIS3,%g0 + be .Lno_key + nop + +1: call .+8 + add %o7,poly1305_blocks_vis3-1b,%o7 + + add %o7,poly1305_emit-poly1305_blocks_vis3,%o5 + STPTR %o7,[%i2] + STPTR %o5,[%i2+SIZE_T] + + ret + restore %g0,1,%o0 ! return 1 + +.Lno_key: + ret + restore %g0,%g0,%o0 ! return 0 +.type poly1305_init,#function +.size poly1305_init,.-poly1305_init + +.globl poly1305_blocks +.align 32 +poly1305_blocks: + save %sp,-STACK_FRAME,%sp + srln $len,4,$len + + brz,pn $len,.Lno_data + nop + + ld [$ctx+32+0],$r1 ! load key + ld [$ctx+32+4],$r0 + ld [$ctx+32+8],$r3 + ld [$ctx+32+12],$r2 + + ld [$ctx+0],$h1 ! load hash value + ld [$ctx+4],$h0 + ld [$ctx+8],$h3 + ld [$ctx+12],$h2 + ld [$ctx+16],$h4 + + and $inp,7,$shr ! alignment factor + andn $inp,7,$inp + set 8,$d1 + sll $shr,3,$shr ! *8 + set 16,$d2 + neg $shr,$shl + + srl $r1,2,$s1 + srl $r2,2,$s2 + add $r1,$s1,$s1 + srl $r3,2,$s3 + add $r2,$s2,$s2 + add $r3,$s3,$s3 + +.Loop: + ldxa [$inp+%g0]0x88,$d0 ! load little-endian input + brz,pt $shr,.Linp_aligned + ldxa [$inp+$d1]0x88,$d1 + + ldxa [$inp+$d2]0x88,$d2 + srlx $d0,$shr,$d0 + sllx $d1,$shl,$t1 + srlx $d1,$shr,$d1 + or $t1,$d0,$d0 + sllx $d2,$shl,$d2 + or $d2,$d1,$d1 + +.Linp_aligned: + srlx $d0,32,$t0 + addcc $d0,$h0,$h0 ! accumulate input + srlx $d1,32,$t1 + addccc $t0,$h1,$h1 + addccc $d1,$h2,$h2 + addccc $t1,$h3,$h3 + addc $padbit,$h4,$h4 + + umul $r0,$h0,$d0 + umul $r1,$h0,$d1 + umul $r2,$h0,$d2 + umul $r3,$h0,$d3 + sub $len,1,$len + add $inp,16,$inp + + umul $s3,$h1,$t0 + umul $r0,$h1,$t1 + umul $r1,$h1,$t2 + add $t0,$d0,$d0 + add $t1,$d1,$d1 + umul $r2,$h1,$t0 + add $t2,$d2,$d2 + add $t0,$d3,$d3 + + umul $s2,$h2,$t1 + umul $s3,$h2,$t2 + umul $r0,$h2,$t0 + add $t1,$d0,$d0 + add $t2,$d1,$d1 + umul $r1,$h2,$t1 + add $t0,$d2,$d2 + add $t1,$d3,$d3 + + umul $s1,$h3,$t2 + umul $s2,$h3,$t0 + umul $s3,$h3,$t1 + add $t2,$d0,$d0 + add $t0,$d1,$d1 + umul $r0,$h3,$t2 + add $t1,$d2,$d2 + add $t2,$d3,$d3 + + umul $s1,$h4,$t0 + umul $s2,$h4,$t1 + umul $s3,$h4,$t2 + umul $r0,$h4,$h4 + add $t0,$d1,$d1 + add $t1,$d2,$d2 + srlx $d0,32,$h1 + add $t2,$d3,$d3 + srlx $d1,32,$h2 + + addcc $d1,$h1,$h1 + srlx $d2,32,$h3 + set 8,$d1 + addccc $d2,$h2,$h2 + srlx $d3,32,$t0 + set 16,$d2 + addccc $d3,$h3,$h3 + addc $t0,$h4,$h4 + + srl $h4,2,$t0 ! final reduction step + andn $h4,3,$t1 + and $h4,3,$h4 + add $t1,$t0,$t0 + + addcc $t0,$d0,$h0 + addccc %g0,$h1,$h1 + addccc %g0,$h2,$h2 + addccc %g0,$h3,$h3 + brnz,pt $len,.Loop + addc %g0,$h4,$h4 + + st $h1,[$ctx+0] ! store hash value + st $h0,[$ctx+4] + st $h3,[$ctx+8] + st $h2,[$ctx+12] + st $h4,[$ctx+16] + +.Lno_data: + ret + restore +.type poly1305_blocks,#function +.size poly1305_blocks,.-poly1305_blocks +___ +######################################################################## +# VIS3 has umulxhi and addxc... +{ +my ($H0,$H1,$H2,$R0,$R1,$S1,$T1) = map("%o$_",(0..5,7)); +my ($D0,$D1,$D2,$T0) = map("%g$_",(1..4)); + +$code.=<<___; +.align 32 +poly1305_blocks_vis3: + save %sp,-STACK_FRAME,%sp + srln $len,4,$len + + brz,pn $len,.Lno_data + nop + + ldx [$ctx+32+0],$R0 ! load key + ldx [$ctx+32+8],$R1 + + ldx [$ctx+0],$H0 ! load hash value + ldx [$ctx+8],$H1 + ld [$ctx+16],$H2 + + and $inp,7,$shr ! alignment factor + andn $inp,7,$inp + set 8,$r1 + sll $shr,3,$shr ! *8 + set 16,$r2 + neg $shr,$shl + + srlx $R1,2,$S1 + b .Loop_vis3 + add $R1,$S1,$S1 + +.Loop_vis3: + ldxa [$inp+%g0]0x88,$D0 ! load little-endian input + brz,pt $shr,.Linp_aligned_vis3 + ldxa [$inp+$r1]0x88,$D1 + + ldxa [$inp+$r2]0x88,$D2 + srlx $D0,$shr,$D0 + sllx $D1,$shl,$T1 + srlx $D1,$shr,$D1 + or $T1,$D0,$D0 + sllx $D2,$shl,$D2 + or $D2,$D1,$D1 + +.Linp_aligned_vis3: + addcc $D0,$H0,$H0 ! accumulate input + sub $len,1,$len + addxccc $D1,$H1,$H1 + add $inp,16,$inp + + mulx $R0,$H0,$D0 ! r0*h0 + addxc $padbit,$H2,$H2 + umulxhi $R0,$H0,$D1 + mulx $S1,$H1,$T0 ! s1*h1 + umulxhi $S1,$H1,$T1 + addcc $T0,$D0,$D0 + mulx $R1,$H0,$T0 ! r1*h0 + addxc $T1,$D1,$D1 + umulxhi $R1,$H0,$D2 + addcc $T0,$D1,$D1 + mulx $R0,$H1,$T0 ! r0*h1 + addxc %g0,$D2,$D2 + umulxhi $R0,$H1,$T1 + addcc $T0,$D1,$D1 + mulx $S1,$H2,$T0 ! s1*h2 + addxc $T1,$D2,$D2 + mulx $R0,$H2,$T1 ! r0*h2 + addcc $T0,$D1,$D1 + addxc $T1,$D2,$D2 + + srlx $D2,2,$T0 ! final reduction step + andn $D2,3,$T1 + and $D2,3,$H2 + add $T1,$T0,$T0 + + addcc $T0,$D0,$H0 + addxccc %g0,$D1,$H1 + brnz,pt $len,.Loop_vis3 + addxc %g0,$H2,$H2 + + stx $H0,[$ctx+0] ! store hash value + stx $H1,[$ctx+8] + st $H2,[$ctx+16] + + ret + restore +.type poly1305_blocks_vis3,#function +.size poly1305_blocks_vis3,.-poly1305_blocks_vis3 +___ +} +my ($mac,$nonce) = ($inp,$len); + +$code.=<<___; +.globl poly1305_emit +.align 32 +poly1305_emit: + save %sp,-STACK_FRAME,%sp + + ld [$ctx+0],$h1 ! load hash value + ld [$ctx+4],$h0 + ld [$ctx+8],$h3 + ld [$ctx+12],$h2 + ld [$ctx+16],$h4 + + addcc $h0,5,$r0 ! compare to modulus + addccc $h1,0,$r1 + addccc $h2,0,$r2 + addccc $h3,0,$r3 + addc $h4,0,$h4 + andcc $h4,4,%g0 ! did it carry/borrow? + + movnz %icc,$r0,$h0 + ld [$nonce+0],$r0 ! load nonce + movnz %icc,$r1,$h1 + ld [$nonce+4],$r1 + movnz %icc,$r2,$h2 + ld [$nonce+8],$r2 + movnz %icc,$r3,$h3 + ld [$nonce+12],$r3 + + addcc $r0,$h0,$h0 ! accumulate nonce + addccc $r1,$h1,$h1 + addccc $r2,$h2,$h2 + addc $r3,$h3,$h3 + + srl $h0,8,$r0 + stb $h0,[$mac+0] ! store little-endian result + srl $h0,16,$r1 + stb $r0,[$mac+1] + srl $h0,24,$r2 + stb $r1,[$mac+2] + stb $r2,[$mac+3] + + srl $h1,8,$r0 + stb $h1,[$mac+4] + srl $h1,16,$r1 + stb $r0,[$mac+5] + srl $h1,24,$r2 + stb $r1,[$mac+6] + stb $r2,[$mac+7] + + srl $h2,8,$r0 + stb $h2,[$mac+8] + srl $h2,16,$r1 + stb $r0,[$mac+9] + srl $h2,24,$r2 + stb $r1,[$mac+10] + stb $r2,[$mac+11] + + srl $h3,8,$r0 + stb $h3,[$mac+12] + srl $h3,16,$r1 + stb $r0,[$mac+13] + srl $h3,24,$r2 + stb $r1,[$mac+14] + stb $r2,[$mac+15] + + ret + restore +.type poly1305_emit,#function +.size poly1305_emit,.-poly1305_emit +___ + +{ +my ($ctx,$inp,$len,$padbit) = map("%i$_",(0..3)); +my ($in0,$in1,$in2,$in3,$in4) = map("%o$_",(0..4)); +my ($i1,$step,$shr,$shl) = map("%l$_",(0..7)); +my $i2=$step; + +my ($h0lo,$h0hi,$h1lo,$h1hi,$h2lo,$h2hi,$h3lo,$h3hi, + $two0,$two32,$two64,$two96,$two130,$five_two130, + $r0lo,$r0hi,$r1lo,$r1hi,$r2lo,$r2hi, + $s2lo,$s2hi,$s3lo,$s3hi, + $c0lo,$c0hi,$c1lo,$c1hi,$c2lo,$c2hi,$c3lo,$c3hi) = map("%f".2*$_,(0..31)); +# borrowings +my ($r3lo,$r3hi,$s1lo,$s1hi) = ($c0lo,$c0hi,$c1lo,$c1hi); +my ($x0,$x1,$x2,$x3) = ($c2lo,$c2hi,$c3lo,$c3hi); +my ($y0,$y1,$y2,$y3) = ($c1lo,$c1hi,$c3hi,$c3lo); + +$code.=<<___; +.align 32 +poly1305_init_fma: + save %sp,-STACK_FRAME-16,%sp + nop + +.Lpoly1305_init_fma: +1: call .+8 + add %o7,.Lconsts_fma-1b,%o7 + + ldd [%o7+8*0],$two0 ! load constants + ldd [%o7+8*1],$two32 + ldd [%o7+8*2],$two64 + ldd [%o7+8*3],$two96 + ldd [%o7+8*5],$five_two130 + + std $two0,[$ctx+8*0] ! initial hash value, biased 0 + std $two32,[$ctx+8*1] + std $two64,[$ctx+8*2] + std $two96,[$ctx+8*3] + + brz,pn $inp,.Lno_key_fma + nop + + stx %fsr,[%sp+LOCALS] ! save original %fsr + ldx [%o7+8*6],%fsr ! load new %fsr + + std $two0,[$ctx+8*4] ! key "template" + std $two32,[$ctx+8*5] + std $two64,[$ctx+8*6] + std $two96,[$ctx+8*7] + + and $inp,7,$shr + andn $inp,7,$inp ! align pointer + mov 8,$i1 + sll $shr,3,$shr + mov 16,$i2 + neg $shr,$shl + + ldxa [$inp+%g0]0x88,$in0 ! load little-endian key + ldxa [$inp+$i1]0x88,$in2 + + brz $shr,.Lkey_aligned_fma + sethi %hi(0xf0000000),$i1 ! 0xf0000000 + + ldxa [$inp+$i2]0x88,$in4 + + srlx $in0,$shr,$in0 ! align data + sllx $in2,$shl,$in1 + srlx $in2,$shr,$in2 + or $in1,$in0,$in0 + sllx $in4,$shl,$in3 + or $in3,$in2,$in2 + +.Lkey_aligned_fma: + or $i1,3,$i2 ! 0xf0000003 + srlx $in0,32,$in1 + andn $in0,$i1,$in0 ! &=0x0fffffff + andn $in1,$i2,$in1 ! &=0x0ffffffc + srlx $in2,32,$in3 + andn $in2,$i2,$in2 + andn $in3,$i2,$in3 + + st $in0,[$ctx+`8*4+4`] ! fill "template" + st $in1,[$ctx+`8*5+4`] + st $in2,[$ctx+`8*6+4`] + st $in3,[$ctx+`8*7+4`] + + ldd [$ctx+8*4],$h0lo ! load [biased] key + ldd [$ctx+8*5],$h1lo + ldd [$ctx+8*6],$h2lo + ldd [$ctx+8*7],$h3lo + + fsubd $h0lo,$two0, $h0lo ! r0 + ldd [%o7+8*7],$two0 ! more constants + fsubd $h1lo,$two32,$h1lo ! r1 + ldd [%o7+8*8],$two32 + fsubd $h2lo,$two64,$h2lo ! r2 + ldd [%o7+8*9],$two64 + fsubd $h3lo,$two96,$h3lo ! r3 + ldd [%o7+8*10],$two96 + + fmuld $five_two130,$h1lo,$s1lo ! s1 + fmuld $five_two130,$h2lo,$s2lo ! s2 + fmuld $five_two130,$h3lo,$s3lo ! s3 + + faddd $h0lo,$two0, $h0hi + faddd $h1lo,$two32,$h1hi + faddd $h2lo,$two64,$h2hi + faddd $h3lo,$two96,$h3hi + + fsubd $h0hi,$two0, $h0hi + ldd [%o7+8*11],$two0 ! more constants + fsubd $h1hi,$two32,$h1hi + ldd [%o7+8*12],$two32 + fsubd $h2hi,$two64,$h2hi + ldd [%o7+8*13],$two64 + fsubd $h3hi,$two96,$h3hi + + fsubd $h0lo,$h0hi,$h0lo + std $h0hi,[$ctx+8*5] ! r0hi + fsubd $h1lo,$h1hi,$h1lo + std $h1hi,[$ctx+8*7] ! r1hi + fsubd $h2lo,$h2hi,$h2lo + std $h2hi,[$ctx+8*9] ! r2hi + fsubd $h3lo,$h3hi,$h3lo + std $h3hi,[$ctx+8*11] ! r3hi + + faddd $s1lo,$two0, $s1hi + faddd $s2lo,$two32,$s2hi + faddd $s3lo,$two64,$s3hi + + fsubd $s1hi,$two0, $s1hi + fsubd $s2hi,$two32,$s2hi + fsubd $s3hi,$two64,$s3hi + + fsubd $s1lo,$s1hi,$s1lo + fsubd $s2lo,$s2hi,$s2lo + fsubd $s3lo,$s3hi,$s3lo + + ldx [%sp+LOCALS],%fsr ! restore %fsr + + std $h0lo,[$ctx+8*4] ! r0lo + std $h1lo,[$ctx+8*6] ! r1lo + std $h2lo,[$ctx+8*8] ! r2lo + std $h3lo,[$ctx+8*10] ! r3lo + + std $s1hi,[$ctx+8*13] + std $s2hi,[$ctx+8*15] + std $s3hi,[$ctx+8*17] + + std $s1lo,[$ctx+8*12] + std $s2lo,[$ctx+8*14] + std $s3lo,[$ctx+8*16] + + add %o7,poly1305_blocks_fma-.Lconsts_fma,%o0 + add %o7,poly1305_emit_fma-.Lconsts_fma,%o1 + STPTR %o0,[%i2] + STPTR %o1,[%i2+SIZE_T] + + ret + restore %g0,1,%o0 ! return 1 + +.Lno_key_fma: + ret + restore %g0,%g0,%o0 ! return 0 +.type poly1305_init_fma,#function +.size poly1305_init_fma,.-poly1305_init_fma + +.align 32 +poly1305_blocks_fma: + save %sp,-STACK_FRAME-48,%sp + srln $len,4,$len + + brz,pn $len,.Labort + sub $len,1,$len + +1: call .+8 + add %o7,.Lconsts_fma-1b,%o7 + + ldd [%o7+8*0],$two0 ! load constants + ldd [%o7+8*1],$two32 + ldd [%o7+8*2],$two64 + ldd [%o7+8*3],$two96 + ldd [%o7+8*4],$two130 + ldd [%o7+8*5],$five_two130 + + ldd [$ctx+8*0],$h0lo ! load [biased] hash value + ldd [$ctx+8*1],$h1lo + ldd [$ctx+8*2],$h2lo + ldd [$ctx+8*3],$h3lo + + std $two0,[%sp+LOCALS+8*0] ! input "template" + sethi %hi((1023+52+96)<<20),$in3 + std $two32,[%sp+LOCALS+8*1] + or $padbit,$in3,$in3 + std $two64,[%sp+LOCALS+8*2] + st $in3,[%sp+LOCALS+8*3] + + and $inp,7,$shr + andn $inp,7,$inp ! align pointer + mov 8,$i1 + sll $shr,3,$shr + mov 16,$step + neg $shr,$shl + + ldxa [$inp+%g0]0x88,$in0 ! load little-endian input + brz $shr,.Linp_aligned_fma + ldxa [$inp+$i1]0x88,$in2 + + ldxa [$inp+$step]0x88,$in4 + add $inp,8,$inp + + srlx $in0,$shr,$in0 ! align data + sllx $in2,$shl,$in1 + srlx $in2,$shr,$in2 + or $in1,$in0,$in0 + sllx $in4,$shl,$in3 + srlx $in4,$shr,$in4 ! pre-shift + or $in3,$in2,$in2 + +.Linp_aligned_fma: + srlx $in0,32,$in1 + movrz $len,0,$step + srlx $in2,32,$in3 + add $step,$inp,$inp ! conditional advance + + st $in0,[%sp+LOCALS+8*0+4] ! fill "template" + st $in1,[%sp+LOCALS+8*1+4] + st $in2,[%sp+LOCALS+8*2+4] + st $in3,[%sp+LOCALS+8*3+4] + + ldd [$ctx+8*4],$r0lo ! load key + ldd [$ctx+8*5],$r0hi + ldd [$ctx+8*6],$r1lo + ldd [$ctx+8*7],$r1hi + ldd [$ctx+8*8],$r2lo + ldd [$ctx+8*9],$r2hi + ldd [$ctx+8*10],$r3lo + ldd [$ctx+8*11],$r3hi + ldd [$ctx+8*12],$s1lo + ldd [$ctx+8*13],$s1hi + ldd [$ctx+8*14],$s2lo + ldd [$ctx+8*15],$s2hi + ldd [$ctx+8*16],$s3lo + ldd [$ctx+8*17],$s3hi + + stx %fsr,[%sp+LOCALS+8*4] ! save original %fsr + ldx [%o7+8*6],%fsr ! load new %fsr + + subcc $len,1,$len + movrz $len,0,$step + + ldd [%sp+LOCALS+8*0],$x0 ! load biased input + ldd [%sp+LOCALS+8*1],$x1 + ldd [%sp+LOCALS+8*2],$x2 + ldd [%sp+LOCALS+8*3],$x3 + + fsubd $h0lo,$two0, $h0lo ! de-bias hash value + fsubd $h1lo,$two32,$h1lo + ldxa [$inp+%g0]0x88,$in0 ! modulo-scheduled input load + fsubd $h2lo,$two64,$h2lo + fsubd $h3lo,$two96,$h3lo + ldxa [$inp+$i1]0x88,$in2 + + fsubd $x0,$two0, $x0 ! de-bias input + fsubd $x1,$two32,$x1 + fsubd $x2,$two64,$x2 + fsubd $x3,$two96,$x3 + + brz $shr,.Linp_aligned_fma2 + add $step,$inp,$inp ! conditional advance + + sllx $in0,$shl,$in1 ! align data + srlx $in0,$shr,$in3 + or $in1,$in4,$in0 + sllx $in2,$shl,$in1 + srlx $in2,$shr,$in4 ! pre-shift + or $in3,$in1,$in2 +.Linp_aligned_fma2: + srlx $in0,32,$in1 + srlx $in2,32,$in3 + + faddd $h0lo,$x0,$x0 ! accumulate input + stw $in0,[%sp+LOCALS+8*0+4] + faddd $h1lo,$x1,$x1 + stw $in1,[%sp+LOCALS+8*1+4] + faddd $h2lo,$x2,$x2 + stw $in2,[%sp+LOCALS+8*2+4] + faddd $h3lo,$x3,$x3 + stw $in3,[%sp+LOCALS+8*3+4] + + b .Lentry_fma + nop + +.align 16 +.Loop_fma: + ldxa [$inp+%g0]0x88,$in0 ! modulo-scheduled input load + ldxa [$inp+$i1]0x88,$in2 + movrz $len,0,$step + + faddd $y0,$h0lo,$h0lo ! accumulate input + faddd $y1,$h0hi,$h0hi + faddd $y2,$h2lo,$h2lo + faddd $y3,$h2hi,$h2hi + + brz,pn $shr,.Linp_aligned_fma3 + add $step,$inp,$inp ! conditional advance + + sllx $in0,$shl,$in1 ! align data + srlx $in0,$shr,$in3 + or $in1,$in4,$in0 + sllx $in2,$shl,$in1 + srlx $in2,$shr,$in4 ! pre-shift + or $in3,$in1,$in2 + +.Linp_aligned_fma3: + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! base 2^48 -> base 2^32 + faddd $two64,$h1lo,$c1lo + srlx $in0,32,$in1 + faddd $two64,$h1hi,$c1hi + srlx $in2,32,$in3 + faddd $two130,$h3lo,$c3lo + st $in0,[%sp+LOCALS+8*0+4] ! fill "template" + faddd $two130,$h3hi,$c3hi + st $in1,[%sp+LOCALS+8*1+4] + faddd $two32,$h0lo,$c0lo + st $in2,[%sp+LOCALS+8*2+4] + faddd $two32,$h0hi,$c0hi + st $in3,[%sp+LOCALS+8*3+4] + faddd $two96,$h2lo,$c2lo + faddd $two96,$h2hi,$c2hi + + fsubd $c1lo,$two64,$c1lo + fsubd $c1hi,$two64,$c1hi + fsubd $c3lo,$two130,$c3lo + fsubd $c3hi,$two130,$c3hi + fsubd $c0lo,$two32,$c0lo + fsubd $c0hi,$two32,$c0hi + fsubd $c2lo,$two96,$c2lo + fsubd $c2hi,$two96,$c2hi + + fsubd $h1lo,$c1lo,$h1lo + fsubd $h1hi,$c1hi,$h1hi + fsubd $h3lo,$c3lo,$h3lo + fsubd $h3hi,$c3hi,$h3hi + fsubd $h2lo,$c2lo,$h2lo + fsubd $h2hi,$c2hi,$h2hi + fsubd $h0lo,$c0lo,$h0lo + fsubd $h0hi,$c0hi,$h0hi + + faddd $h1lo,$c0lo,$h1lo + faddd $h1hi,$c0hi,$h1hi + faddd $h3lo,$c2lo,$h3lo + faddd $h3hi,$c2hi,$h3hi + faddd $h2lo,$c1lo,$h2lo + faddd $h2hi,$c1hi,$h2hi + fmaddd $five_two130,$c3lo,$h0lo,$h0lo + fmaddd $five_two130,$c3hi,$h0hi,$h0hi + + faddd $h1lo,$h1hi,$x1 + ldd [$ctx+8*12],$s1lo ! reload constants + faddd $h3lo,$h3hi,$x3 + ldd [$ctx+8*13],$s1hi + faddd $h2lo,$h2hi,$x2 + ldd [$ctx+8*10],$r3lo + faddd $h0lo,$h0hi,$x0 + ldd [$ctx+8*11],$r3hi + +.Lentry_fma: + fmuld $x1,$s3lo,$h0lo + fmuld $x1,$s3hi,$h0hi + fmuld $x1,$r1lo,$h2lo + fmuld $x1,$r1hi,$h2hi + fmuld $x1,$r0lo,$h1lo + fmuld $x1,$r0hi,$h1hi + fmuld $x1,$r2lo,$h3lo + fmuld $x1,$r2hi,$h3hi + + fmaddd $x3,$s1lo,$h0lo,$h0lo + fmaddd $x3,$s1hi,$h0hi,$h0hi + fmaddd $x3,$s3lo,$h2lo,$h2lo + fmaddd $x3,$s3hi,$h2hi,$h2hi + fmaddd $x3,$s2lo,$h1lo,$h1lo + fmaddd $x3,$s2hi,$h1hi,$h1hi + fmaddd $x3,$r0lo,$h3lo,$h3lo + fmaddd $x3,$r0hi,$h3hi,$h3hi + + fmaddd $x2,$s2lo,$h0lo,$h0lo + fmaddd $x2,$s2hi,$h0hi,$h0hi + fmaddd $x2,$r0lo,$h2lo,$h2lo + fmaddd $x2,$r0hi,$h2hi,$h2hi + fmaddd $x2,$s3lo,$h1lo,$h1lo + ldd [%sp+LOCALS+8*0],$y0 ! load [biased] input + fmaddd $x2,$s3hi,$h1hi,$h1hi + ldd [%sp+LOCALS+8*1],$y1 + fmaddd $x2,$r1lo,$h3lo,$h3lo + ldd [%sp+LOCALS+8*2],$y2 + fmaddd $x2,$r1hi,$h3hi,$h3hi + ldd [%sp+LOCALS+8*3],$y3 + + fmaddd $x0,$r0lo,$h0lo,$h0lo + fsubd $y0,$two0, $y0 ! de-bias input + fmaddd $x0,$r0hi,$h0hi,$h0hi + fsubd $y1,$two32,$y1 + fmaddd $x0,$r2lo,$h2lo,$h2lo + fsubd $y2,$two64,$y2 + fmaddd $x0,$r2hi,$h2hi,$h2hi + fsubd $y3,$two96,$y3 + fmaddd $x0,$r1lo,$h1lo,$h1lo + fmaddd $x0,$r1hi,$h1hi,$h1hi + fmaddd $x0,$r3lo,$h3lo,$h3lo + fmaddd $x0,$r3hi,$h3hi,$h3hi + + bcc SIZE_T_CC,.Loop_fma + subcc $len,1,$len + + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! base 2^48 -> base 2^32 + faddd $h0lo,$two32,$c0lo + faddd $h0hi,$two32,$c0hi + faddd $h2lo,$two96,$c2lo + faddd $h2hi,$two96,$c2hi + faddd $h1lo,$two64,$c1lo + faddd $h1hi,$two64,$c1hi + faddd $h3lo,$two130,$c3lo + faddd $h3hi,$two130,$c3hi + + fsubd $c0lo,$two32,$c0lo + fsubd $c0hi,$two32,$c0hi + fsubd $c2lo,$two96,$c2lo + fsubd $c2hi,$two96,$c2hi + fsubd $c1lo,$two64,$c1lo + fsubd $c1hi,$two64,$c1hi + fsubd $c3lo,$two130,$c3lo + fsubd $c3hi,$two130,$c3hi + + fsubd $h1lo,$c1lo,$h1lo + fsubd $h1hi,$c1hi,$h1hi + fsubd $h3lo,$c3lo,$h3lo + fsubd $h3hi,$c3hi,$h3hi + fsubd $h2lo,$c2lo,$h2lo + fsubd $h2hi,$c2hi,$h2hi + fsubd $h0lo,$c0lo,$h0lo + fsubd $h0hi,$c0hi,$h0hi + + faddd $h1lo,$c0lo,$h1lo + faddd $h1hi,$c0hi,$h1hi + faddd $h3lo,$c2lo,$h3lo + faddd $h3hi,$c2hi,$h3hi + faddd $h2lo,$c1lo,$h2lo + faddd $h2hi,$c1hi,$h2hi + fmaddd $five_two130,$c3lo,$h0lo,$h0lo + fmaddd $five_two130,$c3hi,$h0hi,$h0hi + + faddd $h1lo,$h1hi,$x1 + faddd $h3lo,$h3hi,$x3 + faddd $h2lo,$h2hi,$x2 + faddd $h0lo,$h0hi,$x0 + + faddd $x1,$two32,$x1 ! bias + faddd $x3,$two96,$x3 + faddd $x2,$two64,$x2 + faddd $x0,$two0, $x0 + + ldx [%sp+LOCALS+8*4],%fsr ! restore saved %fsr + + std $x1,[$ctx+8*1] ! store [biased] hash value + std $x3,[$ctx+8*3] + std $x2,[$ctx+8*2] + std $x0,[$ctx+8*0] + +.Labort: + ret + restore +.type poly1305_blocks_fma,#function +.size poly1305_blocks_fma,.-poly1305_blocks_fma +___ +{ +my ($mac,$nonce)=($inp,$len); + +my ($h0,$h1,$h2,$h3,$h4, $d0,$d1,$d2,$d3, $mask + ) = (map("%l$_",(0..5)),map("%o$_",(0..4))); + +$code.=<<___; +.align 32 +poly1305_emit_fma: + save %sp,-STACK_FRAME,%sp + + ld [$ctx+8*0+0],$d0 ! load hash + ld [$ctx+8*0+4],$h0 + ld [$ctx+8*1+0],$d1 + ld [$ctx+8*1+4],$h1 + ld [$ctx+8*2+0],$d2 + ld [$ctx+8*2+4],$h2 + ld [$ctx+8*3+0],$d3 + ld [$ctx+8*3+4],$h3 + + sethi %hi(0xfff00000),$mask + andn $d0,$mask,$d0 ! mask exponent + andn $d1,$mask,$d1 + andn $d2,$mask,$d2 + andn $d3,$mask,$d3 ! can be partially reduced... + mov 3,$mask + + srl $d3,2,$padbit ! ... so reduce + and $d3,$mask,$h4 + andn $d3,$mask,$d3 + add $padbit,$d3,$d3 + + addcc $d3,$h0,$h0 + addccc $d0,$h1,$h1 + addccc $d1,$h2,$h2 + addccc $d2,$h3,$h3 + addc %g0,$h4,$h4 + + addcc $h0,5,$d0 ! compare to modulus + addccc $h1,0,$d1 + addccc $h2,0,$d2 + addccc $h3,0,$d3 + addc $h4,0,$mask + + srl $mask,2,$mask ! did it carry/borrow? + neg $mask,$mask + sra $mask,31,$mask ! mask + + andn $h0,$mask,$h0 + and $d0,$mask,$d0 + andn $h1,$mask,$h1 + and $d1,$mask,$d1 + or $d0,$h0,$h0 + ld [$nonce+0],$d0 ! load nonce + andn $h2,$mask,$h2 + and $d2,$mask,$d2 + or $d1,$h1,$h1 + ld [$nonce+4],$d1 + andn $h3,$mask,$h3 + and $d3,$mask,$d3 + or $d2,$h2,$h2 + ld [$nonce+8],$d2 + or $d3,$h3,$h3 + ld [$nonce+12],$d3 + + addcc $d0,$h0,$h0 ! accumulate nonce + addccc $d1,$h1,$h1 + addccc $d2,$h2,$h2 + addc $d3,$h3,$h3 + + stb $h0,[$mac+0] ! write little-endian result + srl $h0,8,$h0 + stb $h1,[$mac+4] + srl $h1,8,$h1 + stb $h2,[$mac+8] + srl $h2,8,$h2 + stb $h3,[$mac+12] + srl $h3,8,$h3 + + stb $h0,[$mac+1] + srl $h0,8,$h0 + stb $h1,[$mac+5] + srl $h1,8,$h1 + stb $h2,[$mac+9] + srl $h2,8,$h2 + stb $h3,[$mac+13] + srl $h3,8,$h3 + + stb $h0,[$mac+2] + srl $h0,8,$h0 + stb $h1,[$mac+6] + srl $h1,8,$h1 + stb $h2,[$mac+10] + srl $h2,8,$h2 + stb $h3,[$mac+14] + srl $h3,8,$h3 + + stb $h0,[$mac+3] + stb $h1,[$mac+7] + stb $h2,[$mac+11] + stb $h3,[$mac+15] + + ret + restore +.type poly1305_emit_fma,#function +.size poly1305_emit_fma,.-poly1305_emit_fma +___ +} + +$code.=<<___; +.align 64 +.Lconsts_fma: +.word 0x43300000,0x00000000 ! 2^(52+0) +.word 0x45300000,0x00000000 ! 2^(52+32) +.word 0x47300000,0x00000000 ! 2^(52+64) +.word 0x49300000,0x00000000 ! 2^(52+96) +.word 0x4b500000,0x00000000 ! 2^(52+130) + +.word 0x37f40000,0x00000000 ! 5/2^130 +.word 0,1<<30 ! fsr: truncate, no exceptions + +.word 0x44300000,0x00000000 ! 2^(52+16+0) +.word 0x46300000,0x00000000 ! 2^(52+16+32) +.word 0x48300000,0x00000000 ! 2^(52+16+64) +.word 0x4a300000,0x00000000 ! 2^(52+16+96) +.word 0x3e300000,0x00000000 ! 2^(52+16+0-96) +.word 0x40300000,0x00000000 ! 2^(52+16+32-96) +.word 0x42300000,0x00000000 ! 2^(52+16+64-96) +.asciz "Poly1305 for SPARCv9/VIS3/FMA, CRYPTOGAMS by " +.align 4 +___ +} + +# Purpose of these subroutines is to explicitly encode VIS instructions, +# so that one can compile the module without having to specify VIS +# extensions on compiler command line, e.g. -xarch=v9 vs. -xarch=v9a. +# Idea is to reserve for option to produce "universal" binary and let +# programmer detect if current CPU is VIS capable at run-time. +sub unvis3 { +my ($mnemonic,$rs1,$rs2,$rd)=@_; +my %bias = ( "g" => 0, "o" => 8, "l" => 16, "i" => 24 ); +my ($ref,$opf); +my %visopf = ( "addxc" => 0x011, + "addxccc" => 0x013, + "umulxhi" => 0x016 ); + + $ref = "$mnemonic\t$rs1,$rs2,$rd"; + + if ($opf=$visopf{$mnemonic}) { + foreach ($rs1,$rs2,$rd) { + return $ref if (!/%([goli])([0-9])/); + $_=$bias{$1}+$2; + } + + return sprintf ".word\t0x%08x !%s", + 0x81b00000|$rd<<25|$rs1<<14|$opf<<5|$rs2, + $ref; + } else { + return $ref; + } +} + +sub unfma { +my ($mnemonic,$rs1,$rs2,$rs3,$rd)=@_; +my ($ref,$opf); +my %fmaopf = ( "fmadds" => 0x1, + "fmaddd" => 0x2, + "fmsubs" => 0x5, + "fmsubd" => 0x6 ); + + $ref = "$mnemonic\t$rs1,$rs2,$rs3,$rd"; + + if ($opf=$fmaopf{$mnemonic}) { + foreach ($rs1,$rs2,$rs3,$rd) { + return $ref if (!/%f([0-9]{1,2})/); + $_=$1; + if ($1>=32) { + return $ref if ($1&1); + # re-encode for upper double register addressing + $_=($1|$1>>5)&31; + } + } + + return sprintf ".word\t0x%08x !%s", + 0x81b80000|$rd<<25|$rs1<<14|$rs3<<9|$opf<<5|$rs2, + $ref; + } else { + return $ref; + } +} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/ge; + + s/\b(umulxhi|addxc[c]{0,2})\s+(%[goli][0-7]),\s*(%[goli][0-7]),\s*(%[goli][0-7])/ + &unvis3($1,$2,$3,$4) + /ge or + s/\b(fmadd[sd])\s+(%f[0-9]+),\s*(%f[0-9]+),\s*(%f[0-9]+),\s*(%f[0-9]+)/ + &unfma($1,$2,$3,$4,$5) + /ge; + + print $_,"\n"; +} + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-x86.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-x86.pl new file mode 100755 index 000000000..1e09ddcc1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-x86.pl @@ -0,0 +1,1815 @@ +#! /usr/bin/env perl +# Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# This module implements Poly1305 hash for x86. +# +# April 2015 +# +# Numbers are cycles per processed byte with poly1305_blocks alone, +# measured with rdtsc at fixed clock frequency. +# +# IALU/gcc-3.4(*) SSE2(**) AVX2 +# Pentium 15.7/+80% - +# PIII 6.21/+90% - +# P4 19.8/+40% 3.24 +# Core 2 4.85/+90% 1.80 +# Westmere 4.58/+100% 1.43 +# Sandy Bridge 3.90/+100% 1.36 +# Haswell 3.88/+70% 1.18 0.72 +# Skylake 3.10/+60% 1.14 0.62 +# Silvermont 11.0/+40% 4.80 +# Goldmont 4.10/+200% 2.10 +# VIA Nano 6.71/+90% 2.47 +# Sledgehammer 3.51/+180% 4.27 +# Bulldozer 4.53/+140% 1.31 +# +# (*) gcc 4.8 for some reason generated worse code; +# (**) besides SSE2 there are floating-point and AVX options; FP +# is deemed unnecessary, because pre-SSE2 processor are too +# old to care about, while it's not the fastest option on +# SSE2-capable ones; AVX is omitted, because it doesn't give +# a lot of improvement, 5-10% depending on processor; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +$output=pop; +open STDOUT,">$output"; + +&asm_init($ARGV[0],$ARGV[$#ARGV] eq "386"); + +$sse2=$avx=0; +for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); } + +if ($sse2) { + &static_label("const_sse2"); + &static_label("enter_blocks"); + &static_label("enter_emit"); + &external_label("OPENSSL_ia32cap_P"); + + if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler version ([2-9]\.[0-9]+)/) { + $avx = ($1>=2.19) + ($1>=2.22); + } + + if (!$avx && $ARGV[0] eq "win32n" && + `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) { + $avx = ($1>=2.09) + ($1>=2.10); + } + + if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9]\.[0-9]+)/) { + $avx = ($2>=3.0) + ($2>3.0); + } +} + +######################################################################## +# Layout of opaque area is following. +# +# unsigned __int32 h[5]; # current hash value base 2^32 +# unsigned __int32 pad; # is_base2_26 in vector context +# unsigned __int32 r[4]; # key value base 2^32 + +&align(64); +&function_begin("poly1305_init"); + &mov ("edi",&wparam(0)); # context + &mov ("esi",&wparam(1)); # key + &mov ("ebp",&wparam(2)); # function table + + &xor ("eax","eax"); + &mov (&DWP(4*0,"edi"),"eax"); # zero hash value + &mov (&DWP(4*1,"edi"),"eax"); + &mov (&DWP(4*2,"edi"),"eax"); + &mov (&DWP(4*3,"edi"),"eax"); + &mov (&DWP(4*4,"edi"),"eax"); + &mov (&DWP(4*5,"edi"),"eax"); # is_base2_26 + + &cmp ("esi",0); + &je (&label("nokey")); + + if ($sse2) { + &call (&label("pic_point")); + &set_label("pic_point"); + &blindpop("ebx"); + + &lea ("eax",&DWP("poly1305_blocks-".&label("pic_point"),"ebx")); + &lea ("edx",&DWP("poly1305_emit-".&label("pic_point"),"ebx")); + + &picmeup("edi","OPENSSL_ia32cap_P","ebx",&label("pic_point")); + &mov ("ecx",&DWP(0,"edi")); + &and ("ecx",1<<26|1<<24); + &cmp ("ecx",1<<26|1<<24); # SSE2 and XMM? + &jne (&label("no_sse2")); + + &lea ("eax",&DWP("_poly1305_blocks_sse2-".&label("pic_point"),"ebx")); + &lea ("edx",&DWP("_poly1305_emit_sse2-".&label("pic_point"),"ebx")); + + if ($avx>1) { + &mov ("ecx",&DWP(8,"edi")); + &test ("ecx",1<<5); # AVX2? + &jz (&label("no_sse2")); + + &lea ("eax",&DWP("_poly1305_blocks_avx2-".&label("pic_point"),"ebx")); + } + &set_label("no_sse2"); + &mov ("edi",&wparam(0)); # reload context + &mov (&DWP(0,"ebp"),"eax"); # fill function table + &mov (&DWP(4,"ebp"),"edx"); + } + + &mov ("eax",&DWP(4*0,"esi")); # load input key + &mov ("ebx",&DWP(4*1,"esi")); + &mov ("ecx",&DWP(4*2,"esi")); + &mov ("edx",&DWP(4*3,"esi")); + &and ("eax",0x0fffffff); + &and ("ebx",0x0ffffffc); + &and ("ecx",0x0ffffffc); + &and ("edx",0x0ffffffc); + &mov (&DWP(4*6,"edi"),"eax"); + &mov (&DWP(4*7,"edi"),"ebx"); + &mov (&DWP(4*8,"edi"),"ecx"); + &mov (&DWP(4*9,"edi"),"edx"); + + &mov ("eax",$sse2); +&set_label("nokey"); +&function_end("poly1305_init"); + +($h0,$h1,$h2,$h3,$h4, + $d0,$d1,$d2,$d3, + $r0,$r1,$r2,$r3, + $s1,$s2,$s3)=map(4*$_,(0..15)); + +&function_begin("poly1305_blocks"); + &mov ("edi",&wparam(0)); # ctx + &mov ("esi",&wparam(1)); # inp + &mov ("ecx",&wparam(2)); # len +&set_label("enter_blocks"); + &and ("ecx",-15); + &jz (&label("nodata")); + + &stack_push(16); + &mov ("eax",&DWP(4*6,"edi")); # r0 + &mov ("ebx",&DWP(4*7,"edi")); # r1 + &lea ("ebp",&DWP(0,"esi","ecx")); # end of input + &mov ("ecx",&DWP(4*8,"edi")); # r2 + &mov ("edx",&DWP(4*9,"edi")); # r3 + + &mov (&wparam(2),"ebp"); + &mov ("ebp","esi"); + + &mov (&DWP($r0,"esp"),"eax"); # r0 + &mov ("eax","ebx"); + &shr ("eax",2); + &mov (&DWP($r1,"esp"),"ebx"); # r1 + &add ("eax","ebx"); # s1 + &mov ("ebx","ecx"); + &shr ("ebx",2); + &mov (&DWP($r2,"esp"),"ecx"); # r2 + &add ("ebx","ecx"); # s2 + &mov ("ecx","edx"); + &shr ("ecx",2); + &mov (&DWP($r3,"esp"),"edx"); # r3 + &add ("ecx","edx"); # s3 + &mov (&DWP($s1,"esp"),"eax"); # s1 + &mov (&DWP($s2,"esp"),"ebx"); # s2 + &mov (&DWP($s3,"esp"),"ecx"); # s3 + + &mov ("eax",&DWP(4*0,"edi")); # load hash value + &mov ("ebx",&DWP(4*1,"edi")); + &mov ("ecx",&DWP(4*2,"edi")); + &mov ("esi",&DWP(4*3,"edi")); + &mov ("edi",&DWP(4*4,"edi")); + &jmp (&label("loop")); + +&set_label("loop",32); + &add ("eax",&DWP(4*0,"ebp")); # accumulate input + &adc ("ebx",&DWP(4*1,"ebp")); + &adc ("ecx",&DWP(4*2,"ebp")); + &adc ("esi",&DWP(4*3,"ebp")); + &lea ("ebp",&DWP(4*4,"ebp")); + &adc ("edi",&wparam(3)); # padbit + + &mov (&DWP($h0,"esp"),"eax"); # put aside hash[+inp] + &mov (&DWP($h3,"esp"),"esi"); + + &mul (&DWP($r0,"esp")); # h0*r0 + &mov (&DWP($h4,"esp"),"edi"); + &mov ("edi","eax"); + &mov ("eax","ebx"); # h1 + &mov ("esi","edx"); + &mul (&DWP($s3,"esp")); # h1*s3 + &add ("edi","eax"); + &mov ("eax","ecx"); # h2 + &adc ("esi","edx"); + &mul (&DWP($s2,"esp")); # h2*s2 + &add ("edi","eax"); + &mov ("eax",&DWP($h3,"esp")); + &adc ("esi","edx"); + &mul (&DWP($s1,"esp")); # h3*s1 + &add ("edi","eax"); + &mov ("eax",&DWP($h0,"esp")); + &adc ("esi","edx"); + + &mul (&DWP($r1,"esp")); # h0*r1 + &mov (&DWP($d0,"esp"),"edi"); + &xor ("edi","edi"); + &add ("esi","eax"); + &mov ("eax","ebx"); # h1 + &adc ("edi","edx"); + &mul (&DWP($r0,"esp")); # h1*r0 + &add ("esi","eax"); + &mov ("eax","ecx"); # h2 + &adc ("edi","edx"); + &mul (&DWP($s3,"esp")); # h2*s3 + &add ("esi","eax"); + &mov ("eax",&DWP($h3,"esp")); + &adc ("edi","edx"); + &mul (&DWP($s2,"esp")); # h3*s2 + &add ("esi","eax"); + &mov ("eax",&DWP($h4,"esp")); + &adc ("edi","edx"); + &imul ("eax",&DWP($s1,"esp")); # h4*s1 + &add ("esi","eax"); + &mov ("eax",&DWP($h0,"esp")); + &adc ("edi",0); + + &mul (&DWP($r2,"esp")); # h0*r2 + &mov (&DWP($d1,"esp"),"esi"); + &xor ("esi","esi"); + &add ("edi","eax"); + &mov ("eax","ebx"); # h1 + &adc ("esi","edx"); + &mul (&DWP($r1,"esp")); # h1*r1 + &add ("edi","eax"); + &mov ("eax","ecx"); # h2 + &adc ("esi","edx"); + &mul (&DWP($r0,"esp")); # h2*r0 + &add ("edi","eax"); + &mov ("eax",&DWP($h3,"esp")); + &adc ("esi","edx"); + &mul (&DWP($s3,"esp")); # h3*s3 + &add ("edi","eax"); + &mov ("eax",&DWP($h4,"esp")); + &adc ("esi","edx"); + &imul ("eax",&DWP($s2,"esp")); # h4*s2 + &add ("edi","eax"); + &mov ("eax",&DWP($h0,"esp")); + &adc ("esi",0); + + &mul (&DWP($r3,"esp")); # h0*r3 + &mov (&DWP($d2,"esp"),"edi"); + &xor ("edi","edi"); + &add ("esi","eax"); + &mov ("eax","ebx"); # h1 + &adc ("edi","edx"); + &mul (&DWP($r2,"esp")); # h1*r2 + &add ("esi","eax"); + &mov ("eax","ecx"); # h2 + &adc ("edi","edx"); + &mul (&DWP($r1,"esp")); # h2*r1 + &add ("esi","eax"); + &mov ("eax",&DWP($h3,"esp")); + &adc ("edi","edx"); + &mul (&DWP($r0,"esp")); # h3*r0 + &add ("esi","eax"); + &mov ("ecx",&DWP($h4,"esp")); + &adc ("edi","edx"); + + &mov ("edx","ecx"); + &imul ("ecx",&DWP($s3,"esp")); # h4*s3 + &add ("esi","ecx"); + &mov ("eax",&DWP($d0,"esp")); + &adc ("edi",0); + + &imul ("edx",&DWP($r0,"esp")); # h4*r0 + &add ("edx","edi"); + + &mov ("ebx",&DWP($d1,"esp")); + &mov ("ecx",&DWP($d2,"esp")); + + &mov ("edi","edx"); # last reduction step + &shr ("edx",2); + &and ("edi",3); + &lea ("edx",&DWP(0,"edx","edx",4)); # *5 + &add ("eax","edx"); + &adc ("ebx",0); + &adc ("ecx",0); + &adc ("esi",0); + &adc ("edi",0); + + &cmp ("ebp",&wparam(2)); # done yet? + &jne (&label("loop")); + + &mov ("edx",&wparam(0)); # ctx + &stack_pop(16); + &mov (&DWP(4*0,"edx"),"eax"); # store hash value + &mov (&DWP(4*1,"edx"),"ebx"); + &mov (&DWP(4*2,"edx"),"ecx"); + &mov (&DWP(4*3,"edx"),"esi"); + &mov (&DWP(4*4,"edx"),"edi"); +&set_label("nodata"); +&function_end("poly1305_blocks"); + +&function_begin("poly1305_emit"); + &mov ("ebp",&wparam(0)); # context +&set_label("enter_emit"); + &mov ("edi",&wparam(1)); # output + &mov ("eax",&DWP(4*0,"ebp")); # load hash value + &mov ("ebx",&DWP(4*1,"ebp")); + &mov ("ecx",&DWP(4*2,"ebp")); + &mov ("edx",&DWP(4*3,"ebp")); + &mov ("esi",&DWP(4*4,"ebp")); + + &add ("eax",5); # compare to modulus + &adc ("ebx",0); + &adc ("ecx",0); + &adc ("edx",0); + &adc ("esi",0); + &shr ("esi",2); # did it carry/borrow? + &neg ("esi"); # do we choose hash-modulus? + + &and ("eax","esi"); + &and ("ebx","esi"); + &and ("ecx","esi"); + &and ("edx","esi"); + &mov (&DWP(4*0,"edi"),"eax"); + &mov (&DWP(4*1,"edi"),"ebx"); + &mov (&DWP(4*2,"edi"),"ecx"); + &mov (&DWP(4*3,"edi"),"edx"); + + ¬ ("esi"); # or original hash value? + &mov ("eax",&DWP(4*0,"ebp")); + &mov ("ebx",&DWP(4*1,"ebp")); + &mov ("ecx",&DWP(4*2,"ebp")); + &mov ("edx",&DWP(4*3,"ebp")); + &mov ("ebp",&wparam(2)); + &and ("eax","esi"); + &and ("ebx","esi"); + &and ("ecx","esi"); + &and ("edx","esi"); + &or ("eax",&DWP(4*0,"edi")); + &or ("ebx",&DWP(4*1,"edi")); + &or ("ecx",&DWP(4*2,"edi")); + &or ("edx",&DWP(4*3,"edi")); + + &add ("eax",&DWP(4*0,"ebp")); # accumulate key + &adc ("ebx",&DWP(4*1,"ebp")); + &adc ("ecx",&DWP(4*2,"ebp")); + &adc ("edx",&DWP(4*3,"ebp")); + + &mov (&DWP(4*0,"edi"),"eax"); + &mov (&DWP(4*1,"edi"),"ebx"); + &mov (&DWP(4*2,"edi"),"ecx"); + &mov (&DWP(4*3,"edi"),"edx"); +&function_end("poly1305_emit"); + +if ($sse2) { +######################################################################## +# Layout of opaque area is following. +# +# unsigned __int32 h[5]; # current hash value base 2^26 +# unsigned __int32 is_base2_26; +# unsigned __int32 r[4]; # key value base 2^32 +# unsigned __int32 pad[2]; +# struct { unsigned __int32 r^4, r^3, r^2, r^1; } r[9]; +# +# where r^n are base 2^26 digits of degrees of multiplier key. There are +# 5 digits, but last four are interleaved with multiples of 5, totalling +# in 9 elements: r0, r1, 5*r1, r2, 5*r2, r3, 5*r3, r4, 5*r4. + +my ($D0,$D1,$D2,$D3,$D4,$T0,$T1,$T2)=map("xmm$_",(0..7)); +my $MASK=$T2; # borrow and keep in mind + +&align (32); +&function_begin_B("_poly1305_init_sse2"); + &movdqu ($D4,&QWP(4*6,"edi")); # key base 2^32 + &lea ("edi",&DWP(16*3,"edi")); # size optimization + &mov ("ebp","esp"); + &sub ("esp",16*(9+5)); + &and ("esp",-16); + + #&pand ($D4,&QWP(96,"ebx")); # magic mask + &movq ($MASK,&QWP(64,"ebx")); + + &movdqa ($D0,$D4); + &movdqa ($D1,$D4); + &movdqa ($D2,$D4); + + &pand ($D0,$MASK); # -> base 2^26 + &psrlq ($D1,26); + &psrldq ($D2,6); + &pand ($D1,$MASK); + &movdqa ($D3,$D2); + &psrlq ($D2,4) + &psrlq ($D3,30); + &pand ($D2,$MASK); + &pand ($D3,$MASK); + &psrldq ($D4,13); + + &lea ("edx",&DWP(16*9,"esp")); # size optimization + &mov ("ecx",2); +&set_label("square"); + &movdqa (&QWP(16*0,"esp"),$D0); + &movdqa (&QWP(16*1,"esp"),$D1); + &movdqa (&QWP(16*2,"esp"),$D2); + &movdqa (&QWP(16*3,"esp"),$D3); + &movdqa (&QWP(16*4,"esp"),$D4); + + &movdqa ($T1,$D1); + &movdqa ($T0,$D2); + &pslld ($T1,2); + &pslld ($T0,2); + &paddd ($T1,$D1); # *5 + &paddd ($T0,$D2); # *5 + &movdqa (&QWP(16*5,"esp"),$T1); + &movdqa (&QWP(16*6,"esp"),$T0); + &movdqa ($T1,$D3); + &movdqa ($T0,$D4); + &pslld ($T1,2); + &pslld ($T0,2); + &paddd ($T1,$D3); # *5 + &paddd ($T0,$D4); # *5 + &movdqa (&QWP(16*7,"esp"),$T1); + &movdqa (&QWP(16*8,"esp"),$T0); + + &pshufd ($T1,$D0,0b01000100); + &movdqa ($T0,$D1); + &pshufd ($D1,$D1,0b01000100); + &pshufd ($D2,$D2,0b01000100); + &pshufd ($D3,$D3,0b01000100); + &pshufd ($D4,$D4,0b01000100); + &movdqa (&QWP(16*0,"edx"),$T1); + &movdqa (&QWP(16*1,"edx"),$D1); + &movdqa (&QWP(16*2,"edx"),$D2); + &movdqa (&QWP(16*3,"edx"),$D3); + &movdqa (&QWP(16*4,"edx"),$D4); + + ################################################################ + # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + + &pmuludq ($D4,$D0); # h4*r0 + &pmuludq ($D3,$D0); # h3*r0 + &pmuludq ($D2,$D0); # h2*r0 + &pmuludq ($D1,$D0); # h1*r0 + &pmuludq ($D0,$T1); # h0*r0 + +sub pmuladd { +my $load = shift; +my $base = shift; $base = "esp" if (!defined($base)); + + ################################################################ + # As for choice to "rotate" $T0-$T2 in order to move paddq + # past next multiplication. While it makes code harder to read + # and doesn't have significant effect on most processors, it + # makes a lot of difference on Atom, up to 30% improvement. + + &movdqa ($T1,$T0); + &pmuludq ($T0,&QWP(16*3,$base)); # r1*h3 + &movdqa ($T2,$T1); + &pmuludq ($T1,&QWP(16*2,$base)); # r1*h2 + &paddq ($D4,$T0); + &movdqa ($T0,$T2); + &pmuludq ($T2,&QWP(16*1,$base)); # r1*h1 + &paddq ($D3,$T1); + &$load ($T1,5); # s1 + &pmuludq ($T0,&QWP(16*0,$base)); # r1*h0 + &paddq ($D2,$T2); + &pmuludq ($T1,&QWP(16*4,$base)); # s1*h4 + &$load ($T2,2); # r2^n + &paddq ($D1,$T0); + + &movdqa ($T0,$T2); + &pmuludq ($T2,&QWP(16*2,$base)); # r2*h2 + &paddq ($D0,$T1); + &movdqa ($T1,$T0); + &pmuludq ($T0,&QWP(16*1,$base)); # r2*h1 + &paddq ($D4,$T2); + &$load ($T2,6); # s2^n + &pmuludq ($T1,&QWP(16*0,$base)); # r2*h0 + &paddq ($D3,$T0); + &movdqa ($T0,$T2); + &pmuludq ($T2,&QWP(16*4,$base)); # s2*h4 + &paddq ($D2,$T1); + &pmuludq ($T0,&QWP(16*3,$base)); # s2*h3 + &$load ($T1,3); # r3^n + &paddq ($D1,$T2); + + &movdqa ($T2,$T1); + &pmuludq ($T1,&QWP(16*1,$base)); # r3*h1 + &paddq ($D0,$T0); + &$load ($T0,7); # s3^n + &pmuludq ($T2,&QWP(16*0,$base)); # r3*h0 + &paddq ($D4,$T1); + &movdqa ($T1,$T0); + &pmuludq ($T0,&QWP(16*4,$base)); # s3*h4 + &paddq ($D3,$T2); + &movdqa ($T2,$T1); + &pmuludq ($T1,&QWP(16*3,$base)); # s3*h3 + &paddq ($D2,$T0); + &pmuludq ($T2,&QWP(16*2,$base)); # s3*h2 + &$load ($T0,4); # r4^n + &paddq ($D1,$T1); + + &$load ($T1,8); # s4^n + &pmuludq ($T0,&QWP(16*0,$base)); # r4*h0 + &paddq ($D0,$T2); + &movdqa ($T2,$T1); + &pmuludq ($T1,&QWP(16*4,$base)); # s4*h4 + &paddq ($D4,$T0); + &movdqa ($T0,$T2); + &pmuludq ($T2,&QWP(16*1,$base)); # s4*h1 + &paddq ($D3,$T1); + &movdqa ($T1,$T0); + &pmuludq ($T0,&QWP(16*2,$base)); # s4*h2 + &paddq ($D0,$T2); + &pmuludq ($T1,&QWP(16*3,$base)); # s4*h3 + &movdqa ($MASK,&QWP(64,"ebx")); + &paddq ($D1,$T0); + &paddq ($D2,$T1); +} + &pmuladd (sub { my ($reg,$i)=@_; + &movdqa ($reg,&QWP(16*$i,"esp")); + },"edx"); + +sub lazy_reduction { +my $extra = shift; + + ################################################################ + # lazy reduction as discussed in "NEON crypto" by D.J. Bernstein + # and P. Schwabe + # + # [(*) see discussion in poly1305-armv4 module] + + &movdqa ($T0,$D3); + &pand ($D3,$MASK); + &psrlq ($T0,26); + &$extra () if (defined($extra)); + &paddq ($T0,$D4); # h3 -> h4 + &movdqa ($T1,$D0); + &pand ($D0,$MASK); + &psrlq ($T1,26); + &movdqa ($D4,$T0); + &paddq ($T1,$D1); # h0 -> h1 + &psrlq ($T0,26); + &pand ($D4,$MASK); + &movdqa ($D1,$T1); + &psrlq ($T1,26); + &paddd ($D0,$T0); # favour paddd when + # possible, because + # paddq is "broken" + # on Atom + &psllq ($T0,2); + &paddq ($T1,$D2); # h1 -> h2 + &paddq ($T0,$D0); # h4 -> h0 (*) + &pand ($D1,$MASK); + &movdqa ($D2,$T1); + &psrlq ($T1,26); + &pand ($D2,$MASK); + &paddd ($T1,$D3); # h2 -> h3 + &movdqa ($D0,$T0); + &psrlq ($T0,26); + &movdqa ($D3,$T1); + &psrlq ($T1,26); + &pand ($D0,$MASK); + &paddd ($D1,$T0); # h0 -> h1 + &pand ($D3,$MASK); + &paddd ($D4,$T1); # h3 -> h4 +} + &lazy_reduction (); + + &dec ("ecx"); + &jz (&label("square_break")); + + &punpcklqdq ($D0,&QWP(16*0,"esp")); # 0:r^1:0:r^2 + &punpcklqdq ($D1,&QWP(16*1,"esp")); + &punpcklqdq ($D2,&QWP(16*2,"esp")); + &punpcklqdq ($D3,&QWP(16*3,"esp")); + &punpcklqdq ($D4,&QWP(16*4,"esp")); + &jmp (&label("square")); + +&set_label("square_break"); + &psllq ($D0,32); # -> r^3:0:r^4:0 + &psllq ($D1,32); + &psllq ($D2,32); + &psllq ($D3,32); + &psllq ($D4,32); + &por ($D0,&QWP(16*0,"esp")); # r^3:r^1:r^4:r^2 + &por ($D1,&QWP(16*1,"esp")); + &por ($D2,&QWP(16*2,"esp")); + &por ($D3,&QWP(16*3,"esp")); + &por ($D4,&QWP(16*4,"esp")); + + &pshufd ($D0,$D0,0b10001101); # -> r^1:r^2:r^3:r^4 + &pshufd ($D1,$D1,0b10001101); + &pshufd ($D2,$D2,0b10001101); + &pshufd ($D3,$D3,0b10001101); + &pshufd ($D4,$D4,0b10001101); + + &movdqu (&QWP(16*0,"edi"),$D0); # save the table + &movdqu (&QWP(16*1,"edi"),$D1); + &movdqu (&QWP(16*2,"edi"),$D2); + &movdqu (&QWP(16*3,"edi"),$D3); + &movdqu (&QWP(16*4,"edi"),$D4); + + &movdqa ($T1,$D1); + &movdqa ($T0,$D2); + &pslld ($T1,2); + &pslld ($T0,2); + &paddd ($T1,$D1); # *5 + &paddd ($T0,$D2); # *5 + &movdqu (&QWP(16*5,"edi"),$T1); + &movdqu (&QWP(16*6,"edi"),$T0); + &movdqa ($T1,$D3); + &movdqa ($T0,$D4); + &pslld ($T1,2); + &pslld ($T0,2); + &paddd ($T1,$D3); # *5 + &paddd ($T0,$D4); # *5 + &movdqu (&QWP(16*7,"edi"),$T1); + &movdqu (&QWP(16*8,"edi"),$T0); + + &mov ("esp","ebp"); + &lea ("edi",&DWP(-16*3,"edi")); # size de-optimization + &ret (); +&function_end_B("_poly1305_init_sse2"); + +&align (32); +&function_begin("_poly1305_blocks_sse2"); + &mov ("edi",&wparam(0)); # ctx + &mov ("esi",&wparam(1)); # inp + &mov ("ecx",&wparam(2)); # len + + &mov ("eax",&DWP(4*5,"edi")); # is_base2_26 + &and ("ecx",-16); + &jz (&label("nodata")); + &cmp ("ecx",64); + &jae (&label("enter_sse2")); + &test ("eax","eax"); # is_base2_26? + &jz (&label("enter_blocks")); + +&set_label("enter_sse2",16); + &call (&label("pic_point")); +&set_label("pic_point"); + &blindpop("ebx"); + &lea ("ebx",&DWP(&label("const_sse2")."-".&label("pic_point"),"ebx")); + + &test ("eax","eax"); # is_base2_26? + &jnz (&label("base2_26")); + + &call ("_poly1305_init_sse2"); + + ################################################# base 2^32 -> base 2^26 + &mov ("eax",&DWP(0,"edi")); + &mov ("ecx",&DWP(3,"edi")); + &mov ("edx",&DWP(6,"edi")); + &mov ("esi",&DWP(9,"edi")); + &mov ("ebp",&DWP(13,"edi")); + &mov (&DWP(4*5,"edi"),1); # is_base2_26 + + &shr ("ecx",2); + &and ("eax",0x3ffffff); + &shr ("edx",4); + &and ("ecx",0x3ffffff); + &shr ("esi",6); + &and ("edx",0x3ffffff); + + &movd ($D0,"eax"); + &movd ($D1,"ecx"); + &movd ($D2,"edx"); + &movd ($D3,"esi"); + &movd ($D4,"ebp"); + + &mov ("esi",&wparam(1)); # [reload] inp + &mov ("ecx",&wparam(2)); # [reload] len + &jmp (&label("base2_32")); + +&set_label("base2_26",16); + &movd ($D0,&DWP(4*0,"edi")); # load hash value + &movd ($D1,&DWP(4*1,"edi")); + &movd ($D2,&DWP(4*2,"edi")); + &movd ($D3,&DWP(4*3,"edi")); + &movd ($D4,&DWP(4*4,"edi")); + &movdqa ($MASK,&QWP(64,"ebx")); + +&set_label("base2_32"); + &mov ("eax",&wparam(3)); # padbit + &mov ("ebp","esp"); + + &sub ("esp",16*(5+5+5+9+9)); + &and ("esp",-16); + + &lea ("edi",&DWP(16*3,"edi")); # size optimization + &shl ("eax",24); # padbit + + &test ("ecx",31); + &jz (&label("even")); + + ################################################################ + # process single block, with SSE2, because it's still faster + # even though half of result is discarded + + &movdqu ($T1,&QWP(0,"esi")); # input + &lea ("esi",&DWP(16,"esi")); + + &movdqa ($T0,$T1); # -> base 2^26 ... + &pand ($T1,$MASK); + &paddd ($D0,$T1); # ... and accumulate + + &movdqa ($T1,$T0); + &psrlq ($T0,26); + &psrldq ($T1,6); + &pand ($T0,$MASK); + &paddd ($D1,$T0); + + &movdqa ($T0,$T1); + &psrlq ($T1,4); + &pand ($T1,$MASK); + &paddd ($D2,$T1); + + &movdqa ($T1,$T0); + &psrlq ($T0,30); + &pand ($T0,$MASK); + &psrldq ($T1,7); + &paddd ($D3,$T0); + + &movd ($T0,"eax"); # padbit + &paddd ($D4,$T1); + &movd ($T1,&DWP(16*0+12,"edi")); # r0 + &paddd ($D4,$T0); + + &movdqa (&QWP(16*0,"esp"),$D0); + &movdqa (&QWP(16*1,"esp"),$D1); + &movdqa (&QWP(16*2,"esp"),$D2); + &movdqa (&QWP(16*3,"esp"),$D3); + &movdqa (&QWP(16*4,"esp"),$D4); + + ################################################################ + # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + + &pmuludq ($D0,$T1); # h4*r0 + &pmuludq ($D1,$T1); # h3*r0 + &pmuludq ($D2,$T1); # h2*r0 + &movd ($T0,&DWP(16*1+12,"edi")); # r1 + &pmuludq ($D3,$T1); # h1*r0 + &pmuludq ($D4,$T1); # h0*r0 + + &pmuladd (sub { my ($reg,$i)=@_; + &movd ($reg,&DWP(16*$i+12,"edi")); + }); + + &lazy_reduction (); + + &sub ("ecx",16); + &jz (&label("done")); + +&set_label("even"); + &lea ("edx",&DWP(16*(5+5+5+9),"esp"));# size optimization + &lea ("eax",&DWP(-16*2,"esi")); + &sub ("ecx",64); + + ################################################################ + # expand and copy pre-calculated table to stack + + &movdqu ($T0,&QWP(16*0,"edi")); # r^1:r^2:r^3:r^4 + &pshufd ($T1,$T0,0b01000100); # duplicate r^3:r^4 + &cmovb ("esi","eax"); + &pshufd ($T0,$T0,0b11101110); # duplicate r^1:r^2 + &movdqa (&QWP(16*0,"edx"),$T1); + &lea ("eax",&DWP(16*10,"esp")); + &movdqu ($T1,&QWP(16*1,"edi")); + &movdqa (&QWP(16*(0-9),"edx"),$T0); + &pshufd ($T0,$T1,0b01000100); + &pshufd ($T1,$T1,0b11101110); + &movdqa (&QWP(16*1,"edx"),$T0); + &movdqu ($T0,&QWP(16*2,"edi")); + &movdqa (&QWP(16*(1-9),"edx"),$T1); + &pshufd ($T1,$T0,0b01000100); + &pshufd ($T0,$T0,0b11101110); + &movdqa (&QWP(16*2,"edx"),$T1); + &movdqu ($T1,&QWP(16*3,"edi")); + &movdqa (&QWP(16*(2-9),"edx"),$T0); + &pshufd ($T0,$T1,0b01000100); + &pshufd ($T1,$T1,0b11101110); + &movdqa (&QWP(16*3,"edx"),$T0); + &movdqu ($T0,&QWP(16*4,"edi")); + &movdqa (&QWP(16*(3-9),"edx"),$T1); + &pshufd ($T1,$T0,0b01000100); + &pshufd ($T0,$T0,0b11101110); + &movdqa (&QWP(16*4,"edx"),$T1); + &movdqu ($T1,&QWP(16*5,"edi")); + &movdqa (&QWP(16*(4-9),"edx"),$T0); + &pshufd ($T0,$T1,0b01000100); + &pshufd ($T1,$T1,0b11101110); + &movdqa (&QWP(16*5,"edx"),$T0); + &movdqu ($T0,&QWP(16*6,"edi")); + &movdqa (&QWP(16*(5-9),"edx"),$T1); + &pshufd ($T1,$T0,0b01000100); + &pshufd ($T0,$T0,0b11101110); + &movdqa (&QWP(16*6,"edx"),$T1); + &movdqu ($T1,&QWP(16*7,"edi")); + &movdqa (&QWP(16*(6-9),"edx"),$T0); + &pshufd ($T0,$T1,0b01000100); + &pshufd ($T1,$T1,0b11101110); + &movdqa (&QWP(16*7,"edx"),$T0); + &movdqu ($T0,&QWP(16*8,"edi")); + &movdqa (&QWP(16*(7-9),"edx"),$T1); + &pshufd ($T1,$T0,0b01000100); + &pshufd ($T0,$T0,0b11101110); + &movdqa (&QWP(16*8,"edx"),$T1); + &movdqa (&QWP(16*(8-9),"edx"),$T0); + +sub load_input { +my ($inpbase,$offbase)=@_; + + &movdqu ($T0,&QWP($inpbase+0,"esi")); # load input + &movdqu ($T1,&QWP($inpbase+16,"esi")); + &lea ("esi",&DWP(16*2,"esi")); + + &movdqa (&QWP($offbase+16*2,"esp"),$D2); + &movdqa (&QWP($offbase+16*3,"esp"),$D3); + &movdqa (&QWP($offbase+16*4,"esp"),$D4); + + &movdqa ($D2,$T0); # splat input + &movdqa ($D3,$T1); + &psrldq ($D2,6); + &psrldq ($D3,6); + &movdqa ($D4,$T0); + &punpcklqdq ($D2,$D3); # 2:3 + &punpckhqdq ($D4,$T1); # 4 + &punpcklqdq ($T0,$T1); # 0:1 + + &movdqa ($D3,$D2); + &psrlq ($D2,4); + &psrlq ($D3,30); + &movdqa ($T1,$T0); + &psrlq ($D4,40); # 4 + &psrlq ($T1,26); + &pand ($T0,$MASK); # 0 + &pand ($T1,$MASK); # 1 + &pand ($D2,$MASK); # 2 + &pand ($D3,$MASK); # 3 + &por ($D4,&QWP(0,"ebx")); # padbit, yes, always + + &movdqa (&QWP($offbase+16*0,"esp"),$D0) if ($offbase); + &movdqa (&QWP($offbase+16*1,"esp"),$D1) if ($offbase); +} + &load_input (16*2,16*5); + + &jbe (&label("skip_loop")); + &jmp (&label("loop")); + +&set_label("loop",32); + ################################################################ + # ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2 + # ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^3+inp[7]*r + # \___________________/ + # ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2+inp[8])*r^2 + # ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^4+inp[7]*r^2+inp[9])*r + # \___________________/ \____________________/ + ################################################################ + + &movdqa ($T2,&QWP(16*(0-9),"edx")); # r0^2 + &movdqa (&QWP(16*1,"eax"),$T1); + &movdqa (&QWP(16*2,"eax"),$D2); + &movdqa (&QWP(16*3,"eax"),$D3); + &movdqa (&QWP(16*4,"eax"),$D4); + + ################################################################ + # d4 = h4*r0 + h0*r4 + h1*r3 + h2*r2 + h3*r1 + # d3 = h3*r0 + h0*r3 + h1*r2 + h2*r1 + h4*5*r4 + # d2 = h2*r0 + h0*r2 + h1*r1 + h3*5*r4 + h4*5*r3 + # d1 = h1*r0 + h0*r1 + h2*5*r4 + h3*5*r3 + h4*5*r2 + # d0 = h0*r0 + h1*5*r4 + h2*5*r3 + h3*5*r2 + h4*5*r1 + + &movdqa ($D1,$T0); + &pmuludq ($T0,$T2); # h0*r0 + &movdqa ($D0,$T1); + &pmuludq ($T1,$T2); # h1*r0 + &pmuludq ($D2,$T2); # h2*r0 + &pmuludq ($D3,$T2); # h3*r0 + &pmuludq ($D4,$T2); # h4*r0 + +sub pmuladd_alt { +my $addr = shift; + + &pmuludq ($D0,&$addr(8)); # h1*s4 + &movdqa ($T2,$D1); + &pmuludq ($D1,&$addr(1)); # h0*r1 + &paddq ($D0,$T0); + &movdqa ($T0,$T2); + &pmuludq ($T2,&$addr(2)); # h0*r2 + &paddq ($D1,$T1); + &movdqa ($T1,$T0); + &pmuludq ($T0,&$addr(3)); # h0*r3 + &paddq ($D2,$T2); + &movdqa ($T2,&QWP(16*1,"eax")); # pull h1 + &pmuludq ($T1,&$addr(4)); # h0*r4 + &paddq ($D3,$T0); + + &movdqa ($T0,$T2); + &pmuludq ($T2,&$addr(1)); # h1*r1 + &paddq ($D4,$T1); + &movdqa ($T1,$T0); + &pmuludq ($T0,&$addr(2)); # h1*r2 + &paddq ($D2,$T2); + &movdqa ($T2,&QWP(16*2,"eax")); # pull h2 + &pmuludq ($T1,&$addr(3)); # h1*r3 + &paddq ($D3,$T0); + &movdqa ($T0,$T2); + &pmuludq ($T2,&$addr(7)); # h2*s3 + &paddq ($D4,$T1); + &movdqa ($T1,$T0); + &pmuludq ($T0,&$addr(8)); # h2*s4 + &paddq ($D0,$T2); + + &movdqa ($T2,$T1); + &pmuludq ($T1,&$addr(1)); # h2*r1 + &paddq ($D1,$T0); + &movdqa ($T0,&QWP(16*3,"eax")); # pull h3 + &pmuludq ($T2,&$addr(2)); # h2*r2 + &paddq ($D3,$T1); + &movdqa ($T1,$T0); + &pmuludq ($T0,&$addr(6)); # h3*s2 + &paddq ($D4,$T2); + &movdqa ($T2,$T1); + &pmuludq ($T1,&$addr(7)); # h3*s3 + &paddq ($D0,$T0); + &movdqa ($T0,$T2); + &pmuludq ($T2,&$addr(8)); # h3*s4 + &paddq ($D1,$T1); + + &movdqa ($T1,&QWP(16*4,"eax")); # pull h4 + &pmuludq ($T0,&$addr(1)); # h3*r1 + &paddq ($D2,$T2); + &movdqa ($T2,$T1); + &pmuludq ($T1,&$addr(8)); # h4*s4 + &paddq ($D4,$T0); + &movdqa ($T0,$T2); + &pmuludq ($T2,&$addr(5)); # h4*s1 + &paddq ($D3,$T1); + &movdqa ($T1,$T0); + &pmuludq ($T0,&$addr(6)); # h4*s2 + &paddq ($D0,$T2); + &movdqa ($MASK,&QWP(64,"ebx")); + &pmuludq ($T1,&$addr(7)); # h4*s3 + &paddq ($D1,$T0); + &paddq ($D2,$T1); +} + &pmuladd_alt (sub { my $i=shift; &QWP(16*($i-9),"edx"); }); + + &load_input (-16*2,0); + &lea ("eax",&DWP(-16*2,"esi")); + &sub ("ecx",64); + + &paddd ($T0,&QWP(16*(5+0),"esp")); # add hash value + &paddd ($T1,&QWP(16*(5+1),"esp")); + &paddd ($D2,&QWP(16*(5+2),"esp")); + &paddd ($D3,&QWP(16*(5+3),"esp")); + &paddd ($D4,&QWP(16*(5+4),"esp")); + + &cmovb ("esi","eax"); + &lea ("eax",&DWP(16*10,"esp")); + + &movdqa ($T2,&QWP(16*0,"edx")); # r0^4 + &movdqa (&QWP(16*1,"esp"),$D1); + &movdqa (&QWP(16*1,"eax"),$T1); + &movdqa (&QWP(16*2,"eax"),$D2); + &movdqa (&QWP(16*3,"eax"),$D3); + &movdqa (&QWP(16*4,"eax"),$D4); + + ################################################################ + # d4 += h4*r0 + h0*r4 + h1*r3 + h2*r2 + h3*r1 + # d3 += h3*r0 + h0*r3 + h1*r2 + h2*r1 + h4*5*r4 + # d2 += h2*r0 + h0*r2 + h1*r1 + h3*5*r4 + h4*5*r3 + # d1 += h1*r0 + h0*r1 + h2*5*r4 + h3*5*r3 + h4*5*r2 + # d0 += h0*r0 + h1*5*r4 + h2*5*r3 + h3*5*r2 + h4*5*r1 + + &movdqa ($D1,$T0); + &pmuludq ($T0,$T2); # h0*r0 + &paddq ($T0,$D0); + &movdqa ($D0,$T1); + &pmuludq ($T1,$T2); # h1*r0 + &pmuludq ($D2,$T2); # h2*r0 + &pmuludq ($D3,$T2); # h3*r0 + &pmuludq ($D4,$T2); # h4*r0 + + &paddq ($T1,&QWP(16*1,"esp")); + &paddq ($D2,&QWP(16*2,"esp")); + &paddq ($D3,&QWP(16*3,"esp")); + &paddq ($D4,&QWP(16*4,"esp")); + + &pmuladd_alt (sub { my $i=shift; &QWP(16*$i,"edx"); }); + + &lazy_reduction (); + + &load_input (16*2,16*5); + + &ja (&label("loop")); + +&set_label("skip_loop"); + ################################################################ + # multiply (inp[0:1]+hash) or inp[2:3] by r^2:r^1 + + &pshufd ($T2,&QWP(16*(0-9),"edx"),0x10);# r0^n + &add ("ecx",32); + &jnz (&label("long_tail")); + + &paddd ($T0,$D0); # add hash value + &paddd ($T1,$D1); + &paddd ($D2,&QWP(16*7,"esp")); + &paddd ($D3,&QWP(16*8,"esp")); + &paddd ($D4,&QWP(16*9,"esp")); + +&set_label("long_tail"); + + &movdqa (&QWP(16*0,"eax"),$T0); + &movdqa (&QWP(16*1,"eax"),$T1); + &movdqa (&QWP(16*2,"eax"),$D2); + &movdqa (&QWP(16*3,"eax"),$D3); + &movdqa (&QWP(16*4,"eax"),$D4); + + ################################################################ + # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + + &pmuludq ($T0,$T2); # h0*r0 + &pmuludq ($T1,$T2); # h1*r0 + &pmuludq ($D2,$T2); # h2*r0 + &movdqa ($D0,$T0); + &pshufd ($T0,&QWP(16*(1-9),"edx"),0x10);# r1^n + &pmuludq ($D3,$T2); # h3*r0 + &movdqa ($D1,$T1); + &pmuludq ($D4,$T2); # h4*r0 + + &pmuladd (sub { my ($reg,$i)=@_; + &pshufd ($reg,&QWP(16*($i-9),"edx"),0x10); + },"eax"); + + &jz (&label("short_tail")); + + &load_input (-16*2,0); + + &pshufd ($T2,&QWP(16*0,"edx"),0x10); # r0^n + &paddd ($T0,&QWP(16*5,"esp")); # add hash value + &paddd ($T1,&QWP(16*6,"esp")); + &paddd ($D2,&QWP(16*7,"esp")); + &paddd ($D3,&QWP(16*8,"esp")); + &paddd ($D4,&QWP(16*9,"esp")); + + ################################################################ + # multiply inp[0:1] by r^4:r^3 and accumulate + + &movdqa (&QWP(16*0,"esp"),$T0); + &pmuludq ($T0,$T2); # h0*r0 + &movdqa (&QWP(16*1,"esp"),$T1); + &pmuludq ($T1,$T2); # h1*r0 + &paddq ($D0,$T0); + &movdqa ($T0,$D2); + &pmuludq ($D2,$T2); # h2*r0 + &paddq ($D1,$T1); + &movdqa ($T1,$D3); + &pmuludq ($D3,$T2); # h3*r0 + &paddq ($D2,&QWP(16*2,"esp")); + &movdqa (&QWP(16*2,"esp"),$T0); + &pshufd ($T0,&QWP(16*1,"edx"),0x10); # r1^n + &paddq ($D3,&QWP(16*3,"esp")); + &movdqa (&QWP(16*3,"esp"),$T1); + &movdqa ($T1,$D4); + &pmuludq ($D4,$T2); # h4*r0 + &paddq ($D4,&QWP(16*4,"esp")); + &movdqa (&QWP(16*4,"esp"),$T1); + + &pmuladd (sub { my ($reg,$i)=@_; + &pshufd ($reg,&QWP(16*$i,"edx"),0x10); + }); + +&set_label("short_tail"); + + ################################################################ + # horizontal addition + + &pshufd ($T1,$D4,0b01001110); + &pshufd ($T0,$D3,0b01001110); + &paddq ($D4,$T1); + &paddq ($D3,$T0); + &pshufd ($T1,$D0,0b01001110); + &pshufd ($T0,$D1,0b01001110); + &paddq ($D0,$T1); + &paddq ($D1,$T0); + &pshufd ($T1,$D2,0b01001110); + #&paddq ($D2,$T1); + + &lazy_reduction (sub { &paddq ($D2,$T1) }); + +&set_label("done"); + &movd (&DWP(-16*3+4*0,"edi"),$D0); # store hash value + &movd (&DWP(-16*3+4*1,"edi"),$D1); + &movd (&DWP(-16*3+4*2,"edi"),$D2); + &movd (&DWP(-16*3+4*3,"edi"),$D3); + &movd (&DWP(-16*3+4*4,"edi"),$D4); + &mov ("esp","ebp"); +&set_label("nodata"); +&function_end("_poly1305_blocks_sse2"); + +&align (32); +&function_begin("_poly1305_emit_sse2"); + &mov ("ebp",&wparam(0)); # context + + &cmp (&DWP(4*5,"ebp"),0); # is_base2_26? + &je (&label("enter_emit")); + + &mov ("eax",&DWP(4*0,"ebp")); # load hash value + &mov ("edi",&DWP(4*1,"ebp")); + &mov ("ecx",&DWP(4*2,"ebp")); + &mov ("edx",&DWP(4*3,"ebp")); + &mov ("esi",&DWP(4*4,"ebp")); + + &mov ("ebx","edi"); # base 2^26 -> base 2^32 + &shl ("edi",26); + &shr ("ebx",6); + &add ("eax","edi"); + &mov ("edi","ecx"); + &adc ("ebx",0); + + &shl ("edi",20); + &shr ("ecx",12); + &add ("ebx","edi"); + &mov ("edi","edx"); + &adc ("ecx",0); + + &shl ("edi",14); + &shr ("edx",18); + &add ("ecx","edi"); + &mov ("edi","esi"); + &adc ("edx",0); + + &shl ("edi",8); + &shr ("esi",24); + &add ("edx","edi"); + &adc ("esi",0); # can be partially reduced + + &mov ("edi","esi"); # final reduction + &and ("esi",3); + &shr ("edi",2); + &lea ("ebp",&DWP(0,"edi","edi",4)); # *5 + &mov ("edi",&wparam(1)); # output + &add ("eax","ebp"); + &mov ("ebp",&wparam(2)); # key + &adc ("ebx",0); + &adc ("ecx",0); + &adc ("edx",0); + &adc ("esi",0); + + &movd ($D0,"eax"); # offload original hash value + &add ("eax",5); # compare to modulus + &movd ($D1,"ebx"); + &adc ("ebx",0); + &movd ($D2,"ecx"); + &adc ("ecx",0); + &movd ($D3,"edx"); + &adc ("edx",0); + &adc ("esi",0); + &shr ("esi",2); # did it carry/borrow? + + &neg ("esi"); # do we choose (hash-modulus) ... + &and ("eax","esi"); + &and ("ebx","esi"); + &and ("ecx","esi"); + &and ("edx","esi"); + &mov (&DWP(4*0,"edi"),"eax"); + &movd ("eax",$D0); + &mov (&DWP(4*1,"edi"),"ebx"); + &movd ("ebx",$D1); + &mov (&DWP(4*2,"edi"),"ecx"); + &movd ("ecx",$D2); + &mov (&DWP(4*3,"edi"),"edx"); + &movd ("edx",$D3); + + ¬ ("esi"); # ... or original hash value? + &and ("eax","esi"); + &and ("ebx","esi"); + &or ("eax",&DWP(4*0,"edi")); + &and ("ecx","esi"); + &or ("ebx",&DWP(4*1,"edi")); + &and ("edx","esi"); + &or ("ecx",&DWP(4*2,"edi")); + &or ("edx",&DWP(4*3,"edi")); + + &add ("eax",&DWP(4*0,"ebp")); # accumulate key + &adc ("ebx",&DWP(4*1,"ebp")); + &mov (&DWP(4*0,"edi"),"eax"); + &adc ("ecx",&DWP(4*2,"ebp")); + &mov (&DWP(4*1,"edi"),"ebx"); + &adc ("edx",&DWP(4*3,"ebp")); + &mov (&DWP(4*2,"edi"),"ecx"); + &mov (&DWP(4*3,"edi"),"edx"); +&function_end("_poly1305_emit_sse2"); + +if ($avx>1) { +######################################################################## +# Note that poly1305_init_avx2 operates on %xmm, I could have used +# poly1305_init_sse2... + +&align (32); +&function_begin_B("_poly1305_init_avx2"); + &vmovdqu ($D4,&QWP(4*6,"edi")); # key base 2^32 + &lea ("edi",&DWP(16*3,"edi")); # size optimization + &mov ("ebp","esp"); + &sub ("esp",16*(9+5)); + &and ("esp",-16); + + #&vpand ($D4,$D4,&QWP(96,"ebx")); # magic mask + &vmovdqa ($MASK,&QWP(64,"ebx")); + + &vpand ($D0,$D4,$MASK); # -> base 2^26 + &vpsrlq ($D1,$D4,26); + &vpsrldq ($D3,$D4,6); + &vpand ($D1,$D1,$MASK); + &vpsrlq ($D2,$D3,4) + &vpsrlq ($D3,$D3,30); + &vpand ($D2,$D2,$MASK); + &vpand ($D3,$D3,$MASK); + &vpsrldq ($D4,$D4,13); + + &lea ("edx",&DWP(16*9,"esp")); # size optimization + &mov ("ecx",2); +&set_label("square"); + &vmovdqa (&QWP(16*0,"esp"),$D0); + &vmovdqa (&QWP(16*1,"esp"),$D1); + &vmovdqa (&QWP(16*2,"esp"),$D2); + &vmovdqa (&QWP(16*3,"esp"),$D3); + &vmovdqa (&QWP(16*4,"esp"),$D4); + + &vpslld ($T1,$D1,2); + &vpslld ($T0,$D2,2); + &vpaddd ($T1,$T1,$D1); # *5 + &vpaddd ($T0,$T0,$D2); # *5 + &vmovdqa (&QWP(16*5,"esp"),$T1); + &vmovdqa (&QWP(16*6,"esp"),$T0); + &vpslld ($T1,$D3,2); + &vpslld ($T0,$D4,2); + &vpaddd ($T1,$T1,$D3); # *5 + &vpaddd ($T0,$T0,$D4); # *5 + &vmovdqa (&QWP(16*7,"esp"),$T1); + &vmovdqa (&QWP(16*8,"esp"),$T0); + + &vpshufd ($T0,$D0,0b01000100); + &vmovdqa ($T1,$D1); + &vpshufd ($D1,$D1,0b01000100); + &vpshufd ($D2,$D2,0b01000100); + &vpshufd ($D3,$D3,0b01000100); + &vpshufd ($D4,$D4,0b01000100); + &vmovdqa (&QWP(16*0,"edx"),$T0); + &vmovdqa (&QWP(16*1,"edx"),$D1); + &vmovdqa (&QWP(16*2,"edx"),$D2); + &vmovdqa (&QWP(16*3,"edx"),$D3); + &vmovdqa (&QWP(16*4,"edx"),$D4); + + ################################################################ + # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + + &vpmuludq ($D4,$D4,$D0); # h4*r0 + &vpmuludq ($D3,$D3,$D0); # h3*r0 + &vpmuludq ($D2,$D2,$D0); # h2*r0 + &vpmuludq ($D1,$D1,$D0); # h1*r0 + &vpmuludq ($D0,$T0,$D0); # h0*r0 + + &vpmuludq ($T0,$T1,&QWP(16*3,"edx")); # r1*h3 + &vpaddq ($D4,$D4,$T0); + &vpmuludq ($T2,$T1,&QWP(16*2,"edx")); # r1*h2 + &vpaddq ($D3,$D3,$T2); + &vpmuludq ($T0,$T1,&QWP(16*1,"edx")); # r1*h1 + &vpaddq ($D2,$D2,$T0); + &vmovdqa ($T2,&QWP(16*5,"esp")); # s1 + &vpmuludq ($T1,$T1,&QWP(16*0,"edx")); # r1*h0 + &vpaddq ($D1,$D1,$T1); + &vmovdqa ($T0,&QWP(16*2,"esp")); # r2 + &vpmuludq ($T2,$T2,&QWP(16*4,"edx")); # s1*h4 + &vpaddq ($D0,$D0,$T2); + + &vpmuludq ($T1,$T0,&QWP(16*2,"edx")); # r2*h2 + &vpaddq ($D4,$D4,$T1); + &vpmuludq ($T2,$T0,&QWP(16*1,"edx")); # r2*h1 + &vpaddq ($D3,$D3,$T2); + &vmovdqa ($T1,&QWP(16*6,"esp")); # s2 + &vpmuludq ($T0,$T0,&QWP(16*0,"edx")); # r2*h0 + &vpaddq ($D2,$D2,$T0); + &vpmuludq ($T2,$T1,&QWP(16*4,"edx")); # s2*h4 + &vpaddq ($D1,$D1,$T2); + &vmovdqa ($T0,&QWP(16*3,"esp")); # r3 + &vpmuludq ($T1,$T1,&QWP(16*3,"edx")); # s2*h3 + &vpaddq ($D0,$D0,$T1); + + &vpmuludq ($T2,$T0,&QWP(16*1,"edx")); # r3*h1 + &vpaddq ($D4,$D4,$T2); + &vmovdqa ($T1,&QWP(16*7,"esp")); # s3 + &vpmuludq ($T0,$T0,&QWP(16*0,"edx")); # r3*h0 + &vpaddq ($D3,$D3,$T0); + &vpmuludq ($T2,$T1,&QWP(16*4,"edx")); # s3*h4 + &vpaddq ($D2,$D2,$T2); + &vpmuludq ($T0,$T1,&QWP(16*3,"edx")); # s3*h3 + &vpaddq ($D1,$D1,$T0); + &vmovdqa ($T2,&QWP(16*4,"esp")); # r4 + &vpmuludq ($T1,$T1,&QWP(16*2,"edx")); # s3*h2 + &vpaddq ($D0,$D0,$T1); + + &vmovdqa ($T0,&QWP(16*8,"esp")); # s4 + &vpmuludq ($T2,$T2,&QWP(16*0,"edx")); # r4*h0 + &vpaddq ($D4,$D4,$T2); + &vpmuludq ($T1,$T0,&QWP(16*4,"edx")); # s4*h4 + &vpaddq ($D3,$D3,$T1); + &vpmuludq ($T2,$T0,&QWP(16*1,"edx")); # s4*h1 + &vpaddq ($D0,$D0,$T2); + &vpmuludq ($T1,$T0,&QWP(16*2,"edx")); # s4*h2 + &vpaddq ($D1,$D1,$T1); + &vmovdqa ($MASK,&QWP(64,"ebx")); + &vpmuludq ($T0,$T0,&QWP(16*3,"edx")); # s4*h3 + &vpaddq ($D2,$D2,$T0); + + ################################################################ + # lazy reduction + &vpsrlq ($T0,$D3,26); + &vpand ($D3,$D3,$MASK); + &vpsrlq ($T1,$D0,26); + &vpand ($D0,$D0,$MASK); + &vpaddq ($D4,$D4,$T0); # h3 -> h4 + &vpaddq ($D1,$D1,$T1); # h0 -> h1 + &vpsrlq ($T0,$D4,26); + &vpand ($D4,$D4,$MASK); + &vpsrlq ($T1,$D1,26); + &vpand ($D1,$D1,$MASK); + &vpaddq ($D2,$D2,$T1); # h1 -> h2 + &vpaddd ($D0,$D0,$T0); + &vpsllq ($T0,$T0,2); + &vpsrlq ($T1,$D2,26); + &vpand ($D2,$D2,$MASK); + &vpaddd ($D0,$D0,$T0); # h4 -> h0 + &vpaddd ($D3,$D3,$T1); # h2 -> h3 + &vpsrlq ($T1,$D3,26); + &vpsrlq ($T0,$D0,26); + &vpand ($D0,$D0,$MASK); + &vpand ($D3,$D3,$MASK); + &vpaddd ($D1,$D1,$T0); # h0 -> h1 + &vpaddd ($D4,$D4,$T1); # h3 -> h4 + + &dec ("ecx"); + &jz (&label("square_break")); + + &vpunpcklqdq ($D0,$D0,&QWP(16*0,"esp")); # 0:r^1:0:r^2 + &vpunpcklqdq ($D1,$D1,&QWP(16*1,"esp")); + &vpunpcklqdq ($D2,$D2,&QWP(16*2,"esp")); + &vpunpcklqdq ($D3,$D3,&QWP(16*3,"esp")); + &vpunpcklqdq ($D4,$D4,&QWP(16*4,"esp")); + &jmp (&label("square")); + +&set_label("square_break"); + &vpsllq ($D0,$D0,32); # -> r^3:0:r^4:0 + &vpsllq ($D1,$D1,32); + &vpsllq ($D2,$D2,32); + &vpsllq ($D3,$D3,32); + &vpsllq ($D4,$D4,32); + &vpor ($D0,$D0,&QWP(16*0,"esp")); # r^3:r^1:r^4:r^2 + &vpor ($D1,$D1,&QWP(16*1,"esp")); + &vpor ($D2,$D2,&QWP(16*2,"esp")); + &vpor ($D3,$D3,&QWP(16*3,"esp")); + &vpor ($D4,$D4,&QWP(16*4,"esp")); + + &vpshufd ($D0,$D0,0b10001101); # -> r^1:r^2:r^3:r^4 + &vpshufd ($D1,$D1,0b10001101); + &vpshufd ($D2,$D2,0b10001101); + &vpshufd ($D3,$D3,0b10001101); + &vpshufd ($D4,$D4,0b10001101); + + &vmovdqu (&QWP(16*0,"edi"),$D0); # save the table + &vmovdqu (&QWP(16*1,"edi"),$D1); + &vmovdqu (&QWP(16*2,"edi"),$D2); + &vmovdqu (&QWP(16*3,"edi"),$D3); + &vmovdqu (&QWP(16*4,"edi"),$D4); + + &vpslld ($T1,$D1,2); + &vpslld ($T0,$D2,2); + &vpaddd ($T1,$T1,$D1); # *5 + &vpaddd ($T0,$T0,$D2); # *5 + &vmovdqu (&QWP(16*5,"edi"),$T1); + &vmovdqu (&QWP(16*6,"edi"),$T0); + &vpslld ($T1,$D3,2); + &vpslld ($T0,$D4,2); + &vpaddd ($T1,$T1,$D3); # *5 + &vpaddd ($T0,$T0,$D4); # *5 + &vmovdqu (&QWP(16*7,"edi"),$T1); + &vmovdqu (&QWP(16*8,"edi"),$T0); + + &mov ("esp","ebp"); + &lea ("edi",&DWP(-16*3,"edi")); # size de-optimization + &ret (); +&function_end_B("_poly1305_init_avx2"); + +######################################################################## +# now it's time to switch to %ymm + +my ($D0,$D1,$D2,$D3,$D4,$T0,$T1,$T2)=map("ymm$_",(0..7)); +my $MASK=$T2; + +sub X { my $reg=shift; $reg=~s/^ymm/xmm/; $reg; } + +&align (32); +&function_begin("_poly1305_blocks_avx2"); + &mov ("edi",&wparam(0)); # ctx + &mov ("esi",&wparam(1)); # inp + &mov ("ecx",&wparam(2)); # len + + &mov ("eax",&DWP(4*5,"edi")); # is_base2_26 + &and ("ecx",-16); + &jz (&label("nodata")); + &cmp ("ecx",64); + &jae (&label("enter_avx2")); + &test ("eax","eax"); # is_base2_26? + &jz (&label("enter_blocks")); + +&set_label("enter_avx2"); + &vzeroupper (); + + &call (&label("pic_point")); +&set_label("pic_point"); + &blindpop("ebx"); + &lea ("ebx",&DWP(&label("const_sse2")."-".&label("pic_point"),"ebx")); + + &test ("eax","eax"); # is_base2_26? + &jnz (&label("base2_26")); + + &call ("_poly1305_init_avx2"); + + ################################################# base 2^32 -> base 2^26 + &mov ("eax",&DWP(0,"edi")); + &mov ("ecx",&DWP(3,"edi")); + &mov ("edx",&DWP(6,"edi")); + &mov ("esi",&DWP(9,"edi")); + &mov ("ebp",&DWP(13,"edi")); + + &shr ("ecx",2); + &and ("eax",0x3ffffff); + &shr ("edx",4); + &and ("ecx",0x3ffffff); + &shr ("esi",6); + &and ("edx",0x3ffffff); + + &mov (&DWP(4*0,"edi"),"eax"); + &mov (&DWP(4*1,"edi"),"ecx"); + &mov (&DWP(4*2,"edi"),"edx"); + &mov (&DWP(4*3,"edi"),"esi"); + &mov (&DWP(4*4,"edi"),"ebp"); + &mov (&DWP(4*5,"edi"),1); # is_base2_26 + + &mov ("esi",&wparam(1)); # [reload] inp + &mov ("ecx",&wparam(2)); # [reload] len + +&set_label("base2_26"); + &mov ("eax",&wparam(3)); # padbit + &mov ("ebp","esp"); + + &sub ("esp",32*(5+9)); + &and ("esp",-512); # ensure that frame + # doesn't cross page + # boundary, which is + # essential for + # misaligned 32-byte + # loads + + ################################################################ + # expand and copy pre-calculated table to stack + + &vmovdqu (&X($D0),&QWP(16*(3+0),"edi")); + &lea ("edx",&DWP(32*5+128,"esp")); # +128 size optimization + &vmovdqu (&X($D1),&QWP(16*(3+1),"edi")); + &vmovdqu (&X($D2),&QWP(16*(3+2),"edi")); + &vmovdqu (&X($D3),&QWP(16*(3+3),"edi")); + &vmovdqu (&X($D4),&QWP(16*(3+4),"edi")); + &lea ("edi",&DWP(16*3,"edi")); # size optimization + &vpermq ($D0,$D0,0b01000000); # 00001234 -> 12343434 + &vpermq ($D1,$D1,0b01000000); + &vpermq ($D2,$D2,0b01000000); + &vpermq ($D3,$D3,0b01000000); + &vpermq ($D4,$D4,0b01000000); + &vpshufd ($D0,$D0,0b11001000); # 12343434 -> 14243444 + &vpshufd ($D1,$D1,0b11001000); + &vpshufd ($D2,$D2,0b11001000); + &vpshufd ($D3,$D3,0b11001000); + &vpshufd ($D4,$D4,0b11001000); + &vmovdqa (&QWP(32*0-128,"edx"),$D0); + &vmovdqu (&X($D0),&QWP(16*5,"edi")); + &vmovdqa (&QWP(32*1-128,"edx"),$D1); + &vmovdqu (&X($D1),&QWP(16*6,"edi")); + &vmovdqa (&QWP(32*2-128,"edx"),$D2); + &vmovdqu (&X($D2),&QWP(16*7,"edi")); + &vmovdqa (&QWP(32*3-128,"edx"),$D3); + &vmovdqu (&X($D3),&QWP(16*8,"edi")); + &vmovdqa (&QWP(32*4-128,"edx"),$D4); + &vpermq ($D0,$D0,0b01000000); + &vpermq ($D1,$D1,0b01000000); + &vpermq ($D2,$D2,0b01000000); + &vpermq ($D3,$D3,0b01000000); + &vpshufd ($D0,$D0,0b11001000); + &vpshufd ($D1,$D1,0b11001000); + &vpshufd ($D2,$D2,0b11001000); + &vpshufd ($D3,$D3,0b11001000); + &vmovdqa (&QWP(32*5-128,"edx"),$D0); + &vmovd (&X($D0),&DWP(-16*3+4*0,"edi"));# load hash value + &vmovdqa (&QWP(32*6-128,"edx"),$D1); + &vmovd (&X($D1),&DWP(-16*3+4*1,"edi")); + &vmovdqa (&QWP(32*7-128,"edx"),$D2); + &vmovd (&X($D2),&DWP(-16*3+4*2,"edi")); + &vmovdqa (&QWP(32*8-128,"edx"),$D3); + &vmovd (&X($D3),&DWP(-16*3+4*3,"edi")); + &vmovd (&X($D4),&DWP(-16*3+4*4,"edi")); + &vmovdqa ($MASK,&QWP(64,"ebx")); + &neg ("eax"); # padbit + + &test ("ecx",63); + &jz (&label("even")); + + &mov ("edx","ecx"); + &and ("ecx",-64); + &and ("edx",63); + + &vmovdqu (&X($T0),&QWP(16*0,"esi")); + &cmp ("edx",32); + &jb (&label("one")); + + &vmovdqu (&X($T1),&QWP(16*1,"esi")); + &je (&label("two")); + + &vinserti128 ($T0,$T0,&QWP(16*2,"esi"),1); + &lea ("esi",&DWP(16*3,"esi")); + &lea ("ebx",&DWP(8,"ebx")); # three padbits + &lea ("edx",&DWP(32*5+128+8,"esp")); # --:r^1:r^2:r^3 (*) + &jmp (&label("tail")); + +&set_label("two"); + &lea ("esi",&DWP(16*2,"esi")); + &lea ("ebx",&DWP(16,"ebx")); # two padbits + &lea ("edx",&DWP(32*5+128+16,"esp"));# --:--:r^1:r^2 (*) + &jmp (&label("tail")); + +&set_label("one"); + &lea ("esi",&DWP(16*1,"esi")); + &vpxor ($T1,$T1,$T1); + &lea ("ebx",&DWP(32,"ebx","eax",8)); # one or no padbits + &lea ("edx",&DWP(32*5+128+24,"esp"));# --:--:--:r^1 (*) + &jmp (&label("tail")); + +# (*) spots marked with '--' are data from next table entry, but they +# are multiplied by 0 and therefore rendered insignificant + +&set_label("even",32); + &vmovdqu (&X($T0),&QWP(16*0,"esi")); # load input + &vmovdqu (&X($T1),&QWP(16*1,"esi")); + &vinserti128 ($T0,$T0,&QWP(16*2,"esi"),1); + &vinserti128 ($T1,$T1,&QWP(16*3,"esi"),1); + &lea ("esi",&DWP(16*4,"esi")); + &sub ("ecx",64); + &jz (&label("tail")); + +&set_label("loop"); + ################################################################ + # ((inp[0]*r^4+r[4])*r^4+r[8])*r^4 + # ((inp[1]*r^4+r[5])*r^4+r[9])*r^3 + # ((inp[2]*r^4+r[6])*r^4+r[10])*r^2 + # ((inp[3]*r^4+r[7])*r^4+r[11])*r^1 + # \________/ \_______/ + ################################################################ + +sub vsplat_input { + &vmovdqa (&QWP(32*2,"esp"),$D2); + &vpsrldq ($D2,$T0,6); # splat input + &vmovdqa (&QWP(32*0,"esp"),$D0); + &vpsrldq ($D0,$T1,6); + &vmovdqa (&QWP(32*1,"esp"),$D1); + &vpunpckhqdq ($D1,$T0,$T1); # 4 + &vpunpcklqdq ($T0,$T0,$T1); # 0:1 + &vpunpcklqdq ($D2,$D2,$D0); # 2:3 + + &vpsrlq ($D0,$D2,30); + &vpsrlq ($D2,$D2,4); + &vpsrlq ($T1,$T0,26); + &vpsrlq ($D1,$D1,40); # 4 + &vpand ($D2,$D2,$MASK); # 2 + &vpand ($T0,$T0,$MASK); # 0 + &vpand ($T1,$T1,$MASK); # 1 + &vpand ($D0,$D0,$MASK); # 3 (*) + &vpor ($D1,$D1,&QWP(0,"ebx")); # padbit, yes, always + + # (*) note that output is counterintuitive, inp[3:4] is + # returned in $D1-2, while $D3-4 are preserved; +} + &vsplat_input (); + +sub vpmuladd { +my $addr = shift; + + &vpaddq ($D2,$D2,&QWP(32*2,"esp")); # add hash value + &vpaddq ($T0,$T0,&QWP(32*0,"esp")); + &vpaddq ($T1,$T1,&QWP(32*1,"esp")); + &vpaddq ($D0,$D0,$D3); + &vpaddq ($D1,$D1,$D4); + + ################################################################ + # d3 = h2*r1 + h0*r3 + h1*r2 + h3*r0 + h4*5*r4 + # d4 = h2*r2 + h0*r4 + h1*r3 + h3*r1 + h4*r0 + # d0 = h2*5*r3 + h0*r0 + h1*5*r4 + h3*5*r2 + h4*5*r1 + # d1 = h2*5*r4 + h0*r1 + h1*r0 + h3*5*r3 + h4*5*r2 + # d2 = h2*r0 + h0*r2 + h1*r1 + h3*5*r4 + h4*5*r3 + + &vpmuludq ($D3,$D2,&$addr(1)); # d3 = h2*r1 + &vmovdqa (QWP(32*1,"esp"),$T1); + &vpmuludq ($D4,$D2,&$addr(2)); # d4 = h2*r2 + &vmovdqa (QWP(32*3,"esp"),$D0); + &vpmuludq ($D0,$D2,&$addr(7)); # d0 = h2*s3 + &vmovdqa (QWP(32*4,"esp"),$D1); + &vpmuludq ($D1,$D2,&$addr(8)); # d1 = h2*s4 + &vpmuludq ($D2,$D2,&$addr(0)); # d2 = h2*r0 + + &vpmuludq ($T2,$T0,&$addr(3)); # h0*r3 + &vpaddq ($D3,$D3,$T2); # d3 += h0*r3 + &vpmuludq ($T1,$T0,&$addr(4)); # h0*r4 + &vpaddq ($D4,$D4,$T1); # d4 + h0*r4 + &vpmuludq ($T2,$T0,&$addr(0)); # h0*r0 + &vpaddq ($D0,$D0,$T2); # d0 + h0*r0 + &vmovdqa ($T2,&QWP(32*1,"esp")); # h1 + &vpmuludq ($T1,$T0,&$addr(1)); # h0*r1 + &vpaddq ($D1,$D1,$T1); # d1 += h0*r1 + &vpmuludq ($T0,$T0,&$addr(2)); # h0*r2 + &vpaddq ($D2,$D2,$T0); # d2 += h0*r2 + + &vpmuludq ($T1,$T2,&$addr(2)); # h1*r2 + &vpaddq ($D3,$D3,$T1); # d3 += h1*r2 + &vpmuludq ($T0,$T2,&$addr(3)); # h1*r3 + &vpaddq ($D4,$D4,$T0); # d4 += h1*r3 + &vpmuludq ($T1,$T2,&$addr(8)); # h1*s4 + &vpaddq ($D0,$D0,$T1); # d0 += h1*s4 + &vmovdqa ($T1,&QWP(32*3,"esp")); # h3 + &vpmuludq ($T0,$T2,&$addr(0)); # h1*r0 + &vpaddq ($D1,$D1,$T0); # d1 += h1*r0 + &vpmuludq ($T2,$T2,&$addr(1)); # h1*r1 + &vpaddq ($D2,$D2,$T2); # d2 += h1*r1 + + &vpmuludq ($T0,$T1,&$addr(0)); # h3*r0 + &vpaddq ($D3,$D3,$T0); # d3 += h3*r0 + &vpmuludq ($T2,$T1,&$addr(1)); # h3*r1 + &vpaddq ($D4,$D4,$T2); # d4 += h3*r1 + &vpmuludq ($T0,$T1,&$addr(6)); # h3*s2 + &vpaddq ($D0,$D0,$T0); # d0 += h3*s2 + &vmovdqa ($T0,&QWP(32*4,"esp")); # h4 + &vpmuludq ($T2,$T1,&$addr(7)); # h3*s3 + &vpaddq ($D1,$D1,$T2); # d1+= h3*s3 + &vpmuludq ($T1,$T1,&$addr(8)); # h3*s4 + &vpaddq ($D2,$D2,$T1); # d2 += h3*s4 + + &vpmuludq ($T2,$T0,&$addr(8)); # h4*s4 + &vpaddq ($D3,$D3,$T2); # d3 += h4*s4 + &vpmuludq ($T1,$T0,&$addr(5)); # h4*s1 + &vpaddq ($D0,$D0,$T1); # d0 += h4*s1 + &vpmuludq ($T2,$T0,&$addr(0)); # h4*r0 + &vpaddq ($D4,$D4,$T2); # d4 += h4*r0 + &vmovdqa ($MASK,&QWP(64,"ebx")); + &vpmuludq ($T1,$T0,&$addr(6)); # h4*s2 + &vpaddq ($D1,$D1,$T1); # d1 += h4*s2 + &vpmuludq ($T0,$T0,&$addr(7)); # h4*s3 + &vpaddq ($D2,$D2,$T0); # d2 += h4*s3 +} + &vpmuladd (sub { my $i=shift; &QWP(32*$i-128,"edx"); }); + +sub vlazy_reduction { + ################################################################ + # lazy reduction + + &vpsrlq ($T0,$D3,26); + &vpand ($D3,$D3,$MASK); + &vpsrlq ($T1,$D0,26); + &vpand ($D0,$D0,$MASK); + &vpaddq ($D4,$D4,$T0); # h3 -> h4 + &vpaddq ($D1,$D1,$T1); # h0 -> h1 + &vpsrlq ($T0,$D4,26); + &vpand ($D4,$D4,$MASK); + &vpsrlq ($T1,$D1,26); + &vpand ($D1,$D1,$MASK); + &vpaddq ($D2,$D2,$T1); # h1 -> h2 + &vpaddq ($D0,$D0,$T0); + &vpsllq ($T0,$T0,2); + &vpsrlq ($T1,$D2,26); + &vpand ($D2,$D2,$MASK); + &vpaddq ($D0,$D0,$T0); # h4 -> h0 + &vpaddq ($D3,$D3,$T1); # h2 -> h3 + &vpsrlq ($T1,$D3,26); + &vpsrlq ($T0,$D0,26); + &vpand ($D0,$D0,$MASK); + &vpand ($D3,$D3,$MASK); + &vpaddq ($D1,$D1,$T0); # h0 -> h1 + &vpaddq ($D4,$D4,$T1); # h3 -> h4 +} + &vlazy_reduction(); + + &vmovdqu (&X($T0),&QWP(16*0,"esi")); # load input + &vmovdqu (&X($T1),&QWP(16*1,"esi")); + &vinserti128 ($T0,$T0,&QWP(16*2,"esi"),1); + &vinserti128 ($T1,$T1,&QWP(16*3,"esi"),1); + &lea ("esi",&DWP(16*4,"esi")); + &sub ("ecx",64); + &jnz (&label("loop")); + +&set_label("tail"); + &vsplat_input (); + &and ("ebx",-64); # restore pointer + + &vpmuladd (sub { my $i=shift; &QWP(4+32*$i-128,"edx"); }); + + ################################################################ + # horizontal addition + + &vpsrldq ($T0,$D4,8); + &vpsrldq ($T1,$D3,8); + &vpaddq ($D4,$D4,$T0); + &vpsrldq ($T0,$D0,8); + &vpaddq ($D3,$D3,$T1); + &vpsrldq ($T1,$D1,8); + &vpaddq ($D0,$D0,$T0); + &vpsrldq ($T0,$D2,8); + &vpaddq ($D1,$D1,$T1); + &vpermq ($T1,$D4,2); # keep folding + &vpaddq ($D2,$D2,$T0); + &vpermq ($T0,$D3,2); + &vpaddq ($D4,$D4,$T1); + &vpermq ($T1,$D0,2); + &vpaddq ($D3,$D3,$T0); + &vpermq ($T0,$D1,2); + &vpaddq ($D0,$D0,$T1); + &vpermq ($T1,$D2,2); + &vpaddq ($D1,$D1,$T0); + &vpaddq ($D2,$D2,$T1); + + &vlazy_reduction(); + + &cmp ("ecx",0); + &je (&label("done")); + + ################################################################ + # clear all but single word + + &vpshufd (&X($D0),&X($D0),0b11111100); + &lea ("edx",&DWP(32*5+128,"esp")); # restore pointer + &vpshufd (&X($D1),&X($D1),0b11111100); + &vpshufd (&X($D2),&X($D2),0b11111100); + &vpshufd (&X($D3),&X($D3),0b11111100); + &vpshufd (&X($D4),&X($D4),0b11111100); + &jmp (&label("even")); + +&set_label("done",16); + &vmovd (&DWP(-16*3+4*0,"edi"),&X($D0));# store hash value + &vmovd (&DWP(-16*3+4*1,"edi"),&X($D1)); + &vmovd (&DWP(-16*3+4*2,"edi"),&X($D2)); + &vmovd (&DWP(-16*3+4*3,"edi"),&X($D3)); + &vmovd (&DWP(-16*3+4*4,"edi"),&X($D4)); + &vzeroupper (); + &mov ("esp","ebp"); +&set_label("nodata"); +&function_end("_poly1305_blocks_avx2"); +} +&set_label("const_sse2",64); + &data_word(1<<24,0, 1<<24,0, 1<<24,0, 1<<24,0); + &data_word(0,0, 0,0, 0,0, 0,0); + &data_word(0x03ffffff,0,0x03ffffff,0, 0x03ffffff,0, 0x03ffffff,0); + &data_word(0x0fffffff,0x0ffffffc,0x0ffffffc,0x0ffffffc); +} +&asciz ("Poly1305 for x86, CRYPTOGAMS by "); +&align (4); + +&asm_finish(); + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-x86_64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-x86_64.pl new file mode 100755 index 000000000..342ad7f18 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/asm/poly1305-x86_64.pl @@ -0,0 +1,4159 @@ +#! /usr/bin/env perl +# Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# This module implements Poly1305 hash for x86_64. +# +# March 2015 +# +# Initial release. +# +# December 2016 +# +# Add AVX512F+VL+BW code path. +# +# November 2017 +# +# Convert AVX512F+VL+BW code path to pure AVX512F, so that it can be +# executed even on Knights Landing. Trigger for modification was +# observation that AVX512 code paths can negatively affect overall +# Skylake-X system performance. Since we are likely to suppress +# AVX512F capability flag [at least on Skylake-X], conversion serves +# as kind of "investment protection". Note that next *lake processor, +# Cannolake, has AVX512IFMA code path to execute... +# +# Numbers are cycles per processed byte with poly1305_blocks alone, +# measured with rdtsc at fixed clock frequency. +# +# IALU/gcc-4.8(*) AVX(**) AVX2 AVX-512 +# P4 4.46/+120% - +# Core 2 2.41/+90% - +# Westmere 1.88/+120% - +# Sandy Bridge 1.39/+140% 1.10 +# Haswell 1.14/+175% 1.11 0.65 +# Skylake[-X] 1.13/+120% 0.96 0.51 [0.35] +# Silvermont 2.83/+95% - +# Knights L 3.60/? 1.65 1.10 0.41(***) +# Goldmont 1.70/+180% - +# VIA Nano 1.82/+150% - +# Sledgehammer 1.38/+160% - +# Bulldozer 2.30/+130% 0.97 +# Ryzen 1.15/+200% 1.08 1.18 +# +# (*) improvement coefficients relative to clang are more modest and +# are ~50% on most processors, in both cases we are comparing to +# __int128 code; +# (**) SSE2 implementation was attempted, but among non-AVX processors +# it was faster than integer-only code only on older Intel P4 and +# Core processors, 50-30%, less newer processor is, but slower on +# contemporary ones, for example almost 2x slower on Atom, and as +# former are naturally disappearing, SSE2 is deemed unnecessary; +# (***) strangely enough performance seems to vary from core to core, +# listed result is best case; + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler version ([2-9]\.[0-9]+)/) { + $avx = ($1>=2.19) + ($1>=2.22) + ($1>=2.25) + ($1>=2.26); +} + +if (!$avx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) && + `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)(?:\.([0-9]+))?/) { + $avx = ($1>=2.09) + ($1>=2.10) + 2 * ($1>=2.12); + $avx += 2 if ($1==2.11 && $2>=8); +} + +if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && + `ml64 2>&1` =~ /Version ([0-9]+)\./) { + $avx = ($1>=10) + ($1>=12); +} + +if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9]\.[0-9]+)/) { + $avx = ($2>=3.0) + ($2>3.0); +} + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +*STDOUT=*OUT; + +my ($ctx,$inp,$len,$padbit)=("%rdi","%rsi","%rdx","%rcx"); +my ($mac,$nonce)=($inp,$len); # *_emit arguments +my ($d1,$d2,$d3, $r0,$r1,$s1)=map("%r$_",(8..13)); +my ($h0,$h1,$h2)=("%r14","%rbx","%rbp"); + +sub poly1305_iteration { +# input: copy of $r1 in %rax, $h0-$h2, $r0-$r1 +# output: $h0-$h2 *= $r0-$r1 +$code.=<<___; + mulq $h0 # h0*r1 + mov %rax,$d2 + mov $r0,%rax + mov %rdx,$d3 + + mulq $h0 # h0*r0 + mov %rax,$h0 # future $h0 + mov $r0,%rax + mov %rdx,$d1 + + mulq $h1 # h1*r0 + add %rax,$d2 + mov $s1,%rax + adc %rdx,$d3 + + mulq $h1 # h1*s1 + mov $h2,$h1 # borrow $h1 + add %rax,$h0 + adc %rdx,$d1 + + imulq $s1,$h1 # h2*s1 + add $h1,$d2 + mov $d1,$h1 + adc \$0,$d3 + + imulq $r0,$h2 # h2*r0 + add $d2,$h1 + mov \$-4,%rax # mask value + adc $h2,$d3 + + and $d3,%rax # last reduction step + mov $d3,$h2 + shr \$2,$d3 + and \$3,$h2 + add $d3,%rax + add %rax,$h0 + adc \$0,$h1 + adc \$0,$h2 +___ +} + +######################################################################## +# Layout of opaque area is following. +# +# unsigned __int64 h[3]; # current hash value base 2^64 +# unsigned __int64 r[2]; # key value base 2^64 + +$code.=<<___; +.text + +.extern OPENSSL_ia32cap_P + +.globl poly1305_init +.hidden poly1305_init +.globl poly1305_blocks +.hidden poly1305_blocks +.globl poly1305_emit +.hidden poly1305_emit + +.type poly1305_init,\@function,3 +.align 32 +poly1305_init: + xor %rax,%rax + mov %rax,0($ctx) # initialize hash value + mov %rax,8($ctx) + mov %rax,16($ctx) + + cmp \$0,$inp + je .Lno_key + + lea poly1305_blocks(%rip),%r10 + lea poly1305_emit(%rip),%r11 +___ +$code.=<<___ if ($avx); + mov OPENSSL_ia32cap_P+4(%rip),%r9 + lea poly1305_blocks_avx(%rip),%rax + lea poly1305_emit_avx(%rip),%rcx + bt \$`60-32`,%r9 # AVX? + cmovc %rax,%r10 + cmovc %rcx,%r11 +___ +$code.=<<___ if ($avx>1); + lea poly1305_blocks_avx2(%rip),%rax + bt \$`5+32`,%r9 # AVX2? + cmovc %rax,%r10 +___ +$code.=<<___ if ($avx>3); + mov \$`(1<<31|1<<21|1<<16)`,%rax + shr \$32,%r9 + and %rax,%r9 + cmp %rax,%r9 + je .Linit_base2_44 +___ +$code.=<<___; + mov \$0x0ffffffc0fffffff,%rax + mov \$0x0ffffffc0ffffffc,%rcx + and 0($inp),%rax + and 8($inp),%rcx + mov %rax,24($ctx) + mov %rcx,32($ctx) +___ +$code.=<<___ if ($flavour !~ /elf32/); + mov %r10,0(%rdx) + mov %r11,8(%rdx) +___ +$code.=<<___ if ($flavour =~ /elf32/); + mov %r10d,0(%rdx) + mov %r11d,4(%rdx) +___ +$code.=<<___; + mov \$1,%eax +.Lno_key: + ret +.size poly1305_init,.-poly1305_init + +.type poly1305_blocks,\@function,4 +.align 32 +poly1305_blocks: +.cfi_startproc +.Lblocks: + shr \$4,$len + jz .Lno_data # too short + + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +.Lblocks_body: + + mov $len,%r15 # reassign $len + + mov 24($ctx),$r0 # load r + mov 32($ctx),$s1 + + mov 0($ctx),$h0 # load hash value + mov 8($ctx),$h1 + mov 16($ctx),$h2 + + mov $s1,$r1 + shr \$2,$s1 + mov $r1,%rax + add $r1,$s1 # s1 = r1 + (r1 >> 2) + jmp .Loop + +.align 32 +.Loop: + add 0($inp),$h0 # accumulate input + adc 8($inp),$h1 + lea 16($inp),$inp + adc $padbit,$h2 +___ + &poly1305_iteration(); +$code.=<<___; + mov $r1,%rax + dec %r15 # len-=16 + jnz .Loop + + mov $h0,0($ctx) # store hash value + mov $h1,8($ctx) + mov $h2,16($ctx) + + mov 0(%rsp),%r15 +.cfi_restore %r15 + mov 8(%rsp),%r14 +.cfi_restore %r14 + mov 16(%rsp),%r13 +.cfi_restore %r13 + mov 24(%rsp),%r12 +.cfi_restore %r12 + mov 32(%rsp),%rbp +.cfi_restore %rbp + mov 40(%rsp),%rbx +.cfi_restore %rbx + lea 48(%rsp),%rsp +.cfi_adjust_cfa_offset -48 +.Lno_data: +.Lblocks_epilogue: + ret +.cfi_endproc +.size poly1305_blocks,.-poly1305_blocks + +.type poly1305_emit,\@function,3 +.align 32 +poly1305_emit: +.Lemit: + mov 0($ctx),%r8 # load hash value + mov 8($ctx),%r9 + mov 16($ctx),%r10 + + mov %r8,%rax + add \$5,%r8 # compare to modulus + mov %r9,%rcx + adc \$0,%r9 + adc \$0,%r10 + shr \$2,%r10 # did 130-bit value overflow? + cmovnz %r8,%rax + cmovnz %r9,%rcx + + add 0($nonce),%rax # accumulate nonce + adc 8($nonce),%rcx + mov %rax,0($mac) # write result + mov %rcx,8($mac) + + ret +.size poly1305_emit,.-poly1305_emit +___ +if ($avx) { + +######################################################################## +# Layout of opaque area is following. +# +# unsigned __int32 h[5]; # current hash value base 2^26 +# unsigned __int32 is_base2_26; +# unsigned __int64 r[2]; # key value base 2^64 +# unsigned __int64 pad; +# struct { unsigned __int32 r^2, r^1, r^4, r^3; } r[9]; +# +# where r^n are base 2^26 digits of degrees of multiplier key. There are +# 5 digits, but last four are interleaved with multiples of 5, totalling +# in 9 elements: r0, r1, 5*r1, r2, 5*r2, r3, 5*r3, r4, 5*r4. + +my ($H0,$H1,$H2,$H3,$H4, $T0,$T1,$T2,$T3,$T4, $D0,$D1,$D2,$D3,$D4, $MASK) = + map("%xmm$_",(0..15)); + +$code.=<<___; +.type __poly1305_block,\@abi-omnipotent +.align 32 +__poly1305_block: +___ + &poly1305_iteration(); +$code.=<<___; + ret +.size __poly1305_block,.-__poly1305_block + +.type __poly1305_init_avx,\@abi-omnipotent +.align 32 +__poly1305_init_avx: + mov $r0,$h0 + mov $r1,$h1 + xor $h2,$h2 + + lea 48+64($ctx),$ctx # size optimization + + mov $r1,%rax + call __poly1305_block # r^2 + + mov \$0x3ffffff,%eax # save interleaved r^2 and r base 2^26 + mov \$0x3ffffff,%edx + mov $h0,$d1 + and $h0#d,%eax + mov $r0,$d2 + and $r0#d,%edx + mov %eax,`16*0+0-64`($ctx) + shr \$26,$d1 + mov %edx,`16*0+4-64`($ctx) + shr \$26,$d2 + + mov \$0x3ffffff,%eax + mov \$0x3ffffff,%edx + and $d1#d,%eax + and $d2#d,%edx + mov %eax,`16*1+0-64`($ctx) + lea (%rax,%rax,4),%eax # *5 + mov %edx,`16*1+4-64`($ctx) + lea (%rdx,%rdx,4),%edx # *5 + mov %eax,`16*2+0-64`($ctx) + shr \$26,$d1 + mov %edx,`16*2+4-64`($ctx) + shr \$26,$d2 + + mov $h1,%rax + mov $r1,%rdx + shl \$12,%rax + shl \$12,%rdx + or $d1,%rax + or $d2,%rdx + and \$0x3ffffff,%eax + and \$0x3ffffff,%edx + mov %eax,`16*3+0-64`($ctx) + lea (%rax,%rax,4),%eax # *5 + mov %edx,`16*3+4-64`($ctx) + lea (%rdx,%rdx,4),%edx # *5 + mov %eax,`16*4+0-64`($ctx) + mov $h1,$d1 + mov %edx,`16*4+4-64`($ctx) + mov $r1,$d2 + + mov \$0x3ffffff,%eax + mov \$0x3ffffff,%edx + shr \$14,$d1 + shr \$14,$d2 + and $d1#d,%eax + and $d2#d,%edx + mov %eax,`16*5+0-64`($ctx) + lea (%rax,%rax,4),%eax # *5 + mov %edx,`16*5+4-64`($ctx) + lea (%rdx,%rdx,4),%edx # *5 + mov %eax,`16*6+0-64`($ctx) + shr \$26,$d1 + mov %edx,`16*6+4-64`($ctx) + shr \$26,$d2 + + mov $h2,%rax + shl \$24,%rax + or %rax,$d1 + mov $d1#d,`16*7+0-64`($ctx) + lea ($d1,$d1,4),$d1 # *5 + mov $d2#d,`16*7+4-64`($ctx) + lea ($d2,$d2,4),$d2 # *5 + mov $d1#d,`16*8+0-64`($ctx) + mov $d2#d,`16*8+4-64`($ctx) + + mov $r1,%rax + call __poly1305_block # r^3 + + mov \$0x3ffffff,%eax # save r^3 base 2^26 + mov $h0,$d1 + and $h0#d,%eax + shr \$26,$d1 + mov %eax,`16*0+12-64`($ctx) + + mov \$0x3ffffff,%edx + and $d1#d,%edx + mov %edx,`16*1+12-64`($ctx) + lea (%rdx,%rdx,4),%edx # *5 + shr \$26,$d1 + mov %edx,`16*2+12-64`($ctx) + + mov $h1,%rax + shl \$12,%rax + or $d1,%rax + and \$0x3ffffff,%eax + mov %eax,`16*3+12-64`($ctx) + lea (%rax,%rax,4),%eax # *5 + mov $h1,$d1 + mov %eax,`16*4+12-64`($ctx) + + mov \$0x3ffffff,%edx + shr \$14,$d1 + and $d1#d,%edx + mov %edx,`16*5+12-64`($ctx) + lea (%rdx,%rdx,4),%edx # *5 + shr \$26,$d1 + mov %edx,`16*6+12-64`($ctx) + + mov $h2,%rax + shl \$24,%rax + or %rax,$d1 + mov $d1#d,`16*7+12-64`($ctx) + lea ($d1,$d1,4),$d1 # *5 + mov $d1#d,`16*8+12-64`($ctx) + + mov $r1,%rax + call __poly1305_block # r^4 + + mov \$0x3ffffff,%eax # save r^4 base 2^26 + mov $h0,$d1 + and $h0#d,%eax + shr \$26,$d1 + mov %eax,`16*0+8-64`($ctx) + + mov \$0x3ffffff,%edx + and $d1#d,%edx + mov %edx,`16*1+8-64`($ctx) + lea (%rdx,%rdx,4),%edx # *5 + shr \$26,$d1 + mov %edx,`16*2+8-64`($ctx) + + mov $h1,%rax + shl \$12,%rax + or $d1,%rax + and \$0x3ffffff,%eax + mov %eax,`16*3+8-64`($ctx) + lea (%rax,%rax,4),%eax # *5 + mov $h1,$d1 + mov %eax,`16*4+8-64`($ctx) + + mov \$0x3ffffff,%edx + shr \$14,$d1 + and $d1#d,%edx + mov %edx,`16*5+8-64`($ctx) + lea (%rdx,%rdx,4),%edx # *5 + shr \$26,$d1 + mov %edx,`16*6+8-64`($ctx) + + mov $h2,%rax + shl \$24,%rax + or %rax,$d1 + mov $d1#d,`16*7+8-64`($ctx) + lea ($d1,$d1,4),$d1 # *5 + mov $d1#d,`16*8+8-64`($ctx) + + lea -48-64($ctx),$ctx # size [de-]optimization + ret +.size __poly1305_init_avx,.-__poly1305_init_avx + +.type poly1305_blocks_avx,\@function,4 +.align 32 +poly1305_blocks_avx: +.cfi_startproc + mov 20($ctx),%r8d # is_base2_26 + cmp \$128,$len + jae .Lblocks_avx + test %r8d,%r8d + jz .Lblocks + +.Lblocks_avx: + and \$-16,$len + jz .Lno_data_avx + + vzeroupper + + test %r8d,%r8d + jz .Lbase2_64_avx + + test \$31,$len + jz .Leven_avx + + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +.Lblocks_avx_body: + + mov $len,%r15 # reassign $len + + mov 0($ctx),$d1 # load hash value + mov 8($ctx),$d2 + mov 16($ctx),$h2#d + + mov 24($ctx),$r0 # load r + mov 32($ctx),$s1 + + ################################# base 2^26 -> base 2^64 + mov $d1#d,$h0#d + and \$`-1*(1<<31)`,$d1 + mov $d2,$r1 # borrow $r1 + mov $d2#d,$h1#d + and \$`-1*(1<<31)`,$d2 + + shr \$6,$d1 + shl \$52,$r1 + add $d1,$h0 + shr \$12,$h1 + shr \$18,$d2 + add $r1,$h0 + adc $d2,$h1 + + mov $h2,$d1 + shl \$40,$d1 + shr \$24,$h2 + add $d1,$h1 + adc \$0,$h2 # can be partially reduced... + + mov \$-4,$d2 # ... so reduce + mov $h2,$d1 + and $h2,$d2 + shr \$2,$d1 + and \$3,$h2 + add $d2,$d1 # =*5 + add $d1,$h0 + adc \$0,$h1 + adc \$0,$h2 + + mov $s1,$r1 + mov $s1,%rax + shr \$2,$s1 + add $r1,$s1 # s1 = r1 + (r1 >> 2) + + add 0($inp),$h0 # accumulate input + adc 8($inp),$h1 + lea 16($inp),$inp + adc $padbit,$h2 + + call __poly1305_block + + test $padbit,$padbit # if $padbit is zero, + jz .Lstore_base2_64_avx # store hash in base 2^64 format + + ################################# base 2^64 -> base 2^26 + mov $h0,%rax + mov $h0,%rdx + shr \$52,$h0 + mov $h1,$r0 + mov $h1,$r1 + shr \$26,%rdx + and \$0x3ffffff,%rax # h[0] + shl \$12,$r0 + and \$0x3ffffff,%rdx # h[1] + shr \$14,$h1 + or $r0,$h0 + shl \$24,$h2 + and \$0x3ffffff,$h0 # h[2] + shr \$40,$r1 + and \$0x3ffffff,$h1 # h[3] + or $r1,$h2 # h[4] + + sub \$16,%r15 + jz .Lstore_base2_26_avx + + vmovd %rax#d,$H0 + vmovd %rdx#d,$H1 + vmovd $h0#d,$H2 + vmovd $h1#d,$H3 + vmovd $h2#d,$H4 + jmp .Lproceed_avx + +.align 32 +.Lstore_base2_64_avx: + mov $h0,0($ctx) + mov $h1,8($ctx) + mov $h2,16($ctx) # note that is_base2_26 is zeroed + jmp .Ldone_avx + +.align 16 +.Lstore_base2_26_avx: + mov %rax#d,0($ctx) # store hash value base 2^26 + mov %rdx#d,4($ctx) + mov $h0#d,8($ctx) + mov $h1#d,12($ctx) + mov $h2#d,16($ctx) +.align 16 +.Ldone_avx: + mov 0(%rsp),%r15 +.cfi_restore %r15 + mov 8(%rsp),%r14 +.cfi_restore %r14 + mov 16(%rsp),%r13 +.cfi_restore %r13 + mov 24(%rsp),%r12 +.cfi_restore %r12 + mov 32(%rsp),%rbp +.cfi_restore %rbp + mov 40(%rsp),%rbx +.cfi_restore %rbx + lea 48(%rsp),%rsp +.cfi_adjust_cfa_offset -48 +.Lno_data_avx: +.Lblocks_avx_epilogue: + ret +.cfi_endproc + +.align 32 +.Lbase2_64_avx: +.cfi_startproc + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +.Lbase2_64_avx_body: + + mov $len,%r15 # reassign $len + + mov 24($ctx),$r0 # load r + mov 32($ctx),$s1 + + mov 0($ctx),$h0 # load hash value + mov 8($ctx),$h1 + mov 16($ctx),$h2#d + + mov $s1,$r1 + mov $s1,%rax + shr \$2,$s1 + add $r1,$s1 # s1 = r1 + (r1 >> 2) + + test \$31,$len + jz .Linit_avx + + add 0($inp),$h0 # accumulate input + adc 8($inp),$h1 + lea 16($inp),$inp + adc $padbit,$h2 + sub \$16,%r15 + + call __poly1305_block + +.Linit_avx: + ################################# base 2^64 -> base 2^26 + mov $h0,%rax + mov $h0,%rdx + shr \$52,$h0 + mov $h1,$d1 + mov $h1,$d2 + shr \$26,%rdx + and \$0x3ffffff,%rax # h[0] + shl \$12,$d1 + and \$0x3ffffff,%rdx # h[1] + shr \$14,$h1 + or $d1,$h0 + shl \$24,$h2 + and \$0x3ffffff,$h0 # h[2] + shr \$40,$d2 + and \$0x3ffffff,$h1 # h[3] + or $d2,$h2 # h[4] + + vmovd %rax#d,$H0 + vmovd %rdx#d,$H1 + vmovd $h0#d,$H2 + vmovd $h1#d,$H3 + vmovd $h2#d,$H4 + movl \$1,20($ctx) # set is_base2_26 + + call __poly1305_init_avx + +.Lproceed_avx: + mov %r15,$len + + mov 0(%rsp),%r15 +.cfi_restore %r15 + mov 8(%rsp),%r14 +.cfi_restore %r14 + mov 16(%rsp),%r13 +.cfi_restore %r13 + mov 24(%rsp),%r12 +.cfi_restore %r12 + mov 32(%rsp),%rbp +.cfi_restore %rbp + mov 40(%rsp),%rbx +.cfi_restore %rbx + lea 48(%rsp),%rax + lea 48(%rsp),%rsp +.cfi_adjust_cfa_offset -48 +.Lbase2_64_avx_epilogue: + jmp .Ldo_avx +.cfi_endproc + +.align 32 +.Leven_avx: +.cfi_startproc + vmovd 4*0($ctx),$H0 # load hash value + vmovd 4*1($ctx),$H1 + vmovd 4*2($ctx),$H2 + vmovd 4*3($ctx),$H3 + vmovd 4*4($ctx),$H4 + +.Ldo_avx: +___ +$code.=<<___ if (!$win64); + lea -0x58(%rsp),%r11 +.cfi_def_cfa %r11,0x60 + sub \$0x178,%rsp +___ +$code.=<<___ if ($win64); + lea -0xf8(%rsp),%r11 + sub \$0x218,%rsp + vmovdqa %xmm6,0x50(%r11) + vmovdqa %xmm7,0x60(%r11) + vmovdqa %xmm8,0x70(%r11) + vmovdqa %xmm9,0x80(%r11) + vmovdqa %xmm10,0x90(%r11) + vmovdqa %xmm11,0xa0(%r11) + vmovdqa %xmm12,0xb0(%r11) + vmovdqa %xmm13,0xc0(%r11) + vmovdqa %xmm14,0xd0(%r11) + vmovdqa %xmm15,0xe0(%r11) +.Ldo_avx_body: +___ +$code.=<<___; + sub \$64,$len + lea -32($inp),%rax + cmovc %rax,$inp + + vmovdqu `16*3`($ctx),$D4 # preload r0^2 + lea `16*3+64`($ctx),$ctx # size optimization + lea .Lconst(%rip),%rcx + + ################################################################ + # load input + vmovdqu 16*2($inp),$T0 + vmovdqu 16*3($inp),$T1 + vmovdqa 64(%rcx),$MASK # .Lmask26 + + vpsrldq \$6,$T0,$T2 # splat input + vpsrldq \$6,$T1,$T3 + vpunpckhqdq $T1,$T0,$T4 # 4 + vpunpcklqdq $T1,$T0,$T0 # 0:1 + vpunpcklqdq $T3,$T2,$T3 # 2:3 + + vpsrlq \$40,$T4,$T4 # 4 + vpsrlq \$26,$T0,$T1 + vpand $MASK,$T0,$T0 # 0 + vpsrlq \$4,$T3,$T2 + vpand $MASK,$T1,$T1 # 1 + vpsrlq \$30,$T3,$T3 + vpand $MASK,$T2,$T2 # 2 + vpand $MASK,$T3,$T3 # 3 + vpor 32(%rcx),$T4,$T4 # padbit, yes, always + + jbe .Lskip_loop_avx + + # expand and copy pre-calculated table to stack + vmovdqu `16*1-64`($ctx),$D1 + vmovdqu `16*2-64`($ctx),$D2 + vpshufd \$0xEE,$D4,$D3 # 34xx -> 3434 + vpshufd \$0x44,$D4,$D0 # xx12 -> 1212 + vmovdqa $D3,-0x90(%r11) + vmovdqa $D0,0x00(%rsp) + vpshufd \$0xEE,$D1,$D4 + vmovdqu `16*3-64`($ctx),$D0 + vpshufd \$0x44,$D1,$D1 + vmovdqa $D4,-0x80(%r11) + vmovdqa $D1,0x10(%rsp) + vpshufd \$0xEE,$D2,$D3 + vmovdqu `16*4-64`($ctx),$D1 + vpshufd \$0x44,$D2,$D2 + vmovdqa $D3,-0x70(%r11) + vmovdqa $D2,0x20(%rsp) + vpshufd \$0xEE,$D0,$D4 + vmovdqu `16*5-64`($ctx),$D2 + vpshufd \$0x44,$D0,$D0 + vmovdqa $D4,-0x60(%r11) + vmovdqa $D0,0x30(%rsp) + vpshufd \$0xEE,$D1,$D3 + vmovdqu `16*6-64`($ctx),$D0 + vpshufd \$0x44,$D1,$D1 + vmovdqa $D3,-0x50(%r11) + vmovdqa $D1,0x40(%rsp) + vpshufd \$0xEE,$D2,$D4 + vmovdqu `16*7-64`($ctx),$D1 + vpshufd \$0x44,$D2,$D2 + vmovdqa $D4,-0x40(%r11) + vmovdqa $D2,0x50(%rsp) + vpshufd \$0xEE,$D0,$D3 + vmovdqu `16*8-64`($ctx),$D2 + vpshufd \$0x44,$D0,$D0 + vmovdqa $D3,-0x30(%r11) + vmovdqa $D0,0x60(%rsp) + vpshufd \$0xEE,$D1,$D4 + vpshufd \$0x44,$D1,$D1 + vmovdqa $D4,-0x20(%r11) + vmovdqa $D1,0x70(%rsp) + vpshufd \$0xEE,$D2,$D3 + vmovdqa 0x00(%rsp),$D4 # preload r0^2 + vpshufd \$0x44,$D2,$D2 + vmovdqa $D3,-0x10(%r11) + vmovdqa $D2,0x80(%rsp) + + jmp .Loop_avx + +.align 32 +.Loop_avx: + ################################################################ + # ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2 + # ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^3+inp[7]*r + # \___________________/ + # ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2+inp[8])*r^2 + # ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^4+inp[7]*r^2+inp[9])*r + # \___________________/ \____________________/ + # + # Note that we start with inp[2:3]*r^2. This is because it + # doesn't depend on reduction in previous iteration. + ################################################################ + # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + # + # though note that $Tx and $Hx are "reversed" in this section, + # and $D4 is preloaded with r0^2... + + vpmuludq $T0,$D4,$D0 # d0 = h0*r0 + vpmuludq $T1,$D4,$D1 # d1 = h1*r0 + vmovdqa $H2,0x20(%r11) # offload hash + vpmuludq $T2,$D4,$D2 # d3 = h2*r0 + vmovdqa 0x10(%rsp),$H2 # r1^2 + vpmuludq $T3,$D4,$D3 # d3 = h3*r0 + vpmuludq $T4,$D4,$D4 # d4 = h4*r0 + + vmovdqa $H0,0x00(%r11) # + vpmuludq 0x20(%rsp),$T4,$H0 # h4*s1 + vmovdqa $H1,0x10(%r11) # + vpmuludq $T3,$H2,$H1 # h3*r1 + vpaddq $H0,$D0,$D0 # d0 += h4*s1 + vpaddq $H1,$D4,$D4 # d4 += h3*r1 + vmovdqa $H3,0x30(%r11) # + vpmuludq $T2,$H2,$H0 # h2*r1 + vpmuludq $T1,$H2,$H1 # h1*r1 + vpaddq $H0,$D3,$D3 # d3 += h2*r1 + vmovdqa 0x30(%rsp),$H3 # r2^2 + vpaddq $H1,$D2,$D2 # d2 += h1*r1 + vmovdqa $H4,0x40(%r11) # + vpmuludq $T0,$H2,$H2 # h0*r1 + vpmuludq $T2,$H3,$H0 # h2*r2 + vpaddq $H2,$D1,$D1 # d1 += h0*r1 + + vmovdqa 0x40(%rsp),$H4 # s2^2 + vpaddq $H0,$D4,$D4 # d4 += h2*r2 + vpmuludq $T1,$H3,$H1 # h1*r2 + vpmuludq $T0,$H3,$H3 # h0*r2 + vpaddq $H1,$D3,$D3 # d3 += h1*r2 + vmovdqa 0x50(%rsp),$H2 # r3^2 + vpaddq $H3,$D2,$D2 # d2 += h0*r2 + vpmuludq $T4,$H4,$H0 # h4*s2 + vpmuludq $T3,$H4,$H4 # h3*s2 + vpaddq $H0,$D1,$D1 # d1 += h4*s2 + vmovdqa 0x60(%rsp),$H3 # s3^2 + vpaddq $H4,$D0,$D0 # d0 += h3*s2 + + vmovdqa 0x80(%rsp),$H4 # s4^2 + vpmuludq $T1,$H2,$H1 # h1*r3 + vpmuludq $T0,$H2,$H2 # h0*r3 + vpaddq $H1,$D4,$D4 # d4 += h1*r3 + vpaddq $H2,$D3,$D3 # d3 += h0*r3 + vpmuludq $T4,$H3,$H0 # h4*s3 + vpmuludq $T3,$H3,$H1 # h3*s3 + vpaddq $H0,$D2,$D2 # d2 += h4*s3 + vmovdqu 16*0($inp),$H0 # load input + vpaddq $H1,$D1,$D1 # d1 += h3*s3 + vpmuludq $T2,$H3,$H3 # h2*s3 + vpmuludq $T2,$H4,$T2 # h2*s4 + vpaddq $H3,$D0,$D0 # d0 += h2*s3 + + vmovdqu 16*1($inp),$H1 # + vpaddq $T2,$D1,$D1 # d1 += h2*s4 + vpmuludq $T3,$H4,$T3 # h3*s4 + vpmuludq $T4,$H4,$T4 # h4*s4 + vpsrldq \$6,$H0,$H2 # splat input + vpaddq $T3,$D2,$D2 # d2 += h3*s4 + vpaddq $T4,$D3,$D3 # d3 += h4*s4 + vpsrldq \$6,$H1,$H3 # + vpmuludq 0x70(%rsp),$T0,$T4 # h0*r4 + vpmuludq $T1,$H4,$T0 # h1*s4 + vpunpckhqdq $H1,$H0,$H4 # 4 + vpaddq $T4,$D4,$D4 # d4 += h0*r4 + vmovdqa -0x90(%r11),$T4 # r0^4 + vpaddq $T0,$D0,$D0 # d0 += h1*s4 + + vpunpcklqdq $H1,$H0,$H0 # 0:1 + vpunpcklqdq $H3,$H2,$H3 # 2:3 + + #vpsrlq \$40,$H4,$H4 # 4 + vpsrldq \$`40/8`,$H4,$H4 # 4 + vpsrlq \$26,$H0,$H1 + vpand $MASK,$H0,$H0 # 0 + vpsrlq \$4,$H3,$H2 + vpand $MASK,$H1,$H1 # 1 + vpand 0(%rcx),$H4,$H4 # .Lmask24 + vpsrlq \$30,$H3,$H3 + vpand $MASK,$H2,$H2 # 2 + vpand $MASK,$H3,$H3 # 3 + vpor 32(%rcx),$H4,$H4 # padbit, yes, always + + vpaddq 0x00(%r11),$H0,$H0 # add hash value + vpaddq 0x10(%r11),$H1,$H1 + vpaddq 0x20(%r11),$H2,$H2 + vpaddq 0x30(%r11),$H3,$H3 + vpaddq 0x40(%r11),$H4,$H4 + + lea 16*2($inp),%rax + lea 16*4($inp),$inp + sub \$64,$len + cmovc %rax,$inp + + ################################################################ + # Now we accumulate (inp[0:1]+hash)*r^4 + ################################################################ + # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + + vpmuludq $H0,$T4,$T0 # h0*r0 + vpmuludq $H1,$T4,$T1 # h1*r0 + vpaddq $T0,$D0,$D0 + vpaddq $T1,$D1,$D1 + vmovdqa -0x80(%r11),$T2 # r1^4 + vpmuludq $H2,$T4,$T0 # h2*r0 + vpmuludq $H3,$T4,$T1 # h3*r0 + vpaddq $T0,$D2,$D2 + vpaddq $T1,$D3,$D3 + vpmuludq $H4,$T4,$T4 # h4*r0 + vpmuludq -0x70(%r11),$H4,$T0 # h4*s1 + vpaddq $T4,$D4,$D4 + + vpaddq $T0,$D0,$D0 # d0 += h4*s1 + vpmuludq $H2,$T2,$T1 # h2*r1 + vpmuludq $H3,$T2,$T0 # h3*r1 + vpaddq $T1,$D3,$D3 # d3 += h2*r1 + vmovdqa -0x60(%r11),$T3 # r2^4 + vpaddq $T0,$D4,$D4 # d4 += h3*r1 + vpmuludq $H1,$T2,$T1 # h1*r1 + vpmuludq $H0,$T2,$T2 # h0*r1 + vpaddq $T1,$D2,$D2 # d2 += h1*r1 + vpaddq $T2,$D1,$D1 # d1 += h0*r1 + + vmovdqa -0x50(%r11),$T4 # s2^4 + vpmuludq $H2,$T3,$T0 # h2*r2 + vpmuludq $H1,$T3,$T1 # h1*r2 + vpaddq $T0,$D4,$D4 # d4 += h2*r2 + vpaddq $T1,$D3,$D3 # d3 += h1*r2 + vmovdqa -0x40(%r11),$T2 # r3^4 + vpmuludq $H0,$T3,$T3 # h0*r2 + vpmuludq $H4,$T4,$T0 # h4*s2 + vpaddq $T3,$D2,$D2 # d2 += h0*r2 + vpaddq $T0,$D1,$D1 # d1 += h4*s2 + vmovdqa -0x30(%r11),$T3 # s3^4 + vpmuludq $H3,$T4,$T4 # h3*s2 + vpmuludq $H1,$T2,$T1 # h1*r3 + vpaddq $T4,$D0,$D0 # d0 += h3*s2 + + vmovdqa -0x10(%r11),$T4 # s4^4 + vpaddq $T1,$D4,$D4 # d4 += h1*r3 + vpmuludq $H0,$T2,$T2 # h0*r3 + vpmuludq $H4,$T3,$T0 # h4*s3 + vpaddq $T2,$D3,$D3 # d3 += h0*r3 + vpaddq $T0,$D2,$D2 # d2 += h4*s3 + vmovdqu 16*2($inp),$T0 # load input + vpmuludq $H3,$T3,$T2 # h3*s3 + vpmuludq $H2,$T3,$T3 # h2*s3 + vpaddq $T2,$D1,$D1 # d1 += h3*s3 + vmovdqu 16*3($inp),$T1 # + vpaddq $T3,$D0,$D0 # d0 += h2*s3 + + vpmuludq $H2,$T4,$H2 # h2*s4 + vpmuludq $H3,$T4,$H3 # h3*s4 + vpsrldq \$6,$T0,$T2 # splat input + vpaddq $H2,$D1,$D1 # d1 += h2*s4 + vpmuludq $H4,$T4,$H4 # h4*s4 + vpsrldq \$6,$T1,$T3 # + vpaddq $H3,$D2,$H2 # h2 = d2 + h3*s4 + vpaddq $H4,$D3,$H3 # h3 = d3 + h4*s4 + vpmuludq -0x20(%r11),$H0,$H4 # h0*r4 + vpmuludq $H1,$T4,$H0 + vpunpckhqdq $T1,$T0,$T4 # 4 + vpaddq $H4,$D4,$H4 # h4 = d4 + h0*r4 + vpaddq $H0,$D0,$H0 # h0 = d0 + h1*s4 + + vpunpcklqdq $T1,$T0,$T0 # 0:1 + vpunpcklqdq $T3,$T2,$T3 # 2:3 + + #vpsrlq \$40,$T4,$T4 # 4 + vpsrldq \$`40/8`,$T4,$T4 # 4 + vpsrlq \$26,$T0,$T1 + vmovdqa 0x00(%rsp),$D4 # preload r0^2 + vpand $MASK,$T0,$T0 # 0 + vpsrlq \$4,$T3,$T2 + vpand $MASK,$T1,$T1 # 1 + vpand 0(%rcx),$T4,$T4 # .Lmask24 + vpsrlq \$30,$T3,$T3 + vpand $MASK,$T2,$T2 # 2 + vpand $MASK,$T3,$T3 # 3 + vpor 32(%rcx),$T4,$T4 # padbit, yes, always + + ################################################################ + # lazy reduction as discussed in "NEON crypto" by D.J. Bernstein + # and P. Schwabe + + vpsrlq \$26,$H3,$D3 + vpand $MASK,$H3,$H3 + vpaddq $D3,$H4,$H4 # h3 -> h4 + + vpsrlq \$26,$H0,$D0 + vpand $MASK,$H0,$H0 + vpaddq $D0,$D1,$H1 # h0 -> h1 + + vpsrlq \$26,$H4,$D0 + vpand $MASK,$H4,$H4 + + vpsrlq \$26,$H1,$D1 + vpand $MASK,$H1,$H1 + vpaddq $D1,$H2,$H2 # h1 -> h2 + + vpaddq $D0,$H0,$H0 + vpsllq \$2,$D0,$D0 + vpaddq $D0,$H0,$H0 # h4 -> h0 + + vpsrlq \$26,$H2,$D2 + vpand $MASK,$H2,$H2 + vpaddq $D2,$H3,$H3 # h2 -> h3 + + vpsrlq \$26,$H0,$D0 + vpand $MASK,$H0,$H0 + vpaddq $D0,$H1,$H1 # h0 -> h1 + + vpsrlq \$26,$H3,$D3 + vpand $MASK,$H3,$H3 + vpaddq $D3,$H4,$H4 # h3 -> h4 + + ja .Loop_avx + +.Lskip_loop_avx: + ################################################################ + # multiply (inp[0:1]+hash) or inp[2:3] by r^2:r^1 + + vpshufd \$0x10,$D4,$D4 # r0^n, xx12 -> x1x2 + add \$32,$len + jnz .Long_tail_avx + + vpaddq $H2,$T2,$T2 + vpaddq $H0,$T0,$T0 + vpaddq $H1,$T1,$T1 + vpaddq $H3,$T3,$T3 + vpaddq $H4,$T4,$T4 + +.Long_tail_avx: + vmovdqa $H2,0x20(%r11) + vmovdqa $H0,0x00(%r11) + vmovdqa $H1,0x10(%r11) + vmovdqa $H3,0x30(%r11) + vmovdqa $H4,0x40(%r11) + + # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + + vpmuludq $T2,$D4,$D2 # d2 = h2*r0 + vpmuludq $T0,$D4,$D0 # d0 = h0*r0 + vpshufd \$0x10,`16*1-64`($ctx),$H2 # r1^n + vpmuludq $T1,$D4,$D1 # d1 = h1*r0 + vpmuludq $T3,$D4,$D3 # d3 = h3*r0 + vpmuludq $T4,$D4,$D4 # d4 = h4*r0 + + vpmuludq $T3,$H2,$H0 # h3*r1 + vpaddq $H0,$D4,$D4 # d4 += h3*r1 + vpshufd \$0x10,`16*2-64`($ctx),$H3 # s1^n + vpmuludq $T2,$H2,$H1 # h2*r1 + vpaddq $H1,$D3,$D3 # d3 += h2*r1 + vpshufd \$0x10,`16*3-64`($ctx),$H4 # r2^n + vpmuludq $T1,$H2,$H0 # h1*r1 + vpaddq $H0,$D2,$D2 # d2 += h1*r1 + vpmuludq $T0,$H2,$H2 # h0*r1 + vpaddq $H2,$D1,$D1 # d1 += h0*r1 + vpmuludq $T4,$H3,$H3 # h4*s1 + vpaddq $H3,$D0,$D0 # d0 += h4*s1 + + vpshufd \$0x10,`16*4-64`($ctx),$H2 # s2^n + vpmuludq $T2,$H4,$H1 # h2*r2 + vpaddq $H1,$D4,$D4 # d4 += h2*r2 + vpmuludq $T1,$H4,$H0 # h1*r2 + vpaddq $H0,$D3,$D3 # d3 += h1*r2 + vpshufd \$0x10,`16*5-64`($ctx),$H3 # r3^n + vpmuludq $T0,$H4,$H4 # h0*r2 + vpaddq $H4,$D2,$D2 # d2 += h0*r2 + vpmuludq $T4,$H2,$H1 # h4*s2 + vpaddq $H1,$D1,$D1 # d1 += h4*s2 + vpshufd \$0x10,`16*6-64`($ctx),$H4 # s3^n + vpmuludq $T3,$H2,$H2 # h3*s2 + vpaddq $H2,$D0,$D0 # d0 += h3*s2 + + vpmuludq $T1,$H3,$H0 # h1*r3 + vpaddq $H0,$D4,$D4 # d4 += h1*r3 + vpmuludq $T0,$H3,$H3 # h0*r3 + vpaddq $H3,$D3,$D3 # d3 += h0*r3 + vpshufd \$0x10,`16*7-64`($ctx),$H2 # r4^n + vpmuludq $T4,$H4,$H1 # h4*s3 + vpaddq $H1,$D2,$D2 # d2 += h4*s3 + vpshufd \$0x10,`16*8-64`($ctx),$H3 # s4^n + vpmuludq $T3,$H4,$H0 # h3*s3 + vpaddq $H0,$D1,$D1 # d1 += h3*s3 + vpmuludq $T2,$H4,$H4 # h2*s3 + vpaddq $H4,$D0,$D0 # d0 += h2*s3 + + vpmuludq $T0,$H2,$H2 # h0*r4 + vpaddq $H2,$D4,$D4 # h4 = d4 + h0*r4 + vpmuludq $T4,$H3,$H1 # h4*s4 + vpaddq $H1,$D3,$D3 # h3 = d3 + h4*s4 + vpmuludq $T3,$H3,$H0 # h3*s4 + vpaddq $H0,$D2,$D2 # h2 = d2 + h3*s4 + vpmuludq $T2,$H3,$H1 # h2*s4 + vpaddq $H1,$D1,$D1 # h1 = d1 + h2*s4 + vpmuludq $T1,$H3,$H3 # h1*s4 + vpaddq $H3,$D0,$D0 # h0 = d0 + h1*s4 + + jz .Lshort_tail_avx + + vmovdqu 16*0($inp),$H0 # load input + vmovdqu 16*1($inp),$H1 + + vpsrldq \$6,$H0,$H2 # splat input + vpsrldq \$6,$H1,$H3 + vpunpckhqdq $H1,$H0,$H4 # 4 + vpunpcklqdq $H1,$H0,$H0 # 0:1 + vpunpcklqdq $H3,$H2,$H3 # 2:3 + + vpsrlq \$40,$H4,$H4 # 4 + vpsrlq \$26,$H0,$H1 + vpand $MASK,$H0,$H0 # 0 + vpsrlq \$4,$H3,$H2 + vpand $MASK,$H1,$H1 # 1 + vpsrlq \$30,$H3,$H3 + vpand $MASK,$H2,$H2 # 2 + vpand $MASK,$H3,$H3 # 3 + vpor 32(%rcx),$H4,$H4 # padbit, yes, always + + vpshufd \$0x32,`16*0-64`($ctx),$T4 # r0^n, 34xx -> x3x4 + vpaddq 0x00(%r11),$H0,$H0 + vpaddq 0x10(%r11),$H1,$H1 + vpaddq 0x20(%r11),$H2,$H2 + vpaddq 0x30(%r11),$H3,$H3 + vpaddq 0x40(%r11),$H4,$H4 + + ################################################################ + # multiply (inp[0:1]+hash) by r^4:r^3 and accumulate + + vpmuludq $H0,$T4,$T0 # h0*r0 + vpaddq $T0,$D0,$D0 # d0 += h0*r0 + vpmuludq $H1,$T4,$T1 # h1*r0 + vpaddq $T1,$D1,$D1 # d1 += h1*r0 + vpmuludq $H2,$T4,$T0 # h2*r0 + vpaddq $T0,$D2,$D2 # d2 += h2*r0 + vpshufd \$0x32,`16*1-64`($ctx),$T2 # r1^n + vpmuludq $H3,$T4,$T1 # h3*r0 + vpaddq $T1,$D3,$D3 # d3 += h3*r0 + vpmuludq $H4,$T4,$T4 # h4*r0 + vpaddq $T4,$D4,$D4 # d4 += h4*r0 + + vpmuludq $H3,$T2,$T0 # h3*r1 + vpaddq $T0,$D4,$D4 # d4 += h3*r1 + vpshufd \$0x32,`16*2-64`($ctx),$T3 # s1 + vpmuludq $H2,$T2,$T1 # h2*r1 + vpaddq $T1,$D3,$D3 # d3 += h2*r1 + vpshufd \$0x32,`16*3-64`($ctx),$T4 # r2 + vpmuludq $H1,$T2,$T0 # h1*r1 + vpaddq $T0,$D2,$D2 # d2 += h1*r1 + vpmuludq $H0,$T2,$T2 # h0*r1 + vpaddq $T2,$D1,$D1 # d1 += h0*r1 + vpmuludq $H4,$T3,$T3 # h4*s1 + vpaddq $T3,$D0,$D0 # d0 += h4*s1 + + vpshufd \$0x32,`16*4-64`($ctx),$T2 # s2 + vpmuludq $H2,$T4,$T1 # h2*r2 + vpaddq $T1,$D4,$D4 # d4 += h2*r2 + vpmuludq $H1,$T4,$T0 # h1*r2 + vpaddq $T0,$D3,$D3 # d3 += h1*r2 + vpshufd \$0x32,`16*5-64`($ctx),$T3 # r3 + vpmuludq $H0,$T4,$T4 # h0*r2 + vpaddq $T4,$D2,$D2 # d2 += h0*r2 + vpmuludq $H4,$T2,$T1 # h4*s2 + vpaddq $T1,$D1,$D1 # d1 += h4*s2 + vpshufd \$0x32,`16*6-64`($ctx),$T4 # s3 + vpmuludq $H3,$T2,$T2 # h3*s2 + vpaddq $T2,$D0,$D0 # d0 += h3*s2 + + vpmuludq $H1,$T3,$T0 # h1*r3 + vpaddq $T0,$D4,$D4 # d4 += h1*r3 + vpmuludq $H0,$T3,$T3 # h0*r3 + vpaddq $T3,$D3,$D3 # d3 += h0*r3 + vpshufd \$0x32,`16*7-64`($ctx),$T2 # r4 + vpmuludq $H4,$T4,$T1 # h4*s3 + vpaddq $T1,$D2,$D2 # d2 += h4*s3 + vpshufd \$0x32,`16*8-64`($ctx),$T3 # s4 + vpmuludq $H3,$T4,$T0 # h3*s3 + vpaddq $T0,$D1,$D1 # d1 += h3*s3 + vpmuludq $H2,$T4,$T4 # h2*s3 + vpaddq $T4,$D0,$D0 # d0 += h2*s3 + + vpmuludq $H0,$T2,$T2 # h0*r4 + vpaddq $T2,$D4,$D4 # d4 += h0*r4 + vpmuludq $H4,$T3,$T1 # h4*s4 + vpaddq $T1,$D3,$D3 # d3 += h4*s4 + vpmuludq $H3,$T3,$T0 # h3*s4 + vpaddq $T0,$D2,$D2 # d2 += h3*s4 + vpmuludq $H2,$T3,$T1 # h2*s4 + vpaddq $T1,$D1,$D1 # d1 += h2*s4 + vpmuludq $H1,$T3,$T3 # h1*s4 + vpaddq $T3,$D0,$D0 # d0 += h1*s4 + +.Lshort_tail_avx: + ################################################################ + # horizontal addition + + vpsrldq \$8,$D4,$T4 + vpsrldq \$8,$D3,$T3 + vpsrldq \$8,$D1,$T1 + vpsrldq \$8,$D0,$T0 + vpsrldq \$8,$D2,$T2 + vpaddq $T3,$D3,$D3 + vpaddq $T4,$D4,$D4 + vpaddq $T0,$D0,$D0 + vpaddq $T1,$D1,$D1 + vpaddq $T2,$D2,$D2 + + ################################################################ + # lazy reduction + + vpsrlq \$26,$D3,$H3 + vpand $MASK,$D3,$D3 + vpaddq $H3,$D4,$D4 # h3 -> h4 + + vpsrlq \$26,$D0,$H0 + vpand $MASK,$D0,$D0 + vpaddq $H0,$D1,$D1 # h0 -> h1 + + vpsrlq \$26,$D4,$H4 + vpand $MASK,$D4,$D4 + + vpsrlq \$26,$D1,$H1 + vpand $MASK,$D1,$D1 + vpaddq $H1,$D2,$D2 # h1 -> h2 + + vpaddq $H4,$D0,$D0 + vpsllq \$2,$H4,$H4 + vpaddq $H4,$D0,$D0 # h4 -> h0 + + vpsrlq \$26,$D2,$H2 + vpand $MASK,$D2,$D2 + vpaddq $H2,$D3,$D3 # h2 -> h3 + + vpsrlq \$26,$D0,$H0 + vpand $MASK,$D0,$D0 + vpaddq $H0,$D1,$D1 # h0 -> h1 + + vpsrlq \$26,$D3,$H3 + vpand $MASK,$D3,$D3 + vpaddq $H3,$D4,$D4 # h3 -> h4 + + vmovd $D0,`4*0-48-64`($ctx) # save partially reduced + vmovd $D1,`4*1-48-64`($ctx) + vmovd $D2,`4*2-48-64`($ctx) + vmovd $D3,`4*3-48-64`($ctx) + vmovd $D4,`4*4-48-64`($ctx) +___ +$code.=<<___ if ($win64); + vmovdqa 0x50(%r11),%xmm6 + vmovdqa 0x60(%r11),%xmm7 + vmovdqa 0x70(%r11),%xmm8 + vmovdqa 0x80(%r11),%xmm9 + vmovdqa 0x90(%r11),%xmm10 + vmovdqa 0xa0(%r11),%xmm11 + vmovdqa 0xb0(%r11),%xmm12 + vmovdqa 0xc0(%r11),%xmm13 + vmovdqa 0xd0(%r11),%xmm14 + vmovdqa 0xe0(%r11),%xmm15 + lea 0xf8(%r11),%rsp +.Ldo_avx_epilogue: +___ +$code.=<<___ if (!$win64); + lea 0x58(%r11),%rsp +.cfi_def_cfa %rsp,8 +___ +$code.=<<___; + vzeroupper + ret +.cfi_endproc +.size poly1305_blocks_avx,.-poly1305_blocks_avx + +.type poly1305_emit_avx,\@function,3 +.align 32 +poly1305_emit_avx: + cmpl \$0,20($ctx) # is_base2_26? + je .Lemit + + mov 0($ctx),%eax # load hash value base 2^26 + mov 4($ctx),%ecx + mov 8($ctx),%r8d + mov 12($ctx),%r11d + mov 16($ctx),%r10d + + shl \$26,%rcx # base 2^26 -> base 2^64 + mov %r8,%r9 + shl \$52,%r8 + add %rcx,%rax + shr \$12,%r9 + add %rax,%r8 # h0 + adc \$0,%r9 + + shl \$14,%r11 + mov %r10,%rax + shr \$24,%r10 + add %r11,%r9 + shl \$40,%rax + add %rax,%r9 # h1 + adc \$0,%r10 # h2 + + mov %r10,%rax # could be partially reduced, so reduce + mov %r10,%rcx + and \$3,%r10 + shr \$2,%rax + and \$-4,%rcx + add %rcx,%rax + add %rax,%r8 + adc \$0,%r9 + adc \$0,%r10 + + mov %r8,%rax + add \$5,%r8 # compare to modulus + mov %r9,%rcx + adc \$0,%r9 + adc \$0,%r10 + shr \$2,%r10 # did 130-bit value overflow? + cmovnz %r8,%rax + cmovnz %r9,%rcx + + add 0($nonce),%rax # accumulate nonce + adc 8($nonce),%rcx + mov %rax,0($mac) # write result + mov %rcx,8($mac) + + ret +.size poly1305_emit_avx,.-poly1305_emit_avx +___ + +if ($avx>1) { +my ($H0,$H1,$H2,$H3,$H4, $MASK, $T4,$T0,$T1,$T2,$T3, $D0,$D1,$D2,$D3,$D4) = + map("%ymm$_",(0..15)); +my $S4=$MASK; + +$code.=<<___; +.type poly1305_blocks_avx2,\@function,4 +.align 32 +poly1305_blocks_avx2: +.cfi_startproc + mov 20($ctx),%r8d # is_base2_26 + cmp \$128,$len + jae .Lblocks_avx2 + test %r8d,%r8d + jz .Lblocks + +.Lblocks_avx2: + and \$-16,$len + jz .Lno_data_avx2 + + vzeroupper + + test %r8d,%r8d + jz .Lbase2_64_avx2 + + test \$63,$len + jz .Leven_avx2 + + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +.Lblocks_avx2_body: + + mov $len,%r15 # reassign $len + + mov 0($ctx),$d1 # load hash value + mov 8($ctx),$d2 + mov 16($ctx),$h2#d + + mov 24($ctx),$r0 # load r + mov 32($ctx),$s1 + + ################################# base 2^26 -> base 2^64 + mov $d1#d,$h0#d + and \$`-1*(1<<31)`,$d1 + mov $d2,$r1 # borrow $r1 + mov $d2#d,$h1#d + and \$`-1*(1<<31)`,$d2 + + shr \$6,$d1 + shl \$52,$r1 + add $d1,$h0 + shr \$12,$h1 + shr \$18,$d2 + add $r1,$h0 + adc $d2,$h1 + + mov $h2,$d1 + shl \$40,$d1 + shr \$24,$h2 + add $d1,$h1 + adc \$0,$h2 # can be partially reduced... + + mov \$-4,$d2 # ... so reduce + mov $h2,$d1 + and $h2,$d2 + shr \$2,$d1 + and \$3,$h2 + add $d2,$d1 # =*5 + add $d1,$h0 + adc \$0,$h1 + adc \$0,$h2 + + mov $s1,$r1 + mov $s1,%rax + shr \$2,$s1 + add $r1,$s1 # s1 = r1 + (r1 >> 2) + +.Lbase2_26_pre_avx2: + add 0($inp),$h0 # accumulate input + adc 8($inp),$h1 + lea 16($inp),$inp + adc $padbit,$h2 + sub \$16,%r15 + + call __poly1305_block + mov $r1,%rax + + test \$63,%r15 + jnz .Lbase2_26_pre_avx2 + + test $padbit,$padbit # if $padbit is zero, + jz .Lstore_base2_64_avx2 # store hash in base 2^64 format + + ################################# base 2^64 -> base 2^26 + mov $h0,%rax + mov $h0,%rdx + shr \$52,$h0 + mov $h1,$r0 + mov $h1,$r1 + shr \$26,%rdx + and \$0x3ffffff,%rax # h[0] + shl \$12,$r0 + and \$0x3ffffff,%rdx # h[1] + shr \$14,$h1 + or $r0,$h0 + shl \$24,$h2 + and \$0x3ffffff,$h0 # h[2] + shr \$40,$r1 + and \$0x3ffffff,$h1 # h[3] + or $r1,$h2 # h[4] + + test %r15,%r15 + jz .Lstore_base2_26_avx2 + + vmovd %rax#d,%x#$H0 + vmovd %rdx#d,%x#$H1 + vmovd $h0#d,%x#$H2 + vmovd $h1#d,%x#$H3 + vmovd $h2#d,%x#$H4 + jmp .Lproceed_avx2 + +.align 32 +.Lstore_base2_64_avx2: + mov $h0,0($ctx) + mov $h1,8($ctx) + mov $h2,16($ctx) # note that is_base2_26 is zeroed + jmp .Ldone_avx2 + +.align 16 +.Lstore_base2_26_avx2: + mov %rax#d,0($ctx) # store hash value base 2^26 + mov %rdx#d,4($ctx) + mov $h0#d,8($ctx) + mov $h1#d,12($ctx) + mov $h2#d,16($ctx) +.align 16 +.Ldone_avx2: + mov 0(%rsp),%r15 +.cfi_restore %r15 + mov 8(%rsp),%r14 +.cfi_restore %r14 + mov 16(%rsp),%r13 +.cfi_restore %r13 + mov 24(%rsp),%r12 +.cfi_restore %r12 + mov 32(%rsp),%rbp +.cfi_restore %rbp + mov 40(%rsp),%rbx +.cfi_restore %rbx + lea 48(%rsp),%rsp +.cfi_adjust_cfa_offset -48 +.Lno_data_avx2: +.Lblocks_avx2_epilogue: + ret +.cfi_endproc + +.align 32 +.Lbase2_64_avx2: +.cfi_startproc + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +.Lbase2_64_avx2_body: + + mov $len,%r15 # reassign $len + + mov 24($ctx),$r0 # load r + mov 32($ctx),$s1 + + mov 0($ctx),$h0 # load hash value + mov 8($ctx),$h1 + mov 16($ctx),$h2#d + + mov $s1,$r1 + mov $s1,%rax + shr \$2,$s1 + add $r1,$s1 # s1 = r1 + (r1 >> 2) + + test \$63,$len + jz .Linit_avx2 + +.Lbase2_64_pre_avx2: + add 0($inp),$h0 # accumulate input + adc 8($inp),$h1 + lea 16($inp),$inp + adc $padbit,$h2 + sub \$16,%r15 + + call __poly1305_block + mov $r1,%rax + + test \$63,%r15 + jnz .Lbase2_64_pre_avx2 + +.Linit_avx2: + ################################# base 2^64 -> base 2^26 + mov $h0,%rax + mov $h0,%rdx + shr \$52,$h0 + mov $h1,$d1 + mov $h1,$d2 + shr \$26,%rdx + and \$0x3ffffff,%rax # h[0] + shl \$12,$d1 + and \$0x3ffffff,%rdx # h[1] + shr \$14,$h1 + or $d1,$h0 + shl \$24,$h2 + and \$0x3ffffff,$h0 # h[2] + shr \$40,$d2 + and \$0x3ffffff,$h1 # h[3] + or $d2,$h2 # h[4] + + vmovd %rax#d,%x#$H0 + vmovd %rdx#d,%x#$H1 + vmovd $h0#d,%x#$H2 + vmovd $h1#d,%x#$H3 + vmovd $h2#d,%x#$H4 + movl \$1,20($ctx) # set is_base2_26 + + call __poly1305_init_avx + +.Lproceed_avx2: + mov %r15,$len # restore $len + mov OPENSSL_ia32cap_P+8(%rip),%r10d + mov \$`(1<<31|1<<30|1<<16)`,%r11d + + mov 0(%rsp),%r15 +.cfi_restore %r15 + mov 8(%rsp),%r14 +.cfi_restore %r14 + mov 16(%rsp),%r13 +.cfi_restore %r13 + mov 24(%rsp),%r12 +.cfi_restore %r12 + mov 32(%rsp),%rbp +.cfi_restore %rbp + mov 40(%rsp),%rbx +.cfi_restore %rbx + lea 48(%rsp),%rax + lea 48(%rsp),%rsp +.cfi_adjust_cfa_offset -48 +.Lbase2_64_avx2_epilogue: + jmp .Ldo_avx2 +.cfi_endproc + +.align 32 +.Leven_avx2: +.cfi_startproc + mov OPENSSL_ia32cap_P+8(%rip),%r10d + vmovd 4*0($ctx),%x#$H0 # load hash value base 2^26 + vmovd 4*1($ctx),%x#$H1 + vmovd 4*2($ctx),%x#$H2 + vmovd 4*3($ctx),%x#$H3 + vmovd 4*4($ctx),%x#$H4 + +.Ldo_avx2: +___ +$code.=<<___ if ($avx>2); + cmp \$512,$len + jb .Lskip_avx512 + and %r11d,%r10d + test \$`1<<16`,%r10d # check for AVX512F + jnz .Lblocks_avx512 +.Lskip_avx512: +___ +$code.=<<___ if (!$win64); + lea -8(%rsp),%r11 +.cfi_def_cfa %r11,16 + sub \$0x128,%rsp +___ +$code.=<<___ if ($win64); + lea -0xf8(%rsp),%r11 + sub \$0x1c8,%rsp + vmovdqa %xmm6,0x50(%r11) + vmovdqa %xmm7,0x60(%r11) + vmovdqa %xmm8,0x70(%r11) + vmovdqa %xmm9,0x80(%r11) + vmovdqa %xmm10,0x90(%r11) + vmovdqa %xmm11,0xa0(%r11) + vmovdqa %xmm12,0xb0(%r11) + vmovdqa %xmm13,0xc0(%r11) + vmovdqa %xmm14,0xd0(%r11) + vmovdqa %xmm15,0xe0(%r11) +.Ldo_avx2_body: +___ +$code.=<<___; + lea .Lconst(%rip),%rcx + lea 48+64($ctx),$ctx # size optimization + vmovdqa 96(%rcx),$T0 # .Lpermd_avx2 + + # expand and copy pre-calculated table to stack + vmovdqu `16*0-64`($ctx),%x#$T2 + and \$-512,%rsp + vmovdqu `16*1-64`($ctx),%x#$T3 + vmovdqu `16*2-64`($ctx),%x#$T4 + vmovdqu `16*3-64`($ctx),%x#$D0 + vmovdqu `16*4-64`($ctx),%x#$D1 + vmovdqu `16*5-64`($ctx),%x#$D2 + lea 0x90(%rsp),%rax # size optimization + vmovdqu `16*6-64`($ctx),%x#$D3 + vpermd $T2,$T0,$T2 # 00003412 -> 14243444 + vmovdqu `16*7-64`($ctx),%x#$D4 + vpermd $T3,$T0,$T3 + vmovdqu `16*8-64`($ctx),%x#$MASK + vpermd $T4,$T0,$T4 + vmovdqa $T2,0x00(%rsp) + vpermd $D0,$T0,$D0 + vmovdqa $T3,0x20-0x90(%rax) + vpermd $D1,$T0,$D1 + vmovdqa $T4,0x40-0x90(%rax) + vpermd $D2,$T0,$D2 + vmovdqa $D0,0x60-0x90(%rax) + vpermd $D3,$T0,$D3 + vmovdqa $D1,0x80-0x90(%rax) + vpermd $D4,$T0,$D4 + vmovdqa $D2,0xa0-0x90(%rax) + vpermd $MASK,$T0,$MASK + vmovdqa $D3,0xc0-0x90(%rax) + vmovdqa $D4,0xe0-0x90(%rax) + vmovdqa $MASK,0x100-0x90(%rax) + vmovdqa 64(%rcx),$MASK # .Lmask26 + + ################################################################ + # load input + vmovdqu 16*0($inp),%x#$T0 + vmovdqu 16*1($inp),%x#$T1 + vinserti128 \$1,16*2($inp),$T0,$T0 + vinserti128 \$1,16*3($inp),$T1,$T1 + lea 16*4($inp),$inp + + vpsrldq \$6,$T0,$T2 # splat input + vpsrldq \$6,$T1,$T3 + vpunpckhqdq $T1,$T0,$T4 # 4 + vpunpcklqdq $T3,$T2,$T2 # 2:3 + vpunpcklqdq $T1,$T0,$T0 # 0:1 + + vpsrlq \$30,$T2,$T3 + vpsrlq \$4,$T2,$T2 + vpsrlq \$26,$T0,$T1 + vpsrlq \$40,$T4,$T4 # 4 + vpand $MASK,$T2,$T2 # 2 + vpand $MASK,$T0,$T0 # 0 + vpand $MASK,$T1,$T1 # 1 + vpand $MASK,$T3,$T3 # 3 + vpor 32(%rcx),$T4,$T4 # padbit, yes, always + + vpaddq $H2,$T2,$H2 # accumulate input + sub \$64,$len + jz .Ltail_avx2 + jmp .Loop_avx2 + +.align 32 +.Loop_avx2: + ################################################################ + # ((inp[0]*r^4+inp[4])*r^4+inp[ 8])*r^4 + # ((inp[1]*r^4+inp[5])*r^4+inp[ 9])*r^3 + # ((inp[2]*r^4+inp[6])*r^4+inp[10])*r^2 + # ((inp[3]*r^4+inp[7])*r^4+inp[11])*r^1 + # \________/\__________/ + ################################################################ + #vpaddq $H2,$T2,$H2 # accumulate input + vpaddq $H0,$T0,$H0 + vmovdqa `32*0`(%rsp),$T0 # r0^4 + vpaddq $H1,$T1,$H1 + vmovdqa `32*1`(%rsp),$T1 # r1^4 + vpaddq $H3,$T3,$H3 + vmovdqa `32*3`(%rsp),$T2 # r2^4 + vpaddq $H4,$T4,$H4 + vmovdqa `32*6-0x90`(%rax),$T3 # s3^4 + vmovdqa `32*8-0x90`(%rax),$S4 # s4^4 + + # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + # + # however, as h2 is "chronologically" first one available pull + # corresponding operations up, so it's + # + # d4 = h2*r2 + h4*r0 + h3*r1 + h1*r3 + h0*r4 + # d3 = h2*r1 + h3*r0 + h1*r2 + h0*r3 + h4*5*r4 + # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + # d1 = h2*5*r4 + h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + # d0 = h2*5*r3 + h0*r0 + h4*5*r1 + h3*5*r2 + h1*5*r4 + + vpmuludq $H2,$T0,$D2 # d2 = h2*r0 + vpmuludq $H2,$T1,$D3 # d3 = h2*r1 + vpmuludq $H2,$T2,$D4 # d4 = h2*r2 + vpmuludq $H2,$T3,$D0 # d0 = h2*s3 + vpmuludq $H2,$S4,$D1 # d1 = h2*s4 + + vpmuludq $H0,$T1,$T4 # h0*r1 + vpmuludq $H1,$T1,$H2 # h1*r1, borrow $H2 as temp + vpaddq $T4,$D1,$D1 # d1 += h0*r1 + vpaddq $H2,$D2,$D2 # d2 += h1*r1 + vpmuludq $H3,$T1,$T4 # h3*r1 + vpmuludq `32*2`(%rsp),$H4,$H2 # h4*s1 + vpaddq $T4,$D4,$D4 # d4 += h3*r1 + vpaddq $H2,$D0,$D0 # d0 += h4*s1 + vmovdqa `32*4-0x90`(%rax),$T1 # s2 + + vpmuludq $H0,$T0,$T4 # h0*r0 + vpmuludq $H1,$T0,$H2 # h1*r0 + vpaddq $T4,$D0,$D0 # d0 += h0*r0 + vpaddq $H2,$D1,$D1 # d1 += h1*r0 + vpmuludq $H3,$T0,$T4 # h3*r0 + vpmuludq $H4,$T0,$H2 # h4*r0 + vmovdqu 16*0($inp),%x#$T0 # load input + vpaddq $T4,$D3,$D3 # d3 += h3*r0 + vpaddq $H2,$D4,$D4 # d4 += h4*r0 + vinserti128 \$1,16*2($inp),$T0,$T0 + + vpmuludq $H3,$T1,$T4 # h3*s2 + vpmuludq $H4,$T1,$H2 # h4*s2 + vmovdqu 16*1($inp),%x#$T1 + vpaddq $T4,$D0,$D0 # d0 += h3*s2 + vpaddq $H2,$D1,$D1 # d1 += h4*s2 + vmovdqa `32*5-0x90`(%rax),$H2 # r3 + vpmuludq $H1,$T2,$T4 # h1*r2 + vpmuludq $H0,$T2,$T2 # h0*r2 + vpaddq $T4,$D3,$D3 # d3 += h1*r2 + vpaddq $T2,$D2,$D2 # d2 += h0*r2 + vinserti128 \$1,16*3($inp),$T1,$T1 + lea 16*4($inp),$inp + + vpmuludq $H1,$H2,$T4 # h1*r3 + vpmuludq $H0,$H2,$H2 # h0*r3 + vpsrldq \$6,$T0,$T2 # splat input + vpaddq $T4,$D4,$D4 # d4 += h1*r3 + vpaddq $H2,$D3,$D3 # d3 += h0*r3 + vpmuludq $H3,$T3,$T4 # h3*s3 + vpmuludq $H4,$T3,$H2 # h4*s3 + vpsrldq \$6,$T1,$T3 + vpaddq $T4,$D1,$D1 # d1 += h3*s3 + vpaddq $H2,$D2,$D2 # d2 += h4*s3 + vpunpckhqdq $T1,$T0,$T4 # 4 + + vpmuludq $H3,$S4,$H3 # h3*s4 + vpmuludq $H4,$S4,$H4 # h4*s4 + vpunpcklqdq $T1,$T0,$T0 # 0:1 + vpaddq $H3,$D2,$H2 # h2 = d2 + h3*r4 + vpaddq $H4,$D3,$H3 # h3 = d3 + h4*r4 + vpunpcklqdq $T3,$T2,$T3 # 2:3 + vpmuludq `32*7-0x90`(%rax),$H0,$H4 # h0*r4 + vpmuludq $H1,$S4,$H0 # h1*s4 + vmovdqa 64(%rcx),$MASK # .Lmask26 + vpaddq $H4,$D4,$H4 # h4 = d4 + h0*r4 + vpaddq $H0,$D0,$H0 # h0 = d0 + h1*s4 + + ################################################################ + # lazy reduction (interleaved with tail of input splat) + + vpsrlq \$26,$H3,$D3 + vpand $MASK,$H3,$H3 + vpaddq $D3,$H4,$H4 # h3 -> h4 + + vpsrlq \$26,$H0,$D0 + vpand $MASK,$H0,$H0 + vpaddq $D0,$D1,$H1 # h0 -> h1 + + vpsrlq \$26,$H4,$D4 + vpand $MASK,$H4,$H4 + + vpsrlq \$4,$T3,$T2 + + vpsrlq \$26,$H1,$D1 + vpand $MASK,$H1,$H1 + vpaddq $D1,$H2,$H2 # h1 -> h2 + + vpaddq $D4,$H0,$H0 + vpsllq \$2,$D4,$D4 + vpaddq $D4,$H0,$H0 # h4 -> h0 + + vpand $MASK,$T2,$T2 # 2 + vpsrlq \$26,$T0,$T1 + + vpsrlq \$26,$H2,$D2 + vpand $MASK,$H2,$H2 + vpaddq $D2,$H3,$H3 # h2 -> h3 + + vpaddq $T2,$H2,$H2 # modulo-scheduled + vpsrlq \$30,$T3,$T3 + + vpsrlq \$26,$H0,$D0 + vpand $MASK,$H0,$H0 + vpaddq $D0,$H1,$H1 # h0 -> h1 + + vpsrlq \$40,$T4,$T4 # 4 + + vpsrlq \$26,$H3,$D3 + vpand $MASK,$H3,$H3 + vpaddq $D3,$H4,$H4 # h3 -> h4 + + vpand $MASK,$T0,$T0 # 0 + vpand $MASK,$T1,$T1 # 1 + vpand $MASK,$T3,$T3 # 3 + vpor 32(%rcx),$T4,$T4 # padbit, yes, always + + sub \$64,$len + jnz .Loop_avx2 + + .byte 0x66,0x90 +.Ltail_avx2: + ################################################################ + # while above multiplications were by r^4 in all lanes, in last + # iteration we multiply least significant lane by r^4 and most + # significant one by r, so copy of above except that references + # to the precomputed table are displaced by 4... + + #vpaddq $H2,$T2,$H2 # accumulate input + vpaddq $H0,$T0,$H0 + vmovdqu `32*0+4`(%rsp),$T0 # r0^4 + vpaddq $H1,$T1,$H1 + vmovdqu `32*1+4`(%rsp),$T1 # r1^4 + vpaddq $H3,$T3,$H3 + vmovdqu `32*3+4`(%rsp),$T2 # r2^4 + vpaddq $H4,$T4,$H4 + vmovdqu `32*6+4-0x90`(%rax),$T3 # s3^4 + vmovdqu `32*8+4-0x90`(%rax),$S4 # s4^4 + + vpmuludq $H2,$T0,$D2 # d2 = h2*r0 + vpmuludq $H2,$T1,$D3 # d3 = h2*r1 + vpmuludq $H2,$T2,$D4 # d4 = h2*r2 + vpmuludq $H2,$T3,$D0 # d0 = h2*s3 + vpmuludq $H2,$S4,$D1 # d1 = h2*s4 + + vpmuludq $H0,$T1,$T4 # h0*r1 + vpmuludq $H1,$T1,$H2 # h1*r1 + vpaddq $T4,$D1,$D1 # d1 += h0*r1 + vpaddq $H2,$D2,$D2 # d2 += h1*r1 + vpmuludq $H3,$T1,$T4 # h3*r1 + vpmuludq `32*2+4`(%rsp),$H4,$H2 # h4*s1 + vpaddq $T4,$D4,$D4 # d4 += h3*r1 + vpaddq $H2,$D0,$D0 # d0 += h4*s1 + + vpmuludq $H0,$T0,$T4 # h0*r0 + vpmuludq $H1,$T0,$H2 # h1*r0 + vpaddq $T4,$D0,$D0 # d0 += h0*r0 + vmovdqu `32*4+4-0x90`(%rax),$T1 # s2 + vpaddq $H2,$D1,$D1 # d1 += h1*r0 + vpmuludq $H3,$T0,$T4 # h3*r0 + vpmuludq $H4,$T0,$H2 # h4*r0 + vpaddq $T4,$D3,$D3 # d3 += h3*r0 + vpaddq $H2,$D4,$D4 # d4 += h4*r0 + + vpmuludq $H3,$T1,$T4 # h3*s2 + vpmuludq $H4,$T1,$H2 # h4*s2 + vpaddq $T4,$D0,$D0 # d0 += h3*s2 + vpaddq $H2,$D1,$D1 # d1 += h4*s2 + vmovdqu `32*5+4-0x90`(%rax),$H2 # r3 + vpmuludq $H1,$T2,$T4 # h1*r2 + vpmuludq $H0,$T2,$T2 # h0*r2 + vpaddq $T4,$D3,$D3 # d3 += h1*r2 + vpaddq $T2,$D2,$D2 # d2 += h0*r2 + + vpmuludq $H1,$H2,$T4 # h1*r3 + vpmuludq $H0,$H2,$H2 # h0*r3 + vpaddq $T4,$D4,$D4 # d4 += h1*r3 + vpaddq $H2,$D3,$D3 # d3 += h0*r3 + vpmuludq $H3,$T3,$T4 # h3*s3 + vpmuludq $H4,$T3,$H2 # h4*s3 + vpaddq $T4,$D1,$D1 # d1 += h3*s3 + vpaddq $H2,$D2,$D2 # d2 += h4*s3 + + vpmuludq $H3,$S4,$H3 # h3*s4 + vpmuludq $H4,$S4,$H4 # h4*s4 + vpaddq $H3,$D2,$H2 # h2 = d2 + h3*r4 + vpaddq $H4,$D3,$H3 # h3 = d3 + h4*r4 + vpmuludq `32*7+4-0x90`(%rax),$H0,$H4 # h0*r4 + vpmuludq $H1,$S4,$H0 # h1*s4 + vmovdqa 64(%rcx),$MASK # .Lmask26 + vpaddq $H4,$D4,$H4 # h4 = d4 + h0*r4 + vpaddq $H0,$D0,$H0 # h0 = d0 + h1*s4 + + ################################################################ + # horizontal addition + + vpsrldq \$8,$D1,$T1 + vpsrldq \$8,$H2,$T2 + vpsrldq \$8,$H3,$T3 + vpsrldq \$8,$H4,$T4 + vpsrldq \$8,$H0,$T0 + vpaddq $T1,$D1,$D1 + vpaddq $T2,$H2,$H2 + vpaddq $T3,$H3,$H3 + vpaddq $T4,$H4,$H4 + vpaddq $T0,$H0,$H0 + + vpermq \$0x2,$H3,$T3 + vpermq \$0x2,$H4,$T4 + vpermq \$0x2,$H0,$T0 + vpermq \$0x2,$D1,$T1 + vpermq \$0x2,$H2,$T2 + vpaddq $T3,$H3,$H3 + vpaddq $T4,$H4,$H4 + vpaddq $T0,$H0,$H0 + vpaddq $T1,$D1,$D1 + vpaddq $T2,$H2,$H2 + + ################################################################ + # lazy reduction + + vpsrlq \$26,$H3,$D3 + vpand $MASK,$H3,$H3 + vpaddq $D3,$H4,$H4 # h3 -> h4 + + vpsrlq \$26,$H0,$D0 + vpand $MASK,$H0,$H0 + vpaddq $D0,$D1,$H1 # h0 -> h1 + + vpsrlq \$26,$H4,$D4 + vpand $MASK,$H4,$H4 + + vpsrlq \$26,$H1,$D1 + vpand $MASK,$H1,$H1 + vpaddq $D1,$H2,$H2 # h1 -> h2 + + vpaddq $D4,$H0,$H0 + vpsllq \$2,$D4,$D4 + vpaddq $D4,$H0,$H0 # h4 -> h0 + + vpsrlq \$26,$H2,$D2 + vpand $MASK,$H2,$H2 + vpaddq $D2,$H3,$H3 # h2 -> h3 + + vpsrlq \$26,$H0,$D0 + vpand $MASK,$H0,$H0 + vpaddq $D0,$H1,$H1 # h0 -> h1 + + vpsrlq \$26,$H3,$D3 + vpand $MASK,$H3,$H3 + vpaddq $D3,$H4,$H4 # h3 -> h4 + + vmovd %x#$H0,`4*0-48-64`($ctx)# save partially reduced + vmovd %x#$H1,`4*1-48-64`($ctx) + vmovd %x#$H2,`4*2-48-64`($ctx) + vmovd %x#$H3,`4*3-48-64`($ctx) + vmovd %x#$H4,`4*4-48-64`($ctx) +___ +$code.=<<___ if ($win64); + vmovdqa 0x50(%r11),%xmm6 + vmovdqa 0x60(%r11),%xmm7 + vmovdqa 0x70(%r11),%xmm8 + vmovdqa 0x80(%r11),%xmm9 + vmovdqa 0x90(%r11),%xmm10 + vmovdqa 0xa0(%r11),%xmm11 + vmovdqa 0xb0(%r11),%xmm12 + vmovdqa 0xc0(%r11),%xmm13 + vmovdqa 0xd0(%r11),%xmm14 + vmovdqa 0xe0(%r11),%xmm15 + lea 0xf8(%r11),%rsp +.Ldo_avx2_epilogue: +___ +$code.=<<___ if (!$win64); + lea 8(%r11),%rsp +.cfi_def_cfa %rsp,8 +___ +$code.=<<___; + vzeroupper + ret +.cfi_endproc +.size poly1305_blocks_avx2,.-poly1305_blocks_avx2 +___ +####################################################################### +if ($avx>2) { +# On entry we have input length divisible by 64. But since inner loop +# processes 128 bytes per iteration, cases when length is not divisible +# by 128 are handled by passing tail 64 bytes to .Ltail_avx2. For this +# reason stack layout is kept identical to poly1305_blocks_avx2. If not +# for this tail, we wouldn't have to even allocate stack frame... + +my ($R0,$R1,$R2,$R3,$R4, $S1,$S2,$S3,$S4) = map("%zmm$_",(16..24)); +my ($M0,$M1,$M2,$M3,$M4) = map("%zmm$_",(25..29)); +my $PADBIT="%zmm30"; + +map(s/%y/%z/,($T4,$T0,$T1,$T2,$T3)); # switch to %zmm domain +map(s/%y/%z/,($D0,$D1,$D2,$D3,$D4)); +map(s/%y/%z/,($H0,$H1,$H2,$H3,$H4)); +map(s/%y/%z/,($MASK)); + +$code.=<<___; +.type poly1305_blocks_avx512,\@function,4 +.align 32 +poly1305_blocks_avx512: +.cfi_startproc +.Lblocks_avx512: + mov \$15,%eax + kmovw %eax,%k2 +___ +$code.=<<___ if (!$win64); + lea -8(%rsp),%r11 +.cfi_def_cfa %r11,16 + sub \$0x128,%rsp +___ +$code.=<<___ if ($win64); + lea -0xf8(%rsp),%r11 + sub \$0x1c8,%rsp + vmovdqa %xmm6,0x50(%r11) + vmovdqa %xmm7,0x60(%r11) + vmovdqa %xmm8,0x70(%r11) + vmovdqa %xmm9,0x80(%r11) + vmovdqa %xmm10,0x90(%r11) + vmovdqa %xmm11,0xa0(%r11) + vmovdqa %xmm12,0xb0(%r11) + vmovdqa %xmm13,0xc0(%r11) + vmovdqa %xmm14,0xd0(%r11) + vmovdqa %xmm15,0xe0(%r11) +.Ldo_avx512_body: +___ +$code.=<<___; + lea .Lconst(%rip),%rcx + lea 48+64($ctx),$ctx # size optimization + vmovdqa 96(%rcx),%y#$T2 # .Lpermd_avx2 + + # expand pre-calculated table + vmovdqu `16*0-64`($ctx),%x#$D0 # will become expanded ${R0} + and \$-512,%rsp + vmovdqu `16*1-64`($ctx),%x#$D1 # will become ... ${R1} + mov \$0x20,%rax + vmovdqu `16*2-64`($ctx),%x#$T0 # ... ${S1} + vmovdqu `16*3-64`($ctx),%x#$D2 # ... ${R2} + vmovdqu `16*4-64`($ctx),%x#$T1 # ... ${S2} + vmovdqu `16*5-64`($ctx),%x#$D3 # ... ${R3} + vmovdqu `16*6-64`($ctx),%x#$T3 # ... ${S3} + vmovdqu `16*7-64`($ctx),%x#$D4 # ... ${R4} + vmovdqu `16*8-64`($ctx),%x#$T4 # ... ${S4} + vpermd $D0,$T2,$R0 # 00003412 -> 14243444 + vpbroadcastq 64(%rcx),$MASK # .Lmask26 + vpermd $D1,$T2,$R1 + vpermd $T0,$T2,$S1 + vpermd $D2,$T2,$R2 + vmovdqa64 $R0,0x00(%rsp){%k2} # save in case $len%128 != 0 + vpsrlq \$32,$R0,$T0 # 14243444 -> 01020304 + vpermd $T1,$T2,$S2 + vmovdqu64 $R1,0x00(%rsp,%rax){%k2} + vpsrlq \$32,$R1,$T1 + vpermd $D3,$T2,$R3 + vmovdqa64 $S1,0x40(%rsp){%k2} + vpermd $T3,$T2,$S3 + vpermd $D4,$T2,$R4 + vmovdqu64 $R2,0x40(%rsp,%rax){%k2} + vpermd $T4,$T2,$S4 + vmovdqa64 $S2,0x80(%rsp){%k2} + vmovdqu64 $R3,0x80(%rsp,%rax){%k2} + vmovdqa64 $S3,0xc0(%rsp){%k2} + vmovdqu64 $R4,0xc0(%rsp,%rax){%k2} + vmovdqa64 $S4,0x100(%rsp){%k2} + + ################################################################ + # calculate 5th through 8th powers of the key + # + # d0 = r0'*r0 + r1'*5*r4 + r2'*5*r3 + r3'*5*r2 + r4'*5*r1 + # d1 = r0'*r1 + r1'*r0 + r2'*5*r4 + r3'*5*r3 + r4'*5*r2 + # d2 = r0'*r2 + r1'*r1 + r2'*r0 + r3'*5*r4 + r4'*5*r3 + # d3 = r0'*r3 + r1'*r2 + r2'*r1 + r3'*r0 + r4'*5*r4 + # d4 = r0'*r4 + r1'*r3 + r2'*r2 + r3'*r1 + r4'*r0 + + vpmuludq $T0,$R0,$D0 # d0 = r0'*r0 + vpmuludq $T0,$R1,$D1 # d1 = r0'*r1 + vpmuludq $T0,$R2,$D2 # d2 = r0'*r2 + vpmuludq $T0,$R3,$D3 # d3 = r0'*r3 + vpmuludq $T0,$R4,$D4 # d4 = r0'*r4 + vpsrlq \$32,$R2,$T2 + + vpmuludq $T1,$S4,$M0 + vpmuludq $T1,$R0,$M1 + vpmuludq $T1,$R1,$M2 + vpmuludq $T1,$R2,$M3 + vpmuludq $T1,$R3,$M4 + vpsrlq \$32,$R3,$T3 + vpaddq $M0,$D0,$D0 # d0 += r1'*5*r4 + vpaddq $M1,$D1,$D1 # d1 += r1'*r0 + vpaddq $M2,$D2,$D2 # d2 += r1'*r1 + vpaddq $M3,$D3,$D3 # d3 += r1'*r2 + vpaddq $M4,$D4,$D4 # d4 += r1'*r3 + + vpmuludq $T2,$S3,$M0 + vpmuludq $T2,$S4,$M1 + vpmuludq $T2,$R1,$M3 + vpmuludq $T2,$R2,$M4 + vpmuludq $T2,$R0,$M2 + vpsrlq \$32,$R4,$T4 + vpaddq $M0,$D0,$D0 # d0 += r2'*5*r3 + vpaddq $M1,$D1,$D1 # d1 += r2'*5*r4 + vpaddq $M3,$D3,$D3 # d3 += r2'*r1 + vpaddq $M4,$D4,$D4 # d4 += r2'*r2 + vpaddq $M2,$D2,$D2 # d2 += r2'*r0 + + vpmuludq $T3,$S2,$M0 + vpmuludq $T3,$R0,$M3 + vpmuludq $T3,$R1,$M4 + vpmuludq $T3,$S3,$M1 + vpmuludq $T3,$S4,$M2 + vpaddq $M0,$D0,$D0 # d0 += r3'*5*r2 + vpaddq $M3,$D3,$D3 # d3 += r3'*r0 + vpaddq $M4,$D4,$D4 # d4 += r3'*r1 + vpaddq $M1,$D1,$D1 # d1 += r3'*5*r3 + vpaddq $M2,$D2,$D2 # d2 += r3'*5*r4 + + vpmuludq $T4,$S4,$M3 + vpmuludq $T4,$R0,$M4 + vpmuludq $T4,$S1,$M0 + vpmuludq $T4,$S2,$M1 + vpmuludq $T4,$S3,$M2 + vpaddq $M3,$D3,$D3 # d3 += r2'*5*r4 + vpaddq $M4,$D4,$D4 # d4 += r2'*r0 + vpaddq $M0,$D0,$D0 # d0 += r2'*5*r1 + vpaddq $M1,$D1,$D1 # d1 += r2'*5*r2 + vpaddq $M2,$D2,$D2 # d2 += r2'*5*r3 + + ################################################################ + # load input + vmovdqu64 16*0($inp),%z#$T3 + vmovdqu64 16*4($inp),%z#$T4 + lea 16*8($inp),$inp + + ################################################################ + # lazy reduction + + vpsrlq \$26,$D3,$M3 + vpandq $MASK,$D3,$D3 + vpaddq $M3,$D4,$D4 # d3 -> d4 + + vpsrlq \$26,$D0,$M0 + vpandq $MASK,$D0,$D0 + vpaddq $M0,$D1,$D1 # d0 -> d1 + + vpsrlq \$26,$D4,$M4 + vpandq $MASK,$D4,$D4 + + vpsrlq \$26,$D1,$M1 + vpandq $MASK,$D1,$D1 + vpaddq $M1,$D2,$D2 # d1 -> d2 + + vpaddq $M4,$D0,$D0 + vpsllq \$2,$M4,$M4 + vpaddq $M4,$D0,$D0 # d4 -> d0 + + vpsrlq \$26,$D2,$M2 + vpandq $MASK,$D2,$D2 + vpaddq $M2,$D3,$D3 # d2 -> d3 + + vpsrlq \$26,$D0,$M0 + vpandq $MASK,$D0,$D0 + vpaddq $M0,$D1,$D1 # d0 -> d1 + + vpsrlq \$26,$D3,$M3 + vpandq $MASK,$D3,$D3 + vpaddq $M3,$D4,$D4 # d3 -> d4 + + ################################################################ + # at this point we have 14243444 in $R0-$S4 and 05060708 in + # $D0-$D4, ... + + vpunpcklqdq $T4,$T3,$T0 # transpose input + vpunpckhqdq $T4,$T3,$T4 + + # ... since input 64-bit lanes are ordered as 73625140, we could + # "vperm" it to 76543210 (here and in each loop iteration), *or* + # we could just flow along, hence the goal for $R0-$S4 is + # 1858286838784888 ... + + vmovdqa32 128(%rcx),$M0 # .Lpermd_avx512: + mov \$0x7777,%eax + kmovw %eax,%k1 + + vpermd $R0,$M0,$R0 # 14243444 -> 1---2---3---4--- + vpermd $R1,$M0,$R1 + vpermd $R2,$M0,$R2 + vpermd $R3,$M0,$R3 + vpermd $R4,$M0,$R4 + + vpermd $D0,$M0,${R0}{%k1} # 05060708 -> 1858286838784888 + vpermd $D1,$M0,${R1}{%k1} + vpermd $D2,$M0,${R2}{%k1} + vpermd $D3,$M0,${R3}{%k1} + vpermd $D4,$M0,${R4}{%k1} + + vpslld \$2,$R1,$S1 # *5 + vpslld \$2,$R2,$S2 + vpslld \$2,$R3,$S3 + vpslld \$2,$R4,$S4 + vpaddd $R1,$S1,$S1 + vpaddd $R2,$S2,$S2 + vpaddd $R3,$S3,$S3 + vpaddd $R4,$S4,$S4 + + vpbroadcastq 32(%rcx),$PADBIT # .L129 + + vpsrlq \$52,$T0,$T2 # splat input + vpsllq \$12,$T4,$T3 + vporq $T3,$T2,$T2 + vpsrlq \$26,$T0,$T1 + vpsrlq \$14,$T4,$T3 + vpsrlq \$40,$T4,$T4 # 4 + vpandq $MASK,$T2,$T2 # 2 + vpandq $MASK,$T0,$T0 # 0 + #vpandq $MASK,$T1,$T1 # 1 + #vpandq $MASK,$T3,$T3 # 3 + #vporq $PADBIT,$T4,$T4 # padbit, yes, always + + vpaddq $H2,$T2,$H2 # accumulate input + sub \$192,$len + jbe .Ltail_avx512 + jmp .Loop_avx512 + +.align 32 +.Loop_avx512: + ################################################################ + # ((inp[0]*r^8+inp[ 8])*r^8+inp[16])*r^8 + # ((inp[1]*r^8+inp[ 9])*r^8+inp[17])*r^7 + # ((inp[2]*r^8+inp[10])*r^8+inp[18])*r^6 + # ((inp[3]*r^8+inp[11])*r^8+inp[19])*r^5 + # ((inp[4]*r^8+inp[12])*r^8+inp[20])*r^4 + # ((inp[5]*r^8+inp[13])*r^8+inp[21])*r^3 + # ((inp[6]*r^8+inp[14])*r^8+inp[22])*r^2 + # ((inp[7]*r^8+inp[15])*r^8+inp[23])*r^1 + # \________/\___________/ + ################################################################ + #vpaddq $H2,$T2,$H2 # accumulate input + + # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 + # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 + # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 + # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 + # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 + # + # however, as h2 is "chronologically" first one available pull + # corresponding operations up, so it's + # + # d3 = h2*r1 + h0*r3 + h1*r2 + h3*r0 + h4*5*r4 + # d4 = h2*r2 + h0*r4 + h1*r3 + h3*r1 + h4*r0 + # d0 = h2*5*r3 + h0*r0 + h1*5*r4 + h3*5*r2 + h4*5*r1 + # d1 = h2*5*r4 + h0*r1 + h1*r0 + h3*5*r3 + h4*5*r2 + # d2 = h2*r0 + h0*r2 + h1*r1 + h3*5*r4 + h4*5*r3 + + vpmuludq $H2,$R1,$D3 # d3 = h2*r1 + vpaddq $H0,$T0,$H0 + vpmuludq $H2,$R2,$D4 # d4 = h2*r2 + vpandq $MASK,$T1,$T1 # 1 + vpmuludq $H2,$S3,$D0 # d0 = h2*s3 + vpandq $MASK,$T3,$T3 # 3 + vpmuludq $H2,$S4,$D1 # d1 = h2*s4 + vporq $PADBIT,$T4,$T4 # padbit, yes, always + vpmuludq $H2,$R0,$D2 # d2 = h2*r0 + vpaddq $H1,$T1,$H1 # accumulate input + vpaddq $H3,$T3,$H3 + vpaddq $H4,$T4,$H4 + + vmovdqu64 16*0($inp),$T3 # load input + vmovdqu64 16*4($inp),$T4 + lea 16*8($inp),$inp + vpmuludq $H0,$R3,$M3 + vpmuludq $H0,$R4,$M4 + vpmuludq $H0,$R0,$M0 + vpmuludq $H0,$R1,$M1 + vpaddq $M3,$D3,$D3 # d3 += h0*r3 + vpaddq $M4,$D4,$D4 # d4 += h0*r4 + vpaddq $M0,$D0,$D0 # d0 += h0*r0 + vpaddq $M1,$D1,$D1 # d1 += h0*r1 + + vpmuludq $H1,$R2,$M3 + vpmuludq $H1,$R3,$M4 + vpmuludq $H1,$S4,$M0 + vpmuludq $H0,$R2,$M2 + vpaddq $M3,$D3,$D3 # d3 += h1*r2 + vpaddq $M4,$D4,$D4 # d4 += h1*r3 + vpaddq $M0,$D0,$D0 # d0 += h1*s4 + vpaddq $M2,$D2,$D2 # d2 += h0*r2 + + vpunpcklqdq $T4,$T3,$T0 # transpose input + vpunpckhqdq $T4,$T3,$T4 + + vpmuludq $H3,$R0,$M3 + vpmuludq $H3,$R1,$M4 + vpmuludq $H1,$R0,$M1 + vpmuludq $H1,$R1,$M2 + vpaddq $M3,$D3,$D3 # d3 += h3*r0 + vpaddq $M4,$D4,$D4 # d4 += h3*r1 + vpaddq $M1,$D1,$D1 # d1 += h1*r0 + vpaddq $M2,$D2,$D2 # d2 += h1*r1 + + vpmuludq $H4,$S4,$M3 + vpmuludq $H4,$R0,$M4 + vpmuludq $H3,$S2,$M0 + vpmuludq $H3,$S3,$M1 + vpaddq $M3,$D3,$D3 # d3 += h4*s4 + vpmuludq $H3,$S4,$M2 + vpaddq $M4,$D4,$D4 # d4 += h4*r0 + vpaddq $M0,$D0,$D0 # d0 += h3*s2 + vpaddq $M1,$D1,$D1 # d1 += h3*s3 + vpaddq $M2,$D2,$D2 # d2 += h3*s4 + + vpmuludq $H4,$S1,$M0 + vpmuludq $H4,$S2,$M1 + vpmuludq $H4,$S3,$M2 + vpaddq $M0,$D0,$H0 # h0 = d0 + h4*s1 + vpaddq $M1,$D1,$H1 # h1 = d2 + h4*s2 + vpaddq $M2,$D2,$H2 # h2 = d3 + h4*s3 + + ################################################################ + # lazy reduction (interleaved with input splat) + + vpsrlq \$52,$T0,$T2 # splat input + vpsllq \$12,$T4,$T3 + + vpsrlq \$26,$D3,$H3 + vpandq $MASK,$D3,$D3 + vpaddq $H3,$D4,$H4 # h3 -> h4 + + vporq $T3,$T2,$T2 + + vpsrlq \$26,$H0,$D0 + vpandq $MASK,$H0,$H0 + vpaddq $D0,$H1,$H1 # h0 -> h1 + + vpandq $MASK,$T2,$T2 # 2 + + vpsrlq \$26,$H4,$D4 + vpandq $MASK,$H4,$H4 + + vpsrlq \$26,$H1,$D1 + vpandq $MASK,$H1,$H1 + vpaddq $D1,$H2,$H2 # h1 -> h2 + + vpaddq $D4,$H0,$H0 + vpsllq \$2,$D4,$D4 + vpaddq $D4,$H0,$H0 # h4 -> h0 + + vpaddq $T2,$H2,$H2 # modulo-scheduled + vpsrlq \$26,$T0,$T1 + + vpsrlq \$26,$H2,$D2 + vpandq $MASK,$H2,$H2 + vpaddq $D2,$D3,$H3 # h2 -> h3 + + vpsrlq \$14,$T4,$T3 + + vpsrlq \$26,$H0,$D0 + vpandq $MASK,$H0,$H0 + vpaddq $D0,$H1,$H1 # h0 -> h1 + + vpsrlq \$40,$T4,$T4 # 4 + + vpsrlq \$26,$H3,$D3 + vpandq $MASK,$H3,$H3 + vpaddq $D3,$H4,$H4 # h3 -> h4 + + vpandq $MASK,$T0,$T0 # 0 + #vpandq $MASK,$T1,$T1 # 1 + #vpandq $MASK,$T3,$T3 # 3 + #vporq $PADBIT,$T4,$T4 # padbit, yes, always + + sub \$128,$len + ja .Loop_avx512 + +.Ltail_avx512: + ################################################################ + # while above multiplications were by r^8 in all lanes, in last + # iteration we multiply least significant lane by r^8 and most + # significant one by r, that's why table gets shifted... + + vpsrlq \$32,$R0,$R0 # 0105020603070408 + vpsrlq \$32,$R1,$R1 + vpsrlq \$32,$R2,$R2 + vpsrlq \$32,$S3,$S3 + vpsrlq \$32,$S4,$S4 + vpsrlq \$32,$R3,$R3 + vpsrlq \$32,$R4,$R4 + vpsrlq \$32,$S1,$S1 + vpsrlq \$32,$S2,$S2 + + ################################################################ + # load either next or last 64 byte of input + lea ($inp,$len),$inp + + #vpaddq $H2,$T2,$H2 # accumulate input + vpaddq $H0,$T0,$H0 + + vpmuludq $H2,$R1,$D3 # d3 = h2*r1 + vpmuludq $H2,$R2,$D4 # d4 = h2*r2 + vpmuludq $H2,$S3,$D0 # d0 = h2*s3 + vpandq $MASK,$T1,$T1 # 1 + vpmuludq $H2,$S4,$D1 # d1 = h2*s4 + vpandq $MASK,$T3,$T3 # 3 + vpmuludq $H2,$R0,$D2 # d2 = h2*r0 + vporq $PADBIT,$T4,$T4 # padbit, yes, always + vpaddq $H1,$T1,$H1 # accumulate input + vpaddq $H3,$T3,$H3 + vpaddq $H4,$T4,$H4 + + vmovdqu 16*0($inp),%x#$T0 + vpmuludq $H0,$R3,$M3 + vpmuludq $H0,$R4,$M4 + vpmuludq $H0,$R0,$M0 + vpmuludq $H0,$R1,$M1 + vpaddq $M3,$D3,$D3 # d3 += h0*r3 + vpaddq $M4,$D4,$D4 # d4 += h0*r4 + vpaddq $M0,$D0,$D0 # d0 += h0*r0 + vpaddq $M1,$D1,$D1 # d1 += h0*r1 + + vmovdqu 16*1($inp),%x#$T1 + vpmuludq $H1,$R2,$M3 + vpmuludq $H1,$R3,$M4 + vpmuludq $H1,$S4,$M0 + vpmuludq $H0,$R2,$M2 + vpaddq $M3,$D3,$D3 # d3 += h1*r2 + vpaddq $M4,$D4,$D4 # d4 += h1*r3 + vpaddq $M0,$D0,$D0 # d0 += h1*s4 + vpaddq $M2,$D2,$D2 # d2 += h0*r2 + + vinserti128 \$1,16*2($inp),%y#$T0,%y#$T0 + vpmuludq $H3,$R0,$M3 + vpmuludq $H3,$R1,$M4 + vpmuludq $H1,$R0,$M1 + vpmuludq $H1,$R1,$M2 + vpaddq $M3,$D3,$D3 # d3 += h3*r0 + vpaddq $M4,$D4,$D4 # d4 += h3*r1 + vpaddq $M1,$D1,$D1 # d1 += h1*r0 + vpaddq $M2,$D2,$D2 # d2 += h1*r1 + + vinserti128 \$1,16*3($inp),%y#$T1,%y#$T1 + vpmuludq $H4,$S4,$M3 + vpmuludq $H4,$R0,$M4 + vpmuludq $H3,$S2,$M0 + vpmuludq $H3,$S3,$M1 + vpmuludq $H3,$S4,$M2 + vpaddq $M3,$D3,$H3 # h3 = d3 + h4*s4 + vpaddq $M4,$D4,$D4 # d4 += h4*r0 + vpaddq $M0,$D0,$D0 # d0 += h3*s2 + vpaddq $M1,$D1,$D1 # d1 += h3*s3 + vpaddq $M2,$D2,$D2 # d2 += h3*s4 + + vpmuludq $H4,$S1,$M0 + vpmuludq $H4,$S2,$M1 + vpmuludq $H4,$S3,$M2 + vpaddq $M0,$D0,$H0 # h0 = d0 + h4*s1 + vpaddq $M1,$D1,$H1 # h1 = d2 + h4*s2 + vpaddq $M2,$D2,$H2 # h2 = d3 + h4*s3 + + ################################################################ + # horizontal addition + + mov \$1,%eax + vpermq \$0xb1,$H3,$D3 + vpermq \$0xb1,$D4,$H4 + vpermq \$0xb1,$H0,$D0 + vpermq \$0xb1,$H1,$D1 + vpermq \$0xb1,$H2,$D2 + vpaddq $D3,$H3,$H3 + vpaddq $D4,$H4,$H4 + vpaddq $D0,$H0,$H0 + vpaddq $D1,$H1,$H1 + vpaddq $D2,$H2,$H2 + + kmovw %eax,%k3 + vpermq \$0x2,$H3,$D3 + vpermq \$0x2,$H4,$D4 + vpermq \$0x2,$H0,$D0 + vpermq \$0x2,$H1,$D1 + vpermq \$0x2,$H2,$D2 + vpaddq $D3,$H3,$H3 + vpaddq $D4,$H4,$H4 + vpaddq $D0,$H0,$H0 + vpaddq $D1,$H1,$H1 + vpaddq $D2,$H2,$H2 + + vextracti64x4 \$0x1,$H3,%y#$D3 + vextracti64x4 \$0x1,$H4,%y#$D4 + vextracti64x4 \$0x1,$H0,%y#$D0 + vextracti64x4 \$0x1,$H1,%y#$D1 + vextracti64x4 \$0x1,$H2,%y#$D2 + vpaddq $D3,$H3,${H3}{%k3}{z} # keep single qword in case + vpaddq $D4,$H4,${H4}{%k3}{z} # it's passed to .Ltail_avx2 + vpaddq $D0,$H0,${H0}{%k3}{z} + vpaddq $D1,$H1,${H1}{%k3}{z} + vpaddq $D2,$H2,${H2}{%k3}{z} +___ +map(s/%z/%y/,($T0,$T1,$T2,$T3,$T4, $PADBIT)); +map(s/%z/%y/,($H0,$H1,$H2,$H3,$H4, $D0,$D1,$D2,$D3,$D4, $MASK)); +$code.=<<___; + ################################################################ + # lazy reduction (interleaved with input splat) + + vpsrlq \$26,$H3,$D3 + vpand $MASK,$H3,$H3 + vpsrldq \$6,$T0,$T2 # splat input + vpsrldq \$6,$T1,$T3 + vpunpckhqdq $T1,$T0,$T4 # 4 + vpaddq $D3,$H4,$H4 # h3 -> h4 + + vpsrlq \$26,$H0,$D0 + vpand $MASK,$H0,$H0 + vpunpcklqdq $T3,$T2,$T2 # 2:3 + vpunpcklqdq $T1,$T0,$T0 # 0:1 + vpaddq $D0,$H1,$H1 # h0 -> h1 + + vpsrlq \$26,$H4,$D4 + vpand $MASK,$H4,$H4 + + vpsrlq \$26,$H1,$D1 + vpand $MASK,$H1,$H1 + vpsrlq \$30,$T2,$T3 + vpsrlq \$4,$T2,$T2 + vpaddq $D1,$H2,$H2 # h1 -> h2 + + vpaddq $D4,$H0,$H0 + vpsllq \$2,$D4,$D4 + vpsrlq \$26,$T0,$T1 + vpsrlq \$40,$T4,$T4 # 4 + vpaddq $D4,$H0,$H0 # h4 -> h0 + + vpsrlq \$26,$H2,$D2 + vpand $MASK,$H2,$H2 + vpand $MASK,$T2,$T2 # 2 + vpand $MASK,$T0,$T0 # 0 + vpaddq $D2,$H3,$H3 # h2 -> h3 + + vpsrlq \$26,$H0,$D0 + vpand $MASK,$H0,$H0 + vpaddq $H2,$T2,$H2 # accumulate input for .Ltail_avx2 + vpand $MASK,$T1,$T1 # 1 + vpaddq $D0,$H1,$H1 # h0 -> h1 + + vpsrlq \$26,$H3,$D3 + vpand $MASK,$H3,$H3 + vpand $MASK,$T3,$T3 # 3 + vpor 32(%rcx),$T4,$T4 # padbit, yes, always + vpaddq $D3,$H4,$H4 # h3 -> h4 + + lea 0x90(%rsp),%rax # size optimization for .Ltail_avx2 + add \$64,$len + jnz .Ltail_avx2 + + vpsubq $T2,$H2,$H2 # undo input accumulation + vmovd %x#$H0,`4*0-48-64`($ctx)# save partially reduced + vmovd %x#$H1,`4*1-48-64`($ctx) + vmovd %x#$H2,`4*2-48-64`($ctx) + vmovd %x#$H3,`4*3-48-64`($ctx) + vmovd %x#$H4,`4*4-48-64`($ctx) + vzeroall +___ +$code.=<<___ if ($win64); + movdqa 0x50(%r11),%xmm6 + movdqa 0x60(%r11),%xmm7 + movdqa 0x70(%r11),%xmm8 + movdqa 0x80(%r11),%xmm9 + movdqa 0x90(%r11),%xmm10 + movdqa 0xa0(%r11),%xmm11 + movdqa 0xb0(%r11),%xmm12 + movdqa 0xc0(%r11),%xmm13 + movdqa 0xd0(%r11),%xmm14 + movdqa 0xe0(%r11),%xmm15 + lea 0xf8(%r11),%rsp +.Ldo_avx512_epilogue: +___ +$code.=<<___ if (!$win64); + lea 8(%r11),%rsp +.cfi_def_cfa %rsp,8 +___ +$code.=<<___; + ret +.cfi_endproc +.size poly1305_blocks_avx512,.-poly1305_blocks_avx512 +___ +if ($avx>3) { +######################################################################## +# VPMADD52 version using 2^44 radix. +# +# One can argue that base 2^52 would be more natural. Well, even though +# some operations would be more natural, one has to recognize couple of +# things. Base 2^52 doesn't provide advantage over base 2^44 if you look +# at amount of multiply-n-accumulate operations. Secondly, it makes it +# impossible to pre-compute multiples of 5 [referred to as s[]/sN in +# reference implementations], which means that more such operations +# would have to be performed in inner loop, which in turn makes critical +# path longer. In other words, even though base 2^44 reduction might +# look less elegant, overall critical path is actually shorter... + +######################################################################## +# Layout of opaque area is following. +# +# unsigned __int64 h[3]; # current hash value base 2^44 +# unsigned __int64 s[2]; # key value*20 base 2^44 +# unsigned __int64 r[3]; # key value base 2^44 +# struct { unsigned __int64 r^1, r^3, r^2, r^4; } R[4]; +# # r^n positions reflect +# # placement in register, not +# # memory, R[3] is R[1]*20 + +$code.=<<___; +.type poly1305_init_base2_44,\@function,3 +.align 32 +poly1305_init_base2_44: + xor %rax,%rax + mov %rax,0($ctx) # initialize hash value + mov %rax,8($ctx) + mov %rax,16($ctx) + +.Linit_base2_44: + lea poly1305_blocks_vpmadd52(%rip),%r10 + lea poly1305_emit_base2_44(%rip),%r11 + + mov \$0x0ffffffc0fffffff,%rax + mov \$0x0ffffffc0ffffffc,%rcx + and 0($inp),%rax + mov \$0x00000fffffffffff,%r8 + and 8($inp),%rcx + mov \$0x00000fffffffffff,%r9 + and %rax,%r8 + shrd \$44,%rcx,%rax + mov %r8,40($ctx) # r0 + and %r9,%rax + shr \$24,%rcx + mov %rax,48($ctx) # r1 + lea (%rax,%rax,4),%rax # *5 + mov %rcx,56($ctx) # r2 + shl \$2,%rax # magic <<2 + lea (%rcx,%rcx,4),%rcx # *5 + shl \$2,%rcx # magic <<2 + mov %rax,24($ctx) # s1 + mov %rcx,32($ctx) # s2 + movq \$-1,64($ctx) # write impossible value +___ +$code.=<<___ if ($flavour !~ /elf32/); + mov %r10,0(%rdx) + mov %r11,8(%rdx) +___ +$code.=<<___ if ($flavour =~ /elf32/); + mov %r10d,0(%rdx) + mov %r11d,4(%rdx) +___ +$code.=<<___; + mov \$1,%eax + ret +.size poly1305_init_base2_44,.-poly1305_init_base2_44 +___ +{ +my ($H0,$H1,$H2,$r2r1r0,$r1r0s2,$r0s2s1,$Dlo,$Dhi) = map("%ymm$_",(0..5,16,17)); +my ($T0,$inp_permd,$inp_shift,$PAD) = map("%ymm$_",(18..21)); +my ($reduc_mask,$reduc_rght,$reduc_left) = map("%ymm$_",(22..25)); + +$code.=<<___; +.type poly1305_blocks_vpmadd52,\@function,4 +.align 32 +poly1305_blocks_vpmadd52: + shr \$4,$len + jz .Lno_data_vpmadd52 # too short + + shl \$40,$padbit + mov 64($ctx),%r8 # peek on power of the key + + # if powers of the key are not calculated yet, process up to 3 + # blocks with this single-block subroutine, otherwise ensure that + # length is divisible by 2 blocks and pass the rest down to next + # subroutine... + + mov \$3,%rax + mov \$1,%r10 + cmp \$4,$len # is input long + cmovae %r10,%rax + test %r8,%r8 # is power value impossible? + cmovns %r10,%rax + + and $len,%rax # is input of favourable length? + jz .Lblocks_vpmadd52_4x + + sub %rax,$len + mov \$7,%r10d + mov \$1,%r11d + kmovw %r10d,%k7 + lea .L2_44_inp_permd(%rip),%r10 + kmovw %r11d,%k1 + + vmovq $padbit,%x#$PAD + vmovdqa64 0(%r10),$inp_permd # .L2_44_inp_permd + vmovdqa64 32(%r10),$inp_shift # .L2_44_inp_shift + vpermq \$0xcf,$PAD,$PAD + vmovdqa64 64(%r10),$reduc_mask # .L2_44_mask + + vmovdqu64 0($ctx),${Dlo}{%k7}{z} # load hash value + vmovdqu64 40($ctx),${r2r1r0}{%k7}{z} # load keys + vmovdqu64 32($ctx),${r1r0s2}{%k7}{z} + vmovdqu64 24($ctx),${r0s2s1}{%k7}{z} + + vmovdqa64 96(%r10),$reduc_rght # .L2_44_shift_rgt + vmovdqa64 128(%r10),$reduc_left # .L2_44_shift_lft + + jmp .Loop_vpmadd52 + +.align 32 +.Loop_vpmadd52: + vmovdqu32 0($inp),%x#$T0 # load input as ----3210 + lea 16($inp),$inp + + vpermd $T0,$inp_permd,$T0 # ----3210 -> --322110 + vpsrlvq $inp_shift,$T0,$T0 + vpandq $reduc_mask,$T0,$T0 + vporq $PAD,$T0,$T0 + + vpaddq $T0,$Dlo,$Dlo # accumulate input + + vpermq \$0,$Dlo,${H0}{%k7}{z} # smash hash value + vpermq \$0b01010101,$Dlo,${H1}{%k7}{z} + vpermq \$0b10101010,$Dlo,${H2}{%k7}{z} + + vpxord $Dlo,$Dlo,$Dlo + vpxord $Dhi,$Dhi,$Dhi + + vpmadd52luq $r2r1r0,$H0,$Dlo + vpmadd52huq $r2r1r0,$H0,$Dhi + + vpmadd52luq $r1r0s2,$H1,$Dlo + vpmadd52huq $r1r0s2,$H1,$Dhi + + vpmadd52luq $r0s2s1,$H2,$Dlo + vpmadd52huq $r0s2s1,$H2,$Dhi + + vpsrlvq $reduc_rght,$Dlo,$T0 # 0 in topmost qword + vpsllvq $reduc_left,$Dhi,$Dhi # 0 in topmost qword + vpandq $reduc_mask,$Dlo,$Dlo + + vpaddq $T0,$Dhi,$Dhi + + vpermq \$0b10010011,$Dhi,$Dhi # 0 in lowest qword + + vpaddq $Dhi,$Dlo,$Dlo # note topmost qword :-) + + vpsrlvq $reduc_rght,$Dlo,$T0 # 0 in topmost word + vpandq $reduc_mask,$Dlo,$Dlo + + vpermq \$0b10010011,$T0,$T0 + + vpaddq $T0,$Dlo,$Dlo + + vpermq \$0b10010011,$Dlo,${T0}{%k1}{z} + + vpaddq $T0,$Dlo,$Dlo + vpsllq \$2,$T0,$T0 + + vpaddq $T0,$Dlo,$Dlo + + dec %rax # len-=16 + jnz .Loop_vpmadd52 + + vmovdqu64 $Dlo,0($ctx){%k7} # store hash value + + test $len,$len + jnz .Lblocks_vpmadd52_4x + +.Lno_data_vpmadd52: + ret +.size poly1305_blocks_vpmadd52,.-poly1305_blocks_vpmadd52 +___ +} +{ +######################################################################## +# As implied by its name 4x subroutine processes 4 blocks in parallel +# (but handles even 4*n+2 blocks lengths). It takes up to 4th key power +# and is handled in 256-bit %ymm registers. + +my ($H0,$H1,$H2,$R0,$R1,$R2,$S1,$S2) = map("%ymm$_",(0..5,16,17)); +my ($D0lo,$D0hi,$D1lo,$D1hi,$D2lo,$D2hi) = map("%ymm$_",(18..23)); +my ($T0,$T1,$T2,$T3,$mask44,$mask42,$tmp,$PAD) = map("%ymm$_",(24..31)); + +$code.=<<___; +.type poly1305_blocks_vpmadd52_4x,\@function,4 +.align 32 +poly1305_blocks_vpmadd52_4x: + shr \$4,$len + jz .Lno_data_vpmadd52_4x # too short + + shl \$40,$padbit + mov 64($ctx),%r8 # peek on power of the key + +.Lblocks_vpmadd52_4x: + vpbroadcastq $padbit,$PAD + + vmovdqa64 .Lx_mask44(%rip),$mask44 + mov \$5,%eax + vmovdqa64 .Lx_mask42(%rip),$mask42 + kmovw %eax,%k1 # used in 2x path + + test %r8,%r8 # is power value impossible? + js .Linit_vpmadd52 # if it is, then init R[4] + + vmovq 0($ctx),%x#$H0 # load current hash value + vmovq 8($ctx),%x#$H1 + vmovq 16($ctx),%x#$H2 + + test \$3,$len # is length 4*n+2? + jnz .Lblocks_vpmadd52_2x_do + +.Lblocks_vpmadd52_4x_do: + vpbroadcastq 64($ctx),$R0 # load 4th power of the key + vpbroadcastq 96($ctx),$R1 + vpbroadcastq 128($ctx),$R2 + vpbroadcastq 160($ctx),$S1 + +.Lblocks_vpmadd52_4x_key_loaded: + vpsllq \$2,$R2,$S2 # S2 = R2*5*4 + vpaddq $R2,$S2,$S2 + vpsllq \$2,$S2,$S2 + + test \$7,$len # is len 8*n? + jz .Lblocks_vpmadd52_8x + + vmovdqu64 16*0($inp),$T2 # load data + vmovdqu64 16*2($inp),$T3 + lea 16*4($inp),$inp + + vpunpcklqdq $T3,$T2,$T1 # transpose data + vpunpckhqdq $T3,$T2,$T3 + + # at this point 64-bit lanes are ordered as 3-1-2-0 + + vpsrlq \$24,$T3,$T2 # splat the data + vporq $PAD,$T2,$T2 + vpaddq $T2,$H2,$H2 # accumulate input + vpandq $mask44,$T1,$T0 + vpsrlq \$44,$T1,$T1 + vpsllq \$20,$T3,$T3 + vporq $T3,$T1,$T1 + vpandq $mask44,$T1,$T1 + + sub \$4,$len + jz .Ltail_vpmadd52_4x + jmp .Loop_vpmadd52_4x + ud2 + +.align 32 +.Linit_vpmadd52: + vmovq 24($ctx),%x#$S1 # load key + vmovq 56($ctx),%x#$H2 + vmovq 32($ctx),%x#$S2 + vmovq 40($ctx),%x#$R0 + vmovq 48($ctx),%x#$R1 + + vmovdqa $R0,$H0 + vmovdqa $R1,$H1 + vmovdqa $H2,$R2 + + mov \$2,%eax + +.Lmul_init_vpmadd52: + vpxorq $D0lo,$D0lo,$D0lo + vpmadd52luq $H2,$S1,$D0lo + vpxorq $D0hi,$D0hi,$D0hi + vpmadd52huq $H2,$S1,$D0hi + vpxorq $D1lo,$D1lo,$D1lo + vpmadd52luq $H2,$S2,$D1lo + vpxorq $D1hi,$D1hi,$D1hi + vpmadd52huq $H2,$S2,$D1hi + vpxorq $D2lo,$D2lo,$D2lo + vpmadd52luq $H2,$R0,$D2lo + vpxorq $D2hi,$D2hi,$D2hi + vpmadd52huq $H2,$R0,$D2hi + + vpmadd52luq $H0,$R0,$D0lo + vpmadd52huq $H0,$R0,$D0hi + vpmadd52luq $H0,$R1,$D1lo + vpmadd52huq $H0,$R1,$D1hi + vpmadd52luq $H0,$R2,$D2lo + vpmadd52huq $H0,$R2,$D2hi + + vpmadd52luq $H1,$S2,$D0lo + vpmadd52huq $H1,$S2,$D0hi + vpmadd52luq $H1,$R0,$D1lo + vpmadd52huq $H1,$R0,$D1hi + vpmadd52luq $H1,$R1,$D2lo + vpmadd52huq $H1,$R1,$D2hi + + ################################################################ + # partial reduction + vpsrlq \$44,$D0lo,$tmp + vpsllq \$8,$D0hi,$D0hi + vpandq $mask44,$D0lo,$H0 + vpaddq $tmp,$D0hi,$D0hi + + vpaddq $D0hi,$D1lo,$D1lo + + vpsrlq \$44,$D1lo,$tmp + vpsllq \$8,$D1hi,$D1hi + vpandq $mask44,$D1lo,$H1 + vpaddq $tmp,$D1hi,$D1hi + + vpaddq $D1hi,$D2lo,$D2lo + + vpsrlq \$42,$D2lo,$tmp + vpsllq \$10,$D2hi,$D2hi + vpandq $mask42,$D2lo,$H2 + vpaddq $tmp,$D2hi,$D2hi + + vpaddq $D2hi,$H0,$H0 + vpsllq \$2,$D2hi,$D2hi + + vpaddq $D2hi,$H0,$H0 + + vpsrlq \$44,$H0,$tmp # additional step + vpandq $mask44,$H0,$H0 + + vpaddq $tmp,$H1,$H1 + + dec %eax + jz .Ldone_init_vpmadd52 + + vpunpcklqdq $R1,$H1,$R1 # 1,2 + vpbroadcastq %x#$H1,%x#$H1 # 2,2 + vpunpcklqdq $R2,$H2,$R2 + vpbroadcastq %x#$H2,%x#$H2 + vpunpcklqdq $R0,$H0,$R0 + vpbroadcastq %x#$H0,%x#$H0 + + vpsllq \$2,$R1,$S1 # S1 = R1*5*4 + vpsllq \$2,$R2,$S2 # S2 = R2*5*4 + vpaddq $R1,$S1,$S1 + vpaddq $R2,$S2,$S2 + vpsllq \$2,$S1,$S1 + vpsllq \$2,$S2,$S2 + + jmp .Lmul_init_vpmadd52 + ud2 + +.align 32 +.Ldone_init_vpmadd52: + vinserti128 \$1,%x#$R1,$H1,$R1 # 1,2,3,4 + vinserti128 \$1,%x#$R2,$H2,$R2 + vinserti128 \$1,%x#$R0,$H0,$R0 + + vpermq \$0b11011000,$R1,$R1 # 1,3,2,4 + vpermq \$0b11011000,$R2,$R2 + vpermq \$0b11011000,$R0,$R0 + + vpsllq \$2,$R1,$S1 # S1 = R1*5*4 + vpaddq $R1,$S1,$S1 + vpsllq \$2,$S1,$S1 + + vmovq 0($ctx),%x#$H0 # load current hash value + vmovq 8($ctx),%x#$H1 + vmovq 16($ctx),%x#$H2 + + test \$3,$len # is length 4*n+2? + jnz .Ldone_init_vpmadd52_2x + + vmovdqu64 $R0,64($ctx) # save key powers + vpbroadcastq %x#$R0,$R0 # broadcast 4th power + vmovdqu64 $R1,96($ctx) + vpbroadcastq %x#$R1,$R1 + vmovdqu64 $R2,128($ctx) + vpbroadcastq %x#$R2,$R2 + vmovdqu64 $S1,160($ctx) + vpbroadcastq %x#$S1,$S1 + + jmp .Lblocks_vpmadd52_4x_key_loaded + ud2 + +.align 32 +.Ldone_init_vpmadd52_2x: + vmovdqu64 $R0,64($ctx) # save key powers + vpsrldq \$8,$R0,$R0 # 0-1-0-2 + vmovdqu64 $R1,96($ctx) + vpsrldq \$8,$R1,$R1 + vmovdqu64 $R2,128($ctx) + vpsrldq \$8,$R2,$R2 + vmovdqu64 $S1,160($ctx) + vpsrldq \$8,$S1,$S1 + jmp .Lblocks_vpmadd52_2x_key_loaded + ud2 + +.align 32 +.Lblocks_vpmadd52_2x_do: + vmovdqu64 128+8($ctx),${R2}{%k1}{z}# load 2nd and 1st key powers + vmovdqu64 160+8($ctx),${S1}{%k1}{z} + vmovdqu64 64+8($ctx),${R0}{%k1}{z} + vmovdqu64 96+8($ctx),${R1}{%k1}{z} + +.Lblocks_vpmadd52_2x_key_loaded: + vmovdqu64 16*0($inp),$T2 # load data + vpxorq $T3,$T3,$T3 + lea 16*2($inp),$inp + + vpunpcklqdq $T3,$T2,$T1 # transpose data + vpunpckhqdq $T3,$T2,$T3 + + # at this point 64-bit lanes are ordered as x-1-x-0 + + vpsrlq \$24,$T3,$T2 # splat the data + vporq $PAD,$T2,$T2 + vpaddq $T2,$H2,$H2 # accumulate input + vpandq $mask44,$T1,$T0 + vpsrlq \$44,$T1,$T1 + vpsllq \$20,$T3,$T3 + vporq $T3,$T1,$T1 + vpandq $mask44,$T1,$T1 + + jmp .Ltail_vpmadd52_2x + ud2 + +.align 32 +.Loop_vpmadd52_4x: + #vpaddq $T2,$H2,$H2 # accumulate input + vpaddq $T0,$H0,$H0 + vpaddq $T1,$H1,$H1 + + vpxorq $D0lo,$D0lo,$D0lo + vpmadd52luq $H2,$S1,$D0lo + vpxorq $D0hi,$D0hi,$D0hi + vpmadd52huq $H2,$S1,$D0hi + vpxorq $D1lo,$D1lo,$D1lo + vpmadd52luq $H2,$S2,$D1lo + vpxorq $D1hi,$D1hi,$D1hi + vpmadd52huq $H2,$S2,$D1hi + vpxorq $D2lo,$D2lo,$D2lo + vpmadd52luq $H2,$R0,$D2lo + vpxorq $D2hi,$D2hi,$D2hi + vpmadd52huq $H2,$R0,$D2hi + + vmovdqu64 16*0($inp),$T2 # load data + vmovdqu64 16*2($inp),$T3 + lea 16*4($inp),$inp + vpmadd52luq $H0,$R0,$D0lo + vpmadd52huq $H0,$R0,$D0hi + vpmadd52luq $H0,$R1,$D1lo + vpmadd52huq $H0,$R1,$D1hi + vpmadd52luq $H0,$R2,$D2lo + vpmadd52huq $H0,$R2,$D2hi + + vpunpcklqdq $T3,$T2,$T1 # transpose data + vpunpckhqdq $T3,$T2,$T3 + vpmadd52luq $H1,$S2,$D0lo + vpmadd52huq $H1,$S2,$D0hi + vpmadd52luq $H1,$R0,$D1lo + vpmadd52huq $H1,$R0,$D1hi + vpmadd52luq $H1,$R1,$D2lo + vpmadd52huq $H1,$R1,$D2hi + + ################################################################ + # partial reduction (interleaved with data splat) + vpsrlq \$44,$D0lo,$tmp + vpsllq \$8,$D0hi,$D0hi + vpandq $mask44,$D0lo,$H0 + vpaddq $tmp,$D0hi,$D0hi + + vpsrlq \$24,$T3,$T2 + vporq $PAD,$T2,$T2 + vpaddq $D0hi,$D1lo,$D1lo + + vpsrlq \$44,$D1lo,$tmp + vpsllq \$8,$D1hi,$D1hi + vpandq $mask44,$D1lo,$H1 + vpaddq $tmp,$D1hi,$D1hi + + vpandq $mask44,$T1,$T0 + vpsrlq \$44,$T1,$T1 + vpsllq \$20,$T3,$T3 + vpaddq $D1hi,$D2lo,$D2lo + + vpsrlq \$42,$D2lo,$tmp + vpsllq \$10,$D2hi,$D2hi + vpandq $mask42,$D2lo,$H2 + vpaddq $tmp,$D2hi,$D2hi + + vpaddq $T2,$H2,$H2 # accumulate input + vpaddq $D2hi,$H0,$H0 + vpsllq \$2,$D2hi,$D2hi + + vpaddq $D2hi,$H0,$H0 + vporq $T3,$T1,$T1 + vpandq $mask44,$T1,$T1 + + vpsrlq \$44,$H0,$tmp # additional step + vpandq $mask44,$H0,$H0 + + vpaddq $tmp,$H1,$H1 + + sub \$4,$len # len-=64 + jnz .Loop_vpmadd52_4x + +.Ltail_vpmadd52_4x: + vmovdqu64 128($ctx),$R2 # load all key powers + vmovdqu64 160($ctx),$S1 + vmovdqu64 64($ctx),$R0 + vmovdqu64 96($ctx),$R1 + +.Ltail_vpmadd52_2x: + vpsllq \$2,$R2,$S2 # S2 = R2*5*4 + vpaddq $R2,$S2,$S2 + vpsllq \$2,$S2,$S2 + + #vpaddq $T2,$H2,$H2 # accumulate input + vpaddq $T0,$H0,$H0 + vpaddq $T1,$H1,$H1 + + vpxorq $D0lo,$D0lo,$D0lo + vpmadd52luq $H2,$S1,$D0lo + vpxorq $D0hi,$D0hi,$D0hi + vpmadd52huq $H2,$S1,$D0hi + vpxorq $D1lo,$D1lo,$D1lo + vpmadd52luq $H2,$S2,$D1lo + vpxorq $D1hi,$D1hi,$D1hi + vpmadd52huq $H2,$S2,$D1hi + vpxorq $D2lo,$D2lo,$D2lo + vpmadd52luq $H2,$R0,$D2lo + vpxorq $D2hi,$D2hi,$D2hi + vpmadd52huq $H2,$R0,$D2hi + + vpmadd52luq $H0,$R0,$D0lo + vpmadd52huq $H0,$R0,$D0hi + vpmadd52luq $H0,$R1,$D1lo + vpmadd52huq $H0,$R1,$D1hi + vpmadd52luq $H0,$R2,$D2lo + vpmadd52huq $H0,$R2,$D2hi + + vpmadd52luq $H1,$S2,$D0lo + vpmadd52huq $H1,$S2,$D0hi + vpmadd52luq $H1,$R0,$D1lo + vpmadd52huq $H1,$R0,$D1hi + vpmadd52luq $H1,$R1,$D2lo + vpmadd52huq $H1,$R1,$D2hi + + ################################################################ + # horizontal addition + + mov \$1,%eax + kmovw %eax,%k1 + vpsrldq \$8,$D0lo,$T0 + vpsrldq \$8,$D0hi,$H0 + vpsrldq \$8,$D1lo,$T1 + vpsrldq \$8,$D1hi,$H1 + vpaddq $T0,$D0lo,$D0lo + vpaddq $H0,$D0hi,$D0hi + vpsrldq \$8,$D2lo,$T2 + vpsrldq \$8,$D2hi,$H2 + vpaddq $T1,$D1lo,$D1lo + vpaddq $H1,$D1hi,$D1hi + vpermq \$0x2,$D0lo,$T0 + vpermq \$0x2,$D0hi,$H0 + vpaddq $T2,$D2lo,$D2lo + vpaddq $H2,$D2hi,$D2hi + + vpermq \$0x2,$D1lo,$T1 + vpermq \$0x2,$D1hi,$H1 + vpaddq $T0,$D0lo,${D0lo}{%k1}{z} + vpaddq $H0,$D0hi,${D0hi}{%k1}{z} + vpermq \$0x2,$D2lo,$T2 + vpermq \$0x2,$D2hi,$H2 + vpaddq $T1,$D1lo,${D1lo}{%k1}{z} + vpaddq $H1,$D1hi,${D1hi}{%k1}{z} + vpaddq $T2,$D2lo,${D2lo}{%k1}{z} + vpaddq $H2,$D2hi,${D2hi}{%k1}{z} + + ################################################################ + # partial reduction + vpsrlq \$44,$D0lo,$tmp + vpsllq \$8,$D0hi,$D0hi + vpandq $mask44,$D0lo,$H0 + vpaddq $tmp,$D0hi,$D0hi + + vpaddq $D0hi,$D1lo,$D1lo + + vpsrlq \$44,$D1lo,$tmp + vpsllq \$8,$D1hi,$D1hi + vpandq $mask44,$D1lo,$H1 + vpaddq $tmp,$D1hi,$D1hi + + vpaddq $D1hi,$D2lo,$D2lo + + vpsrlq \$42,$D2lo,$tmp + vpsllq \$10,$D2hi,$D2hi + vpandq $mask42,$D2lo,$H2 + vpaddq $tmp,$D2hi,$D2hi + + vpaddq $D2hi,$H0,$H0 + vpsllq \$2,$D2hi,$D2hi + + vpaddq $D2hi,$H0,$H0 + + vpsrlq \$44,$H0,$tmp # additional step + vpandq $mask44,$H0,$H0 + + vpaddq $tmp,$H1,$H1 + # at this point $len is + # either 4*n+2 or 0... + sub \$2,$len # len-=32 + ja .Lblocks_vpmadd52_4x_do + + vmovq %x#$H0,0($ctx) + vmovq %x#$H1,8($ctx) + vmovq %x#$H2,16($ctx) + vzeroall + +.Lno_data_vpmadd52_4x: + ret +.size poly1305_blocks_vpmadd52_4x,.-poly1305_blocks_vpmadd52_4x +___ +} +{ +######################################################################## +# As implied by its name 8x subroutine processes 8 blocks in parallel... +# This is intermediate version, as it's used only in cases when input +# length is either 8*n, 8*n+1 or 8*n+2... + +my ($H0,$H1,$H2,$R0,$R1,$R2,$S1,$S2) = map("%ymm$_",(0..5,16,17)); +my ($D0lo,$D0hi,$D1lo,$D1hi,$D2lo,$D2hi) = map("%ymm$_",(18..23)); +my ($T0,$T1,$T2,$T3,$mask44,$mask42,$tmp,$PAD) = map("%ymm$_",(24..31)); +my ($RR0,$RR1,$RR2,$SS1,$SS2) = map("%ymm$_",(6..10)); + +$code.=<<___; +.type poly1305_blocks_vpmadd52_8x,\@function,4 +.align 32 +poly1305_blocks_vpmadd52_8x: + shr \$4,$len + jz .Lno_data_vpmadd52_8x # too short + + shl \$40,$padbit + mov 64($ctx),%r8 # peek on power of the key + + vmovdqa64 .Lx_mask44(%rip),$mask44 + vmovdqa64 .Lx_mask42(%rip),$mask42 + + test %r8,%r8 # is power value impossible? + js .Linit_vpmadd52 # if it is, then init R[4] + + vmovq 0($ctx),%x#$H0 # load current hash value + vmovq 8($ctx),%x#$H1 + vmovq 16($ctx),%x#$H2 + +.Lblocks_vpmadd52_8x: + ################################################################ + # fist we calculate more key powers + + vmovdqu64 128($ctx),$R2 # load 1-3-2-4 powers + vmovdqu64 160($ctx),$S1 + vmovdqu64 64($ctx),$R0 + vmovdqu64 96($ctx),$R1 + + vpsllq \$2,$R2,$S2 # S2 = R2*5*4 + vpaddq $R2,$S2,$S2 + vpsllq \$2,$S2,$S2 + + vpbroadcastq %x#$R2,$RR2 # broadcast 4th power + vpbroadcastq %x#$R0,$RR0 + vpbroadcastq %x#$R1,$RR1 + + vpxorq $D0lo,$D0lo,$D0lo + vpmadd52luq $RR2,$S1,$D0lo + vpxorq $D0hi,$D0hi,$D0hi + vpmadd52huq $RR2,$S1,$D0hi + vpxorq $D1lo,$D1lo,$D1lo + vpmadd52luq $RR2,$S2,$D1lo + vpxorq $D1hi,$D1hi,$D1hi + vpmadd52huq $RR2,$S2,$D1hi + vpxorq $D2lo,$D2lo,$D2lo + vpmadd52luq $RR2,$R0,$D2lo + vpxorq $D2hi,$D2hi,$D2hi + vpmadd52huq $RR2,$R0,$D2hi + + vpmadd52luq $RR0,$R0,$D0lo + vpmadd52huq $RR0,$R0,$D0hi + vpmadd52luq $RR0,$R1,$D1lo + vpmadd52huq $RR0,$R1,$D1hi + vpmadd52luq $RR0,$R2,$D2lo + vpmadd52huq $RR0,$R2,$D2hi + + vpmadd52luq $RR1,$S2,$D0lo + vpmadd52huq $RR1,$S2,$D0hi + vpmadd52luq $RR1,$R0,$D1lo + vpmadd52huq $RR1,$R0,$D1hi + vpmadd52luq $RR1,$R1,$D2lo + vpmadd52huq $RR1,$R1,$D2hi + + ################################################################ + # partial reduction + vpsrlq \$44,$D0lo,$tmp + vpsllq \$8,$D0hi,$D0hi + vpandq $mask44,$D0lo,$RR0 + vpaddq $tmp,$D0hi,$D0hi + + vpaddq $D0hi,$D1lo,$D1lo + + vpsrlq \$44,$D1lo,$tmp + vpsllq \$8,$D1hi,$D1hi + vpandq $mask44,$D1lo,$RR1 + vpaddq $tmp,$D1hi,$D1hi + + vpaddq $D1hi,$D2lo,$D2lo + + vpsrlq \$42,$D2lo,$tmp + vpsllq \$10,$D2hi,$D2hi + vpandq $mask42,$D2lo,$RR2 + vpaddq $tmp,$D2hi,$D2hi + + vpaddq $D2hi,$RR0,$RR0 + vpsllq \$2,$D2hi,$D2hi + + vpaddq $D2hi,$RR0,$RR0 + + vpsrlq \$44,$RR0,$tmp # additional step + vpandq $mask44,$RR0,$RR0 + + vpaddq $tmp,$RR1,$RR1 + + ################################################################ + # At this point Rx holds 1324 powers, RRx - 5768, and the goal + # is 15263748, which reflects how data is loaded... + + vpunpcklqdq $R2,$RR2,$T2 # 3748 + vpunpckhqdq $R2,$RR2,$R2 # 1526 + vpunpcklqdq $R0,$RR0,$T0 + vpunpckhqdq $R0,$RR0,$R0 + vpunpcklqdq $R1,$RR1,$T1 + vpunpckhqdq $R1,$RR1,$R1 +___ +######## switch to %zmm +map(s/%y/%z/, $H0,$H1,$H2,$R0,$R1,$R2,$S1,$S2); +map(s/%y/%z/, $D0lo,$D0hi,$D1lo,$D1hi,$D2lo,$D2hi); +map(s/%y/%z/, $T0,$T1,$T2,$T3,$mask44,$mask42,$tmp,$PAD); +map(s/%y/%z/, $RR0,$RR1,$RR2,$SS1,$SS2); + +$code.=<<___; + vshufi64x2 \$0x44,$R2,$T2,$RR2 # 15263748 + vshufi64x2 \$0x44,$R0,$T0,$RR0 + vshufi64x2 \$0x44,$R1,$T1,$RR1 + + vmovdqu64 16*0($inp),$T2 # load data + vmovdqu64 16*4($inp),$T3 + lea 16*8($inp),$inp + + vpsllq \$2,$RR2,$SS2 # S2 = R2*5*4 + vpsllq \$2,$RR1,$SS1 # S1 = R1*5*4 + vpaddq $RR2,$SS2,$SS2 + vpaddq $RR1,$SS1,$SS1 + vpsllq \$2,$SS2,$SS2 + vpsllq \$2,$SS1,$SS1 + + vpbroadcastq $padbit,$PAD + vpbroadcastq %x#$mask44,$mask44 + vpbroadcastq %x#$mask42,$mask42 + + vpbroadcastq %x#$SS1,$S1 # broadcast 8th power + vpbroadcastq %x#$SS2,$S2 + vpbroadcastq %x#$RR0,$R0 + vpbroadcastq %x#$RR1,$R1 + vpbroadcastq %x#$RR2,$R2 + + vpunpcklqdq $T3,$T2,$T1 # transpose data + vpunpckhqdq $T3,$T2,$T3 + + # at this point 64-bit lanes are ordered as 73625140 + + vpsrlq \$24,$T3,$T2 # splat the data + vporq $PAD,$T2,$T2 + vpaddq $T2,$H2,$H2 # accumulate input + vpandq $mask44,$T1,$T0 + vpsrlq \$44,$T1,$T1 + vpsllq \$20,$T3,$T3 + vporq $T3,$T1,$T1 + vpandq $mask44,$T1,$T1 + + sub \$8,$len + jz .Ltail_vpmadd52_8x + jmp .Loop_vpmadd52_8x + +.align 32 +.Loop_vpmadd52_8x: + #vpaddq $T2,$H2,$H2 # accumulate input + vpaddq $T0,$H0,$H0 + vpaddq $T1,$H1,$H1 + + vpxorq $D0lo,$D0lo,$D0lo + vpmadd52luq $H2,$S1,$D0lo + vpxorq $D0hi,$D0hi,$D0hi + vpmadd52huq $H2,$S1,$D0hi + vpxorq $D1lo,$D1lo,$D1lo + vpmadd52luq $H2,$S2,$D1lo + vpxorq $D1hi,$D1hi,$D1hi + vpmadd52huq $H2,$S2,$D1hi + vpxorq $D2lo,$D2lo,$D2lo + vpmadd52luq $H2,$R0,$D2lo + vpxorq $D2hi,$D2hi,$D2hi + vpmadd52huq $H2,$R0,$D2hi + + vmovdqu64 16*0($inp),$T2 # load data + vmovdqu64 16*4($inp),$T3 + lea 16*8($inp),$inp + vpmadd52luq $H0,$R0,$D0lo + vpmadd52huq $H0,$R0,$D0hi + vpmadd52luq $H0,$R1,$D1lo + vpmadd52huq $H0,$R1,$D1hi + vpmadd52luq $H0,$R2,$D2lo + vpmadd52huq $H0,$R2,$D2hi + + vpunpcklqdq $T3,$T2,$T1 # transpose data + vpunpckhqdq $T3,$T2,$T3 + vpmadd52luq $H1,$S2,$D0lo + vpmadd52huq $H1,$S2,$D0hi + vpmadd52luq $H1,$R0,$D1lo + vpmadd52huq $H1,$R0,$D1hi + vpmadd52luq $H1,$R1,$D2lo + vpmadd52huq $H1,$R1,$D2hi + + ################################################################ + # partial reduction (interleaved with data splat) + vpsrlq \$44,$D0lo,$tmp + vpsllq \$8,$D0hi,$D0hi + vpandq $mask44,$D0lo,$H0 + vpaddq $tmp,$D0hi,$D0hi + + vpsrlq \$24,$T3,$T2 + vporq $PAD,$T2,$T2 + vpaddq $D0hi,$D1lo,$D1lo + + vpsrlq \$44,$D1lo,$tmp + vpsllq \$8,$D1hi,$D1hi + vpandq $mask44,$D1lo,$H1 + vpaddq $tmp,$D1hi,$D1hi + + vpandq $mask44,$T1,$T0 + vpsrlq \$44,$T1,$T1 + vpsllq \$20,$T3,$T3 + vpaddq $D1hi,$D2lo,$D2lo + + vpsrlq \$42,$D2lo,$tmp + vpsllq \$10,$D2hi,$D2hi + vpandq $mask42,$D2lo,$H2 + vpaddq $tmp,$D2hi,$D2hi + + vpaddq $T2,$H2,$H2 # accumulate input + vpaddq $D2hi,$H0,$H0 + vpsllq \$2,$D2hi,$D2hi + + vpaddq $D2hi,$H0,$H0 + vporq $T3,$T1,$T1 + vpandq $mask44,$T1,$T1 + + vpsrlq \$44,$H0,$tmp # additional step + vpandq $mask44,$H0,$H0 + + vpaddq $tmp,$H1,$H1 + + sub \$8,$len # len-=128 + jnz .Loop_vpmadd52_8x + +.Ltail_vpmadd52_8x: + #vpaddq $T2,$H2,$H2 # accumulate input + vpaddq $T0,$H0,$H0 + vpaddq $T1,$H1,$H1 + + vpxorq $D0lo,$D0lo,$D0lo + vpmadd52luq $H2,$SS1,$D0lo + vpxorq $D0hi,$D0hi,$D0hi + vpmadd52huq $H2,$SS1,$D0hi + vpxorq $D1lo,$D1lo,$D1lo + vpmadd52luq $H2,$SS2,$D1lo + vpxorq $D1hi,$D1hi,$D1hi + vpmadd52huq $H2,$SS2,$D1hi + vpxorq $D2lo,$D2lo,$D2lo + vpmadd52luq $H2,$RR0,$D2lo + vpxorq $D2hi,$D2hi,$D2hi + vpmadd52huq $H2,$RR0,$D2hi + + vpmadd52luq $H0,$RR0,$D0lo + vpmadd52huq $H0,$RR0,$D0hi + vpmadd52luq $H0,$RR1,$D1lo + vpmadd52huq $H0,$RR1,$D1hi + vpmadd52luq $H0,$RR2,$D2lo + vpmadd52huq $H0,$RR2,$D2hi + + vpmadd52luq $H1,$SS2,$D0lo + vpmadd52huq $H1,$SS2,$D0hi + vpmadd52luq $H1,$RR0,$D1lo + vpmadd52huq $H1,$RR0,$D1hi + vpmadd52luq $H1,$RR1,$D2lo + vpmadd52huq $H1,$RR1,$D2hi + + ################################################################ + # horizontal addition + + mov \$1,%eax + kmovw %eax,%k1 + vpsrldq \$8,$D0lo,$T0 + vpsrldq \$8,$D0hi,$H0 + vpsrldq \$8,$D1lo,$T1 + vpsrldq \$8,$D1hi,$H1 + vpaddq $T0,$D0lo,$D0lo + vpaddq $H0,$D0hi,$D0hi + vpsrldq \$8,$D2lo,$T2 + vpsrldq \$8,$D2hi,$H2 + vpaddq $T1,$D1lo,$D1lo + vpaddq $H1,$D1hi,$D1hi + vpermq \$0x2,$D0lo,$T0 + vpermq \$0x2,$D0hi,$H0 + vpaddq $T2,$D2lo,$D2lo + vpaddq $H2,$D2hi,$D2hi + + vpermq \$0x2,$D1lo,$T1 + vpermq \$0x2,$D1hi,$H1 + vpaddq $T0,$D0lo,$D0lo + vpaddq $H0,$D0hi,$D0hi + vpermq \$0x2,$D2lo,$T2 + vpermq \$0x2,$D2hi,$H2 + vpaddq $T1,$D1lo,$D1lo + vpaddq $H1,$D1hi,$D1hi + vextracti64x4 \$1,$D0lo,%y#$T0 + vextracti64x4 \$1,$D0hi,%y#$H0 + vpaddq $T2,$D2lo,$D2lo + vpaddq $H2,$D2hi,$D2hi + + vextracti64x4 \$1,$D1lo,%y#$T1 + vextracti64x4 \$1,$D1hi,%y#$H1 + vextracti64x4 \$1,$D2lo,%y#$T2 + vextracti64x4 \$1,$D2hi,%y#$H2 +___ +######## switch back to %ymm +map(s/%z/%y/, $H0,$H1,$H2,$R0,$R1,$R2,$S1,$S2); +map(s/%z/%y/, $D0lo,$D0hi,$D1lo,$D1hi,$D2lo,$D2hi); +map(s/%z/%y/, $T0,$T1,$T2,$T3,$mask44,$mask42,$tmp,$PAD); + +$code.=<<___; + vpaddq $T0,$D0lo,${D0lo}{%k1}{z} + vpaddq $H0,$D0hi,${D0hi}{%k1}{z} + vpaddq $T1,$D1lo,${D1lo}{%k1}{z} + vpaddq $H1,$D1hi,${D1hi}{%k1}{z} + vpaddq $T2,$D2lo,${D2lo}{%k1}{z} + vpaddq $H2,$D2hi,${D2hi}{%k1}{z} + + ################################################################ + # partial reduction + vpsrlq \$44,$D0lo,$tmp + vpsllq \$8,$D0hi,$D0hi + vpandq $mask44,$D0lo,$H0 + vpaddq $tmp,$D0hi,$D0hi + + vpaddq $D0hi,$D1lo,$D1lo + + vpsrlq \$44,$D1lo,$tmp + vpsllq \$8,$D1hi,$D1hi + vpandq $mask44,$D1lo,$H1 + vpaddq $tmp,$D1hi,$D1hi + + vpaddq $D1hi,$D2lo,$D2lo + + vpsrlq \$42,$D2lo,$tmp + vpsllq \$10,$D2hi,$D2hi + vpandq $mask42,$D2lo,$H2 + vpaddq $tmp,$D2hi,$D2hi + + vpaddq $D2hi,$H0,$H0 + vpsllq \$2,$D2hi,$D2hi + + vpaddq $D2hi,$H0,$H0 + + vpsrlq \$44,$H0,$tmp # additional step + vpandq $mask44,$H0,$H0 + + vpaddq $tmp,$H1,$H1 + + ################################################################ + + vmovq %x#$H0,0($ctx) + vmovq %x#$H1,8($ctx) + vmovq %x#$H2,16($ctx) + vzeroall + +.Lno_data_vpmadd52_8x: + ret +.size poly1305_blocks_vpmadd52_8x,.-poly1305_blocks_vpmadd52_8x +___ +} +$code.=<<___; +.type poly1305_emit_base2_44,\@function,3 +.align 32 +poly1305_emit_base2_44: + mov 0($ctx),%r8 # load hash value + mov 8($ctx),%r9 + mov 16($ctx),%r10 + + mov %r9,%rax + shr \$20,%r9 + shl \$44,%rax + mov %r10,%rcx + shr \$40,%r10 + shl \$24,%rcx + + add %rax,%r8 + adc %rcx,%r9 + adc \$0,%r10 + + mov %r8,%rax + add \$5,%r8 # compare to modulus + mov %r9,%rcx + adc \$0,%r9 + adc \$0,%r10 + shr \$2,%r10 # did 130-bit value overflow? + cmovnz %r8,%rax + cmovnz %r9,%rcx + + add 0($nonce),%rax # accumulate nonce + adc 8($nonce),%rcx + mov %rax,0($mac) # write result + mov %rcx,8($mac) + + ret +.size poly1305_emit_base2_44,.-poly1305_emit_base2_44 +___ +} } } +$code.=<<___; +.align 64 +.Lconst: +.Lmask24: +.long 0x0ffffff,0,0x0ffffff,0,0x0ffffff,0,0x0ffffff,0 +.L129: +.long `1<<24`,0,`1<<24`,0,`1<<24`,0,`1<<24`,0 +.Lmask26: +.long 0x3ffffff,0,0x3ffffff,0,0x3ffffff,0,0x3ffffff,0 +.Lpermd_avx2: +.long 2,2,2,3,2,0,2,1 +.Lpermd_avx512: +.long 0,0,0,1, 0,2,0,3, 0,4,0,5, 0,6,0,7 + +.L2_44_inp_permd: +.long 0,1,1,2,2,3,7,7 +.L2_44_inp_shift: +.quad 0,12,24,64 +.L2_44_mask: +.quad 0xfffffffffff,0xfffffffffff,0x3ffffffffff,0xffffffffffffffff +.L2_44_shift_rgt: +.quad 44,44,42,64 +.L2_44_shift_lft: +.quad 8,8,10,64 + +.align 64 +.Lx_mask44: +.quad 0xfffffffffff,0xfffffffffff,0xfffffffffff,0xfffffffffff +.quad 0xfffffffffff,0xfffffffffff,0xfffffffffff,0xfffffffffff +.Lx_mask42: +.quad 0x3ffffffffff,0x3ffffffffff,0x3ffffffffff,0x3ffffffffff +.quad 0x3ffffffffff,0x3ffffffffff,0x3ffffffffff,0x3ffffffffff +___ +} +$code.=<<___; +.asciz "Poly1305 for x86_64, CRYPTOGAMS by " +.align 16 +___ + +{ # chacha20-poly1305 helpers +my ($out,$inp,$otp,$len)=$win64 ? ("%rcx","%rdx","%r8", "%r9") : # Win64 order + ("%rdi","%rsi","%rdx","%rcx"); # Unix order +$code.=<<___; +.globl xor128_encrypt_n_pad +.type xor128_encrypt_n_pad,\@abi-omnipotent +.align 16 +xor128_encrypt_n_pad: + sub $otp,$inp + sub $otp,$out + mov $len,%r10 # put len aside + shr \$4,$len # len / 16 + jz .Ltail_enc + nop +.Loop_enc_xmm: + movdqu ($inp,$otp),%xmm0 + pxor ($otp),%xmm0 + movdqu %xmm0,($out,$otp) + movdqa %xmm0,($otp) + lea 16($otp),$otp + dec $len + jnz .Loop_enc_xmm + + and \$15,%r10 # len % 16 + jz .Ldone_enc + +.Ltail_enc: + mov \$16,$len + sub %r10,$len + xor %eax,%eax +.Loop_enc_byte: + mov ($inp,$otp),%al + xor ($otp),%al + mov %al,($out,$otp) + mov %al,($otp) + lea 1($otp),$otp + dec %r10 + jnz .Loop_enc_byte + + xor %eax,%eax +.Loop_enc_pad: + mov %al,($otp) + lea 1($otp),$otp + dec $len + jnz .Loop_enc_pad + +.Ldone_enc: + mov $otp,%rax + ret +.size xor128_encrypt_n_pad,.-xor128_encrypt_n_pad + +.globl xor128_decrypt_n_pad +.type xor128_decrypt_n_pad,\@abi-omnipotent +.align 16 +xor128_decrypt_n_pad: + sub $otp,$inp + sub $otp,$out + mov $len,%r10 # put len aside + shr \$4,$len # len / 16 + jz .Ltail_dec + nop +.Loop_dec_xmm: + movdqu ($inp,$otp),%xmm0 + movdqa ($otp),%xmm1 + pxor %xmm0,%xmm1 + movdqu %xmm1,($out,$otp) + movdqa %xmm0,($otp) + lea 16($otp),$otp + dec $len + jnz .Loop_dec_xmm + + pxor %xmm1,%xmm1 + and \$15,%r10 # len % 16 + jz .Ldone_dec + +.Ltail_dec: + mov \$16,$len + sub %r10,$len + xor %eax,%eax + xor %r11,%r11 +.Loop_dec_byte: + mov ($inp,$otp),%r11b + mov ($otp),%al + xor %r11b,%al + mov %al,($out,$otp) + mov %r11b,($otp) + lea 1($otp),$otp + dec %r10 + jnz .Loop_dec_byte + + xor %eax,%eax +.Loop_dec_pad: + mov %al,($otp) + lea 1($otp),$otp + dec $len + jnz .Loop_dec_pad + +.Ldone_dec: + mov $otp,%rax + ret +.size xor128_decrypt_n_pad,.-xor128_decrypt_n_pad +___ +} + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type se_handler,\@abi-omnipotent +.align 16 +se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->Rip<.Lprologue + jb .Lcommon_seh_tail + + mov 152($context),%rax # pull context->Rsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=.Lepilogue + jae .Lcommon_seh_tail + + lea 48(%rax),%rax + + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov -48(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R14 + + jmp .Lcommon_seh_tail +.size se_handler,.-se_handler + +.type avx_handler,\@abi-omnipotent +.align 16 +avx_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lcommon_seh_tail + + mov 208($context),%rax # pull context->R11 + + lea 0x50(%rax),%rsi + lea 0xf8(%rax),%rax + lea 512($context),%rdi # &context.Xmm6 + mov \$20,%ecx + .long 0xa548f3fc # cld; rep movsq + +.Lcommon_seh_tail: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size avx_handler,.-avx_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_poly1305_init + .rva .LSEH_end_poly1305_init + .rva .LSEH_info_poly1305_init + + .rva .LSEH_begin_poly1305_blocks + .rva .LSEH_end_poly1305_blocks + .rva .LSEH_info_poly1305_blocks + + .rva .LSEH_begin_poly1305_emit + .rva .LSEH_end_poly1305_emit + .rva .LSEH_info_poly1305_emit +___ +$code.=<<___ if ($avx); + .rva .LSEH_begin_poly1305_blocks_avx + .rva .Lbase2_64_avx + .rva .LSEH_info_poly1305_blocks_avx_1 + + .rva .Lbase2_64_avx + .rva .Leven_avx + .rva .LSEH_info_poly1305_blocks_avx_2 + + .rva .Leven_avx + .rva .LSEH_end_poly1305_blocks_avx + .rva .LSEH_info_poly1305_blocks_avx_3 + + .rva .LSEH_begin_poly1305_emit_avx + .rva .LSEH_end_poly1305_emit_avx + .rva .LSEH_info_poly1305_emit_avx +___ +$code.=<<___ if ($avx>1); + .rva .LSEH_begin_poly1305_blocks_avx2 + .rva .Lbase2_64_avx2 + .rva .LSEH_info_poly1305_blocks_avx2_1 + + .rva .Lbase2_64_avx2 + .rva .Leven_avx2 + .rva .LSEH_info_poly1305_blocks_avx2_2 + + .rva .Leven_avx2 + .rva .LSEH_end_poly1305_blocks_avx2 + .rva .LSEH_info_poly1305_blocks_avx2_3 +___ +$code.=<<___ if ($avx>2); + .rva .LSEH_begin_poly1305_blocks_avx512 + .rva .LSEH_end_poly1305_blocks_avx512 + .rva .LSEH_info_poly1305_blocks_avx512 +___ +$code.=<<___; +.section .xdata +.align 8 +.LSEH_info_poly1305_init: + .byte 9,0,0,0 + .rva se_handler + .rva .LSEH_begin_poly1305_init,.LSEH_begin_poly1305_init + +.LSEH_info_poly1305_blocks: + .byte 9,0,0,0 + .rva se_handler + .rva .Lblocks_body,.Lblocks_epilogue + +.LSEH_info_poly1305_emit: + .byte 9,0,0,0 + .rva se_handler + .rva .LSEH_begin_poly1305_emit,.LSEH_begin_poly1305_emit +___ +$code.=<<___ if ($avx); +.LSEH_info_poly1305_blocks_avx_1: + .byte 9,0,0,0 + .rva se_handler + .rva .Lblocks_avx_body,.Lblocks_avx_epilogue # HandlerData[] + +.LSEH_info_poly1305_blocks_avx_2: + .byte 9,0,0,0 + .rva se_handler + .rva .Lbase2_64_avx_body,.Lbase2_64_avx_epilogue # HandlerData[] + +.LSEH_info_poly1305_blocks_avx_3: + .byte 9,0,0,0 + .rva avx_handler + .rva .Ldo_avx_body,.Ldo_avx_epilogue # HandlerData[] + +.LSEH_info_poly1305_emit_avx: + .byte 9,0,0,0 + .rva se_handler + .rva .LSEH_begin_poly1305_emit_avx,.LSEH_begin_poly1305_emit_avx +___ +$code.=<<___ if ($avx>1); +.LSEH_info_poly1305_blocks_avx2_1: + .byte 9,0,0,0 + .rva se_handler + .rva .Lblocks_avx2_body,.Lblocks_avx2_epilogue # HandlerData[] + +.LSEH_info_poly1305_blocks_avx2_2: + .byte 9,0,0,0 + .rva se_handler + .rva .Lbase2_64_avx2_body,.Lbase2_64_avx2_epilogue # HandlerData[] + +.LSEH_info_poly1305_blocks_avx2_3: + .byte 9,0,0,0 + .rva avx_handler + .rva .Ldo_avx2_body,.Ldo_avx2_epilogue # HandlerData[] +___ +$code.=<<___ if ($avx>2); +.LSEH_info_poly1305_blocks_avx512: + .byte 9,0,0,0 + .rva avx_handler + .rva .Ldo_avx512_body,.Ldo_avx512_epilogue # HandlerData[] +___ +} + +foreach (split('\n',$code)) { + s/\`([^\`]*)\`/eval($1)/ge; + s/%r([a-z]+)#d/%e$1/g; + s/%r([0-9]+)#d/%r$1d/g; + s/%x#%[yz]/%x/g or s/%y#%z/%y/g or s/%z#%[yz]/%z/g; + + print $_,"\n"; +} +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/build.info new file mode 100644 index 000000000..631b32b8e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/build.info @@ -0,0 +1,24 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + poly1305_pmeth.c \ + poly1305_ameth.c \ + poly1305.c {- $target{poly1305_asm_src} -} + +GENERATE[poly1305-sparcv9.S]=asm/poly1305-sparcv9.pl $(PERLASM_SCHEME) +INCLUDE[poly1305-sparcv9.o]=.. +GENERATE[poly1305-x86.s]=asm/poly1305-x86.pl \ + $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) +GENERATE[poly1305-x86_64.s]=asm/poly1305-x86_64.pl $(PERLASM_SCHEME) +GENERATE[poly1305-ppc.s]=asm/poly1305-ppc.pl $(PERLASM_SCHEME) +GENERATE[poly1305-ppcfp.s]=asm/poly1305-ppcfp.pl $(PERLASM_SCHEME) +GENERATE[poly1305-armv4.S]=asm/poly1305-armv4.pl $(PERLASM_SCHEME) +INCLUDE[poly1305-armv4.o]=.. +GENERATE[poly1305-armv8.S]=asm/poly1305-armv8.pl $(PERLASM_SCHEME) +INCLUDE[poly1305-armv8.o]=.. +GENERATE[poly1305-mips.S]=asm/poly1305-mips.pl $(PERLASM_SCHEME) +INCLUDE[poly1305-mips.o]=.. + +BEGINRAW[Makefile(unix)] +{- $builddir -}/poly1305-%.S: {- $sourcedir -}/asm/poly1305-%.pl + CC="$(CC)" $(PERL) $< $(PERLASM_SCHEME) $@ +ENDRAW[Makefile(unix)] diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/poly1305.c b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/poly1305.c new file mode 100644 index 000000000..1d182364a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/poly1305.c @@ -0,0 +1,531 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include + +#include "internal/poly1305.h" +#include "poly1305_local.h" + +size_t Poly1305_ctx_size(void) +{ + return sizeof(struct poly1305_context); +} + +/* pick 32-bit unsigned integer in little endian order */ +static unsigned int U8TOU32(const unsigned char *p) +{ + return (((unsigned int)(p[0] & 0xff)) | + ((unsigned int)(p[1] & 0xff) << 8) | + ((unsigned int)(p[2] & 0xff) << 16) | + ((unsigned int)(p[3] & 0xff) << 24)); +} + +/* + * Implementations can be classified by amount of significant bits in + * words making up the multi-precision value, or in other words radix + * or base of numerical representation, e.g. base 2^64, base 2^32, + * base 2^26. Complementary characteristic is how wide is the result of + * multiplication of pair of digits, e.g. it would take 128 bits to + * accommodate multiplication result in base 2^64 case. These are used + * interchangeably. To describe implementation that is. But interface + * is designed to isolate this so that low-level primitives implemented + * in assembly can be self-contained/self-coherent. + */ +#ifndef POLY1305_ASM +/* + * Even though there is __int128 reference implementation targeting + * 64-bit platforms provided below, it's not obvious that it's optimal + * choice for every one of them. Depending on instruction set overall + * amount of instructions can be comparable to one in __int64 + * implementation. Amount of multiplication instructions would be lower, + * but not necessarily overall. And in out-of-order execution context, + * it is the latter that can be crucial... + * + * On related note. Poly1305 author, D. J. Bernstein, discusses and + * provides floating-point implementations of the algorithm in question. + * It made a lot of sense by the time of introduction, because most + * then-modern processors didn't have pipelined integer multiplier. + * [Not to mention that some had non-constant timing for integer + * multiplications.] Floating-point instructions on the other hand could + * be issued every cycle, which allowed to achieve better performance. + * Nowadays, with SIMD and/or out-or-order execution, shared or + * even emulated FPU, it's more complicated, and floating-point + * implementation is not necessarily optimal choice in every situation, + * rather contrary... + * + * + */ + +typedef unsigned int u32; + +/* + * poly1305_blocks processes a multiple of POLY1305_BLOCK_SIZE blocks + * of |inp| no longer than |len|. Behaviour for |len| not divisible by + * block size is unspecified in general case, even though in reference + * implementation the trailing chunk is simply ignored. Per algorithm + * specification, every input block, complete or last partial, is to be + * padded with a bit past most significant byte. The latter kind is then + * padded with zeros till block size. This last partial block padding + * is caller(*)'s responsibility, and because of this the last partial + * block is always processed with separate call with |len| set to + * POLY1305_BLOCK_SIZE and |padbit| to 0. In all other cases |padbit| + * should be set to 1 to perform implicit padding with 128th bit. + * poly1305_blocks does not actually check for this constraint though, + * it's caller(*)'s responsibility to comply. + * + * (*) In the context "caller" is not application code, but higher + * level Poly1305_* from this very module, so that quirks are + * handled locally. + */ +static void +poly1305_blocks(void *ctx, const unsigned char *inp, size_t len, u32 padbit); + +/* + * Type-agnostic "rip-off" from constant_time_locl.h + */ +# define CONSTANT_TIME_CARRY(a,b) ( \ + (a ^ ((a ^ b) | ((a - b) ^ b))) >> (sizeof(a) * 8 - 1) \ + ) + +# if (defined(__SIZEOF_INT128__) && __SIZEOF_INT128__==16) && \ + (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__==8) + +typedef unsigned long u64; +typedef __uint128_t u128; + +typedef struct { + u64 h[3]; + u64 r[2]; +} poly1305_internal; + +/* pick 32-bit unsigned integer in little endian order */ +static u64 U8TOU64(const unsigned char *p) +{ + return (((u64)(p[0] & 0xff)) | + ((u64)(p[1] & 0xff) << 8) | + ((u64)(p[2] & 0xff) << 16) | + ((u64)(p[3] & 0xff) << 24) | + ((u64)(p[4] & 0xff) << 32) | + ((u64)(p[5] & 0xff) << 40) | + ((u64)(p[6] & 0xff) << 48) | + ((u64)(p[7] & 0xff) << 56)); +} + +/* store a 32-bit unsigned integer in little endian */ +static void U64TO8(unsigned char *p, u64 v) +{ + p[0] = (unsigned char)((v) & 0xff); + p[1] = (unsigned char)((v >> 8) & 0xff); + p[2] = (unsigned char)((v >> 16) & 0xff); + p[3] = (unsigned char)((v >> 24) & 0xff); + p[4] = (unsigned char)((v >> 32) & 0xff); + p[5] = (unsigned char)((v >> 40) & 0xff); + p[6] = (unsigned char)((v >> 48) & 0xff); + p[7] = (unsigned char)((v >> 56) & 0xff); +} + +static void poly1305_init(void *ctx, const unsigned char key[16]) +{ + poly1305_internal *st = (poly1305_internal *) ctx; + + /* h = 0 */ + st->h[0] = 0; + st->h[1] = 0; + st->h[2] = 0; + + /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ + st->r[0] = U8TOU64(&key[0]) & 0x0ffffffc0fffffff; + st->r[1] = U8TOU64(&key[8]) & 0x0ffffffc0ffffffc; +} + +static void +poly1305_blocks(void *ctx, const unsigned char *inp, size_t len, u32 padbit) +{ + poly1305_internal *st = (poly1305_internal *)ctx; + u64 r0, r1; + u64 s1; + u64 h0, h1, h2, c; + u128 d0, d1; + + r0 = st->r[0]; + r1 = st->r[1]; + + s1 = r1 + (r1 >> 2); + + h0 = st->h[0]; + h1 = st->h[1]; + h2 = st->h[2]; + + while (len >= POLY1305_BLOCK_SIZE) { + /* h += m[i] */ + h0 = (u64)(d0 = (u128)h0 + U8TOU64(inp + 0)); + h1 = (u64)(d1 = (u128)h1 + (d0 >> 64) + U8TOU64(inp + 8)); + /* + * padbit can be zero only when original len was + * POLY1306_BLOCK_SIZE, but we don't check + */ + h2 += (u64)(d1 >> 64) + padbit; + + /* h *= r "%" p, where "%" stands for "partial remainder" */ + d0 = ((u128)h0 * r0) + + ((u128)h1 * s1); + d1 = ((u128)h0 * r1) + + ((u128)h1 * r0) + + (h2 * s1); + h2 = (h2 * r0); + + /* last reduction step: */ + /* a) h2:h0 = h2<<128 + d1<<64 + d0 */ + h0 = (u64)d0; + h1 = (u64)(d1 += d0 >> 64); + h2 += (u64)(d1 >> 64); + /* b) (h2:h0 += (h2:h0>>130) * 5) %= 2^130 */ + c = (h2 >> 2) + (h2 & ~3UL); + h2 &= 3; + h0 += c; + h1 += (c = CONSTANT_TIME_CARRY(h0,c)); + h2 += CONSTANT_TIME_CARRY(h1,c); + /* + * Occasional overflows to 3rd bit of h2 are taken care of + * "naturally". If after this point we end up at the top of + * this loop, then the overflow bit will be accounted for + * in next iteration. If we end up in poly1305_emit, then + * comparison to modulus below will still count as "carry + * into 131st bit", so that properly reduced value will be + * picked in conditional move. + */ + + inp += POLY1305_BLOCK_SIZE; + len -= POLY1305_BLOCK_SIZE; + } + + st->h[0] = h0; + st->h[1] = h1; + st->h[2] = h2; +} + +static void poly1305_emit(void *ctx, unsigned char mac[16], + const u32 nonce[4]) +{ + poly1305_internal *st = (poly1305_internal *) ctx; + u64 h0, h1, h2; + u64 g0, g1, g2; + u128 t; + u64 mask; + + h0 = st->h[0]; + h1 = st->h[1]; + h2 = st->h[2]; + + /* compare to modulus by computing h + -p */ + g0 = (u64)(t = (u128)h0 + 5); + g1 = (u64)(t = (u128)h1 + (t >> 64)); + g2 = h2 + (u64)(t >> 64); + + /* if there was carry into 131st bit, h1:h0 = g1:g0 */ + mask = 0 - (g2 >> 2); + g0 &= mask; + g1 &= mask; + mask = ~mask; + h0 = (h0 & mask) | g0; + h1 = (h1 & mask) | g1; + + /* mac = (h + nonce) % (2^128) */ + h0 = (u64)(t = (u128)h0 + nonce[0] + ((u64)nonce[1]<<32)); + h1 = (u64)(t = (u128)h1 + nonce[2] + ((u64)nonce[3]<<32) + (t >> 64)); + + U64TO8(mac + 0, h0); + U64TO8(mac + 8, h1); +} + +# else + +# if defined(_WIN32) && !defined(__MINGW32__) +typedef unsigned __int64 u64; +# elif defined(__arch64__) +typedef unsigned long u64; +# else +typedef unsigned long long u64; +# endif + +typedef struct { + u32 h[5]; + u32 r[4]; +} poly1305_internal; + +/* store a 32-bit unsigned integer in little endian */ +static void U32TO8(unsigned char *p, unsigned int v) +{ + p[0] = (unsigned char)((v) & 0xff); + p[1] = (unsigned char)((v >> 8) & 0xff); + p[2] = (unsigned char)((v >> 16) & 0xff); + p[3] = (unsigned char)((v >> 24) & 0xff); +} + +static void poly1305_init(void *ctx, const unsigned char key[16]) +{ + poly1305_internal *st = (poly1305_internal *) ctx; + + /* h = 0 */ + st->h[0] = 0; + st->h[1] = 0; + st->h[2] = 0; + st->h[3] = 0; + st->h[4] = 0; + + /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ + st->r[0] = U8TOU32(&key[0]) & 0x0fffffff; + st->r[1] = U8TOU32(&key[4]) & 0x0ffffffc; + st->r[2] = U8TOU32(&key[8]) & 0x0ffffffc; + st->r[3] = U8TOU32(&key[12]) & 0x0ffffffc; +} + +static void +poly1305_blocks(void *ctx, const unsigned char *inp, size_t len, u32 padbit) +{ + poly1305_internal *st = (poly1305_internal *)ctx; + u32 r0, r1, r2, r3; + u32 s1, s2, s3; + u32 h0, h1, h2, h3, h4, c; + u64 d0, d1, d2, d3; + + r0 = st->r[0]; + r1 = st->r[1]; + r2 = st->r[2]; + r3 = st->r[3]; + + s1 = r1 + (r1 >> 2); + s2 = r2 + (r2 >> 2); + s3 = r3 + (r3 >> 2); + + h0 = st->h[0]; + h1 = st->h[1]; + h2 = st->h[2]; + h3 = st->h[3]; + h4 = st->h[4]; + + while (len >= POLY1305_BLOCK_SIZE) { + /* h += m[i] */ + h0 = (u32)(d0 = (u64)h0 + U8TOU32(inp + 0)); + h1 = (u32)(d1 = (u64)h1 + (d0 >> 32) + U8TOU32(inp + 4)); + h2 = (u32)(d2 = (u64)h2 + (d1 >> 32) + U8TOU32(inp + 8)); + h3 = (u32)(d3 = (u64)h3 + (d2 >> 32) + U8TOU32(inp + 12)); + h4 += (u32)(d3 >> 32) + padbit; + + /* h *= r "%" p, where "%" stands for "partial remainder" */ + d0 = ((u64)h0 * r0) + + ((u64)h1 * s3) + + ((u64)h2 * s2) + + ((u64)h3 * s1); + d1 = ((u64)h0 * r1) + + ((u64)h1 * r0) + + ((u64)h2 * s3) + + ((u64)h3 * s2) + + (h4 * s1); + d2 = ((u64)h0 * r2) + + ((u64)h1 * r1) + + ((u64)h2 * r0) + + ((u64)h3 * s3) + + (h4 * s2); + d3 = ((u64)h0 * r3) + + ((u64)h1 * r2) + + ((u64)h2 * r1) + + ((u64)h3 * r0) + + (h4 * s3); + h4 = (h4 * r0); + + /* last reduction step: */ + /* a) h4:h0 = h4<<128 + d3<<96 + d2<<64 + d1<<32 + d0 */ + h0 = (u32)d0; + h1 = (u32)(d1 += d0 >> 32); + h2 = (u32)(d2 += d1 >> 32); + h3 = (u32)(d3 += d2 >> 32); + h4 += (u32)(d3 >> 32); + /* b) (h4:h0 += (h4:h0>>130) * 5) %= 2^130 */ + c = (h4 >> 2) + (h4 & ~3U); + h4 &= 3; + h0 += c; + h1 += (c = CONSTANT_TIME_CARRY(h0,c)); + h2 += (c = CONSTANT_TIME_CARRY(h1,c)); + h3 += (c = CONSTANT_TIME_CARRY(h2,c)); + h4 += CONSTANT_TIME_CARRY(h3,c); + /* + * Occasional overflows to 3rd bit of h4 are taken care of + * "naturally". If after this point we end up at the top of + * this loop, then the overflow bit will be accounted for + * in next iteration. If we end up in poly1305_emit, then + * comparison to modulus below will still count as "carry + * into 131st bit", so that properly reduced value will be + * picked in conditional move. + */ + + inp += POLY1305_BLOCK_SIZE; + len -= POLY1305_BLOCK_SIZE; + } + + st->h[0] = h0; + st->h[1] = h1; + st->h[2] = h2; + st->h[3] = h3; + st->h[4] = h4; +} + +static void poly1305_emit(void *ctx, unsigned char mac[16], + const u32 nonce[4]) +{ + poly1305_internal *st = (poly1305_internal *) ctx; + u32 h0, h1, h2, h3, h4; + u32 g0, g1, g2, g3, g4; + u64 t; + u32 mask; + + h0 = st->h[0]; + h1 = st->h[1]; + h2 = st->h[2]; + h3 = st->h[3]; + h4 = st->h[4]; + + /* compare to modulus by computing h + -p */ + g0 = (u32)(t = (u64)h0 + 5); + g1 = (u32)(t = (u64)h1 + (t >> 32)); + g2 = (u32)(t = (u64)h2 + (t >> 32)); + g3 = (u32)(t = (u64)h3 + (t >> 32)); + g4 = h4 + (u32)(t >> 32); + + /* if there was carry into 131st bit, h3:h0 = g3:g0 */ + mask = 0 - (g4 >> 2); + g0 &= mask; + g1 &= mask; + g2 &= mask; + g3 &= mask; + mask = ~mask; + h0 = (h0 & mask) | g0; + h1 = (h1 & mask) | g1; + h2 = (h2 & mask) | g2; + h3 = (h3 & mask) | g3; + + /* mac = (h + nonce) % (2^128) */ + h0 = (u32)(t = (u64)h0 + nonce[0]); + h1 = (u32)(t = (u64)h1 + (t >> 32) + nonce[1]); + h2 = (u32)(t = (u64)h2 + (t >> 32) + nonce[2]); + h3 = (u32)(t = (u64)h3 + (t >> 32) + nonce[3]); + + U32TO8(mac + 0, h0); + U32TO8(mac + 4, h1); + U32TO8(mac + 8, h2); + U32TO8(mac + 12, h3); +} +# endif +#else +int poly1305_init(void *ctx, const unsigned char key[16], void *func); +void poly1305_blocks(void *ctx, const unsigned char *inp, size_t len, + unsigned int padbit); +void poly1305_emit(void *ctx, unsigned char mac[16], + const unsigned int nonce[4]); +#endif + +void Poly1305_Init(POLY1305 *ctx, const unsigned char key[32]) +{ + ctx->nonce[0] = U8TOU32(&key[16]); + ctx->nonce[1] = U8TOU32(&key[20]); + ctx->nonce[2] = U8TOU32(&key[24]); + ctx->nonce[3] = U8TOU32(&key[28]); + +#ifndef POLY1305_ASM + poly1305_init(ctx->opaque, key); +#else + /* + * Unlike reference poly1305_init assembly counterpart is expected + * to return a value: non-zero if it initializes ctx->func, and zero + * otherwise. Latter is to simplify assembly in cases when there no + * multiple code paths to switch between. + */ + if (!poly1305_init(ctx->opaque, key, &ctx->func)) { + ctx->func.blocks = poly1305_blocks; + ctx->func.emit = poly1305_emit; + } +#endif + + ctx->num = 0; + +} + +#ifdef POLY1305_ASM +/* + * This "eclipses" poly1305_blocks and poly1305_emit, but it's + * conscious choice imposed by -Wshadow compiler warnings. + */ +# define poly1305_blocks (*poly1305_blocks_p) +# define poly1305_emit (*poly1305_emit_p) +#endif + +void Poly1305_Update(POLY1305 *ctx, const unsigned char *inp, size_t len) +{ +#ifdef POLY1305_ASM + /* + * As documented, poly1305_blocks is never called with input + * longer than single block and padbit argument set to 0. This + * property is fluently used in assembly modules to optimize + * padbit handling on loop boundary. + */ + poly1305_blocks_f poly1305_blocks_p = ctx->func.blocks; +#endif + size_t rem, num; + + if ((num = ctx->num)) { + rem = POLY1305_BLOCK_SIZE - num; + if (len >= rem) { + memcpy(ctx->data + num, inp, rem); + poly1305_blocks(ctx->opaque, ctx->data, POLY1305_BLOCK_SIZE, 1); + inp += rem; + len -= rem; + } else { + /* Still not enough data to process a block. */ + memcpy(ctx->data + num, inp, len); + ctx->num = num + len; + return; + } + } + + rem = len % POLY1305_BLOCK_SIZE; + len -= rem; + + if (len >= POLY1305_BLOCK_SIZE) { + poly1305_blocks(ctx->opaque, inp, len, 1); + inp += len; + } + + if (rem) + memcpy(ctx->data, inp, rem); + + ctx->num = rem; +} + +void Poly1305_Final(POLY1305 *ctx, unsigned char mac[16]) +{ +#ifdef POLY1305_ASM + poly1305_blocks_f poly1305_blocks_p = ctx->func.blocks; + poly1305_emit_f poly1305_emit_p = ctx->func.emit; +#endif + size_t num; + + if ((num = ctx->num)) { + ctx->data[num++] = 1; /* pad bit */ + while (num < POLY1305_BLOCK_SIZE) + ctx->data[num++] = 0; + poly1305_blocks(ctx->opaque, ctx->data, POLY1305_BLOCK_SIZE, 0); + } + + poly1305_emit(ctx->opaque, mac, ctx->nonce); + + /* zero out the state */ + OPENSSL_cleanse(ctx, sizeof(*ctx)); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/poly1305_ameth.c b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/poly1305_ameth.c new file mode 100644 index 000000000..033ee8cd9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/poly1305_ameth.c @@ -0,0 +1,122 @@ +/* + * Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include "internal/asn1_int.h" +#include "internal/poly1305.h" +#include "poly1305_local.h" +#include "internal/evp_int.h" + +/* + * POLY1305 "ASN1" method. This is just here to indicate the maximum + * POLY1305 output length and to free up a POLY1305 key. + */ + +static int poly1305_size(const EVP_PKEY *pkey) +{ + return POLY1305_DIGEST_SIZE; +} + +static void poly1305_key_free(EVP_PKEY *pkey) +{ + ASN1_OCTET_STRING *os = EVP_PKEY_get0(pkey); + if (os != NULL) { + if (os->data != NULL) + OPENSSL_cleanse(os->data, os->length); + ASN1_OCTET_STRING_free(os); + } +} + +static int poly1305_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) +{ + /* nothing, (including ASN1_PKEY_CTRL_DEFAULT_MD_NID), is supported */ + return -2; +} + +static int poly1305_pkey_public_cmp(const EVP_PKEY *a, const EVP_PKEY *b) +{ + return ASN1_OCTET_STRING_cmp(EVP_PKEY_get0(a), EVP_PKEY_get0(b)); +} + +static int poly1305_set_priv_key(EVP_PKEY *pkey, const unsigned char *priv, + size_t len) +{ + ASN1_OCTET_STRING *os; + + if (pkey->pkey.ptr != NULL || len != POLY1305_KEY_SIZE) + return 0; + + os = ASN1_OCTET_STRING_new(); + if (os == NULL) + return 0; + + if (!ASN1_OCTET_STRING_set(os, priv, len)) { + ASN1_OCTET_STRING_free(os); + return 0; + } + + pkey->pkey.ptr = os; + return 1; +} + +static int poly1305_get_priv_key(const EVP_PKEY *pkey, unsigned char *priv, + size_t *len) +{ + ASN1_OCTET_STRING *os = (ASN1_OCTET_STRING *)pkey->pkey.ptr; + + if (priv == NULL) { + *len = POLY1305_KEY_SIZE; + return 1; + } + + if (os == NULL || *len < POLY1305_KEY_SIZE) + return 0; + + memcpy(priv, ASN1_STRING_get0_data(os), ASN1_STRING_length(os)); + *len = POLY1305_KEY_SIZE; + + return 1; +} + +const EVP_PKEY_ASN1_METHOD poly1305_asn1_meth = { + EVP_PKEY_POLY1305, + EVP_PKEY_POLY1305, + 0, + + "POLY1305", + "OpenSSL POLY1305 method", + + 0, 0, poly1305_pkey_public_cmp, 0, + + 0, 0, 0, + + poly1305_size, + 0, 0, + 0, 0, 0, 0, 0, 0, 0, + + poly1305_key_free, + poly1305_pkey_ctrl, + NULL, + NULL, + + NULL, + NULL, + NULL, + + NULL, + NULL, + NULL, + + poly1305_set_priv_key, + NULL, + poly1305_get_priv_key, + NULL, +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/poly1305_base2_44.c b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/poly1305_base2_44.c new file mode 100644 index 000000000..b6313d01b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/poly1305_base2_44.c @@ -0,0 +1,171 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This module is meant to be used as template for base 2^44 assembly + * implementation[s]. On side note compiler-generated code is not + * slower than compiler-generated base 2^64 code on [high-end] x86_64, + * even though amount of multiplications is 50% higher. Go figure... + */ +#include + +typedef unsigned char u8; +typedef unsigned int u32; +typedef unsigned long u64; +typedef unsigned __int128 u128; + +typedef struct { + u64 h[3]; + u64 s[2]; + u64 r[3]; +} poly1305_internal; + +#define POLY1305_BLOCK_SIZE 16 + +/* pick 64-bit unsigned integer in little endian order */ +static u64 U8TOU64(const unsigned char *p) +{ + return (((u64)(p[0] & 0xff)) | + ((u64)(p[1] & 0xff) << 8) | + ((u64)(p[2] & 0xff) << 16) | + ((u64)(p[3] & 0xff) << 24) | + ((u64)(p[4] & 0xff) << 32) | + ((u64)(p[5] & 0xff) << 40) | + ((u64)(p[6] & 0xff) << 48) | + ((u64)(p[7] & 0xff) << 56)); +} + +/* store a 64-bit unsigned integer in little endian */ +static void U64TO8(unsigned char *p, u64 v) +{ + p[0] = (unsigned char)((v) & 0xff); + p[1] = (unsigned char)((v >> 8) & 0xff); + p[2] = (unsigned char)((v >> 16) & 0xff); + p[3] = (unsigned char)((v >> 24) & 0xff); + p[4] = (unsigned char)((v >> 32) & 0xff); + p[5] = (unsigned char)((v >> 40) & 0xff); + p[6] = (unsigned char)((v >> 48) & 0xff); + p[7] = (unsigned char)((v >> 56) & 0xff); +} + +int poly1305_init(void *ctx, const unsigned char key[16]) +{ + poly1305_internal *st = (poly1305_internal *)ctx; + u64 r0, r1; + + /* h = 0 */ + st->h[0] = 0; + st->h[1] = 0; + st->h[2] = 0; + + r0 = U8TOU64(&key[0]) & 0x0ffffffc0fffffff; + r1 = U8TOU64(&key[8]) & 0x0ffffffc0ffffffc; + + /* break r1:r0 to three 44-bit digits, masks are 1<<44-1 */ + st->r[0] = r0 & 0x0fffffffffff; + st->r[1] = ((r0 >> 44) | (r1 << 20)) & 0x0fffffffffff; + st->r[2] = (r1 >> 24); + + st->s[0] = (st->r[1] + (st->r[1] << 2)) << 2; + st->s[1] = (st->r[2] + (st->r[2] << 2)) << 2; + + return 0; +} + +void poly1305_blocks(void *ctx, const unsigned char *inp, size_t len, + u32 padbit) +{ + poly1305_internal *st = (poly1305_internal *)ctx; + u64 r0, r1, r2; + u64 s1, s2; + u64 h0, h1, h2, c; + u128 d0, d1, d2; + u64 pad = (u64)padbit << 40; + + r0 = st->r[0]; + r1 = st->r[1]; + r2 = st->r[2]; + + s1 = st->s[0]; + s2 = st->s[1]; + + h0 = st->h[0]; + h1 = st->h[1]; + h2 = st->h[2]; + + while (len >= POLY1305_BLOCK_SIZE) { + u64 m0, m1; + + m0 = U8TOU64(inp + 0); + m1 = U8TOU64(inp + 8); + + /* h += m[i], m[i] is broken to 44-bit digits */ + h0 += m0 & 0x0fffffffffff; + h1 += ((m0 >> 44) | (m1 << 20)) & 0x0fffffffffff; + h2 += (m1 >> 24) + pad; + + /* h *= r "%" p, where "%" stands for "partial remainder" */ + d0 = ((u128)h0 * r0) + ((u128)h1 * s2) + ((u128)h2 * s1); + d1 = ((u128)h0 * r1) + ((u128)h1 * r0) + ((u128)h2 * s2); + d2 = ((u128)h0 * r2) + ((u128)h1 * r1) + ((u128)h2 * r0); + + /* "lazy" reduction step */ + h0 = (u64)d0 & 0x0fffffffffff; + h1 = (u64)(d1 += (u64)(d0 >> 44)) & 0x0fffffffffff; + h2 = (u64)(d2 += (u64)(d1 >> 44)) & 0x03ffffffffff; /* last 42 bits */ + + c = (d2 >> 42); + h0 += c + (c << 2); + + inp += POLY1305_BLOCK_SIZE; + len -= POLY1305_BLOCK_SIZE; + } + + st->h[0] = h0; + st->h[1] = h1; + st->h[2] = h2; +} + +void poly1305_emit(void *ctx, unsigned char mac[16], const u32 nonce[4]) +{ + poly1305_internal *st = (poly1305_internal *) ctx; + u64 h0, h1, h2; + u64 g0, g1, g2; + u128 t; + u64 mask; + + h0 = st->h[0]; + h1 = st->h[1]; + h2 = st->h[2]; + + /* after "lazy" reduction, convert 44+bit digits to 64-bit ones */ + h0 = (u64)(t = (u128)h0 + (h1 << 44)); h1 >>= 20; + h1 = (u64)(t = (u128)h1 + (h2 << 24) + (t >> 64)); h2 >>= 40; + h2 += (u64)(t >> 64); + + /* compare to modulus by computing h + -p */ + g0 = (u64)(t = (u128)h0 + 5); + g1 = (u64)(t = (u128)h1 + (t >> 64)); + g2 = h2 + (u64)(t >> 64); + + /* if there was carry into 131st bit, h1:h0 = g1:g0 */ + mask = 0 - (g2 >> 2); + g0 &= mask; + g1 &= mask; + mask = ~mask; + h0 = (h0 & mask) | g0; + h1 = (h1 & mask) | g1; + + /* mac = (h + nonce) % (2^128) */ + h0 = (u64)(t = (u128)h0 + nonce[0] + ((u64)nonce[1]<<32)); + h1 = (u64)(t = (u128)h1 + nonce[2] + ((u64)nonce[3]<<32) + (t >> 64)); + + U64TO8(mac + 0, h0); + U64TO8(mac + 8, h1); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/poly1305_ieee754.c b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/poly1305_ieee754.c new file mode 100644 index 000000000..7cfd96864 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/poly1305_ieee754.c @@ -0,0 +1,488 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This module is meant to be used as template for non-x87 floating- + * point assembly modules. The template itself is x86_64-specific + * though, as it was debugged on x86_64. So that implementor would + * have to recognize platform-specific parts, UxTOy and inline asm, + * and act accordingly. + * + * Huh? x86_64-specific code as template for non-x87? Note seven, which + * is not a typo, but reference to 80-bit precision. This module on the + * other hand relies on 64-bit precision operations, which are default + * for x86_64 code. And since we are at it, just for sense of it, + * large-block performance in cycles per processed byte for *this* code + * is: + * gcc-4.8 icc-15.0 clang-3.4(*) + * + * Westmere 4.96 5.09 4.37 + * Sandy Bridge 4.95 4.90 4.17 + * Haswell 4.92 4.87 3.78 + * Bulldozer 4.67 4.49 4.68 + * VIA Nano 7.07 7.05 5.98 + * Silvermont 10.6 9.61 12.6 + * + * (*) clang managed to discover parallelism and deployed SIMD; + * + * And for range of other platforms with unspecified gcc versions: + * + * Freescale e300 12.5 + * PPC74x0 10.8 + * POWER6 4.92 + * POWER7 4.50 + * POWER8 4.10 + * + * z10 11.2 + * z196+ 7.30 + * + * UltraSPARC III 16.0 + * SPARC T4 16.1 + */ + +#if !(defined(__GNUC__) && __GNUC__>=2) +# error "this is gcc-specific template" +#endif + +#include + +typedef unsigned char u8; +typedef unsigned int u32; +typedef unsigned long long u64; +typedef union { double d; u64 u; } elem64; + +#define TWO(p) ((double)(1ULL<<(p))) +#define TWO0 TWO(0) +#define TWO32 TWO(32) +#define TWO64 (TWO32*TWO(32)) +#define TWO96 (TWO64*TWO(32)) +#define TWO130 (TWO96*TWO(34)) + +#define EXP(p) ((1023ULL+(p))<<52) + +#if defined(__x86_64__) || (defined(__PPC__) && defined(__LITTLE_ENDIAN__)) +# define U8TOU32(p) (*(const u32 *)(p)) +# define U32TO8(p,v) (*(u32 *)(p) = (v)) +#elif defined(__PPC__) +# define U8TOU32(p) ({u32 ret; asm ("lwbrx %0,0,%1":"=r"(ret):"b"(p)); ret; }) +# define U32TO8(p,v) asm ("stwbrx %0,0,%1"::"r"(v),"b"(p):"memory") +#elif defined(__s390x__) +# define U8TOU32(p) ({u32 ret; asm ("lrv %0,%1":"=d"(ret):"m"(*(u32 *)(p))); ret; }) +# define U32TO8(p,v) asm ("strv %1,%0":"=m"(*(u32 *)(p)):"d"(v)) +#endif + +#ifndef U8TOU32 +# define U8TOU32(p) ((u32)(p)[0] | (u32)(p)[1]<<8 | \ + (u32)(p)[2]<<16 | (u32)(p)[3]<<24 ) +#endif +#ifndef U32TO8 +# define U32TO8(p,v) ((p)[0] = (u8)(v), (p)[1] = (u8)((v)>>8), \ + (p)[2] = (u8)((v)>>16), (p)[3] = (u8)((v)>>24) ) +#endif + +typedef struct { + elem64 h[4]; + double r[8]; + double s[6]; +} poly1305_internal; + +/* "round toward zero (truncate), mask all exceptions" */ +#if defined(__x86_64__) +static const u32 mxcsr = 0x7f80; +#elif defined(__PPC__) +static const u64 one = 1; +#elif defined(__s390x__) +static const u32 fpc = 1; +#elif defined(__sparc__) +static const u64 fsr = 1ULL<<30; +#elif defined(__mips__) +static const u32 fcsr = 1; +#else +#error "unrecognized platform" +#endif + +int poly1305_init(void *ctx, const unsigned char key[16]) +{ + poly1305_internal *st = (poly1305_internal *) ctx; + elem64 r0, r1, r2, r3; + + /* h = 0, biased */ +#if 0 + st->h[0].d = TWO(52)*TWO0; + st->h[1].d = TWO(52)*TWO32; + st->h[2].d = TWO(52)*TWO64; + st->h[3].d = TWO(52)*TWO96; +#else + st->h[0].u = EXP(52+0); + st->h[1].u = EXP(52+32); + st->h[2].u = EXP(52+64); + st->h[3].u = EXP(52+96); +#endif + + if (key) { + /* + * set "truncate" rounding mode + */ +#if defined(__x86_64__) + u32 mxcsr_orig; + + asm volatile ("stmxcsr %0":"=m"(mxcsr_orig)); + asm volatile ("ldmxcsr %0"::"m"(mxcsr)); +#elif defined(__PPC__) + double fpscr_orig, fpscr = *(double *)&one; + + asm volatile ("mffs %0":"=f"(fpscr_orig)); + asm volatile ("mtfsf 255,%0"::"f"(fpscr)); +#elif defined(__s390x__) + u32 fpc_orig; + + asm volatile ("stfpc %0":"=m"(fpc_orig)); + asm volatile ("lfpc %0"::"m"(fpc)); +#elif defined(__sparc__) + u64 fsr_orig; + + asm volatile ("stx %%fsr,%0":"=m"(fsr_orig)); + asm volatile ("ldx %0,%%fsr"::"m"(fsr)); +#elif defined(__mips__) + u32 fcsr_orig; + + asm volatile ("cfc1 %0,$31":"=r"(fcsr_orig)); + asm volatile ("ctc1 %0,$31"::"r"(fcsr)); +#endif + + /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ + r0.u = EXP(52+0) | (U8TOU32(&key[0]) & 0x0fffffff); + r1.u = EXP(52+32) | (U8TOU32(&key[4]) & 0x0ffffffc); + r2.u = EXP(52+64) | (U8TOU32(&key[8]) & 0x0ffffffc); + r3.u = EXP(52+96) | (U8TOU32(&key[12]) & 0x0ffffffc); + + st->r[0] = r0.d - TWO(52)*TWO0; + st->r[2] = r1.d - TWO(52)*TWO32; + st->r[4] = r2.d - TWO(52)*TWO64; + st->r[6] = r3.d - TWO(52)*TWO96; + + st->s[0] = st->r[2] * (5.0/TWO130); + st->s[2] = st->r[4] * (5.0/TWO130); + st->s[4] = st->r[6] * (5.0/TWO130); + + /* + * base 2^32 -> base 2^16 + */ + st->r[1] = (st->r[0] + TWO(52)*TWO(16)*TWO0) - + TWO(52)*TWO(16)*TWO0; + st->r[0] -= st->r[1]; + + st->r[3] = (st->r[2] + TWO(52)*TWO(16)*TWO32) - + TWO(52)*TWO(16)*TWO32; + st->r[2] -= st->r[3]; + + st->r[5] = (st->r[4] + TWO(52)*TWO(16)*TWO64) - + TWO(52)*TWO(16)*TWO64; + st->r[4] -= st->r[5]; + + st->r[7] = (st->r[6] + TWO(52)*TWO(16)*TWO96) - + TWO(52)*TWO(16)*TWO96; + st->r[6] -= st->r[7]; + + st->s[1] = (st->s[0] + TWO(52)*TWO(16)*TWO0/TWO96) - + TWO(52)*TWO(16)*TWO0/TWO96; + st->s[0] -= st->s[1]; + + st->s[3] = (st->s[2] + TWO(52)*TWO(16)*TWO32/TWO96) - + TWO(52)*TWO(16)*TWO32/TWO96; + st->s[2] -= st->s[3]; + + st->s[5] = (st->s[4] + TWO(52)*TWO(16)*TWO64/TWO96) - + TWO(52)*TWO(16)*TWO64/TWO96; + st->s[4] -= st->s[5]; + + /* + * restore original FPU control register + */ +#if defined(__x86_64__) + asm volatile ("ldmxcsr %0"::"m"(mxcsr_orig)); +#elif defined(__PPC__) + asm volatile ("mtfsf 255,%0"::"f"(fpscr_orig)); +#elif defined(__s390x__) + asm volatile ("lfpc %0"::"m"(fpc_orig)); +#elif defined(__sparc__) + asm volatile ("ldx %0,%%fsr"::"m"(fsr_orig)); +#elif defined(__mips__) + asm volatile ("ctc1 %0,$31"::"r"(fcsr_orig)); +#endif + } + + return 0; +} + +void poly1305_blocks(void *ctx, const unsigned char *inp, size_t len, + int padbit) +{ + poly1305_internal *st = (poly1305_internal *)ctx; + elem64 in0, in1, in2, in3; + u64 pad = (u64)padbit<<32; + + double x0, x1, x2, x3; + double h0lo, h0hi, h1lo, h1hi, h2lo, h2hi, h3lo, h3hi; + double c0lo, c0hi, c1lo, c1hi, c2lo, c2hi, c3lo, c3hi; + + const double r0lo = st->r[0]; + const double r0hi = st->r[1]; + const double r1lo = st->r[2]; + const double r1hi = st->r[3]; + const double r2lo = st->r[4]; + const double r2hi = st->r[5]; + const double r3lo = st->r[6]; + const double r3hi = st->r[7]; + + const double s1lo = st->s[0]; + const double s1hi = st->s[1]; + const double s2lo = st->s[2]; + const double s2hi = st->s[3]; + const double s3lo = st->s[4]; + const double s3hi = st->s[5]; + + /* + * set "truncate" rounding mode + */ +#if defined(__x86_64__) + u32 mxcsr_orig; + + asm volatile ("stmxcsr %0":"=m"(mxcsr_orig)); + asm volatile ("ldmxcsr %0"::"m"(mxcsr)); +#elif defined(__PPC__) + double fpscr_orig, fpscr = *(double *)&one; + + asm volatile ("mffs %0":"=f"(fpscr_orig)); + asm volatile ("mtfsf 255,%0"::"f"(fpscr)); +#elif defined(__s390x__) + u32 fpc_orig; + + asm volatile ("stfpc %0":"=m"(fpc_orig)); + asm volatile ("lfpc %0"::"m"(fpc)); +#elif defined(__sparc__) + u64 fsr_orig; + + asm volatile ("stx %%fsr,%0":"=m"(fsr_orig)); + asm volatile ("ldx %0,%%fsr"::"m"(fsr)); +#elif defined(__mips__) + u32 fcsr_orig; + + asm volatile ("cfc1 %0,$31":"=r"(fcsr_orig)); + asm volatile ("ctc1 %0,$31"::"r"(fcsr)); +#endif + + /* + * load base 2^32 and de-bias + */ + h0lo = st->h[0].d - TWO(52)*TWO0; + h1lo = st->h[1].d - TWO(52)*TWO32; + h2lo = st->h[2].d - TWO(52)*TWO64; + h3lo = st->h[3].d - TWO(52)*TWO96; + +#ifdef __clang__ + h0hi = 0; + h1hi = 0; + h2hi = 0; + h3hi = 0; +#else + in0.u = EXP(52+0) | U8TOU32(&inp[0]); + in1.u = EXP(52+32) | U8TOU32(&inp[4]); + in2.u = EXP(52+64) | U8TOU32(&inp[8]); + in3.u = EXP(52+96) | U8TOU32(&inp[12]) | pad; + + x0 = in0.d - TWO(52)*TWO0; + x1 = in1.d - TWO(52)*TWO32; + x2 = in2.d - TWO(52)*TWO64; + x3 = in3.d - TWO(52)*TWO96; + + x0 += h0lo; + x1 += h1lo; + x2 += h2lo; + x3 += h3lo; + + goto fast_entry; +#endif + + do { + in0.u = EXP(52+0) | U8TOU32(&inp[0]); + in1.u = EXP(52+32) | U8TOU32(&inp[4]); + in2.u = EXP(52+64) | U8TOU32(&inp[8]); + in3.u = EXP(52+96) | U8TOU32(&inp[12]) | pad; + + x0 = in0.d - TWO(52)*TWO0; + x1 = in1.d - TWO(52)*TWO32; + x2 = in2.d - TWO(52)*TWO64; + x3 = in3.d - TWO(52)*TWO96; + + /* + * note that there are multiple ways to accumulate input, e.g. + * one can as well accumulate to h0lo-h1lo-h1hi-h2hi... + */ + h0lo += x0; + h0hi += x1; + h2lo += x2; + h2hi += x3; + + /* + * carries that cross 32n-bit (and 130-bit) boundaries + */ + c0lo = (h0lo + TWO(52)*TWO32) - TWO(52)*TWO32; + c1lo = (h1lo + TWO(52)*TWO64) - TWO(52)*TWO64; + c2lo = (h2lo + TWO(52)*TWO96) - TWO(52)*TWO96; + c3lo = (h3lo + TWO(52)*TWO130) - TWO(52)*TWO130; + + c0hi = (h0hi + TWO(52)*TWO32) - TWO(52)*TWO32; + c1hi = (h1hi + TWO(52)*TWO64) - TWO(52)*TWO64; + c2hi = (h2hi + TWO(52)*TWO96) - TWO(52)*TWO96; + c3hi = (h3hi + TWO(52)*TWO130) - TWO(52)*TWO130; + + /* + * base 2^48 -> base 2^32 with last reduction step + */ + x1 = (h1lo - c1lo) + c0lo; + x2 = (h2lo - c2lo) + c1lo; + x3 = (h3lo - c3lo) + c2lo; + x0 = (h0lo - c0lo) + c3lo * (5.0/TWO130); + + x1 += (h1hi - c1hi) + c0hi; + x2 += (h2hi - c2hi) + c1hi; + x3 += (h3hi - c3hi) + c2hi; + x0 += (h0hi - c0hi) + c3hi * (5.0/TWO130); + +#ifndef __clang__ + fast_entry: +#endif + /* + * base 2^32 * base 2^16 = base 2^48 + */ + h0lo = s3lo * x1 + s2lo * x2 + s1lo * x3 + r0lo * x0; + h1lo = r0lo * x1 + s3lo * x2 + s2lo * x3 + r1lo * x0; + h2lo = r1lo * x1 + r0lo * x2 + s3lo * x3 + r2lo * x0; + h3lo = r2lo * x1 + r1lo * x2 + r0lo * x3 + r3lo * x0; + + h0hi = s3hi * x1 + s2hi * x2 + s1hi * x3 + r0hi * x0; + h1hi = r0hi * x1 + s3hi * x2 + s2hi * x3 + r1hi * x0; + h2hi = r1hi * x1 + r0hi * x2 + s3hi * x3 + r2hi * x0; + h3hi = r2hi * x1 + r1hi * x2 + r0hi * x3 + r3hi * x0; + + inp += 16; + len -= 16; + + } while (len >= 16); + + /* + * carries that cross 32n-bit (and 130-bit) boundaries + */ + c0lo = (h0lo + TWO(52)*TWO32) - TWO(52)*TWO32; + c1lo = (h1lo + TWO(52)*TWO64) - TWO(52)*TWO64; + c2lo = (h2lo + TWO(52)*TWO96) - TWO(52)*TWO96; + c3lo = (h3lo + TWO(52)*TWO130) - TWO(52)*TWO130; + + c0hi = (h0hi + TWO(52)*TWO32) - TWO(52)*TWO32; + c1hi = (h1hi + TWO(52)*TWO64) - TWO(52)*TWO64; + c2hi = (h2hi + TWO(52)*TWO96) - TWO(52)*TWO96; + c3hi = (h3hi + TWO(52)*TWO130) - TWO(52)*TWO130; + + /* + * base 2^48 -> base 2^32 with last reduction step + */ + x1 = (h1lo - c1lo) + c0lo; + x2 = (h2lo - c2lo) + c1lo; + x3 = (h3lo - c3lo) + c2lo; + x0 = (h0lo - c0lo) + c3lo * (5.0/TWO130); + + x1 += (h1hi - c1hi) + c0hi; + x2 += (h2hi - c2hi) + c1hi; + x3 += (h3hi - c3hi) + c2hi; + x0 += (h0hi - c0hi) + c3hi * (5.0/TWO130); + + /* + * store base 2^32, with bias + */ + st->h[1].d = x1 + TWO(52)*TWO32; + st->h[2].d = x2 + TWO(52)*TWO64; + st->h[3].d = x3 + TWO(52)*TWO96; + st->h[0].d = x0 + TWO(52)*TWO0; + + /* + * restore original FPU control register + */ +#if defined(__x86_64__) + asm volatile ("ldmxcsr %0"::"m"(mxcsr_orig)); +#elif defined(__PPC__) + asm volatile ("mtfsf 255,%0"::"f"(fpscr_orig)); +#elif defined(__s390x__) + asm volatile ("lfpc %0"::"m"(fpc_orig)); +#elif defined(__sparc__) + asm volatile ("ldx %0,%%fsr"::"m"(fsr_orig)); +#elif defined(__mips__) + asm volatile ("ctc1 %0,$31"::"r"(fcsr_orig)); +#endif +} + +void poly1305_emit(void *ctx, unsigned char mac[16], const u32 nonce[4]) +{ + poly1305_internal *st = (poly1305_internal *) ctx; + u64 h0, h1, h2, h3, h4; + u32 g0, g1, g2, g3, g4; + u64 t; + u32 mask; + + /* + * thanks to bias masking exponent gives integer result + */ + h0 = st->h[0].u & 0x000fffffffffffffULL; + h1 = st->h[1].u & 0x000fffffffffffffULL; + h2 = st->h[2].u & 0x000fffffffffffffULL; + h3 = st->h[3].u & 0x000fffffffffffffULL; + + /* + * can be partially reduced, so reduce... + */ + h4 = h3>>32; h3 &= 0xffffffffU; + g4 = h4&-4; + h4 &= 3; + g4 += g4>>2; + + h0 += g4; + h1 += h0>>32; h0 &= 0xffffffffU; + h2 += h1>>32; h1 &= 0xffffffffU; + h3 += h2>>32; h2 &= 0xffffffffU; + + /* compute h + -p */ + g0 = (u32)(t = h0 + 5); + g1 = (u32)(t = h1 + (t >> 32)); + g2 = (u32)(t = h2 + (t >> 32)); + g3 = (u32)(t = h3 + (t >> 32)); + g4 = h4 + (u32)(t >> 32); + + /* if there was carry, select g0-g3 */ + mask = 0 - (g4 >> 2); + g0 &= mask; + g1 &= mask; + g2 &= mask; + g3 &= mask; + mask = ~mask; + g0 |= (h0 & mask); + g1 |= (h1 & mask); + g2 |= (h2 & mask); + g3 |= (h3 & mask); + + /* mac = (h + nonce) % (2^128) */ + g0 = (u32)(t = (u64)g0 + nonce[0]); + g1 = (u32)(t = (u64)g1 + (t >> 32) + nonce[1]); + g2 = (u32)(t = (u64)g2 + (t >> 32) + nonce[2]); + g3 = (u32)(t = (u64)g3 + (t >> 32) + nonce[3]); + + U32TO8(mac + 0, g0); + U32TO8(mac + 4, g1); + U32TO8(mac + 8, g2); + U32TO8(mac + 12, g3); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/poly1305_local.h b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/poly1305_local.h new file mode 100644 index 000000000..6d4d9dc5b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/poly1305_local.h @@ -0,0 +1,27 @@ +/* + * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +typedef void (*poly1305_blocks_f) (void *ctx, const unsigned char *inp, + size_t len, unsigned int padbit); +typedef void (*poly1305_emit_f) (void *ctx, unsigned char mac[16], + const unsigned int nonce[4]); + +struct poly1305_context { + double opaque[24]; /* large enough to hold internal state, declared + * 'double' to ensure at least 64-bit invariant + * alignment across all platforms and + * configurations */ + unsigned int nonce[4]; + unsigned char data[POLY1305_BLOCK_SIZE]; + size_t num; + struct { + poly1305_blocks_f blocks; + poly1305_emit_f emit; + } func; +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/poly1305_pmeth.c b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/poly1305_pmeth.c new file mode 100644 index 000000000..3bc24c98c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/poly1305/poly1305_pmeth.c @@ -0,0 +1,194 @@ +/* + * Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "internal/poly1305.h" +#include "poly1305_local.h" +#include "internal/evp_int.h" + +/* POLY1305 pkey context structure */ + +typedef struct { + ASN1_OCTET_STRING ktmp; /* Temp storage for key */ + POLY1305 ctx; +} POLY1305_PKEY_CTX; + +static int pkey_poly1305_init(EVP_PKEY_CTX *ctx) +{ + POLY1305_PKEY_CTX *pctx; + + if ((pctx = OPENSSL_zalloc(sizeof(*pctx))) == NULL) { + CRYPTOerr(CRYPTO_F_PKEY_POLY1305_INIT, ERR_R_MALLOC_FAILURE); + return 0; + } + pctx->ktmp.type = V_ASN1_OCTET_STRING; + + EVP_PKEY_CTX_set_data(ctx, pctx); + EVP_PKEY_CTX_set0_keygen_info(ctx, NULL, 0); + return 1; +} + +static void pkey_poly1305_cleanup(EVP_PKEY_CTX *ctx) +{ + POLY1305_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx); + + if (pctx != NULL) { + OPENSSL_clear_free(pctx->ktmp.data, pctx->ktmp.length); + OPENSSL_clear_free(pctx, sizeof(*pctx)); + EVP_PKEY_CTX_set_data(ctx, NULL); + } +} + +static int pkey_poly1305_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) +{ + POLY1305_PKEY_CTX *sctx, *dctx; + + /* allocate memory for dst->data and a new POLY1305_CTX in dst->data->ctx */ + if (!pkey_poly1305_init(dst)) + return 0; + sctx = EVP_PKEY_CTX_get_data(src); + dctx = EVP_PKEY_CTX_get_data(dst); + if (ASN1_STRING_get0_data(&sctx->ktmp) != NULL && + !ASN1_STRING_copy(&dctx->ktmp, &sctx->ktmp)) { + /* cleanup and free the POLY1305_PKEY_CTX in dst->data */ + pkey_poly1305_cleanup(dst); + return 0; + } + memcpy(&dctx->ctx, &sctx->ctx, sizeof(POLY1305)); + return 1; +} + +static int pkey_poly1305_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) +{ + ASN1_OCTET_STRING *key; + POLY1305_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx); + + if (ASN1_STRING_get0_data(&pctx->ktmp) == NULL) + return 0; + key = ASN1_OCTET_STRING_dup(&pctx->ktmp); + if (key == NULL) + return 0; + return EVP_PKEY_assign_POLY1305(pkey, key); +} + +static int int_update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ + POLY1305_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(EVP_MD_CTX_pkey_ctx(ctx)); + + Poly1305_Update(&pctx->ctx, data, count); + return 1; +} + +static int poly1305_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx) +{ + POLY1305_PKEY_CTX *pctx = ctx->data; + ASN1_OCTET_STRING *key = (ASN1_OCTET_STRING *)ctx->pkey->pkey.ptr; + + if (key->length != POLY1305_KEY_SIZE) + return 0; + EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT); + EVP_MD_CTX_set_update_fn(mctx, int_update); + Poly1305_Init(&pctx->ctx, key->data); + return 1; +} +static int poly1305_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, + EVP_MD_CTX *mctx) +{ + POLY1305_PKEY_CTX *pctx = ctx->data; + + *siglen = POLY1305_DIGEST_SIZE; + if (sig != NULL) + Poly1305_Final(&pctx->ctx, sig); + return 1; +} + +static int pkey_poly1305_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) +{ + POLY1305_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx); + const unsigned char *key; + size_t len; + + switch (type) { + + case EVP_PKEY_CTRL_MD: + /* ignore */ + break; + + case EVP_PKEY_CTRL_SET_MAC_KEY: + case EVP_PKEY_CTRL_DIGESTINIT: + if (type == EVP_PKEY_CTRL_SET_MAC_KEY) { + /* user explicitly setting the key */ + key = p2; + len = p1; + } else { + /* user indirectly setting the key via EVP_DigestSignInit */ + key = EVP_PKEY_get0_poly1305(EVP_PKEY_CTX_get0_pkey(ctx), &len); + } + if (key == NULL || len != POLY1305_KEY_SIZE || + !ASN1_OCTET_STRING_set(&pctx->ktmp, key, len)) + return 0; + Poly1305_Init(&pctx->ctx, ASN1_STRING_get0_data(&pctx->ktmp)); + break; + + default: + return -2; + + } + return 1; +} + +static int pkey_poly1305_ctrl_str(EVP_PKEY_CTX *ctx, + const char *type, const char *value) +{ + if (value == NULL) + return 0; + if (strcmp(type, "key") == 0) + return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value); + if (strcmp(type, "hexkey") == 0) + return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value); + return -2; +} + +const EVP_PKEY_METHOD poly1305_pkey_meth = { + EVP_PKEY_POLY1305, + EVP_PKEY_FLAG_SIGCTX_CUSTOM, /* we don't deal with a separate MD */ + pkey_poly1305_init, + pkey_poly1305_copy, + pkey_poly1305_cleanup, + + 0, 0, + + 0, + pkey_poly1305_keygen, + + 0, 0, + + 0, 0, + + 0, 0, + + poly1305_signctx_init, + poly1305_signctx, + + 0, 0, + + 0, 0, + + 0, 0, + + 0, 0, + + pkey_poly1305_ctrl, + pkey_poly1305_ctrl_str +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ppc_arch.h b/trunk/3rdparty/openssl-1.1-fit/crypto/ppc_arch.h new file mode 100644 index 000000000..72bd74687 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ppc_arch.h @@ -0,0 +1,28 @@ +/* + * Copyright 2014-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_PPC_ARCH_H +# define HEADER_PPC_ARCH_H + +extern unsigned int OPENSSL_ppccap_P; + +/* + * Flags' usage can appear ambiguous, because they are set rather + * to reflect OpenSSL performance preferences than actual processor + * capabilities. + */ +# define PPC_FPU64 (1<<0) +# define PPC_ALTIVEC (1<<1) +# define PPC_CRYPTO207 (1<<2) +# define PPC_FPU (1<<3) +# define PPC_MADD300 (1<<4) +# define PPC_MFTB (1<<5) +# define PPC_MFSPR268 (1<<6) + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ppccap.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ppccap.c new file mode 100644 index 000000000..afb9e31b0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ppccap.c @@ -0,0 +1,408 @@ +/* + * Copyright 2009-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include +#if defined(__linux) || defined(_AIX) +# include +#endif +#if defined(_AIX53) /* defined even on post-5.3 */ +# include +# if !defined(__power_set) +# define __power_set(a) (_system_configuration.implementation & (a)) +# endif +#endif +#if defined(__APPLE__) && defined(__MACH__) +# include +# include +#endif +#include +#include +#include +#include +#include "bn/bn_lcl.h" + +#include "ppc_arch.h" + +unsigned int OPENSSL_ppccap_P = 0; + +static sigset_t all_masked; + +#ifdef OPENSSL_BN_ASM_MONT +int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + const BN_ULONG *np, const BN_ULONG *n0, int num) +{ + int bn_mul_mont_int(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + const BN_ULONG *np, const BN_ULONG *n0, int num); + int bn_mul4x_mont_int(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + const BN_ULONG *np, const BN_ULONG *n0, int num); + + if (num < 4) + return 0; + + if ((num & 3) == 0) + return bn_mul4x_mont_int(rp, ap, bp, np, n0, num); + + /* + * There used to be [optional] call to bn_mul_mont_fpu64 here, + * but above subroutine is faster on contemporary processors. + * Formulation means that there might be old processors where + * FPU code path would be faster, POWER6 perhaps, but there was + * no opportunity to figure it out... + */ + + return bn_mul_mont_int(rp, ap, bp, np, n0, num); +} +#endif + +void sha256_block_p8(void *ctx, const void *inp, size_t len); +void sha256_block_ppc(void *ctx, const void *inp, size_t len); +void sha256_block_data_order(void *ctx, const void *inp, size_t len); +void sha256_block_data_order(void *ctx, const void *inp, size_t len) +{ + OPENSSL_ppccap_P & PPC_CRYPTO207 ? sha256_block_p8(ctx, inp, len) : + sha256_block_ppc(ctx, inp, len); +} + +void sha512_block_p8(void *ctx, const void *inp, size_t len); +void sha512_block_ppc(void *ctx, const void *inp, size_t len); +void sha512_block_data_order(void *ctx, const void *inp, size_t len); +void sha512_block_data_order(void *ctx, const void *inp, size_t len) +{ + OPENSSL_ppccap_P & PPC_CRYPTO207 ? sha512_block_p8(ctx, inp, len) : + sha512_block_ppc(ctx, inp, len); +} + +#ifndef OPENSSL_NO_CHACHA +void ChaCha20_ctr32_int(unsigned char *out, const unsigned char *inp, + size_t len, const unsigned int key[8], + const unsigned int counter[4]); +void ChaCha20_ctr32_vmx(unsigned char *out, const unsigned char *inp, + size_t len, const unsigned int key[8], + const unsigned int counter[4]); +void ChaCha20_ctr32_vsx(unsigned char *out, const unsigned char *inp, + size_t len, const unsigned int key[8], + const unsigned int counter[4]); +void ChaCha20_ctr32(unsigned char *out, const unsigned char *inp, + size_t len, const unsigned int key[8], + const unsigned int counter[4]) +{ + OPENSSL_ppccap_P & PPC_CRYPTO207 + ? ChaCha20_ctr32_vsx(out, inp, len, key, counter) + : OPENSSL_ppccap_P & PPC_ALTIVEC + ? ChaCha20_ctr32_vmx(out, inp, len, key, counter) + : ChaCha20_ctr32_int(out, inp, len, key, counter); +} +#endif + +#ifndef OPENSSL_NO_POLY1305 +void poly1305_init_int(void *ctx, const unsigned char key[16]); +void poly1305_blocks(void *ctx, const unsigned char *inp, size_t len, + unsigned int padbit); +void poly1305_emit(void *ctx, unsigned char mac[16], + const unsigned int nonce[4]); +void poly1305_init_fpu(void *ctx, const unsigned char key[16]); +void poly1305_blocks_fpu(void *ctx, const unsigned char *inp, size_t len, + unsigned int padbit); +void poly1305_emit_fpu(void *ctx, unsigned char mac[16], + const unsigned int nonce[4]); +int poly1305_init(void *ctx, const unsigned char key[16], void *func[2]); +int poly1305_init(void *ctx, const unsigned char key[16], void *func[2]) +{ + if (sizeof(size_t) == 4 && (OPENSSL_ppccap_P & PPC_FPU)) { + poly1305_init_fpu(ctx, key); + func[0] = (void*)(uintptr_t)poly1305_blocks_fpu; + func[1] = (void*)(uintptr_t)poly1305_emit_fpu; + } else { + poly1305_init_int(ctx, key); + func[0] = (void*)(uintptr_t)poly1305_blocks; + func[1] = (void*)(uintptr_t)poly1305_emit; + } + return 1; +} +#endif + +#ifdef ECP_NISTZ256_ASM +void ecp_nistz256_mul_mont(unsigned long res[4], const unsigned long a[4], + const unsigned long b[4]); + +void ecp_nistz256_to_mont(unsigned long res[4], const unsigned long in[4]); +void ecp_nistz256_to_mont(unsigned long res[4], const unsigned long in[4]) +{ + static const unsigned long RR[] = { 0x0000000000000003U, + 0xfffffffbffffffffU, + 0xfffffffffffffffeU, + 0x00000004fffffffdU }; + + ecp_nistz256_mul_mont(res, in, RR); +} + +void ecp_nistz256_from_mont(unsigned long res[4], const unsigned long in[4]); +void ecp_nistz256_from_mont(unsigned long res[4], const unsigned long in[4]) +{ + static const unsigned long one[] = { 1, 0, 0, 0 }; + + ecp_nistz256_mul_mont(res, in, one); +} +#endif + +static sigjmp_buf ill_jmp; +static void ill_handler(int sig) +{ + siglongjmp(ill_jmp, sig); +} + +void OPENSSL_fpu_probe(void); +void OPENSSL_ppc64_probe(void); +void OPENSSL_altivec_probe(void); +void OPENSSL_crypto207_probe(void); +void OPENSSL_madd300_probe(void); + +long OPENSSL_rdtsc_mftb(void); +long OPENSSL_rdtsc_mfspr268(void); + +uint32_t OPENSSL_rdtsc(void) +{ + if (OPENSSL_ppccap_P & PPC_MFTB) + return OPENSSL_rdtsc_mftb(); + else if (OPENSSL_ppccap_P & PPC_MFSPR268) + return OPENSSL_rdtsc_mfspr268(); + else + return 0; +} + +size_t OPENSSL_instrument_bus_mftb(unsigned int *, size_t); +size_t OPENSSL_instrument_bus_mfspr268(unsigned int *, size_t); + +size_t OPENSSL_instrument_bus(unsigned int *out, size_t cnt) +{ + if (OPENSSL_ppccap_P & PPC_MFTB) + return OPENSSL_instrument_bus_mftb(out, cnt); + else if (OPENSSL_ppccap_P & PPC_MFSPR268) + return OPENSSL_instrument_bus_mfspr268(out, cnt); + else + return 0; +} + +size_t OPENSSL_instrument_bus2_mftb(unsigned int *, size_t, size_t); +size_t OPENSSL_instrument_bus2_mfspr268(unsigned int *, size_t, size_t); + +size_t OPENSSL_instrument_bus2(unsigned int *out, size_t cnt, size_t max) +{ + if (OPENSSL_ppccap_P & PPC_MFTB) + return OPENSSL_instrument_bus2_mftb(out, cnt, max); + else if (OPENSSL_ppccap_P & PPC_MFSPR268) + return OPENSSL_instrument_bus2_mfspr268(out, cnt, max); + else + return 0; +} + +#if defined(__GLIBC__) && defined(__GLIBC_PREREQ) +# if __GLIBC_PREREQ(2, 16) +# include +# define OSSL_IMPLEMENT_GETAUXVAL +# endif +#endif + +/* I wish was universally available */ +#define HWCAP 16 /* AT_HWCAP */ +#define HWCAP_PPC64 (1U << 30) +#define HWCAP_ALTIVEC (1U << 28) +#define HWCAP_FPU (1U << 27) +#define HWCAP_POWER6_EXT (1U << 9) +#define HWCAP_VSX (1U << 7) + +#define HWCAP2 26 /* AT_HWCAP2 */ +#define HWCAP_VEC_CRYPTO (1U << 25) +#define HWCAP_ARCH_3_00 (1U << 23) + +# if defined(__GNUC__) && __GNUC__>=2 +__attribute__ ((constructor)) +# endif +void OPENSSL_cpuid_setup(void) +{ + char *e; + struct sigaction ill_oact, ill_act; + sigset_t oset; + static int trigger = 0; + + if (trigger) + return; + trigger = 1; + + if ((e = getenv("OPENSSL_ppccap"))) { + OPENSSL_ppccap_P = strtoul(e, NULL, 0); + return; + } + + OPENSSL_ppccap_P = 0; + +#if defined(_AIX) + OPENSSL_ppccap_P |= PPC_FPU; + + if (sizeof(size_t) == 4) { + struct utsname uts; +# if defined(_SC_AIX_KERNEL_BITMODE) + if (sysconf(_SC_AIX_KERNEL_BITMODE) != 64) + return; +# endif + if (uname(&uts) != 0 || atoi(uts.version) < 6) + return; + } + +# if defined(__power_set) + /* + * Value used in __power_set is a single-bit 1< +#include +#include +#include +#include +#include "internal/thread_once.h" +#include "internal/thread_once.h" +#include "rand_lcl.h" +/* + * Implementation of NIST SP 800-90A CTR DRBG. + */ + +static void inc_128(RAND_DRBG_CTR *ctr) +{ + int i; + unsigned char c; + unsigned char *p = &ctr->V[15]; + + for (i = 0; i < 16; i++, p--) { + c = *p; + c++; + *p = c; + if (c != 0) { + /* If we didn't wrap around, we're done. */ + break; + } + } +} + +static void ctr_XOR(RAND_DRBG_CTR *ctr, const unsigned char *in, size_t inlen) +{ + size_t i, n; + + if (in == NULL || inlen == 0) + return; + + /* + * Any zero padding will have no effect on the result as we + * are XORing. So just process however much input we have. + */ + n = inlen < ctr->keylen ? inlen : ctr->keylen; + for (i = 0; i < n; i++) + ctr->K[i] ^= in[i]; + if (inlen <= ctr->keylen) + return; + + n = inlen - ctr->keylen; + if (n > 16) { + /* Should never happen */ + n = 16; + } + for (i = 0; i < n; i++) + ctr->V[i] ^= in[i + ctr->keylen]; +} + +/* + * Process a complete block using BCC algorithm of SP 800-90A 10.3.3 + */ +__owur static int ctr_BCC_block(RAND_DRBG_CTR *ctr, unsigned char *out, + const unsigned char *in) +{ + int i, outlen = AES_BLOCK_SIZE; + + for (i = 0; i < 16; i++) + out[i] ^= in[i]; + + if (!EVP_CipherUpdate(ctr->ctx_df, out, &outlen, out, AES_BLOCK_SIZE) + || outlen != AES_BLOCK_SIZE) + return 0; + return 1; +} + + +/* + * Handle several BCC operations for as much data as we need for K and X + */ +__owur static int ctr_BCC_blocks(RAND_DRBG_CTR *ctr, const unsigned char *in) +{ + if (!ctr_BCC_block(ctr, ctr->KX, in) + || !ctr_BCC_block(ctr, ctr->KX + 16, in)) + return 0; + if (ctr->keylen != 16 && !ctr_BCC_block(ctr, ctr->KX + 32, in)) + return 0; + return 1; +} + +/* + * Initialise BCC blocks: these have the value 0,1,2 in leftmost positions: + * see 10.3.1 stage 7. + */ +__owur static int ctr_BCC_init(RAND_DRBG_CTR *ctr) +{ + memset(ctr->KX, 0, 48); + memset(ctr->bltmp, 0, 16); + if (!ctr_BCC_block(ctr, ctr->KX, ctr->bltmp)) + return 0; + ctr->bltmp[3] = 1; + if (!ctr_BCC_block(ctr, ctr->KX + 16, ctr->bltmp)) + return 0; + if (ctr->keylen != 16) { + ctr->bltmp[3] = 2; + if (!ctr_BCC_block(ctr, ctr->KX + 32, ctr->bltmp)) + return 0; + } + return 1; +} + +/* + * Process several blocks into BCC algorithm, some possibly partial + */ +__owur static int ctr_BCC_update(RAND_DRBG_CTR *ctr, + const unsigned char *in, size_t inlen) +{ + if (in == NULL || inlen == 0) + return 1; + + /* If we have partial block handle it first */ + if (ctr->bltmp_pos) { + size_t left = 16 - ctr->bltmp_pos; + + /* If we now have a complete block process it */ + if (inlen >= left) { + memcpy(ctr->bltmp + ctr->bltmp_pos, in, left); + if (!ctr_BCC_blocks(ctr, ctr->bltmp)) + return 0; + ctr->bltmp_pos = 0; + inlen -= left; + in += left; + } + } + + /* Process zero or more complete blocks */ + for (; inlen >= 16; in += 16, inlen -= 16) { + if (!ctr_BCC_blocks(ctr, in)) + return 0; + } + + /* Copy any remaining partial block to the temporary buffer */ + if (inlen > 0) { + memcpy(ctr->bltmp + ctr->bltmp_pos, in, inlen); + ctr->bltmp_pos += inlen; + } + return 1; +} + +__owur static int ctr_BCC_final(RAND_DRBG_CTR *ctr) +{ + if (ctr->bltmp_pos) { + memset(ctr->bltmp + ctr->bltmp_pos, 0, 16 - ctr->bltmp_pos); + if (!ctr_BCC_blocks(ctr, ctr->bltmp)) + return 0; + } + return 1; +} + +__owur static int ctr_df(RAND_DRBG_CTR *ctr, + const unsigned char *in1, size_t in1len, + const unsigned char *in2, size_t in2len, + const unsigned char *in3, size_t in3len) +{ + static unsigned char c80 = 0x80; + size_t inlen; + unsigned char *p = ctr->bltmp; + int outlen = AES_BLOCK_SIZE; + + if (!ctr_BCC_init(ctr)) + return 0; + if (in1 == NULL) + in1len = 0; + if (in2 == NULL) + in2len = 0; + if (in3 == NULL) + in3len = 0; + inlen = in1len + in2len + in3len; + /* Initialise L||N in temporary block */ + *p++ = (inlen >> 24) & 0xff; + *p++ = (inlen >> 16) & 0xff; + *p++ = (inlen >> 8) & 0xff; + *p++ = inlen & 0xff; + + /* NB keylen is at most 32 bytes */ + *p++ = 0; + *p++ = 0; + *p++ = 0; + *p = (unsigned char)((ctr->keylen + 16) & 0xff); + ctr->bltmp_pos = 8; + if (!ctr_BCC_update(ctr, in1, in1len) + || !ctr_BCC_update(ctr, in2, in2len) + || !ctr_BCC_update(ctr, in3, in3len) + || !ctr_BCC_update(ctr, &c80, 1) + || !ctr_BCC_final(ctr)) + return 0; + /* Set up key K */ + if (!EVP_CipherInit_ex(ctr->ctx, ctr->cipher, NULL, ctr->KX, NULL, 1)) + return 0; + /* X follows key K */ + if (!EVP_CipherUpdate(ctr->ctx, ctr->KX, &outlen, ctr->KX + ctr->keylen, + AES_BLOCK_SIZE) + || outlen != AES_BLOCK_SIZE) + return 0; + if (!EVP_CipherUpdate(ctr->ctx, ctr->KX + 16, &outlen, ctr->KX, + AES_BLOCK_SIZE) + || outlen != AES_BLOCK_SIZE) + return 0; + if (ctr->keylen != 16) + if (!EVP_CipherUpdate(ctr->ctx, ctr->KX + 32, &outlen, ctr->KX + 16, + AES_BLOCK_SIZE) + || outlen != AES_BLOCK_SIZE) + return 0; + return 1; +} + +/* + * NB the no-df Update in SP800-90A specifies a constant input length + * of seedlen, however other uses of this algorithm pad the input with + * zeroes if necessary and have up to two parameters XORed together, + * so we handle both cases in this function instead. + */ +__owur static int ctr_update(RAND_DRBG *drbg, + const unsigned char *in1, size_t in1len, + const unsigned char *in2, size_t in2len, + const unsigned char *nonce, size_t noncelen) +{ + RAND_DRBG_CTR *ctr = &drbg->data.ctr; + int outlen = AES_BLOCK_SIZE; + + /* correct key is already set up. */ + inc_128(ctr); + if (!EVP_CipherUpdate(ctr->ctx, ctr->K, &outlen, ctr->V, AES_BLOCK_SIZE) + || outlen != AES_BLOCK_SIZE) + return 0; + + /* If keylen longer than 128 bits need extra encrypt */ + if (ctr->keylen != 16) { + inc_128(ctr); + if (!EVP_CipherUpdate(ctr->ctx, ctr->K+16, &outlen, ctr->V, + AES_BLOCK_SIZE) + || outlen != AES_BLOCK_SIZE) + return 0; + } + inc_128(ctr); + if (!EVP_CipherUpdate(ctr->ctx, ctr->V, &outlen, ctr->V, AES_BLOCK_SIZE) + || outlen != AES_BLOCK_SIZE) + return 0; + + /* If 192 bit key part of V is on end of K */ + if (ctr->keylen == 24) { + memcpy(ctr->V + 8, ctr->V, 8); + memcpy(ctr->V, ctr->K + 24, 8); + } + + if ((drbg->flags & RAND_DRBG_FLAG_CTR_NO_DF) == 0) { + /* If no input reuse existing derived value */ + if (in1 != NULL || nonce != NULL || in2 != NULL) + if (!ctr_df(ctr, in1, in1len, nonce, noncelen, in2, in2len)) + return 0; + /* If this a reuse input in1len != 0 */ + if (in1len) + ctr_XOR(ctr, ctr->KX, drbg->seedlen); + } else { + ctr_XOR(ctr, in1, in1len); + ctr_XOR(ctr, in2, in2len); + } + + if (!EVP_CipherInit_ex(ctr->ctx, ctr->cipher, NULL, ctr->K, NULL, 1)) + return 0; + return 1; +} + +__owur static int drbg_ctr_instantiate(RAND_DRBG *drbg, + const unsigned char *entropy, size_t entropylen, + const unsigned char *nonce, size_t noncelen, + const unsigned char *pers, size_t perslen) +{ + RAND_DRBG_CTR *ctr = &drbg->data.ctr; + + if (entropy == NULL) + return 0; + + memset(ctr->K, 0, sizeof(ctr->K)); + memset(ctr->V, 0, sizeof(ctr->V)); + if (!EVP_CipherInit_ex(ctr->ctx, ctr->cipher, NULL, ctr->K, NULL, 1)) + return 0; + if (!ctr_update(drbg, entropy, entropylen, pers, perslen, nonce, noncelen)) + return 0; + return 1; +} + +__owur static int drbg_ctr_reseed(RAND_DRBG *drbg, + const unsigned char *entropy, size_t entropylen, + const unsigned char *adin, size_t adinlen) +{ + if (entropy == NULL) + return 0; + if (!ctr_update(drbg, entropy, entropylen, adin, adinlen, NULL, 0)) + return 0; + return 1; +} + +__owur static int drbg_ctr_generate(RAND_DRBG *drbg, + unsigned char *out, size_t outlen, + const unsigned char *adin, size_t adinlen) +{ + RAND_DRBG_CTR *ctr = &drbg->data.ctr; + + if (adin != NULL && adinlen != 0) { + if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0)) + return 0; + /* This means we reuse derived value */ + if ((drbg->flags & RAND_DRBG_FLAG_CTR_NO_DF) == 0) { + adin = NULL; + adinlen = 1; + } + } else { + adinlen = 0; + } + + for ( ; ; ) { + int outl = AES_BLOCK_SIZE; + + inc_128(ctr); + if (outlen < 16) { + /* Use K as temp space as it will be updated */ + if (!EVP_CipherUpdate(ctr->ctx, ctr->K, &outl, ctr->V, + AES_BLOCK_SIZE) + || outl != AES_BLOCK_SIZE) + return 0; + memcpy(out, ctr->K, outlen); + break; + } + if (!EVP_CipherUpdate(ctr->ctx, out, &outl, ctr->V, AES_BLOCK_SIZE) + || outl != AES_BLOCK_SIZE) + return 0; + out += 16; + outlen -= 16; + if (outlen == 0) + break; + } + + if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0)) + return 0; + return 1; +} + +static int drbg_ctr_uninstantiate(RAND_DRBG *drbg) +{ + EVP_CIPHER_CTX_free(drbg->data.ctr.ctx); + EVP_CIPHER_CTX_free(drbg->data.ctr.ctx_df); + OPENSSL_cleanse(&drbg->data.ctr, sizeof(drbg->data.ctr)); + return 1; +} + +static RAND_DRBG_METHOD drbg_ctr_meth = { + drbg_ctr_instantiate, + drbg_ctr_reseed, + drbg_ctr_generate, + drbg_ctr_uninstantiate +}; + +int drbg_ctr_init(RAND_DRBG *drbg) +{ + RAND_DRBG_CTR *ctr = &drbg->data.ctr; + size_t keylen; + + switch (drbg->type) { + default: + /* This can't happen, but silence the compiler warning. */ + return 0; + case NID_aes_128_ctr: + keylen = 16; + ctr->cipher = EVP_aes_128_ecb(); + break; + case NID_aes_192_ctr: + keylen = 24; + ctr->cipher = EVP_aes_192_ecb(); + break; + case NID_aes_256_ctr: + keylen = 32; + ctr->cipher = EVP_aes_256_ecb(); + break; + } + + drbg->meth = &drbg_ctr_meth; + + ctr->keylen = keylen; + if (ctr->ctx == NULL) + ctr->ctx = EVP_CIPHER_CTX_new(); + if (ctr->ctx == NULL) + return 0; + drbg->strength = keylen * 8; + drbg->seedlen = keylen + 16; + + if ((drbg->flags & RAND_DRBG_FLAG_CTR_NO_DF) == 0) { + /* df initialisation */ + static const unsigned char df_key[32] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f + }; + + if (ctr->ctx_df == NULL) + ctr->ctx_df = EVP_CIPHER_CTX_new(); + if (ctr->ctx_df == NULL) + return 0; + /* Set key schedule for df_key */ + if (!EVP_CipherInit_ex(ctr->ctx_df, ctr->cipher, NULL, df_key, NULL, 1)) + return 0; + + drbg->min_entropylen = ctr->keylen; + drbg->max_entropylen = DRBG_MAX_LENGTH; + drbg->min_noncelen = drbg->min_entropylen / 2; + drbg->max_noncelen = DRBG_MAX_LENGTH; + drbg->max_perslen = DRBG_MAX_LENGTH; + drbg->max_adinlen = DRBG_MAX_LENGTH; + } else { + drbg->min_entropylen = drbg->seedlen; + drbg->max_entropylen = drbg->seedlen; + /* Nonce not used */ + drbg->min_noncelen = 0; + drbg->max_noncelen = 0; + drbg->max_perslen = drbg->seedlen; + drbg->max_adinlen = drbg->seedlen; + } + + drbg->max_request = 1 << 16; + + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rand/drbg_lib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rand/drbg_lib.c new file mode 100644 index 000000000..a13282181 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rand/drbg_lib.c @@ -0,0 +1,1159 @@ +/* + * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include "rand_lcl.h" +#include "internal/thread_once.h" +#include "internal/rand_int.h" +#include "internal/cryptlib_int.h" + +/* + * Support framework for NIST SP 800-90A DRBG + * + * See manual page RAND_DRBG(7) for a general overview. + * + * The OpenSSL model is to have new and free functions, and that new + * does all initialization. That is not the NIST model, which has + * instantiation and un-instantiate, and re-use within a new/free + * lifecycle. (No doubt this comes from the desire to support hardware + * DRBG, where allocation of resources on something like an HSM is + * a much bigger deal than just re-setting an allocated resource.) + */ + +/* + * The three shared DRBG instances + * + * There are three shared DRBG instances: , , and . + */ + +/* + * The DRBG + * + * Not used directly by the application, only for reseeding the two other + * DRBGs. It reseeds itself by pulling either randomness from os entropy + * sources or by consuming randomness which was added by RAND_add(). + * + * The DRBG is a global instance which is accessed concurrently by + * all threads. The necessary locking is managed automatically by its child + * DRBG instances during reseeding. + */ +static RAND_DRBG *master_drbg; +/* + * The DRBG + * + * Used by default for generating random bytes using RAND_bytes(). + * + * The DRBG is thread-local, i.e., there is one instance per thread. + */ +static CRYPTO_THREAD_LOCAL public_drbg; +/* + * The DRBG + * + * Used by default for generating private keys using RAND_priv_bytes() + * + * The DRBG is thread-local, i.e., there is one instance per thread. + */ +static CRYPTO_THREAD_LOCAL private_drbg; + + + +/* NIST SP 800-90A DRBG recommends the use of a personalization string. */ +static const char ossl_pers_string[] = "OpenSSL NIST SP 800-90A DRBG"; + +static CRYPTO_ONCE rand_drbg_init = CRYPTO_ONCE_STATIC_INIT; + + + +static int rand_drbg_type = RAND_DRBG_TYPE; +static unsigned int rand_drbg_flags = RAND_DRBG_FLAGS; + +static unsigned int master_reseed_interval = MASTER_RESEED_INTERVAL; +static unsigned int slave_reseed_interval = SLAVE_RESEED_INTERVAL; + +static time_t master_reseed_time_interval = MASTER_RESEED_TIME_INTERVAL; +static time_t slave_reseed_time_interval = SLAVE_RESEED_TIME_INTERVAL; + +/* A logical OR of all used DRBG flag bits (currently there is only one) */ +static const unsigned int rand_drbg_used_flags = + RAND_DRBG_FLAG_CTR_NO_DF; + +static RAND_DRBG *drbg_setup(RAND_DRBG *parent); + +static RAND_DRBG *rand_drbg_new(int secure, + int type, + unsigned int flags, + RAND_DRBG *parent); + +/* + * Set/initialize |drbg| to be of type |type|, with optional |flags|. + * + * If |type| and |flags| are zero, use the defaults + * + * Returns 1 on success, 0 on failure. + */ +int RAND_DRBG_set(RAND_DRBG *drbg, int type, unsigned int flags) +{ + int ret = 1; + + if (type == 0 && flags == 0) { + type = rand_drbg_type; + flags = rand_drbg_flags; + } + + /* If set is called multiple times - clear the old one */ + if (drbg->type != 0 && (type != drbg->type || flags != drbg->flags)) { + drbg->meth->uninstantiate(drbg); + rand_pool_free(drbg->adin_pool); + drbg->adin_pool = NULL; + } + + drbg->state = DRBG_UNINITIALISED; + drbg->flags = flags; + drbg->type = type; + + switch (type) { + default: + drbg->type = 0; + drbg->flags = 0; + drbg->meth = NULL; + RANDerr(RAND_F_RAND_DRBG_SET, RAND_R_UNSUPPORTED_DRBG_TYPE); + return 0; + case 0: + /* Uninitialized; that's okay. */ + drbg->meth = NULL; + return 1; + case NID_aes_128_ctr: + case NID_aes_192_ctr: + case NID_aes_256_ctr: + ret = drbg_ctr_init(drbg); + break; + } + + if (ret == 0) { + drbg->state = DRBG_ERROR; + RANDerr(RAND_F_RAND_DRBG_SET, RAND_R_ERROR_INITIALISING_DRBG); + } + return ret; +} + +/* + * Set/initialize default |type| and |flag| for new drbg instances. + * + * Returns 1 on success, 0 on failure. + */ +int RAND_DRBG_set_defaults(int type, unsigned int flags) +{ + int ret = 1; + + switch (type) { + default: + RANDerr(RAND_F_RAND_DRBG_SET_DEFAULTS, RAND_R_UNSUPPORTED_DRBG_TYPE); + return 0; + case NID_aes_128_ctr: + case NID_aes_192_ctr: + case NID_aes_256_ctr: + break; + } + + if ((flags & ~rand_drbg_used_flags) != 0) { + RANDerr(RAND_F_RAND_DRBG_SET_DEFAULTS, RAND_R_UNSUPPORTED_DRBG_FLAGS); + return 0; + } + + rand_drbg_type = type; + rand_drbg_flags = flags; + + return ret; +} + + +/* + * Allocate memory and initialize a new DRBG. The DRBG is allocated on + * the secure heap if |secure| is nonzero and the secure heap is enabled. + * The |parent|, if not NULL, will be used as random source for reseeding. + * + * Returns a pointer to the new DRBG instance on success, NULL on failure. + */ +static RAND_DRBG *rand_drbg_new(int secure, + int type, + unsigned int flags, + RAND_DRBG *parent) +{ + RAND_DRBG *drbg = secure ? + OPENSSL_secure_zalloc(sizeof(*drbg)) : OPENSSL_zalloc(sizeof(*drbg)); + + if (drbg == NULL) { + RANDerr(RAND_F_RAND_DRBG_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + drbg->secure = secure && CRYPTO_secure_allocated(drbg); + drbg->fork_count = rand_fork_count; + drbg->parent = parent; + + if (parent == NULL) { + drbg->get_entropy = rand_drbg_get_entropy; + drbg->cleanup_entropy = rand_drbg_cleanup_entropy; +#ifndef RAND_DRBG_GET_RANDOM_NONCE + drbg->get_nonce = rand_drbg_get_nonce; + drbg->cleanup_nonce = rand_drbg_cleanup_nonce; +#endif + + drbg->reseed_interval = master_reseed_interval; + drbg->reseed_time_interval = master_reseed_time_interval; + } else { + drbg->get_entropy = rand_drbg_get_entropy; + drbg->cleanup_entropy = rand_drbg_cleanup_entropy; + /* + * Do not provide nonce callbacks, the child DRBGs will + * obtain their nonce using random bits from the parent. + */ + + drbg->reseed_interval = slave_reseed_interval; + drbg->reseed_time_interval = slave_reseed_time_interval; + } + + if (RAND_DRBG_set(drbg, type, flags) == 0) + goto err; + + if (parent != NULL) { + rand_drbg_lock(parent); + if (drbg->strength > parent->strength) { + /* + * We currently don't support the algorithm from NIST SP 800-90C + * 10.1.2 to use a weaker DRBG as source + */ + rand_drbg_unlock(parent); + RANDerr(RAND_F_RAND_DRBG_NEW, RAND_R_PARENT_STRENGTH_TOO_WEAK); + goto err; + } + rand_drbg_unlock(parent); + } + + return drbg; + + err: + RAND_DRBG_free(drbg); + + return NULL; +} + +RAND_DRBG *RAND_DRBG_new(int type, unsigned int flags, RAND_DRBG *parent) +{ + return rand_drbg_new(0, type, flags, parent); +} + +RAND_DRBG *RAND_DRBG_secure_new(int type, unsigned int flags, RAND_DRBG *parent) +{ + return rand_drbg_new(1, type, flags, parent); +} + +/* + * Uninstantiate |drbg| and free all memory. + */ +void RAND_DRBG_free(RAND_DRBG *drbg) +{ + if (drbg == NULL) + return; + + if (drbg->meth != NULL) + drbg->meth->uninstantiate(drbg); + rand_pool_free(drbg->adin_pool); + CRYPTO_THREAD_lock_free(drbg->lock); + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DRBG, drbg, &drbg->ex_data); + + if (drbg->secure) + OPENSSL_secure_clear_free(drbg, sizeof(*drbg)); + else + OPENSSL_clear_free(drbg, sizeof(*drbg)); +} + +/* + * Instantiate |drbg|, after it has been initialized. Use |pers| and + * |perslen| as prediction-resistance input. + * + * Requires that drbg->lock is already locked for write, if non-null. + * + * Returns 1 on success, 0 on failure. + */ +int RAND_DRBG_instantiate(RAND_DRBG *drbg, + const unsigned char *pers, size_t perslen) +{ + unsigned char *nonce = NULL, *entropy = NULL; + size_t noncelen = 0, entropylen = 0; + size_t min_entropy = drbg->strength; + size_t min_entropylen = drbg->min_entropylen; + size_t max_entropylen = drbg->max_entropylen; + + if (perslen > drbg->max_perslen) { + RANDerr(RAND_F_RAND_DRBG_INSTANTIATE, + RAND_R_PERSONALISATION_STRING_TOO_LONG); + goto end; + } + + if (drbg->meth == NULL) { + RANDerr(RAND_F_RAND_DRBG_INSTANTIATE, + RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED); + goto end; + } + + if (drbg->state != DRBG_UNINITIALISED) { + RANDerr(RAND_F_RAND_DRBG_INSTANTIATE, + drbg->state == DRBG_ERROR ? RAND_R_IN_ERROR_STATE + : RAND_R_ALREADY_INSTANTIATED); + goto end; + } + + drbg->state = DRBG_ERROR; + + /* + * NIST SP800-90Ar1 section 9.1 says you can combine getting the entropy + * and nonce in 1 call by increasing the entropy with 50% and increasing + * the minimum length to accomadate the length of the nonce. + * We do this in case a nonce is require and get_nonce is NULL. + */ + if (drbg->min_noncelen > 0 && drbg->get_nonce == NULL) { + min_entropy += drbg->strength / 2; + min_entropylen += drbg->min_noncelen; + max_entropylen += drbg->max_noncelen; + } + + drbg->reseed_next_counter = tsan_load(&drbg->reseed_prop_counter); + if (drbg->reseed_next_counter) { + drbg->reseed_next_counter++; + if(!drbg->reseed_next_counter) + drbg->reseed_next_counter = 1; + } + + if (drbg->get_entropy != NULL) + entropylen = drbg->get_entropy(drbg, &entropy, min_entropy, + min_entropylen, max_entropylen, 0); + if (entropylen < min_entropylen + || entropylen > max_entropylen) { + RANDerr(RAND_F_RAND_DRBG_INSTANTIATE, RAND_R_ERROR_RETRIEVING_ENTROPY); + goto end; + } + + if (drbg->min_noncelen > 0 && drbg->get_nonce != NULL) { + noncelen = drbg->get_nonce(drbg, &nonce, drbg->strength / 2, + drbg->min_noncelen, drbg->max_noncelen); + if (noncelen < drbg->min_noncelen || noncelen > drbg->max_noncelen) { + RANDerr(RAND_F_RAND_DRBG_INSTANTIATE, RAND_R_ERROR_RETRIEVING_NONCE); + goto end; + } + } + + if (!drbg->meth->instantiate(drbg, entropy, entropylen, + nonce, noncelen, pers, perslen)) { + RANDerr(RAND_F_RAND_DRBG_INSTANTIATE, RAND_R_ERROR_INSTANTIATING_DRBG); + goto end; + } + + drbg->state = DRBG_READY; + drbg->reseed_gen_counter = 1; + drbg->reseed_time = time(NULL); + tsan_store(&drbg->reseed_prop_counter, drbg->reseed_next_counter); + + end: + if (entropy != NULL && drbg->cleanup_entropy != NULL) + drbg->cleanup_entropy(drbg, entropy, entropylen); + if (nonce != NULL && drbg->cleanup_nonce != NULL) + drbg->cleanup_nonce(drbg, nonce, noncelen); + if (drbg->state == DRBG_READY) + return 1; + return 0; +} + +/* + * Uninstantiate |drbg|. Must be instantiated before it can be used. + * + * Requires that drbg->lock is already locked for write, if non-null. + * + * Returns 1 on success, 0 on failure. + */ +int RAND_DRBG_uninstantiate(RAND_DRBG *drbg) +{ + if (drbg->meth == NULL) { + drbg->state = DRBG_ERROR; + RANDerr(RAND_F_RAND_DRBG_UNINSTANTIATE, + RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED); + return 0; + } + + /* Clear the entire drbg->ctr struct, then reset some important + * members of the drbg->ctr struct (e.g. keysize, df_ks) to their + * initial values. + */ + drbg->meth->uninstantiate(drbg); + return RAND_DRBG_set(drbg, drbg->type, drbg->flags); +} + +/* + * Reseed |drbg|, mixing in the specified data + * + * Requires that drbg->lock is already locked for write, if non-null. + * + * Returns 1 on success, 0 on failure. + */ +int RAND_DRBG_reseed(RAND_DRBG *drbg, + const unsigned char *adin, size_t adinlen, + int prediction_resistance) +{ + unsigned char *entropy = NULL; + size_t entropylen = 0; + + if (drbg->state == DRBG_ERROR) { + RANDerr(RAND_F_RAND_DRBG_RESEED, RAND_R_IN_ERROR_STATE); + return 0; + } + if (drbg->state == DRBG_UNINITIALISED) { + RANDerr(RAND_F_RAND_DRBG_RESEED, RAND_R_NOT_INSTANTIATED); + return 0; + } + + if (adin == NULL) { + adinlen = 0; + } else if (adinlen > drbg->max_adinlen) { + RANDerr(RAND_F_RAND_DRBG_RESEED, RAND_R_ADDITIONAL_INPUT_TOO_LONG); + return 0; + } + + drbg->state = DRBG_ERROR; + + drbg->reseed_next_counter = tsan_load(&drbg->reseed_prop_counter); + if (drbg->reseed_next_counter) { + drbg->reseed_next_counter++; + if(!drbg->reseed_next_counter) + drbg->reseed_next_counter = 1; + } + + if (drbg->get_entropy != NULL) + entropylen = drbg->get_entropy(drbg, &entropy, drbg->strength, + drbg->min_entropylen, + drbg->max_entropylen, + prediction_resistance); + if (entropylen < drbg->min_entropylen + || entropylen > drbg->max_entropylen) { + RANDerr(RAND_F_RAND_DRBG_RESEED, RAND_R_ERROR_RETRIEVING_ENTROPY); + goto end; + } + + if (!drbg->meth->reseed(drbg, entropy, entropylen, adin, adinlen)) + goto end; + + drbg->state = DRBG_READY; + drbg->reseed_gen_counter = 1; + drbg->reseed_time = time(NULL); + tsan_store(&drbg->reseed_prop_counter, drbg->reseed_next_counter); + + end: + if (entropy != NULL && drbg->cleanup_entropy != NULL) + drbg->cleanup_entropy(drbg, entropy, entropylen); + if (drbg->state == DRBG_READY) + return 1; + return 0; +} + +/* + * Restart |drbg|, using the specified entropy or additional input + * + * Tries its best to get the drbg instantiated by all means, + * regardless of its current state. + * + * Optionally, a |buffer| of |len| random bytes can be passed, + * which is assumed to contain at least |entropy| bits of entropy. + * + * If |entropy| > 0, the buffer content is used as entropy input. + * + * If |entropy| == 0, the buffer content is used as additional input + * + * Returns 1 on success, 0 on failure. + * + * This function is used internally only. + */ +int rand_drbg_restart(RAND_DRBG *drbg, + const unsigned char *buffer, size_t len, size_t entropy) +{ + int reseeded = 0; + const unsigned char *adin = NULL; + size_t adinlen = 0; + + if (drbg->seed_pool != NULL) { + RANDerr(RAND_F_RAND_DRBG_RESTART, ERR_R_INTERNAL_ERROR); + drbg->state = DRBG_ERROR; + rand_pool_free(drbg->seed_pool); + drbg->seed_pool = NULL; + return 0; + } + + if (buffer != NULL) { + if (entropy > 0) { + if (drbg->max_entropylen < len) { + RANDerr(RAND_F_RAND_DRBG_RESTART, + RAND_R_ENTROPY_INPUT_TOO_LONG); + drbg->state = DRBG_ERROR; + return 0; + } + + if (entropy > 8 * len) { + RANDerr(RAND_F_RAND_DRBG_RESTART, RAND_R_ENTROPY_OUT_OF_RANGE); + drbg->state = DRBG_ERROR; + return 0; + } + + /* will be picked up by the rand_drbg_get_entropy() callback */ + drbg->seed_pool = rand_pool_attach(buffer, len, entropy); + if (drbg->seed_pool == NULL) + return 0; + } else { + if (drbg->max_adinlen < len) { + RANDerr(RAND_F_RAND_DRBG_RESTART, + RAND_R_ADDITIONAL_INPUT_TOO_LONG); + drbg->state = DRBG_ERROR; + return 0; + } + adin = buffer; + adinlen = len; + } + } + + /* repair error state */ + if (drbg->state == DRBG_ERROR) + RAND_DRBG_uninstantiate(drbg); + + /* repair uninitialized state */ + if (drbg->state == DRBG_UNINITIALISED) { + /* reinstantiate drbg */ + RAND_DRBG_instantiate(drbg, + (const unsigned char *) ossl_pers_string, + sizeof(ossl_pers_string) - 1); + /* already reseeded. prevent second reseeding below */ + reseeded = (drbg->state == DRBG_READY); + } + + /* refresh current state if entropy or additional input has been provided */ + if (drbg->state == DRBG_READY) { + if (adin != NULL) { + /* + * mix in additional input without reseeding + * + * Similar to RAND_DRBG_reseed(), but the provided additional + * data |adin| is mixed into the current state without pulling + * entropy from the trusted entropy source using get_entropy(). + * This is not a reseeding in the strict sense of NIST SP 800-90A. + */ + drbg->meth->reseed(drbg, adin, adinlen, NULL, 0); + } else if (reseeded == 0) { + /* do a full reseeding if it has not been done yet above */ + RAND_DRBG_reseed(drbg, NULL, 0, 0); + } + } + + rand_pool_free(drbg->seed_pool); + drbg->seed_pool = NULL; + + return drbg->state == DRBG_READY; +} + +/* + * Generate |outlen| bytes into the buffer at |out|. Reseed if we need + * to or if |prediction_resistance| is set. Additional input can be + * sent in |adin| and |adinlen|. + * + * Requires that drbg->lock is already locked for write, if non-null. + * + * Returns 1 on success, 0 on failure. + * + */ +int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen, + int prediction_resistance, + const unsigned char *adin, size_t adinlen) +{ + int reseed_required = 0; + + if (drbg->state != DRBG_READY) { + /* try to recover from previous errors */ + rand_drbg_restart(drbg, NULL, 0, 0); + + if (drbg->state == DRBG_ERROR) { + RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_IN_ERROR_STATE); + return 0; + } + if (drbg->state == DRBG_UNINITIALISED) { + RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_NOT_INSTANTIATED); + return 0; + } + } + + if (outlen > drbg->max_request) { + RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_REQUEST_TOO_LARGE_FOR_DRBG); + return 0; + } + if (adinlen > drbg->max_adinlen) { + RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_ADDITIONAL_INPUT_TOO_LONG); + return 0; + } + + if (drbg->fork_count != rand_fork_count) { + drbg->fork_count = rand_fork_count; + reseed_required = 1; + } + + if (drbg->reseed_interval > 0) { + if (drbg->reseed_gen_counter >= drbg->reseed_interval) + reseed_required = 1; + } + if (drbg->reseed_time_interval > 0) { + time_t now = time(NULL); + if (now < drbg->reseed_time + || now - drbg->reseed_time >= drbg->reseed_time_interval) + reseed_required = 1; + } + if (drbg->parent != NULL) { + unsigned int reseed_counter = tsan_load(&drbg->reseed_prop_counter); + if (reseed_counter > 0 + && tsan_load(&drbg->parent->reseed_prop_counter) + != reseed_counter) + reseed_required = 1; + } + + if (reseed_required || prediction_resistance) { + if (!RAND_DRBG_reseed(drbg, adin, adinlen, prediction_resistance)) { + RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_RESEED_ERROR); + return 0; + } + adin = NULL; + adinlen = 0; + } + + if (!drbg->meth->generate(drbg, out, outlen, adin, adinlen)) { + drbg->state = DRBG_ERROR; + RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_GENERATE_ERROR); + return 0; + } + + drbg->reseed_gen_counter++; + + return 1; +} + +/* + * Generates |outlen| random bytes and stores them in |out|. It will + * using the given |drbg| to generate the bytes. + * + * Requires that drbg->lock is already locked for write, if non-null. + * + * Returns 1 on success 0 on failure. + */ +int RAND_DRBG_bytes(RAND_DRBG *drbg, unsigned char *out, size_t outlen) +{ + unsigned char *additional = NULL; + size_t additional_len; + size_t chunk; + size_t ret = 0; + + if (drbg->adin_pool == NULL) { + if (drbg->type == 0) + goto err; + drbg->adin_pool = rand_pool_new(0, 0, drbg->max_adinlen); + if (drbg->adin_pool == NULL) + goto err; + } + + additional_len = rand_drbg_get_additional_data(drbg->adin_pool, + &additional); + + for ( ; outlen > 0; outlen -= chunk, out += chunk) { + chunk = outlen; + if (chunk > drbg->max_request) + chunk = drbg->max_request; + ret = RAND_DRBG_generate(drbg, out, chunk, 0, additional, additional_len); + if (!ret) + goto err; + } + ret = 1; + + err: + if (additional != NULL) + rand_drbg_cleanup_additional_data(drbg->adin_pool, additional); + + return ret; +} + +/* + * Set the RAND_DRBG callbacks for obtaining entropy and nonce. + * + * Setting the callbacks is allowed only if the drbg has not been + * initialized yet. Otherwise, the operation will fail. + * + * Returns 1 on success, 0 on failure. + */ +int RAND_DRBG_set_callbacks(RAND_DRBG *drbg, + RAND_DRBG_get_entropy_fn get_entropy, + RAND_DRBG_cleanup_entropy_fn cleanup_entropy, + RAND_DRBG_get_nonce_fn get_nonce, + RAND_DRBG_cleanup_nonce_fn cleanup_nonce) +{ + if (drbg->state != DRBG_UNINITIALISED + || drbg->parent != NULL) + return 0; + drbg->get_entropy = get_entropy; + drbg->cleanup_entropy = cleanup_entropy; + drbg->get_nonce = get_nonce; + drbg->cleanup_nonce = cleanup_nonce; + return 1; +} + +/* + * Set the reseed interval. + * + * The drbg will reseed automatically whenever the number of generate + * requests exceeds the given reseed interval. If the reseed interval + * is 0, then this feature is disabled. + * + * Returns 1 on success, 0 on failure. + */ +int RAND_DRBG_set_reseed_interval(RAND_DRBG *drbg, unsigned int interval) +{ + if (interval > MAX_RESEED_INTERVAL) + return 0; + drbg->reseed_interval = interval; + return 1; +} + +/* + * Set the reseed time interval. + * + * The drbg will reseed automatically whenever the time elapsed since + * the last reseeding exceeds the given reseed time interval. For safety, + * a reseeding will also occur if the clock has been reset to a smaller + * value. + * + * Returns 1 on success, 0 on failure. + */ +int RAND_DRBG_set_reseed_time_interval(RAND_DRBG *drbg, time_t interval) +{ + if (interval > MAX_RESEED_TIME_INTERVAL) + return 0; + drbg->reseed_time_interval = interval; + return 1; +} + +/* + * Set the default values for reseed (time) intervals of new DRBG instances + * + * The default values can be set independently for master DRBG instances + * (without a parent) and slave DRBG instances (with parent). + * + * Returns 1 on success, 0 on failure. + */ + +int RAND_DRBG_set_reseed_defaults( + unsigned int _master_reseed_interval, + unsigned int _slave_reseed_interval, + time_t _master_reseed_time_interval, + time_t _slave_reseed_time_interval + ) +{ + if (_master_reseed_interval > MAX_RESEED_INTERVAL + || _slave_reseed_interval > MAX_RESEED_INTERVAL) + return 0; + + if (_master_reseed_time_interval > MAX_RESEED_TIME_INTERVAL + || _slave_reseed_time_interval > MAX_RESEED_TIME_INTERVAL) + return 0; + + master_reseed_interval = _master_reseed_interval; + slave_reseed_interval = _slave_reseed_interval; + + master_reseed_time_interval = _master_reseed_time_interval; + slave_reseed_time_interval = _slave_reseed_time_interval; + + return 1; +} + +/* + * Locks the given drbg. Locking a drbg which does not have locking + * enabled is considered a successful no-op. + * + * Returns 1 on success, 0 on failure. + */ +int rand_drbg_lock(RAND_DRBG *drbg) +{ + if (drbg->lock != NULL) + return CRYPTO_THREAD_write_lock(drbg->lock); + + return 1; +} + +/* + * Unlocks the given drbg. Unlocking a drbg which does not have locking + * enabled is considered a successful no-op. + * + * Returns 1 on success, 0 on failure. + */ +int rand_drbg_unlock(RAND_DRBG *drbg) +{ + if (drbg->lock != NULL) + return CRYPTO_THREAD_unlock(drbg->lock); + + return 1; +} + +/* + * Enables locking for the given drbg + * + * Locking can only be enabled if the random generator + * is in the uninitialized state. + * + * Returns 1 on success, 0 on failure. + */ +int rand_drbg_enable_locking(RAND_DRBG *drbg) +{ + if (drbg->state != DRBG_UNINITIALISED) { + RANDerr(RAND_F_RAND_DRBG_ENABLE_LOCKING, + RAND_R_DRBG_ALREADY_INITIALIZED); + return 0; + } + + if (drbg->lock == NULL) { + if (drbg->parent != NULL && drbg->parent->lock == NULL) { + RANDerr(RAND_F_RAND_DRBG_ENABLE_LOCKING, + RAND_R_PARENT_LOCKING_NOT_ENABLED); + return 0; + } + + drbg->lock = CRYPTO_THREAD_lock_new(); + if (drbg->lock == NULL) { + RANDerr(RAND_F_RAND_DRBG_ENABLE_LOCKING, + RAND_R_FAILED_TO_CREATE_LOCK); + return 0; + } + } + + return 1; +} + +/* + * Get and set the EXDATA + */ +int RAND_DRBG_set_ex_data(RAND_DRBG *drbg, int idx, void *arg) +{ + return CRYPTO_set_ex_data(&drbg->ex_data, idx, arg); +} + +void *RAND_DRBG_get_ex_data(const RAND_DRBG *drbg, int idx) +{ + return CRYPTO_get_ex_data(&drbg->ex_data, idx); +} + + +/* + * The following functions provide a RAND_METHOD that works on the + * global DRBG. They lock. + */ + +/* + * Allocates a new global DRBG on the secure heap (if enabled) and + * initializes it with default settings. + * + * Returns a pointer to the new DRBG instance on success, NULL on failure. + */ +static RAND_DRBG *drbg_setup(RAND_DRBG *parent) +{ + RAND_DRBG *drbg; + + drbg = RAND_DRBG_secure_new(rand_drbg_type, rand_drbg_flags, parent); + if (drbg == NULL) + return NULL; + + /* Only the master DRBG needs to have a lock */ + if (parent == NULL && rand_drbg_enable_locking(drbg) == 0) + goto err; + + /* enable seed propagation */ + tsan_store(&drbg->reseed_prop_counter, 1); + + /* + * Ignore instantiation error to support just-in-time instantiation. + * + * The state of the drbg will be checked in RAND_DRBG_generate() and + * an automatic recovery is attempted. + */ + (void)RAND_DRBG_instantiate(drbg, + (const unsigned char *) ossl_pers_string, + sizeof(ossl_pers_string) - 1); + return drbg; + +err: + RAND_DRBG_free(drbg); + return NULL; +} + +/* + * Initialize the global DRBGs on first use. + * Returns 1 on success, 0 on failure. + */ +DEFINE_RUN_ONCE_STATIC(do_rand_drbg_init) +{ + /* + * ensure that libcrypto is initialized, otherwise the + * DRBG locks are not cleaned up properly + */ + if (!OPENSSL_init_crypto(0, NULL)) + return 0; + + if (!CRYPTO_THREAD_init_local(&private_drbg, NULL)) + return 0; + + if (!CRYPTO_THREAD_init_local(&public_drbg, NULL)) + goto err1; + + master_drbg = drbg_setup(NULL); + if (master_drbg == NULL) + goto err2; + + return 1; + +err2: + CRYPTO_THREAD_cleanup_local(&public_drbg); +err1: + CRYPTO_THREAD_cleanup_local(&private_drbg); + return 0; +} + +/* Clean up the global DRBGs before exit */ +void rand_drbg_cleanup_int(void) +{ + if (master_drbg != NULL) { + RAND_DRBG_free(master_drbg); + master_drbg = NULL; + + CRYPTO_THREAD_cleanup_local(&private_drbg); + CRYPTO_THREAD_cleanup_local(&public_drbg); + } +} + +void drbg_delete_thread_state(void) +{ + RAND_DRBG *drbg; + + drbg = CRYPTO_THREAD_get_local(&public_drbg); + CRYPTO_THREAD_set_local(&public_drbg, NULL); + RAND_DRBG_free(drbg); + + drbg = CRYPTO_THREAD_get_local(&private_drbg); + CRYPTO_THREAD_set_local(&private_drbg, NULL); + RAND_DRBG_free(drbg); +} + +/* Implements the default OpenSSL RAND_bytes() method */ +static int drbg_bytes(unsigned char *out, int count) +{ + int ret; + RAND_DRBG *drbg = RAND_DRBG_get0_public(); + + if (drbg == NULL) + return 0; + + ret = RAND_DRBG_bytes(drbg, out, count); + + return ret; +} + +/* + * Calculates the minimum length of a full entropy buffer + * which is necessary to seed (i.e. instantiate) the DRBG + * successfully. + */ +size_t rand_drbg_seedlen(RAND_DRBG *drbg) +{ + /* + * If no os entropy source is available then RAND_seed(buffer, bufsize) + * is expected to succeed if and only if the buffer length satisfies + * the following requirements, which follow from the calculations + * in RAND_DRBG_instantiate(). + */ + size_t min_entropy = drbg->strength; + size_t min_entropylen = drbg->min_entropylen; + + /* + * Extra entropy for the random nonce in the absence of a + * get_nonce callback, see comment in RAND_DRBG_instantiate(). + */ + if (drbg->min_noncelen > 0 && drbg->get_nonce == NULL) { + min_entropy += drbg->strength / 2; + min_entropylen += drbg->min_noncelen; + } + + /* + * Convert entropy requirement from bits to bytes + * (dividing by 8 without rounding upwards, because + * all entropy requirements are divisible by 8). + */ + min_entropy >>= 3; + + /* Return a value that satisfies both requirements */ + return min_entropy > min_entropylen ? min_entropy : min_entropylen; +} + +/* Implements the default OpenSSL RAND_add() method */ +static int drbg_add(const void *buf, int num, double randomness) +{ + int ret = 0; + RAND_DRBG *drbg = RAND_DRBG_get0_master(); + size_t buflen; + size_t seedlen; + + if (drbg == NULL) + return 0; + + if (num < 0 || randomness < 0.0) + return 0; + + rand_drbg_lock(drbg); + seedlen = rand_drbg_seedlen(drbg); + + buflen = (size_t)num; + + if (buflen < seedlen || randomness < (double) seedlen) { +#if defined(OPENSSL_RAND_SEED_NONE) + /* + * If no os entropy source is available, a reseeding will fail + * inevitably. So we use a trick to mix the buffer contents into + * the DRBG state without forcing a reseeding: we generate a + * dummy random byte, using the buffer content as additional data. + * Note: This won't work with RAND_DRBG_FLAG_CTR_NO_DF. + */ + unsigned char dummy[1]; + + ret = RAND_DRBG_generate(drbg, dummy, sizeof(dummy), 0, buf, buflen); + rand_drbg_unlock(drbg); + return ret; +#else + /* + * If an os entropy source is avaible then we declare the buffer content + * as additional data by setting randomness to zero and trigger a regular + * reseeding. + */ + randomness = 0.0; +#endif + } + + + if (randomness > (double)seedlen) { + /* + * The purpose of this check is to bound |randomness| by a + * relatively small value in order to prevent an integer + * overflow when multiplying by 8 in the rand_drbg_restart() + * call below. Note that randomness is measured in bytes, + * not bits, so this value corresponds to eight times the + * security strength. + */ + randomness = (double)seedlen; + } + + ret = rand_drbg_restart(drbg, buf, buflen, (size_t)(8 * randomness)); + rand_drbg_unlock(drbg); + + return ret; +} + +/* Implements the default OpenSSL RAND_seed() method */ +static int drbg_seed(const void *buf, int num) +{ + return drbg_add(buf, num, num); +} + +/* Implements the default OpenSSL RAND_status() method */ +static int drbg_status(void) +{ + int ret; + RAND_DRBG *drbg = RAND_DRBG_get0_master(); + + if (drbg == NULL) + return 0; + + rand_drbg_lock(drbg); + ret = drbg->state == DRBG_READY ? 1 : 0; + rand_drbg_unlock(drbg); + return ret; +} + +/* + * Get the master DRBG. + * Returns pointer to the DRBG on success, NULL on failure. + * + */ +RAND_DRBG *RAND_DRBG_get0_master(void) +{ + if (!RUN_ONCE(&rand_drbg_init, do_rand_drbg_init)) + return NULL; + + return master_drbg; +} + +/* + * Get the public DRBG. + * Returns pointer to the DRBG on success, NULL on failure. + */ +RAND_DRBG *RAND_DRBG_get0_public(void) +{ + RAND_DRBG *drbg; + + if (!RUN_ONCE(&rand_drbg_init, do_rand_drbg_init)) + return NULL; + + drbg = CRYPTO_THREAD_get_local(&public_drbg); + if (drbg == NULL) { + if (!ossl_init_thread_start(OPENSSL_INIT_THREAD_RAND)) + return NULL; + drbg = drbg_setup(master_drbg); + CRYPTO_THREAD_set_local(&public_drbg, drbg); + } + return drbg; +} + +/* + * Get the private DRBG. + * Returns pointer to the DRBG on success, NULL on failure. + */ +RAND_DRBG *RAND_DRBG_get0_private(void) +{ + RAND_DRBG *drbg; + + if (!RUN_ONCE(&rand_drbg_init, do_rand_drbg_init)) + return NULL; + + drbg = CRYPTO_THREAD_get_local(&private_drbg); + if (drbg == NULL) { + if (!ossl_init_thread_start(OPENSSL_INIT_THREAD_RAND)) + return NULL; + drbg = drbg_setup(master_drbg); + CRYPTO_THREAD_set_local(&private_drbg, drbg); + } + return drbg; +} + +RAND_METHOD rand_meth = { + drbg_seed, + drbg_bytes, + NULL, + drbg_add, + drbg_bytes, + drbg_status +}; + +RAND_METHOD *RAND_OpenSSL(void) +{ + return &rand_meth; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rand/rand_egd.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rand/rand_egd.c new file mode 100644 index 000000000..da3017df3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rand/rand_egd.c @@ -0,0 +1,158 @@ +/* + * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#ifdef OPENSSL_NO_EGD +NON_EMPTY_TRANSLATION_UNIT +#else + +# include +# include +# include + +/* + * Query an EGD + */ + +# if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_VOS) || defined(OPENSSL_SYS_UEFI) +int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes) +{ + return -1; +} + +int RAND_egd(const char *path) +{ + return -1; +} + +int RAND_egd_bytes(const char *path, int bytes) +{ + return -1; +} + +# else + +# include OPENSSL_UNISTD +# include +# include +# include +# ifndef NO_SYS_UN_H +# ifdef OPENSSL_SYS_VXWORKS +# include +# else +# include +# endif +# else +struct sockaddr_un { + short sun_family; /* AF_UNIX */ + char sun_path[108]; /* path name (gag) */ +}; +# endif /* NO_SYS_UN_H */ +# include +# include + +int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes) +{ + FILE *fp = NULL; + struct sockaddr_un addr; + int mybuffer, ret = -1, i, numbytes, fd; + unsigned char tempbuf[255]; + + if (bytes > (int)sizeof(tempbuf)) + return -1; + + /* Make socket. */ + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + if (strlen(path) >= sizeof(addr.sun_path)) + return -1; + strcpy(addr.sun_path, path); + i = offsetof(struct sockaddr_un, sun_path) + strlen(path); + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd == -1 || (fp = fdopen(fd, "r+")) == NULL) + return -1; + setbuf(fp, NULL); + + /* Try to connect */ + for ( ; ; ) { + if (connect(fd, (struct sockaddr *)&addr, i) == 0) + break; +# ifdef EISCONN + if (errno == EISCONN) + break; +# endif + switch (errno) { +# ifdef EINTR + case EINTR: +# endif +# ifdef EAGAIN + case EAGAIN: +# endif +# ifdef EINPROGRESS + case EINPROGRESS: +# endif +# ifdef EALREADY + case EALREADY: +# endif + /* No error, try again */ + break; + default: + ret = -1; + goto err; + } + } + + /* Make request, see how many bytes we can get back. */ + tempbuf[0] = 1; + tempbuf[1] = bytes; + if (fwrite(tempbuf, sizeof(char), 2, fp) != 2 || fflush(fp) == EOF) + goto err; + if (fread(tempbuf, sizeof(char), 1, fp) != 1 || tempbuf[0] == 0) + goto err; + numbytes = tempbuf[0]; + + /* Which buffer are we using? */ + mybuffer = buf == NULL; + if (mybuffer) + buf = tempbuf; + + /* Read bytes. */ + i = fread(buf, sizeof(char), numbytes, fp); + if (i < numbytes) + goto err; + ret = numbytes; + if (mybuffer) + RAND_add(tempbuf, i, i); + + err: + if (fp != NULL) + fclose(fp); + return ret; +} + +int RAND_egd_bytes(const char *path, int bytes) +{ + int num; + + num = RAND_query_egd_bytes(path, NULL, bytes); + if (num < 0) + return -1; + if (RAND_status() != 1) + return -1; + return num; +} + +int RAND_egd(const char *path) +{ + return RAND_egd_bytes(path, 255); +} + +# endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rand/rand_err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rand/rand_err.c new file mode 100644 index 000000000..6a870455d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rand/rand_err.c @@ -0,0 +1,135 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA RAND_str_functs[] = { + {ERR_PACK(ERR_LIB_RAND, RAND_F_DRBG_BYTES, 0), "drbg_bytes"}, + {ERR_PACK(ERR_LIB_RAND, RAND_F_DRBG_GET_ENTROPY, 0), "drbg_get_entropy"}, + {ERR_PACK(ERR_LIB_RAND, RAND_F_DRBG_SETUP, 0), "drbg_setup"}, + {ERR_PACK(ERR_LIB_RAND, RAND_F_GET_ENTROPY, 0), "get_entropy"}, + {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_BYTES, 0), "RAND_bytes"}, + {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_ENABLE_LOCKING, 0), + "rand_drbg_enable_locking"}, + {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_GENERATE, 0), + "RAND_DRBG_generate"}, + {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_GET_ENTROPY, 0), + "rand_drbg_get_entropy"}, + {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_GET_NONCE, 0), + "rand_drbg_get_nonce"}, + {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_INSTANTIATE, 0), + "RAND_DRBG_instantiate"}, + {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_NEW, 0), "RAND_DRBG_new"}, + {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_RESEED, 0), "RAND_DRBG_reseed"}, + {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_RESTART, 0), "rand_drbg_restart"}, + {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_SET, 0), "RAND_DRBG_set"}, + {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_SET_DEFAULTS, 0), + "RAND_DRBG_set_defaults"}, + {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_UNINSTANTIATE, 0), + "RAND_DRBG_uninstantiate"}, + {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_LOAD_FILE, 0), "RAND_load_file"}, + {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_ACQUIRE_ENTROPY, 0), + "rand_pool_acquire_entropy"}, + {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_ADD, 0), "rand_pool_add"}, + {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_ADD_BEGIN, 0), + "rand_pool_add_begin"}, + {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_ADD_END, 0), "rand_pool_add_end"}, + {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_ATTACH, 0), "rand_pool_attach"}, + {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_BYTES_NEEDED, 0), + "rand_pool_bytes_needed"}, + {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_NEW, 0), "rand_pool_new"}, + {ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_WRITE_FILE, 0), "RAND_write_file"}, + {0, NULL} +}; + +static const ERR_STRING_DATA RAND_str_reasons[] = { + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ADDITIONAL_INPUT_TOO_LONG), + "additional input too long"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ALREADY_INSTANTIATED), + "already instantiated"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ARGUMENT_OUT_OF_RANGE), + "argument out of range"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_CANNOT_OPEN_FILE), "Cannot open file"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_DRBG_ALREADY_INITIALIZED), + "drbg already initialized"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_DRBG_NOT_INITIALISED), + "drbg not initialised"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ENTROPY_INPUT_TOO_LONG), + "entropy input too long"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ENTROPY_OUT_OF_RANGE), + "entropy out of range"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ERROR_ENTROPY_POOL_WAS_IGNORED), + "error entropy pool was ignored"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ERROR_INITIALISING_DRBG), + "error initialising drbg"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ERROR_INSTANTIATING_DRBG), + "error instantiating drbg"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ERROR_RETRIEVING_ADDITIONAL_INPUT), + "error retrieving additional input"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ERROR_RETRIEVING_ENTROPY), + "error retrieving entropy"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ERROR_RETRIEVING_NONCE), + "error retrieving nonce"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_FAILED_TO_CREATE_LOCK), + "failed to create lock"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_FUNC_NOT_IMPLEMENTED), + "Function not implemented"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_FWRITE_ERROR), "Error writing file"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_GENERATE_ERROR), "generate error"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_INTERNAL_ERROR), "internal error"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_IN_ERROR_STATE), "in error state"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_NOT_A_REGULAR_FILE), + "Not a regular file"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_NOT_INSTANTIATED), "not instantiated"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED), + "no drbg implementation selected"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_PARENT_LOCKING_NOT_ENABLED), + "parent locking not enabled"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_PARENT_STRENGTH_TOO_WEAK), + "parent strength too weak"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_PERSONALISATION_STRING_TOO_LONG), + "personalisation string too long"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_PREDICTION_RESISTANCE_NOT_SUPPORTED), + "prediction resistance not supported"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_PRNG_NOT_SEEDED), "PRNG not seeded"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_RANDOM_POOL_OVERFLOW), + "random pool overflow"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_RANDOM_POOL_UNDERFLOW), + "random pool underflow"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_REQUEST_TOO_LARGE_FOR_DRBG), + "request too large for drbg"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_RESEED_ERROR), "reseed error"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_SELFTEST_FAILURE), "selftest failure"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_TOO_LITTLE_NONCE_REQUESTED), + "too little nonce requested"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_TOO_MUCH_NONCE_REQUESTED), + "too much nonce requested"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNSUPPORTED_DRBG_FLAGS), + "unsupported drbg flags"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNSUPPORTED_DRBG_TYPE), + "unsupported drbg type"}, + {0, NULL} +}; + +#endif + +int ERR_load_RAND_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(RAND_str_functs[0].error) == NULL) { + ERR_load_strings_const(RAND_str_functs); + ERR_load_strings_const(RAND_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rand/rand_lcl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/rand/rand_lcl.h new file mode 100644 index 000000000..c3e9804dc --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rand/rand_lcl.h @@ -0,0 +1,293 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_RAND_LCL_H +# define HEADER_RAND_LCL_H + +# include +# include +# include +# include +# include +# include +# include "internal/tsan_assist.h" + +# include "internal/numbers.h" + +/* How many times to read the TSC as a randomness source. */ +# define TSC_READ_COUNT 4 + +/* Maximum reseed intervals */ +# define MAX_RESEED_INTERVAL (1 << 24) +# define MAX_RESEED_TIME_INTERVAL (1 << 20) /* approx. 12 days */ + +/* Default reseed intervals */ +# define MASTER_RESEED_INTERVAL (1 << 8) +# define SLAVE_RESEED_INTERVAL (1 << 16) +# define MASTER_RESEED_TIME_INTERVAL (60*60) /* 1 hour */ +# define SLAVE_RESEED_TIME_INTERVAL (7*60) /* 7 minutes */ + + + +/* + * Maximum input size for the DRBG (entropy, nonce, personalization string) + * + * NIST SP800 90Ar1 allows a maximum of (1 << 35) bits i.e., (1 << 32) bytes. + * + * We lower it to 'only' INT32_MAX bytes, which is equivalent to 2 gigabytes. + */ +# define DRBG_MAX_LENGTH INT32_MAX + + + +/* + * Maximum allocation size for RANDOM_POOL buffers + * + * The max_len value for the buffer provided to the rand_drbg_get_entropy() + * callback is currently 2^31 bytes (2 gigabytes), if a derivation function + * is used. Since this is much too large to be allocated, the rand_pool_new() + * function chooses more modest values as default pool length, bounded + * by RAND_POOL_MIN_LENGTH and RAND_POOL_MAX_LENGTH + * + * The choice of the RAND_POOL_FACTOR is large enough such that the + * RAND_POOL can store a random input which has a lousy entropy rate of + * 8/256 (= 0.03125) bits per byte. This input will be sent through the + * derivation function which 'compresses' the low quality input into a + * high quality output. + * + * The factor 1.5 below is the pessimistic estimate for the extra amount + * of entropy required when no get_nonce() callback is defined. + */ +# define RAND_POOL_FACTOR 256 +# define RAND_POOL_MAX_LENGTH (RAND_POOL_FACTOR * \ + 3 * (RAND_DRBG_STRENGTH / 16)) +/* + * = (RAND_POOL_FACTOR * \ + * 1.5 * (RAND_DRBG_STRENGTH / 8)) + */ + + +/* DRBG status values */ +typedef enum drbg_status_e { + DRBG_UNINITIALISED, + DRBG_READY, + DRBG_ERROR +} DRBG_STATUS; + + +/* instantiate */ +typedef int (*RAND_DRBG_instantiate_fn)(RAND_DRBG *ctx, + const unsigned char *ent, + size_t entlen, + const unsigned char *nonce, + size_t noncelen, + const unsigned char *pers, + size_t perslen); +/* reseed */ +typedef int (*RAND_DRBG_reseed_fn)(RAND_DRBG *ctx, + const unsigned char *ent, + size_t entlen, + const unsigned char *adin, + size_t adinlen); +/* generate output */ +typedef int (*RAND_DRBG_generate_fn)(RAND_DRBG *ctx, + unsigned char *out, + size_t outlen, + const unsigned char *adin, + size_t adinlen); +/* uninstantiate */ +typedef int (*RAND_DRBG_uninstantiate_fn)(RAND_DRBG *ctx); + + +/* + * The DRBG methods + */ + +typedef struct rand_drbg_method_st { + RAND_DRBG_instantiate_fn instantiate; + RAND_DRBG_reseed_fn reseed; + RAND_DRBG_generate_fn generate; + RAND_DRBG_uninstantiate_fn uninstantiate; +} RAND_DRBG_METHOD; + + +/* + * The state of a DRBG AES-CTR. + */ +typedef struct rand_drbg_ctr_st { + EVP_CIPHER_CTX *ctx; + EVP_CIPHER_CTX *ctx_df; + const EVP_CIPHER *cipher; + size_t keylen; + unsigned char K[32]; + unsigned char V[16]; + /* Temporary block storage used by ctr_df */ + unsigned char bltmp[16]; + size_t bltmp_pos; + unsigned char KX[48]; +} RAND_DRBG_CTR; + + +/* + * The 'random pool' acts as a dumb container for collecting random + * input from various entropy sources. The pool has no knowledge about + * whether its randomness is fed into a legacy RAND_METHOD via RAND_add() + * or into a new style RAND_DRBG. It is the callers duty to 1) initialize the + * random pool, 2) pass it to the polling callbacks, 3) seed the RNG, and + * 4) cleanup the random pool again. + * + * The random pool contains no locking mechanism because its scope and + * lifetime is intended to be restricted to a single stack frame. + */ +struct rand_pool_st { + unsigned char *buffer; /* points to the beginning of the random pool */ + size_t len; /* current number of random bytes contained in the pool */ + + int attached; /* true pool was attached to existing buffer */ + + size_t min_len; /* minimum number of random bytes requested */ + size_t max_len; /* maximum number of random bytes (allocated buffer size) */ + size_t entropy; /* current entropy count in bits */ + size_t entropy_requested; /* requested entropy count in bits */ +}; + +/* + * The state of all types of DRBGs, even though we only have CTR mode + * right now. + */ +struct rand_drbg_st { + CRYPTO_RWLOCK *lock; + RAND_DRBG *parent; + int secure; /* 1: allocated on the secure heap, 0: otherwise */ + int type; /* the nid of the underlying algorithm */ + /* + * Stores the value of the rand_fork_count global as of when we last + * reseeded. The DRBG reseeds automatically whenever drbg->fork_count != + * rand_fork_count. Used to provide fork-safety and reseed this DRBG in + * the child process. + */ + int fork_count; + unsigned short flags; /* various external flags */ + + /* + * The random_data is used by RAND_add()/drbg_add() to attach random + * data to the global drbg, such that the rand_drbg_get_entropy() callback + * can pull it during instantiation and reseeding. This is necessary to + * reconcile the different philosophies of the RAND and the RAND_DRBG + * with respect to how randomness is added to the RNG during reseeding + * (see PR #4328). + */ + struct rand_pool_st *seed_pool; + + /* + * Auxiliary pool for additional data. + */ + struct rand_pool_st *adin_pool; + + /* + * The following parameters are setup by the per-type "init" function. + * + * Currently the only type is CTR_DRBG, its init function is drbg_ctr_init(). + * + * The parameters are closely related to the ones described in + * section '10.2.1 CTR_DRBG' of [NIST SP 800-90Ar1], with one + * crucial difference: In the NIST standard, all counts are given + * in bits, whereas in OpenSSL entropy counts are given in bits + * and buffer lengths are given in bytes. + * + * Since this difference has lead to some confusion in the past, + * (see [GitHub Issue #2443], formerly [rt.openssl.org #4055]) + * the 'len' suffix has been added to all buffer sizes for + * clarification. + */ + + int strength; + size_t max_request; + size_t min_entropylen, max_entropylen; + size_t min_noncelen, max_noncelen; + size_t max_perslen, max_adinlen; + + /* Counts the number of generate requests since the last reseed. */ + unsigned int reseed_gen_counter; + /* + * Maximum number of generate requests until a reseed is required. + * This value is ignored if it is zero. + */ + unsigned int reseed_interval; + /* Stores the time when the last reseeding occurred */ + time_t reseed_time; + /* + * Specifies the maximum time interval (in seconds) between reseeds. + * This value is ignored if it is zero. + */ + time_t reseed_time_interval; + /* + * Counts the number of reseeds since instantiation. + * This value is ignored if it is zero. + * + * This counter is used only for seed propagation from the DRBG + * to its two children, the and DRBG. This feature is + * very special and its sole purpose is to ensure that any randomness which + * is added by RAND_add() or RAND_seed() will have an immediate effect on + * the output of RAND_bytes() resp. RAND_priv_bytes(). + */ + TSAN_QUALIFIER unsigned int reseed_prop_counter; + unsigned int reseed_next_counter; + + size_t seedlen; + DRBG_STATUS state; + + /* Application data, mainly used in the KATs. */ + CRYPTO_EX_DATA ex_data; + + /* Implementation specific data (currently only one implementation) */ + union { + RAND_DRBG_CTR ctr; + } data; + + /* Implementation specific methods */ + RAND_DRBG_METHOD *meth; + + /* Callback functions. See comments in rand_lib.c */ + RAND_DRBG_get_entropy_fn get_entropy; + RAND_DRBG_cleanup_entropy_fn cleanup_entropy; + RAND_DRBG_get_nonce_fn get_nonce; + RAND_DRBG_cleanup_nonce_fn cleanup_nonce; +}; + +/* The global RAND method, and the global buffer and DRBG instance. */ +extern RAND_METHOD rand_meth; + +/* + * A "generation count" of forks. Incremented in the child process after a + * fork. Since rand_fork_count is increment-only, and only ever written to in + * the child process of the fork, which is guaranteed to be single-threaded, no + * locking is needed for normal (read) accesses; the rest of pthread fork + * processing is assumed to introduce the necessary memory barriers. Sibling + * children of a given parent will produce duplicate values, but this is not + * problematic because the reseeding process pulls input from the system CSPRNG + * and/or other global sources, so the siblings will end up generating + * different output streams. + */ +extern int rand_fork_count; + +/* DRBG helpers */ +int rand_drbg_restart(RAND_DRBG *drbg, + const unsigned char *buffer, size_t len, size_t entropy); +size_t rand_drbg_seedlen(RAND_DRBG *drbg); +/* locking api */ +int rand_drbg_lock(RAND_DRBG *drbg); +int rand_drbg_unlock(RAND_DRBG *drbg); +int rand_drbg_enable_locking(RAND_DRBG *drbg); + + +/* initializes the AES-CTR DRBG implementation */ +int drbg_ctr_init(RAND_DRBG *drbg); + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rand/rand_lib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rand/rand_lib.c new file mode 100644 index 000000000..d8639c4a0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rand/rand_lib.c @@ -0,0 +1,859 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include +#include "internal/rand_int.h" +#include +#include "internal/thread_once.h" +#include "rand_lcl.h" +#include "e_os.h" + +#ifndef OPENSSL_NO_ENGINE +/* non-NULL if default_RAND_meth is ENGINE-provided */ +static ENGINE *funct_ref; +static CRYPTO_RWLOCK *rand_engine_lock; +#endif +static CRYPTO_RWLOCK *rand_meth_lock; +static const RAND_METHOD *default_RAND_meth; +static CRYPTO_ONCE rand_init = CRYPTO_ONCE_STATIC_INIT; + +int rand_fork_count; + +static CRYPTO_RWLOCK *rand_nonce_lock; +static int rand_nonce_count; + +static int rand_inited = 0; + +#ifdef OPENSSL_RAND_SEED_RDTSC +/* + * IMPORTANT NOTE: It is not currently possible to use this code + * because we are not sure about the amount of randomness it provides. + * Some SP900 tests have been run, but there is internal skepticism. + * So for now this code is not used. + */ +# error "RDTSC enabled? Should not be possible!" + +/* + * Acquire entropy from high-speed clock + * + * Since we get some randomness from the low-order bits of the + * high-speed clock, it can help. + * + * Returns the total entropy count, if it exceeds the requested + * entropy count. Otherwise, returns an entropy count of 0. + */ +size_t rand_acquire_entropy_from_tsc(RAND_POOL *pool) +{ + unsigned char c; + int i; + + if ((OPENSSL_ia32cap_P[0] & (1 << 4)) != 0) { + for (i = 0; i < TSC_READ_COUNT; i++) { + c = (unsigned char)(OPENSSL_rdtsc() & 0xFF); + rand_pool_add(pool, &c, 1, 4); + } + } + return rand_pool_entropy_available(pool); +} +#endif + +#ifdef OPENSSL_RAND_SEED_RDCPU +size_t OPENSSL_ia32_rdseed_bytes(unsigned char *buf, size_t len); +size_t OPENSSL_ia32_rdrand_bytes(unsigned char *buf, size_t len); + +extern unsigned int OPENSSL_ia32cap_P[]; + +/* + * Acquire entropy using Intel-specific cpu instructions + * + * Uses the RDSEED instruction if available, otherwise uses + * RDRAND if available. + * + * For the differences between RDSEED and RDRAND, and why RDSEED + * is the preferred choice, see https://goo.gl/oK3KcN + * + * Returns the total entropy count, if it exceeds the requested + * entropy count. Otherwise, returns an entropy count of 0. + */ +size_t rand_acquire_entropy_from_cpu(RAND_POOL *pool) +{ + size_t bytes_needed; + unsigned char *buffer; + + bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); + if (bytes_needed > 0) { + buffer = rand_pool_add_begin(pool, bytes_needed); + + if (buffer != NULL) { + /* Whichever comes first, use RDSEED, RDRAND or nothing */ + if ((OPENSSL_ia32cap_P[2] & (1 << 18)) != 0) { + if (OPENSSL_ia32_rdseed_bytes(buffer, bytes_needed) + == bytes_needed) { + rand_pool_add_end(pool, bytes_needed, 8 * bytes_needed); + } + } else if ((OPENSSL_ia32cap_P[1] & (1 << (62 - 32))) != 0) { + if (OPENSSL_ia32_rdrand_bytes(buffer, bytes_needed) + == bytes_needed) { + rand_pool_add_end(pool, bytes_needed, 8 * bytes_needed); + } + } else { + rand_pool_add_end(pool, 0, 0); + } + } + } + + return rand_pool_entropy_available(pool); +} +#endif + + +/* + * Implements the get_entropy() callback (see RAND_DRBG_set_callbacks()) + * + * If the DRBG has a parent, then the required amount of entropy input + * is fetched using the parent's RAND_DRBG_generate(). + * + * Otherwise, the entropy is polled from the system entropy sources + * using rand_pool_acquire_entropy(). + * + * If a random pool has been added to the DRBG using RAND_add(), then + * its entropy will be used up first. + */ +size_t rand_drbg_get_entropy(RAND_DRBG *drbg, + unsigned char **pout, + int entropy, size_t min_len, size_t max_len, + int prediction_resistance) +{ + size_t ret = 0; + size_t entropy_available = 0; + RAND_POOL *pool; + + if (drbg->parent && drbg->strength > drbg->parent->strength) { + /* + * We currently don't support the algorithm from NIST SP 800-90C + * 10.1.2 to use a weaker DRBG as source + */ + RANDerr(RAND_F_RAND_DRBG_GET_ENTROPY, RAND_R_PARENT_STRENGTH_TOO_WEAK); + return 0; + } + + if (drbg->seed_pool != NULL) { + pool = drbg->seed_pool; + pool->entropy_requested = entropy; + } else { + pool = rand_pool_new(entropy, min_len, max_len); + if (pool == NULL) + return 0; + } + + if (drbg->parent) { + size_t bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); + unsigned char *buffer = rand_pool_add_begin(pool, bytes_needed); + + if (buffer != NULL) { + size_t bytes = 0; + + /* + * Get random from parent, include our state as additional input. + * Our lock is already held, but we need to lock our parent before + * generating bits from it. (Note: taking the lock will be a no-op + * if locking if drbg->parent->lock == NULL.) + */ + rand_drbg_lock(drbg->parent); + if (RAND_DRBG_generate(drbg->parent, + buffer, bytes_needed, + prediction_resistance, + NULL, 0) != 0) + bytes = bytes_needed; + drbg->reseed_next_counter + = tsan_load(&drbg->parent->reseed_prop_counter); + rand_drbg_unlock(drbg->parent); + + rand_pool_add_end(pool, bytes, 8 * bytes); + entropy_available = rand_pool_entropy_available(pool); + } + + } else { + if (prediction_resistance) { + /* + * We don't have any entropy sources that comply with the NIST + * standard to provide prediction resistance (see NIST SP 800-90C, + * Section 5.4). + */ + RANDerr(RAND_F_RAND_DRBG_GET_ENTROPY, + RAND_R_PREDICTION_RESISTANCE_NOT_SUPPORTED); + goto err; + } + + /* Get entropy by polling system entropy sources. */ + entropy_available = rand_pool_acquire_entropy(pool); + } + + if (entropy_available > 0) { + ret = rand_pool_length(pool); + *pout = rand_pool_detach(pool); + } + + err: + if (drbg->seed_pool == NULL) + rand_pool_free(pool); + return ret; +} + +/* + * Implements the cleanup_entropy() callback (see RAND_DRBG_set_callbacks()) + * + */ +void rand_drbg_cleanup_entropy(RAND_DRBG *drbg, + unsigned char *out, size_t outlen) +{ + if (drbg->seed_pool == NULL) + OPENSSL_secure_clear_free(out, outlen); +} + + +/* + * Implements the get_nonce() callback (see RAND_DRBG_set_callbacks()) + * + */ +size_t rand_drbg_get_nonce(RAND_DRBG *drbg, + unsigned char **pout, + int entropy, size_t min_len, size_t max_len) +{ + size_t ret = 0; + RAND_POOL *pool; + + struct { + void * instance; + int count; + } data = { 0 }; + + pool = rand_pool_new(0, min_len, max_len); + if (pool == NULL) + return 0; + + if (rand_pool_add_nonce_data(pool) == 0) + goto err; + + data.instance = drbg; + CRYPTO_atomic_add(&rand_nonce_count, 1, &data.count, rand_nonce_lock); + + if (rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0) == 0) + goto err; + + ret = rand_pool_length(pool); + *pout = rand_pool_detach(pool); + + err: + rand_pool_free(pool); + + return ret; +} + +/* + * Implements the cleanup_nonce() callback (see RAND_DRBG_set_callbacks()) + * + */ +void rand_drbg_cleanup_nonce(RAND_DRBG *drbg, + unsigned char *out, size_t outlen) +{ + OPENSSL_secure_clear_free(out, outlen); +} + +/* + * Generate additional data that can be used for the drbg. The data does + * not need to contain entropy, but it's useful if it contains at least + * some bits that are unpredictable. + * + * Returns 0 on failure. + * + * On success it allocates a buffer at |*pout| and returns the length of + * the data. The buffer should get freed using OPENSSL_secure_clear_free(). + */ +size_t rand_drbg_get_additional_data(RAND_POOL *pool, unsigned char **pout) +{ + size_t ret = 0; + + if (rand_pool_add_additional_data(pool) == 0) + goto err; + + ret = rand_pool_length(pool); + *pout = rand_pool_detach(pool); + + err: + return ret; +} + +void rand_drbg_cleanup_additional_data(RAND_POOL *pool, unsigned char *out) +{ + rand_pool_reattach(pool, out); +} + +void rand_fork(void) +{ + rand_fork_count++; +} + +DEFINE_RUN_ONCE_STATIC(do_rand_init) +{ +#ifndef OPENSSL_NO_ENGINE + rand_engine_lock = CRYPTO_THREAD_lock_new(); + if (rand_engine_lock == NULL) + return 0; +#endif + + rand_meth_lock = CRYPTO_THREAD_lock_new(); + if (rand_meth_lock == NULL) + goto err1; + + rand_nonce_lock = CRYPTO_THREAD_lock_new(); + if (rand_nonce_lock == NULL) + goto err2; + + if (!rand_pool_init()) + goto err3; + + rand_inited = 1; + return 1; + +err3: + CRYPTO_THREAD_lock_free(rand_nonce_lock); + rand_nonce_lock = NULL; +err2: + CRYPTO_THREAD_lock_free(rand_meth_lock); + rand_meth_lock = NULL; +err1: +#ifndef OPENSSL_NO_ENGINE + CRYPTO_THREAD_lock_free(rand_engine_lock); + rand_engine_lock = NULL; +#endif + return 0; +} + +void rand_cleanup_int(void) +{ + const RAND_METHOD *meth = default_RAND_meth; + + if (!rand_inited) + return; + + if (meth != NULL && meth->cleanup != NULL) + meth->cleanup(); + RAND_set_rand_method(NULL); + rand_pool_cleanup(); +#ifndef OPENSSL_NO_ENGINE + CRYPTO_THREAD_lock_free(rand_engine_lock); + rand_engine_lock = NULL; +#endif + CRYPTO_THREAD_lock_free(rand_meth_lock); + rand_meth_lock = NULL; + CRYPTO_THREAD_lock_free(rand_nonce_lock); + rand_nonce_lock = NULL; + rand_inited = 0; +} + +/* + * RAND_close_seed_files() ensures that any seed file decriptors are + * closed after use. + */ +void RAND_keep_random_devices_open(int keep) +{ + if (RUN_ONCE(&rand_init, do_rand_init)) + rand_pool_keep_random_devices_open(keep); +} + +/* + * RAND_poll() reseeds the default RNG using random input + * + * The random input is obtained from polling various entropy + * sources which depend on the operating system and are + * configurable via the --with-rand-seed configure option. + */ +int RAND_poll(void) +{ + int ret = 0; + + RAND_POOL *pool = NULL; + + const RAND_METHOD *meth = RAND_get_rand_method(); + + if (meth == RAND_OpenSSL()) { + /* fill random pool and seed the master DRBG */ + RAND_DRBG *drbg = RAND_DRBG_get0_master(); + + if (drbg == NULL) + return 0; + + rand_drbg_lock(drbg); + ret = rand_drbg_restart(drbg, NULL, 0, 0); + rand_drbg_unlock(drbg); + + return ret; + + } else { + /* fill random pool and seed the current legacy RNG */ + pool = rand_pool_new(RAND_DRBG_STRENGTH, + RAND_DRBG_STRENGTH / 8, + RAND_POOL_MAX_LENGTH); + if (pool == NULL) + return 0; + + if (rand_pool_acquire_entropy(pool) == 0) + goto err; + + if (meth->add == NULL + || meth->add(rand_pool_buffer(pool), + rand_pool_length(pool), + (rand_pool_entropy(pool) / 8.0)) == 0) + goto err; + + ret = 1; + } + +err: + rand_pool_free(pool); + return ret; +} + +/* + * Allocate memory and initialize a new random pool + */ + +RAND_POOL *rand_pool_new(int entropy_requested, size_t min_len, size_t max_len) +{ + RAND_POOL *pool = OPENSSL_zalloc(sizeof(*pool)); + + if (pool == NULL) { + RANDerr(RAND_F_RAND_POOL_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + pool->min_len = min_len; + pool->max_len = (max_len > RAND_POOL_MAX_LENGTH) ? + RAND_POOL_MAX_LENGTH : max_len; + + pool->buffer = OPENSSL_secure_zalloc(pool->max_len); + if (pool->buffer == NULL) { + RANDerr(RAND_F_RAND_POOL_NEW, ERR_R_MALLOC_FAILURE); + goto err; + } + + pool->entropy_requested = entropy_requested; + + return pool; + +err: + OPENSSL_free(pool); + return NULL; +} + +/* + * Attach new random pool to the given buffer + * + * This function is intended to be used only for feeding random data + * provided by RAND_add() and RAND_seed() into the DRBG. + */ +RAND_POOL *rand_pool_attach(const unsigned char *buffer, size_t len, + size_t entropy) +{ + RAND_POOL *pool = OPENSSL_zalloc(sizeof(*pool)); + + if (pool == NULL) { + RANDerr(RAND_F_RAND_POOL_ATTACH, ERR_R_MALLOC_FAILURE); + return NULL; + } + + /* + * The const needs to be cast away, but attached buffers will not be + * modified (in contrary to allocated buffers which are zeroed and + * freed in the end). + */ + pool->buffer = (unsigned char *) buffer; + pool->len = len; + + pool->attached = 1; + + pool->min_len = pool->max_len = pool->len; + pool->entropy = entropy; + + return pool; +} + +/* + * Free |pool|, securely erasing its buffer. + */ +void rand_pool_free(RAND_POOL *pool) +{ + if (pool == NULL) + return; + + /* + * Although it would be advisable from a cryptographical viewpoint, + * we are not allowed to clear attached buffers, since they are passed + * to rand_pool_attach() as `const unsigned char*`. + * (see corresponding comment in rand_pool_attach()). + */ + if (!pool->attached) + OPENSSL_secure_clear_free(pool->buffer, pool->max_len); + OPENSSL_free(pool); +} + +/* + * Return the |pool|'s buffer to the caller (readonly). + */ +const unsigned char *rand_pool_buffer(RAND_POOL *pool) +{ + return pool->buffer; +} + +/* + * Return the |pool|'s entropy to the caller. + */ +size_t rand_pool_entropy(RAND_POOL *pool) +{ + return pool->entropy; +} + +/* + * Return the |pool|'s buffer length to the caller. + */ +size_t rand_pool_length(RAND_POOL *pool) +{ + return pool->len; +} + +/* + * Detach the |pool| buffer and return it to the caller. + * It's the responsibility of the caller to free the buffer + * using OPENSSL_secure_clear_free() or to re-attach it + * again to the pool using rand_pool_reattach(). + */ +unsigned char *rand_pool_detach(RAND_POOL *pool) +{ + unsigned char *ret = pool->buffer; + pool->buffer = NULL; + pool->entropy = 0; + return ret; +} + +/* + * Re-attach the |pool| buffer. It is only allowed to pass + * the |buffer| which was previously detached from the same pool. + */ +void rand_pool_reattach(RAND_POOL *pool, unsigned char *buffer) +{ + pool->buffer = buffer; + OPENSSL_cleanse(pool->buffer, pool->len); + pool->len = 0; +} + +/* + * If |entropy_factor| bits contain 1 bit of entropy, how many bytes does one + * need to obtain at least |bits| bits of entropy? + */ +#define ENTROPY_TO_BYTES(bits, entropy_factor) \ + (((bits) * (entropy_factor) + 7) / 8) + + +/* + * Checks whether the |pool|'s entropy is available to the caller. + * This is the case when entropy count and buffer length are high enough. + * Returns + * + * |entropy| if the entropy count and buffer size is large enough + * 0 otherwise + */ +size_t rand_pool_entropy_available(RAND_POOL *pool) +{ + if (pool->entropy < pool->entropy_requested) + return 0; + + if (pool->len < pool->min_len) + return 0; + + return pool->entropy; +} + +/* + * Returns the (remaining) amount of entropy needed to fill + * the random pool. + */ + +size_t rand_pool_entropy_needed(RAND_POOL *pool) +{ + if (pool->entropy < pool->entropy_requested) + return pool->entropy_requested - pool->entropy; + + return 0; +} + +/* + * Returns the number of bytes needed to fill the pool, assuming + * the input has 1 / |entropy_factor| entropy bits per data bit. + * In case of an error, 0 is returned. + */ + +size_t rand_pool_bytes_needed(RAND_POOL *pool, unsigned int entropy_factor) +{ + size_t bytes_needed; + size_t entropy_needed = rand_pool_entropy_needed(pool); + + if (entropy_factor < 1) { + RANDerr(RAND_F_RAND_POOL_BYTES_NEEDED, RAND_R_ARGUMENT_OUT_OF_RANGE); + return 0; + } + + bytes_needed = ENTROPY_TO_BYTES(entropy_needed, entropy_factor); + + if (bytes_needed > pool->max_len - pool->len) { + /* not enough space left */ + RANDerr(RAND_F_RAND_POOL_BYTES_NEEDED, RAND_R_RANDOM_POOL_OVERFLOW); + return 0; + } + + if (pool->len < pool->min_len && + bytes_needed < pool->min_len - pool->len) + /* to meet the min_len requirement */ + bytes_needed = pool->min_len - pool->len; + + return bytes_needed; +} + +/* Returns the remaining number of bytes available */ +size_t rand_pool_bytes_remaining(RAND_POOL *pool) +{ + return pool->max_len - pool->len; +} + +/* + * Add random bytes to the random pool. + * + * It is expected that the |buffer| contains |len| bytes of + * random input which contains at least |entropy| bits of + * randomness. + * + * Returns 1 if the added amount is adequate, otherwise 0 + */ +int rand_pool_add(RAND_POOL *pool, + const unsigned char *buffer, size_t len, size_t entropy) +{ + if (len > pool->max_len - pool->len) { + RANDerr(RAND_F_RAND_POOL_ADD, RAND_R_ENTROPY_INPUT_TOO_LONG); + return 0; + } + + if (pool->buffer == NULL) { + RANDerr(RAND_F_RAND_POOL_ADD, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (len > 0) { + memcpy(pool->buffer + pool->len, buffer, len); + pool->len += len; + pool->entropy += entropy; + } + + return 1; +} + +/* + * Start to add random bytes to the random pool in-place. + * + * Reserves the next |len| bytes for adding random bytes in-place + * and returns a pointer to the buffer. + * The caller is allowed to copy up to |len| bytes into the buffer. + * If |len| == 0 this is considered a no-op and a NULL pointer + * is returned without producing an error message. + * + * After updating the buffer, rand_pool_add_end() needs to be called + * to finish the udpate operation (see next comment). + */ +unsigned char *rand_pool_add_begin(RAND_POOL *pool, size_t len) +{ + if (len == 0) + return NULL; + + if (len > pool->max_len - pool->len) { + RANDerr(RAND_F_RAND_POOL_ADD_BEGIN, RAND_R_RANDOM_POOL_OVERFLOW); + return NULL; + } + + if (pool->buffer == NULL) { + RANDerr(RAND_F_RAND_POOL_ADD_BEGIN, ERR_R_INTERNAL_ERROR); + return 0; + } + + return pool->buffer + pool->len; +} + +/* + * Finish to add random bytes to the random pool in-place. + * + * Finishes an in-place update of the random pool started by + * rand_pool_add_begin() (see previous comment). + * It is expected that |len| bytes of random input have been added + * to the buffer which contain at least |entropy| bits of randomness. + * It is allowed to add less bytes than originally reserved. + */ +int rand_pool_add_end(RAND_POOL *pool, size_t len, size_t entropy) +{ + if (len > pool->max_len - pool->len) { + RANDerr(RAND_F_RAND_POOL_ADD_END, RAND_R_RANDOM_POOL_OVERFLOW); + return 0; + } + + if (len > 0) { + pool->len += len; + pool->entropy += entropy; + } + + return 1; +} + +int RAND_set_rand_method(const RAND_METHOD *meth) +{ + if (!RUN_ONCE(&rand_init, do_rand_init)) + return 0; + + CRYPTO_THREAD_write_lock(rand_meth_lock); +#ifndef OPENSSL_NO_ENGINE + ENGINE_finish(funct_ref); + funct_ref = NULL; +#endif + default_RAND_meth = meth; + CRYPTO_THREAD_unlock(rand_meth_lock); + return 1; +} + +const RAND_METHOD *RAND_get_rand_method(void) +{ + const RAND_METHOD *tmp_meth = NULL; + + if (!RUN_ONCE(&rand_init, do_rand_init)) + return NULL; + + CRYPTO_THREAD_write_lock(rand_meth_lock); + if (default_RAND_meth == NULL) { +#ifndef OPENSSL_NO_ENGINE + ENGINE *e; + + /* If we have an engine that can do RAND, use it. */ + if ((e = ENGINE_get_default_RAND()) != NULL + && (tmp_meth = ENGINE_get_RAND(e)) != NULL) { + funct_ref = e; + default_RAND_meth = tmp_meth; + } else { + ENGINE_finish(e); + default_RAND_meth = &rand_meth; + } +#else + default_RAND_meth = &rand_meth; +#endif + } + tmp_meth = default_RAND_meth; + CRYPTO_THREAD_unlock(rand_meth_lock); + return tmp_meth; +} + +#ifndef OPENSSL_NO_ENGINE +int RAND_set_rand_engine(ENGINE *engine) +{ + const RAND_METHOD *tmp_meth = NULL; + + if (!RUN_ONCE(&rand_init, do_rand_init)) + return 0; + + if (engine != NULL) { + if (!ENGINE_init(engine)) + return 0; + tmp_meth = ENGINE_get_RAND(engine); + if (tmp_meth == NULL) { + ENGINE_finish(engine); + return 0; + } + } + CRYPTO_THREAD_write_lock(rand_engine_lock); + /* This function releases any prior ENGINE so call it first */ + RAND_set_rand_method(tmp_meth); + funct_ref = engine; + CRYPTO_THREAD_unlock(rand_engine_lock); + return 1; +} +#endif + +void RAND_seed(const void *buf, int num) +{ + const RAND_METHOD *meth = RAND_get_rand_method(); + + if (meth->seed != NULL) + meth->seed(buf, num); +} + +void RAND_add(const void *buf, int num, double randomness) +{ + const RAND_METHOD *meth = RAND_get_rand_method(); + + if (meth->add != NULL) + meth->add(buf, num, randomness); +} + +/* + * This function is not part of RAND_METHOD, so if we're not using + * the default method, then just call RAND_bytes(). Otherwise make + * sure we're instantiated and use the private DRBG. + */ +int RAND_priv_bytes(unsigned char *buf, int num) +{ + const RAND_METHOD *meth = RAND_get_rand_method(); + RAND_DRBG *drbg; + int ret; + + if (meth != RAND_OpenSSL()) + return RAND_bytes(buf, num); + + drbg = RAND_DRBG_get0_private(); + if (drbg == NULL) + return 0; + + ret = RAND_DRBG_bytes(drbg, buf, num); + return ret; +} + +int RAND_bytes(unsigned char *buf, int num) +{ + const RAND_METHOD *meth = RAND_get_rand_method(); + + if (meth->bytes != NULL) + return meth->bytes(buf, num); + RANDerr(RAND_F_RAND_BYTES, RAND_R_FUNC_NOT_IMPLEMENTED); + return -1; +} + +#if OPENSSL_API_COMPAT < 0x10100000L +int RAND_pseudo_bytes(unsigned char *buf, int num) +{ + const RAND_METHOD *meth = RAND_get_rand_method(); + + if (meth->pseudorand != NULL) + return meth->pseudorand(buf, num); + return -1; +} +#endif + +int RAND_status(void) +{ + const RAND_METHOD *meth = RAND_get_rand_method(); + + if (meth->status != NULL) + return meth->status(); + return 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rand/rand_unix.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rand/rand_unix.c new file mode 100644 index 000000000..9cbc9ade7 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rand/rand_unix.c @@ -0,0 +1,707 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif +#include "e_os.h" +#include +#include "internal/cryptlib.h" +#include +#include "rand_lcl.h" +#include "internal/rand_int.h" +#include +#include "internal/dso.h" +#if defined(__linux) +# include +#endif +#if defined(__FreeBSD__) +# include +# include +# include +#endif +#if defined(__OpenBSD__) || defined(__NetBSD__) +# include +#endif + +#if defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__) +# include +# include +# include +# include +# include + +static uint64_t get_time_stamp(void); +static uint64_t get_timer_bits(void); + +/* Macro to convert two thirty two bit values into a sixty four bit one */ +# define TWO32TO64(a, b) ((((uint64_t)(a)) << 32) + (b)) + +/* + * Check for the existence and support of POSIX timers. The standard + * says that the _POSIX_TIMERS macro will have a positive value if they + * are available. + * + * However, we want an additional constraint: that the timer support does + * not require an extra library dependency. Early versions of glibc + * require -lrt to be specified on the link line to access the timers, + * so this needs to be checked for. + * + * It is worse because some libraries define __GLIBC__ but don't + * support the version testing macro (e.g. uClibc). This means + * an extra check is needed. + * + * The final condition is: + * "have posix timers and either not glibc or glibc without -lrt" + * + * The nested #if sequences are required to avoid using a parameterised + * macro that might be undefined. + */ +# undef OSSL_POSIX_TIMER_OKAY +# if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 +# if defined(__GLIBC__) +# if defined(__GLIBC_PREREQ) +# if __GLIBC_PREREQ(2, 17) +# define OSSL_POSIX_TIMER_OKAY +# endif +# endif +# else +# define OSSL_POSIX_TIMER_OKAY +# endif +# endif +#endif /* defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__) */ + +#if defined(OPENSSL_RAND_SEED_NONE) +/* none means none. this simplifies the following logic */ +# undef OPENSSL_RAND_SEED_OS +# undef OPENSSL_RAND_SEED_GETRANDOM +# undef OPENSSL_RAND_SEED_LIBRANDOM +# undef OPENSSL_RAND_SEED_DEVRANDOM +# undef OPENSSL_RAND_SEED_RDTSC +# undef OPENSSL_RAND_SEED_RDCPU +# undef OPENSSL_RAND_SEED_EGD +#endif + +#if (defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI)) && \ + !defined(OPENSSL_RAND_SEED_NONE) +# error "UEFI and VXWorks only support seeding NONE" +#endif + +#if defined(OPENSSL_SYS_VXWORKS) +/* empty implementation */ +int rand_pool_init(void) +{ + return 1; +} + +void rand_pool_cleanup(void) +{ +} + +void rand_pool_keep_random_devices_open(int keep) +{ +} + +size_t rand_pool_acquire_entropy(RAND_POOL *pool) +{ + return rand_pool_entropy_available(pool); +} +#endif + +#if !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) \ + || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_VXWORKS) \ + || defined(OPENSSL_SYS_UEFI)) + +# if defined(OPENSSL_SYS_VOS) + +# ifndef OPENSSL_RAND_SEED_OS +# error "Unsupported seeding method configured; must be os" +# endif + +# if defined(OPENSSL_SYS_VOS_HPPA) && defined(OPENSSL_SYS_VOS_IA32) +# error "Unsupported HP-PA and IA32 at the same time." +# endif +# if !defined(OPENSSL_SYS_VOS_HPPA) && !defined(OPENSSL_SYS_VOS_IA32) +# error "Must have one of HP-PA or IA32" +# endif + +/* + * The following algorithm repeatedly samples the real-time clock (RTC) to + * generate a sequence of unpredictable data. The algorithm relies upon the + * uneven execution speed of the code (due to factors such as cache misses, + * interrupts, bus activity, and scheduling) and upon the rather large + * relative difference between the speed of the clock and the rate at which + * it can be read. If it is ported to an environment where execution speed + * is more constant or where the RTC ticks at a much slower rate, or the + * clock can be read with fewer instructions, it is likely that the results + * would be far more predictable. This should only be used for legacy + * platforms. + * + * As a precaution, we assume only 2 bits of entropy per byte. + */ +size_t rand_pool_acquire_entropy(RAND_POOL *pool) +{ + short int code; + int i, k; + size_t bytes_needed; + struct timespec ts; + unsigned char v; +# ifdef OPENSSL_SYS_VOS_HPPA + long duration; + extern void s$sleep(long *_duration, short int *_code); +# else + long long duration; + extern void s$sleep2(long long *_duration, short int *_code); +# endif + + bytes_needed = rand_pool_bytes_needed(pool, 4 /*entropy_factor*/); + + for (i = 0; i < bytes_needed; i++) { + /* + * burn some cpu; hope for interrupts, cache collisions, bus + * interference, etc. + */ + for (k = 0; k < 99; k++) + ts.tv_nsec = random(); + +# ifdef OPENSSL_SYS_VOS_HPPA + /* sleep for 1/1024 of a second (976 us). */ + duration = 1; + s$sleep(&duration, &code); +# else + /* sleep for 1/65536 of a second (15 us). */ + duration = 1; + s$sleep2(&duration, &code); +# endif + + /* Get wall clock time, take 8 bits. */ + clock_gettime(CLOCK_REALTIME, &ts); + v = (unsigned char)(ts.tv_nsec & 0xFF); + rand_pool_add(pool, arg, &v, sizeof(v) , 2); + } + return rand_pool_entropy_available(pool); +} + +void rand_pool_cleanup(void) +{ +} + +void rand_pool_keep_random_devices_open(int keep) +{ +} + +# else + +# if defined(OPENSSL_RAND_SEED_EGD) && \ + (defined(OPENSSL_NO_EGD) || !defined(DEVRANDOM_EGD)) +# error "Seeding uses EGD but EGD is turned off or no device given" +# endif + +# if defined(OPENSSL_RAND_SEED_DEVRANDOM) && !defined(DEVRANDOM) +# error "Seeding uses urandom but DEVRANDOM is not configured" +# endif + +# if defined(OPENSSL_RAND_SEED_OS) +# if !defined(DEVRANDOM) +# error "OS seeding requires DEVRANDOM to be configured" +# endif +# define OPENSSL_RAND_SEED_GETRANDOM +# define OPENSSL_RAND_SEED_DEVRANDOM +# endif + +# if defined(OPENSSL_RAND_SEED_LIBRANDOM) +# error "librandom not (yet) supported" +# endif + +# if (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND) +/* + * sysctl_random(): Use sysctl() to read a random number from the kernel + * Returns the number of bytes returned in buf on success, -1 on failure. + */ +static ssize_t sysctl_random(char *buf, size_t buflen) +{ + int mib[2]; + size_t done = 0; + size_t len; + + /* + * Note: sign conversion between size_t and ssize_t is safe even + * without a range check, see comment in syscall_random() + */ + + /* + * On FreeBSD old implementations returned longs, newer versions support + * variable sizes up to 256 byte. The code below would not work properly + * when the sysctl returns long and we want to request something not a + * multiple of longs, which should never be the case. + */ + if (!ossl_assert(buflen % sizeof(long) == 0)) { + errno = EINVAL; + return -1; + } + + /* + * On NetBSD before 4.0 KERN_ARND was an alias for KERN_URND, and only + * filled in an int, leaving the rest uninitialized. Since NetBSD 4.0 + * it returns a variable number of bytes with the current version supporting + * up to 256 bytes. + * Just return an error on older NetBSD versions. + */ +#if defined(__NetBSD__) && __NetBSD_Version__ < 400000000 + errno = ENOSYS; + return -1; +#endif + + mib[0] = CTL_KERN; + mib[1] = KERN_ARND; + + do { + len = buflen; + if (sysctl(mib, 2, buf, &len, NULL, 0) == -1) + return done > 0 ? done : -1; + done += len; + buf += len; + buflen -= len; + } while (buflen > 0); + + return done; +} +# endif + +# if defined(OPENSSL_RAND_SEED_GETRANDOM) +/* + * syscall_random(): Try to get random data using a system call + * returns the number of bytes returned in buf, or < 0 on error. + */ +static ssize_t syscall_random(void *buf, size_t buflen) +{ + /* + * Note: 'buflen' equals the size of the buffer which is used by the + * get_entropy() callback of the RAND_DRBG. It is roughly bounded by + * + * 2 * RAND_POOL_FACTOR * (RAND_DRBG_STRENGTH / 8) = 2^14 + * + * which is way below the OSSL_SSIZE_MAX limit. Therefore sign conversion + * between size_t and ssize_t is safe even without a range check. + */ + + /* + * Do runtime detection to find getentropy(). + * + * Known OSs that should support this: + * - Darwin since 16 (OSX 10.12, IOS 10.0). + * - Solaris since 11.3 + * - OpenBSD since 5.6 + * - Linux since 3.17 with glibc 2.25 + * - FreeBSD since 12.0 (1200061) + */ +# if defined(__GNUC__) && __GNUC__>=2 && defined(__ELF__) && !defined(__hpux) + extern int getentropy(void *buffer, size_t length) __attribute__((weak)); + + if (getentropy != NULL) + return getentropy(buf, buflen) == 0 ? (ssize_t)buflen : -1; +# else + union { + void *p; + int (*f)(void *buffer, size_t length); + } p_getentropy; + + /* + * We could cache the result of the lookup, but we normally don't + * call this function often. + */ + ERR_set_mark(); + p_getentropy.p = DSO_global_lookup("getentropy"); + ERR_pop_to_mark(); + if (p_getentropy.p != NULL) + return p_getentropy.f(buf, buflen) == 0 ? (ssize_t)buflen : -1; +# endif + + /* Linux supports this since version 3.17 */ +# if defined(__linux) && defined(SYS_getrandom) + return syscall(SYS_getrandom, buf, buflen, 0); +# elif (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND) + return sysctl_random(buf, buflen); +# else + errno = ENOSYS; + return -1; +# endif +} +# endif /* defined(OPENSSL_RAND_SEED_GETRANDOM) */ + +# if defined(OPENSSL_RAND_SEED_DEVRANDOM) +static const char *random_device_paths[] = { DEVRANDOM }; +static struct random_device { + int fd; + dev_t dev; + ino_t ino; + mode_t mode; + dev_t rdev; +} random_devices[OSSL_NELEM(random_device_paths)]; +static int keep_random_devices_open = 1; + +/* + * Verify that the file descriptor associated with the random source is + * still valid. The rationale for doing this is the fact that it is not + * uncommon for daemons to close all open file handles when daemonizing. + * So the handle might have been closed or even reused for opening + * another file. + */ +static int check_random_device(struct random_device * rd) +{ + struct stat st; + + return rd->fd != -1 + && fstat(rd->fd, &st) != -1 + && rd->dev == st.st_dev + && rd->ino == st.st_ino + && ((rd->mode ^ st.st_mode) & ~(S_IRWXU | S_IRWXG | S_IRWXO)) == 0 + && rd->rdev == st.st_rdev; +} + +/* + * Open a random device if required and return its file descriptor or -1 on error + */ +static int get_random_device(size_t n) +{ + struct stat st; + struct random_device * rd = &random_devices[n]; + + /* reuse existing file descriptor if it is (still) valid */ + if (check_random_device(rd)) + return rd->fd; + + /* open the random device ... */ + if ((rd->fd = open(random_device_paths[n], O_RDONLY)) == -1) + return rd->fd; + + /* ... and cache its relevant stat(2) data */ + if (fstat(rd->fd, &st) != -1) { + rd->dev = st.st_dev; + rd->ino = st.st_ino; + rd->mode = st.st_mode; + rd->rdev = st.st_rdev; + } else { + close(rd->fd); + rd->fd = -1; + } + + return rd->fd; +} + +/* + * Close a random device making sure it is a random device + */ +static void close_random_device(size_t n) +{ + struct random_device * rd = &random_devices[n]; + + if (check_random_device(rd)) + close(rd->fd); + rd->fd = -1; +} + +int rand_pool_init(void) +{ + size_t i; + + for (i = 0; i < OSSL_NELEM(random_devices); i++) + random_devices[i].fd = -1; + + return 1; +} + +void rand_pool_cleanup(void) +{ + size_t i; + + for (i = 0; i < OSSL_NELEM(random_devices); i++) + close_random_device(i); +} + +void rand_pool_keep_random_devices_open(int keep) +{ + if (!keep) + rand_pool_cleanup(); + + keep_random_devices_open = keep; +} + +# else /* !defined(OPENSSL_RAND_SEED_DEVRANDOM) */ + +int rand_pool_init(void) +{ + return 1; +} + +void rand_pool_cleanup(void) +{ +} + +void rand_pool_keep_random_devices_open(int keep) +{ +} + +# endif /* defined(OPENSSL_RAND_SEED_DEVRANDOM) */ + +/* + * Try the various seeding methods in turn, exit when successful. + * + * TODO(DRBG): If more than one entropy source is available, is it + * preferable to stop as soon as enough entropy has been collected + * (as favored by @rsalz) or should one rather be defensive and add + * more entropy than requested and/or from different sources? + * + * Currently, the user can select multiple entropy sources in the + * configure step, yet in practice only the first available source + * will be used. A more flexible solution has been requested, but + * currently it is not clear how this can be achieved without + * overengineering the problem. There are many parameters which + * could be taken into account when selecting the order and amount + * of input from the different entropy sources (trust, quality, + * possibility of blocking). + */ +size_t rand_pool_acquire_entropy(RAND_POOL *pool) +{ +# if defined(OPENSSL_RAND_SEED_NONE) + return rand_pool_entropy_available(pool); +# else + size_t bytes_needed; + size_t entropy_available = 0; + unsigned char *buffer; + +# if defined(OPENSSL_RAND_SEED_GETRANDOM) + { + ssize_t bytes; + /* Maximum allowed number of consecutive unsuccessful attempts */ + int attempts = 3; + + bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); + while (bytes_needed != 0 && attempts-- > 0) { + buffer = rand_pool_add_begin(pool, bytes_needed); + bytes = syscall_random(buffer, bytes_needed); + if (bytes > 0) { + rand_pool_add_end(pool, bytes, 8 * bytes); + bytes_needed -= bytes; + attempts = 3; /* reset counter after successful attempt */ + } else if (bytes < 0 && errno != EINTR) { + break; + } + } + } + entropy_available = rand_pool_entropy_available(pool); + if (entropy_available > 0) + return entropy_available; +# endif + +# if defined(OPENSSL_RAND_SEED_LIBRANDOM) + { + /* Not yet implemented. */ + } +# endif + +# if defined(OPENSSL_RAND_SEED_DEVRANDOM) + bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); + { + size_t i; + + for (i = 0; bytes_needed > 0 && i < OSSL_NELEM(random_device_paths); i++) { + ssize_t bytes = 0; + /* Maximum allowed number of consecutive unsuccessful attempts */ + int attempts = 3; + const int fd = get_random_device(i); + + if (fd == -1) + continue; + + while (bytes_needed != 0 && attempts-- > 0) { + buffer = rand_pool_add_begin(pool, bytes_needed); + bytes = read(fd, buffer, bytes_needed); + + if (bytes > 0) { + rand_pool_add_end(pool, bytes, 8 * bytes); + bytes_needed -= bytes; + attempts = 3; /* reset counter after successful attempt */ + } else if (bytes < 0 && errno != EINTR) { + break; + } + } + if (bytes < 0 || !keep_random_devices_open) + close_random_device(i); + + bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); + } + entropy_available = rand_pool_entropy_available(pool); + if (entropy_available > 0) + return entropy_available; + } +# endif + +# if defined(OPENSSL_RAND_SEED_RDTSC) + entropy_available = rand_acquire_entropy_from_tsc(pool); + if (entropy_available > 0) + return entropy_available; +# endif + +# if defined(OPENSSL_RAND_SEED_RDCPU) + entropy_available = rand_acquire_entropy_from_cpu(pool); + if (entropy_available > 0) + return entropy_available; +# endif + +# if defined(OPENSSL_RAND_SEED_EGD) + bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); + if (bytes_needed > 0) { + static const char *paths[] = { DEVRANDOM_EGD, NULL }; + int i; + + for (i = 0; paths[i] != NULL; i++) { + buffer = rand_pool_add_begin(pool, bytes_needed); + if (buffer != NULL) { + size_t bytes = 0; + int num = RAND_query_egd_bytes(paths[i], + buffer, (int)bytes_needed); + if (num == (int)bytes_needed) + bytes = bytes_needed; + + rand_pool_add_end(pool, bytes, 8 * bytes); + entropy_available = rand_pool_entropy_available(pool); + } + if (entropy_available > 0) + return entropy_available; + } + } +# endif + + return rand_pool_entropy_available(pool); +# endif +} +# endif +#endif + +#if defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__) +int rand_pool_add_nonce_data(RAND_POOL *pool) +{ + struct { + pid_t pid; + CRYPTO_THREAD_ID tid; + uint64_t time; + } data = { 0 }; + + /* + * Add process id, thread id, and a high resolution timestamp to + * ensure that the nonce is unique with high probability for + * different process instances. + */ + data.pid = getpid(); + data.tid = CRYPTO_THREAD_get_current_id(); + data.time = get_time_stamp(); + + return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0); +} + +int rand_pool_add_additional_data(RAND_POOL *pool) +{ + struct { + CRYPTO_THREAD_ID tid; + uint64_t time; + } data = { 0 }; + + /* + * Add some noise from the thread id and a high resolution timer. + * The thread id adds a little randomness if the drbg is accessed + * concurrently (which is the case for the drbg). + */ + data.tid = CRYPTO_THREAD_get_current_id(); + data.time = get_timer_bits(); + + return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0); +} + + +/* + * Get the current time with the highest possible resolution + * + * The time stamp is added to the nonce, so it is optimized for not repeating. + * The current time is ideal for this purpose, provided the computer's clock + * is synchronized. + */ +static uint64_t get_time_stamp(void) +{ +# if defined(OSSL_POSIX_TIMER_OKAY) + { + struct timespec ts; + + if (clock_gettime(CLOCK_REALTIME, &ts) == 0) + return TWO32TO64(ts.tv_sec, ts.tv_nsec); + } +# endif +# if defined(__unix__) \ + || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) + { + struct timeval tv; + + if (gettimeofday(&tv, NULL) == 0) + return TWO32TO64(tv.tv_sec, tv.tv_usec); + } +# endif + return time(NULL); +} + +/* + * Get an arbitrary timer value of the highest possible resolution + * + * The timer value is added as random noise to the additional data, + * which is not considered a trusted entropy sourec, so any result + * is acceptable. + */ +static uint64_t get_timer_bits(void) +{ + uint64_t res = OPENSSL_rdtsc(); + + if (res != 0) + return res; + +# if defined(__sun) || defined(__hpux) + return gethrtime(); +# elif defined(_AIX) + { + timebasestruct_t t; + + read_wall_time(&t, TIMEBASE_SZ); + return TWO32TO64(t.tb_high, t.tb_low); + } +# elif defined(OSSL_POSIX_TIMER_OKAY) + { + struct timespec ts; + +# ifdef CLOCK_BOOTTIME +# define CLOCK_TYPE CLOCK_BOOTTIME +# elif defined(_POSIX_MONOTONIC_CLOCK) +# define CLOCK_TYPE CLOCK_MONOTONIC +# else +# define CLOCK_TYPE CLOCK_REALTIME +# endif + + if (clock_gettime(CLOCK_TYPE, &ts) == 0) + return TWO32TO64(ts.tv_sec, ts.tv_nsec); + } +# endif +# if defined(__unix__) \ + || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) + { + struct timeval tv; + + if (gettimeofday(&tv, NULL) == 0) + return TWO32TO64(tv.tv_sec, tv.tv_usec); + } +# endif + return time(NULL); +} +#endif /* defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__) */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rand/rand_vms.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rand/rand_vms.c new file mode 100644 index 000000000..bfcf6f0a8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rand/rand_vms.c @@ -0,0 +1,528 @@ +/* + * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "e_os.h" + +#if defined(OPENSSL_SYS_VMS) +# define __NEW_STARLET 1 /* New starlet definitions since VMS 7.0 */ +# include +# include "internal/cryptlib.h" +# include +# include "internal/rand_int.h" +# include "rand_lcl.h" +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# ifdef __DECC +# pragma message disable DOLLARID +# endif + +# ifndef OPENSSL_RAND_SEED_OS +# error "Unsupported seeding method configured; must be os" +# endif + +/* We need to make sure we have the right size pointer in some cases */ +# if __INITIAL_POINTER_SIZE == 64 +# pragma pointer_size save +# pragma pointer_size 32 +# endif +typedef uint32_t *uint32_t__ptr32; +# if __INITIAL_POINTER_SIZE == 64 +# pragma pointer_size restore +# endif + +struct item_st { + short length, code; /* length is number of bytes */ +}; + +static const struct item_st DVI_item_data[] = { + {4, DVI$_ERRCNT}, + {4, DVI$_REFCNT}, +}; + +static const struct item_st JPI_item_data[] = { + {4, JPI$_BUFIO}, + {4, JPI$_CPUTIM}, + {4, JPI$_DIRIO}, + {4, JPI$_IMAGECOUNT}, + {4, JPI$_PAGEFLTS}, + {4, JPI$_PID}, + {4, JPI$_PPGCNT}, + {4, JPI$_WSPEAK}, + /* + * Note: the direct result is just a 32-bit address. However, it points + * to a list of 4 32-bit words, so we make extra space for them so we can + * do in-place replacement of values + */ + {16, JPI$_FINALEXC}, +}; + +static const struct item_st JPI_item_data_64bit[] = { + {8, JPI$_LAST_LOGIN_I}, + {8, JPI$_LOGINTIM}, +}; + +static const struct item_st RMI_item_data[] = { + {4, RMI$_COLPG}, + {4, RMI$_MWAIT}, + {4, RMI$_CEF}, + {4, RMI$_PFW}, + {4, RMI$_LEF}, + {4, RMI$_LEFO}, + {4, RMI$_HIB}, + {4, RMI$_HIBO}, + {4, RMI$_SUSP}, + {4, RMI$_SUSPO}, + {4, RMI$_FPG}, + {4, RMI$_COM}, + {4, RMI$_COMO}, + {4, RMI$_CUR}, +#if defined __alpha + {4, RMI$_FRLIST}, + {4, RMI$_MODLIST}, +#endif + {4, RMI$_FAULTS}, + {4, RMI$_PREADS}, + {4, RMI$_PWRITES}, + {4, RMI$_PWRITIO}, + {4, RMI$_PREADIO}, + {4, RMI$_GVALFLTS}, + {4, RMI$_WRTINPROG}, + {4, RMI$_FREFLTS}, + {4, RMI$_DZROFLTS}, + {4, RMI$_SYSFAULTS}, + {4, RMI$_ISWPCNT}, + {4, RMI$_DIRIO}, + {4, RMI$_BUFIO}, + {4, RMI$_MBREADS}, + {4, RMI$_MBWRITES}, + {4, RMI$_LOGNAM}, + {4, RMI$_FCPCALLS}, + {4, RMI$_FCPREAD}, + {4, RMI$_FCPWRITE}, + {4, RMI$_FCPCACHE}, + {4, RMI$_FCPCPU}, + {4, RMI$_FCPHIT}, + {4, RMI$_FCPSPLIT}, + {4, RMI$_FCPFAULT}, + {4, RMI$_ENQNEW}, + {4, RMI$_ENQCVT}, + {4, RMI$_DEQ}, + {4, RMI$_BLKAST}, + {4, RMI$_ENQWAIT}, + {4, RMI$_ENQNOTQD}, + {4, RMI$_DLCKSRCH}, + {4, RMI$_DLCKFND}, + {4, RMI$_NUMLOCKS}, + {4, RMI$_NUMRES}, + {4, RMI$_ARRLOCPK}, + {4, RMI$_DEPLOCPK}, + {4, RMI$_ARRTRAPK}, + {4, RMI$_TRCNGLOS}, + {4, RMI$_RCVBUFFL}, + {4, RMI$_ENQNEWLOC}, + {4, RMI$_ENQNEWIN}, + {4, RMI$_ENQNEWOUT}, + {4, RMI$_ENQCVTLOC}, + {4, RMI$_ENQCVTIN}, + {4, RMI$_ENQCVTOUT}, + {4, RMI$_DEQLOC}, + {4, RMI$_DEQIN}, + {4, RMI$_DEQOUT}, + {4, RMI$_BLKLOC}, + {4, RMI$_BLKIN}, + {4, RMI$_BLKOUT}, + {4, RMI$_DIRIN}, + {4, RMI$_DIROUT}, + /* We currently get a fault when trying these. TODO: To be figured out. */ +#if 0 + {140, RMI$_MSCP_EVERYTHING}, /* 35 32-bit words */ + {152, RMI$_DDTM_ALL}, /* 38 32-bit words */ + {80, RMI$_TMSCP_EVERYTHING} /* 20 32-bit words */ +#endif + {4, RMI$_LPZ_PAGCNT}, + {4, RMI$_LPZ_HITS}, + {4, RMI$_LPZ_MISSES}, + {4, RMI$_LPZ_EXPCNT}, + {4, RMI$_LPZ_ALLOCF}, + {4, RMI$_LPZ_ALLOC2}, + {4, RMI$_ACCESS}, + {4, RMI$_ALLOC}, + {4, RMI$_FCPCREATE}, + {4, RMI$_VOLWAIT}, + {4, RMI$_FCPTURN}, + {4, RMI$_FCPERASE}, + {4, RMI$_OPENS}, + {4, RMI$_FIDHIT}, + {4, RMI$_FIDMISS}, + {4, RMI$_FILHDR_HIT}, + {4, RMI$_DIRFCB_HIT}, + {4, RMI$_DIRFCB_MISS}, + {4, RMI$_DIRDATA_HIT}, + {4, RMI$_EXTHIT}, + {4, RMI$_EXTMISS}, + {4, RMI$_QUOHIT}, + {4, RMI$_QUOMISS}, + {4, RMI$_STORAGMAP_HIT}, + {4, RMI$_VOLLCK}, + {4, RMI$_SYNCHLCK}, + {4, RMI$_SYNCHWAIT}, + {4, RMI$_ACCLCK}, + {4, RMI$_XQPCACHEWAIT}, + {4, RMI$_DIRDATA_MISS}, + {4, RMI$_FILHDR_MISS}, + {4, RMI$_STORAGMAP_MISS}, + {4, RMI$_PROCCNTMAX}, + {4, RMI$_PROCBATCNT}, + {4, RMI$_PROCINTCNT}, + {4, RMI$_PROCNETCNT}, + {4, RMI$_PROCSWITCHCNT}, + {4, RMI$_PROCBALSETCNT}, + {4, RMI$_PROCLOADCNT}, + {4, RMI$_BADFLTS}, + {4, RMI$_EXEFAULTS}, + {4, RMI$_HDRINSWAPS}, + {4, RMI$_HDROUTSWAPS}, + {4, RMI$_IOPAGCNT}, + {4, RMI$_ISWPCNTPG}, + {4, RMI$_OSWPCNT}, + {4, RMI$_OSWPCNTPG}, + {4, RMI$_RDFAULTS}, + {4, RMI$_TRANSFLTS}, + {4, RMI$_WRTFAULTS}, +#if defined __alpha + {4, RMI$_USERPAGES}, +#endif + {4, RMI$_VMSPAGES}, + {4, RMI$_TTWRITES}, + {4, RMI$_BUFOBJPAG}, + {4, RMI$_BUFOBJPAGPEAK}, + {4, RMI$_BUFOBJPAGS01}, + {4, RMI$_BUFOBJPAGS2}, + {4, RMI$_BUFOBJPAGMAXS01}, + {4, RMI$_BUFOBJPAGMAXS2}, + {4, RMI$_BUFOBJPAGPEAKS01}, + {4, RMI$_BUFOBJPAGPEAKS2}, + {4, RMI$_BUFOBJPGLTMAXS01}, + {4, RMI$_BUFOBJPGLTMAXS2}, + {4, RMI$_DLCK_INCMPLT}, + {4, RMI$_DLCKMSGS_IN}, + {4, RMI$_DLCKMSGS_OUT}, + {4, RMI$_MCHKERRS}, + {4, RMI$_MEMERRS}, +}; + +static const struct item_st RMI_item_data_64bit[] = { +#if defined __ia64 + {8, RMI$_FRLIST}, + {8, RMI$_MODLIST}, +#endif + {8, RMI$_LCKMGR_REQCNT}, + {8, RMI$_LCKMGR_REQTIME}, + {8, RMI$_LCKMGR_SPINCNT}, + {8, RMI$_LCKMGR_SPINTIME}, + {8, RMI$_CPUINTSTK}, + {8, RMI$_CPUMPSYNCH}, + {8, RMI$_CPUKERNEL}, + {8, RMI$_CPUEXEC}, + {8, RMI$_CPUSUPER}, + {8, RMI$_CPUUSER}, +#if defined __ia64 + {8, RMI$_USERPAGES}, +#endif + {8, RMI$_TQETOTAL}, + {8, RMI$_TQESYSUB}, + {8, RMI$_TQEUSRTIMR}, + {8, RMI$_TQEUSRWAKE}, +}; + +static const struct item_st SYI_item_data[] = { + {4, SYI$_PAGEFILE_FREE}, +}; + +/* + * Input: + * items_data - an array of lengths and codes + * items_data_num - number of elements in that array + * + * Output: + * items - pre-allocated ILE3 array to be filled. + * It's assumed to have items_data_num elements plus + * one extra for the terminating NULL element + * databuffer - pre-allocated 32-bit word array. + * + * Returns the number of elements used in databuffer + */ +static size_t prepare_item_list(const struct item_st *items_input, + size_t items_input_num, + ILE3 *items, + uint32_t__ptr32 databuffer) +{ + size_t data_sz = 0; + + for (; items_input_num-- > 0; items_input++, items++) { + + items->ile3$w_code = items_input->code; + /* Special treatment of JPI$_FINALEXC */ + if (items->ile3$w_code == JPI$_FINALEXC) + items->ile3$w_length = 4; + else + items->ile3$w_length = items_input->length; + + items->ile3$ps_bufaddr = databuffer; + items->ile3$ps_retlen_addr = 0; + + databuffer += items_input->length / sizeof(databuffer[0]); + data_sz += items_input->length; + } + /* Terminating NULL entry */ + items->ile3$w_length = items->ile3$w_code = 0; + items->ile3$ps_bufaddr = items->ile3$ps_retlen_addr = NULL; + + return data_sz / sizeof(databuffer[0]); +} + +static void massage_JPI(ILE3 *items) +{ + /* + * Special treatment of JPI$_FINALEXC + * The result of that item's data buffer is a 32-bit address to a list of + * 4 32-bit words. + */ + for (; items->ile3$w_length != 0; items++) { + if (items->ile3$w_code == JPI$_FINALEXC) { + uint32_t *data = items->ile3$ps_bufaddr; + uint32_t *ptr = (uint32_t *)*data; + size_t j; + + /* + * We know we made space for 4 32-bit words, so we can do in-place + * replacement. + */ + for (j = 0; j < 4; j++) + data[j] = ptr[j]; + + break; + } + } +} + +/* + * This number expresses how many bits of data contain 1 bit of entropy. + * + * For the moment, we assume about 0.05 entropy bits per data bit, or 1 + * bit of entropy per 20 data bits. + */ +#define ENTROPY_FACTOR 20 + +size_t rand_pool_acquire_entropy(RAND_POOL *pool) +{ + ILE3 JPI_items_64bit[OSSL_NELEM(JPI_item_data_64bit) + 1]; + ILE3 RMI_items_64bit[OSSL_NELEM(RMI_item_data_64bit) + 1]; + ILE3 DVI_items[OSSL_NELEM(DVI_item_data) + 1]; + ILE3 JPI_items[OSSL_NELEM(JPI_item_data) + 1]; + ILE3 RMI_items[OSSL_NELEM(RMI_item_data) + 1]; + ILE3 SYI_items[OSSL_NELEM(SYI_item_data) + 1]; + union { + /* This ensures buffer starts at 64 bit boundary */ + uint64_t dummy; + uint32_t buffer[OSSL_NELEM(JPI_item_data_64bit) * 2 + + OSSL_NELEM(RMI_item_data_64bit) * 2 + + OSSL_NELEM(DVI_item_data) + + OSSL_NELEM(JPI_item_data) + + OSSL_NELEM(RMI_item_data) + + OSSL_NELEM(SYI_item_data) + + 4 /* For JPI$_FINALEXC */]; + } data; + size_t total_elems = 0; + size_t total_length = 0; + size_t bytes_needed = rand_pool_bytes_needed(pool, ENTROPY_FACTOR); + size_t bytes_remaining = rand_pool_bytes_remaining(pool); + + /* Take all the 64-bit items first, to ensure proper alignment of data */ + total_elems += + prepare_item_list(JPI_item_data_64bit, OSSL_NELEM(JPI_item_data_64bit), + JPI_items_64bit, &data.buffer[total_elems]); + total_elems += + prepare_item_list(RMI_item_data_64bit, OSSL_NELEM(RMI_item_data_64bit), + RMI_items_64bit, &data.buffer[total_elems]); + /* Now the 32-bit items */ + total_elems += prepare_item_list(DVI_item_data, OSSL_NELEM(DVI_item_data), + DVI_items, &data.buffer[total_elems]); + total_elems += prepare_item_list(JPI_item_data, OSSL_NELEM(JPI_item_data), + JPI_items, &data.buffer[total_elems]); + total_elems += prepare_item_list(RMI_item_data, OSSL_NELEM(RMI_item_data), + RMI_items, &data.buffer[total_elems]); + total_elems += prepare_item_list(SYI_item_data, OSSL_NELEM(SYI_item_data), + SYI_items, &data.buffer[total_elems]); + total_length = total_elems * sizeof(data.buffer[0]); + + /* Fill data.buffer with various info bits from this process */ + { + uint32_t status; + uint32_t efn; + IOSB iosb; + $DESCRIPTOR(SYSDEVICE,"SYS$SYSDEVICE:"); + + if ((status = sys$getdviw(EFN$C_ENF, 0, &SYSDEVICE, DVI_items, + 0, 0, 0, 0, 0)) != SS$_NORMAL) { + lib$signal(status); + return 0; + } + if ((status = sys$getjpiw(EFN$C_ENF, 0, 0, JPI_items_64bit, 0, 0, 0)) + != SS$_NORMAL) { + lib$signal(status); + return 0; + } + if ((status = sys$getjpiw(EFN$C_ENF, 0, 0, JPI_items, 0, 0, 0)) + != SS$_NORMAL) { + lib$signal(status); + return 0; + } + if ((status = sys$getsyiw(EFN$C_ENF, 0, 0, SYI_items, 0, 0, 0)) + != SS$_NORMAL) { + lib$signal(status); + return 0; + } + /* + * The RMI service is a bit special, as there is no synchronous + * variant, so we MUST create an event flag to synchronise on. + */ + if ((status = lib$get_ef(&efn)) != SS$_NORMAL) { + lib$signal(status); + return 0; + } + if ((status = sys$getrmi(efn, 0, 0, RMI_items_64bit, &iosb, 0, 0)) + != SS$_NORMAL) { + lib$signal(status); + return 0; + } + if ((status = sys$synch(efn, &iosb)) != SS$_NORMAL) { + lib$signal(status); + return 0; + } + if (iosb.iosb$l_getxxi_status != SS$_NORMAL) { + lib$signal(iosb.iosb$l_getxxi_status); + return 0; + } + if ((status = sys$getrmi(efn, 0, 0, RMI_items, &iosb, 0, 0)) + != SS$_NORMAL) { + lib$signal(status); + return 0; + } + if ((status = sys$synch(efn, &iosb)) != SS$_NORMAL) { + lib$signal(status); + return 0; + } + if (iosb.iosb$l_getxxi_status != SS$_NORMAL) { + lib$signal(iosb.iosb$l_getxxi_status); + return 0; + } + if ((status = lib$free_ef(&efn)) != SS$_NORMAL) { + lib$signal(status); + return 0; + } + } + + massage_JPI(JPI_items); + + /* + * If we can't feed the requirements from the caller, we're in deep trouble. + */ + if (!ossl_assert(total_length >= bytes_needed)) { + char neededstr[20]; + char availablestr[20]; + + BIO_snprintf(neededstr, sizeof(neededstr), "%zu", bytes_needed); + BIO_snprintf(availablestr, sizeof(availablestr), "%zu", total_length); + RANDerr(RAND_F_RAND_POOL_ACQUIRE_ENTROPY, + RAND_R_RANDOM_POOL_UNDERFLOW); + ERR_add_error_data(4, "Needed: ", neededstr, ", Available: ", + availablestr); + return 0; + } + + /* + * Try not to overfeed the pool + */ + if (total_length > bytes_remaining) + total_length = bytes_remaining; + + /* We give the pessimistic value for the amount of entropy */ + rand_pool_add(pool, (unsigned char *)data.buffer, total_length, + 8 * total_length / ENTROPY_FACTOR); + return rand_pool_entropy_available(pool); +} + +int rand_pool_add_nonce_data(RAND_POOL *pool) +{ + struct { + pid_t pid; + CRYPTO_THREAD_ID tid; + uint64_t time; + } data = { 0 }; + + /* + * Add process id, thread id, and a high resolution timestamp + * (where available, which is OpenVMS v8.4 and up) to ensure that + * the nonce is unique whith high probability for different process + * instances. + */ + data.pid = getpid(); + data.tid = CRYPTO_THREAD_get_current_id(); +#if __CRTL_VER >= 80400000 + sys$gettim_prec(&data.time); +#else + sys$gettim((void*)&data.time); +#endif + + return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0); +} + +int rand_pool_add_additional_data(RAND_POOL *pool) +{ + struct { + CRYPTO_THREAD_ID tid; + uint64_t time; + } data = { 0 }; + + /* + * Add some noise from the thread id and a high resolution timer. + * The thread id adds a little randomness if the drbg is accessed + * concurrently (which is the case for the drbg). + */ + data.tid = CRYPTO_THREAD_get_current_id(); + sys$gettim_prec(&data.time); + + return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0); +} + +int rand_pool_init(void) +{ + return 1; +} + +void rand_pool_cleanup(void) +{ +} + +void rand_pool_keep_random_devices_open(int keep) +{ +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rand/rand_win.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rand/rand_win.c new file mode 100644 index 000000000..d2039eb22 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rand/rand_win.c @@ -0,0 +1,185 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include +#include "rand_lcl.h" +#include "internal/rand_int.h" +#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) + +# ifndef OPENSSL_RAND_SEED_OS +# error "Unsupported seeding method configured; must be os" +# endif + +# include +/* On Windows 7 or higher use BCrypt instead of the legacy CryptoAPI */ +# if defined(_MSC_VER) && defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0601 +# define USE_BCRYPTGENRANDOM +# endif + +# ifdef USE_BCRYPTGENRANDOM +# include +# pragma comment(lib, "bcrypt.lib") +# ifndef STATUS_SUCCESS +# define STATUS_SUCCESS ((NTSTATUS)0x00000000L) +# endif +# else +# include +/* + * Intel hardware RNG CSP -- available from + * http://developer.intel.com/design/security/rng/redist_license.htm + */ +# define PROV_INTEL_SEC 22 +# define INTEL_DEF_PROV L"Intel Hardware Cryptographic Service Provider" +# endif + +size_t rand_pool_acquire_entropy(RAND_POOL *pool) +{ +# ifndef USE_BCRYPTGENRANDOM + HCRYPTPROV hProvider; +# endif + unsigned char *buffer; + size_t bytes_needed; + size_t entropy_available = 0; + + +# ifdef OPENSSL_RAND_SEED_RDTSC + entropy_available = rand_acquire_entropy_from_tsc(pool); + if (entropy_available > 0) + return entropy_available; +# endif + +# ifdef OPENSSL_RAND_SEED_RDCPU + entropy_available = rand_acquire_entropy_from_cpu(pool); + if (entropy_available > 0) + return entropy_available; +# endif + +# ifdef USE_BCRYPTGENRANDOM + bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); + buffer = rand_pool_add_begin(pool, bytes_needed); + if (buffer != NULL) { + size_t bytes = 0; + if (BCryptGenRandom(NULL, buffer, bytes_needed, + BCRYPT_USE_SYSTEM_PREFERRED_RNG) == STATUS_SUCCESS) + bytes = bytes_needed; + + rand_pool_add_end(pool, bytes, 8 * bytes); + entropy_available = rand_pool_entropy_available(pool); + } + if (entropy_available > 0) + return entropy_available; +# else + bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); + buffer = rand_pool_add_begin(pool, bytes_needed); + if (buffer != NULL) { + size_t bytes = 0; + /* poll the CryptoAPI PRNG */ + if (CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT | CRYPT_SILENT) != 0) { + if (CryptGenRandom(hProvider, bytes_needed, buffer) != 0) + bytes = bytes_needed; + + CryptReleaseContext(hProvider, 0); + } + + rand_pool_add_end(pool, bytes, 8 * bytes); + entropy_available = rand_pool_entropy_available(pool); + } + if (entropy_available > 0) + return entropy_available; + + bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); + buffer = rand_pool_add_begin(pool, bytes_needed); + if (buffer != NULL) { + size_t bytes = 0; + /* poll the Pentium PRG with CryptoAPI */ + if (CryptAcquireContextW(&hProvider, NULL, + INTEL_DEF_PROV, PROV_INTEL_SEC, + CRYPT_VERIFYCONTEXT | CRYPT_SILENT) != 0) { + if (CryptGenRandom(hProvider, bytes_needed, buffer) != 0) + bytes = bytes_needed; + + CryptReleaseContext(hProvider, 0); + } + rand_pool_add_end(pool, bytes, 8 * bytes); + entropy_available = rand_pool_entropy_available(pool); + } + if (entropy_available > 0) + return entropy_available; +# endif + + return rand_pool_entropy_available(pool); +} + + +int rand_pool_add_nonce_data(RAND_POOL *pool) +{ + struct { + DWORD pid; + DWORD tid; + FILETIME time; + } data = { 0 }; + + /* + * Add process id, thread id, and a high resolution timestamp to + * ensure that the nonce is unique whith high probability for + * different process instances. + */ + data.pid = GetCurrentProcessId(); + data.tid = GetCurrentThreadId(); + GetSystemTimeAsFileTime(&data.time); + + return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0); +} + +int rand_pool_add_additional_data(RAND_POOL *pool) +{ + struct { + DWORD tid; + LARGE_INTEGER time; + } data = { 0 }; + + /* + * Add some noise from the thread id and a high resolution timer. + * The thread id adds a little randomness if the drbg is accessed + * concurrently (which is the case for the drbg). + */ + data.tid = GetCurrentThreadId(); + QueryPerformanceCounter(&data.time); + return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0); +} + +# if OPENSSL_API_COMPAT < 0x10100000L +int RAND_event(UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + RAND_poll(); + return RAND_status(); +} + +void RAND_screen(void) +{ + RAND_poll(); +} +# endif + +int rand_pool_init(void) +{ + return 1; +} + +void rand_pool_cleanup(void) +{ +} + +void rand_pool_keep_random_devices_open(int keep) +{ +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rand/randfile.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rand/randfile.c new file mode 100644 index 000000000..1b737d1ba --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rand/randfile.c @@ -0,0 +1,314 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef OPENSSL_SYS_VMS +# include +#endif +#include +#ifndef OPENSSL_NO_POSIX_IO +# include +# include +# ifdef _WIN32 +# include +# include +# define stat _stat +# define chmod _chmod +# define open _open +# define fdopen _fdopen +# define fstat _fstat +# define fileno _fileno +# endif +#endif + +/* + * Following should not be needed, and we could have been stricter + * and demand S_IS*. But some systems just don't comply... Formally + * below macros are "anatomically incorrect", because normally they + * would look like ((m) & MASK == TYPE), but since MASK availability + * is as questionable, we settle for this poor-man fallback... + */ +# if !defined(S_ISREG) +# define S_ISREG(m) ((m) & S_IFREG) +# endif + +#define RAND_BUF_SIZE 1024 +#define RFILE ".rnd" + +#ifdef OPENSSL_SYS_VMS +/* + * __FILE_ptr32 is a type provided by DEC C headers (types.h specifically) + * to make sure the FILE* is a 32-bit pointer no matter what. We know that + * stdio functions return this type (a study of stdio.h proves it). + * + * This declaration is a nasty hack to get around vms' extension to fopen for + * passing in sharing options being disabled by /STANDARD=ANSI89 + */ +static __FILE_ptr32 (*const vms_fopen)(const char *, const char *, ...) = + (__FILE_ptr32 (*)(const char *, const char *, ...))fopen; +# define VMS_OPEN_ATTRS \ + "shr=get,put,upd,del","ctx=bin,stm","rfm=stm","rat=none","mrs=0" +# define openssl_fopen(fname, mode) vms_fopen((fname), (mode), VMS_OPEN_ATTRS) +#endif + +/* + * Note that these functions are intended for seed files only. Entropy + * devices and EGD sockets are handled in rand_unix.c If |bytes| is + * -1 read the complete file; otherwise read the specified amount. + */ +int RAND_load_file(const char *file, long bytes) +{ + /* + * The load buffer size exceeds the chunk size by the comfortable amount + * of 'RAND_DRBG_STRENGTH' bytes (not bits!). This is done on purpose + * to avoid calling RAND_add() with a small final chunk. Instead, such + * a small final chunk will be added together with the previous chunk + * (unless it's the only one). + */ +#define RAND_LOAD_BUF_SIZE (RAND_BUF_SIZE + RAND_DRBG_STRENGTH) + unsigned char buf[RAND_LOAD_BUF_SIZE]; + +#ifndef OPENSSL_NO_POSIX_IO + struct stat sb; +#endif + int i, n, ret = 0; + FILE *in; + + if (bytes == 0) + return 0; + + if ((in = openssl_fopen(file, "rb")) == NULL) { + RANDerr(RAND_F_RAND_LOAD_FILE, RAND_R_CANNOT_OPEN_FILE); + ERR_add_error_data(2, "Filename=", file); + return -1; + } + +#ifndef OPENSSL_NO_POSIX_IO + if (fstat(fileno(in), &sb) < 0) { + RANDerr(RAND_F_RAND_LOAD_FILE, RAND_R_INTERNAL_ERROR); + ERR_add_error_data(2, "Filename=", file); + fclose(in); + return -1; + } + + if (bytes < 0) { + if (S_ISREG(sb.st_mode)) + bytes = sb.st_size; + else + bytes = RAND_DRBG_STRENGTH; + } +#endif + /* + * On VMS, setbuf() will only take 32-bit pointers, and a compilation + * with /POINTER_SIZE=64 will give off a MAYLOSEDATA2 warning here. + * However, we trust that the C RTL will never give us a FILE pointer + * above the first 4 GB of memory, so we simply turn off the warning + * temporarily. + */ +#if defined(OPENSSL_SYS_VMS) && defined(__DECC) +# pragma environment save +# pragma message disable maylosedata2 +#endif + /* + * Don't buffer, because even if |file| is regular file, we have + * no control over the buffer, so why would we want a copy of its + * contents lying around? + */ + setbuf(in, NULL); +#if defined(OPENSSL_SYS_VMS) && defined(__DECC) +# pragma environment restore +#endif + + for ( ; ; ) { + if (bytes > 0) + n = (bytes <= RAND_LOAD_BUF_SIZE) ? (int)bytes : RAND_BUF_SIZE; + else + n = RAND_LOAD_BUF_SIZE; + i = fread(buf, 1, n, in); +#ifdef EINTR + if (ferror(in) && errno == EINTR){ + clearerr(in); + if (i == 0) + continue; + } +#endif + if (i == 0) + break; + + RAND_add(buf, i, (double)i); + ret += i; + + /* If given a bytecount, and we did it, break. */ + if (bytes > 0 && (bytes -= i) <= 0) + break; + } + + OPENSSL_cleanse(buf, sizeof(buf)); + fclose(in); + if (!RAND_status()) { + RANDerr(RAND_F_RAND_LOAD_FILE, RAND_R_RESEED_ERROR); + ERR_add_error_data(2, "Filename=", file); + return -1; + } + + return ret; +} + +int RAND_write_file(const char *file) +{ + unsigned char buf[RAND_BUF_SIZE]; + int ret = -1; + FILE *out = NULL; +#ifndef OPENSSL_NO_POSIX_IO + struct stat sb; + + if (stat(file, &sb) >= 0 && !S_ISREG(sb.st_mode)) { + RANDerr(RAND_F_RAND_WRITE_FILE, RAND_R_NOT_A_REGULAR_FILE); + ERR_add_error_data(2, "Filename=", file); + return -1; + } +#endif + + /* Collect enough random data. */ + if (RAND_priv_bytes(buf, (int)sizeof(buf)) != 1) + return -1; + +#if defined(O_CREAT) && !defined(OPENSSL_NO_POSIX_IO) && \ + !defined(OPENSSL_SYS_VMS) && !defined(OPENSSL_SYS_WINDOWS) + { +# ifndef O_BINARY +# define O_BINARY 0 +# endif + /* + * chmod(..., 0600) is too late to protect the file, permissions + * should be restrictive from the start + */ + int fd = open(file, O_WRONLY | O_CREAT | O_BINARY, 0600); + if (fd != -1) + out = fdopen(fd, "wb"); + } +#endif + +#ifdef OPENSSL_SYS_VMS + /* + * VMS NOTE: Prior versions of this routine created a _new_ version of + * the rand file for each call into this routine, then deleted all + * existing versions named ;-1, and finally renamed the current version + * as ';1'. Under concurrent usage, this resulted in an RMS race + * condition in rename() which could orphan files (see vms message help + * for RMS$_REENT). With the fopen() calls below, openssl/VMS now shares + * the top-level version of the rand file. Note that there may still be + * conditions where the top-level rand file is locked. If so, this code + * will then create a new version of the rand file. Without the delete + * and rename code, this can result in ascending file versions that stop + * at version 32767, and this routine will then return an error. The + * remedy for this is to recode the calling application to avoid + * concurrent use of the rand file, or synchronize usage at the + * application level. Also consider whether or not you NEED a persistent + * rand file in a concurrent use situation. + */ + out = openssl_fopen(file, "rb+"); +#endif + + if (out == NULL) + out = openssl_fopen(file, "wb"); + if (out == NULL) { + RANDerr(RAND_F_RAND_WRITE_FILE, RAND_R_CANNOT_OPEN_FILE); + ERR_add_error_data(2, "Filename=", file); + return -1; + } + +#if !defined(NO_CHMOD) && !defined(OPENSSL_NO_POSIX_IO) + /* + * Yes it's late to do this (see above comment), but better than nothing. + */ + chmod(file, 0600); +#endif + + ret = fwrite(buf, 1, RAND_BUF_SIZE, out); + fclose(out); + OPENSSL_cleanse(buf, RAND_BUF_SIZE); + return ret; +} + +const char *RAND_file_name(char *buf, size_t size) +{ + char *s = NULL; + size_t len; + int use_randfile = 1; + +#if defined(_WIN32) && defined(CP_UTF8) + DWORD envlen; + WCHAR *var; + + /* Look up various environment variables. */ + if ((envlen = GetEnvironmentVariableW(var = L"RANDFILE", NULL, 0)) == 0) { + use_randfile = 0; + if ((envlen = GetEnvironmentVariableW(var = L"HOME", NULL, 0)) == 0 + && (envlen = GetEnvironmentVariableW(var = L"USERPROFILE", + NULL, 0)) == 0) + envlen = GetEnvironmentVariableW(var = L"SYSTEMROOT", NULL, 0); + } + + /* If we got a value, allocate space to hold it and then get it. */ + if (envlen != 0) { + int sz; + WCHAR *val = _alloca(envlen * sizeof(WCHAR)); + + if (GetEnvironmentVariableW(var, val, envlen) < envlen + && (sz = WideCharToMultiByte(CP_UTF8, 0, val, -1, NULL, 0, + NULL, NULL)) != 0) { + s = _alloca(sz); + if (WideCharToMultiByte(CP_UTF8, 0, val, -1, s, sz, + NULL, NULL) == 0) + s = NULL; + } + } +#else + if ((s = ossl_safe_getenv("RANDFILE")) == NULL || *s == '\0') { + use_randfile = 0; + s = ossl_safe_getenv("HOME"); + } +#endif + +#ifdef DEFAULT_HOME + if (!use_randfile && s == NULL) + s = DEFAULT_HOME; +#endif + if (s == NULL || *s == '\0') + return NULL; + + len = strlen(s); + if (use_randfile) { + if (len + 1 >= size) + return NULL; + strcpy(buf, s); + } else { + if (len + 1 + strlen(RFILE) + 1 >= size) + return NULL; + strcpy(buf, s); +#ifndef OPENSSL_SYS_VMS + strcat(buf, "/"); +#endif + strcat(buf, RFILE); + } + + return buf; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rc2/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/rc2/build.info new file mode 100644 index 000000000..47a3fd0d4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rc2/build.info @@ -0,0 +1,3 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + rc2_ecb.c rc2_skey.c rc2_cbc.c rc2cfb64.c rc2ofb64.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rc2/rc2_cbc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rc2/rc2_cbc.c new file mode 100644 index 000000000..2b59353b1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rc2/rc2_cbc.c @@ -0,0 +1,179 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "rc2_locl.h" + +void RC2_cbc_encrypt(const unsigned char *in, unsigned char *out, long length, + RC2_KEY *ks, unsigned char *iv, int encrypt) +{ + register unsigned long tin0, tin1; + register unsigned long tout0, tout1, xor0, xor1; + register long l = length; + unsigned long tin[2]; + + if (encrypt) { + c2l(iv, tout0); + c2l(iv, tout1); + iv -= 8; + for (l -= 8; l >= 0; l -= 8) { + c2l(in, tin0); + c2l(in, tin1); + tin0 ^= tout0; + tin1 ^= tout1; + tin[0] = tin0; + tin[1] = tin1; + RC2_encrypt(tin, ks); + tout0 = tin[0]; + l2c(tout0, out); + tout1 = tin[1]; + l2c(tout1, out); + } + if (l != -8) { + c2ln(in, tin0, tin1, l + 8); + tin0 ^= tout0; + tin1 ^= tout1; + tin[0] = tin0; + tin[1] = tin1; + RC2_encrypt(tin, ks); + tout0 = tin[0]; + l2c(tout0, out); + tout1 = tin[1]; + l2c(tout1, out); + } + l2c(tout0, iv); + l2c(tout1, iv); + } else { + c2l(iv, xor0); + c2l(iv, xor1); + iv -= 8; + for (l -= 8; l >= 0; l -= 8) { + c2l(in, tin0); + tin[0] = tin0; + c2l(in, tin1); + tin[1] = tin1; + RC2_decrypt(tin, ks); + tout0 = tin[0] ^ xor0; + tout1 = tin[1] ^ xor1; + l2c(tout0, out); + l2c(tout1, out); + xor0 = tin0; + xor1 = tin1; + } + if (l != -8) { + c2l(in, tin0); + tin[0] = tin0; + c2l(in, tin1); + tin[1] = tin1; + RC2_decrypt(tin, ks); + tout0 = tin[0] ^ xor0; + tout1 = tin[1] ^ xor1; + l2cn(tout0, tout1, out, l + 8); + xor0 = tin0; + xor1 = tin1; + } + l2c(xor0, iv); + l2c(xor1, iv); + } + tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0; + tin[0] = tin[1] = 0; +} + +void RC2_encrypt(unsigned long *d, RC2_KEY *key) +{ + int i, n; + register RC2_INT *p0, *p1; + register RC2_INT x0, x1, x2, x3, t; + unsigned long l; + + l = d[0]; + x0 = (RC2_INT) l & 0xffff; + x1 = (RC2_INT) (l >> 16L); + l = d[1]; + x2 = (RC2_INT) l & 0xffff; + x3 = (RC2_INT) (l >> 16L); + + n = 3; + i = 5; + + p0 = p1 = &(key->data[0]); + for (;;) { + t = (x0 + (x1 & ~x3) + (x2 & x3) + *(p0++)) & 0xffff; + x0 = (t << 1) | (t >> 15); + t = (x1 + (x2 & ~x0) + (x3 & x0) + *(p0++)) & 0xffff; + x1 = (t << 2) | (t >> 14); + t = (x2 + (x3 & ~x1) + (x0 & x1) + *(p0++)) & 0xffff; + x2 = (t << 3) | (t >> 13); + t = (x3 + (x0 & ~x2) + (x1 & x2) + *(p0++)) & 0xffff; + x3 = (t << 5) | (t >> 11); + + if (--i == 0) { + if (--n == 0) + break; + i = (n == 2) ? 6 : 5; + + x0 += p1[x3 & 0x3f]; + x1 += p1[x0 & 0x3f]; + x2 += p1[x1 & 0x3f]; + x3 += p1[x2 & 0x3f]; + } + } + + d[0] = + (unsigned long)(x0 & 0xffff) | ((unsigned long)(x1 & 0xffff) << 16L); + d[1] = + (unsigned long)(x2 & 0xffff) | ((unsigned long)(x3 & 0xffff) << 16L); +} + +void RC2_decrypt(unsigned long *d, RC2_KEY *key) +{ + int i, n; + register RC2_INT *p0, *p1; + register RC2_INT x0, x1, x2, x3, t; + unsigned long l; + + l = d[0]; + x0 = (RC2_INT) l & 0xffff; + x1 = (RC2_INT) (l >> 16L); + l = d[1]; + x2 = (RC2_INT) l & 0xffff; + x3 = (RC2_INT) (l >> 16L); + + n = 3; + i = 5; + + p0 = &(key->data[63]); + p1 = &(key->data[0]); + for (;;) { + t = ((x3 << 11) | (x3 >> 5)) & 0xffff; + x3 = (t - (x0 & ~x2) - (x1 & x2) - *(p0--)) & 0xffff; + t = ((x2 << 13) | (x2 >> 3)) & 0xffff; + x2 = (t - (x3 & ~x1) - (x0 & x1) - *(p0--)) & 0xffff; + t = ((x1 << 14) | (x1 >> 2)) & 0xffff; + x1 = (t - (x2 & ~x0) - (x3 & x0) - *(p0--)) & 0xffff; + t = ((x0 << 15) | (x0 >> 1)) & 0xffff; + x0 = (t - (x1 & ~x3) - (x2 & x3) - *(p0--)) & 0xffff; + + if (--i == 0) { + if (--n == 0) + break; + i = (n == 2) ? 6 : 5; + + x3 = (x3 - p1[x2 & 0x3f]) & 0xffff; + x2 = (x2 - p1[x1 & 0x3f]) & 0xffff; + x1 = (x1 - p1[x0 & 0x3f]) & 0xffff; + x0 = (x0 - p1[x3 & 0x3f]) & 0xffff; + } + } + + d[0] = + (unsigned long)(x0 & 0xffff) | ((unsigned long)(x1 & 0xffff) << 16L); + d[1] = + (unsigned long)(x2 & 0xffff) | ((unsigned long)(x3 & 0xffff) << 16L); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rc2/rc2_ecb.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rc2/rc2_ecb.c new file mode 100644 index 000000000..fb2f78273 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rc2/rc2_ecb.c @@ -0,0 +1,40 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "rc2_locl.h" +#include + +/*- + * RC2 as implemented frm a posting from + * Newsgroups: sci.crypt + * Subject: Specification for Ron Rivests Cipher No.2 + * Message-ID: <4fk39f$f70@net.auckland.ac.nz> + * Date: 11 Feb 1996 06:45:03 GMT + */ + +void RC2_ecb_encrypt(const unsigned char *in, unsigned char *out, RC2_KEY *ks, + int encrypt) +{ + unsigned long l, d[2]; + + c2l(in, l); + d[0] = l; + c2l(in, l); + d[1] = l; + if (encrypt) + RC2_encrypt(d, ks); + else + RC2_decrypt(d, ks); + l = d[0]; + l2c(l, out); + l = d[1]; + l2c(l, out); + l = d[0] = d[1] = 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rc2/rc2_locl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/rc2/rc2_locl.h new file mode 100644 index 000000000..e4dad9478 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rc2/rc2_locl.h @@ -0,0 +1,134 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#undef c2l +#define c2l(c,l) (l =((unsigned long)(*((c)++))) , \ + l|=((unsigned long)(*((c)++)))<< 8L, \ + l|=((unsigned long)(*((c)++)))<<16L, \ + l|=((unsigned long)(*((c)++)))<<24L) + +/* NOTE - c is not incremented as per c2l */ +#undef c2ln +#define c2ln(c,l1,l2,n) { \ + c+=n; \ + l1=l2=0; \ + switch (n) { \ + case 8: l2 =((unsigned long)(*(--(c))))<<24L; \ + /* fall thru */ \ + case 7: l2|=((unsigned long)(*(--(c))))<<16L; \ + /* fall thru */ \ + case 6: l2|=((unsigned long)(*(--(c))))<< 8L; \ + /* fall thru */ \ + case 5: l2|=((unsigned long)(*(--(c)))); \ + /* fall thru */ \ + case 4: l1 =((unsigned long)(*(--(c))))<<24L; \ + /* fall thru */ \ + case 3: l1|=((unsigned long)(*(--(c))))<<16L; \ + /* fall thru */ \ + case 2: l1|=((unsigned long)(*(--(c))))<< 8L; \ + /* fall thru */ \ + case 1: l1|=((unsigned long)(*(--(c)))); \ + } \ + } + +#undef l2c +#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24L)&0xff)) + +/* NOTE - c is not incremented as per l2c */ +#undef l2cn +#define l2cn(l1,l2,c,n) { \ + c+=n; \ + switch (n) { \ + case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \ + /* fall thru */ \ + case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \ + /* fall thru */ \ + case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \ + /* fall thru */ \ + case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ + /* fall thru */ \ + case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \ + /* fall thru */ \ + case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \ + /* fall thru */ \ + case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \ + /* fall thru */ \ + case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ + } \ + } + +/* NOTE - c is not incremented as per n2l */ +#define n2ln(c,l1,l2,n) { \ + c+=n; \ + l1=l2=0; \ + switch (n) { \ + case 8: l2 =((unsigned long)(*(--(c)))) ; \ + /* fall thru */ \ + case 7: l2|=((unsigned long)(*(--(c))))<< 8; \ + /* fall thru */ \ + case 6: l2|=((unsigned long)(*(--(c))))<<16; \ + /* fall thru */ \ + case 5: l2|=((unsigned long)(*(--(c))))<<24; \ + /* fall thru */ \ + case 4: l1 =((unsigned long)(*(--(c)))) ; \ + /* fall thru */ \ + case 3: l1|=((unsigned long)(*(--(c))))<< 8; \ + /* fall thru */ \ + case 2: l1|=((unsigned long)(*(--(c))))<<16; \ + /* fall thru */ \ + case 1: l1|=((unsigned long)(*(--(c))))<<24; \ + } \ + } + +/* NOTE - c is not incremented as per l2n */ +#define l2nn(l1,l2,c,n) { \ + c+=n; \ + switch (n) { \ + case 8: *(--(c))=(unsigned char)(((l2) )&0xff); \ + /* fall thru */ \ + case 7: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \ + /* fall thru */ \ + case 6: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \ + /* fall thru */ \ + case 5: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \ + /* fall thru */ \ + case 4: *(--(c))=(unsigned char)(((l1) )&0xff); \ + /* fall thru */ \ + case 3: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \ + /* fall thru */ \ + case 2: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \ + /* fall thru */ \ + case 1: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \ + } \ + } + +#undef n2l +#define n2l(c,l) (l =((unsigned long)(*((c)++)))<<24L, \ + l|=((unsigned long)(*((c)++)))<<16L, \ + l|=((unsigned long)(*((c)++)))<< 8L, \ + l|=((unsigned long)(*((c)++)))) + +#undef l2n +#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +#define C_RC2(n) \ + t=(x0+(x1& ~x3)+(x2&x3)+ *(p0++))&0xffff; \ + x0=(t<<1)|(t>>15); \ + t=(x1+(x2& ~x0)+(x3&x0)+ *(p0++))&0xffff; \ + x1=(t<<2)|(t>>14); \ + t=(x2+(x3& ~x1)+(x0&x1)+ *(p0++))&0xffff; \ + x2=(t<<3)|(t>>13); \ + t=(x3+(x0& ~x2)+(x1&x2)+ *(p0++))&0xffff; \ + x3=(t<<5)|(t>>11); diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rc2/rc2_skey.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rc2/rc2_skey.c new file mode 100644 index 000000000..55d8ba371 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rc2/rc2_skey.c @@ -0,0 +1,98 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "rc2_locl.h" + +static const unsigned char key_table[256] = { + 0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 0x28, 0xe9, 0xfd, 0x79, + 0x4a, 0xa0, 0xd8, 0x9d, 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e, + 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2, 0x17, 0x9a, 0x59, 0xf5, + 0x87, 0xb3, 0x4f, 0x13, 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32, + 0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b, 0xf0, 0x95, 0x21, 0x22, + 0x5c, 0x6b, 0x4e, 0x82, 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c, + 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc, 0x12, 0x75, 0xca, 0x1f, + 0x3b, 0xbe, 0xe4, 0xd1, 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26, + 0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57, 0x27, 0xf2, 0x1d, 0x9b, + 0xbc, 0x94, 0x43, 0x03, 0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7, + 0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7, 0x08, 0xe8, 0xea, 0xde, + 0x80, 0x52, 0xee, 0xf7, 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a, + 0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, 0x4b, 0x9f, 0xd0, 0x5e, + 0x04, 0x18, 0xa4, 0xec, 0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc, + 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39, 0x99, 0x7c, 0x3a, 0x85, + 0x23, 0xb8, 0xb4, 0x7a, 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31, + 0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, 0x05, 0xdf, 0x29, 0x10, + 0x67, 0x6c, 0xba, 0xc9, 0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c, + 0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9, 0x0d, 0x38, 0x34, 0x1b, + 0xab, 0x33, 0xff, 0xb0, 0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e, + 0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, 0x0a, 0xa6, 0x20, 0x68, + 0xfe, 0x7f, 0xc1, 0xad, +}; + +#if defined(_MSC_VER) && defined(_ARM_) +# pragma optimize("g",off) +#endif + +/* + * It has come to my attention that there are 2 versions of the RC2 key + * schedule. One which is normal, and anther which has a hook to use a + * reduced key length. BSAFE uses the 'retarded' version. What I previously + * shipped is the same as specifying 1024 for the 'bits' parameter. Bsafe + * uses a version where the bits parameter is the same as len*8 + */ +void RC2_set_key(RC2_KEY *key, int len, const unsigned char *data, int bits) +{ + int i, j; + unsigned char *k; + RC2_INT *ki; + unsigned int c, d; + + k = (unsigned char *)&(key->data[0]); + *k = 0; /* for if there is a zero length key */ + + if (len > 128) + len = 128; + if (bits <= 0) + bits = 1024; + if (bits > 1024) + bits = 1024; + + for (i = 0; i < len; i++) + k[i] = data[i]; + + /* expand table */ + d = k[len - 1]; + j = 0; + for (i = len; i < 128; i++, j++) { + d = key_table[(k[j] + d) & 0xff]; + k[i] = d; + } + + /* hmm.... key reduction to 'bits' bits */ + + j = (bits + 7) >> 3; + i = 128 - j; + c = (0xff >> (-bits & 0x07)); + + d = key_table[k[i] & c]; + k[i] = d; + while (i--) { + d = key_table[k[i + j] ^ d]; + k[i] = d; + } + + /* copy from bytes into RC2_INT's */ + ki = &(key->data[63]); + for (i = 127; i >= 0; i -= 2) + *(ki--) = ((k[i] << 8) | k[i - 1]) & 0xffff; +} + +#if defined(_MSC_VER) +# pragma optimize("",on) +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rc2/rc2cfb64.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rc2/rc2cfb64.c new file mode 100644 index 000000000..e11093db9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rc2/rc2cfb64.c @@ -0,0 +1,74 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "rc2_locl.h" + +/* + * The input and output encrypted as though 64bit cfb mode is being used. + * The extra state information to record how much of the 64bit block we have + * used is contained in *num; + */ + +void RC2_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, RC2_KEY *schedule, unsigned char *ivec, + int *num, int encrypt) +{ + register unsigned long v0, v1, t; + register int n = *num; + register long l = length; + unsigned long ti[2]; + unsigned char *iv, c, cc; + + iv = (unsigned char *)ivec; + if (encrypt) { + while (l--) { + if (n == 0) { + c2l(iv, v0); + ti[0] = v0; + c2l(iv, v1); + ti[1] = v1; + RC2_encrypt((unsigned long *)ti, schedule); + iv = (unsigned char *)ivec; + t = ti[0]; + l2c(t, iv); + t = ti[1]; + l2c(t, iv); + iv = (unsigned char *)ivec; + } + c = *(in++) ^ iv[n]; + *(out++) = c; + iv[n] = c; + n = (n + 1) & 0x07; + } + } else { + while (l--) { + if (n == 0) { + c2l(iv, v0); + ti[0] = v0; + c2l(iv, v1); + ti[1] = v1; + RC2_encrypt((unsigned long *)ti, schedule); + iv = (unsigned char *)ivec; + t = ti[0]; + l2c(t, iv); + t = ti[1]; + l2c(t, iv); + iv = (unsigned char *)ivec; + } + cc = *(in++); + c = iv[n]; + iv[n] = cc; + *(out++) = c ^ cc; + n = (n + 1) & 0x07; + } + } + v0 = v1 = ti[0] = ti[1] = t = c = cc = 0; + *num = n; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rc2/rc2ofb64.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rc2/rc2ofb64.c new file mode 100644 index 000000000..d610278a9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rc2/rc2ofb64.c @@ -0,0 +1,61 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "rc2_locl.h" + +/* + * The input and output encrypted as though 64bit ofb mode is being used. + * The extra state information to record how much of the 64bit block we have + * used is contained in *num; + */ +void RC2_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, RC2_KEY *schedule, unsigned char *ivec, + int *num) +{ + register unsigned long v0, v1, t; + register int n = *num; + register long l = length; + unsigned char d[8]; + register char *dp; + unsigned long ti[2]; + unsigned char *iv; + int save = 0; + + iv = (unsigned char *)ivec; + c2l(iv, v0); + c2l(iv, v1); + ti[0] = v0; + ti[1] = v1; + dp = (char *)d; + l2c(v0, dp); + l2c(v1, dp); + while (l--) { + if (n == 0) { + RC2_encrypt((unsigned long *)ti, schedule); + dp = (char *)d; + t = ti[0]; + l2c(t, dp); + t = ti[1]; + l2c(t, dp); + save++; + } + *(out++) = *(in++) ^ d[n]; + n = (n + 1) & 0x07; + } + if (save) { + v0 = ti[0]; + v1 = ti[1]; + iv = (unsigned char *)ivec; + l2c(v0, iv); + l2c(v1, iv); + } + t = v0 = v1 = ti[0] = ti[1] = 0; + *num = n; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/asm/rc4-586.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/asm/rc4-586.pl new file mode 100644 index 000000000..8c5cf87d0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/asm/rc4-586.pl @@ -0,0 +1,426 @@ +#! /usr/bin/env perl +# Copyright 1998-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# [Re]written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# At some point it became apparent that the original SSLeay RC4 +# assembler implementation performs suboptimally on latest IA-32 +# microarchitectures. After re-tuning performance has changed as +# following: +# +# Pentium -10% +# Pentium III +12% +# AMD +50%(*) +# P4 +250%(**) +# +# (*) This number is actually a trade-off:-) It's possible to +# achieve +72%, but at the cost of -48% off PIII performance. +# In other words code performing further 13% faster on AMD +# would perform almost 2 times slower on Intel PIII... +# For reference! This code delivers ~80% of rc4-amd64.pl +# performance on the same Opteron machine. +# (**) This number requires compressed key schedule set up by +# RC4_set_key [see commentary below for further details]. + +# May 2011 +# +# Optimize for Core2 and Westmere [and incidentally Opteron]. Current +# performance in cycles per processed byte (less is better) and +# improvement relative to previous version of this module is: +# +# Pentium 10.2 # original numbers +# Pentium III 7.8(*) +# Intel P4 7.5 +# +# Opteron 6.1/+20% # new MMX numbers +# Core2 5.3/+67%(**) +# Westmere 5.1/+94%(**) +# Sandy Bridge 5.0/+8% +# Atom 12.6/+6% +# VIA Nano 6.4/+9% +# Ivy Bridge 4.9/±0% +# Bulldozer 4.9/+15% +# +# (*) PIII can actually deliver 6.6 cycles per byte with MMX code, +# but this specific code performs poorly on Core2. And vice +# versa, below MMX/SSE code delivering 5.8/7.1 on Core2 performs +# poorly on PIII, at 8.0/14.5:-( As PIII is not a "hot" CPU +# [anymore], I chose to discard PIII-specific code path and opt +# for original IALU-only code, which is why MMX/SSE code path +# is guarded by SSE2 bit (see below), not MMX/SSE. +# (**) Performance vs. block size on Core2 and Westmere had a maximum +# at ... 64 bytes block size. And it was quite a maximum, 40-60% +# in comparison to largest 8KB block size. Above improvement +# coefficients are for the largest block size. + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +$output=pop; +open STDOUT,">$output"; + +&asm_init($ARGV[0],$x86only = $ARGV[$#ARGV] eq "386"); + +$xx="eax"; +$yy="ebx"; +$tx="ecx"; +$ty="edx"; +$inp="esi"; +$out="ebp"; +$dat="edi"; + +sub RC4_loop { + my $i=shift; + my $func = ($i==0)?*mov:*or; + + &add (&LB($yy),&LB($tx)); + &mov ($ty,&DWP(0,$dat,$yy,4)); + &mov (&DWP(0,$dat,$yy,4),$tx); + &mov (&DWP(0,$dat,$xx,4),$ty); + &add ($ty,$tx); + &inc (&LB($xx)); + &and ($ty,0xff); + &ror ($out,8) if ($i!=0); + if ($i<3) { + &mov ($tx,&DWP(0,$dat,$xx,4)); + } else { + &mov ($tx,&wparam(3)); # reload [re-biased] out + } + &$func ($out,&DWP(0,$dat,$ty,4)); +} + +if ($alt=0) { + # >20% faster on Atom and Sandy Bridge[!], 8% faster on Opteron, + # but ~40% slower on Core2 and Westmere... Attempt to add movz + # brings down Opteron by 25%, Atom and Sandy Bridge by 15%, yet + # on Core2 with movz it's almost 20% slower than below alternative + # code... Yes, it's a total mess... + my @XX=($xx,$out); + $RC4_loop_mmx = sub { # SSE actually... + my $i=shift; + my $j=$i<=0?0:$i>>1; + my $mm=$i<=0?"mm0":"mm".($i&1); + + &add (&LB($yy),&LB($tx)); + &lea (@XX[1],&DWP(1,@XX[0])); + &pxor ("mm2","mm0") if ($i==0); + &psllq ("mm1",8) if ($i==0); + &and (@XX[1],0xff); + &pxor ("mm0","mm0") if ($i<=0); + &mov ($ty,&DWP(0,$dat,$yy,4)); + &mov (&DWP(0,$dat,$yy,4),$tx); + &pxor ("mm1","mm2") if ($i==0); + &mov (&DWP(0,$dat,$XX[0],4),$ty); + &add (&LB($ty),&LB($tx)); + &movd (@XX[0],"mm7") if ($i==0); + &mov ($tx,&DWP(0,$dat,@XX[1],4)); + &pxor ("mm1","mm1") if ($i==1); + &movq ("mm2",&QWP(0,$inp)) if ($i==1); + &movq (&QWP(-8,(@XX[0],$inp)),"mm1") if ($i==0); + &pinsrw ($mm,&DWP(0,$dat,$ty,4),$j); + + push (@XX,shift(@XX)) if ($i>=0); + } +} else { + # Using pinsrw here improves performance on Intel CPUs by 2-3%, but + # brings down AMD by 7%... + $RC4_loop_mmx = sub { + my $i=shift; + + &add (&LB($yy),&LB($tx)); + &psllq ("mm1",8*(($i-1)&7)) if (abs($i)!=1); + &mov ($ty,&DWP(0,$dat,$yy,4)); + &mov (&DWP(0,$dat,$yy,4),$tx); + &mov (&DWP(0,$dat,$xx,4),$ty); + &inc ($xx); + &add ($ty,$tx); + &movz ($xx,&LB($xx)); # (*) + &movz ($ty,&LB($ty)); # (*) + &pxor ("mm2",$i==1?"mm0":"mm1") if ($i>=0); + &movq ("mm0",&QWP(0,$inp)) if ($i<=0); + &movq (&QWP(-8,($out,$inp)),"mm2") if ($i==0); + &mov ($tx,&DWP(0,$dat,$xx,4)); + &movd ($i>0?"mm1":"mm2",&DWP(0,$dat,$ty,4)); + + # (*) This is the key to Core2 and Westmere performance. + # Without movz out-of-order execution logic confuses + # itself and fails to reorder loads and stores. Problem + # appears to be fixed in Sandy Bridge... + } +} + +&external_label("OPENSSL_ia32cap_P"); + +# void RC4(RC4_KEY *key,size_t len,const unsigned char *inp,unsigned char *out); +&function_begin("RC4"); + &mov ($dat,&wparam(0)); # load key schedule pointer + &mov ($ty, &wparam(1)); # load len + &mov ($inp,&wparam(2)); # load inp + &mov ($out,&wparam(3)); # load out + + &xor ($xx,$xx); # avoid partial register stalls + &xor ($yy,$yy); + + &cmp ($ty,0); # safety net + &je (&label("abort")); + + &mov (&LB($xx),&BP(0,$dat)); # load key->x + &mov (&LB($yy),&BP(4,$dat)); # load key->y + &add ($dat,8); + + &lea ($tx,&DWP(0,$inp,$ty)); + &sub ($out,$inp); # re-bias out + &mov (&wparam(1),$tx); # save input+len + + &inc (&LB($xx)); + + # detect compressed key schedule... + &cmp (&DWP(256,$dat),-1); + &je (&label("RC4_CHAR")); + + &mov ($tx,&DWP(0,$dat,$xx,4)); + + &and ($ty,-4); # how many 4-byte chunks? + &jz (&label("loop1")); + + &mov (&wparam(3),$out); # $out as accumulator in these loops + if ($x86only) { + &jmp (&label("go4loop4")); + } else { + &test ($ty,-8); + &jz (&label("go4loop4")); + + &picmeup($out,"OPENSSL_ia32cap_P"); + &bt (&DWP(0,$out),26); # check SSE2 bit [could have been MMX] + &jnc (&label("go4loop4")); + + &mov ($out,&wparam(3)) if (!$alt); + &movd ("mm7",&wparam(3)) if ($alt); + &and ($ty,-8); + &lea ($ty,&DWP(-8,$inp,$ty)); + &mov (&DWP(-4,$dat),$ty); # save input+(len/8)*8-8 + + &$RC4_loop_mmx(-1); + &jmp(&label("loop_mmx_enter")); + + &set_label("loop_mmx",16); + &$RC4_loop_mmx(0); + &set_label("loop_mmx_enter"); + for ($i=1;$i<8;$i++) { &$RC4_loop_mmx($i); } + &mov ($ty,$yy); + &xor ($yy,$yy); # this is second key to Core2 + &mov (&LB($yy),&LB($ty)); # and Westmere performance... + &cmp ($inp,&DWP(-4,$dat)); + &lea ($inp,&DWP(8,$inp)); + &jb (&label("loop_mmx")); + + if ($alt) { + &movd ($out,"mm7"); + &pxor ("mm2","mm0"); + &psllq ("mm1",8); + &pxor ("mm1","mm2"); + &movq (&QWP(-8,$out,$inp),"mm1"); + } else { + &psllq ("mm1",56); + &pxor ("mm2","mm1"); + &movq (&QWP(-8,$out,$inp),"mm2"); + } + &emms (); + + &cmp ($inp,&wparam(1)); # compare to input+len + &je (&label("done")); + &jmp (&label("loop1")); + } + +&set_label("go4loop4",16); + &lea ($ty,&DWP(-4,$inp,$ty)); + &mov (&wparam(2),$ty); # save input+(len/4)*4-4 + + &set_label("loop4"); + for ($i=0;$i<4;$i++) { RC4_loop($i); } + &ror ($out,8); + &xor ($out,&DWP(0,$inp)); + &cmp ($inp,&wparam(2)); # compare to input+(len/4)*4-4 + &mov (&DWP(0,$tx,$inp),$out);# $tx holds re-biased out here + &lea ($inp,&DWP(4,$inp)); + &mov ($tx,&DWP(0,$dat,$xx,4)); + &jb (&label("loop4")); + + &cmp ($inp,&wparam(1)); # compare to input+len + &je (&label("done")); + &mov ($out,&wparam(3)); # restore $out + + &set_label("loop1",16); + &add (&LB($yy),&LB($tx)); + &mov ($ty,&DWP(0,$dat,$yy,4)); + &mov (&DWP(0,$dat,$yy,4),$tx); + &mov (&DWP(0,$dat,$xx,4),$ty); + &add ($ty,$tx); + &inc (&LB($xx)); + &and ($ty,0xff); + &mov ($ty,&DWP(0,$dat,$ty,4)); + &xor (&LB($ty),&BP(0,$inp)); + &lea ($inp,&DWP(1,$inp)); + &mov ($tx,&DWP(0,$dat,$xx,4)); + &cmp ($inp,&wparam(1)); # compare to input+len + &mov (&BP(-1,$out,$inp),&LB($ty)); + &jb (&label("loop1")); + + &jmp (&label("done")); + +# this is essentially Intel P4 specific codepath... +&set_label("RC4_CHAR",16); + &movz ($tx,&BP(0,$dat,$xx)); + # strangely enough unrolled loop performs over 20% slower... + &set_label("cloop1"); + &add (&LB($yy),&LB($tx)); + &movz ($ty,&BP(0,$dat,$yy)); + &mov (&BP(0,$dat,$yy),&LB($tx)); + &mov (&BP(0,$dat,$xx),&LB($ty)); + &add (&LB($ty),&LB($tx)); + &movz ($ty,&BP(0,$dat,$ty)); + &add (&LB($xx),1); + &xor (&LB($ty),&BP(0,$inp)); + &lea ($inp,&DWP(1,$inp)); + &movz ($tx,&BP(0,$dat,$xx)); + &cmp ($inp,&wparam(1)); + &mov (&BP(-1,$out,$inp),&LB($ty)); + &jb (&label("cloop1")); + +&set_label("done"); + &dec (&LB($xx)); + &mov (&DWP(-4,$dat),$yy); # save key->y + &mov (&BP(-8,$dat),&LB($xx)); # save key->x +&set_label("abort"); +&function_end("RC4"); + +######################################################################## + +$inp="esi"; +$out="edi"; +$idi="ebp"; +$ido="ecx"; +$idx="edx"; + +# void RC4_set_key(RC4_KEY *key,int len,const unsigned char *data); +&function_begin("RC4_set_key"); + &mov ($out,&wparam(0)); # load key + &mov ($idi,&wparam(1)); # load len + &mov ($inp,&wparam(2)); # load data + &picmeup($idx,"OPENSSL_ia32cap_P"); + + &lea ($out,&DWP(2*4,$out)); # &key->data + &lea ($inp,&DWP(0,$inp,$idi)); # $inp to point at the end + &neg ($idi); + &xor ("eax","eax"); + &mov (&DWP(-4,$out),$idi); # borrow key->y + + &bt (&DWP(0,$idx),20); # check for bit#20 + &jc (&label("c1stloop")); + +&set_label("w1stloop",16); + &mov (&DWP(0,$out,"eax",4),"eax"); # key->data[i]=i; + &add (&LB("eax"),1); # i++; + &jnc (&label("w1stloop")); + + &xor ($ido,$ido); + &xor ($idx,$idx); + +&set_label("w2ndloop",16); + &mov ("eax",&DWP(0,$out,$ido,4)); + &add (&LB($idx),&BP(0,$inp,$idi)); + &add (&LB($idx),&LB("eax")); + &add ($idi,1); + &mov ("ebx",&DWP(0,$out,$idx,4)); + &jnz (&label("wnowrap")); + &mov ($idi,&DWP(-4,$out)); + &set_label("wnowrap"); + &mov (&DWP(0,$out,$idx,4),"eax"); + &mov (&DWP(0,$out,$ido,4),"ebx"); + &add (&LB($ido),1); + &jnc (&label("w2ndloop")); +&jmp (&label("exit")); + +# Unlike all other x86 [and x86_64] implementations, Intel P4 core +# [including EM64T] was found to perform poorly with above "32-bit" key +# schedule, a.k.a. RC4_INT. Performance improvement for IA-32 hand-coded +# assembler turned out to be 3.5x if re-coded for compressed 8-bit one, +# a.k.a. RC4_CHAR! It's however inappropriate to just switch to 8-bit +# schedule for x86[_64], because non-P4 implementations suffer from +# significant performance losses then, e.g. PIII exhibits >2x +# deterioration, and so does Opteron. In order to assure optimal +# all-round performance, we detect P4 at run-time and set up compressed +# key schedule, which is recognized by RC4 procedure. + +&set_label("c1stloop",16); + &mov (&BP(0,$out,"eax"),&LB("eax")); # key->data[i]=i; + &add (&LB("eax"),1); # i++; + &jnc (&label("c1stloop")); + + &xor ($ido,$ido); + &xor ($idx,$idx); + &xor ("ebx","ebx"); + +&set_label("c2ndloop",16); + &mov (&LB("eax"),&BP(0,$out,$ido)); + &add (&LB($idx),&BP(0,$inp,$idi)); + &add (&LB($idx),&LB("eax")); + &add ($idi,1); + &mov (&LB("ebx"),&BP(0,$out,$idx)); + &jnz (&label("cnowrap")); + &mov ($idi,&DWP(-4,$out)); + &set_label("cnowrap"); + &mov (&BP(0,$out,$idx),&LB("eax")); + &mov (&BP(0,$out,$ido),&LB("ebx")); + &add (&LB($ido),1); + &jnc (&label("c2ndloop")); + + &mov (&DWP(256,$out),-1); # mark schedule as compressed + +&set_label("exit"); + &xor ("eax","eax"); + &mov (&DWP(-8,$out),"eax"); # key->x=0; + &mov (&DWP(-4,$out),"eax"); # key->y=0; +&function_end("RC4_set_key"); + +# const char *RC4_options(void); +&function_begin_B("RC4_options"); + &call (&label("pic_point")); +&set_label("pic_point"); + &blindpop("eax"); + &lea ("eax",&DWP(&label("opts")."-".&label("pic_point"),"eax")); + &picmeup("edx","OPENSSL_ia32cap_P"); + &mov ("edx",&DWP(0,"edx")); + &bt ("edx",20); + &jc (&label("1xchar")); + &bt ("edx",26); + &jnc (&label("ret")); + &add ("eax",25); + &ret (); +&set_label("1xchar"); + &add ("eax",12); +&set_label("ret"); + &ret (); +&set_label("opts",64); +&asciz ("rc4(4x,int)"); +&asciz ("rc4(1x,char)"); +&asciz ("rc4(8x,mmx)"); +&asciz ("RC4 for x86, CRYPTOGAMS by "); +&align (64); +&function_end_B("RC4_options"); + +&asm_finish(); + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/asm/rc4-c64xplus.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/asm/rc4-c64xplus.pl new file mode 100644 index 000000000..1354d1821 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/asm/rc4-c64xplus.pl @@ -0,0 +1,192 @@ +#! /usr/bin/env perl +# Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# RC4 for C64x+. +# +# April 2014 +# +# RC4 subroutine processes one byte in 7.0 cycles, which is 3x faster +# than TI CGT-generated code. Loop is scheduled in such way that +# there is only one reference to memory in each cycle. This is done +# to avoid L1D memory banking conflicts, see SPRU871 TI publication +# for further details. Otherwise it should be possible to schedule +# the loop for iteration interval of 6... + +($KEY,$LEN,$INP,$OUT)=("A4","B4","A6","B6"); + +($KEYA,$XX,$TY,$xx,$ONE,$ret)=map("A$_",(5,7,8,9,1,2)); +($KEYB,$YY,$TX,$tx,$SUM,$dat)=map("B$_",(5,7,8,9,1,2)); + +$code.=<<___; + .text + + .if .ASSEMBLER_VERSION<7000000 + .asg 0,__TI_EABI__ + .endif + .if __TI_EABI__ + .nocmp + .asg RC4,_RC4 + .asg RC4_set_key,_RC4_set_key + .asg RC4_options,_RC4_options + .endif + + .global _RC4 + .align 16 +_RC4: + .asmfunc + MV $LEN,B0 + [!B0] BNOP B3 ; if (len==0) return; +||[B0] ADD $KEY,2,$KEYA +||[B0] ADD $KEY,2,$KEYB + [B0] MVK 1,$ONE +||[B0] LDBU *${KEYA}[-2],$XX ; key->x + [B0] LDBU *${KEYB}[-1],$YY ; key->y +|| NOP 4 + + ADD4 $ONE,$XX,$XX + LDBU *${KEYA}[$XX],$TX +|| MVC $LEN,ILC + NOP 4 +;;================================================== + SPLOOP 7 +|| ADD4 $TX,$YY,$YY + + LDBU *${KEYB}[$YY],$TY +|| MVD $XX,$xx +|| ADD4 $ONE,$XX,$XX + LDBU *${KEYA}[$XX],$tx + CMPEQ $YY,$XX,B0 +|| NOP 3 + STB $TX,*${KEYB}[$YY] +||[B0] ADD4 $TX,$YY,$YY + STB $TY,*${KEYA}[$xx] +||[!B0] ADD4 $tx,$YY,$YY +||[!B0] MVD $tx,$TX + ADD4 $TY,$TX,$SUM ; [0,0] $TX is not replaced by $tx yet! +|| NOP 2 + LDBU *$INP++,$dat +|| NOP 2 + LDBU *${KEYB}[$SUM],$ret +|| NOP 5 + XOR.L $dat,$ret,$ret + SPKERNEL +|| STB $ret,*$OUT++ +;;================================================== + SUB4 $XX,$ONE,$XX +|| NOP 5 + STB $XX,*${KEYA}[-2] ; key->x +|| SUB4 $YY,$TX,$YY +|| BNOP B3 + STB $YY,*${KEYB}[-1] ; key->y +|| NOP 5 + .endasmfunc + + .global _RC4_set_key + .align 16 +_RC4_set_key: + .asmfunc + .if .BIG_ENDIAN + MVK 0x00000404,$ONE +|| MVK 0x00000203,B0 + MVKH 0x04040000,$ONE +|| MVKH 0x00010000,B0 + .else + MVK 0x00000404,$ONE +|| MVK 0x00000100,B0 + MVKH 0x04040000,$ONE +|| MVKH 0x03020000,B0 + .endif + ADD $KEY,2,$KEYA +|| ADD $KEY,2,$KEYB +|| ADD $INP,$LEN,$ret ; end of input + LDBU *${INP}++,$dat +|| MVK 0,$TX + STH $TX,*${KEY}++ ; key->x=key->y=0 +|| MV B0,A0 +|| MVK 64-4,B0 + +;;================================================== + SPLOOPD 1 +|| MVC B0,ILC + + STNW A0,*${KEY}++ +|| ADD4 $ONE,A0,A0 + SPKERNEL +;;================================================== + + MVK 0,$YY +|| MVK 0,$XX + MVK 1,$ONE +|| MVK 256-1,B0 + +;;================================================== + SPLOOPD 8 +|| MVC B0,ILC + + ADD4 $dat,$YY,$YY +|| CMPEQ $INP,$ret,A0 ; end of input? + LDBU *${KEYB}[$YY],$TY +|| MVD $XX,$xx +|| ADD4 $ONE,$XX,$XX + LDBU *${KEYA}[$XX],$tx +||[A0] SUB $INP,$LEN,$INP ; rewind + LDBU *${INP}++,$dat +|| CMPEQ $YY,$XX,B0 +|| NOP 3 + STB $TX,*${KEYB}[$YY] +||[B0] ADD4 $TX,$YY,$YY + STB $TY,*${KEYA}[$xx] +||[!B0] ADD4 $tx,$YY,$YY +||[!B0] MV $tx,$TX + SPKERNEL +;;================================================== + + BNOP B3,5 + .endasmfunc + + .global _RC4_options + .align 16 +_RC4_options: +_rc4_options: + .asmfunc + BNOP B3,1 + ADDKPC _rc4_options,B4 + .if __TI_EABI__ + MVKL \$PCR_OFFSET(rc4_options,_rc4_options),A4 + MVKH \$PCR_OFFSET(rc4_options,_rc4_options),A4 + .else + MVKL (rc4_options-_rc4_options),A4 + MVKH (rc4_options-_rc4_options),A4 + .endif + ADD B4,A4,A4 + .endasmfunc + + .if __TI_EABI__ + .sect ".text:rc4_options.const" + .else + .sect ".const:rc4_options" + .endif + .align 4 +rc4_options: + .cstring "rc4(sploop,char)" + .cstring "RC4 for C64+, CRYPTOGAMS by " + .align 4 +___ + +$output=pop; +open STDOUT,">$output"; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/asm/rc4-md5-x86_64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/asm/rc4-md5-x86_64.pl new file mode 100644 index 000000000..74e519105 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/asm/rc4-md5-x86_64.pl @@ -0,0 +1,661 @@ +#! /usr/bin/env perl +# Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# June 2011 +# +# This is RC4+MD5 "stitch" implementation. The idea, as spelled in +# http://download.intel.com/design/intarch/papers/323686.pdf, is that +# since both algorithms exhibit instruction-level parallelism, ILP, +# below theoretical maximum, interleaving them would allow to utilize +# processor resources better and achieve better performance. RC4 +# instruction sequence is virtually identical to rc4-x86_64.pl, which +# is heavily based on submission by Maxim Perminov, Maxim Locktyukhin +# and Jim Guilford of Intel. MD5 is fresh implementation aiming to +# minimize register usage, which was used as "main thread" with RC4 +# weaved into it, one RC4 round per one MD5 round. In addition to the +# stiched subroutine the script can generate standalone replacement +# md5_block_asm_data_order and RC4. Below are performance numbers in +# cycles per processed byte, less is better, for these the standalone +# subroutines, sum of them, and stitched one: +# +# RC4 MD5 RC4+MD5 stitch gain +# Opteron 6.5(*) 5.4 11.9 7.0 +70%(*) +# Core2 6.5 5.8 12.3 7.7 +60% +# Westmere 4.3 5.2 9.5 7.0 +36% +# Sandy Bridge 4.2 5.5 9.7 6.8 +43% +# Ivy Bridge 4.1 5.2 9.3 6.0 +54% +# Haswell 4.0 5.0 9.0 5.7 +60% +# Skylake 6.3(**) 5.0 11.3 5.3 +110% +# Atom 9.3 6.5 15.8 11.1 +42% +# VIA Nano 6.3 5.4 11.7 8.6 +37% +# Bulldozer 4.5 5.4 9.9 7.7 +29% +# +# (*) rc4-x86_64.pl delivers 5.3 on Opteron, so real improvement +# is +53%... +# (**) unidentified anomaly; + +my ($rc4,$md5)=(1,1); # what to generate? +my $D="#" if (!$md5); # if set to "#", MD5 is stitched into RC4(), + # but its result is discarded. Idea here is + # to be able to use 'openssl speed rc4' for + # benchmarking the stitched subroutine... + +my $flavour = shift; +my $output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +my $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; my $dir=$1; my $xlate; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +*STDOUT=*OUT; + +my ($dat,$in0,$out,$ctx,$inp,$len, $func,$nargs); + +if ($rc4 && !$md5) { + ($dat,$len,$in0,$out) = ("%rdi","%rsi","%rdx","%rcx"); + $func="RC4"; $nargs=4; +} elsif ($md5 && !$rc4) { + ($ctx,$inp,$len) = ("%rdi","%rsi","%rdx"); + $func="md5_block_asm_data_order"; $nargs=3; +} else { + ($dat,$in0,$out,$ctx,$inp,$len) = ("%rdi","%rsi","%rdx","%rcx","%r8","%r9"); + $func="rc4_md5_enc"; $nargs=6; + # void rc4_md5_enc( + # RC4_KEY *key, # + # const void *in0, # RC4 input + # void *out, # RC4 output + # MD5_CTX *ctx, # + # const void *inp, # MD5 input + # size_t len); # number of 64-byte blocks +} + +my @K=( 0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee, + 0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501, + 0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be, + 0x6b901122,0xfd987193,0xa679438e,0x49b40821, + + 0xf61e2562,0xc040b340,0x265e5a51,0xe9b6c7aa, + 0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8, + 0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed, + 0xa9e3e905,0xfcefa3f8,0x676f02d9,0x8d2a4c8a, + + 0xfffa3942,0x8771f681,0x6d9d6122,0xfde5380c, + 0xa4beea44,0x4bdecfa9,0xf6bb4b60,0xbebfbc70, + 0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05, + 0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665, + + 0xf4292244,0x432aff97,0xab9423a7,0xfc93a039, + 0x655b59c3,0x8f0ccc92,0xffeff47d,0x85845dd1, + 0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1, + 0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391 ); + +my @V=("%r8d","%r9d","%r10d","%r11d"); # MD5 registers +my $tmp="%r12d"; + +my @XX=("%rbp","%rsi"); # RC4 registers +my @TX=("%rax","%rbx"); +my $YY="%rcx"; +my $TY="%rdx"; + +my $MOD=32; # 16, 32 or 64 + +$code.=<<___; +.text +.align 16 + +.globl $func +.type $func,\@function,$nargs +$func: +.cfi_startproc + cmp \$0,$len + je .Labort + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + sub \$40,%rsp +.cfi_adjust_cfa_offset 40 +.Lbody: +___ +if ($rc4) { +$code.=<<___; +$D#md5# mov $ctx,%r11 # reassign arguments + mov $len,%r12 + mov $in0,%r13 + mov $out,%r14 +$D#md5# mov $inp,%r15 +___ + $ctx="%r11" if ($md5); # reassign arguments + $len="%r12"; + $in0="%r13"; + $out="%r14"; + $inp="%r15" if ($md5); + $inp=$in0 if (!$md5); +$code.=<<___; + xor $XX[0],$XX[0] + xor $YY,$YY + + lea 8($dat),$dat + mov -8($dat),$XX[0]#b + mov -4($dat),$YY#b + + inc $XX[0]#b + sub $in0,$out + movl ($dat,$XX[0],4),$TX[0]#d +___ +$code.=<<___ if (!$md5); + xor $TX[1],$TX[1] + test \$-128,$len + jz .Loop1 + sub $XX[0],$TX[1] + and \$`$MOD-1`,$TX[1] + jz .Loop${MOD}_is_hot + sub $TX[1],$len +.Loop${MOD}_warmup: + add $TX[0]#b,$YY#b + movl ($dat,$YY,4),$TY#d + movl $TX[0]#d,($dat,$YY,4) + movl $TY#d,($dat,$XX[0],4) + add $TY#b,$TX[0]#b + inc $XX[0]#b + movl ($dat,$TX[0],4),$TY#d + movl ($dat,$XX[0],4),$TX[0]#d + xorb ($in0),$TY#b + movb $TY#b,($out,$in0) + lea 1($in0),$in0 + dec $TX[1] + jnz .Loop${MOD}_warmup + + mov $YY,$TX[1] + xor $YY,$YY + mov $TX[1]#b,$YY#b + +.Loop${MOD}_is_hot: + mov $len,32(%rsp) # save original $len + shr \$6,$len # number of 64-byte blocks +___ + if ($D && !$md5) { # stitch in dummy MD5 + $md5=1; + $ctx="%r11"; + $inp="%r15"; + $code.=<<___; + mov %rsp,$ctx + mov $in0,$inp +___ + } +} +$code.=<<___; +#rc4# add $TX[0]#b,$YY#b +#rc4# lea ($dat,$XX[0],4),$XX[1] + shl \$6,$len + add $inp,$len # pointer to the end of input + mov $len,16(%rsp) + +#md5# mov $ctx,24(%rsp) # save pointer to MD5_CTX +#md5# mov 0*4($ctx),$V[0] # load current hash value from MD5_CTX +#md5# mov 1*4($ctx),$V[1] +#md5# mov 2*4($ctx),$V[2] +#md5# mov 3*4($ctx),$V[3] + jmp .Loop + +.align 16 +.Loop: +#md5# mov $V[0],0*4(%rsp) # put aside current hash value +#md5# mov $V[1],1*4(%rsp) +#md5# mov $V[2],2*4(%rsp) +#md5# mov $V[3],$tmp # forward reference +#md5# mov $V[3],3*4(%rsp) +___ + +sub R0 { + my ($i,$a,$b,$c,$d)=@_; + my @rot0=(7,12,17,22); + my $j=$i%16; + my $k=$i%$MOD; + my $xmm="%xmm".($j&1); + $code.=" movdqu ($in0),%xmm2\n" if ($rc4 && $j==15); + $code.=" add \$$MOD,$XX[0]#b\n" if ($rc4 && $j==15 && $k==$MOD-1); + $code.=" pxor $xmm,$xmm\n" if ($rc4 && $j<=1); + $code.=<<___; +#rc4# movl ($dat,$YY,4),$TY#d +#md5# xor $c,$tmp +#rc4# movl $TX[0]#d,($dat,$YY,4) +#md5# and $b,$tmp +#md5# add 4*`$j`($inp),$a +#rc4# add $TY#b,$TX[0]#b +#rc4# movl `4*(($k+1)%$MOD)`(`$k==$MOD-1?"$dat,$XX[0],4":"$XX[1]"`),$TX[1]#d +#md5# add \$$K[$i],$a +#md5# xor $d,$tmp +#rc4# movz $TX[0]#b,$TX[0]#d +#rc4# movl $TY#d,4*$k($XX[1]) +#md5# add $tmp,$a +#rc4# add $TX[1]#b,$YY#b +#md5# rol \$$rot0[$j%4],$a +#md5# mov `$j==15?"$b":"$c"`,$tmp # forward reference +#rc4# pinsrw \$`($j>>1)&7`,($dat,$TX[0],4),$xmm\n +#md5# add $b,$a +___ + $code.=<<___ if ($rc4 && $j==15 && $k==$MOD-1); + mov $YY,$XX[1] + xor $YY,$YY # keyword to partial register + mov $XX[1]#b,$YY#b + lea ($dat,$XX[0],4),$XX[1] +___ + $code.=<<___ if ($rc4 && $j==15); + psllq \$8,%xmm1 + pxor %xmm0,%xmm2 + pxor %xmm1,%xmm2 +___ +} +sub R1 { + my ($i,$a,$b,$c,$d)=@_; + my @rot1=(5,9,14,20); + my $j=$i%16; + my $k=$i%$MOD; + my $xmm="%xmm".($j&1); + $code.=" movdqu 16($in0),%xmm3\n" if ($rc4 && $j==15); + $code.=" add \$$MOD,$XX[0]#b\n" if ($rc4 && $j==15 && $k==$MOD-1); + $code.=" pxor $xmm,$xmm\n" if ($rc4 && $j<=1); + $code.=<<___; +#rc4# movl ($dat,$YY,4),$TY#d +#md5# xor $b,$tmp +#rc4# movl $TX[0]#d,($dat,$YY,4) +#md5# and $d,$tmp +#md5# add 4*`((1+5*$j)%16)`($inp),$a +#rc4# add $TY#b,$TX[0]#b +#rc4# movl `4*(($k+1)%$MOD)`(`$k==$MOD-1?"$dat,$XX[0],4":"$XX[1]"`),$TX[1]#d +#md5# add \$$K[$i],$a +#md5# xor $c,$tmp +#rc4# movz $TX[0]#b,$TX[0]#d +#rc4# movl $TY#d,4*$k($XX[1]) +#md5# add $tmp,$a +#rc4# add $TX[1]#b,$YY#b +#md5# rol \$$rot1[$j%4],$a +#md5# mov `$j==15?"$c":"$b"`,$tmp # forward reference +#rc4# pinsrw \$`($j>>1)&7`,($dat,$TX[0],4),$xmm\n +#md5# add $b,$a +___ + $code.=<<___ if ($rc4 && $j==15 && $k==$MOD-1); + mov $YY,$XX[1] + xor $YY,$YY # keyword to partial register + mov $XX[1]#b,$YY#b + lea ($dat,$XX[0],4),$XX[1] +___ + $code.=<<___ if ($rc4 && $j==15); + psllq \$8,%xmm1 + pxor %xmm0,%xmm3 + pxor %xmm1,%xmm3 +___ +} +sub R2 { + my ($i,$a,$b,$c,$d)=@_; + my @rot2=(4,11,16,23); + my $j=$i%16; + my $k=$i%$MOD; + my $xmm="%xmm".($j&1); + $code.=" movdqu 32($in0),%xmm4\n" if ($rc4 && $j==15); + $code.=" add \$$MOD,$XX[0]#b\n" if ($rc4 && $j==15 && $k==$MOD-1); + $code.=" pxor $xmm,$xmm\n" if ($rc4 && $j<=1); + $code.=<<___; +#rc4# movl ($dat,$YY,4),$TY#d +#md5# xor $c,$tmp +#rc4# movl $TX[0]#d,($dat,$YY,4) +#md5# xor $b,$tmp +#md5# add 4*`((5+3*$j)%16)`($inp),$a +#rc4# add $TY#b,$TX[0]#b +#rc4# movl `4*(($k+1)%$MOD)`(`$k==$MOD-1?"$dat,$XX[0],4":"$XX[1]"`),$TX[1]#d +#md5# add \$$K[$i],$a +#rc4# movz $TX[0]#b,$TX[0]#d +#md5# add $tmp,$a +#rc4# movl $TY#d,4*$k($XX[1]) +#rc4# add $TX[1]#b,$YY#b +#md5# rol \$$rot2[$j%4],$a +#md5# mov `$j==15?"\\\$-1":"$c"`,$tmp # forward reference +#rc4# pinsrw \$`($j>>1)&7`,($dat,$TX[0],4),$xmm\n +#md5# add $b,$a +___ + $code.=<<___ if ($rc4 && $j==15 && $k==$MOD-1); + mov $YY,$XX[1] + xor $YY,$YY # keyword to partial register + mov $XX[1]#b,$YY#b + lea ($dat,$XX[0],4),$XX[1] +___ + $code.=<<___ if ($rc4 && $j==15); + psllq \$8,%xmm1 + pxor %xmm0,%xmm4 + pxor %xmm1,%xmm4 +___ +} +sub R3 { + my ($i,$a,$b,$c,$d)=@_; + my @rot3=(6,10,15,21); + my $j=$i%16; + my $k=$i%$MOD; + my $xmm="%xmm".($j&1); + $code.=" movdqu 48($in0),%xmm5\n" if ($rc4 && $j==15); + $code.=" add \$$MOD,$XX[0]#b\n" if ($rc4 && $j==15 && $k==$MOD-1); + $code.=" pxor $xmm,$xmm\n" if ($rc4 && $j<=1); + $code.=<<___; +#rc4# movl ($dat,$YY,4),$TY#d +#md5# xor $d,$tmp +#rc4# movl $TX[0]#d,($dat,$YY,4) +#md5# or $b,$tmp +#md5# add 4*`((7*$j)%16)`($inp),$a +#rc4# add $TY#b,$TX[0]#b +#rc4# movl `4*(($k+1)%$MOD)`(`$k==$MOD-1?"$dat,$XX[0],4":"$XX[1]"`),$TX[1]#d +#md5# add \$$K[$i],$a +#rc4# movz $TX[0]#b,$TX[0]#d +#md5# xor $c,$tmp +#rc4# movl $TY#d,4*$k($XX[1]) +#md5# add $tmp,$a +#rc4# add $TX[1]#b,$YY#b +#md5# rol \$$rot3[$j%4],$a +#md5# mov \$-1,$tmp # forward reference +#rc4# pinsrw \$`($j>>1)&7`,($dat,$TX[0],4),$xmm\n +#md5# add $b,$a +___ + $code.=<<___ if ($rc4 && $j==15); + mov $XX[0],$XX[1] + xor $XX[0],$XX[0] # keyword to partial register + mov $XX[1]#b,$XX[0]#b + mov $YY,$XX[1] + xor $YY,$YY # keyword to partial register + mov $XX[1]#b,$YY#b + lea ($dat,$XX[0],4),$XX[1] + psllq \$8,%xmm1 + pxor %xmm0,%xmm5 + pxor %xmm1,%xmm5 +___ +} + +my $i=0; +for(;$i<16;$i++) { R0($i,@V); unshift(@V,pop(@V)); push(@TX,shift(@TX)); } +for(;$i<32;$i++) { R1($i,@V); unshift(@V,pop(@V)); push(@TX,shift(@TX)); } +for(;$i<48;$i++) { R2($i,@V); unshift(@V,pop(@V)); push(@TX,shift(@TX)); } +for(;$i<64;$i++) { R3($i,@V); unshift(@V,pop(@V)); push(@TX,shift(@TX)); } + +$code.=<<___; +#md5# add 0*4(%rsp),$V[0] # accumulate hash value +#md5# add 1*4(%rsp),$V[1] +#md5# add 2*4(%rsp),$V[2] +#md5# add 3*4(%rsp),$V[3] + +#rc4# movdqu %xmm2,($out,$in0) # write RC4 output +#rc4# movdqu %xmm3,16($out,$in0) +#rc4# movdqu %xmm4,32($out,$in0) +#rc4# movdqu %xmm5,48($out,$in0) +#md5# lea 64($inp),$inp +#rc4# lea 64($in0),$in0 + cmp 16(%rsp),$inp # are we done? + jb .Loop + +#md5# mov 24(%rsp),$len # restore pointer to MD5_CTX +#rc4# sub $TX[0]#b,$YY#b # correct $YY +#md5# mov $V[0],0*4($len) # write MD5_CTX +#md5# mov $V[1],1*4($len) +#md5# mov $V[2],2*4($len) +#md5# mov $V[3],3*4($len) +___ +$code.=<<___ if ($rc4 && (!$md5 || $D)); + mov 32(%rsp),$len # restore original $len + and \$63,$len # remaining bytes + jnz .Loop1 + jmp .Ldone + +.align 16 +.Loop1: + add $TX[0]#b,$YY#b + movl ($dat,$YY,4),$TY#d + movl $TX[0]#d,($dat,$YY,4) + movl $TY#d,($dat,$XX[0],4) + add $TY#b,$TX[0]#b + inc $XX[0]#b + movl ($dat,$TX[0],4),$TY#d + movl ($dat,$XX[0],4),$TX[0]#d + xorb ($in0),$TY#b + movb $TY#b,($out,$in0) + lea 1($in0),$in0 + dec $len + jnz .Loop1 + +.Ldone: +___ +$code.=<<___; +#rc4# sub \$1,$XX[0]#b +#rc4# movl $XX[0]#d,-8($dat) +#rc4# movl $YY#d,-4($dat) + + mov 40(%rsp),%r15 +.cfi_restore %r15 + mov 48(%rsp),%r14 +.cfi_restore %r14 + mov 56(%rsp),%r13 +.cfi_restore %r13 + mov 64(%rsp),%r12 +.cfi_restore %r12 + mov 72(%rsp),%rbp +.cfi_restore %rbp + mov 80(%rsp),%rbx +.cfi_restore %rbx + lea 88(%rsp),%rsp +.cfi_adjust_cfa_offset -88 +.Lepilogue: +.Labort: + ret +.cfi_endproc +.size $func,.-$func +___ + +if ($rc4 && $D) { # sole purpose of this section is to provide + # option to use the generated module as drop-in + # replacement for rc4-x86_64.pl for debugging + # and testing purposes... +my ($idx,$ido)=("%r8","%r9"); +my ($dat,$len,$inp)=("%rdi","%rsi","%rdx"); + +$code.=<<___; +.globl RC4_set_key +.type RC4_set_key,\@function,3 +.align 16 +RC4_set_key: + lea 8($dat),$dat + lea ($inp,$len),$inp + neg $len + mov $len,%rcx + xor %eax,%eax + xor $ido,$ido + xor %r10,%r10 + xor %r11,%r11 + jmp .Lw1stloop + +.align 16 +.Lw1stloop: + mov %eax,($dat,%rax,4) + add \$1,%al + jnc .Lw1stloop + + xor $ido,$ido + xor $idx,$idx +.align 16 +.Lw2ndloop: + mov ($dat,$ido,4),%r10d + add ($inp,$len,1),$idx#b + add %r10b,$idx#b + add \$1,$len + mov ($dat,$idx,4),%r11d + cmovz %rcx,$len + mov %r10d,($dat,$idx,4) + mov %r11d,($dat,$ido,4) + add \$1,$ido#b + jnc .Lw2ndloop + + xor %eax,%eax + mov %eax,-8($dat) + mov %eax,-4($dat) + ret +.size RC4_set_key,.-RC4_set_key + +.globl RC4_options +.type RC4_options,\@abi-omnipotent +.align 16 +RC4_options: + lea .Lopts(%rip),%rax + ret +.align 64 +.Lopts: +.asciz "rc4(64x,int)" +.align 64 +.size RC4_options,.-RC4_options +___ +} +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +my $rec="%rcx"; +my $frame="%rdx"; +my $context="%r8"; +my $disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type se_handler,\@abi-omnipotent +.align 16 +se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + lea .Lbody(%rip),%r10 + cmp %r10,%rbx # context->Rip<.Lbody + jb .Lin_prologue + + mov 152($context),%rax # pull context->Rsp + + lea .Lepilogue(%rip),%r10 + cmp %r10,%rbx # context->Rip>=.Lepilogue + jae .Lin_prologue + + mov 40(%rax),%r15 + mov 48(%rax),%r14 + mov 56(%rax),%r13 + mov 64(%rax),%r12 + mov 72(%rax),%rbp + mov 80(%rax),%rbx + lea 88(%rax),%rax + + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R12 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + +.Lin_prologue: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size se_handler,.-se_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_$func + .rva .LSEH_end_$func + .rva .LSEH_info_$func + +.section .xdata +.align 8 +.LSEH_info_$func: + .byte 9,0,0,0 + .rva se_handler +___ +} + +sub reg_part { +my ($reg,$conv)=@_; + if ($reg =~ /%r[0-9]+/) { $reg .= $conv; } + elsif ($conv eq "b") { $reg =~ s/%[er]([^x]+)x?/%$1l/; } + elsif ($conv eq "w") { $reg =~ s/%[er](.+)/%$1/; } + elsif ($conv eq "d") { $reg =~ s/%[er](.+)/%e$1/; } + return $reg; +} + +$code =~ s/(%[a-z0-9]+)#([bwd])/reg_part($1,$2)/gem; +$code =~ s/\`([^\`]*)\`/eval $1/gem; +$code =~ s/pinsrw\s+\$0,/movd /gm; + +$code =~ s/#md5#//gm if ($md5); +$code =~ s/#rc4#//gm if ($rc4); + +print $code; + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/asm/rc4-parisc.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/asm/rc4-parisc.pl new file mode 100644 index 000000000..4111f339d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/asm/rc4-parisc.pl @@ -0,0 +1,333 @@ +#! /usr/bin/env perl +# Copyright 2009-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# RC4 for PA-RISC. + +# June 2009. +# +# Performance is 33% better than gcc 3.2 generated code on PA-7100LC. +# For reference, [4x] unrolled loop is >40% faster than folded one. +# It's possible to unroll loop 8 times on PA-RISC 2.0, but improvement +# is believed to be not sufficient to justify the effort... +# +# Special thanks to polarhome.com for providing HP-UX account. + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + +$flavour = shift; +$output = shift; +open STDOUT,">$output"; + +if ($flavour =~ /64/) { + $LEVEL ="2.0W"; + $SIZE_T =8; + $FRAME_MARKER =80; + $SAVED_RP =16; + $PUSH ="std"; + $PUSHMA ="std,ma"; + $POP ="ldd"; + $POPMB ="ldd,mb"; +} else { + $LEVEL ="1.0"; + $SIZE_T =4; + $FRAME_MARKER =48; + $SAVED_RP =20; + $PUSH ="stw"; + $PUSHMA ="stwm"; + $POP ="ldw"; + $POPMB ="ldwm"; +} + +$FRAME=4*$SIZE_T+$FRAME_MARKER; # 4 saved regs + frame marker + # [+ argument transfer] +$SZ=1; # defaults to RC4_CHAR +if (open CONF,"<${dir}../../opensslconf.h") { + while() { + if (m/#\s*define\s+RC4_INT\s+(.*)/) { + $SZ = ($1=~/char$/) ? 1 : 4; + last; + } + } + close CONF; +} + +if ($SZ==1) { # RC4_CHAR + $LD="ldb"; + $LDX="ldbx"; + $MKX="addl"; + $ST="stb"; +} else { # RC4_INT (~5% faster than RC4_CHAR on PA-7100LC) + $LD="ldw"; + $LDX="ldwx,s"; + $MKX="sh2addl"; + $ST="stw"; +} + +$key="%r26"; +$len="%r25"; +$inp="%r24"; +$out="%r23"; + +@XX=("%r19","%r20"); +@TX=("%r21","%r22"); +$YY="%r28"; +$TY="%r29"; + +$acc="%r1"; +$ix="%r2"; +$iy="%r3"; +$dat0="%r4"; +$dat1="%r5"; +$rem="%r6"; +$mask="%r31"; + +sub unrolledloopbody { +for ($i=0;$i<4;$i++) { +$code.=<<___; + ldo 1($XX[0]),$XX[1] + `sprintf("$LDX %$TY(%$key),%$dat1") if ($i>0)` + and $mask,$XX[1],$XX[1] + $LDX $YY($key),$TY + $MKX $YY,$key,$ix + $LDX $XX[1]($key),$TX[1] + $MKX $XX[0],$key,$iy + $ST $TX[0],0($ix) + comclr,<> $XX[1],$YY,%r0 ; conditional + copy $TX[0],$TX[1] ; move + `sprintf("%sdep %$dat1,%d,8,%$acc",$i==1?"z":"",8*($i-1)+7) if ($i>0)` + $ST $TY,0($iy) + addl $TX[0],$TY,$TY + addl $TX[1],$YY,$YY + and $mask,$TY,$TY + and $mask,$YY,$YY +___ +push(@TX,shift(@TX)); push(@XX,shift(@XX)); # "rotate" registers +} } + +sub foldedloop { +my ($label,$count)=@_; +$code.=<<___; +$label + $MKX $YY,$key,$iy + $LDX $YY($key),$TY + $MKX $XX[0],$key,$ix + $ST $TX[0],0($iy) + ldo 1($XX[0]),$XX[0] + $ST $TY,0($ix) + addl $TX[0],$TY,$TY + ldbx $inp($out),$dat1 + and $mask,$TY,$TY + and $mask,$XX[0],$XX[0] + $LDX $TY($key),$acc + $LDX $XX[0]($key),$TX[0] + ldo 1($out),$out + xor $dat1,$acc,$acc + addl $TX[0],$YY,$YY + stb $acc,-1($out) + addib,<> -1,$count,$label ; $count is always small + and $mask,$YY,$YY +___ +} + +$code=<<___; + .LEVEL $LEVEL + .SPACE \$TEXT\$ + .SUBSPA \$CODE\$,QUAD=0,ALIGN=8,ACCESS=0x2C,CODE_ONLY + + .EXPORT RC4,ENTRY,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR +RC4 + .PROC + .CALLINFO FRAME=`$FRAME-4*$SIZE_T`,NO_CALLS,SAVE_RP,ENTRY_GR=6 + .ENTRY + $PUSH %r2,-$SAVED_RP(%sp) ; standard prologue + $PUSHMA %r3,$FRAME(%sp) + $PUSH %r4,`-$FRAME+1*$SIZE_T`(%sp) + $PUSH %r5,`-$FRAME+2*$SIZE_T`(%sp) + $PUSH %r6,`-$FRAME+3*$SIZE_T`(%sp) + + cmpib,*= 0,$len,L\$abort + sub $inp,$out,$inp ; distance between $inp and $out + + $LD `0*$SZ`($key),$XX[0] + $LD `1*$SZ`($key),$YY + ldo `2*$SZ`($key),$key + + ldi 0xff,$mask + ldi 3,$dat0 + + ldo 1($XX[0]),$XX[0] ; warm up loop + and $mask,$XX[0],$XX[0] + $LDX $XX[0]($key),$TX[0] + addl $TX[0],$YY,$YY + cmpib,*>>= 6,$len,L\$oop1 ; is $len large enough to bother? + and $mask,$YY,$YY + + and,<> $out,$dat0,$rem ; is $out aligned? + b L\$alignedout + subi 4,$rem,$rem + sub $len,$rem,$len +___ +&foldedloop("L\$alignout",$rem); # process till $out is aligned + +$code.=<<___; +L\$alignedout ; $len is at least 4 here + and,<> $inp,$dat0,$acc ; is $inp aligned? + b L\$oop4 + sub $inp,$acc,$rem ; align $inp + + sh3addl $acc,%r0,$acc + subi 32,$acc,$acc + mtctl $acc,%cr11 ; load %sar with vshd align factor + ldwx $rem($out),$dat0 + ldo 4($rem),$rem +L\$oop4misalignedinp +___ +&unrolledloopbody(); +$code.=<<___; + $LDX $TY($key),$ix + ldwx $rem($out),$dat1 + ldo -4($len),$len + or $ix,$acc,$acc ; last piece, no need to dep + vshd $dat0,$dat1,$iy ; align data + copy $dat1,$dat0 + xor $iy,$acc,$acc + stw $acc,0($out) + cmpib,*<< 3,$len,L\$oop4misalignedinp + ldo 4($out),$out + cmpib,*= 0,$len,L\$done + nop + b L\$oop1 + nop + + .ALIGN 8 +L\$oop4 +___ +&unrolledloopbody(); +$code.=<<___; + $LDX $TY($key),$ix + ldwx $inp($out),$dat0 + ldo -4($len),$len + or $ix,$acc,$acc ; last piece, no need to dep + xor $dat0,$acc,$acc + stw $acc,0($out) + cmpib,*<< 3,$len,L\$oop4 + ldo 4($out),$out + cmpib,*= 0,$len,L\$done + nop +___ +&foldedloop("L\$oop1",$len); +$code.=<<___; +L\$done + $POP `-$FRAME-$SAVED_RP`(%sp),%r2 + ldo -1($XX[0]),$XX[0] ; chill out loop + sub $YY,$TX[0],$YY + and $mask,$XX[0],$XX[0] + and $mask,$YY,$YY + $ST $XX[0],`-2*$SZ`($key) + $ST $YY,`-1*$SZ`($key) + $POP `-$FRAME+1*$SIZE_T`(%sp),%r4 + $POP `-$FRAME+2*$SIZE_T`(%sp),%r5 + $POP `-$FRAME+3*$SIZE_T`(%sp),%r6 +L\$abort + bv (%r2) + .EXIT + $POPMB -$FRAME(%sp),%r3 + .PROCEND +___ + +$code.=<<___; + + .EXPORT RC4_set_key,ENTRY,ARGW0=GR,ARGW1=GR,ARGW2=GR + .ALIGN 8 +RC4_set_key + .PROC + .CALLINFO NO_CALLS + .ENTRY + $ST %r0,`0*$SZ`($key) + $ST %r0,`1*$SZ`($key) + ldo `2*$SZ`($key),$key + copy %r0,@XX[0] +L\$1st + $ST @XX[0],0($key) + ldo 1(@XX[0]),@XX[0] + bb,>= @XX[0],`31-8`,L\$1st ; @XX[0]<256 + ldo $SZ($key),$key + + ldo `-256*$SZ`($key),$key ; rewind $key + addl $len,$inp,$inp ; $inp to point at the end + sub %r0,$len,%r23 ; inverse index + copy %r0,@XX[0] + copy %r0,@XX[1] + ldi 0xff,$mask + +L\$2nd + $LDX @XX[0]($key),@TX[0] + ldbx %r23($inp),@TX[1] + addi,nuv 1,%r23,%r23 ; increment and conditional + sub %r0,$len,%r23 ; inverse index + addl @TX[0],@XX[1],@XX[1] + addl @TX[1],@XX[1],@XX[1] + and $mask,@XX[1],@XX[1] + $MKX @XX[0],$key,$TY + $LDX @XX[1]($key),@TX[1] + $MKX @XX[1],$key,$YY + ldo 1(@XX[0]),@XX[0] + $ST @TX[0],0($YY) + bb,>= @XX[0],`31-8`,L\$2nd ; @XX[0]<256 + $ST @TX[1],0($TY) + + bv,n (%r2) + .EXIT + nop + .PROCEND + + .EXPORT RC4_options,ENTRY + .ALIGN 8 +RC4_options + .PROC + .CALLINFO NO_CALLS + .ENTRY + blr %r0,%r28 + ldi 3,%r1 +L\$pic + andcm %r28,%r1,%r28 + bv (%r2) + .EXIT + ldo L\$opts-L\$pic(%r28),%r28 + .PROCEND + .ALIGN 8 +L\$opts + .STRINGZ "rc4(4x,`$SZ==1?"char":"int"`)" + .STRINGZ "RC4 for PA-RISC, CRYPTOGAMS by " +___ + +if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler/) { + $gnuas = 1; +} + +foreach(split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/ge; + + s/(\.LEVEL\s+2\.0)W/$1w/ if ($gnuas && $SIZE_T==8); + s/\.SPACE\s+\$TEXT\$/.text/ if ($gnuas && $SIZE_T==8); + s/\.SUBSPA.*// if ($gnuas && $SIZE_T==8); + s/cmpib,\*/comib,/ if ($SIZE_T==4); + s/\bbv\b/bve/ if ($SIZE_T==8); + + print $_,"\n"; +} +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/asm/rc4-s390x.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/asm/rc4-s390x.pl new file mode 100644 index 000000000..469f110fa --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/asm/rc4-s390x.pl @@ -0,0 +1,241 @@ +#! /usr/bin/env perl +# Copyright 2009-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# February 2009 +# +# Performance is 2x of gcc 3.4.6 on z10. Coding "secret" is to +# "cluster" Address Generation Interlocks, so that one pipeline stall +# resolves several dependencies. + +# November 2010. +# +# Adapt for -m31 build. If kernel supports what's called "highgprs" +# feature on Linux [see /proc/cpuinfo], it's possible to use 64-bit +# instructions and achieve "64-bit" performance even in 31-bit legacy +# application context. The feature is not specific to any particular +# processor, as long as it's "z-CPU". Latter implies that the code +# remains z/Architecture specific. On z990 it was measured to perform +# 50% better than code generated by gcc 4.3. + +$flavour = shift; + +if ($flavour =~ /3[12]/) { + $SIZE_T=4; + $g=""; +} else { + $SIZE_T=8; + $g="g"; +} + +while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} +open STDOUT,">$output"; + +$rp="%r14"; +$sp="%r15"; +$code=<<___; +.text + +___ + +# void RC4(RC4_KEY *key,size_t len,const void *inp,void *out) +{ +$acc="%r0"; +$cnt="%r1"; +$key="%r2"; +$len="%r3"; +$inp="%r4"; +$out="%r5"; + +@XX=("%r6","%r7"); +@TX=("%r8","%r9"); +$YY="%r10"; +$TY="%r11"; + +$code.=<<___; +.globl RC4 +.type RC4,\@function +.align 64 +RC4: + stm${g} %r6,%r11,6*$SIZE_T($sp) +___ +$code.=<<___ if ($flavour =~ /3[12]/); + llgfr $len,$len +___ +$code.=<<___; + llgc $XX[0],0($key) + llgc $YY,1($key) + la $XX[0],1($XX[0]) + nill $XX[0],0xff + srlg $cnt,$len,3 + ltgr $cnt,$cnt + llgc $TX[0],2($XX[0],$key) + jz .Lshort + j .Loop8 + +.align 64 +.Loop8: +___ +for ($i=0;$i<8;$i++) { +$code.=<<___; + la $YY,0($YY,$TX[0]) # $i + nill $YY,255 + la $XX[1],1($XX[0]) + nill $XX[1],255 +___ +$code.=<<___ if ($i==1); + llgc $acc,2($TY,$key) +___ +$code.=<<___ if ($i>1); + sllg $acc,$acc,8 + ic $acc,2($TY,$key) +___ +$code.=<<___; + llgc $TY,2($YY,$key) + stc $TX[0],2($YY,$key) + llgc $TX[1],2($XX[1],$key) + stc $TY,2($XX[0],$key) + cr $XX[1],$YY + jne .Lcmov$i + la $TX[1],0($TX[0]) +.Lcmov$i: + la $TY,0($TY,$TX[0]) + nill $TY,255 +___ +push(@TX,shift(@TX)); push(@XX,shift(@XX)); # "rotate" registers +} + +$code.=<<___; + lg $TX[1],0($inp) + sllg $acc,$acc,8 + la $inp,8($inp) + ic $acc,2($TY,$key) + xgr $acc,$TX[1] + stg $acc,0($out) + la $out,8($out) + brctg $cnt,.Loop8 + +.Lshort: + lghi $acc,7 + ngr $len,$acc + jz .Lexit + j .Loop1 + +.align 16 +.Loop1: + la $YY,0($YY,$TX[0]) + nill $YY,255 + llgc $TY,2($YY,$key) + stc $TX[0],2($YY,$key) + stc $TY,2($XX[0],$key) + ar $TY,$TX[0] + ahi $XX[0],1 + nill $TY,255 + nill $XX[0],255 + llgc $acc,0($inp) + la $inp,1($inp) + llgc $TY,2($TY,$key) + llgc $TX[0],2($XX[0],$key) + xr $acc,$TY + stc $acc,0($out) + la $out,1($out) + brct $len,.Loop1 + +.Lexit: + ahi $XX[0],-1 + stc $XX[0],0($key) + stc $YY,1($key) + lm${g} %r6,%r11,6*$SIZE_T($sp) + br $rp +.size RC4,.-RC4 +.string "RC4 for s390x, CRYPTOGAMS by " + +___ +} + +# void RC4_set_key(RC4_KEY *key,unsigned int len,const void *inp) +{ +$cnt="%r0"; +$idx="%r1"; +$key="%r2"; +$len="%r3"; +$inp="%r4"; +$acc="%r5"; +$dat="%r6"; +$ikey="%r7"; +$iinp="%r8"; + +$code.=<<___; +.globl RC4_set_key +.type RC4_set_key,\@function +.align 64 +RC4_set_key: + stm${g} %r6,%r8,6*$SIZE_T($sp) + lhi $cnt,256 + la $idx,0(%r0) + sth $idx,0($key) +.align 4 +.L1stloop: + stc $idx,2($idx,$key) + la $idx,1($idx) + brct $cnt,.L1stloop + + lghi $ikey,-256 + lr $cnt,$len + la $iinp,0(%r0) + la $idx,0(%r0) +.align 16 +.L2ndloop: + llgc $acc,2+256($ikey,$key) + llgc $dat,0($iinp,$inp) + la $idx,0($idx,$acc) + la $ikey,1($ikey) + la $idx,0($idx,$dat) + nill $idx,255 + la $iinp,1($iinp) + tml $ikey,255 + llgc $dat,2($idx,$key) + stc $dat,2+256-1($ikey,$key) + stc $acc,2($idx,$key) + jz .Ldone + brct $cnt,.L2ndloop + lr $cnt,$len + la $iinp,0(%r0) + j .L2ndloop +.Ldone: + lm${g} %r6,%r8,6*$SIZE_T($sp) + br $rp +.size RC4_set_key,.-RC4_set_key + +___ +} + +# const char *RC4_options() +$code.=<<___; +.globl RC4_options +.type RC4_options,\@function +.align 16 +RC4_options: + larl %r2,.Loptions + br %r14 +.size RC4_options,.-RC4_options +.section .rodata +.Loptions: +.align 8 +.string "rc4(8x,char)" +___ + +print $code; +close STDOUT; # force flush diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/asm/rc4-x86_64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/asm/rc4-x86_64.pl new file mode 100755 index 000000000..1a9cc47d7 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/asm/rc4-x86_64.pl @@ -0,0 +1,696 @@ +#! /usr/bin/env perl +# Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# July 2004 +# +# 2.22x RC4 tune-up:-) It should be noted though that my hand [as in +# "hand-coded assembler"] doesn't stand for the whole improvement +# coefficient. It turned out that eliminating RC4_CHAR from config +# line results in ~40% improvement (yes, even for C implementation). +# Presumably it has everything to do with AMD cache architecture and +# RAW or whatever penalties. Once again! The module *requires* config +# line *without* RC4_CHAR! As for coding "secret," I bet on partial +# register arithmetics. For example instead of 'inc %r8; and $255,%r8' +# I simply 'inc %r8b'. Even though optimization manual discourages +# to operate on partial registers, it turned out to be the best bet. +# At least for AMD... How IA32E would perform remains to be seen... + +# November 2004 +# +# As was shown by Marc Bevand reordering of couple of load operations +# results in even higher performance gain of 3.3x:-) At least on +# Opteron... For reference, 1x in this case is RC4_CHAR C-code +# compiled with gcc 3.3.2, which performs at ~54MBps per 1GHz clock. +# Latter means that if you want to *estimate* what to expect from +# *your* Opteron, then multiply 54 by 3.3 and clock frequency in GHz. + +# November 2004 +# +# Intel P4 EM64T core was found to run the AMD64 code really slow... +# The only way to achieve comparable performance on P4 was to keep +# RC4_CHAR. Kind of ironic, huh? As it's apparently impossible to +# compose blended code, which would perform even within 30% marginal +# on either AMD and Intel platforms, I implement both cases. See +# rc4_skey.c for further details... + +# April 2005 +# +# P4 EM64T core appears to be "allergic" to 64-bit inc/dec. Replacing +# those with add/sub results in 50% performance improvement of folded +# loop... + +# May 2005 +# +# As was shown by Zou Nanhai loop unrolling can improve Intel EM64T +# performance by >30% [unlike P4 32-bit case that is]. But this is +# provided that loads are reordered even more aggressively! Both code +# paths, AMD64 and EM64T, reorder loads in essentially same manner +# as my IA-64 implementation. On Opteron this resulted in modest 5% +# improvement [I had to test it], while final Intel P4 performance +# achieves respectful 432MBps on 2.8GHz processor now. For reference. +# If executed on Xeon, current RC4_CHAR code-path is 2.7x faster than +# RC4_INT code-path. While if executed on Opteron, it's only 25% +# slower than the RC4_INT one [meaning that if CPU µ-arch detection +# is not implemented, then this final RC4_CHAR code-path should be +# preferred, as it provides better *all-round* performance]. + +# March 2007 +# +# Intel Core2 was observed to perform poorly on both code paths:-( It +# apparently suffers from some kind of partial register stall, which +# occurs in 64-bit mode only [as virtually identical 32-bit loop was +# observed to outperform 64-bit one by almost 50%]. Adding two movzb to +# cloop1 boosts its performance by 80%! This loop appears to be optimal +# fit for Core2 and therefore the code was modified to skip cloop8 on +# this CPU. + +# May 2010 +# +# Intel Westmere was observed to perform suboptimally. Adding yet +# another movzb to cloop1 improved performance by almost 50%! Core2 +# performance is improved too, but nominally... + +# May 2011 +# +# The only code path that was not modified is P4-specific one. Non-P4 +# Intel code path optimization is heavily based on submission by Maxim +# Perminov, Maxim Locktyukhin and Jim Guilford of Intel. I've used +# some of the ideas even in attempt to optimize the original RC4_INT +# code path... Current performance in cycles per processed byte (less +# is better) and improvement coefficients relative to previous +# version of this module are: +# +# Opteron 5.3/+0%(*) +# P4 6.5 +# Core2 6.2/+15%(**) +# Westmere 4.2/+60% +# Sandy Bridge 4.2/+120% +# Atom 9.3/+80% +# VIA Nano 6.4/+4% +# Ivy Bridge 4.1/+30% +# Bulldozer 4.5/+30%(*) +# +# (*) But corresponding loop has less instructions, which should have +# positive effect on upcoming Bulldozer, which has one less ALU. +# For reference, Intel code runs at 6.8 cpb rate on Opteron. +# (**) Note that Core2 result is ~15% lower than corresponding result +# for 32-bit code, meaning that it's possible to improve it, +# but more than likely at the cost of the others (see rc4-586.pl +# to get the idea)... + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +*STDOUT=*OUT; + +$dat="%rdi"; # arg1 +$len="%rsi"; # arg2 +$inp="%rdx"; # arg3 +$out="%rcx"; # arg4 + +{ +$code=<<___; +.text +.extern OPENSSL_ia32cap_P + +.globl RC4 +.type RC4,\@function,4 +.align 16 +RC4: or $len,$len + jne .Lentry + ret +.Lentry: +.cfi_startproc + push %rbx +.cfi_push %rbx + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 +.Lprologue: + mov $len,%r11 + mov $inp,%r12 + mov $out,%r13 +___ +my $len="%r11"; # reassign input arguments +my $inp="%r12"; +my $out="%r13"; + +my @XX=("%r10","%rsi"); +my @TX=("%rax","%rbx"); +my $YY="%rcx"; +my $TY="%rdx"; + +$code.=<<___; + xor $XX[0],$XX[0] + xor $YY,$YY + + lea 8($dat),$dat + mov -8($dat),$XX[0]#b + mov -4($dat),$YY#b + cmpl \$-1,256($dat) + je .LRC4_CHAR + mov OPENSSL_ia32cap_P(%rip),%r8d + xor $TX[1],$TX[1] + inc $XX[0]#b + sub $XX[0],$TX[1] + sub $inp,$out + movl ($dat,$XX[0],4),$TX[0]#d + test \$-16,$len + jz .Lloop1 + bt \$30,%r8d # Intel CPU? + jc .Lintel + and \$7,$TX[1] + lea 1($XX[0]),$XX[1] + jz .Loop8 + sub $TX[1],$len +.Loop8_warmup: + add $TX[0]#b,$YY#b + movl ($dat,$YY,4),$TY#d + movl $TX[0]#d,($dat,$YY,4) + movl $TY#d,($dat,$XX[0],4) + add $TY#b,$TX[0]#b + inc $XX[0]#b + movl ($dat,$TX[0],4),$TY#d + movl ($dat,$XX[0],4),$TX[0]#d + xorb ($inp),$TY#b + movb $TY#b,($out,$inp) + lea 1($inp),$inp + dec $TX[1] + jnz .Loop8_warmup + + lea 1($XX[0]),$XX[1] + jmp .Loop8 +.align 16 +.Loop8: +___ +for ($i=0;$i<8;$i++) { +$code.=<<___ if ($i==7); + add \$8,$XX[1]#b +___ +$code.=<<___; + add $TX[0]#b,$YY#b + movl ($dat,$YY,4),$TY#d + movl $TX[0]#d,($dat,$YY,4) + movl `4*($i==7?-1:$i)`($dat,$XX[1],4),$TX[1]#d + ror \$8,%r8 # ror is redundant when $i=0 + movl $TY#d,4*$i($dat,$XX[0],4) + add $TX[0]#b,$TY#b + movb ($dat,$TY,4),%r8b +___ +push(@TX,shift(@TX)); #push(@XX,shift(@XX)); # "rotate" registers +} +$code.=<<___; + add \$8,$XX[0]#b + ror \$8,%r8 + sub \$8,$len + + xor ($inp),%r8 + mov %r8,($out,$inp) + lea 8($inp),$inp + + test \$-8,$len + jnz .Loop8 + cmp \$0,$len + jne .Lloop1 + jmp .Lexit + +.align 16 +.Lintel: + test \$-32,$len + jz .Lloop1 + and \$15,$TX[1] + jz .Loop16_is_hot + sub $TX[1],$len +.Loop16_warmup: + add $TX[0]#b,$YY#b + movl ($dat,$YY,4),$TY#d + movl $TX[0]#d,($dat,$YY,4) + movl $TY#d,($dat,$XX[0],4) + add $TY#b,$TX[0]#b + inc $XX[0]#b + movl ($dat,$TX[0],4),$TY#d + movl ($dat,$XX[0],4),$TX[0]#d + xorb ($inp),$TY#b + movb $TY#b,($out,$inp) + lea 1($inp),$inp + dec $TX[1] + jnz .Loop16_warmup + + mov $YY,$TX[1] + xor $YY,$YY + mov $TX[1]#b,$YY#b + +.Loop16_is_hot: + lea ($dat,$XX[0],4),$XX[1] +___ +sub RC4_loop { + my $i=shift; + my $j=$i<0?0:$i; + my $xmm="%xmm".($j&1); + + $code.=" add \$16,$XX[0]#b\n" if ($i==15); + $code.=" movdqu ($inp),%xmm2\n" if ($i==15); + $code.=" add $TX[0]#b,$YY#b\n" if ($i<=0); + $code.=" movl ($dat,$YY,4),$TY#d\n"; + $code.=" pxor %xmm0,%xmm2\n" if ($i==0); + $code.=" psllq \$8,%xmm1\n" if ($i==0); + $code.=" pxor $xmm,$xmm\n" if ($i<=1); + $code.=" movl $TX[0]#d,($dat,$YY,4)\n"; + $code.=" add $TY#b,$TX[0]#b\n"; + $code.=" movl `4*($j+1)`($XX[1]),$TX[1]#d\n" if ($i<15); + $code.=" movz $TX[0]#b,$TX[0]#d\n"; + $code.=" movl $TY#d,4*$j($XX[1])\n"; + $code.=" pxor %xmm1,%xmm2\n" if ($i==0); + $code.=" lea ($dat,$XX[0],4),$XX[1]\n" if ($i==15); + $code.=" add $TX[1]#b,$YY#b\n" if ($i<15); + $code.=" pinsrw \$`($j>>1)&7`,($dat,$TX[0],4),$xmm\n"; + $code.=" movdqu %xmm2,($out,$inp)\n" if ($i==0); + $code.=" lea 16($inp),$inp\n" if ($i==0); + $code.=" movl ($XX[1]),$TX[1]#d\n" if ($i==15); +} + RC4_loop(-1); +$code.=<<___; + jmp .Loop16_enter +.align 16 +.Loop16: +___ + +for ($i=0;$i<16;$i++) { + $code.=".Loop16_enter:\n" if ($i==1); + RC4_loop($i); + push(@TX,shift(@TX)); # "rotate" registers +} +$code.=<<___; + mov $YY,$TX[1] + xor $YY,$YY # keyword to partial register + sub \$16,$len + mov $TX[1]#b,$YY#b + test \$-16,$len + jnz .Loop16 + + psllq \$8,%xmm1 + pxor %xmm0,%xmm2 + pxor %xmm1,%xmm2 + movdqu %xmm2,($out,$inp) + lea 16($inp),$inp + + cmp \$0,$len + jne .Lloop1 + jmp .Lexit + +.align 16 +.Lloop1: + add $TX[0]#b,$YY#b + movl ($dat,$YY,4),$TY#d + movl $TX[0]#d,($dat,$YY,4) + movl $TY#d,($dat,$XX[0],4) + add $TY#b,$TX[0]#b + inc $XX[0]#b + movl ($dat,$TX[0],4),$TY#d + movl ($dat,$XX[0],4),$TX[0]#d + xorb ($inp),$TY#b + movb $TY#b,($out,$inp) + lea 1($inp),$inp + dec $len + jnz .Lloop1 + jmp .Lexit + +.align 16 +.LRC4_CHAR: + add \$1,$XX[0]#b + movzb ($dat,$XX[0]),$TX[0]#d + test \$-8,$len + jz .Lcloop1 + jmp .Lcloop8 +.align 16 +.Lcloop8: + mov ($inp),%r8d + mov 4($inp),%r9d +___ +# unroll 2x4-wise, because 64-bit rotates kill Intel P4... +for ($i=0;$i<4;$i++) { +$code.=<<___; + add $TX[0]#b,$YY#b + lea 1($XX[0]),$XX[1] + movzb ($dat,$YY),$TY#d + movzb $XX[1]#b,$XX[1]#d + movzb ($dat,$XX[1]),$TX[1]#d + movb $TX[0]#b,($dat,$YY) + cmp $XX[1],$YY + movb $TY#b,($dat,$XX[0]) + jne .Lcmov$i # Intel cmov is sloooow... + mov $TX[0],$TX[1] +.Lcmov$i: + add $TX[0]#b,$TY#b + xor ($dat,$TY),%r8b + ror \$8,%r8d +___ +push(@TX,shift(@TX)); push(@XX,shift(@XX)); # "rotate" registers +} +for ($i=4;$i<8;$i++) { +$code.=<<___; + add $TX[0]#b,$YY#b + lea 1($XX[0]),$XX[1] + movzb ($dat,$YY),$TY#d + movzb $XX[1]#b,$XX[1]#d + movzb ($dat,$XX[1]),$TX[1]#d + movb $TX[0]#b,($dat,$YY) + cmp $XX[1],$YY + movb $TY#b,($dat,$XX[0]) + jne .Lcmov$i # Intel cmov is sloooow... + mov $TX[0],$TX[1] +.Lcmov$i: + add $TX[0]#b,$TY#b + xor ($dat,$TY),%r9b + ror \$8,%r9d +___ +push(@TX,shift(@TX)); push(@XX,shift(@XX)); # "rotate" registers +} +$code.=<<___; + lea -8($len),$len + mov %r8d,($out) + lea 8($inp),$inp + mov %r9d,4($out) + lea 8($out),$out + + test \$-8,$len + jnz .Lcloop8 + cmp \$0,$len + jne .Lcloop1 + jmp .Lexit +___ +$code.=<<___; +.align 16 +.Lcloop1: + add $TX[0]#b,$YY#b + movzb $YY#b,$YY#d + movzb ($dat,$YY),$TY#d + movb $TX[0]#b,($dat,$YY) + movb $TY#b,($dat,$XX[0]) + add $TX[0]#b,$TY#b + add \$1,$XX[0]#b + movzb $TY#b,$TY#d + movzb $XX[0]#b,$XX[0]#d + movzb ($dat,$TY),$TY#d + movzb ($dat,$XX[0]),$TX[0]#d + xorb ($inp),$TY#b + lea 1($inp),$inp + movb $TY#b,($out) + lea 1($out),$out + sub \$1,$len + jnz .Lcloop1 + jmp .Lexit + +.align 16 +.Lexit: + sub \$1,$XX[0]#b + movl $XX[0]#d,-8($dat) + movl $YY#d,-4($dat) + + mov (%rsp),%r13 +.cfi_restore %r13 + mov 8(%rsp),%r12 +.cfi_restore %r12 + mov 16(%rsp),%rbx +.cfi_restore %rbx + add \$24,%rsp +.cfi_adjust_cfa_offset -24 +.Lepilogue: + ret +.cfi_endproc +.size RC4,.-RC4 +___ +} + +$idx="%r8"; +$ido="%r9"; + +$code.=<<___; +.globl RC4_set_key +.type RC4_set_key,\@function,3 +.align 16 +RC4_set_key: + lea 8($dat),$dat + lea ($inp,$len),$inp + neg $len + mov $len,%rcx + xor %eax,%eax + xor $ido,$ido + xor %r10,%r10 + xor %r11,%r11 + + mov OPENSSL_ia32cap_P(%rip),$idx#d + bt \$20,$idx#d # RC4_CHAR? + jc .Lc1stloop + jmp .Lw1stloop + +.align 16 +.Lw1stloop: + mov %eax,($dat,%rax,4) + add \$1,%al + jnc .Lw1stloop + + xor $ido,$ido + xor $idx,$idx +.align 16 +.Lw2ndloop: + mov ($dat,$ido,4),%r10d + add ($inp,$len,1),$idx#b + add %r10b,$idx#b + add \$1,$len + mov ($dat,$idx,4),%r11d + cmovz %rcx,$len + mov %r10d,($dat,$idx,4) + mov %r11d,($dat,$ido,4) + add \$1,$ido#b + jnc .Lw2ndloop + jmp .Lexit_key + +.align 16 +.Lc1stloop: + mov %al,($dat,%rax) + add \$1,%al + jnc .Lc1stloop + + xor $ido,$ido + xor $idx,$idx +.align 16 +.Lc2ndloop: + mov ($dat,$ido),%r10b + add ($inp,$len),$idx#b + add %r10b,$idx#b + add \$1,$len + mov ($dat,$idx),%r11b + jnz .Lcnowrap + mov %rcx,$len +.Lcnowrap: + mov %r10b,($dat,$idx) + mov %r11b,($dat,$ido) + add \$1,$ido#b + jnc .Lc2ndloop + movl \$-1,256($dat) + +.align 16 +.Lexit_key: + xor %eax,%eax + mov %eax,-8($dat) + mov %eax,-4($dat) + ret +.size RC4_set_key,.-RC4_set_key + +.globl RC4_options +.type RC4_options,\@abi-omnipotent +.align 16 +RC4_options: + lea .Lopts(%rip),%rax + mov OPENSSL_ia32cap_P(%rip),%edx + bt \$20,%edx + jc .L8xchar + bt \$30,%edx + jnc .Ldone + add \$25,%rax + ret +.L8xchar: + add \$12,%rax +.Ldone: + ret +.align 64 +.Lopts: +.asciz "rc4(8x,int)" +.asciz "rc4(8x,char)" +.asciz "rc4(16x,int)" +.asciz "RC4 for x86_64, CRYPTOGAMS by " +.align 64 +.size RC4_options,.-RC4_options +___ + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type stream_se_handler,\@abi-omnipotent +.align 16 +stream_se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + lea .Lprologue(%rip),%r10 + cmp %r10,%rbx # context->RipRsp + + lea .Lepilogue(%rip),%r10 + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lin_prologue + + lea 24(%rax),%rax + + mov -8(%rax),%rbx + mov -16(%rax),%r12 + mov -24(%rax),%r13 + mov %rbx,144($context) # restore context->Rbx + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + +.Lin_prologue: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + jmp .Lcommon_seh_exit +.size stream_se_handler,.-stream_se_handler + +.type key_se_handler,\@abi-omnipotent +.align 16 +key_se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 152($context),%rax # pull context->Rsp + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + +.Lcommon_seh_exit: + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size key_se_handler,.-key_se_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_RC4 + .rva .LSEH_end_RC4 + .rva .LSEH_info_RC4 + + .rva .LSEH_begin_RC4_set_key + .rva .LSEH_end_RC4_set_key + .rva .LSEH_info_RC4_set_key + +.section .xdata +.align 8 +.LSEH_info_RC4: + .byte 9,0,0,0 + .rva stream_se_handler +.LSEH_info_RC4_set_key: + .byte 9,0,0,0 + .rva key_se_handler +___ +} + +sub reg_part { +my ($reg,$conv)=@_; + if ($reg =~ /%r[0-9]+/) { $reg .= $conv; } + elsif ($conv eq "b") { $reg =~ s/%[er]([^x]+)x?/%$1l/; } + elsif ($conv eq "w") { $reg =~ s/%[er](.+)/%$1/; } + elsif ($conv eq "d") { $reg =~ s/%[er](.+)/%e$1/; } + return $reg; +} + +$code =~ s/(%[a-z0-9]+)#([bwd])/reg_part($1,$2)/gem; +$code =~ s/\`([^\`]*)\`/eval $1/gem; + +print $code; + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/build.info new file mode 100644 index 000000000..46ee66b61 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/build.info @@ -0,0 +1,18 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + {- $target{rc4_asm_src} -} + +GENERATE[rc4-586.s]=asm/rc4-586.pl \ + $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) +DEPEND[rc4-586.s]=../perlasm/x86asm.pl + +GENERATE[rc4-x86_64.s]=asm/rc4-x86_64.pl $(PERLASM_SCHEME) +GENERATE[rc4-md5-x86_64.s]=asm/rc4-md5-x86_64.pl $(PERLASM_SCHEME) + +GENERATE[rc4-parisc.s]=asm/rc4-parisc.pl $(PERLASM_SCHEME) + +BEGINRAW[Makefile] +# GNU make "catch all" +{- $builddir -}/rc4-%.s: {- $sourcedir -}/asm/rc4-%.pl + CC="$(CC)" $(PERL) $< $(PERLASM_SCHEME) $@ +ENDRAW[Makefile] diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/rc4_enc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/rc4_enc.c new file mode 100644 index 000000000..638a75bb0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/rc4_enc.c @@ -0,0 +1,85 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "rc4_locl.h" + +/*- + * RC4 as implemented from a posting from + * Newsgroups: sci.crypt + * Subject: RC4 Algorithm revealed. + * Message-ID: + * Date: Wed, 14 Sep 1994 06:35:31 GMT + */ + +void RC4(RC4_KEY *key, size_t len, const unsigned char *indata, + unsigned char *outdata) +{ + register RC4_INT *d; + register RC4_INT x, y, tx, ty; + size_t i; + + x = key->x; + y = key->y; + d = key->data; + +#define LOOP(in,out) \ + x=((x+1)&0xff); \ + tx=d[x]; \ + y=(tx+y)&0xff; \ + d[x]=ty=d[y]; \ + d[y]=tx; \ + (out) = d[(tx+ty)&0xff]^ (in); + + i = len >> 3; + if (i) { + for (;;) { + LOOP(indata[0], outdata[0]); + LOOP(indata[1], outdata[1]); + LOOP(indata[2], outdata[2]); + LOOP(indata[3], outdata[3]); + LOOP(indata[4], outdata[4]); + LOOP(indata[5], outdata[5]); + LOOP(indata[6], outdata[6]); + LOOP(indata[7], outdata[7]); + indata += 8; + outdata += 8; + if (--i == 0) + break; + } + } + i = len & 0x07; + if (i) { + for (;;) { + LOOP(indata[0], outdata[0]); + if (--i == 0) + break; + LOOP(indata[1], outdata[1]); + if (--i == 0) + break; + LOOP(indata[2], outdata[2]); + if (--i == 0) + break; + LOOP(indata[3], outdata[3]); + if (--i == 0) + break; + LOOP(indata[4], outdata[4]); + if (--i == 0) + break; + LOOP(indata[5], outdata[5]); + if (--i == 0) + break; + LOOP(indata[6], outdata[6]); + if (--i == 0) + break; + } + } + key->x = x; + key->y = y; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/rc4_locl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/rc4_locl.h new file mode 100644 index 000000000..4380addbc --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/rc4_locl.h @@ -0,0 +1,16 @@ +/* + * Copyright 1998-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_RC4_LOCL_H +# define HEADER_RC4_LOCL_H + +# include +# include "internal/cryptlib.h" + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/rc4_skey.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/rc4_skey.c new file mode 100644 index 000000000..e9007331e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rc4/rc4_skey.c @@ -0,0 +1,57 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "rc4_locl.h" +#include + +const char *RC4_options(void) +{ + if (sizeof(RC4_INT) == 1) + return "rc4(char)"; + else + return "rc4(int)"; +} + +/*- + * RC4 as implemented from a posting from + * Newsgroups: sci.crypt + * Subject: RC4 Algorithm revealed. + * Message-ID: + * Date: Wed, 14 Sep 1994 06:35:31 GMT + */ + +void RC4_set_key(RC4_KEY *key, int len, const unsigned char *data) +{ + register RC4_INT tmp; + register int id1, id2; + register RC4_INT *d; + unsigned int i; + + d = &(key->data[0]); + key->x = 0; + key->y = 0; + id1 = id2 = 0; + +#define SK_LOOP(d,n) { \ + tmp=d[(n)]; \ + id2 = (data[id1] + tmp + id2) & 0xff; \ + if (++id1 == len) id1=0; \ + d[(n)]=d[id2]; \ + d[id2]=tmp; } + + for (i = 0; i < 256; i++) + d[i] = i; + for (i = 0; i < 256; i += 4) { + SK_LOOP(d, i + 0); + SK_LOOP(d, i + 1); + SK_LOOP(d, i + 2); + SK_LOOP(d, i + 3); + } +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rc5/asm/rc5-586.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/rc5/asm/rc5-586.pl new file mode 100644 index 000000000..e58a98bc8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rc5/asm/rc5-586.pl @@ -0,0 +1,122 @@ +#! /usr/bin/env perl +# Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; +require "cbc.pl"; + +$output = pop; +open STDOUT,">$output"; + +&asm_init($ARGV[0]); + +$RC5_MAX_ROUNDS=16; +$RC5_32_OFF=($RC5_MAX_ROUNDS+2)*4; +$A="edi"; +$B="esi"; +$S="ebp"; +$tmp1="eax"; +$r="ebx"; +$tmpc="ecx"; +$tmp4="edx"; + +&RC5_32_encrypt("RC5_32_encrypt",1); +&RC5_32_encrypt("RC5_32_decrypt",0); +&cbc("RC5_32_cbc_encrypt","RC5_32_encrypt","RC5_32_decrypt",0,4,5,3,-1,-1); +&asm_finish(); + +close STDOUT; + +sub RC5_32_encrypt + { + local($name,$enc)=@_; + + &function_begin_B($name,""); + + &comment(""); + + &push("ebp"); + &push("esi"); + &push("edi"); + &mov($tmp4,&wparam(0)); + &mov($S,&wparam(1)); + + &comment("Load the 2 words"); + &mov($A,&DWP(0,$tmp4,"",0)); + &mov($B,&DWP(4,$tmp4,"",0)); + + &push($r); + &mov($r, &DWP(0,$S,"",0)); + + # encrypting part + + if ($enc) + { + &add($A, &DWP(4+0,$S,"",0)); + &add($B, &DWP(4+4,$S,"",0)); + + for ($i=0; $i<$RC5_MAX_ROUNDS; $i++) + { + &xor($A, $B); + &mov($tmp1, &DWP(12+$i*8,$S,"",0)); + &mov($tmpc, $B); + &rotl($A, &LB("ecx")); + &add($A, $tmp1); + + &xor($B, $A); + &mov($tmp1, &DWP(16+$i*8,$S,"",0)); + &mov($tmpc, $A); + &rotl($B, &LB("ecx")); + &add($B, $tmp1); + if (($i == 7) || ($i == 11)) + { + &cmp($r, $i+1); + &je(&label("rc5_exit")); + } + } + } + else + { + &cmp($r, 12); + &je(&label("rc5_dec_12")); + &cmp($r, 8); + &je(&label("rc5_dec_8")); + for ($i=$RC5_MAX_ROUNDS; $i > 0; $i--) + { + &set_label("rc5_dec_$i") if ($i == 12) || ($i == 8); + &mov($tmp1, &DWP($i*8+8,$S,"",0)); + &sub($B, $tmp1); + &mov($tmpc, $A); + &rotr($B, &LB("ecx")); + &xor($B, $A); + + &mov($tmp1, &DWP($i*8+4,$S,"",0)); + &sub($A, $tmp1); + &mov($tmpc, $B); + &rotr($A, &LB("ecx")); + &xor($A, $B); + } + &sub($B, &DWP(4+4,$S,"",0)); + &sub($A, &DWP(4+0,$S,"",0)); + } + + &set_label("rc5_exit"); + &mov(&DWP(0,$tmp4,"",0),$A); + &mov(&DWP(4,$tmp4,"",0),$B); + + &pop("ebx"); + &pop("edi"); + &pop("esi"); + &pop("ebp"); + &ret(); + &function_end_B($name); + } + + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rc5/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/rc5/build.info new file mode 100644 index 000000000..928a62cd8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rc5/build.info @@ -0,0 +1,7 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + rc5_skey.c rc5_ecb.c {- $target{rc5_asm_src} -} rc5cfb64.c rc5ofb64.c + +GENERATE[rc5-586.s]=asm/rc5-586.pl \ + $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) +DEPEND[rc5-586.s]=../perlasm/x86asm.pl ../perlasm/cbc.pl diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rc5/rc5_ecb.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rc5/rc5_ecb.c new file mode 100644 index 000000000..c32f38e47 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rc5/rc5_ecb.c @@ -0,0 +1,32 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "rc5_locl.h" +#include + +void RC5_32_ecb_encrypt(const unsigned char *in, unsigned char *out, + RC5_32_KEY *ks, int encrypt) +{ + unsigned long l, d[2]; + + c2l(in, l); + d[0] = l; + c2l(in, l); + d[1] = l; + if (encrypt) + RC5_32_encrypt(d, ks); + else + RC5_32_decrypt(d, ks); + l = d[0]; + l2c(l, out); + l = d[1]; + l2c(l, out); + l = d[0] = d[1] = 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rc5/rc5_enc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rc5/rc5_enc.c new file mode 100644 index 000000000..58631dee2 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rc5/rc5_enc.c @@ -0,0 +1,160 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "rc5_locl.h" + +void RC5_32_cbc_encrypt(const unsigned char *in, unsigned char *out, + long length, RC5_32_KEY *ks, unsigned char *iv, + int encrypt) +{ + register unsigned long tin0, tin1; + register unsigned long tout0, tout1, xor0, xor1; + register long l = length; + unsigned long tin[2]; + + if (encrypt) { + c2l(iv, tout0); + c2l(iv, tout1); + iv -= 8; + for (l -= 8; l >= 0; l -= 8) { + c2l(in, tin0); + c2l(in, tin1); + tin0 ^= tout0; + tin1 ^= tout1; + tin[0] = tin0; + tin[1] = tin1; + RC5_32_encrypt(tin, ks); + tout0 = tin[0]; + l2c(tout0, out); + tout1 = tin[1]; + l2c(tout1, out); + } + if (l != -8) { + c2ln(in, tin0, tin1, l + 8); + tin0 ^= tout0; + tin1 ^= tout1; + tin[0] = tin0; + tin[1] = tin1; + RC5_32_encrypt(tin, ks); + tout0 = tin[0]; + l2c(tout0, out); + tout1 = tin[1]; + l2c(tout1, out); + } + l2c(tout0, iv); + l2c(tout1, iv); + } else { + c2l(iv, xor0); + c2l(iv, xor1); + iv -= 8; + for (l -= 8; l >= 0; l -= 8) { + c2l(in, tin0); + tin[0] = tin0; + c2l(in, tin1); + tin[1] = tin1; + RC5_32_decrypt(tin, ks); + tout0 = tin[0] ^ xor0; + tout1 = tin[1] ^ xor1; + l2c(tout0, out); + l2c(tout1, out); + xor0 = tin0; + xor1 = tin1; + } + if (l != -8) { + c2l(in, tin0); + tin[0] = tin0; + c2l(in, tin1); + tin[1] = tin1; + RC5_32_decrypt(tin, ks); + tout0 = tin[0] ^ xor0; + tout1 = tin[1] ^ xor1; + l2cn(tout0, tout1, out, l + 8); + xor0 = tin0; + xor1 = tin1; + } + l2c(xor0, iv); + l2c(xor1, iv); + } + tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0; + tin[0] = tin[1] = 0; +} + +void RC5_32_encrypt(unsigned long *d, RC5_32_KEY *key) +{ + RC5_32_INT a, b, *s; + + s = key->data; + + a = d[0] + s[0]; + b = d[1] + s[1]; + E_RC5_32(a, b, s, 2); + E_RC5_32(a, b, s, 4); + E_RC5_32(a, b, s, 6); + E_RC5_32(a, b, s, 8); + E_RC5_32(a, b, s, 10); + E_RC5_32(a, b, s, 12); + E_RC5_32(a, b, s, 14); + E_RC5_32(a, b, s, 16); + if (key->rounds == 12) { + E_RC5_32(a, b, s, 18); + E_RC5_32(a, b, s, 20); + E_RC5_32(a, b, s, 22); + E_RC5_32(a, b, s, 24); + } else if (key->rounds == 16) { + /* Do a full expansion to avoid a jump */ + E_RC5_32(a, b, s, 18); + E_RC5_32(a, b, s, 20); + E_RC5_32(a, b, s, 22); + E_RC5_32(a, b, s, 24); + E_RC5_32(a, b, s, 26); + E_RC5_32(a, b, s, 28); + E_RC5_32(a, b, s, 30); + E_RC5_32(a, b, s, 32); + } + d[0] = a; + d[1] = b; +} + +void RC5_32_decrypt(unsigned long *d, RC5_32_KEY *key) +{ + RC5_32_INT a, b, *s; + + s = key->data; + + a = d[0]; + b = d[1]; + if (key->rounds == 16) { + D_RC5_32(a, b, s, 32); + D_RC5_32(a, b, s, 30); + D_RC5_32(a, b, s, 28); + D_RC5_32(a, b, s, 26); + /* Do a full expansion to avoid a jump */ + D_RC5_32(a, b, s, 24); + D_RC5_32(a, b, s, 22); + D_RC5_32(a, b, s, 20); + D_RC5_32(a, b, s, 18); + } else if (key->rounds == 12) { + D_RC5_32(a, b, s, 24); + D_RC5_32(a, b, s, 22); + D_RC5_32(a, b, s, 20); + D_RC5_32(a, b, s, 18); + } + D_RC5_32(a, b, s, 16); + D_RC5_32(a, b, s, 14); + D_RC5_32(a, b, s, 12); + D_RC5_32(a, b, s, 10); + D_RC5_32(a, b, s, 8); + D_RC5_32(a, b, s, 6); + D_RC5_32(a, b, s, 4); + D_RC5_32(a, b, s, 2); + d[0] = a - s[0]; + d[1] = b - s[1]; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rc5/rc5_locl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/rc5/rc5_locl.h new file mode 100644 index 000000000..41130fe33 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rc5/rc5_locl.h @@ -0,0 +1,186 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#undef c2l +#define c2l(c,l) (l =((unsigned long)(*((c)++))) , \ + l|=((unsigned long)(*((c)++)))<< 8L, \ + l|=((unsigned long)(*((c)++)))<<16L, \ + l|=((unsigned long)(*((c)++)))<<24L) + +/* NOTE - c is not incremented as per c2l */ +#undef c2ln +#define c2ln(c,l1,l2,n) { \ + c+=n; \ + l1=l2=0; \ + switch (n) { \ + case 8: l2 =((unsigned long)(*(--(c))))<<24L; \ + /* fall thru */ \ + case 7: l2|=((unsigned long)(*(--(c))))<<16L; \ + /* fall thru */ \ + case 6: l2|=((unsigned long)(*(--(c))))<< 8L; \ + /* fall thru */ \ + case 5: l2|=((unsigned long)(*(--(c)))); \ + /* fall thru */ \ + case 4: l1 =((unsigned long)(*(--(c))))<<24L; \ + /* fall thru */ \ + case 3: l1|=((unsigned long)(*(--(c))))<<16L; \ + /* fall thru */ \ + case 2: l1|=((unsigned long)(*(--(c))))<< 8L; \ + /* fall thru */ \ + case 1: l1|=((unsigned long)(*(--(c)))); \ + } \ + } + +#undef l2c +#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24L)&0xff)) + +/* NOTE - c is not incremented as per l2c */ +#undef l2cn +#define l2cn(l1,l2,c,n) { \ + c+=n; \ + switch (n) { \ + case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \ + /* fall thru */ \ + case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \ + /* fall thru */ \ + case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \ + /* fall thru */ \ + case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ + /* fall thru */ \ + case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \ + /* fall thru */ \ + case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \ + /* fall thru */ \ + case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \ + /* fall thru */ \ + case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ + } \ + } + +/* NOTE - c is not incremented as per n2l */ +#define n2ln(c,l1,l2,n) { \ + c+=n; \ + l1=l2=0; \ + switch (n) { \ + case 8: l2 =((unsigned long)(*(--(c)))) ; \ + /* fall thru */ \ + case 7: l2|=((unsigned long)(*(--(c))))<< 8; \ + /* fall thru */ \ + case 6: l2|=((unsigned long)(*(--(c))))<<16; \ + /* fall thru */ \ + case 5: l2|=((unsigned long)(*(--(c))))<<24; \ + /* fall thru */ \ + case 4: l1 =((unsigned long)(*(--(c)))) ; \ + /* fall thru */ \ + case 3: l1|=((unsigned long)(*(--(c))))<< 8; \ + /* fall thru */ \ + case 2: l1|=((unsigned long)(*(--(c))))<<16; \ + /* fall thru */ \ + case 1: l1|=((unsigned long)(*(--(c))))<<24; \ + } \ + } + +/* NOTE - c is not incremented as per l2n */ +#define l2nn(l1,l2,c,n) { \ + c+=n; \ + switch (n) { \ + case 8: *(--(c))=(unsigned char)(((l2) )&0xff); \ + /* fall thru */ \ + case 7: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \ + /* fall thru */ \ + case 6: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \ + /* fall thru */ \ + case 5: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \ + /* fall thru */ \ + case 4: *(--(c))=(unsigned char)(((l1) )&0xff); \ + /* fall thru */ \ + case 3: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \ + /* fall thru */ \ + case 2: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \ + /* fall thru */ \ + case 1: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \ + } \ + } + +#undef n2l +#define n2l(c,l) (l =((unsigned long)(*((c)++)))<<24L, \ + l|=((unsigned long)(*((c)++)))<<16L, \ + l|=((unsigned long)(*((c)++)))<< 8L, \ + l|=((unsigned long)(*((c)++)))) + +#undef l2n +#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +#if (defined(OPENSSL_SYS_WIN32) && defined(_MSC_VER)) +# define ROTATE_l32(a,n) _lrotl(a,n) +# define ROTATE_r32(a,n) _lrotr(a,n) +#elif defined(__ICC) +# define ROTATE_l32(a,n) _rotl(a,n) +# define ROTATE_r32(a,n) _rotr(a,n) +#elif defined(__GNUC__) && __GNUC__>=2 && !defined(__STRICT_ANSI__) && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) && !defined(PEDANTIC) +# if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__) +# define ROTATE_l32(a,n) ({ register unsigned int ret; \ + asm ("roll %%cl,%0" \ + : "=r"(ret) \ + : "c"(n),"0"((unsigned int)(a)) \ + : "cc"); \ + ret; \ + }) +# define ROTATE_r32(a,n) ({ register unsigned int ret; \ + asm ("rorl %%cl,%0" \ + : "=r"(ret) \ + : "c"(n),"0"((unsigned int)(a)) \ + : "cc"); \ + ret; \ + }) +# endif +#endif +#ifndef ROTATE_l32 +# define ROTATE_l32(a,n) (((a)<<(n&0x1f))|(((a)&0xffffffff)>>((32-n)&0x1f))) +#endif +#ifndef ROTATE_r32 +# define ROTATE_r32(a,n) (((a)<<((32-n)&0x1f))|(((a)&0xffffffff)>>(n&0x1f))) +#endif + +#define RC5_32_MASK 0xffffffffL + +#define RC5_16_P 0xB7E1 +#define RC5_16_Q 0x9E37 +#define RC5_32_P 0xB7E15163L +#define RC5_32_Q 0x9E3779B9L +#define RC5_64_P 0xB7E151628AED2A6BLL +#define RC5_64_Q 0x9E3779B97F4A7C15LL + +#define E_RC5_32(a,b,s,n) \ + a^=b; \ + a=ROTATE_l32(a,b); \ + a+=s[n]; \ + a&=RC5_32_MASK; \ + b^=a; \ + b=ROTATE_l32(b,a); \ + b+=s[n+1]; \ + b&=RC5_32_MASK; + +#define D_RC5_32(a,b,s,n) \ + b-=s[n+1]; \ + b&=RC5_32_MASK; \ + b=ROTATE_r32(b,a); \ + b^=a; \ + a-=s[n]; \ + a&=RC5_32_MASK; \ + a=ROTATE_r32(a,b); \ + a^=b; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rc5/rc5_skey.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rc5/rc5_skey.c new file mode 100644 index 000000000..943a7849b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rc5/rc5_skey.c @@ -0,0 +1,61 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "rc5_locl.h" + +void RC5_32_set_key(RC5_32_KEY *key, int len, const unsigned char *data, + int rounds) +{ + RC5_32_INT L[64], l, ll, A, B, *S, k; + int i, j, m, c, t, ii, jj; + + if ((rounds != RC5_16_ROUNDS) && + (rounds != RC5_12_ROUNDS) && (rounds != RC5_8_ROUNDS)) + rounds = RC5_16_ROUNDS; + + key->rounds = rounds; + S = &(key->data[0]); + j = 0; + for (i = 0; i <= (len - 8); i += 8) { + c2l(data, l); + L[j++] = l; + c2l(data, l); + L[j++] = l; + } + ii = len - i; + if (ii) { + k = len & 0x07; + c2ln(data, l, ll, k); + L[j + 0] = l; + L[j + 1] = ll; + } + + c = (len + 3) / 4; + t = (rounds + 1) * 2; + S[0] = RC5_32_P; + for (i = 1; i < t; i++) + S[i] = (S[i - 1] + RC5_32_Q) & RC5_32_MASK; + + j = (t > c) ? t : c; + j *= 3; + ii = jj = 0; + A = B = 0; + for (i = 0; i < j; i++) { + k = (S[ii] + A + B) & RC5_32_MASK; + A = S[ii] = ROTATE_l32(k, 3); + m = (int)(A + B); + k = (L[jj] + A + B) & RC5_32_MASK; + B = L[jj] = ROTATE_l32(k, m); + if (++ii >= t) + ii = 0; + if (++jj >= c) + jj = 0; + } +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rc5/rc5cfb64.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rc5/rc5cfb64.c new file mode 100644 index 000000000..9a8aa6b24 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rc5/rc5cfb64.c @@ -0,0 +1,74 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "rc5_locl.h" + +/* + * The input and output encrypted as though 64bit cfb mode is being used. + * The extra state information to record how much of the 64bit block we have + * used is contained in *num; + */ + +void RC5_32_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, RC5_32_KEY *schedule, + unsigned char *ivec, int *num, int encrypt) +{ + register unsigned long v0, v1, t; + register int n = *num; + register long l = length; + unsigned long ti[2]; + unsigned char *iv, c, cc; + + iv = (unsigned char *)ivec; + if (encrypt) { + while (l--) { + if (n == 0) { + c2l(iv, v0); + ti[0] = v0; + c2l(iv, v1); + ti[1] = v1; + RC5_32_encrypt((unsigned long *)ti, schedule); + iv = (unsigned char *)ivec; + t = ti[0]; + l2c(t, iv); + t = ti[1]; + l2c(t, iv); + iv = (unsigned char *)ivec; + } + c = *(in++) ^ iv[n]; + *(out++) = c; + iv[n] = c; + n = (n + 1) & 0x07; + } + } else { + while (l--) { + if (n == 0) { + c2l(iv, v0); + ti[0] = v0; + c2l(iv, v1); + ti[1] = v1; + RC5_32_encrypt((unsigned long *)ti, schedule); + iv = (unsigned char *)ivec; + t = ti[0]; + l2c(t, iv); + t = ti[1]; + l2c(t, iv); + iv = (unsigned char *)ivec; + } + cc = *(in++); + c = iv[n]; + iv[n] = cc; + *(out++) = c ^ cc; + n = (n + 1) & 0x07; + } + } + v0 = v1 = ti[0] = ti[1] = t = c = cc = 0; + *num = n; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rc5/rc5ofb64.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rc5/rc5ofb64.c new file mode 100644 index 000000000..3a41d773c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rc5/rc5ofb64.c @@ -0,0 +1,61 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "rc5_locl.h" + +/* + * The input and output encrypted as though 64bit ofb mode is being used. + * The extra state information to record how much of the 64bit block we have + * used is contained in *num; + */ +void RC5_32_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, RC5_32_KEY *schedule, + unsigned char *ivec, int *num) +{ + register unsigned long v0, v1, t; + register int n = *num; + register long l = length; + unsigned char d[8]; + register char *dp; + unsigned long ti[2]; + unsigned char *iv; + int save = 0; + + iv = (unsigned char *)ivec; + c2l(iv, v0); + c2l(iv, v1); + ti[0] = v0; + ti[1] = v1; + dp = (char *)d; + l2c(v0, dp); + l2c(v1, dp); + while (l--) { + if (n == 0) { + RC5_32_encrypt((unsigned long *)ti, schedule); + dp = (char *)d; + t = ti[0]; + l2c(t, dp); + t = ti[1]; + l2c(t, dp); + save++; + } + *(out++) = *(in++) ^ d[n]; + n = (n + 1) & 0x07; + } + if (save) { + v0 = ti[0]; + v1 = ti[1]; + iv = (unsigned char *)ivec; + l2c(v0, iv); + l2c(v1, iv); + } + t = v0 = v1 = ti[0] = ti[1] = 0; + *num = n; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ripemd/asm/rmd-586.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/ripemd/asm/rmd-586.pl new file mode 100644 index 000000000..84aa7ced1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ripemd/asm/rmd-586.pl @@ -0,0 +1,602 @@ +#! /usr/bin/env perl +# Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# Normal is the +# ripemd160_block_asm_data_order(RIPEMD160_CTX *c, ULONG *X,int blocks); + +$normal=0; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +$output=pop; +open STDOUT,">$output"; + +&asm_init($ARGV[0]); + +$A="ecx"; +$B="esi"; +$C="edi"; +$D="ebx"; +$E="ebp"; +$tmp1="eax"; +$tmp2="edx"; + +$KL1=0x5A827999; +$KL2=0x6ED9EBA1; +$KL3=0x8F1BBCDC; +$KL4=0xA953FD4E; +$KR0=0x50A28BE6; +$KR1=0x5C4DD124; +$KR2=0x6D703EF3; +$KR3=0x7A6D76E9; + + +@wl=( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, + 7, 4,13, 1,10, 6,15, 3,12, 0, 9, 5, 2,14,11, 8, + 3,10,14, 4, 9,15, 8, 1, 2, 7, 0, 6,13,11, 5,12, + 1, 9,11,10, 0, 8,12, 4,13, 3, 7,15,14, 5, 6, 2, + 4, 0, 5, 9, 7,12, 2,10,14, 1, 3, 8,11, 6,15,13, + ); + +@wr=( 5,14, 7, 0, 9, 2,11, 4,13, 6,15, 8, 1,10, 3,12, + 6,11, 3, 7, 0,13, 5,10,14,15, 8,12, 4, 9, 1, 2, + 15, 5, 1, 3, 7,14, 6, 9,11, 8,12, 2,10, 0, 4,13, + 8, 6, 4, 1, 3,11,15, 0, 5,12, 2,13, 9, 7,10,14, + 12,15,10, 4, 1, 5, 8, 7, 6, 2,13,14, 0, 3, 9,11, + ); + +@sl=( 11,14,15,12, 5, 8, 7, 9,11,13,14,15, 6, 7, 9, 8, + 7, 6, 8,13,11, 9, 7,15, 7,12,15, 9,11, 7,13,12, + 11,13, 6, 7,14, 9,13,15,14, 8,13, 6, 5,12, 7, 5, + 11,12,14,15,14,15, 9, 8, 9,14, 5, 6, 8, 6, 5,12, + 9,15, 5,11, 6, 8,13,12, 5,12,13,14,11, 8, 5, 6, + ); + +@sr=( 8, 9, 9,11,13,15,15, 5, 7, 7, 8,11,14,14,12, 6, + 9,13,15, 7,12, 8, 9,11, 7, 7,12, 7, 6,15,13,11, + 9, 7,15,11, 8, 6, 6,14,12,13, 5,14,13,13, 7, 5, + 15, 5, 8,11,14,14, 6,14, 6, 9,12, 9,12, 5,15, 8, + 8, 5,12, 9,12, 5,14, 6, 8,13, 6, 5,15,13,11,11, + ); + +&ripemd160_block("ripemd160_block_asm_data_order"); +&asm_finish(); + +close STDOUT; + +sub Xv + { + local($n)=@_; + return(&swtmp($n)); + # tmp on stack + } + +sub Np + { + local($p)=@_; + local(%n)=($A,$E,$B,$A,$C,$B,$D,$C,$E,$D); + return($n{$p}); + } + +sub RIP1 + { + local($a,$b,$c,$d,$e,$pos,$s,$o,$pos2)=@_; + + &comment($p++); + if ($p & 1) + { + #&mov($tmp1, $c) if $o == -1; + &xor($tmp1, $d) if $o == -1; + &mov($tmp2, &Xv($pos)); + &xor($tmp1, $b); + &add($a, $tmp2); + &rotl($c, 10); + &add($a, $tmp1); + &mov($tmp1, &Np($c)); # NEXT + # XXX + &rotl($a, $s); + &add($a, $e); + } + else + { + &xor($tmp1, $d); + &mov($tmp2, &Xv($pos)); + &xor($tmp1, $b); + &add($a, $tmp1); + &mov($tmp1, &Np($c)) if $o <= 0; + &mov($tmp1, -1) if $o == 1; + # XXX if $o == 2; + &rotl($c, 10); + &add($a, $tmp2); + &xor($tmp1, &Np($d)) if $o <= 0; + &mov($tmp2, &Xv($pos2)) if $o == 1; + &mov($tmp2, &wparam(0)) if $o == 2; + &rotl($a, $s); + &add($a, $e); + } + } + +sub RIP2 + { + local($a,$b,$c,$d,$e,$pos,$pos2,$s,$K,$o)=@_; + +# XXXXXX + &comment($p++); + if ($p & 1) + { +# &mov($tmp2, &Xv($pos)) if $o < -1; +# &mov($tmp1, -1) if $o < -1; + + &add($a, $tmp2); + &mov($tmp2, $c); + &sub($tmp1, $b); + &and($tmp2, $b); + &and($tmp1, $d); + &or($tmp2, $tmp1); + &mov($tmp1, &Xv($pos2)) if $o <= 0; # XXXXXXXXXXXXXX + # XXX + &rotl($c, 10); + &lea($a, &DWP($K,$a,$tmp2,1)); + &mov($tmp2, -1) if $o <= 0; + # XXX + &rotl($a, $s); + &add($a, $e); + } + else + { + # XXX + &add($a, $tmp1); + &mov($tmp1, $c); + &sub($tmp2, $b); + &and($tmp1, $b); + &and($tmp2, $d); + if ($o != 2) + { + &or($tmp1, $tmp2); + &mov($tmp2, &Xv($pos2)) if $o <= 0; + &mov($tmp2, -1) if $o == 1; + &rotl($c, 10); + &lea($a, &DWP($K,$a,$tmp1,1)); + &mov($tmp1, -1) if $o <= 0; + &sub($tmp2, &Np($c)) if $o == 1; + } else { + &or($tmp2, $tmp1); + &mov($tmp1, &Np($c)); + &rotl($c, 10); + &lea($a, &DWP($K,$a,$tmp2,1)); + &xor($tmp1, &Np($d)); + } + &rotl($a, $s); + &add($a, $e); + } + } + +sub RIP3 + { + local($a,$b,$c,$d,$e,$pos,$s,$K,$o,$pos2)=@_; + + &comment($p++); + if ($p & 1) + { +# &mov($tmp2, -1) if $o < -1; +# &sub($tmp2, $c) if $o < -1; + &mov($tmp1, &Xv($pos)); + &or($tmp2, $b); + &add($a, $tmp1); + &xor($tmp2, $d); + &mov($tmp1, -1) if $o <= 0; # NEXT + # XXX + &rotl($c, 10); + &lea($a, &DWP($K,$a,$tmp2,1)); + &sub($tmp1, &Np($c)) if $o <= 0; # NEXT + # XXX + &rotl($a, $s); + &add($a, $e); + } + else + { + &mov($tmp2, &Xv($pos)); + &or($tmp1, $b); + &add($a, $tmp2); + &xor($tmp1, $d); + &mov($tmp2, -1) if $o <= 0; # NEXT + &mov($tmp2, -1) if $o == 1; + &mov($tmp2, &Xv($pos2)) if $o == 2; + &rotl($c, 10); + &lea($a, &DWP($K,$a,$tmp1,1)); + &sub($tmp2, &Np($c)) if $o <= 0; # NEXT + &mov($tmp1, &Np($d)) if $o == 1; + &mov($tmp1, -1) if $o == 2; + &rotl($a, $s); + &add($a, $e); + } + } + +sub RIP4 + { + local($a,$b,$c,$d,$e,$pos,$s,$K,$o)=@_; + + &comment($p++); + if ($p & 1) + { +# &mov($tmp2, -1) if $o == -2; +# &mov($tmp1, $d) if $o == -2; + &sub($tmp2, $d); + &and($tmp1, $b); + &and($tmp2, $c); + &or($tmp2, $tmp1); + &mov($tmp1, &Xv($pos)); + &rotl($c, 10); + &lea($a, &DWP($K,$a,$tmp2)); + &mov($tmp2, -1) unless $o > 0; # NEXT + # XXX + &add($a, $tmp1); + &mov($tmp1, &Np($d)) unless $o > 0; # NEXT + # XXX + &rotl($a, $s); + &add($a, $e); + } + else + { + &sub($tmp2, $d); + &and($tmp1, $b); + &and($tmp2, $c); + &or($tmp2, $tmp1); + &mov($tmp1, &Xv($pos)); + &rotl($c, 10); + &lea($a, &DWP($K,$a,$tmp2)); + &mov($tmp2, -1) if $o == 0; # NEXT + &mov($tmp2, -1) if $o == 1; + &mov($tmp2, -1) if $o == 2; + # XXX + &add($a, $tmp1); + &mov($tmp1, &Np($d)) if $o == 0; # NEXT + &sub($tmp2, &Np($d)) if $o == 1; + &sub($tmp2, &Np($c)) if $o == 2; + # XXX + &rotl($a, $s); + &add($a, $e); + } + } + +sub RIP5 + { + local($a,$b,$c,$d,$e,$pos,$s,$K,$o)=@_; + + &comment($p++); + if ($p & 1) + { + &mov($tmp2, -1) if $o == -2; + &sub($tmp2, $d) if $o == -2; + &mov($tmp1, &Xv($pos)); + &or($tmp2, $c); + &add($a, $tmp1); + &xor($tmp2, $b); + &mov($tmp1, -1) if $o <= 0; + # XXX + &rotl($c, 10); + &lea($a, &DWP($K,$a,$tmp2,1)); + &sub($tmp1, &Np($d)) if $o <= 0; + # XXX + &rotl($a, $s); + &add($a, $e); + } + else + { + &mov($tmp2, &Xv($pos)); + &or($tmp1, $c); + &add($a, $tmp2); + &xor($tmp1, $b); + &mov($tmp2, -1) if $o <= 0; + &mov($tmp2, &wparam(0)) if $o == 1; # Middle code + &mov($tmp2, -1) if $o == 2; + &rotl($c, 10); + &lea($a, &DWP($K,$a,$tmp1,1)); + &sub($tmp2, &Np($d)) if $o <= 0; + &mov(&swtmp(16), $A) if $o == 1; + &mov($tmp1, &Np($d)) if $o == 2; + &rotl($a, $s); + &add($a, $e); + } + } + +sub ripemd160_block + { + local($name)=@_; + + &function_begin_B($name,"",3); + + # parameter 1 is the RIPEMD160_CTX structure. + # A 0 + # B 4 + # C 8 + # D 12 + # E 16 + + &mov($tmp2, &wparam(0)); + &mov($tmp1, &wparam(1)); + &push("esi"); + &mov($A, &DWP( 0,$tmp2,"",0)); + &push("edi"); + &mov($B, &DWP( 4,$tmp2,"",0)); + &push("ebp"); + &mov($C, &DWP( 8,$tmp2,"",0)); + &push("ebx"); + &stack_push(16+5+6); + # Special comment about the figure of 6. + # Idea is to pad the current frame so + # that the top of the stack gets fairly + # aligned. Well, as you realize it would + # always depend on how the frame below is + # aligned. The good news are that gcc-2.95 + # and later does keep first argument at + # least double-wise aligned. + + &set_label("start") unless $normal; + &comment(""); + + # &mov($tmp1, &wparam(1)); # Done at end of loop + # &mov($tmp2, &wparam(0)); # Done at end of loop + + for ($z=0; $z<16; $z+=2) + { + &mov($D, &DWP( $z*4,$tmp1,"",0)); + &mov($E, &DWP( ($z+1)*4,$tmp1,"",0)); + &mov(&swtmp($z), $D); + &mov(&swtmp($z+1), $E); + } + &mov($tmp1, $C); + &mov($D, &DWP(12,$tmp2,"",0)); + &mov($E, &DWP(16,$tmp2,"",0)); + + &RIP1($A,$B,$C,$D,$E,$wl[ 0],$sl[ 0],-1); + &RIP1($E,$A,$B,$C,$D,$wl[ 1],$sl[ 1],0); + &RIP1($D,$E,$A,$B,$C,$wl[ 2],$sl[ 2],0); + &RIP1($C,$D,$E,$A,$B,$wl[ 3],$sl[ 3],0); + &RIP1($B,$C,$D,$E,$A,$wl[ 4],$sl[ 4],0); + &RIP1($A,$B,$C,$D,$E,$wl[ 5],$sl[ 5],0); + &RIP1($E,$A,$B,$C,$D,$wl[ 6],$sl[ 6],0); + &RIP1($D,$E,$A,$B,$C,$wl[ 7],$sl[ 7],0); + &RIP1($C,$D,$E,$A,$B,$wl[ 8],$sl[ 8],0); + &RIP1($B,$C,$D,$E,$A,$wl[ 9],$sl[ 9],0); + &RIP1($A,$B,$C,$D,$E,$wl[10],$sl[10],0); + &RIP1($E,$A,$B,$C,$D,$wl[11],$sl[11],0); + &RIP1($D,$E,$A,$B,$C,$wl[12],$sl[12],0); + &RIP1($C,$D,$E,$A,$B,$wl[13],$sl[13],0); + &RIP1($B,$C,$D,$E,$A,$wl[14],$sl[14],0); + &RIP1($A,$B,$C,$D,$E,$wl[15],$sl[15],1,$wl[16]); + + &RIP2($E,$A,$B,$C,$D,$wl[16],$wl[17],$sl[16],$KL1,-1); + &RIP2($D,$E,$A,$B,$C,$wl[17],$wl[18],$sl[17],$KL1,0); + &RIP2($C,$D,$E,$A,$B,$wl[18],$wl[19],$sl[18],$KL1,0); + &RIP2($B,$C,$D,$E,$A,$wl[19],$wl[20],$sl[19],$KL1,0); + &RIP2($A,$B,$C,$D,$E,$wl[20],$wl[21],$sl[20],$KL1,0); + &RIP2($E,$A,$B,$C,$D,$wl[21],$wl[22],$sl[21],$KL1,0); + &RIP2($D,$E,$A,$B,$C,$wl[22],$wl[23],$sl[22],$KL1,0); + &RIP2($C,$D,$E,$A,$B,$wl[23],$wl[24],$sl[23],$KL1,0); + &RIP2($B,$C,$D,$E,$A,$wl[24],$wl[25],$sl[24],$KL1,0); + &RIP2($A,$B,$C,$D,$E,$wl[25],$wl[26],$sl[25],$KL1,0); + &RIP2($E,$A,$B,$C,$D,$wl[26],$wl[27],$sl[26],$KL1,0); + &RIP2($D,$E,$A,$B,$C,$wl[27],$wl[28],$sl[27],$KL1,0); + &RIP2($C,$D,$E,$A,$B,$wl[28],$wl[29],$sl[28],$KL1,0); + &RIP2($B,$C,$D,$E,$A,$wl[29],$wl[30],$sl[29],$KL1,0); + &RIP2($A,$B,$C,$D,$E,$wl[30],$wl[31],$sl[30],$KL1,0); + &RIP2($E,$A,$B,$C,$D,$wl[31],$wl[32],$sl[31],$KL1,1); + + &RIP3($D,$E,$A,$B,$C,$wl[32],$sl[32],$KL2,-1); + &RIP3($C,$D,$E,$A,$B,$wl[33],$sl[33],$KL2,0); + &RIP3($B,$C,$D,$E,$A,$wl[34],$sl[34],$KL2,0); + &RIP3($A,$B,$C,$D,$E,$wl[35],$sl[35],$KL2,0); + &RIP3($E,$A,$B,$C,$D,$wl[36],$sl[36],$KL2,0); + &RIP3($D,$E,$A,$B,$C,$wl[37],$sl[37],$KL2,0); + &RIP3($C,$D,$E,$A,$B,$wl[38],$sl[38],$KL2,0); + &RIP3($B,$C,$D,$E,$A,$wl[39],$sl[39],$KL2,0); + &RIP3($A,$B,$C,$D,$E,$wl[40],$sl[40],$KL2,0); + &RIP3($E,$A,$B,$C,$D,$wl[41],$sl[41],$KL2,0); + &RIP3($D,$E,$A,$B,$C,$wl[42],$sl[42],$KL2,0); + &RIP3($C,$D,$E,$A,$B,$wl[43],$sl[43],$KL2,0); + &RIP3($B,$C,$D,$E,$A,$wl[44],$sl[44],$KL2,0); + &RIP3($A,$B,$C,$D,$E,$wl[45],$sl[45],$KL2,0); + &RIP3($E,$A,$B,$C,$D,$wl[46],$sl[46],$KL2,0); + &RIP3($D,$E,$A,$B,$C,$wl[47],$sl[47],$KL2,1); + + &RIP4($C,$D,$E,$A,$B,$wl[48],$sl[48],$KL3,-1); + &RIP4($B,$C,$D,$E,$A,$wl[49],$sl[49],$KL3,0); + &RIP4($A,$B,$C,$D,$E,$wl[50],$sl[50],$KL3,0); + &RIP4($E,$A,$B,$C,$D,$wl[51],$sl[51],$KL3,0); + &RIP4($D,$E,$A,$B,$C,$wl[52],$sl[52],$KL3,0); + &RIP4($C,$D,$E,$A,$B,$wl[53],$sl[53],$KL3,0); + &RIP4($B,$C,$D,$E,$A,$wl[54],$sl[54],$KL3,0); + &RIP4($A,$B,$C,$D,$E,$wl[55],$sl[55],$KL3,0); + &RIP4($E,$A,$B,$C,$D,$wl[56],$sl[56],$KL3,0); + &RIP4($D,$E,$A,$B,$C,$wl[57],$sl[57],$KL3,0); + &RIP4($C,$D,$E,$A,$B,$wl[58],$sl[58],$KL3,0); + &RIP4($B,$C,$D,$E,$A,$wl[59],$sl[59],$KL3,0); + &RIP4($A,$B,$C,$D,$E,$wl[60],$sl[60],$KL3,0); + &RIP4($E,$A,$B,$C,$D,$wl[61],$sl[61],$KL3,0); + &RIP4($D,$E,$A,$B,$C,$wl[62],$sl[62],$KL3,0); + &RIP4($C,$D,$E,$A,$B,$wl[63],$sl[63],$KL3,1); + + &RIP5($B,$C,$D,$E,$A,$wl[64],$sl[64],$KL4,-1); + &RIP5($A,$B,$C,$D,$E,$wl[65],$sl[65],$KL4,0); + &RIP5($E,$A,$B,$C,$D,$wl[66],$sl[66],$KL4,0); + &RIP5($D,$E,$A,$B,$C,$wl[67],$sl[67],$KL4,0); + &RIP5($C,$D,$E,$A,$B,$wl[68],$sl[68],$KL4,0); + &RIP5($B,$C,$D,$E,$A,$wl[69],$sl[69],$KL4,0); + &RIP5($A,$B,$C,$D,$E,$wl[70],$sl[70],$KL4,0); + &RIP5($E,$A,$B,$C,$D,$wl[71],$sl[71],$KL4,0); + &RIP5($D,$E,$A,$B,$C,$wl[72],$sl[72],$KL4,0); + &RIP5($C,$D,$E,$A,$B,$wl[73],$sl[73],$KL4,0); + &RIP5($B,$C,$D,$E,$A,$wl[74],$sl[74],$KL4,0); + &RIP5($A,$B,$C,$D,$E,$wl[75],$sl[75],$KL4,0); + &RIP5($E,$A,$B,$C,$D,$wl[76],$sl[76],$KL4,0); + &RIP5($D,$E,$A,$B,$C,$wl[77],$sl[77],$KL4,0); + &RIP5($C,$D,$E,$A,$B,$wl[78],$sl[78],$KL4,0); + &RIP5($B,$C,$D,$E,$A,$wl[79],$sl[79],$KL4,1); + + # &mov($tmp2, &wparam(0)); # moved into last RIP5 + # &mov(&swtmp(16), $A); + &mov($A, &DWP( 0,$tmp2,"",0)); + &mov(&swtmp(16+1), $B); + &mov(&swtmp(16+2), $C); + &mov($B, &DWP( 4,$tmp2,"",0)); + &mov(&swtmp(16+3), $D); + &mov($C, &DWP( 8,$tmp2,"",0)); + &mov(&swtmp(16+4), $E); + &mov($D, &DWP(12,$tmp2,"",0)); + &mov($E, &DWP(16,$tmp2,"",0)); + + &RIP5($A,$B,$C,$D,$E,$wr[ 0],$sr[ 0],$KR0,-2); + &RIP5($E,$A,$B,$C,$D,$wr[ 1],$sr[ 1],$KR0,0); + &RIP5($D,$E,$A,$B,$C,$wr[ 2],$sr[ 2],$KR0,0); + &RIP5($C,$D,$E,$A,$B,$wr[ 3],$sr[ 3],$KR0,0); + &RIP5($B,$C,$D,$E,$A,$wr[ 4],$sr[ 4],$KR0,0); + &RIP5($A,$B,$C,$D,$E,$wr[ 5],$sr[ 5],$KR0,0); + &RIP5($E,$A,$B,$C,$D,$wr[ 6],$sr[ 6],$KR0,0); + &RIP5($D,$E,$A,$B,$C,$wr[ 7],$sr[ 7],$KR0,0); + &RIP5($C,$D,$E,$A,$B,$wr[ 8],$sr[ 8],$KR0,0); + &RIP5($B,$C,$D,$E,$A,$wr[ 9],$sr[ 9],$KR0,0); + &RIP5($A,$B,$C,$D,$E,$wr[10],$sr[10],$KR0,0); + &RIP5($E,$A,$B,$C,$D,$wr[11],$sr[11],$KR0,0); + &RIP5($D,$E,$A,$B,$C,$wr[12],$sr[12],$KR0,0); + &RIP5($C,$D,$E,$A,$B,$wr[13],$sr[13],$KR0,0); + &RIP5($B,$C,$D,$E,$A,$wr[14],$sr[14],$KR0,0); + &RIP5($A,$B,$C,$D,$E,$wr[15],$sr[15],$KR0,2); + + &RIP4($E,$A,$B,$C,$D,$wr[16],$sr[16],$KR1,-2); + &RIP4($D,$E,$A,$B,$C,$wr[17],$sr[17],$KR1,0); + &RIP4($C,$D,$E,$A,$B,$wr[18],$sr[18],$KR1,0); + &RIP4($B,$C,$D,$E,$A,$wr[19],$sr[19],$KR1,0); + &RIP4($A,$B,$C,$D,$E,$wr[20],$sr[20],$KR1,0); + &RIP4($E,$A,$B,$C,$D,$wr[21],$sr[21],$KR1,0); + &RIP4($D,$E,$A,$B,$C,$wr[22],$sr[22],$KR1,0); + &RIP4($C,$D,$E,$A,$B,$wr[23],$sr[23],$KR1,0); + &RIP4($B,$C,$D,$E,$A,$wr[24],$sr[24],$KR1,0); + &RIP4($A,$B,$C,$D,$E,$wr[25],$sr[25],$KR1,0); + &RIP4($E,$A,$B,$C,$D,$wr[26],$sr[26],$KR1,0); + &RIP4($D,$E,$A,$B,$C,$wr[27],$sr[27],$KR1,0); + &RIP4($C,$D,$E,$A,$B,$wr[28],$sr[28],$KR1,0); + &RIP4($B,$C,$D,$E,$A,$wr[29],$sr[29],$KR1,0); + &RIP4($A,$B,$C,$D,$E,$wr[30],$sr[30],$KR1,0); + &RIP4($E,$A,$B,$C,$D,$wr[31],$sr[31],$KR1,2); + + &RIP3($D,$E,$A,$B,$C,$wr[32],$sr[32],$KR2,-2); + &RIP3($C,$D,$E,$A,$B,$wr[33],$sr[33],$KR2,0); + &RIP3($B,$C,$D,$E,$A,$wr[34],$sr[34],$KR2,0); + &RIP3($A,$B,$C,$D,$E,$wr[35],$sr[35],$KR2,0); + &RIP3($E,$A,$B,$C,$D,$wr[36],$sr[36],$KR2,0); + &RIP3($D,$E,$A,$B,$C,$wr[37],$sr[37],$KR2,0); + &RIP3($C,$D,$E,$A,$B,$wr[38],$sr[38],$KR2,0); + &RIP3($B,$C,$D,$E,$A,$wr[39],$sr[39],$KR2,0); + &RIP3($A,$B,$C,$D,$E,$wr[40],$sr[40],$KR2,0); + &RIP3($E,$A,$B,$C,$D,$wr[41],$sr[41],$KR2,0); + &RIP3($D,$E,$A,$B,$C,$wr[42],$sr[42],$KR2,0); + &RIP3($C,$D,$E,$A,$B,$wr[43],$sr[43],$KR2,0); + &RIP3($B,$C,$D,$E,$A,$wr[44],$sr[44],$KR2,0); + &RIP3($A,$B,$C,$D,$E,$wr[45],$sr[45],$KR2,0); + &RIP3($E,$A,$B,$C,$D,$wr[46],$sr[46],$KR2,0); + &RIP3($D,$E,$A,$B,$C,$wr[47],$sr[47],$KR2,2,$wr[48]); + + &RIP2($C,$D,$E,$A,$B,$wr[48],$wr[49],$sr[48],$KR3,-2); + &RIP2($B,$C,$D,$E,$A,$wr[49],$wr[50],$sr[49],$KR3,0); + &RIP2($A,$B,$C,$D,$E,$wr[50],$wr[51],$sr[50],$KR3,0); + &RIP2($E,$A,$B,$C,$D,$wr[51],$wr[52],$sr[51],$KR3,0); + &RIP2($D,$E,$A,$B,$C,$wr[52],$wr[53],$sr[52],$KR3,0); + &RIP2($C,$D,$E,$A,$B,$wr[53],$wr[54],$sr[53],$KR3,0); + &RIP2($B,$C,$D,$E,$A,$wr[54],$wr[55],$sr[54],$KR3,0); + &RIP2($A,$B,$C,$D,$E,$wr[55],$wr[56],$sr[55],$KR3,0); + &RIP2($E,$A,$B,$C,$D,$wr[56],$wr[57],$sr[56],$KR3,0); + &RIP2($D,$E,$A,$B,$C,$wr[57],$wr[58],$sr[57],$KR3,0); + &RIP2($C,$D,$E,$A,$B,$wr[58],$wr[59],$sr[58],$KR3,0); + &RIP2($B,$C,$D,$E,$A,$wr[59],$wr[60],$sr[59],$KR3,0); + &RIP2($A,$B,$C,$D,$E,$wr[60],$wr[61],$sr[60],$KR3,0); + &RIP2($E,$A,$B,$C,$D,$wr[61],$wr[62],$sr[61],$KR3,0); + &RIP2($D,$E,$A,$B,$C,$wr[62],$wr[63],$sr[62],$KR3,0); + &RIP2($C,$D,$E,$A,$B,$wr[63],$wr[64],$sr[63],$KR3,2); + + &RIP1($B,$C,$D,$E,$A,$wr[64],$sr[64],-2); + &RIP1($A,$B,$C,$D,$E,$wr[65],$sr[65],0); + &RIP1($E,$A,$B,$C,$D,$wr[66],$sr[66],0); + &RIP1($D,$E,$A,$B,$C,$wr[67],$sr[67],0); + &RIP1($C,$D,$E,$A,$B,$wr[68],$sr[68],0); + &RIP1($B,$C,$D,$E,$A,$wr[69],$sr[69],0); + &RIP1($A,$B,$C,$D,$E,$wr[70],$sr[70],0); + &RIP1($E,$A,$B,$C,$D,$wr[71],$sr[71],0); + &RIP1($D,$E,$A,$B,$C,$wr[72],$sr[72],0); + &RIP1($C,$D,$E,$A,$B,$wr[73],$sr[73],0); + &RIP1($B,$C,$D,$E,$A,$wr[74],$sr[74],0); + &RIP1($A,$B,$C,$D,$E,$wr[75],$sr[75],0); + &RIP1($E,$A,$B,$C,$D,$wr[76],$sr[76],0); + &RIP1($D,$E,$A,$B,$C,$wr[77],$sr[77],0); + &RIP1($C,$D,$E,$A,$B,$wr[78],$sr[78],0); + &RIP1($B,$C,$D,$E,$A,$wr[79],$sr[79],2); + + # &mov($tmp2, &wparam(0)); # Moved into last round + + &mov($tmp1, &DWP( 4,$tmp2,"",0)); # ctx->B + &add($D, $tmp1); + &mov($tmp1, &swtmp(16+2)); # $c + &add($D, $tmp1); + + &mov($tmp1, &DWP( 8,$tmp2,"",0)); # ctx->C + &add($E, $tmp1); + &mov($tmp1, &swtmp(16+3)); # $d + &add($E, $tmp1); + + &mov($tmp1, &DWP(12,$tmp2,"",0)); # ctx->D + &add($A, $tmp1); + &mov($tmp1, &swtmp(16+4)); # $e + &add($A, $tmp1); + + + &mov($tmp1, &DWP(16,$tmp2,"",0)); # ctx->E + &add($B, $tmp1); + &mov($tmp1, &swtmp(16+0)); # $a + &add($B, $tmp1); + + &mov($tmp1, &DWP( 0,$tmp2,"",0)); # ctx->A + &add($C, $tmp1); + &mov($tmp1, &swtmp(16+1)); # $b + &add($C, $tmp1); + + &mov($tmp1, &wparam(2)); + + &mov(&DWP( 0,$tmp2,"",0), $D); + &mov(&DWP( 4,$tmp2,"",0), $E); + &mov(&DWP( 8,$tmp2,"",0), $A); + &sub($tmp1,1); + &mov(&DWP(12,$tmp2,"",0), $B); + &mov(&DWP(16,$tmp2,"",0), $C); + + &jle(&label("get_out")); + + &mov(&wparam(2),$tmp1); + &mov($C, $A); + &mov($tmp1, &wparam(1)); + &mov($A, $D); + &add($tmp1, 64); + &mov($B, $E); + &mov(&wparam(1),$tmp1); + + &jmp(&label("start")); + + &set_label("get_out"); + + &stack_pop(16+5+6); + + &pop("ebx"); + &pop("ebp"); + &pop("edi"); + &pop("esi"); + &ret(); + &function_end_B($name); + } + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ripemd/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/ripemd/build.info new file mode 100644 index 000000000..a4a894e2d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ripemd/build.info @@ -0,0 +1,7 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + rmd_dgst.c rmd_one.c {- $target{rmd160_asm_src} -} + +GENERATE[rmd-586.s]=asm/rmd-586.pl \ + $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) +DEPEND[rmd-586.s]=../perlasm/x86asm.pl diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ripemd/rmd_dgst.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ripemd/rmd_dgst.c new file mode 100644 index 000000000..a1670c7fb --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ripemd/rmd_dgst.c @@ -0,0 +1,282 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "rmd_locl.h" +#include + +#ifdef RMD160_ASM +void ripemd160_block_x86(RIPEMD160_CTX *c, unsigned long *p, size_t num); +# define ripemd160_block ripemd160_block_x86 +#else +void ripemd160_block(RIPEMD160_CTX *c, unsigned long *p, size_t num); +#endif + +int RIPEMD160_Init(RIPEMD160_CTX *c) +{ + memset(c, 0, sizeof(*c)); + c->A = RIPEMD160_A; + c->B = RIPEMD160_B; + c->C = RIPEMD160_C; + c->D = RIPEMD160_D; + c->E = RIPEMD160_E; + return 1; +} + +#ifndef ripemd160_block_data_order +# ifdef X +# undef X +# endif +void ripemd160_block_data_order(RIPEMD160_CTX *ctx, const void *p, size_t num) +{ + const unsigned char *data = p; + register unsigned MD32_REG_T A, B, C, D, E; + unsigned MD32_REG_T a, b, c, d, e, l; +# ifndef MD32_XARRAY + /* See comment in crypto/sha/sha_locl.h for details. */ + unsigned MD32_REG_T XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, + XX8, XX9, XX10, XX11, XX12, XX13, XX14, XX15; +# define X(i) XX##i +# else + RIPEMD160_LONG XX[16]; +# define X(i) XX[i] +# endif + + for (; num--;) { + + A = ctx->A; + B = ctx->B; + C = ctx->C; + D = ctx->D; + E = ctx->E; + + (void)HOST_c2l(data, l); + X(0) = l; + (void)HOST_c2l(data, l); + X(1) = l; + RIP1(A, B, C, D, E, WL00, SL00); + (void)HOST_c2l(data, l); + X(2) = l; + RIP1(E, A, B, C, D, WL01, SL01); + (void)HOST_c2l(data, l); + X(3) = l; + RIP1(D, E, A, B, C, WL02, SL02); + (void)HOST_c2l(data, l); + X(4) = l; + RIP1(C, D, E, A, B, WL03, SL03); + (void)HOST_c2l(data, l); + X(5) = l; + RIP1(B, C, D, E, A, WL04, SL04); + (void)HOST_c2l(data, l); + X(6) = l; + RIP1(A, B, C, D, E, WL05, SL05); + (void)HOST_c2l(data, l); + X(7) = l; + RIP1(E, A, B, C, D, WL06, SL06); + (void)HOST_c2l(data, l); + X(8) = l; + RIP1(D, E, A, B, C, WL07, SL07); + (void)HOST_c2l(data, l); + X(9) = l; + RIP1(C, D, E, A, B, WL08, SL08); + (void)HOST_c2l(data, l); + X(10) = l; + RIP1(B, C, D, E, A, WL09, SL09); + (void)HOST_c2l(data, l); + X(11) = l; + RIP1(A, B, C, D, E, WL10, SL10); + (void)HOST_c2l(data, l); + X(12) = l; + RIP1(E, A, B, C, D, WL11, SL11); + (void)HOST_c2l(data, l); + X(13) = l; + RIP1(D, E, A, B, C, WL12, SL12); + (void)HOST_c2l(data, l); + X(14) = l; + RIP1(C, D, E, A, B, WL13, SL13); + (void)HOST_c2l(data, l); + X(15) = l; + RIP1(B, C, D, E, A, WL14, SL14); + RIP1(A, B, C, D, E, WL15, SL15); + + RIP2(E, A, B, C, D, WL16, SL16, KL1); + RIP2(D, E, A, B, C, WL17, SL17, KL1); + RIP2(C, D, E, A, B, WL18, SL18, KL1); + RIP2(B, C, D, E, A, WL19, SL19, KL1); + RIP2(A, B, C, D, E, WL20, SL20, KL1); + RIP2(E, A, B, C, D, WL21, SL21, KL1); + RIP2(D, E, A, B, C, WL22, SL22, KL1); + RIP2(C, D, E, A, B, WL23, SL23, KL1); + RIP2(B, C, D, E, A, WL24, SL24, KL1); + RIP2(A, B, C, D, E, WL25, SL25, KL1); + RIP2(E, A, B, C, D, WL26, SL26, KL1); + RIP2(D, E, A, B, C, WL27, SL27, KL1); + RIP2(C, D, E, A, B, WL28, SL28, KL1); + RIP2(B, C, D, E, A, WL29, SL29, KL1); + RIP2(A, B, C, D, E, WL30, SL30, KL1); + RIP2(E, A, B, C, D, WL31, SL31, KL1); + + RIP3(D, E, A, B, C, WL32, SL32, KL2); + RIP3(C, D, E, A, B, WL33, SL33, KL2); + RIP3(B, C, D, E, A, WL34, SL34, KL2); + RIP3(A, B, C, D, E, WL35, SL35, KL2); + RIP3(E, A, B, C, D, WL36, SL36, KL2); + RIP3(D, E, A, B, C, WL37, SL37, KL2); + RIP3(C, D, E, A, B, WL38, SL38, KL2); + RIP3(B, C, D, E, A, WL39, SL39, KL2); + RIP3(A, B, C, D, E, WL40, SL40, KL2); + RIP3(E, A, B, C, D, WL41, SL41, KL2); + RIP3(D, E, A, B, C, WL42, SL42, KL2); + RIP3(C, D, E, A, B, WL43, SL43, KL2); + RIP3(B, C, D, E, A, WL44, SL44, KL2); + RIP3(A, B, C, D, E, WL45, SL45, KL2); + RIP3(E, A, B, C, D, WL46, SL46, KL2); + RIP3(D, E, A, B, C, WL47, SL47, KL2); + + RIP4(C, D, E, A, B, WL48, SL48, KL3); + RIP4(B, C, D, E, A, WL49, SL49, KL3); + RIP4(A, B, C, D, E, WL50, SL50, KL3); + RIP4(E, A, B, C, D, WL51, SL51, KL3); + RIP4(D, E, A, B, C, WL52, SL52, KL3); + RIP4(C, D, E, A, B, WL53, SL53, KL3); + RIP4(B, C, D, E, A, WL54, SL54, KL3); + RIP4(A, B, C, D, E, WL55, SL55, KL3); + RIP4(E, A, B, C, D, WL56, SL56, KL3); + RIP4(D, E, A, B, C, WL57, SL57, KL3); + RIP4(C, D, E, A, B, WL58, SL58, KL3); + RIP4(B, C, D, E, A, WL59, SL59, KL3); + RIP4(A, B, C, D, E, WL60, SL60, KL3); + RIP4(E, A, B, C, D, WL61, SL61, KL3); + RIP4(D, E, A, B, C, WL62, SL62, KL3); + RIP4(C, D, E, A, B, WL63, SL63, KL3); + + RIP5(B, C, D, E, A, WL64, SL64, KL4); + RIP5(A, B, C, D, E, WL65, SL65, KL4); + RIP5(E, A, B, C, D, WL66, SL66, KL4); + RIP5(D, E, A, B, C, WL67, SL67, KL4); + RIP5(C, D, E, A, B, WL68, SL68, KL4); + RIP5(B, C, D, E, A, WL69, SL69, KL4); + RIP5(A, B, C, D, E, WL70, SL70, KL4); + RIP5(E, A, B, C, D, WL71, SL71, KL4); + RIP5(D, E, A, B, C, WL72, SL72, KL4); + RIP5(C, D, E, A, B, WL73, SL73, KL4); + RIP5(B, C, D, E, A, WL74, SL74, KL4); + RIP5(A, B, C, D, E, WL75, SL75, KL4); + RIP5(E, A, B, C, D, WL76, SL76, KL4); + RIP5(D, E, A, B, C, WL77, SL77, KL4); + RIP5(C, D, E, A, B, WL78, SL78, KL4); + RIP5(B, C, D, E, A, WL79, SL79, KL4); + + a = A; + b = B; + c = C; + d = D; + e = E; + /* Do other half */ + A = ctx->A; + B = ctx->B; + C = ctx->C; + D = ctx->D; + E = ctx->E; + + RIP5(A, B, C, D, E, WR00, SR00, KR0); + RIP5(E, A, B, C, D, WR01, SR01, KR0); + RIP5(D, E, A, B, C, WR02, SR02, KR0); + RIP5(C, D, E, A, B, WR03, SR03, KR0); + RIP5(B, C, D, E, A, WR04, SR04, KR0); + RIP5(A, B, C, D, E, WR05, SR05, KR0); + RIP5(E, A, B, C, D, WR06, SR06, KR0); + RIP5(D, E, A, B, C, WR07, SR07, KR0); + RIP5(C, D, E, A, B, WR08, SR08, KR0); + RIP5(B, C, D, E, A, WR09, SR09, KR0); + RIP5(A, B, C, D, E, WR10, SR10, KR0); + RIP5(E, A, B, C, D, WR11, SR11, KR0); + RIP5(D, E, A, B, C, WR12, SR12, KR0); + RIP5(C, D, E, A, B, WR13, SR13, KR0); + RIP5(B, C, D, E, A, WR14, SR14, KR0); + RIP5(A, B, C, D, E, WR15, SR15, KR0); + + RIP4(E, A, B, C, D, WR16, SR16, KR1); + RIP4(D, E, A, B, C, WR17, SR17, KR1); + RIP4(C, D, E, A, B, WR18, SR18, KR1); + RIP4(B, C, D, E, A, WR19, SR19, KR1); + RIP4(A, B, C, D, E, WR20, SR20, KR1); + RIP4(E, A, B, C, D, WR21, SR21, KR1); + RIP4(D, E, A, B, C, WR22, SR22, KR1); + RIP4(C, D, E, A, B, WR23, SR23, KR1); + RIP4(B, C, D, E, A, WR24, SR24, KR1); + RIP4(A, B, C, D, E, WR25, SR25, KR1); + RIP4(E, A, B, C, D, WR26, SR26, KR1); + RIP4(D, E, A, B, C, WR27, SR27, KR1); + RIP4(C, D, E, A, B, WR28, SR28, KR1); + RIP4(B, C, D, E, A, WR29, SR29, KR1); + RIP4(A, B, C, D, E, WR30, SR30, KR1); + RIP4(E, A, B, C, D, WR31, SR31, KR1); + + RIP3(D, E, A, B, C, WR32, SR32, KR2); + RIP3(C, D, E, A, B, WR33, SR33, KR2); + RIP3(B, C, D, E, A, WR34, SR34, KR2); + RIP3(A, B, C, D, E, WR35, SR35, KR2); + RIP3(E, A, B, C, D, WR36, SR36, KR2); + RIP3(D, E, A, B, C, WR37, SR37, KR2); + RIP3(C, D, E, A, B, WR38, SR38, KR2); + RIP3(B, C, D, E, A, WR39, SR39, KR2); + RIP3(A, B, C, D, E, WR40, SR40, KR2); + RIP3(E, A, B, C, D, WR41, SR41, KR2); + RIP3(D, E, A, B, C, WR42, SR42, KR2); + RIP3(C, D, E, A, B, WR43, SR43, KR2); + RIP3(B, C, D, E, A, WR44, SR44, KR2); + RIP3(A, B, C, D, E, WR45, SR45, KR2); + RIP3(E, A, B, C, D, WR46, SR46, KR2); + RIP3(D, E, A, B, C, WR47, SR47, KR2); + + RIP2(C, D, E, A, B, WR48, SR48, KR3); + RIP2(B, C, D, E, A, WR49, SR49, KR3); + RIP2(A, B, C, D, E, WR50, SR50, KR3); + RIP2(E, A, B, C, D, WR51, SR51, KR3); + RIP2(D, E, A, B, C, WR52, SR52, KR3); + RIP2(C, D, E, A, B, WR53, SR53, KR3); + RIP2(B, C, D, E, A, WR54, SR54, KR3); + RIP2(A, B, C, D, E, WR55, SR55, KR3); + RIP2(E, A, B, C, D, WR56, SR56, KR3); + RIP2(D, E, A, B, C, WR57, SR57, KR3); + RIP2(C, D, E, A, B, WR58, SR58, KR3); + RIP2(B, C, D, E, A, WR59, SR59, KR3); + RIP2(A, B, C, D, E, WR60, SR60, KR3); + RIP2(E, A, B, C, D, WR61, SR61, KR3); + RIP2(D, E, A, B, C, WR62, SR62, KR3); + RIP2(C, D, E, A, B, WR63, SR63, KR3); + + RIP1(B, C, D, E, A, WR64, SR64); + RIP1(A, B, C, D, E, WR65, SR65); + RIP1(E, A, B, C, D, WR66, SR66); + RIP1(D, E, A, B, C, WR67, SR67); + RIP1(C, D, E, A, B, WR68, SR68); + RIP1(B, C, D, E, A, WR69, SR69); + RIP1(A, B, C, D, E, WR70, SR70); + RIP1(E, A, B, C, D, WR71, SR71); + RIP1(D, E, A, B, C, WR72, SR72); + RIP1(C, D, E, A, B, WR73, SR73); + RIP1(B, C, D, E, A, WR74, SR74); + RIP1(A, B, C, D, E, WR75, SR75); + RIP1(E, A, B, C, D, WR76, SR76); + RIP1(D, E, A, B, C, WR77, SR77); + RIP1(C, D, E, A, B, WR78, SR78); + RIP1(B, C, D, E, A, WR79, SR79); + + D = ctx->B + c + D; + ctx->B = ctx->C + d + E; + ctx->C = ctx->D + e + A; + ctx->D = ctx->E + a + B; + ctx->E = ctx->A + b + C; + ctx->A = D; + + } +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ripemd/rmd_locl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/ripemd/rmd_locl.h new file mode 100644 index 000000000..f1ae4323c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ripemd/rmd_locl.h @@ -0,0 +1,87 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include + +/* + * DO EXAMINE COMMENTS IN crypto/md5/md5_locl.h & crypto/md5/md5_dgst.c + * FOR EXPLANATIONS ON FOLLOWING "CODE." + */ +#ifdef RMD160_ASM +# if defined(__i386) || defined(__i386__) || defined(_M_IX86) +# define ripemd160_block_data_order ripemd160_block_asm_data_order +# endif +#endif + +void ripemd160_block_data_order(RIPEMD160_CTX *c, const void *p, size_t num); + +#define DATA_ORDER_IS_LITTLE_ENDIAN + +#define HASH_LONG RIPEMD160_LONG +#define HASH_CTX RIPEMD160_CTX +#define HASH_CBLOCK RIPEMD160_CBLOCK +#define HASH_UPDATE RIPEMD160_Update +#define HASH_TRANSFORM RIPEMD160_Transform +#define HASH_FINAL RIPEMD160_Final +#define HASH_MAKE_STRING(c,s) do { \ + unsigned long ll; \ + ll=(c)->A; (void)HOST_l2c(ll,(s)); \ + ll=(c)->B; (void)HOST_l2c(ll,(s)); \ + ll=(c)->C; (void)HOST_l2c(ll,(s)); \ + ll=(c)->D; (void)HOST_l2c(ll,(s)); \ + ll=(c)->E; (void)HOST_l2c(ll,(s)); \ + } while (0) +#define HASH_BLOCK_DATA_ORDER ripemd160_block_data_order + +#include "internal/md32_common.h" + +/* + * Transformed F2 and F4 are courtesy of Wei Dai + */ +#define F1(x,y,z) ((x) ^ (y) ^ (z)) +#define F2(x,y,z) ((((y) ^ (z)) & (x)) ^ (z)) +#define F3(x,y,z) (((~(y)) | (x)) ^ (z)) +#define F4(x,y,z) ((((x) ^ (y)) & (z)) ^ (y)) +#define F5(x,y,z) (((~(z)) | (y)) ^ (x)) + +#define RIPEMD160_A 0x67452301L +#define RIPEMD160_B 0xEFCDAB89L +#define RIPEMD160_C 0x98BADCFEL +#define RIPEMD160_D 0x10325476L +#define RIPEMD160_E 0xC3D2E1F0L + +#include "rmdconst.h" + +#define RIP1(a,b,c,d,e,w,s) { \ + a+=F1(b,c,d)+X(w); \ + a=ROTATE(a,s)+e; \ + c=ROTATE(c,10); } + +#define RIP2(a,b,c,d,e,w,s,K) { \ + a+=F2(b,c,d)+X(w)+K; \ + a=ROTATE(a,s)+e; \ + c=ROTATE(c,10); } + +#define RIP3(a,b,c,d,e,w,s,K) { \ + a+=F3(b,c,d)+X(w)+K; \ + a=ROTATE(a,s)+e; \ + c=ROTATE(c,10); } + +#define RIP4(a,b,c,d,e,w,s,K) { \ + a+=F4(b,c,d)+X(w)+K; \ + a=ROTATE(a,s)+e; \ + c=ROTATE(c,10); } + +#define RIP5(a,b,c,d,e,w,s,K) { \ + a+=F5(b,c,d)+X(w)+K; \ + a=ROTATE(a,s)+e; \ + c=ROTATE(c,10); } diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ripemd/rmd_one.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ripemd/rmd_one.c new file mode 100644 index 000000000..cc01f15c7 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ripemd/rmd_one.c @@ -0,0 +1,28 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include + +unsigned char *RIPEMD160(const unsigned char *d, size_t n, unsigned char *md) +{ + RIPEMD160_CTX c; + static unsigned char m[RIPEMD160_DIGEST_LENGTH]; + + if (md == NULL) + md = m; + if (!RIPEMD160_Init(&c)) + return NULL; + RIPEMD160_Update(&c, d, n); + RIPEMD160_Final(md, &c); + OPENSSL_cleanse(&c, sizeof(c)); /* security consideration */ + return md; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ripemd/rmdconst.h b/trunk/3rdparty/openssl-1.1-fit/crypto/ripemd/rmdconst.h new file mode 100644 index 000000000..b81013239 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ripemd/rmdconst.h @@ -0,0 +1,350 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#define KL0 0x00000000L +#define KL1 0x5A827999L +#define KL2 0x6ED9EBA1L +#define KL3 0x8F1BBCDCL +#define KL4 0xA953FD4EL + +#define KR0 0x50A28BE6L +#define KR1 0x5C4DD124L +#define KR2 0x6D703EF3L +#define KR3 0x7A6D76E9L +#define KR4 0x00000000L + +#define WL00 0 +#define SL00 11 +#define WL01 1 +#define SL01 14 +#define WL02 2 +#define SL02 15 +#define WL03 3 +#define SL03 12 +#define WL04 4 +#define SL04 5 +#define WL05 5 +#define SL05 8 +#define WL06 6 +#define SL06 7 +#define WL07 7 +#define SL07 9 +#define WL08 8 +#define SL08 11 +#define WL09 9 +#define SL09 13 +#define WL10 10 +#define SL10 14 +#define WL11 11 +#define SL11 15 +#define WL12 12 +#define SL12 6 +#define WL13 13 +#define SL13 7 +#define WL14 14 +#define SL14 9 +#define WL15 15 +#define SL15 8 + +#define WL16 7 +#define SL16 7 +#define WL17 4 +#define SL17 6 +#define WL18 13 +#define SL18 8 +#define WL19 1 +#define SL19 13 +#define WL20 10 +#define SL20 11 +#define WL21 6 +#define SL21 9 +#define WL22 15 +#define SL22 7 +#define WL23 3 +#define SL23 15 +#define WL24 12 +#define SL24 7 +#define WL25 0 +#define SL25 12 +#define WL26 9 +#define SL26 15 +#define WL27 5 +#define SL27 9 +#define WL28 2 +#define SL28 11 +#define WL29 14 +#define SL29 7 +#define WL30 11 +#define SL30 13 +#define WL31 8 +#define SL31 12 + +#define WL32 3 +#define SL32 11 +#define WL33 10 +#define SL33 13 +#define WL34 14 +#define SL34 6 +#define WL35 4 +#define SL35 7 +#define WL36 9 +#define SL36 14 +#define WL37 15 +#define SL37 9 +#define WL38 8 +#define SL38 13 +#define WL39 1 +#define SL39 15 +#define WL40 2 +#define SL40 14 +#define WL41 7 +#define SL41 8 +#define WL42 0 +#define SL42 13 +#define WL43 6 +#define SL43 6 +#define WL44 13 +#define SL44 5 +#define WL45 11 +#define SL45 12 +#define WL46 5 +#define SL46 7 +#define WL47 12 +#define SL47 5 + +#define WL48 1 +#define SL48 11 +#define WL49 9 +#define SL49 12 +#define WL50 11 +#define SL50 14 +#define WL51 10 +#define SL51 15 +#define WL52 0 +#define SL52 14 +#define WL53 8 +#define SL53 15 +#define WL54 12 +#define SL54 9 +#define WL55 4 +#define SL55 8 +#define WL56 13 +#define SL56 9 +#define WL57 3 +#define SL57 14 +#define WL58 7 +#define SL58 5 +#define WL59 15 +#define SL59 6 +#define WL60 14 +#define SL60 8 +#define WL61 5 +#define SL61 6 +#define WL62 6 +#define SL62 5 +#define WL63 2 +#define SL63 12 + +#define WL64 4 +#define SL64 9 +#define WL65 0 +#define SL65 15 +#define WL66 5 +#define SL66 5 +#define WL67 9 +#define SL67 11 +#define WL68 7 +#define SL68 6 +#define WL69 12 +#define SL69 8 +#define WL70 2 +#define SL70 13 +#define WL71 10 +#define SL71 12 +#define WL72 14 +#define SL72 5 +#define WL73 1 +#define SL73 12 +#define WL74 3 +#define SL74 13 +#define WL75 8 +#define SL75 14 +#define WL76 11 +#define SL76 11 +#define WL77 6 +#define SL77 8 +#define WL78 15 +#define SL78 5 +#define WL79 13 +#define SL79 6 + +#define WR00 5 +#define SR00 8 +#define WR01 14 +#define SR01 9 +#define WR02 7 +#define SR02 9 +#define WR03 0 +#define SR03 11 +#define WR04 9 +#define SR04 13 +#define WR05 2 +#define SR05 15 +#define WR06 11 +#define SR06 15 +#define WR07 4 +#define SR07 5 +#define WR08 13 +#define SR08 7 +#define WR09 6 +#define SR09 7 +#define WR10 15 +#define SR10 8 +#define WR11 8 +#define SR11 11 +#define WR12 1 +#define SR12 14 +#define WR13 10 +#define SR13 14 +#define WR14 3 +#define SR14 12 +#define WR15 12 +#define SR15 6 + +#define WR16 6 +#define SR16 9 +#define WR17 11 +#define SR17 13 +#define WR18 3 +#define SR18 15 +#define WR19 7 +#define SR19 7 +#define WR20 0 +#define SR20 12 +#define WR21 13 +#define SR21 8 +#define WR22 5 +#define SR22 9 +#define WR23 10 +#define SR23 11 +#define WR24 14 +#define SR24 7 +#define WR25 15 +#define SR25 7 +#define WR26 8 +#define SR26 12 +#define WR27 12 +#define SR27 7 +#define WR28 4 +#define SR28 6 +#define WR29 9 +#define SR29 15 +#define WR30 1 +#define SR30 13 +#define WR31 2 +#define SR31 11 + +#define WR32 15 +#define SR32 9 +#define WR33 5 +#define SR33 7 +#define WR34 1 +#define SR34 15 +#define WR35 3 +#define SR35 11 +#define WR36 7 +#define SR36 8 +#define WR37 14 +#define SR37 6 +#define WR38 6 +#define SR38 6 +#define WR39 9 +#define SR39 14 +#define WR40 11 +#define SR40 12 +#define WR41 8 +#define SR41 13 +#define WR42 12 +#define SR42 5 +#define WR43 2 +#define SR43 14 +#define WR44 10 +#define SR44 13 +#define WR45 0 +#define SR45 13 +#define WR46 4 +#define SR46 7 +#define WR47 13 +#define SR47 5 + +#define WR48 8 +#define SR48 15 +#define WR49 6 +#define SR49 5 +#define WR50 4 +#define SR50 8 +#define WR51 1 +#define SR51 11 +#define WR52 3 +#define SR52 14 +#define WR53 11 +#define SR53 14 +#define WR54 15 +#define SR54 6 +#define WR55 0 +#define SR55 14 +#define WR56 5 +#define SR56 6 +#define WR57 12 +#define SR57 9 +#define WR58 2 +#define SR58 12 +#define WR59 13 +#define SR59 9 +#define WR60 9 +#define SR60 12 +#define WR61 7 +#define SR61 5 +#define WR62 10 +#define SR62 15 +#define WR63 14 +#define SR63 8 + +#define WR64 12 +#define SR64 8 +#define WR65 15 +#define SR65 5 +#define WR66 10 +#define SR66 12 +#define WR67 4 +#define SR67 9 +#define WR68 1 +#define SR68 12 +#define WR69 5 +#define SR69 5 +#define WR70 8 +#define SR70 14 +#define WR71 7 +#define SR71 6 +#define WR72 6 +#define SR72 8 +#define WR73 2 +#define SR73 13 +#define WR74 13 +#define SR74 6 +#define WR75 14 +#define SR75 5 +#define WR76 0 +#define SR76 15 +#define WR77 3 +#define SR77 13 +#define WR78 9 +#define SR78 11 +#define WR79 11 +#define SR79 11 diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/build.info new file mode 100644 index 000000000..87f924922 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/build.info @@ -0,0 +1,6 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + rsa_ossl.c rsa_gen.c rsa_lib.c rsa_sign.c rsa_saos.c rsa_err.c \ + rsa_pk1.c rsa_ssl.c rsa_none.c rsa_oaep.c rsa_chk.c \ + rsa_pss.c rsa_x931.c rsa_asn1.c rsa_depr.c rsa_ameth.c rsa_prn.c \ + rsa_pmeth.c rsa_crpt.c rsa_x931g.c rsa_meth.c rsa_mp.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_ameth.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_ameth.c new file mode 100644 index 000000000..75debb3e0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_ameth.c @@ -0,0 +1,1105 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "internal/asn1_int.h" +#include "internal/evp_int.h" +#include "rsa_locl.h" + +#ifndef OPENSSL_NO_CMS +static int rsa_cms_sign(CMS_SignerInfo *si); +static int rsa_cms_verify(CMS_SignerInfo *si); +static int rsa_cms_decrypt(CMS_RecipientInfo *ri); +static int rsa_cms_encrypt(CMS_RecipientInfo *ri); +#endif + +static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg); + +/* Set any parameters associated with pkey */ +static int rsa_param_encode(const EVP_PKEY *pkey, + ASN1_STRING **pstr, int *pstrtype) +{ + const RSA *rsa = pkey->pkey.rsa; + + *pstr = NULL; + /* If RSA it's just NULL type */ + if (pkey->ameth->pkey_id != EVP_PKEY_RSA_PSS) { + *pstrtype = V_ASN1_NULL; + return 1; + } + /* If no PSS parameters we omit parameters entirely */ + if (rsa->pss == NULL) { + *pstrtype = V_ASN1_UNDEF; + return 1; + } + /* Encode PSS parameters */ + if (ASN1_item_pack(rsa->pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), pstr) == NULL) + return 0; + + *pstrtype = V_ASN1_SEQUENCE; + return 1; +} +/* Decode any parameters and set them in RSA structure */ +static int rsa_param_decode(RSA *rsa, const X509_ALGOR *alg) +{ + const ASN1_OBJECT *algoid; + const void *algp; + int algptype; + + X509_ALGOR_get0(&algoid, &algptype, &algp, alg); + if (OBJ_obj2nid(algoid) != EVP_PKEY_RSA_PSS) + return 1; + if (algptype == V_ASN1_UNDEF) + return 1; + if (algptype != V_ASN1_SEQUENCE) { + RSAerr(RSA_F_RSA_PARAM_DECODE, RSA_R_INVALID_PSS_PARAMETERS); + return 0; + } + rsa->pss = rsa_pss_decode(alg); + if (rsa->pss == NULL) + return 0; + return 1; +} + +static int rsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) +{ + unsigned char *penc = NULL; + int penclen; + ASN1_STRING *str; + int strtype; + + if (!rsa_param_encode(pkey, &str, &strtype)) + return 0; + penclen = i2d_RSAPublicKey(pkey->pkey.rsa, &penc); + if (penclen <= 0) + return 0; + if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(pkey->ameth->pkey_id), + strtype, str, penc, penclen)) + return 1; + + OPENSSL_free(penc); + return 0; +} + +static int rsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) +{ + const unsigned char *p; + int pklen; + X509_ALGOR *alg; + RSA *rsa = NULL; + + if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &alg, pubkey)) + return 0; + if ((rsa = d2i_RSAPublicKey(NULL, &p, pklen)) == NULL) { + RSAerr(RSA_F_RSA_PUB_DECODE, ERR_R_RSA_LIB); + return 0; + } + if (!rsa_param_decode(rsa, alg)) { + RSA_free(rsa); + return 0; + } + if (!EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, rsa)) { + RSA_free(rsa); + return 0; + } + return 1; +} + +static int rsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) +{ + if (BN_cmp(b->pkey.rsa->n, a->pkey.rsa->n) != 0 + || BN_cmp(b->pkey.rsa->e, a->pkey.rsa->e) != 0) + return 0; + return 1; +} + +static int old_rsa_priv_decode(EVP_PKEY *pkey, + const unsigned char **pder, int derlen) +{ + RSA *rsa; + + if ((rsa = d2i_RSAPrivateKey(NULL, pder, derlen)) == NULL) { + RSAerr(RSA_F_OLD_RSA_PRIV_DECODE, ERR_R_RSA_LIB); + return 0; + } + EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, rsa); + return 1; +} + +static int old_rsa_priv_encode(const EVP_PKEY *pkey, unsigned char **pder) +{ + return i2d_RSAPrivateKey(pkey->pkey.rsa, pder); +} + +static int rsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) +{ + unsigned char *rk = NULL; + int rklen; + ASN1_STRING *str; + int strtype; + + if (!rsa_param_encode(pkey, &str, &strtype)) + return 0; + rklen = i2d_RSAPrivateKey(pkey->pkey.rsa, &rk); + + if (rklen <= 0) { + RSAerr(RSA_F_RSA_PRIV_ENCODE, ERR_R_MALLOC_FAILURE); + ASN1_STRING_free(str); + return 0; + } + + if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(pkey->ameth->pkey_id), 0, + strtype, str, rk, rklen)) { + RSAerr(RSA_F_RSA_PRIV_ENCODE, ERR_R_MALLOC_FAILURE); + ASN1_STRING_free(str); + return 0; + } + + return 1; +} + +static int rsa_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8) +{ + const unsigned char *p; + RSA *rsa; + int pklen; + const X509_ALGOR *alg; + + if (!PKCS8_pkey_get0(NULL, &p, &pklen, &alg, p8)) + return 0; + rsa = d2i_RSAPrivateKey(NULL, &p, pklen); + if (rsa == NULL) { + RSAerr(RSA_F_RSA_PRIV_DECODE, ERR_R_RSA_LIB); + return 0; + } + if (!rsa_param_decode(rsa, alg)) { + RSA_free(rsa); + return 0; + } + EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, rsa); + return 1; +} + +static int int_rsa_size(const EVP_PKEY *pkey) +{ + return RSA_size(pkey->pkey.rsa); +} + +static int rsa_bits(const EVP_PKEY *pkey) +{ + return BN_num_bits(pkey->pkey.rsa->n); +} + +static int rsa_security_bits(const EVP_PKEY *pkey) +{ + return RSA_security_bits(pkey->pkey.rsa); +} + +static void int_rsa_free(EVP_PKEY *pkey) +{ + RSA_free(pkey->pkey.rsa); +} + +static X509_ALGOR *rsa_mgf1_decode(X509_ALGOR *alg) +{ + if (OBJ_obj2nid(alg->algorithm) != NID_mgf1) + return NULL; + return ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(X509_ALGOR), + alg->parameter); +} + +static int rsa_pss_param_print(BIO *bp, int pss_key, RSA_PSS_PARAMS *pss, + int indent) +{ + int rv = 0; + X509_ALGOR *maskHash = NULL; + + if (!BIO_indent(bp, indent, 128)) + goto err; + if (pss_key) { + if (pss == NULL) { + if (BIO_puts(bp, "No PSS parameter restrictions\n") <= 0) + return 0; + return 1; + } else { + if (BIO_puts(bp, "PSS parameter restrictions:") <= 0) + return 0; + } + } else if (pss == NULL) { + if (BIO_puts(bp,"(INVALID PSS PARAMETERS)\n") <= 0) + return 0; + return 1; + } + if (BIO_puts(bp, "\n") <= 0) + goto err; + if (pss_key) + indent += 2; + if (!BIO_indent(bp, indent, 128)) + goto err; + if (BIO_puts(bp, "Hash Algorithm: ") <= 0) + goto err; + + if (pss->hashAlgorithm) { + if (i2a_ASN1_OBJECT(bp, pss->hashAlgorithm->algorithm) <= 0) + goto err; + } else if (BIO_puts(bp, "sha1 (default)") <= 0) { + goto err; + } + + if (BIO_puts(bp, "\n") <= 0) + goto err; + + if (!BIO_indent(bp, indent, 128)) + goto err; + + if (BIO_puts(bp, "Mask Algorithm: ") <= 0) + goto err; + if (pss->maskGenAlgorithm) { + if (i2a_ASN1_OBJECT(bp, pss->maskGenAlgorithm->algorithm) <= 0) + goto err; + if (BIO_puts(bp, " with ") <= 0) + goto err; + maskHash = rsa_mgf1_decode(pss->maskGenAlgorithm); + if (maskHash != NULL) { + if (i2a_ASN1_OBJECT(bp, maskHash->algorithm) <= 0) + goto err; + } else if (BIO_puts(bp, "INVALID") <= 0) { + goto err; + } + } else if (BIO_puts(bp, "mgf1 with sha1 (default)") <= 0) { + goto err; + } + BIO_puts(bp, "\n"); + + if (!BIO_indent(bp, indent, 128)) + goto err; + if (BIO_printf(bp, "%s Salt Length: 0x", pss_key ? "Minimum" : "") <= 0) + goto err; + if (pss->saltLength) { + if (i2a_ASN1_INTEGER(bp, pss->saltLength) <= 0) + goto err; + } else if (BIO_puts(bp, "14 (default)") <= 0) { + goto err; + } + BIO_puts(bp, "\n"); + + if (!BIO_indent(bp, indent, 128)) + goto err; + if (BIO_puts(bp, "Trailer Field: 0x") <= 0) + goto err; + if (pss->trailerField) { + if (i2a_ASN1_INTEGER(bp, pss->trailerField) <= 0) + goto err; + } else if (BIO_puts(bp, "BC (default)") <= 0) { + goto err; + } + BIO_puts(bp, "\n"); + + rv = 1; + + err: + X509_ALGOR_free(maskHash); + return rv; + +} + +static int pkey_rsa_print(BIO *bp, const EVP_PKEY *pkey, int off, int priv) +{ + const RSA *x = pkey->pkey.rsa; + char *str; + const char *s; + int ret = 0, mod_len = 0, ex_primes; + + if (x->n != NULL) + mod_len = BN_num_bits(x->n); + ex_primes = sk_RSA_PRIME_INFO_num(x->prime_infos); + + if (!BIO_indent(bp, off, 128)) + goto err; + + if (BIO_printf(bp, "%s ", pkey_is_pss(pkey) ? "RSA-PSS" : "RSA") <= 0) + goto err; + + if (priv && x->d) { + if (BIO_printf(bp, "Private-Key: (%d bit, %d primes)\n", + mod_len, ex_primes <= 0 ? 2 : ex_primes + 2) <= 0) + goto err; + str = "modulus:"; + s = "publicExponent:"; + } else { + if (BIO_printf(bp, "Public-Key: (%d bit)\n", mod_len) <= 0) + goto err; + str = "Modulus:"; + s = "Exponent:"; + } + if (!ASN1_bn_print(bp, str, x->n, NULL, off)) + goto err; + if (!ASN1_bn_print(bp, s, x->e, NULL, off)) + goto err; + if (priv) { + int i; + + if (!ASN1_bn_print(bp, "privateExponent:", x->d, NULL, off)) + goto err; + if (!ASN1_bn_print(bp, "prime1:", x->p, NULL, off)) + goto err; + if (!ASN1_bn_print(bp, "prime2:", x->q, NULL, off)) + goto err; + if (!ASN1_bn_print(bp, "exponent1:", x->dmp1, NULL, off)) + goto err; + if (!ASN1_bn_print(bp, "exponent2:", x->dmq1, NULL, off)) + goto err; + if (!ASN1_bn_print(bp, "coefficient:", x->iqmp, NULL, off)) + goto err; + for (i = 0; i < sk_RSA_PRIME_INFO_num(x->prime_infos); i++) { + /* print multi-prime info */ + BIGNUM *bn = NULL; + RSA_PRIME_INFO *pinfo; + int j; + + pinfo = sk_RSA_PRIME_INFO_value(x->prime_infos, i); + for (j = 0; j < 3; j++) { + if (!BIO_indent(bp, off, 128)) + goto err; + switch (j) { + case 0: + if (BIO_printf(bp, "prime%d:", i + 3) <= 0) + goto err; + bn = pinfo->r; + break; + case 1: + if (BIO_printf(bp, "exponent%d:", i + 3) <= 0) + goto err; + bn = pinfo->d; + break; + case 2: + if (BIO_printf(bp, "coefficient%d:", i + 3) <= 0) + goto err; + bn = pinfo->t; + break; + default: + break; + } + if (!ASN1_bn_print(bp, "", bn, NULL, off)) + goto err; + } + } + } + if (pkey_is_pss(pkey) && !rsa_pss_param_print(bp, 1, x->pss, off)) + goto err; + ret = 1; + err: + return ret; +} + +static int rsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *ctx) +{ + return pkey_rsa_print(bp, pkey, indent, 0); +} + +static int rsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *ctx) +{ + return pkey_rsa_print(bp, pkey, indent, 1); +} + +static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg) +{ + RSA_PSS_PARAMS *pss; + + pss = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(RSA_PSS_PARAMS), + alg->parameter); + + if (pss == NULL) + return NULL; + + if (pss->maskGenAlgorithm != NULL) { + pss->maskHash = rsa_mgf1_decode(pss->maskGenAlgorithm); + if (pss->maskHash == NULL) { + RSA_PSS_PARAMS_free(pss); + return NULL; + } + } + + return pss; +} + +static int rsa_sig_print(BIO *bp, const X509_ALGOR *sigalg, + const ASN1_STRING *sig, int indent, ASN1_PCTX *pctx) +{ + if (OBJ_obj2nid(sigalg->algorithm) == EVP_PKEY_RSA_PSS) { + int rv; + RSA_PSS_PARAMS *pss = rsa_pss_decode(sigalg); + + rv = rsa_pss_param_print(bp, 0, pss, indent); + RSA_PSS_PARAMS_free(pss); + if (!rv) + return 0; + } else if (!sig && BIO_puts(bp, "\n") <= 0) { + return 0; + } + if (sig) + return X509_signature_dump(bp, sig, indent); + return 1; +} + +static int rsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) +{ + X509_ALGOR *alg = NULL; + + switch (op) { + + case ASN1_PKEY_CTRL_PKCS7_SIGN: + if (arg1 == 0) + PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, NULL, &alg); + break; + + case ASN1_PKEY_CTRL_PKCS7_ENCRYPT: + if (pkey_is_pss(pkey)) + return -2; + if (arg1 == 0) + PKCS7_RECIP_INFO_get0_alg(arg2, &alg); + break; +#ifndef OPENSSL_NO_CMS + case ASN1_PKEY_CTRL_CMS_SIGN: + if (arg1 == 0) + return rsa_cms_sign(arg2); + else if (arg1 == 1) + return rsa_cms_verify(arg2); + break; + + case ASN1_PKEY_CTRL_CMS_ENVELOPE: + if (pkey_is_pss(pkey)) + return -2; + if (arg1 == 0) + return rsa_cms_encrypt(arg2); + else if (arg1 == 1) + return rsa_cms_decrypt(arg2); + break; + + case ASN1_PKEY_CTRL_CMS_RI_TYPE: + if (pkey_is_pss(pkey)) + return -2; + *(int *)arg2 = CMS_RECIPINFO_TRANS; + return 1; +#endif + + case ASN1_PKEY_CTRL_DEFAULT_MD_NID: + *(int *)arg2 = NID_sha256; + return 1; + + default: + return -2; + + } + + if (alg) + X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0); + + return 1; + +} + +/* allocate and set algorithm ID from EVP_MD, default SHA1 */ +static int rsa_md_to_algor(X509_ALGOR **palg, const EVP_MD *md) +{ + if (md == NULL || EVP_MD_type(md) == NID_sha1) + return 1; + *palg = X509_ALGOR_new(); + if (*palg == NULL) + return 0; + X509_ALGOR_set_md(*palg, md); + return 1; +} + +/* Allocate and set MGF1 algorithm ID from EVP_MD */ +static int rsa_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md) +{ + X509_ALGOR *algtmp = NULL; + ASN1_STRING *stmp = NULL; + + *palg = NULL; + if (mgf1md == NULL || EVP_MD_type(mgf1md) == NID_sha1) + return 1; + /* need to embed algorithm ID inside another */ + if (!rsa_md_to_algor(&algtmp, mgf1md)) + goto err; + if (ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp) == NULL) + goto err; + *palg = X509_ALGOR_new(); + if (*palg == NULL) + goto err; + X509_ALGOR_set0(*palg, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, stmp); + stmp = NULL; + err: + ASN1_STRING_free(stmp); + X509_ALGOR_free(algtmp); + if (*palg) + return 1; + return 0; +} + +/* convert algorithm ID to EVP_MD, default SHA1 */ +static const EVP_MD *rsa_algor_to_md(X509_ALGOR *alg) +{ + const EVP_MD *md; + + if (!alg) + return EVP_sha1(); + md = EVP_get_digestbyobj(alg->algorithm); + if (md == NULL) + RSAerr(RSA_F_RSA_ALGOR_TO_MD, RSA_R_UNKNOWN_DIGEST); + return md; +} + +/* + * Convert EVP_PKEY_CTX in PSS mode into corresponding algorithm parameter, + * suitable for setting an AlgorithmIdentifier. + */ + +static RSA_PSS_PARAMS *rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx) +{ + const EVP_MD *sigmd, *mgf1md; + EVP_PKEY *pk = EVP_PKEY_CTX_get0_pkey(pkctx); + int saltlen; + + if (EVP_PKEY_CTX_get_signature_md(pkctx, &sigmd) <= 0) + return NULL; + if (EVP_PKEY_CTX_get_rsa_mgf1_md(pkctx, &mgf1md) <= 0) + return NULL; + if (!EVP_PKEY_CTX_get_rsa_pss_saltlen(pkctx, &saltlen)) + return NULL; + if (saltlen == -1) { + saltlen = EVP_MD_size(sigmd); + } else if (saltlen == -2) { + saltlen = EVP_PKEY_size(pk) - EVP_MD_size(sigmd) - 2; + if ((EVP_PKEY_bits(pk) & 0x7) == 1) + saltlen--; + } + + return rsa_pss_params_create(sigmd, mgf1md, saltlen); +} + +RSA_PSS_PARAMS *rsa_pss_params_create(const EVP_MD *sigmd, + const EVP_MD *mgf1md, int saltlen) +{ + RSA_PSS_PARAMS *pss = RSA_PSS_PARAMS_new(); + + if (pss == NULL) + goto err; + if (saltlen != 20) { + pss->saltLength = ASN1_INTEGER_new(); + if (pss->saltLength == NULL) + goto err; + if (!ASN1_INTEGER_set(pss->saltLength, saltlen)) + goto err; + } + if (!rsa_md_to_algor(&pss->hashAlgorithm, sigmd)) + goto err; + if (mgf1md == NULL) + mgf1md = sigmd; + if (!rsa_md_to_mgf1(&pss->maskGenAlgorithm, mgf1md)) + goto err; + if (!rsa_md_to_algor(&pss->maskHash, mgf1md)) + goto err; + return pss; + err: + RSA_PSS_PARAMS_free(pss); + return NULL; +} + +static ASN1_STRING *rsa_ctx_to_pss_string(EVP_PKEY_CTX *pkctx) +{ + RSA_PSS_PARAMS *pss = rsa_ctx_to_pss(pkctx); + ASN1_STRING *os; + + if (pss == NULL) + return NULL; + + os = ASN1_item_pack(pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), NULL); + RSA_PSS_PARAMS_free(pss); + return os; +} + +/* + * From PSS AlgorithmIdentifier set public key parameters. If pkey isn't NULL + * then the EVP_MD_CTX is setup and initialised. If it is NULL parameters are + * passed to pkctx instead. + */ + +static int rsa_pss_to_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pkctx, + X509_ALGOR *sigalg, EVP_PKEY *pkey) +{ + int rv = -1; + int saltlen; + const EVP_MD *mgf1md = NULL, *md = NULL; + RSA_PSS_PARAMS *pss; + + /* Sanity check: make sure it is PSS */ + if (OBJ_obj2nid(sigalg->algorithm) != EVP_PKEY_RSA_PSS) { + RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_UNSUPPORTED_SIGNATURE_TYPE); + return -1; + } + /* Decode PSS parameters */ + pss = rsa_pss_decode(sigalg); + + if (!rsa_pss_get_param(pss, &md, &mgf1md, &saltlen)) { + RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_INVALID_PSS_PARAMETERS); + goto err; + } + + /* We have all parameters now set up context */ + if (pkey) { + if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey)) + goto err; + } else { + const EVP_MD *checkmd; + if (EVP_PKEY_CTX_get_signature_md(pkctx, &checkmd) <= 0) + goto err; + if (EVP_MD_type(md) != EVP_MD_type(checkmd)) { + RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_DIGEST_DOES_NOT_MATCH); + goto err; + } + } + + if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) <= 0) + goto err; + + if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) <= 0) + goto err; + + if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0) + goto err; + /* Carry on */ + rv = 1; + + err: + RSA_PSS_PARAMS_free(pss); + return rv; +} + +int rsa_pss_get_param(const RSA_PSS_PARAMS *pss, const EVP_MD **pmd, + const EVP_MD **pmgf1md, int *psaltlen) +{ + if (pss == NULL) + return 0; + *pmd = rsa_algor_to_md(pss->hashAlgorithm); + if (*pmd == NULL) + return 0; + *pmgf1md = rsa_algor_to_md(pss->maskHash); + if (*pmgf1md == NULL) + return 0; + if (pss->saltLength) { + *psaltlen = ASN1_INTEGER_get(pss->saltLength); + if (*psaltlen < 0) { + RSAerr(RSA_F_RSA_PSS_GET_PARAM, RSA_R_INVALID_SALT_LENGTH); + return 0; + } + } else { + *psaltlen = 20; + } + + /* + * low-level routines support only trailer field 0xbc (value 1) and + * PKCS#1 says we should reject any other value anyway. + */ + if (pss->trailerField && ASN1_INTEGER_get(pss->trailerField) != 1) { + RSAerr(RSA_F_RSA_PSS_GET_PARAM, RSA_R_INVALID_TRAILER); + return 0; + } + + return 1; +} + +#ifndef OPENSSL_NO_CMS +static int rsa_cms_verify(CMS_SignerInfo *si) +{ + int nid, nid2; + X509_ALGOR *alg; + EVP_PKEY_CTX *pkctx = CMS_SignerInfo_get0_pkey_ctx(si); + + CMS_SignerInfo_get0_algs(si, NULL, NULL, NULL, &alg); + nid = OBJ_obj2nid(alg->algorithm); + if (nid == EVP_PKEY_RSA_PSS) + return rsa_pss_to_ctx(NULL, pkctx, alg, NULL); + /* Only PSS allowed for PSS keys */ + if (pkey_ctx_is_pss(pkctx)) { + RSAerr(RSA_F_RSA_CMS_VERIFY, RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE); + return 0; + } + if (nid == NID_rsaEncryption) + return 1; + /* Workaround for some implementation that use a signature OID */ + if (OBJ_find_sigid_algs(nid, NULL, &nid2)) { + if (nid2 == NID_rsaEncryption) + return 1; + } + return 0; +} +#endif + +/* + * Customised RSA item verification routine. This is called when a signature + * is encountered requiring special handling. We currently only handle PSS. + */ + +static int rsa_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn, + X509_ALGOR *sigalg, ASN1_BIT_STRING *sig, + EVP_PKEY *pkey) +{ + /* Sanity check: make sure it is PSS */ + if (OBJ_obj2nid(sigalg->algorithm) != EVP_PKEY_RSA_PSS) { + RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNSUPPORTED_SIGNATURE_TYPE); + return -1; + } + if (rsa_pss_to_ctx(ctx, NULL, sigalg, pkey) > 0) { + /* Carry on */ + return 2; + } + return -1; +} + +#ifndef OPENSSL_NO_CMS +static int rsa_cms_sign(CMS_SignerInfo *si) +{ + int pad_mode = RSA_PKCS1_PADDING; + X509_ALGOR *alg; + EVP_PKEY_CTX *pkctx = CMS_SignerInfo_get0_pkey_ctx(si); + ASN1_STRING *os = NULL; + + CMS_SignerInfo_get0_algs(si, NULL, NULL, NULL, &alg); + if (pkctx) { + if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0) + return 0; + } + if (pad_mode == RSA_PKCS1_PADDING) { + X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0); + return 1; + } + /* We don't support it */ + if (pad_mode != RSA_PKCS1_PSS_PADDING) + return 0; + os = rsa_ctx_to_pss_string(pkctx); + if (!os) + return 0; + X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_PKEY_RSA_PSS), V_ASN1_SEQUENCE, os); + return 1; +} +#endif + +static int rsa_item_sign(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn, + X509_ALGOR *alg1, X509_ALGOR *alg2, + ASN1_BIT_STRING *sig) +{ + int pad_mode; + EVP_PKEY_CTX *pkctx = EVP_MD_CTX_pkey_ctx(ctx); + + if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0) + return 0; + if (pad_mode == RSA_PKCS1_PADDING) + return 2; + if (pad_mode == RSA_PKCS1_PSS_PADDING) { + ASN1_STRING *os1 = NULL; + os1 = rsa_ctx_to_pss_string(pkctx); + if (!os1) + return 0; + /* Duplicate parameters if we have to */ + if (alg2) { + ASN1_STRING *os2 = ASN1_STRING_dup(os1); + if (!os2) { + ASN1_STRING_free(os1); + return 0; + } + X509_ALGOR_set0(alg2, OBJ_nid2obj(EVP_PKEY_RSA_PSS), + V_ASN1_SEQUENCE, os2); + } + X509_ALGOR_set0(alg1, OBJ_nid2obj(EVP_PKEY_RSA_PSS), + V_ASN1_SEQUENCE, os1); + return 3; + } + return 2; +} + +static int rsa_sig_info_set(X509_SIG_INFO *siginf, const X509_ALGOR *sigalg, + const ASN1_STRING *sig) +{ + int rv = 0; + int mdnid, saltlen; + uint32_t flags; + const EVP_MD *mgf1md = NULL, *md = NULL; + RSA_PSS_PARAMS *pss; + + /* Sanity check: make sure it is PSS */ + if (OBJ_obj2nid(sigalg->algorithm) != EVP_PKEY_RSA_PSS) + return 0; + /* Decode PSS parameters */ + pss = rsa_pss_decode(sigalg); + if (!rsa_pss_get_param(pss, &md, &mgf1md, &saltlen)) + goto err; + mdnid = EVP_MD_type(md); + /* + * For TLS need SHA256, SHA384 or SHA512, digest and MGF1 digest must + * match and salt length must equal digest size + */ + if ((mdnid == NID_sha256 || mdnid == NID_sha384 || mdnid == NID_sha512) + && mdnid == EVP_MD_type(mgf1md) && saltlen == EVP_MD_size(md)) + flags = X509_SIG_INFO_TLS; + else + flags = 0; + /* Note: security bits half number of digest bits */ + X509_SIG_INFO_set(siginf, mdnid, EVP_PKEY_RSA_PSS, EVP_MD_size(md) * 4, + flags); + rv = 1; + err: + RSA_PSS_PARAMS_free(pss); + return rv; +} + +#ifndef OPENSSL_NO_CMS +static RSA_OAEP_PARAMS *rsa_oaep_decode(const X509_ALGOR *alg) +{ + RSA_OAEP_PARAMS *oaep; + + oaep = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(RSA_OAEP_PARAMS), + alg->parameter); + + if (oaep == NULL) + return NULL; + + if (oaep->maskGenFunc != NULL) { + oaep->maskHash = rsa_mgf1_decode(oaep->maskGenFunc); + if (oaep->maskHash == NULL) { + RSA_OAEP_PARAMS_free(oaep); + return NULL; + } + } + return oaep; +} + +static int rsa_cms_decrypt(CMS_RecipientInfo *ri) +{ + EVP_PKEY_CTX *pkctx; + X509_ALGOR *cmsalg; + int nid; + int rv = -1; + unsigned char *label = NULL; + int labellen = 0; + const EVP_MD *mgf1md = NULL, *md = NULL; + RSA_OAEP_PARAMS *oaep; + + pkctx = CMS_RecipientInfo_get0_pkey_ctx(ri); + if (pkctx == NULL) + return 0; + if (!CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &cmsalg)) + return -1; + nid = OBJ_obj2nid(cmsalg->algorithm); + if (nid == NID_rsaEncryption) + return 1; + if (nid != NID_rsaesOaep) { + RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_UNSUPPORTED_ENCRYPTION_TYPE); + return -1; + } + /* Decode OAEP parameters */ + oaep = rsa_oaep_decode(cmsalg); + + if (oaep == NULL) { + RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_INVALID_OAEP_PARAMETERS); + goto err; + } + + mgf1md = rsa_algor_to_md(oaep->maskHash); + if (mgf1md == NULL) + goto err; + md = rsa_algor_to_md(oaep->hashFunc); + if (md == NULL) + goto err; + + if (oaep->pSourceFunc != NULL) { + X509_ALGOR *plab = oaep->pSourceFunc; + + if (OBJ_obj2nid(plab->algorithm) != NID_pSpecified) { + RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_UNSUPPORTED_LABEL_SOURCE); + goto err; + } + if (plab->parameter->type != V_ASN1_OCTET_STRING) { + RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_INVALID_LABEL); + goto err; + } + + label = plab->parameter->value.octet_string->data; + /* Stop label being freed when OAEP parameters are freed */ + plab->parameter->value.octet_string->data = NULL; + labellen = plab->parameter->value.octet_string->length; + } + + if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_OAEP_PADDING) <= 0) + goto err; + if (EVP_PKEY_CTX_set_rsa_oaep_md(pkctx, md) <= 0) + goto err; + if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0) + goto err; + if (EVP_PKEY_CTX_set0_rsa_oaep_label(pkctx, label, labellen) <= 0) + goto err; + /* Carry on */ + rv = 1; + + err: + RSA_OAEP_PARAMS_free(oaep); + return rv; +} + +static int rsa_cms_encrypt(CMS_RecipientInfo *ri) +{ + const EVP_MD *md, *mgf1md; + RSA_OAEP_PARAMS *oaep = NULL; + ASN1_STRING *os = NULL; + X509_ALGOR *alg; + EVP_PKEY_CTX *pkctx = CMS_RecipientInfo_get0_pkey_ctx(ri); + int pad_mode = RSA_PKCS1_PADDING, rv = 0, labellen; + unsigned char *label; + + if (CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &alg) <= 0) + return 0; + if (pkctx) { + if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0) + return 0; + } + if (pad_mode == RSA_PKCS1_PADDING) { + X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0); + return 1; + } + /* Not supported */ + if (pad_mode != RSA_PKCS1_OAEP_PADDING) + return 0; + if (EVP_PKEY_CTX_get_rsa_oaep_md(pkctx, &md) <= 0) + goto err; + if (EVP_PKEY_CTX_get_rsa_mgf1_md(pkctx, &mgf1md) <= 0) + goto err; + labellen = EVP_PKEY_CTX_get0_rsa_oaep_label(pkctx, &label); + if (labellen < 0) + goto err; + oaep = RSA_OAEP_PARAMS_new(); + if (oaep == NULL) + goto err; + if (!rsa_md_to_algor(&oaep->hashFunc, md)) + goto err; + if (!rsa_md_to_mgf1(&oaep->maskGenFunc, mgf1md)) + goto err; + if (labellen > 0) { + ASN1_OCTET_STRING *los; + oaep->pSourceFunc = X509_ALGOR_new(); + if (oaep->pSourceFunc == NULL) + goto err; + los = ASN1_OCTET_STRING_new(); + if (los == NULL) + goto err; + if (!ASN1_OCTET_STRING_set(los, label, labellen)) { + ASN1_OCTET_STRING_free(los); + goto err; + } + X509_ALGOR_set0(oaep->pSourceFunc, OBJ_nid2obj(NID_pSpecified), + V_ASN1_OCTET_STRING, los); + } + /* create string with pss parameter encoding. */ + if (!ASN1_item_pack(oaep, ASN1_ITEM_rptr(RSA_OAEP_PARAMS), &os)) + goto err; + X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaesOaep), V_ASN1_SEQUENCE, os); + os = NULL; + rv = 1; + err: + RSA_OAEP_PARAMS_free(oaep); + ASN1_STRING_free(os); + return rv; +} +#endif + +static int rsa_pkey_check(const EVP_PKEY *pkey) +{ + return RSA_check_key_ex(pkey->pkey.rsa, NULL); +} + +const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[2] = { + { + EVP_PKEY_RSA, + EVP_PKEY_RSA, + ASN1_PKEY_SIGPARAM_NULL, + + "RSA", + "OpenSSL RSA method", + + rsa_pub_decode, + rsa_pub_encode, + rsa_pub_cmp, + rsa_pub_print, + + rsa_priv_decode, + rsa_priv_encode, + rsa_priv_print, + + int_rsa_size, + rsa_bits, + rsa_security_bits, + + 0, 0, 0, 0, 0, 0, + + rsa_sig_print, + int_rsa_free, + rsa_pkey_ctrl, + old_rsa_priv_decode, + old_rsa_priv_encode, + rsa_item_verify, + rsa_item_sign, + rsa_sig_info_set, + rsa_pkey_check + }, + + { + EVP_PKEY_RSA2, + EVP_PKEY_RSA, + ASN1_PKEY_ALIAS} +}; + +const EVP_PKEY_ASN1_METHOD rsa_pss_asn1_meth = { + EVP_PKEY_RSA_PSS, + EVP_PKEY_RSA_PSS, + ASN1_PKEY_SIGPARAM_NULL, + + "RSA-PSS", + "OpenSSL RSA-PSS method", + + rsa_pub_decode, + rsa_pub_encode, + rsa_pub_cmp, + rsa_pub_print, + + rsa_priv_decode, + rsa_priv_encode, + rsa_priv_print, + + int_rsa_size, + rsa_bits, + rsa_security_bits, + + 0, 0, 0, 0, 0, 0, + + rsa_sig_print, + int_rsa_free, + rsa_pkey_ctrl, + 0, 0, + rsa_item_verify, + rsa_item_sign, + 0, + rsa_pkey_check +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_asn1.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_asn1.c new file mode 100644 index 000000000..9fe62c82e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_asn1.c @@ -0,0 +1,121 @@ +/* + * Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include "rsa_locl.h" + +/* + * Override the default free and new methods, + * and calculate helper products for multi-prime + * RSA keys. + */ +static int rsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + if (operation == ASN1_OP_NEW_PRE) { + *pval = (ASN1_VALUE *)RSA_new(); + if (*pval != NULL) + return 2; + return 0; + } else if (operation == ASN1_OP_FREE_PRE) { + RSA_free((RSA *)*pval); + *pval = NULL; + return 2; + } else if (operation == ASN1_OP_D2I_POST) { + if (((RSA *)*pval)->version != RSA_ASN1_VERSION_MULTI) { + /* not a multi-prime key, skip */ + return 1; + } + return (rsa_multip_calc_product((RSA *)*pval) == 1) ? 2 : 0; + } + return 1; +} + +/* Based on definitions in RFC 8017 appendix A.1.2 */ +ASN1_SEQUENCE(RSA_PRIME_INFO) = { + ASN1_SIMPLE(RSA_PRIME_INFO, r, CBIGNUM), + ASN1_SIMPLE(RSA_PRIME_INFO, d, CBIGNUM), + ASN1_SIMPLE(RSA_PRIME_INFO, t, CBIGNUM), +} ASN1_SEQUENCE_END(RSA_PRIME_INFO) + +ASN1_SEQUENCE_cb(RSAPrivateKey, rsa_cb) = { + ASN1_EMBED(RSA, version, INT32), + ASN1_SIMPLE(RSA, n, BIGNUM), + ASN1_SIMPLE(RSA, e, BIGNUM), + ASN1_SIMPLE(RSA, d, CBIGNUM), + ASN1_SIMPLE(RSA, p, CBIGNUM), + ASN1_SIMPLE(RSA, q, CBIGNUM), + ASN1_SIMPLE(RSA, dmp1, CBIGNUM), + ASN1_SIMPLE(RSA, dmq1, CBIGNUM), + ASN1_SIMPLE(RSA, iqmp, CBIGNUM), + ASN1_SEQUENCE_OF_OPT(RSA, prime_infos, RSA_PRIME_INFO) +} ASN1_SEQUENCE_END_cb(RSA, RSAPrivateKey) + + +ASN1_SEQUENCE_cb(RSAPublicKey, rsa_cb) = { + ASN1_SIMPLE(RSA, n, BIGNUM), + ASN1_SIMPLE(RSA, e, BIGNUM), +} ASN1_SEQUENCE_END_cb(RSA, RSAPublicKey) + +/* Free up maskHash */ +static int rsa_pss_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + if (operation == ASN1_OP_FREE_PRE) { + RSA_PSS_PARAMS *pss = (RSA_PSS_PARAMS *)*pval; + X509_ALGOR_free(pss->maskHash); + } + return 1; +} + +ASN1_SEQUENCE_cb(RSA_PSS_PARAMS, rsa_pss_cb) = { + ASN1_EXP_OPT(RSA_PSS_PARAMS, hashAlgorithm, X509_ALGOR,0), + ASN1_EXP_OPT(RSA_PSS_PARAMS, maskGenAlgorithm, X509_ALGOR,1), + ASN1_EXP_OPT(RSA_PSS_PARAMS, saltLength, ASN1_INTEGER,2), + ASN1_EXP_OPT(RSA_PSS_PARAMS, trailerField, ASN1_INTEGER,3) +} ASN1_SEQUENCE_END_cb(RSA_PSS_PARAMS, RSA_PSS_PARAMS) + +IMPLEMENT_ASN1_FUNCTIONS(RSA_PSS_PARAMS) + +/* Free up maskHash */ +static int rsa_oaep_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + if (operation == ASN1_OP_FREE_PRE) { + RSA_OAEP_PARAMS *oaep = (RSA_OAEP_PARAMS *)*pval; + X509_ALGOR_free(oaep->maskHash); + } + return 1; +} + +ASN1_SEQUENCE_cb(RSA_OAEP_PARAMS, rsa_oaep_cb) = { + ASN1_EXP_OPT(RSA_OAEP_PARAMS, hashFunc, X509_ALGOR, 0), + ASN1_EXP_OPT(RSA_OAEP_PARAMS, maskGenFunc, X509_ALGOR, 1), + ASN1_EXP_OPT(RSA_OAEP_PARAMS, pSourceFunc, X509_ALGOR, 2), +} ASN1_SEQUENCE_END_cb(RSA_OAEP_PARAMS, RSA_OAEP_PARAMS) + +IMPLEMENT_ASN1_FUNCTIONS(RSA_OAEP_PARAMS) + +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(RSA, RSAPrivateKey, RSAPrivateKey) + +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(RSA, RSAPublicKey, RSAPublicKey) + +RSA *RSAPublicKey_dup(RSA *rsa) +{ + return ASN1_item_dup(ASN1_ITEM_rptr(RSAPublicKey), rsa); +} + +RSA *RSAPrivateKey_dup(RSA *rsa) +{ + return ASN1_item_dup(ASN1_ITEM_rptr(RSAPrivateKey), rsa); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_chk.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_chk.c new file mode 100644 index 000000000..1b69be30c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_chk.c @@ -0,0 +1,228 @@ +/* + * Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "rsa_locl.h" + +int RSA_check_key(const RSA *key) +{ + return RSA_check_key_ex(key, NULL); +} + +int RSA_check_key_ex(const RSA *key, BN_GENCB *cb) +{ + BIGNUM *i, *j, *k, *l, *m; + BN_CTX *ctx; + int ret = 1, ex_primes = 0, idx; + RSA_PRIME_INFO *pinfo; + + if (key->p == NULL || key->q == NULL || key->n == NULL + || key->e == NULL || key->d == NULL) { + RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_VALUE_MISSING); + return 0; + } + + /* multi-prime? */ + if (key->version == RSA_ASN1_VERSION_MULTI) { + ex_primes = sk_RSA_PRIME_INFO_num(key->prime_infos); + if (ex_primes <= 0 + || (ex_primes + 2) > rsa_multip_cap(BN_num_bits(key->n))) { + RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_INVALID_MULTI_PRIME_KEY); + return 0; + } + } + + i = BN_new(); + j = BN_new(); + k = BN_new(); + l = BN_new(); + m = BN_new(); + ctx = BN_CTX_new(); + if (i == NULL || j == NULL || k == NULL || l == NULL + || m == NULL || ctx == NULL) { + ret = -1; + RSAerr(RSA_F_RSA_CHECK_KEY_EX, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (BN_is_one(key->e)) { + ret = 0; + RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_BAD_E_VALUE); + } + if (!BN_is_odd(key->e)) { + ret = 0; + RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_BAD_E_VALUE); + } + + /* p prime? */ + if (BN_is_prime_ex(key->p, BN_prime_checks, NULL, cb) != 1) { + ret = 0; + RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_P_NOT_PRIME); + } + + /* q prime? */ + if (BN_is_prime_ex(key->q, BN_prime_checks, NULL, cb) != 1) { + ret = 0; + RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_Q_NOT_PRIME); + } + + /* r_i prime? */ + for (idx = 0; idx < ex_primes; idx++) { + pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx); + if (BN_is_prime_ex(pinfo->r, BN_prime_checks, NULL, cb) != 1) { + ret = 0; + RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_MP_R_NOT_PRIME); + } + } + + /* n = p*q * r_3...r_i? */ + if (!BN_mul(i, key->p, key->q, ctx)) { + ret = -1; + goto err; + } + for (idx = 0; idx < ex_primes; idx++) { + pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx); + if (!BN_mul(i, i, pinfo->r, ctx)) { + ret = -1; + goto err; + } + } + if (BN_cmp(i, key->n) != 0) { + ret = 0; + if (ex_primes) + RSAerr(RSA_F_RSA_CHECK_KEY_EX, + RSA_R_N_DOES_NOT_EQUAL_PRODUCT_OF_PRIMES); + else + RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_N_DOES_NOT_EQUAL_P_Q); + } + + /* d*e = 1 mod \lambda(n)? */ + if (!BN_sub(i, key->p, BN_value_one())) { + ret = -1; + goto err; + } + if (!BN_sub(j, key->q, BN_value_one())) { + ret = -1; + goto err; + } + + /* now compute k = \lambda(n) = LCM(i, j, r_3 - 1...) */ + if (!BN_mul(l, i, j, ctx)) { + ret = -1; + goto err; + } + if (!BN_gcd(m, i, j, ctx)) { + ret = -1; + goto err; + } + for (idx = 0; idx < ex_primes; idx++) { + pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx); + if (!BN_sub(k, pinfo->r, BN_value_one())) { + ret = -1; + goto err; + } + if (!BN_mul(l, l, k, ctx)) { + ret = -1; + goto err; + } + if (!BN_gcd(m, m, k, ctx)) { + ret = -1; + goto err; + } + } + if (!BN_div(k, NULL, l, m, ctx)) { /* remainder is 0 */ + ret = -1; + goto err; + } + if (!BN_mod_mul(i, key->d, key->e, k, ctx)) { + ret = -1; + goto err; + } + + if (!BN_is_one(i)) { + ret = 0; + RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_D_E_NOT_CONGRUENT_TO_1); + } + + if (key->dmp1 != NULL && key->dmq1 != NULL && key->iqmp != NULL) { + /* dmp1 = d mod (p-1)? */ + if (!BN_sub(i, key->p, BN_value_one())) { + ret = -1; + goto err; + } + if (!BN_mod(j, key->d, i, ctx)) { + ret = -1; + goto err; + } + if (BN_cmp(j, key->dmp1) != 0) { + ret = 0; + RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_DMP1_NOT_CONGRUENT_TO_D); + } + + /* dmq1 = d mod (q-1)? */ + if (!BN_sub(i, key->q, BN_value_one())) { + ret = -1; + goto err; + } + if (!BN_mod(j, key->d, i, ctx)) { + ret = -1; + goto err; + } + if (BN_cmp(j, key->dmq1) != 0) { + ret = 0; + RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_DMQ1_NOT_CONGRUENT_TO_D); + } + + /* iqmp = q^-1 mod p? */ + if (!BN_mod_inverse(i, key->q, key->p, ctx)) { + ret = -1; + goto err; + } + if (BN_cmp(i, key->iqmp) != 0) { + ret = 0; + RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_IQMP_NOT_INVERSE_OF_Q); + } + } + + for (idx = 0; idx < ex_primes; idx++) { + pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx); + /* d_i = d mod (r_i - 1)? */ + if (!BN_sub(i, pinfo->r, BN_value_one())) { + ret = -1; + goto err; + } + if (!BN_mod(j, key->d, i, ctx)) { + ret = -1; + goto err; + } + if (BN_cmp(j, pinfo->d) != 0) { + ret = 0; + RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_MP_EXPONENT_NOT_CONGRUENT_TO_D); + } + /* t_i = R_i ^ -1 mod r_i ? */ + if (!BN_mod_inverse(i, pinfo->pp, pinfo->r, ctx)) { + ret = -1; + goto err; + } + if (BN_cmp(i, pinfo->t) != 0) { + ret = 0; + RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_MP_COEFFICIENT_NOT_INVERSE_OF_R); + } + } + + err: + BN_free(i); + BN_free(j); + BN_free(k); + BN_free(l); + BN_free(m); + BN_CTX_free(ctx); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_crpt.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_crpt.c new file mode 100644 index 000000000..f4ef8b438 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_crpt.c @@ -0,0 +1,169 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include "internal/bn_int.h" +#include +#include "rsa_locl.h" + +int RSA_bits(const RSA *r) +{ + return BN_num_bits(r->n); +} + +int RSA_size(const RSA *r) +{ + return BN_num_bytes(r->n); +} + +int RSA_public_encrypt(int flen, const unsigned char *from, unsigned char *to, + RSA *rsa, int padding) +{ + return rsa->meth->rsa_pub_enc(flen, from, to, rsa, padding); +} + +int RSA_private_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) +{ + return rsa->meth->rsa_priv_enc(flen, from, to, rsa, padding); +} + +int RSA_private_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) +{ + return rsa->meth->rsa_priv_dec(flen, from, to, rsa, padding); +} + +int RSA_public_decrypt(int flen, const unsigned char *from, unsigned char *to, + RSA *rsa, int padding) +{ + return rsa->meth->rsa_pub_dec(flen, from, to, rsa, padding); +} + +int RSA_flags(const RSA *r) +{ + return r == NULL ? 0 : r->meth->flags; +} + +void RSA_blinding_off(RSA *rsa) +{ + BN_BLINDING_free(rsa->blinding); + rsa->blinding = NULL; + rsa->flags &= ~RSA_FLAG_BLINDING; + rsa->flags |= RSA_FLAG_NO_BLINDING; +} + +int RSA_blinding_on(RSA *rsa, BN_CTX *ctx) +{ + int ret = 0; + + if (rsa->blinding != NULL) + RSA_blinding_off(rsa); + + rsa->blinding = RSA_setup_blinding(rsa, ctx); + if (rsa->blinding == NULL) + goto err; + + rsa->flags |= RSA_FLAG_BLINDING; + rsa->flags &= ~RSA_FLAG_NO_BLINDING; + ret = 1; + err: + return ret; +} + +static BIGNUM *rsa_get_public_exp(const BIGNUM *d, const BIGNUM *p, + const BIGNUM *q, BN_CTX *ctx) +{ + BIGNUM *ret = NULL, *r0, *r1, *r2; + + if (d == NULL || p == NULL || q == NULL) + return NULL; + + BN_CTX_start(ctx); + r0 = BN_CTX_get(ctx); + r1 = BN_CTX_get(ctx); + r2 = BN_CTX_get(ctx); + if (r2 == NULL) + goto err; + + if (!BN_sub(r1, p, BN_value_one())) + goto err; + if (!BN_sub(r2, q, BN_value_one())) + goto err; + if (!BN_mul(r0, r1, r2, ctx)) + goto err; + + ret = BN_mod_inverse(NULL, d, r0, ctx); + err: + BN_CTX_end(ctx); + return ret; +} + +BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *in_ctx) +{ + BIGNUM *e; + BN_CTX *ctx; + BN_BLINDING *ret = NULL; + + if (in_ctx == NULL) { + if ((ctx = BN_CTX_new()) == NULL) + return 0; + } else { + ctx = in_ctx; + } + + BN_CTX_start(ctx); + e = BN_CTX_get(ctx); + if (e == NULL) { + RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (rsa->e == NULL) { + e = rsa_get_public_exp(rsa->d, rsa->p, rsa->q, ctx); + if (e == NULL) { + RSAerr(RSA_F_RSA_SETUP_BLINDING, RSA_R_NO_PUBLIC_EXPONENT); + goto err; + } + } else { + e = rsa->e; + } + + { + BIGNUM *n = BN_new(); + + if (n == NULL) { + RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_MALLOC_FAILURE); + goto err; + } + BN_with_flags(n, rsa->n, BN_FLG_CONSTTIME); + + ret = BN_BLINDING_create_param(NULL, e, n, ctx, rsa->meth->bn_mod_exp, + rsa->_method_mod_n); + /* We MUST free n before any further use of rsa->n */ + BN_free(n); + } + if (ret == NULL) { + RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_BN_LIB); + goto err; + } + + BN_BLINDING_set_current_thread(ret); + + err: + BN_CTX_end(ctx); + if (ctx != in_ctx) + BN_CTX_free(ctx); + if (e != rsa->e) + BN_free(e); + + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_depr.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_depr.c new file mode 100644 index 000000000..21e056252 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_depr.c @@ -0,0 +1,61 @@ +/* + * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * NB: This file contains deprecated functions (compatibility wrappers to the + * "new" versions). + */ + +#include +#if OPENSSL_API_COMPAT >= 0x00908000L +NON_EMPTY_TRANSLATION_UNIT + +#else + +# include +# include +# include "internal/cryptlib.h" +# include +# include + +RSA *RSA_generate_key(int bits, unsigned long e_value, + void (*callback) (int, int, void *), void *cb_arg) +{ + int i; + BN_GENCB *cb = BN_GENCB_new(); + RSA *rsa = RSA_new(); + BIGNUM *e = BN_new(); + + if (cb == NULL || rsa == NULL || e == NULL) + goto err; + + /* + * The problem is when building with 8, 16, or 32 BN_ULONG, unsigned long + * can be larger + */ + for (i = 0; i < (int)sizeof(unsigned long) * 8; i++) { + if (e_value & (1UL << i)) + if (BN_set_bit(e, i) == 0) + goto err; + } + + BN_GENCB_set_old(cb, callback, cb_arg); + + if (RSA_generate_key_ex(rsa, bits, e, cb)) { + BN_free(e); + BN_GENCB_free(cb); + return rsa; + } + err: + BN_free(e); + RSA_free(rsa); + BN_GENCB_free(cb); + return 0; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_err.c new file mode 100644 index 000000000..62fd9e0b1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_err.c @@ -0,0 +1,246 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA RSA_str_functs[] = { + {ERR_PACK(ERR_LIB_RSA, RSA_F_CHECK_PADDING_MD, 0), "check_padding_md"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_ENCODE_PKCS1, 0), "encode_pkcs1"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_INT_RSA_VERIFY, 0), "int_rsa_verify"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_OLD_RSA_PRIV_DECODE, 0), + "old_rsa_priv_decode"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_PKEY_PSS_INIT, 0), "pkey_pss_init"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_PKEY_RSA_CTRL, 0), "pkey_rsa_ctrl"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_PKEY_RSA_CTRL_STR, 0), "pkey_rsa_ctrl_str"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_PKEY_RSA_SIGN, 0), "pkey_rsa_sign"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_PKEY_RSA_VERIFY, 0), "pkey_rsa_verify"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_PKEY_RSA_VERIFYRECOVER, 0), + "pkey_rsa_verifyrecover"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_ALGOR_TO_MD, 0), "rsa_algor_to_md"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_BUILTIN_KEYGEN, 0), "rsa_builtin_keygen"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_CHECK_KEY, 0), "RSA_check_key"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_CHECK_KEY_EX, 0), "RSA_check_key_ex"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_CMS_DECRYPT, 0), "rsa_cms_decrypt"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_CMS_VERIFY, 0), "rsa_cms_verify"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_ITEM_VERIFY, 0), "rsa_item_verify"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_METH_DUP, 0), "RSA_meth_dup"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_METH_NEW, 0), "RSA_meth_new"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_METH_SET1_NAME, 0), "RSA_meth_set1_name"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_MGF1_TO_MD, 0), ""}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_MULTIP_INFO_NEW, 0), + "rsa_multip_info_new"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_NEW_METHOD, 0), "RSA_new_method"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_NULL, 0), ""}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_NULL_PRIVATE_DECRYPT, 0), ""}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_NULL_PRIVATE_ENCRYPT, 0), ""}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_NULL_PUBLIC_DECRYPT, 0), ""}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_NULL_PUBLIC_ENCRYPT, 0), ""}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_OSSL_PRIVATE_DECRYPT, 0), + "rsa_ossl_private_decrypt"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, 0), + "rsa_ossl_private_encrypt"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_OSSL_PUBLIC_DECRYPT, 0), + "rsa_ossl_public_decrypt"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, 0), + "rsa_ossl_public_encrypt"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_ADD_NONE, 0), + "RSA_padding_add_none"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, 0), + "RSA_padding_add_PKCS1_OAEP"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1, 0), + "RSA_padding_add_PKCS1_OAEP_mgf1"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_ADD_PKCS1_PSS, 0), + "RSA_padding_add_PKCS1_PSS"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1, 0), + "RSA_padding_add_PKCS1_PSS_mgf1"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1, 0), + "RSA_padding_add_PKCS1_type_1"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2, 0), + "RSA_padding_add_PKCS1_type_2"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_ADD_SSLV23, 0), + "RSA_padding_add_SSLv23"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_ADD_X931, 0), + "RSA_padding_add_X931"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_CHECK_NONE, 0), + "RSA_padding_check_none"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, 0), + "RSA_padding_check_PKCS1_OAEP"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1, 0), + "RSA_padding_check_PKCS1_OAEP_mgf1"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1, 0), + "RSA_padding_check_PKCS1_type_1"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2, 0), + "RSA_padding_check_PKCS1_type_2"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_CHECK_SSLV23, 0), + "RSA_padding_check_SSLv23"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_CHECK_X931, 0), + "RSA_padding_check_X931"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PARAM_DECODE, 0), "rsa_param_decode"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PRINT, 0), "RSA_print"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PRINT_FP, 0), "RSA_print_fp"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PRIV_DECODE, 0), "rsa_priv_decode"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PRIV_ENCODE, 0), "rsa_priv_encode"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PSS_GET_PARAM, 0), "rsa_pss_get_param"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PSS_TO_CTX, 0), "rsa_pss_to_ctx"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PUB_DECODE, 0), "rsa_pub_decode"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_SETUP_BLINDING, 0), "RSA_setup_blinding"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_SIGN, 0), "RSA_sign"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_SIGN_ASN1_OCTET_STRING, 0), + "RSA_sign_ASN1_OCTET_STRING"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_VERIFY, 0), "RSA_verify"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_VERIFY_ASN1_OCTET_STRING, 0), + "RSA_verify_ASN1_OCTET_STRING"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, 0), + "RSA_verify_PKCS1_PSS_mgf1"}, + {ERR_PACK(ERR_LIB_RSA, RSA_F_SETUP_TBUF, 0), "setup_tbuf"}, + {0, NULL} +}; + +static const ERR_STRING_DATA RSA_str_reasons[] = { + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_ALGORITHM_MISMATCH), "algorithm mismatch"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_BAD_E_VALUE), "bad e value"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_BAD_FIXED_HEADER_DECRYPT), + "bad fixed header decrypt"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_BAD_PAD_BYTE_COUNT), "bad pad byte count"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_BAD_SIGNATURE), "bad signature"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_BLOCK_TYPE_IS_NOT_01), + "block type is not 01"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_BLOCK_TYPE_IS_NOT_02), + "block type is not 02"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DATA_GREATER_THAN_MOD_LEN), + "data greater than mod len"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DATA_TOO_LARGE), "data too large"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE), + "data too large for key size"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DATA_TOO_LARGE_FOR_MODULUS), + "data too large for modulus"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DATA_TOO_SMALL), "data too small"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE), + "data too small for key size"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DIGEST_DOES_NOT_MATCH), + "digest does not match"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DIGEST_NOT_ALLOWED), "digest not allowed"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY), + "digest too big for rsa key"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DMP1_NOT_CONGRUENT_TO_D), + "dmp1 not congruent to d"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DMQ1_NOT_CONGRUENT_TO_D), + "dmq1 not congruent to d"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_D_E_NOT_CONGRUENT_TO_1), + "d e not congruent to 1"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_FIRST_OCTET_INVALID), + "first octet invalid"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE), + "illegal or unsupported padding mode"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_DIGEST), "invalid digest"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_DIGEST_LENGTH), + "invalid digest length"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_HEADER), "invalid header"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_LABEL), "invalid label"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_MESSAGE_LENGTH), + "invalid message length"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_MGF1_MD), "invalid mgf1 md"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_MULTI_PRIME_KEY), + "invalid multi prime key"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_OAEP_PARAMETERS), + "invalid oaep parameters"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_PADDING), "invalid padding"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_PADDING_MODE), + "invalid padding mode"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_PSS_PARAMETERS), + "invalid pss parameters"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_PSS_SALTLEN), + "invalid pss saltlen"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_SALT_LENGTH), + "invalid salt length"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_TRAILER), "invalid trailer"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_X931_DIGEST), + "invalid x931 digest"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_IQMP_NOT_INVERSE_OF_Q), + "iqmp not inverse of q"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_KEY_PRIME_NUM_INVALID), + "key prime num invalid"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_KEY_SIZE_TOO_SMALL), "key size too small"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_LAST_OCTET_INVALID), "last octet invalid"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_MGF1_DIGEST_NOT_ALLOWED), + "mgf1 digest not allowed"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_MODULUS_TOO_LARGE), "modulus too large"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_MP_COEFFICIENT_NOT_INVERSE_OF_R), + "mp coefficient not inverse of r"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_MP_EXPONENT_NOT_CONGRUENT_TO_D), + "mp exponent not congruent to d"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_MP_R_NOT_PRIME), "mp r not prime"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_NO_PUBLIC_EXPONENT), "no public exponent"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_NULL_BEFORE_BLOCK_MISSING), + "null before block missing"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_N_DOES_NOT_EQUAL_PRODUCT_OF_PRIMES), + "n does not equal product of primes"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_N_DOES_NOT_EQUAL_P_Q), + "n does not equal p q"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_OAEP_DECODING_ERROR), + "oaep decoding error"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE), + "operation not supported for this keytype"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_PADDING_CHECK_FAILED), + "padding check failed"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_PKCS_DECODING_ERROR), + "pkcs decoding error"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_PSS_SALTLEN_TOO_SMALL), + "pss saltlen too small"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_P_NOT_PRIME), "p not prime"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_Q_NOT_PRIME), "q not prime"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED), + "rsa operations not supported"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_SLEN_CHECK_FAILED), + "salt length check failed"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_SLEN_RECOVERY_FAILED), + "salt length recovery failed"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_SSLV3_ROLLBACK_ATTACK), + "sslv3 rollback attack"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD), + "the asn1 object identifier is not known for this md"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_UNKNOWN_ALGORITHM_TYPE), + "unknown algorithm type"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_UNKNOWN_DIGEST), "unknown digest"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_UNKNOWN_MASK_DIGEST), + "unknown mask digest"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_UNKNOWN_PADDING_TYPE), + "unknown padding type"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_UNSUPPORTED_ENCRYPTION_TYPE), + "unsupported encryption type"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_UNSUPPORTED_LABEL_SOURCE), + "unsupported label source"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_UNSUPPORTED_MASK_ALGORITHM), + "unsupported mask algorithm"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_UNSUPPORTED_MASK_PARAMETER), + "unsupported mask parameter"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_UNSUPPORTED_SIGNATURE_TYPE), + "unsupported signature type"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_VALUE_MISSING), "value missing"}, + {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_WRONG_SIGNATURE_LENGTH), + "wrong signature length"}, + {0, NULL} +}; + +#endif + +int ERR_load_RSA_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(RSA_str_functs[0].error) == NULL) { + ERR_load_strings_const(RSA_str_functs); + ERR_load_strings_const(RSA_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_gen.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_gen.c new file mode 100644 index 000000000..7f0a25648 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_gen.c @@ -0,0 +1,394 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * NB: these functions have been "upgraded", the deprecated versions (which + * are compatibility wrappers using these functions) are in rsa_depr.c. - + * Geoff + */ + +#include +#include +#include "internal/cryptlib.h" +#include +#include "rsa_locl.h" + +static int rsa_builtin_keygen(RSA *rsa, int bits, int primes, BIGNUM *e_value, + BN_GENCB *cb); + +/* + * NB: this wrapper would normally be placed in rsa_lib.c and the static + * implementation would probably be in rsa_eay.c. Nonetheless, is kept here + * so that we don't introduce a new linker dependency. Eg. any application + * that wasn't previously linking object code related to key-generation won't + * have to now just because key-generation is part of RSA_METHOD. + */ +int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) +{ + if (rsa->meth->rsa_keygen != NULL) + return rsa->meth->rsa_keygen(rsa, bits, e_value, cb); + + return RSA_generate_multi_prime_key(rsa, bits, RSA_DEFAULT_PRIME_NUM, + e_value, cb); +} + +int RSA_generate_multi_prime_key(RSA *rsa, int bits, int primes, + BIGNUM *e_value, BN_GENCB *cb) +{ + /* multi-prime is only supported with the builtin key generation */ + if (rsa->meth->rsa_multi_prime_keygen != NULL) { + return rsa->meth->rsa_multi_prime_keygen(rsa, bits, primes, + e_value, cb); + } else if (rsa->meth->rsa_keygen != NULL) { + /* + * However, if rsa->meth implements only rsa_keygen, then we + * have to honour it in 2-prime case and assume that it wouldn't + * know what to do with multi-prime key generated by builtin + * subroutine... + */ + if (primes == 2) + return rsa->meth->rsa_keygen(rsa, bits, e_value, cb); + else + return 0; + } + + return rsa_builtin_keygen(rsa, bits, primes, e_value, cb); +} + +static int rsa_builtin_keygen(RSA *rsa, int bits, int primes, BIGNUM *e_value, + BN_GENCB *cb) +{ + BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *tmp, *prime; + int ok = -1, n = 0, bitsr[RSA_MAX_PRIME_NUM], bitse = 0; + int i = 0, quo = 0, rmd = 0, adj = 0, retries = 0; + RSA_PRIME_INFO *pinfo = NULL; + STACK_OF(RSA_PRIME_INFO) *prime_infos = NULL; + BN_CTX *ctx = NULL; + BN_ULONG bitst = 0; + unsigned long error = 0; + + if (bits < RSA_MIN_MODULUS_BITS) { + ok = 0; /* we set our own err */ + RSAerr(RSA_F_RSA_BUILTIN_KEYGEN, RSA_R_KEY_SIZE_TOO_SMALL); + goto err; + } + + if (primes < RSA_DEFAULT_PRIME_NUM || primes > rsa_multip_cap(bits)) { + ok = 0; /* we set our own err */ + RSAerr(RSA_F_RSA_BUILTIN_KEYGEN, RSA_R_KEY_PRIME_NUM_INVALID); + goto err; + } + + ctx = BN_CTX_new(); + if (ctx == NULL) + goto err; + BN_CTX_start(ctx); + r0 = BN_CTX_get(ctx); + r1 = BN_CTX_get(ctx); + r2 = BN_CTX_get(ctx); + if (r2 == NULL) + goto err; + + /* divide bits into 'primes' pieces evenly */ + quo = bits / primes; + rmd = bits % primes; + + for (i = 0; i < primes; i++) + bitsr[i] = (i < rmd) ? quo + 1 : quo; + + /* We need the RSA components non-NULL */ + if (!rsa->n && ((rsa->n = BN_new()) == NULL)) + goto err; + if (!rsa->d && ((rsa->d = BN_secure_new()) == NULL)) + goto err; + if (!rsa->e && ((rsa->e = BN_new()) == NULL)) + goto err; + if (!rsa->p && ((rsa->p = BN_secure_new()) == NULL)) + goto err; + if (!rsa->q && ((rsa->q = BN_secure_new()) == NULL)) + goto err; + if (!rsa->dmp1 && ((rsa->dmp1 = BN_secure_new()) == NULL)) + goto err; + if (!rsa->dmq1 && ((rsa->dmq1 = BN_secure_new()) == NULL)) + goto err; + if (!rsa->iqmp && ((rsa->iqmp = BN_secure_new()) == NULL)) + goto err; + + /* initialize multi-prime components */ + if (primes > RSA_DEFAULT_PRIME_NUM) { + rsa->version = RSA_ASN1_VERSION_MULTI; + prime_infos = sk_RSA_PRIME_INFO_new_reserve(NULL, primes - 2); + if (prime_infos == NULL) + goto err; + if (rsa->prime_infos != NULL) { + /* could this happen? */ + sk_RSA_PRIME_INFO_pop_free(rsa->prime_infos, rsa_multip_info_free); + } + rsa->prime_infos = prime_infos; + + /* prime_info from 2 to |primes| -1 */ + for (i = 2; i < primes; i++) { + pinfo = rsa_multip_info_new(); + if (pinfo == NULL) + goto err; + (void)sk_RSA_PRIME_INFO_push(prime_infos, pinfo); + } + } + + if (BN_copy(rsa->e, e_value) == NULL) + goto err; + + /* generate p, q and other primes (if any) */ + for (i = 0; i < primes; i++) { + adj = 0; + retries = 0; + + if (i == 0) { + prime = rsa->p; + } else if (i == 1) { + prime = rsa->q; + } else { + pinfo = sk_RSA_PRIME_INFO_value(prime_infos, i - 2); + prime = pinfo->r; + } + BN_set_flags(prime, BN_FLG_CONSTTIME); + + for (;;) { + redo: + if (!BN_generate_prime_ex(prime, bitsr[i] + adj, 0, NULL, NULL, cb)) + goto err; + /* + * prime should not be equal to p, q, r_3... + * (those primes prior to this one) + */ + { + int j; + + for (j = 0; j < i; j++) { + BIGNUM *prev_prime; + + if (j == 0) + prev_prime = rsa->p; + else if (j == 1) + prev_prime = rsa->q; + else + prev_prime = sk_RSA_PRIME_INFO_value(prime_infos, + j - 2)->r; + + if (!BN_cmp(prime, prev_prime)) { + goto redo; + } + } + } + if (!BN_sub(r2, prime, BN_value_one())) + goto err; + ERR_set_mark(); + BN_set_flags(r2, BN_FLG_CONSTTIME); + if (BN_mod_inverse(r1, r2, rsa->e, ctx) != NULL) { + /* GCD == 1 since inverse exists */ + break; + } + error = ERR_peek_last_error(); + if (ERR_GET_LIB(error) == ERR_LIB_BN + && ERR_GET_REASON(error) == BN_R_NO_INVERSE) { + /* GCD != 1 */ + ERR_pop_to_mark(); + } else { + goto err; + } + if (!BN_GENCB_call(cb, 2, n++)) + goto err; + } + + bitse += bitsr[i]; + + /* calculate n immediately to see if it's sufficient */ + if (i == 1) { + /* we get at least 2 primes */ + if (!BN_mul(r1, rsa->p, rsa->q, ctx)) + goto err; + } else if (i != 0) { + /* modulus n = p * q * r_3 * r_4 ... */ + if (!BN_mul(r1, rsa->n, prime, ctx)) + goto err; + } else { + /* i == 0, do nothing */ + if (!BN_GENCB_call(cb, 3, i)) + goto err; + continue; + } + /* + * if |r1|, product of factors so far, is not as long as expected + * (by checking the first 4 bits are less than 0x9 or greater than + * 0xF). If so, re-generate the last prime. + * + * NOTE: This actually can't happen in two-prime case, because of + * the way factors are generated. + * + * Besides, another consideration is, for multi-prime case, even the + * length modulus is as long as expected, the modulus could start at + * 0x8, which could be utilized to distinguish a multi-prime private + * key by using the modulus in a certificate. This is also covered + * by checking the length should not be less than 0x9. + */ + if (!BN_rshift(r2, r1, bitse - 4)) + goto err; + bitst = BN_get_word(r2); + + if (bitst < 0x9 || bitst > 0xF) { + /* + * For keys with more than 4 primes, we attempt longer factor to + * meet length requirement. + * + * Otherwise, we just re-generate the prime with the same length. + * + * This strategy has the following goals: + * + * 1. 1024-bit factors are effcient when using 3072 and 4096-bit key + * 2. stay the same logic with normal 2-prime key + */ + bitse -= bitsr[i]; + if (!BN_GENCB_call(cb, 2, n++)) + goto err; + if (primes > 4) { + if (bitst < 0x9) + adj++; + else + adj--; + } else if (retries == 4) { + /* + * re-generate all primes from scratch, mainly used + * in 4 prime case to avoid long loop. Max retry times + * is set to 4. + */ + i = -1; + bitse = 0; + continue; + } + retries++; + goto redo; + } + /* save product of primes for further use, for multi-prime only */ + if (i > 1 && BN_copy(pinfo->pp, rsa->n) == NULL) + goto err; + if (BN_copy(rsa->n, r1) == NULL) + goto err; + if (!BN_GENCB_call(cb, 3, i)) + goto err; + } + + if (BN_cmp(rsa->p, rsa->q) < 0) { + tmp = rsa->p; + rsa->p = rsa->q; + rsa->q = tmp; + } + + /* calculate d */ + + /* p - 1 */ + if (!BN_sub(r1, rsa->p, BN_value_one())) + goto err; + /* q - 1 */ + if (!BN_sub(r2, rsa->q, BN_value_one())) + goto err; + /* (p - 1)(q - 1) */ + if (!BN_mul(r0, r1, r2, ctx)) + goto err; + /* multi-prime */ + for (i = 2; i < primes; i++) { + pinfo = sk_RSA_PRIME_INFO_value(prime_infos, i - 2); + /* save r_i - 1 to pinfo->d temporarily */ + if (!BN_sub(pinfo->d, pinfo->r, BN_value_one())) + goto err; + if (!BN_mul(r0, r0, pinfo->d, ctx)) + goto err; + } + + { + BIGNUM *pr0 = BN_new(); + + if (pr0 == NULL) + goto err; + + BN_with_flags(pr0, r0, BN_FLG_CONSTTIME); + if (!BN_mod_inverse(rsa->d, rsa->e, pr0, ctx)) { + BN_free(pr0); + goto err; /* d */ + } + /* We MUST free pr0 before any further use of r0 */ + BN_free(pr0); + } + + { + BIGNUM *d = BN_new(); + + if (d == NULL) + goto err; + + BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME); + + /* calculate d mod (p-1) and d mod (q - 1) */ + if (!BN_mod(rsa->dmp1, d, r1, ctx) + || !BN_mod(rsa->dmq1, d, r2, ctx)) { + BN_free(d); + goto err; + } + + /* calculate CRT exponents */ + for (i = 2; i < primes; i++) { + pinfo = sk_RSA_PRIME_INFO_value(prime_infos, i - 2); + /* pinfo->d == r_i - 1 */ + if (!BN_mod(pinfo->d, d, pinfo->d, ctx)) { + BN_free(d); + goto err; + } + } + + /* We MUST free d before any further use of rsa->d */ + BN_free(d); + } + + { + BIGNUM *p = BN_new(); + + if (p == NULL) + goto err; + BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME); + + /* calculate inverse of q mod p */ + if (!BN_mod_inverse(rsa->iqmp, rsa->q, p, ctx)) { + BN_free(p); + goto err; + } + + /* calculate CRT coefficient for other primes */ + for (i = 2; i < primes; i++) { + pinfo = sk_RSA_PRIME_INFO_value(prime_infos, i - 2); + BN_with_flags(p, pinfo->r, BN_FLG_CONSTTIME); + if (!BN_mod_inverse(pinfo->t, pinfo->pp, p, ctx)) { + BN_free(p); + goto err; + } + } + + /* We MUST free p before any further use of rsa->p */ + BN_free(p); + } + + ok = 1; + err: + if (ok == -1) { + RSAerr(RSA_F_RSA_BUILTIN_KEYGEN, ERR_LIB_BN); + ok = 0; + } + if (ctx != NULL) + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ok; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_lib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_lib.c new file mode 100644 index 000000000..49c34b7c3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_lib.c @@ -0,0 +1,479 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include "internal/refcount.h" +#include "internal/bn_int.h" +#include +#include +#include "internal/evp_int.h" +#include "rsa_locl.h" + +RSA *RSA_new(void) +{ + return RSA_new_method(NULL); +} + +const RSA_METHOD *RSA_get_method(const RSA *rsa) +{ + return rsa->meth; +} + +int RSA_set_method(RSA *rsa, const RSA_METHOD *meth) +{ + /* + * NB: The caller is specifically setting a method, so it's not up to us + * to deal with which ENGINE it comes from. + */ + const RSA_METHOD *mtmp; + mtmp = rsa->meth; + if (mtmp->finish) + mtmp->finish(rsa); +#ifndef OPENSSL_NO_ENGINE + ENGINE_finish(rsa->engine); + rsa->engine = NULL; +#endif + rsa->meth = meth; + if (meth->init) + meth->init(rsa); + return 1; +} + +RSA *RSA_new_method(ENGINE *engine) +{ + RSA *ret = OPENSSL_zalloc(sizeof(*ret)); + + if (ret == NULL) { + RSAerr(RSA_F_RSA_NEW_METHOD, ERR_R_MALLOC_FAILURE); + return NULL; + } + + ret->references = 1; + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) { + RSAerr(RSA_F_RSA_NEW_METHOD, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ret); + return NULL; + } + + ret->meth = RSA_get_default_method(); +#ifndef OPENSSL_NO_ENGINE + ret->flags = ret->meth->flags & ~RSA_FLAG_NON_FIPS_ALLOW; + if (engine) { + if (!ENGINE_init(engine)) { + RSAerr(RSA_F_RSA_NEW_METHOD, ERR_R_ENGINE_LIB); + goto err; + } + ret->engine = engine; + } else { + ret->engine = ENGINE_get_default_RSA(); + } + if (ret->engine) { + ret->meth = ENGINE_get_RSA(ret->engine); + if (ret->meth == NULL) { + RSAerr(RSA_F_RSA_NEW_METHOD, ERR_R_ENGINE_LIB); + goto err; + } + } +#endif + + ret->flags = ret->meth->flags & ~RSA_FLAG_NON_FIPS_ALLOW; + if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_RSA, ret, &ret->ex_data)) { + goto err; + } + + if ((ret->meth->init != NULL) && !ret->meth->init(ret)) { + RSAerr(RSA_F_RSA_NEW_METHOD, ERR_R_INIT_FAIL); + goto err; + } + + return ret; + + err: + RSA_free(ret); + return NULL; +} + +void RSA_free(RSA *r) +{ + int i; + + if (r == NULL) + return; + + CRYPTO_DOWN_REF(&r->references, &i, r->lock); + REF_PRINT_COUNT("RSA", r); + if (i > 0) + return; + REF_ASSERT_ISNT(i < 0); + + if (r->meth != NULL && r->meth->finish != NULL) + r->meth->finish(r); +#ifndef OPENSSL_NO_ENGINE + ENGINE_finish(r->engine); +#endif + + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, r, &r->ex_data); + + CRYPTO_THREAD_lock_free(r->lock); + + BN_free(r->n); + BN_free(r->e); + BN_clear_free(r->d); + BN_clear_free(r->p); + BN_clear_free(r->q); + BN_clear_free(r->dmp1); + BN_clear_free(r->dmq1); + BN_clear_free(r->iqmp); + RSA_PSS_PARAMS_free(r->pss); + sk_RSA_PRIME_INFO_pop_free(r->prime_infos, rsa_multip_info_free); + BN_BLINDING_free(r->blinding); + BN_BLINDING_free(r->mt_blinding); + OPENSSL_free(r->bignum_data); + OPENSSL_free(r); +} + +int RSA_up_ref(RSA *r) +{ + int i; + + if (CRYPTO_UP_REF(&r->references, &i, r->lock) <= 0) + return 0; + + REF_PRINT_COUNT("RSA", r); + REF_ASSERT_ISNT(i < 2); + return i > 1 ? 1 : 0; +} + +int RSA_set_ex_data(RSA *r, int idx, void *arg) +{ + return CRYPTO_set_ex_data(&r->ex_data, idx, arg); +} + +void *RSA_get_ex_data(const RSA *r, int idx) +{ + return CRYPTO_get_ex_data(&r->ex_data, idx); +} + +int RSA_security_bits(const RSA *rsa) +{ + int bits = BN_num_bits(rsa->n); + + if (rsa->version == RSA_ASN1_VERSION_MULTI) { + /* This ought to mean that we have private key at hand. */ + int ex_primes = sk_RSA_PRIME_INFO_num(rsa->prime_infos); + + if (ex_primes <= 0 || (ex_primes + 2) > rsa_multip_cap(bits)) + return 0; + } + return BN_security_bits(bits, -1); +} + +int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) +{ + /* If the fields n and e in r are NULL, the corresponding input + * parameters MUST be non-NULL for n and e. d may be + * left NULL (in case only the public key is used). + */ + if ((r->n == NULL && n == NULL) + || (r->e == NULL && e == NULL)) + return 0; + + if (n != NULL) { + BN_free(r->n); + r->n = n; + } + if (e != NULL) { + BN_free(r->e); + r->e = e; + } + if (d != NULL) { + BN_clear_free(r->d); + r->d = d; + } + + return 1; +} + +int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q) +{ + /* If the fields p and q in r are NULL, the corresponding input + * parameters MUST be non-NULL. + */ + if ((r->p == NULL && p == NULL) + || (r->q == NULL && q == NULL)) + return 0; + + if (p != NULL) { + BN_clear_free(r->p); + r->p = p; + } + if (q != NULL) { + BN_clear_free(r->q); + r->q = q; + } + + return 1; +} + +int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp) +{ + /* If the fields dmp1, dmq1 and iqmp in r are NULL, the corresponding input + * parameters MUST be non-NULL. + */ + if ((r->dmp1 == NULL && dmp1 == NULL) + || (r->dmq1 == NULL && dmq1 == NULL) + || (r->iqmp == NULL && iqmp == NULL)) + return 0; + + if (dmp1 != NULL) { + BN_clear_free(r->dmp1); + r->dmp1 = dmp1; + } + if (dmq1 != NULL) { + BN_clear_free(r->dmq1); + r->dmq1 = dmq1; + } + if (iqmp != NULL) { + BN_clear_free(r->iqmp); + r->iqmp = iqmp; + } + + return 1; +} + +/* + * Is it better to export RSA_PRIME_INFO structure + * and related functions to let user pass a triplet? + */ +int RSA_set0_multi_prime_params(RSA *r, BIGNUM *primes[], BIGNUM *exps[], + BIGNUM *coeffs[], int pnum) +{ + STACK_OF(RSA_PRIME_INFO) *prime_infos, *old = NULL; + RSA_PRIME_INFO *pinfo; + int i; + + if (primes == NULL || exps == NULL || coeffs == NULL || pnum == 0) + return 0; + + prime_infos = sk_RSA_PRIME_INFO_new_reserve(NULL, pnum); + if (prime_infos == NULL) + return 0; + + if (r->prime_infos != NULL) + old = r->prime_infos; + + for (i = 0; i < pnum; i++) { + pinfo = rsa_multip_info_new(); + if (pinfo == NULL) + goto err; + if (primes[i] != NULL && exps[i] != NULL && coeffs[i] != NULL) { + BN_free(pinfo->r); + BN_free(pinfo->d); + BN_free(pinfo->t); + pinfo->r = primes[i]; + pinfo->d = exps[i]; + pinfo->t = coeffs[i]; + } else { + rsa_multip_info_free(pinfo); + goto err; + } + (void)sk_RSA_PRIME_INFO_push(prime_infos, pinfo); + } + + r->prime_infos = prime_infos; + + if (!rsa_multip_calc_product(r)) { + r->prime_infos = old; + goto err; + } + + if (old != NULL) { + /* + * This is hard to deal with, since the old infos could + * also be set by this function and r, d, t should not + * be freed in that case. So currently, stay consistent + * with other *set0* functions: just free it... + */ + sk_RSA_PRIME_INFO_pop_free(old, rsa_multip_info_free); + } + + r->version = RSA_ASN1_VERSION_MULTI; + + return 1; + err: + /* r, d, t should not be freed */ + sk_RSA_PRIME_INFO_pop_free(prime_infos, rsa_multip_info_free_ex); + return 0; +} + +void RSA_get0_key(const RSA *r, + const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) +{ + if (n != NULL) + *n = r->n; + if (e != NULL) + *e = r->e; + if (d != NULL) + *d = r->d; +} + +void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q) +{ + if (p != NULL) + *p = r->p; + if (q != NULL) + *q = r->q; +} + +int RSA_get_multi_prime_extra_count(const RSA *r) +{ + int pnum; + + pnum = sk_RSA_PRIME_INFO_num(r->prime_infos); + if (pnum <= 0) + pnum = 0; + return pnum; +} + +int RSA_get0_multi_prime_factors(const RSA *r, const BIGNUM *primes[]) +{ + int pnum, i; + RSA_PRIME_INFO *pinfo; + + if ((pnum = RSA_get_multi_prime_extra_count(r)) == 0) + return 0; + + /* + * return other primes + * it's caller's responsibility to allocate oth_primes[pnum] + */ + for (i = 0; i < pnum; i++) { + pinfo = sk_RSA_PRIME_INFO_value(r->prime_infos, i); + primes[i] = pinfo->r; + } + + return 1; +} + +void RSA_get0_crt_params(const RSA *r, + const BIGNUM **dmp1, const BIGNUM **dmq1, + const BIGNUM **iqmp) +{ + if (dmp1 != NULL) + *dmp1 = r->dmp1; + if (dmq1 != NULL) + *dmq1 = r->dmq1; + if (iqmp != NULL) + *iqmp = r->iqmp; +} + +int RSA_get0_multi_prime_crt_params(const RSA *r, const BIGNUM *exps[], + const BIGNUM *coeffs[]) +{ + int pnum; + + if ((pnum = RSA_get_multi_prime_extra_count(r)) == 0) + return 0; + + /* return other primes */ + if (exps != NULL || coeffs != NULL) { + RSA_PRIME_INFO *pinfo; + int i; + + /* it's the user's job to guarantee the buffer length */ + for (i = 0; i < pnum; i++) { + pinfo = sk_RSA_PRIME_INFO_value(r->prime_infos, i); + if (exps != NULL) + exps[i] = pinfo->d; + if (coeffs != NULL) + coeffs[i] = pinfo->t; + } + } + + return 1; +} + +const BIGNUM *RSA_get0_n(const RSA *r) +{ + return r->n; +} + +const BIGNUM *RSA_get0_e(const RSA *r) +{ + return r->e; +} + +const BIGNUM *RSA_get0_d(const RSA *r) +{ + return r->d; +} + +const BIGNUM *RSA_get0_p(const RSA *r) +{ + return r->p; +} + +const BIGNUM *RSA_get0_q(const RSA *r) +{ + return r->q; +} + +const BIGNUM *RSA_get0_dmp1(const RSA *r) +{ + return r->dmp1; +} + +const BIGNUM *RSA_get0_dmq1(const RSA *r) +{ + return r->dmq1; +} + +const BIGNUM *RSA_get0_iqmp(const RSA *r) +{ + return r->iqmp; +} + +void RSA_clear_flags(RSA *r, int flags) +{ + r->flags &= ~flags; +} + +int RSA_test_flags(const RSA *r, int flags) +{ + return r->flags & flags; +} + +void RSA_set_flags(RSA *r, int flags) +{ + r->flags |= flags; +} + +int RSA_get_version(RSA *r) +{ + /* { two-prime(0), multi(1) } */ + return r->version; +} + +ENGINE *RSA_get0_engine(const RSA *r) +{ + return r->engine; +} + +int RSA_pkey_ctx_ctrl(EVP_PKEY_CTX *ctx, int optype, int cmd, int p1, void *p2) +{ + /* If key type not RSA or RSA-PSS return error */ + if (ctx != NULL && ctx->pmeth != NULL + && ctx->pmeth->pkey_id != EVP_PKEY_RSA + && ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS) + return -1; + return EVP_PKEY_CTX_ctrl(ctx, -1, optype, cmd, p1, p2); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_locl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_locl.h new file mode 100644 index 000000000..2b94462a9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_locl.h @@ -0,0 +1,132 @@ +/* + * Copyright 2006-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/refcount.h" + +#define RSA_MAX_PRIME_NUM 5 +#define RSA_MIN_MODULUS_BITS 512 + +typedef struct rsa_prime_info_st { + BIGNUM *r; + BIGNUM *d; + BIGNUM *t; + /* save product of primes prior to this one */ + BIGNUM *pp; + BN_MONT_CTX *m; +} RSA_PRIME_INFO; + +DECLARE_ASN1_ITEM(RSA_PRIME_INFO) +DEFINE_STACK_OF(RSA_PRIME_INFO) + +struct rsa_st { + /* + * The first parameter is used to pickup errors where this is passed + * instead of an EVP_PKEY, it is set to 0 + */ + int pad; + int32_t version; + const RSA_METHOD *meth; + /* functional reference if 'meth' is ENGINE-provided */ + ENGINE *engine; + BIGNUM *n; + BIGNUM *e; + BIGNUM *d; + BIGNUM *p; + BIGNUM *q; + BIGNUM *dmp1; + BIGNUM *dmq1; + BIGNUM *iqmp; + /* for multi-prime RSA, defined in RFC 8017 */ + STACK_OF(RSA_PRIME_INFO) *prime_infos; + /* If a PSS only key this contains the parameter restrictions */ + RSA_PSS_PARAMS *pss; + /* be careful using this if the RSA structure is shared */ + CRYPTO_EX_DATA ex_data; + CRYPTO_REF_COUNT references; + int flags; + /* Used to cache montgomery values */ + BN_MONT_CTX *_method_mod_n; + BN_MONT_CTX *_method_mod_p; + BN_MONT_CTX *_method_mod_q; + /* + * all BIGNUM values are actually in the following data, if it is not + * NULL + */ + char *bignum_data; + BN_BLINDING *blinding; + BN_BLINDING *mt_blinding; + CRYPTO_RWLOCK *lock; +}; + +struct rsa_meth_st { + char *name; + int (*rsa_pub_enc) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); + int (*rsa_pub_dec) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); + int (*rsa_priv_enc) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); + int (*rsa_priv_dec) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); + /* Can be null */ + int (*rsa_mod_exp) (BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx); + /* Can be null */ + int (*bn_mod_exp) (BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); + /* called at new */ + int (*init) (RSA *rsa); + /* called at free */ + int (*finish) (RSA *rsa); + /* RSA_METHOD_FLAG_* things */ + int flags; + /* may be needed! */ + char *app_data; + /* + * New sign and verify functions: some libraries don't allow arbitrary + * data to be signed/verified: this allows them to be used. Note: for + * this to work the RSA_public_decrypt() and RSA_private_encrypt() should + * *NOT* be used RSA_sign(), RSA_verify() should be used instead. + */ + int (*rsa_sign) (int type, + const unsigned char *m, unsigned int m_length, + unsigned char *sigret, unsigned int *siglen, + const RSA *rsa); + int (*rsa_verify) (int dtype, const unsigned char *m, + unsigned int m_length, const unsigned char *sigbuf, + unsigned int siglen, const RSA *rsa); + /* + * If this callback is NULL, the builtin software RSA key-gen will be + * used. This is for behavioural compatibility whilst the code gets + * rewired, but one day it would be nice to assume there are no such + * things as "builtin software" implementations. + */ + int (*rsa_keygen) (RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb); + int (*rsa_multi_prime_keygen) (RSA *rsa, int bits, int primes, + BIGNUM *e, BN_GENCB *cb); +}; + +extern int int_rsa_verify(int dtype, const unsigned char *m, + unsigned int m_len, unsigned char *rm, + size_t *prm_len, const unsigned char *sigbuf, + size_t siglen, RSA *rsa); +/* Macros to test if a pkey or ctx is for a PSS key */ +#define pkey_is_pss(pkey) (pkey->ameth->pkey_id == EVP_PKEY_RSA_PSS) +#define pkey_ctx_is_pss(ctx) (ctx->pmeth->pkey_id == EVP_PKEY_RSA_PSS) + +RSA_PSS_PARAMS *rsa_pss_params_create(const EVP_MD *sigmd, + const EVP_MD *mgf1md, int saltlen); +int rsa_pss_get_param(const RSA_PSS_PARAMS *pss, const EVP_MD **pmd, + const EVP_MD **pmgf1md, int *psaltlen); +/* internal function to clear and free multi-prime parameters */ +void rsa_multip_info_free_ex(RSA_PRIME_INFO *pinfo); +void rsa_multip_info_free(RSA_PRIME_INFO *pinfo); +RSA_PRIME_INFO *rsa_multip_info_new(void); +int rsa_multip_calc_product(RSA *rsa); +int rsa_multip_cap(int bits); diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_meth.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_meth.c new file mode 100644 index 000000000..def19f375 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_meth.c @@ -0,0 +1,287 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "rsa_locl.h" +#include + +RSA_METHOD *RSA_meth_new(const char *name, int flags) +{ + RSA_METHOD *meth = OPENSSL_zalloc(sizeof(*meth)); + + if (meth != NULL) { + meth->flags = flags; + + meth->name = OPENSSL_strdup(name); + if (meth->name != NULL) + return meth; + + OPENSSL_free(meth); + } + + RSAerr(RSA_F_RSA_METH_NEW, ERR_R_MALLOC_FAILURE); + return NULL; +} + +void RSA_meth_free(RSA_METHOD *meth) +{ + if (meth != NULL) { + OPENSSL_free(meth->name); + OPENSSL_free(meth); + } +} + +RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth) +{ + RSA_METHOD *ret = OPENSSL_malloc(sizeof(*ret)); + + if (ret != NULL) { + memcpy(ret, meth, sizeof(*meth)); + + ret->name = OPENSSL_strdup(meth->name); + if (ret->name != NULL) + return ret; + + OPENSSL_free(ret); + } + + RSAerr(RSA_F_RSA_METH_DUP, ERR_R_MALLOC_FAILURE); + return NULL; +} + +const char *RSA_meth_get0_name(const RSA_METHOD *meth) +{ + return meth->name; +} + +int RSA_meth_set1_name(RSA_METHOD *meth, const char *name) +{ + char *tmpname = OPENSSL_strdup(name); + + if (tmpname == NULL) { + RSAerr(RSA_F_RSA_METH_SET1_NAME, ERR_R_MALLOC_FAILURE); + return 0; + } + + OPENSSL_free(meth->name); + meth->name = tmpname; + + return 1; +} + +int RSA_meth_get_flags(const RSA_METHOD *meth) +{ + return meth->flags; +} + +int RSA_meth_set_flags(RSA_METHOD *meth, int flags) +{ + meth->flags = flags; + return 1; +} + +void *RSA_meth_get0_app_data(const RSA_METHOD *meth) +{ + return meth->app_data; +} + +int RSA_meth_set0_app_data(RSA_METHOD *meth, void *app_data) +{ + meth->app_data = app_data; + return 1; +} + +int (*RSA_meth_get_pub_enc(const RSA_METHOD *meth)) + (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) +{ + return meth->rsa_pub_enc; +} + +int RSA_meth_set_pub_enc(RSA_METHOD *meth, + int (*pub_enc) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, + int padding)) +{ + meth->rsa_pub_enc = pub_enc; + return 1; +} + +int (*RSA_meth_get_pub_dec(const RSA_METHOD *meth)) + (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) +{ + return meth->rsa_pub_dec; +} + +int RSA_meth_set_pub_dec(RSA_METHOD *meth, + int (*pub_dec) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, + int padding)) +{ + meth->rsa_pub_dec = pub_dec; + return 1; +} + +int (*RSA_meth_get_priv_enc(const RSA_METHOD *meth)) + (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) +{ + return meth->rsa_priv_enc; +} + +int RSA_meth_set_priv_enc(RSA_METHOD *meth, + int (*priv_enc) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, + int padding)) +{ + meth->rsa_priv_enc = priv_enc; + return 1; +} + +int (*RSA_meth_get_priv_dec(const RSA_METHOD *meth)) + (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) +{ + return meth->rsa_priv_dec; +} + +int RSA_meth_set_priv_dec(RSA_METHOD *meth, + int (*priv_dec) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, + int padding)) +{ + meth->rsa_priv_dec = priv_dec; + return 1; +} + + /* Can be null */ +int (*RSA_meth_get_mod_exp(const RSA_METHOD *meth)) + (BIGNUM *r0, const BIGNUM *i, RSA *rsa, BN_CTX *ctx) +{ + return meth->rsa_mod_exp; +} + +int RSA_meth_set_mod_exp(RSA_METHOD *meth, + int (*mod_exp) (BIGNUM *r0, const BIGNUM *i, RSA *rsa, + BN_CTX *ctx)) +{ + meth->rsa_mod_exp = mod_exp; + return 1; +} + + /* Can be null */ +int (*RSA_meth_get_bn_mod_exp(const RSA_METHOD *meth)) + (BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) +{ + return meth->bn_mod_exp; +} + +int RSA_meth_set_bn_mod_exp(RSA_METHOD *meth, + int (*bn_mod_exp) (BIGNUM *r, + const BIGNUM *a, + const BIGNUM *p, + const BIGNUM *m, + BN_CTX *ctx, + BN_MONT_CTX *m_ctx)) +{ + meth->bn_mod_exp = bn_mod_exp; + return 1; +} + + /* called at new */ +int (*RSA_meth_get_init(const RSA_METHOD *meth)) (RSA *rsa) +{ + return meth->init; +} + +int RSA_meth_set_init(RSA_METHOD *meth, int (*init) (RSA *rsa)) +{ + meth->init = init; + return 1; +} + + /* called at free */ +int (*RSA_meth_get_finish(const RSA_METHOD *meth)) (RSA *rsa) +{ + return meth->finish; +} + +int RSA_meth_set_finish(RSA_METHOD *meth, int (*finish) (RSA *rsa)) +{ + meth->finish = finish; + return 1; +} + +int (*RSA_meth_get_sign(const RSA_METHOD *meth)) + (int type, + const unsigned char *m, unsigned int m_length, + unsigned char *sigret, unsigned int *siglen, + const RSA *rsa) +{ + return meth->rsa_sign; +} + +int RSA_meth_set_sign(RSA_METHOD *meth, + int (*sign) (int type, const unsigned char *m, + unsigned int m_length, + unsigned char *sigret, unsigned int *siglen, + const RSA *rsa)) +{ + meth->rsa_sign = sign; + return 1; +} + +int (*RSA_meth_get_verify(const RSA_METHOD *meth)) + (int dtype, const unsigned char *m, + unsigned int m_length, const unsigned char *sigbuf, + unsigned int siglen, const RSA *rsa) +{ + return meth->rsa_verify; +} + +int RSA_meth_set_verify(RSA_METHOD *meth, + int (*verify) (int dtype, const unsigned char *m, + unsigned int m_length, + const unsigned char *sigbuf, + unsigned int siglen, const RSA *rsa)) +{ + meth->rsa_verify = verify; + return 1; +} + +int (*RSA_meth_get_keygen(const RSA_METHOD *meth)) + (RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb) +{ + return meth->rsa_keygen; +} + +int RSA_meth_set_keygen(RSA_METHOD *meth, + int (*keygen) (RSA *rsa, int bits, BIGNUM *e, + BN_GENCB *cb)) +{ + meth->rsa_keygen = keygen; + return 1; +} + +int (*RSA_meth_get_multi_prime_keygen(const RSA_METHOD *meth)) + (RSA *rsa, int bits, int primes, BIGNUM *e, BN_GENCB *cb) +{ + return meth->rsa_multi_prime_keygen; +} + +int RSA_meth_set_multi_prime_keygen(RSA_METHOD *meth, + int (*keygen) (RSA *rsa, int bits, + int primes, BIGNUM *e, + BN_GENCB *cb)) +{ + meth->rsa_multi_prime_keygen = keygen; + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_mp.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_mp.c new file mode 100644 index 000000000..e7e810823 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_mp.c @@ -0,0 +1,115 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017 BaishanCloud. All rights reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "rsa_locl.h" + +void rsa_multip_info_free_ex(RSA_PRIME_INFO *pinfo) +{ + /* free pp and pinfo only */ + BN_clear_free(pinfo->pp); + OPENSSL_free(pinfo); +} + +void rsa_multip_info_free(RSA_PRIME_INFO *pinfo) +{ + /* free a RSA_PRIME_INFO structure */ + BN_clear_free(pinfo->r); + BN_clear_free(pinfo->d); + BN_clear_free(pinfo->t); + rsa_multip_info_free_ex(pinfo); +} + +RSA_PRIME_INFO *rsa_multip_info_new(void) +{ + RSA_PRIME_INFO *pinfo; + + /* create a RSA_PRIME_INFO structure */ + if ((pinfo = OPENSSL_zalloc(sizeof(RSA_PRIME_INFO))) == NULL) { + RSAerr(RSA_F_RSA_MULTIP_INFO_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + if ((pinfo->r = BN_secure_new()) == NULL) + goto err; + if ((pinfo->d = BN_secure_new()) == NULL) + goto err; + if ((pinfo->t = BN_secure_new()) == NULL) + goto err; + if ((pinfo->pp = BN_secure_new()) == NULL) + goto err; + + return pinfo; + + err: + BN_free(pinfo->r); + BN_free(pinfo->d); + BN_free(pinfo->t); + BN_free(pinfo->pp); + OPENSSL_free(pinfo); + return NULL; +} + +/* Refill products of primes */ +int rsa_multip_calc_product(RSA *rsa) +{ + RSA_PRIME_INFO *pinfo; + BIGNUM *p1 = NULL, *p2 = NULL; + BN_CTX *ctx = NULL; + int i, rv = 0, ex_primes; + + if ((ex_primes = sk_RSA_PRIME_INFO_num(rsa->prime_infos)) <= 0) { + /* invalid */ + goto err; + } + + if ((ctx = BN_CTX_new()) == NULL) + goto err; + + /* calculate pinfo->pp = p * q for first 'extra' prime */ + p1 = rsa->p; + p2 = rsa->q; + + for (i = 0; i < ex_primes; i++) { + pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i); + if (pinfo->pp == NULL) { + pinfo->pp = BN_secure_new(); + if (pinfo->pp == NULL) + goto err; + } + if (!BN_mul(pinfo->pp, p1, p2, ctx)) + goto err; + /* save previous one */ + p1 = pinfo->pp; + p2 = pinfo->r; + } + + rv = 1; + err: + BN_CTX_free(ctx); + return rv; +} + +int rsa_multip_cap(int bits) +{ + int cap = 5; + + if (bits < 1024) + cap = 2; + else if (bits < 4096) + cap = 3; + else if (bits < 8192) + cap = 4; + + if (cap > RSA_MAX_PRIME_NUM) + cap = RSA_MAX_PRIME_NUM; + + return cap; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_none.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_none.c new file mode 100644 index 000000000..f16cc6706 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_none.c @@ -0,0 +1,43 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include +#include + +int RSA_padding_add_none(unsigned char *to, int tlen, + const unsigned char *from, int flen) +{ + if (flen > tlen) { + RSAerr(RSA_F_RSA_PADDING_ADD_NONE, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + return 0; + } + + if (flen < tlen) { + RSAerr(RSA_F_RSA_PADDING_ADD_NONE, RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE); + return 0; + } + + memcpy(to, from, (unsigned int)flen); + return 1; +} + +int RSA_padding_check_none(unsigned char *to, int tlen, + const unsigned char *from, int flen, int num) +{ + + if (flen > tlen) { + RSAerr(RSA_F_RSA_PADDING_CHECK_NONE, RSA_R_DATA_TOO_LARGE); + return -1; + } + + memset(to, 0, tlen - flen); + memcpy(to + tlen - flen, from, flen); + return tlen; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_oaep.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_oaep.c new file mode 100644 index 000000000..689e6dc22 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_oaep.c @@ -0,0 +1,313 @@ +/* + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* EME-OAEP as defined in RFC 2437 (PKCS #1 v2.0) */ + +/* + * See Victor Shoup, "OAEP reconsidered," Nov. 2000, for problems with the security + * proof for the original OAEP scheme, which EME-OAEP is based on. A new + * proof can be found in E. Fujisaki, T. Okamoto, D. Pointcheval, J. Stern, + * "RSA-OEAP is Still Alive!", Dec. 2000, . The new proof has stronger requirements + * for the underlying permutation: "partial-one-wayness" instead of + * one-wayness. For the RSA function, this is an equivalent notion. + */ + +#include "internal/constant_time_locl.h" + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "rsa_locl.h" + +int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen, + const unsigned char *from, int flen, + const unsigned char *param, int plen) +{ + return RSA_padding_add_PKCS1_OAEP_mgf1(to, tlen, from, flen, + param, plen, NULL, NULL); +} + +int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen, + const unsigned char *from, int flen, + const unsigned char *param, int plen, + const EVP_MD *md, const EVP_MD *mgf1md) +{ + int rv = 0; + int i, emlen = tlen - 1; + unsigned char *db, *seed; + unsigned char *dbmask = NULL; + unsigned char seedmask[EVP_MAX_MD_SIZE]; + int mdlen, dbmask_len = 0; + + if (md == NULL) + md = EVP_sha1(); + if (mgf1md == NULL) + mgf1md = md; + + mdlen = EVP_MD_size(md); + + if (flen > emlen - 2 * mdlen - 1) { + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1, + RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + return 0; + } + + if (emlen < 2 * mdlen + 1) { + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1, + RSA_R_KEY_SIZE_TOO_SMALL); + return 0; + } + + to[0] = 0; + seed = to + 1; + db = to + mdlen + 1; + + if (!EVP_Digest((void *)param, plen, db, NULL, md, NULL)) + goto err; + memset(db + mdlen, 0, emlen - flen - 2 * mdlen - 1); + db[emlen - flen - mdlen - 1] = 0x01; + memcpy(db + emlen - flen - mdlen, from, (unsigned int)flen); + if (RAND_bytes(seed, mdlen) <= 0) + goto err; + + dbmask_len = emlen - mdlen; + dbmask = OPENSSL_malloc(dbmask_len); + if (dbmask == NULL) { + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (PKCS1_MGF1(dbmask, dbmask_len, seed, mdlen, mgf1md) < 0) + goto err; + for (i = 0; i < dbmask_len; i++) + db[i] ^= dbmask[i]; + + if (PKCS1_MGF1(seedmask, mdlen, db, dbmask_len, mgf1md) < 0) + goto err; + for (i = 0; i < mdlen; i++) + seed[i] ^= seedmask[i]; + rv = 1; + + err: + OPENSSL_cleanse(seedmask, sizeof(seedmask)); + OPENSSL_clear_free(dbmask, dbmask_len); + return rv; +} + +int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen, + const unsigned char *from, int flen, int num, + const unsigned char *param, int plen) +{ + return RSA_padding_check_PKCS1_OAEP_mgf1(to, tlen, from, flen, num, + param, plen, NULL, NULL); +} + +int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen, + const unsigned char *from, int flen, + int num, const unsigned char *param, + int plen, const EVP_MD *md, + const EVP_MD *mgf1md) +{ + int i, dblen = 0, mlen = -1, one_index = 0, msg_index; + unsigned int good = 0, found_one_byte, mask; + const unsigned char *maskedseed, *maskeddb; + /* + * |em| is the encoded message, zero-padded to exactly |num| bytes: em = + * Y || maskedSeed || maskedDB + */ + unsigned char *db = NULL, *em = NULL, seed[EVP_MAX_MD_SIZE], + phash[EVP_MAX_MD_SIZE]; + int mdlen; + + if (md == NULL) + md = EVP_sha1(); + if (mgf1md == NULL) + mgf1md = md; + + mdlen = EVP_MD_size(md); + + if (tlen <= 0 || flen <= 0) + return -1; + /* + * |num| is the length of the modulus; |flen| is the length of the + * encoded message. Therefore, for any |from| that was obtained by + * decrypting a ciphertext, we must have |flen| <= |num|. Similarly, + * num < 2 * mdlen + 2 must hold for the modulus irrespective of + * the ciphertext, see PKCS #1 v2.2, section 7.1.2. + * This does not leak any side-channel information. + */ + if (num < flen || num < 2 * mdlen + 2) { + RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1, + RSA_R_OAEP_DECODING_ERROR); + return -1; + } + + dblen = num - mdlen - 1; + db = OPENSSL_malloc(dblen); + if (db == NULL) { + RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + em = OPENSSL_malloc(num); + if (em == NULL) { + RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1, + ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + /* + * Caller is encouraged to pass zero-padded message created with + * BN_bn2binpad. Trouble is that since we can't read out of |from|'s + * bounds, it's impossible to have an invariant memory access pattern + * in case |from| was not zero-padded in advance. + */ + for (from += flen, em += num, i = 0; i < num; i++) { + mask = ~constant_time_is_zero(flen); + flen -= 1 & mask; + from -= 1 & mask; + *--em = *from & mask; + } + from = em; + + /* + * The first byte must be zero, however we must not leak if this is + * true. See James H. Manger, "A Chosen Ciphertext Attack on RSA + * Optimal Asymmetric Encryption Padding (OAEP) [...]", CRYPTO 2001). + */ + good = constant_time_is_zero(from[0]); + + maskedseed = from + 1; + maskeddb = from + 1 + mdlen; + + if (PKCS1_MGF1(seed, mdlen, maskeddb, dblen, mgf1md)) + goto cleanup; + for (i = 0; i < mdlen; i++) + seed[i] ^= maskedseed[i]; + + if (PKCS1_MGF1(db, dblen, seed, mdlen, mgf1md)) + goto cleanup; + for (i = 0; i < dblen; i++) + db[i] ^= maskeddb[i]; + + if (!EVP_Digest((void *)param, plen, phash, NULL, md, NULL)) + goto cleanup; + + good &= constant_time_is_zero(CRYPTO_memcmp(db, phash, mdlen)); + + found_one_byte = 0; + for (i = mdlen; i < dblen; i++) { + /* + * Padding consists of a number of 0-bytes, followed by a 1. + */ + unsigned int equals1 = constant_time_eq(db[i], 1); + unsigned int equals0 = constant_time_is_zero(db[i]); + one_index = constant_time_select_int(~found_one_byte & equals1, + i, one_index); + found_one_byte |= equals1; + good &= (found_one_byte | equals0); + } + + good &= found_one_byte; + + /* + * At this point |good| is zero unless the plaintext was valid, + * so plaintext-awareness ensures timing side-channels are no longer a + * concern. + */ + msg_index = one_index + 1; + mlen = dblen - msg_index; + + /* + * For good measure, do this check in constant tine as well. + */ + good &= constant_time_ge(tlen, mlen); + + /* + * Even though we can't fake result's length, we can pretend copying + * |tlen| bytes where |mlen| bytes would be real. Last |tlen| of |dblen| + * bytes are viewed as circular buffer with start at |tlen|-|mlen'|, + * where |mlen'| is "saturated" |mlen| value. Deducing information + * about failure or |mlen| would take attacker's ability to observe + * memory access pattern with byte granularity *as it occurs*. It + * should be noted that failure is indistinguishable from normal + * operation if |tlen| is fixed by protocol. + */ + tlen = constant_time_select_int(constant_time_lt(dblen, tlen), dblen, tlen); + msg_index = constant_time_select_int(good, msg_index, dblen - tlen); + mlen = dblen - msg_index; + for (from = db + msg_index, mask = good, i = 0; i < tlen; i++) { + unsigned int equals = constant_time_eq(i, mlen); + + from -= dblen & equals; /* if (i == dblen) rewind */ + mask &= mask ^ equals; /* if (i == dblen) mask = 0 */ + to[i] = constant_time_select_8(mask, from[i], to[i]); + } + + /* + * To avoid chosen ciphertext attacks, the error message should not + * reveal which kind of decoding error happened. + */ + RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1, + RSA_R_OAEP_DECODING_ERROR); + err_clear_last_constant_time(1 & good); + cleanup: + OPENSSL_cleanse(seed, sizeof(seed)); + OPENSSL_clear_free(db, dblen); + OPENSSL_clear_free(em, num); + + return constant_time_select_int(good, mlen, -1); +} + +int PKCS1_MGF1(unsigned char *mask, long len, + const unsigned char *seed, long seedlen, const EVP_MD *dgst) +{ + long i, outlen = 0; + unsigned char cnt[4]; + EVP_MD_CTX *c = EVP_MD_CTX_new(); + unsigned char md[EVP_MAX_MD_SIZE]; + int mdlen; + int rv = -1; + + if (c == NULL) + goto err; + mdlen = EVP_MD_size(dgst); + if (mdlen < 0) + goto err; + for (i = 0; outlen < len; i++) { + cnt[0] = (unsigned char)((i >> 24) & 255); + cnt[1] = (unsigned char)((i >> 16) & 255); + cnt[2] = (unsigned char)((i >> 8)) & 255; + cnt[3] = (unsigned char)(i & 255); + if (!EVP_DigestInit_ex(c, dgst, NULL) + || !EVP_DigestUpdate(c, seed, seedlen) + || !EVP_DigestUpdate(c, cnt, 4)) + goto err; + if (outlen + mdlen <= len) { + if (!EVP_DigestFinal_ex(c, mask + outlen, NULL)) + goto err; + outlen += mdlen; + } else { + if (!EVP_DigestFinal_ex(c, md, NULL)) + goto err; + memcpy(mask + outlen, md, len - outlen); + outlen = len; + } + } + rv = 0; + err: + OPENSSL_cleanse(md, sizeof(md)); + EVP_MD_CTX_free(c); + return rv; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_ossl.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_ossl.c new file mode 100644 index 000000000..465134257 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_ossl.c @@ -0,0 +1,970 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include "internal/bn_int.h" +#include "rsa_locl.h" +#include "internal/constant_time_locl.h" + +static int rsa_ossl_public_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int rsa_ossl_private_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int rsa_ossl_public_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int rsa_ossl_private_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int rsa_ossl_mod_exp(BIGNUM *r0, const BIGNUM *i, RSA *rsa, + BN_CTX *ctx); +static int rsa_ossl_init(RSA *rsa); +static int rsa_ossl_finish(RSA *rsa); +static RSA_METHOD rsa_pkcs1_ossl_meth = { + "OpenSSL PKCS#1 RSA", + rsa_ossl_public_encrypt, + rsa_ossl_public_decrypt, /* signature verification */ + rsa_ossl_private_encrypt, /* signing */ + rsa_ossl_private_decrypt, + rsa_ossl_mod_exp, + BN_mod_exp_mont, /* XXX probably we should not use Montgomery + * if e == 3 */ + rsa_ossl_init, + rsa_ossl_finish, + RSA_FLAG_FIPS_METHOD, /* flags */ + NULL, + 0, /* rsa_sign */ + 0, /* rsa_verify */ + NULL, /* rsa_keygen */ + NULL /* rsa_multi_prime_keygen */ +}; + +static const RSA_METHOD *default_RSA_meth = &rsa_pkcs1_ossl_meth; + +void RSA_set_default_method(const RSA_METHOD *meth) +{ + default_RSA_meth = meth; +} + +const RSA_METHOD *RSA_get_default_method(void) +{ + return default_RSA_meth; +} + +const RSA_METHOD *RSA_PKCS1_OpenSSL(void) +{ + return &rsa_pkcs1_ossl_meth; +} + +const RSA_METHOD *RSA_null_method(void) +{ + return NULL; +} + +static int rsa_ossl_public_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) +{ + BIGNUM *f, *ret; + int i, num = 0, r = -1; + unsigned char *buf = NULL; + BN_CTX *ctx = NULL; + + if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS) { + RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, RSA_R_MODULUS_TOO_LARGE); + return -1; + } + + if (BN_ucmp(rsa->n, rsa->e) <= 0) { + RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, RSA_R_BAD_E_VALUE); + return -1; + } + + /* for large moduli, enforce exponent limit */ + if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS) { + if (BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS) { + RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, RSA_R_BAD_E_VALUE); + return -1; + } + } + + if ((ctx = BN_CTX_new()) == NULL) + goto err; + BN_CTX_start(ctx); + f = BN_CTX_get(ctx); + ret = BN_CTX_get(ctx); + num = BN_num_bytes(rsa->n); + buf = OPENSSL_malloc(num); + if (ret == NULL || buf == NULL) { + RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto err; + } + + switch (padding) { + case RSA_PKCS1_PADDING: + i = RSA_padding_add_PKCS1_type_2(buf, num, from, flen); + break; + case RSA_PKCS1_OAEP_PADDING: + i = RSA_padding_add_PKCS1_OAEP(buf, num, from, flen, NULL, 0); + break; + case RSA_SSLV23_PADDING: + i = RSA_padding_add_SSLv23(buf, num, from, flen); + break; + case RSA_NO_PADDING: + i = RSA_padding_add_none(buf, num, from, flen); + break; + default: + RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE); + goto err; + } + if (i <= 0) + goto err; + + if (BN_bin2bn(buf, num, f) == NULL) + goto err; + + if (BN_ucmp(f, rsa->n) >= 0) { + /* usually the padding functions would catch this */ + RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, + RSA_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } + + if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) + if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, rsa->lock, + rsa->n, ctx)) + goto err; + + if (!rsa->meth->bn_mod_exp(ret, f, rsa->e, rsa->n, ctx, + rsa->_method_mod_n)) + goto err; + + /* + * BN_bn2binpad puts in leading 0 bytes if the number is less than + * the length of the modulus. + */ + r = BN_bn2binpad(ret, to, num); + err: + if (ctx != NULL) + BN_CTX_end(ctx); + BN_CTX_free(ctx); + OPENSSL_clear_free(buf, num); + return r; +} + +static BN_BLINDING *rsa_get_blinding(RSA *rsa, int *local, BN_CTX *ctx) +{ + BN_BLINDING *ret; + + CRYPTO_THREAD_write_lock(rsa->lock); + + if (rsa->blinding == NULL) { + rsa->blinding = RSA_setup_blinding(rsa, ctx); + } + + ret = rsa->blinding; + if (ret == NULL) + goto err; + + if (BN_BLINDING_is_current_thread(ret)) { + /* rsa->blinding is ours! */ + + *local = 1; + } else { + /* resort to rsa->mt_blinding instead */ + + /* + * instructs rsa_blinding_convert(), rsa_blinding_invert() that the + * BN_BLINDING is shared, meaning that accesses require locks, and + * that the blinding factor must be stored outside the BN_BLINDING + */ + *local = 0; + + if (rsa->mt_blinding == NULL) { + rsa->mt_blinding = RSA_setup_blinding(rsa, ctx); + } + ret = rsa->mt_blinding; + } + + err: + CRYPTO_THREAD_unlock(rsa->lock); + return ret; +} + +static int rsa_blinding_convert(BN_BLINDING *b, BIGNUM *f, BIGNUM *unblind, + BN_CTX *ctx) +{ + if (unblind == NULL) { + /* + * Local blinding: store the unblinding factor in BN_BLINDING. + */ + return BN_BLINDING_convert_ex(f, NULL, b, ctx); + } else { + /* + * Shared blinding: store the unblinding factor outside BN_BLINDING. + */ + int ret; + + BN_BLINDING_lock(b); + ret = BN_BLINDING_convert_ex(f, unblind, b, ctx); + BN_BLINDING_unlock(b); + + return ret; + } +} + +static int rsa_blinding_invert(BN_BLINDING *b, BIGNUM *f, BIGNUM *unblind, + BN_CTX *ctx) +{ + /* + * For local blinding, unblind is set to NULL, and BN_BLINDING_invert_ex + * will use the unblinding factor stored in BN_BLINDING. If BN_BLINDING + * is shared between threads, unblind must be non-null: + * BN_BLINDING_invert_ex will then use the local unblinding factor, and + * will only read the modulus from BN_BLINDING. In both cases it's safe + * to access the blinding without a lock. + */ + return BN_BLINDING_invert_ex(f, unblind, b, ctx); +} + +/* signing */ +static int rsa_ossl_private_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) +{ + BIGNUM *f, *ret, *res; + int i, num = 0, r = -1; + unsigned char *buf = NULL; + BN_CTX *ctx = NULL; + int local_blinding = 0; + /* + * Used only if the blinding structure is shared. A non-NULL unblind + * instructs rsa_blinding_convert() and rsa_blinding_invert() to store + * the unblinding factor outside the blinding structure. + */ + BIGNUM *unblind = NULL; + BN_BLINDING *blinding = NULL; + + if ((ctx = BN_CTX_new()) == NULL) + goto err; + BN_CTX_start(ctx); + f = BN_CTX_get(ctx); + ret = BN_CTX_get(ctx); + num = BN_num_bytes(rsa->n); + buf = OPENSSL_malloc(num); + if (ret == NULL || buf == NULL) { + RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto err; + } + + switch (padding) { + case RSA_PKCS1_PADDING: + i = RSA_padding_add_PKCS1_type_1(buf, num, from, flen); + break; + case RSA_X931_PADDING: + i = RSA_padding_add_X931(buf, num, from, flen); + break; + case RSA_NO_PADDING: + i = RSA_padding_add_none(buf, num, from, flen); + break; + case RSA_SSLV23_PADDING: + default: + RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE); + goto err; + } + if (i <= 0) + goto err; + + if (BN_bin2bn(buf, num, f) == NULL) + goto err; + + if (BN_ucmp(f, rsa->n) >= 0) { + /* usually the padding functions would catch this */ + RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, + RSA_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } + + if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) + if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, rsa->lock, + rsa->n, ctx)) + goto err; + + if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) { + blinding = rsa_get_blinding(rsa, &local_blinding, ctx); + if (blinding == NULL) { + RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); + goto err; + } + } + + if (blinding != NULL) { + if (!local_blinding && ((unblind = BN_CTX_get(ctx)) == NULL)) { + RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!rsa_blinding_convert(blinding, f, unblind, ctx)) + goto err; + } + + if ((rsa->flags & RSA_FLAG_EXT_PKEY) || + (rsa->version == RSA_ASN1_VERSION_MULTI) || + ((rsa->p != NULL) && + (rsa->q != NULL) && + (rsa->dmp1 != NULL) && (rsa->dmq1 != NULL) && (rsa->iqmp != NULL))) { + if (!rsa->meth->rsa_mod_exp(ret, f, rsa, ctx)) + goto err; + } else { + BIGNUM *d = BN_new(); + if (d == NULL) { + RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto err; + } + BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME); + + if (!rsa->meth->bn_mod_exp(ret, f, d, rsa->n, ctx, + rsa->_method_mod_n)) { + BN_free(d); + goto err; + } + /* We MUST free d before any further use of rsa->d */ + BN_free(d); + } + + if (blinding) + if (!rsa_blinding_invert(blinding, ret, unblind, ctx)) + goto err; + + if (padding == RSA_X931_PADDING) { + if (!BN_sub(f, rsa->n, ret)) + goto err; + if (BN_cmp(ret, f) > 0) + res = f; + else + res = ret; + } else { + res = ret; + } + + /* + * BN_bn2binpad puts in leading 0 bytes if the number is less than + * the length of the modulus. + */ + r = BN_bn2binpad(res, to, num); + err: + if (ctx != NULL) + BN_CTX_end(ctx); + BN_CTX_free(ctx); + OPENSSL_clear_free(buf, num); + return r; +} + +static int rsa_ossl_private_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) +{ + BIGNUM *f, *ret; + int j, num = 0, r = -1; + unsigned char *buf = NULL; + BN_CTX *ctx = NULL; + int local_blinding = 0; + /* + * Used only if the blinding structure is shared. A non-NULL unblind + * instructs rsa_blinding_convert() and rsa_blinding_invert() to store + * the unblinding factor outside the blinding structure. + */ + BIGNUM *unblind = NULL; + BN_BLINDING *blinding = NULL; + + if ((ctx = BN_CTX_new()) == NULL) + goto err; + BN_CTX_start(ctx); + f = BN_CTX_get(ctx); + ret = BN_CTX_get(ctx); + num = BN_num_bytes(rsa->n); + buf = OPENSSL_malloc(num); + if (ret == NULL || buf == NULL) { + RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* + * This check was for equality but PGP does evil things and chops off the + * top '0' bytes + */ + if (flen > num) { + RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, + RSA_R_DATA_GREATER_THAN_MOD_LEN); + goto err; + } + + /* make data into a big number */ + if (BN_bin2bn(from, (int)flen, f) == NULL) + goto err; + + if (BN_ucmp(f, rsa->n) >= 0) { + RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, + RSA_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } + + if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) { + blinding = rsa_get_blinding(rsa, &local_blinding, ctx); + if (blinding == NULL) { + RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, ERR_R_INTERNAL_ERROR); + goto err; + } + } + + if (blinding != NULL) { + if (!local_blinding && ((unblind = BN_CTX_get(ctx)) == NULL)) { + RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!rsa_blinding_convert(blinding, f, unblind, ctx)) + goto err; + } + + /* do the decrypt */ + if ((rsa->flags & RSA_FLAG_EXT_PKEY) || + (rsa->version == RSA_ASN1_VERSION_MULTI) || + ((rsa->p != NULL) && + (rsa->q != NULL) && + (rsa->dmp1 != NULL) && (rsa->dmq1 != NULL) && (rsa->iqmp != NULL))) { + if (!rsa->meth->rsa_mod_exp(ret, f, rsa, ctx)) + goto err; + } else { + BIGNUM *d = BN_new(); + if (d == NULL) { + RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, ERR_R_MALLOC_FAILURE); + goto err; + } + BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME); + + if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) + if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, rsa->lock, + rsa->n, ctx)) { + BN_free(d); + goto err; + } + if (!rsa->meth->bn_mod_exp(ret, f, d, rsa->n, ctx, + rsa->_method_mod_n)) { + BN_free(d); + goto err; + } + /* We MUST free d before any further use of rsa->d */ + BN_free(d); + } + + if (blinding) + if (!rsa_blinding_invert(blinding, ret, unblind, ctx)) + goto err; + + j = BN_bn2binpad(ret, buf, num); + + switch (padding) { + case RSA_PKCS1_PADDING: + r = RSA_padding_check_PKCS1_type_2(to, num, buf, j, num); + break; + case RSA_PKCS1_OAEP_PADDING: + r = RSA_padding_check_PKCS1_OAEP(to, num, buf, j, num, NULL, 0); + break; + case RSA_SSLV23_PADDING: + r = RSA_padding_check_SSLv23(to, num, buf, j, num); + break; + case RSA_NO_PADDING: + memcpy(to, buf, (r = j)); + break; + default: + RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, RSA_R_UNKNOWN_PADDING_TYPE); + goto err; + } + RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, RSA_R_PADDING_CHECK_FAILED); + err_clear_last_constant_time(r >= 0); + + err: + if (ctx != NULL) + BN_CTX_end(ctx); + BN_CTX_free(ctx); + OPENSSL_clear_free(buf, num); + return r; +} + +/* signature verification */ +static int rsa_ossl_public_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) +{ + BIGNUM *f, *ret; + int i, num = 0, r = -1; + unsigned char *buf = NULL; + BN_CTX *ctx = NULL; + + if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS) { + RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_MODULUS_TOO_LARGE); + return -1; + } + + if (BN_ucmp(rsa->n, rsa->e) <= 0) { + RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_BAD_E_VALUE); + return -1; + } + + /* for large moduli, enforce exponent limit */ + if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS) { + if (BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS) { + RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_BAD_E_VALUE); + return -1; + } + } + + if ((ctx = BN_CTX_new()) == NULL) + goto err; + BN_CTX_start(ctx); + f = BN_CTX_get(ctx); + ret = BN_CTX_get(ctx); + num = BN_num_bytes(rsa->n); + buf = OPENSSL_malloc(num); + if (ret == NULL || buf == NULL) { + RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* + * This check was for equality but PGP does evil things and chops off the + * top '0' bytes + */ + if (flen > num) { + RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_DATA_GREATER_THAN_MOD_LEN); + goto err; + } + + if (BN_bin2bn(from, flen, f) == NULL) + goto err; + + if (BN_ucmp(f, rsa->n) >= 0) { + RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, + RSA_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } + + if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) + if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, rsa->lock, + rsa->n, ctx)) + goto err; + + if (!rsa->meth->bn_mod_exp(ret, f, rsa->e, rsa->n, ctx, + rsa->_method_mod_n)) + goto err; + + if ((padding == RSA_X931_PADDING) && ((bn_get_words(ret)[0] & 0xf) != 12)) + if (!BN_sub(ret, rsa->n, ret)) + goto err; + + i = BN_bn2binpad(ret, buf, num); + + switch (padding) { + case RSA_PKCS1_PADDING: + r = RSA_padding_check_PKCS1_type_1(to, num, buf, i, num); + break; + case RSA_X931_PADDING: + r = RSA_padding_check_X931(to, num, buf, i, num); + break; + case RSA_NO_PADDING: + memcpy(to, buf, (r = i)); + break; + default: + RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_UNKNOWN_PADDING_TYPE); + goto err; + } + if (r < 0) + RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_PADDING_CHECK_FAILED); + + err: + if (ctx != NULL) + BN_CTX_end(ctx); + BN_CTX_free(ctx); + OPENSSL_clear_free(buf, num); + return r; +} + +static int rsa_ossl_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) +{ + BIGNUM *r1, *m1, *vrfy, *r2, *m[RSA_MAX_PRIME_NUM - 2]; + int ret = 0, i, ex_primes = 0, smooth = 0; + RSA_PRIME_INFO *pinfo; + + BN_CTX_start(ctx); + + r1 = BN_CTX_get(ctx); + r2 = BN_CTX_get(ctx); + m1 = BN_CTX_get(ctx); + vrfy = BN_CTX_get(ctx); + if (vrfy == NULL) + goto err; + + if (rsa->version == RSA_ASN1_VERSION_MULTI + && ((ex_primes = sk_RSA_PRIME_INFO_num(rsa->prime_infos)) <= 0 + || ex_primes > RSA_MAX_PRIME_NUM - 2)) + goto err; + + if (rsa->flags & RSA_FLAG_CACHE_PRIVATE) { + BIGNUM *factor = BN_new(); + + if (factor == NULL) + goto err; + + /* + * Make sure BN_mod_inverse in Montgomery initialization uses the + * BN_FLG_CONSTTIME flag + */ + if (!(BN_with_flags(factor, rsa->p, BN_FLG_CONSTTIME), + BN_MONT_CTX_set_locked(&rsa->_method_mod_p, rsa->lock, + factor, ctx)) + || !(BN_with_flags(factor, rsa->q, BN_FLG_CONSTTIME), + BN_MONT_CTX_set_locked(&rsa->_method_mod_q, rsa->lock, + factor, ctx))) { + BN_free(factor); + goto err; + } + for (i = 0; i < ex_primes; i++) { + pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i); + BN_with_flags(factor, pinfo->r, BN_FLG_CONSTTIME); + if (!BN_MONT_CTX_set_locked(&pinfo->m, rsa->lock, factor, ctx)) { + BN_free(factor); + goto err; + } + } + /* + * We MUST free |factor| before any further use of the prime factors + */ + BN_free(factor); + + smooth = (ex_primes == 0) + && (rsa->meth->bn_mod_exp == BN_mod_exp_mont) + && (BN_num_bits(rsa->q) == BN_num_bits(rsa->p)); + } + + if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) + if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, rsa->lock, + rsa->n, ctx)) + goto err; + + if (smooth) { + /* + * Conversion from Montgomery domain, a.k.a. Montgomery reduction, + * accepts values in [0-m*2^w) range. w is m's bit width rounded up + * to limb width. So that at the very least if |I| is fully reduced, + * i.e. less than p*q, we can count on from-to round to perform + * below modulo operations on |I|. Unlike BN_mod it's constant time. + */ + if (/* m1 = I moq q */ + !bn_from_mont_fixed_top(m1, I, rsa->_method_mod_q, ctx) + || !bn_to_mont_fixed_top(m1, m1, rsa->_method_mod_q, ctx) + /* m1 = m1^dmq1 mod q */ + || !BN_mod_exp_mont_consttime(m1, m1, rsa->dmq1, rsa->q, ctx, + rsa->_method_mod_q) + /* r1 = I mod p */ + || !bn_from_mont_fixed_top(r1, I, rsa->_method_mod_p, ctx) + || !bn_to_mont_fixed_top(r1, r1, rsa->_method_mod_p, ctx) + /* r1 = r1^dmp1 mod p */ + || !BN_mod_exp_mont_consttime(r1, r1, rsa->dmp1, rsa->p, ctx, + rsa->_method_mod_p) + /* r1 = (r1 - m1) mod p */ + /* + * bn_mod_sub_fixed_top is not regular modular subtraction, + * it can tolerate subtrahend to be larger than modulus, but + * not bit-wise wider. This makes up for uncommon q>p case, + * when |m1| can be larger than |rsa->p|. + */ + || !bn_mod_sub_fixed_top(r1, r1, m1, rsa->p) + + /* r1 = r1 * iqmp mod p */ + || !bn_to_mont_fixed_top(r1, r1, rsa->_method_mod_p, ctx) + || !bn_mul_mont_fixed_top(r1, r1, rsa->iqmp, rsa->_method_mod_p, + ctx) + /* r0 = r1 * q + m1 */ + || !bn_mul_fixed_top(r0, r1, rsa->q, ctx) + || !bn_mod_add_fixed_top(r0, r0, m1, rsa->n)) + goto err; + + goto tail; + } + + /* compute I mod q */ + { + BIGNUM *c = BN_new(); + if (c == NULL) + goto err; + BN_with_flags(c, I, BN_FLG_CONSTTIME); + + if (!BN_mod(r1, c, rsa->q, ctx)) { + BN_free(c); + goto err; + } + + { + BIGNUM *dmq1 = BN_new(); + if (dmq1 == NULL) { + BN_free(c); + goto err; + } + BN_with_flags(dmq1, rsa->dmq1, BN_FLG_CONSTTIME); + + /* compute r1^dmq1 mod q */ + if (!rsa->meth->bn_mod_exp(m1, r1, dmq1, rsa->q, ctx, + rsa->_method_mod_q)) { + BN_free(c); + BN_free(dmq1); + goto err; + } + /* We MUST free dmq1 before any further use of rsa->dmq1 */ + BN_free(dmq1); + } + + /* compute I mod p */ + if (!BN_mod(r1, c, rsa->p, ctx)) { + BN_free(c); + goto err; + } + /* We MUST free c before any further use of I */ + BN_free(c); + } + + { + BIGNUM *dmp1 = BN_new(); + if (dmp1 == NULL) + goto err; + BN_with_flags(dmp1, rsa->dmp1, BN_FLG_CONSTTIME); + + /* compute r1^dmp1 mod p */ + if (!rsa->meth->bn_mod_exp(r0, r1, dmp1, rsa->p, ctx, + rsa->_method_mod_p)) { + BN_free(dmp1); + goto err; + } + /* We MUST free dmp1 before any further use of rsa->dmp1 */ + BN_free(dmp1); + } + + /* + * calculate m_i in multi-prime case + * + * TODO: + * 1. squash the following two loops and calculate |m_i| there. + * 2. remove cc and reuse |c|. + * 3. remove |dmq1| and |dmp1| in previous block and use |di|. + * + * If these things are done, the code will be more readable. + */ + if (ex_primes > 0) { + BIGNUM *di = BN_new(), *cc = BN_new(); + + if (cc == NULL || di == NULL) { + BN_free(cc); + BN_free(di); + goto err; + } + + for (i = 0; i < ex_primes; i++) { + /* prepare m_i */ + if ((m[i] = BN_CTX_get(ctx)) == NULL) { + BN_free(cc); + BN_free(di); + goto err; + } + + pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i); + + /* prepare c and d_i */ + BN_with_flags(cc, I, BN_FLG_CONSTTIME); + BN_with_flags(di, pinfo->d, BN_FLG_CONSTTIME); + + if (!BN_mod(r1, cc, pinfo->r, ctx)) { + BN_free(cc); + BN_free(di); + goto err; + } + /* compute r1 ^ d_i mod r_i */ + if (!rsa->meth->bn_mod_exp(m[i], r1, di, pinfo->r, ctx, pinfo->m)) { + BN_free(cc); + BN_free(di); + goto err; + } + } + + BN_free(cc); + BN_free(di); + } + + if (!BN_sub(r0, r0, m1)) + goto err; + /* + * This will help stop the size of r0 increasing, which does affect the + * multiply if it optimised for a power of 2 size + */ + if (BN_is_negative(r0)) + if (!BN_add(r0, r0, rsa->p)) + goto err; + + if (!BN_mul(r1, r0, rsa->iqmp, ctx)) + goto err; + + { + BIGNUM *pr1 = BN_new(); + if (pr1 == NULL) + goto err; + BN_with_flags(pr1, r1, BN_FLG_CONSTTIME); + + if (!BN_mod(r0, pr1, rsa->p, ctx)) { + BN_free(pr1); + goto err; + } + /* We MUST free pr1 before any further use of r1 */ + BN_free(pr1); + } + + /* + * If p < q it is occasionally possible for the correction of adding 'p' + * if r0 is negative above to leave the result still negative. This can + * break the private key operations: the following second correction + * should *always* correct this rare occurrence. This will *never* happen + * with OpenSSL generated keys because they ensure p > q [steve] + */ + if (BN_is_negative(r0)) + if (!BN_add(r0, r0, rsa->p)) + goto err; + if (!BN_mul(r1, r0, rsa->q, ctx)) + goto err; + if (!BN_add(r0, r1, m1)) + goto err; + + /* add m_i to m in multi-prime case */ + if (ex_primes > 0) { + BIGNUM *pr2 = BN_new(); + + if (pr2 == NULL) + goto err; + + for (i = 0; i < ex_primes; i++) { + pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i); + if (!BN_sub(r1, m[i], r0)) { + BN_free(pr2); + goto err; + } + + if (!BN_mul(r2, r1, pinfo->t, ctx)) { + BN_free(pr2); + goto err; + } + + BN_with_flags(pr2, r2, BN_FLG_CONSTTIME); + + if (!BN_mod(r1, pr2, pinfo->r, ctx)) { + BN_free(pr2); + goto err; + } + + if (BN_is_negative(r1)) + if (!BN_add(r1, r1, pinfo->r)) { + BN_free(pr2); + goto err; + } + if (!BN_mul(r1, r1, pinfo->pp, ctx)) { + BN_free(pr2); + goto err; + } + if (!BN_add(r0, r0, r1)) { + BN_free(pr2); + goto err; + } + } + BN_free(pr2); + } + + tail: + if (rsa->e && rsa->n) { + if (rsa->meth->bn_mod_exp == BN_mod_exp_mont) { + if (!BN_mod_exp_mont(vrfy, r0, rsa->e, rsa->n, ctx, + rsa->_method_mod_n)) + goto err; + } else { + bn_correct_top(r0); + if (!rsa->meth->bn_mod_exp(vrfy, r0, rsa->e, rsa->n, ctx, + rsa->_method_mod_n)) + goto err; + } + /* + * If 'I' was greater than (or equal to) rsa->n, the operation will + * be equivalent to using 'I mod n'. However, the result of the + * verify will *always* be less than 'n' so we don't check for + * absolute equality, just congruency. + */ + if (!BN_sub(vrfy, vrfy, I)) + goto err; + if (BN_is_zero(vrfy)) { + bn_correct_top(r0); + ret = 1; + goto err; /* not actually error */ + } + if (!BN_mod(vrfy, vrfy, rsa->n, ctx)) + goto err; + if (BN_is_negative(vrfy)) + if (!BN_add(vrfy, vrfy, rsa->n)) + goto err; + if (!BN_is_zero(vrfy)) { + /* + * 'I' and 'vrfy' aren't congruent mod n. Don't leak + * miscalculated CRT output, just do a raw (slower) mod_exp and + * return that instead. + */ + + BIGNUM *d = BN_new(); + if (d == NULL) + goto err; + BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME); + + if (!rsa->meth->bn_mod_exp(r0, I, d, rsa->n, ctx, + rsa->_method_mod_n)) { + BN_free(d); + goto err; + } + /* We MUST free d before any further use of rsa->d */ + BN_free(d); + } + } + /* + * It's unfortunate that we have to bn_correct_top(r0). What hopefully + * saves the day is that correction is highly unlike, and private key + * operations are customarily performed on blinded message. Which means + * that attacker won't observe correlation with chosen plaintext. + * Secondly, remaining code would still handle it in same computational + * time and even conceal memory access pattern around corrected top. + */ + bn_correct_top(r0); + ret = 1; + err: + BN_CTX_end(ctx); + return ret; +} + +static int rsa_ossl_init(RSA *rsa) +{ + rsa->flags |= RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE; + return 1; +} + +static int rsa_ossl_finish(RSA *rsa) +{ + int i; + RSA_PRIME_INFO *pinfo; + + BN_MONT_CTX_free(rsa->_method_mod_n); + BN_MONT_CTX_free(rsa->_method_mod_p); + BN_MONT_CTX_free(rsa->_method_mod_q); + for (i = 0; i < sk_RSA_PRIME_INFO_num(rsa->prime_infos); i++) { + pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i); + BN_MONT_CTX_free(pinfo->m); + } + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_pk1.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_pk1.c new file mode 100644 index 000000000..062690741 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_pk1.c @@ -0,0 +1,255 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/constant_time_locl.h" + +#include +#include "internal/cryptlib.h" +#include +#include +#include + +int RSA_padding_add_PKCS1_type_1(unsigned char *to, int tlen, + const unsigned char *from, int flen) +{ + int j; + unsigned char *p; + + if (flen > (tlen - RSA_PKCS1_PADDING_SIZE)) { + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1, + RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + return 0; + } + + p = (unsigned char *)to; + + *(p++) = 0; + *(p++) = 1; /* Private Key BT (Block Type) */ + + /* pad out with 0xff data */ + j = tlen - 3 - flen; + memset(p, 0xff, j); + p += j; + *(p++) = '\0'; + memcpy(p, from, (unsigned int)flen); + return 1; +} + +int RSA_padding_check_PKCS1_type_1(unsigned char *to, int tlen, + const unsigned char *from, int flen, + int num) +{ + int i, j; + const unsigned char *p; + + p = from; + + /* + * The format is + * 00 || 01 || PS || 00 || D + * PS - padding string, at least 8 bytes of FF + * D - data. + */ + + if (num < 11) + return -1; + + /* Accept inputs with and without the leading 0-byte. */ + if (num == flen) { + if ((*p++) != 0x00) { + RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1, + RSA_R_INVALID_PADDING); + return -1; + } + flen--; + } + + if ((num != (flen + 1)) || (*(p++) != 0x01)) { + RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1, + RSA_R_BLOCK_TYPE_IS_NOT_01); + return -1; + } + + /* scan over padding data */ + j = flen - 1; /* one for type. */ + for (i = 0; i < j; i++) { + if (*p != 0xff) { /* should decrypt to 0xff */ + if (*p == 0) { + p++; + break; + } else { + RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1, + RSA_R_BAD_FIXED_HEADER_DECRYPT); + return -1; + } + } + p++; + } + + if (i == j) { + RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1, + RSA_R_NULL_BEFORE_BLOCK_MISSING); + return -1; + } + + if (i < 8) { + RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1, + RSA_R_BAD_PAD_BYTE_COUNT); + return -1; + } + i++; /* Skip over the '\0' */ + j -= i; + if (j > tlen) { + RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1, RSA_R_DATA_TOO_LARGE); + return -1; + } + memcpy(to, p, (unsigned int)j); + + return j; +} + +int RSA_padding_add_PKCS1_type_2(unsigned char *to, int tlen, + const unsigned char *from, int flen) +{ + int i, j; + unsigned char *p; + + if (flen > (tlen - 11)) { + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2, + RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + return 0; + } + + p = (unsigned char *)to; + + *(p++) = 0; + *(p++) = 2; /* Public Key BT (Block Type) */ + + /* pad out with non-zero random data */ + j = tlen - 3 - flen; + + if (RAND_bytes(p, j) <= 0) + return 0; + for (i = 0; i < j; i++) { + if (*p == '\0') + do { + if (RAND_bytes(p, 1) <= 0) + return 0; + } while (*p == '\0'); + p++; + } + + *(p++) = '\0'; + + memcpy(p, from, (unsigned int)flen); + return 1; +} + +int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen, + const unsigned char *from, int flen, + int num) +{ + int i; + /* |em| is the encoded message, zero-padded to exactly |num| bytes */ + unsigned char *em = NULL; + unsigned int good, found_zero_byte, mask; + int zero_index = 0, msg_index, mlen = -1; + + if (tlen <= 0 || flen <= 0) + return -1; + + /* + * PKCS#1 v1.5 decryption. See "PKCS #1 v2.2: RSA Cryptography Standard", + * section 7.2.2. + */ + + if (flen > num || num < 11) { + RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2, + RSA_R_PKCS_DECODING_ERROR); + return -1; + } + + em = OPENSSL_malloc(num); + if (em == NULL) { + RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2, ERR_R_MALLOC_FAILURE); + return -1; + } + /* + * Caller is encouraged to pass zero-padded message created with + * BN_bn2binpad. Trouble is that since we can't read out of |from|'s + * bounds, it's impossible to have an invariant memory access pattern + * in case |from| was not zero-padded in advance. + */ + for (from += flen, em += num, i = 0; i < num; i++) { + mask = ~constant_time_is_zero(flen); + flen -= 1 & mask; + from -= 1 & mask; + *--em = *from & mask; + } + from = em; + + good = constant_time_is_zero(from[0]); + good &= constant_time_eq(from[1], 2); + + /* scan over padding data */ + found_zero_byte = 0; + for (i = 2; i < num; i++) { + unsigned int equals0 = constant_time_is_zero(from[i]); + + zero_index = constant_time_select_int(~found_zero_byte & equals0, + i, zero_index); + found_zero_byte |= equals0; + } + + /* + * PS must be at least 8 bytes long, and it starts two bytes into |from|. + * If we never found a 0-byte, then |zero_index| is 0 and the check + * also fails. + */ + good &= constant_time_ge(zero_index, 2 + 8); + + /* + * Skip the zero byte. This is incorrect if we never found a zero-byte + * but in this case we also do not copy the message out. + */ + msg_index = zero_index + 1; + mlen = num - msg_index; + + /* + * For good measure, do this check in constant time as well. + */ + good &= constant_time_ge(tlen, mlen); + + /* + * Even though we can't fake result's length, we can pretend copying + * |tlen| bytes where |mlen| bytes would be real. Last |tlen| of |num| + * bytes are viewed as circular buffer with start at |tlen|-|mlen'|, + * where |mlen'| is "saturated" |mlen| value. Deducing information + * about failure or |mlen| would take attacker's ability to observe + * memory access pattern with byte granularity *as it occurs*. It + * should be noted that failure is indistinguishable from normal + * operation if |tlen| is fixed by protocol. + */ + tlen = constant_time_select_int(constant_time_lt(num, tlen), num, tlen); + msg_index = constant_time_select_int(good, msg_index, num - tlen); + mlen = num - msg_index; + for (from += msg_index, mask = good, i = 0; i < tlen; i++) { + unsigned int equals = constant_time_eq(i, mlen); + + from -= tlen & equals; /* if (i == mlen) rewind */ + mask &= mask ^ equals; /* if (i == mlen) mask = 0 */ + to[i] = constant_time_select_8(mask, from[i], to[i]); + } + + OPENSSL_clear_free(em, num); + RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2, RSA_R_PKCS_DECODING_ERROR); + err_clear_last_constant_time(1 & good); + + return constant_time_select_int(good, mlen, -1); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_pmeth.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_pmeth.c new file mode 100644 index 000000000..c10669f8a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_pmeth.c @@ -0,0 +1,860 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include +#include +#include "internal/evp_int.h" +#include "rsa_locl.h" + +/* RSA pkey context structure */ + +typedef struct { + /* Key gen parameters */ + int nbits; + BIGNUM *pub_exp; + int primes; + /* Keygen callback info */ + int gentmp[2]; + /* RSA padding mode */ + int pad_mode; + /* message digest */ + const EVP_MD *md; + /* message digest for MGF1 */ + const EVP_MD *mgf1md; + /* PSS salt length */ + int saltlen; + /* Minimum salt length or -1 if no PSS parameter restriction */ + int min_saltlen; + /* Temp buffer */ + unsigned char *tbuf; + /* OAEP label */ + unsigned char *oaep_label; + size_t oaep_labellen; +} RSA_PKEY_CTX; + +/* True if PSS parameters are restricted */ +#define rsa_pss_restricted(rctx) (rctx->min_saltlen != -1) + +static int pkey_rsa_init(EVP_PKEY_CTX *ctx) +{ + RSA_PKEY_CTX *rctx = OPENSSL_zalloc(sizeof(*rctx)); + + if (rctx == NULL) + return 0; + rctx->nbits = 1024; + rctx->primes = RSA_DEFAULT_PRIME_NUM; + if (pkey_ctx_is_pss(ctx)) + rctx->pad_mode = RSA_PKCS1_PSS_PADDING; + else + rctx->pad_mode = RSA_PKCS1_PADDING; + /* Maximum for sign, auto for verify */ + rctx->saltlen = RSA_PSS_SALTLEN_AUTO; + rctx->min_saltlen = -1; + ctx->data = rctx; + ctx->keygen_info = rctx->gentmp; + ctx->keygen_info_count = 2; + + return 1; +} + +static int pkey_rsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) +{ + RSA_PKEY_CTX *dctx, *sctx; + + if (!pkey_rsa_init(dst)) + return 0; + sctx = src->data; + dctx = dst->data; + dctx->nbits = sctx->nbits; + if (sctx->pub_exp) { + dctx->pub_exp = BN_dup(sctx->pub_exp); + if (!dctx->pub_exp) + return 0; + } + dctx->pad_mode = sctx->pad_mode; + dctx->md = sctx->md; + dctx->mgf1md = sctx->mgf1md; + if (sctx->oaep_label) { + OPENSSL_free(dctx->oaep_label); + dctx->oaep_label = OPENSSL_memdup(sctx->oaep_label, sctx->oaep_labellen); + if (!dctx->oaep_label) + return 0; + dctx->oaep_labellen = sctx->oaep_labellen; + } + return 1; +} + +static int setup_tbuf(RSA_PKEY_CTX *ctx, EVP_PKEY_CTX *pk) +{ + if (ctx->tbuf != NULL) + return 1; + if ((ctx->tbuf = OPENSSL_malloc(EVP_PKEY_size(pk->pkey))) == NULL) { + RSAerr(RSA_F_SETUP_TBUF, ERR_R_MALLOC_FAILURE); + return 0; + } + return 1; +} + +static void pkey_rsa_cleanup(EVP_PKEY_CTX *ctx) +{ + RSA_PKEY_CTX *rctx = ctx->data; + if (rctx) { + BN_free(rctx->pub_exp); + OPENSSL_free(rctx->tbuf); + OPENSSL_free(rctx->oaep_label); + OPENSSL_free(rctx); + } +} + +static int pkey_rsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, + size_t *siglen, const unsigned char *tbs, + size_t tbslen) +{ + int ret; + RSA_PKEY_CTX *rctx = ctx->data; + RSA *rsa = ctx->pkey->pkey.rsa; + + if (rctx->md) { + if (tbslen != (size_t)EVP_MD_size(rctx->md)) { + RSAerr(RSA_F_PKEY_RSA_SIGN, RSA_R_INVALID_DIGEST_LENGTH); + return -1; + } + + if (EVP_MD_type(rctx->md) == NID_mdc2) { + unsigned int sltmp; + if (rctx->pad_mode != RSA_PKCS1_PADDING) + return -1; + ret = RSA_sign_ASN1_OCTET_STRING(0, + tbs, tbslen, sig, &sltmp, rsa); + + if (ret <= 0) + return ret; + ret = sltmp; + } else if (rctx->pad_mode == RSA_X931_PADDING) { + if ((size_t)EVP_PKEY_size(ctx->pkey) < tbslen + 1) { + RSAerr(RSA_F_PKEY_RSA_SIGN, RSA_R_KEY_SIZE_TOO_SMALL); + return -1; + } + if (!setup_tbuf(rctx, ctx)) { + RSAerr(RSA_F_PKEY_RSA_SIGN, ERR_R_MALLOC_FAILURE); + return -1; + } + memcpy(rctx->tbuf, tbs, tbslen); + rctx->tbuf[tbslen] = RSA_X931_hash_id(EVP_MD_type(rctx->md)); + ret = RSA_private_encrypt(tbslen + 1, rctx->tbuf, + sig, rsa, RSA_X931_PADDING); + } else if (rctx->pad_mode == RSA_PKCS1_PADDING) { + unsigned int sltmp; + ret = RSA_sign(EVP_MD_type(rctx->md), + tbs, tbslen, sig, &sltmp, rsa); + if (ret <= 0) + return ret; + ret = sltmp; + } else if (rctx->pad_mode == RSA_PKCS1_PSS_PADDING) { + if (!setup_tbuf(rctx, ctx)) + return -1; + if (!RSA_padding_add_PKCS1_PSS_mgf1(rsa, + rctx->tbuf, tbs, + rctx->md, rctx->mgf1md, + rctx->saltlen)) + return -1; + ret = RSA_private_encrypt(RSA_size(rsa), rctx->tbuf, + sig, rsa, RSA_NO_PADDING); + } else { + return -1; + } + } else { + ret = RSA_private_encrypt(tbslen, tbs, sig, ctx->pkey->pkey.rsa, + rctx->pad_mode); + } + if (ret < 0) + return ret; + *siglen = ret; + return 1; +} + +static int pkey_rsa_verifyrecover(EVP_PKEY_CTX *ctx, + unsigned char *rout, size_t *routlen, + const unsigned char *sig, size_t siglen) +{ + int ret; + RSA_PKEY_CTX *rctx = ctx->data; + + if (rctx->md) { + if (rctx->pad_mode == RSA_X931_PADDING) { + if (!setup_tbuf(rctx, ctx)) + return -1; + ret = RSA_public_decrypt(siglen, sig, + rctx->tbuf, ctx->pkey->pkey.rsa, + RSA_X931_PADDING); + if (ret < 1) + return 0; + ret--; + if (rctx->tbuf[ret] != RSA_X931_hash_id(EVP_MD_type(rctx->md))) { + RSAerr(RSA_F_PKEY_RSA_VERIFYRECOVER, + RSA_R_ALGORITHM_MISMATCH); + return 0; + } + if (ret != EVP_MD_size(rctx->md)) { + RSAerr(RSA_F_PKEY_RSA_VERIFYRECOVER, + RSA_R_INVALID_DIGEST_LENGTH); + return 0; + } + if (rout) + memcpy(rout, rctx->tbuf, ret); + } else if (rctx->pad_mode == RSA_PKCS1_PADDING) { + size_t sltmp; + ret = int_rsa_verify(EVP_MD_type(rctx->md), + NULL, 0, rout, &sltmp, + sig, siglen, ctx->pkey->pkey.rsa); + if (ret <= 0) + return 0; + ret = sltmp; + } else { + return -1; + } + } else { + ret = RSA_public_decrypt(siglen, sig, rout, ctx->pkey->pkey.rsa, + rctx->pad_mode); + } + if (ret < 0) + return ret; + *routlen = ret; + return 1; +} + +static int pkey_rsa_verify(EVP_PKEY_CTX *ctx, + const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen) +{ + RSA_PKEY_CTX *rctx = ctx->data; + RSA *rsa = ctx->pkey->pkey.rsa; + size_t rslen; + + if (rctx->md) { + if (rctx->pad_mode == RSA_PKCS1_PADDING) + return RSA_verify(EVP_MD_type(rctx->md), tbs, tbslen, + sig, siglen, rsa); + if (tbslen != (size_t)EVP_MD_size(rctx->md)) { + RSAerr(RSA_F_PKEY_RSA_VERIFY, RSA_R_INVALID_DIGEST_LENGTH); + return -1; + } + if (rctx->pad_mode == RSA_X931_PADDING) { + if (pkey_rsa_verifyrecover(ctx, NULL, &rslen, sig, siglen) <= 0) + return 0; + } else if (rctx->pad_mode == RSA_PKCS1_PSS_PADDING) { + int ret; + if (!setup_tbuf(rctx, ctx)) + return -1; + ret = RSA_public_decrypt(siglen, sig, rctx->tbuf, + rsa, RSA_NO_PADDING); + if (ret <= 0) + return 0; + ret = RSA_verify_PKCS1_PSS_mgf1(rsa, tbs, + rctx->md, rctx->mgf1md, + rctx->tbuf, rctx->saltlen); + if (ret <= 0) + return 0; + return 1; + } else { + return -1; + } + } else { + if (!setup_tbuf(rctx, ctx)) + return -1; + rslen = RSA_public_decrypt(siglen, sig, rctx->tbuf, + rsa, rctx->pad_mode); + if (rslen == 0) + return 0; + } + + if ((rslen != tbslen) || memcmp(tbs, rctx->tbuf, rslen)) + return 0; + + return 1; + +} + +static int pkey_rsa_encrypt(EVP_PKEY_CTX *ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen) +{ + int ret; + RSA_PKEY_CTX *rctx = ctx->data; + + if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) { + int klen = RSA_size(ctx->pkey->pkey.rsa); + if (!setup_tbuf(rctx, ctx)) + return -1; + if (!RSA_padding_add_PKCS1_OAEP_mgf1(rctx->tbuf, klen, + in, inlen, + rctx->oaep_label, + rctx->oaep_labellen, + rctx->md, rctx->mgf1md)) + return -1; + ret = RSA_public_encrypt(klen, rctx->tbuf, out, + ctx->pkey->pkey.rsa, RSA_NO_PADDING); + } else { + ret = RSA_public_encrypt(inlen, in, out, ctx->pkey->pkey.rsa, + rctx->pad_mode); + } + if (ret < 0) + return ret; + *outlen = ret; + return 1; +} + +static int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen) +{ + int ret; + RSA_PKEY_CTX *rctx = ctx->data; + + if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) { + if (!setup_tbuf(rctx, ctx)) + return -1; + ret = RSA_private_decrypt(inlen, in, rctx->tbuf, + ctx->pkey->pkey.rsa, RSA_NO_PADDING); + if (ret <= 0) + return ret; + ret = RSA_padding_check_PKCS1_OAEP_mgf1(out, ret, rctx->tbuf, + ret, ret, + rctx->oaep_label, + rctx->oaep_labellen, + rctx->md, rctx->mgf1md); + } else { + ret = RSA_private_decrypt(inlen, in, out, ctx->pkey->pkey.rsa, + rctx->pad_mode); + } + if (ret < 0) + return ret; + *outlen = ret; + return 1; +} + +static int check_padding_md(const EVP_MD *md, int padding) +{ + int mdnid; + + if (!md) + return 1; + + mdnid = EVP_MD_type(md); + + if (padding == RSA_NO_PADDING) { + RSAerr(RSA_F_CHECK_PADDING_MD, RSA_R_INVALID_PADDING_MODE); + return 0; + } + + if (padding == RSA_X931_PADDING) { + if (RSA_X931_hash_id(mdnid) == -1) { + RSAerr(RSA_F_CHECK_PADDING_MD, RSA_R_INVALID_X931_DIGEST); + return 0; + } + } else { + switch(mdnid) { + /* List of all supported RSA digests */ + case NID_sha1: + case NID_sha224: + case NID_sha256: + case NID_sha384: + case NID_sha512: + case NID_md5: + case NID_md5_sha1: + case NID_md2: + case NID_md4: + case NID_mdc2: + case NID_ripemd160: + case NID_sha3_224: + case NID_sha3_256: + case NID_sha3_384: + case NID_sha3_512: + return 1; + + default: + RSAerr(RSA_F_CHECK_PADDING_MD, RSA_R_INVALID_DIGEST); + return 0; + + } + } + + return 1; +} + +static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) +{ + RSA_PKEY_CTX *rctx = ctx->data; + + switch (type) { + case EVP_PKEY_CTRL_RSA_PADDING: + if ((p1 >= RSA_PKCS1_PADDING) && (p1 <= RSA_PKCS1_PSS_PADDING)) { + if (!check_padding_md(rctx->md, p1)) + return 0; + if (p1 == RSA_PKCS1_PSS_PADDING) { + if (!(ctx->operation & + (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY))) + goto bad_pad; + if (!rctx->md) + rctx->md = EVP_sha1(); + } else if (pkey_ctx_is_pss(ctx)) { + goto bad_pad; + } + if (p1 == RSA_PKCS1_OAEP_PADDING) { + if (!(ctx->operation & EVP_PKEY_OP_TYPE_CRYPT)) + goto bad_pad; + if (!rctx->md) + rctx->md = EVP_sha1(); + } + rctx->pad_mode = p1; + return 1; + } + bad_pad: + RSAerr(RSA_F_PKEY_RSA_CTRL, + RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE); + return -2; + + case EVP_PKEY_CTRL_GET_RSA_PADDING: + *(int *)p2 = rctx->pad_mode; + return 1; + + case EVP_PKEY_CTRL_RSA_PSS_SALTLEN: + case EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN: + if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING) { + RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PSS_SALTLEN); + return -2; + } + if (type == EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN) { + *(int *)p2 = rctx->saltlen; + } else { + if (p1 < RSA_PSS_SALTLEN_MAX) + return -2; + if (rsa_pss_restricted(rctx)) { + if (p1 == RSA_PSS_SALTLEN_AUTO + && ctx->operation == EVP_PKEY_OP_VERIFY) { + RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PSS_SALTLEN); + return -2; + } + if ((p1 == RSA_PSS_SALTLEN_DIGEST + && rctx->min_saltlen > EVP_MD_size(rctx->md)) + || (p1 >= 0 && p1 < rctx->min_saltlen)) { + RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_PSS_SALTLEN_TOO_SMALL); + return 0; + } + } + rctx->saltlen = p1; + } + return 1; + + case EVP_PKEY_CTRL_RSA_KEYGEN_BITS: + if (p1 < RSA_MIN_MODULUS_BITS) { + RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_KEY_SIZE_TOO_SMALL); + return -2; + } + rctx->nbits = p1; + return 1; + + case EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP: + if (p2 == NULL || !BN_is_odd((BIGNUM *)p2) || BN_is_one((BIGNUM *)p2)) { + RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_BAD_E_VALUE); + return -2; + } + BN_free(rctx->pub_exp); + rctx->pub_exp = p2; + return 1; + + case EVP_PKEY_CTRL_RSA_KEYGEN_PRIMES: + if (p1 < RSA_DEFAULT_PRIME_NUM || p1 > RSA_MAX_PRIME_NUM) { + RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_KEY_PRIME_NUM_INVALID); + return -2; + } + rctx->primes = p1; + return 1; + + case EVP_PKEY_CTRL_RSA_OAEP_MD: + case EVP_PKEY_CTRL_GET_RSA_OAEP_MD: + if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) { + RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PADDING_MODE); + return -2; + } + if (type == EVP_PKEY_CTRL_GET_RSA_OAEP_MD) + *(const EVP_MD **)p2 = rctx->md; + else + rctx->md = p2; + return 1; + + case EVP_PKEY_CTRL_MD: + if (!check_padding_md(p2, rctx->pad_mode)) + return 0; + if (rsa_pss_restricted(rctx)) { + if (EVP_MD_type(rctx->md) == EVP_MD_type(p2)) + return 1; + RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_DIGEST_NOT_ALLOWED); + return 0; + } + rctx->md = p2; + return 1; + + case EVP_PKEY_CTRL_GET_MD: + *(const EVP_MD **)p2 = rctx->md; + return 1; + + case EVP_PKEY_CTRL_RSA_MGF1_MD: + case EVP_PKEY_CTRL_GET_RSA_MGF1_MD: + if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING + && rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) { + RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_MGF1_MD); + return -2; + } + if (type == EVP_PKEY_CTRL_GET_RSA_MGF1_MD) { + if (rctx->mgf1md) + *(const EVP_MD **)p2 = rctx->mgf1md; + else + *(const EVP_MD **)p2 = rctx->md; + } else { + if (rsa_pss_restricted(rctx)) { + if (EVP_MD_type(rctx->mgf1md) == EVP_MD_type(p2)) + return 1; + RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_MGF1_DIGEST_NOT_ALLOWED); + return 0; + } + rctx->mgf1md = p2; + } + return 1; + + case EVP_PKEY_CTRL_RSA_OAEP_LABEL: + if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) { + RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PADDING_MODE); + return -2; + } + OPENSSL_free(rctx->oaep_label); + if (p2 && p1 > 0) { + rctx->oaep_label = p2; + rctx->oaep_labellen = p1; + } else { + rctx->oaep_label = NULL; + rctx->oaep_labellen = 0; + } + return 1; + + case EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL: + if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) { + RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PADDING_MODE); + return -2; + } + *(unsigned char **)p2 = rctx->oaep_label; + return rctx->oaep_labellen; + + case EVP_PKEY_CTRL_DIGESTINIT: + case EVP_PKEY_CTRL_PKCS7_SIGN: +#ifndef OPENSSL_NO_CMS + case EVP_PKEY_CTRL_CMS_SIGN: +#endif + return 1; + + case EVP_PKEY_CTRL_PKCS7_ENCRYPT: + case EVP_PKEY_CTRL_PKCS7_DECRYPT: +#ifndef OPENSSL_NO_CMS + case EVP_PKEY_CTRL_CMS_DECRYPT: + case EVP_PKEY_CTRL_CMS_ENCRYPT: +#endif + if (!pkey_ctx_is_pss(ctx)) + return 1; + /* fall through */ + case EVP_PKEY_CTRL_PEER_KEY: + RSAerr(RSA_F_PKEY_RSA_CTRL, + RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + + default: + return -2; + + } +} + +static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx, + const char *type, const char *value) +{ + if (value == NULL) { + RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_VALUE_MISSING); + return 0; + } + if (strcmp(type, "rsa_padding_mode") == 0) { + int pm; + + if (strcmp(value, "pkcs1") == 0) { + pm = RSA_PKCS1_PADDING; + } else if (strcmp(value, "sslv23") == 0) { + pm = RSA_SSLV23_PADDING; + } else if (strcmp(value, "none") == 0) { + pm = RSA_NO_PADDING; + } else if (strcmp(value, "oeap") == 0) { + pm = RSA_PKCS1_OAEP_PADDING; + } else if (strcmp(value, "oaep") == 0) { + pm = RSA_PKCS1_OAEP_PADDING; + } else if (strcmp(value, "x931") == 0) { + pm = RSA_X931_PADDING; + } else if (strcmp(value, "pss") == 0) { + pm = RSA_PKCS1_PSS_PADDING; + } else { + RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_UNKNOWN_PADDING_TYPE); + return -2; + } + return EVP_PKEY_CTX_set_rsa_padding(ctx, pm); + } + + if (strcmp(type, "rsa_pss_saltlen") == 0) { + int saltlen; + + if (!strcmp(value, "digest")) + saltlen = RSA_PSS_SALTLEN_DIGEST; + else if (!strcmp(value, "max")) + saltlen = RSA_PSS_SALTLEN_MAX; + else if (!strcmp(value, "auto")) + saltlen = RSA_PSS_SALTLEN_AUTO; + else + saltlen = atoi(value); + return EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, saltlen); + } + + if (strcmp(type, "rsa_keygen_bits") == 0) { + int nbits = atoi(value); + + return EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, nbits); + } + + if (strcmp(type, "rsa_keygen_pubexp") == 0) { + int ret; + + BIGNUM *pubexp = NULL; + if (!BN_asc2bn(&pubexp, value)) + return 0; + ret = EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, pubexp); + if (ret <= 0) + BN_free(pubexp); + return ret; + } + + if (strcmp(type, "rsa_keygen_primes") == 0) { + int nprimes = atoi(value); + + return EVP_PKEY_CTX_set_rsa_keygen_primes(ctx, nprimes); + } + + if (strcmp(type, "rsa_mgf1_md") == 0) + return EVP_PKEY_CTX_md(ctx, + EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, + EVP_PKEY_CTRL_RSA_MGF1_MD, value); + + if (pkey_ctx_is_pss(ctx)) { + + if (strcmp(type, "rsa_pss_keygen_mgf1_md") == 0) + return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_KEYGEN, + EVP_PKEY_CTRL_RSA_MGF1_MD, value); + + if (strcmp(type, "rsa_pss_keygen_md") == 0) + return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_KEYGEN, + EVP_PKEY_CTRL_MD, value); + + if (strcmp(type, "rsa_pss_keygen_saltlen") == 0) { + int saltlen = atoi(value); + + return EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(ctx, saltlen); + } + } + + if (strcmp(type, "rsa_oaep_md") == 0) + return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_TYPE_CRYPT, + EVP_PKEY_CTRL_RSA_OAEP_MD, value); + + if (strcmp(type, "rsa_oaep_label") == 0) { + unsigned char *lab; + long lablen; + int ret; + + lab = OPENSSL_hexstr2buf(value, &lablen); + if (!lab) + return 0; + ret = EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, lab, lablen); + if (ret <= 0) + OPENSSL_free(lab); + return ret; + } + + return -2; +} + +/* Set PSS parameters when generating a key, if necessary */ +static int rsa_set_pss_param(RSA *rsa, EVP_PKEY_CTX *ctx) +{ + RSA_PKEY_CTX *rctx = ctx->data; + + if (!pkey_ctx_is_pss(ctx)) + return 1; + /* If all parameters are default values don't set pss */ + if (rctx->md == NULL && rctx->mgf1md == NULL && rctx->saltlen == -2) + return 1; + rsa->pss = rsa_pss_params_create(rctx->md, rctx->mgf1md, + rctx->saltlen == -2 ? 0 : rctx->saltlen); + if (rsa->pss == NULL) + return 0; + return 1; +} + +static int pkey_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) +{ + RSA *rsa = NULL; + RSA_PKEY_CTX *rctx = ctx->data; + BN_GENCB *pcb; + int ret; + + if (rctx->pub_exp == NULL) { + rctx->pub_exp = BN_new(); + if (rctx->pub_exp == NULL || !BN_set_word(rctx->pub_exp, RSA_F4)) + return 0; + } + rsa = RSA_new(); + if (rsa == NULL) + return 0; + if (ctx->pkey_gencb) { + pcb = BN_GENCB_new(); + if (pcb == NULL) { + RSA_free(rsa); + return 0; + } + evp_pkey_set_cb_translate(pcb, ctx); + } else { + pcb = NULL; + } + ret = RSA_generate_multi_prime_key(rsa, rctx->nbits, rctx->primes, + rctx->pub_exp, pcb); + BN_GENCB_free(pcb); + if (ret > 0 && !rsa_set_pss_param(rsa, ctx)) { + RSA_free(rsa); + return 0; + } + if (ret > 0) + EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, rsa); + else + RSA_free(rsa); + return ret; +} + +const EVP_PKEY_METHOD rsa_pkey_meth = { + EVP_PKEY_RSA, + EVP_PKEY_FLAG_AUTOARGLEN, + pkey_rsa_init, + pkey_rsa_copy, + pkey_rsa_cleanup, + + 0, 0, + + 0, + pkey_rsa_keygen, + + 0, + pkey_rsa_sign, + + 0, + pkey_rsa_verify, + + 0, + pkey_rsa_verifyrecover, + + 0, 0, 0, 0, + + 0, + pkey_rsa_encrypt, + + 0, + pkey_rsa_decrypt, + + 0, 0, + + pkey_rsa_ctrl, + pkey_rsa_ctrl_str +}; + +/* + * Called for PSS sign or verify initialisation: checks PSS parameter + * sanity and sets any restrictions on key usage. + */ + +static int pkey_pss_init(EVP_PKEY_CTX *ctx) +{ + RSA *rsa; + RSA_PKEY_CTX *rctx = ctx->data; + const EVP_MD *md; + const EVP_MD *mgf1md; + int min_saltlen, max_saltlen; + + /* Should never happen */ + if (!pkey_ctx_is_pss(ctx)) + return 0; + rsa = ctx->pkey->pkey.rsa; + /* If no restrictions just return */ + if (rsa->pss == NULL) + return 1; + /* Get and check parameters */ + if (!rsa_pss_get_param(rsa->pss, &md, &mgf1md, &min_saltlen)) + return 0; + + /* See if minimum salt length exceeds maximum possible */ + max_saltlen = RSA_size(rsa) - EVP_MD_size(md); + if ((RSA_bits(rsa) & 0x7) == 1) + max_saltlen--; + if (min_saltlen > max_saltlen) { + RSAerr(RSA_F_PKEY_PSS_INIT, RSA_R_INVALID_SALT_LENGTH); + return 0; + } + + rctx->min_saltlen = min_saltlen; + + /* + * Set PSS restrictions as defaults: we can then block any attempt to + * use invalid values in pkey_rsa_ctrl + */ + + rctx->md = md; + rctx->mgf1md = mgf1md; + rctx->saltlen = min_saltlen; + + return 1; +} + +const EVP_PKEY_METHOD rsa_pss_pkey_meth = { + EVP_PKEY_RSA_PSS, + EVP_PKEY_FLAG_AUTOARGLEN, + pkey_rsa_init, + pkey_rsa_copy, + pkey_rsa_cleanup, + + 0, 0, + + 0, + pkey_rsa_keygen, + + pkey_pss_init, + pkey_rsa_sign, + + pkey_pss_init, + pkey_rsa_verify, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + pkey_rsa_ctrl, + pkey_rsa_ctrl_str +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_prn.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_prn.c new file mode 100644 index 000000000..b5f4bce2a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_prn.c @@ -0,0 +1,42 @@ +/* + * Copyright 2006-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include + +#ifndef OPENSSL_NO_STDIO +int RSA_print_fp(FILE *fp, const RSA *x, int off) +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + RSAerr(RSA_F_RSA_PRINT_FP, ERR_R_BUF_LIB); + return 0; + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = RSA_print(b, x, off); + BIO_free(b); + return ret; +} +#endif + +int RSA_print(BIO *bp, const RSA *x, int off) +{ + EVP_PKEY *pk; + int ret; + pk = EVP_PKEY_new(); + if (pk == NULL || !EVP_PKEY_set1_RSA(pk, (RSA *)x)) + return 0; + ret = EVP_PKEY_print_private(bp, pk, off, NULL); + EVP_PKEY_free(pk); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_pss.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_pss.c new file mode 100644 index 000000000..f7c575d00 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_pss.c @@ -0,0 +1,255 @@ +/* + * Copyright 2005-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include "rsa_locl.h" + +static const unsigned char zeroes[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + +#if defined(_MSC_VER) && defined(_ARM_) +# pragma optimize("g", off) +#endif + +int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash, + const EVP_MD *Hash, const unsigned char *EM, + int sLen) +{ + return RSA_verify_PKCS1_PSS_mgf1(rsa, mHash, Hash, NULL, EM, sLen); +} + +int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash, + const EVP_MD *Hash, const EVP_MD *mgf1Hash, + const unsigned char *EM, int sLen) +{ + int i; + int ret = 0; + int hLen, maskedDBLen, MSBits, emLen; + const unsigned char *H; + unsigned char *DB = NULL; + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + unsigned char H_[EVP_MAX_MD_SIZE]; + + if (ctx == NULL) + goto err; + + if (mgf1Hash == NULL) + mgf1Hash = Hash; + + hLen = EVP_MD_size(Hash); + if (hLen < 0) + goto err; + /*- + * Negative sLen has special meanings: + * -1 sLen == hLen + * -2 salt length is autorecovered from signature + * -3 salt length is maximized + * -N reserved + */ + if (sLen == RSA_PSS_SALTLEN_DIGEST) { + sLen = hLen; + } else if (sLen < RSA_PSS_SALTLEN_MAX) { + RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_SLEN_CHECK_FAILED); + goto err; + } + + MSBits = (BN_num_bits(rsa->n) - 1) & 0x7; + emLen = RSA_size(rsa); + if (EM[0] & (0xFF << MSBits)) { + RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_FIRST_OCTET_INVALID); + goto err; + } + if (MSBits == 0) { + EM++; + emLen--; + } + if (emLen < hLen + 2) { + RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_DATA_TOO_LARGE); + goto err; + } + if (sLen == RSA_PSS_SALTLEN_MAX) { + sLen = emLen - hLen - 2; + } else if (sLen > emLen - hLen - 2) { /* sLen can be small negative */ + RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_DATA_TOO_LARGE); + goto err; + } + if (EM[emLen - 1] != 0xbc) { + RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_LAST_OCTET_INVALID); + goto err; + } + maskedDBLen = emLen - hLen - 1; + H = EM + maskedDBLen; + DB = OPENSSL_malloc(maskedDBLen); + if (DB == NULL) { + RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, ERR_R_MALLOC_FAILURE); + goto err; + } + if (PKCS1_MGF1(DB, maskedDBLen, H, hLen, mgf1Hash) < 0) + goto err; + for (i = 0; i < maskedDBLen; i++) + DB[i] ^= EM[i]; + if (MSBits) + DB[0] &= 0xFF >> (8 - MSBits); + for (i = 0; DB[i] == 0 && i < (maskedDBLen - 1); i++) ; + if (DB[i++] != 0x1) { + RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_SLEN_RECOVERY_FAILED); + goto err; + } + if (sLen != RSA_PSS_SALTLEN_AUTO && (maskedDBLen - i) != sLen) { + RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_SLEN_CHECK_FAILED); + goto err; + } + if (!EVP_DigestInit_ex(ctx, Hash, NULL) + || !EVP_DigestUpdate(ctx, zeroes, sizeof(zeroes)) + || !EVP_DigestUpdate(ctx, mHash, hLen)) + goto err; + if (maskedDBLen - i) { + if (!EVP_DigestUpdate(ctx, DB + i, maskedDBLen - i)) + goto err; + } + if (!EVP_DigestFinal_ex(ctx, H_, NULL)) + goto err; + if (memcmp(H_, H, hLen)) { + RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_BAD_SIGNATURE); + ret = 0; + } else { + ret = 1; + } + + err: + OPENSSL_free(DB); + EVP_MD_CTX_free(ctx); + + return ret; + +} + +int RSA_padding_add_PKCS1_PSS(RSA *rsa, unsigned char *EM, + const unsigned char *mHash, + const EVP_MD *Hash, int sLen) +{ + return RSA_padding_add_PKCS1_PSS_mgf1(rsa, EM, mHash, Hash, NULL, sLen); +} + +int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM, + const unsigned char *mHash, + const EVP_MD *Hash, const EVP_MD *mgf1Hash, + int sLen) +{ + int i; + int ret = 0; + int hLen, maskedDBLen, MSBits, emLen; + unsigned char *H, *salt = NULL, *p; + EVP_MD_CTX *ctx = NULL; + + if (mgf1Hash == NULL) + mgf1Hash = Hash; + + hLen = EVP_MD_size(Hash); + if (hLen < 0) + goto err; + /*- + * Negative sLen has special meanings: + * -1 sLen == hLen + * -2 salt length is maximized + * -3 same as above (on signing) + * -N reserved + */ + if (sLen == RSA_PSS_SALTLEN_DIGEST) { + sLen = hLen; + } else if (sLen == RSA_PSS_SALTLEN_MAX_SIGN) { + sLen = RSA_PSS_SALTLEN_MAX; + } else if (sLen < RSA_PSS_SALTLEN_MAX) { + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1, RSA_R_SLEN_CHECK_FAILED); + goto err; + } + + MSBits = (BN_num_bits(rsa->n) - 1) & 0x7; + emLen = RSA_size(rsa); + if (MSBits == 0) { + *EM++ = 0; + emLen--; + } + if (emLen < hLen + 2) { + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1, + RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + goto err; + } + if (sLen == RSA_PSS_SALTLEN_MAX) { + sLen = emLen - hLen - 2; + } else if (sLen > emLen - hLen - 2) { + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1, + RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + goto err; + } + if (sLen > 0) { + salt = OPENSSL_malloc(sLen); + if (salt == NULL) { + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1, + ERR_R_MALLOC_FAILURE); + goto err; + } + if (RAND_bytes(salt, sLen) <= 0) + goto err; + } + maskedDBLen = emLen - hLen - 1; + H = EM + maskedDBLen; + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) + goto err; + if (!EVP_DigestInit_ex(ctx, Hash, NULL) + || !EVP_DigestUpdate(ctx, zeroes, sizeof(zeroes)) + || !EVP_DigestUpdate(ctx, mHash, hLen)) + goto err; + if (sLen && !EVP_DigestUpdate(ctx, salt, sLen)) + goto err; + if (!EVP_DigestFinal_ex(ctx, H, NULL)) + goto err; + + /* Generate dbMask in place then perform XOR on it */ + if (PKCS1_MGF1(EM, maskedDBLen, H, hLen, mgf1Hash)) + goto err; + + p = EM; + + /* + * Initial PS XORs with all zeroes which is a NOP so just update pointer. + * Note from a test above this value is guaranteed to be non-negative. + */ + p += emLen - sLen - hLen - 2; + *p++ ^= 0x1; + if (sLen > 0) { + for (i = 0; i < sLen; i++) + *p++ ^= salt[i]; + } + if (MSBits) + EM[0] &= 0xFF >> (8 - MSBits); + + /* H is already in place so just set final 0xbc */ + + EM[emLen - 1] = 0xbc; + + ret = 1; + + err: + EVP_MD_CTX_free(ctx); + OPENSSL_clear_free(salt, (size_t)sLen); /* salt != NULL implies sLen > 0 */ + + return ret; + +} + +#if defined(_MSC_VER) +# pragma optimize("",on) +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_saos.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_saos.c new file mode 100644 index 000000000..8336f32f1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_saos.c @@ -0,0 +1,95 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include + +int RSA_sign_ASN1_OCTET_STRING(int type, + const unsigned char *m, unsigned int m_len, + unsigned char *sigret, unsigned int *siglen, + RSA *rsa) +{ + ASN1_OCTET_STRING sig; + int i, j, ret = 1; + unsigned char *p, *s; + + sig.type = V_ASN1_OCTET_STRING; + sig.length = m_len; + sig.data = (unsigned char *)m; + + i = i2d_ASN1_OCTET_STRING(&sig, NULL); + j = RSA_size(rsa); + if (i > (j - RSA_PKCS1_PADDING_SIZE)) { + RSAerr(RSA_F_RSA_SIGN_ASN1_OCTET_STRING, + RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY); + return 0; + } + s = OPENSSL_malloc((unsigned int)j + 1); + if (s == NULL) { + RSAerr(RSA_F_RSA_SIGN_ASN1_OCTET_STRING, ERR_R_MALLOC_FAILURE); + return 0; + } + p = s; + i2d_ASN1_OCTET_STRING(&sig, &p); + i = RSA_private_encrypt(i, s, sigret, rsa, RSA_PKCS1_PADDING); + if (i <= 0) + ret = 0; + else + *siglen = i; + + OPENSSL_clear_free(s, (unsigned int)j + 1); + return ret; +} + +int RSA_verify_ASN1_OCTET_STRING(int dtype, + const unsigned char *m, + unsigned int m_len, unsigned char *sigbuf, + unsigned int siglen, RSA *rsa) +{ + int i, ret = 0; + unsigned char *s; + const unsigned char *p; + ASN1_OCTET_STRING *sig = NULL; + + if (siglen != (unsigned int)RSA_size(rsa)) { + RSAerr(RSA_F_RSA_VERIFY_ASN1_OCTET_STRING, + RSA_R_WRONG_SIGNATURE_LENGTH); + return 0; + } + + s = OPENSSL_malloc((unsigned int)siglen); + if (s == NULL) { + RSAerr(RSA_F_RSA_VERIFY_ASN1_OCTET_STRING, ERR_R_MALLOC_FAILURE); + goto err; + } + i = RSA_public_decrypt((int)siglen, sigbuf, s, rsa, RSA_PKCS1_PADDING); + + if (i <= 0) + goto err; + + p = s; + sig = d2i_ASN1_OCTET_STRING(NULL, &p, (long)i); + if (sig == NULL) + goto err; + + if (((unsigned int)sig->length != m_len) || + (memcmp(m, sig->data, m_len) != 0)) { + RSAerr(RSA_F_RSA_VERIFY_ASN1_OCTET_STRING, RSA_R_BAD_SIGNATURE); + } else { + ret = 1; + } + err: + ASN1_OCTET_STRING_free(sig); + OPENSSL_clear_free(s, (unsigned int)siglen); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_sign.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_sign.c new file mode 100644 index 000000000..952d24fb8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_sign.c @@ -0,0 +1,248 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "internal/x509_int.h" +#include "rsa_locl.h" + +/* Size of an SSL signature: MD5+SHA1 */ +#define SSL_SIG_LENGTH 36 + +/* + * encode_pkcs1 encodes a DigestInfo prefix of hash |type| and digest |m|, as + * described in EMSA-PKCS1-v1_5-ENCODE, RFC 3447 section 9.2 step 2. This + * encodes the DigestInfo (T and tLen) but does not add the padding. + * + * On success, it returns one and sets |*out| to a newly allocated buffer + * containing the result and |*out_len| to its length. The caller must free + * |*out| with |OPENSSL_free|. Otherwise, it returns zero. + */ +static int encode_pkcs1(unsigned char **out, int *out_len, int type, + const unsigned char *m, unsigned int m_len) +{ + X509_SIG sig; + X509_ALGOR algor; + ASN1_TYPE parameter; + ASN1_OCTET_STRING digest; + uint8_t *der = NULL; + int len; + + sig.algor = &algor; + sig.algor->algorithm = OBJ_nid2obj(type); + if (sig.algor->algorithm == NULL) { + RSAerr(RSA_F_ENCODE_PKCS1, RSA_R_UNKNOWN_ALGORITHM_TYPE); + return 0; + } + if (OBJ_length(sig.algor->algorithm) == 0) { + RSAerr(RSA_F_ENCODE_PKCS1, + RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD); + return 0; + } + parameter.type = V_ASN1_NULL; + parameter.value.ptr = NULL; + sig.algor->parameter = ¶meter; + + sig.digest = &digest; + sig.digest->data = (unsigned char *)m; + sig.digest->length = m_len; + + len = i2d_X509_SIG(&sig, &der); + if (len < 0) + return 0; + + *out = der; + *out_len = len; + return 1; +} + +int RSA_sign(int type, const unsigned char *m, unsigned int m_len, + unsigned char *sigret, unsigned int *siglen, RSA *rsa) +{ + int encrypt_len, encoded_len = 0, ret = 0; + unsigned char *tmps = NULL; + const unsigned char *encoded = NULL; + + if (rsa->meth->rsa_sign) { + return rsa->meth->rsa_sign(type, m, m_len, sigret, siglen, rsa); + } + + /* Compute the encoded digest. */ + if (type == NID_md5_sha1) { + /* + * NID_md5_sha1 corresponds to the MD5/SHA1 combination in TLS 1.1 and + * earlier. It has no DigestInfo wrapper but otherwise is + * RSASSA-PKCS1-v1_5. + */ + if (m_len != SSL_SIG_LENGTH) { + RSAerr(RSA_F_RSA_SIGN, RSA_R_INVALID_MESSAGE_LENGTH); + return 0; + } + encoded_len = SSL_SIG_LENGTH; + encoded = m; + } else { + if (!encode_pkcs1(&tmps, &encoded_len, type, m, m_len)) + goto err; + encoded = tmps; + } + + if (encoded_len > RSA_size(rsa) - RSA_PKCS1_PADDING_SIZE) { + RSAerr(RSA_F_RSA_SIGN, RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY); + goto err; + } + encrypt_len = RSA_private_encrypt(encoded_len, encoded, sigret, rsa, + RSA_PKCS1_PADDING); + if (encrypt_len <= 0) + goto err; + + *siglen = encrypt_len; + ret = 1; + +err: + OPENSSL_clear_free(tmps, (size_t)encoded_len); + return ret; +} + +/* + * int_rsa_verify verifies an RSA signature in |sigbuf| using |rsa|. It may be + * called in two modes. If |rm| is NULL, it verifies the signature for digest + * |m|. Otherwise, it recovers the digest from the signature, writing the digest + * to |rm| and the length to |*prm_len|. |type| is the NID of the digest + * algorithm to use. It returns one on successful verification and zero + * otherwise. + */ +int int_rsa_verify(int type, const unsigned char *m, unsigned int m_len, + unsigned char *rm, size_t *prm_len, + const unsigned char *sigbuf, size_t siglen, RSA *rsa) +{ + int decrypt_len, ret = 0, encoded_len = 0; + unsigned char *decrypt_buf = NULL, *encoded = NULL; + + if (siglen != (size_t)RSA_size(rsa)) { + RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_WRONG_SIGNATURE_LENGTH); + return 0; + } + + /* Recover the encoded digest. */ + decrypt_buf = OPENSSL_malloc(siglen); + if (decrypt_buf == NULL) { + RSAerr(RSA_F_INT_RSA_VERIFY, ERR_R_MALLOC_FAILURE); + goto err; + } + + decrypt_len = RSA_public_decrypt((int)siglen, sigbuf, decrypt_buf, rsa, + RSA_PKCS1_PADDING); + if (decrypt_len <= 0) + goto err; + + if (type == NID_md5_sha1) { + /* + * NID_md5_sha1 corresponds to the MD5/SHA1 combination in TLS 1.1 and + * earlier. It has no DigestInfo wrapper but otherwise is + * RSASSA-PKCS1-v1_5. + */ + if (decrypt_len != SSL_SIG_LENGTH) { + RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE); + goto err; + } + + if (rm != NULL) { + memcpy(rm, decrypt_buf, SSL_SIG_LENGTH); + *prm_len = SSL_SIG_LENGTH; + } else { + if (m_len != SSL_SIG_LENGTH) { + RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_INVALID_MESSAGE_LENGTH); + goto err; + } + + if (memcmp(decrypt_buf, m, SSL_SIG_LENGTH) != 0) { + RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE); + goto err; + } + } + } else if (type == NID_mdc2 && decrypt_len == 2 + 16 + && decrypt_buf[0] == 0x04 && decrypt_buf[1] == 0x10) { + /* + * Oddball MDC2 case: signature can be OCTET STRING. check for correct + * tag and length octets. + */ + if (rm != NULL) { + memcpy(rm, decrypt_buf + 2, 16); + *prm_len = 16; + } else { + if (m_len != 16) { + RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_INVALID_MESSAGE_LENGTH); + goto err; + } + + if (memcmp(m, decrypt_buf + 2, 16) != 0) { + RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE); + goto err; + } + } + } else { + /* + * If recovering the digest, extract a digest-sized output from the end + * of |decrypt_buf| for |encode_pkcs1|, then compare the decryption + * output as in a standard verification. + */ + if (rm != NULL) { + const EVP_MD *md = EVP_get_digestbynid(type); + if (md == NULL) { + RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_UNKNOWN_ALGORITHM_TYPE); + goto err; + } + + m_len = EVP_MD_size(md); + if (m_len > (size_t)decrypt_len) { + RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_INVALID_DIGEST_LENGTH); + goto err; + } + m = decrypt_buf + decrypt_len - m_len; + } + + /* Construct the encoded digest and ensure it matches. */ + if (!encode_pkcs1(&encoded, &encoded_len, type, m, m_len)) + goto err; + + if (encoded_len != decrypt_len + || memcmp(encoded, decrypt_buf, encoded_len) != 0) { + RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE); + goto err; + } + + /* Output the recovered digest. */ + if (rm != NULL) { + memcpy(rm, m, m_len); + *prm_len = m_len; + } + } + + ret = 1; + +err: + OPENSSL_clear_free(encoded, (size_t)encoded_len); + OPENSSL_clear_free(decrypt_buf, siglen); + return ret; +} + +int RSA_verify(int type, const unsigned char *m, unsigned int m_len, + const unsigned char *sigbuf, unsigned int siglen, RSA *rsa) +{ + + if (rsa->meth->rsa_verify) { + return rsa->meth->rsa_verify(type, m, m_len, sigbuf, siglen, rsa); + } + + return int_rsa_verify(type, m, m_len, NULL, NULL, sigbuf, siglen, rsa); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_ssl.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_ssl.c new file mode 100644 index 000000000..c5654595f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_ssl.c @@ -0,0 +1,167 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include "internal/constant_time_locl.h" + +int RSA_padding_add_SSLv23(unsigned char *to, int tlen, + const unsigned char *from, int flen) +{ + int i, j; + unsigned char *p; + + if (flen > (tlen - 11)) { + RSAerr(RSA_F_RSA_PADDING_ADD_SSLV23, + RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + return 0; + } + + p = (unsigned char *)to; + + *(p++) = 0; + *(p++) = 2; /* Public Key BT (Block Type) */ + + /* pad out with non-zero random data */ + j = tlen - 3 - 8 - flen; + + if (RAND_bytes(p, j) <= 0) + return 0; + for (i = 0; i < j; i++) { + if (*p == '\0') + do { + if (RAND_bytes(p, 1) <= 0) + return 0; + } while (*p == '\0'); + p++; + } + + memset(p, 3, 8); + p += 8; + *(p++) = '\0'; + + memcpy(p, from, (unsigned int)flen); + return 1; +} + +/* + * Copy of RSA_padding_check_PKCS1_type_2 with a twist that rejects padding + * if nul delimiter is preceded by 8 consecutive 0x03 bytes. It also + * preserves error code reporting for backward compatibility. + */ +int RSA_padding_check_SSLv23(unsigned char *to, int tlen, + const unsigned char *from, int flen, int num) +{ + int i; + /* |em| is the encoded message, zero-padded to exactly |num| bytes */ + unsigned char *em = NULL; + unsigned int good, found_zero_byte, mask, threes_in_row; + int zero_index = 0, msg_index, mlen = -1, err; + + if (flen < 10) { + RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23, RSA_R_DATA_TOO_SMALL); + return -1; + } + + em = OPENSSL_malloc(num); + if (em == NULL) { + RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23, ERR_R_MALLOC_FAILURE); + return -1; + } + /* + * Caller is encouraged to pass zero-padded message created with + * BN_bn2binpad. Trouble is that since we can't read out of |from|'s + * bounds, it's impossible to have an invariant memory access pattern + * in case |from| was not zero-padded in advance. + */ + for (from += flen, em += num, i = 0; i < num; i++) { + mask = ~constant_time_is_zero(flen); + flen -= 1 & mask; + from -= 1 & mask; + *--em = *from & mask; + } + from = em; + + good = constant_time_is_zero(from[0]); + good &= constant_time_eq(from[1], 2); + err = constant_time_select_int(good, 0, RSA_R_BLOCK_TYPE_IS_NOT_02); + mask = ~good; + + /* scan over padding data */ + found_zero_byte = 0; + threes_in_row = 0; + for (i = 2; i < num; i++) { + unsigned int equals0 = constant_time_is_zero(from[i]); + + zero_index = constant_time_select_int(~found_zero_byte & equals0, + i, zero_index); + found_zero_byte |= equals0; + + threes_in_row += 1 & ~found_zero_byte; + threes_in_row &= found_zero_byte | constant_time_eq(from[i], 3); + } + + /* + * PS must be at least 8 bytes long, and it starts two bytes into |from|. + * If we never found a 0-byte, then |zero_index| is 0 and the check + * also fails. + */ + good &= constant_time_ge(zero_index, 2 + 8); + err = constant_time_select_int(mask | good, err, + RSA_R_NULL_BEFORE_BLOCK_MISSING); + mask = ~good; + + good &= constant_time_lt(threes_in_row, 8); + err = constant_time_select_int(mask | good, err, + RSA_R_SSLV3_ROLLBACK_ATTACK); + mask = ~good; + + /* + * Skip the zero byte. This is incorrect if we never found a zero-byte + * but in this case we also do not copy the message out. + */ + msg_index = zero_index + 1; + mlen = num - msg_index; + + /* + * For good measure, do this check in constant time as well. + */ + good &= constant_time_ge(tlen, mlen); + err = constant_time_select_int(mask | good, err, RSA_R_DATA_TOO_LARGE); + + /* + * Even though we can't fake result's length, we can pretend copying + * |tlen| bytes where |mlen| bytes would be real. Last |tlen| of |num| + * bytes are viewed as circular buffer with start at |tlen|-|mlen'|, + * where |mlen'| is "saturated" |mlen| value. Deducing information + * about failure or |mlen| would take attacker's ability to observe + * memory access pattern with byte granularity *as it occurs*. It + * should be noted that failure is indistinguishable from normal + * operation if |tlen| is fixed by protocol. + */ + tlen = constant_time_select_int(constant_time_lt(num, tlen), num, tlen); + msg_index = constant_time_select_int(good, msg_index, num - tlen); + mlen = num - msg_index; + for (from += msg_index, mask = good, i = 0; i < tlen; i++) { + unsigned int equals = constant_time_eq(i, mlen); + + from -= tlen & equals; /* if (i == mlen) rewind */ + mask &= mask ^ equals; /* if (i == mlen) mask = 0 */ + to[i] = constant_time_select_8(mask, from[i], to[i]); + } + + OPENSSL_clear_free(em, num); + RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23, err); + err_clear_last_constant_time(1 & good); + + return constant_time_select_int(good, mlen, -1); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_x931.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_x931.c new file mode 100644 index 000000000..7b0486c0f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_x931.c @@ -0,0 +1,117 @@ +/* + * Copyright 2005-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include + +int RSA_padding_add_X931(unsigned char *to, int tlen, + const unsigned char *from, int flen) +{ + int j; + unsigned char *p; + + /* + * Absolute minimum amount of padding is 1 header nibble, 1 padding + * nibble and 2 trailer bytes: but 1 hash if is already in 'from'. + */ + + j = tlen - flen - 2; + + if (j < 0) { + RSAerr(RSA_F_RSA_PADDING_ADD_X931, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + return -1; + } + + p = (unsigned char *)to; + + /* If no padding start and end nibbles are in one byte */ + if (j == 0) { + *p++ = 0x6A; + } else { + *p++ = 0x6B; + if (j > 1) { + memset(p, 0xBB, j - 1); + p += j - 1; + } + *p++ = 0xBA; + } + memcpy(p, from, (unsigned int)flen); + p += flen; + *p = 0xCC; + return 1; +} + +int RSA_padding_check_X931(unsigned char *to, int tlen, + const unsigned char *from, int flen, int num) +{ + int i = 0, j; + const unsigned char *p; + + p = from; + if ((num != flen) || ((*p != 0x6A) && (*p != 0x6B))) { + RSAerr(RSA_F_RSA_PADDING_CHECK_X931, RSA_R_INVALID_HEADER); + return -1; + } + + if (*p++ == 0x6B) { + j = flen - 3; + for (i = 0; i < j; i++) { + unsigned char c = *p++; + if (c == 0xBA) + break; + if (c != 0xBB) { + RSAerr(RSA_F_RSA_PADDING_CHECK_X931, RSA_R_INVALID_PADDING); + return -1; + } + } + + j -= i; + + if (i == 0) { + RSAerr(RSA_F_RSA_PADDING_CHECK_X931, RSA_R_INVALID_PADDING); + return -1; + } + + } else { + j = flen - 2; + } + + if (p[j] != 0xCC) { + RSAerr(RSA_F_RSA_PADDING_CHECK_X931, RSA_R_INVALID_TRAILER); + return -1; + } + + memcpy(to, p, (unsigned int)j); + + return j; +} + +/* Translate between X931 hash ids and NIDs */ + +int RSA_X931_hash_id(int nid) +{ + switch (nid) { + case NID_sha1: + return 0x33; + + case NID_sha256: + return 0x34; + + case NID_sha384: + return 0x36; + + case NID_sha512: + return 0x35; + + } + return -1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_x931g.c b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_x931g.c new file mode 100644 index 000000000..15e40e8d1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/rsa/rsa_x931g.c @@ -0,0 +1,200 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include "rsa_locl.h" + +/* X9.31 RSA key derivation and generation */ + +int RSA_X931_derive_ex(RSA *rsa, BIGNUM *p1, BIGNUM *p2, BIGNUM *q1, + BIGNUM *q2, const BIGNUM *Xp1, const BIGNUM *Xp2, + const BIGNUM *Xp, const BIGNUM *Xq1, const BIGNUM *Xq2, + const BIGNUM *Xq, const BIGNUM *e, BN_GENCB *cb) +{ + BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *r3 = NULL; + BN_CTX *ctx = NULL, *ctx2 = NULL; + int ret = 0; + + if (!rsa) + goto err; + + ctx = BN_CTX_new(); + if (ctx == NULL) + goto err; + BN_CTX_start(ctx); + + r0 = BN_CTX_get(ctx); + r1 = BN_CTX_get(ctx); + r2 = BN_CTX_get(ctx); + r3 = BN_CTX_get(ctx); + + if (r3 == NULL) + goto err; + if (!rsa->e) { + rsa->e = BN_dup(e); + if (!rsa->e) + goto err; + } else { + e = rsa->e; + } + + /* + * If not all parameters present only calculate what we can. This allows + * test programs to output selective parameters. + */ + + if (Xp && rsa->p == NULL) { + rsa->p = BN_new(); + if (rsa->p == NULL) + goto err; + + if (!BN_X931_derive_prime_ex(rsa->p, p1, p2, + Xp, Xp1, Xp2, e, ctx, cb)) + goto err; + } + + if (Xq && rsa->q == NULL) { + rsa->q = BN_new(); + if (rsa->q == NULL) + goto err; + if (!BN_X931_derive_prime_ex(rsa->q, q1, q2, + Xq, Xq1, Xq2, e, ctx, cb)) + goto err; + } + + if (rsa->p == NULL || rsa->q == NULL) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return 2; + } + + /* + * Since both primes are set we can now calculate all remaining + * components. + */ + + /* calculate n */ + rsa->n = BN_new(); + if (rsa->n == NULL) + goto err; + if (!BN_mul(rsa->n, rsa->p, rsa->q, ctx)) + goto err; + + /* calculate d */ + if (!BN_sub(r1, rsa->p, BN_value_one())) + goto err; /* p-1 */ + if (!BN_sub(r2, rsa->q, BN_value_one())) + goto err; /* q-1 */ + if (!BN_mul(r0, r1, r2, ctx)) + goto err; /* (p-1)(q-1) */ + + if (!BN_gcd(r3, r1, r2, ctx)) + goto err; + + if (!BN_div(r0, NULL, r0, r3, ctx)) + goto err; /* LCM((p-1)(q-1)) */ + + ctx2 = BN_CTX_new(); + if (ctx2 == NULL) + goto err; + + rsa->d = BN_mod_inverse(NULL, rsa->e, r0, ctx2); /* d */ + if (rsa->d == NULL) + goto err; + + /* calculate d mod (p-1) */ + rsa->dmp1 = BN_new(); + if (rsa->dmp1 == NULL) + goto err; + if (!BN_mod(rsa->dmp1, rsa->d, r1, ctx)) + goto err; + + /* calculate d mod (q-1) */ + rsa->dmq1 = BN_new(); + if (rsa->dmq1 == NULL) + goto err; + if (!BN_mod(rsa->dmq1, rsa->d, r2, ctx)) + goto err; + + /* calculate inverse of q mod p */ + rsa->iqmp = BN_mod_inverse(NULL, rsa->q, rsa->p, ctx2); + if (rsa->iqmp == NULL) + goto err; + + ret = 1; + err: + if (ctx) + BN_CTX_end(ctx); + BN_CTX_free(ctx); + BN_CTX_free(ctx2); + + return ret; + +} + +int RSA_X931_generate_key_ex(RSA *rsa, int bits, const BIGNUM *e, + BN_GENCB *cb) +{ + int ok = 0; + BIGNUM *Xp = NULL, *Xq = NULL; + BN_CTX *ctx = NULL; + + ctx = BN_CTX_new(); + if (ctx == NULL) + goto error; + + BN_CTX_start(ctx); + Xp = BN_CTX_get(ctx); + Xq = BN_CTX_get(ctx); + if (Xq == NULL) + goto error; + if (!BN_X931_generate_Xpq(Xp, Xq, bits, ctx)) + goto error; + + rsa->p = BN_new(); + rsa->q = BN_new(); + if (rsa->p == NULL || rsa->q == NULL) + goto error; + + /* Generate two primes from Xp, Xq */ + + if (!BN_X931_generate_prime_ex(rsa->p, NULL, NULL, NULL, NULL, Xp, + e, ctx, cb)) + goto error; + + if (!BN_X931_generate_prime_ex(rsa->q, NULL, NULL, NULL, NULL, Xq, + e, ctx, cb)) + goto error; + + /* + * Since rsa->p and rsa->q are valid this call will just derive remaining + * RSA components. + */ + + if (!RSA_X931_derive_ex(rsa, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, e, cb)) + goto error; + + ok = 1; + + error: + if (ctx) + BN_CTX_end(ctx); + BN_CTX_free(ctx); + + if (ok) + return 1; + + return 0; + +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/s390x_arch.h b/trunk/3rdparty/openssl-1.1-fit/crypto/s390x_arch.h new file mode 100644 index 000000000..4a775a927 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/s390x_arch.h @@ -0,0 +1,103 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef S390X_ARCH_H +# define S390X_ARCH_H + +# ifndef __ASSEMBLER__ + +void s390x_kimd(const unsigned char *in, size_t len, unsigned int fc, + void *param); +void s390x_klmd(const unsigned char *in, size_t inlen, unsigned char *out, + size_t outlen, unsigned int fc, void *param); +void s390x_km(const unsigned char *in, size_t len, unsigned char *out, + unsigned int fc, void *param); +void s390x_kmac(const unsigned char *in, size_t len, unsigned int fc, + void *param); +void s390x_kmo(const unsigned char *in, size_t len, unsigned char *out, + unsigned int fc, void *param); +void s390x_kmf(const unsigned char *in, size_t len, unsigned char *out, + unsigned int fc, void *param); +void s390x_kma(const unsigned char *aad, size_t alen, const unsigned char *in, + size_t len, unsigned char *out, unsigned int fc, void *param); + +/* + * The field elements of OPENSSL_s390xcap_P are the 64-bit words returned by + * the STFLE instruction followed by the 64-bit word pairs returned by + * instructions' QUERY functions. If STFLE returns fewer data or an instruction + * is not supported, the corresponding field elements are zero. + */ +struct OPENSSL_s390xcap_st { + unsigned long long stfle[4]; + unsigned long long kimd[2]; + unsigned long long klmd[2]; + unsigned long long km[2]; + unsigned long long kmc[2]; + unsigned long long kmac[2]; + unsigned long long kmctr[2]; + unsigned long long kmo[2]; + unsigned long long kmf[2]; + unsigned long long prno[2]; + unsigned long long kma[2]; +}; + +extern struct OPENSSL_s390xcap_st OPENSSL_s390xcap_P; + +/* convert facility bit number or function code to bit mask */ +# define S390X_CAPBIT(i) (1ULL << (63 - (i) % 64)) + +# endif + +/* OPENSSL_s390xcap_P offsets [bytes] */ +# define S390X_STFLE 0x00 +# define S390X_KIMD 0x20 +# define S390X_KLMD 0x30 +# define S390X_KM 0x40 +# define S390X_KMC 0x50 +# define S390X_KMAC 0x60 +# define S390X_KMCTR 0x70 +# define S390X_KMO 0x80 +# define S390X_KMF 0x90 +# define S390X_PRNO 0xa0 +# define S390X_KMA 0xb0 + +/* Facility Bit Numbers */ +# define S390X_VX 129 +# define S390X_VXD 134 +# define S390X_VXE 135 + +/* Function Codes */ + +/* all instructions */ +# define S390X_QUERY 0 + +/* kimd/klmd */ +# define S390X_SHA3_224 32 +# define S390X_SHA3_256 33 +# define S390X_SHA3_384 34 +# define S390X_SHA3_512 35 +# define S390X_SHAKE_128 36 +# define S390X_SHAKE_256 37 +# define S390X_GHASH 65 + +/* km/kmc/kmac/kmctr/kmo/kmf/kma */ +# define S390X_AES_128 18 +# define S390X_AES_192 19 +# define S390X_AES_256 20 + +/* prno */ +# define S390X_TRNG 114 + +/* Register 0 Flags */ +# define S390X_DECRYPT 0x80 +# define S390X_KMA_LPC 0x100 +# define S390X_KMA_LAAD 0x200 +# define S390X_KMA_HS 0x400 + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/s390xcap.c b/trunk/3rdparty/openssl-1.1-fit/crypto/s390xcap.c new file mode 100644 index 000000000..e7c7f0a35 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/s390xcap.c @@ -0,0 +1,67 @@ +/* + * Copyright 2010-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include "internal/cryptlib.h" +#include "s390x_arch.h" + +static sigjmp_buf ill_jmp; +static void ill_handler(int sig) +{ + siglongjmp(ill_jmp, sig); +} + +void OPENSSL_s390x_facilities(void); +void OPENSSL_vx_probe(void); + +struct OPENSSL_s390xcap_st OPENSSL_s390xcap_P; + +void OPENSSL_cpuid_setup(void) +{ + sigset_t oset; + struct sigaction ill_act, oact; + + if (OPENSSL_s390xcap_P.stfle[0]) + return; + + /* set a bit that will not be tested later */ + OPENSSL_s390xcap_P.stfle[0] |= S390X_CAPBIT(0); + + memset(&ill_act, 0, sizeof(ill_act)); + ill_act.sa_handler = ill_handler; + sigfillset(&ill_act.sa_mask); + sigdelset(&ill_act.sa_mask, SIGILL); + sigdelset(&ill_act.sa_mask, SIGFPE); + sigdelset(&ill_act.sa_mask, SIGTRAP); + sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset); + sigaction(SIGILL, &ill_act, &oact); + sigaction(SIGFPE, &ill_act, &oact); + + /* protection against missing store-facility-list-extended */ + if (sigsetjmp(ill_jmp, 1) == 0) + OPENSSL_s390x_facilities(); + + /* protection against disabled vector facility */ + if ((OPENSSL_s390xcap_P.stfle[2] & S390X_CAPBIT(S390X_VX)) + && (sigsetjmp(ill_jmp, 1) == 0)) { + OPENSSL_vx_probe(); + } else { + OPENSSL_s390xcap_P.stfle[2] &= ~(S390X_CAPBIT(S390X_VX) + | S390X_CAPBIT(S390X_VXD) + | S390X_CAPBIT(S390X_VXE)); + } + + sigaction(SIGFPE, &oact, NULL); + sigaction(SIGILL, &oact, NULL); + sigprocmask(SIG_SETMASK, &oset, NULL); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/s390xcpuid.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/s390xcpuid.pl new file mode 100755 index 000000000..ec700a47d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/s390xcpuid.pl @@ -0,0 +1,421 @@ +#! /usr/bin/env perl +# Copyright 2009-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +$flavour = shift; + +if ($flavour =~ /3[12]/) { + $SIZE_T=4; + $g=""; +} else { + $SIZE_T=8; + $g="g"; +} + +while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} +open STDOUT,">$output"; + +$ra="%r14"; +$sp="%r15"; +$stdframe=16*$SIZE_T+4*8; + +$code=<<___; +#include "s390x_arch.h" + +.text + +.globl OPENSSL_s390x_facilities +.type OPENSSL_s390x_facilities,\@function +.align 16 +OPENSSL_s390x_facilities: + lghi %r0,0 + larl %r4,OPENSSL_s390xcap_P + + stg %r0,S390X_STFLE+8(%r4) # wipe capability vectors + stg %r0,S390X_STFLE+16(%r4) + stg %r0,S390X_STFLE+24(%r4) + stg %r0,S390X_KIMD(%r4) + stg %r0,S390X_KIMD+8(%r4) + stg %r0,S390X_KLMD(%r4) + stg %r0,S390X_KLMD+8(%r4) + stg %r0,S390X_KM(%r4) + stg %r0,S390X_KM+8(%r4) + stg %r0,S390X_KMC(%r4) + stg %r0,S390X_KMC+8(%r4) + stg %r0,S390X_KMAC(%r4) + stg %r0,S390X_KMAC+8(%r4) + stg %r0,S390X_KMCTR(%r4) + stg %r0,S390X_KMCTR+8(%r4) + stg %r0,S390X_KMO(%r4) + stg %r0,S390X_KMO+8(%r4) + stg %r0,S390X_KMF(%r4) + stg %r0,S390X_KMF+8(%r4) + stg %r0,S390X_PRNO(%r4) + stg %r0,S390X_PRNO+8(%r4) + stg %r0,S390X_KMA(%r4) + stg %r0,S390X_KMA+8(%r4) + + .long 0xb2b04000 # stfle 0(%r4) + brc 8,.Ldone + lghi %r0,1 + .long 0xb2b04000 # stfle 0(%r4) + brc 8,.Ldone + lghi %r0,2 + .long 0xb2b04000 # stfle 0(%r4) +.Ldone: + lmg %r2,%r3,S390X_STFLE(%r4) + tmhl %r2,0x4000 # check for message-security-assist + jz .Lret + + lghi %r0,S390X_QUERY # query kimd capabilities + la %r1,S390X_KIMD(%r4) + .long 0xb93e0002 # kimd %r0,%r2 + + lghi %r0,S390X_QUERY # query klmd capabilities + la %r1,S390X_KLMD(%r4) + .long 0xb93f0002 # klmd %r0,%r2 + + lghi %r0,S390X_QUERY # query km capability vector + la %r1,S390X_KM(%r4) + .long 0xb92e0042 # km %r4,%r2 + + lghi %r0,S390X_QUERY # query kmc capability vector + la %r1,S390X_KMC(%r4) + .long 0xb92f0042 # kmc %r4,%r2 + + lghi %r0,S390X_QUERY # query kmac capability vector + la %r1,S390X_KMAC(%r4) + .long 0xb91e0042 # kmac %r4,%r2 + + tmhh %r3,0x0004 # check for message-security-assist-4 + jz .Lret + + lghi %r0,S390X_QUERY # query kmctr capability vector + la %r1,S390X_KMCTR(%r4) + .long 0xb92d2042 # kmctr %r4,%r2,%r2 + + lghi %r0,S390X_QUERY # query kmo capability vector + la %r1,S390X_KMO(%r4) + .long 0xb92b0042 # kmo %r4,%r2 + + lghi %r0,S390X_QUERY # query kmf capability vector + la %r1,S390X_KMF(%r4) + .long 0xb92a0042 # kmf %r4,%r2 + + tml %r2,0x40 # check for message-security-assist-5 + jz .Lret + + lghi %r0,S390X_QUERY # query prno capability vector + la %r1,S390X_PRNO(%r4) + .long 0xb93c0042 # prno %r4,%r2 + + lg %r2,S390X_STFLE+16(%r4) + tmhl %r2,0x2000 # check for message-security-assist-8 + jz .Lret + + lghi %r0,S390X_QUERY # query kma capability vector + la %r1,S390X_KMA(%r4) + .long 0xb9294022 # kma %r2,%r4,%r2 + +.Lret: + br $ra +.size OPENSSL_s390x_facilities,.-OPENSSL_s390x_facilities + +.globl OPENSSL_rdtsc +.type OPENSSL_rdtsc,\@function +.align 16 +OPENSSL_rdtsc: + larl %r4,OPENSSL_s390xcap_P + tm S390X_STFLE+3(%r4),0x40 # check for store-clock-fast facility + jz .Lstck + + .long 0xb27cf010 # stckf 16($sp) + lg %r2,16($sp) + br $ra +.Lstck: + stck 16($sp) + lg %r2,16($sp) + br $ra +.size OPENSSL_rdtsc,.-OPENSSL_rdtsc + +.globl OPENSSL_atomic_add +.type OPENSSL_atomic_add,\@function +.align 16 +OPENSSL_atomic_add: + l %r1,0(%r2) +.Lspin: lr %r0,%r1 + ar %r0,%r3 + cs %r1,%r0,0(%r2) + brc 4,.Lspin + lgfr %r2,%r0 # OpenSSL expects the new value + br $ra +.size OPENSSL_atomic_add,.-OPENSSL_atomic_add + +.globl OPENSSL_wipe_cpu +.type OPENSSL_wipe_cpu,\@function +.align 16 +OPENSSL_wipe_cpu: + xgr %r0,%r0 + xgr %r1,%r1 + lgr %r2,$sp + xgr %r3,%r3 + xgr %r4,%r4 + lzdr %f0 + lzdr %f1 + lzdr %f2 + lzdr %f3 + lzdr %f4 + lzdr %f5 + lzdr %f6 + lzdr %f7 + br $ra +.size OPENSSL_wipe_cpu,.-OPENSSL_wipe_cpu + +.globl OPENSSL_cleanse +.type OPENSSL_cleanse,\@function +.align 16 +OPENSSL_cleanse: +#if !defined(__s390x__) && !defined(__s390x) + llgfr %r3,%r3 +#endif + lghi %r4,15 + lghi %r0,0 + clgr %r3,%r4 + jh .Lot + clgr %r3,%r0 + bcr 8,%r14 +.Little: + stc %r0,0(%r2) + la %r2,1(%r2) + brctg %r3,.Little + br %r14 +.align 4 +.Lot: tmll %r2,7 + jz .Laligned + stc %r0,0(%r2) + la %r2,1(%r2) + brctg %r3,.Lot +.Laligned: + srlg %r4,%r3,3 +.Loop: stg %r0,0(%r2) + la %r2,8(%r2) + brctg %r4,.Loop + lghi %r4,7 + ngr %r3,%r4 + jnz .Little + br $ra +.size OPENSSL_cleanse,.-OPENSSL_cleanse + +.globl CRYPTO_memcmp +.type CRYPTO_memcmp,\@function +.align 16 +CRYPTO_memcmp: +#if !defined(__s390x__) && !defined(__s390x) + llgfr %r4,%r4 +#endif + lghi %r5,0 + clgr %r4,%r5 + je .Lno_data + +.Loop_cmp: + llgc %r0,0(%r2) + la %r2,1(%r2) + llgc %r1,0(%r3) + la %r3,1(%r3) + xr %r1,%r0 + or %r5,%r1 + brctg %r4,.Loop_cmp + + lnr %r5,%r5 + srl %r5,31 +.Lno_data: + lgr %r2,%r5 + br $ra +.size CRYPTO_memcmp,.-CRYPTO_memcmp + +.globl OPENSSL_instrument_bus +.type OPENSSL_instrument_bus,\@function +.align 16 +OPENSSL_instrument_bus: + lghi %r2,0 + br %r14 +.size OPENSSL_instrument_bus,.-OPENSSL_instrument_bus + +.globl OPENSSL_instrument_bus2 +.type OPENSSL_instrument_bus2,\@function +.align 16 +OPENSSL_instrument_bus2: + lghi %r2,0 + br $ra +.size OPENSSL_instrument_bus2,.-OPENSSL_instrument_bus2 + +.globl OPENSSL_vx_probe +.type OPENSSL_vx_probe,\@function +.align 16 +OPENSSL_vx_probe: + .word 0xe700,0x0000,0x0044 # vzero %v0 + br $ra +.size OPENSSL_vx_probe,.-OPENSSL_vx_probe +___ + +{ +################ +# void s390x_kimd(const unsigned char *in, size_t len, unsigned int fc, +# void *param) +my ($in,$len,$fc,$param) = map("%r$_",(2..5)); +$code.=<<___; +.globl s390x_kimd +.type s390x_kimd,\@function +.align 16 +s390x_kimd: + llgfr %r0,$fc + lgr %r1,$param + + .long 0xb93e0002 # kimd %r0,%r2 + brc 1,.-4 # pay attention to "partial completion" + + br $ra +.size s390x_kimd,.-s390x_kimd +___ +} + +{ +################ +# void s390x_klmd(const unsigned char *in, size_t inlen, unsigned char *out, +# size_t outlen, unsigned int fc, void *param) +my ($in,$inlen,$out,$outlen,$fc) = map("%r$_",(2..6)); +$code.=<<___; +.globl s390x_klmd +.type s390x_klmd,\@function +.align 32 +s390x_klmd: + llgfr %r0,$fc + l${g} %r1,$stdframe($sp) + + .long 0xb93f0042 # klmd %r4,%r2 + brc 1,.-4 # pay attention to "partial completion" + + br $ra +.size s390x_klmd,.-s390x_klmd +___ +} + +################ +# void s390x_km(const unsigned char *in, size_t len, unsigned char *out, +# unsigned int fc, void *param) +{ +my ($in,$len,$out,$fc,$param) = map("%r$_",(2..6)); +$code.=<<___; +.globl s390x_km +.type s390x_km,\@function +.align 16 +s390x_km: + lr %r0,$fc + l${g}r %r1,$param + + .long 0xb92e0042 # km $out,$in + brc 1,.-4 # pay attention to "partial completion" + + br $ra +.size s390x_km,.-s390x_km +___ +} + +################ +# void s390x_kmac(const unsigned char *in, size_t len, unsigned int fc, +# void *param) +{ +my ($in,$len,$fc,$param) = map("%r$_",(2..5)); +$code.=<<___; +.globl s390x_kmac +.type s390x_kmac,\@function +.align 16 +s390x_kmac: + lr %r0,$fc + l${g}r %r1,$param + + .long 0xb91e0002 # kmac %r0,$in + brc 1,.-4 # pay attention to "partial completion" + + br $ra +.size s390x_kmac,.-s390x_kmac +___ +} + +################ +# void s390x_kmo(const unsigned char *in, size_t len, unsigned char *out, +# unsigned int fc, void *param) +{ +my ($in,$len,$out,$fc,$param) = map("%r$_",(2..6)); +$code.=<<___; +.globl s390x_kmo +.type s390x_kmo,\@function +.align 16 +s390x_kmo: + lr %r0,$fc + l${g}r %r1,$param + + .long 0xb92b0042 # kmo $out,$in + brc 1,.-4 # pay attention to "partial completion" + + br $ra +.size s390x_kmo,.-s390x_kmo +___ +} + +################ +# void s390x_kmf(const unsigned char *in, size_t len, unsigned char *out, +# unsigned int fc, void *param) +{ +my ($in,$len,$out,$fc,$param) = map("%r$_",(2..6)); +$code.=<<___; +.globl s390x_kmf +.type s390x_kmf,\@function +.align 16 +s390x_kmf: + lr %r0,$fc + l${g}r %r1,$param + + .long 0xb92a0042 # kmf $out,$in + brc 1,.-4 # pay attention to "partial completion" + + br $ra +.size s390x_kmf,.-s390x_kmf +___ +} + +################ +# void s390x_kma(const unsigned char *aad, size_t alen, +# const unsigned char *in, size_t len, +# unsigned char *out, unsigned int fc, void *param) +{ +my ($aad,$alen,$in,$len,$out) = map("%r$_",(2..6)); +$code.=<<___; +.globl s390x_kma +.type s390x_kma,\@function +.align 16 +s390x_kma: + st${g} $out,6*$SIZE_T($sp) + lm${g} %r0,%r1,$stdframe($sp) + + .long 0xb9292064 # kma $out,$aad,$in + brc 1,.-4 # pay attention to "partial completion" + + l${g} $out,6*$SIZE_T($sp) + br $ra +.size s390x_kma,.-s390x_kma +___ +} + +$code.=<<___; +.section .init + brasl $ra,OPENSSL_cpuid_setup +___ + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +print $code; +close STDOUT; # force flush diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/seed/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/seed/build.info new file mode 100644 index 000000000..abdcbcaa9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/seed/build.info @@ -0,0 +1,2 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=seed.c seed_ecb.c seed_cbc.c seed_cfb.c seed_ofb.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/seed/seed.c b/trunk/3rdparty/openssl-1.1-fit/crypto/seed/seed.c new file mode 100644 index 000000000..d62da91ed --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/seed/seed.c @@ -0,0 +1,590 @@ +/* + * Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Copyright (c) 2007 KISA(Korea Information Security Agency). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Neither the name of author nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#ifndef OPENSSL_NO_SEED + +# include +# include +# include +# ifdef _WIN32 +# include +# endif + +# include +# include "seed_locl.h" + +# ifdef SS /* can get defined on Solaris by inclusion of + * */ +# undef SS +# endif + +# if !defined(OPENSSL_SMALL_FOOTPRINT) + +# define G_FUNC(v) \ + SS[0][(unsigned char) (v) & 0xff] ^ \ + SS[1][(unsigned char) ((v)>>8) & 0xff] ^ \ + SS[2][(unsigned char)((v)>>16) & 0xff] ^ \ + SS[3][(unsigned char)((v)>>24) & 0xff] + +static const seed_word SS[4][256] = { + { 0x2989a1a8, 0x05858184, 0x16c6d2d4, 0x13c3d3d0, + 0x14445054, 0x1d0d111c, 0x2c8ca0ac, 0x25052124, + 0x1d4d515c, 0x03434340, 0x18081018, 0x1e0e121c, + 0x11415150, 0x3cccf0fc, 0x0acac2c8, 0x23436360, + 0x28082028, 0x04444044, 0x20002020, 0x1d8d919c, + 0x20c0e0e0, 0x22c2e2e0, 0x08c8c0c8, 0x17071314, + 0x2585a1a4, 0x0f8f838c, 0x03030300, 0x3b4b7378, + 0x3b8bb3b8, 0x13031310, 0x12c2d2d0, 0x2ecee2ec, + 0x30407070, 0x0c8c808c, 0x3f0f333c, 0x2888a0a8, + 0x32023230, 0x1dcdd1dc, 0x36c6f2f4, 0x34447074, + 0x2ccce0ec, 0x15859194, 0x0b0b0308, 0x17475354, + 0x1c4c505c, 0x1b4b5358, 0x3d8db1bc, 0x01010100, + 0x24042024, 0x1c0c101c, 0x33437370, 0x18889098, + 0x10001010, 0x0cccc0cc, 0x32c2f2f0, 0x19c9d1d8, + 0x2c0c202c, 0x27c7e3e4, 0x32427270, 0x03838380, + 0x1b8b9398, 0x11c1d1d0, 0x06868284, 0x09c9c1c8, + 0x20406060, 0x10405050, 0x2383a3a0, 0x2bcbe3e8, + 0x0d0d010c, 0x3686b2b4, 0x1e8e929c, 0x0f4f434c, + 0x3787b3b4, 0x1a4a5258, 0x06c6c2c4, 0x38487078, + 0x2686a2a4, 0x12021210, 0x2f8fa3ac, 0x15c5d1d4, + 0x21416160, 0x03c3c3c0, 0x3484b0b4, 0x01414140, + 0x12425250, 0x3d4d717c, 0x0d8d818c, 0x08080008, + 0x1f0f131c, 0x19899198, 0x00000000, 0x19091118, + 0x04040004, 0x13435350, 0x37c7f3f4, 0x21c1e1e0, + 0x3dcdf1fc, 0x36467274, 0x2f0f232c, 0x27072324, + 0x3080b0b0, 0x0b8b8388, 0x0e0e020c, 0x2b8ba3a8, + 0x2282a2a0, 0x2e4e626c, 0x13839390, 0x0d4d414c, + 0x29496168, 0x3c4c707c, 0x09090108, 0x0a0a0208, + 0x3f8fb3bc, 0x2fcfe3ec, 0x33c3f3f0, 0x05c5c1c4, + 0x07878384, 0x14041014, 0x3ecef2fc, 0x24446064, + 0x1eced2dc, 0x2e0e222c, 0x0b4b4348, 0x1a0a1218, + 0x06060204, 0x21012120, 0x2b4b6368, 0x26466264, + 0x02020200, 0x35c5f1f4, 0x12829290, 0x0a8a8288, + 0x0c0c000c, 0x3383b3b0, 0x3e4e727c, 0x10c0d0d0, + 0x3a4a7278, 0x07474344, 0x16869294, 0x25c5e1e4, + 0x26062224, 0x00808080, 0x2d8da1ac, 0x1fcfd3dc, + 0x2181a1a0, 0x30003030, 0x37073334, 0x2e8ea2ac, + 0x36063234, 0x15051114, 0x22022220, 0x38083038, + 0x34c4f0f4, 0x2787a3a4, 0x05454144, 0x0c4c404c, + 0x01818180, 0x29c9e1e8, 0x04848084, 0x17879394, + 0x35053134, 0x0bcbc3c8, 0x0ecec2cc, 0x3c0c303c, + 0x31417170, 0x11011110, 0x07c7c3c4, 0x09898188, + 0x35457174, 0x3bcbf3f8, 0x1acad2d8, 0x38c8f0f8, + 0x14849094, 0x19495158, 0x02828280, 0x04c4c0c4, + 0x3fcff3fc, 0x09494148, 0x39093138, 0x27476364, + 0x00c0c0c0, 0x0fcfc3cc, 0x17c7d3d4, 0x3888b0b8, + 0x0f0f030c, 0x0e8e828c, 0x02424240, 0x23032320, + 0x11819190, 0x2c4c606c, 0x1bcbd3d8, 0x2484a0a4, + 0x34043034, 0x31c1f1f0, 0x08484048, 0x02c2c2c0, + 0x2f4f636c, 0x3d0d313c, 0x2d0d212c, 0x00404040, + 0x3e8eb2bc, 0x3e0e323c, 0x3c8cb0bc, 0x01c1c1c0, + 0x2a8aa2a8, 0x3a8ab2b8, 0x0e4e424c, 0x15455154, + 0x3b0b3338, 0x1cccd0dc, 0x28486068, 0x3f4f737c, + 0x1c8c909c, 0x18c8d0d8, 0x0a4a4248, 0x16465254, + 0x37477374, 0x2080a0a0, 0x2dcde1ec, 0x06464244, + 0x3585b1b4, 0x2b0b2328, 0x25456164, 0x3acaf2f8, + 0x23c3e3e0, 0x3989b1b8, 0x3181b1b0, 0x1f8f939c, + 0x1e4e525c, 0x39c9f1f8, 0x26c6e2e4, 0x3282b2b0, + 0x31013130, 0x2acae2e8, 0x2d4d616c, 0x1f4f535c, + 0x24c4e0e4, 0x30c0f0f0, 0x0dcdc1cc, 0x08888088, + 0x16061214, 0x3a0a3238, 0x18485058, 0x14c4d0d4, + 0x22426260, 0x29092128, 0x07070304, 0x33033330, + 0x28c8e0e8, 0x1b0b1318, 0x05050104, 0x39497178, + 0x10809090, 0x2a4a6268, 0x2a0a2228, 0x1a8a9298 + }, + { 0x38380830, 0xe828c8e0, 0x2c2d0d21, 0xa42686a2, + 0xcc0fcfc3, 0xdc1eced2, 0xb03383b3, 0xb83888b0, + 0xac2f8fa3, 0x60204060, 0x54154551, 0xc407c7c3, + 0x44044440, 0x6c2f4f63, 0x682b4b63, 0x581b4b53, + 0xc003c3c3, 0x60224262, 0x30330333, 0xb43585b1, + 0x28290921, 0xa02080a0, 0xe022c2e2, 0xa42787a3, + 0xd013c3d3, 0x90118191, 0x10110111, 0x04060602, + 0x1c1c0c10, 0xbc3c8cb0, 0x34360632, 0x480b4b43, + 0xec2fcfe3, 0x88088880, 0x6c2c4c60, 0xa82888a0, + 0x14170713, 0xc404c4c0, 0x14160612, 0xf434c4f0, + 0xc002c2c2, 0x44054541, 0xe021c1e1, 0xd416c6d2, + 0x3c3f0f33, 0x3c3d0d31, 0x8c0e8e82, 0x98188890, + 0x28280820, 0x4c0e4e42, 0xf436c6f2, 0x3c3e0e32, + 0xa42585a1, 0xf839c9f1, 0x0c0d0d01, 0xdc1fcfd3, + 0xd818c8d0, 0x282b0b23, 0x64264662, 0x783a4a72, + 0x24270723, 0x2c2f0f23, 0xf031c1f1, 0x70324272, + 0x40024242, 0xd414c4d0, 0x40014141, 0xc000c0c0, + 0x70334373, 0x64274763, 0xac2c8ca0, 0x880b8b83, + 0xf437c7f3, 0xac2d8da1, 0x80008080, 0x1c1f0f13, + 0xc80acac2, 0x2c2c0c20, 0xa82a8aa2, 0x34340430, + 0xd012c2d2, 0x080b0b03, 0xec2ecee2, 0xe829c9e1, + 0x5c1d4d51, 0x94148490, 0x18180810, 0xf838c8f0, + 0x54174753, 0xac2e8ea2, 0x08080800, 0xc405c5c1, + 0x10130313, 0xcc0dcdc1, 0x84068682, 0xb83989b1, + 0xfc3fcff3, 0x7c3d4d71, 0xc001c1c1, 0x30310131, + 0xf435c5f1, 0x880a8a82, 0x682a4a62, 0xb03181b1, + 0xd011c1d1, 0x20200020, 0xd417c7d3, 0x00020202, + 0x20220222, 0x04040400, 0x68284860, 0x70314171, + 0x04070703, 0xd81bcbd3, 0x9c1d8d91, 0x98198991, + 0x60214161, 0xbc3e8eb2, 0xe426c6e2, 0x58194951, + 0xdc1dcdd1, 0x50114151, 0x90108090, 0xdc1cccd0, + 0x981a8a92, 0xa02383a3, 0xa82b8ba3, 0xd010c0d0, + 0x80018181, 0x0c0f0f03, 0x44074743, 0x181a0a12, + 0xe023c3e3, 0xec2ccce0, 0x8c0d8d81, 0xbc3f8fb3, + 0x94168692, 0x783b4b73, 0x5c1c4c50, 0xa02282a2, + 0xa02181a1, 0x60234363, 0x20230323, 0x4c0d4d41, + 0xc808c8c0, 0x9c1e8e92, 0x9c1c8c90, 0x383a0a32, + 0x0c0c0c00, 0x2c2e0e22, 0xb83a8ab2, 0x6c2e4e62, + 0x9c1f8f93, 0x581a4a52, 0xf032c2f2, 0x90128292, + 0xf033c3f3, 0x48094941, 0x78384870, 0xcc0cccc0, + 0x14150511, 0xf83bcbf3, 0x70304070, 0x74354571, + 0x7c3f4f73, 0x34350531, 0x10100010, 0x00030303, + 0x64244460, 0x6c2d4d61, 0xc406c6c2, 0x74344470, + 0xd415c5d1, 0xb43484b0, 0xe82acae2, 0x08090901, + 0x74364672, 0x18190911, 0xfc3ecef2, 0x40004040, + 0x10120212, 0xe020c0e0, 0xbc3d8db1, 0x04050501, + 0xf83acaf2, 0x00010101, 0xf030c0f0, 0x282a0a22, + 0x5c1e4e52, 0xa82989a1, 0x54164652, 0x40034343, + 0x84058581, 0x14140410, 0x88098981, 0x981b8b93, + 0xb03080b0, 0xe425c5e1, 0x48084840, 0x78394971, + 0x94178793, 0xfc3cccf0, 0x1c1e0e12, 0x80028282, + 0x20210121, 0x8c0c8c80, 0x181b0b13, 0x5c1f4f53, + 0x74374773, 0x54144450, 0xb03282b2, 0x1c1d0d11, + 0x24250521, 0x4c0f4f43, 0x00000000, 0x44064642, + 0xec2dcde1, 0x58184850, 0x50124252, 0xe82bcbe3, + 0x7c3e4e72, 0xd81acad2, 0xc809c9c1, 0xfc3dcdf1, + 0x30300030, 0x94158591, 0x64254561, 0x3c3c0c30, + 0xb43686b2, 0xe424c4e0, 0xb83b8bb3, 0x7c3c4c70, + 0x0c0e0e02, 0x50104050, 0x38390931, 0x24260622, + 0x30320232, 0x84048480, 0x68294961, 0x90138393, + 0x34370733, 0xe427c7e3, 0x24240420, 0xa42484a0, + 0xc80bcbc3, 0x50134353, 0x080a0a02, 0x84078783, + 0xd819c9d1, 0x4c0c4c40, 0x80038383, 0x8c0f8f83, + 0xcc0ecec2, 0x383b0b33, 0x480a4a42, 0xb43787b3 + }, + { 0xa1a82989, 0x81840585, 0xd2d416c6, 0xd3d013c3, + 0x50541444, 0x111c1d0d, 0xa0ac2c8c, 0x21242505, + 0x515c1d4d, 0x43400343, 0x10181808, 0x121c1e0e, + 0x51501141, 0xf0fc3ccc, 0xc2c80aca, 0x63602343, + 0x20282808, 0x40440444, 0x20202000, 0x919c1d8d, + 0xe0e020c0, 0xe2e022c2, 0xc0c808c8, 0x13141707, + 0xa1a42585, 0x838c0f8f, 0x03000303, 0x73783b4b, + 0xb3b83b8b, 0x13101303, 0xd2d012c2, 0xe2ec2ece, + 0x70703040, 0x808c0c8c, 0x333c3f0f, 0xa0a82888, + 0x32303202, 0xd1dc1dcd, 0xf2f436c6, 0x70743444, + 0xe0ec2ccc, 0x91941585, 0x03080b0b, 0x53541747, + 0x505c1c4c, 0x53581b4b, 0xb1bc3d8d, 0x01000101, + 0x20242404, 0x101c1c0c, 0x73703343, 0x90981888, + 0x10101000, 0xc0cc0ccc, 0xf2f032c2, 0xd1d819c9, + 0x202c2c0c, 0xe3e427c7, 0x72703242, 0x83800383, + 0x93981b8b, 0xd1d011c1, 0x82840686, 0xc1c809c9, + 0x60602040, 0x50501040, 0xa3a02383, 0xe3e82bcb, + 0x010c0d0d, 0xb2b43686, 0x929c1e8e, 0x434c0f4f, + 0xb3b43787, 0x52581a4a, 0xc2c406c6, 0x70783848, + 0xa2a42686, 0x12101202, 0xa3ac2f8f, 0xd1d415c5, + 0x61602141, 0xc3c003c3, 0xb0b43484, 0x41400141, + 0x52501242, 0x717c3d4d, 0x818c0d8d, 0x00080808, + 0x131c1f0f, 0x91981989, 0x00000000, 0x11181909, + 0x00040404, 0x53501343, 0xf3f437c7, 0xe1e021c1, + 0xf1fc3dcd, 0x72743646, 0x232c2f0f, 0x23242707, + 0xb0b03080, 0x83880b8b, 0x020c0e0e, 0xa3a82b8b, + 0xa2a02282, 0x626c2e4e, 0x93901383, 0x414c0d4d, + 0x61682949, 0x707c3c4c, 0x01080909, 0x02080a0a, + 0xb3bc3f8f, 0xe3ec2fcf, 0xf3f033c3, 0xc1c405c5, + 0x83840787, 0x10141404, 0xf2fc3ece, 0x60642444, + 0xd2dc1ece, 0x222c2e0e, 0x43480b4b, 0x12181a0a, + 0x02040606, 0x21202101, 0x63682b4b, 0x62642646, + 0x02000202, 0xf1f435c5, 0x92901282, 0x82880a8a, + 0x000c0c0c, 0xb3b03383, 0x727c3e4e, 0xd0d010c0, + 0x72783a4a, 0x43440747, 0x92941686, 0xe1e425c5, + 0x22242606, 0x80800080, 0xa1ac2d8d, 0xd3dc1fcf, + 0xa1a02181, 0x30303000, 0x33343707, 0xa2ac2e8e, + 0x32343606, 0x11141505, 0x22202202, 0x30383808, + 0xf0f434c4, 0xa3a42787, 0x41440545, 0x404c0c4c, + 0x81800181, 0xe1e829c9, 0x80840484, 0x93941787, + 0x31343505, 0xc3c80bcb, 0xc2cc0ece, 0x303c3c0c, + 0x71703141, 0x11101101, 0xc3c407c7, 0x81880989, + 0x71743545, 0xf3f83bcb, 0xd2d81aca, 0xf0f838c8, + 0x90941484, 0x51581949, 0x82800282, 0xc0c404c4, + 0xf3fc3fcf, 0x41480949, 0x31383909, 0x63642747, + 0xc0c000c0, 0xc3cc0fcf, 0xd3d417c7, 0xb0b83888, + 0x030c0f0f, 0x828c0e8e, 0x42400242, 0x23202303, + 0x91901181, 0x606c2c4c, 0xd3d81bcb, 0xa0a42484, + 0x30343404, 0xf1f031c1, 0x40480848, 0xc2c002c2, + 0x636c2f4f, 0x313c3d0d, 0x212c2d0d, 0x40400040, + 0xb2bc3e8e, 0x323c3e0e, 0xb0bc3c8c, 0xc1c001c1, + 0xa2a82a8a, 0xb2b83a8a, 0x424c0e4e, 0x51541545, + 0x33383b0b, 0xd0dc1ccc, 0x60682848, 0x737c3f4f, + 0x909c1c8c, 0xd0d818c8, 0x42480a4a, 0x52541646, + 0x73743747, 0xa0a02080, 0xe1ec2dcd, 0x42440646, + 0xb1b43585, 0x23282b0b, 0x61642545, 0xf2f83aca, + 0xe3e023c3, 0xb1b83989, 0xb1b03181, 0x939c1f8f, + 0x525c1e4e, 0xf1f839c9, 0xe2e426c6, 0xb2b03282, + 0x31303101, 0xe2e82aca, 0x616c2d4d, 0x535c1f4f, + 0xe0e424c4, 0xf0f030c0, 0xc1cc0dcd, 0x80880888, + 0x12141606, 0x32383a0a, 0x50581848, 0xd0d414c4, + 0x62602242, 0x21282909, 0x03040707, 0x33303303, + 0xe0e828c8, 0x13181b0b, 0x01040505, 0x71783949, + 0x90901080, 0x62682a4a, 0x22282a0a, 0x92981a8a + }, + { 0x08303838, 0xc8e0e828, 0x0d212c2d, 0x86a2a426, + 0xcfc3cc0f, 0xced2dc1e, 0x83b3b033, 0x88b0b838, + 0x8fa3ac2f, 0x40606020, 0x45515415, 0xc7c3c407, + 0x44404404, 0x4f636c2f, 0x4b63682b, 0x4b53581b, + 0xc3c3c003, 0x42626022, 0x03333033, 0x85b1b435, + 0x09212829, 0x80a0a020, 0xc2e2e022, 0x87a3a427, + 0xc3d3d013, 0x81919011, 0x01111011, 0x06020406, + 0x0c101c1c, 0x8cb0bc3c, 0x06323436, 0x4b43480b, + 0xcfe3ec2f, 0x88808808, 0x4c606c2c, 0x88a0a828, + 0x07131417, 0xc4c0c404, 0x06121416, 0xc4f0f434, + 0xc2c2c002, 0x45414405, 0xc1e1e021, 0xc6d2d416, + 0x0f333c3f, 0x0d313c3d, 0x8e828c0e, 0x88909818, + 0x08202828, 0x4e424c0e, 0xc6f2f436, 0x0e323c3e, + 0x85a1a425, 0xc9f1f839, 0x0d010c0d, 0xcfd3dc1f, + 0xc8d0d818, 0x0b23282b, 0x46626426, 0x4a72783a, + 0x07232427, 0x0f232c2f, 0xc1f1f031, 0x42727032, + 0x42424002, 0xc4d0d414, 0x41414001, 0xc0c0c000, + 0x43737033, 0x47636427, 0x8ca0ac2c, 0x8b83880b, + 0xc7f3f437, 0x8da1ac2d, 0x80808000, 0x0f131c1f, + 0xcac2c80a, 0x0c202c2c, 0x8aa2a82a, 0x04303434, + 0xc2d2d012, 0x0b03080b, 0xcee2ec2e, 0xc9e1e829, + 0x4d515c1d, 0x84909414, 0x08101818, 0xc8f0f838, + 0x47535417, 0x8ea2ac2e, 0x08000808, 0xc5c1c405, + 0x03131013, 0xcdc1cc0d, 0x86828406, 0x89b1b839, + 0xcff3fc3f, 0x4d717c3d, 0xc1c1c001, 0x01313031, + 0xc5f1f435, 0x8a82880a, 0x4a62682a, 0x81b1b031, + 0xc1d1d011, 0x00202020, 0xc7d3d417, 0x02020002, + 0x02222022, 0x04000404, 0x48606828, 0x41717031, + 0x07030407, 0xcbd3d81b, 0x8d919c1d, 0x89919819, + 0x41616021, 0x8eb2bc3e, 0xc6e2e426, 0x49515819, + 0xcdd1dc1d, 0x41515011, 0x80909010, 0xccd0dc1c, + 0x8a92981a, 0x83a3a023, 0x8ba3a82b, 0xc0d0d010, + 0x81818001, 0x0f030c0f, 0x47434407, 0x0a12181a, + 0xc3e3e023, 0xcce0ec2c, 0x8d818c0d, 0x8fb3bc3f, + 0x86929416, 0x4b73783b, 0x4c505c1c, 0x82a2a022, + 0x81a1a021, 0x43636023, 0x03232023, 0x4d414c0d, + 0xc8c0c808, 0x8e929c1e, 0x8c909c1c, 0x0a32383a, + 0x0c000c0c, 0x0e222c2e, 0x8ab2b83a, 0x4e626c2e, + 0x8f939c1f, 0x4a52581a, 0xc2f2f032, 0x82929012, + 0xc3f3f033, 0x49414809, 0x48707838, 0xccc0cc0c, + 0x05111415, 0xcbf3f83b, 0x40707030, 0x45717435, + 0x4f737c3f, 0x05313435, 0x00101010, 0x03030003, + 0x44606424, 0x4d616c2d, 0xc6c2c406, 0x44707434, + 0xc5d1d415, 0x84b0b434, 0xcae2e82a, 0x09010809, + 0x46727436, 0x09111819, 0xcef2fc3e, 0x40404000, + 0x02121012, 0xc0e0e020, 0x8db1bc3d, 0x05010405, + 0xcaf2f83a, 0x01010001, 0xc0f0f030, 0x0a22282a, + 0x4e525c1e, 0x89a1a829, 0x46525416, 0x43434003, + 0x85818405, 0x04101414, 0x89818809, 0x8b93981b, + 0x80b0b030, 0xc5e1e425, 0x48404808, 0x49717839, + 0x87939417, 0xccf0fc3c, 0x0e121c1e, 0x82828002, + 0x01212021, 0x8c808c0c, 0x0b13181b, 0x4f535c1f, + 0x47737437, 0x44505414, 0x82b2b032, 0x0d111c1d, + 0x05212425, 0x4f434c0f, 0x00000000, 0x46424406, + 0xcde1ec2d, 0x48505818, 0x42525012, 0xcbe3e82b, + 0x4e727c3e, 0xcad2d81a, 0xc9c1c809, 0xcdf1fc3d, + 0x00303030, 0x85919415, 0x45616425, 0x0c303c3c, + 0x86b2b436, 0xc4e0e424, 0x8bb3b83b, 0x4c707c3c, + 0x0e020c0e, 0x40505010, 0x09313839, 0x06222426, + 0x02323032, 0x84808404, 0x49616829, 0x83939013, + 0x07333437, 0xc7e3e427, 0x04202424, 0x84a0a424, + 0xcbc3c80b, 0x43535013, 0x0a02080a, 0x87838407, + 0xc9d1d819, 0x4c404c0c, 0x83838003, 0x8f838c0f, + 0xcec2cc0e, 0x0b33383b, 0x4a42480a, 0x87b3b437 + } +}; + +#else + +/* on x86_64 >5x size reduction at 40% performance penalty */ +static const unsigned char SEED_Sbox[2][256] = { +{ + 0xA9, 0x85, 0xD6, 0xD3, 0x54, 0x1D, 0xAC, 0x25, + 0x5D, 0x43, 0x18, 0x1E, 0x51, 0xFC, 0xCA, 0x63, + 0x28, 0x44, 0x20, 0x9D, 0xE0, 0xE2, 0xC8, 0x17, + 0xA5, 0x8F, 0x03, 0x7B, 0xBB, 0x13, 0xD2, 0xEE, + 0x70, 0x8C, 0x3F, 0xA8, 0x32, 0xDD, 0xF6, 0x74, + 0xEC, 0x95, 0x0B, 0x57, 0x5C, 0x5B, 0xBD, 0x01, + 0x24, 0x1C, 0x73, 0x98, 0x10, 0xCC, 0xF2, 0xD9, + 0x2C, 0xE7, 0x72, 0x83, 0x9B, 0xD1, 0x86, 0xC9, + 0x60, 0x50, 0xA3, 0xEB, 0x0D, 0xB6, 0x9E, 0x4F, + 0xB7, 0x5A, 0xC6, 0x78, 0xA6, 0x12, 0xAF, 0xD5, + 0x61, 0xC3, 0xB4, 0x41, 0x52, 0x7D, 0x8D, 0x08, + 0x1F, 0x99, 0x00, 0x19, 0x04, 0x53, 0xF7, 0xE1, + 0xFD, 0x76, 0x2F, 0x27, 0xB0, 0x8B, 0x0E, 0xAB, + 0xA2, 0x6E, 0x93, 0x4D, 0x69, 0x7C, 0x09, 0x0A, + 0xBF, 0xEF, 0xF3, 0xC5, 0x87, 0x14, 0xFE, 0x64, + 0xDE, 0x2E, 0x4B, 0x1A, 0x06, 0x21, 0x6B, 0x66, + 0x02, 0xF5, 0x92, 0x8A, 0x0C, 0xB3, 0x7E, 0xD0, + 0x7A, 0x47, 0x96, 0xE5, 0x26, 0x80, 0xAD, 0xDF, + 0xA1, 0x30, 0x37, 0xAE, 0x36, 0x15, 0x22, 0x38, + 0xF4, 0xA7, 0x45, 0x4C, 0x81, 0xE9, 0x84, 0x97, + 0x35, 0xCB, 0xCE, 0x3C, 0x71, 0x11, 0xC7, 0x89, + 0x75, 0xFB, 0xDA, 0xF8, 0x94, 0x59, 0x82, 0xC4, + 0xFF, 0x49, 0x39, 0x67, 0xC0, 0xCF, 0xD7, 0xB8, + 0x0F, 0x8E, 0x42, 0x23, 0x91, 0x6C, 0xDB, 0xA4, + 0x34, 0xF1, 0x48, 0xC2, 0x6F, 0x3D, 0x2D, 0x40, + 0xBE, 0x3E, 0xBC, 0xC1, 0xAA, 0xBA, 0x4E, 0x55, + 0x3B, 0xDC, 0x68, 0x7F, 0x9C, 0xD8, 0x4A, 0x56, + 0x77, 0xA0, 0xED, 0x46, 0xB5, 0x2B, 0x65, 0xFA, + 0xE3, 0xB9, 0xB1, 0x9F, 0x5E, 0xF9, 0xE6, 0xB2, + 0x31, 0xEA, 0x6D, 0x5F, 0xE4, 0xF0, 0xCD, 0x88, + 0x16, 0x3A, 0x58, 0xD4, 0x62, 0x29, 0x07, 0x33, + 0xE8, 0x1B, 0x05, 0x79, 0x90, 0x6A, 0x2A, 0x9A + }, + { + 0x38, 0xE8, 0x2D, 0xA6, 0xCF, 0xDE, 0xB3, 0xB8, + 0xAF, 0x60, 0x55, 0xC7, 0x44, 0x6F, 0x6B, 0x5B, + 0xC3, 0x62, 0x33, 0xB5, 0x29, 0xA0, 0xE2, 0xA7, + 0xD3, 0x91, 0x11, 0x06, 0x1C, 0xBC, 0x36, 0x4B, + 0xEF, 0x88, 0x6C, 0xA8, 0x17, 0xC4, 0x16, 0xF4, + 0xC2, 0x45, 0xE1, 0xD6, 0x3F, 0x3D, 0x8E, 0x98, + 0x28, 0x4E, 0xF6, 0x3E, 0xA5, 0xF9, 0x0D, 0xDF, + 0xD8, 0x2B, 0x66, 0x7A, 0x27, 0x2F, 0xF1, 0x72, + 0x42, 0xD4, 0x41, 0xC0, 0x73, 0x67, 0xAC, 0x8B, + 0xF7, 0xAD, 0x80, 0x1F, 0xCA, 0x2C, 0xAA, 0x34, + 0xD2, 0x0B, 0xEE, 0xE9, 0x5D, 0x94, 0x18, 0xF8, + 0x57, 0xAE, 0x08, 0xC5, 0x13, 0xCD, 0x86, 0xB9, + 0xFF, 0x7D, 0xC1, 0x31, 0xF5, 0x8A, 0x6A, 0xB1, + 0xD1, 0x20, 0xD7, 0x02, 0x22, 0x04, 0x68, 0x71, + 0x07, 0xDB, 0x9D, 0x99, 0x61, 0xBE, 0xE6, 0x59, + 0xDD, 0x51, 0x90, 0xDC, 0x9A, 0xA3, 0xAB, 0xD0, + 0x81, 0x0F, 0x47, 0x1A, 0xE3, 0xEC, 0x8D, 0xBF, + 0x96, 0x7B, 0x5C, 0xA2, 0xA1, 0x63, 0x23, 0x4D, + 0xC8, 0x9E, 0x9C, 0x3A, 0x0C, 0x2E, 0xBA, 0x6E, + 0x9F, 0x5A, 0xF2, 0x92, 0xF3, 0x49, 0x78, 0xCC, + 0x15, 0xFB, 0x70, 0x75, 0x7F, 0x35, 0x10, 0x03, + 0x64, 0x6D, 0xC6, 0x74, 0xD5, 0xB4, 0xEA, 0x09, + 0x76, 0x19, 0xFE, 0x40, 0x12, 0xE0, 0xBD, 0x05, + 0xFA, 0x01, 0xF0, 0x2A, 0x5E, 0xA9, 0x56, 0x43, + 0x85, 0x14, 0x89, 0x9B, 0xB0, 0xE5, 0x48, 0x79, + 0x97, 0xFC, 0x1E, 0x82, 0x21, 0x8C, 0x1B, 0x5F, + 0x77, 0x54, 0xB2, 0x1D, 0x25, 0x4F, 0x00, 0x46, + 0xED, 0x58, 0x52, 0xEB, 0x7E, 0xDA, 0xC9, 0xFD, + 0x30, 0x95, 0x65, 0x3C, 0xB6, 0xE4, 0xBB, 0x7C, + 0x0E, 0x50, 0x39, 0x26, 0x32, 0x84, 0x69, 0x93, + 0x37, 0xE7, 0x24, 0xA4, 0xCB, 0x53, 0x0A, 0x87, + 0xD9, 0x4C, 0x83, 0x8F, 0xCE, 0x3B, 0x4A, 0xB7 + } +}; + +static unsigned int G_FUNC(unsigned int v) +{ + unsigned int s0, s1, s2, s3, ret; + + s0 = SEED_Sbox[0][(unsigned char) (v) & 0xff]; + s1 = SEED_Sbox[1][(unsigned char)((v)>> 8) & 0xff]; + s2 = SEED_Sbox[0][(unsigned char)((v)>>16) & 0xff]; + s3 = SEED_Sbox[1][(unsigned char)((v)>>24) & 0xff]; + + ret = ((s0 & 0xFC) ^ (s1 & 0xF3) ^ (s2 & 0xCF) ^ (s3 & 0x3F)); + ret |= ((s0 & 0xF3) ^ (s1 & 0xCF) ^ (s2 & 0x3F) ^ (s3 & 0xFC)) << 8; + ret |= ((s0 & 0xCF) ^ (s1 & 0x3F) ^ (s2 & 0xFC) ^ (s3 & 0xF3)) << 16; + ret |= ((s0 & 0x3F) ^ (s1 & 0xFC) ^ (s2 & 0xF3) ^ (s3 & 0xCF)) << 24; + + return ret; +} +# endif + +/* key schedule constants - golden ratio */ +# define KC0 0x9e3779b9 +# define KC1 0x3c6ef373 +# define KC2 0x78dde6e6 +# define KC3 0xf1bbcdcc +# define KC4 0xe3779b99 +# define KC5 0xc6ef3733 +# define KC6 0x8dde6e67 +# define KC7 0x1bbcdccf +# define KC8 0x3779b99e +# define KC9 0x6ef3733c +# define KC10 0xdde6e678 +# define KC11 0xbbcdccf1 +# define KC12 0x779b99e3 +# define KC13 0xef3733c6 +# define KC14 0xde6e678d +# define KC15 0xbcdccf1b + +# if defined(OPENSSL_SMALL_FOOTPRINT) +static const seed_word KC[] = { + KC0, KC1, KC2, KC3, KC4, KC5, KC6, KC7, + KC8, KC9, KC10, KC11, KC12, KC13, KC14, KC15 +}; +# endif + +void SEED_set_key(const unsigned char rawkey[SEED_KEY_LENGTH], + SEED_KEY_SCHEDULE *ks) +{ + seed_word x1, x2, x3, x4; + seed_word t0, t1; + + char2word(rawkey, x1); + char2word(rawkey + 4, x2); + char2word(rawkey + 8, x3); + char2word(rawkey + 12, x4); + + t0 = (x1 + x3 - KC0) & 0xffffffff; + t1 = (x2 - x4 + KC0) & 0xffffffff; + KEYUPDATE_TEMP(t0, t1, &ks->data[0]); + KEYSCHEDULE_UPDATE1(t0, t1, x1, x2, x3, x4, KC1); + KEYUPDATE_TEMP(t0, t1, &ks->data[2]); + +# if !defined(OPENSSL_SMALL_FOOTPRINT) + KEYSCHEDULE_UPDATE0(t0, t1, x1, x2, x3, x4, KC2); + KEYUPDATE_TEMP(t0, t1, &ks->data[4]); + KEYSCHEDULE_UPDATE1(t0, t1, x1, x2, x3, x4, KC3); + KEYUPDATE_TEMP(t0, t1, &ks->data[6]); + KEYSCHEDULE_UPDATE0(t0, t1, x1, x2, x3, x4, KC4); + KEYUPDATE_TEMP(t0, t1, &ks->data[8]); + KEYSCHEDULE_UPDATE1(t0, t1, x1, x2, x3, x4, KC5); + KEYUPDATE_TEMP(t0, t1, &ks->data[10]); + KEYSCHEDULE_UPDATE0(t0, t1, x1, x2, x3, x4, KC6); + KEYUPDATE_TEMP(t0, t1, &ks->data[12]); + KEYSCHEDULE_UPDATE1(t0, t1, x1, x2, x3, x4, KC7); + KEYUPDATE_TEMP(t0, t1, &ks->data[14]); + KEYSCHEDULE_UPDATE0(t0, t1, x1, x2, x3, x4, KC8); + KEYUPDATE_TEMP(t0, t1, &ks->data[16]); + KEYSCHEDULE_UPDATE1(t0, t1, x1, x2, x3, x4, KC9); + KEYUPDATE_TEMP(t0, t1, &ks->data[18]); + KEYSCHEDULE_UPDATE0(t0, t1, x1, x2, x3, x4, KC10); + KEYUPDATE_TEMP(t0, t1, &ks->data[20]); + KEYSCHEDULE_UPDATE1(t0, t1, x1, x2, x3, x4, KC11); + KEYUPDATE_TEMP(t0, t1, &ks->data[22]); + KEYSCHEDULE_UPDATE0(t0, t1, x1, x2, x3, x4, KC12); + KEYUPDATE_TEMP(t0, t1, &ks->data[24]); + KEYSCHEDULE_UPDATE1(t0, t1, x1, x2, x3, x4, KC13); + KEYUPDATE_TEMP(t0, t1, &ks->data[26]); + KEYSCHEDULE_UPDATE0(t0, t1, x1, x2, x3, x4, KC14); + KEYUPDATE_TEMP(t0, t1, &ks->data[28]); + KEYSCHEDULE_UPDATE1(t0, t1, x1, x2, x3, x4, KC15); + KEYUPDATE_TEMP(t0, t1, &ks->data[30]); +# else + { + int i; + for (i = 2; i < 16; i += 2) { + KEYSCHEDULE_UPDATE0(t0, t1, x1, x2, x3, x4, KC[i]); + KEYUPDATE_TEMP(t0, t1, &ks->data[i * 2]); + KEYSCHEDULE_UPDATE1(t0, t1, x1, x2, x3, x4, KC[i + 1]); + KEYUPDATE_TEMP(t0, t1, &ks->data[i * 2 + 2]); + } + } +# endif +} + +void SEED_encrypt(const unsigned char s[SEED_BLOCK_SIZE], + unsigned char d[SEED_BLOCK_SIZE], + const SEED_KEY_SCHEDULE *ks) +{ + seed_word x1, x2, x3, x4; + seed_word t0, t1; + + char2word(s, x1); + char2word(s + 4, x2); + char2word(s + 8, x3); + char2word(s + 12, x4); + +# if !defined(OPENSSL_SMALL_FOOTPRINT) + E_SEED(t0, t1, x1, x2, x3, x4, 0); + E_SEED(t0, t1, x3, x4, x1, x2, 2); + E_SEED(t0, t1, x1, x2, x3, x4, 4); + E_SEED(t0, t1, x3, x4, x1, x2, 6); + E_SEED(t0, t1, x1, x2, x3, x4, 8); + E_SEED(t0, t1, x3, x4, x1, x2, 10); + E_SEED(t0, t1, x1, x2, x3, x4, 12); + E_SEED(t0, t1, x3, x4, x1, x2, 14); + E_SEED(t0, t1, x1, x2, x3, x4, 16); + E_SEED(t0, t1, x3, x4, x1, x2, 18); + E_SEED(t0, t1, x1, x2, x3, x4, 20); + E_SEED(t0, t1, x3, x4, x1, x2, 22); + E_SEED(t0, t1, x1, x2, x3, x4, 24); + E_SEED(t0, t1, x3, x4, x1, x2, 26); + E_SEED(t0, t1, x1, x2, x3, x4, 28); + E_SEED(t0, t1, x3, x4, x1, x2, 30); +# else + { + int i; + for (i = 0; i < 30; i += 4) { + E_SEED(t0, t1, x1, x2, x3, x4, i); + E_SEED(t0, t1, x3, x4, x1, x2, i + 2); + } + } +# endif + + word2char(x3, d); + word2char(x4, d + 4); + word2char(x1, d + 8); + word2char(x2, d + 12); +} + +void SEED_decrypt(const unsigned char s[SEED_BLOCK_SIZE], + unsigned char d[SEED_BLOCK_SIZE], + const SEED_KEY_SCHEDULE *ks) +{ + seed_word x1, x2, x3, x4; + seed_word t0, t1; + + char2word(s, x1); + char2word(s + 4, x2); + char2word(s + 8, x3); + char2word(s + 12, x4); + +# if !defined(OPENSSL_SMALL_FOOTPRINT) + E_SEED(t0, t1, x1, x2, x3, x4, 30); + E_SEED(t0, t1, x3, x4, x1, x2, 28); + E_SEED(t0, t1, x1, x2, x3, x4, 26); + E_SEED(t0, t1, x3, x4, x1, x2, 24); + E_SEED(t0, t1, x1, x2, x3, x4, 22); + E_SEED(t0, t1, x3, x4, x1, x2, 20); + E_SEED(t0, t1, x1, x2, x3, x4, 18); + E_SEED(t0, t1, x3, x4, x1, x2, 16); + E_SEED(t0, t1, x1, x2, x3, x4, 14); + E_SEED(t0, t1, x3, x4, x1, x2, 12); + E_SEED(t0, t1, x1, x2, x3, x4, 10); + E_SEED(t0, t1, x3, x4, x1, x2, 8); + E_SEED(t0, t1, x1, x2, x3, x4, 6); + E_SEED(t0, t1, x3, x4, x1, x2, 4); + E_SEED(t0, t1, x1, x2, x3, x4, 2); + E_SEED(t0, t1, x3, x4, x1, x2, 0); +# else + { + int i; + for (i = 30; i > 0; i -= 4) { + E_SEED(t0, t1, x1, x2, x3, x4, i); + E_SEED(t0, t1, x3, x4, x1, x2, i - 2); + + } + } +# endif + + word2char(x3, d); + word2char(x4, d + 4); + word2char(x1, d + 8); + word2char(x2, d + 12); +} + +#endif /* OPENSSL_NO_SEED */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/seed/seed_cbc.c b/trunk/3rdparty/openssl-1.1-fit/crypto/seed/seed_cbc.c new file mode 100644 index 000000000..c9a4fe217 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/seed/seed_cbc.c @@ -0,0 +1,23 @@ +/* + * Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +void SEED_cbc_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const SEED_KEY_SCHEDULE *ks, + unsigned char ivec[SEED_BLOCK_SIZE], int enc) +{ + if (enc) + CRYPTO_cbc128_encrypt(in, out, len, ks, ivec, + (block128_f) SEED_encrypt); + else + CRYPTO_cbc128_decrypt(in, out, len, ks, ivec, + (block128_f) SEED_decrypt); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/seed/seed_cfb.c b/trunk/3rdparty/openssl-1.1-fit/crypto/seed/seed_cfb.c new file mode 100644 index 000000000..2aee1ffe3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/seed/seed_cfb.c @@ -0,0 +1,20 @@ +/* + * Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +void SEED_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const SEED_KEY_SCHEDULE *ks, + unsigned char ivec[SEED_BLOCK_SIZE], int *num, + int enc) +{ + CRYPTO_cfb128_encrypt(in, out, len, ks, ivec, num, enc, + (block128_f) SEED_encrypt); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/seed/seed_ecb.c b/trunk/3rdparty/openssl-1.1-fit/crypto/seed/seed_ecb.c new file mode 100644 index 000000000..b6e301ccd --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/seed/seed_ecb.c @@ -0,0 +1,19 @@ +/* + * Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +void SEED_ecb_encrypt(const unsigned char *in, unsigned char *out, + const SEED_KEY_SCHEDULE *ks, int enc) +{ + if (enc) + SEED_encrypt(in, out, ks); + else + SEED_decrypt(in, out, ks); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/seed/seed_locl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/seed/seed_locl.h new file mode 100644 index 000000000..ac2950d97 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/seed/seed_locl.h @@ -0,0 +1,112 @@ +/* + * Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Copyright (c) 2007 KISA(Korea Information Security Agency). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Neither the name of author nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#ifndef HEADER_SEED_LOCL_H +# define HEADER_SEED_LOCL_H + +# include "openssl/e_os2.h" +# include + +# ifdef SEED_LONG /* need 32-bit type */ +typedef unsigned long seed_word; +# else +typedef unsigned int seed_word; +# endif + + +# define char2word(c, i) \ + (i) = ((((seed_word)(c)[0]) << 24) | (((seed_word)(c)[1]) << 16) | (((seed_word)(c)[2]) << 8) | ((seed_word)(c)[3])) + +# define word2char(l, c) \ + *((c)+0) = (unsigned char)((l)>>24) & 0xff; \ + *((c)+1) = (unsigned char)((l)>>16) & 0xff; \ + *((c)+2) = (unsigned char)((l)>> 8) & 0xff; \ + *((c)+3) = (unsigned char)((l)) & 0xff + +# define KEYSCHEDULE_UPDATE0(T0, T1, X1, X2, X3, X4, KC) \ + (T0) = (X3); \ + (X3) = (((X3)<<8) ^ ((X4)>>24)) & 0xffffffff; \ + (X4) = (((X4)<<8) ^ ((T0)>>24)) & 0xffffffff; \ + (T0) = ((X1) + (X3) - (KC)) & 0xffffffff; \ + (T1) = ((X2) + (KC) - (X4)) & 0xffffffff + +# define KEYSCHEDULE_UPDATE1(T0, T1, X1, X2, X3, X4, KC) \ + (T0) = (X1); \ + (X1) = (((X1)>>8) ^ ((X2)<<24)) & 0xffffffff; \ + (X2) = (((X2)>>8) ^ ((T0)<<24)) & 0xffffffff; \ + (T0) = ((X1) + (X3) - (KC)) & 0xffffffff; \ + (T1) = ((X2) + (KC) - (X4)) & 0xffffffff + +# define KEYUPDATE_TEMP(T0, T1, K) \ + (K)[0] = G_FUNC((T0)); \ + (K)[1] = G_FUNC((T1)) + +# define XOR_SEEDBLOCK(DST, SRC) \ + ((DST))[0] ^= ((SRC))[0]; \ + ((DST))[1] ^= ((SRC))[1]; \ + ((DST))[2] ^= ((SRC))[2]; \ + ((DST))[3] ^= ((SRC))[3] + +# define MOV_SEEDBLOCK(DST, SRC) \ + ((DST))[0] = ((SRC))[0]; \ + ((DST))[1] = ((SRC))[1]; \ + ((DST))[2] = ((SRC))[2]; \ + ((DST))[3] = ((SRC))[3] + +# define CHAR2WORD(C, I) \ + char2word((C), (I)[0]); \ + char2word((C+4), (I)[1]); \ + char2word((C+8), (I)[2]); \ + char2word((C+12), (I)[3]) + +# define WORD2CHAR(I, C) \ + word2char((I)[0], (C)); \ + word2char((I)[1], (C+4)); \ + word2char((I)[2], (C+8)); \ + word2char((I)[3], (C+12)) + +# define E_SEED(T0, T1, X1, X2, X3, X4, rbase) \ + (T0) = (X3) ^ (ks->data)[(rbase)]; \ + (T1) = (X4) ^ (ks->data)[(rbase)+1]; \ + (T1) ^= (T0); \ + (T1) = G_FUNC((T1)); \ + (T0) = ((T0) + (T1)) & 0xffffffff; \ + (T0) = G_FUNC((T0)); \ + (T1) = ((T1) + (T0)) & 0xffffffff; \ + (T1) = G_FUNC((T1)); \ + (T0) = ((T0) + (T1)) & 0xffffffff; \ + (X1) ^= (T0); \ + (X2) ^= (T1) + +#endif /* HEADER_SEED_LOCL_H */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/seed/seed_ofb.c b/trunk/3rdparty/openssl-1.1-fit/crypto/seed/seed_ofb.c new file mode 100644 index 000000000..b45554058 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/seed/seed_ofb.c @@ -0,0 +1,19 @@ +/* + * Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +void SEED_ofb128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const SEED_KEY_SCHEDULE *ks, + unsigned char ivec[SEED_BLOCK_SIZE], int *num) +{ + CRYPTO_ofb128_encrypt(in, out, len, ks, ivec, num, + (block128_f) SEED_encrypt); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-armv4.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-armv4.pl new file mode 100755 index 000000000..8bf665c8b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-armv4.pl @@ -0,0 +1,1606 @@ +#!/usr/bin/env perl +# Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# Keccak-1600 for ARMv4. +# +# June 2017. +# +# Non-NEON code is KECCAK_1X variant (see sha/keccak1600.c) with bit +# interleaving. How does it compare to Keccak Code Package? It's as +# fast, but several times smaller, and is endian- and ISA-neutral. ISA +# neutrality means that minimum ISA requirement is ARMv4, yet it can +# be assembled even as Thumb-2. NEON code path is KECCAK_1X_ALT with +# register layout taken from Keccak Code Package. It's also as fast, +# in fact faster by 10-15% on some processors, and endian-neutral. +# +# August 2017. +# +# Switch to KECCAK_2X variant for non-NEON code and merge almost 1/2 +# of rotate instructions with logical ones. This resulted in ~10% +# improvement on most processors. Switch to KECCAK_2X effectively +# minimizes re-loads from temporary storage, and merged rotates just +# eliminate corresponding instructions. As for latter. When examining +# code you'll notice commented ror instructions. These are eliminated +# ones, and you should trace destination register below to see what's +# going on. Just in case, why not all rotates are eliminated. Trouble +# is that you have operations that require both inputs to be rotated, +# e.g. 'eor a,b>>>x,c>>>y'. This conundrum is resolved by using +# 'eor a,b,c>>>(x-y)' and then merge-rotating 'a' in next operation +# that takes 'a' as input. And thing is that this next operation can +# be in next round. It's totally possible to "carry" rotate "factors" +# to the next round, but it makes code more complex. And the last word +# is the keyword, i.e. "almost 1/2" is kind of complexity cap [for the +# time being]... +# +# Reduce per-round instruction count in Thumb-2 case by 16%. This is +# achieved by folding ldr/str pairs to their double-word counterparts. +# Theoretically this should have improved performance on single-issue +# cores, such as Cortex-A5/A7, by 19%. Reality is a bit different, as +# usual... +# +######################################################################## +# Numbers are cycles per processed byte. Non-NEON results account even +# for input bit interleaving. +# +# r=1088(*) Thumb-2(**) NEON +# +# ARM11xx 82/+150% +# Cortex-A5 88/+160%, 86, 36 +# Cortex-A7 78/+160%, 68, 34 +# Cortex-A8 51/+230%, 57, 30 +# Cortex-A9 53/+210%, 51, 26 +# Cortex-A15 42/+160%, 38, 18 +# Snapdragon S4 43/+210%, 38, 24 +# +# (*) Corresponds to SHA3-256. Percentage after slash is improvement +# over compiler-generated KECCAK_2X reference code. +# (**) Thumb-2 results for Cortex-A5/A7 are likely to apply even to +# Cortex-Mx, x>=3. Otherwise, non-NEON results for NEON-capable +# processors are presented mostly for reference purposes. + +$flavour = shift; +if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + open STDOUT,">$output"; +} + +my @C = map("r$_",(0..9)); +my @E = map("r$_",(10..12,14)); + +######################################################################## +# Stack layout +# ----->+-----------------------+ +# | uint64_t A[5][5] | +# | ... | +# +200->+-----------------------+ +# | uint64_t D[5] | +# | ... | +# +240->+-----------------------+ +# | uint64_t T[5][5] | +# | ... | +# +440->+-----------------------+ +# | saved lr | +# +444->+-----------------------+ +# | loop counter | +# +448->+-----------------------+ +# | ... + +my @A = map([ 8*$_, 8*($_+1), 8*($_+2), 8*($_+3), 8*($_+4) ], (0,5,10,15,20)); +my @D = map(8*$_, (25..29)); +my @T = map([ 8*$_, 8*($_+1), 8*($_+2), 8*($_+3), 8*($_+4) ], (30,35,40,45,50)); + +$code.=<<___; +#include "arm_arch.h" + +.text + +#if defined(__thumb2__) +.syntax unified +.thumb +#else +.code 32 +#endif + +.type iotas32, %object +.align 5 +iotas32: + .long 0x00000001, 0x00000000 + .long 0x00000000, 0x00000089 + .long 0x00000000, 0x8000008b + .long 0x00000000, 0x80008080 + .long 0x00000001, 0x0000008b + .long 0x00000001, 0x00008000 + .long 0x00000001, 0x80008088 + .long 0x00000001, 0x80000082 + .long 0x00000000, 0x0000000b + .long 0x00000000, 0x0000000a + .long 0x00000001, 0x00008082 + .long 0x00000000, 0x00008003 + .long 0x00000001, 0x0000808b + .long 0x00000001, 0x8000000b + .long 0x00000001, 0x8000008a + .long 0x00000001, 0x80000081 + .long 0x00000000, 0x80000081 + .long 0x00000000, 0x80000008 + .long 0x00000000, 0x00000083 + .long 0x00000000, 0x80008003 + .long 0x00000001, 0x80008088 + .long 0x00000000, 0x80000088 + .long 0x00000001, 0x00008000 + .long 0x00000000, 0x80008082 +.size iotas32,.-iotas32 + +.type KeccakF1600_int, %function +.align 5 +KeccakF1600_int: + add @C[9],sp,#$A[4][2] + add @E[2],sp,#$A[0][0] + add @E[0],sp,#$A[1][0] + ldmia @C[9],{@C[4]-@C[9]} @ A[4][2..4] +KeccakF1600_enter: + str lr,[sp,#440] + eor @E[1],@E[1],@E[1] + str @E[1],[sp,#444] + b .Lround2x + +.align 4 +.Lround2x: +___ +sub Round { +my (@A,@R); (@A[0..4],@R) = @_; + +$code.=<<___; + ldmia @E[2],{@C[0]-@C[3]} @ A[0][0..1] + ldmia @E[0],{@E[0]-@E[2],@E[3]} @ A[1][0..1] +#ifdef __thumb2__ + eor @C[0],@C[0],@E[0] + eor @C[1],@C[1],@E[1] + eor @C[2],@C[2],@E[2] + ldrd @E[0],@E[1],[sp,#$A[1][2]] + eor @C[3],@C[3],@E[3] + ldrd @E[2],@E[3],[sp,#$A[1][3]] + eor @C[4],@C[4],@E[0] + eor @C[5],@C[5],@E[1] + eor @C[6],@C[6],@E[2] + ldrd @E[0],@E[1],[sp,#$A[1][4]] + eor @C[7],@C[7],@E[3] + ldrd @E[2],@E[3],[sp,#$A[2][0]] + eor @C[8],@C[8],@E[0] + eor @C[9],@C[9],@E[1] + eor @C[0],@C[0],@E[2] + ldrd @E[0],@E[1],[sp,#$A[2][1]] + eor @C[1],@C[1],@E[3] + ldrd @E[2],@E[3],[sp,#$A[2][2]] + eor @C[2],@C[2],@E[0] + eor @C[3],@C[3],@E[1] + eor @C[4],@C[4],@E[2] + ldrd @E[0],@E[1],[sp,#$A[2][3]] + eor @C[5],@C[5],@E[3] + ldrd @E[2],@E[3],[sp,#$A[2][4]] + eor @C[6],@C[6],@E[0] + eor @C[7],@C[7],@E[1] + eor @C[8],@C[8],@E[2] + ldrd @E[0],@E[1],[sp,#$A[3][0]] + eor @C[9],@C[9],@E[3] + ldrd @E[2],@E[3],[sp,#$A[3][1]] + eor @C[0],@C[0],@E[0] + eor @C[1],@C[1],@E[1] + eor @C[2],@C[2],@E[2] + ldrd @E[0],@E[1],[sp,#$A[3][2]] + eor @C[3],@C[3],@E[3] + ldrd @E[2],@E[3],[sp,#$A[3][3]] + eor @C[4],@C[4],@E[0] + eor @C[5],@C[5],@E[1] + eor @C[6],@C[6],@E[2] + ldrd @E[0],@E[1],[sp,#$A[3][4]] + eor @C[7],@C[7],@E[3] + ldrd @E[2],@E[3],[sp,#$A[4][0]] + eor @C[8],@C[8],@E[0] + eor @C[9],@C[9],@E[1] + eor @C[0],@C[0],@E[2] + ldrd @E[0],@E[1],[sp,#$A[4][1]] + eor @C[1],@C[1],@E[3] + ldrd @E[2],@E[3],[sp,#$A[0][2]] + eor @C[2],@C[2],@E[0] + eor @C[3],@C[3],@E[1] + eor @C[4],@C[4],@E[2] + ldrd @E[0],@E[1],[sp,#$A[0][3]] + eor @C[5],@C[5],@E[3] + ldrd @E[2],@E[3],[sp,#$A[0][4]] +#else + eor @C[0],@C[0],@E[0] + add @E[0],sp,#$A[1][2] + eor @C[1],@C[1],@E[1] + eor @C[2],@C[2],@E[2] + eor @C[3],@C[3],@E[3] + ldmia @E[0],{@E[0]-@E[2],@E[3]} @ A[1][2..3] + eor @C[4],@C[4],@E[0] + add @E[0],sp,#$A[1][4] + eor @C[5],@C[5],@E[1] + eor @C[6],@C[6],@E[2] + eor @C[7],@C[7],@E[3] + ldmia @E[0],{@E[0]-@E[2],@E[3]} @ A[1][4]..A[2][0] + eor @C[8],@C[8],@E[0] + add @E[0],sp,#$A[2][1] + eor @C[9],@C[9],@E[1] + eor @C[0],@C[0],@E[2] + eor @C[1],@C[1],@E[3] + ldmia @E[0],{@E[0]-@E[2],@E[3]} @ A[2][1..2] + eor @C[2],@C[2],@E[0] + add @E[0],sp,#$A[2][3] + eor @C[3],@C[3],@E[1] + eor @C[4],@C[4],@E[2] + eor @C[5],@C[5],@E[3] + ldmia @E[0],{@E[0]-@E[2],@E[3]} @ A[2][3..4] + eor @C[6],@C[6],@E[0] + add @E[0],sp,#$A[3][0] + eor @C[7],@C[7],@E[1] + eor @C[8],@C[8],@E[2] + eor @C[9],@C[9],@E[3] + ldmia @E[0],{@E[0]-@E[2],@E[3]} @ A[3][0..1] + eor @C[0],@C[0],@E[0] + add @E[0],sp,#$A[3][2] + eor @C[1],@C[1],@E[1] + eor @C[2],@C[2],@E[2] + eor @C[3],@C[3],@E[3] + ldmia @E[0],{@E[0]-@E[2],@E[3]} @ A[3][2..3] + eor @C[4],@C[4],@E[0] + add @E[0],sp,#$A[3][4] + eor @C[5],@C[5],@E[1] + eor @C[6],@C[6],@E[2] + eor @C[7],@C[7],@E[3] + ldmia @E[0],{@E[0]-@E[2],@E[3]} @ A[3][4]..A[4][0] + eor @C[8],@C[8],@E[0] + ldr @E[0],[sp,#$A[4][1]] @ A[4][1] + eor @C[9],@C[9],@E[1] + ldr @E[1],[sp,#$A[4][1]+4] + eor @C[0],@C[0],@E[2] + ldr @E[2],[sp,#$A[0][2]] @ A[0][2] + eor @C[1],@C[1],@E[3] + ldr @E[3],[sp,#$A[0][2]+4] + eor @C[2],@C[2],@E[0] + add @E[0],sp,#$A[0][3] + eor @C[3],@C[3],@E[1] + eor @C[4],@C[4],@E[2] + eor @C[5],@C[5],@E[3] + ldmia @E[0],{@E[0]-@E[2],@E[3]} @ A[0][3..4] +#endif + eor @C[6],@C[6],@E[0] + eor @C[7],@C[7],@E[1] + eor @C[8],@C[8],@E[2] + eor @C[9],@C[9],@E[3] + + eor @E[0],@C[0],@C[5],ror#32-1 @ E[0] = ROL64(C[2], 1) ^ C[0]; + str.l @E[0],[sp,#$D[1]] @ D[1] = E[0] + eor @E[1],@C[1],@C[4] + str.h @E[1],[sp,#$D[1]+4] + eor @E[2],@C[6],@C[1],ror#32-1 @ E[1] = ROL64(C[0], 1) ^ C[3]; + eor @E[3],@C[7],@C[0] + str.l @E[2],[sp,#$D[4]] @ D[4] = E[1] + eor @C[0],@C[8],@C[3],ror#32-1 @ C[0] = ROL64(C[1], 1) ^ C[4]; + str.h @E[3],[sp,#$D[4]+4] + eor @C[1],@C[9],@C[2] + str.l @C[0],[sp,#$D[0]] @ D[0] = C[0] + eor @C[2],@C[2],@C[7],ror#32-1 @ C[1] = ROL64(C[3], 1) ^ C[1]; + ldr.l @C[7],[sp,#$A[3][3]] + eor @C[3],@C[3],@C[6] + str.h @C[1],[sp,#$D[0]+4] + ldr.h @C[6],[sp,#$A[3][3]+4] + str.l @C[2],[sp,#$D[2]] @ D[2] = C[1] + eor @C[4],@C[4],@C[9],ror#32-1 @ C[2] = ROL64(C[4], 1) ^ C[2]; + str.h @C[3],[sp,#$D[2]+4] + eor @C[5],@C[5],@C[8] + + ldr.l @C[8],[sp,#$A[4][4]] + ldr.h @C[9],[sp,#$A[4][4]+4] + str.l @C[4],[sp,#$D[3]] @ D[3] = C[2] + eor @C[7],@C[7],@C[4] + str.h @C[5],[sp,#$D[3]+4] + eor @C[6],@C[6],@C[5] + ldr.l @C[4],[sp,#$A[0][0]] + @ ror @C[7],@C[7],#32-10 @ C[3] = ROL64(A[3][3] ^ C[2], rhotates[3][3]); /* D[3] */ + @ ror @C[6],@C[6],#32-11 + ldr.h @C[5],[sp,#$A[0][0]+4] + eor @C[8],@C[8],@E[2] + eor @C[9],@C[9],@E[3] + ldr.l @E[2],[sp,#$A[2][2]] + eor @C[0],@C[0],@C[4] + ldr.h @E[3],[sp,#$A[2][2]+4] + @ ror @C[8],@C[8],#32-7 @ C[4] = ROL64(A[4][4] ^ E[1], rhotates[4][4]); /* D[4] */ + @ ror @C[9],@C[9],#32-7 + eor @C[1],@C[1],@C[5] @ C[0] = A[0][0] ^ C[0]; /* rotate by 0 */ /* D[0] */ + eor @E[2],@E[2],@C[2] + ldr.l @C[2],[sp,#$A[1][1]] + eor @E[3],@E[3],@C[3] + ldr.h @C[3],[sp,#$A[1][1]+4] + ror @C[5],@E[2],#32-21 @ C[2] = ROL64(A[2][2] ^ C[1], rhotates[2][2]); /* D[2] */ + ldr @E[2],[sp,#444] @ load counter + eor @C[2],@C[2],@E[0] + adr @E[0],iotas32 + ror @C[4],@E[3],#32-22 + add @E[3],@E[0],@E[2] + eor @C[3],@C[3],@E[1] +___ +$code.=<<___ if ($A[0][0] != $T[0][0]); + ldmia @E[3],{@E[0],@E[1]} @ iotas[i] +___ +$code.=<<___ if ($A[0][0] == $T[0][0]); + ldr.l @E[0],[@E[3],#8] @ iotas[i].lo + add @E[2],@E[2],#16 + ldr.h @E[1],[@E[3],#12] @ iotas[i].hi + cmp @E[2],#192 + str @E[2],[sp,#444] @ store counter +___ +$code.=<<___; + bic @E[2],@C[4],@C[2],ror#32-22 + bic @E[3],@C[5],@C[3],ror#32-22 + ror @C[2],@C[2],#32-22 @ C[1] = ROL64(A[1][1] ^ E[0], rhotates[1][1]); /* D[1] */ + ror @C[3],@C[3],#32-22 + eor @E[2],@E[2],@C[0] + eor @E[3],@E[3],@C[1] + eor @E[0],@E[0],@E[2] + eor @E[1],@E[1],@E[3] + str.l @E[0],[sp,#$R[0][0]] @ R[0][0] = C[0] ^ (~C[1] & C[2]) ^ iotas[i]; + bic @E[2],@C[6],@C[4],ror#11 + str.h @E[1],[sp,#$R[0][0]+4] + bic @E[3],@C[7],@C[5],ror#10 + bic @E[0],@C[8],@C[6],ror#32-(11-7) + bic @E[1],@C[9],@C[7],ror#32-(10-7) + eor @E[2],@C[2],@E[2],ror#32-11 + str.l @E[2],[sp,#$R[0][1]] @ R[0][1] = C[1] ^ (~C[2] & C[3]); + eor @E[3],@C[3],@E[3],ror#32-10 + str.h @E[3],[sp,#$R[0][1]+4] + eor @E[0],@C[4],@E[0],ror#32-7 + eor @E[1],@C[5],@E[1],ror#32-7 + str.l @E[0],[sp,#$R[0][2]] @ R[0][2] = C[2] ^ (~C[3] & C[4]); + bic @E[2],@C[0],@C[8],ror#32-7 + str.h @E[1],[sp,#$R[0][2]+4] + bic @E[3],@C[1],@C[9],ror#32-7 + eor @E[2],@E[2],@C[6],ror#32-11 + str.l @E[2],[sp,#$R[0][3]] @ R[0][3] = C[3] ^ (~C[4] & C[0]); + eor @E[3],@E[3],@C[7],ror#32-10 + str.h @E[3],[sp,#$R[0][3]+4] + bic @E[0],@C[2],@C[0] + add @E[3],sp,#$D[3] + ldr.l @C[0],[sp,#$A[0][3]] @ A[0][3] + bic @E[1],@C[3],@C[1] + ldr.h @C[1],[sp,#$A[0][3]+4] + eor @E[0],@E[0],@C[8],ror#32-7 + eor @E[1],@E[1],@C[9],ror#32-7 + str.l @E[0],[sp,#$R[0][4]] @ R[0][4] = C[4] ^ (~C[0] & C[1]); + add @C[9],sp,#$D[0] + str.h @E[1],[sp,#$R[0][4]+4] + + ldmia @E[3],{@E[0]-@E[2],@E[3]} @ D[3..4] + ldmia @C[9],{@C[6]-@C[9]} @ D[0..1] + + ldr.l @C[2],[sp,#$A[1][4]] @ A[1][4] + eor @C[0],@C[0],@E[0] + ldr.h @C[3],[sp,#$A[1][4]+4] + eor @C[1],@C[1],@E[1] + @ ror @C[0],@C[0],#32-14 @ C[0] = ROL64(A[0][3] ^ D[3], rhotates[0][3]); + ldr.l @E[0],[sp,#$A[3][1]] @ A[3][1] + @ ror @C[1],@C[1],#32-14 + ldr.h @E[1],[sp,#$A[3][1]+4] + + eor @C[2],@C[2],@E[2] + ldr.l @C[4],[sp,#$A[2][0]] @ A[2][0] + eor @C[3],@C[3],@E[3] + ldr.h @C[5],[sp,#$A[2][0]+4] + @ ror @C[2],@C[2],#32-10 @ C[1] = ROL64(A[1][4] ^ D[4], rhotates[1][4]); + @ ror @C[3],@C[3],#32-10 + + eor @C[6],@C[6],@C[4] + ldr.l @E[2],[sp,#$D[2]] @ D[2] + eor @C[7],@C[7],@C[5] + ldr.h @E[3],[sp,#$D[2]+4] + ror @C[5],@C[6],#32-1 @ C[2] = ROL64(A[2][0] ^ D[0], rhotates[2][0]); + ror @C[4],@C[7],#32-2 + + eor @E[0],@E[0],@C[8] + ldr.l @C[8],[sp,#$A[4][2]] @ A[4][2] + eor @E[1],@E[1],@C[9] + ldr.h @C[9],[sp,#$A[4][2]+4] + ror @C[7],@E[0],#32-22 @ C[3] = ROL64(A[3][1] ^ D[1], rhotates[3][1]); + ror @C[6],@E[1],#32-23 + + bic @E[0],@C[4],@C[2],ror#32-10 + bic @E[1],@C[5],@C[3],ror#32-10 + eor @E[2],@E[2],@C[8] + eor @E[3],@E[3],@C[9] + ror @C[9],@E[2],#32-30 @ C[4] = ROL64(A[4][2] ^ D[2], rhotates[4][2]); + ror @C[8],@E[3],#32-31 + eor @E[0],@E[0],@C[0],ror#32-14 + eor @E[1],@E[1],@C[1],ror#32-14 + str.l @E[0],[sp,#$R[1][0]] @ R[1][0] = C[0] ^ (~C[1] & C[2]) + bic @E[2],@C[6],@C[4] + str.h @E[1],[sp,#$R[1][0]+4] + bic @E[3],@C[7],@C[5] + eor @E[2],@E[2],@C[2],ror#32-10 + str.l @E[2],[sp,#$R[1][1]] @ R[1][1] = C[1] ^ (~C[2] & C[3]); + eor @E[3],@E[3],@C[3],ror#32-10 + str.h @E[3],[sp,#$R[1][1]+4] + bic @E[0],@C[8],@C[6] + bic @E[1],@C[9],@C[7] + bic @E[2],@C[0],@C[8],ror#14 + bic @E[3],@C[1],@C[9],ror#14 + eor @E[0],@E[0],@C[4] + eor @E[1],@E[1],@C[5] + str.l @E[0],[sp,#$R[1][2]] @ R[1][2] = C[2] ^ (~C[3] & C[4]); + bic @C[2],@C[2],@C[0],ror#32-(14-10) + str.h @E[1],[sp,#$R[1][2]+4] + eor @E[2],@C[6],@E[2],ror#32-14 + bic @E[1],@C[3],@C[1],ror#32-(14-10) + str.l @E[2],[sp,#$R[1][3]] @ R[1][3] = C[3] ^ (~C[4] & C[0]); + eor @E[3],@C[7],@E[3],ror#32-14 + str.h @E[3],[sp,#$R[1][3]+4] + add @E[2],sp,#$D[1] + ldr.l @C[1],[sp,#$A[0][1]] @ A[0][1] + eor @E[0],@C[8],@C[2],ror#32-10 + ldr.h @C[0],[sp,#$A[0][1]+4] + eor @E[1],@C[9],@E[1],ror#32-10 + str.l @E[0],[sp,#$R[1][4]] @ R[1][4] = C[4] ^ (~C[0] & C[1]); + str.h @E[1],[sp,#$R[1][4]+4] + + add @C[9],sp,#$D[3] + ldmia @E[2],{@E[0]-@E[2],@E[3]} @ D[1..2] + ldr.l @C[2],[sp,#$A[1][2]] @ A[1][2] + ldr.h @C[3],[sp,#$A[1][2]+4] + ldmia @C[9],{@C[6]-@C[9]} @ D[3..4] + + eor @C[1],@C[1],@E[0] + ldr.l @C[4],[sp,#$A[2][3]] @ A[2][3] + eor @C[0],@C[0],@E[1] + ldr.h @C[5],[sp,#$A[2][3]+4] + ror @C[0],@C[0],#32-1 @ C[0] = ROL64(A[0][1] ^ D[1], rhotates[0][1]); + + eor @C[2],@C[2],@E[2] + ldr.l @E[0],[sp,#$A[3][4]] @ A[3][4] + eor @C[3],@C[3],@E[3] + ldr.h @E[1],[sp,#$A[3][4]+4] + @ ror @C[2],@C[2],#32-3 @ C[1] = ROL64(A[1][2] ^ D[2], rhotates[1][2]); + ldr.l @E[2],[sp,#$D[0]] @ D[0] + @ ror @C[3],@C[3],#32-3 + ldr.h @E[3],[sp,#$D[0]+4] + + eor @C[4],@C[4],@C[6] + eor @C[5],@C[5],@C[7] + @ ror @C[5],@C[6],#32-12 @ C[2] = ROL64(A[2][3] ^ D[3], rhotates[2][3]); + @ ror @C[4],@C[7],#32-13 @ [track reverse order below] + + eor @E[0],@E[0],@C[8] + ldr.l @C[8],[sp,#$A[4][0]] @ A[4][0] + eor @E[1],@E[1],@C[9] + ldr.h @C[9],[sp,#$A[4][0]+4] + ror @C[6],@E[0],#32-4 @ C[3] = ROL64(A[3][4] ^ D[4], rhotates[3][4]); + ror @C[7],@E[1],#32-4 + + eor @E[2],@E[2],@C[8] + eor @E[3],@E[3],@C[9] + ror @C[8],@E[2],#32-9 @ C[4] = ROL64(A[4][0] ^ D[0], rhotates[4][0]); + ror @C[9],@E[3],#32-9 + + bic @E[0],@C[5],@C[2],ror#13-3 + bic @E[1],@C[4],@C[3],ror#12-3 + bic @E[2],@C[6],@C[5],ror#32-13 + bic @E[3],@C[7],@C[4],ror#32-12 + eor @E[0],@C[0],@E[0],ror#32-13 + eor @E[1],@C[1],@E[1],ror#32-12 + str.l @E[0],[sp,#$R[2][0]] @ R[2][0] = C[0] ^ (~C[1] & C[2]) + eor @E[2],@E[2],@C[2],ror#32-3 + str.h @E[1],[sp,#$R[2][0]+4] + eor @E[3],@E[3],@C[3],ror#32-3 + str.l @E[2],[sp,#$R[2][1]] @ R[2][1] = C[1] ^ (~C[2] & C[3]); + bic @E[0],@C[8],@C[6] + bic @E[1],@C[9],@C[7] + str.h @E[3],[sp,#$R[2][1]+4] + eor @E[0],@E[0],@C[5],ror#32-13 + eor @E[1],@E[1],@C[4],ror#32-12 + str.l @E[0],[sp,#$R[2][2]] @ R[2][2] = C[2] ^ (~C[3] & C[4]); + bic @E[2],@C[0],@C[8] + str.h @E[1],[sp,#$R[2][2]+4] + bic @E[3],@C[1],@C[9] + eor @E[2],@E[2],@C[6] + eor @E[3],@E[3],@C[7] + str.l @E[2],[sp,#$R[2][3]] @ R[2][3] = C[3] ^ (~C[4] & C[0]); + bic @E[0],@C[2],@C[0],ror#3 + str.h @E[3],[sp,#$R[2][3]+4] + bic @E[1],@C[3],@C[1],ror#3 + ldr.l @C[1],[sp,#$A[0][4]] @ A[0][4] [in reverse order] + eor @E[0],@C[8],@E[0],ror#32-3 + ldr.h @C[0],[sp,#$A[0][4]+4] + eor @E[1],@C[9],@E[1],ror#32-3 + str.l @E[0],[sp,#$R[2][4]] @ R[2][4] = C[4] ^ (~C[0] & C[1]); + add @C[9],sp,#$D[1] + str.h @E[1],[sp,#$R[2][4]+4] + + ldr.l @E[0],[sp,#$D[4]] @ D[4] + ldr.h @E[1],[sp,#$D[4]+4] + ldr.l @E[2],[sp,#$D[0]] @ D[0] + ldr.h @E[3],[sp,#$D[0]+4] + + ldmia @C[9],{@C[6]-@C[9]} @ D[1..2] + + eor @C[1],@C[1],@E[0] + ldr.l @C[2],[sp,#$A[1][0]] @ A[1][0] + eor @C[0],@C[0],@E[1] + ldr.h @C[3],[sp,#$A[1][0]+4] + @ ror @C[1],@E[0],#32-13 @ C[0] = ROL64(A[0][4] ^ D[4], rhotates[0][4]); + ldr.l @C[4],[sp,#$A[2][1]] @ A[2][1] + @ ror @C[0],@E[1],#32-14 @ [was loaded in reverse order] + ldr.h @C[5],[sp,#$A[2][1]+4] + + eor @C[2],@C[2],@E[2] + ldr.l @E[0],[sp,#$A[3][2]] @ A[3][2] + eor @C[3],@C[3],@E[3] + ldr.h @E[1],[sp,#$A[3][2]+4] + @ ror @C[2],@C[2],#32-18 @ C[1] = ROL64(A[1][0] ^ D[0], rhotates[1][0]); + ldr.l @E[2],[sp,#$D[3]] @ D[3] + @ ror @C[3],@C[3],#32-18 + ldr.h @E[3],[sp,#$D[3]+4] + + eor @C[6],@C[6],@C[4] + eor @C[7],@C[7],@C[5] + ror @C[4],@C[6],#32-5 @ C[2] = ROL64(A[2][1] ^ D[1], rhotates[2][1]); + ror @C[5],@C[7],#32-5 + + eor @E[0],@E[0],@C[8] + ldr.l @C[8],[sp,#$A[4][3]] @ A[4][3] + eor @E[1],@E[1],@C[9] + ldr.h @C[9],[sp,#$A[4][3]+4] + ror @C[7],@E[0],#32-7 @ C[3] = ROL64(A[3][2] ^ D[2], rhotates[3][2]); + ror @C[6],@E[1],#32-8 + + eor @E[2],@E[2],@C[8] + eor @E[3],@E[3],@C[9] + ror @C[8],@E[2],#32-28 @ C[4] = ROL64(A[4][3] ^ D[3], rhotates[4][3]); + ror @C[9],@E[3],#32-28 + + bic @E[0],@C[4],@C[2],ror#32-18 + bic @E[1],@C[5],@C[3],ror#32-18 + eor @E[0],@E[0],@C[0],ror#32-14 + eor @E[1],@E[1],@C[1],ror#32-13 + str.l @E[0],[sp,#$R[3][0]] @ R[3][0] = C[0] ^ (~C[1] & C[2]) + bic @E[2],@C[6],@C[4] + str.h @E[1],[sp,#$R[3][0]+4] + bic @E[3],@C[7],@C[5] + eor @E[2],@E[2],@C[2],ror#32-18 + str.l @E[2],[sp,#$R[3][1]] @ R[3][1] = C[1] ^ (~C[2] & C[3]); + eor @E[3],@E[3],@C[3],ror#32-18 + str.h @E[3],[sp,#$R[3][1]+4] + bic @E[0],@C[8],@C[6] + bic @E[1],@C[9],@C[7] + bic @E[2],@C[0],@C[8],ror#14 + bic @E[3],@C[1],@C[9],ror#13 + eor @E[0],@E[0],@C[4] + eor @E[1],@E[1],@C[5] + str.l @E[0],[sp,#$R[3][2]] @ R[3][2] = C[2] ^ (~C[3] & C[4]); + bic @C[2],@C[2],@C[0],ror#18-14 + str.h @E[1],[sp,#$R[3][2]+4] + eor @E[2],@C[6],@E[2],ror#32-14 + bic @E[1],@C[3],@C[1],ror#18-13 + eor @E[3],@C[7],@E[3],ror#32-13 + str.l @E[2],[sp,#$R[3][3]] @ R[3][3] = C[3] ^ (~C[4] & C[0]); + str.h @E[3],[sp,#$R[3][3]+4] + add @E[3],sp,#$D[2] + ldr.l @C[0],[sp,#$A[0][2]] @ A[0][2] + eor @E[0],@C[8],@C[2],ror#32-18 + ldr.h @C[1],[sp,#$A[0][2]+4] + eor @E[1],@C[9],@E[1],ror#32-18 + str.l @E[0],[sp,#$R[3][4]] @ R[3][4] = C[4] ^ (~C[0] & C[1]); + str.h @E[1],[sp,#$R[3][4]+4] + + ldmia @E[3],{@E[0]-@E[2],@E[3]} @ D[2..3] + ldr.l @C[2],[sp,#$A[1][3]] @ A[1][3] + ldr.h @C[3],[sp,#$A[1][3]+4] + ldr.l @C[6],[sp,#$D[4]] @ D[4] + ldr.h @C[7],[sp,#$D[4]+4] + + eor @C[0],@C[0],@E[0] + ldr.l @C[4],[sp,#$A[2][4]] @ A[2][4] + eor @C[1],@C[1],@E[1] + ldr.h @C[5],[sp,#$A[2][4]+4] + @ ror @C[0],@C[0],#32-31 @ C[0] = ROL64(A[0][2] ^ D[2], rhotates[0][2]); + ldr.l @C[8],[sp,#$D[0]] @ D[0] + @ ror @C[1],@C[1],#32-31 + ldr.h @C[9],[sp,#$D[0]+4] + + eor @E[2],@E[2],@C[2] + ldr.l @E[0],[sp,#$A[3][0]] @ A[3][0] + eor @E[3],@E[3],@C[3] + ldr.h @E[1],[sp,#$A[3][0]+4] + ror @C[3],@E[2],#32-27 @ C[1] = ROL64(A[1][3] ^ D[3], rhotates[1][3]); + ldr.l @E[2],[sp,#$D[1]] @ D[1] + ror @C[2],@E[3],#32-28 + ldr.h @E[3],[sp,#$D[1]+4] + + eor @C[6],@C[6],@C[4] + eor @C[7],@C[7],@C[5] + ror @C[5],@C[6],#32-19 @ C[2] = ROL64(A[2][4] ^ D[4], rhotates[2][4]); + ror @C[4],@C[7],#32-20 + + eor @E[0],@E[0],@C[8] + ldr.l @C[8],[sp,#$A[4][1]] @ A[4][1] + eor @E[1],@E[1],@C[9] + ldr.h @C[9],[sp,#$A[4][1]+4] + ror @C[7],@E[0],#32-20 @ C[3] = ROL64(A[3][0] ^ D[0], rhotates[3][0]); + ror @C[6],@E[1],#32-21 + + eor @C[8],@C[8],@E[2] + eor @C[9],@C[9],@E[3] + @ ror @C[8],@C[2],#32-1 @ C[4] = ROL64(A[4][1] ^ D[1], rhotates[4][1]); + @ ror @C[9],@C[3],#32-1 + + bic @E[0],@C[4],@C[2] + bic @E[1],@C[5],@C[3] + eor @E[0],@E[0],@C[0],ror#32-31 + str.l @E[0],[sp,#$R[4][0]] @ R[4][0] = C[0] ^ (~C[1] & C[2]) + eor @E[1],@E[1],@C[1],ror#32-31 + str.h @E[1],[sp,#$R[4][0]+4] + bic @E[2],@C[6],@C[4] + bic @E[3],@C[7],@C[5] + eor @E[2],@E[2],@C[2] + eor @E[3],@E[3],@C[3] + str.l @E[2],[sp,#$R[4][1]] @ R[4][1] = C[1] ^ (~C[2] & C[3]); + bic @E[0],@C[8],@C[6],ror#1 + str.h @E[3],[sp,#$R[4][1]+4] + bic @E[1],@C[9],@C[7],ror#1 + bic @E[2],@C[0],@C[8],ror#31-1 + bic @E[3],@C[1],@C[9],ror#31-1 + eor @C[4],@C[4],@E[0],ror#32-1 + str.l @C[4],[sp,#$R[4][2]] @ R[4][2] = C[2] ^= (~C[3] & C[4]); + eor @C[5],@C[5],@E[1],ror#32-1 + str.h @C[5],[sp,#$R[4][2]+4] + eor @C[6],@C[6],@E[2],ror#32-31 + eor @C[7],@C[7],@E[3],ror#32-31 + str.l @C[6],[sp,#$R[4][3]] @ R[4][3] = C[3] ^= (~C[4] & C[0]); + bic @E[0],@C[2],@C[0],ror#32-31 + str.h @C[7],[sp,#$R[4][3]+4] + bic @E[1],@C[3],@C[1],ror#32-31 + add @E[2],sp,#$R[0][0] + eor @C[8],@E[0],@C[8],ror#32-1 + add @E[0],sp,#$R[1][0] + eor @C[9],@E[1],@C[9],ror#32-1 + str.l @C[8],[sp,#$R[4][4]] @ R[4][4] = C[4] ^= (~C[0] & C[1]); + str.h @C[9],[sp,#$R[4][4]+4] +___ +} + Round(@A,@T); + Round(@T,@A); +$code.=<<___; + blo .Lround2x + + ldr pc,[sp,#440] +.size KeccakF1600_int,.-KeccakF1600_int + +.type KeccakF1600, %function +.align 5 +KeccakF1600: + stmdb sp!,{r0,r4-r11,lr} + sub sp,sp,#440+16 @ space for A[5][5],D[5],T[5][5],... + + add @E[0],r0,#$A[1][0] + add @E[1],sp,#$A[1][0] + ldmia r0, {@C[0]-@C[9]} @ copy A[5][5] to stack + stmia sp, {@C[0]-@C[9]} + ldmia @E[0]!,{@C[0]-@C[9]} + stmia @E[1]!,{@C[0]-@C[9]} + ldmia @E[0]!,{@C[0]-@C[9]} + stmia @E[1]!,{@C[0]-@C[9]} + ldmia @E[0]!,{@C[0]-@C[9]} + stmia @E[1]!,{@C[0]-@C[9]} + ldmia @E[0], {@C[0]-@C[9]} + add @E[2],sp,#$A[0][0] + add @E[0],sp,#$A[1][0] + stmia @E[1], {@C[0]-@C[9]} + + bl KeccakF1600_enter + + ldr @E[1], [sp,#440+16] @ restore pointer to A + ldmia sp, {@C[0]-@C[9]} + stmia @E[1]!,{@C[0]-@C[9]} @ return A[5][5] + ldmia @E[0]!,{@C[0]-@C[9]} + stmia @E[1]!,{@C[0]-@C[9]} + ldmia @E[0]!,{@C[0]-@C[9]} + stmia @E[1]!,{@C[0]-@C[9]} + ldmia @E[0]!,{@C[0]-@C[9]} + stmia @E[1]!,{@C[0]-@C[9]} + ldmia @E[0], {@C[0]-@C[9]} + stmia @E[1], {@C[0]-@C[9]} + + add sp,sp,#440+20 + ldmia sp!,{r4-r11,pc} +.size KeccakF1600,.-KeccakF1600 +___ +{ my ($A_flat,$inp,$len,$bsz) = map("r$_",(10..12,14)); + +######################################################################## +# Stack layout +# ----->+-----------------------+ +# | uint64_t A[5][5] | +# | ... | +# | ... | +# +456->+-----------------------+ +# | 0x55555555 | +# +460->+-----------------------+ +# | 0x33333333 | +# +464->+-----------------------+ +# | 0x0f0f0f0f | +# +468->+-----------------------+ +# | 0x00ff00ff | +# +472->+-----------------------+ +# | uint64_t *A | +# +476->+-----------------------+ +# | const void *inp | +# +480->+-----------------------+ +# | size_t len | +# +484->+-----------------------+ +# | size_t bs | +# +488->+-----------------------+ +# | .... + +$code.=<<___; +.global SHA3_absorb +.type SHA3_absorb,%function +.align 5 +SHA3_absorb: + stmdb sp!,{r0-r12,lr} + sub sp,sp,#456+16 + + add $A_flat,r0,#$A[1][0] + @ mov $inp,r1 + mov $len,r2 + mov $bsz,r3 + cmp r2,r3 + blo .Labsorb_abort + + add $inp,sp,#0 + ldmia r0, {@C[0]-@C[9]} @ copy A[5][5] to stack + stmia $inp!, {@C[0]-@C[9]} + ldmia $A_flat!,{@C[0]-@C[9]} + stmia $inp!, {@C[0]-@C[9]} + ldmia $A_flat!,{@C[0]-@C[9]} + stmia $inp!, {@C[0]-@C[9]} + ldmia $A_flat!,{@C[0]-@C[9]} + stmia $inp!, {@C[0]-@C[9]} + ldmia $A_flat!,{@C[0]-@C[9]} + stmia $inp, {@C[0]-@C[9]} + + ldr $inp,[sp,#476] @ restore $inp +#ifdef __thumb2__ + mov r9,#0x00ff00ff + mov r8,#0x0f0f0f0f + mov r7,#0x33333333 + mov r6,#0x55555555 +#else + mov r6,#0x11 @ compose constants + mov r8,#0x0f + mov r9,#0xff + orr r6,r6,r6,lsl#8 + orr r8,r8,r8,lsl#8 + orr r6,r6,r6,lsl#16 @ 0x11111111 + orr r9,r9,r9,lsl#16 @ 0x00ff00ff + orr r8,r8,r8,lsl#16 @ 0x0f0f0f0f + orr r7,r6,r6,lsl#1 @ 0x33333333 + orr r6,r6,r6,lsl#2 @ 0x55555555 +#endif + str r9,[sp,#468] + str r8,[sp,#464] + str r7,[sp,#460] + str r6,[sp,#456] + b .Loop_absorb + +.align 4 +.Loop_absorb: + subs r0,$len,$bsz + blo .Labsorbed + add $A_flat,sp,#0 + str r0,[sp,#480] @ save len - bsz + +.align 4 +.Loop_block: + ldrb r0,[$inp],#1 + ldrb r1,[$inp],#1 + ldrb r2,[$inp],#1 + ldrb r3,[$inp],#1 + ldrb r4,[$inp],#1 + orr r0,r0,r1,lsl#8 + ldrb r1,[$inp],#1 + orr r0,r0,r2,lsl#16 + ldrb r2,[$inp],#1 + orr r0,r0,r3,lsl#24 @ lo + ldrb r3,[$inp],#1 + orr r1,r4,r1,lsl#8 + orr r1,r1,r2,lsl#16 + orr r1,r1,r3,lsl#24 @ hi + + and r2,r0,r6 @ &=0x55555555 + and r0,r0,r6,lsl#1 @ &=0xaaaaaaaa + and r3,r1,r6 @ &=0x55555555 + and r1,r1,r6,lsl#1 @ &=0xaaaaaaaa + orr r2,r2,r2,lsr#1 + orr r0,r0,r0,lsl#1 + orr r3,r3,r3,lsr#1 + orr r1,r1,r1,lsl#1 + and r2,r2,r7 @ &=0x33333333 + and r0,r0,r7,lsl#2 @ &=0xcccccccc + and r3,r3,r7 @ &=0x33333333 + and r1,r1,r7,lsl#2 @ &=0xcccccccc + orr r2,r2,r2,lsr#2 + orr r0,r0,r0,lsl#2 + orr r3,r3,r3,lsr#2 + orr r1,r1,r1,lsl#2 + and r2,r2,r8 @ &=0x0f0f0f0f + and r0,r0,r8,lsl#4 @ &=0xf0f0f0f0 + and r3,r3,r8 @ &=0x0f0f0f0f + and r1,r1,r8,lsl#4 @ &=0xf0f0f0f0 + ldmia $A_flat,{r4-r5} @ A_flat[i] + orr r2,r2,r2,lsr#4 + orr r0,r0,r0,lsl#4 + orr r3,r3,r3,lsr#4 + orr r1,r1,r1,lsl#4 + and r2,r2,r9 @ &=0x00ff00ff + and r0,r0,r9,lsl#8 @ &=0xff00ff00 + and r3,r3,r9 @ &=0x00ff00ff + and r1,r1,r9,lsl#8 @ &=0xff00ff00 + orr r2,r2,r2,lsr#8 + orr r0,r0,r0,lsl#8 + orr r3,r3,r3,lsr#8 + orr r1,r1,r1,lsl#8 + + lsl r2,r2,#16 + lsr r1,r1,#16 + eor r4,r4,r3,lsl#16 + eor r5,r5,r0,lsr#16 + eor r4,r4,r2,lsr#16 + eor r5,r5,r1,lsl#16 + stmia $A_flat!,{r4-r5} @ A_flat[i++] ^= BitInterleave(inp[0..7]) + + subs $bsz,$bsz,#8 + bhi .Loop_block + + str $inp,[sp,#476] + + bl KeccakF1600_int + + add r14,sp,#456 + ldmia r14,{r6-r12,r14} @ restore constants and variables + b .Loop_absorb + +.align 4 +.Labsorbed: + add $inp,sp,#$A[1][0] + ldmia sp, {@C[0]-@C[9]} + stmia $A_flat!,{@C[0]-@C[9]} @ return A[5][5] + ldmia $inp!, {@C[0]-@C[9]} + stmia $A_flat!,{@C[0]-@C[9]} + ldmia $inp!, {@C[0]-@C[9]} + stmia $A_flat!,{@C[0]-@C[9]} + ldmia $inp!, {@C[0]-@C[9]} + stmia $A_flat!,{@C[0]-@C[9]} + ldmia $inp, {@C[0]-@C[9]} + stmia $A_flat, {@C[0]-@C[9]} + +.Labsorb_abort: + add sp,sp,#456+32 + mov r0,$len @ return value + ldmia sp!,{r4-r12,pc} +.size SHA3_absorb,.-SHA3_absorb +___ +} +{ my ($out,$len,$A_flat,$bsz) = map("r$_", (4,5,10,12)); + +$code.=<<___; +.global SHA3_squeeze +.type SHA3_squeeze,%function +.align 5 +SHA3_squeeze: + stmdb sp!,{r0,r3-r10,lr} + + mov $A_flat,r0 + mov $out,r1 + mov $len,r2 + mov $bsz,r3 + +#ifdef __thumb2__ + mov r9,#0x00ff00ff + mov r8,#0x0f0f0f0f + mov r7,#0x33333333 + mov r6,#0x55555555 +#else + mov r6,#0x11 @ compose constants + mov r8,#0x0f + mov r9,#0xff + orr r6,r6,r6,lsl#8 + orr r8,r8,r8,lsl#8 + orr r6,r6,r6,lsl#16 @ 0x11111111 + orr r9,r9,r9,lsl#16 @ 0x00ff00ff + orr r8,r8,r8,lsl#16 @ 0x0f0f0f0f + orr r7,r6,r6,lsl#1 @ 0x33333333 + orr r6,r6,r6,lsl#2 @ 0x55555555 +#endif + stmdb sp!,{r6-r9} + + mov r14,$A_flat + b .Loop_squeeze + +.align 4 +.Loop_squeeze: + ldmia $A_flat!,{r0,r1} @ A_flat[i++] + + lsl r2,r0,#16 + lsl r3,r1,#16 @ r3 = r1 << 16 + lsr r2,r2,#16 @ r2 = r0 & 0x0000ffff + lsr r1,r1,#16 + lsr r0,r0,#16 @ r0 = r0 >> 16 + lsl r1,r1,#16 @ r1 = r1 & 0xffff0000 + + orr r2,r2,r2,lsl#8 + orr r3,r3,r3,lsr#8 + orr r0,r0,r0,lsl#8 + orr r1,r1,r1,lsr#8 + and r2,r2,r9 @ &=0x00ff00ff + and r3,r3,r9,lsl#8 @ &=0xff00ff00 + and r0,r0,r9 @ &=0x00ff00ff + and r1,r1,r9,lsl#8 @ &=0xff00ff00 + orr r2,r2,r2,lsl#4 + orr r3,r3,r3,lsr#4 + orr r0,r0,r0,lsl#4 + orr r1,r1,r1,lsr#4 + and r2,r2,r8 @ &=0x0f0f0f0f + and r3,r3,r8,lsl#4 @ &=0xf0f0f0f0 + and r0,r0,r8 @ &=0x0f0f0f0f + and r1,r1,r8,lsl#4 @ &=0xf0f0f0f0 + orr r2,r2,r2,lsl#2 + orr r3,r3,r3,lsr#2 + orr r0,r0,r0,lsl#2 + orr r1,r1,r1,lsr#2 + and r2,r2,r7 @ &=0x33333333 + and r3,r3,r7,lsl#2 @ &=0xcccccccc + and r0,r0,r7 @ &=0x33333333 + and r1,r1,r7,lsl#2 @ &=0xcccccccc + orr r2,r2,r2,lsl#1 + orr r3,r3,r3,lsr#1 + orr r0,r0,r0,lsl#1 + orr r1,r1,r1,lsr#1 + and r2,r2,r6 @ &=0x55555555 + and r3,r3,r6,lsl#1 @ &=0xaaaaaaaa + and r0,r0,r6 @ &=0x55555555 + and r1,r1,r6,lsl#1 @ &=0xaaaaaaaa + + orr r2,r2,r3 + orr r0,r0,r1 + + cmp $len,#8 + blo .Lsqueeze_tail + lsr r1,r2,#8 + strb r2,[$out],#1 + lsr r3,r2,#16 + strb r1,[$out],#1 + lsr r2,r2,#24 + strb r3,[$out],#1 + strb r2,[$out],#1 + + lsr r1,r0,#8 + strb r0,[$out],#1 + lsr r3,r0,#16 + strb r1,[$out],#1 + lsr r0,r0,#24 + strb r3,[$out],#1 + strb r0,[$out],#1 + subs $len,$len,#8 + beq .Lsqueeze_done + + subs $bsz,$bsz,#8 @ bsz -= 8 + bhi .Loop_squeeze + + mov r0,r14 @ original $A_flat + + bl KeccakF1600 + + ldmia sp,{r6-r10,r12} @ restore constants and variables + mov r14,$A_flat + b .Loop_squeeze + +.align 4 +.Lsqueeze_tail: + strb r2,[$out],#1 + lsr r2,r2,#8 + subs $len,$len,#1 + beq .Lsqueeze_done + strb r2,[$out],#1 + lsr r2,r2,#8 + subs $len,$len,#1 + beq .Lsqueeze_done + strb r2,[$out],#1 + lsr r2,r2,#8 + subs $len,$len,#1 + beq .Lsqueeze_done + strb r2,[$out],#1 + subs $len,$len,#1 + beq .Lsqueeze_done + + strb r0,[$out],#1 + lsr r0,r0,#8 + subs $len,$len,#1 + beq .Lsqueeze_done + strb r0,[$out],#1 + lsr r0,r0,#8 + subs $len,$len,#1 + beq .Lsqueeze_done + strb r0,[$out] + b .Lsqueeze_done + +.align 4 +.Lsqueeze_done: + add sp,sp,#24 + ldmia sp!,{r4-r10,pc} +.size SHA3_squeeze,.-SHA3_squeeze +___ +} + +$code.=<<___; +#if __ARM_MAX_ARCH__>=7 +.fpu neon + +.type iotas64, %object +.align 5 +iotas64: + .quad 0x0000000000000001 + .quad 0x0000000000008082 + .quad 0x800000000000808a + .quad 0x8000000080008000 + .quad 0x000000000000808b + .quad 0x0000000080000001 + .quad 0x8000000080008081 + .quad 0x8000000000008009 + .quad 0x000000000000008a + .quad 0x0000000000000088 + .quad 0x0000000080008009 + .quad 0x000000008000000a + .quad 0x000000008000808b + .quad 0x800000000000008b + .quad 0x8000000000008089 + .quad 0x8000000000008003 + .quad 0x8000000000008002 + .quad 0x8000000000000080 + .quad 0x000000000000800a + .quad 0x800000008000000a + .quad 0x8000000080008081 + .quad 0x8000000000008080 + .quad 0x0000000080000001 + .quad 0x8000000080008008 +.size iotas64,.-iotas64 + +.type KeccakF1600_neon, %function +.align 5 +KeccakF1600_neon: + add r1, r0, #16 + adr r2, iotas64 + mov r3, #24 @ loop counter + b .Loop_neon + +.align 4 +.Loop_neon: + @ Theta + vst1.64 {q4}, [r0:64] @ offload A[0..1][4] + veor q13, q0, q5 @ A[0..1][0]^A[2..3][0] + vst1.64 {d18}, [r1:64] @ offload A[2][4] + veor q14, q1, q6 @ A[0..1][1]^A[2..3][1] + veor q15, q2, q7 @ A[0..1][2]^A[2..3][2] + veor d26, d26, d27 @ C[0]=A[0][0]^A[1][0]^A[2][0]^A[3][0] + veor d27, d28, d29 @ C[1]=A[0][1]^A[1][1]^A[2][1]^A[3][1] + veor q14, q3, q8 @ A[0..1][3]^A[2..3][3] + veor q4, q4, q9 @ A[0..1][4]^A[2..3][4] + veor d30, d30, d31 @ C[2]=A[0][2]^A[1][2]^A[2][2]^A[3][2] + veor d31, d28, d29 @ C[3]=A[0][3]^A[1][3]^A[2][3]^A[3][3] + veor d25, d8, d9 @ C[4]=A[0][4]^A[1][4]^A[2][4]^A[3][4] + veor q13, q13, q10 @ C[0..1]^=A[4][0..1] + veor q14, q15, q11 @ C[2..3]^=A[4][2..3] + veor d25, d25, d24 @ C[4]^=A[4][4] + + vadd.u64 q4, q13, q13 @ C[0..1]<<1 + vadd.u64 q15, q14, q14 @ C[2..3]<<1 + vadd.u64 d18, d25, d25 @ C[4]<<1 + vsri.u64 q4, q13, #63 @ ROL64(C[0..1],1) + vsri.u64 q15, q14, #63 @ ROL64(C[2..3],1) + vsri.u64 d18, d25, #63 @ ROL64(C[4],1) + veor d25, d25, d9 @ D[0] = C[4] ^= ROL64(C[1],1) + veor q13, q13, q15 @ D[1..2] = C[0..1] ^ ROL64(C[2..3],1) + veor d28, d28, d18 @ D[3] = C[2] ^= ROL64(C[4],1) + veor d29, d29, d8 @ D[4] = C[3] ^= ROL64(C[0],1) + + veor d0, d0, d25 @ A[0][0] ^= C[4] + veor d1, d1, d25 @ A[1][0] ^= C[4] + veor d10, d10, d25 @ A[2][0] ^= C[4] + veor d11, d11, d25 @ A[3][0] ^= C[4] + veor d20, d20, d25 @ A[4][0] ^= C[4] + + veor d2, d2, d26 @ A[0][1] ^= D[1] + veor d3, d3, d26 @ A[1][1] ^= D[1] + veor d12, d12, d26 @ A[2][1] ^= D[1] + veor d13, d13, d26 @ A[3][1] ^= D[1] + veor d21, d21, d26 @ A[4][1] ^= D[1] + vmov d26, d27 + + veor d6, d6, d28 @ A[0][3] ^= C[2] + veor d7, d7, d28 @ A[1][3] ^= C[2] + veor d16, d16, d28 @ A[2][3] ^= C[2] + veor d17, d17, d28 @ A[3][3] ^= C[2] + veor d23, d23, d28 @ A[4][3] ^= C[2] + vld1.64 {q4}, [r0:64] @ restore A[0..1][4] + vmov d28, d29 + + vld1.64 {d18}, [r1:64] @ restore A[2][4] + veor q2, q2, q13 @ A[0..1][2] ^= D[2] + veor q7, q7, q13 @ A[2..3][2] ^= D[2] + veor d22, d22, d27 @ A[4][2] ^= D[2] + + veor q4, q4, q14 @ A[0..1][4] ^= C[3] + veor q9, q9, q14 @ A[2..3][4] ^= C[3] + veor d24, d24, d29 @ A[4][4] ^= C[3] + + @ Rho + Pi + vmov d26, d2 @ C[1] = A[0][1] + vshl.u64 d2, d3, #44 + vmov d27, d4 @ C[2] = A[0][2] + vshl.u64 d4, d14, #43 + vmov d28, d6 @ C[3] = A[0][3] + vshl.u64 d6, d17, #21 + vmov d29, d8 @ C[4] = A[0][4] + vshl.u64 d8, d24, #14 + vsri.u64 d2, d3, #64-44 @ A[0][1] = ROL64(A[1][1], rhotates[1][1]) + vsri.u64 d4, d14, #64-43 @ A[0][2] = ROL64(A[2][2], rhotates[2][2]) + vsri.u64 d6, d17, #64-21 @ A[0][3] = ROL64(A[3][3], rhotates[3][3]) + vsri.u64 d8, d24, #64-14 @ A[0][4] = ROL64(A[4][4], rhotates[4][4]) + + vshl.u64 d3, d9, #20 + vshl.u64 d14, d16, #25 + vshl.u64 d17, d15, #15 + vshl.u64 d24, d21, #2 + vsri.u64 d3, d9, #64-20 @ A[1][1] = ROL64(A[1][4], rhotates[1][4]) + vsri.u64 d14, d16, #64-25 @ A[2][2] = ROL64(A[2][3], rhotates[2][3]) + vsri.u64 d17, d15, #64-15 @ A[3][3] = ROL64(A[3][2], rhotates[3][2]) + vsri.u64 d24, d21, #64-2 @ A[4][4] = ROL64(A[4][1], rhotates[4][1]) + + vshl.u64 d9, d22, #61 + @ vshl.u64 d16, d19, #8 + vshl.u64 d15, d12, #10 + vshl.u64 d21, d7, #55 + vsri.u64 d9, d22, #64-61 @ A[1][4] = ROL64(A[4][2], rhotates[4][2]) + vext.8 d16, d19, d19, #8-1 @ A[2][3] = ROL64(A[3][4], rhotates[3][4]) + vsri.u64 d15, d12, #64-10 @ A[3][2] = ROL64(A[2][1], rhotates[2][1]) + vsri.u64 d21, d7, #64-55 @ A[4][1] = ROL64(A[1][3], rhotates[1][3]) + + vshl.u64 d22, d18, #39 + @ vshl.u64 d19, d23, #56 + vshl.u64 d12, d5, #6 + vshl.u64 d7, d13, #45 + vsri.u64 d22, d18, #64-39 @ A[4][2] = ROL64(A[2][4], rhotates[2][4]) + vext.8 d19, d23, d23, #8-7 @ A[3][4] = ROL64(A[4][3], rhotates[4][3]) + vsri.u64 d12, d5, #64-6 @ A[2][1] = ROL64(A[1][2], rhotates[1][2]) + vsri.u64 d7, d13, #64-45 @ A[1][3] = ROL64(A[3][1], rhotates[3][1]) + + vshl.u64 d18, d20, #18 + vshl.u64 d23, d11, #41 + vshl.u64 d5, d10, #3 + vshl.u64 d13, d1, #36 + vsri.u64 d18, d20, #64-18 @ A[2][4] = ROL64(A[4][0], rhotates[4][0]) + vsri.u64 d23, d11, #64-41 @ A[4][3] = ROL64(A[3][0], rhotates[3][0]) + vsri.u64 d5, d10, #64-3 @ A[1][2] = ROL64(A[2][0], rhotates[2][0]) + vsri.u64 d13, d1, #64-36 @ A[3][1] = ROL64(A[1][0], rhotates[1][0]) + + vshl.u64 d1, d28, #28 + vshl.u64 d10, d26, #1 + vshl.u64 d11, d29, #27 + vshl.u64 d20, d27, #62 + vsri.u64 d1, d28, #64-28 @ A[1][0] = ROL64(C[3], rhotates[0][3]) + vsri.u64 d10, d26, #64-1 @ A[2][0] = ROL64(C[1], rhotates[0][1]) + vsri.u64 d11, d29, #64-27 @ A[3][0] = ROL64(C[4], rhotates[0][4]) + vsri.u64 d20, d27, #64-62 @ A[4][0] = ROL64(C[2], rhotates[0][2]) + + @ Chi + Iota + vbic q13, q2, q1 + vbic q14, q3, q2 + vbic q15, q4, q3 + veor q13, q13, q0 @ A[0..1][0] ^ (~A[0..1][1] & A[0..1][2]) + veor q14, q14, q1 @ A[0..1][1] ^ (~A[0..1][2] & A[0..1][3]) + veor q2, q2, q15 @ A[0..1][2] ^= (~A[0..1][3] & A[0..1][4]) + vst1.64 {q13}, [r0:64] @ offload A[0..1][0] + vbic q13, q0, q4 + vbic q15, q1, q0 + vmov q1, q14 @ A[0..1][1] + veor q3, q3, q13 @ A[0..1][3] ^= (~A[0..1][4] & A[0..1][0]) + veor q4, q4, q15 @ A[0..1][4] ^= (~A[0..1][0] & A[0..1][1]) + + vbic q13, q7, q6 + vmov q0, q5 @ A[2..3][0] + vbic q14, q8, q7 + vmov q15, q6 @ A[2..3][1] + veor q5, q5, q13 @ A[2..3][0] ^= (~A[2..3][1] & A[2..3][2]) + vbic q13, q9, q8 + veor q6, q6, q14 @ A[2..3][1] ^= (~A[2..3][2] & A[2..3][3]) + vbic q14, q0, q9 + veor q7, q7, q13 @ A[2..3][2] ^= (~A[2..3][3] & A[2..3][4]) + vbic q13, q15, q0 + veor q8, q8, q14 @ A[2..3][3] ^= (~A[2..3][4] & A[2..3][0]) + vmov q14, q10 @ A[4][0..1] + veor q9, q9, q13 @ A[2..3][4] ^= (~A[2..3][0] & A[2..3][1]) + + vld1.64 d25, [r2:64]! @ Iota[i++] + vbic d26, d22, d21 + vbic d27, d23, d22 + vld1.64 {q0}, [r0:64] @ restore A[0..1][0] + veor d20, d20, d26 @ A[4][0] ^= (~A[4][1] & A[4][2]) + vbic d26, d24, d23 + veor d21, d21, d27 @ A[4][1] ^= (~A[4][2] & A[4][3]) + vbic d27, d28, d24 + veor d22, d22, d26 @ A[4][2] ^= (~A[4][3] & A[4][4]) + vbic d26, d29, d28 + veor d23, d23, d27 @ A[4][3] ^= (~A[4][4] & A[4][0]) + veor d0, d0, d25 @ A[0][0] ^= Iota[i] + veor d24, d24, d26 @ A[4][4] ^= (~A[4][0] & A[4][1]) + + subs r3, r3, #1 + bne .Loop_neon + + bx lr +.size KeccakF1600_neon,.-KeccakF1600_neon + +.global SHA3_absorb_neon +.type SHA3_absorb_neon, %function +.align 5 +SHA3_absorb_neon: + stmdb sp!, {r4-r6,lr} + vstmdb sp!, {d8-d15} + + mov r4, r1 @ inp + mov r5, r2 @ len + mov r6, r3 @ bsz + + vld1.32 {d0}, [r0:64]! @ A[0][0] + vld1.32 {d2}, [r0:64]! @ A[0][1] + vld1.32 {d4}, [r0:64]! @ A[0][2] + vld1.32 {d6}, [r0:64]! @ A[0][3] + vld1.32 {d8}, [r0:64]! @ A[0][4] + + vld1.32 {d1}, [r0:64]! @ A[1][0] + vld1.32 {d3}, [r0:64]! @ A[1][1] + vld1.32 {d5}, [r0:64]! @ A[1][2] + vld1.32 {d7}, [r0:64]! @ A[1][3] + vld1.32 {d9}, [r0:64]! @ A[1][4] + + vld1.32 {d10}, [r0:64]! @ A[2][0] + vld1.32 {d12}, [r0:64]! @ A[2][1] + vld1.32 {d14}, [r0:64]! @ A[2][2] + vld1.32 {d16}, [r0:64]! @ A[2][3] + vld1.32 {d18}, [r0:64]! @ A[2][4] + + vld1.32 {d11}, [r0:64]! @ A[3][0] + vld1.32 {d13}, [r0:64]! @ A[3][1] + vld1.32 {d15}, [r0:64]! @ A[3][2] + vld1.32 {d17}, [r0:64]! @ A[3][3] + vld1.32 {d19}, [r0:64]! @ A[3][4] + + vld1.32 {d20-d23}, [r0:64]! @ A[4][0..3] + vld1.32 {d24}, [r0:64] @ A[4][4] + sub r0, r0, #24*8 @ rewind + b .Loop_absorb_neon + +.align 4 +.Loop_absorb_neon: + subs r12, r5, r6 @ len - bsz + blo .Labsorbed_neon + mov r5, r12 + + vld1.8 {d31}, [r4]! @ endian-neutral loads... + cmp r6, #8*2 + veor d0, d0, d31 @ A[0][0] ^= *inp++ + blo .Lprocess_neon + vld1.8 {d31}, [r4]! + veor d2, d2, d31 @ A[0][1] ^= *inp++ + beq .Lprocess_neon + vld1.8 {d31}, [r4]! + cmp r6, #8*4 + veor d4, d4, d31 @ A[0][2] ^= *inp++ + blo .Lprocess_neon + vld1.8 {d31}, [r4]! + veor d6, d6, d31 @ A[0][3] ^= *inp++ + beq .Lprocess_neon + vld1.8 {d31},[r4]! + cmp r6, #8*6 + veor d8, d8, d31 @ A[0][4] ^= *inp++ + blo .Lprocess_neon + + vld1.8 {d31}, [r4]! + veor d1, d1, d31 @ A[1][0] ^= *inp++ + beq .Lprocess_neon + vld1.8 {d31}, [r4]! + cmp r6, #8*8 + veor d3, d3, d31 @ A[1][1] ^= *inp++ + blo .Lprocess_neon + vld1.8 {d31}, [r4]! + veor d5, d5, d31 @ A[1][2] ^= *inp++ + beq .Lprocess_neon + vld1.8 {d31}, [r4]! + cmp r6, #8*10 + veor d7, d7, d31 @ A[1][3] ^= *inp++ + blo .Lprocess_neon + vld1.8 {d31}, [r4]! + veor d9, d9, d31 @ A[1][4] ^= *inp++ + beq .Lprocess_neon + + vld1.8 {d31}, [r4]! + cmp r6, #8*12 + veor d10, d10, d31 @ A[2][0] ^= *inp++ + blo .Lprocess_neon + vld1.8 {d31}, [r4]! + veor d12, d12, d31 @ A[2][1] ^= *inp++ + beq .Lprocess_neon + vld1.8 {d31}, [r4]! + cmp r6, #8*14 + veor d14, d14, d31 @ A[2][2] ^= *inp++ + blo .Lprocess_neon + vld1.8 {d31}, [r4]! + veor d16, d16, d31 @ A[2][3] ^= *inp++ + beq .Lprocess_neon + vld1.8 {d31}, [r4]! + cmp r6, #8*16 + veor d18, d18, d31 @ A[2][4] ^= *inp++ + blo .Lprocess_neon + + vld1.8 {d31}, [r4]! + veor d11, d11, d31 @ A[3][0] ^= *inp++ + beq .Lprocess_neon + vld1.8 {d31}, [r4]! + cmp r6, #8*18 + veor d13, d13, d31 @ A[3][1] ^= *inp++ + blo .Lprocess_neon + vld1.8 {d31}, [r4]! + veor d15, d15, d31 @ A[3][2] ^= *inp++ + beq .Lprocess_neon + vld1.8 {d31}, [r4]! + cmp r6, #8*20 + veor d17, d17, d31 @ A[3][3] ^= *inp++ + blo .Lprocess_neon + vld1.8 {d31}, [r4]! + veor d19, d19, d31 @ A[3][4] ^= *inp++ + beq .Lprocess_neon + + vld1.8 {d31}, [r4]! + cmp r6, #8*22 + veor d20, d20, d31 @ A[4][0] ^= *inp++ + blo .Lprocess_neon + vld1.8 {d31}, [r4]! + veor d21, d21, d31 @ A[4][1] ^= *inp++ + beq .Lprocess_neon + vld1.8 {d31}, [r4]! + cmp r6, #8*24 + veor d22, d22, d31 @ A[4][2] ^= *inp++ + blo .Lprocess_neon + vld1.8 {d31}, [r4]! + veor d23, d23, d31 @ A[4][3] ^= *inp++ + beq .Lprocess_neon + vld1.8 {d31}, [r4]! + veor d24, d24, d31 @ A[4][4] ^= *inp++ + +.Lprocess_neon: + bl KeccakF1600_neon + b .Loop_absorb_neon + +.align 4 +.Labsorbed_neon: + vst1.32 {d0}, [r0:64]! @ A[0][0..4] + vst1.32 {d2}, [r0:64]! + vst1.32 {d4}, [r0:64]! + vst1.32 {d6}, [r0:64]! + vst1.32 {d8}, [r0:64]! + + vst1.32 {d1}, [r0:64]! @ A[1][0..4] + vst1.32 {d3}, [r0:64]! + vst1.32 {d5}, [r0:64]! + vst1.32 {d7}, [r0:64]! + vst1.32 {d9}, [r0:64]! + + vst1.32 {d10}, [r0:64]! @ A[2][0..4] + vst1.32 {d12}, [r0:64]! + vst1.32 {d14}, [r0:64]! + vst1.32 {d16}, [r0:64]! + vst1.32 {d18}, [r0:64]! + + vst1.32 {d11}, [r0:64]! @ A[3][0..4] + vst1.32 {d13}, [r0:64]! + vst1.32 {d15}, [r0:64]! + vst1.32 {d17}, [r0:64]! + vst1.32 {d19}, [r0:64]! + + vst1.32 {d20-d23}, [r0:64]! @ A[4][0..4] + vst1.32 {d24}, [r0:64] + + mov r0, r5 @ return value + vldmia sp!, {d8-d15} + ldmia sp!, {r4-r6,pc} +.size SHA3_absorb_neon,.-SHA3_absorb_neon + +.global SHA3_squeeze_neon +.type SHA3_squeeze_neon, %function +.align 5 +SHA3_squeeze_neon: + stmdb sp!, {r4-r6,lr} + + mov r4, r1 @ out + mov r5, r2 @ len + mov r6, r3 @ bsz + mov r12, r0 @ A_flat + mov r14, r3 @ bsz + b .Loop_squeeze_neon + +.align 4 +.Loop_squeeze_neon: + cmp r5, #8 + blo .Lsqueeze_neon_tail + vld1.32 {d0}, [r12]! + vst1.8 {d0}, [r4]! @ endian-neutral store + + subs r5, r5, #8 @ len -= 8 + beq .Lsqueeze_neon_done + + subs r14, r14, #8 @ bsz -= 8 + bhi .Loop_squeeze_neon + + vstmdb sp!, {d8-d15} + + vld1.32 {d0}, [r0:64]! @ A[0][0..4] + vld1.32 {d2}, [r0:64]! + vld1.32 {d4}, [r0:64]! + vld1.32 {d6}, [r0:64]! + vld1.32 {d8}, [r0:64]! + + vld1.32 {d1}, [r0:64]! @ A[1][0..4] + vld1.32 {d3}, [r0:64]! + vld1.32 {d5}, [r0:64]! + vld1.32 {d7}, [r0:64]! + vld1.32 {d9}, [r0:64]! + + vld1.32 {d10}, [r0:64]! @ A[2][0..4] + vld1.32 {d12}, [r0:64]! + vld1.32 {d14}, [r0:64]! + vld1.32 {d16}, [r0:64]! + vld1.32 {d18}, [r0:64]! + + vld1.32 {d11}, [r0:64]! @ A[3][0..4] + vld1.32 {d13}, [r0:64]! + vld1.32 {d15}, [r0:64]! + vld1.32 {d17}, [r0:64]! + vld1.32 {d19}, [r0:64]! + + vld1.32 {d20-d23}, [r0:64]! @ A[4][0..4] + vld1.32 {d24}, [r0:64] + sub r0, r0, #24*8 @ rewind + + bl KeccakF1600_neon + + mov r12, r0 @ A_flat + vst1.32 {d0}, [r0:64]! @ A[0][0..4] + vst1.32 {d2}, [r0:64]! + vst1.32 {d4}, [r0:64]! + vst1.32 {d6}, [r0:64]! + vst1.32 {d8}, [r0:64]! + + vst1.32 {d1}, [r0:64]! @ A[1][0..4] + vst1.32 {d3}, [r0:64]! + vst1.32 {d5}, [r0:64]! + vst1.32 {d7}, [r0:64]! + vst1.32 {d9}, [r0:64]! + + vst1.32 {d10}, [r0:64]! @ A[2][0..4] + vst1.32 {d12}, [r0:64]! + vst1.32 {d14}, [r0:64]! + vst1.32 {d16}, [r0:64]! + vst1.32 {d18}, [r0:64]! + + vst1.32 {d11}, [r0:64]! @ A[3][0..4] + vst1.32 {d13}, [r0:64]! + vst1.32 {d15}, [r0:64]! + vst1.32 {d17}, [r0:64]! + vst1.32 {d19}, [r0:64]! + + vst1.32 {d20-d23}, [r0:64]! @ A[4][0..4] + mov r14, r6 @ bsz + vst1.32 {d24}, [r0:64] + mov r0, r12 @ rewind + + vldmia sp!, {d8-d15} + b .Loop_squeeze_neon + +.align 4 +.Lsqueeze_neon_tail: + ldmia r12, {r2,r3} + cmp r5, #2 + strb r2, [r4],#1 @ endian-neutral store + lsr r2, r2, #8 + blo .Lsqueeze_neon_done + strb r2, [r4], #1 + lsr r2, r2, #8 + beq .Lsqueeze_neon_done + strb r2, [r4], #1 + lsr r2, r2, #8 + cmp r5, #4 + blo .Lsqueeze_neon_done + strb r2, [r4], #1 + beq .Lsqueeze_neon_done + + strb r3, [r4], #1 + lsr r3, r3, #8 + cmp r5, #6 + blo .Lsqueeze_neon_done + strb r3, [r4], #1 + lsr r3, r3, #8 + beq .Lsqueeze_neon_done + strb r3, [r4], #1 + +.Lsqueeze_neon_done: + ldmia sp!, {r4-r6,pc} +.size SHA3_squeeze_neon,.-SHA3_squeeze_neon +#endif +.asciz "Keccak-1600 absorb and squeeze for ARMv4/NEON, CRYPTOGAMS by " +.align 2 +___ + +{ + my %ldr, %str; + + sub ldrd { + my ($mnemonic,$half,$reg,$ea) = @_; + my $op = $mnemonic eq "ldr" ? \%ldr : \%str; + + if ($half eq "l") { + $$op{reg} = $reg; + $$op{ea} = $ea; + sprintf "#ifndef __thumb2__\n" . + " %s\t%s,%s\n" . + "#endif", $mnemonic,$reg,$ea; + } else { + sprintf "#ifndef __thumb2__\n" . + " %s\t%s,%s\n" . + "#else\n" . + " %sd\t%s,%s,%s\n" . + "#endif", $mnemonic,$reg,$ea, + $mnemonic,$$op{reg},$reg,$$op{ea}; + } + } +} + +foreach (split($/,$code)) { + s/\`([^\`]*)\`/eval $1/ge; + + s/^\s+(ldr|str)\.([lh])\s+(r[0-9]+),\s*(\[.*)/ldrd($1,$2,$3,$4)/ge or + s/\b(ror|ls[rl])\s+(r[0-9]+.*)#/mov $2$1#/g or + s/\bret\b/bx lr/g or + s/\bbx\s+lr\b/.word\t0xe12fff1e/g; # make it possible to compile with -march=armv4 + + print $_,"\n"; +} + +close STDOUT; # enforce flush diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-armv8.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-armv8.pl new file mode 100755 index 000000000..a3117bd75 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-armv8.pl @@ -0,0 +1,880 @@ +#!/usr/bin/env perl +# Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# Keccak-1600 for ARMv8. +# +# June 2017. +# +# This is straightforward KECCAK_1X_ALT implementation. It makes no +# sense to attempt SIMD/NEON implementation for following reason. +# 64-bit lanes of vector registers can't be addressed as easily as in +# 32-bit mode. This means that 64-bit NEON is bound to be slower than +# 32-bit NEON, and this implementation is faster than 32-bit NEON on +# same processor. Even though it takes more scalar xor's and andn's, +# it gets compensated by availability of rotate. Not to forget that +# most processors achieve higher issue rate with scalar instructions. +# +# February 2018. +# +# Add hardware-assisted ARMv8.2 implementation. It's KECCAK_1X_ALT +# variant with register permutation/rotation twist that allows to +# eliminate copies to temporary registers. If you look closely you'll +# notice that it uses only one lane of vector registers. The new +# instructions effectively facilitate parallel hashing, which we don't +# support [yet?]. But lowest-level core procedure is prepared for it. +# The inner round is 67 [vector] instructions, so it's not actually +# obvious that it will provide performance improvement [in serial +# hash] as long as vector instructions issue rate is limited to 1 per +# cycle... +# +###################################################################### +# Numbers are cycles per processed byte. +# +# r=1088(*) +# +# Cortex-A53 13 +# Cortex-A57 12 +# X-Gene 14 +# Mongoose 10 +# Kryo 12 +# Denver 7.8 +# Apple A7 7.2 +# +# (*) Corresponds to SHA3-256. No improvement coefficients are listed +# because they vary too much from compiler to compiler. Newer +# compiler does much better and improvement varies from 5% on +# Cortex-A57 to 25% on Cortex-A53. While in comparison to older +# compiler this code is at least 2x faster... + +$flavour = shift; +$output = shift; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or +die "can't locate arm-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +my @rhotates = ([ 0, 1, 62, 28, 27 ], + [ 36, 44, 6, 55, 20 ], + [ 3, 10, 43, 25, 39 ], + [ 41, 45, 15, 21, 8 ], + [ 18, 2, 61, 56, 14 ]); + +$code.=<<___; +.text + +.align 8 // strategic alignment and padding that allows to use + // address value as loop termination condition... + .quad 0,0,0,0,0,0,0,0 +.type iotas,%object +iotas: + .quad 0x0000000000000001 + .quad 0x0000000000008082 + .quad 0x800000000000808a + .quad 0x8000000080008000 + .quad 0x000000000000808b + .quad 0x0000000080000001 + .quad 0x8000000080008081 + .quad 0x8000000000008009 + .quad 0x000000000000008a + .quad 0x0000000000000088 + .quad 0x0000000080008009 + .quad 0x000000008000000a + .quad 0x000000008000808b + .quad 0x800000000000008b + .quad 0x8000000000008089 + .quad 0x8000000000008003 + .quad 0x8000000000008002 + .quad 0x8000000000000080 + .quad 0x000000000000800a + .quad 0x800000008000000a + .quad 0x8000000080008081 + .quad 0x8000000000008080 + .quad 0x0000000080000001 + .quad 0x8000000080008008 +.size iotas,.-iotas +___ + {{{ +my @A = map([ "x$_", "x".($_+1), "x".($_+2), "x".($_+3), "x".($_+4) ], + (0, 5, 10, 15, 20)); + $A[3][3] = "x25"; # x18 is reserved + +my @C = map("x$_", (26,27,28,30)); + +$code.=<<___; +.type KeccakF1600_int,%function +.align 5 +KeccakF1600_int: + adr $C[2],iotas + .inst 0xd503233f // paciasp + stp $C[2],x30,[sp,#16] // 32 bytes on top are mine + b .Loop +.align 4 +.Loop: + ////////////////////////////////////////// Theta + eor $C[0],$A[0][0],$A[1][0] + stp $A[0][4],$A[1][4],[sp,#0] // offload pair... + eor $C[1],$A[0][1],$A[1][1] + eor $C[2],$A[0][2],$A[1][2] + eor $C[3],$A[0][3],$A[1][3] +___ + $C[4]=$A[0][4]; + $C[5]=$A[1][4]; +$code.=<<___; + eor $C[4],$A[0][4],$A[1][4] + eor $C[0],$C[0],$A[2][0] + eor $C[1],$C[1],$A[2][1] + eor $C[2],$C[2],$A[2][2] + eor $C[3],$C[3],$A[2][3] + eor $C[4],$C[4],$A[2][4] + eor $C[0],$C[0],$A[3][0] + eor $C[1],$C[1],$A[3][1] + eor $C[2],$C[2],$A[3][2] + eor $C[3],$C[3],$A[3][3] + eor $C[4],$C[4],$A[3][4] + eor $C[0],$C[0],$A[4][0] + eor $C[2],$C[2],$A[4][2] + eor $C[1],$C[1],$A[4][1] + eor $C[3],$C[3],$A[4][3] + eor $C[4],$C[4],$A[4][4] + + eor $C[5],$C[0],$C[2],ror#63 + + eor $A[0][1],$A[0][1],$C[5] + eor $A[1][1],$A[1][1],$C[5] + eor $A[2][1],$A[2][1],$C[5] + eor $A[3][1],$A[3][1],$C[5] + eor $A[4][1],$A[4][1],$C[5] + + eor $C[5],$C[1],$C[3],ror#63 + eor $C[2],$C[2],$C[4],ror#63 + eor $C[3],$C[3],$C[0],ror#63 + eor $C[4],$C[4],$C[1],ror#63 + + eor $C[1], $A[0][2],$C[5] // mov $C[1],$A[0][2] + eor $A[1][2],$A[1][2],$C[5] + eor $A[2][2],$A[2][2],$C[5] + eor $A[3][2],$A[3][2],$C[5] + eor $A[4][2],$A[4][2],$C[5] + + eor $A[0][0],$A[0][0],$C[4] + eor $A[1][0],$A[1][0],$C[4] + eor $A[2][0],$A[2][0],$C[4] + eor $A[3][0],$A[3][0],$C[4] + eor $A[4][0],$A[4][0],$C[4] +___ + $C[4]=undef; + $C[5]=undef; +$code.=<<___; + ldp $A[0][4],$A[1][4],[sp,#0] // re-load offloaded data + eor $C[0], $A[0][3],$C[2] // mov $C[0],$A[0][3] + eor $A[1][3],$A[1][3],$C[2] + eor $A[2][3],$A[2][3],$C[2] + eor $A[3][3],$A[3][3],$C[2] + eor $A[4][3],$A[4][3],$C[2] + + eor $C[2], $A[0][4],$C[3] // mov $C[2],$A[0][4] + eor $A[1][4],$A[1][4],$C[3] + eor $A[2][4],$A[2][4],$C[3] + eor $A[3][4],$A[3][4],$C[3] + eor $A[4][4],$A[4][4],$C[3] + + ////////////////////////////////////////// Rho+Pi + mov $C[3],$A[0][1] + ror $A[0][1],$A[1][1],#64-$rhotates[1][1] + //mov $C[1],$A[0][2] + ror $A[0][2],$A[2][2],#64-$rhotates[2][2] + //mov $C[0],$A[0][3] + ror $A[0][3],$A[3][3],#64-$rhotates[3][3] + //mov $C[2],$A[0][4] + ror $A[0][4],$A[4][4],#64-$rhotates[4][4] + + ror $A[1][1],$A[1][4],#64-$rhotates[1][4] + ror $A[2][2],$A[2][3],#64-$rhotates[2][3] + ror $A[3][3],$A[3][2],#64-$rhotates[3][2] + ror $A[4][4],$A[4][1],#64-$rhotates[4][1] + + ror $A[1][4],$A[4][2],#64-$rhotates[4][2] + ror $A[2][3],$A[3][4],#64-$rhotates[3][4] + ror $A[3][2],$A[2][1],#64-$rhotates[2][1] + ror $A[4][1],$A[1][3],#64-$rhotates[1][3] + + ror $A[4][2],$A[2][4],#64-$rhotates[2][4] + ror $A[3][4],$A[4][3],#64-$rhotates[4][3] + ror $A[2][1],$A[1][2],#64-$rhotates[1][2] + ror $A[1][3],$A[3][1],#64-$rhotates[3][1] + + ror $A[2][4],$A[4][0],#64-$rhotates[4][0] + ror $A[4][3],$A[3][0],#64-$rhotates[3][0] + ror $A[1][2],$A[2][0],#64-$rhotates[2][0] + ror $A[3][1],$A[1][0],#64-$rhotates[1][0] + + ror $A[1][0],$C[0],#64-$rhotates[0][3] + ror $A[2][0],$C[3],#64-$rhotates[0][1] + ror $A[3][0],$C[2],#64-$rhotates[0][4] + ror $A[4][0],$C[1],#64-$rhotates[0][2] + + ////////////////////////////////////////// Chi+Iota + bic $C[0],$A[0][2],$A[0][1] + bic $C[1],$A[0][3],$A[0][2] + bic $C[2],$A[0][0],$A[0][4] + bic $C[3],$A[0][1],$A[0][0] + eor $A[0][0],$A[0][0],$C[0] + bic $C[0],$A[0][4],$A[0][3] + eor $A[0][1],$A[0][1],$C[1] + ldr $C[1],[sp,#16] + eor $A[0][3],$A[0][3],$C[2] + eor $A[0][4],$A[0][4],$C[3] + eor $A[0][2],$A[0][2],$C[0] + ldr $C[3],[$C[1]],#8 // Iota[i++] + + bic $C[0],$A[1][2],$A[1][1] + tst $C[1],#255 // are we done? + str $C[1],[sp,#16] + bic $C[1],$A[1][3],$A[1][2] + bic $C[2],$A[1][0],$A[1][4] + eor $A[0][0],$A[0][0],$C[3] // A[0][0] ^= Iota + bic $C[3],$A[1][1],$A[1][0] + eor $A[1][0],$A[1][0],$C[0] + bic $C[0],$A[1][4],$A[1][3] + eor $A[1][1],$A[1][1],$C[1] + eor $A[1][3],$A[1][3],$C[2] + eor $A[1][4],$A[1][4],$C[3] + eor $A[1][2],$A[1][2],$C[0] + + bic $C[0],$A[2][2],$A[2][1] + bic $C[1],$A[2][3],$A[2][2] + bic $C[2],$A[2][0],$A[2][4] + bic $C[3],$A[2][1],$A[2][0] + eor $A[2][0],$A[2][0],$C[0] + bic $C[0],$A[2][4],$A[2][3] + eor $A[2][1],$A[2][1],$C[1] + eor $A[2][3],$A[2][3],$C[2] + eor $A[2][4],$A[2][4],$C[3] + eor $A[2][2],$A[2][2],$C[0] + + bic $C[0],$A[3][2],$A[3][1] + bic $C[1],$A[3][3],$A[3][2] + bic $C[2],$A[3][0],$A[3][4] + bic $C[3],$A[3][1],$A[3][0] + eor $A[3][0],$A[3][0],$C[0] + bic $C[0],$A[3][4],$A[3][3] + eor $A[3][1],$A[3][1],$C[1] + eor $A[3][3],$A[3][3],$C[2] + eor $A[3][4],$A[3][4],$C[3] + eor $A[3][2],$A[3][2],$C[0] + + bic $C[0],$A[4][2],$A[4][1] + bic $C[1],$A[4][3],$A[4][2] + bic $C[2],$A[4][0],$A[4][4] + bic $C[3],$A[4][1],$A[4][0] + eor $A[4][0],$A[4][0],$C[0] + bic $C[0],$A[4][4],$A[4][3] + eor $A[4][1],$A[4][1],$C[1] + eor $A[4][3],$A[4][3],$C[2] + eor $A[4][4],$A[4][4],$C[3] + eor $A[4][2],$A[4][2],$C[0] + + bne .Loop + + ldr x30,[sp,#24] + .inst 0xd50323bf // autiasp + ret +.size KeccakF1600_int,.-KeccakF1600_int + +.type KeccakF1600,%function +.align 5 +KeccakF1600: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-128]! + add x29,sp,#0 + stp x19,x20,[sp,#16] + stp x21,x22,[sp,#32] + stp x23,x24,[sp,#48] + stp x25,x26,[sp,#64] + stp x27,x28,[sp,#80] + sub sp,sp,#48 + + str x0,[sp,#32] // offload argument + mov $C[0],x0 + ldp $A[0][0],$A[0][1],[x0,#16*0] + ldp $A[0][2],$A[0][3],[$C[0],#16*1] + ldp $A[0][4],$A[1][0],[$C[0],#16*2] + ldp $A[1][1],$A[1][2],[$C[0],#16*3] + ldp $A[1][3],$A[1][4],[$C[0],#16*4] + ldp $A[2][0],$A[2][1],[$C[0],#16*5] + ldp $A[2][2],$A[2][3],[$C[0],#16*6] + ldp $A[2][4],$A[3][0],[$C[0],#16*7] + ldp $A[3][1],$A[3][2],[$C[0],#16*8] + ldp $A[3][3],$A[3][4],[$C[0],#16*9] + ldp $A[4][0],$A[4][1],[$C[0],#16*10] + ldp $A[4][2],$A[4][3],[$C[0],#16*11] + ldr $A[4][4],[$C[0],#16*12] + + bl KeccakF1600_int + + ldr $C[0],[sp,#32] + stp $A[0][0],$A[0][1],[$C[0],#16*0] + stp $A[0][2],$A[0][3],[$C[0],#16*1] + stp $A[0][4],$A[1][0],[$C[0],#16*2] + stp $A[1][1],$A[1][2],[$C[0],#16*3] + stp $A[1][3],$A[1][4],[$C[0],#16*4] + stp $A[2][0],$A[2][1],[$C[0],#16*5] + stp $A[2][2],$A[2][3],[$C[0],#16*6] + stp $A[2][4],$A[3][0],[$C[0],#16*7] + stp $A[3][1],$A[3][2],[$C[0],#16*8] + stp $A[3][3],$A[3][4],[$C[0],#16*9] + stp $A[4][0],$A[4][1],[$C[0],#16*10] + stp $A[4][2],$A[4][3],[$C[0],#16*11] + str $A[4][4],[$C[0],#16*12] + + ldp x19,x20,[x29,#16] + add sp,sp,#48 + ldp x21,x22,[x29,#32] + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x27,x28,[x29,#80] + ldp x29,x30,[sp],#128 + .inst 0xd50323bf // autiasp + ret +.size KeccakF1600,.-KeccakF1600 + +.globl SHA3_absorb +.type SHA3_absorb,%function +.align 5 +SHA3_absorb: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-128]! + add x29,sp,#0 + stp x19,x20,[sp,#16] + stp x21,x22,[sp,#32] + stp x23,x24,[sp,#48] + stp x25,x26,[sp,#64] + stp x27,x28,[sp,#80] + sub sp,sp,#64 + + stp x0,x1,[sp,#32] // offload arguments + stp x2,x3,[sp,#48] + + mov $C[0],x0 // uint64_t A[5][5] + mov $C[1],x1 // const void *inp + mov $C[2],x2 // size_t len + mov $C[3],x3 // size_t bsz + ldp $A[0][0],$A[0][1],[$C[0],#16*0] + ldp $A[0][2],$A[0][3],[$C[0],#16*1] + ldp $A[0][4],$A[1][0],[$C[0],#16*2] + ldp $A[1][1],$A[1][2],[$C[0],#16*3] + ldp $A[1][3],$A[1][4],[$C[0],#16*4] + ldp $A[2][0],$A[2][1],[$C[0],#16*5] + ldp $A[2][2],$A[2][3],[$C[0],#16*6] + ldp $A[2][4],$A[3][0],[$C[0],#16*7] + ldp $A[3][1],$A[3][2],[$C[0],#16*8] + ldp $A[3][3],$A[3][4],[$C[0],#16*9] + ldp $A[4][0],$A[4][1],[$C[0],#16*10] + ldp $A[4][2],$A[4][3],[$C[0],#16*11] + ldr $A[4][4],[$C[0],#16*12] + b .Loop_absorb + +.align 4 +.Loop_absorb: + subs $C[0],$C[2],$C[3] // len - bsz + blo .Labsorbed + + str $C[0],[sp,#48] // save len - bsz +___ +for (my $i=0; $i<24; $i+=2) { +my $j = $i+1; +$code.=<<___; + ldr $C[0],[$C[1]],#8 // *inp++ +#ifdef __AARCH64EB__ + rev $C[0],$C[0] +#endif + eor $A[$i/5][$i%5],$A[$i/5][$i%5],$C[0] + cmp $C[3],#8*($i+2) + blo .Lprocess_block + ldr $C[0],[$C[1]],#8 // *inp++ +#ifdef __AARCH64EB__ + rev $C[0],$C[0] +#endif + eor $A[$j/5][$j%5],$A[$j/5][$j%5],$C[0] + beq .Lprocess_block +___ +} +$code.=<<___; + ldr $C[0],[$C[1]],#8 // *inp++ +#ifdef __AARCH64EB__ + rev $C[0],$C[0] +#endif + eor $A[4][4],$A[4][4],$C[0] + +.Lprocess_block: + str $C[1],[sp,#40] // save inp + + bl KeccakF1600_int + + ldr $C[1],[sp,#40] // restore arguments + ldp $C[2],$C[3],[sp,#48] + b .Loop_absorb + +.align 4 +.Labsorbed: + ldr $C[1],[sp,#32] + stp $A[0][0],$A[0][1],[$C[1],#16*0] + stp $A[0][2],$A[0][3],[$C[1],#16*1] + stp $A[0][4],$A[1][0],[$C[1],#16*2] + stp $A[1][1],$A[1][2],[$C[1],#16*3] + stp $A[1][3],$A[1][4],[$C[1],#16*4] + stp $A[2][0],$A[2][1],[$C[1],#16*5] + stp $A[2][2],$A[2][3],[$C[1],#16*6] + stp $A[2][4],$A[3][0],[$C[1],#16*7] + stp $A[3][1],$A[3][2],[$C[1],#16*8] + stp $A[3][3],$A[3][4],[$C[1],#16*9] + stp $A[4][0],$A[4][1],[$C[1],#16*10] + stp $A[4][2],$A[4][3],[$C[1],#16*11] + str $A[4][4],[$C[1],#16*12] + + mov x0,$C[2] // return value + ldp x19,x20,[x29,#16] + add sp,sp,#64 + ldp x21,x22,[x29,#32] + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x27,x28,[x29,#80] + ldp x29,x30,[sp],#128 + .inst 0xd50323bf // autiasp + ret +.size SHA3_absorb,.-SHA3_absorb +___ +{ +my ($A_flat,$out,$len,$bsz) = map("x$_",(19..22)); +$code.=<<___; +.globl SHA3_squeeze +.type SHA3_squeeze,%function +.align 5 +SHA3_squeeze: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-48]! + add x29,sp,#0 + stp x19,x20,[sp,#16] + stp x21,x22,[sp,#32] + + mov $A_flat,x0 // put aside arguments + mov $out,x1 + mov $len,x2 + mov $bsz,x3 + +.Loop_squeeze: + ldr x4,[x0],#8 + cmp $len,#8 + blo .Lsqueeze_tail +#ifdef __AARCH64EB__ + rev x4,x4 +#endif + str x4,[$out],#8 + subs $len,$len,#8 + beq .Lsqueeze_done + + subs x3,x3,#8 + bhi .Loop_squeeze + + mov x0,$A_flat + bl KeccakF1600 + mov x0,$A_flat + mov x3,$bsz + b .Loop_squeeze + +.align 4 +.Lsqueeze_tail: + strb w4,[$out],#1 + lsr x4,x4,#8 + subs $len,$len,#1 + beq .Lsqueeze_done + strb w4,[$out],#1 + lsr x4,x4,#8 + subs $len,$len,#1 + beq .Lsqueeze_done + strb w4,[$out],#1 + lsr x4,x4,#8 + subs $len,$len,#1 + beq .Lsqueeze_done + strb w4,[$out],#1 + lsr x4,x4,#8 + subs $len,$len,#1 + beq .Lsqueeze_done + strb w4,[$out],#1 + lsr x4,x4,#8 + subs $len,$len,#1 + beq .Lsqueeze_done + strb w4,[$out],#1 + lsr x4,x4,#8 + subs $len,$len,#1 + beq .Lsqueeze_done + strb w4,[$out],#1 + +.Lsqueeze_done: + ldp x19,x20,[sp,#16] + ldp x21,x22,[sp,#32] + ldp x29,x30,[sp],#48 + .inst 0xd50323bf // autiasp + ret +.size SHA3_squeeze,.-SHA3_squeeze +___ +} }}} + {{{ +my @A = map([ "v".$_.".16b", "v".($_+1).".16b", "v".($_+2).".16b", + "v".($_+3).".16b", "v".($_+4).".16b" ], + (0, 5, 10, 15, 20)); + +my @C = map("v$_.16b", (25..31)); + +$code.=<<___; +.type KeccakF1600_ce,%function +.align 5 +KeccakF1600_ce: + mov x9,#12 + adr x10,iotas + b .Loop_ce +.align 4 +.Loop_ce: +___ +for($i=0; $i<2; $i++) { +$code.=<<___; + ////////////////////////////////////////////////// Theta + eor3 $C[0],$A[0][0],$A[1][0],$A[2][0] + eor3 $C[1],$A[0][1],$A[1][1],$A[2][1] + eor3 $C[2],$A[0][2],$A[1][2],$A[2][2] + eor3 $C[3],$A[0][3],$A[1][3],$A[2][3] + eor3 $C[4],$A[0][4],$A[1][4],$A[2][4] + eor3 $C[0],$C[0], $A[3][0],$A[4][0] + eor3 $C[1],$C[1], $A[3][1],$A[4][1] + eor3 $C[2],$C[2], $A[3][2],$A[4][2] + eor3 $C[3],$C[3], $A[3][3],$A[4][3] + eor3 $C[4],$C[4], $A[3][4],$A[4][4] + + rax1 $C[5],$C[0],$C[2] // D[1] + rax1 $C[6],$C[1],$C[3] // D[2] + rax1 $C[2],$C[2],$C[4] // D[3] + rax1 $C[3],$C[3],$C[0] // D[4] + rax1 $C[4],$C[4],$C[1] // D[0] + + ////////////////////////////////////////////////// Theta+Rho+Pi + xar $C[0], $A[1][1],$C[5],#64-$rhotates[1][1] // C[0]=A[0][1] + xar $A[1][1],$A[1][4],$C[3],#64-$rhotates[1][4] + xar $A[1][4],$A[4][2],$C[6],#64-$rhotates[4][2] + xar $A[4][2],$A[2][4],$C[3],#64-$rhotates[2][4] + xar $A[2][4],$A[4][0],$C[4],#64-$rhotates[4][0] + + xar $A[4][0],$A[0][2],$C[6],#64-$rhotates[0][2] + + xar $A[0][2],$A[2][2],$C[6],#64-$rhotates[2][2] + xar $A[2][2],$A[2][3],$C[2],#64-$rhotates[2][3] + xar $A[2][3],$A[3][4],$C[3],#64-$rhotates[3][4] + xar $A[3][4],$A[4][3],$C[2],#64-$rhotates[4][3] + xar $A[4][3],$A[3][0],$C[4],#64-$rhotates[3][0] + + xar $A[3][0],$A[0][4],$C[3],#64-$rhotates[0][4] + + eor $A[0][0],$A[0][0],$C[4] + ldr x11,[x10],#8 + + xar $C[1], $A[3][3],$C[2],#64-$rhotates[3][3] // C[1]=A[0][3] + xar $A[3][3],$A[3][2],$C[6],#64-$rhotates[3][2] + xar $A[3][2],$A[2][1],$C[5],#64-$rhotates[2][1] + xar $A[2][1],$A[1][2],$C[6],#64-$rhotates[1][2] + xar $A[1][2],$A[2][0],$C[4],#64-$rhotates[2][0] + + xar $A[2][0],$A[0][1],$C[5],#64-$rhotates[0][1] // * + + xar $A[0][4],$A[4][4],$C[3],#64-$rhotates[4][4] + xar $A[4][4],$A[4][1],$C[5],#64-$rhotates[4][1] + xar $A[4][1],$A[1][3],$C[2],#64-$rhotates[1][3] + xar $A[1][3],$A[3][1],$C[5],#64-$rhotates[3][1] + xar $A[3][1],$A[1][0],$C[4],#64-$rhotates[1][0] + + xar $C[2], $A[0][3],$C[2],#64-$rhotates[0][3] // C[2]=A[1][0] + + ////////////////////////////////////////////////// Chi+Iota + dup $C[6],x11 // borrow C[6] + bcax $C[3], $A[0][0],$A[0][2],$C[0] // * + bcax $A[0][1],$C[0], $C[1], $A[0][2] // * + bcax $A[0][2],$A[0][2],$A[0][4],$C[1] + bcax $A[0][3],$C[1], $A[0][0],$A[0][4] + bcax $A[0][4],$A[0][4],$C[0], $A[0][0] + + bcax $A[1][0],$C[2], $A[1][2],$A[1][1] // * + bcax $C[0], $A[1][1],$A[1][3],$A[1][2] // * + bcax $A[1][2],$A[1][2],$A[1][4],$A[1][3] + bcax $A[1][3],$A[1][3],$C[2], $A[1][4] + bcax $A[1][4],$A[1][4],$A[1][1],$C[2] + + eor $A[0][0],$C[3],$C[6] // Iota + + bcax $C[1], $A[2][0],$A[2][2],$A[2][1] // * + bcax $C[2], $A[2][1],$A[2][3],$A[2][2] // * + bcax $A[2][2],$A[2][2],$A[2][4],$A[2][3] + bcax $A[2][3],$A[2][3],$A[2][0],$A[2][4] + bcax $A[2][4],$A[2][4],$A[2][1],$A[2][0] + + bcax $C[3], $A[3][0],$A[3][2],$A[3][1] // * + bcax $C[4], $A[3][1],$A[3][3],$A[3][2] // * + bcax $A[3][2],$A[3][2],$A[3][4],$A[3][3] + bcax $A[3][3],$A[3][3],$A[3][0],$A[3][4] + bcax $A[3][4],$A[3][4],$A[3][1],$A[3][0] + + bcax $C[5], $A[4][0],$A[4][2],$A[4][1] // * + bcax $C[6], $A[4][1],$A[4][3],$A[4][2] // * + bcax $A[4][2],$A[4][2],$A[4][4],$A[4][3] + bcax $A[4][3],$A[4][3],$A[4][0],$A[4][4] + bcax $A[4][4],$A[4][4],$A[4][1],$A[4][0] +___ + ( $A[1][1], $C[0]) = ( $C[0], $A[1][1]); + ($A[2][0],$A[2][1], $C[1],$C[2]) = ($C[1],$C[2], $A[2][0],$A[2][1]); + ($A[3][0],$A[3][1], $C[3],$C[4]) = ($C[3],$C[4], $A[3][0],$A[3][1]); + ($A[4][0],$A[4][1], $C[5],$C[6]) = ($C[5],$C[6], $A[4][0],$A[4][1]); +} +$code.=<<___; + subs x9,x9,#1 + bne .Loop_ce + + ret +.size KeccakF1600_ce,.-KeccakF1600_ce + +.type KeccakF1600_cext,%function +.align 5 +KeccakF1600_cext: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-80]! + add x29,sp,#0 + stp d8,d9,[sp,#16] // per ABI requirement + stp d10,d11,[sp,#32] + stp d12,d13,[sp,#48] + stp d14,d15,[sp,#64] +___ +for($i=0; $i<24; $i+=2) { # load A[5][5] +my $j=$i+1; +$code.=<<___; + ldp d$i,d$j,[x0,#8*$i] +___ +} +$code.=<<___; + ldr d24,[x0,#8*$i] + bl KeccakF1600_ce + ldr x30,[sp,#8] +___ +for($i=0; $i<24; $i+=2) { # store A[5][5] +my $j=$i+1; +$code.=<<___; + stp d$i,d$j,[x0,#8*$i] +___ +} +$code.=<<___; + str d24,[x0,#8*$i] + + ldp d8,d9,[sp,#16] + ldp d10,d11,[sp,#32] + ldp d12,d13,[sp,#48] + ldp d14,d15,[sp,#64] + ldr x29,[sp],#80 + .inst 0xd50323bf // autiasp + ret +.size KeccakF1600_cext,.-KeccakF1600_cext +___ + +{ +my ($ctx,$inp,$len,$bsz) = map("x$_",(0..3)); + +$code.=<<___; +.globl SHA3_absorb_cext +.type SHA3_absorb_cext,%function +.align 5 +SHA3_absorb_cext: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-80]! + add x29,sp,#0 + stp d8,d9,[sp,#16] // per ABI requirement + stp d10,d11,[sp,#32] + stp d12,d13,[sp,#48] + stp d14,d15,[sp,#64] +___ +for($i=0; $i<24; $i+=2) { # load A[5][5] +my $j=$i+1; +$code.=<<___; + ldp d$i,d$j,[x0,#8*$i] +___ +} +$code.=<<___; + ldr d24,[x0,#8*$i] + b .Loop_absorb_ce + +.align 4 +.Loop_absorb_ce: + subs $len,$len,$bsz // len - bsz + blo .Labsorbed_ce +___ +for (my $i=0; $i<24; $i+=2) { +my $j = $i+1; +$code.=<<___; + ldr d31,[$inp],#8 // *inp++ +#ifdef __AARCH64EB__ + rev64 v31.16b,v31.16b +#endif + eor $A[$i/5][$i%5],$A[$i/5][$i%5],v31.16b + cmp $bsz,#8*($i+2) + blo .Lprocess_block_ce + ldr d31,[$inp],#8 // *inp++ +#ifdef __AARCH64EB__ + rev v31.16b,v31.16b +#endif + eor $A[$j/5][$j%5],$A[$j/5][$j%5],v31.16b + beq .Lprocess_block_ce +___ +} +$code.=<<___; + ldr d31,[$inp],#8 // *inp++ +#ifdef __AARCH64EB__ + rev v31.16b,v31.16b +#endif + eor $A[4][4],$A[4][4],v31.16b + +.Lprocess_block_ce: + + bl KeccakF1600_ce + + b .Loop_absorb_ce + +.align 4 +.Labsorbed_ce: +___ +for($i=0; $i<24; $i+=2) { # store A[5][5] +my $j=$i+1; +$code.=<<___; + stp d$i,d$j,[x0,#8*$i] +___ +} +$code.=<<___; + str d24,[x0,#8*$i] + add x0,$len,$bsz // return value + + ldp d8,d9,[sp,#16] + ldp d10,d11,[sp,#32] + ldp d12,d13,[sp,#48] + ldp d14,d15,[sp,#64] + ldp x29,x30,[sp],#80 + .inst 0xd50323bf // autiasp + ret +.size SHA3_absorb_cext,.-SHA3_absorb_cext +___ +} +{ +my ($ctx,$out,$len,$bsz) = map("x$_",(0..3)); +$code.=<<___; +.globl SHA3_squeeze_cext +.type SHA3_squeeze_cext,%function +.align 5 +SHA3_squeeze_cext: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-16]! + add x29,sp,#0 + mov x9,$ctx + mov x10,$bsz + +.Loop_squeeze_ce: + ldr x4,[x9],#8 + cmp $len,#8 + blo .Lsqueeze_tail_ce +#ifdef __AARCH64EB__ + rev x4,x4 +#endif + str x4,[$out],#8 + beq .Lsqueeze_done_ce + + sub $len,$len,#8 + subs x10,x10,#8 + bhi .Loop_squeeze_ce + + bl KeccakF1600_cext + ldr x30,[sp,#8] + mov x9,$ctx + mov x10,$bsz + b .Loop_squeeze_ce + +.align 4 +.Lsqueeze_tail_ce: + strb w4,[$out],#1 + lsr x4,x4,#8 + subs $len,$len,#1 + beq .Lsqueeze_done_ce + strb w4,[$out],#1 + lsr x4,x4,#8 + subs $len,$len,#1 + beq .Lsqueeze_done_ce + strb w4,[$out],#1 + lsr x4,x4,#8 + subs $len,$len,#1 + beq .Lsqueeze_done_ce + strb w4,[$out],#1 + lsr x4,x4,#8 + subs $len,$len,#1 + beq .Lsqueeze_done_ce + strb w4,[$out],#1 + lsr x4,x4,#8 + subs $len,$len,#1 + beq .Lsqueeze_done_ce + strb w4,[$out],#1 + lsr x4,x4,#8 + subs $len,$len,#1 + beq .Lsqueeze_done_ce + strb w4,[$out],#1 + +.Lsqueeze_done_ce: + ldr x29,[sp],#16 + .inst 0xd50323bf // autiasp + ret +.size SHA3_squeeze_cext,.-SHA3_squeeze_cext +___ +} }}} +$code.=<<___; +.asciz "Keccak-1600 absorb and squeeze for ARMv8, CRYPTOGAMS by " +___ + +{ my %opcode = ( + "rax1" => 0xce608c00, "eor3" => 0xce000000, + "bcax" => 0xce200000, "xar" => 0xce800000 ); + + sub unsha3 { + my ($mnemonic,$arg)=@_; + + $arg =~ m/[qv]([0-9]+)[^,]*,\s*[qv]([0-9]+)[^,]*(?:,\s*[qv]([0-9]+)[^,]*(?:,\s*[qv#]([0-9\-]+))?)?/ + && + sprintf ".inst\t0x%08x\t//%s %s", + $opcode{$mnemonic}|$1|($2<<5)|($3<<16)|(eval($4)<<10), + $mnemonic,$arg; + } +} + +foreach(split("\n",$code)) { + + s/\`([^\`]*)\`/eval($1)/ge; + + m/\bdup\b/ and s/\.16b/.2d/g or + s/\b(eor3|rax1|xar|bcax)\s+(v.*)/unsha3($1,$2)/ge; + + print $_,"\n"; +} + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-avx2.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-avx2.pl new file mode 100755 index 000000000..d9fc1c59e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-avx2.pl @@ -0,0 +1,482 @@ +#!/usr/bin/env perl +# Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# Keccak-1600 for AVX2. +# +# July 2017. +# +# To paraphrase Gilles Van Assche, if you contemplate Fig. 2.3 on page +# 20 of The Keccak reference [or Fig. 5 of FIPS PUB 202], and load data +# other than A[0][0] in magic order into 6 [256-bit] registers, *each +# dedicated to one axis*, Pi permutation is reduced to intra-register +# shuffles... +# +# It makes other steps more intricate, but overall, is it a win? To be +# more specific index permutations organized by quadruples are: +# +# [4][4] [3][3] [2][2] [1][1]<-+ +# [0][4] [0][3] [0][2] [0][1]<-+ +# [3][0] [1][0] [4][0] [2][0] | +# [4][3] [3][1] [2][4] [1][2] | +# [3][4] [1][3] [4][2] [2][1] | +# [2][3] [4][1] [1][4] [3][2] | +# [2][2] [4][4] [1][1] [3][3] -+ +# +# This however is highly impractical for Theta and Chi. What would help +# Theta is if x indices were aligned column-wise, or in other words: +# +# [0][4] [0][3] [0][2] [0][1] +# [3][0] [1][0] [4][0] [2][0] +#vpermq([4][3] [3][1] [2][4] [1][2], 0b01110010) +# [2][4] [4][3] [1][2] [3][1] +#vpermq([4][2] [3][4] [2][1] [1][3], 0b10001101) +# [3][4] [1][3] [4][2] [2][1] +#vpermq([2][3] [4][1] [1][4] [3][2], 0b01110010) +# [1][4] [2][3] [3][2] [4][1] +#vpermq([1][1] [2][2] [3][3] [4][4], 0b00011011) +# [4][4] [3][3] [2][2] [1][1] +# +# So here we have it, lines not marked with vpermq() represent the magic +# order in which data is to be loaded and maintained. [And lines marked +# with vpermq() represent Pi circular permutation in chosen layout. Note +# that first step is permutation-free.] A[0][0] is loaded to register of +# its own, to all lanes. [A[0][0] is not part of Pi permutation or Rho.] +# Digits in variables' names denote right-most coordinates: + +my ($A00, # [0][0] [0][0] [0][0] [0][0] # %ymm0 + $A01, # [0][4] [0][3] [0][2] [0][1] # %ymm1 + $A20, # [3][0] [1][0] [4][0] [2][0] # %ymm2 + $A31, # [2][4] [4][3] [1][2] [3][1] # %ymm3 + $A21, # [3][4] [1][3] [4][2] [2][1] # %ymm4 + $A41, # [1][4] [2][3] [3][2] [4][1] # %ymm5 + $A11) = # [4][4] [3][3] [2][2] [1][1] # %ymm6 + map("%ymm$_",(0..6)); + +# We also need to map the magic order into offsets within structure: + +my @A_jagged = ([0,0], [1,0], [1,1], [1,2], [1,3], # [0][0..4] + [2,2], [6,0], [3,1], [4,2], [5,3], # [1][0..4] + [2,0], [4,0], [6,1], [5,2], [3,3], # [2][0..4] + [2,3], [3,0], [5,1], [6,2], [4,3], # [3][0..4] + [2,1], [5,0], [4,1], [3,2], [6,3]); # [4][0..4] + @A_jagged = map(8*($$_[0]*4+$$_[1]), @A_jagged); # ... and now linear + +# But on the other hand Chi is much better off if y indices were aligned +# column-wise, not x. For this reason we have to shuffle data prior +# Chi and revert it afterwards. Prior shuffle is naturally merged with +# Pi itself: +# +# [0][4] [0][3] [0][2] [0][1] +# [3][0] [1][0] [4][0] [2][0] +#vpermq([4][3] [3][1] [2][4] [1][2], 0b01110010) +#vpermq([2][4] [4][3] [1][2] [3][1], 0b00011011) = 0b10001101 +# [3][1] [1][2] [4][3] [2][4] +#vpermq([4][2] [3][4] [2][1] [1][3], 0b10001101) +#vpermq([3][4] [1][3] [4][2] [2][1], 0b11100100) = 0b10001101 +# [3][4] [1][3] [4][2] [2][1] +#vpermq([2][3] [4][1] [1][4] [3][2], 0b01110010) +#vpermq([1][4] [2][3] [3][2] [4][1], 0b01110010) = 0b00011011 +# [3][2] [1][4] [4][1] [2][3] +#vpermq([1][1] [2][2] [3][3] [4][4], 0b00011011) +#vpermq([4][4] [3][3] [2][2] [1][1], 0b10001101) = 0b01110010 +# [3][3] [1][1] [4][4] [2][2] +# +# And reverse post-Chi permutation: +# +# [0][4] [0][3] [0][2] [0][1] +# [3][0] [1][0] [4][0] [2][0] +#vpermq([3][1] [1][2] [4][3] [2][4], 0b00011011) +# [2][4] [4][3] [1][2] [3][1] +#vpermq([3][4] [1][3] [4][2] [2][1], 0b11100100) = nop :-) +# [3][4] [1][3] [4][2] [2][1] +#vpermq([3][2] [1][4] [4][1] [2][3], 0b10001101) +# [1][4] [2][3] [3][2] [4][1] +#vpermq([3][3] [1][1] [4][4] [2][2], 0b01110010) +# [4][4] [3][3] [2][2] [1][1] +# +######################################################################## +# Numbers are cycles per processed byte out of large message. +# +# r=1088(*) +# +# Haswell 8.7/+10% +# Skylake 7.8/+20% +# Ryzen 17(**) +# +# (*) Corresponds to SHA3-256. Percentage after slash is improvement +# coefficient in comparison to scalar keccak1600-x86_64.pl. +# (**) It's expected that Ryzen performs poorly, because instruction +# issue rate is limited to two AVX2 instructions per cycle and +# in addition vpblendd is reportedly bound to specific port. +# Obviously this code path should not be executed on Ryzen. + +my @T = map("%ymm$_",(7..15)); +my ($C14,$C00,$D00,$D14) = @T[5..8]; + +$code.=<<___; +.text + +.type __KeccakF1600,\@function +.align 32 +__KeccakF1600: + lea rhotates_left+96(%rip),%r8 + lea rhotates_right+96(%rip),%r9 + lea iotas(%rip),%r10 + mov \$24,%eax + jmp .Loop_avx2 + +.align 32 +.Loop_avx2: + ######################################### Theta + vpshufd \$0b01001110,$A20,$C00 + vpxor $A31,$A41,$C14 + vpxor $A11,$A21,@T[2] + vpxor $A01,$C14,$C14 + vpxor @T[2],$C14,$C14 # C[1..4] + + vpermq \$0b10010011,$C14,@T[4] + vpxor $A20,$C00,$C00 + vpermq \$0b01001110,$C00,@T[0] + + vpsrlq \$63,$C14,@T[1] + vpaddq $C14,$C14,@T[2] + vpor @T[2],@T[1],@T[1] # ROL64(C[1..4],1) + + vpermq \$0b00111001,@T[1],$D14 + vpxor @T[4],@T[1],$D00 + vpermq \$0b00000000,$D00,$D00 # D[0..0] = ROL64(C[1],1) ^ C[4] + + vpxor $A00,$C00,$C00 + vpxor @T[0],$C00,$C00 # C[0..0] + + vpsrlq \$63,$C00,@T[0] + vpaddq $C00,$C00,@T[1] + vpor @T[0],@T[1],@T[1] # ROL64(C[0..0],1) + + vpxor $D00,$A20,$A20 # ^= D[0..0] + vpxor $D00,$A00,$A00 # ^= D[0..0] + + vpblendd \$0b11000000,@T[1],$D14,$D14 + vpblendd \$0b00000011,$C00,@T[4],@T[4] + vpxor @T[4],$D14,$D14 # D[1..4] = ROL64(C[2..4,0),1) ^ C[0..3] + + ######################################### Rho + Pi + pre-Chi shuffle + vpsllvq 0*32-96(%r8),$A20,@T[3] + vpsrlvq 0*32-96(%r9),$A20,$A20 + vpor @T[3],$A20,$A20 + + vpxor $D14,$A31,$A31 # ^= D[1..4] from Theta + vpsllvq 2*32-96(%r8),$A31,@T[4] + vpsrlvq 2*32-96(%r9),$A31,$A31 + vpor @T[4],$A31,$A31 + + vpxor $D14,$A21,$A21 # ^= D[1..4] from Theta + vpsllvq 3*32-96(%r8),$A21,@T[5] + vpsrlvq 3*32-96(%r9),$A21,$A21 + vpor @T[5],$A21,$A21 + + vpxor $D14,$A41,$A41 # ^= D[1..4] from Theta + vpsllvq 4*32-96(%r8),$A41,@T[6] + vpsrlvq 4*32-96(%r9),$A41,$A41 + vpor @T[6],$A41,$A41 + + vpxor $D14,$A11,$A11 # ^= D[1..4] from Theta + vpermq \$0b10001101,$A20,@T[3] # $A20 -> future $A31 + vpermq \$0b10001101,$A31,@T[4] # $A31 -> future $A21 + vpsllvq 5*32-96(%r8),$A11,@T[7] + vpsrlvq 5*32-96(%r9),$A11,@T[1] + vpor @T[7],@T[1],@T[1] # $A11 -> future $A01 + + vpxor $D14,$A01,$A01 # ^= D[1..4] from Theta + vpermq \$0b00011011,$A21,@T[5] # $A21 -> future $A41 + vpermq \$0b01110010,$A41,@T[6] # $A41 -> future $A11 + vpsllvq 1*32-96(%r8),$A01,@T[8] + vpsrlvq 1*32-96(%r9),$A01,@T[2] + vpor @T[8],@T[2],@T[2] # $A01 -> future $A20 + + ######################################### Chi + vpsrldq \$8,@T[1],@T[7] + vpandn @T[7],@T[1],@T[0] # tgting [0][0] [0][0] [0][0] [0][0] + + vpblendd \$0b00001100,@T[6],@T[2],$A31 # [4][4] [2][0] + vpblendd \$0b00001100,@T[2],@T[4],@T[8] # [4][0] [2][1] + vpblendd \$0b00001100,@T[4],@T[3],$A41 # [4][2] [2][4] + vpblendd \$0b00001100,@T[3],@T[2],@T[7] # [4][3] [2][0] + vpblendd \$0b00110000,@T[4],$A31,$A31 # [1][3] [4][4] [2][0] + vpblendd \$0b00110000,@T[5],@T[8],@T[8] # [1][4] [4][0] [2][1] + vpblendd \$0b00110000,@T[2],$A41,$A41 # [1][0] [4][2] [2][4] + vpblendd \$0b00110000,@T[6],@T[7],@T[7] # [1][1] [4][3] [2][0] + vpblendd \$0b11000000,@T[5],$A31,$A31 # [3][2] [1][3] [4][4] [2][0] + vpblendd \$0b11000000,@T[6],@T[8],@T[8] # [3][3] [1][4] [4][0] [2][1] + vpblendd \$0b11000000,@T[6],$A41,$A41 # [3][3] [1][0] [4][2] [2][4] + vpblendd \$0b11000000,@T[4],@T[7],@T[7] # [3][4] [1][1] [4][3] [2][0] + vpandn @T[8],$A31,$A31 # tgting [3][1] [1][2] [4][3] [2][4] + vpandn @T[7],$A41,$A41 # tgting [3][2] [1][4] [4][1] [2][3] + + vpblendd \$0b00001100,@T[2],@T[5],$A11 # [4][0] [2][3] + vpblendd \$0b00001100,@T[5],@T[3],@T[8] # [4][1] [2][4] + vpxor @T[3],$A31,$A31 + vpblendd \$0b00110000,@T[3],$A11,$A11 # [1][2] [4][0] [2][3] + vpblendd \$0b00110000,@T[4],@T[8],@T[8] # [1][3] [4][1] [2][4] + vpxor @T[5],$A41,$A41 + vpblendd \$0b11000000,@T[4],$A11,$A11 # [3][4] [1][2] [4][0] [2][3] + vpblendd \$0b11000000,@T[2],@T[8],@T[8] # [3][0] [1][3] [4][1] [2][4] + vpandn @T[8],$A11,$A11 # tgting [3][3] [1][1] [4][4] [2][2] + vpxor @T[6],$A11,$A11 + + vpermq \$0b00011110,@T[1],$A21 # [0][1] [0][2] [0][4] [0][3] + vpblendd \$0b00110000,$A00,$A21,@T[8] # [0][1] [0][0] [0][4] [0][3] + vpermq \$0b00111001,@T[1],$A01 # [0][1] [0][4] [0][3] [0][2] + vpblendd \$0b11000000,$A00,$A01,$A01 # [0][0] [0][4] [0][3] [0][2] + vpandn @T[8],$A01,$A01 # tgting [0][4] [0][3] [0][2] [0][1] + + vpblendd \$0b00001100,@T[5],@T[4],$A20 # [4][1] [2][1] + vpblendd \$0b00001100,@T[4],@T[6],@T[7] # [4][2] [2][2] + vpblendd \$0b00110000,@T[6],$A20,$A20 # [1][1] [4][1] [2][1] + vpblendd \$0b00110000,@T[3],@T[7],@T[7] # [1][2] [4][2] [2][2] + vpblendd \$0b11000000,@T[3],$A20,$A20 # [3][1] [1][1] [4][1] [2][1] + vpblendd \$0b11000000,@T[5],@T[7],@T[7] # [3][2] [1][2] [4][2] [2][2] + vpandn @T[7],$A20,$A20 # tgting [3][0] [1][0] [4][0] [2][0] + vpxor @T[2],$A20,$A20 + + vpermq \$0b00000000,@T[0],@T[0] # [0][0] [0][0] [0][0] [0][0] + vpermq \$0b00011011,$A31,$A31 # post-Chi shuffle + vpermq \$0b10001101,$A41,$A41 + vpermq \$0b01110010,$A11,$A11 + + vpblendd \$0b00001100,@T[3],@T[6],$A21 # [4][3] [2][2] + vpblendd \$0b00001100,@T[6],@T[5],@T[7] # [4][4] [2][3] + vpblendd \$0b00110000,@T[5],$A21,$A21 # [1][4] [4][3] [2][2] + vpblendd \$0b00110000,@T[2],@T[7],@T[7] # [1][0] [4][4] [2][3] + vpblendd \$0b11000000,@T[2],$A21,$A21 # [3][0] [1][4] [4][3] [2][2] + vpblendd \$0b11000000,@T[3],@T[7],@T[7] # [3][1] [1][0] [4][4] [2][3] + vpandn @T[7],$A21,$A21 # tgting [3][4] [1][3] [4][2] [2][1] + + vpxor @T[0],$A00,$A00 + vpxor @T[1],$A01,$A01 + vpxor @T[4],$A21,$A21 + + ######################################### Iota + vpxor (%r10),$A00,$A00 + lea 32(%r10),%r10 + + dec %eax + jnz .Loop_avx2 + + ret +.size __KeccakF1600,.-__KeccakF1600 +___ +my ($A_flat,$inp,$len,$bsz) = ("%rdi","%rsi","%rdx","%rcx"); +my $out = $inp; # in squeeze + +$code.=<<___; +.globl SHA3_absorb +.type SHA3_absorb,\@function +.align 32 +SHA3_absorb: + mov %rsp,%r11 + + lea -240(%rsp),%rsp + and \$-32,%rsp + + lea 96($A_flat),$A_flat + lea 96($inp),$inp + lea 96(%rsp),%r10 + + vzeroupper + + vpbroadcastq -96($A_flat),$A00 # load A[5][5] + vmovdqu 8+32*0-96($A_flat),$A01 + vmovdqu 8+32*1-96($A_flat),$A20 + vmovdqu 8+32*2-96($A_flat),$A31 + vmovdqu 8+32*3-96($A_flat),$A21 + vmovdqu 8+32*4-96($A_flat),$A41 + vmovdqu 8+32*5-96($A_flat),$A11 + + vpxor @T[0],@T[0],@T[0] + vmovdqa @T[0],32*2-96(%r10) # zero transfer area on stack + vmovdqa @T[0],32*3-96(%r10) + vmovdqa @T[0],32*4-96(%r10) + vmovdqa @T[0],32*5-96(%r10) + vmovdqa @T[0],32*6-96(%r10) + +.Loop_absorb_avx2: + mov $bsz,%rax + sub $bsz,$len + jc .Ldone_absorb_avx2 + + shr \$3,%eax + vpbroadcastq 0-96($inp),@T[0] + vmovdqu 8-96($inp),@T[1] + sub \$4,%eax +___ +for(my $i=5; $i<25; $i++) { +$code.=<<___ + dec %eax + jz .Labsorved_avx2 + mov 8*$i-96($inp),%r8 + mov %r8,$A_jagged[$i]-96(%r10) +___ +} +$code.=<<___; +.Labsorved_avx2: + lea ($inp,$bsz),$inp + + vpxor @T[0],$A00,$A00 + vpxor @T[1],$A01,$A01 + vpxor 32*2-96(%r10),$A20,$A20 + vpxor 32*3-96(%r10),$A31,$A31 + vpxor 32*4-96(%r10),$A21,$A21 + vpxor 32*5-96(%r10),$A41,$A41 + vpxor 32*6-96(%r10),$A11,$A11 + + call __KeccakF1600 + + lea 96(%rsp),%r10 + jmp .Loop_absorb_avx2 + +.Ldone_absorb_avx2: + vmovq %xmm0,-96($A_flat) + vmovdqu $A01,8+32*0-96($A_flat) + vmovdqu $A20,8+32*1-96($A_flat) + vmovdqu $A31,8+32*2-96($A_flat) + vmovdqu $A21,8+32*3-96($A_flat) + vmovdqu $A41,8+32*4-96($A_flat) + vmovdqu $A11,8+32*5-96($A_flat) + + vzeroupper + + lea (%r11),%rsp + lea ($len,$bsz),%rax # return value + ret +.size SHA3_absorb,.-SHA3_absorb + +.globl SHA3_squeeze +.type SHA3_squeeze,\@function +.align 32 +SHA3_squeeze: + mov %rsp,%r11 + + lea 96($A_flat),$A_flat + shr \$3,$bsz + + vzeroupper + + vpbroadcastq -96($A_flat),$A00 + vpxor @T[0],@T[0],@T[0] + vmovdqu 8+32*0-96($A_flat),$A01 + vmovdqu 8+32*1-96($A_flat),$A20 + vmovdqu 8+32*2-96($A_flat),$A31 + vmovdqu 8+32*3-96($A_flat),$A21 + vmovdqu 8+32*4-96($A_flat),$A41 + vmovdqu 8+32*5-96($A_flat),$A11 + + mov $bsz,%rax + +.Loop_squeeze_avx2: + mov @A_jagged[$i]-96($A_flat),%r8 +___ +for (my $i=0; $i<25; $i++) { +$code.=<<___; + sub \$8,$len + jc .Ltail_squeeze_avx2 + mov %r8,($out) + lea 8($out),$out + je .Ldone_squeeze_avx2 + dec %eax + je .Lextend_output_avx2 + mov @A_jagged[$i+1]-120($A_flat),%r8 +___ +} +$code.=<<___; +.Lextend_output_avx2: + call __KeccakF1600 + + vmovq %xmm0,-96($A_flat) + vmovdqu $A01,8+32*0-96($A_flat) + vmovdqu $A20,8+32*1-96($A_flat) + vmovdqu $A31,8+32*2-96($A_flat) + vmovdqu $A21,8+32*3-96($A_flat) + vmovdqu $A41,8+32*4-96($A_flat) + vmovdqu $A11,8+32*5-96($A_flat) + + mov $bsz,%rax + jmp .Loop_squeeze_avx2 + + +.Ltail_squeeze_avx2: + add \$8,$len +.Loop_tail_avx2: + mov %r8b,($out) + lea 1($out),$out + shr \$8,%r8 + dec $len + jnz .Loop_tail_avx2 + +.Ldone_squeeze_avx2: + vzeroupper + + lea (%r11),%rsp + ret +.size SHA3_squeeze,.-SHA3_squeeze + +.align 64 +rhotates_left: + .quad 3, 18, 36, 41 # [2][0] [4][0] [1][0] [3][0] + .quad 1, 62, 28, 27 # [0][1] [0][2] [0][3] [0][4] + .quad 45, 6, 56, 39 # [3][1] [1][2] [4][3] [2][4] + .quad 10, 61, 55, 8 # [2][1] [4][2] [1][3] [3][4] + .quad 2, 15, 25, 20 # [4][1] [3][2] [2][3] [1][4] + .quad 44, 43, 21, 14 # [1][1] [2][2] [3][3] [4][4] +rhotates_right: + .quad 64-3, 64-18, 64-36, 64-41 + .quad 64-1, 64-62, 64-28, 64-27 + .quad 64-45, 64-6, 64-56, 64-39 + .quad 64-10, 64-61, 64-55, 64-8 + .quad 64-2, 64-15, 64-25, 64-20 + .quad 64-44, 64-43, 64-21, 64-14 +iotas: + .quad 0x0000000000000001, 0x0000000000000001, 0x0000000000000001, 0x0000000000000001 + .quad 0x0000000000008082, 0x0000000000008082, 0x0000000000008082, 0x0000000000008082 + .quad 0x800000000000808a, 0x800000000000808a, 0x800000000000808a, 0x800000000000808a + .quad 0x8000000080008000, 0x8000000080008000, 0x8000000080008000, 0x8000000080008000 + .quad 0x000000000000808b, 0x000000000000808b, 0x000000000000808b, 0x000000000000808b + .quad 0x0000000080000001, 0x0000000080000001, 0x0000000080000001, 0x0000000080000001 + .quad 0x8000000080008081, 0x8000000080008081, 0x8000000080008081, 0x8000000080008081 + .quad 0x8000000000008009, 0x8000000000008009, 0x8000000000008009, 0x8000000000008009 + .quad 0x000000000000008a, 0x000000000000008a, 0x000000000000008a, 0x000000000000008a + .quad 0x0000000000000088, 0x0000000000000088, 0x0000000000000088, 0x0000000000000088 + .quad 0x0000000080008009, 0x0000000080008009, 0x0000000080008009, 0x0000000080008009 + .quad 0x000000008000000a, 0x000000008000000a, 0x000000008000000a, 0x000000008000000a + .quad 0x000000008000808b, 0x000000008000808b, 0x000000008000808b, 0x000000008000808b + .quad 0x800000000000008b, 0x800000000000008b, 0x800000000000008b, 0x800000000000008b + .quad 0x8000000000008089, 0x8000000000008089, 0x8000000000008089, 0x8000000000008089 + .quad 0x8000000000008003, 0x8000000000008003, 0x8000000000008003, 0x8000000000008003 + .quad 0x8000000000008002, 0x8000000000008002, 0x8000000000008002, 0x8000000000008002 + .quad 0x8000000000000080, 0x8000000000000080, 0x8000000000000080, 0x8000000000000080 + .quad 0x000000000000800a, 0x000000000000800a, 0x000000000000800a, 0x000000000000800a + .quad 0x800000008000000a, 0x800000008000000a, 0x800000008000000a, 0x800000008000000a + .quad 0x8000000080008081, 0x8000000080008081, 0x8000000080008081, 0x8000000080008081 + .quad 0x8000000000008080, 0x8000000000008080, 0x8000000000008080, 0x8000000000008080 + .quad 0x0000000080000001, 0x0000000080000001, 0x0000000080000001, 0x0000000080000001 + .quad 0x8000000080008008, 0x8000000080008008, 0x8000000080008008, 0x8000000080008008 + +.asciz "Keccak-1600 absorb and squeeze for AVX2, CRYPTOGAMS by " +___ + +$output=pop; +open STDOUT,">$output"; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-avx512.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-avx512.pl new file mode 100755 index 000000000..9074ff02d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-avx512.pl @@ -0,0 +1,551 @@ +#!/usr/bin/env perl +# Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# Keccak-1600 for AVX-512F. +# +# July 2017. +# +# Below code is KECCAK_1X_ALT implementation (see sha/keccak1600.c). +# Pretty straightforward, the only "magic" is data layout in registers. +# It's impossible to have one that is optimal for every step, hence +# it's changing as algorithm progresses. Data is saved in linear order, +# but in-register order morphs between rounds. Even rounds take in +# linear layout, and odd rounds - transposed, or "verticaly-shaped"... +# +######################################################################## +# Numbers are cycles per processed byte out of large message. +# +# r=1088(*) +# +# Knights Landing 7.6 +# Skylake-X 5.7 +# +# (*) Corresponds to SHA3-256. + +######################################################################## +# Below code is combination of two ideas. One is taken from Keccak Code +# Package, hereafter KCP, and another one from initial version of this +# module. What is common is observation that Pi's input and output are +# "mostly transposed", i.e. if input is aligned by x coordinate, then +# output is [mostly] aligned by y. Both versions, KCP and predecessor, +# were trying to use one of them from round to round, which resulted in +# some kind of transposition in each round. This version still does +# transpose data, but only every second round. Another essential factor +# is that KCP transposition has to be performed with instructions that +# turned to be rather expensive on Knights Landing, both latency- and +# throughput-wise. Not to mention that some of them have to depend on +# each other. On the other hand initial version of this module was +# relying heavily on blend instructions. There were lots of them, +# resulting in higher instruction count, yet it performed better on +# Knights Landing, because processor can execute pair of them each +# cycle and they have minimal latency. This module is an attempt to +# bring best parts together:-) +# +# Coordinates below correspond to those in sha/keccak1600.c. Input +# layout is straight linear: +# +# [0][4] [0][3] [0][2] [0][1] [0][0] +# [1][4] [1][3] [1][2] [1][1] [1][0] +# [2][4] [2][3] [2][2] [2][1] [2][0] +# [3][4] [3][3] [3][2] [3][1] [3][0] +# [4][4] [4][3] [4][2] [4][1] [4][0] +# +# It's perfect for Theta, while Pi is reduced to intra-register +# permutations which yield layout perfect for Chi: +# +# [4][0] [3][0] [2][0] [1][0] [0][0] +# [4][1] [3][1] [2][1] [1][1] [0][1] +# [4][2] [3][2] [2][2] [1][2] [0][2] +# [4][3] [3][3] [2][3] [1][3] [0][3] +# [4][4] [3][4] [2][4] [1][4] [0][4] +# +# Now instead of performing full transposition and feeding it to next +# identical round, we perform kind of diagonal transposition to layout +# from initial version of this module, and make it suitable for Theta: +# +# [4][4] [3][3] [2][2] [1][1] [0][0]>4.3.2.1.0>[4][4] [3][3] [2][2] [1][1] [0][0] +# [4][0] [3][4] [2][3] [1][2] [0][1]>3.2.1.0.4>[3][4] [2][3] [1][2] [0][1] [4][0] +# [4][1] [3][0] [2][4] [1][3] [0][2]>2.1.0.4.3>[2][4] [1][3] [0][2] [4][1] [3][0] +# [4][2] [3][1] [2][0] [1][4] [0][3]>1.0.4.3.2>[1][4] [0][3] [4][2] [3][1] [2][0] +# [4][3] [3][2] [2][1] [1][0] [0][4]>0.4.3.2.1>[0][4] [4][3] [3][2] [2][1] [1][0] +# +# Now intra-register permutations yield initial [almost] straight +# linear layout: +# +# [4][4] [3][3] [2][2] [1][1] [0][0] +##[0][4] [0][3] [0][2] [0][1] [0][0] +# [3][4] [2][3] [1][2] [0][1] [4][0] +##[2][3] [2][2] [2][1] [2][0] [2][4] +# [2][4] [1][3] [0][2] [4][1] [3][0] +##[4][2] [4][1] [4][0] [4][4] [4][3] +# [1][4] [0][3] [4][2] [3][1] [2][0] +##[1][1] [1][0] [1][4] [1][3] [1][2] +# [0][4] [4][3] [3][2] [2][1] [1][0] +##[3][0] [3][4] [3][3] [3][2] [3][1] +# +# This means that odd round Chi is performed in less suitable layout, +# with a number of additional permutations. But overall it turned to be +# a win. Permutations are fastest possible on Knights Landing and they +# are laid down to be independent of each other. In the essence I traded +# 20 blend instructions for 3 permutations. The result is 13% faster +# than KCP on Skylake-X, and >40% on Knights Landing. +# +# As implied, data is loaded in straight linear order. Digits in +# variables' names represent coordinates of right-most element of +# loaded data chunk: + +my ($A00, # [0][4] [0][3] [0][2] [0][1] [0][0] + $A10, # [1][4] [1][3] [1][2] [1][1] [1][0] + $A20, # [2][4] [2][3] [2][2] [2][1] [2][0] + $A30, # [3][4] [3][3] [3][2] [3][1] [3][0] + $A40) = # [4][4] [4][3] [4][2] [4][1] [4][0] + map("%zmm$_",(0..4)); + +# We also need to map the magic order into offsets within structure: + +my @A_jagged = ([0,0], [0,1], [0,2], [0,3], [0,4], + [1,0], [1,1], [1,2], [1,3], [1,4], + [2,0], [2,1], [2,2], [2,3], [2,4], + [3,0], [3,1], [3,2], [3,3], [3,4], + [4,0], [4,1], [4,2], [4,3], [4,4]); + @A_jagged = map(8*($$_[0]*8+$$_[1]), @A_jagged); # ... and now linear + +my @T = map("%zmm$_",(5..12)); +my @Theta = map("%zmm$_",(33,13..16)); # invalid @Theta[0] is not typo +my @Pi0 = map("%zmm$_",(17..21)); +my @Rhotate0 = map("%zmm$_",(22..26)); +my @Rhotate1 = map("%zmm$_",(27..31)); + +my ($C00,$D00) = @T[0..1]; +my ($k00001,$k00010,$k00100,$k01000,$k10000,$k11111) = map("%k$_",(1..6)); + +$code.=<<___; +.text + +.type __KeccakF1600,\@function +.align 32 +__KeccakF1600: + lea iotas(%rip),%r10 + mov \$12,%eax + jmp .Loop_avx512 + +.align 32 +.Loop_avx512: + ######################################### Theta, even round + vmovdqa64 $A00,@T[0] # put aside original A00 + vpternlogq \$0x96,$A20,$A10,$A00 # and use it as "C00" + vpternlogq \$0x96,$A40,$A30,$A00 + + vprolq \$1,$A00,$D00 + vpermq $A00,@Theta[1],$A00 + vpermq $D00,@Theta[4],$D00 + + vpternlogq \$0x96,$A00,$D00,@T[0] # T[0] is original A00 + vpternlogq \$0x96,$A00,$D00,$A10 + vpternlogq \$0x96,$A00,$D00,$A20 + vpternlogq \$0x96,$A00,$D00,$A30 + vpternlogq \$0x96,$A00,$D00,$A40 + + ######################################### Rho + vprolvq @Rhotate0[0],@T[0],$A00 # T[0] is original A00 + vprolvq @Rhotate0[1],$A10,$A10 + vprolvq @Rhotate0[2],$A20,$A20 + vprolvq @Rhotate0[3],$A30,$A30 + vprolvq @Rhotate0[4],$A40,$A40 + + ######################################### Pi + vpermq $A00,@Pi0[0],$A00 + vpermq $A10,@Pi0[1],$A10 + vpermq $A20,@Pi0[2],$A20 + vpermq $A30,@Pi0[3],$A30 + vpermq $A40,@Pi0[4],$A40 + + ######################################### Chi + vmovdqa64 $A00,@T[0] + vmovdqa64 $A10,@T[1] + vpternlogq \$0xD2,$A20,$A10,$A00 + vpternlogq \$0xD2,$A30,$A20,$A10 + vpternlogq \$0xD2,$A40,$A30,$A20 + vpternlogq \$0xD2,@T[0],$A40,$A30 + vpternlogq \$0xD2,@T[1],@T[0],$A40 + + ######################################### Iota + vpxorq (%r10),$A00,${A00}{$k00001} + lea 16(%r10),%r10 + + ######################################### Harmonize rounds + vpblendmq $A20,$A10,@{T[1]}{$k00010} + vpblendmq $A30,$A20,@{T[2]}{$k00010} + vpblendmq $A40,$A30,@{T[3]}{$k00010} + vpblendmq $A10,$A00,@{T[0]}{$k00010} + vpblendmq $A00,$A40,@{T[4]}{$k00010} + + vpblendmq $A30,@T[1],@{T[1]}{$k00100} + vpblendmq $A40,@T[2],@{T[2]}{$k00100} + vpblendmq $A20,@T[0],@{T[0]}{$k00100} + vpblendmq $A00,@T[3],@{T[3]}{$k00100} + vpblendmq $A10,@T[4],@{T[4]}{$k00100} + + vpblendmq $A40,@T[1],@{T[1]}{$k01000} + vpblendmq $A30,@T[0],@{T[0]}{$k01000} + vpblendmq $A00,@T[2],@{T[2]}{$k01000} + vpblendmq $A10,@T[3],@{T[3]}{$k01000} + vpblendmq $A20,@T[4],@{T[4]}{$k01000} + + vpblendmq $A40,@T[0],@{T[0]}{$k10000} + vpblendmq $A00,@T[1],@{T[1]}{$k10000} + vpblendmq $A10,@T[2],@{T[2]}{$k10000} + vpblendmq $A20,@T[3],@{T[3]}{$k10000} + vpblendmq $A30,@T[4],@{T[4]}{$k10000} + + #vpermq @T[0],@Theta[0],$A00 # doesn't actually change order + vpermq @T[1],@Theta[1],$A10 + vpermq @T[2],@Theta[2],$A20 + vpermq @T[3],@Theta[3],$A30 + vpermq @T[4],@Theta[4],$A40 + + ######################################### Theta, odd round + vmovdqa64 $T[0],$A00 # real A00 + vpternlogq \$0x96,$A20,$A10,$C00 # C00 is @T[0]'s alias + vpternlogq \$0x96,$A40,$A30,$C00 + + vprolq \$1,$C00,$D00 + vpermq $C00,@Theta[1],$C00 + vpermq $D00,@Theta[4],$D00 + + vpternlogq \$0x96,$C00,$D00,$A00 + vpternlogq \$0x96,$C00,$D00,$A30 + vpternlogq \$0x96,$C00,$D00,$A10 + vpternlogq \$0x96,$C00,$D00,$A40 + vpternlogq \$0x96,$C00,$D00,$A20 + + ######################################### Rho + vprolvq @Rhotate1[0],$A00,$A00 + vprolvq @Rhotate1[3],$A30,@T[1] + vprolvq @Rhotate1[1],$A10,@T[2] + vprolvq @Rhotate1[4],$A40,@T[3] + vprolvq @Rhotate1[2],$A20,@T[4] + + vpermq $A00,@Theta[4],@T[5] + vpermq $A00,@Theta[3],@T[6] + + ######################################### Iota + vpxorq -8(%r10),$A00,${A00}{$k00001} + + ######################################### Pi + vpermq @T[1],@Theta[2],$A10 + vpermq @T[2],@Theta[4],$A20 + vpermq @T[3],@Theta[1],$A30 + vpermq @T[4],@Theta[3],$A40 + + ######################################### Chi + vpternlogq \$0xD2,@T[6],@T[5],$A00 + + vpermq @T[1],@Theta[1],@T[7] + #vpermq @T[1],@Theta[0],@T[1] + vpternlogq \$0xD2,@T[1],@T[7],$A10 + + vpermq @T[2],@Theta[3],@T[0] + vpermq @T[2],@Theta[2],@T[2] + vpternlogq \$0xD2,@T[2],@T[0],$A20 + + #vpermq @T[3],@Theta[0],@T[3] + vpermq @T[3],@Theta[4],@T[1] + vpternlogq \$0xD2,@T[1],@T[3],$A30 + + vpermq @T[4],@Theta[2],@T[0] + vpermq @T[4],@Theta[1],@T[4] + vpternlogq \$0xD2,@T[4],@T[0],$A40 + + dec %eax + jnz .Loop_avx512 + + ret +.size __KeccakF1600,.-__KeccakF1600 +___ + +my ($A_flat,$inp,$len,$bsz) = ("%rdi","%rsi","%rdx","%rcx"); +my $out = $inp; # in squeeze + +$code.=<<___; +.globl SHA3_absorb +.type SHA3_absorb,\@function +.align 32 +SHA3_absorb: + mov %rsp,%r11 + + lea -320(%rsp),%rsp + and \$-64,%rsp + + lea 96($A_flat),$A_flat + lea 96($inp),$inp + lea 128(%rsp),%r9 + + lea theta_perm(%rip),%r8 + + kxnorw $k11111,$k11111,$k11111 + kshiftrw \$15,$k11111,$k00001 + kshiftrw \$11,$k11111,$k11111 + kshiftlw \$1,$k00001,$k00010 + kshiftlw \$2,$k00001,$k00100 + kshiftlw \$3,$k00001,$k01000 + kshiftlw \$4,$k00001,$k10000 + + #vmovdqa64 64*0(%r8),@Theta[0] + vmovdqa64 64*1(%r8),@Theta[1] + vmovdqa64 64*2(%r8),@Theta[2] + vmovdqa64 64*3(%r8),@Theta[3] + vmovdqa64 64*4(%r8),@Theta[4] + + vmovdqa64 64*5(%r8),@Rhotate1[0] + vmovdqa64 64*6(%r8),@Rhotate1[1] + vmovdqa64 64*7(%r8),@Rhotate1[2] + vmovdqa64 64*8(%r8),@Rhotate1[3] + vmovdqa64 64*9(%r8),@Rhotate1[4] + + vmovdqa64 64*10(%r8),@Rhotate0[0] + vmovdqa64 64*11(%r8),@Rhotate0[1] + vmovdqa64 64*12(%r8),@Rhotate0[2] + vmovdqa64 64*13(%r8),@Rhotate0[3] + vmovdqa64 64*14(%r8),@Rhotate0[4] + + vmovdqa64 64*15(%r8),@Pi0[0] + vmovdqa64 64*16(%r8),@Pi0[1] + vmovdqa64 64*17(%r8),@Pi0[2] + vmovdqa64 64*18(%r8),@Pi0[3] + vmovdqa64 64*19(%r8),@Pi0[4] + + vmovdqu64 40*0-96($A_flat),${A00}{$k11111}{z} + vpxorq @T[0],@T[0],@T[0] + vmovdqu64 40*1-96($A_flat),${A10}{$k11111}{z} + vmovdqu64 40*2-96($A_flat),${A20}{$k11111}{z} + vmovdqu64 40*3-96($A_flat),${A30}{$k11111}{z} + vmovdqu64 40*4-96($A_flat),${A40}{$k11111}{z} + + vmovdqa64 @T[0],0*64-128(%r9) # zero transfer area on stack + vmovdqa64 @T[0],1*64-128(%r9) + vmovdqa64 @T[0],2*64-128(%r9) + vmovdqa64 @T[0],3*64-128(%r9) + vmovdqa64 @T[0],4*64-128(%r9) + jmp .Loop_absorb_avx512 + +.align 32 +.Loop_absorb_avx512: + mov $bsz,%rax + sub $bsz,$len + jc .Ldone_absorb_avx512 + + shr \$3,%eax +___ +for(my $i=0; $i<25; $i++) { +$code.=<<___ + mov 8*$i-96($inp),%r8 + mov %r8,$A_jagged[$i]-128(%r9) + dec %eax + jz .Labsorved_avx512 +___ +} +$code.=<<___; +.Labsorved_avx512: + lea ($inp,$bsz),$inp + + vpxorq 64*0-128(%r9),$A00,$A00 + vpxorq 64*1-128(%r9),$A10,$A10 + vpxorq 64*2-128(%r9),$A20,$A20 + vpxorq 64*3-128(%r9),$A30,$A30 + vpxorq 64*4-128(%r9),$A40,$A40 + + call __KeccakF1600 + + jmp .Loop_absorb_avx512 + +.align 32 +.Ldone_absorb_avx512: + vmovdqu64 $A00,40*0-96($A_flat){$k11111} + vmovdqu64 $A10,40*1-96($A_flat){$k11111} + vmovdqu64 $A20,40*2-96($A_flat){$k11111} + vmovdqu64 $A30,40*3-96($A_flat){$k11111} + vmovdqu64 $A40,40*4-96($A_flat){$k11111} + + vzeroupper + + lea (%r11),%rsp + lea ($len,$bsz),%rax # return value + ret +.size SHA3_absorb,.-SHA3_absorb + +.globl SHA3_squeeze +.type SHA3_squeeze,\@function +.align 32 +SHA3_squeeze: + mov %rsp,%r11 + + lea 96($A_flat),$A_flat + cmp $bsz,$len + jbe .Lno_output_extension_avx512 + + lea theta_perm(%rip),%r8 + + kxnorw $k11111,$k11111,$k11111 + kshiftrw \$15,$k11111,$k00001 + kshiftrw \$11,$k11111,$k11111 + kshiftlw \$1,$k00001,$k00010 + kshiftlw \$2,$k00001,$k00100 + kshiftlw \$3,$k00001,$k01000 + kshiftlw \$4,$k00001,$k10000 + + #vmovdqa64 64*0(%r8),@Theta[0] + vmovdqa64 64*1(%r8),@Theta[1] + vmovdqa64 64*2(%r8),@Theta[2] + vmovdqa64 64*3(%r8),@Theta[3] + vmovdqa64 64*4(%r8),@Theta[4] + + vmovdqa64 64*5(%r8),@Rhotate1[0] + vmovdqa64 64*6(%r8),@Rhotate1[1] + vmovdqa64 64*7(%r8),@Rhotate1[2] + vmovdqa64 64*8(%r8),@Rhotate1[3] + vmovdqa64 64*9(%r8),@Rhotate1[4] + + vmovdqa64 64*10(%r8),@Rhotate0[0] + vmovdqa64 64*11(%r8),@Rhotate0[1] + vmovdqa64 64*12(%r8),@Rhotate0[2] + vmovdqa64 64*13(%r8),@Rhotate0[3] + vmovdqa64 64*14(%r8),@Rhotate0[4] + + vmovdqa64 64*15(%r8),@Pi0[0] + vmovdqa64 64*16(%r8),@Pi0[1] + vmovdqa64 64*17(%r8),@Pi0[2] + vmovdqa64 64*18(%r8),@Pi0[3] + vmovdqa64 64*19(%r8),@Pi0[4] + + vmovdqu64 40*0-96($A_flat),${A00}{$k11111}{z} + vmovdqu64 40*1-96($A_flat),${A10}{$k11111}{z} + vmovdqu64 40*2-96($A_flat),${A20}{$k11111}{z} + vmovdqu64 40*3-96($A_flat),${A30}{$k11111}{z} + vmovdqu64 40*4-96($A_flat),${A40}{$k11111}{z} + +.Lno_output_extension_avx512: + shr \$3,$bsz + lea -96($A_flat),%r9 + mov $bsz,%rax + jmp .Loop_squeeze_avx512 + +.align 32 +.Loop_squeeze_avx512: + cmp \$8,$len + jb .Ltail_squeeze_avx512 + + mov (%r9),%r8 + lea 8(%r9),%r9 + mov %r8,($out) + lea 8($out),$out + sub \$8,$len # len -= 8 + jz .Ldone_squeeze_avx512 + + sub \$1,%rax # bsz-- + jnz .Loop_squeeze_avx512 + + #vpermq @Theta[4],@Theta[4],@Theta[3] + #vpermq @Theta[3],@Theta[4],@Theta[2] + #vpermq @Theta[3],@Theta[3],@Theta[1] + + call __KeccakF1600 + + vmovdqu64 $A00,40*0-96($A_flat){$k11111} + vmovdqu64 $A10,40*1-96($A_flat){$k11111} + vmovdqu64 $A20,40*2-96($A_flat){$k11111} + vmovdqu64 $A30,40*3-96($A_flat){$k11111} + vmovdqu64 $A40,40*4-96($A_flat){$k11111} + + lea -96($A_flat),%r9 + mov $bsz,%rax + jmp .Loop_squeeze_avx512 + +.Ltail_squeeze_avx512: + mov $out,%rdi + mov %r9,%rsi + mov $len,%rcx + .byte 0xf3,0xa4 # rep movsb + +.Ldone_squeeze_avx512: + vzeroupper + + lea (%r11),%rsp + ret +.size SHA3_squeeze,.-SHA3_squeeze + +.align 64 +theta_perm: + .quad 0, 1, 2, 3, 4, 5, 6, 7 # [not used] + .quad 4, 0, 1, 2, 3, 5, 6, 7 + .quad 3, 4, 0, 1, 2, 5, 6, 7 + .quad 2, 3, 4, 0, 1, 5, 6, 7 + .quad 1, 2, 3, 4, 0, 5, 6, 7 + +rhotates1: + .quad 0, 44, 43, 21, 14, 0, 0, 0 # [0][0] [1][1] [2][2] [3][3] [4][4] + .quad 18, 1, 6, 25, 8, 0, 0, 0 # [4][0] [0][1] [1][2] [2][3] [3][4] + .quad 41, 2, 62, 55, 39, 0, 0, 0 # [3][0] [4][1] [0][2] [1][3] [2][4] + .quad 3, 45, 61, 28, 20, 0, 0, 0 # [2][0] [3][1] [4][2] [0][3] [1][4] + .quad 36, 10, 15, 56, 27, 0, 0, 0 # [1][0] [2][1] [3][2] [4][3] [0][4] + +rhotates0: + .quad 0, 1, 62, 28, 27, 0, 0, 0 + .quad 36, 44, 6, 55, 20, 0, 0, 0 + .quad 3, 10, 43, 25, 39, 0, 0, 0 + .quad 41, 45, 15, 21, 8, 0, 0, 0 + .quad 18, 2, 61, 56, 14, 0, 0, 0 + +pi0_perm: + .quad 0, 3, 1, 4, 2, 5, 6, 7 + .quad 1, 4, 2, 0, 3, 5, 6, 7 + .quad 2, 0, 3, 1, 4, 5, 6, 7 + .quad 3, 1, 4, 2, 0, 5, 6, 7 + .quad 4, 2, 0, 3, 1, 5, 6, 7 + + +iotas: + .quad 0x0000000000000001 + .quad 0x0000000000008082 + .quad 0x800000000000808a + .quad 0x8000000080008000 + .quad 0x000000000000808b + .quad 0x0000000080000001 + .quad 0x8000000080008081 + .quad 0x8000000000008009 + .quad 0x000000000000008a + .quad 0x0000000000000088 + .quad 0x0000000080008009 + .quad 0x000000008000000a + .quad 0x000000008000808b + .quad 0x800000000000008b + .quad 0x8000000000008089 + .quad 0x8000000000008003 + .quad 0x8000000000008002 + .quad 0x8000000000000080 + .quad 0x000000000000800a + .quad 0x800000008000000a + .quad 0x8000000080008081 + .quad 0x8000000000008080 + .quad 0x0000000080000001 + .quad 0x8000000080008008 + +.asciz "Keccak-1600 absorb and squeeze for AVX-512F, CRYPTOGAMS by " +___ + +$output=pop; +open STDOUT,">$output"; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-avx512vl.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-avx512vl.pl new file mode 100755 index 000000000..a21bb8615 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-avx512vl.pl @@ -0,0 +1,392 @@ +#!/usr/bin/env perl +# Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# Keccak-1600 for AVX512VL. +# +# December 2017. +# +# This is an adaptation of AVX2 module that reuses register data +# layout, but utilizes new 256-bit AVX512VL instructions. See AVX2 +# module for further information on layout. +# +######################################################################## +# Numbers are cycles per processed byte out of large message. +# +# r=1088(*) +# +# Skylake-X 6.4/+47% +# +# (*) Corresponds to SHA3-256. Percentage after slash is improvement +# coefficient in comparison to scalar keccak1600-x86_64.pl. + +# Digits in variables' names denote right-most coordinates: + +my ($A00, # [0][0] [0][0] [0][0] [0][0] # %ymm0 + $A01, # [0][4] [0][3] [0][2] [0][1] # %ymm1 + $A20, # [3][0] [1][0] [4][0] [2][0] # %ymm2 + $A31, # [2][4] [4][3] [1][2] [3][1] # %ymm3 + $A21, # [3][4] [1][3] [4][2] [2][1] # %ymm4 + $A41, # [1][4] [2][3] [3][2] [4][1] # %ymm5 + $A11) = # [4][4] [3][3] [2][2] [1][1] # %ymm6 + map("%ymm$_",(0..6)); + +# We also need to map the magic order into offsets within structure: + +my @A_jagged = ([0,0], [1,0], [1,1], [1,2], [1,3], # [0][0..4] + [2,2], [6,0], [3,1], [4,2], [5,3], # [1][0..4] + [2,0], [4,0], [6,1], [5,2], [3,3], # [2][0..4] + [2,3], [3,0], [5,1], [6,2], [4,3], # [3][0..4] + [2,1], [5,0], [4,1], [3,2], [6,3]); # [4][0..4] + @A_jagged = map(8*($$_[0]*4+$$_[1]), @A_jagged); # ... and now linear + +my @T = map("%ymm$_",(7..15)); +my ($C14,$C00,$D00,$D14) = @T[5..8]; +my ($R20,$R01,$R31,$R21,$R41,$R11) = map("%ymm$_",(16..21)); + +$code.=<<___; +.text + +.type __KeccakF1600,\@function +.align 32 +__KeccakF1600: + lea iotas(%rip),%r10 + mov \$24,%eax + jmp .Loop_avx512vl + +.align 32 +.Loop_avx512vl: + ######################################### Theta + vpshufd \$0b01001110,$A20,$C00 + vpxor $A31,$A41,$C14 + vpxor $A11,$A21,@T[2] + vpternlogq \$0x96,$A01,$T[2],$C14 # C[1..4] + + vpxor $A20,$C00,$C00 + vpermq \$0b01001110,$C00,@T[0] + + vpermq \$0b10010011,$C14,@T[4] + vprolq \$1,$C14,@T[1] # ROL64(C[1..4],1) + + vpermq \$0b00111001,@T[1],$D14 + vpxor @T[4],@T[1],$D00 + vpermq \$0b00000000,$D00,$D00 # D[0..0] = ROL64(C[1],1) ^ C[4] + + vpternlogq \$0x96,@T[0],$A00,$C00 # C[0..0] + vprolq \$1,$C00,@T[1] # ROL64(C[0..0],1) + + vpxor $D00,$A00,$A00 # ^= D[0..0] + + vpblendd \$0b11000000,@T[1],$D14,$D14 + vpblendd \$0b00000011,$C00,@T[4],@T[0] + + ######################################### Rho + Pi + pre-Chi shuffle + vpxor $D00,$A20,$A20 # ^= D[0..0] from Theta + vprolvq $R20,$A20,$A20 + + vpternlogq \$0x96,@T[0],$D14,$A31 # ^= D[1..4] from Theta + vprolvq $R31,$A31,$A31 + + vpternlogq \$0x96,@T[0],$D14,$A21 # ^= D[1..4] from Theta + vprolvq $R21,$A21,$A21 + + vpternlogq \$0x96,@T[0],$D14,$A41 # ^= D[1..4] from Theta + vprolvq $R41,$A41,$A41 + + vpermq \$0b10001101,$A20,@T[3] # $A20 -> future $A31 + vpermq \$0b10001101,$A31,@T[4] # $A31 -> future $A21 + vpternlogq \$0x96,@T[0],$D14,$A11 # ^= D[1..4] from Theta + vprolvq $R11,$A11,@T[1] # $A11 -> future $A01 + + vpermq \$0b00011011,$A21,@T[5] # $A21 -> future $A41 + vpermq \$0b01110010,$A41,@T[6] # $A41 -> future $A11 + vpternlogq \$0x96,@T[0],$D14,$A01 # ^= D[1..4] from Theta + vprolvq $R01,$A01,@T[2] # $A01 -> future $A20 + + ######################################### Chi + vpblendd \$0b00001100,@T[6],@T[2],$A31 # [4][4] [2][0] + vpblendd \$0b00001100,@T[2],@T[4],@T[8] # [4][0] [2][1] + vpblendd \$0b00001100,@T[4],@T[3],$A41 # [4][2] [2][4] + vpblendd \$0b00001100,@T[3],@T[2],@T[7] # [4][3] [2][0] + vpblendd \$0b00110000,@T[4],$A31,$A31 # [1][3] [4][4] [2][0] + vpblendd \$0b00110000,@T[5],@T[8],@T[8] # [1][4] [4][0] [2][1] + vpblendd \$0b00110000,@T[2],$A41,$A41 # [1][0] [4][2] [2][4] + vpblendd \$0b00110000,@T[6],@T[7],@T[7] # [1][1] [4][3] [2][0] + vpblendd \$0b11000000,@T[5],$A31,$A31 # [3][2] [1][3] [4][4] [2][0] + vpblendd \$0b11000000,@T[6],@T[8],@T[8] # [3][3] [1][4] [4][0] [2][1] + vpblendd \$0b11000000,@T[6],$A41,$A41 # [3][3] [1][0] [4][2] [2][4] + vpblendd \$0b11000000,@T[4],@T[7],@T[7] # [3][4] [1][1] [4][3] [2][0] + vpternlogq \$0xC6,@T[8],@T[3],$A31 # [3][1] [1][2] [4][3] [2][4] + vpternlogq \$0xC6,@T[7],@T[5],$A41 # [3][2] [1][4] [4][1] [2][3] + + vpsrldq \$8,@T[1],@T[0] + vpandn @T[0],@T[1],@T[0] # tgting [0][0] [0][0] [0][0] [0][0] + + vpblendd \$0b00001100,@T[2],@T[5],$A11 # [4][0] [2][3] + vpblendd \$0b00001100,@T[5],@T[3],@T[8] # [4][1] [2][4] + vpblendd \$0b00110000,@T[3],$A11,$A11 # [1][2] [4][0] [2][3] + vpblendd \$0b00110000,@T[4],@T[8],@T[8] # [1][3] [4][1] [2][4] + vpblendd \$0b11000000,@T[4],$A11,$A11 # [3][4] [1][2] [4][0] [2][3] + vpblendd \$0b11000000,@T[2],@T[8],@T[8] # [3][0] [1][3] [4][1] [2][4] + vpternlogq \$0xC6,@T[8],@T[6],$A11 # [3][3] [1][1] [4][4] [2][2] + + vpermq \$0b00011110,@T[1],$A21 # [0][1] [0][2] [0][4] [0][3] + vpblendd \$0b00110000,$A00,$A21,@T[8] # [0][1] [0][0] [0][4] [0][3] + vpermq \$0b00111001,@T[1],$A01 # [0][1] [0][4] [0][3] [0][2] + vpblendd \$0b11000000,$A00,$A01,$A01 # [0][0] [0][4] [0][3] [0][2] + + vpblendd \$0b00001100,@T[5],@T[4],$A20 # [4][1] [2][1] + vpblendd \$0b00001100,@T[4],@T[6],@T[7] # [4][2] [2][2] + vpblendd \$0b00110000,@T[6],$A20,$A20 # [1][1] [4][1] [2][1] + vpblendd \$0b00110000,@T[3],@T[7],@T[7] # [1][2] [4][2] [2][2] + vpblendd \$0b11000000,@T[3],$A20,$A20 # [3][1] [1][1] [4][1] [2][1] + vpblendd \$0b11000000,@T[5],@T[7],@T[7] # [3][2] [1][2] [4][2] [2][2] + vpternlogq \$0xC6,@T[7],@T[2],$A20 # [3][0] [1][0] [4][0] [2][0] + + vpermq \$0b00000000,@T[0],@T[0] # [0][0] [0][0] [0][0] [0][0] + vpermq \$0b00011011,$A31,$A31 # post-Chi shuffle + vpermq \$0b10001101,$A41,$A41 + vpermq \$0b01110010,$A11,$A11 + + vpblendd \$0b00001100,@T[3],@T[6],$A21 # [4][3] [2][2] + vpblendd \$0b00001100,@T[6],@T[5],@T[7] # [4][4] [2][3] + vpblendd \$0b00110000,@T[5],$A21,$A21 # [1][4] [4][3] [2][2] + vpblendd \$0b00110000,@T[2],@T[7],@T[7] # [1][0] [4][4] [2][3] + vpblendd \$0b11000000,@T[2],$A21,$A21 # [3][0] [1][4] [4][3] [2][2] + vpblendd \$0b11000000,@T[3],@T[7],@T[7] # [3][1] [1][0] [4][4] [2][3] + + vpternlogq \$0xC6,@T[8],@T[1],$A01 # [0][4] [0][3] [0][2] [0][1] + vpternlogq \$0xC6,@T[7],@T[4],$A21 # [3][4] [1][3] [4][2] [2][1] + + ######################################### Iota + vpternlogq \$0x96,(%r10),@T[0],$A00 + lea 32(%r10),%r10 + + dec %eax + jnz .Loop_avx512vl + + ret +.size __KeccakF1600,.-__KeccakF1600 +___ +my ($A_flat,$inp,$len,$bsz) = ("%rdi","%rsi","%rdx","%rcx"); +my $out = $inp; # in squeeze + +$code.=<<___; +.globl SHA3_absorb +.type SHA3_absorb,\@function +.align 32 +SHA3_absorb: + mov %rsp,%r11 + + lea -240(%rsp),%rsp + and \$-32,%rsp + + lea 96($A_flat),$A_flat + lea 96($inp),$inp + lea 96(%rsp),%r10 + lea rhotates_left(%rip),%r8 + + vzeroupper + + vpbroadcastq -96($A_flat),$A00 # load A[5][5] + vmovdqu 8+32*0-96($A_flat),$A01 + vmovdqu 8+32*1-96($A_flat),$A20 + vmovdqu 8+32*2-96($A_flat),$A31 + vmovdqu 8+32*3-96($A_flat),$A21 + vmovdqu 8+32*4-96($A_flat),$A41 + vmovdqu 8+32*5-96($A_flat),$A11 + + vmovdqa64 0*32(%r8),$R20 # load "rhotate" indices + vmovdqa64 1*32(%r8),$R01 + vmovdqa64 2*32(%r8),$R31 + vmovdqa64 3*32(%r8),$R21 + vmovdqa64 4*32(%r8),$R41 + vmovdqa64 5*32(%r8),$R11 + + vpxor @T[0],@T[0],@T[0] + vmovdqa @T[0],32*2-96(%r10) # zero transfer area on stack + vmovdqa @T[0],32*3-96(%r10) + vmovdqa @T[0],32*4-96(%r10) + vmovdqa @T[0],32*5-96(%r10) + vmovdqa @T[0],32*6-96(%r10) + +.Loop_absorb_avx512vl: + mov $bsz,%rax + sub $bsz,$len + jc .Ldone_absorb_avx512vl + + shr \$3,%eax + vpbroadcastq 0-96($inp),@T[0] + vmovdqu 8-96($inp),@T[1] + sub \$4,%eax +___ +for(my $i=5; $i<25; $i++) { +$code.=<<___ + dec %eax + jz .Labsorved_avx512vl + mov 8*$i-96($inp),%r8 + mov %r8,$A_jagged[$i]-96(%r10) +___ +} +$code.=<<___; +.Labsorved_avx512vl: + lea ($inp,$bsz),$inp + + vpxor @T[0],$A00,$A00 + vpxor @T[1],$A01,$A01 + vpxor 32*2-96(%r10),$A20,$A20 + vpxor 32*3-96(%r10),$A31,$A31 + vpxor 32*4-96(%r10),$A21,$A21 + vpxor 32*5-96(%r10),$A41,$A41 + vpxor 32*6-96(%r10),$A11,$A11 + + call __KeccakF1600 + + lea 96(%rsp),%r10 + jmp .Loop_absorb_avx512vl + +.Ldone_absorb_avx512vl: + vmovq %xmm0,-96($A_flat) + vmovdqu $A01,8+32*0-96($A_flat) + vmovdqu $A20,8+32*1-96($A_flat) + vmovdqu $A31,8+32*2-96($A_flat) + vmovdqu $A21,8+32*3-96($A_flat) + vmovdqu $A41,8+32*4-96($A_flat) + vmovdqu $A11,8+32*5-96($A_flat) + + vzeroupper + + lea (%r11),%rsp + lea ($len,$bsz),%rax # return value + ret +.size SHA3_absorb,.-SHA3_absorb + +.globl SHA3_squeeze +.type SHA3_squeeze,\@function +.align 32 +SHA3_squeeze: + mov %rsp,%r11 + + lea 96($A_flat),$A_flat + lea rhotates_left(%rip),%r8 + shr \$3,$bsz + + vzeroupper + + vpbroadcastq -96($A_flat),$A00 + vpxor @T[0],@T[0],@T[0] + vmovdqu 8+32*0-96($A_flat),$A01 + vmovdqu 8+32*1-96($A_flat),$A20 + vmovdqu 8+32*2-96($A_flat),$A31 + vmovdqu 8+32*3-96($A_flat),$A21 + vmovdqu 8+32*4-96($A_flat),$A41 + vmovdqu 8+32*5-96($A_flat),$A11 + + vmovdqa64 0*32(%r8),$R20 # load "rhotate" indices + vmovdqa64 1*32(%r8),$R01 + vmovdqa64 2*32(%r8),$R31 + vmovdqa64 3*32(%r8),$R21 + vmovdqa64 4*32(%r8),$R41 + vmovdqa64 5*32(%r8),$R11 + + mov $bsz,%rax + +.Loop_squeeze_avx512vl: + mov @A_jagged[$i]-96($A_flat),%r8 +___ +for (my $i=0; $i<25; $i++) { +$code.=<<___; + sub \$8,$len + jc .Ltail_squeeze_avx512vl + mov %r8,($out) + lea 8($out),$out + je .Ldone_squeeze_avx512vl + dec %eax + je .Lextend_output_avx512vl + mov @A_jagged[$i+1]-120($A_flat),%r8 +___ +} +$code.=<<___; +.Lextend_output_avx512vl: + call __KeccakF1600 + + vmovq %xmm0,-96($A_flat) + vmovdqu $A01,8+32*0-96($A_flat) + vmovdqu $A20,8+32*1-96($A_flat) + vmovdqu $A31,8+32*2-96($A_flat) + vmovdqu $A21,8+32*3-96($A_flat) + vmovdqu $A41,8+32*4-96($A_flat) + vmovdqu $A11,8+32*5-96($A_flat) + + mov $bsz,%rax + jmp .Loop_squeeze_avx512vl + + +.Ltail_squeeze_avx512vl: + add \$8,$len +.Loop_tail_avx512vl: + mov %r8b,($out) + lea 1($out),$out + shr \$8,%r8 + dec $len + jnz .Loop_tail_avx512vl + +.Ldone_squeeze_avx512vl: + vzeroupper + + lea (%r11),%rsp + ret +.size SHA3_squeeze,.-SHA3_squeeze + +.align 64 +rhotates_left: + .quad 3, 18, 36, 41 # [2][0] [4][0] [1][0] [3][0] + .quad 1, 62, 28, 27 # [0][1] [0][2] [0][3] [0][4] + .quad 45, 6, 56, 39 # [3][1] [1][2] [4][3] [2][4] + .quad 10, 61, 55, 8 # [2][1] [4][2] [1][3] [3][4] + .quad 2, 15, 25, 20 # [4][1] [3][2] [2][3] [1][4] + .quad 44, 43, 21, 14 # [1][1] [2][2] [3][3] [4][4] +iotas: + .quad 0x0000000000000001, 0x0000000000000001, 0x0000000000000001, 0x0000000000000001 + .quad 0x0000000000008082, 0x0000000000008082, 0x0000000000008082, 0x0000000000008082 + .quad 0x800000000000808a, 0x800000000000808a, 0x800000000000808a, 0x800000000000808a + .quad 0x8000000080008000, 0x8000000080008000, 0x8000000080008000, 0x8000000080008000 + .quad 0x000000000000808b, 0x000000000000808b, 0x000000000000808b, 0x000000000000808b + .quad 0x0000000080000001, 0x0000000080000001, 0x0000000080000001, 0x0000000080000001 + .quad 0x8000000080008081, 0x8000000080008081, 0x8000000080008081, 0x8000000080008081 + .quad 0x8000000000008009, 0x8000000000008009, 0x8000000000008009, 0x8000000000008009 + .quad 0x000000000000008a, 0x000000000000008a, 0x000000000000008a, 0x000000000000008a + .quad 0x0000000000000088, 0x0000000000000088, 0x0000000000000088, 0x0000000000000088 + .quad 0x0000000080008009, 0x0000000080008009, 0x0000000080008009, 0x0000000080008009 + .quad 0x000000008000000a, 0x000000008000000a, 0x000000008000000a, 0x000000008000000a + .quad 0x000000008000808b, 0x000000008000808b, 0x000000008000808b, 0x000000008000808b + .quad 0x800000000000008b, 0x800000000000008b, 0x800000000000008b, 0x800000000000008b + .quad 0x8000000000008089, 0x8000000000008089, 0x8000000000008089, 0x8000000000008089 + .quad 0x8000000000008003, 0x8000000000008003, 0x8000000000008003, 0x8000000000008003 + .quad 0x8000000000008002, 0x8000000000008002, 0x8000000000008002, 0x8000000000008002 + .quad 0x8000000000000080, 0x8000000000000080, 0x8000000000000080, 0x8000000000000080 + .quad 0x000000000000800a, 0x000000000000800a, 0x000000000000800a, 0x000000000000800a + .quad 0x800000008000000a, 0x800000008000000a, 0x800000008000000a, 0x800000008000000a + .quad 0x8000000080008081, 0x8000000080008081, 0x8000000080008081, 0x8000000080008081 + .quad 0x8000000000008080, 0x8000000000008080, 0x8000000000008080, 0x8000000000008080 + .quad 0x0000000080000001, 0x0000000080000001, 0x0000000080000001, 0x0000000080000001 + .quad 0x8000000080008008, 0x8000000080008008, 0x8000000080008008, 0x8000000080008008 + +.asciz "Keccak-1600 absorb and squeeze for AVX512VL, CRYPTOGAMS by " +___ + +$output=pop; +open STDOUT,">$output"; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-c64x.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-c64x.pl new file mode 100755 index 000000000..b00af9af9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-c64x.pl @@ -0,0 +1,885 @@ +#!/usr/bin/env perl +# Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# [ABI- and endian-neutral] Keccak-1600 for C64x. +# +# June 2017. +# +# This is straightforward KECCAK_1X_ALT variant (see sha/keccak1600.c) +# with bit interleaving. 64-bit values are simply split between A- and +# B-files, with A-file holding least significant halves. This works +# out perfectly, because all operations including cross-communications +# [in rotate operations] are always complementary. Performance is +# [incredible for a 32-bit processor] 10.9 cycles per processed byte +# for r=1088, which corresponds to SHA3-256. This is >15x faster than +# compiler-generated KECCAK_1X_ALT code, and >10x than other variants. +# On average processor ends up issuing ~4.5 instructions per cycle... + +my @A = map([ $_, ($_+1), ($_+2), ($_+3), ($_+4) ], (5,10,16,21,26)); + $A[1][4] = 31; # B14 is reserved, A14 is used as iota[] + ($A[3][0],$A[4][1]) = ($A[4][1],$A[3][0]); +my @C = (0..4,$A[3][0],$A[4][0]); +my $iotas = "A14"; + +my @rhotates = ([ 0, 1, 62, 28, 27 ], + [ 36, 44, 6, 55, 20 ], + [ 3, 10, 43, 25, 39 ], + [ 41, 45, 15, 21, 8 ], + [ 18, 2, 61, 56, 14 ]); + +sub ROL64 { + my ($src,$rot,$dst,$p) = @_; + + if ($rot&1) { +$code.=<<___; +$p ROTL B$src,$rot/2+1,A$dst +|| ROTL A$src,$rot/2, B$dst +___ + } else { +$code.=<<___; +$p ROTL A$src,$rot/2,A$dst +|| ROTL B$src,$rot/2,B$dst +___ + } +} + +######################################################################## +# Stack frame layout +# +# SP--->+------+------+ +# | | | +# +1--->+------+------+<- -9 below 4 slots are used by KeccakF1600_int +# | | | +# +2--->+------+------+<- -8 +# | | | +# +3--->+------+------+<- -7 +# | A2 | A3 | A3:A2 are preserved by KeccakF1600_int +# +4--->+------+------+<- -6 +# | B2 | B3 | B3:B2 are preserved by KeccakF1600_int +# +5--->+------+------+<- -5 below is ABI-compliant layout +# | A10 | A11 | +# +6--->+------+------+<- -4 +# | A12 | A13 | +# +7--->+------+------+<- -3 +# | A14 | B3 | +# +8--->+------+------+<- -2 +# | B10 | B11 | +# +9--->+------+------+<- -1 +# | B12 | B13 | +# +------+------+<---FP +# | A15 | +# +------+-- + +$code.=<<___; + .text + + .if .ASSEMBLER_VERSION<7000000 + .asg 0,__TI_EABI__ + .endif + .if __TI_EABI__ + .nocmp + .asg KeccakF1600,_KeccakF1600 + .asg SHA3_absorb,_SHA3_absorb + .asg SHA3_squeeze,_SHA3_squeeze + .endif + + .asg B3,RA + .asg A15,FP + .asg B15,SP + + .align 32 +_KeccakF1600_int: + .asmfunc + STDW A3:A2,*FP[-7] +|| STDW B3:B2,*SP[4] +_KeccakF1600_cheat: + .if __TI_EABI__ + ADDKPC _KeccakF1600_int,B0 +|| MVKL \$PCR_OFFSET(iotas,_KeccakF1600_int),$iotas + MVKH \$PCR_OFFSET(iotas,_KeccakF1600_int),$iotas + .else + ADDKPC _KeccakF1600_int,B0 +|| MVKL (iotas-_KeccakF1600_int),$iotas + MVKH (iotas-_KeccakF1600_int),$iotas + .endif + ADD B0,$iotas,$iotas +loop?: + XOR A$A[0][2],A$A[1][2],A$C[2] ; Theta +|| XOR B$A[0][2],B$A[1][2],B$C[2] +|| XOR A$A[0][3],A$A[1][3],A$C[3] +|| XOR B$A[0][3],B$A[1][3],B$C[3] +|| XOR A$A[0][0],A$A[1][0],A$C[0] +|| XOR B$A[0][0],B$A[1][0],B$C[0] + XOR A$A[2][2],A$C[2],A$C[2] +|| XOR B$A[2][2],B$C[2],B$C[2] +|| XOR A$A[2][3],A$C[3],A$C[3] +|| XOR B$A[2][3],B$C[3],B$C[3] +|| XOR A$A[2][0],A$C[0],A$C[0] +|| XOR B$A[2][0],B$C[0],B$C[0] + XOR A$A[3][2],A$C[2],A$C[2] +|| XOR B$A[3][2],B$C[2],B$C[2] +|| XOR A$A[3][3],A$C[3],A$C[3] +|| XOR B$A[3][3],B$C[3],B$C[3] +|| XOR A$A[3][0],A$C[0],A$C[0] +|| XOR B$A[3][0],B$C[0],B$C[0] + XOR A$A[4][2],A$C[2],A$C[2] +|| XOR B$A[4][2],B$C[2],B$C[2] +|| XOR A$A[4][3],A$C[3],A$C[3] +|| XOR B$A[4][3],B$C[3],B$C[3] +|| XOR A$A[4][0],A$C[0],A$C[0] +|| XOR B$A[4][0],B$C[0],B$C[0] + XOR A$A[0][4],A$A[1][4],A$C[4] +|| XOR B$A[0][4],B$A[1][4],B$C[4] +|| XOR A$A[0][1],A$A[1][1],A$C[1] +|| XOR B$A[0][1],B$A[1][1],B$C[1] +|| STDW A$A[3][0]:A$A[4][0],*SP[1] ; offload some data + STDW B$A[3][0]:B$A[4][0],*SP[2] +|| XOR A$A[2][4],A$C[4],A$C[4] +|| XOR B$A[2][4],B$C[4],B$C[4] +|| XOR A$A[2][1],A$C[1],A$C[1] +|| XOR B$A[2][1],B$C[1],B$C[1] +|| ROTL B$C[2],1,A$C[5] ; ROL64(C[2],1) +|| ROTL A$C[2],0,B$C[5] + XOR A$A[3][4],A$C[4],A$C[4] +|| XOR B$A[3][4],B$C[4],B$C[4] +|| XOR A$A[3][1],A$C[1],A$C[1] +|| XOR B$A[3][1],B$C[1],B$C[1] +|| ROTL B$C[3],1,A$C[6] ; ROL64(C[3],1) +|| ROTL A$C[3],0,B$C[6] + XOR A$A[4][4],A$C[4],A$C[4] +|| XOR B$A[4][4],B$C[4],B$C[4] +|| XOR A$A[4][1],A$C[1],A$C[1] +|| XOR B$A[4][1],B$C[1],B$C[1] +|| XOR A$C[0],A$C[5],A$C[5] ; C[0] ^ ROL64(C[2],1) +|| XOR B$C[0],B$C[5],B$C[5] + XOR A$C[5],A$A[0][1],A$A[0][1] +|| XOR B$C[5],B$A[0][1],B$A[0][1] +|| XOR A$C[5],A$A[1][1],A$A[1][1] +|| XOR B$C[5],B$A[1][1],B$A[1][1] +|| XOR A$C[5],A$A[2][1],A$A[2][1] +|| XOR B$C[5],B$A[2][1],B$A[2][1] + XOR A$C[5],A$A[3][1],A$A[3][1] +|| XOR B$C[5],B$A[3][1],B$A[3][1] +|| XOR A$C[5],A$A[4][1],A$A[4][1] +|| XOR B$C[5],B$A[4][1],B$A[4][1] +|| ROTL B$C[4],1,A$C[5] ; ROL64(C[4],1) +|| ROTL A$C[4],0,B$C[5] +|| XOR A$C[1],A$C[6],A$C[6] ; C[1] ^ ROL64(C[3],1) +|| XOR B$C[1],B$C[6],B$C[6] + XOR A$C[6],A$A[0][2],A$A[0][2] +|| XOR B$C[6],B$A[0][2],B$A[0][2] +|| XOR A$C[6],A$A[1][2],A$A[1][2] +|| XOR B$C[6],B$A[1][2],B$A[1][2] +|| XOR A$C[6],A$A[2][2],A$A[2][2] +|| XOR B$C[6],B$A[2][2],B$A[2][2] +|| ROTL B$C[1],1,A$C[1] ; ROL64(C[1],1) +|| ROTL A$C[1],0,B$C[1] + XOR A$C[6],A$A[3][2],A$A[3][2] +|| XOR B$C[6],B$A[3][2],B$A[3][2] +|| XOR A$C[6],A$A[4][2],A$A[4][2] +|| XOR B$C[6],B$A[4][2],B$A[4][2] +|| ROTL B$C[0],1,A$C[6] ; ROL64(C[0],1) +|| ROTL A$C[0],0,B$C[6] +|| XOR A$C[5],A$C[2],A$C[2] ; C[2] ^= ROL64(C[4],1) +|| XOR B$C[5],B$C[2],B$C[2] + XOR A$C[2],A$A[0][3],A$A[0][3] +|| XOR B$C[2],B$A[0][3],B$A[0][3] +|| XOR A$C[2],A$A[1][3],A$A[1][3] +|| XOR B$C[2],B$A[1][3],B$A[1][3] +|| XOR A$C[2],A$A[2][3],A$A[2][3] +|| XOR B$C[2],B$A[2][3],B$A[2][3] + XOR A$C[6],A$C[3],A$C[3] ; C[3] ^= ROL64(C[0],1) +|| XOR B$C[6],B$C[3],B$C[3] +|| LDDW *FP[-9],A$A[3][0]:A$A[4][0] ; restore offloaded data +|| LDDW *SP[2],B$A[3][0]:B$A[4][0] +|| XOR A$C[2],A$A[3][3],A$A[3][3] +|| XOR B$C[2],B$A[3][3],B$A[3][3] + XOR A$C[2],A$A[4][3],A$A[4][3] +|| XOR B$C[2],B$A[4][3],B$A[4][3] +|| XOR A$C[3],A$A[0][4],A$A[0][4] +|| XOR B$C[3],B$A[0][4],B$A[0][4] +|| XOR A$C[3],A$A[1][4],A$A[1][4] +|| XOR B$C[3],B$A[1][4],B$A[1][4] + XOR A$C[3],A$A[2][4],A$A[2][4] +|| XOR B$C[3],B$A[2][4],B$A[2][4] +|| XOR A$C[3],A$A[3][4],A$A[3][4] +|| XOR B$C[3],B$A[3][4],B$A[3][4] +|| XOR A$C[3],A$A[4][4],A$A[4][4] +|| XOR B$C[3],B$A[4][4],B$A[4][4] + XOR A$C[1],A$C[4],A$C[4] ; C[4] ^= ROL64(C[1],1) +|| XOR B$C[1],B$C[4],B$C[4] +|| MV A$A[0][1],A$C[1] ; Rho+Pi, "early start" +|| MV B$A[0][1],B$C[1] +___ + &ROL64 ($A[1][1],$rhotates[1][1],$A[0][1],"||"); +$code.=<<___; + XOR A$C[4],A$A[0][0],A$A[0][0] +|| XOR B$C[4],B$A[0][0],B$A[0][0] +|| XOR A$C[4],A$A[1][0],A$A[1][0] +|| XOR B$C[4],B$A[1][0],B$A[1][0] +|| MV A$A[0][3],A$C[3] +|| MV B$A[0][3],B$C[3] +___ + &ROL64 ($A[3][3],$rhotates[3][3],$A[0][3],"||"); +$code.=<<___; + XOR A$C[4],A$A[2][0],A$A[2][0] +|| XOR B$C[4],B$A[2][0],B$A[2][0] +|| XOR A$C[4],A$A[3][0],A$A[3][0] +|| XOR B$C[4],B$A[3][0],B$A[3][0] +|| MV A$A[0][2],A$C[2] +|| MV B$A[0][2],B$C[2] +___ + &ROL64 ($A[2][2],$rhotates[2][2],$A[0][2],"||"); +$code.=<<___; + XOR A$C[4],A$A[4][0],A$A[4][0] +|| XOR B$C[4],B$A[4][0],B$A[4][0] +|| MV A$A[0][4],A$C[4] +|| MV B$A[0][4],B$C[4] +___ + &ROL64 ($A[4][4],$rhotates[4][4],$A[0][4],"||"); + + &ROL64 ($A[1][4],$rhotates[1][4],$A[1][1]); +$code.=<<___; +|| LDW *${iotas}++[2],A$C[0] +___ + &ROL64 ($A[2][3],$rhotates[2][3],$A[2][2]); +$code.=<<___; +|| LDW *${iotas}[-1],B$C[0] +___ + &ROL64 ($A[3][2],$rhotates[3][2],$A[3][3]); + &ROL64 ($A[4][1],$rhotates[4][1],$A[4][4]); + + &ROL64 ($A[4][2],$rhotates[4][2],$A[1][4]); + &ROL64 ($A[3][4],$rhotates[3][4],$A[2][3]); + &ROL64 ($A[2][1],$rhotates[2][1],$A[3][2]); + &ROL64 ($A[1][3],$rhotates[1][3],$A[4][1]); + + &ROL64 ($A[2][4],$rhotates[2][4],$A[4][2]); + &ROL64 ($A[4][3],$rhotates[4][3],$A[3][4]); + &ROL64 ($A[1][2],$rhotates[1][2],$A[2][1]); + &ROL64 ($A[3][1],$rhotates[3][1],$A[1][3]); + + &ROL64 ($A[4][0],$rhotates[4][0],$A[2][4]); + &ROL64 ($A[3][0],$rhotates[3][0],$A[4][3]); + &ROL64 ($A[2][0],$rhotates[2][0],$A[1][2]); + &ROL64 ($A[1][0],$rhotates[1][0],$A[3][1]); + + #&ROL64 ($C[3], $rhotates[0][3],$A[1][0]); # moved below + &ROL64 ($C[1], $rhotates[0][1],$A[2][0]); + &ROL64 ($C[4], $rhotates[0][4],$A[3][0]); + &ROL64 ($C[2], $rhotates[0][2],$A[4][0]); +$code.=<<___; +|| ANDN A$A[0][2],A$A[0][1],A$C[4] ; Chi+Iota +|| ANDN B$A[0][2],B$A[0][1],B$C[4] +|| ANDN A$A[0][3],A$A[0][2],A$C[1] +|| ANDN B$A[0][3],B$A[0][2],B$C[1] +|| ANDN A$A[0][4],A$A[0][3],A$C[2] +|| ANDN B$A[0][4],B$A[0][3],B$C[2] +___ + &ROL64 ($C[3], $rhotates[0][3],$A[1][0]); +$code.=<<___; +|| ANDN A$A[0][0],A$A[0][4],A$C[3] +|| ANDN B$A[0][0],B$A[0][4],B$C[3] +|| XOR A$C[4],A$A[0][0],A$A[0][0] +|| XOR B$C[4],B$A[0][0],B$A[0][0] +|| ANDN A$A[0][1],A$A[0][0],A$C[4] +|| ANDN B$A[0][1],B$A[0][0],B$C[4] + XOR A$C[1],A$A[0][1],A$A[0][1] +|| XOR B$C[1],B$A[0][1],B$A[0][1] +|| XOR A$C[2],A$A[0][2],A$A[0][2] +|| XOR B$C[2],B$A[0][2],B$A[0][2] +|| XOR A$C[3],A$A[0][3],A$A[0][3] +|| XOR B$C[3],B$A[0][3],B$A[0][3] + XOR A$C[4],A$A[0][4],A$A[0][4] +|| XOR B$C[4],B$A[0][4],B$A[0][4] +|| XOR A$C[0],A$A[0][0],A$A[0][0] ; A[0][0] ^= iotas[i++]; +|| XOR B$C[0],B$A[0][0],B$A[0][0] +|| EXTU $iotas,24,24,A0 ; A0 is A$C[0], as we done? + + ANDN A$A[1][2],A$A[1][1],A$C[4] +|| ANDN B$A[1][2],B$A[1][1],B$C[4] +|| ANDN A$A[1][3],A$A[1][2],A$C[1] +|| ANDN B$A[1][3],B$A[1][2],B$C[1] +|| ANDN A$A[1][4],A$A[1][3],A$C[2] +|| ANDN B$A[1][4],B$A[1][3],B$C[2] + ANDN A$A[1][0],A$A[1][4],A$C[3] +|| ANDN B$A[1][0],B$A[1][4],B$C[3] +|| XOR A$C[4],A$A[1][0],A$A[1][0] +|| XOR B$C[4],B$A[1][0],B$A[1][0] +|| ANDN A$A[1][1],A$A[1][0],A$C[4] +|| ANDN B$A[1][1],B$A[1][0],B$C[4] + XOR A$C[1],A$A[1][1],A$A[1][1] +|| XOR B$C[1],B$A[1][1],B$A[1][1] +|| XOR A$C[2],A$A[1][2],A$A[1][2] +|| XOR B$C[2],B$A[1][2],B$A[1][2] +|| XOR A$C[3],A$A[1][3],A$A[1][3] +|| XOR B$C[3],B$A[1][3],B$A[1][3] + XOR A$C[4],A$A[1][4],A$A[1][4] +|| XOR B$C[4],B$A[1][4],B$A[1][4] + +|| ANDN A$A[2][2],A$A[2][1],A$C[4] +|| ANDN B$A[2][2],B$A[2][1],B$C[4] +|| ANDN A$A[2][3],A$A[2][2],A$C[1] +|| ANDN B$A[2][3],B$A[2][2],B$C[1] + ANDN A$A[2][4],A$A[2][3],A$C[2] +|| ANDN B$A[2][4],B$A[2][3],B$C[2] +|| ANDN A$A[2][0],A$A[2][4],A$C[3] +|| ANDN B$A[2][0],B$A[2][4],B$C[3] +|| XOR A$C[4],A$A[2][0],A$A[2][0] +|| XOR B$C[4],B$A[2][0],B$A[2][0] + ANDN A$A[2][1],A$A[2][0],A$C[4] +|| ANDN B$A[2][1],B$A[2][0],B$C[4] +|| XOR A$C[1],A$A[2][1],A$A[2][1] +|| XOR B$C[1],B$A[2][1],B$A[2][1] +|| XOR A$C[2],A$A[2][2],A$A[2][2] +|| XOR B$C[2],B$A[2][2],B$A[2][2] + XOR A$C[3],A$A[2][3],A$A[2][3] +|| XOR B$C[3],B$A[2][3],B$A[2][3] +|| XOR A$C[4],A$A[2][4],A$A[2][4] +|| XOR B$C[4],B$A[2][4],B$A[2][4] + + ANDN A$A[3][2],A$A[3][1],A$C[4] +|| ANDN B$A[3][2],B$A[3][1],B$C[4] +|| ANDN A$A[3][3],A$A[3][2],A$C[1] +|| ANDN B$A[3][3],B$A[3][2],B$C[1] +|| ANDN A$A[3][4],A$A[3][3],A$C[2] +|| ANDN B$A[3][4],B$A[3][3],B$C[2] + ANDN A$A[3][0],A$A[3][4],A$C[3] +|| ANDN B$A[3][0],B$A[3][4],B$C[3] +|| XOR A$C[4],A$A[3][0],A$A[3][0] +|| XOR B$C[4],B$A[3][0],B$A[3][0] +|| ANDN A$A[3][1],A$A[3][0],A$C[4] +|| ANDN B$A[3][1],B$A[3][0],B$C[4] + XOR A$C[1],A$A[3][1],A$A[3][1] +|| XOR B$C[1],B$A[3][1],B$A[3][1] +|| XOR A$C[2],A$A[3][2],A$A[3][2] +|| XOR B$C[2],B$A[3][2],B$A[3][2] +|| XOR A$C[3],A$A[3][3],A$A[3][3] +||[A0] BNOP loop? + XOR B$C[3],B$A[3][3],B$A[3][3] +|| XOR A$C[4],A$A[3][4],A$A[3][4] +|| XOR B$C[4],B$A[3][4],B$A[3][4] +||[!A0] LDDW *FP[-7],A3:A2 +||[!A0] LDDW *SP[4], RA:B2 + + ANDN A$A[4][2],A$A[4][1],A$C[4] +|| ANDN B$A[4][2],B$A[4][1],B$C[4] +|| ANDN A$A[4][3],A$A[4][2],A$C[1] +|| ANDN B$A[4][3],B$A[4][2],B$C[1] +|| ANDN A$A[4][4],A$A[4][3],A$C[2] +|| ANDN B$A[4][4],B$A[4][3],B$C[2] + ANDN A$A[4][0],A$A[4][4],A$C[3] +|| ANDN B$A[4][0],B$A[4][4],B$C[3] +|| XOR A$C[4],A$A[4][0],A$A[4][0] +|| XOR B$C[4],B$A[4][0],B$A[4][0] +|| ANDN A$A[4][1],A$A[4][0],A$C[4] +|| ANDN B$A[4][1],B$A[4][0],B$C[4] + XOR A$C[1],A$A[4][1],A$A[4][1] +|| XOR B$C[1],B$A[4][1],B$A[4][1] +|| XOR A$C[2],A$A[4][2],A$A[4][2] +|| XOR B$C[2],B$A[4][2],B$A[4][2] +|| XOR A$C[3],A$A[4][3],A$A[4][3] +|| XOR B$C[3],B$A[4][3],B$A[4][3] + XOR A$C[4],A$A[4][4],A$A[4][4] +|| XOR B$C[4],B$A[4][4],B$A[4][4] +;;===== branch to loop? is taken here + + BNOP RA,5 + .endasmfunc + + .newblock + .global _KeccakF1600 + .align 32 +_KeccakF1600: + .asmfunc stack_usage(80) + STW FP,*SP--(80) ; save frame pointer +|| MV SP,FP + STDW B13:B12,*SP[9] +|| STDW A13:A12,*FP[-4] + STDW B11:B10,*SP[8] +|| STDW A11:A10,*FP[-5] + STW RA, *SP[15] +|| STW A14,*FP[-6] +|| MV A4,A2 +|| ADD 4,A4,B2 + + LDW *A2++[2],A$A[0][0] ; load A[5][5] +|| LDW *B2++[2],B$A[0][0] + LDW *A2++[2],A$A[0][1] +|| LDW *B2++[2],B$A[0][1] + LDW *A2++[2],A$A[0][2] +|| LDW *B2++[2],B$A[0][2] + LDW *A2++[2],A$A[0][3] +|| LDW *B2++[2],B$A[0][3] + LDW *A2++[2],A$A[0][4] +|| LDW *B2++[2],B$A[0][4] + + LDW *A2++[2],A$A[1][0] +|| LDW *B2++[2],B$A[1][0] + LDW *A2++[2],A$A[1][1] +|| LDW *B2++[2],B$A[1][1] + LDW *A2++[2],A$A[1][2] +|| LDW *B2++[2],B$A[1][2] + LDW *A2++[2],A$A[1][3] +|| LDW *B2++[2],B$A[1][3] + LDW *A2++[2],A$A[1][4] +|| LDW *B2++[2],B$A[1][4] + + LDW *A2++[2],A$A[2][0] +|| LDW *B2++[2],B$A[2][0] + LDW *A2++[2],A$A[2][1] +|| LDW *B2++[2],B$A[2][1] + LDW *A2++[2],A$A[2][2] +|| LDW *B2++[2],B$A[2][2] + LDW *A2++[2],A$A[2][3] +|| LDW *B2++[2],B$A[2][3] + LDW *A2++[2],A$A[2][4] +|| LDW *B2++[2],B$A[2][4] + + LDW *A2++[2],A$A[3][0] +|| LDW *B2++[2],B$A[3][0] + LDW *A2++[2],A$A[3][1] +|| LDW *B2++[2],B$A[3][1] + LDW *A2++[2],A$A[3][2] +|| LDW *B2++[2],B$A[3][2] + LDW *A2++[2],A$A[3][3] +|| LDW *B2++[2],B$A[3][3] + LDW *A2++[2],A$A[3][4] +|| LDW *B2++[2],B$A[3][4] +|| BNOP _KeccakF1600_int + + ADDKPC ret?,RA +|| LDW *A2++[2],A$A[4][0] +|| LDW *B2++[2],B$A[4][0] + LDW *A2++[2],A$A[4][1] +|| LDW *B2++[2],B$A[4][1] + LDW *A2++[2],A$A[4][2] +|| LDW *B2++[2],B$A[4][2] + LDW *A2++[2],A$A[4][3] +|| LDW *B2++[2],B$A[4][3] + LDW *A2,A$A[4][4] +|| LDW *B2,B$A[4][4] +|| ADDK -192,A2 ; rewind +|| ADDK -192,B2 + + .align 16 +ret?: + STW A$A[0][0],*A2++[2] ; store A[5][5] +|| STW B$A[0][0],*B2++[2] + STW A$A[0][1],*A2++[2] +|| STW B$A[0][1],*B2++[2] + STW A$A[0][2],*A2++[2] +|| STW B$A[0][2],*B2++[2] + STW A$A[0][3],*A2++[2] +|| STW B$A[0][3],*B2++[2] + STW A$A[0][4],*A2++[2] +|| STW B$A[0][4],*B2++[2] + + STW A$A[1][0],*A2++[2] +|| STW B$A[1][0],*B2++[2] + STW A$A[1][1],*A2++[2] +|| STW B$A[1][1],*B2++[2] + STW A$A[1][2],*A2++[2] +|| STW B$A[1][2],*B2++[2] + STW A$A[1][3],*A2++[2] +|| STW B$A[1][3],*B2++[2] + STW A$A[1][4],*A2++[2] +|| STW B$A[1][4],*B2++[2] + + STW A$A[2][0],*A2++[2] +|| STW B$A[2][0],*B2++[2] + STW A$A[2][1],*A2++[2] +|| STW B$A[2][1],*B2++[2] + STW A$A[2][2],*A2++[2] +|| STW B$A[2][2],*B2++[2] + STW A$A[2][3],*A2++[2] +|| STW B$A[2][3],*B2++[2] + STW A$A[2][4],*A2++[2] +|| STW B$A[2][4],*B2++[2] + + STW A$A[3][0],*A2++[2] +|| STW B$A[3][0],*B2++[2] + STW A$A[3][1],*A2++[2] +|| STW B$A[3][1],*B2++[2] + STW A$A[3][2],*A2++[2] +|| STW B$A[3][2],*B2++[2] + STW A$A[3][3],*A2++[2] +|| STW B$A[3][3],*B2++[2] + STW A$A[3][4],*A2++[2] +|| STW B$A[3][4],*B2++[2] + + LDW *SP[15],RA +|| LDW *FP[-6],A14 + + STW A$A[4][0],*A2++[2] +|| STW B$A[4][0],*B2++[2] + STW A$A[4][1],*A2++[2] +|| STW B$A[4][1],*B2++[2] + STW A$A[4][2],*A2++[2] +|| STW B$A[4][2],*B2++[2] + STW A$A[4][3],*A2++[2] +|| STW B$A[4][3],*B2++[2] + STW A$A[4][4],*A2 +|| STW B$A[4][4],*B2 +|| ADDK -192,A2 ; rewind + + MV A2,A4 ; return original A4 +|| LDDW *SP[8], B11:B10 +|| LDDW *FP[-5],A11:A10 + LDDW *SP[9], B13:B12 +|| LDDW *FP[-4],A13:A12 +|| BNOP RA + LDW *++SP(80),FP ; restore frame pointer + NOP 4 ; wait till FP is committed + .endasmfunc + + .newblock + .asg B2,BSZ + .asg A2,INP + .asg A3,LEN + .global _SHA3_absorb + .align 32 +_SHA3_absorb: + .asmfunc stack_usage(80) + STW FP,*SP--(80) ; save frame pointer +|| MV SP,FP + STDW B13:B12,*SP[9] +|| STDW A13:A12,*FP[-4] + STDW B11:B10,*SP[8] +|| STDW A11:A10,*FP[-5] + STW RA, *SP[15] +|| STW A14,*FP[-6] + + STW A4,*SP[1] ; save A[][] +|| MV B4,INP ; reassign arguments +|| MV A6,LEN +|| MV B6,BSZ +|| ADD 4,A4,B4 + + LDW *A4++[2],A$A[0][0] ; load A[5][5] +|| LDW *B4++[2],B$A[0][0] + LDW *A4++[2],A$A[0][1] +|| LDW *B4++[2],B$A[0][1] + LDW *A4++[2],A$A[0][2] +|| LDW *B4++[2],B$A[0][2] + LDW *A4++[2],A$A[0][3] +|| LDW *B4++[2],B$A[0][3] + LDW *A4++[2],A$A[0][4] +|| LDW *B4++[2],B$A[0][4] + + LDW *A4++[2],A$A[1][0] +|| LDW *B4++[2],B$A[1][0] + LDW *A4++[2],A$A[1][1] +|| LDW *B4++[2],B$A[1][1] + LDW *A4++[2],A$A[1][2] +|| LDW *B4++[2],B$A[1][2] + LDW *A4++[2],A$A[1][3] +|| LDW *B4++[2],B$A[1][3] + LDW *A4++[2],A$A[1][4] +|| LDW *B4++[2],B$A[1][4] + + LDW *A4++[2],A$A[2][0] +|| LDW *B4++[2],B$A[2][0] + LDW *A4++[2],A$A[2][1] +|| LDW *B4++[2],B$A[2][1] + LDW *A4++[2],A$A[2][2] +|| LDW *B4++[2],B$A[2][2] + LDW *A4++[2],A$A[2][3] +|| LDW *B4++[2],B$A[2][3] + LDW *A4++[2],A$A[2][4] +|| LDW *B4++[2],B$A[2][4] + + LDW *A4++[2],A$A[3][0] +|| LDW *B4++[2],B$A[3][0] + LDW *A4++[2],A$A[3][1] +|| LDW *B4++[2],B$A[3][1] + LDW *A4++[2],A$A[3][2] +|| LDW *B4++[2],B$A[3][2] + LDW *A4++[2],A$A[3][3] +|| LDW *B4++[2],B$A[3][3] + LDW *A4++[2],A$A[3][4] +|| LDW *B4++[2],B$A[3][4] + + LDW *A4++[2],A$A[4][0] +|| LDW *B4++[2],B$A[4][0] + LDW *A4++[2],A$A[4][1] +|| LDW *B4++[2],B$A[4][1] + LDW *A4++[2],A$A[4][2] +|| LDW *B4++[2],B$A[4][2] + LDW *A4++[2],A$A[4][3] +|| LDW *B4++[2],B$A[4][3] + LDW *A4,A$A[4][4] +|| LDW *B4,B$A[4][4] +|| ADDKPC loop?,RA + STDW RA:BSZ,*SP[4] + +loop?: + CMPLTU LEN,BSZ,A0 ; len < bsz? +|| SHRU BSZ,3,BSZ + [A0] BNOP ret? +||[A0] ZERO BSZ +||[A0] LDW *SP[1],A2 ; pull A[][] + [BSZ] LDNDW *INP++,A1:A0 +||[BSZ] SUB LEN,8,LEN +||[BSZ] SUB BSZ,1,BSZ + NOP 4 +___ +for ($y = 0; $y < 5; $y++) { + for ($x = 0; $x < ($y<4 ? 5 : 4); $x++) { +$code.=<<___; + .if .BIG_ENDIAN + SWAP2 A0,A1 +|| SWAP2 A1,A0 + SWAP4 A0,A0 + SWAP4 A1,A1 +||[!BSZ]BNOP _KeccakF1600_cheat +||[!BSZ]STDW LEN:INP,*SP[3] +|| DEAL A0,A0 + .else + [!BSZ]BNOP _KeccakF1600_cheat +||[!BSZ]STDW LEN:INP,*SP[3] +|| DEAL A0,A0 + .endif + [BSZ] LDNDW *INP++,A1:A0 +|| DEAL A1,A1 + [BSZ] SUB LEN,8,LEN +||[BSZ] SUB BSZ,1,BSZ + PACK2 A1,A0,A0 +|| PACKH2 A1,A0,A1 + XOR A0,A$A[$y][$x],A$A[$y][$x] + XOR A1,B$A[$y][$x],B$A[$y][$x] +___ + } +} +$code.=<<___; + .if .BIG_ENDIAN + SWAP2 A0,A1 +|| SWAP2 A1,A0 + SWAP4 A0,A0 + SWAP4 A1,A1 + .endif + BNOP _KeccakF1600_cheat +|| STDW LEN:INP,*SP[3] +|| DEAL A0,A0 + DEAL A1,A1 + NOP + PACK2 A1,A0,A0 +|| PACKH2 A1,A0,A1 + XOR A0,A$A[4][4],A$A[4][4] + XOR A1,B$A[4][4],B$A[4][4] + + .align 16 +ret?: + MV LEN,A4 ; return value +|| ADD 4,A2,B2 + + STW A$A[0][0],*A2++[2] ; store A[5][5] +|| STW B$A[0][0],*B2++[2] + STW A$A[0][1],*A2++[2] +|| STW B$A[0][1],*B2++[2] + STW A$A[0][2],*A2++[2] +|| STW B$A[0][2],*B2++[2] + STW A$A[0][3],*A2++[2] +|| STW B$A[0][3],*B2++[2] + STW A$A[0][4],*A2++[2] +|| STW B$A[0][4],*B2++[2] + + STW A$A[1][0],*A2++[2] +|| STW B$A[1][0],*B2++[2] + STW A$A[1][1],*A2++[2] +|| STW B$A[1][1],*B2++[2] + STW A$A[1][2],*A2++[2] +|| STW B$A[1][2],*B2++[2] + STW A$A[1][3],*A2++[2] +|| STW B$A[1][3],*B2++[2] + STW A$A[1][4],*A2++[2] +|| STW B$A[1][4],*B2++[2] + + STW A$A[2][0],*A2++[2] +|| STW B$A[2][0],*B2++[2] + STW A$A[2][1],*A2++[2] +|| STW B$A[2][1],*B2++[2] + STW A$A[2][2],*A2++[2] +|| STW B$A[2][2],*B2++[2] + STW A$A[2][3],*A2++[2] +|| STW B$A[2][3],*B2++[2] + STW A$A[2][4],*A2++[2] +|| STW B$A[2][4],*B2++[2] + + LDW *SP[15],RA +|| LDW *FP[-6],A14 + + STW A$A[3][0],*A2++[2] +|| STW B$A[3][0],*B2++[2] + STW A$A[3][1],*A2++[2] +|| STW B$A[3][1],*B2++[2] + STW A$A[3][2],*A2++[2] +|| STW B$A[3][2],*B2++[2] + STW A$A[3][3],*A2++[2] +|| STW B$A[3][3],*B2++[2] + STW A$A[3][4],*A2++[2] +|| STW B$A[3][4],*B2++[2] + + LDDW *SP[8], B11:B10 +|| LDDW *FP[-5],A11:A10 + LDDW *SP[9], B13:B12 +|| LDDW *FP[-4],A13:A12 + BNOP RA +|| LDW *++SP(80),FP ; restore frame pointer + + STW A$A[4][0],*A2++[2] +|| STW B$A[4][0],*B2++[2] + STW A$A[4][1],*A2++[2] +|| STW B$A[4][1],*B2++[2] + STW A$A[4][2],*A2++[2] +|| STW B$A[4][2],*B2++[2] + STW A$A[4][3],*A2++[2] +|| STW B$A[4][3],*B2++[2] + STW A$A[4][4],*A2++[2] +|| STW B$A[4][4],*B2++[2] + .endasmfunc + + .newblock + .global _SHA3_squeeze + .asg A12,OUT + .asg A13,LEN + .asg A14,BSZ + .align 32 +_SHA3_squeeze: + .asmfunc stack_usage(24) + STW FP,*SP--(24) ; save frame pointer +|| MV SP,FP + STW RA, *SP[5] +|| STW A14,*FP[-2] + STDW A13:A12,*FP[-2] +|| MV B4,OUT ; reassign arguments + MV A6,LEN +|| MV B6,BSZ + +loop?: + LDW *SP[5],RA ; reload RA +|| SHRU BSZ,3,A1 +|| MV A4,A8 +|| ADD 4,A4,B8 +block?: + CMPLTU LEN,8,A0 ; len < 8? + [A0] BNOP tail? + LDW *A8++[2],A9 +|| LDW *B8++[2],B9 +|| SUB LEN,8,LEN ; len -= 8 + MV LEN,A0 +|| SUB A1,1,A1 ; bsz-- +|| NOP 4 + .if .BIG_ENDIAN + SWAP4 A9,A9 +|| SWAP4 B9,B9 + SWAP2 A9,A9 +|| SWAP2 B9,B9 + .endif + [!A0] BNOP ret? +||[!A0] ZERO A1 + PACK2 B9,A9,B7 +||[A1] BNOP block? + PACKH2 B9,A9,B9 +|| SHFL B7,B7 + SHFL B9,B9 + STNW B7,*OUT++ + STNW B9,*OUT++ + NOP + + BNOP _KeccakF1600,4 + ADDKPC loop?,RA + + .align 16 +tail?: + .if .BIG_ENDIAN + SWAP4 A9,A9 +|| SWAP4 B9,B9 + SWAP2 A9,A9 +|| SWAP2 B9,B9 + .endif + PACK2 B9,A9,B7 + PACKH2 B9,A9,B9 +|| SHFL B7,B7 + SHFL B9,B9 + + STB B7,*OUT++ +|| SHRU B7,8,B7 +|| ADD LEN,7,A0 + [A0] STB B7,*OUT++ +||[A0] SHRU B7,8,B7 +||[A0] SUB A0,1,A0 + [A0] STB B7,*OUT++ +||[A0] SHRU B7,8,B7 +||[A0] SUB A0,1,A0 + [A0] STB B7,*OUT++ +||[A0] SUB A0,1,A0 + [A0] STB B9,*OUT++ +||[A0] SHRU B9,8,B9 +||[A0] SUB A0,1,A0 + [A0] STB B9,*OUT++ +||[A0] SHRU B9,8,B9 +||[A0] SUB A0,1,A0 + [A0] STB B9,*OUT++ + +ret?: + LDDW *FP[-2],A13:A12 + BNOP RA +|| LDW *FP[-2],A14 + LDW *++SP(24),FP ; restore frame pointer + NOP 4 ; wait till FP is committed + .endasmfunc + + .if __TI_EABI__ + .sect ".text:sha_asm.const" + .else + .sect ".const:sha_asm" + .endif + .align 256 + .uword 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +iotas: + .uword 0x00000001, 0x00000000 + .uword 0x00000000, 0x00000089 + .uword 0x00000000, 0x8000008b + .uword 0x00000000, 0x80008080 + .uword 0x00000001, 0x0000008b + .uword 0x00000001, 0x00008000 + .uword 0x00000001, 0x80008088 + .uword 0x00000001, 0x80000082 + .uword 0x00000000, 0x0000000b + .uword 0x00000000, 0x0000000a + .uword 0x00000001, 0x00008082 + .uword 0x00000000, 0x00008003 + .uword 0x00000001, 0x0000808b + .uword 0x00000001, 0x8000000b + .uword 0x00000001, 0x8000008a + .uword 0x00000001, 0x80000081 + .uword 0x00000000, 0x80000081 + .uword 0x00000000, 0x80000008 + .uword 0x00000000, 0x00000083 + .uword 0x00000000, 0x80008003 + .uword 0x00000001, 0x80008088 + .uword 0x00000000, 0x80000088 + .uword 0x00000001, 0x00008000 + .uword 0x00000000, 0x80008082 + + .cstring "Keccak-1600 absorb and squeeze for C64x, CRYPTOGAMS by " + .align 4 +___ + +$output=pop; +open STDOUT,">$output"; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-mmx.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-mmx.pl new file mode 100755 index 000000000..c7685add7 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-mmx.pl @@ -0,0 +1,440 @@ +#!/usr/bin/env perl +# Copyright 2017 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# Keccak-1600 for x86 MMX. +# +# June 2017. +# +# Below code is KECCAK_2X implementation (see sha/keccak1600.c) with +# C[5] held in register bank and D[5] offloaded to memory. Though +# instead of actually unrolling the loop pair-wise I simply flip +# pointers to T[][] and A[][] and the end of round. Since number of +# rounds is even, last round writes to A[][] and everything works out. +# It's argued that MMX is the only code path meaningful to implement +# for x86. This is because non-MMX-capable processors is an extinct +# breed, and they as well can lurk executing compiler-generated code. +# For reference gcc-5.x-generated KECCAK_2X code takes 89 cycles per +# processed byte on Pentium. Which is fair result. But older compilers +# produce worse code. On the other hand one can wonder why not 128-bit +# SSE2? Well, SSE2 won't provide double improvement, rather far from +# that, if any at all on some processors, because it will take extra +# permutations and inter-bank data trasfers. Besides, contemporary +# CPUs are better off executing 64-bit code, and it makes lesser sense +# to invest into fancy 32-bit code. And the decision doesn't seem to +# be inadequate, if one compares below results to "64-bit platforms in +# 32-bit mode" SIMD data points available at +# http://keccak.noekeon.org/sw_performance.html. +# +######################################################################## +# Numbers are cycles per processed byte out of large message. +# +# r=1088(i) +# +# PIII 30/+150% +# Pentium M 27/+150% +# P4 40/+85% +# Core 2 19/+170% +# Sandy Bridge(ii) 18/+140% +# Atom 33/+180% +# Silvermont(ii) 30/+180% +# VIA Nano(ii) 43/+60% +# Sledgehammer(ii)(iii) 24/+130% +# +# (i) Corresponds to SHA3-256. Numbers after slash are improvement +# coefficients over KECCAK_2X [with bit interleave and lane +# complementing] position-independent *scalar* code generated +# by gcc-5.x. It's not exactly fair comparison, but it's a +# datapoint... +# (ii) 64-bit processor executing 32-bit code. +# (iii) Result is considered to be representative even for older AMD +# processors. + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +$output=pop; +open STDOUT,">$output"; + +&asm_init($ARGV[0],$ARGV[$#ARGV] eq "386"); + +my @C = map("mm$_",(0..4)); +my @T = map("mm$_",(5..7)); +my @A = map([ 8*$_-100, 8*($_+1)-100, 8*($_+2)-100, + 8*($_+3)-100, 8*($_+4)-100 ], (0,5,10,15,20)); +my @D = map(8*$_+4, (0..4)); +my @rhotates = ([ 0, 1, 62, 28, 27 ], + [ 36, 44, 6, 55, 20 ], + [ 3, 10, 43, 25, 39 ], + [ 41, 45, 15, 21, 8 ], + [ 18, 2, 61, 56, 14 ]); + +&static_label("iotas"); + +&function_begin_B("_KeccakF1600"); + &movq (@C[0],&QWP($A[4][0],"esi")); + &movq (@C[1],&QWP($A[4][1],"esi")); + &movq (@C[2],&QWP($A[4][2],"esi")); + &movq (@C[3],&QWP($A[4][3],"esi")); + &movq (@C[4],&QWP($A[4][4],"esi")); + + &mov ("ecx",24); # loop counter + &jmp (&label("loop")); + + &set_label("loop",16); + ######################################### Theta + &pxor (@C[0],&QWP($A[0][0],"esi")); + &pxor (@C[1],&QWP($A[0][1],"esi")); + &pxor (@C[2],&QWP($A[0][2],"esi")); + &pxor (@C[3],&QWP($A[0][3],"esi")); + &pxor (@C[4],&QWP($A[0][4],"esi")); + + &pxor (@C[0],&QWP($A[1][0],"esi")); + &pxor (@C[1],&QWP($A[1][1],"esi")); + &pxor (@C[2],&QWP($A[1][2],"esi")); + &pxor (@C[3],&QWP($A[1][3],"esi")); + &pxor (@C[4],&QWP($A[1][4],"esi")); + + &pxor (@C[0],&QWP($A[2][0],"esi")); + &pxor (@C[1],&QWP($A[2][1],"esi")); + &pxor (@C[2],&QWP($A[2][2],"esi")); + &pxor (@C[3],&QWP($A[2][3],"esi")); + &pxor (@C[4],&QWP($A[2][4],"esi")); + + &pxor (@C[2],&QWP($A[3][2],"esi")); + &pxor (@C[0],&QWP($A[3][0],"esi")); + &pxor (@C[1],&QWP($A[3][1],"esi")); + &pxor (@C[3],&QWP($A[3][3],"esi")); + &movq (@T[0],@C[2]); + &pxor (@C[4],&QWP($A[3][4],"esi")); + + &movq (@T[2],@C[2]); + &psrlq (@T[0],63); + &movq (@T[1],@C[0]); + &psllq (@T[2],1); + &pxor (@T[0],@C[0]); + &psrlq (@C[0],63); + &pxor (@T[0],@T[2]); + &psllq (@T[1],1); + &movq (@T[2],@C[1]); + &movq (&QWP(@D[1],"esp"),@T[0]); # D[1] = E[0] = ROL64(C[2], 1) ^ C[0]; + + &pxor (@T[1],@C[0]); + &psrlq (@T[2],63); + &pxor (@T[1],@C[3]); + &movq (@C[0],@C[1]); + &movq (&QWP(@D[4],"esp"),@T[1]); # D[4] = E[1] = ROL64(C[0], 1) ^ C[3]; + + &psllq (@C[0],1); + &pxor (@T[2],@C[4]); + &pxor (@C[0],@T[2]); + + &movq (@T[2],@C[3]); + &psrlq (@C[3],63); + &movq (&QWP(@D[0],"esp"),@C[0]); # D[0] = C[0] = ROL64(C[1], 1) ^ C[4]; + &psllq (@T[2],1); + &movq (@T[0],@C[4]); + &psrlq (@C[4],63); + &pxor (@C[1],@C[3]); + &psllq (@T[0],1); + &pxor (@C[1],@T[2]); + &pxor (@C[2],@C[4]); + &movq (&QWP(@D[2],"esp"),@C[1]); # D[2] = C[1] = ROL64(C[3], 1) ^ C[1]; + &pxor (@C[2],@T[0]); + + ######################################### first Rho(0) is special + &movq (@C[3],&QWP($A[3][3],"esi")); + &movq (&QWP(@D[3],"esp"),@C[2]); # D[3] = C[2] = ROL64(C[4], 1) ^ C[2]; + &pxor (@C[3],@C[2]); + &movq (@C[4],&QWP($A[4][4],"esi")); + &movq (@T[2],@C[3]); + &psrlq (@C[3],64-$rhotates[3][3]); + &pxor (@C[4],@T[1]); + &psllq (@T[2],$rhotates[3][3]); + &movq (@T[1],@C[4]); + &psrlq (@C[4],64-$rhotates[4][4]); + &por (@C[3],@T[2]); # C[3] = ROL64(A[3][3] ^ C[2], rhotates[3][3]); /* D[3] */ + &psllq (@T[1],$rhotates[4][4]); + + &movq (@C[2],&QWP($A[2][2],"esi")); + &por (@C[4],@T[1]); # C[4] = ROL64(A[4][4] ^ E[1], rhotates[4][4]); /* D[4] */ + &pxor (@C[2],@C[1]); + &movq (@C[1],&QWP($A[1][1],"esi")); + &movq (@T[1],@C[2]); + &psrlq (@C[2],64-$rhotates[2][2]); + &pxor (@C[1],&QWP(@D[1],"esp")); + &psllq (@T[1],$rhotates[2][2]); + + &movq (@T[2],@C[1]); + &psrlq (@C[1],64-$rhotates[1][1]); + &por (@C[2],@T[1]); # C[2] = ROL64(A[2][2] ^ C[1], rhotates[2][2]); /* D[2] */ + &psllq (@T[2],$rhotates[1][1]); + &pxor (@C[0],&QWP($A[0][0],"esi")); # /* rotate by 0 */ /* D[0] */ + &por (@C[1],@T[2]); # C[1] = ROL64(A[1][1] ^ D[1], rhotates[1][1]); + +sub Chi() { ######### regular Chi step + my ($y,$xrho) = @_; + + &movq (@T[0],@C[1]); + &movq (@T[1],@C[2]); + &pandn (@T[0],@C[2]); + &pandn (@C[2],@C[3]); + &pxor (@T[0],@C[0]); + &pxor (@C[2],@C[1]); + &pxor (@T[0],&QWP(0,"ebx")) if ($y == 0); + &lea ("ebx",&DWP(8,"ebx")) if ($y == 0); + + &movq (@T[2],@C[3]); + &movq (&QWP($A[$y][0],"edi"),@T[0]); # R[0][0] = C[0] ^ (~C[1] & C[2]) ^ iotas[i]; + &movq (@T[0],@C[4]); + &pandn (@C[3],@C[4]); + &pandn (@C[4],@C[0]); + &pxor (@C[3],@T[1]); + &movq (&QWP($A[$y][1],"edi"),@C[2]); # R[0][1] = C[1] ^ (~C[2] & C[3]); + &pxor (@C[4],@T[2]); + &movq (@T[2],&QWP($A[0][$xrho],"esi")) if (defined($xrho)); + + &movq (&QWP($A[$y][2],"edi"),@C[3]); # R[0][2] = C[2] ^ (~C[3] & C[4]); + &pandn (@C[0],@C[1]); + &movq (&QWP($A[$y][3],"edi"),@C[4]); # R[0][3] = C[3] ^ (~C[4] & C[0]); + &pxor (@C[0],@T[0]); + &pxor (@T[2],&QWP(@D[$xrho],"esp")) if (defined($xrho)); + &movq (&QWP($A[$y][4],"edi"),@C[0]); # R[0][4] = C[4] ^ (~C[0] & C[1]); +} + &Chi (0, 3); + +sub Rho() { ######### regular Rho step + my $x = shift; + + #&movq (@T[2],&QWP($A[0][$x],"esi")); # moved to Chi + #&pxor (@T[2],&QWP(@D[$x],"esp")); # moved to Chi + &movq (@C[0],@T[2]); + &psrlq (@T[2],64-$rhotates[0][$x]); + &movq (@C[1],&QWP($A[1][($x+1)%5],"esi")); + &psllq (@C[0],$rhotates[0][$x]); + &pxor (@C[1],&QWP(@D[($x+1)%5],"esp")); + &por (@C[0],@T[2]); # C[0] = ROL64(A[0][3] ^ D[3], rhotates[0][3]); + + &movq (@T[1],@C[1]); + &psrlq (@C[1],64-$rhotates[1][($x+1)%5]); + &movq (@C[2],&QWP($A[2][($x+2)%5],"esi")); + &psllq (@T[1],$rhotates[1][($x+1)%5]); + &pxor (@C[2],&QWP(@D[($x+2)%5],"esp")); + &por (@C[1],@T[1]); # C[1] = ROL64(A[1][4] ^ D[4], rhotates[1][4]); + + &movq (@T[2],@C[2]); + &psrlq (@C[2],64-$rhotates[2][($x+2)%5]); + &movq (@C[3],&QWP($A[3][($x+3)%5],"esi")); + &psllq (@T[2],$rhotates[2][($x+2)%5]); + &pxor (@C[3],&QWP(@D[($x+3)%5],"esp")); + &por (@C[2],@T[2]); # C[2] = ROL64(A[2][0] ^ D[0], rhotates[2][0]); + + &movq (@T[0],@C[3]); + &psrlq (@C[3],64-$rhotates[3][($x+3)%5]); + &movq (@C[4],&QWP($A[4][($x+4)%5],"esi")); + &psllq (@T[0],$rhotates[3][($x+3)%5]); + &pxor (@C[4],&QWP(@D[($x+4)%5],"esp")); + &por (@C[3],@T[0]); # C[3] = ROL64(A[3][1] ^ D[1], rhotates[3][1]); + + &movq (@T[1],@C[4]); + &psrlq (@C[4],64-$rhotates[4][($x+4)%5]); + &psllq (@T[1],$rhotates[4][($x+4)%5]); + &por (@C[4],@T[1]); # C[4] = ROL64(A[4][2] ^ D[2], rhotates[4][2]); +} + &Rho (3); &Chi (1, 1); + &Rho (1); &Chi (2, 4); + &Rho (4); &Chi (3, 2); + &Rho (2); ###&Chi (4); + + &movq (@T[0],@C[0]); ######### last Chi(4) is special + &xor ("edi","esi"); # &xchg ("esi","edi"); + &movq (&QWP(@D[1],"esp"),@C[1]); + &xor ("esi","edi"); + &xor ("edi","esi"); + + &movq (@T[1],@C[1]); + &movq (@T[2],@C[2]); + &pandn (@T[1],@C[2]); + &pandn (@T[2],@C[3]); + &pxor (@C[0],@T[1]); + &pxor (@C[1],@T[2]); + + &movq (@T[1],@C[3]); + &movq (&QWP($A[4][0],"esi"),@C[0]); # R[4][0] = C[0] ^= (~C[1] & C[2]); + &pandn (@T[1],@C[4]); + &movq (&QWP($A[4][1],"esi"),@C[1]); # R[4][1] = C[1] ^= (~C[2] & C[3]); + &pxor (@C[2],@T[1]); + &movq (@T[2],@C[4]); + &movq (&QWP($A[4][2],"esi"),@C[2]); # R[4][2] = C[2] ^= (~C[3] & C[4]); + + &pandn (@T[2],@T[0]); + &pandn (@T[0],&QWP(@D[1],"esp")); + &pxor (@C[3],@T[2]); + &pxor (@C[4],@T[0]); + &movq (&QWP($A[4][3],"esi"),@C[3]); # R[4][3] = C[3] ^= (~C[4] & D[0]); + &sub ("ecx",1); + &movq (&QWP($A[4][4],"esi"),@C[4]); # R[4][4] = C[4] ^= (~D[0] & D[1]); + &jnz (&label("loop")); + + &lea ("ebx",&DWP(-192,"ebx")); # rewind iotas + &ret (); +&function_end_B("_KeccakF1600"); + +&function_begin("KeccakF1600"); + &mov ("esi",&wparam(0)); + &mov ("ebp","esp"); + &sub ("esp",240); + &call (&label("pic_point")); + &set_label("pic_point"); + &blindpop("ebx"); + &lea ("ebx",&DWP(&label("iotas")."-".&label("pic_point"),"ebx")); + &and ("esp",-8); + &lea ("esi",&DWP(100,"esi")); # size optimization + &lea ("edi",&DWP(8*5+100,"esp")); # size optimization + + &call ("_KeccakF1600"); + + &mov ("esp","ebp"); + &emms (); +&function_end("KeccakF1600"); + +&function_begin("SHA3_absorb"); + &mov ("esi",&wparam(0)); # A[][] + &mov ("eax",&wparam(1)); # inp + &mov ("ecx",&wparam(2)); # len + &mov ("edx",&wparam(3)); # bsz + &mov ("ebp","esp"); + &sub ("esp",240+8); + &call (&label("pic_point")); + &set_label("pic_point"); + &blindpop("ebx"); + &lea ("ebx",&DWP(&label("iotas")."-".&label("pic_point"),"ebx")); + &and ("esp",-8); + + &mov ("edi","esi"); + &lea ("esi",&DWP(100,"esi")); # size optimization + &mov (&DWP(-4,"ebp"),"edx"); # save bsz + &jmp (&label("loop")); + +&set_label("loop",16); + &cmp ("ecx","edx"); # len < bsz? + &jc (&label("absorbed")); + + &shr ("edx",3); # bsz /= 8 +&set_label("block"); + &movq ("mm0",&QWP(0,"eax")); + &lea ("eax",&DWP(8,"eax")); + &pxor ("mm0",&QWP(0,"edi")); + &lea ("edi",&DWP(8,"edi")); + &sub ("ecx",8); # len -= 8 + &movq (&QWP(-8,"edi"),"mm0"); + &dec ("edx"); # bsz-- + &jnz (&label("block")); + + &lea ("edi",&DWP(8*5+100,"esp")); # size optimization + &mov (&DWP(-8,"ebp"),"ecx"); # save len + &call ("_KeccakF1600"); + &mov ("ecx",&DWP(-8,"ebp")); # pull len + &mov ("edx",&DWP(-4,"ebp")); # pull bsz + &lea ("edi",&DWP(-100,"esi")); + &jmp (&label("loop")); + +&set_label("absorbed",16); + &mov ("eax","ecx"); # return value + &mov ("esp","ebp"); + &emms (); +&function_end("SHA3_absorb"); + +&function_begin("SHA3_squeeze"); + &mov ("esi",&wparam(0)); # A[][] + &mov ("eax",&wparam(1)); # out + &mov ("ecx",&wparam(2)); # len + &mov ("edx",&wparam(3)); # bsz + &mov ("ebp","esp"); + &sub ("esp",240+8); + &call (&label("pic_point")); + &set_label("pic_point"); + &blindpop("ebx"); + &lea ("ebx",&DWP(&label("iotas")."-".&label("pic_point"),"ebx")); + &and ("esp",-8); + + &shr ("edx",3); # bsz /= 8 + &mov ("edi","esi"); + &lea ("esi",&DWP(100,"esi")); # size optimization + &mov (&DWP(-4,"ebp"),"edx"); # save bsz + &jmp (&label("loop")); + +&set_label("loop",16); + &cmp ("ecx",8); # len < 8? + &jc (&label("tail")); + + &movq ("mm0",&QWP(0,"edi")); + &lea ("edi",&DWP(8,"edi")); + &movq (&QWP(0,"eax"),"mm0"); + &lea ("eax",&DWP(8,"eax")); + &sub ("ecx",8); # len -= 8 + &jz (&label("done")); + + &dec ("edx"); # bsz-- + &jnz (&label("loop")); + + &lea ("edi",&DWP(8*5+100,"esp")); # size optimization + &mov (&DWP(-8,"ebp"),"ecx"); # save len + &call ("_KeccakF1600"); + &mov ("ecx",&DWP(-8,"ebp")); # pull len + &mov ("edx",&DWP(-4,"ebp")); # pull bsz + &lea ("edi",&DWP(-100,"esi")); + &jmp (&label("loop")); + +&set_label("tail",16); + &mov ("esi","edi"); + &mov ("edi","eax"); + &data_word("0xA4F39066"); # rep movsb + +&set_label("done"); + &mov ("esp","ebp"); + &emms (); +&function_end("SHA3_squeeze"); + +&set_label("iotas",32); + &data_word(0x00000001,0x00000000); + &data_word(0x00008082,0x00000000); + &data_word(0x0000808a,0x80000000); + &data_word(0x80008000,0x80000000); + &data_word(0x0000808b,0x00000000); + &data_word(0x80000001,0x00000000); + &data_word(0x80008081,0x80000000); + &data_word(0x00008009,0x80000000); + &data_word(0x0000008a,0x00000000); + &data_word(0x00000088,0x00000000); + &data_word(0x80008009,0x00000000); + &data_word(0x8000000a,0x00000000); + &data_word(0x8000808b,0x00000000); + &data_word(0x0000008b,0x80000000); + &data_word(0x00008089,0x80000000); + &data_word(0x00008003,0x80000000); + &data_word(0x00008002,0x80000000); + &data_word(0x00000080,0x80000000); + &data_word(0x0000800a,0x00000000); + &data_word(0x8000000a,0x80000000); + &data_word(0x80008081,0x80000000); + &data_word(0x00008080,0x80000000); + &data_word(0x80000001,0x00000000); + &data_word(0x80008008,0x80000000); +&asciz("Keccak-1600 absorb and squeeze for MMX, CRYPTOGAMS by "); + +&asm_finish(); + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-ppc64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-ppc64.pl new file mode 100755 index 000000000..30e70c5d6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-ppc64.pl @@ -0,0 +1,758 @@ +#!/usr/bin/env perl +# Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# Keccak-1600 for PPC64. +# +# June 2017. +# +# This is straightforward KECCAK_1X_ALT implementation that works on +# *any* PPC64. Then PowerISA 2.07 adds 2x64-bit vector rotate, and +# it's possible to achieve performance better than below, but that is +# naturally option only for POWER8 and successors... +# +###################################################################### +# Numbers are cycles per processed byte. +# +# r=1088(*) +# +# PPC970/G5 14.6/+120% +# POWER7 10.3/+100% +# POWER8 11.5/+85% +# POWER9 9.4/+45% +# +# (*) Corresponds to SHA3-256. Percentage after slash is improvement +# over gcc-4.x-generated KECCAK_1X_ALT code. Newer compilers do +# much better (but watch out for them generating code specific +# to processor they execute on). + +$flavour = shift; + +if ($flavour =~ /64/) { + $SIZE_T =8; + $LRSAVE =2*$SIZE_T; + $UCMP ="cmpld"; + $STU ="stdu"; + $POP ="ld"; + $PUSH ="std"; +} else { die "nonsense $flavour"; } + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or +die "can't locate ppc-xlate.pl"; + +open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!"; + +$FRAME=24*$SIZE_T+6*$SIZE_T+32; +$LOCALS=6*$SIZE_T; +$TEMP=$LOCALS+6*$SIZE_T; + +my $sp ="r1"; + +my @A = map([ "r$_", "r".($_+1), "r".($_+2), "r".($_+3), "r".($_+4) ], + (7, 12, 17, 22, 27)); + $A[1][1] = "r6"; # r13 is reserved + +my @C = map("r$_", (0,3,4,5)); + +my @rhotates = ([ 0, 1, 62, 28, 27 ], + [ 36, 44, 6, 55, 20 ], + [ 3, 10, 43, 25, 39 ], + [ 41, 45, 15, 21, 8 ], + [ 18, 2, 61, 56, 14 ]); + +$code.=<<___; +.text + +.type KeccakF1600_int,\@function +.align 5 +KeccakF1600_int: + li r0,24 + mtctr r0 + b .Loop +.align 4 +.Loop: + xor $C[0],$A[0][0],$A[1][0] ; Theta + std $A[0][4],`$TEMP+0`($sp) + xor $C[1],$A[0][1],$A[1][1] + std $A[1][4],`$TEMP+8`($sp) + xor $C[2],$A[0][2],$A[1][2] + std $A[2][4],`$TEMP+16`($sp) + xor $C[3],$A[0][3],$A[1][3] + std $A[3][4],`$TEMP+24`($sp) +___ + $C[4]=$A[0][4]; + $C[5]=$A[1][4]; + $C[6]=$A[2][4]; + $C[7]=$A[3][4]; +$code.=<<___; + xor $C[4],$A[0][4],$A[1][4] + xor $C[0],$C[0],$A[2][0] + xor $C[1],$C[1],$A[2][1] + xor $C[2],$C[2],$A[2][2] + xor $C[3],$C[3],$A[2][3] + xor $C[4],$C[4],$A[2][4] + xor $C[0],$C[0],$A[3][0] + xor $C[1],$C[1],$A[3][1] + xor $C[2],$C[2],$A[3][2] + xor $C[3],$C[3],$A[3][3] + xor $C[4],$C[4],$A[3][4] + xor $C[0],$C[0],$A[4][0] + xor $C[2],$C[2],$A[4][2] + xor $C[1],$C[1],$A[4][1] + xor $C[3],$C[3],$A[4][3] + rotldi $C[5],$C[2],1 + xor $C[4],$C[4],$A[4][4] + rotldi $C[6],$C[3],1 + xor $C[5],$C[5],$C[0] + rotldi $C[7],$C[4],1 + + xor $A[0][1],$A[0][1],$C[5] + xor $A[1][1],$A[1][1],$C[5] + xor $A[2][1],$A[2][1],$C[5] + xor $A[3][1],$A[3][1],$C[5] + xor $A[4][1],$A[4][1],$C[5] + + rotldi $C[5],$C[0],1 + xor $C[6],$C[6],$C[1] + xor $C[2],$C[2],$C[7] + rotldi $C[7],$C[1],1 + xor $C[3],$C[3],$C[5] + xor $C[4],$C[4],$C[7] + + xor $C[1], $A[0][2],$C[6] ;mr $C[1],$A[0][2] + xor $A[1][2],$A[1][2],$C[6] + xor $A[2][2],$A[2][2],$C[6] + xor $A[3][2],$A[3][2],$C[6] + xor $A[4][2],$A[4][2],$C[6] + + xor $A[0][0],$A[0][0],$C[4] + xor $A[1][0],$A[1][0],$C[4] + xor $A[2][0],$A[2][0],$C[4] + xor $A[3][0],$A[3][0],$C[4] + xor $A[4][0],$A[4][0],$C[4] +___ + $C[4]=undef; + $C[5]=undef; + $C[6]=undef; + $C[7]=undef; +$code.=<<___; + ld $A[0][4],`$TEMP+0`($sp) + xor $C[0], $A[0][3],$C[2] ;mr $C[0],$A[0][3] + ld $A[1][4],`$TEMP+8`($sp) + xor $A[1][3],$A[1][3],$C[2] + ld $A[2][4],`$TEMP+16`($sp) + xor $A[2][3],$A[2][3],$C[2] + ld $A[3][4],`$TEMP+24`($sp) + xor $A[3][3],$A[3][3],$C[2] + xor $A[4][3],$A[4][3],$C[2] + + xor $C[2], $A[0][4],$C[3] ;mr $C[2],$A[0][4] + xor $A[1][4],$A[1][4],$C[3] + xor $A[2][4],$A[2][4],$C[3] + xor $A[3][4],$A[3][4],$C[3] + xor $A[4][4],$A[4][4],$C[3] + + mr $C[3],$A[0][1] ; Rho+Pi + rotldi $A[0][1],$A[1][1],$rhotates[1][1] + ;mr $C[1],$A[0][2] + rotldi $A[0][2],$A[2][2],$rhotates[2][2] + ;mr $C[0],$A[0][3] + rotldi $A[0][3],$A[3][3],$rhotates[3][3] + ;mr $C[2],$A[0][4] + rotldi $A[0][4],$A[4][4],$rhotates[4][4] + + rotldi $A[1][1],$A[1][4],$rhotates[1][4] + rotldi $A[2][2],$A[2][3],$rhotates[2][3] + rotldi $A[3][3],$A[3][2],$rhotates[3][2] + rotldi $A[4][4],$A[4][1],$rhotates[4][1] + + rotldi $A[1][4],$A[4][2],$rhotates[4][2] + rotldi $A[2][3],$A[3][4],$rhotates[3][4] + rotldi $A[3][2],$A[2][1],$rhotates[2][1] + rotldi $A[4][1],$A[1][3],$rhotates[1][3] + + rotldi $A[4][2],$A[2][4],$rhotates[2][4] + rotldi $A[3][4],$A[4][3],$rhotates[4][3] + rotldi $A[2][1],$A[1][2],$rhotates[1][2] + rotldi $A[1][3],$A[3][1],$rhotates[3][1] + + rotldi $A[2][4],$A[4][0],$rhotates[4][0] + rotldi $A[4][3],$A[3][0],$rhotates[3][0] + rotldi $A[1][2],$A[2][0],$rhotates[2][0] + rotldi $A[3][1],$A[1][0],$rhotates[1][0] + + rotldi $A[1][0],$C[0],$rhotates[0][3] + rotldi $A[2][0],$C[3],$rhotates[0][1] + rotldi $A[3][0],$C[2],$rhotates[0][4] + rotldi $A[4][0],$C[1],$rhotates[0][2] + + andc $C[0],$A[0][2],$A[0][1] ; Chi+Iota + andc $C[1],$A[0][3],$A[0][2] + andc $C[2],$A[0][0],$A[0][4] + andc $C[3],$A[0][1],$A[0][0] + xor $A[0][0],$A[0][0],$C[0] + andc $C[0],$A[0][4],$A[0][3] + xor $A[0][1],$A[0][1],$C[1] + ld $C[1],`$LOCALS+4*$SIZE_T`($sp) + xor $A[0][3],$A[0][3],$C[2] + xor $A[0][4],$A[0][4],$C[3] + xor $A[0][2],$A[0][2],$C[0] + ldu $C[3],8($C[1]) ; Iota[i++] + + andc $C[0],$A[1][2],$A[1][1] + std $C[1],`$LOCALS+4*$SIZE_T`($sp) + andc $C[1],$A[1][3],$A[1][2] + andc $C[2],$A[1][0],$A[1][4] + xor $A[0][0],$A[0][0],$C[3] ; A[0][0] ^= Iota + andc $C[3],$A[1][1],$A[1][0] + xor $A[1][0],$A[1][0],$C[0] + andc $C[0],$A[1][4],$A[1][3] + xor $A[1][1],$A[1][1],$C[1] + xor $A[1][3],$A[1][3],$C[2] + xor $A[1][4],$A[1][4],$C[3] + xor $A[1][2],$A[1][2],$C[0] + + andc $C[0],$A[2][2],$A[2][1] + andc $C[1],$A[2][3],$A[2][2] + andc $C[2],$A[2][0],$A[2][4] + andc $C[3],$A[2][1],$A[2][0] + xor $A[2][0],$A[2][0],$C[0] + andc $C[0],$A[2][4],$A[2][3] + xor $A[2][1],$A[2][1],$C[1] + xor $A[2][3],$A[2][3],$C[2] + xor $A[2][4],$A[2][4],$C[3] + xor $A[2][2],$A[2][2],$C[0] + + andc $C[0],$A[3][2],$A[3][1] + andc $C[1],$A[3][3],$A[3][2] + andc $C[2],$A[3][0],$A[3][4] + andc $C[3],$A[3][1],$A[3][0] + xor $A[3][0],$A[3][0],$C[0] + andc $C[0],$A[3][4],$A[3][3] + xor $A[3][1],$A[3][1],$C[1] + xor $A[3][3],$A[3][3],$C[2] + xor $A[3][4],$A[3][4],$C[3] + xor $A[3][2],$A[3][2],$C[0] + + andc $C[0],$A[4][2],$A[4][1] + andc $C[1],$A[4][3],$A[4][2] + andc $C[2],$A[4][0],$A[4][4] + andc $C[3],$A[4][1],$A[4][0] + xor $A[4][0],$A[4][0],$C[0] + andc $C[0],$A[4][4],$A[4][3] + xor $A[4][1],$A[4][1],$C[1] + xor $A[4][3],$A[4][3],$C[2] + xor $A[4][4],$A[4][4],$C[3] + xor $A[4][2],$A[4][2],$C[0] + + bdnz .Loop + + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 +.size KeccakF1600_int,.-KeccakF1600_int + +.type KeccakF1600,\@function +.align 5 +KeccakF1600: + $STU $sp,-$FRAME($sp) + mflr r0 + $PUSH r14,`$FRAME-$SIZE_T*18`($sp) + $PUSH r15,`$FRAME-$SIZE_T*17`($sp) + $PUSH r16,`$FRAME-$SIZE_T*16`($sp) + $PUSH r17,`$FRAME-$SIZE_T*15`($sp) + $PUSH r18,`$FRAME-$SIZE_T*14`($sp) + $PUSH r19,`$FRAME-$SIZE_T*13`($sp) + $PUSH r20,`$FRAME-$SIZE_T*12`($sp) + $PUSH r21,`$FRAME-$SIZE_T*11`($sp) + $PUSH r22,`$FRAME-$SIZE_T*10`($sp) + $PUSH r23,`$FRAME-$SIZE_T*9`($sp) + $PUSH r24,`$FRAME-$SIZE_T*8`($sp) + $PUSH r25,`$FRAME-$SIZE_T*7`($sp) + $PUSH r26,`$FRAME-$SIZE_T*6`($sp) + $PUSH r27,`$FRAME-$SIZE_T*5`($sp) + $PUSH r28,`$FRAME-$SIZE_T*4`($sp) + $PUSH r29,`$FRAME-$SIZE_T*3`($sp) + $PUSH r30,`$FRAME-$SIZE_T*2`($sp) + $PUSH r31,`$FRAME-$SIZE_T*1`($sp) + $PUSH r0,`$FRAME+$LRSAVE`($sp) + + bl PICmeup + subi r12,r12,8 ; prepare for ldu + + $PUSH r3,`$LOCALS+0*$SIZE_T`($sp) + ;$PUSH r4,`$LOCALS+1*$SIZE_T`($sp) + ;$PUSH r5,`$LOCALS+2*$SIZE_T`($sp) + ;$PUSH r6,`$LOCALS+3*$SIZE_T`($sp) + $PUSH r12,`$LOCALS+4*$SIZE_T`($sp) + + ld $A[0][0],`8*0`(r3) ; load A[5][5] + ld $A[0][1],`8*1`(r3) + ld $A[0][2],`8*2`(r3) + ld $A[0][3],`8*3`(r3) + ld $A[0][4],`8*4`(r3) + ld $A[1][0],`8*5`(r3) + ld $A[1][1],`8*6`(r3) + ld $A[1][2],`8*7`(r3) + ld $A[1][3],`8*8`(r3) + ld $A[1][4],`8*9`(r3) + ld $A[2][0],`8*10`(r3) + ld $A[2][1],`8*11`(r3) + ld $A[2][2],`8*12`(r3) + ld $A[2][3],`8*13`(r3) + ld $A[2][4],`8*14`(r3) + ld $A[3][0],`8*15`(r3) + ld $A[3][1],`8*16`(r3) + ld $A[3][2],`8*17`(r3) + ld $A[3][3],`8*18`(r3) + ld $A[3][4],`8*19`(r3) + ld $A[4][0],`8*20`(r3) + ld $A[4][1],`8*21`(r3) + ld $A[4][2],`8*22`(r3) + ld $A[4][3],`8*23`(r3) + ld $A[4][4],`8*24`(r3) + + bl KeccakF1600_int + + $POP r3,`$LOCALS+0*$SIZE_T`($sp) + std $A[0][0],`8*0`(r3) ; return A[5][5] + std $A[0][1],`8*1`(r3) + std $A[0][2],`8*2`(r3) + std $A[0][3],`8*3`(r3) + std $A[0][4],`8*4`(r3) + std $A[1][0],`8*5`(r3) + std $A[1][1],`8*6`(r3) + std $A[1][2],`8*7`(r3) + std $A[1][3],`8*8`(r3) + std $A[1][4],`8*9`(r3) + std $A[2][0],`8*10`(r3) + std $A[2][1],`8*11`(r3) + std $A[2][2],`8*12`(r3) + std $A[2][3],`8*13`(r3) + std $A[2][4],`8*14`(r3) + std $A[3][0],`8*15`(r3) + std $A[3][1],`8*16`(r3) + std $A[3][2],`8*17`(r3) + std $A[3][3],`8*18`(r3) + std $A[3][4],`8*19`(r3) + std $A[4][0],`8*20`(r3) + std $A[4][1],`8*21`(r3) + std $A[4][2],`8*22`(r3) + std $A[4][3],`8*23`(r3) + std $A[4][4],`8*24`(r3) + + $POP r0,`$FRAME+$LRSAVE`($sp) + $POP r14,`$FRAME-$SIZE_T*18`($sp) + $POP r15,`$FRAME-$SIZE_T*17`($sp) + $POP r16,`$FRAME-$SIZE_T*16`($sp) + $POP r17,`$FRAME-$SIZE_T*15`($sp) + $POP r18,`$FRAME-$SIZE_T*14`($sp) + $POP r19,`$FRAME-$SIZE_T*13`($sp) + $POP r20,`$FRAME-$SIZE_T*12`($sp) + $POP r21,`$FRAME-$SIZE_T*11`($sp) + $POP r22,`$FRAME-$SIZE_T*10`($sp) + $POP r23,`$FRAME-$SIZE_T*9`($sp) + $POP r24,`$FRAME-$SIZE_T*8`($sp) + $POP r25,`$FRAME-$SIZE_T*7`($sp) + $POP r26,`$FRAME-$SIZE_T*6`($sp) + $POP r27,`$FRAME-$SIZE_T*5`($sp) + $POP r28,`$FRAME-$SIZE_T*4`($sp) + $POP r29,`$FRAME-$SIZE_T*3`($sp) + $POP r30,`$FRAME-$SIZE_T*2`($sp) + $POP r31,`$FRAME-$SIZE_T*1`($sp) + mtlr r0 + addi $sp,$sp,$FRAME + blr + .long 0 + .byte 0,12,4,1,0x80,18,1,0 + .long 0 +.size KeccakF1600,.-KeccakF1600 + +.type dword_le_load,\@function +.align 5 +dword_le_load: + lbzu r0,1(r3) + lbzu r4,1(r3) + lbzu r5,1(r3) + insrdi r0,r4,8,48 + lbzu r4,1(r3) + insrdi r0,r5,8,40 + lbzu r5,1(r3) + insrdi r0,r4,8,32 + lbzu r4,1(r3) + insrdi r0,r5,8,24 + lbzu r5,1(r3) + insrdi r0,r4,8,16 + lbzu r4,1(r3) + insrdi r0,r5,8,8 + insrdi r0,r4,8,0 + blr + .long 0 + .byte 0,12,0x14,0,0,0,1,0 + .long 0 +.size dword_le_load,.-dword_le_load + +.globl SHA3_absorb +.type SHA3_absorb,\@function +.align 5 +SHA3_absorb: + $STU $sp,-$FRAME($sp) + mflr r0 + $PUSH r14,`$FRAME-$SIZE_T*18`($sp) + $PUSH r15,`$FRAME-$SIZE_T*17`($sp) + $PUSH r16,`$FRAME-$SIZE_T*16`($sp) + $PUSH r17,`$FRAME-$SIZE_T*15`($sp) + $PUSH r18,`$FRAME-$SIZE_T*14`($sp) + $PUSH r19,`$FRAME-$SIZE_T*13`($sp) + $PUSH r20,`$FRAME-$SIZE_T*12`($sp) + $PUSH r21,`$FRAME-$SIZE_T*11`($sp) + $PUSH r22,`$FRAME-$SIZE_T*10`($sp) + $PUSH r23,`$FRAME-$SIZE_T*9`($sp) + $PUSH r24,`$FRAME-$SIZE_T*8`($sp) + $PUSH r25,`$FRAME-$SIZE_T*7`($sp) + $PUSH r26,`$FRAME-$SIZE_T*6`($sp) + $PUSH r27,`$FRAME-$SIZE_T*5`($sp) + $PUSH r28,`$FRAME-$SIZE_T*4`($sp) + $PUSH r29,`$FRAME-$SIZE_T*3`($sp) + $PUSH r30,`$FRAME-$SIZE_T*2`($sp) + $PUSH r31,`$FRAME-$SIZE_T*1`($sp) + $PUSH r0,`$FRAME+$LRSAVE`($sp) + + bl PICmeup + subi r4,r4,1 ; prepare for lbzu + subi r12,r12,8 ; prepare for ldu + + $PUSH r3,`$LOCALS+0*$SIZE_T`($sp) ; save A[][] + $PUSH r4,`$LOCALS+1*$SIZE_T`($sp) ; save inp + $PUSH r5,`$LOCALS+2*$SIZE_T`($sp) ; save len + $PUSH r6,`$LOCALS+3*$SIZE_T`($sp) ; save bsz + mr r0,r6 + $PUSH r12,`$LOCALS+4*$SIZE_T`($sp) + + ld $A[0][0],`8*0`(r3) ; load A[5][5] + ld $A[0][1],`8*1`(r3) + ld $A[0][2],`8*2`(r3) + ld $A[0][3],`8*3`(r3) + ld $A[0][4],`8*4`(r3) + ld $A[1][0],`8*5`(r3) + ld $A[1][1],`8*6`(r3) + ld $A[1][2],`8*7`(r3) + ld $A[1][3],`8*8`(r3) + ld $A[1][4],`8*9`(r3) + ld $A[2][0],`8*10`(r3) + ld $A[2][1],`8*11`(r3) + ld $A[2][2],`8*12`(r3) + ld $A[2][3],`8*13`(r3) + ld $A[2][4],`8*14`(r3) + ld $A[3][0],`8*15`(r3) + ld $A[3][1],`8*16`(r3) + ld $A[3][2],`8*17`(r3) + ld $A[3][3],`8*18`(r3) + ld $A[3][4],`8*19`(r3) + ld $A[4][0],`8*20`(r3) + ld $A[4][1],`8*21`(r3) + ld $A[4][2],`8*22`(r3) + ld $A[4][3],`8*23`(r3) + ld $A[4][4],`8*24`(r3) + + mr r3,r4 + mr r4,r5 + mr r5,r0 + + b .Loop_absorb + +.align 4 +.Loop_absorb: + $UCMP r4,r5 ; len < bsz? + blt .Labsorbed + + sub r4,r4,r5 ; len -= bsz + srwi r5,r5,3 + $PUSH r4,`$LOCALS+2*$SIZE_T`($sp) ; save len + mtctr r5 + bl dword_le_load ; *inp++ + xor $A[0][0],$A[0][0],r0 + bdz .Lprocess_block + bl dword_le_load ; *inp++ + xor $A[0][1],$A[0][1],r0 + bdz .Lprocess_block + bl dword_le_load ; *inp++ + xor $A[0][2],$A[0][2],r0 + bdz .Lprocess_block + bl dword_le_load ; *inp++ + xor $A[0][3],$A[0][3],r0 + bdz .Lprocess_block + bl dword_le_load ; *inp++ + xor $A[0][4],$A[0][4],r0 + bdz .Lprocess_block + bl dword_le_load ; *inp++ + xor $A[1][0],$A[1][0],r0 + bdz .Lprocess_block + bl dword_le_load ; *inp++ + xor $A[1][1],$A[1][1],r0 + bdz .Lprocess_block + bl dword_le_load ; *inp++ + xor $A[1][2],$A[1][2],r0 + bdz .Lprocess_block + bl dword_le_load ; *inp++ + xor $A[1][3],$A[1][3],r0 + bdz .Lprocess_block + bl dword_le_load ; *inp++ + xor $A[1][4],$A[1][4],r0 + bdz .Lprocess_block + bl dword_le_load ; *inp++ + xor $A[2][0],$A[2][0],r0 + bdz .Lprocess_block + bl dword_le_load ; *inp++ + xor $A[2][1],$A[2][1],r0 + bdz .Lprocess_block + bl dword_le_load ; *inp++ + xor $A[2][2],$A[2][2],r0 + bdz .Lprocess_block + bl dword_le_load ; *inp++ + xor $A[2][3],$A[2][3],r0 + bdz .Lprocess_block + bl dword_le_load ; *inp++ + xor $A[2][4],$A[2][4],r0 + bdz .Lprocess_block + bl dword_le_load ; *inp++ + xor $A[3][0],$A[3][0],r0 + bdz .Lprocess_block + bl dword_le_load ; *inp++ + xor $A[3][1],$A[3][1],r0 + bdz .Lprocess_block + bl dword_le_load ; *inp++ + xor $A[3][2],$A[3][2],r0 + bdz .Lprocess_block + bl dword_le_load ; *inp++ + xor $A[3][3],$A[3][3],r0 + bdz .Lprocess_block + bl dword_le_load ; *inp++ + xor $A[3][4],$A[3][4],r0 + bdz .Lprocess_block + bl dword_le_load ; *inp++ + xor $A[4][0],$A[4][0],r0 + bdz .Lprocess_block + bl dword_le_load ; *inp++ + xor $A[4][1],$A[4][1],r0 + bdz .Lprocess_block + bl dword_le_load ; *inp++ + xor $A[4][2],$A[4][2],r0 + bdz .Lprocess_block + bl dword_le_load ; *inp++ + xor $A[4][3],$A[4][3],r0 + bdz .Lprocess_block + bl dword_le_load ; *inp++ + xor $A[4][4],$A[4][4],r0 + +.Lprocess_block: + $PUSH r3,`$LOCALS+1*$SIZE_T`($sp) ; save inp + + bl KeccakF1600_int + + $POP r0,`$LOCALS+4*$SIZE_T`($sp) ; pull iotas[24] + $POP r5,`$LOCALS+3*$SIZE_T`($sp) ; restore bsz + $POP r4,`$LOCALS+2*$SIZE_T`($sp) ; restore len + $POP r3,`$LOCALS+1*$SIZE_T`($sp) ; restore inp + addic r0,r0,`-8*24` ; rewind iotas + $PUSH r0,`$LOCALS+4*$SIZE_T`($sp) + + b .Loop_absorb + +.align 4 +.Labsorbed: + $POP r3,`$LOCALS+0*$SIZE_T`($sp) + std $A[0][0],`8*0`(r3) ; return A[5][5] + std $A[0][1],`8*1`(r3) + std $A[0][2],`8*2`(r3) + std $A[0][3],`8*3`(r3) + std $A[0][4],`8*4`(r3) + std $A[1][0],`8*5`(r3) + std $A[1][1],`8*6`(r3) + std $A[1][2],`8*7`(r3) + std $A[1][3],`8*8`(r3) + std $A[1][4],`8*9`(r3) + std $A[2][0],`8*10`(r3) + std $A[2][1],`8*11`(r3) + std $A[2][2],`8*12`(r3) + std $A[2][3],`8*13`(r3) + std $A[2][4],`8*14`(r3) + std $A[3][0],`8*15`(r3) + std $A[3][1],`8*16`(r3) + std $A[3][2],`8*17`(r3) + std $A[3][3],`8*18`(r3) + std $A[3][4],`8*19`(r3) + std $A[4][0],`8*20`(r3) + std $A[4][1],`8*21`(r3) + std $A[4][2],`8*22`(r3) + std $A[4][3],`8*23`(r3) + std $A[4][4],`8*24`(r3) + + mr r3,r4 ; return value + $POP r0,`$FRAME+$LRSAVE`($sp) + $POP r14,`$FRAME-$SIZE_T*18`($sp) + $POP r15,`$FRAME-$SIZE_T*17`($sp) + $POP r16,`$FRAME-$SIZE_T*16`($sp) + $POP r17,`$FRAME-$SIZE_T*15`($sp) + $POP r18,`$FRAME-$SIZE_T*14`($sp) + $POP r19,`$FRAME-$SIZE_T*13`($sp) + $POP r20,`$FRAME-$SIZE_T*12`($sp) + $POP r21,`$FRAME-$SIZE_T*11`($sp) + $POP r22,`$FRAME-$SIZE_T*10`($sp) + $POP r23,`$FRAME-$SIZE_T*9`($sp) + $POP r24,`$FRAME-$SIZE_T*8`($sp) + $POP r25,`$FRAME-$SIZE_T*7`($sp) + $POP r26,`$FRAME-$SIZE_T*6`($sp) + $POP r27,`$FRAME-$SIZE_T*5`($sp) + $POP r28,`$FRAME-$SIZE_T*4`($sp) + $POP r29,`$FRAME-$SIZE_T*3`($sp) + $POP r30,`$FRAME-$SIZE_T*2`($sp) + $POP r31,`$FRAME-$SIZE_T*1`($sp) + mtlr r0 + addi $sp,$sp,$FRAME + blr + .long 0 + .byte 0,12,4,1,0x80,18,4,0 + .long 0 +.size SHA3_absorb,.-SHA3_absorb +___ +{ +my ($A_flat,$out,$len,$bsz) = map("r$_",(28..31)); +$code.=<<___; +.globl SHA3_squeeze +.type SHA3_squeeze,\@function +.align 5 +SHA3_squeeze: + $STU $sp,`-10*$SIZE_T`($sp) + mflr r0 + $PUSH r28,`6*$SIZE_T`($sp) + $PUSH r29,`7*$SIZE_T`($sp) + $PUSH r30,`8*$SIZE_T`($sp) + $PUSH r31,`9*$SIZE_T`($sp) + $PUSH r0,`10*$SIZE_T+$LRSAVE`($sp) + + mr $A_flat,r3 + subi r3,r3,8 ; prepare for ldu + subi $out,r4,1 ; prepare for stbu + mr $len,r5 + mr $bsz,r6 + b .Loop_squeeze + +.align 4 +.Loop_squeeze: + ldu r0,8(r3) + ${UCMP}i $len,8 + blt .Lsqueeze_tail + + stbu r0,1($out) + srdi r0,r0,8 + stbu r0,1($out) + srdi r0,r0,8 + stbu r0,1($out) + srdi r0,r0,8 + stbu r0,1($out) + srdi r0,r0,8 + stbu r0,1($out) + srdi r0,r0,8 + stbu r0,1($out) + srdi r0,r0,8 + stbu r0,1($out) + srdi r0,r0,8 + stbu r0,1($out) + + subic. $len,$len,8 + beq .Lsqueeze_done + + subic. r6,r6,8 + bgt .Loop_squeeze + + mr r3,$A_flat + bl KeccakF1600 + subi r3,$A_flat,8 ; prepare for ldu + mr r6,$bsz + b .Loop_squeeze + +.align 4 +.Lsqueeze_tail: + mtctr $len +.Loop_tail: + stbu r0,1($out) + srdi r0,r0,8 + bdnz .Loop_tail + +.Lsqueeze_done: + $POP r0,`10*$SIZE_T+$LRSAVE`($sp) + $POP r28,`6*$SIZE_T`($sp) + $POP r29,`7*$SIZE_T`($sp) + $POP r30,`8*$SIZE_T`($sp) + $POP r31,`9*$SIZE_T`($sp) + mtlr r0 + addi $sp,$sp,`10*$SIZE_T` + blr + .long 0 + .byte 0,12,4,1,0x80,4,4,0 + .long 0 +.size SHA3_squeeze,.-SHA3_squeeze +___ +} + +# Ugly hack here, because PPC assembler syntax seem to vary too +# much from platforms to platform... +$code.=<<___; +.align 6 +PICmeup: + mflr r0 + bcl 20,31,\$+4 + mflr r12 ; vvvvvv "distance" between . and 1st data entry + addi r12,r12,`64-8` + mtlr r0 + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 + .space `64-9*4` +.type iotas,\@object +iotas: + .quad 0x0000000000000001 + .quad 0x0000000000008082 + .quad 0x800000000000808a + .quad 0x8000000080008000 + .quad 0x000000000000808b + .quad 0x0000000080000001 + .quad 0x8000000080008081 + .quad 0x8000000000008009 + .quad 0x000000000000008a + .quad 0x0000000000000088 + .quad 0x0000000080008009 + .quad 0x000000008000000a + .quad 0x000000008000808b + .quad 0x800000000000008b + .quad 0x8000000000008089 + .quad 0x8000000000008003 + .quad 0x8000000000008002 + .quad 0x8000000000000080 + .quad 0x000000000000800a + .quad 0x800000008000000a + .quad 0x8000000080008081 + .quad 0x8000000000008080 + .quad 0x0000000080000001 + .quad 0x8000000080008008 +.size iotas,.-iotas +.asciz "Keccak-1600 absorb and squeeze for PPC64, CRYPTOGAMS by " +___ + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-s390x.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-s390x.pl new file mode 100755 index 000000000..1184cf233 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-s390x.pl @@ -0,0 +1,560 @@ +#!/usr/bin/env perl +# Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# Keccak-1600 for s390x. +# +# June 2017. +# +# Below code is [lane complementing] KECCAK_2X implementation (see +# sha/keccak1600.c) with C[5] and D[5] held in register bank. Though +# instead of actually unrolling the loop pair-wise I simply flip +# pointers to T[][] and A[][] at the end of round. Since number of +# rounds is even, last round writes to A[][] and everything works out. +# In the nutshell it's transliteration of x86_64 module, because both +# architectures have similar capabilities/limitations. Performance +# measurement is problematic as I don't have access to an idle system. +# It looks like z13 processes one byte [out of long message] in ~14 +# cycles. At least the result is consistent with estimate based on +# amount of instruction and assumed instruction issue rate. It's ~2.5x +# faster than compiler-generated code. + +$flavour = shift; + +if ($flavour =~ /3[12]/) { + $SIZE_T=4; + $g=""; +} else { + $SIZE_T=8; + $g="g"; +} + +while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} +open STDOUT,">$output"; + +my @A = map([ 8*$_, 8*($_+1), 8*($_+2), 8*($_+3), 8*($_+4) ], (0,5,10,15,20)); + +my @C = map("%r$_",(0,1,5..7)); +my @D = map("%r$_",(8..12)); +my @T = map("%r$_",(13..14)); +my ($src,$dst,$iotas) = map("%r$_",(2..4)); +my $sp = "%r15"; + +$stdframe=16*$SIZE_T+4*8; +$frame=$stdframe+25*8; + +my @rhotates = ([ 0, 1, 62, 28, 27 ], + [ 36, 44, 6, 55, 20 ], + [ 3, 10, 43, 25, 39 ], + [ 41, 45, 15, 21, 8 ], + [ 18, 2, 61, 56, 14 ]); + +{ my @C = @C; # copy, because we mess them up... + my @D = @D; + +$code.=<<___; +.text + +.type __KeccakF1600,\@function +.align 32 +__KeccakF1600: + st${g} %r14,$SIZE_T*14($sp) + lg @C[0],$A[4][0]($src) + lg @C[1],$A[4][1]($src) + lg @C[2],$A[4][2]($src) + lg @C[3],$A[4][3]($src) + lg @C[4],$A[4][4]($src) + larl $iotas,iotas + j .Loop + +.align 16 +.Loop: + lg @D[0],$A[0][0]($src) + lg @D[1],$A[1][1]($src) + lg @D[2],$A[2][2]($src) + lg @D[3],$A[3][3]($src) + + xgr @C[0],@D[0] + xg @C[1],$A[0][1]($src) + xg @C[2],$A[0][2]($src) + xg @C[3],$A[0][3]($src) + lgr @D[4],@C[4] + xg @C[4],$A[0][4]($src) + + xg @C[0],$A[1][0]($src) + xgr @C[1],@D[1] + xg @C[2],$A[1][2]($src) + xg @C[3],$A[1][3]($src) + xg @C[4],$A[1][4]($src) + + xg @C[0],$A[2][0]($src) + xg @C[1],$A[2][1]($src) + xgr @C[2],@D[2] + xg @C[3],$A[2][3]($src) + xg @C[4],$A[2][4]($src) + + xg @C[0],$A[3][0]($src) + xg @C[1],$A[3][1]($src) + xg @C[2],$A[3][2]($src) + xgr @C[3],@D[3] + xg @C[4],$A[3][4]($src) + + lgr @T[0],@C[2] + rllg @C[2],@C[2],1 + xgr @C[2],@C[0] # D[1] = ROL64(C[2], 1) ^ C[0] + + rllg @C[0],@C[0],1 + xgr @C[0],@C[3] # D[4] = ROL64(C[0], 1) ^ C[3] + + rllg @C[3],@C[3],1 + xgr @C[3],@C[1] # D[2] = ROL64(C[3], 1) ^ C[1] + + rllg @C[1],@C[1],1 + xgr @C[1],@C[4] # D[0] = ROL64(C[1], 1) ^ C[4] + + rllg @C[4],@C[4],1 + xgr @C[4],@T[0] # D[3] = ROL64(C[4], 1) ^ C[2] +___ + (@D[0..4], @C) = (@C[1..4,0], @D); +$code.=<<___; + xgr @C[1],@D[1] + xgr @C[2],@D[2] + xgr @C[3],@D[3] + rllg @C[1],@C[1],$rhotates[1][1] + xgr @C[4],@D[4] + rllg @C[2],@C[2],$rhotates[2][2] + xgr @C[0],@D[0] + + lgr @T[0],@C[1] + ogr @C[1],@C[2] + rllg @C[3],@C[3],$rhotates[3][3] + xgr @C[1],@C[0] # C[0] ^ ( C[1] | C[2]) + rllg @C[4],@C[4],$rhotates[4][4] + xg @C[1],0($iotas) + la $iotas,8($iotas) + stg @C[1],$A[0][0]($dst) # R[0][0] = C[0] ^ ( C[1] | C[2]) ^ iotas[i] + + lgr @T[1],@C[4] + ngr @C[4],@C[3] + lghi @C[1],-1 # no 'not' instruction :-( + xgr @C[4],@C[2] # C[2] ^ ( C[4] & C[3]) + xgr @C[2],@C[1] # not @C[2] + stg @C[4],$A[0][2]($dst) # R[0][2] = C[2] ^ ( C[4] & C[3]) + ogr @C[2],@C[3] + xgr @C[2],@T[0] # C[1] ^ (~C[2] | C[3]) + + ngr @T[0],@C[0] + stg @C[2],$A[0][1]($dst) # R[0][1] = C[1] ^ (~C[2] | C[3]) + xgr @T[0],@T[1] # C[4] ^ ( C[1] & C[0]) + ogr @T[1],@C[0] + stg @T[0],$A[0][4]($dst) # R[0][4] = C[4] ^ ( C[1] & C[0]) + xgr @T[1],@C[3] # C[3] ^ ( C[4] | C[0]) + stg @T[1],$A[0][3]($dst) # R[0][3] = C[3] ^ ( C[4] | C[0]) + + + lg @C[0],$A[0][3]($src) + lg @C[4],$A[4][2]($src) + lg @C[3],$A[3][1]($src) + lg @C[1],$A[1][4]($src) + lg @C[2],$A[2][0]($src) + + xgr @C[0],@D[3] + xgr @C[4],@D[2] + rllg @C[0],@C[0],$rhotates[0][3] + xgr @C[3],@D[1] + rllg @C[4],@C[4],$rhotates[4][2] + xgr @C[1],@D[4] + rllg @C[3],@C[3],$rhotates[3][1] + xgr @C[2],@D[0] + + lgr @T[0],@C[0] + ogr @C[0],@C[4] + rllg @C[1],@C[1],$rhotates[1][4] + xgr @C[0],@C[3] # C[3] ^ (C[0] | C[4]) + rllg @C[2],@C[2],$rhotates[2][0] + stg @C[0],$A[1][3]($dst) # R[1][3] = C[3] ^ (C[0] | C[4]) + + lgr @T[1],@C[1] + ngr @C[1],@T[0] + lghi @C[0],-1 # no 'not' instruction :-( + xgr @C[1],@C[4] # C[4] ^ (C[1] & C[0]) + xgr @C[4],@C[0] # not @C[4] + stg @C[1],$A[1][4]($dst) # R[1][4] = C[4] ^ (C[1] & C[0]) + + ogr @C[4],@C[3] + xgr @C[4],@C[2] # C[2] ^ (~C[4] | C[3]) + + ngr @C[3],@C[2] + stg @C[4],$A[1][2]($dst) # R[1][2] = C[2] ^ (~C[4] | C[3]) + xgr @C[3],@T[1] # C[1] ^ (C[3] & C[2]) + ogr @T[1],@C[2] + stg @C[3],$A[1][1]($dst) # R[1][1] = C[1] ^ (C[3] & C[2]) + xgr @T[1],@T[0] # C[0] ^ (C[1] | C[2]) + stg @T[1],$A[1][0]($dst) # R[1][0] = C[0] ^ (C[1] | C[2]) + + + lg @C[2],$A[2][3]($src) + lg @C[3],$A[3][4]($src) + lg @C[1],$A[1][2]($src) + lg @C[4],$A[4][0]($src) + lg @C[0],$A[0][1]($src) + + xgr @C[2],@D[3] + xgr @C[3],@D[4] + rllg @C[2],@C[2],$rhotates[2][3] + xgr @C[1],@D[2] + rllg @C[3],@C[3],$rhotates[3][4] + xgr @C[4],@D[0] + rllg @C[1],@C[1],$rhotates[1][2] + xgr @C[0],@D[1] + + lgr @T[0],@C[2] + ngr @C[2],@C[3] + rllg @C[4],@C[4],$rhotates[4][0] + xgr @C[2],@C[1] # C[1] ^ ( C[2] & C[3]) + lghi @T[1],-1 # no 'not' instruction :-( + stg @C[2],$A[2][1]($dst) # R[2][1] = C[1] ^ ( C[2] & C[3]) + + xgr @C[3],@T[1] # not @C[3] + lgr @T[1],@C[4] + ngr @C[4],@C[3] + rllg @C[0],@C[0],$rhotates[0][1] + xgr @C[4],@T[0] # C[2] ^ ( C[4] & ~C[3]) + ogr @T[0],@C[1] + stg @C[4],$A[2][2]($dst) # R[2][2] = C[2] ^ ( C[4] & ~C[3]) + xgr @T[0],@C[0] # C[0] ^ ( C[2] | C[1]) + + ngr @C[1],@C[0] + stg @T[0],$A[2][0]($dst) # R[2][0] = C[0] ^ ( C[2] | C[1]) + xgr @C[1],@T[1] # C[4] ^ ( C[1] & C[0]) + ogr @C[0],@T[1] + stg @C[1],$A[2][4]($dst) # R[2][4] = C[4] ^ ( C[1] & C[0]) + xgr @C[0],@C[3] # ~C[3] ^ ( C[0] | C[4]) + stg @C[0],$A[2][3]($dst) # R[2][3] = ~C[3] ^ ( C[0] | C[4]) + + + lg @C[2],$A[2][1]($src) + lg @C[3],$A[3][2]($src) + lg @C[1],$A[1][0]($src) + lg @C[4],$A[4][3]($src) + lg @C[0],$A[0][4]($src) + + xgr @C[2],@D[1] + xgr @C[3],@D[2] + rllg @C[2],@C[2],$rhotates[2][1] + xgr @C[1],@D[0] + rllg @C[3],@C[3],$rhotates[3][2] + xgr @C[4],@D[3] + rllg @C[1],@C[1],$rhotates[1][0] + xgr @C[0],@D[4] + rllg @C[4],@C[4],$rhotates[4][3] + + lgr @T[0],@C[2] + ogr @C[2],@C[3] + lghi @T[1],-1 # no 'not' instruction :-( + xgr @C[2],@C[1] # C[1] ^ ( C[2] | C[3]) + xgr @C[3],@T[1] # not @C[3] + stg @C[2],$A[3][1]($dst) # R[3][1] = C[1] ^ ( C[2] | C[3]) + + lgr @T[1],@C[4] + ogr @C[4],@C[3] + rllg @C[0],@C[0],$rhotates[0][4] + xgr @C[4],@T[0] # C[2] ^ ( C[4] | ~C[3]) + ngr @T[0],@C[1] + stg @C[4],$A[3][2]($dst) # R[3][2] = C[2] ^ ( C[4] | ~C[3]) + xgr @T[0],@C[0] # C[0] ^ ( C[2] & C[1]) + + ogr @C[1],@C[0] + stg @T[0],$A[3][0]($dst) # R[3][0] = C[0] ^ ( C[2] & C[1]) + xgr @C[1],@T[1] # C[4] ^ ( C[1] | C[0]) + ngr @C[0],@T[1] + stg @C[1],$A[3][4]($dst) # R[3][4] = C[4] ^ ( C[1] | C[0]) + xgr @C[0],@C[3] # ~C[3] ^ ( C[0] & C[4]) + stg @C[0],$A[3][3]($dst) # R[3][3] = ~C[3] ^ ( C[0] & C[4]) + + + xg @D[2],$A[0][2]($src) + xg @D[3],$A[1][3]($src) + xg @D[1],$A[4][1]($src) + xg @D[4],$A[2][4]($src) + xgr $dst,$src # xchg $dst,$src + rllg @D[2],@D[2],$rhotates[0][2] + xg @D[0],$A[3][0]($src) + rllg @D[3],@D[3],$rhotates[1][3] + xgr $src,$dst + rllg @D[1],@D[1],$rhotates[4][1] + xgr $dst,$src + rllg @D[4],@D[4],$rhotates[2][4] +___ + @C = @D[2..4,0,1]; +$code.=<<___; + lgr @T[0],@C[0] + ngr @C[0],@C[1] + lghi @T[1],-1 # no 'not' instruction :-( + xgr @C[0],@C[4] # C[4] ^ ( C[0] & C[1]) + xgr @C[1],@T[1] # not @C[1] + stg @C[0],$A[4][4]($src) # R[4][4] = C[4] ^ ( C[0] & C[1]) + + lgr @T[1],@C[2] + ngr @C[2],@C[1] + rllg @D[0],@D[0],$rhotates[3][0] + xgr @C[2],@T[0] # C[0] ^ ( C[2] & ~C[1]) + ogr @T[0],@C[4] + stg @C[2],$A[4][0]($src) # R[4][0] = C[0] ^ ( C[2] & ~C[1]) + xgr @T[0],@C[3] # C[3] ^ ( C[0] | C[4]) + + ngr @C[4],@C[3] + stg @T[0],$A[4][3]($src) # R[4][3] = C[3] ^ ( C[0] | C[4]) + xgr @C[4],@T[1] # C[2] ^ ( C[4] & C[3]) + ogr @C[3],@T[1] + stg @C[4],$A[4][2]($src) # R[4][2] = C[2] ^ ( C[4] & C[3]) + xgr @C[3],@C[1] # ~C[1] ^ ( C[2] | C[3]) + + lgr @C[1],@C[0] # harmonize with the loop top + lgr @C[0],@T[0] + stg @C[3],$A[4][1]($src) # R[4][1] = ~C[1] ^ ( C[2] | C[3]) + + tmll $iotas,255 + jnz .Loop + + l${g} %r14,$SIZE_T*14($sp) + br %r14 +.size __KeccakF1600,.-__KeccakF1600 +___ +} +{ +$code.=<<___; +.type KeccakF1600,\@function +.align 32 +KeccakF1600: +.LKeccakF1600: + lghi %r1,-$frame + stm${g} %r6,%r15,$SIZE_T*6($sp) + lgr %r0,$sp + la $sp,0(%r1,$sp) + st${g} %r0,0($sp) + + lghi @D[0],-1 # no 'not' instruction :-( + lghi @D[1],-1 + lghi @D[2],-1 + lghi @D[3],-1 + lghi @D[4],-1 + lghi @T[0],-1 + xg @D[0],$A[0][1]($src) + xg @D[1],$A[0][2]($src) + xg @D[2],$A[1][3]($src) + xg @D[3],$A[2][2]($src) + xg @D[4],$A[3][2]($src) + xg @T[0],$A[4][0]($src) + stmg @D[0],@D[1],$A[0][1]($src) + stg @D[2],$A[1][3]($src) + stg @D[3],$A[2][2]($src) + stg @D[4],$A[3][2]($src) + stg @T[0],$A[4][0]($src) + + la $dst,$stdframe($sp) + + bras %r14,__KeccakF1600 + + lghi @D[0],-1 # no 'not' instruction :-( + lghi @D[1],-1 + lghi @D[2],-1 + lghi @D[3],-1 + lghi @D[4],-1 + lghi @T[0],-1 + xg @D[0],$A[0][1]($src) + xg @D[1],$A[0][2]($src) + xg @D[2],$A[1][3]($src) + xg @D[3],$A[2][2]($src) + xg @D[4],$A[3][2]($src) + xg @T[0],$A[4][0]($src) + stmg @D[0],@D[1],$A[0][1]($src) + stg @D[2],$A[1][3]($src) + stg @D[3],$A[2][2]($src) + stg @D[4],$A[3][2]($src) + stg @T[0],$A[4][0]($src) + + lm${g} %r6,%r15,$frame+6*$SIZE_T($sp) + br %r14 +.size KeccakF1600,.-KeccakF1600 +___ +} +{ my ($A_flat,$inp,$len,$bsz) = map("%r$_",(2..5)); + +$code.=<<___; +.globl SHA3_absorb +.type SHA3_absorb,\@function +.align 32 +SHA3_absorb: + lghi %r1,-$frame + stm${g} %r5,%r15,$SIZE_T*5($sp) + lgr %r0,$sp + la $sp,0(%r1,$sp) + st${g} %r0,0($sp) + + lghi @D[0],-1 # no 'not' instruction :-( + lghi @D[1],-1 + lghi @D[2],-1 + lghi @D[3],-1 + lghi @D[4],-1 + lghi @T[0],-1 + xg @D[0],$A[0][1]($src) + xg @D[1],$A[0][2]($src) + xg @D[2],$A[1][3]($src) + xg @D[3],$A[2][2]($src) + xg @D[4],$A[3][2]($src) + xg @T[0],$A[4][0]($src) + stmg @D[0],@D[1],$A[0][1]($src) + stg @D[2],$A[1][3]($src) + stg @D[3],$A[2][2]($src) + stg @D[4],$A[3][2]($src) + stg @T[0],$A[4][0]($src) + +.Loop_absorb: + cl${g}r $len,$bsz + jl .Ldone_absorb + + srl${g} $bsz,3 + la %r1,0($A_flat) + +.Lblock_absorb: + lrvg %r0,0($inp) + la $inp,8($inp) + xg %r0,0(%r1) + a${g}hi $len,-8 + stg %r0,0(%r1) + la %r1,8(%r1) + brct $bsz,.Lblock_absorb + + stm${g} $inp,$len,$frame+3*$SIZE_T($sp) + la $dst,$stdframe($sp) + bras %r14,__KeccakF1600 + lm${g} $inp,$bsz,$frame+3*$SIZE_T($sp) + j .Loop_absorb + +.align 16 +.Ldone_absorb: + lghi @D[0],-1 # no 'not' instruction :-( + lghi @D[1],-1 + lghi @D[2],-1 + lghi @D[3],-1 + lghi @D[4],-1 + lghi @T[0],-1 + xg @D[0],$A[0][1]($src) + xg @D[1],$A[0][2]($src) + xg @D[2],$A[1][3]($src) + xg @D[3],$A[2][2]($src) + xg @D[4],$A[3][2]($src) + xg @T[0],$A[4][0]($src) + stmg @D[0],@D[1],$A[0][1]($src) + stg @D[2],$A[1][3]($src) + stg @D[3],$A[2][2]($src) + stg @D[4],$A[3][2]($src) + stg @T[0],$A[4][0]($src) + + lgr %r2,$len # return value + + lm${g} %r6,%r15,$frame+6*$SIZE_T($sp) + br %r14 +.size SHA3_absorb,.-SHA3_absorb +___ +} +{ my ($A_flat,$out,$len,$bsz) = map("%r$_",(2..5)); + +$code.=<<___; +.globl SHA3_squeeze +.type SHA3_squeeze,\@function +.align 32 +SHA3_squeeze: + srl${g} $bsz,3 + st${g} %r14,2*$SIZE_T($sp) + lghi %r14,8 + st${g} $bsz,5*$SIZE_T($sp) + la %r1,0($A_flat) + + j .Loop_squeeze + +.align 16 +.Loop_squeeze: + cl${g}r $len,%r14 + jl .Ltail_squeeze + + lrvg %r0,0(%r1) + la %r1,8(%r1) + stg %r0,0($out) + la $out,8($out) + a${g}hi $len,-8 # len -= 8 + jz .Ldone_squeeze + + brct $bsz,.Loop_squeeze # bsz-- + + stm${g} $out,$len,3*$SIZE_T($sp) + bras %r14,.LKeccakF1600 + lm${g} $out,$bsz,3*$SIZE_T($sp) + lghi %r14,8 + la %r1,0($A_flat) + j .Loop_squeeze + +.Ltail_squeeze: + lg %r0,0(%r1) +.Loop_tail_squeeze: + stc %r0,0($out) + la $out,1($out) + srlg %r0,8 + brct $len,.Loop_tail_squeeze + +.Ldone_squeeze: + l${g} %r14,2*$SIZE_T($sp) + br %r14 +.size SHA3_squeeze,.-SHA3_squeeze +___ +} +$code.=<<___; +.align 256 + .quad 0,0,0,0,0,0,0,0 +.type iotas,\@object +iotas: + .quad 0x0000000000000001 + .quad 0x0000000000008082 + .quad 0x800000000000808a + .quad 0x8000000080008000 + .quad 0x000000000000808b + .quad 0x0000000080000001 + .quad 0x8000000080008081 + .quad 0x8000000000008009 + .quad 0x000000000000008a + .quad 0x0000000000000088 + .quad 0x0000000080008009 + .quad 0x000000008000000a + .quad 0x000000008000808b + .quad 0x800000000000008b + .quad 0x8000000000008089 + .quad 0x8000000000008003 + .quad 0x8000000000008002 + .quad 0x8000000000000080 + .quad 0x000000000000800a + .quad 0x800000008000000a + .quad 0x8000000080008081 + .quad 0x8000000000008080 + .quad 0x0000000080000001 + .quad 0x8000000080008008 +.size iotas,.-iotas +.asciz "Keccak-1600 absorb and squeeze for s390x, CRYPTOGAMS by " +___ + +# unlike 32-bit shift 64-bit one takes three arguments +$code =~ s/(srlg\s+)(%r[0-9]+),/$1$2,$2,/gm; + +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-x86_64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-x86_64.pl new file mode 100755 index 000000000..42de5bf12 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600-x86_64.pl @@ -0,0 +1,607 @@ +#!/usr/bin/env perl +# Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# Keccak-1600 for x86_64. +# +# June 2017. +# +# Below code is [lane complementing] KECCAK_2X implementation (see +# sha/keccak1600.c) with C[5] and D[5] held in register bank. Though +# instead of actually unrolling the loop pair-wise I simply flip +# pointers to T[][] and A[][] at the end of round. Since number of +# rounds is even, last round writes to A[][] and everything works out. +# How does it compare to x86_64 assembly module in Keccak Code Package? +# Depending on processor it's either as fast or faster by up to 15%... +# +######################################################################## +# Numbers are cycles per processed byte out of large message. +# +# r=1088(*) +# +# P4 25.8 +# Core 2 12.9 +# Westmere 13.7 +# Sandy Bridge 12.9(**) +# Haswell 9.6 +# Skylake 9.4 +# Silvermont 22.8 +# Goldmont 15.8 +# VIA Nano 17.3 +# Sledgehammer 13.3 +# Bulldozer 16.5 +# Ryzen 8.8 +# +# (*) Corresponds to SHA3-256. Improvement over compiler-generate +# varies a lot, most commont coefficient is 15% in comparison to +# gcc-5.x, 50% for gcc-4.x, 90% for gcc-3.x. +# (**) Sandy Bridge has broken rotate instruction. Performance can be +# improved by 14% by replacing rotates with double-precision +# shift with same register as source and destination. + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +*STDOUT=*OUT; + +my @A = map([ 8*$_-100, 8*($_+1)-100, 8*($_+2)-100, + 8*($_+3)-100, 8*($_+4)-100 ], (0,5,10,15,20)); + +my @C = ("%rax","%rbx","%rcx","%rdx","%rbp"); +my @D = map("%r$_",(8..12)); +my @T = map("%r$_",(13..14)); +my $iotas = "%r15"; + +my @rhotates = ([ 0, 1, 62, 28, 27 ], + [ 36, 44, 6, 55, 20 ], + [ 3, 10, 43, 25, 39 ], + [ 41, 45, 15, 21, 8 ], + [ 18, 2, 61, 56, 14 ]); + +$code.=<<___; +.text + +.type __KeccakF1600,\@abi-omnipotent +.align 32 +__KeccakF1600: + mov $A[4][0](%rdi),@C[0] + mov $A[4][1](%rdi),@C[1] + mov $A[4][2](%rdi),@C[2] + mov $A[4][3](%rdi),@C[3] + mov $A[4][4](%rdi),@C[4] + jmp .Loop + +.align 32 +.Loop: + mov $A[0][0](%rdi),@D[0] + mov $A[1][1](%rdi),@D[1] + mov $A[2][2](%rdi),@D[2] + mov $A[3][3](%rdi),@D[3] + + xor $A[0][2](%rdi),@C[2] + xor $A[0][3](%rdi),@C[3] + xor @D[0], @C[0] + xor $A[0][1](%rdi),@C[1] + xor $A[1][2](%rdi),@C[2] + xor $A[1][0](%rdi),@C[0] + mov @C[4],@D[4] + xor $A[0][4](%rdi),@C[4] + + xor @D[2], @C[2] + xor $A[2][0](%rdi),@C[0] + xor $A[1][3](%rdi),@C[3] + xor @D[1], @C[1] + xor $A[1][4](%rdi),@C[4] + + xor $A[3][2](%rdi),@C[2] + xor $A[3][0](%rdi),@C[0] + xor $A[2][3](%rdi),@C[3] + xor $A[2][1](%rdi),@C[1] + xor $A[2][4](%rdi),@C[4] + + mov @C[2],@T[0] + rol \$1,@C[2] + xor @C[0],@C[2] # D[1] = ROL64(C[2], 1) ^ C[0] + xor @D[3], @C[3] + + rol \$1,@C[0] + xor @C[3],@C[0] # D[4] = ROL64(C[0], 1) ^ C[3] + xor $A[3][1](%rdi),@C[1] + + rol \$1,@C[3] + xor @C[1],@C[3] # D[2] = ROL64(C[3], 1) ^ C[1] + xor $A[3][4](%rdi),@C[4] + + rol \$1,@C[1] + xor @C[4],@C[1] # D[0] = ROL64(C[1], 1) ^ C[4] + + rol \$1,@C[4] + xor @T[0],@C[4] # D[3] = ROL64(C[4], 1) ^ C[2] +___ + (@D[0..4], @C) = (@C[1..4,0], @D); +$code.=<<___; + xor @D[1],@C[1] + xor @D[2],@C[2] + rol \$$rhotates[1][1],@C[1] + xor @D[3],@C[3] + xor @D[4],@C[4] + rol \$$rhotates[2][2],@C[2] + xor @D[0],@C[0] + mov @C[1],@T[0] + rol \$$rhotates[3][3],@C[3] + or @C[2],@C[1] + xor @C[0],@C[1] # C[0] ^ ( C[1] | C[2]) + rol \$$rhotates[4][4],@C[4] + + xor ($iotas),@C[1] + lea 8($iotas),$iotas + + mov @C[4],@T[1] + and @C[3],@C[4] + mov @C[1],$A[0][0](%rsi) # R[0][0] = C[0] ^ ( C[1] | C[2]) ^ iotas[i] + xor @C[2],@C[4] # C[2] ^ ( C[4] & C[3]) + not @C[2] + mov @C[4],$A[0][2](%rsi) # R[0][2] = C[2] ^ ( C[4] & C[3]) + + or @C[3],@C[2] + mov $A[4][2](%rdi),@C[4] + xor @T[0],@C[2] # C[1] ^ (~C[2] | C[3]) + mov @C[2],$A[0][1](%rsi) # R[0][1] = C[1] ^ (~C[2] | C[3]) + + and @C[0],@T[0] + mov $A[1][4](%rdi),@C[1] + xor @T[1],@T[0] # C[4] ^ ( C[1] & C[0]) + mov $A[2][0](%rdi),@C[2] + mov @T[0],$A[0][4](%rsi) # R[0][4] = C[4] ^ ( C[1] & C[0]) + + or @C[0],@T[1] + mov $A[0][3](%rdi),@C[0] + xor @C[3],@T[1] # C[3] ^ ( C[4] | C[0]) + mov $A[3][1](%rdi),@C[3] + mov @T[1],$A[0][3](%rsi) # R[0][3] = C[3] ^ ( C[4] | C[0]) + + + xor @D[3],@C[0] + xor @D[2],@C[4] + rol \$$rhotates[0][3],@C[0] + xor @D[1],@C[3] + xor @D[4],@C[1] + rol \$$rhotates[4][2],@C[4] + rol \$$rhotates[3][1],@C[3] + xor @D[0],@C[2] + rol \$$rhotates[1][4],@C[1] + mov @C[0],@T[0] + or @C[4],@C[0] + rol \$$rhotates[2][0],@C[2] + + xor @C[3],@C[0] # C[3] ^ (C[0] | C[4]) + mov @C[0],$A[1][3](%rsi) # R[1][3] = C[3] ^ (C[0] | C[4]) + + mov @C[1],@T[1] + and @T[0],@C[1] + mov $A[0][1](%rdi),@C[0] + xor @C[4],@C[1] # C[4] ^ (C[1] & C[0]) + not @C[4] + mov @C[1],$A[1][4](%rsi) # R[1][4] = C[4] ^ (C[1] & C[0]) + + or @C[3],@C[4] + mov $A[1][2](%rdi),@C[1] + xor @C[2],@C[4] # C[2] ^ (~C[4] | C[3]) + mov @C[4],$A[1][2](%rsi) # R[1][2] = C[2] ^ (~C[4] | C[3]) + + and @C[2],@C[3] + mov $A[4][0](%rdi),@C[4] + xor @T[1],@C[3] # C[1] ^ (C[3] & C[2]) + mov @C[3],$A[1][1](%rsi) # R[1][1] = C[1] ^ (C[3] & C[2]) + + or @C[2],@T[1] + mov $A[2][3](%rdi),@C[2] + xor @T[0],@T[1] # C[0] ^ (C[1] | C[2]) + mov $A[3][4](%rdi),@C[3] + mov @T[1],$A[1][0](%rsi) # R[1][0] = C[0] ^ (C[1] | C[2]) + + + xor @D[3],@C[2] + xor @D[4],@C[3] + rol \$$rhotates[2][3],@C[2] + xor @D[2],@C[1] + rol \$$rhotates[3][4],@C[3] + xor @D[0],@C[4] + rol \$$rhotates[1][2],@C[1] + xor @D[1],@C[0] + rol \$$rhotates[4][0],@C[4] + mov @C[2],@T[0] + and @C[3],@C[2] + rol \$$rhotates[0][1],@C[0] + + not @C[3] + xor @C[1],@C[2] # C[1] ^ ( C[2] & C[3]) + mov @C[2],$A[2][1](%rsi) # R[2][1] = C[1] ^ ( C[2] & C[3]) + + mov @C[4],@T[1] + and @C[3],@C[4] + mov $A[2][1](%rdi),@C[2] + xor @T[0],@C[4] # C[2] ^ ( C[4] & ~C[3]) + mov @C[4],$A[2][2](%rsi) # R[2][2] = C[2] ^ ( C[4] & ~C[3]) + + or @C[1],@T[0] + mov $A[4][3](%rdi),@C[4] + xor @C[0],@T[0] # C[0] ^ ( C[2] | C[1]) + mov @T[0],$A[2][0](%rsi) # R[2][0] = C[0] ^ ( C[2] | C[1]) + + and @C[0],@C[1] + xor @T[1],@C[1] # C[4] ^ ( C[1] & C[0]) + mov @C[1],$A[2][4](%rsi) # R[2][4] = C[4] ^ ( C[1] & C[0]) + + or @C[0],@T[1] + mov $A[1][0](%rdi),@C[1] + xor @C[3],@T[1] # ~C[3] ^ ( C[0] | C[4]) + mov $A[3][2](%rdi),@C[3] + mov @T[1],$A[2][3](%rsi) # R[2][3] = ~C[3] ^ ( C[0] | C[4]) + + + mov $A[0][4](%rdi),@C[0] + + xor @D[1],@C[2] + xor @D[2],@C[3] + rol \$$rhotates[2][1],@C[2] + xor @D[0],@C[1] + rol \$$rhotates[3][2],@C[3] + xor @D[3],@C[4] + rol \$$rhotates[1][0],@C[1] + xor @D[4],@C[0] + rol \$$rhotates[4][3],@C[4] + mov @C[2],@T[0] + or @C[3],@C[2] + rol \$$rhotates[0][4],@C[0] + + not @C[3] + xor @C[1],@C[2] # C[1] ^ ( C[2] | C[3]) + mov @C[2],$A[3][1](%rsi) # R[3][1] = C[1] ^ ( C[2] | C[3]) + + mov @C[4],@T[1] + or @C[3],@C[4] + xor @T[0],@C[4] # C[2] ^ ( C[4] | ~C[3]) + mov @C[4],$A[3][2](%rsi) # R[3][2] = C[2] ^ ( C[4] | ~C[3]) + + and @C[1],@T[0] + xor @C[0],@T[0] # C[0] ^ ( C[2] & C[1]) + mov @T[0],$A[3][0](%rsi) # R[3][0] = C[0] ^ ( C[2] & C[1]) + + or @C[0],@C[1] + xor @T[1],@C[1] # C[4] ^ ( C[1] | C[0]) + mov @C[1],$A[3][4](%rsi) # R[3][4] = C[4] ^ ( C[1] | C[0]) + + and @T[1],@C[0] + xor @C[3],@C[0] # ~C[3] ^ ( C[0] & C[4]) + mov @C[0],$A[3][3](%rsi) # R[3][3] = ~C[3] ^ ( C[0] & C[4]) + + + xor $A[0][2](%rdi),@D[2] + xor $A[1][3](%rdi),@D[3] + rol \$$rhotates[0][2],@D[2] + xor $A[4][1](%rdi),@D[1] + rol \$$rhotates[1][3],@D[3] + xor $A[2][4](%rdi),@D[4] + rol \$$rhotates[4][1],@D[1] + xor $A[3][0](%rdi),@D[0] + xchg %rsi,%rdi + rol \$$rhotates[2][4],@D[4] + rol \$$rhotates[3][0],@D[0] +___ + @C = @D[2..4,0,1]; +$code.=<<___; + mov @C[0],@T[0] + and @C[1],@C[0] + not @C[1] + xor @C[4],@C[0] # C[4] ^ ( C[0] & C[1]) + mov @C[0],$A[4][4](%rdi) # R[4][4] = C[4] ^ ( C[0] & C[1]) + + mov @C[2],@T[1] + and @C[1],@C[2] + xor @T[0],@C[2] # C[0] ^ ( C[2] & ~C[1]) + mov @C[2],$A[4][0](%rdi) # R[4][0] = C[0] ^ ( C[2] & ~C[1]) + + or @C[4],@T[0] + xor @C[3],@T[0] # C[3] ^ ( C[0] | C[4]) + mov @T[0],$A[4][3](%rdi) # R[4][3] = C[3] ^ ( C[0] | C[4]) + + and @C[3],@C[4] + xor @T[1],@C[4] # C[2] ^ ( C[4] & C[3]) + mov @C[4],$A[4][2](%rdi) # R[4][2] = C[2] ^ ( C[4] & C[3]) + + or @T[1],@C[3] + xor @C[1],@C[3] # ~C[1] ^ ( C[2] | C[3]) + mov @C[3],$A[4][1](%rdi) # R[4][1] = ~C[1] ^ ( C[2] | C[3]) + + mov @C[0],@C[1] # harmonize with the loop top + mov @T[0],@C[0] + + test \$255,$iotas + jnz .Loop + + lea -192($iotas),$iotas # rewind iotas + ret +.size __KeccakF1600,.-__KeccakF1600 + +.type KeccakF1600,\@abi-omnipotent +.align 32 +KeccakF1600: +.cfi_startproc + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + + lea 100(%rdi),%rdi # size optimization + sub \$200,%rsp +.cfi_adjust_cfa_offset 200 + + notq $A[0][1](%rdi) + notq $A[0][2](%rdi) + notq $A[1][3](%rdi) + notq $A[2][2](%rdi) + notq $A[3][2](%rdi) + notq $A[4][0](%rdi) + + lea iotas(%rip),$iotas + lea 100(%rsp),%rsi # size optimization + + call __KeccakF1600 + + notq $A[0][1](%rdi) + notq $A[0][2](%rdi) + notq $A[1][3](%rdi) + notq $A[2][2](%rdi) + notq $A[3][2](%rdi) + notq $A[4][0](%rdi) + lea -100(%rdi),%rdi # preserve A[][] + + add \$200,%rsp +.cfi_adjust_cfa_offset -200 + + pop %r15 +.cfi_pop %r15 + pop %r14 +.cfi_pop %r14 + pop %r13 +.cfi_pop %r13 + pop %r12 +.cfi_pop %r12 + pop %rbp +.cfi_pop %rbp + pop %rbx +.cfi_pop %rbx + ret +.cfi_endproc +.size KeccakF1600,.-KeccakF1600 +___ + +{ my ($A_flat,$inp,$len,$bsz) = ("%rdi","%rsi","%rdx","%rcx"); + ($A_flat,$inp) = ("%r8","%r9"); +$code.=<<___; +.globl SHA3_absorb +.type SHA3_absorb,\@function,4 +.align 32 +SHA3_absorb: +.cfi_startproc + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + + lea 100(%rdi),%rdi # size optimization + sub \$232,%rsp +.cfi_adjust_cfa_offset 232 + + mov %rsi,$inp + lea 100(%rsp),%rsi # size optimization + + notq $A[0][1](%rdi) + notq $A[0][2](%rdi) + notq $A[1][3](%rdi) + notq $A[2][2](%rdi) + notq $A[3][2](%rdi) + notq $A[4][0](%rdi) + lea iotas(%rip),$iotas + + mov $bsz,216-100(%rsi) # save bsz + +.Loop_absorb: + cmp $bsz,$len + jc .Ldone_absorb + + shr \$3,$bsz + lea -100(%rdi),$A_flat + +.Lblock_absorb: + mov ($inp),%rax + lea 8($inp),$inp + xor ($A_flat),%rax + lea 8($A_flat),$A_flat + sub \$8,$len + mov %rax,-8($A_flat) + sub \$1,$bsz + jnz .Lblock_absorb + + mov $inp,200-100(%rsi) # save inp + mov $len,208-100(%rsi) # save len + call __KeccakF1600 + mov 200-100(%rsi),$inp # pull inp + mov 208-100(%rsi),$len # pull len + mov 216-100(%rsi),$bsz # pull bsz + jmp .Loop_absorb + +.align 32 +.Ldone_absorb: + mov $len,%rax # return value + + notq $A[0][1](%rdi) + notq $A[0][2](%rdi) + notq $A[1][3](%rdi) + notq $A[2][2](%rdi) + notq $A[3][2](%rdi) + notq $A[4][0](%rdi) + + add \$232,%rsp +.cfi_adjust_cfa_offset -232 + + pop %r15 +.cfi_pop %r15 + pop %r14 +.cfi_pop %r14 + pop %r13 +.cfi_pop %r13 + pop %r12 +.cfi_pop %r12 + pop %rbp +.cfi_pop %rbp + pop %rbx +.cfi_pop %rbx + ret +.cfi_endproc +.size SHA3_absorb,.-SHA3_absorb +___ +} +{ my ($A_flat,$out,$len,$bsz) = ("%rdi","%rsi","%rdx","%rcx"); + ($out,$len,$bsz) = ("%r12","%r13","%r14"); + +$code.=<<___; +.globl SHA3_squeeze +.type SHA3_squeeze,\@function,4 +.align 32 +SHA3_squeeze: +.cfi_startproc + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + + shr \$3,%rcx + mov $A_flat,%r8 + mov %rsi,$out + mov %rdx,$len + mov %rcx,$bsz + jmp .Loop_squeeze + +.align 32 +.Loop_squeeze: + cmp \$8,$len + jb .Ltail_squeeze + + mov (%r8),%rax + lea 8(%r8),%r8 + mov %rax,($out) + lea 8($out),$out + sub \$8,$len # len -= 8 + jz .Ldone_squeeze + + sub \$1,%rcx # bsz-- + jnz .Loop_squeeze + + call KeccakF1600 + mov $A_flat,%r8 + mov $bsz,%rcx + jmp .Loop_squeeze + +.Ltail_squeeze: + mov %r8, %rsi + mov $out,%rdi + mov $len,%rcx + .byte 0xf3,0xa4 # rep movsb + +.Ldone_squeeze: + pop %r14 +.cfi_pop %r14 + pop %r13 +.cfi_pop %r13 + pop %r12 +.cfi_pop %r13 + ret +.cfi_endproc +.size SHA3_squeeze,.-SHA3_squeeze +___ +} +$code.=<<___; +.align 256 + .quad 0,0,0,0,0,0,0,0 +.type iotas,\@object +iotas: + .quad 0x0000000000000001 + .quad 0x0000000000008082 + .quad 0x800000000000808a + .quad 0x8000000080008000 + .quad 0x000000000000808b + .quad 0x0000000080000001 + .quad 0x8000000080008081 + .quad 0x8000000000008009 + .quad 0x000000000000008a + .quad 0x0000000000000088 + .quad 0x0000000080008009 + .quad 0x000000008000000a + .quad 0x000000008000808b + .quad 0x800000000000008b + .quad 0x8000000000008089 + .quad 0x8000000000008003 + .quad 0x8000000000008002 + .quad 0x8000000000000080 + .quad 0x000000000000800a + .quad 0x800000008000000a + .quad 0x8000000080008081 + .quad 0x8000000000008080 + .quad 0x0000000080000001 + .quad 0x8000000080008008 +.size iotas,.-iotas +.asciz "Keccak-1600 absorb and squeeze for x86_64, CRYPTOGAMS by " +___ + +foreach (split("\n",$code)) { + # Below replacement results in 11.2 on Sandy Bridge, 9.4 on + # Haswell, but it hurts other processors by up to 2-3-4x... + #s/rol\s+(\$[0-9]+),(%[a-z][a-z0-9]+)/shld\t$1,$2,$2/; + # Below replacement results in 9.3 on Haswell [as well as + # on Ryzen, i.e. it *hurts* Ryzen]... + #s/rol\s+\$([0-9]+),(%[a-z][a-z0-9]+)/rorx\t\$64-$1,$2,$2/; + + print $_, "\n"; +} + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600p8-ppc.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600p8-ppc.pl new file mode 100755 index 000000000..de2bcd660 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/keccak1600p8-ppc.pl @@ -0,0 +1,850 @@ +#!/usr/bin/env perl +# Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# Keccak-1600 for PowerISA 2.07. +# +# June 2017. +# +# This is straightforward KECCAK_1X_ALT SIMD implementation, but with +# disjoint Rho and Pi. The module is ABI-bitness- and endian-neutral. +# POWER8 processor spends 9.8 cycles to process byte out of large +# buffer for r=1088, which matches SHA3-256. This is 17% better than +# scalar PPC64 code. It probably should be noted that if POWER8's +# successor can achieve higher scalar instruction issue rate, then +# this module will loose... And it does on POWER9 with 12.0 vs. 9.4. + +$flavour = shift; + +if ($flavour =~ /64/) { + $SIZE_T =8; + $LRSAVE =2*$SIZE_T; + $UCMP ="cmpld"; + $STU ="stdu"; + $POP ="ld"; + $PUSH ="std"; +} elsif ($flavour =~ /32/) { + $SIZE_T =4; + $LRSAVE =$SIZE_T; + $STU ="stwu"; + $POP ="lwz"; + $PUSH ="stw"; + $UCMP ="cmplw"; +} else { die "nonsense $flavour"; } + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or +die "can't locate ppc-xlate.pl"; + +open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!"; + +$FRAME=6*$SIZE_T+13*16; # 13*16 is for v20-v31 offload + +my $sp ="r1"; + +my $iotas = "r12"; + +######################################################################## +# Register layout: +# +# v0 A[0][0] A[1][0] +# v1 A[0][1] A[1][1] +# v2 A[0][2] A[1][2] +# v3 A[0][3] A[1][3] +# v4 A[0][4] A[1][4] +# +# v5 A[2][0] A[3][0] +# v6 A[2][1] A[3][1] +# v7 A[2][2] A[3][2] +# v8 A[2][3] A[3][3] +# v9 A[2][4] A[3][4] +# +# v10 A[4][0] A[4][1] +# v11 A[4][2] A[4][3] +# v12 A[4][4] A[4][4] +# +# v13..25 rhotates[][] +# v26..31 volatile +# +$code.=<<___; +.machine "any" +.text + +.type KeccakF1600_int,\@function +.align 5 +KeccakF1600_int: + li r0,24 + mtctr r0 + li r0,0 + b .Loop + +.align 4 +.Loop: + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Theta + vxor v26,v0, v5 ; A[0..1][0]^A[2..3][0] + vxor v27,v1, v6 ; A[0..1][1]^A[2..3][1] + vxor v28,v2, v7 ; A[0..1][2]^A[2..3][2] + vxor v29,v3, v8 ; A[0..1][3]^A[2..3][3] + vxor v30,v4, v9 ; A[0..1][4]^A[2..3][4] + vpermdi v31,v26,v27,0b00 ; A[0][0..1]^A[2][0..1] + vpermdi v26,v26,v27,0b11 ; A[1][0..1]^A[3][0..1] + vpermdi v27,v28,v29,0b00 ; A[0][2..3]^A[2][2..3] + vpermdi v28,v28,v29,0b11 ; A[1][2..3]^A[3][2..3] + vpermdi v29,v30,v30,0b10 ; A[1..0][4]^A[3..2][4] + vxor v26,v26,v31 ; C[0..1] + vxor v27,v27,v28 ; C[2..3] + vxor v28,v29,v30 ; C[4..4] + vspltisb v31,1 + vxor v26,v26,v10 ; C[0..1] ^= A[4][0..1] + vxor v27,v27,v11 ; C[2..3] ^= A[4][2..3] + vxor v28,v28,v12 ; C[4..4] ^= A[4][4..4], low! + + vrld v29,v26,v31 ; ROL64(C[0..1],1) + vrld v30,v27,v31 ; ROL64(C[2..3],1) + vrld v31,v28,v31 ; ROL64(C[4..4],1) + vpermdi v31,v31,v29,0b10 + vxor v26,v26,v30 ; C[0..1] ^= ROL64(C[2..3],1) + vxor v27,v27,v31 ; C[2..3] ^= ROL64(C[4..0],1) + vxor v28,v28,v29 ; C[4..4] ^= ROL64(C[0..1],1), low! + + vpermdi v29,v26,v26,0b00 ; C[0..0] + vpermdi v30,v28,v26,0b10 ; C[4..0] + vpermdi v31,v28,v28,0b11 ; C[4..4] + vxor v1, v1, v29 ; A[0..1][1] ^= C[0..0] + vxor v6, v6, v29 ; A[2..3][1] ^= C[0..0] + vxor v10,v10,v30 ; A[4][0..1] ^= C[4..0] + vxor v0, v0, v31 ; A[0..1][0] ^= C[4..4] + vxor v5, v5, v31 ; A[2..3][0] ^= C[4..4] + + vpermdi v29,v27,v27,0b00 ; C[2..2] + vpermdi v30,v26,v26,0b11 ; C[1..1] + vpermdi v31,v26,v27,0b10 ; C[1..2] + vxor v3, v3, v29 ; A[0..1][3] ^= C[2..2] + vxor v8, v8, v29 ; A[2..3][3] ^= C[2..2] + vxor v2, v2, v30 ; A[0..1][2] ^= C[1..1] + vxor v7, v7, v30 ; A[2..3][2] ^= C[1..1] + vxor v11,v11,v31 ; A[4][2..3] ^= C[1..2] + + vpermdi v29,v27,v27,0b11 ; C[3..3] + vxor v4, v4, v29 ; A[0..1][4] ^= C[3..3] + vxor v9, v9, v29 ; A[2..3][4] ^= C[3..3] + vxor v12,v12,v29 ; A[4..4][4] ^= C[3..3] + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Rho + vrld v26,v0, v13 ; v0 + vrld v1, v1, v14 + vrld v27,v2, v15 ; v2 + vrld v28,v3, v16 ; v3 + vrld v4, v4, v17 + vrld v5, v5, v18 + vrld v6, v6, v19 + vrld v29,v7, v20 ; v7 + vrld v8, v8, v21 + vrld v9, v9, v22 + vrld v10,v10,v23 + vrld v30,v11,v24 ; v11 + vrld v12,v12,v25 + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Pi + vpermdi v0, v26,v28,0b00 ; [0][0] [1][0] < [0][0] [0][3] + vpermdi v2, v29,v5, 0b00 ; [0][2] [1][2] < [2][2] [2][0] + vpermdi v11,v9, v5, 0b01 ; [4][2] [4][3] < [2][4] [3][0] + vpermdi v5, v1, v4, 0b00 ; [2][0] [3][0] < [0][1] [0][4] + vpermdi v1, v1, v4, 0b11 ; [0][1] [1][1] < [1][1] [1][4] + vpermdi v3, v8, v6, 0b11 ; [0][3] [1][3] < [3][3] [3][1] + vpermdi v4, v12,v30,0b10 ; [0][4] [1][4] < [4][4] [4][2] + vpermdi v7, v8, v6, 0b00 ; [2][2] [3][2] < [2][3] [2][1] + vpermdi v6, v27,v26,0b11 ; [2][1] [3][1] < [1][2] [1][0] + vpermdi v8, v9, v29,0b11 ; [2][3] [3][3] < [3][4] [3][2] + vpermdi v12,v10,v10,0b11 ; [4][4] [4][4] < [4][1] [4][1] + vpermdi v9, v10,v30,0b01 ; [2][4] [3][4] < [4][0] [4][3] + vpermdi v10,v27,v28,0b01 ; [4][0] [4][1] < [0][2] [1][3] + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Chi + Iota + lvx_u v31,$iotas,r0 ; iotas[index] + addic r0,r0,16 ; index++ + + vandc v26,v2, v1 ; (~A[0..1][1] & A[0..1][2]) + vandc v27,v3, v2 ; (~A[0..1][2] & A[0..1][3]) + vandc v28,v4, v3 ; (~A[0..1][3] & A[0..1][4]) + vandc v29,v0, v4 ; (~A[0..1][4] & A[0..1][0]) + vandc v30,v1, v0 ; (~A[0..1][0] & A[0..1][1]) + vxor v0, v0, v26 ; A[0..1][0] ^= (~A[0..1][1] & A[0..1][2]) + vxor v1, v1, v27 ; A[0..1][1] ^= (~A[0..1][2] & A[0..1][3]) + vxor v2, v2, v28 ; A[0..1][2] ^= (~A[0..1][3] & A[0..1][4]) + vxor v3, v3, v29 ; A[0..1][3] ^= (~A[0..1][4] & A[0..1][0]) + vxor v4, v4, v30 ; A[0..1][4] ^= (~A[0..1][0] & A[0..1][1]) + + vandc v26,v7, v6 ; (~A[2..3][1] & A[2..3][2]) + vandc v27,v8, v7 ; (~A[2..3][2] & A[2..3][3]) + vandc v28,v9, v8 ; (~A[2..3][3] & A[2..3][4]) + vandc v29,v5, v9 ; (~A[2..3][4] & A[2..3][0]) + vandc v30,v6, v5 ; (~A[2..3][0] & A[2..3][1]) + vxor v5, v5, v26 ; A[2..3][0] ^= (~A[2..3][1] & A[2..3][2]) + vxor v6, v6, v27 ; A[2..3][1] ^= (~A[2..3][2] & A[2..3][3]) + vxor v7, v7, v28 ; A[2..3][2] ^= (~A[2..3][3] & A[2..3][4]) + vxor v8, v8, v29 ; A[2..3][3] ^= (~A[2..3][4] & A[2..3][0]) + vxor v9, v9, v30 ; A[2..3][4] ^= (~A[2..3][0] & A[2..3][1]) + + vxor v0, v0, v31 ; A[0][0] ^= iotas[index++] + + vpermdi v26,v10,v11,0b10 ; A[4][1..2] + vpermdi v27,v12,v10,0b00 ; A[4][4..0] + vpermdi v28,v11,v12,0b10 ; A[4][3..4] + vpermdi v29,v10,v10,0b10 ; A[4][1..0] + vandc v26,v11,v26 ; (~A[4][1..2] & A[4][2..3]) + vandc v27,v27,v28 ; (~A[4][3..4] & A[4][4..0]) + vandc v28,v10,v29 ; (~A[4][1..0] & A[4][0..1]) + vxor v10,v10,v26 ; A[4][0..1] ^= (~A[4][1..2] & A[4][2..3]) + vxor v11,v11,v27 ; A[4][2..3] ^= (~A[4][3..4] & A[4][4..0]) + vxor v12,v12,v28 ; A[4][4..4] ^= (~A[4][0..1] & A[4][1..0]) + + bdnz .Loop + + vpermdi v12,v12,v12,0b11 ; broadcast A[4][4] + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 +.size KeccakF1600_int,.-KeccakF1600_int + +.type KeccakF1600,\@function +.align 5 +KeccakF1600: + $STU $sp,-$FRAME($sp) + li r10,`15+6*$SIZE_T` + li r11,`31+6*$SIZE_T` + mflr r8 + mfspr r7, 256 ; save vrsave + stvx v20,r10,$sp + addi r10,r10,32 + stvx v21,r11,$sp + addi r11,r11,32 + stvx v22,r10,$sp + addi r10,r10,32 + stvx v23,r11,$sp + addi r11,r11,32 + stvx v24,r10,$sp + addi r10,r10,32 + stvx v25,r11,$sp + addi r11,r11,32 + stvx v26,r10,$sp + addi r10,r10,32 + stvx v27,r11,$sp + addi r11,r11,32 + stvx v28,r10,$sp + addi r10,r10,32 + stvx v29,r11,$sp + addi r11,r11,32 + stvx v30,r10,$sp + stvx v31,r11,$sp + stw r7,`$FRAME-4`($sp) ; save vrsave + li r0, -1 + $PUSH r8,`$FRAME+$LRSAVE`($sp) + mtspr 256, r0 ; preserve all AltiVec registers + + li r11,16 + lvx_4w v0,0,r3 ; load A[5][5] + li r10,32 + lvx_4w v1,r11,r3 + addi r11,r11,32 + lvx_4w v2,r10,r3 + addi r10,r10,32 + lvx_4w v3,r11,r3 + addi r11,r11,32 + lvx_4w v4,r10,r3 + addi r10,r10,32 + lvx_4w v5,r11,r3 + addi r11,r11,32 + lvx_4w v6,r10,r3 + addi r10,r10,32 + lvx_4w v7,r11,r3 + addi r11,r11,32 + lvx_4w v8,r10,r3 + addi r10,r10,32 + lvx_4w v9,r11,r3 + addi r11,r11,32 + lvx_4w v10,r10,r3 + addi r10,r10,32 + lvx_4w v11,r11,r3 + lvx_splt v12,r10,r3 + + bl PICmeup + + li r11,16 + lvx_u v13,0,r12 ; load rhotates + li r10,32 + lvx_u v14,r11,r12 + addi r11,r11,32 + lvx_u v15,r10,r12 + addi r10,r10,32 + lvx_u v16,r11,r12 + addi r11,r11,32 + lvx_u v17,r10,r12 + addi r10,r10,32 + lvx_u v18,r11,r12 + addi r11,r11,32 + lvx_u v19,r10,r12 + addi r10,r10,32 + lvx_u v20,r11,r12 + addi r11,r11,32 + lvx_u v21,r10,r12 + addi r10,r10,32 + lvx_u v22,r11,r12 + addi r11,r11,32 + lvx_u v23,r10,r12 + addi r10,r10,32 + lvx_u v24,r11,r12 + lvx_u v25,r10,r12 + addi r12,r12,`16*16` ; points at iotas + + bl KeccakF1600_int + + li r11,16 + stvx_4w v0,0,r3 ; return A[5][5] + li r10,32 + stvx_4w v1,r11,r3 + addi r11,r11,32 + stvx_4w v2,r10,r3 + addi r10,r10,32 + stvx_4w v3,r11,r3 + addi r11,r11,32 + stvx_4w v4,r10,r3 + addi r10,r10,32 + stvx_4w v5,r11,r3 + addi r11,r11,32 + stvx_4w v6,r10,r3 + addi r10,r10,32 + stvx_4w v7,r11,r3 + addi r11,r11,32 + stvx_4w v8,r10,r3 + addi r10,r10,32 + stvx_4w v9,r11,r3 + addi r11,r11,32 + stvx_4w v10,r10,r3 + addi r10,r10,32 + stvx_4w v11,r11,r3 + stvdx_u v12,r10,r3 + + li r10,`15+6*$SIZE_T` + li r11,`31+6*$SIZE_T` + mtlr r8 + mtspr 256, r7 ; restore vrsave + lvx v20,r10,$sp + addi r10,r10,32 + lvx v21,r11,$sp + addi r11,r11,32 + lvx v22,r10,$sp + addi r10,r10,32 + lvx v23,r11,$sp + addi r11,r11,32 + lvx v24,r10,$sp + addi r10,r10,32 + lvx v25,r11,$sp + addi r11,r11,32 + lvx v26,r10,$sp + addi r10,r10,32 + lvx v27,r11,$sp + addi r11,r11,32 + lvx v28,r10,$sp + addi r10,r10,32 + lvx v29,r11,$sp + addi r11,r11,32 + lvx v30,r10,$sp + lvx v31,r11,$sp + addi $sp,$sp,$FRAME + blr + .long 0 + .byte 0,12,0x04,1,0x80,0,1,0 + .long 0 +.size KeccakF1600,.-KeccakF1600 +___ +{ +my ($A_jagged,$inp,$len,$bsz) = map("r$_",(3..6)); + +$code.=<<___; +.globl SHA3_absorb +.type SHA3_absorb,\@function +.align 5 +SHA3_absorb: + $STU $sp,-$FRAME($sp) + li r10,`15+6*$SIZE_T` + li r11,`31+6*$SIZE_T` + mflr r8 + mfspr r7, 256 ; save vrsave + stvx v20,r10,$sp + addi r10,r10,32 + stvx v21,r11,$sp + addi r11,r11,32 + stvx v22,r10,$sp + addi r10,r10,32 + stvx v23,r11,$sp + addi r11,r11,32 + stvx v24,r10,$sp + addi r10,r10,32 + stvx v25,r11,$sp + addi r11,r11,32 + stvx v26,r10,$sp + addi r10,r10,32 + stvx v27,r11,$sp + addi r11,r11,32 + stvx v28,r10,$sp + addi r10,r10,32 + stvx v29,r11,$sp + addi r11,r11,32 + stvx v30,r10,$sp + stvx v31,r11,$sp + stw r7,`$FRAME-4`($sp) ; save vrsave + li r0, -1 + $PUSH r8,`$FRAME+$LRSAVE`($sp) + mtspr 256, r0 ; preserve all AltiVec registers + + li r11,16 + lvx_4w v0,0,$A_jagged ; load A[5][5] + li r10,32 + lvx_4w v1,r11,$A_jagged + addi r11,r11,32 + lvx_4w v2,r10,$A_jagged + addi r10,r10,32 + lvx_4w v3,r11,$A_jagged + addi r11,r11,32 + lvx_4w v4,r10,$A_jagged + addi r10,r10,32 + lvx_4w v5,r11,$A_jagged + addi r11,r11,32 + lvx_4w v6,r10,$A_jagged + addi r10,r10,32 + lvx_4w v7,r11,$A_jagged + addi r11,r11,32 + lvx_4w v8,r10,$A_jagged + addi r10,r10,32 + lvx_4w v9,r11,$A_jagged + addi r11,r11,32 + lvx_4w v10,r10,$A_jagged + addi r10,r10,32 + lvx_4w v11,r11,$A_jagged + lvx_splt v12,r10,$A_jagged + + bl PICmeup + + li r11,16 + lvx_u v13,0,r12 ; load rhotates + li r10,32 + lvx_u v14,r11,r12 + addi r11,r11,32 + lvx_u v15,r10,r12 + addi r10,r10,32 + lvx_u v16,r11,r12 + addi r11,r11,32 + lvx_u v17,r10,r12 + addi r10,r10,32 + lvx_u v18,r11,r12 + addi r11,r11,32 + lvx_u v19,r10,r12 + addi r10,r10,32 + lvx_u v20,r11,r12 + addi r11,r11,32 + lvx_u v21,r10,r12 + addi r10,r10,32 + lvx_u v22,r11,r12 + addi r11,r11,32 + lvx_u v23,r10,r12 + addi r10,r10,32 + lvx_u v24,r11,r12 + lvx_u v25,r10,r12 + li r10,-32 + li r11,-16 + addi r12,r12,`16*16` ; points at iotas + b .Loop_absorb + +.align 4 +.Loop_absorb: + $UCMP $len,$bsz ; len < bsz? + blt .Labsorbed + + sub $len,$len,$bsz ; len -= bsz + srwi r0,$bsz,3 + mtctr r0 + + lvx_u v30,r10,r12 ; permutation masks + lvx_u v31,r11,r12 + ?vspltisb v27,7 ; prepare masks for byte swap + ?vxor v30,v30,v27 ; on big-endian + ?vxor v31,v31,v27 + + vxor v27,v27,v27 ; zero + lvdx_u v26,0,$inp + addi $inp,$inp,8 + vperm v26,v26,v27,v30 + vxor v0, v0, v26 + bdz .Lprocess_block + lvdx_u v26,0,$inp + addi $inp,$inp,8 + vperm v26,v26,v27,v30 + vxor v1, v1, v26 + bdz .Lprocess_block + lvdx_u v26,0,$inp + addi $inp,$inp,8 + vperm v26,v26,v27,v30 + vxor v2, v2, v26 + bdz .Lprocess_block + lvdx_u v26,0,$inp + addi $inp,$inp,8 + vperm v26,v26,v27,v30 + vxor v3, v3, v26 + bdz .Lprocess_block + lvdx_u v26,0,$inp + addi $inp,$inp,8 + vperm v26,v26,v27,v30 + vxor v4, v4, v26 + bdz .Lprocess_block + lvdx_u v26,0,$inp + addi $inp,$inp,8 + vperm v26,v26,v27,v31 + vxor v0, v0, v26 + bdz .Lprocess_block + lvdx_u v26,0,$inp + addi $inp,$inp,8 + vperm v26,v26,v27,v31 + vxor v1, v1, v26 + bdz .Lprocess_block + lvdx_u v26,0,$inp + addi $inp,$inp,8 + vperm v26,v26,v27,v31 + vxor v2, v2, v26 + bdz .Lprocess_block + lvdx_u v26,0,$inp + addi $inp,$inp,8 + vperm v26,v26,v27,v31 + vxor v3, v3, v26 + bdz .Lprocess_block + lvdx_u v26,0,$inp + addi $inp,$inp,8 + vperm v26,v26,v27,v31 + vxor v4, v4, v26 + bdz .Lprocess_block + lvdx_u v26,0,$inp + addi $inp,$inp,8 + vperm v26,v26,v27,v30 + vxor v5, v5, v26 + bdz .Lprocess_block + lvdx_u v26,0,$inp + addi $inp,$inp,8 + vperm v26,v26,v27,v30 + vxor v6, v6, v26 + bdz .Lprocess_block + lvdx_u v26,0,$inp + addi $inp,$inp,8 + vperm v26,v26,v27,v30 + vxor v7, v7, v26 + bdz .Lprocess_block + lvdx_u v26,0,$inp + addi $inp,$inp,8 + vperm v26,v26,v27,v30 + vxor v8, v8, v26 + bdz .Lprocess_block + lvdx_u v26,0,$inp + addi $inp,$inp,8 + vperm v26,v26,v27,v30 + vxor v9, v9, v26 + bdz .Lprocess_block + lvdx_u v26,0,$inp + addi $inp,$inp,8 + vperm v26,v26,v27,v31 + vxor v5, v5, v26 + bdz .Lprocess_block + lvdx_u v26,0,$inp + addi $inp,$inp,8 + vperm v26,v26,v27,v31 + vxor v6, v6, v26 + bdz .Lprocess_block + lvdx_u v26,0,$inp + addi $inp,$inp,8 + vperm v26,v26,v27,v31 + vxor v7, v7, v26 + bdz .Lprocess_block + lvdx_u v26,0,$inp + addi $inp,$inp,8 + vperm v26,v26,v27,v31 + vxor v8, v8, v26 + bdz .Lprocess_block + lvdx_u v26,0,$inp + addi $inp,$inp,8 + vperm v26,v26,v27,v31 + vxor v9, v9, v26 + bdz .Lprocess_block + lvdx_u v26,0,$inp + addi $inp,$inp,8 + vperm v26,v26,v27,v30 + vxor v10, v10, v26 + bdz .Lprocess_block + lvdx_u v26,0,$inp + addi $inp,$inp,8 + vperm v26,v26,v27,v31 + vxor v10, v10, v26 + bdz .Lprocess_block + lvdx_u v26,0,$inp + addi $inp,$inp,8 + vperm v26,v26,v27,v30 + vxor v11, v11, v26 + bdz .Lprocess_block + lvdx_u v26,0,$inp + addi $inp,$inp,8 + vperm v26,v26,v27,v31 + vxor v11, v11, v26 + bdz .Lprocess_block + lvdx_u v26,0,$inp + addi $inp,$inp,8 + vperm v26,v26,v27,v31 + vxor v12, v12, v26 + +.Lprocess_block: + bl KeccakF1600_int + + b .Loop_absorb + +.align 4 +.Labsorbed: + li r11,16 + stvx_4w v0,0,$A_jagged ; return A[5][5] + li r10,32 + stvx_4w v1,r11,$A_jagged + addi r11,r11,32 + stvx_4w v2,r10,$A_jagged + addi r10,r10,32 + stvx_4w v3,r11,$A_jagged + addi r11,r11,32 + stvx_4w v4,r10,$A_jagged + addi r10,r10,32 + stvx_4w v5,r11,$A_jagged + addi r11,r11,32 + stvx_4w v6,r10,$A_jagged + addi r10,r10,32 + stvx_4w v7,r11,$A_jagged + addi r11,r11,32 + stvx_4w v8,r10,$A_jagged + addi r10,r10,32 + stvx_4w v9,r11,$A_jagged + addi r11,r11,32 + stvx_4w v10,r10,$A_jagged + addi r10,r10,32 + stvx_4w v11,r11,$A_jagged + stvdx_u v12,r10,$A_jagged + + mr r3,$len ; return value + li r10,`15+6*$SIZE_T` + li r11,`31+6*$SIZE_T` + mtlr r8 + mtspr 256, r7 ; restore vrsave + lvx v20,r10,$sp + addi r10,r10,32 + lvx v21,r11,$sp + addi r11,r11,32 + lvx v22,r10,$sp + addi r10,r10,32 + lvx v23,r11,$sp + addi r11,r11,32 + lvx v24,r10,$sp + addi r10,r10,32 + lvx v25,r11,$sp + addi r11,r11,32 + lvx v26,r10,$sp + addi r10,r10,32 + lvx v27,r11,$sp + addi r11,r11,32 + lvx v28,r10,$sp + addi r10,r10,32 + lvx v29,r11,$sp + addi r11,r11,32 + lvx v30,r10,$sp + lvx v31,r11,$sp + addi $sp,$sp,$FRAME + blr + .long 0 + .byte 0,12,0x04,1,0x80,0,4,0 + .long 0 +.size SHA3_absorb,.-SHA3_absorb +___ +} +{ +my ($A_jagged,$out,$len,$bsz) = map("r$_",(3..6)); + +$code.=<<___; +.globl SHA3_squeeze +.type SHA3_squeeze,\@function +.align 5 +SHA3_squeeze: + mflr r9 ; r9 is not touched by KeccakF1600 + subi $out,$out,1 ; prepare for stbu + addi r8,$A_jagged,4 ; prepare volatiles + mr r10,$bsz + li r11,0 + b .Loop_squeeze +.align 4 +.Loop_squeeze: + lwzx r7,r11,r8 ; lo + lwzx r0,r11,$A_jagged ; hi + ${UCMP}i $len,8 + blt .Lsqueeze_tail + + stbu r7,1($out) ; write lo + srwi r7,r7,8 + stbu r7,1($out) + srwi r7,r7,8 + stbu r7,1($out) + srwi r7,r7,8 + stbu r7,1($out) + stbu r0,1($out) ; write hi + srwi r0,r0,8 + stbu r0,1($out) + srwi r0,r0,8 + stbu r0,1($out) + srwi r0,r0,8 + stbu r0,1($out) + + subic. $len,$len,8 + beqlr ; return if done + + subic. r10,r10,8 + ble .Loutput_expand + + addi r11,r11,16 ; calculate jagged index + cmplwi r11,`16*5` + blt .Loop_squeeze + subi r11,r11,72 + beq .Loop_squeeze + addi r11,r11,72 + cmplwi r11,`16*5+8` + subi r11,r11,8 + beq .Loop_squeeze + addi r11,r11,8 + cmplwi r11,`16*10` + subi r11,r11,72 + beq .Loop_squeeze + addi r11,r11,72 + blt .Loop_squeeze + subi r11,r11,8 + b .Loop_squeeze + +.align 4 +.Loutput_expand: + bl KeccakF1600 + mtlr r9 + + addi r8,$A_jagged,4 ; restore volatiles + mr r10,$bsz + li r11,0 + b .Loop_squeeze + +.align 4 +.Lsqueeze_tail: + mtctr $len + subic. $len,$len,4 + ble .Loop_tail_lo + li r8,4 + mtctr r8 +.Loop_tail_lo: + stbu r7,1($out) + srdi r7,r7,8 + bdnz .Loop_tail_lo + ble .Lsqueeze_done + mtctr $len +.Loop_tail_hi: + stbu r0,1($out) + srdi r0,r0,8 + bdnz .Loop_tail_hi + +.Lsqueeze_done: + blr + .long 0 + .byte 0,12,0x14,0,0,0,4,0 + .long 0 +.size SHA3_squeeze,.-SHA3_squeeze +___ +} +$code.=<<___; +.align 6 +PICmeup: + mflr r0 + bcl 20,31,\$+4 + mflr r12 ; vvvvvv "distance" between . and 1st data entry + addi r12,r12,`64-8` + mtlr r0 + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 + .space `64-9*4` +.type rhotates,\@object +.align 6 +rhotates: + .quad 0, 36 + .quad 1, 44 + .quad 62, 6 + .quad 28, 55 + .quad 27, 20 + .quad 3, 41 + .quad 10, 45 + .quad 43, 15 + .quad 25, 21 + .quad 39, 8 + .quad 18, 2 + .quad 61, 56 + .quad 14, 14 +.size rhotates,.-rhotates + .quad 0,0 + .quad 0x0001020304050607,0x1011121314151617 + .quad 0x1011121314151617,0x0001020304050607 +.type iotas,\@object +iotas: + .quad 0x0000000000000001,0 + .quad 0x0000000000008082,0 + .quad 0x800000000000808a,0 + .quad 0x8000000080008000,0 + .quad 0x000000000000808b,0 + .quad 0x0000000080000001,0 + .quad 0x8000000080008081,0 + .quad 0x8000000000008009,0 + .quad 0x000000000000008a,0 + .quad 0x0000000000000088,0 + .quad 0x0000000080008009,0 + .quad 0x000000008000000a,0 + .quad 0x000000008000808b,0 + .quad 0x800000000000008b,0 + .quad 0x8000000000008089,0 + .quad 0x8000000000008003,0 + .quad 0x8000000000008002,0 + .quad 0x8000000000000080,0 + .quad 0x000000000000800a,0 + .quad 0x800000008000000a,0 + .quad 0x8000000080008081,0 + .quad 0x8000000000008080,0 + .quad 0x0000000080000001,0 + .quad 0x8000000080008008,0 +.size iotas,.-iotas +.asciz "Keccak-1600 absorb and squeeze for PowerISA 2.07, CRYPTOGAMS by " +___ + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/ge; + + if ($flavour =~ /le$/) { # little-endian + s/\?([a-z]+)/;$1/; + } else { # big-endian + s/\?([a-z]+)/$1/; + } + + print $_,"\n"; +} + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-586.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-586.pl new file mode 100644 index 000000000..9d4ff7f39 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-586.pl @@ -0,0 +1,1491 @@ +#! /usr/bin/env perl +# Copyright 1998-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# [Re]written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# "[Re]written" was achieved in two major overhauls. In 2004 BODY_* +# functions were re-implemented to address P4 performance issue [see +# commentary below], and in 2006 the rest was rewritten in order to +# gain freedom to liberate licensing terms. + +# January, September 2004. +# +# It was noted that Intel IA-32 C compiler generates code which +# performs ~30% *faster* on P4 CPU than original *hand-coded* +# SHA1 assembler implementation. To address this problem (and +# prove that humans are still better than machines:-), the +# original code was overhauled, which resulted in following +# performance changes: +# +# compared with original compared with Intel cc +# assembler impl. generated code +# Pentium -16% +48% +# PIII/AMD +8% +16% +# P4 +85%(!) +45% +# +# As you can see Pentium came out as looser:-( Yet I reckoned that +# improvement on P4 outweighs the loss and incorporate this +# re-tuned code to 0.9.7 and later. +# ---------------------------------------------------------------- + +# August 2009. +# +# George Spelvin has tipped that F_40_59(b,c,d) can be rewritten as +# '(c&d) + (b&(c^d))', which allows to accumulate partial results +# and lighten "pressure" on scratch registers. This resulted in +# >12% performance improvement on contemporary AMD cores (with no +# degradation on other CPUs:-). Also, the code was revised to maximize +# "distance" between instructions producing input to 'lea' instruction +# and the 'lea' instruction itself, which is essential for Intel Atom +# core and resulted in ~15% improvement. + +# October 2010. +# +# Add SSSE3, Supplemental[!] SSE3, implementation. The idea behind it +# is to offload message schedule denoted by Wt in NIST specification, +# or Xupdate in OpenSSL source, to SIMD unit. The idea is not novel, +# and in SSE2 context was first explored by Dean Gaudet in 2004, see +# http://arctic.org/~dean/crypto/sha1.html. Since then several things +# have changed that made it interesting again: +# +# a) XMM units became faster and wider; +# b) instruction set became more versatile; +# c) an important observation was made by Max Locktykhin, which made +# it possible to reduce amount of instructions required to perform +# the operation in question, for further details see +# http://software.intel.com/en-us/articles/improving-the-performance-of-the-secure-hash-algorithm-1/. + +# April 2011. +# +# Add AVX code path, probably most controversial... The thing is that +# switch to AVX alone improves performance by as little as 4% in +# comparison to SSSE3 code path. But below result doesn't look like +# 4% improvement... Trouble is that Sandy Bridge decodes 'ro[rl]' as +# pair of µ-ops, and it's the additional µ-ops, two per round, that +# make it run slower than Core2 and Westmere. But 'sh[rl]d' is decoded +# as single µ-op by Sandy Bridge and it's replacing 'ro[rl]' with +# equivalent 'sh[rl]d' that is responsible for the impressive 5.1 +# cycles per processed byte. But 'sh[rl]d' is not something that used +# to be fast, nor does it appear to be fast in upcoming Bulldozer +# [according to its optimization manual]. Which is why AVX code path +# is guarded by *both* AVX and synthetic bit denoting Intel CPUs. +# One can argue that it's unfair to AMD, but without 'sh[rl]d' it +# makes no sense to keep the AVX code path. If somebody feels that +# strongly, it's probably more appropriate to discuss possibility of +# using vector rotate XOP on AMD... + +# March 2014. +# +# Add support for Intel SHA Extensions. + +###################################################################### +# Current performance is summarized in following table. Numbers are +# CPU clock cycles spent to process single byte (less is better). +# +# x86 SSSE3 AVX +# Pentium 15.7 - +# PIII 11.5 - +# P4 10.6 - +# AMD K8 7.1 - +# Core2 7.3 6.0/+22% - +# Westmere 7.3 5.5/+33% - +# Sandy Bridge 8.8 6.2/+40% 5.1(**)/+73% +# Ivy Bridge 7.2 4.8/+51% 4.7(**)/+53% +# Haswell 6.5 4.3/+51% 4.1(**)/+58% +# Skylake 6.4 4.1/+55% 4.1(**)/+55% +# Bulldozer 11.6 6.0/+92% +# VIA Nano 10.6 7.5/+41% +# Atom 12.5 9.3(*)/+35% +# Silvermont 14.5 9.9(*)/+46% +# Goldmont 8.8 6.7/+30% 1.7(***)/+415% +# +# (*) Loop is 1056 instructions long and expected result is ~8.25. +# The discrepancy is because of front-end limitations, so +# called MS-ROM penalties, and on Silvermont even rotate's +# limited parallelism. +# +# (**) As per above comment, the result is for AVX *plus* sh[rl]d. +# +# (***) SHAEXT result + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +$output=pop; +open STDOUT,">$output"; + +&asm_init($ARGV[0],$ARGV[$#ARGV] eq "386"); + +$xmm=$ymm=0; +for (@ARGV) { $xmm=1 if (/-DOPENSSL_IA32_SSE2/); } + +$ymm=1 if ($xmm && + `$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler version ([2-9]\.[0-9]+)/ && + $1>=2.19); # first version supporting AVX + +$ymm=1 if ($xmm && !$ymm && $ARGV[0] eq "win32n" && + `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/ && + $1>=2.03); # first version supporting AVX + +$ymm=1 if ($xmm && !$ymm && $ARGV[0] eq "win32" && + `ml 2>&1` =~ /Version ([0-9]+)\./ && + $1>=10); # first version supporting AVX + +$ymm=1 if ($xmm && !$ymm && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9]\.[0-9]+)/ && + $2>=3.0); # first version supporting AVX + +$shaext=$xmm; ### set to zero if compiling for 1.0.1 + +&external_label("OPENSSL_ia32cap_P") if ($xmm); + + +$A="eax"; +$B="ebx"; +$C="ecx"; +$D="edx"; +$E="edi"; +$T="esi"; +$tmp1="ebp"; + +@V=($A,$B,$C,$D,$E,$T); + +$alt=0; # 1 denotes alternative IALU implementation, which performs + # 8% *worse* on P4, same on Westmere and Atom, 2% better on + # Sandy Bridge... + +sub BODY_00_15 + { + local($n,$a,$b,$c,$d,$e,$f)=@_; + + &comment("00_15 $n"); + + &mov($f,$c); # f to hold F_00_19(b,c,d) + if ($n==0) { &mov($tmp1,$a); } + else { &mov($a,$tmp1); } + &rotl($tmp1,5); # tmp1=ROTATE(a,5) + &xor($f,$d); + &add($tmp1,$e); # tmp1+=e; + &mov($e,&swtmp($n%16)); # e becomes volatile and is loaded + # with xi, also note that e becomes + # f in next round... + &and($f,$b); + &rotr($b,2); # b=ROTATE(b,30) + &xor($f,$d); # f holds F_00_19(b,c,d) + &lea($tmp1,&DWP(0x5a827999,$tmp1,$e)); # tmp1+=K_00_19+xi + + if ($n==15) { &mov($e,&swtmp(($n+1)%16));# pre-fetch f for next round + &add($f,$tmp1); } # f+=tmp1 + else { &add($tmp1,$f); } # f becomes a in next round + &mov($tmp1,$a) if ($alt && $n==15); + } + +sub BODY_16_19 + { + local($n,$a,$b,$c,$d,$e,$f)=@_; + + &comment("16_19 $n"); + +if ($alt) { + &xor($c,$d); + &xor($f,&swtmp(($n+2)%16)); # f to hold Xupdate(xi,xa,xb,xc,xd) + &and($tmp1,$c); # tmp1 to hold F_00_19(b,c,d), b&=c^d + &xor($f,&swtmp(($n+8)%16)); + &xor($tmp1,$d); # tmp1=F_00_19(b,c,d) + &xor($f,&swtmp(($n+13)%16)); # f holds xa^xb^xc^xd + &rotl($f,1); # f=ROTATE(f,1) + &add($e,$tmp1); # e+=F_00_19(b,c,d) + &xor($c,$d); # restore $c + &mov($tmp1,$a); # b in next round + &rotr($b,$n==16?2:7); # b=ROTATE(b,30) + &mov(&swtmp($n%16),$f); # xi=f + &rotl($a,5); # ROTATE(a,5) + &lea($f,&DWP(0x5a827999,$f,$e));# f+=F_00_19(b,c,d)+e + &mov($e,&swtmp(($n+1)%16)); # pre-fetch f for next round + &add($f,$a); # f+=ROTATE(a,5) +} else { + &mov($tmp1,$c); # tmp1 to hold F_00_19(b,c,d) + &xor($f,&swtmp(($n+2)%16)); # f to hold Xupdate(xi,xa,xb,xc,xd) + &xor($tmp1,$d); + &xor($f,&swtmp(($n+8)%16)); + &and($tmp1,$b); + &xor($f,&swtmp(($n+13)%16)); # f holds xa^xb^xc^xd + &rotl($f,1); # f=ROTATE(f,1) + &xor($tmp1,$d); # tmp1=F_00_19(b,c,d) + &add($e,$tmp1); # e+=F_00_19(b,c,d) + &mov($tmp1,$a); + &rotr($b,2); # b=ROTATE(b,30) + &mov(&swtmp($n%16),$f); # xi=f + &rotl($tmp1,5); # ROTATE(a,5) + &lea($f,&DWP(0x5a827999,$f,$e));# f+=F_00_19(b,c,d)+e + &mov($e,&swtmp(($n+1)%16)); # pre-fetch f for next round + &add($f,$tmp1); # f+=ROTATE(a,5) +} + } + +sub BODY_20_39 + { + local($n,$a,$b,$c,$d,$e,$f)=@_; + local $K=($n<40)?0x6ed9eba1:0xca62c1d6; + + &comment("20_39 $n"); + +if ($alt) { + &xor($tmp1,$c); # tmp1 to hold F_20_39(b,c,d), b^=c + &xor($f,&swtmp(($n+2)%16)); # f to hold Xupdate(xi,xa,xb,xc,xd) + &xor($tmp1,$d); # tmp1 holds F_20_39(b,c,d) + &xor($f,&swtmp(($n+8)%16)); + &add($e,$tmp1); # e+=F_20_39(b,c,d) + &xor($f,&swtmp(($n+13)%16)); # f holds xa^xb^xc^xd + &rotl($f,1); # f=ROTATE(f,1) + &mov($tmp1,$a); # b in next round + &rotr($b,7); # b=ROTATE(b,30) + &mov(&swtmp($n%16),$f) if($n<77);# xi=f + &rotl($a,5); # ROTATE(a,5) + &xor($b,$c) if($n==39);# warm up for BODY_40_59 + &and($tmp1,$b) if($n==39); + &lea($f,&DWP($K,$f,$e)); # f+=e+K_XX_YY + &mov($e,&swtmp(($n+1)%16)) if($n<79);# pre-fetch f for next round + &add($f,$a); # f+=ROTATE(a,5) + &rotr($a,5) if ($n==79); +} else { + &mov($tmp1,$b); # tmp1 to hold F_20_39(b,c,d) + &xor($f,&swtmp(($n+2)%16)); # f to hold Xupdate(xi,xa,xb,xc,xd) + &xor($tmp1,$c); + &xor($f,&swtmp(($n+8)%16)); + &xor($tmp1,$d); # tmp1 holds F_20_39(b,c,d) + &xor($f,&swtmp(($n+13)%16)); # f holds xa^xb^xc^xd + &rotl($f,1); # f=ROTATE(f,1) + &add($e,$tmp1); # e+=F_20_39(b,c,d) + &rotr($b,2); # b=ROTATE(b,30) + &mov($tmp1,$a); + &rotl($tmp1,5); # ROTATE(a,5) + &mov(&swtmp($n%16),$f) if($n<77);# xi=f + &lea($f,&DWP($K,$f,$e)); # f+=e+K_XX_YY + &mov($e,&swtmp(($n+1)%16)) if($n<79);# pre-fetch f for next round + &add($f,$tmp1); # f+=ROTATE(a,5) +} + } + +sub BODY_40_59 + { + local($n,$a,$b,$c,$d,$e,$f)=@_; + + &comment("40_59 $n"); + +if ($alt) { + &add($e,$tmp1); # e+=b&(c^d) + &xor($f,&swtmp(($n+2)%16)); # f to hold Xupdate(xi,xa,xb,xc,xd) + &mov($tmp1,$d); + &xor($f,&swtmp(($n+8)%16)); + &xor($c,$d); # restore $c + &xor($f,&swtmp(($n+13)%16)); # f holds xa^xb^xc^xd + &rotl($f,1); # f=ROTATE(f,1) + &and($tmp1,$c); + &rotr($b,7); # b=ROTATE(b,30) + &add($e,$tmp1); # e+=c&d + &mov($tmp1,$a); # b in next round + &mov(&swtmp($n%16),$f); # xi=f + &rotl($a,5); # ROTATE(a,5) + &xor($b,$c) if ($n<59); + &and($tmp1,$b) if ($n<59);# tmp1 to hold F_40_59(b,c,d) + &lea($f,&DWP(0x8f1bbcdc,$f,$e));# f+=K_40_59+e+(b&(c^d)) + &mov($e,&swtmp(($n+1)%16)); # pre-fetch f for next round + &add($f,$a); # f+=ROTATE(a,5) +} else { + &mov($tmp1,$c); # tmp1 to hold F_40_59(b,c,d) + &xor($f,&swtmp(($n+2)%16)); # f to hold Xupdate(xi,xa,xb,xc,xd) + &xor($tmp1,$d); + &xor($f,&swtmp(($n+8)%16)); + &and($tmp1,$b); + &xor($f,&swtmp(($n+13)%16)); # f holds xa^xb^xc^xd + &rotl($f,1); # f=ROTATE(f,1) + &add($tmp1,$e); # b&(c^d)+=e + &rotr($b,2); # b=ROTATE(b,30) + &mov($e,$a); # e becomes volatile + &rotl($e,5); # ROTATE(a,5) + &mov(&swtmp($n%16),$f); # xi=f + &lea($f,&DWP(0x8f1bbcdc,$f,$tmp1));# f+=K_40_59+e+(b&(c^d)) + &mov($tmp1,$c); + &add($f,$e); # f+=ROTATE(a,5) + &and($tmp1,$d); + &mov($e,&swtmp(($n+1)%16)); # pre-fetch f for next round + &add($f,$tmp1); # f+=c&d +} + } + +&function_begin("sha1_block_data_order"); +if ($xmm) { + &static_label("shaext_shortcut") if ($shaext); + &static_label("ssse3_shortcut"); + &static_label("avx_shortcut") if ($ymm); + &static_label("K_XX_XX"); + + &call (&label("pic_point")); # make it PIC! + &set_label("pic_point"); + &blindpop($tmp1); + &picmeup($T,"OPENSSL_ia32cap_P",$tmp1,&label("pic_point")); + &lea ($tmp1,&DWP(&label("K_XX_XX")."-".&label("pic_point"),$tmp1)); + + &mov ($A,&DWP(0,$T)); + &mov ($D,&DWP(4,$T)); + &test ($D,1<<9); # check SSSE3 bit + &jz (&label("x86")); + &mov ($C,&DWP(8,$T)); + &test ($A,1<<24); # check FXSR bit + &jz (&label("x86")); + if ($shaext) { + &test ($C,1<<29); # check SHA bit + &jnz (&label("shaext_shortcut")); + } + if ($ymm) { + &and ($D,1<<28); # mask AVX bit + &and ($A,1<<30); # mask "Intel CPU" bit + &or ($A,$D); + &cmp ($A,1<<28|1<<30); + &je (&label("avx_shortcut")); + } + &jmp (&label("ssse3_shortcut")); + &set_label("x86",16); +} + &mov($tmp1,&wparam(0)); # SHA_CTX *c + &mov($T,&wparam(1)); # const void *input + &mov($A,&wparam(2)); # size_t num + &stack_push(16+3); # allocate X[16] + &shl($A,6); + &add($A,$T); + &mov(&wparam(2),$A); # pointer beyond the end of input + &mov($E,&DWP(16,$tmp1));# pre-load E + &jmp(&label("loop")); + +&set_label("loop",16); + + # copy input chunk to X, but reversing byte order! + for ($i=0; $i<16; $i+=4) + { + &mov($A,&DWP(4*($i+0),$T)); + &mov($B,&DWP(4*($i+1),$T)); + &mov($C,&DWP(4*($i+2),$T)); + &mov($D,&DWP(4*($i+3),$T)); + &bswap($A); + &bswap($B); + &bswap($C); + &bswap($D); + &mov(&swtmp($i+0),$A); + &mov(&swtmp($i+1),$B); + &mov(&swtmp($i+2),$C); + &mov(&swtmp($i+3),$D); + } + &mov(&wparam(1),$T); # redundant in 1st spin + + &mov($A,&DWP(0,$tmp1)); # load SHA_CTX + &mov($B,&DWP(4,$tmp1)); + &mov($C,&DWP(8,$tmp1)); + &mov($D,&DWP(12,$tmp1)); + # E is pre-loaded + + for($i=0;$i<16;$i++) { &BODY_00_15($i,@V); unshift(@V,pop(@V)); } + for(;$i<20;$i++) { &BODY_16_19($i,@V); unshift(@V,pop(@V)); } + for(;$i<40;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); } + for(;$i<60;$i++) { &BODY_40_59($i,@V); unshift(@V,pop(@V)); } + for(;$i<80;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); } + + (($V[5] eq $D) and ($V[0] eq $E)) or die; # double-check + + &mov($tmp1,&wparam(0)); # re-load SHA_CTX* + &mov($D,&wparam(1)); # D is last "T" and is discarded + + &add($E,&DWP(0,$tmp1)); # E is last "A"... + &add($T,&DWP(4,$tmp1)); + &add($A,&DWP(8,$tmp1)); + &add($B,&DWP(12,$tmp1)); + &add($C,&DWP(16,$tmp1)); + + &mov(&DWP(0,$tmp1),$E); # update SHA_CTX + &add($D,64); # advance input pointer + &mov(&DWP(4,$tmp1),$T); + &cmp($D,&wparam(2)); # have we reached the end yet? + &mov(&DWP(8,$tmp1),$A); + &mov($E,$C); # C is last "E" which needs to be "pre-loaded" + &mov(&DWP(12,$tmp1),$B); + &mov($T,$D); # input pointer + &mov(&DWP(16,$tmp1),$C); + &jb(&label("loop")); + + &stack_pop(16+3); +&function_end("sha1_block_data_order"); + +if ($xmm) { +if ($shaext) { +###################################################################### +# Intel SHA Extensions implementation of SHA1 update function. +# +my ($ctx,$inp,$num)=("edi","esi","ecx"); +my ($ABCD,$E,$E_,$BSWAP)=map("xmm$_",(0..3)); +my @MSG=map("xmm$_",(4..7)); + +sub sha1rnds4 { + my ($dst,$src,$imm)=@_; + if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/) + { &data_byte(0x0f,0x3a,0xcc,0xc0|($1<<3)|$2,$imm); } +} +sub sha1op38 { + my ($opcodelet,$dst,$src)=@_; + if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/) + { &data_byte(0x0f,0x38,$opcodelet,0xc0|($1<<3)|$2); } +} +sub sha1nexte { sha1op38(0xc8,@_); } +sub sha1msg1 { sha1op38(0xc9,@_); } +sub sha1msg2 { sha1op38(0xca,@_); } + +&function_begin("_sha1_block_data_order_shaext"); + &call (&label("pic_point")); # make it PIC! + &set_label("pic_point"); + &blindpop($tmp1); + &lea ($tmp1,&DWP(&label("K_XX_XX")."-".&label("pic_point"),$tmp1)); +&set_label("shaext_shortcut"); + &mov ($ctx,&wparam(0)); + &mov ("ebx","esp"); + &mov ($inp,&wparam(1)); + &mov ($num,&wparam(2)); + &sub ("esp",32); + + &movdqu ($ABCD,&QWP(0,$ctx)); + &movd ($E,&DWP(16,$ctx)); + &and ("esp",-32); + &movdqa ($BSWAP,&QWP(0x50,$tmp1)); # byte-n-word swap + + &movdqu (@MSG[0],&QWP(0,$inp)); + &pshufd ($ABCD,$ABCD,0b00011011); # flip word order + &movdqu (@MSG[1],&QWP(0x10,$inp)); + &pshufd ($E,$E,0b00011011); # flip word order + &movdqu (@MSG[2],&QWP(0x20,$inp)); + &pshufb (@MSG[0],$BSWAP); + &movdqu (@MSG[3],&QWP(0x30,$inp)); + &pshufb (@MSG[1],$BSWAP); + &pshufb (@MSG[2],$BSWAP); + &pshufb (@MSG[3],$BSWAP); + &jmp (&label("loop_shaext")); + +&set_label("loop_shaext",16); + &dec ($num); + &lea ("eax",&DWP(0x40,$inp)); + &movdqa (&QWP(0,"esp"),$E); # offload $E + &paddd ($E,@MSG[0]); + &cmovne ($inp,"eax"); + &movdqa (&QWP(16,"esp"),$ABCD); # offload $ABCD + +for($i=0;$i<20-4;$i+=2) { + &sha1msg1 (@MSG[0],@MSG[1]); + &movdqa ($E_,$ABCD); + &sha1rnds4 ($ABCD,$E,int($i/5)); # 0-3... + &sha1nexte ($E_,@MSG[1]); + &pxor (@MSG[0],@MSG[2]); + &sha1msg1 (@MSG[1],@MSG[2]); + &sha1msg2 (@MSG[0],@MSG[3]); + + &movdqa ($E,$ABCD); + &sha1rnds4 ($ABCD,$E_,int(($i+1)/5)); + &sha1nexte ($E,@MSG[2]); + &pxor (@MSG[1],@MSG[3]); + &sha1msg2 (@MSG[1],@MSG[0]); + + push(@MSG,shift(@MSG)); push(@MSG,shift(@MSG)); +} + &movdqu (@MSG[0],&QWP(0,$inp)); + &movdqa ($E_,$ABCD); + &sha1rnds4 ($ABCD,$E,3); # 64-67 + &sha1nexte ($E_,@MSG[1]); + &movdqu (@MSG[1],&QWP(0x10,$inp)); + &pshufb (@MSG[0],$BSWAP); + + &movdqa ($E,$ABCD); + &sha1rnds4 ($ABCD,$E_,3); # 68-71 + &sha1nexte ($E,@MSG[2]); + &movdqu (@MSG[2],&QWP(0x20,$inp)); + &pshufb (@MSG[1],$BSWAP); + + &movdqa ($E_,$ABCD); + &sha1rnds4 ($ABCD,$E,3); # 72-75 + &sha1nexte ($E_,@MSG[3]); + &movdqu (@MSG[3],&QWP(0x30,$inp)); + &pshufb (@MSG[2],$BSWAP); + + &movdqa ($E,$ABCD); + &sha1rnds4 ($ABCD,$E_,3); # 76-79 + &movdqa ($E_,&QWP(0,"esp")); + &pshufb (@MSG[3],$BSWAP); + &sha1nexte ($E,$E_); + &paddd ($ABCD,&QWP(16,"esp")); + + &jnz (&label("loop_shaext")); + + &pshufd ($ABCD,$ABCD,0b00011011); + &pshufd ($E,$E,0b00011011); + &movdqu (&QWP(0,$ctx),$ABCD) + &movd (&DWP(16,$ctx),$E); + &mov ("esp","ebx"); +&function_end("_sha1_block_data_order_shaext"); +} +###################################################################### +# The SSSE3 implementation. +# +# %xmm[0-7] are used as ring @X[] buffer containing quadruples of last +# 32 elements of the message schedule or Xupdate outputs. First 4 +# quadruples are simply byte-swapped input, next 4 are calculated +# according to method originally suggested by Dean Gaudet (modulo +# being implemented in SSSE3). Once 8 quadruples or 32 elements are +# collected, it switches to routine proposed by Max Locktyukhin. +# +# Calculations inevitably require temporary registers, and there are +# no %xmm registers left to spare. For this reason part of the ring +# buffer, X[2..4] to be specific, is offloaded to 3 quadriples ring +# buffer on the stack. Keep in mind that X[2] is alias X[-6], X[3] - +# X[-5], and X[4] - X[-4]... +# +# Another notable optimization is aggressive stack frame compression +# aiming to minimize amount of 9-byte instructions... +# +# Yet another notable optimization is "jumping" $B variable. It means +# that there is no register permanently allocated for $B value. This +# allowed to eliminate one instruction from body_20_39... +# +my $Xi=4; # 4xSIMD Xupdate round, start pre-seeded +my @X=map("xmm$_",(4..7,0..3)); # pre-seeded for $Xi=4 +my @V=($A,$B,$C,$D,$E); +my $j=0; # hash round +my $rx=0; +my @T=($T,$tmp1); +my $inp; + +my $_rol=sub { &rol(@_) }; +my $_ror=sub { &ror(@_) }; + +&function_begin("_sha1_block_data_order_ssse3"); + &call (&label("pic_point")); # make it PIC! + &set_label("pic_point"); + &blindpop($tmp1); + &lea ($tmp1,&DWP(&label("K_XX_XX")."-".&label("pic_point"),$tmp1)); +&set_label("ssse3_shortcut"); + + &movdqa (@X[3],&QWP(0,$tmp1)); # K_00_19 + &movdqa (@X[4],&QWP(16,$tmp1)); # K_20_39 + &movdqa (@X[5],&QWP(32,$tmp1)); # K_40_59 + &movdqa (@X[6],&QWP(48,$tmp1)); # K_60_79 + &movdqa (@X[2],&QWP(64,$tmp1)); # pbswap mask + + &mov ($E,&wparam(0)); # load argument block + &mov ($inp=@T[1],&wparam(1)); + &mov ($D,&wparam(2)); + &mov (@T[0],"esp"); + + # stack frame layout + # + # +0 X[0]+K X[1]+K X[2]+K X[3]+K # XMM->IALU xfer area + # X[4]+K X[5]+K X[6]+K X[7]+K + # X[8]+K X[9]+K X[10]+K X[11]+K + # X[12]+K X[13]+K X[14]+K X[15]+K + # + # +64 X[0] X[1] X[2] X[3] # XMM->XMM backtrace area + # X[4] X[5] X[6] X[7] + # X[8] X[9] X[10] X[11] # even borrowed for K_00_19 + # + # +112 K_20_39 K_20_39 K_20_39 K_20_39 # constants + # K_40_59 K_40_59 K_40_59 K_40_59 + # K_60_79 K_60_79 K_60_79 K_60_79 + # K_00_19 K_00_19 K_00_19 K_00_19 + # pbswap mask + # + # +192 ctx # argument block + # +196 inp + # +200 end + # +204 esp + &sub ("esp",208); + &and ("esp",-64); + + &movdqa (&QWP(112+0,"esp"),@X[4]); # copy constants + &movdqa (&QWP(112+16,"esp"),@X[5]); + &movdqa (&QWP(112+32,"esp"),@X[6]); + &shl ($D,6); # len*64 + &movdqa (&QWP(112+48,"esp"),@X[3]); + &add ($D,$inp); # end of input + &movdqa (&QWP(112+64,"esp"),@X[2]); + &add ($inp,64); + &mov (&DWP(192+0,"esp"),$E); # save argument block + &mov (&DWP(192+4,"esp"),$inp); + &mov (&DWP(192+8,"esp"),$D); + &mov (&DWP(192+12,"esp"),@T[0]); # save original %esp + + &mov ($A,&DWP(0,$E)); # load context + &mov ($B,&DWP(4,$E)); + &mov ($C,&DWP(8,$E)); + &mov ($D,&DWP(12,$E)); + &mov ($E,&DWP(16,$E)); + &mov (@T[0],$B); # magic seed + + &movdqu (@X[-4&7],&QWP(-64,$inp)); # load input to %xmm[0-3] + &movdqu (@X[-3&7],&QWP(-48,$inp)); + &movdqu (@X[-2&7],&QWP(-32,$inp)); + &movdqu (@X[-1&7],&QWP(-16,$inp)); + &pshufb (@X[-4&7],@X[2]); # byte swap + &pshufb (@X[-3&7],@X[2]); + &pshufb (@X[-2&7],@X[2]); + &movdqa (&QWP(112-16,"esp"),@X[3]); # borrow last backtrace slot + &pshufb (@X[-1&7],@X[2]); + &paddd (@X[-4&7],@X[3]); # add K_00_19 + &paddd (@X[-3&7],@X[3]); + &paddd (@X[-2&7],@X[3]); + &movdqa (&QWP(0,"esp"),@X[-4&7]); # X[]+K xfer to IALU + &psubd (@X[-4&7],@X[3]); # restore X[] + &movdqa (&QWP(0+16,"esp"),@X[-3&7]); + &psubd (@X[-3&7],@X[3]); + &movdqa (&QWP(0+32,"esp"),@X[-2&7]); + &mov (@T[1],$C); + &psubd (@X[-2&7],@X[3]); + &xor (@T[1],$D); + &pshufd (@X[0],@X[-4&7],0xee); # was &movdqa (@X[0],@X[-3&7]); + &and (@T[0],@T[1]); + &jmp (&label("loop")); + +###################################################################### +# SSE instruction sequence is first broken to groups of independent +# instructions, independent in respect to their inputs and shifter +# (not all architectures have more than one). Then IALU instructions +# are "knitted in" between the SSE groups. Distance is maintained for +# SSE latency of 2 in hope that it fits better upcoming AMD Bulldozer +# [which allegedly also implements SSSE3]... +# +# Temporary registers usage. X[2] is volatile at the entry and at the +# end is restored from backtrace ring buffer. X[3] is expected to +# contain current K_XX_XX constant and is used to calculate X[-1]+K +# from previous round, it becomes volatile the moment the value is +# saved to stack for transfer to IALU. X[4] becomes volatile whenever +# X[-4] is accumulated and offloaded to backtrace ring buffer, at the +# end it is loaded with next K_XX_XX [which becomes X[3] in next +# round]... +# +sub Xupdate_ssse3_16_31() # recall that $Xi starts with 4 +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 40 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); # ror + eval(shift(@insns)); + eval(shift(@insns)); + &punpcklqdq(@X[0],@X[-3&7]); # compose "X[-14]" in "X[0]", was &palignr(@X[0],@X[-4&7],8); + &movdqa (@X[2],@X[-1&7]); + eval(shift(@insns)); + eval(shift(@insns)); + + &paddd (@X[3],@X[-1&7]); + &movdqa (&QWP(64+16*(($Xi-4)%3),"esp"),@X[-4&7]);# save X[] to backtrace buffer + eval(shift(@insns)); # rol + eval(shift(@insns)); + &psrldq (@X[2],4); # "X[-3]", 3 dwords + eval(shift(@insns)); + eval(shift(@insns)); + &pxor (@X[0],@X[-4&7]); # "X[0]"^="X[-16]" + eval(shift(@insns)); + eval(shift(@insns)); # ror + + &pxor (@X[2],@X[-2&7]); # "X[-3]"^"X[-8]" + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &pxor (@X[0],@X[2]); # "X[0]"^="X[-3]"^"X[-8]" + eval(shift(@insns)); + eval(shift(@insns)); # rol + &movdqa (&QWP(0+16*(($Xi-1)&3),"esp"),@X[3]); # X[]+K xfer to IALU + eval(shift(@insns)); + eval(shift(@insns)); + + &movdqa (@X[4],@X[0]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # ror + &movdqa (@X[2],@X[0]); + eval(shift(@insns)); + + &pslldq (@X[4],12); # "X[0]"<<96, extract one dword + &paddd (@X[0],@X[0]); + eval(shift(@insns)); + eval(shift(@insns)); + + &psrld (@X[2],31); + eval(shift(@insns)); + eval(shift(@insns)); # rol + &movdqa (@X[3],@X[4]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &psrld (@X[4],30); + eval(shift(@insns)); + eval(shift(@insns)); # ror + &por (@X[0],@X[2]); # "X[0]"<<<=1 + eval(shift(@insns)); + &movdqa (@X[2],&QWP(64+16*(($Xi-6)%3),"esp")) if ($Xi>5); # restore X[] from backtrace buffer + eval(shift(@insns)); + eval(shift(@insns)); + + &pslld (@X[3],2); + eval(shift(@insns)); + eval(shift(@insns)); # rol + &pxor (@X[0],@X[4]); + &movdqa (@X[4],&QWP(112-16+16*(($Xi)/5),"esp")); # K_XX_XX + eval(shift(@insns)); + eval(shift(@insns)); + + &pxor (@X[0],@X[3]); # "X[0]"^=("X[0]"<<96)<<<2 + &pshufd (@X[1],@X[-3&7],0xee) if ($Xi<7); # was &movdqa (@X[1],@X[-2&7]) + &pshufd (@X[3],@X[-1&7],0xee) if ($Xi==7); + eval(shift(@insns)); + eval(shift(@insns)); + + foreach (@insns) { eval; } # remaining instructions [if any] + + $Xi++; push(@X,shift(@X)); # "rotate" X[] +} + +sub Xupdate_ssse3_32_79() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 to 44 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); # body_20_39 + &pxor (@X[0],@X[-4&7]); # "X[0]"="X[-32]"^"X[-16]" + &punpcklqdq(@X[2],@X[-1&7]); # compose "X[-6]", was &palignr(@X[2],@X[-2&7],8) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + + &pxor (@X[0],@X[-7&7]); # "X[0]"^="X[-28]" + &movdqa (&QWP(64+16*(($Xi-4)%3),"esp"),@X[-4&7]); # save X[] to backtrace buffer + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)) if (@insns[0] =~ /_rol/); + if ($Xi%5) { + &movdqa (@X[4],@X[3]); # "perpetuate" K_XX_XX... + } else { # ... or load next one + &movdqa (@X[4],&QWP(112-16+16*($Xi/5),"esp")); + } + eval(shift(@insns)); # ror + &paddd (@X[3],@X[-1&7]); + eval(shift(@insns)); + + &pxor (@X[0],@X[2]); # "X[0]"^="X[-6]" + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + + &movdqa (@X[2],@X[0]); + &movdqa (&QWP(0+16*(($Xi-1)&3),"esp"),@X[3]); # X[]+K xfer to IALU + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # ror + eval(shift(@insns)); + eval(shift(@insns)) if (@insns[0] =~ /_rol/); + + &pslld (@X[0],2); + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + &psrld (@X[2],30); + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # ror + eval(shift(@insns)); + eval(shift(@insns)) if (@insns[1] =~ /_rol/); + eval(shift(@insns)) if (@insns[0] =~ /_rol/); + + &por (@X[0],@X[2]); # "X[0]"<<<=2 + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + &movdqa (@X[2],&QWP(64+16*(($Xi-6)%3),"esp")) if($Xi<19); # restore X[] from backtrace buffer + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # ror + &pshufd (@X[3],@X[-1],0xee) if ($Xi<19); # was &movdqa (@X[3],@X[0]) + eval(shift(@insns)); + + foreach (@insns) { eval; } # remaining instructions + + $Xi++; push(@X,shift(@X)); # "rotate" X[] +} + +sub Xuplast_ssse3_80() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &paddd (@X[3],@X[-1&7]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &movdqa (&QWP(0+16*(($Xi-1)&3),"esp"),@X[3]); # X[]+K xfer IALU + + foreach (@insns) { eval; } # remaining instructions + + &mov ($inp=@T[1],&DWP(192+4,"esp")); + &cmp ($inp,&DWP(192+8,"esp")); + &je (&label("done")); + + &movdqa (@X[3],&QWP(112+48,"esp")); # K_00_19 + &movdqa (@X[2],&QWP(112+64,"esp")); # pbswap mask + &movdqu (@X[-4&7],&QWP(0,$inp)); # load input + &movdqu (@X[-3&7],&QWP(16,$inp)); + &movdqu (@X[-2&7],&QWP(32,$inp)); + &movdqu (@X[-1&7],&QWP(48,$inp)); + &add ($inp,64); + &pshufb (@X[-4&7],@X[2]); # byte swap + &mov (&DWP(192+4,"esp"),$inp); + &movdqa (&QWP(112-16,"esp"),@X[3]); # borrow last backtrace slot + + $Xi=0; +} + +sub Xloop_ssse3() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &pshufb (@X[($Xi-3)&7],@X[2]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &paddd (@X[($Xi-4)&7],@X[3]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &movdqa (&QWP(0+16*$Xi,"esp"),@X[($Xi-4)&7]); # X[]+K xfer to IALU + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &psubd (@X[($Xi-4)&7],@X[3]); + + foreach (@insns) { eval; } + $Xi++; +} + +sub Xtail_ssse3() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + foreach (@insns) { eval; } +} + +sub body_00_19 () { # ((c^d)&b)^d + # on start @T[0]=(c^d)&b + return &body_20_39() if ($rx==19); $rx++; + ( + '($a,$b,$c,$d,$e)=@V;'. + '&$_ror ($b,$j?7:2);', # $b>>>2 + '&xor (@T[0],$d);', + '&mov (@T[1],$a);', # $b in next round + + '&add ($e,&DWP(4*($j&15),"esp"));', # X[]+K xfer + '&xor ($b,$c);', # $c^$d for next round + + '&$_rol ($a,5);', + '&add ($e,@T[0]);', + '&and (@T[1],$b);', # ($b&($c^$d)) for next round + + '&xor ($b,$c);', # restore $b + '&add ($e,$a);' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));' + ); +} + +sub body_20_39 () { # b^d^c + # on entry @T[0]=b^d + return &body_40_59() if ($rx==39); $rx++; + ( + '($a,$b,$c,$d,$e)=@V;'. + '&add ($e,&DWP(4*($j&15),"esp"));', # X[]+K xfer + '&xor (@T[0],$d) if($j==19);'. + '&xor (@T[0],$c) if($j> 19);', # ($b^$d^$c) + '&mov (@T[1],$a);', # $b in next round + + '&$_rol ($a,5);', + '&add ($e,@T[0]);', + '&xor (@T[1],$c) if ($j< 79);', # $b^$d for next round + + '&$_ror ($b,7);', # $b>>>2 + '&add ($e,$a);' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));' + ); +} + +sub body_40_59 () { # ((b^c)&(c^d))^c + # on entry @T[0]=(b^c), (c^=d) + $rx++; + ( + '($a,$b,$c,$d,$e)=@V;'. + '&add ($e,&DWP(4*($j&15),"esp"));', # X[]+K xfer + '&and (@T[0],$c) if ($j>=40);', # (b^c)&(c^d) + '&xor ($c,$d) if ($j>=40);', # restore $c + + '&$_ror ($b,7);', # $b>>>2 + '&mov (@T[1],$a);', # $b for next round + '&xor (@T[0],$c);', + + '&$_rol ($a,5);', + '&add ($e,@T[0]);', + '&xor (@T[1],$c) if ($j==59);'. + '&xor (@T[1],$b) if ($j< 59);', # b^c for next round + + '&xor ($b,$c) if ($j< 59);', # c^d for next round + '&add ($e,$a);' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));' + ); +} +###### +sub bodyx_00_19 () { # ((c^d)&b)^d + # on start @T[0]=(b&c)^(~b&d), $e+=X[]+K + return &bodyx_20_39() if ($rx==19); $rx++; + ( + '($a,$b,$c,$d,$e)=@V;'. + + '&rorx ($b,$b,2) if ($j==0);'. # $b>>>2 + '&rorx ($b,@T[1],7) if ($j!=0);', # $b>>>2 + '&lea ($e,&DWP(0,$e,@T[0]));', + '&rorx (@T[0],$a,5);', + + '&andn (@T[1],$a,$c);', + '&and ($a,$b)', + '&add ($d,&DWP(4*(($j+1)&15),"esp"));', # X[]+K xfer + + '&xor (@T[1],$a)', + '&add ($e,@T[0]);' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));' + ); +} + +sub bodyx_20_39 () { # b^d^c + # on start $b=b^c^d + return &bodyx_40_59() if ($rx==39); $rx++; + ( + '($a,$b,$c,$d,$e)=@V;'. + + '&add ($e,($j==19?@T[0]:$b))', + '&rorx ($b,@T[1],7);', # $b>>>2 + '&rorx (@T[0],$a,5);', + + '&xor ($a,$b) if ($j<79);', + '&add ($d,&DWP(4*(($j+1)&15),"esp")) if ($j<79);', # X[]+K xfer + '&xor ($a,$c) if ($j<79);', + '&add ($e,@T[0]);' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));' + ); +} + +sub bodyx_40_59 () { # ((b^c)&(c^d))^c + # on start $b=((b^c)&(c^d))^c + return &bodyx_20_39() if ($rx==59); $rx++; + ( + '($a,$b,$c,$d,$e)=@V;'. + + '&rorx (@T[0],$a,5)', + '&lea ($e,&DWP(0,$e,$b))', + '&rorx ($b,@T[1],7)', # $b>>>2 + '&add ($d,&DWP(4*(($j+1)&15),"esp"))', # X[]+K xfer + + '&mov (@T[1],$c)', + '&xor ($a,$b)', # b^c for next round + '&xor (@T[1],$b)', # c^d for next round + + '&and ($a,@T[1])', + '&add ($e,@T[0])', + '&xor ($a,$b)' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));' + ); +} + +&set_label("loop",16); + &Xupdate_ssse3_16_31(\&body_00_19); + &Xupdate_ssse3_16_31(\&body_00_19); + &Xupdate_ssse3_16_31(\&body_00_19); + &Xupdate_ssse3_16_31(\&body_00_19); + &Xupdate_ssse3_32_79(\&body_00_19); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xupdate_ssse3_32_79(\&body_40_59); + &Xupdate_ssse3_32_79(\&body_40_59); + &Xupdate_ssse3_32_79(\&body_40_59); + &Xupdate_ssse3_32_79(\&body_40_59); + &Xupdate_ssse3_32_79(\&body_40_59); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xuplast_ssse3_80(\&body_20_39); # can jump to "done" + + $saved_j=$j; @saved_V=@V; + + &Xloop_ssse3(\&body_20_39); + &Xloop_ssse3(\&body_20_39); + &Xloop_ssse3(\&body_20_39); + + &mov (@T[1],&DWP(192,"esp")); # update context + &add ($A,&DWP(0,@T[1])); + &add (@T[0],&DWP(4,@T[1])); # $b + &add ($C,&DWP(8,@T[1])); + &mov (&DWP(0,@T[1]),$A); + &add ($D,&DWP(12,@T[1])); + &mov (&DWP(4,@T[1]),@T[0]); + &add ($E,&DWP(16,@T[1])); + &mov (&DWP(8,@T[1]),$C); + &mov ($B,$C); + &mov (&DWP(12,@T[1]),$D); + &xor ($B,$D); + &mov (&DWP(16,@T[1]),$E); + &mov (@T[1],@T[0]); + &pshufd (@X[0],@X[-4&7],0xee); # was &movdqa (@X[0],@X[-3&7]); + &and (@T[0],$B); + &mov ($B,$T[1]); + + &jmp (&label("loop")); + +&set_label("done",16); $j=$saved_j; @V=@saved_V; + + &Xtail_ssse3(\&body_20_39); + &Xtail_ssse3(\&body_20_39); + &Xtail_ssse3(\&body_20_39); + + &mov (@T[1],&DWP(192,"esp")); # update context + &add ($A,&DWP(0,@T[1])); + &mov ("esp",&DWP(192+12,"esp")); # restore %esp + &add (@T[0],&DWP(4,@T[1])); # $b + &add ($C,&DWP(8,@T[1])); + &mov (&DWP(0,@T[1]),$A); + &add ($D,&DWP(12,@T[1])); + &mov (&DWP(4,@T[1]),@T[0]); + &add ($E,&DWP(16,@T[1])); + &mov (&DWP(8,@T[1]),$C); + &mov (&DWP(12,@T[1]),$D); + &mov (&DWP(16,@T[1]),$E); + +&function_end("_sha1_block_data_order_ssse3"); + +$rx=0; # reset + +if ($ymm) { +my $Xi=4; # 4xSIMD Xupdate round, start pre-seeded +my @X=map("xmm$_",(4..7,0..3)); # pre-seeded for $Xi=4 +my @V=($A,$B,$C,$D,$E); +my $j=0; # hash round +my @T=($T,$tmp1); +my $inp; + +my $_rol=sub { &shld(@_[0],@_) }; +my $_ror=sub { &shrd(@_[0],@_) }; + +&function_begin("_sha1_block_data_order_avx"); + &call (&label("pic_point")); # make it PIC! + &set_label("pic_point"); + &blindpop($tmp1); + &lea ($tmp1,&DWP(&label("K_XX_XX")."-".&label("pic_point"),$tmp1)); +&set_label("avx_shortcut"); + &vzeroall(); + + &vmovdqa(@X[3],&QWP(0,$tmp1)); # K_00_19 + &vmovdqa(@X[4],&QWP(16,$tmp1)); # K_20_39 + &vmovdqa(@X[5],&QWP(32,$tmp1)); # K_40_59 + &vmovdqa(@X[6],&QWP(48,$tmp1)); # K_60_79 + &vmovdqa(@X[2],&QWP(64,$tmp1)); # pbswap mask + + &mov ($E,&wparam(0)); # load argument block + &mov ($inp=@T[1],&wparam(1)); + &mov ($D,&wparam(2)); + &mov (@T[0],"esp"); + + # stack frame layout + # + # +0 X[0]+K X[1]+K X[2]+K X[3]+K # XMM->IALU xfer area + # X[4]+K X[5]+K X[6]+K X[7]+K + # X[8]+K X[9]+K X[10]+K X[11]+K + # X[12]+K X[13]+K X[14]+K X[15]+K + # + # +64 X[0] X[1] X[2] X[3] # XMM->XMM backtrace area + # X[4] X[5] X[6] X[7] + # X[8] X[9] X[10] X[11] # even borrowed for K_00_19 + # + # +112 K_20_39 K_20_39 K_20_39 K_20_39 # constants + # K_40_59 K_40_59 K_40_59 K_40_59 + # K_60_79 K_60_79 K_60_79 K_60_79 + # K_00_19 K_00_19 K_00_19 K_00_19 + # pbswap mask + # + # +192 ctx # argument block + # +196 inp + # +200 end + # +204 esp + &sub ("esp",208); + &and ("esp",-64); + + &vmovdqa(&QWP(112+0,"esp"),@X[4]); # copy constants + &vmovdqa(&QWP(112+16,"esp"),@X[5]); + &vmovdqa(&QWP(112+32,"esp"),@X[6]); + &shl ($D,6); # len*64 + &vmovdqa(&QWP(112+48,"esp"),@X[3]); + &add ($D,$inp); # end of input + &vmovdqa(&QWP(112+64,"esp"),@X[2]); + &add ($inp,64); + &mov (&DWP(192+0,"esp"),$E); # save argument block + &mov (&DWP(192+4,"esp"),$inp); + &mov (&DWP(192+8,"esp"),$D); + &mov (&DWP(192+12,"esp"),@T[0]); # save original %esp + + &mov ($A,&DWP(0,$E)); # load context + &mov ($B,&DWP(4,$E)); + &mov ($C,&DWP(8,$E)); + &mov ($D,&DWP(12,$E)); + &mov ($E,&DWP(16,$E)); + &mov (@T[0],$B); # magic seed + + &vmovdqu(@X[-4&7],&QWP(-64,$inp)); # load input to %xmm[0-3] + &vmovdqu(@X[-3&7],&QWP(-48,$inp)); + &vmovdqu(@X[-2&7],&QWP(-32,$inp)); + &vmovdqu(@X[-1&7],&QWP(-16,$inp)); + &vpshufb(@X[-4&7],@X[-4&7],@X[2]); # byte swap + &vpshufb(@X[-3&7],@X[-3&7],@X[2]); + &vpshufb(@X[-2&7],@X[-2&7],@X[2]); + &vmovdqa(&QWP(112-16,"esp"),@X[3]); # borrow last backtrace slot + &vpshufb(@X[-1&7],@X[-1&7],@X[2]); + &vpaddd (@X[0],@X[-4&7],@X[3]); # add K_00_19 + &vpaddd (@X[1],@X[-3&7],@X[3]); + &vpaddd (@X[2],@X[-2&7],@X[3]); + &vmovdqa(&QWP(0,"esp"),@X[0]); # X[]+K xfer to IALU + &mov (@T[1],$C); + &vmovdqa(&QWP(0+16,"esp"),@X[1]); + &xor (@T[1],$D); + &vmovdqa(&QWP(0+32,"esp"),@X[2]); + &and (@T[0],@T[1]); + &jmp (&label("loop")); + +sub Xupdate_avx_16_31() # recall that $Xi starts with 4 +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 40 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); + eval(shift(@insns)); + &vpalignr(@X[0],@X[-3&7],@X[-4&7],8); # compose "X[-14]" in "X[0]" + eval(shift(@insns)); + eval(shift(@insns)); + + &vpaddd (@X[3],@X[3],@X[-1&7]); + &vmovdqa (&QWP(64+16*(($Xi-4)%3),"esp"),@X[-4&7]);# save X[] to backtrace buffer + eval(shift(@insns)); + eval(shift(@insns)); + &vpsrldq(@X[2],@X[-1&7],4); # "X[-3]", 3 dwords + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor (@X[0],@X[0],@X[-4&7]); # "X[0]"^="X[-16]" + eval(shift(@insns)); + eval(shift(@insns)); + + &vpxor (@X[2],@X[2],@X[-2&7]); # "X[-3]"^"X[-8]" + eval(shift(@insns)); + eval(shift(@insns)); + &vmovdqa (&QWP(0+16*(($Xi-1)&3),"esp"),@X[3]); # X[]+K xfer to IALU + eval(shift(@insns)); + eval(shift(@insns)); + + &vpxor (@X[0],@X[0],@X[2]); # "X[0]"^="X[-3]"^"X[-8]" + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpsrld (@X[2],@X[0],31); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpslldq(@X[4],@X[0],12); # "X[0]"<<96, extract one dword + &vpaddd (@X[0],@X[0],@X[0]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpsrld (@X[3],@X[4],30); + &vpor (@X[0],@X[0],@X[2]); # "X[0]"<<<=1 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpslld (@X[4],@X[4],2); + &vmovdqa (@X[2],&QWP(64+16*(($Xi-6)%3),"esp")) if ($Xi>5); # restore X[] from backtrace buffer + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor (@X[0],@X[0],@X[3]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpxor (@X[0],@X[0],@X[4]); # "X[0]"^=("X[0]"<<96)<<<2 + eval(shift(@insns)); + eval(shift(@insns)); + &vmovdqa (@X[4],&QWP(112-16+16*(($Xi)/5),"esp")); # K_XX_XX + eval(shift(@insns)); + eval(shift(@insns)); + + foreach (@insns) { eval; } # remaining instructions [if any] + + $Xi++; push(@X,shift(@X)); # "rotate" X[] +} + +sub Xupdate_avx_32_79() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 to 44 instructions + my ($a,$b,$c,$d,$e); + + &vpalignr(@X[2],@X[-1&7],@X[-2&7],8); # compose "X[-6]" + &vpxor (@X[0],@X[0],@X[-4&7]); # "X[0]"="X[-32]"^"X[-16]" + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + + &vpxor (@X[0],@X[0],@X[-7&7]); # "X[0]"^="X[-28]" + &vmovdqa (&QWP(64+16*(($Xi-4)%3),"esp"),@X[-4&7]); # save X[] to backtrace buffer + eval(shift(@insns)); + eval(shift(@insns)); + if ($Xi%5) { + &vmovdqa (@X[4],@X[3]); # "perpetuate" K_XX_XX... + } else { # ... or load next one + &vmovdqa (@X[4],&QWP(112-16+16*($Xi/5),"esp")); + } + &vpaddd (@X[3],@X[3],@X[-1&7]); + eval(shift(@insns)); # ror + eval(shift(@insns)); + + &vpxor (@X[0],@X[0],@X[2]); # "X[0]"^="X[-6]" + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + + &vpsrld (@X[2],@X[0],30); + &vmovdqa (&QWP(0+16*(($Xi-1)&3),"esp"),@X[3]); # X[]+K xfer to IALU + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # ror + eval(shift(@insns)); + + &vpslld (@X[0],@X[0],2); + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # ror + eval(shift(@insns)); + + &vpor (@X[0],@X[0],@X[2]); # "X[0]"<<<=2 + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + &vmovdqa (@X[2],&QWP(64+16*(($Xi-6)%3),"esp")) if($Xi<19); # restore X[] from backtrace buffer + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # ror + eval(shift(@insns)); + + foreach (@insns) { eval; } # remaining instructions + + $Xi++; push(@X,shift(@X)); # "rotate" X[] +} + +sub Xuplast_avx_80() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); + &vpaddd (@X[3],@X[3],@X[-1&7]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vmovdqa (&QWP(0+16*(($Xi-1)&3),"esp"),@X[3]); # X[]+K xfer IALU + + foreach (@insns) { eval; } # remaining instructions + + &mov ($inp=@T[1],&DWP(192+4,"esp")); + &cmp ($inp,&DWP(192+8,"esp")); + &je (&label("done")); + + &vmovdqa(@X[3],&QWP(112+48,"esp")); # K_00_19 + &vmovdqa(@X[2],&QWP(112+64,"esp")); # pbswap mask + &vmovdqu(@X[-4&7],&QWP(0,$inp)); # load input + &vmovdqu(@X[-3&7],&QWP(16,$inp)); + &vmovdqu(@X[-2&7],&QWP(32,$inp)); + &vmovdqu(@X[-1&7],&QWP(48,$inp)); + &add ($inp,64); + &vpshufb(@X[-4&7],@X[-4&7],@X[2]); # byte swap + &mov (&DWP(192+4,"esp"),$inp); + &vmovdqa(&QWP(112-16,"esp"),@X[3]); # borrow last backtrace slot + + $Xi=0; +} + +sub Xloop_avx() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); + eval(shift(@insns)); + &vpshufb (@X[($Xi-3)&7],@X[($Xi-3)&7],@X[2]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpaddd (@X[$Xi&7],@X[($Xi-4)&7],@X[3]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vmovdqa (&QWP(0+16*$Xi,"esp"),@X[$Xi&7]); # X[]+K xfer to IALU + eval(shift(@insns)); + eval(shift(@insns)); + + foreach (@insns) { eval; } + $Xi++; +} + +sub Xtail_avx() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + foreach (@insns) { eval; } +} + +&set_label("loop",16); + &Xupdate_avx_16_31(\&body_00_19); + &Xupdate_avx_16_31(\&body_00_19); + &Xupdate_avx_16_31(\&body_00_19); + &Xupdate_avx_16_31(\&body_00_19); + &Xupdate_avx_32_79(\&body_00_19); + &Xupdate_avx_32_79(\&body_20_39); + &Xupdate_avx_32_79(\&body_20_39); + &Xupdate_avx_32_79(\&body_20_39); + &Xupdate_avx_32_79(\&body_20_39); + &Xupdate_avx_32_79(\&body_20_39); + &Xupdate_avx_32_79(\&body_40_59); + &Xupdate_avx_32_79(\&body_40_59); + &Xupdate_avx_32_79(\&body_40_59); + &Xupdate_avx_32_79(\&body_40_59); + &Xupdate_avx_32_79(\&body_40_59); + &Xupdate_avx_32_79(\&body_20_39); + &Xuplast_avx_80(\&body_20_39); # can jump to "done" + + $saved_j=$j; @saved_V=@V; + + &Xloop_avx(\&body_20_39); + &Xloop_avx(\&body_20_39); + &Xloop_avx(\&body_20_39); + + &mov (@T[1],&DWP(192,"esp")); # update context + &add ($A,&DWP(0,@T[1])); + &add (@T[0],&DWP(4,@T[1])); # $b + &add ($C,&DWP(8,@T[1])); + &mov (&DWP(0,@T[1]),$A); + &add ($D,&DWP(12,@T[1])); + &mov (&DWP(4,@T[1]),@T[0]); + &add ($E,&DWP(16,@T[1])); + &mov ($B,$C); + &mov (&DWP(8,@T[1]),$C); + &xor ($B,$D); + &mov (&DWP(12,@T[1]),$D); + &mov (&DWP(16,@T[1]),$E); + &mov (@T[1],@T[0]); + &and (@T[0],$B); + &mov ($B,@T[1]); + + &jmp (&label("loop")); + +&set_label("done",16); $j=$saved_j; @V=@saved_V; + + &Xtail_avx(\&body_20_39); + &Xtail_avx(\&body_20_39); + &Xtail_avx(\&body_20_39); + + &vzeroall(); + + &mov (@T[1],&DWP(192,"esp")); # update context + &add ($A,&DWP(0,@T[1])); + &mov ("esp",&DWP(192+12,"esp")); # restore %esp + &add (@T[0],&DWP(4,@T[1])); # $b + &add ($C,&DWP(8,@T[1])); + &mov (&DWP(0,@T[1]),$A); + &add ($D,&DWP(12,@T[1])); + &mov (&DWP(4,@T[1]),@T[0]); + &add ($E,&DWP(16,@T[1])); + &mov (&DWP(8,@T[1]),$C); + &mov (&DWP(12,@T[1]),$D); + &mov (&DWP(16,@T[1]),$E); +&function_end("_sha1_block_data_order_avx"); +} +&set_label("K_XX_XX",64); +&data_word(0x5a827999,0x5a827999,0x5a827999,0x5a827999); # K_00_19 +&data_word(0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1); # K_20_39 +&data_word(0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc); # K_40_59 +&data_word(0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6); # K_60_79 +&data_word(0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f); # pbswap mask +&data_byte(0xf,0xe,0xd,0xc,0xb,0xa,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0); +} +&asciz("SHA1 block transform for x86, CRYPTOGAMS by "); + +&asm_finish(); + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-alpha.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-alpha.pl new file mode 100644 index 000000000..c1a0b0c69 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-alpha.pl @@ -0,0 +1,329 @@ +#! /usr/bin/env perl +# Copyright 2009-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# SHA1 block procedure for Alpha. + +# On 21264 performance is 33% better than code generated by vendor +# compiler, and 75% better than GCC [3.4], and in absolute terms is +# 8.7 cycles per processed byte. Implementation features vectorized +# byte swap, but not Xupdate. + +@X=( "\$0", "\$1", "\$2", "\$3", "\$4", "\$5", "\$6", "\$7", + "\$8", "\$9", "\$10", "\$11", "\$12", "\$13", "\$14", "\$15"); +$ctx="a0"; # $16 +$inp="a1"; +$num="a2"; +$A="a3"; +$B="a4"; # 20 +$C="a5"; +$D="t8"; +$E="t9"; @V=($A,$B,$C,$D,$E); +$t0="t10"; # 24 +$t1="t11"; +$t2="ra"; +$t3="t12"; +$K="AT"; # 28 + +sub BODY_00_19 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i+1; +$code.=<<___ if ($i==0); + ldq_u @X[0],0+0($inp) + ldq_u @X[1],0+7($inp) +___ +$code.=<<___ if (!($i&1) && $i<14); + ldq_u @X[$i+2],($i+2)*4+0($inp) + ldq_u @X[$i+3],($i+2)*4+7($inp) +___ +$code.=<<___ if (!($i&1) && $i<15); + extql @X[$i],$inp,@X[$i] + extqh @X[$i+1],$inp,@X[$i+1] + + or @X[$i+1],@X[$i],@X[$i] # pair of 32-bit values are fetched + + srl @X[$i],24,$t0 # vectorized byte swap + srl @X[$i],8,$t2 + + sll @X[$i],8,$t3 + sll @X[$i],24,@X[$i] + zapnot $t0,0x11,$t0 + zapnot $t2,0x22,$t2 + + zapnot @X[$i],0x88,@X[$i] + or $t0,$t2,$t0 + zapnot $t3,0x44,$t3 + sll $a,5,$t1 + + or @X[$i],$t0,@X[$i] + addl $K,$e,$e + and $b,$c,$t2 + zapnot $a,0xf,$a + + or @X[$i],$t3,@X[$i] + srl $a,27,$t0 + bic $d,$b,$t3 + sll $b,30,$b + + extll @X[$i],4,@X[$i+1] # extract upper half + or $t2,$t3,$t2 + addl @X[$i],$e,$e + + addl $t1,$e,$e + srl $b,32,$t3 + zapnot @X[$i],0xf,@X[$i] + + addl $t0,$e,$e + addl $t2,$e,$e + or $t3,$b,$b +___ +$code.=<<___ if (($i&1) && $i<15); + sll $a,5,$t1 + addl $K,$e,$e + and $b,$c,$t2 + zapnot $a,0xf,$a + + srl $a,27,$t0 + addl @X[$i%16],$e,$e + bic $d,$b,$t3 + sll $b,30,$b + + or $t2,$t3,$t2 + addl $t1,$e,$e + srl $b,32,$t3 + zapnot @X[$i],0xf,@X[$i] + + addl $t0,$e,$e + addl $t2,$e,$e + or $t3,$b,$b +___ +$code.=<<___ if ($i>=15); # with forward Xupdate + sll $a,5,$t1 + addl $K,$e,$e + and $b,$c,$t2 + xor @X[($j+2)%16],@X[$j%16],@X[$j%16] + + zapnot $a,0xf,$a + addl @X[$i%16],$e,$e + bic $d,$b,$t3 + xor @X[($j+8)%16],@X[$j%16],@X[$j%16] + + srl $a,27,$t0 + addl $t1,$e,$e + or $t2,$t3,$t2 + xor @X[($j+13)%16],@X[$j%16],@X[$j%16] + + sll $b,30,$b + addl $t0,$e,$e + srl @X[$j%16],31,$t1 + + addl $t2,$e,$e + srl $b,32,$t3 + addl @X[$j%16],@X[$j%16],@X[$j%16] + + or $t3,$b,$b + zapnot @X[$i%16],0xf,@X[$i%16] + or $t1,@X[$j%16],@X[$j%16] +___ +} + +sub BODY_20_39 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i+1; +$code.=<<___ if ($i<79); # with forward Xupdate + sll $a,5,$t1 + addl $K,$e,$e + zapnot $a,0xf,$a + xor @X[($j+2)%16],@X[$j%16],@X[$j%16] + + sll $b,30,$t3 + addl $t1,$e,$e + xor $b,$c,$t2 + xor @X[($j+8)%16],@X[$j%16],@X[$j%16] + + srl $b,2,$b + addl @X[$i%16],$e,$e + xor $d,$t2,$t2 + xor @X[($j+13)%16],@X[$j%16],@X[$j%16] + + srl @X[$j%16],31,$t1 + addl $t2,$e,$e + srl $a,27,$t0 + addl @X[$j%16],@X[$j%16],@X[$j%16] + + or $t3,$b,$b + addl $t0,$e,$e + or $t1,@X[$j%16],@X[$j%16] +___ +$code.=<<___ if ($i<77); + zapnot @X[$i%16],0xf,@X[$i%16] +___ +$code.=<<___ if ($i==79); # with context fetch + sll $a,5,$t1 + addl $K,$e,$e + zapnot $a,0xf,$a + ldl @X[0],0($ctx) + + sll $b,30,$t3 + addl $t1,$e,$e + xor $b,$c,$t2 + ldl @X[1],4($ctx) + + srl $b,2,$b + addl @X[$i%16],$e,$e + xor $d,$t2,$t2 + ldl @X[2],8($ctx) + + srl $a,27,$t0 + addl $t2,$e,$e + ldl @X[3],12($ctx) + + or $t3,$b,$b + addl $t0,$e,$e + ldl @X[4],16($ctx) +___ +} + +sub BODY_40_59 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i+1; +$code.=<<___; # with forward Xupdate + sll $a,5,$t1 + addl $K,$e,$e + zapnot $a,0xf,$a + xor @X[($j+2)%16],@X[$j%16],@X[$j%16] + + srl $a,27,$t0 + and $b,$c,$t2 + and $b,$d,$t3 + xor @X[($j+8)%16],@X[$j%16],@X[$j%16] + + sll $b,30,$b + addl $t1,$e,$e + xor @X[($j+13)%16],@X[$j%16],@X[$j%16] + + srl @X[$j%16],31,$t1 + addl $t0,$e,$e + or $t2,$t3,$t2 + and $c,$d,$t3 + + or $t2,$t3,$t2 + srl $b,32,$t3 + addl @X[$i%16],$e,$e + addl @X[$j%16],@X[$j%16],@X[$j%16] + + or $t3,$b,$b + addl $t2,$e,$e + or $t1,@X[$j%16],@X[$j%16] + zapnot @X[$i%16],0xf,@X[$i%16] +___ +} + +$code=<<___; +#ifdef __linux__ +#include +#else +#include +#include +#endif + +.text + +.set noat +.set noreorder +.globl sha1_block_data_order +.align 5 +.ent sha1_block_data_order +sha1_block_data_order: + lda sp,-64(sp) + stq ra,0(sp) + stq s0,8(sp) + stq s1,16(sp) + stq s2,24(sp) + stq s3,32(sp) + stq s4,40(sp) + stq s5,48(sp) + stq fp,56(sp) + .mask 0x0400fe00,-64 + .frame sp,64,ra + .prologue 0 + + ldl $A,0($ctx) + ldl $B,4($ctx) + sll $num,6,$num + ldl $C,8($ctx) + ldl $D,12($ctx) + ldl $E,16($ctx) + addq $inp,$num,$num + +.Lloop: + .set noreorder + ldah $K,23170(zero) + zapnot $B,0xf,$B + lda $K,31129($K) # K_00_19 +___ +for ($i=0;$i<20;$i++) { &BODY_00_19($i,@V); unshift(@V,pop(@V)); } + +$code.=<<___; + ldah $K,28378(zero) + lda $K,-5215($K) # K_20_39 +___ +for (;$i<40;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); } + +$code.=<<___; + ldah $K,-28900(zero) + lda $K,-17188($K) # K_40_59 +___ +for (;$i<60;$i++) { &BODY_40_59($i,@V); unshift(@V,pop(@V)); } + +$code.=<<___; + ldah $K,-13725(zero) + lda $K,-15914($K) # K_60_79 +___ +for (;$i<80;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); } + +$code.=<<___; + addl @X[0],$A,$A + addl @X[1],$B,$B + addl @X[2],$C,$C + addl @X[3],$D,$D + addl @X[4],$E,$E + stl $A,0($ctx) + stl $B,4($ctx) + addq $inp,64,$inp + stl $C,8($ctx) + stl $D,12($ctx) + stl $E,16($ctx) + cmpult $inp,$num,$t1 + bne $t1,.Lloop + + .set noreorder + ldq ra,0(sp) + ldq s0,8(sp) + ldq s1,16(sp) + ldq s2,24(sp) + ldq s3,32(sp) + ldq s4,40(sp) + ldq s5,48(sp) + ldq fp,56(sp) + lda sp,64(sp) + ret (ra) +.end sha1_block_data_order +.ascii "SHA1 block transform for Alpha, CRYPTOGAMS by " +.align 2 +___ +$output=pop and open STDOUT,">$output"; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-armv4-large.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-armv4-large.pl new file mode 100644 index 000000000..7ff5bfbba --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-armv4-large.pl @@ -0,0 +1,742 @@ +#! /usr/bin/env perl +# Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# sha1_block procedure for ARMv4. +# +# January 2007. + +# Size/performance trade-off +# ==================================================================== +# impl size in bytes comp cycles[*] measured performance +# ==================================================================== +# thumb 304 3212 4420 +# armv4-small 392/+29% 1958/+64% 2250/+96% +# armv4-compact 740/+89% 1552/+26% 1840/+22% +# armv4-large 1420/+92% 1307/+19% 1370/+34%[***] +# full unroll ~5100/+260% ~1260/+4% ~1300/+5% +# ==================================================================== +# thumb = same as 'small' but in Thumb instructions[**] and +# with recurring code in two private functions; +# small = detached Xload/update, loops are folded; +# compact = detached Xload/update, 5x unroll; +# large = interleaved Xload/update, 5x unroll; +# full unroll = interleaved Xload/update, full unroll, estimated[!]; +# +# [*] Manually counted instructions in "grand" loop body. Measured +# performance is affected by prologue and epilogue overhead, +# i-cache availability, branch penalties, etc. +# [**] While each Thumb instruction is twice smaller, they are not as +# diverse as ARM ones: e.g., there are only two arithmetic +# instructions with 3 arguments, no [fixed] rotate, addressing +# modes are limited. As result it takes more instructions to do +# the same job in Thumb, therefore the code is never twice as +# small and always slower. +# [***] which is also ~35% better than compiler generated code. Dual- +# issue Cortex A8 core was measured to process input block in +# ~990 cycles. + +# August 2010. +# +# Rescheduling for dual-issue pipeline resulted in 13% improvement on +# Cortex A8 core and in absolute terms ~870 cycles per input block +# [or 13.6 cycles per byte]. + +# February 2011. +# +# Profiler-assisted and platform-specific optimization resulted in 10% +# improvement on Cortex A8 core and 12.2 cycles per byte. + +# September 2013. +# +# Add NEON implementation (see sha1-586.pl for background info). On +# Cortex A8 it was measured to process one byte in 6.7 cycles or >80% +# faster than integer-only code. Because [fully unrolled] NEON code +# is ~2.5x larger and there are some redundant instructions executed +# when processing last block, improvement is not as big for smallest +# blocks, only ~30%. Snapdragon S4 is a tad faster, 6.4 cycles per +# byte, which is also >80% faster than integer-only code. Cortex-A15 +# is even faster spending 5.6 cycles per byte outperforming integer- +# only code by factor of 2. + +# May 2014. +# +# Add ARMv8 code path performing at 2.35 cpb on Apple A7. + +$flavour = shift; +if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + open STDOUT,">$output"; +} + +$ctx="r0"; +$inp="r1"; +$len="r2"; +$a="r3"; +$b="r4"; +$c="r5"; +$d="r6"; +$e="r7"; +$K="r8"; +$t0="r9"; +$t1="r10"; +$t2="r11"; +$t3="r12"; +$Xi="r14"; +@V=($a,$b,$c,$d,$e); + +sub Xupdate { +my ($a,$b,$c,$d,$e,$opt1,$opt2)=@_; +$code.=<<___; + ldr $t0,[$Xi,#15*4] + ldr $t1,[$Xi,#13*4] + ldr $t2,[$Xi,#7*4] + add $e,$K,$e,ror#2 @ E+=K_xx_xx + ldr $t3,[$Xi,#2*4] + eor $t0,$t0,$t1 + eor $t2,$t2,$t3 @ 1 cycle stall + eor $t1,$c,$d @ F_xx_xx + mov $t0,$t0,ror#31 + add $e,$e,$a,ror#27 @ E+=ROR(A,27) + eor $t0,$t0,$t2,ror#31 + str $t0,[$Xi,#-4]! + $opt1 @ F_xx_xx + $opt2 @ F_xx_xx + add $e,$e,$t0 @ E+=X[i] +___ +} + +sub BODY_00_15 { +my ($a,$b,$c,$d,$e)=@_; +$code.=<<___; +#if __ARM_ARCH__<7 + ldrb $t1,[$inp,#2] + ldrb $t0,[$inp,#3] + ldrb $t2,[$inp,#1] + add $e,$K,$e,ror#2 @ E+=K_00_19 + ldrb $t3,[$inp],#4 + orr $t0,$t0,$t1,lsl#8 + eor $t1,$c,$d @ F_xx_xx + orr $t0,$t0,$t2,lsl#16 + add $e,$e,$a,ror#27 @ E+=ROR(A,27) + orr $t0,$t0,$t3,lsl#24 +#else + ldr $t0,[$inp],#4 @ handles unaligned + add $e,$K,$e,ror#2 @ E+=K_00_19 + eor $t1,$c,$d @ F_xx_xx + add $e,$e,$a,ror#27 @ E+=ROR(A,27) +#ifdef __ARMEL__ + rev $t0,$t0 @ byte swap +#endif +#endif + and $t1,$b,$t1,ror#2 + add $e,$e,$t0 @ E+=X[i] + eor $t1,$t1,$d,ror#2 @ F_00_19(B,C,D) + str $t0,[$Xi,#-4]! + add $e,$e,$t1 @ E+=F_00_19(B,C,D) +___ +} + +sub BODY_16_19 { +my ($a,$b,$c,$d,$e)=@_; + &Xupdate(@_,"and $t1,$b,$t1,ror#2"); +$code.=<<___; + eor $t1,$t1,$d,ror#2 @ F_00_19(B,C,D) + add $e,$e,$t1 @ E+=F_00_19(B,C,D) +___ +} + +sub BODY_20_39 { +my ($a,$b,$c,$d,$e)=@_; + &Xupdate(@_,"eor $t1,$b,$t1,ror#2"); +$code.=<<___; + add $e,$e,$t1 @ E+=F_20_39(B,C,D) +___ +} + +sub BODY_40_59 { +my ($a,$b,$c,$d,$e)=@_; + &Xupdate(@_,"and $t1,$b,$t1,ror#2","and $t2,$c,$d"); +$code.=<<___; + add $e,$e,$t1 @ E+=F_40_59(B,C,D) + add $e,$e,$t2,ror#2 +___ +} + +$code=<<___; +#include "arm_arch.h" + +.text +#if defined(__thumb2__) +.syntax unified +.thumb +#else +.code 32 +#endif + +.global sha1_block_data_order +.type sha1_block_data_order,%function + +.align 5 +sha1_block_data_order: +#if __ARM_MAX_ARCH__>=7 +.Lsha1_block: + adr r3,.Lsha1_block + ldr r12,.LOPENSSL_armcap + ldr r12,[r3,r12] @ OPENSSL_armcap_P +#ifdef __APPLE__ + ldr r12,[r12] +#endif + tst r12,#ARMV8_SHA1 + bne .LARMv8 + tst r12,#ARMV7_NEON + bne .LNEON +#endif + stmdb sp!,{r4-r12,lr} + add $len,$inp,$len,lsl#6 @ $len to point at the end of $inp + ldmia $ctx,{$a,$b,$c,$d,$e} +.Lloop: + ldr $K,.LK_00_19 + mov $Xi,sp + sub sp,sp,#15*4 + mov $c,$c,ror#30 + mov $d,$d,ror#30 + mov $e,$e,ror#30 @ [6] +.L_00_15: +___ +for($i=0;$i<5;$i++) { + &BODY_00_15(@V); unshift(@V,pop(@V)); +} +$code.=<<___; +#if defined(__thumb2__) + mov $t3,sp + teq $Xi,$t3 +#else + teq $Xi,sp +#endif + bne .L_00_15 @ [((11+4)*5+2)*3] + sub sp,sp,#25*4 +___ + &BODY_00_15(@V); unshift(@V,pop(@V)); + &BODY_16_19(@V); unshift(@V,pop(@V)); + &BODY_16_19(@V); unshift(@V,pop(@V)); + &BODY_16_19(@V); unshift(@V,pop(@V)); + &BODY_16_19(@V); unshift(@V,pop(@V)); +$code.=<<___; + + ldr $K,.LK_20_39 @ [+15+16*4] + cmn sp,#0 @ [+3], clear carry to denote 20_39 +.L_20_39_or_60_79: +___ +for($i=0;$i<5;$i++) { + &BODY_20_39(@V); unshift(@V,pop(@V)); +} +$code.=<<___; +#if defined(__thumb2__) + mov $t3,sp + teq $Xi,$t3 +#else + teq $Xi,sp @ preserve carry +#endif + bne .L_20_39_or_60_79 @ [+((12+3)*5+2)*4] + bcs .L_done @ [+((12+3)*5+2)*4], spare 300 bytes + + ldr $K,.LK_40_59 + sub sp,sp,#20*4 @ [+2] +.L_40_59: +___ +for($i=0;$i<5;$i++) { + &BODY_40_59(@V); unshift(@V,pop(@V)); +} +$code.=<<___; +#if defined(__thumb2__) + mov $t3,sp + teq $Xi,$t3 +#else + teq $Xi,sp +#endif + bne .L_40_59 @ [+((12+5)*5+2)*4] + + ldr $K,.LK_60_79 + sub sp,sp,#20*4 + cmp sp,#0 @ set carry to denote 60_79 + b .L_20_39_or_60_79 @ [+4], spare 300 bytes +.L_done: + add sp,sp,#80*4 @ "deallocate" stack frame + ldmia $ctx,{$K,$t0,$t1,$t2,$t3} + add $a,$K,$a + add $b,$t0,$b + add $c,$t1,$c,ror#2 + add $d,$t2,$d,ror#2 + add $e,$t3,$e,ror#2 + stmia $ctx,{$a,$b,$c,$d,$e} + teq $inp,$len + bne .Lloop @ [+18], total 1307 + +#if __ARM_ARCH__>=5 + ldmia sp!,{r4-r12,pc} +#else + ldmia sp!,{r4-r12,lr} + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.size sha1_block_data_order,.-sha1_block_data_order + +.align 5 +.LK_00_19: .word 0x5a827999 +.LK_20_39: .word 0x6ed9eba1 +.LK_40_59: .word 0x8f1bbcdc +.LK_60_79: .word 0xca62c1d6 +#if __ARM_MAX_ARCH__>=7 +.LOPENSSL_armcap: +.word OPENSSL_armcap_P-.Lsha1_block +#endif +.asciz "SHA1 block transform for ARMv4/NEON/ARMv8, CRYPTOGAMS by " +.align 5 +___ +##################################################################### +# NEON stuff +# +{{{ +my @V=($a,$b,$c,$d,$e); +my ($K_XX_XX,$Ki,$t0,$t1,$Xfer,$saved_sp)=map("r$_",(8..12,14)); +my $Xi=4; +my @X=map("q$_",(8..11,0..3)); +my @Tx=("q12","q13"); +my ($K,$zero)=("q14","q15"); +my $j=0; + +sub AUTOLOAD() # thunk [simplified] x86-style perlasm +{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; $opcode =~ s/_/\./; + my $arg = pop; + $arg = "#$arg" if ($arg*1 eq $arg); + $code .= "\t$opcode\t".join(',',@_,$arg)."\n"; +} + +sub body_00_19 () { + ( + '($a,$b,$c,$d,$e)=@V;'. # '$code.="@ $j\n";'. + '&bic ($t0,$d,$b)', + '&add ($e,$e,$Ki)', # e+=X[i]+K + '&and ($t1,$c,$b)', + '&ldr ($Ki,sprintf "[sp,#%d]",4*(($j+1)&15))', + '&add ($e,$e,$a,"ror#27")', # e+=ROR(A,27) + '&eor ($t1,$t1,$t0)', # F_00_19 + '&mov ($b,$b,"ror#2")', # b=ROR(b,2) + '&add ($e,$e,$t1);'. # e+=F_00_19 + '$j++; unshift(@V,pop(@V));' + ) +} +sub body_20_39 () { + ( + '($a,$b,$c,$d,$e)=@V;'. # '$code.="@ $j\n";'. + '&eor ($t0,$b,$d)', + '&add ($e,$e,$Ki)', # e+=X[i]+K + '&ldr ($Ki,sprintf "[sp,#%d]",4*(($j+1)&15)) if ($j<79)', + '&eor ($t1,$t0,$c)', # F_20_39 + '&add ($e,$e,$a,"ror#27")', # e+=ROR(A,27) + '&mov ($b,$b,"ror#2")', # b=ROR(b,2) + '&add ($e,$e,$t1);'. # e+=F_20_39 + '$j++; unshift(@V,pop(@V));' + ) +} +sub body_40_59 () { + ( + '($a,$b,$c,$d,$e)=@V;'. # '$code.="@ $j\n";'. + '&add ($e,$e,$Ki)', # e+=X[i]+K + '&and ($t0,$c,$d)', + '&ldr ($Ki,sprintf "[sp,#%d]",4*(($j+1)&15))', + '&add ($e,$e,$a,"ror#27")', # e+=ROR(A,27) + '&eor ($t1,$c,$d)', + '&add ($e,$e,$t0)', + '&and ($t1,$t1,$b)', + '&mov ($b,$b,"ror#2")', # b=ROR(b,2) + '&add ($e,$e,$t1);'. # e+=F_40_59 + '$j++; unshift(@V,pop(@V));' + ) +} + +sub Xupdate_16_31 () +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); + my ($a,$b,$c,$d,$e); + + &vext_8 (@X[0],@X[-4&7],@X[-3&7],8); # compose "X[-14]" in "X[0]" + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vadd_i32 (@Tx[1],@X[-1&7],$K); + eval(shift(@insns)); + &vld1_32 ("{$K\[]}","[$K_XX_XX,:32]!") if ($Xi%5==0); + eval(shift(@insns)); + &vext_8 (@Tx[0],@X[-1&7],$zero,4); # "X[-3]", 3 words + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &veor (@X[0],@X[0],@X[-4&7]); # "X[0]"^="X[-16]" + eval(shift(@insns)); + eval(shift(@insns)); + &veor (@Tx[0],@Tx[0],@X[-2&7]); # "X[-3]"^"X[-8]" + eval(shift(@insns)); + eval(shift(@insns)); + &veor (@Tx[0],@Tx[0],@X[0]); # "X[0]"^="X[-3]"^"X[-8] + eval(shift(@insns)); + eval(shift(@insns)); + &vst1_32 ("{@Tx[1]}","[$Xfer,:128]!"); # X[]+K xfer + &sub ($Xfer,$Xfer,64) if ($Xi%4==0); + eval(shift(@insns)); + eval(shift(@insns)); + &vext_8 (@Tx[1],$zero,@Tx[0],4); # "X[0]"<<96, extract one dword + eval(shift(@insns)); + eval(shift(@insns)); + &vadd_i32 (@X[0],@Tx[0],@Tx[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &vsri_32 (@X[0],@Tx[0],31); # "X[0]"<<<=1 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vshr_u32 (@Tx[0],@Tx[1],30); + eval(shift(@insns)); + eval(shift(@insns)); + &vshl_u32 (@Tx[1],@Tx[1],2); + eval(shift(@insns)); + eval(shift(@insns)); + &veor (@X[0],@X[0],@Tx[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &veor (@X[0],@X[0],@Tx[1]); # "X[0]"^=("X[0]">>96)<<<2 + + foreach (@insns) { eval; } # remaining instructions [if any] + + $Xi++; push(@X,shift(@X)); # "rotate" X[] +} + +sub Xupdate_32_79 () +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); + my ($a,$b,$c,$d,$e); + + &vext_8 (@Tx[0],@X[-2&7],@X[-1&7],8); # compose "X[-6]" + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &veor (@X[0],@X[0],@X[-4&7]); # "X[0]"="X[-32]"^"X[-16]" + eval(shift(@insns)); + eval(shift(@insns)); + &veor (@X[0],@X[0],@X[-7&7]); # "X[0]"^="X[-28]" + eval(shift(@insns)); + eval(shift(@insns)); + &vadd_i32 (@Tx[1],@X[-1&7],$K); + eval(shift(@insns)); + &vld1_32 ("{$K\[]}","[$K_XX_XX,:32]!") if ($Xi%5==0); + eval(shift(@insns)); + &veor (@Tx[0],@Tx[0],@X[0]); # "X[-6]"^="X[0]" + eval(shift(@insns)); + eval(shift(@insns)); + &vshr_u32 (@X[0],@Tx[0],30); + eval(shift(@insns)); + eval(shift(@insns)); + &vst1_32 ("{@Tx[1]}","[$Xfer,:128]!"); # X[]+K xfer + &sub ($Xfer,$Xfer,64) if ($Xi%4==0); + eval(shift(@insns)); + eval(shift(@insns)); + &vsli_32 (@X[0],@Tx[0],2); # "X[0]"="X[-6]"<<<2 + + foreach (@insns) { eval; } # remaining instructions [if any] + + $Xi++; push(@X,shift(@X)); # "rotate" X[] +} + +sub Xuplast_80 () +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); + my ($a,$b,$c,$d,$e); + + &vadd_i32 (@Tx[1],@X[-1&7],$K); + eval(shift(@insns)); + eval(shift(@insns)); + &vst1_32 ("{@Tx[1]}","[$Xfer,:128]!"); + &sub ($Xfer,$Xfer,64); + + &teq ($inp,$len); + &sub ($K_XX_XX,$K_XX_XX,16); # rewind $K_XX_XX + &it ("eq"); + &subeq ($inp,$inp,64); # reload last block to avoid SEGV + &vld1_8 ("{@X[-4&7]-@X[-3&7]}","[$inp]!"); + eval(shift(@insns)); + eval(shift(@insns)); + &vld1_8 ("{@X[-2&7]-@X[-1&7]}","[$inp]!"); + eval(shift(@insns)); + eval(shift(@insns)); + &vld1_32 ("{$K\[]}","[$K_XX_XX,:32]!"); # load K_00_19 + eval(shift(@insns)); + eval(shift(@insns)); + &vrev32_8 (@X[-4&7],@X[-4&7]); + + foreach (@insns) { eval; } # remaining instructions + + $Xi=0; +} + +sub Xloop() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); + my ($a,$b,$c,$d,$e); + + &vrev32_8 (@X[($Xi-3)&7],@X[($Xi-3)&7]); + eval(shift(@insns)); + eval(shift(@insns)); + &vadd_i32 (@X[$Xi&7],@X[($Xi-4)&7],$K); + eval(shift(@insns)); + eval(shift(@insns)); + &vst1_32 ("{@X[$Xi&7]}","[$Xfer,:128]!");# X[]+K xfer to IALU + + foreach (@insns) { eval; } + + $Xi++; +} + +$code.=<<___; +#if __ARM_MAX_ARCH__>=7 +.arch armv7-a +.fpu neon + +.type sha1_block_data_order_neon,%function +.align 4 +sha1_block_data_order_neon: +.LNEON: + stmdb sp!,{r4-r12,lr} + add $len,$inp,$len,lsl#6 @ $len to point at the end of $inp + @ dmb @ errata #451034 on early Cortex A8 + @ vstmdb sp!,{d8-d15} @ ABI specification says so + mov $saved_sp,sp + sub $Xfer,sp,#64 + adr $K_XX_XX,.LK_00_19 + bic $Xfer,$Xfer,#15 @ align for 128-bit stores + + ldmia $ctx,{$a,$b,$c,$d,$e} @ load context + mov sp,$Xfer @ alloca + + vld1.8 {@X[-4&7]-@X[-3&7]},[$inp]! @ handles unaligned + veor $zero,$zero,$zero + vld1.8 {@X[-2&7]-@X[-1&7]},[$inp]! + vld1.32 {${K}\[]},[$K_XX_XX,:32]! @ load K_00_19 + vrev32.8 @X[-4&7],@X[-4&7] @ yes, even on + vrev32.8 @X[-3&7],@X[-3&7] @ big-endian... + vrev32.8 @X[-2&7],@X[-2&7] + vadd.i32 @X[0],@X[-4&7],$K + vrev32.8 @X[-1&7],@X[-1&7] + vadd.i32 @X[1],@X[-3&7],$K + vst1.32 {@X[0]},[$Xfer,:128]! + vadd.i32 @X[2],@X[-2&7],$K + vst1.32 {@X[1]},[$Xfer,:128]! + vst1.32 {@X[2]},[$Xfer,:128]! + ldr $Ki,[sp] @ big RAW stall + +.Loop_neon: +___ + &Xupdate_16_31(\&body_00_19); + &Xupdate_16_31(\&body_00_19); + &Xupdate_16_31(\&body_00_19); + &Xupdate_16_31(\&body_00_19); + &Xupdate_32_79(\&body_00_19); + &Xupdate_32_79(\&body_20_39); + &Xupdate_32_79(\&body_20_39); + &Xupdate_32_79(\&body_20_39); + &Xupdate_32_79(\&body_20_39); + &Xupdate_32_79(\&body_20_39); + &Xupdate_32_79(\&body_40_59); + &Xupdate_32_79(\&body_40_59); + &Xupdate_32_79(\&body_40_59); + &Xupdate_32_79(\&body_40_59); + &Xupdate_32_79(\&body_40_59); + &Xupdate_32_79(\&body_20_39); + &Xuplast_80(\&body_20_39); + &Xloop(\&body_20_39); + &Xloop(\&body_20_39); + &Xloop(\&body_20_39); +$code.=<<___; + ldmia $ctx,{$Ki,$t0,$t1,$Xfer} @ accumulate context + add $a,$a,$Ki + ldr $Ki,[$ctx,#16] + add $b,$b,$t0 + add $c,$c,$t1 + add $d,$d,$Xfer + it eq + moveq sp,$saved_sp + add $e,$e,$Ki + it ne + ldrne $Ki,[sp] + stmia $ctx,{$a,$b,$c,$d,$e} + itt ne + addne $Xfer,sp,#3*16 + bne .Loop_neon + + @ vldmia sp!,{d8-d15} + ldmia sp!,{r4-r12,pc} +.size sha1_block_data_order_neon,.-sha1_block_data_order_neon +#endif +___ +}}} +##################################################################### +# ARMv8 stuff +# +{{{ +my ($ABCD,$E,$E0,$E1)=map("q$_",(0..3)); +my @MSG=map("q$_",(4..7)); +my @Kxx=map("q$_",(8..11)); +my ($W0,$W1,$ABCD_SAVE)=map("q$_",(12..14)); + +$code.=<<___; +#if __ARM_MAX_ARCH__>=7 + +# if defined(__thumb2__) +# define INST(a,b,c,d) .byte c,d|0xf,a,b +# else +# define INST(a,b,c,d) .byte a,b,c,d|0x10 +# endif + +.type sha1_block_data_order_armv8,%function +.align 5 +sha1_block_data_order_armv8: +.LARMv8: + vstmdb sp!,{d8-d15} @ ABI specification says so + + veor $E,$E,$E + adr r3,.LK_00_19 + vld1.32 {$ABCD},[$ctx]! + vld1.32 {$E\[0]},[$ctx] + sub $ctx,$ctx,#16 + vld1.32 {@Kxx[0]\[]},[r3,:32]! + vld1.32 {@Kxx[1]\[]},[r3,:32]! + vld1.32 {@Kxx[2]\[]},[r3,:32]! + vld1.32 {@Kxx[3]\[]},[r3,:32] + +.Loop_v8: + vld1.8 {@MSG[0]-@MSG[1]},[$inp]! + vld1.8 {@MSG[2]-@MSG[3]},[$inp]! + vrev32.8 @MSG[0],@MSG[0] + vrev32.8 @MSG[1],@MSG[1] + + vadd.i32 $W0,@Kxx[0],@MSG[0] + vrev32.8 @MSG[2],@MSG[2] + vmov $ABCD_SAVE,$ABCD @ offload + subs $len,$len,#1 + + vadd.i32 $W1,@Kxx[0],@MSG[1] + vrev32.8 @MSG[3],@MSG[3] + sha1h $E1,$ABCD @ 0 + sha1c $ABCD,$E,$W0 + vadd.i32 $W0,@Kxx[$j],@MSG[2] + sha1su0 @MSG[0],@MSG[1],@MSG[2] +___ +for ($j=0,$i=1;$i<20-3;$i++) { +my $f=("c","p","m","p")[$i/5]; +$code.=<<___; + sha1h $E0,$ABCD @ $i + sha1$f $ABCD,$E1,$W1 + vadd.i32 $W1,@Kxx[$j],@MSG[3] + sha1su1 @MSG[0],@MSG[3] +___ +$code.=<<___ if ($i<20-4); + sha1su0 @MSG[1],@MSG[2],@MSG[3] +___ + ($E0,$E1)=($E1,$E0); ($W0,$W1)=($W1,$W0); + push(@MSG,shift(@MSG)); $j++ if ((($i+3)%5)==0); +} +$code.=<<___; + sha1h $E0,$ABCD @ $i + sha1p $ABCD,$E1,$W1 + vadd.i32 $W1,@Kxx[$j],@MSG[3] + + sha1h $E1,$ABCD @ 18 + sha1p $ABCD,$E0,$W0 + + sha1h $E0,$ABCD @ 19 + sha1p $ABCD,$E1,$W1 + + vadd.i32 $E,$E,$E0 + vadd.i32 $ABCD,$ABCD,$ABCD_SAVE + bne .Loop_v8 + + vst1.32 {$ABCD},[$ctx]! + vst1.32 {$E\[0]},[$ctx] + + vldmia sp!,{d8-d15} + ret @ bx lr +.size sha1_block_data_order_armv8,.-sha1_block_data_order_armv8 +#endif +___ +}}} +$code.=<<___; +#if __ARM_MAX_ARCH__>=7 +.comm OPENSSL_armcap_P,4,4 +#endif +___ + +{ my %opcode = ( + "sha1c" => 0xf2000c40, "sha1p" => 0xf2100c40, + "sha1m" => 0xf2200c40, "sha1su0" => 0xf2300c40, + "sha1h" => 0xf3b902c0, "sha1su1" => 0xf3ba0380 ); + + sub unsha1 { + my ($mnemonic,$arg)=@_; + + if ($arg =~ m/q([0-9]+)(?:,\s*q([0-9]+))?,\s*q([0-9]+)/o) { + my $word = $opcode{$mnemonic}|(($1&7)<<13)|(($1&8)<<19) + |(($2&7)<<17)|(($2&8)<<4) + |(($3&7)<<1) |(($3&8)<<2); + # since ARMv7 instructions are always encoded little-endian. + # correct solution is to use .inst directive, but older + # assemblers don't implement it:-( + + # this fix-up provides Thumb encoding in conjunction with INST + $word &= ~0x10000000 if (($word & 0x0f000000) == 0x02000000); + sprintf "INST(0x%02x,0x%02x,0x%02x,0x%02x)\t@ %s %s", + $word&0xff,($word>>8)&0xff, + ($word>>16)&0xff,($word>>24)&0xff, + $mnemonic,$arg; + } + } +} + +foreach (split($/,$code)) { + s/{q([0-9]+)\[\]}/sprintf "{d%d[],d%d[]}",2*$1,2*$1+1/eo or + s/{q([0-9]+)\[0\]}/sprintf "{d%d[0]}",2*$1/eo; + + s/\b(sha1\w+)\s+(q.*)/unsha1($1,$2)/geo; + + s/\bret\b/bx lr/o or + s/\bbx\s+lr\b/.word\t0xe12fff1e/o; # make it possible to compile with -march=armv4 + + print $_,$/; +} + +close STDOUT; # enforce flush diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-armv8.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-armv8.pl new file mode 100644 index 000000000..3ba871fed --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-armv8.pl @@ -0,0 +1,364 @@ +#! /usr/bin/env perl +# Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# SHA1 for ARMv8. +# +# Performance in cycles per processed byte and improvement coefficient +# over code generated with "default" compiler: +# +# hardware-assisted software(*) +# Apple A7 2.31 4.13 (+14%) +# Cortex-A53 2.24 8.03 (+97%) +# Cortex-A57 2.35 7.88 (+74%) +# Denver 2.13 3.97 (+0%)(**) +# X-Gene 8.80 (+200%) +# Mongoose 2.05 6.50 (+160%) +# Kryo 1.88 8.00 (+90%) +# +# (*) Software results are presented mostly for reference purposes. +# (**) Keep in mind that Denver relies on binary translation, which +# optimizes compiler output at run-time. + +$flavour = shift; +$output = shift; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or +die "can't locate arm-xlate.pl"; + +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; + +($ctx,$inp,$num)=("x0","x1","x2"); +@Xw=map("w$_",(3..17,19)); +@Xx=map("x$_",(3..17,19)); +@V=($A,$B,$C,$D,$E)=map("w$_",(20..24)); +($t0,$t1,$t2,$K)=map("w$_",(25..28)); + + +sub BODY_00_19 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=($i+2)&15; + +$code.=<<___ if ($i<15 && !($i&1)); + lsr @Xx[$i+1],@Xx[$i],#32 +___ +$code.=<<___ if ($i<14 && !($i&1)); + ldr @Xx[$i+2],[$inp,#`($i+2)*4-64`] +___ +$code.=<<___ if ($i<14 && ($i&1)); +#ifdef __ARMEB__ + ror @Xx[$i+1],@Xx[$i+1],#32 +#else + rev32 @Xx[$i+1],@Xx[$i+1] +#endif +___ +$code.=<<___ if ($i<14); + bic $t0,$d,$b + and $t1,$c,$b + ror $t2,$a,#27 + add $d,$d,$K // future e+=K + orr $t0,$t0,$t1 + add $e,$e,$t2 // e+=rot(a,5) + ror $b,$b,#2 + add $d,$d,@Xw[($i+1)&15] // future e+=X[i] + add $e,$e,$t0 // e+=F(b,c,d) +___ +$code.=<<___ if ($i==19); + movz $K,#0xeba1 + movk $K,#0x6ed9,lsl#16 +___ +$code.=<<___ if ($i>=14); + eor @Xw[$j],@Xw[$j],@Xw[($j+2)&15] + bic $t0,$d,$b + and $t1,$c,$b + ror $t2,$a,#27 + eor @Xw[$j],@Xw[$j],@Xw[($j+8)&15] + add $d,$d,$K // future e+=K + orr $t0,$t0,$t1 + add $e,$e,$t2 // e+=rot(a,5) + eor @Xw[$j],@Xw[$j],@Xw[($j+13)&15] + ror $b,$b,#2 + add $d,$d,@Xw[($i+1)&15] // future e+=X[i] + add $e,$e,$t0 // e+=F(b,c,d) + ror @Xw[$j],@Xw[$j],#31 +___ +} + +sub BODY_40_59 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=($i+2)&15; + +$code.=<<___ if ($i==59); + movz $K,#0xc1d6 + movk $K,#0xca62,lsl#16 +___ +$code.=<<___; + orr $t0,$b,$c + and $t1,$b,$c + eor @Xw[$j],@Xw[$j],@Xw[($j+2)&15] + ror $t2,$a,#27 + and $t0,$t0,$d + add $d,$d,$K // future e+=K + eor @Xw[$j],@Xw[$j],@Xw[($j+8)&15] + add $e,$e,$t2 // e+=rot(a,5) + orr $t0,$t0,$t1 + ror $b,$b,#2 + eor @Xw[$j],@Xw[$j],@Xw[($j+13)&15] + add $d,$d,@Xw[($i+1)&15] // future e+=X[i] + add $e,$e,$t0 // e+=F(b,c,d) + ror @Xw[$j],@Xw[$j],#31 +___ +} + +sub BODY_20_39 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=($i+2)&15; + +$code.=<<___ if ($i==39); + movz $K,#0xbcdc + movk $K,#0x8f1b,lsl#16 +___ +$code.=<<___ if ($i<78); + eor @Xw[$j],@Xw[$j],@Xw[($j+2)&15] + eor $t0,$d,$b + ror $t2,$a,#27 + add $d,$d,$K // future e+=K + eor @Xw[$j],@Xw[$j],@Xw[($j+8)&15] + eor $t0,$t0,$c + add $e,$e,$t2 // e+=rot(a,5) + ror $b,$b,#2 + eor @Xw[$j],@Xw[$j],@Xw[($j+13)&15] + add $d,$d,@Xw[($i+1)&15] // future e+=X[i] + add $e,$e,$t0 // e+=F(b,c,d) + ror @Xw[$j],@Xw[$j],#31 +___ +$code.=<<___ if ($i==78); + ldp @Xw[1],@Xw[2],[$ctx] + eor $t0,$d,$b + ror $t2,$a,#27 + add $d,$d,$K // future e+=K + eor $t0,$t0,$c + add $e,$e,$t2 // e+=rot(a,5) + ror $b,$b,#2 + add $d,$d,@Xw[($i+1)&15] // future e+=X[i] + add $e,$e,$t0 // e+=F(b,c,d) +___ +$code.=<<___ if ($i==79); + ldp @Xw[3],@Xw[4],[$ctx,#8] + eor $t0,$d,$b + ror $t2,$a,#27 + eor $t0,$t0,$c + add $e,$e,$t2 // e+=rot(a,5) + ror $b,$b,#2 + ldr @Xw[5],[$ctx,#16] + add $e,$e,$t0 // e+=F(b,c,d) +___ +} + +$code.=<<___; +#include "arm_arch.h" + +.text + +.extern OPENSSL_armcap_P +.globl sha1_block_data_order +.type sha1_block_data_order,%function +.align 6 +sha1_block_data_order: +#ifdef __ILP32__ + ldrsw x16,.LOPENSSL_armcap_P +#else + ldr x16,.LOPENSSL_armcap_P +#endif + adr x17,.LOPENSSL_armcap_P + add x16,x16,x17 + ldr w16,[x16] + tst w16,#ARMV8_SHA1 + b.ne .Lv8_entry + + stp x29,x30,[sp,#-96]! + add x29,sp,#0 + stp x19,x20,[sp,#16] + stp x21,x22,[sp,#32] + stp x23,x24,[sp,#48] + stp x25,x26,[sp,#64] + stp x27,x28,[sp,#80] + + ldp $A,$B,[$ctx] + ldp $C,$D,[$ctx,#8] + ldr $E,[$ctx,#16] + +.Loop: + ldr @Xx[0],[$inp],#64 + movz $K,#0x7999 + sub $num,$num,#1 + movk $K,#0x5a82,lsl#16 +#ifdef __ARMEB__ + ror $Xx[0],@Xx[0],#32 +#else + rev32 @Xx[0],@Xx[0] +#endif + add $E,$E,$K // warm it up + add $E,$E,@Xw[0] +___ +for($i=0;$i<20;$i++) { &BODY_00_19($i,@V); unshift(@V,pop(@V)); } +for(;$i<40;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); } +for(;$i<60;$i++) { &BODY_40_59($i,@V); unshift(@V,pop(@V)); } +for(;$i<80;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + add $B,$B,@Xw[2] + add $C,$C,@Xw[3] + add $A,$A,@Xw[1] + add $D,$D,@Xw[4] + add $E,$E,@Xw[5] + stp $A,$B,[$ctx] + stp $C,$D,[$ctx,#8] + str $E,[$ctx,#16] + cbnz $num,.Loop + + ldp x19,x20,[sp,#16] + ldp x21,x22,[sp,#32] + ldp x23,x24,[sp,#48] + ldp x25,x26,[sp,#64] + ldp x27,x28,[sp,#80] + ldr x29,[sp],#96 + ret +.size sha1_block_data_order,.-sha1_block_data_order +___ +{{{ +my ($ABCD,$E,$E0,$E1)=map("v$_.16b",(0..3)); +my @MSG=map("v$_.16b",(4..7)); +my @Kxx=map("v$_.4s",(16..19)); +my ($W0,$W1)=("v20.4s","v21.4s"); +my $ABCD_SAVE="v22.16b"; + +$code.=<<___; +.type sha1_block_armv8,%function +.align 6 +sha1_block_armv8: +.Lv8_entry: + stp x29,x30,[sp,#-16]! + add x29,sp,#0 + + adr x4,.Lconst + eor $E,$E,$E + ld1.32 {$ABCD},[$ctx],#16 + ld1.32 {$E}[0],[$ctx] + sub $ctx,$ctx,#16 + ld1.32 {@Kxx[0]-@Kxx[3]},[x4] + +.Loop_hw: + ld1 {@MSG[0]-@MSG[3]},[$inp],#64 + sub $num,$num,#1 + rev32 @MSG[0],@MSG[0] + rev32 @MSG[1],@MSG[1] + + add.i32 $W0,@Kxx[0],@MSG[0] + rev32 @MSG[2],@MSG[2] + orr $ABCD_SAVE,$ABCD,$ABCD // offload + + add.i32 $W1,@Kxx[0],@MSG[1] + rev32 @MSG[3],@MSG[3] + sha1h $E1,$ABCD + sha1c $ABCD,$E,$W0 // 0 + add.i32 $W0,@Kxx[$j],@MSG[2] + sha1su0 @MSG[0],@MSG[1],@MSG[2] +___ +for ($j=0,$i=1;$i<20-3;$i++) { +my $f=("c","p","m","p")[$i/5]; +$code.=<<___; + sha1h $E0,$ABCD // $i + sha1$f $ABCD,$E1,$W1 + add.i32 $W1,@Kxx[$j],@MSG[3] + sha1su1 @MSG[0],@MSG[3] +___ +$code.=<<___ if ($i<20-4); + sha1su0 @MSG[1],@MSG[2],@MSG[3] +___ + ($E0,$E1)=($E1,$E0); ($W0,$W1)=($W1,$W0); + push(@MSG,shift(@MSG)); $j++ if ((($i+3)%5)==0); +} +$code.=<<___; + sha1h $E0,$ABCD // $i + sha1p $ABCD,$E1,$W1 + add.i32 $W1,@Kxx[$j],@MSG[3] + + sha1h $E1,$ABCD // 18 + sha1p $ABCD,$E0,$W0 + + sha1h $E0,$ABCD // 19 + sha1p $ABCD,$E1,$W1 + + add.i32 $E,$E,$E0 + add.i32 $ABCD,$ABCD,$ABCD_SAVE + + cbnz $num,.Loop_hw + + st1.32 {$ABCD},[$ctx],#16 + st1.32 {$E}[0],[$ctx] + + ldr x29,[sp],#16 + ret +.size sha1_block_armv8,.-sha1_block_armv8 +.align 6 +.Lconst: +.long 0x5a827999,0x5a827999,0x5a827999,0x5a827999 //K_00_19 +.long 0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1 //K_20_39 +.long 0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc //K_40_59 +.long 0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6 //K_60_79 +.LOPENSSL_armcap_P: +#ifdef __ILP32__ +.long OPENSSL_armcap_P-. +#else +.quad OPENSSL_armcap_P-. +#endif +.asciz "SHA1 block transform for ARMv8, CRYPTOGAMS by " +.align 2 +.comm OPENSSL_armcap_P,4,4 +___ +}}} + +{ my %opcode = ( + "sha1c" => 0x5e000000, "sha1p" => 0x5e001000, + "sha1m" => 0x5e002000, "sha1su0" => 0x5e003000, + "sha1h" => 0x5e280800, "sha1su1" => 0x5e281800 ); + + sub unsha1 { + my ($mnemonic,$arg)=@_; + + $arg =~ m/[qv]([0-9]+)[^,]*,\s*[qv]([0-9]+)[^,]*(?:,\s*[qv]([0-9]+))?/o + && + sprintf ".inst\t0x%08x\t//%s %s", + $opcode{$mnemonic}|$1|($2<<5)|($3<<16), + $mnemonic,$arg; + } +} + +foreach(split("\n",$code)) { + + s/\`([^\`]*)\`/eval($1)/geo; + + s/\b(sha1\w+)\s+([qv].*)/unsha1($1,$2)/geo; + + s/\.\w?32\b//o and s/\.16b/\.4s/go; + m/(ld|st)1[^\[]+\[0\]/o and s/\.4s/\.s/go; + + print $_,"\n"; +} + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-c64xplus.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-c64xplus.pl new file mode 100644 index 000000000..4db2bcb06 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-c64xplus.pl @@ -0,0 +1,337 @@ +#! /usr/bin/env perl +# Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# SHA1 for C64x+. +# +# November 2011 +# +# If compared to compiler-generated code with similar characteristics, +# i.e. compiled with OPENSSL_SMALL_FOOTPRINT and utilizing SPLOOPs, +# this implementation is 25% smaller and >2x faster. In absolute terms +# performance is (quite impressive) ~6.5 cycles per processed byte. +# Fully unrolled assembler would be ~5x larger and is likely to be +# ~15% faster. It would be free from references to intermediate ring +# buffer, but put more pressure on L1P [both because the code would be +# larger and won't be using SPLOOP buffer]. There are no plans to +# realize fully unrolled variant though... +# +# !!! Note that this module uses AMR, which means that all interrupt +# service routines are expected to preserve it and for own well-being +# zero it upon entry. + +while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} +open STDOUT,">$output"; + +($CTX,$INP,$NUM) = ("A4","B4","A6"); # arguments + +($A,$B,$C,$D,$E, $Arot,$F,$F0,$T,$K) = map("A$_",(16..20, 21..25)); +($X0,$X2,$X8,$X13) = ("A26","B26","A27","B27"); +($TX0,$TX1,$TX2,$TX3) = map("B$_",(28..31)); +($XPA,$XPB) = ("A5","B5"); # X circular buffer +($Actx,$Bctx,$Cctx,$Dctx,$Ectx) = map("A$_",(3,6..9)); # zaps $NUM + +$code=<<___; + .text + + .if .ASSEMBLER_VERSION<7000000 + .asg 0,__TI_EABI__ + .endif + .if __TI_EABI__ + .asg sha1_block_data_order,_sha1_block_data_order + .endif + + .asg B3,RA + .asg A15,FP + .asg B15,SP + + .if .BIG_ENDIAN + .asg MV,SWAP2 + .asg MV,SWAP4 + .endif + + .global _sha1_block_data_order +_sha1_block_data_order: + .asmfunc stack_usage(64) + MV $NUM,A0 ; reassign $NUM +|| MVK -64,B0 + [!A0] BNOP RA ; if ($NUM==0) return; +|| [A0] STW FP,*SP--[16] ; save frame pointer and alloca(64) +|| [A0] MV SP,FP + [A0] LDW *${CTX}[0],$A ; load A-E... +|| [A0] AND B0,SP,SP ; align stack at 64 bytes + [A0] LDW *${CTX}[1],$B +|| [A0] SUBAW SP,2,SP ; reserve two words above buffer + [A0] LDW *${CTX}[2],$C +|| [A0] MVK 0x00404,B0 + [A0] LDW *${CTX}[3],$D +|| [A0] MVKH 0x50000,B0 ; 0x050404, 64 bytes for $XP[AB] + [A0] LDW *${CTX}[4],$E +|| [A0] MVC B0,AMR ; setup circular addressing + LDNW *${INP}++,$TX1 ; pre-fetch input + NOP 1 + +loop?: + MVK 0x00007999,$K +|| ADDAW SP,2,$XPA +|| SUB A0,1,A0 +|| MVK 13,B0 + MVKH 0x5a820000,$K ; K_00_19 +|| ADDAW SP,2,$XPB +|| MV $A,$Actx +|| MV $B,$Bctx +;;================================================== + SPLOOPD 5 ; BODY_00_13 +|| MV $C,$Cctx +|| MV $D,$Dctx +|| MV $E,$Ectx +|| MVC B0,ILC + + ROTL $A,5,$Arot +|| AND $C,$B,$F +|| ANDN $D,$B,$F0 +|| ADD $K,$E,$T ; T=E+K + + XOR $F0,$F,$F ; F_00_19(B,C,D) +|| MV $D,$E ; E=D +|| MV $C,$D ; D=C +|| SWAP2 $TX1,$TX2 +|| LDNW *${INP}++,$TX1 + + ADD $F,$T,$T ; T+=F_00_19(B,C,D) +|| ROTL $B,30,$C ; C=ROL(B,30) +|| SWAP4 $TX2,$TX3 ; byte swap + + ADD $Arot,$T,$T ; T+=ROL(A,5) +|| MV $A,$B ; B=A + + ADD $TX3,$T,$A ; A=T+Xi +|| STW $TX3,*${XPB}++ + SPKERNEL +;;================================================== + ROTL $A,5,$Arot ; BODY_14 +|| AND $C,$B,$F +|| ANDN $D,$B,$F0 +|| ADD $K,$E,$T ; T=E+K + + XOR $F0,$F,$F ; F_00_19(B,C,D) +|| MV $D,$E ; E=D +|| MV $C,$D ; D=C +|| SWAP2 $TX1,$TX2 +|| LDNW *${INP}++,$TX1 + + ADD $F,$T,$T ; T+=F_00_19(B,C,D) +|| ROTL $B,30,$C ; C=ROL(B,30) +|| SWAP4 $TX2,$TX2 ; byte swap +|| LDW *${XPA}++,$X0 ; fetches from X ring buffer are +|| LDW *${XPB}[4],$X2 ; 2 iterations ahead + + ADD $Arot,$T,$T ; T+=ROL(A,5) +|| MV $A,$B ; B=A +|| LDW *${XPA}[7],$X8 +|| MV $TX3,$X13 ; || LDW *${XPB}[15],$X13 +|| MV $TX2,$TX3 + + ADD $TX2,$T,$A ; A=T+Xi +|| STW $TX2,*${XPB}++ +;;================================================== + ROTL $A,5,$Arot ; BODY_15 +|| AND $C,$B,$F +|| ANDN $D,$B,$F0 +|| ADD $K,$E,$T ; T=E+K + + XOR $F0,$F,$F ; F_00_19(B,C,D) +|| MV $D,$E ; E=D +|| MV $C,$D ; D=C +|| SWAP2 $TX1,$TX2 + + ADD $F,$T,$T ; T+=F_00_19(B,C,D) +|| ROTL $B,30,$C ; C=ROL(B,30) +|| SWAP4 $TX2,$TX2 ; byte swap +|| XOR $X0,$X2,$TX0 ; Xupdate XORs are 1 iteration ahead +|| LDW *${XPA}++,$X0 +|| LDW *${XPB}[4],$X2 + + ADD $Arot,$T,$T ; T+=ROL(A,5) +|| MV $A,$B ; B=A +|| XOR $X8,$X13,$TX1 +|| LDW *${XPA}[7],$X8 +|| MV $TX3,$X13 ; || LDW *${XPB}[15],$X13 +|| MV $TX2,$TX3 + + ADD $TX2,$T,$A ; A=T+Xi +|| STW $TX2,*${XPB}++ +|| XOR $TX0,$TX1,$TX1 +|| MVK 3,B0 +;;================================================== + SPLOOPD 5 ; BODY_16_19 +|| MVC B0,ILC + + ROTL $A,5,$Arot +|| AND $C,$B,$F +|| ANDN $D,$B,$F0 +|| ADD $K,$E,$T ; T=E+K +|| ROTL $TX1,1,$TX2 ; Xupdate output + + XOR $F0,$F,$F ; F_00_19(B,C,D) +|| MV $D,$E ; E=D +|| MV $C,$D ; D=C + + ADD $F,$T,$T ; T+=F_00_19(B,C,D) +|| ROTL $B,30,$C ; C=ROL(B,30) +|| XOR $X0,$X2,$TX0 +|| LDW *${XPA}++,$X0 +|| LDW *${XPB}[4],$X2 + + ADD $Arot,$T,$T ; T+=ROL(A,5) +|| MV $A,$B ; B=A +|| XOR $X8,$X13,$TX1 +|| LDW *${XPA}[7],$X8 +|| MV $TX3,$X13 ; || LDW *${XPB}[15],$X13 +|| MV $TX2,$TX3 + + ADD $TX2,$T,$A ; A=T+Xi +|| STW $TX2,*${XPB}++ +|| XOR $TX0,$TX1,$TX1 + SPKERNEL + + MVK 0xffffeba1,$K +|| MVK 19,B0 + MVKH 0x6ed90000,$K ; K_20_39 +___ +sub BODY_20_39 { +$code.=<<___; +;;================================================== + SPLOOPD 5 ; BODY_20_39 +|| MVC B0,ILC + + ROTL $A,5,$Arot +|| XOR $B,$C,$F +|| ADD $K,$E,$T ; T=E+K +|| ROTL $TX1,1,$TX2 ; Xupdate output + + XOR $D,$F,$F ; F_20_39(B,C,D) +|| MV $D,$E ; E=D +|| MV $C,$D ; D=C + + ADD $F,$T,$T ; T+=F_20_39(B,C,D) +|| ROTL $B,30,$C ; C=ROL(B,30) +|| XOR $X0,$X2,$TX0 +|| LDW *${XPA}++,$X0 +|| LDW *${XPB}[4],$X2 + + ADD $Arot,$T,$T ; T+=ROL(A,5) +|| MV $A,$B ; B=A +|| XOR $X8,$X13,$TX1 +|| LDW *${XPA}[7],$X8 +|| MV $TX3,$X13 ; || LDW *${XPB}[15],$X13 +|| MV $TX2,$TX3 + + ADD $TX2,$T,$A ; A=T+Xi +|| STW $TX2,*${XPB}++ ; last one is redundant +|| XOR $TX0,$TX1,$TX1 + SPKERNEL +___ +$code.=<<___ if (!shift); + MVK 0xffffbcdc,$K + MVKH 0x8f1b0000,$K ; K_40_59 +___ +} &BODY_20_39(); +$code.=<<___; +;;================================================== + SPLOOPD 5 ; BODY_40_59 +|| MVC B0,ILC +|| AND $B,$C,$F +|| AND $B,$D,$F0 + + ROTL $A,5,$Arot +|| XOR $F0,$F,$F +|| AND $C,$D,$F0 +|| ADD $K,$E,$T ; T=E+K +|| ROTL $TX1,1,$TX2 ; Xupdate output + + XOR $F0,$F,$F ; F_40_59(B,C,D) +|| MV $D,$E ; E=D +|| MV $C,$D ; D=C + + ADD $F,$T,$T ; T+=F_40_59(B,C,D) +|| ROTL $B,30,$C ; C=ROL(B,30) +|| XOR $X0,$X2,$TX0 +|| LDW *${XPA}++,$X0 +|| LDW *${XPB}[4],$X2 + + ADD $Arot,$T,$T ; T+=ROL(A,5) +|| MV $A,$B ; B=A +|| XOR $X8,$X13,$TX1 +|| LDW *${XPA}[7],$X8 +|| MV $TX3,$X13 ; || LDW *${XPB}[15],$X13 +|| MV $TX2,$TX3 + + ADD $TX2,$T,$A ; A=T+Xi +|| STW $TX2,*${XPB}++ +|| XOR $TX0,$TX1,$TX1 +|| AND $B,$C,$F +|| AND $B,$D,$F0 + SPKERNEL + + MVK 0xffffc1d6,$K +|| MVK 18,B0 + MVKH 0xca620000,$K ; K_60_79 +___ + &BODY_20_39(-1); # BODY_60_78 +$code.=<<___; +;;================================================== + [A0] B loop? +|| ROTL $A,5,$Arot ; BODY_79 +|| XOR $B,$C,$F +|| ROTL $TX1,1,$TX2 ; Xupdate output + + [A0] LDNW *${INP}++,$TX1 ; pre-fetch input +|| ADD $K,$E,$T ; T=E+K +|| XOR $D,$F,$F ; F_20_39(B,C,D) + + ADD $F,$T,$T ; T+=F_20_39(B,C,D) +|| ADD $Ectx,$D,$E ; E=D,E+=Ectx +|| ADD $Dctx,$C,$D ; D=C,D+=Dctx +|| ROTL $B,30,$C ; C=ROL(B,30) + + ADD $Arot,$T,$T ; T+=ROL(A,5) +|| ADD $Bctx,$A,$B ; B=A,B+=Bctx + + ADD $TX2,$T,$A ; A=T+Xi + + ADD $Actx,$A,$A ; A+=Actx +|| ADD $Cctx,$C,$C ; C+=Cctx +;; end of loop? + + BNOP RA ; return +|| MV FP,SP ; restore stack pointer +|| LDW *FP[0],FP ; restore frame pointer + STW $A,*${CTX}[0] ; emit A-E... +|| MVK 0,B0 + STW $B,*${CTX}[1] +|| MVC B0,AMR ; clear AMR + STW $C,*${CTX}[2] + STW $D,*${CTX}[3] + STW $E,*${CTX}[4] + .endasmfunc + + .sect .const + .cstring "SHA1 block transform for C64x+, CRYPTOGAMS by " + .align 4 +___ + +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-ia64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-ia64.pl new file mode 100644 index 000000000..bf1d2ebeb --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-ia64.pl @@ -0,0 +1,314 @@ +#! /usr/bin/env perl +# Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# Eternal question is what's wrong with compiler generated code? The +# trick is that it's possible to reduce the number of shifts required +# to perform rotations by maintaining copy of 32-bit value in upper +# bits of 64-bit register. Just follow mux2 and shrp instructions... +# Performance under big-endian OS such as HP-UX is 179MBps*1GHz, which +# is >50% better than HP C and >2x better than gcc. + +$output = pop; + +$code=<<___; +.ident \"sha1-ia64.s, version 1.3\" +.ident \"IA-64 ISA artwork by Andy Polyakov \" +.explicit + +___ + + +if ($^O eq "hpux") { + $ADDP="addp4"; + for (@ARGV) { $ADDP="add" if (/[\+DD|\-mlp]64/); } +} else { $ADDP="add"; } + +#$human=1; +if ($human) { # useful for visual code auditing... + ($A,$B,$C,$D,$E) = ("A","B","C","D","E"); + ($h0,$h1,$h2,$h3,$h4) = ("h0","h1","h2","h3","h4"); + ($K_00_19, $K_20_39, $K_40_59, $K_60_79) = + ( "K_00_19","K_20_39","K_40_59","K_60_79" ); + @X= ( "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", + "X8", "X9","X10","X11","X12","X13","X14","X15" ); +} +else { + ($A,$B,$C,$D,$E) = ("loc0","loc1","loc2","loc3","loc4"); + ($h0,$h1,$h2,$h3,$h4) = ("loc5","loc6","loc7","loc8","loc9"); + ($K_00_19, $K_20_39, $K_40_59, $K_60_79) = + ( "r14", "r15", "loc10", "loc11" ); + @X= ( "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31" ); +} + +sub BODY_00_15 { +local *code=shift; +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i+1; +my $Xn=@X[$j%16]; + +$code.=<<___ if ($i==0); +{ .mmi; ld1 $X[$i]=[inp],2 // MSB + ld1 tmp2=[tmp3],2 };; +{ .mmi; ld1 tmp0=[inp],2 + ld1 tmp4=[tmp3],2 // LSB + dep $X[$i]=$X[$i],tmp2,8,8 };; +___ +if ($i<15) { + $code.=<<___; +{ .mmi; ld1 $Xn=[inp],2 // forward Xload + nop.m 0x0 + dep tmp1=tmp0,tmp4,8,8 };; +{ .mmi; ld1 tmp2=[tmp3],2 // forward Xload + and tmp4=$c,$b + dep $X[$i]=$X[$i],tmp1,16,16} //;; +{ .mmi; add $e=$e,$K_00_19 // e+=K_00_19 + andcm tmp1=$d,$b + dep.z tmp5=$a,5,27 };; // a<<5 +{ .mmi; add $e=$e,$X[$i] // e+=Xload + or tmp4=tmp4,tmp1 // F_00_19(b,c,d)=(b&c)|(~b&d) + extr.u tmp1=$a,27,5 };; // a>>27 +{ .mmi; ld1 tmp0=[inp],2 // forward Xload + add $e=$e,tmp4 // e+=F_00_19(b,c,d) + shrp $b=tmp6,tmp6,2 } // b=ROTATE(b,30) +{ .mmi; ld1 tmp4=[tmp3],2 // forward Xload + or tmp5=tmp1,tmp5 // ROTATE(a,5) + mux2 tmp6=$a,0x44 };; // see b in next iteration +{ .mii; add $e=$e,tmp5 // e+=ROTATE(a,5) + dep $Xn=$Xn,tmp2,8,8 // forward Xload + mux2 $X[$i]=$X[$i],0x44 } //;; + +___ + } +else { + $code.=<<___; +{ .mii; and tmp3=$c,$b + dep tmp1=tmp0,tmp4,8,8;; + dep $X[$i]=$X[$i],tmp1,16,16} //;; +{ .mmi; add $e=$e,$K_00_19 // e+=K_00_19 + andcm tmp1=$d,$b + dep.z tmp5=$a,5,27 };; // a<<5 +{ .mmi; add $e=$e,$X[$i] // e+=Xupdate + or tmp4=tmp3,tmp1 // F_00_19(b,c,d)=(b&c)|(~b&d) + extr.u tmp1=$a,27,5 } // a>>27 +{ .mmi; xor $Xn=$Xn,$X[($j+2)%16] // forward Xupdate + xor tmp3=$X[($j+8)%16],$X[($j+13)%16] // forward Xupdate + nop.i 0 };; +{ .mmi; add $e=$e,tmp4 // e+=F_00_19(b,c,d) + xor $Xn=$Xn,tmp3 // forward Xupdate + shrp $b=tmp6,tmp6,2 } // b=ROTATE(b,30) +{ .mmi; or tmp1=tmp1,tmp5 // ROTATE(a,5) + mux2 tmp6=$a,0x44 };; // see b in next iteration +{ .mii; add $e=$e,tmp1 // e+=ROTATE(a,5) + shrp $Xn=$Xn,$Xn,31 // ROTATE(x[0]^x[2]^x[8]^x[13],1) + mux2 $X[$i]=$X[$i],0x44 };; + +___ + } +} + +sub BODY_16_19 { +local *code=shift; +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i+1; +my $Xn=@X[$j%16]; + +$code.=<<___; +{ .mib; add $e=$e,$K_00_19 // e+=K_00_19 + dep.z tmp5=$a,5,27 } // a<<5 +{ .mib; andcm tmp1=$d,$b + and tmp0=$c,$b };; +{ .mmi; add $e=$e,$X[$i%16] // e+=Xupdate + or tmp0=tmp0,tmp1 // F_00_19(b,c,d)=(b&c)|(~b&d) + extr.u tmp1=$a,27,5 } // a>>27 +{ .mmi; xor $Xn=$Xn,$X[($j+2)%16] // forward Xupdate + xor tmp3=$X[($j+8)%16],$X[($j+13)%16] // forward Xupdate + nop.i 0 };; +{ .mmi; add $e=$e,tmp0 // f+=F_00_19(b,c,d) + xor $Xn=$Xn,tmp3 // forward Xupdate + shrp $b=tmp6,tmp6,2 } // b=ROTATE(b,30) +{ .mmi; or tmp1=tmp1,tmp5 // ROTATE(a,5) + mux2 tmp6=$a,0x44 };; // see b in next iteration +{ .mii; add $e=$e,tmp1 // e+=ROTATE(a,5) + shrp $Xn=$Xn,$Xn,31 // ROTATE(x[0]^x[2]^x[8]^x[13],1) + nop.i 0 };; + +___ +} + +sub BODY_20_39 { +local *code=shift; +my ($i,$a,$b,$c,$d,$e,$Konst)=@_; + $Konst = $K_20_39 if (!defined($Konst)); +my $j=$i+1; +my $Xn=@X[$j%16]; + +if ($i<79) { +$code.=<<___; +{ .mib; add $e=$e,$Konst // e+=K_XX_XX + dep.z tmp5=$a,5,27 } // a<<5 +{ .mib; xor tmp0=$c,$b + xor $Xn=$Xn,$X[($j+2)%16] };; // forward Xupdate +{ .mib; add $e=$e,$X[$i%16] // e+=Xupdate + extr.u tmp1=$a,27,5 } // a>>27 +{ .mib; xor tmp0=tmp0,$d // F_20_39(b,c,d)=b^c^d + xor $Xn=$Xn,$X[($j+8)%16] };; // forward Xupdate +{ .mmi; add $e=$e,tmp0 // e+=F_20_39(b,c,d) + xor $Xn=$Xn,$X[($j+13)%16] // forward Xupdate + shrp $b=tmp6,tmp6,2 } // b=ROTATE(b,30) +{ .mmi; or tmp1=tmp1,tmp5 // ROTATE(a,5) + mux2 tmp6=$a,0x44 };; // see b in next iteration +{ .mii; add $e=$e,tmp1 // e+=ROTATE(a,5) + shrp $Xn=$Xn,$Xn,31 // ROTATE(x[0]^x[2]^x[8]^x[13],1) + nop.i 0 };; + +___ +} +else { +$code.=<<___; +{ .mib; add $e=$e,$Konst // e+=K_60_79 + dep.z tmp5=$a,5,27 } // a<<5 +{ .mib; xor tmp0=$c,$b + add $h1=$h1,$a };; // wrap up +{ .mib; add $e=$e,$X[$i%16] // e+=Xupdate + extr.u tmp1=$a,27,5 } // a>>27 +{ .mib; xor tmp0=tmp0,$d // F_20_39(b,c,d)=b^c^d + add $h3=$h3,$c };; // wrap up +{ .mmi; add $e=$e,tmp0 // e+=F_20_39(b,c,d) + or tmp1=tmp1,tmp5 // ROTATE(a,5) + shrp $b=tmp6,tmp6,2 };; // b=ROTATE(b,30) ;;? +{ .mmi; add $e=$e,tmp1 // e+=ROTATE(a,5) + add tmp3=1,inp // used in unaligned codepath + add $h4=$h4,$d };; // wrap up + +___ +} +} + +sub BODY_40_59 { +local *code=shift; +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i+1; +my $Xn=@X[$j%16]; + +$code.=<<___; +{ .mib; add $e=$e,$K_40_59 // e+=K_40_59 + dep.z tmp5=$a,5,27 } // a<<5 +{ .mib; and tmp1=$c,$d + xor tmp0=$c,$d };; +{ .mmi; add $e=$e,$X[$i%16] // e+=Xupdate + add tmp5=tmp5,tmp1 // a<<5+(c&d) + extr.u tmp1=$a,27,5 } // a>>27 +{ .mmi; and tmp0=tmp0,$b + xor $Xn=$Xn,$X[($j+2)%16] // forward Xupdate + xor tmp3=$X[($j+8)%16],$X[($j+13)%16] };; // forward Xupdate +{ .mmi; add $e=$e,tmp0 // e+=b&(c^d) + add tmp5=tmp5,tmp1 // ROTATE(a,5)+(c&d) + shrp $b=tmp6,tmp6,2 } // b=ROTATE(b,30) +{ .mmi; xor $Xn=$Xn,tmp3 + mux2 tmp6=$a,0x44 };; // see b in next iteration +{ .mii; add $e=$e,tmp5 // e+=ROTATE(a,5)+(c&d) + shrp $Xn=$Xn,$Xn,31 // ROTATE(x[0]^x[2]^x[8]^x[13],1) + nop.i 0x0 };; + +___ +} +sub BODY_60_79 { &BODY_20_39(@_,$K_60_79); } + +$code.=<<___; +.text + +tmp0=r8; +tmp1=r9; +tmp2=r10; +tmp3=r11; +ctx=r32; // in0 +inp=r33; // in1 + +// void sha1_block_data_order(SHA_CTX *c,const void *p,size_t num); +.global sha1_block_data_order# +.proc sha1_block_data_order# +.align 32 +sha1_block_data_order: + .prologue +{ .mmi; alloc tmp1=ar.pfs,3,14,0,0 + $ADDP tmp0=4,ctx + .save ar.lc,r3 + mov r3=ar.lc } +{ .mmi; $ADDP ctx=0,ctx + $ADDP inp=0,inp + mov r2=pr };; +tmp4=in2; +tmp5=loc12; +tmp6=loc13; + .body +{ .mlx; ld4 $h0=[ctx],8 + movl $K_00_19=0x5a827999 } +{ .mlx; ld4 $h1=[tmp0],8 + movl $K_20_39=0x6ed9eba1 };; +{ .mlx; ld4 $h2=[ctx],8 + movl $K_40_59=0x8f1bbcdc } +{ .mlx; ld4 $h3=[tmp0] + movl $K_60_79=0xca62c1d6 };; +{ .mmi; ld4 $h4=[ctx],-16 + add in2=-1,in2 // adjust num for ar.lc + mov ar.ec=1 };; +{ .mmi; nop.m 0 + add tmp3=1,inp + mov ar.lc=in2 };; // brp.loop.imp: too far + +.Ldtop: +{ .mmi; mov $A=$h0 + mov $B=$h1 + mux2 tmp6=$h1,0x44 } +{ .mmi; mov $C=$h2 + mov $D=$h3 + mov $E=$h4 };; + +___ + +{ my $i; + my @V=($A,$B,$C,$D,$E); + + for($i=0;$i<16;$i++) { &BODY_00_15(\$code,$i,@V); unshift(@V,pop(@V)); } + for(;$i<20;$i++) { &BODY_16_19(\$code,$i,@V); unshift(@V,pop(@V)); } + for(;$i<40;$i++) { &BODY_20_39(\$code,$i,@V); unshift(@V,pop(@V)); } + for(;$i<60;$i++) { &BODY_40_59(\$code,$i,@V); unshift(@V,pop(@V)); } + for(;$i<80;$i++) { &BODY_60_79(\$code,$i,@V); unshift(@V,pop(@V)); } + + (($V[0] eq $A) and ($V[4] eq $E)) or die; # double-check +} + +$code.=<<___; +{ .mmb; add $h0=$h0,$A + add $h2=$h2,$C + br.ctop.dptk.many .Ldtop };; +.Ldend: +{ .mmi; add tmp0=4,ctx + mov ar.lc=r3 };; +{ .mmi; st4 [ctx]=$h0,8 + st4 [tmp0]=$h1,8 };; +{ .mmi; st4 [ctx]=$h2,8 + st4 [tmp0]=$h3 };; +{ .mib; st4 [ctx]=$h4,-16 + mov pr=r2,0x1ffff + br.ret.sptk.many b0 };; +.endp sha1_block_data_order# +stringz "SHA1 block transform for IA64, CRYPTOGAMS by " +___ + +open STDOUT,">$output" if $output; +print $code; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-mb-x86_64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-mb-x86_64.pl new file mode 100644 index 000000000..443b64983 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-mb-x86_64.pl @@ -0,0 +1,1628 @@ +#! /usr/bin/env perl +# Copyright 2013-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# Multi-buffer SHA1 procedure processes n buffers in parallel by +# placing buffer data to designated lane of SIMD register. n is +# naturally limited to 4 on pre-AVX2 processors and to 8 on +# AVX2-capable processors such as Haswell. +# +# this +aesni(i) sha1 aesni-sha1 gain(iv) +# ------------------------------------------------------------------- +# Westmere(ii) 10.7/n +1.28=3.96(n=4) 5.30 6.66 +68% +# Atom(ii) 18.1/n +3.93=8.46(n=4) 9.37 12.8 +51% +# Sandy Bridge (8.16 +5.15=13.3)/n 4.99 5.98 +80% +# Ivy Bridge (8.08 +5.14=13.2)/n 4.60 5.54 +68% +# Haswell(iii) (8.96 +5.00=14.0)/n 3.57 4.55 +160% +# Skylake (8.70 +5.00=13.7)/n 3.64 4.20 +145% +# Bulldozer (9.76 +5.76=15.5)/n 5.95 6.37 +64% +# +# (i) multi-block CBC encrypt with 128-bit key; +# (ii) (HASH+AES)/n does not apply to Westmere for n>3 and Atom, +# because of lower AES-NI instruction throughput; +# (iii) "this" is for n=8, when we gather twice as much data, result +# for n=4 is 8.00+4.44=12.4; +# (iv) presented improvement coefficients are asymptotic limits and +# in real-life application are somewhat lower, e.g. for 2KB +# fragments they range from 30% to 100% (on Haswell); + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +$avx=0; + +if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler version ([2-9]\.[0-9]+)/) { + $avx = ($1>=2.19) + ($1>=2.22); +} + +if (!$avx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) && + `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) { + $avx = ($1>=2.09) + ($1>=2.10); +} + +if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && + `ml64 2>&1` =~ /Version ([0-9]+)\./) { + $avx = ($1>=10) + ($1>=11); +} + +if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9]\.[0-9]+)/) { + $avx = ($2>=3.0) + ($2>3.0); +} + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +*STDOUT=*OUT; + +# void sha1_multi_block ( +# struct { unsigned int A[8]; +# unsigned int B[8]; +# unsigned int C[8]; +# unsigned int D[8]; +# unsigned int E[8]; } *ctx, +# struct { void *ptr; int blocks; } inp[8], +# int num); /* 1 or 2 */ +# +$ctx="%rdi"; # 1st arg +$inp="%rsi"; # 2nd arg +$num="%edx"; +@ptr=map("%r$_",(8..11)); +$Tbl="%rbp"; + +@V=($A,$B,$C,$D,$E)=map("%xmm$_",(0..4)); +($t0,$t1,$t2,$t3,$tx)=map("%xmm$_",(5..9)); +@Xi=map("%xmm$_",(10..14)); +$K="%xmm15"; + +if (1) { + # Atom-specific optimization aiming to eliminate pshufb with high + # registers [and thus get rid of 48 cycles accumulated penalty] + @Xi=map("%xmm$_",(0..4)); + ($tx,$t0,$t1,$t2,$t3)=map("%xmm$_",(5..9)); + @V=($A,$B,$C,$D,$E)=map("%xmm$_",(10..14)); +} + +$REG_SZ=16; + +sub Xi_off { +my $off = shift; + + $off %= 16; $off *= $REG_SZ; + $off<256 ? "$off-128(%rax)" : "$off-256-128(%rbx)"; +} + +sub BODY_00_19 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i+1; +my $k=$i+2; + +# Loads are performed 2+3/4 iterations in advance. 3/4 means that out +# of 4 words you would expect to be loaded per given iteration one is +# spilled to next iteration. In other words indices in four input +# streams are distributed as following: +# +# $i==0: 0,0,0,0,1,1,1,1,2,2,2, +# $i==1: 2,3,3,3, +# $i==2: 3,4,4,4, +# ... +# $i==13: 14,15,15,15, +# $i==14: 15 +# +# Then at $i==15 Xupdate is applied one iteration in advance... +$code.=<<___ if ($i==0); + movd (@ptr[0]),@Xi[0] + lea `16*4`(@ptr[0]),@ptr[0] + movd (@ptr[1]),@Xi[2] # borrow @Xi[2] + lea `16*4`(@ptr[1]),@ptr[1] + movd (@ptr[2]),@Xi[3] # borrow @Xi[3] + lea `16*4`(@ptr[2]),@ptr[2] + movd (@ptr[3]),@Xi[4] # borrow @Xi[4] + lea `16*4`(@ptr[3]),@ptr[3] + punpckldq @Xi[3],@Xi[0] + movd `4*$j-16*4`(@ptr[0]),@Xi[1] + punpckldq @Xi[4],@Xi[2] + movd `4*$j-16*4`(@ptr[1]),$t3 + punpckldq @Xi[2],@Xi[0] + movd `4*$j-16*4`(@ptr[2]),$t2 + pshufb $tx,@Xi[0] +___ +$code.=<<___ if ($i<14); # just load input + movd `4*$j-16*4`(@ptr[3]),$t1 + punpckldq $t2,@Xi[1] + movdqa $a,$t2 + paddd $K,$e # e+=K_00_19 + punpckldq $t1,$t3 + movdqa $b,$t1 + movdqa $b,$t0 + pslld \$5,$t2 + pandn $d,$t1 + pand $c,$t0 + punpckldq $t3,@Xi[1] + movdqa $a,$t3 + + movdqa @Xi[0],`&Xi_off($i)` + paddd @Xi[0],$e # e+=X[i] + movd `4*$k-16*4`(@ptr[0]),@Xi[2] + psrld \$27,$t3 + pxor $t1,$t0 # Ch(b,c,d) + movdqa $b,$t1 + + por $t3,$t2 # rol(a,5) + movd `4*$k-16*4`(@ptr[1]),$t3 + pslld \$30,$t1 + paddd $t0,$e # e+=Ch(b,c,d) + + psrld \$2,$b + paddd $t2,$e # e+=rol(a,5) + pshufb $tx,@Xi[1] + movd `4*$k-16*4`(@ptr[2]),$t2 + por $t1,$b # b=rol(b,30) +___ +$code.=<<___ if ($i==14); # just load input + movd `4*$j-16*4`(@ptr[3]),$t1 + punpckldq $t2,@Xi[1] + movdqa $a,$t2 + paddd $K,$e # e+=K_00_19 + punpckldq $t1,$t3 + movdqa $b,$t1 + movdqa $b,$t0 + pslld \$5,$t2 + prefetcht0 63(@ptr[0]) + pandn $d,$t1 + pand $c,$t0 + punpckldq $t3,@Xi[1] + movdqa $a,$t3 + + movdqa @Xi[0],`&Xi_off($i)` + paddd @Xi[0],$e # e+=X[i] + psrld \$27,$t3 + pxor $t1,$t0 # Ch(b,c,d) + movdqa $b,$t1 + prefetcht0 63(@ptr[1]) + + por $t3,$t2 # rol(a,5) + pslld \$30,$t1 + paddd $t0,$e # e+=Ch(b,c,d) + prefetcht0 63(@ptr[2]) + + psrld \$2,$b + paddd $t2,$e # e+=rol(a,5) + pshufb $tx,@Xi[1] + prefetcht0 63(@ptr[3]) + por $t1,$b # b=rol(b,30) +___ +$code.=<<___ if ($i>=13 && $i<15); + movdqa `&Xi_off($j+2)`,@Xi[3] # preload "X[2]" +___ +$code.=<<___ if ($i>=15); # apply Xupdate + pxor @Xi[-2],@Xi[1] # "X[13]" + movdqa `&Xi_off($j+2)`,@Xi[3] # "X[2]" + + movdqa $a,$t2 + pxor `&Xi_off($j+8)`,@Xi[1] + paddd $K,$e # e+=K_00_19 + movdqa $b,$t1 + pslld \$5,$t2 + pxor @Xi[3],@Xi[1] + movdqa $b,$t0 + pandn $d,$t1 + movdqa @Xi[1],$tx + pand $c,$t0 + movdqa $a,$t3 + psrld \$31,$tx + paddd @Xi[1],@Xi[1] + + movdqa @Xi[0],`&Xi_off($i)` + paddd @Xi[0],$e # e+=X[i] + psrld \$27,$t3 + pxor $t1,$t0 # Ch(b,c,d) + + movdqa $b,$t1 + por $t3,$t2 # rol(a,5) + pslld \$30,$t1 + paddd $t0,$e # e+=Ch(b,c,d) + + psrld \$2,$b + paddd $t2,$e # e+=rol(a,5) + por $tx,@Xi[1] # rol \$1,@Xi[1] + por $t1,$b # b=rol(b,30) +___ +push(@Xi,shift(@Xi)); +} + +sub BODY_20_39 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i+1; + +$code.=<<___ if ($i<79); + pxor @Xi[-2],@Xi[1] # "X[13]" + movdqa `&Xi_off($j+2)`,@Xi[3] # "X[2]" + + movdqa $a,$t2 + movdqa $d,$t0 + pxor `&Xi_off($j+8)`,@Xi[1] + paddd $K,$e # e+=K_20_39 + pslld \$5,$t2 + pxor $b,$t0 + + movdqa $a,$t3 +___ +$code.=<<___ if ($i<72); + movdqa @Xi[0],`&Xi_off($i)` +___ +$code.=<<___ if ($i<79); + paddd @Xi[0],$e # e+=X[i] + pxor @Xi[3],@Xi[1] + psrld \$27,$t3 + pxor $c,$t0 # Parity(b,c,d) + movdqa $b,$t1 + + pslld \$30,$t1 + movdqa @Xi[1],$tx + por $t3,$t2 # rol(a,5) + psrld \$31,$tx + paddd $t0,$e # e+=Parity(b,c,d) + paddd @Xi[1],@Xi[1] + + psrld \$2,$b + paddd $t2,$e # e+=rol(a,5) + por $tx,@Xi[1] # rol(@Xi[1],1) + por $t1,$b # b=rol(b,30) +___ +$code.=<<___ if ($i==79); + movdqa $a,$t2 + paddd $K,$e # e+=K_20_39 + movdqa $d,$t0 + pslld \$5,$t2 + pxor $b,$t0 + + movdqa $a,$t3 + paddd @Xi[0],$e # e+=X[i] + psrld \$27,$t3 + movdqa $b,$t1 + pxor $c,$t0 # Parity(b,c,d) + + pslld \$30,$t1 + por $t3,$t2 # rol(a,5) + paddd $t0,$e # e+=Parity(b,c,d) + + psrld \$2,$b + paddd $t2,$e # e+=rol(a,5) + por $t1,$b # b=rol(b,30) +___ +push(@Xi,shift(@Xi)); +} + +sub BODY_40_59 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i+1; + +$code.=<<___; + pxor @Xi[-2],@Xi[1] # "X[13]" + movdqa `&Xi_off($j+2)`,@Xi[3] # "X[2]" + + movdqa $a,$t2 + movdqa $d,$t1 + pxor `&Xi_off($j+8)`,@Xi[1] + pxor @Xi[3],@Xi[1] + paddd $K,$e # e+=K_40_59 + pslld \$5,$t2 + movdqa $a,$t3 + pand $c,$t1 + + movdqa $d,$t0 + movdqa @Xi[1],$tx + psrld \$27,$t3 + paddd $t1,$e + pxor $c,$t0 + + movdqa @Xi[0],`&Xi_off($i)` + paddd @Xi[0],$e # e+=X[i] + por $t3,$t2 # rol(a,5) + psrld \$31,$tx + pand $b,$t0 + movdqa $b,$t1 + + pslld \$30,$t1 + paddd @Xi[1],@Xi[1] + paddd $t0,$e # e+=Maj(b,d,c) + + psrld \$2,$b + paddd $t2,$e # e+=rol(a,5) + por $tx,@Xi[1] # rol(@X[1],1) + por $t1,$b # b=rol(b,30) +___ +push(@Xi,shift(@Xi)); +} + +$code.=<<___; +.text + +.extern OPENSSL_ia32cap_P + +.globl sha1_multi_block +.type sha1_multi_block,\@function,3 +.align 32 +sha1_multi_block: +.cfi_startproc + mov OPENSSL_ia32cap_P+4(%rip),%rcx + bt \$61,%rcx # check SHA bit + jc _shaext_shortcut +___ +$code.=<<___ if ($avx); + test \$`1<<28`,%ecx + jnz _avx_shortcut +___ +$code.=<<___; + mov %rsp,%rax +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbx +___ +$code.=<<___ if ($win64); + lea -0xa8(%rsp),%rsp + movaps %xmm6,(%rsp) + movaps %xmm7,0x10(%rsp) + movaps %xmm8,0x20(%rsp) + movaps %xmm9,0x30(%rsp) + movaps %xmm10,-0x78(%rax) + movaps %xmm11,-0x68(%rax) + movaps %xmm12,-0x58(%rax) + movaps %xmm13,-0x48(%rax) + movaps %xmm14,-0x38(%rax) + movaps %xmm15,-0x28(%rax) +___ +$code.=<<___; + sub \$`$REG_SZ*18`,%rsp + and \$-256,%rsp + mov %rax,`$REG_SZ*17`(%rsp) # original %rsp +.cfi_cfa_expression %rsp+`$REG_SZ*17`,deref,+8 +.Lbody: + lea K_XX_XX(%rip),$Tbl + lea `$REG_SZ*16`(%rsp),%rbx + +.Loop_grande: + mov $num,`$REG_SZ*17+8`(%rsp) # original $num + xor $num,$num +___ +for($i=0;$i<4;$i++) { + $code.=<<___; + mov `16*$i+0`($inp),@ptr[$i] # input pointer + mov `16*$i+8`($inp),%ecx # number of blocks + cmp $num,%ecx + cmovg %ecx,$num # find maximum + test %ecx,%ecx + mov %ecx,`4*$i`(%rbx) # initialize counters + cmovle $Tbl,@ptr[$i] # cancel input +___ +} +$code.=<<___; + test $num,$num + jz .Ldone + + movdqu 0x00($ctx),$A # load context + lea 128(%rsp),%rax + movdqu 0x20($ctx),$B + movdqu 0x40($ctx),$C + movdqu 0x60($ctx),$D + movdqu 0x80($ctx),$E + movdqa 0x60($Tbl),$tx # pbswap_mask + movdqa -0x20($Tbl),$K # K_00_19 + jmp .Loop + +.align 32 +.Loop: +___ +for($i=0;$i<20;$i++) { &BODY_00_19($i,@V); unshift(@V,pop(@V)); } +$code.=" movdqa 0x00($Tbl),$K\n"; # K_20_39 +for(;$i<40;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); } +$code.=" movdqa 0x20($Tbl),$K\n"; # K_40_59 +for(;$i<60;$i++) { &BODY_40_59($i,@V); unshift(@V,pop(@V)); } +$code.=" movdqa 0x40($Tbl),$K\n"; # K_60_79 +for(;$i<80;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + movdqa (%rbx),@Xi[0] # pull counters + mov \$1,%ecx + cmp 4*0(%rbx),%ecx # examine counters + pxor $t2,$t2 + cmovge $Tbl,@ptr[0] # cancel input + cmp 4*1(%rbx),%ecx + movdqa @Xi[0],@Xi[1] + cmovge $Tbl,@ptr[1] + cmp 4*2(%rbx),%ecx + pcmpgtd $t2,@Xi[1] # mask value + cmovge $Tbl,@ptr[2] + cmp 4*3(%rbx),%ecx + paddd @Xi[1],@Xi[0] # counters-- + cmovge $Tbl,@ptr[3] + + movdqu 0x00($ctx),$t0 + pand @Xi[1],$A + movdqu 0x20($ctx),$t1 + pand @Xi[1],$B + paddd $t0,$A + movdqu 0x40($ctx),$t2 + pand @Xi[1],$C + paddd $t1,$B + movdqu 0x60($ctx),$t3 + pand @Xi[1],$D + paddd $t2,$C + movdqu 0x80($ctx),$tx + pand @Xi[1],$E + movdqu $A,0x00($ctx) + paddd $t3,$D + movdqu $B,0x20($ctx) + paddd $tx,$E + movdqu $C,0x40($ctx) + movdqu $D,0x60($ctx) + movdqu $E,0x80($ctx) + + movdqa @Xi[0],(%rbx) # save counters + movdqa 0x60($Tbl),$tx # pbswap_mask + movdqa -0x20($Tbl),$K # K_00_19 + dec $num + jnz .Loop + + mov `$REG_SZ*17+8`(%rsp),$num + lea $REG_SZ($ctx),$ctx + lea `16*$REG_SZ/4`($inp),$inp + dec $num + jnz .Loop_grande + +.Ldone: + mov `$REG_SZ*17`(%rsp),%rax # original %rsp +.cfi_def_cfa %rax,8 +___ +$code.=<<___ if ($win64); + movaps -0xb8(%rax),%xmm6 + movaps -0xa8(%rax),%xmm7 + movaps -0x98(%rax),%xmm8 + movaps -0x88(%rax),%xmm9 + movaps -0x78(%rax),%xmm10 + movaps -0x68(%rax),%xmm11 + movaps -0x58(%rax),%xmm12 + movaps -0x48(%rax),%xmm13 + movaps -0x38(%rax),%xmm14 + movaps -0x28(%rax),%xmm15 +___ +$code.=<<___; + mov -16(%rax),%rbp +.cfi_restore %rbp + mov -8(%rax),%rbx +.cfi_restore %rbx + lea (%rax),%rsp +.cfi_def_cfa_register %rsp +.Lepilogue: + ret +.cfi_endproc +.size sha1_multi_block,.-sha1_multi_block +___ + {{{ +my ($ABCD0,$E0,$E0_,$BSWAP,$ABCD1,$E1,$E1_)=map("%xmm$_",(0..3,8..10)); +my @MSG0=map("%xmm$_",(4..7)); +my @MSG1=map("%xmm$_",(11..14)); + +$code.=<<___; +.type sha1_multi_block_shaext,\@function,3 +.align 32 +sha1_multi_block_shaext: +.cfi_startproc +_shaext_shortcut: + mov %rsp,%rax +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp +___ +$code.=<<___ if ($win64); + lea -0xa8(%rsp),%rsp + movaps %xmm6,(%rsp) + movaps %xmm7,0x10(%rsp) + movaps %xmm8,0x20(%rsp) + movaps %xmm9,0x30(%rsp) + movaps %xmm10,-0x78(%rax) + movaps %xmm11,-0x68(%rax) + movaps %xmm12,-0x58(%rax) + movaps %xmm13,-0x48(%rax) + movaps %xmm14,-0x38(%rax) + movaps %xmm15,-0x28(%rax) +___ +$code.=<<___; + sub \$`$REG_SZ*18`,%rsp + shl \$1,$num # we process pair at a time + and \$-256,%rsp + lea 0x40($ctx),$ctx # size optimization + mov %rax,`$REG_SZ*17`(%rsp) # original %rsp +.Lbody_shaext: + lea `$REG_SZ*16`(%rsp),%rbx + movdqa K_XX_XX+0x80(%rip),$BSWAP # byte-n-word swap + +.Loop_grande_shaext: + mov $num,`$REG_SZ*17+8`(%rsp) # original $num + xor $num,$num +___ +for($i=0;$i<2;$i++) { + $code.=<<___; + mov `16*$i+0`($inp),@ptr[$i] # input pointer + mov `16*$i+8`($inp),%ecx # number of blocks + cmp $num,%ecx + cmovg %ecx,$num # find maximum + test %ecx,%ecx + mov %ecx,`4*$i`(%rbx) # initialize counters + cmovle %rsp,@ptr[$i] # cancel input +___ +} +$code.=<<___; + test $num,$num + jz .Ldone_shaext + + movq 0x00-0x40($ctx),$ABCD0 # a1.a0 + movq 0x20-0x40($ctx),@MSG0[0]# b1.b0 + movq 0x40-0x40($ctx),@MSG0[1]# c1.c0 + movq 0x60-0x40($ctx),@MSG0[2]# d1.d0 + movq 0x80-0x40($ctx),@MSG0[3]# e1.e0 + + punpckldq @MSG0[0],$ABCD0 # b1.a1.b0.a0 + punpckldq @MSG0[2],@MSG0[1] # d1.c1.d0.c0 + + movdqa $ABCD0,$ABCD1 + punpcklqdq @MSG0[1],$ABCD0 # d0.c0.b0.a0 + punpckhqdq @MSG0[1],$ABCD1 # d1.c1.b1.a1 + + pshufd \$0b00111111,@MSG0[3],$E0 + pshufd \$0b01111111,@MSG0[3],$E1 + pshufd \$0b00011011,$ABCD0,$ABCD0 + pshufd \$0b00011011,$ABCD1,$ABCD1 + jmp .Loop_shaext + +.align 32 +.Loop_shaext: + movdqu 0x00(@ptr[0]),@MSG0[0] + movdqu 0x00(@ptr[1]),@MSG1[0] + movdqu 0x10(@ptr[0]),@MSG0[1] + movdqu 0x10(@ptr[1]),@MSG1[1] + movdqu 0x20(@ptr[0]),@MSG0[2] + pshufb $BSWAP,@MSG0[0] + movdqu 0x20(@ptr[1]),@MSG1[2] + pshufb $BSWAP,@MSG1[0] + movdqu 0x30(@ptr[0]),@MSG0[3] + lea 0x40(@ptr[0]),@ptr[0] + pshufb $BSWAP,@MSG0[1] + movdqu 0x30(@ptr[1]),@MSG1[3] + lea 0x40(@ptr[1]),@ptr[1] + pshufb $BSWAP,@MSG1[1] + + movdqa $E0,0x50(%rsp) # offload + paddd @MSG0[0],$E0 + movdqa $E1,0x70(%rsp) + paddd @MSG1[0],$E1 + movdqa $ABCD0,0x40(%rsp) # offload + movdqa $ABCD0,$E0_ + movdqa $ABCD1,0x60(%rsp) + movdqa $ABCD1,$E1_ + sha1rnds4 \$0,$E0,$ABCD0 # 0-3 + sha1nexte @MSG0[1],$E0_ + sha1rnds4 \$0,$E1,$ABCD1 # 0-3 + sha1nexte @MSG1[1],$E1_ + pshufb $BSWAP,@MSG0[2] + prefetcht0 127(@ptr[0]) + sha1msg1 @MSG0[1],@MSG0[0] + pshufb $BSWAP,@MSG1[2] + prefetcht0 127(@ptr[1]) + sha1msg1 @MSG1[1],@MSG1[0] + + pshufb $BSWAP,@MSG0[3] + movdqa $ABCD0,$E0 + pshufb $BSWAP,@MSG1[3] + movdqa $ABCD1,$E1 + sha1rnds4 \$0,$E0_,$ABCD0 # 4-7 + sha1nexte @MSG0[2],$E0 + sha1rnds4 \$0,$E1_,$ABCD1 # 4-7 + sha1nexte @MSG1[2],$E1 + pxor @MSG0[2],@MSG0[0] + sha1msg1 @MSG0[2],@MSG0[1] + pxor @MSG1[2],@MSG1[0] + sha1msg1 @MSG1[2],@MSG1[1] +___ +for($i=2;$i<20-4;$i++) { +$code.=<<___; + movdqa $ABCD0,$E0_ + movdqa $ABCD1,$E1_ + sha1rnds4 \$`int($i/5)`,$E0,$ABCD0 # 8-11 + sha1nexte @MSG0[3],$E0_ + sha1rnds4 \$`int($i/5)`,$E1,$ABCD1 # 8-11 + sha1nexte @MSG1[3],$E1_ + sha1msg2 @MSG0[3],@MSG0[0] + sha1msg2 @MSG1[3],@MSG1[0] + pxor @MSG0[3],@MSG0[1] + sha1msg1 @MSG0[3],@MSG0[2] + pxor @MSG1[3],@MSG1[1] + sha1msg1 @MSG1[3],@MSG1[2] +___ + ($E0,$E0_)=($E0_,$E0); ($E1,$E1_)=($E1_,$E1); + push(@MSG0,shift(@MSG0)); push(@MSG1,shift(@MSG1)); +} +$code.=<<___; + movdqa $ABCD0,$E0_ + movdqa $ABCD1,$E1_ + sha1rnds4 \$3,$E0,$ABCD0 # 64-67 + sha1nexte @MSG0[3],$E0_ + sha1rnds4 \$3,$E1,$ABCD1 # 64-67 + sha1nexte @MSG1[3],$E1_ + sha1msg2 @MSG0[3],@MSG0[0] + sha1msg2 @MSG1[3],@MSG1[0] + pxor @MSG0[3],@MSG0[1] + pxor @MSG1[3],@MSG1[1] + + mov \$1,%ecx + pxor @MSG0[2],@MSG0[2] # zero + cmp 4*0(%rbx),%ecx # examine counters + cmovge %rsp,@ptr[0] # cancel input + + movdqa $ABCD0,$E0 + movdqa $ABCD1,$E1 + sha1rnds4 \$3,$E0_,$ABCD0 # 68-71 + sha1nexte @MSG0[0],$E0 + sha1rnds4 \$3,$E1_,$ABCD1 # 68-71 + sha1nexte @MSG1[0],$E1 + sha1msg2 @MSG0[0],@MSG0[1] + sha1msg2 @MSG1[0],@MSG1[1] + + cmp 4*1(%rbx),%ecx + cmovge %rsp,@ptr[1] + movq (%rbx),@MSG0[0] # pull counters + + movdqa $ABCD0,$E0_ + movdqa $ABCD1,$E1_ + sha1rnds4 \$3,$E0,$ABCD0 # 72-75 + sha1nexte @MSG0[1],$E0_ + sha1rnds4 \$3,$E1,$ABCD1 # 72-75 + sha1nexte @MSG1[1],$E1_ + + pshufd \$0x00,@MSG0[0],@MSG1[2] + pshufd \$0x55,@MSG0[0],@MSG1[3] + movdqa @MSG0[0],@MSG0[1] + pcmpgtd @MSG0[2],@MSG1[2] + pcmpgtd @MSG0[2],@MSG1[3] + + movdqa $ABCD0,$E0 + movdqa $ABCD1,$E1 + sha1rnds4 \$3,$E0_,$ABCD0 # 76-79 + sha1nexte $MSG0[2],$E0 + sha1rnds4 \$3,$E1_,$ABCD1 # 76-79 + sha1nexte $MSG0[2],$E1 + + pcmpgtd @MSG0[2],@MSG0[1] # counter mask + pand @MSG1[2],$ABCD0 + pand @MSG1[2],$E0 + pand @MSG1[3],$ABCD1 + pand @MSG1[3],$E1 + paddd @MSG0[1],@MSG0[0] # counters-- + + paddd 0x40(%rsp),$ABCD0 + paddd 0x50(%rsp),$E0 + paddd 0x60(%rsp),$ABCD1 + paddd 0x70(%rsp),$E1 + + movq @MSG0[0],(%rbx) # save counters + dec $num + jnz .Loop_shaext + + mov `$REG_SZ*17+8`(%rsp),$num + + pshufd \$0b00011011,$ABCD0,$ABCD0 + pshufd \$0b00011011,$ABCD1,$ABCD1 + + movdqa $ABCD0,@MSG0[0] + punpckldq $ABCD1,$ABCD0 # b1.b0.a1.a0 + punpckhdq $ABCD1,@MSG0[0] # d1.d0.c1.c0 + punpckhdq $E1,$E0 # e1.e0.xx.xx + movq $ABCD0,0x00-0x40($ctx) # a1.a0 + psrldq \$8,$ABCD0 + movq @MSG0[0],0x40-0x40($ctx)# c1.c0 + psrldq \$8,@MSG0[0] + movq $ABCD0,0x20-0x40($ctx) # b1.b0 + psrldq \$8,$E0 + movq @MSG0[0],0x60-0x40($ctx)# d1.d0 + movq $E0,0x80-0x40($ctx) # e1.e0 + + lea `$REG_SZ/2`($ctx),$ctx + lea `16*2`($inp),$inp + dec $num + jnz .Loop_grande_shaext + +.Ldone_shaext: + #mov `$REG_SZ*17`(%rsp),%rax # original %rsp +___ +$code.=<<___ if ($win64); + movaps -0xb8(%rax),%xmm6 + movaps -0xa8(%rax),%xmm7 + movaps -0x98(%rax),%xmm8 + movaps -0x88(%rax),%xmm9 + movaps -0x78(%rax),%xmm10 + movaps -0x68(%rax),%xmm11 + movaps -0x58(%rax),%xmm12 + movaps -0x48(%rax),%xmm13 + movaps -0x38(%rax),%xmm14 + movaps -0x28(%rax),%xmm15 +___ +$code.=<<___; + mov -16(%rax),%rbp +.cfi_restore %rbp + mov -8(%rax),%rbx +.cfi_restore %rbx + lea (%rax),%rsp +.cfi_def_cfa_register %rsp +.Lepilogue_shaext: + ret +.cfi_endproc +.size sha1_multi_block_shaext,.-sha1_multi_block_shaext +___ + }}} + + if ($avx) {{{ +sub BODY_00_19_avx { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i+1; +my $k=$i+2; +my $vpack = $REG_SZ==16 ? "vpunpckldq" : "vinserti128"; +my $ptr_n = $REG_SZ==16 ? @ptr[1] : @ptr[4]; + +$code.=<<___ if ($i==0 && $REG_SZ==16); + vmovd (@ptr[0]),@Xi[0] + lea `16*4`(@ptr[0]),@ptr[0] + vmovd (@ptr[1]),@Xi[2] # borrow Xi[2] + lea `16*4`(@ptr[1]),@ptr[1] + vpinsrd \$1,(@ptr[2]),@Xi[0],@Xi[0] + lea `16*4`(@ptr[2]),@ptr[2] + vpinsrd \$1,(@ptr[3]),@Xi[2],@Xi[2] + lea `16*4`(@ptr[3]),@ptr[3] + vmovd `4*$j-16*4`(@ptr[0]),@Xi[1] + vpunpckldq @Xi[2],@Xi[0],@Xi[0] + vmovd `4*$j-16*4`($ptr_n),$t3 + vpshufb $tx,@Xi[0],@Xi[0] +___ +$code.=<<___ if ($i<15 && $REG_SZ==16); # just load input + vpinsrd \$1,`4*$j-16*4`(@ptr[2]),@Xi[1],@Xi[1] + vpinsrd \$1,`4*$j-16*4`(@ptr[3]),$t3,$t3 +___ +$code.=<<___ if ($i==0 && $REG_SZ==32); + vmovd (@ptr[0]),@Xi[0] + lea `16*4`(@ptr[0]),@ptr[0] + vmovd (@ptr[4]),@Xi[2] # borrow Xi[2] + lea `16*4`(@ptr[4]),@ptr[4] + vmovd (@ptr[1]),$t2 + lea `16*4`(@ptr[1]),@ptr[1] + vmovd (@ptr[5]),$t1 + lea `16*4`(@ptr[5]),@ptr[5] + vpinsrd \$1,(@ptr[2]),@Xi[0],@Xi[0] + lea `16*4`(@ptr[2]),@ptr[2] + vpinsrd \$1,(@ptr[6]),@Xi[2],@Xi[2] + lea `16*4`(@ptr[6]),@ptr[6] + vpinsrd \$1,(@ptr[3]),$t2,$t2 + lea `16*4`(@ptr[3]),@ptr[3] + vpunpckldq $t2,@Xi[0],@Xi[0] + vpinsrd \$1,(@ptr[7]),$t1,$t1 + lea `16*4`(@ptr[7]),@ptr[7] + vpunpckldq $t1,@Xi[2],@Xi[2] + vmovd `4*$j-16*4`(@ptr[0]),@Xi[1] + vinserti128 @Xi[2],@Xi[0],@Xi[0] + vmovd `4*$j-16*4`($ptr_n),$t3 + vpshufb $tx,@Xi[0],@Xi[0] +___ +$code.=<<___ if ($i<15 && $REG_SZ==32); # just load input + vmovd `4*$j-16*4`(@ptr[1]),$t2 + vmovd `4*$j-16*4`(@ptr[5]),$t1 + vpinsrd \$1,`4*$j-16*4`(@ptr[2]),@Xi[1],@Xi[1] + vpinsrd \$1,`4*$j-16*4`(@ptr[6]),$t3,$t3 + vpinsrd \$1,`4*$j-16*4`(@ptr[3]),$t2,$t2 + vpunpckldq $t2,@Xi[1],@Xi[1] + vpinsrd \$1,`4*$j-16*4`(@ptr[7]),$t1,$t1 + vpunpckldq $t1,$t3,$t3 +___ +$code.=<<___ if ($i<14); + vpaddd $K,$e,$e # e+=K_00_19 + vpslld \$5,$a,$t2 + vpandn $d,$b,$t1 + vpand $c,$b,$t0 + + vmovdqa @Xi[0],`&Xi_off($i)` + vpaddd @Xi[0],$e,$e # e+=X[i] + $vpack $t3,@Xi[1],@Xi[1] + vpsrld \$27,$a,$t3 + vpxor $t1,$t0,$t0 # Ch(b,c,d) + vmovd `4*$k-16*4`(@ptr[0]),@Xi[2] + + vpslld \$30,$b,$t1 + vpor $t3,$t2,$t2 # rol(a,5) + vmovd `4*$k-16*4`($ptr_n),$t3 + vpaddd $t0,$e,$e # e+=Ch(b,c,d) + + vpsrld \$2,$b,$b + vpaddd $t2,$e,$e # e+=rol(a,5) + vpshufb $tx,@Xi[1],@Xi[1] + vpor $t1,$b,$b # b=rol(b,30) +___ +$code.=<<___ if ($i==14); + vpaddd $K,$e,$e # e+=K_00_19 + prefetcht0 63(@ptr[0]) + vpslld \$5,$a,$t2 + vpandn $d,$b,$t1 + vpand $c,$b,$t0 + + vmovdqa @Xi[0],`&Xi_off($i)` + vpaddd @Xi[0],$e,$e # e+=X[i] + $vpack $t3,@Xi[1],@Xi[1] + vpsrld \$27,$a,$t3 + prefetcht0 63(@ptr[1]) + vpxor $t1,$t0,$t0 # Ch(b,c,d) + + vpslld \$30,$b,$t1 + vpor $t3,$t2,$t2 # rol(a,5) + prefetcht0 63(@ptr[2]) + vpaddd $t0,$e,$e # e+=Ch(b,c,d) + + vpsrld \$2,$b,$b + vpaddd $t2,$e,$e # e+=rol(a,5) + prefetcht0 63(@ptr[3]) + vpshufb $tx,@Xi[1],@Xi[1] + vpor $t1,$b,$b # b=rol(b,30) +___ +$code.=<<___ if ($i>=13 && $i<15); + vmovdqa `&Xi_off($j+2)`,@Xi[3] # preload "X[2]" +___ +$code.=<<___ if ($i>=15); # apply Xupdate + vpxor @Xi[-2],@Xi[1],@Xi[1] # "X[13]" + vmovdqa `&Xi_off($j+2)`,@Xi[3] # "X[2]" + + vpaddd $K,$e,$e # e+=K_00_19 + vpslld \$5,$a,$t2 + vpandn $d,$b,$t1 + `"prefetcht0 63(@ptr[4])" if ($i==15 && $REG_SZ==32)` + vpand $c,$b,$t0 + + vmovdqa @Xi[0],`&Xi_off($i)` + vpaddd @Xi[0],$e,$e # e+=X[i] + vpxor `&Xi_off($j+8)`,@Xi[1],@Xi[1] + vpsrld \$27,$a,$t3 + vpxor $t1,$t0,$t0 # Ch(b,c,d) + vpxor @Xi[3],@Xi[1],@Xi[1] + `"prefetcht0 63(@ptr[5])" if ($i==15 && $REG_SZ==32)` + + vpslld \$30,$b,$t1 + vpor $t3,$t2,$t2 # rol(a,5) + vpaddd $t0,$e,$e # e+=Ch(b,c,d) + `"prefetcht0 63(@ptr[6])" if ($i==15 && $REG_SZ==32)` + vpsrld \$31,@Xi[1],$tx + vpaddd @Xi[1],@Xi[1],@Xi[1] + + vpsrld \$2,$b,$b + `"prefetcht0 63(@ptr[7])" if ($i==15 && $REG_SZ==32)` + vpaddd $t2,$e,$e # e+=rol(a,5) + vpor $tx,@Xi[1],@Xi[1] # rol \$1,@Xi[1] + vpor $t1,$b,$b # b=rol(b,30) +___ +push(@Xi,shift(@Xi)); +} + +sub BODY_20_39_avx { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i+1; + +$code.=<<___ if ($i<79); + vpxor @Xi[-2],@Xi[1],@Xi[1] # "X[13]" + vmovdqa `&Xi_off($j+2)`,@Xi[3] # "X[2]" + + vpslld \$5,$a,$t2 + vpaddd $K,$e,$e # e+=K_20_39 + vpxor $b,$d,$t0 +___ +$code.=<<___ if ($i<72); + vmovdqa @Xi[0],`&Xi_off($i)` +___ +$code.=<<___ if ($i<79); + vpaddd @Xi[0],$e,$e # e+=X[i] + vpxor `&Xi_off($j+8)`,@Xi[1],@Xi[1] + vpsrld \$27,$a,$t3 + vpxor $c,$t0,$t0 # Parity(b,c,d) + vpxor @Xi[3],@Xi[1],@Xi[1] + + vpslld \$30,$b,$t1 + vpor $t3,$t2,$t2 # rol(a,5) + vpaddd $t0,$e,$e # e+=Parity(b,c,d) + vpsrld \$31,@Xi[1],$tx + vpaddd @Xi[1],@Xi[1],@Xi[1] + + vpsrld \$2,$b,$b + vpaddd $t2,$e,$e # e+=rol(a,5) + vpor $tx,@Xi[1],@Xi[1] # rol(@Xi[1],1) + vpor $t1,$b,$b # b=rol(b,30) +___ +$code.=<<___ if ($i==79); + vpslld \$5,$a,$t2 + vpaddd $K,$e,$e # e+=K_20_39 + vpxor $b,$d,$t0 + + vpsrld \$27,$a,$t3 + vpaddd @Xi[0],$e,$e # e+=X[i] + vpxor $c,$t0,$t0 # Parity(b,c,d) + + vpslld \$30,$b,$t1 + vpor $t3,$t2,$t2 # rol(a,5) + vpaddd $t0,$e,$e # e+=Parity(b,c,d) + + vpsrld \$2,$b,$b + vpaddd $t2,$e,$e # e+=rol(a,5) + vpor $t1,$b,$b # b=rol(b,30) +___ +push(@Xi,shift(@Xi)); +} + +sub BODY_40_59_avx { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i+1; + +$code.=<<___; + vpxor @Xi[-2],@Xi[1],@Xi[1] # "X[13]" + vmovdqa `&Xi_off($j+2)`,@Xi[3] # "X[2]" + + vpaddd $K,$e,$e # e+=K_40_59 + vpslld \$5,$a,$t2 + vpand $c,$d,$t1 + vpxor `&Xi_off($j+8)`,@Xi[1],@Xi[1] + + vpaddd $t1,$e,$e + vpsrld \$27,$a,$t3 + vpxor $c,$d,$t0 + vpxor @Xi[3],@Xi[1],@Xi[1] + + vmovdqu @Xi[0],`&Xi_off($i)` + vpaddd @Xi[0],$e,$e # e+=X[i] + vpor $t3,$t2,$t2 # rol(a,5) + vpsrld \$31,@Xi[1],$tx + vpand $b,$t0,$t0 + vpaddd @Xi[1],@Xi[1],@Xi[1] + + vpslld \$30,$b,$t1 + vpaddd $t0,$e,$e # e+=Maj(b,d,c) + + vpsrld \$2,$b,$b + vpaddd $t2,$e,$e # e+=rol(a,5) + vpor $tx,@Xi[1],@Xi[1] # rol(@X[1],1) + vpor $t1,$b,$b # b=rol(b,30) +___ +push(@Xi,shift(@Xi)); +} + +$code.=<<___; +.type sha1_multi_block_avx,\@function,3 +.align 32 +sha1_multi_block_avx: +.cfi_startproc +_avx_shortcut: +___ +$code.=<<___ if ($avx>1); + shr \$32,%rcx + cmp \$2,$num + jb .Lavx + test \$`1<<5`,%ecx + jnz _avx2_shortcut + jmp .Lavx +.align 32 +.Lavx: +___ +$code.=<<___; + mov %rsp,%rax +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp +___ +$code.=<<___ if ($win64); + lea -0xa8(%rsp),%rsp + movaps %xmm6,(%rsp) + movaps %xmm7,0x10(%rsp) + movaps %xmm8,0x20(%rsp) + movaps %xmm9,0x30(%rsp) + movaps %xmm10,-0x78(%rax) + movaps %xmm11,-0x68(%rax) + movaps %xmm12,-0x58(%rax) + movaps %xmm13,-0x48(%rax) + movaps %xmm14,-0x38(%rax) + movaps %xmm15,-0x28(%rax) +___ +$code.=<<___; + sub \$`$REG_SZ*18`, %rsp + and \$-256,%rsp + mov %rax,`$REG_SZ*17`(%rsp) # original %rsp +.cfi_cfa_expression %rsp+`$REG_SZ*17`,deref,+8 +.Lbody_avx: + lea K_XX_XX(%rip),$Tbl + lea `$REG_SZ*16`(%rsp),%rbx + + vzeroupper +.Loop_grande_avx: + mov $num,`$REG_SZ*17+8`(%rsp) # original $num + xor $num,$num +___ +for($i=0;$i<4;$i++) { + $code.=<<___; + mov `16*$i+0`($inp),@ptr[$i] # input pointer + mov `16*$i+8`($inp),%ecx # number of blocks + cmp $num,%ecx + cmovg %ecx,$num # find maximum + test %ecx,%ecx + mov %ecx,`4*$i`(%rbx) # initialize counters + cmovle $Tbl,@ptr[$i] # cancel input +___ +} +$code.=<<___; + test $num,$num + jz .Ldone_avx + + vmovdqu 0x00($ctx),$A # load context + lea 128(%rsp),%rax + vmovdqu 0x20($ctx),$B + vmovdqu 0x40($ctx),$C + vmovdqu 0x60($ctx),$D + vmovdqu 0x80($ctx),$E + vmovdqu 0x60($Tbl),$tx # pbswap_mask + jmp .Loop_avx + +.align 32 +.Loop_avx: +___ +$code.=" vmovdqa -0x20($Tbl),$K\n"; # K_00_19 +for($i=0;$i<20;$i++) { &BODY_00_19_avx($i,@V); unshift(@V,pop(@V)); } +$code.=" vmovdqa 0x00($Tbl),$K\n"; # K_20_39 +for(;$i<40;$i++) { &BODY_20_39_avx($i,@V); unshift(@V,pop(@V)); } +$code.=" vmovdqa 0x20($Tbl),$K\n"; # K_40_59 +for(;$i<60;$i++) { &BODY_40_59_avx($i,@V); unshift(@V,pop(@V)); } +$code.=" vmovdqa 0x40($Tbl),$K\n"; # K_60_79 +for(;$i<80;$i++) { &BODY_20_39_avx($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + mov \$1,%ecx +___ +for($i=0;$i<4;$i++) { + $code.=<<___; + cmp `4*$i`(%rbx),%ecx # examine counters + cmovge $Tbl,@ptr[$i] # cancel input +___ +} +$code.=<<___; + vmovdqu (%rbx),$t0 # pull counters + vpxor $t2,$t2,$t2 + vmovdqa $t0,$t1 + vpcmpgtd $t2,$t1,$t1 # mask value + vpaddd $t1,$t0,$t0 # counters-- + + vpand $t1,$A,$A + vpand $t1,$B,$B + vpaddd 0x00($ctx),$A,$A + vpand $t1,$C,$C + vpaddd 0x20($ctx),$B,$B + vpand $t1,$D,$D + vpaddd 0x40($ctx),$C,$C + vpand $t1,$E,$E + vpaddd 0x60($ctx),$D,$D + vpaddd 0x80($ctx),$E,$E + vmovdqu $A,0x00($ctx) + vmovdqu $B,0x20($ctx) + vmovdqu $C,0x40($ctx) + vmovdqu $D,0x60($ctx) + vmovdqu $E,0x80($ctx) + + vmovdqu $t0,(%rbx) # save counters + vmovdqu 0x60($Tbl),$tx # pbswap_mask + dec $num + jnz .Loop_avx + + mov `$REG_SZ*17+8`(%rsp),$num + lea $REG_SZ($ctx),$ctx + lea `16*$REG_SZ/4`($inp),$inp + dec $num + jnz .Loop_grande_avx + +.Ldone_avx: + mov `$REG_SZ*17`(%rsp),%rax # original %rsp +.cfi_def_cfa %rax,8 + vzeroupper +___ +$code.=<<___ if ($win64); + movaps -0xb8(%rax),%xmm6 + movaps -0xa8(%rax),%xmm7 + movaps -0x98(%rax),%xmm8 + movaps -0x88(%rax),%xmm9 + movaps -0x78(%rax),%xmm10 + movaps -0x68(%rax),%xmm11 + movaps -0x58(%rax),%xmm12 + movaps -0x48(%rax),%xmm13 + movaps -0x38(%rax),%xmm14 + movaps -0x28(%rax),%xmm15 +___ +$code.=<<___; + mov -16(%rax),%rbp +.cfi_restore %rbp + mov -8(%rax),%rbx +.cfi_restore %rbx + lea (%rax),%rsp +.cfi_def_cfa_register %rsp +.Lepilogue_avx: + ret +.cfi_endproc +.size sha1_multi_block_avx,.-sha1_multi_block_avx +___ + + if ($avx>1) { +$code =~ s/\`([^\`]*)\`/eval $1/gem; + +$REG_SZ=32; + +@ptr=map("%r$_",(12..15,8..11)); + +@V=($A,$B,$C,$D,$E)=map("%ymm$_",(0..4)); +($t0,$t1,$t2,$t3,$tx)=map("%ymm$_",(5..9)); +@Xi=map("%ymm$_",(10..14)); +$K="%ymm15"; + +$code.=<<___; +.type sha1_multi_block_avx2,\@function,3 +.align 32 +sha1_multi_block_avx2: +.cfi_startproc +_avx2_shortcut: + mov %rsp,%rax +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +___ +$code.=<<___ if ($win64); + lea -0xa8(%rsp),%rsp + movaps %xmm6,(%rsp) + movaps %xmm7,0x10(%rsp) + movaps %xmm8,0x20(%rsp) + movaps %xmm9,0x30(%rsp) + movaps %xmm10,0x40(%rsp) + movaps %xmm11,0x50(%rsp) + movaps %xmm12,-0x78(%rax) + movaps %xmm13,-0x68(%rax) + movaps %xmm14,-0x58(%rax) + movaps %xmm15,-0x48(%rax) +___ +$code.=<<___; + sub \$`$REG_SZ*18`, %rsp + and \$-256,%rsp + mov %rax,`$REG_SZ*17`(%rsp) # original %rsp +.cfi_cfa_expression %rsp+`$REG_SZ*17`,deref,+8 +.Lbody_avx2: + lea K_XX_XX(%rip),$Tbl + shr \$1,$num + + vzeroupper +.Loop_grande_avx2: + mov $num,`$REG_SZ*17+8`(%rsp) # original $num + xor $num,$num + lea `$REG_SZ*16`(%rsp),%rbx +___ +for($i=0;$i<8;$i++) { + $code.=<<___; + mov `16*$i+0`($inp),@ptr[$i] # input pointer + mov `16*$i+8`($inp),%ecx # number of blocks + cmp $num,%ecx + cmovg %ecx,$num # find maximum + test %ecx,%ecx + mov %ecx,`4*$i`(%rbx) # initialize counters + cmovle $Tbl,@ptr[$i] # cancel input +___ +} +$code.=<<___; + vmovdqu 0x00($ctx),$A # load context + lea 128(%rsp),%rax + vmovdqu 0x20($ctx),$B + lea 256+128(%rsp),%rbx + vmovdqu 0x40($ctx),$C + vmovdqu 0x60($ctx),$D + vmovdqu 0x80($ctx),$E + vmovdqu 0x60($Tbl),$tx # pbswap_mask + jmp .Loop_avx2 + +.align 32 +.Loop_avx2: +___ +$code.=" vmovdqa -0x20($Tbl),$K\n"; # K_00_19 +for($i=0;$i<20;$i++) { &BODY_00_19_avx($i,@V); unshift(@V,pop(@V)); } +$code.=" vmovdqa 0x00($Tbl),$K\n"; # K_20_39 +for(;$i<40;$i++) { &BODY_20_39_avx($i,@V); unshift(@V,pop(@V)); } +$code.=" vmovdqa 0x20($Tbl),$K\n"; # K_40_59 +for(;$i<60;$i++) { &BODY_40_59_avx($i,@V); unshift(@V,pop(@V)); } +$code.=" vmovdqa 0x40($Tbl),$K\n"; # K_60_79 +for(;$i<80;$i++) { &BODY_20_39_avx($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + mov \$1,%ecx + lea `$REG_SZ*16`(%rsp),%rbx +___ +for($i=0;$i<8;$i++) { + $code.=<<___; + cmp `4*$i`(%rbx),%ecx # examine counters + cmovge $Tbl,@ptr[$i] # cancel input +___ +} +$code.=<<___; + vmovdqu (%rbx),$t0 # pull counters + vpxor $t2,$t2,$t2 + vmovdqa $t0,$t1 + vpcmpgtd $t2,$t1,$t1 # mask value + vpaddd $t1,$t0,$t0 # counters-- + + vpand $t1,$A,$A + vpand $t1,$B,$B + vpaddd 0x00($ctx),$A,$A + vpand $t1,$C,$C + vpaddd 0x20($ctx),$B,$B + vpand $t1,$D,$D + vpaddd 0x40($ctx),$C,$C + vpand $t1,$E,$E + vpaddd 0x60($ctx),$D,$D + vpaddd 0x80($ctx),$E,$E + vmovdqu $A,0x00($ctx) + vmovdqu $B,0x20($ctx) + vmovdqu $C,0x40($ctx) + vmovdqu $D,0x60($ctx) + vmovdqu $E,0x80($ctx) + + vmovdqu $t0,(%rbx) # save counters + lea 256+128(%rsp),%rbx + vmovdqu 0x60($Tbl),$tx # pbswap_mask + dec $num + jnz .Loop_avx2 + + #mov `$REG_SZ*17+8`(%rsp),$num + #lea $REG_SZ($ctx),$ctx + #lea `16*$REG_SZ/4`($inp),$inp + #dec $num + #jnz .Loop_grande_avx2 + +.Ldone_avx2: + mov `$REG_SZ*17`(%rsp),%rax # original %rsp +.cfi_def_cfa %rax,8 + vzeroupper +___ +$code.=<<___ if ($win64); + movaps -0xd8(%rax),%xmm6 + movaps -0xc8(%rax),%xmm7 + movaps -0xb8(%rax),%xmm8 + movaps -0xa8(%rax),%xmm9 + movaps -0x98(%rax),%xmm10 + movaps -0x88(%rax),%xmm11 + movaps -0x78(%rax),%xmm12 + movaps -0x68(%rax),%xmm13 + movaps -0x58(%rax),%xmm14 + movaps -0x48(%rax),%xmm15 +___ +$code.=<<___; + mov -48(%rax),%r15 +.cfi_restore %r15 + mov -40(%rax),%r14 +.cfi_restore %r14 + mov -32(%rax),%r13 +.cfi_restore %r13 + mov -24(%rax),%r12 +.cfi_restore %r12 + mov -16(%rax),%rbp +.cfi_restore %rbp + mov -8(%rax),%rbx +.cfi_restore %rbx + lea (%rax),%rsp +.cfi_def_cfa_register %rsp +.Lepilogue_avx2: + ret +.cfi_endproc +.size sha1_multi_block_avx2,.-sha1_multi_block_avx2 +___ + } }}} +$code.=<<___; + +.align 256 + .long 0x5a827999,0x5a827999,0x5a827999,0x5a827999 # K_00_19 + .long 0x5a827999,0x5a827999,0x5a827999,0x5a827999 # K_00_19 +K_XX_XX: + .long 0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1 # K_20_39 + .long 0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1 # K_20_39 + .long 0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc # K_40_59 + .long 0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc # K_40_59 + .long 0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6 # K_60_79 + .long 0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6 # K_60_79 + .long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f # pbswap + .long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f # pbswap + .byte 0xf,0xe,0xd,0xc,0xb,0xa,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0 + .asciz "SHA1 multi-block transform for x86_64, CRYPTOGAMS by " +___ + +if ($win64) { +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type se_handler,\@abi-omnipotent +.align 16 +se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # end of prologue label + cmp %r10,%rbx # context->Rip<.Lbody + jb .Lin_prologue + + mov 152($context),%rax # pull context->Rsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=.Lepilogue + jae .Lin_prologue + + mov `16*17`(%rax),%rax # pull saved stack pointer + + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + + lea -24-10*16(%rax),%rsi + lea 512($context),%rdi # &context.Xmm6 + mov \$20,%ecx + .long 0xa548f3fc # cld; rep movsq + +.Lin_prologue: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size se_handler,.-se_handler +___ +$code.=<<___ if ($avx>1); +.type avx2_handler,\@abi-omnipotent +.align 16 +avx2_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # end of prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lin_prologue + + mov `32*17`($context),%rax # pull saved stack pointer + + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov -48(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + + lea -56-10*16(%rax),%rsi + lea 512($context),%rdi # &context.Xmm6 + mov \$20,%ecx + .long 0xa548f3fc # cld; rep movsq + + jmp .Lin_prologue +.size avx2_handler,.-avx2_handler +___ +$code.=<<___; +.section .pdata +.align 4 + .rva .LSEH_begin_sha1_multi_block + .rva .LSEH_end_sha1_multi_block + .rva .LSEH_info_sha1_multi_block + .rva .LSEH_begin_sha1_multi_block_shaext + .rva .LSEH_end_sha1_multi_block_shaext + .rva .LSEH_info_sha1_multi_block_shaext +___ +$code.=<<___ if ($avx); + .rva .LSEH_begin_sha1_multi_block_avx + .rva .LSEH_end_sha1_multi_block_avx + .rva .LSEH_info_sha1_multi_block_avx +___ +$code.=<<___ if ($avx>1); + .rva .LSEH_begin_sha1_multi_block_avx2 + .rva .LSEH_end_sha1_multi_block_avx2 + .rva .LSEH_info_sha1_multi_block_avx2 +___ +$code.=<<___; +.section .xdata +.align 8 +.LSEH_info_sha1_multi_block: + .byte 9,0,0,0 + .rva se_handler + .rva .Lbody,.Lepilogue # HandlerData[] +.LSEH_info_sha1_multi_block_shaext: + .byte 9,0,0,0 + .rva se_handler + .rva .Lbody_shaext,.Lepilogue_shaext # HandlerData[] +___ +$code.=<<___ if ($avx); +.LSEH_info_sha1_multi_block_avx: + .byte 9,0,0,0 + .rva se_handler + .rva .Lbody_avx,.Lepilogue_avx # HandlerData[] +___ +$code.=<<___ if ($avx>1); +.LSEH_info_sha1_multi_block_avx2: + .byte 9,0,0,0 + .rva avx2_handler + .rva .Lbody_avx2,.Lepilogue_avx2 # HandlerData[] +___ +} +#################################################################### + +sub rex { + local *opcode=shift; + my ($dst,$src)=@_; + my $rex=0; + + $rex|=0x04 if ($dst>=8); + $rex|=0x01 if ($src>=8); + unshift @opcode,$rex|0x40 if ($rex); +} + +sub sha1rnds4 { + if (@_[0] =~ /\$([x0-9a-f]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) { + my @opcode=(0x0f,0x3a,0xcc); + rex(\@opcode,$3,$2); + push @opcode,0xc0|($2&7)|(($3&7)<<3); # ModR/M + my $c=$1; + push @opcode,$c=~/^0/?oct($c):$c; + return ".byte\t".join(',',@opcode); + } else { + return "sha1rnds4\t".@_[0]; + } +} + +sub sha1op38 { + my $instr = shift; + my %opcodelet = ( + "sha1nexte" => 0xc8, + "sha1msg1" => 0xc9, + "sha1msg2" => 0xca ); + + if (defined($opcodelet{$instr}) && @_[0] =~ /%xmm([0-9]+),\s*%xmm([0-9]+)/) { + my @opcode=(0x0f,0x38); + rex(\@opcode,$2,$1); + push @opcode,$opcodelet{$instr}; + push @opcode,0xc0|($1&7)|(($2&7)<<3); # ModR/M + return ".byte\t".join(',',@opcode); + } else { + return $instr."\t".@_[0]; + } +} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval($1)/ge; + + s/\b(sha1rnds4)\s+(.*)/sha1rnds4($2)/geo or + s/\b(sha1[^\s]*)\s+(.*)/sha1op38($1,$2)/geo or + + s/\b(vmov[dq])\b(.+)%ymm([0-9]+)/$1$2%xmm$3/go or + s/\b(vmovdqu)\b(.+)%x%ymm([0-9]+)/$1$2%xmm$3/go or + s/\b(vpinsr[qd])\b(.+)%ymm([0-9]+),%ymm([0-9]+)/$1$2%xmm$3,%xmm$4/go or + s/\b(vpextr[qd])\b(.+)%ymm([0-9]+)/$1$2%xmm$3/go or + s/\b(vinserti128)\b(\s+)%ymm/$1$2\$1,%xmm/go or + s/\b(vpbroadcast[qd]\s+)%ymm([0-9]+)/$1%xmm$2/go; + + print $_,"\n"; +} + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-mips.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-mips.pl new file mode 100644 index 000000000..08f84bc3b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-mips.pl @@ -0,0 +1,461 @@ +#! /usr/bin/env perl +# Copyright 2009-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# SHA1 block procedure for MIPS. + +# Performance improvement is 30% on unaligned input. The "secret" is +# to deploy lwl/lwr pair to load unaligned input. One could have +# vectorized Xupdate on MIPSIII/IV, but the goal was to code MIPS32- +# compatible subroutine. There is room for minor optimization on +# little-endian platforms... + +# September 2012. +# +# Add MIPS32r2 code (>25% less instructions). + +###################################################################### +# There is a number of MIPS ABI in use, O32 and N32/64 are most +# widely used. Then there is a new contender: NUBI. It appears that if +# one picks the latter, it's possible to arrange code in ABI neutral +# manner. Therefore let's stick to NUBI register layout: +# +($zero,$at,$t0,$t1,$t2)=map("\$$_",(0..2,24,25)); +($a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7)=map("\$$_",(4..11)); +($s0,$s1,$s2,$s3,$s4,$s5,$s6,$s7,$s8,$s9,$s10,$s11)=map("\$$_",(12..23)); +($gp,$tp,$sp,$fp,$ra)=map("\$$_",(3,28..31)); +# +# The return value is placed in $a0. Following coding rules facilitate +# interoperability: +# +# - never ever touch $tp, "thread pointer", former $gp; +# - copy return value to $t0, former $v0 [or to $a0 if you're adapting +# old code]; +# - on O32 populate $a4-$a7 with 'lw $aN,4*N($sp)' if necessary; +# +# For reference here is register layout for N32/64 MIPS ABIs: +# +# ($zero,$at,$v0,$v1)=map("\$$_",(0..3)); +# ($a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7)=map("\$$_",(4..11)); +# ($t0,$t1,$t2,$t3,$t8,$t9)=map("\$$_",(12..15,24,25)); +# ($s0,$s1,$s2,$s3,$s4,$s5,$s6,$s7)=map("\$$_",(16..23)); +# ($gp,$sp,$fp,$ra)=map("\$$_",(28..31)); +# +$flavour = shift || "o32"; # supported flavours are o32,n32,64,nubi32,nubi64 + +if ($flavour =~ /64|n32/i) { + $PTR_ADD="daddu"; # incidentally works even on n32 + $PTR_SUB="dsubu"; # incidentally works even on n32 + $REG_S="sd"; + $REG_L="ld"; + $PTR_SLL="dsll"; # incidentally works even on n32 + $SZREG=8; +} else { + $PTR_ADD="addu"; + $PTR_SUB="subu"; + $REG_S="sw"; + $REG_L="lw"; + $PTR_SLL="sll"; + $SZREG=4; +} +# +# +# +###################################################################### + +$big_endian=(`echo MIPSEB | $ENV{CC} -E -`=~/MIPSEB/)?0:1 if ($ENV{CC}); + +for (@ARGV) { $output=$_ if (/\w[\w\-]*\.\w+$/); } +open STDOUT,">$output"; + +if (!defined($big_endian)) + { $big_endian=(unpack('L',pack('N',1))==1); } + +# offsets of the Most and Least Significant Bytes +$MSB=$big_endian?0:3; +$LSB=3&~$MSB; + +@X=map("\$$_",(8..23)); # a4-a7,s0-s11 + +$ctx=$a0; +$inp=$a1; +$num=$a2; +$A="\$1"; +$B="\$2"; +$C="\$3"; +$D="\$7"; +$E="\$24"; @V=($A,$B,$C,$D,$E); +$t0="\$25"; +$t1=$num; # $num is offloaded to stack +$t2="\$30"; # fp +$K="\$31"; # ra + +sub BODY_00_14 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i+1; +$code.=<<___ if (!$big_endian); +#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2) + wsbh @X[$i],@X[$i] # byte swap($i) + rotr @X[$i],@X[$i],16 +#else + srl $t0,@X[$i],24 # byte swap($i) + srl $t1,@X[$i],8 + andi $t2,@X[$i],0xFF00 + sll @X[$i],@X[$i],24 + andi $t1,0xFF00 + sll $t2,$t2,8 + or @X[$i],$t0 + or $t1,$t2 + or @X[$i],$t1 +#endif +___ +$code.=<<___; +#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2) + addu $e,$K # $i + xor $t0,$c,$d + rotr $t1,$a,27 + and $t0,$b + addu $e,$t1 +#if defined(_MIPS_ARCH_MIPS32R6) || defined(_MIPS_ARCH_MIPS64R6) + lw @X[$j],$j*4($inp) +#else + lwl @X[$j],$j*4+$MSB($inp) + lwr @X[$j],$j*4+$LSB($inp) +#endif + xor $t0,$d + addu $e,@X[$i] + rotr $b,$b,2 + addu $e,$t0 +#else + lwl @X[$j],$j*4+$MSB($inp) + sll $t0,$a,5 # $i + addu $e,$K + lwr @X[$j],$j*4+$LSB($inp) + srl $t1,$a,27 + addu $e,$t0 + xor $t0,$c,$d + addu $e,$t1 + sll $t2,$b,30 + and $t0,$b + srl $b,$b,2 + xor $t0,$d + addu $e,@X[$i] + or $b,$t2 + addu $e,$t0 +#endif +___ +} + +sub BODY_15_19 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i+1; + +$code.=<<___ if (!$big_endian && $i==15); +#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2) + wsbh @X[$i],@X[$i] # byte swap($i) + rotr @X[$i],@X[$i],16 +#else + srl $t0,@X[$i],24 # byte swap($i) + srl $t1,@X[$i],8 + andi $t2,@X[$i],0xFF00 + sll @X[$i],@X[$i],24 + andi $t1,0xFF00 + sll $t2,$t2,8 + or @X[$i],$t0 + or @X[$i],$t1 + or @X[$i],$t2 +#endif +___ +$code.=<<___; +#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2) + addu $e,$K # $i + xor @X[$j%16],@X[($j+2)%16] + xor $t0,$c,$d + rotr $t1,$a,27 + xor @X[$j%16],@X[($j+8)%16] + and $t0,$b + addu $e,$t1 + xor @X[$j%16],@X[($j+13)%16] + xor $t0,$d + addu $e,@X[$i%16] + rotr @X[$j%16],@X[$j%16],31 + rotr $b,$b,2 + addu $e,$t0 +#else + xor @X[$j%16],@X[($j+2)%16] + sll $t0,$a,5 # $i + addu $e,$K + srl $t1,$a,27 + addu $e,$t0 + xor @X[$j%16],@X[($j+8)%16] + xor $t0,$c,$d + addu $e,$t1 + xor @X[$j%16],@X[($j+13)%16] + sll $t2,$b,30 + and $t0,$b + srl $t1,@X[$j%16],31 + addu @X[$j%16],@X[$j%16] + srl $b,$b,2 + xor $t0,$d + or @X[$j%16],$t1 + addu $e,@X[$i%16] + or $b,$t2 + addu $e,$t0 +#endif +___ +} + +sub BODY_20_39 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i+1; +$code.=<<___ if ($i<79); +#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2) + xor @X[$j%16],@X[($j+2)%16] + addu $e,$K # $i + rotr $t1,$a,27 + xor @X[$j%16],@X[($j+8)%16] + xor $t0,$c,$d + addu $e,$t1 + xor @X[$j%16],@X[($j+13)%16] + xor $t0,$b + addu $e,@X[$i%16] + rotr @X[$j%16],@X[$j%16],31 + rotr $b,$b,2 + addu $e,$t0 +#else + xor @X[$j%16],@X[($j+2)%16] + sll $t0,$a,5 # $i + addu $e,$K + srl $t1,$a,27 + addu $e,$t0 + xor @X[$j%16],@X[($j+8)%16] + xor $t0,$c,$d + addu $e,$t1 + xor @X[$j%16],@X[($j+13)%16] + sll $t2,$b,30 + xor $t0,$b + srl $t1,@X[$j%16],31 + addu @X[$j%16],@X[$j%16] + srl $b,$b,2 + addu $e,@X[$i%16] + or @X[$j%16],$t1 + or $b,$t2 + addu $e,$t0 +#endif +___ +$code.=<<___ if ($i==79); +#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2) + lw @X[0],0($ctx) + addu $e,$K # $i + lw @X[1],4($ctx) + rotr $t1,$a,27 + lw @X[2],8($ctx) + xor $t0,$c,$d + addu $e,$t1 + lw @X[3],12($ctx) + xor $t0,$b + addu $e,@X[$i%16] + lw @X[4],16($ctx) + rotr $b,$b,2 + addu $e,$t0 +#else + lw @X[0],0($ctx) + sll $t0,$a,5 # $i + addu $e,$K + lw @X[1],4($ctx) + srl $t1,$a,27 + addu $e,$t0 + lw @X[2],8($ctx) + xor $t0,$c,$d + addu $e,$t1 + lw @X[3],12($ctx) + sll $t2,$b,30 + xor $t0,$b + lw @X[4],16($ctx) + srl $b,$b,2 + addu $e,@X[$i%16] + or $b,$t2 + addu $e,$t0 +#endif +___ +} + +sub BODY_40_59 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i+1; +$code.=<<___ if ($i<79); +#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2) + addu $e,$K # $i + and $t0,$c,$d + xor @X[$j%16],@X[($j+2)%16] + rotr $t1,$a,27 + addu $e,$t0 + xor @X[$j%16],@X[($j+8)%16] + xor $t0,$c,$d + addu $e,$t1 + xor @X[$j%16],@X[($j+13)%16] + and $t0,$b + addu $e,@X[$i%16] + rotr @X[$j%16],@X[$j%16],31 + rotr $b,$b,2 + addu $e,$t0 +#else + xor @X[$j%16],@X[($j+2)%16] + sll $t0,$a,5 # $i + addu $e,$K + srl $t1,$a,27 + addu $e,$t0 + xor @X[$j%16],@X[($j+8)%16] + and $t0,$c,$d + addu $e,$t1 + xor @X[$j%16],@X[($j+13)%16] + sll $t2,$b,30 + addu $e,$t0 + srl $t1,@X[$j%16],31 + xor $t0,$c,$d + addu @X[$j%16],@X[$j%16] + and $t0,$b + srl $b,$b,2 + or @X[$j%16],$t1 + addu $e,@X[$i%16] + or $b,$t2 + addu $e,$t0 +#endif +___ +} + +$FRAMESIZE=16; # large enough to accommodate NUBI saved registers +$SAVED_REGS_MASK = ($flavour =~ /nubi/i) ? "0xc0fff008" : "0xc0ff0000"; + +$code=<<___; +#include "mips_arch.h" + +.text + +.set noat +.set noreorder +.align 5 +.globl sha1_block_data_order +.ent sha1_block_data_order +sha1_block_data_order: + .frame $sp,$FRAMESIZE*$SZREG,$ra + .mask $SAVED_REGS_MASK,-$SZREG + .set noreorder + $PTR_SUB $sp,$FRAMESIZE*$SZREG + $REG_S $ra,($FRAMESIZE-1)*$SZREG($sp) + $REG_S $fp,($FRAMESIZE-2)*$SZREG($sp) + $REG_S $s11,($FRAMESIZE-3)*$SZREG($sp) + $REG_S $s10,($FRAMESIZE-4)*$SZREG($sp) + $REG_S $s9,($FRAMESIZE-5)*$SZREG($sp) + $REG_S $s8,($FRAMESIZE-6)*$SZREG($sp) + $REG_S $s7,($FRAMESIZE-7)*$SZREG($sp) + $REG_S $s6,($FRAMESIZE-8)*$SZREG($sp) + $REG_S $s5,($FRAMESIZE-9)*$SZREG($sp) + $REG_S $s4,($FRAMESIZE-10)*$SZREG($sp) +___ +$code.=<<___ if ($flavour =~ /nubi/i); # optimize non-nubi prologue + $REG_S $s3,($FRAMESIZE-11)*$SZREG($sp) + $REG_S $s2,($FRAMESIZE-12)*$SZREG($sp) + $REG_S $s1,($FRAMESIZE-13)*$SZREG($sp) + $REG_S $s0,($FRAMESIZE-14)*$SZREG($sp) + $REG_S $gp,($FRAMESIZE-15)*$SZREG($sp) +___ +$code.=<<___; + $PTR_SLL $num,6 + $PTR_ADD $num,$inp + $REG_S $num,0($sp) + lw $A,0($ctx) + lw $B,4($ctx) + lw $C,8($ctx) + lw $D,12($ctx) + b .Loop + lw $E,16($ctx) +.align 4 +.Loop: + .set reorder +#if defined(_MIPS_ARCH_MIPS32R6) || defined(_MIPS_ARCH_MIPS64R6) + lui $K,0x5a82 + lw @X[0],($inp) + ori $K,0x7999 # K_00_19 +#else + lwl @X[0],$MSB($inp) + lui $K,0x5a82 + lwr @X[0],$LSB($inp) + ori $K,0x7999 # K_00_19 +#endif +___ +for ($i=0;$i<15;$i++) { &BODY_00_14($i,@V); unshift(@V,pop(@V)); } +for (;$i<20;$i++) { &BODY_15_19($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + lui $K,0x6ed9 + ori $K,0xeba1 # K_20_39 +___ +for (;$i<40;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + lui $K,0x8f1b + ori $K,0xbcdc # K_40_59 +___ +for (;$i<60;$i++) { &BODY_40_59($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + lui $K,0xca62 + ori $K,0xc1d6 # K_60_79 +___ +for (;$i<80;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + $PTR_ADD $inp,64 + $REG_L $num,0($sp) + + addu $A,$X[0] + addu $B,$X[1] + sw $A,0($ctx) + addu $C,$X[2] + addu $D,$X[3] + sw $B,4($ctx) + addu $E,$X[4] + sw $C,8($ctx) + sw $D,12($ctx) + sw $E,16($ctx) + .set noreorder + bne $inp,$num,.Loop + nop + + .set noreorder + $REG_L $ra,($FRAMESIZE-1)*$SZREG($sp) + $REG_L $fp,($FRAMESIZE-2)*$SZREG($sp) + $REG_L $s11,($FRAMESIZE-3)*$SZREG($sp) + $REG_L $s10,($FRAMESIZE-4)*$SZREG($sp) + $REG_L $s9,($FRAMESIZE-5)*$SZREG($sp) + $REG_L $s8,($FRAMESIZE-6)*$SZREG($sp) + $REG_L $s7,($FRAMESIZE-7)*$SZREG($sp) + $REG_L $s6,($FRAMESIZE-8)*$SZREG($sp) + $REG_L $s5,($FRAMESIZE-9)*$SZREG($sp) + $REG_L $s4,($FRAMESIZE-10)*$SZREG($sp) +___ +$code.=<<___ if ($flavour =~ /nubi/i); + $REG_L $s3,($FRAMESIZE-11)*$SZREG($sp) + $REG_L $s2,($FRAMESIZE-12)*$SZREG($sp) + $REG_L $s1,($FRAMESIZE-13)*$SZREG($sp) + $REG_L $s0,($FRAMESIZE-14)*$SZREG($sp) + $REG_L $gp,($FRAMESIZE-15)*$SZREG($sp) +___ +$code.=<<___; + jr $ra + $PTR_ADD $sp,$FRAMESIZE*$SZREG +.end sha1_block_data_order +.rdata +.asciiz "SHA1 for MIPS, CRYPTOGAMS by " +___ +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-parisc.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-parisc.pl new file mode 100644 index 000000000..b001be16a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-parisc.pl @@ -0,0 +1,279 @@ +#! /usr/bin/env perl +# Copyright 2009-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# SHA1 block procedure for PA-RISC. + +# June 2009. +# +# On PA-7100LC performance is >30% better than gcc 3.2 generated code +# for aligned input and >50% better for unaligned. Compared to vendor +# compiler on PA-8600 it's almost 60% faster in 64-bit build and just +# few percent faster in 32-bit one (this for aligned input, data for +# unaligned input is not available). +# +# Special thanks to polarhome.com for providing HP-UX account. + +$flavour = shift; +$output = shift; +open STDOUT,">$output"; + +if ($flavour =~ /64/) { + $LEVEL ="2.0W"; + $SIZE_T =8; + $FRAME_MARKER =80; + $SAVED_RP =16; + $PUSH ="std"; + $PUSHMA ="std,ma"; + $POP ="ldd"; + $POPMB ="ldd,mb"; +} else { + $LEVEL ="1.0"; + $SIZE_T =4; + $FRAME_MARKER =48; + $SAVED_RP =20; + $PUSH ="stw"; + $PUSHMA ="stwm"; + $POP ="ldw"; + $POPMB ="ldwm"; +} + +$FRAME=14*$SIZE_T+$FRAME_MARKER;# 14 saved regs + frame marker + # [+ argument transfer] +$ctx="%r26"; # arg0 +$inp="%r25"; # arg1 +$num="%r24"; # arg2 + +$t0="%r28"; +$t1="%r29"; +$K="%r31"; + +@X=("%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7", "%r8", + "%r9", "%r10","%r11","%r12","%r13","%r14","%r15","%r16",$t0); + +@V=($A,$B,$C,$D,$E)=("%r19","%r20","%r21","%r22","%r23"); + +sub BODY_00_19 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i+1; +$code.=<<___ if ($i<15); + addl $K,$e,$e ; $i + shd $a,$a,27,$t1 + addl @X[$i],$e,$e + and $c,$b,$t0 + addl $t1,$e,$e + andcm $d,$b,$t1 + shd $b,$b,2,$b + or $t1,$t0,$t0 + addl $t0,$e,$e +___ +$code.=<<___ if ($i>=15); # with forward Xupdate + addl $K,$e,$e ; $i + shd $a,$a,27,$t1 + xor @X[($j+2)%16],@X[$j%16],@X[$j%16] + addl @X[$i%16],$e,$e + and $c,$b,$t0 + xor @X[($j+8)%16],@X[$j%16],@X[$j%16] + addl $t1,$e,$e + andcm $d,$b,$t1 + shd $b,$b,2,$b + or $t1,$t0,$t0 + xor @X[($j+13)%16],@X[$j%16],@X[$j%16] + add $t0,$e,$e + shd @X[$j%16],@X[$j%16],31,@X[$j%16] +___ +} + +sub BODY_20_39 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i+1; +$code.=<<___ if ($i<79); + xor @X[($j+2)%16],@X[$j%16],@X[$j%16] ; $i + addl $K,$e,$e + shd $a,$a,27,$t1 + xor @X[($j+8)%16],@X[$j%16],@X[$j%16] + addl @X[$i%16],$e,$e + xor $b,$c,$t0 + xor @X[($j+13)%16],@X[$j%16],@X[$j%16] + addl $t1,$e,$e + shd $b,$b,2,$b + xor $d,$t0,$t0 + shd @X[$j%16],@X[$j%16],31,@X[$j%16] + addl $t0,$e,$e +___ +$code.=<<___ if ($i==79); # with context load + ldw 0($ctx),@X[0] ; $i + addl $K,$e,$e + shd $a,$a,27,$t1 + ldw 4($ctx),@X[1] + addl @X[$i%16],$e,$e + xor $b,$c,$t0 + ldw 8($ctx),@X[2] + addl $t1,$e,$e + shd $b,$b,2,$b + xor $d,$t0,$t0 + ldw 12($ctx),@X[3] + addl $t0,$e,$e + ldw 16($ctx),@X[4] +___ +} + +sub BODY_40_59 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i+1; +$code.=<<___; + shd $a,$a,27,$t1 ; $i + addl $K,$e,$e + xor @X[($j+2)%16],@X[$j%16],@X[$j%16] + xor $d,$c,$t0 + addl @X[$i%16],$e,$e + xor @X[($j+8)%16],@X[$j%16],@X[$j%16] + and $b,$t0,$t0 + addl $t1,$e,$e + shd $b,$b,2,$b + xor @X[($j+13)%16],@X[$j%16],@X[$j%16] + addl $t0,$e,$e + and $d,$c,$t1 + shd @X[$j%16],@X[$j%16],31,@X[$j%16] + addl $t1,$e,$e +___ +} + +$code=<<___; + .LEVEL $LEVEL + .SPACE \$TEXT\$ + .SUBSPA \$CODE\$,QUAD=0,ALIGN=8,ACCESS=0x2C,CODE_ONLY + + .EXPORT sha1_block_data_order,ENTRY,ARGW0=GR,ARGW1=GR,ARGW2=GR +sha1_block_data_order + .PROC + .CALLINFO FRAME=`$FRAME-14*$SIZE_T`,NO_CALLS,SAVE_RP,ENTRY_GR=16 + .ENTRY + $PUSH %r2,-$SAVED_RP(%sp) ; standard prologue + $PUSHMA %r3,$FRAME(%sp) + $PUSH %r4,`-$FRAME+1*$SIZE_T`(%sp) + $PUSH %r5,`-$FRAME+2*$SIZE_T`(%sp) + $PUSH %r6,`-$FRAME+3*$SIZE_T`(%sp) + $PUSH %r7,`-$FRAME+4*$SIZE_T`(%sp) + $PUSH %r8,`-$FRAME+5*$SIZE_T`(%sp) + $PUSH %r9,`-$FRAME+6*$SIZE_T`(%sp) + $PUSH %r10,`-$FRAME+7*$SIZE_T`(%sp) + $PUSH %r11,`-$FRAME+8*$SIZE_T`(%sp) + $PUSH %r12,`-$FRAME+9*$SIZE_T`(%sp) + $PUSH %r13,`-$FRAME+10*$SIZE_T`(%sp) + $PUSH %r14,`-$FRAME+11*$SIZE_T`(%sp) + $PUSH %r15,`-$FRAME+12*$SIZE_T`(%sp) + $PUSH %r16,`-$FRAME+13*$SIZE_T`(%sp) + + ldw 0($ctx),$A + ldw 4($ctx),$B + ldw 8($ctx),$C + ldw 12($ctx),$D + ldw 16($ctx),$E + + extru $inp,31,2,$t0 ; t0=inp&3; + sh3addl $t0,%r0,$t0 ; t0*=8; + subi 32,$t0,$t0 ; t0=32-t0; + mtctl $t0,%cr11 ; %sar=t0; + +L\$oop + ldi 3,$t0 + andcm $inp,$t0,$t0 ; 64-bit neutral +___ + for ($i=0;$i<15;$i++) { # load input block + $code.="\tldw `4*$i`($t0),@X[$i]\n"; } +$code.=<<___; + cmpb,*= $inp,$t0,L\$aligned + ldw 60($t0),@X[15] + ldw 64($t0),@X[16] +___ + for ($i=0;$i<16;$i++) { # align input + $code.="\tvshd @X[$i],@X[$i+1],@X[$i]\n"; } +$code.=<<___; +L\$aligned + ldil L'0x5a827000,$K ; K_00_19 + ldo 0x999($K),$K +___ +for ($i=0;$i<20;$i++) { &BODY_00_19($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + ldil L'0x6ed9e000,$K ; K_20_39 + ldo 0xba1($K),$K +___ + +for (;$i<40;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + ldil L'0x8f1bb000,$K ; K_40_59 + ldo 0xcdc($K),$K +___ + +for (;$i<60;$i++) { &BODY_40_59($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + ldil L'0xca62c000,$K ; K_60_79 + ldo 0x1d6($K),$K +___ +for (;$i<80;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); } + +$code.=<<___; + addl @X[0],$A,$A + addl @X[1],$B,$B + addl @X[2],$C,$C + addl @X[3],$D,$D + addl @X[4],$E,$E + stw $A,0($ctx) + stw $B,4($ctx) + stw $C,8($ctx) + stw $D,12($ctx) + stw $E,16($ctx) + addib,*<> -1,$num,L\$oop + ldo 64($inp),$inp + + $POP `-$FRAME-$SAVED_RP`(%sp),%r2 ; standard epilogue + $POP `-$FRAME+1*$SIZE_T`(%sp),%r4 + $POP `-$FRAME+2*$SIZE_T`(%sp),%r5 + $POP `-$FRAME+3*$SIZE_T`(%sp),%r6 + $POP `-$FRAME+4*$SIZE_T`(%sp),%r7 + $POP `-$FRAME+5*$SIZE_T`(%sp),%r8 + $POP `-$FRAME+6*$SIZE_T`(%sp),%r9 + $POP `-$FRAME+7*$SIZE_T`(%sp),%r10 + $POP `-$FRAME+8*$SIZE_T`(%sp),%r11 + $POP `-$FRAME+9*$SIZE_T`(%sp),%r12 + $POP `-$FRAME+10*$SIZE_T`(%sp),%r13 + $POP `-$FRAME+11*$SIZE_T`(%sp),%r14 + $POP `-$FRAME+12*$SIZE_T`(%sp),%r15 + $POP `-$FRAME+13*$SIZE_T`(%sp),%r16 + bv (%r2) + .EXIT + $POPMB -$FRAME(%sp),%r3 + .PROCEND + .STRINGZ "SHA1 block transform for PA-RISC, CRYPTOGAMS by " +___ + +if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler/) { + $gnuas = 1; +} + +foreach(split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/ge; + + s/(\.LEVEL\s+2\.0)W/$1w/ if ($gnuas && $SIZE_T==8); + s/\.SPACE\s+\$TEXT\$/.text/ if ($gnuas && $SIZE_T==8); + s/\.SUBSPA.*// if ($gnuas && $SIZE_T==8); + s/,\*/,/ if ($SIZE_T==4); + s/\bbv\b/bve/ if ($SIZE_T==8); + + print $_,"\n"; +} +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-ppc.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-ppc.pl new file mode 100755 index 000000000..0cda0a3e1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-ppc.pl @@ -0,0 +1,351 @@ +#! /usr/bin/env perl +# Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# I let hardware handle unaligned input(*), except on page boundaries +# (see below for details). Otherwise straightforward implementation +# with X vector in register bank. +# +# (*) this means that this module is inappropriate for PPC403? Does +# anybody know if pre-POWER3 can sustain unaligned load? + +# -m64 -m32 +# ---------------------------------- +# PPC970,gcc-4.0.0 +76% +59% +# Power6,xlc-7 +68% +33% + +$flavour = shift; + +if ($flavour =~ /64/) { + $SIZE_T =8; + $LRSAVE =2*$SIZE_T; + $UCMP ="cmpld"; + $STU ="stdu"; + $POP ="ld"; + $PUSH ="std"; +} elsif ($flavour =~ /32/) { + $SIZE_T =4; + $LRSAVE =$SIZE_T; + $UCMP ="cmplw"; + $STU ="stwu"; + $POP ="lwz"; + $PUSH ="stw"; +} else { die "nonsense $flavour"; } + +# Define endianness based on flavour +# i.e.: linux64le +$LITTLE_ENDIAN = ($flavour=~/le$/) ? $SIZE_T : 0; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or +die "can't locate ppc-xlate.pl"; + +open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!"; + +$FRAME=24*$SIZE_T+64; +$LOCALS=6*$SIZE_T; + +$K ="r0"; +$sp ="r1"; +$toc="r2"; +$ctx="r3"; +$inp="r4"; +$num="r5"; +$t0 ="r15"; +$t1 ="r6"; + +$A ="r7"; +$B ="r8"; +$C ="r9"; +$D ="r10"; +$E ="r11"; +$T ="r12"; + +@V=($A,$B,$C,$D,$E,$T); +@X=("r16","r17","r18","r19","r20","r21","r22","r23", + "r24","r25","r26","r27","r28","r29","r30","r31"); + +sub loadbe { +my ($dst, $src, $temp_reg) = @_; +$code.=<<___ if (!$LITTLE_ENDIAN); + lwz $dst,$src +___ +$code.=<<___ if ($LITTLE_ENDIAN); + lwz $temp_reg,$src + rotlwi $dst,$temp_reg,8 + rlwimi $dst,$temp_reg,24,0,7 + rlwimi $dst,$temp_reg,24,16,23 +___ +} + +sub BODY_00_19 { +my ($i,$a,$b,$c,$d,$e,$f)=@_; +my $j=$i+1; + + # Since the last value of $f is discarded, we can use + # it as a temp reg to swap byte-order when needed. + loadbe("@X[$i]","`$i*4`($inp)",$f) if ($i==0); + loadbe("@X[$j]","`$j*4`($inp)",$f) if ($i<15); +$code.=<<___ if ($i<15); + add $f,$K,$e + rotlwi $e,$a,5 + add $f,$f,@X[$i] + and $t0,$c,$b + add $f,$f,$e + andc $t1,$d,$b + rotlwi $b,$b,30 + or $t0,$t0,$t1 + add $f,$f,$t0 +___ +$code.=<<___ if ($i>=15); + add $f,$K,$e + rotlwi $e,$a,5 + xor @X[$j%16],@X[$j%16],@X[($j+2)%16] + add $f,$f,@X[$i%16] + and $t0,$c,$b + xor @X[$j%16],@X[$j%16],@X[($j+8)%16] + add $f,$f,$e + andc $t1,$d,$b + rotlwi $b,$b,30 + or $t0,$t0,$t1 + xor @X[$j%16],@X[$j%16],@X[($j+13)%16] + add $f,$f,$t0 + rotlwi @X[$j%16],@X[$j%16],1 +___ +} + +sub BODY_20_39 { +my ($i,$a,$b,$c,$d,$e,$f)=@_; +my $j=$i+1; +$code.=<<___ if ($i<79); + add $f,$K,$e + xor $t0,$b,$d + rotlwi $e,$a,5 + xor @X[$j%16],@X[$j%16],@X[($j+2)%16] + add $f,$f,@X[$i%16] + xor $t0,$t0,$c + xor @X[$j%16],@X[$j%16],@X[($j+8)%16] + add $f,$f,$t0 + rotlwi $b,$b,30 + xor @X[$j%16],@X[$j%16],@X[($j+13)%16] + add $f,$f,$e + rotlwi @X[$j%16],@X[$j%16],1 +___ +$code.=<<___ if ($i==79); + add $f,$K,$e + xor $t0,$b,$d + rotlwi $e,$a,5 + lwz r16,0($ctx) + add $f,$f,@X[$i%16] + xor $t0,$t0,$c + lwz r17,4($ctx) + add $f,$f,$t0 + rotlwi $b,$b,30 + lwz r18,8($ctx) + lwz r19,12($ctx) + add $f,$f,$e + lwz r20,16($ctx) +___ +} + +sub BODY_40_59 { +my ($i,$a,$b,$c,$d,$e,$f)=@_; +my $j=$i+1; +$code.=<<___; + add $f,$K,$e + rotlwi $e,$a,5 + xor @X[$j%16],@X[$j%16],@X[($j+2)%16] + add $f,$f,@X[$i%16] + and $t0,$b,$c + xor @X[$j%16],@X[$j%16],@X[($j+8)%16] + add $f,$f,$e + or $t1,$b,$c + rotlwi $b,$b,30 + xor @X[$j%16],@X[$j%16],@X[($j+13)%16] + and $t1,$t1,$d + or $t0,$t0,$t1 + rotlwi @X[$j%16],@X[$j%16],1 + add $f,$f,$t0 +___ +} + +$code=<<___; +.machine "any" +.text + +.globl .sha1_block_data_order +.align 4 +.sha1_block_data_order: + $STU $sp,-$FRAME($sp) + mflr r0 + $PUSH r15,`$FRAME-$SIZE_T*17`($sp) + $PUSH r16,`$FRAME-$SIZE_T*16`($sp) + $PUSH r17,`$FRAME-$SIZE_T*15`($sp) + $PUSH r18,`$FRAME-$SIZE_T*14`($sp) + $PUSH r19,`$FRAME-$SIZE_T*13`($sp) + $PUSH r20,`$FRAME-$SIZE_T*12`($sp) + $PUSH r21,`$FRAME-$SIZE_T*11`($sp) + $PUSH r22,`$FRAME-$SIZE_T*10`($sp) + $PUSH r23,`$FRAME-$SIZE_T*9`($sp) + $PUSH r24,`$FRAME-$SIZE_T*8`($sp) + $PUSH r25,`$FRAME-$SIZE_T*7`($sp) + $PUSH r26,`$FRAME-$SIZE_T*6`($sp) + $PUSH r27,`$FRAME-$SIZE_T*5`($sp) + $PUSH r28,`$FRAME-$SIZE_T*4`($sp) + $PUSH r29,`$FRAME-$SIZE_T*3`($sp) + $PUSH r30,`$FRAME-$SIZE_T*2`($sp) + $PUSH r31,`$FRAME-$SIZE_T*1`($sp) + $PUSH r0,`$FRAME+$LRSAVE`($sp) + lwz $A,0($ctx) + lwz $B,4($ctx) + lwz $C,8($ctx) + lwz $D,12($ctx) + lwz $E,16($ctx) + andi. r0,$inp,3 + bne Lunaligned +Laligned: + mtctr $num + bl Lsha1_block_private + b Ldone + +; PowerPC specification allows an implementation to be ill-behaved +; upon unaligned access which crosses page boundary. "Better safe +; than sorry" principle makes me treat it specially. But I don't +; look for particular offending word, but rather for 64-byte input +; block which crosses the boundary. Once found that block is aligned +; and hashed separately... +.align 4 +Lunaligned: + subfic $t1,$inp,4096 + andi. $t1,$t1,4095 ; distance to closest page boundary + srwi. $t1,$t1,6 ; t1/=64 + beq Lcross_page + $UCMP $num,$t1 + ble Laligned ; didn't cross the page boundary + mtctr $t1 + subfc $num,$t1,$num + bl Lsha1_block_private +Lcross_page: + li $t1,16 + mtctr $t1 + addi r20,$sp,$LOCALS ; spot within the frame +Lmemcpy: + lbz r16,0($inp) + lbz r17,1($inp) + lbz r18,2($inp) + lbz r19,3($inp) + addi $inp,$inp,4 + stb r16,0(r20) + stb r17,1(r20) + stb r18,2(r20) + stb r19,3(r20) + addi r20,r20,4 + bdnz Lmemcpy + + $PUSH $inp,`$FRAME-$SIZE_T*18`($sp) + li $t1,1 + addi $inp,$sp,$LOCALS + mtctr $t1 + bl Lsha1_block_private + $POP $inp,`$FRAME-$SIZE_T*18`($sp) + addic. $num,$num,-1 + bne Lunaligned + +Ldone: + $POP r0,`$FRAME+$LRSAVE`($sp) + $POP r15,`$FRAME-$SIZE_T*17`($sp) + $POP r16,`$FRAME-$SIZE_T*16`($sp) + $POP r17,`$FRAME-$SIZE_T*15`($sp) + $POP r18,`$FRAME-$SIZE_T*14`($sp) + $POP r19,`$FRAME-$SIZE_T*13`($sp) + $POP r20,`$FRAME-$SIZE_T*12`($sp) + $POP r21,`$FRAME-$SIZE_T*11`($sp) + $POP r22,`$FRAME-$SIZE_T*10`($sp) + $POP r23,`$FRAME-$SIZE_T*9`($sp) + $POP r24,`$FRAME-$SIZE_T*8`($sp) + $POP r25,`$FRAME-$SIZE_T*7`($sp) + $POP r26,`$FRAME-$SIZE_T*6`($sp) + $POP r27,`$FRAME-$SIZE_T*5`($sp) + $POP r28,`$FRAME-$SIZE_T*4`($sp) + $POP r29,`$FRAME-$SIZE_T*3`($sp) + $POP r30,`$FRAME-$SIZE_T*2`($sp) + $POP r31,`$FRAME-$SIZE_T*1`($sp) + mtlr r0 + addi $sp,$sp,$FRAME + blr + .long 0 + .byte 0,12,4,1,0x80,18,3,0 + .long 0 +___ + +# This is private block function, which uses tailored calling +# interface, namely upon entry SHA_CTX is pre-loaded to given +# registers and counter register contains amount of chunks to +# digest... +$code.=<<___; +.align 4 +Lsha1_block_private: +___ +$code.=<<___; # load K_00_19 + lis $K,0x5a82 + ori $K,$K,0x7999 +___ +for($i=0;$i<20;$i++) { &BODY_00_19($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; # load K_20_39 + lis $K,0x6ed9 + ori $K,$K,0xeba1 +___ +for(;$i<40;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; # load K_40_59 + lis $K,0x8f1b + ori $K,$K,0xbcdc +___ +for(;$i<60;$i++) { &BODY_40_59($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; # load K_60_79 + lis $K,0xca62 + ori $K,$K,0xc1d6 +___ +for(;$i<80;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + add r16,r16,$E + add r17,r17,$T + add r18,r18,$A + add r19,r19,$B + add r20,r20,$C + stw r16,0($ctx) + mr $A,r16 + stw r17,4($ctx) + mr $B,r17 + stw r18,8($ctx) + mr $C,r18 + stw r19,12($ctx) + mr $D,r19 + stw r20,16($ctx) + mr $E,r20 + addi $inp,$inp,`16*4` + bdnz Lsha1_block_private + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 +.size .sha1_block_data_order,.-.sha1_block_data_order +___ +$code.=<<___; +.asciz "SHA1 block transform for PPC, CRYPTOGAMS by " +___ + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-s390x.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-s390x.pl new file mode 100644 index 000000000..5729c3089 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-s390x.pl @@ -0,0 +1,249 @@ +#! /usr/bin/env perl +# Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# SHA1 block procedure for s390x. + +# April 2007. +# +# Performance is >30% better than gcc 3.3 generated code. But the real +# twist is that SHA1 hardware support is detected and utilized. In +# which case performance can reach further >4.5x for larger chunks. + +# January 2009. +# +# Optimize Xupdate for amount of memory references and reschedule +# instructions to favour dual-issue z10 pipeline. On z10 hardware is +# "only" ~2.3x faster than software. + +# November 2010. +# +# Adapt for -m31 build. If kernel supports what's called "highgprs" +# feature on Linux [see /proc/cpuinfo], it's possible to use 64-bit +# instructions and achieve "64-bit" performance even in 31-bit legacy +# application context. The feature is not specific to any particular +# processor, as long as it's "z-CPU". Latter implies that the code +# remains z/Architecture specific. On z990 it was measured to perform +# 23% better than code generated by gcc 4.3. + +$kimdfunc=1; # magic function code for kimd instruction + +$flavour = shift; + +if ($flavour =~ /3[12]/) { + $SIZE_T=4; + $g=""; +} else { + $SIZE_T=8; + $g="g"; +} + +while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} +open STDOUT,">$output"; + +$K_00_39="%r0"; $K=$K_00_39; +$K_40_79="%r1"; +$ctx="%r2"; $prefetch="%r2"; +$inp="%r3"; +$len="%r4"; + +$A="%r5"; +$B="%r6"; +$C="%r7"; +$D="%r8"; +$E="%r9"; @V=($A,$B,$C,$D,$E); +$t0="%r10"; +$t1="%r11"; +@X=("%r12","%r13","%r14"); +$sp="%r15"; + +$stdframe=16*$SIZE_T+4*8; +$frame=$stdframe+16*4; + +sub Xupdate { +my $i=shift; + +$code.=<<___ if ($i==15); + lg $prefetch,$stdframe($sp) ### Xupdate(16) warm-up + lr $X[0],$X[2] +___ +return if ($i&1); # Xupdate is vectorized and executed every 2nd cycle +$code.=<<___ if ($i<16); + lg $X[0],`$i*4`($inp) ### Xload($i) + rllg $X[1],$X[0],32 +___ +$code.=<<___ if ($i>=16); + xgr $X[0],$prefetch ### Xupdate($i) + lg $prefetch,`$stdframe+4*(($i+2)%16)`($sp) + xg $X[0],`$stdframe+4*(($i+8)%16)`($sp) + xgr $X[0],$prefetch + rll $X[0],$X[0],1 + rllg $X[1],$X[0],32 + rll $X[1],$X[1],1 + rllg $X[0],$X[1],32 + lr $X[2],$X[1] # feedback +___ +$code.=<<___ if ($i<=70); + stg $X[0],`$stdframe+4*($i%16)`($sp) +___ +unshift(@X,pop(@X)); +} + +sub BODY_00_19 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $xi=$X[1]; + + &Xupdate($i); +$code.=<<___; + alr $e,$K ### $i + rll $t1,$a,5 + lr $t0,$d + xr $t0,$c + alr $e,$t1 + nr $t0,$b + alr $e,$xi + xr $t0,$d + rll $b,$b,30 + alr $e,$t0 +___ +} + +sub BODY_20_39 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $xi=$X[1]; + + &Xupdate($i); +$code.=<<___; + alr $e,$K ### $i + rll $t1,$a,5 + lr $t0,$b + alr $e,$t1 + xr $t0,$c + alr $e,$xi + xr $t0,$d + rll $b,$b,30 + alr $e,$t0 +___ +} + +sub BODY_40_59 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $xi=$X[1]; + + &Xupdate($i); +$code.=<<___; + alr $e,$K ### $i + rll $t1,$a,5 + lr $t0,$b + alr $e,$t1 + or $t0,$c + lr $t1,$b + nr $t0,$d + nr $t1,$c + alr $e,$xi + or $t0,$t1 + rll $b,$b,30 + alr $e,$t0 +___ +} + +$code.=<<___; +#include "s390x_arch.h" + +.text +.align 64 +.type Ktable,\@object +Ktable: .long 0x5a827999,0x6ed9eba1,0x8f1bbcdc,0xca62c1d6 + .skip 48 #.long 0,0,0,0,0,0,0,0,0,0,0,0 +.size Ktable,.-Ktable +.globl sha1_block_data_order +.type sha1_block_data_order,\@function +sha1_block_data_order: +___ +$code.=<<___ if ($kimdfunc); + larl %r1,OPENSSL_s390xcap_P + lg %r0,S390X_KIMD(%r1) # check kimd capabilities + tmhh %r0,`0x8000>>$kimdfunc` + jz .Lsoftware + lghi %r0,$kimdfunc + lgr %r1,$ctx + lgr %r2,$inp + sllg %r3,$len,6 + .long 0xb93e0002 # kimd %r0,%r2 + brc 1,.-4 # pay attention to "partial completion" + br %r14 +.align 16 +.Lsoftware: +___ +$code.=<<___; + lghi %r1,-$frame + st${g} $ctx,`2*$SIZE_T`($sp) + stm${g} %r6,%r15,`6*$SIZE_T`($sp) + lgr %r0,$sp + la $sp,0(%r1,$sp) + st${g} %r0,0($sp) + + larl $t0,Ktable + llgf $A,0($ctx) + llgf $B,4($ctx) + llgf $C,8($ctx) + llgf $D,12($ctx) + llgf $E,16($ctx) + + lg $K_00_39,0($t0) + lg $K_40_79,8($t0) + +.Lloop: + rllg $K_00_39,$K_00_39,32 +___ +for ($i=0;$i<20;$i++) { &BODY_00_19($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + rllg $K_00_39,$K_00_39,32 +___ +for (;$i<40;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; $K=$K_40_79; + rllg $K_40_79,$K_40_79,32 +___ +for (;$i<60;$i++) { &BODY_40_59($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + rllg $K_40_79,$K_40_79,32 +___ +for (;$i<80;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + + l${g} $ctx,`$frame+2*$SIZE_T`($sp) + la $inp,64($inp) + al $A,0($ctx) + al $B,4($ctx) + al $C,8($ctx) + al $D,12($ctx) + al $E,16($ctx) + st $A,0($ctx) + st $B,4($ctx) + st $C,8($ctx) + st $D,12($ctx) + st $E,16($ctx) + brct${g} $len,.Lloop + + lm${g} %r6,%r15,`$frame+6*$SIZE_T`($sp) + br %r14 +.size sha1_block_data_order,.-sha1_block_data_order +.string "SHA1 block transform for s390x, CRYPTOGAMS by " +___ + +$code =~ s/\`([^\`]*)\`/eval $1/gem; + +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-sparcv9.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-sparcv9.pl new file mode 100644 index 000000000..3e612e3d5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-sparcv9.pl @@ -0,0 +1,434 @@ +#! /usr/bin/env perl +# Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# +# Hardware SPARC T4 support by David S. Miller +# ==================================================================== + +# Performance improvement is not really impressive on pre-T1 CPU: +8% +# over Sun C and +25% over gcc [3.3]. While on T1, a.k.a. Niagara, it +# turned to be 40% faster than 64-bit code generated by Sun C 5.8 and +# >2x than 64-bit code generated by gcc 3.4. And there is a gimmick. +# X[16] vector is packed to 8 64-bit registers and as result nothing +# is spilled on stack. In addition input data is loaded in compact +# instruction sequence, thus minimizing the window when the code is +# subject to [inter-thread] cache-thrashing hazard. The goal is to +# ensure scalability on UltraSPARC T1, or rather to avoid decay when +# amount of active threads exceeds the number of physical cores. + +# SPARC T4 SHA1 hardware achieves 3.72 cycles per byte, which is 3.1x +# faster than software. Multi-process benchmark saturates at 11x +# single-process result on 8-core processor, or ~9GBps per 2.85GHz +# socket. + +$output=pop; +open STDOUT,">$output"; + +@X=("%o0","%o1","%o2","%o3","%o4","%o5","%g1","%o7"); +$rot1m="%g2"; +$tmp64="%g3"; +$Xi="%g4"; +$A="%l0"; +$B="%l1"; +$C="%l2"; +$D="%l3"; +$E="%l4"; +@V=($A,$B,$C,$D,$E); +$K_00_19="%l5"; +$K_20_39="%l6"; +$K_40_59="%l7"; +$K_60_79="%g5"; +@K=($K_00_19,$K_20_39,$K_40_59,$K_60_79); + +$ctx="%i0"; +$inp="%i1"; +$len="%i2"; +$tmp0="%i3"; +$tmp1="%i4"; +$tmp2="%i5"; + +sub BODY_00_15 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $xi=($i&1)?@X[($i/2)%8]:$Xi; + +$code.=<<___; + sll $a,5,$tmp0 !! $i + add @K[$i/20],$e,$e + srl $a,27,$tmp1 + add $tmp0,$e,$e + and $c,$b,$tmp0 + add $tmp1,$e,$e + sll $b,30,$tmp2 + andn $d,$b,$tmp1 + srl $b,2,$b + or $tmp1,$tmp0,$tmp1 + or $tmp2,$b,$b + add $xi,$e,$e +___ +if ($i&1 && $i<15) { + $code.= + " srlx @X[(($i+1)/2)%8],32,$Xi\n"; +} +$code.=<<___; + add $tmp1,$e,$e +___ +} + +sub Xupdate { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i/2; + +if ($i&1) { +$code.=<<___; + sll $a,5,$tmp0 !! $i + add @K[$i/20],$e,$e + srl $a,27,$tmp1 +___ +} else { +$code.=<<___; + sllx @X[($j+6)%8],32,$Xi ! Xupdate($i) + xor @X[($j+1)%8],@X[$j%8],@X[$j%8] + srlx @X[($j+7)%8],32,$tmp1 + xor @X[($j+4)%8],@X[$j%8],@X[$j%8] + sll $a,5,$tmp0 !! $i + or $tmp1,$Xi,$Xi + add @K[$i/20],$e,$e !! + xor $Xi,@X[$j%8],@X[$j%8] + srlx @X[$j%8],31,$Xi + add @X[$j%8],@X[$j%8],@X[$j%8] + and $Xi,$rot1m,$Xi + andn @X[$j%8],$rot1m,@X[$j%8] + srl $a,27,$tmp1 !! + or $Xi,@X[$j%8],@X[$j%8] +___ +} +} + +sub BODY_16_19 { +my ($i,$a,$b,$c,$d,$e)=@_; + + &Xupdate(@_); + if ($i&1) { + $xi=@X[($i/2)%8]; + } else { + $xi=$Xi; + $code.="\tsrlx @X[($i/2)%8],32,$xi\n"; + } +$code.=<<___; + add $tmp0,$e,$e !! + and $c,$b,$tmp0 + add $tmp1,$e,$e + sll $b,30,$tmp2 + add $xi,$e,$e + andn $d,$b,$tmp1 + srl $b,2,$b + or $tmp1,$tmp0,$tmp1 + or $tmp2,$b,$b + add $tmp1,$e,$e +___ +} + +sub BODY_20_39 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $xi; + &Xupdate(@_); + if ($i&1) { + $xi=@X[($i/2)%8]; + } else { + $xi=$Xi; + $code.="\tsrlx @X[($i/2)%8],32,$xi\n"; + } +$code.=<<___; + add $tmp0,$e,$e !! + xor $c,$b,$tmp0 + add $tmp1,$e,$e + sll $b,30,$tmp2 + xor $d,$tmp0,$tmp1 + srl $b,2,$b + add $tmp1,$e,$e + or $tmp2,$b,$b + add $xi,$e,$e +___ +} + +sub BODY_40_59 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $xi; + &Xupdate(@_); + if ($i&1) { + $xi=@X[($i/2)%8]; + } else { + $xi=$Xi; + $code.="\tsrlx @X[($i/2)%8],32,$xi\n"; + } +$code.=<<___; + add $tmp0,$e,$e !! + and $c,$b,$tmp0 + add $tmp1,$e,$e + sll $b,30,$tmp2 + or $c,$b,$tmp1 + srl $b,2,$b + and $d,$tmp1,$tmp1 + add $xi,$e,$e + or $tmp1,$tmp0,$tmp1 + or $tmp2,$b,$b + add $tmp1,$e,$e +___ +} + +$code.=<<___; +#include "sparc_arch.h" + +#ifdef __arch64__ +.register %g2,#scratch +.register %g3,#scratch +#endif + +.section ".text",#alloc,#execinstr + +#ifdef __PIC__ +SPARC_PIC_THUNK(%g1) +#endif + +.align 32 +.globl sha1_block_data_order +sha1_block_data_order: + SPARC_LOAD_ADDRESS_LEAF(OPENSSL_sparcv9cap_P,%g1,%g5) + ld [%g1+4],%g1 ! OPENSSL_sparcv9cap_P[1] + + andcc %g1, CFR_SHA1, %g0 + be .Lsoftware + nop + + ld [%o0 + 0x00], %f0 ! load context + ld [%o0 + 0x04], %f1 + ld [%o0 + 0x08], %f2 + andcc %o1, 0x7, %g0 + ld [%o0 + 0x0c], %f3 + bne,pn %icc, .Lhwunaligned + ld [%o0 + 0x10], %f4 + +.Lhw_loop: + ldd [%o1 + 0x00], %f8 + ldd [%o1 + 0x08], %f10 + ldd [%o1 + 0x10], %f12 + ldd [%o1 + 0x18], %f14 + ldd [%o1 + 0x20], %f16 + ldd [%o1 + 0x28], %f18 + ldd [%o1 + 0x30], %f20 + subcc %o2, 1, %o2 ! done yet? + ldd [%o1 + 0x38], %f22 + add %o1, 0x40, %o1 + prefetch [%o1 + 63], 20 + + .word 0x81b02820 ! SHA1 + + bne,pt SIZE_T_CC, .Lhw_loop + nop + +.Lhwfinish: + st %f0, [%o0 + 0x00] ! store context + st %f1, [%o0 + 0x04] + st %f2, [%o0 + 0x08] + st %f3, [%o0 + 0x0c] + retl + st %f4, [%o0 + 0x10] + +.align 8 +.Lhwunaligned: + alignaddr %o1, %g0, %o1 + + ldd [%o1 + 0x00], %f10 +.Lhwunaligned_loop: + ldd [%o1 + 0x08], %f12 + ldd [%o1 + 0x10], %f14 + ldd [%o1 + 0x18], %f16 + ldd [%o1 + 0x20], %f18 + ldd [%o1 + 0x28], %f20 + ldd [%o1 + 0x30], %f22 + ldd [%o1 + 0x38], %f24 + subcc %o2, 1, %o2 ! done yet? + ldd [%o1 + 0x40], %f26 + add %o1, 0x40, %o1 + prefetch [%o1 + 63], 20 + + faligndata %f10, %f12, %f8 + faligndata %f12, %f14, %f10 + faligndata %f14, %f16, %f12 + faligndata %f16, %f18, %f14 + faligndata %f18, %f20, %f16 + faligndata %f20, %f22, %f18 + faligndata %f22, %f24, %f20 + faligndata %f24, %f26, %f22 + + .word 0x81b02820 ! SHA1 + + bne,pt SIZE_T_CC, .Lhwunaligned_loop + for %f26, %f26, %f10 ! %f10=%f26 + + ba .Lhwfinish + nop + +.align 16 +.Lsoftware: + save %sp,-STACK_FRAME,%sp + sllx $len,6,$len + add $inp,$len,$len + + or %g0,1,$rot1m + sllx $rot1m,32,$rot1m + or $rot1m,1,$rot1m + + ld [$ctx+0],$A + ld [$ctx+4],$B + ld [$ctx+8],$C + ld [$ctx+12],$D + ld [$ctx+16],$E + andn $inp,7,$tmp0 + + sethi %hi(0x5a827999),$K_00_19 + or $K_00_19,%lo(0x5a827999),$K_00_19 + sethi %hi(0x6ed9eba1),$K_20_39 + or $K_20_39,%lo(0x6ed9eba1),$K_20_39 + sethi %hi(0x8f1bbcdc),$K_40_59 + or $K_40_59,%lo(0x8f1bbcdc),$K_40_59 + sethi %hi(0xca62c1d6),$K_60_79 + or $K_60_79,%lo(0xca62c1d6),$K_60_79 + +.Lloop: + ldx [$tmp0+0],@X[0] + ldx [$tmp0+16],@X[2] + ldx [$tmp0+32],@X[4] + ldx [$tmp0+48],@X[6] + and $inp,7,$tmp1 + ldx [$tmp0+8],@X[1] + sll $tmp1,3,$tmp1 + ldx [$tmp0+24],@X[3] + subcc %g0,$tmp1,$tmp2 ! should be 64-$tmp1, but -$tmp1 works too + ldx [$tmp0+40],@X[5] + bz,pt %icc,.Laligned + ldx [$tmp0+56],@X[7] + + sllx @X[0],$tmp1,@X[0] + ldx [$tmp0+64],$tmp64 +___ +for($i=0;$i<7;$i++) +{ $code.=<<___; + srlx @X[$i+1],$tmp2,$Xi + sllx @X[$i+1],$tmp1,@X[$i+1] + or $Xi,@X[$i],@X[$i] +___ +} +$code.=<<___; + srlx $tmp64,$tmp2,$tmp64 + or $tmp64,@X[7],@X[7] +.Laligned: + srlx @X[0],32,$Xi +___ +for ($i=0;$i<16;$i++) { &BODY_00_15($i,@V); unshift(@V,pop(@V)); } +for (;$i<20;$i++) { &BODY_16_19($i,@V); unshift(@V,pop(@V)); } +for (;$i<40;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); } +for (;$i<60;$i++) { &BODY_40_59($i,@V); unshift(@V,pop(@V)); } +for (;$i<80;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + + ld [$ctx+0],@X[0] + ld [$ctx+4],@X[1] + ld [$ctx+8],@X[2] + ld [$ctx+12],@X[3] + add $inp,64,$inp + ld [$ctx+16],@X[4] + cmp $inp,$len + + add $A,@X[0],$A + st $A,[$ctx+0] + add $B,@X[1],$B + st $B,[$ctx+4] + add $C,@X[2],$C + st $C,[$ctx+8] + add $D,@X[3],$D + st $D,[$ctx+12] + add $E,@X[4],$E + st $E,[$ctx+16] + + bne SIZE_T_CC,.Lloop + andn $inp,7,$tmp0 + + ret + restore +.type sha1_block_data_order,#function +.size sha1_block_data_order,(.-sha1_block_data_order) +.asciz "SHA1 block transform for SPARCv9, CRYPTOGAMS by " +.align 4 +___ + +# Purpose of these subroutines is to explicitly encode VIS instructions, +# so that one can compile the module without having to specify VIS +# extensions on compiler command line, e.g. -xarch=v9 vs. -xarch=v9a. +# Idea is to reserve for option to produce "universal" binary and let +# programmer detect if current CPU is VIS capable at run-time. +sub unvis { +my ($mnemonic,$rs1,$rs2,$rd)=@_; +my $ref,$opf; +my %visopf = ( "faligndata" => 0x048, + "for" => 0x07c ); + + $ref = "$mnemonic\t$rs1,$rs2,$rd"; + + if ($opf=$visopf{$mnemonic}) { + foreach ($rs1,$rs2,$rd) { + return $ref if (!/%f([0-9]{1,2})/); + $_=$1; + if ($1>=32) { + return $ref if ($1&1); + # re-encode for upper double register addressing + $_=($1|$1>>5)&31; + } + } + + return sprintf ".word\t0x%08x !%s", + 0x81b00000|$rd<<25|$rs1<<14|$opf<<5|$rs2, + $ref; + } else { + return $ref; + } +} +sub unalignaddr { +my ($mnemonic,$rs1,$rs2,$rd)=@_; +my %bias = ( "g" => 0, "o" => 8, "l" => 16, "i" => 24 ); +my $ref="$mnemonic\t$rs1,$rs2,$rd"; + + foreach ($rs1,$rs2,$rd) { + if (/%([goli])([0-7])/) { $_=$bias{$1}+$2; } + else { return $ref; } + } + return sprintf ".word\t0x%08x !%s", + 0x81b00300|$rd<<25|$rs1<<14|$rs2, + $ref; +} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/ge; + + s/\b(f[^\s]*)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*(%f[0-9]{1,2})/ + &unvis($1,$2,$3,$4) + /ge; + s/\b(alignaddr)\s+(%[goli][0-7]),\s*(%[goli][0-7]),\s*(%[goli][0-7])/ + &unalignaddr($1,$2,$3,$4) + /ge; + + print $_,"\n"; +} + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-sparcv9a.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-sparcv9a.pl new file mode 100644 index 000000000..50d3e136a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-sparcv9a.pl @@ -0,0 +1,608 @@ +#! /usr/bin/env perl +# Copyright 2009-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# January 2009 +# +# Provided that UltraSPARC VIS instructions are pipe-lined(*) and +# pairable(*) with IALU ones, offloading of Xupdate to the UltraSPARC +# Graphic Unit would make it possible to achieve higher instruction- +# level parallelism, ILP, and thus higher performance. It should be +# explicitly noted that ILP is the keyword, and it means that this +# code would be unsuitable for cores like UltraSPARC-Tx. The idea is +# not really novel, Sun had VIS-powered implementation for a while. +# Unlike Sun's implementation this one can process multiple unaligned +# input blocks, and as such works as drop-in replacement for OpenSSL +# sha1_block_data_order. Performance improvement was measured to be +# 40% over pure IALU sha1-sparcv9.pl on UltraSPARC-IIi, but 12% on +# UltraSPARC-III. See below for discussion... +# +# The module does not present direct interest for OpenSSL, because +# it doesn't provide better performance on contemporary SPARCv9 CPUs, +# UltraSPARC-Tx and SPARC64-V[II] to be specific. Those who feel they +# absolutely must score on UltraSPARC-I-IV can simply replace +# crypto/sha/asm/sha1-sparcv9.pl with this module. +# +# (*) "Pipe-lined" means that even if it takes several cycles to +# complete, next instruction using same functional unit [but not +# depending on the result of the current instruction] can start +# execution without having to wait for the unit. "Pairable" +# means that two [or more] independent instructions can be +# issued at the very same time. + +$bits=32; +for (@ARGV) { $bits=64 if (/\-m64/ || /\-xarch\=v9/); } +if ($bits==64) { $bias=2047; $frame=192; } +else { $bias=0; $frame=112; } + +$output=shift; +open STDOUT,">$output"; + +$ctx="%i0"; +$inp="%i1"; +$len="%i2"; +$tmp0="%i3"; +$tmp1="%i4"; +$tmp2="%i5"; +$tmp3="%g5"; + +$base="%g1"; +$align="%g4"; +$Xfer="%o5"; +$nXfer=$tmp3; +$Xi="%o7"; + +$A="%l0"; +$B="%l1"; +$C="%l2"; +$D="%l3"; +$E="%l4"; +@V=($A,$B,$C,$D,$E); + +$Actx="%o0"; +$Bctx="%o1"; +$Cctx="%o2"; +$Dctx="%o3"; +$Ectx="%o4"; + +$fmul="%f32"; +$VK_00_19="%f34"; +$VK_20_39="%f36"; +$VK_40_59="%f38"; +$VK_60_79="%f40"; +@VK=($VK_00_19,$VK_20_39,$VK_40_59,$VK_60_79); +@X=("%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7", + "%f8", "%f9","%f10","%f11","%f12","%f13","%f14","%f15","%f16"); + +# This is reference 2x-parallelized VIS-powered Xupdate procedure. It +# covers even K_NN_MM addition... +sub Xupdate { +my ($i)=@_; +my $K=@VK[($i+16)/20]; +my $j=($i+16)%16; + +# [ provided that GSR.alignaddr_offset is 5, $mul contains +# 0x100ULL<<32|0x100 value and K_NN_MM are pre-loaded to +# chosen registers... ] +$code.=<<___; + fxors @X[($j+13)%16],@X[$j],@X[$j] !-1/-1/-1:X[0]^=X[13] + fxors @X[($j+14)%16],@X[$j+1],@X[$j+1]! 0/ 0/ 0:X[1]^=X[14] + fxor @X[($j+2)%16],@X[($j+8)%16],%f18! 1/ 1/ 1:Tmp=X[2,3]^X[8,9] + fxor %f18,@X[$j],@X[$j] ! 2/ 4/ 3:X[0,1]^=X[2,3]^X[8,9] + faligndata @X[$j],@X[$j],%f18 ! 3/ 7/ 5:Tmp=X[0,1]>>>24 + fpadd32 @X[$j],@X[$j],@X[$j] ! 4/ 8/ 6:X[0,1]<<=1 + fmul8ulx16 %f18,$fmul,%f18 ! 5/10/ 7:Tmp>>=7, Tmp&=1 + ![fxors %f15,%f2,%f2] + for %f18,@X[$j],@X[$j] ! 8/14/10:X[0,1]|=Tmp + ![fxors %f0,%f3,%f3] !10/17/12:X[0] dependency + fpadd32 $K,@X[$j],%f20 + std %f20,[$Xfer+`4*$j`] +___ +# The numbers delimited with slash are the earliest possible dispatch +# cycles for given instruction assuming 1 cycle latency for simple VIS +# instructions, such as on UltraSPARC-I&II, 3 cycles latency, such as +# on UltraSPARC-III&IV, and 2 cycles latency(*), respectively. Being +# 2x-parallelized the procedure is "worth" 5, 8.5 or 6 ticks per SHA1 +# round. As [long as] FPU/VIS instructions are perfectly pairable with +# IALU ones, the round timing is defined by the maximum between VIS +# and IALU timings. The latter varies from round to round and averages +# out at 6.25 ticks. This means that USI&II should operate at IALU +# rate, while USIII&IV - at VIS rate. This explains why performance +# improvement varies among processors. Well, given that pure IALU +# sha1-sparcv9.pl module exhibits virtually uniform performance of +# ~9.3 cycles per SHA1 round. Timings mentioned above are theoretical +# lower limits. Real-life performance was measured to be 6.6 cycles +# per SHA1 round on USIIi and 8.3 on USIII. The latter is lower than +# half-round VIS timing, because there are 16 Xupdate-free rounds, +# which "push down" average theoretical timing to 8 cycles... + +# (*) SPARC64-V[II] was originally believed to have 2 cycles VIS +# latency. Well, it might have, but it doesn't have dedicated +# VIS-unit. Instead, VIS instructions are executed by other +# functional units, ones used here - by IALU. This doesn't +# improve effective ILP... +} + +# The reference Xupdate procedure is then "strained" over *pairs* of +# BODY_NN_MM and kind of modulo-scheduled in respect to X[n]^=X[n+13] +# and K_NN_MM addition. It's "running" 15 rounds ahead, which leaves +# plenty of room to amortize for read-after-write hazard, as well as +# to fetch and align input for the next spin. The VIS instructions are +# scheduled for latency of 2 cycles, because there are not enough IALU +# instructions to schedule for latency of 3, while scheduling for 1 +# would give no gain on USI&II anyway. + +sub BODY_00_19 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i&~1; +my $k=($j+16+2)%16; # ahead reference +my $l=($j+16-2)%16; # behind reference +my $K=@VK[($j+16-2)/20]; + +$j=($j+16)%16; + +$code.=<<___ if (!($i&1)); + sll $a,5,$tmp0 !! $i + and $c,$b,$tmp3 + ld [$Xfer+`4*($i%16)`],$Xi + fxors @X[($j+14)%16],@X[$j+1],@X[$j+1]! 0/ 0/ 0:X[1]^=X[14] + srl $a,27,$tmp1 + add $tmp0,$e,$e + fxor @X[($j+2)%16],@X[($j+8)%16],%f18! 1/ 1/ 1:Tmp=X[2,3]^X[8,9] + sll $b,30,$tmp2 + add $tmp1,$e,$e + andn $d,$b,$tmp1 + add $Xi,$e,$e + fxor %f18,@X[$j],@X[$j] ! 2/ 4/ 3:X[0,1]^=X[2,3]^X[8,9] + srl $b,2,$b + or $tmp1,$tmp3,$tmp1 + or $tmp2,$b,$b + add $tmp1,$e,$e + faligndata @X[$j],@X[$j],%f18 ! 3/ 7/ 5:Tmp=X[0,1]>>>24 +___ +$code.=<<___ if ($i&1); + sll $a,5,$tmp0 !! $i + and $c,$b,$tmp3 + ld [$Xfer+`4*($i%16)`],$Xi + fpadd32 @X[$j],@X[$j],@X[$j] ! 4/ 8/ 6:X[0,1]<<=1 + srl $a,27,$tmp1 + add $tmp0,$e,$e + fmul8ulx16 %f18,$fmul,%f18 ! 5/10/ 7:Tmp>>=7, Tmp&=1 + sll $b,30,$tmp2 + add $tmp1,$e,$e + fpadd32 $K,@X[$l],%f20 ! + andn $d,$b,$tmp1 + add $Xi,$e,$e + fxors @X[($k+13)%16],@X[$k],@X[$k] !-1/-1/-1:X[0]^=X[13] + srl $b,2,$b + or $tmp1,$tmp3,$tmp1 + fxor %f18,@X[$j],@X[$j] ! 8/14/10:X[0,1]|=Tmp + or $tmp2,$b,$b + add $tmp1,$e,$e +___ +$code.=<<___ if ($i&1 && $i>=2); + std %f20,[$Xfer+`4*$l`] ! +___ +} + +sub BODY_20_39 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i&~1; +my $k=($j+16+2)%16; # ahead reference +my $l=($j+16-2)%16; # behind reference +my $K=@VK[($j+16-2)/20]; + +$j=($j+16)%16; + +$code.=<<___ if (!($i&1) && $i<64); + sll $a,5,$tmp0 !! $i + ld [$Xfer+`4*($i%16)`],$Xi + fxors @X[($j+14)%16],@X[$j+1],@X[$j+1]! 0/ 0/ 0:X[1]^=X[14] + srl $a,27,$tmp1 + add $tmp0,$e,$e + fxor @X[($j+2)%16],@X[($j+8)%16],%f18! 1/ 1/ 1:Tmp=X[2,3]^X[8,9] + xor $c,$b,$tmp0 + add $tmp1,$e,$e + sll $b,30,$tmp2 + xor $d,$tmp0,$tmp1 + fxor %f18,@X[$j],@X[$j] ! 2/ 4/ 3:X[0,1]^=X[2,3]^X[8,9] + srl $b,2,$b + add $tmp1,$e,$e + or $tmp2,$b,$b + add $Xi,$e,$e + faligndata @X[$j],@X[$j],%f18 ! 3/ 7/ 5:Tmp=X[0,1]>>>24 +___ +$code.=<<___ if ($i&1 && $i<64); + sll $a,5,$tmp0 !! $i + ld [$Xfer+`4*($i%16)`],$Xi + fpadd32 @X[$j],@X[$j],@X[$j] ! 4/ 8/ 6:X[0,1]<<=1 + srl $a,27,$tmp1 + add $tmp0,$e,$e + fmul8ulx16 %f18,$fmul,%f18 ! 5/10/ 7:Tmp>>=7, Tmp&=1 + xor $c,$b,$tmp0 + add $tmp1,$e,$e + fpadd32 $K,@X[$l],%f20 ! + sll $b,30,$tmp2 + xor $d,$tmp0,$tmp1 + fxors @X[($k+13)%16],@X[$k],@X[$k] !-1/-1/-1:X[0]^=X[13] + srl $b,2,$b + add $tmp1,$e,$e + fxor %f18,@X[$j],@X[$j] ! 8/14/10:X[0,1]|=Tmp + or $tmp2,$b,$b + add $Xi,$e,$e + std %f20,[$Xfer+`4*$l`] ! +___ +$code.=<<___ if ($i==64); + sll $a,5,$tmp0 !! $i + ld [$Xfer+`4*($i%16)`],$Xi + fpadd32 $K,@X[$l],%f20 + srl $a,27,$tmp1 + add $tmp0,$e,$e + xor $c,$b,$tmp0 + add $tmp1,$e,$e + sll $b,30,$tmp2 + xor $d,$tmp0,$tmp1 + std %f20,[$Xfer+`4*$l`] + srl $b,2,$b + add $tmp1,$e,$e + or $tmp2,$b,$b + add $Xi,$e,$e +___ +$code.=<<___ if ($i>64); + sll $a,5,$tmp0 !! $i + ld [$Xfer+`4*($i%16)`],$Xi + srl $a,27,$tmp1 + add $tmp0,$e,$e + xor $c,$b,$tmp0 + add $tmp1,$e,$e + sll $b,30,$tmp2 + xor $d,$tmp0,$tmp1 + srl $b,2,$b + add $tmp1,$e,$e + or $tmp2,$b,$b + add $Xi,$e,$e +___ +} + +sub BODY_40_59 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i&~1; +my $k=($j+16+2)%16; # ahead reference +my $l=($j+16-2)%16; # behind reference +my $K=@VK[($j+16-2)/20]; + +$j=($j+16)%16; + +$code.=<<___ if (!($i&1)); + sll $a,5,$tmp0 !! $i + ld [$Xfer+`4*($i%16)`],$Xi + fxors @X[($j+14)%16],@X[$j+1],@X[$j+1]! 0/ 0/ 0:X[1]^=X[14] + srl $a,27,$tmp1 + add $tmp0,$e,$e + fxor @X[($j+2)%16],@X[($j+8)%16],%f18! 1/ 1/ 1:Tmp=X[2,3]^X[8,9] + and $c,$b,$tmp0 + add $tmp1,$e,$e + sll $b,30,$tmp2 + or $c,$b,$tmp1 + fxor %f18,@X[$j],@X[$j] ! 2/ 4/ 3:X[0,1]^=X[2,3]^X[8,9] + srl $b,2,$b + and $d,$tmp1,$tmp1 + add $Xi,$e,$e + or $tmp1,$tmp0,$tmp1 + faligndata @X[$j],@X[$j],%f18 ! 3/ 7/ 5:Tmp=X[0,1]>>>24 + or $tmp2,$b,$b + add $tmp1,$e,$e + fpadd32 @X[$j],@X[$j],@X[$j] ! 4/ 8/ 6:X[0,1]<<=1 +___ +$code.=<<___ if ($i&1); + sll $a,5,$tmp0 !! $i + ld [$Xfer+`4*($i%16)`],$Xi + srl $a,27,$tmp1 + add $tmp0,$e,$e + fmul8ulx16 %f18,$fmul,%f18 ! 5/10/ 7:Tmp>>=7, Tmp&=1 + and $c,$b,$tmp0 + add $tmp1,$e,$e + fpadd32 $K,@X[$l],%f20 ! + sll $b,30,$tmp2 + or $c,$b,$tmp1 + fxors @X[($k+13)%16],@X[$k],@X[$k] !-1/-1/-1:X[0]^=X[13] + srl $b,2,$b + and $d,$tmp1,$tmp1 + fxor %f18,@X[$j],@X[$j] ! 8/14/10:X[0,1]|=Tmp + add $Xi,$e,$e + or $tmp1,$tmp0,$tmp1 + or $tmp2,$b,$b + add $tmp1,$e,$e + std %f20,[$Xfer+`4*$l`] ! +___ +} + +# If there is more data to process, then we pre-fetch the data for +# next iteration in last ten rounds... +sub BODY_70_79 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i&~1; +my $m=($i%8)*2; + +$j=($j+16)%16; + +$code.=<<___ if ($i==70); + sll $a,5,$tmp0 !! $i + ld [$Xfer+`4*($i%16)`],$Xi + srl $a,27,$tmp1 + add $tmp0,$e,$e + ldd [$inp+64],@X[0] + xor $c,$b,$tmp0 + add $tmp1,$e,$e + sll $b,30,$tmp2 + xor $d,$tmp0,$tmp1 + srl $b,2,$b + add $tmp1,$e,$e + or $tmp2,$b,$b + add $Xi,$e,$e + + and $inp,-64,$nXfer + inc 64,$inp + and $nXfer,255,$nXfer + alignaddr %g0,$align,%g0 + add $base,$nXfer,$nXfer +___ +$code.=<<___ if ($i==71); + sll $a,5,$tmp0 !! $i + ld [$Xfer+`4*($i%16)`],$Xi + srl $a,27,$tmp1 + add $tmp0,$e,$e + xor $c,$b,$tmp0 + add $tmp1,$e,$e + sll $b,30,$tmp2 + xor $d,$tmp0,$tmp1 + srl $b,2,$b + add $tmp1,$e,$e + or $tmp2,$b,$b + add $Xi,$e,$e +___ +$code.=<<___ if ($i>=72); + faligndata @X[$m],@X[$m+2],@X[$m] + sll $a,5,$tmp0 !! $i + ld [$Xfer+`4*($i%16)`],$Xi + srl $a,27,$tmp1 + add $tmp0,$e,$e + xor $c,$b,$tmp0 + add $tmp1,$e,$e + fpadd32 $VK_00_19,@X[$m],%f20 + sll $b,30,$tmp2 + xor $d,$tmp0,$tmp1 + srl $b,2,$b + add $tmp1,$e,$e + or $tmp2,$b,$b + add $Xi,$e,$e +___ +$code.=<<___ if ($i<77); + ldd [$inp+`8*($i+1-70)`],@X[2*($i+1-70)] +___ +$code.=<<___ if ($i==77); # redundant if $inp was aligned + add $align,63,$tmp0 + and $tmp0,-8,$tmp0 + ldd [$inp+$tmp0],@X[16] +___ +$code.=<<___ if ($i>=72); + std %f20,[$nXfer+`4*$m`] +___ +} + +$code.=<<___; +.section ".text",#alloc,#execinstr + +.align 64 +vis_const: +.long 0x5a827999,0x5a827999 ! K_00_19 +.long 0x6ed9eba1,0x6ed9eba1 ! K_20_39 +.long 0x8f1bbcdc,0x8f1bbcdc ! K_40_59 +.long 0xca62c1d6,0xca62c1d6 ! K_60_79 +.long 0x00000100,0x00000100 +.align 64 +.type vis_const,#object +.size vis_const,(.-vis_const) + +.globl sha1_block_data_order +sha1_block_data_order: + save %sp,-$frame,%sp + add %fp,$bias-256,$base + +1: call .+8 + add %o7,vis_const-1b,$tmp0 + + ldd [$tmp0+0],$VK_00_19 + ldd [$tmp0+8],$VK_20_39 + ldd [$tmp0+16],$VK_40_59 + ldd [$tmp0+24],$VK_60_79 + ldd [$tmp0+32],$fmul + + ld [$ctx+0],$Actx + and $base,-256,$base + ld [$ctx+4],$Bctx + sub $base,$bias+$frame,%sp + ld [$ctx+8],$Cctx + and $inp,7,$align + ld [$ctx+12],$Dctx + and $inp,-8,$inp + ld [$ctx+16],$Ectx + + ! X[16] is maintained in FP register bank + alignaddr %g0,$align,%g0 + ldd [$inp+0],@X[0] + sub $inp,-64,$Xfer + ldd [$inp+8],@X[2] + and $Xfer,-64,$Xfer + ldd [$inp+16],@X[4] + and $Xfer,255,$Xfer + ldd [$inp+24],@X[6] + add $base,$Xfer,$Xfer + ldd [$inp+32],@X[8] + ldd [$inp+40],@X[10] + ldd [$inp+48],@X[12] + brz,pt $align,.Laligned + ldd [$inp+56],@X[14] + + ldd [$inp+64],@X[16] + faligndata @X[0],@X[2],@X[0] + faligndata @X[2],@X[4],@X[2] + faligndata @X[4],@X[6],@X[4] + faligndata @X[6],@X[8],@X[6] + faligndata @X[8],@X[10],@X[8] + faligndata @X[10],@X[12],@X[10] + faligndata @X[12],@X[14],@X[12] + faligndata @X[14],@X[16],@X[14] + +.Laligned: + mov 5,$tmp0 + dec 1,$len + alignaddr %g0,$tmp0,%g0 + fpadd32 $VK_00_19,@X[0],%f16 + fpadd32 $VK_00_19,@X[2],%f18 + fpadd32 $VK_00_19,@X[4],%f20 + fpadd32 $VK_00_19,@X[6],%f22 + fpadd32 $VK_00_19,@X[8],%f24 + fpadd32 $VK_00_19,@X[10],%f26 + fpadd32 $VK_00_19,@X[12],%f28 + fpadd32 $VK_00_19,@X[14],%f30 + std %f16,[$Xfer+0] + mov $Actx,$A + std %f18,[$Xfer+8] + mov $Bctx,$B + std %f20,[$Xfer+16] + mov $Cctx,$C + std %f22,[$Xfer+24] + mov $Dctx,$D + std %f24,[$Xfer+32] + mov $Ectx,$E + std %f26,[$Xfer+40] + fxors @X[13],@X[0],@X[0] + std %f28,[$Xfer+48] + ba .Loop + std %f30,[$Xfer+56] +.align 32 +.Loop: +___ +for ($i=0;$i<20;$i++) { &BODY_00_19($i,@V); unshift(@V,pop(@V)); } +for (;$i<40;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); } +for (;$i<60;$i++) { &BODY_40_59($i,@V); unshift(@V,pop(@V)); } +for (;$i<70;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + tst $len + bz,pn `$bits==32?"%icc":"%xcc"`,.Ltail + nop +___ +for (;$i<80;$i++) { &BODY_70_79($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + add $A,$Actx,$Actx + add $B,$Bctx,$Bctx + add $C,$Cctx,$Cctx + add $D,$Dctx,$Dctx + add $E,$Ectx,$Ectx + mov 5,$tmp0 + fxors @X[13],@X[0],@X[0] + mov $Actx,$A + mov $Bctx,$B + mov $Cctx,$C + mov $Dctx,$D + mov $Ectx,$E + alignaddr %g0,$tmp0,%g0 + dec 1,$len + ba .Loop + mov $nXfer,$Xfer + +.align 32 +.Ltail: +___ +for($i=70;$i<80;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + add $A,$Actx,$Actx + add $B,$Bctx,$Bctx + add $C,$Cctx,$Cctx + add $D,$Dctx,$Dctx + add $E,$Ectx,$Ectx + + st $Actx,[$ctx+0] + st $Bctx,[$ctx+4] + st $Cctx,[$ctx+8] + st $Dctx,[$ctx+12] + st $Ectx,[$ctx+16] + + ret + restore +.type sha1_block_data_order,#function +.size sha1_block_data_order,(.-sha1_block_data_order) +.asciz "SHA1 block transform for SPARCv9a, CRYPTOGAMS by " +.align 4 +___ + +# Purpose of these subroutines is to explicitly encode VIS instructions, +# so that one can compile the module without having to specify VIS +# extensions on compiler command line, e.g. -xarch=v9 vs. -xarch=v9a. +# Idea is to reserve for option to produce "universal" binary and let +# programmer detect if current CPU is VIS capable at run-time. +sub unvis { +my ($mnemonic,$rs1,$rs2,$rd)=@_; +my ($ref,$opf); +my %visopf = ( "fmul8ulx16" => 0x037, + "faligndata" => 0x048, + "fpadd32" => 0x052, + "fxor" => 0x06c, + "fxors" => 0x06d ); + + $ref = "$mnemonic\t$rs1,$rs2,$rd"; + + if ($opf=$visopf{$mnemonic}) { + foreach ($rs1,$rs2,$rd) { + return $ref if (!/%f([0-9]{1,2})/); + $_=$1; + if ($1>=32) { + return $ref if ($1&1); + # re-encode for upper double register addressing + $_=($1|$1>>5)&31; + } + } + + return sprintf ".word\t0x%08x !%s", + 0x81b00000|$rd<<25|$rs1<<14|$opf<<5|$rs2, + $ref; + } else { + return $ref; + } +} +sub unalignaddr { +my ($mnemonic,$rs1,$rs2,$rd)=@_; +my %bias = ( "g" => 0, "o" => 8, "l" => 16, "i" => 24 ); +my $ref="$mnemonic\t$rs1,$rs2,$rd"; + + foreach ($rs1,$rs2,$rd) { + if (/%([goli])([0-7])/) { $_=$bias{$1}+$2; } + else { return $ref; } + } + return sprintf ".word\t0x%08x !%s", + 0x81b00300|$rd<<25|$rs1<<14|$rs2, + $ref; +} + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +$code =~ s/\b(f[^\s]*)\s+(%f[0-9]{1,2}),(%f[0-9]{1,2}),(%f[0-9]{1,2})/ + &unvis($1,$2,$3,$4) + /gem; +$code =~ s/\b(alignaddr)\s+(%[goli][0-7]),(%[goli][0-7]),(%[goli][0-7])/ + &unalignaddr($1,$2,$3,$4) + /gem; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-thumb.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-thumb.pl new file mode 100644 index 000000000..ac74a25d6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-thumb.pl @@ -0,0 +1,266 @@ +#! /usr/bin/env perl +# Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# sha1_block for Thumb. +# +# January 2007. +# +# The code does not present direct interest to OpenSSL, because of low +# performance. Its purpose is to establish _size_ benchmark. Pretty +# useless one I must say, because 30% or 88 bytes larger ARMv4 code +# [available on demand] is almost _twice_ as fast. It should also be +# noted that in-lining of .Lcommon and .Lrotate improves performance +# by over 40%, while code increases by only 10% or 32 bytes. But once +# again, the goal was to establish _size_ benchmark, not performance. + +$output=shift; +open STDOUT,">$output"; + +$inline=0; +#$cheat_on_binutils=1; + +$t0="r0"; +$t1="r1"; +$t2="r2"; +$a="r3"; +$b="r4"; +$c="r5"; +$d="r6"; +$e="r7"; +$K="r8"; # "upper" registers can be used in add/sub and mov insns +$ctx="r9"; +$inp="r10"; +$len="r11"; +$Xi="r12"; + +sub common { +<<___; + sub $t0,#4 + ldr $t1,[$t0] + add $e,$K @ E+=K_xx_xx + lsl $t2,$a,#5 + add $t2,$e + lsr $e,$a,#27 + add $t2,$e @ E+=ROR(A,27) + add $t2,$t1 @ E+=X[i] +___ +} +sub rotate { +<<___; + mov $e,$d @ E=D + mov $d,$c @ D=C + lsl $c,$b,#30 + lsr $b,$b,#2 + orr $c,$b @ C=ROR(B,2) + mov $b,$a @ B=A + add $a,$t2,$t1 @ A=E+F_xx_xx(B,C,D) +___ +} + +sub BODY_00_19 { +$code.=$inline?&common():"\tbl .Lcommon\n"; +$code.=<<___; + mov $t1,$c + eor $t1,$d + and $t1,$b + eor $t1,$d @ F_00_19(B,C,D) +___ +$code.=$inline?&rotate():"\tbl .Lrotate\n"; +} + +sub BODY_20_39 { +$code.=$inline?&common():"\tbl .Lcommon\n"; +$code.=<<___; + mov $t1,$b + eor $t1,$c + eor $t1,$d @ F_20_39(B,C,D) +___ +$code.=$inline?&rotate():"\tbl .Lrotate\n"; +} + +sub BODY_40_59 { +$code.=$inline?&common():"\tbl .Lcommon\n"; +$code.=<<___; + mov $t1,$b + and $t1,$c + mov $e,$b + orr $e,$c + and $e,$d + orr $t1,$e @ F_40_59(B,C,D) +___ +$code.=$inline?&rotate():"\tbl .Lrotate\n"; +} + +$code=<<___; +.text +.code 16 + +.global sha1_block_data_order +.type sha1_block_data_order,%function + +.align 2 +sha1_block_data_order: +___ +if ($cheat_on_binutils) { +$code.=<<___; +.code 32 + add r3,pc,#1 + bx r3 @ switch to Thumb ISA +.code 16 +___ +} +$code.=<<___; + push {r4-r7} + mov r3,r8 + mov r4,r9 + mov r5,r10 + mov r6,r11 + mov r7,r12 + push {r3-r7,lr} + lsl r2,#6 + mov $ctx,r0 @ save context + mov $inp,r1 @ save inp + mov $len,r2 @ save len + add $len,$inp @ $len to point at inp end + +.Lloop: + mov $Xi,sp + mov $t2,sp + sub $t2,#16*4 @ [3] +.LXload: + ldrb $a,[$t1,#0] @ $t1 is r1 and holds inp + ldrb $b,[$t1,#1] + ldrb $c,[$t1,#2] + ldrb $d,[$t1,#3] + lsl $a,#24 + lsl $b,#16 + lsl $c,#8 + orr $a,$b + orr $a,$c + orr $a,$d + add $t1,#4 + push {$a} + cmp sp,$t2 + bne .LXload @ [+14*16] + + mov $inp,$t1 @ update $inp + sub $t2,#32*4 + sub $t2,#32*4 + mov $e,#31 @ [+4] +.LXupdate: + ldr $a,[sp,#15*4] + ldr $b,[sp,#13*4] + ldr $c,[sp,#7*4] + ldr $d,[sp,#2*4] + eor $a,$b + eor $a,$c + eor $a,$d + ror $a,$e + push {$a} + cmp sp,$t2 + bne .LXupdate @ [+(11+1)*64] + + ldmia $t0!,{$a,$b,$c,$d,$e} @ $t0 is r0 and holds ctx + mov $t0,$Xi + + ldr $t2,.LK_00_19 + mov $t1,$t0 + sub $t1,#20*4 + mov $Xi,$t1 + mov $K,$t2 @ [+7+4] +.L_00_19: +___ + &BODY_00_19(); +$code.=<<___; + cmp $Xi,$t0 + bne .L_00_19 @ [+(2+9+4+2+8+2)*20] + + ldr $t2,.LK_20_39 + mov $t1,$t0 + sub $t1,#20*4 + mov $Xi,$t1 + mov $K,$t2 @ [+5] +.L_20_39_or_60_79: +___ + &BODY_20_39(); +$code.=<<___; + cmp $Xi,$t0 + bne .L_20_39_or_60_79 @ [+(2+9+3+2+8+2)*20*2] + cmp sp,$t0 + beq .Ldone @ [+2] + + ldr $t2,.LK_40_59 + mov $t1,$t0 + sub $t1,#20*4 + mov $Xi,$t1 + mov $K,$t2 @ [+5] +.L_40_59: +___ + &BODY_40_59(); +$code.=<<___; + cmp $Xi,$t0 + bne .L_40_59 @ [+(2+9+6+2+8+2)*20] + + ldr $t2,.LK_60_79 + mov $Xi,sp + mov $K,$t2 + b .L_20_39_or_60_79 @ [+4] +.Ldone: + mov $t0,$ctx + ldr $t1,[$t0,#0] + ldr $t2,[$t0,#4] + add $a,$t1 + ldr $t1,[$t0,#8] + add $b,$t2 + ldr $t2,[$t0,#12] + add $c,$t1 + ldr $t1,[$t0,#16] + add $d,$t2 + add $e,$t1 + stmia $t0!,{$a,$b,$c,$d,$e} @ [+20] + + add sp,#80*4 @ deallocate stack frame + mov $t0,$ctx @ restore ctx + mov $t1,$inp @ restore inp + cmp $t1,$len + beq .Lexit + b .Lloop @ [+6] total 3212 cycles +.Lexit: + pop {r2-r7} + mov r8,r2 + mov r9,r3 + mov r10,r4 + mov r11,r5 + mov r12,r6 + mov lr,r7 + pop {r4-r7} + bx lr +.align 2 +___ +$code.=".Lcommon:\n".&common()."\tmov pc,lr\n" if (!$inline); +$code.=".Lrotate:\n".&rotate()."\tmov pc,lr\n" if (!$inline); +$code.=<<___; +.align 2 +.LK_00_19: .word 0x5a827999 +.LK_20_39: .word 0x6ed9eba1 +.LK_40_59: .word 0x8f1bbcdc +.LK_60_79: .word 0xca62c1d6 +.size sha1_block_data_order,.-sha1_block_data_order +.asciz "SHA1 block transform for Thumb, CRYPTOGAMS by " +___ + +print $code; +close STDOUT; # enforce flush diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-x86_64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-x86_64.pl new file mode 100755 index 000000000..60819f618 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha1-x86_64.pl @@ -0,0 +1,2132 @@ +#! /usr/bin/env perl +# Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# sha1_block procedure for x86_64. +# +# It was brought to my attention that on EM64T compiler-generated code +# was far behind 32-bit assembler implementation. This is unlike on +# Opteron where compiler-generated code was only 15% behind 32-bit +# assembler, which originally made it hard to motivate the effort. +# There was suggestion to mechanically translate 32-bit code, but I +# dismissed it, reasoning that x86_64 offers enough register bank +# capacity to fully utilize SHA-1 parallelism. Therefore this fresh +# implementation:-) However! While 64-bit code does perform better +# on Opteron, I failed to beat 32-bit assembler on EM64T core. Well, +# x86_64 does offer larger *addressable* bank, but out-of-order core +# reaches for even more registers through dynamic aliasing, and EM64T +# core must have managed to run-time optimize even 32-bit code just as +# good as 64-bit one. Performance improvement is summarized in the +# following table: +# +# gcc 3.4 32-bit asm cycles/byte +# Opteron +45% +20% 6.8 +# Xeon P4 +65% +0% 9.9 +# Core2 +60% +10% 7.0 + +# August 2009. +# +# The code was revised to minimize code size and to maximize +# "distance" between instructions producing input to 'lea' +# instruction and the 'lea' instruction itself, which is essential +# for Intel Atom core. + +# October 2010. +# +# Add SSSE3, Supplemental[!] SSE3, implementation. The idea behind it +# is to offload message schedule denoted by Wt in NIST specification, +# or Xupdate in OpenSSL source, to SIMD unit. See sha1-586.pl module +# for background and implementation details. The only difference from +# 32-bit code is that 64-bit code doesn't have to spill @X[] elements +# to free temporary registers. + +# April 2011. +# +# Add AVX code path. See sha1-586.pl for further information. + +# May 2013. +# +# Add AVX2+BMI code path. Initial attempt (utilizing BMI instructions +# and loading pair of consecutive blocks to 256-bit %ymm registers) +# did not provide impressive performance improvement till a crucial +# hint regarding the number of Xupdate iterations to pre-compute in +# advance was provided by Ilya Albrekht of Intel Corp. + +# March 2014. +# +# Add support for Intel SHA Extensions. + +###################################################################### +# Current performance is summarized in following table. Numbers are +# CPU clock cycles spent to process single byte (less is better). +# +# x86_64 SSSE3 AVX[2] +# P4 9.05 - +# Opteron 6.26 - +# Core2 6.55 6.05/+8% - +# Westmere 6.73 5.30/+27% - +# Sandy Bridge 7.70 6.10/+26% 4.99/+54% +# Ivy Bridge 6.06 4.67/+30% 4.60/+32% +# Haswell 5.45 4.15/+31% 3.57/+53% +# Skylake 5.18 4.06/+28% 3.54/+46% +# Bulldozer 9.11 5.95/+53% +# Ryzen 4.75 3.80/+24% 1.93/+150%(**) +# VIA Nano 9.32 7.15/+30% +# Atom 10.3 9.17/+12% +# Silvermont 13.1(*) 9.37/+40% +# Knights L 13.2(*) 9.68/+36% 8.30/+59% +# Goldmont 8.13 6.42/+27% 1.70/+380%(**) +# +# (*) obviously suboptimal result, nothing was done about it, +# because SSSE3 code is compiled unconditionally; +# (**) SHAEXT result + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler version ([2-9]\.[0-9]+)/) { + $avx = ($1>=2.19) + ($1>=2.22); +} + +if (!$avx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) && + `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) { + $avx = ($1>=2.09) + ($1>=2.10); +} + +if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && + `ml64 2>&1` =~ /Version ([0-9]+)\./) { + $avx = ($1>=10) + ($1>=11); +} + +if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([2-9]\.[0-9]+)/) { + $avx = ($2>=3.0) + ($2>3.0); +} + +$shaext=1; ### set to zero if compiling for 1.0.1 +$avx=1 if (!$shaext && $avx); + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +*STDOUT=*OUT; + +$ctx="%rdi"; # 1st arg +$inp="%rsi"; # 2nd arg +$num="%rdx"; # 3rd arg + +# reassign arguments in order to produce more compact code +$ctx="%r8"; +$inp="%r9"; +$num="%r10"; + +$t0="%eax"; +$t1="%ebx"; +$t2="%ecx"; +@xi=("%edx","%ebp","%r14d"); +$A="%esi"; +$B="%edi"; +$C="%r11d"; +$D="%r12d"; +$E="%r13d"; + +@V=($A,$B,$C,$D,$E); + +sub BODY_00_19 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i+1; +$code.=<<___ if ($i==0); + mov `4*$i`($inp),$xi[0] + bswap $xi[0] +___ +$code.=<<___ if ($i<15); + mov `4*$j`($inp),$xi[1] + mov $d,$t0 + mov $xi[0],`4*$i`(%rsp) + mov $a,$t2 + bswap $xi[1] + xor $c,$t0 + rol \$5,$t2 + and $b,$t0 + lea 0x5a827999($xi[0],$e),$e + add $t2,$e + xor $d,$t0 + rol \$30,$b + add $t0,$e +___ +$code.=<<___ if ($i>=15); + xor `4*($j%16)`(%rsp),$xi[1] + mov $d,$t0 + mov $xi[0],`4*($i%16)`(%rsp) + mov $a,$t2 + xor `4*(($j+2)%16)`(%rsp),$xi[1] + xor $c,$t0 + rol \$5,$t2 + xor `4*(($j+8)%16)`(%rsp),$xi[1] + and $b,$t0 + lea 0x5a827999($xi[0],$e),$e + rol \$30,$b + xor $d,$t0 + add $t2,$e + rol \$1,$xi[1] + add $t0,$e +___ +push(@xi,shift(@xi)); +} + +sub BODY_20_39 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i+1; +my $K=($i<40)?0x6ed9eba1:0xca62c1d6; +$code.=<<___ if ($i<79); + xor `4*($j%16)`(%rsp),$xi[1] + mov $b,$t0 + `"mov $xi[0],".4*($i%16)."(%rsp)" if ($i<72)` + mov $a,$t2 + xor `4*(($j+2)%16)`(%rsp),$xi[1] + xor $d,$t0 + rol \$5,$t2 + xor `4*(($j+8)%16)`(%rsp),$xi[1] + lea $K($xi[0],$e),$e + xor $c,$t0 + add $t2,$e + rol \$30,$b + add $t0,$e + rol \$1,$xi[1] +___ +$code.=<<___ if ($i==79); + mov $b,$t0 + mov $a,$t2 + xor $d,$t0 + lea $K($xi[0],$e),$e + rol \$5,$t2 + xor $c,$t0 + add $t2,$e + rol \$30,$b + add $t0,$e +___ +push(@xi,shift(@xi)); +} + +sub BODY_40_59 { +my ($i,$a,$b,$c,$d,$e)=@_; +my $j=$i+1; +$code.=<<___; + xor `4*($j%16)`(%rsp),$xi[1] + mov $d,$t0 + mov $xi[0],`4*($i%16)`(%rsp) + mov $d,$t1 + xor `4*(($j+2)%16)`(%rsp),$xi[1] + and $c,$t0 + mov $a,$t2 + xor `4*(($j+8)%16)`(%rsp),$xi[1] + lea 0x8f1bbcdc($xi[0],$e),$e + xor $c,$t1 + rol \$5,$t2 + add $t0,$e + rol \$1,$xi[1] + and $b,$t1 + add $t2,$e + rol \$30,$b + add $t1,$e +___ +push(@xi,shift(@xi)); +} + +$code.=<<___; +.text +.extern OPENSSL_ia32cap_P + +.globl sha1_block_data_order +.type sha1_block_data_order,\@function,3 +.align 16 +sha1_block_data_order: +.cfi_startproc + mov OPENSSL_ia32cap_P+0(%rip),%r9d + mov OPENSSL_ia32cap_P+4(%rip),%r8d + mov OPENSSL_ia32cap_P+8(%rip),%r10d + test \$`1<<9`,%r8d # check SSSE3 bit + jz .Lialu +___ +$code.=<<___ if ($shaext); + test \$`1<<29`,%r10d # check SHA bit + jnz _shaext_shortcut +___ +$code.=<<___ if ($avx>1); + and \$`1<<3|1<<5|1<<8`,%r10d # check AVX2+BMI1+BMI2 + cmp \$`1<<3|1<<5|1<<8`,%r10d + je _avx2_shortcut +___ +$code.=<<___ if ($avx); + and \$`1<<28`,%r8d # mask AVX bit + and \$`1<<30`,%r9d # mask "Intel CPU" bit + or %r9d,%r8d + cmp \$`1<<28|1<<30`,%r8d + je _avx_shortcut +___ +$code.=<<___; + jmp _ssse3_shortcut + +.align 16 +.Lialu: + mov %rsp,%rax +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + mov %rdi,$ctx # reassigned argument + sub \$`8+16*4`,%rsp + mov %rsi,$inp # reassigned argument + and \$-64,%rsp + mov %rdx,$num # reassigned argument + mov %rax,`16*4`(%rsp) +.cfi_cfa_expression %rsp+64,deref,+8 +.Lprologue: + + mov 0($ctx),$A + mov 4($ctx),$B + mov 8($ctx),$C + mov 12($ctx),$D + mov 16($ctx),$E + jmp .Lloop + +.align 16 +.Lloop: +___ +for($i=0;$i<20;$i++) { &BODY_00_19($i,@V); unshift(@V,pop(@V)); } +for(;$i<40;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); } +for(;$i<60;$i++) { &BODY_40_59($i,@V); unshift(@V,pop(@V)); } +for(;$i<80;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + add 0($ctx),$A + add 4($ctx),$B + add 8($ctx),$C + add 12($ctx),$D + add 16($ctx),$E + mov $A,0($ctx) + mov $B,4($ctx) + mov $C,8($ctx) + mov $D,12($ctx) + mov $E,16($ctx) + + sub \$1,$num + lea `16*4`($inp),$inp + jnz .Lloop + + mov `16*4`(%rsp),%rsi +.cfi_def_cfa %rsi,8 + mov -40(%rsi),%r14 +.cfi_restore %r14 + mov -32(%rsi),%r13 +.cfi_restore %r13 + mov -24(%rsi),%r12 +.cfi_restore %r12 + mov -16(%rsi),%rbp +.cfi_restore %rbp + mov -8(%rsi),%rbx +.cfi_restore %rbx + lea (%rsi),%rsp +.cfi_def_cfa_register %rsp +.Lepilogue: + ret +.cfi_endproc +.size sha1_block_data_order,.-sha1_block_data_order +___ +if ($shaext) {{{ +###################################################################### +# Intel SHA Extensions implementation of SHA1 update function. +# +my ($ctx,$inp,$num)=("%rdi","%rsi","%rdx"); +my ($ABCD,$E,$E_,$BSWAP,$ABCD_SAVE,$E_SAVE)=map("%xmm$_",(0..3,8,9)); +my @MSG=map("%xmm$_",(4..7)); + +$code.=<<___; +.type sha1_block_data_order_shaext,\@function,3 +.align 32 +sha1_block_data_order_shaext: +_shaext_shortcut: +.cfi_startproc +___ +$code.=<<___ if ($win64); + lea `-8-4*16`(%rsp),%rsp + movaps %xmm6,-8-4*16(%rax) + movaps %xmm7,-8-3*16(%rax) + movaps %xmm8,-8-2*16(%rax) + movaps %xmm9,-8-1*16(%rax) +.Lprologue_shaext: +___ +$code.=<<___; + movdqu ($ctx),$ABCD + movd 16($ctx),$E + movdqa K_XX_XX+0xa0(%rip),$BSWAP # byte-n-word swap + + movdqu ($inp),@MSG[0] + pshufd \$0b00011011,$ABCD,$ABCD # flip word order + movdqu 0x10($inp),@MSG[1] + pshufd \$0b00011011,$E,$E # flip word order + movdqu 0x20($inp),@MSG[2] + pshufb $BSWAP,@MSG[0] + movdqu 0x30($inp),@MSG[3] + pshufb $BSWAP,@MSG[1] + pshufb $BSWAP,@MSG[2] + movdqa $E,$E_SAVE # offload $E + pshufb $BSWAP,@MSG[3] + jmp .Loop_shaext + +.align 16 +.Loop_shaext: + dec $num + lea 0x40($inp),%r8 # next input block + paddd @MSG[0],$E + cmovne %r8,$inp + movdqa $ABCD,$ABCD_SAVE # offload $ABCD +___ +for($i=0;$i<20-4;$i+=2) { +$code.=<<___; + sha1msg1 @MSG[1],@MSG[0] + movdqa $ABCD,$E_ + sha1rnds4 \$`int($i/5)`,$E,$ABCD # 0-3... + sha1nexte @MSG[1],$E_ + pxor @MSG[2],@MSG[0] + sha1msg1 @MSG[2],@MSG[1] + sha1msg2 @MSG[3],@MSG[0] + + movdqa $ABCD,$E + sha1rnds4 \$`int(($i+1)/5)`,$E_,$ABCD + sha1nexte @MSG[2],$E + pxor @MSG[3],@MSG[1] + sha1msg2 @MSG[0],@MSG[1] +___ + push(@MSG,shift(@MSG)); push(@MSG,shift(@MSG)); +} +$code.=<<___; + movdqu ($inp),@MSG[0] + movdqa $ABCD,$E_ + sha1rnds4 \$3,$E,$ABCD # 64-67 + sha1nexte @MSG[1],$E_ + movdqu 0x10($inp),@MSG[1] + pshufb $BSWAP,@MSG[0] + + movdqa $ABCD,$E + sha1rnds4 \$3,$E_,$ABCD # 68-71 + sha1nexte @MSG[2],$E + movdqu 0x20($inp),@MSG[2] + pshufb $BSWAP,@MSG[1] + + movdqa $ABCD,$E_ + sha1rnds4 \$3,$E,$ABCD # 72-75 + sha1nexte @MSG[3],$E_ + movdqu 0x30($inp),@MSG[3] + pshufb $BSWAP,@MSG[2] + + movdqa $ABCD,$E + sha1rnds4 \$3,$E_,$ABCD # 76-79 + sha1nexte $E_SAVE,$E + pshufb $BSWAP,@MSG[3] + + paddd $ABCD_SAVE,$ABCD + movdqa $E,$E_SAVE # offload $E + + jnz .Loop_shaext + + pshufd \$0b00011011,$ABCD,$ABCD + pshufd \$0b00011011,$E,$E + movdqu $ABCD,($ctx) + movd $E,16($ctx) +___ +$code.=<<___ if ($win64); + movaps -8-4*16(%rax),%xmm6 + movaps -8-3*16(%rax),%xmm7 + movaps -8-2*16(%rax),%xmm8 + movaps -8-1*16(%rax),%xmm9 + mov %rax,%rsp +.Lepilogue_shaext: +___ +$code.=<<___; +.cfi_endproc + ret +.size sha1_block_data_order_shaext,.-sha1_block_data_order_shaext +___ +}}} +{{{ +my $Xi=4; +my @X=map("%xmm$_",(4..7,0..3)); +my @Tx=map("%xmm$_",(8..10)); +my $Kx="%xmm11"; +my @V=($A,$B,$C,$D,$E)=("%eax","%ebx","%ecx","%edx","%ebp"); # size optimization +my @T=("%esi","%edi"); +my $j=0; +my $rx=0; +my $K_XX_XX="%r14"; +my $fp="%r11"; + +my $_rol=sub { &rol(@_) }; +my $_ror=sub { &ror(@_) }; + +{ my $sn; +sub align32() { + ++$sn; +$code.=<<___; + jmp .Lalign32_$sn # see "Decoded ICache" in manual +.align 32 +.Lalign32_$sn: +___ +} +} + +$code.=<<___; +.type sha1_block_data_order_ssse3,\@function,3 +.align 16 +sha1_block_data_order_ssse3: +_ssse3_shortcut: +.cfi_startproc + mov %rsp,$fp # frame pointer +.cfi_def_cfa_register $fp + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 # redundant, done to share Win64 SE handler +.cfi_push %r13 + push %r14 +.cfi_push %r14 + lea `-64-($win64?6*16:0)`(%rsp),%rsp +___ +$code.=<<___ if ($win64); + movaps %xmm6,-40-6*16($fp) + movaps %xmm7,-40-5*16($fp) + movaps %xmm8,-40-4*16($fp) + movaps %xmm9,-40-3*16($fp) + movaps %xmm10,-40-2*16($fp) + movaps %xmm11,-40-1*16($fp) +.Lprologue_ssse3: +___ +$code.=<<___; + and \$-64,%rsp + mov %rdi,$ctx # reassigned argument + mov %rsi,$inp # reassigned argument + mov %rdx,$num # reassigned argument + + shl \$6,$num + add $inp,$num + lea K_XX_XX+64(%rip),$K_XX_XX + + mov 0($ctx),$A # load context + mov 4($ctx),$B + mov 8($ctx),$C + mov 12($ctx),$D + mov $B,@T[0] # magic seed + mov 16($ctx),$E + mov $C,@T[1] + xor $D,@T[1] + and @T[1],@T[0] + + movdqa 64($K_XX_XX),@X[2] # pbswap mask + movdqa -64($K_XX_XX),@Tx[1] # K_00_19 + movdqu 0($inp),@X[-4&7] # load input to %xmm[0-3] + movdqu 16($inp),@X[-3&7] + movdqu 32($inp),@X[-2&7] + movdqu 48($inp),@X[-1&7] + pshufb @X[2],@X[-4&7] # byte swap + pshufb @X[2],@X[-3&7] + pshufb @X[2],@X[-2&7] + add \$64,$inp + paddd @Tx[1],@X[-4&7] # add K_00_19 + pshufb @X[2],@X[-1&7] + paddd @Tx[1],@X[-3&7] + paddd @Tx[1],@X[-2&7] + movdqa @X[-4&7],0(%rsp) # X[]+K xfer to IALU + psubd @Tx[1],@X[-4&7] # restore X[] + movdqa @X[-3&7],16(%rsp) + psubd @Tx[1],@X[-3&7] + movdqa @X[-2&7],32(%rsp) + psubd @Tx[1],@X[-2&7] + jmp .Loop_ssse3 +___ + +sub AUTOLOAD() # thunk [simplified] 32-bit style perlasm +{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; + my $arg = pop; + $arg = "\$$arg" if ($arg*1 eq $arg); + $code .= "\t$opcode\t".join(',',$arg,reverse @_)."\n"; +} + +sub Xupdate_ssse3_16_31() # recall that $Xi starts with 4 +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 40 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); # ror + &pshufd (@X[0],@X[-4&7],0xee); # was &movdqa (@X[0],@X[-3&7]); + eval(shift(@insns)); + &movdqa (@Tx[0],@X[-1&7]); + &paddd (@Tx[1],@X[-1&7]); + eval(shift(@insns)); + eval(shift(@insns)); + + &punpcklqdq(@X[0],@X[-3&7]); # compose "X[-14]" in "X[0]", was &palignr(@X[0],@X[-4&7],8); + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)); + &psrldq (@Tx[0],4); # "X[-3]", 3 dwords + eval(shift(@insns)); + eval(shift(@insns)); + + &pxor (@X[0],@X[-4&7]); # "X[0]"^="X[-16]" + eval(shift(@insns)); + eval(shift(@insns)); # ror + &pxor (@Tx[0],@X[-2&7]); # "X[-3]"^"X[-8]" + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &pxor (@X[0],@Tx[0]); # "X[0]"^="X[-3]"^"X[-8]" + eval(shift(@insns)); + eval(shift(@insns)); # rol + &movdqa (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU + eval(shift(@insns)); + eval(shift(@insns)); + + &movdqa (@Tx[2],@X[0]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # ror + &movdqa (@Tx[0],@X[0]); + eval(shift(@insns)); + + &pslldq (@Tx[2],12); # "X[0]"<<96, extract one dword + &paddd (@X[0],@X[0]); + eval(shift(@insns)); + eval(shift(@insns)); + + &psrld (@Tx[0],31); + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)); + &movdqa (@Tx[1],@Tx[2]); + eval(shift(@insns)); + eval(shift(@insns)); + + &psrld (@Tx[2],30); + eval(shift(@insns)); + eval(shift(@insns)); # ror + &por (@X[0],@Tx[0]); # "X[0]"<<<=1 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &pslld (@Tx[1],2); + &pxor (@X[0],@Tx[2]); + eval(shift(@insns)); + &movdqa (@Tx[2],eval(2*16*(($Xi)/5)-64)."($K_XX_XX)"); # K_XX_XX + eval(shift(@insns)); # rol + eval(shift(@insns)); + eval(shift(@insns)); + + &pxor (@X[0],@Tx[1]); # "X[0]"^=("X[0]">>96)<<<2 + &pshufd (@Tx[1],@X[-1&7],0xee) if ($Xi==7); # was &movdqa (@Tx[0],@X[-1&7]) in Xupdate_ssse3_32_79 + + foreach (@insns) { eval; } # remaining instructions [if any] + + $Xi++; push(@X,shift(@X)); # "rotate" X[] + push(@Tx,shift(@Tx)); +} + +sub Xupdate_ssse3_32_79() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 to 44 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)) if ($Xi==8); + &pxor (@X[0],@X[-4&7]); # "X[0]"="X[-32]"^"X[-16]" + eval(shift(@insns)) if ($Xi==8); + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + eval(shift(@insns)) if (@insns[1] =~ /_ror/); + eval(shift(@insns)) if (@insns[0] =~ /_ror/); + &punpcklqdq(@Tx[0],@X[-1&7]); # compose "X[-6]", was &palignr(@Tx[0],@X[-2&7],8); + eval(shift(@insns)); + eval(shift(@insns)); # rol + + &pxor (@X[0],@X[-7&7]); # "X[0]"^="X[-28]" + eval(shift(@insns)); + eval(shift(@insns)); + if ($Xi%5) { + &movdqa (@Tx[2],@Tx[1]);# "perpetuate" K_XX_XX... + } else { # ... or load next one + &movdqa (@Tx[2],eval(2*16*($Xi/5)-64)."($K_XX_XX)"); + } + eval(shift(@insns)); # ror + &paddd (@Tx[1],@X[-1&7]); + eval(shift(@insns)); + + &pxor (@X[0],@Tx[0]); # "X[0]"^="X[-6]" + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)) if (@insns[0] =~ /_ror/); + + &movdqa (@Tx[0],@X[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &movdqa (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU + eval(shift(@insns)); # ror + eval(shift(@insns)); + eval(shift(@insns)); # body_20_39 + + &pslld (@X[0],2); + eval(shift(@insns)); + eval(shift(@insns)); + &psrld (@Tx[0],30); + eval(shift(@insns)) if (@insns[0] =~ /_rol/);# rol + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # ror + + &por (@X[0],@Tx[0]); # "X[0]"<<<=2 + eval(shift(@insns)); + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)) if (@insns[1] =~ /_rol/); + eval(shift(@insns)) if (@insns[0] =~ /_rol/); + &pshufd(@Tx[1],@X[-1&7],0xee) if ($Xi<19); # was &movdqa (@Tx[1],@X[0]) + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)); + + foreach (@insns) { eval; } # remaining instructions + + $Xi++; push(@X,shift(@X)); # "rotate" X[] + push(@Tx,shift(@Tx)); +} + +sub Xuplast_ssse3_80() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &paddd (@Tx[1],@X[-1&7]); + eval(shift(@insns)); + eval(shift(@insns)); + + &movdqa (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer IALU + + foreach (@insns) { eval; } # remaining instructions + + &cmp ($inp,$num); + &je (".Ldone_ssse3"); + + unshift(@Tx,pop(@Tx)); + + &movdqa (@X[2],"64($K_XX_XX)"); # pbswap mask + &movdqa (@Tx[1],"-64($K_XX_XX)"); # K_00_19 + &movdqu (@X[-4&7],"0($inp)"); # load input + &movdqu (@X[-3&7],"16($inp)"); + &movdqu (@X[-2&7],"32($inp)"); + &movdqu (@X[-1&7],"48($inp)"); + &pshufb (@X[-4&7],@X[2]); # byte swap + &add ($inp,64); + + $Xi=0; +} + +sub Xloop_ssse3() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &pshufb (@X[($Xi-3)&7],@X[2]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &paddd (@X[($Xi-4)&7],@Tx[1]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &movdqa (eval(16*$Xi)."(%rsp)",@X[($Xi-4)&7]); # X[]+K xfer to IALU + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &psubd (@X[($Xi-4)&7],@Tx[1]); + + foreach (@insns) { eval; } + $Xi++; +} + +sub Xtail_ssse3() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + foreach (@insns) { eval; } +} + +sub body_00_19 () { # ((c^d)&b)^d + # on start @T[0]=(c^d)&b + return &body_20_39() if ($rx==19); $rx++; + ( + '($a,$b,$c,$d,$e)=@V;'. + '&$_ror ($b,$j?7:2)', # $b>>>2 + '&xor (@T[0],$d)', + '&mov (@T[1],$a)', # $b for next round + + '&add ($e,eval(4*($j&15))."(%rsp)")', # X[]+K xfer + '&xor ($b,$c)', # $c^$d for next round + + '&$_rol ($a,5)', + '&add ($e,@T[0])', + '&and (@T[1],$b)', # ($b&($c^$d)) for next round + + '&xor ($b,$c)', # restore $b + '&add ($e,$a);' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));' + ); +} + +sub body_20_39 () { # b^d^c + # on entry @T[0]=b^d + return &body_40_59() if ($rx==39); $rx++; + ( + '($a,$b,$c,$d,$e)=@V;'. + '&add ($e,eval(4*($j&15))."(%rsp)")', # X[]+K xfer + '&xor (@T[0],$d) if($j==19);'. + '&xor (@T[0],$c) if($j> 19)', # ($b^$d^$c) + '&mov (@T[1],$a)', # $b for next round + + '&$_rol ($a,5)', + '&add ($e,@T[0])', + '&xor (@T[1],$c) if ($j< 79)', # $b^$d for next round + + '&$_ror ($b,7)', # $b>>>2 + '&add ($e,$a);' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));' + ); +} + +sub body_40_59 () { # ((b^c)&(c^d))^c + # on entry @T[0]=(b^c), (c^=d) + $rx++; + ( + '($a,$b,$c,$d,$e)=@V;'. + '&add ($e,eval(4*($j&15))."(%rsp)")', # X[]+K xfer + '&and (@T[0],$c) if ($j>=40)', # (b^c)&(c^d) + '&xor ($c,$d) if ($j>=40)', # restore $c + + '&$_ror ($b,7)', # $b>>>2 + '&mov (@T[1],$a)', # $b for next round + '&xor (@T[0],$c)', + + '&$_rol ($a,5)', + '&add ($e,@T[0])', + '&xor (@T[1],$c) if ($j==59);'. + '&xor (@T[1],$b) if ($j< 59)', # b^c for next round + + '&xor ($b,$c) if ($j< 59)', # c^d for next round + '&add ($e,$a);' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));' + ); +} +$code.=<<___; +.align 16 +.Loop_ssse3: +___ + &Xupdate_ssse3_16_31(\&body_00_19); + &Xupdate_ssse3_16_31(\&body_00_19); + &Xupdate_ssse3_16_31(\&body_00_19); + &Xupdate_ssse3_16_31(\&body_00_19); + &Xupdate_ssse3_32_79(\&body_00_19); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xupdate_ssse3_32_79(\&body_40_59); + &Xupdate_ssse3_32_79(\&body_40_59); + &Xupdate_ssse3_32_79(\&body_40_59); + &Xupdate_ssse3_32_79(\&body_40_59); + &Xupdate_ssse3_32_79(\&body_40_59); + &Xupdate_ssse3_32_79(\&body_20_39); + &Xuplast_ssse3_80(\&body_20_39); # can jump to "done" + + $saved_j=$j; @saved_V=@V; + + &Xloop_ssse3(\&body_20_39); + &Xloop_ssse3(\&body_20_39); + &Xloop_ssse3(\&body_20_39); + +$code.=<<___; + add 0($ctx),$A # update context + add 4($ctx),@T[0] + add 8($ctx),$C + add 12($ctx),$D + mov $A,0($ctx) + add 16($ctx),$E + mov @T[0],4($ctx) + mov @T[0],$B # magic seed + mov $C,8($ctx) + mov $C,@T[1] + mov $D,12($ctx) + xor $D,@T[1] + mov $E,16($ctx) + and @T[1],@T[0] + jmp .Loop_ssse3 + +.align 16 +.Ldone_ssse3: +___ + $j=$saved_j; @V=@saved_V; + + &Xtail_ssse3(\&body_20_39); + &Xtail_ssse3(\&body_20_39); + &Xtail_ssse3(\&body_20_39); + +$code.=<<___; + add 0($ctx),$A # update context + add 4($ctx),@T[0] + add 8($ctx),$C + mov $A,0($ctx) + add 12($ctx),$D + mov @T[0],4($ctx) + add 16($ctx),$E + mov $C,8($ctx) + mov $D,12($ctx) + mov $E,16($ctx) +___ +$code.=<<___ if ($win64); + movaps -40-6*16($fp),%xmm6 + movaps -40-5*16($fp),%xmm7 + movaps -40-4*16($fp),%xmm8 + movaps -40-3*16($fp),%xmm9 + movaps -40-2*16($fp),%xmm10 + movaps -40-1*16($fp),%xmm11 +___ +$code.=<<___; + mov -40($fp),%r14 +.cfi_restore %r14 + mov -32($fp),%r13 +.cfi_restore %r13 + mov -24($fp),%r12 +.cfi_restore %r12 + mov -16($fp),%rbp +.cfi_restore %rbp + mov -8($fp),%rbx +.cfi_restore %rbx + lea ($fp),%rsp +.cfi_def_cfa_register %rsp +.Lepilogue_ssse3: + ret +.cfi_endproc +.size sha1_block_data_order_ssse3,.-sha1_block_data_order_ssse3 +___ + +if ($avx) { +$Xi=4; # reset variables +@X=map("%xmm$_",(4..7,0..3)); +@Tx=map("%xmm$_",(8..10)); +$j=0; +$rx=0; + +my $done_avx_label=".Ldone_avx"; + +my $_rol=sub { &shld(@_[0],@_) }; +my $_ror=sub { &shrd(@_[0],@_) }; + +$code.=<<___; +.type sha1_block_data_order_avx,\@function,3 +.align 16 +sha1_block_data_order_avx: +_avx_shortcut: +.cfi_startproc + mov %rsp,$fp +.cfi_def_cfa_register $fp + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 # redundant, done to share Win64 SE handler +.cfi_push %r13 + push %r14 +.cfi_push %r14 + lea `-64-($win64?6*16:0)`(%rsp),%rsp + vzeroupper +___ +$code.=<<___ if ($win64); + vmovaps %xmm6,-40-6*16($fp) + vmovaps %xmm7,-40-5*16($fp) + vmovaps %xmm8,-40-4*16($fp) + vmovaps %xmm9,-40-3*16($fp) + vmovaps %xmm10,-40-2*16($fp) + vmovaps %xmm11,-40-1*16($fp) +.Lprologue_avx: +___ +$code.=<<___; + and \$-64,%rsp + mov %rdi,$ctx # reassigned argument + mov %rsi,$inp # reassigned argument + mov %rdx,$num # reassigned argument + + shl \$6,$num + add $inp,$num + lea K_XX_XX+64(%rip),$K_XX_XX + + mov 0($ctx),$A # load context + mov 4($ctx),$B + mov 8($ctx),$C + mov 12($ctx),$D + mov $B,@T[0] # magic seed + mov 16($ctx),$E + mov $C,@T[1] + xor $D,@T[1] + and @T[1],@T[0] + + vmovdqa 64($K_XX_XX),@X[2] # pbswap mask + vmovdqa -64($K_XX_XX),$Kx # K_00_19 + vmovdqu 0($inp),@X[-4&7] # load input to %xmm[0-3] + vmovdqu 16($inp),@X[-3&7] + vmovdqu 32($inp),@X[-2&7] + vmovdqu 48($inp),@X[-1&7] + vpshufb @X[2],@X[-4&7],@X[-4&7] # byte swap + add \$64,$inp + vpshufb @X[2],@X[-3&7],@X[-3&7] + vpshufb @X[2],@X[-2&7],@X[-2&7] + vpshufb @X[2],@X[-1&7],@X[-1&7] + vpaddd $Kx,@X[-4&7],@X[0] # add K_00_19 + vpaddd $Kx,@X[-3&7],@X[1] + vpaddd $Kx,@X[-2&7],@X[2] + vmovdqa @X[0],0(%rsp) # X[]+K xfer to IALU + vmovdqa @X[1],16(%rsp) + vmovdqa @X[2],32(%rsp) + jmp .Loop_avx +___ + +sub Xupdate_avx_16_31() # recall that $Xi starts with 4 +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 40 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); + eval(shift(@insns)); + &vpalignr(@X[0],@X[-3&7],@X[-4&7],8); # compose "X[-14]" in "X[0]" + eval(shift(@insns)); + eval(shift(@insns)); + + &vpaddd (@Tx[1],$Kx,@X[-1&7]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpsrldq(@Tx[0],@X[-1&7],4); # "X[-3]", 3 dwords + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor (@X[0],@X[0],@X[-4&7]); # "X[0]"^="X[-16]" + eval(shift(@insns)); + eval(shift(@insns)); + + &vpxor (@Tx[0],@Tx[0],@X[-2&7]); # "X[-3]"^"X[-8]" + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpxor (@X[0],@X[0],@Tx[0]); # "X[0]"^="X[-3]"^"X[-8]" + eval(shift(@insns)); + eval(shift(@insns)); + &vmovdqa (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU + eval(shift(@insns)); + eval(shift(@insns)); + + &vpsrld (@Tx[0],@X[0],31); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpslldq(@Tx[2],@X[0],12); # "X[0]"<<96, extract one dword + &vpaddd (@X[0],@X[0],@X[0]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpsrld (@Tx[1],@Tx[2],30); + &vpor (@X[0],@X[0],@Tx[0]); # "X[0]"<<<=1 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpslld (@Tx[2],@Tx[2],2); + &vpxor (@X[0],@X[0],@Tx[1]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpxor (@X[0],@X[0],@Tx[2]); # "X[0]"^=("X[0]">>96)<<<2 + eval(shift(@insns)); + eval(shift(@insns)); + &vmovdqa ($Kx,eval(2*16*(($Xi)/5)-64)."($K_XX_XX)") if ($Xi%5==0); # K_XX_XX + eval(shift(@insns)); + eval(shift(@insns)); + + + foreach (@insns) { eval; } # remaining instructions [if any] + + $Xi++; push(@X,shift(@X)); # "rotate" X[] +} + +sub Xupdate_avx_32_79() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 to 44 instructions + my ($a,$b,$c,$d,$e); + + &vpalignr(@Tx[0],@X[-1&7],@X[-2&7],8); # compose "X[-6]" + &vpxor (@X[0],@X[0],@X[-4&7]); # "X[0]"="X[-32]"^"X[-16]" + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + + &vpxor (@X[0],@X[0],@X[-7&7]); # "X[0]"^="X[-28]" + eval(shift(@insns)); + eval(shift(@insns)) if (@insns[0] !~ /&ro[rl]/); + &vpaddd (@Tx[1],$Kx,@X[-1&7]); + &vmovdqa ($Kx,eval(2*16*($Xi/5)-64)."($K_XX_XX)") if ($Xi%5==0); + eval(shift(@insns)); # ror + eval(shift(@insns)); + + &vpxor (@X[0],@X[0],@Tx[0]); # "X[0]"^="X[-6]" + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + + &vpsrld (@Tx[0],@X[0],30); + &vmovdqa (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # ror + eval(shift(@insns)); + + &vpslld (@X[0],@X[0],2); + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # ror + eval(shift(@insns)); + + &vpor (@X[0],@X[0],@Tx[0]); # "X[0]"<<<=2 + eval(shift(@insns)); # body_20_39 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # rol + eval(shift(@insns)); + + foreach (@insns) { eval; } # remaining instructions + + $Xi++; push(@X,shift(@X)); # "rotate" X[] +} + +sub Xuplast_avx_80() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); + &vpaddd (@Tx[1],$Kx,@X[-1&7]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vmovdqa (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer IALU + + foreach (@insns) { eval; } # remaining instructions + + &cmp ($inp,$num); + &je ($done_avx_label); + + &vmovdqa(@X[2],"64($K_XX_XX)"); # pbswap mask + &vmovdqa($Kx,"-64($K_XX_XX)"); # K_00_19 + &vmovdqu(@X[-4&7],"0($inp)"); # load input + &vmovdqu(@X[-3&7],"16($inp)"); + &vmovdqu(@X[-2&7],"32($inp)"); + &vmovdqu(@X[-1&7],"48($inp)"); + &vpshufb(@X[-4&7],@X[-4&7],@X[2]); # byte swap + &add ($inp,64); + + $Xi=0; +} + +sub Xloop_avx() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + eval(shift(@insns)); + eval(shift(@insns)); + &vpshufb(@X[($Xi-3)&7],@X[($Xi-3)&7],@X[2]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpaddd (@X[$Xi&7],@X[($Xi-4)&7],$Kx); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vmovdqa(eval(16*$Xi)."(%rsp)",@X[$Xi&7]); # X[]+K xfer to IALU + eval(shift(@insns)); + eval(shift(@insns)); + + foreach (@insns) { eval; } + $Xi++; +} + +sub Xtail_avx() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + foreach (@insns) { eval; } +} + +$code.=<<___; +.align 16 +.Loop_avx: +___ + &Xupdate_avx_16_31(\&body_00_19); + &Xupdate_avx_16_31(\&body_00_19); + &Xupdate_avx_16_31(\&body_00_19); + &Xupdate_avx_16_31(\&body_00_19); + &Xupdate_avx_32_79(\&body_00_19); + &Xupdate_avx_32_79(\&body_20_39); + &Xupdate_avx_32_79(\&body_20_39); + &Xupdate_avx_32_79(\&body_20_39); + &Xupdate_avx_32_79(\&body_20_39); + &Xupdate_avx_32_79(\&body_20_39); + &Xupdate_avx_32_79(\&body_40_59); + &Xupdate_avx_32_79(\&body_40_59); + &Xupdate_avx_32_79(\&body_40_59); + &Xupdate_avx_32_79(\&body_40_59); + &Xupdate_avx_32_79(\&body_40_59); + &Xupdate_avx_32_79(\&body_20_39); + &Xuplast_avx_80(\&body_20_39); # can jump to "done" + + $saved_j=$j; @saved_V=@V; + + &Xloop_avx(\&body_20_39); + &Xloop_avx(\&body_20_39); + &Xloop_avx(\&body_20_39); + +$code.=<<___; + add 0($ctx),$A # update context + add 4($ctx),@T[0] + add 8($ctx),$C + add 12($ctx),$D + mov $A,0($ctx) + add 16($ctx),$E + mov @T[0],4($ctx) + mov @T[0],$B # magic seed + mov $C,8($ctx) + mov $C,@T[1] + mov $D,12($ctx) + xor $D,@T[1] + mov $E,16($ctx) + and @T[1],@T[0] + jmp .Loop_avx + +.align 16 +$done_avx_label: +___ + $j=$saved_j; @V=@saved_V; + + &Xtail_avx(\&body_20_39); + &Xtail_avx(\&body_20_39); + &Xtail_avx(\&body_20_39); + +$code.=<<___; + vzeroupper + + add 0($ctx),$A # update context + add 4($ctx),@T[0] + add 8($ctx),$C + mov $A,0($ctx) + add 12($ctx),$D + mov @T[0],4($ctx) + add 16($ctx),$E + mov $C,8($ctx) + mov $D,12($ctx) + mov $E,16($ctx) +___ +$code.=<<___ if ($win64); + movaps -40-6*16($fp),%xmm6 + movaps -40-5*16($fp),%xmm7 + movaps -40-4*16($fp),%xmm8 + movaps -40-3*16($fp),%xmm9 + movaps -40-2*16($fp),%xmm10 + movaps -40-1*16($fp),%xmm11 +___ +$code.=<<___; + mov -40($fp),%r14 +.cfi_restore %r14 + mov -32($fp),%r13 +.cfi_restore %r13 + mov -24($fp),%r12 +.cfi_restore %r12 + mov -16($fp),%rbp +.cfi_restore %rbp + mov -8($fp),%rbx +.cfi_restore %rbx + lea ($fp),%rsp +.cfi_def_cfa_register %rsp +.Lepilogue_avx: + ret +.cfi_endproc +.size sha1_block_data_order_avx,.-sha1_block_data_order_avx +___ + +if ($avx>1) { +use integer; +$Xi=4; # reset variables +@X=map("%ymm$_",(4..7,0..3)); +@Tx=map("%ymm$_",(8..10)); +$Kx="%ymm11"; +$j=0; + +my @ROTX=("%eax","%ebp","%ebx","%ecx","%edx","%esi"); +my ($a5,$t0)=("%r12d","%edi"); + +my ($A,$F,$B,$C,$D,$E)=@ROTX; +my $rx=0; +my $frame="%r13"; + +$code.=<<___; +.type sha1_block_data_order_avx2,\@function,3 +.align 16 +sha1_block_data_order_avx2: +_avx2_shortcut: +.cfi_startproc + mov %rsp,$fp +.cfi_def_cfa_register $fp + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + vzeroupper +___ +$code.=<<___ if ($win64); + lea -6*16(%rsp),%rsp + vmovaps %xmm6,-40-6*16($fp) + vmovaps %xmm7,-40-5*16($fp) + vmovaps %xmm8,-40-4*16($fp) + vmovaps %xmm9,-40-3*16($fp) + vmovaps %xmm10,-40-2*16($fp) + vmovaps %xmm11,-40-1*16($fp) +.Lprologue_avx2: +___ +$code.=<<___; + mov %rdi,$ctx # reassigned argument + mov %rsi,$inp # reassigned argument + mov %rdx,$num # reassigned argument + + lea -640(%rsp),%rsp + shl \$6,$num + lea 64($inp),$frame + and \$-128,%rsp + add $inp,$num + lea K_XX_XX+64(%rip),$K_XX_XX + + mov 0($ctx),$A # load context + cmp $num,$frame + cmovae $inp,$frame # next or same block + mov 4($ctx),$F + mov 8($ctx),$C + mov 12($ctx),$D + mov 16($ctx),$E + vmovdqu 64($K_XX_XX),@X[2] # pbswap mask + + vmovdqu ($inp),%xmm0 + vmovdqu 16($inp),%xmm1 + vmovdqu 32($inp),%xmm2 + vmovdqu 48($inp),%xmm3 + lea 64($inp),$inp + vinserti128 \$1,($frame),@X[-4&7],@X[-4&7] + vinserti128 \$1,16($frame),@X[-3&7],@X[-3&7] + vpshufb @X[2],@X[-4&7],@X[-4&7] + vinserti128 \$1,32($frame),@X[-2&7],@X[-2&7] + vpshufb @X[2],@X[-3&7],@X[-3&7] + vinserti128 \$1,48($frame),@X[-1&7],@X[-1&7] + vpshufb @X[2],@X[-2&7],@X[-2&7] + vmovdqu -64($K_XX_XX),$Kx # K_00_19 + vpshufb @X[2],@X[-1&7],@X[-1&7] + + vpaddd $Kx,@X[-4&7],@X[0] # add K_00_19 + vpaddd $Kx,@X[-3&7],@X[1] + vmovdqu @X[0],0(%rsp) # X[]+K xfer to IALU + vpaddd $Kx,@X[-2&7],@X[2] + vmovdqu @X[1],32(%rsp) + vpaddd $Kx,@X[-1&7],@X[3] + vmovdqu @X[2],64(%rsp) + vmovdqu @X[3],96(%rsp) +___ +for (;$Xi<8;$Xi++) { # Xupdate_avx2_16_31 + use integer; + + &vpalignr(@X[0],@X[-3&7],@X[-4&7],8); # compose "X[-14]" in "X[0]" + &vpsrldq(@Tx[0],@X[-1&7],4); # "X[-3]", 3 dwords + &vpxor (@X[0],@X[0],@X[-4&7]); # "X[0]"^="X[-16]" + &vpxor (@Tx[0],@Tx[0],@X[-2&7]); # "X[-3]"^"X[-8]" + &vpxor (@X[0],@X[0],@Tx[0]); # "X[0]"^="X[-3]"^"X[-8]" + &vpsrld (@Tx[0],@X[0],31); + &vmovdqu($Kx,eval(2*16*(($Xi)/5)-64)."($K_XX_XX)") if ($Xi%5==0); # K_XX_XX + &vpslldq(@Tx[2],@X[0],12); # "X[0]"<<96, extract one dword + &vpaddd (@X[0],@X[0],@X[0]); + &vpsrld (@Tx[1],@Tx[2],30); + &vpor (@X[0],@X[0],@Tx[0]); # "X[0]"<<<=1 + &vpslld (@Tx[2],@Tx[2],2); + &vpxor (@X[0],@X[0],@Tx[1]); + &vpxor (@X[0],@X[0],@Tx[2]); # "X[0]"^=("X[0]">>96)<<<2 + &vpaddd (@Tx[1],@X[0],$Kx); + &vmovdqu("32*$Xi(%rsp)",@Tx[1]); # X[]+K xfer to IALU + + push(@X,shift(@X)); # "rotate" X[] +} +$code.=<<___; + lea 128(%rsp),$frame + jmp .Loop_avx2 +.align 32 +.Loop_avx2: + rorx \$2,$F,$B + andn $D,$F,$t0 + and $C,$F + xor $t0,$F +___ +sub bodyx_00_19 () { # 8 instructions, 3 cycles critical path + # at start $f=(b&c)^(~b&d), $b>>>=2 + return &bodyx_20_39() if ($rx==19); $rx++; + ( + '($a,$f,$b,$c,$d,$e)=@ROTX;'. + + '&add ($e,((32*($j/4)+4*($j%4))%256-128)."($frame)");'. # e+=X[i]+K + '&lea ($frame,"256($frame)") if ($j%32==31);', + '&andn ($t0,$a,$c)', # ~b&d for next round + + '&add ($e,$f)', # e+=(b&c)^(~b&d) + '&rorx ($a5,$a,27)', # a<<<5 + '&rorx ($f,$a,2)', # b>>>2 for next round + '&and ($a,$b)', # b&c for next round + + '&add ($e,$a5)', # e+=a<<<5 + '&xor ($a,$t0);'. # f=(b&c)^(~b&d) for next round + + 'unshift(@ROTX,pop(@ROTX)); $j++;' + ) +} + +sub bodyx_20_39 () { # 7 instructions, 2 cycles critical path + # on entry $f=b^c^d, $b>>>=2 + return &bodyx_40_59() if ($rx==39); $rx++; + ( + '($a,$f,$b,$c,$d,$e)=@ROTX;'. + + '&add ($e,((32*($j/4)+4*($j%4))%256-128)."($frame)");'. # e+=X[i]+K + '&lea ($frame,"256($frame)") if ($j%32==31);', + + '&lea ($e,"($e,$f)")', # e+=b^c^d + '&rorx ($a5,$a,27)', # a<<<5 + '&rorx ($f,$a,2) if ($j<79)', # b>>>2 in next round + '&xor ($a,$b) if ($j<79)', # b^c for next round + + '&add ($e,$a5)', # e+=a<<<5 + '&xor ($a,$c) if ($j<79);'. # f=b^c^d for next round + + 'unshift(@ROTX,pop(@ROTX)); $j++;' + ) +} + +sub bodyx_40_59 () { # 10 instructions, 3 cycles critical path + # on entry $f=((b^c)&(c^d)), $b>>>=2 + $rx++; + ( + '($a,$f,$b,$c,$d,$e)=@ROTX;'. + + '&add ($e,((32*($j/4)+4*($j%4))%256-128)."($frame)");'. # e+=X[i]+K + '&lea ($frame,"256($frame)") if ($j%32==31);', + '&xor ($f,$c) if ($j>39)', # (b^c)&(c^d)^c + '&mov ($t0,$b) if ($j<59)', # count on zero latency + '&xor ($t0,$c) if ($j<59)', # c^d for next round + + '&lea ($e,"($e,$f)")', # e+=(b^c)&(c^d)^c + '&rorx ($a5,$a,27)', # a<<<5 + '&rorx ($f,$a,2)', # b>>>2 in next round + '&xor ($a,$b)', # b^c for next round + + '&add ($e,$a5)', # e+=a<<<5 + '&and ($a,$t0) if ($j< 59);'. # f=(b^c)&(c^d) for next round + '&xor ($a,$c) if ($j==59);'. # f=b^c^d for next round + + 'unshift(@ROTX,pop(@ROTX)); $j++;' + ) +} + +sub Xupdate_avx2_16_31() # recall that $Xi starts with 4 +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body,&$body); # 35 instructions + my ($a,$b,$c,$d,$e); + + &vpalignr(@X[0],@X[-3&7],@X[-4&7],8); # compose "X[-14]" in "X[0]" + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpsrldq(@Tx[0],@X[-1&7],4); # "X[-3]", 3 dwords + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpxor (@X[0],@X[0],@X[-4&7]); # "X[0]"^="X[-16]" + &vpxor (@Tx[0],@Tx[0],@X[-2&7]); # "X[-3]"^"X[-8]" + eval(shift(@insns)); + eval(shift(@insns)); + + &vpxor (@X[0],@X[0],@Tx[0]); # "X[0]"^="X[-3]"^"X[-8]" + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpsrld (@Tx[0],@X[0],31); + &vmovdqu($Kx,eval(2*16*(($Xi)/5)-64)."($K_XX_XX)") if ($Xi%5==0); # K_XX_XX + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpslldq(@Tx[2],@X[0],12); # "X[0]"<<96, extract one dword + &vpaddd (@X[0],@X[0],@X[0]); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpsrld (@Tx[1],@Tx[2],30); + &vpor (@X[0],@X[0],@Tx[0]); # "X[0]"<<<=1 + eval(shift(@insns)); + eval(shift(@insns)); + + &vpslld (@Tx[2],@Tx[2],2); + &vpxor (@X[0],@X[0],@Tx[1]); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpxor (@X[0],@X[0],@Tx[2]); # "X[0]"^=("X[0]">>96)<<<2 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpaddd (@Tx[1],@X[0],$Kx); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vmovdqu(eval(32*($Xi))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU + + foreach (@insns) { eval; } # remaining instructions [if any] + + $Xi++; + push(@X,shift(@X)); # "rotate" X[] +} + +sub Xupdate_avx2_32_79() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body,&$body); # 35 to 50 instructions + my ($a,$b,$c,$d,$e); + + &vpalignr(@Tx[0],@X[-1&7],@X[-2&7],8); # compose "X[-6]" + &vpxor (@X[0],@X[0],@X[-4&7]); # "X[0]"="X[-32]"^"X[-16]" + eval(shift(@insns)); + eval(shift(@insns)); + + &vpxor (@X[0],@X[0],@X[-7&7]); # "X[0]"^="X[-28]" + &vmovdqu($Kx,eval(2*16*($Xi/5)-64)."($K_XX_XX)") if ($Xi%5==0); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpxor (@X[0],@X[0],@Tx[0]); # "X[0]"^="X[-6]" + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpsrld (@Tx[0],@X[0],30); + &vpslld (@X[0],@X[0],2); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + #&vpslld (@X[0],@X[0],2); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpor (@X[0],@X[0],@Tx[0]); # "X[0]"<<<=2 + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vpaddd (@Tx[1],@X[0],$Kx); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + + &vmovdqu("32*$Xi(%rsp)",@Tx[1]); # X[]+K xfer to IALU + + foreach (@insns) { eval; } # remaining instructions + + $Xi++; + push(@X,shift(@X)); # "rotate" X[] +} + +sub Xloop_avx2() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body,&$body); # 32 instructions + my ($a,$b,$c,$d,$e); + + foreach (@insns) { eval; } +} + + &align32(); + &Xupdate_avx2_32_79(\&bodyx_00_19); + &Xupdate_avx2_32_79(\&bodyx_00_19); + &Xupdate_avx2_32_79(\&bodyx_00_19); + &Xupdate_avx2_32_79(\&bodyx_00_19); + + &Xupdate_avx2_32_79(\&bodyx_20_39); + &Xupdate_avx2_32_79(\&bodyx_20_39); + &Xupdate_avx2_32_79(\&bodyx_20_39); + &Xupdate_avx2_32_79(\&bodyx_20_39); + + &align32(); + &Xupdate_avx2_32_79(\&bodyx_40_59); + &Xupdate_avx2_32_79(\&bodyx_40_59); + &Xupdate_avx2_32_79(\&bodyx_40_59); + &Xupdate_avx2_32_79(\&bodyx_40_59); + + &Xloop_avx2(\&bodyx_20_39); + &Xloop_avx2(\&bodyx_20_39); + &Xloop_avx2(\&bodyx_20_39); + &Xloop_avx2(\&bodyx_20_39); + +$code.=<<___; + lea 128($inp),$frame + lea 128($inp),%rdi # borrow $t0 + cmp $num,$frame + cmovae $inp,$frame # next or previous block + + # output is d-e-[a]-f-b-c => A=d,F=e,C=f,D=b,E=c + add 0($ctx),@ROTX[0] # update context + add 4($ctx),@ROTX[1] + add 8($ctx),@ROTX[3] + mov @ROTX[0],0($ctx) + add 12($ctx),@ROTX[4] + mov @ROTX[1],4($ctx) + mov @ROTX[0],$A # A=d + add 16($ctx),@ROTX[5] + mov @ROTX[3],$a5 + mov @ROTX[3],8($ctx) + mov @ROTX[4],$D # D=b + #xchg @ROTX[5],$F # F=c, C=f + mov @ROTX[4],12($ctx) + mov @ROTX[1],$F # F=e + mov @ROTX[5],16($ctx) + #mov $F,16($ctx) + mov @ROTX[5],$E # E=c + mov $a5,$C # C=f + #xchg $F,$E # E=c, F=e + + cmp $num,$inp + je .Ldone_avx2 +___ + +$Xi=4; # reset variables +@X=map("%ymm$_",(4..7,0..3)); + +$code.=<<___; + vmovdqu 64($K_XX_XX),@X[2] # pbswap mask + cmp $num,%rdi # borrowed $t0 + ja .Last_avx2 + + vmovdqu -64(%rdi),%xmm0 # low part of @X[-4&7] + vmovdqu -48(%rdi),%xmm1 + vmovdqu -32(%rdi),%xmm2 + vmovdqu -16(%rdi),%xmm3 + vinserti128 \$1,0($frame),@X[-4&7],@X[-4&7] + vinserti128 \$1,16($frame),@X[-3&7],@X[-3&7] + vinserti128 \$1,32($frame),@X[-2&7],@X[-2&7] + vinserti128 \$1,48($frame),@X[-1&7],@X[-1&7] + jmp .Last_avx2 + +.align 32 +.Last_avx2: + lea 128+16(%rsp),$frame + rorx \$2,$F,$B + andn $D,$F,$t0 + and $C,$F + xor $t0,$F + sub \$-128,$inp +___ + $rx=$j=0; @ROTX=($A,$F,$B,$C,$D,$E); + + &Xloop_avx2 (\&bodyx_00_19); + &Xloop_avx2 (\&bodyx_00_19); + &Xloop_avx2 (\&bodyx_00_19); + &Xloop_avx2 (\&bodyx_00_19); + + &Xloop_avx2 (\&bodyx_20_39); + &vmovdqu ($Kx,"-64($K_XX_XX)"); # K_00_19 + &vpshufb (@X[-4&7],@X[-4&7],@X[2]); # byte swap + &Xloop_avx2 (\&bodyx_20_39); + &vpshufb (@X[-3&7],@X[-3&7],@X[2]); + &vpaddd (@Tx[0],@X[-4&7],$Kx); # add K_00_19 + &Xloop_avx2 (\&bodyx_20_39); + &vmovdqu ("0(%rsp)",@Tx[0]); + &vpshufb (@X[-2&7],@X[-2&7],@X[2]); + &vpaddd (@Tx[1],@X[-3&7],$Kx); + &Xloop_avx2 (\&bodyx_20_39); + &vmovdqu ("32(%rsp)",@Tx[1]); + &vpshufb (@X[-1&7],@X[-1&7],@X[2]); + &vpaddd (@X[2],@X[-2&7],$Kx); + + &Xloop_avx2 (\&bodyx_40_59); + &align32 (); + &vmovdqu ("64(%rsp)",@X[2]); + &vpaddd (@X[3],@X[-1&7],$Kx); + &Xloop_avx2 (\&bodyx_40_59); + &vmovdqu ("96(%rsp)",@X[3]); + &Xloop_avx2 (\&bodyx_40_59); + &Xupdate_avx2_16_31(\&bodyx_40_59); + + &Xupdate_avx2_16_31(\&bodyx_20_39); + &Xupdate_avx2_16_31(\&bodyx_20_39); + &Xupdate_avx2_16_31(\&bodyx_20_39); + &Xloop_avx2 (\&bodyx_20_39); + +$code.=<<___; + lea 128(%rsp),$frame + + # output is d-e-[a]-f-b-c => A=d,F=e,C=f,D=b,E=c + add 0($ctx),@ROTX[0] # update context + add 4($ctx),@ROTX[1] + add 8($ctx),@ROTX[3] + mov @ROTX[0],0($ctx) + add 12($ctx),@ROTX[4] + mov @ROTX[1],4($ctx) + mov @ROTX[0],$A # A=d + add 16($ctx),@ROTX[5] + mov @ROTX[3],$a5 + mov @ROTX[3],8($ctx) + mov @ROTX[4],$D # D=b + #xchg @ROTX[5],$F # F=c, C=f + mov @ROTX[4],12($ctx) + mov @ROTX[1],$F # F=e + mov @ROTX[5],16($ctx) + #mov $F,16($ctx) + mov @ROTX[5],$E # E=c + mov $a5,$C # C=f + #xchg $F,$E # E=c, F=e + + cmp $num,$inp + jbe .Loop_avx2 + +.Ldone_avx2: + vzeroupper +___ +$code.=<<___ if ($win64); + movaps -40-6*16($fp),%xmm6 + movaps -40-5*16($fp),%xmm7 + movaps -40-4*16($fp),%xmm8 + movaps -40-3*16($fp),%xmm9 + movaps -40-2*16($fp),%xmm10 + movaps -40-1*16($fp),%xmm11 +___ +$code.=<<___; + mov -40($fp),%r14 +.cfi_restore %r14 + mov -32($fp),%r13 +.cfi_restore %r13 + mov -24($fp),%r12 +.cfi_restore %r12 + mov -16($fp),%rbp +.cfi_restore %rbp + mov -8($fp),%rbx +.cfi_restore %rbx + lea ($fp),%rsp +.cfi_def_cfa_register %rsp +.Lepilogue_avx2: + ret +.cfi_endproc +.size sha1_block_data_order_avx2,.-sha1_block_data_order_avx2 +___ +} +} +$code.=<<___; +.align 64 +K_XX_XX: +.long 0x5a827999,0x5a827999,0x5a827999,0x5a827999 # K_00_19 +.long 0x5a827999,0x5a827999,0x5a827999,0x5a827999 # K_00_19 +.long 0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1 # K_20_39 +.long 0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1 # K_20_39 +.long 0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc # K_40_59 +.long 0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc # K_40_59 +.long 0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6 # K_60_79 +.long 0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6 # K_60_79 +.long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f # pbswap mask +.long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f # pbswap mask +.byte 0xf,0xe,0xd,0xc,0xb,0xa,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0 +___ +}}} +$code.=<<___; +.asciz "SHA1 block transform for x86_64, CRYPTOGAMS by " +.align 64 +___ + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type se_handler,\@abi-omnipotent +.align 16 +se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + lea .Lprologue(%rip),%r10 + cmp %r10,%rbx # context->Rip<.Lprologue + jb .Lcommon_seh_tail + + mov 152($context),%rax # pull context->Rsp + + lea .Lepilogue(%rip),%r10 + cmp %r10,%rbx # context->Rip>=.Lepilogue + jae .Lcommon_seh_tail + + mov `16*4`(%rax),%rax # pull saved stack pointer + + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + + jmp .Lcommon_seh_tail +.size se_handler,.-se_handler +___ + +$code.=<<___ if ($shaext); +.type shaext_handler,\@abi-omnipotent +.align 16 +shaext_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + lea .Lprologue_shaext(%rip),%r10 + cmp %r10,%rbx # context->Rip<.Lprologue + jb .Lcommon_seh_tail + + lea .Lepilogue_shaext(%rip),%r10 + cmp %r10,%rbx # context->Rip>=.Lepilogue + jae .Lcommon_seh_tail + + lea -8-4*16(%rax),%rsi + lea 512($context),%rdi # &context.Xmm6 + mov \$8,%ecx + .long 0xa548f3fc # cld; rep movsq + + jmp .Lcommon_seh_tail +.size shaext_handler,.-shaext_handler +___ + +$code.=<<___; +.type ssse3_handler,\@abi-omnipotent +.align 16 +ssse3_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->RipR11 + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lcommon_seh_tail + + lea -40-6*16(%rax),%rsi + lea 512($context),%rdi # &context.Xmm6 + mov \$12,%ecx + .long 0xa548f3fc # cld; rep movsq + + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + +.Lcommon_seh_tail: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size ssse3_handler,.-ssse3_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_sha1_block_data_order + .rva .LSEH_end_sha1_block_data_order + .rva .LSEH_info_sha1_block_data_order +___ +$code.=<<___ if ($shaext); + .rva .LSEH_begin_sha1_block_data_order_shaext + .rva .LSEH_end_sha1_block_data_order_shaext + .rva .LSEH_info_sha1_block_data_order_shaext +___ +$code.=<<___; + .rva .LSEH_begin_sha1_block_data_order_ssse3 + .rva .LSEH_end_sha1_block_data_order_ssse3 + .rva .LSEH_info_sha1_block_data_order_ssse3 +___ +$code.=<<___ if ($avx); + .rva .LSEH_begin_sha1_block_data_order_avx + .rva .LSEH_end_sha1_block_data_order_avx + .rva .LSEH_info_sha1_block_data_order_avx +___ +$code.=<<___ if ($avx>1); + .rva .LSEH_begin_sha1_block_data_order_avx2 + .rva .LSEH_end_sha1_block_data_order_avx2 + .rva .LSEH_info_sha1_block_data_order_avx2 +___ +$code.=<<___; +.section .xdata +.align 8 +.LSEH_info_sha1_block_data_order: + .byte 9,0,0,0 + .rva se_handler +___ +$code.=<<___ if ($shaext); +.LSEH_info_sha1_block_data_order_shaext: + .byte 9,0,0,0 + .rva shaext_handler +___ +$code.=<<___; +.LSEH_info_sha1_block_data_order_ssse3: + .byte 9,0,0,0 + .rva ssse3_handler + .rva .Lprologue_ssse3,.Lepilogue_ssse3 # HandlerData[] +___ +$code.=<<___ if ($avx); +.LSEH_info_sha1_block_data_order_avx: + .byte 9,0,0,0 + .rva ssse3_handler + .rva .Lprologue_avx,.Lepilogue_avx # HandlerData[] +___ +$code.=<<___ if ($avx>1); +.LSEH_info_sha1_block_data_order_avx2: + .byte 9,0,0,0 + .rva ssse3_handler + .rva .Lprologue_avx2,.Lepilogue_avx2 # HandlerData[] +___ +} + +#################################################################### + +sub sha1rnds4 { + if (@_[0] =~ /\$([x0-9a-f]+),\s*%xmm([0-7]),\s*%xmm([0-7])/) { + my @opcode=(0x0f,0x3a,0xcc); + push @opcode,0xc0|($2&7)|(($3&7)<<3); # ModR/M + my $c=$1; + push @opcode,$c=~/^0/?oct($c):$c; + return ".byte\t".join(',',@opcode); + } else { + return "sha1rnds4\t".@_[0]; + } +} + +sub sha1op38 { + my $instr = shift; + my %opcodelet = ( + "sha1nexte" => 0xc8, + "sha1msg1" => 0xc9, + "sha1msg2" => 0xca ); + + if (defined($opcodelet{$instr}) && @_[0] =~ /%xmm([0-9]+),\s*%xmm([0-9]+)/) { + my @opcode=(0x0f,0x38); + my $rex=0; + $rex|=0x04 if ($2>=8); + $rex|=0x01 if ($1>=8); + unshift @opcode,0x40|$rex if ($rex); + push @opcode,$opcodelet{$instr}; + push @opcode,0xc0|($1&7)|(($2&7)<<3); # ModR/M + return ".byte\t".join(',',@opcode); + } else { + return $instr."\t".@_[0]; + } +} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/geo; + + s/\b(sha1rnds4)\s+(.*)/sha1rnds4($2)/geo or + s/\b(sha1[^\s]*)\s+(.*)/sha1op38($1,$2)/geo; + + print $_,"\n"; +} +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha256-586.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha256-586.pl new file mode 100644 index 000000000..dccc771ad --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha256-586.pl @@ -0,0 +1,1296 @@ +#! /usr/bin/env perl +# Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# SHA256 block transform for x86. September 2007. +# +# Performance improvement over compiler generated code varies from +# 10% to 40% [see below]. Not very impressive on some µ-archs, but +# it's 5 times smaller and optimizes amount of writes. +# +# May 2012. +# +# Optimization including two of Pavel Semjanov's ideas, alternative +# Maj and full unroll, resulted in ~20-25% improvement on most CPUs, +# ~7% on Pentium, ~40% on Atom. As fully unrolled loop body is almost +# 15x larger, 8KB vs. 560B, it's fired only for longer inputs. But not +# on P4, where it kills performance, nor Sandy Bridge, where folded +# loop is approximately as fast... +# +# June 2012. +# +# Add AMD XOP-specific code path, >30% improvement on Bulldozer over +# May version, >60% over original. Add AVX+shrd code path, >25% +# improvement on Sandy Bridge over May version, 60% over original. +# +# May 2013. +# +# Replace AMD XOP code path with SSSE3 to cover more processors. +# (Biggest improvement coefficient is on upcoming Atom Silvermont, +# not shown.) Add AVX+BMI code path. +# +# March 2014. +# +# Add support for Intel SHA Extensions. +# +# Performance in clock cycles per processed byte (less is better): +# +# gcc icc x86 asm(*) SIMD x86_64 asm(**) +# Pentium 46 57 40/38 - - +# PIII 36 33 27/24 - - +# P4 41 38 28 - 17.3 +# AMD K8 27 25 19/15.5 - 14.9 +# Core2 26 23 18/15.6 14.3 13.8 +# Westmere 27 - 19/15.7 13.4 12.3 +# Sandy Bridge 25 - 15.9 12.4 11.6 +# Ivy Bridge 24 - 15.0 11.4 10.3 +# Haswell 22 - 13.9 9.46 7.80 +# Skylake 20 - 14.9 9.50 7.70 +# Bulldozer 36 - 27/22 17.0 13.6 +# VIA Nano 36 - 25/22 16.8 16.5 +# Atom 50 - 30/25 21.9 18.9 +# Silvermont 40 - 34/31 22.9 20.6 +# Goldmont 29 - 20 16.3(***) +# +# (*) numbers after slash are for unrolled loop, where applicable; +# (**) x86_64 assembly performance is presented for reference +# purposes, results are best-available; +# (***) SHAEXT result is 4.1, strangely enough better than 64-bit one; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +$output=pop; +open STDOUT,">$output"; + +&asm_init($ARGV[0],$ARGV[$#ARGV] eq "386"); + +$xmm=$avx=0; +for (@ARGV) { $xmm=1 if (/-DOPENSSL_IA32_SSE2/); } + +if ($xmm && `$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler version ([2-9]\.[0-9]+)/) { + $avx = ($1>=2.19) + ($1>=2.22); +} + +if ($xmm && !$avx && $ARGV[0] eq "win32n" && + `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) { + $avx = ($1>=2.03) + ($1>=2.10); +} + +if ($xmm && !$avx && $ARGV[0] eq "win32" && + `ml 2>&1` =~ /Version ([0-9]+)\./) { + $avx = ($1>=10) + ($1>=11); +} + +if ($xmm && !$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9]\.[0-9]+)/) { + $avx = ($2>=3.0) + ($2>3.0); +} + +$shaext=$xmm; ### set to zero if compiling for 1.0.1 + +$unroll_after = 64*4; # If pre-evicted from L1P cache first spin of + # fully unrolled loop was measured to run about + # 3-4x slower. If slowdown coefficient is N and + # unrolled loop is m times faster, then you break + # even at (N-1)/(m-1) blocks. Then it needs to be + # adjusted for probability of code being evicted, + # code size/cache size=1/4. Typical m is 1.15... + +$A="eax"; +$E="edx"; +$T="ebx"; +$Aoff=&DWP(4,"esp"); +$Boff=&DWP(8,"esp"); +$Coff=&DWP(12,"esp"); +$Doff=&DWP(16,"esp"); +$Eoff=&DWP(20,"esp"); +$Foff=&DWP(24,"esp"); +$Goff=&DWP(28,"esp"); +$Hoff=&DWP(32,"esp"); +$Xoff=&DWP(36,"esp"); +$K256="ebp"; + +sub BODY_16_63() { + &mov ($T,"ecx"); # "ecx" is preloaded + &mov ("esi",&DWP(4*(9+15+16-14),"esp")); + &ror ("ecx",18-7); + &mov ("edi","esi"); + &ror ("esi",19-17); + &xor ("ecx",$T); + &shr ($T,3); + &ror ("ecx",7); + &xor ("esi","edi"); + &xor ($T,"ecx"); # T = sigma0(X[-15]) + &ror ("esi",17); + &add ($T,&DWP(4*(9+15+16),"esp")); # T += X[-16] + &shr ("edi",10); + &add ($T,&DWP(4*(9+15+16-9),"esp")); # T += X[-7] + #&xor ("edi","esi") # sigma1(X[-2]) + # &add ($T,"edi"); # T += sigma1(X[-2]) + # &mov (&DWP(4*(9+15),"esp"),$T); # save X[0] + + &BODY_00_15(1); +} +sub BODY_00_15() { + my $in_16_63=shift; + + &mov ("ecx",$E); + &xor ("edi","esi") if ($in_16_63); # sigma1(X[-2]) + &mov ("esi",$Foff); + &ror ("ecx",25-11); + &add ($T,"edi") if ($in_16_63); # T += sigma1(X[-2]) + &mov ("edi",$Goff); + &xor ("ecx",$E); + &xor ("esi","edi"); + &mov ($T,&DWP(4*(9+15),"esp")) if (!$in_16_63); + &mov (&DWP(4*(9+15),"esp"),$T) if ($in_16_63); # save X[0] + &ror ("ecx",11-6); + &and ("esi",$E); + &mov ($Eoff,$E); # modulo-scheduled + &xor ($E,"ecx"); + &add ($T,$Hoff); # T += h + &xor ("esi","edi"); # Ch(e,f,g) + &ror ($E,6); # Sigma1(e) + &mov ("ecx",$A); + &add ($T,"esi"); # T += Ch(e,f,g) + + &ror ("ecx",22-13); + &add ($T,$E); # T += Sigma1(e) + &mov ("edi",$Boff); + &xor ("ecx",$A); + &mov ($Aoff,$A); # modulo-scheduled + &lea ("esp",&DWP(-4,"esp")); + &ror ("ecx",13-2); + &mov ("esi",&DWP(0,$K256)); + &xor ("ecx",$A); + &mov ($E,$Eoff); # e in next iteration, d in this one + &xor ($A,"edi"); # a ^= b + &ror ("ecx",2); # Sigma0(a) + + &add ($T,"esi"); # T+= K[i] + &mov (&DWP(0,"esp"),$A); # (b^c) in next round + &add ($E,$T); # d += T + &and ($A,&DWP(4,"esp")); # a &= (b^c) + &add ($T,"ecx"); # T += Sigma0(a) + &xor ($A,"edi"); # h = Maj(a,b,c) = Ch(a^b,c,b) + &mov ("ecx",&DWP(4*(9+15+16-1),"esp")) if ($in_16_63); # preload T + &add ($K256,4); + &add ($A,$T); # h += T +} + +&external_label("OPENSSL_ia32cap_P") if (!$i386); + +&function_begin("sha256_block_data_order"); + &mov ("esi",wparam(0)); # ctx + &mov ("edi",wparam(1)); # inp + &mov ("eax",wparam(2)); # num + &mov ("ebx","esp"); # saved sp + + &call (&label("pic_point")); # make it PIC! +&set_label("pic_point"); + &blindpop($K256); + &lea ($K256,&DWP(&label("K256")."-".&label("pic_point"),$K256)); + + &sub ("esp",16); + &and ("esp",-64); + + &shl ("eax",6); + &add ("eax","edi"); + &mov (&DWP(0,"esp"),"esi"); # ctx + &mov (&DWP(4,"esp"),"edi"); # inp + &mov (&DWP(8,"esp"),"eax"); # inp+num*128 + &mov (&DWP(12,"esp"),"ebx"); # saved sp + if (!$i386 && $xmm) { + &picmeup("edx","OPENSSL_ia32cap_P",$K256,&label("K256")); + &mov ("ecx",&DWP(0,"edx")); + &mov ("ebx",&DWP(4,"edx")); + &test ("ecx",1<<20); # check for P4 + &jnz (&label("loop")); + &mov ("edx",&DWP(8,"edx")) if ($xmm); + &test ("ecx",1<<24); # check for FXSR + &jz ($unroll_after?&label("no_xmm"):&label("loop")); + &and ("ecx",1<<30); # mask "Intel CPU" bit + &and ("ebx",1<<28|1<<9); # mask AVX and SSSE3 bits + &test ("edx",1<<29) if ($shaext); # check for SHA + &jnz (&label("shaext")) if ($shaext); + &or ("ecx","ebx"); + &and ("ecx",1<<28|1<<30); + &cmp ("ecx",1<<28|1<<30); + if ($xmm) { + &je (&label("AVX")) if ($avx); + &test ("ebx",1<<9); # check for SSSE3 + &jnz (&label("SSSE3")); + } else { + &je (&label("loop_shrd")); + } + if ($unroll_after) { +&set_label("no_xmm"); + &sub ("eax","edi"); + &cmp ("eax",$unroll_after); + &jae (&label("unrolled")); + } } + &jmp (&label("loop")); + +sub COMPACT_LOOP() { +my $suffix=shift; + +&set_label("loop$suffix",$suffix?32:16); + # copy input block to stack reversing byte and dword order + for($i=0;$i<4;$i++) { + &mov ("eax",&DWP($i*16+0,"edi")); + &mov ("ebx",&DWP($i*16+4,"edi")); + &mov ("ecx",&DWP($i*16+8,"edi")); + &bswap ("eax"); + &mov ("edx",&DWP($i*16+12,"edi")); + &bswap ("ebx"); + &push ("eax"); + &bswap ("ecx"); + &push ("ebx"); + &bswap ("edx"); + &push ("ecx"); + &push ("edx"); + } + &add ("edi",64); + &lea ("esp",&DWP(-4*9,"esp"));# place for A,B,C,D,E,F,G,H + &mov (&DWP(4*(9+16)+4,"esp"),"edi"); + + # copy ctx->h[0-7] to A,B,C,D,E,F,G,H on stack + &mov ($A,&DWP(0,"esi")); + &mov ("ebx",&DWP(4,"esi")); + &mov ("ecx",&DWP(8,"esi")); + &mov ("edi",&DWP(12,"esi")); + # &mov ($Aoff,$A); + &mov ($Boff,"ebx"); + &xor ("ebx","ecx"); + &mov ($Coff,"ecx"); + &mov ($Doff,"edi"); + &mov (&DWP(0,"esp"),"ebx"); # magic + &mov ($E,&DWP(16,"esi")); + &mov ("ebx",&DWP(20,"esi")); + &mov ("ecx",&DWP(24,"esi")); + &mov ("edi",&DWP(28,"esi")); + # &mov ($Eoff,$E); + &mov ($Foff,"ebx"); + &mov ($Goff,"ecx"); + &mov ($Hoff,"edi"); + +&set_label("00_15$suffix",16); + + &BODY_00_15(); + + &cmp ("esi",0xc19bf174); + &jne (&label("00_15$suffix")); + + &mov ("ecx",&DWP(4*(9+15+16-1),"esp")); # preloaded in BODY_00_15(1) + &jmp (&label("16_63$suffix")); + +&set_label("16_63$suffix",16); + + &BODY_16_63(); + + &cmp ("esi",0xc67178f2); + &jne (&label("16_63$suffix")); + + &mov ("esi",&DWP(4*(9+16+64)+0,"esp"));#ctx + # &mov ($A,$Aoff); + &mov ("ebx",$Boff); + # &mov ("edi",$Coff); + &mov ("ecx",$Doff); + &add ($A,&DWP(0,"esi")); + &add ("ebx",&DWP(4,"esi")); + &add ("edi",&DWP(8,"esi")); + &add ("ecx",&DWP(12,"esi")); + &mov (&DWP(0,"esi"),$A); + &mov (&DWP(4,"esi"),"ebx"); + &mov (&DWP(8,"esi"),"edi"); + &mov (&DWP(12,"esi"),"ecx"); + # &mov ($E,$Eoff); + &mov ("eax",$Foff); + &mov ("ebx",$Goff); + &mov ("ecx",$Hoff); + &mov ("edi",&DWP(4*(9+16+64)+4,"esp"));#inp + &add ($E,&DWP(16,"esi")); + &add ("eax",&DWP(20,"esi")); + &add ("ebx",&DWP(24,"esi")); + &add ("ecx",&DWP(28,"esi")); + &mov (&DWP(16,"esi"),$E); + &mov (&DWP(20,"esi"),"eax"); + &mov (&DWP(24,"esi"),"ebx"); + &mov (&DWP(28,"esi"),"ecx"); + + &lea ("esp",&DWP(4*(9+16+64),"esp"));# destroy frame + &sub ($K256,4*64); # rewind K + + &cmp ("edi",&DWP(8,"esp")); # are we done yet? + &jb (&label("loop$suffix")); +} + &COMPACT_LOOP(); + &mov ("esp",&DWP(12,"esp")); # restore sp +&function_end_A(); + if (!$i386 && !$xmm) { + # ~20% improvement on Sandy Bridge + local *ror = sub { &shrd(@_[0],@_) }; + &COMPACT_LOOP("_shrd"); + &mov ("esp",&DWP(12,"esp")); # restore sp +&function_end_A(); + } + +&set_label("K256",64); # Yes! I keep it in the code segment! +@K256=( 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5, + 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5, + 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3, + 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174, + 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc, + 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da, + 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7, + 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967, + 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13, + 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85, + 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3, + 0xd192e819,0xd6990624,0xf40e3585,0x106aa070, + 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5, + 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3, + 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208, + 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 ); +&data_word(@K256); +&data_word(0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f); # byte swap mask +&asciz("SHA256 block transform for x86, CRYPTOGAMS by "); + +($a,$b,$c,$d,$e,$f,$g,$h)=(0..7); # offsets +sub off { &DWP(4*(((shift)-$i)&7),"esp"); } + +if (!$i386 && $unroll_after) { +my @AH=($A,$K256); + +&set_label("unrolled",16); + &lea ("esp",&DWP(-96,"esp")); + # copy ctx->h[0-7] to A,B,C,D,E,F,G,H on stack + &mov ($AH[0],&DWP(0,"esi")); + &mov ($AH[1],&DWP(4,"esi")); + &mov ("ecx",&DWP(8,"esi")); + &mov ("ebx",&DWP(12,"esi")); + #&mov (&DWP(0,"esp"),$AH[0]); + &mov (&DWP(4,"esp"),$AH[1]); + &xor ($AH[1],"ecx"); # magic + &mov (&DWP(8,"esp"),"ecx"); + &mov (&DWP(12,"esp"),"ebx"); + &mov ($E,&DWP(16,"esi")); + &mov ("ebx",&DWP(20,"esi")); + &mov ("ecx",&DWP(24,"esi")); + &mov ("esi",&DWP(28,"esi")); + #&mov (&DWP(16,"esp"),$E); + &mov (&DWP(20,"esp"),"ebx"); + &mov (&DWP(24,"esp"),"ecx"); + &mov (&DWP(28,"esp"),"esi"); + &jmp (&label("grand_loop")); + +&set_label("grand_loop",16); + # copy input block to stack reversing byte order + for($i=0;$i<5;$i++) { + &mov ("ebx",&DWP(12*$i+0,"edi")); + &mov ("ecx",&DWP(12*$i+4,"edi")); + &bswap ("ebx"); + &mov ("esi",&DWP(12*$i+8,"edi")); + &bswap ("ecx"); + &mov (&DWP(32+12*$i+0,"esp"),"ebx"); + &bswap ("esi"); + &mov (&DWP(32+12*$i+4,"esp"),"ecx"); + &mov (&DWP(32+12*$i+8,"esp"),"esi"); + } + &mov ("ebx",&DWP($i*12,"edi")); + &add ("edi",64); + &bswap ("ebx"); + &mov (&DWP(96+4,"esp"),"edi"); + &mov (&DWP(32+12*$i,"esp"),"ebx"); + + my ($t1,$t2) = ("ecx","esi"); + + for ($i=0;$i<64;$i++) { + + if ($i>=16) { + &mov ($T,$t1); # $t1 is preloaded + # &mov ($t2,&DWP(32+4*(($i+14)&15),"esp")); + &ror ($t1,18-7); + &mov ("edi",$t2); + &ror ($t2,19-17); + &xor ($t1,$T); + &shr ($T,3); + &ror ($t1,7); + &xor ($t2,"edi"); + &xor ($T,$t1); # T = sigma0(X[-15]) + &ror ($t2,17); + &add ($T,&DWP(32+4*($i&15),"esp")); # T += X[-16] + &shr ("edi",10); + &add ($T,&DWP(32+4*(($i+9)&15),"esp")); # T += X[-7] + #&xor ("edi",$t2) # sigma1(X[-2]) + # &add ($T,"edi"); # T += sigma1(X[-2]) + # &mov (&DWP(4*(9+15),"esp"),$T); # save X[0] + } + &mov ($t1,$E); + &xor ("edi",$t2) if ($i>=16); # sigma1(X[-2]) + &mov ($t2,&off($f)); + &ror ($E,25-11); + &add ($T,"edi") if ($i>=16); # T += sigma1(X[-2]) + &mov ("edi",&off($g)); + &xor ($E,$t1); + &mov ($T,&DWP(32+4*($i&15),"esp")) if ($i<16); # X[i] + &mov (&DWP(32+4*($i&15),"esp"),$T) if ($i>=16 && $i<62); # save X[0] + &xor ($t2,"edi"); + &ror ($E,11-6); + &and ($t2,$t1); + &mov (&off($e),$t1); # save $E, modulo-scheduled + &xor ($E,$t1); + &add ($T,&off($h)); # T += h + &xor ("edi",$t2); # Ch(e,f,g) + &ror ($E,6); # Sigma1(e) + &mov ($t1,$AH[0]); + &add ($T,"edi"); # T += Ch(e,f,g) + + &ror ($t1,22-13); + &mov ($t2,$AH[0]); + &mov ("edi",&off($b)); + &xor ($t1,$AH[0]); + &mov (&off($a),$AH[0]); # save $A, modulo-scheduled + &xor ($AH[0],"edi"); # a ^= b, (b^c) in next round + &ror ($t1,13-2); + &and ($AH[1],$AH[0]); # (b^c) &= (a^b) + &lea ($E,&DWP(@K256[$i],$T,$E)); # T += Sigma1(1)+K[i] + &xor ($t1,$t2); + &xor ($AH[1],"edi"); # h = Maj(a,b,c) = Ch(a^b,c,b) + &mov ($t2,&DWP(32+4*(($i+2)&15),"esp")) if ($i>=15 && $i<63); + &ror ($t1,2); # Sigma0(a) + + &add ($AH[1],$E); # h += T + &add ($E,&off($d)); # d += T + &add ($AH[1],$t1); # h += Sigma0(a) + &mov ($t1,&DWP(32+4*(($i+15)&15),"esp")) if ($i>=15 && $i<63); + + @AH = reverse(@AH); # rotate(a,h) + ($t1,$t2) = ($t2,$t1); # rotate(t1,t2) + } + &mov ("esi",&DWP(96,"esp")); #ctx + #&mov ($AH[0],&DWP(0,"esp")); + &xor ($AH[1],"edi"); #&mov ($AH[1],&DWP(4,"esp")); + #&mov ("edi", &DWP(8,"esp")); + &mov ("ecx",&DWP(12,"esp")); + &add ($AH[0],&DWP(0,"esi")); + &add ($AH[1],&DWP(4,"esi")); + &add ("edi",&DWP(8,"esi")); + &add ("ecx",&DWP(12,"esi")); + &mov (&DWP(0,"esi"),$AH[0]); + &mov (&DWP(4,"esi"),$AH[1]); + &mov (&DWP(8,"esi"),"edi"); + &mov (&DWP(12,"esi"),"ecx"); + #&mov (&DWP(0,"esp"),$AH[0]); + &mov (&DWP(4,"esp"),$AH[1]); + &xor ($AH[1],"edi"); # magic + &mov (&DWP(8,"esp"),"edi"); + &mov (&DWP(12,"esp"),"ecx"); + #&mov ($E,&DWP(16,"esp")); + &mov ("edi",&DWP(20,"esp")); + &mov ("ebx",&DWP(24,"esp")); + &mov ("ecx",&DWP(28,"esp")); + &add ($E,&DWP(16,"esi")); + &add ("edi",&DWP(20,"esi")); + &add ("ebx",&DWP(24,"esi")); + &add ("ecx",&DWP(28,"esi")); + &mov (&DWP(16,"esi"),$E); + &mov (&DWP(20,"esi"),"edi"); + &mov (&DWP(24,"esi"),"ebx"); + &mov (&DWP(28,"esi"),"ecx"); + #&mov (&DWP(16,"esp"),$E); + &mov (&DWP(20,"esp"),"edi"); + &mov ("edi",&DWP(96+4,"esp")); # inp + &mov (&DWP(24,"esp"),"ebx"); + &mov (&DWP(28,"esp"),"ecx"); + + &cmp ("edi",&DWP(96+8,"esp")); # are we done yet? + &jb (&label("grand_loop")); + + &mov ("esp",&DWP(96+12,"esp")); # restore sp +&function_end_A(); +} + if (!$i386 && $xmm) {{{ +if ($shaext) { +###################################################################### +# Intel SHA Extensions implementation of SHA256 update function. +# +my ($ctx,$inp,$end)=("esi","edi","eax"); +my ($Wi,$ABEF,$CDGH,$TMP)=map("xmm$_",(0..2,7)); +my @MSG=map("xmm$_",(3..6)); + +sub sha256op38 { + my ($opcodelet,$dst,$src)=@_; + if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/) + { &data_byte(0x0f,0x38,$opcodelet,0xc0|($1<<3)|$2); } +} +sub sha256rnds2 { sha256op38(0xcb,@_); } +sub sha256msg1 { sha256op38(0xcc,@_); } +sub sha256msg2 { sha256op38(0xcd,@_); } + +&set_label("shaext",32); + &sub ("esp",32); + + &movdqu ($ABEF,&QWP(0,$ctx)); # DCBA + &lea ($K256,&DWP(0x80,$K256)); + &movdqu ($CDGH,&QWP(16,$ctx)); # HGFE + &movdqa ($TMP,&QWP(0x100-0x80,$K256)); # byte swap mask + + &pshufd ($Wi,$ABEF,0x1b); # ABCD + &pshufd ($ABEF,$ABEF,0xb1); # CDAB + &pshufd ($CDGH,$CDGH,0x1b); # EFGH + &palignr ($ABEF,$CDGH,8); # ABEF + &punpcklqdq ($CDGH,$Wi); # CDGH + &jmp (&label("loop_shaext")); + +&set_label("loop_shaext",16); + &movdqu (@MSG[0],&QWP(0,$inp)); + &movdqu (@MSG[1],&QWP(0x10,$inp)); + &movdqu (@MSG[2],&QWP(0x20,$inp)); + &pshufb (@MSG[0],$TMP); + &movdqu (@MSG[3],&QWP(0x30,$inp)); + &movdqa (&QWP(16,"esp"),$CDGH); # offload + + &movdqa ($Wi,&QWP(0*16-0x80,$K256)); + &paddd ($Wi,@MSG[0]); + &pshufb (@MSG[1],$TMP); + &sha256rnds2 ($CDGH,$ABEF); # 0-3 + &pshufd ($Wi,$Wi,0x0e); + &nop (); + &movdqa (&QWP(0,"esp"),$ABEF); # offload + &sha256rnds2 ($ABEF,$CDGH); + + &movdqa ($Wi,&QWP(1*16-0x80,$K256)); + &paddd ($Wi,@MSG[1]); + &pshufb (@MSG[2],$TMP); + &sha256rnds2 ($CDGH,$ABEF); # 4-7 + &pshufd ($Wi,$Wi,0x0e); + &lea ($inp,&DWP(0x40,$inp)); + &sha256msg1 (@MSG[0],@MSG[1]); + &sha256rnds2 ($ABEF,$CDGH); + + &movdqa ($Wi,&QWP(2*16-0x80,$K256)); + &paddd ($Wi,@MSG[2]); + &pshufb (@MSG[3],$TMP); + &sha256rnds2 ($CDGH,$ABEF); # 8-11 + &pshufd ($Wi,$Wi,0x0e); + &movdqa ($TMP,@MSG[3]); + &palignr ($TMP,@MSG[2],4); + &nop (); + &paddd (@MSG[0],$TMP); + &sha256msg1 (@MSG[1],@MSG[2]); + &sha256rnds2 ($ABEF,$CDGH); + + &movdqa ($Wi,&QWP(3*16-0x80,$K256)); + &paddd ($Wi,@MSG[3]); + &sha256msg2 (@MSG[0],@MSG[3]); + &sha256rnds2 ($CDGH,$ABEF); # 12-15 + &pshufd ($Wi,$Wi,0x0e); + &movdqa ($TMP,@MSG[0]); + &palignr ($TMP,@MSG[3],4); + &nop (); + &paddd (@MSG[1],$TMP); + &sha256msg1 (@MSG[2],@MSG[3]); + &sha256rnds2 ($ABEF,$CDGH); + +for($i=4;$i<16-3;$i++) { + &movdqa ($Wi,&QWP($i*16-0x80,$K256)); + &paddd ($Wi,@MSG[0]); + &sha256msg2 (@MSG[1],@MSG[0]); + &sha256rnds2 ($CDGH,$ABEF); # 16-19... + &pshufd ($Wi,$Wi,0x0e); + &movdqa ($TMP,@MSG[1]); + &palignr ($TMP,@MSG[0],4); + &nop (); + &paddd (@MSG[2],$TMP); + &sha256msg1 (@MSG[3],@MSG[0]); + &sha256rnds2 ($ABEF,$CDGH); + + push(@MSG,shift(@MSG)); +} + &movdqa ($Wi,&QWP(13*16-0x80,$K256)); + &paddd ($Wi,@MSG[0]); + &sha256msg2 (@MSG[1],@MSG[0]); + &sha256rnds2 ($CDGH,$ABEF); # 52-55 + &pshufd ($Wi,$Wi,0x0e); + &movdqa ($TMP,@MSG[1]) + &palignr ($TMP,@MSG[0],4); + &sha256rnds2 ($ABEF,$CDGH); + &paddd (@MSG[2],$TMP); + + &movdqa ($Wi,&QWP(14*16-0x80,$K256)); + &paddd ($Wi,@MSG[1]); + &sha256rnds2 ($CDGH,$ABEF); # 56-59 + &pshufd ($Wi,$Wi,0x0e); + &sha256msg2 (@MSG[2],@MSG[1]); + &movdqa ($TMP,&QWP(0x100-0x80,$K256)); # byte swap mask + &sha256rnds2 ($ABEF,$CDGH); + + &movdqa ($Wi,&QWP(15*16-0x80,$K256)); + &paddd ($Wi,@MSG[2]); + &nop (); + &sha256rnds2 ($CDGH,$ABEF); # 60-63 + &pshufd ($Wi,$Wi,0x0e); + &cmp ($end,$inp); + &nop (); + &sha256rnds2 ($ABEF,$CDGH); + + &paddd ($CDGH,&QWP(16,"esp")); + &paddd ($ABEF,&QWP(0,"esp")); + &jnz (&label("loop_shaext")); + + &pshufd ($CDGH,$CDGH,0xb1); # DCHG + &pshufd ($TMP,$ABEF,0x1b); # FEBA + &pshufd ($ABEF,$ABEF,0xb1); # BAFE + &punpckhqdq ($ABEF,$CDGH); # DCBA + &palignr ($CDGH,$TMP,8); # HGFE + + &mov ("esp",&DWP(32+12,"esp")); + &movdqu (&QWP(0,$ctx),$ABEF); + &movdqu (&QWP(16,$ctx),$CDGH); +&function_end_A(); +} + +my @X = map("xmm$_",(0..3)); +my ($t0,$t1,$t2,$t3) = map("xmm$_",(4..7)); +my @AH = ($A,$T); + +&set_label("SSSE3",32); + &lea ("esp",&DWP(-96,"esp")); + # copy ctx->h[0-7] to A,B,C,D,E,F,G,H on stack + &mov ($AH[0],&DWP(0,"esi")); + &mov ($AH[1],&DWP(4,"esi")); + &mov ("ecx",&DWP(8,"esi")); + &mov ("edi",&DWP(12,"esi")); + #&mov (&DWP(0,"esp"),$AH[0]); + &mov (&DWP(4,"esp"),$AH[1]); + &xor ($AH[1],"ecx"); # magic + &mov (&DWP(8,"esp"),"ecx"); + &mov (&DWP(12,"esp"),"edi"); + &mov ($E,&DWP(16,"esi")); + &mov ("edi",&DWP(20,"esi")); + &mov ("ecx",&DWP(24,"esi")); + &mov ("esi",&DWP(28,"esi")); + #&mov (&DWP(16,"esp"),$E); + &mov (&DWP(20,"esp"),"edi"); + &mov ("edi",&DWP(96+4,"esp")); # inp + &mov (&DWP(24,"esp"),"ecx"); + &mov (&DWP(28,"esp"),"esi"); + &movdqa ($t3,&QWP(256,$K256)); + &jmp (&label("grand_ssse3")); + +&set_label("grand_ssse3",16); + # load input, reverse byte order, add K256[0..15], save to stack + &movdqu (@X[0],&QWP(0,"edi")); + &movdqu (@X[1],&QWP(16,"edi")); + &movdqu (@X[2],&QWP(32,"edi")); + &movdqu (@X[3],&QWP(48,"edi")); + &add ("edi",64); + &pshufb (@X[0],$t3); + &mov (&DWP(96+4,"esp"),"edi"); + &pshufb (@X[1],$t3); + &movdqa ($t0,&QWP(0,$K256)); + &pshufb (@X[2],$t3); + &movdqa ($t1,&QWP(16,$K256)); + &paddd ($t0,@X[0]); + &pshufb (@X[3],$t3); + &movdqa ($t2,&QWP(32,$K256)); + &paddd ($t1,@X[1]); + &movdqa ($t3,&QWP(48,$K256)); + &movdqa (&QWP(32+0,"esp"),$t0); + &paddd ($t2,@X[2]); + &movdqa (&QWP(32+16,"esp"),$t1); + &paddd ($t3,@X[3]); + &movdqa (&QWP(32+32,"esp"),$t2); + &movdqa (&QWP(32+48,"esp"),$t3); + &jmp (&label("ssse3_00_47")); + +&set_label("ssse3_00_47",16); + &add ($K256,64); + +sub SSSE3_00_47 () { +my $j = shift; +my $body = shift; +my @X = @_; +my @insns = (&$body,&$body,&$body,&$body); # 120 instructions + + eval(shift(@insns)); + &movdqa ($t0,@X[1]); + eval(shift(@insns)); # @ + eval(shift(@insns)); + &movdqa ($t3,@X[3]); + eval(shift(@insns)); + eval(shift(@insns)); + &palignr ($t0,@X[0],4); # X[1..4] + eval(shift(@insns)); + eval(shift(@insns)); # @ + eval(shift(@insns)); + &palignr ($t3,@X[2],4); # X[9..12] + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &movdqa ($t1,$t0); + eval(shift(@insns)); # @ + eval(shift(@insns)); + &movdqa ($t2,$t0); + eval(shift(@insns)); + eval(shift(@insns)); + &psrld ($t0,3); + eval(shift(@insns)); + eval(shift(@insns)); # @ + &paddd (@X[0],$t3); # X[0..3] += X[9..12] + eval(shift(@insns)); + eval(shift(@insns)); + &psrld ($t2,7); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # @ + eval(shift(@insns)); + &pshufd ($t3,@X[3],0b11111010); # X[14..15] + eval(shift(@insns)); + eval(shift(@insns)); + &pslld ($t1,32-18); + eval(shift(@insns)); + eval(shift(@insns)); # @ + &pxor ($t0,$t2); + eval(shift(@insns)); + eval(shift(@insns)); + &psrld ($t2,18-7); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # @ + &pxor ($t0,$t1); + eval(shift(@insns)); + eval(shift(@insns)); + &pslld ($t1,18-7); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # @ + &pxor ($t0,$t2); + eval(shift(@insns)); + eval(shift(@insns)); + &movdqa ($t2,$t3); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # @ + &pxor ($t0,$t1); # sigma0(X[1..4]) + eval(shift(@insns)); + eval(shift(@insns)); + &psrld ($t3,10); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # @ + &paddd (@X[0],$t0); # X[0..3] += sigma0(X[1..4]) + eval(shift(@insns)); + eval(shift(@insns)); + &psrlq ($t2,17); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # @ + &pxor ($t3,$t2); + eval(shift(@insns)); + eval(shift(@insns)); + &psrlq ($t2,19-17); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # @ + &pxor ($t3,$t2); + eval(shift(@insns)); + eval(shift(@insns)); + &pshufd ($t3,$t3,0b10000000); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # @ + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # @ + eval(shift(@insns)); + &psrldq ($t3,8); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &paddd (@X[0],$t3); # X[0..1] += sigma1(X[14..15]) + eval(shift(@insns)); # @ + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # @ + eval(shift(@insns)); + &pshufd ($t3,@X[0],0b01010000); # X[16..17] + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &movdqa ($t2,$t3); + eval(shift(@insns)); # @ + &psrld ($t3,10); + eval(shift(@insns)); + &psrlq ($t2,17); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # @ + &pxor ($t3,$t2); + eval(shift(@insns)); + eval(shift(@insns)); + &psrlq ($t2,19-17); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # @ + &pxor ($t3,$t2); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &pshufd ($t3,$t3,0b00001000); + eval(shift(@insns)); + eval(shift(@insns)); # @ + &movdqa ($t2,&QWP(16*$j,$K256)); + eval(shift(@insns)); + eval(shift(@insns)); + &pslldq ($t3,8); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # @ + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); # @ + &paddd (@X[0],$t3); # X[2..3] += sigma1(X[16..17]) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &paddd ($t2,@X[0]); + eval(shift(@insns)); # @ + + foreach (@insns) { eval; } # remaining instructions + + &movdqa (&QWP(32+16*$j,"esp"),$t2); +} + +sub body_00_15 () { + ( + '&mov ("ecx",$E);', + '&ror ($E,25-11);', + '&mov ("esi",&off($f));', + '&xor ($E,"ecx");', + '&mov ("edi",&off($g));', + '&xor ("esi","edi");', + '&ror ($E,11-6);', + '&and ("esi","ecx");', + '&mov (&off($e),"ecx");', # save $E, modulo-scheduled + '&xor ($E,"ecx");', + '&xor ("edi","esi");', # Ch(e,f,g) + '&ror ($E,6);', # T = Sigma1(e) + '&mov ("ecx",$AH[0]);', + '&add ($E,"edi");', # T += Ch(e,f,g) + '&mov ("edi",&off($b));', + '&mov ("esi",$AH[0]);', + + '&ror ("ecx",22-13);', + '&mov (&off($a),$AH[0]);', # save $A, modulo-scheduled + '&xor ("ecx",$AH[0]);', + '&xor ($AH[0],"edi");', # a ^= b, (b^c) in next round + '&add ($E,&off($h));', # T += h + '&ror ("ecx",13-2);', + '&and ($AH[1],$AH[0]);', # (b^c) &= (a^b) + '&xor ("ecx","esi");', + '&add ($E,&DWP(32+4*($i&15),"esp"));', # T += K[i]+X[i] + '&xor ($AH[1],"edi");', # h = Maj(a,b,c) = Ch(a^b,c,b) + '&ror ("ecx",2);', # Sigma0(a) + + '&add ($AH[1],$E);', # h += T + '&add ($E,&off($d));', # d += T + '&add ($AH[1],"ecx");'. # h += Sigma0(a) + + '@AH = reverse(@AH); $i++;' # rotate(a,h) + ); +} + + for ($i=0,$j=0; $j<4; $j++) { + &SSSE3_00_47($j,\&body_00_15,@X); + push(@X,shift(@X)); # rotate(@X) + } + &cmp (&DWP(16*$j,$K256),0x00010203); + &jne (&label("ssse3_00_47")); + + for ($i=0; $i<16; ) { + foreach(body_00_15()) { eval; } + } + + &mov ("esi",&DWP(96,"esp")); #ctx + #&mov ($AH[0],&DWP(0,"esp")); + &xor ($AH[1],"edi"); #&mov ($AH[1],&DWP(4,"esp")); + #&mov ("edi", &DWP(8,"esp")); + &mov ("ecx",&DWP(12,"esp")); + &add ($AH[0],&DWP(0,"esi")); + &add ($AH[1],&DWP(4,"esi")); + &add ("edi",&DWP(8,"esi")); + &add ("ecx",&DWP(12,"esi")); + &mov (&DWP(0,"esi"),$AH[0]); + &mov (&DWP(4,"esi"),$AH[1]); + &mov (&DWP(8,"esi"),"edi"); + &mov (&DWP(12,"esi"),"ecx"); + #&mov (&DWP(0,"esp"),$AH[0]); + &mov (&DWP(4,"esp"),$AH[1]); + &xor ($AH[1],"edi"); # magic + &mov (&DWP(8,"esp"),"edi"); + &mov (&DWP(12,"esp"),"ecx"); + #&mov ($E,&DWP(16,"esp")); + &mov ("edi",&DWP(20,"esp")); + &mov ("ecx",&DWP(24,"esp")); + &add ($E,&DWP(16,"esi")); + &add ("edi",&DWP(20,"esi")); + &add ("ecx",&DWP(24,"esi")); + &mov (&DWP(16,"esi"),$E); + &mov (&DWP(20,"esi"),"edi"); + &mov (&DWP(20,"esp"),"edi"); + &mov ("edi",&DWP(28,"esp")); + &mov (&DWP(24,"esi"),"ecx"); + #&mov (&DWP(16,"esp"),$E); + &add ("edi",&DWP(28,"esi")); + &mov (&DWP(24,"esp"),"ecx"); + &mov (&DWP(28,"esi"),"edi"); + &mov (&DWP(28,"esp"),"edi"); + &mov ("edi",&DWP(96+4,"esp")); # inp + + &movdqa ($t3,&QWP(64,$K256)); + &sub ($K256,3*64); # rewind K + &cmp ("edi",&DWP(96+8,"esp")); # are we done yet? + &jb (&label("grand_ssse3")); + + &mov ("esp",&DWP(96+12,"esp")); # restore sp +&function_end_A(); + if ($avx) { +&set_label("AVX",32); + if ($avx>1) { + &and ("edx",1<<8|1<<3); # check for BMI2+BMI1 + &cmp ("edx",1<<8|1<<3); + &je (&label("AVX_BMI")); + } + &lea ("esp",&DWP(-96,"esp")); + &vzeroall (); + # copy ctx->h[0-7] to A,B,C,D,E,F,G,H on stack + &mov ($AH[0],&DWP(0,"esi")); + &mov ($AH[1],&DWP(4,"esi")); + &mov ("ecx",&DWP(8,"esi")); + &mov ("edi",&DWP(12,"esi")); + #&mov (&DWP(0,"esp"),$AH[0]); + &mov (&DWP(4,"esp"),$AH[1]); + &xor ($AH[1],"ecx"); # magic + &mov (&DWP(8,"esp"),"ecx"); + &mov (&DWP(12,"esp"),"edi"); + &mov ($E,&DWP(16,"esi")); + &mov ("edi",&DWP(20,"esi")); + &mov ("ecx",&DWP(24,"esi")); + &mov ("esi",&DWP(28,"esi")); + #&mov (&DWP(16,"esp"),$E); + &mov (&DWP(20,"esp"),"edi"); + &mov ("edi",&DWP(96+4,"esp")); # inp + &mov (&DWP(24,"esp"),"ecx"); + &mov (&DWP(28,"esp"),"esi"); + &vmovdqa ($t3,&QWP(256,$K256)); + &jmp (&label("grand_avx")); + +&set_label("grand_avx",32); + # load input, reverse byte order, add K256[0..15], save to stack + &vmovdqu (@X[0],&QWP(0,"edi")); + &vmovdqu (@X[1],&QWP(16,"edi")); + &vmovdqu (@X[2],&QWP(32,"edi")); + &vmovdqu (@X[3],&QWP(48,"edi")); + &add ("edi",64); + &vpshufb (@X[0],@X[0],$t3); + &mov (&DWP(96+4,"esp"),"edi"); + &vpshufb (@X[1],@X[1],$t3); + &vpshufb (@X[2],@X[2],$t3); + &vpaddd ($t0,@X[0],&QWP(0,$K256)); + &vpshufb (@X[3],@X[3],$t3); + &vpaddd ($t1,@X[1],&QWP(16,$K256)); + &vpaddd ($t2,@X[2],&QWP(32,$K256)); + &vpaddd ($t3,@X[3],&QWP(48,$K256)); + &vmovdqa (&QWP(32+0,"esp"),$t0); + &vmovdqa (&QWP(32+16,"esp"),$t1); + &vmovdqa (&QWP(32+32,"esp"),$t2); + &vmovdqa (&QWP(32+48,"esp"),$t3); + &jmp (&label("avx_00_47")); + +&set_label("avx_00_47",16); + &add ($K256,64); + +sub Xupdate_AVX () { + ( + '&vpalignr ($t0,@X[1],@X[0],4);', # X[1..4] + '&vpalignr ($t3,@X[3],@X[2],4);', # X[9..12] + '&vpsrld ($t2,$t0,7);', + '&vpaddd (@X[0],@X[0],$t3);', # X[0..3] += X[9..16] + '&vpsrld ($t3,$t0,3);', + '&vpslld ($t1,$t0,14);', + '&vpxor ($t0,$t3,$t2);', + '&vpshufd ($t3,@X[3],0b11111010)',# X[14..15] + '&vpsrld ($t2,$t2,18-7);', + '&vpxor ($t0,$t0,$t1);', + '&vpslld ($t1,$t1,25-14);', + '&vpxor ($t0,$t0,$t2);', + '&vpsrld ($t2,$t3,10);', + '&vpxor ($t0,$t0,$t1);', # sigma0(X[1..4]) + '&vpsrlq ($t1,$t3,17);', + '&vpaddd (@X[0],@X[0],$t0);', # X[0..3] += sigma0(X[1..4]) + '&vpxor ($t2,$t2,$t1);', + '&vpsrlq ($t3,$t3,19);', + '&vpxor ($t2,$t2,$t3);', # sigma1(X[14..15] + '&vpshufd ($t3,$t2,0b10000100);', + '&vpsrldq ($t3,$t3,8);', + '&vpaddd (@X[0],@X[0],$t3);', # X[0..1] += sigma1(X[14..15]) + '&vpshufd ($t3,@X[0],0b01010000)',# X[16..17] + '&vpsrld ($t2,$t3,10);', + '&vpsrlq ($t1,$t3,17);', + '&vpxor ($t2,$t2,$t1);', + '&vpsrlq ($t3,$t3,19);', + '&vpxor ($t2,$t2,$t3);', # sigma1(X[16..17] + '&vpshufd ($t3,$t2,0b11101000);', + '&vpslldq ($t3,$t3,8);', + '&vpaddd (@X[0],@X[0],$t3);' # X[2..3] += sigma1(X[16..17]) + ); +} + +local *ror = sub { &shrd(@_[0],@_) }; +sub AVX_00_47 () { +my $j = shift; +my $body = shift; +my @X = @_; +my @insns = (&$body,&$body,&$body,&$body); # 120 instructions +my $insn; + + foreach (Xupdate_AVX()) { # 31 instructions + eval; + eval(shift(@insns)); + eval(shift(@insns)); + eval($insn = shift(@insns)); + eval(shift(@insns)) if ($insn =~ /rorx/ && @insns[0] =~ /rorx/); + } + &vpaddd ($t2,@X[0],&QWP(16*$j,$K256)); + foreach (@insns) { eval; } # remaining instructions + &vmovdqa (&QWP(32+16*$j,"esp"),$t2); +} + + for ($i=0,$j=0; $j<4; $j++) { + &AVX_00_47($j,\&body_00_15,@X); + push(@X,shift(@X)); # rotate(@X) + } + &cmp (&DWP(16*$j,$K256),0x00010203); + &jne (&label("avx_00_47")); + + for ($i=0; $i<16; ) { + foreach(body_00_15()) { eval; } + } + + &mov ("esi",&DWP(96,"esp")); #ctx + #&mov ($AH[0],&DWP(0,"esp")); + &xor ($AH[1],"edi"); #&mov ($AH[1],&DWP(4,"esp")); + #&mov ("edi", &DWP(8,"esp")); + &mov ("ecx",&DWP(12,"esp")); + &add ($AH[0],&DWP(0,"esi")); + &add ($AH[1],&DWP(4,"esi")); + &add ("edi",&DWP(8,"esi")); + &add ("ecx",&DWP(12,"esi")); + &mov (&DWP(0,"esi"),$AH[0]); + &mov (&DWP(4,"esi"),$AH[1]); + &mov (&DWP(8,"esi"),"edi"); + &mov (&DWP(12,"esi"),"ecx"); + #&mov (&DWP(0,"esp"),$AH[0]); + &mov (&DWP(4,"esp"),$AH[1]); + &xor ($AH[1],"edi"); # magic + &mov (&DWP(8,"esp"),"edi"); + &mov (&DWP(12,"esp"),"ecx"); + #&mov ($E,&DWP(16,"esp")); + &mov ("edi",&DWP(20,"esp")); + &mov ("ecx",&DWP(24,"esp")); + &add ($E,&DWP(16,"esi")); + &add ("edi",&DWP(20,"esi")); + &add ("ecx",&DWP(24,"esi")); + &mov (&DWP(16,"esi"),$E); + &mov (&DWP(20,"esi"),"edi"); + &mov (&DWP(20,"esp"),"edi"); + &mov ("edi",&DWP(28,"esp")); + &mov (&DWP(24,"esi"),"ecx"); + #&mov (&DWP(16,"esp"),$E); + &add ("edi",&DWP(28,"esi")); + &mov (&DWP(24,"esp"),"ecx"); + &mov (&DWP(28,"esi"),"edi"); + &mov (&DWP(28,"esp"),"edi"); + &mov ("edi",&DWP(96+4,"esp")); # inp + + &vmovdqa ($t3,&QWP(64,$K256)); + &sub ($K256,3*64); # rewind K + &cmp ("edi",&DWP(96+8,"esp")); # are we done yet? + &jb (&label("grand_avx")); + + &mov ("esp",&DWP(96+12,"esp")); # restore sp + &vzeroall (); +&function_end_A(); + if ($avx>1) { +sub bodyx_00_15 () { # +10% + ( + '&rorx ("ecx",$E,6)', + '&rorx ("esi",$E,11)', + '&mov (&off($e),$E)', # save $E, modulo-scheduled + '&rorx ("edi",$E,25)', + '&xor ("ecx","esi")', + '&andn ("esi",$E,&off($g))', + '&xor ("ecx","edi")', # Sigma1(e) + '&and ($E,&off($f))', + '&mov (&off($a),$AH[0]);', # save $A, modulo-scheduled + '&or ($E,"esi")', # T = Ch(e,f,g) + + '&rorx ("edi",$AH[0],2)', + '&rorx ("esi",$AH[0],13)', + '&lea ($E,&DWP(0,$E,"ecx"))', # T += Sigma1(e) + '&rorx ("ecx",$AH[0],22)', + '&xor ("esi","edi")', + '&mov ("edi",&off($b))', + '&xor ("ecx","esi")', # Sigma0(a) + + '&xor ($AH[0],"edi")', # a ^= b, (b^c) in next round + '&add ($E,&off($h))', # T += h + '&and ($AH[1],$AH[0])', # (b^c) &= (a^b) + '&add ($E,&DWP(32+4*($i&15),"esp"))', # T += K[i]+X[i] + '&xor ($AH[1],"edi")', # h = Maj(a,b,c) = Ch(a^b,c,b) + + '&add ("ecx",$E)', # h += T + '&add ($E,&off($d))', # d += T + '&lea ($AH[1],&DWP(0,$AH[1],"ecx"));'. # h += Sigma0(a) + + '@AH = reverse(@AH); $i++;' # rotate(a,h) + ); +} + +&set_label("AVX_BMI",32); + &lea ("esp",&DWP(-96,"esp")); + &vzeroall (); + # copy ctx->h[0-7] to A,B,C,D,E,F,G,H on stack + &mov ($AH[0],&DWP(0,"esi")); + &mov ($AH[1],&DWP(4,"esi")); + &mov ("ecx",&DWP(8,"esi")); + &mov ("edi",&DWP(12,"esi")); + #&mov (&DWP(0,"esp"),$AH[0]); + &mov (&DWP(4,"esp"),$AH[1]); + &xor ($AH[1],"ecx"); # magic + &mov (&DWP(8,"esp"),"ecx"); + &mov (&DWP(12,"esp"),"edi"); + &mov ($E,&DWP(16,"esi")); + &mov ("edi",&DWP(20,"esi")); + &mov ("ecx",&DWP(24,"esi")); + &mov ("esi",&DWP(28,"esi")); + #&mov (&DWP(16,"esp"),$E); + &mov (&DWP(20,"esp"),"edi"); + &mov ("edi",&DWP(96+4,"esp")); # inp + &mov (&DWP(24,"esp"),"ecx"); + &mov (&DWP(28,"esp"),"esi"); + &vmovdqa ($t3,&QWP(256,$K256)); + &jmp (&label("grand_avx_bmi")); + +&set_label("grand_avx_bmi",32); + # load input, reverse byte order, add K256[0..15], save to stack + &vmovdqu (@X[0],&QWP(0,"edi")); + &vmovdqu (@X[1],&QWP(16,"edi")); + &vmovdqu (@X[2],&QWP(32,"edi")); + &vmovdqu (@X[3],&QWP(48,"edi")); + &add ("edi",64); + &vpshufb (@X[0],@X[0],$t3); + &mov (&DWP(96+4,"esp"),"edi"); + &vpshufb (@X[1],@X[1],$t3); + &vpshufb (@X[2],@X[2],$t3); + &vpaddd ($t0,@X[0],&QWP(0,$K256)); + &vpshufb (@X[3],@X[3],$t3); + &vpaddd ($t1,@X[1],&QWP(16,$K256)); + &vpaddd ($t2,@X[2],&QWP(32,$K256)); + &vpaddd ($t3,@X[3],&QWP(48,$K256)); + &vmovdqa (&QWP(32+0,"esp"),$t0); + &vmovdqa (&QWP(32+16,"esp"),$t1); + &vmovdqa (&QWP(32+32,"esp"),$t2); + &vmovdqa (&QWP(32+48,"esp"),$t3); + &jmp (&label("avx_bmi_00_47")); + +&set_label("avx_bmi_00_47",16); + &add ($K256,64); + + for ($i=0,$j=0; $j<4; $j++) { + &AVX_00_47($j,\&bodyx_00_15,@X); + push(@X,shift(@X)); # rotate(@X) + } + &cmp (&DWP(16*$j,$K256),0x00010203); + &jne (&label("avx_bmi_00_47")); + + for ($i=0; $i<16; ) { + foreach(bodyx_00_15()) { eval; } + } + + &mov ("esi",&DWP(96,"esp")); #ctx + #&mov ($AH[0],&DWP(0,"esp")); + &xor ($AH[1],"edi"); #&mov ($AH[1],&DWP(4,"esp")); + #&mov ("edi", &DWP(8,"esp")); + &mov ("ecx",&DWP(12,"esp")); + &add ($AH[0],&DWP(0,"esi")); + &add ($AH[1],&DWP(4,"esi")); + &add ("edi",&DWP(8,"esi")); + &add ("ecx",&DWP(12,"esi")); + &mov (&DWP(0,"esi"),$AH[0]); + &mov (&DWP(4,"esi"),$AH[1]); + &mov (&DWP(8,"esi"),"edi"); + &mov (&DWP(12,"esi"),"ecx"); + #&mov (&DWP(0,"esp"),$AH[0]); + &mov (&DWP(4,"esp"),$AH[1]); + &xor ($AH[1],"edi"); # magic + &mov (&DWP(8,"esp"),"edi"); + &mov (&DWP(12,"esp"),"ecx"); + #&mov ($E,&DWP(16,"esp")); + &mov ("edi",&DWP(20,"esp")); + &mov ("ecx",&DWP(24,"esp")); + &add ($E,&DWP(16,"esi")); + &add ("edi",&DWP(20,"esi")); + &add ("ecx",&DWP(24,"esi")); + &mov (&DWP(16,"esi"),$E); + &mov (&DWP(20,"esi"),"edi"); + &mov (&DWP(20,"esp"),"edi"); + &mov ("edi",&DWP(28,"esp")); + &mov (&DWP(24,"esi"),"ecx"); + #&mov (&DWP(16,"esp"),$E); + &add ("edi",&DWP(28,"esi")); + &mov (&DWP(24,"esp"),"ecx"); + &mov (&DWP(28,"esi"),"edi"); + &mov (&DWP(28,"esp"),"edi"); + &mov ("edi",&DWP(96+4,"esp")); # inp + + &vmovdqa ($t3,&QWP(64,$K256)); + &sub ($K256,3*64); # rewind K + &cmp ("edi",&DWP(96+8,"esp")); # are we done yet? + &jb (&label("grand_avx_bmi")); + + &mov ("esp",&DWP(96+12,"esp")); # restore sp + &vzeroall (); +&function_end_A(); + } + } + }}} +&function_end_B("sha256_block_data_order"); + +&asm_finish(); + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha256-armv4.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha256-armv4.pl new file mode 100644 index 000000000..edcfc3127 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha256-armv4.pl @@ -0,0 +1,732 @@ +#! /usr/bin/env perl +# Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# +# Permission to use under GPL terms is granted. +# ==================================================================== + +# SHA256 block procedure for ARMv4. May 2007. + +# Performance is ~2x better than gcc 3.4 generated code and in "abso- +# lute" terms is ~2250 cycles per 64-byte block or ~35 cycles per +# byte [on single-issue Xscale PXA250 core]. + +# July 2010. +# +# Rescheduling for dual-issue pipeline resulted in 22% improvement on +# Cortex A8 core and ~20 cycles per processed byte. + +# February 2011. +# +# Profiler-assisted and platform-specific optimization resulted in 16% +# improvement on Cortex A8 core and ~15.4 cycles per processed byte. + +# September 2013. +# +# Add NEON implementation. On Cortex A8 it was measured to process one +# byte in 12.5 cycles or 23% faster than integer-only code. Snapdragon +# S4 does it in 12.5 cycles too, but it's 50% faster than integer-only +# code (meaning that latter performs sub-optimally, nothing was done +# about it). + +# May 2014. +# +# Add ARMv8 code path performing at 2.0 cpb on Apple A7. + +$flavour = shift; +if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + open STDOUT,">$output"; +} + +$ctx="r0"; $t0="r0"; +$inp="r1"; $t4="r1"; +$len="r2"; $t1="r2"; +$T1="r3"; $t3="r3"; +$A="r4"; +$B="r5"; +$C="r6"; +$D="r7"; +$E="r8"; +$F="r9"; +$G="r10"; +$H="r11"; +@V=($A,$B,$C,$D,$E,$F,$G,$H); +$t2="r12"; +$Ktbl="r14"; + +@Sigma0=( 2,13,22); +@Sigma1=( 6,11,25); +@sigma0=( 7,18, 3); +@sigma1=(17,19,10); + +sub BODY_00_15 { +my ($i,$a,$b,$c,$d,$e,$f,$g,$h) = @_; + +$code.=<<___ if ($i<16); +#if __ARM_ARCH__>=7 + @ ldr $t1,[$inp],#4 @ $i +# if $i==15 + str $inp,[sp,#17*4] @ make room for $t4 +# endif + eor $t0,$e,$e,ror#`$Sigma1[1]-$Sigma1[0]` + add $a,$a,$t2 @ h+=Maj(a,b,c) from the past + eor $t0,$t0,$e,ror#`$Sigma1[2]-$Sigma1[0]` @ Sigma1(e) +# ifndef __ARMEB__ + rev $t1,$t1 +# endif +#else + @ ldrb $t1,[$inp,#3] @ $i + add $a,$a,$t2 @ h+=Maj(a,b,c) from the past + ldrb $t2,[$inp,#2] + ldrb $t0,[$inp,#1] + orr $t1,$t1,$t2,lsl#8 + ldrb $t2,[$inp],#4 + orr $t1,$t1,$t0,lsl#16 +# if $i==15 + str $inp,[sp,#17*4] @ make room for $t4 +# endif + eor $t0,$e,$e,ror#`$Sigma1[1]-$Sigma1[0]` + orr $t1,$t1,$t2,lsl#24 + eor $t0,$t0,$e,ror#`$Sigma1[2]-$Sigma1[0]` @ Sigma1(e) +#endif +___ +$code.=<<___; + ldr $t2,[$Ktbl],#4 @ *K256++ + add $h,$h,$t1 @ h+=X[i] + str $t1,[sp,#`$i%16`*4] + eor $t1,$f,$g + add $h,$h,$t0,ror#$Sigma1[0] @ h+=Sigma1(e) + and $t1,$t1,$e + add $h,$h,$t2 @ h+=K256[i] + eor $t1,$t1,$g @ Ch(e,f,g) + eor $t0,$a,$a,ror#`$Sigma0[1]-$Sigma0[0]` + add $h,$h,$t1 @ h+=Ch(e,f,g) +#if $i==31 + and $t2,$t2,#0xff + cmp $t2,#0xf2 @ done? +#endif +#if $i<15 +# if __ARM_ARCH__>=7 + ldr $t1,[$inp],#4 @ prefetch +# else + ldrb $t1,[$inp,#3] +# endif + eor $t2,$a,$b @ a^b, b^c in next round +#else + ldr $t1,[sp,#`($i+2)%16`*4] @ from future BODY_16_xx + eor $t2,$a,$b @ a^b, b^c in next round + ldr $t4,[sp,#`($i+15)%16`*4] @ from future BODY_16_xx +#endif + eor $t0,$t0,$a,ror#`$Sigma0[2]-$Sigma0[0]` @ Sigma0(a) + and $t3,$t3,$t2 @ (b^c)&=(a^b) + add $d,$d,$h @ d+=h + eor $t3,$t3,$b @ Maj(a,b,c) + add $h,$h,$t0,ror#$Sigma0[0] @ h+=Sigma0(a) + @ add $h,$h,$t3 @ h+=Maj(a,b,c) +___ + ($t2,$t3)=($t3,$t2); +} + +sub BODY_16_XX { +my ($i,$a,$b,$c,$d,$e,$f,$g,$h) = @_; + +$code.=<<___; + @ ldr $t1,[sp,#`($i+1)%16`*4] @ $i + @ ldr $t4,[sp,#`($i+14)%16`*4] + mov $t0,$t1,ror#$sigma0[0] + add $a,$a,$t2 @ h+=Maj(a,b,c) from the past + mov $t2,$t4,ror#$sigma1[0] + eor $t0,$t0,$t1,ror#$sigma0[1] + eor $t2,$t2,$t4,ror#$sigma1[1] + eor $t0,$t0,$t1,lsr#$sigma0[2] @ sigma0(X[i+1]) + ldr $t1,[sp,#`($i+0)%16`*4] + eor $t2,$t2,$t4,lsr#$sigma1[2] @ sigma1(X[i+14]) + ldr $t4,[sp,#`($i+9)%16`*4] + + add $t2,$t2,$t0 + eor $t0,$e,$e,ror#`$Sigma1[1]-$Sigma1[0]` @ from BODY_00_15 + add $t1,$t1,$t2 + eor $t0,$t0,$e,ror#`$Sigma1[2]-$Sigma1[0]` @ Sigma1(e) + add $t1,$t1,$t4 @ X[i] +___ + &BODY_00_15(@_); +} + +$code=<<___; +#ifndef __KERNEL__ +# include "arm_arch.h" +#else +# define __ARM_ARCH__ __LINUX_ARM_ARCH__ +# define __ARM_MAX_ARCH__ 7 +#endif + +.text +#if defined(__thumb2__) +.syntax unified +.thumb +#else +.code 32 +#endif + +.type K256,%object +.align 5 +K256: +.word 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 +.word 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 +.word 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 +.word 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 +.word 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc +.word 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da +.word 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 +.word 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967 +.word 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 +.word 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 +.word 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 +.word 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 +.word 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 +.word 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 +.word 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 +.word 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 +.size K256,.-K256 +.word 0 @ terminator +#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) +.LOPENSSL_armcap: +.word OPENSSL_armcap_P-.Lsha256_block_data_order +#endif +.align 5 + +.global sha256_block_data_order +.type sha256_block_data_order,%function +sha256_block_data_order: +.Lsha256_block_data_order: +#if __ARM_ARCH__<7 && !defined(__thumb2__) + sub r3,pc,#8 @ sha256_block_data_order +#else + adr r3,.Lsha256_block_data_order +#endif +#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) + ldr r12,.LOPENSSL_armcap + ldr r12,[r3,r12] @ OPENSSL_armcap_P +#ifdef __APPLE__ + ldr r12,[r12] +#endif + tst r12,#ARMV8_SHA256 + bne .LARMv8 + tst r12,#ARMV7_NEON + bne .LNEON +#endif + add $len,$inp,$len,lsl#6 @ len to point at the end of inp + stmdb sp!,{$ctx,$inp,$len,r4-r11,lr} + ldmia $ctx,{$A,$B,$C,$D,$E,$F,$G,$H} + sub $Ktbl,r3,#256+32 @ K256 + sub sp,sp,#16*4 @ alloca(X[16]) +.Loop: +# if __ARM_ARCH__>=7 + ldr $t1,[$inp],#4 +# else + ldrb $t1,[$inp,#3] +# endif + eor $t3,$B,$C @ magic + eor $t2,$t2,$t2 +___ +for($i=0;$i<16;$i++) { &BODY_00_15($i,@V); unshift(@V,pop(@V)); } +$code.=".Lrounds_16_xx:\n"; +for (;$i<32;$i++) { &BODY_16_XX($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; +#ifdef __thumb2__ + ite eq @ Thumb2 thing, sanity check in ARM +#endif + ldreq $t3,[sp,#16*4] @ pull ctx + bne .Lrounds_16_xx + + add $A,$A,$t2 @ h+=Maj(a,b,c) from the past + ldr $t0,[$t3,#0] + ldr $t1,[$t3,#4] + ldr $t2,[$t3,#8] + add $A,$A,$t0 + ldr $t0,[$t3,#12] + add $B,$B,$t1 + ldr $t1,[$t3,#16] + add $C,$C,$t2 + ldr $t2,[$t3,#20] + add $D,$D,$t0 + ldr $t0,[$t3,#24] + add $E,$E,$t1 + ldr $t1,[$t3,#28] + add $F,$F,$t2 + ldr $inp,[sp,#17*4] @ pull inp + ldr $t2,[sp,#18*4] @ pull inp+len + add $G,$G,$t0 + add $H,$H,$t1 + stmia $t3,{$A,$B,$C,$D,$E,$F,$G,$H} + cmp $inp,$t2 + sub $Ktbl,$Ktbl,#256 @ rewind Ktbl + bne .Loop + + add sp,sp,#`16+3`*4 @ destroy frame +#if __ARM_ARCH__>=5 + ldmia sp!,{r4-r11,pc} +#else + ldmia sp!,{r4-r11,lr} + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.size sha256_block_data_order,.-sha256_block_data_order +___ +###################################################################### +# NEON stuff +# +{{{ +my @X=map("q$_",(0..3)); +my ($T0,$T1,$T2,$T3,$T4,$T5)=("q8","q9","q10","q11","d24","d25"); +my $Xfer=$t4; +my $j=0; + +sub Dlo() { shift=~m|q([1]?[0-9])|?"d".($1*2):""; } +sub Dhi() { shift=~m|q([1]?[0-9])|?"d".($1*2+1):""; } + +sub AUTOLOAD() # thunk [simplified] x86-style perlasm +{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; $opcode =~ s/_/\./; + my $arg = pop; + $arg = "#$arg" if ($arg*1 eq $arg); + $code .= "\t$opcode\t".join(',',@_,$arg)."\n"; +} + +sub Xupdate() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); + my ($a,$b,$c,$d,$e,$f,$g,$h); + + &vext_8 ($T0,@X[0],@X[1],4); # X[1..4] + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vext_8 ($T1,@X[2],@X[3],4); # X[9..12] + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vshr_u32 ($T2,$T0,$sigma0[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &vadd_i32 (@X[0],@X[0],$T1); # X[0..3] += X[9..12] + eval(shift(@insns)); + eval(shift(@insns)); + &vshr_u32 ($T1,$T0,$sigma0[2]); + eval(shift(@insns)); + eval(shift(@insns)); + &vsli_32 ($T2,$T0,32-$sigma0[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &vshr_u32 ($T3,$T0,$sigma0[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &veor ($T1,$T1,$T2); + eval(shift(@insns)); + eval(shift(@insns)); + &vsli_32 ($T3,$T0,32-$sigma0[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &vshr_u32 ($T4,&Dhi(@X[3]),$sigma1[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &veor ($T1,$T1,$T3); # sigma0(X[1..4]) + eval(shift(@insns)); + eval(shift(@insns)); + &vsli_32 ($T4,&Dhi(@X[3]),32-$sigma1[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &vshr_u32 ($T5,&Dhi(@X[3]),$sigma1[2]); + eval(shift(@insns)); + eval(shift(@insns)); + &vadd_i32 (@X[0],@X[0],$T1); # X[0..3] += sigma0(X[1..4]) + eval(shift(@insns)); + eval(shift(@insns)); + &veor ($T5,$T5,$T4); + eval(shift(@insns)); + eval(shift(@insns)); + &vshr_u32 ($T4,&Dhi(@X[3]),$sigma1[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &vsli_32 ($T4,&Dhi(@X[3]),32-$sigma1[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &veor ($T5,$T5,$T4); # sigma1(X[14..15]) + eval(shift(@insns)); + eval(shift(@insns)); + &vadd_i32 (&Dlo(@X[0]),&Dlo(@X[0]),$T5);# X[0..1] += sigma1(X[14..15]) + eval(shift(@insns)); + eval(shift(@insns)); + &vshr_u32 ($T4,&Dlo(@X[0]),$sigma1[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &vsli_32 ($T4,&Dlo(@X[0]),32-$sigma1[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &vshr_u32 ($T5,&Dlo(@X[0]),$sigma1[2]); + eval(shift(@insns)); + eval(shift(@insns)); + &veor ($T5,$T5,$T4); + eval(shift(@insns)); + eval(shift(@insns)); + &vshr_u32 ($T4,&Dlo(@X[0]),$sigma1[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &vld1_32 ("{$T0}","[$Ktbl,:128]!"); + eval(shift(@insns)); + eval(shift(@insns)); + &vsli_32 ($T4,&Dlo(@X[0]),32-$sigma1[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &veor ($T5,$T5,$T4); # sigma1(X[16..17]) + eval(shift(@insns)); + eval(shift(@insns)); + &vadd_i32 (&Dhi(@X[0]),&Dhi(@X[0]),$T5);# X[2..3] += sigma1(X[16..17]) + eval(shift(@insns)); + eval(shift(@insns)); + &vadd_i32 ($T0,$T0,@X[0]); + while($#insns>=2) { eval(shift(@insns)); } + &vst1_32 ("{$T0}","[$Xfer,:128]!"); + eval(shift(@insns)); + eval(shift(@insns)); + + push(@X,shift(@X)); # "rotate" X[] +} + +sub Xpreload() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); + my ($a,$b,$c,$d,$e,$f,$g,$h); + + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vld1_32 ("{$T0}","[$Ktbl,:128]!"); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vrev32_8 (@X[0],@X[0]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vadd_i32 ($T0,$T0,@X[0]); + foreach (@insns) { eval; } # remaining instructions + &vst1_32 ("{$T0}","[$Xfer,:128]!"); + + push(@X,shift(@X)); # "rotate" X[] +} + +sub body_00_15 () { + ( + '($a,$b,$c,$d,$e,$f,$g,$h)=@V;'. + '&add ($h,$h,$t1)', # h+=X[i]+K[i] + '&eor ($t1,$f,$g)', + '&eor ($t0,$e,$e,"ror#".($Sigma1[1]-$Sigma1[0]))', + '&add ($a,$a,$t2)', # h+=Maj(a,b,c) from the past + '&and ($t1,$t1,$e)', + '&eor ($t2,$t0,$e,"ror#".($Sigma1[2]-$Sigma1[0]))', # Sigma1(e) + '&eor ($t0,$a,$a,"ror#".($Sigma0[1]-$Sigma0[0]))', + '&eor ($t1,$t1,$g)', # Ch(e,f,g) + '&add ($h,$h,$t2,"ror#$Sigma1[0]")', # h+=Sigma1(e) + '&eor ($t2,$a,$b)', # a^b, b^c in next round + '&eor ($t0,$t0,$a,"ror#".($Sigma0[2]-$Sigma0[0]))', # Sigma0(a) + '&add ($h,$h,$t1)', # h+=Ch(e,f,g) + '&ldr ($t1,sprintf "[sp,#%d]",4*(($j+1)&15)) if (($j&15)!=15);'. + '&ldr ($t1,"[$Ktbl]") if ($j==15);'. + '&ldr ($t1,"[sp,#64]") if ($j==31)', + '&and ($t3,$t3,$t2)', # (b^c)&=(a^b) + '&add ($d,$d,$h)', # d+=h + '&add ($h,$h,$t0,"ror#$Sigma0[0]");'. # h+=Sigma0(a) + '&eor ($t3,$t3,$b)', # Maj(a,b,c) + '$j++; unshift(@V,pop(@V)); ($t2,$t3)=($t3,$t2);' + ) +} + +$code.=<<___; +#if __ARM_MAX_ARCH__>=7 +.arch armv7-a +.fpu neon + +.global sha256_block_data_order_neon +.type sha256_block_data_order_neon,%function +.align 5 +.skip 16 +sha256_block_data_order_neon: +.LNEON: + stmdb sp!,{r4-r12,lr} + + sub $H,sp,#16*4+16 + adr $Ktbl,K256 + bic $H,$H,#15 @ align for 128-bit stores + mov $t2,sp + mov sp,$H @ alloca + add $len,$inp,$len,lsl#6 @ len to point at the end of inp + + vld1.8 {@X[0]},[$inp]! + vld1.8 {@X[1]},[$inp]! + vld1.8 {@X[2]},[$inp]! + vld1.8 {@X[3]},[$inp]! + vld1.32 {$T0},[$Ktbl,:128]! + vld1.32 {$T1},[$Ktbl,:128]! + vld1.32 {$T2},[$Ktbl,:128]! + vld1.32 {$T3},[$Ktbl,:128]! + vrev32.8 @X[0],@X[0] @ yes, even on + str $ctx,[sp,#64] + vrev32.8 @X[1],@X[1] @ big-endian + str $inp,[sp,#68] + mov $Xfer,sp + vrev32.8 @X[2],@X[2] + str $len,[sp,#72] + vrev32.8 @X[3],@X[3] + str $t2,[sp,#76] @ save original sp + vadd.i32 $T0,$T0,@X[0] + vadd.i32 $T1,$T1,@X[1] + vst1.32 {$T0},[$Xfer,:128]! + vadd.i32 $T2,$T2,@X[2] + vst1.32 {$T1},[$Xfer,:128]! + vadd.i32 $T3,$T3,@X[3] + vst1.32 {$T2},[$Xfer,:128]! + vst1.32 {$T3},[$Xfer,:128]! + + ldmia $ctx,{$A-$H} + sub $Xfer,$Xfer,#64 + ldr $t1,[sp,#0] + eor $t2,$t2,$t2 + eor $t3,$B,$C + b .L_00_48 + +.align 4 +.L_00_48: +___ + &Xupdate(\&body_00_15); + &Xupdate(\&body_00_15); + &Xupdate(\&body_00_15); + &Xupdate(\&body_00_15); +$code.=<<___; + teq $t1,#0 @ check for K256 terminator + ldr $t1,[sp,#0] + sub $Xfer,$Xfer,#64 + bne .L_00_48 + + ldr $inp,[sp,#68] + ldr $t0,[sp,#72] + sub $Ktbl,$Ktbl,#256 @ rewind $Ktbl + teq $inp,$t0 + it eq + subeq $inp,$inp,#64 @ avoid SEGV + vld1.8 {@X[0]},[$inp]! @ load next input block + vld1.8 {@X[1]},[$inp]! + vld1.8 {@X[2]},[$inp]! + vld1.8 {@X[3]},[$inp]! + it ne + strne $inp,[sp,#68] + mov $Xfer,sp +___ + &Xpreload(\&body_00_15); + &Xpreload(\&body_00_15); + &Xpreload(\&body_00_15); + &Xpreload(\&body_00_15); +$code.=<<___; + ldr $t0,[$t1,#0] + add $A,$A,$t2 @ h+=Maj(a,b,c) from the past + ldr $t2,[$t1,#4] + ldr $t3,[$t1,#8] + ldr $t4,[$t1,#12] + add $A,$A,$t0 @ accumulate + ldr $t0,[$t1,#16] + add $B,$B,$t2 + ldr $t2,[$t1,#20] + add $C,$C,$t3 + ldr $t3,[$t1,#24] + add $D,$D,$t4 + ldr $t4,[$t1,#28] + add $E,$E,$t0 + str $A,[$t1],#4 + add $F,$F,$t2 + str $B,[$t1],#4 + add $G,$G,$t3 + str $C,[$t1],#4 + add $H,$H,$t4 + str $D,[$t1],#4 + stmia $t1,{$E-$H} + + ittte ne + movne $Xfer,sp + ldrne $t1,[sp,#0] + eorne $t2,$t2,$t2 + ldreq sp,[sp,#76] @ restore original sp + itt ne + eorne $t3,$B,$C + bne .L_00_48 + + ldmia sp!,{r4-r12,pc} +.size sha256_block_data_order_neon,.-sha256_block_data_order_neon +#endif +___ +}}} +###################################################################### +# ARMv8 stuff +# +{{{ +my ($ABCD,$EFGH,$abcd)=map("q$_",(0..2)); +my @MSG=map("q$_",(8..11)); +my ($W0,$W1,$ABCD_SAVE,$EFGH_SAVE)=map("q$_",(12..15)); +my $Ktbl="r3"; + +$code.=<<___; +#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) + +# if defined(__thumb2__) +# define INST(a,b,c,d) .byte c,d|0xc,a,b +# else +# define INST(a,b,c,d) .byte a,b,c,d +# endif + +.type sha256_block_data_order_armv8,%function +.align 5 +sha256_block_data_order_armv8: +.LARMv8: + vld1.32 {$ABCD,$EFGH},[$ctx] + sub $Ktbl,$Ktbl,#256+32 + add $len,$inp,$len,lsl#6 @ len to point at the end of inp + b .Loop_v8 + +.align 4 +.Loop_v8: + vld1.8 {@MSG[0]-@MSG[1]},[$inp]! + vld1.8 {@MSG[2]-@MSG[3]},[$inp]! + vld1.32 {$W0},[$Ktbl]! + vrev32.8 @MSG[0],@MSG[0] + vrev32.8 @MSG[1],@MSG[1] + vrev32.8 @MSG[2],@MSG[2] + vrev32.8 @MSG[3],@MSG[3] + vmov $ABCD_SAVE,$ABCD @ offload + vmov $EFGH_SAVE,$EFGH + teq $inp,$len +___ +for($i=0;$i<12;$i++) { +$code.=<<___; + vld1.32 {$W1},[$Ktbl]! + vadd.i32 $W0,$W0,@MSG[0] + sha256su0 @MSG[0],@MSG[1] + vmov $abcd,$ABCD + sha256h $ABCD,$EFGH,$W0 + sha256h2 $EFGH,$abcd,$W0 + sha256su1 @MSG[0],@MSG[2],@MSG[3] +___ + ($W0,$W1)=($W1,$W0); push(@MSG,shift(@MSG)); +} +$code.=<<___; + vld1.32 {$W1},[$Ktbl]! + vadd.i32 $W0,$W0,@MSG[0] + vmov $abcd,$ABCD + sha256h $ABCD,$EFGH,$W0 + sha256h2 $EFGH,$abcd,$W0 + + vld1.32 {$W0},[$Ktbl]! + vadd.i32 $W1,$W1,@MSG[1] + vmov $abcd,$ABCD + sha256h $ABCD,$EFGH,$W1 + sha256h2 $EFGH,$abcd,$W1 + + vld1.32 {$W1},[$Ktbl] + vadd.i32 $W0,$W0,@MSG[2] + sub $Ktbl,$Ktbl,#256-16 @ rewind + vmov $abcd,$ABCD + sha256h $ABCD,$EFGH,$W0 + sha256h2 $EFGH,$abcd,$W0 + + vadd.i32 $W1,$W1,@MSG[3] + vmov $abcd,$ABCD + sha256h $ABCD,$EFGH,$W1 + sha256h2 $EFGH,$abcd,$W1 + + vadd.i32 $ABCD,$ABCD,$ABCD_SAVE + vadd.i32 $EFGH,$EFGH,$EFGH_SAVE + it ne + bne .Loop_v8 + + vst1.32 {$ABCD,$EFGH},[$ctx] + + ret @ bx lr +.size sha256_block_data_order_armv8,.-sha256_block_data_order_armv8 +#endif +___ +}}} +$code.=<<___; +.asciz "SHA256 block transform for ARMv4/NEON/ARMv8, CRYPTOGAMS by " +.align 2 +#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) +.comm OPENSSL_armcap_P,4,4 +#endif +___ + +open SELF,$0; +while() { + next if (/^#!/); + last if (!s/^#/@/ and !/^$/); + print; +} +close SELF; + +{ my %opcode = ( + "sha256h" => 0xf3000c40, "sha256h2" => 0xf3100c40, + "sha256su0" => 0xf3ba03c0, "sha256su1" => 0xf3200c40 ); + + sub unsha256 { + my ($mnemonic,$arg)=@_; + + if ($arg =~ m/q([0-9]+)(?:,\s*q([0-9]+))?,\s*q([0-9]+)/o) { + my $word = $opcode{$mnemonic}|(($1&7)<<13)|(($1&8)<<19) + |(($2&7)<<17)|(($2&8)<<4) + |(($3&7)<<1) |(($3&8)<<2); + # since ARMv7 instructions are always encoded little-endian. + # correct solution is to use .inst directive, but older + # assemblers don't implement it:-( + sprintf "INST(0x%02x,0x%02x,0x%02x,0x%02x)\t@ %s %s", + $word&0xff,($word>>8)&0xff, + ($word>>16)&0xff,($word>>24)&0xff, + $mnemonic,$arg; + } + } +} + +foreach (split($/,$code)) { + + s/\`([^\`]*)\`/eval $1/geo; + + s/\b(sha256\w+)\s+(q.*)/unsha256($1,$2)/geo; + + s/\bret\b/bx lr/go or + s/\bbx\s+lr\b/.word\t0xe12fff1e/go; # make it possible to compile with -march=armv4 + + print $_,"\n"; +} + +close STDOUT; # enforce flush diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha256-c64xplus.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha256-c64xplus.pl new file mode 100644 index 000000000..3ab7d9b68 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha256-c64xplus.pl @@ -0,0 +1,320 @@ +#! /usr/bin/env perl +# Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# SHA256 for C64x+. +# +# January 2012 +# +# Performance is just below 10 cycles per processed byte, which is +# almost 40% faster than compiler-generated code. Unroll is unlikely +# to give more than ~8% improvement... +# +# !!! Note that this module uses AMR, which means that all interrupt +# service routines are expected to preserve it and for own well-being +# zero it upon entry. + +while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} +open STDOUT,">$output"; + +($CTXA,$INP,$NUM) = ("A4","B4","A6"); # arguments + $K256="A3"; + +($A,$Actx,$B,$Bctx,$C,$Cctx,$D,$Dctx,$T2,$S0,$s1,$t0a,$t1a,$t2a,$X9,$X14) + =map("A$_",(16..31)); +($E,$Ectx,$F,$Fctx,$G,$Gctx,$H,$Hctx,$T1,$S1,$s0,$t0e,$t1e,$t2e,$X1,$X15) + =map("B$_",(16..31)); + +($Xia,$Xib)=("A5","B5"); # circular/ring buffer + $CTXB=$t2e; + +($Xn,$X0,$K)=("B7","B8","B9"); +($Maj,$Ch)=($T2,"B6"); + +$code.=<<___; + .text + + .if .ASSEMBLER_VERSION<7000000 + .asg 0,__TI_EABI__ + .endif + .if __TI_EABI__ + .nocmp + .asg sha256_block_data_order,_sha256_block_data_order + .endif + + .asg B3,RA + .asg A15,FP + .asg B15,SP + + .if .BIG_ENDIAN + .asg SWAP2,MV + .asg SWAP4,MV + .endif + + .global _sha256_block_data_order +_sha256_block_data_order: +__sha256_block: + .asmfunc stack_usage(64) + MV $NUM,A0 ; reassign $NUM +|| MVK -64,B0 + [!A0] BNOP RA ; if ($NUM==0) return; +|| [A0] STW FP,*SP--[16] ; save frame pointer and alloca(64) +|| [A0] MV SP,FP + [A0] ADDKPC __sha256_block,B2 +|| [A0] AND B0,SP,SP ; align stack at 64 bytes + .if __TI_EABI__ + [A0] MVK 0x00404,B1 +|| [A0] MVKL \$PCR_OFFSET(K256,__sha256_block),$K256 + [A0] MVKH 0x50000,B1 +|| [A0] MVKH \$PCR_OFFSET(K256,__sha256_block),$K256 + .else + [A0] MVK 0x00404,B1 +|| [A0] MVKL (K256-__sha256_block),$K256 + [A0] MVKH 0x50000,B1 +|| [A0] MVKH (K256-__sha256_block),$K256 + .endif + [A0] MVC B1,AMR ; setup circular addressing +|| [A0] MV SP,$Xia + [A0] MV SP,$Xib +|| [A0] ADD B2,$K256,$K256 +|| [A0] MV $CTXA,$CTXB +|| [A0] SUBAW SP,2,SP ; reserve two words above buffer + LDW *${CTXA}[0],$A ; load ctx +|| LDW *${CTXB}[4],$E + LDW *${CTXA}[1],$B +|| LDW *${CTXB}[5],$F + LDW *${CTXA}[2],$C +|| LDW *${CTXB}[6],$G + LDW *${CTXA}[3],$D +|| LDW *${CTXB}[7],$H + + LDNW *$INP++,$Xn ; pre-fetch input + LDW *$K256++,$K ; pre-fetch K256[0] + MVK 14,B0 ; loop counters + MVK 47,B1 +|| ADDAW $Xia,9,$Xia +outerloop?: + SUB A0,1,A0 +|| MV $A,$Actx +|| MV $E,$Ectx +|| MVD $B,$Bctx +|| MVD $F,$Fctx + MV $C,$Cctx +|| MV $G,$Gctx +|| MVD $D,$Dctx +|| MVD $H,$Hctx +|| SWAP4 $Xn,$X0 + + SPLOOPD 8 ; BODY_00_14 +|| MVC B0,ILC +|| SWAP2 $X0,$X0 + + LDNW *$INP++,$Xn +|| ROTL $A,30,$S0 +|| OR $A,$B,$Maj +|| AND $A,$B,$t2a +|| ROTL $E,26,$S1 +|| AND $F,$E,$Ch +|| ANDN $G,$E,$t2e + ROTL $A,19,$t0a +|| AND $C,$Maj,$Maj +|| ROTL $E,21,$t0e +|| XOR $t2e,$Ch,$Ch ; Ch(e,f,g) = (e&f)^(~e&g) + ROTL $A,10,$t1a +|| OR $t2a,$Maj,$Maj ; Maj(a,b,c) = ((a|b)&c)|(a&b) +|| ROTL $E,7,$t1e +|| ADD $K,$H,$T1 ; T1 = h + K256[i] + ADD $X0,$T1,$T1 ; T1 += X[i]; +|| STW $X0,*$Xib++ +|| XOR $t0a,$S0,$S0 +|| XOR $t0e,$S1,$S1 + XOR $t1a,$S0,$S0 ; Sigma0(a) +|| XOR $t1e,$S1,$S1 ; Sigma1(e) +|| LDW *$K256++,$K ; pre-fetch K256[i+1] +|| ADD $Ch,$T1,$T1 ; T1 += Ch(e,f,g) + ADD $S1,$T1,$T1 ; T1 += Sigma1(e) +|| ADD $S0,$Maj,$T2 ; T2 = Sigma0(a) + Maj(a,b,c) +|| ROTL $G,0,$H ; h = g +|| MV $F,$G ; g = f +|| MV $X0,$X14 +|| SWAP4 $Xn,$X0 + SWAP2 $X0,$X0 +|| MV $E,$F ; f = e +|| ADD $D,$T1,$E ; e = d + T1 +|| MV $C,$D ; d = c + MV $B,$C ; c = b +|| MV $A,$B ; b = a +|| ADD $T1,$T2,$A ; a = T1 + T2 + SPKERNEL + + ROTL $A,30,$S0 ; BODY_15 +|| OR $A,$B,$Maj +|| AND $A,$B,$t2a +|| ROTL $E,26,$S1 +|| AND $F,$E,$Ch +|| ANDN $G,$E,$t2e +|| LDW *${Xib}[1],$Xn ; modulo-scheduled + ROTL $A,19,$t0a +|| AND $C,$Maj,$Maj +|| ROTL $E,21,$t0e +|| XOR $t2e,$Ch,$Ch ; Ch(e,f,g) = (e&f)^(~e&g) +|| LDW *${Xib}[2],$X1 ; modulo-scheduled + ROTL $A,10,$t1a +|| OR $t2a,$Maj,$Maj ; Maj(a,b,c) = ((a|b)&c)|(a&b) +|| ROTL $E,7,$t1e +|| ADD $K,$H,$T1 ; T1 = h + K256[i] + ADD $X0,$T1,$T1 ; T1 += X[i]; +|| STW $X0,*$Xib++ +|| XOR $t0a,$S0,$S0 +|| XOR $t0e,$S1,$S1 + XOR $t1a,$S0,$S0 ; Sigma0(a) +|| XOR $t1e,$S1,$S1 ; Sigma1(e) +|| LDW *$K256++,$K ; pre-fetch K256[i+1] +|| ADD $Ch,$T1,$T1 ; T1 += Ch(e,f,g) + ADD $S1,$T1,$T1 ; T1 += Sigma1(e) +|| ADD $S0,$Maj,$T2 ; T2 = Sigma0(a) + Maj(a,b,c) +|| ROTL $G,0,$H ; h = g +|| MV $F,$G ; g = f +|| MV $X0,$X15 + MV $E,$F ; f = e +|| ADD $D,$T1,$E ; e = d + T1 +|| MV $C,$D ; d = c +|| MV $Xn,$X0 ; modulo-scheduled +|| LDW *$Xia,$X9 ; modulo-scheduled +|| ROTL $X1,25,$t0e ; modulo-scheduled +|| ROTL $X14,15,$t0a ; modulo-scheduled + SHRU $X1,3,$s0 ; modulo-scheduled +|| SHRU $X14,10,$s1 ; modulo-scheduled +|| ROTL $B,0,$C ; c = b +|| MV $A,$B ; b = a +|| ADD $T1,$T2,$A ; a = T1 + T2 + + SPLOOPD 10 ; BODY_16_63 +|| MVC B1,ILC +|| ROTL $X1,14,$t1e ; modulo-scheduled +|| ROTL $X14,13,$t1a ; modulo-scheduled + + XOR $t0e,$s0,$s0 +|| XOR $t0a,$s1,$s1 +|| MV $X15,$X14 +|| MV $X1,$Xn + XOR $t1e,$s0,$s0 ; sigma0(X[i+1]) +|| XOR $t1a,$s1,$s1 ; sigma1(X[i+14]) +|| LDW *${Xib}[2],$X1 ; module-scheduled + ROTL $A,30,$S0 +|| OR $A,$B,$Maj +|| AND $A,$B,$t2a +|| ROTL $E,26,$S1 +|| AND $F,$E,$Ch +|| ANDN $G,$E,$t2e +|| ADD $X9,$X0,$X0 ; X[i] += X[i+9] + ROTL $A,19,$t0a +|| AND $C,$Maj,$Maj +|| ROTL $E,21,$t0e +|| XOR $t2e,$Ch,$Ch ; Ch(e,f,g) = (e&f)^(~e&g) +|| ADD $s0,$X0,$X0 ; X[i] += sigma1(X[i+1]) + ROTL $A,10,$t1a +|| OR $t2a,$Maj,$Maj ; Maj(a,b,c) = ((a|b)&c)|(a&b) +|| ROTL $E,7,$t1e +|| ADD $H,$K,$T1 ; T1 = h + K256[i] +|| ADD $s1,$X0,$X0 ; X[i] += sigma1(X[i+14]) + XOR $t0a,$S0,$S0 +|| XOR $t0e,$S1,$S1 +|| ADD $X0,$T1,$T1 ; T1 += X[i] +|| STW $X0,*$Xib++ + XOR $t1a,$S0,$S0 ; Sigma0(a) +|| XOR $t1e,$S1,$S1 ; Sigma1(e) +|| ADD $Ch,$T1,$T1 ; T1 += Ch(e,f,g) +|| MV $X0,$X15 +|| ROTL $G,0,$H ; h = g +|| LDW *$K256++,$K ; pre-fetch K256[i+1] + ADD $S1,$T1,$T1 ; T1 += Sigma1(e) +|| ADD $S0,$Maj,$T2 ; T2 = Sigma0(a) + Maj(a,b,c) +|| MV $F,$G ; g = f +|| MV $Xn,$X0 ; modulo-scheduled +|| LDW *++$Xia,$X9 ; modulo-scheduled +|| ROTL $X1,25,$t0e ; module-scheduled +|| ROTL $X14,15,$t0a ; modulo-scheduled + ROTL $X1,14,$t1e ; modulo-scheduled +|| ROTL $X14,13,$t1a ; modulo-scheduled +|| MV $E,$F ; f = e +|| ADD $D,$T1,$E ; e = d + T1 +|| MV $C,$D ; d = c +|| MV $B,$C ; c = b + MV $A,$B ; b = a +|| ADD $T1,$T2,$A ; a = T1 + T2 +|| SHRU $X1,3,$s0 ; modulo-scheduled +|| SHRU $X14,10,$s1 ; modulo-scheduled + SPKERNEL + + [A0] B outerloop? +|| [A0] LDNW *$INP++,$Xn ; pre-fetch input +|| [A0] ADDK -260,$K256 ; rewind K256 +|| ADD $Actx,$A,$A ; accumulate ctx +|| ADD $Ectx,$E,$E +|| ADD $Bctx,$B,$B + ADD $Fctx,$F,$F +|| ADD $Cctx,$C,$C +|| ADD $Gctx,$G,$G +|| ADD $Dctx,$D,$D +|| ADD $Hctx,$H,$H +|| [A0] LDW *$K256++,$K ; pre-fetch K256[0] + + [!A0] BNOP RA +||[!A0] MV $CTXA,$CTXB + [!A0] MV FP,SP ; restore stack pointer +||[!A0] LDW *FP[0],FP ; restore frame pointer + [!A0] STW $A,*${CTXA}[0] ; save ctx +||[!A0] STW $E,*${CTXB}[4] +||[!A0] MVK 0,B0 + [!A0] STW $B,*${CTXA}[1] +||[!A0] STW $F,*${CTXB}[5] +||[!A0] MVC B0,AMR ; clear AMR + STW $C,*${CTXA}[2] +|| STW $G,*${CTXB}[6] + STW $D,*${CTXA}[3] +|| STW $H,*${CTXB}[7] + .endasmfunc + + .if __TI_EABI__ + .sect ".text:sha_asm.const" + .else + .sect ".const:sha_asm" + .endif + .align 128 +K256: + .uword 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5 + .uword 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5 + .uword 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3 + .uword 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174 + .uword 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc + .uword 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da + .uword 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7 + .uword 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967 + .uword 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13 + .uword 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85 + .uword 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3 + .uword 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070 + .uword 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5 + .uword 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3 + .uword 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208 + .uword 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 + .cstring "SHA256 block transform for C64x+, CRYPTOGAMS by " + .align 4 + +___ + +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha256-mb-x86_64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha256-mb-x86_64.pl new file mode 100644 index 000000000..73978dbd8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha256-mb-x86_64.pl @@ -0,0 +1,1614 @@ +#! /usr/bin/env perl +# Copyright 2013-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# Multi-buffer SHA256 procedure processes n buffers in parallel by +# placing buffer data to designated lane of SIMD register. n is +# naturally limited to 4 on pre-AVX2 processors and to 8 on +# AVX2-capable processors such as Haswell. +# +# this +aesni(i) sha256 aesni-sha256 gain(iv) +# ------------------------------------------------------------------- +# Westmere(ii) 23.3/n +1.28=7.11(n=4) 12.3 +3.75=16.1 +126% +# Atom(ii) 38.7/n +3.93=13.6(n=4) 20.8 +5.69=26.5 +95% +# Sandy Bridge (20.5 +5.15=25.7)/n 11.6 13.0 +103% +# Ivy Bridge (20.4 +5.14=25.5)/n 10.3 11.6 +82% +# Haswell(iii) (21.0 +5.00=26.0)/n 7.80 8.79 +170% +# Skylake (18.9 +5.00=23.9)/n 7.70 8.17 +170% +# Bulldozer (21.6 +5.76=27.4)/n 13.6 13.7 +100% +# +# (i) multi-block CBC encrypt with 128-bit key; +# (ii) (HASH+AES)/n does not apply to Westmere for n>3 and Atom, +# because of lower AES-NI instruction throughput, nor is there +# AES-NI-SHA256 stitch for these processors; +# (iii) "this" is for n=8, when we gather twice as much data, result +# for n=4 is 20.3+4.44=24.7; +# (iv) presented improvement coefficients are asymptotic limits and +# in real-life application are somewhat lower, e.g. for 2KB +# fragments they range from 75% to 130% (on Haswell); + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +$avx=0; + +if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler version ([2-9]\.[0-9]+)/) { + $avx = ($1>=2.19) + ($1>=2.22); +} + +if (!$avx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) && + `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) { + $avx = ($1>=2.09) + ($1>=2.10); +} + +if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && + `ml64 2>&1` =~ /Version ([0-9]+)\./) { + $avx = ($1>=10) + ($1>=11); +} + +if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9]\.[0-9]+)/) { + $avx = ($2>=3.0) + ($2>3.0); +} + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +*STDOUT=*OUT; + +# void sha256_multi_block ( +# struct { unsigned int A[8]; +# unsigned int B[8]; +# unsigned int C[8]; +# unsigned int D[8]; +# unsigned int E[8]; +# unsigned int F[8]; +# unsigned int G[8]; +# unsigned int H[8]; } *ctx, +# struct { void *ptr; int blocks; } inp[8], +# int num); /* 1 or 2 */ +# +$ctx="%rdi"; # 1st arg +$inp="%rsi"; # 2nd arg +$num="%edx"; # 3rd arg +@ptr=map("%r$_",(8..11)); +$Tbl="%rbp"; + +@V=($A,$B,$C,$D,$E,$F,$G,$H)=map("%xmm$_",(8..15)); +($t1,$t2,$t3,$axb,$bxc,$Xi,$Xn,$sigma)=map("%xmm$_",(0..7)); + +$REG_SZ=16; + +sub Xi_off { +my $off = shift; + + $off %= 16; $off *= $REG_SZ; + $off<256 ? "$off-128(%rax)" : "$off-256-128(%rbx)"; +} + +sub ROUND_00_15 { +my ($i,$a,$b,$c,$d,$e,$f,$g,$h)=@_; + +$code.=<<___ if ($i<15); + movd `4*$i`(@ptr[0]),$Xi + movd `4*$i`(@ptr[1]),$t1 + movd `4*$i`(@ptr[2]),$t2 + movd `4*$i`(@ptr[3]),$t3 + punpckldq $t2,$Xi + punpckldq $t3,$t1 + punpckldq $t1,$Xi +___ +$code.=<<___ if ($i==15); + movd `4*$i`(@ptr[0]),$Xi + lea `16*4`(@ptr[0]),@ptr[0] + movd `4*$i`(@ptr[1]),$t1 + lea `16*4`(@ptr[1]),@ptr[1] + movd `4*$i`(@ptr[2]),$t2 + lea `16*4`(@ptr[2]),@ptr[2] + movd `4*$i`(@ptr[3]),$t3 + lea `16*4`(@ptr[3]),@ptr[3] + punpckldq $t2,$Xi + punpckldq $t3,$t1 + punpckldq $t1,$Xi +___ +$code.=<<___; + movdqa $e,$sigma + `"pshufb $Xn,$Xi" if ($i<=15 && ($i&1)==0)` + movdqa $e,$t3 + `"pshufb $Xn,$Xi" if ($i<=15 && ($i&1)==1)` + psrld \$6,$sigma + movdqa $e,$t2 + pslld \$7,$t3 + movdqa $Xi,`&Xi_off($i)` + paddd $h,$Xi # Xi+=h + + psrld \$11,$t2 + pxor $t3,$sigma + pslld \$21-7,$t3 + paddd `32*($i%8)-128`($Tbl),$Xi # Xi+=K[round] + pxor $t2,$sigma + + psrld \$25-11,$t2 + movdqa $e,$t1 + `"prefetcht0 63(@ptr[0])" if ($i==15)` + pxor $t3,$sigma + movdqa $e,$axb # borrow $axb + pslld \$26-21,$t3 + pandn $g,$t1 + pand $f,$axb + pxor $t2,$sigma + + `"prefetcht0 63(@ptr[1])" if ($i==15)` + movdqa $a,$t2 + pxor $t3,$sigma # Sigma1(e) + movdqa $a,$t3 + psrld \$2,$t2 + paddd $sigma,$Xi # Xi+=Sigma1(e) + pxor $axb,$t1 # Ch(e,f,g) + movdqa $b,$axb + movdqa $a,$sigma + pslld \$10,$t3 + pxor $a,$axb # a^b, b^c in next round + + `"prefetcht0 63(@ptr[2])" if ($i==15)` + psrld \$13,$sigma + pxor $t3,$t2 + paddd $t1,$Xi # Xi+=Ch(e,f,g) + pslld \$19-10,$t3 + pand $axb,$bxc + pxor $sigma,$t2 + + `"prefetcht0 63(@ptr[3])" if ($i==15)` + psrld \$22-13,$sigma + pxor $t3,$t2 + movdqa $b,$h + pslld \$30-19,$t3 + pxor $t2,$sigma + pxor $bxc,$h # h=Maj(a,b,c)=Ch(a^b,c,b) + paddd $Xi,$d # d+=Xi + pxor $t3,$sigma # Sigma0(a) + + paddd $Xi,$h # h+=Xi + paddd $sigma,$h # h+=Sigma0(a) +___ +$code.=<<___ if (($i%8)==7); + lea `32*8`($Tbl),$Tbl +___ + ($axb,$bxc)=($bxc,$axb); +} + +sub ROUND_16_XX { +my $i=shift; + +$code.=<<___; + movdqa `&Xi_off($i+1)`,$Xn + paddd `&Xi_off($i+9)`,$Xi # Xi+=X[i+9] + + movdqa $Xn,$sigma + movdqa $Xn,$t2 + psrld \$3,$sigma + movdqa $Xn,$t3 + + psrld \$7,$t2 + movdqa `&Xi_off($i+14)`,$t1 + pslld \$14,$t3 + pxor $t2,$sigma + psrld \$18-7,$t2 + movdqa $t1,$axb # borrow $axb + pxor $t3,$sigma + pslld \$25-14,$t3 + pxor $t2,$sigma + psrld \$10,$t1 + movdqa $axb,$t2 + + psrld \$17,$axb + pxor $t3,$sigma # sigma0(X[i+1]) + pslld \$13,$t2 + paddd $sigma,$Xi # Xi+=sigma0(e) + pxor $axb,$t1 + psrld \$19-17,$axb + pxor $t2,$t1 + pslld \$15-13,$t2 + pxor $axb,$t1 + pxor $t2,$t1 # sigma0(X[i+14]) + paddd $t1,$Xi # Xi+=sigma1(X[i+14]) +___ + &ROUND_00_15($i,@_); + ($Xi,$Xn)=($Xn,$Xi); +} + +$code.=<<___; +.text + +.extern OPENSSL_ia32cap_P + +.globl sha256_multi_block +.type sha256_multi_block,\@function,3 +.align 32 +sha256_multi_block: +.cfi_startproc + mov OPENSSL_ia32cap_P+4(%rip),%rcx + bt \$61,%rcx # check SHA bit + jc _shaext_shortcut +___ +$code.=<<___ if ($avx); + test \$`1<<28`,%ecx + jnz _avx_shortcut +___ +$code.=<<___; + mov %rsp,%rax +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp +___ +$code.=<<___ if ($win64); + lea -0xa8(%rsp),%rsp + movaps %xmm6,(%rsp) + movaps %xmm7,0x10(%rsp) + movaps %xmm8,0x20(%rsp) + movaps %xmm9,0x30(%rsp) + movaps %xmm10,-0x78(%rax) + movaps %xmm11,-0x68(%rax) + movaps %xmm12,-0x58(%rax) + movaps %xmm13,-0x48(%rax) + movaps %xmm14,-0x38(%rax) + movaps %xmm15,-0x28(%rax) +___ +$code.=<<___; + sub \$`$REG_SZ*18`, %rsp + and \$-256,%rsp + mov %rax,`$REG_SZ*17`(%rsp) # original %rsp +.cfi_cfa_expression %rsp+`$REG_SZ*17`,deref,+8 +.Lbody: + lea K256+128(%rip),$Tbl + lea `$REG_SZ*16`(%rsp),%rbx + lea 0x80($ctx),$ctx # size optimization + +.Loop_grande: + mov $num,`$REG_SZ*17+8`(%rsp) # original $num + xor $num,$num +___ +for($i=0;$i<4;$i++) { + $code.=<<___; + mov `16*$i+0`($inp),@ptr[$i] # input pointer + mov `16*$i+8`($inp),%ecx # number of blocks + cmp $num,%ecx + cmovg %ecx,$num # find maximum + test %ecx,%ecx + mov %ecx,`4*$i`(%rbx) # initialize counters + cmovle $Tbl,@ptr[$i] # cancel input +___ +} +$code.=<<___; + test $num,$num + jz .Ldone + + movdqu 0x00-0x80($ctx),$A # load context + lea 128(%rsp),%rax + movdqu 0x20-0x80($ctx),$B + movdqu 0x40-0x80($ctx),$C + movdqu 0x60-0x80($ctx),$D + movdqu 0x80-0x80($ctx),$E + movdqu 0xa0-0x80($ctx),$F + movdqu 0xc0-0x80($ctx),$G + movdqu 0xe0-0x80($ctx),$H + movdqu .Lpbswap(%rip),$Xn + jmp .Loop + +.align 32 +.Loop: + movdqa $C,$bxc + pxor $B,$bxc # magic seed +___ +for($i=0;$i<16;$i++) { &ROUND_00_15($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + movdqu `&Xi_off($i)`,$Xi + mov \$3,%ecx + jmp .Loop_16_xx +.align 32 +.Loop_16_xx: +___ +for(;$i<32;$i++) { &ROUND_16_XX($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + dec %ecx + jnz .Loop_16_xx + + mov \$1,%ecx + lea K256+128(%rip),$Tbl + + movdqa (%rbx),$sigma # pull counters + cmp 4*0(%rbx),%ecx # examine counters + pxor $t1,$t1 + cmovge $Tbl,@ptr[0] # cancel input + cmp 4*1(%rbx),%ecx + movdqa $sigma,$Xn + cmovge $Tbl,@ptr[1] + cmp 4*2(%rbx),%ecx + pcmpgtd $t1,$Xn # mask value + cmovge $Tbl,@ptr[2] + cmp 4*3(%rbx),%ecx + paddd $Xn,$sigma # counters-- + cmovge $Tbl,@ptr[3] + + movdqu 0x00-0x80($ctx),$t1 + pand $Xn,$A + movdqu 0x20-0x80($ctx),$t2 + pand $Xn,$B + movdqu 0x40-0x80($ctx),$t3 + pand $Xn,$C + movdqu 0x60-0x80($ctx),$Xi + pand $Xn,$D + paddd $t1,$A + movdqu 0x80-0x80($ctx),$t1 + pand $Xn,$E + paddd $t2,$B + movdqu 0xa0-0x80($ctx),$t2 + pand $Xn,$F + paddd $t3,$C + movdqu 0xc0-0x80($ctx),$t3 + pand $Xn,$G + paddd $Xi,$D + movdqu 0xe0-0x80($ctx),$Xi + pand $Xn,$H + paddd $t1,$E + paddd $t2,$F + movdqu $A,0x00-0x80($ctx) + paddd $t3,$G + movdqu $B,0x20-0x80($ctx) + paddd $Xi,$H + movdqu $C,0x40-0x80($ctx) + movdqu $D,0x60-0x80($ctx) + movdqu $E,0x80-0x80($ctx) + movdqu $F,0xa0-0x80($ctx) + movdqu $G,0xc0-0x80($ctx) + movdqu $H,0xe0-0x80($ctx) + + movdqa $sigma,(%rbx) # save counters + movdqa .Lpbswap(%rip),$Xn + dec $num + jnz .Loop + + mov `$REG_SZ*17+8`(%rsp),$num + lea $REG_SZ($ctx),$ctx + lea `16*$REG_SZ/4`($inp),$inp + dec $num + jnz .Loop_grande + +.Ldone: + mov `$REG_SZ*17`(%rsp),%rax # original %rsp +.cfi_def_cfa %rax,8 +___ +$code.=<<___ if ($win64); + movaps -0xb8(%rax),%xmm6 + movaps -0xa8(%rax),%xmm7 + movaps -0x98(%rax),%xmm8 + movaps -0x88(%rax),%xmm9 + movaps -0x78(%rax),%xmm10 + movaps -0x68(%rax),%xmm11 + movaps -0x58(%rax),%xmm12 + movaps -0x48(%rax),%xmm13 + movaps -0x38(%rax),%xmm14 + movaps -0x28(%rax),%xmm15 +___ +$code.=<<___; + mov -16(%rax),%rbp +.cfi_restore %rbp + mov -8(%rax),%rbx +.cfi_restore %rbx + lea (%rax),%rsp +.cfi_def_cfa_register %rsp +.Lepilogue: + ret +.cfi_endproc +.size sha256_multi_block,.-sha256_multi_block +___ + {{{ +my ($Wi,$TMP0,$TMP1,$TMPx,$ABEF0,$CDGH0,$ABEF1,$CDGH1)=map("%xmm$_",(0..3,12..15)); +my @MSG0=map("%xmm$_",(4..7)); +my @MSG1=map("%xmm$_",(8..11)); + +$code.=<<___; +.type sha256_multi_block_shaext,\@function,3 +.align 32 +sha256_multi_block_shaext: +.cfi_startproc +_shaext_shortcut: + mov %rsp,%rax +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp +___ +$code.=<<___ if ($win64); + lea -0xa8(%rsp),%rsp + movaps %xmm6,(%rsp) + movaps %xmm7,0x10(%rsp) + movaps %xmm8,0x20(%rsp) + movaps %xmm9,0x30(%rsp) + movaps %xmm10,-0x78(%rax) + movaps %xmm11,-0x68(%rax) + movaps %xmm12,-0x58(%rax) + movaps %xmm13,-0x48(%rax) + movaps %xmm14,-0x38(%rax) + movaps %xmm15,-0x28(%rax) +___ +$code.=<<___; + sub \$`$REG_SZ*18`,%rsp + shl \$1,$num # we process pair at a time + and \$-256,%rsp + lea 0x80($ctx),$ctx # size optimization + mov %rax,`$REG_SZ*17`(%rsp) # original %rsp +.Lbody_shaext: + lea `$REG_SZ*16`(%rsp),%rbx + lea K256_shaext+0x80(%rip),$Tbl + +.Loop_grande_shaext: + mov $num,`$REG_SZ*17+8`(%rsp) # original $num + xor $num,$num +___ +for($i=0;$i<2;$i++) { + $code.=<<___; + mov `16*$i+0`($inp),@ptr[$i] # input pointer + mov `16*$i+8`($inp),%ecx # number of blocks + cmp $num,%ecx + cmovg %ecx,$num # find maximum + test %ecx,%ecx + mov %ecx,`4*$i`(%rbx) # initialize counters + cmovle %rsp,@ptr[$i] # cancel input +___ +} +$code.=<<___; + test $num,$num + jz .Ldone_shaext + + movq 0x00-0x80($ctx),$ABEF0 # A1.A0 + movq 0x20-0x80($ctx),@MSG0[0] # B1.B0 + movq 0x40-0x80($ctx),$CDGH0 # C1.C0 + movq 0x60-0x80($ctx),@MSG0[1] # D1.D0 + movq 0x80-0x80($ctx),@MSG1[0] # E1.E0 + movq 0xa0-0x80($ctx),@MSG1[1] # F1.F0 + movq 0xc0-0x80($ctx),@MSG1[2] # G1.G0 + movq 0xe0-0x80($ctx),@MSG1[3] # H1.H0 + + punpckldq @MSG0[0],$ABEF0 # B1.A1.B0.A0 + punpckldq @MSG0[1],$CDGH0 # D1.C1.D0.C0 + punpckldq @MSG1[1],@MSG1[0] # F1.E1.F0.E0 + punpckldq @MSG1[3],@MSG1[2] # H1.G1.H0.G0 + movdqa K256_shaext-0x10(%rip),$TMPx # byte swap + + movdqa $ABEF0,$ABEF1 + movdqa $CDGH0,$CDGH1 + punpcklqdq @MSG1[0],$ABEF0 # F0.E0.B0.A0 + punpcklqdq @MSG1[2],$CDGH0 # H0.G0.D0.C0 + punpckhqdq @MSG1[0],$ABEF1 # F1.E1.B1.A1 + punpckhqdq @MSG1[2],$CDGH1 # H1.G1.D1.C1 + + pshufd \$0b00011011,$ABEF0,$ABEF0 + pshufd \$0b00011011,$CDGH0,$CDGH0 + pshufd \$0b00011011,$ABEF1,$ABEF1 + pshufd \$0b00011011,$CDGH1,$CDGH1 + jmp .Loop_shaext + +.align 32 +.Loop_shaext: + movdqu 0x00(@ptr[0]),@MSG0[0] + movdqu 0x00(@ptr[1]),@MSG1[0] + movdqu 0x10(@ptr[0]),@MSG0[1] + movdqu 0x10(@ptr[1]),@MSG1[1] + movdqu 0x20(@ptr[0]),@MSG0[2] + pshufb $TMPx,@MSG0[0] + movdqu 0x20(@ptr[1]),@MSG1[2] + pshufb $TMPx,@MSG1[0] + movdqu 0x30(@ptr[0]),@MSG0[3] + lea 0x40(@ptr[0]),@ptr[0] + movdqu 0x30(@ptr[1]),@MSG1[3] + lea 0x40(@ptr[1]),@ptr[1] + + movdqa 0*16-0x80($Tbl),$Wi + pshufb $TMPx,@MSG0[1] + paddd @MSG0[0],$Wi + pxor $ABEF0,@MSG0[0] # black magic + movdqa $Wi,$TMP0 + movdqa 0*16-0x80($Tbl),$TMP1 + pshufb $TMPx,@MSG1[1] + paddd @MSG1[0],$TMP1 + movdqa $CDGH0,0x50(%rsp) # offload + sha256rnds2 $ABEF0,$CDGH0 # 0-3 + pxor $ABEF1,@MSG1[0] # black magic + movdqa $TMP1,$Wi + movdqa $CDGH1,0x70(%rsp) + sha256rnds2 $ABEF1,$CDGH1 # 0-3 + pshufd \$0x0e,$TMP0,$Wi + pxor $ABEF0,@MSG0[0] # black magic + movdqa $ABEF0,0x40(%rsp) # offload + sha256rnds2 $CDGH0,$ABEF0 + pshufd \$0x0e,$TMP1,$Wi + pxor $ABEF1,@MSG1[0] # black magic + movdqa $ABEF1,0x60(%rsp) + movdqa 1*16-0x80($Tbl),$TMP0 + paddd @MSG0[1],$TMP0 + pshufb $TMPx,@MSG0[2] + sha256rnds2 $CDGH1,$ABEF1 + + movdqa $TMP0,$Wi + movdqa 1*16-0x80($Tbl),$TMP1 + paddd @MSG1[1],$TMP1 + sha256rnds2 $ABEF0,$CDGH0 # 4-7 + movdqa $TMP1,$Wi + prefetcht0 127(@ptr[0]) + pshufb $TMPx,@MSG0[3] + pshufb $TMPx,@MSG1[2] + prefetcht0 127(@ptr[1]) + sha256rnds2 $ABEF1,$CDGH1 # 4-7 + pshufd \$0x0e,$TMP0,$Wi + pshufb $TMPx,@MSG1[3] + sha256msg1 @MSG0[1],@MSG0[0] + sha256rnds2 $CDGH0,$ABEF0 + pshufd \$0x0e,$TMP1,$Wi + movdqa 2*16-0x80($Tbl),$TMP0 + paddd @MSG0[2],$TMP0 + sha256rnds2 $CDGH1,$ABEF1 + + movdqa $TMP0,$Wi + movdqa 2*16-0x80($Tbl),$TMP1 + paddd @MSG1[2],$TMP1 + sha256rnds2 $ABEF0,$CDGH0 # 8-11 + sha256msg1 @MSG1[1],@MSG1[0] + movdqa $TMP1,$Wi + movdqa @MSG0[3],$TMPx + sha256rnds2 $ABEF1,$CDGH1 # 8-11 + pshufd \$0x0e,$TMP0,$Wi + palignr \$4,@MSG0[2],$TMPx + paddd $TMPx,@MSG0[0] + movdqa @MSG1[3],$TMPx + palignr \$4,@MSG1[2],$TMPx + sha256msg1 @MSG0[2],@MSG0[1] + sha256rnds2 $CDGH0,$ABEF0 + pshufd \$0x0e,$TMP1,$Wi + movdqa 3*16-0x80($Tbl),$TMP0 + paddd @MSG0[3],$TMP0 + sha256rnds2 $CDGH1,$ABEF1 + sha256msg1 @MSG1[2],@MSG1[1] + + movdqa $TMP0,$Wi + movdqa 3*16-0x80($Tbl),$TMP1 + paddd $TMPx,@MSG1[0] + paddd @MSG1[3],$TMP1 + sha256msg2 @MSG0[3],@MSG0[0] + sha256rnds2 $ABEF0,$CDGH0 # 12-15 + movdqa $TMP1,$Wi + movdqa @MSG0[0],$TMPx + palignr \$4,@MSG0[3],$TMPx + sha256rnds2 $ABEF1,$CDGH1 # 12-15 + sha256msg2 @MSG1[3],@MSG1[0] + pshufd \$0x0e,$TMP0,$Wi + paddd $TMPx,@MSG0[1] + movdqa @MSG1[0],$TMPx + palignr \$4,@MSG1[3],$TMPx + sha256msg1 @MSG0[3],@MSG0[2] + sha256rnds2 $CDGH0,$ABEF0 + pshufd \$0x0e,$TMP1,$Wi + movdqa 4*16-0x80($Tbl),$TMP0 + paddd @MSG0[0],$TMP0 + sha256rnds2 $CDGH1,$ABEF1 + sha256msg1 @MSG1[3],@MSG1[2] +___ +for($i=4;$i<16-3;$i++) { +$code.=<<___; + movdqa $TMP0,$Wi + movdqa $i*16-0x80($Tbl),$TMP1 + paddd $TMPx,@MSG1[1] + paddd @MSG1[0],$TMP1 + sha256msg2 @MSG0[0],@MSG0[1] + sha256rnds2 $ABEF0,$CDGH0 # 16-19... + movdqa $TMP1,$Wi + movdqa @MSG0[1],$TMPx + palignr \$4,@MSG0[0],$TMPx + sha256rnds2 $ABEF1,$CDGH1 # 16-19... + sha256msg2 @MSG1[0],@MSG1[1] + pshufd \$0x0e,$TMP0,$Wi + paddd $TMPx,@MSG0[2] + movdqa @MSG1[1],$TMPx + palignr \$4,@MSG1[0],$TMPx + sha256msg1 @MSG0[0],@MSG0[3] + sha256rnds2 $CDGH0,$ABEF0 + pshufd \$0x0e,$TMP1,$Wi + movdqa `($i+1)*16`-0x80($Tbl),$TMP0 + paddd @MSG0[1],$TMP0 + sha256rnds2 $CDGH1,$ABEF1 + sha256msg1 @MSG1[0],@MSG1[3] +___ + push(@MSG0,shift(@MSG0)); push(@MSG1,shift(@MSG1)); +} +$code.=<<___; + movdqa $TMP0,$Wi + movdqa 13*16-0x80($Tbl),$TMP1 + paddd $TMPx,@MSG1[1] + paddd @MSG1[0],$TMP1 + sha256msg2 @MSG0[0],@MSG0[1] + sha256rnds2 $ABEF0,$CDGH0 # 52-55 + movdqa $TMP1,$Wi + movdqa @MSG0[1],$TMPx + palignr \$4,@MSG0[0],$TMPx + sha256rnds2 $ABEF1,$CDGH1 # 52-55 + sha256msg2 @MSG1[0],@MSG1[1] + pshufd \$0x0e,$TMP0,$Wi + paddd $TMPx,@MSG0[2] + movdqa @MSG1[1],$TMPx + palignr \$4,@MSG1[0],$TMPx + nop + sha256rnds2 $CDGH0,$ABEF0 + pshufd \$0x0e,$TMP1,$Wi + movdqa 14*16-0x80($Tbl),$TMP0 + paddd @MSG0[1],$TMP0 + sha256rnds2 $CDGH1,$ABEF1 + + movdqa $TMP0,$Wi + movdqa 14*16-0x80($Tbl),$TMP1 + paddd $TMPx,@MSG1[2] + paddd @MSG1[1],$TMP1 + sha256msg2 @MSG0[1],@MSG0[2] + nop + sha256rnds2 $ABEF0,$CDGH0 # 56-59 + movdqa $TMP1,$Wi + mov \$1,%ecx + pxor @MSG0[1],@MSG0[1] # zero + sha256rnds2 $ABEF1,$CDGH1 # 56-59 + sha256msg2 @MSG1[1],@MSG1[2] + pshufd \$0x0e,$TMP0,$Wi + movdqa 15*16-0x80($Tbl),$TMP0 + paddd @MSG0[2],$TMP0 + movq (%rbx),@MSG0[2] # pull counters + nop + sha256rnds2 $CDGH0,$ABEF0 + pshufd \$0x0e,$TMP1,$Wi + movdqa 15*16-0x80($Tbl),$TMP1 + paddd @MSG1[2],$TMP1 + sha256rnds2 $CDGH1,$ABEF1 + + movdqa $TMP0,$Wi + cmp 4*0(%rbx),%ecx # examine counters + cmovge %rsp,@ptr[0] # cancel input + cmp 4*1(%rbx),%ecx + cmovge %rsp,@ptr[1] + pshufd \$0x00,@MSG0[2],@MSG1[0] + sha256rnds2 $ABEF0,$CDGH0 # 60-63 + movdqa $TMP1,$Wi + pshufd \$0x55,@MSG0[2],@MSG1[1] + movdqa @MSG0[2],@MSG1[2] + sha256rnds2 $ABEF1,$CDGH1 # 60-63 + pshufd \$0x0e,$TMP0,$Wi + pcmpgtd @MSG0[1],@MSG1[0] + pcmpgtd @MSG0[1],@MSG1[1] + sha256rnds2 $CDGH0,$ABEF0 + pshufd \$0x0e,$TMP1,$Wi + pcmpgtd @MSG0[1],@MSG1[2] # counter mask + movdqa K256_shaext-0x10(%rip),$TMPx + sha256rnds2 $CDGH1,$ABEF1 + + pand @MSG1[0],$CDGH0 + pand @MSG1[1],$CDGH1 + pand @MSG1[0],$ABEF0 + pand @MSG1[1],$ABEF1 + paddd @MSG0[2],@MSG1[2] # counters-- + + paddd 0x50(%rsp),$CDGH0 + paddd 0x70(%rsp),$CDGH1 + paddd 0x40(%rsp),$ABEF0 + paddd 0x60(%rsp),$ABEF1 + + movq @MSG1[2],(%rbx) # save counters + dec $num + jnz .Loop_shaext + + mov `$REG_SZ*17+8`(%rsp),$num + + pshufd \$0b00011011,$ABEF0,$ABEF0 + pshufd \$0b00011011,$CDGH0,$CDGH0 + pshufd \$0b00011011,$ABEF1,$ABEF1 + pshufd \$0b00011011,$CDGH1,$CDGH1 + + movdqa $ABEF0,@MSG0[0] + movdqa $CDGH0,@MSG0[1] + punpckldq $ABEF1,$ABEF0 # B1.B0.A1.A0 + punpckhdq $ABEF1,@MSG0[0] # F1.F0.E1.E0 + punpckldq $CDGH1,$CDGH0 # D1.D0.C1.C0 + punpckhdq $CDGH1,@MSG0[1] # H1.H0.G1.G0 + + movq $ABEF0,0x00-0x80($ctx) # A1.A0 + psrldq \$8,$ABEF0 + movq @MSG0[0],0x80-0x80($ctx) # E1.E0 + psrldq \$8,@MSG0[0] + movq $ABEF0,0x20-0x80($ctx) # B1.B0 + movq @MSG0[0],0xa0-0x80($ctx) # F1.F0 + + movq $CDGH0,0x40-0x80($ctx) # C1.C0 + psrldq \$8,$CDGH0 + movq @MSG0[1],0xc0-0x80($ctx) # G1.G0 + psrldq \$8,@MSG0[1] + movq $CDGH0,0x60-0x80($ctx) # D1.D0 + movq @MSG0[1],0xe0-0x80($ctx) # H1.H0 + + lea `$REG_SZ/2`($ctx),$ctx + lea `16*2`($inp),$inp + dec $num + jnz .Loop_grande_shaext + +.Ldone_shaext: + #mov `$REG_SZ*17`(%rsp),%rax # original %rsp +___ +$code.=<<___ if ($win64); + movaps -0xb8(%rax),%xmm6 + movaps -0xa8(%rax),%xmm7 + movaps -0x98(%rax),%xmm8 + movaps -0x88(%rax),%xmm9 + movaps -0x78(%rax),%xmm10 + movaps -0x68(%rax),%xmm11 + movaps -0x58(%rax),%xmm12 + movaps -0x48(%rax),%xmm13 + movaps -0x38(%rax),%xmm14 + movaps -0x28(%rax),%xmm15 +___ +$code.=<<___; + mov -16(%rax),%rbp +.cfi_restore %rbp + mov -8(%rax),%rbx +.cfi_restore %rbx + lea (%rax),%rsp +.cfi_def_cfa_register %rsp +.Lepilogue_shaext: + ret +.cfi_endproc +.size sha256_multi_block_shaext,.-sha256_multi_block_shaext +___ + }}} + if ($avx) {{{ +sub ROUND_00_15_avx { +my ($i,$a,$b,$c,$d,$e,$f,$g,$h)=@_; + +$code.=<<___ if ($i<15 && $REG_SZ==16); + vmovd `4*$i`(@ptr[0]),$Xi + vmovd `4*$i`(@ptr[1]),$t1 + vpinsrd \$1,`4*$i`(@ptr[2]),$Xi,$Xi + vpinsrd \$1,`4*$i`(@ptr[3]),$t1,$t1 + vpunpckldq $t1,$Xi,$Xi + vpshufb $Xn,$Xi,$Xi +___ +$code.=<<___ if ($i==15 && $REG_SZ==16); + vmovd `4*$i`(@ptr[0]),$Xi + lea `16*4`(@ptr[0]),@ptr[0] + vmovd `4*$i`(@ptr[1]),$t1 + lea `16*4`(@ptr[1]),@ptr[1] + vpinsrd \$1,`4*$i`(@ptr[2]),$Xi,$Xi + lea `16*4`(@ptr[2]),@ptr[2] + vpinsrd \$1,`4*$i`(@ptr[3]),$t1,$t1 + lea `16*4`(@ptr[3]),@ptr[3] + vpunpckldq $t1,$Xi,$Xi + vpshufb $Xn,$Xi,$Xi +___ +$code.=<<___ if ($i<15 && $REG_SZ==32); + vmovd `4*$i`(@ptr[0]),$Xi + vmovd `4*$i`(@ptr[4]),$t1 + vmovd `4*$i`(@ptr[1]),$t2 + vmovd `4*$i`(@ptr[5]),$t3 + vpinsrd \$1,`4*$i`(@ptr[2]),$Xi,$Xi + vpinsrd \$1,`4*$i`(@ptr[6]),$t1,$t1 + vpinsrd \$1,`4*$i`(@ptr[3]),$t2,$t2 + vpunpckldq $t2,$Xi,$Xi + vpinsrd \$1,`4*$i`(@ptr[7]),$t3,$t3 + vpunpckldq $t3,$t1,$t1 + vinserti128 $t1,$Xi,$Xi + vpshufb $Xn,$Xi,$Xi +___ +$code.=<<___ if ($i==15 && $REG_SZ==32); + vmovd `4*$i`(@ptr[0]),$Xi + lea `16*4`(@ptr[0]),@ptr[0] + vmovd `4*$i`(@ptr[4]),$t1 + lea `16*4`(@ptr[4]),@ptr[4] + vmovd `4*$i`(@ptr[1]),$t2 + lea `16*4`(@ptr[1]),@ptr[1] + vmovd `4*$i`(@ptr[5]),$t3 + lea `16*4`(@ptr[5]),@ptr[5] + vpinsrd \$1,`4*$i`(@ptr[2]),$Xi,$Xi + lea `16*4`(@ptr[2]),@ptr[2] + vpinsrd \$1,`4*$i`(@ptr[6]),$t1,$t1 + lea `16*4`(@ptr[6]),@ptr[6] + vpinsrd \$1,`4*$i`(@ptr[3]),$t2,$t2 + lea `16*4`(@ptr[3]),@ptr[3] + vpunpckldq $t2,$Xi,$Xi + vpinsrd \$1,`4*$i`(@ptr[7]),$t3,$t3 + lea `16*4`(@ptr[7]),@ptr[7] + vpunpckldq $t3,$t1,$t1 + vinserti128 $t1,$Xi,$Xi + vpshufb $Xn,$Xi,$Xi +___ +$code.=<<___; + vpsrld \$6,$e,$sigma + vpslld \$26,$e,$t3 + vmovdqu $Xi,`&Xi_off($i)` + vpaddd $h,$Xi,$Xi # Xi+=h + + vpsrld \$11,$e,$t2 + vpxor $t3,$sigma,$sigma + vpslld \$21,$e,$t3 + vpaddd `32*($i%8)-128`($Tbl),$Xi,$Xi # Xi+=K[round] + vpxor $t2,$sigma,$sigma + + vpsrld \$25,$e,$t2 + vpxor $t3,$sigma,$sigma + `"prefetcht0 63(@ptr[0])" if ($i==15)` + vpslld \$7,$e,$t3 + vpandn $g,$e,$t1 + vpand $f,$e,$axb # borrow $axb + `"prefetcht0 63(@ptr[1])" if ($i==15)` + vpxor $t2,$sigma,$sigma + + vpsrld \$2,$a,$h # borrow $h + vpxor $t3,$sigma,$sigma # Sigma1(e) + `"prefetcht0 63(@ptr[2])" if ($i==15)` + vpslld \$30,$a,$t2 + vpxor $axb,$t1,$t1 # Ch(e,f,g) + vpxor $a,$b,$axb # a^b, b^c in next round + `"prefetcht0 63(@ptr[3])" if ($i==15)` + vpxor $t2,$h,$h + vpaddd $sigma,$Xi,$Xi # Xi+=Sigma1(e) + + vpsrld \$13,$a,$t2 + `"prefetcht0 63(@ptr[4])" if ($i==15 && $REG_SZ==32)` + vpslld \$19,$a,$t3 + vpaddd $t1,$Xi,$Xi # Xi+=Ch(e,f,g) + vpand $axb,$bxc,$bxc + `"prefetcht0 63(@ptr[5])" if ($i==15 && $REG_SZ==32)` + vpxor $t2,$h,$sigma + + vpsrld \$22,$a,$t2 + vpxor $t3,$sigma,$sigma + `"prefetcht0 63(@ptr[6])" if ($i==15 && $REG_SZ==32)` + vpslld \$10,$a,$t3 + vpxor $bxc,$b,$h # h=Maj(a,b,c)=Ch(a^b,c,b) + vpaddd $Xi,$d,$d # d+=Xi + `"prefetcht0 63(@ptr[7])" if ($i==15 && $REG_SZ==32)` + vpxor $t2,$sigma,$sigma + vpxor $t3,$sigma,$sigma # Sigma0(a) + + vpaddd $Xi,$h,$h # h+=Xi + vpaddd $sigma,$h,$h # h+=Sigma0(a) +___ +$code.=<<___ if (($i%8)==7); + add \$`32*8`,$Tbl +___ + ($axb,$bxc)=($bxc,$axb); +} + +sub ROUND_16_XX_avx { +my $i=shift; + +$code.=<<___; + vmovdqu `&Xi_off($i+1)`,$Xn + vpaddd `&Xi_off($i+9)`,$Xi,$Xi # Xi+=X[i+9] + + vpsrld \$3,$Xn,$sigma + vpsrld \$7,$Xn,$t2 + vpslld \$25,$Xn,$t3 + vpxor $t2,$sigma,$sigma + vpsrld \$18,$Xn,$t2 + vpxor $t3,$sigma,$sigma + vpslld \$14,$Xn,$t3 + vmovdqu `&Xi_off($i+14)`,$t1 + vpsrld \$10,$t1,$axb # borrow $axb + + vpxor $t2,$sigma,$sigma + vpsrld \$17,$t1,$t2 + vpxor $t3,$sigma,$sigma # sigma0(X[i+1]) + vpslld \$15,$t1,$t3 + vpaddd $sigma,$Xi,$Xi # Xi+=sigma0(e) + vpxor $t2,$axb,$sigma + vpsrld \$19,$t1,$t2 + vpxor $t3,$sigma,$sigma + vpslld \$13,$t1,$t3 + vpxor $t2,$sigma,$sigma + vpxor $t3,$sigma,$sigma # sigma0(X[i+14]) + vpaddd $sigma,$Xi,$Xi # Xi+=sigma1(X[i+14]) +___ + &ROUND_00_15_avx($i,@_); + ($Xi,$Xn)=($Xn,$Xi); +} + +$code.=<<___; +.type sha256_multi_block_avx,\@function,3 +.align 32 +sha256_multi_block_avx: +.cfi_startproc +_avx_shortcut: +___ +$code.=<<___ if ($avx>1); + shr \$32,%rcx + cmp \$2,$num + jb .Lavx + test \$`1<<5`,%ecx + jnz _avx2_shortcut + jmp .Lavx +.align 32 +.Lavx: +___ +$code.=<<___; + mov %rsp,%rax +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp +___ +$code.=<<___ if ($win64); + lea -0xa8(%rsp),%rsp + movaps %xmm6,(%rsp) + movaps %xmm7,0x10(%rsp) + movaps %xmm8,0x20(%rsp) + movaps %xmm9,0x30(%rsp) + movaps %xmm10,-0x78(%rax) + movaps %xmm11,-0x68(%rax) + movaps %xmm12,-0x58(%rax) + movaps %xmm13,-0x48(%rax) + movaps %xmm14,-0x38(%rax) + movaps %xmm15,-0x28(%rax) +___ +$code.=<<___; + sub \$`$REG_SZ*18`, %rsp + and \$-256,%rsp + mov %rax,`$REG_SZ*17`(%rsp) # original %rsp +.cfi_cfa_expression %rsp+`$REG_SZ*17`,deref,+8 +.Lbody_avx: + lea K256+128(%rip),$Tbl + lea `$REG_SZ*16`(%rsp),%rbx + lea 0x80($ctx),$ctx # size optimization + +.Loop_grande_avx: + mov $num,`$REG_SZ*17+8`(%rsp) # original $num + xor $num,$num +___ +for($i=0;$i<4;$i++) { + $code.=<<___; + mov `16*$i+0`($inp),@ptr[$i] # input pointer + mov `16*$i+8`($inp),%ecx # number of blocks + cmp $num,%ecx + cmovg %ecx,$num # find maximum + test %ecx,%ecx + mov %ecx,`4*$i`(%rbx) # initialize counters + cmovle $Tbl,@ptr[$i] # cancel input +___ +} +$code.=<<___; + test $num,$num + jz .Ldone_avx + + vmovdqu 0x00-0x80($ctx),$A # load context + lea 128(%rsp),%rax + vmovdqu 0x20-0x80($ctx),$B + vmovdqu 0x40-0x80($ctx),$C + vmovdqu 0x60-0x80($ctx),$D + vmovdqu 0x80-0x80($ctx),$E + vmovdqu 0xa0-0x80($ctx),$F + vmovdqu 0xc0-0x80($ctx),$G + vmovdqu 0xe0-0x80($ctx),$H + vmovdqu .Lpbswap(%rip),$Xn + jmp .Loop_avx + +.align 32 +.Loop_avx: + vpxor $B,$C,$bxc # magic seed +___ +for($i=0;$i<16;$i++) { &ROUND_00_15_avx($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + vmovdqu `&Xi_off($i)`,$Xi + mov \$3,%ecx + jmp .Loop_16_xx_avx +.align 32 +.Loop_16_xx_avx: +___ +for(;$i<32;$i++) { &ROUND_16_XX_avx($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + dec %ecx + jnz .Loop_16_xx_avx + + mov \$1,%ecx + lea K256+128(%rip),$Tbl +___ +for($i=0;$i<4;$i++) { + $code.=<<___; + cmp `4*$i`(%rbx),%ecx # examine counters + cmovge $Tbl,@ptr[$i] # cancel input +___ +} +$code.=<<___; + vmovdqa (%rbx),$sigma # pull counters + vpxor $t1,$t1,$t1 + vmovdqa $sigma,$Xn + vpcmpgtd $t1,$Xn,$Xn # mask value + vpaddd $Xn,$sigma,$sigma # counters-- + + vmovdqu 0x00-0x80($ctx),$t1 + vpand $Xn,$A,$A + vmovdqu 0x20-0x80($ctx),$t2 + vpand $Xn,$B,$B + vmovdqu 0x40-0x80($ctx),$t3 + vpand $Xn,$C,$C + vmovdqu 0x60-0x80($ctx),$Xi + vpand $Xn,$D,$D + vpaddd $t1,$A,$A + vmovdqu 0x80-0x80($ctx),$t1 + vpand $Xn,$E,$E + vpaddd $t2,$B,$B + vmovdqu 0xa0-0x80($ctx),$t2 + vpand $Xn,$F,$F + vpaddd $t3,$C,$C + vmovdqu 0xc0-0x80($ctx),$t3 + vpand $Xn,$G,$G + vpaddd $Xi,$D,$D + vmovdqu 0xe0-0x80($ctx),$Xi + vpand $Xn,$H,$H + vpaddd $t1,$E,$E + vpaddd $t2,$F,$F + vmovdqu $A,0x00-0x80($ctx) + vpaddd $t3,$G,$G + vmovdqu $B,0x20-0x80($ctx) + vpaddd $Xi,$H,$H + vmovdqu $C,0x40-0x80($ctx) + vmovdqu $D,0x60-0x80($ctx) + vmovdqu $E,0x80-0x80($ctx) + vmovdqu $F,0xa0-0x80($ctx) + vmovdqu $G,0xc0-0x80($ctx) + vmovdqu $H,0xe0-0x80($ctx) + + vmovdqu $sigma,(%rbx) # save counters + vmovdqu .Lpbswap(%rip),$Xn + dec $num + jnz .Loop_avx + + mov `$REG_SZ*17+8`(%rsp),$num + lea $REG_SZ($ctx),$ctx + lea `16*$REG_SZ/4`($inp),$inp + dec $num + jnz .Loop_grande_avx + +.Ldone_avx: + mov `$REG_SZ*17`(%rsp),%rax # original %rsp +.cfi_def_cfa %rax,8 + vzeroupper +___ +$code.=<<___ if ($win64); + movaps -0xb8(%rax),%xmm6 + movaps -0xa8(%rax),%xmm7 + movaps -0x98(%rax),%xmm8 + movaps -0x88(%rax),%xmm9 + movaps -0x78(%rax),%xmm10 + movaps -0x68(%rax),%xmm11 + movaps -0x58(%rax),%xmm12 + movaps -0x48(%rax),%xmm13 + movaps -0x38(%rax),%xmm14 + movaps -0x28(%rax),%xmm15 +___ +$code.=<<___; + mov -16(%rax),%rbp +.cfi_restore %rbp + mov -8(%rax),%rbx +.cfi_restore %rbx + lea (%rax),%rsp +.cfi_def_cfa_register %rsp +.Lepilogue_avx: + ret +.cfi_endproc +.size sha256_multi_block_avx,.-sha256_multi_block_avx +___ + if ($avx>1) { +$code =~ s/\`([^\`]*)\`/eval $1/gem; + +$REG_SZ=32; +@ptr=map("%r$_",(12..15,8..11)); + +@V=($A,$B,$C,$D,$E,$F,$G,$H)=map("%ymm$_",(8..15)); +($t1,$t2,$t3,$axb,$bxc,$Xi,$Xn,$sigma)=map("%ymm$_",(0..7)); + +$code.=<<___; +.type sha256_multi_block_avx2,\@function,3 +.align 32 +sha256_multi_block_avx2: +.cfi_startproc +_avx2_shortcut: + mov %rsp,%rax +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +___ +$code.=<<___ if ($win64); + lea -0xa8(%rsp),%rsp + movaps %xmm6,(%rsp) + movaps %xmm7,0x10(%rsp) + movaps %xmm8,0x20(%rsp) + movaps %xmm9,0x30(%rsp) + movaps %xmm10,0x40(%rsp) + movaps %xmm11,0x50(%rsp) + movaps %xmm12,-0x78(%rax) + movaps %xmm13,-0x68(%rax) + movaps %xmm14,-0x58(%rax) + movaps %xmm15,-0x48(%rax) +___ +$code.=<<___; + sub \$`$REG_SZ*18`, %rsp + and \$-256,%rsp + mov %rax,`$REG_SZ*17`(%rsp) # original %rsp +.cfi_cfa_expression %rsp+`$REG_SZ*17`,deref,+8 +.Lbody_avx2: + lea K256+128(%rip),$Tbl + lea 0x80($ctx),$ctx # size optimization + +.Loop_grande_avx2: + mov $num,`$REG_SZ*17+8`(%rsp) # original $num + xor $num,$num + lea `$REG_SZ*16`(%rsp),%rbx +___ +for($i=0;$i<8;$i++) { + $code.=<<___; + mov `16*$i+0`($inp),@ptr[$i] # input pointer + mov `16*$i+8`($inp),%ecx # number of blocks + cmp $num,%ecx + cmovg %ecx,$num # find maximum + test %ecx,%ecx + mov %ecx,`4*$i`(%rbx) # initialize counters + cmovle $Tbl,@ptr[$i] # cancel input +___ +} +$code.=<<___; + vmovdqu 0x00-0x80($ctx),$A # load context + lea 128(%rsp),%rax + vmovdqu 0x20-0x80($ctx),$B + lea 256+128(%rsp),%rbx + vmovdqu 0x40-0x80($ctx),$C + vmovdqu 0x60-0x80($ctx),$D + vmovdqu 0x80-0x80($ctx),$E + vmovdqu 0xa0-0x80($ctx),$F + vmovdqu 0xc0-0x80($ctx),$G + vmovdqu 0xe0-0x80($ctx),$H + vmovdqu .Lpbswap(%rip),$Xn + jmp .Loop_avx2 + +.align 32 +.Loop_avx2: + vpxor $B,$C,$bxc # magic seed +___ +for($i=0;$i<16;$i++) { &ROUND_00_15_avx($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + vmovdqu `&Xi_off($i)`,$Xi + mov \$3,%ecx + jmp .Loop_16_xx_avx2 +.align 32 +.Loop_16_xx_avx2: +___ +for(;$i<32;$i++) { &ROUND_16_XX_avx($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + dec %ecx + jnz .Loop_16_xx_avx2 + + mov \$1,%ecx + lea `$REG_SZ*16`(%rsp),%rbx + lea K256+128(%rip),$Tbl +___ +for($i=0;$i<8;$i++) { + $code.=<<___; + cmp `4*$i`(%rbx),%ecx # examine counters + cmovge $Tbl,@ptr[$i] # cancel input +___ +} +$code.=<<___; + vmovdqa (%rbx),$sigma # pull counters + vpxor $t1,$t1,$t1 + vmovdqa $sigma,$Xn + vpcmpgtd $t1,$Xn,$Xn # mask value + vpaddd $Xn,$sigma,$sigma # counters-- + + vmovdqu 0x00-0x80($ctx),$t1 + vpand $Xn,$A,$A + vmovdqu 0x20-0x80($ctx),$t2 + vpand $Xn,$B,$B + vmovdqu 0x40-0x80($ctx),$t3 + vpand $Xn,$C,$C + vmovdqu 0x60-0x80($ctx),$Xi + vpand $Xn,$D,$D + vpaddd $t1,$A,$A + vmovdqu 0x80-0x80($ctx),$t1 + vpand $Xn,$E,$E + vpaddd $t2,$B,$B + vmovdqu 0xa0-0x80($ctx),$t2 + vpand $Xn,$F,$F + vpaddd $t3,$C,$C + vmovdqu 0xc0-0x80($ctx),$t3 + vpand $Xn,$G,$G + vpaddd $Xi,$D,$D + vmovdqu 0xe0-0x80($ctx),$Xi + vpand $Xn,$H,$H + vpaddd $t1,$E,$E + vpaddd $t2,$F,$F + vmovdqu $A,0x00-0x80($ctx) + vpaddd $t3,$G,$G + vmovdqu $B,0x20-0x80($ctx) + vpaddd $Xi,$H,$H + vmovdqu $C,0x40-0x80($ctx) + vmovdqu $D,0x60-0x80($ctx) + vmovdqu $E,0x80-0x80($ctx) + vmovdqu $F,0xa0-0x80($ctx) + vmovdqu $G,0xc0-0x80($ctx) + vmovdqu $H,0xe0-0x80($ctx) + + vmovdqu $sigma,(%rbx) # save counters + lea 256+128(%rsp),%rbx + vmovdqu .Lpbswap(%rip),$Xn + dec $num + jnz .Loop_avx2 + + #mov `$REG_SZ*17+8`(%rsp),$num + #lea $REG_SZ($ctx),$ctx + #lea `16*$REG_SZ/4`($inp),$inp + #dec $num + #jnz .Loop_grande_avx2 + +.Ldone_avx2: + mov `$REG_SZ*17`(%rsp),%rax # original %rsp +.cfi_def_cfa %rax,8 + vzeroupper +___ +$code.=<<___ if ($win64); + movaps -0xd8(%rax),%xmm6 + movaps -0xc8(%rax),%xmm7 + movaps -0xb8(%rax),%xmm8 + movaps -0xa8(%rax),%xmm9 + movaps -0x98(%rax),%xmm10 + movaps -0x88(%rax),%xmm11 + movaps -0x78(%rax),%xmm12 + movaps -0x68(%rax),%xmm13 + movaps -0x58(%rax),%xmm14 + movaps -0x48(%rax),%xmm15 +___ +$code.=<<___; + mov -48(%rax),%r15 +.cfi_restore %r15 + mov -40(%rax),%r14 +.cfi_restore %r14 + mov -32(%rax),%r13 +.cfi_restore %r13 + mov -24(%rax),%r12 +.cfi_restore %r12 + mov -16(%rax),%rbp +.cfi_restore %rbp + mov -8(%rax),%rbx +.cfi_restore %rbx + lea (%rax),%rsp +.cfi_def_cfa_register %rsp +.Lepilogue_avx2: + ret +.cfi_endproc +.size sha256_multi_block_avx2,.-sha256_multi_block_avx2 +___ + } }}} +$code.=<<___; +.align 256 +K256: +___ +sub TABLE { + foreach (@_) { + $code.=<<___; + .long $_,$_,$_,$_ + .long $_,$_,$_,$_ +___ + } +} +&TABLE( 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5, + 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5, + 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3, + 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174, + 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc, + 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da, + 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7, + 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967, + 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13, + 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85, + 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3, + 0xd192e819,0xd6990624,0xf40e3585,0x106aa070, + 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5, + 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3, + 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208, + 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 ); +$code.=<<___; +.Lpbswap: + .long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f # pbswap + .long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f # pbswap +K256_shaext: + .long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 + .long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 + .long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 + .long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 + .long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc + .long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da + .long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 + .long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967 + .long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 + .long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 + .long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 + .long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 + .long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 + .long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 + .long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 + .long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 + .asciz "SHA256 multi-block transform for x86_64, CRYPTOGAMS by " +___ + +if ($win64) { +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type se_handler,\@abi-omnipotent +.align 16 +se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # end of prologue label + cmp %r10,%rbx # context->Rip<.Lbody + jb .Lin_prologue + + mov 152($context),%rax # pull context->Rsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=.Lepilogue + jae .Lin_prologue + + mov `16*17`(%rax),%rax # pull saved stack pointer + + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + + lea -24-10*16(%rax),%rsi + lea 512($context),%rdi # &context.Xmm6 + mov \$20,%ecx + .long 0xa548f3fc # cld; rep movsq + +.Lin_prologue: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size se_handler,.-se_handler +___ +$code.=<<___ if ($avx>1); +.type avx2_handler,\@abi-omnipotent +.align 16 +avx2_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # end of prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lin_prologue + + mov `32*17`($context),%rax # pull saved stack pointer + + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov -48(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + + lea -56-10*16(%rax),%rsi + lea 512($context),%rdi # &context.Xmm6 + mov \$20,%ecx + .long 0xa548f3fc # cld; rep movsq + + jmp .Lin_prologue +.size avx2_handler,.-avx2_handler +___ +$code.=<<___; +.section .pdata +.align 4 + .rva .LSEH_begin_sha256_multi_block + .rva .LSEH_end_sha256_multi_block + .rva .LSEH_info_sha256_multi_block + .rva .LSEH_begin_sha256_multi_block_shaext + .rva .LSEH_end_sha256_multi_block_shaext + .rva .LSEH_info_sha256_multi_block_shaext +___ +$code.=<<___ if ($avx); + .rva .LSEH_begin_sha256_multi_block_avx + .rva .LSEH_end_sha256_multi_block_avx + .rva .LSEH_info_sha256_multi_block_avx +___ +$code.=<<___ if ($avx>1); + .rva .LSEH_begin_sha256_multi_block_avx2 + .rva .LSEH_end_sha256_multi_block_avx2 + .rva .LSEH_info_sha256_multi_block_avx2 +___ +$code.=<<___; +.section .xdata +.align 8 +.LSEH_info_sha256_multi_block: + .byte 9,0,0,0 + .rva se_handler + .rva .Lbody,.Lepilogue # HandlerData[] +.LSEH_info_sha256_multi_block_shaext: + .byte 9,0,0,0 + .rva se_handler + .rva .Lbody_shaext,.Lepilogue_shaext # HandlerData[] +___ +$code.=<<___ if ($avx); +.LSEH_info_sha256_multi_block_avx: + .byte 9,0,0,0 + .rva se_handler + .rva .Lbody_avx,.Lepilogue_avx # HandlerData[] +___ +$code.=<<___ if ($avx>1); +.LSEH_info_sha256_multi_block_avx2: + .byte 9,0,0,0 + .rva avx2_handler + .rva .Lbody_avx2,.Lepilogue_avx2 # HandlerData[] +___ +} +#################################################################### + +sub rex { + local *opcode=shift; + my ($dst,$src)=@_; + my $rex=0; + + $rex|=0x04 if ($dst>=8); + $rex|=0x01 if ($src>=8); + unshift @opcode,$rex|0x40 if ($rex); +} + +sub sha256op38 { + my $instr = shift; + my %opcodelet = ( + "sha256rnds2" => 0xcb, + "sha256msg1" => 0xcc, + "sha256msg2" => 0xcd ); + + if (defined($opcodelet{$instr}) && @_[0] =~ /%xmm([0-9]+),\s*%xmm([0-9]+)/) { + my @opcode=(0x0f,0x38); + rex(\@opcode,$2,$1); + push @opcode,$opcodelet{$instr}; + push @opcode,0xc0|($1&7)|(($2&7)<<3); # ModR/M + return ".byte\t".join(',',@opcode); + } else { + return $instr."\t".@_[0]; + } +} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval($1)/ge; + + s/\b(sha256[^\s]*)\s+(.*)/sha256op38($1,$2)/geo or + + s/\b(vmov[dq])\b(.+)%ymm([0-9]+)/$1$2%xmm$3/go or + s/\b(vmovdqu)\b(.+)%x%ymm([0-9]+)/$1$2%xmm$3/go or + s/\b(vpinsr[qd])\b(.+)%ymm([0-9]+),%ymm([0-9]+)/$1$2%xmm$3,%xmm$4/go or + s/\b(vpextr[qd])\b(.+)%ymm([0-9]+)/$1$2%xmm$3/go or + s/\b(vinserti128)\b(\s+)%ymm/$1$2\$1,%xmm/go or + s/\b(vpbroadcast[qd]\s+)%ymm([0-9]+)/$1%xmm$2/go; + + print $_,"\n"; +} + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-586.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-586.pl new file mode 100644 index 000000000..867ce30b9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-586.pl @@ -0,0 +1,925 @@ +#! /usr/bin/env perl +# Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# SHA512 block transform for x86. September 2007. +# +# May 2013. +# +# Add SSSE3 code path, 20-25% improvement [over original SSE2 code]. +# +# Performance in clock cycles per processed byte (less is better): +# +# gcc icc x86 asm SIMD(*) x86_64(**) +# Pentium 100 97 61 - - +# PIII 75 77 56 - - +# P4 116 95 82 34.6 30.8 +# AMD K8 54 55 36 20.7 9.57 +# Core2 66 57 40 15.9 9.97 +# Westmere 70 - 38 12.2 9.58 +# Sandy Bridge 58 - 35 11.9 11.2 +# Ivy Bridge 50 - 33 11.5 8.17 +# Haswell 46 - 29 11.3 7.66 +# Skylake 40 - 26 13.3 7.25 +# Bulldozer 121 - 50 14.0 13.5 +# VIA Nano 91 - 52 33 14.7 +# Atom 126 - 68 48(***) 14.7 +# Silvermont 97 - 58 42(***) 17.5 +# Goldmont 80 - 48 19.5 12.0 +# +# (*) whichever best applicable. +# (**) x86_64 assembler performance is presented for reference +# purposes, the results are for integer-only code. +# (***) paddq is incredibly slow on Atom. +# +# IALU code-path is optimized for elder Pentiums. On vanilla Pentium +# performance improvement over compiler generated code reaches ~60%, +# while on PIII - ~35%. On newer µ-archs improvement varies from 15% +# to 50%, but it's less important as they are expected to execute SSE2 +# code-path, which is commonly ~2-3x faster [than compiler generated +# code]. SSE2 code-path is as fast as original sha512-sse2.pl, even +# though it does not use 128-bit operations. The latter means that +# SSE2-aware kernel is no longer required to execute the code. Another +# difference is that new code optimizes amount of writes, but at the +# cost of increased data cache "footprint" by 1/2KB. + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +$output=pop; +open STDOUT,">$output"; + +&asm_init($ARGV[0],$ARGV[$#ARGV] eq "386"); + +$sse2=0; +for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); } + +&external_label("OPENSSL_ia32cap_P") if ($sse2); + +$Tlo=&DWP(0,"esp"); $Thi=&DWP(4,"esp"); +$Alo=&DWP(8,"esp"); $Ahi=&DWP(8+4,"esp"); +$Blo=&DWP(16,"esp"); $Bhi=&DWP(16+4,"esp"); +$Clo=&DWP(24,"esp"); $Chi=&DWP(24+4,"esp"); +$Dlo=&DWP(32,"esp"); $Dhi=&DWP(32+4,"esp"); +$Elo=&DWP(40,"esp"); $Ehi=&DWP(40+4,"esp"); +$Flo=&DWP(48,"esp"); $Fhi=&DWP(48+4,"esp"); +$Glo=&DWP(56,"esp"); $Ghi=&DWP(56+4,"esp"); +$Hlo=&DWP(64,"esp"); $Hhi=&DWP(64+4,"esp"); +$K512="ebp"; + +$Asse2=&QWP(0,"esp"); +$Bsse2=&QWP(8,"esp"); +$Csse2=&QWP(16,"esp"); +$Dsse2=&QWP(24,"esp"); +$Esse2=&QWP(32,"esp"); +$Fsse2=&QWP(40,"esp"); +$Gsse2=&QWP(48,"esp"); +$Hsse2=&QWP(56,"esp"); + +$A="mm0"; # B-D and +$E="mm4"; # F-H are commonly loaded to respectively mm1-mm3 and + # mm5-mm7, but it's done on on-demand basis... +$BxC="mm2"; # ... except for B^C + +sub BODY_00_15_sse2 { + my $phase=shift; + + #&movq ("mm5",$Fsse2); # load f + #&movq ("mm6",$Gsse2); # load g + + &movq ("mm1",$E); # %mm1 is sliding right + &pxor ("mm5","mm6"); # f^=g + &psrlq ("mm1",14); + &movq ($Esse2,$E); # modulo-scheduled save e + &pand ("mm5",$E); # f&=e + &psllq ($E,23); # $E is sliding left + &movq ($A,"mm3") if ($phase<2); + &movq (&QWP(8*9,"esp"),"mm7") # save X[i] + &movq ("mm3","mm1"); # %mm3 is T1 + &psrlq ("mm1",4); + &pxor ("mm5","mm6"); # Ch(e,f,g) + &pxor ("mm3",$E); + &psllq ($E,23); + &pxor ("mm3","mm1"); + &movq ($Asse2,$A); # modulo-scheduled save a + &paddq ("mm7","mm5"); # X[i]+=Ch(e,f,g) + &pxor ("mm3",$E); + &psrlq ("mm1",23); + &paddq ("mm7",$Hsse2); # X[i]+=h + &pxor ("mm3","mm1"); + &psllq ($E,4); + &paddq ("mm7",QWP(0,$K512)); # X[i]+=K512[i] + &pxor ("mm3",$E); # T1=Sigma1_512(e) + + &movq ($E,$Dsse2); # e = load d, e in next round + &paddq ("mm3","mm7"); # T1+=X[i] + &movq ("mm5",$A); # %mm5 is sliding right + &psrlq ("mm5",28); + &paddq ($E,"mm3"); # d += T1 + &movq ("mm6",$A); # %mm6 is sliding left + &movq ("mm7","mm5"); + &psllq ("mm6",25); + &movq ("mm1",$Bsse2); # load b + &psrlq ("mm5",6); + &pxor ("mm7","mm6"); + &sub ("esp",8); + &psllq ("mm6",5); + &pxor ("mm7","mm5"); + &pxor ($A,"mm1"); # a^b, b^c in next round + &psrlq ("mm5",5); + &pxor ("mm7","mm6"); + &pand ($BxC,$A); # (b^c)&(a^b) + &psllq ("mm6",6); + &pxor ("mm7","mm5"); + &pxor ($BxC,"mm1"); # [h=]Maj(a,b,c) + &pxor ("mm6","mm7"); # Sigma0_512(a) + &movq ("mm7",&QWP(8*(9+16-1),"esp")) if ($phase!=0); # pre-fetch + &movq ("mm5",$Fsse2) if ($phase==0); # load f + + if ($phase>1) { + &paddq ($BxC,"mm6"); # h+=Sigma0(a) + &add ($K512,8); + #&paddq ($BxC,"mm3"); # h+=T1 + + ($A,$BxC) = ($BxC,$A); # rotate registers + } else { + &paddq ("mm3",$BxC); # T1+=Maj(a,b,c) + &movq ($BxC,$A); + &add ($K512,8); + &paddq ("mm3","mm6"); # T1+=Sigma0(a) + &movq ("mm6",$Gsse2) if ($phase==0); # load g + #&movq ($A,"mm3"); # h=T1 + } +} + +sub BODY_00_15_x86 { + #define Sigma1(x) (ROTR((x),14) ^ ROTR((x),18) ^ ROTR((x),41)) + # LO lo>>14^hi<<18 ^ lo>>18^hi<<14 ^ hi>>9^lo<<23 + # HI hi>>14^lo<<18 ^ hi>>18^lo<<14 ^ lo>>9^hi<<23 + &mov ("ecx",$Elo); + &mov ("edx",$Ehi); + &mov ("esi","ecx"); + + &shr ("ecx",9); # lo>>9 + &mov ("edi","edx"); + &shr ("edx",9); # hi>>9 + &mov ("ebx","ecx"); + &shl ("esi",14); # lo<<14 + &mov ("eax","edx"); + &shl ("edi",14); # hi<<14 + &xor ("ebx","esi"); + + &shr ("ecx",14-9); # lo>>14 + &xor ("eax","edi"); + &shr ("edx",14-9); # hi>>14 + &xor ("eax","ecx"); + &shl ("esi",18-14); # lo<<18 + &xor ("ebx","edx"); + &shl ("edi",18-14); # hi<<18 + &xor ("ebx","esi"); + + &shr ("ecx",18-14); # lo>>18 + &xor ("eax","edi"); + &shr ("edx",18-14); # hi>>18 + &xor ("eax","ecx"); + &shl ("esi",23-18); # lo<<23 + &xor ("ebx","edx"); + &shl ("edi",23-18); # hi<<23 + &xor ("eax","esi"); + &xor ("ebx","edi"); # T1 = Sigma1(e) + + &mov ("ecx",$Flo); + &mov ("edx",$Fhi); + &mov ("esi",$Glo); + &mov ("edi",$Ghi); + &add ("eax",$Hlo); + &adc ("ebx",$Hhi); # T1 += h + &xor ("ecx","esi"); + &xor ("edx","edi"); + &and ("ecx",$Elo); + &and ("edx",$Ehi); + &add ("eax",&DWP(8*(9+15)+0,"esp")); + &adc ("ebx",&DWP(8*(9+15)+4,"esp")); # T1 += X[0] + &xor ("ecx","esi"); + &xor ("edx","edi"); # Ch(e,f,g) = (f^g)&e)^g + + &mov ("esi",&DWP(0,$K512)); + &mov ("edi",&DWP(4,$K512)); # K[i] + &add ("eax","ecx"); + &adc ("ebx","edx"); # T1 += Ch(e,f,g) + &mov ("ecx",$Dlo); + &mov ("edx",$Dhi); + &add ("eax","esi"); + &adc ("ebx","edi"); # T1 += K[i] + &mov ($Tlo,"eax"); + &mov ($Thi,"ebx"); # put T1 away + &add ("eax","ecx"); + &adc ("ebx","edx"); # d += T1 + + #define Sigma0(x) (ROTR((x),28) ^ ROTR((x),34) ^ ROTR((x),39)) + # LO lo>>28^hi<<4 ^ hi>>2^lo<<30 ^ hi>>7^lo<<25 + # HI hi>>28^lo<<4 ^ lo>>2^hi<<30 ^ lo>>7^hi<<25 + &mov ("ecx",$Alo); + &mov ("edx",$Ahi); + &mov ($Dlo,"eax"); + &mov ($Dhi,"ebx"); + &mov ("esi","ecx"); + + &shr ("ecx",2); # lo>>2 + &mov ("edi","edx"); + &shr ("edx",2); # hi>>2 + &mov ("ebx","ecx"); + &shl ("esi",4); # lo<<4 + &mov ("eax","edx"); + &shl ("edi",4); # hi<<4 + &xor ("ebx","esi"); + + &shr ("ecx",7-2); # lo>>7 + &xor ("eax","edi"); + &shr ("edx",7-2); # hi>>7 + &xor ("ebx","ecx"); + &shl ("esi",25-4); # lo<<25 + &xor ("eax","edx"); + &shl ("edi",25-4); # hi<<25 + &xor ("eax","esi"); + + &shr ("ecx",28-7); # lo>>28 + &xor ("ebx","edi"); + &shr ("edx",28-7); # hi>>28 + &xor ("eax","ecx"); + &shl ("esi",30-25); # lo<<30 + &xor ("ebx","edx"); + &shl ("edi",30-25); # hi<<30 + &xor ("eax","esi"); + &xor ("ebx","edi"); # Sigma0(a) + + &mov ("ecx",$Alo); + &mov ("edx",$Ahi); + &mov ("esi",$Blo); + &mov ("edi",$Bhi); + &add ("eax",$Tlo); + &adc ("ebx",$Thi); # T1 = Sigma0(a)+T1 + &or ("ecx","esi"); + &or ("edx","edi"); + &and ("ecx",$Clo); + &and ("edx",$Chi); + &and ("esi",$Alo); + &and ("edi",$Ahi); + &or ("ecx","esi"); + &or ("edx","edi"); # Maj(a,b,c) = ((a|b)&c)|(a&b) + + &add ("eax","ecx"); + &adc ("ebx","edx"); # T1 += Maj(a,b,c) + &mov ($Tlo,"eax"); + &mov ($Thi,"ebx"); + + &mov (&LB("edx"),&BP(0,$K512)); # pre-fetch LSB of *K + &sub ("esp",8); + &lea ($K512,&DWP(8,$K512)); # K++ +} + + +&function_begin("sha512_block_data_order"); + &mov ("esi",wparam(0)); # ctx + &mov ("edi",wparam(1)); # inp + &mov ("eax",wparam(2)); # num + &mov ("ebx","esp"); # saved sp + + &call (&label("pic_point")); # make it PIC! +&set_label("pic_point"); + &blindpop($K512); + &lea ($K512,&DWP(&label("K512")."-".&label("pic_point"),$K512)); + + &sub ("esp",16); + &and ("esp",-64); + + &shl ("eax",7); + &add ("eax","edi"); + &mov (&DWP(0,"esp"),"esi"); # ctx + &mov (&DWP(4,"esp"),"edi"); # inp + &mov (&DWP(8,"esp"),"eax"); # inp+num*128 + &mov (&DWP(12,"esp"),"ebx"); # saved sp + +if ($sse2) { + &picmeup("edx","OPENSSL_ia32cap_P",$K512,&label("K512")); + &mov ("ecx",&DWP(0,"edx")); + &test ("ecx",1<<26); + &jz (&label("loop_x86")); + + &mov ("edx",&DWP(4,"edx")); + + # load ctx->h[0-7] + &movq ($A,&QWP(0,"esi")); + &and ("ecx",1<<24); # XMM registers availability + &movq ("mm1",&QWP(8,"esi")); + &and ("edx",1<<9); # SSSE3 bit + &movq ($BxC,&QWP(16,"esi")); + &or ("ecx","edx"); + &movq ("mm3",&QWP(24,"esi")); + &movq ($E,&QWP(32,"esi")); + &movq ("mm5",&QWP(40,"esi")); + &movq ("mm6",&QWP(48,"esi")); + &movq ("mm7",&QWP(56,"esi")); + &cmp ("ecx",1<<24|1<<9); + &je (&label("SSSE3")); + &sub ("esp",8*10); + &jmp (&label("loop_sse2")); + +&set_label("loop_sse2",16); + #&movq ($Asse2,$A); + &movq ($Bsse2,"mm1"); + &movq ($Csse2,$BxC); + &movq ($Dsse2,"mm3"); + #&movq ($Esse2,$E); + &movq ($Fsse2,"mm5"); + &movq ($Gsse2,"mm6"); + &pxor ($BxC,"mm1"); # magic + &movq ($Hsse2,"mm7"); + &movq ("mm3",$A); # magic + + &mov ("eax",&DWP(0,"edi")); + &mov ("ebx",&DWP(4,"edi")); + &add ("edi",8); + &mov ("edx",15); # counter + &bswap ("eax"); + &bswap ("ebx"); + &jmp (&label("00_14_sse2")); + +&set_label("00_14_sse2",16); + &movd ("mm1","eax"); + &mov ("eax",&DWP(0,"edi")); + &movd ("mm7","ebx"); + &mov ("ebx",&DWP(4,"edi")); + &add ("edi",8); + &bswap ("eax"); + &bswap ("ebx"); + &punpckldq("mm7","mm1"); + + &BODY_00_15_sse2(); + + &dec ("edx"); + &jnz (&label("00_14_sse2")); + + &movd ("mm1","eax"); + &movd ("mm7","ebx"); + &punpckldq("mm7","mm1"); + + &BODY_00_15_sse2(1); + + &pxor ($A,$A); # A is in %mm3 + &mov ("edx",32); # counter + &jmp (&label("16_79_sse2")); + +&set_label("16_79_sse2",16); + for ($j=0;$j<2;$j++) { # 2x unroll + #&movq ("mm7",&QWP(8*(9+16-1),"esp")); # prefetched in BODY_00_15 + &movq ("mm5",&QWP(8*(9+16-14),"esp")); + &movq ("mm1","mm7"); + &psrlq ("mm7",1); + &movq ("mm6","mm5"); + &psrlq ("mm5",6); + &psllq ("mm1",56); + &paddq ($A,"mm3"); # from BODY_00_15 + &movq ("mm3","mm7"); + &psrlq ("mm7",7-1); + &pxor ("mm3","mm1"); + &psllq ("mm1",63-56); + &pxor ("mm3","mm7"); + &psrlq ("mm7",8-7); + &pxor ("mm3","mm1"); + &movq ("mm1","mm5"); + &psrlq ("mm5",19-6); + &pxor ("mm7","mm3"); # sigma0 + + &psllq ("mm6",3); + &pxor ("mm1","mm5"); + &paddq ("mm7",&QWP(8*(9+16),"esp")); + &pxor ("mm1","mm6"); + &psrlq ("mm5",61-19); + &paddq ("mm7",&QWP(8*(9+16-9),"esp")); + &pxor ("mm1","mm5"); + &psllq ("mm6",45-3); + &movq ("mm5",$Fsse2); # load f + &pxor ("mm1","mm6"); # sigma1 + &movq ("mm6",$Gsse2); # load g + + &paddq ("mm7","mm1"); # X[i] + #&movq (&QWP(8*9,"esp"),"mm7"); # moved to BODY_00_15 + + &BODY_00_15_sse2(2); + } + &dec ("edx"); + &jnz (&label("16_79_sse2")); + + #&movq ($A,$Asse2); + &paddq ($A,"mm3"); # from BODY_00_15 + &movq ("mm1",$Bsse2); + #&movq ($BxC,$Csse2); + &movq ("mm3",$Dsse2); + #&movq ($E,$Esse2); + &movq ("mm5",$Fsse2); + &movq ("mm6",$Gsse2); + &movq ("mm7",$Hsse2); + + &pxor ($BxC,"mm1"); # de-magic + &paddq ($A,&QWP(0,"esi")); + &paddq ("mm1",&QWP(8,"esi")); + &paddq ($BxC,&QWP(16,"esi")); + &paddq ("mm3",&QWP(24,"esi")); + &paddq ($E,&QWP(32,"esi")); + &paddq ("mm5",&QWP(40,"esi")); + &paddq ("mm6",&QWP(48,"esi")); + &paddq ("mm7",&QWP(56,"esi")); + + &mov ("eax",8*80); + &movq (&QWP(0,"esi"),$A); + &movq (&QWP(8,"esi"),"mm1"); + &movq (&QWP(16,"esi"),$BxC); + &movq (&QWP(24,"esi"),"mm3"); + &movq (&QWP(32,"esi"),$E); + &movq (&QWP(40,"esi"),"mm5"); + &movq (&QWP(48,"esi"),"mm6"); + &movq (&QWP(56,"esi"),"mm7"); + + &lea ("esp",&DWP(0,"esp","eax")); # destroy frame + &sub ($K512,"eax"); # rewind K + + &cmp ("edi",&DWP(8*10+8,"esp")); # are we done yet? + &jb (&label("loop_sse2")); + + &mov ("esp",&DWP(8*10+12,"esp")); # restore sp + &emms (); +&function_end_A(); + +&set_label("SSSE3",32); +{ my ($cnt,$frame)=("ecx","edx"); + my @X=map("xmm$_",(0..7)); + my $j; + my $i=0; + + &lea ($frame,&DWP(-64,"esp")); + &sub ("esp",256); + + # fixed stack frame layout + # + # +0 A B C D E F G H # backing store + # +64 X[0]+K[i] .. X[15]+K[i] # XMM->MM xfer area + # +192 # XMM off-load ring buffer + # +256 # saved parameters + + &movdqa (@X[1],&QWP(80*8,$K512)); # byte swap mask + &movdqu (@X[0],&QWP(0,"edi")); + &pshufb (@X[0],@X[1]); + for ($j=0;$j<8;$j++) { + &movdqa (&QWP(16*(($j-1)%4),$frame),@X[3]) if ($j>4); # off-load + &movdqa (@X[3],&QWP(16*($j%8),$K512)); + &movdqa (@X[2],@X[1]) if ($j<7); # perpetuate byte swap mask + &movdqu (@X[1],&QWP(16*($j+1),"edi")) if ($j<7); # next input + &movdqa (@X[1],&QWP(16*(($j+1)%4),$frame)) if ($j==7);# restore @X[0] + &paddq (@X[3],@X[0]); + &pshufb (@X[1],@X[2]) if ($j<7); + &movdqa (&QWP(16*($j%8)-128,$frame),@X[3]); # xfer X[i]+K[i] + + push(@X,shift(@X)); # rotate(@X) + } + #&jmp (&label("loop_ssse3")); + &nop (); + +&set_label("loop_ssse3",32); + &movdqa (@X[2],&QWP(16*(($j+1)%4),$frame)); # pre-restore @X[1] + &movdqa (&QWP(16*(($j-1)%4),$frame),@X[3]); # off-load @X[3] + &lea ($K512,&DWP(16*8,$K512)); + + #&movq ($Asse2,$A); # off-load A-H + &movq ($Bsse2,"mm1"); + &mov ("ebx","edi"); + &movq ($Csse2,$BxC); + &lea ("edi",&DWP(128,"edi")); # advance input + &movq ($Dsse2,"mm3"); + &cmp ("edi","eax"); + #&movq ($Esse2,$E); + &movq ($Fsse2,"mm5"); + &cmovb ("ebx","edi"); + &movq ($Gsse2,"mm6"); + &mov ("ecx",4); # loop counter + &pxor ($BxC,"mm1"); # magic + &movq ($Hsse2,"mm7"); + &pxor ("mm3","mm3"); # magic + + &jmp (&label("00_47_ssse3")); + +sub BODY_00_15_ssse3 { # "phase-less" copy of BODY_00_15_sse2 + ( + '&movq ("mm1",$E)', # %mm1 is sliding right + '&movq ("mm7",&QWP(((-8*$i)%128)-128,$frame))',# X[i]+K[i] + '&pxor ("mm5","mm6")', # f^=g + '&psrlq ("mm1",14)', + '&movq (&QWP(8*($i+4)%64,"esp"),$E)', # modulo-scheduled save e + '&pand ("mm5",$E)', # f&=e + '&psllq ($E,23)', # $E is sliding left + '&paddq ($A,"mm3")', # [h+=Maj(a,b,c)] + '&movq ("mm3","mm1")', # %mm3 is T1 + '&psrlq("mm1",4)', + '&pxor ("mm5","mm6")', # Ch(e,f,g) + '&pxor ("mm3",$E)', + '&psllq($E,23)', + '&pxor ("mm3","mm1")', + '&movq (&QWP(8*$i%64,"esp"),$A)', # modulo-scheduled save a + '&paddq("mm7","mm5")', # X[i]+=Ch(e,f,g) + '&pxor ("mm3",$E)', + '&psrlq("mm1",23)', + '&paddq("mm7",&QWP(8*($i+7)%64,"esp"))', # X[i]+=h + '&pxor ("mm3","mm1")', + '&psllq($E,4)', + '&pxor ("mm3",$E)', # T1=Sigma1_512(e) + + '&movq ($E,&QWP(8*($i+3)%64,"esp"))', # e = load d, e in next round + '&paddq ("mm3","mm7")', # T1+=X[i] + '&movq ("mm5",$A)', # %mm5 is sliding right + '&psrlq("mm5",28)', + '&paddq ($E,"mm3")', # d += T1 + '&movq ("mm6",$A)', # %mm6 is sliding left + '&movq ("mm7","mm5")', + '&psllq("mm6",25)', + '&movq ("mm1",&QWP(8*($i+1)%64,"esp"))', # load b + '&psrlq("mm5",6)', + '&pxor ("mm7","mm6")', + '&psllq("mm6",5)', + '&pxor ("mm7","mm5")', + '&pxor ($A,"mm1")', # a^b, b^c in next round + '&psrlq("mm5",5)', + '&pxor ("mm7","mm6")', + '&pand ($BxC,$A)', # (b^c)&(a^b) + '&psllq("mm6",6)', + '&pxor ("mm7","mm5")', + '&pxor ($BxC,"mm1")', # [h=]Maj(a,b,c) + '&pxor ("mm6","mm7")', # Sigma0_512(a) + '&movq ("mm5",&QWP(8*($i+5-1)%64,"esp"))', # pre-load f + '&paddq ($BxC,"mm6")', # h+=Sigma0(a) + '&movq ("mm6",&QWP(8*($i+6-1)%64,"esp"))', # pre-load g + + '($A,$BxC) = ($BxC,$A); $i--;' + ); +} + +&set_label("00_47_ssse3",32); + + for(;$j<16;$j++) { + my ($t0,$t2,$t1)=@X[2..4]; + my @insns = (&BODY_00_15_ssse3(),&BODY_00_15_ssse3()); + + &movdqa ($t2,@X[5]); + &movdqa (@X[1],$t0); # restore @X[1] + &palignr ($t0,@X[0],8); # X[1..2] + &movdqa (&QWP(16*($j%4),$frame),@X[4]); # off-load @X[4] + &palignr ($t2,@X[4],8); # X[9..10] + + &movdqa ($t1,$t0); + &psrlq ($t0,7); + &paddq (@X[0],$t2); # X[0..1] += X[9..10] + &movdqa ($t2,$t1); + &psrlq ($t1,1); + &psllq ($t2,64-8); + &pxor ($t0,$t1); + &psrlq ($t1,8-1); + &pxor ($t0,$t2); + &psllq ($t2,8-1); + &pxor ($t0,$t1); + &movdqa ($t1,@X[7]); + &pxor ($t0,$t2); # sigma0(X[1..2]) + &movdqa ($t2,@X[7]); + &psrlq ($t1,6); + &paddq (@X[0],$t0); # X[0..1] += sigma0(X[1..2]) + + &movdqa ($t0,@X[7]); + &psrlq ($t2,19); + &psllq ($t0,64-61); + &pxor ($t1,$t2); + &psrlq ($t2,61-19); + &pxor ($t1,$t0); + &psllq ($t0,61-19); + &pxor ($t1,$t2); + &movdqa ($t2,&QWP(16*(($j+2)%4),$frame));# pre-restore @X[1] + &pxor ($t1,$t0); # sigma0(X[1..2]) + &movdqa ($t0,&QWP(16*($j%8),$K512)); + eval(shift(@insns)); + &paddq (@X[0],$t1); # X[0..1] += sigma0(X[14..15]) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &paddq ($t0,@X[0]); + foreach(@insns) { eval; } + &movdqa (&QWP(16*($j%8)-128,$frame),$t0);# xfer X[i]+K[i] + + push(@X,shift(@X)); # rotate(@X) + } + &lea ($K512,&DWP(16*8,$K512)); + &dec ("ecx"); + &jnz (&label("00_47_ssse3")); + + &movdqa (@X[1],&QWP(0,$K512)); # byte swap mask + &lea ($K512,&DWP(-80*8,$K512)); # rewind + &movdqu (@X[0],&QWP(0,"ebx")); + &pshufb (@X[0],@X[1]); + + for ($j=0;$j<8;$j++) { # load next or same block + my @insns = (&BODY_00_15_ssse3(),&BODY_00_15_ssse3()); + + &movdqa (&QWP(16*(($j-1)%4),$frame),@X[3]) if ($j>4); # off-load + &movdqa (@X[3],&QWP(16*($j%8),$K512)); + &movdqa (@X[2],@X[1]) if ($j<7); # perpetuate byte swap mask + &movdqu (@X[1],&QWP(16*($j+1),"ebx")) if ($j<7); # next input + &movdqa (@X[1],&QWP(16*(($j+1)%4),$frame)) if ($j==7);# restore @X[0] + &paddq (@X[3],@X[0]); + &pshufb (@X[1],@X[2]) if ($j<7); + foreach(@insns) { eval; } + &movdqa (&QWP(16*($j%8)-128,$frame),@X[3]);# xfer X[i]+K[i] + + push(@X,shift(@X)); # rotate(@X) + } + + #&movq ($A,$Asse2); # load A-H + &movq ("mm1",$Bsse2); + &paddq ($A,"mm3"); # from BODY_00_15 + #&movq ($BxC,$Csse2); + &movq ("mm3",$Dsse2); + #&movq ($E,$Esse2); + #&movq ("mm5",$Fsse2); + #&movq ("mm6",$Gsse2); + &movq ("mm7",$Hsse2); + + &pxor ($BxC,"mm1"); # de-magic + &paddq ($A,&QWP(0,"esi")); + &paddq ("mm1",&QWP(8,"esi")); + &paddq ($BxC,&QWP(16,"esi")); + &paddq ("mm3",&QWP(24,"esi")); + &paddq ($E,&QWP(32,"esi")); + &paddq ("mm5",&QWP(40,"esi")); + &paddq ("mm6",&QWP(48,"esi")); + &paddq ("mm7",&QWP(56,"esi")); + + &movq (&QWP(0,"esi"),$A); + &movq (&QWP(8,"esi"),"mm1"); + &movq (&QWP(16,"esi"),$BxC); + &movq (&QWP(24,"esi"),"mm3"); + &movq (&QWP(32,"esi"),$E); + &movq (&QWP(40,"esi"),"mm5"); + &movq (&QWP(48,"esi"),"mm6"); + &movq (&QWP(56,"esi"),"mm7"); + + &cmp ("edi","eax") # are we done yet? + &jb (&label("loop_ssse3")); + + &mov ("esp",&DWP(64+12,$frame)); # restore sp + &emms (); +} +&function_end_A(); +} +&set_label("loop_x86",16); + # copy input block to stack reversing byte and qword order + for ($i=0;$i<8;$i++) { + &mov ("eax",&DWP($i*16+0,"edi")); + &mov ("ebx",&DWP($i*16+4,"edi")); + &mov ("ecx",&DWP($i*16+8,"edi")); + &mov ("edx",&DWP($i*16+12,"edi")); + &bswap ("eax"); + &bswap ("ebx"); + &bswap ("ecx"); + &bswap ("edx"); + &push ("eax"); + &push ("ebx"); + &push ("ecx"); + &push ("edx"); + } + &add ("edi",128); + &sub ("esp",9*8); # place for T,A,B,C,D,E,F,G,H + &mov (&DWP(8*(9+16)+4,"esp"),"edi"); + + # copy ctx->h[0-7] to A,B,C,D,E,F,G,H on stack + &lea ("edi",&DWP(8,"esp")); + &mov ("ecx",16); + &data_word(0xA5F3F689); # rep movsd + +&set_label("00_15_x86",16); + &BODY_00_15_x86(); + + &cmp (&LB("edx"),0x94); + &jne (&label("00_15_x86")); + +&set_label("16_79_x86",16); + #define sigma0(x) (ROTR((x),1) ^ ROTR((x),8) ^ ((x)>>7)) + # LO lo>>1^hi<<31 ^ lo>>8^hi<<24 ^ lo>>7^hi<<25 + # HI hi>>1^lo<<31 ^ hi>>8^lo<<24 ^ hi>>7 + &mov ("ecx",&DWP(8*(9+15+16-1)+0,"esp")); + &mov ("edx",&DWP(8*(9+15+16-1)+4,"esp")); + &mov ("esi","ecx"); + + &shr ("ecx",1); # lo>>1 + &mov ("edi","edx"); + &shr ("edx",1); # hi>>1 + &mov ("eax","ecx"); + &shl ("esi",24); # lo<<24 + &mov ("ebx","edx"); + &shl ("edi",24); # hi<<24 + &xor ("ebx","esi"); + + &shr ("ecx",7-1); # lo>>7 + &xor ("eax","edi"); + &shr ("edx",7-1); # hi>>7 + &xor ("eax","ecx"); + &shl ("esi",31-24); # lo<<31 + &xor ("ebx","edx"); + &shl ("edi",25-24); # hi<<25 + &xor ("ebx","esi"); + + &shr ("ecx",8-7); # lo>>8 + &xor ("eax","edi"); + &shr ("edx",8-7); # hi>>8 + &xor ("eax","ecx"); + &shl ("edi",31-25); # hi<<31 + &xor ("ebx","edx"); + &xor ("eax","edi"); # T1 = sigma0(X[-15]) + + &mov (&DWP(0,"esp"),"eax"); + &mov (&DWP(4,"esp"),"ebx"); # put T1 away + + #define sigma1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6)) + # LO lo>>19^hi<<13 ^ hi>>29^lo<<3 ^ lo>>6^hi<<26 + # HI hi>>19^lo<<13 ^ lo>>29^hi<<3 ^ hi>>6 + &mov ("ecx",&DWP(8*(9+15+16-14)+0,"esp")); + &mov ("edx",&DWP(8*(9+15+16-14)+4,"esp")); + &mov ("esi","ecx"); + + &shr ("ecx",6); # lo>>6 + &mov ("edi","edx"); + &shr ("edx",6); # hi>>6 + &mov ("eax","ecx"); + &shl ("esi",3); # lo<<3 + &mov ("ebx","edx"); + &shl ("edi",3); # hi<<3 + &xor ("eax","esi"); + + &shr ("ecx",19-6); # lo>>19 + &xor ("ebx","edi"); + &shr ("edx",19-6); # hi>>19 + &xor ("eax","ecx"); + &shl ("esi",13-3); # lo<<13 + &xor ("ebx","edx"); + &shl ("edi",13-3); # hi<<13 + &xor ("ebx","esi"); + + &shr ("ecx",29-19); # lo>>29 + &xor ("eax","edi"); + &shr ("edx",29-19); # hi>>29 + &xor ("ebx","ecx"); + &shl ("edi",26-13); # hi<<26 + &xor ("eax","edx"); + &xor ("eax","edi"); # sigma1(X[-2]) + + &mov ("ecx",&DWP(8*(9+15+16)+0,"esp")); + &mov ("edx",&DWP(8*(9+15+16)+4,"esp")); + &add ("eax",&DWP(0,"esp")); + &adc ("ebx",&DWP(4,"esp")); # T1 = sigma1(X[-2])+T1 + &mov ("esi",&DWP(8*(9+15+16-9)+0,"esp")); + &mov ("edi",&DWP(8*(9+15+16-9)+4,"esp")); + &add ("eax","ecx"); + &adc ("ebx","edx"); # T1 += X[-16] + &add ("eax","esi"); + &adc ("ebx","edi"); # T1 += X[-7] + &mov (&DWP(8*(9+15)+0,"esp"),"eax"); + &mov (&DWP(8*(9+15)+4,"esp"),"ebx"); # save X[0] + + &BODY_00_15_x86(); + + &cmp (&LB("edx"),0x17); + &jne (&label("16_79_x86")); + + &mov ("esi",&DWP(8*(9+16+80)+0,"esp"));# ctx + &mov ("edi",&DWP(8*(9+16+80)+4,"esp"));# inp + for($i=0;$i<4;$i++) { + &mov ("eax",&DWP($i*16+0,"esi")); + &mov ("ebx",&DWP($i*16+4,"esi")); + &mov ("ecx",&DWP($i*16+8,"esi")); + &mov ("edx",&DWP($i*16+12,"esi")); + &add ("eax",&DWP(8+($i*16)+0,"esp")); + &adc ("ebx",&DWP(8+($i*16)+4,"esp")); + &mov (&DWP($i*16+0,"esi"),"eax"); + &mov (&DWP($i*16+4,"esi"),"ebx"); + &add ("ecx",&DWP(8+($i*16)+8,"esp")); + &adc ("edx",&DWP(8+($i*16)+12,"esp")); + &mov (&DWP($i*16+8,"esi"),"ecx"); + &mov (&DWP($i*16+12,"esi"),"edx"); + } + &add ("esp",8*(9+16+80)); # destroy frame + &sub ($K512,8*80); # rewind K + + &cmp ("edi",&DWP(8,"esp")); # are we done yet? + &jb (&label("loop_x86")); + + &mov ("esp",&DWP(12,"esp")); # restore sp +&function_end_A(); + +&set_label("K512",64); # Yes! I keep it in the code segment! + &data_word(0xd728ae22,0x428a2f98); # u64 + &data_word(0x23ef65cd,0x71374491); # u64 + &data_word(0xec4d3b2f,0xb5c0fbcf); # u64 + &data_word(0x8189dbbc,0xe9b5dba5); # u64 + &data_word(0xf348b538,0x3956c25b); # u64 + &data_word(0xb605d019,0x59f111f1); # u64 + &data_word(0xaf194f9b,0x923f82a4); # u64 + &data_word(0xda6d8118,0xab1c5ed5); # u64 + &data_word(0xa3030242,0xd807aa98); # u64 + &data_word(0x45706fbe,0x12835b01); # u64 + &data_word(0x4ee4b28c,0x243185be); # u64 + &data_word(0xd5ffb4e2,0x550c7dc3); # u64 + &data_word(0xf27b896f,0x72be5d74); # u64 + &data_word(0x3b1696b1,0x80deb1fe); # u64 + &data_word(0x25c71235,0x9bdc06a7); # u64 + &data_word(0xcf692694,0xc19bf174); # u64 + &data_word(0x9ef14ad2,0xe49b69c1); # u64 + &data_word(0x384f25e3,0xefbe4786); # u64 + &data_word(0x8b8cd5b5,0x0fc19dc6); # u64 + &data_word(0x77ac9c65,0x240ca1cc); # u64 + &data_word(0x592b0275,0x2de92c6f); # u64 + &data_word(0x6ea6e483,0x4a7484aa); # u64 + &data_word(0xbd41fbd4,0x5cb0a9dc); # u64 + &data_word(0x831153b5,0x76f988da); # u64 + &data_word(0xee66dfab,0x983e5152); # u64 + &data_word(0x2db43210,0xa831c66d); # u64 + &data_word(0x98fb213f,0xb00327c8); # u64 + &data_word(0xbeef0ee4,0xbf597fc7); # u64 + &data_word(0x3da88fc2,0xc6e00bf3); # u64 + &data_word(0x930aa725,0xd5a79147); # u64 + &data_word(0xe003826f,0x06ca6351); # u64 + &data_word(0x0a0e6e70,0x14292967); # u64 + &data_word(0x46d22ffc,0x27b70a85); # u64 + &data_word(0x5c26c926,0x2e1b2138); # u64 + &data_word(0x5ac42aed,0x4d2c6dfc); # u64 + &data_word(0x9d95b3df,0x53380d13); # u64 + &data_word(0x8baf63de,0x650a7354); # u64 + &data_word(0x3c77b2a8,0x766a0abb); # u64 + &data_word(0x47edaee6,0x81c2c92e); # u64 + &data_word(0x1482353b,0x92722c85); # u64 + &data_word(0x4cf10364,0xa2bfe8a1); # u64 + &data_word(0xbc423001,0xa81a664b); # u64 + &data_word(0xd0f89791,0xc24b8b70); # u64 + &data_word(0x0654be30,0xc76c51a3); # u64 + &data_word(0xd6ef5218,0xd192e819); # u64 + &data_word(0x5565a910,0xd6990624); # u64 + &data_word(0x5771202a,0xf40e3585); # u64 + &data_word(0x32bbd1b8,0x106aa070); # u64 + &data_word(0xb8d2d0c8,0x19a4c116); # u64 + &data_word(0x5141ab53,0x1e376c08); # u64 + &data_word(0xdf8eeb99,0x2748774c); # u64 + &data_word(0xe19b48a8,0x34b0bcb5); # u64 + &data_word(0xc5c95a63,0x391c0cb3); # u64 + &data_word(0xe3418acb,0x4ed8aa4a); # u64 + &data_word(0x7763e373,0x5b9cca4f); # u64 + &data_word(0xd6b2b8a3,0x682e6ff3); # u64 + &data_word(0x5defb2fc,0x748f82ee); # u64 + &data_word(0x43172f60,0x78a5636f); # u64 + &data_word(0xa1f0ab72,0x84c87814); # u64 + &data_word(0x1a6439ec,0x8cc70208); # u64 + &data_word(0x23631e28,0x90befffa); # u64 + &data_word(0xde82bde9,0xa4506ceb); # u64 + &data_word(0xb2c67915,0xbef9a3f7); # u64 + &data_word(0xe372532b,0xc67178f2); # u64 + &data_word(0xea26619c,0xca273ece); # u64 + &data_word(0x21c0c207,0xd186b8c7); # u64 + &data_word(0xcde0eb1e,0xeada7dd6); # u64 + &data_word(0xee6ed178,0xf57d4f7f); # u64 + &data_word(0x72176fba,0x06f067aa); # u64 + &data_word(0xa2c898a6,0x0a637dc5); # u64 + &data_word(0xbef90dae,0x113f9804); # u64 + &data_word(0x131c471b,0x1b710b35); # u64 + &data_word(0x23047d84,0x28db77f5); # u64 + &data_word(0x40c72493,0x32caab7b); # u64 + &data_word(0x15c9bebc,0x3c9ebe0a); # u64 + &data_word(0x9c100d4c,0x431d67c4); # u64 + &data_word(0xcb3e42b6,0x4cc5d4be); # u64 + &data_word(0xfc657e2a,0x597f299c); # u64 + &data_word(0x3ad6faec,0x5fcb6fab); # u64 + &data_word(0x4a475817,0x6c44198c); # u64 + + &data_word(0x04050607,0x00010203); # byte swap + &data_word(0x0c0d0e0f,0x08090a0b); # mask +&function_end_B("sha512_block_data_order"); +&asciz("SHA512 block transform for x86, CRYPTOGAMS by "); + +&asm_finish(); + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-armv4.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-armv4.pl new file mode 100644 index 000000000..0b4c5674d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-armv4.pl @@ -0,0 +1,668 @@ +#! /usr/bin/env perl +# Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# +# Permission to use under GPL terms is granted. +# ==================================================================== + +# SHA512 block procedure for ARMv4. September 2007. + +# This code is ~4.5 (four and a half) times faster than code generated +# by gcc 3.4 and it spends ~72 clock cycles per byte [on single-issue +# Xscale PXA250 core]. +# +# July 2010. +# +# Rescheduling for dual-issue pipeline resulted in 6% improvement on +# Cortex A8 core and ~40 cycles per processed byte. + +# February 2011. +# +# Profiler-assisted and platform-specific optimization resulted in 7% +# improvement on Coxtex A8 core and ~38 cycles per byte. + +# March 2011. +# +# Add NEON implementation. On Cortex A8 it was measured to process +# one byte in 23.3 cycles or ~60% faster than integer-only code. + +# August 2012. +# +# Improve NEON performance by 12% on Snapdragon S4. In absolute +# terms it's 22.6 cycles per byte, which is disappointing result. +# Technical writers asserted that 3-way S4 pipeline can sustain +# multiple NEON instructions per cycle, but dual NEON issue could +# not be observed, see http://www.openssl.org/~appro/Snapdragon-S4.html +# for further details. On side note Cortex-A15 processes one byte in +# 16 cycles. + +# Byte order [in]dependence. ========================================= +# +# Originally caller was expected to maintain specific *dword* order in +# h[0-7], namely with most significant dword at *lower* address, which +# was reflected in below two parameters as 0 and 4. Now caller is +# expected to maintain native byte order for whole 64-bit values. +$hi="HI"; +$lo="LO"; +# ==================================================================== + +$flavour = shift; +if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } +else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} } + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open STDOUT,"| \"$^X\" $xlate $flavour $output"; +} else { + open STDOUT,">$output"; +} + +$ctx="r0"; # parameter block +$inp="r1"; +$len="r2"; + +$Tlo="r3"; +$Thi="r4"; +$Alo="r5"; +$Ahi="r6"; +$Elo="r7"; +$Ehi="r8"; +$t0="r9"; +$t1="r10"; +$t2="r11"; +$t3="r12"; +############ r13 is stack pointer +$Ktbl="r14"; +############ r15 is program counter + +$Aoff=8*0; +$Boff=8*1; +$Coff=8*2; +$Doff=8*3; +$Eoff=8*4; +$Foff=8*5; +$Goff=8*6; +$Hoff=8*7; +$Xoff=8*8; + +sub BODY_00_15() { +my $magic = shift; +$code.=<<___; + @ Sigma1(x) (ROTR((x),14) ^ ROTR((x),18) ^ ROTR((x),41)) + @ LO lo>>14^hi<<18 ^ lo>>18^hi<<14 ^ hi>>9^lo<<23 + @ HI hi>>14^lo<<18 ^ hi>>18^lo<<14 ^ lo>>9^hi<<23 + mov $t0,$Elo,lsr#14 + str $Tlo,[sp,#$Xoff+0] + mov $t1,$Ehi,lsr#14 + str $Thi,[sp,#$Xoff+4] + eor $t0,$t0,$Ehi,lsl#18 + ldr $t2,[sp,#$Hoff+0] @ h.lo + eor $t1,$t1,$Elo,lsl#18 + ldr $t3,[sp,#$Hoff+4] @ h.hi + eor $t0,$t0,$Elo,lsr#18 + eor $t1,$t1,$Ehi,lsr#18 + eor $t0,$t0,$Ehi,lsl#14 + eor $t1,$t1,$Elo,lsl#14 + eor $t0,$t0,$Ehi,lsr#9 + eor $t1,$t1,$Elo,lsr#9 + eor $t0,$t0,$Elo,lsl#23 + eor $t1,$t1,$Ehi,lsl#23 @ Sigma1(e) + adds $Tlo,$Tlo,$t0 + ldr $t0,[sp,#$Foff+0] @ f.lo + adc $Thi,$Thi,$t1 @ T += Sigma1(e) + ldr $t1,[sp,#$Foff+4] @ f.hi + adds $Tlo,$Tlo,$t2 + ldr $t2,[sp,#$Goff+0] @ g.lo + adc $Thi,$Thi,$t3 @ T += h + ldr $t3,[sp,#$Goff+4] @ g.hi + + eor $t0,$t0,$t2 + str $Elo,[sp,#$Eoff+0] + eor $t1,$t1,$t3 + str $Ehi,[sp,#$Eoff+4] + and $t0,$t0,$Elo + str $Alo,[sp,#$Aoff+0] + and $t1,$t1,$Ehi + str $Ahi,[sp,#$Aoff+4] + eor $t0,$t0,$t2 + ldr $t2,[$Ktbl,#$lo] @ K[i].lo + eor $t1,$t1,$t3 @ Ch(e,f,g) + ldr $t3,[$Ktbl,#$hi] @ K[i].hi + + adds $Tlo,$Tlo,$t0 + ldr $Elo,[sp,#$Doff+0] @ d.lo + adc $Thi,$Thi,$t1 @ T += Ch(e,f,g) + ldr $Ehi,[sp,#$Doff+4] @ d.hi + adds $Tlo,$Tlo,$t2 + and $t0,$t2,#0xff + adc $Thi,$Thi,$t3 @ T += K[i] + adds $Elo,$Elo,$Tlo + ldr $t2,[sp,#$Boff+0] @ b.lo + adc $Ehi,$Ehi,$Thi @ d += T + teq $t0,#$magic + + ldr $t3,[sp,#$Coff+0] @ c.lo +#ifdef __thumb2__ + it eq @ Thumb2 thing, sanity check in ARM +#endif + orreq $Ktbl,$Ktbl,#1 + @ Sigma0(x) (ROTR((x),28) ^ ROTR((x),34) ^ ROTR((x),39)) + @ LO lo>>28^hi<<4 ^ hi>>2^lo<<30 ^ hi>>7^lo<<25 + @ HI hi>>28^lo<<4 ^ lo>>2^hi<<30 ^ lo>>7^hi<<25 + mov $t0,$Alo,lsr#28 + mov $t1,$Ahi,lsr#28 + eor $t0,$t0,$Ahi,lsl#4 + eor $t1,$t1,$Alo,lsl#4 + eor $t0,$t0,$Ahi,lsr#2 + eor $t1,$t1,$Alo,lsr#2 + eor $t0,$t0,$Alo,lsl#30 + eor $t1,$t1,$Ahi,lsl#30 + eor $t0,$t0,$Ahi,lsr#7 + eor $t1,$t1,$Alo,lsr#7 + eor $t0,$t0,$Alo,lsl#25 + eor $t1,$t1,$Ahi,lsl#25 @ Sigma0(a) + adds $Tlo,$Tlo,$t0 + and $t0,$Alo,$t2 + adc $Thi,$Thi,$t1 @ T += Sigma0(a) + + ldr $t1,[sp,#$Boff+4] @ b.hi + orr $Alo,$Alo,$t2 + ldr $t2,[sp,#$Coff+4] @ c.hi + and $Alo,$Alo,$t3 + and $t3,$Ahi,$t1 + orr $Ahi,$Ahi,$t1 + orr $Alo,$Alo,$t0 @ Maj(a,b,c).lo + and $Ahi,$Ahi,$t2 + adds $Alo,$Alo,$Tlo + orr $Ahi,$Ahi,$t3 @ Maj(a,b,c).hi + sub sp,sp,#8 + adc $Ahi,$Ahi,$Thi @ h += T + tst $Ktbl,#1 + add $Ktbl,$Ktbl,#8 +___ +} +$code=<<___; +#ifndef __KERNEL__ +# include "arm_arch.h" +# define VFP_ABI_PUSH vstmdb sp!,{d8-d15} +# define VFP_ABI_POP vldmia sp!,{d8-d15} +#else +# define __ARM_ARCH__ __LINUX_ARM_ARCH__ +# define __ARM_MAX_ARCH__ 7 +# define VFP_ABI_PUSH +# define VFP_ABI_POP +#endif + +#ifdef __ARMEL__ +# define LO 0 +# define HI 4 +# define WORD64(hi0,lo0,hi1,lo1) .word lo0,hi0, lo1,hi1 +#else +# define HI 0 +# define LO 4 +# define WORD64(hi0,lo0,hi1,lo1) .word hi0,lo0, hi1,lo1 +#endif + +.text +#if defined(__thumb2__) +.syntax unified +.thumb +# define adrl adr +#else +.code 32 +#endif + +.type K512,%object +.align 5 +K512: +WORD64(0x428a2f98,0xd728ae22, 0x71374491,0x23ef65cd) +WORD64(0xb5c0fbcf,0xec4d3b2f, 0xe9b5dba5,0x8189dbbc) +WORD64(0x3956c25b,0xf348b538, 0x59f111f1,0xb605d019) +WORD64(0x923f82a4,0xaf194f9b, 0xab1c5ed5,0xda6d8118) +WORD64(0xd807aa98,0xa3030242, 0x12835b01,0x45706fbe) +WORD64(0x243185be,0x4ee4b28c, 0x550c7dc3,0xd5ffb4e2) +WORD64(0x72be5d74,0xf27b896f, 0x80deb1fe,0x3b1696b1) +WORD64(0x9bdc06a7,0x25c71235, 0xc19bf174,0xcf692694) +WORD64(0xe49b69c1,0x9ef14ad2, 0xefbe4786,0x384f25e3) +WORD64(0x0fc19dc6,0x8b8cd5b5, 0x240ca1cc,0x77ac9c65) +WORD64(0x2de92c6f,0x592b0275, 0x4a7484aa,0x6ea6e483) +WORD64(0x5cb0a9dc,0xbd41fbd4, 0x76f988da,0x831153b5) +WORD64(0x983e5152,0xee66dfab, 0xa831c66d,0x2db43210) +WORD64(0xb00327c8,0x98fb213f, 0xbf597fc7,0xbeef0ee4) +WORD64(0xc6e00bf3,0x3da88fc2, 0xd5a79147,0x930aa725) +WORD64(0x06ca6351,0xe003826f, 0x14292967,0x0a0e6e70) +WORD64(0x27b70a85,0x46d22ffc, 0x2e1b2138,0x5c26c926) +WORD64(0x4d2c6dfc,0x5ac42aed, 0x53380d13,0x9d95b3df) +WORD64(0x650a7354,0x8baf63de, 0x766a0abb,0x3c77b2a8) +WORD64(0x81c2c92e,0x47edaee6, 0x92722c85,0x1482353b) +WORD64(0xa2bfe8a1,0x4cf10364, 0xa81a664b,0xbc423001) +WORD64(0xc24b8b70,0xd0f89791, 0xc76c51a3,0x0654be30) +WORD64(0xd192e819,0xd6ef5218, 0xd6990624,0x5565a910) +WORD64(0xf40e3585,0x5771202a, 0x106aa070,0x32bbd1b8) +WORD64(0x19a4c116,0xb8d2d0c8, 0x1e376c08,0x5141ab53) +WORD64(0x2748774c,0xdf8eeb99, 0x34b0bcb5,0xe19b48a8) +WORD64(0x391c0cb3,0xc5c95a63, 0x4ed8aa4a,0xe3418acb) +WORD64(0x5b9cca4f,0x7763e373, 0x682e6ff3,0xd6b2b8a3) +WORD64(0x748f82ee,0x5defb2fc, 0x78a5636f,0x43172f60) +WORD64(0x84c87814,0xa1f0ab72, 0x8cc70208,0x1a6439ec) +WORD64(0x90befffa,0x23631e28, 0xa4506ceb,0xde82bde9) +WORD64(0xbef9a3f7,0xb2c67915, 0xc67178f2,0xe372532b) +WORD64(0xca273ece,0xea26619c, 0xd186b8c7,0x21c0c207) +WORD64(0xeada7dd6,0xcde0eb1e, 0xf57d4f7f,0xee6ed178) +WORD64(0x06f067aa,0x72176fba, 0x0a637dc5,0xa2c898a6) +WORD64(0x113f9804,0xbef90dae, 0x1b710b35,0x131c471b) +WORD64(0x28db77f5,0x23047d84, 0x32caab7b,0x40c72493) +WORD64(0x3c9ebe0a,0x15c9bebc, 0x431d67c4,0x9c100d4c) +WORD64(0x4cc5d4be,0xcb3e42b6, 0x597f299c,0xfc657e2a) +WORD64(0x5fcb6fab,0x3ad6faec, 0x6c44198c,0x4a475817) +.size K512,.-K512 +#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) +.LOPENSSL_armcap: +.word OPENSSL_armcap_P-.Lsha512_block_data_order +.skip 32-4 +#else +.skip 32 +#endif + +.global sha512_block_data_order +.type sha512_block_data_order,%function +sha512_block_data_order: +.Lsha512_block_data_order: +#if __ARM_ARCH__<7 && !defined(__thumb2__) + sub r3,pc,#8 @ sha512_block_data_order +#else + adr r3,.Lsha512_block_data_order +#endif +#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) + ldr r12,.LOPENSSL_armcap + ldr r12,[r3,r12] @ OPENSSL_armcap_P +#ifdef __APPLE__ + ldr r12,[r12] +#endif + tst r12,#ARMV7_NEON + bne .LNEON +#endif + add $len,$inp,$len,lsl#7 @ len to point at the end of inp + stmdb sp!,{r4-r12,lr} + sub $Ktbl,r3,#672 @ K512 + sub sp,sp,#9*8 + + ldr $Elo,[$ctx,#$Eoff+$lo] + ldr $Ehi,[$ctx,#$Eoff+$hi] + ldr $t0, [$ctx,#$Goff+$lo] + ldr $t1, [$ctx,#$Goff+$hi] + ldr $t2, [$ctx,#$Hoff+$lo] + ldr $t3, [$ctx,#$Hoff+$hi] +.Loop: + str $t0, [sp,#$Goff+0] + str $t1, [sp,#$Goff+4] + str $t2, [sp,#$Hoff+0] + str $t3, [sp,#$Hoff+4] + ldr $Alo,[$ctx,#$Aoff+$lo] + ldr $Ahi,[$ctx,#$Aoff+$hi] + ldr $Tlo,[$ctx,#$Boff+$lo] + ldr $Thi,[$ctx,#$Boff+$hi] + ldr $t0, [$ctx,#$Coff+$lo] + ldr $t1, [$ctx,#$Coff+$hi] + ldr $t2, [$ctx,#$Doff+$lo] + ldr $t3, [$ctx,#$Doff+$hi] + str $Tlo,[sp,#$Boff+0] + str $Thi,[sp,#$Boff+4] + str $t0, [sp,#$Coff+0] + str $t1, [sp,#$Coff+4] + str $t2, [sp,#$Doff+0] + str $t3, [sp,#$Doff+4] + ldr $Tlo,[$ctx,#$Foff+$lo] + ldr $Thi,[$ctx,#$Foff+$hi] + str $Tlo,[sp,#$Foff+0] + str $Thi,[sp,#$Foff+4] + +.L00_15: +#if __ARM_ARCH__<7 + ldrb $Tlo,[$inp,#7] + ldrb $t0, [$inp,#6] + ldrb $t1, [$inp,#5] + ldrb $t2, [$inp,#4] + ldrb $Thi,[$inp,#3] + ldrb $t3, [$inp,#2] + orr $Tlo,$Tlo,$t0,lsl#8 + ldrb $t0, [$inp,#1] + orr $Tlo,$Tlo,$t1,lsl#16 + ldrb $t1, [$inp],#8 + orr $Tlo,$Tlo,$t2,lsl#24 + orr $Thi,$Thi,$t3,lsl#8 + orr $Thi,$Thi,$t0,lsl#16 + orr $Thi,$Thi,$t1,lsl#24 +#else + ldr $Tlo,[$inp,#4] + ldr $Thi,[$inp],#8 +#ifdef __ARMEL__ + rev $Tlo,$Tlo + rev $Thi,$Thi +#endif +#endif +___ + &BODY_00_15(0x94); +$code.=<<___; + tst $Ktbl,#1 + beq .L00_15 + ldr $t0,[sp,#`$Xoff+8*(16-1)`+0] + ldr $t1,[sp,#`$Xoff+8*(16-1)`+4] + bic $Ktbl,$Ktbl,#1 +.L16_79: + @ sigma0(x) (ROTR((x),1) ^ ROTR((x),8) ^ ((x)>>7)) + @ LO lo>>1^hi<<31 ^ lo>>8^hi<<24 ^ lo>>7^hi<<25 + @ HI hi>>1^lo<<31 ^ hi>>8^lo<<24 ^ hi>>7 + mov $Tlo,$t0,lsr#1 + ldr $t2,[sp,#`$Xoff+8*(16-14)`+0] + mov $Thi,$t1,lsr#1 + ldr $t3,[sp,#`$Xoff+8*(16-14)`+4] + eor $Tlo,$Tlo,$t1,lsl#31 + eor $Thi,$Thi,$t0,lsl#31 + eor $Tlo,$Tlo,$t0,lsr#8 + eor $Thi,$Thi,$t1,lsr#8 + eor $Tlo,$Tlo,$t1,lsl#24 + eor $Thi,$Thi,$t0,lsl#24 + eor $Tlo,$Tlo,$t0,lsr#7 + eor $Thi,$Thi,$t1,lsr#7 + eor $Tlo,$Tlo,$t1,lsl#25 + + @ sigma1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6)) + @ LO lo>>19^hi<<13 ^ hi>>29^lo<<3 ^ lo>>6^hi<<26 + @ HI hi>>19^lo<<13 ^ lo>>29^hi<<3 ^ hi>>6 + mov $t0,$t2,lsr#19 + mov $t1,$t3,lsr#19 + eor $t0,$t0,$t3,lsl#13 + eor $t1,$t1,$t2,lsl#13 + eor $t0,$t0,$t3,lsr#29 + eor $t1,$t1,$t2,lsr#29 + eor $t0,$t0,$t2,lsl#3 + eor $t1,$t1,$t3,lsl#3 + eor $t0,$t0,$t2,lsr#6 + eor $t1,$t1,$t3,lsr#6 + ldr $t2,[sp,#`$Xoff+8*(16-9)`+0] + eor $t0,$t0,$t3,lsl#26 + + ldr $t3,[sp,#`$Xoff+8*(16-9)`+4] + adds $Tlo,$Tlo,$t0 + ldr $t0,[sp,#`$Xoff+8*16`+0] + adc $Thi,$Thi,$t1 + + ldr $t1,[sp,#`$Xoff+8*16`+4] + adds $Tlo,$Tlo,$t2 + adc $Thi,$Thi,$t3 + adds $Tlo,$Tlo,$t0 + adc $Thi,$Thi,$t1 +___ + &BODY_00_15(0x17); +$code.=<<___; +#ifdef __thumb2__ + ittt eq @ Thumb2 thing, sanity check in ARM +#endif + ldreq $t0,[sp,#`$Xoff+8*(16-1)`+0] + ldreq $t1,[sp,#`$Xoff+8*(16-1)`+4] + beq .L16_79 + bic $Ktbl,$Ktbl,#1 + + ldr $Tlo,[sp,#$Boff+0] + ldr $Thi,[sp,#$Boff+4] + ldr $t0, [$ctx,#$Aoff+$lo] + ldr $t1, [$ctx,#$Aoff+$hi] + ldr $t2, [$ctx,#$Boff+$lo] + ldr $t3, [$ctx,#$Boff+$hi] + adds $t0,$Alo,$t0 + str $t0, [$ctx,#$Aoff+$lo] + adc $t1,$Ahi,$t1 + str $t1, [$ctx,#$Aoff+$hi] + adds $t2,$Tlo,$t2 + str $t2, [$ctx,#$Boff+$lo] + adc $t3,$Thi,$t3 + str $t3, [$ctx,#$Boff+$hi] + + ldr $Alo,[sp,#$Coff+0] + ldr $Ahi,[sp,#$Coff+4] + ldr $Tlo,[sp,#$Doff+0] + ldr $Thi,[sp,#$Doff+4] + ldr $t0, [$ctx,#$Coff+$lo] + ldr $t1, [$ctx,#$Coff+$hi] + ldr $t2, [$ctx,#$Doff+$lo] + ldr $t3, [$ctx,#$Doff+$hi] + adds $t0,$Alo,$t0 + str $t0, [$ctx,#$Coff+$lo] + adc $t1,$Ahi,$t1 + str $t1, [$ctx,#$Coff+$hi] + adds $t2,$Tlo,$t2 + str $t2, [$ctx,#$Doff+$lo] + adc $t3,$Thi,$t3 + str $t3, [$ctx,#$Doff+$hi] + + ldr $Tlo,[sp,#$Foff+0] + ldr $Thi,[sp,#$Foff+4] + ldr $t0, [$ctx,#$Eoff+$lo] + ldr $t1, [$ctx,#$Eoff+$hi] + ldr $t2, [$ctx,#$Foff+$lo] + ldr $t3, [$ctx,#$Foff+$hi] + adds $Elo,$Elo,$t0 + str $Elo,[$ctx,#$Eoff+$lo] + adc $Ehi,$Ehi,$t1 + str $Ehi,[$ctx,#$Eoff+$hi] + adds $t2,$Tlo,$t2 + str $t2, [$ctx,#$Foff+$lo] + adc $t3,$Thi,$t3 + str $t3, [$ctx,#$Foff+$hi] + + ldr $Alo,[sp,#$Goff+0] + ldr $Ahi,[sp,#$Goff+4] + ldr $Tlo,[sp,#$Hoff+0] + ldr $Thi,[sp,#$Hoff+4] + ldr $t0, [$ctx,#$Goff+$lo] + ldr $t1, [$ctx,#$Goff+$hi] + ldr $t2, [$ctx,#$Hoff+$lo] + ldr $t3, [$ctx,#$Hoff+$hi] + adds $t0,$Alo,$t0 + str $t0, [$ctx,#$Goff+$lo] + adc $t1,$Ahi,$t1 + str $t1, [$ctx,#$Goff+$hi] + adds $t2,$Tlo,$t2 + str $t2, [$ctx,#$Hoff+$lo] + adc $t3,$Thi,$t3 + str $t3, [$ctx,#$Hoff+$hi] + + add sp,sp,#640 + sub $Ktbl,$Ktbl,#640 + + teq $inp,$len + bne .Loop + + add sp,sp,#8*9 @ destroy frame +#if __ARM_ARCH__>=5 + ldmia sp!,{r4-r12,pc} +#else + ldmia sp!,{r4-r12,lr} + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + bx lr @ interoperable with Thumb ISA:-) +#endif +.size sha512_block_data_order,.-sha512_block_data_order +___ + +{ +my @Sigma0=(28,34,39); +my @Sigma1=(14,18,41); +my @sigma0=(1, 8, 7); +my @sigma1=(19,61,6); + +my $Ktbl="r3"; +my $cnt="r12"; # volatile register known as ip, intra-procedure-call scratch + +my @X=map("d$_",(0..15)); +my @V=($A,$B,$C,$D,$E,$F,$G,$H)=map("d$_",(16..23)); + +sub NEON_00_15() { +my $i=shift; +my ($a,$b,$c,$d,$e,$f,$g,$h)=@_; +my ($t0,$t1,$t2,$T1,$K,$Ch,$Maj)=map("d$_",(24..31)); # temps + +$code.=<<___ if ($i<16 || $i&1); + vshr.u64 $t0,$e,#@Sigma1[0] @ $i +#if $i<16 + vld1.64 {@X[$i%16]},[$inp]! @ handles unaligned +#endif + vshr.u64 $t1,$e,#@Sigma1[1] +#if $i>0 + vadd.i64 $a,$Maj @ h+=Maj from the past +#endif + vshr.u64 $t2,$e,#@Sigma1[2] +___ +$code.=<<___; + vld1.64 {$K},[$Ktbl,:64]! @ K[i++] + vsli.64 $t0,$e,#`64-@Sigma1[0]` + vsli.64 $t1,$e,#`64-@Sigma1[1]` + vmov $Ch,$e + vsli.64 $t2,$e,#`64-@Sigma1[2]` +#if $i<16 && defined(__ARMEL__) + vrev64.8 @X[$i],@X[$i] +#endif + veor $t1,$t0 + vbsl $Ch,$f,$g @ Ch(e,f,g) + vshr.u64 $t0,$a,#@Sigma0[0] + veor $t2,$t1 @ Sigma1(e) + vadd.i64 $T1,$Ch,$h + vshr.u64 $t1,$a,#@Sigma0[1] + vsli.64 $t0,$a,#`64-@Sigma0[0]` + vadd.i64 $T1,$t2 + vshr.u64 $t2,$a,#@Sigma0[2] + vadd.i64 $K,@X[$i%16] + vsli.64 $t1,$a,#`64-@Sigma0[1]` + veor $Maj,$a,$b + vsli.64 $t2,$a,#`64-@Sigma0[2]` + veor $h,$t0,$t1 + vadd.i64 $T1,$K + vbsl $Maj,$c,$b @ Maj(a,b,c) + veor $h,$t2 @ Sigma0(a) + vadd.i64 $d,$T1 + vadd.i64 $Maj,$T1 + @ vadd.i64 $h,$Maj +___ +} + +sub NEON_16_79() { +my $i=shift; + +if ($i&1) { &NEON_00_15($i,@_); return; } + +# 2x-vectorized, therefore runs every 2nd round +my @X=map("q$_",(0..7)); # view @X as 128-bit vector +my ($t0,$t1,$s0,$s1) = map("q$_",(12..15)); # temps +my ($d0,$d1,$d2) = map("d$_",(24..26)); # temps from NEON_00_15 +my $e=@_[4]; # $e from NEON_00_15 +$i /= 2; +$code.=<<___; + vshr.u64 $t0,@X[($i+7)%8],#@sigma1[0] + vshr.u64 $t1,@X[($i+7)%8],#@sigma1[1] + vadd.i64 @_[0],d30 @ h+=Maj from the past + vshr.u64 $s1,@X[($i+7)%8],#@sigma1[2] + vsli.64 $t0,@X[($i+7)%8],#`64-@sigma1[0]` + vext.8 $s0,@X[$i%8],@X[($i+1)%8],#8 @ X[i+1] + vsli.64 $t1,@X[($i+7)%8],#`64-@sigma1[1]` + veor $s1,$t0 + vshr.u64 $t0,$s0,#@sigma0[0] + veor $s1,$t1 @ sigma1(X[i+14]) + vshr.u64 $t1,$s0,#@sigma0[1] + vadd.i64 @X[$i%8],$s1 + vshr.u64 $s1,$s0,#@sigma0[2] + vsli.64 $t0,$s0,#`64-@sigma0[0]` + vsli.64 $t1,$s0,#`64-@sigma0[1]` + vext.8 $s0,@X[($i+4)%8],@X[($i+5)%8],#8 @ X[i+9] + veor $s1,$t0 + vshr.u64 $d0,$e,#@Sigma1[0] @ from NEON_00_15 + vadd.i64 @X[$i%8],$s0 + vshr.u64 $d1,$e,#@Sigma1[1] @ from NEON_00_15 + veor $s1,$t1 @ sigma0(X[i+1]) + vshr.u64 $d2,$e,#@Sigma1[2] @ from NEON_00_15 + vadd.i64 @X[$i%8],$s1 +___ + &NEON_00_15(2*$i,@_); +} + +$code.=<<___; +#if __ARM_MAX_ARCH__>=7 +.arch armv7-a +.fpu neon + +.global sha512_block_data_order_neon +.type sha512_block_data_order_neon,%function +.align 4 +sha512_block_data_order_neon: +.LNEON: + dmb @ errata #451034 on early Cortex A8 + add $len,$inp,$len,lsl#7 @ len to point at the end of inp + adr $Ktbl,K512 + VFP_ABI_PUSH + vldmia $ctx,{$A-$H} @ load context +.Loop_neon: +___ +for($i=0;$i<16;$i++) { &NEON_00_15($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + mov $cnt,#4 +.L16_79_neon: + subs $cnt,#1 +___ +for(;$i<32;$i++) { &NEON_16_79($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + bne .L16_79_neon + + vadd.i64 $A,d30 @ h+=Maj from the past + vldmia $ctx,{d24-d31} @ load context to temp + vadd.i64 q8,q12 @ vectorized accumulate + vadd.i64 q9,q13 + vadd.i64 q10,q14 + vadd.i64 q11,q15 + vstmia $ctx,{$A-$H} @ save context + teq $inp,$len + sub $Ktbl,#640 @ rewind K512 + bne .Loop_neon + + VFP_ABI_POP + ret @ bx lr +.size sha512_block_data_order_neon,.-sha512_block_data_order_neon +#endif +___ +} +$code.=<<___; +.asciz "SHA512 block transform for ARMv4/NEON, CRYPTOGAMS by " +.align 2 +#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) +.comm OPENSSL_armcap_P,4,4 +#endif +___ + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +$code =~ s/\bbx\s+lr\b/.word\t0xe12fff1e/gm; # make it possible to compile with -march=armv4 +$code =~ s/\bret\b/bx lr/gm; + +open SELF,$0; +while() { + next if (/^#!/); + last if (!s/^#/@/ and !/^$/); + print; +} +close SELF; + +print $code; +close STDOUT; # enforce flush diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-armv8.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-armv8.pl new file mode 100644 index 000000000..01ffe9f98 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-armv8.pl @@ -0,0 +1,905 @@ +#! /usr/bin/env perl +# Copyright 2014-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# +# Permission to use under GPLv2 terms is granted. +# ==================================================================== +# +# SHA256/512 for ARMv8. +# +# Performance in cycles per processed byte and improvement coefficient +# over code generated with "default" compiler: +# +# SHA256-hw SHA256(*) SHA512 +# Apple A7 1.97 10.5 (+33%) 6.73 (-1%(**)) +# Cortex-A53 2.38 15.5 (+115%) 10.0 (+150%(***)) +# Cortex-A57 2.31 11.6 (+86%) 7.51 (+260%(***)) +# Denver 2.01 10.5 (+26%) 6.70 (+8%) +# X-Gene 20.0 (+100%) 12.8 (+300%(***)) +# Mongoose 2.36 13.0 (+50%) 8.36 (+33%) +# Kryo 1.92 17.4 (+30%) 11.2 (+8%) +# +# (*) Software SHA256 results are of lesser relevance, presented +# mostly for informational purposes. +# (**) The result is a trade-off: it's possible to improve it by +# 10% (or by 1 cycle per round), but at the cost of 20% loss +# on Cortex-A53 (or by 4 cycles per round). +# (***) Super-impressive coefficients over gcc-generated code are +# indication of some compiler "pathology", most notably code +# generated with -mgeneral-regs-only is significantly faster +# and the gap is only 40-90%. +# +# October 2016. +# +# Originally it was reckoned that it makes no sense to implement NEON +# version of SHA256 for 64-bit processors. This is because performance +# improvement on most wide-spread Cortex-A5x processors was observed +# to be marginal, same on Cortex-A53 and ~10% on A57. But then it was +# observed that 32-bit NEON SHA256 performs significantly better than +# 64-bit scalar version on *some* of the more recent processors. As +# result 64-bit NEON version of SHA256 was added to provide best +# all-round performance. For example it executes ~30% faster on X-Gene +# and Mongoose. [For reference, NEON version of SHA512 is bound to +# deliver much less improvement, likely *negative* on Cortex-A5x. +# Which is why NEON support is limited to SHA256.] + +$output=pop; +$flavour=pop; + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open OUT,"| \"$^X\" $xlate $flavour $output"; + *STDOUT=*OUT; +} else { + open STDOUT,">$output"; +} + +if ($output =~ /512/) { + $BITS=512; + $SZ=8; + @Sigma0=(28,34,39); + @Sigma1=(14,18,41); + @sigma0=(1, 8, 7); + @sigma1=(19,61, 6); + $rounds=80; + $reg_t="x"; +} else { + $BITS=256; + $SZ=4; + @Sigma0=( 2,13,22); + @Sigma1=( 6,11,25); + @sigma0=( 7,18, 3); + @sigma1=(17,19,10); + $rounds=64; + $reg_t="w"; +} + +$func="sha${BITS}_block_data_order"; + +($ctx,$inp,$num,$Ktbl)=map("x$_",(0..2,30)); + +@X=map("$reg_t$_",(3..15,0..2)); +@V=($A,$B,$C,$D,$E,$F,$G,$H)=map("$reg_t$_",(20..27)); +($t0,$t1,$t2,$t3)=map("$reg_t$_",(16,17,19,28)); + +sub BODY_00_xx { +my ($i,$a,$b,$c,$d,$e,$f,$g,$h)=@_; +my $j=($i+1)&15; +my ($T0,$T1,$T2)=(@X[($i-8)&15],@X[($i-9)&15],@X[($i-10)&15]); + $T0=@X[$i+3] if ($i<11); + +$code.=<<___ if ($i<16); +#ifndef __AARCH64EB__ + rev @X[$i],@X[$i] // $i +#endif +___ +$code.=<<___ if ($i<13 && ($i&1)); + ldp @X[$i+1],@X[$i+2],[$inp],#2*$SZ +___ +$code.=<<___ if ($i==13); + ldp @X[14],@X[15],[$inp] +___ +$code.=<<___ if ($i>=14); + ldr @X[($i-11)&15],[sp,#`$SZ*(($i-11)%4)`] +___ +$code.=<<___ if ($i>0 && $i<16); + add $a,$a,$t1 // h+=Sigma0(a) +___ +$code.=<<___ if ($i>=11); + str @X[($i-8)&15],[sp,#`$SZ*(($i-8)%4)`] +___ +# While ARMv8 specifies merged rotate-n-logical operation such as +# 'eor x,y,z,ror#n', it was found to negatively affect performance +# on Apple A7. The reason seems to be that it requires even 'y' to +# be available earlier. This means that such merged instruction is +# not necessarily best choice on critical path... On the other hand +# Cortex-A5x handles merged instructions much better than disjoint +# rotate and logical... See (**) footnote above. +$code.=<<___ if ($i<15); + ror $t0,$e,#$Sigma1[0] + add $h,$h,$t2 // h+=K[i] + eor $T0,$e,$e,ror#`$Sigma1[2]-$Sigma1[1]` + and $t1,$f,$e + bic $t2,$g,$e + add $h,$h,@X[$i&15] // h+=X[i] + orr $t1,$t1,$t2 // Ch(e,f,g) + eor $t2,$a,$b // a^b, b^c in next round + eor $t0,$t0,$T0,ror#$Sigma1[1] // Sigma1(e) + ror $T0,$a,#$Sigma0[0] + add $h,$h,$t1 // h+=Ch(e,f,g) + eor $t1,$a,$a,ror#`$Sigma0[2]-$Sigma0[1]` + add $h,$h,$t0 // h+=Sigma1(e) + and $t3,$t3,$t2 // (b^c)&=(a^b) + add $d,$d,$h // d+=h + eor $t3,$t3,$b // Maj(a,b,c) + eor $t1,$T0,$t1,ror#$Sigma0[1] // Sigma0(a) + add $h,$h,$t3 // h+=Maj(a,b,c) + ldr $t3,[$Ktbl],#$SZ // *K++, $t2 in next round + //add $h,$h,$t1 // h+=Sigma0(a) +___ +$code.=<<___ if ($i>=15); + ror $t0,$e,#$Sigma1[0] + add $h,$h,$t2 // h+=K[i] + ror $T1,@X[($j+1)&15],#$sigma0[0] + and $t1,$f,$e + ror $T2,@X[($j+14)&15],#$sigma1[0] + bic $t2,$g,$e + ror $T0,$a,#$Sigma0[0] + add $h,$h,@X[$i&15] // h+=X[i] + eor $t0,$t0,$e,ror#$Sigma1[1] + eor $T1,$T1,@X[($j+1)&15],ror#$sigma0[1] + orr $t1,$t1,$t2 // Ch(e,f,g) + eor $t2,$a,$b // a^b, b^c in next round + eor $t0,$t0,$e,ror#$Sigma1[2] // Sigma1(e) + eor $T0,$T0,$a,ror#$Sigma0[1] + add $h,$h,$t1 // h+=Ch(e,f,g) + and $t3,$t3,$t2 // (b^c)&=(a^b) + eor $T2,$T2,@X[($j+14)&15],ror#$sigma1[1] + eor $T1,$T1,@X[($j+1)&15],lsr#$sigma0[2] // sigma0(X[i+1]) + add $h,$h,$t0 // h+=Sigma1(e) + eor $t3,$t3,$b // Maj(a,b,c) + eor $t1,$T0,$a,ror#$Sigma0[2] // Sigma0(a) + eor $T2,$T2,@X[($j+14)&15],lsr#$sigma1[2] // sigma1(X[i+14]) + add @X[$j],@X[$j],@X[($j+9)&15] + add $d,$d,$h // d+=h + add $h,$h,$t3 // h+=Maj(a,b,c) + ldr $t3,[$Ktbl],#$SZ // *K++, $t2 in next round + add @X[$j],@X[$j],$T1 + add $h,$h,$t1 // h+=Sigma0(a) + add @X[$j],@X[$j],$T2 +___ + ($t2,$t3)=($t3,$t2); +} + +$code.=<<___; +#ifndef __KERNEL__ +# include "arm_arch.h" +#endif + +.text + +.extern OPENSSL_armcap_P +.globl $func +.type $func,%function +.align 6 +$func: +#ifndef __KERNEL__ +# ifdef __ILP32__ + ldrsw x16,.LOPENSSL_armcap_P +# else + ldr x16,.LOPENSSL_armcap_P +# endif + adr x17,.LOPENSSL_armcap_P + add x16,x16,x17 + ldr w16,[x16] +___ +$code.=<<___ if ($SZ==4); + tst w16,#ARMV8_SHA256 + b.ne .Lv8_entry + tst w16,#ARMV7_NEON + b.ne .Lneon_entry +___ +$code.=<<___ if ($SZ==8); + tst w16,#ARMV8_SHA512 + b.ne .Lv8_entry +___ +$code.=<<___; +#endif + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-128]! + add x29,sp,#0 + + stp x19,x20,[sp,#16] + stp x21,x22,[sp,#32] + stp x23,x24,[sp,#48] + stp x25,x26,[sp,#64] + stp x27,x28,[sp,#80] + sub sp,sp,#4*$SZ + + ldp $A,$B,[$ctx] // load context + ldp $C,$D,[$ctx,#2*$SZ] + ldp $E,$F,[$ctx,#4*$SZ] + add $num,$inp,$num,lsl#`log(16*$SZ)/log(2)` // end of input + ldp $G,$H,[$ctx,#6*$SZ] + adr $Ktbl,.LK$BITS + stp $ctx,$num,[x29,#96] + +.Loop: + ldp @X[0],@X[1],[$inp],#2*$SZ + ldr $t2,[$Ktbl],#$SZ // *K++ + eor $t3,$B,$C // magic seed + str $inp,[x29,#112] +___ +for ($i=0;$i<16;$i++) { &BODY_00_xx($i,@V); unshift(@V,pop(@V)); } +$code.=".Loop_16_xx:\n"; +for (;$i<32;$i++) { &BODY_00_xx($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + cbnz $t2,.Loop_16_xx + + ldp $ctx,$num,[x29,#96] + ldr $inp,[x29,#112] + sub $Ktbl,$Ktbl,#`$SZ*($rounds+1)` // rewind + + ldp @X[0],@X[1],[$ctx] + ldp @X[2],@X[3],[$ctx,#2*$SZ] + add $inp,$inp,#14*$SZ // advance input pointer + ldp @X[4],@X[5],[$ctx,#4*$SZ] + add $A,$A,@X[0] + ldp @X[6],@X[7],[$ctx,#6*$SZ] + add $B,$B,@X[1] + add $C,$C,@X[2] + add $D,$D,@X[3] + stp $A,$B,[$ctx] + add $E,$E,@X[4] + add $F,$F,@X[5] + stp $C,$D,[$ctx,#2*$SZ] + add $G,$G,@X[6] + add $H,$H,@X[7] + cmp $inp,$num + stp $E,$F,[$ctx,#4*$SZ] + stp $G,$H,[$ctx,#6*$SZ] + b.ne .Loop + + ldp x19,x20,[x29,#16] + add sp,sp,#4*$SZ + ldp x21,x22,[x29,#32] + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x27,x28,[x29,#80] + ldp x29,x30,[sp],#128 + .inst 0xd50323bf // autiasp + ret +.size $func,.-$func + +.align 6 +.type .LK$BITS,%object +.LK$BITS: +___ +$code.=<<___ if ($SZ==8); + .quad 0x428a2f98d728ae22,0x7137449123ef65cd + .quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc + .quad 0x3956c25bf348b538,0x59f111f1b605d019 + .quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118 + .quad 0xd807aa98a3030242,0x12835b0145706fbe + .quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 + .quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1 + .quad 0x9bdc06a725c71235,0xc19bf174cf692694 + .quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3 + .quad 0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65 + .quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483 + .quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 + .quad 0x983e5152ee66dfab,0xa831c66d2db43210 + .quad 0xb00327c898fb213f,0xbf597fc7beef0ee4 + .quad 0xc6e00bf33da88fc2,0xd5a79147930aa725 + .quad 0x06ca6351e003826f,0x142929670a0e6e70 + .quad 0x27b70a8546d22ffc,0x2e1b21385c26c926 + .quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df + .quad 0x650a73548baf63de,0x766a0abb3c77b2a8 + .quad 0x81c2c92e47edaee6,0x92722c851482353b + .quad 0xa2bfe8a14cf10364,0xa81a664bbc423001 + .quad 0xc24b8b70d0f89791,0xc76c51a30654be30 + .quad 0xd192e819d6ef5218,0xd69906245565a910 + .quad 0xf40e35855771202a,0x106aa07032bbd1b8 + .quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53 + .quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 + .quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb + .quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 + .quad 0x748f82ee5defb2fc,0x78a5636f43172f60 + .quad 0x84c87814a1f0ab72,0x8cc702081a6439ec + .quad 0x90befffa23631e28,0xa4506cebde82bde9 + .quad 0xbef9a3f7b2c67915,0xc67178f2e372532b + .quad 0xca273eceea26619c,0xd186b8c721c0c207 + .quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 + .quad 0x06f067aa72176fba,0x0a637dc5a2c898a6 + .quad 0x113f9804bef90dae,0x1b710b35131c471b + .quad 0x28db77f523047d84,0x32caab7b40c72493 + .quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c + .quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a + .quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817 + .quad 0 // terminator +___ +$code.=<<___ if ($SZ==4); + .long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 + .long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 + .long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 + .long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 + .long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc + .long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da + .long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 + .long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967 + .long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 + .long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 + .long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 + .long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 + .long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 + .long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 + .long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 + .long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 + .long 0 //terminator +___ +$code.=<<___; +.size .LK$BITS,.-.LK$BITS +#ifndef __KERNEL__ +.align 3 +.LOPENSSL_armcap_P: +# ifdef __ILP32__ + .long OPENSSL_armcap_P-. +# else + .quad OPENSSL_armcap_P-. +# endif +#endif +.asciz "SHA$BITS block transform for ARMv8, CRYPTOGAMS by " +.align 2 +___ + +if ($SZ==4) { +my $Ktbl="x3"; + +my ($ABCD,$EFGH,$abcd)=map("v$_.16b",(0..2)); +my @MSG=map("v$_.16b",(4..7)); +my ($W0,$W1)=("v16.4s","v17.4s"); +my ($ABCD_SAVE,$EFGH_SAVE)=("v18.16b","v19.16b"); + +$code.=<<___; +#ifndef __KERNEL__ +.type sha256_block_armv8,%function +.align 6 +sha256_block_armv8: +.Lv8_entry: + stp x29,x30,[sp,#-16]! + add x29,sp,#0 + + ld1.32 {$ABCD,$EFGH},[$ctx] + adr $Ktbl,.LK256 + +.Loop_hw: + ld1 {@MSG[0]-@MSG[3]},[$inp],#64 + sub $num,$num,#1 + ld1.32 {$W0},[$Ktbl],#16 + rev32 @MSG[0],@MSG[0] + rev32 @MSG[1],@MSG[1] + rev32 @MSG[2],@MSG[2] + rev32 @MSG[3],@MSG[3] + orr $ABCD_SAVE,$ABCD,$ABCD // offload + orr $EFGH_SAVE,$EFGH,$EFGH +___ +for($i=0;$i<12;$i++) { +$code.=<<___; + ld1.32 {$W1},[$Ktbl],#16 + add.i32 $W0,$W0,@MSG[0] + sha256su0 @MSG[0],@MSG[1] + orr $abcd,$ABCD,$ABCD + sha256h $ABCD,$EFGH,$W0 + sha256h2 $EFGH,$abcd,$W0 + sha256su1 @MSG[0],@MSG[2],@MSG[3] +___ + ($W0,$W1)=($W1,$W0); push(@MSG,shift(@MSG)); +} +$code.=<<___; + ld1.32 {$W1},[$Ktbl],#16 + add.i32 $W0,$W0,@MSG[0] + orr $abcd,$ABCD,$ABCD + sha256h $ABCD,$EFGH,$W0 + sha256h2 $EFGH,$abcd,$W0 + + ld1.32 {$W0},[$Ktbl],#16 + add.i32 $W1,$W1,@MSG[1] + orr $abcd,$ABCD,$ABCD + sha256h $ABCD,$EFGH,$W1 + sha256h2 $EFGH,$abcd,$W1 + + ld1.32 {$W1},[$Ktbl] + add.i32 $W0,$W0,@MSG[2] + sub $Ktbl,$Ktbl,#$rounds*$SZ-16 // rewind + orr $abcd,$ABCD,$ABCD + sha256h $ABCD,$EFGH,$W0 + sha256h2 $EFGH,$abcd,$W0 + + add.i32 $W1,$W1,@MSG[3] + orr $abcd,$ABCD,$ABCD + sha256h $ABCD,$EFGH,$W1 + sha256h2 $EFGH,$abcd,$W1 + + add.i32 $ABCD,$ABCD,$ABCD_SAVE + add.i32 $EFGH,$EFGH,$EFGH_SAVE + + cbnz $num,.Loop_hw + + st1.32 {$ABCD,$EFGH},[$ctx] + + ldr x29,[sp],#16 + ret +.size sha256_block_armv8,.-sha256_block_armv8 +#endif +___ +} + +if ($SZ==4) { ######################################### NEON stuff # +# You'll surely note a lot of similarities with sha256-armv4 module, +# and of course it's not a coincidence. sha256-armv4 was used as +# initial template, but was adapted for ARMv8 instruction set and +# extensively re-tuned for all-round performance. + +my @V = ($A,$B,$C,$D,$E,$F,$G,$H) = map("w$_",(3..10)); +my ($t0,$t1,$t2,$t3,$t4) = map("w$_",(11..15)); +my $Ktbl="x16"; +my $Xfer="x17"; +my @X = map("q$_",(0..3)); +my ($T0,$T1,$T2,$T3,$T4,$T5,$T6,$T7) = map("q$_",(4..7,16..19)); +my $j=0; + +sub AUTOLOAD() # thunk [simplified] x86-style perlasm +{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; $opcode =~ s/_/\./; + my $arg = pop; + $arg = "#$arg" if ($arg*1 eq $arg); + $code .= "\t$opcode\t".join(',',@_,$arg)."\n"; +} + +sub Dscalar { shift =~ m|[qv]([0-9]+)|?"d$1":""; } +sub Dlo { shift =~ m|[qv]([0-9]+)|?"v$1.d[0]":""; } +sub Dhi { shift =~ m|[qv]([0-9]+)|?"v$1.d[1]":""; } + +sub Xupdate() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); + my ($a,$b,$c,$d,$e,$f,$g,$h); + + &ext_8 ($T0,@X[0],@X[1],4); # X[1..4] + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &ext_8 ($T3,@X[2],@X[3],4); # X[9..12] + eval(shift(@insns)); + eval(shift(@insns)); + &mov (&Dscalar($T7),&Dhi(@X[3])); # X[14..15] + eval(shift(@insns)); + eval(shift(@insns)); + &ushr_32 ($T2,$T0,$sigma0[0]); + eval(shift(@insns)); + &ushr_32 ($T1,$T0,$sigma0[2]); + eval(shift(@insns)); + &add_32 (@X[0],@X[0],$T3); # X[0..3] += X[9..12] + eval(shift(@insns)); + &sli_32 ($T2,$T0,32-$sigma0[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &ushr_32 ($T3,$T0,$sigma0[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &eor_8 ($T1,$T1,$T2); + eval(shift(@insns)); + eval(shift(@insns)); + &sli_32 ($T3,$T0,32-$sigma0[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &ushr_32 ($T4,$T7,$sigma1[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &eor_8 ($T1,$T1,$T3); # sigma0(X[1..4]) + eval(shift(@insns)); + eval(shift(@insns)); + &sli_32 ($T4,$T7,32-$sigma1[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &ushr_32 ($T5,$T7,$sigma1[2]); + eval(shift(@insns)); + eval(shift(@insns)); + &ushr_32 ($T3,$T7,$sigma1[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &add_32 (@X[0],@X[0],$T1); # X[0..3] += sigma0(X[1..4]) + eval(shift(@insns)); + eval(shift(@insns)); + &sli_u32 ($T3,$T7,32-$sigma1[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &eor_8 ($T5,$T5,$T4); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &eor_8 ($T5,$T5,$T3); # sigma1(X[14..15]) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &add_32 (@X[0],@X[0],$T5); # X[0..1] += sigma1(X[14..15]) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &ushr_32 ($T6,@X[0],$sigma1[0]); + eval(shift(@insns)); + &ushr_32 ($T7,@X[0],$sigma1[2]); + eval(shift(@insns)); + eval(shift(@insns)); + &sli_32 ($T6,@X[0],32-$sigma1[0]); + eval(shift(@insns)); + &ushr_32 ($T5,@X[0],$sigma1[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &eor_8 ($T7,$T7,$T6); + eval(shift(@insns)); + eval(shift(@insns)); + &sli_32 ($T5,@X[0],32-$sigma1[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &ld1_32 ("{$T0}","[$Ktbl], #16"); + eval(shift(@insns)); + &eor_8 ($T7,$T7,$T5); # sigma1(X[16..17]) + eval(shift(@insns)); + eval(shift(@insns)); + &eor_8 ($T5,$T5,$T5); + eval(shift(@insns)); + eval(shift(@insns)); + &mov (&Dhi($T5), &Dlo($T7)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &add_32 (@X[0],@X[0],$T5); # X[2..3] += sigma1(X[16..17]) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &add_32 ($T0,$T0,@X[0]); + while($#insns>=1) { eval(shift(@insns)); } + &st1_32 ("{$T0}","[$Xfer], #16"); + eval(shift(@insns)); + + push(@X,shift(@X)); # "rotate" X[] +} + +sub Xpreload() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); + my ($a,$b,$c,$d,$e,$f,$g,$h); + + eval(shift(@insns)); + eval(shift(@insns)); + &ld1_8 ("{@X[0]}","[$inp],#16"); + eval(shift(@insns)); + eval(shift(@insns)); + &ld1_32 ("{$T0}","[$Ktbl],#16"); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &rev32 (@X[0],@X[0]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &add_32 ($T0,$T0,@X[0]); + foreach (@insns) { eval; } # remaining instructions + &st1_32 ("{$T0}","[$Xfer], #16"); + + push(@X,shift(@X)); # "rotate" X[] +} + +sub body_00_15 () { + ( + '($a,$b,$c,$d,$e,$f,$g,$h)=@V;'. + '&add ($h,$h,$t1)', # h+=X[i]+K[i] + '&add ($a,$a,$t4);'. # h+=Sigma0(a) from the past + '&and ($t1,$f,$e)', + '&bic ($t4,$g,$e)', + '&eor ($t0,$e,$e,"ror#".($Sigma1[1]-$Sigma1[0]))', + '&add ($a,$a,$t2)', # h+=Maj(a,b,c) from the past + '&orr ($t1,$t1,$t4)', # Ch(e,f,g) + '&eor ($t0,$t0,$e,"ror#".($Sigma1[2]-$Sigma1[0]))', # Sigma1(e) + '&eor ($t4,$a,$a,"ror#".($Sigma0[1]-$Sigma0[0]))', + '&add ($h,$h,$t1)', # h+=Ch(e,f,g) + '&ror ($t0,$t0,"#$Sigma1[0]")', + '&eor ($t2,$a,$b)', # a^b, b^c in next round + '&eor ($t4,$t4,$a,"ror#".($Sigma0[2]-$Sigma0[0]))', # Sigma0(a) + '&add ($h,$h,$t0)', # h+=Sigma1(e) + '&ldr ($t1,sprintf "[sp,#%d]",4*(($j+1)&15)) if (($j&15)!=15);'. + '&ldr ($t1,"[$Ktbl]") if ($j==15);'. + '&and ($t3,$t3,$t2)', # (b^c)&=(a^b) + '&ror ($t4,$t4,"#$Sigma0[0]")', + '&add ($d,$d,$h)', # d+=h + '&eor ($t3,$t3,$b)', # Maj(a,b,c) + '$j++; unshift(@V,pop(@V)); ($t2,$t3)=($t3,$t2);' + ) +} + +$code.=<<___; +#ifdef __KERNEL__ +.globl sha256_block_neon +#endif +.type sha256_block_neon,%function +.align 4 +sha256_block_neon: +.Lneon_entry: + stp x29, x30, [sp, #-16]! + mov x29, sp + sub sp,sp,#16*4 + + adr $Ktbl,.LK256 + add $num,$inp,$num,lsl#6 // len to point at the end of inp + + ld1.8 {@X[0]},[$inp], #16 + ld1.8 {@X[1]},[$inp], #16 + ld1.8 {@X[2]},[$inp], #16 + ld1.8 {@X[3]},[$inp], #16 + ld1.32 {$T0},[$Ktbl], #16 + ld1.32 {$T1},[$Ktbl], #16 + ld1.32 {$T2},[$Ktbl], #16 + ld1.32 {$T3},[$Ktbl], #16 + rev32 @X[0],@X[0] // yes, even on + rev32 @X[1],@X[1] // big-endian + rev32 @X[2],@X[2] + rev32 @X[3],@X[3] + mov $Xfer,sp + add.32 $T0,$T0,@X[0] + add.32 $T1,$T1,@X[1] + add.32 $T2,$T2,@X[2] + st1.32 {$T0-$T1},[$Xfer], #32 + add.32 $T3,$T3,@X[3] + st1.32 {$T2-$T3},[$Xfer] + sub $Xfer,$Xfer,#32 + + ldp $A,$B,[$ctx] + ldp $C,$D,[$ctx,#8] + ldp $E,$F,[$ctx,#16] + ldp $G,$H,[$ctx,#24] + ldr $t1,[sp,#0] + mov $t2,wzr + eor $t3,$B,$C + mov $t4,wzr + b .L_00_48 + +.align 4 +.L_00_48: +___ + &Xupdate(\&body_00_15); + &Xupdate(\&body_00_15); + &Xupdate(\&body_00_15); + &Xupdate(\&body_00_15); +$code.=<<___; + cmp $t1,#0 // check for K256 terminator + ldr $t1,[sp,#0] + sub $Xfer,$Xfer,#64 + bne .L_00_48 + + sub $Ktbl,$Ktbl,#256 // rewind $Ktbl + cmp $inp,$num + mov $Xfer, #64 + csel $Xfer, $Xfer, xzr, eq + sub $inp,$inp,$Xfer // avoid SEGV + mov $Xfer,sp +___ + &Xpreload(\&body_00_15); + &Xpreload(\&body_00_15); + &Xpreload(\&body_00_15); + &Xpreload(\&body_00_15); +$code.=<<___; + add $A,$A,$t4 // h+=Sigma0(a) from the past + ldp $t0,$t1,[$ctx,#0] + add $A,$A,$t2 // h+=Maj(a,b,c) from the past + ldp $t2,$t3,[$ctx,#8] + add $A,$A,$t0 // accumulate + add $B,$B,$t1 + ldp $t0,$t1,[$ctx,#16] + add $C,$C,$t2 + add $D,$D,$t3 + ldp $t2,$t3,[$ctx,#24] + add $E,$E,$t0 + add $F,$F,$t1 + ldr $t1,[sp,#0] + stp $A,$B,[$ctx,#0] + add $G,$G,$t2 + mov $t2,wzr + stp $C,$D,[$ctx,#8] + add $H,$H,$t3 + stp $E,$F,[$ctx,#16] + eor $t3,$B,$C + stp $G,$H,[$ctx,#24] + mov $t4,wzr + mov $Xfer,sp + b.ne .L_00_48 + + ldr x29,[x29] + add sp,sp,#16*4+16 + ret +.size sha256_block_neon,.-sha256_block_neon +___ +} + +if ($SZ==8) { +my $Ktbl="x3"; + +my @H = map("v$_.16b",(0..4)); +my ($fg,$de,$m9_10)=map("v$_.16b",(5..7)); +my @MSG=map("v$_.16b",(16..23)); +my ($W0,$W1)=("v24.2d","v25.2d"); +my ($AB,$CD,$EF,$GH)=map("v$_.16b",(26..29)); + +$code.=<<___; +#ifndef __KERNEL__ +.type sha512_block_armv8,%function +.align 6 +sha512_block_armv8: +.Lv8_entry: + stp x29,x30,[sp,#-16]! + add x29,sp,#0 + + ld1 {@MSG[0]-@MSG[3]},[$inp],#64 // load input + ld1 {@MSG[4]-@MSG[7]},[$inp],#64 + + ld1.64 {@H[0]-@H[3]},[$ctx] // load context + adr $Ktbl,.LK512 + + rev64 @MSG[0],@MSG[0] + rev64 @MSG[1],@MSG[1] + rev64 @MSG[2],@MSG[2] + rev64 @MSG[3],@MSG[3] + rev64 @MSG[4],@MSG[4] + rev64 @MSG[5],@MSG[5] + rev64 @MSG[6],@MSG[6] + rev64 @MSG[7],@MSG[7] + b .Loop_hw + +.align 4 +.Loop_hw: + ld1.64 {$W0},[$Ktbl],#16 + subs $num,$num,#1 + sub x4,$inp,#128 + orr $AB,@H[0],@H[0] // offload + orr $CD,@H[1],@H[1] + orr $EF,@H[2],@H[2] + orr $GH,@H[3],@H[3] + csel $inp,$inp,x4,ne // conditional rewind +___ +for($i=0;$i<32;$i++) { +$code.=<<___; + add.i64 $W0,$W0,@MSG[0] + ld1.64 {$W1},[$Ktbl],#16 + ext $W0,$W0,$W0,#8 + ext $fg,@H[2],@H[3],#8 + ext $de,@H[1],@H[2],#8 + add.i64 @H[3],@H[3],$W0 // "T1 + H + K512[i]" + sha512su0 @MSG[0],@MSG[1] + ext $m9_10,@MSG[4],@MSG[5],#8 + sha512h @H[3],$fg,$de + sha512su1 @MSG[0],@MSG[7],$m9_10 + add.i64 @H[4],@H[1],@H[3] // "D + T1" + sha512h2 @H[3],$H[1],@H[0] +___ + ($W0,$W1)=($W1,$W0); push(@MSG,shift(@MSG)); + @H = (@H[3],@H[0],@H[4],@H[2],@H[1]); +} +for(;$i<40;$i++) { +$code.=<<___ if ($i<39); + ld1.64 {$W1},[$Ktbl],#16 +___ +$code.=<<___ if ($i==39); + sub $Ktbl,$Ktbl,#$rounds*$SZ // rewind +___ +$code.=<<___; + add.i64 $W0,$W0,@MSG[0] + ld1 {@MSG[0]},[$inp],#16 // load next input + ext $W0,$W0,$W0,#8 + ext $fg,@H[2],@H[3],#8 + ext $de,@H[1],@H[2],#8 + add.i64 @H[3],@H[3],$W0 // "T1 + H + K512[i]" + sha512h @H[3],$fg,$de + rev64 @MSG[0],@MSG[0] + add.i64 @H[4],@H[1],@H[3] // "D + T1" + sha512h2 @H[3],$H[1],@H[0] +___ + ($W0,$W1)=($W1,$W0); push(@MSG,shift(@MSG)); + @H = (@H[3],@H[0],@H[4],@H[2],@H[1]); +} +$code.=<<___; + add.i64 @H[0],@H[0],$AB // accumulate + add.i64 @H[1],@H[1],$CD + add.i64 @H[2],@H[2],$EF + add.i64 @H[3],@H[3],$GH + + cbnz $num,.Loop_hw + + st1.64 {@H[0]-@H[3]},[$ctx] // store context + + ldr x29,[sp],#16 + ret +.size sha512_block_armv8,.-sha512_block_armv8 +#endif +___ +} + +$code.=<<___; +#ifndef __KERNEL__ +.comm OPENSSL_armcap_P,4,4 +#endif +___ + +{ my %opcode = ( + "sha256h" => 0x5e004000, "sha256h2" => 0x5e005000, + "sha256su0" => 0x5e282800, "sha256su1" => 0x5e006000 ); + + sub unsha256 { + my ($mnemonic,$arg)=@_; + + $arg =~ m/[qv]([0-9]+)[^,]*,\s*[qv]([0-9]+)[^,]*(?:,\s*[qv]([0-9]+))?/o + && + sprintf ".inst\t0x%08x\t//%s %s", + $opcode{$mnemonic}|$1|($2<<5)|($3<<16), + $mnemonic,$arg; + } +} + +{ my %opcode = ( + "sha512h" => 0xce608000, "sha512h2" => 0xce608400, + "sha512su0" => 0xcec08000, "sha512su1" => 0xce608800 ); + + sub unsha512 { + my ($mnemonic,$arg)=@_; + + $arg =~ m/[qv]([0-9]+)[^,]*,\s*[qv]([0-9]+)[^,]*(?:,\s*[qv]([0-9]+))?/o + && + sprintf ".inst\t0x%08x\t//%s %s", + $opcode{$mnemonic}|$1|($2<<5)|($3<<16), + $mnemonic,$arg; + } +} + +open SELF,$0; +while() { + next if (/^#!/); + last if (!s/^#/\/\// and !/^$/); + print; +} +close SELF; + +foreach(split("\n",$code)) { + + s/\`([^\`]*)\`/eval($1)/ge; + + s/\b(sha512\w+)\s+([qv].*)/unsha512($1,$2)/ge or + s/\b(sha256\w+)\s+([qv].*)/unsha256($1,$2)/ge; + + s/\bq([0-9]+)\b/v$1.16b/g; # old->new registers + + s/\.[ui]?8(\s)/$1/; + s/\.\w?64\b// and s/\.16b/\.2d/g or + s/\.\w?32\b// and s/\.16b/\.4s/g; + m/\bext\b/ and s/\.2d/\.16b/g or + m/(ld|st)1[^\[]+\[0\]/ and s/\.4s/\.s/g; + + print $_,"\n"; +} + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-c64xplus.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-c64xplus.pl new file mode 100644 index 000000000..9ebfc92e2 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-c64xplus.pl @@ -0,0 +1,438 @@ +#! /usr/bin/env perl +# Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# SHA512 for C64x+. +# +# January 2012 +# +# Performance is 19 cycles per processed byte. Compared to block +# transform function from sha512.c compiled with cl6x with -mv6400+ +# -o2 -DOPENSSL_SMALL_FOOTPRINT it's almost 7x faster and 2x smaller. +# Loop unroll won't make it, this implementation, any faster, because +# it's effectively dominated by SHRU||SHL pairs and you can't schedule +# more of them. +# +# !!! Note that this module uses AMR, which means that all interrupt +# service routines are expected to preserve it and for own well-being +# zero it upon entry. + +while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} +open STDOUT,">$output"; + +($CTXA,$INP,$NUM) = ("A4","B4","A6"); # arguments + $K512="A3"; + +($Ahi,$Actxhi,$Bhi,$Bctxhi,$Chi,$Cctxhi,$Dhi,$Dctxhi, + $Ehi,$Ectxhi,$Fhi,$Fctxhi,$Ghi,$Gctxhi,$Hhi,$Hctxhi)=map("A$_",(16..31)); +($Alo,$Actxlo,$Blo,$Bctxlo,$Clo,$Cctxlo,$Dlo,$Dctxlo, + $Elo,$Ectxlo,$Flo,$Fctxlo,$Glo,$Gctxlo,$Hlo,$Hctxlo)=map("B$_",(16..31)); + +($S1hi,$CHhi,$S0hi,$t0hi)=map("A$_",(10..13)); +($S1lo,$CHlo,$S0lo,$t0lo)=map("B$_",(10..13)); +($T1hi, $T2hi)= ("A6","A7"); +($T1lo,$T1carry,$T2lo,$T2carry)=("B6","B7","B8","B9"); +($Khi,$Klo)=("A9","A8"); +($MAJhi,$MAJlo)=($T2hi,$T2lo); +($t1hi,$t1lo)=($Khi,"B2"); + $CTXB=$t1lo; + +($Xihi,$Xilo)=("A5","B5"); # circular/ring buffer + +$code.=<<___; + .text + + .if .ASSEMBLER_VERSION<7000000 + .asg 0,__TI_EABI__ + .endif + .if __TI_EABI__ + .nocmp + .asg sha512_block_data_order,_sha512_block_data_order + .endif + + .asg B3,RA + .asg A15,FP + .asg B15,SP + + .if .BIG_ENDIAN + .asg $Khi,KHI + .asg $Klo,KLO + .else + .asg $Khi,KLO + .asg $Klo,KHI + .endif + + .global _sha512_block_data_order +_sha512_block_data_order: +__sha512_block: + .asmfunc stack_usage(40+128) + MV $NUM,A0 ; reassign $NUM +|| MVK -128,B0 + [!A0] BNOP RA ; if ($NUM==0) return; +|| [A0] STW FP,*SP--(40) ; save frame pointer +|| [A0] MV SP,FP + [A0] STDW B13:B12,*SP[4] +|| [A0] MVK 0x00404,B1 + [A0] STDW B11:B10,*SP[3] +|| [A0] STDW A13:A12,*FP[-3] +|| [A0] MVKH 0x60000,B1 + [A0] STDW A11:A10,*SP[1] +|| [A0] MVC B1,AMR ; setup circular addressing +|| [A0] ADD B0,SP,SP ; alloca(128) + .if __TI_EABI__ + [A0] AND B0,SP,SP ; align stack at 128 bytes +|| [A0] ADDKPC __sha512_block,B1 +|| [A0] MVKL \$PCR_OFFSET(K512,__sha512_block),$K512 + [A0] MVKH \$PCR_OFFSET(K512,__sha512_block),$K512 +|| [A0] SUBAW SP,2,SP ; reserve two words above buffer + .else + [A0] AND B0,SP,SP ; align stack at 128 bytes +|| [A0] ADDKPC __sha512_block,B1 +|| [A0] MVKL (K512-__sha512_block),$K512 + [A0] MVKH (K512-__sha512_block),$K512 +|| [A0] SUBAW SP,2,SP ; reserve two words above buffer + .endif + ADDAW SP,3,$Xilo + ADDAW SP,2,$Xihi + +|| MV $CTXA,$CTXB + LDW *${CTXA}[0^.LITTLE_ENDIAN],$Ahi ; load ctx +|| LDW *${CTXB}[1^.LITTLE_ENDIAN],$Alo +|| ADD B1,$K512,$K512 + LDW *${CTXA}[2^.LITTLE_ENDIAN],$Bhi +|| LDW *${CTXB}[3^.LITTLE_ENDIAN],$Blo + LDW *${CTXA}[4^.LITTLE_ENDIAN],$Chi +|| LDW *${CTXB}[5^.LITTLE_ENDIAN],$Clo + LDW *${CTXA}[6^.LITTLE_ENDIAN],$Dhi +|| LDW *${CTXB}[7^.LITTLE_ENDIAN],$Dlo + LDW *${CTXA}[8^.LITTLE_ENDIAN],$Ehi +|| LDW *${CTXB}[9^.LITTLE_ENDIAN],$Elo + LDW *${CTXA}[10^.LITTLE_ENDIAN],$Fhi +|| LDW *${CTXB}[11^.LITTLE_ENDIAN],$Flo + LDW *${CTXA}[12^.LITTLE_ENDIAN],$Ghi +|| LDW *${CTXB}[13^.LITTLE_ENDIAN],$Glo + LDW *${CTXA}[14^.LITTLE_ENDIAN],$Hhi +|| LDW *${CTXB}[15^.LITTLE_ENDIAN],$Hlo + + LDNDW *$INP++,B11:B10 ; pre-fetch input + LDDW *$K512++,$Khi:$Klo ; pre-fetch K512[0] +outerloop?: + MVK 15,B0 ; loop counters +|| MVK 64,B1 +|| SUB A0,1,A0 + MV $Ahi,$Actxhi +|| MV $Alo,$Actxlo +|| MV $Bhi,$Bctxhi +|| MV $Blo,$Bctxlo +|| MV $Chi,$Cctxhi +|| MV $Clo,$Cctxlo +|| MVD $Dhi,$Dctxhi +|| MVD $Dlo,$Dctxlo + MV $Ehi,$Ectxhi +|| MV $Elo,$Ectxlo +|| MV $Fhi,$Fctxhi +|| MV $Flo,$Fctxlo +|| MV $Ghi,$Gctxhi +|| MV $Glo,$Gctxlo +|| MVD $Hhi,$Hctxhi +|| MVD $Hlo,$Hctxlo +loop0_15?: + .if .BIG_ENDIAN + MV B11,$T1hi +|| MV B10,$T1lo + .else + SWAP4 B10,$T1hi +|| SWAP4 B11,$T1lo + SWAP2 $T1hi,$T1hi +|| SWAP2 $T1lo,$T1lo + .endif +loop16_79?: + STW $T1hi,*$Xihi++[2] +|| STW $T1lo,*$Xilo++[2] ; X[i] = T1 +|| ADD $Hhi,$T1hi,$T1hi +|| ADDU $Hlo,$T1lo,$T1carry:$T1lo ; T1 += h +|| SHRU $Ehi,14,$S1hi +|| SHL $Ehi,32-14,$S1lo + XOR $Fhi,$Ghi,$CHhi +|| XOR $Flo,$Glo,$CHlo +|| ADD KHI,$T1hi,$T1hi +|| ADDU KLO,$T1carry:$T1lo,$T1carry:$T1lo ; T1 += K512[i] +|| SHRU $Elo,14,$t0lo +|| SHL $Elo,32-14,$t0hi + XOR $t0hi,$S1hi,$S1hi +|| XOR $t0lo,$S1lo,$S1lo +|| AND $Ehi,$CHhi,$CHhi +|| AND $Elo,$CHlo,$CHlo +|| ROTL $Ghi,0,$Hhi +|| ROTL $Glo,0,$Hlo ; h = g +|| SHRU $Ehi,18,$t0hi +|| SHL $Ehi,32-18,$t0lo + XOR $t0hi,$S1hi,$S1hi +|| XOR $t0lo,$S1lo,$S1lo +|| XOR $Ghi,$CHhi,$CHhi +|| XOR $Glo,$CHlo,$CHlo ; Ch(e,f,g) = ((f^g)&e)^g +|| ROTL $Fhi,0,$Ghi +|| ROTL $Flo,0,$Glo ; g = f +|| SHRU $Elo,18,$t0lo +|| SHL $Elo,32-18,$t0hi + XOR $t0hi,$S1hi,$S1hi +|| XOR $t0lo,$S1lo,$S1lo +|| OR $Ahi,$Bhi,$MAJhi +|| OR $Alo,$Blo,$MAJlo +|| ROTL $Ehi,0,$Fhi +|| ROTL $Elo,0,$Flo ; f = e +|| SHRU $Ehi,41-32,$t0lo +|| SHL $Ehi,64-41,$t0hi + XOR $t0hi,$S1hi,$S1hi +|| XOR $t0lo,$S1lo,$S1lo +|| AND $Chi,$MAJhi,$MAJhi +|| AND $Clo,$MAJlo,$MAJlo +|| ROTL $Dhi,0,$Ehi +|| ROTL $Dlo,0,$Elo ; e = d +|| SHRU $Elo,41-32,$t0hi +|| SHL $Elo,64-41,$t0lo + XOR $t0hi,$S1hi,$S1hi +|| XOR $t0lo,$S1lo,$S1lo ; Sigma1(e) +|| AND $Ahi,$Bhi,$t1hi +|| AND $Alo,$Blo,$t1lo +|| ROTL $Chi,0,$Dhi +|| ROTL $Clo,0,$Dlo ; d = c +|| SHRU $Ahi,28,$S0hi +|| SHL $Ahi,32-28,$S0lo + OR $t1hi,$MAJhi,$MAJhi +|| OR $t1lo,$MAJlo,$MAJlo ; Maj(a,b,c) = ((a|b)&c)|(a&b) +|| ADD $CHhi,$T1hi,$T1hi +|| ADDU $CHlo,$T1carry:$T1lo,$T1carry:$T1lo ; T1 += Ch(e,f,g) +|| ROTL $Bhi,0,$Chi +|| ROTL $Blo,0,$Clo ; c = b +|| SHRU $Alo,28,$t0lo +|| SHL $Alo,32-28,$t0hi + XOR $t0hi,$S0hi,$S0hi +|| XOR $t0lo,$S0lo,$S0lo +|| ADD $S1hi,$T1hi,$T1hi +|| ADDU $S1lo,$T1carry:$T1lo,$T1carry:$T1lo ; T1 += Sigma1(e) +|| ROTL $Ahi,0,$Bhi +|| ROTL $Alo,0,$Blo ; b = a +|| SHRU $Ahi,34-32,$t0lo +|| SHL $Ahi,64-34,$t0hi + XOR $t0hi,$S0hi,$S0hi +|| XOR $t0lo,$S0lo,$S0lo +|| ADD $MAJhi,$T1hi,$T2hi +|| ADDU $MAJlo,$T1carry:$T1lo,$T2carry:$T2lo ; T2 = T1+Maj(a,b,c) +|| SHRU $Alo,34-32,$t0hi +|| SHL $Alo,64-34,$t0lo + XOR $t0hi,$S0hi,$S0hi +|| XOR $t0lo,$S0lo,$S0lo +|| ADD $Ehi,$T1hi,$T1hi +|| ADDU $Elo,$T1carry:$T1lo,$T1carry:$T1lo ; T1 += e +|| [B0] BNOP loop0_15? +|| SHRU $Ahi,39-32,$t0lo +|| SHL $Ahi,64-39,$t0hi + XOR $t0hi,$S0hi,$S0hi +|| XOR $t0lo,$S0lo,$S0lo +|| [B0] LDNDW *$INP++,B11:B10 ; pre-fetch input +||[!B1] BNOP break? +|| SHRU $Alo,39-32,$t0hi +|| SHL $Alo,64-39,$t0lo + XOR $t0hi,$S0hi,$S0hi +|| XOR $t0lo,$S0lo,$S0lo ; Sigma0(a) +|| ADD $T1carry,$T1hi,$Ehi +|| MV $T1lo,$Elo ; e = T1 +||[!B0] LDW *${Xihi}[28],$T1hi +||[!B0] LDW *${Xilo}[28],$T1lo ; X[i+14] + ADD $S0hi,$T2hi,$T2hi +|| ADDU $S0lo,$T2carry:$T2lo,$T2carry:$T2lo ; T2 += Sigma0(a) +|| [B1] LDDW *$K512++,$Khi:$Klo ; pre-fetch K512[i] + NOP ; avoid cross-path stall + ADD $T2carry,$T2hi,$Ahi +|| MV $T2lo,$Alo ; a = T2 +|| [B0] SUB B0,1,B0 +;;===== branch to loop00_15? is taken here + NOP +;;===== branch to break? is taken here + LDW *${Xihi}[2],$T2hi +|| LDW *${Xilo}[2],$T2lo ; X[i+1] +|| SHRU $T1hi,19,$S1hi +|| SHL $T1hi,32-19,$S1lo + SHRU $T1lo,19,$t0lo +|| SHL $T1lo,32-19,$t0hi + XOR $t0hi,$S1hi,$S1hi +|| XOR $t0lo,$S1lo,$S1lo +|| SHRU $T1hi,61-32,$t0lo +|| SHL $T1hi,64-61,$t0hi + XOR $t0hi,$S1hi,$S1hi +|| XOR $t0lo,$S1lo,$S1lo +|| SHRU $T1lo,61-32,$t0hi +|| SHL $T1lo,64-61,$t0lo + XOR $t0hi,$S1hi,$S1hi +|| XOR $t0lo,$S1lo,$S1lo +|| SHRU $T1hi,6,$t0hi +|| SHL $T1hi,32-6,$t0lo + XOR $t0hi,$S1hi,$S1hi +|| XOR $t0lo,$S1lo,$S1lo +|| SHRU $T1lo,6,$t0lo +|| LDW *${Xihi}[18],$T1hi +|| LDW *${Xilo}[18],$T1lo ; X[i+9] + XOR $t0lo,$S1lo,$S1lo ; sigma1(Xi[i+14]) + +|| LDW *${Xihi}[0],$CHhi +|| LDW *${Xilo}[0],$CHlo ; X[i] +|| SHRU $T2hi,1,$S0hi +|| SHL $T2hi,32-1,$S0lo + SHRU $T2lo,1,$t0lo +|| SHL $T2lo,32-1,$t0hi + XOR $t0hi,$S0hi,$S0hi +|| XOR $t0lo,$S0lo,$S0lo +|| SHRU $T2hi,8,$t0hi +|| SHL $T2hi,32-8,$t0lo + XOR $t0hi,$S0hi,$S0hi +|| XOR $t0lo,$S0lo,$S0lo +|| SHRU $T2lo,8,$t0lo +|| SHL $T2lo,32-8,$t0hi + XOR $t0hi,$S0hi,$S0hi +|| XOR $t0lo,$S0lo,$S0lo +|| ADD $S1hi,$T1hi,$T1hi +|| ADDU $S1lo,$T1lo,$T1carry:$T1lo ; T1 = X[i+9]+sigma1() +|| [B1] BNOP loop16_79? +|| SHRU $T2hi,7,$t0hi +|| SHL $T2hi,32-7,$t0lo + XOR $t0hi,$S0hi,$S0hi +|| XOR $t0lo,$S0lo,$S0lo +|| ADD $CHhi,$T1hi,$T1hi +|| ADDU $CHlo,$T1carry:$T1lo,$T1carry:$T1lo ; T1 += X[i] +|| SHRU $T2lo,7,$t0lo + XOR $t0lo,$S0lo,$S0lo ; sigma0(Xi[i+1] + + ADD $S0hi,$T1hi,$T1hi +|| ADDU $S0lo,$T1carry:$T1lo,$T1carry:$T1lo ; T1 += sigma0() +|| [B1] SUB B1,1,B1 + NOP ; avoid cross-path stall + ADD $T1carry,$T1hi,$T1hi +;;===== branch to loop16_79? is taken here + +break?: + ADD $Ahi,$Actxhi,$Ahi ; accumulate ctx +|| ADDU $Alo,$Actxlo,$Actxlo:$Alo +|| [A0] LDNDW *$INP++,B11:B10 ; pre-fetch input +|| [A0] ADDK -640,$K512 ; rewind pointer to K512 + ADD $Bhi,$Bctxhi,$Bhi +|| ADDU $Blo,$Bctxlo,$Bctxlo:$Blo +|| [A0] LDDW *$K512++,$Khi:$Klo ; pre-fetch K512[0] + ADD $Chi,$Cctxhi,$Chi +|| ADDU $Clo,$Cctxlo,$Cctxlo:$Clo +|| ADD $Actxlo,$Ahi,$Ahi +||[!A0] MV $CTXA,$CTXB + ADD $Dhi,$Dctxhi,$Dhi +|| ADDU $Dlo,$Dctxlo,$Dctxlo:$Dlo +|| ADD $Bctxlo,$Bhi,$Bhi +||[!A0] STW $Ahi,*${CTXA}[0^.LITTLE_ENDIAN] ; save ctx +||[!A0] STW $Alo,*${CTXB}[1^.LITTLE_ENDIAN] + ADD $Ehi,$Ectxhi,$Ehi +|| ADDU $Elo,$Ectxlo,$Ectxlo:$Elo +|| ADD $Cctxlo,$Chi,$Chi +|| [A0] BNOP outerloop? +||[!A0] STW $Bhi,*${CTXA}[2^.LITTLE_ENDIAN] +||[!A0] STW $Blo,*${CTXB}[3^.LITTLE_ENDIAN] + ADD $Fhi,$Fctxhi,$Fhi +|| ADDU $Flo,$Fctxlo,$Fctxlo:$Flo +|| ADD $Dctxlo,$Dhi,$Dhi +||[!A0] STW $Chi,*${CTXA}[4^.LITTLE_ENDIAN] +||[!A0] STW $Clo,*${CTXB}[5^.LITTLE_ENDIAN] + ADD $Ghi,$Gctxhi,$Ghi +|| ADDU $Glo,$Gctxlo,$Gctxlo:$Glo +|| ADD $Ectxlo,$Ehi,$Ehi +||[!A0] STW $Dhi,*${CTXA}[6^.LITTLE_ENDIAN] +||[!A0] STW $Dlo,*${CTXB}[7^.LITTLE_ENDIAN] + ADD $Hhi,$Hctxhi,$Hhi +|| ADDU $Hlo,$Hctxlo,$Hctxlo:$Hlo +|| ADD $Fctxlo,$Fhi,$Fhi +||[!A0] STW $Ehi,*${CTXA}[8^.LITTLE_ENDIAN] +||[!A0] STW $Elo,*${CTXB}[9^.LITTLE_ENDIAN] + ADD $Gctxlo,$Ghi,$Ghi +||[!A0] STW $Fhi,*${CTXA}[10^.LITTLE_ENDIAN] +||[!A0] STW $Flo,*${CTXB}[11^.LITTLE_ENDIAN] + ADD $Hctxlo,$Hhi,$Hhi +||[!A0] STW $Ghi,*${CTXA}[12^.LITTLE_ENDIAN] +||[!A0] STW $Glo,*${CTXB}[13^.LITTLE_ENDIAN] +;;===== branch to outerloop? is taken here + + STW $Hhi,*${CTXA}[14^.LITTLE_ENDIAN] +|| STW $Hlo,*${CTXB}[15^.LITTLE_ENDIAN] +|| MVK -40,B0 + ADD FP,B0,SP ; destroy circular buffer +|| LDDW *FP[-4],A11:A10 + LDDW *SP[2],A13:A12 +|| LDDW *FP[-2],B11:B10 + LDDW *SP[4],B13:B12 +|| BNOP RA + LDW *++SP(40),FP ; restore frame pointer + MVK 0,B0 + MVC B0,AMR ; clear AMR + NOP 2 ; wait till FP is committed + .endasmfunc + + .if __TI_EABI__ + .sect ".text:sha_asm.const" + .else + .sect ".const:sha_asm" + .endif + .align 128 +K512: + .uword 0x428a2f98,0xd728ae22, 0x71374491,0x23ef65cd + .uword 0xb5c0fbcf,0xec4d3b2f, 0xe9b5dba5,0x8189dbbc + .uword 0x3956c25b,0xf348b538, 0x59f111f1,0xb605d019 + .uword 0x923f82a4,0xaf194f9b, 0xab1c5ed5,0xda6d8118 + .uword 0xd807aa98,0xa3030242, 0x12835b01,0x45706fbe + .uword 0x243185be,0x4ee4b28c, 0x550c7dc3,0xd5ffb4e2 + .uword 0x72be5d74,0xf27b896f, 0x80deb1fe,0x3b1696b1 + .uword 0x9bdc06a7,0x25c71235, 0xc19bf174,0xcf692694 + .uword 0xe49b69c1,0x9ef14ad2, 0xefbe4786,0x384f25e3 + .uword 0x0fc19dc6,0x8b8cd5b5, 0x240ca1cc,0x77ac9c65 + .uword 0x2de92c6f,0x592b0275, 0x4a7484aa,0x6ea6e483 + .uword 0x5cb0a9dc,0xbd41fbd4, 0x76f988da,0x831153b5 + .uword 0x983e5152,0xee66dfab, 0xa831c66d,0x2db43210 + .uword 0xb00327c8,0x98fb213f, 0xbf597fc7,0xbeef0ee4 + .uword 0xc6e00bf3,0x3da88fc2, 0xd5a79147,0x930aa725 + .uword 0x06ca6351,0xe003826f, 0x14292967,0x0a0e6e70 + .uword 0x27b70a85,0x46d22ffc, 0x2e1b2138,0x5c26c926 + .uword 0x4d2c6dfc,0x5ac42aed, 0x53380d13,0x9d95b3df + .uword 0x650a7354,0x8baf63de, 0x766a0abb,0x3c77b2a8 + .uword 0x81c2c92e,0x47edaee6, 0x92722c85,0x1482353b + .uword 0xa2bfe8a1,0x4cf10364, 0xa81a664b,0xbc423001 + .uword 0xc24b8b70,0xd0f89791, 0xc76c51a3,0x0654be30 + .uword 0xd192e819,0xd6ef5218, 0xd6990624,0x5565a910 + .uword 0xf40e3585,0x5771202a, 0x106aa070,0x32bbd1b8 + .uword 0x19a4c116,0xb8d2d0c8, 0x1e376c08,0x5141ab53 + .uword 0x2748774c,0xdf8eeb99, 0x34b0bcb5,0xe19b48a8 + .uword 0x391c0cb3,0xc5c95a63, 0x4ed8aa4a,0xe3418acb + .uword 0x5b9cca4f,0x7763e373, 0x682e6ff3,0xd6b2b8a3 + .uword 0x748f82ee,0x5defb2fc, 0x78a5636f,0x43172f60 + .uword 0x84c87814,0xa1f0ab72, 0x8cc70208,0x1a6439ec + .uword 0x90befffa,0x23631e28, 0xa4506ceb,0xde82bde9 + .uword 0xbef9a3f7,0xb2c67915, 0xc67178f2,0xe372532b + .uword 0xca273ece,0xea26619c, 0xd186b8c7,0x21c0c207 + .uword 0xeada7dd6,0xcde0eb1e, 0xf57d4f7f,0xee6ed178 + .uword 0x06f067aa,0x72176fba, 0x0a637dc5,0xa2c898a6 + .uword 0x113f9804,0xbef90dae, 0x1b710b35,0x131c471b + .uword 0x28db77f5,0x23047d84, 0x32caab7b,0x40c72493 + .uword 0x3c9ebe0a,0x15c9bebc, 0x431d67c4,0x9c100d4c + .uword 0x4cc5d4be,0xcb3e42b6, 0x597f299c,0xfc657e2a + .uword 0x5fcb6fab,0x3ad6faec, 0x6c44198c,0x4a475817 + .cstring "SHA512 block transform for C64x+, CRYPTOGAMS by " + .align 4 +___ + +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-ia64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-ia64.pl new file mode 100755 index 000000000..356a46ace --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-ia64.pl @@ -0,0 +1,692 @@ +#! /usr/bin/env perl +# Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# SHA256/512_Transform for Itanium. +# +# sha512_block runs in 1003 cycles on Itanium 2, which is almost 50% +# faster than gcc and >60%(!) faster than code generated by HP-UX +# compiler (yes, HP-UX is generating slower code, because unlike gcc, +# it failed to deploy "shift right pair," 'shrp' instruction, which +# substitutes for 64-bit rotate). +# +# 924 cycles long sha256_block outperforms gcc by over factor of 2(!) +# and HP-UX compiler - by >40% (yes, gcc won sha512_block, but lost +# this one big time). Note that "formally" 924 is about 100 cycles +# too much. I mean it's 64 32-bit rounds vs. 80 virtually identical +# 64-bit ones and 1003*64/80 gives 802. Extra cycles, 2 per round, +# are spent on extra work to provide for 32-bit rotations. 32-bit +# rotations are still handled by 'shrp' instruction and for this +# reason lower 32 bits are deposited to upper half of 64-bit register +# prior 'shrp' issue. And in order to minimize the amount of such +# operations, X[16] values are *maintained* with copies of lower +# halves in upper halves, which is why you'll spot such instructions +# as custom 'mux2', "parallel 32-bit add," 'padd4' and "parallel +# 32-bit unsigned right shift," 'pshr4.u' instructions here. +# +# Rules of engagement. +# +# There is only one integer shifter meaning that if I have two rotate, +# deposit or extract instructions in adjacent bundles, they shall +# split [at run-time if they have to]. But note that variable and +# parallel shifts are performed by multi-media ALU and *are* pairable +# with rotates [and alike]. On the backside MMALU is rather slow: it +# takes 2 extra cycles before the result of integer operation is +# available *to* MMALU and 2(*) extra cycles before the result of MM +# operation is available "back" *to* integer ALU, not to mention that +# MMALU itself has 2 cycles latency. However! I explicitly scheduled +# these MM instructions to avoid MM stalls, so that all these extra +# latencies get "hidden" in instruction-level parallelism. +# +# (*) 2 cycles on Itanium 1 and 1 cycle on Itanium 2. But I schedule +# for 2 in order to provide for best *overall* performance, +# because on Itanium 1 stall on MM result is accompanied by +# pipeline flush, which takes 6 cycles:-( +# +# June 2012 +# +# Improve performance by 15-20%. Note about "rules of engagement" +# above. Contemporary cores are equipped with additional shifter, +# so that they should perform even better than below, presumably +# by ~10%. +# +###################################################################### +# Current performance in cycles per processed byte for Itanium 2 +# pre-9000 series [little-endian] system: +# +# SHA1(*) 5.7 +# SHA256 12.6 +# SHA512 6.7 +# +# (*) SHA1 result is presented purely for reference purposes. +# +# To generate code, pass the file name with either 256 or 512 in its +# name and compiler flags. + +$output=pop; + +if ($output =~ /512.*\.[s|asm]/) { + $SZ=8; + $BITS=8*$SZ; + $LDW="ld8"; + $STW="st8"; + $ADD="add"; + $SHRU="shr.u"; + $TABLE="K512"; + $func="sha512_block_data_order"; + @Sigma0=(28,34,39); + @Sigma1=(14,18,41); + @sigma0=(1, 8, 7); + @sigma1=(19,61, 6); + $rounds=80; +} elsif ($output =~ /256.*\.[s|asm]/) { + $SZ=4; + $BITS=8*$SZ; + $LDW="ld4"; + $STW="st4"; + $ADD="padd4"; + $SHRU="pshr4.u"; + $TABLE="K256"; + $func="sha256_block_data_order"; + @Sigma0=( 2,13,22); + @Sigma1=( 6,11,25); + @sigma0=( 7,18, 3); + @sigma1=(17,19,10); + $rounds=64; +} else { die "nonsense $output"; } + +open STDOUT,">$output" || die "can't open $output: $!"; + +if ($^O eq "hpux") { + $ADDP="addp4"; + for (@ARGV) { $ADDP="add" if (/[\+DD|\-mlp]64/); } +} else { $ADDP="add"; } +for (@ARGV) { $big_endian=1 if (/\-DB_ENDIAN/); + $big_endian=0 if (/\-DL_ENDIAN/); } +if (!defined($big_endian)) + { $big_endian=(unpack('L',pack('N',1))==1); } + +$code=<<___; +.ident \"$output, version 2.0\" +.ident \"IA-64 ISA artwork by Andy Polyakov \" +.explicit +.text + +pfssave=r2; +lcsave=r3; +prsave=r14; +K=r15; +A_=r16; B_=r17; C_=r18; D_=r19; +E_=r20; F_=r21; G_=r22; H_=r23; +T1=r24; T2=r25; +s0=r26; s1=r27; t0=r28; t1=r29; +Ktbl=r30; +ctx=r31; // 1st arg +input=r56; // 2nd arg +num=r57; // 3rd arg +sgm0=r58; sgm1=r59; // small constants + +// void $func (SHA_CTX *ctx, const void *in,size_t num[,int host]) +.global $func# +.proc $func# +.align 32 +.skip 16 +$func: + .prologue + .save ar.pfs,pfssave +{ .mmi; alloc pfssave=ar.pfs,3,25,0,24 + $ADDP ctx=0,r32 // 1st arg + .save ar.lc,lcsave + mov lcsave=ar.lc } +{ .mmi; $ADDP input=0,r33 // 2nd arg + mov num=r34 // 3rd arg + .save pr,prsave + mov prsave=pr };; + + .body +{ .mib; add r8=0*$SZ,ctx + add r9=1*$SZ,ctx } +{ .mib; add r10=2*$SZ,ctx + add r11=3*$SZ,ctx };; + +// load A-H +.Lpic_point: +{ .mmi; $LDW A_=[r8],4*$SZ + $LDW B_=[r9],4*$SZ + mov Ktbl=ip } +{ .mmi; $LDW C_=[r10],4*$SZ + $LDW D_=[r11],4*$SZ + mov sgm0=$sigma0[2] };; +{ .mmi; $LDW E_=[r8] + $LDW F_=[r9] + add Ktbl=($TABLE#-.Lpic_point),Ktbl } +{ .mmi; $LDW G_=[r10] + $LDW H_=[r11] + cmp.ne p0,p16=0,r0 };; +___ +$code.=<<___ if ($BITS==64); +{ .mii; and r8=7,input + and input=~7,input;; + cmp.eq p9,p0=1,r8 } +{ .mmi; cmp.eq p10,p0=2,r8 + cmp.eq p11,p0=3,r8 + cmp.eq p12,p0=4,r8 } +{ .mmi; cmp.eq p13,p0=5,r8 + cmp.eq p14,p0=6,r8 + cmp.eq p15,p0=7,r8 };; +___ +$code.=<<___; +.L_outer: +.rotr R[8],X[16] +A=R[0]; B=R[1]; C=R[2]; D=R[3]; E=R[4]; F=R[5]; G=R[6]; H=R[7] +{ .mmi; ld1 X[15]=[input],$SZ // eliminated in sha512 + mov A=A_ + mov ar.lc=14 } +{ .mmi; mov B=B_ + mov C=C_ + mov D=D_ } +{ .mmi; mov E=E_ + mov F=F_ + mov ar.ec=2 };; +{ .mmi; mov G=G_ + mov H=H_ + mov sgm1=$sigma1[2] } +{ .mib; mov r8=0 + add r9=1-$SZ,input + brp.loop.imp .L_first16,.L_first16_end-16 };; +___ +$t0="A", $t1="E", $code.=<<___ if ($BITS==64); +// in sha512 case I load whole X[16] at once and take care of alignment... +{ .mmi; add r8=1*$SZ,input + add r9=2*$SZ,input + add r10=3*$SZ,input };; +{ .mmb; $LDW X[15]=[input],4*$SZ + $LDW X[14]=[r8],4*$SZ +(p9) br.cond.dpnt.many .L1byte };; +{ .mmb; $LDW X[13]=[r9],4*$SZ + $LDW X[12]=[r10],4*$SZ +(p10) br.cond.dpnt.many .L2byte };; +{ .mmb; $LDW X[11]=[input],4*$SZ + $LDW X[10]=[r8],4*$SZ +(p11) br.cond.dpnt.many .L3byte };; +{ .mmb; $LDW X[ 9]=[r9],4*$SZ + $LDW X[ 8]=[r10],4*$SZ +(p12) br.cond.dpnt.many .L4byte };; +{ .mmb; $LDW X[ 7]=[input],4*$SZ + $LDW X[ 6]=[r8],4*$SZ +(p13) br.cond.dpnt.many .L5byte };; +{ .mmb; $LDW X[ 5]=[r9],4*$SZ + $LDW X[ 4]=[r10],4*$SZ +(p14) br.cond.dpnt.many .L6byte };; +{ .mmb; $LDW X[ 3]=[input],4*$SZ + $LDW X[ 2]=[r8],4*$SZ +(p15) br.cond.dpnt.many .L7byte };; +{ .mmb; $LDW X[ 1]=[r9],4*$SZ + $LDW X[ 0]=[r10],4*$SZ } +{ .mib; mov r8=0 + mux1 X[15]=X[15],\@rev // eliminated on big-endian + br.many .L_first16 };; +.L1byte: +{ .mmi; $LDW X[13]=[r9],4*$SZ + $LDW X[12]=[r10],4*$SZ + shrp X[15]=X[15],X[14],56 };; +{ .mmi; $LDW X[11]=[input],4*$SZ + $LDW X[10]=[r8],4*$SZ + shrp X[14]=X[14],X[13],56 } +{ .mmi; $LDW X[ 9]=[r9],4*$SZ + $LDW X[ 8]=[r10],4*$SZ + shrp X[13]=X[13],X[12],56 };; +{ .mmi; $LDW X[ 7]=[input],4*$SZ + $LDW X[ 6]=[r8],4*$SZ + shrp X[12]=X[12],X[11],56 } +{ .mmi; $LDW X[ 5]=[r9],4*$SZ + $LDW X[ 4]=[r10],4*$SZ + shrp X[11]=X[11],X[10],56 };; +{ .mmi; $LDW X[ 3]=[input],4*$SZ + $LDW X[ 2]=[r8],4*$SZ + shrp X[10]=X[10],X[ 9],56 } +{ .mmi; $LDW X[ 1]=[r9],4*$SZ + $LDW X[ 0]=[r10],4*$SZ + shrp X[ 9]=X[ 9],X[ 8],56 };; +{ .mii; $LDW T1=[input] + shrp X[ 8]=X[ 8],X[ 7],56 + shrp X[ 7]=X[ 7],X[ 6],56 } +{ .mii; shrp X[ 6]=X[ 6],X[ 5],56 + shrp X[ 5]=X[ 5],X[ 4],56 };; +{ .mii; shrp X[ 4]=X[ 4],X[ 3],56 + shrp X[ 3]=X[ 3],X[ 2],56 } +{ .mii; shrp X[ 2]=X[ 2],X[ 1],56 + shrp X[ 1]=X[ 1],X[ 0],56 } +{ .mib; shrp X[ 0]=X[ 0],T1,56 } +{ .mib; mov r8=0 + mux1 X[15]=X[15],\@rev // eliminated on big-endian + br.many .L_first16 };; +.L2byte: +{ .mmi; $LDW X[11]=[input],4*$SZ + $LDW X[10]=[r8],4*$SZ + shrp X[15]=X[15],X[14],48 } +{ .mmi; $LDW X[ 9]=[r9],4*$SZ + $LDW X[ 8]=[r10],4*$SZ + shrp X[14]=X[14],X[13],48 };; +{ .mmi; $LDW X[ 7]=[input],4*$SZ + $LDW X[ 6]=[r8],4*$SZ + shrp X[13]=X[13],X[12],48 } +{ .mmi; $LDW X[ 5]=[r9],4*$SZ + $LDW X[ 4]=[r10],4*$SZ + shrp X[12]=X[12],X[11],48 };; +{ .mmi; $LDW X[ 3]=[input],4*$SZ + $LDW X[ 2]=[r8],4*$SZ + shrp X[11]=X[11],X[10],48 } +{ .mmi; $LDW X[ 1]=[r9],4*$SZ + $LDW X[ 0]=[r10],4*$SZ + shrp X[10]=X[10],X[ 9],48 };; +{ .mii; $LDW T1=[input] + shrp X[ 9]=X[ 9],X[ 8],48 + shrp X[ 8]=X[ 8],X[ 7],48 } +{ .mii; shrp X[ 7]=X[ 7],X[ 6],48 + shrp X[ 6]=X[ 6],X[ 5],48 };; +{ .mii; shrp X[ 5]=X[ 5],X[ 4],48 + shrp X[ 4]=X[ 4],X[ 3],48 } +{ .mii; shrp X[ 3]=X[ 3],X[ 2],48 + shrp X[ 2]=X[ 2],X[ 1],48 } +{ .mii; shrp X[ 1]=X[ 1],X[ 0],48 + shrp X[ 0]=X[ 0],T1,48 } +{ .mib; mov r8=0 + mux1 X[15]=X[15],\@rev // eliminated on big-endian + br.many .L_first16 };; +.L3byte: +{ .mmi; $LDW X[ 9]=[r9],4*$SZ + $LDW X[ 8]=[r10],4*$SZ + shrp X[15]=X[15],X[14],40 };; +{ .mmi; $LDW X[ 7]=[input],4*$SZ + $LDW X[ 6]=[r8],4*$SZ + shrp X[14]=X[14],X[13],40 } +{ .mmi; $LDW X[ 5]=[r9],4*$SZ + $LDW X[ 4]=[r10],4*$SZ + shrp X[13]=X[13],X[12],40 };; +{ .mmi; $LDW X[ 3]=[input],4*$SZ + $LDW X[ 2]=[r8],4*$SZ + shrp X[12]=X[12],X[11],40 } +{ .mmi; $LDW X[ 1]=[r9],4*$SZ + $LDW X[ 0]=[r10],4*$SZ + shrp X[11]=X[11],X[10],40 };; +{ .mii; $LDW T1=[input] + shrp X[10]=X[10],X[ 9],40 + shrp X[ 9]=X[ 9],X[ 8],40 } +{ .mii; shrp X[ 8]=X[ 8],X[ 7],40 + shrp X[ 7]=X[ 7],X[ 6],40 };; +{ .mii; shrp X[ 6]=X[ 6],X[ 5],40 + shrp X[ 5]=X[ 5],X[ 4],40 } +{ .mii; shrp X[ 4]=X[ 4],X[ 3],40 + shrp X[ 3]=X[ 3],X[ 2],40 } +{ .mii; shrp X[ 2]=X[ 2],X[ 1],40 + shrp X[ 1]=X[ 1],X[ 0],40 } +{ .mib; shrp X[ 0]=X[ 0],T1,40 } +{ .mib; mov r8=0 + mux1 X[15]=X[15],\@rev // eliminated on big-endian + br.many .L_first16 };; +.L4byte: +{ .mmi; $LDW X[ 7]=[input],4*$SZ + $LDW X[ 6]=[r8],4*$SZ + shrp X[15]=X[15],X[14],32 } +{ .mmi; $LDW X[ 5]=[r9],4*$SZ + $LDW X[ 4]=[r10],4*$SZ + shrp X[14]=X[14],X[13],32 };; +{ .mmi; $LDW X[ 3]=[input],4*$SZ + $LDW X[ 2]=[r8],4*$SZ + shrp X[13]=X[13],X[12],32 } +{ .mmi; $LDW X[ 1]=[r9],4*$SZ + $LDW X[ 0]=[r10],4*$SZ + shrp X[12]=X[12],X[11],32 };; +{ .mii; $LDW T1=[input] + shrp X[11]=X[11],X[10],32 + shrp X[10]=X[10],X[ 9],32 } +{ .mii; shrp X[ 9]=X[ 9],X[ 8],32 + shrp X[ 8]=X[ 8],X[ 7],32 };; +{ .mii; shrp X[ 7]=X[ 7],X[ 6],32 + shrp X[ 6]=X[ 6],X[ 5],32 } +{ .mii; shrp X[ 5]=X[ 5],X[ 4],32 + shrp X[ 4]=X[ 4],X[ 3],32 } +{ .mii; shrp X[ 3]=X[ 3],X[ 2],32 + shrp X[ 2]=X[ 2],X[ 1],32 } +{ .mii; shrp X[ 1]=X[ 1],X[ 0],32 + shrp X[ 0]=X[ 0],T1,32 } +{ .mib; mov r8=0 + mux1 X[15]=X[15],\@rev // eliminated on big-endian + br.many .L_first16 };; +.L5byte: +{ .mmi; $LDW X[ 5]=[r9],4*$SZ + $LDW X[ 4]=[r10],4*$SZ + shrp X[15]=X[15],X[14],24 };; +{ .mmi; $LDW X[ 3]=[input],4*$SZ + $LDW X[ 2]=[r8],4*$SZ + shrp X[14]=X[14],X[13],24 } +{ .mmi; $LDW X[ 1]=[r9],4*$SZ + $LDW X[ 0]=[r10],4*$SZ + shrp X[13]=X[13],X[12],24 };; +{ .mii; $LDW T1=[input] + shrp X[12]=X[12],X[11],24 + shrp X[11]=X[11],X[10],24 } +{ .mii; shrp X[10]=X[10],X[ 9],24 + shrp X[ 9]=X[ 9],X[ 8],24 };; +{ .mii; shrp X[ 8]=X[ 8],X[ 7],24 + shrp X[ 7]=X[ 7],X[ 6],24 } +{ .mii; shrp X[ 6]=X[ 6],X[ 5],24 + shrp X[ 5]=X[ 5],X[ 4],24 } +{ .mii; shrp X[ 4]=X[ 4],X[ 3],24 + shrp X[ 3]=X[ 3],X[ 2],24 } +{ .mii; shrp X[ 2]=X[ 2],X[ 1],24 + shrp X[ 1]=X[ 1],X[ 0],24 } +{ .mib; shrp X[ 0]=X[ 0],T1,24 } +{ .mib; mov r8=0 + mux1 X[15]=X[15],\@rev // eliminated on big-endian + br.many .L_first16 };; +.L6byte: +{ .mmi; $LDW X[ 3]=[input],4*$SZ + $LDW X[ 2]=[r8],4*$SZ + shrp X[15]=X[15],X[14],16 } +{ .mmi; $LDW X[ 1]=[r9],4*$SZ + $LDW X[ 0]=[r10],4*$SZ + shrp X[14]=X[14],X[13],16 };; +{ .mii; $LDW T1=[input] + shrp X[13]=X[13],X[12],16 + shrp X[12]=X[12],X[11],16 } +{ .mii; shrp X[11]=X[11],X[10],16 + shrp X[10]=X[10],X[ 9],16 };; +{ .mii; shrp X[ 9]=X[ 9],X[ 8],16 + shrp X[ 8]=X[ 8],X[ 7],16 } +{ .mii; shrp X[ 7]=X[ 7],X[ 6],16 + shrp X[ 6]=X[ 6],X[ 5],16 } +{ .mii; shrp X[ 5]=X[ 5],X[ 4],16 + shrp X[ 4]=X[ 4],X[ 3],16 } +{ .mii; shrp X[ 3]=X[ 3],X[ 2],16 + shrp X[ 2]=X[ 2],X[ 1],16 } +{ .mii; shrp X[ 1]=X[ 1],X[ 0],16 + shrp X[ 0]=X[ 0],T1,16 } +{ .mib; mov r8=0 + mux1 X[15]=X[15],\@rev // eliminated on big-endian + br.many .L_first16 };; +.L7byte: +{ .mmi; $LDW X[ 1]=[r9],4*$SZ + $LDW X[ 0]=[r10],4*$SZ + shrp X[15]=X[15],X[14],8 };; +{ .mii; $LDW T1=[input] + shrp X[14]=X[14],X[13],8 + shrp X[13]=X[13],X[12],8 } +{ .mii; shrp X[12]=X[12],X[11],8 + shrp X[11]=X[11],X[10],8 };; +{ .mii; shrp X[10]=X[10],X[ 9],8 + shrp X[ 9]=X[ 9],X[ 8],8 } +{ .mii; shrp X[ 8]=X[ 8],X[ 7],8 + shrp X[ 7]=X[ 7],X[ 6],8 } +{ .mii; shrp X[ 6]=X[ 6],X[ 5],8 + shrp X[ 5]=X[ 5],X[ 4],8 } +{ .mii; shrp X[ 4]=X[ 4],X[ 3],8 + shrp X[ 3]=X[ 3],X[ 2],8 } +{ .mii; shrp X[ 2]=X[ 2],X[ 1],8 + shrp X[ 1]=X[ 1],X[ 0],8 } +{ .mib; shrp X[ 0]=X[ 0],T1,8 } +{ .mib; mov r8=0 + mux1 X[15]=X[15],\@rev };; // eliminated on big-endian + +.align 32 +.L_first16: +{ .mmi; $LDW K=[Ktbl],$SZ + add A=A,r8 // H+=Sigma(0) from the past + _rotr r10=$t1,$Sigma1[0] } // ROTR(e,14) +{ .mmi; and T1=F,E + andcm r8=G,E + (p16) mux1 X[14]=X[14],\@rev };; // eliminated on big-endian +{ .mmi; and T2=A,B + and r9=A,C + _rotr r11=$t1,$Sigma1[1] } // ROTR(e,41) +{ .mmi; xor T1=T1,r8 // T1=((e & f) ^ (~e & g)) + and r8=B,C };; +___ +$t0="t0", $t1="t1", $code.=<<___ if ($BITS==32); +.align 32 +.L_first16: +{ .mmi; add A=A,r8 // H+=Sigma(0) from the past + add r10=2-$SZ,input + add r11=3-$SZ,input };; +{ .mmi; ld1 r9=[r9] + ld1 r10=[r10] + dep.z $t1=E,32,32 } +{ .mmi; ld1 r11=[r11] + $LDW K=[Ktbl],$SZ + zxt4 E=E };; +{ .mii; or $t1=$t1,E + dep X[15]=X[15],r9,8,8 + mux2 $t0=A,0x44 };; // copy lower half to upper +{ .mmi; and T1=F,E + andcm r8=G,E + dep r11=r10,r11,8,8 };; +{ .mmi; and T2=A,B + and r9=A,C + dep X[15]=X[15],r11,16,16 };; +{ .mmi; (p16) ld1 X[15-1]=[input],$SZ // prefetch + xor T1=T1,r8 // T1=((e & f) ^ (~e & g)) + _rotr r10=$t1,$Sigma1[0] } // ROTR(e,14) +{ .mmi; and r8=B,C + _rotr r11=$t1,$Sigma1[1] };; // ROTR(e,18) +___ +$code.=<<___; +{ .mmi; add T1=T1,H // T1=Ch(e,f,g)+h + xor r10=r10,r11 + _rotr r11=$t1,$Sigma1[2] } // ROTR(e,41) +{ .mmi; xor T2=T2,r9 + add K=K,X[15] };; +{ .mmi; add T1=T1,K // T1+=K[i]+X[i] + xor T2=T2,r8 // T2=((a & b) ^ (a & c) ^ (b & c)) + _rotr r8=$t0,$Sigma0[0] } // ROTR(a,28) +{ .mmi; xor r11=r11,r10 // Sigma1(e) + _rotr r9=$t0,$Sigma0[1] };; // ROTR(a,34) +{ .mmi; add T1=T1,r11 // T+=Sigma1(e) + xor r8=r8,r9 + _rotr r9=$t0,$Sigma0[2] };; // ROTR(a,39) +{ .mmi; xor r8=r8,r9 // Sigma0(a) + add D=D,T1 + mux2 H=X[15],0x44 } // mov H=X[15] in sha512 +{ .mib; (p16) add r9=1-$SZ,input // not used in sha512 + add X[15]=T1,T2 // H=T1+Maj(a,b,c) + br.ctop.sptk .L_first16 };; +.L_first16_end: + +{ .mib; mov ar.lc=$rounds-17 + brp.loop.imp .L_rest,.L_rest_end-16 } +{ .mib; mov ar.ec=1 + br.many .L_rest };; + +.align 32 +.L_rest: +{ .mmi; $LDW K=[Ktbl],$SZ + add A=A,r8 // H+=Sigma0(a) from the past + _rotr r8=X[15-1],$sigma0[0] } // ROTR(s0,1) +{ .mmi; add X[15]=X[15],X[15-9] // X[i&0xF]+=X[(i+9)&0xF] + $SHRU s0=X[15-1],sgm0 };; // s0=X[(i+1)&0xF]>>7 +{ .mib; and T1=F,E + _rotr r9=X[15-1],$sigma0[1] } // ROTR(s0,8) +{ .mib; andcm r10=G,E + $SHRU s1=X[15-14],sgm1 };; // s1=X[(i+14)&0xF]>>6 +// Pair of mmi; splits on Itanium 1 and prevents pipeline flush +// upon $SHRU output usage +{ .mmi; xor T1=T1,r10 // T1=((e & f) ^ (~e & g)) + xor r9=r8,r9 + _rotr r10=X[15-14],$sigma1[0] }// ROTR(s1,19) +{ .mmi; and T2=A,B + and r8=A,C + _rotr r11=X[15-14],$sigma1[1] };;// ROTR(s1,61) +___ +$t0="t0", $t1="t1", $code.=<<___ if ($BITS==32); +{ .mib; xor s0=s0,r9 // s0=sigma0(X[(i+1)&0xF]) + dep.z $t1=E,32,32 } +{ .mib; xor r10=r11,r10 + zxt4 E=E };; +{ .mii; xor s1=s1,r10 // s1=sigma1(X[(i+14)&0xF]) + shrp r9=E,$t1,32+$Sigma1[0] // ROTR(e,14) + mux2 $t0=A,0x44 };; // copy lower half to upper +// Pair of mmi; splits on Itanium 1 and prevents pipeline flush +// upon mux2 output usage +{ .mmi; xor T2=T2,r8 + shrp r8=E,$t1,32+$Sigma1[1]} // ROTR(e,18) +{ .mmi; and r10=B,C + add T1=T1,H // T1=Ch(e,f,g)+h + or $t1=$t1,E };; +___ +$t0="A", $t1="E", $code.=<<___ if ($BITS==64); +{ .mib; xor s0=s0,r9 // s0=sigma0(X[(i+1)&0xF]) + _rotr r9=$t1,$Sigma1[0] } // ROTR(e,14) +{ .mib; xor r10=r11,r10 + xor T2=T2,r8 };; +{ .mib; xor s1=s1,r10 // s1=sigma1(X[(i+14)&0xF]) + _rotr r8=$t1,$Sigma1[1] } // ROTR(e,18) +{ .mib; and r10=B,C + add T1=T1,H };; // T1+=H +___ +$code.=<<___; +{ .mib; xor r9=r9,r8 + _rotr r8=$t1,$Sigma1[2] } // ROTR(e,41) +{ .mib; xor T2=T2,r10 // T2=((a & b) ^ (a & c) ^ (b & c)) + add X[15]=X[15],s0 };; // X[i]+=sigma0(X[i+1]) +{ .mmi; xor r9=r9,r8 // Sigma1(e) + add X[15]=X[15],s1 // X[i]+=sigma0(X[i+14]) + _rotr r8=$t0,$Sigma0[0] };; // ROTR(a,28) +{ .mmi; add K=K,X[15] + add T1=T1,r9 // T1+=Sigma1(e) + _rotr r9=$t0,$Sigma0[1] };; // ROTR(a,34) +{ .mmi; add T1=T1,K // T1+=K[i]+X[i] + xor r8=r8,r9 + _rotr r9=$t0,$Sigma0[2] };; // ROTR(a,39) +{ .mib; add D=D,T1 + mux2 H=X[15],0x44 } // mov H=X[15] in sha512 +{ .mib; xor r8=r8,r9 // Sigma0(a) + add X[15]=T1,T2 // H=T1+Maj(a,b,c) + br.ctop.sptk .L_rest };; +.L_rest_end: + +{ .mmi; add A=A,r8 };; // H+=Sigma0(a) from the past +{ .mmi; add A_=A_,A + add B_=B_,B + add C_=C_,C } +{ .mmi; add D_=D_,D + add E_=E_,E + cmp.ltu p16,p0=1,num };; +{ .mmi; add F_=F_,F + add G_=G_,G + add H_=H_,H } +{ .mmb; add Ktbl=-$SZ*$rounds,Ktbl +(p16) add num=-1,num +(p16) br.dptk.many .L_outer };; + +{ .mib; add r8=0*$SZ,ctx + add r9=1*$SZ,ctx } +{ .mib; add r10=2*$SZ,ctx + add r11=3*$SZ,ctx };; +{ .mmi; $STW [r8]=A_,4*$SZ + $STW [r9]=B_,4*$SZ + mov ar.lc=lcsave } +{ .mmi; $STW [r10]=C_,4*$SZ + $STW [r11]=D_,4*$SZ + mov pr=prsave,0x1ffff };; +{ .mmb; $STW [r8]=E_ + $STW [r9]=F_ } +{ .mmb; $STW [r10]=G_ + $STW [r11]=H_ + br.ret.sptk.many b0 };; +.endp $func# +___ + +foreach(split($/,$code)) { + s/\`([^\`]*)\`/eval $1/gem; + s/_rotr(\s+)([^=]+)=([^,]+),([0-9]+)/shrp$1$2=$3,$3,$4/gm; + if ($BITS==64) { + s/mux2(\s+)([^=]+)=([^,]+),\S+/mov$1 $2=$3/gm; + s/mux1(\s+)\S+/nop.i$1 0x0/gm if ($big_endian); + s/(shrp\s+X\[[^=]+)=([^,]+),([^,]+),([1-9]+)/$1=$3,$2,64-$4/gm + if (!$big_endian); + s/ld1(\s+)X\[\S+/nop.m$1 0x0/gm; + } + + print $_,"\n"; +} + +print<<___ if ($BITS==32); +.align 64 +.type K256#,\@object +K256: data4 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 + data4 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 + data4 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 + data4 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 + data4 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc + data4 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da + data4 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 + data4 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967 + data4 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 + data4 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 + data4 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 + data4 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 + data4 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 + data4 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 + data4 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 + data4 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 +.size K256#,$SZ*$rounds +stringz "SHA256 block transform for IA64, CRYPTOGAMS by " +___ +print<<___ if ($BITS==64); +.align 64 +.type K512#,\@object +K512: data8 0x428a2f98d728ae22,0x7137449123ef65cd + data8 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc + data8 0x3956c25bf348b538,0x59f111f1b605d019 + data8 0x923f82a4af194f9b,0xab1c5ed5da6d8118 + data8 0xd807aa98a3030242,0x12835b0145706fbe + data8 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 + data8 0x72be5d74f27b896f,0x80deb1fe3b1696b1 + data8 0x9bdc06a725c71235,0xc19bf174cf692694 + data8 0xe49b69c19ef14ad2,0xefbe4786384f25e3 + data8 0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65 + data8 0x2de92c6f592b0275,0x4a7484aa6ea6e483 + data8 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 + data8 0x983e5152ee66dfab,0xa831c66d2db43210 + data8 0xb00327c898fb213f,0xbf597fc7beef0ee4 + data8 0xc6e00bf33da88fc2,0xd5a79147930aa725 + data8 0x06ca6351e003826f,0x142929670a0e6e70 + data8 0x27b70a8546d22ffc,0x2e1b21385c26c926 + data8 0x4d2c6dfc5ac42aed,0x53380d139d95b3df + data8 0x650a73548baf63de,0x766a0abb3c77b2a8 + data8 0x81c2c92e47edaee6,0x92722c851482353b + data8 0xa2bfe8a14cf10364,0xa81a664bbc423001 + data8 0xc24b8b70d0f89791,0xc76c51a30654be30 + data8 0xd192e819d6ef5218,0xd69906245565a910 + data8 0xf40e35855771202a,0x106aa07032bbd1b8 + data8 0x19a4c116b8d2d0c8,0x1e376c085141ab53 + data8 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 + data8 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb + data8 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 + data8 0x748f82ee5defb2fc,0x78a5636f43172f60 + data8 0x84c87814a1f0ab72,0x8cc702081a6439ec + data8 0x90befffa23631e28,0xa4506cebde82bde9 + data8 0xbef9a3f7b2c67915,0xc67178f2e372532b + data8 0xca273eceea26619c,0xd186b8c721c0c207 + data8 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 + data8 0x06f067aa72176fba,0x0a637dc5a2c898a6 + data8 0x113f9804bef90dae,0x1b710b35131c471b + data8 0x28db77f523047d84,0x32caab7b40c72493 + data8 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c + data8 0x4cc5d4becb3e42b6,0x597f299cfc657e2a + data8 0x5fcb6fab3ad6faec,0x6c44198c4a475817 +.size K512#,$SZ*$rounds +stringz "SHA512 block transform for IA64, CRYPTOGAMS by " +___ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-mips.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-mips.pl new file mode 100644 index 000000000..dab684dde --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-mips.pl @@ -0,0 +1,521 @@ +#! /usr/bin/env perl +# Copyright 2010-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# SHA2 block procedures for MIPS. + +# October 2010. +# +# SHA256 performance improvement on MIPS R5000 CPU is ~27% over gcc- +# generated code in o32 build and ~55% in n32/64 build. SHA512 [which +# for now can only be compiled for MIPS64 ISA] improvement is modest +# ~17%, but it comes for free, because it's same instruction sequence. +# Improvement coefficients are for aligned input. + +# September 2012. +# +# Add MIPS[32|64]R2 code (>25% less instructions). + +###################################################################### +# There is a number of MIPS ABI in use, O32 and N32/64 are most +# widely used. Then there is a new contender: NUBI. It appears that if +# one picks the latter, it's possible to arrange code in ABI neutral +# manner. Therefore let's stick to NUBI register layout: +# +($zero,$at,$t0,$t1,$t2)=map("\$$_",(0..2,24,25)); +($a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7)=map("\$$_",(4..11)); +($s0,$s1,$s2,$s3,$s4,$s5,$s6,$s7,$s8,$s9,$s10,$s11)=map("\$$_",(12..23)); +($gp,$tp,$sp,$fp,$ra)=map("\$$_",(3,28..31)); +# +# The return value is placed in $a0. Following coding rules facilitate +# interoperability: +# +# - never ever touch $tp, "thread pointer", former $gp [o32 can be +# excluded from the rule, because it's specified volatile]; +# - copy return value to $t0, former $v0 [or to $a0 if you're adapting +# old code]; +# - on O32 populate $a4-$a7 with 'lw $aN,4*N($sp)' if necessary; +# +# For reference here is register layout for N32/64 MIPS ABIs: +# +# ($zero,$at,$v0,$v1)=map("\$$_",(0..3)); +# ($a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7)=map("\$$_",(4..11)); +# ($t0,$t1,$t2,$t3,$t8,$t9)=map("\$$_",(12..15,24,25)); +# ($s0,$s1,$s2,$s3,$s4,$s5,$s6,$s7)=map("\$$_",(16..23)); +# ($gp,$sp,$fp,$ra)=map("\$$_",(28..31)); +# +$flavour = shift || "o32"; # supported flavours are o32,n32,64,nubi32,nubi64 + +if ($flavour =~ /64|n32/i) { + $PTR_LA="dla"; + $PTR_ADD="daddu"; # incidentally works even on n32 + $PTR_SUB="dsubu"; # incidentally works even on n32 + $REG_S="sd"; + $REG_L="ld"; + $PTR_SLL="dsll"; # incidentally works even on n32 + $SZREG=8; +} else { + $PTR_LA="la"; + $PTR_ADD="addu"; + $PTR_SUB="subu"; + $REG_S="sw"; + $REG_L="lw"; + $PTR_SLL="sll"; + $SZREG=4; +} +$pf = ($flavour =~ /nubi/i) ? $t0 : $t2; +# +# +# +###################################################################### + +$big_endian=(`echo MIPSEB | $ENV{CC} -E -`=~/MIPSEB/)?0:1 if ($ENV{CC}); + +for (@ARGV) { $output=$_ if (/\w[\w\-]*\.\w+$/); } +open STDOUT,">$output"; + +if (!defined($big_endian)) { $big_endian=(unpack('L',pack('N',1))==1); } + +if ($output =~ /512/) { + $label="512"; + $SZ=8; + $LD="ld"; # load from memory + $ST="sd"; # store to memory + $SLL="dsll"; # shift left logical + $SRL="dsrl"; # shift right logical + $ADDU="daddu"; + $ROTR="drotr"; + @Sigma0=(28,34,39); + @Sigma1=(14,18,41); + @sigma0=( 7, 1, 8); # right shift first + @sigma1=( 6,19,61); # right shift first + $lastK=0x817; + $rounds=80; +} else { + $label="256"; + $SZ=4; + $LD="lw"; # load from memory + $ST="sw"; # store to memory + $SLL="sll"; # shift left logical + $SRL="srl"; # shift right logical + $ADDU="addu"; + $ROTR="rotr"; + @Sigma0=( 2,13,22); + @Sigma1=( 6,11,25); + @sigma0=( 3, 7,18); # right shift first + @sigma1=(10,17,19); # right shift first + $lastK=0x8f2; + $rounds=64; +} + +$MSB = $big_endian ? 0 : ($SZ-1); +$LSB = ($SZ-1)&~$MSB; + +@V=($A,$B,$C,$D,$E,$F,$G,$H)=map("\$$_",(1,2,3,7,24,25,30,31)); +@X=map("\$$_",(8..23)); + +$ctx=$a0; +$inp=$a1; +$len=$a2; $Ktbl=$len; + +sub BODY_00_15 { +my ($i,$a,$b,$c,$d,$e,$f,$g,$h)=@_; +my ($T1,$tmp0,$tmp1,$tmp2)=(@X[4],@X[5],@X[6],@X[7]); + +$code.=<<___ if ($i<15); +#if defined(_MIPS_ARCH_MIPS32R6) || defined(_MIPS_ARCH_MIPS64R6) + ${LD} @X[1],`($i+1)*$SZ`($inp) +#else + ${LD}l @X[1],`($i+1)*$SZ+$MSB`($inp) + ${LD}r @X[1],`($i+1)*$SZ+$LSB`($inp) +#endif +___ +$code.=<<___ if (!$big_endian && $i<16 && $SZ==4); +#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2) + wsbh @X[0],@X[0] # byte swap($i) + rotr @X[0],@X[0],16 +#else + srl $tmp0,@X[0],24 # byte swap($i) + srl $tmp1,@X[0],8 + andi $tmp2,@X[0],0xFF00 + sll @X[0],@X[0],24 + andi $tmp1,0xFF00 + sll $tmp2,$tmp2,8 + or @X[0],$tmp0 + or $tmp1,$tmp2 + or @X[0],$tmp1 +#endif +___ +$code.=<<___ if (!$big_endian && $i<16 && $SZ==8); +#if defined(_MIPS_ARCH_MIPS64R2) + dsbh @X[0],@X[0] # byte swap($i) + dshd @X[0],@X[0] +#else + ori $tmp0,$zero,0xFF + dsll $tmp2,$tmp0,32 + or $tmp0,$tmp2 # 0x000000FF000000FF + and $tmp1,@X[0],$tmp0 # byte swap($i) + dsrl $tmp2,@X[0],24 + dsll $tmp1,24 + and $tmp2,$tmp0 + dsll $tmp0,8 # 0x0000FF000000FF00 + or $tmp1,$tmp2 + and $tmp2,@X[0],$tmp0 + dsrl @X[0],8 + dsll $tmp2,8 + and @X[0],$tmp0 + or $tmp1,$tmp2 + or @X[0],$tmp1 + dsrl $tmp1,@X[0],32 + dsll @X[0],32 + or @X[0],$tmp1 +#endif +___ +$code.=<<___; +#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2) + xor $tmp2,$f,$g # $i + $ROTR $tmp0,$e,@Sigma1[0] + $ADDU $T1,$X[0],$h + $ROTR $tmp1,$e,@Sigma1[1] + and $tmp2,$e + $ROTR $h,$e,@Sigma1[2] + xor $tmp0,$tmp1 + $ROTR $tmp1,$a,@Sigma0[0] + xor $tmp2,$g # Ch(e,f,g) + xor $tmp0,$h # Sigma1(e) + + $ROTR $h,$a,@Sigma0[1] + $ADDU $T1,$tmp2 + $LD $tmp2,`$i*$SZ`($Ktbl) # K[$i] + xor $h,$tmp1 + $ROTR $tmp1,$a,@Sigma0[2] + $ADDU $T1,$tmp0 + and $tmp0,$b,$c + xor $h,$tmp1 # Sigma0(a) + xor $tmp1,$b,$c +#else + $ADDU $T1,$X[0],$h # $i + $SRL $h,$e,@Sigma1[0] + xor $tmp2,$f,$g + $SLL $tmp1,$e,`$SZ*8-@Sigma1[2]` + and $tmp2,$e + $SRL $tmp0,$e,@Sigma1[1] + xor $h,$tmp1 + $SLL $tmp1,$e,`$SZ*8-@Sigma1[1]` + xor $h,$tmp0 + $SRL $tmp0,$e,@Sigma1[2] + xor $h,$tmp1 + $SLL $tmp1,$e,`$SZ*8-@Sigma1[0]` + xor $h,$tmp0 + xor $tmp2,$g # Ch(e,f,g) + xor $tmp0,$tmp1,$h # Sigma1(e) + + $SRL $h,$a,@Sigma0[0] + $ADDU $T1,$tmp2 + $LD $tmp2,`$i*$SZ`($Ktbl) # K[$i] + $SLL $tmp1,$a,`$SZ*8-@Sigma0[2]` + $ADDU $T1,$tmp0 + $SRL $tmp0,$a,@Sigma0[1] + xor $h,$tmp1 + $SLL $tmp1,$a,`$SZ*8-@Sigma0[1]` + xor $h,$tmp0 + $SRL $tmp0,$a,@Sigma0[2] + xor $h,$tmp1 + $SLL $tmp1,$a,`$SZ*8-@Sigma0[0]` + xor $h,$tmp0 + and $tmp0,$b,$c + xor $h,$tmp1 # Sigma0(a) + xor $tmp1,$b,$c +#endif + $ST @X[0],`($i%16)*$SZ`($sp) # offload to ring buffer + $ADDU $h,$tmp0 + and $tmp1,$a + $ADDU $T1,$tmp2 # +=K[$i] + $ADDU $h,$tmp1 # +=Maj(a,b,c) + $ADDU $d,$T1 + $ADDU $h,$T1 +___ +$code.=<<___ if ($i>=13); + $LD @X[3],`(($i+3)%16)*$SZ`($sp) # prefetch from ring buffer +___ +} + +sub BODY_16_XX { +my $i=@_[0]; +my ($tmp0,$tmp1,$tmp2,$tmp3)=(@X[4],@X[5],@X[6],@X[7]); + +$code.=<<___; +#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2) + $SRL $tmp2,@X[1],@sigma0[0] # Xupdate($i) + $ROTR $tmp0,@X[1],@sigma0[1] + $ADDU @X[0],@X[9] # +=X[i+9] + xor $tmp2,$tmp0 + $ROTR $tmp0,@X[1],@sigma0[2] + + $SRL $tmp3,@X[14],@sigma1[0] + $ROTR $tmp1,@X[14],@sigma1[1] + xor $tmp2,$tmp0 # sigma0(X[i+1]) + $ROTR $tmp0,@X[14],@sigma1[2] + xor $tmp3,$tmp1 + $ADDU @X[0],$tmp2 +#else + $SRL $tmp2,@X[1],@sigma0[0] # Xupdate($i) + $ADDU @X[0],@X[9] # +=X[i+9] + $SLL $tmp1,@X[1],`$SZ*8-@sigma0[2]` + $SRL $tmp0,@X[1],@sigma0[1] + xor $tmp2,$tmp1 + $SLL $tmp1,`@sigma0[2]-@sigma0[1]` + xor $tmp2,$tmp0 + $SRL $tmp0,@X[1],@sigma0[2] + xor $tmp2,$tmp1 + + $SRL $tmp3,@X[14],@sigma1[0] + xor $tmp2,$tmp0 # sigma0(X[i+1]) + $SLL $tmp1,@X[14],`$SZ*8-@sigma1[2]` + $ADDU @X[0],$tmp2 + $SRL $tmp0,@X[14],@sigma1[1] + xor $tmp3,$tmp1 + $SLL $tmp1,`@sigma1[2]-@sigma1[1]` + xor $tmp3,$tmp0 + $SRL $tmp0,@X[14],@sigma1[2] + xor $tmp3,$tmp1 +#endif + xor $tmp3,$tmp0 # sigma1(X[i+14]) + $ADDU @X[0],$tmp3 +___ + &BODY_00_15(@_); +} + +$FRAMESIZE=16*$SZ+16*$SZREG; +$SAVED_REGS_MASK = ($flavour =~ /nubi/i) ? "0xc0fff008" : "0xc0ff0000"; + +$code.=<<___; +#include "mips_arch.h" + +.text +.set noat +#if !defined(__mips_eabi) && (!defined(__vxworks) || defined(__pic__)) +.option pic2 +#endif + +.align 5 +.globl sha${label}_block_data_order +.ent sha${label}_block_data_order +sha${label}_block_data_order: + .frame $sp,$FRAMESIZE,$ra + .mask $SAVED_REGS_MASK,-$SZREG + .set noreorder +___ +$code.=<<___ if ($flavour =~ /o32/i); # o32 PIC-ification + .cpload $pf +___ +$code.=<<___; + $PTR_SUB $sp,$FRAMESIZE + $REG_S $ra,$FRAMESIZE-1*$SZREG($sp) + $REG_S $fp,$FRAMESIZE-2*$SZREG($sp) + $REG_S $s11,$FRAMESIZE-3*$SZREG($sp) + $REG_S $s10,$FRAMESIZE-4*$SZREG($sp) + $REG_S $s9,$FRAMESIZE-5*$SZREG($sp) + $REG_S $s8,$FRAMESIZE-6*$SZREG($sp) + $REG_S $s7,$FRAMESIZE-7*$SZREG($sp) + $REG_S $s6,$FRAMESIZE-8*$SZREG($sp) + $REG_S $s5,$FRAMESIZE-9*$SZREG($sp) + $REG_S $s4,$FRAMESIZE-10*$SZREG($sp) +___ +$code.=<<___ if ($flavour =~ /nubi/i); # optimize non-nubi prologue + $REG_S $s3,$FRAMESIZE-11*$SZREG($sp) + $REG_S $s2,$FRAMESIZE-12*$SZREG($sp) + $REG_S $s1,$FRAMESIZE-13*$SZREG($sp) + $REG_S $s0,$FRAMESIZE-14*$SZREG($sp) + $REG_S $gp,$FRAMESIZE-15*$SZREG($sp) +___ +$code.=<<___; + $PTR_SLL @X[15],$len,`log(16*$SZ)/log(2)` +___ +$code.=<<___ if ($flavour !~ /o32/i); # non-o32 PIC-ification + .cplocal $Ktbl + .cpsetup $pf,$zero,sha${label}_block_data_order +___ +$code.=<<___; + .set reorder + $PTR_LA $Ktbl,K${label} # PIC-ified 'load address' + + $LD $A,0*$SZ($ctx) # load context + $LD $B,1*$SZ($ctx) + $LD $C,2*$SZ($ctx) + $LD $D,3*$SZ($ctx) + $LD $E,4*$SZ($ctx) + $LD $F,5*$SZ($ctx) + $LD $G,6*$SZ($ctx) + $LD $H,7*$SZ($ctx) + + $PTR_ADD @X[15],$inp # pointer to the end of input + $REG_S @X[15],16*$SZ($sp) + b .Loop + +.align 5 +.Loop: +#if defined(_MIPS_ARCH_MIPS32R6) || defined(_MIPS_ARCH_MIPS64R6) + ${LD} @X[0],($inp) +#else + ${LD}l @X[0],$MSB($inp) + ${LD}r @X[0],$LSB($inp) +#endif +___ +for ($i=0;$i<16;$i++) +{ &BODY_00_15($i,@V); unshift(@V,pop(@V)); push(@X,shift(@X)); } +$code.=<<___; + b .L16_xx +.align 4 +.L16_xx: +___ +for (;$i<32;$i++) +{ &BODY_16_XX($i,@V); unshift(@V,pop(@V)); push(@X,shift(@X)); } +$code.=<<___; + and @X[6],0xfff + li @X[7],$lastK + .set noreorder + bne @X[6],@X[7],.L16_xx + $PTR_ADD $Ktbl,16*$SZ # Ktbl+=16 + + $REG_L @X[15],16*$SZ($sp) # restore pointer to the end of input + $LD @X[0],0*$SZ($ctx) + $LD @X[1],1*$SZ($ctx) + $LD @X[2],2*$SZ($ctx) + $PTR_ADD $inp,16*$SZ + $LD @X[3],3*$SZ($ctx) + $ADDU $A,@X[0] + $LD @X[4],4*$SZ($ctx) + $ADDU $B,@X[1] + $LD @X[5],5*$SZ($ctx) + $ADDU $C,@X[2] + $LD @X[6],6*$SZ($ctx) + $ADDU $D,@X[3] + $LD @X[7],7*$SZ($ctx) + $ADDU $E,@X[4] + $ST $A,0*$SZ($ctx) + $ADDU $F,@X[5] + $ST $B,1*$SZ($ctx) + $ADDU $G,@X[6] + $ST $C,2*$SZ($ctx) + $ADDU $H,@X[7] + $ST $D,3*$SZ($ctx) + $ST $E,4*$SZ($ctx) + $ST $F,5*$SZ($ctx) + $ST $G,6*$SZ($ctx) + $ST $H,7*$SZ($ctx) + + bne $inp,@X[15],.Loop + $PTR_SUB $Ktbl,`($rounds-16)*$SZ` # rewind $Ktbl + + $REG_L $ra,$FRAMESIZE-1*$SZREG($sp) + $REG_L $fp,$FRAMESIZE-2*$SZREG($sp) + $REG_L $s11,$FRAMESIZE-3*$SZREG($sp) + $REG_L $s10,$FRAMESIZE-4*$SZREG($sp) + $REG_L $s9,$FRAMESIZE-5*$SZREG($sp) + $REG_L $s8,$FRAMESIZE-6*$SZREG($sp) + $REG_L $s7,$FRAMESIZE-7*$SZREG($sp) + $REG_L $s6,$FRAMESIZE-8*$SZREG($sp) + $REG_L $s5,$FRAMESIZE-9*$SZREG($sp) + $REG_L $s4,$FRAMESIZE-10*$SZREG($sp) +___ +$code.=<<___ if ($flavour =~ /nubi/i); + $REG_L $s3,$FRAMESIZE-11*$SZREG($sp) + $REG_L $s2,$FRAMESIZE-12*$SZREG($sp) + $REG_L $s1,$FRAMESIZE-13*$SZREG($sp) + $REG_L $s0,$FRAMESIZE-14*$SZREG($sp) + $REG_L $gp,$FRAMESIZE-15*$SZREG($sp) +___ +$code.=<<___; + jr $ra + $PTR_ADD $sp,$FRAMESIZE +.end sha${label}_block_data_order + +.rdata +.align 5 +K${label}: +___ +if ($SZ==4) { +$code.=<<___; + .word 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5 + .word 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5 + .word 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3 + .word 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174 + .word 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc + .word 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da + .word 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7 + .word 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967 + .word 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13 + .word 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85 + .word 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3 + .word 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070 + .word 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5 + .word 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3 + .word 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208 + .word 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +___ +} else { +$code.=<<___; + .dword 0x428a2f98d728ae22, 0x7137449123ef65cd + .dword 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc + .dword 0x3956c25bf348b538, 0x59f111f1b605d019 + .dword 0x923f82a4af194f9b, 0xab1c5ed5da6d8118 + .dword 0xd807aa98a3030242, 0x12835b0145706fbe + .dword 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2 + .dword 0x72be5d74f27b896f, 0x80deb1fe3b1696b1 + .dword 0x9bdc06a725c71235, 0xc19bf174cf692694 + .dword 0xe49b69c19ef14ad2, 0xefbe4786384f25e3 + .dword 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65 + .dword 0x2de92c6f592b0275, 0x4a7484aa6ea6e483 + .dword 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5 + .dword 0x983e5152ee66dfab, 0xa831c66d2db43210 + .dword 0xb00327c898fb213f, 0xbf597fc7beef0ee4 + .dword 0xc6e00bf33da88fc2, 0xd5a79147930aa725 + .dword 0x06ca6351e003826f, 0x142929670a0e6e70 + .dword 0x27b70a8546d22ffc, 0x2e1b21385c26c926 + .dword 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df + .dword 0x650a73548baf63de, 0x766a0abb3c77b2a8 + .dword 0x81c2c92e47edaee6, 0x92722c851482353b + .dword 0xa2bfe8a14cf10364, 0xa81a664bbc423001 + .dword 0xc24b8b70d0f89791, 0xc76c51a30654be30 + .dword 0xd192e819d6ef5218, 0xd69906245565a910 + .dword 0xf40e35855771202a, 0x106aa07032bbd1b8 + .dword 0x19a4c116b8d2d0c8, 0x1e376c085141ab53 + .dword 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8 + .dword 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb + .dword 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3 + .dword 0x748f82ee5defb2fc, 0x78a5636f43172f60 + .dword 0x84c87814a1f0ab72, 0x8cc702081a6439ec + .dword 0x90befffa23631e28, 0xa4506cebde82bde9 + .dword 0xbef9a3f7b2c67915, 0xc67178f2e372532b + .dword 0xca273eceea26619c, 0xd186b8c721c0c207 + .dword 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178 + .dword 0x06f067aa72176fba, 0x0a637dc5a2c898a6 + .dword 0x113f9804bef90dae, 0x1b710b35131c471b + .dword 0x28db77f523047d84, 0x32caab7b40c72493 + .dword 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c + .dword 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a + .dword 0x5fcb6fab3ad6faec, 0x6c44198c4a475817 +___ +} +$code.=<<___; +.asciiz "SHA${label} for MIPS, CRYPTOGAMS by " +.align 5 + +___ + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-parisc.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-parisc.pl new file mode 100755 index 000000000..59eb320ab --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-parisc.pl @@ -0,0 +1,807 @@ +#! /usr/bin/env perl +# Copyright 2009-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# SHA256/512 block procedure for PA-RISC. + +# June 2009. +# +# SHA256 performance is >75% better than gcc 3.2 generated code on +# PA-7100LC. Compared to code generated by vendor compiler this +# implementation is almost 70% faster in 64-bit build, but delivers +# virtually same performance in 32-bit build on PA-8600. +# +# SHA512 performance is >2.9x better than gcc 3.2 generated code on +# PA-7100LC, PA-RISC 1.1 processor. Then implementation detects if the +# code is executed on PA-RISC 2.0 processor and switches to 64-bit +# code path delivering adequate performance even in "blended" 32-bit +# build. Though 64-bit code is not any faster than code generated by +# vendor compiler on PA-8600... +# +# Special thanks to polarhome.com for providing HP-UX account. + +$flavour = shift; +$output = shift; +open STDOUT,">$output"; + +if ($flavour =~ /64/) { + $LEVEL ="2.0W"; + $SIZE_T =8; + $FRAME_MARKER =80; + $SAVED_RP =16; + $PUSH ="std"; + $PUSHMA ="std,ma"; + $POP ="ldd"; + $POPMB ="ldd,mb"; +} else { + $LEVEL ="1.0"; + $SIZE_T =4; + $FRAME_MARKER =48; + $SAVED_RP =20; + $PUSH ="stw"; + $PUSHMA ="stwm"; + $POP ="ldw"; + $POPMB ="ldwm"; +} + +if ($output =~ /512/) { + $func="sha512_block_data_order"; + $SZ=8; + @Sigma0=(28,34,39); + @Sigma1=(14,18,41); + @sigma0=(1, 8, 7); + @sigma1=(19,61, 6); + $rounds=80; + $LAST10BITS=0x017; + $LD="ldd"; + $LDM="ldd,ma"; + $ST="std"; +} else { + $func="sha256_block_data_order"; + $SZ=4; + @Sigma0=( 2,13,22); + @Sigma1=( 6,11,25); + @sigma0=( 7,18, 3); + @sigma1=(17,19,10); + $rounds=64; + $LAST10BITS=0x0f2; + $LD="ldw"; + $LDM="ldwm"; + $ST="stw"; +} + +$FRAME=16*$SIZE_T+$FRAME_MARKER;# 16 saved regs + frame marker + # [+ argument transfer] +$XOFF=16*$SZ+32; # local variables +$FRAME+=$XOFF; +$XOFF+=$FRAME_MARKER; # distance between %sp and local variables + +$ctx="%r26"; # zapped by $a0 +$inp="%r25"; # zapped by $a1 +$num="%r24"; # zapped by $t0 + +$a0 ="%r26"; +$a1 ="%r25"; +$t0 ="%r24"; +$t1 ="%r29"; +$Tbl="%r31"; + +@V=($A,$B,$C,$D,$E,$F,$G,$H)=("%r17","%r18","%r19","%r20","%r21","%r22","%r23","%r28"); + +@X=("%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7", "%r8", + "%r9", "%r10","%r11","%r12","%r13","%r14","%r15","%r16",$inp); + +sub ROUND_00_15 { +my ($i,$a,$b,$c,$d,$e,$f,$g,$h)=@_; +$code.=<<___; + _ror $e,$Sigma1[0],$a0 + and $f,$e,$t0 + _ror $e,$Sigma1[1],$a1 + addl $t1,$h,$h + andcm $g,$e,$t1 + xor $a1,$a0,$a0 + _ror $a1,`$Sigma1[2]-$Sigma1[1]`,$a1 + or $t0,$t1,$t1 ; Ch(e,f,g) + addl @X[$i%16],$h,$h + xor $a0,$a1,$a1 ; Sigma1(e) + addl $t1,$h,$h + _ror $a,$Sigma0[0],$a0 + addl $a1,$h,$h + + _ror $a,$Sigma0[1],$a1 + and $a,$b,$t0 + and $a,$c,$t1 + xor $a1,$a0,$a0 + _ror $a1,`$Sigma0[2]-$Sigma0[1]`,$a1 + xor $t1,$t0,$t0 + and $b,$c,$t1 + xor $a0,$a1,$a1 ; Sigma0(a) + addl $h,$d,$d + xor $t1,$t0,$t0 ; Maj(a,b,c) + `"$LDM $SZ($Tbl),$t1" if ($i<15)` + addl $a1,$h,$h + addl $t0,$h,$h + +___ +} + +sub ROUND_16_xx { +my ($i,$a,$b,$c,$d,$e,$f,$g,$h)=@_; +$i-=16; +$code.=<<___; + _ror @X[($i+1)%16],$sigma0[0],$a0 + _ror @X[($i+1)%16],$sigma0[1],$a1 + addl @X[($i+9)%16],@X[$i],@X[$i] + _ror @X[($i+14)%16],$sigma1[0],$t0 + _ror @X[($i+14)%16],$sigma1[1],$t1 + xor $a1,$a0,$a0 + _shr @X[($i+1)%16],$sigma0[2],$a1 + xor $t1,$t0,$t0 + _shr @X[($i+14)%16],$sigma1[2],$t1 + xor $a1,$a0,$a0 ; sigma0(X[(i+1)&0x0f]) + xor $t1,$t0,$t0 ; sigma1(X[(i+14)&0x0f]) + $LDM $SZ($Tbl),$t1 + addl $a0,@X[$i],@X[$i] + addl $t0,@X[$i],@X[$i] +___ +$code.=<<___ if ($i==15); + extru $t1,31,10,$a1 + comiclr,<> $LAST10BITS,$a1,%r0 + ldo 1($Tbl),$Tbl ; signal end of $Tbl +___ +&ROUND_00_15($i+16,$a,$b,$c,$d,$e,$f,$g,$h); +} + +$code=<<___; + .LEVEL $LEVEL + .SPACE \$TEXT\$ + .SUBSPA \$CODE\$,QUAD=0,ALIGN=8,ACCESS=0x2C,CODE_ONLY + + .ALIGN 64 +L\$table +___ +$code.=<<___ if ($SZ==8); + .WORD 0x428a2f98,0xd728ae22,0x71374491,0x23ef65cd + .WORD 0xb5c0fbcf,0xec4d3b2f,0xe9b5dba5,0x8189dbbc + .WORD 0x3956c25b,0xf348b538,0x59f111f1,0xb605d019 + .WORD 0x923f82a4,0xaf194f9b,0xab1c5ed5,0xda6d8118 + .WORD 0xd807aa98,0xa3030242,0x12835b01,0x45706fbe + .WORD 0x243185be,0x4ee4b28c,0x550c7dc3,0xd5ffb4e2 + .WORD 0x72be5d74,0xf27b896f,0x80deb1fe,0x3b1696b1 + .WORD 0x9bdc06a7,0x25c71235,0xc19bf174,0xcf692694 + .WORD 0xe49b69c1,0x9ef14ad2,0xefbe4786,0x384f25e3 + .WORD 0x0fc19dc6,0x8b8cd5b5,0x240ca1cc,0x77ac9c65 + .WORD 0x2de92c6f,0x592b0275,0x4a7484aa,0x6ea6e483 + .WORD 0x5cb0a9dc,0xbd41fbd4,0x76f988da,0x831153b5 + .WORD 0x983e5152,0xee66dfab,0xa831c66d,0x2db43210 + .WORD 0xb00327c8,0x98fb213f,0xbf597fc7,0xbeef0ee4 + .WORD 0xc6e00bf3,0x3da88fc2,0xd5a79147,0x930aa725 + .WORD 0x06ca6351,0xe003826f,0x14292967,0x0a0e6e70 + .WORD 0x27b70a85,0x46d22ffc,0x2e1b2138,0x5c26c926 + .WORD 0x4d2c6dfc,0x5ac42aed,0x53380d13,0x9d95b3df + .WORD 0x650a7354,0x8baf63de,0x766a0abb,0x3c77b2a8 + .WORD 0x81c2c92e,0x47edaee6,0x92722c85,0x1482353b + .WORD 0xa2bfe8a1,0x4cf10364,0xa81a664b,0xbc423001 + .WORD 0xc24b8b70,0xd0f89791,0xc76c51a3,0x0654be30 + .WORD 0xd192e819,0xd6ef5218,0xd6990624,0x5565a910 + .WORD 0xf40e3585,0x5771202a,0x106aa070,0x32bbd1b8 + .WORD 0x19a4c116,0xb8d2d0c8,0x1e376c08,0x5141ab53 + .WORD 0x2748774c,0xdf8eeb99,0x34b0bcb5,0xe19b48a8 + .WORD 0x391c0cb3,0xc5c95a63,0x4ed8aa4a,0xe3418acb + .WORD 0x5b9cca4f,0x7763e373,0x682e6ff3,0xd6b2b8a3 + .WORD 0x748f82ee,0x5defb2fc,0x78a5636f,0x43172f60 + .WORD 0x84c87814,0xa1f0ab72,0x8cc70208,0x1a6439ec + .WORD 0x90befffa,0x23631e28,0xa4506ceb,0xde82bde9 + .WORD 0xbef9a3f7,0xb2c67915,0xc67178f2,0xe372532b + .WORD 0xca273ece,0xea26619c,0xd186b8c7,0x21c0c207 + .WORD 0xeada7dd6,0xcde0eb1e,0xf57d4f7f,0xee6ed178 + .WORD 0x06f067aa,0x72176fba,0x0a637dc5,0xa2c898a6 + .WORD 0x113f9804,0xbef90dae,0x1b710b35,0x131c471b + .WORD 0x28db77f5,0x23047d84,0x32caab7b,0x40c72493 + .WORD 0x3c9ebe0a,0x15c9bebc,0x431d67c4,0x9c100d4c + .WORD 0x4cc5d4be,0xcb3e42b6,0x597f299c,0xfc657e2a + .WORD 0x5fcb6fab,0x3ad6faec,0x6c44198c,0x4a475817 +___ +$code.=<<___ if ($SZ==4); + .WORD 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 + .WORD 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 + .WORD 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 + .WORD 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 + .WORD 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc + .WORD 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da + .WORD 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 + .WORD 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967 + .WORD 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 + .WORD 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 + .WORD 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 + .WORD 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 + .WORD 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 + .WORD 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 + .WORD 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 + .WORD 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 +___ +$code.=<<___; + + .EXPORT $func,ENTRY,ARGW0=GR,ARGW1=GR,ARGW2=GR + .ALIGN 64 +$func + .PROC + .CALLINFO FRAME=`$FRAME-16*$SIZE_T`,NO_CALLS,SAVE_RP,ENTRY_GR=18 + .ENTRY + $PUSH %r2,-$SAVED_RP(%sp) ; standard prologue + $PUSHMA %r3,$FRAME(%sp) + $PUSH %r4,`-$FRAME+1*$SIZE_T`(%sp) + $PUSH %r5,`-$FRAME+2*$SIZE_T`(%sp) + $PUSH %r6,`-$FRAME+3*$SIZE_T`(%sp) + $PUSH %r7,`-$FRAME+4*$SIZE_T`(%sp) + $PUSH %r8,`-$FRAME+5*$SIZE_T`(%sp) + $PUSH %r9,`-$FRAME+6*$SIZE_T`(%sp) + $PUSH %r10,`-$FRAME+7*$SIZE_T`(%sp) + $PUSH %r11,`-$FRAME+8*$SIZE_T`(%sp) + $PUSH %r12,`-$FRAME+9*$SIZE_T`(%sp) + $PUSH %r13,`-$FRAME+10*$SIZE_T`(%sp) + $PUSH %r14,`-$FRAME+11*$SIZE_T`(%sp) + $PUSH %r15,`-$FRAME+12*$SIZE_T`(%sp) + $PUSH %r16,`-$FRAME+13*$SIZE_T`(%sp) + $PUSH %r17,`-$FRAME+14*$SIZE_T`(%sp) + $PUSH %r18,`-$FRAME+15*$SIZE_T`(%sp) + + _shl $num,`log(16*$SZ)/log(2)`,$num + addl $inp,$num,$num ; $num to point at the end of $inp + + $PUSH $num,`-$FRAME_MARKER-4*$SIZE_T`(%sp) ; save arguments + $PUSH $inp,`-$FRAME_MARKER-3*$SIZE_T`(%sp) + $PUSH $ctx,`-$FRAME_MARKER-2*$SIZE_T`(%sp) + + blr %r0,$Tbl + ldi 3,$t1 +L\$pic + andcm $Tbl,$t1,$Tbl ; wipe privilege level + ldo L\$table-L\$pic($Tbl),$Tbl +___ +$code.=<<___ if ($SZ==8 && $SIZE_T==4); + ldi 31,$t1 + mtctl $t1,%cr11 + extrd,u,*= $t1,%sar,1,$t1 ; executes on PA-RISC 1.0 + b L\$parisc1 + nop +___ +$code.=<<___; + $LD `0*$SZ`($ctx),$A ; load context + $LD `1*$SZ`($ctx),$B + $LD `2*$SZ`($ctx),$C + $LD `3*$SZ`($ctx),$D + $LD `4*$SZ`($ctx),$E + $LD `5*$SZ`($ctx),$F + $LD `6*$SZ`($ctx),$G + $LD `7*$SZ`($ctx),$H + + extru $inp,31,`log($SZ)/log(2)`,$t0 + sh3addl $t0,%r0,$t0 + subi `8*$SZ`,$t0,$t0 + mtctl $t0,%cr11 ; load %sar with align factor + +L\$oop + ldi `$SZ-1`,$t0 + $LDM $SZ($Tbl),$t1 + andcm $inp,$t0,$t0 ; align $inp +___ + for ($i=0;$i<15;$i++) { # load input block + $code.="\t$LD `$SZ*$i`($t0),@X[$i]\n"; } +$code.=<<___; + cmpb,*= $inp,$t0,L\$aligned + $LD `$SZ*15`($t0),@X[15] + $LD `$SZ*16`($t0),@X[16] +___ + for ($i=0;$i<16;$i++) { # align data + $code.="\t_align @X[$i],@X[$i+1],@X[$i]\n"; } +$code.=<<___; +L\$aligned + nop ; otherwise /usr/ccs/bin/as is confused by below .WORD +___ + +for($i=0;$i<16;$i++) { &ROUND_00_15($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; +L\$rounds + nop ; otherwise /usr/ccs/bin/as is confused by below .WORD +___ +for(;$i<32;$i++) { &ROUND_16_xx($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + bb,>= $Tbl,31,L\$rounds ; end of $Tbl signalled? + nop + + $POP `-$FRAME_MARKER-2*$SIZE_T`(%sp),$ctx ; restore arguments + $POP `-$FRAME_MARKER-3*$SIZE_T`(%sp),$inp + $POP `-$FRAME_MARKER-4*$SIZE_T`(%sp),$num + ldo `-$rounds*$SZ-1`($Tbl),$Tbl ; rewind $Tbl + + $LD `0*$SZ`($ctx),@X[0] ; load context + $LD `1*$SZ`($ctx),@X[1] + $LD `2*$SZ`($ctx),@X[2] + $LD `3*$SZ`($ctx),@X[3] + $LD `4*$SZ`($ctx),@X[4] + $LD `5*$SZ`($ctx),@X[5] + addl @X[0],$A,$A + $LD `6*$SZ`($ctx),@X[6] + addl @X[1],$B,$B + $LD `7*$SZ`($ctx),@X[7] + ldo `16*$SZ`($inp),$inp ; advance $inp + + $ST $A,`0*$SZ`($ctx) ; save context + addl @X[2],$C,$C + $ST $B,`1*$SZ`($ctx) + addl @X[3],$D,$D + $ST $C,`2*$SZ`($ctx) + addl @X[4],$E,$E + $ST $D,`3*$SZ`($ctx) + addl @X[5],$F,$F + $ST $E,`4*$SZ`($ctx) + addl @X[6],$G,$G + $ST $F,`5*$SZ`($ctx) + addl @X[7],$H,$H + $ST $G,`6*$SZ`($ctx) + $ST $H,`7*$SZ`($ctx) + + cmpb,*<>,n $inp,$num,L\$oop + $PUSH $inp,`-$FRAME_MARKER-3*$SIZE_T`(%sp) ; save $inp +___ +if ($SZ==8 && $SIZE_T==4) # SHA512 for 32-bit PA-RISC 1.0 +{{ +$code.=<<___; + b L\$done + nop + + .ALIGN 64 +L\$parisc1 +___ + +@V=( $Ahi, $Alo, $Bhi, $Blo, $Chi, $Clo, $Dhi, $Dlo, + $Ehi, $Elo, $Fhi, $Flo, $Ghi, $Glo, $Hhi, $Hlo) = + ( "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7", "%r8", + "%r9","%r10","%r11","%r12","%r13","%r14","%r15","%r16"); +$a0 ="%r17"; +$a1 ="%r18"; +$a2 ="%r19"; +$a3 ="%r20"; +$t0 ="%r21"; +$t1 ="%r22"; +$t2 ="%r28"; +$t3 ="%r29"; +$Tbl="%r31"; + +@X=("%r23","%r24","%r25","%r26"); # zaps $num,$inp,$ctx + +sub ROUND_00_15_pa1 { +my ($i,$ahi,$alo,$bhi,$blo,$chi,$clo,$dhi,$dlo, + $ehi,$elo,$fhi,$flo,$ghi,$glo,$hhi,$hlo,$flag)=@_; +my ($Xhi,$Xlo,$Xnhi,$Xnlo) = @X; + +$code.=<<___ if (!$flag); + ldw `-$XOFF+8*(($i+1)%16)`(%sp),$Xnhi + ldw `-$XOFF+8*(($i+1)%16)+4`(%sp),$Xnlo ; load X[i+1] +___ +$code.=<<___; + shd $ehi,$elo,$Sigma1[0],$t0 + add $Xlo,$hlo,$hlo + shd $elo,$ehi,$Sigma1[0],$t1 + addc $Xhi,$hhi,$hhi ; h += X[i] + shd $ehi,$elo,$Sigma1[1],$t2 + ldwm 8($Tbl),$Xhi + shd $elo,$ehi,$Sigma1[1],$t3 + ldw -4($Tbl),$Xlo ; load K[i] + xor $t2,$t0,$t0 + xor $t3,$t1,$t1 + and $flo,$elo,$a0 + and $fhi,$ehi,$a1 + shd $ehi,$elo,$Sigma1[2],$t2 + andcm $glo,$elo,$a2 + shd $elo,$ehi,$Sigma1[2],$t3 + andcm $ghi,$ehi,$a3 + xor $t2,$t0,$t0 + xor $t3,$t1,$t1 ; Sigma1(e) + add $Xlo,$hlo,$hlo + xor $a2,$a0,$a0 + addc $Xhi,$hhi,$hhi ; h += K[i] + xor $a3,$a1,$a1 ; Ch(e,f,g) + + add $t0,$hlo,$hlo + shd $ahi,$alo,$Sigma0[0],$t0 + addc $t1,$hhi,$hhi ; h += Sigma1(e) + shd $alo,$ahi,$Sigma0[0],$t1 + add $a0,$hlo,$hlo + shd $ahi,$alo,$Sigma0[1],$t2 + addc $a1,$hhi,$hhi ; h += Ch(e,f,g) + shd $alo,$ahi,$Sigma0[1],$t3 + + xor $t2,$t0,$t0 + xor $t3,$t1,$t1 + shd $ahi,$alo,$Sigma0[2],$t2 + and $alo,$blo,$a0 + shd $alo,$ahi,$Sigma0[2],$t3 + and $ahi,$bhi,$a1 + xor $t2,$t0,$t0 + xor $t3,$t1,$t1 ; Sigma0(a) + + and $alo,$clo,$a2 + and $ahi,$chi,$a3 + xor $a2,$a0,$a0 + add $hlo,$dlo,$dlo + xor $a3,$a1,$a1 + addc $hhi,$dhi,$dhi ; d += h + and $blo,$clo,$a2 + add $t0,$hlo,$hlo + and $bhi,$chi,$a3 + addc $t1,$hhi,$hhi ; h += Sigma0(a) + xor $a2,$a0,$a0 + add $a0,$hlo,$hlo + xor $a3,$a1,$a1 ; Maj(a,b,c) + addc $a1,$hhi,$hhi ; h += Maj(a,b,c) + +___ +$code.=<<___ if ($i==15 && $flag); + extru $Xlo,31,10,$Xlo + comiclr,= $LAST10BITS,$Xlo,%r0 + b L\$rounds_pa1 + nop +___ +push(@X,shift(@X)); push(@X,shift(@X)); +} + +sub ROUND_16_xx_pa1 { +my ($Xhi,$Xlo,$Xnhi,$Xnlo) = @X; +my ($i)=shift; +$i-=16; +$code.=<<___; + ldw `-$XOFF+8*(($i+1)%16)`(%sp),$Xnhi + ldw `-$XOFF+8*(($i+1)%16)+4`(%sp),$Xnlo ; load X[i+1] + ldw `-$XOFF+8*(($i+9)%16)`(%sp),$a1 + ldw `-$XOFF+8*(($i+9)%16)+4`(%sp),$a0 ; load X[i+9] + ldw `-$XOFF+8*(($i+14)%16)`(%sp),$a3 + ldw `-$XOFF+8*(($i+14)%16)+4`(%sp),$a2 ; load X[i+14] + shd $Xnhi,$Xnlo,$sigma0[0],$t0 + shd $Xnlo,$Xnhi,$sigma0[0],$t1 + add $a0,$Xlo,$Xlo + shd $Xnhi,$Xnlo,$sigma0[1],$t2 + addc $a1,$Xhi,$Xhi + shd $Xnlo,$Xnhi,$sigma0[1],$t3 + xor $t2,$t0,$t0 + shd $Xnhi,$Xnlo,$sigma0[2],$t2 + xor $t3,$t1,$t1 + extru $Xnhi,`31-$sigma0[2]`,`32-$sigma0[2]`,$t3 + xor $t2,$t0,$t0 + shd $a3,$a2,$sigma1[0],$a0 + xor $t3,$t1,$t1 ; sigma0(X[i+1)&0x0f]) + shd $a2,$a3,$sigma1[0],$a1 + add $t0,$Xlo,$Xlo + shd $a3,$a2,$sigma1[1],$t2 + addc $t1,$Xhi,$Xhi + shd $a2,$a3,$sigma1[1],$t3 + xor $t2,$a0,$a0 + shd $a3,$a2,$sigma1[2],$t2 + xor $t3,$a1,$a1 + extru $a3,`31-$sigma1[2]`,`32-$sigma1[2]`,$t3 + xor $t2,$a0,$a0 + xor $t3,$a1,$a1 ; sigma0(X[i+14)&0x0f]) + add $a0,$Xlo,$Xlo + addc $a1,$Xhi,$Xhi + + stw $Xhi,`-$XOFF+8*($i%16)`(%sp) + stw $Xlo,`-$XOFF+8*($i%16)+4`(%sp) +___ +&ROUND_00_15_pa1($i,@_,1); +} +$code.=<<___; + ldw `0*4`($ctx),$Ahi ; load context + ldw `1*4`($ctx),$Alo + ldw `2*4`($ctx),$Bhi + ldw `3*4`($ctx),$Blo + ldw `4*4`($ctx),$Chi + ldw `5*4`($ctx),$Clo + ldw `6*4`($ctx),$Dhi + ldw `7*4`($ctx),$Dlo + ldw `8*4`($ctx),$Ehi + ldw `9*4`($ctx),$Elo + ldw `10*4`($ctx),$Fhi + ldw `11*4`($ctx),$Flo + ldw `12*4`($ctx),$Ghi + ldw `13*4`($ctx),$Glo + ldw `14*4`($ctx),$Hhi + ldw `15*4`($ctx),$Hlo + + extru $inp,31,2,$t0 + sh3addl $t0,%r0,$t0 + subi 32,$t0,$t0 + mtctl $t0,%cr11 ; load %sar with align factor + +L\$oop_pa1 + extru $inp,31,2,$a3 + comib,= 0,$a3,L\$aligned_pa1 + sub $inp,$a3,$inp + + ldw `0*4`($inp),$X[0] + ldw `1*4`($inp),$X[1] + ldw `2*4`($inp),$t2 + ldw `3*4`($inp),$t3 + ldw `4*4`($inp),$a0 + ldw `5*4`($inp),$a1 + ldw `6*4`($inp),$a2 + ldw `7*4`($inp),$a3 + vshd $X[0],$X[1],$X[0] + vshd $X[1],$t2,$X[1] + stw $X[0],`-$XOFF+0*4`(%sp) + ldw `8*4`($inp),$t0 + vshd $t2,$t3,$t2 + stw $X[1],`-$XOFF+1*4`(%sp) + ldw `9*4`($inp),$t1 + vshd $t3,$a0,$t3 +___ +{ +my @t=($t2,$t3,$a0,$a1,$a2,$a3,$t0,$t1); +for ($i=2;$i<=(128/4-8);$i++) { +$code.=<<___; + stw $t[0],`-$XOFF+$i*4`(%sp) + ldw `(8+$i)*4`($inp),$t[0] + vshd $t[1],$t[2],$t[1] +___ +push(@t,shift(@t)); +} +for (;$i<(128/4-1);$i++) { +$code.=<<___; + stw $t[0],`-$XOFF+$i*4`(%sp) + vshd $t[1],$t[2],$t[1] +___ +push(@t,shift(@t)); +} +$code.=<<___; + b L\$collected_pa1 + stw $t[0],`-$XOFF+$i*4`(%sp) + +___ +} +$code.=<<___; +L\$aligned_pa1 + ldw `0*4`($inp),$X[0] + ldw `1*4`($inp),$X[1] + ldw `2*4`($inp),$t2 + ldw `3*4`($inp),$t3 + ldw `4*4`($inp),$a0 + ldw `5*4`($inp),$a1 + ldw `6*4`($inp),$a2 + ldw `7*4`($inp),$a3 + stw $X[0],`-$XOFF+0*4`(%sp) + ldw `8*4`($inp),$t0 + stw $X[1],`-$XOFF+1*4`(%sp) + ldw `9*4`($inp),$t1 +___ +{ +my @t=($t2,$t3,$a0,$a1,$a2,$a3,$t0,$t1); +for ($i=2;$i<(128/4-8);$i++) { +$code.=<<___; + stw $t[0],`-$XOFF+$i*4`(%sp) + ldw `(8+$i)*4`($inp),$t[0] +___ +push(@t,shift(@t)); +} +for (;$i<128/4;$i++) { +$code.=<<___; + stw $t[0],`-$XOFF+$i*4`(%sp) +___ +push(@t,shift(@t)); +} +$code.="L\$collected_pa1\n"; +} + +for($i=0;$i<16;$i++) { &ROUND_00_15_pa1($i,@V); unshift(@V,pop(@V)); unshift(@V,pop(@V)); } +$code.="L\$rounds_pa1\n"; +for(;$i<32;$i++) { &ROUND_16_xx_pa1($i,@V); unshift(@V,pop(@V)); unshift(@V,pop(@V)); } + +$code.=<<___; + $POP `-$FRAME_MARKER-2*$SIZE_T`(%sp),$ctx ; restore arguments + $POP `-$FRAME_MARKER-3*$SIZE_T`(%sp),$inp + $POP `-$FRAME_MARKER-4*$SIZE_T`(%sp),$num + ldo `-$rounds*$SZ`($Tbl),$Tbl ; rewind $Tbl + + ldw `0*4`($ctx),$t1 ; update context + ldw `1*4`($ctx),$t0 + ldw `2*4`($ctx),$t3 + ldw `3*4`($ctx),$t2 + ldw `4*4`($ctx),$a1 + ldw `5*4`($ctx),$a0 + ldw `6*4`($ctx),$a3 + add $t0,$Alo,$Alo + ldw `7*4`($ctx),$a2 + addc $t1,$Ahi,$Ahi + ldw `8*4`($ctx),$t1 + add $t2,$Blo,$Blo + ldw `9*4`($ctx),$t0 + addc $t3,$Bhi,$Bhi + ldw `10*4`($ctx),$t3 + add $a0,$Clo,$Clo + ldw `11*4`($ctx),$t2 + addc $a1,$Chi,$Chi + ldw `12*4`($ctx),$a1 + add $a2,$Dlo,$Dlo + ldw `13*4`($ctx),$a0 + addc $a3,$Dhi,$Dhi + ldw `14*4`($ctx),$a3 + add $t0,$Elo,$Elo + ldw `15*4`($ctx),$a2 + addc $t1,$Ehi,$Ehi + stw $Ahi,`0*4`($ctx) + add $t2,$Flo,$Flo + stw $Alo,`1*4`($ctx) + addc $t3,$Fhi,$Fhi + stw $Bhi,`2*4`($ctx) + add $a0,$Glo,$Glo + stw $Blo,`3*4`($ctx) + addc $a1,$Ghi,$Ghi + stw $Chi,`4*4`($ctx) + add $a2,$Hlo,$Hlo + stw $Clo,`5*4`($ctx) + addc $a3,$Hhi,$Hhi + stw $Dhi,`6*4`($ctx) + ldo `16*$SZ`($inp),$inp ; advance $inp + stw $Dlo,`7*4`($ctx) + stw $Ehi,`8*4`($ctx) + stw $Elo,`9*4`($ctx) + stw $Fhi,`10*4`($ctx) + stw $Flo,`11*4`($ctx) + stw $Ghi,`12*4`($ctx) + stw $Glo,`13*4`($ctx) + stw $Hhi,`14*4`($ctx) + comb,= $inp,$num,L\$done + stw $Hlo,`15*4`($ctx) + b L\$oop_pa1 + $PUSH $inp,`-$FRAME_MARKER-3*$SIZE_T`(%sp) ; save $inp +L\$done +___ +}} +$code.=<<___; + $POP `-$FRAME-$SAVED_RP`(%sp),%r2 ; standard epilogue + $POP `-$FRAME+1*$SIZE_T`(%sp),%r4 + $POP `-$FRAME+2*$SIZE_T`(%sp),%r5 + $POP `-$FRAME+3*$SIZE_T`(%sp),%r6 + $POP `-$FRAME+4*$SIZE_T`(%sp),%r7 + $POP `-$FRAME+5*$SIZE_T`(%sp),%r8 + $POP `-$FRAME+6*$SIZE_T`(%sp),%r9 + $POP `-$FRAME+7*$SIZE_T`(%sp),%r10 + $POP `-$FRAME+8*$SIZE_T`(%sp),%r11 + $POP `-$FRAME+9*$SIZE_T`(%sp),%r12 + $POP `-$FRAME+10*$SIZE_T`(%sp),%r13 + $POP `-$FRAME+11*$SIZE_T`(%sp),%r14 + $POP `-$FRAME+12*$SIZE_T`(%sp),%r15 + $POP `-$FRAME+13*$SIZE_T`(%sp),%r16 + $POP `-$FRAME+14*$SIZE_T`(%sp),%r17 + $POP `-$FRAME+15*$SIZE_T`(%sp),%r18 + bv (%r2) + .EXIT + $POPMB -$FRAME(%sp),%r3 + .PROCEND + .STRINGZ "SHA`64*$SZ` block transform for PA-RISC, CRYPTOGAMS by " +___ + +# Explicitly encode PA-RISC 2.0 instructions used in this module, so +# that it can be compiled with .LEVEL 1.0. It should be noted that I +# wouldn't have to do this, if GNU assembler understood .ALLOW 2.0 +# directive... + +my $ldd = sub { + my ($mod,$args) = @_; + my $orig = "ldd$mod\t$args"; + + if ($args =~ /(\-?[0-9]+)\(%r([0-9]+)\),%r([0-9]+)/) # format 3 suffices + { my $opcode=(0x14<<26)|($2<<21)|($3<<16)|(($1&0x1FF8)<<1)|(($1>>13)&1); + $opcode|=(1<<3) if ($mod =~ /^,m/); + $opcode|=(1<<2) if ($mod =~ /^,mb/); + sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig; + } + else { "\t".$orig; } +}; + +my $std = sub { + my ($mod,$args) = @_; + my $orig = "std$mod\t$args"; + + if ($args =~ /%r([0-9]+),(\-?[0-9]+)\(%r([0-9]+)\)/) # format 3 suffices + { my $opcode=(0x1c<<26)|($3<<21)|($1<<16)|(($2&0x1FF8)<<1)|(($2>>13)&1); + sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig; + } + else { "\t".$orig; } +}; + +my $extrd = sub { + my ($mod,$args) = @_; + my $orig = "extrd$mod\t$args"; + + # I only have ",u" completer, it's implicitly encoded... + if ($args =~ /%r([0-9]+),([0-9]+),([0-9]+),%r([0-9]+)/) # format 15 + { my $opcode=(0x36<<26)|($1<<21)|($4<<16); + my $len=32-$3; + $opcode |= (($2&0x20)<<6)|(($2&0x1f)<<5); # encode pos + $opcode |= (($len&0x20)<<7)|($len&0x1f); # encode len + sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig; + } + elsif ($args =~ /%r([0-9]+),%sar,([0-9]+),%r([0-9]+)/) # format 12 + { my $opcode=(0x34<<26)|($1<<21)|($3<<16)|(2<<11)|(1<<9); + my $len=32-$2; + $opcode |= (($len&0x20)<<3)|($len&0x1f); # encode len + $opcode |= (1<<13) if ($mod =~ /,\**=/); + sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig; + } + else { "\t".$orig; } +}; + +my $shrpd = sub { + my ($mod,$args) = @_; + my $orig = "shrpd$mod\t$args"; + + if ($args =~ /%r([0-9]+),%r([0-9]+),([0-9]+),%r([0-9]+)/) # format 14 + { my $opcode=(0x34<<26)|($2<<21)|($1<<16)|(1<<10)|$4; + my $cpos=63-$3; + $opcode |= (($cpos&0x20)<<6)|(($cpos&0x1f)<<5); # encode sa + sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig; + } + elsif ($args =~ /%r([0-9]+),%r([0-9]+),%sar,%r([0-9]+)/) # format 11 + { sprintf "\t.WORD\t0x%08x\t; %s", + (0x34<<26)|($2<<21)|($1<<16)|(1<<9)|$3,$orig; + } + else { "\t".$orig; } +}; + +sub assemble { + my ($mnemonic,$mod,$args)=@_; + my $opcode = eval("\$$mnemonic"); + + ref($opcode) eq 'CODE' ? &$opcode($mod,$args) : "\t$mnemonic$mod\t$args"; +} + +if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler/) { + $gnuas = 1; +} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/ge; + + s/shd\s+(%r[0-9]+),(%r[0-9]+),([0-9]+)/ + $3>31 ? sprintf("shd\t%$2,%$1,%d",$3-32) # rotation for >=32 + : sprintf("shd\t%$1,%$2,%d",$3)/e or + # translate made up instructions: _ror, _shr, _align, _shl + s/_ror(\s+)(%r[0-9]+),/ + ($SZ==4 ? "shd" : "shrpd")."$1$2,$2,"/e or + + s/_shr(\s+%r[0-9]+),([0-9]+),/ + $SZ==4 ? sprintf("extru%s,%d,%d,",$1,31-$2,32-$2) + : sprintf("extrd,u%s,%d,%d,",$1,63-$2,64-$2)/e or + + s/_align(\s+%r[0-9]+,%r[0-9]+),/ + ($SZ==4 ? "vshd$1," : "shrpd$1,%sar,")/e or + + s/_shl(\s+%r[0-9]+),([0-9]+),/ + $SIZE_T==4 ? sprintf("zdep%s,%d,%d,",$1,31-$2,32-$2) + : sprintf("depd,z%s,%d,%d,",$1,63-$2,64-$2)/e; + + s/^\s+([a-z]+)([\S]*)\s+([\S]*)/&assemble($1,$2,$3)/e if ($SIZE_T==4); + + s/(\.LEVEL\s+2\.0)W/$1w/ if ($gnuas && $SIZE_T==8); + s/\.SPACE\s+\$TEXT\$/.text/ if ($gnuas && $SIZE_T==8); + s/\.SUBSPA.*// if ($gnuas && $SIZE_T==8); + s/cmpb,\*/comb,/ if ($SIZE_T==4); + s/\bbv\b/bve/ if ($SIZE_T==8); + + print $_,"\n"; +} + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-ppc.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-ppc.pl new file mode 100755 index 000000000..71699f663 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-ppc.pl @@ -0,0 +1,799 @@ +#! /usr/bin/env perl +# Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# I let hardware handle unaligned input, except on page boundaries +# (see below for details). Otherwise straightforward implementation +# with X vector in register bank. + +# sha256 | sha512 +# -m64 -m32 | -m64 -m32 +# --------------------------------------+----------------------- +# PPC970,gcc-4.0.0 +50% +38% | +40% +410%(*) +# Power6,xlc-7 +150% +90% | +100% +430%(*) +# +# (*) 64-bit code in 32-bit application context, which actually is +# on TODO list. It should be noted that for safe deployment in +# 32-bit *multi-threaded* context asynchronous signals should be +# blocked upon entry to SHA512 block routine. This is because +# 32-bit signaling procedure invalidates upper halves of GPRs. +# Context switch procedure preserves them, but not signaling:-( + +# Second version is true multi-thread safe. Trouble with the original +# version was that it was using thread local storage pointer register. +# Well, it scrupulously preserved it, but the problem would arise the +# moment asynchronous signal was delivered and signal handler would +# dereference the TLS pointer. While it's never the case in openssl +# application or test suite, we have to respect this scenario and not +# use TLS pointer register. Alternative would be to require caller to +# block signals prior calling this routine. For the record, in 32-bit +# context R2 serves as TLS pointer, while in 64-bit context - R13. + +$flavour=shift; +$output =shift; + +if ($flavour =~ /64/) { + $SIZE_T=8; + $LRSAVE=2*$SIZE_T; + $STU="stdu"; + $UCMP="cmpld"; + $SHL="sldi"; + $POP="ld"; + $PUSH="std"; +} elsif ($flavour =~ /32/) { + $SIZE_T=4; + $LRSAVE=$SIZE_T; + $STU="stwu"; + $UCMP="cmplw"; + $SHL="slwi"; + $POP="lwz"; + $PUSH="stw"; +} else { die "nonsense $flavour"; } + +$LITTLE_ENDIAN = ($flavour=~/le$/) ? $SIZE_T : 0; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or +die "can't locate ppc-xlate.pl"; + +open STDOUT,"| $^X $xlate $flavour $output" || die "can't call $xlate: $!"; + +if ($output =~ /512/) { + $func="sha512_block_ppc"; + $SZ=8; + @Sigma0=(28,34,39); + @Sigma1=(14,18,41); + @sigma0=(1, 8, 7); + @sigma1=(19,61, 6); + $rounds=80; + $LD="ld"; + $ST="std"; + $ROR="rotrdi"; + $SHR="srdi"; +} else { + $func="sha256_block_ppc"; + $SZ=4; + @Sigma0=( 2,13,22); + @Sigma1=( 6,11,25); + @sigma0=( 7,18, 3); + @sigma1=(17,19,10); + $rounds=64; + $LD="lwz"; + $ST="stw"; + $ROR="rotrwi"; + $SHR="srwi"; +} + +$FRAME=32*$SIZE_T+16*$SZ; +$LOCALS=6*$SIZE_T; + +$sp ="r1"; +$toc="r2"; +$ctx="r3"; # zapped by $a0 +$inp="r4"; # zapped by $a1 +$num="r5"; # zapped by $t0 + +$T ="r0"; +$a0 ="r3"; +$a1 ="r4"; +$t0 ="r5"; +$t1 ="r6"; +$Tbl="r7"; + +$A ="r8"; +$B ="r9"; +$C ="r10"; +$D ="r11"; +$E ="r12"; +$F =$t1; $t1 = "r0"; # stay away from "r13"; +$G ="r14"; +$H ="r15"; + +@V=($A,$B,$C,$D,$E,$F,$G,$H); +@X=("r16","r17","r18","r19","r20","r21","r22","r23", + "r24","r25","r26","r27","r28","r29","r30","r31"); + +$inp="r31" if($SZ==4 || $SIZE_T==8); # reassigned $inp! aliases with @X[15] + +sub ROUND_00_15 { +my ($i,$a,$b,$c,$d,$e,$f,$g,$h)=@_; +$code.=<<___; + $ROR $a0,$e,$Sigma1[0] + $ROR $a1,$e,$Sigma1[1] + and $t0,$f,$e + xor $a0,$a0,$a1 + add $h,$h,$t1 + andc $t1,$g,$e + $ROR $a1,$a1,`$Sigma1[2]-$Sigma1[1]` + or $t0,$t0,$t1 ; Ch(e,f,g) + add $h,$h,@X[$i%16] + xor $a0,$a0,$a1 ; Sigma1(e) + add $h,$h,$t0 + add $h,$h,$a0 + + $ROR $a0,$a,$Sigma0[0] + $ROR $a1,$a,$Sigma0[1] + and $t0,$a,$b + and $t1,$a,$c + xor $a0,$a0,$a1 + $ROR $a1,$a1,`$Sigma0[2]-$Sigma0[1]` + xor $t0,$t0,$t1 + and $t1,$b,$c + xor $a0,$a0,$a1 ; Sigma0(a) + add $d,$d,$h + xor $t0,$t0,$t1 ; Maj(a,b,c) +___ +$code.=<<___ if ($i<15); + $LD $t1,`($i+1)*$SZ`($Tbl) +___ +$code.=<<___; + add $h,$h,$a0 + add $h,$h,$t0 + +___ +} + +sub ROUND_16_xx { +my ($i,$a,$b,$c,$d,$e,$f,$g,$h)=@_; +$i-=16; +$code.=<<___; + $ROR $a0,@X[($i+1)%16],$sigma0[0] + $ROR $a1,@X[($i+1)%16],$sigma0[1] + $ROR $t0,@X[($i+14)%16],$sigma1[0] + $ROR $t1,@X[($i+14)%16],$sigma1[1] + xor $a0,$a0,$a1 + $SHR $a1,@X[($i+1)%16],$sigma0[2] + xor $t0,$t0,$t1 + $SHR $t1,@X[($i+14)%16],$sigma1[2] + add @X[$i],@X[$i],@X[($i+9)%16] + xor $a0,$a0,$a1 ; sigma0(X[(i+1)&0x0f]) + xor $t0,$t0,$t1 ; sigma1(X[(i+14)&0x0f]) + $LD $t1,`$i*$SZ`($Tbl) + add @X[$i],@X[$i],$a0 + add @X[$i],@X[$i],$t0 +___ +&ROUND_00_15($i+16,$a,$b,$c,$d,$e,$f,$g,$h); +} + +$code=<<___; +.machine "any" +.text + +.globl $func +.align 6 +$func: + $STU $sp,-$FRAME($sp) + mflr r0 + $SHL $num,$num,`log(16*$SZ)/log(2)` + + $PUSH $ctx,`$FRAME-$SIZE_T*22`($sp) + + $PUSH r14,`$FRAME-$SIZE_T*18`($sp) + $PUSH r15,`$FRAME-$SIZE_T*17`($sp) + $PUSH r16,`$FRAME-$SIZE_T*16`($sp) + $PUSH r17,`$FRAME-$SIZE_T*15`($sp) + $PUSH r18,`$FRAME-$SIZE_T*14`($sp) + $PUSH r19,`$FRAME-$SIZE_T*13`($sp) + $PUSH r20,`$FRAME-$SIZE_T*12`($sp) + $PUSH r21,`$FRAME-$SIZE_T*11`($sp) + $PUSH r22,`$FRAME-$SIZE_T*10`($sp) + $PUSH r23,`$FRAME-$SIZE_T*9`($sp) + $PUSH r24,`$FRAME-$SIZE_T*8`($sp) + $PUSH r25,`$FRAME-$SIZE_T*7`($sp) + $PUSH r26,`$FRAME-$SIZE_T*6`($sp) + $PUSH r27,`$FRAME-$SIZE_T*5`($sp) + $PUSH r28,`$FRAME-$SIZE_T*4`($sp) + $PUSH r29,`$FRAME-$SIZE_T*3`($sp) + $PUSH r30,`$FRAME-$SIZE_T*2`($sp) + $PUSH r31,`$FRAME-$SIZE_T*1`($sp) + $PUSH r0,`$FRAME+$LRSAVE`($sp) +___ + +if ($SZ==4 || $SIZE_T==8) { +$code.=<<___; + $LD $A,`0*$SZ`($ctx) + mr $inp,r4 ; incarnate $inp + $LD $B,`1*$SZ`($ctx) + $LD $C,`2*$SZ`($ctx) + $LD $D,`3*$SZ`($ctx) + $LD $E,`4*$SZ`($ctx) + $LD $F,`5*$SZ`($ctx) + $LD $G,`6*$SZ`($ctx) + $LD $H,`7*$SZ`($ctx) +___ +} else { + for ($i=16;$i<32;$i++) { + $code.=<<___; + lwz r$i,`$LITTLE_ENDIAN^(4*($i-16))`($ctx) +___ + } +} + +$code.=<<___; + bl LPICmeup +LPICedup: + andi. r0,$inp,3 + bne Lunaligned +Laligned: + add $num,$inp,$num + $PUSH $num,`$FRAME-$SIZE_T*24`($sp) ; end pointer + $PUSH $inp,`$FRAME-$SIZE_T*23`($sp) ; inp pointer + bl Lsha2_block_private + b Ldone + +; PowerPC specification allows an implementation to be ill-behaved +; upon unaligned access which crosses page boundary. "Better safe +; than sorry" principle makes me treat it specially. But I don't +; look for particular offending word, but rather for the input +; block which crosses the boundary. Once found that block is aligned +; and hashed separately... +.align 4 +Lunaligned: + subfic $t1,$inp,4096 + andi. $t1,$t1,`4096-16*$SZ` ; distance to closest page boundary + beq Lcross_page + $UCMP $num,$t1 + ble Laligned ; didn't cross the page boundary + subfc $num,$t1,$num + add $t1,$inp,$t1 + $PUSH $num,`$FRAME-$SIZE_T*25`($sp) ; save real remaining num + $PUSH $t1,`$FRAME-$SIZE_T*24`($sp) ; intermediate end pointer + $PUSH $inp,`$FRAME-$SIZE_T*23`($sp) ; inp pointer + bl Lsha2_block_private + ; $inp equals to the intermediate end pointer here + $POP $num,`$FRAME-$SIZE_T*25`($sp) ; restore real remaining num +Lcross_page: + li $t1,`16*$SZ/4` + mtctr $t1 +___ +if ($SZ==4 || $SIZE_T==8) { +$code.=<<___; + addi r20,$sp,$LOCALS ; aligned spot below the frame +Lmemcpy: + lbz r16,0($inp) + lbz r17,1($inp) + lbz r18,2($inp) + lbz r19,3($inp) + addi $inp,$inp,4 + stb r16,0(r20) + stb r17,1(r20) + stb r18,2(r20) + stb r19,3(r20) + addi r20,r20,4 + bdnz Lmemcpy +___ +} else { +$code.=<<___; + addi r12,$sp,$LOCALS ; aligned spot below the frame +Lmemcpy: + lbz r8,0($inp) + lbz r9,1($inp) + lbz r10,2($inp) + lbz r11,3($inp) + addi $inp,$inp,4 + stb r8,0(r12) + stb r9,1(r12) + stb r10,2(r12) + stb r11,3(r12) + addi r12,r12,4 + bdnz Lmemcpy +___ +} + +$code.=<<___; + $PUSH $inp,`$FRAME-$SIZE_T*26`($sp) ; save real inp + addi $t1,$sp,`$LOCALS+16*$SZ` ; fictitious end pointer + addi $inp,$sp,$LOCALS ; fictitious inp pointer + $PUSH $num,`$FRAME-$SIZE_T*25`($sp) ; save real num + $PUSH $t1,`$FRAME-$SIZE_T*24`($sp) ; end pointer + $PUSH $inp,`$FRAME-$SIZE_T*23`($sp) ; inp pointer + bl Lsha2_block_private + $POP $inp,`$FRAME-$SIZE_T*26`($sp) ; restore real inp + $POP $num,`$FRAME-$SIZE_T*25`($sp) ; restore real num + addic. $num,$num,`-16*$SZ` ; num-- + bne Lunaligned + +Ldone: + $POP r0,`$FRAME+$LRSAVE`($sp) + $POP r14,`$FRAME-$SIZE_T*18`($sp) + $POP r15,`$FRAME-$SIZE_T*17`($sp) + $POP r16,`$FRAME-$SIZE_T*16`($sp) + $POP r17,`$FRAME-$SIZE_T*15`($sp) + $POP r18,`$FRAME-$SIZE_T*14`($sp) + $POP r19,`$FRAME-$SIZE_T*13`($sp) + $POP r20,`$FRAME-$SIZE_T*12`($sp) + $POP r21,`$FRAME-$SIZE_T*11`($sp) + $POP r22,`$FRAME-$SIZE_T*10`($sp) + $POP r23,`$FRAME-$SIZE_T*9`($sp) + $POP r24,`$FRAME-$SIZE_T*8`($sp) + $POP r25,`$FRAME-$SIZE_T*7`($sp) + $POP r26,`$FRAME-$SIZE_T*6`($sp) + $POP r27,`$FRAME-$SIZE_T*5`($sp) + $POP r28,`$FRAME-$SIZE_T*4`($sp) + $POP r29,`$FRAME-$SIZE_T*3`($sp) + $POP r30,`$FRAME-$SIZE_T*2`($sp) + $POP r31,`$FRAME-$SIZE_T*1`($sp) + mtlr r0 + addi $sp,$sp,$FRAME + blr + .long 0 + .byte 0,12,4,1,0x80,18,3,0 + .long 0 +___ + +if ($SZ==4 || $SIZE_T==8) { +$code.=<<___; +.align 4 +Lsha2_block_private: + $LD $t1,0($Tbl) +___ +for($i=0;$i<16;$i++) { +$code.=<<___ if ($SZ==4 && !$LITTLE_ENDIAN); + lwz @X[$i],`$i*$SZ`($inp) +___ +$code.=<<___ if ($SZ==4 && $LITTLE_ENDIAN); + lwz $a0,`$i*$SZ`($inp) + rotlwi @X[$i],$a0,8 + rlwimi @X[$i],$a0,24,0,7 + rlwimi @X[$i],$a0,24,16,23 +___ +# 64-bit loads are split to 2x32-bit ones, as CPU can't handle +# unaligned 64-bit loads, only 32-bit ones... +$code.=<<___ if ($SZ==8 && !$LITTLE_ENDIAN); + lwz $t0,`$i*$SZ`($inp) + lwz @X[$i],`$i*$SZ+4`($inp) + insrdi @X[$i],$t0,32,0 +___ +$code.=<<___ if ($SZ==8 && $LITTLE_ENDIAN); + lwz $a0,`$i*$SZ`($inp) + lwz $a1,`$i*$SZ+4`($inp) + rotlwi $t0,$a0,8 + rotlwi @X[$i],$a1,8 + rlwimi $t0,$a0,24,0,7 + rlwimi @X[$i],$a1,24,0,7 + rlwimi $t0,$a0,24,16,23 + rlwimi @X[$i],$a1,24,16,23 + insrdi @X[$i],$t0,32,0 +___ + &ROUND_00_15($i,@V); + unshift(@V,pop(@V)); +} +$code.=<<___; + li $t0,`$rounds/16-1` + mtctr $t0 +.align 4 +Lrounds: + addi $Tbl,$Tbl,`16*$SZ` +___ +for(;$i<32;$i++) { + &ROUND_16_xx($i,@V); + unshift(@V,pop(@V)); +} +$code.=<<___; + bdnz Lrounds + + $POP $ctx,`$FRAME-$SIZE_T*22`($sp) + $POP $inp,`$FRAME-$SIZE_T*23`($sp) ; inp pointer + $POP $num,`$FRAME-$SIZE_T*24`($sp) ; end pointer + subi $Tbl,$Tbl,`($rounds-16)*$SZ` ; rewind Tbl + + $LD r16,`0*$SZ`($ctx) + $LD r17,`1*$SZ`($ctx) + $LD r18,`2*$SZ`($ctx) + $LD r19,`3*$SZ`($ctx) + $LD r20,`4*$SZ`($ctx) + $LD r21,`5*$SZ`($ctx) + $LD r22,`6*$SZ`($ctx) + addi $inp,$inp,`16*$SZ` ; advance inp + $LD r23,`7*$SZ`($ctx) + add $A,$A,r16 + add $B,$B,r17 + $PUSH $inp,`$FRAME-$SIZE_T*23`($sp) + add $C,$C,r18 + $ST $A,`0*$SZ`($ctx) + add $D,$D,r19 + $ST $B,`1*$SZ`($ctx) + add $E,$E,r20 + $ST $C,`2*$SZ`($ctx) + add $F,$F,r21 + $ST $D,`3*$SZ`($ctx) + add $G,$G,r22 + $ST $E,`4*$SZ`($ctx) + add $H,$H,r23 + $ST $F,`5*$SZ`($ctx) + $ST $G,`6*$SZ`($ctx) + $UCMP $inp,$num + $ST $H,`7*$SZ`($ctx) + bne Lsha2_block_private + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 +.size $func,.-$func +___ +} else { +######################################################################## +# SHA512 for PPC32, X vector is off-loaded to stack... +# +# | sha512 +# | -m32 +# ----------------------+----------------------- +# PPC74x0,gcc-4.0.1 | +48% +# POWER6,gcc-4.4.6 | +124%(*) +# POWER7,gcc-4.4.6 | +79%(*) +# e300,gcc-4.1.0 | +167% +# +# (*) ~1/3 of -m64 result [and ~20% better than -m32 code generated +# by xlc-12.1] + +my $XOFF=$LOCALS; + +my @V=map("r$_",(16..31)); # A..H + +my ($s0,$s1,$t0,$t1,$t2,$t3,$a0,$a1,$a2,$a3)=map("r$_",(0,5,6,8..12,14,15)); +my ($x0,$x1)=("r3","r4"); # zaps $ctx and $inp + +sub ROUND_00_15_ppc32 { +my ($i, $ahi,$alo,$bhi,$blo,$chi,$clo,$dhi,$dlo, + $ehi,$elo,$fhi,$flo,$ghi,$glo,$hhi,$hlo)=@_; + +$code.=<<___; + lwz $t2,`$SZ*($i%16)+($LITTLE_ENDIAN^4)`($Tbl) + xor $a0,$flo,$glo + lwz $t3,`$SZ*($i%16)+($LITTLE_ENDIAN^0)`($Tbl) + xor $a1,$fhi,$ghi + addc $hlo,$hlo,$t0 ; h+=x[i] + stw $t0,`$XOFF+0+$SZ*($i%16)`($sp) ; save x[i] + + srwi $s0,$elo,$Sigma1[0] + srwi $s1,$ehi,$Sigma1[0] + and $a0,$a0,$elo + adde $hhi,$hhi,$t1 + and $a1,$a1,$ehi + stw $t1,`$XOFF+4+$SZ*($i%16)`($sp) + srwi $t0,$elo,$Sigma1[1] + srwi $t1,$ehi,$Sigma1[1] + addc $hlo,$hlo,$t2 ; h+=K512[i] + insrwi $s0,$ehi,$Sigma1[0],0 + insrwi $s1,$elo,$Sigma1[0],0 + xor $a0,$a0,$glo ; Ch(e,f,g) + adde $hhi,$hhi,$t3 + xor $a1,$a1,$ghi + insrwi $t0,$ehi,$Sigma1[1],0 + insrwi $t1,$elo,$Sigma1[1],0 + addc $hlo,$hlo,$a0 ; h+=Ch(e,f,g) + srwi $t2,$ehi,$Sigma1[2]-32 + srwi $t3,$elo,$Sigma1[2]-32 + xor $s0,$s0,$t0 + xor $s1,$s1,$t1 + insrwi $t2,$elo,$Sigma1[2]-32,0 + insrwi $t3,$ehi,$Sigma1[2]-32,0 + xor $a0,$alo,$blo ; a^b, b^c in next round + adde $hhi,$hhi,$a1 + xor $a1,$ahi,$bhi + xor $s0,$s0,$t2 ; Sigma1(e) + xor $s1,$s1,$t3 + + srwi $t0,$alo,$Sigma0[0] + and $a2,$a2,$a0 + addc $hlo,$hlo,$s0 ; h+=Sigma1(e) + and $a3,$a3,$a1 + srwi $t1,$ahi,$Sigma0[0] + srwi $s0,$ahi,$Sigma0[1]-32 + adde $hhi,$hhi,$s1 + srwi $s1,$alo,$Sigma0[1]-32 + insrwi $t0,$ahi,$Sigma0[0],0 + insrwi $t1,$alo,$Sigma0[0],0 + xor $a2,$a2,$blo ; Maj(a,b,c) + addc $dlo,$dlo,$hlo ; d+=h + xor $a3,$a3,$bhi + insrwi $s0,$alo,$Sigma0[1]-32,0 + insrwi $s1,$ahi,$Sigma0[1]-32,0 + adde $dhi,$dhi,$hhi + srwi $t2,$ahi,$Sigma0[2]-32 + srwi $t3,$alo,$Sigma0[2]-32 + xor $s0,$s0,$t0 + addc $hlo,$hlo,$a2 ; h+=Maj(a,b,c) + xor $s1,$s1,$t1 + insrwi $t2,$alo,$Sigma0[2]-32,0 + insrwi $t3,$ahi,$Sigma0[2]-32,0 + adde $hhi,$hhi,$a3 +___ +$code.=<<___ if ($i>=15); + lwz $t0,`$XOFF+0+$SZ*(($i+2)%16)`($sp) + lwz $t1,`$XOFF+4+$SZ*(($i+2)%16)`($sp) +___ +$code.=<<___ if ($i<15 && !$LITTLE_ENDIAN); + lwz $t1,`$SZ*($i+1)+0`($inp) + lwz $t0,`$SZ*($i+1)+4`($inp) +___ +$code.=<<___ if ($i<15 && $LITTLE_ENDIAN); + lwz $a2,`$SZ*($i+1)+0`($inp) + lwz $a3,`$SZ*($i+1)+4`($inp) + rotlwi $t1,$a2,8 + rotlwi $t0,$a3,8 + rlwimi $t1,$a2,24,0,7 + rlwimi $t0,$a3,24,0,7 + rlwimi $t1,$a2,24,16,23 + rlwimi $t0,$a3,24,16,23 +___ +$code.=<<___; + xor $s0,$s0,$t2 ; Sigma0(a) + xor $s1,$s1,$t3 + addc $hlo,$hlo,$s0 ; h+=Sigma0(a) + adde $hhi,$hhi,$s1 +___ +$code.=<<___ if ($i==15); + lwz $x0,`$XOFF+0+$SZ*(($i+1)%16)`($sp) + lwz $x1,`$XOFF+4+$SZ*(($i+1)%16)`($sp) +___ +} +sub ROUND_16_xx_ppc32 { +my ($i, $ahi,$alo,$bhi,$blo,$chi,$clo,$dhi,$dlo, + $ehi,$elo,$fhi,$flo,$ghi,$glo,$hhi,$hlo)=@_; + +$code.=<<___; + srwi $s0,$t0,$sigma0[0] + srwi $s1,$t1,$sigma0[0] + srwi $t2,$t0,$sigma0[1] + srwi $t3,$t1,$sigma0[1] + insrwi $s0,$t1,$sigma0[0],0 + insrwi $s1,$t0,$sigma0[0],0 + srwi $a0,$t0,$sigma0[2] + insrwi $t2,$t1,$sigma0[1],0 + insrwi $t3,$t0,$sigma0[1],0 + insrwi $a0,$t1,$sigma0[2],0 + xor $s0,$s0,$t2 + lwz $t2,`$XOFF+0+$SZ*(($i+14)%16)`($sp) + srwi $a1,$t1,$sigma0[2] + xor $s1,$s1,$t3 + lwz $t3,`$XOFF+4+$SZ*(($i+14)%16)`($sp) + xor $a0,$a0,$s0 + srwi $s0,$t2,$sigma1[0] + xor $a1,$a1,$s1 + srwi $s1,$t3,$sigma1[0] + addc $x0,$x0,$a0 ; x[i]+=sigma0(x[i+1]) + srwi $a0,$t3,$sigma1[1]-32 + insrwi $s0,$t3,$sigma1[0],0 + insrwi $s1,$t2,$sigma1[0],0 + adde $x1,$x1,$a1 + srwi $a1,$t2,$sigma1[1]-32 + + insrwi $a0,$t2,$sigma1[1]-32,0 + srwi $t2,$t2,$sigma1[2] + insrwi $a1,$t3,$sigma1[1]-32,0 + insrwi $t2,$t3,$sigma1[2],0 + xor $s0,$s0,$a0 + lwz $a0,`$XOFF+0+$SZ*(($i+9)%16)`($sp) + srwi $t3,$t3,$sigma1[2] + xor $s1,$s1,$a1 + lwz $a1,`$XOFF+4+$SZ*(($i+9)%16)`($sp) + xor $s0,$s0,$t2 + addc $x0,$x0,$a0 ; x[i]+=x[i+9] + xor $s1,$s1,$t3 + adde $x1,$x1,$a1 + addc $x0,$x0,$s0 ; x[i]+=sigma1(x[i+14]) + adde $x1,$x1,$s1 +___ + ($t0,$t1,$x0,$x1) = ($x0,$x1,$t0,$t1); + &ROUND_00_15_ppc32(@_); +} + +$code.=<<___; +.align 4 +Lsha2_block_private: +___ +$code.=<<___ if (!$LITTLE_ENDIAN); + lwz $t1,0($inp) + xor $a2,@V[3],@V[5] ; B^C, magic seed + lwz $t0,4($inp) + xor $a3,@V[2],@V[4] +___ +$code.=<<___ if ($LITTLE_ENDIAN); + lwz $a1,0($inp) + xor $a2,@V[3],@V[5] ; B^C, magic seed + lwz $a0,4($inp) + xor $a3,@V[2],@V[4] + rotlwi $t1,$a1,8 + rotlwi $t0,$a0,8 + rlwimi $t1,$a1,24,0,7 + rlwimi $t0,$a0,24,0,7 + rlwimi $t1,$a1,24,16,23 + rlwimi $t0,$a0,24,16,23 +___ +for($i=0;$i<16;$i++) { + &ROUND_00_15_ppc32($i,@V); + unshift(@V,pop(@V)); unshift(@V,pop(@V)); + ($a0,$a1,$a2,$a3) = ($a2,$a3,$a0,$a1); +} +$code.=<<___; + li $a0,`$rounds/16-1` + mtctr $a0 +.align 4 +Lrounds: + addi $Tbl,$Tbl,`16*$SZ` +___ +for(;$i<32;$i++) { + &ROUND_16_xx_ppc32($i,@V); + unshift(@V,pop(@V)); unshift(@V,pop(@V)); + ($a0,$a1,$a2,$a3) = ($a2,$a3,$a0,$a1); +} +$code.=<<___; + bdnz Lrounds + + $POP $ctx,`$FRAME-$SIZE_T*22`($sp) + $POP $inp,`$FRAME-$SIZE_T*23`($sp) ; inp pointer + $POP $num,`$FRAME-$SIZE_T*24`($sp) ; end pointer + subi $Tbl,$Tbl,`($rounds-16)*$SZ` ; rewind Tbl + + lwz $t0,`$LITTLE_ENDIAN^0`($ctx) + lwz $t1,`$LITTLE_ENDIAN^4`($ctx) + lwz $t2,`$LITTLE_ENDIAN^8`($ctx) + lwz $t3,`$LITTLE_ENDIAN^12`($ctx) + lwz $a0,`$LITTLE_ENDIAN^16`($ctx) + lwz $a1,`$LITTLE_ENDIAN^20`($ctx) + lwz $a2,`$LITTLE_ENDIAN^24`($ctx) + addc @V[1],@V[1],$t1 + lwz $a3,`$LITTLE_ENDIAN^28`($ctx) + adde @V[0],@V[0],$t0 + lwz $t0,`$LITTLE_ENDIAN^32`($ctx) + addc @V[3],@V[3],$t3 + lwz $t1,`$LITTLE_ENDIAN^36`($ctx) + adde @V[2],@V[2],$t2 + lwz $t2,`$LITTLE_ENDIAN^40`($ctx) + addc @V[5],@V[5],$a1 + lwz $t3,`$LITTLE_ENDIAN^44`($ctx) + adde @V[4],@V[4],$a0 + lwz $a0,`$LITTLE_ENDIAN^48`($ctx) + addc @V[7],@V[7],$a3 + lwz $a1,`$LITTLE_ENDIAN^52`($ctx) + adde @V[6],@V[6],$a2 + lwz $a2,`$LITTLE_ENDIAN^56`($ctx) + addc @V[9],@V[9],$t1 + lwz $a3,`$LITTLE_ENDIAN^60`($ctx) + adde @V[8],@V[8],$t0 + stw @V[0],`$LITTLE_ENDIAN^0`($ctx) + stw @V[1],`$LITTLE_ENDIAN^4`($ctx) + addc @V[11],@V[11],$t3 + stw @V[2],`$LITTLE_ENDIAN^8`($ctx) + stw @V[3],`$LITTLE_ENDIAN^12`($ctx) + adde @V[10],@V[10],$t2 + stw @V[4],`$LITTLE_ENDIAN^16`($ctx) + stw @V[5],`$LITTLE_ENDIAN^20`($ctx) + addc @V[13],@V[13],$a1 + stw @V[6],`$LITTLE_ENDIAN^24`($ctx) + stw @V[7],`$LITTLE_ENDIAN^28`($ctx) + adde @V[12],@V[12],$a0 + stw @V[8],`$LITTLE_ENDIAN^32`($ctx) + stw @V[9],`$LITTLE_ENDIAN^36`($ctx) + addc @V[15],@V[15],$a3 + stw @V[10],`$LITTLE_ENDIAN^40`($ctx) + stw @V[11],`$LITTLE_ENDIAN^44`($ctx) + adde @V[14],@V[14],$a2 + stw @V[12],`$LITTLE_ENDIAN^48`($ctx) + stw @V[13],`$LITTLE_ENDIAN^52`($ctx) + stw @V[14],`$LITTLE_ENDIAN^56`($ctx) + stw @V[15],`$LITTLE_ENDIAN^60`($ctx) + + addi $inp,$inp,`16*$SZ` ; advance inp + $PUSH $inp,`$FRAME-$SIZE_T*23`($sp) + $UCMP $inp,$num + bne Lsha2_block_private + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 +.size $func,.-$func +___ +} + +# Ugly hack here, because PPC assembler syntax seem to vary too +# much from platforms to platform... +$code.=<<___; +.align 6 +LPICmeup: + mflr r0 + bcl 20,31,\$+4 + mflr $Tbl ; vvvvvv "distance" between . and 1st data entry + addi $Tbl,$Tbl,`64-8` + mtlr r0 + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 + .space `64-9*4` +___ +$code.=<<___ if ($SZ==8); + .quad 0x428a2f98d728ae22,0x7137449123ef65cd + .quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc + .quad 0x3956c25bf348b538,0x59f111f1b605d019 + .quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118 + .quad 0xd807aa98a3030242,0x12835b0145706fbe + .quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 + .quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1 + .quad 0x9bdc06a725c71235,0xc19bf174cf692694 + .quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3 + .quad 0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65 + .quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483 + .quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 + .quad 0x983e5152ee66dfab,0xa831c66d2db43210 + .quad 0xb00327c898fb213f,0xbf597fc7beef0ee4 + .quad 0xc6e00bf33da88fc2,0xd5a79147930aa725 + .quad 0x06ca6351e003826f,0x142929670a0e6e70 + .quad 0x27b70a8546d22ffc,0x2e1b21385c26c926 + .quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df + .quad 0x650a73548baf63de,0x766a0abb3c77b2a8 + .quad 0x81c2c92e47edaee6,0x92722c851482353b + .quad 0xa2bfe8a14cf10364,0xa81a664bbc423001 + .quad 0xc24b8b70d0f89791,0xc76c51a30654be30 + .quad 0xd192e819d6ef5218,0xd69906245565a910 + .quad 0xf40e35855771202a,0x106aa07032bbd1b8 + .quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53 + .quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 + .quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb + .quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 + .quad 0x748f82ee5defb2fc,0x78a5636f43172f60 + .quad 0x84c87814a1f0ab72,0x8cc702081a6439ec + .quad 0x90befffa23631e28,0xa4506cebde82bde9 + .quad 0xbef9a3f7b2c67915,0xc67178f2e372532b + .quad 0xca273eceea26619c,0xd186b8c721c0c207 + .quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 + .quad 0x06f067aa72176fba,0x0a637dc5a2c898a6 + .quad 0x113f9804bef90dae,0x1b710b35131c471b + .quad 0x28db77f523047d84,0x32caab7b40c72493 + .quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c + .quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a + .quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817 +___ +$code.=<<___ if ($SZ==4); + .long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 + .long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 + .long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 + .long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 + .long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc + .long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da + .long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 + .long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967 + .long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 + .long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 + .long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 + .long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 + .long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 + .long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 + .long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 + .long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 +___ + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-s390x.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-s390x.pl new file mode 100644 index 000000000..4c0f4e793 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-s390x.pl @@ -0,0 +1,324 @@ +#! /usr/bin/env perl +# Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# SHA256/512 block procedures for s390x. + +# April 2007. +# +# sha256_block_data_order is reportedly >3 times faster than gcc 3.3 +# generated code (must be a bug in compiler, as improvement is +# "pathologically" high, in particular in comparison to other SHA +# modules). But the real twist is that it detects if hardware support +# for SHA256 is available and in such case utilizes it. Then the +# performance can reach >6.5x of assembler one for larger chunks. +# +# sha512_block_data_order is ~70% faster than gcc 3.3 generated code. + +# January 2009. +# +# Add support for hardware SHA512 and reschedule instructions to +# favour dual-issue z10 pipeline. Hardware SHA256/512 is ~4.7x faster +# than software. + +# November 2010. +# +# Adapt for -m31 build. If kernel supports what's called "highgprs" +# feature on Linux [see /proc/cpuinfo], it's possible to use 64-bit +# instructions and achieve "64-bit" performance even in 31-bit legacy +# application context. The feature is not specific to any particular +# processor, as long as it's "z-CPU". Latter implies that the code +# remains z/Architecture specific. On z990 SHA256 was measured to +# perform 2.4x and SHA512 - 13x better than code generated by gcc 4.3. + +$flavour = shift; + +if ($flavour =~ /3[12]/) { + $SIZE_T=4; + $g=""; +} else { + $SIZE_T=8; + $g="g"; +} + +$t0="%r0"; +$t1="%r1"; +$ctx="%r2"; $t2="%r2"; +$inp="%r3"; +$len="%r4"; # used as index in inner loop + +$A="%r5"; +$B="%r6"; +$C="%r7"; +$D="%r8"; +$E="%r9"; +$F="%r10"; +$G="%r11"; +$H="%r12"; @V=($A,$B,$C,$D,$E,$F,$G,$H); +$tbl="%r13"; +$T1="%r14"; +$sp="%r15"; + +while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} +open STDOUT,">$output"; + +if ($output =~ /512/) { + $label="512"; + $SZ=8; + $LD="lg"; # load from memory + $ST="stg"; # store to memory + $ADD="alg"; # add with memory operand + $ROT="rllg"; # rotate left + $SHR="srlg"; # logical right shift [see even at the end] + @Sigma0=(25,30,36); + @Sigma1=(23,46,50); + @sigma0=(56,63, 7); + @sigma1=( 3,45, 6); + $rounds=80; + $kimdfunc=3; # 0 means unknown/unsupported/unimplemented/disabled +} else { + $label="256"; + $SZ=4; + $LD="llgf"; # load from memory + $ST="st"; # store to memory + $ADD="al"; # add with memory operand + $ROT="rll"; # rotate left + $SHR="srl"; # logical right shift + @Sigma0=(10,19,30); + @Sigma1=( 7,21,26); + @sigma0=(14,25, 3); + @sigma1=(13,15,10); + $rounds=64; + $kimdfunc=2; # magic function code for kimd instruction +} +$Func="sha${label}_block_data_order"; +$Table="K${label}"; +$stdframe=16*$SIZE_T+4*8; +$frame=$stdframe+16*$SZ; + +sub BODY_00_15 { +my ($i,$a,$b,$c,$d,$e,$f,$g,$h) = @_; + +$code.=<<___ if ($i<16); + $LD $T1,`$i*$SZ`($inp) ### $i +___ +$code.=<<___; + $ROT $t0,$e,$Sigma1[0] + $ROT $t1,$e,$Sigma1[1] + lgr $t2,$f + xgr $t0,$t1 + $ROT $t1,$t1,`$Sigma1[2]-$Sigma1[1]` + xgr $t2,$g + $ST $T1,`$stdframe+$SZ*($i%16)`($sp) + xgr $t0,$t1 # Sigma1(e) + algr $T1,$h # T1+=h + ngr $t2,$e + lgr $t1,$a + algr $T1,$t0 # T1+=Sigma1(e) + $ROT $h,$a,$Sigma0[0] + xgr $t2,$g # Ch(e,f,g) + $ADD $T1,`$i*$SZ`($len,$tbl) # T1+=K[i] + $ROT $t0,$a,$Sigma0[1] + algr $T1,$t2 # T1+=Ch(e,f,g) + ogr $t1,$b + xgr $h,$t0 + lgr $t2,$a + ngr $t1,$c + $ROT $t0,$t0,`$Sigma0[2]-$Sigma0[1]` + xgr $h,$t0 # h=Sigma0(a) + ngr $t2,$b + algr $h,$T1 # h+=T1 + ogr $t2,$t1 # Maj(a,b,c) + algr $d,$T1 # d+=T1 + algr $h,$t2 # h+=Maj(a,b,c) +___ +} + +sub BODY_16_XX { +my ($i,$a,$b,$c,$d,$e,$f,$g,$h) = @_; + +$code.=<<___; + $LD $T1,`$stdframe+$SZ*(($i+1)%16)`($sp) ### $i + $LD $t1,`$stdframe+$SZ*(($i+14)%16)`($sp) + $ROT $t0,$T1,$sigma0[0] + $SHR $T1,$sigma0[2] + $ROT $t2,$t0,`$sigma0[1]-$sigma0[0]` + xgr $T1,$t0 + $ROT $t0,$t1,$sigma1[0] + xgr $T1,$t2 # sigma0(X[i+1]) + $SHR $t1,$sigma1[2] + $ADD $T1,`$stdframe+$SZ*($i%16)`($sp) # +=X[i] + xgr $t1,$t0 + $ROT $t0,$t0,`$sigma1[1]-$sigma1[0]` + $ADD $T1,`$stdframe+$SZ*(($i+9)%16)`($sp) # +=X[i+9] + xgr $t1,$t0 # sigma1(X[i+14]) + algr $T1,$t1 # +=sigma1(X[i+14]) +___ + &BODY_00_15(@_); +} + +$code.=<<___; +#include "s390x_arch.h" + +.text +.align 64 +.type $Table,\@object +$Table: +___ +$code.=<<___ if ($SZ==4); + .long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 + .long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 + .long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 + .long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 + .long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc + .long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da + .long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 + .long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967 + .long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 + .long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 + .long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 + .long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 + .long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 + .long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 + .long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 + .long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 +___ +$code.=<<___ if ($SZ==8); + .quad 0x428a2f98d728ae22,0x7137449123ef65cd + .quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc + .quad 0x3956c25bf348b538,0x59f111f1b605d019 + .quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118 + .quad 0xd807aa98a3030242,0x12835b0145706fbe + .quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 + .quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1 + .quad 0x9bdc06a725c71235,0xc19bf174cf692694 + .quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3 + .quad 0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65 + .quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483 + .quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 + .quad 0x983e5152ee66dfab,0xa831c66d2db43210 + .quad 0xb00327c898fb213f,0xbf597fc7beef0ee4 + .quad 0xc6e00bf33da88fc2,0xd5a79147930aa725 + .quad 0x06ca6351e003826f,0x142929670a0e6e70 + .quad 0x27b70a8546d22ffc,0x2e1b21385c26c926 + .quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df + .quad 0x650a73548baf63de,0x766a0abb3c77b2a8 + .quad 0x81c2c92e47edaee6,0x92722c851482353b + .quad 0xa2bfe8a14cf10364,0xa81a664bbc423001 + .quad 0xc24b8b70d0f89791,0xc76c51a30654be30 + .quad 0xd192e819d6ef5218,0xd69906245565a910 + .quad 0xf40e35855771202a,0x106aa07032bbd1b8 + .quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53 + .quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 + .quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb + .quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 + .quad 0x748f82ee5defb2fc,0x78a5636f43172f60 + .quad 0x84c87814a1f0ab72,0x8cc702081a6439ec + .quad 0x90befffa23631e28,0xa4506cebde82bde9 + .quad 0xbef9a3f7b2c67915,0xc67178f2e372532b + .quad 0xca273eceea26619c,0xd186b8c721c0c207 + .quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 + .quad 0x06f067aa72176fba,0x0a637dc5a2c898a6 + .quad 0x113f9804bef90dae,0x1b710b35131c471b + .quad 0x28db77f523047d84,0x32caab7b40c72493 + .quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c + .quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a + .quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817 +___ +$code.=<<___; +.size $Table,.-$Table +.globl $Func +.type $Func,\@function +$Func: + sllg $len,$len,`log(16*$SZ)/log(2)` +___ +$code.=<<___ if ($kimdfunc); + larl %r1,OPENSSL_s390xcap_P + lg %r0,S390X_KIMD(%r1) # check kimd capabilities + tmhh %r0,`0x8000>>$kimdfunc` + jz .Lsoftware + lghi %r0,$kimdfunc + lgr %r1,$ctx + lgr %r2,$inp + lgr %r3,$len + .long 0xb93e0002 # kimd %r0,%r2 + brc 1,.-4 # pay attention to "partial completion" + br %r14 +.align 16 +.Lsoftware: +___ +$code.=<<___; + lghi %r1,-$frame + la $len,0($len,$inp) + stm${g} $ctx,%r15,`2*$SIZE_T`($sp) + lgr %r0,$sp + la $sp,0(%r1,$sp) + st${g} %r0,0($sp) + + larl $tbl,$Table + $LD $A,`0*$SZ`($ctx) + $LD $B,`1*$SZ`($ctx) + $LD $C,`2*$SZ`($ctx) + $LD $D,`3*$SZ`($ctx) + $LD $E,`4*$SZ`($ctx) + $LD $F,`5*$SZ`($ctx) + $LD $G,`6*$SZ`($ctx) + $LD $H,`7*$SZ`($ctx) + +.Lloop: + lghi $len,0 +___ +for ($i=0;$i<16;$i++) { &BODY_00_15($i,@V); unshift(@V,pop(@V)); } +$code.=".Lrounds_16_xx:\n"; +for (;$i<32;$i++) { &BODY_16_XX($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + aghi $len,`16*$SZ` + lghi $t0,`($rounds-16)*$SZ` + clgr $len,$t0 + jne .Lrounds_16_xx + + l${g} $ctx,`$frame+2*$SIZE_T`($sp) + la $inp,`16*$SZ`($inp) + $ADD $A,`0*$SZ`($ctx) + $ADD $B,`1*$SZ`($ctx) + $ADD $C,`2*$SZ`($ctx) + $ADD $D,`3*$SZ`($ctx) + $ADD $E,`4*$SZ`($ctx) + $ADD $F,`5*$SZ`($ctx) + $ADD $G,`6*$SZ`($ctx) + $ADD $H,`7*$SZ`($ctx) + $ST $A,`0*$SZ`($ctx) + $ST $B,`1*$SZ`($ctx) + $ST $C,`2*$SZ`($ctx) + $ST $D,`3*$SZ`($ctx) + $ST $E,`4*$SZ`($ctx) + $ST $F,`5*$SZ`($ctx) + $ST $G,`6*$SZ`($ctx) + $ST $H,`7*$SZ`($ctx) + cl${g} $inp,`$frame+4*$SIZE_T`($sp) + jne .Lloop + + lm${g} %r6,%r15,`$frame+6*$SIZE_T`($sp) + br %r14 +.size $Func,.-$Func +.string "SHA${label} block transform for s390x, CRYPTOGAMS by " +___ + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +# unlike 32-bit shift 64-bit one takes three arguments +$code =~ s/(srlg\s+)(%r[0-9]+),/$1$2,$2,/gm; + +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-sparcv9.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-sparcv9.pl new file mode 100644 index 000000000..4432bda65 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-sparcv9.pl @@ -0,0 +1,857 @@ +#! /usr/bin/env perl +# Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# +# Hardware SPARC T4 support by David S. Miller +# ==================================================================== + +# SHA256 performance improvement over compiler generated code varies +# from 40% for Sun C [32-bit build] to 70% for gcc [3.3, 64-bit +# build]. Just like in SHA1 module I aim to ensure scalability on +# UltraSPARC T1 by packing X[16] to 8 64-bit registers. + +# SHA512 on pre-T1 UltraSPARC. +# +# Performance is >75% better than 64-bit code generated by Sun C and +# over 2x than 32-bit code. X[16] resides on stack, but access to it +# is scheduled for L2 latency and staged through 32 least significant +# bits of %l0-%l7. The latter is done to achieve 32-/64-bit ABI +# duality. Nevetheless it's ~40% faster than SHA256, which is pretty +# good [optimal coefficient is 50%]. +# +# SHA512 on UltraSPARC T1. +# +# It's not any faster than 64-bit code generated by Sun C 5.8. This is +# because 64-bit code generator has the advantage of using 64-bit +# loads(*) to access X[16], which I consciously traded for 32-/64-bit +# ABI duality [as per above]. But it surpasses 32-bit Sun C generated +# code by 60%, not to mention that it doesn't suffer from severe decay +# when running 4 times physical cores threads and that it leaves gcc +# [3.4] behind by over 4x factor! If compared to SHA256, single thread +# performance is only 10% better, but overall throughput for maximum +# amount of threads for given CPU exceeds corresponding one of SHA256 +# by 30% [again, optimal coefficient is 50%]. +# +# (*) Unlike pre-T1 UltraSPARC loads on T1 are executed strictly +# in-order, i.e. load instruction has to complete prior next +# instruction in given thread is executed, even if the latter is +# not dependent on load result! This means that on T1 two 32-bit +# loads are always slower than one 64-bit load. Once again this +# is unlike pre-T1 UltraSPARC, where, if scheduled appropriately, +# 2x32-bit loads can be as fast as 1x64-bit ones. +# +# SPARC T4 SHA256/512 hardware achieves 3.17/2.01 cycles per byte, +# which is 9.3x/11.1x faster than software. Multi-process benchmark +# saturates at 11.5x single-process result on 8-core processor, or +# ~11/16GBps per 2.85GHz socket. + +$output=pop; +open STDOUT,">$output"; + +if ($output =~ /512/) { + $label="512"; + $SZ=8; + $LD="ldx"; # load from memory + $ST="stx"; # store to memory + $SLL="sllx"; # shift left logical + $SRL="srlx"; # shift right logical + @Sigma0=(28,34,39); + @Sigma1=(14,18,41); + @sigma0=( 7, 1, 8); # right shift first + @sigma1=( 6,19,61); # right shift first + $lastK=0x817; + $rounds=80; + $align=4; + + $locals=16*$SZ; # X[16] + + $A="%o0"; + $B="%o1"; + $C="%o2"; + $D="%o3"; + $E="%o4"; + $F="%o5"; + $G="%g1"; + $H="%o7"; + @V=($A,$B,$C,$D,$E,$F,$G,$H); +} else { + $label="256"; + $SZ=4; + $LD="ld"; # load from memory + $ST="st"; # store to memory + $SLL="sll"; # shift left logical + $SRL="srl"; # shift right logical + @Sigma0=( 2,13,22); + @Sigma1=( 6,11,25); + @sigma0=( 3, 7,18); # right shift first + @sigma1=(10,17,19); # right shift first + $lastK=0x8f2; + $rounds=64; + $align=8; + + $locals=0; # X[16] is register resident + @X=("%o0","%o1","%o2","%o3","%o4","%o5","%g1","%o7"); + + $A="%l0"; + $B="%l1"; + $C="%l2"; + $D="%l3"; + $E="%l4"; + $F="%l5"; + $G="%l6"; + $H="%l7"; + @V=($A,$B,$C,$D,$E,$F,$G,$H); +} +$T1="%g2"; +$tmp0="%g3"; +$tmp1="%g4"; +$tmp2="%g5"; + +$ctx="%i0"; +$inp="%i1"; +$len="%i2"; +$Ktbl="%i3"; +$tmp31="%i4"; +$tmp32="%i5"; + +########### SHA256 +$Xload = sub { +my ($i,$a,$b,$c,$d,$e,$f,$g,$h)=@_; + + if ($i==0) { +$code.=<<___; + ldx [$inp+0],@X[0] + ldx [$inp+16],@X[2] + ldx [$inp+32],@X[4] + ldx [$inp+48],@X[6] + ldx [$inp+8],@X[1] + ldx [$inp+24],@X[3] + subcc %g0,$tmp31,$tmp32 ! should be 64-$tmp31, but -$tmp31 works too + ldx [$inp+40],@X[5] + bz,pt %icc,.Laligned + ldx [$inp+56],@X[7] + + sllx @X[0],$tmp31,@X[0] + ldx [$inp+64],$T1 +___ +for($j=0;$j<7;$j++) +{ $code.=<<___; + srlx @X[$j+1],$tmp32,$tmp1 + sllx @X[$j+1],$tmp31,@X[$j+1] + or $tmp1,@X[$j],@X[$j] +___ +} +$code.=<<___; + srlx $T1,$tmp32,$T1 + or $T1,@X[7],@X[7] +.Laligned: +___ + } + + if ($i&1) { + $code.="\tadd @X[$i/2],$h,$T1\n"; + } else { + $code.="\tsrlx @X[$i/2],32,$T1\n\tadd $h,$T1,$T1\n"; + } +} if ($SZ==4); + +########### SHA512 +$Xload = sub { +my ($i,$a,$b,$c,$d,$e,$f,$g,$h)=@_; +my @pair=("%l".eval(($i*2)%8),"%l".eval(($i*2)%8+1),"%l".eval((($i+1)*2)%8)); + +$code.=<<___ if ($i==0); + ld [$inp+0],%l0 + ld [$inp+4],%l1 + ld [$inp+8],%l2 + ld [$inp+12],%l3 + ld [$inp+16],%l4 + ld [$inp+20],%l5 + ld [$inp+24],%l6 + cmp $tmp31,0 + ld [$inp+28],%l7 +___ +$code.=<<___ if ($i<15); + sllx @pair[1],$tmp31,$tmp2 ! Xload($i) + add $tmp31,32,$tmp0 + sllx @pair[0],$tmp0,$tmp1 + `"ld [$inp+".eval(32+0+$i*8)."],@pair[0]" if ($i<12)` + srlx @pair[2],$tmp32,@pair[1] + or $tmp1,$tmp2,$tmp2 + or @pair[1],$tmp2,$tmp2 + `"ld [$inp+".eval(32+4+$i*8)."],@pair[1]" if ($i<12)` + add $h,$tmp2,$T1 + $ST $tmp2,[%sp+STACK_BIAS+STACK_FRAME+`$i*$SZ`] +___ +$code.=<<___ if ($i==12); + bnz,a,pn %icc,.+8 + ld [$inp+128],%l0 +___ +$code.=<<___ if ($i==15); + ld [%sp+STACK_BIAS+STACK_FRAME+`(($i+1+1)%16)*$SZ+0`],%l2 + sllx @pair[1],$tmp31,$tmp2 ! Xload($i) + add $tmp31,32,$tmp0 + ld [%sp+STACK_BIAS+STACK_FRAME+`(($i+1+1)%16)*$SZ+4`],%l3 + sllx @pair[0],$tmp0,$tmp1 + ld [%sp+STACK_BIAS+STACK_FRAME+`(($i+1+9)%16)*$SZ+0`],%l4 + srlx @pair[2],$tmp32,@pair[1] + or $tmp1,$tmp2,$tmp2 + ld [%sp+STACK_BIAS+STACK_FRAME+`(($i+1+9)%16)*$SZ+4`],%l5 + or @pair[1],$tmp2,$tmp2 + ld [%sp+STACK_BIAS+STACK_FRAME+`(($i+1+14)%16)*$SZ+0`],%l6 + add $h,$tmp2,$T1 + $ST $tmp2,[%sp+STACK_BIAS+STACK_FRAME+`$i*$SZ`] + ld [%sp+STACK_BIAS+STACK_FRAME+`(($i+1+14)%16)*$SZ+4`],%l7 + ld [%sp+STACK_BIAS+STACK_FRAME+`(($i+1+0)%16)*$SZ+0`],%l0 + ld [%sp+STACK_BIAS+STACK_FRAME+`(($i+1+0)%16)*$SZ+4`],%l1 +___ +} if ($SZ==8); + +########### common +sub BODY_00_15 { +my ($i,$a,$b,$c,$d,$e,$f,$g,$h)=@_; + + if ($i<16) { + &$Xload(@_); + } else { + $code.="\tadd $h,$T1,$T1\n"; + } + +$code.=<<___; + $SRL $e,@Sigma1[0],$h !! $i + xor $f,$g,$tmp2 + $SLL $e,`$SZ*8-@Sigma1[2]`,$tmp1 + and $e,$tmp2,$tmp2 + $SRL $e,@Sigma1[1],$tmp0 + xor $tmp1,$h,$h + $SLL $e,`$SZ*8-@Sigma1[1]`,$tmp1 + xor $tmp0,$h,$h + $SRL $e,@Sigma1[2],$tmp0 + xor $tmp1,$h,$h + $SLL $e,`$SZ*8-@Sigma1[0]`,$tmp1 + xor $tmp0,$h,$h + xor $g,$tmp2,$tmp2 ! Ch(e,f,g) + xor $tmp1,$h,$tmp0 ! Sigma1(e) + + $SRL $a,@Sigma0[0],$h + add $tmp2,$T1,$T1 + $LD [$Ktbl+`$i*$SZ`],$tmp2 ! K[$i] + $SLL $a,`$SZ*8-@Sigma0[2]`,$tmp1 + add $tmp0,$T1,$T1 + $SRL $a,@Sigma0[1],$tmp0 + xor $tmp1,$h,$h + $SLL $a,`$SZ*8-@Sigma0[1]`,$tmp1 + xor $tmp0,$h,$h + $SRL $a,@Sigma0[2],$tmp0 + xor $tmp1,$h,$h + $SLL $a,`$SZ*8-@Sigma0[0]`,$tmp1 + xor $tmp0,$h,$h + xor $tmp1,$h,$h ! Sigma0(a) + + or $a,$b,$tmp0 + and $a,$b,$tmp1 + and $c,$tmp0,$tmp0 + or $tmp0,$tmp1,$tmp1 ! Maj(a,b,c) + add $tmp2,$T1,$T1 ! +=K[$i] + add $tmp1,$h,$h + + add $T1,$d,$d + add $T1,$h,$h +___ +} + +########### SHA256 +$BODY_16_XX = sub { +my $i=@_[0]; +my $xi; + + if ($i&1) { + $xi=$tmp32; + $code.="\tsrlx @X[(($i+1)/2)%8],32,$xi\n"; + } else { + $xi=@X[(($i+1)/2)%8]; + } +$code.=<<___; + srl $xi,@sigma0[0],$T1 !! Xupdate($i) + sll $xi,`32-@sigma0[2]`,$tmp1 + srl $xi,@sigma0[1],$tmp0 + xor $tmp1,$T1,$T1 + sll $tmp1,`@sigma0[2]-@sigma0[1]`,$tmp1 + xor $tmp0,$T1,$T1 + srl $xi,@sigma0[2],$tmp0 + xor $tmp1,$T1,$T1 +___ + if ($i&1) { + $xi=@X[(($i+14)/2)%8]; + } else { + $xi=$tmp32; + $code.="\tsrlx @X[(($i+14)/2)%8],32,$xi\n"; + } +$code.=<<___; + srl $xi,@sigma1[0],$tmp2 + xor $tmp0,$T1,$T1 ! T1=sigma0(X[i+1]) + sll $xi,`32-@sigma1[2]`,$tmp1 + srl $xi,@sigma1[1],$tmp0 + xor $tmp1,$tmp2,$tmp2 + sll $tmp1,`@sigma1[2]-@sigma1[1]`,$tmp1 + xor $tmp0,$tmp2,$tmp2 + srl $xi,@sigma1[2],$tmp0 + xor $tmp1,$tmp2,$tmp2 +___ + if ($i&1) { + $xi=@X[($i/2)%8]; +$code.=<<___; + srlx @X[(($i+9)/2)%8],32,$tmp1 ! X[i+9] + xor $tmp0,$tmp2,$tmp2 ! sigma1(X[i+14]) + srl @X[($i/2)%8],0,$tmp0 + add $tmp2,$tmp1,$tmp1 + add $xi,$T1,$T1 ! +=X[i] + xor $tmp0,@X[($i/2)%8],@X[($i/2)%8] + add $tmp1,$T1,$T1 + + srl $T1,0,$T1 + or $T1,@X[($i/2)%8],@X[($i/2)%8] +___ + } else { + $xi=@X[(($i+9)/2)%8]; +$code.=<<___; + srlx @X[($i/2)%8],32,$tmp1 ! X[i] + xor $tmp0,$tmp2,$tmp2 ! sigma1(X[i+14]) + add $xi,$T1,$T1 ! +=X[i+9] + add $tmp2,$tmp1,$tmp1 + srl @X[($i/2)%8],0,@X[($i/2)%8] + add $tmp1,$T1,$T1 + + sllx $T1,32,$tmp0 + or $tmp0,@X[($i/2)%8],@X[($i/2)%8] +___ + } + &BODY_00_15(@_); +} if ($SZ==4); + +########### SHA512 +$BODY_16_XX = sub { +my $i=@_[0]; +my @pair=("%l".eval(($i*2)%8),"%l".eval(($i*2)%8+1)); + +$code.=<<___; + sllx %l2,32,$tmp0 !! Xupdate($i) + or %l3,$tmp0,$tmp0 + + srlx $tmp0,@sigma0[0],$T1 + ld [%sp+STACK_BIAS+STACK_FRAME+`(($i+1+1)%16)*$SZ+0`],%l2 + sllx $tmp0,`64-@sigma0[2]`,$tmp1 + ld [%sp+STACK_BIAS+STACK_FRAME+`(($i+1+1)%16)*$SZ+4`],%l3 + srlx $tmp0,@sigma0[1],$tmp0 + xor $tmp1,$T1,$T1 + sllx $tmp1,`@sigma0[2]-@sigma0[1]`,$tmp1 + xor $tmp0,$T1,$T1 + srlx $tmp0,`@sigma0[2]-@sigma0[1]`,$tmp0 + xor $tmp1,$T1,$T1 + sllx %l6,32,$tmp2 + xor $tmp0,$T1,$T1 ! sigma0(X[$i+1]) + or %l7,$tmp2,$tmp2 + + srlx $tmp2,@sigma1[0],$tmp1 + ld [%sp+STACK_BIAS+STACK_FRAME+`(($i+1+14)%16)*$SZ+0`],%l6 + sllx $tmp2,`64-@sigma1[2]`,$tmp0 + ld [%sp+STACK_BIAS+STACK_FRAME+`(($i+1+14)%16)*$SZ+4`],%l7 + srlx $tmp2,@sigma1[1],$tmp2 + xor $tmp0,$tmp1,$tmp1 + sllx $tmp0,`@sigma1[2]-@sigma1[1]`,$tmp0 + xor $tmp2,$tmp1,$tmp1 + srlx $tmp2,`@sigma1[2]-@sigma1[1]`,$tmp2 + xor $tmp0,$tmp1,$tmp1 + sllx %l4,32,$tmp0 + xor $tmp2,$tmp1,$tmp1 ! sigma1(X[$i+14]) + ld [%sp+STACK_BIAS+STACK_FRAME+`(($i+1+9)%16)*$SZ+0`],%l4 + or %l5,$tmp0,$tmp0 + ld [%sp+STACK_BIAS+STACK_FRAME+`(($i+1+9)%16)*$SZ+4`],%l5 + + sllx %l0,32,$tmp2 + add $tmp1,$T1,$T1 + ld [%sp+STACK_BIAS+STACK_FRAME+`(($i+1+0)%16)*$SZ+0`],%l0 + or %l1,$tmp2,$tmp2 + add $tmp0,$T1,$T1 ! +=X[$i+9] + ld [%sp+STACK_BIAS+STACK_FRAME+`(($i+1+0)%16)*$SZ+4`],%l1 + add $tmp2,$T1,$T1 ! +=X[$i] + $ST $T1,[%sp+STACK_BIAS+STACK_FRAME+`($i%16)*$SZ`] +___ + &BODY_00_15(@_); +} if ($SZ==8); + +$code.=<<___; +#include "sparc_arch.h" + +#ifdef __arch64__ +.register %g2,#scratch +.register %g3,#scratch +#endif + +.section ".text",#alloc,#execinstr + +.align 64 +K${label}: +.type K${label},#object +___ +if ($SZ==4) { +$code.=<<___; + .long 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5 + .long 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5 + .long 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3 + .long 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174 + .long 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc + .long 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da + .long 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7 + .long 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967 + .long 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13 + .long 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85 + .long 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3 + .long 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070 + .long 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5 + .long 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3 + .long 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208 + .long 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +___ +} else { +$code.=<<___; + .long 0x428a2f98,0xd728ae22, 0x71374491,0x23ef65cd + .long 0xb5c0fbcf,0xec4d3b2f, 0xe9b5dba5,0x8189dbbc + .long 0x3956c25b,0xf348b538, 0x59f111f1,0xb605d019 + .long 0x923f82a4,0xaf194f9b, 0xab1c5ed5,0xda6d8118 + .long 0xd807aa98,0xa3030242, 0x12835b01,0x45706fbe + .long 0x243185be,0x4ee4b28c, 0x550c7dc3,0xd5ffb4e2 + .long 0x72be5d74,0xf27b896f, 0x80deb1fe,0x3b1696b1 + .long 0x9bdc06a7,0x25c71235, 0xc19bf174,0xcf692694 + .long 0xe49b69c1,0x9ef14ad2, 0xefbe4786,0x384f25e3 + .long 0x0fc19dc6,0x8b8cd5b5, 0x240ca1cc,0x77ac9c65 + .long 0x2de92c6f,0x592b0275, 0x4a7484aa,0x6ea6e483 + .long 0x5cb0a9dc,0xbd41fbd4, 0x76f988da,0x831153b5 + .long 0x983e5152,0xee66dfab, 0xa831c66d,0x2db43210 + .long 0xb00327c8,0x98fb213f, 0xbf597fc7,0xbeef0ee4 + .long 0xc6e00bf3,0x3da88fc2, 0xd5a79147,0x930aa725 + .long 0x06ca6351,0xe003826f, 0x14292967,0x0a0e6e70 + .long 0x27b70a85,0x46d22ffc, 0x2e1b2138,0x5c26c926 + .long 0x4d2c6dfc,0x5ac42aed, 0x53380d13,0x9d95b3df + .long 0x650a7354,0x8baf63de, 0x766a0abb,0x3c77b2a8 + .long 0x81c2c92e,0x47edaee6, 0x92722c85,0x1482353b + .long 0xa2bfe8a1,0x4cf10364, 0xa81a664b,0xbc423001 + .long 0xc24b8b70,0xd0f89791, 0xc76c51a3,0x0654be30 + .long 0xd192e819,0xd6ef5218, 0xd6990624,0x5565a910 + .long 0xf40e3585,0x5771202a, 0x106aa070,0x32bbd1b8 + .long 0x19a4c116,0xb8d2d0c8, 0x1e376c08,0x5141ab53 + .long 0x2748774c,0xdf8eeb99, 0x34b0bcb5,0xe19b48a8 + .long 0x391c0cb3,0xc5c95a63, 0x4ed8aa4a,0xe3418acb + .long 0x5b9cca4f,0x7763e373, 0x682e6ff3,0xd6b2b8a3 + .long 0x748f82ee,0x5defb2fc, 0x78a5636f,0x43172f60 + .long 0x84c87814,0xa1f0ab72, 0x8cc70208,0x1a6439ec + .long 0x90befffa,0x23631e28, 0xa4506ceb,0xde82bde9 + .long 0xbef9a3f7,0xb2c67915, 0xc67178f2,0xe372532b + .long 0xca273ece,0xea26619c, 0xd186b8c7,0x21c0c207 + .long 0xeada7dd6,0xcde0eb1e, 0xf57d4f7f,0xee6ed178 + .long 0x06f067aa,0x72176fba, 0x0a637dc5,0xa2c898a6 + .long 0x113f9804,0xbef90dae, 0x1b710b35,0x131c471b + .long 0x28db77f5,0x23047d84, 0x32caab7b,0x40c72493 + .long 0x3c9ebe0a,0x15c9bebc, 0x431d67c4,0x9c100d4c + .long 0x4cc5d4be,0xcb3e42b6, 0x597f299c,0xfc657e2a + .long 0x5fcb6fab,0x3ad6faec, 0x6c44198c,0x4a475817 +___ +} +$code.=<<___; +.size K${label},.-K${label} + +#ifdef __PIC__ +SPARC_PIC_THUNK(%g1) +#endif + +.globl sha${label}_block_data_order +.align 32 +sha${label}_block_data_order: + SPARC_LOAD_ADDRESS_LEAF(OPENSSL_sparcv9cap_P,%g1,%g5) + ld [%g1+4],%g1 ! OPENSSL_sparcv9cap_P[1] + + andcc %g1, CFR_SHA${label}, %g0 + be .Lsoftware + nop +___ +$code.=<<___ if ($SZ==8); # SHA512 + ldd [%o0 + 0x00], %f0 ! load context + ldd [%o0 + 0x08], %f2 + ldd [%o0 + 0x10], %f4 + ldd [%o0 + 0x18], %f6 + ldd [%o0 + 0x20], %f8 + ldd [%o0 + 0x28], %f10 + andcc %o1, 0x7, %g0 + ldd [%o0 + 0x30], %f12 + bne,pn %icc, .Lhwunaligned + ldd [%o0 + 0x38], %f14 + +.Lhwaligned_loop: + ldd [%o1 + 0x00], %f16 + ldd [%o1 + 0x08], %f18 + ldd [%o1 + 0x10], %f20 + ldd [%o1 + 0x18], %f22 + ldd [%o1 + 0x20], %f24 + ldd [%o1 + 0x28], %f26 + ldd [%o1 + 0x30], %f28 + ldd [%o1 + 0x38], %f30 + ldd [%o1 + 0x40], %f32 + ldd [%o1 + 0x48], %f34 + ldd [%o1 + 0x50], %f36 + ldd [%o1 + 0x58], %f38 + ldd [%o1 + 0x60], %f40 + ldd [%o1 + 0x68], %f42 + ldd [%o1 + 0x70], %f44 + subcc %o2, 1, %o2 ! done yet? + ldd [%o1 + 0x78], %f46 + add %o1, 0x80, %o1 + prefetch [%o1 + 63], 20 + prefetch [%o1 + 64+63], 20 + + .word 0x81b02860 ! SHA512 + + bne,pt SIZE_T_CC, .Lhwaligned_loop + nop + +.Lhwfinish: + std %f0, [%o0 + 0x00] ! store context + std %f2, [%o0 + 0x08] + std %f4, [%o0 + 0x10] + std %f6, [%o0 + 0x18] + std %f8, [%o0 + 0x20] + std %f10, [%o0 + 0x28] + std %f12, [%o0 + 0x30] + retl + std %f14, [%o0 + 0x38] + +.align 16 +.Lhwunaligned: + alignaddr %o1, %g0, %o1 + + ldd [%o1 + 0x00], %f18 +.Lhwunaligned_loop: + ldd [%o1 + 0x08], %f20 + ldd [%o1 + 0x10], %f22 + ldd [%o1 + 0x18], %f24 + ldd [%o1 + 0x20], %f26 + ldd [%o1 + 0x28], %f28 + ldd [%o1 + 0x30], %f30 + ldd [%o1 + 0x38], %f32 + ldd [%o1 + 0x40], %f34 + ldd [%o1 + 0x48], %f36 + ldd [%o1 + 0x50], %f38 + ldd [%o1 + 0x58], %f40 + ldd [%o1 + 0x60], %f42 + ldd [%o1 + 0x68], %f44 + ldd [%o1 + 0x70], %f46 + ldd [%o1 + 0x78], %f48 + subcc %o2, 1, %o2 ! done yet? + ldd [%o1 + 0x80], %f50 + add %o1, 0x80, %o1 + prefetch [%o1 + 63], 20 + prefetch [%o1 + 64+63], 20 + + faligndata %f18, %f20, %f16 + faligndata %f20, %f22, %f18 + faligndata %f22, %f24, %f20 + faligndata %f24, %f26, %f22 + faligndata %f26, %f28, %f24 + faligndata %f28, %f30, %f26 + faligndata %f30, %f32, %f28 + faligndata %f32, %f34, %f30 + faligndata %f34, %f36, %f32 + faligndata %f36, %f38, %f34 + faligndata %f38, %f40, %f36 + faligndata %f40, %f42, %f38 + faligndata %f42, %f44, %f40 + faligndata %f44, %f46, %f42 + faligndata %f46, %f48, %f44 + faligndata %f48, %f50, %f46 + + .word 0x81b02860 ! SHA512 + + bne,pt SIZE_T_CC, .Lhwunaligned_loop + for %f50, %f50, %f18 ! %f18=%f50 + + ba .Lhwfinish + nop +___ +$code.=<<___ if ($SZ==4); # SHA256 + ld [%o0 + 0x00], %f0 + ld [%o0 + 0x04], %f1 + ld [%o0 + 0x08], %f2 + ld [%o0 + 0x0c], %f3 + ld [%o0 + 0x10], %f4 + ld [%o0 + 0x14], %f5 + andcc %o1, 0x7, %g0 + ld [%o0 + 0x18], %f6 + bne,pn %icc, .Lhwunaligned + ld [%o0 + 0x1c], %f7 + +.Lhwloop: + ldd [%o1 + 0x00], %f8 + ldd [%o1 + 0x08], %f10 + ldd [%o1 + 0x10], %f12 + ldd [%o1 + 0x18], %f14 + ldd [%o1 + 0x20], %f16 + ldd [%o1 + 0x28], %f18 + ldd [%o1 + 0x30], %f20 + subcc %o2, 1, %o2 ! done yet? + ldd [%o1 + 0x38], %f22 + add %o1, 0x40, %o1 + prefetch [%o1 + 63], 20 + + .word 0x81b02840 ! SHA256 + + bne,pt SIZE_T_CC, .Lhwloop + nop + +.Lhwfinish: + st %f0, [%o0 + 0x00] ! store context + st %f1, [%o0 + 0x04] + st %f2, [%o0 + 0x08] + st %f3, [%o0 + 0x0c] + st %f4, [%o0 + 0x10] + st %f5, [%o0 + 0x14] + st %f6, [%o0 + 0x18] + retl + st %f7, [%o0 + 0x1c] + +.align 8 +.Lhwunaligned: + alignaddr %o1, %g0, %o1 + + ldd [%o1 + 0x00], %f10 +.Lhwunaligned_loop: + ldd [%o1 + 0x08], %f12 + ldd [%o1 + 0x10], %f14 + ldd [%o1 + 0x18], %f16 + ldd [%o1 + 0x20], %f18 + ldd [%o1 + 0x28], %f20 + ldd [%o1 + 0x30], %f22 + ldd [%o1 + 0x38], %f24 + subcc %o2, 1, %o2 ! done yet? + ldd [%o1 + 0x40], %f26 + add %o1, 0x40, %o1 + prefetch [%o1 + 63], 20 + + faligndata %f10, %f12, %f8 + faligndata %f12, %f14, %f10 + faligndata %f14, %f16, %f12 + faligndata %f16, %f18, %f14 + faligndata %f18, %f20, %f16 + faligndata %f20, %f22, %f18 + faligndata %f22, %f24, %f20 + faligndata %f24, %f26, %f22 + + .word 0x81b02840 ! SHA256 + + bne,pt SIZE_T_CC, .Lhwunaligned_loop + for %f26, %f26, %f10 ! %f10=%f26 + + ba .Lhwfinish + nop +___ +$code.=<<___; +.align 16 +.Lsoftware: + save %sp,-STACK_FRAME-$locals,%sp + and $inp,`$align-1`,$tmp31 + sllx $len,`log(16*$SZ)/log(2)`,$len + andn $inp,`$align-1`,$inp + sll $tmp31,3,$tmp31 + add $inp,$len,$len +___ +$code.=<<___ if ($SZ==8); # SHA512 + mov 32,$tmp32 + sub $tmp32,$tmp31,$tmp32 +___ +$code.=<<___; +.Lpic: call .+8 + add %o7,K${label}-.Lpic,$Ktbl + + $LD [$ctx+`0*$SZ`],$A + $LD [$ctx+`1*$SZ`],$B + $LD [$ctx+`2*$SZ`],$C + $LD [$ctx+`3*$SZ`],$D + $LD [$ctx+`4*$SZ`],$E + $LD [$ctx+`5*$SZ`],$F + $LD [$ctx+`6*$SZ`],$G + $LD [$ctx+`7*$SZ`],$H + +.Lloop: +___ +for ($i=0;$i<16;$i++) { &BODY_00_15($i,@V); unshift(@V,pop(@V)); } +$code.=".L16_xx:\n"; +for (;$i<32;$i++) { &$BODY_16_XX($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + and $tmp2,0xfff,$tmp2 + cmp $tmp2,$lastK + bne .L16_xx + add $Ktbl,`16*$SZ`,$Ktbl ! Ktbl+=16 + +___ +$code.=<<___ if ($SZ==4); # SHA256 + $LD [$ctx+`0*$SZ`],@X[0] + $LD [$ctx+`1*$SZ`],@X[1] + $LD [$ctx+`2*$SZ`],@X[2] + $LD [$ctx+`3*$SZ`],@X[3] + $LD [$ctx+`4*$SZ`],@X[4] + $LD [$ctx+`5*$SZ`],@X[5] + $LD [$ctx+`6*$SZ`],@X[6] + $LD [$ctx+`7*$SZ`],@X[7] + + add $A,@X[0],$A + $ST $A,[$ctx+`0*$SZ`] + add $B,@X[1],$B + $ST $B,[$ctx+`1*$SZ`] + add $C,@X[2],$C + $ST $C,[$ctx+`2*$SZ`] + add $D,@X[3],$D + $ST $D,[$ctx+`3*$SZ`] + add $E,@X[4],$E + $ST $E,[$ctx+`4*$SZ`] + add $F,@X[5],$F + $ST $F,[$ctx+`5*$SZ`] + add $G,@X[6],$G + $ST $G,[$ctx+`6*$SZ`] + add $H,@X[7],$H + $ST $H,[$ctx+`7*$SZ`] +___ +$code.=<<___ if ($SZ==8); # SHA512 + ld [$ctx+`0*$SZ+0`],%l0 + ld [$ctx+`0*$SZ+4`],%l1 + ld [$ctx+`1*$SZ+0`],%l2 + ld [$ctx+`1*$SZ+4`],%l3 + ld [$ctx+`2*$SZ+0`],%l4 + ld [$ctx+`2*$SZ+4`],%l5 + ld [$ctx+`3*$SZ+0`],%l6 + + sllx %l0,32,$tmp0 + ld [$ctx+`3*$SZ+4`],%l7 + sllx %l2,32,$tmp1 + or %l1,$tmp0,$tmp0 + or %l3,$tmp1,$tmp1 + add $tmp0,$A,$A + add $tmp1,$B,$B + $ST $A,[$ctx+`0*$SZ`] + sllx %l4,32,$tmp2 + $ST $B,[$ctx+`1*$SZ`] + sllx %l6,32,$T1 + or %l5,$tmp2,$tmp2 + or %l7,$T1,$T1 + add $tmp2,$C,$C + $ST $C,[$ctx+`2*$SZ`] + add $T1,$D,$D + $ST $D,[$ctx+`3*$SZ`] + + ld [$ctx+`4*$SZ+0`],%l0 + ld [$ctx+`4*$SZ+4`],%l1 + ld [$ctx+`5*$SZ+0`],%l2 + ld [$ctx+`5*$SZ+4`],%l3 + ld [$ctx+`6*$SZ+0`],%l4 + ld [$ctx+`6*$SZ+4`],%l5 + ld [$ctx+`7*$SZ+0`],%l6 + + sllx %l0,32,$tmp0 + ld [$ctx+`7*$SZ+4`],%l7 + sllx %l2,32,$tmp1 + or %l1,$tmp0,$tmp0 + or %l3,$tmp1,$tmp1 + add $tmp0,$E,$E + add $tmp1,$F,$F + $ST $E,[$ctx+`4*$SZ`] + sllx %l4,32,$tmp2 + $ST $F,[$ctx+`5*$SZ`] + sllx %l6,32,$T1 + or %l5,$tmp2,$tmp2 + or %l7,$T1,$T1 + add $tmp2,$G,$G + $ST $G,[$ctx+`6*$SZ`] + add $T1,$H,$H + $ST $H,[$ctx+`7*$SZ`] +___ +$code.=<<___; + add $inp,`16*$SZ`,$inp ! advance inp + cmp $inp,$len + bne SIZE_T_CC,.Lloop + sub $Ktbl,`($rounds-16)*$SZ`,$Ktbl ! rewind Ktbl + + ret + restore +.type sha${label}_block_data_order,#function +.size sha${label}_block_data_order,(.-sha${label}_block_data_order) +.asciz "SHA${label} block transform for SPARCv9, CRYPTOGAMS by " +.align 4 +___ + +# Purpose of these subroutines is to explicitly encode VIS instructions, +# so that one can compile the module without having to specify VIS +# extensions on compiler command line, e.g. -xarch=v9 vs. -xarch=v9a. +# Idea is to reserve for option to produce "universal" binary and let +# programmer detect if current CPU is VIS capable at run-time. +sub unvis { +my ($mnemonic,$rs1,$rs2,$rd)=@_; +my $ref,$opf; +my %visopf = ( "faligndata" => 0x048, + "for" => 0x07c ); + + $ref = "$mnemonic\t$rs1,$rs2,$rd"; + + if ($opf=$visopf{$mnemonic}) { + foreach ($rs1,$rs2,$rd) { + return $ref if (!/%f([0-9]{1,2})/); + $_=$1; + if ($1>=32) { + return $ref if ($1&1); + # re-encode for upper double register addressing + $_=($1|$1>>5)&31; + } + } + + return sprintf ".word\t0x%08x !%s", + 0x81b00000|$rd<<25|$rs1<<14|$opf<<5|$rs2, + $ref; + } else { + return $ref; + } +} +sub unalignaddr { +my ($mnemonic,$rs1,$rs2,$rd)=@_; +my %bias = ( "g" => 0, "o" => 8, "l" => 16, "i" => 24 ); +my $ref="$mnemonic\t$rs1,$rs2,$rd"; + + foreach ($rs1,$rs2,$rd) { + if (/%([goli])([0-7])/) { $_=$bias{$1}+$2; } + else { return $ref; } + } + return sprintf ".word\t0x%08x !%s", + 0x81b00300|$rd<<25|$rs1<<14|$rs2, + $ref; +} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/ge; + + s/\b(f[^\s]*)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*(%f[0-9]{1,2})/ + &unvis($1,$2,$3,$4) + /ge; + s/\b(alignaddr)\s+(%[goli][0-7]),\s*(%[goli][0-7]),\s*(%[goli][0-7])/ + &unalignaddr($1,$2,$3,$4) + /ge; + + print $_,"\n"; +} + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-x86_64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-x86_64.pl new file mode 100755 index 000000000..f2ebdfdb6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512-x86_64.pl @@ -0,0 +1,2498 @@ +#! /usr/bin/env perl +# Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. Rights for redistribution and usage in source and binary +# forms are granted according to the OpenSSL license. +# ==================================================================== +# +# sha256/512_block procedure for x86_64. +# +# 40% improvement over compiler-generated code on Opteron. On EM64T +# sha256 was observed to run >80% faster and sha512 - >40%. No magical +# tricks, just straight implementation... I really wonder why gcc +# [being armed with inline assembler] fails to generate as fast code. +# The only thing which is cool about this module is that it's very +# same instruction sequence used for both SHA-256 and SHA-512. In +# former case the instructions operate on 32-bit operands, while in +# latter - on 64-bit ones. All I had to do is to get one flavor right, +# the other one passed the test right away:-) +# +# sha256_block runs in ~1005 cycles on Opteron, which gives you +# asymptotic performance of 64*1000/1005=63.7MBps times CPU clock +# frequency in GHz. sha512_block runs in ~1275 cycles, which results +# in 128*1000/1275=100MBps per GHz. Is there room for improvement? +# Well, if you compare it to IA-64 implementation, which maintains +# X[16] in register bank[!], tends to 4 instructions per CPU clock +# cycle and runs in 1003 cycles, 1275 is very good result for 3-way +# issue Opteron pipeline and X[16] maintained in memory. So that *if* +# there is a way to improve it, *then* the only way would be to try to +# offload X[16] updates to SSE unit, but that would require "deeper" +# loop unroll, which in turn would naturally cause size blow-up, not +# to mention increased complexity! And once again, only *if* it's +# actually possible to noticeably improve overall ILP, instruction +# level parallelism, on a given CPU implementation in this case. +# +# Special note on Intel EM64T. While Opteron CPU exhibits perfect +# performance ratio of 1.5 between 64- and 32-bit flavors [see above], +# [currently available] EM64T CPUs apparently are far from it. On the +# contrary, 64-bit version, sha512_block, is ~30% *slower* than 32-bit +# sha256_block:-( This is presumably because 64-bit shifts/rotates +# apparently are not atomic instructions, but implemented in microcode. +# +# May 2012. +# +# Optimization including one of Pavel Semjanov's ideas, alternative +# Maj, resulted in >=5% improvement on most CPUs, +20% SHA256 and +# unfortunately -2% SHA512 on P4 [which nobody should care about +# that much]. +# +# June 2012. +# +# Add SIMD code paths, see below for improvement coefficients. SSSE3 +# code path was not attempted for SHA512, because improvement is not +# estimated to be high enough, noticeably less than 9%, to justify +# the effort, not on pre-AVX processors. [Obviously with exclusion +# for VIA Nano, but it has SHA512 instruction that is faster and +# should be used instead.] For reference, corresponding estimated +# upper limit for improvement for SSSE3 SHA256 is 28%. The fact that +# higher coefficients are observed on VIA Nano and Bulldozer has more +# to do with specifics of their architecture [which is topic for +# separate discussion]. +# +# November 2012. +# +# Add AVX2 code path. Two consecutive input blocks are loaded to +# 256-bit %ymm registers, with data from first block to least +# significant 128-bit halves and data from second to most significant. +# The data is then processed with same SIMD instruction sequence as +# for AVX, but with %ymm as operands. Side effect is increased stack +# frame, 448 additional bytes in SHA256 and 1152 in SHA512, and 1.2KB +# code size increase. +# +# March 2014. +# +# Add support for Intel SHA Extensions. + +###################################################################### +# Current performance in cycles per processed byte (less is better): +# +# SHA256 SSSE3 AVX/XOP(*) SHA512 AVX/XOP(*) +# +# AMD K8 14.9 - - 9.57 - +# P4 17.3 - - 30.8 - +# Core 2 15.6 13.8(+13%) - 9.97 - +# Westmere 14.8 12.3(+19%) - 9.58 - +# Sandy Bridge 17.4 14.2(+23%) 11.6(+50%(**)) 11.2 8.10(+38%(**)) +# Ivy Bridge 12.6 10.5(+20%) 10.3(+22%) 8.17 7.22(+13%) +# Haswell 12.2 9.28(+31%) 7.80(+56%) 7.66 5.40(+42%) +# Skylake 11.4 9.03(+26%) 7.70(+48%) 7.25 5.20(+40%) +# Bulldozer 21.1 13.6(+54%) 13.6(+54%(***)) 13.5 8.58(+57%) +# Ryzen 11.0 9.02(+22%) 2.05(+440%) 7.05 5.67(+20%) +# VIA Nano 23.0 16.5(+39%) - 14.7 - +# Atom 23.0 18.9(+22%) - 14.7 - +# Silvermont 27.4 20.6(+33%) - 17.5 - +# Knights L 27.4 21.0(+30%) 19.6(+40%) 17.5 12.8(+37%) +# Goldmont 18.9 14.3(+32%) 4.16(+350%) 12.0 - +# +# (*) whichever best applicable, including SHAEXT; +# (**) switch from ror to shrd stands for fair share of improvement; +# (***) execution time is fully determined by remaining integer-only +# part, body_00_15; reducing the amount of SIMD instructions +# below certain limit makes no difference/sense; to conserve +# space SHA256 XOP code path is therefore omitted; + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler version ([2-9]\.[0-9]+)/) { + $avx = ($1>=2.19) + ($1>=2.22); +} + +if (!$avx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) && + `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) { + $avx = ($1>=2.09) + ($1>=2.10); +} + +if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && + `ml64 2>&1` =~ /Version ([0-9]+)\./) { + $avx = ($1>=10) + ($1>=11); +} + +if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9]\.[0-9]+)/) { + $avx = ($2>=3.0) + ($2>3.0); +} + +$shaext=1; ### set to zero if compiling for 1.0.1 +$avx=1 if (!$shaext && $avx); + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +*STDOUT=*OUT; + +if ($output =~ /512/) { + $func="sha512_block_data_order"; + $TABLE="K512"; + $SZ=8; + @ROT=($A,$B,$C,$D,$E,$F,$G,$H)=("%rax","%rbx","%rcx","%rdx", + "%r8", "%r9", "%r10","%r11"); + ($T1,$a0,$a1,$a2,$a3)=("%r12","%r13","%r14","%r15","%rdi"); + @Sigma0=(28,34,39); + @Sigma1=(14,18,41); + @sigma0=(1, 8, 7); + @sigma1=(19,61, 6); + $rounds=80; +} else { + $func="sha256_block_data_order"; + $TABLE="K256"; + $SZ=4; + @ROT=($A,$B,$C,$D,$E,$F,$G,$H)=("%eax","%ebx","%ecx","%edx", + "%r8d","%r9d","%r10d","%r11d"); + ($T1,$a0,$a1,$a2,$a3)=("%r12d","%r13d","%r14d","%r15d","%edi"); + @Sigma0=( 2,13,22); + @Sigma1=( 6,11,25); + @sigma0=( 7,18, 3); + @sigma1=(17,19,10); + $rounds=64; +} + +$ctx="%rdi"; # 1st arg, zapped by $a3 +$inp="%rsi"; # 2nd arg +$Tbl="%rbp"; + +$_ctx="16*$SZ+0*8(%rsp)"; +$_inp="16*$SZ+1*8(%rsp)"; +$_end="16*$SZ+2*8(%rsp)"; +$_rsp="`16*$SZ+3*8`(%rsp)"; +$framesz="16*$SZ+4*8"; + + +sub ROUND_00_15() +{ my ($i,$a,$b,$c,$d,$e,$f,$g,$h) = @_; + my $STRIDE=$SZ; + $STRIDE += 16 if ($i%(16/$SZ)==(16/$SZ-1)); + +$code.=<<___; + ror \$`$Sigma1[2]-$Sigma1[1]`,$a0 + mov $f,$a2 + + xor $e,$a0 + ror \$`$Sigma0[2]-$Sigma0[1]`,$a1 + xor $g,$a2 # f^g + + mov $T1,`$SZ*($i&0xf)`(%rsp) + xor $a,$a1 + and $e,$a2 # (f^g)&e + + ror \$`$Sigma1[1]-$Sigma1[0]`,$a0 + add $h,$T1 # T1+=h + xor $g,$a2 # Ch(e,f,g)=((f^g)&e)^g + + ror \$`$Sigma0[1]-$Sigma0[0]`,$a1 + xor $e,$a0 + add $a2,$T1 # T1+=Ch(e,f,g) + + mov $a,$a2 + add ($Tbl),$T1 # T1+=K[round] + xor $a,$a1 + + xor $b,$a2 # a^b, b^c in next round + ror \$$Sigma1[0],$a0 # Sigma1(e) + mov $b,$h + + and $a2,$a3 + ror \$$Sigma0[0],$a1 # Sigma0(a) + add $a0,$T1 # T1+=Sigma1(e) + + xor $a3,$h # h=Maj(a,b,c)=Ch(a^b,c,b) + add $T1,$d # d+=T1 + add $T1,$h # h+=T1 + + lea $STRIDE($Tbl),$Tbl # round++ +___ +$code.=<<___ if ($i<15); + add $a1,$h # h+=Sigma0(a) +___ + ($a2,$a3) = ($a3,$a2); +} + +sub ROUND_16_XX() +{ my ($i,$a,$b,$c,$d,$e,$f,$g,$h) = @_; + +$code.=<<___; + mov `$SZ*(($i+1)&0xf)`(%rsp),$a0 + mov `$SZ*(($i+14)&0xf)`(%rsp),$a2 + + mov $a0,$T1 + ror \$`$sigma0[1]-$sigma0[0]`,$a0 + add $a1,$a # modulo-scheduled h+=Sigma0(a) + mov $a2,$a1 + ror \$`$sigma1[1]-$sigma1[0]`,$a2 + + xor $T1,$a0 + shr \$$sigma0[2],$T1 + ror \$$sigma0[0],$a0 + xor $a1,$a2 + shr \$$sigma1[2],$a1 + + ror \$$sigma1[0],$a2 + xor $a0,$T1 # sigma0(X[(i+1)&0xf]) + xor $a1,$a2 # sigma1(X[(i+14)&0xf]) + add `$SZ*(($i+9)&0xf)`(%rsp),$T1 + + add `$SZ*($i&0xf)`(%rsp),$T1 + mov $e,$a0 + add $a2,$T1 + mov $a,$a1 +___ + &ROUND_00_15(@_); +} + +$code=<<___; +.text + +.extern OPENSSL_ia32cap_P +.globl $func +.type $func,\@function,3 +.align 16 +$func: +.cfi_startproc +___ +$code.=<<___ if ($SZ==4 || $avx); + lea OPENSSL_ia32cap_P(%rip),%r11 + mov 0(%r11),%r9d + mov 4(%r11),%r10d + mov 8(%r11),%r11d +___ +$code.=<<___ if ($SZ==4 && $shaext); + test \$`1<<29`,%r11d # check for SHA + jnz _shaext_shortcut +___ +$code.=<<___ if ($avx && $SZ==8); + test \$`1<<11`,%r10d # check for XOP + jnz .Lxop_shortcut +___ +$code.=<<___ if ($avx>1); + and \$`1<<8|1<<5|1<<3`,%r11d # check for BMI2+AVX2+BMI1 + cmp \$`1<<8|1<<5|1<<3`,%r11d + je .Lavx2_shortcut +___ +$code.=<<___ if ($avx); + and \$`1<<30`,%r9d # mask "Intel CPU" bit + and \$`1<<28|1<<9`,%r10d # mask AVX and SSSE3 bits + or %r9d,%r10d + cmp \$`1<<28|1<<9|1<<30`,%r10d + je .Lavx_shortcut +___ +$code.=<<___ if ($SZ==4); + test \$`1<<9`,%r10d + jnz .Lssse3_shortcut +___ +$code.=<<___; + mov %rsp,%rax # copy %rsp +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + shl \$4,%rdx # num*16 + sub \$$framesz,%rsp + lea ($inp,%rdx,$SZ),%rdx # inp+num*16*$SZ + and \$-64,%rsp # align stack frame + mov $ctx,$_ctx # save ctx, 1st arg + mov $inp,$_inp # save inp, 2nd arh + mov %rdx,$_end # save end pointer, "3rd" arg + mov %rax,$_rsp # save copy of %rsp +.cfi_cfa_expression $_rsp,deref,+8 +.Lprologue: + + mov $SZ*0($ctx),$A + mov $SZ*1($ctx),$B + mov $SZ*2($ctx),$C + mov $SZ*3($ctx),$D + mov $SZ*4($ctx),$E + mov $SZ*5($ctx),$F + mov $SZ*6($ctx),$G + mov $SZ*7($ctx),$H + jmp .Lloop + +.align 16 +.Lloop: + mov $B,$a3 + lea $TABLE(%rip),$Tbl + xor $C,$a3 # magic +___ + for($i=0;$i<16;$i++) { + $code.=" mov $SZ*$i($inp),$T1\n"; + $code.=" mov @ROT[4],$a0\n"; + $code.=" mov @ROT[0],$a1\n"; + $code.=" bswap $T1\n"; + &ROUND_00_15($i,@ROT); + unshift(@ROT,pop(@ROT)); + } +$code.=<<___; + jmp .Lrounds_16_xx +.align 16 +.Lrounds_16_xx: +___ + for(;$i<32;$i++) { + &ROUND_16_XX($i,@ROT); + unshift(@ROT,pop(@ROT)); + } + +$code.=<<___; + cmpb \$0,`$SZ-1`($Tbl) + jnz .Lrounds_16_xx + + mov $_ctx,$ctx + add $a1,$A # modulo-scheduled h+=Sigma0(a) + lea 16*$SZ($inp),$inp + + add $SZ*0($ctx),$A + add $SZ*1($ctx),$B + add $SZ*2($ctx),$C + add $SZ*3($ctx),$D + add $SZ*4($ctx),$E + add $SZ*5($ctx),$F + add $SZ*6($ctx),$G + add $SZ*7($ctx),$H + + cmp $_end,$inp + + mov $A,$SZ*0($ctx) + mov $B,$SZ*1($ctx) + mov $C,$SZ*2($ctx) + mov $D,$SZ*3($ctx) + mov $E,$SZ*4($ctx) + mov $F,$SZ*5($ctx) + mov $G,$SZ*6($ctx) + mov $H,$SZ*7($ctx) + jb .Lloop + + mov $_rsp,%rsi +.cfi_def_cfa %rsi,8 + mov -48(%rsi),%r15 +.cfi_restore %r15 + mov -40(%rsi),%r14 +.cfi_restore %r14 + mov -32(%rsi),%r13 +.cfi_restore %r13 + mov -24(%rsi),%r12 +.cfi_restore %r12 + mov -16(%rsi),%rbp +.cfi_restore %rbp + mov -8(%rsi),%rbx +.cfi_restore %rbx + lea (%rsi),%rsp +.cfi_def_cfa_register %rsp +.Lepilogue: + ret +.cfi_endproc +.size $func,.-$func +___ + +if ($SZ==4) { +$code.=<<___; +.align 64 +.type $TABLE,\@object +$TABLE: + .long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 + .long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 + .long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 + .long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 + .long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 + .long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 + .long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 + .long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 + .long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc + .long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc + .long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da + .long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da + .long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 + .long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 + .long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967 + .long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967 + .long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 + .long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 + .long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 + .long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 + .long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 + .long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 + .long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 + .long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 + .long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 + .long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 + .long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 + .long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 + .long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 + .long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 + .long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 + .long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 + + .long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f + .long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f + .long 0x03020100,0x0b0a0908,0xffffffff,0xffffffff + .long 0x03020100,0x0b0a0908,0xffffffff,0xffffffff + .long 0xffffffff,0xffffffff,0x03020100,0x0b0a0908 + .long 0xffffffff,0xffffffff,0x03020100,0x0b0a0908 + .asciz "SHA256 block transform for x86_64, CRYPTOGAMS by " +___ +} else { +$code.=<<___; +.align 64 +.type $TABLE,\@object +$TABLE: + .quad 0x428a2f98d728ae22,0x7137449123ef65cd + .quad 0x428a2f98d728ae22,0x7137449123ef65cd + .quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc + .quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc + .quad 0x3956c25bf348b538,0x59f111f1b605d019 + .quad 0x3956c25bf348b538,0x59f111f1b605d019 + .quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118 + .quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118 + .quad 0xd807aa98a3030242,0x12835b0145706fbe + .quad 0xd807aa98a3030242,0x12835b0145706fbe + .quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 + .quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 + .quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1 + .quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1 + .quad 0x9bdc06a725c71235,0xc19bf174cf692694 + .quad 0x9bdc06a725c71235,0xc19bf174cf692694 + .quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3 + .quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3 + .quad 0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65 + .quad 0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65 + .quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483 + .quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483 + .quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 + .quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 + .quad 0x983e5152ee66dfab,0xa831c66d2db43210 + .quad 0x983e5152ee66dfab,0xa831c66d2db43210 + .quad 0xb00327c898fb213f,0xbf597fc7beef0ee4 + .quad 0xb00327c898fb213f,0xbf597fc7beef0ee4 + .quad 0xc6e00bf33da88fc2,0xd5a79147930aa725 + .quad 0xc6e00bf33da88fc2,0xd5a79147930aa725 + .quad 0x06ca6351e003826f,0x142929670a0e6e70 + .quad 0x06ca6351e003826f,0x142929670a0e6e70 + .quad 0x27b70a8546d22ffc,0x2e1b21385c26c926 + .quad 0x27b70a8546d22ffc,0x2e1b21385c26c926 + .quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df + .quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df + .quad 0x650a73548baf63de,0x766a0abb3c77b2a8 + .quad 0x650a73548baf63de,0x766a0abb3c77b2a8 + .quad 0x81c2c92e47edaee6,0x92722c851482353b + .quad 0x81c2c92e47edaee6,0x92722c851482353b + .quad 0xa2bfe8a14cf10364,0xa81a664bbc423001 + .quad 0xa2bfe8a14cf10364,0xa81a664bbc423001 + .quad 0xc24b8b70d0f89791,0xc76c51a30654be30 + .quad 0xc24b8b70d0f89791,0xc76c51a30654be30 + .quad 0xd192e819d6ef5218,0xd69906245565a910 + .quad 0xd192e819d6ef5218,0xd69906245565a910 + .quad 0xf40e35855771202a,0x106aa07032bbd1b8 + .quad 0xf40e35855771202a,0x106aa07032bbd1b8 + .quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53 + .quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53 + .quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 + .quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 + .quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb + .quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb + .quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 + .quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 + .quad 0x748f82ee5defb2fc,0x78a5636f43172f60 + .quad 0x748f82ee5defb2fc,0x78a5636f43172f60 + .quad 0x84c87814a1f0ab72,0x8cc702081a6439ec + .quad 0x84c87814a1f0ab72,0x8cc702081a6439ec + .quad 0x90befffa23631e28,0xa4506cebde82bde9 + .quad 0x90befffa23631e28,0xa4506cebde82bde9 + .quad 0xbef9a3f7b2c67915,0xc67178f2e372532b + .quad 0xbef9a3f7b2c67915,0xc67178f2e372532b + .quad 0xca273eceea26619c,0xd186b8c721c0c207 + .quad 0xca273eceea26619c,0xd186b8c721c0c207 + .quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 + .quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 + .quad 0x06f067aa72176fba,0x0a637dc5a2c898a6 + .quad 0x06f067aa72176fba,0x0a637dc5a2c898a6 + .quad 0x113f9804bef90dae,0x1b710b35131c471b + .quad 0x113f9804bef90dae,0x1b710b35131c471b + .quad 0x28db77f523047d84,0x32caab7b40c72493 + .quad 0x28db77f523047d84,0x32caab7b40c72493 + .quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c + .quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c + .quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a + .quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a + .quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817 + .quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817 + + .quad 0x0001020304050607,0x08090a0b0c0d0e0f + .quad 0x0001020304050607,0x08090a0b0c0d0e0f + .asciz "SHA512 block transform for x86_64, CRYPTOGAMS by " +___ +} + +###################################################################### +# SIMD code paths +# +if ($SZ==4 && $shaext) {{{ +###################################################################### +# Intel SHA Extensions implementation of SHA256 update function. +# +my ($ctx,$inp,$num,$Tbl)=("%rdi","%rsi","%rdx","%rcx"); + +my ($Wi,$ABEF,$CDGH,$TMP,$BSWAP,$ABEF_SAVE,$CDGH_SAVE)=map("%xmm$_",(0..2,7..10)); +my @MSG=map("%xmm$_",(3..6)); + +$code.=<<___; +.type sha256_block_data_order_shaext,\@function,3 +.align 64 +sha256_block_data_order_shaext: +_shaext_shortcut: +___ +$code.=<<___ if ($win64); + lea `-8-5*16`(%rsp),%rsp + movaps %xmm6,-8-5*16(%rax) + movaps %xmm7,-8-4*16(%rax) + movaps %xmm8,-8-3*16(%rax) + movaps %xmm9,-8-2*16(%rax) + movaps %xmm10,-8-1*16(%rax) +.Lprologue_shaext: +___ +$code.=<<___; + lea K256+0x80(%rip),$Tbl + movdqu ($ctx),$ABEF # DCBA + movdqu 16($ctx),$CDGH # HGFE + movdqa 0x200-0x80($Tbl),$TMP # byte swap mask + + pshufd \$0x1b,$ABEF,$Wi # ABCD + pshufd \$0xb1,$ABEF,$ABEF # CDAB + pshufd \$0x1b,$CDGH,$CDGH # EFGH + movdqa $TMP,$BSWAP # offload + palignr \$8,$CDGH,$ABEF # ABEF + punpcklqdq $Wi,$CDGH # CDGH + jmp .Loop_shaext + +.align 16 +.Loop_shaext: + movdqu ($inp),@MSG[0] + movdqu 0x10($inp),@MSG[1] + movdqu 0x20($inp),@MSG[2] + pshufb $TMP,@MSG[0] + movdqu 0x30($inp),@MSG[3] + + movdqa 0*32-0x80($Tbl),$Wi + paddd @MSG[0],$Wi + pshufb $TMP,@MSG[1] + movdqa $CDGH,$CDGH_SAVE # offload + sha256rnds2 $ABEF,$CDGH # 0-3 + pshufd \$0x0e,$Wi,$Wi + nop + movdqa $ABEF,$ABEF_SAVE # offload + sha256rnds2 $CDGH,$ABEF + + movdqa 1*32-0x80($Tbl),$Wi + paddd @MSG[1],$Wi + pshufb $TMP,@MSG[2] + sha256rnds2 $ABEF,$CDGH # 4-7 + pshufd \$0x0e,$Wi,$Wi + lea 0x40($inp),$inp + sha256msg1 @MSG[1],@MSG[0] + sha256rnds2 $CDGH,$ABEF + + movdqa 2*32-0x80($Tbl),$Wi + paddd @MSG[2],$Wi + pshufb $TMP,@MSG[3] + sha256rnds2 $ABEF,$CDGH # 8-11 + pshufd \$0x0e,$Wi,$Wi + movdqa @MSG[3],$TMP + palignr \$4,@MSG[2],$TMP + nop + paddd $TMP,@MSG[0] + sha256msg1 @MSG[2],@MSG[1] + sha256rnds2 $CDGH,$ABEF + + movdqa 3*32-0x80($Tbl),$Wi + paddd @MSG[3],$Wi + sha256msg2 @MSG[3],@MSG[0] + sha256rnds2 $ABEF,$CDGH # 12-15 + pshufd \$0x0e,$Wi,$Wi + movdqa @MSG[0],$TMP + palignr \$4,@MSG[3],$TMP + nop + paddd $TMP,@MSG[1] + sha256msg1 @MSG[3],@MSG[2] + sha256rnds2 $CDGH,$ABEF +___ +for($i=4;$i<16-3;$i++) { +$code.=<<___; + movdqa $i*32-0x80($Tbl),$Wi + paddd @MSG[0],$Wi + sha256msg2 @MSG[0],@MSG[1] + sha256rnds2 $ABEF,$CDGH # 16-19... + pshufd \$0x0e,$Wi,$Wi + movdqa @MSG[1],$TMP + palignr \$4,@MSG[0],$TMP + nop + paddd $TMP,@MSG[2] + sha256msg1 @MSG[0],@MSG[3] + sha256rnds2 $CDGH,$ABEF +___ + push(@MSG,shift(@MSG)); +} +$code.=<<___; + movdqa 13*32-0x80($Tbl),$Wi + paddd @MSG[0],$Wi + sha256msg2 @MSG[0],@MSG[1] + sha256rnds2 $ABEF,$CDGH # 52-55 + pshufd \$0x0e,$Wi,$Wi + movdqa @MSG[1],$TMP + palignr \$4,@MSG[0],$TMP + sha256rnds2 $CDGH,$ABEF + paddd $TMP,@MSG[2] + + movdqa 14*32-0x80($Tbl),$Wi + paddd @MSG[1],$Wi + sha256rnds2 $ABEF,$CDGH # 56-59 + pshufd \$0x0e,$Wi,$Wi + sha256msg2 @MSG[1],@MSG[2] + movdqa $BSWAP,$TMP + sha256rnds2 $CDGH,$ABEF + + movdqa 15*32-0x80($Tbl),$Wi + paddd @MSG[2],$Wi + nop + sha256rnds2 $ABEF,$CDGH # 60-63 + pshufd \$0x0e,$Wi,$Wi + dec $num + nop + sha256rnds2 $CDGH,$ABEF + + paddd $CDGH_SAVE,$CDGH + paddd $ABEF_SAVE,$ABEF + jnz .Loop_shaext + + pshufd \$0xb1,$CDGH,$CDGH # DCHG + pshufd \$0x1b,$ABEF,$TMP # FEBA + pshufd \$0xb1,$ABEF,$ABEF # BAFE + punpckhqdq $CDGH,$ABEF # DCBA + palignr \$8,$TMP,$CDGH # HGFE + + movdqu $ABEF,($ctx) + movdqu $CDGH,16($ctx) +___ +$code.=<<___ if ($win64); + movaps -8-5*16(%rax),%xmm6 + movaps -8-4*16(%rax),%xmm7 + movaps -8-3*16(%rax),%xmm8 + movaps -8-2*16(%rax),%xmm9 + movaps -8-1*16(%rax),%xmm10 + mov %rax,%rsp +.Lepilogue_shaext: +___ +$code.=<<___; + ret +.size sha256_block_data_order_shaext,.-sha256_block_data_order_shaext +___ +}}} +{{{ + +my $a4=$T1; +my ($a,$b,$c,$d,$e,$f,$g,$h); + +sub AUTOLOAD() # thunk [simplified] 32-bit style perlasm +{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; + my $arg = pop; + $arg = "\$$arg" if ($arg*1 eq $arg); + $code .= "\t$opcode\t".join(',',$arg,reverse @_)."\n"; +} + +sub body_00_15 () { + ( + '($a,$b,$c,$d,$e,$f,$g,$h)=@ROT;'. + + '&ror ($a0,$Sigma1[2]-$Sigma1[1])', + '&mov ($a,$a1)', + '&mov ($a4,$f)', + + '&ror ($a1,$Sigma0[2]-$Sigma0[1])', + '&xor ($a0,$e)', + '&xor ($a4,$g)', # f^g + + '&ror ($a0,$Sigma1[1]-$Sigma1[0])', + '&xor ($a1,$a)', + '&and ($a4,$e)', # (f^g)&e + + '&xor ($a0,$e)', + '&add ($h,$SZ*($i&15)."(%rsp)")', # h+=X[i]+K[i] + '&mov ($a2,$a)', + + '&xor ($a4,$g)', # Ch(e,f,g)=((f^g)&e)^g + '&ror ($a1,$Sigma0[1]-$Sigma0[0])', + '&xor ($a2,$b)', # a^b, b^c in next round + + '&add ($h,$a4)', # h+=Ch(e,f,g) + '&ror ($a0,$Sigma1[0])', # Sigma1(e) + '&and ($a3,$a2)', # (b^c)&(a^b) + + '&xor ($a1,$a)', + '&add ($h,$a0)', # h+=Sigma1(e) + '&xor ($a3,$b)', # Maj(a,b,c)=Ch(a^b,c,b) + + '&ror ($a1,$Sigma0[0])', # Sigma0(a) + '&add ($d,$h)', # d+=h + '&add ($h,$a3)', # h+=Maj(a,b,c) + + '&mov ($a0,$d)', + '&add ($a1,$h);'. # h+=Sigma0(a) + '($a2,$a3) = ($a3,$a2); unshift(@ROT,pop(@ROT)); $i++;' + ); +} + +###################################################################### +# SSSE3 code path +# +if ($SZ==4) { # SHA256 only +my @X = map("%xmm$_",(0..3)); +my ($t0,$t1,$t2,$t3, $t4,$t5) = map("%xmm$_",(4..9)); + +$code.=<<___; +.type ${func}_ssse3,\@function,3 +.align 64 +${func}_ssse3: +.cfi_startproc +.Lssse3_shortcut: + mov %rsp,%rax # copy %rsp +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + shl \$4,%rdx # num*16 + sub \$`$framesz+$win64*16*4`,%rsp + lea ($inp,%rdx,$SZ),%rdx # inp+num*16*$SZ + and \$-64,%rsp # align stack frame + mov $ctx,$_ctx # save ctx, 1st arg + mov $inp,$_inp # save inp, 2nd arh + mov %rdx,$_end # save end pointer, "3rd" arg + mov %rax,$_rsp # save copy of %rsp +.cfi_cfa_expression $_rsp,deref,+8 +___ +$code.=<<___ if ($win64); + movaps %xmm6,16*$SZ+32(%rsp) + movaps %xmm7,16*$SZ+48(%rsp) + movaps %xmm8,16*$SZ+64(%rsp) + movaps %xmm9,16*$SZ+80(%rsp) +___ +$code.=<<___; +.Lprologue_ssse3: + + mov $SZ*0($ctx),$A + mov $SZ*1($ctx),$B + mov $SZ*2($ctx),$C + mov $SZ*3($ctx),$D + mov $SZ*4($ctx),$E + mov $SZ*5($ctx),$F + mov $SZ*6($ctx),$G + mov $SZ*7($ctx),$H +___ + +$code.=<<___; + #movdqa $TABLE+`$SZ*2*$rounds`+32(%rip),$t4 + #movdqa $TABLE+`$SZ*2*$rounds`+64(%rip),$t5 + jmp .Lloop_ssse3 +.align 16 +.Lloop_ssse3: + movdqa $TABLE+`$SZ*2*$rounds`(%rip),$t3 + movdqu 0x00($inp),@X[0] + movdqu 0x10($inp),@X[1] + movdqu 0x20($inp),@X[2] + pshufb $t3,@X[0] + movdqu 0x30($inp),@X[3] + lea $TABLE(%rip),$Tbl + pshufb $t3,@X[1] + movdqa 0x00($Tbl),$t0 + movdqa 0x20($Tbl),$t1 + pshufb $t3,@X[2] + paddd @X[0],$t0 + movdqa 0x40($Tbl),$t2 + pshufb $t3,@X[3] + movdqa 0x60($Tbl),$t3 + paddd @X[1],$t1 + paddd @X[2],$t2 + paddd @X[3],$t3 + movdqa $t0,0x00(%rsp) + mov $A,$a1 + movdqa $t1,0x10(%rsp) + mov $B,$a3 + movdqa $t2,0x20(%rsp) + xor $C,$a3 # magic + movdqa $t3,0x30(%rsp) + mov $E,$a0 + jmp .Lssse3_00_47 + +.align 16 +.Lssse3_00_47: + sub \$`-16*2*$SZ`,$Tbl # size optimization +___ +sub Xupdate_256_SSSE3 () { + ( + '&movdqa ($t0,@X[1]);', + '&movdqa ($t3,@X[3])', + '&palignr ($t0,@X[0],$SZ)', # X[1..4] + '&palignr ($t3,@X[2],$SZ);', # X[9..12] + '&movdqa ($t1,$t0)', + '&movdqa ($t2,$t0);', + '&psrld ($t0,$sigma0[2])', + '&paddd (@X[0],$t3);', # X[0..3] += X[9..12] + '&psrld ($t2,$sigma0[0])', + '&pshufd ($t3,@X[3],0b11111010)',# X[14..15] + '&pslld ($t1,8*$SZ-$sigma0[1]);'. + '&pxor ($t0,$t2)', + '&psrld ($t2,$sigma0[1]-$sigma0[0]);'. + '&pxor ($t0,$t1)', + '&pslld ($t1,$sigma0[1]-$sigma0[0]);'. + '&pxor ($t0,$t2);', + '&movdqa ($t2,$t3)', + '&pxor ($t0,$t1);', # sigma0(X[1..4]) + '&psrld ($t3,$sigma1[2])', + '&paddd (@X[0],$t0);', # X[0..3] += sigma0(X[1..4]) + '&psrlq ($t2,$sigma1[0])', + '&pxor ($t3,$t2);', + '&psrlq ($t2,$sigma1[1]-$sigma1[0])', + '&pxor ($t3,$t2)', + '&pshufb ($t3,$t4)', # sigma1(X[14..15]) + '&paddd (@X[0],$t3)', # X[0..1] += sigma1(X[14..15]) + '&pshufd ($t3,@X[0],0b01010000)',# X[16..17] + '&movdqa ($t2,$t3);', + '&psrld ($t3,$sigma1[2])', + '&psrlq ($t2,$sigma1[0])', + '&pxor ($t3,$t2);', + '&psrlq ($t2,$sigma1[1]-$sigma1[0])', + '&pxor ($t3,$t2);', + '&movdqa ($t2,16*2*$j."($Tbl)")', + '&pshufb ($t3,$t5)', + '&paddd (@X[0],$t3)' # X[2..3] += sigma1(X[16..17]) + ); +} + +sub SSSE3_256_00_47 () { +my $j = shift; +my $body = shift; +my @X = @_; +my @insns = (&$body,&$body,&$body,&$body); # 104 instructions + + if (0) { + foreach (Xupdate_256_SSSE3()) { # 36 instructions + eval; + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + } + } else { # squeeze extra 4% on Westmere and 19% on Atom + eval(shift(@insns)); #@ + &movdqa ($t0,@X[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &movdqa ($t3,@X[3]); + eval(shift(@insns)); #@ + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); #@ + eval(shift(@insns)); + &palignr ($t0,@X[0],$SZ); # X[1..4] + eval(shift(@insns)); + eval(shift(@insns)); + &palignr ($t3,@X[2],$SZ); # X[9..12] + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); #@ + &movdqa ($t1,$t0); + eval(shift(@insns)); + eval(shift(@insns)); + &movdqa ($t2,$t0); + eval(shift(@insns)); #@ + eval(shift(@insns)); + &psrld ($t0,$sigma0[2]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &paddd (@X[0],$t3); # X[0..3] += X[9..12] + eval(shift(@insns)); #@ + eval(shift(@insns)); + &psrld ($t2,$sigma0[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &pshufd ($t3,@X[3],0b11111010); # X[4..15] + eval(shift(@insns)); + eval(shift(@insns)); #@ + &pslld ($t1,8*$SZ-$sigma0[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &pxor ($t0,$t2); + eval(shift(@insns)); #@ + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); #@ + &psrld ($t2,$sigma0[1]-$sigma0[0]); + eval(shift(@insns)); + &pxor ($t0,$t1); + eval(shift(@insns)); + eval(shift(@insns)); + &pslld ($t1,$sigma0[1]-$sigma0[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &pxor ($t0,$t2); + eval(shift(@insns)); + eval(shift(@insns)); #@ + &movdqa ($t2,$t3); + eval(shift(@insns)); + eval(shift(@insns)); + &pxor ($t0,$t1); # sigma0(X[1..4]) + eval(shift(@insns)); #@ + eval(shift(@insns)); + eval(shift(@insns)); + &psrld ($t3,$sigma1[2]); + eval(shift(@insns)); + eval(shift(@insns)); + &paddd (@X[0],$t0); # X[0..3] += sigma0(X[1..4]) + eval(shift(@insns)); #@ + eval(shift(@insns)); + &psrlq ($t2,$sigma1[0]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &pxor ($t3,$t2); + eval(shift(@insns)); #@ + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); #@ + &psrlq ($t2,$sigma1[1]-$sigma1[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &pxor ($t3,$t2); + eval(shift(@insns)); #@ + eval(shift(@insns)); + eval(shift(@insns)); + #&pshufb ($t3,$t4); # sigma1(X[14..15]) + &pshufd ($t3,$t3,0b10000000); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &psrldq ($t3,8); + eval(shift(@insns)); + eval(shift(@insns)); #@ + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); #@ + &paddd (@X[0],$t3); # X[0..1] += sigma1(X[14..15]) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &pshufd ($t3,@X[0],0b01010000); # X[16..17] + eval(shift(@insns)); + eval(shift(@insns)); #@ + eval(shift(@insns)); + &movdqa ($t2,$t3); + eval(shift(@insns)); + eval(shift(@insns)); + &psrld ($t3,$sigma1[2]); + eval(shift(@insns)); + eval(shift(@insns)); #@ + &psrlq ($t2,$sigma1[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &pxor ($t3,$t2); + eval(shift(@insns)); #@ + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); #@ + eval(shift(@insns)); + &psrlq ($t2,$sigma1[1]-$sigma1[0]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &pxor ($t3,$t2); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); #@ + #&pshufb ($t3,$t5); + &pshufd ($t3,$t3,0b00001000); + eval(shift(@insns)); + eval(shift(@insns)); + &movdqa ($t2,16*2*$j."($Tbl)"); + eval(shift(@insns)); #@ + eval(shift(@insns)); + &pslldq ($t3,8); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &paddd (@X[0],$t3); # X[2..3] += sigma1(X[16..17]) + eval(shift(@insns)); #@ + eval(shift(@insns)); + eval(shift(@insns)); + } + &paddd ($t2,@X[0]); + foreach (@insns) { eval; } # remaining instructions + &movdqa (16*$j."(%rsp)",$t2); +} + + for ($i=0,$j=0; $j<4; $j++) { + &SSSE3_256_00_47($j,\&body_00_15,@X); + push(@X,shift(@X)); # rotate(@X) + } + &cmpb ($SZ-1+16*2*$SZ."($Tbl)",0); + &jne (".Lssse3_00_47"); + + for ($i=0; $i<16; ) { + foreach(body_00_15()) { eval; } + } +$code.=<<___; + mov $_ctx,$ctx + mov $a1,$A + + add $SZ*0($ctx),$A + lea 16*$SZ($inp),$inp + add $SZ*1($ctx),$B + add $SZ*2($ctx),$C + add $SZ*3($ctx),$D + add $SZ*4($ctx),$E + add $SZ*5($ctx),$F + add $SZ*6($ctx),$G + add $SZ*7($ctx),$H + + cmp $_end,$inp + + mov $A,$SZ*0($ctx) + mov $B,$SZ*1($ctx) + mov $C,$SZ*2($ctx) + mov $D,$SZ*3($ctx) + mov $E,$SZ*4($ctx) + mov $F,$SZ*5($ctx) + mov $G,$SZ*6($ctx) + mov $H,$SZ*7($ctx) + jb .Lloop_ssse3 + + mov $_rsp,%rsi +.cfi_def_cfa %rsi,8 +___ +$code.=<<___ if ($win64); + movaps 16*$SZ+32(%rsp),%xmm6 + movaps 16*$SZ+48(%rsp),%xmm7 + movaps 16*$SZ+64(%rsp),%xmm8 + movaps 16*$SZ+80(%rsp),%xmm9 +___ +$code.=<<___; + mov -48(%rsi),%r15 +.cfi_restore %r15 + mov -40(%rsi),%r14 +.cfi_restore %r14 + mov -32(%rsi),%r13 +.cfi_restore %r13 + mov -24(%rsi),%r12 +.cfi_restore %r12 + mov -16(%rsi),%rbp +.cfi_restore %rbp + mov -8(%rsi),%rbx +.cfi_restore %rbx + lea (%rsi),%rsp +.cfi_def_cfa_register %rsp +.Lepilogue_ssse3: + ret +.cfi_endproc +.size ${func}_ssse3,.-${func}_ssse3 +___ +} + +if ($avx) {{ +###################################################################### +# XOP code path +# +if ($SZ==8) { # SHA512 only +$code.=<<___; +.type ${func}_xop,\@function,3 +.align 64 +${func}_xop: +.cfi_startproc +.Lxop_shortcut: + mov %rsp,%rax # copy %rsp +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + shl \$4,%rdx # num*16 + sub \$`$framesz+$win64*16*($SZ==4?4:6)`,%rsp + lea ($inp,%rdx,$SZ),%rdx # inp+num*16*$SZ + and \$-64,%rsp # align stack frame + mov $ctx,$_ctx # save ctx, 1st arg + mov $inp,$_inp # save inp, 2nd arh + mov %rdx,$_end # save end pointer, "3rd" arg + mov %rax,$_rsp # save copy of %rsp +.cfi_cfa_expression $_rsp,deref,+8 +___ +$code.=<<___ if ($win64); + movaps %xmm6,16*$SZ+32(%rsp) + movaps %xmm7,16*$SZ+48(%rsp) + movaps %xmm8,16*$SZ+64(%rsp) + movaps %xmm9,16*$SZ+80(%rsp) +___ +$code.=<<___ if ($win64 && $SZ>4); + movaps %xmm10,16*$SZ+96(%rsp) + movaps %xmm11,16*$SZ+112(%rsp) +___ +$code.=<<___; +.Lprologue_xop: + + vzeroupper + mov $SZ*0($ctx),$A + mov $SZ*1($ctx),$B + mov $SZ*2($ctx),$C + mov $SZ*3($ctx),$D + mov $SZ*4($ctx),$E + mov $SZ*5($ctx),$F + mov $SZ*6($ctx),$G + mov $SZ*7($ctx),$H + jmp .Lloop_xop +___ + if ($SZ==4) { # SHA256 + my @X = map("%xmm$_",(0..3)); + my ($t0,$t1,$t2,$t3) = map("%xmm$_",(4..7)); + +$code.=<<___; +.align 16 +.Lloop_xop: + vmovdqa $TABLE+`$SZ*2*$rounds`(%rip),$t3 + vmovdqu 0x00($inp),@X[0] + vmovdqu 0x10($inp),@X[1] + vmovdqu 0x20($inp),@X[2] + vmovdqu 0x30($inp),@X[3] + vpshufb $t3,@X[0],@X[0] + lea $TABLE(%rip),$Tbl + vpshufb $t3,@X[1],@X[1] + vpshufb $t3,@X[2],@X[2] + vpaddd 0x00($Tbl),@X[0],$t0 + vpshufb $t3,@X[3],@X[3] + vpaddd 0x20($Tbl),@X[1],$t1 + vpaddd 0x40($Tbl),@X[2],$t2 + vpaddd 0x60($Tbl),@X[3],$t3 + vmovdqa $t0,0x00(%rsp) + mov $A,$a1 + vmovdqa $t1,0x10(%rsp) + mov $B,$a3 + vmovdqa $t2,0x20(%rsp) + xor $C,$a3 # magic + vmovdqa $t3,0x30(%rsp) + mov $E,$a0 + jmp .Lxop_00_47 + +.align 16 +.Lxop_00_47: + sub \$`-16*2*$SZ`,$Tbl # size optimization +___ +sub XOP_256_00_47 () { +my $j = shift; +my $body = shift; +my @X = @_; +my @insns = (&$body,&$body,&$body,&$body); # 104 instructions + + &vpalignr ($t0,@X[1],@X[0],$SZ); # X[1..4] + eval(shift(@insns)); + eval(shift(@insns)); + &vpalignr ($t3,@X[3],@X[2],$SZ); # X[9..12] + eval(shift(@insns)); + eval(shift(@insns)); + &vprotd ($t1,$t0,8*$SZ-$sigma0[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpsrld ($t0,$t0,$sigma0[2]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpaddd (@X[0],@X[0],$t3); # X[0..3] += X[9..12] + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vprotd ($t2,$t1,$sigma0[1]-$sigma0[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor ($t0,$t0,$t1); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vprotd ($t3,@X[3],8*$SZ-$sigma1[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor ($t0,$t0,$t2); # sigma0(X[1..4]) + eval(shift(@insns)); + eval(shift(@insns)); + &vpsrld ($t2,@X[3],$sigma1[2]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpaddd (@X[0],@X[0],$t0); # X[0..3] += sigma0(X[1..4]) + eval(shift(@insns)); + eval(shift(@insns)); + &vprotd ($t1,$t3,$sigma1[1]-$sigma1[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor ($t3,$t3,$t2); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor ($t3,$t3,$t1); # sigma1(X[14..15]) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vpsrldq ($t3,$t3,8); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vpaddd (@X[0],@X[0],$t3); # X[0..1] += sigma1(X[14..15]) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vprotd ($t3,@X[0],8*$SZ-$sigma1[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpsrld ($t2,@X[0],$sigma1[2]); + eval(shift(@insns)); + eval(shift(@insns)); + &vprotd ($t1,$t3,$sigma1[1]-$sigma1[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor ($t3,$t3,$t2); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor ($t3,$t3,$t1); # sigma1(X[16..17]) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vpslldq ($t3,$t3,8); # 22 instructions + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vpaddd (@X[0],@X[0],$t3); # X[2..3] += sigma1(X[16..17]) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vpaddd ($t2,@X[0],16*2*$j."($Tbl)"); + foreach (@insns) { eval; } # remaining instructions + &vmovdqa (16*$j."(%rsp)",$t2); +} + + for ($i=0,$j=0; $j<4; $j++) { + &XOP_256_00_47($j,\&body_00_15,@X); + push(@X,shift(@X)); # rotate(@X) + } + &cmpb ($SZ-1+16*2*$SZ."($Tbl)",0); + &jne (".Lxop_00_47"); + + for ($i=0; $i<16; ) { + foreach(body_00_15()) { eval; } + } + + } else { # SHA512 + my @X = map("%xmm$_",(0..7)); + my ($t0,$t1,$t2,$t3) = map("%xmm$_",(8..11)); + +$code.=<<___; +.align 16 +.Lloop_xop: + vmovdqa $TABLE+`$SZ*2*$rounds`(%rip),$t3 + vmovdqu 0x00($inp),@X[0] + lea $TABLE+0x80(%rip),$Tbl # size optimization + vmovdqu 0x10($inp),@X[1] + vmovdqu 0x20($inp),@X[2] + vpshufb $t3,@X[0],@X[0] + vmovdqu 0x30($inp),@X[3] + vpshufb $t3,@X[1],@X[1] + vmovdqu 0x40($inp),@X[4] + vpshufb $t3,@X[2],@X[2] + vmovdqu 0x50($inp),@X[5] + vpshufb $t3,@X[3],@X[3] + vmovdqu 0x60($inp),@X[6] + vpshufb $t3,@X[4],@X[4] + vmovdqu 0x70($inp),@X[7] + vpshufb $t3,@X[5],@X[5] + vpaddq -0x80($Tbl),@X[0],$t0 + vpshufb $t3,@X[6],@X[6] + vpaddq -0x60($Tbl),@X[1],$t1 + vpshufb $t3,@X[7],@X[7] + vpaddq -0x40($Tbl),@X[2],$t2 + vpaddq -0x20($Tbl),@X[3],$t3 + vmovdqa $t0,0x00(%rsp) + vpaddq 0x00($Tbl),@X[4],$t0 + vmovdqa $t1,0x10(%rsp) + vpaddq 0x20($Tbl),@X[5],$t1 + vmovdqa $t2,0x20(%rsp) + vpaddq 0x40($Tbl),@X[6],$t2 + vmovdqa $t3,0x30(%rsp) + vpaddq 0x60($Tbl),@X[7],$t3 + vmovdqa $t0,0x40(%rsp) + mov $A,$a1 + vmovdqa $t1,0x50(%rsp) + mov $B,$a3 + vmovdqa $t2,0x60(%rsp) + xor $C,$a3 # magic + vmovdqa $t3,0x70(%rsp) + mov $E,$a0 + jmp .Lxop_00_47 + +.align 16 +.Lxop_00_47: + add \$`16*2*$SZ`,$Tbl +___ +sub XOP_512_00_47 () { +my $j = shift; +my $body = shift; +my @X = @_; +my @insns = (&$body,&$body); # 52 instructions + + &vpalignr ($t0,@X[1],@X[0],$SZ); # X[1..2] + eval(shift(@insns)); + eval(shift(@insns)); + &vpalignr ($t3,@X[5],@X[4],$SZ); # X[9..10] + eval(shift(@insns)); + eval(shift(@insns)); + &vprotq ($t1,$t0,8*$SZ-$sigma0[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpsrlq ($t0,$t0,$sigma0[2]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpaddq (@X[0],@X[0],$t3); # X[0..1] += X[9..10] + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vprotq ($t2,$t1,$sigma0[1]-$sigma0[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor ($t0,$t0,$t1); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vprotq ($t3,@X[7],8*$SZ-$sigma1[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor ($t0,$t0,$t2); # sigma0(X[1..2]) + eval(shift(@insns)); + eval(shift(@insns)); + &vpsrlq ($t2,@X[7],$sigma1[2]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpaddq (@X[0],@X[0],$t0); # X[0..1] += sigma0(X[1..2]) + eval(shift(@insns)); + eval(shift(@insns)); + &vprotq ($t1,$t3,$sigma1[1]-$sigma1[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor ($t3,$t3,$t2); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vpxor ($t3,$t3,$t1); # sigma1(X[14..15]) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vpaddq (@X[0],@X[0],$t3); # X[0..1] += sigma1(X[14..15]) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &vpaddq ($t2,@X[0],16*2*$j-0x80."($Tbl)"); + foreach (@insns) { eval; } # remaining instructions + &vmovdqa (16*$j."(%rsp)",$t2); +} + + for ($i=0,$j=0; $j<8; $j++) { + &XOP_512_00_47($j,\&body_00_15,@X); + push(@X,shift(@X)); # rotate(@X) + } + &cmpb ($SZ-1+16*2*$SZ-0x80."($Tbl)",0); + &jne (".Lxop_00_47"); + + for ($i=0; $i<16; ) { + foreach(body_00_15()) { eval; } + } +} +$code.=<<___; + mov $_ctx,$ctx + mov $a1,$A + + add $SZ*0($ctx),$A + lea 16*$SZ($inp),$inp + add $SZ*1($ctx),$B + add $SZ*2($ctx),$C + add $SZ*3($ctx),$D + add $SZ*4($ctx),$E + add $SZ*5($ctx),$F + add $SZ*6($ctx),$G + add $SZ*7($ctx),$H + + cmp $_end,$inp + + mov $A,$SZ*0($ctx) + mov $B,$SZ*1($ctx) + mov $C,$SZ*2($ctx) + mov $D,$SZ*3($ctx) + mov $E,$SZ*4($ctx) + mov $F,$SZ*5($ctx) + mov $G,$SZ*6($ctx) + mov $H,$SZ*7($ctx) + jb .Lloop_xop + + mov $_rsp,%rsi +.cfi_def_cfa %rsi,8 + vzeroupper +___ +$code.=<<___ if ($win64); + movaps 16*$SZ+32(%rsp),%xmm6 + movaps 16*$SZ+48(%rsp),%xmm7 + movaps 16*$SZ+64(%rsp),%xmm8 + movaps 16*$SZ+80(%rsp),%xmm9 +___ +$code.=<<___ if ($win64 && $SZ>4); + movaps 16*$SZ+96(%rsp),%xmm10 + movaps 16*$SZ+112(%rsp),%xmm11 +___ +$code.=<<___; + mov -48(%rsi),%r15 +.cfi_restore %r15 + mov -40(%rsi),%r14 +.cfi_restore %r14 + mov -32(%rsi),%r13 +.cfi_restore %r13 + mov -24(%rsi),%r12 +.cfi_restore %r12 + mov -16(%rsi),%rbp +.cfi_restore %rbp + mov -8(%rsi),%rbx +.cfi_restore %rbx + lea (%rsi),%rsp +.cfi_def_cfa_register %rsp +.Lepilogue_xop: + ret +.cfi_endproc +.size ${func}_xop,.-${func}_xop +___ +} +###################################################################### +# AVX+shrd code path +# +local *ror = sub { &shrd(@_[0],@_) }; + +$code.=<<___; +.type ${func}_avx,\@function,3 +.align 64 +${func}_avx: +.cfi_startproc +.Lavx_shortcut: + mov %rsp,%rax # copy %rsp +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + shl \$4,%rdx # num*16 + sub \$`$framesz+$win64*16*($SZ==4?4:6)`,%rsp + lea ($inp,%rdx,$SZ),%rdx # inp+num*16*$SZ + and \$-64,%rsp # align stack frame + mov $ctx,$_ctx # save ctx, 1st arg + mov $inp,$_inp # save inp, 2nd arh + mov %rdx,$_end # save end pointer, "3rd" arg + mov %rax,$_rsp # save copy of %rsp +.cfi_cfa_expression $_rsp,deref,+8 +___ +$code.=<<___ if ($win64); + movaps %xmm6,16*$SZ+32(%rsp) + movaps %xmm7,16*$SZ+48(%rsp) + movaps %xmm8,16*$SZ+64(%rsp) + movaps %xmm9,16*$SZ+80(%rsp) +___ +$code.=<<___ if ($win64 && $SZ>4); + movaps %xmm10,16*$SZ+96(%rsp) + movaps %xmm11,16*$SZ+112(%rsp) +___ +$code.=<<___; +.Lprologue_avx: + + vzeroupper + mov $SZ*0($ctx),$A + mov $SZ*1($ctx),$B + mov $SZ*2($ctx),$C + mov $SZ*3($ctx),$D + mov $SZ*4($ctx),$E + mov $SZ*5($ctx),$F + mov $SZ*6($ctx),$G + mov $SZ*7($ctx),$H +___ + if ($SZ==4) { # SHA256 + my @X = map("%xmm$_",(0..3)); + my ($t0,$t1,$t2,$t3, $t4,$t5) = map("%xmm$_",(4..9)); + +$code.=<<___; + vmovdqa $TABLE+`$SZ*2*$rounds`+32(%rip),$t4 + vmovdqa $TABLE+`$SZ*2*$rounds`+64(%rip),$t5 + jmp .Lloop_avx +.align 16 +.Lloop_avx: + vmovdqa $TABLE+`$SZ*2*$rounds`(%rip),$t3 + vmovdqu 0x00($inp),@X[0] + vmovdqu 0x10($inp),@X[1] + vmovdqu 0x20($inp),@X[2] + vmovdqu 0x30($inp),@X[3] + vpshufb $t3,@X[0],@X[0] + lea $TABLE(%rip),$Tbl + vpshufb $t3,@X[1],@X[1] + vpshufb $t3,@X[2],@X[2] + vpaddd 0x00($Tbl),@X[0],$t0 + vpshufb $t3,@X[3],@X[3] + vpaddd 0x20($Tbl),@X[1],$t1 + vpaddd 0x40($Tbl),@X[2],$t2 + vpaddd 0x60($Tbl),@X[3],$t3 + vmovdqa $t0,0x00(%rsp) + mov $A,$a1 + vmovdqa $t1,0x10(%rsp) + mov $B,$a3 + vmovdqa $t2,0x20(%rsp) + xor $C,$a3 # magic + vmovdqa $t3,0x30(%rsp) + mov $E,$a0 + jmp .Lavx_00_47 + +.align 16 +.Lavx_00_47: + sub \$`-16*2*$SZ`,$Tbl # size optimization +___ +sub Xupdate_256_AVX () { + ( + '&vpalignr ($t0,@X[1],@X[0],$SZ)', # X[1..4] + '&vpalignr ($t3,@X[3],@X[2],$SZ)', # X[9..12] + '&vpsrld ($t2,$t0,$sigma0[0]);', + '&vpaddd (@X[0],@X[0],$t3)', # X[0..3] += X[9..12] + '&vpsrld ($t3,$t0,$sigma0[2])', + '&vpslld ($t1,$t0,8*$SZ-$sigma0[1]);', + '&vpxor ($t0,$t3,$t2)', + '&vpshufd ($t3,@X[3],0b11111010)',# X[14..15] + '&vpsrld ($t2,$t2,$sigma0[1]-$sigma0[0]);', + '&vpxor ($t0,$t0,$t1)', + '&vpslld ($t1,$t1,$sigma0[1]-$sigma0[0]);', + '&vpxor ($t0,$t0,$t2)', + '&vpsrld ($t2,$t3,$sigma1[2]);', + '&vpxor ($t0,$t0,$t1)', # sigma0(X[1..4]) + '&vpsrlq ($t3,$t3,$sigma1[0]);', + '&vpaddd (@X[0],@X[0],$t0)', # X[0..3] += sigma0(X[1..4]) + '&vpxor ($t2,$t2,$t3);', + '&vpsrlq ($t3,$t3,$sigma1[1]-$sigma1[0])', + '&vpxor ($t2,$t2,$t3)', + '&vpshufb ($t2,$t2,$t4)', # sigma1(X[14..15]) + '&vpaddd (@X[0],@X[0],$t2)', # X[0..1] += sigma1(X[14..15]) + '&vpshufd ($t3,@X[0],0b01010000)',# X[16..17] + '&vpsrld ($t2,$t3,$sigma1[2])', + '&vpsrlq ($t3,$t3,$sigma1[0])', + '&vpxor ($t2,$t2,$t3);', + '&vpsrlq ($t3,$t3,$sigma1[1]-$sigma1[0])', + '&vpxor ($t2,$t2,$t3)', + '&vpshufb ($t2,$t2,$t5)', + '&vpaddd (@X[0],@X[0],$t2)' # X[2..3] += sigma1(X[16..17]) + ); +} + +sub AVX_256_00_47 () { +my $j = shift; +my $body = shift; +my @X = @_; +my @insns = (&$body,&$body,&$body,&$body); # 104 instructions + + foreach (Xupdate_256_AVX()) { # 29 instructions + eval; + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + } + &vpaddd ($t2,@X[0],16*2*$j."($Tbl)"); + foreach (@insns) { eval; } # remaining instructions + &vmovdqa (16*$j."(%rsp)",$t2); +} + + for ($i=0,$j=0; $j<4; $j++) { + &AVX_256_00_47($j,\&body_00_15,@X); + push(@X,shift(@X)); # rotate(@X) + } + &cmpb ($SZ-1+16*2*$SZ."($Tbl)",0); + &jne (".Lavx_00_47"); + + for ($i=0; $i<16; ) { + foreach(body_00_15()) { eval; } + } + + } else { # SHA512 + my @X = map("%xmm$_",(0..7)); + my ($t0,$t1,$t2,$t3) = map("%xmm$_",(8..11)); + +$code.=<<___; + jmp .Lloop_avx +.align 16 +.Lloop_avx: + vmovdqa $TABLE+`$SZ*2*$rounds`(%rip),$t3 + vmovdqu 0x00($inp),@X[0] + lea $TABLE+0x80(%rip),$Tbl # size optimization + vmovdqu 0x10($inp),@X[1] + vmovdqu 0x20($inp),@X[2] + vpshufb $t3,@X[0],@X[0] + vmovdqu 0x30($inp),@X[3] + vpshufb $t3,@X[1],@X[1] + vmovdqu 0x40($inp),@X[4] + vpshufb $t3,@X[2],@X[2] + vmovdqu 0x50($inp),@X[5] + vpshufb $t3,@X[3],@X[3] + vmovdqu 0x60($inp),@X[6] + vpshufb $t3,@X[4],@X[4] + vmovdqu 0x70($inp),@X[7] + vpshufb $t3,@X[5],@X[5] + vpaddq -0x80($Tbl),@X[0],$t0 + vpshufb $t3,@X[6],@X[6] + vpaddq -0x60($Tbl),@X[1],$t1 + vpshufb $t3,@X[7],@X[7] + vpaddq -0x40($Tbl),@X[2],$t2 + vpaddq -0x20($Tbl),@X[3],$t3 + vmovdqa $t0,0x00(%rsp) + vpaddq 0x00($Tbl),@X[4],$t0 + vmovdqa $t1,0x10(%rsp) + vpaddq 0x20($Tbl),@X[5],$t1 + vmovdqa $t2,0x20(%rsp) + vpaddq 0x40($Tbl),@X[6],$t2 + vmovdqa $t3,0x30(%rsp) + vpaddq 0x60($Tbl),@X[7],$t3 + vmovdqa $t0,0x40(%rsp) + mov $A,$a1 + vmovdqa $t1,0x50(%rsp) + mov $B,$a3 + vmovdqa $t2,0x60(%rsp) + xor $C,$a3 # magic + vmovdqa $t3,0x70(%rsp) + mov $E,$a0 + jmp .Lavx_00_47 + +.align 16 +.Lavx_00_47: + add \$`16*2*$SZ`,$Tbl +___ +sub Xupdate_512_AVX () { + ( + '&vpalignr ($t0,@X[1],@X[0],$SZ)', # X[1..2] + '&vpalignr ($t3,@X[5],@X[4],$SZ)', # X[9..10] + '&vpsrlq ($t2,$t0,$sigma0[0])', + '&vpaddq (@X[0],@X[0],$t3);', # X[0..1] += X[9..10] + '&vpsrlq ($t3,$t0,$sigma0[2])', + '&vpsllq ($t1,$t0,8*$SZ-$sigma0[1]);', + '&vpxor ($t0,$t3,$t2)', + '&vpsrlq ($t2,$t2,$sigma0[1]-$sigma0[0]);', + '&vpxor ($t0,$t0,$t1)', + '&vpsllq ($t1,$t1,$sigma0[1]-$sigma0[0]);', + '&vpxor ($t0,$t0,$t2)', + '&vpsrlq ($t3,@X[7],$sigma1[2]);', + '&vpxor ($t0,$t0,$t1)', # sigma0(X[1..2]) + '&vpsllq ($t2,@X[7],8*$SZ-$sigma1[1]);', + '&vpaddq (@X[0],@X[0],$t0)', # X[0..1] += sigma0(X[1..2]) + '&vpsrlq ($t1,@X[7],$sigma1[0]);', + '&vpxor ($t3,$t3,$t2)', + '&vpsllq ($t2,$t2,$sigma1[1]-$sigma1[0]);', + '&vpxor ($t3,$t3,$t1)', + '&vpsrlq ($t1,$t1,$sigma1[1]-$sigma1[0]);', + '&vpxor ($t3,$t3,$t2)', + '&vpxor ($t3,$t3,$t1)', # sigma1(X[14..15]) + '&vpaddq (@X[0],@X[0],$t3)', # X[0..1] += sigma1(X[14..15]) + ); +} + +sub AVX_512_00_47 () { +my $j = shift; +my $body = shift; +my @X = @_; +my @insns = (&$body,&$body); # 52 instructions + + foreach (Xupdate_512_AVX()) { # 23 instructions + eval; + eval(shift(@insns)); + eval(shift(@insns)); + } + &vpaddq ($t2,@X[0],16*2*$j-0x80."($Tbl)"); + foreach (@insns) { eval; } # remaining instructions + &vmovdqa (16*$j."(%rsp)",$t2); +} + + for ($i=0,$j=0; $j<8; $j++) { + &AVX_512_00_47($j,\&body_00_15,@X); + push(@X,shift(@X)); # rotate(@X) + } + &cmpb ($SZ-1+16*2*$SZ-0x80."($Tbl)",0); + &jne (".Lavx_00_47"); + + for ($i=0; $i<16; ) { + foreach(body_00_15()) { eval; } + } +} +$code.=<<___; + mov $_ctx,$ctx + mov $a1,$A + + add $SZ*0($ctx),$A + lea 16*$SZ($inp),$inp + add $SZ*1($ctx),$B + add $SZ*2($ctx),$C + add $SZ*3($ctx),$D + add $SZ*4($ctx),$E + add $SZ*5($ctx),$F + add $SZ*6($ctx),$G + add $SZ*7($ctx),$H + + cmp $_end,$inp + + mov $A,$SZ*0($ctx) + mov $B,$SZ*1($ctx) + mov $C,$SZ*2($ctx) + mov $D,$SZ*3($ctx) + mov $E,$SZ*4($ctx) + mov $F,$SZ*5($ctx) + mov $G,$SZ*6($ctx) + mov $H,$SZ*7($ctx) + jb .Lloop_avx + + mov $_rsp,%rsi +.cfi_def_cfa %rsi,8 + vzeroupper +___ +$code.=<<___ if ($win64); + movaps 16*$SZ+32(%rsp),%xmm6 + movaps 16*$SZ+48(%rsp),%xmm7 + movaps 16*$SZ+64(%rsp),%xmm8 + movaps 16*$SZ+80(%rsp),%xmm9 +___ +$code.=<<___ if ($win64 && $SZ>4); + movaps 16*$SZ+96(%rsp),%xmm10 + movaps 16*$SZ+112(%rsp),%xmm11 +___ +$code.=<<___; + mov -48(%rsi),%r15 +.cfi_restore %r15 + mov -40(%rsi),%r14 +.cfi_restore %r14 + mov -32(%rsi),%r13 +.cfi_restore %r13 + mov -24(%rsi),%r12 +.cfi_restore %r12 + mov -16(%rsi),%rbp +.cfi_restore %rbp + mov -8(%rsi),%rbx +.cfi_restore %rbx + lea (%rsi),%rsp +.cfi_def_cfa_register %rsp +.Lepilogue_avx: + ret +.cfi_endproc +.size ${func}_avx,.-${func}_avx +___ + +if ($avx>1) {{ +###################################################################### +# AVX2+BMI code path +# +my $a5=$SZ==4?"%esi":"%rsi"; # zap $inp +my $PUSH8=8*2*$SZ; +use integer; + +sub bodyx_00_15 () { + # at start $a1 should be zero, $a3 - $b^$c and $a4 copy of $f + ( + '($a,$b,$c,$d,$e,$f,$g,$h)=@ROT;'. + + '&add ($h,(32*($i/(16/$SZ))+$SZ*($i%(16/$SZ)))%$PUSH8.$base)', # h+=X[i]+K[i] + '&and ($a4,$e)', # f&e + '&rorx ($a0,$e,$Sigma1[2])', + '&rorx ($a2,$e,$Sigma1[1])', + + '&lea ($a,"($a,$a1)")', # h+=Sigma0(a) from the past + '&lea ($h,"($h,$a4)")', + '&andn ($a4,$e,$g)', # ~e&g + '&xor ($a0,$a2)', + + '&rorx ($a1,$e,$Sigma1[0])', + '&lea ($h,"($h,$a4)")', # h+=Ch(e,f,g)=(e&f)+(~e&g) + '&xor ($a0,$a1)', # Sigma1(e) + '&mov ($a2,$a)', + + '&rorx ($a4,$a,$Sigma0[2])', + '&lea ($h,"($h,$a0)")', # h+=Sigma1(e) + '&xor ($a2,$b)', # a^b, b^c in next round + '&rorx ($a1,$a,$Sigma0[1])', + + '&rorx ($a0,$a,$Sigma0[0])', + '&lea ($d,"($d,$h)")', # d+=h + '&and ($a3,$a2)', # (b^c)&(a^b) + '&xor ($a1,$a4)', + + '&xor ($a3,$b)', # Maj(a,b,c)=Ch(a^b,c,b) + '&xor ($a1,$a0)', # Sigma0(a) + '&lea ($h,"($h,$a3)");'. # h+=Maj(a,b,c) + '&mov ($a4,$e)', # copy of f in future + + '($a2,$a3) = ($a3,$a2); unshift(@ROT,pop(@ROT)); $i++;' + ); + # and at the finish one has to $a+=$a1 +} + +$code.=<<___; +.type ${func}_avx2,\@function,3 +.align 64 +${func}_avx2: +.cfi_startproc +.Lavx2_shortcut: + mov %rsp,%rax # copy %rsp +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + sub \$`2*$SZ*$rounds+4*8+$win64*16*($SZ==4?4:6)`,%rsp + shl \$4,%rdx # num*16 + and \$-256*$SZ,%rsp # align stack frame + lea ($inp,%rdx,$SZ),%rdx # inp+num*16*$SZ + add \$`2*$SZ*($rounds-8)`,%rsp + mov $ctx,$_ctx # save ctx, 1st arg + mov $inp,$_inp # save inp, 2nd arh + mov %rdx,$_end # save end pointer, "3rd" arg + mov %rax,$_rsp # save copy of %rsp +.cfi_cfa_expression $_rsp,deref,+8 +___ +$code.=<<___ if ($win64); + movaps %xmm6,16*$SZ+32(%rsp) + movaps %xmm7,16*$SZ+48(%rsp) + movaps %xmm8,16*$SZ+64(%rsp) + movaps %xmm9,16*$SZ+80(%rsp) +___ +$code.=<<___ if ($win64 && $SZ>4); + movaps %xmm10,16*$SZ+96(%rsp) + movaps %xmm11,16*$SZ+112(%rsp) +___ +$code.=<<___; +.Lprologue_avx2: + + vzeroupper + sub \$-16*$SZ,$inp # inp++, size optimization + mov $SZ*0($ctx),$A + mov $inp,%r12 # borrow $T1 + mov $SZ*1($ctx),$B + cmp %rdx,$inp # $_end + mov $SZ*2($ctx),$C + cmove %rsp,%r12 # next block or random data + mov $SZ*3($ctx),$D + mov $SZ*4($ctx),$E + mov $SZ*5($ctx),$F + mov $SZ*6($ctx),$G + mov $SZ*7($ctx),$H +___ + if ($SZ==4) { # SHA256 + my @X = map("%ymm$_",(0..3)); + my ($t0,$t1,$t2,$t3, $t4,$t5) = map("%ymm$_",(4..9)); + +$code.=<<___; + vmovdqa $TABLE+`$SZ*2*$rounds`+32(%rip),$t4 + vmovdqa $TABLE+`$SZ*2*$rounds`+64(%rip),$t5 + jmp .Loop_avx2 +.align 16 +.Loop_avx2: + vmovdqa $TABLE+`$SZ*2*$rounds`(%rip),$t3 + vmovdqu -16*$SZ+0($inp),%xmm0 + vmovdqu -16*$SZ+16($inp),%xmm1 + vmovdqu -16*$SZ+32($inp),%xmm2 + vmovdqu -16*$SZ+48($inp),%xmm3 + #mov $inp,$_inp # offload $inp + vinserti128 \$1,(%r12),@X[0],@X[0] + vinserti128 \$1,16(%r12),@X[1],@X[1] + vpshufb $t3,@X[0],@X[0] + vinserti128 \$1,32(%r12),@X[2],@X[2] + vpshufb $t3,@X[1],@X[1] + vinserti128 \$1,48(%r12),@X[3],@X[3] + + lea $TABLE(%rip),$Tbl + vpshufb $t3,@X[2],@X[2] + vpaddd 0x00($Tbl),@X[0],$t0 + vpshufb $t3,@X[3],@X[3] + vpaddd 0x20($Tbl),@X[1],$t1 + vpaddd 0x40($Tbl),@X[2],$t2 + vpaddd 0x60($Tbl),@X[3],$t3 + vmovdqa $t0,0x00(%rsp) + xor $a1,$a1 + vmovdqa $t1,0x20(%rsp) + lea -$PUSH8(%rsp),%rsp + mov $B,$a3 + vmovdqa $t2,0x00(%rsp) + xor $C,$a3 # magic + vmovdqa $t3,0x20(%rsp) + mov $F,$a4 + sub \$-16*2*$SZ,$Tbl # size optimization + jmp .Lavx2_00_47 + +.align 16 +.Lavx2_00_47: +___ + +sub AVX2_256_00_47 () { +my $j = shift; +my $body = shift; +my @X = @_; +my @insns = (&$body,&$body,&$body,&$body); # 96 instructions +my $base = "+2*$PUSH8(%rsp)"; + + &lea ("%rsp","-$PUSH8(%rsp)") if (($j%2)==0); + foreach (Xupdate_256_AVX()) { # 29 instructions + eval; + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + } + &vpaddd ($t2,@X[0],16*2*$j."($Tbl)"); + foreach (@insns) { eval; } # remaining instructions + &vmovdqa ((32*$j)%$PUSH8."(%rsp)",$t2); +} + + for ($i=0,$j=0; $j<4; $j++) { + &AVX2_256_00_47($j,\&bodyx_00_15,@X); + push(@X,shift(@X)); # rotate(@X) + } + &lea ($Tbl,16*2*$SZ."($Tbl)"); + &cmpb (($SZ-1)."($Tbl)",0); + &jne (".Lavx2_00_47"); + + for ($i=0; $i<16; ) { + my $base=$i<8?"+$PUSH8(%rsp)":"(%rsp)"; + foreach(bodyx_00_15()) { eval; } + } + } else { # SHA512 + my @X = map("%ymm$_",(0..7)); + my ($t0,$t1,$t2,$t3) = map("%ymm$_",(8..11)); + +$code.=<<___; + jmp .Loop_avx2 +.align 16 +.Loop_avx2: + vmovdqu -16*$SZ($inp),%xmm0 + vmovdqu -16*$SZ+16($inp),%xmm1 + vmovdqu -16*$SZ+32($inp),%xmm2 + lea $TABLE+0x80(%rip),$Tbl # size optimization + vmovdqu -16*$SZ+48($inp),%xmm3 + vmovdqu -16*$SZ+64($inp),%xmm4 + vmovdqu -16*$SZ+80($inp),%xmm5 + vmovdqu -16*$SZ+96($inp),%xmm6 + vmovdqu -16*$SZ+112($inp),%xmm7 + #mov $inp,$_inp # offload $inp + vmovdqa `$SZ*2*$rounds-0x80`($Tbl),$t2 + vinserti128 \$1,(%r12),@X[0],@X[0] + vinserti128 \$1,16(%r12),@X[1],@X[1] + vpshufb $t2,@X[0],@X[0] + vinserti128 \$1,32(%r12),@X[2],@X[2] + vpshufb $t2,@X[1],@X[1] + vinserti128 \$1,48(%r12),@X[3],@X[3] + vpshufb $t2,@X[2],@X[2] + vinserti128 \$1,64(%r12),@X[4],@X[4] + vpshufb $t2,@X[3],@X[3] + vinserti128 \$1,80(%r12),@X[5],@X[5] + vpshufb $t2,@X[4],@X[4] + vinserti128 \$1,96(%r12),@X[6],@X[6] + vpshufb $t2,@X[5],@X[5] + vinserti128 \$1,112(%r12),@X[7],@X[7] + + vpaddq -0x80($Tbl),@X[0],$t0 + vpshufb $t2,@X[6],@X[6] + vpaddq -0x60($Tbl),@X[1],$t1 + vpshufb $t2,@X[7],@X[7] + vpaddq -0x40($Tbl),@X[2],$t2 + vpaddq -0x20($Tbl),@X[3],$t3 + vmovdqa $t0,0x00(%rsp) + vpaddq 0x00($Tbl),@X[4],$t0 + vmovdqa $t1,0x20(%rsp) + vpaddq 0x20($Tbl),@X[5],$t1 + vmovdqa $t2,0x40(%rsp) + vpaddq 0x40($Tbl),@X[6],$t2 + vmovdqa $t3,0x60(%rsp) + lea -$PUSH8(%rsp),%rsp + vpaddq 0x60($Tbl),@X[7],$t3 + vmovdqa $t0,0x00(%rsp) + xor $a1,$a1 + vmovdqa $t1,0x20(%rsp) + mov $B,$a3 + vmovdqa $t2,0x40(%rsp) + xor $C,$a3 # magic + vmovdqa $t3,0x60(%rsp) + mov $F,$a4 + add \$16*2*$SZ,$Tbl + jmp .Lavx2_00_47 + +.align 16 +.Lavx2_00_47: +___ + +sub AVX2_512_00_47 () { +my $j = shift; +my $body = shift; +my @X = @_; +my @insns = (&$body,&$body); # 48 instructions +my $base = "+2*$PUSH8(%rsp)"; + + &lea ("%rsp","-$PUSH8(%rsp)") if (($j%4)==0); + foreach (Xupdate_512_AVX()) { # 23 instructions + eval; + if ($_ !~ /\;$/) { + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + } + } + &vpaddq ($t2,@X[0],16*2*$j-0x80."($Tbl)"); + foreach (@insns) { eval; } # remaining instructions + &vmovdqa ((32*$j)%$PUSH8."(%rsp)",$t2); +} + + for ($i=0,$j=0; $j<8; $j++) { + &AVX2_512_00_47($j,\&bodyx_00_15,@X); + push(@X,shift(@X)); # rotate(@X) + } + &lea ($Tbl,16*2*$SZ."($Tbl)"); + &cmpb (($SZ-1-0x80)."($Tbl)",0); + &jne (".Lavx2_00_47"); + + for ($i=0; $i<16; ) { + my $base=$i<8?"+$PUSH8(%rsp)":"(%rsp)"; + foreach(bodyx_00_15()) { eval; } + } +} +$code.=<<___; + mov `2*$SZ*$rounds`(%rsp),$ctx # $_ctx + add $a1,$A + #mov `2*$SZ*$rounds+8`(%rsp),$inp # $_inp + lea `2*$SZ*($rounds-8)`(%rsp),$Tbl + + add $SZ*0($ctx),$A + add $SZ*1($ctx),$B + add $SZ*2($ctx),$C + add $SZ*3($ctx),$D + add $SZ*4($ctx),$E + add $SZ*5($ctx),$F + add $SZ*6($ctx),$G + add $SZ*7($ctx),$H + + mov $A,$SZ*0($ctx) + mov $B,$SZ*1($ctx) + mov $C,$SZ*2($ctx) + mov $D,$SZ*3($ctx) + mov $E,$SZ*4($ctx) + mov $F,$SZ*5($ctx) + mov $G,$SZ*6($ctx) + mov $H,$SZ*7($ctx) + + cmp `$PUSH8+2*8`($Tbl),$inp # $_end + je .Ldone_avx2 + + xor $a1,$a1 + mov $B,$a3 + xor $C,$a3 # magic + mov $F,$a4 + jmp .Lower_avx2 +.align 16 +.Lower_avx2: +___ + for ($i=0; $i<8; ) { + my $base="+16($Tbl)"; + foreach(bodyx_00_15()) { eval; } + } +$code.=<<___; + lea -$PUSH8($Tbl),$Tbl + cmp %rsp,$Tbl + jae .Lower_avx2 + + mov `2*$SZ*$rounds`(%rsp),$ctx # $_ctx + add $a1,$A + #mov `2*$SZ*$rounds+8`(%rsp),$inp # $_inp + lea `2*$SZ*($rounds-8)`(%rsp),%rsp + + add $SZ*0($ctx),$A + add $SZ*1($ctx),$B + add $SZ*2($ctx),$C + add $SZ*3($ctx),$D + add $SZ*4($ctx),$E + add $SZ*5($ctx),$F + lea `2*16*$SZ`($inp),$inp # inp+=2 + add $SZ*6($ctx),$G + mov $inp,%r12 + add $SZ*7($ctx),$H + cmp $_end,$inp + + mov $A,$SZ*0($ctx) + cmove %rsp,%r12 # next block or stale data + mov $B,$SZ*1($ctx) + mov $C,$SZ*2($ctx) + mov $D,$SZ*3($ctx) + mov $E,$SZ*4($ctx) + mov $F,$SZ*5($ctx) + mov $G,$SZ*6($ctx) + mov $H,$SZ*7($ctx) + + jbe .Loop_avx2 + lea (%rsp),$Tbl + +.Ldone_avx2: + lea ($Tbl),%rsp + mov $_rsp,%rsi +.cfi_def_cfa %rsi,8 + vzeroupper +___ +$code.=<<___ if ($win64); + movaps 16*$SZ+32(%rsp),%xmm6 + movaps 16*$SZ+48(%rsp),%xmm7 + movaps 16*$SZ+64(%rsp),%xmm8 + movaps 16*$SZ+80(%rsp),%xmm9 +___ +$code.=<<___ if ($win64 && $SZ>4); + movaps 16*$SZ+96(%rsp),%xmm10 + movaps 16*$SZ+112(%rsp),%xmm11 +___ +$code.=<<___; + mov -48(%rsi),%r15 +.cfi_restore %r15 + mov -40(%rsi),%r14 +.cfi_restore %r14 + mov -32(%rsi),%r13 +.cfi_restore %r13 + mov -24(%rsi),%r12 +.cfi_restore %r12 + mov -16(%rsi),%rbp +.cfi_restore %rbp + mov -8(%rsi),%rbx +.cfi_restore %rbx + lea (%rsi),%rsp +.cfi_def_cfa_register %rsp +.Lepilogue_avx2: + ret +.cfi_endproc +.size ${func}_avx2,.-${func}_avx2 +___ +}} +}}}}} + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type se_handler,\@abi-omnipotent +.align 16 +se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HanderlData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lin_prologue +___ +$code.=<<___ if ($avx>1); + lea .Lavx2_shortcut(%rip),%r10 + cmp %r10,%rbx # context->RipRbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + + lea .Lepilogue(%rip),%r10 + cmp %r10,%rbx + jb .Lin_prologue # non-AVX code + + lea 16*$SZ+4*8(%rsi),%rsi # Xmm6- save area + lea 512($context),%rdi # &context.Xmm6 + mov \$`$SZ==4?8:12`,%ecx + .long 0xa548f3fc # cld; rep movsq + +.Lin_prologue: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size se_handler,.-se_handler +___ + +$code.=<<___ if ($SZ==4 && $shaext); +.type shaext_handler,\@abi-omnipotent +.align 16 +shaext_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + lea .Lprologue_shaext(%rip),%r10 + cmp %r10,%rbx # context->Rip<.Lprologue + jb .Lin_prologue + + lea .Lepilogue_shaext(%rip),%r10 + cmp %r10,%rbx # context->Rip>=.Lepilogue + jae .Lin_prologue + + lea -8-5*16(%rax),%rsi + lea 512($context),%rdi # &context.Xmm6 + mov \$10,%ecx + .long 0xa548f3fc # cld; rep movsq + + jmp .Lin_prologue +.size shaext_handler,.-shaext_handler +___ + +$code.=<<___; +.section .pdata +.align 4 + .rva .LSEH_begin_$func + .rva .LSEH_end_$func + .rva .LSEH_info_$func +___ +$code.=<<___ if ($SZ==4 && $shaext); + .rva .LSEH_begin_${func}_shaext + .rva .LSEH_end_${func}_shaext + .rva .LSEH_info_${func}_shaext +___ +$code.=<<___ if ($SZ==4); + .rva .LSEH_begin_${func}_ssse3 + .rva .LSEH_end_${func}_ssse3 + .rva .LSEH_info_${func}_ssse3 +___ +$code.=<<___ if ($avx && $SZ==8); + .rva .LSEH_begin_${func}_xop + .rva .LSEH_end_${func}_xop + .rva .LSEH_info_${func}_xop +___ +$code.=<<___ if ($avx); + .rva .LSEH_begin_${func}_avx + .rva .LSEH_end_${func}_avx + .rva .LSEH_info_${func}_avx +___ +$code.=<<___ if ($avx>1); + .rva .LSEH_begin_${func}_avx2 + .rva .LSEH_end_${func}_avx2 + .rva .LSEH_info_${func}_avx2 +___ +$code.=<<___; +.section .xdata +.align 8 +.LSEH_info_$func: + .byte 9,0,0,0 + .rva se_handler + .rva .Lprologue,.Lepilogue # HandlerData[] +___ +$code.=<<___ if ($SZ==4 && $shaext); +.LSEH_info_${func}_shaext: + .byte 9,0,0,0 + .rva shaext_handler +___ +$code.=<<___ if ($SZ==4); +.LSEH_info_${func}_ssse3: + .byte 9,0,0,0 + .rva se_handler + .rva .Lprologue_ssse3,.Lepilogue_ssse3 # HandlerData[] +___ +$code.=<<___ if ($avx && $SZ==8); +.LSEH_info_${func}_xop: + .byte 9,0,0,0 + .rva se_handler + .rva .Lprologue_xop,.Lepilogue_xop # HandlerData[] +___ +$code.=<<___ if ($avx); +.LSEH_info_${func}_avx: + .byte 9,0,0,0 + .rva se_handler + .rva .Lprologue_avx,.Lepilogue_avx # HandlerData[] +___ +$code.=<<___ if ($avx>1); +.LSEH_info_${func}_avx2: + .byte 9,0,0,0 + .rva se_handler + .rva .Lprologue_avx2,.Lepilogue_avx2 # HandlerData[] +___ +} + +sub sha256op38 { + my $instr = shift; + my %opcodelet = ( + "sha256rnds2" => 0xcb, + "sha256msg1" => 0xcc, + "sha256msg2" => 0xcd ); + + if (defined($opcodelet{$instr}) && @_[0] =~ /%xmm([0-7]),\s*%xmm([0-7])/) { + my @opcode=(0x0f,0x38); + push @opcode,$opcodelet{$instr}; + push @opcode,0xc0|($1&7)|(($2&7)<<3); # ModR/M + return ".byte\t".join(',',@opcode); + } else { + return $instr."\t".@_[0]; + } +} + +foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/geo; + + s/\b(sha256[^\s]*)\s+(.*)/sha256op38($1,$2)/geo; + + print $_,"\n"; +} +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512p8-ppc.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512p8-ppc.pl new file mode 100755 index 000000000..0d4fdd292 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/asm/sha512p8-ppc.pl @@ -0,0 +1,420 @@ +#! /usr/bin/env perl +# Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# SHA256/512 for PowerISA v2.07. +# +# Accurate performance measurements are problematic, because it's +# always virtualized setup with possibly throttled processor. +# Relative comparison is therefore more informative. This module is +# ~60% faster than integer-only sha512-ppc.pl. To anchor to something +# else, SHA256 is 24% slower than sha1-ppc.pl and 2.5x slower than +# hardware-assisted aes-128-cbc encrypt. SHA512 is 20% faster than +# sha1-ppc.pl and 1.6x slower than aes-128-cbc. Another interesting +# result is degree of computational resources' utilization. POWER8 is +# "massively multi-threaded chip" and difference between single- and +# maximum multi-process benchmark results tells that utilization is +# whooping 94%. For sha512-ppc.pl we get [not unimpressive] 84% and +# for sha1-ppc.pl - 73%. 100% means that multi-process result equals +# to single-process one, given that all threads end up on the same +# physical core. +# +###################################################################### +# Believed-to-be-accurate results in cycles per processed byte [on +# little-endian system]. Numbers in square brackets are for 64-bit +# build of sha512-ppc.pl, presented for reference. +# +# POWER8 POWER9 +# SHA256 9.7 [15.8] 11.2 [12.5] +# SHA512 6.1 [10.3] 7.0 [7.9] + +$flavour=shift; +$output =shift; + +if ($flavour =~ /64/) { + $SIZE_T=8; + $LRSAVE=2*$SIZE_T; + $STU="stdu"; + $POP="ld"; + $PUSH="std"; +} elsif ($flavour =~ /32/) { + $SIZE_T=4; + $LRSAVE=$SIZE_T; + $STU="stwu"; + $POP="lwz"; + $PUSH="stw"; +} else { die "nonsense $flavour"; } + +$LENDIAN=($flavour=~/le/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or +die "can't locate ppc-xlate.pl"; + +open STDOUT,"| $^X $xlate $flavour $output" || die "can't call $xlate: $!"; + +if ($output =~ /512/) { + $bits=512; + $SZ=8; + $sz="d"; + $rounds=80; +} else { + $bits=256; + $SZ=4; + $sz="w"; + $rounds=64; +} + +$func="sha${bits}_block_p8"; +$LOCALS=8*$SIZE_T+8*16; +$FRAME=$LOCALS+9*16+6*$SIZE_T; + +$sp ="r1"; +$toc="r2"; +$ctx="r3"; +$inp="r4"; +$num="r5"; +$Tbl="r6"; +$idx="r7"; +$lrsave="r8"; +$offload="r11"; +$vrsave="r12"; +@I = ($x00,$x10,$x20,$x30,$x40,$x50,$x60,$x70) = (0,map("r$_",(10,26..31))); + +@V=($A,$B,$C,$D,$E,$F,$G,$H)=map("v$_",(0..7)); +@X=map("v$_",(8..19,24..27)); +($Ki,$Func,$Sigma,$lemask)=map("v$_",(28..31)); + +sub ROUND { +my ($i,$a,$b,$c,$d,$e,$f,$g,$h)=@_; +my $j=($i+1)%16; +my $k=($i+2)%8; + +$code.=<<___ if ($i<15 && ($i%(16/$SZ))==(16/$SZ-1)); + lvx_u @X[$i+1],0,$inp ; load X[i] in advance + addi $inp,$inp,16 +___ +$code.=<<___ if ($i<16 && ($i%(16/$SZ))); + vsldoi @X[$i],@X[$i-1],@X[$i-1],$SZ +___ +$code.=<<___ if ($LENDIAN && $i<16 && ($i%(16/$SZ))==0); + vperm @X[$i],@X[$i],@X[$i],$lemask +___ +$code.=<<___ if ($i>=15); + vshasigma${sz} $Sigma,@X[($j+1)%16],0,0 + vaddu${sz}m @X[$j],@X[$j],$Sigma + vshasigma${sz} $Sigma,@X[($j+14)%16],0,15 + vaddu${sz}m @X[$j],@X[$j],$Sigma + vaddu${sz}m @X[$j],@X[$j],@X[($j+9)%16] +___ +$code.=<<___; + vaddu${sz}m $h,$h,@X[$i%16] ; h+=X[i] + vsel $Func,$g,$f,$e ; Ch(e,f,g) + vaddu${sz}m $g,$g,$Ki ; future h+=K[i] + vaddu${sz}m $h,$h,$Func ; h+=Ch(e,f,g) + vshasigma${sz} $Sigma,$e,1,15 ; Sigma1(e) + vaddu${sz}m $h,$h,$Sigma ; h+=Sigma1(e) + vxor $Func,$a,$b + vsel $Func,$b,$c,$Func ; Maj(a,b,c) + vaddu${sz}m $d,$d,$h ; d+=h + vshasigma${sz} $Sigma,$a,1,0 ; Sigma0(a) + vaddu${sz}m $Sigma,$Sigma,$Func ; Sigma0(a)+Maj(a,b,c) + vaddu${sz}m $h,$h,$Sigma ; h+=Sigma0(a)+Maj(a,b,c) + lvx $Ki,@I[$k],$idx ; load next K[i] +___ +$code.=<<___ if ($k == 7); + addi $idx,$idx,0x80 +___ +} + +$code=<<___; +.machine "any" +.text + +.globl $func +.align 6 +$func: + $STU $sp,-$FRAME($sp) + mflr $lrsave + li r10,`$LOCALS+15` + li r11,`$LOCALS+31` + stvx v24,r10,$sp # ABI says so + addi r10,r10,32 + mfspr $vrsave,256 + stvx v25,r11,$sp + addi r11,r11,32 + stvx v26,r10,$sp + addi r10,r10,32 + stvx v27,r11,$sp + addi r11,r11,32 + stvx v28,r10,$sp + addi r10,r10,32 + stvx v29,r11,$sp + addi r11,r11,32 + stvx v30,r10,$sp + stvx v31,r11,$sp + li r11,-4096+255 # 0xfffff0ff + stw $vrsave,`$FRAME-6*$SIZE_T-4`($sp) # save vrsave + li $x10,0x10 + $PUSH r26,`$FRAME-6*$SIZE_T`($sp) + li $x20,0x20 + $PUSH r27,`$FRAME-5*$SIZE_T`($sp) + li $x30,0x30 + $PUSH r28,`$FRAME-4*$SIZE_T`($sp) + li $x40,0x40 + $PUSH r29,`$FRAME-3*$SIZE_T`($sp) + li $x50,0x50 + $PUSH r30,`$FRAME-2*$SIZE_T`($sp) + li $x60,0x60 + $PUSH r31,`$FRAME-1*$SIZE_T`($sp) + li $x70,0x70 + $PUSH $lrsave,`$FRAME+$LRSAVE`($sp) + mtspr 256,r11 + + bl LPICmeup + addi $offload,$sp,`8*$SIZE_T+15` +___ +$code.=<<___ if ($LENDIAN); + li $idx,8 + lvsl $lemask,0,$idx + vspltisb $Ki,0x0f + vxor $lemask,$lemask,$Ki +___ +$code.=<<___ if ($SZ==4); + lvx_4w $A,$x00,$ctx + lvx_4w $E,$x10,$ctx + vsldoi $B,$A,$A,4 # unpack + vsldoi $C,$A,$A,8 + vsldoi $D,$A,$A,12 + vsldoi $F,$E,$E,4 + vsldoi $G,$E,$E,8 + vsldoi $H,$E,$E,12 +___ +$code.=<<___ if ($SZ==8); + lvx_u $A,$x00,$ctx + lvx_u $C,$x10,$ctx + lvx_u $E,$x20,$ctx + vsldoi $B,$A,$A,8 # unpack + lvx_u $G,$x30,$ctx + vsldoi $D,$C,$C,8 + vsldoi $F,$E,$E,8 + vsldoi $H,$G,$G,8 +___ +$code.=<<___; + li r0,`($rounds-16)/16` # inner loop counter + b Loop +.align 5 +Loop: + lvx $Ki,$x00,$Tbl + lvx_u @X[0],0,$inp + addi $inp,$inp,16 + mr $idx,$Tbl # copy $Tbl + stvx $A,$x00,$offload # offload $A-$H + stvx $B,$x10,$offload + stvx $C,$x20,$offload + stvx $D,$x30,$offload + stvx $E,$x40,$offload + stvx $F,$x50,$offload + stvx $G,$x60,$offload + stvx $H,$x70,$offload + vaddu${sz}m $H,$H,$Ki # h+K[i] + lvx $Ki,$x10,$Tbl +___ +for ($i=0;$i<16;$i++) { &ROUND($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + mtctr r0 + b L16_xx +.align 5 +L16_xx: +___ +for (;$i<32;$i++) { &ROUND($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + bdnz L16_xx + + lvx @X[2],$x00,$offload + subic. $num,$num,1 + lvx @X[3],$x10,$offload + vaddu${sz}m $A,$A,@X[2] + lvx @X[4],$x20,$offload + vaddu${sz}m $B,$B,@X[3] + lvx @X[5],$x30,$offload + vaddu${sz}m $C,$C,@X[4] + lvx @X[6],$x40,$offload + vaddu${sz}m $D,$D,@X[5] + lvx @X[7],$x50,$offload + vaddu${sz}m $E,$E,@X[6] + lvx @X[8],$x60,$offload + vaddu${sz}m $F,$F,@X[7] + lvx @X[9],$x70,$offload + vaddu${sz}m $G,$G,@X[8] + vaddu${sz}m $H,$H,@X[9] + bne Loop +___ +$code.=<<___ if ($SZ==4); + lvx @X[0],$x20,$idx + vperm $A,$A,$B,$Ki # pack the answer + lvx @X[1],$x30,$idx + vperm $E,$E,$F,$Ki + vperm $A,$A,$C,@X[0] + vperm $E,$E,$G,@X[0] + vperm $A,$A,$D,@X[1] + vperm $E,$E,$H,@X[1] + stvx_4w $A,$x00,$ctx + stvx_4w $E,$x10,$ctx +___ +$code.=<<___ if ($SZ==8); + vperm $A,$A,$B,$Ki # pack the answer + vperm $C,$C,$D,$Ki + vperm $E,$E,$F,$Ki + vperm $G,$G,$H,$Ki + stvx_u $A,$x00,$ctx + stvx_u $C,$x10,$ctx + stvx_u $E,$x20,$ctx + stvx_u $G,$x30,$ctx +___ +$code.=<<___; + addi $offload,$sp,`$LOCALS+15` + mtlr $lrsave + mtspr 256,$vrsave + lvx v24,$x00,$offload # ABI says so + lvx v25,$x10,$offload + lvx v26,$x20,$offload + lvx v27,$x30,$offload + lvx v28,$x40,$offload + lvx v29,$x50,$offload + lvx v30,$x60,$offload + lvx v31,$x70,$offload + $POP r26,`$FRAME-6*$SIZE_T`($sp) + $POP r27,`$FRAME-5*$SIZE_T`($sp) + $POP r28,`$FRAME-4*$SIZE_T`($sp) + $POP r29,`$FRAME-3*$SIZE_T`($sp) + $POP r30,`$FRAME-2*$SIZE_T`($sp) + $POP r31,`$FRAME-1*$SIZE_T`($sp) + addi $sp,$sp,$FRAME + blr + .long 0 + .byte 0,12,4,1,0x80,6,3,0 + .long 0 +.size $func,.-$func +___ + +# Ugly hack here, because PPC assembler syntax seem to vary too +# much from platforms to platform... +$code.=<<___; +.align 6 +LPICmeup: + mflr r0 + bcl 20,31,\$+4 + mflr $Tbl ; vvvvvv "distance" between . and 1st data entry + addi $Tbl,$Tbl,`64-8` + mtlr r0 + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 + .space `64-9*4` +___ + +if ($SZ==8) { + local *table = sub { + foreach(@_) { $code.=".quad $_,$_\n"; } + }; + table( + "0x428a2f98d728ae22","0x7137449123ef65cd", + "0xb5c0fbcfec4d3b2f","0xe9b5dba58189dbbc", + "0x3956c25bf348b538","0x59f111f1b605d019", + "0x923f82a4af194f9b","0xab1c5ed5da6d8118", + "0xd807aa98a3030242","0x12835b0145706fbe", + "0x243185be4ee4b28c","0x550c7dc3d5ffb4e2", + "0x72be5d74f27b896f","0x80deb1fe3b1696b1", + "0x9bdc06a725c71235","0xc19bf174cf692694", + "0xe49b69c19ef14ad2","0xefbe4786384f25e3", + "0x0fc19dc68b8cd5b5","0x240ca1cc77ac9c65", + "0x2de92c6f592b0275","0x4a7484aa6ea6e483", + "0x5cb0a9dcbd41fbd4","0x76f988da831153b5", + "0x983e5152ee66dfab","0xa831c66d2db43210", + "0xb00327c898fb213f","0xbf597fc7beef0ee4", + "0xc6e00bf33da88fc2","0xd5a79147930aa725", + "0x06ca6351e003826f","0x142929670a0e6e70", + "0x27b70a8546d22ffc","0x2e1b21385c26c926", + "0x4d2c6dfc5ac42aed","0x53380d139d95b3df", + "0x650a73548baf63de","0x766a0abb3c77b2a8", + "0x81c2c92e47edaee6","0x92722c851482353b", + "0xa2bfe8a14cf10364","0xa81a664bbc423001", + "0xc24b8b70d0f89791","0xc76c51a30654be30", + "0xd192e819d6ef5218","0xd69906245565a910", + "0xf40e35855771202a","0x106aa07032bbd1b8", + "0x19a4c116b8d2d0c8","0x1e376c085141ab53", + "0x2748774cdf8eeb99","0x34b0bcb5e19b48a8", + "0x391c0cb3c5c95a63","0x4ed8aa4ae3418acb", + "0x5b9cca4f7763e373","0x682e6ff3d6b2b8a3", + "0x748f82ee5defb2fc","0x78a5636f43172f60", + "0x84c87814a1f0ab72","0x8cc702081a6439ec", + "0x90befffa23631e28","0xa4506cebde82bde9", + "0xbef9a3f7b2c67915","0xc67178f2e372532b", + "0xca273eceea26619c","0xd186b8c721c0c207", + "0xeada7dd6cde0eb1e","0xf57d4f7fee6ed178", + "0x06f067aa72176fba","0x0a637dc5a2c898a6", + "0x113f9804bef90dae","0x1b710b35131c471b", + "0x28db77f523047d84","0x32caab7b40c72493", + "0x3c9ebe0a15c9bebc","0x431d67c49c100d4c", + "0x4cc5d4becb3e42b6","0x597f299cfc657e2a", + "0x5fcb6fab3ad6faec","0x6c44198c4a475817","0"); +$code.=<<___ if (!$LENDIAN); +.quad 0x0001020304050607,0x1011121314151617 +___ +$code.=<<___ if ($LENDIAN); # quad-swapped +.quad 0x1011121314151617,0x0001020304050607 +___ +} else { + local *table = sub { + foreach(@_) { $code.=".long $_,$_,$_,$_\n"; } + }; + table( + "0x428a2f98","0x71374491","0xb5c0fbcf","0xe9b5dba5", + "0x3956c25b","0x59f111f1","0x923f82a4","0xab1c5ed5", + "0xd807aa98","0x12835b01","0x243185be","0x550c7dc3", + "0x72be5d74","0x80deb1fe","0x9bdc06a7","0xc19bf174", + "0xe49b69c1","0xefbe4786","0x0fc19dc6","0x240ca1cc", + "0x2de92c6f","0x4a7484aa","0x5cb0a9dc","0x76f988da", + "0x983e5152","0xa831c66d","0xb00327c8","0xbf597fc7", + "0xc6e00bf3","0xd5a79147","0x06ca6351","0x14292967", + "0x27b70a85","0x2e1b2138","0x4d2c6dfc","0x53380d13", + "0x650a7354","0x766a0abb","0x81c2c92e","0x92722c85", + "0xa2bfe8a1","0xa81a664b","0xc24b8b70","0xc76c51a3", + "0xd192e819","0xd6990624","0xf40e3585","0x106aa070", + "0x19a4c116","0x1e376c08","0x2748774c","0x34b0bcb5", + "0x391c0cb3","0x4ed8aa4a","0x5b9cca4f","0x682e6ff3", + "0x748f82ee","0x78a5636f","0x84c87814","0x8cc70208", + "0x90befffa","0xa4506ceb","0xbef9a3f7","0xc67178f2","0"); +$code.=<<___ if (!$LENDIAN); +.long 0x00010203,0x10111213,0x10111213,0x10111213 +.long 0x00010203,0x04050607,0x10111213,0x10111213 +.long 0x00010203,0x04050607,0x08090a0b,0x10111213 +___ +$code.=<<___ if ($LENDIAN); # word-swapped +.long 0x10111213,0x10111213,0x10111213,0x00010203 +.long 0x10111213,0x10111213,0x04050607,0x00010203 +.long 0x10111213,0x08090a0b,0x04050607,0x00010203 +___ +} +$code.=<<___; +.asciz "SHA${bits} for PowerISA 2.07, CRYPTOGAMS by " +.align 2 +___ + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/build.info new file mode 100644 index 000000000..5dd5a9941 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/build.info @@ -0,0 +1,89 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + sha1dgst.c sha1_one.c sha256.c sha512.c {- $target{sha1_asm_src} -} \ + {- $target{keccak1600_asm_src} -} + +GENERATE[sha1-586.s]=asm/sha1-586.pl \ + $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) +DEPEND[sha1-586.s]=../perlasm/x86asm.pl +GENERATE[sha256-586.s]=asm/sha256-586.pl \ + $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) +DEPEND[sha256-586.s]=../perlasm/x86asm.pl +GENERATE[sha512-586.s]=asm/sha512-586.pl \ + $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) +DEPEND[sha512-586.s]=../perlasm/x86asm.pl + +GENERATE[sha1-ia64.s]=asm/sha1-ia64.pl $(LIB_CFLAGS) $(LIB_CPPFLAGS) +GENERATE[sha256-ia64.s]=asm/sha512-ia64.pl $(LIB_CFLAGS) $(LIB_CPPFLAGS) +GENERATE[sha512-ia64.s]=asm/sha512-ia64.pl $(LIB_CFLAGS) $(LIB_CPPFLAGS) + +GENERATE[sha1-alpha.S]=asm/sha1-alpha.pl $(PERLASM_SCHEME) + +GENERATE[sha1-x86_64.s]=asm/sha1-x86_64.pl $(PERLASM_SCHEME) +GENERATE[sha1-mb-x86_64.s]=asm/sha1-mb-x86_64.pl $(PERLASM_SCHEME) +GENERATE[sha256-x86_64.s]=asm/sha512-x86_64.pl $(PERLASM_SCHEME) +GENERATE[sha256-mb-x86_64.s]=asm/sha256-mb-x86_64.pl $(PERLASM_SCHEME) +GENERATE[sha512-x86_64.s]=asm/sha512-x86_64.pl $(PERLASM_SCHEME) +GENERATE[keccak1600-x86_64.s]=asm/keccak1600-x86_64.pl $(PERLASM_SCHEME) + +GENERATE[sha1-sparcv9.S]=asm/sha1-sparcv9.pl $(PERLASM_SCHEME) +INCLUDE[sha1-sparcv9.o]=.. +GENERATE[sha256-sparcv9.S]=asm/sha512-sparcv9.pl $(PERLASM_SCHEME) +INCLUDE[sha256-sparcv9.o]=.. +GENERATE[sha512-sparcv9.S]=asm/sha512-sparcv9.pl $(PERLASM_SCHEME) +INCLUDE[sha512-sparcv9.o]=.. + +GENERATE[sha1-ppc.s]=asm/sha1-ppc.pl $(PERLASM_SCHEME) +GENERATE[sha256-ppc.s]=asm/sha512-ppc.pl $(PERLASM_SCHEME) +GENERATE[sha512-ppc.s]=asm/sha512-ppc.pl $(PERLASM_SCHEME) +GENERATE[sha256p8-ppc.s]=asm/sha512p8-ppc.pl $(PERLASM_SCHEME) +GENERATE[sha512p8-ppc.s]=asm/sha512p8-ppc.pl $(PERLASM_SCHEME) +GENERATE[keccak1600-ppc64.s]=asm/keccak1600-ppc64.pl $(PERLASM_SCHEME) + +GENERATE[sha1-parisc.s]=asm/sha1-parisc.pl $(PERLASM_SCHEME) +GENERATE[sha256-parisc.s]=asm/sha512-parisc.pl $(PERLASM_SCHEME) +GENERATE[sha512-parisc.s]=asm/sha512-parisc.pl $(PERLASM_SCHEME) + +GENERATE[sha1-mips.S]=asm/sha1-mips.pl $(PERLASM_SCHEME) +INCLUDE[sha1-mips.o]=.. +GENERATE[sha256-mips.S]=asm/sha512-mips.pl $(PERLASM_SCHEME) +INCLUDE[sha256-mips.o]=.. +GENERATE[sha512-mips.S]=asm/sha512-mips.pl $(PERLASM_SCHEME) +INCLUDE[sha512-mips.o]=.. + +GENERATE[sha1-armv4-large.S]=asm/sha1-armv4-large.pl $(PERLASM_SCHEME) +INCLUDE[sha1-armv4-large.o]=.. +GENERATE[sha256-armv4.S]=asm/sha256-armv4.pl $(PERLASM_SCHEME) +INCLUDE[sha256-armv4.o]=.. +GENERATE[sha512-armv4.S]=asm/sha512-armv4.pl $(PERLASM_SCHEME) +INCLUDE[sha512-armv4.o]=.. +GENERATE[keccak1600-armv4.S]=asm/keccak1600-armv4.pl $(PERLASM_SCHEME) +INCLUDE[keccak1600-armv4.o]=.. + +GENERATE[sha1-armv8.S]=asm/sha1-armv8.pl $(PERLASM_SCHEME) +INCLUDE[sha1-armv8.o]=.. +GENERATE[sha256-armv8.S]=asm/sha512-armv8.pl $(PERLASM_SCHEME) +INCLUDE[sha256-armv8.o]=.. +GENERATE[sha512-armv8.S]=asm/sha512-armv8.pl $(PERLASM_SCHEME) +INCLUDE[sha512-armv8.o]=.. +GENERATE[keccak1600-armv8.S]=asm/keccak1600-armv8.pl $(PERLASM_SCHEME) + +GENERATE[sha1-s390x.S]=asm/sha1-s390x.pl $(PERLASM_SCHEME) +INCLUDE[sha1-s390x.o]=.. +GENERATE[sha256-s390x.S]=asm/sha512-s390x.pl $(PERLASM_SCHEME) +INCLUDE[sha256-s390x.o]=.. +GENERATE[sha512-s390x.S]=asm/sha512-s390x.pl $(PERLASM_SCHEME) +INCLUDE[sha512-s390x.o]=.. +GENERATE[keccak1600-s390x.S]=asm/keccak1600-s390x.pl $(PERLASM_SCHEME) + +BEGINRAW[Makefile(unix)] +##### SHA assembler implementations + +# GNU make "catch all" +{- $builddir -}/sha1-%.S: {- $sourcedir -}/asm/sha1-%.pl + CC="$(CC)" $(PERL) $< $(PERLASM_SCHEME) $@ +{- $builddir -}/sha256-%.S: {- $sourcedir -}/asm/sha512-%.pl + CC="$(CC)" $(PERL) $< $(PERLASM_SCHEME) $@ +{- $builddir -}/sha512-%.S: {- $sourcedir -}/asm/sha512-%.pl + CC="$(CC)" $(PERL) $< $(PERLASM_SCHEME) $@ +ENDRAW[Makefile(unix)] diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/keccak1600.c b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/keccak1600.c new file mode 100644 index 000000000..e7223486a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/keccak1600.c @@ -0,0 +1,1246 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include + +size_t SHA3_absorb(uint64_t A[5][5], const unsigned char *inp, size_t len, + size_t r); +void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len, size_t r); + +#if !defined(KECCAK1600_ASM) || !defined(SELFTEST) + +/* + * Choose some sensible defaults + */ +#if !defined(KECCAK_REF) && !defined(KECCAK_1X) && !defined(KECCAK_1X_ALT) && \ + !defined(KECCAK_2X) && !defined(KECCAK_INPLACE) +# define KECCAK_2X /* default to KECCAK_2X variant */ +#endif + +#if defined(__i386) || defined(__i386__) || defined(_M_IX86) +# define KECCAK_COMPLEMENTING_TRANSFORM +#endif + +#if defined(__x86_64__) || defined(__aarch64__) || \ + defined(__mips64) || defined(__ia64) || \ + (defined(__VMS) && !defined(__vax)) +/* + * These are available even in ILP32 flavours, but even then they are + * capable of performing 64-bit operations as efficiently as in *P64. + * Since it's not given that we can use sizeof(void *), just shunt it. + */ +# define BIT_INTERLEAVE (0) +#else +# define BIT_INTERLEAVE (sizeof(void *) < 8) +#endif + +#define ROL32(a, offset) (((a) << (offset)) | ((a) >> ((32 - (offset)) & 31))) + +static uint64_t ROL64(uint64_t val, int offset) +{ + if (offset == 0) { + return val; + } else if (!BIT_INTERLEAVE) { + return (val << offset) | (val >> (64-offset)); + } else { + uint32_t hi = (uint32_t)(val >> 32), lo = (uint32_t)val; + + if (offset & 1) { + uint32_t tmp = hi; + + offset >>= 1; + hi = ROL32(lo, offset); + lo = ROL32(tmp, offset + 1); + } else { + offset >>= 1; + lo = ROL32(lo, offset); + hi = ROL32(hi, offset); + } + + return ((uint64_t)hi << 32) | lo; + } +} + +static const unsigned char rhotates[5][5] = { + { 0, 1, 62, 28, 27 }, + { 36, 44, 6, 55, 20 }, + { 3, 10, 43, 25, 39 }, + { 41, 45, 15, 21, 8 }, + { 18, 2, 61, 56, 14 } +}; + +static const uint64_t iotas[] = { + BIT_INTERLEAVE ? 0x0000000000000001U : 0x0000000000000001U, + BIT_INTERLEAVE ? 0x0000008900000000U : 0x0000000000008082U, + BIT_INTERLEAVE ? 0x8000008b00000000U : 0x800000000000808aU, + BIT_INTERLEAVE ? 0x8000808000000000U : 0x8000000080008000U, + BIT_INTERLEAVE ? 0x0000008b00000001U : 0x000000000000808bU, + BIT_INTERLEAVE ? 0x0000800000000001U : 0x0000000080000001U, + BIT_INTERLEAVE ? 0x8000808800000001U : 0x8000000080008081U, + BIT_INTERLEAVE ? 0x8000008200000001U : 0x8000000000008009U, + BIT_INTERLEAVE ? 0x0000000b00000000U : 0x000000000000008aU, + BIT_INTERLEAVE ? 0x0000000a00000000U : 0x0000000000000088U, + BIT_INTERLEAVE ? 0x0000808200000001U : 0x0000000080008009U, + BIT_INTERLEAVE ? 0x0000800300000000U : 0x000000008000000aU, + BIT_INTERLEAVE ? 0x0000808b00000001U : 0x000000008000808bU, + BIT_INTERLEAVE ? 0x8000000b00000001U : 0x800000000000008bU, + BIT_INTERLEAVE ? 0x8000008a00000001U : 0x8000000000008089U, + BIT_INTERLEAVE ? 0x8000008100000001U : 0x8000000000008003U, + BIT_INTERLEAVE ? 0x8000008100000000U : 0x8000000000008002U, + BIT_INTERLEAVE ? 0x8000000800000000U : 0x8000000000000080U, + BIT_INTERLEAVE ? 0x0000008300000000U : 0x000000000000800aU, + BIT_INTERLEAVE ? 0x8000800300000000U : 0x800000008000000aU, + BIT_INTERLEAVE ? 0x8000808800000001U : 0x8000000080008081U, + BIT_INTERLEAVE ? 0x8000008800000000U : 0x8000000000008080U, + BIT_INTERLEAVE ? 0x0000800000000001U : 0x0000000080000001U, + BIT_INTERLEAVE ? 0x8000808200000000U : 0x8000000080008008U +}; + +#if defined(KECCAK_REF) +/* + * This is straightforward or "maximum clarity" implementation aiming + * to resemble section 3.2 of the FIPS PUB 202 "SHA-3 Standard: + * Permutation-Based Hash and Extendible-Output Functions" as much as + * possible. With one caveat. Because of the way C stores matrices, + * references to A[x,y] in the specification are presented as A[y][x]. + * Implementation unrolls inner x-loops so that modulo 5 operations are + * explicitly pre-computed. + */ +static void Theta(uint64_t A[5][5]) +{ + uint64_t C[5], D[5]; + size_t y; + + C[0] = A[0][0]; + C[1] = A[0][1]; + C[2] = A[0][2]; + C[3] = A[0][3]; + C[4] = A[0][4]; + + for (y = 1; y < 5; y++) { + C[0] ^= A[y][0]; + C[1] ^= A[y][1]; + C[2] ^= A[y][2]; + C[3] ^= A[y][3]; + C[4] ^= A[y][4]; + } + + D[0] = ROL64(C[1], 1) ^ C[4]; + D[1] = ROL64(C[2], 1) ^ C[0]; + D[2] = ROL64(C[3], 1) ^ C[1]; + D[3] = ROL64(C[4], 1) ^ C[2]; + D[4] = ROL64(C[0], 1) ^ C[3]; + + for (y = 0; y < 5; y++) { + A[y][0] ^= D[0]; + A[y][1] ^= D[1]; + A[y][2] ^= D[2]; + A[y][3] ^= D[3]; + A[y][4] ^= D[4]; + } +} + +static void Rho(uint64_t A[5][5]) +{ + size_t y; + + for (y = 0; y < 5; y++) { + A[y][0] = ROL64(A[y][0], rhotates[y][0]); + A[y][1] = ROL64(A[y][1], rhotates[y][1]); + A[y][2] = ROL64(A[y][2], rhotates[y][2]); + A[y][3] = ROL64(A[y][3], rhotates[y][3]); + A[y][4] = ROL64(A[y][4], rhotates[y][4]); + } +} + +static void Pi(uint64_t A[5][5]) +{ + uint64_t T[5][5]; + + /* + * T = A + * A[y][x] = T[x][(3*y+x)%5] + */ + memcpy(T, A, sizeof(T)); + + A[0][0] = T[0][0]; + A[0][1] = T[1][1]; + A[0][2] = T[2][2]; + A[0][3] = T[3][3]; + A[0][4] = T[4][4]; + + A[1][0] = T[0][3]; + A[1][1] = T[1][4]; + A[1][2] = T[2][0]; + A[1][3] = T[3][1]; + A[1][4] = T[4][2]; + + A[2][0] = T[0][1]; + A[2][1] = T[1][2]; + A[2][2] = T[2][3]; + A[2][3] = T[3][4]; + A[2][4] = T[4][0]; + + A[3][0] = T[0][4]; + A[3][1] = T[1][0]; + A[3][2] = T[2][1]; + A[3][3] = T[3][2]; + A[3][4] = T[4][3]; + + A[4][0] = T[0][2]; + A[4][1] = T[1][3]; + A[4][2] = T[2][4]; + A[4][3] = T[3][0]; + A[4][4] = T[4][1]; +} + +static void Chi(uint64_t A[5][5]) +{ + uint64_t C[5]; + size_t y; + + for (y = 0; y < 5; y++) { + C[0] = A[y][0] ^ (~A[y][1] & A[y][2]); + C[1] = A[y][1] ^ (~A[y][2] & A[y][3]); + C[2] = A[y][2] ^ (~A[y][3] & A[y][4]); + C[3] = A[y][3] ^ (~A[y][4] & A[y][0]); + C[4] = A[y][4] ^ (~A[y][0] & A[y][1]); + + A[y][0] = C[0]; + A[y][1] = C[1]; + A[y][2] = C[2]; + A[y][3] = C[3]; + A[y][4] = C[4]; + } +} + +static void Iota(uint64_t A[5][5], size_t i) +{ + assert(i < (sizeof(iotas) / sizeof(iotas[0]))); + A[0][0] ^= iotas[i]; +} + +static void KeccakF1600(uint64_t A[5][5]) +{ + size_t i; + + for (i = 0; i < 24; i++) { + Theta(A); + Rho(A); + Pi(A); + Chi(A); + Iota(A, i); + } +} + +#elif defined(KECCAK_1X) +/* + * This implementation is optimization of above code featuring unroll + * of even y-loops, their fusion and code motion. It also minimizes + * temporary storage. Compiler would normally do all these things for + * you, purpose of manual optimization is to provide "unobscured" + * reference for assembly implementation [in case this approach is + * chosen for implementation on some platform]. In the nutshell it's + * equivalent of "plane-per-plane processing" approach discussed in + * section 2.4 of "Keccak implementation overview". + */ +static void Round(uint64_t A[5][5], size_t i) +{ + uint64_t C[5], E[2]; /* registers */ + uint64_t D[5], T[2][5]; /* memory */ + + assert(i < (sizeof(iotas) / sizeof(iotas[0]))); + + C[0] = A[0][0] ^ A[1][0] ^ A[2][0] ^ A[3][0] ^ A[4][0]; + C[1] = A[0][1] ^ A[1][1] ^ A[2][1] ^ A[3][1] ^ A[4][1]; + C[2] = A[0][2] ^ A[1][2] ^ A[2][2] ^ A[3][2] ^ A[4][2]; + C[3] = A[0][3] ^ A[1][3] ^ A[2][3] ^ A[3][3] ^ A[4][3]; + C[4] = A[0][4] ^ A[1][4] ^ A[2][4] ^ A[3][4] ^ A[4][4]; + +#if defined(__arm__) + D[1] = E[0] = ROL64(C[2], 1) ^ C[0]; + D[4] = E[1] = ROL64(C[0], 1) ^ C[3]; + D[0] = C[0] = ROL64(C[1], 1) ^ C[4]; + D[2] = C[1] = ROL64(C[3], 1) ^ C[1]; + D[3] = C[2] = ROL64(C[4], 1) ^ C[2]; + + T[0][0] = A[3][0] ^ C[0]; /* borrow T[0][0] */ + T[0][1] = A[0][1] ^ E[0]; /* D[1] */ + T[0][2] = A[0][2] ^ C[1]; /* D[2] */ + T[0][3] = A[0][3] ^ C[2]; /* D[3] */ + T[0][4] = A[0][4] ^ E[1]; /* D[4] */ + + C[3] = ROL64(A[3][3] ^ C[2], rhotates[3][3]); /* D[3] */ + C[4] = ROL64(A[4][4] ^ E[1], rhotates[4][4]); /* D[4] */ + C[0] = A[0][0] ^ C[0]; /* rotate by 0 */ /* D[0] */ + C[2] = ROL64(A[2][2] ^ C[1], rhotates[2][2]); /* D[2] */ + C[1] = ROL64(A[1][1] ^ E[0], rhotates[1][1]); /* D[1] */ +#else + D[0] = ROL64(C[1], 1) ^ C[4]; + D[1] = ROL64(C[2], 1) ^ C[0]; + D[2] = ROL64(C[3], 1) ^ C[1]; + D[3] = ROL64(C[4], 1) ^ C[2]; + D[4] = ROL64(C[0], 1) ^ C[3]; + + T[0][0] = A[3][0] ^ D[0]; /* borrow T[0][0] */ + T[0][1] = A[0][1] ^ D[1]; + T[0][2] = A[0][2] ^ D[2]; + T[0][3] = A[0][3] ^ D[3]; + T[0][4] = A[0][4] ^ D[4]; + + C[0] = A[0][0] ^ D[0]; /* rotate by 0 */ + C[1] = ROL64(A[1][1] ^ D[1], rhotates[1][1]); + C[2] = ROL64(A[2][2] ^ D[2], rhotates[2][2]); + C[3] = ROL64(A[3][3] ^ D[3], rhotates[3][3]); + C[4] = ROL64(A[4][4] ^ D[4], rhotates[4][4]); +#endif + A[0][0] = C[0] ^ (~C[1] & C[2]) ^ iotas[i]; + A[0][1] = C[1] ^ (~C[2] & C[3]); + A[0][2] = C[2] ^ (~C[3] & C[4]); + A[0][3] = C[3] ^ (~C[4] & C[0]); + A[0][4] = C[4] ^ (~C[0] & C[1]); + + T[1][0] = A[1][0] ^ (C[3] = D[0]); + T[1][1] = A[2][1] ^ (C[4] = D[1]); /* borrow T[1][1] */ + T[1][2] = A[1][2] ^ (E[0] = D[2]); + T[1][3] = A[1][3] ^ (E[1] = D[3]); + T[1][4] = A[2][4] ^ (C[2] = D[4]); /* borrow T[1][4] */ + + C[0] = ROL64(T[0][3], rhotates[0][3]); + C[1] = ROL64(A[1][4] ^ C[2], rhotates[1][4]); /* D[4] */ + C[2] = ROL64(A[2][0] ^ C[3], rhotates[2][0]); /* D[0] */ + C[3] = ROL64(A[3][1] ^ C[4], rhotates[3][1]); /* D[1] */ + C[4] = ROL64(A[4][2] ^ E[0], rhotates[4][2]); /* D[2] */ + + A[1][0] = C[0] ^ (~C[1] & C[2]); + A[1][1] = C[1] ^ (~C[2] & C[3]); + A[1][2] = C[2] ^ (~C[3] & C[4]); + A[1][3] = C[3] ^ (~C[4] & C[0]); + A[1][4] = C[4] ^ (~C[0] & C[1]); + + C[0] = ROL64(T[0][1], rhotates[0][1]); + C[1] = ROL64(T[1][2], rhotates[1][2]); + C[2] = ROL64(A[2][3] ^ D[3], rhotates[2][3]); + C[3] = ROL64(A[3][4] ^ D[4], rhotates[3][4]); + C[4] = ROL64(A[4][0] ^ D[0], rhotates[4][0]); + + A[2][0] = C[0] ^ (~C[1] & C[2]); + A[2][1] = C[1] ^ (~C[2] & C[3]); + A[2][2] = C[2] ^ (~C[3] & C[4]); + A[2][3] = C[3] ^ (~C[4] & C[0]); + A[2][4] = C[4] ^ (~C[0] & C[1]); + + C[0] = ROL64(T[0][4], rhotates[0][4]); + C[1] = ROL64(T[1][0], rhotates[1][0]); + C[2] = ROL64(T[1][1], rhotates[2][1]); /* originally A[2][1] */ + C[3] = ROL64(A[3][2] ^ D[2], rhotates[3][2]); + C[4] = ROL64(A[4][3] ^ D[3], rhotates[4][3]); + + A[3][0] = C[0] ^ (~C[1] & C[2]); + A[3][1] = C[1] ^ (~C[2] & C[3]); + A[3][2] = C[2] ^ (~C[3] & C[4]); + A[3][3] = C[3] ^ (~C[4] & C[0]); + A[3][4] = C[4] ^ (~C[0] & C[1]); + + C[0] = ROL64(T[0][2], rhotates[0][2]); + C[1] = ROL64(T[1][3], rhotates[1][3]); + C[2] = ROL64(T[1][4], rhotates[2][4]); /* originally A[2][4] */ + C[3] = ROL64(T[0][0], rhotates[3][0]); /* originally A[3][0] */ + C[4] = ROL64(A[4][1] ^ D[1], rhotates[4][1]); + + A[4][0] = C[0] ^ (~C[1] & C[2]); + A[4][1] = C[1] ^ (~C[2] & C[3]); + A[4][2] = C[2] ^ (~C[3] & C[4]); + A[4][3] = C[3] ^ (~C[4] & C[0]); + A[4][4] = C[4] ^ (~C[0] & C[1]); +} + +static void KeccakF1600(uint64_t A[5][5]) +{ + size_t i; + + for (i = 0; i < 24; i++) { + Round(A, i); + } +} + +#elif defined(KECCAK_1X_ALT) +/* + * This is variant of above KECCAK_1X that reduces requirement for + * temporary storage even further, but at cost of more updates to A[][]. + * It's less suitable if A[][] is memory bound, but better if it's + * register bound. + */ + +static void Round(uint64_t A[5][5], size_t i) +{ + uint64_t C[5], D[5]; + + assert(i < (sizeof(iotas) / sizeof(iotas[0]))); + + C[0] = A[0][0] ^ A[1][0] ^ A[2][0] ^ A[3][0] ^ A[4][0]; + C[1] = A[0][1] ^ A[1][1] ^ A[2][1] ^ A[3][1] ^ A[4][1]; + C[2] = A[0][2] ^ A[1][2] ^ A[2][2] ^ A[3][2] ^ A[4][2]; + C[3] = A[0][3] ^ A[1][3] ^ A[2][3] ^ A[3][3] ^ A[4][3]; + C[4] = A[0][4] ^ A[1][4] ^ A[2][4] ^ A[3][4] ^ A[4][4]; + + D[1] = C[0] ^ ROL64(C[2], 1); + D[2] = C[1] ^ ROL64(C[3], 1); + D[3] = C[2] ^= ROL64(C[4], 1); + D[4] = C[3] ^= ROL64(C[0], 1); + D[0] = C[4] ^= ROL64(C[1], 1); + + A[0][1] ^= D[1]; + A[1][1] ^= D[1]; + A[2][1] ^= D[1]; + A[3][1] ^= D[1]; + A[4][1] ^= D[1]; + + A[0][2] ^= D[2]; + A[1][2] ^= D[2]; + A[2][2] ^= D[2]; + A[3][2] ^= D[2]; + A[4][2] ^= D[2]; + + A[0][3] ^= C[2]; + A[1][3] ^= C[2]; + A[2][3] ^= C[2]; + A[3][3] ^= C[2]; + A[4][3] ^= C[2]; + + A[0][4] ^= C[3]; + A[1][4] ^= C[3]; + A[2][4] ^= C[3]; + A[3][4] ^= C[3]; + A[4][4] ^= C[3]; + + A[0][0] ^= C[4]; + A[1][0] ^= C[4]; + A[2][0] ^= C[4]; + A[3][0] ^= C[4]; + A[4][0] ^= C[4]; + + C[1] = A[0][1]; + C[2] = A[0][2]; + C[3] = A[0][3]; + C[4] = A[0][4]; + + A[0][1] = ROL64(A[1][1], rhotates[1][1]); + A[0][2] = ROL64(A[2][2], rhotates[2][2]); + A[0][3] = ROL64(A[3][3], rhotates[3][3]); + A[0][4] = ROL64(A[4][4], rhotates[4][4]); + + A[1][1] = ROL64(A[1][4], rhotates[1][4]); + A[2][2] = ROL64(A[2][3], rhotates[2][3]); + A[3][3] = ROL64(A[3][2], rhotates[3][2]); + A[4][4] = ROL64(A[4][1], rhotates[4][1]); + + A[1][4] = ROL64(A[4][2], rhotates[4][2]); + A[2][3] = ROL64(A[3][4], rhotates[3][4]); + A[3][2] = ROL64(A[2][1], rhotates[2][1]); + A[4][1] = ROL64(A[1][3], rhotates[1][3]); + + A[4][2] = ROL64(A[2][4], rhotates[2][4]); + A[3][4] = ROL64(A[4][3], rhotates[4][3]); + A[2][1] = ROL64(A[1][2], rhotates[1][2]); + A[1][3] = ROL64(A[3][1], rhotates[3][1]); + + A[2][4] = ROL64(A[4][0], rhotates[4][0]); + A[4][3] = ROL64(A[3][0], rhotates[3][0]); + A[1][2] = ROL64(A[2][0], rhotates[2][0]); + A[3][1] = ROL64(A[1][0], rhotates[1][0]); + + A[1][0] = ROL64(C[3], rhotates[0][3]); + A[2][0] = ROL64(C[1], rhotates[0][1]); + A[3][0] = ROL64(C[4], rhotates[0][4]); + A[4][0] = ROL64(C[2], rhotates[0][2]); + + C[0] = A[0][0]; + C[1] = A[1][0]; + D[0] = A[0][1]; + D[1] = A[1][1]; + + A[0][0] ^= (~A[0][1] & A[0][2]); + A[1][0] ^= (~A[1][1] & A[1][2]); + A[0][1] ^= (~A[0][2] & A[0][3]); + A[1][1] ^= (~A[1][2] & A[1][3]); + A[0][2] ^= (~A[0][3] & A[0][4]); + A[1][2] ^= (~A[1][3] & A[1][4]); + A[0][3] ^= (~A[0][4] & C[0]); + A[1][3] ^= (~A[1][4] & C[1]); + A[0][4] ^= (~C[0] & D[0]); + A[1][4] ^= (~C[1] & D[1]); + + C[2] = A[2][0]; + C[3] = A[3][0]; + D[2] = A[2][1]; + D[3] = A[3][1]; + + A[2][0] ^= (~A[2][1] & A[2][2]); + A[3][0] ^= (~A[3][1] & A[3][2]); + A[2][1] ^= (~A[2][2] & A[2][3]); + A[3][1] ^= (~A[3][2] & A[3][3]); + A[2][2] ^= (~A[2][3] & A[2][4]); + A[3][2] ^= (~A[3][3] & A[3][4]); + A[2][3] ^= (~A[2][4] & C[2]); + A[3][3] ^= (~A[3][4] & C[3]); + A[2][4] ^= (~C[2] & D[2]); + A[3][4] ^= (~C[3] & D[3]); + + C[4] = A[4][0]; + D[4] = A[4][1]; + + A[4][0] ^= (~A[4][1] & A[4][2]); + A[4][1] ^= (~A[4][2] & A[4][3]); + A[4][2] ^= (~A[4][3] & A[4][4]); + A[4][3] ^= (~A[4][4] & C[4]); + A[4][4] ^= (~C[4] & D[4]); + A[0][0] ^= iotas[i]; +} + +static void KeccakF1600(uint64_t A[5][5]) +{ + size_t i; + + for (i = 0; i < 24; i++) { + Round(A, i); + } +} + +#elif defined(KECCAK_2X) +/* + * This implementation is variant of KECCAK_1X above with outer-most + * round loop unrolled twice. This allows to take temporary storage + * out of round procedure and simplify references to it by alternating + * it with actual data (see round loop below). Originally it was meant + * rather as reference for an assembly implementation, but it seems to + * play best with compilers [as well as provide best instruction per + * processed byte ratio at minimal round unroll factor]... + */ +static void Round(uint64_t R[5][5], uint64_t A[5][5], size_t i) +{ + uint64_t C[5], D[5]; + + assert(i < (sizeof(iotas) / sizeof(iotas[0]))); + + C[0] = A[0][0] ^ A[1][0] ^ A[2][0] ^ A[3][0] ^ A[4][0]; + C[1] = A[0][1] ^ A[1][1] ^ A[2][1] ^ A[3][1] ^ A[4][1]; + C[2] = A[0][2] ^ A[1][2] ^ A[2][2] ^ A[3][2] ^ A[4][2]; + C[3] = A[0][3] ^ A[1][3] ^ A[2][3] ^ A[3][3] ^ A[4][3]; + C[4] = A[0][4] ^ A[1][4] ^ A[2][4] ^ A[3][4] ^ A[4][4]; + + D[0] = ROL64(C[1], 1) ^ C[4]; + D[1] = ROL64(C[2], 1) ^ C[0]; + D[2] = ROL64(C[3], 1) ^ C[1]; + D[3] = ROL64(C[4], 1) ^ C[2]; + D[4] = ROL64(C[0], 1) ^ C[3]; + + C[0] = A[0][0] ^ D[0]; /* rotate by 0 */ + C[1] = ROL64(A[1][1] ^ D[1], rhotates[1][1]); + C[2] = ROL64(A[2][2] ^ D[2], rhotates[2][2]); + C[3] = ROL64(A[3][3] ^ D[3], rhotates[3][3]); + C[4] = ROL64(A[4][4] ^ D[4], rhotates[4][4]); + +#ifdef KECCAK_COMPLEMENTING_TRANSFORM + R[0][0] = C[0] ^ ( C[1] | C[2]) ^ iotas[i]; + R[0][1] = C[1] ^ (~C[2] | C[3]); + R[0][2] = C[2] ^ ( C[3] & C[4]); + R[0][3] = C[3] ^ ( C[4] | C[0]); + R[0][4] = C[4] ^ ( C[0] & C[1]); +#else + R[0][0] = C[0] ^ (~C[1] & C[2]) ^ iotas[i]; + R[0][1] = C[1] ^ (~C[2] & C[3]); + R[0][2] = C[2] ^ (~C[3] & C[4]); + R[0][3] = C[3] ^ (~C[4] & C[0]); + R[0][4] = C[4] ^ (~C[0] & C[1]); +#endif + + C[0] = ROL64(A[0][3] ^ D[3], rhotates[0][3]); + C[1] = ROL64(A[1][4] ^ D[4], rhotates[1][4]); + C[2] = ROL64(A[2][0] ^ D[0], rhotates[2][0]); + C[3] = ROL64(A[3][1] ^ D[1], rhotates[3][1]); + C[4] = ROL64(A[4][2] ^ D[2], rhotates[4][2]); + +#ifdef KECCAK_COMPLEMENTING_TRANSFORM + R[1][0] = C[0] ^ (C[1] | C[2]); + R[1][1] = C[1] ^ (C[2] & C[3]); + R[1][2] = C[2] ^ (C[3] | ~C[4]); + R[1][3] = C[3] ^ (C[4] | C[0]); + R[1][4] = C[4] ^ (C[0] & C[1]); +#else + R[1][0] = C[0] ^ (~C[1] & C[2]); + R[1][1] = C[1] ^ (~C[2] & C[3]); + R[1][2] = C[2] ^ (~C[3] & C[4]); + R[1][3] = C[3] ^ (~C[4] & C[0]); + R[1][4] = C[4] ^ (~C[0] & C[1]); +#endif + + C[0] = ROL64(A[0][1] ^ D[1], rhotates[0][1]); + C[1] = ROL64(A[1][2] ^ D[2], rhotates[1][2]); + C[2] = ROL64(A[2][3] ^ D[3], rhotates[2][3]); + C[3] = ROL64(A[3][4] ^ D[4], rhotates[3][4]); + C[4] = ROL64(A[4][0] ^ D[0], rhotates[4][0]); + +#ifdef KECCAK_COMPLEMENTING_TRANSFORM + R[2][0] = C[0] ^ ( C[1] | C[2]); + R[2][1] = C[1] ^ ( C[2] & C[3]); + R[2][2] = C[2] ^ (~C[3] & C[4]); + R[2][3] = ~C[3] ^ ( C[4] | C[0]); + R[2][4] = C[4] ^ ( C[0] & C[1]); +#else + R[2][0] = C[0] ^ (~C[1] & C[2]); + R[2][1] = C[1] ^ (~C[2] & C[3]); + R[2][2] = C[2] ^ (~C[3] & C[4]); + R[2][3] = C[3] ^ (~C[4] & C[0]); + R[2][4] = C[4] ^ (~C[0] & C[1]); +#endif + + C[0] = ROL64(A[0][4] ^ D[4], rhotates[0][4]); + C[1] = ROL64(A[1][0] ^ D[0], rhotates[1][0]); + C[2] = ROL64(A[2][1] ^ D[1], rhotates[2][1]); + C[3] = ROL64(A[3][2] ^ D[2], rhotates[3][2]); + C[4] = ROL64(A[4][3] ^ D[3], rhotates[4][3]); + +#ifdef KECCAK_COMPLEMENTING_TRANSFORM + R[3][0] = C[0] ^ ( C[1] & C[2]); + R[3][1] = C[1] ^ ( C[2] | C[3]); + R[3][2] = C[2] ^ (~C[3] | C[4]); + R[3][3] = ~C[3] ^ ( C[4] & C[0]); + R[3][4] = C[4] ^ ( C[0] | C[1]); +#else + R[3][0] = C[0] ^ (~C[1] & C[2]); + R[3][1] = C[1] ^ (~C[2] & C[3]); + R[3][2] = C[2] ^ (~C[3] & C[4]); + R[3][3] = C[3] ^ (~C[4] & C[0]); + R[3][4] = C[4] ^ (~C[0] & C[1]); +#endif + + C[0] = ROL64(A[0][2] ^ D[2], rhotates[0][2]); + C[1] = ROL64(A[1][3] ^ D[3], rhotates[1][3]); + C[2] = ROL64(A[2][4] ^ D[4], rhotates[2][4]); + C[3] = ROL64(A[3][0] ^ D[0], rhotates[3][0]); + C[4] = ROL64(A[4][1] ^ D[1], rhotates[4][1]); + +#ifdef KECCAK_COMPLEMENTING_TRANSFORM + R[4][0] = C[0] ^ (~C[1] & C[2]); + R[4][1] = ~C[1] ^ ( C[2] | C[3]); + R[4][2] = C[2] ^ ( C[3] & C[4]); + R[4][3] = C[3] ^ ( C[4] | C[0]); + R[4][4] = C[4] ^ ( C[0] & C[1]); +#else + R[4][0] = C[0] ^ (~C[1] & C[2]); + R[4][1] = C[1] ^ (~C[2] & C[3]); + R[4][2] = C[2] ^ (~C[3] & C[4]); + R[4][3] = C[3] ^ (~C[4] & C[0]); + R[4][4] = C[4] ^ (~C[0] & C[1]); +#endif +} + +static void KeccakF1600(uint64_t A[5][5]) +{ + uint64_t T[5][5]; + size_t i; + +#ifdef KECCAK_COMPLEMENTING_TRANSFORM + A[0][1] = ~A[0][1]; + A[0][2] = ~A[0][2]; + A[1][3] = ~A[1][3]; + A[2][2] = ~A[2][2]; + A[3][2] = ~A[3][2]; + A[4][0] = ~A[4][0]; +#endif + + for (i = 0; i < 24; i += 2) { + Round(T, A, i); + Round(A, T, i + 1); + } + +#ifdef KECCAK_COMPLEMENTING_TRANSFORM + A[0][1] = ~A[0][1]; + A[0][2] = ~A[0][2]; + A[1][3] = ~A[1][3]; + A[2][2] = ~A[2][2]; + A[3][2] = ~A[3][2]; + A[4][0] = ~A[4][0]; +#endif +} + +#else /* define KECCAK_INPLACE to compile this code path */ +/* + * This implementation is KECCAK_1X from above combined 4 times with + * a twist that allows to omit temporary storage and perform in-place + * processing. It's discussed in section 2.5 of "Keccak implementation + * overview". It's likely to be best suited for processors with large + * register bank... On the other hand processor with large register + * bank can as well use KECCAK_1X_ALT, it would be as fast but much + * more compact... + */ +static void FourRounds(uint64_t A[5][5], size_t i) +{ + uint64_t B[5], C[5], D[5]; + + assert(i <= (sizeof(iotas) / sizeof(iotas[0]) - 4)); + + /* Round 4*n */ + C[0] = A[0][0] ^ A[1][0] ^ A[2][0] ^ A[3][0] ^ A[4][0]; + C[1] = A[0][1] ^ A[1][1] ^ A[2][1] ^ A[3][1] ^ A[4][1]; + C[2] = A[0][2] ^ A[1][2] ^ A[2][2] ^ A[3][2] ^ A[4][2]; + C[3] = A[0][3] ^ A[1][3] ^ A[2][3] ^ A[3][3] ^ A[4][3]; + C[4] = A[0][4] ^ A[1][4] ^ A[2][4] ^ A[3][4] ^ A[4][4]; + + D[0] = ROL64(C[1], 1) ^ C[4]; + D[1] = ROL64(C[2], 1) ^ C[0]; + D[2] = ROL64(C[3], 1) ^ C[1]; + D[3] = ROL64(C[4], 1) ^ C[2]; + D[4] = ROL64(C[0], 1) ^ C[3]; + + B[0] = A[0][0] ^ D[0]; /* rotate by 0 */ + B[1] = ROL64(A[1][1] ^ D[1], rhotates[1][1]); + B[2] = ROL64(A[2][2] ^ D[2], rhotates[2][2]); + B[3] = ROL64(A[3][3] ^ D[3], rhotates[3][3]); + B[4] = ROL64(A[4][4] ^ D[4], rhotates[4][4]); + + C[0] = A[0][0] = B[0] ^ (~B[1] & B[2]) ^ iotas[i]; + C[1] = A[1][1] = B[1] ^ (~B[2] & B[3]); + C[2] = A[2][2] = B[2] ^ (~B[3] & B[4]); + C[3] = A[3][3] = B[3] ^ (~B[4] & B[0]); + C[4] = A[4][4] = B[4] ^ (~B[0] & B[1]); + + B[0] = ROL64(A[0][3] ^ D[3], rhotates[0][3]); + B[1] = ROL64(A[1][4] ^ D[4], rhotates[1][4]); + B[2] = ROL64(A[2][0] ^ D[0], rhotates[2][0]); + B[3] = ROL64(A[3][1] ^ D[1], rhotates[3][1]); + B[4] = ROL64(A[4][2] ^ D[2], rhotates[4][2]); + + C[0] ^= A[2][0] = B[0] ^ (~B[1] & B[2]); + C[1] ^= A[3][1] = B[1] ^ (~B[2] & B[3]); + C[2] ^= A[4][2] = B[2] ^ (~B[3] & B[4]); + C[3] ^= A[0][3] = B[3] ^ (~B[4] & B[0]); + C[4] ^= A[1][4] = B[4] ^ (~B[0] & B[1]); + + B[0] = ROL64(A[0][1] ^ D[1], rhotates[0][1]); + B[1] = ROL64(A[1][2] ^ D[2], rhotates[1][2]); + B[2] = ROL64(A[2][3] ^ D[3], rhotates[2][3]); + B[3] = ROL64(A[3][4] ^ D[4], rhotates[3][4]); + B[4] = ROL64(A[4][0] ^ D[0], rhotates[4][0]); + + C[0] ^= A[4][0] = B[0] ^ (~B[1] & B[2]); + C[1] ^= A[0][1] = B[1] ^ (~B[2] & B[3]); + C[2] ^= A[1][2] = B[2] ^ (~B[3] & B[4]); + C[3] ^= A[2][3] = B[3] ^ (~B[4] & B[0]); + C[4] ^= A[3][4] = B[4] ^ (~B[0] & B[1]); + + B[0] = ROL64(A[0][4] ^ D[4], rhotates[0][4]); + B[1] = ROL64(A[1][0] ^ D[0], rhotates[1][0]); + B[2] = ROL64(A[2][1] ^ D[1], rhotates[2][1]); + B[3] = ROL64(A[3][2] ^ D[2], rhotates[3][2]); + B[4] = ROL64(A[4][3] ^ D[3], rhotates[4][3]); + + C[0] ^= A[1][0] = B[0] ^ (~B[1] & B[2]); + C[1] ^= A[2][1] = B[1] ^ (~B[2] & B[3]); + C[2] ^= A[3][2] = B[2] ^ (~B[3] & B[4]); + C[3] ^= A[4][3] = B[3] ^ (~B[4] & B[0]); + C[4] ^= A[0][4] = B[4] ^ (~B[0] & B[1]); + + B[0] = ROL64(A[0][2] ^ D[2], rhotates[0][2]); + B[1] = ROL64(A[1][3] ^ D[3], rhotates[1][3]); + B[2] = ROL64(A[2][4] ^ D[4], rhotates[2][4]); + B[3] = ROL64(A[3][0] ^ D[0], rhotates[3][0]); + B[4] = ROL64(A[4][1] ^ D[1], rhotates[4][1]); + + C[0] ^= A[3][0] = B[0] ^ (~B[1] & B[2]); + C[1] ^= A[4][1] = B[1] ^ (~B[2] & B[3]); + C[2] ^= A[0][2] = B[2] ^ (~B[3] & B[4]); + C[3] ^= A[1][3] = B[3] ^ (~B[4] & B[0]); + C[4] ^= A[2][4] = B[4] ^ (~B[0] & B[1]); + + /* Round 4*n+1 */ + D[0] = ROL64(C[1], 1) ^ C[4]; + D[1] = ROL64(C[2], 1) ^ C[0]; + D[2] = ROL64(C[3], 1) ^ C[1]; + D[3] = ROL64(C[4], 1) ^ C[2]; + D[4] = ROL64(C[0], 1) ^ C[3]; + + B[0] = A[0][0] ^ D[0]; /* rotate by 0 */ + B[1] = ROL64(A[3][1] ^ D[1], rhotates[1][1]); + B[2] = ROL64(A[1][2] ^ D[2], rhotates[2][2]); + B[3] = ROL64(A[4][3] ^ D[3], rhotates[3][3]); + B[4] = ROL64(A[2][4] ^ D[4], rhotates[4][4]); + + C[0] = A[0][0] = B[0] ^ (~B[1] & B[2]) ^ iotas[i + 1]; + C[1] = A[3][1] = B[1] ^ (~B[2] & B[3]); + C[2] = A[1][2] = B[2] ^ (~B[3] & B[4]); + C[3] = A[4][3] = B[3] ^ (~B[4] & B[0]); + C[4] = A[2][4] = B[4] ^ (~B[0] & B[1]); + + B[0] = ROL64(A[3][3] ^ D[3], rhotates[0][3]); + B[1] = ROL64(A[1][4] ^ D[4], rhotates[1][4]); + B[2] = ROL64(A[4][0] ^ D[0], rhotates[2][0]); + B[3] = ROL64(A[2][1] ^ D[1], rhotates[3][1]); + B[4] = ROL64(A[0][2] ^ D[2], rhotates[4][2]); + + C[0] ^= A[4][0] = B[0] ^ (~B[1] & B[2]); + C[1] ^= A[2][1] = B[1] ^ (~B[2] & B[3]); + C[2] ^= A[0][2] = B[2] ^ (~B[3] & B[4]); + C[3] ^= A[3][3] = B[3] ^ (~B[4] & B[0]); + C[4] ^= A[1][4] = B[4] ^ (~B[0] & B[1]); + + B[0] = ROL64(A[1][1] ^ D[1], rhotates[0][1]); + B[1] = ROL64(A[4][2] ^ D[2], rhotates[1][2]); + B[2] = ROL64(A[2][3] ^ D[3], rhotates[2][3]); + B[3] = ROL64(A[0][4] ^ D[4], rhotates[3][4]); + B[4] = ROL64(A[3][0] ^ D[0], rhotates[4][0]); + + C[0] ^= A[3][0] = B[0] ^ (~B[1] & B[2]); + C[1] ^= A[1][1] = B[1] ^ (~B[2] & B[3]); + C[2] ^= A[4][2] = B[2] ^ (~B[3] & B[4]); + C[3] ^= A[2][3] = B[3] ^ (~B[4] & B[0]); + C[4] ^= A[0][4] = B[4] ^ (~B[0] & B[1]); + + B[0] = ROL64(A[4][4] ^ D[4], rhotates[0][4]); + B[1] = ROL64(A[2][0] ^ D[0], rhotates[1][0]); + B[2] = ROL64(A[0][1] ^ D[1], rhotates[2][1]); + B[3] = ROL64(A[3][2] ^ D[2], rhotates[3][2]); + B[4] = ROL64(A[1][3] ^ D[3], rhotates[4][3]); + + C[0] ^= A[2][0] = B[0] ^ (~B[1] & B[2]); + C[1] ^= A[0][1] = B[1] ^ (~B[2] & B[3]); + C[2] ^= A[3][2] = B[2] ^ (~B[3] & B[4]); + C[3] ^= A[1][3] = B[3] ^ (~B[4] & B[0]); + C[4] ^= A[4][4] = B[4] ^ (~B[0] & B[1]); + + B[0] = ROL64(A[2][2] ^ D[2], rhotates[0][2]); + B[1] = ROL64(A[0][3] ^ D[3], rhotates[1][3]); + B[2] = ROL64(A[3][4] ^ D[4], rhotates[2][4]); + B[3] = ROL64(A[1][0] ^ D[0], rhotates[3][0]); + B[4] = ROL64(A[4][1] ^ D[1], rhotates[4][1]); + + C[0] ^= A[1][0] = B[0] ^ (~B[1] & B[2]); + C[1] ^= A[4][1] = B[1] ^ (~B[2] & B[3]); + C[2] ^= A[2][2] = B[2] ^ (~B[3] & B[4]); + C[3] ^= A[0][3] = B[3] ^ (~B[4] & B[0]); + C[4] ^= A[3][4] = B[4] ^ (~B[0] & B[1]); + + /* Round 4*n+2 */ + D[0] = ROL64(C[1], 1) ^ C[4]; + D[1] = ROL64(C[2], 1) ^ C[0]; + D[2] = ROL64(C[3], 1) ^ C[1]; + D[3] = ROL64(C[4], 1) ^ C[2]; + D[4] = ROL64(C[0], 1) ^ C[3]; + + B[0] = A[0][0] ^ D[0]; /* rotate by 0 */ + B[1] = ROL64(A[2][1] ^ D[1], rhotates[1][1]); + B[2] = ROL64(A[4][2] ^ D[2], rhotates[2][2]); + B[3] = ROL64(A[1][3] ^ D[3], rhotates[3][3]); + B[4] = ROL64(A[3][4] ^ D[4], rhotates[4][4]); + + C[0] = A[0][0] = B[0] ^ (~B[1] & B[2]) ^ iotas[i + 2]; + C[1] = A[2][1] = B[1] ^ (~B[2] & B[3]); + C[2] = A[4][2] = B[2] ^ (~B[3] & B[4]); + C[3] = A[1][3] = B[3] ^ (~B[4] & B[0]); + C[4] = A[3][4] = B[4] ^ (~B[0] & B[1]); + + B[0] = ROL64(A[4][3] ^ D[3], rhotates[0][3]); + B[1] = ROL64(A[1][4] ^ D[4], rhotates[1][4]); + B[2] = ROL64(A[3][0] ^ D[0], rhotates[2][0]); + B[3] = ROL64(A[0][1] ^ D[1], rhotates[3][1]); + B[4] = ROL64(A[2][2] ^ D[2], rhotates[4][2]); + + C[0] ^= A[3][0] = B[0] ^ (~B[1] & B[2]); + C[1] ^= A[0][1] = B[1] ^ (~B[2] & B[3]); + C[2] ^= A[2][2] = B[2] ^ (~B[3] & B[4]); + C[3] ^= A[4][3] = B[3] ^ (~B[4] & B[0]); + C[4] ^= A[1][4] = B[4] ^ (~B[0] & B[1]); + + B[0] = ROL64(A[3][1] ^ D[1], rhotates[0][1]); + B[1] = ROL64(A[0][2] ^ D[2], rhotates[1][2]); + B[2] = ROL64(A[2][3] ^ D[3], rhotates[2][3]); + B[3] = ROL64(A[4][4] ^ D[4], rhotates[3][4]); + B[4] = ROL64(A[1][0] ^ D[0], rhotates[4][0]); + + C[0] ^= A[1][0] = B[0] ^ (~B[1] & B[2]); + C[1] ^= A[3][1] = B[1] ^ (~B[2] & B[3]); + C[2] ^= A[0][2] = B[2] ^ (~B[3] & B[4]); + C[3] ^= A[2][3] = B[3] ^ (~B[4] & B[0]); + C[4] ^= A[4][4] = B[4] ^ (~B[0] & B[1]); + + B[0] = ROL64(A[2][4] ^ D[4], rhotates[0][4]); + B[1] = ROL64(A[4][0] ^ D[0], rhotates[1][0]); + B[2] = ROL64(A[1][1] ^ D[1], rhotates[2][1]); + B[3] = ROL64(A[3][2] ^ D[2], rhotates[3][2]); + B[4] = ROL64(A[0][3] ^ D[3], rhotates[4][3]); + + C[0] ^= A[4][0] = B[0] ^ (~B[1] & B[2]); + C[1] ^= A[1][1] = B[1] ^ (~B[2] & B[3]); + C[2] ^= A[3][2] = B[2] ^ (~B[3] & B[4]); + C[3] ^= A[0][3] = B[3] ^ (~B[4] & B[0]); + C[4] ^= A[2][4] = B[4] ^ (~B[0] & B[1]); + + B[0] = ROL64(A[1][2] ^ D[2], rhotates[0][2]); + B[1] = ROL64(A[3][3] ^ D[3], rhotates[1][3]); + B[2] = ROL64(A[0][4] ^ D[4], rhotates[2][4]); + B[3] = ROL64(A[2][0] ^ D[0], rhotates[3][0]); + B[4] = ROL64(A[4][1] ^ D[1], rhotates[4][1]); + + C[0] ^= A[2][0] = B[0] ^ (~B[1] & B[2]); + C[1] ^= A[4][1] = B[1] ^ (~B[2] & B[3]); + C[2] ^= A[1][2] = B[2] ^ (~B[3] & B[4]); + C[3] ^= A[3][3] = B[3] ^ (~B[4] & B[0]); + C[4] ^= A[0][4] = B[4] ^ (~B[0] & B[1]); + + /* Round 4*n+3 */ + D[0] = ROL64(C[1], 1) ^ C[4]; + D[1] = ROL64(C[2], 1) ^ C[0]; + D[2] = ROL64(C[3], 1) ^ C[1]; + D[3] = ROL64(C[4], 1) ^ C[2]; + D[4] = ROL64(C[0], 1) ^ C[3]; + + B[0] = A[0][0] ^ D[0]; /* rotate by 0 */ + B[1] = ROL64(A[0][1] ^ D[1], rhotates[1][1]); + B[2] = ROL64(A[0][2] ^ D[2], rhotates[2][2]); + B[3] = ROL64(A[0][3] ^ D[3], rhotates[3][3]); + B[4] = ROL64(A[0][4] ^ D[4], rhotates[4][4]); + + /* C[0] = */ A[0][0] = B[0] ^ (~B[1] & B[2]) ^ iotas[i + 3]; + /* C[1] = */ A[0][1] = B[1] ^ (~B[2] & B[3]); + /* C[2] = */ A[0][2] = B[2] ^ (~B[3] & B[4]); + /* C[3] = */ A[0][3] = B[3] ^ (~B[4] & B[0]); + /* C[4] = */ A[0][4] = B[4] ^ (~B[0] & B[1]); + + B[0] = ROL64(A[1][3] ^ D[3], rhotates[0][3]); + B[1] = ROL64(A[1][4] ^ D[4], rhotates[1][4]); + B[2] = ROL64(A[1][0] ^ D[0], rhotates[2][0]); + B[3] = ROL64(A[1][1] ^ D[1], rhotates[3][1]); + B[4] = ROL64(A[1][2] ^ D[2], rhotates[4][2]); + + /* C[0] ^= */ A[1][0] = B[0] ^ (~B[1] & B[2]); + /* C[1] ^= */ A[1][1] = B[1] ^ (~B[2] & B[3]); + /* C[2] ^= */ A[1][2] = B[2] ^ (~B[3] & B[4]); + /* C[3] ^= */ A[1][3] = B[3] ^ (~B[4] & B[0]); + /* C[4] ^= */ A[1][4] = B[4] ^ (~B[0] & B[1]); + + B[0] = ROL64(A[2][1] ^ D[1], rhotates[0][1]); + B[1] = ROL64(A[2][2] ^ D[2], rhotates[1][2]); + B[2] = ROL64(A[2][3] ^ D[3], rhotates[2][3]); + B[3] = ROL64(A[2][4] ^ D[4], rhotates[3][4]); + B[4] = ROL64(A[2][0] ^ D[0], rhotates[4][0]); + + /* C[0] ^= */ A[2][0] = B[0] ^ (~B[1] & B[2]); + /* C[1] ^= */ A[2][1] = B[1] ^ (~B[2] & B[3]); + /* C[2] ^= */ A[2][2] = B[2] ^ (~B[3] & B[4]); + /* C[3] ^= */ A[2][3] = B[3] ^ (~B[4] & B[0]); + /* C[4] ^= */ A[2][4] = B[4] ^ (~B[0] & B[1]); + + B[0] = ROL64(A[3][4] ^ D[4], rhotates[0][4]); + B[1] = ROL64(A[3][0] ^ D[0], rhotates[1][0]); + B[2] = ROL64(A[3][1] ^ D[1], rhotates[2][1]); + B[3] = ROL64(A[3][2] ^ D[2], rhotates[3][2]); + B[4] = ROL64(A[3][3] ^ D[3], rhotates[4][3]); + + /* C[0] ^= */ A[3][0] = B[0] ^ (~B[1] & B[2]); + /* C[1] ^= */ A[3][1] = B[1] ^ (~B[2] & B[3]); + /* C[2] ^= */ A[3][2] = B[2] ^ (~B[3] & B[4]); + /* C[3] ^= */ A[3][3] = B[3] ^ (~B[4] & B[0]); + /* C[4] ^= */ A[3][4] = B[4] ^ (~B[0] & B[1]); + + B[0] = ROL64(A[4][2] ^ D[2], rhotates[0][2]); + B[1] = ROL64(A[4][3] ^ D[3], rhotates[1][3]); + B[2] = ROL64(A[4][4] ^ D[4], rhotates[2][4]); + B[3] = ROL64(A[4][0] ^ D[0], rhotates[3][0]); + B[4] = ROL64(A[4][1] ^ D[1], rhotates[4][1]); + + /* C[0] ^= */ A[4][0] = B[0] ^ (~B[1] & B[2]); + /* C[1] ^= */ A[4][1] = B[1] ^ (~B[2] & B[3]); + /* C[2] ^= */ A[4][2] = B[2] ^ (~B[3] & B[4]); + /* C[3] ^= */ A[4][3] = B[3] ^ (~B[4] & B[0]); + /* C[4] ^= */ A[4][4] = B[4] ^ (~B[0] & B[1]); +} + +static void KeccakF1600(uint64_t A[5][5]) +{ + size_t i; + + for (i = 0; i < 24; i += 4) { + FourRounds(A, i); + } +} + +#endif + +static uint64_t BitInterleave(uint64_t Ai) +{ + if (BIT_INTERLEAVE) { + uint32_t hi = (uint32_t)(Ai >> 32), lo = (uint32_t)Ai; + uint32_t t0, t1; + + t0 = lo & 0x55555555; + t0 |= t0 >> 1; t0 &= 0x33333333; + t0 |= t0 >> 2; t0 &= 0x0f0f0f0f; + t0 |= t0 >> 4; t0 &= 0x00ff00ff; + t0 |= t0 >> 8; t0 &= 0x0000ffff; + + t1 = hi & 0x55555555; + t1 |= t1 >> 1; t1 &= 0x33333333; + t1 |= t1 >> 2; t1 &= 0x0f0f0f0f; + t1 |= t1 >> 4; t1 &= 0x00ff00ff; + t1 |= t1 >> 8; t1 <<= 16; + + lo &= 0xaaaaaaaa; + lo |= lo << 1; lo &= 0xcccccccc; + lo |= lo << 2; lo &= 0xf0f0f0f0; + lo |= lo << 4; lo &= 0xff00ff00; + lo |= lo << 8; lo >>= 16; + + hi &= 0xaaaaaaaa; + hi |= hi << 1; hi &= 0xcccccccc; + hi |= hi << 2; hi &= 0xf0f0f0f0; + hi |= hi << 4; hi &= 0xff00ff00; + hi |= hi << 8; hi &= 0xffff0000; + + Ai = ((uint64_t)(hi | lo) << 32) | (t1 | t0); + } + + return Ai; +} + +static uint64_t BitDeinterleave(uint64_t Ai) +{ + if (BIT_INTERLEAVE) { + uint32_t hi = (uint32_t)(Ai >> 32), lo = (uint32_t)Ai; + uint32_t t0, t1; + + t0 = lo & 0x0000ffff; + t0 |= t0 << 8; t0 &= 0x00ff00ff; + t0 |= t0 << 4; t0 &= 0x0f0f0f0f; + t0 |= t0 << 2; t0 &= 0x33333333; + t0 |= t0 << 1; t0 &= 0x55555555; + + t1 = hi << 16; + t1 |= t1 >> 8; t1 &= 0xff00ff00; + t1 |= t1 >> 4; t1 &= 0xf0f0f0f0; + t1 |= t1 >> 2; t1 &= 0xcccccccc; + t1 |= t1 >> 1; t1 &= 0xaaaaaaaa; + + lo >>= 16; + lo |= lo << 8; lo &= 0x00ff00ff; + lo |= lo << 4; lo &= 0x0f0f0f0f; + lo |= lo << 2; lo &= 0x33333333; + lo |= lo << 1; lo &= 0x55555555; + + hi &= 0xffff0000; + hi |= hi >> 8; hi &= 0xff00ff00; + hi |= hi >> 4; hi &= 0xf0f0f0f0; + hi |= hi >> 2; hi &= 0xcccccccc; + hi |= hi >> 1; hi &= 0xaaaaaaaa; + + Ai = ((uint64_t)(hi | lo) << 32) | (t1 | t0); + } + + return Ai; +} + +/* + * SHA3_absorb can be called multiple times, but at each invocation + * largest multiple of |r| out of |len| bytes are processed. Then + * remaining amount of bytes is returned. This is done to spare caller + * trouble of calculating the largest multiple of |r|. |r| can be viewed + * as blocksize. It is commonly (1600 - 256*n)/8, e.g. 168, 136, 104, + * 72, but can also be (1600 - 448)/8 = 144. All this means that message + * padding and intermediate sub-block buffering, byte- or bitwise, is + * caller's responsibility. + */ +size_t SHA3_absorb(uint64_t A[5][5], const unsigned char *inp, size_t len, + size_t r) +{ + uint64_t *A_flat = (uint64_t *)A; + size_t i, w = r / 8; + + assert(r < (25 * sizeof(A[0][0])) && (r % 8) == 0); + + while (len >= r) { + for (i = 0; i < w; i++) { + uint64_t Ai = (uint64_t)inp[0] | (uint64_t)inp[1] << 8 | + (uint64_t)inp[2] << 16 | (uint64_t)inp[3] << 24 | + (uint64_t)inp[4] << 32 | (uint64_t)inp[5] << 40 | + (uint64_t)inp[6] << 48 | (uint64_t)inp[7] << 56; + inp += 8; + + A_flat[i] ^= BitInterleave(Ai); + } + KeccakF1600(A); + len -= r; + } + + return len; +} + +/* + * SHA3_squeeze is called once at the end to generate |out| hash value + * of |len| bytes. + */ +void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len, size_t r) +{ + uint64_t *A_flat = (uint64_t *)A; + size_t i, w = r / 8; + + assert(r < (25 * sizeof(A[0][0])) && (r % 8) == 0); + + while (len != 0) { + for (i = 0; i < w && len != 0; i++) { + uint64_t Ai = BitDeinterleave(A_flat[i]); + + if (len < 8) { + for (i = 0; i < len; i++) { + *out++ = (unsigned char)Ai; + Ai >>= 8; + } + return; + } + + out[0] = (unsigned char)(Ai); + out[1] = (unsigned char)(Ai >> 8); + out[2] = (unsigned char)(Ai >> 16); + out[3] = (unsigned char)(Ai >> 24); + out[4] = (unsigned char)(Ai >> 32); + out[5] = (unsigned char)(Ai >> 40); + out[6] = (unsigned char)(Ai >> 48); + out[7] = (unsigned char)(Ai >> 56); + out += 8; + len -= 8; + } + if (len) + KeccakF1600(A); + } +} +#endif + +#ifdef SELFTEST +/* + * Post-padding one-shot implementations would look as following: + * + * SHA3_224 SHA3_sponge(inp, len, out, 224/8, (1600-448)/8); + * SHA3_256 SHA3_sponge(inp, len, out, 256/8, (1600-512)/8); + * SHA3_384 SHA3_sponge(inp, len, out, 384/8, (1600-768)/8); + * SHA3_512 SHA3_sponge(inp, len, out, 512/8, (1600-1024)/8); + * SHAKE_128 SHA3_sponge(inp, len, out, d, (1600-256)/8); + * SHAKE_256 SHA3_sponge(inp, len, out, d, (1600-512)/8); + */ + +void SHA3_sponge(const unsigned char *inp, size_t len, + unsigned char *out, size_t d, size_t r) +{ + uint64_t A[5][5]; + + memset(A, 0, sizeof(A)); + SHA3_absorb(A, inp, len, r); + SHA3_squeeze(A, out, d, r); +} + +# include + +int main() +{ + /* + * This is 5-bit SHAKE128 test from http://csrc.nist.gov/groups/ST/toolkit/examples.html#aHashing + */ + unsigned char test[168] = { '\xf3', '\x3' }; + unsigned char out[512]; + size_t i; + static const unsigned char result[512] = { + 0x2E, 0x0A, 0xBF, 0xBA, 0x83, 0xE6, 0x72, 0x0B, + 0xFB, 0xC2, 0x25, 0xFF, 0x6B, 0x7A, 0xB9, 0xFF, + 0xCE, 0x58, 0xBA, 0x02, 0x7E, 0xE3, 0xD8, 0x98, + 0x76, 0x4F, 0xEF, 0x28, 0x7D, 0xDE, 0xCC, 0xCA, + 0x3E, 0x6E, 0x59, 0x98, 0x41, 0x1E, 0x7D, 0xDB, + 0x32, 0xF6, 0x75, 0x38, 0xF5, 0x00, 0xB1, 0x8C, + 0x8C, 0x97, 0xC4, 0x52, 0xC3, 0x70, 0xEA, 0x2C, + 0xF0, 0xAF, 0xCA, 0x3E, 0x05, 0xDE, 0x7E, 0x4D, + 0xE2, 0x7F, 0xA4, 0x41, 0xA9, 0xCB, 0x34, 0xFD, + 0x17, 0xC9, 0x78, 0xB4, 0x2D, 0x5B, 0x7E, 0x7F, + 0x9A, 0xB1, 0x8F, 0xFE, 0xFF, 0xC3, 0xC5, 0xAC, + 0x2F, 0x3A, 0x45, 0x5E, 0xEB, 0xFD, 0xC7, 0x6C, + 0xEA, 0xEB, 0x0A, 0x2C, 0xCA, 0x22, 0xEE, 0xF6, + 0xE6, 0x37, 0xF4, 0xCA, 0xBE, 0x5C, 0x51, 0xDE, + 0xD2, 0xE3, 0xFA, 0xD8, 0xB9, 0x52, 0x70, 0xA3, + 0x21, 0x84, 0x56, 0x64, 0xF1, 0x07, 0xD1, 0x64, + 0x96, 0xBB, 0x7A, 0xBF, 0xBE, 0x75, 0x04, 0xB6, + 0xED, 0xE2, 0xE8, 0x9E, 0x4B, 0x99, 0x6F, 0xB5, + 0x8E, 0xFD, 0xC4, 0x18, 0x1F, 0x91, 0x63, 0x38, + 0x1C, 0xBE, 0x7B, 0xC0, 0x06, 0xA7, 0xA2, 0x05, + 0x98, 0x9C, 0x52, 0x6C, 0xD1, 0xBD, 0x68, 0x98, + 0x36, 0x93, 0xB4, 0xBD, 0xC5, 0x37, 0x28, 0xB2, + 0x41, 0xC1, 0xCF, 0xF4, 0x2B, 0xB6, 0x11, 0x50, + 0x2C, 0x35, 0x20, 0x5C, 0xAB, 0xB2, 0x88, 0x75, + 0x56, 0x55, 0xD6, 0x20, 0xC6, 0x79, 0x94, 0xF0, + 0x64, 0x51, 0x18, 0x7F, 0x6F, 0xD1, 0x7E, 0x04, + 0x66, 0x82, 0xBA, 0x12, 0x86, 0x06, 0x3F, 0xF8, + 0x8F, 0xE2, 0x50, 0x8D, 0x1F, 0xCA, 0xF9, 0x03, + 0x5A, 0x12, 0x31, 0xAD, 0x41, 0x50, 0xA9, 0xC9, + 0xB2, 0x4C, 0x9B, 0x2D, 0x66, 0xB2, 0xAD, 0x1B, + 0xDE, 0x0B, 0xD0, 0xBB, 0xCB, 0x8B, 0xE0, 0x5B, + 0x83, 0x52, 0x29, 0xEF, 0x79, 0x19, 0x73, 0x73, + 0x23, 0x42, 0x44, 0x01, 0xE1, 0xD8, 0x37, 0xB6, + 0x6E, 0xB4, 0xE6, 0x30, 0xFF, 0x1D, 0xE7, 0x0C, + 0xB3, 0x17, 0xC2, 0xBA, 0xCB, 0x08, 0x00, 0x1D, + 0x34, 0x77, 0xB7, 0xA7, 0x0A, 0x57, 0x6D, 0x20, + 0x86, 0x90, 0x33, 0x58, 0x9D, 0x85, 0xA0, 0x1D, + 0xDB, 0x2B, 0x66, 0x46, 0xC0, 0x43, 0xB5, 0x9F, + 0xC0, 0x11, 0x31, 0x1D, 0xA6, 0x66, 0xFA, 0x5A, + 0xD1, 0xD6, 0x38, 0x7F, 0xA9, 0xBC, 0x40, 0x15, + 0xA3, 0x8A, 0x51, 0xD1, 0xDA, 0x1E, 0xA6, 0x1D, + 0x64, 0x8D, 0xC8, 0xE3, 0x9A, 0x88, 0xB9, 0xD6, + 0x22, 0xBD, 0xE2, 0x07, 0xFD, 0xAB, 0xC6, 0xF2, + 0x82, 0x7A, 0x88, 0x0C, 0x33, 0x0B, 0xBF, 0x6D, + 0xF7, 0x33, 0x77, 0x4B, 0x65, 0x3E, 0x57, 0x30, + 0x5D, 0x78, 0xDC, 0xE1, 0x12, 0xF1, 0x0A, 0x2C, + 0x71, 0xF4, 0xCD, 0xAD, 0x92, 0xED, 0x11, 0x3E, + 0x1C, 0xEA, 0x63, 0xB9, 0x19, 0x25, 0xED, 0x28, + 0x19, 0x1E, 0x6D, 0xBB, 0xB5, 0xAA, 0x5A, 0x2A, + 0xFD, 0xA5, 0x1F, 0xC0, 0x5A, 0x3A, 0xF5, 0x25, + 0x8B, 0x87, 0x66, 0x52, 0x43, 0x55, 0x0F, 0x28, + 0x94, 0x8A, 0xE2, 0xB8, 0xBE, 0xB6, 0xBC, 0x9C, + 0x77, 0x0B, 0x35, 0xF0, 0x67, 0xEA, 0xA6, 0x41, + 0xEF, 0xE6, 0x5B, 0x1A, 0x44, 0x90, 0x9D, 0x1B, + 0x14, 0x9F, 0x97, 0xEE, 0xA6, 0x01, 0x39, 0x1C, + 0x60, 0x9E, 0xC8, 0x1D, 0x19, 0x30, 0xF5, 0x7C, + 0x18, 0xA4, 0xE0, 0xFA, 0xB4, 0x91, 0xD1, 0xCA, + 0xDF, 0xD5, 0x04, 0x83, 0x44, 0x9E, 0xDC, 0x0F, + 0x07, 0xFF, 0xB2, 0x4D, 0x2C, 0x6F, 0x9A, 0x9A, + 0x3B, 0xFF, 0x39, 0xAE, 0x3D, 0x57, 0xF5, 0x60, + 0x65, 0x4D, 0x7D, 0x75, 0xC9, 0x08, 0xAB, 0xE6, + 0x25, 0x64, 0x75, 0x3E, 0xAC, 0x39, 0xD7, 0x50, + 0x3D, 0xA6, 0xD3, 0x7C, 0x2E, 0x32, 0xE1, 0xAF, + 0x3B, 0x8A, 0xEC, 0x8A, 0xE3, 0x06, 0x9C, 0xD9 + }; + + test[167] = '\x80'; + SHA3_sponge(test, sizeof(test), out, sizeof(out), sizeof(test)); + + /* + * Rationale behind keeping output [formatted as below] is that + * one should be able to redirect it to a file, then copy-n-paste + * final "output val" from official example to another file, and + * compare the two with diff(1). + */ + for (i = 0; i < sizeof(out);) { + printf("%02X", out[i]); + printf(++i % 16 && i != sizeof(out) ? " " : "\n"); + } + + if (memcmp(out,result,sizeof(out))) { + fprintf(stderr,"failure\n"); + return 1; + } else { + fprintf(stderr,"success\n"); + return 0; + } +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/sha1_one.c b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/sha1_one.c new file mode 100644 index 000000000..e5b38211d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/sha1_one.c @@ -0,0 +1,28 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include + +unsigned char *SHA1(const unsigned char *d, size_t n, unsigned char *md) +{ + SHA_CTX c; + static unsigned char m[SHA_DIGEST_LENGTH]; + + if (md == NULL) + md = m; + if (!SHA1_Init(&c)) + return NULL; + SHA1_Update(&c, d, n); + SHA1_Final(md, &c); + OPENSSL_cleanse(&c, sizeof(c)); + return md; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/sha1dgst.c b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/sha1dgst.c new file mode 100644 index 000000000..819370e61 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/sha1dgst.c @@ -0,0 +1,17 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +# include + +/* The implementation is in ../md32_common.h */ + +# include "sha_locl.h" diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/sha256.c b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/sha256.c new file mode 100644 index 000000000..bf78f075e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/sha256.c @@ -0,0 +1,386 @@ +/* + * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#include +#include + +#include +#include +#include + +int SHA224_Init(SHA256_CTX *c) +{ + memset(c, 0, sizeof(*c)); + c->h[0] = 0xc1059ed8UL; + c->h[1] = 0x367cd507UL; + c->h[2] = 0x3070dd17UL; + c->h[3] = 0xf70e5939UL; + c->h[4] = 0xffc00b31UL; + c->h[5] = 0x68581511UL; + c->h[6] = 0x64f98fa7UL; + c->h[7] = 0xbefa4fa4UL; + c->md_len = SHA224_DIGEST_LENGTH; + return 1; +} + +int SHA256_Init(SHA256_CTX *c) +{ + memset(c, 0, sizeof(*c)); + c->h[0] = 0x6a09e667UL; + c->h[1] = 0xbb67ae85UL; + c->h[2] = 0x3c6ef372UL; + c->h[3] = 0xa54ff53aUL; + c->h[4] = 0x510e527fUL; + c->h[5] = 0x9b05688cUL; + c->h[6] = 0x1f83d9abUL; + c->h[7] = 0x5be0cd19UL; + c->md_len = SHA256_DIGEST_LENGTH; + return 1; +} + +unsigned char *SHA224(const unsigned char *d, size_t n, unsigned char *md) +{ + SHA256_CTX c; + static unsigned char m[SHA224_DIGEST_LENGTH]; + + if (md == NULL) + md = m; + SHA224_Init(&c); + SHA256_Update(&c, d, n); + SHA256_Final(md, &c); + OPENSSL_cleanse(&c, sizeof(c)); + return md; +} + +unsigned char *SHA256(const unsigned char *d, size_t n, unsigned char *md) +{ + SHA256_CTX c; + static unsigned char m[SHA256_DIGEST_LENGTH]; + + if (md == NULL) + md = m; + SHA256_Init(&c); + SHA256_Update(&c, d, n); + SHA256_Final(md, &c); + OPENSSL_cleanse(&c, sizeof(c)); + return md; +} + +int SHA224_Update(SHA256_CTX *c, const void *data, size_t len) +{ + return SHA256_Update(c, data, len); +} + +int SHA224_Final(unsigned char *md, SHA256_CTX *c) +{ + return SHA256_Final(md, c); +} + +#define DATA_ORDER_IS_BIG_ENDIAN + +#define HASH_LONG SHA_LONG +#define HASH_CTX SHA256_CTX +#define HASH_CBLOCK SHA_CBLOCK + +/* + * Note that FIPS180-2 discusses "Truncation of the Hash Function Output." + * default: case below covers for it. It's not clear however if it's + * permitted to truncate to amount of bytes not divisible by 4. I bet not, + * but if it is, then default: case shall be extended. For reference. + * Idea behind separate cases for pre-defined lengths is to let the + * compiler decide if it's appropriate to unroll small loops. + */ +#define HASH_MAKE_STRING(c,s) do { \ + unsigned long ll; \ + unsigned int nn; \ + switch ((c)->md_len) \ + { case SHA224_DIGEST_LENGTH: \ + for (nn=0;nnh[nn]; (void)HOST_l2c(ll,(s)); } \ + break; \ + case SHA256_DIGEST_LENGTH: \ + for (nn=0;nnh[nn]; (void)HOST_l2c(ll,(s)); } \ + break; \ + default: \ + if ((c)->md_len > SHA256_DIGEST_LENGTH) \ + return 0; \ + for (nn=0;nn<(c)->md_len/4;nn++) \ + { ll=(c)->h[nn]; (void)HOST_l2c(ll,(s)); } \ + break; \ + } \ + } while (0) + +#define HASH_UPDATE SHA256_Update +#define HASH_TRANSFORM SHA256_Transform +#define HASH_FINAL SHA256_Final +#define HASH_BLOCK_DATA_ORDER sha256_block_data_order +#ifndef SHA256_ASM +static +#endif +void sha256_block_data_order(SHA256_CTX *ctx, const void *in, size_t num); + +#include "internal/md32_common.h" + +#ifndef SHA256_ASM +static const SHA_LONG K256[64] = { + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, + 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, + 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, + 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, + 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, + 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, + 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, + 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, + 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, + 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, + 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, + 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, + 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL +}; + +/* + * FIPS specification refers to right rotations, while our ROTATE macro + * is left one. This is why you might notice that rotation coefficients + * differ from those observed in FIPS document by 32-N... + */ +# define Sigma0(x) (ROTATE((x),30) ^ ROTATE((x),19) ^ ROTATE((x),10)) +# define Sigma1(x) (ROTATE((x),26) ^ ROTATE((x),21) ^ ROTATE((x),7)) +# define sigma0(x) (ROTATE((x),25) ^ ROTATE((x),14) ^ ((x)>>3)) +# define sigma1(x) (ROTATE((x),15) ^ ROTATE((x),13) ^ ((x)>>10)) + +# define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) +# define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +# ifdef OPENSSL_SMALL_FOOTPRINT + +static void sha256_block_data_order(SHA256_CTX *ctx, const void *in, + size_t num) +{ + unsigned MD32_REG_T a, b, c, d, e, f, g, h, s0, s1, T1, T2; + SHA_LONG X[16], l; + int i; + const unsigned char *data = in; + + while (num--) { + + a = ctx->h[0]; + b = ctx->h[1]; + c = ctx->h[2]; + d = ctx->h[3]; + e = ctx->h[4]; + f = ctx->h[5]; + g = ctx->h[6]; + h = ctx->h[7]; + + for (i = 0; i < 16; i++) { + (void)HOST_c2l(data, l); + T1 = X[i] = l; + T1 += h + Sigma1(e) + Ch(e, f, g) + K256[i]; + T2 = Sigma0(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + } + + for (; i < 64; i++) { + s0 = X[(i + 1) & 0x0f]; + s0 = sigma0(s0); + s1 = X[(i + 14) & 0x0f]; + s1 = sigma1(s1); + + T1 = X[i & 0xf] += s0 + s1 + X[(i + 9) & 0xf]; + T1 += h + Sigma1(e) + Ch(e, f, g) + K256[i]; + T2 = Sigma0(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + } + + ctx->h[0] += a; + ctx->h[1] += b; + ctx->h[2] += c; + ctx->h[3] += d; + ctx->h[4] += e; + ctx->h[5] += f; + ctx->h[6] += g; + ctx->h[7] += h; + + } +} + +# else + +# define ROUND_00_15(i,a,b,c,d,e,f,g,h) do { \ + T1 += h + Sigma1(e) + Ch(e,f,g) + K256[i]; \ + h = Sigma0(a) + Maj(a,b,c); \ + d += T1; h += T1; } while (0) + +# define ROUND_16_63(i,a,b,c,d,e,f,g,h,X) do { \ + s0 = X[(i+1)&0x0f]; s0 = sigma0(s0); \ + s1 = X[(i+14)&0x0f]; s1 = sigma1(s1); \ + T1 = X[(i)&0x0f] += s0 + s1 + X[(i+9)&0x0f]; \ + ROUND_00_15(i,a,b,c,d,e,f,g,h); } while (0) + +static void sha256_block_data_order(SHA256_CTX *ctx, const void *in, + size_t num) +{ + unsigned MD32_REG_T a, b, c, d, e, f, g, h, s0, s1, T1; + SHA_LONG X[16]; + int i; + const unsigned char *data = in; + const union { + long one; + char little; + } is_endian = { + 1 + }; + + while (num--) { + + a = ctx->h[0]; + b = ctx->h[1]; + c = ctx->h[2]; + d = ctx->h[3]; + e = ctx->h[4]; + f = ctx->h[5]; + g = ctx->h[6]; + h = ctx->h[7]; + + if (!is_endian.little && sizeof(SHA_LONG) == 4 + && ((size_t)in % 4) == 0) { + const SHA_LONG *W = (const SHA_LONG *)data; + + T1 = X[0] = W[0]; + ROUND_00_15(0, a, b, c, d, e, f, g, h); + T1 = X[1] = W[1]; + ROUND_00_15(1, h, a, b, c, d, e, f, g); + T1 = X[2] = W[2]; + ROUND_00_15(2, g, h, a, b, c, d, e, f); + T1 = X[3] = W[3]; + ROUND_00_15(3, f, g, h, a, b, c, d, e); + T1 = X[4] = W[4]; + ROUND_00_15(4, e, f, g, h, a, b, c, d); + T1 = X[5] = W[5]; + ROUND_00_15(5, d, e, f, g, h, a, b, c); + T1 = X[6] = W[6]; + ROUND_00_15(6, c, d, e, f, g, h, a, b); + T1 = X[7] = W[7]; + ROUND_00_15(7, b, c, d, e, f, g, h, a); + T1 = X[8] = W[8]; + ROUND_00_15(8, a, b, c, d, e, f, g, h); + T1 = X[9] = W[9]; + ROUND_00_15(9, h, a, b, c, d, e, f, g); + T1 = X[10] = W[10]; + ROUND_00_15(10, g, h, a, b, c, d, e, f); + T1 = X[11] = W[11]; + ROUND_00_15(11, f, g, h, a, b, c, d, e); + T1 = X[12] = W[12]; + ROUND_00_15(12, e, f, g, h, a, b, c, d); + T1 = X[13] = W[13]; + ROUND_00_15(13, d, e, f, g, h, a, b, c); + T1 = X[14] = W[14]; + ROUND_00_15(14, c, d, e, f, g, h, a, b); + T1 = X[15] = W[15]; + ROUND_00_15(15, b, c, d, e, f, g, h, a); + + data += SHA256_CBLOCK; + } else { + SHA_LONG l; + + (void)HOST_c2l(data, l); + T1 = X[0] = l; + ROUND_00_15(0, a, b, c, d, e, f, g, h); + (void)HOST_c2l(data, l); + T1 = X[1] = l; + ROUND_00_15(1, h, a, b, c, d, e, f, g); + (void)HOST_c2l(data, l); + T1 = X[2] = l; + ROUND_00_15(2, g, h, a, b, c, d, e, f); + (void)HOST_c2l(data, l); + T1 = X[3] = l; + ROUND_00_15(3, f, g, h, a, b, c, d, e); + (void)HOST_c2l(data, l); + T1 = X[4] = l; + ROUND_00_15(4, e, f, g, h, a, b, c, d); + (void)HOST_c2l(data, l); + T1 = X[5] = l; + ROUND_00_15(5, d, e, f, g, h, a, b, c); + (void)HOST_c2l(data, l); + T1 = X[6] = l; + ROUND_00_15(6, c, d, e, f, g, h, a, b); + (void)HOST_c2l(data, l); + T1 = X[7] = l; + ROUND_00_15(7, b, c, d, e, f, g, h, a); + (void)HOST_c2l(data, l); + T1 = X[8] = l; + ROUND_00_15(8, a, b, c, d, e, f, g, h); + (void)HOST_c2l(data, l); + T1 = X[9] = l; + ROUND_00_15(9, h, a, b, c, d, e, f, g); + (void)HOST_c2l(data, l); + T1 = X[10] = l; + ROUND_00_15(10, g, h, a, b, c, d, e, f); + (void)HOST_c2l(data, l); + T1 = X[11] = l; + ROUND_00_15(11, f, g, h, a, b, c, d, e); + (void)HOST_c2l(data, l); + T1 = X[12] = l; + ROUND_00_15(12, e, f, g, h, a, b, c, d); + (void)HOST_c2l(data, l); + T1 = X[13] = l; + ROUND_00_15(13, d, e, f, g, h, a, b, c); + (void)HOST_c2l(data, l); + T1 = X[14] = l; + ROUND_00_15(14, c, d, e, f, g, h, a, b); + (void)HOST_c2l(data, l); + T1 = X[15] = l; + ROUND_00_15(15, b, c, d, e, f, g, h, a); + } + + for (i = 16; i < 64; i += 8) { + ROUND_16_63(i + 0, a, b, c, d, e, f, g, h, X); + ROUND_16_63(i + 1, h, a, b, c, d, e, f, g, X); + ROUND_16_63(i + 2, g, h, a, b, c, d, e, f, X); + ROUND_16_63(i + 3, f, g, h, a, b, c, d, e, X); + ROUND_16_63(i + 4, e, f, g, h, a, b, c, d, X); + ROUND_16_63(i + 5, d, e, f, g, h, a, b, c, X); + ROUND_16_63(i + 6, c, d, e, f, g, h, a, b, X); + ROUND_16_63(i + 7, b, c, d, e, f, g, h, a, X); + } + + ctx->h[0] += a; + ctx->h[1] += b; + ctx->h[2] += c; + ctx->h[3] += d; + ctx->h[4] += e; + ctx->h[5] += f; + ctx->h[6] += g; + ctx->h[7] += h; + + } +} + +# endif +#endif /* SHA256_ASM */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/sha512.c b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/sha512.c new file mode 100644 index 000000000..50b65ee81 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/sha512.c @@ -0,0 +1,765 @@ +/* + * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +/*- + * IMPLEMENTATION NOTES. + * + * As you might have noticed 32-bit hash algorithms: + * + * - permit SHA_LONG to be wider than 32-bit + * - optimized versions implement two transform functions: one operating + * on [aligned] data in host byte order and one - on data in input + * stream byte order; + * - share common byte-order neutral collector and padding function + * implementations, ../md32_common.h; + * + * Neither of the above applies to this SHA-512 implementations. Reasons + * [in reverse order] are: + * + * - it's the only 64-bit hash algorithm for the moment of this writing, + * there is no need for common collector/padding implementation [yet]; + * - by supporting only one transform function [which operates on + * *aligned* data in input stream byte order, big-endian in this case] + * we minimize burden of maintenance in two ways: a) collector/padding + * function is simpler; b) only one transform function to stare at; + * - SHA_LONG64 is required to be exactly 64-bit in order to be able to + * apply a number of optimizations to mitigate potential performance + * penalties caused by previous design decision; + * + * Caveat lector. + * + * Implementation relies on the fact that "long long" is 64-bit on + * both 32- and 64-bit platforms. If some compiler vendor comes up + * with 128-bit long long, adjustment to sha.h would be required. + * As this implementation relies on 64-bit integer type, it's totally + * inappropriate for platforms which don't support it, most notably + * 16-bit platforms. + */ +#include +#include + +#include +#include +#include + +#include "internal/cryptlib.h" +#include "internal/sha.h" + +#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ + defined(__x86_64) || defined(_M_AMD64) || defined(_M_X64) || \ + defined(__s390__) || defined(__s390x__) || \ + defined(__aarch64__) || \ + defined(SHA512_ASM) +# define SHA512_BLOCK_CAN_MANAGE_UNALIGNED_DATA +#endif + +int sha512_224_init(SHA512_CTX *c) +{ + c->h[0] = U64(0x8c3d37c819544da2); + c->h[1] = U64(0x73e1996689dcd4d6); + c->h[2] = U64(0x1dfab7ae32ff9c82); + c->h[3] = U64(0x679dd514582f9fcf); + c->h[4] = U64(0x0f6d2b697bd44da8); + c->h[5] = U64(0x77e36f7304c48942); + c->h[6] = U64(0x3f9d85a86a1d36c8); + c->h[7] = U64(0x1112e6ad91d692a1); + + c->Nl = 0; + c->Nh = 0; + c->num = 0; + c->md_len = SHA224_DIGEST_LENGTH; + return 1; +} + +int sha512_256_init(SHA512_CTX *c) +{ + c->h[0] = U64(0x22312194fc2bf72c); + c->h[1] = U64(0x9f555fa3c84c64c2); + c->h[2] = U64(0x2393b86b6f53b151); + c->h[3] = U64(0x963877195940eabd); + c->h[4] = U64(0x96283ee2a88effe3); + c->h[5] = U64(0xbe5e1e2553863992); + c->h[6] = U64(0x2b0199fc2c85b8aa); + c->h[7] = U64(0x0eb72ddc81c52ca2); + + c->Nl = 0; + c->Nh = 0; + c->num = 0; + c->md_len = SHA256_DIGEST_LENGTH; + return 1; +} + +int SHA384_Init(SHA512_CTX *c) +{ + c->h[0] = U64(0xcbbb9d5dc1059ed8); + c->h[1] = U64(0x629a292a367cd507); + c->h[2] = U64(0x9159015a3070dd17); + c->h[3] = U64(0x152fecd8f70e5939); + c->h[4] = U64(0x67332667ffc00b31); + c->h[5] = U64(0x8eb44a8768581511); + c->h[6] = U64(0xdb0c2e0d64f98fa7); + c->h[7] = U64(0x47b5481dbefa4fa4); + + c->Nl = 0; + c->Nh = 0; + c->num = 0; + c->md_len = SHA384_DIGEST_LENGTH; + return 1; +} + +int SHA512_Init(SHA512_CTX *c) +{ + c->h[0] = U64(0x6a09e667f3bcc908); + c->h[1] = U64(0xbb67ae8584caa73b); + c->h[2] = U64(0x3c6ef372fe94f82b); + c->h[3] = U64(0xa54ff53a5f1d36f1); + c->h[4] = U64(0x510e527fade682d1); + c->h[5] = U64(0x9b05688c2b3e6c1f); + c->h[6] = U64(0x1f83d9abfb41bd6b); + c->h[7] = U64(0x5be0cd19137e2179); + + c->Nl = 0; + c->Nh = 0; + c->num = 0; + c->md_len = SHA512_DIGEST_LENGTH; + return 1; +} + +#ifndef SHA512_ASM +static +#endif +void sha512_block_data_order(SHA512_CTX *ctx, const void *in, size_t num); + +int SHA512_Final(unsigned char *md, SHA512_CTX *c) +{ + unsigned char *p = (unsigned char *)c->u.p; + size_t n = c->num; + + p[n] = 0x80; /* There always is a room for one */ + n++; + if (n > (sizeof(c->u) - 16)) { + memset(p + n, 0, sizeof(c->u) - n); + n = 0; + sha512_block_data_order(c, p, 1); + } + + memset(p + n, 0, sizeof(c->u) - 16 - n); +#ifdef B_ENDIAN + c->u.d[SHA_LBLOCK - 2] = c->Nh; + c->u.d[SHA_LBLOCK - 1] = c->Nl; +#else + p[sizeof(c->u) - 1] = (unsigned char)(c->Nl); + p[sizeof(c->u) - 2] = (unsigned char)(c->Nl >> 8); + p[sizeof(c->u) - 3] = (unsigned char)(c->Nl >> 16); + p[sizeof(c->u) - 4] = (unsigned char)(c->Nl >> 24); + p[sizeof(c->u) - 5] = (unsigned char)(c->Nl >> 32); + p[sizeof(c->u) - 6] = (unsigned char)(c->Nl >> 40); + p[sizeof(c->u) - 7] = (unsigned char)(c->Nl >> 48); + p[sizeof(c->u) - 8] = (unsigned char)(c->Nl >> 56); + p[sizeof(c->u) - 9] = (unsigned char)(c->Nh); + p[sizeof(c->u) - 10] = (unsigned char)(c->Nh >> 8); + p[sizeof(c->u) - 11] = (unsigned char)(c->Nh >> 16); + p[sizeof(c->u) - 12] = (unsigned char)(c->Nh >> 24); + p[sizeof(c->u) - 13] = (unsigned char)(c->Nh >> 32); + p[sizeof(c->u) - 14] = (unsigned char)(c->Nh >> 40); + p[sizeof(c->u) - 15] = (unsigned char)(c->Nh >> 48); + p[sizeof(c->u) - 16] = (unsigned char)(c->Nh >> 56); +#endif + + sha512_block_data_order(c, p, 1); + + if (md == 0) + return 0; + + switch (c->md_len) { + /* Let compiler decide if it's appropriate to unroll... */ + case SHA224_DIGEST_LENGTH: + for (n = 0; n < SHA224_DIGEST_LENGTH / 8; n++) { + SHA_LONG64 t = c->h[n]; + + *(md++) = (unsigned char)(t >> 56); + *(md++) = (unsigned char)(t >> 48); + *(md++) = (unsigned char)(t >> 40); + *(md++) = (unsigned char)(t >> 32); + *(md++) = (unsigned char)(t >> 24); + *(md++) = (unsigned char)(t >> 16); + *(md++) = (unsigned char)(t >> 8); + *(md++) = (unsigned char)(t); + } + /* + * For 224 bits, there are four bytes left over that have to be + * processed separately. + */ + { + SHA_LONG64 t = c->h[SHA224_DIGEST_LENGTH / 8]; + + *(md++) = (unsigned char)(t >> 56); + *(md++) = (unsigned char)(t >> 48); + *(md++) = (unsigned char)(t >> 40); + *(md++) = (unsigned char)(t >> 32); + } + break; + case SHA256_DIGEST_LENGTH: + for (n = 0; n < SHA256_DIGEST_LENGTH / 8; n++) { + SHA_LONG64 t = c->h[n]; + + *(md++) = (unsigned char)(t >> 56); + *(md++) = (unsigned char)(t >> 48); + *(md++) = (unsigned char)(t >> 40); + *(md++) = (unsigned char)(t >> 32); + *(md++) = (unsigned char)(t >> 24); + *(md++) = (unsigned char)(t >> 16); + *(md++) = (unsigned char)(t >> 8); + *(md++) = (unsigned char)(t); + } + break; + case SHA384_DIGEST_LENGTH: + for (n = 0; n < SHA384_DIGEST_LENGTH / 8; n++) { + SHA_LONG64 t = c->h[n]; + + *(md++) = (unsigned char)(t >> 56); + *(md++) = (unsigned char)(t >> 48); + *(md++) = (unsigned char)(t >> 40); + *(md++) = (unsigned char)(t >> 32); + *(md++) = (unsigned char)(t >> 24); + *(md++) = (unsigned char)(t >> 16); + *(md++) = (unsigned char)(t >> 8); + *(md++) = (unsigned char)(t); + } + break; + case SHA512_DIGEST_LENGTH: + for (n = 0; n < SHA512_DIGEST_LENGTH / 8; n++) { + SHA_LONG64 t = c->h[n]; + + *(md++) = (unsigned char)(t >> 56); + *(md++) = (unsigned char)(t >> 48); + *(md++) = (unsigned char)(t >> 40); + *(md++) = (unsigned char)(t >> 32); + *(md++) = (unsigned char)(t >> 24); + *(md++) = (unsigned char)(t >> 16); + *(md++) = (unsigned char)(t >> 8); + *(md++) = (unsigned char)(t); + } + break; + /* ... as well as make sure md_len is not abused. */ + default: + return 0; + } + + return 1; +} + +int SHA384_Final(unsigned char *md, SHA512_CTX *c) +{ + return SHA512_Final(md, c); +} + +int SHA512_Update(SHA512_CTX *c, const void *_data, size_t len) +{ + SHA_LONG64 l; + unsigned char *p = c->u.p; + const unsigned char *data = (const unsigned char *)_data; + + if (len == 0) + return 1; + + l = (c->Nl + (((SHA_LONG64) len) << 3)) & U64(0xffffffffffffffff); + if (l < c->Nl) + c->Nh++; + if (sizeof(len) >= 8) + c->Nh += (((SHA_LONG64) len) >> 61); + c->Nl = l; + + if (c->num != 0) { + size_t n = sizeof(c->u) - c->num; + + if (len < n) { + memcpy(p + c->num, data, len), c->num += (unsigned int)len; + return 1; + } else { + memcpy(p + c->num, data, n), c->num = 0; + len -= n, data += n; + sha512_block_data_order(c, p, 1); + } + } + + if (len >= sizeof(c->u)) { +#ifndef SHA512_BLOCK_CAN_MANAGE_UNALIGNED_DATA + if ((size_t)data % sizeof(c->u.d[0]) != 0) + while (len >= sizeof(c->u)) + memcpy(p, data, sizeof(c->u)), + sha512_block_data_order(c, p, 1), + len -= sizeof(c->u), data += sizeof(c->u); + else +#endif + sha512_block_data_order(c, data, len / sizeof(c->u)), + data += len, len %= sizeof(c->u), data -= len; + } + + if (len != 0) + memcpy(p, data, len), c->num = (int)len; + + return 1; +} + +int SHA384_Update(SHA512_CTX *c, const void *data, size_t len) +{ + return SHA512_Update(c, data, len); +} + +void SHA512_Transform(SHA512_CTX *c, const unsigned char *data) +{ +#ifndef SHA512_BLOCK_CAN_MANAGE_UNALIGNED_DATA + if ((size_t)data % sizeof(c->u.d[0]) != 0) + memcpy(c->u.p, data, sizeof(c->u.p)), data = c->u.p; +#endif + sha512_block_data_order(c, data, 1); +} + +unsigned char *SHA384(const unsigned char *d, size_t n, unsigned char *md) +{ + SHA512_CTX c; + static unsigned char m[SHA384_DIGEST_LENGTH]; + + if (md == NULL) + md = m; + SHA384_Init(&c); + SHA512_Update(&c, d, n); + SHA512_Final(md, &c); + OPENSSL_cleanse(&c, sizeof(c)); + return md; +} + +unsigned char *SHA512(const unsigned char *d, size_t n, unsigned char *md) +{ + SHA512_CTX c; + static unsigned char m[SHA512_DIGEST_LENGTH]; + + if (md == NULL) + md = m; + SHA512_Init(&c); + SHA512_Update(&c, d, n); + SHA512_Final(md, &c); + OPENSSL_cleanse(&c, sizeof(c)); + return md; +} + +#ifndef SHA512_ASM +static const SHA_LONG64 K512[80] = { + U64(0x428a2f98d728ae22), U64(0x7137449123ef65cd), + U64(0xb5c0fbcfec4d3b2f), U64(0xe9b5dba58189dbbc), + U64(0x3956c25bf348b538), U64(0x59f111f1b605d019), + U64(0x923f82a4af194f9b), U64(0xab1c5ed5da6d8118), + U64(0xd807aa98a3030242), U64(0x12835b0145706fbe), + U64(0x243185be4ee4b28c), U64(0x550c7dc3d5ffb4e2), + U64(0x72be5d74f27b896f), U64(0x80deb1fe3b1696b1), + U64(0x9bdc06a725c71235), U64(0xc19bf174cf692694), + U64(0xe49b69c19ef14ad2), U64(0xefbe4786384f25e3), + U64(0x0fc19dc68b8cd5b5), U64(0x240ca1cc77ac9c65), + U64(0x2de92c6f592b0275), U64(0x4a7484aa6ea6e483), + U64(0x5cb0a9dcbd41fbd4), U64(0x76f988da831153b5), + U64(0x983e5152ee66dfab), U64(0xa831c66d2db43210), + U64(0xb00327c898fb213f), U64(0xbf597fc7beef0ee4), + U64(0xc6e00bf33da88fc2), U64(0xd5a79147930aa725), + U64(0x06ca6351e003826f), U64(0x142929670a0e6e70), + U64(0x27b70a8546d22ffc), U64(0x2e1b21385c26c926), + U64(0x4d2c6dfc5ac42aed), U64(0x53380d139d95b3df), + U64(0x650a73548baf63de), U64(0x766a0abb3c77b2a8), + U64(0x81c2c92e47edaee6), U64(0x92722c851482353b), + U64(0xa2bfe8a14cf10364), U64(0xa81a664bbc423001), + U64(0xc24b8b70d0f89791), U64(0xc76c51a30654be30), + U64(0xd192e819d6ef5218), U64(0xd69906245565a910), + U64(0xf40e35855771202a), U64(0x106aa07032bbd1b8), + U64(0x19a4c116b8d2d0c8), U64(0x1e376c085141ab53), + U64(0x2748774cdf8eeb99), U64(0x34b0bcb5e19b48a8), + U64(0x391c0cb3c5c95a63), U64(0x4ed8aa4ae3418acb), + U64(0x5b9cca4f7763e373), U64(0x682e6ff3d6b2b8a3), + U64(0x748f82ee5defb2fc), U64(0x78a5636f43172f60), + U64(0x84c87814a1f0ab72), U64(0x8cc702081a6439ec), + U64(0x90befffa23631e28), U64(0xa4506cebde82bde9), + U64(0xbef9a3f7b2c67915), U64(0xc67178f2e372532b), + U64(0xca273eceea26619c), U64(0xd186b8c721c0c207), + U64(0xeada7dd6cde0eb1e), U64(0xf57d4f7fee6ed178), + U64(0x06f067aa72176fba), U64(0x0a637dc5a2c898a6), + U64(0x113f9804bef90dae), U64(0x1b710b35131c471b), + U64(0x28db77f523047d84), U64(0x32caab7b40c72493), + U64(0x3c9ebe0a15c9bebc), U64(0x431d67c49c100d4c), + U64(0x4cc5d4becb3e42b6), U64(0x597f299cfc657e2a), + U64(0x5fcb6fab3ad6faec), U64(0x6c44198c4a475817) +}; + +# ifndef PEDANTIC +# if defined(__GNUC__) && __GNUC__>=2 && \ + !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) +# if defined(__x86_64) || defined(__x86_64__) +# define ROTR(a,n) ({ SHA_LONG64 ret; \ + asm ("rorq %1,%0" \ + : "=r"(ret) \ + : "J"(n),"0"(a) \ + : "cc"); ret; }) +# if !defined(B_ENDIAN) +# define PULL64(x) ({ SHA_LONG64 ret=*((const SHA_LONG64 *)(&(x))); \ + asm ("bswapq %0" \ + : "=r"(ret) \ + : "0"(ret)); ret; }) +# endif +# elif (defined(__i386) || defined(__i386__)) && !defined(B_ENDIAN) +# if defined(I386_ONLY) +# define PULL64(x) ({ const unsigned int *p=(const unsigned int *)(&(x));\ + unsigned int hi=p[0],lo=p[1]; \ + asm("xchgb %%ah,%%al;xchgb %%dh,%%dl;"\ + "roll $16,%%eax; roll $16,%%edx; "\ + "xchgb %%ah,%%al;xchgb %%dh,%%dl;"\ + : "=a"(lo),"=d"(hi) \ + : "0"(lo),"1"(hi) : "cc"); \ + ((SHA_LONG64)hi)<<32|lo; }) +# else +# define PULL64(x) ({ const unsigned int *p=(const unsigned int *)(&(x));\ + unsigned int hi=p[0],lo=p[1]; \ + asm ("bswapl %0; bswapl %1;" \ + : "=r"(lo),"=r"(hi) \ + : "0"(lo),"1"(hi)); \ + ((SHA_LONG64)hi)<<32|lo; }) +# endif +# elif (defined(_ARCH_PPC) && defined(__64BIT__)) || defined(_ARCH_PPC64) +# define ROTR(a,n) ({ SHA_LONG64 ret; \ + asm ("rotrdi %0,%1,%2" \ + : "=r"(ret) \ + : "r"(a),"K"(n)); ret; }) +# elif defined(__aarch64__) +# define ROTR(a,n) ({ SHA_LONG64 ret; \ + asm ("ror %0,%1,%2" \ + : "=r"(ret) \ + : "r"(a),"I"(n)); ret; }) +# if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \ + __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ +# define PULL64(x) ({ SHA_LONG64 ret; \ + asm ("rev %0,%1" \ + : "=r"(ret) \ + : "r"(*((const SHA_LONG64 *)(&(x))))); ret; }) +# endif +# endif +# elif defined(_MSC_VER) +# if defined(_WIN64) /* applies to both IA-64 and AMD64 */ +# pragma intrinsic(_rotr64) +# define ROTR(a,n) _rotr64((a),n) +# endif +# if defined(_M_IX86) && !defined(OPENSSL_NO_ASM) && \ + !defined(OPENSSL_NO_INLINE_ASM) +# if defined(I386_ONLY) +static SHA_LONG64 __fastcall __pull64be(const void *x) +{ + _asm mov edx,[ecx + 0] + _asm mov eax,[ecx + 4] + _asm xchg dh, dl + _asm xchg ah, al + _asm rol edx, 16 + _asm rol eax, 16 + _asm xchg dh, dl + _asm xchg ah, al +} +# else +static SHA_LONG64 __fastcall __pull64be(const void *x) +{ + _asm mov edx,[ecx + 0] + _asm mov eax,[ecx + 4] + _asm bswap edx + _asm bswap eax +} +# endif +# define PULL64(x) __pull64be(&(x)) +# endif +# endif +# endif +# ifndef PULL64 +# define B(x,j) (((SHA_LONG64)(*(((const unsigned char *)(&x))+j)))<<((7-j)*8)) +# define PULL64(x) (B(x,0)|B(x,1)|B(x,2)|B(x,3)|B(x,4)|B(x,5)|B(x,6)|B(x,7)) +# endif +# ifndef ROTR +# define ROTR(x,s) (((x)>>s) | (x)<<(64-s)) +# endif +# define Sigma0(x) (ROTR((x),28) ^ ROTR((x),34) ^ ROTR((x),39)) +# define Sigma1(x) (ROTR((x),14) ^ ROTR((x),18) ^ ROTR((x),41)) +# define sigma0(x) (ROTR((x),1) ^ ROTR((x),8) ^ ((x)>>7)) +# define sigma1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6)) +# define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) +# define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +# if defined(__i386) || defined(__i386__) || defined(_M_IX86) +/* + * This code should give better results on 32-bit CPU with less than + * ~24 registers, both size and performance wise... + */ + +static void sha512_block_data_order(SHA512_CTX *ctx, const void *in, + size_t num) +{ + const SHA_LONG64 *W = in; + SHA_LONG64 A, E, T; + SHA_LONG64 X[9 + 80], *F; + int i; + + while (num--) { + + F = X + 80; + A = ctx->h[0]; + F[1] = ctx->h[1]; + F[2] = ctx->h[2]; + F[3] = ctx->h[3]; + E = ctx->h[4]; + F[5] = ctx->h[5]; + F[6] = ctx->h[6]; + F[7] = ctx->h[7]; + + for (i = 0; i < 16; i++, F--) { +# ifdef B_ENDIAN + T = W[i]; +# else + T = PULL64(W[i]); +# endif + F[0] = A; + F[4] = E; + F[8] = T; + T += F[7] + Sigma1(E) + Ch(E, F[5], F[6]) + K512[i]; + E = F[3] + T; + A = T + Sigma0(A) + Maj(A, F[1], F[2]); + } + + for (; i < 80; i++, F--) { + T = sigma0(F[8 + 16 - 1]); + T += sigma1(F[8 + 16 - 14]); + T += F[8 + 16] + F[8 + 16 - 9]; + + F[0] = A; + F[4] = E; + F[8] = T; + T += F[7] + Sigma1(E) + Ch(E, F[5], F[6]) + K512[i]; + E = F[3] + T; + A = T + Sigma0(A) + Maj(A, F[1], F[2]); + } + + ctx->h[0] += A; + ctx->h[1] += F[1]; + ctx->h[2] += F[2]; + ctx->h[3] += F[3]; + ctx->h[4] += E; + ctx->h[5] += F[5]; + ctx->h[6] += F[6]; + ctx->h[7] += F[7]; + + W += SHA_LBLOCK; + } +} + +# elif defined(OPENSSL_SMALL_FOOTPRINT) + +static void sha512_block_data_order(SHA512_CTX *ctx, const void *in, + size_t num) +{ + const SHA_LONG64 *W = in; + SHA_LONG64 a, b, c, d, e, f, g, h, s0, s1, T1, T2; + SHA_LONG64 X[16]; + int i; + + while (num--) { + + a = ctx->h[0]; + b = ctx->h[1]; + c = ctx->h[2]; + d = ctx->h[3]; + e = ctx->h[4]; + f = ctx->h[5]; + g = ctx->h[6]; + h = ctx->h[7]; + + for (i = 0; i < 16; i++) { +# ifdef B_ENDIAN + T1 = X[i] = W[i]; +# else + T1 = X[i] = PULL64(W[i]); +# endif + T1 += h + Sigma1(e) + Ch(e, f, g) + K512[i]; + T2 = Sigma0(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + } + + for (; i < 80; i++) { + s0 = X[(i + 1) & 0x0f]; + s0 = sigma0(s0); + s1 = X[(i + 14) & 0x0f]; + s1 = sigma1(s1); + + T1 = X[i & 0xf] += s0 + s1 + X[(i + 9) & 0xf]; + T1 += h + Sigma1(e) + Ch(e, f, g) + K512[i]; + T2 = Sigma0(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + } + + ctx->h[0] += a; + ctx->h[1] += b; + ctx->h[2] += c; + ctx->h[3] += d; + ctx->h[4] += e; + ctx->h[5] += f; + ctx->h[6] += g; + ctx->h[7] += h; + + W += SHA_LBLOCK; + } +} + +# else +# define ROUND_00_15(i,a,b,c,d,e,f,g,h) do { \ + T1 += h + Sigma1(e) + Ch(e,f,g) + K512[i]; \ + h = Sigma0(a) + Maj(a,b,c); \ + d += T1; h += T1; } while (0) + +# define ROUND_16_80(i,j,a,b,c,d,e,f,g,h,X) do { \ + s0 = X[(j+1)&0x0f]; s0 = sigma0(s0); \ + s1 = X[(j+14)&0x0f]; s1 = sigma1(s1); \ + T1 = X[(j)&0x0f] += s0 + s1 + X[(j+9)&0x0f]; \ + ROUND_00_15(i+j,a,b,c,d,e,f,g,h); } while (0) + +static void sha512_block_data_order(SHA512_CTX *ctx, const void *in, + size_t num) +{ + const SHA_LONG64 *W = in; + SHA_LONG64 a, b, c, d, e, f, g, h, s0, s1, T1; + SHA_LONG64 X[16]; + int i; + + while (num--) { + + a = ctx->h[0]; + b = ctx->h[1]; + c = ctx->h[2]; + d = ctx->h[3]; + e = ctx->h[4]; + f = ctx->h[5]; + g = ctx->h[6]; + h = ctx->h[7]; + +# ifdef B_ENDIAN + T1 = X[0] = W[0]; + ROUND_00_15(0, a, b, c, d, e, f, g, h); + T1 = X[1] = W[1]; + ROUND_00_15(1, h, a, b, c, d, e, f, g); + T1 = X[2] = W[2]; + ROUND_00_15(2, g, h, a, b, c, d, e, f); + T1 = X[3] = W[3]; + ROUND_00_15(3, f, g, h, a, b, c, d, e); + T1 = X[4] = W[4]; + ROUND_00_15(4, e, f, g, h, a, b, c, d); + T1 = X[5] = W[5]; + ROUND_00_15(5, d, e, f, g, h, a, b, c); + T1 = X[6] = W[6]; + ROUND_00_15(6, c, d, e, f, g, h, a, b); + T1 = X[7] = W[7]; + ROUND_00_15(7, b, c, d, e, f, g, h, a); + T1 = X[8] = W[8]; + ROUND_00_15(8, a, b, c, d, e, f, g, h); + T1 = X[9] = W[9]; + ROUND_00_15(9, h, a, b, c, d, e, f, g); + T1 = X[10] = W[10]; + ROUND_00_15(10, g, h, a, b, c, d, e, f); + T1 = X[11] = W[11]; + ROUND_00_15(11, f, g, h, a, b, c, d, e); + T1 = X[12] = W[12]; + ROUND_00_15(12, e, f, g, h, a, b, c, d); + T1 = X[13] = W[13]; + ROUND_00_15(13, d, e, f, g, h, a, b, c); + T1 = X[14] = W[14]; + ROUND_00_15(14, c, d, e, f, g, h, a, b); + T1 = X[15] = W[15]; + ROUND_00_15(15, b, c, d, e, f, g, h, a); +# else + T1 = X[0] = PULL64(W[0]); + ROUND_00_15(0, a, b, c, d, e, f, g, h); + T1 = X[1] = PULL64(W[1]); + ROUND_00_15(1, h, a, b, c, d, e, f, g); + T1 = X[2] = PULL64(W[2]); + ROUND_00_15(2, g, h, a, b, c, d, e, f); + T1 = X[3] = PULL64(W[3]); + ROUND_00_15(3, f, g, h, a, b, c, d, e); + T1 = X[4] = PULL64(W[4]); + ROUND_00_15(4, e, f, g, h, a, b, c, d); + T1 = X[5] = PULL64(W[5]); + ROUND_00_15(5, d, e, f, g, h, a, b, c); + T1 = X[6] = PULL64(W[6]); + ROUND_00_15(6, c, d, e, f, g, h, a, b); + T1 = X[7] = PULL64(W[7]); + ROUND_00_15(7, b, c, d, e, f, g, h, a); + T1 = X[8] = PULL64(W[8]); + ROUND_00_15(8, a, b, c, d, e, f, g, h); + T1 = X[9] = PULL64(W[9]); + ROUND_00_15(9, h, a, b, c, d, e, f, g); + T1 = X[10] = PULL64(W[10]); + ROUND_00_15(10, g, h, a, b, c, d, e, f); + T1 = X[11] = PULL64(W[11]); + ROUND_00_15(11, f, g, h, a, b, c, d, e); + T1 = X[12] = PULL64(W[12]); + ROUND_00_15(12, e, f, g, h, a, b, c, d); + T1 = X[13] = PULL64(W[13]); + ROUND_00_15(13, d, e, f, g, h, a, b, c); + T1 = X[14] = PULL64(W[14]); + ROUND_00_15(14, c, d, e, f, g, h, a, b); + T1 = X[15] = PULL64(W[15]); + ROUND_00_15(15, b, c, d, e, f, g, h, a); +# endif + + for (i = 16; i < 80; i += 16) { + ROUND_16_80(i, 0, a, b, c, d, e, f, g, h, X); + ROUND_16_80(i, 1, h, a, b, c, d, e, f, g, X); + ROUND_16_80(i, 2, g, h, a, b, c, d, e, f, X); + ROUND_16_80(i, 3, f, g, h, a, b, c, d, e, X); + ROUND_16_80(i, 4, e, f, g, h, a, b, c, d, X); + ROUND_16_80(i, 5, d, e, f, g, h, a, b, c, X); + ROUND_16_80(i, 6, c, d, e, f, g, h, a, b, X); + ROUND_16_80(i, 7, b, c, d, e, f, g, h, a, X); + ROUND_16_80(i, 8, a, b, c, d, e, f, g, h, X); + ROUND_16_80(i, 9, h, a, b, c, d, e, f, g, X); + ROUND_16_80(i, 10, g, h, a, b, c, d, e, f, X); + ROUND_16_80(i, 11, f, g, h, a, b, c, d, e, X); + ROUND_16_80(i, 12, e, f, g, h, a, b, c, d, X); + ROUND_16_80(i, 13, d, e, f, g, h, a, b, c, X); + ROUND_16_80(i, 14, c, d, e, f, g, h, a, b, X); + ROUND_16_80(i, 15, b, c, d, e, f, g, h, a, X); + } + + ctx->h[0] += a; + ctx->h[1] += b; + ctx->h[2] += c; + ctx->h[3] += d; + ctx->h[4] += e; + ctx->h[5] += f; + ctx->h[6] += g; + ctx->h[7] += h; + + W += SHA_LBLOCK; + } +} + +# endif + +#endif /* SHA512_ASM */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sha/sha_locl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/sha_locl.h new file mode 100644 index 000000000..4e5a09038 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sha/sha_locl.h @@ -0,0 +1,424 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#include +#include + +#define DATA_ORDER_IS_BIG_ENDIAN + +#define HASH_LONG SHA_LONG +#define HASH_CTX SHA_CTX +#define HASH_CBLOCK SHA_CBLOCK +#define HASH_MAKE_STRING(c,s) do { \ + unsigned long ll; \ + ll=(c)->h0; (void)HOST_l2c(ll,(s)); \ + ll=(c)->h1; (void)HOST_l2c(ll,(s)); \ + ll=(c)->h2; (void)HOST_l2c(ll,(s)); \ + ll=(c)->h3; (void)HOST_l2c(ll,(s)); \ + ll=(c)->h4; (void)HOST_l2c(ll,(s)); \ + } while (0) + +#define HASH_UPDATE SHA1_Update +#define HASH_TRANSFORM SHA1_Transform +#define HASH_FINAL SHA1_Final +#define HASH_INIT SHA1_Init +#define HASH_BLOCK_DATA_ORDER sha1_block_data_order +#define Xupdate(a,ix,ia,ib,ic,id) ( (a)=(ia^ib^ic^id), \ + ix=(a)=ROTATE((a),1) \ + ) + +#ifndef SHA1_ASM +static void sha1_block_data_order(SHA_CTX *c, const void *p, size_t num); +#else +void sha1_block_data_order(SHA_CTX *c, const void *p, size_t num); +#endif + +#include "internal/md32_common.h" + +#define INIT_DATA_h0 0x67452301UL +#define INIT_DATA_h1 0xefcdab89UL +#define INIT_DATA_h2 0x98badcfeUL +#define INIT_DATA_h3 0x10325476UL +#define INIT_DATA_h4 0xc3d2e1f0UL + +int HASH_INIT(SHA_CTX *c) +{ + memset(c, 0, sizeof(*c)); + c->h0 = INIT_DATA_h0; + c->h1 = INIT_DATA_h1; + c->h2 = INIT_DATA_h2; + c->h3 = INIT_DATA_h3; + c->h4 = INIT_DATA_h4; + return 1; +} + +#define K_00_19 0x5a827999UL +#define K_20_39 0x6ed9eba1UL +#define K_40_59 0x8f1bbcdcUL +#define K_60_79 0xca62c1d6UL + +/* + * As pointed out by Wei Dai, F() below can be simplified to the code in + * F_00_19. Wei attributes these optimizations to Peter Gutmann's SHS code, + * and he attributes it to Rich Schroeppel. + * #define F(x,y,z) (((x) & (y)) | ((~(x)) & (z))) + * I've just become aware of another tweak to be made, again from Wei Dai, + * in F_40_59, (x&a)|(y&a) -> (x|y)&a + */ +#define F_00_19(b,c,d) ((((c) ^ (d)) & (b)) ^ (d)) +#define F_20_39(b,c,d) ((b) ^ (c) ^ (d)) +#define F_40_59(b,c,d) (((b) & (c)) | (((b)|(c)) & (d))) +#define F_60_79(b,c,d) F_20_39(b,c,d) + +#ifndef OPENSSL_SMALL_FOOTPRINT + +# define BODY_00_15(i,a,b,c,d,e,f,xi) \ + (f)=xi+(e)+K_00_19+ROTATE((a),5)+F_00_19((b),(c),(d)); \ + (b)=ROTATE((b),30); + +# define BODY_16_19(i,a,b,c,d,e,f,xi,xa,xb,xc,xd) \ + Xupdate(f,xi,xa,xb,xc,xd); \ + (f)+=(e)+K_00_19+ROTATE((a),5)+F_00_19((b),(c),(d)); \ + (b)=ROTATE((b),30); + +# define BODY_20_31(i,a,b,c,d,e,f,xi,xa,xb,xc,xd) \ + Xupdate(f,xi,xa,xb,xc,xd); \ + (f)+=(e)+K_20_39+ROTATE((a),5)+F_20_39((b),(c),(d)); \ + (b)=ROTATE((b),30); + +# define BODY_32_39(i,a,b,c,d,e,f,xa,xb,xc,xd) \ + Xupdate(f,xa,xa,xb,xc,xd); \ + (f)+=(e)+K_20_39+ROTATE((a),5)+F_20_39((b),(c),(d)); \ + (b)=ROTATE((b),30); + +# define BODY_40_59(i,a,b,c,d,e,f,xa,xb,xc,xd) \ + Xupdate(f,xa,xa,xb,xc,xd); \ + (f)+=(e)+K_40_59+ROTATE((a),5)+F_40_59((b),(c),(d)); \ + (b)=ROTATE((b),30); + +# define BODY_60_79(i,a,b,c,d,e,f,xa,xb,xc,xd) \ + Xupdate(f,xa,xa,xb,xc,xd); \ + (f)=xa+(e)+K_60_79+ROTATE((a),5)+F_60_79((b),(c),(d)); \ + (b)=ROTATE((b),30); + +# ifdef X +# undef X +# endif +# ifndef MD32_XARRAY + /* + * Originally X was an array. As it's automatic it's natural + * to expect RISC compiler to accommodate at least part of it in + * the register bank, isn't it? Unfortunately not all compilers + * "find" this expectation reasonable:-( On order to make such + * compilers generate better code I replace X[] with a bunch of + * X0, X1, etc. See the function body below... + */ +# define X(i) XX##i +# else + /* + * However! Some compilers (most notably HP C) get overwhelmed by + * that many local variables so that we have to have the way to + * fall down to the original behavior. + */ +# define X(i) XX[i] +# endif + +# if !defined(SHA1_ASM) +static void HASH_BLOCK_DATA_ORDER(SHA_CTX *c, const void *p, size_t num) +{ + const unsigned char *data = p; + register unsigned MD32_REG_T A, B, C, D, E, T, l; +# ifndef MD32_XARRAY + unsigned MD32_REG_T XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, + XX8, XX9, XX10, XX11, XX12, XX13, XX14, XX15; +# else + SHA_LONG XX[16]; +# endif + + A = c->h0; + B = c->h1; + C = c->h2; + D = c->h3; + E = c->h4; + + for (;;) { + const union { + long one; + char little; + } is_endian = { + 1 + }; + + if (!is_endian.little && sizeof(SHA_LONG) == 4 + && ((size_t)p % 4) == 0) { + const SHA_LONG *W = (const SHA_LONG *)data; + + X(0) = W[0]; + X(1) = W[1]; + BODY_00_15(0, A, B, C, D, E, T, X(0)); + X(2) = W[2]; + BODY_00_15(1, T, A, B, C, D, E, X(1)); + X(3) = W[3]; + BODY_00_15(2, E, T, A, B, C, D, X(2)); + X(4) = W[4]; + BODY_00_15(3, D, E, T, A, B, C, X(3)); + X(5) = W[5]; + BODY_00_15(4, C, D, E, T, A, B, X(4)); + X(6) = W[6]; + BODY_00_15(5, B, C, D, E, T, A, X(5)); + X(7) = W[7]; + BODY_00_15(6, A, B, C, D, E, T, X(6)); + X(8) = W[8]; + BODY_00_15(7, T, A, B, C, D, E, X(7)); + X(9) = W[9]; + BODY_00_15(8, E, T, A, B, C, D, X(8)); + X(10) = W[10]; + BODY_00_15(9, D, E, T, A, B, C, X(9)); + X(11) = W[11]; + BODY_00_15(10, C, D, E, T, A, B, X(10)); + X(12) = W[12]; + BODY_00_15(11, B, C, D, E, T, A, X(11)); + X(13) = W[13]; + BODY_00_15(12, A, B, C, D, E, T, X(12)); + X(14) = W[14]; + BODY_00_15(13, T, A, B, C, D, E, X(13)); + X(15) = W[15]; + BODY_00_15(14, E, T, A, B, C, D, X(14)); + BODY_00_15(15, D, E, T, A, B, C, X(15)); + + data += SHA_CBLOCK; + } else { + (void)HOST_c2l(data, l); + X(0) = l; + (void)HOST_c2l(data, l); + X(1) = l; + BODY_00_15(0, A, B, C, D, E, T, X(0)); + (void)HOST_c2l(data, l); + X(2) = l; + BODY_00_15(1, T, A, B, C, D, E, X(1)); + (void)HOST_c2l(data, l); + X(3) = l; + BODY_00_15(2, E, T, A, B, C, D, X(2)); + (void)HOST_c2l(data, l); + X(4) = l; + BODY_00_15(3, D, E, T, A, B, C, X(3)); + (void)HOST_c2l(data, l); + X(5) = l; + BODY_00_15(4, C, D, E, T, A, B, X(4)); + (void)HOST_c2l(data, l); + X(6) = l; + BODY_00_15(5, B, C, D, E, T, A, X(5)); + (void)HOST_c2l(data, l); + X(7) = l; + BODY_00_15(6, A, B, C, D, E, T, X(6)); + (void)HOST_c2l(data, l); + X(8) = l; + BODY_00_15(7, T, A, B, C, D, E, X(7)); + (void)HOST_c2l(data, l); + X(9) = l; + BODY_00_15(8, E, T, A, B, C, D, X(8)); + (void)HOST_c2l(data, l); + X(10) = l; + BODY_00_15(9, D, E, T, A, B, C, X(9)); + (void)HOST_c2l(data, l); + X(11) = l; + BODY_00_15(10, C, D, E, T, A, B, X(10)); + (void)HOST_c2l(data, l); + X(12) = l; + BODY_00_15(11, B, C, D, E, T, A, X(11)); + (void)HOST_c2l(data, l); + X(13) = l; + BODY_00_15(12, A, B, C, D, E, T, X(12)); + (void)HOST_c2l(data, l); + X(14) = l; + BODY_00_15(13, T, A, B, C, D, E, X(13)); + (void)HOST_c2l(data, l); + X(15) = l; + BODY_00_15(14, E, T, A, B, C, D, X(14)); + BODY_00_15(15, D, E, T, A, B, C, X(15)); + } + + BODY_16_19(16, C, D, E, T, A, B, X(0), X(0), X(2), X(8), X(13)); + BODY_16_19(17, B, C, D, E, T, A, X(1), X(1), X(3), X(9), X(14)); + BODY_16_19(18, A, B, C, D, E, T, X(2), X(2), X(4), X(10), X(15)); + BODY_16_19(19, T, A, B, C, D, E, X(3), X(3), X(5), X(11), X(0)); + + BODY_20_31(20, E, T, A, B, C, D, X(4), X(4), X(6), X(12), X(1)); + BODY_20_31(21, D, E, T, A, B, C, X(5), X(5), X(7), X(13), X(2)); + BODY_20_31(22, C, D, E, T, A, B, X(6), X(6), X(8), X(14), X(3)); + BODY_20_31(23, B, C, D, E, T, A, X(7), X(7), X(9), X(15), X(4)); + BODY_20_31(24, A, B, C, D, E, T, X(8), X(8), X(10), X(0), X(5)); + BODY_20_31(25, T, A, B, C, D, E, X(9), X(9), X(11), X(1), X(6)); + BODY_20_31(26, E, T, A, B, C, D, X(10), X(10), X(12), X(2), X(7)); + BODY_20_31(27, D, E, T, A, B, C, X(11), X(11), X(13), X(3), X(8)); + BODY_20_31(28, C, D, E, T, A, B, X(12), X(12), X(14), X(4), X(9)); + BODY_20_31(29, B, C, D, E, T, A, X(13), X(13), X(15), X(5), X(10)); + BODY_20_31(30, A, B, C, D, E, T, X(14), X(14), X(0), X(6), X(11)); + BODY_20_31(31, T, A, B, C, D, E, X(15), X(15), X(1), X(7), X(12)); + + BODY_32_39(32, E, T, A, B, C, D, X(0), X(2), X(8), X(13)); + BODY_32_39(33, D, E, T, A, B, C, X(1), X(3), X(9), X(14)); + BODY_32_39(34, C, D, E, T, A, B, X(2), X(4), X(10), X(15)); + BODY_32_39(35, B, C, D, E, T, A, X(3), X(5), X(11), X(0)); + BODY_32_39(36, A, B, C, D, E, T, X(4), X(6), X(12), X(1)); + BODY_32_39(37, T, A, B, C, D, E, X(5), X(7), X(13), X(2)); + BODY_32_39(38, E, T, A, B, C, D, X(6), X(8), X(14), X(3)); + BODY_32_39(39, D, E, T, A, B, C, X(7), X(9), X(15), X(4)); + + BODY_40_59(40, C, D, E, T, A, B, X(8), X(10), X(0), X(5)); + BODY_40_59(41, B, C, D, E, T, A, X(9), X(11), X(1), X(6)); + BODY_40_59(42, A, B, C, D, E, T, X(10), X(12), X(2), X(7)); + BODY_40_59(43, T, A, B, C, D, E, X(11), X(13), X(3), X(8)); + BODY_40_59(44, E, T, A, B, C, D, X(12), X(14), X(4), X(9)); + BODY_40_59(45, D, E, T, A, B, C, X(13), X(15), X(5), X(10)); + BODY_40_59(46, C, D, E, T, A, B, X(14), X(0), X(6), X(11)); + BODY_40_59(47, B, C, D, E, T, A, X(15), X(1), X(7), X(12)); + BODY_40_59(48, A, B, C, D, E, T, X(0), X(2), X(8), X(13)); + BODY_40_59(49, T, A, B, C, D, E, X(1), X(3), X(9), X(14)); + BODY_40_59(50, E, T, A, B, C, D, X(2), X(4), X(10), X(15)); + BODY_40_59(51, D, E, T, A, B, C, X(3), X(5), X(11), X(0)); + BODY_40_59(52, C, D, E, T, A, B, X(4), X(6), X(12), X(1)); + BODY_40_59(53, B, C, D, E, T, A, X(5), X(7), X(13), X(2)); + BODY_40_59(54, A, B, C, D, E, T, X(6), X(8), X(14), X(3)); + BODY_40_59(55, T, A, B, C, D, E, X(7), X(9), X(15), X(4)); + BODY_40_59(56, E, T, A, B, C, D, X(8), X(10), X(0), X(5)); + BODY_40_59(57, D, E, T, A, B, C, X(9), X(11), X(1), X(6)); + BODY_40_59(58, C, D, E, T, A, B, X(10), X(12), X(2), X(7)); + BODY_40_59(59, B, C, D, E, T, A, X(11), X(13), X(3), X(8)); + + BODY_60_79(60, A, B, C, D, E, T, X(12), X(14), X(4), X(9)); + BODY_60_79(61, T, A, B, C, D, E, X(13), X(15), X(5), X(10)); + BODY_60_79(62, E, T, A, B, C, D, X(14), X(0), X(6), X(11)); + BODY_60_79(63, D, E, T, A, B, C, X(15), X(1), X(7), X(12)); + BODY_60_79(64, C, D, E, T, A, B, X(0), X(2), X(8), X(13)); + BODY_60_79(65, B, C, D, E, T, A, X(1), X(3), X(9), X(14)); + BODY_60_79(66, A, B, C, D, E, T, X(2), X(4), X(10), X(15)); + BODY_60_79(67, T, A, B, C, D, E, X(3), X(5), X(11), X(0)); + BODY_60_79(68, E, T, A, B, C, D, X(4), X(6), X(12), X(1)); + BODY_60_79(69, D, E, T, A, B, C, X(5), X(7), X(13), X(2)); + BODY_60_79(70, C, D, E, T, A, B, X(6), X(8), X(14), X(3)); + BODY_60_79(71, B, C, D, E, T, A, X(7), X(9), X(15), X(4)); + BODY_60_79(72, A, B, C, D, E, T, X(8), X(10), X(0), X(5)); + BODY_60_79(73, T, A, B, C, D, E, X(9), X(11), X(1), X(6)); + BODY_60_79(74, E, T, A, B, C, D, X(10), X(12), X(2), X(7)); + BODY_60_79(75, D, E, T, A, B, C, X(11), X(13), X(3), X(8)); + BODY_60_79(76, C, D, E, T, A, B, X(12), X(14), X(4), X(9)); + BODY_60_79(77, B, C, D, E, T, A, X(13), X(15), X(5), X(10)); + BODY_60_79(78, A, B, C, D, E, T, X(14), X(0), X(6), X(11)); + BODY_60_79(79, T, A, B, C, D, E, X(15), X(1), X(7), X(12)); + + c->h0 = (c->h0 + E) & 0xffffffffL; + c->h1 = (c->h1 + T) & 0xffffffffL; + c->h2 = (c->h2 + A) & 0xffffffffL; + c->h3 = (c->h3 + B) & 0xffffffffL; + c->h4 = (c->h4 + C) & 0xffffffffL; + + if (--num == 0) + break; + + A = c->h0; + B = c->h1; + C = c->h2; + D = c->h3; + E = c->h4; + + } +} +# endif + +#else /* OPENSSL_SMALL_FOOTPRINT */ + +# define BODY_00_15(xi) do { \ + T=E+K_00_19+F_00_19(B,C,D); \ + E=D, D=C, C=ROTATE(B,30), B=A; \ + A=ROTATE(A,5)+T+xi; } while(0) + +# define BODY_16_19(xa,xb,xc,xd) do { \ + Xupdate(T,xa,xa,xb,xc,xd); \ + T+=E+K_00_19+F_00_19(B,C,D); \ + E=D, D=C, C=ROTATE(B,30), B=A; \ + A=ROTATE(A,5)+T; } while(0) + +# define BODY_20_39(xa,xb,xc,xd) do { \ + Xupdate(T,xa,xa,xb,xc,xd); \ + T+=E+K_20_39+F_20_39(B,C,D); \ + E=D, D=C, C=ROTATE(B,30), B=A; \ + A=ROTATE(A,5)+T; } while(0) + +# define BODY_40_59(xa,xb,xc,xd) do { \ + Xupdate(T,xa,xa,xb,xc,xd); \ + T+=E+K_40_59+F_40_59(B,C,D); \ + E=D, D=C, C=ROTATE(B,30), B=A; \ + A=ROTATE(A,5)+T; } while(0) + +# define BODY_60_79(xa,xb,xc,xd) do { \ + Xupdate(T,xa,xa,xb,xc,xd); \ + T=E+K_60_79+F_60_79(B,C,D); \ + E=D, D=C, C=ROTATE(B,30), B=A; \ + A=ROTATE(A,5)+T+xa; } while(0) + +# if !defined(SHA1_ASM) +static void HASH_BLOCK_DATA_ORDER(SHA_CTX *c, const void *p, size_t num) +{ + const unsigned char *data = p; + register unsigned MD32_REG_T A, B, C, D, E, T, l; + int i; + SHA_LONG X[16]; + + A = c->h0; + B = c->h1; + C = c->h2; + D = c->h3; + E = c->h4; + + for (;;) { + for (i = 0; i < 16; i++) { + (void)HOST_c2l(data, l); + X[i] = l; + BODY_00_15(X[i]); + } + for (i = 0; i < 4; i++) { + BODY_16_19(X[i], X[i + 2], X[i + 8], X[(i + 13) & 15]); + } + for (; i < 24; i++) { + BODY_20_39(X[i & 15], X[(i + 2) & 15], X[(i + 8) & 15], + X[(i + 13) & 15]); + } + for (i = 0; i < 20; i++) { + BODY_40_59(X[(i + 8) & 15], X[(i + 10) & 15], X[i & 15], + X[(i + 5) & 15]); + } + for (i = 4; i < 24; i++) { + BODY_60_79(X[(i + 8) & 15], X[(i + 10) & 15], X[i & 15], + X[(i + 5) & 15]); + } + + c->h0 = (c->h0 + A) & 0xffffffffL; + c->h1 = (c->h1 + B) & 0xffffffffL; + c->h2 = (c->h2 + C) & 0xffffffffL; + c->h3 = (c->h3 + D) & 0xffffffffL; + c->h4 = (c->h4 + E) & 0xffffffffL; + + if (--num == 0) + break; + + A = c->h0; + B = c->h1; + C = c->h2; + D = c->h3; + E = c->h4; + + } +} +# endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/siphash/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/siphash/build.info new file mode 100644 index 000000000..4166344a5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/siphash/build.info @@ -0,0 +1,5 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + siphash.c \ + siphash_pmeth.c \ + siphash_ameth.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/siphash/siphash.c b/trunk/3rdparty/openssl-1.1-fit/crypto/siphash/siphash.c new file mode 100644 index 000000000..be74a38d9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/siphash/siphash.c @@ -0,0 +1,260 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Based on https://131002.net/siphash C reference implementation */ +/* + SipHash reference C implementation + + Copyright (c) 2012-2016 Jean-Philippe Aumasson + Copyright (c) 2012-2014 Daniel J. Bernstein + + To the extent possible under law, the author(s) have dedicated all copyright + and related and neighboring rights to this software to the public domain + worldwide. This software is distributed without any warranty. + + You should have received a copy of the CC0 Public Domain Dedication along + with this software. If not, see + . + */ + +#include +#include +#include + +#include "internal/siphash.h" +#include "siphash_local.h" + +/* default: SipHash-2-4 */ +#define SIPHASH_C_ROUNDS 2 +#define SIPHASH_D_ROUNDS 4 + +#define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b)))) + +#define U32TO8_LE(p, v) \ + (p)[0] = (uint8_t)((v)); \ + (p)[1] = (uint8_t)((v) >> 8); \ + (p)[2] = (uint8_t)((v) >> 16); \ + (p)[3] = (uint8_t)((v) >> 24); + +#define U64TO8_LE(p, v) \ + U32TO8_LE((p), (uint32_t)((v))); \ + U32TO8_LE((p) + 4, (uint32_t)((v) >> 32)); + +#define U8TO64_LE(p) \ + (((uint64_t)((p)[0])) | ((uint64_t)((p)[1]) << 8) | \ + ((uint64_t)((p)[2]) << 16) | ((uint64_t)((p)[3]) << 24) | \ + ((uint64_t)((p)[4]) << 32) | ((uint64_t)((p)[5]) << 40) | \ + ((uint64_t)((p)[6]) << 48) | ((uint64_t)((p)[7]) << 56)) + +#define SIPROUND \ + do { \ + v0 += v1; \ + v1 = ROTL(v1, 13); \ + v1 ^= v0; \ + v0 = ROTL(v0, 32); \ + v2 += v3; \ + v3 = ROTL(v3, 16); \ + v3 ^= v2; \ + v0 += v3; \ + v3 = ROTL(v3, 21); \ + v3 ^= v0; \ + v2 += v1; \ + v1 = ROTL(v1, 17); \ + v1 ^= v2; \ + v2 = ROTL(v2, 32); \ + } while (0) + +size_t SipHash_ctx_size(void) +{ + return sizeof(SIPHASH); +} + +size_t SipHash_hash_size(SIPHASH *ctx) +{ + return ctx->hash_size; +} + +static size_t siphash_adjust_hash_size(size_t hash_size) +{ + if (hash_size == 0) + hash_size = SIPHASH_MAX_DIGEST_SIZE; + return hash_size; +} + +int SipHash_set_hash_size(SIPHASH *ctx, size_t hash_size) +{ + hash_size = siphash_adjust_hash_size(hash_size); + if (hash_size != SIPHASH_MIN_DIGEST_SIZE + && hash_size != SIPHASH_MAX_DIGEST_SIZE) + return 0; + + /* + * It's possible that the key was set first. If the hash size changes, + * we need to adjust v1 (see SipHash_Init(). + */ + + /* Start by adjusting the stored size, to make things easier */ + ctx->hash_size = siphash_adjust_hash_size(ctx->hash_size); + + /* Now, adjust ctx->v1 if the old and the new size differ */ + if ((size_t)ctx->hash_size != hash_size) { + ctx->v1 ^= 0xee; + ctx->hash_size = hash_size; + } + return 1; +} + +/* hash_size = crounds = drounds = 0 means SipHash24 with 16-byte output */ +int SipHash_Init(SIPHASH *ctx, const unsigned char *k, int crounds, int drounds) +{ + uint64_t k0 = U8TO64_LE(k); + uint64_t k1 = U8TO64_LE(k + 8); + + /* If the hash size wasn't set, i.e. is zero */ + ctx->hash_size = siphash_adjust_hash_size(ctx->hash_size); + + if (drounds == 0) + drounds = SIPHASH_D_ROUNDS; + if (crounds == 0) + crounds = SIPHASH_C_ROUNDS; + + ctx->crounds = crounds; + ctx->drounds = drounds; + + ctx->len = 0; + ctx->total_inlen = 0; + + ctx->v0 = 0x736f6d6570736575ULL ^ k0; + ctx->v1 = 0x646f72616e646f6dULL ^ k1; + ctx->v2 = 0x6c7967656e657261ULL ^ k0; + ctx->v3 = 0x7465646279746573ULL ^ k1; + + if (ctx->hash_size == SIPHASH_MAX_DIGEST_SIZE) + ctx->v1 ^= 0xee; + + return 1; +} + +void SipHash_Update(SIPHASH *ctx, const unsigned char *in, size_t inlen) +{ + uint64_t m; + const uint8_t *end; + int left; + int i; + uint64_t v0 = ctx->v0; + uint64_t v1 = ctx->v1; + uint64_t v2 = ctx->v2; + uint64_t v3 = ctx->v3; + + ctx->total_inlen += inlen; + + if (ctx->len) { + /* deal with leavings */ + size_t available = SIPHASH_BLOCK_SIZE - ctx->len; + + /* not enough to fill leavings */ + if (inlen < available) { + memcpy(&ctx->leavings[ctx->len], in, inlen); + ctx->len += inlen; + return; + } + + /* copy data into leavings and reduce input */ + memcpy(&ctx->leavings[ctx->len], in, available); + inlen -= available; + in += available; + + /* process leavings */ + m = U8TO64_LE(ctx->leavings); + v3 ^= m; + for (i = 0; i < ctx->crounds; ++i) + SIPROUND; + v0 ^= m; + } + left = inlen & (SIPHASH_BLOCK_SIZE-1); /* gets put into leavings */ + end = in + inlen - left; + + for (; in != end; in += 8) { + m = U8TO64_LE(in); + v3 ^= m; + for (i = 0; i < ctx->crounds; ++i) + SIPROUND; + v0 ^= m; + } + + /* save leavings and other ctx */ + if (left) + memcpy(ctx->leavings, end, left); + ctx->len = left; + + ctx->v0 = v0; + ctx->v1 = v1; + ctx->v2 = v2; + ctx->v3 = v3; +} + +int SipHash_Final(SIPHASH *ctx, unsigned char *out, size_t outlen) +{ + /* finalize hash */ + int i; + uint64_t b = ctx->total_inlen << 56; + uint64_t v0 = ctx->v0; + uint64_t v1 = ctx->v1; + uint64_t v2 = ctx->v2; + uint64_t v3 = ctx->v3; + + if (outlen != (size_t)ctx->hash_size) + return 0; + + switch (ctx->len) { + case 7: + b |= ((uint64_t)ctx->leavings[6]) << 48; + /* fall thru */ + case 6: + b |= ((uint64_t)ctx->leavings[5]) << 40; + /* fall thru */ + case 5: + b |= ((uint64_t)ctx->leavings[4]) << 32; + /* fall thru */ + case 4: + b |= ((uint64_t)ctx->leavings[3]) << 24; + /* fall thru */ + case 3: + b |= ((uint64_t)ctx->leavings[2]) << 16; + /* fall thru */ + case 2: + b |= ((uint64_t)ctx->leavings[1]) << 8; + /* fall thru */ + case 1: + b |= ((uint64_t)ctx->leavings[0]); + case 0: + break; + } + + v3 ^= b; + for (i = 0; i < ctx->crounds; ++i) + SIPROUND; + v0 ^= b; + if (ctx->hash_size == SIPHASH_MAX_DIGEST_SIZE) + v2 ^= 0xee; + else + v2 ^= 0xff; + for (i = 0; i < ctx->drounds; ++i) + SIPROUND; + b = v0 ^ v1 ^ v2 ^ v3; + U64TO8_LE(out, b); + if (ctx->hash_size == SIPHASH_MIN_DIGEST_SIZE) + return 1; + v1 ^= 0xdd; + for (i = 0; i < ctx->drounds; ++i) + SIPROUND; + b = v0 ^ v1 ^ v2 ^ v3; + U64TO8_LE(out + 8, b); + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/siphash/siphash_ameth.c b/trunk/3rdparty/openssl-1.1-fit/crypto/siphash/siphash_ameth.c new file mode 100644 index 000000000..c0ab7efae --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/siphash/siphash_ameth.c @@ -0,0 +1,123 @@ +/* + * Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include "internal/asn1_int.h" +#include "internal/siphash.h" +#include "siphash_local.h" +#include "internal/evp_int.h" + +/* + * SIPHASH "ASN1" method. This is just here to indicate the maximum + * SIPHASH output length and to free up a SIPHASH key. + */ + +static int siphash_size(const EVP_PKEY *pkey) +{ + return SIPHASH_MAX_DIGEST_SIZE; +} + +static void siphash_key_free(EVP_PKEY *pkey) +{ + ASN1_OCTET_STRING *os = EVP_PKEY_get0(pkey); + + if (os != NULL) { + if (os->data != NULL) + OPENSSL_cleanse(os->data, os->length); + ASN1_OCTET_STRING_free(os); + } +} + +static int siphash_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) +{ + /* nothing (including ASN1_PKEY_CTRL_DEFAULT_MD_NID), is supported */ + return -2; +} + +static int siphash_pkey_public_cmp(const EVP_PKEY *a, const EVP_PKEY *b) +{ + return ASN1_OCTET_STRING_cmp(EVP_PKEY_get0(a), EVP_PKEY_get0(b)); +} + +static int siphash_set_priv_key(EVP_PKEY *pkey, const unsigned char *priv, + size_t len) +{ + ASN1_OCTET_STRING *os; + + if (pkey->pkey.ptr != NULL || len != SIPHASH_KEY_SIZE) + return 0; + + os = ASN1_OCTET_STRING_new(); + if (os == NULL) + return 0; + + if (!ASN1_OCTET_STRING_set(os, priv, len)) { + ASN1_OCTET_STRING_free(os); + return 0; + } + + pkey->pkey.ptr = os; + return 1; +} + +static int siphash_get_priv_key(const EVP_PKEY *pkey, unsigned char *priv, + size_t *len) +{ + ASN1_OCTET_STRING *os = (ASN1_OCTET_STRING *)pkey->pkey.ptr; + + if (priv == NULL) { + *len = SIPHASH_KEY_SIZE; + return 1; + } + + if (os == NULL || *len < SIPHASH_KEY_SIZE) + return 0; + + memcpy(priv, ASN1_STRING_get0_data(os), ASN1_STRING_length(os)); + *len = SIPHASH_KEY_SIZE; + + return 1; +} + +const EVP_PKEY_ASN1_METHOD siphash_asn1_meth = { + EVP_PKEY_SIPHASH, + EVP_PKEY_SIPHASH, + 0, + + "SIPHASH", + "OpenSSL SIPHASH method", + + 0, 0, siphash_pkey_public_cmp, 0, + + 0, 0, 0, + + siphash_size, + 0, 0, + 0, 0, 0, 0, 0, 0, 0, + + siphash_key_free, + siphash_pkey_ctrl, + NULL, + NULL, + + NULL, + NULL, + NULL, + + NULL, + NULL, + NULL, + + siphash_set_priv_key, + NULL, + siphash_get_priv_key, + NULL, +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/siphash/siphash_local.h b/trunk/3rdparty/openssl-1.1-fit/crypto/siphash/siphash_local.h new file mode 100644 index 000000000..5ad347646 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/siphash/siphash_local.h @@ -0,0 +1,23 @@ +/* + * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Based on https://131002.net/siphash C reference implementation */ + +struct siphash_st { + uint64_t total_inlen; + uint64_t v0; + uint64_t v1; + uint64_t v2; + uint64_t v3; + unsigned int len; + int hash_size; + int crounds; + int drounds; + unsigned char leavings[SIPHASH_BLOCK_SIZE]; +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/siphash/siphash_pmeth.c b/trunk/3rdparty/openssl-1.1-fit/crypto/siphash/siphash_pmeth.c new file mode 100644 index 000000000..66e552fec --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/siphash/siphash_pmeth.c @@ -0,0 +1,205 @@ +/* + * Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "internal/siphash.h" +#include "siphash_local.h" +#include "internal/evp_int.h" + +/* SIPHASH pkey context structure */ + +typedef struct siphash_pkey_ctx_st { + ASN1_OCTET_STRING ktmp; /* Temp storage for key */ + SIPHASH ctx; +} SIPHASH_PKEY_CTX; + +static int pkey_siphash_init(EVP_PKEY_CTX *ctx) +{ + SIPHASH_PKEY_CTX *pctx; + + if ((pctx = OPENSSL_zalloc(sizeof(*pctx))) == NULL) { + CRYPTOerr(CRYPTO_F_PKEY_SIPHASH_INIT, ERR_R_MALLOC_FAILURE); + return 0; + } + pctx->ktmp.type = V_ASN1_OCTET_STRING; + + EVP_PKEY_CTX_set_data(ctx, pctx); + EVP_PKEY_CTX_set0_keygen_info(ctx, NULL, 0); + return 1; +} + +static void pkey_siphash_cleanup(EVP_PKEY_CTX *ctx) +{ + SIPHASH_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx); + + if (pctx != NULL) { + OPENSSL_clear_free(pctx->ktmp.data, pctx->ktmp.length); + OPENSSL_clear_free(pctx, sizeof(*pctx)); + EVP_PKEY_CTX_set_data(ctx, NULL); + } +} + +static int pkey_siphash_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) +{ + SIPHASH_PKEY_CTX *sctx, *dctx; + + /* allocate memory for dst->data and a new SIPHASH_CTX in dst->data->ctx */ + if (!pkey_siphash_init(dst)) + return 0; + sctx = EVP_PKEY_CTX_get_data(src); + dctx = EVP_PKEY_CTX_get_data(dst); + if (ASN1_STRING_get0_data(&sctx->ktmp) != NULL && + !ASN1_STRING_copy(&dctx->ktmp, &sctx->ktmp)) { + /* cleanup and free the SIPHASH_PKEY_CTX in dst->data */ + pkey_siphash_cleanup(dst); + return 0; + } + memcpy(&dctx->ctx, &sctx->ctx, sizeof(SIPHASH)); + return 1; +} + +static int pkey_siphash_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) +{ + ASN1_OCTET_STRING *key; + SIPHASH_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx); + + if (ASN1_STRING_get0_data(&pctx->ktmp) == NULL) + return 0; + key = ASN1_OCTET_STRING_dup(&pctx->ktmp); + if (key == NULL) + return 0; + return EVP_PKEY_assign_SIPHASH(pkey, key); +} + +static int int_update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ + SIPHASH_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(EVP_MD_CTX_pkey_ctx(ctx)); + + SipHash_Update(&pctx->ctx, data, count); + return 1; +} + +static int siphash_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx) +{ + SIPHASH_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx); + const unsigned char* key; + size_t len; + + key = EVP_PKEY_get0_siphash(EVP_PKEY_CTX_get0_pkey(ctx), &len); + if (key == NULL || len != SIPHASH_KEY_SIZE) + return 0; + EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT); + EVP_MD_CTX_set_update_fn(mctx, int_update); + return SipHash_Init(&pctx->ctx, key, 0, 0); +} +static int siphash_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, + EVP_MD_CTX *mctx) +{ + SIPHASH_PKEY_CTX *pctx = ctx->data; + + *siglen = SipHash_hash_size(&pctx->ctx); + if (sig != NULL) + return SipHash_Final(&pctx->ctx, sig, *siglen); + return 1; +} + +static int pkey_siphash_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) +{ + SIPHASH_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx); + const unsigned char *key; + size_t len; + + switch (type) { + + case EVP_PKEY_CTRL_MD: + /* ignore */ + break; + + case EVP_PKEY_CTRL_SET_DIGEST_SIZE: + return SipHash_set_hash_size(&pctx->ctx, p1); + + case EVP_PKEY_CTRL_SET_MAC_KEY: + case EVP_PKEY_CTRL_DIGESTINIT: + if (type == EVP_PKEY_CTRL_SET_MAC_KEY) { + /* user explicitly setting the key */ + key = p2; + len = p1; + } else { + /* user indirectly setting the key via EVP_DigestSignInit */ + key = EVP_PKEY_get0_siphash(EVP_PKEY_CTX_get0_pkey(ctx), &len); + } + if (key == NULL || len != SIPHASH_KEY_SIZE || + !ASN1_OCTET_STRING_set(&pctx->ktmp, key, len)) + return 0; + /* use default rounds (2,4) */ + return SipHash_Init(&pctx->ctx, ASN1_STRING_get0_data(&pctx->ktmp), + 0, 0); + + default: + return -2; + + } + return 1; +} + +static int pkey_siphash_ctrl_str(EVP_PKEY_CTX *ctx, + const char *type, const char *value) +{ + if (value == NULL) + return 0; + if (strcmp(type, "digestsize") == 0) { + size_t hash_size = atoi(value); + + return pkey_siphash_ctrl(ctx, EVP_PKEY_CTRL_SET_DIGEST_SIZE, hash_size, + NULL); + } + if (strcmp(type, "key") == 0) + return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value); + if (strcmp(type, "hexkey") == 0) + return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value); + return -2; +} + +const EVP_PKEY_METHOD siphash_pkey_meth = { + EVP_PKEY_SIPHASH, + EVP_PKEY_FLAG_SIGCTX_CUSTOM, /* we don't deal with a separate MD */ + pkey_siphash_init, + pkey_siphash_copy, + pkey_siphash_cleanup, + + 0, 0, + + 0, + pkey_siphash_keygen, + + 0, 0, + + 0, 0, + + 0, 0, + + siphash_signctx_init, + siphash_signctx, + + 0, 0, + + 0, 0, + + 0, 0, + + 0, 0, + + pkey_siphash_ctrl, + pkey_siphash_ctrl_str +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sm2/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/sm2/build.info new file mode 100644 index 000000000..be76d96d3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sm2/build.info @@ -0,0 +1,5 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + sm2_sign.c sm2_crypt.c sm2_err.c sm2_pmeth.c + + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sm2/sm2_crypt.c b/trunk/3rdparty/openssl-1.1-fit/crypto/sm2/sm2_crypt.c new file mode 100644 index 000000000..4389fc731 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sm2/sm2_crypt.c @@ -0,0 +1,393 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017 Ribose Inc. All Rights Reserved. + * Ported from Ribose contributions from Botan. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/sm2.h" +#include "internal/sm2err.h" +#include "internal/ec_int.h" /* ecdh_KDF_X9_63() */ +#include +#include +#include +#include +#include +#include + +typedef struct SM2_Ciphertext_st SM2_Ciphertext; +DECLARE_ASN1_FUNCTIONS(SM2_Ciphertext) + +struct SM2_Ciphertext_st { + BIGNUM *C1x; + BIGNUM *C1y; + ASN1_OCTET_STRING *C3; + ASN1_OCTET_STRING *C2; +}; + +ASN1_SEQUENCE(SM2_Ciphertext) = { + ASN1_SIMPLE(SM2_Ciphertext, C1x, BIGNUM), + ASN1_SIMPLE(SM2_Ciphertext, C1y, BIGNUM), + ASN1_SIMPLE(SM2_Ciphertext, C3, ASN1_OCTET_STRING), + ASN1_SIMPLE(SM2_Ciphertext, C2, ASN1_OCTET_STRING), +} ASN1_SEQUENCE_END(SM2_Ciphertext) + +IMPLEMENT_ASN1_FUNCTIONS(SM2_Ciphertext) + +static size_t ec_field_size(const EC_GROUP *group) +{ + /* Is there some simpler way to do this? */ + BIGNUM *p = BN_new(); + BIGNUM *a = BN_new(); + BIGNUM *b = BN_new(); + size_t field_size = 0; + + if (p == NULL || a == NULL || b == NULL) + goto done; + + if (!EC_GROUP_get_curve(group, p, a, b, NULL)) + goto done; + field_size = (BN_num_bits(p) + 7) / 8; + + done: + BN_free(p); + BN_free(a); + BN_free(b); + + return field_size; +} + +int sm2_plaintext_size(const EC_KEY *key, const EVP_MD *digest, size_t msg_len, + size_t *pt_size) +{ + const size_t field_size = ec_field_size(EC_KEY_get0_group(key)); + const int md_size = EVP_MD_size(digest); + size_t overhead; + + if (md_size < 0) { + SM2err(SM2_F_SM2_PLAINTEXT_SIZE, SM2_R_INVALID_DIGEST); + return 0; + } + if (field_size == 0) { + SM2err(SM2_F_SM2_PLAINTEXT_SIZE, SM2_R_INVALID_FIELD); + return 0; + } + + overhead = 10 + 2 * field_size + (size_t)md_size; + if (msg_len <= overhead) { + SM2err(SM2_F_SM2_PLAINTEXT_SIZE, SM2_R_INVALID_ENCODING); + return 0; + } + + *pt_size = msg_len - overhead; + return 1; +} + +int sm2_ciphertext_size(const EC_KEY *key, const EVP_MD *digest, size_t msg_len, + size_t *ct_size) +{ + const size_t field_size = ec_field_size(EC_KEY_get0_group(key)); + const int md_size = EVP_MD_size(digest); + size_t sz; + + if (field_size == 0 || md_size < 0) + return 0; + + /* Integer and string are simple type; set constructed = 0, means primitive and definite length encoding. */ + sz = 2 * ASN1_object_size(0, field_size + 1, V_ASN1_INTEGER) + + ASN1_object_size(0, md_size, V_ASN1_OCTET_STRING) + + ASN1_object_size(0, msg_len, V_ASN1_OCTET_STRING); + /* Sequence is structured type; set constructed = 1, means constructed and definite length encoding. */ + *ct_size = ASN1_object_size(1, sz, V_ASN1_SEQUENCE); + + return 1; +} + +int sm2_encrypt(const EC_KEY *key, + const EVP_MD *digest, + const uint8_t *msg, + size_t msg_len, uint8_t *ciphertext_buf, size_t *ciphertext_len) +{ + int rc = 0, ciphertext_leni; + size_t i; + BN_CTX *ctx = NULL; + BIGNUM *k = NULL; + BIGNUM *x1 = NULL; + BIGNUM *y1 = NULL; + BIGNUM *x2 = NULL; + BIGNUM *y2 = NULL; + EVP_MD_CTX *hash = EVP_MD_CTX_new(); + struct SM2_Ciphertext_st ctext_struct; + const EC_GROUP *group = EC_KEY_get0_group(key); + const BIGNUM *order = EC_GROUP_get0_order(group); + const EC_POINT *P = EC_KEY_get0_public_key(key); + EC_POINT *kG = NULL; + EC_POINT *kP = NULL; + uint8_t *msg_mask = NULL; + uint8_t *x2y2 = NULL; + uint8_t *C3 = NULL; + size_t field_size; + const int C3_size = EVP_MD_size(digest); + + /* NULL these before any "goto done" */ + ctext_struct.C2 = NULL; + ctext_struct.C3 = NULL; + + if (hash == NULL || C3_size <= 0) { + SM2err(SM2_F_SM2_ENCRYPT, ERR_R_INTERNAL_ERROR); + goto done; + } + + field_size = ec_field_size(group); + if (field_size == 0) { + SM2err(SM2_F_SM2_ENCRYPT, ERR_R_INTERNAL_ERROR); + goto done; + } + + kG = EC_POINT_new(group); + kP = EC_POINT_new(group); + ctx = BN_CTX_new(); + if (kG == NULL || kP == NULL || ctx == NULL) { + SM2err(SM2_F_SM2_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto done; + } + + BN_CTX_start(ctx); + k = BN_CTX_get(ctx); + x1 = BN_CTX_get(ctx); + x2 = BN_CTX_get(ctx); + y1 = BN_CTX_get(ctx); + y2 = BN_CTX_get(ctx); + + if (y2 == NULL) { + SM2err(SM2_F_SM2_ENCRYPT, ERR_R_BN_LIB); + goto done; + } + + x2y2 = OPENSSL_zalloc(2 * field_size); + C3 = OPENSSL_zalloc(C3_size); + + if (x2y2 == NULL || C3 == NULL) { + SM2err(SM2_F_SM2_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto done; + } + + memset(ciphertext_buf, 0, *ciphertext_len); + + if (!BN_priv_rand_range(k, order)) { + SM2err(SM2_F_SM2_ENCRYPT, ERR_R_INTERNAL_ERROR); + goto done; + } + + if (!EC_POINT_mul(group, kG, k, NULL, NULL, ctx) + || !EC_POINT_get_affine_coordinates(group, kG, x1, y1, ctx) + || !EC_POINT_mul(group, kP, NULL, P, k, ctx) + || !EC_POINT_get_affine_coordinates(group, kP, x2, y2, ctx)) { + SM2err(SM2_F_SM2_ENCRYPT, ERR_R_EC_LIB); + goto done; + } + + if (BN_bn2binpad(x2, x2y2, field_size) < 0 + || BN_bn2binpad(y2, x2y2 + field_size, field_size) < 0) { + SM2err(SM2_F_SM2_ENCRYPT, ERR_R_INTERNAL_ERROR); + goto done; + } + + msg_mask = OPENSSL_zalloc(msg_len); + if (msg_mask == NULL) { + SM2err(SM2_F_SM2_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto done; + } + + /* X9.63 with no salt happens to match the KDF used in SM2 */ + if (!ecdh_KDF_X9_63(msg_mask, msg_len, x2y2, 2 * field_size, NULL, 0, + digest)) { + SM2err(SM2_F_SM2_ENCRYPT, ERR_R_EVP_LIB); + goto done; + } + + for (i = 0; i != msg_len; ++i) + msg_mask[i] ^= msg[i]; + + if (EVP_DigestInit(hash, digest) == 0 + || EVP_DigestUpdate(hash, x2y2, field_size) == 0 + || EVP_DigestUpdate(hash, msg, msg_len) == 0 + || EVP_DigestUpdate(hash, x2y2 + field_size, field_size) == 0 + || EVP_DigestFinal(hash, C3, NULL) == 0) { + SM2err(SM2_F_SM2_ENCRYPT, ERR_R_EVP_LIB); + goto done; + } + + ctext_struct.C1x = x1; + ctext_struct.C1y = y1; + ctext_struct.C3 = ASN1_OCTET_STRING_new(); + ctext_struct.C2 = ASN1_OCTET_STRING_new(); + + if (ctext_struct.C3 == NULL || ctext_struct.C2 == NULL) { + SM2err(SM2_F_SM2_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto done; + } + if (!ASN1_OCTET_STRING_set(ctext_struct.C3, C3, C3_size) + || !ASN1_OCTET_STRING_set(ctext_struct.C2, msg_mask, msg_len)) { + SM2err(SM2_F_SM2_ENCRYPT, ERR_R_INTERNAL_ERROR); + goto done; + } + + ciphertext_leni = i2d_SM2_Ciphertext(&ctext_struct, &ciphertext_buf); + /* Ensure cast to size_t is safe */ + if (ciphertext_leni < 0) { + SM2err(SM2_F_SM2_ENCRYPT, ERR_R_INTERNAL_ERROR); + goto done; + } + *ciphertext_len = (size_t)ciphertext_leni; + + rc = 1; + + done: + ASN1_OCTET_STRING_free(ctext_struct.C2); + ASN1_OCTET_STRING_free(ctext_struct.C3); + OPENSSL_free(msg_mask); + OPENSSL_free(x2y2); + OPENSSL_free(C3); + EVP_MD_CTX_free(hash); + BN_CTX_free(ctx); + EC_POINT_free(kG); + EC_POINT_free(kP); + return rc; +} + +int sm2_decrypt(const EC_KEY *key, + const EVP_MD *digest, + const uint8_t *ciphertext, + size_t ciphertext_len, uint8_t *ptext_buf, size_t *ptext_len) +{ + int rc = 0; + int i; + BN_CTX *ctx = NULL; + const EC_GROUP *group = EC_KEY_get0_group(key); + EC_POINT *C1 = NULL; + struct SM2_Ciphertext_st *sm2_ctext = NULL; + BIGNUM *x2 = NULL; + BIGNUM *y2 = NULL; + uint8_t *x2y2 = NULL; + uint8_t *computed_C3 = NULL; + const size_t field_size = ec_field_size(group); + const int hash_size = EVP_MD_size(digest); + uint8_t *msg_mask = NULL; + const uint8_t *C2 = NULL; + const uint8_t *C3 = NULL; + int msg_len = 0; + EVP_MD_CTX *hash = NULL; + + if (field_size == 0 || hash_size <= 0) + goto done; + + memset(ptext_buf, 0xFF, *ptext_len); + + sm2_ctext = d2i_SM2_Ciphertext(NULL, &ciphertext, ciphertext_len); + + if (sm2_ctext == NULL) { + SM2err(SM2_F_SM2_DECRYPT, SM2_R_ASN1_ERROR); + goto done; + } + + if (sm2_ctext->C3->length != hash_size) { + SM2err(SM2_F_SM2_DECRYPT, SM2_R_INVALID_ENCODING); + goto done; + } + + C2 = sm2_ctext->C2->data; + C3 = sm2_ctext->C3->data; + msg_len = sm2_ctext->C2->length; + + ctx = BN_CTX_new(); + if (ctx == NULL) { + SM2err(SM2_F_SM2_DECRYPT, ERR_R_MALLOC_FAILURE); + goto done; + } + + BN_CTX_start(ctx); + x2 = BN_CTX_get(ctx); + y2 = BN_CTX_get(ctx); + + if (y2 == NULL) { + SM2err(SM2_F_SM2_DECRYPT, ERR_R_BN_LIB); + goto done; + } + + msg_mask = OPENSSL_zalloc(msg_len); + x2y2 = OPENSSL_zalloc(2 * field_size); + computed_C3 = OPENSSL_zalloc(hash_size); + + if (msg_mask == NULL || x2y2 == NULL || computed_C3 == NULL) { + SM2err(SM2_F_SM2_DECRYPT, ERR_R_MALLOC_FAILURE); + goto done; + } + + C1 = EC_POINT_new(group); + if (C1 == NULL) { + SM2err(SM2_F_SM2_DECRYPT, ERR_R_MALLOC_FAILURE); + goto done; + } + + if (!EC_POINT_set_affine_coordinates(group, C1, sm2_ctext->C1x, + sm2_ctext->C1y, ctx) + || !EC_POINT_mul(group, C1, NULL, C1, EC_KEY_get0_private_key(key), + ctx) + || !EC_POINT_get_affine_coordinates(group, C1, x2, y2, ctx)) { + SM2err(SM2_F_SM2_DECRYPT, ERR_R_EC_LIB); + goto done; + } + + if (BN_bn2binpad(x2, x2y2, field_size) < 0 + || BN_bn2binpad(y2, x2y2 + field_size, field_size) < 0 + || !ecdh_KDF_X9_63(msg_mask, msg_len, x2y2, 2 * field_size, NULL, 0, + digest)) { + SM2err(SM2_F_SM2_DECRYPT, ERR_R_INTERNAL_ERROR); + goto done; + } + + for (i = 0; i != msg_len; ++i) + ptext_buf[i] = C2[i] ^ msg_mask[i]; + + hash = EVP_MD_CTX_new(); + if (hash == NULL) { + SM2err(SM2_F_SM2_DECRYPT, ERR_R_MALLOC_FAILURE); + goto done; + } + + if (!EVP_DigestInit(hash, digest) + || !EVP_DigestUpdate(hash, x2y2, field_size) + || !EVP_DigestUpdate(hash, ptext_buf, msg_len) + || !EVP_DigestUpdate(hash, x2y2 + field_size, field_size) + || !EVP_DigestFinal(hash, computed_C3, NULL)) { + SM2err(SM2_F_SM2_DECRYPT, ERR_R_EVP_LIB); + goto done; + } + + if (CRYPTO_memcmp(computed_C3, C3, hash_size) != 0) { + SM2err(SM2_F_SM2_DECRYPT, SM2_R_INVALID_DIGEST); + goto done; + } + + rc = 1; + *ptext_len = msg_len; + + done: + if (rc == 0) + memset(ptext_buf, 0, *ptext_len); + + OPENSSL_free(msg_mask); + OPENSSL_free(x2y2); + OPENSSL_free(computed_C3); + EC_POINT_free(C1); + BN_CTX_free(ctx); + SM2_Ciphertext_free(sm2_ctext); + EVP_MD_CTX_free(hash); + + return rc; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sm2/sm2_err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/sm2/sm2_err.c new file mode 100644 index 000000000..653c6797f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sm2/sm2_err.c @@ -0,0 +1,69 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/sm2err.h" + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA SM2_str_functs[] = { + {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_COPY, 0), "pkey_sm2_copy"}, + {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_CTRL, 0), "pkey_sm2_ctrl"}, + {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_CTRL_STR, 0), "pkey_sm2_ctrl_str"}, + {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_DIGEST_CUSTOM, 0), + "pkey_sm2_digest_custom"}, + {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_INIT, 0), "pkey_sm2_init"}, + {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_SIGN, 0), "pkey_sm2_sign"}, + {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_COMPUTE_MSG_HASH, 0), + "sm2_compute_msg_hash"}, + {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_COMPUTE_USERID_DIGEST, 0), + "sm2_compute_userid_digest"}, + {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_COMPUTE_Z_DIGEST, 0), + "sm2_compute_z_digest"}, + {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_DECRYPT, 0), "sm2_decrypt"}, + {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_ENCRYPT, 0), "sm2_encrypt"}, + {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_PLAINTEXT_SIZE, 0), "sm2_plaintext_size"}, + {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_SIGN, 0), "sm2_sign"}, + {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_SIG_GEN, 0), "sm2_sig_gen"}, + {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_SIG_VERIFY, 0), "sm2_sig_verify"}, + {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_VERIFY, 0), "sm2_verify"}, + {0, NULL} +}; + +static const ERR_STRING_DATA SM2_str_reasons[] = { + {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_ASN1_ERROR), "asn1 error"}, + {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_BAD_SIGNATURE), "bad signature"}, + {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_BUFFER_TOO_SMALL), "buffer too small"}, + {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_DIST_ID_TOO_LARGE), "dist id too large"}, + {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_ID_NOT_SET), "id not set"}, + {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_ID_TOO_LARGE), "id too large"}, + {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_CURVE), "invalid curve"}, + {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_DIGEST), "invalid digest"}, + {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_DIGEST_TYPE), + "invalid digest type"}, + {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_ENCODING), "invalid encoding"}, + {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_FIELD), "invalid field"}, + {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_NO_PARAMETERS_SET), "no parameters set"}, + {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_USER_ID_TOO_LARGE), "user id too large"}, + {0, NULL} +}; + +#endif + +int ERR_load_SM2_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(SM2_str_functs[0].error) == NULL) { + ERR_load_strings_const(SM2_str_functs); + ERR_load_strings_const(SM2_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sm2/sm2_pmeth.c b/trunk/3rdparty/openssl-1.1-fit/crypto/sm2/sm2_pmeth.c new file mode 100644 index 000000000..d187699cc --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sm2/sm2_pmeth.c @@ -0,0 +1,325 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include +#include +#include +#include "internal/evp_int.h" +#include "internal/sm2.h" +#include "internal/sm2err.h" + +/* EC pkey context structure */ + +typedef struct { + /* Key and paramgen group */ + EC_GROUP *gen_group; + /* message digest */ + const EVP_MD *md; + /* Distinguishing Identifier, ISO/IEC 15946-3 */ + uint8_t *id; + size_t id_len; + /* id_set indicates if the 'id' field is set (1) or not (0) */ + int id_set; +} SM2_PKEY_CTX; + +static int pkey_sm2_init(EVP_PKEY_CTX *ctx) +{ + SM2_PKEY_CTX *smctx; + + if ((smctx = OPENSSL_zalloc(sizeof(*smctx))) == NULL) { + SM2err(SM2_F_PKEY_SM2_INIT, ERR_R_MALLOC_FAILURE); + return 0; + } + + ctx->data = smctx; + return 1; +} + +static void pkey_sm2_cleanup(EVP_PKEY_CTX *ctx) +{ + SM2_PKEY_CTX *smctx = ctx->data; + + if (smctx != NULL) { + EC_GROUP_free(smctx->gen_group); + OPENSSL_free(smctx->id); + OPENSSL_free(smctx); + ctx->data = NULL; + } +} + +static int pkey_sm2_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) +{ + SM2_PKEY_CTX *dctx, *sctx; + + if (!pkey_sm2_init(dst)) + return 0; + sctx = src->data; + dctx = dst->data; + if (sctx->gen_group != NULL) { + dctx->gen_group = EC_GROUP_dup(sctx->gen_group); + if (dctx->gen_group == NULL) { + pkey_sm2_cleanup(dst); + return 0; + } + } + if (sctx->id != NULL) { + dctx->id = OPENSSL_malloc(sctx->id_len); + if (dctx->id == NULL) { + SM2err(SM2_F_PKEY_SM2_COPY, ERR_R_MALLOC_FAILURE); + pkey_sm2_cleanup(dst); + return 0; + } + memcpy(dctx->id, sctx->id, sctx->id_len); + } + dctx->id_len = sctx->id_len; + dctx->id_set = sctx->id_set; + dctx->md = sctx->md; + + return 1; +} + +static int pkey_sm2_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbslen) +{ + int ret; + unsigned int sltmp; + EC_KEY *ec = ctx->pkey->pkey.ec; + const int sig_sz = ECDSA_size(ctx->pkey->pkey.ec); + + if (sig_sz <= 0) { + return 0; + } + + if (sig == NULL) { + *siglen = (size_t)sig_sz; + return 1; + } + + if (*siglen < (size_t)sig_sz) { + SM2err(SM2_F_PKEY_SM2_SIGN, SM2_R_BUFFER_TOO_SMALL); + return 0; + } + + ret = sm2_sign(tbs, tbslen, sig, &sltmp, ec); + + if (ret <= 0) + return ret; + *siglen = (size_t)sltmp; + return 1; +} + +static int pkey_sm2_verify(EVP_PKEY_CTX *ctx, + const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen) +{ + EC_KEY *ec = ctx->pkey->pkey.ec; + + return sm2_verify(tbs, tbslen, sig, siglen, ec); +} + +static int pkey_sm2_encrypt(EVP_PKEY_CTX *ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen) +{ + EC_KEY *ec = ctx->pkey->pkey.ec; + SM2_PKEY_CTX *dctx = ctx->data; + const EVP_MD *md = (dctx->md == NULL) ? EVP_sm3() : dctx->md; + + if (out == NULL) { + if (!sm2_ciphertext_size(ec, md, inlen, outlen)) + return -1; + else + return 1; + } + + return sm2_encrypt(ec, md, in, inlen, out, outlen); +} + +static int pkey_sm2_decrypt(EVP_PKEY_CTX *ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen) +{ + EC_KEY *ec = ctx->pkey->pkey.ec; + SM2_PKEY_CTX *dctx = ctx->data; + const EVP_MD *md = (dctx->md == NULL) ? EVP_sm3() : dctx->md; + + if (out == NULL) { + if (!sm2_plaintext_size(ec, md, inlen, outlen)) + return -1; + else + return 1; + } + + return sm2_decrypt(ec, md, in, inlen, out, outlen); +} + +static int pkey_sm2_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) +{ + SM2_PKEY_CTX *smctx = ctx->data; + EC_GROUP *group; + uint8_t *tmp_id; + + switch (type) { + case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID: + group = EC_GROUP_new_by_curve_name(p1); + if (group == NULL) { + SM2err(SM2_F_PKEY_SM2_CTRL, SM2_R_INVALID_CURVE); + return 0; + } + EC_GROUP_free(smctx->gen_group); + smctx->gen_group = group; + return 1; + + case EVP_PKEY_CTRL_EC_PARAM_ENC: + if (smctx->gen_group == NULL) { + SM2err(SM2_F_PKEY_SM2_CTRL, SM2_R_NO_PARAMETERS_SET); + return 0; + } + EC_GROUP_set_asn1_flag(smctx->gen_group, p1); + return 1; + + case EVP_PKEY_CTRL_MD: + smctx->md = p2; + return 1; + + case EVP_PKEY_CTRL_GET_MD: + *(const EVP_MD **)p2 = smctx->md; + return 1; + + case EVP_PKEY_CTRL_SET1_ID: + if (p1 > 0) { + tmp_id = OPENSSL_malloc(p1); + if (tmp_id == NULL) { + SM2err(SM2_F_PKEY_SM2_CTRL, ERR_R_MALLOC_FAILURE); + return 0; + } + memcpy(tmp_id, p2, p1); + OPENSSL_free(smctx->id); + smctx->id = tmp_id; + } else { + /* set null-ID */ + OPENSSL_free(smctx->id); + smctx->id = NULL; + } + smctx->id_len = (size_t)p1; + smctx->id_set = 1; + return 1; + + case EVP_PKEY_CTRL_GET1_ID: + memcpy(p2, smctx->id, smctx->id_len); + return 1; + + case EVP_PKEY_CTRL_GET1_ID_LEN: + *(size_t *)p2 = smctx->id_len; + return 1; + + default: + return -2; + } +} + +static int pkey_sm2_ctrl_str(EVP_PKEY_CTX *ctx, + const char *type, const char *value) +{ + if (strcmp(type, "ec_paramgen_curve") == 0) { + int nid = NID_undef; + + if (((nid = EC_curve_nist2nid(value)) == NID_undef) + && ((nid = OBJ_sn2nid(value)) == NID_undef) + && ((nid = OBJ_ln2nid(value)) == NID_undef)) { + SM2err(SM2_F_PKEY_SM2_CTRL_STR, SM2_R_INVALID_CURVE); + return 0; + } + return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid); + } else if (strcmp(type, "ec_param_enc") == 0) { + int param_enc; + + if (strcmp(value, "explicit") == 0) + param_enc = 0; + else if (strcmp(value, "named_curve") == 0) + param_enc = OPENSSL_EC_NAMED_CURVE; + else + return -2; + return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc); + } + + return -2; +} + +static int pkey_sm2_digest_custom(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx) +{ + uint8_t z[EVP_MAX_MD_SIZE]; + SM2_PKEY_CTX *smctx = ctx->data; + EC_KEY *ec = ctx->pkey->pkey.ec; + const EVP_MD *md = EVP_MD_CTX_md(mctx); + int mdlen = EVP_MD_size(md); + + if (!smctx->id_set) { + /* + * An ID value must be set. The specifications are not clear whether a + * NULL is allowed. We only allow it if set explicitly for maximum + * flexibility. + */ + SM2err(SM2_F_PKEY_SM2_DIGEST_CUSTOM, SM2_R_ID_NOT_SET); + return 0; + } + + if (mdlen < 0) { + SM2err(SM2_F_PKEY_SM2_DIGEST_CUSTOM, SM2_R_INVALID_DIGEST); + return 0; + } + + /* get hashed prefix 'z' of tbs message */ + if (!sm2_compute_z_digest(z, md, smctx->id, smctx->id_len, ec)) + return 0; + + return EVP_DigestUpdate(mctx, z, (size_t)mdlen); +} + +const EVP_PKEY_METHOD sm2_pkey_meth = { + EVP_PKEY_SM2, + 0, + pkey_sm2_init, + pkey_sm2_copy, + pkey_sm2_cleanup, + + 0, + 0, + + 0, + 0, + + 0, + pkey_sm2_sign, + + 0, + pkey_sm2_verify, + + 0, 0, + + 0, 0, 0, 0, + + 0, + pkey_sm2_encrypt, + + 0, + pkey_sm2_decrypt, + + 0, + 0, + pkey_sm2_ctrl, + pkey_sm2_ctrl_str, + + 0, 0, + + 0, 0, 0, + + pkey_sm2_digest_custom +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sm2/sm2_sign.c b/trunk/3rdparty/openssl-1.1-fit/crypto/sm2/sm2_sign.c new file mode 100644 index 000000000..0f9c14cb5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sm2/sm2_sign.c @@ -0,0 +1,479 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017 Ribose Inc. All Rights Reserved. + * Ported from Ribose contributions from Botan. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/sm2.h" +#include "internal/sm2err.h" +#include "internal/ec_int.h" /* ec_group_do_inverse_ord() */ +#include "internal/numbers.h" +#include +#include +#include +#include +#include + +int sm2_compute_z_digest(uint8_t *out, + const EVP_MD *digest, + const uint8_t *id, + const size_t id_len, + const EC_KEY *key) +{ + int rc = 0; + const EC_GROUP *group = EC_KEY_get0_group(key); + BN_CTX *ctx = NULL; + EVP_MD_CTX *hash = NULL; + BIGNUM *p = NULL; + BIGNUM *a = NULL; + BIGNUM *b = NULL; + BIGNUM *xG = NULL; + BIGNUM *yG = NULL; + BIGNUM *xA = NULL; + BIGNUM *yA = NULL; + int p_bytes = 0; + uint8_t *buf = NULL; + uint16_t entl = 0; + uint8_t e_byte = 0; + + hash = EVP_MD_CTX_new(); + ctx = BN_CTX_new(); + if (hash == NULL || ctx == NULL) { + SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_MALLOC_FAILURE); + goto done; + } + + p = BN_CTX_get(ctx); + a = BN_CTX_get(ctx); + b = BN_CTX_get(ctx); + xG = BN_CTX_get(ctx); + yG = BN_CTX_get(ctx); + xA = BN_CTX_get(ctx); + yA = BN_CTX_get(ctx); + + if (yA == NULL) { + SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_MALLOC_FAILURE); + goto done; + } + + if (!EVP_DigestInit(hash, digest)) { + SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EVP_LIB); + goto done; + } + + /* Z = h(ENTL || ID || a || b || xG || yG || xA || yA) */ + + if (id_len >= (UINT16_MAX / 8)) { + /* too large */ + SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, SM2_R_ID_TOO_LARGE); + goto done; + } + + entl = (uint16_t)(8 * id_len); + + e_byte = entl >> 8; + if (!EVP_DigestUpdate(hash, &e_byte, 1)) { + SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EVP_LIB); + goto done; + } + e_byte = entl & 0xFF; + if (!EVP_DigestUpdate(hash, &e_byte, 1)) { + SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EVP_LIB); + goto done; + } + + if (id_len > 0 && !EVP_DigestUpdate(hash, id, id_len)) { + SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EVP_LIB); + goto done; + } + + if (!EC_GROUP_get_curve(group, p, a, b, ctx)) { + SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EC_LIB); + goto done; + } + + p_bytes = BN_num_bytes(p); + buf = OPENSSL_zalloc(p_bytes); + if (buf == NULL) { + SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_MALLOC_FAILURE); + goto done; + } + + if (BN_bn2binpad(a, buf, p_bytes) < 0 + || !EVP_DigestUpdate(hash, buf, p_bytes) + || BN_bn2binpad(b, buf, p_bytes) < 0 + || !EVP_DigestUpdate(hash, buf, p_bytes) + || !EC_POINT_get_affine_coordinates(group, + EC_GROUP_get0_generator(group), + xG, yG, ctx) + || BN_bn2binpad(xG, buf, p_bytes) < 0 + || !EVP_DigestUpdate(hash, buf, p_bytes) + || BN_bn2binpad(yG, buf, p_bytes) < 0 + || !EVP_DigestUpdate(hash, buf, p_bytes) + || !EC_POINT_get_affine_coordinates(group, + EC_KEY_get0_public_key(key), + xA, yA, ctx) + || BN_bn2binpad(xA, buf, p_bytes) < 0 + || !EVP_DigestUpdate(hash, buf, p_bytes) + || BN_bn2binpad(yA, buf, p_bytes) < 0 + || !EVP_DigestUpdate(hash, buf, p_bytes) + || !EVP_DigestFinal(hash, out, NULL)) { + SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_INTERNAL_ERROR); + goto done; + } + + rc = 1; + + done: + OPENSSL_free(buf); + BN_CTX_free(ctx); + EVP_MD_CTX_free(hash); + return rc; +} + +static BIGNUM *sm2_compute_msg_hash(const EVP_MD *digest, + const EC_KEY *key, + const uint8_t *id, + const size_t id_len, + const uint8_t *msg, size_t msg_len) +{ + EVP_MD_CTX *hash = EVP_MD_CTX_new(); + const int md_size = EVP_MD_size(digest); + uint8_t *z = NULL; + BIGNUM *e = NULL; + + if (md_size < 0) { + SM2err(SM2_F_SM2_COMPUTE_MSG_HASH, SM2_R_INVALID_DIGEST); + goto done; + } + + z = OPENSSL_zalloc(md_size); + if (hash == NULL || z == NULL) { + SM2err(SM2_F_SM2_COMPUTE_MSG_HASH, ERR_R_MALLOC_FAILURE); + goto done; + } + + if (!sm2_compute_z_digest(z, digest, id, id_len, key)) { + /* SM2err already called */ + goto done; + } + + if (!EVP_DigestInit(hash, digest) + || !EVP_DigestUpdate(hash, z, md_size) + || !EVP_DigestUpdate(hash, msg, msg_len) + /* reuse z buffer to hold H(Z || M) */ + || !EVP_DigestFinal(hash, z, NULL)) { + SM2err(SM2_F_SM2_COMPUTE_MSG_HASH, ERR_R_EVP_LIB); + goto done; + } + + e = BN_bin2bn(z, md_size, NULL); + if (e == NULL) + SM2err(SM2_F_SM2_COMPUTE_MSG_HASH, ERR_R_INTERNAL_ERROR); + + done: + OPENSSL_free(z); + EVP_MD_CTX_free(hash); + return e; +} + +static ECDSA_SIG *sm2_sig_gen(const EC_KEY *key, const BIGNUM *e) +{ + const BIGNUM *dA = EC_KEY_get0_private_key(key); + const EC_GROUP *group = EC_KEY_get0_group(key); + const BIGNUM *order = EC_GROUP_get0_order(group); + ECDSA_SIG *sig = NULL; + EC_POINT *kG = NULL; + BN_CTX *ctx = NULL; + BIGNUM *k = NULL; + BIGNUM *rk = NULL; + BIGNUM *r = NULL; + BIGNUM *s = NULL; + BIGNUM *x1 = NULL; + BIGNUM *tmp = NULL; + + kG = EC_POINT_new(group); + ctx = BN_CTX_new(); + if (kG == NULL || ctx == NULL) { + SM2err(SM2_F_SM2_SIG_GEN, ERR_R_MALLOC_FAILURE); + goto done; + } + + BN_CTX_start(ctx); + k = BN_CTX_get(ctx); + rk = BN_CTX_get(ctx); + x1 = BN_CTX_get(ctx); + tmp = BN_CTX_get(ctx); + if (tmp == NULL) { + SM2err(SM2_F_SM2_SIG_GEN, ERR_R_MALLOC_FAILURE); + goto done; + } + + /* + * These values are returned and so should not be allocated out of the + * context + */ + r = BN_new(); + s = BN_new(); + + if (r == NULL || s == NULL) { + SM2err(SM2_F_SM2_SIG_GEN, ERR_R_MALLOC_FAILURE); + goto done; + } + + for (;;) { + if (!BN_priv_rand_range(k, order)) { + SM2err(SM2_F_SM2_SIG_GEN, ERR_R_INTERNAL_ERROR); + goto done; + } + + if (!EC_POINT_mul(group, kG, k, NULL, NULL, ctx) + || !EC_POINT_get_affine_coordinates(group, kG, x1, NULL, + ctx) + || !BN_mod_add(r, e, x1, order, ctx)) { + SM2err(SM2_F_SM2_SIG_GEN, ERR_R_INTERNAL_ERROR); + goto done; + } + + /* try again if r == 0 or r+k == n */ + if (BN_is_zero(r)) + continue; + + if (!BN_add(rk, r, k)) { + SM2err(SM2_F_SM2_SIG_GEN, ERR_R_INTERNAL_ERROR); + goto done; + } + + if (BN_cmp(rk, order) == 0) + continue; + + if (!BN_add(s, dA, BN_value_one()) + || !ec_group_do_inverse_ord(group, s, s, ctx) + || !BN_mod_mul(tmp, dA, r, order, ctx) + || !BN_sub(tmp, k, tmp) + || !BN_mod_mul(s, s, tmp, order, ctx)) { + SM2err(SM2_F_SM2_SIG_GEN, ERR_R_BN_LIB); + goto done; + } + + sig = ECDSA_SIG_new(); + if (sig == NULL) { + SM2err(SM2_F_SM2_SIG_GEN, ERR_R_MALLOC_FAILURE); + goto done; + } + + /* takes ownership of r and s */ + ECDSA_SIG_set0(sig, r, s); + break; + } + + done: + if (sig == NULL) { + BN_free(r); + BN_free(s); + } + + BN_CTX_free(ctx); + EC_POINT_free(kG); + return sig; +} + +static int sm2_sig_verify(const EC_KEY *key, const ECDSA_SIG *sig, + const BIGNUM *e) +{ + int ret = 0; + const EC_GROUP *group = EC_KEY_get0_group(key); + const BIGNUM *order = EC_GROUP_get0_order(group); + BN_CTX *ctx = NULL; + EC_POINT *pt = NULL; + BIGNUM *t = NULL; + BIGNUM *x1 = NULL; + const BIGNUM *r = NULL; + const BIGNUM *s = NULL; + + ctx = BN_CTX_new(); + pt = EC_POINT_new(group); + if (ctx == NULL || pt == NULL) { + SM2err(SM2_F_SM2_SIG_VERIFY, ERR_R_MALLOC_FAILURE); + goto done; + } + + BN_CTX_start(ctx); + t = BN_CTX_get(ctx); + x1 = BN_CTX_get(ctx); + if (x1 == NULL) { + SM2err(SM2_F_SM2_SIG_VERIFY, ERR_R_MALLOC_FAILURE); + goto done; + } + + /* + * B1: verify whether r' in [1,n-1], verification failed if not + * B2: vefify whether s' in [1,n-1], verification failed if not + * B3: set M'~=ZA || M' + * B4: calculate e'=Hv(M'~) + * B5: calculate t = (r' + s') modn, verification failed if t=0 + * B6: calculate the point (x1', y1')=[s']G + [t]PA + * B7: calculate R=(e'+x1') modn, verfication pass if yes, otherwise failed + */ + + ECDSA_SIG_get0(sig, &r, &s); + + if (BN_cmp(r, BN_value_one()) < 0 + || BN_cmp(s, BN_value_one()) < 0 + || BN_cmp(order, r) <= 0 + || BN_cmp(order, s) <= 0) { + SM2err(SM2_F_SM2_SIG_VERIFY, SM2_R_BAD_SIGNATURE); + goto done; + } + + if (!BN_mod_add(t, r, s, order, ctx)) { + SM2err(SM2_F_SM2_SIG_VERIFY, ERR_R_BN_LIB); + goto done; + } + + if (BN_is_zero(t)) { + SM2err(SM2_F_SM2_SIG_VERIFY, SM2_R_BAD_SIGNATURE); + goto done; + } + + if (!EC_POINT_mul(group, pt, s, EC_KEY_get0_public_key(key), t, ctx) + || !EC_POINT_get_affine_coordinates(group, pt, x1, NULL, ctx)) { + SM2err(SM2_F_SM2_SIG_VERIFY, ERR_R_EC_LIB); + goto done; + } + + if (!BN_mod_add(t, e, x1, order, ctx)) { + SM2err(SM2_F_SM2_SIG_VERIFY, ERR_R_BN_LIB); + goto done; + } + + if (BN_cmp(r, t) == 0) + ret = 1; + + done: + EC_POINT_free(pt); + BN_CTX_free(ctx); + return ret; +} + +ECDSA_SIG *sm2_do_sign(const EC_KEY *key, + const EVP_MD *digest, + const uint8_t *id, + const size_t id_len, + const uint8_t *msg, size_t msg_len) +{ + BIGNUM *e = NULL; + ECDSA_SIG *sig = NULL; + + e = sm2_compute_msg_hash(digest, key, id, id_len, msg, msg_len); + if (e == NULL) { + /* SM2err already called */ + goto done; + } + + sig = sm2_sig_gen(key, e); + + done: + BN_free(e); + return sig; +} + +int sm2_do_verify(const EC_KEY *key, + const EVP_MD *digest, + const ECDSA_SIG *sig, + const uint8_t *id, + const size_t id_len, + const uint8_t *msg, size_t msg_len) +{ + BIGNUM *e = NULL; + int ret = 0; + + e = sm2_compute_msg_hash(digest, key, id, id_len, msg, msg_len); + if (e == NULL) { + /* SM2err already called */ + goto done; + } + + ret = sm2_sig_verify(key, sig, e); + + done: + BN_free(e); + return ret; +} + +int sm2_sign(const unsigned char *dgst, int dgstlen, + unsigned char *sig, unsigned int *siglen, EC_KEY *eckey) +{ + BIGNUM *e = NULL; + ECDSA_SIG *s = NULL; + int sigleni; + int ret = -1; + + e = BN_bin2bn(dgst, dgstlen, NULL); + if (e == NULL) { + SM2err(SM2_F_SM2_SIGN, ERR_R_BN_LIB); + goto done; + } + + s = sm2_sig_gen(eckey, e); + + sigleni = i2d_ECDSA_SIG(s, &sig); + if (sigleni < 0) { + SM2err(SM2_F_SM2_SIGN, ERR_R_INTERNAL_ERROR); + goto done; + } + *siglen = (unsigned int)sigleni; + + ret = 1; + + done: + ECDSA_SIG_free(s); + BN_free(e); + return ret; +} + +int sm2_verify(const unsigned char *dgst, int dgstlen, + const unsigned char *sig, int sig_len, EC_KEY *eckey) +{ + ECDSA_SIG *s = NULL; + BIGNUM *e = NULL; + const unsigned char *p = sig; + unsigned char *der = NULL; + int derlen = -1; + int ret = -1; + + s = ECDSA_SIG_new(); + if (s == NULL) { + SM2err(SM2_F_SM2_VERIFY, ERR_R_MALLOC_FAILURE); + goto done; + } + if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL) { + SM2err(SM2_F_SM2_VERIFY, SM2_R_INVALID_ENCODING); + goto done; + } + /* Ensure signature uses DER and doesn't have trailing garbage */ + derlen = i2d_ECDSA_SIG(s, &der); + if (derlen != sig_len || memcmp(sig, der, derlen) != 0) { + SM2err(SM2_F_SM2_VERIFY, SM2_R_INVALID_ENCODING); + goto done; + } + + e = BN_bin2bn(dgst, dgstlen, NULL); + if (e == NULL) { + SM2err(SM2_F_SM2_VERIFY, ERR_R_BN_LIB); + goto done; + } + + ret = sm2_sig_verify(eckey, s, e); + + done: + OPENSSL_free(der); + BN_free(e); + ECDSA_SIG_free(s); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sm3/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/sm3/build.info new file mode 100644 index 000000000..6009b1949 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sm3/build.info @@ -0,0 +1,2 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=sm3.c m_sm3.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sm3/m_sm3.c b/trunk/3rdparty/openssl-1.1-fit/crypto/sm3/m_sm3.c new file mode 100644 index 000000000..85538dc8a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sm3/m_sm3.c @@ -0,0 +1,52 @@ +/* + * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017 Ribose Inc. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" + +#ifndef OPENSSL_NO_SM3 +# include +# include "internal/evp_int.h" +# include "internal/sm3.h" + +static int init(EVP_MD_CTX *ctx) +{ + return sm3_init(EVP_MD_CTX_md_data(ctx)); +} + +static int update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ + return sm3_update(EVP_MD_CTX_md_data(ctx), data, count); +} + +static int final(EVP_MD_CTX *ctx, unsigned char *md) +{ + return sm3_final(md, EVP_MD_CTX_md_data(ctx)); +} + +static const EVP_MD sm3_md = { + NID_sm3, + NID_sm3WithRSAEncryption, + SM3_DIGEST_LENGTH, + 0, + init, + update, + final, + NULL, + NULL, + SM3_CBLOCK, + sizeof(EVP_MD *) + sizeof(SM3_CTX), +}; + +const EVP_MD *EVP_sm3(void) +{ + return &sm3_md; +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sm3/sm3.c b/trunk/3rdparty/openssl-1.1-fit/crypto/sm3/sm3.c new file mode 100644 index 000000000..1588dd115 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sm3/sm3.c @@ -0,0 +1,196 @@ +/* + * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017 Ribose Inc. All Rights Reserved. + * Ported from Ribose contributions from Botan. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "sm3_locl.h" + +int sm3_init(SM3_CTX *c) +{ + memset(c, 0, sizeof(*c)); + c->A = SM3_A; + c->B = SM3_B; + c->C = SM3_C; + c->D = SM3_D; + c->E = SM3_E; + c->F = SM3_F; + c->G = SM3_G; + c->H = SM3_H; + return 1; +} + +void sm3_block_data_order(SM3_CTX *ctx, const void *p, size_t num) +{ + const unsigned char *data = p; + register unsigned MD32_REG_T A, B, C, D, E, F, G, H; + + unsigned MD32_REG_T W00, W01, W02, W03, W04, W05, W06, W07, + W08, W09, W10, W11, W12, W13, W14, W15; + + for (; num--;) { + + A = ctx->A; + B = ctx->B; + C = ctx->C; + D = ctx->D; + E = ctx->E; + F = ctx->F; + G = ctx->G; + H = ctx->H; + + /* + * We have to load all message bytes immediately since SM3 reads + * them slightly out of order. + */ + (void)HOST_c2l(data, W00); + (void)HOST_c2l(data, W01); + (void)HOST_c2l(data, W02); + (void)HOST_c2l(data, W03); + (void)HOST_c2l(data, W04); + (void)HOST_c2l(data, W05); + (void)HOST_c2l(data, W06); + (void)HOST_c2l(data, W07); + (void)HOST_c2l(data, W08); + (void)HOST_c2l(data, W09); + (void)HOST_c2l(data, W10); + (void)HOST_c2l(data, W11); + (void)HOST_c2l(data, W12); + (void)HOST_c2l(data, W13); + (void)HOST_c2l(data, W14); + (void)HOST_c2l(data, W15); + + R1(A, B, C, D, E, F, G, H, 0x79CC4519, W00, W00 ^ W04); + W00 = EXPAND(W00, W07, W13, W03, W10); + R1(D, A, B, C, H, E, F, G, 0xF3988A32, W01, W01 ^ W05); + W01 = EXPAND(W01, W08, W14, W04, W11); + R1(C, D, A, B, G, H, E, F, 0xE7311465, W02, W02 ^ W06); + W02 = EXPAND(W02, W09, W15, W05, W12); + R1(B, C, D, A, F, G, H, E, 0xCE6228CB, W03, W03 ^ W07); + W03 = EXPAND(W03, W10, W00, W06, W13); + R1(A, B, C, D, E, F, G, H, 0x9CC45197, W04, W04 ^ W08); + W04 = EXPAND(W04, W11, W01, W07, W14); + R1(D, A, B, C, H, E, F, G, 0x3988A32F, W05, W05 ^ W09); + W05 = EXPAND(W05, W12, W02, W08, W15); + R1(C, D, A, B, G, H, E, F, 0x7311465E, W06, W06 ^ W10); + W06 = EXPAND(W06, W13, W03, W09, W00); + R1(B, C, D, A, F, G, H, E, 0xE6228CBC, W07, W07 ^ W11); + W07 = EXPAND(W07, W14, W04, W10, W01); + R1(A, B, C, D, E, F, G, H, 0xCC451979, W08, W08 ^ W12); + W08 = EXPAND(W08, W15, W05, W11, W02); + R1(D, A, B, C, H, E, F, G, 0x988A32F3, W09, W09 ^ W13); + W09 = EXPAND(W09, W00, W06, W12, W03); + R1(C, D, A, B, G, H, E, F, 0x311465E7, W10, W10 ^ W14); + W10 = EXPAND(W10, W01, W07, W13, W04); + R1(B, C, D, A, F, G, H, E, 0x6228CBCE, W11, W11 ^ W15); + W11 = EXPAND(W11, W02, W08, W14, W05); + R1(A, B, C, D, E, F, G, H, 0xC451979C, W12, W12 ^ W00); + W12 = EXPAND(W12, W03, W09, W15, W06); + R1(D, A, B, C, H, E, F, G, 0x88A32F39, W13, W13 ^ W01); + W13 = EXPAND(W13, W04, W10, W00, W07); + R1(C, D, A, B, G, H, E, F, 0x11465E73, W14, W14 ^ W02); + W14 = EXPAND(W14, W05, W11, W01, W08); + R1(B, C, D, A, F, G, H, E, 0x228CBCE6, W15, W15 ^ W03); + W15 = EXPAND(W15, W06, W12, W02, W09); + R2(A, B, C, D, E, F, G, H, 0x9D8A7A87, W00, W00 ^ W04); + W00 = EXPAND(W00, W07, W13, W03, W10); + R2(D, A, B, C, H, E, F, G, 0x3B14F50F, W01, W01 ^ W05); + W01 = EXPAND(W01, W08, W14, W04, W11); + R2(C, D, A, B, G, H, E, F, 0x7629EA1E, W02, W02 ^ W06); + W02 = EXPAND(W02, W09, W15, W05, W12); + R2(B, C, D, A, F, G, H, E, 0xEC53D43C, W03, W03 ^ W07); + W03 = EXPAND(W03, W10, W00, W06, W13); + R2(A, B, C, D, E, F, G, H, 0xD8A7A879, W04, W04 ^ W08); + W04 = EXPAND(W04, W11, W01, W07, W14); + R2(D, A, B, C, H, E, F, G, 0xB14F50F3, W05, W05 ^ W09); + W05 = EXPAND(W05, W12, W02, W08, W15); + R2(C, D, A, B, G, H, E, F, 0x629EA1E7, W06, W06 ^ W10); + W06 = EXPAND(W06, W13, W03, W09, W00); + R2(B, C, D, A, F, G, H, E, 0xC53D43CE, W07, W07 ^ W11); + W07 = EXPAND(W07, W14, W04, W10, W01); + R2(A, B, C, D, E, F, G, H, 0x8A7A879D, W08, W08 ^ W12); + W08 = EXPAND(W08, W15, W05, W11, W02); + R2(D, A, B, C, H, E, F, G, 0x14F50F3B, W09, W09 ^ W13); + W09 = EXPAND(W09, W00, W06, W12, W03); + R2(C, D, A, B, G, H, E, F, 0x29EA1E76, W10, W10 ^ W14); + W10 = EXPAND(W10, W01, W07, W13, W04); + R2(B, C, D, A, F, G, H, E, 0x53D43CEC, W11, W11 ^ W15); + W11 = EXPAND(W11, W02, W08, W14, W05); + R2(A, B, C, D, E, F, G, H, 0xA7A879D8, W12, W12 ^ W00); + W12 = EXPAND(W12, W03, W09, W15, W06); + R2(D, A, B, C, H, E, F, G, 0x4F50F3B1, W13, W13 ^ W01); + W13 = EXPAND(W13, W04, W10, W00, W07); + R2(C, D, A, B, G, H, E, F, 0x9EA1E762, W14, W14 ^ W02); + W14 = EXPAND(W14, W05, W11, W01, W08); + R2(B, C, D, A, F, G, H, E, 0x3D43CEC5, W15, W15 ^ W03); + W15 = EXPAND(W15, W06, W12, W02, W09); + R2(A, B, C, D, E, F, G, H, 0x7A879D8A, W00, W00 ^ W04); + W00 = EXPAND(W00, W07, W13, W03, W10); + R2(D, A, B, C, H, E, F, G, 0xF50F3B14, W01, W01 ^ W05); + W01 = EXPAND(W01, W08, W14, W04, W11); + R2(C, D, A, B, G, H, E, F, 0xEA1E7629, W02, W02 ^ W06); + W02 = EXPAND(W02, W09, W15, W05, W12); + R2(B, C, D, A, F, G, H, E, 0xD43CEC53, W03, W03 ^ W07); + W03 = EXPAND(W03, W10, W00, W06, W13); + R2(A, B, C, D, E, F, G, H, 0xA879D8A7, W04, W04 ^ W08); + W04 = EXPAND(W04, W11, W01, W07, W14); + R2(D, A, B, C, H, E, F, G, 0x50F3B14F, W05, W05 ^ W09); + W05 = EXPAND(W05, W12, W02, W08, W15); + R2(C, D, A, B, G, H, E, F, 0xA1E7629E, W06, W06 ^ W10); + W06 = EXPAND(W06, W13, W03, W09, W00); + R2(B, C, D, A, F, G, H, E, 0x43CEC53D, W07, W07 ^ W11); + W07 = EXPAND(W07, W14, W04, W10, W01); + R2(A, B, C, D, E, F, G, H, 0x879D8A7A, W08, W08 ^ W12); + W08 = EXPAND(W08, W15, W05, W11, W02); + R2(D, A, B, C, H, E, F, G, 0x0F3B14F5, W09, W09 ^ W13); + W09 = EXPAND(W09, W00, W06, W12, W03); + R2(C, D, A, B, G, H, E, F, 0x1E7629EA, W10, W10 ^ W14); + W10 = EXPAND(W10, W01, W07, W13, W04); + R2(B, C, D, A, F, G, H, E, 0x3CEC53D4, W11, W11 ^ W15); + W11 = EXPAND(W11, W02, W08, W14, W05); + R2(A, B, C, D, E, F, G, H, 0x79D8A7A8, W12, W12 ^ W00); + W12 = EXPAND(W12, W03, W09, W15, W06); + R2(D, A, B, C, H, E, F, G, 0xF3B14F50, W13, W13 ^ W01); + W13 = EXPAND(W13, W04, W10, W00, W07); + R2(C, D, A, B, G, H, E, F, 0xE7629EA1, W14, W14 ^ W02); + W14 = EXPAND(W14, W05, W11, W01, W08); + R2(B, C, D, A, F, G, H, E, 0xCEC53D43, W15, W15 ^ W03); + W15 = EXPAND(W15, W06, W12, W02, W09); + R2(A, B, C, D, E, F, G, H, 0x9D8A7A87, W00, W00 ^ W04); + W00 = EXPAND(W00, W07, W13, W03, W10); + R2(D, A, B, C, H, E, F, G, 0x3B14F50F, W01, W01 ^ W05); + W01 = EXPAND(W01, W08, W14, W04, W11); + R2(C, D, A, B, G, H, E, F, 0x7629EA1E, W02, W02 ^ W06); + W02 = EXPAND(W02, W09, W15, W05, W12); + R2(B, C, D, A, F, G, H, E, 0xEC53D43C, W03, W03 ^ W07); + W03 = EXPAND(W03, W10, W00, W06, W13); + R2(A, B, C, D, E, F, G, H, 0xD8A7A879, W04, W04 ^ W08); + R2(D, A, B, C, H, E, F, G, 0xB14F50F3, W05, W05 ^ W09); + R2(C, D, A, B, G, H, E, F, 0x629EA1E7, W06, W06 ^ W10); + R2(B, C, D, A, F, G, H, E, 0xC53D43CE, W07, W07 ^ W11); + R2(A, B, C, D, E, F, G, H, 0x8A7A879D, W08, W08 ^ W12); + R2(D, A, B, C, H, E, F, G, 0x14F50F3B, W09, W09 ^ W13); + R2(C, D, A, B, G, H, E, F, 0x29EA1E76, W10, W10 ^ W14); + R2(B, C, D, A, F, G, H, E, 0x53D43CEC, W11, W11 ^ W15); + R2(A, B, C, D, E, F, G, H, 0xA7A879D8, W12, W12 ^ W00); + R2(D, A, B, C, H, E, F, G, 0x4F50F3B1, W13, W13 ^ W01); + R2(C, D, A, B, G, H, E, F, 0x9EA1E762, W14, W14 ^ W02); + R2(B, C, D, A, F, G, H, E, 0x3D43CEC5, W15, W15 ^ W03); + + ctx->A ^= A; + ctx->B ^= B; + ctx->C ^= C; + ctx->D ^= D; + ctx->E ^= E; + ctx->F ^= F; + ctx->G ^= G; + ctx->H ^= H; + } +} + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sm3/sm3_locl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/sm3/sm3_locl.h new file mode 100644 index 000000000..efa6db57c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sm3/sm3_locl.h @@ -0,0 +1,79 @@ +/* + * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017 Ribose Inc. All Rights Reserved. + * Ported from Ribose contributions from Botan. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/sm3.h" + +#define DATA_ORDER_IS_BIG_ENDIAN + +#define HASH_LONG SM3_WORD +#define HASH_CTX SM3_CTX +#define HASH_CBLOCK SM3_CBLOCK +#define HASH_UPDATE sm3_update +#define HASH_TRANSFORM sm3_transform +#define HASH_FINAL sm3_final +#define HASH_MAKE_STRING(c, s) \ + do { \ + unsigned long ll; \ + ll=(c)->A; (void)HOST_l2c(ll, (s)); \ + ll=(c)->B; (void)HOST_l2c(ll, (s)); \ + ll=(c)->C; (void)HOST_l2c(ll, (s)); \ + ll=(c)->D; (void)HOST_l2c(ll, (s)); \ + ll=(c)->E; (void)HOST_l2c(ll, (s)); \ + ll=(c)->F; (void)HOST_l2c(ll, (s)); \ + ll=(c)->G; (void)HOST_l2c(ll, (s)); \ + ll=(c)->H; (void)HOST_l2c(ll, (s)); \ + } while (0) +#define HASH_BLOCK_DATA_ORDER sm3_block_data_order + +void sm3_transform(SM3_CTX *c, const unsigned char *data); + +#include "internal/md32_common.h" + +#define P0(X) (X ^ ROTATE(X, 9) ^ ROTATE(X, 17)) +#define P1(X) (X ^ ROTATE(X, 15) ^ ROTATE(X, 23)) + +#define FF0(X,Y,Z) (X ^ Y ^ Z) +#define GG0(X,Y,Z) (X ^ Y ^ Z) + +#define FF1(X,Y,Z) ((X & Y) | ((X | Y) & Z)) +#define GG1(X,Y,Z) ((Z ^ (X & (Y ^ Z)))) + +#define EXPAND(W0,W7,W13,W3,W10) \ + (P1(W0 ^ W7 ^ ROTATE(W13, 15)) ^ ROTATE(W3, 7) ^ W10) + +#define RND(A, B, C, D, E, F, G, H, TJ, Wi, Wj, FF, GG) \ + do { \ + const SM3_WORD A12 = ROTATE(A, 12); \ + const SM3_WORD A12_SM = A12 + E + TJ; \ + const SM3_WORD SS1 = ROTATE(A12_SM, 7); \ + const SM3_WORD TT1 = FF(A, B, C) + D + (SS1 ^ A12) + (Wj); \ + const SM3_WORD TT2 = GG(E, F, G) + H + SS1 + Wi; \ + B = ROTATE(B, 9); \ + D = TT1; \ + F = ROTATE(F, 19); \ + H = P0(TT2); \ + } while(0) + +#define R1(A,B,C,D,E,F,G,H,TJ,Wi,Wj) \ + RND(A,B,C,D,E,F,G,H,TJ,Wi,Wj,FF0,GG0) + +#define R2(A,B,C,D,E,F,G,H,TJ,Wi,Wj) \ + RND(A,B,C,D,E,F,G,H,TJ,Wi,Wj,FF1,GG1) + +#define SM3_A 0x7380166fUL +#define SM3_B 0x4914b2b9UL +#define SM3_C 0x172442d7UL +#define SM3_D 0xda8a0600UL +#define SM3_E 0xa96f30bcUL +#define SM3_F 0x163138aaUL +#define SM3_G 0xe38dee4dUL +#define SM3_H 0xb0fb0e4eUL diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sm4/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/sm4/build.info new file mode 100644 index 000000000..b65a7d149 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sm4/build.info @@ -0,0 +1,4 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + sm4.c + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sm4/sm4.c b/trunk/3rdparty/openssl-1.1-fit/crypto/sm4/sm4.c new file mode 100644 index 000000000..0c819a4b6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sm4/sm4.c @@ -0,0 +1,233 @@ +/* + * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017 Ribose Inc. All Rights Reserved. + * Ported from Ribose contributions from Botan. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/sm4.h" + +static const uint8_t SM4_S[256] = { + 0xD6, 0x90, 0xE9, 0xFE, 0xCC, 0xE1, 0x3D, 0xB7, 0x16, 0xB6, 0x14, 0xC2, + 0x28, 0xFB, 0x2C, 0x05, 0x2B, 0x67, 0x9A, 0x76, 0x2A, 0xBE, 0x04, 0xC3, + 0xAA, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, 0x9C, 0x42, 0x50, 0xF4, + 0x91, 0xEF, 0x98, 0x7A, 0x33, 0x54, 0x0B, 0x43, 0xED, 0xCF, 0xAC, 0x62, + 0xE4, 0xB3, 0x1C, 0xA9, 0xC9, 0x08, 0xE8, 0x95, 0x80, 0xDF, 0x94, 0xFA, + 0x75, 0x8F, 0x3F, 0xA6, 0x47, 0x07, 0xA7, 0xFC, 0xF3, 0x73, 0x17, 0xBA, + 0x83, 0x59, 0x3C, 0x19, 0xE6, 0x85, 0x4F, 0xA8, 0x68, 0x6B, 0x81, 0xB2, + 0x71, 0x64, 0xDA, 0x8B, 0xF8, 0xEB, 0x0F, 0x4B, 0x70, 0x56, 0x9D, 0x35, + 0x1E, 0x24, 0x0E, 0x5E, 0x63, 0x58, 0xD1, 0xA2, 0x25, 0x22, 0x7C, 0x3B, + 0x01, 0x21, 0x78, 0x87, 0xD4, 0x00, 0x46, 0x57, 0x9F, 0xD3, 0x27, 0x52, + 0x4C, 0x36, 0x02, 0xE7, 0xA0, 0xC4, 0xC8, 0x9E, 0xEA, 0xBF, 0x8A, 0xD2, + 0x40, 0xC7, 0x38, 0xB5, 0xA3, 0xF7, 0xF2, 0xCE, 0xF9, 0x61, 0x15, 0xA1, + 0xE0, 0xAE, 0x5D, 0xA4, 0x9B, 0x34, 0x1A, 0x55, 0xAD, 0x93, 0x32, 0x30, + 0xF5, 0x8C, 0xB1, 0xE3, 0x1D, 0xF6, 0xE2, 0x2E, 0x82, 0x66, 0xCA, 0x60, + 0xC0, 0x29, 0x23, 0xAB, 0x0D, 0x53, 0x4E, 0x6F, 0xD5, 0xDB, 0x37, 0x45, + 0xDE, 0xFD, 0x8E, 0x2F, 0x03, 0xFF, 0x6A, 0x72, 0x6D, 0x6C, 0x5B, 0x51, + 0x8D, 0x1B, 0xAF, 0x92, 0xBB, 0xDD, 0xBC, 0x7F, 0x11, 0xD9, 0x5C, 0x41, + 0x1F, 0x10, 0x5A, 0xD8, 0x0A, 0xC1, 0x31, 0x88, 0xA5, 0xCD, 0x7B, 0xBD, + 0x2D, 0x74, 0xD0, 0x12, 0xB8, 0xE5, 0xB4, 0xB0, 0x89, 0x69, 0x97, 0x4A, + 0x0C, 0x96, 0x77, 0x7E, 0x65, 0xB9, 0xF1, 0x09, 0xC5, 0x6E, 0xC6, 0x84, + 0x18, 0xF0, 0x7D, 0xEC, 0x3A, 0xDC, 0x4D, 0x20, 0x79, 0xEE, 0x5F, 0x3E, + 0xD7, 0xCB, 0x39, 0x48 +}; + +/* + * SM4_SBOX_T[j] == L(SM4_SBOX[j]). + */ +static const uint32_t SM4_SBOX_T[256] = { + 0x8ED55B5B, 0xD0924242, 0x4DEAA7A7, 0x06FDFBFB, 0xFCCF3333, 0x65E28787, + 0xC93DF4F4, 0x6BB5DEDE, 0x4E165858, 0x6EB4DADA, 0x44145050, 0xCAC10B0B, + 0x8828A0A0, 0x17F8EFEF, 0x9C2CB0B0, 0x11051414, 0x872BACAC, 0xFB669D9D, + 0xF2986A6A, 0xAE77D9D9, 0x822AA8A8, 0x46BCFAFA, 0x14041010, 0xCFC00F0F, + 0x02A8AAAA, 0x54451111, 0x5F134C4C, 0xBE269898, 0x6D482525, 0x9E841A1A, + 0x1E061818, 0xFD9B6666, 0xEC9E7272, 0x4A430909, 0x10514141, 0x24F7D3D3, + 0xD5934646, 0x53ECBFBF, 0xF89A6262, 0x927BE9E9, 0xFF33CCCC, 0x04555151, + 0x270B2C2C, 0x4F420D0D, 0x59EEB7B7, 0xF3CC3F3F, 0x1CAEB2B2, 0xEA638989, + 0x74E79393, 0x7FB1CECE, 0x6C1C7070, 0x0DABA6A6, 0xEDCA2727, 0x28082020, + 0x48EBA3A3, 0xC1975656, 0x80820202, 0xA3DC7F7F, 0xC4965252, 0x12F9EBEB, + 0xA174D5D5, 0xB38D3E3E, 0xC33FFCFC, 0x3EA49A9A, 0x5B461D1D, 0x1B071C1C, + 0x3BA59E9E, 0x0CFFF3F3, 0x3FF0CFCF, 0xBF72CDCD, 0x4B175C5C, 0x52B8EAEA, + 0x8F810E0E, 0x3D586565, 0xCC3CF0F0, 0x7D196464, 0x7EE59B9B, 0x91871616, + 0x734E3D3D, 0x08AAA2A2, 0xC869A1A1, 0xC76AADAD, 0x85830606, 0x7AB0CACA, + 0xB570C5C5, 0xF4659191, 0xB2D96B6B, 0xA7892E2E, 0x18FBE3E3, 0x47E8AFAF, + 0x330F3C3C, 0x674A2D2D, 0xB071C1C1, 0x0E575959, 0xE99F7676, 0xE135D4D4, + 0x661E7878, 0xB4249090, 0x360E3838, 0x265F7979, 0xEF628D8D, 0x38596161, + 0x95D24747, 0x2AA08A8A, 0xB1259494, 0xAA228888, 0x8C7DF1F1, 0xD73BECEC, + 0x05010404, 0xA5218484, 0x9879E1E1, 0x9B851E1E, 0x84D75353, 0x00000000, + 0x5E471919, 0x0B565D5D, 0xE39D7E7E, 0x9FD04F4F, 0xBB279C9C, 0x1A534949, + 0x7C4D3131, 0xEE36D8D8, 0x0A020808, 0x7BE49F9F, 0x20A28282, 0xD4C71313, + 0xE8CB2323, 0xE69C7A7A, 0x42E9ABAB, 0x43BDFEFE, 0xA2882A2A, 0x9AD14B4B, + 0x40410101, 0xDBC41F1F, 0xD838E0E0, 0x61B7D6D6, 0x2FA18E8E, 0x2BF4DFDF, + 0x3AF1CBCB, 0xF6CD3B3B, 0x1DFAE7E7, 0xE5608585, 0x41155454, 0x25A38686, + 0x60E38383, 0x16ACBABA, 0x295C7575, 0x34A69292, 0xF7996E6E, 0xE434D0D0, + 0x721A6868, 0x01545555, 0x19AFB6B6, 0xDF914E4E, 0xFA32C8C8, 0xF030C0C0, + 0x21F6D7D7, 0xBC8E3232, 0x75B3C6C6, 0x6FE08F8F, 0x691D7474, 0x2EF5DBDB, + 0x6AE18B8B, 0x962EB8B8, 0x8A800A0A, 0xFE679999, 0xE2C92B2B, 0xE0618181, + 0xC0C30303, 0x8D29A4A4, 0xAF238C8C, 0x07A9AEAE, 0x390D3434, 0x1F524D4D, + 0x764F3939, 0xD36EBDBD, 0x81D65757, 0xB7D86F6F, 0xEB37DCDC, 0x51441515, + 0xA6DD7B7B, 0x09FEF7F7, 0xB68C3A3A, 0x932FBCBC, 0x0F030C0C, 0x03FCFFFF, + 0xC26BA9A9, 0xBA73C9C9, 0xD96CB5B5, 0xDC6DB1B1, 0x375A6D6D, 0x15504545, + 0xB98F3636, 0x771B6C6C, 0x13ADBEBE, 0xDA904A4A, 0x57B9EEEE, 0xA9DE7777, + 0x4CBEF2F2, 0x837EFDFD, 0x55114444, 0xBDDA6767, 0x2C5D7171, 0x45400505, + 0x631F7C7C, 0x50104040, 0x325B6969, 0xB8DB6363, 0x220A2828, 0xC5C20707, + 0xF531C4C4, 0xA88A2222, 0x31A79696, 0xF9CE3737, 0x977AEDED, 0x49BFF6F6, + 0x992DB4B4, 0xA475D1D1, 0x90D34343, 0x5A124848, 0x58BAE2E2, 0x71E69797, + 0x64B6D2D2, 0x70B2C2C2, 0xAD8B2626, 0xCD68A5A5, 0xCB955E5E, 0x624B2929, + 0x3C0C3030, 0xCE945A5A, 0xAB76DDDD, 0x867FF9F9, 0xF1649595, 0x5DBBE6E6, + 0x35F2C7C7, 0x2D092424, 0xD1C61717, 0xD66FB9B9, 0xDEC51B1B, 0x94861212, + 0x78186060, 0x30F3C3C3, 0x897CF5F5, 0x5CEFB3B3, 0xD23AE8E8, 0xACDF7373, + 0x794C3535, 0xA0208080, 0x9D78E5E5, 0x56EDBBBB, 0x235E7D7D, 0xC63EF8F8, + 0x8BD45F5F, 0xE7C82F2F, 0xDD39E4E4, 0x68492121 }; + +static ossl_inline uint32_t rotl(uint32_t a, uint8_t n) +{ + return (a << n) | (a >> (32 - n)); +} + +static ossl_inline uint32_t load_u32_be(const uint8_t *b, uint32_t n) +{ + return ((uint32_t)b[4 * n] << 24) | + ((uint32_t)b[4 * n + 1] << 16) | + ((uint32_t)b[4 * n + 2] << 8) | + ((uint32_t)b[4 * n + 3]); +} + +static ossl_inline void store_u32_be(uint32_t v, uint8_t *b) +{ + b[0] = (uint8_t)(v >> 24); + b[1] = (uint8_t)(v >> 16); + b[2] = (uint8_t)(v >> 8); + b[3] = (uint8_t)(v); +} + +static ossl_inline uint32_t SM4_T_slow(uint32_t X) +{ + uint32_t t = 0; + + t |= ((uint32_t)SM4_S[(uint8_t)(X >> 24)]) << 24; + t |= ((uint32_t)SM4_S[(uint8_t)(X >> 16)]) << 16; + t |= ((uint32_t)SM4_S[(uint8_t)(X >> 8)]) << 8; + t |= SM4_S[(uint8_t)X]; + + /* + * L linear transform + */ + return t ^ rotl(t, 2) ^ rotl(t, 10) ^ rotl(t, 18) ^ rotl(t, 24); +} + +static ossl_inline uint32_t SM4_T(uint32_t X) +{ + return SM4_SBOX_T[(uint8_t)(X >> 24)] ^ + rotl(SM4_SBOX_T[(uint8_t)(X >> 16)], 24) ^ + rotl(SM4_SBOX_T[(uint8_t)(X >> 8)], 16) ^ + rotl(SM4_SBOX_T[(uint8_t)X], 8); +} + +int SM4_set_key(const uint8_t *key, SM4_KEY *ks) +{ + /* + * Family Key + */ + static const uint32_t FK[4] = + { 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc }; + + /* + * Constant Key + */ + static const uint32_t CK[32] = { + 0x00070E15, 0x1C232A31, 0x383F464D, 0x545B6269, + 0x70777E85, 0x8C939AA1, 0xA8AFB6BD, 0xC4CBD2D9, + 0xE0E7EEF5, 0xFC030A11, 0x181F262D, 0x343B4249, + 0x50575E65, 0x6C737A81, 0x888F969D, 0xA4ABB2B9, + 0xC0C7CED5, 0xDCE3EAF1, 0xF8FF060D, 0x141B2229, + 0x30373E45, 0x4C535A61, 0x686F767D, 0x848B9299, + 0xA0A7AEB5, 0xBCC3CAD1, 0xD8DFE6ED, 0xF4FB0209, + 0x10171E25, 0x2C333A41, 0x484F565D, 0x646B7279 + }; + + uint32_t K[4]; + int i; + + K[0] = load_u32_be(key, 0) ^ FK[0]; + K[1] = load_u32_be(key, 1) ^ FK[1]; + K[2] = load_u32_be(key, 2) ^ FK[2]; + K[3] = load_u32_be(key, 3) ^ FK[3]; + + for (i = 0; i != SM4_KEY_SCHEDULE; ++i) { + uint32_t X = K[(i + 1) % 4] ^ K[(i + 2) % 4] ^ K[(i + 3) % 4] ^ CK[i]; + uint32_t t = 0; + + t |= ((uint32_t)SM4_S[(uint8_t)(X >> 24)]) << 24; + t |= ((uint32_t)SM4_S[(uint8_t)(X >> 16)]) << 16; + t |= ((uint32_t)SM4_S[(uint8_t)(X >> 8)]) << 8; + t |= SM4_S[(uint8_t)X]; + + t = t ^ rotl(t, 13) ^ rotl(t, 23); + K[i % 4] ^= t; + ks->rk[i] = K[i % 4]; + } + + return 1; +} + +#define SM4_RNDS(k0, k1, k2, k3, F) \ + do { \ + B0 ^= F(B1 ^ B2 ^ B3 ^ ks->rk[k0]); \ + B1 ^= F(B0 ^ B2 ^ B3 ^ ks->rk[k1]); \ + B2 ^= F(B0 ^ B1 ^ B3 ^ ks->rk[k2]); \ + B3 ^= F(B0 ^ B1 ^ B2 ^ ks->rk[k3]); \ + } while(0) + +void SM4_encrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks) +{ + uint32_t B0 = load_u32_be(in, 0); + uint32_t B1 = load_u32_be(in, 1); + uint32_t B2 = load_u32_be(in, 2); + uint32_t B3 = load_u32_be(in, 3); + + /* + * Uses byte-wise sbox in the first and last rounds to provide some + * protection from cache based side channels. + */ + SM4_RNDS( 0, 1, 2, 3, SM4_T_slow); + SM4_RNDS( 4, 5, 6, 7, SM4_T); + SM4_RNDS( 8, 9, 10, 11, SM4_T); + SM4_RNDS(12, 13, 14, 15, SM4_T); + SM4_RNDS(16, 17, 18, 19, SM4_T); + SM4_RNDS(20, 21, 22, 23, SM4_T); + SM4_RNDS(24, 25, 26, 27, SM4_T); + SM4_RNDS(28, 29, 30, 31, SM4_T_slow); + + store_u32_be(B3, out); + store_u32_be(B2, out + 4); + store_u32_be(B1, out + 8); + store_u32_be(B0, out + 12); +} + +void SM4_decrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks) +{ + uint32_t B0 = load_u32_be(in, 0); + uint32_t B1 = load_u32_be(in, 1); + uint32_t B2 = load_u32_be(in, 2); + uint32_t B3 = load_u32_be(in, 3); + + SM4_RNDS(31, 30, 29, 28, SM4_T_slow); + SM4_RNDS(27, 26, 25, 24, SM4_T); + SM4_RNDS(23, 22, 21, 20, SM4_T); + SM4_RNDS(19, 18, 17, 16, SM4_T); + SM4_RNDS(15, 14, 13, 12, SM4_T); + SM4_RNDS(11, 10, 9, 8, SM4_T); + SM4_RNDS( 7, 6, 5, 4, SM4_T); + SM4_RNDS( 3, 2, 1, 0, SM4_T_slow); + + store_u32_be(B3, out); + store_u32_be(B2, out + 4); + store_u32_be(B1, out + 8); + store_u32_be(B0, out + 12); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sparc_arch.h b/trunk/3rdparty/openssl-1.1-fit/crypto/sparc_arch.h new file mode 100644 index 000000000..99eafb331 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sparc_arch.h @@ -0,0 +1,118 @@ +/* + * Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef __SPARC_ARCH_H__ +# define __SPARC_ARCH_H__ + +# define SPARCV9_TICK_PRIVILEGED (1<<0) +# define SPARCV9_PREFER_FPU (1<<1) +# define SPARCV9_VIS1 (1<<2) +# define SPARCV9_VIS2 (1<<3)/* reserved */ +# define SPARCV9_FMADD (1<<4) +# define SPARCV9_BLK (1<<5)/* VIS1 block copy */ +# define SPARCV9_VIS3 (1<<6) +# define SPARCV9_RANDOM (1<<7) +# define SPARCV9_64BIT_STACK (1<<8) +# define SPARCV9_FJAESX (1<<9)/* Fujitsu SPARC64 X AES */ +# define SPARCV9_FJDESX (1<<10)/* Fujitsu SPARC64 X DES, reserved */ +# define SPARCV9_FJHPCACE (1<<11)/* Fujitsu HPC-ACE, reserved */ +# define SPARCV9_IMA (1<<13)/* reserved */ +# define SPARCV9_VIS4 (1<<14)/* reserved */ + +/* + * OPENSSL_sparcv9cap_P[1] is copy of Compatibility Feature Register, + * %asr26, SPARC-T4 and later. There is no SPARCV9_CFR bit in + * OPENSSL_sparcv9cap_P[0], as %cfr copy is sufficient... + */ +# define CFR_AES 0x00000001/* Supports AES opcodes */ +# define CFR_DES 0x00000002/* Supports DES opcodes */ +# define CFR_KASUMI 0x00000004/* Supports KASUMI opcodes */ +# define CFR_CAMELLIA 0x00000008/* Supports CAMELLIA opcodes */ +# define CFR_MD5 0x00000010/* Supports MD5 opcodes */ +# define CFR_SHA1 0x00000020/* Supports SHA1 opcodes */ +# define CFR_SHA256 0x00000040/* Supports SHA256 opcodes */ +# define CFR_SHA512 0x00000080/* Supports SHA512 opcodes */ +# define CFR_MPMUL 0x00000100/* Supports MPMUL opcodes */ +# define CFR_MONTMUL 0x00000200/* Supports MONTMUL opcodes */ +# define CFR_MONTSQR 0x00000400/* Supports MONTSQR opcodes */ +# define CFR_CRC32C 0x00000800/* Supports CRC32C opcodes */ +# define CFR_XMPMUL 0x00001000/* Supports XMPMUL opcodes */ +# define CFR_XMONTMUL 0x00002000/* Supports XMONTMUL opcodes */ +# define CFR_XMONTSQR 0x00004000/* Supports XMONTSQR opcodes */ + +# if defined(OPENSSL_PIC) && !defined(__PIC__) +# define __PIC__ +# endif + +# if defined(__SUNPRO_C) && defined(__sparcv9) && !defined(__arch64__) +# define __arch64__ +# endif + +# define SPARC_PIC_THUNK(reg) \ + .align 32; \ +.Lpic_thunk: \ + jmp %o7 + 8; \ + add %o7, reg, reg; + +# define SPARC_PIC_THUNK_CALL(reg) \ + sethi %hi(_GLOBAL_OFFSET_TABLE_-4), reg; \ + call .Lpic_thunk; \ + or reg, %lo(_GLOBAL_OFFSET_TABLE_+4), reg; + +# if 1 +# define SPARC_SETUP_GOT_REG(reg) SPARC_PIC_THUNK_CALL(reg) +# else +# define SPARC_SETUP_GOT_REG(reg) \ + sethi %hi(_GLOBAL_OFFSET_TABLE_-4), reg; \ + call .+8; \ + or reg,%lo(_GLOBAL_OFFSET_TABLE_+4), reg; \ + add %o7, reg, reg +# endif + +# if defined(__arch64__) + +# define SPARC_LOAD_ADDRESS(SYM, reg) \ + setx SYM, %o7, reg; +# define LDPTR ldx +# define SIZE_T_CC %xcc +# define STACK_FRAME 192 +# define STACK_BIAS 2047 +# define STACK_7thARG (STACK_BIAS+176) + +# else + +# define SPARC_LOAD_ADDRESS(SYM, reg) \ + set SYM, reg; +# define LDPTR ld +# define SIZE_T_CC %icc +# define STACK_FRAME 112 +# define STACK_BIAS 0 +# define STACK_7thARG 92 +# define SPARC_LOAD_ADDRESS_LEAF(SYM,reg,tmp) SPARC_LOAD_ADDRESS(SYM,reg) + +# endif + +# ifdef __PIC__ +# undef SPARC_LOAD_ADDRESS +# undef SPARC_LOAD_ADDRESS_LEAF +# define SPARC_LOAD_ADDRESS(SYM, reg) \ + SPARC_SETUP_GOT_REG(reg); \ + sethi %hi(SYM), %o7; \ + or %o7, %lo(SYM), %o7; \ + LDPTR [reg + %o7], reg; +# endif + +# ifndef SPARC_LOAD_ADDRESS_LEAF +# define SPARC_LOAD_ADDRESS_LEAF(SYM, reg, tmp) \ + mov %o7, tmp; \ + SPARC_LOAD_ADDRESS(SYM, reg) \ + mov tmp, %o7; +# endif + +#endif /* __SPARC_ARCH_H__ */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sparccpuid.S b/trunk/3rdparty/openssl-1.1-fit/crypto/sparccpuid.S new file mode 100644 index 000000000..95acd2f9d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sparccpuid.S @@ -0,0 +1,578 @@ +! Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved. +! +! Licensed under the OpenSSL license (the "License"). You may not use +! this file except in compliance with the License. You can obtain a copy +! in the file LICENSE in the source distribution or at +! https://www.openssl.org/source/license.html + +#if defined(__SUNPRO_C) && defined(__sparcv9) +# define ABI64 /* They've said -xarch=v9 at command line */ +#elif defined(__GNUC__) && defined(__arch64__) +# define ABI64 /* They've said -m64 at command line */ +#endif + +#ifdef ABI64 + .register %g2,#scratch + .register %g3,#scratch +# define FRAME -192 +# define BIAS 2047 +#else +# define FRAME -96 +# define BIAS 0 +#endif + +.text +.align 32 +.global OPENSSL_wipe_cpu +.type OPENSSL_wipe_cpu,#function +! Keep in mind that this does not excuse us from wiping the stack! +! This routine wipes registers, but not the backing store [which +! resides on the stack, toward lower addresses]. To facilitate for +! stack wiping I return pointer to the top of stack of the *caller*. +OPENSSL_wipe_cpu: + save %sp,FRAME,%sp + nop +#ifdef __sun +#include + ta ST_CLEAN_WINDOWS +#else + call .walk.reg.wins +#endif + nop + call .PIC.zero.up + mov .zero-(.-4),%o0 + ld [%o0],%f0 + ld [%o0],%f1 + + subcc %g0,1,%o0 + ! Following is V9 "rd %ccr,%o0" instruction. However! V8 + ! specification says that it ("rd %asr2,%o0" in V8 terms) does + ! not cause illegal_instruction trap. It therefore can be used + ! to determine if the CPU the code is executing on is V8- or + ! V9-compliant, as V9 returns a distinct value of 0x99, + ! "negative" and "borrow" bits set in both %icc and %xcc. + .word 0x91408000 !rd %ccr,%o0 + cmp %o0,0x99 + bne .v8 + nop + ! Even though we do not use %fp register bank, + ! we wipe it as memcpy might have used it... + .word 0xbfa00040 !fmovd %f0,%f62 + .word 0xbba00040 !... + .word 0xb7a00040 + .word 0xb3a00040 + .word 0xafa00040 + .word 0xaba00040 + .word 0xa7a00040 + .word 0xa3a00040 + .word 0x9fa00040 + .word 0x9ba00040 + .word 0x97a00040 + .word 0x93a00040 + .word 0x8fa00040 + .word 0x8ba00040 + .word 0x87a00040 + .word 0x83a00040 !fmovd %f0,%f32 +.v8: fmovs %f1,%f31 + clr %o0 + fmovs %f0,%f30 + clr %o1 + fmovs %f1,%f29 + clr %o2 + fmovs %f0,%f28 + clr %o3 + fmovs %f1,%f27 + clr %o4 + fmovs %f0,%f26 + clr %o5 + fmovs %f1,%f25 + clr %o7 + fmovs %f0,%f24 + clr %l0 + fmovs %f1,%f23 + clr %l1 + fmovs %f0,%f22 + clr %l2 + fmovs %f1,%f21 + clr %l3 + fmovs %f0,%f20 + clr %l4 + fmovs %f1,%f19 + clr %l5 + fmovs %f0,%f18 + clr %l6 + fmovs %f1,%f17 + clr %l7 + fmovs %f0,%f16 + clr %i0 + fmovs %f1,%f15 + clr %i1 + fmovs %f0,%f14 + clr %i2 + fmovs %f1,%f13 + clr %i3 + fmovs %f0,%f12 + clr %i4 + fmovs %f1,%f11 + clr %i5 + fmovs %f0,%f10 + clr %g1 + fmovs %f1,%f9 + clr %g2 + fmovs %f0,%f8 + clr %g3 + fmovs %f1,%f7 + clr %g4 + fmovs %f0,%f6 + clr %g5 + fmovs %f1,%f5 + fmovs %f0,%f4 + fmovs %f1,%f3 + fmovs %f0,%f2 + + add %fp,BIAS,%i0 ! return pointer to caller´s top of stack + + ret + restore + +.zero: .long 0x0,0x0 +.PIC.zero.up: + retl + add %o0,%o7,%o0 +#ifdef DEBUG +.global walk_reg_wins +.type walk_reg_wins,#function +walk_reg_wins: +#endif +.walk.reg.wins: + save %sp,FRAME,%sp + cmp %i7,%o7 + be 2f + clr %o0 + cmp %o7,0 ! compiler never cleans %o7... + be 1f ! could have been a leaf function... + clr %o1 + call .walk.reg.wins + nop +1: clr %o2 + clr %o3 + clr %o4 + clr %o5 + clr %o7 + clr %l0 + clr %l1 + clr %l2 + clr %l3 + clr %l4 + clr %l5 + clr %l6 + clr %l7 + add %o0,1,%i0 ! used for debugging +2: ret + restore +.size OPENSSL_wipe_cpu,.-OPENSSL_wipe_cpu + +.global OPENSSL_atomic_add +.type OPENSSL_atomic_add,#function +.align 32 +OPENSSL_atomic_add: +#ifndef ABI64 + subcc %g0,1,%o2 + .word 0x95408000 !rd %ccr,%o2, see comment above + cmp %o2,0x99 + be .v9 + nop + save %sp,FRAME,%sp + ba .enter + nop +#ifdef __sun +! Note that you do not have to link with libthread to call thr_yield, +! as libc provides a stub, which is overloaded the moment you link +! with *either* libpthread or libthread... +#define YIELD_CPU thr_yield +#else +! applies at least to Linux and FreeBSD... Feedback expected... +#define YIELD_CPU sched_yield +#endif +.spin: call YIELD_CPU + nop +.enter: ld [%i0],%i2 + cmp %i2,-4096 + be .spin + mov -1,%i2 + swap [%i0],%i2 + cmp %i2,-1 + be .spin + add %i2,%i1,%i2 + stbar + st %i2,[%i0] + sra %i2,%g0,%i0 + ret + restore +.v9: +#endif + ld [%o0],%o2 +1: add %o1,%o2,%o3 + .word 0xd7e2100a !cas [%o0],%o2,%o3, compare [%o0] with %o2 and swap %o3 + cmp %o2,%o3 + bne 1b + mov %o3,%o2 ! cas is always fetching to dest. register + add %o1,%o2,%o0 ! OpenSSL expects the new value + retl + sra %o0,%g0,%o0 ! we return signed int, remember? +.size OPENSSL_atomic_add,.-OPENSSL_atomic_add + +.global _sparcv9_rdtick +.align 32 +_sparcv9_rdtick: + subcc %g0,1,%o0 + .word 0x91408000 !rd %ccr,%o0 + cmp %o0,0x99 + bne .notick + xor %o0,%o0,%o0 + .word 0x91410000 !rd %tick,%o0 + retl + .word 0x93323020 !srlx %o0,32,%o1 +.notick: + retl + xor %o1,%o1,%o1 +.type _sparcv9_rdtick,#function +.size _sparcv9_rdtick,.-_sparcv9_rdtick + +.global _sparcv9_vis1_probe +.align 8 +_sparcv9_vis1_probe: + add %sp,BIAS+2,%o1 + .word 0xc19a5a40 !ldda [%o1]ASI_FP16_P,%f0 + retl + .word 0x81b00d80 !fxor %f0,%f0,%f0 +.type _sparcv9_vis1_probe,#function +.size _sparcv9_vis1_probe,.-_sparcv9_vis1_probe + +! Probe and instrument VIS1 instruction. Output is number of cycles it +! takes to execute rdtick and pair of VIS1 instructions. US-Tx VIS unit +! is slow (documented to be 6 cycles on T2) and the core is in-order +! single-issue, it should be possible to distinguish Tx reliably... +! Observed return values are: +! +! UltraSPARC IIe 7 +! UltraSPARC III 7 +! UltraSPARC T1 24 +! SPARC T4 65(*) +! +! (*) result has lesser to do with VIS instruction latencies, rdtick +! appears that slow, but it does the trick in sense that FP and +! VIS code paths are still slower than integer-only ones. +! +! Numbers for T2 and SPARC64 V-VII are more than welcomed. +! +! It would be possible to detect specifically US-T1 by instrumenting +! fmul8ulx16, which is emulated on T1 and as such accounts for quite +! a lot of %tick-s, couple of thousand on Linux... +.global _sparcv9_vis1_instrument +.align 8 +_sparcv9_vis1_instrument: + .word 0x81b00d80 !fxor %f0,%f0,%f0 + .word 0x85b08d82 !fxor %f2,%f2,%f2 + .word 0x91410000 !rd %tick,%o0 + .word 0x81b00d80 !fxor %f0,%f0,%f0 + .word 0x85b08d82 !fxor %f2,%f2,%f2 + .word 0x93410000 !rd %tick,%o1 + .word 0x81b00d80 !fxor %f0,%f0,%f0 + .word 0x85b08d82 !fxor %f2,%f2,%f2 + .word 0x95410000 !rd %tick,%o2 + .word 0x81b00d80 !fxor %f0,%f0,%f0 + .word 0x85b08d82 !fxor %f2,%f2,%f2 + .word 0x97410000 !rd %tick,%o3 + .word 0x81b00d80 !fxor %f0,%f0,%f0 + .word 0x85b08d82 !fxor %f2,%f2,%f2 + .word 0x99410000 !rd %tick,%o4 + + ! calculate intervals + sub %o1,%o0,%o0 + sub %o2,%o1,%o1 + sub %o3,%o2,%o2 + sub %o4,%o3,%o3 + + ! find minimum value + cmp %o0,%o1 + .word 0x38680002 !bgu,a %xcc,.+8 + mov %o1,%o0 + cmp %o0,%o2 + .word 0x38680002 !bgu,a %xcc,.+8 + mov %o2,%o0 + cmp %o0,%o3 + .word 0x38680002 !bgu,a %xcc,.+8 + mov %o3,%o0 + + retl + nop +.type _sparcv9_vis1_instrument,#function +.size _sparcv9_vis1_instrument,.-_sparcv9_vis1_instrument + +.global _sparcv9_vis2_probe +.align 8 +_sparcv9_vis2_probe: + retl + .word 0x81b00980 !bshuffle %f0,%f0,%f0 +.type _sparcv9_vis2_probe,#function +.size _sparcv9_vis2_probe,.-_sparcv9_vis2_probe + +.global _sparcv9_fmadd_probe +.align 8 +_sparcv9_fmadd_probe: + .word 0x81b00d80 !fxor %f0,%f0,%f0 + .word 0x85b08d82 !fxor %f2,%f2,%f2 + retl + .word 0x81b80440 !fmaddd %f0,%f0,%f2,%f0 +.type _sparcv9_fmadd_probe,#function +.size _sparcv9_fmadd_probe,.-_sparcv9_fmadd_probe + +.global _sparcv9_rdcfr +.align 8 +_sparcv9_rdcfr: + retl + .word 0x91468000 !rd %asr26,%o0 +.type _sparcv9_rdcfr,#function +.size _sparcv9_rdcfr,.-_sparcv9_rdcfr + +.global _sparcv9_vis3_probe +.align 8 +_sparcv9_vis3_probe: + retl + .word 0x81b022a0 !xmulx %g0,%g0,%g0 +.type _sparcv9_vis3_probe,#function +.size _sparcv9_vis3_probe,.-_sparcv9_vis3_probe + +.global _sparcv9_random +.align 8 +_sparcv9_random: + retl + .word 0x91b002a0 !random %o0 +.type _sparcv9_random,#function +.size _sparcv9_random,.-_sparcv9_vis3_probe + +.global _sparcv9_fjaesx_probe +.align 8 +_sparcv9_fjaesx_probe: + .word 0x81b09206 !faesencx %f2,%f6,%f0 + retl + nop +.size _sparcv9_fjaesx_probe,.-_sparcv9_fjaesx_probe + +.global OPENSSL_cleanse +.align 32 +OPENSSL_cleanse: + cmp %o1,14 + nop +#ifdef ABI64 + bgu %xcc,.Lot +#else + bgu .Lot +#endif + cmp %o1,0 + bne .Little + nop + retl + nop + +.Little: + stb %g0,[%o0] + subcc %o1,1,%o1 + bnz .Little + add %o0,1,%o0 + retl + nop +.align 32 +.Lot: +#ifndef ABI64 + subcc %g0,1,%g1 + ! see above for explanation + .word 0x83408000 !rd %ccr,%g1 + cmp %g1,0x99 + bne .v8lot + nop +#endif + +.v9lot: andcc %o0,7,%g0 + bz .v9aligned + nop + stb %g0,[%o0] + sub %o1,1,%o1 + ba .v9lot + add %o0,1,%o0 +.align 16,0x01000000 +.v9aligned: + .word 0xc0720000 !stx %g0,[%o0] + sub %o1,8,%o1 + andcc %o1,-8,%g0 +#ifdef ABI64 + .word 0x126ffffd !bnz %xcc,.v9aligned +#else + .word 0x124ffffd !bnz %icc,.v9aligned +#endif + add %o0,8,%o0 + + cmp %o1,0 + bne .Little + nop + retl + nop +#ifndef ABI64 +.v8lot: andcc %o0,3,%g0 + bz .v8aligned + nop + stb %g0,[%o0] + sub %o1,1,%o1 + ba .v8lot + add %o0,1,%o0 + nop +.v8aligned: + st %g0,[%o0] + sub %o1,4,%o1 + andcc %o1,-4,%g0 + bnz .v8aligned + add %o0,4,%o0 + + cmp %o1,0 + bne .Little + nop + retl + nop +#endif +.type OPENSSL_cleanse,#function +.size OPENSSL_cleanse,.-OPENSSL_cleanse + +.global CRYPTO_memcmp +.align 16 +CRYPTO_memcmp: + cmp %o2,0 +#ifdef ABI64 + beq,pn %xcc,.Lno_data +#else + beq .Lno_data +#endif + xor %g1,%g1,%g1 + nop + +.Loop_cmp: + ldub [%o0],%o3 + add %o0,1,%o0 + ldub [%o1],%o4 + add %o1,1,%o1 + subcc %o2,1,%o2 + xor %o3,%o4,%o4 +#ifdef ABI64 + bnz %xcc,.Loop_cmp +#else + bnz .Loop_cmp +#endif + or %o4,%g1,%g1 + + sub %g0,%g1,%g1 + srl %g1,31,%g1 +.Lno_data: + retl + mov %g1,%o0 +.type CRYPTO_memcmp,#function +.size CRYPTO_memcmp,.-CRYPTO_memcmp + +.global _sparcv9_vis1_instrument_bus +.align 8 +_sparcv9_vis1_instrument_bus: + mov %o1,%o3 ! save cnt + .word 0x99410000 !rd %tick,%o4 ! tick + mov %o4,%o5 ! lasttick = tick + set 0,%g4 ! diff + + andn %o0,63,%g1 + .word 0xc1985e00 !ldda [%g1]0xf0,%f0 ! block load + .word 0x8143e040 !membar #Sync + .word 0xc1b85c00 !stda %f0,[%g1]0xe0 ! block store and commit + .word 0x8143e040 !membar #Sync + ld [%o0],%o4 + add %o4,%g4,%g4 + .word 0xc9e2100c !cas [%o0],%o4,%g4 + +.Loop: .word 0x99410000 !rd %tick,%o4 + sub %o4,%o5,%g4 ! diff=tick-lasttick + mov %o4,%o5 ! lasttick=tick + + andn %o0,63,%g1 + .word 0xc1985e00 !ldda [%g1]0xf0,%f0 ! block load + .word 0x8143e040 !membar #Sync + .word 0xc1b85c00 !stda %f0,[%g1]0xe0 ! block store and commit + .word 0x8143e040 !membar #Sync + ld [%o0],%o4 + add %o4,%g4,%g4 + .word 0xc9e2100c !cas [%o0],%o4,%g4 + subcc %o1,1,%o1 ! --$cnt + bnz .Loop + add %o0,4,%o0 ! ++$out + + retl + mov %o3,%o0 +.type _sparcv9_vis1_instrument_bus,#function +.size _sparcv9_vis1_instrument_bus,.-_sparcv9_vis1_instrument_bus + +.global _sparcv9_vis1_instrument_bus2 +.align 8 +_sparcv9_vis1_instrument_bus2: + mov %o1,%o3 ! save cnt + sll %o1,2,%o1 ! cnt*=4 + + .word 0x99410000 !rd %tick,%o4 ! tick + mov %o4,%o5 ! lasttick = tick + set 0,%g4 ! diff + + andn %o0,63,%g1 + .word 0xc1985e00 !ldda [%g1]0xf0,%f0 ! block load + .word 0x8143e040 !membar #Sync + .word 0xc1b85c00 !stda %f0,[%g1]0xe0 ! block store and commit + .word 0x8143e040 !membar #Sync + ld [%o0],%o4 + add %o4,%g4,%g4 + .word 0xc9e2100c !cas [%o0],%o4,%g4 + + .word 0x99410000 !rd %tick,%o4 ! tick + sub %o4,%o5,%g4 ! diff=tick-lasttick + mov %o4,%o5 ! lasttick=tick + mov %g4,%g5 ! lastdiff=diff +.Loop2: + andn %o0,63,%g1 + .word 0xc1985e00 !ldda [%g1]0xf0,%f0 ! block load + .word 0x8143e040 !membar #Sync + .word 0xc1b85c00 !stda %f0,[%g1]0xe0 ! block store and commit + .word 0x8143e040 !membar #Sync + ld [%o0],%o4 + add %o4,%g4,%g4 + .word 0xc9e2100c !cas [%o0],%o4,%g4 + + subcc %o2,1,%o2 ! --max + bz .Ldone2 + nop + + .word 0x99410000 !rd %tick,%o4 ! tick + sub %o4,%o5,%g4 ! diff=tick-lasttick + mov %o4,%o5 ! lasttick=tick + cmp %g4,%g5 + mov %g4,%g5 ! lastdiff=diff + + .word 0x83408000 !rd %ccr,%g1 + and %g1,4,%g1 ! isolate zero flag + xor %g1,4,%g1 ! flip zero flag + + subcc %o1,%g1,%o1 ! conditional --$cnt + bnz .Loop2 + add %o0,%g1,%o0 ! conditional ++$out + +.Ldone2: + srl %o1,2,%o1 + retl + sub %o3,%o1,%o0 +.type _sparcv9_vis1_instrument_bus2,#function +.size _sparcv9_vis1_instrument_bus2,.-_sparcv9_vis1_instrument_bus2 + +.section ".init",#alloc,#execinstr + call OPENSSL_cpuid_setup + nop diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/sparcv9cap.c b/trunk/3rdparty/openssl-1.1-fit/crypto/sparcv9cap.c new file mode 100644 index 000000000..c8c567536 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/sparcv9cap.c @@ -0,0 +1,295 @@ +/* + * Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "internal/cryptlib.h" + +#include "sparc_arch.h" + +#if defined(__GNUC__) && defined(__linux) +__attribute__ ((visibility("hidden"))) +#endif +unsigned int OPENSSL_sparcv9cap_P[2] = { SPARCV9_TICK_PRIVILEGED, 0 }; + +int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + const BN_ULONG *np, const BN_ULONG *n0, int num) +{ + int bn_mul_mont_vis3(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + const BN_ULONG *np, const BN_ULONG *n0, int num); + int bn_mul_mont_fpu(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + const BN_ULONG *np, const BN_ULONG *n0, int num); + int bn_mul_mont_int(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + const BN_ULONG *np, const BN_ULONG *n0, int num); + + if (!(num & 1) && num >= 6) { + if ((num & 15) == 0 && num <= 64 && + (OPENSSL_sparcv9cap_P[1] & (CFR_MONTMUL | CFR_MONTSQR)) == + (CFR_MONTMUL | CFR_MONTSQR)) { + typedef int (*bn_mul_mont_f) (BN_ULONG *rp, const BN_ULONG *ap, + const BN_ULONG *bp, + const BN_ULONG *np, + const BN_ULONG *n0); + int bn_mul_mont_t4_8(BN_ULONG *rp, const BN_ULONG *ap, + const BN_ULONG *bp, const BN_ULONG *np, + const BN_ULONG *n0); + int bn_mul_mont_t4_16(BN_ULONG *rp, const BN_ULONG *ap, + const BN_ULONG *bp, const BN_ULONG *np, + const BN_ULONG *n0); + int bn_mul_mont_t4_24(BN_ULONG *rp, const BN_ULONG *ap, + const BN_ULONG *bp, const BN_ULONG *np, + const BN_ULONG *n0); + int bn_mul_mont_t4_32(BN_ULONG *rp, const BN_ULONG *ap, + const BN_ULONG *bp, const BN_ULONG *np, + const BN_ULONG *n0); + static const bn_mul_mont_f funcs[4] = { + bn_mul_mont_t4_8, bn_mul_mont_t4_16, + bn_mul_mont_t4_24, bn_mul_mont_t4_32 + }; + bn_mul_mont_f worker = funcs[num / 16 - 1]; + + if ((*worker) (rp, ap, bp, np, n0)) + return 1; + /* retry once and fall back */ + if ((*worker) (rp, ap, bp, np, n0)) + return 1; + return bn_mul_mont_vis3(rp, ap, bp, np, n0, num); + } + if ((OPENSSL_sparcv9cap_P[0] & SPARCV9_VIS3)) + return bn_mul_mont_vis3(rp, ap, bp, np, n0, num); + else if (num >= 8 && + /* + * bn_mul_mont_fpu doesn't use FMADD, we just use the + * flag to detect when FPU path is preferable in cases + * when current heuristics is unreliable. [it works + * out because FMADD-capable processors where FPU + * code path is undesirable are also VIS3-capable and + * VIS3 code path takes precedence.] + */ + ( (OPENSSL_sparcv9cap_P[0] & SPARCV9_FMADD) || + (OPENSSL_sparcv9cap_P[0] & + (SPARCV9_PREFER_FPU | SPARCV9_VIS1)) == + (SPARCV9_PREFER_FPU | SPARCV9_VIS1) )) + return bn_mul_mont_fpu(rp, ap, bp, np, n0, num); + } + return bn_mul_mont_int(rp, ap, bp, np, n0, num); +} + +unsigned long _sparcv9_rdtick(void); +void _sparcv9_vis1_probe(void); +unsigned long _sparcv9_vis1_instrument(void); +void _sparcv9_vis2_probe(void); +void _sparcv9_fmadd_probe(void); +unsigned long _sparcv9_rdcfr(void); +void _sparcv9_vis3_probe(void); +void _sparcv9_fjaesx_probe(void); +unsigned long _sparcv9_random(void); +size_t _sparcv9_vis1_instrument_bus(unsigned int *, size_t); +size_t _sparcv9_vis1_instrument_bus2(unsigned int *, size_t, size_t); + +uint32_t OPENSSL_rdtsc(void) +{ + if (OPENSSL_sparcv9cap_P[0] & SPARCV9_TICK_PRIVILEGED) +#if defined(__sun) && defined(__SVR4) + return gethrtime(); +#else + return 0; +#endif + else + return _sparcv9_rdtick(); +} + +size_t OPENSSL_instrument_bus(unsigned int *out, size_t cnt) +{ + if ((OPENSSL_sparcv9cap_P[0] & (SPARCV9_TICK_PRIVILEGED | SPARCV9_BLK)) == + SPARCV9_BLK) + return _sparcv9_vis1_instrument_bus(out, cnt); + else + return 0; +} + +size_t OPENSSL_instrument_bus2(unsigned int *out, size_t cnt, size_t max) +{ + if ((OPENSSL_sparcv9cap_P[0] & (SPARCV9_TICK_PRIVILEGED | SPARCV9_BLK)) == + SPARCV9_BLK) + return _sparcv9_vis1_instrument_bus2(out, cnt, max); + else + return 0; +} + +static sigjmp_buf common_jmp; +static void common_handler(int sig) +{ + siglongjmp(common_jmp, sig); +} + +#if defined(__sun) && defined(__SVR4) +# if defined(__GNUC__) && __GNUC__>=2 +extern unsigned int getisax(unsigned int vec[], unsigned int sz) __attribute__ ((weak)); +# elif defined(__SUNPRO_C) +#pragma weak getisax +extern unsigned int getisax(unsigned int vec[], unsigned int sz); +# else +static unsigned int (*getisax) (unsigned int vec[], unsigned int sz) = NULL; +# endif +#endif + +void OPENSSL_cpuid_setup(void) +{ + char *e; + struct sigaction common_act, ill_oact, bus_oact; + sigset_t all_masked, oset; + static int trigger = 0; + + if (trigger) + return; + trigger = 1; + + if ((e = getenv("OPENSSL_sparcv9cap"))) { + OPENSSL_sparcv9cap_P[0] = strtoul(e, NULL, 0); + if ((e = strchr(e, ':'))) + OPENSSL_sparcv9cap_P[1] = strtoul(e + 1, NULL, 0); + return; + } + +#if defined(__sun) && defined(__SVR4) + if (getisax != NULL) { + unsigned int vec[2] = { 0, 0 }; + + if (getisax (vec,2)) { + if (vec[0]&0x00020) OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS1; + if (vec[0]&0x00040) OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS2; + if (vec[0]&0x00080) OPENSSL_sparcv9cap_P[0] |= SPARCV9_BLK; + if (vec[0]&0x00100) OPENSSL_sparcv9cap_P[0] |= SPARCV9_FMADD; + if (vec[0]&0x00400) OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS3; + if (vec[0]&0x01000) OPENSSL_sparcv9cap_P[0] |= SPARCV9_FJHPCACE; + if (vec[0]&0x02000) OPENSSL_sparcv9cap_P[0] |= SPARCV9_FJDESX; + if (vec[0]&0x08000) OPENSSL_sparcv9cap_P[0] |= SPARCV9_IMA; + if (vec[0]&0x10000) OPENSSL_sparcv9cap_P[0] |= SPARCV9_FJAESX; + if (vec[1]&0x00008) OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS4; + + /* reconstruct %cfr copy */ + OPENSSL_sparcv9cap_P[1] = (vec[0]>>17)&0x3ff; + OPENSSL_sparcv9cap_P[1] |= (OPENSSL_sparcv9cap_P[1]&CFR_MONTMUL)<<1; + if (vec[0]&0x20000000) OPENSSL_sparcv9cap_P[1] |= CFR_CRC32C; + if (vec[1]&0x00000020) OPENSSL_sparcv9cap_P[1] |= CFR_XMPMUL; + if (vec[1]&0x00000040) + OPENSSL_sparcv9cap_P[1] |= CFR_XMONTMUL|CFR_XMONTSQR; + + /* Some heuristics */ + /* all known VIS2-capable CPUs have unprivileged tick counter */ + if (OPENSSL_sparcv9cap_P[0]&SPARCV9_VIS2) + OPENSSL_sparcv9cap_P[0] &= ~SPARCV9_TICK_PRIVILEGED; + + OPENSSL_sparcv9cap_P[0] |= SPARCV9_PREFER_FPU; + + /* detect UltraSPARC-Tx, see sparccpud.S for details... */ + if ((OPENSSL_sparcv9cap_P[0]&SPARCV9_VIS1) && + _sparcv9_vis1_instrument() >= 12) + OPENSSL_sparcv9cap_P[0] &= ~(SPARCV9_VIS1 | SPARCV9_PREFER_FPU); + } + + if (sizeof(size_t) == 8) + OPENSSL_sparcv9cap_P[0] |= SPARCV9_64BIT_STACK; + + return; + } +#endif + + /* Initial value, fits UltraSPARC-I&II... */ + OPENSSL_sparcv9cap_P[0] = SPARCV9_PREFER_FPU | SPARCV9_TICK_PRIVILEGED; + + sigfillset(&all_masked); + sigdelset(&all_masked, SIGILL); + sigdelset(&all_masked, SIGTRAP); +# ifdef SIGEMT + sigdelset(&all_masked, SIGEMT); +# endif + sigdelset(&all_masked, SIGFPE); + sigdelset(&all_masked, SIGBUS); + sigdelset(&all_masked, SIGSEGV); + sigprocmask(SIG_SETMASK, &all_masked, &oset); + + memset(&common_act, 0, sizeof(common_act)); + common_act.sa_handler = common_handler; + common_act.sa_mask = all_masked; + + sigaction(SIGILL, &common_act, &ill_oact); + sigaction(SIGBUS, &common_act, &bus_oact); /* T1 fails 16-bit ldda [on + * Linux] */ + + if (sigsetjmp(common_jmp, 1) == 0) { + _sparcv9_rdtick(); + OPENSSL_sparcv9cap_P[0] &= ~SPARCV9_TICK_PRIVILEGED; + } + + if (sigsetjmp(common_jmp, 1) == 0) { + _sparcv9_vis1_probe(); + OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS1 | SPARCV9_BLK; + /* detect UltraSPARC-Tx, see sparccpud.S for details... */ + if (_sparcv9_vis1_instrument() >= 12) + OPENSSL_sparcv9cap_P[0] &= ~(SPARCV9_VIS1 | SPARCV9_PREFER_FPU); + else { + _sparcv9_vis2_probe(); + OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS2; + } + } + + if (sigsetjmp(common_jmp, 1) == 0) { + _sparcv9_fmadd_probe(); + OPENSSL_sparcv9cap_P[0] |= SPARCV9_FMADD; + } + + /* + * VIS3 flag is tested independently from VIS1, unlike VIS2 that is, + * because VIS3 defines even integer instructions. + */ + if (sigsetjmp(common_jmp, 1) == 0) { + _sparcv9_vis3_probe(); + OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS3; + } + + if (sigsetjmp(common_jmp, 1) == 0) { + _sparcv9_fjaesx_probe(); + OPENSSL_sparcv9cap_P[0] |= SPARCV9_FJAESX; + } + + /* + * In wait for better solution _sparcv9_rdcfr is masked by + * VIS3 flag, because it goes to uninterruptable endless + * loop on UltraSPARC II running Solaris. Things might be + * different on Linux... + */ + if ((OPENSSL_sparcv9cap_P[0] & SPARCV9_VIS3) && + sigsetjmp(common_jmp, 1) == 0) { + OPENSSL_sparcv9cap_P[1] = (unsigned int)_sparcv9_rdcfr(); + } + + sigaction(SIGBUS, &bus_oact, NULL); + sigaction(SIGILL, &ill_oact, NULL); + + sigprocmask(SIG_SETMASK, &oset, NULL); + + if (sizeof(size_t) == 8) + OPENSSL_sparcv9cap_P[0] |= SPARCV9_64BIT_STACK; +# ifdef __linux + else { + int ret = syscall(340); + + if (ret >= 0 && ret & 1) + OPENSSL_sparcv9cap_P[0] |= SPARCV9_64BIT_STACK; + } +# endif +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/srp/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/srp/build.info new file mode 100644 index 000000000..b6c7fe7ad --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/srp/build.info @@ -0,0 +1,2 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=srp_lib.c srp_vfy.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/srp/srp_lib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/srp/srp_lib.c new file mode 100644 index 000000000..ca20f6d09 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/srp/srp_lib.c @@ -0,0 +1,286 @@ +/* + * Copyright 2004-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2004, EdelKey Project. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + * + * Originally written by Christophe Renou and Peter Sylvester, + * for the EdelKey project. + */ + +#ifndef OPENSSL_NO_SRP +# include "internal/cryptlib.h" +# include +# include +# include +# include "internal/bn_srp.h" + +/* calculate = SHA1(PAD(x) || PAD(y)) */ + +static BIGNUM *srp_Calc_xy(const BIGNUM *x, const BIGNUM *y, const BIGNUM *N) +{ + unsigned char digest[SHA_DIGEST_LENGTH]; + unsigned char *tmp = NULL; + int numN = BN_num_bytes(N); + BIGNUM *res = NULL; + + if (x != N && BN_ucmp(x, N) >= 0) + return NULL; + if (y != N && BN_ucmp(y, N) >= 0) + return NULL; + if ((tmp = OPENSSL_malloc(numN * 2)) == NULL) + goto err; + if (BN_bn2binpad(x, tmp, numN) < 0 + || BN_bn2binpad(y, tmp + numN, numN) < 0 + || !EVP_Digest(tmp, numN * 2, digest, NULL, EVP_sha1(), NULL)) + goto err; + res = BN_bin2bn(digest, sizeof(digest), NULL); + err: + OPENSSL_free(tmp); + return res; +} + +static BIGNUM *srp_Calc_k(const BIGNUM *N, const BIGNUM *g) +{ + /* k = SHA1(N | PAD(g)) -- tls-srp draft 8 */ + return srp_Calc_xy(N, g, N); +} + +BIGNUM *SRP_Calc_u(const BIGNUM *A, const BIGNUM *B, const BIGNUM *N) +{ + /* k = SHA1(PAD(A) || PAD(B) ) -- tls-srp draft 8 */ + return srp_Calc_xy(A, B, N); +} + +BIGNUM *SRP_Calc_server_key(const BIGNUM *A, const BIGNUM *v, const BIGNUM *u, + const BIGNUM *b, const BIGNUM *N) +{ + BIGNUM *tmp = NULL, *S = NULL; + BN_CTX *bn_ctx; + + if (u == NULL || A == NULL || v == NULL || b == NULL || N == NULL) + return NULL; + + if ((bn_ctx = BN_CTX_new()) == NULL || (tmp = BN_new()) == NULL) + goto err; + + /* S = (A*v**u) ** b */ + + if (!BN_mod_exp(tmp, v, u, N, bn_ctx)) + goto err; + if (!BN_mod_mul(tmp, A, tmp, N, bn_ctx)) + goto err; + + S = BN_new(); + if (S != NULL && !BN_mod_exp(S, tmp, b, N, bn_ctx)) { + BN_free(S); + S = NULL; + } + err: + BN_CTX_free(bn_ctx); + BN_clear_free(tmp); + return S; +} + +BIGNUM *SRP_Calc_B(const BIGNUM *b, const BIGNUM *N, const BIGNUM *g, + const BIGNUM *v) +{ + BIGNUM *kv = NULL, *gb = NULL; + BIGNUM *B = NULL, *k = NULL; + BN_CTX *bn_ctx; + + if (b == NULL || N == NULL || g == NULL || v == NULL || + (bn_ctx = BN_CTX_new()) == NULL) + return NULL; + + if ((kv = BN_new()) == NULL || + (gb = BN_new()) == NULL || (B = BN_new()) == NULL) + goto err; + + /* B = g**b + k*v */ + + if (!BN_mod_exp(gb, g, b, N, bn_ctx) + || (k = srp_Calc_k(N, g)) == NULL + || !BN_mod_mul(kv, v, k, N, bn_ctx) + || !BN_mod_add(B, gb, kv, N, bn_ctx)) { + BN_free(B); + B = NULL; + } + err: + BN_CTX_free(bn_ctx); + BN_clear_free(kv); + BN_clear_free(gb); + BN_free(k); + return B; +} + +BIGNUM *SRP_Calc_x(const BIGNUM *s, const char *user, const char *pass) +{ + unsigned char dig[SHA_DIGEST_LENGTH]; + EVP_MD_CTX *ctxt; + unsigned char *cs = NULL; + BIGNUM *res = NULL; + + if ((s == NULL) || (user == NULL) || (pass == NULL)) + return NULL; + + ctxt = EVP_MD_CTX_new(); + if (ctxt == NULL) + return NULL; + if ((cs = OPENSSL_malloc(BN_num_bytes(s))) == NULL) + goto err; + + if (!EVP_DigestInit_ex(ctxt, EVP_sha1(), NULL) + || !EVP_DigestUpdate(ctxt, user, strlen(user)) + || !EVP_DigestUpdate(ctxt, ":", 1) + || !EVP_DigestUpdate(ctxt, pass, strlen(pass)) + || !EVP_DigestFinal_ex(ctxt, dig, NULL) + || !EVP_DigestInit_ex(ctxt, EVP_sha1(), NULL)) + goto err; + if (BN_bn2bin(s, cs) < 0) + goto err; + if (!EVP_DigestUpdate(ctxt, cs, BN_num_bytes(s))) + goto err; + + if (!EVP_DigestUpdate(ctxt, dig, sizeof(dig)) + || !EVP_DigestFinal_ex(ctxt, dig, NULL)) + goto err; + + res = BN_bin2bn(dig, sizeof(dig), NULL); + + err: + OPENSSL_free(cs); + EVP_MD_CTX_free(ctxt); + return res; +} + +BIGNUM *SRP_Calc_A(const BIGNUM *a, const BIGNUM *N, const BIGNUM *g) +{ + BN_CTX *bn_ctx; + BIGNUM *A = NULL; + + if (a == NULL || N == NULL || g == NULL || (bn_ctx = BN_CTX_new()) == NULL) + return NULL; + + if ((A = BN_new()) != NULL && !BN_mod_exp(A, g, a, N, bn_ctx)) { + BN_free(A); + A = NULL; + } + BN_CTX_free(bn_ctx); + return A; +} + +BIGNUM *SRP_Calc_client_key(const BIGNUM *N, const BIGNUM *B, const BIGNUM *g, + const BIGNUM *x, const BIGNUM *a, const BIGNUM *u) +{ + BIGNUM *tmp = NULL, *tmp2 = NULL, *tmp3 = NULL, *k = NULL, *K = NULL; + BN_CTX *bn_ctx; + + if (u == NULL || B == NULL || N == NULL || g == NULL || x == NULL + || a == NULL || (bn_ctx = BN_CTX_new()) == NULL) + return NULL; + + if ((tmp = BN_new()) == NULL || + (tmp2 = BN_new()) == NULL || + (tmp3 = BN_new()) == NULL) + goto err; + + if (!BN_mod_exp(tmp, g, x, N, bn_ctx)) + goto err; + if ((k = srp_Calc_k(N, g)) == NULL) + goto err; + if (!BN_mod_mul(tmp2, tmp, k, N, bn_ctx)) + goto err; + if (!BN_mod_sub(tmp, B, tmp2, N, bn_ctx)) + goto err; + if (!BN_mul(tmp3, u, x, bn_ctx)) + goto err; + if (!BN_add(tmp2, a, tmp3)) + goto err; + K = BN_new(); + if (K != NULL && !BN_mod_exp(K, tmp, tmp2, N, bn_ctx)) { + BN_free(K); + K = NULL; + } + + err: + BN_CTX_free(bn_ctx); + BN_clear_free(tmp); + BN_clear_free(tmp2); + BN_clear_free(tmp3); + BN_free(k); + return K; +} + +int SRP_Verify_B_mod_N(const BIGNUM *B, const BIGNUM *N) +{ + BIGNUM *r; + BN_CTX *bn_ctx; + int ret = 0; + + if (B == NULL || N == NULL || (bn_ctx = BN_CTX_new()) == NULL) + return 0; + + if ((r = BN_new()) == NULL) + goto err; + /* Checks if B % N == 0 */ + if (!BN_nnmod(r, B, N, bn_ctx)) + goto err; + ret = !BN_is_zero(r); + err: + BN_CTX_free(bn_ctx); + BN_free(r); + return ret; +} + +int SRP_Verify_A_mod_N(const BIGNUM *A, const BIGNUM *N) +{ + /* Checks if A % N == 0 */ + return SRP_Verify_B_mod_N(A, N); +} + +static SRP_gN knowngN[] = { + {"8192", &bn_generator_19, &bn_group_8192}, + {"6144", &bn_generator_5, &bn_group_6144}, + {"4096", &bn_generator_5, &bn_group_4096}, + {"3072", &bn_generator_5, &bn_group_3072}, + {"2048", &bn_generator_2, &bn_group_2048}, + {"1536", &bn_generator_2, &bn_group_1536}, + {"1024", &bn_generator_2, &bn_group_1024}, +}; + +# define KNOWN_GN_NUMBER sizeof(knowngN) / sizeof(SRP_gN) + +/* + * Check if G and N are known parameters. The values have been generated + * from the ietf-tls-srp draft version 8 + */ +char *SRP_check_known_gN_param(const BIGNUM *g, const BIGNUM *N) +{ + size_t i; + if ((g == NULL) || (N == NULL)) + return 0; + + for (i = 0; i < KNOWN_GN_NUMBER; i++) { + if (BN_cmp(knowngN[i].g, g) == 0 && BN_cmp(knowngN[i].N, N) == 0) + return knowngN[i].id; + } + return NULL; +} + +SRP_gN *SRP_get_default_gN(const char *id) +{ + size_t i; + + if (id == NULL) + return knowngN; + for (i = 0; i < KNOWN_GN_NUMBER; i++) { + if (strcmp(knowngN[i].id, id) == 0) + return knowngN + i; + } + return NULL; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/srp/srp_vfy.c b/trunk/3rdparty/openssl-1.1-fit/crypto/srp/srp_vfy.c new file mode 100644 index 000000000..eb279dd41 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/srp/srp_vfy.c @@ -0,0 +1,730 @@ +/* + * Copyright 2004-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2004, EdelKey Project. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + * + * Originally written by Christophe Renou and Peter Sylvester, + * for the EdelKey project. + */ + +#ifndef OPENSSL_NO_SRP +# include "internal/cryptlib.h" +# include "internal/evp_int.h" +# include +# include +# include +# include +# include +# include +# include + +# define SRP_RANDOM_SALT_LEN 20 +# define MAX_LEN 2500 + +/* + * Note that SRP uses its own variant of base 64 encoding. A different base64 + * alphabet is used and no padding '=' characters are added. Instead we pad to + * the front with 0 bytes and subsequently strip off leading encoded padding. + * This variant is used for compatibility with other SRP implementations - + * notably libsrp, but also others. It is also required for backwards + * compatibility in order to load verifier files from other OpenSSL versions. + */ + +/* + * Convert a base64 string into raw byte array representation. + * Returns the length of the decoded data, or -1 on error. + */ +static int t_fromb64(unsigned char *a, size_t alen, const char *src) +{ + EVP_ENCODE_CTX *ctx; + int outl = 0, outl2 = 0; + size_t size, padsize; + const unsigned char *pad = (const unsigned char *)"00"; + + while (*src == ' ' || *src == '\t' || *src == '\n') + ++src; + size = strlen(src); + padsize = 4 - (size & 3); + padsize &= 3; + + /* Four bytes in src become three bytes output. */ + if (size > INT_MAX || ((size + padsize) / 4) * 3 > alen) + return -1; + + ctx = EVP_ENCODE_CTX_new(); + if (ctx == NULL) + return -1; + + /* + * This should never occur because 1 byte of data always requires 2 bytes of + * encoding, i.e. + * 0 bytes unencoded = 0 bytes encoded + * 1 byte unencoded = 2 bytes encoded + * 2 bytes unencoded = 3 bytes encoded + * 3 bytes unencoded = 4 bytes encoded + * 4 bytes unencoded = 6 bytes encoded + * etc + */ + if (padsize == 3) { + outl = -1; + goto err; + } + + /* Valid padsize values are now 0, 1 or 2 */ + + EVP_DecodeInit(ctx); + evp_encode_ctx_set_flags(ctx, EVP_ENCODE_CTX_USE_SRP_ALPHABET); + + /* Add any encoded padding that is required */ + if (padsize != 0 + && EVP_DecodeUpdate(ctx, a, &outl, pad, padsize) < 0) { + outl = -1; + goto err; + } + if (EVP_DecodeUpdate(ctx, a, &outl2, (const unsigned char *)src, size) < 0) { + outl = -1; + goto err; + } + outl += outl2; + EVP_DecodeFinal(ctx, a + outl, &outl2); + outl += outl2; + + /* Strip off the leading padding */ + if (padsize != 0) { + if ((int)padsize >= outl) { + outl = -1; + goto err; + } + + /* + * If we added 1 byte of padding prior to encoding then we have 2 bytes + * of "real" data which gets spread across 4 encoded bytes like this: + * (6 bits pad)(2 bits pad | 4 bits data)(6 bits data)(6 bits data) + * So 1 byte of pre-encoding padding results in 1 full byte of encoded + * padding. + * If we added 2 bytes of padding prior to encoding this gets encoded + * as: + * (6 bits pad)(6 bits pad)(4 bits pad | 2 bits data)(6 bits data) + * So 2 bytes of pre-encoding padding results in 2 full bytes of encoded + * padding, i.e. we have to strip the same number of bytes of padding + * from the encoded data as we added to the pre-encoded data. + */ + memmove(a, a + padsize, outl - padsize); + outl -= padsize; + } + + err: + EVP_ENCODE_CTX_free(ctx); + + return outl; +} + +/* + * Convert a raw byte string into a null-terminated base64 ASCII string. + * Returns 1 on success or 0 on error. + */ +static int t_tob64(char *dst, const unsigned char *src, int size) +{ + EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new(); + int outl = 0, outl2 = 0; + unsigned char pad[2] = {0, 0}; + size_t leadz = 0; + + if (ctx == NULL) + return 0; + + EVP_EncodeInit(ctx); + evp_encode_ctx_set_flags(ctx, EVP_ENCODE_CTX_NO_NEWLINES + | EVP_ENCODE_CTX_USE_SRP_ALPHABET); + + /* + * We pad at the front with zero bytes until the length is a multiple of 3 + * so that EVP_EncodeUpdate/EVP_EncodeFinal does not add any of its own "=" + * padding + */ + leadz = 3 - (size % 3); + if (leadz != 3 + && !EVP_EncodeUpdate(ctx, (unsigned char *)dst, &outl, pad, + leadz)) { + EVP_ENCODE_CTX_free(ctx); + return 0; + } + + if (!EVP_EncodeUpdate(ctx, (unsigned char *)dst + outl, &outl2, src, + size)) { + EVP_ENCODE_CTX_free(ctx); + return 0; + } + outl += outl2; + EVP_EncodeFinal(ctx, (unsigned char *)dst + outl, &outl2); + outl += outl2; + + /* Strip the encoded padding at the front */ + if (leadz != 3) { + memmove(dst, dst + leadz, outl - leadz); + dst[outl - leadz] = '\0'; + } + + EVP_ENCODE_CTX_free(ctx); + return 1; +} + +void SRP_user_pwd_free(SRP_user_pwd *user_pwd) +{ + if (user_pwd == NULL) + return; + BN_free(user_pwd->s); + BN_clear_free(user_pwd->v); + OPENSSL_free(user_pwd->id); + OPENSSL_free(user_pwd->info); + OPENSSL_free(user_pwd); +} + +static SRP_user_pwd *SRP_user_pwd_new(void) +{ + SRP_user_pwd *ret; + + if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) { + /* SRPerr(SRP_F_SRP_USER_PWD_NEW, ERR_R_MALLOC_FAILURE); */ /*ckerr_ignore*/ + return NULL; + } + ret->N = NULL; + ret->g = NULL; + ret->s = NULL; + ret->v = NULL; + ret->id = NULL; + ret->info = NULL; + return ret; +} + +static void SRP_user_pwd_set_gN(SRP_user_pwd *vinfo, const BIGNUM *g, + const BIGNUM *N) +{ + vinfo->N = N; + vinfo->g = g; +} + +static int SRP_user_pwd_set_ids(SRP_user_pwd *vinfo, const char *id, + const char *info) +{ + if (id != NULL && NULL == (vinfo->id = OPENSSL_strdup(id))) + return 0; + return (info == NULL || NULL != (vinfo->info = OPENSSL_strdup(info))); +} + +static int SRP_user_pwd_set_sv(SRP_user_pwd *vinfo, const char *s, + const char *v) +{ + unsigned char tmp[MAX_LEN]; + int len; + + vinfo->v = NULL; + vinfo->s = NULL; + + len = t_fromb64(tmp, sizeof(tmp), v); + if (len < 0) + return 0; + if (NULL == (vinfo->v = BN_bin2bn(tmp, len, NULL))) + return 0; + len = t_fromb64(tmp, sizeof(tmp), s); + if (len < 0) + goto err; + vinfo->s = BN_bin2bn(tmp, len, NULL); + if (vinfo->s == NULL) + goto err; + return 1; + err: + BN_free(vinfo->v); + vinfo->v = NULL; + return 0; +} + +static int SRP_user_pwd_set_sv_BN(SRP_user_pwd *vinfo, BIGNUM *s, BIGNUM *v) +{ + vinfo->v = v; + vinfo->s = s; + return (vinfo->s != NULL && vinfo->v != NULL); +} + +static SRP_user_pwd *srp_user_pwd_dup(SRP_user_pwd *src) +{ + SRP_user_pwd *ret; + + if (src == NULL) + return NULL; + if ((ret = SRP_user_pwd_new()) == NULL) + return NULL; + + SRP_user_pwd_set_gN(ret, src->g, src->N); + if (!SRP_user_pwd_set_ids(ret, src->id, src->info) + || !SRP_user_pwd_set_sv_BN(ret, BN_dup(src->s), BN_dup(src->v))) { + SRP_user_pwd_free(ret); + return NULL; + } + return ret; +} + +SRP_VBASE *SRP_VBASE_new(char *seed_key) +{ + SRP_VBASE *vb = OPENSSL_malloc(sizeof(*vb)); + + if (vb == NULL) + return NULL; + if ((vb->users_pwd = sk_SRP_user_pwd_new_null()) == NULL + || (vb->gN_cache = sk_SRP_gN_cache_new_null()) == NULL) { + OPENSSL_free(vb); + return NULL; + } + vb->default_g = NULL; + vb->default_N = NULL; + vb->seed_key = NULL; + if ((seed_key != NULL) && (vb->seed_key = OPENSSL_strdup(seed_key)) == NULL) { + sk_SRP_user_pwd_free(vb->users_pwd); + sk_SRP_gN_cache_free(vb->gN_cache); + OPENSSL_free(vb); + return NULL; + } + return vb; +} + +void SRP_VBASE_free(SRP_VBASE *vb) +{ + if (!vb) + return; + sk_SRP_user_pwd_pop_free(vb->users_pwd, SRP_user_pwd_free); + sk_SRP_gN_cache_free(vb->gN_cache); + OPENSSL_free(vb->seed_key); + OPENSSL_free(vb); +} + +static SRP_gN_cache *SRP_gN_new_init(const char *ch) +{ + unsigned char tmp[MAX_LEN]; + int len; + SRP_gN_cache *newgN = OPENSSL_malloc(sizeof(*newgN)); + + if (newgN == NULL) + return NULL; + + len = t_fromb64(tmp, sizeof(tmp), ch); + if (len < 0) + goto err; + + if ((newgN->b64_bn = OPENSSL_strdup(ch)) == NULL) + goto err; + + if ((newgN->bn = BN_bin2bn(tmp, len, NULL))) + return newgN; + + OPENSSL_free(newgN->b64_bn); + err: + OPENSSL_free(newgN); + return NULL; +} + +static void SRP_gN_free(SRP_gN_cache *gN_cache) +{ + if (gN_cache == NULL) + return; + OPENSSL_free(gN_cache->b64_bn); + BN_free(gN_cache->bn); + OPENSSL_free(gN_cache); +} + +static SRP_gN *SRP_get_gN_by_id(const char *id, STACK_OF(SRP_gN) *gN_tab) +{ + int i; + + SRP_gN *gN; + if (gN_tab != NULL) + for (i = 0; i < sk_SRP_gN_num(gN_tab); i++) { + gN = sk_SRP_gN_value(gN_tab, i); + if (gN && (id == NULL || strcmp(gN->id, id) == 0)) + return gN; + } + + return SRP_get_default_gN(id); +} + +static BIGNUM *SRP_gN_place_bn(STACK_OF(SRP_gN_cache) *gN_cache, char *ch) +{ + int i; + if (gN_cache == NULL) + return NULL; + + /* search if we have already one... */ + for (i = 0; i < sk_SRP_gN_cache_num(gN_cache); i++) { + SRP_gN_cache *cache = sk_SRP_gN_cache_value(gN_cache, i); + if (strcmp(cache->b64_bn, ch) == 0) + return cache->bn; + } + { /* it is the first time that we find it */ + SRP_gN_cache *newgN = SRP_gN_new_init(ch); + if (newgN) { + if (sk_SRP_gN_cache_insert(gN_cache, newgN, 0) > 0) + return newgN->bn; + SRP_gN_free(newgN); + } + } + return NULL; +} + +/* + * this function parses verifier file. Format is: + * string(index):base64(N):base64(g):0 + * string(username):base64(v):base64(salt):int(index) + */ + +int SRP_VBASE_init(SRP_VBASE *vb, char *verifier_file) +{ + int error_code; + STACK_OF(SRP_gN) *SRP_gN_tab = sk_SRP_gN_new_null(); + char *last_index = NULL; + int i; + char **pp; + + SRP_gN *gN = NULL; + SRP_user_pwd *user_pwd = NULL; + + TXT_DB *tmpdb = NULL; + BIO *in = BIO_new(BIO_s_file()); + + error_code = SRP_ERR_OPEN_FILE; + + if (in == NULL || BIO_read_filename(in, verifier_file) <= 0) + goto err; + + error_code = SRP_ERR_VBASE_INCOMPLETE_FILE; + + if ((tmpdb = TXT_DB_read(in, DB_NUMBER)) == NULL) + goto err; + + error_code = SRP_ERR_MEMORY; + + if (vb->seed_key) { + last_index = SRP_get_default_gN(NULL)->id; + } + for (i = 0; i < sk_OPENSSL_PSTRING_num(tmpdb->data); i++) { + pp = sk_OPENSSL_PSTRING_value(tmpdb->data, i); + if (pp[DB_srptype][0] == DB_SRP_INDEX) { + /* + * we add this couple in the internal Stack + */ + + if ((gN = OPENSSL_malloc(sizeof(*gN))) == NULL) + goto err; + + if ((gN->id = OPENSSL_strdup(pp[DB_srpid])) == NULL + || (gN->N = SRP_gN_place_bn(vb->gN_cache, pp[DB_srpverifier])) + == NULL + || (gN->g = SRP_gN_place_bn(vb->gN_cache, pp[DB_srpsalt])) + == NULL + || sk_SRP_gN_insert(SRP_gN_tab, gN, 0) == 0) + goto err; + + gN = NULL; + + if (vb->seed_key != NULL) { + last_index = pp[DB_srpid]; + } + } else if (pp[DB_srptype][0] == DB_SRP_VALID) { + /* it is a user .... */ + const SRP_gN *lgN; + + if ((lgN = SRP_get_gN_by_id(pp[DB_srpgN], SRP_gN_tab)) != NULL) { + error_code = SRP_ERR_MEMORY; + if ((user_pwd = SRP_user_pwd_new()) == NULL) + goto err; + + SRP_user_pwd_set_gN(user_pwd, lgN->g, lgN->N); + if (!SRP_user_pwd_set_ids + (user_pwd, pp[DB_srpid], pp[DB_srpinfo])) + goto err; + + error_code = SRP_ERR_VBASE_BN_LIB; + if (!SRP_user_pwd_set_sv + (user_pwd, pp[DB_srpsalt], pp[DB_srpverifier])) + goto err; + + if (sk_SRP_user_pwd_insert(vb->users_pwd, user_pwd, 0) == 0) + goto err; + user_pwd = NULL; /* abandon responsibility */ + } + } + } + + if (last_index != NULL) { + /* this means that we want to simulate a default user */ + + if (((gN = SRP_get_gN_by_id(last_index, SRP_gN_tab)) == NULL)) { + error_code = SRP_ERR_VBASE_BN_LIB; + goto err; + } + vb->default_g = gN->g; + vb->default_N = gN->N; + gN = NULL; + } + error_code = SRP_NO_ERROR; + + err: + /* + * there may be still some leaks to fix, if this fails, the application + * terminates most likely + */ + + if (gN != NULL) { + OPENSSL_free(gN->id); + OPENSSL_free(gN); + } + + SRP_user_pwd_free(user_pwd); + + TXT_DB_free(tmpdb); + BIO_free_all(in); + + sk_SRP_gN_free(SRP_gN_tab); + + return error_code; + +} + +static SRP_user_pwd *find_user(SRP_VBASE *vb, char *username) +{ + int i; + SRP_user_pwd *user; + + if (vb == NULL) + return NULL; + + for (i = 0; i < sk_SRP_user_pwd_num(vb->users_pwd); i++) { + user = sk_SRP_user_pwd_value(vb->users_pwd, i); + if (strcmp(user->id, username) == 0) + return user; + } + + return NULL; +} + +# if OPENSSL_API_COMPAT < 0x10100000L +/* + * DEPRECATED: use SRP_VBASE_get1_by_user instead. + * This method ignores the configured seed and fails for an unknown user. + * Ownership of the returned pointer is not released to the caller. + * In other words, caller must not free the result. + */ +SRP_user_pwd *SRP_VBASE_get_by_user(SRP_VBASE *vb, char *username) +{ + return find_user(vb, username); +} +# endif + +/* + * Ownership of the returned pointer is released to the caller. + * In other words, caller must free the result once done. + */ +SRP_user_pwd *SRP_VBASE_get1_by_user(SRP_VBASE *vb, char *username) +{ + SRP_user_pwd *user; + unsigned char digv[SHA_DIGEST_LENGTH]; + unsigned char digs[SHA_DIGEST_LENGTH]; + EVP_MD_CTX *ctxt = NULL; + + if (vb == NULL) + return NULL; + + if ((user = find_user(vb, username)) != NULL) + return srp_user_pwd_dup(user); + + if ((vb->seed_key == NULL) || + (vb->default_g == NULL) || (vb->default_N == NULL)) + return NULL; + +/* if the user is unknown we set parameters as well if we have a seed_key */ + + if ((user = SRP_user_pwd_new()) == NULL) + return NULL; + + SRP_user_pwd_set_gN(user, vb->default_g, vb->default_N); + + if (!SRP_user_pwd_set_ids(user, username, NULL)) + goto err; + + if (RAND_priv_bytes(digv, SHA_DIGEST_LENGTH) <= 0) + goto err; + ctxt = EVP_MD_CTX_new(); + if (ctxt == NULL + || !EVP_DigestInit_ex(ctxt, EVP_sha1(), NULL) + || !EVP_DigestUpdate(ctxt, vb->seed_key, strlen(vb->seed_key)) + || !EVP_DigestUpdate(ctxt, username, strlen(username)) + || !EVP_DigestFinal_ex(ctxt, digs, NULL)) + goto err; + EVP_MD_CTX_free(ctxt); + ctxt = NULL; + if (SRP_user_pwd_set_sv_BN(user, + BN_bin2bn(digs, SHA_DIGEST_LENGTH, NULL), + BN_bin2bn(digv, SHA_DIGEST_LENGTH, NULL))) + return user; + + err: + EVP_MD_CTX_free(ctxt); + SRP_user_pwd_free(user); + return NULL; +} + +/* + * create a verifier (*salt,*verifier,g and N are in base64) + */ +char *SRP_create_verifier(const char *user, const char *pass, char **salt, + char **verifier, const char *N, const char *g) +{ + int len; + char *result = NULL, *vf = NULL; + const BIGNUM *N_bn = NULL, *g_bn = NULL; + BIGNUM *N_bn_alloc = NULL, *g_bn_alloc = NULL, *s = NULL, *v = NULL; + unsigned char tmp[MAX_LEN]; + unsigned char tmp2[MAX_LEN]; + char *defgNid = NULL; + int vfsize = 0; + + if ((user == NULL) || + (pass == NULL) || (salt == NULL) || (verifier == NULL)) + goto err; + + if (N) { + if ((len = t_fromb64(tmp, sizeof(tmp), N)) <= 0) + goto err; + N_bn_alloc = BN_bin2bn(tmp, len, NULL); + if (N_bn_alloc == NULL) + goto err; + N_bn = N_bn_alloc; + if ((len = t_fromb64(tmp, sizeof(tmp) ,g)) <= 0) + goto err; + g_bn_alloc = BN_bin2bn(tmp, len, NULL); + if (g_bn_alloc == NULL) + goto err; + g_bn = g_bn_alloc; + defgNid = "*"; + } else { + SRP_gN *gN = SRP_get_gN_by_id(g, NULL); + if (gN == NULL) + goto err; + N_bn = gN->N; + g_bn = gN->g; + defgNid = gN->id; + } + + if (*salt == NULL) { + if (RAND_bytes(tmp2, SRP_RANDOM_SALT_LEN) <= 0) + goto err; + + s = BN_bin2bn(tmp2, SRP_RANDOM_SALT_LEN, NULL); + } else { + if ((len = t_fromb64(tmp2, sizeof(tmp2), *salt)) <= 0) + goto err; + s = BN_bin2bn(tmp2, len, NULL); + } + if (s == NULL) + goto err; + + if (!SRP_create_verifier_BN(user, pass, &s, &v, N_bn, g_bn)) + goto err; + + if (BN_bn2bin(v, tmp) < 0) + goto err; + vfsize = BN_num_bytes(v) * 2; + if (((vf = OPENSSL_malloc(vfsize)) == NULL)) + goto err; + if (!t_tob64(vf, tmp, BN_num_bytes(v))) + goto err; + + if (*salt == NULL) { + char *tmp_salt; + + if ((tmp_salt = OPENSSL_malloc(SRP_RANDOM_SALT_LEN * 2)) == NULL) { + goto err; + } + if (!t_tob64(tmp_salt, tmp2, SRP_RANDOM_SALT_LEN)) { + OPENSSL_free(tmp_salt); + goto err; + } + *salt = tmp_salt; + } + + *verifier = vf; + vf = NULL; + result = defgNid; + + err: + BN_free(N_bn_alloc); + BN_free(g_bn_alloc); + OPENSSL_clear_free(vf, vfsize); + BN_clear_free(s); + BN_clear_free(v); + return result; +} + +/* + * create a verifier (*salt,*verifier,g and N are BIGNUMs). If *salt != NULL + * then the provided salt will be used. On successful exit *verifier will point + * to a newly allocated BIGNUM containing the verifier and (if a salt was not + * provided) *salt will be populated with a newly allocated BIGNUM containing a + * random salt. + * The caller is responsible for freeing the allocated *salt and *verifier + * BIGNUMS. + */ +int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt, + BIGNUM **verifier, const BIGNUM *N, + const BIGNUM *g) +{ + int result = 0; + BIGNUM *x = NULL; + BN_CTX *bn_ctx = BN_CTX_new(); + unsigned char tmp2[MAX_LEN]; + BIGNUM *salttmp = NULL; + + if ((user == NULL) || + (pass == NULL) || + (salt == NULL) || + (verifier == NULL) || (N == NULL) || (g == NULL) || (bn_ctx == NULL)) + goto err; + + if (*salt == NULL) { + if (RAND_bytes(tmp2, SRP_RANDOM_SALT_LEN) <= 0) + goto err; + + salttmp = BN_bin2bn(tmp2, SRP_RANDOM_SALT_LEN, NULL); + if (salttmp == NULL) + goto err; + } else { + salttmp = *salt; + } + + x = SRP_Calc_x(salttmp, user, pass); + if (x == NULL) + goto err; + + *verifier = BN_new(); + if (*verifier == NULL) + goto err; + + if (!BN_mod_exp(*verifier, g, x, N, bn_ctx)) { + BN_clear_free(*verifier); + goto err; + } + + result = 1; + *salt = salttmp; + + err: + if (salt != NULL && *salt != salttmp) + BN_clear_free(salttmp); + BN_clear_free(x); + BN_CTX_free(bn_ctx); + return result; +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/stack/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/stack/build.info new file mode 100644 index 000000000..e5870210a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/stack/build.info @@ -0,0 +1,2 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=stack.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/stack/stack.c b/trunk/3rdparty/openssl-1.1-fit/crypto/stack/stack.c new file mode 100644 index 000000000..975515db5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/stack/stack.c @@ -0,0 +1,413 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include "internal/numbers.h" +#include +#include +#include +#include /* For ossl_inline */ + +/* + * The initial number of nodes in the array. + */ +static const int min_nodes = 4; +static const int max_nodes = SIZE_MAX / sizeof(void *) < INT_MAX + ? (int)(SIZE_MAX / sizeof(void *)) + : INT_MAX; + +struct stack_st { + int num; + const void **data; + int sorted; + int num_alloc; + OPENSSL_sk_compfunc comp; +}; + +OPENSSL_sk_compfunc OPENSSL_sk_set_cmp_func(OPENSSL_STACK *sk, OPENSSL_sk_compfunc c) +{ + OPENSSL_sk_compfunc old = sk->comp; + + if (sk->comp != c) + sk->sorted = 0; + sk->comp = c; + + return old; +} + +OPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *sk) +{ + OPENSSL_STACK *ret; + + if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) { + CRYPTOerr(CRYPTO_F_OPENSSL_SK_DUP, ERR_R_MALLOC_FAILURE); + return NULL; + } + + /* direct structure assignment */ + *ret = *sk; + + if (sk->num == 0) { + /* postpone |ret->data| allocation */ + ret->data = NULL; + ret->num_alloc = 0; + return ret; + } + /* duplicate |sk->data| content */ + if ((ret->data = OPENSSL_malloc(sizeof(*ret->data) * sk->num_alloc)) == NULL) + goto err; + memcpy(ret->data, sk->data, sizeof(void *) * sk->num); + return ret; + err: + OPENSSL_sk_free(ret); + return NULL; +} + +OPENSSL_STACK *OPENSSL_sk_deep_copy(const OPENSSL_STACK *sk, + OPENSSL_sk_copyfunc copy_func, + OPENSSL_sk_freefunc free_func) +{ + OPENSSL_STACK *ret; + int i; + + if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) { + CRYPTOerr(CRYPTO_F_OPENSSL_SK_DEEP_COPY, ERR_R_MALLOC_FAILURE); + return NULL; + } + + /* direct structure assignment */ + *ret = *sk; + + if (sk->num == 0) { + /* postpone |ret| data allocation */ + ret->data = NULL; + ret->num_alloc = 0; + return ret; + } + + ret->num_alloc = sk->num > min_nodes ? sk->num : min_nodes; + ret->data = OPENSSL_zalloc(sizeof(*ret->data) * ret->num_alloc); + if (ret->data == NULL) { + OPENSSL_free(ret); + return NULL; + } + + for (i = 0; i < ret->num; ++i) { + if (sk->data[i] == NULL) + continue; + if ((ret->data[i] = copy_func(sk->data[i])) == NULL) { + while (--i >= 0) + if (ret->data[i] != NULL) + free_func((void *)ret->data[i]); + OPENSSL_sk_free(ret); + return NULL; + } + } + return ret; +} + +OPENSSL_STACK *OPENSSL_sk_new_null(void) +{ + return OPENSSL_sk_new_reserve(NULL, 0); +} + +OPENSSL_STACK *OPENSSL_sk_new(OPENSSL_sk_compfunc c) +{ + return OPENSSL_sk_new_reserve(c, 0); +} + +/* + * Calculate the array growth based on the target size. + * + * The growth fraction is a rational number and is defined by a numerator + * and a denominator. According to Andrew Koenig in his paper "Why Are + * Vectors Efficient?" from JOOP 11(5) 1998, this factor should be less + * than the golden ratio (1.618...). + * + * We use 3/2 = 1.5 for simplicity of calculation and overflow checking. + * Another option 8/5 = 1.6 allows for slightly faster growth, although safe + * computation is more difficult. + * + * The limit to avoid overflow is spot on. The modulo three correction term + * ensures that the limit is the largest number than can be expanded by the + * growth factor without exceeding the hard limit. + * + * Do not call it with |current| lower than 2, or it will infinitely loop. + */ +static ossl_inline int compute_growth(int target, int current) +{ + const int limit = (max_nodes / 3) * 2 + (max_nodes % 3 ? 1 : 0); + + while (current < target) { + /* Check to see if we're at the hard limit */ + if (current >= max_nodes) + return 0; + + /* Expand the size by a factor of 3/2 if it is within range */ + current = current < limit ? current + current / 2 : max_nodes; + } + return current; +} + +/* internal STACK storage allocation */ +static int sk_reserve(OPENSSL_STACK *st, int n, int exact) +{ + const void **tmpdata; + int num_alloc; + + /* Check to see the reservation isn't exceeding the hard limit */ + if (n > max_nodes - st->num) + return 0; + + /* Figure out the new size */ + num_alloc = st->num + n; + if (num_alloc < min_nodes) + num_alloc = min_nodes; + + /* If |st->data| allocation was postponed */ + if (st->data == NULL) { + /* + * At this point, |st->num_alloc| and |st->num| are 0; + * so |num_alloc| value is |n| or |min_nodes| if greater than |n|. + */ + if ((st->data = OPENSSL_zalloc(sizeof(void *) * num_alloc)) == NULL) { + CRYPTOerr(CRYPTO_F_SK_RESERVE, ERR_R_MALLOC_FAILURE); + return 0; + } + st->num_alloc = num_alloc; + return 1; + } + + if (!exact) { + if (num_alloc <= st->num_alloc) + return 1; + num_alloc = compute_growth(num_alloc, st->num_alloc); + if (num_alloc == 0) + return 0; + } else if (num_alloc == st->num_alloc) { + return 1; + } + + tmpdata = OPENSSL_realloc((void *)st->data, sizeof(void *) * num_alloc); + if (tmpdata == NULL) + return 0; + + st->data = tmpdata; + st->num_alloc = num_alloc; + return 1; +} + +OPENSSL_STACK *OPENSSL_sk_new_reserve(OPENSSL_sk_compfunc c, int n) +{ + OPENSSL_STACK *st = OPENSSL_zalloc(sizeof(OPENSSL_STACK)); + + if (st == NULL) + return NULL; + + st->comp = c; + + if (n <= 0) + return st; + + if (!sk_reserve(st, n, 1)) { + OPENSSL_sk_free(st); + return NULL; + } + + return st; +} + +int OPENSSL_sk_reserve(OPENSSL_STACK *st, int n) +{ + if (st == NULL) + return 0; + + if (n < 0) + return 1; + return sk_reserve(st, n, 1); +} + +int OPENSSL_sk_insert(OPENSSL_STACK *st, const void *data, int loc) +{ + if (st == NULL || st->num == max_nodes) + return 0; + + if (!sk_reserve(st, 1, 0)) + return 0; + + if ((loc >= st->num) || (loc < 0)) { + st->data[st->num] = data; + } else { + memmove(&st->data[loc + 1], &st->data[loc], + sizeof(st->data[0]) * (st->num - loc)); + st->data[loc] = data; + } + st->num++; + st->sorted = 0; + return st->num; +} + +static ossl_inline void *internal_delete(OPENSSL_STACK *st, int loc) +{ + const void *ret = st->data[loc]; + + if (loc != st->num - 1) + memmove(&st->data[loc], &st->data[loc + 1], + sizeof(st->data[0]) * (st->num - loc - 1)); + st->num--; + + return (void *)ret; +} + +void *OPENSSL_sk_delete_ptr(OPENSSL_STACK *st, const void *p) +{ + int i; + + for (i = 0; i < st->num; i++) + if (st->data[i] == p) + return internal_delete(st, i); + return NULL; +} + +void *OPENSSL_sk_delete(OPENSSL_STACK *st, int loc) +{ + if (st == NULL || loc < 0 || loc >= st->num) + return NULL; + + return internal_delete(st, loc); +} + +static int internal_find(OPENSSL_STACK *st, const void *data, + int ret_val_options) +{ + const void *r; + int i; + + if (st == NULL || st->num == 0) + return -1; + + if (st->comp == NULL) { + for (i = 0; i < st->num; i++) + if (st->data[i] == data) + return i; + return -1; + } + + if (!st->sorted) { + if (st->num > 1) + qsort(st->data, st->num, sizeof(void *), st->comp); + st->sorted = 1; /* empty or single-element stack is considered sorted */ + } + if (data == NULL) + return -1; + r = OBJ_bsearch_ex_(&data, st->data, st->num, sizeof(void *), st->comp, + ret_val_options); + + return r == NULL ? -1 : (int)((const void **)r - st->data); +} + +int OPENSSL_sk_find(OPENSSL_STACK *st, const void *data) +{ + return internal_find(st, data, OBJ_BSEARCH_FIRST_VALUE_ON_MATCH); +} + +int OPENSSL_sk_find_ex(OPENSSL_STACK *st, const void *data) +{ + return internal_find(st, data, OBJ_BSEARCH_VALUE_ON_NOMATCH); +} + +int OPENSSL_sk_push(OPENSSL_STACK *st, const void *data) +{ + if (st == NULL) + return -1; + return OPENSSL_sk_insert(st, data, st->num); +} + +int OPENSSL_sk_unshift(OPENSSL_STACK *st, const void *data) +{ + return OPENSSL_sk_insert(st, data, 0); +} + +void *OPENSSL_sk_shift(OPENSSL_STACK *st) +{ + if (st == NULL || st->num == 0) + return NULL; + return internal_delete(st, 0); +} + +void *OPENSSL_sk_pop(OPENSSL_STACK *st) +{ + if (st == NULL || st->num == 0) + return NULL; + return internal_delete(st, st->num - 1); +} + +void OPENSSL_sk_zero(OPENSSL_STACK *st) +{ + if (st == NULL || st->num == 0) + return; + memset(st->data, 0, sizeof(*st->data) * st->num); + st->num = 0; +} + +void OPENSSL_sk_pop_free(OPENSSL_STACK *st, OPENSSL_sk_freefunc func) +{ + int i; + + if (st == NULL) + return; + for (i = 0; i < st->num; i++) + if (st->data[i] != NULL) + func((char *)st->data[i]); + OPENSSL_sk_free(st); +} + +void OPENSSL_sk_free(OPENSSL_STACK *st) +{ + if (st == NULL) + return; + OPENSSL_free(st->data); + OPENSSL_free(st); +} + +int OPENSSL_sk_num(const OPENSSL_STACK *st) +{ + return st == NULL ? -1 : st->num; +} + +void *OPENSSL_sk_value(const OPENSSL_STACK *st, int i) +{ + if (st == NULL || i < 0 || i >= st->num) + return NULL; + return (void *)st->data[i]; +} + +void *OPENSSL_sk_set(OPENSSL_STACK *st, int i, const void *data) +{ + if (st == NULL || i < 0 || i >= st->num) + return NULL; + st->data[i] = data; + st->sorted = 0; + return (void *)st->data[i]; +} + +void OPENSSL_sk_sort(OPENSSL_STACK *st) +{ + if (st != NULL && !st->sorted && st->comp != NULL) { + if (st->num > 1) + qsort(st->data, st->num, sizeof(void *), st->comp); + st->sorted = 1; /* empty or single-element stack is considered sorted */ + } +} + +int OPENSSL_sk_is_sorted(const OPENSSL_STACK *st) +{ + return st == NULL ? 1 : st->sorted; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/store/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/store/build.info new file mode 100644 index 000000000..7d882f313 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/store/build.info @@ -0,0 +1,4 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + store_err.c store_init.c store_lib.c store_register.c store_strings.c \ + loader_file.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/store/loader_file.c b/trunk/3rdparty/openssl-1.1-fit/crypto/store/loader_file.c new file mode 100644 index 000000000..632e4511f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/store/loader_file.c @@ -0,0 +1,1440 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "e_os.h" +#include +#include +#include +#include + +#include +#include /* For d2i_DSAPrivateKey */ +#include +#include +#include +#include /* For the PKCS8 stuff o.O */ +#include /* For d2i_RSAPrivateKey */ +#include +#include +#include +#include /* For the PKCS8 stuff o.O */ +#include "internal/asn1_int.h" +#include "internal/ctype.h" +#include "internal/o_dir.h" +#include "internal/cryptlib.h" +#include "internal/store_int.h" +#include "store_locl.h" + +#ifdef _WIN32 +# define stat _stat +#endif + +#ifndef S_ISDIR +# define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR) +#endif + +/*- + * Password prompting + * ------------------ + */ + +static char *file_get_pass(const UI_METHOD *ui_method, char *pass, + size_t maxsize, const char *prompt_info, void *data) +{ + UI *ui = UI_new(); + char *prompt = NULL; + + if (ui == NULL) { + OSSL_STOREerr(OSSL_STORE_F_FILE_GET_PASS, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (ui_method != NULL) + UI_set_method(ui, ui_method); + UI_add_user_data(ui, data); + + if ((prompt = UI_construct_prompt(ui, "pass phrase", + prompt_info)) == NULL) { + OSSL_STOREerr(OSSL_STORE_F_FILE_GET_PASS, ERR_R_MALLOC_FAILURE); + pass = NULL; + } else if (!UI_add_input_string(ui, prompt, UI_INPUT_FLAG_DEFAULT_PWD, + pass, 0, maxsize - 1)) { + OSSL_STOREerr(OSSL_STORE_F_FILE_GET_PASS, ERR_R_UI_LIB); + pass = NULL; + } else { + switch (UI_process(ui)) { + case -2: + OSSL_STOREerr(OSSL_STORE_F_FILE_GET_PASS, + OSSL_STORE_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED); + pass = NULL; + break; + case -1: + OSSL_STOREerr(OSSL_STORE_F_FILE_GET_PASS, ERR_R_UI_LIB); + pass = NULL; + break; + default: + break; + } + } + + OPENSSL_free(prompt); + UI_free(ui); + return pass; +} + +struct pem_pass_data { + const UI_METHOD *ui_method; + void *data; + const char *prompt_info; +}; + +static int file_fill_pem_pass_data(struct pem_pass_data *pass_data, + const char *prompt_info, + const UI_METHOD *ui_method, void *ui_data) +{ + if (pass_data == NULL) + return 0; + pass_data->ui_method = ui_method; + pass_data->data = ui_data; + pass_data->prompt_info = prompt_info; + return 1; +} + +/* This is used anywhere a pem_password_cb is needed */ +static int file_get_pem_pass(char *buf, int num, int w, void *data) +{ + struct pem_pass_data *pass_data = data; + char *pass = file_get_pass(pass_data->ui_method, buf, num, + pass_data->prompt_info, pass_data->data); + + return pass == NULL ? 0 : strlen(pass); +} + +/*- + * The file scheme decoders + * ------------------------ + * + * Each possible data type has its own decoder, which either operates + * through a given PEM name, or attempts to decode to see if the blob + * it's given is decodable for its data type. The assumption is that + * only the correct data type will match the content. + */ + +/*- + * The try_decode function is called to check if the blob of data can + * be used by this handler, and if it can, decodes it into a supported + * OpenSSL type and returns a OSSL_STORE_INFO with the decoded data. + * Input: + * pem_name: If this blob comes from a PEM file, this holds + * the PEM name. If it comes from another type of + * file, this is NULL. + * pem_header: If this blob comes from a PEM file, this holds + * the PEM headers. If it comes from another type of + * file, this is NULL. + * blob: The blob of data to match with what this handler + * can use. + * len: The length of the blob. + * handler_ctx: For a handler marked repeatable, this pointer can + * be used to create a context for the handler. IT IS + * THE HANDLER'S RESPONSIBILITY TO CREATE AND DESTROY + * THIS CONTEXT APPROPRIATELY, i.e. create on first call + * and destroy when about to return NULL. + * matchcount: A pointer to an int to count matches for this data. + * Usually becomes 0 (no match) or 1 (match!), but may + * be higher in the (unlikely) event that the data matches + * more than one possibility. The int will always be + * zero when the function is called. + * ui_method: Application UI method for getting a password, pin + * or any other interactive data. + * ui_data: Application data to be passed to ui_method when + * it's called. + * Output: + * a OSSL_STORE_INFO + */ +typedef OSSL_STORE_INFO *(*file_try_decode_fn)(const char *pem_name, + const char *pem_header, + const unsigned char *blob, + size_t len, void **handler_ctx, + int *matchcount, + const UI_METHOD *ui_method, + void *ui_data); +/* + * The eof function should return 1 if there's no more data to be found + * with the handler_ctx, otherwise 0. This is only used when the handler is + * marked repeatable. + */ +typedef int (*file_eof_fn)(void *handler_ctx); +/* + * The destroy_ctx function is used to destroy the handler_ctx that was + * intiated by a repeatable try_decode fuction. This is only used when + * the handler is marked repeatable. + */ +typedef void (*file_destroy_ctx_fn)(void **handler_ctx); + +typedef struct file_handler_st { + const char *name; + file_try_decode_fn try_decode; + file_eof_fn eof; + file_destroy_ctx_fn destroy_ctx; + + /* flags */ + int repeatable; +} FILE_HANDLER; + +/* + * PKCS#12 decoder. It operates by decoding all of the blob content, + * extracting all the interesting data from it and storing them internally, + * then serving them one piece at a time. + */ +static OSSL_STORE_INFO *try_decode_PKCS12(const char *pem_name, + const char *pem_header, + const unsigned char *blob, + size_t len, void **pctx, + int *matchcount, + const UI_METHOD *ui_method, + void *ui_data) +{ + OSSL_STORE_INFO *store_info = NULL; + STACK_OF(OSSL_STORE_INFO) *ctx = *pctx; + + if (ctx == NULL) { + /* Initial parsing */ + PKCS12 *p12; + int ok = 0; + + if (pem_name != NULL) + /* No match, there is no PEM PKCS12 tag */ + return NULL; + + if ((p12 = d2i_PKCS12(NULL, &blob, len)) != NULL) { + char *pass = NULL; + char tpass[PEM_BUFSIZE]; + EVP_PKEY *pkey = NULL; + X509 *cert = NULL; + STACK_OF(X509) *chain = NULL; + + *matchcount = 1; + + if (PKCS12_verify_mac(p12, "", 0) + || PKCS12_verify_mac(p12, NULL, 0)) { + pass = ""; + } else { + if ((pass = file_get_pass(ui_method, tpass, PEM_BUFSIZE, + "PKCS12 import password", + ui_data)) == NULL) { + OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PKCS12, + OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR); + goto p12_end; + } + if (!PKCS12_verify_mac(p12, pass, strlen(pass))) { + OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PKCS12, + OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC); + goto p12_end; + } + } + + if (PKCS12_parse(p12, pass, &pkey, &cert, &chain)) { + OSSL_STORE_INFO *osi_pkey = NULL; + OSSL_STORE_INFO *osi_cert = NULL; + OSSL_STORE_INFO *osi_ca = NULL; + + if ((ctx = sk_OSSL_STORE_INFO_new_null()) != NULL + && (osi_pkey = OSSL_STORE_INFO_new_PKEY(pkey)) != NULL + && sk_OSSL_STORE_INFO_push(ctx, osi_pkey) != 0 + && (osi_cert = OSSL_STORE_INFO_new_CERT(cert)) != NULL + && sk_OSSL_STORE_INFO_push(ctx, osi_cert) != 0) { + ok = 1; + osi_pkey = NULL; + osi_cert = NULL; + + while(sk_X509_num(chain) > 0) { + X509 *ca = sk_X509_value(chain, 0); + + if ((osi_ca = OSSL_STORE_INFO_new_CERT(ca)) == NULL + || sk_OSSL_STORE_INFO_push(ctx, osi_ca) == 0) { + ok = 0; + break; + } + osi_ca = NULL; + (void)sk_X509_shift(chain); + } + } + if (!ok) { + OSSL_STORE_INFO_free(osi_ca); + OSSL_STORE_INFO_free(osi_cert); + OSSL_STORE_INFO_free(osi_pkey); + sk_OSSL_STORE_INFO_pop_free(ctx, OSSL_STORE_INFO_free); + EVP_PKEY_free(pkey); + X509_free(cert); + sk_X509_pop_free(chain, X509_free); + ctx = NULL; + } + *pctx = ctx; + } + } + p12_end: + PKCS12_free(p12); + if (!ok) + return NULL; + } + + if (ctx != NULL) { + *matchcount = 1; + store_info = sk_OSSL_STORE_INFO_shift(ctx); + } + + return store_info; +} + +static int eof_PKCS12(void *ctx_) +{ + STACK_OF(OSSL_STORE_INFO) *ctx = ctx_; + + return ctx == NULL || sk_OSSL_STORE_INFO_num(ctx) == 0; +} + +static void destroy_ctx_PKCS12(void **pctx) +{ + STACK_OF(OSSL_STORE_INFO) *ctx = *pctx; + + sk_OSSL_STORE_INFO_pop_free(ctx, OSSL_STORE_INFO_free); + *pctx = NULL; +} + +static FILE_HANDLER PKCS12_handler = { + "PKCS12", + try_decode_PKCS12, + eof_PKCS12, + destroy_ctx_PKCS12, + 1 /* repeatable */ +}; + +/* + * Encrypted PKCS#8 decoder. It operates by just decrypting the given blob + * into a new blob, which is returned as an EMBEDDED STORE_INFO. The whole + * decoding process will then start over with the new blob. + */ +static OSSL_STORE_INFO *try_decode_PKCS8Encrypted(const char *pem_name, + const char *pem_header, + const unsigned char *blob, + size_t len, void **pctx, + int *matchcount, + const UI_METHOD *ui_method, + void *ui_data) +{ + X509_SIG *p8 = NULL; + char kbuf[PEM_BUFSIZE]; + char *pass = NULL; + const X509_ALGOR *dalg = NULL; + const ASN1_OCTET_STRING *doct = NULL; + OSSL_STORE_INFO *store_info = NULL; + BUF_MEM *mem = NULL; + unsigned char *new_data = NULL; + int new_data_len; + + if (pem_name != NULL) { + if (strcmp(pem_name, PEM_STRING_PKCS8) != 0) + return NULL; + *matchcount = 1; + } + + if ((p8 = d2i_X509_SIG(NULL, &blob, len)) == NULL) + return NULL; + + *matchcount = 1; + + if ((mem = BUF_MEM_new()) == NULL) { + OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED, + ERR_R_MALLOC_FAILURE); + goto nop8; + } + + if ((pass = file_get_pass(ui_method, kbuf, PEM_BUFSIZE, + "PKCS8 decrypt password", ui_data)) == NULL) { + OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED, + OSSL_STORE_R_BAD_PASSWORD_READ); + goto nop8; + } + + X509_SIG_get0(p8, &dalg, &doct); + if (!PKCS12_pbe_crypt(dalg, pass, strlen(pass), doct->data, doct->length, + &new_data, &new_data_len, 0)) + goto nop8; + + mem->data = (char *)new_data; + mem->max = mem->length = (size_t)new_data_len; + X509_SIG_free(p8); + + store_info = ossl_store_info_new_EMBEDDED(PEM_STRING_PKCS8INF, mem); + if (store_info == NULL) { + OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED, + ERR_R_MALLOC_FAILURE); + goto nop8; + } + + return store_info; + nop8: + X509_SIG_free(p8); + BUF_MEM_free(mem); + return NULL; +} + +static FILE_HANDLER PKCS8Encrypted_handler = { + "PKCS8Encrypted", + try_decode_PKCS8Encrypted +}; + +/* + * Private key decoder. Decodes all sorts of private keys, both PKCS#8 + * encoded ones and old style PEM ones (with the key type is encoded into + * the PEM name). + */ +int pem_check_suffix(const char *pem_str, const char *suffix); +static OSSL_STORE_INFO *try_decode_PrivateKey(const char *pem_name, + const char *pem_header, + const unsigned char *blob, + size_t len, void **pctx, + int *matchcount, + const UI_METHOD *ui_method, + void *ui_data) +{ + OSSL_STORE_INFO *store_info = NULL; + EVP_PKEY *pkey = NULL; + const EVP_PKEY_ASN1_METHOD *ameth = NULL; + + if (pem_name != NULL) { + if (strcmp(pem_name, PEM_STRING_PKCS8INF) == 0) { + PKCS8_PRIV_KEY_INFO *p8inf = + d2i_PKCS8_PRIV_KEY_INFO(NULL, &blob, len); + + *matchcount = 1; + if (p8inf != NULL) + pkey = EVP_PKCS82PKEY(p8inf); + PKCS8_PRIV_KEY_INFO_free(p8inf); + } else { + int slen; + + if ((slen = pem_check_suffix(pem_name, "PRIVATE KEY")) > 0 + && (ameth = EVP_PKEY_asn1_find_str(NULL, pem_name, + slen)) != NULL) { + *matchcount = 1; + pkey = d2i_PrivateKey(ameth->pkey_id, NULL, &blob, len); + } + } + } else { + int i; + + for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) { + EVP_PKEY *tmp_pkey = NULL; + const unsigned char *tmp_blob = blob; + + ameth = EVP_PKEY_asn1_get0(i); + if (ameth->pkey_flags & ASN1_PKEY_ALIAS) + continue; + + tmp_pkey = d2i_PrivateKey(ameth->pkey_id, NULL, &tmp_blob, len); + if (tmp_pkey != NULL) { + if (pkey != NULL) + EVP_PKEY_free(tmp_pkey); + else + pkey = tmp_pkey; + (*matchcount)++; + } + } + + if (*matchcount > 1) { + EVP_PKEY_free(pkey); + pkey = NULL; + } + } + if (pkey == NULL) + /* No match */ + return NULL; + + store_info = OSSL_STORE_INFO_new_PKEY(pkey); + if (store_info == NULL) + EVP_PKEY_free(pkey); + + return store_info; +} + +static FILE_HANDLER PrivateKey_handler = { + "PrivateKey", + try_decode_PrivateKey +}; + +/* + * Public key decoder. Only supports SubjectPublicKeyInfo formated keys. + */ +static OSSL_STORE_INFO *try_decode_PUBKEY(const char *pem_name, + const char *pem_header, + const unsigned char *blob, + size_t len, void **pctx, + int *matchcount, + const UI_METHOD *ui_method, + void *ui_data) +{ + OSSL_STORE_INFO *store_info = NULL; + EVP_PKEY *pkey = NULL; + + if (pem_name != NULL) { + if (strcmp(pem_name, PEM_STRING_PUBLIC) != 0) + /* No match */ + return NULL; + *matchcount = 1; + } + + if ((pkey = d2i_PUBKEY(NULL, &blob, len)) != NULL) { + *matchcount = 1; + store_info = OSSL_STORE_INFO_new_PKEY(pkey); + } + + return store_info; +} + +static FILE_HANDLER PUBKEY_handler = { + "PUBKEY", + try_decode_PUBKEY +}; + +/* + * Key parameter decoder. + */ +static OSSL_STORE_INFO *try_decode_params(const char *pem_name, + const char *pem_header, + const unsigned char *blob, + size_t len, void **pctx, + int *matchcount, + const UI_METHOD *ui_method, + void *ui_data) +{ + OSSL_STORE_INFO *store_info = NULL; + int slen = 0; + EVP_PKEY *pkey = NULL; + const EVP_PKEY_ASN1_METHOD *ameth = NULL; + int ok = 0; + + if (pem_name != NULL) { + if ((slen = pem_check_suffix(pem_name, "PARAMETERS")) == 0) + return NULL; + *matchcount = 1; + } + + if (slen > 0) { + if ((pkey = EVP_PKEY_new()) == NULL) { + OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PARAMS, ERR_R_EVP_LIB); + return NULL; + } + + + if (EVP_PKEY_set_type_str(pkey, pem_name, slen) + && (ameth = EVP_PKEY_get0_asn1(pkey)) != NULL + && ameth->param_decode != NULL + && ameth->param_decode(pkey, &blob, len)) + ok = 1; + } else { + int i; + EVP_PKEY *tmp_pkey = NULL; + + for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) { + const unsigned char *tmp_blob = blob; + + if (tmp_pkey == NULL && (tmp_pkey = EVP_PKEY_new()) == NULL) { + OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PARAMS, ERR_R_EVP_LIB); + break; + } + + ameth = EVP_PKEY_asn1_get0(i); + if (ameth->pkey_flags & ASN1_PKEY_ALIAS) + continue; + + if (EVP_PKEY_set_type(tmp_pkey, ameth->pkey_id) + && (ameth = EVP_PKEY_get0_asn1(tmp_pkey)) != NULL + && ameth->param_decode != NULL + && ameth->param_decode(tmp_pkey, &tmp_blob, len)) { + if (pkey != NULL) + EVP_PKEY_free(tmp_pkey); + else + pkey = tmp_pkey; + tmp_pkey = NULL; + (*matchcount)++; + } + } + + EVP_PKEY_free(tmp_pkey); + if (*matchcount == 1) { + ok = 1; + } + } + + if (ok) + store_info = OSSL_STORE_INFO_new_PARAMS(pkey); + if (store_info == NULL) + EVP_PKEY_free(pkey); + + return store_info; +} + +static FILE_HANDLER params_handler = { + "params", + try_decode_params +}; + +/* + * X.509 certificate decoder. + */ +static OSSL_STORE_INFO *try_decode_X509Certificate(const char *pem_name, + const char *pem_header, + const unsigned char *blob, + size_t len, void **pctx, + int *matchcount, + const UI_METHOD *ui_method, + void *ui_data) +{ + OSSL_STORE_INFO *store_info = NULL; + X509 *cert = NULL; + + /* + * In most cases, we can try to interpret the serialized data as a trusted + * cert (X509 + X509_AUX) and fall back to reading it as a normal cert + * (just X509), but if the PEM name specifically declares it as a trusted + * cert, then no fallback should be engaged. |ignore_trusted| tells if + * the fallback can be used (1) or not (0). + */ + int ignore_trusted = 1; + + if (pem_name != NULL) { + if (strcmp(pem_name, PEM_STRING_X509_TRUSTED) == 0) + ignore_trusted = 0; + else if (strcmp(pem_name, PEM_STRING_X509_OLD) != 0 + && strcmp(pem_name, PEM_STRING_X509) != 0) + /* No match */ + return NULL; + *matchcount = 1; + } + + if ((cert = d2i_X509_AUX(NULL, &blob, len)) != NULL + || (ignore_trusted && (cert = d2i_X509(NULL, &blob, len)) != NULL)) { + *matchcount = 1; + store_info = OSSL_STORE_INFO_new_CERT(cert); + } + + if (store_info == NULL) + X509_free(cert); + + return store_info; +} + +static FILE_HANDLER X509Certificate_handler = { + "X509Certificate", + try_decode_X509Certificate +}; + +/* + * X.509 CRL decoder. + */ +static OSSL_STORE_INFO *try_decode_X509CRL(const char *pem_name, + const char *pem_header, + const unsigned char *blob, + size_t len, void **pctx, + int *matchcount, + const UI_METHOD *ui_method, + void *ui_data) +{ + OSSL_STORE_INFO *store_info = NULL; + X509_CRL *crl = NULL; + + if (pem_name != NULL) { + if (strcmp(pem_name, PEM_STRING_X509_CRL) != 0) + /* No match */ + return NULL; + *matchcount = 1; + } + + if ((crl = d2i_X509_CRL(NULL, &blob, len)) != NULL) { + *matchcount = 1; + store_info = OSSL_STORE_INFO_new_CRL(crl); + } + + if (store_info == NULL) + X509_CRL_free(crl); + + return store_info; +} + +static FILE_HANDLER X509CRL_handler = { + "X509CRL", + try_decode_X509CRL +}; + +/* + * To finish it all off, we collect all the handlers. + */ +static const FILE_HANDLER *file_handlers[] = { + &PKCS12_handler, + &PKCS8Encrypted_handler, + &X509Certificate_handler, + &X509CRL_handler, + ¶ms_handler, + &PUBKEY_handler, + &PrivateKey_handler, +}; + + +/*- + * The loader itself + * ----------------- + */ + +struct ossl_store_loader_ctx_st { + enum { + is_raw = 0, + is_pem, + is_dir + } type; + int errcnt; +#define FILE_FLAG_SECMEM (1<<0) + unsigned int flags; + union { + struct { /* Used with is_raw and is_pem */ + BIO *file; + + /* + * The following are used when the handler is marked as + * repeatable + */ + const FILE_HANDLER *last_handler; + void *last_handler_ctx; + } file; + struct { /* Used with is_dir */ + OPENSSL_DIR_CTX *ctx; + int end_reached; + char *uri; + + /* + * When a search expression is given, these are filled in. + * |search_name| contains the file basename to look for. + * The string is exactly 8 characters long. + */ + char search_name[9]; + + /* + * The directory reading utility we have combines opening with + * reading the first name. To make sure we can detect the end + * at the right time, we read early and cache the name. + */ + const char *last_entry; + int last_errno; + } dir; + } _; + + /* Expected object type. May be unspecified */ + int expected_type; +}; + +static void OSSL_STORE_LOADER_CTX_free(OSSL_STORE_LOADER_CTX *ctx) +{ + if (ctx->type == is_dir) { + OPENSSL_free(ctx->_.dir.uri); + } else { + if (ctx->_.file.last_handler != NULL) { + ctx->_.file.last_handler->destroy_ctx(&ctx->_.file.last_handler_ctx); + ctx->_.file.last_handler_ctx = NULL; + ctx->_.file.last_handler = NULL; + } + } + OPENSSL_free(ctx); +} + +static OSSL_STORE_LOADER_CTX *file_open(const OSSL_STORE_LOADER *loader, + const char *uri, + const UI_METHOD *ui_method, + void *ui_data) +{ + OSSL_STORE_LOADER_CTX *ctx = NULL; + struct stat st; + struct { + const char *path; + unsigned int check_absolute:1; + } path_data[2]; + size_t path_data_n = 0, i; + const char *path; + + /* + * First step, just take the URI as is. + */ + path_data[path_data_n].check_absolute = 0; + path_data[path_data_n++].path = uri; + + /* + * Second step, if the URI appears to start with the 'file' scheme, + * extract the path and make that the second path to check. + * There's a special case if the URI also contains an authority, then + * the full URI shouldn't be used as a path anywhere. + */ + if (strncasecmp(uri, "file:", 5) == 0) { + const char *p = &uri[5]; + + if (strncmp(&uri[5], "//", 2) == 0) { + path_data_n--; /* Invalidate using the full URI */ + if (strncasecmp(&uri[7], "localhost/", 10) == 0) { + p = &uri[16]; + } else if (uri[7] == '/') { + p = &uri[7]; + } else { + OSSL_STOREerr(OSSL_STORE_F_FILE_OPEN, + OSSL_STORE_R_URI_AUTHORITY_UNSUPPORTED); + return NULL; + } + } + + path_data[path_data_n].check_absolute = 1; +#ifdef _WIN32 + /* Windows file: URIs with a drive letter start with a / */ + if (p[0] == '/' && p[2] == ':' && p[3] == '/') { + char c = ossl_tolower(p[1]); + + if (c >= 'a' && c <= 'z') { + p++; + /* We know it's absolute, so no need to check */ + path_data[path_data_n].check_absolute = 0; + } + } +#endif + path_data[path_data_n++].path = p; + } + + + for (i = 0, path = NULL; path == NULL && i < path_data_n; i++) { + /* + * If the scheme "file" was an explicit part of the URI, the path must + * be absolute. So says RFC 8089 + */ + if (path_data[i].check_absolute && path_data[i].path[0] != '/') { + OSSL_STOREerr(OSSL_STORE_F_FILE_OPEN, + OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE); + ERR_add_error_data(1, path_data[i].path); + return NULL; + } + + if (stat(path_data[i].path, &st) < 0) { + SYSerr(SYS_F_STAT, errno); + ERR_add_error_data(1, path_data[i].path); + } else { + path = path_data[i].path; + } + } + if (path == NULL) { + return NULL; + } + + /* Successfully found a working path, clear possible collected errors */ + ERR_clear_error(); + + ctx = OPENSSL_zalloc(sizeof(*ctx)); + if (ctx == NULL) { + OSSL_STOREerr(OSSL_STORE_F_FILE_OPEN, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (S_ISDIR(st.st_mode)) { + /* + * Try to copy everything, even if we know that some of them must be + * NULL for the moment. This prevents errors in the future, when more + * components may be used. + */ + ctx->_.dir.uri = OPENSSL_strdup(uri); + ctx->type = is_dir; + + if (ctx->_.dir.uri == NULL) + goto err; + + ctx->_.dir.last_entry = OPENSSL_DIR_read(&ctx->_.dir.ctx, path); + ctx->_.dir.last_errno = errno; + if (ctx->_.dir.last_entry == NULL) { + if (ctx->_.dir.last_errno != 0) { + char errbuf[256]; + errno = ctx->_.dir.last_errno; + openssl_strerror_r(errno, errbuf, sizeof(errbuf)); + OSSL_STOREerr(OSSL_STORE_F_FILE_OPEN, ERR_R_SYS_LIB); + ERR_add_error_data(1, errbuf); + goto err; + } + ctx->_.dir.end_reached = 1; + } + } else { + BIO *buff = NULL; + char peekbuf[4096] = { 0, }; + + if ((buff = BIO_new(BIO_f_buffer())) == NULL + || (ctx->_.file.file = BIO_new_file(path, "rb")) == NULL) { + BIO_free_all(buff); + goto err; + } + + ctx->_.file.file = BIO_push(buff, ctx->_.file.file); + if (BIO_buffer_peek(ctx->_.file.file, peekbuf, sizeof(peekbuf) - 1) > 0) { + peekbuf[sizeof(peekbuf) - 1] = '\0'; + if (strstr(peekbuf, "-----BEGIN ") != NULL) + ctx->type = is_pem; + } + } + + return ctx; + err: + OSSL_STORE_LOADER_CTX_free(ctx); + return NULL; +} + +static int file_ctrl(OSSL_STORE_LOADER_CTX *ctx, int cmd, va_list args) +{ + int ret = 1; + + switch (cmd) { + case OSSL_STORE_C_USE_SECMEM: + { + int on = *(va_arg(args, int *)); + + switch (on) { + case 0: + ctx->flags &= ~FILE_FLAG_SECMEM; + break; + case 1: + ctx->flags |= FILE_FLAG_SECMEM; + break; + default: + OSSL_STOREerr(OSSL_STORE_F_FILE_CTRL, + ERR_R_PASSED_INVALID_ARGUMENT); + ret = 0; + break; + } + } + break; + default: + break; + } + + return ret; +} + +static int file_expect(OSSL_STORE_LOADER_CTX *ctx, int expected) +{ + ctx->expected_type = expected; + return 1; +} + +static int file_find(OSSL_STORE_LOADER_CTX *ctx, OSSL_STORE_SEARCH *search) +{ + /* + * If ctx == NULL, the library is looking to know if this loader supports + * the given search type. + */ + + if (OSSL_STORE_SEARCH_get_type(search) == OSSL_STORE_SEARCH_BY_NAME) { + unsigned long hash = 0; + + if (ctx == NULL) + return 1; + + if (ctx->type != is_dir) { + OSSL_STOREerr(OSSL_STORE_F_FILE_FIND, + OSSL_STORE_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES); + return 0; + } + + hash = X509_NAME_hash(OSSL_STORE_SEARCH_get0_name(search)); + BIO_snprintf(ctx->_.dir.search_name, sizeof(ctx->_.dir.search_name), + "%08lx", hash); + return 1; + } + + if (ctx != NULL) + OSSL_STOREerr(OSSL_STORE_F_FILE_FIND, + OSSL_STORE_R_UNSUPPORTED_SEARCH_TYPE); + return 0; +} + +/* Internal function to decode an already opened PEM file */ +OSSL_STORE_LOADER_CTX *ossl_store_file_attach_pem_bio_int(BIO *bp) +{ + OSSL_STORE_LOADER_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); + + if (ctx == NULL) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_FILE_ATTACH_PEM_BIO_INT, + ERR_R_MALLOC_FAILURE); + return NULL; + } + + ctx->_.file.file = bp; + ctx->type = is_pem; + + return ctx; +} + +static OSSL_STORE_INFO *file_load_try_decode(OSSL_STORE_LOADER_CTX *ctx, + const char *pem_name, + const char *pem_header, + unsigned char *data, size_t len, + const UI_METHOD *ui_method, + void *ui_data, int *matchcount) +{ + OSSL_STORE_INFO *result = NULL; + BUF_MEM *new_mem = NULL; + char *new_pem_name = NULL; + int t = 0; + + again: + { + size_t i = 0; + void *handler_ctx = NULL; + const FILE_HANDLER **matching_handlers = + OPENSSL_zalloc(sizeof(*matching_handlers) + * OSSL_NELEM(file_handlers)); + + if (matching_handlers == NULL) { + OSSL_STOREerr(OSSL_STORE_F_FILE_LOAD_TRY_DECODE, + ERR_R_MALLOC_FAILURE); + goto err; + } + + *matchcount = 0; + for (i = 0; i < OSSL_NELEM(file_handlers); i++) { + const FILE_HANDLER *handler = file_handlers[i]; + int try_matchcount = 0; + void *tmp_handler_ctx = NULL; + OSSL_STORE_INFO *tmp_result = + handler->try_decode(pem_name, pem_header, data, len, + &tmp_handler_ctx, &try_matchcount, + ui_method, ui_data); + + if (try_matchcount > 0) { + + matching_handlers[*matchcount] = handler; + + if (handler_ctx) + handler->destroy_ctx(&handler_ctx); + handler_ctx = tmp_handler_ctx; + + if ((*matchcount += try_matchcount) > 1) { + /* more than one match => ambiguous, kill any result */ + OSSL_STORE_INFO_free(result); + OSSL_STORE_INFO_free(tmp_result); + if (handler->destroy_ctx != NULL) + handler->destroy_ctx(&handler_ctx); + handler_ctx = NULL; + tmp_result = NULL; + result = NULL; + } + if (result == NULL) + result = tmp_result; + } + } + + if (*matchcount == 1 && matching_handlers[0]->repeatable) { + ctx->_.file.last_handler = matching_handlers[0]; + ctx->_.file.last_handler_ctx = handler_ctx; + } + + OPENSSL_free(matching_handlers); + } + + err: + OPENSSL_free(new_pem_name); + BUF_MEM_free(new_mem); + + if (result != NULL + && (t = OSSL_STORE_INFO_get_type(result)) == OSSL_STORE_INFO_EMBEDDED) { + pem_name = new_pem_name = + ossl_store_info_get0_EMBEDDED_pem_name(result); + new_mem = ossl_store_info_get0_EMBEDDED_buffer(result); + data = (unsigned char *)new_mem->data; + len = new_mem->length; + OPENSSL_free(result); + result = NULL; + goto again; + } + + if (result != NULL) + ERR_clear_error(); + + return result; +} + +static OSSL_STORE_INFO *file_load_try_repeat(OSSL_STORE_LOADER_CTX *ctx, + const UI_METHOD *ui_method, + void *ui_data) +{ + OSSL_STORE_INFO *result = NULL; + int try_matchcount = 0; + + if (ctx->_.file.last_handler != NULL) { + result = + ctx->_.file.last_handler->try_decode(NULL, NULL, NULL, 0, + &ctx->_.file.last_handler_ctx, + &try_matchcount, + ui_method, ui_data); + + if (result == NULL) { + ctx->_.file.last_handler->destroy_ctx(&ctx->_.file.last_handler_ctx); + ctx->_.file.last_handler_ctx = NULL; + ctx->_.file.last_handler = NULL; + } + } + return result; +} + +static void pem_free_flag(void *pem_data, int secure, size_t num) +{ + if (secure) + OPENSSL_secure_clear_free(pem_data, num); + else + OPENSSL_free(pem_data); +} +static int file_read_pem(BIO *bp, char **pem_name, char **pem_header, + unsigned char **data, long *len, + const UI_METHOD *ui_method, + void *ui_data, int secure) +{ + int i = secure + ? PEM_read_bio_ex(bp, pem_name, pem_header, data, len, + PEM_FLAG_SECURE | PEM_FLAG_EAY_COMPATIBLE) + : PEM_read_bio(bp, pem_name, pem_header, data, len); + + if (i <= 0) + return 0; + + /* + * 10 is the number of characters in "Proc-Type:", which + * PEM_get_EVP_CIPHER_INFO() requires to be present. + * If the PEM header has less characters than that, it's + * not worth spending cycles on it. + */ + if (strlen(*pem_header) > 10) { + EVP_CIPHER_INFO cipher; + struct pem_pass_data pass_data; + + if (!PEM_get_EVP_CIPHER_INFO(*pem_header, &cipher) + || !file_fill_pem_pass_data(&pass_data, "PEM", ui_method, ui_data) + || !PEM_do_header(&cipher, *data, len, file_get_pem_pass, + &pass_data)) { + return 0; + } + } + return 1; +} + +static int file_read_asn1(BIO *bp, unsigned char **data, long *len) +{ + BUF_MEM *mem = NULL; + + if (asn1_d2i_read_bio(bp, &mem) < 0) + return 0; + + *data = (unsigned char *)mem->data; + *len = (long)mem->length; + OPENSSL_free(mem); + + return 1; +} + +static int ends_with_dirsep(const char *uri) +{ + if (*uri != '\0') + uri += strlen(uri) - 1; +#if defined __VMS + if (*uri == ']' || *uri == '>' || *uri == ':') + return 1; +#elif defined _WIN32 + if (*uri == '\\') + return 1; +#endif + return *uri == '/'; +} + +static int file_name_to_uri(OSSL_STORE_LOADER_CTX *ctx, const char *name, + char **data) +{ + assert(name != NULL); + assert(data != NULL); + { + const char *pathsep = ends_with_dirsep(ctx->_.dir.uri) ? "" : "/"; + long calculated_length = strlen(ctx->_.dir.uri) + strlen(pathsep) + + strlen(name) + 1 /* \0 */; + + *data = OPENSSL_zalloc(calculated_length); + if (*data == NULL) { + OSSL_STOREerr(OSSL_STORE_F_FILE_NAME_TO_URI, ERR_R_MALLOC_FAILURE); + return 0; + } + + OPENSSL_strlcat(*data, ctx->_.dir.uri, calculated_length); + OPENSSL_strlcat(*data, pathsep, calculated_length); + OPENSSL_strlcat(*data, name, calculated_length); + } + return 1; +} + +static int file_name_check(OSSL_STORE_LOADER_CTX *ctx, const char *name) +{ + const char *p = NULL; + + /* If there are no search criteria, all names are accepted */ + if (ctx->_.dir.search_name[0] == '\0') + return 1; + + /* If the expected type isn't supported, no name is accepted */ + if (ctx->expected_type != 0 + && ctx->expected_type != OSSL_STORE_INFO_CERT + && ctx->expected_type != OSSL_STORE_INFO_CRL) + return 0; + + /* + * First, check the basename + */ + if (strncasecmp(name, ctx->_.dir.search_name, + sizeof(ctx->_.dir.search_name) - 1) != 0 + || name[sizeof(ctx->_.dir.search_name) - 1] != '.') + return 0; + p = &name[sizeof(ctx->_.dir.search_name)]; + + /* + * Then, if the expected type is a CRL, check that the extension starts + * with 'r' + */ + if (*p == 'r') { + p++; + if (ctx->expected_type != 0 + && ctx->expected_type != OSSL_STORE_INFO_CRL) + return 0; + } else if (ctx->expected_type == OSSL_STORE_INFO_CRL) { + return 0; + } + + /* + * Last, check that the rest of the extension is a decimal number, at + * least one digit long. + */ + if (!ossl_isdigit(*p)) + return 0; + while (ossl_isdigit(*p)) + p++; + +# ifdef __VMS + /* + * One extra step here, check for a possible generation number. + */ + if (*p == ';') + for (p++; *p != '\0'; p++) + if (!ossl_isdigit(*p)) + break; +# endif + + /* + * If we've reached the end of the string at this point, we've successfully + * found a fitting file name. + */ + return *p == '\0'; +} + +static int file_eof(OSSL_STORE_LOADER_CTX *ctx); +static int file_error(OSSL_STORE_LOADER_CTX *ctx); +static OSSL_STORE_INFO *file_load(OSSL_STORE_LOADER_CTX *ctx, + const UI_METHOD *ui_method, void *ui_data) +{ + OSSL_STORE_INFO *result = NULL; + + ctx->errcnt = 0; + ERR_clear_error(); + + if (ctx->type == is_dir) { + do { + char *newname = NULL; + + if (ctx->_.dir.last_entry == NULL) { + if (!ctx->_.dir.end_reached) { + char errbuf[256]; + assert(ctx->_.dir.last_errno != 0); + errno = ctx->_.dir.last_errno; + ctx->errcnt++; + openssl_strerror_r(errno, errbuf, sizeof(errbuf)); + OSSL_STOREerr(OSSL_STORE_F_FILE_LOAD, ERR_R_SYS_LIB); + ERR_add_error_data(1, errbuf); + } + return NULL; + } + + if (ctx->_.dir.last_entry[0] != '.' + && file_name_check(ctx, ctx->_.dir.last_entry) + && !file_name_to_uri(ctx, ctx->_.dir.last_entry, &newname)) + return NULL; + + /* + * On the first call (with a NULL context), OPENSSL_DIR_read() + * cares about the second argument. On the following calls, it + * only cares that it isn't NULL. Therefore, we can safely give + * it our URI here. + */ + ctx->_.dir.last_entry = OPENSSL_DIR_read(&ctx->_.dir.ctx, + ctx->_.dir.uri); + ctx->_.dir.last_errno = errno; + if (ctx->_.dir.last_entry == NULL && ctx->_.dir.last_errno == 0) + ctx->_.dir.end_reached = 1; + + if (newname != NULL + && (result = OSSL_STORE_INFO_new_NAME(newname)) == NULL) { + OPENSSL_free(newname); + OSSL_STOREerr(OSSL_STORE_F_FILE_LOAD, ERR_R_OSSL_STORE_LIB); + return NULL; + } + } while (result == NULL && !file_eof(ctx)); + } else { + int matchcount = -1; + + again: + result = file_load_try_repeat(ctx, ui_method, ui_data); + if (result != NULL) + return result; + + if (file_eof(ctx)) + return NULL; + + do { + char *pem_name = NULL; /* PEM record name */ + char *pem_header = NULL; /* PEM record header */ + unsigned char *data = NULL; /* DER encoded data */ + long len = 0; /* DER encoded data length */ + + matchcount = -1; + if (ctx->type == is_pem) { + if (!file_read_pem(ctx->_.file.file, &pem_name, &pem_header, + &data, &len, ui_method, ui_data, + (ctx->flags & FILE_FLAG_SECMEM) != 0)) { + ctx->errcnt++; + goto endloop; + } + } else { + if (!file_read_asn1(ctx->_.file.file, &data, &len)) { + ctx->errcnt++; + goto endloop; + } + } + + result = file_load_try_decode(ctx, pem_name, pem_header, data, len, + ui_method, ui_data, &matchcount); + + if (result != NULL) + goto endloop; + + /* + * If a PEM name matches more than one handler, the handlers are + * badly coded. + */ + if (!ossl_assert(pem_name == NULL || matchcount <= 1)) { + ctx->errcnt++; + goto endloop; + } + + if (matchcount > 1) { + OSSL_STOREerr(OSSL_STORE_F_FILE_LOAD, + OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE); + } else if (matchcount == 1) { + /* + * If there are other errors on the stack, they already show + * what the problem is. + */ + if (ERR_peek_error() == 0) { + OSSL_STOREerr(OSSL_STORE_F_FILE_LOAD, + OSSL_STORE_R_UNSUPPORTED_CONTENT_TYPE); + if (pem_name != NULL) + ERR_add_error_data(3, "PEM type is '", pem_name, "'"); + } + } + if (matchcount > 0) + ctx->errcnt++; + + endloop: + pem_free_flag(pem_name, (ctx->flags & FILE_FLAG_SECMEM) != 0, 0); + pem_free_flag(pem_header, (ctx->flags & FILE_FLAG_SECMEM) != 0, 0); + pem_free_flag(data, (ctx->flags & FILE_FLAG_SECMEM) != 0, len); + } while (matchcount == 0 && !file_eof(ctx) && !file_error(ctx)); + + /* We bail out on ambiguity */ + if (matchcount > 1) + return NULL; + + if (result != NULL + && ctx->expected_type != 0 + && ctx->expected_type != OSSL_STORE_INFO_get_type(result)) { + OSSL_STORE_INFO_free(result); + goto again; + } + } + + return result; +} + +static int file_error(OSSL_STORE_LOADER_CTX *ctx) +{ + return ctx->errcnt > 0; +} + +static int file_eof(OSSL_STORE_LOADER_CTX *ctx) +{ + if (ctx->type == is_dir) + return ctx->_.dir.end_reached; + + if (ctx->_.file.last_handler != NULL + && !ctx->_.file.last_handler->eof(ctx->_.file.last_handler_ctx)) + return 0; + return BIO_eof(ctx->_.file.file); +} + +static int file_close(OSSL_STORE_LOADER_CTX *ctx) +{ + if (ctx->type == is_dir) { + OPENSSL_DIR_end(&ctx->_.dir.ctx); + } else { + BIO_free_all(ctx->_.file.file); + } + OSSL_STORE_LOADER_CTX_free(ctx); + return 1; +} + +int ossl_store_file_detach_pem_bio_int(OSSL_STORE_LOADER_CTX *ctx) +{ + OSSL_STORE_LOADER_CTX_free(ctx); + return 1; +} + +static OSSL_STORE_LOADER file_loader = + { + "file", + NULL, + file_open, + file_ctrl, + file_expect, + file_find, + file_load, + file_eof, + file_error, + file_close + }; + +static void store_file_loader_deinit(void) +{ + ossl_store_unregister_loader_int(file_loader.scheme); +} + +int ossl_store_file_loader_init(void) +{ + int ret = ossl_store_register_loader_int(&file_loader); + + OPENSSL_atexit(store_file_loader_deinit); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/store/store_err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/store/store_err.c new file mode 100644 index 000000000..5a8a8404d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/store/store_err.c @@ -0,0 +1,146 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA OSSL_STORE_str_functs[] = { + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_FILE_CTRL, 0), "file_ctrl"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_FILE_FIND, 0), "file_find"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_FILE_GET_PASS, 0), + "file_get_pass"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_FILE_LOAD, 0), "file_load"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_FILE_LOAD_TRY_DECODE, 0), + "file_load_try_decode"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_FILE_NAME_TO_URI, 0), + "file_name_to_uri"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_FILE_OPEN, 0), "file_open"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_ATTACH_PEM_BIO, 0), + "ossl_store_attach_pem_bio"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_EXPECT, 0), + "OSSL_STORE_expect"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_FILE_ATTACH_PEM_BIO_INT, 0), + "ossl_store_file_attach_pem_bio_int"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_FIND, 0), + "OSSL_STORE_find"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_GET0_LOADER_INT, 0), + "ossl_store_get0_loader_int"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_GET1_CERT, 0), + "OSSL_STORE_INFO_get1_CERT"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_GET1_CRL, 0), + "OSSL_STORE_INFO_get1_CRL"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME, 0), + "OSSL_STORE_INFO_get1_NAME"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME_DESCRIPTION, 0), + "OSSL_STORE_INFO_get1_NAME_description"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_GET1_PARAMS, 0), + "OSSL_STORE_INFO_get1_PARAMS"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_GET1_PKEY, 0), + "OSSL_STORE_INFO_get1_PKEY"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_NEW_CERT, 0), + "OSSL_STORE_INFO_new_CERT"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_NEW_CRL, 0), + "OSSL_STORE_INFO_new_CRL"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_NEW_EMBEDDED, 0), + "ossl_store_info_new_EMBEDDED"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_NEW_NAME, 0), + "OSSL_STORE_INFO_new_NAME"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_NEW_PARAMS, 0), + "OSSL_STORE_INFO_new_PARAMS"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_NEW_PKEY, 0), + "OSSL_STORE_INFO_new_PKEY"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INFO_SET0_NAME_DESCRIPTION, 0), + "OSSL_STORE_INFO_set0_NAME_description"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_INIT_ONCE, 0), + "ossl_store_init_once"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_LOADER_NEW, 0), + "OSSL_STORE_LOADER_new"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_OPEN, 0), + "OSSL_STORE_open"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_OPEN_INT, 0), ""}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_REGISTER_LOADER_INT, 0), + "ossl_store_register_loader_int"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ALIAS, 0), + "OSSL_STORE_SEARCH_by_alias"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ISSUER_SERIAL, 0), + "OSSL_STORE_SEARCH_by_issuer_serial"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT, 0), + "OSSL_STORE_SEARCH_by_key_fingerprint"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_SEARCH_BY_NAME, 0), + "OSSL_STORE_SEARCH_by_name"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_OSSL_STORE_UNREGISTER_LOADER_INT, 0), + "ossl_store_unregister_loader_int"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_TRY_DECODE_PARAMS, 0), + "try_decode_params"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_TRY_DECODE_PKCS12, 0), + "try_decode_PKCS12"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED, 0), + "try_decode_PKCS8Encrypted"}, + {0, NULL} +}; + +static const ERR_STRING_DATA OSSL_STORE_str_reasons[] = { + {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE), + "ambiguous content type"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_BAD_PASSWORD_READ), + "bad password read"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC), + "error verifying pkcs12 mac"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_FINGERPRINT_SIZE_DOES_NOT_MATCH_DIGEST), + "fingerprint size does not match digest"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_INVALID_SCHEME), + "invalid scheme"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_IS_NOT_A), "is not a"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_LOADER_INCOMPLETE), + "loader incomplete"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_LOADING_STARTED), + "loading started"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_A_CERTIFICATE), + "not a certificate"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_A_CRL), "not a crl"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_A_KEY), "not a key"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_A_NAME), "not a name"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_PARAMETERS), + "not parameters"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR), + "passphrase callback error"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE), + "path must be absolute"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES), + "search only supported for directories"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED), + "ui process interrupted or cancelled"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_UNREGISTERED_SCHEME), + "unregistered scheme"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_UNSUPPORTED_CONTENT_TYPE), + "unsupported content type"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_UNSUPPORTED_OPERATION), + "unsupported operation"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_UNSUPPORTED_SEARCH_TYPE), + "unsupported search type"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_URI_AUTHORITY_UNSUPPORTED), + "uri authority unsupported"}, + {0, NULL} +}; + +#endif + +int ERR_load_OSSL_STORE_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(OSSL_STORE_str_functs[0].error) == NULL) { + ERR_load_strings_const(OSSL_STORE_str_functs); + ERR_load_strings_const(OSSL_STORE_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/store/store_init.c b/trunk/3rdparty/openssl-1.1-fit/crypto/store/store_init.c new file mode 100644 index 000000000..b398bf598 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/store/store_init.c @@ -0,0 +1,33 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/store.h" +#include "store_locl.h" + +static CRYPTO_ONCE store_init = CRYPTO_ONCE_STATIC_INIT; +DEFINE_RUN_ONCE_STATIC(do_store_init) +{ + return OPENSSL_init_crypto(0, NULL) + && ossl_store_file_loader_init(); +} + +int ossl_store_init_once(void) +{ + if (!RUN_ONCE(&store_init, do_store_init)) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INIT_ONCE, ERR_R_MALLOC_FAILURE); + return 0; + } + return 1; +} + +void ossl_store_cleanup_int(void) +{ + ossl_store_destroy_loaders_int(); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/store/store_lib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/store/store_lib.c new file mode 100644 index 000000000..1c4354766 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/store/store_lib.c @@ -0,0 +1,681 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "e_os.h" +#include +#include +#include + +#include "e_os.h" + +#include +#include +#include +#include "internal/thread_once.h" +#include "internal/store_int.h" +#include "store_locl.h" + +struct ossl_store_ctx_st { + const OSSL_STORE_LOADER *loader; + OSSL_STORE_LOADER_CTX *loader_ctx; + const UI_METHOD *ui_method; + void *ui_data; + OSSL_STORE_post_process_info_fn post_process; + void *post_process_data; + int expected_type; + + /* 0 before the first STORE_load(), 1 otherwise */ + int loading; +}; + +OSSL_STORE_CTX *OSSL_STORE_open(const char *uri, const UI_METHOD *ui_method, + void *ui_data, + OSSL_STORE_post_process_info_fn post_process, + void *post_process_data) +{ + const OSSL_STORE_LOADER *loader = NULL; + OSSL_STORE_LOADER_CTX *loader_ctx = NULL; + OSSL_STORE_CTX *ctx = NULL; + char scheme_copy[256], *p, *schemes[2]; + size_t schemes_n = 0; + size_t i; + + /* + * Put the file scheme first. If the uri does represent an existing file, + * possible device name and all, then it should be loaded. Only a failed + * attempt at loading a local file should have us try something else. + */ + schemes[schemes_n++] = "file"; + + /* + * Now, check if we have something that looks like a scheme, and add it + * as a second scheme. However, also check if there's an authority start + * (://), because that will invalidate the previous file scheme. Also, + * check that this isn't actually the file scheme, as there's no point + * going through that one twice! + */ + OPENSSL_strlcpy(scheme_copy, uri, sizeof(scheme_copy)); + if ((p = strchr(scheme_copy, ':')) != NULL) { + *p++ = '\0'; + if (strcasecmp(scheme_copy, "file") != 0) { + if (strncmp(p, "//", 2) == 0) + schemes_n--; /* Invalidate the file scheme */ + schemes[schemes_n++] = scheme_copy; + } + } + + ERR_set_mark(); + + /* Try each scheme until we find one that could open the URI */ + for (i = 0; loader_ctx == NULL && i < schemes_n; i++) { + if ((loader = ossl_store_get0_loader_int(schemes[i])) != NULL) + loader_ctx = loader->open(loader, uri, ui_method, ui_data); + } + if (loader_ctx == NULL) + goto err; + + if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_OPEN, ERR_R_MALLOC_FAILURE); + goto err; + } + + ctx->loader = loader; + ctx->loader_ctx = loader_ctx; + ctx->ui_method = ui_method; + ctx->ui_data = ui_data; + ctx->post_process = post_process; + ctx->post_process_data = post_process_data; + + /* + * If the attempt to open with the 'file' scheme loader failed and the + * other scheme loader succeeded, the failure to open with the 'file' + * scheme loader leaves an error on the error stack. Let's remove it. + */ + ERR_pop_to_mark(); + + return ctx; + + err: + ERR_clear_last_mark(); + if (loader_ctx != NULL) { + /* + * We ignore a returned error because we will return NULL anyway in + * this case, so if something goes wrong when closing, that'll simply + * just add another entry on the error stack. + */ + (void)loader->close(loader_ctx); + } + return NULL; +} + +int OSSL_STORE_ctrl(OSSL_STORE_CTX *ctx, int cmd, ...) +{ + va_list args; + int ret; + + va_start(args, cmd); + ret = OSSL_STORE_vctrl(ctx, cmd, args); + va_end(args); + + return ret; +} + +int OSSL_STORE_vctrl(OSSL_STORE_CTX *ctx, int cmd, va_list args) +{ + if (ctx->loader->ctrl != NULL) + return ctx->loader->ctrl(ctx->loader_ctx, cmd, args); + return 0; +} + +int OSSL_STORE_expect(OSSL_STORE_CTX *ctx, int expected_type) +{ + if (ctx->loading) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_EXPECT, + OSSL_STORE_R_LOADING_STARTED); + return 0; + } + + ctx->expected_type = expected_type; + if (ctx->loader->expect != NULL) + return ctx->loader->expect(ctx->loader_ctx, expected_type); + return 1; +} + +int OSSL_STORE_find(OSSL_STORE_CTX *ctx, OSSL_STORE_SEARCH *search) +{ + if (ctx->loading) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_FIND, + OSSL_STORE_R_LOADING_STARTED); + return 0; + } + if (ctx->loader->find == NULL) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_FIND, + OSSL_STORE_R_UNSUPPORTED_OPERATION); + return 0; + } + + return ctx->loader->find(ctx->loader_ctx, search); +} + +OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx) +{ + OSSL_STORE_INFO *v = NULL; + + ctx->loading = 1; + again: + if (OSSL_STORE_eof(ctx)) + return NULL; + + v = ctx->loader->load(ctx->loader_ctx, ctx->ui_method, ctx->ui_data); + + if (ctx->post_process != NULL && v != NULL) { + v = ctx->post_process(v, ctx->post_process_data); + + /* + * By returning NULL, the callback decides that this object should + * be ignored. + */ + if (v == NULL) + goto again; + } + + if (v != NULL && ctx->expected_type != 0) { + int returned_type = OSSL_STORE_INFO_get_type(v); + + if (returned_type != OSSL_STORE_INFO_NAME && returned_type != 0) { + /* + * Soft assert here so those who want to harsly weed out faulty + * loaders can do so using a debugging version of libcrypto. + */ + if (ctx->loader->expect != NULL) + assert(ctx->expected_type == returned_type); + + if (ctx->expected_type != returned_type) { + OSSL_STORE_INFO_free(v); + goto again; + } + } + } + + return v; +} + +int OSSL_STORE_error(OSSL_STORE_CTX *ctx) +{ + return ctx->loader->error(ctx->loader_ctx); +} + +int OSSL_STORE_eof(OSSL_STORE_CTX *ctx) +{ + return ctx->loader->eof(ctx->loader_ctx); +} + +int OSSL_STORE_close(OSSL_STORE_CTX *ctx) +{ + int loader_ret = ctx->loader->close(ctx->loader_ctx); + + OPENSSL_free(ctx); + return loader_ret; +} + +/* + * Functions to generate OSSL_STORE_INFOs, one function for each type we + * support having in them as well as a generic constructor. + * + * In all cases, ownership of the object is transfered to the OSSL_STORE_INFO + * and will therefore be freed when the OSSL_STORE_INFO is freed. + */ +static OSSL_STORE_INFO *store_info_new(int type, void *data) +{ + OSSL_STORE_INFO *info = OPENSSL_zalloc(sizeof(*info)); + + if (info == NULL) + return NULL; + + info->type = type; + info->_.data = data; + return info; +} + +OSSL_STORE_INFO *OSSL_STORE_INFO_new_NAME(char *name) +{ + OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_NAME, NULL); + + if (info == NULL) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_NAME, + ERR_R_MALLOC_FAILURE); + return NULL; + } + + info->_.name.name = name; + info->_.name.desc = NULL; + + return info; +} + +int OSSL_STORE_INFO_set0_NAME_description(OSSL_STORE_INFO *info, char *desc) +{ + if (info->type != OSSL_STORE_INFO_NAME) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_SET0_NAME_DESCRIPTION, + ERR_R_PASSED_INVALID_ARGUMENT); + return 0; + } + + info->_.name.desc = desc; + + return 1; +} +OSSL_STORE_INFO *OSSL_STORE_INFO_new_PARAMS(EVP_PKEY *params) +{ + OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_PARAMS, params); + + if (info == NULL) + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_PARAMS, + ERR_R_MALLOC_FAILURE); + return info; +} + +OSSL_STORE_INFO *OSSL_STORE_INFO_new_PKEY(EVP_PKEY *pkey) +{ + OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_PKEY, pkey); + + if (info == NULL) + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_PKEY, + ERR_R_MALLOC_FAILURE); + return info; +} + +OSSL_STORE_INFO *OSSL_STORE_INFO_new_CERT(X509 *x509) +{ + OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_CERT, x509); + + if (info == NULL) + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_CERT, + ERR_R_MALLOC_FAILURE); + return info; +} + +OSSL_STORE_INFO *OSSL_STORE_INFO_new_CRL(X509_CRL *crl) +{ + OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_CRL, crl); + + if (info == NULL) + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_CRL, + ERR_R_MALLOC_FAILURE); + return info; +} + +/* + * Functions to try to extract data from a OSSL_STORE_INFO. + */ +int OSSL_STORE_INFO_get_type(const OSSL_STORE_INFO *info) +{ + return info->type; +} + +const char *OSSL_STORE_INFO_get0_NAME(const OSSL_STORE_INFO *info) +{ + if (info->type == OSSL_STORE_INFO_NAME) + return info->_.name.name; + return NULL; +} + +char *OSSL_STORE_INFO_get1_NAME(const OSSL_STORE_INFO *info) +{ + if (info->type == OSSL_STORE_INFO_NAME) { + char *ret = OPENSSL_strdup(info->_.name.name); + + if (ret == NULL) + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME, + ERR_R_MALLOC_FAILURE); + return ret; + } + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME, + OSSL_STORE_R_NOT_A_NAME); + return NULL; +} + +const char *OSSL_STORE_INFO_get0_NAME_description(const OSSL_STORE_INFO *info) +{ + if (info->type == OSSL_STORE_INFO_NAME) + return info->_.name.desc; + return NULL; +} + +char *OSSL_STORE_INFO_get1_NAME_description(const OSSL_STORE_INFO *info) +{ + if (info->type == OSSL_STORE_INFO_NAME) { + char *ret = OPENSSL_strdup(info->_.name.desc + ? info->_.name.desc : ""); + + if (ret == NULL) + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME_DESCRIPTION, + ERR_R_MALLOC_FAILURE); + return ret; + } + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME_DESCRIPTION, + OSSL_STORE_R_NOT_A_NAME); + return NULL; +} + +EVP_PKEY *OSSL_STORE_INFO_get0_PARAMS(const OSSL_STORE_INFO *info) +{ + if (info->type == OSSL_STORE_INFO_PARAMS) + return info->_.params; + return NULL; +} + +EVP_PKEY *OSSL_STORE_INFO_get1_PARAMS(const OSSL_STORE_INFO *info) +{ + if (info->type == OSSL_STORE_INFO_PARAMS) { + EVP_PKEY_up_ref(info->_.params); + return info->_.params; + } + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_PARAMS, + OSSL_STORE_R_NOT_PARAMETERS); + return NULL; +} + +EVP_PKEY *OSSL_STORE_INFO_get0_PKEY(const OSSL_STORE_INFO *info) +{ + if (info->type == OSSL_STORE_INFO_PKEY) + return info->_.pkey; + return NULL; +} + +EVP_PKEY *OSSL_STORE_INFO_get1_PKEY(const OSSL_STORE_INFO *info) +{ + if (info->type == OSSL_STORE_INFO_PKEY) { + EVP_PKEY_up_ref(info->_.pkey); + return info->_.pkey; + } + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_PKEY, + OSSL_STORE_R_NOT_A_KEY); + return NULL; +} + +X509 *OSSL_STORE_INFO_get0_CERT(const OSSL_STORE_INFO *info) +{ + if (info->type == OSSL_STORE_INFO_CERT) + return info->_.x509; + return NULL; +} + +X509 *OSSL_STORE_INFO_get1_CERT(const OSSL_STORE_INFO *info) +{ + if (info->type == OSSL_STORE_INFO_CERT) { + X509_up_ref(info->_.x509); + return info->_.x509; + } + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_CERT, + OSSL_STORE_R_NOT_A_CERTIFICATE); + return NULL; +} + +X509_CRL *OSSL_STORE_INFO_get0_CRL(const OSSL_STORE_INFO *info) +{ + if (info->type == OSSL_STORE_INFO_CRL) + return info->_.crl; + return NULL; +} + +X509_CRL *OSSL_STORE_INFO_get1_CRL(const OSSL_STORE_INFO *info) +{ + if (info->type == OSSL_STORE_INFO_CRL) { + X509_CRL_up_ref(info->_.crl); + return info->_.crl; + } + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_CRL, + OSSL_STORE_R_NOT_A_CRL); + return NULL; +} + +/* + * Free the OSSL_STORE_INFO + */ +void OSSL_STORE_INFO_free(OSSL_STORE_INFO *info) +{ + if (info != NULL) { + switch (info->type) { + case OSSL_STORE_INFO_EMBEDDED: + BUF_MEM_free(info->_.embedded.blob); + OPENSSL_free(info->_.embedded.pem_name); + break; + case OSSL_STORE_INFO_NAME: + OPENSSL_free(info->_.name.name); + OPENSSL_free(info->_.name.desc); + break; + case OSSL_STORE_INFO_PARAMS: + EVP_PKEY_free(info->_.params); + break; + case OSSL_STORE_INFO_PKEY: + EVP_PKEY_free(info->_.pkey); + break; + case OSSL_STORE_INFO_CERT: + X509_free(info->_.x509); + break; + case OSSL_STORE_INFO_CRL: + X509_CRL_free(info->_.crl); + break; + } + OPENSSL_free(info); + } +} + +int OSSL_STORE_supports_search(OSSL_STORE_CTX *ctx, int search_type) +{ + OSSL_STORE_SEARCH tmp_search; + + if (ctx->loader->find == NULL) + return 0; + tmp_search.search_type = search_type; + return ctx->loader->find(NULL, &tmp_search); +} + +/* Search term constructors */ +OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_name(X509_NAME *name) +{ + OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search)); + + if (search == NULL) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_SEARCH_BY_NAME, + ERR_R_MALLOC_FAILURE); + return NULL; + } + + search->search_type = OSSL_STORE_SEARCH_BY_NAME; + search->name = name; + return search; +} + +OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_issuer_serial(X509_NAME *name, + const ASN1_INTEGER *serial) +{ + OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search)); + + if (search == NULL) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ISSUER_SERIAL, + ERR_R_MALLOC_FAILURE); + return NULL; + } + + search->search_type = OSSL_STORE_SEARCH_BY_ISSUER_SERIAL; + search->name = name; + search->serial = serial; + return search; +} + +OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_key_fingerprint(const EVP_MD *digest, + const unsigned char + *bytes, size_t len) +{ + OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search)); + + if (search == NULL) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT, + ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (digest != NULL && len != (size_t)EVP_MD_size(digest)) { + char buf1[20], buf2[20]; + + BIO_snprintf(buf1, sizeof(buf1), "%d", EVP_MD_size(digest)); + BIO_snprintf(buf2, sizeof(buf2), "%zu", len); + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT, + OSSL_STORE_R_FINGERPRINT_SIZE_DOES_NOT_MATCH_DIGEST); + ERR_add_error_data(5, EVP_MD_name(digest), " size is ", buf1, + ", fingerprint size is ", buf2); + } + + search->search_type = OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT; + search->digest = digest; + search->string = bytes; + search->stringlength = len; + return search; +} + +OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_alias(const char *alias) +{ + OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search)); + + if (search == NULL) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ALIAS, + ERR_R_MALLOC_FAILURE); + return NULL; + } + + search->search_type = OSSL_STORE_SEARCH_BY_ALIAS; + search->string = (const unsigned char *)alias; + search->stringlength = strlen(alias); + return search; +} + +/* Search term destructor */ +void OSSL_STORE_SEARCH_free(OSSL_STORE_SEARCH *search) +{ + OPENSSL_free(search); +} + +/* Search term accessors */ +int OSSL_STORE_SEARCH_get_type(const OSSL_STORE_SEARCH *criterion) +{ + return criterion->search_type; +} + +X509_NAME *OSSL_STORE_SEARCH_get0_name(OSSL_STORE_SEARCH *criterion) +{ + return criterion->name; +} + +const ASN1_INTEGER *OSSL_STORE_SEARCH_get0_serial(const OSSL_STORE_SEARCH + *criterion) +{ + return criterion->serial; +} + +const unsigned char *OSSL_STORE_SEARCH_get0_bytes(const OSSL_STORE_SEARCH + *criterion, size_t *length) +{ + *length = criterion->stringlength; + return criterion->string; +} + +const char *OSSL_STORE_SEARCH_get0_string(const OSSL_STORE_SEARCH *criterion) +{ + return (const char *)criterion->string; +} + +const EVP_MD *OSSL_STORE_SEARCH_get0_digest(const OSSL_STORE_SEARCH *criterion) +{ + return criterion->digest; +} + +/* Internal functions */ +OSSL_STORE_INFO *ossl_store_info_new_EMBEDDED(const char *new_pem_name, + BUF_MEM *embedded) +{ + OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_EMBEDDED, NULL); + + if (info == NULL) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_EMBEDDED, + ERR_R_MALLOC_FAILURE); + return NULL; + } + + info->_.embedded.blob = embedded; + info->_.embedded.pem_name = + new_pem_name == NULL ? NULL : OPENSSL_strdup(new_pem_name); + + if (new_pem_name != NULL && info->_.embedded.pem_name == NULL) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_NEW_EMBEDDED, + ERR_R_MALLOC_FAILURE); + OSSL_STORE_INFO_free(info); + info = NULL; + } + + return info; +} + +BUF_MEM *ossl_store_info_get0_EMBEDDED_buffer(OSSL_STORE_INFO *info) +{ + if (info->type == OSSL_STORE_INFO_EMBEDDED) + return info->_.embedded.blob; + return NULL; +} + +char *ossl_store_info_get0_EMBEDDED_pem_name(OSSL_STORE_INFO *info) +{ + if (info->type == OSSL_STORE_INFO_EMBEDDED) + return info->_.embedded.pem_name; + return NULL; +} + +OSSL_STORE_CTX *ossl_store_attach_pem_bio(BIO *bp, const UI_METHOD *ui_method, + void *ui_data) +{ + OSSL_STORE_CTX *ctx = NULL; + const OSSL_STORE_LOADER *loader = NULL; + OSSL_STORE_LOADER_CTX *loader_ctx = NULL; + + if ((loader = ossl_store_get0_loader_int("file")) == NULL + || ((loader_ctx = ossl_store_file_attach_pem_bio_int(bp)) == NULL)) + goto done; + if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_ATTACH_PEM_BIO, + ERR_R_MALLOC_FAILURE); + goto done; + } + + ctx->loader = loader; + ctx->loader_ctx = loader_ctx; + loader_ctx = NULL; + ctx->ui_method = ui_method; + ctx->ui_data = ui_data; + ctx->post_process = NULL; + ctx->post_process_data = NULL; + + done: + if (loader_ctx != NULL) + /* + * We ignore a returned error because we will return NULL anyway in + * this case, so if something goes wrong when closing, that'll simply + * just add another entry on the error stack. + */ + (void)loader->close(loader_ctx); + return ctx; +} + +int ossl_store_detach_pem_bio(OSSL_STORE_CTX *ctx) +{ + int loader_ret = ossl_store_file_detach_pem_bio_int(ctx->loader_ctx); + + OPENSSL_free(ctx); + return loader_ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/store/store_locl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/store/store_locl.h new file mode 100644 index 000000000..369dcb33f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/store/store_locl.h @@ -0,0 +1,132 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/thread_once.h" +#include +#include +#include +#include +#include +#include + +/*- + * OSSL_STORE_INFO stuff + * --------------------- + */ + +struct ossl_store_info_st { + int type; + union { + void *data; /* used internally as generic pointer */ + + struct { + BUF_MEM *blob; + char *pem_name; + } embedded; /* when type == OSSL_STORE_INFO_EMBEDDED */ + + struct { + char *name; + char *desc; + } name; /* when type == OSSL_STORE_INFO_NAME */ + + EVP_PKEY *params; /* when type == OSSL_STORE_INFO_PARAMS */ + EVP_PKEY *pkey; /* when type == OSSL_STORE_INFO_PKEY */ + X509 *x509; /* when type == OSSL_STORE_INFO_CERT */ + X509_CRL *crl; /* when type == OSSL_STORE_INFO_CRL */ + } _; +}; + +DEFINE_STACK_OF(OSSL_STORE_INFO) + +/* + * EMBEDDED is a special type of OSSL_STORE_INFO, specially for the file + * handlers. It should never reach a calling application or any engine. + * However, it can be used by a FILE_HANDLER's try_decode function to signal + * that it has decoded the incoming blob into a new blob, and that the + * attempted decoding should be immediately restarted with the new blob, using + * the new PEM name. + */ +/* + * Because this is an internal type, we don't make it public. + */ +#define OSSL_STORE_INFO_EMBEDDED -1 +OSSL_STORE_INFO *ossl_store_info_new_EMBEDDED(const char *new_pem_name, + BUF_MEM *embedded); +BUF_MEM *ossl_store_info_get0_EMBEDDED_buffer(OSSL_STORE_INFO *info); +char *ossl_store_info_get0_EMBEDDED_pem_name(OSSL_STORE_INFO *info); + +/*- + * OSSL_STORE_SEARCH stuff + * ----------------------- + */ + +struct ossl_store_search_st { + int search_type; + + /* + * Used by OSSL_STORE_SEARCH_BY_NAME and + * OSSL_STORE_SEARCH_BY_ISSUER_SERIAL + */ + X509_NAME *name; + + /* Used by OSSL_STORE_SEARCH_BY_ISSUER_SERIAL */ + const ASN1_INTEGER *serial; + + /* Used by OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT */ + const EVP_MD *digest; + + /* + * Used by OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT and + * OSSL_STORE_SEARCH_BY_ALIAS + */ + const unsigned char *string; + size_t stringlength; +}; + +/*- + * OSSL_STORE_LOADER stuff + * ----------------------- + */ + +int ossl_store_register_loader_int(OSSL_STORE_LOADER *loader); +OSSL_STORE_LOADER *ossl_store_unregister_loader_int(const char *scheme); + +/* loader stuff */ +struct ossl_store_loader_st { + const char *scheme; + ENGINE *engine; + OSSL_STORE_open_fn open; + OSSL_STORE_ctrl_fn ctrl; + OSSL_STORE_expect_fn expect; + OSSL_STORE_find_fn find; + OSSL_STORE_load_fn load; + OSSL_STORE_eof_fn eof; + OSSL_STORE_error_fn error; + OSSL_STORE_close_fn close; +}; +DEFINE_LHASH_OF(OSSL_STORE_LOADER); + +const OSSL_STORE_LOADER *ossl_store_get0_loader_int(const char *scheme); +void ossl_store_destroy_loaders_int(void); + +/*- + * OSSL_STORE init stuff + * --------------------- + */ + +int ossl_store_init_once(void); +int ossl_store_file_loader_init(void); + +/*- + * 'file' scheme stuff + * ------------------- + */ + +OSSL_STORE_LOADER_CTX *ossl_store_file_attach_pem_bio_int(BIO *bp); +int ossl_store_file_detach_pem_bio_int(OSSL_STORE_LOADER_CTX *ctx); diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/store/store_register.c b/trunk/3rdparty/openssl-1.1-fit/crypto/store/store_register.c new file mode 100644 index 000000000..e68cb3c56 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/store/store_register.c @@ -0,0 +1,297 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/ctype.h" +#include + +#include +#include +#include "store_locl.h" + +static CRYPTO_RWLOCK *registry_lock; +static CRYPTO_ONCE registry_init = CRYPTO_ONCE_STATIC_INIT; + +DEFINE_RUN_ONCE_STATIC(do_registry_init) +{ + registry_lock = CRYPTO_THREAD_lock_new(); + return registry_lock != NULL; +} + +/* + * Functions for manipulating OSSL_STORE_LOADERs + */ + +OSSL_STORE_LOADER *OSSL_STORE_LOADER_new(ENGINE *e, const char *scheme) +{ + OSSL_STORE_LOADER *res = NULL; + + /* + * We usually don't check NULL arguments. For loaders, though, the + * scheme is crucial and must never be NULL, or the user will get + * mysterious errors when trying to register the created loader + * later on. + */ + if (scheme == NULL) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_LOADER_NEW, + OSSL_STORE_R_INVALID_SCHEME); + return NULL; + } + + if ((res = OPENSSL_zalloc(sizeof(*res))) == NULL) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_LOADER_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + res->engine = e; + res->scheme = scheme; + return res; +} + +const ENGINE *OSSL_STORE_LOADER_get0_engine(const OSSL_STORE_LOADER *loader) +{ + return loader->engine; +} + +const char *OSSL_STORE_LOADER_get0_scheme(const OSSL_STORE_LOADER *loader) +{ + return loader->scheme; +} + +int OSSL_STORE_LOADER_set_open(OSSL_STORE_LOADER *loader, + OSSL_STORE_open_fn open_function) +{ + loader->open = open_function; + return 1; +} + +int OSSL_STORE_LOADER_set_ctrl(OSSL_STORE_LOADER *loader, + OSSL_STORE_ctrl_fn ctrl_function) +{ + loader->ctrl = ctrl_function; + return 1; +} + +int OSSL_STORE_LOADER_set_expect(OSSL_STORE_LOADER *loader, + OSSL_STORE_expect_fn expect_function) +{ + loader->expect = expect_function; + return 1; +} + +int OSSL_STORE_LOADER_set_find(OSSL_STORE_LOADER *loader, + OSSL_STORE_find_fn find_function) +{ + loader->find = find_function; + return 1; +} + +int OSSL_STORE_LOADER_set_load(OSSL_STORE_LOADER *loader, + OSSL_STORE_load_fn load_function) +{ + loader->load = load_function; + return 1; +} + +int OSSL_STORE_LOADER_set_eof(OSSL_STORE_LOADER *loader, + OSSL_STORE_eof_fn eof_function) +{ + loader->eof = eof_function; + return 1; +} + +int OSSL_STORE_LOADER_set_error(OSSL_STORE_LOADER *loader, + OSSL_STORE_error_fn error_function) +{ + loader->error = error_function; + return 1; +} + +int OSSL_STORE_LOADER_set_close(OSSL_STORE_LOADER *loader, + OSSL_STORE_close_fn close_function) +{ + loader->close = close_function; + return 1; +} + +void OSSL_STORE_LOADER_free(OSSL_STORE_LOADER *loader) +{ + OPENSSL_free(loader); +} + +/* + * Functions for registering OSSL_STORE_LOADERs + */ + +static unsigned long store_loader_hash(const OSSL_STORE_LOADER *v) +{ + return OPENSSL_LH_strhash(v->scheme); +} + +static int store_loader_cmp(const OSSL_STORE_LOADER *a, + const OSSL_STORE_LOADER *b) +{ + assert(a->scheme != NULL && b->scheme != NULL); + return strcmp(a->scheme, b->scheme); +} + +static LHASH_OF(OSSL_STORE_LOADER) *loader_register = NULL; + +int ossl_store_register_loader_int(OSSL_STORE_LOADER *loader) +{ + const char *scheme = loader->scheme; + int ok = 0; + + /* + * Check that the given scheme conforms to correct scheme syntax as per + * RFC 3986: + * + * scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + */ + if (ossl_isalpha(*scheme)) + while (*scheme != '\0' + && (ossl_isalpha(*scheme) + || ossl_isdigit(*scheme) + || strchr("+-.", *scheme) != NULL)) + scheme++; + if (*scheme != '\0') { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_REGISTER_LOADER_INT, + OSSL_STORE_R_INVALID_SCHEME); + ERR_add_error_data(2, "scheme=", loader->scheme); + return 0; + } + + /* Check that functions we absolutely require are present */ + if (loader->open == NULL || loader->load == NULL || loader->eof == NULL + || loader->error == NULL || loader->close == NULL) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_REGISTER_LOADER_INT, + OSSL_STORE_R_LOADER_INCOMPLETE); + return 0; + } + + if (!RUN_ONCE(®istry_init, do_registry_init)) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_REGISTER_LOADER_INT, + ERR_R_MALLOC_FAILURE); + return 0; + } + CRYPTO_THREAD_write_lock(registry_lock); + + if (loader_register == NULL) { + loader_register = lh_OSSL_STORE_LOADER_new(store_loader_hash, + store_loader_cmp); + } + + if (loader_register != NULL + && (lh_OSSL_STORE_LOADER_insert(loader_register, loader) != NULL + || lh_OSSL_STORE_LOADER_error(loader_register) == 0)) + ok = 1; + + CRYPTO_THREAD_unlock(registry_lock); + + return ok; +} +int OSSL_STORE_register_loader(OSSL_STORE_LOADER *loader) +{ + if (!ossl_store_init_once()) + return 0; + return ossl_store_register_loader_int(loader); +} + +const OSSL_STORE_LOADER *ossl_store_get0_loader_int(const char *scheme) +{ + OSSL_STORE_LOADER template; + OSSL_STORE_LOADER *loader = NULL; + + template.scheme = scheme; + template.open = NULL; + template.load = NULL; + template.eof = NULL; + template.close = NULL; + + if (!ossl_store_init_once()) + return NULL; + + if (!RUN_ONCE(®istry_init, do_registry_init)) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_GET0_LOADER_INT, + ERR_R_MALLOC_FAILURE); + return NULL; + } + CRYPTO_THREAD_write_lock(registry_lock); + + loader = lh_OSSL_STORE_LOADER_retrieve(loader_register, &template); + + if (loader == NULL) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_GET0_LOADER_INT, + OSSL_STORE_R_UNREGISTERED_SCHEME); + ERR_add_error_data(2, "scheme=", scheme); + } + + CRYPTO_THREAD_unlock(registry_lock); + + return loader; +} + +OSSL_STORE_LOADER *ossl_store_unregister_loader_int(const char *scheme) +{ + OSSL_STORE_LOADER template; + OSSL_STORE_LOADER *loader = NULL; + + template.scheme = scheme; + template.open = NULL; + template.load = NULL; + template.eof = NULL; + template.close = NULL; + + if (!RUN_ONCE(®istry_init, do_registry_init)) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_UNREGISTER_LOADER_INT, + ERR_R_MALLOC_FAILURE); + return NULL; + } + CRYPTO_THREAD_write_lock(registry_lock); + + loader = lh_OSSL_STORE_LOADER_delete(loader_register, &template); + + if (loader == NULL) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_UNREGISTER_LOADER_INT, + OSSL_STORE_R_UNREGISTERED_SCHEME); + ERR_add_error_data(2, "scheme=", scheme); + } + + CRYPTO_THREAD_unlock(registry_lock); + + return loader; +} +OSSL_STORE_LOADER *OSSL_STORE_unregister_loader(const char *scheme) +{ + if (!ossl_store_init_once()) + return 0; + return ossl_store_unregister_loader_int(scheme); +} + +void ossl_store_destroy_loaders_int(void) +{ + assert(lh_OSSL_STORE_LOADER_num_items(loader_register) == 0); + lh_OSSL_STORE_LOADER_free(loader_register); + loader_register = NULL; + CRYPTO_THREAD_lock_free(registry_lock); + registry_lock = NULL; +} + +/* + * Functions to list OSSL_STORE loaders + */ + +IMPLEMENT_LHASH_DOALL_ARG_CONST(OSSL_STORE_LOADER, void); +int OSSL_STORE_do_all_loaders(void (*do_function) (const OSSL_STORE_LOADER + *loader, void *do_arg), + void *do_arg) +{ + lh_OSSL_STORE_LOADER_doall_void(loader_register, do_function, do_arg); + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/store/store_strings.c b/trunk/3rdparty/openssl-1.1-fit/crypto/store/store_strings.c new file mode 100644 index 000000000..76cf31648 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/store/store_strings.c @@ -0,0 +1,28 @@ +/* + * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +static char *type_strings[] = { + "Name", /* OSSL_STORE_INFO_NAME */ + "Parameters", /* OSSL_STORE_INFO_PARAMS */ + "Pkey", /* OSSL_STORE_INFO_PKEY */ + "Certificate", /* OSSL_STORE_INFO_CERT */ + "CRL" /* OSSL_STORE_INFO_CRL */ +}; + +const char *OSSL_STORE_INFO_type_string(int type) +{ + int types = sizeof(type_strings) / sizeof(type_strings[0]); + + if (type < 1 || type > types) + return NULL; + + return type_strings[type - 1]; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/threads_none.c b/trunk/3rdparty/openssl-1.1-fit/crypto/threads_none.c new file mode 100644 index 000000000..4b1940ae4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/threads_none.c @@ -0,0 +1,136 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" + +#if !defined(OPENSSL_THREADS) || defined(CRYPTO_TDEBUG) + +CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void) +{ + CRYPTO_RWLOCK *lock; + + if ((lock = OPENSSL_zalloc(sizeof(unsigned int))) == NULL) { + /* Don't set error, to avoid recursion blowup. */ + return NULL; + } + + *(unsigned int *)lock = 1; + + return lock; +} + +int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock) +{ + if (!ossl_assert(*(unsigned int *)lock == 1)) + return 0; + return 1; +} + +int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock) +{ + if (!ossl_assert(*(unsigned int *)lock == 1)) + return 0; + return 1; +} + +int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock) +{ + if (!ossl_assert(*(unsigned int *)lock == 1)) + return 0; + return 1; +} + +void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock) { + if (lock == NULL) + return; + + *(unsigned int *)lock = 0; + OPENSSL_free(lock); + + return; +} + +int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void)) +{ + if (*once != 0) + return 1; + + init(); + *once = 1; + + return 1; +} + +#define OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX 256 + +static void *thread_local_storage[OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX]; + +int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *)) +{ + static unsigned int thread_local_key = 0; + + if (thread_local_key >= OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX) + return 0; + + *key = thread_local_key++; + + thread_local_storage[*key] = NULL; + + return 1; +} + +void *CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL *key) +{ + if (*key >= OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX) + return NULL; + + return thread_local_storage[*key]; +} + +int CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL *key, void *val) +{ + if (*key >= OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX) + return 0; + + thread_local_storage[*key] = val; + + return 1; +} + +int CRYPTO_THREAD_cleanup_local(CRYPTO_THREAD_LOCAL *key) +{ + *key = OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX + 1; + return 1; +} + +CRYPTO_THREAD_ID CRYPTO_THREAD_get_current_id(void) +{ + return 0; +} + +int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b) +{ + return (a == b); +} + +int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock) +{ + *val += amount; + *ret = *val; + + return 1; +} + +int openssl_init_fork_handlers(void) +{ + return 0; +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/threads_pthread.c b/trunk/3rdparty/openssl-1.1-fit/crypto/threads_pthread.c new file mode 100644 index 000000000..5a59779eb --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/threads_pthread.c @@ -0,0 +1,196 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" + +#if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) && !defined(OPENSSL_SYS_WINDOWS) + +# ifdef PTHREAD_RWLOCK_INITIALIZER +# define USE_RWLOCK +# endif + +CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void) +{ +# ifdef USE_RWLOCK + CRYPTO_RWLOCK *lock; + + if ((lock = OPENSSL_zalloc(sizeof(pthread_rwlock_t))) == NULL) { + /* Don't set error, to avoid recursion blowup. */ + return NULL; + } + + if (pthread_rwlock_init(lock, NULL) != 0) { + OPENSSL_free(lock); + return NULL; + } +# else + pthread_mutexattr_t attr; + CRYPTO_RWLOCK *lock; + + if ((lock = OPENSSL_zalloc(sizeof(pthread_mutex_t))) == NULL) { + /* Don't set error, to avoid recursion blowup. */ + return NULL; + } + + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + + if (pthread_mutex_init(lock, &attr) != 0) { + pthread_mutexattr_destroy(&attr); + OPENSSL_free(lock); + return NULL; + } + + pthread_mutexattr_destroy(&attr); +# endif + + return lock; +} + +int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock) +{ +# ifdef USE_RWLOCK + if (pthread_rwlock_rdlock(lock) != 0) + return 0; +# else + if (pthread_mutex_lock(lock) != 0) + return 0; +# endif + + return 1; +} + +int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock) +{ +# ifdef USE_RWLOCK + if (pthread_rwlock_wrlock(lock) != 0) + return 0; +# else + if (pthread_mutex_lock(lock) != 0) + return 0; +# endif + + return 1; +} + +int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock) +{ +# ifdef USE_RWLOCK + if (pthread_rwlock_unlock(lock) != 0) + return 0; +# else + if (pthread_mutex_unlock(lock) != 0) + return 0; +# endif + + return 1; +} + +void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock) +{ + if (lock == NULL) + return; + +# ifdef USE_RWLOCK + pthread_rwlock_destroy(lock); +# else + pthread_mutex_destroy(lock); +# endif + OPENSSL_free(lock); + + return; +} + +int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void)) +{ + if (pthread_once(once, init) != 0) + return 0; + + return 1; +} + +int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *)) +{ + if (pthread_key_create(key, cleanup) != 0) + return 0; + + return 1; +} + +void *CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL *key) +{ + return pthread_getspecific(*key); +} + +int CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL *key, void *val) +{ + if (pthread_setspecific(*key, val) != 0) + return 0; + + return 1; +} + +int CRYPTO_THREAD_cleanup_local(CRYPTO_THREAD_LOCAL *key) +{ + if (pthread_key_delete(*key) != 0) + return 0; + + return 1; +} + +CRYPTO_THREAD_ID CRYPTO_THREAD_get_current_id(void) +{ + return pthread_self(); +} + +int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b) +{ + return pthread_equal(a, b); +} + +int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock) +{ +# if defined(__GNUC__) && defined(__ATOMIC_ACQ_REL) + if (__atomic_is_lock_free(sizeof(*val), val)) { + *ret = __atomic_add_fetch(val, amount, __ATOMIC_ACQ_REL); + return 1; + } +# endif + if (!CRYPTO_THREAD_write_lock(lock)) + return 0; + + *val += amount; + *ret = *val; + + if (!CRYPTO_THREAD_unlock(lock)) + return 0; + + return 1; +} + +# ifdef OPENSSL_SYS_UNIX +static pthread_once_t fork_once_control = PTHREAD_ONCE_INIT; + +static void fork_once_func(void) +{ + pthread_atfork(OPENSSL_fork_prepare, + OPENSSL_fork_parent, OPENSSL_fork_child); +} +# endif + +int openssl_init_fork_handlers(void) +{ +# ifdef OPENSSL_SYS_UNIX + if (pthread_once(&fork_once_control, fork_once_func) == 0) + return 1; +# endif + return 0; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/threads_win.c b/trunk/3rdparty/openssl-1.1-fit/crypto/threads_win.c new file mode 100644 index 000000000..d8fdfb74f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/threads_win.c @@ -0,0 +1,163 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#if defined(_WIN32) +# include +#endif + +#include + +#if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) && defined(OPENSSL_SYS_WINDOWS) + +CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void) +{ + CRYPTO_RWLOCK *lock; + + if ((lock = OPENSSL_zalloc(sizeof(CRITICAL_SECTION))) == NULL) { + /* Don't set error, to avoid recursion blowup. */ + return NULL; + } + + /* 0x400 is the spin count value suggested in the documentation */ + if (!InitializeCriticalSectionAndSpinCount(lock, 0x400)) { + OPENSSL_free(lock); + return NULL; + } + + return lock; +} + +int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock) +{ + EnterCriticalSection(lock); + return 1; +} + +int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock) +{ + EnterCriticalSection(lock); + return 1; +} + +int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock) +{ + LeaveCriticalSection(lock); + return 1; +} + +void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock) +{ + if (lock == NULL) + return; + + DeleteCriticalSection(lock); + OPENSSL_free(lock); + + return; +} + +# define ONCE_UNINITED 0 +# define ONCE_ININIT 1 +# define ONCE_DONE 2 + +/* + * We don't use InitOnceExecuteOnce because that isn't available in WinXP which + * we still have to support. + */ +int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void)) +{ + LONG volatile *lock = (LONG *)once; + LONG result; + + if (*lock == ONCE_DONE) + return 1; + + do { + result = InterlockedCompareExchange(lock, ONCE_ININIT, ONCE_UNINITED); + if (result == ONCE_UNINITED) { + init(); + *lock = ONCE_DONE; + return 1; + } + } while (result == ONCE_ININIT); + + return (*lock == ONCE_DONE); +} + +int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *)) +{ + *key = TlsAlloc(); + if (*key == TLS_OUT_OF_INDEXES) + return 0; + + return 1; +} + +void *CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL *key) +{ + DWORD last_error; + void *ret; + + /* + * TlsGetValue clears the last error even on success, so that callers may + * distinguish it successfully returning NULL or failing. It is documented + * to never fail if the argument is a valid index from TlsAlloc, so we do + * not need to handle this. + * + * However, this error-mangling behavior interferes with the caller's use of + * GetLastError. In particular SSL_get_error queries the error queue to + * determine whether the caller should look at the OS's errors. To avoid + * destroying state, save and restore the Windows error. + * + * https://msdn.microsoft.com/en-us/library/windows/desktop/ms686812(v=vs.85).aspx + */ + last_error = GetLastError(); + ret = TlsGetValue(*key); + SetLastError(last_error); + return ret; +} + +int CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL *key, void *val) +{ + if (TlsSetValue(*key, val) == 0) + return 0; + + return 1; +} + +int CRYPTO_THREAD_cleanup_local(CRYPTO_THREAD_LOCAL *key) +{ + if (TlsFree(*key) == 0) + return 0; + + return 1; +} + +CRYPTO_THREAD_ID CRYPTO_THREAD_get_current_id(void) +{ + return GetCurrentThreadId(); +} + +int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b) +{ + return (a == b); +} + +int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock) +{ + *ret = InterlockedExchangeAdd(val, amount) + amount; + return 1; +} + +int openssl_init_fork_handlers(void) +{ + return 0; +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ts/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/ts/build.info new file mode 100644 index 000000000..98e633d57 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ts/build.info @@ -0,0 +1,5 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + ts_err.c ts_req_utils.c ts_req_print.c ts_rsp_utils.c ts_rsp_print.c \ + ts_rsp_sign.c ts_rsp_verify.c ts_verify_ctx.c ts_lib.c ts_conf.c \ + ts_asn1.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_asn1.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_asn1.c new file mode 100644 index 000000000..870720708 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_asn1.c @@ -0,0 +1,276 @@ +/* + * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "ts_lcl.h" + +ASN1_SEQUENCE(TS_MSG_IMPRINT) = { + ASN1_SIMPLE(TS_MSG_IMPRINT, hash_algo, X509_ALGOR), + ASN1_SIMPLE(TS_MSG_IMPRINT, hashed_msg, ASN1_OCTET_STRING) +} static_ASN1_SEQUENCE_END(TS_MSG_IMPRINT) + +IMPLEMENT_ASN1_FUNCTIONS_const(TS_MSG_IMPRINT) +IMPLEMENT_ASN1_DUP_FUNCTION(TS_MSG_IMPRINT) +TS_MSG_IMPRINT *d2i_TS_MSG_IMPRINT_bio(BIO *bp, TS_MSG_IMPRINT **a) +{ + return ASN1_d2i_bio_of(TS_MSG_IMPRINT, TS_MSG_IMPRINT_new, + d2i_TS_MSG_IMPRINT, bp, a); +} + +int i2d_TS_MSG_IMPRINT_bio(BIO *bp, TS_MSG_IMPRINT *a) +{ + return ASN1_i2d_bio_of_const(TS_MSG_IMPRINT, i2d_TS_MSG_IMPRINT, bp, a); +} +#ifndef OPENSSL_NO_STDIO +TS_MSG_IMPRINT *d2i_TS_MSG_IMPRINT_fp(FILE *fp, TS_MSG_IMPRINT **a) +{ + return ASN1_d2i_fp_of(TS_MSG_IMPRINT, TS_MSG_IMPRINT_new, + d2i_TS_MSG_IMPRINT, fp, a); +} + +int i2d_TS_MSG_IMPRINT_fp(FILE *fp, TS_MSG_IMPRINT *a) +{ + return ASN1_i2d_fp_of_const(TS_MSG_IMPRINT, i2d_TS_MSG_IMPRINT, fp, a); +} +#endif + +ASN1_SEQUENCE(TS_REQ) = { + ASN1_SIMPLE(TS_REQ, version, ASN1_INTEGER), + ASN1_SIMPLE(TS_REQ, msg_imprint, TS_MSG_IMPRINT), + ASN1_OPT(TS_REQ, policy_id, ASN1_OBJECT), + ASN1_OPT(TS_REQ, nonce, ASN1_INTEGER), + ASN1_OPT(TS_REQ, cert_req, ASN1_FBOOLEAN), + ASN1_IMP_SEQUENCE_OF_OPT(TS_REQ, extensions, X509_EXTENSION, 0) +} static_ASN1_SEQUENCE_END(TS_REQ) + +IMPLEMENT_ASN1_FUNCTIONS_const(TS_REQ) +IMPLEMENT_ASN1_DUP_FUNCTION(TS_REQ) +TS_REQ *d2i_TS_REQ_bio(BIO *bp, TS_REQ **a) +{ + return ASN1_d2i_bio_of(TS_REQ, TS_REQ_new, d2i_TS_REQ, bp, a); +} + +int i2d_TS_REQ_bio(BIO *bp, TS_REQ *a) +{ + return ASN1_i2d_bio_of_const(TS_REQ, i2d_TS_REQ, bp, a); +} +#ifndef OPENSSL_NO_STDIO +TS_REQ *d2i_TS_REQ_fp(FILE *fp, TS_REQ **a) +{ + return ASN1_d2i_fp_of(TS_REQ, TS_REQ_new, d2i_TS_REQ, fp, a); +} + +int i2d_TS_REQ_fp(FILE *fp, TS_REQ *a) +{ + return ASN1_i2d_fp_of_const(TS_REQ, i2d_TS_REQ, fp, a); +} +#endif + +ASN1_SEQUENCE(TS_ACCURACY) = { + ASN1_OPT(TS_ACCURACY, seconds, ASN1_INTEGER), + ASN1_IMP_OPT(TS_ACCURACY, millis, ASN1_INTEGER, 0), + ASN1_IMP_OPT(TS_ACCURACY, micros, ASN1_INTEGER, 1) +} static_ASN1_SEQUENCE_END(TS_ACCURACY) + +IMPLEMENT_ASN1_FUNCTIONS_const(TS_ACCURACY) +IMPLEMENT_ASN1_DUP_FUNCTION(TS_ACCURACY) + +ASN1_SEQUENCE(TS_TST_INFO) = { + ASN1_SIMPLE(TS_TST_INFO, version, ASN1_INTEGER), + ASN1_SIMPLE(TS_TST_INFO, policy_id, ASN1_OBJECT), + ASN1_SIMPLE(TS_TST_INFO, msg_imprint, TS_MSG_IMPRINT), + ASN1_SIMPLE(TS_TST_INFO, serial, ASN1_INTEGER), + ASN1_SIMPLE(TS_TST_INFO, time, ASN1_GENERALIZEDTIME), + ASN1_OPT(TS_TST_INFO, accuracy, TS_ACCURACY), + ASN1_OPT(TS_TST_INFO, ordering, ASN1_FBOOLEAN), + ASN1_OPT(TS_TST_INFO, nonce, ASN1_INTEGER), + ASN1_EXP_OPT(TS_TST_INFO, tsa, GENERAL_NAME, 0), + ASN1_IMP_SEQUENCE_OF_OPT(TS_TST_INFO, extensions, X509_EXTENSION, 1) +} static_ASN1_SEQUENCE_END(TS_TST_INFO) + +IMPLEMENT_ASN1_FUNCTIONS_const(TS_TST_INFO) +IMPLEMENT_ASN1_DUP_FUNCTION(TS_TST_INFO) +TS_TST_INFO *d2i_TS_TST_INFO_bio(BIO *bp, TS_TST_INFO **a) +{ + return ASN1_d2i_bio_of(TS_TST_INFO, TS_TST_INFO_new, d2i_TS_TST_INFO, bp, + a); +} + +int i2d_TS_TST_INFO_bio(BIO *bp, TS_TST_INFO *a) +{ + return ASN1_i2d_bio_of_const(TS_TST_INFO, i2d_TS_TST_INFO, bp, a); +} +#ifndef OPENSSL_NO_STDIO +TS_TST_INFO *d2i_TS_TST_INFO_fp(FILE *fp, TS_TST_INFO **a) +{ + return ASN1_d2i_fp_of(TS_TST_INFO, TS_TST_INFO_new, d2i_TS_TST_INFO, fp, + a); +} + +int i2d_TS_TST_INFO_fp(FILE *fp, TS_TST_INFO *a) +{ + return ASN1_i2d_fp_of_const(TS_TST_INFO, i2d_TS_TST_INFO, fp, a); +} +#endif + +ASN1_SEQUENCE(TS_STATUS_INFO) = { + ASN1_SIMPLE(TS_STATUS_INFO, status, ASN1_INTEGER), + ASN1_SEQUENCE_OF_OPT(TS_STATUS_INFO, text, ASN1_UTF8STRING), + ASN1_OPT(TS_STATUS_INFO, failure_info, ASN1_BIT_STRING) +} static_ASN1_SEQUENCE_END(TS_STATUS_INFO) + +IMPLEMENT_ASN1_FUNCTIONS_const(TS_STATUS_INFO) +IMPLEMENT_ASN1_DUP_FUNCTION(TS_STATUS_INFO) + +static int ts_resp_set_tst_info(TS_RESP *a) +{ + long status; + + status = ASN1_INTEGER_get(a->status_info->status); + + if (a->token) { + if (status != 0 && status != 1) { + TSerr(TS_F_TS_RESP_SET_TST_INFO, TS_R_TOKEN_PRESENT); + return 0; + } + TS_TST_INFO_free(a->tst_info); + a->tst_info = PKCS7_to_TS_TST_INFO(a->token); + if (!a->tst_info) { + TSerr(TS_F_TS_RESP_SET_TST_INFO, + TS_R_PKCS7_TO_TS_TST_INFO_FAILED); + return 0; + } + } else if (status == 0 || status == 1) { + TSerr(TS_F_TS_RESP_SET_TST_INFO, TS_R_TOKEN_NOT_PRESENT); + return 0; + } + + return 1; +} + +static int ts_resp_cb(int op, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + TS_RESP *ts_resp = (TS_RESP *)*pval; + if (op == ASN1_OP_NEW_POST) { + ts_resp->tst_info = NULL; + } else if (op == ASN1_OP_FREE_POST) { + TS_TST_INFO_free(ts_resp->tst_info); + } else if (op == ASN1_OP_D2I_POST) { + if (ts_resp_set_tst_info(ts_resp) == 0) + return 0; + } + return 1; +} + +ASN1_SEQUENCE_cb(TS_RESP, ts_resp_cb) = { + ASN1_SIMPLE(TS_RESP, status_info, TS_STATUS_INFO), + ASN1_OPT(TS_RESP, token, PKCS7), +} static_ASN1_SEQUENCE_END_cb(TS_RESP, TS_RESP) + +IMPLEMENT_ASN1_FUNCTIONS_const(TS_RESP) + +IMPLEMENT_ASN1_DUP_FUNCTION(TS_RESP) + +TS_RESP *d2i_TS_RESP_bio(BIO *bp, TS_RESP **a) +{ + return ASN1_d2i_bio_of(TS_RESP, TS_RESP_new, d2i_TS_RESP, bp, a); +} + +int i2d_TS_RESP_bio(BIO *bp, TS_RESP *a) +{ + return ASN1_i2d_bio_of_const(TS_RESP, i2d_TS_RESP, bp, a); +} +#ifndef OPENSSL_NO_STDIO +TS_RESP *d2i_TS_RESP_fp(FILE *fp, TS_RESP **a) +{ + return ASN1_d2i_fp_of(TS_RESP, TS_RESP_new, d2i_TS_RESP, fp, a); +} + +int i2d_TS_RESP_fp(FILE *fp, TS_RESP *a) +{ + return ASN1_i2d_fp_of_const(TS_RESP, i2d_TS_RESP, fp, a); +} +#endif + +ASN1_SEQUENCE(ESS_ISSUER_SERIAL) = { + ASN1_SEQUENCE_OF(ESS_ISSUER_SERIAL, issuer, GENERAL_NAME), + ASN1_SIMPLE(ESS_ISSUER_SERIAL, serial, ASN1_INTEGER) +} static_ASN1_SEQUENCE_END(ESS_ISSUER_SERIAL) + +IMPLEMENT_ASN1_FUNCTIONS_const(ESS_ISSUER_SERIAL) +IMPLEMENT_ASN1_DUP_FUNCTION(ESS_ISSUER_SERIAL) + +ASN1_SEQUENCE(ESS_CERT_ID) = { + ASN1_SIMPLE(ESS_CERT_ID, hash, ASN1_OCTET_STRING), + ASN1_OPT(ESS_CERT_ID, issuer_serial, ESS_ISSUER_SERIAL) +} static_ASN1_SEQUENCE_END(ESS_CERT_ID) + +IMPLEMENT_ASN1_FUNCTIONS_const(ESS_CERT_ID) +IMPLEMENT_ASN1_DUP_FUNCTION(ESS_CERT_ID) + +ASN1_SEQUENCE(ESS_SIGNING_CERT) = { + ASN1_SEQUENCE_OF(ESS_SIGNING_CERT, cert_ids, ESS_CERT_ID), + ASN1_SEQUENCE_OF_OPT(ESS_SIGNING_CERT, policy_info, POLICYINFO) +} static_ASN1_SEQUENCE_END(ESS_SIGNING_CERT) + +IMPLEMENT_ASN1_FUNCTIONS_const(ESS_SIGNING_CERT) +IMPLEMENT_ASN1_DUP_FUNCTION(ESS_SIGNING_CERT) + +ASN1_SEQUENCE(ESS_CERT_ID_V2) = { + ASN1_OPT(ESS_CERT_ID_V2, hash_alg, X509_ALGOR), + ASN1_SIMPLE(ESS_CERT_ID_V2, hash, ASN1_OCTET_STRING), + ASN1_OPT(ESS_CERT_ID_V2, issuer_serial, ESS_ISSUER_SERIAL) +} static_ASN1_SEQUENCE_END(ESS_CERT_ID_V2) + +IMPLEMENT_ASN1_FUNCTIONS_const(ESS_CERT_ID_V2) +IMPLEMENT_ASN1_DUP_FUNCTION(ESS_CERT_ID_V2) + +ASN1_SEQUENCE(ESS_SIGNING_CERT_V2) = { + ASN1_SEQUENCE_OF(ESS_SIGNING_CERT_V2, cert_ids, ESS_CERT_ID_V2), + ASN1_SEQUENCE_OF_OPT(ESS_SIGNING_CERT_V2, policy_info, POLICYINFO) +} static_ASN1_SEQUENCE_END(ESS_SIGNING_CERT_V2) + +IMPLEMENT_ASN1_FUNCTIONS_const(ESS_SIGNING_CERT_V2) +IMPLEMENT_ASN1_DUP_FUNCTION(ESS_SIGNING_CERT_V2) + +/* Getting encapsulated TS_TST_INFO object from PKCS7. */ +TS_TST_INFO *PKCS7_to_TS_TST_INFO(PKCS7 *token) +{ + PKCS7_SIGNED *pkcs7_signed; + PKCS7 *enveloped; + ASN1_TYPE *tst_info_wrapper; + ASN1_OCTET_STRING *tst_info_der; + const unsigned char *p; + + if (!PKCS7_type_is_signed(token)) { + TSerr(TS_F_PKCS7_TO_TS_TST_INFO, TS_R_BAD_PKCS7_TYPE); + return NULL; + } + if (PKCS7_get_detached(token)) { + TSerr(TS_F_PKCS7_TO_TS_TST_INFO, TS_R_DETACHED_CONTENT); + return NULL; + } + pkcs7_signed = token->d.sign; + enveloped = pkcs7_signed->contents; + if (OBJ_obj2nid(enveloped->type) != NID_id_smime_ct_TSTInfo) { + TSerr(TS_F_PKCS7_TO_TS_TST_INFO, TS_R_BAD_PKCS7_TYPE); + return NULL; + } + tst_info_wrapper = enveloped->d.other; + if (tst_info_wrapper->type != V_ASN1_OCTET_STRING) { + TSerr(TS_F_PKCS7_TO_TS_TST_INFO, TS_R_BAD_TYPE); + return NULL; + } + tst_info_der = tst_info_wrapper->value.octet_string; + p = tst_info_der->data; + return d2i_TS_TST_INFO(NULL, &p, tst_info_der->length); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_conf.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_conf.c new file mode 100644 index 000000000..625089a59 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_conf.c @@ -0,0 +1,493 @@ +/* + * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#include +#include "internal/cryptlib.h" +#include +#include +#include + +/* Macro definitions for the configuration file. */ +#define BASE_SECTION "tsa" +#define ENV_DEFAULT_TSA "default_tsa" +#define ENV_SERIAL "serial" +#define ENV_CRYPTO_DEVICE "crypto_device" +#define ENV_SIGNER_CERT "signer_cert" +#define ENV_CERTS "certs" +#define ENV_SIGNER_KEY "signer_key" +#define ENV_SIGNER_DIGEST "signer_digest" +#define ENV_DEFAULT_POLICY "default_policy" +#define ENV_OTHER_POLICIES "other_policies" +#define ENV_DIGESTS "digests" +#define ENV_ACCURACY "accuracy" +#define ENV_ORDERING "ordering" +#define ENV_TSA_NAME "tsa_name" +#define ENV_ESS_CERT_ID_CHAIN "ess_cert_id_chain" +#define ENV_VALUE_SECS "secs" +#define ENV_VALUE_MILLISECS "millisecs" +#define ENV_VALUE_MICROSECS "microsecs" +#define ENV_CLOCK_PRECISION_DIGITS "clock_precision_digits" +#define ENV_VALUE_YES "yes" +#define ENV_VALUE_NO "no" +#define ENV_ESS_CERT_ID_ALG "ess_cert_id_alg" + +/* Function definitions for certificate and key loading. */ + +X509 *TS_CONF_load_cert(const char *file) +{ + BIO *cert = NULL; + X509 *x = NULL; + + if ((cert = BIO_new_file(file, "r")) == NULL) + goto end; + x = PEM_read_bio_X509_AUX(cert, NULL, NULL, NULL); + end: + if (x == NULL) + TSerr(TS_F_TS_CONF_LOAD_CERT, TS_R_CANNOT_LOAD_CERT); + BIO_free(cert); + return x; +} + +STACK_OF(X509) *TS_CONF_load_certs(const char *file) +{ + BIO *certs = NULL; + STACK_OF(X509) *othercerts = NULL; + STACK_OF(X509_INFO) *allcerts = NULL; + int i; + + if ((certs = BIO_new_file(file, "r")) == NULL) + goto end; + if ((othercerts = sk_X509_new_null()) == NULL) + goto end; + + allcerts = PEM_X509_INFO_read_bio(certs, NULL, NULL, NULL); + for (i = 0; i < sk_X509_INFO_num(allcerts); i++) { + X509_INFO *xi = sk_X509_INFO_value(allcerts, i); + if (xi->x509) { + sk_X509_push(othercerts, xi->x509); + xi->x509 = NULL; + } + } + end: + if (othercerts == NULL) + TSerr(TS_F_TS_CONF_LOAD_CERTS, TS_R_CANNOT_LOAD_CERT); + sk_X509_INFO_pop_free(allcerts, X509_INFO_free); + BIO_free(certs); + return othercerts; +} + +EVP_PKEY *TS_CONF_load_key(const char *file, const char *pass) +{ + BIO *key = NULL; + EVP_PKEY *pkey = NULL; + + if ((key = BIO_new_file(file, "r")) == NULL) + goto end; + pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, (char *)pass); + end: + if (pkey == NULL) + TSerr(TS_F_TS_CONF_LOAD_KEY, TS_R_CANNOT_LOAD_KEY); + BIO_free(key); + return pkey; +} + +/* Function definitions for handling configuration options. */ + +static void ts_CONF_lookup_fail(const char *name, const char *tag) +{ + TSerr(TS_F_TS_CONF_LOOKUP_FAIL, TS_R_VAR_LOOKUP_FAILURE); + ERR_add_error_data(3, name, "::", tag); +} + +static void ts_CONF_invalid(const char *name, const char *tag) +{ + TSerr(TS_F_TS_CONF_INVALID, TS_R_VAR_BAD_VALUE); + ERR_add_error_data(3, name, "::", tag); +} + +const char *TS_CONF_get_tsa_section(CONF *conf, const char *section) +{ + if (!section) { + section = NCONF_get_string(conf, BASE_SECTION, ENV_DEFAULT_TSA); + if (!section) + ts_CONF_lookup_fail(BASE_SECTION, ENV_DEFAULT_TSA); + } + return section; +} + +int TS_CONF_set_serial(CONF *conf, const char *section, TS_serial_cb cb, + TS_RESP_CTX *ctx) +{ + int ret = 0; + char *serial = NCONF_get_string(conf, section, ENV_SERIAL); + if (!serial) { + ts_CONF_lookup_fail(section, ENV_SERIAL); + goto err; + } + TS_RESP_CTX_set_serial_cb(ctx, cb, serial); + + ret = 1; + err: + return ret; +} + +#ifndef OPENSSL_NO_ENGINE + +int TS_CONF_set_crypto_device(CONF *conf, const char *section, + const char *device) +{ + int ret = 0; + + if (device == NULL) + device = NCONF_get_string(conf, section, ENV_CRYPTO_DEVICE); + + if (device && !TS_CONF_set_default_engine(device)) { + ts_CONF_invalid(section, ENV_CRYPTO_DEVICE); + goto err; + } + ret = 1; + err: + return ret; +} + +int TS_CONF_set_default_engine(const char *name) +{ + ENGINE *e = NULL; + int ret = 0; + + if (strcmp(name, "builtin") == 0) + return 1; + + if ((e = ENGINE_by_id(name)) == NULL) + goto err; + if (strcmp(name, "chil") == 0) + ENGINE_ctrl(e, ENGINE_CTRL_CHIL_SET_FORKCHECK, 1, 0, 0); + if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) + goto err; + ret = 1; + + err: + if (!ret) { + TSerr(TS_F_TS_CONF_SET_DEFAULT_ENGINE, TS_R_COULD_NOT_SET_ENGINE); + ERR_add_error_data(2, "engine:", name); + } + ENGINE_free(e); + return ret; +} + +#endif + +int TS_CONF_set_signer_cert(CONF *conf, const char *section, + const char *cert, TS_RESP_CTX *ctx) +{ + int ret = 0; + X509 *cert_obj = NULL; + + if (cert == NULL) { + cert = NCONF_get_string(conf, section, ENV_SIGNER_CERT); + if (cert == NULL) { + ts_CONF_lookup_fail(section, ENV_SIGNER_CERT); + goto err; + } + } + if ((cert_obj = TS_CONF_load_cert(cert)) == NULL) + goto err; + if (!TS_RESP_CTX_set_signer_cert(ctx, cert_obj)) + goto err; + + ret = 1; + err: + X509_free(cert_obj); + return ret; +} + +int TS_CONF_set_certs(CONF *conf, const char *section, const char *certs, + TS_RESP_CTX *ctx) +{ + int ret = 0; + STACK_OF(X509) *certs_obj = NULL; + + if (certs == NULL) { + /* Certificate chain is optional. */ + if ((certs = NCONF_get_string(conf, section, ENV_CERTS)) == NULL) + goto end; + } + if ((certs_obj = TS_CONF_load_certs(certs)) == NULL) + goto err; + if (!TS_RESP_CTX_set_certs(ctx, certs_obj)) + goto err; + end: + ret = 1; + err: + sk_X509_pop_free(certs_obj, X509_free); + return ret; +} + +int TS_CONF_set_signer_key(CONF *conf, const char *section, + const char *key, const char *pass, + TS_RESP_CTX *ctx) +{ + int ret = 0; + EVP_PKEY *key_obj = NULL; + if (!key) + key = NCONF_get_string(conf, section, ENV_SIGNER_KEY); + if (!key) { + ts_CONF_lookup_fail(section, ENV_SIGNER_KEY); + goto err; + } + if ((key_obj = TS_CONF_load_key(key, pass)) == NULL) + goto err; + if (!TS_RESP_CTX_set_signer_key(ctx, key_obj)) + goto err; + + ret = 1; + err: + EVP_PKEY_free(key_obj); + return ret; +} + +int TS_CONF_set_signer_digest(CONF *conf, const char *section, + const char *md, TS_RESP_CTX *ctx) +{ + int ret = 0; + const EVP_MD *sign_md = NULL; + if (md == NULL) + md = NCONF_get_string(conf, section, ENV_SIGNER_DIGEST); + if (md == NULL) { + ts_CONF_lookup_fail(section, ENV_SIGNER_DIGEST); + goto err; + } + sign_md = EVP_get_digestbyname(md); + if (sign_md == NULL) { + ts_CONF_invalid(section, ENV_SIGNER_DIGEST); + goto err; + } + if (!TS_RESP_CTX_set_signer_digest(ctx, sign_md)) + goto err; + + ret = 1; + err: + return ret; +} + +int TS_CONF_set_def_policy(CONF *conf, const char *section, + const char *policy, TS_RESP_CTX *ctx) +{ + int ret = 0; + ASN1_OBJECT *policy_obj = NULL; + if (!policy) + policy = NCONF_get_string(conf, section, ENV_DEFAULT_POLICY); + if (!policy) { + ts_CONF_lookup_fail(section, ENV_DEFAULT_POLICY); + goto err; + } + if ((policy_obj = OBJ_txt2obj(policy, 0)) == NULL) { + ts_CONF_invalid(section, ENV_DEFAULT_POLICY); + goto err; + } + if (!TS_RESP_CTX_set_def_policy(ctx, policy_obj)) + goto err; + + ret = 1; + err: + ASN1_OBJECT_free(policy_obj); + return ret; +} + +int TS_CONF_set_policies(CONF *conf, const char *section, TS_RESP_CTX *ctx) +{ + int ret = 0; + int i; + STACK_OF(CONF_VALUE) *list = NULL; + char *policies = NCONF_get_string(conf, section, ENV_OTHER_POLICIES); + + /* If no other policy is specified, that's fine. */ + if (policies && (list = X509V3_parse_list(policies)) == NULL) { + ts_CONF_invalid(section, ENV_OTHER_POLICIES); + goto err; + } + for (i = 0; i < sk_CONF_VALUE_num(list); ++i) { + CONF_VALUE *val = sk_CONF_VALUE_value(list, i); + const char *extval = val->value ? val->value : val->name; + ASN1_OBJECT *objtmp; + + if ((objtmp = OBJ_txt2obj(extval, 0)) == NULL) { + ts_CONF_invalid(section, ENV_OTHER_POLICIES); + goto err; + } + if (!TS_RESP_CTX_add_policy(ctx, objtmp)) + goto err; + ASN1_OBJECT_free(objtmp); + } + + ret = 1; + err: + sk_CONF_VALUE_pop_free(list, X509V3_conf_free); + return ret; +} + +int TS_CONF_set_digests(CONF *conf, const char *section, TS_RESP_CTX *ctx) +{ + int ret = 0; + int i; + STACK_OF(CONF_VALUE) *list = NULL; + char *digests = NCONF_get_string(conf, section, ENV_DIGESTS); + + if (digests == NULL) { + ts_CONF_lookup_fail(section, ENV_DIGESTS); + goto err; + } + if ((list = X509V3_parse_list(digests)) == NULL) { + ts_CONF_invalid(section, ENV_DIGESTS); + goto err; + } + if (sk_CONF_VALUE_num(list) == 0) { + ts_CONF_invalid(section, ENV_DIGESTS); + goto err; + } + for (i = 0; i < sk_CONF_VALUE_num(list); ++i) { + CONF_VALUE *val = sk_CONF_VALUE_value(list, i); + const char *extval = val->value ? val->value : val->name; + const EVP_MD *md; + + if ((md = EVP_get_digestbyname(extval)) == NULL) { + ts_CONF_invalid(section, ENV_DIGESTS); + goto err; + } + if (!TS_RESP_CTX_add_md(ctx, md)) + goto err; + } + + ret = 1; + err: + sk_CONF_VALUE_pop_free(list, X509V3_conf_free); + return ret; +} + +int TS_CONF_set_accuracy(CONF *conf, const char *section, TS_RESP_CTX *ctx) +{ + int ret = 0; + int i; + int secs = 0, millis = 0, micros = 0; + STACK_OF(CONF_VALUE) *list = NULL; + char *accuracy = NCONF_get_string(conf, section, ENV_ACCURACY); + + if (accuracy && (list = X509V3_parse_list(accuracy)) == NULL) { + ts_CONF_invalid(section, ENV_ACCURACY); + goto err; + } + for (i = 0; i < sk_CONF_VALUE_num(list); ++i) { + CONF_VALUE *val = sk_CONF_VALUE_value(list, i); + if (strcmp(val->name, ENV_VALUE_SECS) == 0) { + if (val->value) + secs = atoi(val->value); + } else if (strcmp(val->name, ENV_VALUE_MILLISECS) == 0) { + if (val->value) + millis = atoi(val->value); + } else if (strcmp(val->name, ENV_VALUE_MICROSECS) == 0) { + if (val->value) + micros = atoi(val->value); + } else { + ts_CONF_invalid(section, ENV_ACCURACY); + goto err; + } + } + if (!TS_RESP_CTX_set_accuracy(ctx, secs, millis, micros)) + goto err; + + ret = 1; + err: + sk_CONF_VALUE_pop_free(list, X509V3_conf_free); + return ret; +} + +int TS_CONF_set_clock_precision_digits(CONF *conf, const char *section, + TS_RESP_CTX *ctx) +{ + int ret = 0; + long digits = 0; + + /* + * If not specified, set the default value to 0, i.e. sec precision + */ + if (!NCONF_get_number_e(conf, section, ENV_CLOCK_PRECISION_DIGITS, + &digits)) + digits = 0; + if (digits < 0 || digits > TS_MAX_CLOCK_PRECISION_DIGITS) { + ts_CONF_invalid(section, ENV_CLOCK_PRECISION_DIGITS); + goto err; + } + + if (!TS_RESP_CTX_set_clock_precision_digits(ctx, digits)) + goto err; + + return 1; + err: + return ret; +} + +static int ts_CONF_add_flag(CONF *conf, const char *section, + const char *field, int flag, TS_RESP_CTX *ctx) +{ + const char *value = NCONF_get_string(conf, section, field); + + if (value) { + if (strcmp(value, ENV_VALUE_YES) == 0) + TS_RESP_CTX_add_flags(ctx, flag); + else if (strcmp(value, ENV_VALUE_NO) != 0) { + ts_CONF_invalid(section, field); + return 0; + } + } + + return 1; +} + +int TS_CONF_set_ordering(CONF *conf, const char *section, TS_RESP_CTX *ctx) +{ + return ts_CONF_add_flag(conf, section, ENV_ORDERING, TS_ORDERING, ctx); +} + +int TS_CONF_set_tsa_name(CONF *conf, const char *section, TS_RESP_CTX *ctx) +{ + return ts_CONF_add_flag(conf, section, ENV_TSA_NAME, TS_TSA_NAME, ctx); +} + +int TS_CONF_set_ess_cert_id_chain(CONF *conf, const char *section, + TS_RESP_CTX *ctx) +{ + return ts_CONF_add_flag(conf, section, ENV_ESS_CERT_ID_CHAIN, + TS_ESS_CERT_ID_CHAIN, ctx); +} + +int TS_CONF_set_ess_cert_id_digest(CONF *conf, const char *section, + TS_RESP_CTX *ctx) +{ + int ret = 0; + const EVP_MD *cert_md = NULL; + const char *md = NCONF_get_string(conf, section, ENV_ESS_CERT_ID_ALG); + + if (md == NULL) + md = "sha1"; + + cert_md = EVP_get_digestbyname(md); + if (cert_md == NULL) { + ts_CONF_invalid(section, ENV_ESS_CERT_ID_ALG); + goto err; + } + + if (!TS_RESP_CTX_set_ess_cert_id_digest(ctx, cert_md)) + goto err; + + ret = 1; +err: + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_err.c new file mode 100644 index 000000000..1f3854d84 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_err.c @@ -0,0 +1,184 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA TS_str_functs[] = { + {ERR_PACK(ERR_LIB_TS, TS_F_DEF_SERIAL_CB, 0), "def_serial_cb"}, + {ERR_PACK(ERR_LIB_TS, TS_F_DEF_TIME_CB, 0), "def_time_cb"}, + {ERR_PACK(ERR_LIB_TS, TS_F_ESS_ADD_SIGNING_CERT, 0), + "ess_add_signing_cert"}, + {ERR_PACK(ERR_LIB_TS, TS_F_ESS_ADD_SIGNING_CERT_V2, 0), + "ess_add_signing_cert_v2"}, + {ERR_PACK(ERR_LIB_TS, TS_F_ESS_CERT_ID_NEW_INIT, 0), + "ess_CERT_ID_new_init"}, + {ERR_PACK(ERR_LIB_TS, TS_F_ESS_CERT_ID_V2_NEW_INIT, 0), + "ess_cert_id_v2_new_init"}, + {ERR_PACK(ERR_LIB_TS, TS_F_ESS_SIGNING_CERT_NEW_INIT, 0), + "ess_SIGNING_CERT_new_init"}, + {ERR_PACK(ERR_LIB_TS, TS_F_ESS_SIGNING_CERT_V2_NEW_INIT, 0), + "ess_signing_cert_v2_new_init"}, + {ERR_PACK(ERR_LIB_TS, TS_F_INT_TS_RESP_VERIFY_TOKEN, 0), + "int_ts_RESP_verify_token"}, + {ERR_PACK(ERR_LIB_TS, TS_F_PKCS7_TO_TS_TST_INFO, 0), + "PKCS7_to_TS_TST_INFO"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_ACCURACY_SET_MICROS, 0), + "TS_ACCURACY_set_micros"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_ACCURACY_SET_MILLIS, 0), + "TS_ACCURACY_set_millis"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_ACCURACY_SET_SECONDS, 0), + "TS_ACCURACY_set_seconds"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_CHECK_IMPRINTS, 0), "ts_check_imprints"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_CHECK_NONCES, 0), "ts_check_nonces"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_CHECK_POLICY, 0), "ts_check_policy"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_CHECK_SIGNING_CERTS, 0), + "ts_check_signing_certs"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_CHECK_STATUS_INFO, 0), + "ts_check_status_info"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_COMPUTE_IMPRINT, 0), "ts_compute_imprint"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_CONF_INVALID, 0), "ts_CONF_invalid"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_CONF_LOAD_CERT, 0), "TS_CONF_load_cert"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_CONF_LOAD_CERTS, 0), "TS_CONF_load_certs"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_CONF_LOAD_KEY, 0), "TS_CONF_load_key"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_CONF_LOOKUP_FAIL, 0), "ts_CONF_lookup_fail"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_CONF_SET_DEFAULT_ENGINE, 0), + "TS_CONF_set_default_engine"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_GET_STATUS_TEXT, 0), "ts_get_status_text"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_MSG_IMPRINT_SET_ALGO, 0), + "TS_MSG_IMPRINT_set_algo"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_REQ_SET_MSG_IMPRINT, 0), + "TS_REQ_set_msg_imprint"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_REQ_SET_NONCE, 0), "TS_REQ_set_nonce"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_REQ_SET_POLICY_ID, 0), + "TS_REQ_set_policy_id"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_CREATE_RESPONSE, 0), + "TS_RESP_create_response"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_CREATE_TST_INFO, 0), + "ts_RESP_create_tst_info"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_CTX_ADD_FAILURE_INFO, 0), + "TS_RESP_CTX_add_failure_info"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_CTX_ADD_MD, 0), "TS_RESP_CTX_add_md"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_CTX_ADD_POLICY, 0), + "TS_RESP_CTX_add_policy"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_CTX_NEW, 0), "TS_RESP_CTX_new"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_CTX_SET_ACCURACY, 0), + "TS_RESP_CTX_set_accuracy"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_CTX_SET_CERTS, 0), + "TS_RESP_CTX_set_certs"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_CTX_SET_DEF_POLICY, 0), + "TS_RESP_CTX_set_def_policy"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_CTX_SET_SIGNER_CERT, 0), + "TS_RESP_CTX_set_signer_cert"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_CTX_SET_STATUS_INFO, 0), + "TS_RESP_CTX_set_status_info"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_GET_POLICY, 0), "ts_RESP_get_policy"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_SET_GENTIME_WITH_PRECISION, 0), + "TS_RESP_set_genTime_with_precision"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_SET_STATUS_INFO, 0), + "TS_RESP_set_status_info"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_SET_TST_INFO, 0), + "TS_RESP_set_tst_info"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_SIGN, 0), "ts_RESP_sign"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_RESP_VERIFY_SIGNATURE, 0), + "TS_RESP_verify_signature"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_TST_INFO_SET_ACCURACY, 0), + "TS_TST_INFO_set_accuracy"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_TST_INFO_SET_MSG_IMPRINT, 0), + "TS_TST_INFO_set_msg_imprint"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_TST_INFO_SET_NONCE, 0), + "TS_TST_INFO_set_nonce"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_TST_INFO_SET_POLICY_ID, 0), + "TS_TST_INFO_set_policy_id"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_TST_INFO_SET_SERIAL, 0), + "TS_TST_INFO_set_serial"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_TST_INFO_SET_TIME, 0), + "TS_TST_INFO_set_time"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_TST_INFO_SET_TSA, 0), "TS_TST_INFO_set_tsa"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_VERIFY, 0), ""}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_VERIFY_CERT, 0), "ts_verify_cert"}, + {ERR_PACK(ERR_LIB_TS, TS_F_TS_VERIFY_CTX_NEW, 0), "TS_VERIFY_CTX_new"}, + {0, NULL} +}; + +static const ERR_STRING_DATA TS_str_reasons[] = { + {ERR_PACK(ERR_LIB_TS, 0, TS_R_BAD_PKCS7_TYPE), "bad pkcs7 type"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_BAD_TYPE), "bad type"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_CANNOT_LOAD_CERT), "cannot load certificate"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_CANNOT_LOAD_KEY), "cannot load private key"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_CERTIFICATE_VERIFY_ERROR), + "certificate verify error"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_COULD_NOT_SET_ENGINE), + "could not set engine"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_COULD_NOT_SET_TIME), "could not set time"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_DETACHED_CONTENT), "detached content"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_ESS_ADD_SIGNING_CERT_ERROR), + "ess add signing cert error"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_ESS_ADD_SIGNING_CERT_V2_ERROR), + "ess add signing cert v2 error"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_ESS_SIGNING_CERTIFICATE_ERROR), + "ess signing certificate error"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_INVALID_NULL_POINTER), + "invalid null pointer"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_INVALID_SIGNER_CERTIFICATE_PURPOSE), + "invalid signer certificate purpose"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_MESSAGE_IMPRINT_MISMATCH), + "message imprint mismatch"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_NONCE_MISMATCH), "nonce mismatch"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_NONCE_NOT_RETURNED), "nonce not returned"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_NO_CONTENT), "no content"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_NO_TIME_STAMP_TOKEN), "no time stamp token"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_PKCS7_ADD_SIGNATURE_ERROR), + "pkcs7 add signature error"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_PKCS7_ADD_SIGNED_ATTR_ERROR), + "pkcs7 add signed attr error"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_PKCS7_TO_TS_TST_INFO_FAILED), + "pkcs7 to ts tst info failed"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_POLICY_MISMATCH), "policy mismatch"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE), + "private key does not match certificate"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_RESPONSE_SETUP_ERROR), + "response setup error"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_SIGNATURE_FAILURE), "signature failure"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_THERE_MUST_BE_ONE_SIGNER), + "there must be one signer"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_TIME_SYSCALL_ERROR), "time syscall error"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_TOKEN_NOT_PRESENT), "token not present"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_TOKEN_PRESENT), "token present"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_TSA_NAME_MISMATCH), "tsa name mismatch"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_TSA_UNTRUSTED), "tsa untrusted"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_TST_INFO_SETUP_ERROR), + "tst info setup error"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_TS_DATASIGN), "ts datasign"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_UNACCEPTABLE_POLICY), "unacceptable policy"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_UNSUPPORTED_MD_ALGORITHM), + "unsupported md algorithm"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_UNSUPPORTED_VERSION), "unsupported version"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_VAR_BAD_VALUE), "var bad value"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_VAR_LOOKUP_FAILURE), + "cannot find config variable"}, + {ERR_PACK(ERR_LIB_TS, 0, TS_R_WRONG_CONTENT_TYPE), "wrong content type"}, + {0, NULL} +}; + +#endif + +int ERR_load_TS_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(TS_str_functs[0].error) == NULL) { + ERR_load_strings_const(TS_str_functs); + ERR_load_strings_const(TS_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_lcl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_lcl.h new file mode 100644 index 000000000..771784fef --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_lcl.h @@ -0,0 +1,211 @@ +/* + * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * MessageImprint ::= SEQUENCE { + * hashAlgorithm AlgorithmIdentifier, + * hashedMessage OCTET STRING } + */ +struct TS_msg_imprint_st { + X509_ALGOR *hash_algo; + ASN1_OCTET_STRING *hashed_msg; +}; + +/*- + * TimeStampResp ::= SEQUENCE { + * status PKIStatusInfo, + * timeStampToken TimeStampToken OPTIONAL } + */ +struct TS_resp_st { + TS_STATUS_INFO *status_info; + PKCS7 *token; + TS_TST_INFO *tst_info; +}; + +/*- + * TimeStampReq ::= SEQUENCE { + * version INTEGER { v1(1) }, + * messageImprint MessageImprint, + * --a hash algorithm OID and the hash value of the data to be + * --time-stamped + * reqPolicy TSAPolicyId OPTIONAL, + * nonce INTEGER OPTIONAL, + * certReq BOOLEAN DEFAULT FALSE, + * extensions [0] IMPLICIT Extensions OPTIONAL } + */ +struct TS_req_st { + ASN1_INTEGER *version; + TS_MSG_IMPRINT *msg_imprint; + ASN1_OBJECT *policy_id; + ASN1_INTEGER *nonce; + ASN1_BOOLEAN cert_req; + STACK_OF(X509_EXTENSION) *extensions; +}; + +/*- + * Accuracy ::= SEQUENCE { + * seconds INTEGER OPTIONAL, + * millis [0] INTEGER (1..999) OPTIONAL, + * micros [1] INTEGER (1..999) OPTIONAL } + */ +struct TS_accuracy_st { + ASN1_INTEGER *seconds; + ASN1_INTEGER *millis; + ASN1_INTEGER *micros; +}; + +/*- + * TSTInfo ::= SEQUENCE { + * version INTEGER { v1(1) }, + * policy TSAPolicyId, + * messageImprint MessageImprint, + * -- MUST have the same value as the similar field in + * -- TimeStampReq + * serialNumber INTEGER, + * -- Time-Stamping users MUST be ready to accommodate integers + * -- up to 160 bits. + * genTime GeneralizedTime, + * accuracy Accuracy OPTIONAL, + * ordering BOOLEAN DEFAULT FALSE, + * nonce INTEGER OPTIONAL, + * -- MUST be present if the similar field was present + * -- in TimeStampReq. In that case it MUST have the same value. + * tsa [0] GeneralName OPTIONAL, + * extensions [1] IMPLICIT Extensions OPTIONAL } + */ +struct TS_tst_info_st { + ASN1_INTEGER *version; + ASN1_OBJECT *policy_id; + TS_MSG_IMPRINT *msg_imprint; + ASN1_INTEGER *serial; + ASN1_GENERALIZEDTIME *time; + TS_ACCURACY *accuracy; + ASN1_BOOLEAN ordering; + ASN1_INTEGER *nonce; + GENERAL_NAME *tsa; + STACK_OF(X509_EXTENSION) *extensions; +}; + +struct TS_status_info_st { + ASN1_INTEGER *status; + STACK_OF(ASN1_UTF8STRING) *text; + ASN1_BIT_STRING *failure_info; +}; + +/*- + * IssuerSerial ::= SEQUENCE { + * issuer GeneralNames, + * serialNumber CertificateSerialNumber + * } + */ +struct ESS_issuer_serial { + STACK_OF(GENERAL_NAME) *issuer; + ASN1_INTEGER *serial; +}; + +/*- + * ESSCertID ::= SEQUENCE { + * certHash Hash, + * issuerSerial IssuerSerial OPTIONAL + * } + */ +struct ESS_cert_id { + ASN1_OCTET_STRING *hash; /* Always SHA-1 digest. */ + ESS_ISSUER_SERIAL *issuer_serial; +}; + +/*- + * SigningCertificate ::= SEQUENCE { + * certs SEQUENCE OF ESSCertID, + * policies SEQUENCE OF PolicyInformation OPTIONAL + * } + */ +struct ESS_signing_cert { + STACK_OF(ESS_CERT_ID) *cert_ids; + STACK_OF(POLICYINFO) *policy_info; +}; + +/*- + * ESSCertIDv2 ::= SEQUENCE { + * hashAlgorithm AlgorithmIdentifier + * DEFAULT {algorithm id-sha256}, + * certHash Hash, + * issuerSerial IssuerSerial OPTIONAL + * } + */ + +struct ESS_cert_id_v2_st { + X509_ALGOR *hash_alg; /* Default: SHA-256 */ + ASN1_OCTET_STRING *hash; + ESS_ISSUER_SERIAL *issuer_serial; +}; + +/*- + * SigningCertificateV2 ::= SEQUENCE { + * certs SEQUENCE OF ESSCertIDv2, + * policies SEQUENCE OF PolicyInformation OPTIONAL + * } + */ + +struct ESS_signing_cert_v2_st { + STACK_OF(ESS_CERT_ID_V2) *cert_ids; + STACK_OF(POLICYINFO) *policy_info; +}; + + +struct TS_resp_ctx { + X509 *signer_cert; + EVP_PKEY *signer_key; + const EVP_MD *signer_md; + const EVP_MD *ess_cert_id_digest; + STACK_OF(X509) *certs; /* Certs to include in signed data. */ + STACK_OF(ASN1_OBJECT) *policies; /* Acceptable policies. */ + ASN1_OBJECT *default_policy; /* It may appear in policies, too. */ + STACK_OF(EVP_MD) *mds; /* Acceptable message digests. */ + ASN1_INTEGER *seconds; /* accuracy, 0 means not specified. */ + ASN1_INTEGER *millis; /* accuracy, 0 means not specified. */ + ASN1_INTEGER *micros; /* accuracy, 0 means not specified. */ + unsigned clock_precision_digits; /* fraction of seconds in time stamp + * token. */ + unsigned flags; /* Optional info, see values above. */ + /* Callback functions. */ + TS_serial_cb serial_cb; + void *serial_cb_data; /* User data for serial_cb. */ + TS_time_cb time_cb; + void *time_cb_data; /* User data for time_cb. */ + TS_extension_cb extension_cb; + void *extension_cb_data; /* User data for extension_cb. */ + /* These members are used only while creating the response. */ + TS_REQ *request; + TS_RESP *response; + TS_TST_INFO *tst_info; +}; + +struct TS_verify_ctx { + /* Set this to the union of TS_VFY_... flags you want to carry out. */ + unsigned flags; + /* Must be set only with TS_VFY_SIGNATURE. certs is optional. */ + X509_STORE *store; + STACK_OF(X509) *certs; + /* Must be set only with TS_VFY_POLICY. */ + ASN1_OBJECT *policy; + /* + * Must be set only with TS_VFY_IMPRINT. If md_alg is NULL, the + * algorithm from the response is used. + */ + X509_ALGOR *md_alg; + unsigned char *imprint; + unsigned imprint_len; + /* Must be set only with TS_VFY_DATA. */ + BIO *data; + /* Must be set only with TS_VFY_TSA_NAME. */ + ASN1_INTEGER *nonce; + /* Must be set only with TS_VFY_TSA_NAME. */ + GENERAL_NAME *tsa_name; +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_lib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_lib.c new file mode 100644 index 000000000..ce2e12c59 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_lib.c @@ -0,0 +1,92 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include "ts_lcl.h" + +int TS_ASN1_INTEGER_print_bio(BIO *bio, const ASN1_INTEGER *num) +{ + BIGNUM *num_bn; + int result = 0; + char *hex; + + num_bn = ASN1_INTEGER_to_BN(num, NULL); + if (num_bn == NULL) + return -1; + if ((hex = BN_bn2hex(num_bn))) { + result = BIO_write(bio, "0x", 2) > 0; + result = result && BIO_write(bio, hex, strlen(hex)) > 0; + OPENSSL_free(hex); + } + BN_free(num_bn); + + return result; +} + +int TS_OBJ_print_bio(BIO *bio, const ASN1_OBJECT *obj) +{ + char obj_txt[128]; + + OBJ_obj2txt(obj_txt, sizeof(obj_txt), obj, 0); + BIO_printf(bio, "%s\n", obj_txt); + + return 1; +} + +int TS_ext_print_bio(BIO *bio, const STACK_OF(X509_EXTENSION) *extensions) +{ + int i, critical, n; + X509_EXTENSION *ex; + ASN1_OBJECT *obj; + + BIO_printf(bio, "Extensions:\n"); + n = X509v3_get_ext_count(extensions); + for (i = 0; i < n; i++) { + ex = X509v3_get_ext(extensions, i); + obj = X509_EXTENSION_get_object(ex); + if (i2a_ASN1_OBJECT(bio, obj) < 0) + return 0; + critical = X509_EXTENSION_get_critical(ex); + BIO_printf(bio, ":%s\n", critical ? " critical" : ""); + if (!X509V3_EXT_print(bio, ex, 0, 4)) { + BIO_printf(bio, "%4s", ""); + ASN1_STRING_print(bio, X509_EXTENSION_get_data(ex)); + } + BIO_write(bio, "\n", 1); + } + + return 1; +} + +int TS_X509_ALGOR_print_bio(BIO *bio, const X509_ALGOR *alg) +{ + int i = OBJ_obj2nid(alg->algorithm); + return BIO_printf(bio, "Hash Algorithm: %s\n", + (i == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(i)); +} + +int TS_MSG_IMPRINT_print_bio(BIO *bio, TS_MSG_IMPRINT *a) +{ + ASN1_OCTET_STRING *msg; + + TS_X509_ALGOR_print_bio(bio, a->hash_algo); + + BIO_printf(bio, "Message data:\n"); + msg = a->hashed_msg; + BIO_dump_indent(bio, (const char *)ASN1_STRING_get0_data(msg), + ASN1_STRING_length(msg), 4); + + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_req_print.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_req_print.c new file mode 100644 index 000000000..0dedf47d9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_req_print.c @@ -0,0 +1,51 @@ +/* + * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "ts_lcl.h" + +int TS_REQ_print_bio(BIO *bio, TS_REQ *a) +{ + int v; + ASN1_OBJECT *policy_id; + + if (a == NULL) + return 0; + + v = TS_REQ_get_version(a); + BIO_printf(bio, "Version: %d\n", v); + + TS_MSG_IMPRINT_print_bio(bio, a->msg_imprint); + + BIO_printf(bio, "Policy OID: "); + policy_id = TS_REQ_get_policy_id(a); + if (policy_id == NULL) + BIO_printf(bio, "unspecified\n"); + else + TS_OBJ_print_bio(bio, policy_id); + + BIO_printf(bio, "Nonce: "); + if (a->nonce == NULL) + BIO_printf(bio, "unspecified"); + else + TS_ASN1_INTEGER_print_bio(bio, a->nonce); + BIO_write(bio, "\n", 1); + + BIO_printf(bio, "Certificate required: %s\n", + a->cert_req ? "yes" : "no"); + + TS_ext_print_bio(bio, a->extensions); + + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_req_utils.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_req_utils.c new file mode 100644 index 000000000..2073d3395 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_req_utils.c @@ -0,0 +1,183 @@ +/* + * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include "ts_lcl.h" + +int TS_REQ_set_version(TS_REQ *a, long version) +{ + return ASN1_INTEGER_set(a->version, version); +} + +long TS_REQ_get_version(const TS_REQ *a) +{ + return ASN1_INTEGER_get(a->version); +} + +int TS_REQ_set_msg_imprint(TS_REQ *a, TS_MSG_IMPRINT *msg_imprint) +{ + TS_MSG_IMPRINT *new_msg_imprint; + + if (a->msg_imprint == msg_imprint) + return 1; + new_msg_imprint = TS_MSG_IMPRINT_dup(msg_imprint); + if (new_msg_imprint == NULL) { + TSerr(TS_F_TS_REQ_SET_MSG_IMPRINT, ERR_R_MALLOC_FAILURE); + return 0; + } + TS_MSG_IMPRINT_free(a->msg_imprint); + a->msg_imprint = new_msg_imprint; + return 1; +} + +TS_MSG_IMPRINT *TS_REQ_get_msg_imprint(TS_REQ *a) +{ + return a->msg_imprint; +} + +int TS_MSG_IMPRINT_set_algo(TS_MSG_IMPRINT *a, X509_ALGOR *alg) +{ + X509_ALGOR *new_alg; + + if (a->hash_algo == alg) + return 1; + new_alg = X509_ALGOR_dup(alg); + if (new_alg == NULL) { + TSerr(TS_F_TS_MSG_IMPRINT_SET_ALGO, ERR_R_MALLOC_FAILURE); + return 0; + } + X509_ALGOR_free(a->hash_algo); + a->hash_algo = new_alg; + return 1; +} + +X509_ALGOR *TS_MSG_IMPRINT_get_algo(TS_MSG_IMPRINT *a) +{ + return a->hash_algo; +} + +int TS_MSG_IMPRINT_set_msg(TS_MSG_IMPRINT *a, unsigned char *d, int len) +{ + return ASN1_OCTET_STRING_set(a->hashed_msg, d, len); +} + +ASN1_OCTET_STRING *TS_MSG_IMPRINT_get_msg(TS_MSG_IMPRINT *a) +{ + return a->hashed_msg; +} + +int TS_REQ_set_policy_id(TS_REQ *a, const ASN1_OBJECT *policy) +{ + ASN1_OBJECT *new_policy; + + if (a->policy_id == policy) + return 1; + new_policy = OBJ_dup(policy); + if (new_policy == NULL) { + TSerr(TS_F_TS_REQ_SET_POLICY_ID, ERR_R_MALLOC_FAILURE); + return 0; + } + ASN1_OBJECT_free(a->policy_id); + a->policy_id = new_policy; + return 1; +} + +ASN1_OBJECT *TS_REQ_get_policy_id(TS_REQ *a) +{ + return a->policy_id; +} + +int TS_REQ_set_nonce(TS_REQ *a, const ASN1_INTEGER *nonce) +{ + ASN1_INTEGER *new_nonce; + + if (a->nonce == nonce) + return 1; + new_nonce = ASN1_INTEGER_dup(nonce); + if (new_nonce == NULL) { + TSerr(TS_F_TS_REQ_SET_NONCE, ERR_R_MALLOC_FAILURE); + return 0; + } + ASN1_INTEGER_free(a->nonce); + a->nonce = new_nonce; + return 1; +} + +const ASN1_INTEGER *TS_REQ_get_nonce(const TS_REQ *a) +{ + return a->nonce; +} + +int TS_REQ_set_cert_req(TS_REQ *a, int cert_req) +{ + a->cert_req = cert_req ? 0xFF : 0x00; + return 1; +} + +int TS_REQ_get_cert_req(const TS_REQ *a) +{ + return a->cert_req ? 1 : 0; +} + +STACK_OF(X509_EXTENSION) *TS_REQ_get_exts(TS_REQ *a) +{ + return a->extensions; +} + +void TS_REQ_ext_free(TS_REQ *a) +{ + if (!a) + return; + sk_X509_EXTENSION_pop_free(a->extensions, X509_EXTENSION_free); + a->extensions = NULL; +} + +int TS_REQ_get_ext_count(TS_REQ *a) +{ + return X509v3_get_ext_count(a->extensions); +} + +int TS_REQ_get_ext_by_NID(TS_REQ *a, int nid, int lastpos) +{ + return X509v3_get_ext_by_NID(a->extensions, nid, lastpos); +} + +int TS_REQ_get_ext_by_OBJ(TS_REQ *a, const ASN1_OBJECT *obj, int lastpos) +{ + return X509v3_get_ext_by_OBJ(a->extensions, obj, lastpos); +} + +int TS_REQ_get_ext_by_critical(TS_REQ *a, int crit, int lastpos) +{ + return X509v3_get_ext_by_critical(a->extensions, crit, lastpos); +} + +X509_EXTENSION *TS_REQ_get_ext(TS_REQ *a, int loc) +{ + return X509v3_get_ext(a->extensions, loc); +} + +X509_EXTENSION *TS_REQ_delete_ext(TS_REQ *a, int loc) +{ + return X509v3_delete_ext(a->extensions, loc); +} + +int TS_REQ_add_ext(TS_REQ *a, X509_EXTENSION *ex, int loc) +{ + return X509v3_add_ext(&a->extensions, ex, loc) != NULL; +} + +void *TS_REQ_get_ext_d2i(TS_REQ *a, int nid, int *crit, int *idx) +{ + return X509V3_get_d2i(a->extensions, nid, crit, idx); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_rsp_print.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_rsp_print.c new file mode 100644 index 000000000..6eb0ec8d7 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_rsp_print.c @@ -0,0 +1,195 @@ +/* + * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "ts_lcl.h" + +struct status_map_st { + int bit; + const char *text; +}; + +static int ts_status_map_print(BIO *bio, const struct status_map_st *a, + const ASN1_BIT_STRING *v); +static int ts_ACCURACY_print_bio(BIO *bio, const TS_ACCURACY *accuracy); + + +int TS_RESP_print_bio(BIO *bio, TS_RESP *a) +{ + BIO_printf(bio, "Status info:\n"); + TS_STATUS_INFO_print_bio(bio, a->status_info); + + BIO_printf(bio, "\nTST info:\n"); + if (a->tst_info != NULL) + TS_TST_INFO_print_bio(bio, a->tst_info); + else + BIO_printf(bio, "Not included.\n"); + + return 1; +} + +int TS_STATUS_INFO_print_bio(BIO *bio, TS_STATUS_INFO *a) +{ + static const char *status_map[] = { + "Granted.", + "Granted with modifications.", + "Rejected.", + "Waiting.", + "Revocation warning.", + "Revoked." + }; + static const struct status_map_st failure_map[] = { + {TS_INFO_BAD_ALG, + "unrecognized or unsupported algorithm identifier"}, + {TS_INFO_BAD_REQUEST, + "transaction not permitted or supported"}, + {TS_INFO_BAD_DATA_FORMAT, + "the data submitted has the wrong format"}, + {TS_INFO_TIME_NOT_AVAILABLE, + "the TSA's time source is not available"}, + {TS_INFO_UNACCEPTED_POLICY, + "the requested TSA policy is not supported by the TSA"}, + {TS_INFO_UNACCEPTED_EXTENSION, + "the requested extension is not supported by the TSA"}, + {TS_INFO_ADD_INFO_NOT_AVAILABLE, + "the additional information requested could not be understood " + "or is not available"}, + {TS_INFO_SYSTEM_FAILURE, + "the request cannot be handled due to system failure"}, + {-1, NULL} + }; + long status; + int i, lines = 0; + + BIO_printf(bio, "Status: "); + status = ASN1_INTEGER_get(a->status); + if (0 <= status && status < (long)OSSL_NELEM(status_map)) + BIO_printf(bio, "%s\n", status_map[status]); + else + BIO_printf(bio, "out of bounds\n"); + + BIO_printf(bio, "Status description: "); + for (i = 0; i < sk_ASN1_UTF8STRING_num(a->text); ++i) { + if (i > 0) + BIO_puts(bio, "\t"); + ASN1_STRING_print_ex(bio, sk_ASN1_UTF8STRING_value(a->text, i), 0); + BIO_puts(bio, "\n"); + } + if (i == 0) + BIO_printf(bio, "unspecified\n"); + + BIO_printf(bio, "Failure info: "); + if (a->failure_info != NULL) + lines = ts_status_map_print(bio, failure_map, a->failure_info); + if (lines == 0) + BIO_printf(bio, "unspecified"); + BIO_printf(bio, "\n"); + + return 1; +} + +static int ts_status_map_print(BIO *bio, const struct status_map_st *a, + const ASN1_BIT_STRING *v) +{ + int lines = 0; + + for (; a->bit >= 0; ++a) { + if (ASN1_BIT_STRING_get_bit(v, a->bit)) { + if (++lines > 1) + BIO_printf(bio, ", "); + BIO_printf(bio, "%s", a->text); + } + } + + return lines; +} + +int TS_TST_INFO_print_bio(BIO *bio, TS_TST_INFO *a) +{ + int v; + + if (a == NULL) + return 0; + + v = ASN1_INTEGER_get(a->version); + BIO_printf(bio, "Version: %d\n", v); + + BIO_printf(bio, "Policy OID: "); + TS_OBJ_print_bio(bio, a->policy_id); + + TS_MSG_IMPRINT_print_bio(bio, a->msg_imprint); + + BIO_printf(bio, "Serial number: "); + if (a->serial == NULL) + BIO_printf(bio, "unspecified"); + else + TS_ASN1_INTEGER_print_bio(bio, a->serial); + BIO_write(bio, "\n", 1); + + BIO_printf(bio, "Time stamp: "); + ASN1_GENERALIZEDTIME_print(bio, a->time); + BIO_write(bio, "\n", 1); + + BIO_printf(bio, "Accuracy: "); + if (a->accuracy == NULL) + BIO_printf(bio, "unspecified"); + else + ts_ACCURACY_print_bio(bio, a->accuracy); + BIO_write(bio, "\n", 1); + + BIO_printf(bio, "Ordering: %s\n", a->ordering ? "yes" : "no"); + + BIO_printf(bio, "Nonce: "); + if (a->nonce == NULL) + BIO_printf(bio, "unspecified"); + else + TS_ASN1_INTEGER_print_bio(bio, a->nonce); + BIO_write(bio, "\n", 1); + + BIO_printf(bio, "TSA: "); + if (a->tsa == NULL) + BIO_printf(bio, "unspecified"); + else { + STACK_OF(CONF_VALUE) *nval; + if ((nval = i2v_GENERAL_NAME(NULL, a->tsa, NULL))) + X509V3_EXT_val_prn(bio, nval, 0, 0); + sk_CONF_VALUE_pop_free(nval, X509V3_conf_free); + } + BIO_write(bio, "\n", 1); + + TS_ext_print_bio(bio, a->extensions); + + return 1; +} + +static int ts_ACCURACY_print_bio(BIO *bio, const TS_ACCURACY *a) +{ + if (a->seconds != NULL) + TS_ASN1_INTEGER_print_bio(bio, a->seconds); + else + BIO_printf(bio, "unspecified"); + BIO_printf(bio, " seconds, "); + if (a->millis != NULL) + TS_ASN1_INTEGER_print_bio(bio, a->millis); + else + BIO_printf(bio, "unspecified"); + BIO_printf(bio, " millis, "); + if (a->micros != NULL) + TS_ASN1_INTEGER_print_bio(bio, a->micros); + else + BIO_printf(bio, "unspecified"); + BIO_printf(bio, " micros"); + + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_rsp_sign.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_rsp_sign.c new file mode 100644 index 000000000..1b2b84ef6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_rsp_sign.c @@ -0,0 +1,1057 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "e_os.h" +#include "internal/cryptlib.h" + +#include +#include +#include +#include +#include "ts_lcl.h" + +static ASN1_INTEGER *def_serial_cb(struct TS_resp_ctx *, void *); +static int def_time_cb(struct TS_resp_ctx *, void *, long *sec, long *usec); +static int def_extension_cb(struct TS_resp_ctx *, X509_EXTENSION *, void *); + +static void ts_RESP_CTX_init(TS_RESP_CTX *ctx); +static void ts_RESP_CTX_cleanup(TS_RESP_CTX *ctx); +static int ts_RESP_check_request(TS_RESP_CTX *ctx); +static ASN1_OBJECT *ts_RESP_get_policy(TS_RESP_CTX *ctx); +static TS_TST_INFO *ts_RESP_create_tst_info(TS_RESP_CTX *ctx, + ASN1_OBJECT *policy); +static int ts_RESP_process_extensions(TS_RESP_CTX *ctx); +static int ts_RESP_sign(TS_RESP_CTX *ctx); + +static ESS_SIGNING_CERT *ess_SIGNING_CERT_new_init(X509 *signcert, + STACK_OF(X509) *certs); +static ESS_CERT_ID *ess_CERT_ID_new_init(X509 *cert, int issuer_needed); +static int ts_TST_INFO_content_new(PKCS7 *p7); +static int ess_add_signing_cert(PKCS7_SIGNER_INFO *si, ESS_SIGNING_CERT *sc); + +static ESS_SIGNING_CERT_V2 *ess_signing_cert_v2_new_init(const EVP_MD *hash_alg, + X509 *signcert, + STACK_OF(X509) + *certs); +static ESS_CERT_ID_V2 *ess_cert_id_v2_new_init(const EVP_MD *hash_alg, + X509 *cert, int issuer_needed); +static int ess_add_signing_cert_v2(PKCS7_SIGNER_INFO *si, + ESS_SIGNING_CERT_V2 *sc); + +static ASN1_GENERALIZEDTIME +*TS_RESP_set_genTime_with_precision(ASN1_GENERALIZEDTIME *, long, long, + unsigned); + +/* Default callback for response generation. */ +static ASN1_INTEGER *def_serial_cb(struct TS_resp_ctx *ctx, void *data) +{ + ASN1_INTEGER *serial = ASN1_INTEGER_new(); + + if (serial == NULL) + goto err; + if (!ASN1_INTEGER_set(serial, 1)) + goto err; + return serial; + + err: + TSerr(TS_F_DEF_SERIAL_CB, ERR_R_MALLOC_FAILURE); + TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION, + "Error during serial number generation."); + return NULL; +} + +#if defined(OPENSSL_SYS_UNIX) + +static int def_time_cb(struct TS_resp_ctx *ctx, void *data, + long *sec, long *usec) +{ + struct timeval tv; + if (gettimeofday(&tv, NULL) != 0) { + TSerr(TS_F_DEF_TIME_CB, TS_R_TIME_SYSCALL_ERROR); + TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION, + "Time is not available."); + TS_RESP_CTX_add_failure_info(ctx, TS_INFO_TIME_NOT_AVAILABLE); + return 0; + } + *sec = tv.tv_sec; + *usec = tv.tv_usec; + + return 1; +} + +#else + +static int def_time_cb(struct TS_resp_ctx *ctx, void *data, + long *sec, long *usec) +{ + time_t t; + if (time(&t) == (time_t)-1) { + TSerr(TS_F_DEF_TIME_CB, TS_R_TIME_SYSCALL_ERROR); + TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION, + "Time is not available."); + TS_RESP_CTX_add_failure_info(ctx, TS_INFO_TIME_NOT_AVAILABLE); + return 0; + } + *sec = (long)t; + *usec = 0; + + return 1; +} + +#endif + +static int def_extension_cb(struct TS_resp_ctx *ctx, X509_EXTENSION *ext, + void *data) +{ + TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION, + "Unsupported extension."); + TS_RESP_CTX_add_failure_info(ctx, TS_INFO_UNACCEPTED_EXTENSION); + return 0; +} + +/* TS_RESP_CTX management functions. */ + +TS_RESP_CTX *TS_RESP_CTX_new(void) +{ + TS_RESP_CTX *ctx; + + if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) { + TSerr(TS_F_TS_RESP_CTX_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + ctx->signer_md = EVP_sha256(); + + ctx->serial_cb = def_serial_cb; + ctx->time_cb = def_time_cb; + ctx->extension_cb = def_extension_cb; + + return ctx; +} + +void TS_RESP_CTX_free(TS_RESP_CTX *ctx) +{ + if (!ctx) + return; + + X509_free(ctx->signer_cert); + EVP_PKEY_free(ctx->signer_key); + sk_X509_pop_free(ctx->certs, X509_free); + sk_ASN1_OBJECT_pop_free(ctx->policies, ASN1_OBJECT_free); + ASN1_OBJECT_free(ctx->default_policy); + sk_EVP_MD_free(ctx->mds); /* No EVP_MD_free method exists. */ + ASN1_INTEGER_free(ctx->seconds); + ASN1_INTEGER_free(ctx->millis); + ASN1_INTEGER_free(ctx->micros); + OPENSSL_free(ctx); +} + +int TS_RESP_CTX_set_signer_cert(TS_RESP_CTX *ctx, X509 *signer) +{ + if (X509_check_purpose(signer, X509_PURPOSE_TIMESTAMP_SIGN, 0) != 1) { + TSerr(TS_F_TS_RESP_CTX_SET_SIGNER_CERT, + TS_R_INVALID_SIGNER_CERTIFICATE_PURPOSE); + return 0; + } + X509_free(ctx->signer_cert); + ctx->signer_cert = signer; + X509_up_ref(ctx->signer_cert); + return 1; +} + +int TS_RESP_CTX_set_signer_key(TS_RESP_CTX *ctx, EVP_PKEY *key) +{ + EVP_PKEY_free(ctx->signer_key); + ctx->signer_key = key; + EVP_PKEY_up_ref(ctx->signer_key); + + return 1; +} + +int TS_RESP_CTX_set_signer_digest(TS_RESP_CTX *ctx, const EVP_MD *md) +{ + ctx->signer_md = md; + return 1; +} + +int TS_RESP_CTX_set_def_policy(TS_RESP_CTX *ctx, const ASN1_OBJECT *def_policy) +{ + ASN1_OBJECT_free(ctx->default_policy); + if ((ctx->default_policy = OBJ_dup(def_policy)) == NULL) + goto err; + return 1; + err: + TSerr(TS_F_TS_RESP_CTX_SET_DEF_POLICY, ERR_R_MALLOC_FAILURE); + return 0; +} + +int TS_RESP_CTX_set_certs(TS_RESP_CTX *ctx, STACK_OF(X509) *certs) +{ + + sk_X509_pop_free(ctx->certs, X509_free); + ctx->certs = NULL; + if (!certs) + return 1; + if ((ctx->certs = X509_chain_up_ref(certs)) == NULL) { + TSerr(TS_F_TS_RESP_CTX_SET_CERTS, ERR_R_MALLOC_FAILURE); + return 0; + } + + return 1; +} + +int TS_RESP_CTX_add_policy(TS_RESP_CTX *ctx, const ASN1_OBJECT *policy) +{ + ASN1_OBJECT *copy = NULL; + + if (ctx->policies == NULL + && (ctx->policies = sk_ASN1_OBJECT_new_null()) == NULL) + goto err; + if ((copy = OBJ_dup(policy)) == NULL) + goto err; + if (!sk_ASN1_OBJECT_push(ctx->policies, copy)) + goto err; + + return 1; + err: + TSerr(TS_F_TS_RESP_CTX_ADD_POLICY, ERR_R_MALLOC_FAILURE); + ASN1_OBJECT_free(copy); + return 0; +} + +int TS_RESP_CTX_add_md(TS_RESP_CTX *ctx, const EVP_MD *md) +{ + if (ctx->mds == NULL + && (ctx->mds = sk_EVP_MD_new_null()) == NULL) + goto err; + if (!sk_EVP_MD_push(ctx->mds, md)) + goto err; + + return 1; + err: + TSerr(TS_F_TS_RESP_CTX_ADD_MD, ERR_R_MALLOC_FAILURE); + return 0; +} + +#define TS_RESP_CTX_accuracy_free(ctx) \ + ASN1_INTEGER_free(ctx->seconds); \ + ctx->seconds = NULL; \ + ASN1_INTEGER_free(ctx->millis); \ + ctx->millis = NULL; \ + ASN1_INTEGER_free(ctx->micros); \ + ctx->micros = NULL; + +int TS_RESP_CTX_set_accuracy(TS_RESP_CTX *ctx, + int secs, int millis, int micros) +{ + + TS_RESP_CTX_accuracy_free(ctx); + if (secs + && ((ctx->seconds = ASN1_INTEGER_new()) == NULL + || !ASN1_INTEGER_set(ctx->seconds, secs))) + goto err; + if (millis + && ((ctx->millis = ASN1_INTEGER_new()) == NULL + || !ASN1_INTEGER_set(ctx->millis, millis))) + goto err; + if (micros + && ((ctx->micros = ASN1_INTEGER_new()) == NULL + || !ASN1_INTEGER_set(ctx->micros, micros))) + goto err; + + return 1; + err: + TS_RESP_CTX_accuracy_free(ctx); + TSerr(TS_F_TS_RESP_CTX_SET_ACCURACY, ERR_R_MALLOC_FAILURE); + return 0; +} + +void TS_RESP_CTX_add_flags(TS_RESP_CTX *ctx, int flags) +{ + ctx->flags |= flags; +} + +void TS_RESP_CTX_set_serial_cb(TS_RESP_CTX *ctx, TS_serial_cb cb, void *data) +{ + ctx->serial_cb = cb; + ctx->serial_cb_data = data; +} + +void TS_RESP_CTX_set_time_cb(TS_RESP_CTX *ctx, TS_time_cb cb, void *data) +{ + ctx->time_cb = cb; + ctx->time_cb_data = data; +} + +void TS_RESP_CTX_set_extension_cb(TS_RESP_CTX *ctx, + TS_extension_cb cb, void *data) +{ + ctx->extension_cb = cb; + ctx->extension_cb_data = data; +} + +int TS_RESP_CTX_set_status_info(TS_RESP_CTX *ctx, + int status, const char *text) +{ + TS_STATUS_INFO *si = NULL; + ASN1_UTF8STRING *utf8_text = NULL; + int ret = 0; + + if ((si = TS_STATUS_INFO_new()) == NULL) + goto err; + if (!ASN1_INTEGER_set(si->status, status)) + goto err; + if (text) { + if ((utf8_text = ASN1_UTF8STRING_new()) == NULL + || !ASN1_STRING_set(utf8_text, text, strlen(text))) + goto err; + if (si->text == NULL + && (si->text = sk_ASN1_UTF8STRING_new_null()) == NULL) + goto err; + if (!sk_ASN1_UTF8STRING_push(si->text, utf8_text)) + goto err; + utf8_text = NULL; /* Ownership is lost. */ + } + if (!TS_RESP_set_status_info(ctx->response, si)) + goto err; + ret = 1; + err: + if (!ret) + TSerr(TS_F_TS_RESP_CTX_SET_STATUS_INFO, ERR_R_MALLOC_FAILURE); + TS_STATUS_INFO_free(si); + ASN1_UTF8STRING_free(utf8_text); + return ret; +} + +int TS_RESP_CTX_set_status_info_cond(TS_RESP_CTX *ctx, + int status, const char *text) +{ + int ret = 1; + TS_STATUS_INFO *si = ctx->response->status_info; + + if (ASN1_INTEGER_get(si->status) == TS_STATUS_GRANTED) { + ret = TS_RESP_CTX_set_status_info(ctx, status, text); + } + return ret; +} + +int TS_RESP_CTX_add_failure_info(TS_RESP_CTX *ctx, int failure) +{ + TS_STATUS_INFO *si = ctx->response->status_info; + if (si->failure_info == NULL + && (si->failure_info = ASN1_BIT_STRING_new()) == NULL) + goto err; + if (!ASN1_BIT_STRING_set_bit(si->failure_info, failure, 1)) + goto err; + return 1; + err: + TSerr(TS_F_TS_RESP_CTX_ADD_FAILURE_INFO, ERR_R_MALLOC_FAILURE); + return 0; +} + +TS_REQ *TS_RESP_CTX_get_request(TS_RESP_CTX *ctx) +{ + return ctx->request; +} + +TS_TST_INFO *TS_RESP_CTX_get_tst_info(TS_RESP_CTX *ctx) +{ + return ctx->tst_info; +} + +int TS_RESP_CTX_set_clock_precision_digits(TS_RESP_CTX *ctx, + unsigned precision) +{ + if (precision > TS_MAX_CLOCK_PRECISION_DIGITS) + return 0; + ctx->clock_precision_digits = precision; + return 1; +} + +/* Main entry method of the response generation. */ +TS_RESP *TS_RESP_create_response(TS_RESP_CTX *ctx, BIO *req_bio) +{ + ASN1_OBJECT *policy; + TS_RESP *response; + int result = 0; + + ts_RESP_CTX_init(ctx); + + if ((ctx->response = TS_RESP_new()) == NULL) { + TSerr(TS_F_TS_RESP_CREATE_RESPONSE, ERR_R_MALLOC_FAILURE); + goto end; + } + if ((ctx->request = d2i_TS_REQ_bio(req_bio, NULL)) == NULL) { + TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION, + "Bad request format or system error."); + TS_RESP_CTX_add_failure_info(ctx, TS_INFO_BAD_DATA_FORMAT); + goto end; + } + if (!TS_RESP_CTX_set_status_info(ctx, TS_STATUS_GRANTED, NULL)) + goto end; + if (!ts_RESP_check_request(ctx)) + goto end; + if ((policy = ts_RESP_get_policy(ctx)) == NULL) + goto end; + if ((ctx->tst_info = ts_RESP_create_tst_info(ctx, policy)) == NULL) + goto end; + if (!ts_RESP_process_extensions(ctx)) + goto end; + if (!ts_RESP_sign(ctx)) + goto end; + result = 1; + + end: + if (!result) { + TSerr(TS_F_TS_RESP_CREATE_RESPONSE, TS_R_RESPONSE_SETUP_ERROR); + if (ctx->response != NULL) { + if (TS_RESP_CTX_set_status_info_cond(ctx, + TS_STATUS_REJECTION, + "Error during response " + "generation.") == 0) { + TS_RESP_free(ctx->response); + ctx->response = NULL; + } + } + } + response = ctx->response; + ctx->response = NULL; /* Ownership will be returned to caller. */ + ts_RESP_CTX_cleanup(ctx); + return response; +} + +/* Initializes the variable part of the context. */ +static void ts_RESP_CTX_init(TS_RESP_CTX *ctx) +{ + ctx->request = NULL; + ctx->response = NULL; + ctx->tst_info = NULL; +} + +/* Cleans up the variable part of the context. */ +static void ts_RESP_CTX_cleanup(TS_RESP_CTX *ctx) +{ + TS_REQ_free(ctx->request); + ctx->request = NULL; + TS_RESP_free(ctx->response); + ctx->response = NULL; + TS_TST_INFO_free(ctx->tst_info); + ctx->tst_info = NULL; +} + +/* Checks the format and content of the request. */ +static int ts_RESP_check_request(TS_RESP_CTX *ctx) +{ + TS_REQ *request = ctx->request; + TS_MSG_IMPRINT *msg_imprint; + X509_ALGOR *md_alg; + int md_alg_id; + const ASN1_OCTET_STRING *digest; + const EVP_MD *md = NULL; + int i; + + if (TS_REQ_get_version(request) != 1) { + TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION, + "Bad request version."); + TS_RESP_CTX_add_failure_info(ctx, TS_INFO_BAD_REQUEST); + return 0; + } + + msg_imprint = request->msg_imprint; + md_alg = msg_imprint->hash_algo; + md_alg_id = OBJ_obj2nid(md_alg->algorithm); + for (i = 0; !md && i < sk_EVP_MD_num(ctx->mds); ++i) { + const EVP_MD *current_md = sk_EVP_MD_value(ctx->mds, i); + if (md_alg_id == EVP_MD_type(current_md)) + md = current_md; + } + if (!md) { + TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION, + "Message digest algorithm is " + "not supported."); + TS_RESP_CTX_add_failure_info(ctx, TS_INFO_BAD_ALG); + return 0; + } + + if (md_alg->parameter && ASN1_TYPE_get(md_alg->parameter) != V_ASN1_NULL) { + TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION, + "Superfluous message digest " + "parameter."); + TS_RESP_CTX_add_failure_info(ctx, TS_INFO_BAD_ALG); + return 0; + } + digest = msg_imprint->hashed_msg; + if (digest->length != EVP_MD_size(md)) { + TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION, + "Bad message digest."); + TS_RESP_CTX_add_failure_info(ctx, TS_INFO_BAD_DATA_FORMAT); + return 0; + } + + return 1; +} + +/* Returns the TSA policy based on the requested and acceptable policies. */ +static ASN1_OBJECT *ts_RESP_get_policy(TS_RESP_CTX *ctx) +{ + ASN1_OBJECT *requested = ctx->request->policy_id; + ASN1_OBJECT *policy = NULL; + int i; + + if (ctx->default_policy == NULL) { + TSerr(TS_F_TS_RESP_GET_POLICY, TS_R_INVALID_NULL_POINTER); + return NULL; + } + if (!requested || !OBJ_cmp(requested, ctx->default_policy)) + policy = ctx->default_policy; + + /* Check if the policy is acceptable. */ + for (i = 0; !policy && i < sk_ASN1_OBJECT_num(ctx->policies); ++i) { + ASN1_OBJECT *current = sk_ASN1_OBJECT_value(ctx->policies, i); + if (!OBJ_cmp(requested, current)) + policy = current; + } + if (!policy) { + TSerr(TS_F_TS_RESP_GET_POLICY, TS_R_UNACCEPTABLE_POLICY); + TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION, + "Requested policy is not " "supported."); + TS_RESP_CTX_add_failure_info(ctx, TS_INFO_UNACCEPTED_POLICY); + } + return policy; +} + +/* Creates the TS_TST_INFO object based on the settings of the context. */ +static TS_TST_INFO *ts_RESP_create_tst_info(TS_RESP_CTX *ctx, + ASN1_OBJECT *policy) +{ + int result = 0; + TS_TST_INFO *tst_info = NULL; + ASN1_INTEGER *serial = NULL; + ASN1_GENERALIZEDTIME *asn1_time = NULL; + long sec, usec; + TS_ACCURACY *accuracy = NULL; + const ASN1_INTEGER *nonce; + GENERAL_NAME *tsa_name = NULL; + + if ((tst_info = TS_TST_INFO_new()) == NULL) + goto end; + if (!TS_TST_INFO_set_version(tst_info, 1)) + goto end; + if (!TS_TST_INFO_set_policy_id(tst_info, policy)) + goto end; + if (!TS_TST_INFO_set_msg_imprint(tst_info, ctx->request->msg_imprint)) + goto end; + if ((serial = ctx->serial_cb(ctx, ctx->serial_cb_data)) == NULL + || !TS_TST_INFO_set_serial(tst_info, serial)) + goto end; + if (!ctx->time_cb(ctx, ctx->time_cb_data, &sec, &usec) + || (asn1_time = + TS_RESP_set_genTime_with_precision(NULL, sec, usec, + ctx->clock_precision_digits)) == NULL + || !TS_TST_INFO_set_time(tst_info, asn1_time)) + goto end; + + if ((ctx->seconds || ctx->millis || ctx->micros) + && (accuracy = TS_ACCURACY_new()) == NULL) + goto end; + if (ctx->seconds && !TS_ACCURACY_set_seconds(accuracy, ctx->seconds)) + goto end; + if (ctx->millis && !TS_ACCURACY_set_millis(accuracy, ctx->millis)) + goto end; + if (ctx->micros && !TS_ACCURACY_set_micros(accuracy, ctx->micros)) + goto end; + if (accuracy && !TS_TST_INFO_set_accuracy(tst_info, accuracy)) + goto end; + + if ((ctx->flags & TS_ORDERING) + && !TS_TST_INFO_set_ordering(tst_info, 1)) + goto end; + + if ((nonce = ctx->request->nonce) != NULL + && !TS_TST_INFO_set_nonce(tst_info, nonce)) + goto end; + + if (ctx->flags & TS_TSA_NAME) { + if ((tsa_name = GENERAL_NAME_new()) == NULL) + goto end; + tsa_name->type = GEN_DIRNAME; + tsa_name->d.dirn = + X509_NAME_dup(X509_get_subject_name(ctx->signer_cert)); + if (!tsa_name->d.dirn) + goto end; + if (!TS_TST_INFO_set_tsa(tst_info, tsa_name)) + goto end; + } + + result = 1; + end: + if (!result) { + TS_TST_INFO_free(tst_info); + tst_info = NULL; + TSerr(TS_F_TS_RESP_CREATE_TST_INFO, TS_R_TST_INFO_SETUP_ERROR); + TS_RESP_CTX_set_status_info_cond(ctx, TS_STATUS_REJECTION, + "Error during TSTInfo " + "generation."); + } + GENERAL_NAME_free(tsa_name); + TS_ACCURACY_free(accuracy); + ASN1_GENERALIZEDTIME_free(asn1_time); + ASN1_INTEGER_free(serial); + + return tst_info; +} + +/* Processing the extensions of the request. */ +static int ts_RESP_process_extensions(TS_RESP_CTX *ctx) +{ + STACK_OF(X509_EXTENSION) *exts = ctx->request->extensions; + int i; + int ok = 1; + + for (i = 0; ok && i < sk_X509_EXTENSION_num(exts); ++i) { + X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i); + /* + * The last argument was previously (void *)ctx->extension_cb, + * but ISO C doesn't permit converting a function pointer to void *. + * For lack of better information, I'm placing a NULL there instead. + * The callback can pick its own address out from the ctx anyway... + */ + ok = (*ctx->extension_cb) (ctx, ext, NULL); + } + + return ok; +} + +/* Functions for signing the TS_TST_INFO structure of the context. */ +static int ts_RESP_sign(TS_RESP_CTX *ctx) +{ + int ret = 0; + PKCS7 *p7 = NULL; + PKCS7_SIGNER_INFO *si; + STACK_OF(X509) *certs; /* Certificates to include in sc. */ + ESS_SIGNING_CERT_V2 *sc2 = NULL; + ESS_SIGNING_CERT *sc = NULL; + ASN1_OBJECT *oid; + BIO *p7bio = NULL; + int i; + + if (!X509_check_private_key(ctx->signer_cert, ctx->signer_key)) { + TSerr(TS_F_TS_RESP_SIGN, TS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); + goto err; + } + + if ((p7 = PKCS7_new()) == NULL) { + TSerr(TS_F_TS_RESP_SIGN, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!PKCS7_set_type(p7, NID_pkcs7_signed)) + goto err; + if (!ASN1_INTEGER_set(p7->d.sign->version, 3)) + goto err; + + if (ctx->request->cert_req) { + PKCS7_add_certificate(p7, ctx->signer_cert); + if (ctx->certs) { + for (i = 0; i < sk_X509_num(ctx->certs); ++i) { + X509 *cert = sk_X509_value(ctx->certs, i); + PKCS7_add_certificate(p7, cert); + } + } + } + + if ((si = PKCS7_add_signature(p7, ctx->signer_cert, + ctx->signer_key, ctx->signer_md)) == NULL) { + TSerr(TS_F_TS_RESP_SIGN, TS_R_PKCS7_ADD_SIGNATURE_ERROR); + goto err; + } + + oid = OBJ_nid2obj(NID_id_smime_ct_TSTInfo); + if (!PKCS7_add_signed_attribute(si, NID_pkcs9_contentType, + V_ASN1_OBJECT, oid)) { + TSerr(TS_F_TS_RESP_SIGN, TS_R_PKCS7_ADD_SIGNED_ATTR_ERROR); + goto err; + } + + certs = ctx->flags & TS_ESS_CERT_ID_CHAIN ? ctx->certs : NULL; + if (ctx->ess_cert_id_digest == NULL + || ctx->ess_cert_id_digest == EVP_sha1()) { + if ((sc = ess_SIGNING_CERT_new_init(ctx->signer_cert, certs)) == NULL) + goto err; + + if (!ess_add_signing_cert(si, sc)) { + TSerr(TS_F_TS_RESP_SIGN, TS_R_ESS_ADD_SIGNING_CERT_ERROR); + goto err; + } + } else { + sc2 = ess_signing_cert_v2_new_init(ctx->ess_cert_id_digest, + ctx->signer_cert, certs); + if (sc2 == NULL) + goto err; + + if (!ess_add_signing_cert_v2(si, sc2)) { + TSerr(TS_F_TS_RESP_SIGN, TS_R_ESS_ADD_SIGNING_CERT_V2_ERROR); + goto err; + } + } + + if (!ts_TST_INFO_content_new(p7)) + goto err; + if ((p7bio = PKCS7_dataInit(p7, NULL)) == NULL) { + TSerr(TS_F_TS_RESP_SIGN, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!i2d_TS_TST_INFO_bio(p7bio, ctx->tst_info)) { + TSerr(TS_F_TS_RESP_SIGN, TS_R_TS_DATASIGN); + goto err; + } + if (!PKCS7_dataFinal(p7, p7bio)) { + TSerr(TS_F_TS_RESP_SIGN, TS_R_TS_DATASIGN); + goto err; + } + TS_RESP_set_tst_info(ctx->response, p7, ctx->tst_info); + p7 = NULL; /* Ownership is lost. */ + ctx->tst_info = NULL; /* Ownership is lost. */ + + ret = 1; + err: + if (!ret) + TS_RESP_CTX_set_status_info_cond(ctx, TS_STATUS_REJECTION, + "Error during signature " + "generation."); + BIO_free_all(p7bio); + ESS_SIGNING_CERT_V2_free(sc2); + ESS_SIGNING_CERT_free(sc); + PKCS7_free(p7); + return ret; +} + +static ESS_SIGNING_CERT *ess_SIGNING_CERT_new_init(X509 *signcert, + STACK_OF(X509) *certs) +{ + ESS_CERT_ID *cid; + ESS_SIGNING_CERT *sc = NULL; + int i; + + if ((sc = ESS_SIGNING_CERT_new()) == NULL) + goto err; + if (sc->cert_ids == NULL + && (sc->cert_ids = sk_ESS_CERT_ID_new_null()) == NULL) + goto err; + + if ((cid = ess_CERT_ID_new_init(signcert, 0)) == NULL + || !sk_ESS_CERT_ID_push(sc->cert_ids, cid)) + goto err; + for (i = 0; i < sk_X509_num(certs); ++i) { + X509 *cert = sk_X509_value(certs, i); + if ((cid = ess_CERT_ID_new_init(cert, 1)) == NULL + || !sk_ESS_CERT_ID_push(sc->cert_ids, cid)) + goto err; + } + + return sc; + err: + ESS_SIGNING_CERT_free(sc); + TSerr(TS_F_ESS_SIGNING_CERT_NEW_INIT, ERR_R_MALLOC_FAILURE); + return NULL; +} + +static ESS_CERT_ID *ess_CERT_ID_new_init(X509 *cert, int issuer_needed) +{ + ESS_CERT_ID *cid = NULL; + GENERAL_NAME *name = NULL; + unsigned char cert_sha1[SHA_DIGEST_LENGTH]; + + /* Call for side-effect of computing hash and caching extensions */ + X509_check_purpose(cert, -1, 0); + if ((cid = ESS_CERT_ID_new()) == NULL) + goto err; + X509_digest(cert, EVP_sha1(), cert_sha1, NULL); + if (!ASN1_OCTET_STRING_set(cid->hash, cert_sha1, SHA_DIGEST_LENGTH)) + goto err; + + /* Setting the issuer/serial if requested. */ + if (issuer_needed) { + if (cid->issuer_serial == NULL + && (cid->issuer_serial = ESS_ISSUER_SERIAL_new()) == NULL) + goto err; + if ((name = GENERAL_NAME_new()) == NULL) + goto err; + name->type = GEN_DIRNAME; + if ((name->d.dirn = X509_NAME_dup(X509_get_issuer_name(cert))) == NULL) + goto err; + if (!sk_GENERAL_NAME_push(cid->issuer_serial->issuer, name)) + goto err; + name = NULL; /* Ownership is lost. */ + ASN1_INTEGER_free(cid->issuer_serial->serial); + if (!(cid->issuer_serial->serial = + ASN1_INTEGER_dup(X509_get_serialNumber(cert)))) + goto err; + } + + return cid; + err: + GENERAL_NAME_free(name); + ESS_CERT_ID_free(cid); + TSerr(TS_F_ESS_CERT_ID_NEW_INIT, ERR_R_MALLOC_FAILURE); + return NULL; +} + +static int ts_TST_INFO_content_new(PKCS7 *p7) +{ + PKCS7 *ret = NULL; + ASN1_OCTET_STRING *octet_string = NULL; + + /* Create new encapsulated NID_id_smime_ct_TSTInfo content. */ + if ((ret = PKCS7_new()) == NULL) + goto err; + if ((ret->d.other = ASN1_TYPE_new()) == NULL) + goto err; + ret->type = OBJ_nid2obj(NID_id_smime_ct_TSTInfo); + if ((octet_string = ASN1_OCTET_STRING_new()) == NULL) + goto err; + ASN1_TYPE_set(ret->d.other, V_ASN1_OCTET_STRING, octet_string); + octet_string = NULL; + + /* Add encapsulated content to signed PKCS7 structure. */ + if (!PKCS7_set_content(p7, ret)) + goto err; + + return 1; + err: + ASN1_OCTET_STRING_free(octet_string); + PKCS7_free(ret); + return 0; +} + +static int ess_add_signing_cert(PKCS7_SIGNER_INFO *si, ESS_SIGNING_CERT *sc) +{ + ASN1_STRING *seq = NULL; + unsigned char *p, *pp = NULL; + int len; + + len = i2d_ESS_SIGNING_CERT(sc, NULL); + if ((pp = OPENSSL_malloc(len)) == NULL) { + TSerr(TS_F_ESS_ADD_SIGNING_CERT, ERR_R_MALLOC_FAILURE); + goto err; + } + p = pp; + i2d_ESS_SIGNING_CERT(sc, &p); + if ((seq = ASN1_STRING_new()) == NULL || !ASN1_STRING_set(seq, pp, len)) { + TSerr(TS_F_ESS_ADD_SIGNING_CERT, ERR_R_MALLOC_FAILURE); + goto err; + } + OPENSSL_free(pp); + pp = NULL; + return PKCS7_add_signed_attribute(si, + NID_id_smime_aa_signingCertificate, + V_ASN1_SEQUENCE, seq); + err: + ASN1_STRING_free(seq); + OPENSSL_free(pp); + + return 0; +} + +static ESS_SIGNING_CERT_V2 *ess_signing_cert_v2_new_init(const EVP_MD *hash_alg, + X509 *signcert, + STACK_OF(X509) *certs) +{ + ESS_CERT_ID_V2 *cid = NULL; + ESS_SIGNING_CERT_V2 *sc = NULL; + int i; + + if ((sc = ESS_SIGNING_CERT_V2_new()) == NULL) + goto err; + if ((cid = ess_cert_id_v2_new_init(hash_alg, signcert, 0)) == NULL) + goto err; + if (!sk_ESS_CERT_ID_V2_push(sc->cert_ids, cid)) + goto err; + cid = NULL; + + for (i = 0; i < sk_X509_num(certs); ++i) { + X509 *cert = sk_X509_value(certs, i); + + if ((cid = ess_cert_id_v2_new_init(hash_alg, cert, 1)) == NULL) + goto err; + if (!sk_ESS_CERT_ID_V2_push(sc->cert_ids, cid)) + goto err; + cid = NULL; + } + + return sc; + err: + ESS_SIGNING_CERT_V2_free(sc); + ESS_CERT_ID_V2_free(cid); + TSerr(TS_F_ESS_SIGNING_CERT_V2_NEW_INIT, ERR_R_MALLOC_FAILURE); + return NULL; +} + +static ESS_CERT_ID_V2 *ess_cert_id_v2_new_init(const EVP_MD *hash_alg, + X509 *cert, int issuer_needed) +{ + ESS_CERT_ID_V2 *cid = NULL; + GENERAL_NAME *name = NULL; + unsigned char hash[EVP_MAX_MD_SIZE]; + unsigned int hash_len = sizeof(hash); + X509_ALGOR *alg = NULL; + + memset(hash, 0, sizeof(hash)); + + if ((cid = ESS_CERT_ID_V2_new()) == NULL) + goto err; + + if (hash_alg != EVP_sha256()) { + alg = X509_ALGOR_new(); + if (alg == NULL) + goto err; + X509_ALGOR_set_md(alg, hash_alg); + if (alg->algorithm == NULL) + goto err; + cid->hash_alg = alg; + alg = NULL; + } else { + cid->hash_alg = NULL; + } + + if (!X509_digest(cert, hash_alg, hash, &hash_len)) + goto err; + + if (!ASN1_OCTET_STRING_set(cid->hash, hash, hash_len)) + goto err; + + if (issuer_needed) { + if ((cid->issuer_serial = ESS_ISSUER_SERIAL_new()) == NULL) + goto err; + if ((name = GENERAL_NAME_new()) == NULL) + goto err; + name->type = GEN_DIRNAME; + if ((name->d.dirn = X509_NAME_dup(X509_get_issuer_name(cert))) == NULL) + goto err; + if (!sk_GENERAL_NAME_push(cid->issuer_serial->issuer, name)) + goto err; + name = NULL; /* Ownership is lost. */ + ASN1_INTEGER_free(cid->issuer_serial->serial); + cid->issuer_serial->serial = + ASN1_INTEGER_dup(X509_get_serialNumber(cert)); + if (cid->issuer_serial->serial == NULL) + goto err; + } + + return cid; + err: + X509_ALGOR_free(alg); + GENERAL_NAME_free(name); + ESS_CERT_ID_V2_free(cid); + TSerr(TS_F_ESS_CERT_ID_V2_NEW_INIT, ERR_R_MALLOC_FAILURE); + return NULL; +} + +static int ess_add_signing_cert_v2(PKCS7_SIGNER_INFO *si, + ESS_SIGNING_CERT_V2 *sc) +{ + ASN1_STRING *seq = NULL; + unsigned char *p, *pp = NULL; + int len = i2d_ESS_SIGNING_CERT_V2(sc, NULL); + + if ((pp = OPENSSL_malloc(len)) == NULL) { + TSerr(TS_F_ESS_ADD_SIGNING_CERT_V2, ERR_R_MALLOC_FAILURE); + goto err; + } + + p = pp; + i2d_ESS_SIGNING_CERT_V2(sc, &p); + if ((seq = ASN1_STRING_new()) == NULL || !ASN1_STRING_set(seq, pp, len)) { + TSerr(TS_F_ESS_ADD_SIGNING_CERT_V2, ERR_R_MALLOC_FAILURE); + goto err; + } + + OPENSSL_free(pp); + pp = NULL; + return PKCS7_add_signed_attribute(si, + NID_id_smime_aa_signingCertificateV2, + V_ASN1_SEQUENCE, seq); + err: + ASN1_STRING_free(seq); + OPENSSL_free(pp); + return 0; +} + +static ASN1_GENERALIZEDTIME *TS_RESP_set_genTime_with_precision( + ASN1_GENERALIZEDTIME *asn1_time, long sec, long usec, + unsigned precision) +{ + time_t time_sec = (time_t)sec; + struct tm *tm = NULL, tm_result; + char genTime_str[17 + TS_MAX_CLOCK_PRECISION_DIGITS]; + char *p = genTime_str; + char *p_end = genTime_str + sizeof(genTime_str); + + if (precision > TS_MAX_CLOCK_PRECISION_DIGITS) + goto err; + + if ((tm = OPENSSL_gmtime(&time_sec, &tm_result)) == NULL) + goto err; + + /* + * Put "genTime_str" in GeneralizedTime format. We work around the + * restrictions imposed by rfc3280 (i.e. "GeneralizedTime values MUST + * NOT include fractional seconds") and OpenSSL related functions to + * meet the rfc3161 requirement: "GeneralizedTime syntax can include + * fraction-of-second details". + */ + p += BIO_snprintf(p, p_end - p, + "%04d%02d%02d%02d%02d%02d", + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + if (precision > 0) { + BIO_snprintf(p, 2 + precision, ".%06ld", usec); + p += strlen(p); + + /* + * To make things a bit harder, X.690 | ISO/IEC 8825-1 provides the + * following restrictions for a DER-encoding, which OpenSSL + * (specifically ASN1_GENERALIZEDTIME_check() function) doesn't + * support: "The encoding MUST terminate with a "Z" (which means + * "Zulu" time). The decimal point element, if present, MUST be the + * point option ".". The fractional-seconds elements, if present, + * MUST omit all trailing 0's; if the elements correspond to 0, they + * MUST be wholly omitted, and the decimal point element also MUST be + * omitted." + */ + /* + * Remove trailing zeros. The dot guarantees the exit condition of + * this loop even if all the digits are zero. + */ + while (*--p == '0') + continue; + if (*p != '.') + ++p; + } + *p++ = 'Z'; + *p++ = '\0'; + + if (asn1_time == NULL + && (asn1_time = ASN1_GENERALIZEDTIME_new()) == NULL) + goto err; + if (!ASN1_GENERALIZEDTIME_set_string(asn1_time, genTime_str)) { + ASN1_GENERALIZEDTIME_free(asn1_time); + goto err; + } + return asn1_time; + + err: + TSerr(TS_F_TS_RESP_SET_GENTIME_WITH_PRECISION, TS_R_COULD_NOT_SET_TIME); + return NULL; +} + +int TS_RESP_CTX_set_ess_cert_id_digest(TS_RESP_CTX *ctx, const EVP_MD *md) +{ + ctx->ess_cert_id_digest = md; + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_rsp_utils.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_rsp_utils.c new file mode 100644 index 000000000..3ecee39a2 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_rsp_utils.c @@ -0,0 +1,365 @@ +/* + * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include "ts_lcl.h" + +int TS_RESP_set_status_info(TS_RESP *a, TS_STATUS_INFO *status_info) +{ + TS_STATUS_INFO *new_status_info; + + if (a->status_info == status_info) + return 1; + new_status_info = TS_STATUS_INFO_dup(status_info); + if (new_status_info == NULL) { + TSerr(TS_F_TS_RESP_SET_STATUS_INFO, ERR_R_MALLOC_FAILURE); + return 0; + } + TS_STATUS_INFO_free(a->status_info); + a->status_info = new_status_info; + + return 1; +} + +TS_STATUS_INFO *TS_RESP_get_status_info(TS_RESP *a) +{ + return a->status_info; +} + +/* Caller loses ownership of PKCS7 and TS_TST_INFO objects. */ +void TS_RESP_set_tst_info(TS_RESP *a, PKCS7 *p7, TS_TST_INFO *tst_info) +{ + PKCS7_free(a->token); + a->token = p7; + TS_TST_INFO_free(a->tst_info); + a->tst_info = tst_info; +} + +PKCS7 *TS_RESP_get_token(TS_RESP *a) +{ + return a->token; +} + +TS_TST_INFO *TS_RESP_get_tst_info(TS_RESP *a) +{ + return a->tst_info; +} + +int TS_TST_INFO_set_version(TS_TST_INFO *a, long version) +{ + return ASN1_INTEGER_set(a->version, version); +} + +long TS_TST_INFO_get_version(const TS_TST_INFO *a) +{ + return ASN1_INTEGER_get(a->version); +} + +int TS_TST_INFO_set_policy_id(TS_TST_INFO *a, ASN1_OBJECT *policy) +{ + ASN1_OBJECT *new_policy; + + if (a->policy_id == policy) + return 1; + new_policy = OBJ_dup(policy); + if (new_policy == NULL) { + TSerr(TS_F_TS_TST_INFO_SET_POLICY_ID, ERR_R_MALLOC_FAILURE); + return 0; + } + ASN1_OBJECT_free(a->policy_id); + a->policy_id = new_policy; + return 1; +} + +ASN1_OBJECT *TS_TST_INFO_get_policy_id(TS_TST_INFO *a) +{ + return a->policy_id; +} + +int TS_TST_INFO_set_msg_imprint(TS_TST_INFO *a, TS_MSG_IMPRINT *msg_imprint) +{ + TS_MSG_IMPRINT *new_msg_imprint; + + if (a->msg_imprint == msg_imprint) + return 1; + new_msg_imprint = TS_MSG_IMPRINT_dup(msg_imprint); + if (new_msg_imprint == NULL) { + TSerr(TS_F_TS_TST_INFO_SET_MSG_IMPRINT, ERR_R_MALLOC_FAILURE); + return 0; + } + TS_MSG_IMPRINT_free(a->msg_imprint); + a->msg_imprint = new_msg_imprint; + return 1; +} + +TS_MSG_IMPRINT *TS_TST_INFO_get_msg_imprint(TS_TST_INFO *a) +{ + return a->msg_imprint; +} + +int TS_TST_INFO_set_serial(TS_TST_INFO *a, const ASN1_INTEGER *serial) +{ + ASN1_INTEGER *new_serial; + + if (a->serial == serial) + return 1; + new_serial = ASN1_INTEGER_dup(serial); + if (new_serial == NULL) { + TSerr(TS_F_TS_TST_INFO_SET_SERIAL, ERR_R_MALLOC_FAILURE); + return 0; + } + ASN1_INTEGER_free(a->serial); + a->serial = new_serial; + return 1; +} + +const ASN1_INTEGER *TS_TST_INFO_get_serial(const TS_TST_INFO *a) +{ + return a->serial; +} + +int TS_TST_INFO_set_time(TS_TST_INFO *a, const ASN1_GENERALIZEDTIME *gtime) +{ + ASN1_GENERALIZEDTIME *new_time; + + if (a->time == gtime) + return 1; + new_time = ASN1_STRING_dup(gtime); + if (new_time == NULL) { + TSerr(TS_F_TS_TST_INFO_SET_TIME, ERR_R_MALLOC_FAILURE); + return 0; + } + ASN1_GENERALIZEDTIME_free(a->time); + a->time = new_time; + return 1; +} + +const ASN1_GENERALIZEDTIME *TS_TST_INFO_get_time(const TS_TST_INFO *a) +{ + return a->time; +} + +int TS_TST_INFO_set_accuracy(TS_TST_INFO *a, TS_ACCURACY *accuracy) +{ + TS_ACCURACY *new_accuracy; + + if (a->accuracy == accuracy) + return 1; + new_accuracy = TS_ACCURACY_dup(accuracy); + if (new_accuracy == NULL) { + TSerr(TS_F_TS_TST_INFO_SET_ACCURACY, ERR_R_MALLOC_FAILURE); + return 0; + } + TS_ACCURACY_free(a->accuracy); + a->accuracy = new_accuracy; + return 1; +} + +TS_ACCURACY *TS_TST_INFO_get_accuracy(TS_TST_INFO *a) +{ + return a->accuracy; +} + +int TS_ACCURACY_set_seconds(TS_ACCURACY *a, const ASN1_INTEGER *seconds) +{ + ASN1_INTEGER *new_seconds; + + if (a->seconds == seconds) + return 1; + new_seconds = ASN1_INTEGER_dup(seconds); + if (new_seconds == NULL) { + TSerr(TS_F_TS_ACCURACY_SET_SECONDS, ERR_R_MALLOC_FAILURE); + return 0; + } + ASN1_INTEGER_free(a->seconds); + a->seconds = new_seconds; + return 1; +} + +const ASN1_INTEGER *TS_ACCURACY_get_seconds(const TS_ACCURACY *a) +{ + return a->seconds; +} + +int TS_ACCURACY_set_millis(TS_ACCURACY *a, const ASN1_INTEGER *millis) +{ + ASN1_INTEGER *new_millis = NULL; + + if (a->millis == millis) + return 1; + if (millis != NULL) { + new_millis = ASN1_INTEGER_dup(millis); + if (new_millis == NULL) { + TSerr(TS_F_TS_ACCURACY_SET_MILLIS, ERR_R_MALLOC_FAILURE); + return 0; + } + } + ASN1_INTEGER_free(a->millis); + a->millis = new_millis; + return 1; +} + +const ASN1_INTEGER *TS_ACCURACY_get_millis(const TS_ACCURACY *a) +{ + return a->millis; +} + +int TS_ACCURACY_set_micros(TS_ACCURACY *a, const ASN1_INTEGER *micros) +{ + ASN1_INTEGER *new_micros = NULL; + + if (a->micros == micros) + return 1; + if (micros != NULL) { + new_micros = ASN1_INTEGER_dup(micros); + if (new_micros == NULL) { + TSerr(TS_F_TS_ACCURACY_SET_MICROS, ERR_R_MALLOC_FAILURE); + return 0; + } + } + ASN1_INTEGER_free(a->micros); + a->micros = new_micros; + return 1; +} + +const ASN1_INTEGER *TS_ACCURACY_get_micros(const TS_ACCURACY *a) +{ + return a->micros; +} + +int TS_TST_INFO_set_ordering(TS_TST_INFO *a, int ordering) +{ + a->ordering = ordering ? 0xFF : 0x00; + return 1; +} + +int TS_TST_INFO_get_ordering(const TS_TST_INFO *a) +{ + return a->ordering ? 1 : 0; +} + +int TS_TST_INFO_set_nonce(TS_TST_INFO *a, const ASN1_INTEGER *nonce) +{ + ASN1_INTEGER *new_nonce; + + if (a->nonce == nonce) + return 1; + new_nonce = ASN1_INTEGER_dup(nonce); + if (new_nonce == NULL) { + TSerr(TS_F_TS_TST_INFO_SET_NONCE, ERR_R_MALLOC_FAILURE); + return 0; + } + ASN1_INTEGER_free(a->nonce); + a->nonce = new_nonce; + return 1; +} + +const ASN1_INTEGER *TS_TST_INFO_get_nonce(const TS_TST_INFO *a) +{ + return a->nonce; +} + +int TS_TST_INFO_set_tsa(TS_TST_INFO *a, GENERAL_NAME *tsa) +{ + GENERAL_NAME *new_tsa; + + if (a->tsa == tsa) + return 1; + new_tsa = GENERAL_NAME_dup(tsa); + if (new_tsa == NULL) { + TSerr(TS_F_TS_TST_INFO_SET_TSA, ERR_R_MALLOC_FAILURE); + return 0; + } + GENERAL_NAME_free(a->tsa); + a->tsa = new_tsa; + return 1; +} + +GENERAL_NAME *TS_TST_INFO_get_tsa(TS_TST_INFO *a) +{ + return a->tsa; +} + +STACK_OF(X509_EXTENSION) *TS_TST_INFO_get_exts(TS_TST_INFO *a) +{ + return a->extensions; +} + +void TS_TST_INFO_ext_free(TS_TST_INFO *a) +{ + if (!a) + return; + sk_X509_EXTENSION_pop_free(a->extensions, X509_EXTENSION_free); + a->extensions = NULL; +} + +int TS_TST_INFO_get_ext_count(TS_TST_INFO *a) +{ + return X509v3_get_ext_count(a->extensions); +} + +int TS_TST_INFO_get_ext_by_NID(TS_TST_INFO *a, int nid, int lastpos) +{ + return X509v3_get_ext_by_NID(a->extensions, nid, lastpos); +} + +int TS_TST_INFO_get_ext_by_OBJ(TS_TST_INFO *a, const ASN1_OBJECT *obj, int lastpos) +{ + return X509v3_get_ext_by_OBJ(a->extensions, obj, lastpos); +} + +int TS_TST_INFO_get_ext_by_critical(TS_TST_INFO *a, int crit, int lastpos) +{ + return X509v3_get_ext_by_critical(a->extensions, crit, lastpos); +} + +X509_EXTENSION *TS_TST_INFO_get_ext(TS_TST_INFO *a, int loc) +{ + return X509v3_get_ext(a->extensions, loc); +} + +X509_EXTENSION *TS_TST_INFO_delete_ext(TS_TST_INFO *a, int loc) +{ + return X509v3_delete_ext(a->extensions, loc); +} + +int TS_TST_INFO_add_ext(TS_TST_INFO *a, X509_EXTENSION *ex, int loc) +{ + return X509v3_add_ext(&a->extensions, ex, loc) != NULL; +} + +void *TS_TST_INFO_get_ext_d2i(TS_TST_INFO *a, int nid, int *crit, int *idx) +{ + return X509V3_get_d2i(a->extensions, nid, crit, idx); +} + +int TS_STATUS_INFO_set_status(TS_STATUS_INFO *a, int i) +{ + return ASN1_INTEGER_set(a->status, i); +} + +const ASN1_INTEGER *TS_STATUS_INFO_get0_status(const TS_STATUS_INFO *a) +{ + return a->status; +} + +const STACK_OF(ASN1_UTF8STRING) * +TS_STATUS_INFO_get0_text(const TS_STATUS_INFO *a) +{ + return a->text; +} + +const ASN1_BIT_STRING *TS_STATUS_INFO_get0_failure_info(const TS_STATUS_INFO *a) +{ + return a->failure_info; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_rsp_verify.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_rsp_verify.c new file mode 100644 index 000000000..9deda81b0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_rsp_verify.c @@ -0,0 +1,704 @@ +/* + * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include "ts_lcl.h" + +static int ts_verify_cert(X509_STORE *store, STACK_OF(X509) *untrusted, + X509 *signer, STACK_OF(X509) **chain); +static int ts_check_signing_certs(PKCS7_SIGNER_INFO *si, + STACK_OF(X509) *chain); +static ESS_SIGNING_CERT *ess_get_signing_cert(PKCS7_SIGNER_INFO *si); +static int ts_find_cert(STACK_OF(ESS_CERT_ID) *cert_ids, X509 *cert); +static int ts_issuer_serial_cmp(ESS_ISSUER_SERIAL *is, X509 *cert); +static int int_ts_RESP_verify_token(TS_VERIFY_CTX *ctx, + PKCS7 *token, TS_TST_INFO *tst_info); +static int ts_check_status_info(TS_RESP *response); +static char *ts_get_status_text(STACK_OF(ASN1_UTF8STRING) *text); +static int ts_check_policy(const ASN1_OBJECT *req_oid, + const TS_TST_INFO *tst_info); +static int ts_compute_imprint(BIO *data, TS_TST_INFO *tst_info, + X509_ALGOR **md_alg, + unsigned char **imprint, unsigned *imprint_len); +static int ts_check_imprints(X509_ALGOR *algor_a, + const unsigned char *imprint_a, unsigned len_a, + TS_TST_INFO *tst_info); +static int ts_check_nonces(const ASN1_INTEGER *a, TS_TST_INFO *tst_info); +static int ts_check_signer_name(GENERAL_NAME *tsa_name, X509 *signer); +static int ts_find_name(STACK_OF(GENERAL_NAME) *gen_names, + GENERAL_NAME *name); +static int ts_find_cert_v2(STACK_OF(ESS_CERT_ID_V2) *cert_ids, X509 *cert); +static ESS_SIGNING_CERT_V2 *ess_get_signing_cert_v2(PKCS7_SIGNER_INFO *si); + +/* + * This must be large enough to hold all values in ts_status_text (with + * comma separator) or all text fields in ts_failure_info (also with comma). + */ +#define TS_STATUS_BUF_SIZE 256 + +/* + * Local mapping between response codes and descriptions. + */ +static const char *ts_status_text[] = { + "granted", + "grantedWithMods", + "rejection", + "waiting", + "revocationWarning", + "revocationNotification" +}; + +#define TS_STATUS_TEXT_SIZE OSSL_NELEM(ts_status_text) + +static struct { + int code; + const char *text; +} ts_failure_info[] = { + {TS_INFO_BAD_ALG, "badAlg"}, + {TS_INFO_BAD_REQUEST, "badRequest"}, + {TS_INFO_BAD_DATA_FORMAT, "badDataFormat"}, + {TS_INFO_TIME_NOT_AVAILABLE, "timeNotAvailable"}, + {TS_INFO_UNACCEPTED_POLICY, "unacceptedPolicy"}, + {TS_INFO_UNACCEPTED_EXTENSION, "unacceptedExtension"}, + {TS_INFO_ADD_INFO_NOT_AVAILABLE, "addInfoNotAvailable"}, + {TS_INFO_SYSTEM_FAILURE, "systemFailure"} +}; + + +/*- + * This function carries out the following tasks: + * - Checks if there is one and only one signer. + * - Search for the signing certificate in 'certs' and in the response. + * - Check the extended key usage and key usage fields of the signer + * certificate (done by the path validation). + * - Build and validate the certificate path. + * - Check if the certificate path meets the requirements of the + * SigningCertificate ESS signed attribute. + * - Verify the signature value. + * - Returns the signer certificate in 'signer', if 'signer' is not NULL. + */ +int TS_RESP_verify_signature(PKCS7 *token, STACK_OF(X509) *certs, + X509_STORE *store, X509 **signer_out) +{ + STACK_OF(PKCS7_SIGNER_INFO) *sinfos = NULL; + PKCS7_SIGNER_INFO *si; + STACK_OF(X509) *signers = NULL; + X509 *signer; + STACK_OF(X509) *chain = NULL; + char buf[4096]; + int i, j = 0, ret = 0; + BIO *p7bio = NULL; + + /* Some sanity checks first. */ + if (!token) { + TSerr(TS_F_TS_RESP_VERIFY_SIGNATURE, TS_R_INVALID_NULL_POINTER); + goto err; + } + if (!PKCS7_type_is_signed(token)) { + TSerr(TS_F_TS_RESP_VERIFY_SIGNATURE, TS_R_WRONG_CONTENT_TYPE); + goto err; + } + sinfos = PKCS7_get_signer_info(token); + if (!sinfos || sk_PKCS7_SIGNER_INFO_num(sinfos) != 1) { + TSerr(TS_F_TS_RESP_VERIFY_SIGNATURE, TS_R_THERE_MUST_BE_ONE_SIGNER); + goto err; + } + si = sk_PKCS7_SIGNER_INFO_value(sinfos, 0); + if (PKCS7_get_detached(token)) { + TSerr(TS_F_TS_RESP_VERIFY_SIGNATURE, TS_R_NO_CONTENT); + goto err; + } + + /* + * Get hold of the signer certificate, search only internal certificates + * if it was requested. + */ + signers = PKCS7_get0_signers(token, certs, 0); + if (!signers || sk_X509_num(signers) != 1) + goto err; + signer = sk_X509_value(signers, 0); + + if (!ts_verify_cert(store, certs, signer, &chain)) + goto err; + if (!ts_check_signing_certs(si, chain)) + goto err; + p7bio = PKCS7_dataInit(token, NULL); + + /* We now have to 'read' from p7bio to calculate digests etc. */ + while ((i = BIO_read(p7bio, buf, sizeof(buf))) > 0) + continue; + + j = PKCS7_signatureVerify(p7bio, token, si, signer); + if (j <= 0) { + TSerr(TS_F_TS_RESP_VERIFY_SIGNATURE, TS_R_SIGNATURE_FAILURE); + goto err; + } + + if (signer_out) { + *signer_out = signer; + X509_up_ref(signer); + } + ret = 1; + + err: + BIO_free_all(p7bio); + sk_X509_pop_free(chain, X509_free); + sk_X509_free(signers); + + return ret; +} + +/* + * The certificate chain is returned in chain. Caller is responsible for + * freeing the vector. + */ +static int ts_verify_cert(X509_STORE *store, STACK_OF(X509) *untrusted, + X509 *signer, STACK_OF(X509) **chain) +{ + X509_STORE_CTX *cert_ctx = NULL; + int i; + int ret = 0; + + *chain = NULL; + cert_ctx = X509_STORE_CTX_new(); + if (cert_ctx == NULL) { + TSerr(TS_F_TS_VERIFY_CERT, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!X509_STORE_CTX_init(cert_ctx, store, signer, untrusted)) + goto end; + X509_STORE_CTX_set_purpose(cert_ctx, X509_PURPOSE_TIMESTAMP_SIGN); + i = X509_verify_cert(cert_ctx); + if (i <= 0) { + int j = X509_STORE_CTX_get_error(cert_ctx); + TSerr(TS_F_TS_VERIFY_CERT, TS_R_CERTIFICATE_VERIFY_ERROR); + ERR_add_error_data(2, "Verify error:", + X509_verify_cert_error_string(j)); + goto err; + } + *chain = X509_STORE_CTX_get1_chain(cert_ctx); + ret = 1; + goto end; + +err: + ret = 0; + +end: + X509_STORE_CTX_free(cert_ctx); + return ret; +} + +static int ts_check_signing_certs(PKCS7_SIGNER_INFO *si, + STACK_OF(X509) *chain) +{ + ESS_SIGNING_CERT *ss = ess_get_signing_cert(si); + STACK_OF(ESS_CERT_ID) *cert_ids = NULL; + ESS_SIGNING_CERT_V2 *ssv2 = ess_get_signing_cert_v2(si); + STACK_OF(ESS_CERT_ID_V2) *cert_ids_v2 = NULL; + X509 *cert; + int i = 0; + int ret = 0; + + if (ss != NULL) { + cert_ids = ss->cert_ids; + cert = sk_X509_value(chain, 0); + if (ts_find_cert(cert_ids, cert) != 0) + goto err; + + /* + * Check the other certificates of the chain if there are more than one + * certificate ids in cert_ids. + */ + if (sk_ESS_CERT_ID_num(cert_ids) > 1) { + for (i = 1; i < sk_X509_num(chain); ++i) { + cert = sk_X509_value(chain, i); + if (ts_find_cert(cert_ids, cert) < 0) + goto err; + } + } + } else if (ssv2 != NULL) { + cert_ids_v2 = ssv2->cert_ids; + cert = sk_X509_value(chain, 0); + if (ts_find_cert_v2(cert_ids_v2, cert) != 0) + goto err; + + /* + * Check the other certificates of the chain if there are more than one + * certificate ids in cert_ids. + */ + if (sk_ESS_CERT_ID_V2_num(cert_ids_v2) > 1) { + for (i = 1; i < sk_X509_num(chain); ++i) { + cert = sk_X509_value(chain, i); + if (ts_find_cert_v2(cert_ids_v2, cert) < 0) + goto err; + } + } + } else { + goto err; + } + + ret = 1; + err: + if (!ret) + TSerr(TS_F_TS_CHECK_SIGNING_CERTS, + TS_R_ESS_SIGNING_CERTIFICATE_ERROR); + ESS_SIGNING_CERT_free(ss); + ESS_SIGNING_CERT_V2_free(ssv2); + return ret; +} + +static ESS_SIGNING_CERT *ess_get_signing_cert(PKCS7_SIGNER_INFO *si) +{ + ASN1_TYPE *attr; + const unsigned char *p; + attr = PKCS7_get_signed_attribute(si, NID_id_smime_aa_signingCertificate); + if (!attr) + return NULL; + p = attr->value.sequence->data; + return d2i_ESS_SIGNING_CERT(NULL, &p, attr->value.sequence->length); +} + +static ESS_SIGNING_CERT_V2 *ess_get_signing_cert_v2(PKCS7_SIGNER_INFO *si) +{ + ASN1_TYPE *attr; + const unsigned char *p; + + attr = PKCS7_get_signed_attribute(si, NID_id_smime_aa_signingCertificateV2); + if (attr == NULL) + return NULL; + p = attr->value.sequence->data; + return d2i_ESS_SIGNING_CERT_V2(NULL, &p, attr->value.sequence->length); +} + +/* Returns < 0 if certificate is not found, certificate index otherwise. */ +static int ts_find_cert(STACK_OF(ESS_CERT_ID) *cert_ids, X509 *cert) +{ + int i; + unsigned char cert_sha1[SHA_DIGEST_LENGTH]; + + if (!cert_ids || !cert) + return -1; + + X509_digest(cert, EVP_sha1(), cert_sha1, NULL); + + /* Recompute SHA1 hash of certificate if necessary (side effect). */ + X509_check_purpose(cert, -1, 0); + + /* Look for cert in the cert_ids vector. */ + for (i = 0; i < sk_ESS_CERT_ID_num(cert_ids); ++i) { + ESS_CERT_ID *cid = sk_ESS_CERT_ID_value(cert_ids, i); + + if (cid->hash->length == SHA_DIGEST_LENGTH + && memcmp(cid->hash->data, cert_sha1, SHA_DIGEST_LENGTH) == 0) { + ESS_ISSUER_SERIAL *is = cid->issuer_serial; + if (!is || !ts_issuer_serial_cmp(is, cert)) + return i; + } + } + + return -1; +} + +/* Returns < 0 if certificate is not found, certificate index otherwise. */ +static int ts_find_cert_v2(STACK_OF(ESS_CERT_ID_V2) *cert_ids, X509 *cert) +{ + int i; + unsigned char cert_digest[EVP_MAX_MD_SIZE]; + unsigned int len; + + /* Look for cert in the cert_ids vector. */ + for (i = 0; i < sk_ESS_CERT_ID_V2_num(cert_ids); ++i) { + ESS_CERT_ID_V2 *cid = sk_ESS_CERT_ID_V2_value(cert_ids, i); + const EVP_MD *md; + + if (cid->hash_alg != NULL) + md = EVP_get_digestbyobj(cid->hash_alg->algorithm); + else + md = EVP_sha256(); + + X509_digest(cert, md, cert_digest, &len); + if (cid->hash->length != (int)len) + return -1; + + if (memcmp(cid->hash->data, cert_digest, cid->hash->length) == 0) { + ESS_ISSUER_SERIAL *is = cid->issuer_serial; + + if (is == NULL || !ts_issuer_serial_cmp(is, cert)) + return i; + } + } + + return -1; +} + +static int ts_issuer_serial_cmp(ESS_ISSUER_SERIAL *is, X509 *cert) +{ + GENERAL_NAME *issuer; + + if (!is || !cert || sk_GENERAL_NAME_num(is->issuer) != 1) + return -1; + + issuer = sk_GENERAL_NAME_value(is->issuer, 0); + if (issuer->type != GEN_DIRNAME + || X509_NAME_cmp(issuer->d.dirn, X509_get_issuer_name(cert))) + return -1; + + if (ASN1_INTEGER_cmp(is->serial, X509_get_serialNumber(cert))) + return -1; + + return 0; +} + +/*- + * Verifies whether 'response' contains a valid response with regards + * to the settings of the context: + * - Gives an error message if the TS_TST_INFO is not present. + * - Calls _TS_RESP_verify_token to verify the token content. + */ +int TS_RESP_verify_response(TS_VERIFY_CTX *ctx, TS_RESP *response) +{ + PKCS7 *token = response->token; + TS_TST_INFO *tst_info = response->tst_info; + int ret = 0; + + if (!ts_check_status_info(response)) + goto err; + if (!int_ts_RESP_verify_token(ctx, token, tst_info)) + goto err; + ret = 1; + + err: + return ret; +} + +/* + * Tries to extract a TS_TST_INFO structure from the PKCS7 token and + * calls the internal int_TS_RESP_verify_token function for verifying it. + */ +int TS_RESP_verify_token(TS_VERIFY_CTX *ctx, PKCS7 *token) +{ + TS_TST_INFO *tst_info = PKCS7_to_TS_TST_INFO(token); + int ret = 0; + if (tst_info) { + ret = int_ts_RESP_verify_token(ctx, token, tst_info); + TS_TST_INFO_free(tst_info); + } + return ret; +} + +/*- + * Verifies whether the 'token' contains a valid time stamp token + * with regards to the settings of the context. Only those checks are + * carried out that are specified in the context: + * - Verifies the signature of the TS_TST_INFO. + * - Checks the version number of the response. + * - Check if the requested and returned policies math. + * - Check if the message imprints are the same. + * - Check if the nonces are the same. + * - Check if the TSA name matches the signer. + * - Check if the TSA name is the expected TSA. + */ +static int int_ts_RESP_verify_token(TS_VERIFY_CTX *ctx, + PKCS7 *token, TS_TST_INFO *tst_info) +{ + X509 *signer = NULL; + GENERAL_NAME *tsa_name = tst_info->tsa; + X509_ALGOR *md_alg = NULL; + unsigned char *imprint = NULL; + unsigned imprint_len = 0; + int ret = 0; + int flags = ctx->flags; + + /* Some options require us to also check the signature */ + if (((flags & TS_VFY_SIGNER) && tsa_name != NULL) + || (flags & TS_VFY_TSA_NAME)) { + flags |= TS_VFY_SIGNATURE; + } + + if ((flags & TS_VFY_SIGNATURE) + && !TS_RESP_verify_signature(token, ctx->certs, ctx->store, &signer)) + goto err; + if ((flags & TS_VFY_VERSION) + && TS_TST_INFO_get_version(tst_info) != 1) { + TSerr(TS_F_INT_TS_RESP_VERIFY_TOKEN, TS_R_UNSUPPORTED_VERSION); + goto err; + } + if ((flags & TS_VFY_POLICY) + && !ts_check_policy(ctx->policy, tst_info)) + goto err; + if ((flags & TS_VFY_IMPRINT) + && !ts_check_imprints(ctx->md_alg, ctx->imprint, ctx->imprint_len, + tst_info)) + goto err; + if ((flags & TS_VFY_DATA) + && (!ts_compute_imprint(ctx->data, tst_info, + &md_alg, &imprint, &imprint_len) + || !ts_check_imprints(md_alg, imprint, imprint_len, tst_info))) + goto err; + if ((flags & TS_VFY_NONCE) + && !ts_check_nonces(ctx->nonce, tst_info)) + goto err; + if ((flags & TS_VFY_SIGNER) + && tsa_name && !ts_check_signer_name(tsa_name, signer)) { + TSerr(TS_F_INT_TS_RESP_VERIFY_TOKEN, TS_R_TSA_NAME_MISMATCH); + goto err; + } + if ((flags & TS_VFY_TSA_NAME) + && !ts_check_signer_name(ctx->tsa_name, signer)) { + TSerr(TS_F_INT_TS_RESP_VERIFY_TOKEN, TS_R_TSA_UNTRUSTED); + goto err; + } + ret = 1; + + err: + X509_free(signer); + X509_ALGOR_free(md_alg); + OPENSSL_free(imprint); + return ret; +} + +static int ts_check_status_info(TS_RESP *response) +{ + TS_STATUS_INFO *info = response->status_info; + long status = ASN1_INTEGER_get(info->status); + const char *status_text = NULL; + char *embedded_status_text = NULL; + char failure_text[TS_STATUS_BUF_SIZE] = ""; + + if (status == 0 || status == 1) + return 1; + + /* There was an error, get the description in status_text. */ + if (0 <= status && status < (long) OSSL_NELEM(ts_status_text)) + status_text = ts_status_text[status]; + else + status_text = "unknown code"; + + if (sk_ASN1_UTF8STRING_num(info->text) > 0 + && (embedded_status_text = ts_get_status_text(info->text)) == NULL) + return 0; + + /* Fill in failure_text with the failure information. */ + if (info->failure_info) { + int i; + int first = 1; + for (i = 0; i < (int)OSSL_NELEM(ts_failure_info); ++i) { + if (ASN1_BIT_STRING_get_bit(info->failure_info, + ts_failure_info[i].code)) { + if (!first) + strcat(failure_text, ","); + else + first = 0; + strcat(failure_text, ts_failure_info[i].text); + } + } + } + if (failure_text[0] == '\0') + strcpy(failure_text, "unspecified"); + + TSerr(TS_F_TS_CHECK_STATUS_INFO, TS_R_NO_TIME_STAMP_TOKEN); + ERR_add_error_data(6, + "status code: ", status_text, + ", status text: ", embedded_status_text ? + embedded_status_text : "unspecified", + ", failure codes: ", failure_text); + OPENSSL_free(embedded_status_text); + + return 0; +} + +static char *ts_get_status_text(STACK_OF(ASN1_UTF8STRING) *text) +{ + int i; + int length = 0; + char *result = NULL; + char *p; + + for (i = 0; i < sk_ASN1_UTF8STRING_num(text); ++i) { + ASN1_UTF8STRING *current = sk_ASN1_UTF8STRING_value(text, i); + if (ASN1_STRING_length(current) > TS_MAX_STATUS_LENGTH - length - 1) + return NULL; + length += ASN1_STRING_length(current); + length += 1; /* separator character */ + } + if ((result = OPENSSL_malloc(length)) == NULL) { + TSerr(TS_F_TS_GET_STATUS_TEXT, ERR_R_MALLOC_FAILURE); + return NULL; + } + + for (i = 0, p = result; i < sk_ASN1_UTF8STRING_num(text); ++i) { + ASN1_UTF8STRING *current = sk_ASN1_UTF8STRING_value(text, i); + length = ASN1_STRING_length(current); + if (i > 0) + *p++ = '/'; + strncpy(p, (const char *)ASN1_STRING_get0_data(current), length); + p += length; + } + *p = '\0'; + + return result; +} + +static int ts_check_policy(const ASN1_OBJECT *req_oid, + const TS_TST_INFO *tst_info) +{ + const ASN1_OBJECT *resp_oid = tst_info->policy_id; + + if (OBJ_cmp(req_oid, resp_oid) != 0) { + TSerr(TS_F_TS_CHECK_POLICY, TS_R_POLICY_MISMATCH); + return 0; + } + + return 1; +} + +static int ts_compute_imprint(BIO *data, TS_TST_INFO *tst_info, + X509_ALGOR **md_alg, + unsigned char **imprint, unsigned *imprint_len) +{ + TS_MSG_IMPRINT *msg_imprint = tst_info->msg_imprint; + X509_ALGOR *md_alg_resp = msg_imprint->hash_algo; + const EVP_MD *md; + EVP_MD_CTX *md_ctx = NULL; + unsigned char buffer[4096]; + int length; + + *md_alg = NULL; + *imprint = NULL; + + if ((*md_alg = X509_ALGOR_dup(md_alg_resp)) == NULL) + goto err; + if ((md = EVP_get_digestbyobj((*md_alg)->algorithm)) == NULL) { + TSerr(TS_F_TS_COMPUTE_IMPRINT, TS_R_UNSUPPORTED_MD_ALGORITHM); + goto err; + } + length = EVP_MD_size(md); + if (length < 0) + goto err; + *imprint_len = length; + if ((*imprint = OPENSSL_malloc(*imprint_len)) == NULL) { + TSerr(TS_F_TS_COMPUTE_IMPRINT, ERR_R_MALLOC_FAILURE); + goto err; + } + + md_ctx = EVP_MD_CTX_new(); + if (md_ctx == NULL) { + TSerr(TS_F_TS_COMPUTE_IMPRINT, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!EVP_DigestInit(md_ctx, md)) + goto err; + while ((length = BIO_read(data, buffer, sizeof(buffer))) > 0) { + if (!EVP_DigestUpdate(md_ctx, buffer, length)) + goto err; + } + if (!EVP_DigestFinal(md_ctx, *imprint, NULL)) + goto err; + EVP_MD_CTX_free(md_ctx); + + return 1; + err: + EVP_MD_CTX_free(md_ctx); + X509_ALGOR_free(*md_alg); + OPENSSL_free(*imprint); + *imprint_len = 0; + *imprint = 0; + return 0; +} + +static int ts_check_imprints(X509_ALGOR *algor_a, + const unsigned char *imprint_a, unsigned len_a, + TS_TST_INFO *tst_info) +{ + TS_MSG_IMPRINT *b = tst_info->msg_imprint; + X509_ALGOR *algor_b = b->hash_algo; + int ret = 0; + + if (algor_a) { + if (OBJ_cmp(algor_a->algorithm, algor_b->algorithm)) + goto err; + + /* The parameter must be NULL in both. */ + if ((algor_a->parameter + && ASN1_TYPE_get(algor_a->parameter) != V_ASN1_NULL) + || (algor_b->parameter + && ASN1_TYPE_get(algor_b->parameter) != V_ASN1_NULL)) + goto err; + } + + ret = len_a == (unsigned)ASN1_STRING_length(b->hashed_msg) && + memcmp(imprint_a, ASN1_STRING_get0_data(b->hashed_msg), len_a) == 0; + err: + if (!ret) + TSerr(TS_F_TS_CHECK_IMPRINTS, TS_R_MESSAGE_IMPRINT_MISMATCH); + return ret; +} + +static int ts_check_nonces(const ASN1_INTEGER *a, TS_TST_INFO *tst_info) +{ + const ASN1_INTEGER *b = tst_info->nonce; + + if (!b) { + TSerr(TS_F_TS_CHECK_NONCES, TS_R_NONCE_NOT_RETURNED); + return 0; + } + + /* No error if a nonce is returned without being requested. */ + if (ASN1_INTEGER_cmp(a, b) != 0) { + TSerr(TS_F_TS_CHECK_NONCES, TS_R_NONCE_MISMATCH); + return 0; + } + + return 1; +} + +/* + * Check if the specified TSA name matches either the subject or one of the + * subject alternative names of the TSA certificate. + */ +static int ts_check_signer_name(GENERAL_NAME *tsa_name, X509 *signer) +{ + STACK_OF(GENERAL_NAME) *gen_names = NULL; + int idx = -1; + int found = 0; + + if (tsa_name->type == GEN_DIRNAME + && X509_name_cmp(tsa_name->d.dirn, X509_get_subject_name(signer)) == 0) + return 1; + gen_names = X509_get_ext_d2i(signer, NID_subject_alt_name, NULL, &idx); + while (gen_names != NULL) { + found = ts_find_name(gen_names, tsa_name) >= 0; + if (found) + break; + /* + * Get the next subject alternative name, although there should be no + * more than one. + */ + GENERAL_NAMES_free(gen_names); + gen_names = X509_get_ext_d2i(signer, NID_subject_alt_name, NULL, &idx); + } + GENERAL_NAMES_free(gen_names); + + return found; +} + +/* Returns 1 if name is in gen_names, 0 otherwise. */ +static int ts_find_name(STACK_OF(GENERAL_NAME) *gen_names, GENERAL_NAME *name) +{ + int i, found; + for (i = 0, found = 0; !found && i < sk_GENERAL_NAME_num(gen_names); ++i) { + GENERAL_NAME *current = sk_GENERAL_NAME_value(gen_names, i); + found = GENERAL_NAME_cmp(current, name) == 0; + } + return found ? i - 1 : -1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_verify_ctx.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_verify_ctx.c new file mode 100644 index 000000000..d4792ee04 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ts/ts_verify_ctx.c @@ -0,0 +1,146 @@ +/* + * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include +#include +#include "ts_lcl.h" + +TS_VERIFY_CTX *TS_VERIFY_CTX_new(void) +{ + TS_VERIFY_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); + + if (ctx == NULL) + TSerr(TS_F_TS_VERIFY_CTX_NEW, ERR_R_MALLOC_FAILURE); + return ctx; +} + +void TS_VERIFY_CTX_init(TS_VERIFY_CTX *ctx) +{ + OPENSSL_assert(ctx != NULL); + memset(ctx, 0, sizeof(*ctx)); +} + +void TS_VERIFY_CTX_free(TS_VERIFY_CTX *ctx) +{ + if (!ctx) + return; + + TS_VERIFY_CTX_cleanup(ctx); + OPENSSL_free(ctx); +} + +int TS_VERIFY_CTX_add_flags(TS_VERIFY_CTX *ctx, int f) +{ + ctx->flags |= f; + return ctx->flags; +} + +int TS_VERIFY_CTX_set_flags(TS_VERIFY_CTX *ctx, int f) +{ + ctx->flags = f; + return ctx->flags; +} + +BIO *TS_VERIFY_CTX_set_data(TS_VERIFY_CTX *ctx, BIO *b) +{ + ctx->data = b; + return ctx->data; +} + +X509_STORE *TS_VERIFY_CTX_set_store(TS_VERIFY_CTX *ctx, X509_STORE *s) +{ + ctx->store = s; + return ctx->store; +} + +STACK_OF(X509) *TS_VERIFY_CTS_set_certs(TS_VERIFY_CTX *ctx, + STACK_OF(X509) *certs) +{ + ctx->certs = certs; + return ctx->certs; +} + +unsigned char *TS_VERIFY_CTX_set_imprint(TS_VERIFY_CTX *ctx, + unsigned char *hexstr, long len) +{ + ctx->imprint = hexstr; + ctx->imprint_len = len; + return ctx->imprint; +} + +void TS_VERIFY_CTX_cleanup(TS_VERIFY_CTX *ctx) +{ + if (!ctx) + return; + + X509_STORE_free(ctx->store); + sk_X509_pop_free(ctx->certs, X509_free); + + ASN1_OBJECT_free(ctx->policy); + + X509_ALGOR_free(ctx->md_alg); + OPENSSL_free(ctx->imprint); + + BIO_free_all(ctx->data); + + ASN1_INTEGER_free(ctx->nonce); + + GENERAL_NAME_free(ctx->tsa_name); + + TS_VERIFY_CTX_init(ctx); +} + +TS_VERIFY_CTX *TS_REQ_to_TS_VERIFY_CTX(TS_REQ *req, TS_VERIFY_CTX *ctx) +{ + TS_VERIFY_CTX *ret = ctx; + ASN1_OBJECT *policy; + TS_MSG_IMPRINT *imprint; + X509_ALGOR *md_alg; + ASN1_OCTET_STRING *msg; + const ASN1_INTEGER *nonce; + + OPENSSL_assert(req != NULL); + if (ret) + TS_VERIFY_CTX_cleanup(ret); + else if ((ret = TS_VERIFY_CTX_new()) == NULL) + return NULL; + + ret->flags = TS_VFY_ALL_IMPRINT & ~(TS_VFY_TSA_NAME | TS_VFY_SIGNATURE); + + if ((policy = req->policy_id) != NULL) { + if ((ret->policy = OBJ_dup(policy)) == NULL) + goto err; + } else + ret->flags &= ~TS_VFY_POLICY; + + imprint = req->msg_imprint; + md_alg = imprint->hash_algo; + if ((ret->md_alg = X509_ALGOR_dup(md_alg)) == NULL) + goto err; + msg = imprint->hashed_msg; + ret->imprint_len = ASN1_STRING_length(msg); + if ((ret->imprint = OPENSSL_malloc(ret->imprint_len)) == NULL) + goto err; + memcpy(ret->imprint, ASN1_STRING_get0_data(msg), ret->imprint_len); + + if ((nonce = req->nonce) != NULL) { + if ((ret->nonce = ASN1_INTEGER_dup(nonce)) == NULL) + goto err; + } else + ret->flags &= ~TS_VFY_NONCE; + + return ret; + err: + if (ctx) + TS_VERIFY_CTX_cleanup(ctx); + else + TS_VERIFY_CTX_free(ret); + return NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/txt_db/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/txt_db/build.info new file mode 100644 index 000000000..4379d5f1b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/txt_db/build.info @@ -0,0 +1,2 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=txt_db.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/txt_db/txt_db.c b/trunk/3rdparty/openssl-1.1-fit/crypto/txt_db/txt_db.c new file mode 100644 index 000000000..c4e178251 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/txt_db/txt_db.c @@ -0,0 +1,317 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "internal/cryptlib.h" +#include +#include + +#undef BUFSIZE +#define BUFSIZE 512 + +TXT_DB *TXT_DB_read(BIO *in, int num) +{ + TXT_DB *ret = NULL; + int esc = 0; + long ln = 0; + int i, add, n; + int size = BUFSIZE; + int offset = 0; + char *p, *f; + OPENSSL_STRING *pp; + BUF_MEM *buf = NULL; + + if ((buf = BUF_MEM_new()) == NULL) + goto err; + if (!BUF_MEM_grow(buf, size)) + goto err; + + if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) + goto err; + ret->num_fields = num; + ret->index = NULL; + ret->qual = NULL; + if ((ret->data = sk_OPENSSL_PSTRING_new_null()) == NULL) + goto err; + if ((ret->index = OPENSSL_malloc(sizeof(*ret->index) * num)) == NULL) + goto err; + if ((ret->qual = OPENSSL_malloc(sizeof(*(ret->qual)) * num)) == NULL) + goto err; + for (i = 0; i < num; i++) { + ret->index[i] = NULL; + ret->qual[i] = NULL; + } + + add = (num + 1) * sizeof(char *); + buf->data[size - 1] = '\0'; + offset = 0; + for (;;) { + if (offset != 0) { + size += BUFSIZE; + if (!BUF_MEM_grow_clean(buf, size)) + goto err; + } + buf->data[offset] = '\0'; + BIO_gets(in, &(buf->data[offset]), size - offset); + ln++; + if (buf->data[offset] == '\0') + break; + if ((offset == 0) && (buf->data[0] == '#')) + continue; + i = strlen(&(buf->data[offset])); + offset += i; + if (buf->data[offset - 1] != '\n') + continue; + else { + buf->data[offset - 1] = '\0'; /* blat the '\n' */ + if ((p = OPENSSL_malloc(add + offset)) == NULL) + goto err; + offset = 0; + } + pp = (char **)p; + p += add; + n = 0; + pp[n++] = p; + i = 0; + f = buf->data; + + esc = 0; + for (;;) { + if (*f == '\0') + break; + if (*f == '\t') { + if (esc) + p--; + else { + *(p++) = '\0'; + f++; + if (n >= num) + break; + pp[n++] = p; + continue; + } + } + esc = (*f == '\\'); + *(p++) = *(f++); + } + *(p++) = '\0'; + if ((n != num) || (*f != '\0')) { + OPENSSL_free(pp); + ret->error = DB_ERROR_WRONG_NUM_FIELDS; + goto err; + } + pp[n] = p; + if (!sk_OPENSSL_PSTRING_push(ret->data, pp)) { + OPENSSL_free(pp); + goto err; + } + } + BUF_MEM_free(buf); + return ret; + err: + BUF_MEM_free(buf); + if (ret != NULL) { + sk_OPENSSL_PSTRING_free(ret->data); + OPENSSL_free(ret->index); + OPENSSL_free(ret->qual); + OPENSSL_free(ret); + } + return NULL; +} + +OPENSSL_STRING *TXT_DB_get_by_index(TXT_DB *db, int idx, + OPENSSL_STRING *value) +{ + OPENSSL_STRING *ret; + LHASH_OF(OPENSSL_STRING) *lh; + + if (idx >= db->num_fields) { + db->error = DB_ERROR_INDEX_OUT_OF_RANGE; + return NULL; + } + lh = db->index[idx]; + if (lh == NULL) { + db->error = DB_ERROR_NO_INDEX; + return NULL; + } + ret = lh_OPENSSL_STRING_retrieve(lh, value); + db->error = DB_ERROR_OK; + return ret; +} + +int TXT_DB_create_index(TXT_DB *db, int field, int (*qual) (OPENSSL_STRING *), + OPENSSL_LH_HASHFUNC hash, OPENSSL_LH_COMPFUNC cmp) +{ + LHASH_OF(OPENSSL_STRING) *idx; + OPENSSL_STRING *r, *k; + int i, n; + + if (field >= db->num_fields) { + db->error = DB_ERROR_INDEX_OUT_OF_RANGE; + return 0; + } + /* FIXME: we lose type checking at this point */ + if ((idx = (LHASH_OF(OPENSSL_STRING) *)OPENSSL_LH_new(hash, cmp)) == NULL) { + db->error = DB_ERROR_MALLOC; + return 0; + } + n = sk_OPENSSL_PSTRING_num(db->data); + for (i = 0; i < n; i++) { + r = sk_OPENSSL_PSTRING_value(db->data, i); + if ((qual != NULL) && (qual(r) == 0)) + continue; + if ((k = lh_OPENSSL_STRING_insert(idx, r)) != NULL) { + db->error = DB_ERROR_INDEX_CLASH; + db->arg1 = sk_OPENSSL_PSTRING_find(db->data, k); + db->arg2 = i; + lh_OPENSSL_STRING_free(idx); + return 0; + } + if (lh_OPENSSL_STRING_retrieve(idx, r) == NULL) { + db->error = DB_ERROR_MALLOC; + lh_OPENSSL_STRING_free(idx); + return 0; + } + } + lh_OPENSSL_STRING_free(db->index[field]); + db->index[field] = idx; + db->qual[field] = qual; + return 1; +} + +long TXT_DB_write(BIO *out, TXT_DB *db) +{ + long i, j, n, nn, l, tot = 0; + char *p, **pp, *f; + BUF_MEM *buf = NULL; + long ret = -1; + + if ((buf = BUF_MEM_new()) == NULL) + goto err; + n = sk_OPENSSL_PSTRING_num(db->data); + nn = db->num_fields; + for (i = 0; i < n; i++) { + pp = sk_OPENSSL_PSTRING_value(db->data, i); + + l = 0; + for (j = 0; j < nn; j++) { + if (pp[j] != NULL) + l += strlen(pp[j]); + } + if (!BUF_MEM_grow_clean(buf, (int)(l * 2 + nn))) + goto err; + + p = buf->data; + for (j = 0; j < nn; j++) { + f = pp[j]; + if (f != NULL) + for (;;) { + if (*f == '\0') + break; + if (*f == '\t') + *(p++) = '\\'; + *(p++) = *(f++); + } + *(p++) = '\t'; + } + p[-1] = '\n'; + j = p - buf->data; + if (BIO_write(out, buf->data, (int)j) != j) + goto err; + tot += j; + } + ret = tot; + err: + BUF_MEM_free(buf); + return ret; +} + +int TXT_DB_insert(TXT_DB *db, OPENSSL_STRING *row) +{ + int i; + OPENSSL_STRING *r; + + for (i = 0; i < db->num_fields; i++) { + if (db->index[i] != NULL) { + if ((db->qual[i] != NULL) && (db->qual[i] (row) == 0)) + continue; + r = lh_OPENSSL_STRING_retrieve(db->index[i], row); + if (r != NULL) { + db->error = DB_ERROR_INDEX_CLASH; + db->arg1 = i; + db->arg_row = r; + goto err; + } + } + } + + for (i = 0; i < db->num_fields; i++) { + if (db->index[i] != NULL) { + if ((db->qual[i] != NULL) && (db->qual[i] (row) == 0)) + continue; + (void)lh_OPENSSL_STRING_insert(db->index[i], row); + if (lh_OPENSSL_STRING_retrieve(db->index[i], row) == NULL) + goto err1; + } + } + if (!sk_OPENSSL_PSTRING_push(db->data, row)) + goto err1; + return 1; + + err1: + db->error = DB_ERROR_MALLOC; + while (i-- > 0) { + if (db->index[i] != NULL) { + if ((db->qual[i] != NULL) && (db->qual[i] (row) == 0)) + continue; + (void)lh_OPENSSL_STRING_delete(db->index[i], row); + } + } + err: + return 0; +} + +void TXT_DB_free(TXT_DB *db) +{ + int i, n; + char **p, *max; + + if (db == NULL) + return; + if (db->index != NULL) { + for (i = db->num_fields - 1; i >= 0; i--) + lh_OPENSSL_STRING_free(db->index[i]); + OPENSSL_free(db->index); + } + OPENSSL_free(db->qual); + if (db->data != NULL) { + for (i = sk_OPENSSL_PSTRING_num(db->data) - 1; i >= 0; i--) { + /* + * check if any 'fields' have been allocated from outside of the + * initial block + */ + p = sk_OPENSSL_PSTRING_value(db->data, i); + max = p[db->num_fields]; /* last address */ + if (max == NULL) { /* new row */ + for (n = 0; n < db->num_fields; n++) + OPENSSL_free(p[n]); + } else { + for (n = 0; n < db->num_fields; n++) { + if (((p[n] < (char *)p) || (p[n] > max))) + OPENSSL_free(p[n]); + } + } + OPENSSL_free(sk_OPENSSL_PSTRING_value(db->data, i)); + } + sk_OPENSSL_PSTRING_free(db->data); + } + OPENSSL_free(db); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ui/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/ui/build.info new file mode 100644 index 000000000..c5d17fb74 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ui/build.info @@ -0,0 +1,3 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + ui_err.c ui_lib.c ui_openssl.c ui_null.c ui_util.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ui/ui_err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ui/ui_err.c new file mode 100644 index 000000000..b806872c3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ui/ui_err.c @@ -0,0 +1,78 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA UI_str_functs[] = { + {ERR_PACK(ERR_LIB_UI, UI_F_CLOSE_CONSOLE, 0), "close_console"}, + {ERR_PACK(ERR_LIB_UI, UI_F_ECHO_CONSOLE, 0), "echo_console"}, + {ERR_PACK(ERR_LIB_UI, UI_F_GENERAL_ALLOCATE_BOOLEAN, 0), + "general_allocate_boolean"}, + {ERR_PACK(ERR_LIB_UI, UI_F_GENERAL_ALLOCATE_PROMPT, 0), + "general_allocate_prompt"}, + {ERR_PACK(ERR_LIB_UI, UI_F_NOECHO_CONSOLE, 0), "noecho_console"}, + {ERR_PACK(ERR_LIB_UI, UI_F_OPEN_CONSOLE, 0), "open_console"}, + {ERR_PACK(ERR_LIB_UI, UI_F_UI_CONSTRUCT_PROMPT, 0), "UI_construct_prompt"}, + {ERR_PACK(ERR_LIB_UI, UI_F_UI_CREATE_METHOD, 0), "UI_create_method"}, + {ERR_PACK(ERR_LIB_UI, UI_F_UI_CTRL, 0), "UI_ctrl"}, + {ERR_PACK(ERR_LIB_UI, UI_F_UI_DUP_ERROR_STRING, 0), "UI_dup_error_string"}, + {ERR_PACK(ERR_LIB_UI, UI_F_UI_DUP_INFO_STRING, 0), "UI_dup_info_string"}, + {ERR_PACK(ERR_LIB_UI, UI_F_UI_DUP_INPUT_BOOLEAN, 0), + "UI_dup_input_boolean"}, + {ERR_PACK(ERR_LIB_UI, UI_F_UI_DUP_INPUT_STRING, 0), "UI_dup_input_string"}, + {ERR_PACK(ERR_LIB_UI, UI_F_UI_DUP_USER_DATA, 0), "UI_dup_user_data"}, + {ERR_PACK(ERR_LIB_UI, UI_F_UI_DUP_VERIFY_STRING, 0), + "UI_dup_verify_string"}, + {ERR_PACK(ERR_LIB_UI, UI_F_UI_GET0_RESULT, 0), "UI_get0_result"}, + {ERR_PACK(ERR_LIB_UI, UI_F_UI_GET_RESULT_LENGTH, 0), + "UI_get_result_length"}, + {ERR_PACK(ERR_LIB_UI, UI_F_UI_NEW_METHOD, 0), "UI_new_method"}, + {ERR_PACK(ERR_LIB_UI, UI_F_UI_PROCESS, 0), "UI_process"}, + {ERR_PACK(ERR_LIB_UI, UI_F_UI_SET_RESULT, 0), "UI_set_result"}, + {ERR_PACK(ERR_LIB_UI, UI_F_UI_SET_RESULT_EX, 0), "UI_set_result_ex"}, + {0, NULL} +}; + +static const ERR_STRING_DATA UI_str_reasons[] = { + {ERR_PACK(ERR_LIB_UI, 0, UI_R_COMMON_OK_AND_CANCEL_CHARACTERS), + "common ok and cancel characters"}, + {ERR_PACK(ERR_LIB_UI, 0, UI_R_INDEX_TOO_LARGE), "index too large"}, + {ERR_PACK(ERR_LIB_UI, 0, UI_R_INDEX_TOO_SMALL), "index too small"}, + {ERR_PACK(ERR_LIB_UI, 0, UI_R_NO_RESULT_BUFFER), "no result buffer"}, + {ERR_PACK(ERR_LIB_UI, 0, UI_R_PROCESSING_ERROR), "processing error"}, + {ERR_PACK(ERR_LIB_UI, 0, UI_R_RESULT_TOO_LARGE), "result too large"}, + {ERR_PACK(ERR_LIB_UI, 0, UI_R_RESULT_TOO_SMALL), "result too small"}, + {ERR_PACK(ERR_LIB_UI, 0, UI_R_SYSASSIGN_ERROR), "sys$assign error"}, + {ERR_PACK(ERR_LIB_UI, 0, UI_R_SYSDASSGN_ERROR), "sys$dassgn error"}, + {ERR_PACK(ERR_LIB_UI, 0, UI_R_SYSQIOW_ERROR), "sys$qiow error"}, + {ERR_PACK(ERR_LIB_UI, 0, UI_R_UNKNOWN_CONTROL_COMMAND), + "unknown control command"}, + {ERR_PACK(ERR_LIB_UI, 0, UI_R_UNKNOWN_TTYGET_ERRNO_VALUE), + "unknown ttyget errno value"}, + {ERR_PACK(ERR_LIB_UI, 0, UI_R_USER_DATA_DUPLICATION_UNSUPPORTED), + "user data duplication unsupported"}, + {0, NULL} +}; + +#endif + +int ERR_load_UI_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(UI_str_functs[0].error) == NULL) { + ERR_load_strings_const(UI_str_functs); + ERR_load_strings_const(UI_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ui/ui_lib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ui/ui_lib.c new file mode 100644 index 000000000..139485dcd --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ui/ui_lib.c @@ -0,0 +1,954 @@ +/* + * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "ui_locl.h" + +UI *UI_new(void) +{ + return UI_new_method(NULL); +} + +UI *UI_new_method(const UI_METHOD *method) +{ + UI *ret = OPENSSL_zalloc(sizeof(*ret)); + + if (ret == NULL) { + UIerr(UI_F_UI_NEW_METHOD, ERR_R_MALLOC_FAILURE); + return NULL; + } + + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) { + UIerr(UI_F_UI_NEW_METHOD, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ret); + return NULL; + } + + if (method == NULL) + method = UI_get_default_method(); + if (method == NULL) + method = UI_null(); + ret->meth = method; + + if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_UI, ret, &ret->ex_data)) { + OPENSSL_free(ret); + return NULL; + } + return ret; +} + +static void free_string(UI_STRING *uis) +{ + if (uis->flags & OUT_STRING_FREEABLE) { + OPENSSL_free((char *)uis->out_string); + switch (uis->type) { + case UIT_BOOLEAN: + OPENSSL_free((char *)uis->_.boolean_data.action_desc); + OPENSSL_free((char *)uis->_.boolean_data.ok_chars); + OPENSSL_free((char *)uis->_.boolean_data.cancel_chars); + break; + case UIT_NONE: + case UIT_PROMPT: + case UIT_VERIFY: + case UIT_ERROR: + case UIT_INFO: + break; + } + } + OPENSSL_free(uis); +} + +void UI_free(UI *ui) +{ + if (ui == NULL) + return; + if ((ui->flags & UI_FLAG_DUPL_DATA) != 0) { + ui->meth->ui_destroy_data(ui, ui->user_data); + } + sk_UI_STRING_pop_free(ui->strings, free_string); + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_UI, ui, &ui->ex_data); + CRYPTO_THREAD_lock_free(ui->lock); + OPENSSL_free(ui); +} + +static int allocate_string_stack(UI *ui) +{ + if (ui->strings == NULL) { + ui->strings = sk_UI_STRING_new_null(); + if (ui->strings == NULL) { + return -1; + } + } + return 0; +} + +static UI_STRING *general_allocate_prompt(UI *ui, const char *prompt, + int prompt_freeable, + enum UI_string_types type, + int input_flags, char *result_buf) +{ + UI_STRING *ret = NULL; + + if (prompt == NULL) { + UIerr(UI_F_GENERAL_ALLOCATE_PROMPT, ERR_R_PASSED_NULL_PARAMETER); + } else if ((type == UIT_PROMPT || type == UIT_VERIFY + || type == UIT_BOOLEAN) && result_buf == NULL) { + UIerr(UI_F_GENERAL_ALLOCATE_PROMPT, UI_R_NO_RESULT_BUFFER); + } else if ((ret = OPENSSL_malloc(sizeof(*ret))) != NULL) { + ret->out_string = prompt; + ret->flags = prompt_freeable ? OUT_STRING_FREEABLE : 0; + ret->input_flags = input_flags; + ret->type = type; + ret->result_buf = result_buf; + } + return ret; +} + +static int general_allocate_string(UI *ui, const char *prompt, + int prompt_freeable, + enum UI_string_types type, int input_flags, + char *result_buf, int minsize, int maxsize, + const char *test_buf) +{ + int ret = -1; + UI_STRING *s = general_allocate_prompt(ui, prompt, prompt_freeable, + type, input_flags, result_buf); + + if (s != NULL) { + if (allocate_string_stack(ui) >= 0) { + s->_.string_data.result_minsize = minsize; + s->_.string_data.result_maxsize = maxsize; + s->_.string_data.test_buf = test_buf; + ret = sk_UI_STRING_push(ui->strings, s); + /* sk_push() returns 0 on error. Let's adapt that */ + if (ret <= 0) { + ret--; + free_string(s); + } + } else + free_string(s); + } + return ret; +} + +static int general_allocate_boolean(UI *ui, + const char *prompt, + const char *action_desc, + const char *ok_chars, + const char *cancel_chars, + int prompt_freeable, + enum UI_string_types type, + int input_flags, char *result_buf) +{ + int ret = -1; + UI_STRING *s; + const char *p; + + if (ok_chars == NULL) { + UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN, ERR_R_PASSED_NULL_PARAMETER); + } else if (cancel_chars == NULL) { + UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN, ERR_R_PASSED_NULL_PARAMETER); + } else { + for (p = ok_chars; *p != '\0'; p++) { + if (strchr(cancel_chars, *p) != NULL) { + UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN, + UI_R_COMMON_OK_AND_CANCEL_CHARACTERS); + } + } + + s = general_allocate_prompt(ui, prompt, prompt_freeable, + type, input_flags, result_buf); + + if (s != NULL) { + if (allocate_string_stack(ui) >= 0) { + s->_.boolean_data.action_desc = action_desc; + s->_.boolean_data.ok_chars = ok_chars; + s->_.boolean_data.cancel_chars = cancel_chars; + ret = sk_UI_STRING_push(ui->strings, s); + /* + * sk_push() returns 0 on error. Let's adapt that + */ + if (ret <= 0) { + ret--; + free_string(s); + } + } else + free_string(s); + } + } + return ret; +} + +/* + * Returns the index to the place in the stack or -1 for error. Uses a + * direct reference to the prompt. + */ +int UI_add_input_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize) +{ + return general_allocate_string(ui, prompt, 0, + UIT_PROMPT, flags, result_buf, minsize, + maxsize, NULL); +} + +/* Same as UI_add_input_string(), excepts it takes a copy of the prompt */ +int UI_dup_input_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize) +{ + char *prompt_copy = NULL; + + if (prompt != NULL) { + prompt_copy = OPENSSL_strdup(prompt); + if (prompt_copy == NULL) { + UIerr(UI_F_UI_DUP_INPUT_STRING, ERR_R_MALLOC_FAILURE); + return 0; + } + } + + return general_allocate_string(ui, prompt_copy, 1, + UIT_PROMPT, flags, result_buf, minsize, + maxsize, NULL); +} + +int UI_add_verify_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize, + const char *test_buf) +{ + return general_allocate_string(ui, prompt, 0, + UIT_VERIFY, flags, result_buf, minsize, + maxsize, test_buf); +} + +int UI_dup_verify_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize, + const char *test_buf) +{ + char *prompt_copy = NULL; + + if (prompt != NULL) { + prompt_copy = OPENSSL_strdup(prompt); + if (prompt_copy == NULL) { + UIerr(UI_F_UI_DUP_VERIFY_STRING, ERR_R_MALLOC_FAILURE); + return -1; + } + } + + return general_allocate_string(ui, prompt_copy, 1, + UIT_VERIFY, flags, result_buf, minsize, + maxsize, test_buf); +} + +int UI_add_input_boolean(UI *ui, const char *prompt, const char *action_desc, + const char *ok_chars, const char *cancel_chars, + int flags, char *result_buf) +{ + return general_allocate_boolean(ui, prompt, action_desc, + ok_chars, cancel_chars, 0, UIT_BOOLEAN, + flags, result_buf); +} + +int UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc, + const char *ok_chars, const char *cancel_chars, + int flags, char *result_buf) +{ + char *prompt_copy = NULL; + char *action_desc_copy = NULL; + char *ok_chars_copy = NULL; + char *cancel_chars_copy = NULL; + + if (prompt != NULL) { + prompt_copy = OPENSSL_strdup(prompt); + if (prompt_copy == NULL) { + UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + if (action_desc != NULL) { + action_desc_copy = OPENSSL_strdup(action_desc); + if (action_desc_copy == NULL) { + UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + if (ok_chars != NULL) { + ok_chars_copy = OPENSSL_strdup(ok_chars); + if (ok_chars_copy == NULL) { + UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + if (cancel_chars != NULL) { + cancel_chars_copy = OPENSSL_strdup(cancel_chars); + if (cancel_chars_copy == NULL) { + UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + return general_allocate_boolean(ui, prompt_copy, action_desc_copy, + ok_chars_copy, cancel_chars_copy, 1, + UIT_BOOLEAN, flags, result_buf); + err: + OPENSSL_free(prompt_copy); + OPENSSL_free(action_desc_copy); + OPENSSL_free(ok_chars_copy); + OPENSSL_free(cancel_chars_copy); + return -1; +} + +int UI_add_info_string(UI *ui, const char *text) +{ + return general_allocate_string(ui, text, 0, UIT_INFO, 0, NULL, 0, 0, + NULL); +} + +int UI_dup_info_string(UI *ui, const char *text) +{ + char *text_copy = NULL; + + if (text != NULL) { + text_copy = OPENSSL_strdup(text); + if (text_copy == NULL) { + UIerr(UI_F_UI_DUP_INFO_STRING, ERR_R_MALLOC_FAILURE); + return -1; + } + } + + return general_allocate_string(ui, text_copy, 1, UIT_INFO, 0, NULL, + 0, 0, NULL); +} + +int UI_add_error_string(UI *ui, const char *text) +{ + return general_allocate_string(ui, text, 0, UIT_ERROR, 0, NULL, 0, 0, + NULL); +} + +int UI_dup_error_string(UI *ui, const char *text) +{ + char *text_copy = NULL; + + if (text != NULL) { + text_copy = OPENSSL_strdup(text); + if (text_copy == NULL) { + UIerr(UI_F_UI_DUP_ERROR_STRING, ERR_R_MALLOC_FAILURE); + return -1; + } + } + return general_allocate_string(ui, text_copy, 1, UIT_ERROR, 0, NULL, + 0, 0, NULL); +} + +char *UI_construct_prompt(UI *ui, const char *object_desc, + const char *object_name) +{ + char *prompt = NULL; + + if (ui->meth->ui_construct_prompt != NULL) + prompt = ui->meth->ui_construct_prompt(ui, object_desc, object_name); + else { + char prompt1[] = "Enter "; + char prompt2[] = " for "; + char prompt3[] = ":"; + int len = 0; + + if (object_desc == NULL) + return NULL; + len = sizeof(prompt1) - 1 + strlen(object_desc); + if (object_name != NULL) + len += sizeof(prompt2) - 1 + strlen(object_name); + len += sizeof(prompt3) - 1; + + if ((prompt = OPENSSL_malloc(len + 1)) == NULL) { + UIerr(UI_F_UI_CONSTRUCT_PROMPT, ERR_R_MALLOC_FAILURE); + return NULL; + } + OPENSSL_strlcpy(prompt, prompt1, len + 1); + OPENSSL_strlcat(prompt, object_desc, len + 1); + if (object_name != NULL) { + OPENSSL_strlcat(prompt, prompt2, len + 1); + OPENSSL_strlcat(prompt, object_name, len + 1); + } + OPENSSL_strlcat(prompt, prompt3, len + 1); + } + return prompt; +} + +void *UI_add_user_data(UI *ui, void *user_data) +{ + void *old_data = ui->user_data; + + if ((ui->flags & UI_FLAG_DUPL_DATA) != 0) { + ui->meth->ui_destroy_data(ui, old_data); + old_data = NULL; + } + ui->user_data = user_data; + ui->flags &= ~UI_FLAG_DUPL_DATA; + return old_data; +} + +int UI_dup_user_data(UI *ui, void *user_data) +{ + void *duplicate = NULL; + + if (ui->meth->ui_duplicate_data == NULL + || ui->meth->ui_destroy_data == NULL) { + UIerr(UI_F_UI_DUP_USER_DATA, UI_R_USER_DATA_DUPLICATION_UNSUPPORTED); + return -1; + } + + duplicate = ui->meth->ui_duplicate_data(ui, user_data); + if (duplicate == NULL) { + UIerr(UI_F_UI_DUP_USER_DATA, ERR_R_MALLOC_FAILURE); + return -1; + } + + (void)UI_add_user_data(ui, duplicate); + ui->flags |= UI_FLAG_DUPL_DATA; + + return 0; +} + +void *UI_get0_user_data(UI *ui) +{ + return ui->user_data; +} + +const char *UI_get0_result(UI *ui, int i) +{ + if (i < 0) { + UIerr(UI_F_UI_GET0_RESULT, UI_R_INDEX_TOO_SMALL); + return NULL; + } + if (i >= sk_UI_STRING_num(ui->strings)) { + UIerr(UI_F_UI_GET0_RESULT, UI_R_INDEX_TOO_LARGE); + return NULL; + } + return UI_get0_result_string(sk_UI_STRING_value(ui->strings, i)); +} + +int UI_get_result_length(UI *ui, int i) +{ + if (i < 0) { + UIerr(UI_F_UI_GET_RESULT_LENGTH, UI_R_INDEX_TOO_SMALL); + return -1; + } + if (i >= sk_UI_STRING_num(ui->strings)) { + UIerr(UI_F_UI_GET_RESULT_LENGTH, UI_R_INDEX_TOO_LARGE); + return -1; + } + return UI_get_result_string_length(sk_UI_STRING_value(ui->strings, i)); +} + +static int print_error(const char *str, size_t len, UI *ui) +{ + UI_STRING uis; + + memset(&uis, 0, sizeof(uis)); + uis.type = UIT_ERROR; + uis.out_string = str; + + if (ui->meth->ui_write_string != NULL + && ui->meth->ui_write_string(ui, &uis) <= 0) + return -1; + return 0; +} + +int UI_process(UI *ui) +{ + int i, ok = 0; + const char *state = "processing"; + + if (ui->meth->ui_open_session != NULL + && ui->meth->ui_open_session(ui) <= 0) { + state = "opening session"; + ok = -1; + goto err; + } + + if (ui->flags & UI_FLAG_PRINT_ERRORS) + ERR_print_errors_cb((int (*)(const char *, size_t, void *)) + print_error, (void *)ui); + + for (i = 0; i < sk_UI_STRING_num(ui->strings); i++) { + if (ui->meth->ui_write_string != NULL + && (ui->meth->ui_write_string(ui, + sk_UI_STRING_value(ui->strings, i)) + <= 0)) + { + state = "writing strings"; + ok = -1; + goto err; + } + } + + if (ui->meth->ui_flush != NULL) + switch (ui->meth->ui_flush(ui)) { + case -1: /* Interrupt/Cancel/something... */ + ok = -2; + goto err; + case 0: /* Errors */ + state = "flushing"; + ok = -1; + goto err; + default: /* Success */ + ok = 0; + break; + } + + for (i = 0; i < sk_UI_STRING_num(ui->strings); i++) { + if (ui->meth->ui_read_string != NULL) { + switch (ui->meth->ui_read_string(ui, + sk_UI_STRING_value(ui->strings, + i))) { + case -1: /* Interrupt/Cancel/something... */ + ok = -2; + goto err; + case 0: /* Errors */ + state = "reading strings"; + ok = -1; + goto err; + default: /* Success */ + ok = 0; + break; + } + } + } + + state = NULL; + err: + if (ui->meth->ui_close_session != NULL + && ui->meth->ui_close_session(ui) <= 0) { + if (state == NULL) + state = "closing session"; + ok = -1; + } + + if (ok == -1) { + UIerr(UI_F_UI_PROCESS, UI_R_PROCESSING_ERROR); + ERR_add_error_data(2, "while ", state); + } + return ok; +} + +int UI_ctrl(UI *ui, int cmd, long i, void *p, void (*f) (void)) +{ + if (ui == NULL) { + UIerr(UI_F_UI_CTRL, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + switch (cmd) { + case UI_CTRL_PRINT_ERRORS: + { + int save_flag = ! !(ui->flags & UI_FLAG_PRINT_ERRORS); + if (i) + ui->flags |= UI_FLAG_PRINT_ERRORS; + else + ui->flags &= ~UI_FLAG_PRINT_ERRORS; + return save_flag; + } + case UI_CTRL_IS_REDOABLE: + return ! !(ui->flags & UI_FLAG_REDOABLE); + default: + break; + } + UIerr(UI_F_UI_CTRL, UI_R_UNKNOWN_CONTROL_COMMAND); + return -1; +} + +int UI_set_ex_data(UI *r, int idx, void *arg) +{ + return CRYPTO_set_ex_data(&r->ex_data, idx, arg); +} + +void *UI_get_ex_data(UI *r, int idx) +{ + return CRYPTO_get_ex_data(&r->ex_data, idx); +} + +const UI_METHOD *UI_get_method(UI *ui) +{ + return ui->meth; +} + +const UI_METHOD *UI_set_method(UI *ui, const UI_METHOD *meth) +{ + ui->meth = meth; + return ui->meth; +} + +UI_METHOD *UI_create_method(const char *name) +{ + UI_METHOD *ui_method = NULL; + + if ((ui_method = OPENSSL_zalloc(sizeof(*ui_method))) == NULL + || (ui_method->name = OPENSSL_strdup(name)) == NULL + || !CRYPTO_new_ex_data(CRYPTO_EX_INDEX_UI_METHOD, ui_method, + &ui_method->ex_data)) { + if (ui_method) + OPENSSL_free(ui_method->name); + OPENSSL_free(ui_method); + UIerr(UI_F_UI_CREATE_METHOD, ERR_R_MALLOC_FAILURE); + return NULL; + } + return ui_method; +} + +/* + * BIG FSCKING WARNING!!!! If you use this on a statically allocated method + * (that is, it hasn't been allocated using UI_create_method(), you deserve + * anything Murphy can throw at you and more! You have been warned. + */ +void UI_destroy_method(UI_METHOD *ui_method) +{ + if (ui_method == NULL) + return; + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_UI_METHOD, ui_method, + &ui_method->ex_data); + OPENSSL_free(ui_method->name); + ui_method->name = NULL; + OPENSSL_free(ui_method); +} + +int UI_method_set_opener(UI_METHOD *method, int (*opener) (UI *ui)) +{ + if (method != NULL) { + method->ui_open_session = opener; + return 0; + } + return -1; +} + +int UI_method_set_writer(UI_METHOD *method, + int (*writer) (UI *ui, UI_STRING *uis)) +{ + if (method != NULL) { + method->ui_write_string = writer; + return 0; + } + return -1; +} + +int UI_method_set_flusher(UI_METHOD *method, int (*flusher) (UI *ui)) +{ + if (method != NULL) { + method->ui_flush = flusher; + return 0; + } + return -1; +} + +int UI_method_set_reader(UI_METHOD *method, + int (*reader) (UI *ui, UI_STRING *uis)) +{ + if (method != NULL) { + method->ui_read_string = reader; + return 0; + } + return -1; +} + +int UI_method_set_closer(UI_METHOD *method, int (*closer) (UI *ui)) +{ + if (method != NULL) { + method->ui_close_session = closer; + return 0; + } + return -1; +} + +int UI_method_set_data_duplicator(UI_METHOD *method, + void *(*duplicator) (UI *ui, void *ui_data), + void (*destructor)(UI *ui, void *ui_data)) +{ + if (method != NULL) { + method->ui_duplicate_data = duplicator; + method->ui_destroy_data = destructor; + return 0; + } + return -1; +} + +int UI_method_set_prompt_constructor(UI_METHOD *method, + char *(*prompt_constructor) (UI *ui, + const char + *object_desc, + const char + *object_name)) +{ + if (method != NULL) { + method->ui_construct_prompt = prompt_constructor; + return 0; + } + return -1; +} + +int UI_method_set_ex_data(UI_METHOD *method, int idx, void *data) +{ + return CRYPTO_set_ex_data(&method->ex_data, idx, data); +} + +int (*UI_method_get_opener(const UI_METHOD *method)) (UI *) +{ + if (method != NULL) + return method->ui_open_session; + return NULL; +} + +int (*UI_method_get_writer(const UI_METHOD *method)) (UI *, UI_STRING *) +{ + if (method != NULL) + return method->ui_write_string; + return NULL; +} + +int (*UI_method_get_flusher(const UI_METHOD *method)) (UI *) +{ + if (method != NULL) + return method->ui_flush; + return NULL; +} + +int (*UI_method_get_reader(const UI_METHOD *method)) (UI *, UI_STRING *) +{ + if (method != NULL) + return method->ui_read_string; + return NULL; +} + +int (*UI_method_get_closer(const UI_METHOD *method)) (UI *) +{ + if (method != NULL) + return method->ui_close_session; + return NULL; +} + +char *(*UI_method_get_prompt_constructor(const UI_METHOD *method)) + (UI *, const char *, const char *) +{ + if (method != NULL) + return method->ui_construct_prompt; + return NULL; +} + +void *(*UI_method_get_data_duplicator(const UI_METHOD *method)) (UI *, void *) +{ + if (method != NULL) + return method->ui_duplicate_data; + return NULL; +} + +void (*UI_method_get_data_destructor(const UI_METHOD *method)) (UI *, void *) +{ + if (method != NULL) + return method->ui_destroy_data; + return NULL; +} + +const void *UI_method_get_ex_data(const UI_METHOD *method, int idx) +{ + return CRYPTO_get_ex_data(&method->ex_data, idx); +} + +enum UI_string_types UI_get_string_type(UI_STRING *uis) +{ + return uis->type; +} + +int UI_get_input_flags(UI_STRING *uis) +{ + return uis->input_flags; +} + +const char *UI_get0_output_string(UI_STRING *uis) +{ + return uis->out_string; +} + +const char *UI_get0_action_string(UI_STRING *uis) +{ + switch (uis->type) { + case UIT_BOOLEAN: + return uis->_.boolean_data.action_desc; + case UIT_PROMPT: + case UIT_NONE: + case UIT_VERIFY: + case UIT_INFO: + case UIT_ERROR: + break; + } + return NULL; +} + +const char *UI_get0_result_string(UI_STRING *uis) +{ + switch (uis->type) { + case UIT_PROMPT: + case UIT_VERIFY: + return uis->result_buf; + case UIT_NONE: + case UIT_BOOLEAN: + case UIT_INFO: + case UIT_ERROR: + break; + } + return NULL; +} + +int UI_get_result_string_length(UI_STRING *uis) +{ + switch (uis->type) { + case UIT_PROMPT: + case UIT_VERIFY: + return uis->result_len; + case UIT_NONE: + case UIT_BOOLEAN: + case UIT_INFO: + case UIT_ERROR: + break; + } + return -1; +} + +const char *UI_get0_test_string(UI_STRING *uis) +{ + switch (uis->type) { + case UIT_VERIFY: + return uis->_.string_data.test_buf; + case UIT_NONE: + case UIT_BOOLEAN: + case UIT_INFO: + case UIT_ERROR: + case UIT_PROMPT: + break; + } + return NULL; +} + +int UI_get_result_minsize(UI_STRING *uis) +{ + switch (uis->type) { + case UIT_PROMPT: + case UIT_VERIFY: + return uis->_.string_data.result_minsize; + case UIT_NONE: + case UIT_INFO: + case UIT_ERROR: + case UIT_BOOLEAN: + break; + } + return -1; +} + +int UI_get_result_maxsize(UI_STRING *uis) +{ + switch (uis->type) { + case UIT_PROMPT: + case UIT_VERIFY: + return uis->_.string_data.result_maxsize; + case UIT_NONE: + case UIT_INFO: + case UIT_ERROR: + case UIT_BOOLEAN: + break; + } + return -1; +} + +int UI_set_result(UI *ui, UI_STRING *uis, const char *result) +{ +#if 0 + /* + * This is placed here solely to preserve UI_F_UI_SET_RESULT + * To be removed for OpenSSL 1.2.0 + */ + UIerr(UI_F_UI_SET_RESULT, ERR_R_DISABLED); +#endif + return UI_set_result_ex(ui, uis, result, strlen(result)); +} + +int UI_set_result_ex(UI *ui, UI_STRING *uis, const char *result, int len) +{ + ui->flags &= ~UI_FLAG_REDOABLE; + + switch (uis->type) { + case UIT_PROMPT: + case UIT_VERIFY: + { + char number1[DECIMAL_SIZE(uis->_.string_data.result_minsize) + 1]; + char number2[DECIMAL_SIZE(uis->_.string_data.result_maxsize) + 1]; + + BIO_snprintf(number1, sizeof(number1), "%d", + uis->_.string_data.result_minsize); + BIO_snprintf(number2, sizeof(number2), "%d", + uis->_.string_data.result_maxsize); + + if (len < uis->_.string_data.result_minsize) { + ui->flags |= UI_FLAG_REDOABLE; + UIerr(UI_F_UI_SET_RESULT_EX, UI_R_RESULT_TOO_SMALL); + ERR_add_error_data(5, "You must type in ", + number1, " to ", number2, " characters"); + return -1; + } + if (len > uis->_.string_data.result_maxsize) { + ui->flags |= UI_FLAG_REDOABLE; + UIerr(UI_F_UI_SET_RESULT_EX, UI_R_RESULT_TOO_LARGE); + ERR_add_error_data(5, "You must type in ", + number1, " to ", number2, " characters"); + return -1; + } + } + + if (uis->result_buf == NULL) { + UIerr(UI_F_UI_SET_RESULT_EX, UI_R_NO_RESULT_BUFFER); + return -1; + } + + memcpy(uis->result_buf, result, len); + if (len <= uis->_.string_data.result_maxsize) + uis->result_buf[len] = '\0'; + uis->result_len = len; + break; + case UIT_BOOLEAN: + { + const char *p; + + if (uis->result_buf == NULL) { + UIerr(UI_F_UI_SET_RESULT_EX, UI_R_NO_RESULT_BUFFER); + return -1; + } + + uis->result_buf[0] = '\0'; + for (p = result; *p; p++) { + if (strchr(uis->_.boolean_data.ok_chars, *p)) { + uis->result_buf[0] = uis->_.boolean_data.ok_chars[0]; + break; + } + if (strchr(uis->_.boolean_data.cancel_chars, *p)) { + uis->result_buf[0] = uis->_.boolean_data.cancel_chars[0]; + break; + } + } + } + case UIT_NONE: + case UIT_INFO: + case UIT_ERROR: + break; + } + return 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ui/ui_locl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/ui/ui_locl.h new file mode 100644 index 000000000..19b33b8fc --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ui/ui_locl.h @@ -0,0 +1,109 @@ +/* + * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_UI_LOCL_H +# define HEADER_UI_LOCL_H + +# include +# include + +# ifdef _ +# undef _ +# endif + +struct ui_method_st { + char *name; + /* + * All the functions return 1 or non-NULL for success and 0 or NULL for + * failure + */ + /* + * Open whatever channel for this, be it the console, an X window or + * whatever. This function should use the ex_data structure to save + * intermediate data. + */ + int (*ui_open_session) (UI *ui); + int (*ui_write_string) (UI *ui, UI_STRING *uis); + /* + * Flush the output. If a GUI dialog box is used, this function can be + * used to actually display it. + */ + int (*ui_flush) (UI *ui); + int (*ui_read_string) (UI *ui, UI_STRING *uis); + int (*ui_close_session) (UI *ui); + /* + * Duplicate the ui_data that often comes alongside a ui_method. This + * allows some backends to save away UI information for later use. + */ + void *(*ui_duplicate_data) (UI *ui, void *ui_data); + void (*ui_destroy_data) (UI *ui, void *ui_data); + /* + * Construct a prompt in a user-defined manner. object_desc is a textual + * short description of the object, for example "pass phrase", and + * object_name is the name of the object (might be a card name or a file + * name. The returned string shall always be allocated on the heap with + * OPENSSL_malloc(), and need to be free'd with OPENSSL_free(). + */ + char *(*ui_construct_prompt) (UI *ui, const char *object_desc, + const char *object_name); + /* + * UI_METHOD specific application data. + */ + CRYPTO_EX_DATA ex_data; +}; + +struct ui_string_st { + enum UI_string_types type; /* Input */ + const char *out_string; /* Input */ + int input_flags; /* Flags from the user */ + /* + * The following parameters are completely irrelevant for UIT_INFO, and + * can therefore be set to 0 or NULL + */ + char *result_buf; /* Input and Output: If not NULL, + * user-defined with size in result_maxsize. + * Otherwise, it may be allocated by the UI + * routine, meaning result_minsize is going + * to be overwritten. */ + size_t result_len; + union { + struct { + int result_minsize; /* Input: minimum required size of the + * result. */ + int result_maxsize; /* Input: maximum permitted size of the + * result */ + const char *test_buf; /* Input: test string to verify against */ + } string_data; + struct { + const char *action_desc; /* Input */ + const char *ok_chars; /* Input */ + const char *cancel_chars; /* Input */ + } boolean_data; + } _; + +# define OUT_STRING_FREEABLE 0x01 + int flags; /* flags for internal use */ +}; + +struct ui_st { + const UI_METHOD *meth; + STACK_OF(UI_STRING) *strings; /* We might want to prompt for more than + * one thing at a time, and with different + * echoing status. */ + void *user_data; + CRYPTO_EX_DATA ex_data; +# define UI_FLAG_REDOABLE 0x0001 +# define UI_FLAG_DUPL_DATA 0x0002 /* user_data was duplicated */ +# define UI_FLAG_PRINT_ERRORS 0x0100 + int flags; + + CRYPTO_RWLOCK *lock; +}; + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ui/ui_null.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ui/ui_null.c new file mode 100644 index 000000000..9e5f6fca5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ui/ui_null.c @@ -0,0 +1,26 @@ +/* + * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "ui_locl.h" + +static const UI_METHOD ui_null = { + "OpenSSL NULL UI", + NULL, /* opener */ + NULL, /* writer */ + NULL, /* flusher */ + NULL, /* reader */ + NULL, /* closer */ + NULL +}; + +/* The method with all the built-in thingies */ +const UI_METHOD *UI_null(void) +{ + return &ui_null; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ui/ui_openssl.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ui/ui_openssl.c new file mode 100644 index 000000000..5ca418d24 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ui/ui_openssl.c @@ -0,0 +1,744 @@ +/* + * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "e_os.h" +#include +#include +#include + +#ifndef OPENSSL_NO_UI_CONSOLE +/* + * need for #define _POSIX_C_SOURCE arises whenever you pass -ansi to gcc + * [maybe others?], because it masks interfaces not discussed in standard, + * sigaction and fileno included. -pedantic would be more appropriate for the + * intended purposes, but we can't prevent users from adding -ansi. + */ +# if defined(OPENSSL_SYS_VXWORKS) +# include +# endif + +# if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS) +# ifndef _POSIX_C_SOURCE +# define _POSIX_C_SOURCE 2 +# endif +# endif +# include +# include +# include +# include + +# if !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS) +# ifdef OPENSSL_UNISTD +# include OPENSSL_UNISTD +# else +# include +# endif +/* + * If unistd.h defines _POSIX_VERSION, we conclude that we are on a POSIX + * system and have sigaction and termios. + */ +# if defined(_POSIX_VERSION) && _POSIX_VERSION>=199309L + +# define SIGACTION +# if !defined(TERMIOS) && !defined(TERMIO) && !defined(SGTTY) +# define TERMIOS +# endif + +# endif +# endif + +# include "ui_locl.h" +# include "internal/cryptlib.h" + +# ifdef OPENSSL_SYS_VMS /* prototypes for sys$whatever */ +# include +# ifdef __DECC +# pragma message disable DOLLARID +# endif +# endif + +# ifdef WIN_CONSOLE_BUG +# include +# ifndef OPENSSL_SYS_WINCE +# include +# endif +# endif + +/* + * There are 6 types of terminal interface supported, TERMIO, TERMIOS, VMS, + * MSDOS, WIN32 Console and SGTTY. + * + * If someone defines one of the macros TERMIO, TERMIOS or SGTTY, it will + * remain respected. Otherwise, we default to TERMIOS except for a few + * systems that require something different. + * + * Note: we do not use SGTTY unless it's defined by the configuration. We + * may eventually opt to remove it's use entirely. + */ + +# if !defined(TERMIOS) && !defined(TERMIO) && !defined(SGTTY) + +# if defined(_LIBC) +# undef TERMIOS +# define TERMIO +# undef SGTTY +/* + * We know that VMS, MSDOS, VXWORKS, use entirely other mechanisms. + */ +# elif !defined(OPENSSL_SYS_VMS) \ + && !defined(OPENSSL_SYS_MSDOS) \ + && !defined(OPENSSL_SYS_VXWORKS) +# define TERMIOS +# undef TERMIO +# undef SGTTY +# endif + +# endif + +# if defined(OPENSSL_SYS_VXWORKS) +# undef TERMIOS +# undef TERMIO +# undef SGTTY +# endif + +# ifdef TERMIOS +# include +# define TTY_STRUCT struct termios +# define TTY_FLAGS c_lflag +# define TTY_get(tty,data) tcgetattr(tty,data) +# define TTY_set(tty,data) tcsetattr(tty,TCSANOW,data) +# endif + +# ifdef TERMIO +# include +# define TTY_STRUCT struct termio +# define TTY_FLAGS c_lflag +# define TTY_get(tty,data) ioctl(tty,TCGETA,data) +# define TTY_set(tty,data) ioctl(tty,TCSETA,data) +# endif + +# ifdef SGTTY +# include +# define TTY_STRUCT struct sgttyb +# define TTY_FLAGS sg_flags +# define TTY_get(tty,data) ioctl(tty,TIOCGETP,data) +# define TTY_set(tty,data) ioctl(tty,TIOCSETP,data) +# endif + +# if !defined(_LIBC) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS) +# include +# endif + +# ifdef OPENSSL_SYS_MSDOS +# include +# endif + +# ifdef OPENSSL_SYS_VMS +# include +# include +# include +# include +struct IOSB { + short iosb$w_value; + short iosb$w_count; + long iosb$l_info; +}; +# endif + +# ifndef NX509_SIG +# define NX509_SIG 32 +# endif + +/* Define globals. They are protected by a lock */ +# ifdef SIGACTION +static struct sigaction savsig[NX509_SIG]; +# else +static void (*savsig[NX509_SIG]) (int); +# endif + +# ifdef OPENSSL_SYS_VMS +static struct IOSB iosb; +static $DESCRIPTOR(terminal, "TT"); +static long tty_orig[3], tty_new[3]; /* XXX Is there any guarantee that this + * will always suffice for the actual + * structures? */ +static long status; +static unsigned short channel = 0; +# elif defined(_WIN32) && !defined(_WIN32_WCE) +static DWORD tty_orig, tty_new; +# else +# if !defined(OPENSSL_SYS_MSDOS) || defined(__DJGPP__) +static TTY_STRUCT tty_orig, tty_new; +# endif +# endif +static FILE *tty_in, *tty_out; +static int is_a_tty; + +/* Declare static functions */ +# if !defined(OPENSSL_SYS_WINCE) +static int read_till_nl(FILE *); +static void recsig(int); +static void pushsig(void); +static void popsig(void); +# endif +# if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32) +static int noecho_fgets(char *buf, int size, FILE *tty); +# endif +static int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl); + +static int read_string(UI *ui, UI_STRING *uis); +static int write_string(UI *ui, UI_STRING *uis); + +static int open_console(UI *ui); +static int echo_console(UI *ui); +static int noecho_console(UI *ui); +static int close_console(UI *ui); + +/* + * The following function makes sure that info and error strings are printed + * before any prompt. + */ +static int write_string(UI *ui, UI_STRING *uis) +{ + switch (UI_get_string_type(uis)) { + case UIT_ERROR: + case UIT_INFO: + fputs(UI_get0_output_string(uis), tty_out); + fflush(tty_out); + break; + case UIT_NONE: + case UIT_PROMPT: + case UIT_VERIFY: + case UIT_BOOLEAN: + break; + } + return 1; +} + +static int read_string(UI *ui, UI_STRING *uis) +{ + int ok = 0; + + switch (UI_get_string_type(uis)) { + case UIT_BOOLEAN: + fputs(UI_get0_output_string(uis), tty_out); + fputs(UI_get0_action_string(uis), tty_out); + fflush(tty_out); + return read_string_inner(ui, uis, + UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO, + 0); + case UIT_PROMPT: + fputs(UI_get0_output_string(uis), tty_out); + fflush(tty_out); + return read_string_inner(ui, uis, + UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO, + 1); + case UIT_VERIFY: + fprintf(tty_out, "Verifying - %s", UI_get0_output_string(uis)); + fflush(tty_out); + if ((ok = read_string_inner(ui, uis, + UI_get_input_flags(uis) & + UI_INPUT_FLAG_ECHO, 1)) <= 0) + return ok; + if (strcmp(UI_get0_result_string(uis), UI_get0_test_string(uis)) != 0) { + fprintf(tty_out, "Verify failure\n"); + fflush(tty_out); + return 0; + } + break; + case UIT_NONE: + case UIT_INFO: + case UIT_ERROR: + break; + } + return 1; +} + +# if !defined(OPENSSL_SYS_WINCE) +/* Internal functions to read a string without echoing */ +static int read_till_nl(FILE *in) +{ +# define SIZE 4 + char buf[SIZE + 1]; + + do { + if (!fgets(buf, SIZE, in)) + return 0; + } while (strchr(buf, '\n') == NULL); + return 1; +} + +static volatile sig_atomic_t intr_signal; +# endif + +static int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl) +{ + static int ps; + int ok; + char result[BUFSIZ]; + int maxsize = BUFSIZ - 1; +# if !defined(OPENSSL_SYS_WINCE) + char *p = NULL; + int echo_eol = !echo; + + intr_signal = 0; + ok = 0; + ps = 0; + + pushsig(); + ps = 1; + + if (!echo && !noecho_console(ui)) + goto error; + ps = 2; + + result[0] = '\0'; +# if defined(_WIN32) + if (is_a_tty) { + DWORD numread; +# if defined(CP_UTF8) + if (GetEnvironmentVariableW(L"OPENSSL_WIN32_UTF8", NULL, 0) != 0) { + WCHAR wresult[BUFSIZ]; + + if (ReadConsoleW(GetStdHandle(STD_INPUT_HANDLE), + wresult, maxsize, &numread, NULL)) { + if (numread >= 2 && + wresult[numread-2] == L'\r' && + wresult[numread-1] == L'\n') { + wresult[numread-2] = L'\n'; + numread--; + } + wresult[numread] = '\0'; + if (WideCharToMultiByte(CP_UTF8, 0, wresult, -1, + result, sizeof(result), NULL, 0) > 0) + p = result; + + OPENSSL_cleanse(wresult, sizeof(wresult)); + } + } else +# endif + if (ReadConsoleA(GetStdHandle(STD_INPUT_HANDLE), + result, maxsize, &numread, NULL)) { + if (numread >= 2 && + result[numread-2] == '\r' && result[numread-1] == '\n') { + result[numread-2] = '\n'; + numread--; + } + result[numread] = '\0'; + p = result; + } + } else +# elif defined(OPENSSL_SYS_MSDOS) + if (!echo) { + noecho_fgets(result, maxsize, tty_in); + p = result; /* FIXME: noecho_fgets doesn't return errors */ + } else +# endif + p = fgets(result, maxsize, tty_in); + if (p == NULL) + goto error; + if (feof(tty_in)) + goto error; + if (ferror(tty_in)) + goto error; + if ((p = (char *)strchr(result, '\n')) != NULL) { + if (strip_nl) + *p = '\0'; + } else if (!read_till_nl(tty_in)) + goto error; + if (UI_set_result(ui, uis, result) >= 0) + ok = 1; + + error: + if (intr_signal == SIGINT) + ok = -1; + if (echo_eol) + fprintf(tty_out, "\n"); + if (ps >= 2 && !echo && !echo_console(ui)) + ok = 0; + + if (ps >= 1) + popsig(); +# else + ok = 1; +# endif + + OPENSSL_cleanse(result, BUFSIZ); + return ok; +} + +/* Internal functions to open, handle and close a channel to the console. */ +static int open_console(UI *ui) +{ + CRYPTO_THREAD_write_lock(ui->lock); + is_a_tty = 1; + +# if defined(OPENSSL_SYS_VXWORKS) + tty_in = stdin; + tty_out = stderr; +# elif defined(_WIN32) && !defined(_WIN32_WCE) + if ((tty_out = fopen("conout$", "w")) == NULL) + tty_out = stderr; + + if (GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &tty_orig)) { + tty_in = stdin; + } else { + is_a_tty = 0; + if ((tty_in = fopen("conin$", "r")) == NULL) + tty_in = stdin; + } +# else +# ifdef OPENSSL_SYS_MSDOS +# define DEV_TTY "con" +# else +# define DEV_TTY "/dev/tty" +# endif + if ((tty_in = fopen(DEV_TTY, "r")) == NULL) + tty_in = stdin; + if ((tty_out = fopen(DEV_TTY, "w")) == NULL) + tty_out = stderr; +# endif + +# if defined(TTY_get) && !defined(OPENSSL_SYS_VMS) + if (TTY_get(fileno(tty_in), &tty_orig) == -1) { +# ifdef ENOTTY + if (errno == ENOTTY) + is_a_tty = 0; + else +# endif +# ifdef EINVAL + /* + * Ariel Glenn reports that solaris can return EINVAL instead. + * This should be ok + */ + if (errno == EINVAL) + is_a_tty = 0; + else +# endif +# ifdef ENXIO + /* + * Solaris can return ENXIO. + * This should be ok + */ + if (errno == ENXIO) + is_a_tty = 0; + else +# endif +# ifdef EIO + /* + * Linux can return EIO. + * This should be ok + */ + if (errno == EIO) + is_a_tty = 0; + else +# endif +# ifdef ENODEV + /* + * MacOS X returns ENODEV (Operation not supported by device), + * which seems appropriate. + */ + if (errno == ENODEV) + is_a_tty = 0; + else +# endif + { + char tmp_num[10]; + BIO_snprintf(tmp_num, sizeof(tmp_num) - 1, "%d", errno); + UIerr(UI_F_OPEN_CONSOLE, UI_R_UNKNOWN_TTYGET_ERRNO_VALUE); + ERR_add_error_data(2, "errno=", tmp_num); + + return 0; + } + } +# endif +# ifdef OPENSSL_SYS_VMS + status = sys$assign(&terminal, &channel, 0, 0); + + /* if there isn't a TT device, something is very wrong */ + if (status != SS$_NORMAL) { + char tmp_num[12]; + + BIO_snprintf(tmp_num, sizeof(tmp_num) - 1, "%%X%08X", status); + UIerr(UI_F_OPEN_CONSOLE, UI_R_SYSASSIGN_ERROR); + ERR_add_error_data(2, "status=", tmp_num); + return 0; + } + + status = sys$qiow(0, channel, IO$_SENSEMODE, &iosb, 0, 0, tty_orig, 12, + 0, 0, 0, 0); + + /* If IO$_SENSEMODE doesn't work, this is not a terminal device */ + if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) + is_a_tty = 0; +# endif + return 1; +} + +static int noecho_console(UI *ui) +{ +# ifdef TTY_FLAGS + memcpy(&(tty_new), &(tty_orig), sizeof(tty_orig)); + tty_new.TTY_FLAGS &= ~ECHO; +# endif + +# if defined(TTY_set) && !defined(OPENSSL_SYS_VMS) + if (is_a_tty && (TTY_set(fileno(tty_in), &tty_new) == -1)) + return 0; +# endif +# ifdef OPENSSL_SYS_VMS + if (is_a_tty) { + tty_new[0] = tty_orig[0]; + tty_new[1] = tty_orig[1] | TT$M_NOECHO; + tty_new[2] = tty_orig[2]; + status = sys$qiow(0, channel, IO$_SETMODE, &iosb, 0, 0, tty_new, 12, + 0, 0, 0, 0); + if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) { + char tmp_num[2][12]; + + BIO_snprintf(tmp_num[0], sizeof(tmp_num[0]) - 1, "%%X%08X", + status); + BIO_snprintf(tmp_num[1], sizeof(tmp_num[1]) - 1, "%%X%08X", + iosb.iosb$w_value); + UIerr(UI_F_NOECHO_CONSOLE, UI_R_SYSQIOW_ERROR); + ERR_add_error_data(5, "status=", tmp_num[0], + ",", "iosb.iosb$w_value=", tmp_num[1]); + return 0; + } + } +# endif +# if defined(_WIN32) && !defined(_WIN32_WCE) + if (is_a_tty) { + tty_new = tty_orig; + tty_new &= ~ENABLE_ECHO_INPUT; + SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), tty_new); + } +# endif + return 1; +} + +static int echo_console(UI *ui) +{ +# if defined(TTY_set) && !defined(OPENSSL_SYS_VMS) + memcpy(&(tty_new), &(tty_orig), sizeof(tty_orig)); + if (is_a_tty && (TTY_set(fileno(tty_in), &tty_new) == -1)) + return 0; +# endif +# ifdef OPENSSL_SYS_VMS + if (is_a_tty) { + tty_new[0] = tty_orig[0]; + tty_new[1] = tty_orig[1]; + tty_new[2] = tty_orig[2]; + status = sys$qiow(0, channel, IO$_SETMODE, &iosb, 0, 0, tty_new, 12, + 0, 0, 0, 0); + if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) { + char tmp_num[2][12]; + + BIO_snprintf(tmp_num[0], sizeof(tmp_num[0]) - 1, "%%X%08X", + status); + BIO_snprintf(tmp_num[1], sizeof(tmp_num[1]) - 1, "%%X%08X", + iosb.iosb$w_value); + UIerr(UI_F_ECHO_CONSOLE, UI_R_SYSQIOW_ERROR); + ERR_add_error_data(5, "status=", tmp_num[0], + ",", "iosb.iosb$w_value=", tmp_num[1]); + return 0; + } + } +# endif +# if defined(_WIN32) && !defined(_WIN32_WCE) + if (is_a_tty) { + tty_new = tty_orig; + SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), tty_new); + } +# endif + return 1; +} + +static int close_console(UI *ui) +{ + if (tty_in != stdin) + fclose(tty_in); + if (tty_out != stderr) + fclose(tty_out); +# ifdef OPENSSL_SYS_VMS + status = sys$dassgn(channel); + if (status != SS$_NORMAL) { + char tmp_num[12]; + + BIO_snprintf(tmp_num, sizeof(tmp_num) - 1, "%%X%08X", status); + UIerr(UI_F_CLOSE_CONSOLE, UI_R_SYSDASSGN_ERROR); + ERR_add_error_data(2, "status=", tmp_num); + return 0; + } +# endif + CRYPTO_THREAD_unlock(ui->lock); + + return 1; +} + +# if !defined(OPENSSL_SYS_WINCE) +/* Internal functions to handle signals and act on them */ +static void pushsig(void) +{ +# ifndef OPENSSL_SYS_WIN32 + int i; +# endif +# ifdef SIGACTION + struct sigaction sa; + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = recsig; +# endif + +# ifdef OPENSSL_SYS_WIN32 + savsig[SIGABRT] = signal(SIGABRT, recsig); + savsig[SIGFPE] = signal(SIGFPE, recsig); + savsig[SIGILL] = signal(SIGILL, recsig); + savsig[SIGINT] = signal(SIGINT, recsig); + savsig[SIGSEGV] = signal(SIGSEGV, recsig); + savsig[SIGTERM] = signal(SIGTERM, recsig); +# else + for (i = 1; i < NX509_SIG; i++) { +# ifdef SIGUSR1 + if (i == SIGUSR1) + continue; +# endif +# ifdef SIGUSR2 + if (i == SIGUSR2) + continue; +# endif +# ifdef SIGKILL + if (i == SIGKILL) /* We can't make any action on that. */ + continue; +# endif +# ifdef SIGACTION + sigaction(i, &sa, &savsig[i]); +# else + savsig[i] = signal(i, recsig); +# endif + } +# endif + +# ifdef SIGWINCH + signal(SIGWINCH, SIG_DFL); +# endif +} + +static void popsig(void) +{ +# ifdef OPENSSL_SYS_WIN32 + signal(SIGABRT, savsig[SIGABRT]); + signal(SIGFPE, savsig[SIGFPE]); + signal(SIGILL, savsig[SIGILL]); + signal(SIGINT, savsig[SIGINT]); + signal(SIGSEGV, savsig[SIGSEGV]); + signal(SIGTERM, savsig[SIGTERM]); +# else + int i; + for (i = 1; i < NX509_SIG; i++) { +# ifdef SIGUSR1 + if (i == SIGUSR1) + continue; +# endif +# ifdef SIGUSR2 + if (i == SIGUSR2) + continue; +# endif +# ifdef SIGACTION + sigaction(i, &savsig[i], NULL); +# else + signal(i, savsig[i]); +# endif + } +# endif +} + +static void recsig(int i) +{ + intr_signal = i; +} +# endif + +/* Internal functions specific for Windows */ +# if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32) +static int noecho_fgets(char *buf, int size, FILE *tty) +{ + int i; + char *p; + + p = buf; + for (;;) { + if (size == 0) { + *p = '\0'; + break; + } + size--; +# if defined(_WIN32) + i = _getch(); +# else + i = getch(); +# endif + if (i == '\r') + i = '\n'; + *(p++) = i; + if (i == '\n') { + *p = '\0'; + break; + } + } +# ifdef WIN_CONSOLE_BUG + /* + * Win95 has several evil console bugs: one of these is that the last + * character read using getch() is passed to the next read: this is + * usually a CR so this can be trouble. No STDIO fix seems to work but + * flushing the console appears to do the trick. + */ + { + HANDLE inh; + inh = GetStdHandle(STD_INPUT_HANDLE); + FlushConsoleInputBuffer(inh); + } +# endif + return strlen(buf); +} +# endif + +static UI_METHOD ui_openssl = { + "OpenSSL default user interface", + open_console, + write_string, + NULL, /* No flusher is needed for command lines */ + read_string, + close_console, + NULL +}; + +/* The method with all the built-in console thingies */ +UI_METHOD *UI_OpenSSL(void) +{ + return &ui_openssl; +} + +static const UI_METHOD *default_UI_meth = &ui_openssl; + +#else + +static const UI_METHOD *default_UI_meth = NULL; + +#endif + +void UI_set_default_method(const UI_METHOD *meth) +{ + default_UI_meth = meth; +} + +const UI_METHOD *UI_get_default_method(void) +{ + return default_UI_meth; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/ui/ui_util.c b/trunk/3rdparty/openssl-1.1-fit/crypto/ui/ui_util.c new file mode 100644 index 000000000..b379324f9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/ui/ui_util.c @@ -0,0 +1,162 @@ +/* + * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/thread_once.h" +#include "ui_locl.h" + +#ifndef BUFSIZ +#define BUFSIZ 256 +#endif + +int UI_UTIL_read_pw_string(char *buf, int length, const char *prompt, + int verify) +{ + char buff[BUFSIZ]; + int ret; + + ret = + UI_UTIL_read_pw(buf, buff, (length > BUFSIZ) ? BUFSIZ : length, + prompt, verify); + OPENSSL_cleanse(buff, BUFSIZ); + return ret; +} + +int UI_UTIL_read_pw(char *buf, char *buff, int size, const char *prompt, + int verify) +{ + int ok = 0; + UI *ui; + + if (size < 1) + return -1; + + ui = UI_new(); + if (ui != NULL) { + ok = UI_add_input_string(ui, prompt, 0, buf, 0, size - 1); + if (ok >= 0 && verify) + ok = UI_add_verify_string(ui, prompt, 0, buff, 0, size - 1, buf); + if (ok >= 0) + ok = UI_process(ui); + UI_free(ui); + } + if (ok > 0) + ok = 0; + return ok; +} + +/* + * Wrapper around pem_password_cb, a method to help older APIs use newer + * ones. + */ +struct pem_password_cb_data { + pem_password_cb *cb; + int rwflag; +}; + +static void ui_new_method_data(void *parent, void *ptr, CRYPTO_EX_DATA *ad, + int idx, long argl, void *argp) +{ + /* + * Do nothing, the data is allocated externally and assigned later with + * CRYPTO_set_ex_data() + */ +} + +static int ui_dup_method_data(CRYPTO_EX_DATA *to, const CRYPTO_EX_DATA *from, + void *from_d, int idx, long argl, void *argp) +{ + void **pptr = (void **)from_d; + if (*pptr != NULL) + *pptr = OPENSSL_memdup(*pptr, sizeof(struct pem_password_cb_data)); + return 1; +} + +static void ui_free_method_data(void *parent, void *ptr, CRYPTO_EX_DATA *ad, + int idx, long argl, void *argp) +{ + OPENSSL_free(ptr); +} + +static CRYPTO_ONCE get_index_once = CRYPTO_ONCE_STATIC_INIT; +static int ui_method_data_index = -1; +DEFINE_RUN_ONCE_STATIC(ui_method_data_index_init) +{ + ui_method_data_index = CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_UI_METHOD, + 0, NULL, ui_new_method_data, + ui_dup_method_data, + ui_free_method_data); + return 1; +} + +static int ui_open(UI *ui) +{ + return 1; +} +static int ui_read(UI *ui, UI_STRING *uis) +{ + switch (UI_get_string_type(uis)) { + case UIT_PROMPT: + { + char result[PEM_BUFSIZE + 1]; + const struct pem_password_cb_data *data = + UI_method_get_ex_data(UI_get_method(ui), ui_method_data_index); + int maxsize = UI_get_result_maxsize(uis); + int len = data->cb(result, + maxsize > PEM_BUFSIZE ? PEM_BUFSIZE : maxsize, + data->rwflag, UI_get0_user_data(ui)); + + if (len >= 0) + result[len] = '\0'; + if (len <= 0) + return len; + if (UI_set_result_ex(ui, uis, result, len) >= 0) + return 1; + return 0; + } + case UIT_VERIFY: + case UIT_NONE: + case UIT_BOOLEAN: + case UIT_INFO: + case UIT_ERROR: + break; + } + return 1; +} +static int ui_write(UI *ui, UI_STRING *uis) +{ + return 1; +} +static int ui_close(UI *ui) +{ + return 1; +} + +UI_METHOD *UI_UTIL_wrap_read_pem_callback(pem_password_cb *cb, int rwflag) +{ + struct pem_password_cb_data *data = NULL; + UI_METHOD *ui_method = NULL; + + if ((data = OPENSSL_zalloc(sizeof(*data))) == NULL + || (ui_method = UI_create_method("PEM password callback wrapper")) == NULL + || UI_method_set_opener(ui_method, ui_open) < 0 + || UI_method_set_reader(ui_method, ui_read) < 0 + || UI_method_set_writer(ui_method, ui_write) < 0 + || UI_method_set_closer(ui_method, ui_close) < 0 + || !RUN_ONCE(&get_index_once, ui_method_data_index_init) + || UI_method_set_ex_data(ui_method, ui_method_data_index, data) < 0) { + UI_destroy_method(ui_method); + OPENSSL_free(data); + return NULL; + } + data->rwflag = rwflag; + data->cb = cb; + + return ui_method; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/uid.c b/trunk/3rdparty/openssl-1.1-fit/crypto/uid.c new file mode 100644 index 000000000..b2b096446 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/uid.c @@ -0,0 +1,49 @@ +/* + * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#if defined(__OpenBSD__) || (defined(__FreeBSD__) && __FreeBSD__ > 2) || defined(__DragonFly__) + +# include OPENSSL_UNISTD + +int OPENSSL_issetugid(void) +{ + return issetugid(); +} + +#elif defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI) + +int OPENSSL_issetugid(void) +{ + return 0; +} + +#else + +# include OPENSSL_UNISTD +# include + +# if defined(__GLIBC__) && defined(__GLIBC_PREREQ) +# if __GLIBC_PREREQ(2, 16) +# include +# define OSSL_IMPLEMENT_GETAUXVAL +# endif +# endif + +int OPENSSL_issetugid(void) +{ +# ifdef OSSL_IMPLEMENT_GETAUXVAL + return getauxval(AT_SECURE) != 0; +# else + return getuid() != geteuid() || getgid() != getegid(); +# endif +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/vms_rms.h b/trunk/3rdparty/openssl-1.1-fit/crypto/vms_rms.h new file mode 100644 index 000000000..3b994a0ab --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/vms_rms.h @@ -0,0 +1,58 @@ +/* + * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifdef NAML$C_MAXRSS + +# define CC_RMS_NAMX cc$rms_naml +# define FAB_NAMX fab$l_naml +# define FAB_OR_NAML( fab, naml) naml +# define FAB_OR_NAML_DNA naml$l_long_defname +# define FAB_OR_NAML_DNS naml$l_long_defname_size +# define FAB_OR_NAML_FNA naml$l_long_filename +# define FAB_OR_NAML_FNS naml$l_long_filename_size +# define NAMX_ESA naml$l_long_expand +# define NAMX_ESL naml$l_long_expand_size +# define NAMX_ESS naml$l_long_expand_alloc +# define NAMX_NOP naml$b_nop +# define SET_NAMX_NO_SHORT_UPCASE( nam) nam.naml$v_no_short_upcase = 1 + +# if __INITIAL_POINTER_SIZE == 64 +# define NAMX_DNA_FNA_SET(fab) fab.fab$l_dna = (__char_ptr32) -1; \ + fab.fab$l_fna = (__char_ptr32) -1; +# else /* __INITIAL_POINTER_SIZE == 64 */ +# define NAMX_DNA_FNA_SET(fab) fab.fab$l_dna = (char *) -1; \ + fab.fab$l_fna = (char *) -1; +# endif /* __INITIAL_POINTER_SIZE == 64 [else] */ + +# define NAMX_MAXRSS NAML$C_MAXRSS +# define NAMX_STRUCT NAML + +#else /* def NAML$C_MAXRSS */ + +# define CC_RMS_NAMX cc$rms_nam +# define FAB_NAMX fab$l_nam +# define FAB_OR_NAML( fab, naml) fab +# define FAB_OR_NAML_DNA fab$l_dna +# define FAB_OR_NAML_DNS fab$b_dns +# define FAB_OR_NAML_FNA fab$l_fna +# define FAB_OR_NAML_FNS fab$b_fns +# define NAMX_ESA nam$l_esa +# define NAMX_ESL nam$b_esl +# define NAMX_ESS nam$b_ess +# define NAMX_NOP nam$b_nop +# define NAMX_DNA_FNA_SET(fab) +# define NAMX_MAXRSS NAM$C_MAXRSS +# define NAMX_STRUCT NAM +# ifdef NAM$M_NO_SHORT_UPCASE +# define SET_NAMX_NO_SHORT_UPCASE( nam) naml.naml$v_no_short_upcase = 1 +# else /* def NAM$M_NO_SHORT_UPCASE */ +# define SET_NAMX_NO_SHORT_UPCASE( nam) +# endif /* def NAM$M_NO_SHORT_UPCASE [else] */ + +#endif /* def NAML$C_MAXRSS [else] */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/whrlpool/asm/wp-mmx.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/whrlpool/asm/wp-mmx.pl new file mode 100644 index 000000000..2241c6f0f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/whrlpool/asm/wp-mmx.pl @@ -0,0 +1,507 @@ +#! /usr/bin/env perl +# Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. Rights for redistribution and usage in source and binary +# forms are granted according to the OpenSSL license. +# ==================================================================== +# +# whirlpool_block_mmx implementation. +# +*SCALE=\(2); # 2 or 8, that is the question:-) Value of 8 results +# in 16KB large table, which is tough on L1 cache, but eliminates +# unaligned references to it. Value of 2 results in 4KB table, but +# 7/8 of references to it are unaligned. AMD cores seem to be +# allergic to the latter, while Intel ones - to former [see the +# table]. I stick to value of 2 for two reasons: 1. smaller table +# minimizes cache trashing and thus mitigates the hazard of side- +# channel leakage similar to AES cache-timing one; 2. performance +# gap among different µ-archs is smaller. +# +# Performance table lists rounded amounts of CPU cycles spent by +# whirlpool_block_mmx routine on single 64 byte input block, i.e. +# smaller is better and asymptotic throughput can be estimated by +# multiplying 64 by CPU clock frequency and dividing by relevant +# value from the given table: +# +# $SCALE=2/8 icc8 gcc3 +# Intel P4 3200/4600 4600(*) 6400 +# Intel PIII 2900/3000 4900 5400 +# AMD K[78] 2500/1800 9900 8200(**) +# +# (*) I've sketched even non-MMX assembler, but for the record +# I've failed to beat the Intel compiler on P4, without using +# MMX that is... +# (**) ... on AMD on the other hand non-MMX assembler was observed +# to perform significantly better, but I figured this MMX +# implementation is even faster anyway, so why bother? As for +# pre-MMX AMD core[s], the improvement coefficient is more +# than likely to vary anyway and I don't know how. But the +# least I know is that gcc-generated code compiled with +# -DL_ENDIAN and -DOPENSSL_SMALL_FOOTPRINT [see C module for +# details] and optimized for Pentium was observed to perform +# *better* on Pentium 100 than unrolled non-MMX assembler +# loop... So we just say that I don't know if maintaining +# non-MMX implementation would actually pay off, but till +# opposite is proved "unlikely" is assumed. + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +$output=pop; +open STDOUT,">$output"; + +&asm_init($ARGV[0]); + +sub L() { &data_byte(@_); } +sub LL() +{ if ($SCALE==2) { &data_byte(@_); &data_byte(@_); } + elsif ($SCALE==8) { for ($i=0;$i<8;$i++) { + &data_byte(@_); + unshift(@_,pop(@_)); + } + } + else { die "unvalid SCALE value"; } +} + +sub scale() +{ if ($SCALE==2) { &lea(@_[0],&DWP(0,@_[1],@_[1])); } + elsif ($SCALE==8) { &lea(@_[0],&DWP(0,"",@_[1],8)); } + else { die "unvalid SCALE value"; } +} + +sub row() +{ if ($SCALE==2) { ((8-shift)&7); } + elsif ($SCALE==8) { (8*shift); } + else { die "unvalid SCALE value"; } +} + +$tbl="ebp"; +@mm=("mm0","mm1","mm2","mm3","mm4","mm5","mm6","mm7"); + +&function_begin_B("whirlpool_block_mmx"); + &push ("ebp"); + &push ("ebx"); + &push ("esi"); + &push ("edi"); + + &mov ("esi",&wparam(0)); # hash value + &mov ("edi",&wparam(1)); # input data stream + &mov ("ebp",&wparam(2)); # number of chunks in input + + &mov ("eax","esp"); # copy stack pointer + &sub ("esp",128+20); # allocate frame + &and ("esp",-64); # align for cache-line + + &lea ("ebx",&DWP(128,"esp")); + &mov (&DWP(0,"ebx"),"esi"); # save parameter block + &mov (&DWP(4,"ebx"),"edi"); + &mov (&DWP(8,"ebx"),"ebp"); + &mov (&DWP(16,"ebx"),"eax"); # saved stack pointer + + &call (&label("pic_point")); +&set_label("pic_point"); + &blindpop($tbl); + &lea ($tbl,&DWP(&label("table")."-".&label("pic_point"),$tbl)); + + &xor ("ecx","ecx"); + &xor ("edx","edx"); + + for($i=0;$i<8;$i++) { &movq(@mm[$i],&QWP($i*8,"esi")); } # L=H +&set_label("outerloop"); + for($i=0;$i<8;$i++) { &movq(&QWP($i*8,"esp"),@mm[$i]); } # K=L + for($i=0;$i<8;$i++) { &pxor(@mm[$i],&QWP($i*8,"edi")); } # L^=inp + for($i=0;$i<8;$i++) { &movq(&QWP(64+$i*8,"esp"),@mm[$i]); } # S=L + + &xor ("esi","esi"); + &mov (&DWP(12,"ebx"),"esi"); # zero round counter + +&set_label("round",16); + &movq (@mm[0],&QWP(2048*$SCALE,$tbl,"esi",8)); # rc[r] + &mov ("eax",&DWP(0,"esp")); + &mov ("ebx",&DWP(4,"esp")); + &movz ("ecx",&LB("eax")); + &movz ("edx",&HB("eax")); +for($i=0;$i<8;$i++) { + my $func = ($i==0)? \&movq : \&pxor; + &shr ("eax",16); + &scale ("esi","ecx"); + &movz ("ecx",&LB("eax")); + &scale ("edi","edx"); + &movz ("edx",&HB("eax")); + &pxor (@mm[0],&QWP(&row(0),$tbl,"esi",8)); + &$func (@mm[1],&QWP(&row(1),$tbl,"edi",8)); + &mov ("eax",&DWP(($i+1)*8,"esp")); + &scale ("esi","ecx"); + &movz ("ecx",&LB("ebx")); + &scale ("edi","edx"); + &movz ("edx",&HB("ebx")); + &$func (@mm[2],&QWP(&row(2),$tbl,"esi",8)); + &$func (@mm[3],&QWP(&row(3),$tbl,"edi",8)); + &shr ("ebx",16); + &scale ("esi","ecx"); + &movz ("ecx",&LB("ebx")); + &scale ("edi","edx"); + &movz ("edx",&HB("ebx")); + &$func (@mm[4],&QWP(&row(4),$tbl,"esi",8)); + &$func (@mm[5],&QWP(&row(5),$tbl,"edi",8)); + &mov ("ebx",&DWP(($i+1)*8+4,"esp")); + &scale ("esi","ecx"); + &movz ("ecx",&LB("eax")); + &scale ("edi","edx"); + &movz ("edx",&HB("eax")); + &$func (@mm[6],&QWP(&row(6),$tbl,"esi",8)); + &$func (@mm[7],&QWP(&row(7),$tbl,"edi",8)); + push(@mm,shift(@mm)); +} + + for($i=0;$i<8;$i++) { &movq(&QWP($i*8,"esp"),@mm[$i]); } # K=L + +for($i=0;$i<8;$i++) { + &shr ("eax",16); + &scale ("esi","ecx"); + &movz ("ecx",&LB("eax")); + &scale ("edi","edx"); + &movz ("edx",&HB("eax")); + &pxor (@mm[0],&QWP(&row(0),$tbl,"esi",8)); + &pxor (@mm[1],&QWP(&row(1),$tbl,"edi",8)); + &mov ("eax",&DWP(64+($i+1)*8,"esp")) if ($i<7); + &scale ("esi","ecx"); + &movz ("ecx",&LB("ebx")); + &scale ("edi","edx"); + &movz ("edx",&HB("ebx")); + &pxor (@mm[2],&QWP(&row(2),$tbl,"esi",8)); + &pxor (@mm[3],&QWP(&row(3),$tbl,"edi",8)); + &shr ("ebx",16); + &scale ("esi","ecx"); + &movz ("ecx",&LB("ebx")); + &scale ("edi","edx"); + &movz ("edx",&HB("ebx")); + &pxor (@mm[4],&QWP(&row(4),$tbl,"esi",8)); + &pxor (@mm[5],&QWP(&row(5),$tbl,"edi",8)); + &mov ("ebx",&DWP(64+($i+1)*8+4,"esp")) if ($i<7); + &scale ("esi","ecx"); + &movz ("ecx",&LB("eax")); + &scale ("edi","edx"); + &movz ("edx",&HB("eax")); + &pxor (@mm[6],&QWP(&row(6),$tbl,"esi",8)); + &pxor (@mm[7],&QWP(&row(7),$tbl,"edi",8)); + push(@mm,shift(@mm)); +} + &lea ("ebx",&DWP(128,"esp")); + &mov ("esi",&DWP(12,"ebx")); # pull round counter + &add ("esi",1); + &cmp ("esi",10); + &je (&label("roundsdone")); + + &mov (&DWP(12,"ebx"),"esi"); # update round counter + for($i=0;$i<8;$i++) { &movq(&QWP(64+$i*8,"esp"),@mm[$i]); } # S=L + &jmp (&label("round")); + +&set_label("roundsdone",16); + &mov ("esi",&DWP(0,"ebx")); # reload argument block + &mov ("edi",&DWP(4,"ebx")); + &mov ("eax",&DWP(8,"ebx")); + + for($i=0;$i<8;$i++) { &pxor(@mm[$i],&QWP($i*8,"edi")); } # L^=inp + for($i=0;$i<8;$i++) { &pxor(@mm[$i],&QWP($i*8,"esi")); } # L^=H + for($i=0;$i<8;$i++) { &movq(&QWP($i*8,"esi"),@mm[$i]); } # H=L + + &lea ("edi",&DWP(64,"edi")); # inp+=64 + &sub ("eax",1); # num-- + &jz (&label("alldone")); + &mov (&DWP(4,"ebx"),"edi"); # update argument block + &mov (&DWP(8,"ebx"),"eax"); + &jmp (&label("outerloop")); + +&set_label("alldone"); + &emms (); + &mov ("esp",&DWP(16,"ebx")); # restore saved stack pointer + &pop ("edi"); + &pop ("esi"); + &pop ("ebx"); + &pop ("ebp"); + &ret (); + +&align(64); +&set_label("table"); + &LL(0x18,0x18,0x60,0x18,0xc0,0x78,0x30,0xd8); + &LL(0x23,0x23,0x8c,0x23,0x05,0xaf,0x46,0x26); + &LL(0xc6,0xc6,0x3f,0xc6,0x7e,0xf9,0x91,0xb8); + &LL(0xe8,0xe8,0x87,0xe8,0x13,0x6f,0xcd,0xfb); + &LL(0x87,0x87,0x26,0x87,0x4c,0xa1,0x13,0xcb); + &LL(0xb8,0xb8,0xda,0xb8,0xa9,0x62,0x6d,0x11); + &LL(0x01,0x01,0x04,0x01,0x08,0x05,0x02,0x09); + &LL(0x4f,0x4f,0x21,0x4f,0x42,0x6e,0x9e,0x0d); + &LL(0x36,0x36,0xd8,0x36,0xad,0xee,0x6c,0x9b); + &LL(0xa6,0xa6,0xa2,0xa6,0x59,0x04,0x51,0xff); + &LL(0xd2,0xd2,0x6f,0xd2,0xde,0xbd,0xb9,0x0c); + &LL(0xf5,0xf5,0xf3,0xf5,0xfb,0x06,0xf7,0x0e); + &LL(0x79,0x79,0xf9,0x79,0xef,0x80,0xf2,0x96); + &LL(0x6f,0x6f,0xa1,0x6f,0x5f,0xce,0xde,0x30); + &LL(0x91,0x91,0x7e,0x91,0xfc,0xef,0x3f,0x6d); + &LL(0x52,0x52,0x55,0x52,0xaa,0x07,0xa4,0xf8); + &LL(0x60,0x60,0x9d,0x60,0x27,0xfd,0xc0,0x47); + &LL(0xbc,0xbc,0xca,0xbc,0x89,0x76,0x65,0x35); + &LL(0x9b,0x9b,0x56,0x9b,0xac,0xcd,0x2b,0x37); + &LL(0x8e,0x8e,0x02,0x8e,0x04,0x8c,0x01,0x8a); + &LL(0xa3,0xa3,0xb6,0xa3,0x71,0x15,0x5b,0xd2); + &LL(0x0c,0x0c,0x30,0x0c,0x60,0x3c,0x18,0x6c); + &LL(0x7b,0x7b,0xf1,0x7b,0xff,0x8a,0xf6,0x84); + &LL(0x35,0x35,0xd4,0x35,0xb5,0xe1,0x6a,0x80); + &LL(0x1d,0x1d,0x74,0x1d,0xe8,0x69,0x3a,0xf5); + &LL(0xe0,0xe0,0xa7,0xe0,0x53,0x47,0xdd,0xb3); + &LL(0xd7,0xd7,0x7b,0xd7,0xf6,0xac,0xb3,0x21); + &LL(0xc2,0xc2,0x2f,0xc2,0x5e,0xed,0x99,0x9c); + &LL(0x2e,0x2e,0xb8,0x2e,0x6d,0x96,0x5c,0x43); + &LL(0x4b,0x4b,0x31,0x4b,0x62,0x7a,0x96,0x29); + &LL(0xfe,0xfe,0xdf,0xfe,0xa3,0x21,0xe1,0x5d); + &LL(0x57,0x57,0x41,0x57,0x82,0x16,0xae,0xd5); + &LL(0x15,0x15,0x54,0x15,0xa8,0x41,0x2a,0xbd); + &LL(0x77,0x77,0xc1,0x77,0x9f,0xb6,0xee,0xe8); + &LL(0x37,0x37,0xdc,0x37,0xa5,0xeb,0x6e,0x92); + &LL(0xe5,0xe5,0xb3,0xe5,0x7b,0x56,0xd7,0x9e); + &LL(0x9f,0x9f,0x46,0x9f,0x8c,0xd9,0x23,0x13); + &LL(0xf0,0xf0,0xe7,0xf0,0xd3,0x17,0xfd,0x23); + &LL(0x4a,0x4a,0x35,0x4a,0x6a,0x7f,0x94,0x20); + &LL(0xda,0xda,0x4f,0xda,0x9e,0x95,0xa9,0x44); + &LL(0x58,0x58,0x7d,0x58,0xfa,0x25,0xb0,0xa2); + &LL(0xc9,0xc9,0x03,0xc9,0x06,0xca,0x8f,0xcf); + &LL(0x29,0x29,0xa4,0x29,0x55,0x8d,0x52,0x7c); + &LL(0x0a,0x0a,0x28,0x0a,0x50,0x22,0x14,0x5a); + &LL(0xb1,0xb1,0xfe,0xb1,0xe1,0x4f,0x7f,0x50); + &LL(0xa0,0xa0,0xba,0xa0,0x69,0x1a,0x5d,0xc9); + &LL(0x6b,0x6b,0xb1,0x6b,0x7f,0xda,0xd6,0x14); + &LL(0x85,0x85,0x2e,0x85,0x5c,0xab,0x17,0xd9); + &LL(0xbd,0xbd,0xce,0xbd,0x81,0x73,0x67,0x3c); + &LL(0x5d,0x5d,0x69,0x5d,0xd2,0x34,0xba,0x8f); + &LL(0x10,0x10,0x40,0x10,0x80,0x50,0x20,0x90); + &LL(0xf4,0xf4,0xf7,0xf4,0xf3,0x03,0xf5,0x07); + &LL(0xcb,0xcb,0x0b,0xcb,0x16,0xc0,0x8b,0xdd); + &LL(0x3e,0x3e,0xf8,0x3e,0xed,0xc6,0x7c,0xd3); + &LL(0x05,0x05,0x14,0x05,0x28,0x11,0x0a,0x2d); + &LL(0x67,0x67,0x81,0x67,0x1f,0xe6,0xce,0x78); + &LL(0xe4,0xe4,0xb7,0xe4,0x73,0x53,0xd5,0x97); + &LL(0x27,0x27,0x9c,0x27,0x25,0xbb,0x4e,0x02); + &LL(0x41,0x41,0x19,0x41,0x32,0x58,0x82,0x73); + &LL(0x8b,0x8b,0x16,0x8b,0x2c,0x9d,0x0b,0xa7); + &LL(0xa7,0xa7,0xa6,0xa7,0x51,0x01,0x53,0xf6); + &LL(0x7d,0x7d,0xe9,0x7d,0xcf,0x94,0xfa,0xb2); + &LL(0x95,0x95,0x6e,0x95,0xdc,0xfb,0x37,0x49); + &LL(0xd8,0xd8,0x47,0xd8,0x8e,0x9f,0xad,0x56); + &LL(0xfb,0xfb,0xcb,0xfb,0x8b,0x30,0xeb,0x70); + &LL(0xee,0xee,0x9f,0xee,0x23,0x71,0xc1,0xcd); + &LL(0x7c,0x7c,0xed,0x7c,0xc7,0x91,0xf8,0xbb); + &LL(0x66,0x66,0x85,0x66,0x17,0xe3,0xcc,0x71); + &LL(0xdd,0xdd,0x53,0xdd,0xa6,0x8e,0xa7,0x7b); + &LL(0x17,0x17,0x5c,0x17,0xb8,0x4b,0x2e,0xaf); + &LL(0x47,0x47,0x01,0x47,0x02,0x46,0x8e,0x45); + &LL(0x9e,0x9e,0x42,0x9e,0x84,0xdc,0x21,0x1a); + &LL(0xca,0xca,0x0f,0xca,0x1e,0xc5,0x89,0xd4); + &LL(0x2d,0x2d,0xb4,0x2d,0x75,0x99,0x5a,0x58); + &LL(0xbf,0xbf,0xc6,0xbf,0x91,0x79,0x63,0x2e); + &LL(0x07,0x07,0x1c,0x07,0x38,0x1b,0x0e,0x3f); + &LL(0xad,0xad,0x8e,0xad,0x01,0x23,0x47,0xac); + &LL(0x5a,0x5a,0x75,0x5a,0xea,0x2f,0xb4,0xb0); + &LL(0x83,0x83,0x36,0x83,0x6c,0xb5,0x1b,0xef); + &LL(0x33,0x33,0xcc,0x33,0x85,0xff,0x66,0xb6); + &LL(0x63,0x63,0x91,0x63,0x3f,0xf2,0xc6,0x5c); + &LL(0x02,0x02,0x08,0x02,0x10,0x0a,0x04,0x12); + &LL(0xaa,0xaa,0x92,0xaa,0x39,0x38,0x49,0x93); + &LL(0x71,0x71,0xd9,0x71,0xaf,0xa8,0xe2,0xde); + &LL(0xc8,0xc8,0x07,0xc8,0x0e,0xcf,0x8d,0xc6); + &LL(0x19,0x19,0x64,0x19,0xc8,0x7d,0x32,0xd1); + &LL(0x49,0x49,0x39,0x49,0x72,0x70,0x92,0x3b); + &LL(0xd9,0xd9,0x43,0xd9,0x86,0x9a,0xaf,0x5f); + &LL(0xf2,0xf2,0xef,0xf2,0xc3,0x1d,0xf9,0x31); + &LL(0xe3,0xe3,0xab,0xe3,0x4b,0x48,0xdb,0xa8); + &LL(0x5b,0x5b,0x71,0x5b,0xe2,0x2a,0xb6,0xb9); + &LL(0x88,0x88,0x1a,0x88,0x34,0x92,0x0d,0xbc); + &LL(0x9a,0x9a,0x52,0x9a,0xa4,0xc8,0x29,0x3e); + &LL(0x26,0x26,0x98,0x26,0x2d,0xbe,0x4c,0x0b); + &LL(0x32,0x32,0xc8,0x32,0x8d,0xfa,0x64,0xbf); + &LL(0xb0,0xb0,0xfa,0xb0,0xe9,0x4a,0x7d,0x59); + &LL(0xe9,0xe9,0x83,0xe9,0x1b,0x6a,0xcf,0xf2); + &LL(0x0f,0x0f,0x3c,0x0f,0x78,0x33,0x1e,0x77); + &LL(0xd5,0xd5,0x73,0xd5,0xe6,0xa6,0xb7,0x33); + &LL(0x80,0x80,0x3a,0x80,0x74,0xba,0x1d,0xf4); + &LL(0xbe,0xbe,0xc2,0xbe,0x99,0x7c,0x61,0x27); + &LL(0xcd,0xcd,0x13,0xcd,0x26,0xde,0x87,0xeb); + &LL(0x34,0x34,0xd0,0x34,0xbd,0xe4,0x68,0x89); + &LL(0x48,0x48,0x3d,0x48,0x7a,0x75,0x90,0x32); + &LL(0xff,0xff,0xdb,0xff,0xab,0x24,0xe3,0x54); + &LL(0x7a,0x7a,0xf5,0x7a,0xf7,0x8f,0xf4,0x8d); + &LL(0x90,0x90,0x7a,0x90,0xf4,0xea,0x3d,0x64); + &LL(0x5f,0x5f,0x61,0x5f,0xc2,0x3e,0xbe,0x9d); + &LL(0x20,0x20,0x80,0x20,0x1d,0xa0,0x40,0x3d); + &LL(0x68,0x68,0xbd,0x68,0x67,0xd5,0xd0,0x0f); + &LL(0x1a,0x1a,0x68,0x1a,0xd0,0x72,0x34,0xca); + &LL(0xae,0xae,0x82,0xae,0x19,0x2c,0x41,0xb7); + &LL(0xb4,0xb4,0xea,0xb4,0xc9,0x5e,0x75,0x7d); + &LL(0x54,0x54,0x4d,0x54,0x9a,0x19,0xa8,0xce); + &LL(0x93,0x93,0x76,0x93,0xec,0xe5,0x3b,0x7f); + &LL(0x22,0x22,0x88,0x22,0x0d,0xaa,0x44,0x2f); + &LL(0x64,0x64,0x8d,0x64,0x07,0xe9,0xc8,0x63); + &LL(0xf1,0xf1,0xe3,0xf1,0xdb,0x12,0xff,0x2a); + &LL(0x73,0x73,0xd1,0x73,0xbf,0xa2,0xe6,0xcc); + &LL(0x12,0x12,0x48,0x12,0x90,0x5a,0x24,0x82); + &LL(0x40,0x40,0x1d,0x40,0x3a,0x5d,0x80,0x7a); + &LL(0x08,0x08,0x20,0x08,0x40,0x28,0x10,0x48); + &LL(0xc3,0xc3,0x2b,0xc3,0x56,0xe8,0x9b,0x95); + &LL(0xec,0xec,0x97,0xec,0x33,0x7b,0xc5,0xdf); + &LL(0xdb,0xdb,0x4b,0xdb,0x96,0x90,0xab,0x4d); + &LL(0xa1,0xa1,0xbe,0xa1,0x61,0x1f,0x5f,0xc0); + &LL(0x8d,0x8d,0x0e,0x8d,0x1c,0x83,0x07,0x91); + &LL(0x3d,0x3d,0xf4,0x3d,0xf5,0xc9,0x7a,0xc8); + &LL(0x97,0x97,0x66,0x97,0xcc,0xf1,0x33,0x5b); + &LL(0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00); + &LL(0xcf,0xcf,0x1b,0xcf,0x36,0xd4,0x83,0xf9); + &LL(0x2b,0x2b,0xac,0x2b,0x45,0x87,0x56,0x6e); + &LL(0x76,0x76,0xc5,0x76,0x97,0xb3,0xec,0xe1); + &LL(0x82,0x82,0x32,0x82,0x64,0xb0,0x19,0xe6); + &LL(0xd6,0xd6,0x7f,0xd6,0xfe,0xa9,0xb1,0x28); + &LL(0x1b,0x1b,0x6c,0x1b,0xd8,0x77,0x36,0xc3); + &LL(0xb5,0xb5,0xee,0xb5,0xc1,0x5b,0x77,0x74); + &LL(0xaf,0xaf,0x86,0xaf,0x11,0x29,0x43,0xbe); + &LL(0x6a,0x6a,0xb5,0x6a,0x77,0xdf,0xd4,0x1d); + &LL(0x50,0x50,0x5d,0x50,0xba,0x0d,0xa0,0xea); + &LL(0x45,0x45,0x09,0x45,0x12,0x4c,0x8a,0x57); + &LL(0xf3,0xf3,0xeb,0xf3,0xcb,0x18,0xfb,0x38); + &LL(0x30,0x30,0xc0,0x30,0x9d,0xf0,0x60,0xad); + &LL(0xef,0xef,0x9b,0xef,0x2b,0x74,0xc3,0xc4); + &LL(0x3f,0x3f,0xfc,0x3f,0xe5,0xc3,0x7e,0xda); + &LL(0x55,0x55,0x49,0x55,0x92,0x1c,0xaa,0xc7); + &LL(0xa2,0xa2,0xb2,0xa2,0x79,0x10,0x59,0xdb); + &LL(0xea,0xea,0x8f,0xea,0x03,0x65,0xc9,0xe9); + &LL(0x65,0x65,0x89,0x65,0x0f,0xec,0xca,0x6a); + &LL(0xba,0xba,0xd2,0xba,0xb9,0x68,0x69,0x03); + &LL(0x2f,0x2f,0xbc,0x2f,0x65,0x93,0x5e,0x4a); + &LL(0xc0,0xc0,0x27,0xc0,0x4e,0xe7,0x9d,0x8e); + &LL(0xde,0xde,0x5f,0xde,0xbe,0x81,0xa1,0x60); + &LL(0x1c,0x1c,0x70,0x1c,0xe0,0x6c,0x38,0xfc); + &LL(0xfd,0xfd,0xd3,0xfd,0xbb,0x2e,0xe7,0x46); + &LL(0x4d,0x4d,0x29,0x4d,0x52,0x64,0x9a,0x1f); + &LL(0x92,0x92,0x72,0x92,0xe4,0xe0,0x39,0x76); + &LL(0x75,0x75,0xc9,0x75,0x8f,0xbc,0xea,0xfa); + &LL(0x06,0x06,0x18,0x06,0x30,0x1e,0x0c,0x36); + &LL(0x8a,0x8a,0x12,0x8a,0x24,0x98,0x09,0xae); + &LL(0xb2,0xb2,0xf2,0xb2,0xf9,0x40,0x79,0x4b); + &LL(0xe6,0xe6,0xbf,0xe6,0x63,0x59,0xd1,0x85); + &LL(0x0e,0x0e,0x38,0x0e,0x70,0x36,0x1c,0x7e); + &LL(0x1f,0x1f,0x7c,0x1f,0xf8,0x63,0x3e,0xe7); + &LL(0x62,0x62,0x95,0x62,0x37,0xf7,0xc4,0x55); + &LL(0xd4,0xd4,0x77,0xd4,0xee,0xa3,0xb5,0x3a); + &LL(0xa8,0xa8,0x9a,0xa8,0x29,0x32,0x4d,0x81); + &LL(0x96,0x96,0x62,0x96,0xc4,0xf4,0x31,0x52); + &LL(0xf9,0xf9,0xc3,0xf9,0x9b,0x3a,0xef,0x62); + &LL(0xc5,0xc5,0x33,0xc5,0x66,0xf6,0x97,0xa3); + &LL(0x25,0x25,0x94,0x25,0x35,0xb1,0x4a,0x10); + &LL(0x59,0x59,0x79,0x59,0xf2,0x20,0xb2,0xab); + &LL(0x84,0x84,0x2a,0x84,0x54,0xae,0x15,0xd0); + &LL(0x72,0x72,0xd5,0x72,0xb7,0xa7,0xe4,0xc5); + &LL(0x39,0x39,0xe4,0x39,0xd5,0xdd,0x72,0xec); + &LL(0x4c,0x4c,0x2d,0x4c,0x5a,0x61,0x98,0x16); + &LL(0x5e,0x5e,0x65,0x5e,0xca,0x3b,0xbc,0x94); + &LL(0x78,0x78,0xfd,0x78,0xe7,0x85,0xf0,0x9f); + &LL(0x38,0x38,0xe0,0x38,0xdd,0xd8,0x70,0xe5); + &LL(0x8c,0x8c,0x0a,0x8c,0x14,0x86,0x05,0x98); + &LL(0xd1,0xd1,0x63,0xd1,0xc6,0xb2,0xbf,0x17); + &LL(0xa5,0xa5,0xae,0xa5,0x41,0x0b,0x57,0xe4); + &LL(0xe2,0xe2,0xaf,0xe2,0x43,0x4d,0xd9,0xa1); + &LL(0x61,0x61,0x99,0x61,0x2f,0xf8,0xc2,0x4e); + &LL(0xb3,0xb3,0xf6,0xb3,0xf1,0x45,0x7b,0x42); + &LL(0x21,0x21,0x84,0x21,0x15,0xa5,0x42,0x34); + &LL(0x9c,0x9c,0x4a,0x9c,0x94,0xd6,0x25,0x08); + &LL(0x1e,0x1e,0x78,0x1e,0xf0,0x66,0x3c,0xee); + &LL(0x43,0x43,0x11,0x43,0x22,0x52,0x86,0x61); + &LL(0xc7,0xc7,0x3b,0xc7,0x76,0xfc,0x93,0xb1); + &LL(0xfc,0xfc,0xd7,0xfc,0xb3,0x2b,0xe5,0x4f); + &LL(0x04,0x04,0x10,0x04,0x20,0x14,0x08,0x24); + &LL(0x51,0x51,0x59,0x51,0xb2,0x08,0xa2,0xe3); + &LL(0x99,0x99,0x5e,0x99,0xbc,0xc7,0x2f,0x25); + &LL(0x6d,0x6d,0xa9,0x6d,0x4f,0xc4,0xda,0x22); + &LL(0x0d,0x0d,0x34,0x0d,0x68,0x39,0x1a,0x65); + &LL(0xfa,0xfa,0xcf,0xfa,0x83,0x35,0xe9,0x79); + &LL(0xdf,0xdf,0x5b,0xdf,0xb6,0x84,0xa3,0x69); + &LL(0x7e,0x7e,0xe5,0x7e,0xd7,0x9b,0xfc,0xa9); + &LL(0x24,0x24,0x90,0x24,0x3d,0xb4,0x48,0x19); + &LL(0x3b,0x3b,0xec,0x3b,0xc5,0xd7,0x76,0xfe); + &LL(0xab,0xab,0x96,0xab,0x31,0x3d,0x4b,0x9a); + &LL(0xce,0xce,0x1f,0xce,0x3e,0xd1,0x81,0xf0); + &LL(0x11,0x11,0x44,0x11,0x88,0x55,0x22,0x99); + &LL(0x8f,0x8f,0x06,0x8f,0x0c,0x89,0x03,0x83); + &LL(0x4e,0x4e,0x25,0x4e,0x4a,0x6b,0x9c,0x04); + &LL(0xb7,0xb7,0xe6,0xb7,0xd1,0x51,0x73,0x66); + &LL(0xeb,0xeb,0x8b,0xeb,0x0b,0x60,0xcb,0xe0); + &LL(0x3c,0x3c,0xf0,0x3c,0xfd,0xcc,0x78,0xc1); + &LL(0x81,0x81,0x3e,0x81,0x7c,0xbf,0x1f,0xfd); + &LL(0x94,0x94,0x6a,0x94,0xd4,0xfe,0x35,0x40); + &LL(0xf7,0xf7,0xfb,0xf7,0xeb,0x0c,0xf3,0x1c); + &LL(0xb9,0xb9,0xde,0xb9,0xa1,0x67,0x6f,0x18); + &LL(0x13,0x13,0x4c,0x13,0x98,0x5f,0x26,0x8b); + &LL(0x2c,0x2c,0xb0,0x2c,0x7d,0x9c,0x58,0x51); + &LL(0xd3,0xd3,0x6b,0xd3,0xd6,0xb8,0xbb,0x05); + &LL(0xe7,0xe7,0xbb,0xe7,0x6b,0x5c,0xd3,0x8c); + &LL(0x6e,0x6e,0xa5,0x6e,0x57,0xcb,0xdc,0x39); + &LL(0xc4,0xc4,0x37,0xc4,0x6e,0xf3,0x95,0xaa); + &LL(0x03,0x03,0x0c,0x03,0x18,0x0f,0x06,0x1b); + &LL(0x56,0x56,0x45,0x56,0x8a,0x13,0xac,0xdc); + &LL(0x44,0x44,0x0d,0x44,0x1a,0x49,0x88,0x5e); + &LL(0x7f,0x7f,0xe1,0x7f,0xdf,0x9e,0xfe,0xa0); + &LL(0xa9,0xa9,0x9e,0xa9,0x21,0x37,0x4f,0x88); + &LL(0x2a,0x2a,0xa8,0x2a,0x4d,0x82,0x54,0x67); + &LL(0xbb,0xbb,0xd6,0xbb,0xb1,0x6d,0x6b,0x0a); + &LL(0xc1,0xc1,0x23,0xc1,0x46,0xe2,0x9f,0x87); + &LL(0x53,0x53,0x51,0x53,0xa2,0x02,0xa6,0xf1); + &LL(0xdc,0xdc,0x57,0xdc,0xae,0x8b,0xa5,0x72); + &LL(0x0b,0x0b,0x2c,0x0b,0x58,0x27,0x16,0x53); + &LL(0x9d,0x9d,0x4e,0x9d,0x9c,0xd3,0x27,0x01); + &LL(0x6c,0x6c,0xad,0x6c,0x47,0xc1,0xd8,0x2b); + &LL(0x31,0x31,0xc4,0x31,0x95,0xf5,0x62,0xa4); + &LL(0x74,0x74,0xcd,0x74,0x87,0xb9,0xe8,0xf3); + &LL(0xf6,0xf6,0xff,0xf6,0xe3,0x09,0xf1,0x15); + &LL(0x46,0x46,0x05,0x46,0x0a,0x43,0x8c,0x4c); + &LL(0xac,0xac,0x8a,0xac,0x09,0x26,0x45,0xa5); + &LL(0x89,0x89,0x1e,0x89,0x3c,0x97,0x0f,0xb5); + &LL(0x14,0x14,0x50,0x14,0xa0,0x44,0x28,0xb4); + &LL(0xe1,0xe1,0xa3,0xe1,0x5b,0x42,0xdf,0xba); + &LL(0x16,0x16,0x58,0x16,0xb0,0x4e,0x2c,0xa6); + &LL(0x3a,0x3a,0xe8,0x3a,0xcd,0xd2,0x74,0xf7); + &LL(0x69,0x69,0xb9,0x69,0x6f,0xd0,0xd2,0x06); + &LL(0x09,0x09,0x24,0x09,0x48,0x2d,0x12,0x41); + &LL(0x70,0x70,0xdd,0x70,0xa7,0xad,0xe0,0xd7); + &LL(0xb6,0xb6,0xe2,0xb6,0xd9,0x54,0x71,0x6f); + &LL(0xd0,0xd0,0x67,0xd0,0xce,0xb7,0xbd,0x1e); + &LL(0xed,0xed,0x93,0xed,0x3b,0x7e,0xc7,0xd6); + &LL(0xcc,0xcc,0x17,0xcc,0x2e,0xdb,0x85,0xe2); + &LL(0x42,0x42,0x15,0x42,0x2a,0x57,0x84,0x68); + &LL(0x98,0x98,0x5a,0x98,0xb4,0xc2,0x2d,0x2c); + &LL(0xa4,0xa4,0xaa,0xa4,0x49,0x0e,0x55,0xed); + &LL(0x28,0x28,0xa0,0x28,0x5d,0x88,0x50,0x75); + &LL(0x5c,0x5c,0x6d,0x5c,0xda,0x31,0xb8,0x86); + &LL(0xf8,0xf8,0xc7,0xf8,0x93,0x3f,0xed,0x6b); + &LL(0x86,0x86,0x22,0x86,0x44,0xa4,0x11,0xc2); + + &L(0x18,0x23,0xc6,0xe8,0x87,0xb8,0x01,0x4f); # rc[ROUNDS] + &L(0x36,0xa6,0xd2,0xf5,0x79,0x6f,0x91,0x52); + &L(0x60,0xbc,0x9b,0x8e,0xa3,0x0c,0x7b,0x35); + &L(0x1d,0xe0,0xd7,0xc2,0x2e,0x4b,0xfe,0x57); + &L(0x15,0x77,0x37,0xe5,0x9f,0xf0,0x4a,0xda); + &L(0x58,0xc9,0x29,0x0a,0xb1,0xa0,0x6b,0x85); + &L(0xbd,0x5d,0x10,0xf4,0xcb,0x3e,0x05,0x67); + &L(0xe4,0x27,0x41,0x8b,0xa7,0x7d,0x95,0xd8); + &L(0xfb,0xee,0x7c,0x66,0xdd,0x17,0x47,0x9e); + &L(0xca,0x2d,0xbf,0x07,0xad,0x5a,0x83,0x33); + +&function_end_B("whirlpool_block_mmx"); +&asm_finish(); + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/whrlpool/asm/wp-x86_64.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/whrlpool/asm/wp-x86_64.pl new file mode 100644 index 000000000..fe23d8cad --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/whrlpool/asm/wp-x86_64.pl @@ -0,0 +1,617 @@ +#! /usr/bin/env perl +# Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. Rights for redistribution and usage in source and binary +# forms are granted according to the OpenSSL license. +# ==================================================================== +# +# whirlpool_block for x86_64. +# +# 2500 cycles per 64-byte input block on AMD64, which is *identical* +# to 32-bit MMX version executed on same CPU. So why did I bother? +# Well, it's faster than gcc 3.3.2 generated code by over 50%, and +# over 80% faster than PathScale 1.4, an "ambitious" commercial +# compiler. Furthermore it surpasses gcc 3.4.3 by 170% and Sun Studio +# 10 - by 360%[!]... What is it with x86_64 compilers? It's not the +# first example when they fail to generate more optimal code, when +# I believe they had *all* chances to... +# +# Note that register and stack frame layout are virtually identical +# to 32-bit MMX version, except that %r8-15 are used instead of +# %mm0-8. You can even notice that K[i] and S[i] are loaded to +# %eax:%ebx as pair of 32-bit values and not as single 64-bit one. +# This is done in order to avoid 64-bit shift penalties on Intel +# EM64T core. Speaking of which! I bet it's possible to improve +# Opteron performance by compressing the table to 2KB and replacing +# unaligned references with complementary rotations [which would +# incidentally replace lea instructions], but it would definitely +# just "kill" EM64T, because it has only 1 shifter/rotator [against +# 3 on Opteron] and which is *unacceptably* slow with 64-bit +# operand. + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; my $dir=$1; my $xlate; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +*STDOUT=*OUT; + +sub L() { $code.=".byte ".join(',',@_)."\n"; } +sub LL(){ $code.=".byte ".join(',',@_).",".join(',',@_)."\n"; } + +@mm=("%r8","%r9","%r10","%r11","%r12","%r13","%r14","%r15"); + +$func="whirlpool_block"; +$table=".Ltable"; + +$code=<<___; +.text + +.globl $func +.type $func,\@function,3 +.align 16 +$func: +.cfi_startproc + mov %rsp,%rax +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + + sub \$128+40,%rsp + and \$-64,%rsp + + lea 128(%rsp),%r10 + mov %rdi,0(%r10) # save parameter block + mov %rsi,8(%r10) + mov %rdx,16(%r10) + mov %rax,32(%r10) # saved stack pointer +.cfi_cfa_expression %rsp+`128+32`,deref,+8 +.Lprologue: + + mov %r10,%rbx + lea $table(%rip),%rbp + + xor %rcx,%rcx + xor %rdx,%rdx +___ +for($i=0;$i<8;$i++) { $code.="mov $i*8(%rdi),@mm[$i]\n"; } # L=H +$code.=".Louterloop:\n"; +for($i=0;$i<8;$i++) { $code.="mov @mm[$i],$i*8(%rsp)\n"; } # K=L +for($i=0;$i<8;$i++) { $code.="xor $i*8(%rsi),@mm[$i]\n"; } # L^=inp +for($i=0;$i<8;$i++) { $code.="mov @mm[$i],64+$i*8(%rsp)\n"; } # S=L +$code.=<<___; + xor %rsi,%rsi + mov %rsi,24(%rbx) # zero round counter + jmp .Lround +.align 16 +.Lround: + mov 4096(%rbp,%rsi,8),@mm[0] # rc[r] + mov 0(%rsp),%eax + mov 4(%rsp),%ebx + movz %al,%ecx + movz %ah,%edx +___ +for($i=0;$i<8;$i++) { + my $func = ($i==0)? "mov" : "xor"; + $code.=<<___; + shr \$16,%eax + lea (%rcx,%rcx),%rsi + movz %al,%ecx + lea (%rdx,%rdx),%rdi + movz %ah,%edx + xor 0(%rbp,%rsi,8),@mm[0] + $func 7(%rbp,%rdi,8),@mm[1] + mov $i*8+8(%rsp),%eax # ($i+1)*8 + lea (%rcx,%rcx),%rsi + movz %bl,%ecx + lea (%rdx,%rdx),%rdi + movz %bh,%edx + $func 6(%rbp,%rsi,8),@mm[2] + $func 5(%rbp,%rdi,8),@mm[3] + shr \$16,%ebx + lea (%rcx,%rcx),%rsi + movz %bl,%ecx + lea (%rdx,%rdx),%rdi + movz %bh,%edx + $func 4(%rbp,%rsi,8),@mm[4] + $func 3(%rbp,%rdi,8),@mm[5] + mov $i*8+8+4(%rsp),%ebx # ($i+1)*8+4 + lea (%rcx,%rcx),%rsi + movz %al,%ecx + lea (%rdx,%rdx),%rdi + movz %ah,%edx + $func 2(%rbp,%rsi,8),@mm[6] + $func 1(%rbp,%rdi,8),@mm[7] +___ + push(@mm,shift(@mm)); +} +for($i=0;$i<8;$i++) { $code.="mov @mm[$i],$i*8(%rsp)\n"; } # K=L +for($i=0;$i<8;$i++) { + $code.=<<___; + shr \$16,%eax + lea (%rcx,%rcx),%rsi + movz %al,%ecx + lea (%rdx,%rdx),%rdi + movz %ah,%edx + xor 0(%rbp,%rsi,8),@mm[0] + xor 7(%rbp,%rdi,8),@mm[1] + `"mov 64+$i*8+8(%rsp),%eax" if($i<7);` # 64+($i+1)*8 + lea (%rcx,%rcx),%rsi + movz %bl,%ecx + lea (%rdx,%rdx),%rdi + movz %bh,%edx + xor 6(%rbp,%rsi,8),@mm[2] + xor 5(%rbp,%rdi,8),@mm[3] + shr \$16,%ebx + lea (%rcx,%rcx),%rsi + movz %bl,%ecx + lea (%rdx,%rdx),%rdi + movz %bh,%edx + xor 4(%rbp,%rsi,8),@mm[4] + xor 3(%rbp,%rdi,8),@mm[5] + `"mov 64+$i*8+8+4(%rsp),%ebx" if($i<7);` # 64+($i+1)*8+4 + lea (%rcx,%rcx),%rsi + movz %al,%ecx + lea (%rdx,%rdx),%rdi + movz %ah,%edx + xor 2(%rbp,%rsi,8),@mm[6] + xor 1(%rbp,%rdi,8),@mm[7] +___ + push(@mm,shift(@mm)); +} +$code.=<<___; + lea 128(%rsp),%rbx + mov 24(%rbx),%rsi # pull round counter + add \$1,%rsi + cmp \$10,%rsi + je .Lroundsdone + + mov %rsi,24(%rbx) # update round counter +___ +for($i=0;$i<8;$i++) { $code.="mov @mm[$i],64+$i*8(%rsp)\n"; } # S=L +$code.=<<___; + jmp .Lround +.align 16 +.Lroundsdone: + mov 0(%rbx),%rdi # reload argument block + mov 8(%rbx),%rsi + mov 16(%rbx),%rax +___ +for($i=0;$i<8;$i++) { $code.="xor $i*8(%rsi),@mm[$i]\n"; } # L^=inp +for($i=0;$i<8;$i++) { $code.="xor $i*8(%rdi),@mm[$i]\n"; } # L^=H +for($i=0;$i<8;$i++) { $code.="mov @mm[$i],$i*8(%rdi)\n"; } # H=L +$code.=<<___; + lea 64(%rsi),%rsi # inp+=64 + sub \$1,%rax # num-- + jz .Lalldone + mov %rsi,8(%rbx) # update parameter block + mov %rax,16(%rbx) + jmp .Louterloop +.Lalldone: + mov 32(%rbx),%rsi # restore saved pointer +.cfi_def_cfa %rsi,8 + mov -48(%rsi),%r15 +.cfi_restore %r15 + mov -40(%rsi),%r14 +.cfi_restore %r14 + mov -32(%rsi),%r13 +.cfi_restore %r13 + mov -24(%rsi),%r12 +.cfi_restore %r12 + mov -16(%rsi),%rbp +.cfi_restore %rbp + mov -8(%rsi),%rbx +.cfi_restore %rbx + lea (%rsi),%rsp +.cfi_def_cfa_register %rsp +.Lepilogue: + ret +.cfi_endproc +.size $func,.-$func + +.align 64 +.type $table,\@object +$table: +___ + &LL(0x18,0x18,0x60,0x18,0xc0,0x78,0x30,0xd8); + &LL(0x23,0x23,0x8c,0x23,0x05,0xaf,0x46,0x26); + &LL(0xc6,0xc6,0x3f,0xc6,0x7e,0xf9,0x91,0xb8); + &LL(0xe8,0xe8,0x87,0xe8,0x13,0x6f,0xcd,0xfb); + &LL(0x87,0x87,0x26,0x87,0x4c,0xa1,0x13,0xcb); + &LL(0xb8,0xb8,0xda,0xb8,0xa9,0x62,0x6d,0x11); + &LL(0x01,0x01,0x04,0x01,0x08,0x05,0x02,0x09); + &LL(0x4f,0x4f,0x21,0x4f,0x42,0x6e,0x9e,0x0d); + &LL(0x36,0x36,0xd8,0x36,0xad,0xee,0x6c,0x9b); + &LL(0xa6,0xa6,0xa2,0xa6,0x59,0x04,0x51,0xff); + &LL(0xd2,0xd2,0x6f,0xd2,0xde,0xbd,0xb9,0x0c); + &LL(0xf5,0xf5,0xf3,0xf5,0xfb,0x06,0xf7,0x0e); + &LL(0x79,0x79,0xf9,0x79,0xef,0x80,0xf2,0x96); + &LL(0x6f,0x6f,0xa1,0x6f,0x5f,0xce,0xde,0x30); + &LL(0x91,0x91,0x7e,0x91,0xfc,0xef,0x3f,0x6d); + &LL(0x52,0x52,0x55,0x52,0xaa,0x07,0xa4,0xf8); + &LL(0x60,0x60,0x9d,0x60,0x27,0xfd,0xc0,0x47); + &LL(0xbc,0xbc,0xca,0xbc,0x89,0x76,0x65,0x35); + &LL(0x9b,0x9b,0x56,0x9b,0xac,0xcd,0x2b,0x37); + &LL(0x8e,0x8e,0x02,0x8e,0x04,0x8c,0x01,0x8a); + &LL(0xa3,0xa3,0xb6,0xa3,0x71,0x15,0x5b,0xd2); + &LL(0x0c,0x0c,0x30,0x0c,0x60,0x3c,0x18,0x6c); + &LL(0x7b,0x7b,0xf1,0x7b,0xff,0x8a,0xf6,0x84); + &LL(0x35,0x35,0xd4,0x35,0xb5,0xe1,0x6a,0x80); + &LL(0x1d,0x1d,0x74,0x1d,0xe8,0x69,0x3a,0xf5); + &LL(0xe0,0xe0,0xa7,0xe0,0x53,0x47,0xdd,0xb3); + &LL(0xd7,0xd7,0x7b,0xd7,0xf6,0xac,0xb3,0x21); + &LL(0xc2,0xc2,0x2f,0xc2,0x5e,0xed,0x99,0x9c); + &LL(0x2e,0x2e,0xb8,0x2e,0x6d,0x96,0x5c,0x43); + &LL(0x4b,0x4b,0x31,0x4b,0x62,0x7a,0x96,0x29); + &LL(0xfe,0xfe,0xdf,0xfe,0xa3,0x21,0xe1,0x5d); + &LL(0x57,0x57,0x41,0x57,0x82,0x16,0xae,0xd5); + &LL(0x15,0x15,0x54,0x15,0xa8,0x41,0x2a,0xbd); + &LL(0x77,0x77,0xc1,0x77,0x9f,0xb6,0xee,0xe8); + &LL(0x37,0x37,0xdc,0x37,0xa5,0xeb,0x6e,0x92); + &LL(0xe5,0xe5,0xb3,0xe5,0x7b,0x56,0xd7,0x9e); + &LL(0x9f,0x9f,0x46,0x9f,0x8c,0xd9,0x23,0x13); + &LL(0xf0,0xf0,0xe7,0xf0,0xd3,0x17,0xfd,0x23); + &LL(0x4a,0x4a,0x35,0x4a,0x6a,0x7f,0x94,0x20); + &LL(0xda,0xda,0x4f,0xda,0x9e,0x95,0xa9,0x44); + &LL(0x58,0x58,0x7d,0x58,0xfa,0x25,0xb0,0xa2); + &LL(0xc9,0xc9,0x03,0xc9,0x06,0xca,0x8f,0xcf); + &LL(0x29,0x29,0xa4,0x29,0x55,0x8d,0x52,0x7c); + &LL(0x0a,0x0a,0x28,0x0a,0x50,0x22,0x14,0x5a); + &LL(0xb1,0xb1,0xfe,0xb1,0xe1,0x4f,0x7f,0x50); + &LL(0xa0,0xa0,0xba,0xa0,0x69,0x1a,0x5d,0xc9); + &LL(0x6b,0x6b,0xb1,0x6b,0x7f,0xda,0xd6,0x14); + &LL(0x85,0x85,0x2e,0x85,0x5c,0xab,0x17,0xd9); + &LL(0xbd,0xbd,0xce,0xbd,0x81,0x73,0x67,0x3c); + &LL(0x5d,0x5d,0x69,0x5d,0xd2,0x34,0xba,0x8f); + &LL(0x10,0x10,0x40,0x10,0x80,0x50,0x20,0x90); + &LL(0xf4,0xf4,0xf7,0xf4,0xf3,0x03,0xf5,0x07); + &LL(0xcb,0xcb,0x0b,0xcb,0x16,0xc0,0x8b,0xdd); + &LL(0x3e,0x3e,0xf8,0x3e,0xed,0xc6,0x7c,0xd3); + &LL(0x05,0x05,0x14,0x05,0x28,0x11,0x0a,0x2d); + &LL(0x67,0x67,0x81,0x67,0x1f,0xe6,0xce,0x78); + &LL(0xe4,0xe4,0xb7,0xe4,0x73,0x53,0xd5,0x97); + &LL(0x27,0x27,0x9c,0x27,0x25,0xbb,0x4e,0x02); + &LL(0x41,0x41,0x19,0x41,0x32,0x58,0x82,0x73); + &LL(0x8b,0x8b,0x16,0x8b,0x2c,0x9d,0x0b,0xa7); + &LL(0xa7,0xa7,0xa6,0xa7,0x51,0x01,0x53,0xf6); + &LL(0x7d,0x7d,0xe9,0x7d,0xcf,0x94,0xfa,0xb2); + &LL(0x95,0x95,0x6e,0x95,0xdc,0xfb,0x37,0x49); + &LL(0xd8,0xd8,0x47,0xd8,0x8e,0x9f,0xad,0x56); + &LL(0xfb,0xfb,0xcb,0xfb,0x8b,0x30,0xeb,0x70); + &LL(0xee,0xee,0x9f,0xee,0x23,0x71,0xc1,0xcd); + &LL(0x7c,0x7c,0xed,0x7c,0xc7,0x91,0xf8,0xbb); + &LL(0x66,0x66,0x85,0x66,0x17,0xe3,0xcc,0x71); + &LL(0xdd,0xdd,0x53,0xdd,0xa6,0x8e,0xa7,0x7b); + &LL(0x17,0x17,0x5c,0x17,0xb8,0x4b,0x2e,0xaf); + &LL(0x47,0x47,0x01,0x47,0x02,0x46,0x8e,0x45); + &LL(0x9e,0x9e,0x42,0x9e,0x84,0xdc,0x21,0x1a); + &LL(0xca,0xca,0x0f,0xca,0x1e,0xc5,0x89,0xd4); + &LL(0x2d,0x2d,0xb4,0x2d,0x75,0x99,0x5a,0x58); + &LL(0xbf,0xbf,0xc6,0xbf,0x91,0x79,0x63,0x2e); + &LL(0x07,0x07,0x1c,0x07,0x38,0x1b,0x0e,0x3f); + &LL(0xad,0xad,0x8e,0xad,0x01,0x23,0x47,0xac); + &LL(0x5a,0x5a,0x75,0x5a,0xea,0x2f,0xb4,0xb0); + &LL(0x83,0x83,0x36,0x83,0x6c,0xb5,0x1b,0xef); + &LL(0x33,0x33,0xcc,0x33,0x85,0xff,0x66,0xb6); + &LL(0x63,0x63,0x91,0x63,0x3f,0xf2,0xc6,0x5c); + &LL(0x02,0x02,0x08,0x02,0x10,0x0a,0x04,0x12); + &LL(0xaa,0xaa,0x92,0xaa,0x39,0x38,0x49,0x93); + &LL(0x71,0x71,0xd9,0x71,0xaf,0xa8,0xe2,0xde); + &LL(0xc8,0xc8,0x07,0xc8,0x0e,0xcf,0x8d,0xc6); + &LL(0x19,0x19,0x64,0x19,0xc8,0x7d,0x32,0xd1); + &LL(0x49,0x49,0x39,0x49,0x72,0x70,0x92,0x3b); + &LL(0xd9,0xd9,0x43,0xd9,0x86,0x9a,0xaf,0x5f); + &LL(0xf2,0xf2,0xef,0xf2,0xc3,0x1d,0xf9,0x31); + &LL(0xe3,0xe3,0xab,0xe3,0x4b,0x48,0xdb,0xa8); + &LL(0x5b,0x5b,0x71,0x5b,0xe2,0x2a,0xb6,0xb9); + &LL(0x88,0x88,0x1a,0x88,0x34,0x92,0x0d,0xbc); + &LL(0x9a,0x9a,0x52,0x9a,0xa4,0xc8,0x29,0x3e); + &LL(0x26,0x26,0x98,0x26,0x2d,0xbe,0x4c,0x0b); + &LL(0x32,0x32,0xc8,0x32,0x8d,0xfa,0x64,0xbf); + &LL(0xb0,0xb0,0xfa,0xb0,0xe9,0x4a,0x7d,0x59); + &LL(0xe9,0xe9,0x83,0xe9,0x1b,0x6a,0xcf,0xf2); + &LL(0x0f,0x0f,0x3c,0x0f,0x78,0x33,0x1e,0x77); + &LL(0xd5,0xd5,0x73,0xd5,0xe6,0xa6,0xb7,0x33); + &LL(0x80,0x80,0x3a,0x80,0x74,0xba,0x1d,0xf4); + &LL(0xbe,0xbe,0xc2,0xbe,0x99,0x7c,0x61,0x27); + &LL(0xcd,0xcd,0x13,0xcd,0x26,0xde,0x87,0xeb); + &LL(0x34,0x34,0xd0,0x34,0xbd,0xe4,0x68,0x89); + &LL(0x48,0x48,0x3d,0x48,0x7a,0x75,0x90,0x32); + &LL(0xff,0xff,0xdb,0xff,0xab,0x24,0xe3,0x54); + &LL(0x7a,0x7a,0xf5,0x7a,0xf7,0x8f,0xf4,0x8d); + &LL(0x90,0x90,0x7a,0x90,0xf4,0xea,0x3d,0x64); + &LL(0x5f,0x5f,0x61,0x5f,0xc2,0x3e,0xbe,0x9d); + &LL(0x20,0x20,0x80,0x20,0x1d,0xa0,0x40,0x3d); + &LL(0x68,0x68,0xbd,0x68,0x67,0xd5,0xd0,0x0f); + &LL(0x1a,0x1a,0x68,0x1a,0xd0,0x72,0x34,0xca); + &LL(0xae,0xae,0x82,0xae,0x19,0x2c,0x41,0xb7); + &LL(0xb4,0xb4,0xea,0xb4,0xc9,0x5e,0x75,0x7d); + &LL(0x54,0x54,0x4d,0x54,0x9a,0x19,0xa8,0xce); + &LL(0x93,0x93,0x76,0x93,0xec,0xe5,0x3b,0x7f); + &LL(0x22,0x22,0x88,0x22,0x0d,0xaa,0x44,0x2f); + &LL(0x64,0x64,0x8d,0x64,0x07,0xe9,0xc8,0x63); + &LL(0xf1,0xf1,0xe3,0xf1,0xdb,0x12,0xff,0x2a); + &LL(0x73,0x73,0xd1,0x73,0xbf,0xa2,0xe6,0xcc); + &LL(0x12,0x12,0x48,0x12,0x90,0x5a,0x24,0x82); + &LL(0x40,0x40,0x1d,0x40,0x3a,0x5d,0x80,0x7a); + &LL(0x08,0x08,0x20,0x08,0x40,0x28,0x10,0x48); + &LL(0xc3,0xc3,0x2b,0xc3,0x56,0xe8,0x9b,0x95); + &LL(0xec,0xec,0x97,0xec,0x33,0x7b,0xc5,0xdf); + &LL(0xdb,0xdb,0x4b,0xdb,0x96,0x90,0xab,0x4d); + &LL(0xa1,0xa1,0xbe,0xa1,0x61,0x1f,0x5f,0xc0); + &LL(0x8d,0x8d,0x0e,0x8d,0x1c,0x83,0x07,0x91); + &LL(0x3d,0x3d,0xf4,0x3d,0xf5,0xc9,0x7a,0xc8); + &LL(0x97,0x97,0x66,0x97,0xcc,0xf1,0x33,0x5b); + &LL(0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00); + &LL(0xcf,0xcf,0x1b,0xcf,0x36,0xd4,0x83,0xf9); + &LL(0x2b,0x2b,0xac,0x2b,0x45,0x87,0x56,0x6e); + &LL(0x76,0x76,0xc5,0x76,0x97,0xb3,0xec,0xe1); + &LL(0x82,0x82,0x32,0x82,0x64,0xb0,0x19,0xe6); + &LL(0xd6,0xd6,0x7f,0xd6,0xfe,0xa9,0xb1,0x28); + &LL(0x1b,0x1b,0x6c,0x1b,0xd8,0x77,0x36,0xc3); + &LL(0xb5,0xb5,0xee,0xb5,0xc1,0x5b,0x77,0x74); + &LL(0xaf,0xaf,0x86,0xaf,0x11,0x29,0x43,0xbe); + &LL(0x6a,0x6a,0xb5,0x6a,0x77,0xdf,0xd4,0x1d); + &LL(0x50,0x50,0x5d,0x50,0xba,0x0d,0xa0,0xea); + &LL(0x45,0x45,0x09,0x45,0x12,0x4c,0x8a,0x57); + &LL(0xf3,0xf3,0xeb,0xf3,0xcb,0x18,0xfb,0x38); + &LL(0x30,0x30,0xc0,0x30,0x9d,0xf0,0x60,0xad); + &LL(0xef,0xef,0x9b,0xef,0x2b,0x74,0xc3,0xc4); + &LL(0x3f,0x3f,0xfc,0x3f,0xe5,0xc3,0x7e,0xda); + &LL(0x55,0x55,0x49,0x55,0x92,0x1c,0xaa,0xc7); + &LL(0xa2,0xa2,0xb2,0xa2,0x79,0x10,0x59,0xdb); + &LL(0xea,0xea,0x8f,0xea,0x03,0x65,0xc9,0xe9); + &LL(0x65,0x65,0x89,0x65,0x0f,0xec,0xca,0x6a); + &LL(0xba,0xba,0xd2,0xba,0xb9,0x68,0x69,0x03); + &LL(0x2f,0x2f,0xbc,0x2f,0x65,0x93,0x5e,0x4a); + &LL(0xc0,0xc0,0x27,0xc0,0x4e,0xe7,0x9d,0x8e); + &LL(0xde,0xde,0x5f,0xde,0xbe,0x81,0xa1,0x60); + &LL(0x1c,0x1c,0x70,0x1c,0xe0,0x6c,0x38,0xfc); + &LL(0xfd,0xfd,0xd3,0xfd,0xbb,0x2e,0xe7,0x46); + &LL(0x4d,0x4d,0x29,0x4d,0x52,0x64,0x9a,0x1f); + &LL(0x92,0x92,0x72,0x92,0xe4,0xe0,0x39,0x76); + &LL(0x75,0x75,0xc9,0x75,0x8f,0xbc,0xea,0xfa); + &LL(0x06,0x06,0x18,0x06,0x30,0x1e,0x0c,0x36); + &LL(0x8a,0x8a,0x12,0x8a,0x24,0x98,0x09,0xae); + &LL(0xb2,0xb2,0xf2,0xb2,0xf9,0x40,0x79,0x4b); + &LL(0xe6,0xe6,0xbf,0xe6,0x63,0x59,0xd1,0x85); + &LL(0x0e,0x0e,0x38,0x0e,0x70,0x36,0x1c,0x7e); + &LL(0x1f,0x1f,0x7c,0x1f,0xf8,0x63,0x3e,0xe7); + &LL(0x62,0x62,0x95,0x62,0x37,0xf7,0xc4,0x55); + &LL(0xd4,0xd4,0x77,0xd4,0xee,0xa3,0xb5,0x3a); + &LL(0xa8,0xa8,0x9a,0xa8,0x29,0x32,0x4d,0x81); + &LL(0x96,0x96,0x62,0x96,0xc4,0xf4,0x31,0x52); + &LL(0xf9,0xf9,0xc3,0xf9,0x9b,0x3a,0xef,0x62); + &LL(0xc5,0xc5,0x33,0xc5,0x66,0xf6,0x97,0xa3); + &LL(0x25,0x25,0x94,0x25,0x35,0xb1,0x4a,0x10); + &LL(0x59,0x59,0x79,0x59,0xf2,0x20,0xb2,0xab); + &LL(0x84,0x84,0x2a,0x84,0x54,0xae,0x15,0xd0); + &LL(0x72,0x72,0xd5,0x72,0xb7,0xa7,0xe4,0xc5); + &LL(0x39,0x39,0xe4,0x39,0xd5,0xdd,0x72,0xec); + &LL(0x4c,0x4c,0x2d,0x4c,0x5a,0x61,0x98,0x16); + &LL(0x5e,0x5e,0x65,0x5e,0xca,0x3b,0xbc,0x94); + &LL(0x78,0x78,0xfd,0x78,0xe7,0x85,0xf0,0x9f); + &LL(0x38,0x38,0xe0,0x38,0xdd,0xd8,0x70,0xe5); + &LL(0x8c,0x8c,0x0a,0x8c,0x14,0x86,0x05,0x98); + &LL(0xd1,0xd1,0x63,0xd1,0xc6,0xb2,0xbf,0x17); + &LL(0xa5,0xa5,0xae,0xa5,0x41,0x0b,0x57,0xe4); + &LL(0xe2,0xe2,0xaf,0xe2,0x43,0x4d,0xd9,0xa1); + &LL(0x61,0x61,0x99,0x61,0x2f,0xf8,0xc2,0x4e); + &LL(0xb3,0xb3,0xf6,0xb3,0xf1,0x45,0x7b,0x42); + &LL(0x21,0x21,0x84,0x21,0x15,0xa5,0x42,0x34); + &LL(0x9c,0x9c,0x4a,0x9c,0x94,0xd6,0x25,0x08); + &LL(0x1e,0x1e,0x78,0x1e,0xf0,0x66,0x3c,0xee); + &LL(0x43,0x43,0x11,0x43,0x22,0x52,0x86,0x61); + &LL(0xc7,0xc7,0x3b,0xc7,0x76,0xfc,0x93,0xb1); + &LL(0xfc,0xfc,0xd7,0xfc,0xb3,0x2b,0xe5,0x4f); + &LL(0x04,0x04,0x10,0x04,0x20,0x14,0x08,0x24); + &LL(0x51,0x51,0x59,0x51,0xb2,0x08,0xa2,0xe3); + &LL(0x99,0x99,0x5e,0x99,0xbc,0xc7,0x2f,0x25); + &LL(0x6d,0x6d,0xa9,0x6d,0x4f,0xc4,0xda,0x22); + &LL(0x0d,0x0d,0x34,0x0d,0x68,0x39,0x1a,0x65); + &LL(0xfa,0xfa,0xcf,0xfa,0x83,0x35,0xe9,0x79); + &LL(0xdf,0xdf,0x5b,0xdf,0xb6,0x84,0xa3,0x69); + &LL(0x7e,0x7e,0xe5,0x7e,0xd7,0x9b,0xfc,0xa9); + &LL(0x24,0x24,0x90,0x24,0x3d,0xb4,0x48,0x19); + &LL(0x3b,0x3b,0xec,0x3b,0xc5,0xd7,0x76,0xfe); + &LL(0xab,0xab,0x96,0xab,0x31,0x3d,0x4b,0x9a); + &LL(0xce,0xce,0x1f,0xce,0x3e,0xd1,0x81,0xf0); + &LL(0x11,0x11,0x44,0x11,0x88,0x55,0x22,0x99); + &LL(0x8f,0x8f,0x06,0x8f,0x0c,0x89,0x03,0x83); + &LL(0x4e,0x4e,0x25,0x4e,0x4a,0x6b,0x9c,0x04); + &LL(0xb7,0xb7,0xe6,0xb7,0xd1,0x51,0x73,0x66); + &LL(0xeb,0xeb,0x8b,0xeb,0x0b,0x60,0xcb,0xe0); + &LL(0x3c,0x3c,0xf0,0x3c,0xfd,0xcc,0x78,0xc1); + &LL(0x81,0x81,0x3e,0x81,0x7c,0xbf,0x1f,0xfd); + &LL(0x94,0x94,0x6a,0x94,0xd4,0xfe,0x35,0x40); + &LL(0xf7,0xf7,0xfb,0xf7,0xeb,0x0c,0xf3,0x1c); + &LL(0xb9,0xb9,0xde,0xb9,0xa1,0x67,0x6f,0x18); + &LL(0x13,0x13,0x4c,0x13,0x98,0x5f,0x26,0x8b); + &LL(0x2c,0x2c,0xb0,0x2c,0x7d,0x9c,0x58,0x51); + &LL(0xd3,0xd3,0x6b,0xd3,0xd6,0xb8,0xbb,0x05); + &LL(0xe7,0xe7,0xbb,0xe7,0x6b,0x5c,0xd3,0x8c); + &LL(0x6e,0x6e,0xa5,0x6e,0x57,0xcb,0xdc,0x39); + &LL(0xc4,0xc4,0x37,0xc4,0x6e,0xf3,0x95,0xaa); + &LL(0x03,0x03,0x0c,0x03,0x18,0x0f,0x06,0x1b); + &LL(0x56,0x56,0x45,0x56,0x8a,0x13,0xac,0xdc); + &LL(0x44,0x44,0x0d,0x44,0x1a,0x49,0x88,0x5e); + &LL(0x7f,0x7f,0xe1,0x7f,0xdf,0x9e,0xfe,0xa0); + &LL(0xa9,0xa9,0x9e,0xa9,0x21,0x37,0x4f,0x88); + &LL(0x2a,0x2a,0xa8,0x2a,0x4d,0x82,0x54,0x67); + &LL(0xbb,0xbb,0xd6,0xbb,0xb1,0x6d,0x6b,0x0a); + &LL(0xc1,0xc1,0x23,0xc1,0x46,0xe2,0x9f,0x87); + &LL(0x53,0x53,0x51,0x53,0xa2,0x02,0xa6,0xf1); + &LL(0xdc,0xdc,0x57,0xdc,0xae,0x8b,0xa5,0x72); + &LL(0x0b,0x0b,0x2c,0x0b,0x58,0x27,0x16,0x53); + &LL(0x9d,0x9d,0x4e,0x9d,0x9c,0xd3,0x27,0x01); + &LL(0x6c,0x6c,0xad,0x6c,0x47,0xc1,0xd8,0x2b); + &LL(0x31,0x31,0xc4,0x31,0x95,0xf5,0x62,0xa4); + &LL(0x74,0x74,0xcd,0x74,0x87,0xb9,0xe8,0xf3); + &LL(0xf6,0xf6,0xff,0xf6,0xe3,0x09,0xf1,0x15); + &LL(0x46,0x46,0x05,0x46,0x0a,0x43,0x8c,0x4c); + &LL(0xac,0xac,0x8a,0xac,0x09,0x26,0x45,0xa5); + &LL(0x89,0x89,0x1e,0x89,0x3c,0x97,0x0f,0xb5); + &LL(0x14,0x14,0x50,0x14,0xa0,0x44,0x28,0xb4); + &LL(0xe1,0xe1,0xa3,0xe1,0x5b,0x42,0xdf,0xba); + &LL(0x16,0x16,0x58,0x16,0xb0,0x4e,0x2c,0xa6); + &LL(0x3a,0x3a,0xe8,0x3a,0xcd,0xd2,0x74,0xf7); + &LL(0x69,0x69,0xb9,0x69,0x6f,0xd0,0xd2,0x06); + &LL(0x09,0x09,0x24,0x09,0x48,0x2d,0x12,0x41); + &LL(0x70,0x70,0xdd,0x70,0xa7,0xad,0xe0,0xd7); + &LL(0xb6,0xb6,0xe2,0xb6,0xd9,0x54,0x71,0x6f); + &LL(0xd0,0xd0,0x67,0xd0,0xce,0xb7,0xbd,0x1e); + &LL(0xed,0xed,0x93,0xed,0x3b,0x7e,0xc7,0xd6); + &LL(0xcc,0xcc,0x17,0xcc,0x2e,0xdb,0x85,0xe2); + &LL(0x42,0x42,0x15,0x42,0x2a,0x57,0x84,0x68); + &LL(0x98,0x98,0x5a,0x98,0xb4,0xc2,0x2d,0x2c); + &LL(0xa4,0xa4,0xaa,0xa4,0x49,0x0e,0x55,0xed); + &LL(0x28,0x28,0xa0,0x28,0x5d,0x88,0x50,0x75); + &LL(0x5c,0x5c,0x6d,0x5c,0xda,0x31,0xb8,0x86); + &LL(0xf8,0xf8,0xc7,0xf8,0x93,0x3f,0xed,0x6b); + &LL(0x86,0x86,0x22,0x86,0x44,0xa4,0x11,0xc2); + + &L(0x18,0x23,0xc6,0xe8,0x87,0xb8,0x01,0x4f); # rc[ROUNDS] + &L(0x36,0xa6,0xd2,0xf5,0x79,0x6f,0x91,0x52); + &L(0x60,0xbc,0x9b,0x8e,0xa3,0x0c,0x7b,0x35); + &L(0x1d,0xe0,0xd7,0xc2,0x2e,0x4b,0xfe,0x57); + &L(0x15,0x77,0x37,0xe5,0x9f,0xf0,0x4a,0xda); + &L(0x58,0xc9,0x29,0x0a,0xb1,0xa0,0x6b,0x85); + &L(0xbd,0x5d,0x10,0xf4,0xcb,0x3e,0x05,0x67); + &L(0xe4,0x27,0x41,0x8b,0xa7,0x7d,0x95,0xd8); + &L(0xfb,0xee,0x7c,0x66,0xdd,0x17,0x47,0x9e); + &L(0xca,0x2d,0xbf,0x07,0xad,0x5a,0x83,0x33); + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type se_handler,\@abi-omnipotent +.align 16 +se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + lea .Lprologue(%rip),%r10 + cmp %r10,%rbx # context->Rip<.Lprologue + jb .Lin_prologue + + mov 152($context),%rax # pull context->Rsp + + lea .Lepilogue(%rip),%r10 + cmp %r10,%rbx # context->Rip>=.Lepilogue + jae .Lin_prologue + + mov 128+32(%rax),%rax # pull saved stack pointer + + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov -48(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + +.Lin_prologue: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size se_handler,.-se_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_$func + .rva .LSEH_end_$func + .rva .LSEH_info_$func + +.section .xdata +.align 8 +.LSEH_info_$func: + .byte 9,0,0,0 + .rva se_handler +___ +} + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +print $code; +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/whrlpool/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/whrlpool/build.info new file mode 100644 index 000000000..4b167b504 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/whrlpool/build.info @@ -0,0 +1,8 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=wp_dgst.c {- $target{wp_asm_src} -} + +GENERATE[wp-mmx.s]=asm/wp-mmx.pl \ + $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) +DEPEND[wp-mmx.s]=../perlasm/x86asm.pl + +GENERATE[wp-x86_64.s]=asm/wp-x86_64.pl $(PERLASM_SCHEME) diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/whrlpool/wp_block.c b/trunk/3rdparty/openssl-1.1-fit/crypto/whrlpool/wp_block.c new file mode 100644 index 000000000..0cc92a3b0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/whrlpool/wp_block.c @@ -0,0 +1,784 @@ +/* + * Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/** + * The Whirlpool hashing function. + * + * See + * P.S.L.M. Barreto, V. Rijmen, + * ``The Whirlpool hashing function,'' + * NESSIE submission, 2000 (tweaked version, 2001), + * + * + * Based on "@version 3.0 (2003.03.12)" by Paulo S.L.M. Barreto and + * Vincent Rijmen. Lookup "reference implementations" on + * + * + * ============================================================================= + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "wp_locl.h" +#include + +typedef unsigned char u8; +#if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32) +typedef unsigned __int64 u64; +#elif defined(__arch64__) +typedef unsigned long u64; +#else +typedef unsigned long long u64; +#endif + +#define ROUNDS 10 + +#define STRICT_ALIGNMENT +#if !defined(PEDANTIC) && (defined(__i386) || defined(__i386__) || \ + defined(__x86_64) || defined(__x86_64__) || \ + defined(_M_IX86) || defined(_M_AMD64) || \ + defined(_M_X64)) +/* + * Well, formally there're couple of other architectures, which permit + * unaligned loads, specifically those not crossing cache lines, IA-64 and + * PowerPC... + */ +# undef STRICT_ALIGNMENT +#endif + +#undef SMALL_REGISTER_BANK +#if defined(__i386) || defined(__i386__) || defined(_M_IX86) +# define SMALL_REGISTER_BANK +# if defined(WHIRLPOOL_ASM) +# ifndef OPENSSL_SMALL_FOOTPRINT +/* + * it appears that for elder non-MMX + * CPUs this is actually faster! + */ +# define OPENSSL_SMALL_FOOTPRINT +# endif +# define GO_FOR_MMX(ctx,inp,num) do { \ + extern unsigned long OPENSSL_ia32cap_P[]; \ + void whirlpool_block_mmx(void *,const void *,size_t); \ + if (!(OPENSSL_ia32cap_P[0] & (1<<23))) break; \ + whirlpool_block_mmx(ctx->H.c,inp,num); return; \ + } while (0) +# endif +#endif + +#undef ROTATE +#ifndef PEDANTIC +# if defined(_MSC_VER) +# if defined(_WIN64) /* applies to both IA-64 and AMD64 */ +# pragma intrinsic(_rotl64) +# define ROTATE(a,n) _rotl64((a),n) +# endif +# elif defined(__GNUC__) && __GNUC__>=2 +# if defined(__x86_64) || defined(__x86_64__) +# if defined(L_ENDIAN) +# define ROTATE(a,n) ({ u64 ret; asm ("rolq %1,%0" \ + : "=r"(ret) : "J"(n),"0"(a) : "cc"); ret; }) +# elif defined(B_ENDIAN) + /* + * Most will argue that x86_64 is always little-endian. Well, yes, but + * then we have stratus.com who has modified gcc to "emulate" + * big-endian on x86. Is there evidence that they [or somebody else] + * won't do same for x86_64? Naturally no. And this line is waiting + * ready for that brave soul:-) + */ +# define ROTATE(a,n) ({ u64 ret; asm ("rorq %1,%0" \ + : "=r"(ret) : "J"(n),"0"(a) : "cc"); ret; }) +# endif +# elif defined(__ia64) || defined(__ia64__) +# if defined(L_ENDIAN) +# define ROTATE(a,n) ({ u64 ret; asm ("shrp %0=%1,%1,%2" \ + : "=r"(ret) : "r"(a),"M"(64-(n))); ret; }) +# elif defined(B_ENDIAN) +# define ROTATE(a,n) ({ u64 ret; asm ("shrp %0=%1,%1,%2" \ + : "=r"(ret) : "r"(a),"M"(n)); ret; }) +# endif +# endif +# endif +#endif + +#if defined(OPENSSL_SMALL_FOOTPRINT) +# if !defined(ROTATE) +# if defined(L_ENDIAN) /* little-endians have to rotate left */ +# define ROTATE(i,n) ((i)<<(n) ^ (i)>>(64-n)) +# elif defined(B_ENDIAN) /* big-endians have to rotate right */ +# define ROTATE(i,n) ((i)>>(n) ^ (i)<<(64-n)) +# endif +# endif +# if defined(ROTATE) && !defined(STRICT_ALIGNMENT) +# define STRICT_ALIGNMENT /* ensure smallest table size */ +# endif +#endif + +/* + * Table size depends on STRICT_ALIGNMENT and whether or not endian- + * specific ROTATE macro is defined. If STRICT_ALIGNMENT is not + * defined, which is normally the case on x86[_64] CPUs, the table is + * 4KB large unconditionally. Otherwise if ROTATE is defined, the + * table is 2KB large, and otherwise - 16KB. 2KB table requires a + * whole bunch of additional rotations, but I'm willing to "trade," + * because 16KB table certainly trashes L1 cache. I wish all CPUs + * could handle unaligned load as 4KB table doesn't trash the cache, + * nor does it require additional rotations. + */ +/* + * Note that every Cn macro expands as two loads: one byte load and + * one quadword load. One can argue that that many single-byte loads + * is too excessive, as one could load a quadword and "milk" it for + * eight 8-bit values instead. Well, yes, but in order to do so *and* + * avoid excessive loads you have to accommodate a handful of 64-bit + * values in the register bank and issue a bunch of shifts and mask. + * It's a tradeoff: loads vs. shift and mask in big register bank[!]. + * On most CPUs eight single-byte loads are faster and I let other + * ones to depend on smart compiler to fold byte loads if beneficial. + * Hand-coded assembler would be another alternative:-) + */ +#ifdef STRICT_ALIGNMENT +# if defined(ROTATE) +# define N 1 +# define LL(c0,c1,c2,c3,c4,c5,c6,c7) c0,c1,c2,c3,c4,c5,c6,c7 +# define C0(K,i) (Cx.q[K.c[(i)*8+0]]) +# define C1(K,i) ROTATE(Cx.q[K.c[(i)*8+1]],8) +# define C2(K,i) ROTATE(Cx.q[K.c[(i)*8+2]],16) +# define C3(K,i) ROTATE(Cx.q[K.c[(i)*8+3]],24) +# define C4(K,i) ROTATE(Cx.q[K.c[(i)*8+4]],32) +# define C5(K,i) ROTATE(Cx.q[K.c[(i)*8+5]],40) +# define C6(K,i) ROTATE(Cx.q[K.c[(i)*8+6]],48) +# define C7(K,i) ROTATE(Cx.q[K.c[(i)*8+7]],56) +# else +# define N 8 +# define LL(c0,c1,c2,c3,c4,c5,c6,c7) c0,c1,c2,c3,c4,c5,c6,c7, \ + c7,c0,c1,c2,c3,c4,c5,c6, \ + c6,c7,c0,c1,c2,c3,c4,c5, \ + c5,c6,c7,c0,c1,c2,c3,c4, \ + c4,c5,c6,c7,c0,c1,c2,c3, \ + c3,c4,c5,c6,c7,c0,c1,c2, \ + c2,c3,c4,c5,c6,c7,c0,c1, \ + c1,c2,c3,c4,c5,c6,c7,c0 +# define C0(K,i) (Cx.q[0+8*K.c[(i)*8+0]]) +# define C1(K,i) (Cx.q[1+8*K.c[(i)*8+1]]) +# define C2(K,i) (Cx.q[2+8*K.c[(i)*8+2]]) +# define C3(K,i) (Cx.q[3+8*K.c[(i)*8+3]]) +# define C4(K,i) (Cx.q[4+8*K.c[(i)*8+4]]) +# define C5(K,i) (Cx.q[5+8*K.c[(i)*8+5]]) +# define C6(K,i) (Cx.q[6+8*K.c[(i)*8+6]]) +# define C7(K,i) (Cx.q[7+8*K.c[(i)*8+7]]) +# endif +#else +# define N 2 +# define LL(c0,c1,c2,c3,c4,c5,c6,c7) c0,c1,c2,c3,c4,c5,c6,c7, \ + c0,c1,c2,c3,c4,c5,c6,c7 +# define C0(K,i) (((u64*)(Cx.c+0))[2*K.c[(i)*8+0]]) +# define C1(K,i) (((u64*)(Cx.c+7))[2*K.c[(i)*8+1]]) +# define C2(K,i) (((u64*)(Cx.c+6))[2*K.c[(i)*8+2]]) +# define C3(K,i) (((u64*)(Cx.c+5))[2*K.c[(i)*8+3]]) +# define C4(K,i) (((u64*)(Cx.c+4))[2*K.c[(i)*8+4]]) +# define C5(K,i) (((u64*)(Cx.c+3))[2*K.c[(i)*8+5]]) +# define C6(K,i) (((u64*)(Cx.c+2))[2*K.c[(i)*8+6]]) +# define C7(K,i) (((u64*)(Cx.c+1))[2*K.c[(i)*8+7]]) +#endif + +static const + union { + u8 c[(256 * N + ROUNDS) * sizeof(u64)]; + u64 q[(256 * N + ROUNDS)]; +} Cx = { + { + /* Note endian-neutral representation:-) */ + LL(0x18, 0x18, 0x60, 0x18, 0xc0, 0x78, 0x30, 0xd8), + LL(0x23, 0x23, 0x8c, 0x23, 0x05, 0xaf, 0x46, 0x26), + LL(0xc6, 0xc6, 0x3f, 0xc6, 0x7e, 0xf9, 0x91, 0xb8), + LL(0xe8, 0xe8, 0x87, 0xe8, 0x13, 0x6f, 0xcd, 0xfb), + LL(0x87, 0x87, 0x26, 0x87, 0x4c, 0xa1, 0x13, 0xcb), + LL(0xb8, 0xb8, 0xda, 0xb8, 0xa9, 0x62, 0x6d, 0x11), + LL(0x01, 0x01, 0x04, 0x01, 0x08, 0x05, 0x02, 0x09), + LL(0x4f, 0x4f, 0x21, 0x4f, 0x42, 0x6e, 0x9e, 0x0d), + LL(0x36, 0x36, 0xd8, 0x36, 0xad, 0xee, 0x6c, 0x9b), + LL(0xa6, 0xa6, 0xa2, 0xa6, 0x59, 0x04, 0x51, 0xff), + LL(0xd2, 0xd2, 0x6f, 0xd2, 0xde, 0xbd, 0xb9, 0x0c), + LL(0xf5, 0xf5, 0xf3, 0xf5, 0xfb, 0x06, 0xf7, 0x0e), + LL(0x79, 0x79, 0xf9, 0x79, 0xef, 0x80, 0xf2, 0x96), + LL(0x6f, 0x6f, 0xa1, 0x6f, 0x5f, 0xce, 0xde, 0x30), + LL(0x91, 0x91, 0x7e, 0x91, 0xfc, 0xef, 0x3f, 0x6d), + LL(0x52, 0x52, 0x55, 0x52, 0xaa, 0x07, 0xa4, 0xf8), + LL(0x60, 0x60, 0x9d, 0x60, 0x27, 0xfd, 0xc0, 0x47), + LL(0xbc, 0xbc, 0xca, 0xbc, 0x89, 0x76, 0x65, 0x35), + LL(0x9b, 0x9b, 0x56, 0x9b, 0xac, 0xcd, 0x2b, 0x37), + LL(0x8e, 0x8e, 0x02, 0x8e, 0x04, 0x8c, 0x01, 0x8a), + LL(0xa3, 0xa3, 0xb6, 0xa3, 0x71, 0x15, 0x5b, 0xd2), + LL(0x0c, 0x0c, 0x30, 0x0c, 0x60, 0x3c, 0x18, 0x6c), + LL(0x7b, 0x7b, 0xf1, 0x7b, 0xff, 0x8a, 0xf6, 0x84), + LL(0x35, 0x35, 0xd4, 0x35, 0xb5, 0xe1, 0x6a, 0x80), + LL(0x1d, 0x1d, 0x74, 0x1d, 0xe8, 0x69, 0x3a, 0xf5), + LL(0xe0, 0xe0, 0xa7, 0xe0, 0x53, 0x47, 0xdd, 0xb3), + LL(0xd7, 0xd7, 0x7b, 0xd7, 0xf6, 0xac, 0xb3, 0x21), + LL(0xc2, 0xc2, 0x2f, 0xc2, 0x5e, 0xed, 0x99, 0x9c), + LL(0x2e, 0x2e, 0xb8, 0x2e, 0x6d, 0x96, 0x5c, 0x43), + LL(0x4b, 0x4b, 0x31, 0x4b, 0x62, 0x7a, 0x96, 0x29), + LL(0xfe, 0xfe, 0xdf, 0xfe, 0xa3, 0x21, 0xe1, 0x5d), + LL(0x57, 0x57, 0x41, 0x57, 0x82, 0x16, 0xae, 0xd5), + LL(0x15, 0x15, 0x54, 0x15, 0xa8, 0x41, 0x2a, 0xbd), + LL(0x77, 0x77, 0xc1, 0x77, 0x9f, 0xb6, 0xee, 0xe8), + LL(0x37, 0x37, 0xdc, 0x37, 0xa5, 0xeb, 0x6e, 0x92), + LL(0xe5, 0xe5, 0xb3, 0xe5, 0x7b, 0x56, 0xd7, 0x9e), + LL(0x9f, 0x9f, 0x46, 0x9f, 0x8c, 0xd9, 0x23, 0x13), + LL(0xf0, 0xf0, 0xe7, 0xf0, 0xd3, 0x17, 0xfd, 0x23), + LL(0x4a, 0x4a, 0x35, 0x4a, 0x6a, 0x7f, 0x94, 0x20), + LL(0xda, 0xda, 0x4f, 0xda, 0x9e, 0x95, 0xa9, 0x44), + LL(0x58, 0x58, 0x7d, 0x58, 0xfa, 0x25, 0xb0, 0xa2), + LL(0xc9, 0xc9, 0x03, 0xc9, 0x06, 0xca, 0x8f, 0xcf), + LL(0x29, 0x29, 0xa4, 0x29, 0x55, 0x8d, 0x52, 0x7c), + LL(0x0a, 0x0a, 0x28, 0x0a, 0x50, 0x22, 0x14, 0x5a), + LL(0xb1, 0xb1, 0xfe, 0xb1, 0xe1, 0x4f, 0x7f, 0x50), + LL(0xa0, 0xa0, 0xba, 0xa0, 0x69, 0x1a, 0x5d, 0xc9), + LL(0x6b, 0x6b, 0xb1, 0x6b, 0x7f, 0xda, 0xd6, 0x14), + LL(0x85, 0x85, 0x2e, 0x85, 0x5c, 0xab, 0x17, 0xd9), + LL(0xbd, 0xbd, 0xce, 0xbd, 0x81, 0x73, 0x67, 0x3c), + LL(0x5d, 0x5d, 0x69, 0x5d, 0xd2, 0x34, 0xba, 0x8f), + LL(0x10, 0x10, 0x40, 0x10, 0x80, 0x50, 0x20, 0x90), + LL(0xf4, 0xf4, 0xf7, 0xf4, 0xf3, 0x03, 0xf5, 0x07), + LL(0xcb, 0xcb, 0x0b, 0xcb, 0x16, 0xc0, 0x8b, 0xdd), + LL(0x3e, 0x3e, 0xf8, 0x3e, 0xed, 0xc6, 0x7c, 0xd3), + LL(0x05, 0x05, 0x14, 0x05, 0x28, 0x11, 0x0a, 0x2d), + LL(0x67, 0x67, 0x81, 0x67, 0x1f, 0xe6, 0xce, 0x78), + LL(0xe4, 0xe4, 0xb7, 0xe4, 0x73, 0x53, 0xd5, 0x97), + LL(0x27, 0x27, 0x9c, 0x27, 0x25, 0xbb, 0x4e, 0x02), + LL(0x41, 0x41, 0x19, 0x41, 0x32, 0x58, 0x82, 0x73), + LL(0x8b, 0x8b, 0x16, 0x8b, 0x2c, 0x9d, 0x0b, 0xa7), + LL(0xa7, 0xa7, 0xa6, 0xa7, 0x51, 0x01, 0x53, 0xf6), + LL(0x7d, 0x7d, 0xe9, 0x7d, 0xcf, 0x94, 0xfa, 0xb2), + LL(0x95, 0x95, 0x6e, 0x95, 0xdc, 0xfb, 0x37, 0x49), + LL(0xd8, 0xd8, 0x47, 0xd8, 0x8e, 0x9f, 0xad, 0x56), + LL(0xfb, 0xfb, 0xcb, 0xfb, 0x8b, 0x30, 0xeb, 0x70), + LL(0xee, 0xee, 0x9f, 0xee, 0x23, 0x71, 0xc1, 0xcd), + LL(0x7c, 0x7c, 0xed, 0x7c, 0xc7, 0x91, 0xf8, 0xbb), + LL(0x66, 0x66, 0x85, 0x66, 0x17, 0xe3, 0xcc, 0x71), + LL(0xdd, 0xdd, 0x53, 0xdd, 0xa6, 0x8e, 0xa7, 0x7b), + LL(0x17, 0x17, 0x5c, 0x17, 0xb8, 0x4b, 0x2e, 0xaf), + LL(0x47, 0x47, 0x01, 0x47, 0x02, 0x46, 0x8e, 0x45), + LL(0x9e, 0x9e, 0x42, 0x9e, 0x84, 0xdc, 0x21, 0x1a), + LL(0xca, 0xca, 0x0f, 0xca, 0x1e, 0xc5, 0x89, 0xd4), + LL(0x2d, 0x2d, 0xb4, 0x2d, 0x75, 0x99, 0x5a, 0x58), + LL(0xbf, 0xbf, 0xc6, 0xbf, 0x91, 0x79, 0x63, 0x2e), + LL(0x07, 0x07, 0x1c, 0x07, 0x38, 0x1b, 0x0e, 0x3f), + LL(0xad, 0xad, 0x8e, 0xad, 0x01, 0x23, 0x47, 0xac), + LL(0x5a, 0x5a, 0x75, 0x5a, 0xea, 0x2f, 0xb4, 0xb0), + LL(0x83, 0x83, 0x36, 0x83, 0x6c, 0xb5, 0x1b, 0xef), + LL(0x33, 0x33, 0xcc, 0x33, 0x85, 0xff, 0x66, 0xb6), + LL(0x63, 0x63, 0x91, 0x63, 0x3f, 0xf2, 0xc6, 0x5c), + LL(0x02, 0x02, 0x08, 0x02, 0x10, 0x0a, 0x04, 0x12), + LL(0xaa, 0xaa, 0x92, 0xaa, 0x39, 0x38, 0x49, 0x93), + LL(0x71, 0x71, 0xd9, 0x71, 0xaf, 0xa8, 0xe2, 0xde), + LL(0xc8, 0xc8, 0x07, 0xc8, 0x0e, 0xcf, 0x8d, 0xc6), + LL(0x19, 0x19, 0x64, 0x19, 0xc8, 0x7d, 0x32, 0xd1), + LL(0x49, 0x49, 0x39, 0x49, 0x72, 0x70, 0x92, 0x3b), + LL(0xd9, 0xd9, 0x43, 0xd9, 0x86, 0x9a, 0xaf, 0x5f), + LL(0xf2, 0xf2, 0xef, 0xf2, 0xc3, 0x1d, 0xf9, 0x31), + LL(0xe3, 0xe3, 0xab, 0xe3, 0x4b, 0x48, 0xdb, 0xa8), + LL(0x5b, 0x5b, 0x71, 0x5b, 0xe2, 0x2a, 0xb6, 0xb9), + LL(0x88, 0x88, 0x1a, 0x88, 0x34, 0x92, 0x0d, 0xbc), + LL(0x9a, 0x9a, 0x52, 0x9a, 0xa4, 0xc8, 0x29, 0x3e), + LL(0x26, 0x26, 0x98, 0x26, 0x2d, 0xbe, 0x4c, 0x0b), + LL(0x32, 0x32, 0xc8, 0x32, 0x8d, 0xfa, 0x64, 0xbf), + LL(0xb0, 0xb0, 0xfa, 0xb0, 0xe9, 0x4a, 0x7d, 0x59), + LL(0xe9, 0xe9, 0x83, 0xe9, 0x1b, 0x6a, 0xcf, 0xf2), + LL(0x0f, 0x0f, 0x3c, 0x0f, 0x78, 0x33, 0x1e, 0x77), + LL(0xd5, 0xd5, 0x73, 0xd5, 0xe6, 0xa6, 0xb7, 0x33), + LL(0x80, 0x80, 0x3a, 0x80, 0x74, 0xba, 0x1d, 0xf4), + LL(0xbe, 0xbe, 0xc2, 0xbe, 0x99, 0x7c, 0x61, 0x27), + LL(0xcd, 0xcd, 0x13, 0xcd, 0x26, 0xde, 0x87, 0xeb), + LL(0x34, 0x34, 0xd0, 0x34, 0xbd, 0xe4, 0x68, 0x89), + LL(0x48, 0x48, 0x3d, 0x48, 0x7a, 0x75, 0x90, 0x32), + LL(0xff, 0xff, 0xdb, 0xff, 0xab, 0x24, 0xe3, 0x54), + LL(0x7a, 0x7a, 0xf5, 0x7a, 0xf7, 0x8f, 0xf4, 0x8d), + LL(0x90, 0x90, 0x7a, 0x90, 0xf4, 0xea, 0x3d, 0x64), + LL(0x5f, 0x5f, 0x61, 0x5f, 0xc2, 0x3e, 0xbe, 0x9d), + LL(0x20, 0x20, 0x80, 0x20, 0x1d, 0xa0, 0x40, 0x3d), + LL(0x68, 0x68, 0xbd, 0x68, 0x67, 0xd5, 0xd0, 0x0f), + LL(0x1a, 0x1a, 0x68, 0x1a, 0xd0, 0x72, 0x34, 0xca), + LL(0xae, 0xae, 0x82, 0xae, 0x19, 0x2c, 0x41, 0xb7), + LL(0xb4, 0xb4, 0xea, 0xb4, 0xc9, 0x5e, 0x75, 0x7d), + LL(0x54, 0x54, 0x4d, 0x54, 0x9a, 0x19, 0xa8, 0xce), + LL(0x93, 0x93, 0x76, 0x93, 0xec, 0xe5, 0x3b, 0x7f), + LL(0x22, 0x22, 0x88, 0x22, 0x0d, 0xaa, 0x44, 0x2f), + LL(0x64, 0x64, 0x8d, 0x64, 0x07, 0xe9, 0xc8, 0x63), + LL(0xf1, 0xf1, 0xe3, 0xf1, 0xdb, 0x12, 0xff, 0x2a), + LL(0x73, 0x73, 0xd1, 0x73, 0xbf, 0xa2, 0xe6, 0xcc), + LL(0x12, 0x12, 0x48, 0x12, 0x90, 0x5a, 0x24, 0x82), + LL(0x40, 0x40, 0x1d, 0x40, 0x3a, 0x5d, 0x80, 0x7a), + LL(0x08, 0x08, 0x20, 0x08, 0x40, 0x28, 0x10, 0x48), + LL(0xc3, 0xc3, 0x2b, 0xc3, 0x56, 0xe8, 0x9b, 0x95), + LL(0xec, 0xec, 0x97, 0xec, 0x33, 0x7b, 0xc5, 0xdf), + LL(0xdb, 0xdb, 0x4b, 0xdb, 0x96, 0x90, 0xab, 0x4d), + LL(0xa1, 0xa1, 0xbe, 0xa1, 0x61, 0x1f, 0x5f, 0xc0), + LL(0x8d, 0x8d, 0x0e, 0x8d, 0x1c, 0x83, 0x07, 0x91), + LL(0x3d, 0x3d, 0xf4, 0x3d, 0xf5, 0xc9, 0x7a, 0xc8), + LL(0x97, 0x97, 0x66, 0x97, 0xcc, 0xf1, 0x33, 0x5b), + LL(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + LL(0xcf, 0xcf, 0x1b, 0xcf, 0x36, 0xd4, 0x83, 0xf9), + LL(0x2b, 0x2b, 0xac, 0x2b, 0x45, 0x87, 0x56, 0x6e), + LL(0x76, 0x76, 0xc5, 0x76, 0x97, 0xb3, 0xec, 0xe1), + LL(0x82, 0x82, 0x32, 0x82, 0x64, 0xb0, 0x19, 0xe6), + LL(0xd6, 0xd6, 0x7f, 0xd6, 0xfe, 0xa9, 0xb1, 0x28), + LL(0x1b, 0x1b, 0x6c, 0x1b, 0xd8, 0x77, 0x36, 0xc3), + LL(0xb5, 0xb5, 0xee, 0xb5, 0xc1, 0x5b, 0x77, 0x74), + LL(0xaf, 0xaf, 0x86, 0xaf, 0x11, 0x29, 0x43, 0xbe), + LL(0x6a, 0x6a, 0xb5, 0x6a, 0x77, 0xdf, 0xd4, 0x1d), + LL(0x50, 0x50, 0x5d, 0x50, 0xba, 0x0d, 0xa0, 0xea), + LL(0x45, 0x45, 0x09, 0x45, 0x12, 0x4c, 0x8a, 0x57), + LL(0xf3, 0xf3, 0xeb, 0xf3, 0xcb, 0x18, 0xfb, 0x38), + LL(0x30, 0x30, 0xc0, 0x30, 0x9d, 0xf0, 0x60, 0xad), + LL(0xef, 0xef, 0x9b, 0xef, 0x2b, 0x74, 0xc3, 0xc4), + LL(0x3f, 0x3f, 0xfc, 0x3f, 0xe5, 0xc3, 0x7e, 0xda), + LL(0x55, 0x55, 0x49, 0x55, 0x92, 0x1c, 0xaa, 0xc7), + LL(0xa2, 0xa2, 0xb2, 0xa2, 0x79, 0x10, 0x59, 0xdb), + LL(0xea, 0xea, 0x8f, 0xea, 0x03, 0x65, 0xc9, 0xe9), + LL(0x65, 0x65, 0x89, 0x65, 0x0f, 0xec, 0xca, 0x6a), + LL(0xba, 0xba, 0xd2, 0xba, 0xb9, 0x68, 0x69, 0x03), + LL(0x2f, 0x2f, 0xbc, 0x2f, 0x65, 0x93, 0x5e, 0x4a), + LL(0xc0, 0xc0, 0x27, 0xc0, 0x4e, 0xe7, 0x9d, 0x8e), + LL(0xde, 0xde, 0x5f, 0xde, 0xbe, 0x81, 0xa1, 0x60), + LL(0x1c, 0x1c, 0x70, 0x1c, 0xe0, 0x6c, 0x38, 0xfc), + LL(0xfd, 0xfd, 0xd3, 0xfd, 0xbb, 0x2e, 0xe7, 0x46), + LL(0x4d, 0x4d, 0x29, 0x4d, 0x52, 0x64, 0x9a, 0x1f), + LL(0x92, 0x92, 0x72, 0x92, 0xe4, 0xe0, 0x39, 0x76), + LL(0x75, 0x75, 0xc9, 0x75, 0x8f, 0xbc, 0xea, 0xfa), + LL(0x06, 0x06, 0x18, 0x06, 0x30, 0x1e, 0x0c, 0x36), + LL(0x8a, 0x8a, 0x12, 0x8a, 0x24, 0x98, 0x09, 0xae), + LL(0xb2, 0xb2, 0xf2, 0xb2, 0xf9, 0x40, 0x79, 0x4b), + LL(0xe6, 0xe6, 0xbf, 0xe6, 0x63, 0x59, 0xd1, 0x85), + LL(0x0e, 0x0e, 0x38, 0x0e, 0x70, 0x36, 0x1c, 0x7e), + LL(0x1f, 0x1f, 0x7c, 0x1f, 0xf8, 0x63, 0x3e, 0xe7), + LL(0x62, 0x62, 0x95, 0x62, 0x37, 0xf7, 0xc4, 0x55), + LL(0xd4, 0xd4, 0x77, 0xd4, 0xee, 0xa3, 0xb5, 0x3a), + LL(0xa8, 0xa8, 0x9a, 0xa8, 0x29, 0x32, 0x4d, 0x81), + LL(0x96, 0x96, 0x62, 0x96, 0xc4, 0xf4, 0x31, 0x52), + LL(0xf9, 0xf9, 0xc3, 0xf9, 0x9b, 0x3a, 0xef, 0x62), + LL(0xc5, 0xc5, 0x33, 0xc5, 0x66, 0xf6, 0x97, 0xa3), + LL(0x25, 0x25, 0x94, 0x25, 0x35, 0xb1, 0x4a, 0x10), + LL(0x59, 0x59, 0x79, 0x59, 0xf2, 0x20, 0xb2, 0xab), + LL(0x84, 0x84, 0x2a, 0x84, 0x54, 0xae, 0x15, 0xd0), + LL(0x72, 0x72, 0xd5, 0x72, 0xb7, 0xa7, 0xe4, 0xc5), + LL(0x39, 0x39, 0xe4, 0x39, 0xd5, 0xdd, 0x72, 0xec), + LL(0x4c, 0x4c, 0x2d, 0x4c, 0x5a, 0x61, 0x98, 0x16), + LL(0x5e, 0x5e, 0x65, 0x5e, 0xca, 0x3b, 0xbc, 0x94), + LL(0x78, 0x78, 0xfd, 0x78, 0xe7, 0x85, 0xf0, 0x9f), + LL(0x38, 0x38, 0xe0, 0x38, 0xdd, 0xd8, 0x70, 0xe5), + LL(0x8c, 0x8c, 0x0a, 0x8c, 0x14, 0x86, 0x05, 0x98), + LL(0xd1, 0xd1, 0x63, 0xd1, 0xc6, 0xb2, 0xbf, 0x17), + LL(0xa5, 0xa5, 0xae, 0xa5, 0x41, 0x0b, 0x57, 0xe4), + LL(0xe2, 0xe2, 0xaf, 0xe2, 0x43, 0x4d, 0xd9, 0xa1), + LL(0x61, 0x61, 0x99, 0x61, 0x2f, 0xf8, 0xc2, 0x4e), + LL(0xb3, 0xb3, 0xf6, 0xb3, 0xf1, 0x45, 0x7b, 0x42), + LL(0x21, 0x21, 0x84, 0x21, 0x15, 0xa5, 0x42, 0x34), + LL(0x9c, 0x9c, 0x4a, 0x9c, 0x94, 0xd6, 0x25, 0x08), + LL(0x1e, 0x1e, 0x78, 0x1e, 0xf0, 0x66, 0x3c, 0xee), + LL(0x43, 0x43, 0x11, 0x43, 0x22, 0x52, 0x86, 0x61), + LL(0xc7, 0xc7, 0x3b, 0xc7, 0x76, 0xfc, 0x93, 0xb1), + LL(0xfc, 0xfc, 0xd7, 0xfc, 0xb3, 0x2b, 0xe5, 0x4f), + LL(0x04, 0x04, 0x10, 0x04, 0x20, 0x14, 0x08, 0x24), + LL(0x51, 0x51, 0x59, 0x51, 0xb2, 0x08, 0xa2, 0xe3), + LL(0x99, 0x99, 0x5e, 0x99, 0xbc, 0xc7, 0x2f, 0x25), + LL(0x6d, 0x6d, 0xa9, 0x6d, 0x4f, 0xc4, 0xda, 0x22), + LL(0x0d, 0x0d, 0x34, 0x0d, 0x68, 0x39, 0x1a, 0x65), + LL(0xfa, 0xfa, 0xcf, 0xfa, 0x83, 0x35, 0xe9, 0x79), + LL(0xdf, 0xdf, 0x5b, 0xdf, 0xb6, 0x84, 0xa3, 0x69), + LL(0x7e, 0x7e, 0xe5, 0x7e, 0xd7, 0x9b, 0xfc, 0xa9), + LL(0x24, 0x24, 0x90, 0x24, 0x3d, 0xb4, 0x48, 0x19), + LL(0x3b, 0x3b, 0xec, 0x3b, 0xc5, 0xd7, 0x76, 0xfe), + LL(0xab, 0xab, 0x96, 0xab, 0x31, 0x3d, 0x4b, 0x9a), + LL(0xce, 0xce, 0x1f, 0xce, 0x3e, 0xd1, 0x81, 0xf0), + LL(0x11, 0x11, 0x44, 0x11, 0x88, 0x55, 0x22, 0x99), + LL(0x8f, 0x8f, 0x06, 0x8f, 0x0c, 0x89, 0x03, 0x83), + LL(0x4e, 0x4e, 0x25, 0x4e, 0x4a, 0x6b, 0x9c, 0x04), + LL(0xb7, 0xb7, 0xe6, 0xb7, 0xd1, 0x51, 0x73, 0x66), + LL(0xeb, 0xeb, 0x8b, 0xeb, 0x0b, 0x60, 0xcb, 0xe0), + LL(0x3c, 0x3c, 0xf0, 0x3c, 0xfd, 0xcc, 0x78, 0xc1), + LL(0x81, 0x81, 0x3e, 0x81, 0x7c, 0xbf, 0x1f, 0xfd), + LL(0x94, 0x94, 0x6a, 0x94, 0xd4, 0xfe, 0x35, 0x40), + LL(0xf7, 0xf7, 0xfb, 0xf7, 0xeb, 0x0c, 0xf3, 0x1c), + LL(0xb9, 0xb9, 0xde, 0xb9, 0xa1, 0x67, 0x6f, 0x18), + LL(0x13, 0x13, 0x4c, 0x13, 0x98, 0x5f, 0x26, 0x8b), + LL(0x2c, 0x2c, 0xb0, 0x2c, 0x7d, 0x9c, 0x58, 0x51), + LL(0xd3, 0xd3, 0x6b, 0xd3, 0xd6, 0xb8, 0xbb, 0x05), + LL(0xe7, 0xe7, 0xbb, 0xe7, 0x6b, 0x5c, 0xd3, 0x8c), + LL(0x6e, 0x6e, 0xa5, 0x6e, 0x57, 0xcb, 0xdc, 0x39), + LL(0xc4, 0xc4, 0x37, 0xc4, 0x6e, 0xf3, 0x95, 0xaa), + LL(0x03, 0x03, 0x0c, 0x03, 0x18, 0x0f, 0x06, 0x1b), + LL(0x56, 0x56, 0x45, 0x56, 0x8a, 0x13, 0xac, 0xdc), + LL(0x44, 0x44, 0x0d, 0x44, 0x1a, 0x49, 0x88, 0x5e), + LL(0x7f, 0x7f, 0xe1, 0x7f, 0xdf, 0x9e, 0xfe, 0xa0), + LL(0xa9, 0xa9, 0x9e, 0xa9, 0x21, 0x37, 0x4f, 0x88), + LL(0x2a, 0x2a, 0xa8, 0x2a, 0x4d, 0x82, 0x54, 0x67), + LL(0xbb, 0xbb, 0xd6, 0xbb, 0xb1, 0x6d, 0x6b, 0x0a), + LL(0xc1, 0xc1, 0x23, 0xc1, 0x46, 0xe2, 0x9f, 0x87), + LL(0x53, 0x53, 0x51, 0x53, 0xa2, 0x02, 0xa6, 0xf1), + LL(0xdc, 0xdc, 0x57, 0xdc, 0xae, 0x8b, 0xa5, 0x72), + LL(0x0b, 0x0b, 0x2c, 0x0b, 0x58, 0x27, 0x16, 0x53), + LL(0x9d, 0x9d, 0x4e, 0x9d, 0x9c, 0xd3, 0x27, 0x01), + LL(0x6c, 0x6c, 0xad, 0x6c, 0x47, 0xc1, 0xd8, 0x2b), + LL(0x31, 0x31, 0xc4, 0x31, 0x95, 0xf5, 0x62, 0xa4), + LL(0x74, 0x74, 0xcd, 0x74, 0x87, 0xb9, 0xe8, 0xf3), + LL(0xf6, 0xf6, 0xff, 0xf6, 0xe3, 0x09, 0xf1, 0x15), + LL(0x46, 0x46, 0x05, 0x46, 0x0a, 0x43, 0x8c, 0x4c), + LL(0xac, 0xac, 0x8a, 0xac, 0x09, 0x26, 0x45, 0xa5), + LL(0x89, 0x89, 0x1e, 0x89, 0x3c, 0x97, 0x0f, 0xb5), + LL(0x14, 0x14, 0x50, 0x14, 0xa0, 0x44, 0x28, 0xb4), + LL(0xe1, 0xe1, 0xa3, 0xe1, 0x5b, 0x42, 0xdf, 0xba), + LL(0x16, 0x16, 0x58, 0x16, 0xb0, 0x4e, 0x2c, 0xa6), + LL(0x3a, 0x3a, 0xe8, 0x3a, 0xcd, 0xd2, 0x74, 0xf7), + LL(0x69, 0x69, 0xb9, 0x69, 0x6f, 0xd0, 0xd2, 0x06), + LL(0x09, 0x09, 0x24, 0x09, 0x48, 0x2d, 0x12, 0x41), + LL(0x70, 0x70, 0xdd, 0x70, 0xa7, 0xad, 0xe0, 0xd7), + LL(0xb6, 0xb6, 0xe2, 0xb6, 0xd9, 0x54, 0x71, 0x6f), + LL(0xd0, 0xd0, 0x67, 0xd0, 0xce, 0xb7, 0xbd, 0x1e), + LL(0xed, 0xed, 0x93, 0xed, 0x3b, 0x7e, 0xc7, 0xd6), + LL(0xcc, 0xcc, 0x17, 0xcc, 0x2e, 0xdb, 0x85, 0xe2), + LL(0x42, 0x42, 0x15, 0x42, 0x2a, 0x57, 0x84, 0x68), + LL(0x98, 0x98, 0x5a, 0x98, 0xb4, 0xc2, 0x2d, 0x2c), + LL(0xa4, 0xa4, 0xaa, 0xa4, 0x49, 0x0e, 0x55, 0xed), + LL(0x28, 0x28, 0xa0, 0x28, 0x5d, 0x88, 0x50, 0x75), + LL(0x5c, 0x5c, 0x6d, 0x5c, 0xda, 0x31, 0xb8, 0x86), + LL(0xf8, 0xf8, 0xc7, 0xf8, 0x93, 0x3f, 0xed, 0x6b), + LL(0x86, 0x86, 0x22, 0x86, 0x44, 0xa4, 0x11, 0xc2), +#define RC (&(Cx.q[256*N])) + 0x18, 0x23, 0xc6, 0xe8, 0x87, 0xb8, 0x01, 0x4f, + /* rc[ROUNDS] */ + 0x36, 0xa6, 0xd2, 0xf5, 0x79, 0x6f, 0x91, 0x52, 0x60, 0xbc, 0x9b, + 0x8e, 0xa3, 0x0c, 0x7b, 0x35, 0x1d, 0xe0, 0xd7, 0xc2, 0x2e, 0x4b, + 0xfe, 0x57, 0x15, 0x77, 0x37, 0xe5, 0x9f, 0xf0, 0x4a, 0xda, 0x58, + 0xc9, 0x29, 0x0a, 0xb1, 0xa0, 0x6b, 0x85, 0xbd, 0x5d, 0x10, 0xf4, + 0xcb, 0x3e, 0x05, 0x67, 0xe4, 0x27, 0x41, 0x8b, 0xa7, 0x7d, 0x95, + 0xd8, 0xfb, 0xee, 0x7c, 0x66, 0xdd, 0x17, 0x47, 0x9e, 0xca, 0x2d, + 0xbf, 0x07, 0xad, 0x5a, 0x83, 0x33 + } + }; + +void whirlpool_block(WHIRLPOOL_CTX *ctx, const void *inp, size_t n) +{ + int r; + const u8 *p = inp; + union { + u64 q[8]; + u8 c[64]; + } S, K, *H = (void *)ctx->H.q; + +#ifdef GO_FOR_MMX + GO_FOR_MMX(ctx, inp, n); +#endif + do { +#ifdef OPENSSL_SMALL_FOOTPRINT + u64 L[8]; + int i; + + for (i = 0; i < 64; i++) + S.c[i] = (K.c[i] = H->c[i]) ^ p[i]; + for (r = 0; r < ROUNDS; r++) { + for (i = 0; i < 8; i++) { + L[i] = i ? 0 : RC[r]; + L[i] ^= C0(K, i) ^ C1(K, (i - 1) & 7) ^ + C2(K, (i - 2) & 7) ^ C3(K, (i - 3) & 7) ^ + C4(K, (i - 4) & 7) ^ C5(K, (i - 5) & 7) ^ + C6(K, (i - 6) & 7) ^ C7(K, (i - 7) & 7); + } + memcpy(K.q, L, 64); + for (i = 0; i < 8; i++) { + L[i] ^= C0(S, i) ^ C1(S, (i - 1) & 7) ^ + C2(S, (i - 2) & 7) ^ C3(S, (i - 3) & 7) ^ + C4(S, (i - 4) & 7) ^ C5(S, (i - 5) & 7) ^ + C6(S, (i - 6) & 7) ^ C7(S, (i - 7) & 7); + } + memcpy(S.q, L, 64); + } + for (i = 0; i < 64; i++) + H->c[i] ^= S.c[i] ^ p[i]; +#else + u64 L0, L1, L2, L3, L4, L5, L6, L7; + +# ifdef STRICT_ALIGNMENT + if ((size_t)p & 7) { + memcpy(S.c, p, 64); + S.q[0] ^= (K.q[0] = H->q[0]); + S.q[1] ^= (K.q[1] = H->q[1]); + S.q[2] ^= (K.q[2] = H->q[2]); + S.q[3] ^= (K.q[3] = H->q[3]); + S.q[4] ^= (K.q[4] = H->q[4]); + S.q[5] ^= (K.q[5] = H->q[5]); + S.q[6] ^= (K.q[6] = H->q[6]); + S.q[7] ^= (K.q[7] = H->q[7]); + } else +# endif + { + const u64 *pa = (const u64 *)p; + S.q[0] = (K.q[0] = H->q[0]) ^ pa[0]; + S.q[1] = (K.q[1] = H->q[1]) ^ pa[1]; + S.q[2] = (K.q[2] = H->q[2]) ^ pa[2]; + S.q[3] = (K.q[3] = H->q[3]) ^ pa[3]; + S.q[4] = (K.q[4] = H->q[4]) ^ pa[4]; + S.q[5] = (K.q[5] = H->q[5]) ^ pa[5]; + S.q[6] = (K.q[6] = H->q[6]) ^ pa[6]; + S.q[7] = (K.q[7] = H->q[7]) ^ pa[7]; + } + + for (r = 0; r < ROUNDS; r++) { +# ifdef SMALL_REGISTER_BANK + L0 = C0(K, 0) ^ C1(K, 7) ^ C2(K, 6) ^ C3(K, 5) ^ + C4(K, 4) ^ C5(K, 3) ^ C6(K, 2) ^ C7(K, 1) ^ RC[r]; + L1 = C0(K, 1) ^ C1(K, 0) ^ C2(K, 7) ^ C3(K, 6) ^ + C4(K, 5) ^ C5(K, 4) ^ C6(K, 3) ^ C7(K, 2); + L2 = C0(K, 2) ^ C1(K, 1) ^ C2(K, 0) ^ C3(K, 7) ^ + C4(K, 6) ^ C5(K, 5) ^ C6(K, 4) ^ C7(K, 3); + L3 = C0(K, 3) ^ C1(K, 2) ^ C2(K, 1) ^ C3(K, 0) ^ + C4(K, 7) ^ C5(K, 6) ^ C6(K, 5) ^ C7(K, 4); + L4 = C0(K, 4) ^ C1(K, 3) ^ C2(K, 2) ^ C3(K, 1) ^ + C4(K, 0) ^ C5(K, 7) ^ C6(K, 6) ^ C7(K, 5); + L5 = C0(K, 5) ^ C1(K, 4) ^ C2(K, 3) ^ C3(K, 2) ^ + C4(K, 1) ^ C5(K, 0) ^ C6(K, 7) ^ C7(K, 6); + L6 = C0(K, 6) ^ C1(K, 5) ^ C2(K, 4) ^ C3(K, 3) ^ + C4(K, 2) ^ C5(K, 1) ^ C6(K, 0) ^ C7(K, 7); + L7 = C0(K, 7) ^ C1(K, 6) ^ C2(K, 5) ^ C3(K, 4) ^ + C4(K, 3) ^ C5(K, 2) ^ C6(K, 1) ^ C7(K, 0); + + K.q[0] = L0; + K.q[1] = L1; + K.q[2] = L2; + K.q[3] = L3; + K.q[4] = L4; + K.q[5] = L5; + K.q[6] = L6; + K.q[7] = L7; + + L0 ^= C0(S, 0) ^ C1(S, 7) ^ C2(S, 6) ^ C3(S, 5) ^ + C4(S, 4) ^ C5(S, 3) ^ C6(S, 2) ^ C7(S, 1); + L1 ^= C0(S, 1) ^ C1(S, 0) ^ C2(S, 7) ^ C3(S, 6) ^ + C4(S, 5) ^ C5(S, 4) ^ C6(S, 3) ^ C7(S, 2); + L2 ^= C0(S, 2) ^ C1(S, 1) ^ C2(S, 0) ^ C3(S, 7) ^ + C4(S, 6) ^ C5(S, 5) ^ C6(S, 4) ^ C7(S, 3); + L3 ^= C0(S, 3) ^ C1(S, 2) ^ C2(S, 1) ^ C3(S, 0) ^ + C4(S, 7) ^ C5(S, 6) ^ C6(S, 5) ^ C7(S, 4); + L4 ^= C0(S, 4) ^ C1(S, 3) ^ C2(S, 2) ^ C3(S, 1) ^ + C4(S, 0) ^ C5(S, 7) ^ C6(S, 6) ^ C7(S, 5); + L5 ^= C0(S, 5) ^ C1(S, 4) ^ C2(S, 3) ^ C3(S, 2) ^ + C4(S, 1) ^ C5(S, 0) ^ C6(S, 7) ^ C7(S, 6); + L6 ^= C0(S, 6) ^ C1(S, 5) ^ C2(S, 4) ^ C3(S, 3) ^ + C4(S, 2) ^ C5(S, 1) ^ C6(S, 0) ^ C7(S, 7); + L7 ^= C0(S, 7) ^ C1(S, 6) ^ C2(S, 5) ^ C3(S, 4) ^ + C4(S, 3) ^ C5(S, 2) ^ C6(S, 1) ^ C7(S, 0); + + S.q[0] = L0; + S.q[1] = L1; + S.q[2] = L2; + S.q[3] = L3; + S.q[4] = L4; + S.q[5] = L5; + S.q[6] = L6; + S.q[7] = L7; +# else + L0 = C0(K, 0); + L1 = C1(K, 0); + L2 = C2(K, 0); + L3 = C3(K, 0); + L4 = C4(K, 0); + L5 = C5(K, 0); + L6 = C6(K, 0); + L7 = C7(K, 0); + L0 ^= RC[r]; + + L1 ^= C0(K, 1); + L2 ^= C1(K, 1); + L3 ^= C2(K, 1); + L4 ^= C3(K, 1); + L5 ^= C4(K, 1); + L6 ^= C5(K, 1); + L7 ^= C6(K, 1); + L0 ^= C7(K, 1); + + L2 ^= C0(K, 2); + L3 ^= C1(K, 2); + L4 ^= C2(K, 2); + L5 ^= C3(K, 2); + L6 ^= C4(K, 2); + L7 ^= C5(K, 2); + L0 ^= C6(K, 2); + L1 ^= C7(K, 2); + + L3 ^= C0(K, 3); + L4 ^= C1(K, 3); + L5 ^= C2(K, 3); + L6 ^= C3(K, 3); + L7 ^= C4(K, 3); + L0 ^= C5(K, 3); + L1 ^= C6(K, 3); + L2 ^= C7(K, 3); + + L4 ^= C0(K, 4); + L5 ^= C1(K, 4); + L6 ^= C2(K, 4); + L7 ^= C3(K, 4); + L0 ^= C4(K, 4); + L1 ^= C5(K, 4); + L2 ^= C6(K, 4); + L3 ^= C7(K, 4); + + L5 ^= C0(K, 5); + L6 ^= C1(K, 5); + L7 ^= C2(K, 5); + L0 ^= C3(K, 5); + L1 ^= C4(K, 5); + L2 ^= C5(K, 5); + L3 ^= C6(K, 5); + L4 ^= C7(K, 5); + + L6 ^= C0(K, 6); + L7 ^= C1(K, 6); + L0 ^= C2(K, 6); + L1 ^= C3(K, 6); + L2 ^= C4(K, 6); + L3 ^= C5(K, 6); + L4 ^= C6(K, 6); + L5 ^= C7(K, 6); + + L7 ^= C0(K, 7); + L0 ^= C1(K, 7); + L1 ^= C2(K, 7); + L2 ^= C3(K, 7); + L3 ^= C4(K, 7); + L4 ^= C5(K, 7); + L5 ^= C6(K, 7); + L6 ^= C7(K, 7); + + K.q[0] = L0; + K.q[1] = L1; + K.q[2] = L2; + K.q[3] = L3; + K.q[4] = L4; + K.q[5] = L5; + K.q[6] = L6; + K.q[7] = L7; + + L0 ^= C0(S, 0); + L1 ^= C1(S, 0); + L2 ^= C2(S, 0); + L3 ^= C3(S, 0); + L4 ^= C4(S, 0); + L5 ^= C5(S, 0); + L6 ^= C6(S, 0); + L7 ^= C7(S, 0); + + L1 ^= C0(S, 1); + L2 ^= C1(S, 1); + L3 ^= C2(S, 1); + L4 ^= C3(S, 1); + L5 ^= C4(S, 1); + L6 ^= C5(S, 1); + L7 ^= C6(S, 1); + L0 ^= C7(S, 1); + + L2 ^= C0(S, 2); + L3 ^= C1(S, 2); + L4 ^= C2(S, 2); + L5 ^= C3(S, 2); + L6 ^= C4(S, 2); + L7 ^= C5(S, 2); + L0 ^= C6(S, 2); + L1 ^= C7(S, 2); + + L3 ^= C0(S, 3); + L4 ^= C1(S, 3); + L5 ^= C2(S, 3); + L6 ^= C3(S, 3); + L7 ^= C4(S, 3); + L0 ^= C5(S, 3); + L1 ^= C6(S, 3); + L2 ^= C7(S, 3); + + L4 ^= C0(S, 4); + L5 ^= C1(S, 4); + L6 ^= C2(S, 4); + L7 ^= C3(S, 4); + L0 ^= C4(S, 4); + L1 ^= C5(S, 4); + L2 ^= C6(S, 4); + L3 ^= C7(S, 4); + + L5 ^= C0(S, 5); + L6 ^= C1(S, 5); + L7 ^= C2(S, 5); + L0 ^= C3(S, 5); + L1 ^= C4(S, 5); + L2 ^= C5(S, 5); + L3 ^= C6(S, 5); + L4 ^= C7(S, 5); + + L6 ^= C0(S, 6); + L7 ^= C1(S, 6); + L0 ^= C2(S, 6); + L1 ^= C3(S, 6); + L2 ^= C4(S, 6); + L3 ^= C5(S, 6); + L4 ^= C6(S, 6); + L5 ^= C7(S, 6); + + L7 ^= C0(S, 7); + L0 ^= C1(S, 7); + L1 ^= C2(S, 7); + L2 ^= C3(S, 7); + L3 ^= C4(S, 7); + L4 ^= C5(S, 7); + L5 ^= C6(S, 7); + L6 ^= C7(S, 7); + + S.q[0] = L0; + S.q[1] = L1; + S.q[2] = L2; + S.q[3] = L3; + S.q[4] = L4; + S.q[5] = L5; + S.q[6] = L6; + S.q[7] = L7; +# endif + } + +# ifdef STRICT_ALIGNMENT + if ((size_t)p & 7) { + int i; + for (i = 0; i < 64; i++) + H->c[i] ^= S.c[i] ^ p[i]; + } else +# endif + { + const u64 *pa = (const u64 *)p; + H->q[0] ^= S.q[0] ^ pa[0]; + H->q[1] ^= S.q[1] ^ pa[1]; + H->q[2] ^= S.q[2] ^ pa[2]; + H->q[3] ^= S.q[3] ^ pa[3]; + H->q[4] ^= S.q[4] ^ pa[4]; + H->q[5] ^= S.q[5] ^ pa[5]; + H->q[6] ^= S.q[6] ^ pa[6]; + H->q[7] ^= S.q[7] ^ pa[7]; + } +#endif + p += 64; + } while (--n); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/whrlpool/wp_dgst.c b/trunk/3rdparty/openssl-1.1-fit/crypto/whrlpool/wp_dgst.c new file mode 100644 index 000000000..1ac29803a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/whrlpool/wp_dgst.c @@ -0,0 +1,258 @@ +/* + * Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/** + * The Whirlpool hashing function. + * + * See + * P.S.L.M. Barreto, V. Rijmen, + * ``The Whirlpool hashing function,'' + * NESSIE submission, 2000 (tweaked version, 2001), + * + * + * Based on "@version 3.0 (2003.03.12)" by Paulo S.L.M. Barreto and + * Vincent Rijmen. Lookup "reference implementations" on + * + * + * ============================================================================= + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* + * OpenSSL-specific implementation notes. + * + * WHIRLPOOL_Update as well as one-stroke WHIRLPOOL both expect + * number of *bytes* as input length argument. Bit-oriented routine + * as specified by authors is called WHIRLPOOL_BitUpdate[!] and + * does not have one-stroke counterpart. + * + * WHIRLPOOL_BitUpdate implements byte-oriented loop, essentially + * to serve WHIRLPOOL_Update. This is done for performance. + * + * Unlike authors' reference implementation, block processing + * routine whirlpool_block is designed to operate on multi-block + * input. This is done for performance. + */ + +#include +#include "wp_locl.h" +#include + +int WHIRLPOOL_Init(WHIRLPOOL_CTX *c) +{ + memset(c, 0, sizeof(*c)); + return 1; +} + +int WHIRLPOOL_Update(WHIRLPOOL_CTX *c, const void *_inp, size_t bytes) +{ + /* + * Well, largest suitable chunk size actually is + * (1<<(sizeof(size_t)*8-3))-64, but below number is large enough for not + * to care about excessive calls to WHIRLPOOL_BitUpdate... + */ + size_t chunk = ((size_t)1) << (sizeof(size_t) * 8 - 4); + const unsigned char *inp = _inp; + + while (bytes >= chunk) { + WHIRLPOOL_BitUpdate(c, inp, chunk * 8); + bytes -= chunk; + inp += chunk; + } + if (bytes) + WHIRLPOOL_BitUpdate(c, inp, bytes * 8); + + return 1; +} + +void WHIRLPOOL_BitUpdate(WHIRLPOOL_CTX *c, const void *_inp, size_t bits) +{ + size_t n; + unsigned int bitoff = c->bitoff, + bitrem = bitoff % 8, inpgap = (8 - (unsigned int)bits % 8) & 7; + const unsigned char *inp = _inp; + + /* + * This 256-bit increment procedure relies on the size_t being natural + * size of CPU register, so that we don't have to mask the value in order + * to detect overflows. + */ + c->bitlen[0] += bits; + if (c->bitlen[0] < bits) { /* overflow */ + n = 1; + do { + c->bitlen[n]++; + } while (c->bitlen[n] == 0 + && ++n < (WHIRLPOOL_COUNTER / sizeof(size_t))); + } +#ifndef OPENSSL_SMALL_FOOTPRINT + reconsider: + if (inpgap == 0 && bitrem == 0) { /* byte-oriented loop */ + while (bits) { + if (bitoff == 0 && (n = bits / WHIRLPOOL_BBLOCK)) { + whirlpool_block(c, inp, n); + inp += n * WHIRLPOOL_BBLOCK / 8; + bits %= WHIRLPOOL_BBLOCK; + } else { + unsigned int byteoff = bitoff / 8; + + bitrem = WHIRLPOOL_BBLOCK - bitoff; /* re-use bitrem */ + if (bits >= bitrem) { + bits -= bitrem; + bitrem /= 8; + memcpy(c->data + byteoff, inp, bitrem); + inp += bitrem; + whirlpool_block(c, c->data, 1); + bitoff = 0; + } else { + memcpy(c->data + byteoff, inp, bits / 8); + bitoff += (unsigned int)bits; + bits = 0; + } + c->bitoff = bitoff; + } + } + } else /* bit-oriented loop */ +#endif + { + /*- + inp + | + +-------+-------+------- + ||||||||||||||||||||| + +-------+-------+------- + +-------+-------+-------+-------+------- + |||||||||||||| c->data + +-------+-------+-------+-------+------- + | + c->bitoff/8 + */ + while (bits) { + unsigned int byteoff = bitoff / 8; + unsigned char b; + +#ifndef OPENSSL_SMALL_FOOTPRINT + if (bitrem == inpgap) { + c->data[byteoff++] |= inp[0] & (0xff >> inpgap); + inpgap = 8 - inpgap; + bitoff += inpgap; + bitrem = 0; /* bitoff%8 */ + bits -= inpgap; + inpgap = 0; /* bits%8 */ + inp++; + if (bitoff == WHIRLPOOL_BBLOCK) { + whirlpool_block(c, c->data, 1); + bitoff = 0; + } + c->bitoff = bitoff; + goto reconsider; + } else +#endif + if (bits > 8) { + b = ((inp[0] << inpgap) | (inp[1] >> (8 - inpgap))); + b &= 0xff; + if (bitrem) + c->data[byteoff++] |= b >> bitrem; + else + c->data[byteoff++] = b; + bitoff += 8; + bits -= 8; + inp++; + if (bitoff >= WHIRLPOOL_BBLOCK) { + whirlpool_block(c, c->data, 1); + byteoff = 0; + bitoff %= WHIRLPOOL_BBLOCK; + } + if (bitrem) + c->data[byteoff] = b << (8 - bitrem); + } else { /* remaining less than or equal to 8 bits */ + + b = (inp[0] << inpgap) & 0xff; + if (bitrem) + c->data[byteoff++] |= b >> bitrem; + else + c->data[byteoff++] = b; + bitoff += (unsigned int)bits; + if (bitoff == WHIRLPOOL_BBLOCK) { + whirlpool_block(c, c->data, 1); + byteoff = 0; + bitoff %= WHIRLPOOL_BBLOCK; + } + if (bitrem) + c->data[byteoff] = b << (8 - bitrem); + bits = 0; + } + c->bitoff = bitoff; + } + } +} + +int WHIRLPOOL_Final(unsigned char *md, WHIRLPOOL_CTX *c) +{ + unsigned int bitoff = c->bitoff, byteoff = bitoff / 8; + size_t i, j, v; + unsigned char *p; + + bitoff %= 8; + if (bitoff) + c->data[byteoff] |= 0x80 >> bitoff; + else + c->data[byteoff] = 0x80; + byteoff++; + + /* pad with zeros */ + if (byteoff > (WHIRLPOOL_BBLOCK / 8 - WHIRLPOOL_COUNTER)) { + if (byteoff < WHIRLPOOL_BBLOCK / 8) + memset(&c->data[byteoff], 0, WHIRLPOOL_BBLOCK / 8 - byteoff); + whirlpool_block(c, c->data, 1); + byteoff = 0; + } + if (byteoff < (WHIRLPOOL_BBLOCK / 8 - WHIRLPOOL_COUNTER)) + memset(&c->data[byteoff], 0, + (WHIRLPOOL_BBLOCK / 8 - WHIRLPOOL_COUNTER) - byteoff); + /* smash 256-bit c->bitlen in big-endian order */ + p = &c->data[WHIRLPOOL_BBLOCK / 8 - 1]; /* last byte in c->data */ + for (i = 0; i < WHIRLPOOL_COUNTER / sizeof(size_t); i++) + for (v = c->bitlen[i], j = 0; j < sizeof(size_t); j++, v >>= 8) + *p-- = (unsigned char)(v & 0xff); + + whirlpool_block(c, c->data, 1); + + if (md) { + memcpy(md, c->H.c, WHIRLPOOL_DIGEST_LENGTH); + OPENSSL_cleanse(c, sizeof(*c)); + return 1; + } + return 0; +} + +unsigned char *WHIRLPOOL(const void *inp, size_t bytes, unsigned char *md) +{ + WHIRLPOOL_CTX ctx; + static unsigned char m[WHIRLPOOL_DIGEST_LENGTH]; + + if (md == NULL) + md = m; + WHIRLPOOL_Init(&ctx); + WHIRLPOOL_Update(&ctx, inp, bytes); + WHIRLPOOL_Final(md, &ctx); + return md; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/whrlpool/wp_locl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/whrlpool/wp_locl.h new file mode 100644 index 000000000..3a81cfd58 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/whrlpool/wp_locl.h @@ -0,0 +1,12 @@ +/* + * Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +void whirlpool_block(WHIRLPOOL_CTX *, const void *, size_t); diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/build.info new file mode 100644 index 000000000..afd0b6134 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/build.info @@ -0,0 +1,10 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + x509_def.c x509_d2.c x509_r2x.c x509_cmp.c \ + x509_obj.c x509_req.c x509spki.c x509_vfy.c \ + x509_set.c x509cset.c x509rset.c x509_err.c \ + x509name.c x509_v3.c x509_ext.c x509_att.c \ + x509type.c x509_meth.c x509_lu.c x_all.c x509_txt.c \ + x509_trs.c by_file.c by_dir.c x509_vpm.c \ + x_crl.c t_crl.c x_req.c t_req.c x_x509.c t_x509.c \ + x_pubkey.c x_x509a.c x_attrib.c x_exten.c x_name.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/by_dir.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/by_dir.c new file mode 100644 index 000000000..b3760dbad --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/by_dir.c @@ -0,0 +1,390 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "e_os.h" +#include "internal/cryptlib.h" +#include +#include +#include +#include + +#ifndef OPENSSL_NO_POSIX_IO +# include +#endif + +#include +#include "internal/x509_int.h" +#include "x509_lcl.h" + +struct lookup_dir_hashes_st { + unsigned long hash; + int suffix; +}; + +struct lookup_dir_entry_st { + char *dir; + int dir_type; + STACK_OF(BY_DIR_HASH) *hashes; +}; + +typedef struct lookup_dir_st { + BUF_MEM *buffer; + STACK_OF(BY_DIR_ENTRY) *dirs; + CRYPTO_RWLOCK *lock; +} BY_DIR; + +static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, + char **ret); +static int new_dir(X509_LOOKUP *lu); +static void free_dir(X509_LOOKUP *lu); +static int add_cert_dir(BY_DIR *ctx, const char *dir, int type); +static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type, + X509_NAME *name, X509_OBJECT *ret); +static X509_LOOKUP_METHOD x509_dir_lookup = { + "Load certs from files in a directory", + new_dir, /* new_item */ + free_dir, /* free */ + NULL, /* init */ + NULL, /* shutdown */ + dir_ctrl, /* ctrl */ + get_cert_by_subject, /* get_by_subject */ + NULL, /* get_by_issuer_serial */ + NULL, /* get_by_fingerprint */ + NULL, /* get_by_alias */ +}; + +X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void) +{ + return &x509_dir_lookup; +} + +static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, + char **retp) +{ + int ret = 0; + BY_DIR *ld = (BY_DIR *)ctx->method_data; + + switch (cmd) { + case X509_L_ADD_DIR: + if (argl == X509_FILETYPE_DEFAULT) { + const char *dir = ossl_safe_getenv(X509_get_default_cert_dir_env()); + + if (dir) + ret = add_cert_dir(ld, dir, X509_FILETYPE_PEM); + else + ret = add_cert_dir(ld, X509_get_default_cert_dir(), + X509_FILETYPE_PEM); + if (!ret) { + X509err(X509_F_DIR_CTRL, X509_R_LOADING_CERT_DIR); + } + } else + ret = add_cert_dir(ld, argp, (int)argl); + break; + } + return ret; +} + +static int new_dir(X509_LOOKUP *lu) +{ + BY_DIR *a = OPENSSL_malloc(sizeof(*a)); + + if (a == NULL) { + X509err(X509_F_NEW_DIR, ERR_R_MALLOC_FAILURE); + return 0; + } + + if ((a->buffer = BUF_MEM_new()) == NULL) { + X509err(X509_F_NEW_DIR, ERR_R_MALLOC_FAILURE); + goto err; + } + a->dirs = NULL; + a->lock = CRYPTO_THREAD_lock_new(); + if (a->lock == NULL) { + BUF_MEM_free(a->buffer); + X509err(X509_F_NEW_DIR, ERR_R_MALLOC_FAILURE); + goto err; + } + lu->method_data = a; + return 1; + + err: + OPENSSL_free(a); + return 0; +} + +static void by_dir_hash_free(BY_DIR_HASH *hash) +{ + OPENSSL_free(hash); +} + +static int by_dir_hash_cmp(const BY_DIR_HASH *const *a, + const BY_DIR_HASH *const *b) +{ + if ((*a)->hash > (*b)->hash) + return 1; + if ((*a)->hash < (*b)->hash) + return -1; + return 0; +} + +static void by_dir_entry_free(BY_DIR_ENTRY *ent) +{ + OPENSSL_free(ent->dir); + sk_BY_DIR_HASH_pop_free(ent->hashes, by_dir_hash_free); + OPENSSL_free(ent); +} + +static void free_dir(X509_LOOKUP *lu) +{ + BY_DIR *a = (BY_DIR *)lu->method_data; + + sk_BY_DIR_ENTRY_pop_free(a->dirs, by_dir_entry_free); + BUF_MEM_free(a->buffer); + CRYPTO_THREAD_lock_free(a->lock); + OPENSSL_free(a); +} + +static int add_cert_dir(BY_DIR *ctx, const char *dir, int type) +{ + int j; + size_t len; + const char *s, *ss, *p; + + if (dir == NULL || !*dir) { + X509err(X509_F_ADD_CERT_DIR, X509_R_INVALID_DIRECTORY); + return 0; + } + + s = dir; + p = s; + do { + if ((*p == LIST_SEPARATOR_CHAR) || (*p == '\0')) { + BY_DIR_ENTRY *ent; + + ss = s; + s = p + 1; + len = p - ss; + if (len == 0) + continue; + for (j = 0; j < sk_BY_DIR_ENTRY_num(ctx->dirs); j++) { + ent = sk_BY_DIR_ENTRY_value(ctx->dirs, j); + if (strlen(ent->dir) == len && strncmp(ent->dir, ss, len) == 0) + break; + } + if (j < sk_BY_DIR_ENTRY_num(ctx->dirs)) + continue; + if (ctx->dirs == NULL) { + ctx->dirs = sk_BY_DIR_ENTRY_new_null(); + if (!ctx->dirs) { + X509err(X509_F_ADD_CERT_DIR, ERR_R_MALLOC_FAILURE); + return 0; + } + } + ent = OPENSSL_malloc(sizeof(*ent)); + if (ent == NULL) { + X509err(X509_F_ADD_CERT_DIR, ERR_R_MALLOC_FAILURE); + return 0; + } + ent->dir_type = type; + ent->hashes = sk_BY_DIR_HASH_new(by_dir_hash_cmp); + ent->dir = OPENSSL_strndup(ss, len); + if (ent->dir == NULL || ent->hashes == NULL) { + by_dir_entry_free(ent); + return 0; + } + if (!sk_BY_DIR_ENTRY_push(ctx->dirs, ent)) { + by_dir_entry_free(ent); + X509err(X509_F_ADD_CERT_DIR, ERR_R_MALLOC_FAILURE); + return 0; + } + } + } while (*p++ != '\0'); + return 1; +} + +static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type, + X509_NAME *name, X509_OBJECT *ret) +{ + BY_DIR *ctx; + union { + X509 st_x509; + X509_CRL crl; + } data; + int ok = 0; + int i, j, k; + unsigned long h; + BUF_MEM *b = NULL; + X509_OBJECT stmp, *tmp; + const char *postfix = ""; + + if (name == NULL) + return 0; + + stmp.type = type; + if (type == X509_LU_X509) { + data.st_x509.cert_info.subject = name; + stmp.data.x509 = &data.st_x509; + postfix = ""; + } else if (type == X509_LU_CRL) { + data.crl.crl.issuer = name; + stmp.data.crl = &data.crl; + postfix = "r"; + } else { + X509err(X509_F_GET_CERT_BY_SUBJECT, X509_R_WRONG_LOOKUP_TYPE); + goto finish; + } + + if ((b = BUF_MEM_new()) == NULL) { + X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_BUF_LIB); + goto finish; + } + + ctx = (BY_DIR *)xl->method_data; + + h = X509_NAME_hash(name); + for (i = 0; i < sk_BY_DIR_ENTRY_num(ctx->dirs); i++) { + BY_DIR_ENTRY *ent; + int idx; + BY_DIR_HASH htmp, *hent; + + ent = sk_BY_DIR_ENTRY_value(ctx->dirs, i); + j = strlen(ent->dir) + 1 + 8 + 6 + 1 + 1; + if (!BUF_MEM_grow(b, j)) { + X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_MALLOC_FAILURE); + goto finish; + } + if (type == X509_LU_CRL && ent->hashes) { + htmp.hash = h; + CRYPTO_THREAD_read_lock(ctx->lock); + idx = sk_BY_DIR_HASH_find(ent->hashes, &htmp); + if (idx >= 0) { + hent = sk_BY_DIR_HASH_value(ent->hashes, idx); + k = hent->suffix; + } else { + hent = NULL; + k = 0; + } + CRYPTO_THREAD_unlock(ctx->lock); + } else { + k = 0; + hent = NULL; + } + for (;;) { + char c = '/'; +#ifdef OPENSSL_SYS_VMS + c = ent->dir[strlen(ent->dir) - 1]; + if (c != ':' && c != '>' && c != ']') { + /* + * If no separator is present, we assume the directory + * specifier is a logical name, and add a colon. We really + * should use better VMS routines for merging things like + * this, but this will do for now... -- Richard Levitte + */ + c = ':'; + } else { + c = '\0'; + } +#endif + if (c == '\0') { + /* + * This is special. When c == '\0', no directory separator + * should be added. + */ + BIO_snprintf(b->data, b->max, + "%s%08lx.%s%d", ent->dir, h, postfix, k); + } else { + BIO_snprintf(b->data, b->max, + "%s%c%08lx.%s%d", ent->dir, c, h, postfix, k); + } +#ifndef OPENSSL_NO_POSIX_IO +# ifdef _WIN32 +# define stat _stat +# endif + { + struct stat st; + if (stat(b->data, &st) < 0) + break; + } +#endif + /* found one. */ + if (type == X509_LU_X509) { + if ((X509_load_cert_file(xl, b->data, ent->dir_type)) == 0) + break; + } else if (type == X509_LU_CRL) { + if ((X509_load_crl_file(xl, b->data, ent->dir_type)) == 0) + break; + } + /* else case will caught higher up */ + k++; + } + + /* + * we have added it to the cache so now pull it out again + */ + CRYPTO_THREAD_write_lock(ctx->lock); + j = sk_X509_OBJECT_find(xl->store_ctx->objs, &stmp); + tmp = sk_X509_OBJECT_value(xl->store_ctx->objs, j); + CRYPTO_THREAD_unlock(ctx->lock); + + /* If a CRL, update the last file suffix added for this */ + + if (type == X509_LU_CRL) { + CRYPTO_THREAD_write_lock(ctx->lock); + /* + * Look for entry again in case another thread added an entry + * first. + */ + if (hent == NULL) { + htmp.hash = h; + idx = sk_BY_DIR_HASH_find(ent->hashes, &htmp); + hent = sk_BY_DIR_HASH_value(ent->hashes, idx); + } + if (hent == NULL) { + hent = OPENSSL_malloc(sizeof(*hent)); + if (hent == NULL) { + CRYPTO_THREAD_unlock(ctx->lock); + X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_MALLOC_FAILURE); + ok = 0; + goto finish; + } + hent->hash = h; + hent->suffix = k; + if (!sk_BY_DIR_HASH_push(ent->hashes, hent)) { + CRYPTO_THREAD_unlock(ctx->lock); + OPENSSL_free(hent); + X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_MALLOC_FAILURE); + ok = 0; + goto finish; + } + } else if (hent->suffix < k) { + hent->suffix = k; + } + + CRYPTO_THREAD_unlock(ctx->lock); + + } + + if (tmp != NULL) { + ok = 1; + ret->type = tmp->type; + memcpy(&ret->data, &tmp->data, sizeof(ret->data)); + + /* + * Clear any errors that might have been raised processing empty + * or malformed files. + */ + ERR_clear_error(); + + goto finish; + } + } + finish: + BUF_MEM_free(b); + return ok; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/by_file.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/by_file.c new file mode 100644 index 000000000..244512c93 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/by_file.c @@ -0,0 +1,227 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include + +#include "internal/cryptlib.h" +#include +#include +#include +#include "x509_lcl.h" + +static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, + long argl, char **ret); +static X509_LOOKUP_METHOD x509_file_lookup = { + "Load file into cache", + NULL, /* new_item */ + NULL, /* free */ + NULL, /* init */ + NULL, /* shutdown */ + by_file_ctrl, /* ctrl */ + NULL, /* get_by_subject */ + NULL, /* get_by_issuer_serial */ + NULL, /* get_by_fingerprint */ + NULL, /* get_by_alias */ +}; + +X509_LOOKUP_METHOD *X509_LOOKUP_file(void) +{ + return &x509_file_lookup; +} + +static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, + long argl, char **ret) +{ + int ok = 0; + const char *file; + + switch (cmd) { + case X509_L_FILE_LOAD: + if (argl == X509_FILETYPE_DEFAULT) { + file = ossl_safe_getenv(X509_get_default_cert_file_env()); + if (file) + ok = (X509_load_cert_crl_file(ctx, file, + X509_FILETYPE_PEM) != 0); + + else + ok = (X509_load_cert_crl_file + (ctx, X509_get_default_cert_file(), + X509_FILETYPE_PEM) != 0); + + if (!ok) { + X509err(X509_F_BY_FILE_CTRL, X509_R_LOADING_DEFAULTS); + } + } else { + if (argl == X509_FILETYPE_PEM) + ok = (X509_load_cert_crl_file(ctx, argp, + X509_FILETYPE_PEM) != 0); + else + ok = (X509_load_cert_file(ctx, argp, (int)argl) != 0); + } + break; + } + return ok; +} + +int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type) +{ + int ret = 0; + BIO *in = NULL; + int i, count = 0; + X509 *x = NULL; + + in = BIO_new(BIO_s_file()); + + if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) { + X509err(X509_F_X509_LOAD_CERT_FILE, ERR_R_SYS_LIB); + goto err; + } + + if (type == X509_FILETYPE_PEM) { + for (;;) { + x = PEM_read_bio_X509_AUX(in, NULL, NULL, ""); + if (x == NULL) { + if ((ERR_GET_REASON(ERR_peek_last_error()) == + PEM_R_NO_START_LINE) && (count > 0)) { + ERR_clear_error(); + break; + } else { + X509err(X509_F_X509_LOAD_CERT_FILE, ERR_R_PEM_LIB); + goto err; + } + } + i = X509_STORE_add_cert(ctx->store_ctx, x); + if (!i) + goto err; + count++; + X509_free(x); + x = NULL; + } + ret = count; + } else if (type == X509_FILETYPE_ASN1) { + x = d2i_X509_bio(in, NULL); + if (x == NULL) { + X509err(X509_F_X509_LOAD_CERT_FILE, ERR_R_ASN1_LIB); + goto err; + } + i = X509_STORE_add_cert(ctx->store_ctx, x); + if (!i) + goto err; + ret = i; + } else { + X509err(X509_F_X509_LOAD_CERT_FILE, X509_R_BAD_X509_FILETYPE); + goto err; + } + if (ret == 0) + X509err(X509_F_X509_LOAD_CERT_FILE, X509_R_NO_CERTIFICATE_FOUND); + err: + X509_free(x); + BIO_free(in); + return ret; +} + +int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type) +{ + int ret = 0; + BIO *in = NULL; + int i, count = 0; + X509_CRL *x = NULL; + + in = BIO_new(BIO_s_file()); + + if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) { + X509err(X509_F_X509_LOAD_CRL_FILE, ERR_R_SYS_LIB); + goto err; + } + + if (type == X509_FILETYPE_PEM) { + for (;;) { + x = PEM_read_bio_X509_CRL(in, NULL, NULL, ""); + if (x == NULL) { + if ((ERR_GET_REASON(ERR_peek_last_error()) == + PEM_R_NO_START_LINE) && (count > 0)) { + ERR_clear_error(); + break; + } else { + X509err(X509_F_X509_LOAD_CRL_FILE, ERR_R_PEM_LIB); + goto err; + } + } + i = X509_STORE_add_crl(ctx->store_ctx, x); + if (!i) + goto err; + count++; + X509_CRL_free(x); + x = NULL; + } + ret = count; + } else if (type == X509_FILETYPE_ASN1) { + x = d2i_X509_CRL_bio(in, NULL); + if (x == NULL) { + X509err(X509_F_X509_LOAD_CRL_FILE, ERR_R_ASN1_LIB); + goto err; + } + i = X509_STORE_add_crl(ctx->store_ctx, x); + if (!i) + goto err; + ret = i; + } else { + X509err(X509_F_X509_LOAD_CRL_FILE, X509_R_BAD_X509_FILETYPE); + goto err; + } + if (ret == 0) + X509err(X509_F_X509_LOAD_CRL_FILE, X509_R_NO_CRL_FOUND); + err: + X509_CRL_free(x); + BIO_free(in); + return ret; +} + +int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type) +{ + STACK_OF(X509_INFO) *inf; + X509_INFO *itmp; + BIO *in; + int i, count = 0; + + if (type != X509_FILETYPE_PEM) + return X509_load_cert_file(ctx, file, type); + in = BIO_new_file(file, "r"); + if (!in) { + X509err(X509_F_X509_LOAD_CERT_CRL_FILE, ERR_R_SYS_LIB); + return 0; + } + inf = PEM_X509_INFO_read_bio(in, NULL, NULL, ""); + BIO_free(in); + if (!inf) { + X509err(X509_F_X509_LOAD_CERT_CRL_FILE, ERR_R_PEM_LIB); + return 0; + } + for (i = 0; i < sk_X509_INFO_num(inf); i++) { + itmp = sk_X509_INFO_value(inf, i); + if (itmp->x509) { + if (!X509_STORE_add_cert(ctx->store_ctx, itmp->x509)) + goto err; + count++; + } + if (itmp->crl) { + if (!X509_STORE_add_crl(ctx->store_ctx, itmp->crl)) + goto err; + count++; + } + } + if (count == 0) + X509err(X509_F_X509_LOAD_CERT_CRL_FILE, + X509_R_NO_CERTIFICATE_OR_CRL_FOUND); + err: + sk_X509_INFO_pop_free(inf, X509_INFO_free); + return count; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/t_crl.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/t_crl.c new file mode 100644 index 000000000..8e262912f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/t_crl.c @@ -0,0 +1,94 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include + +#ifndef OPENSSL_NO_STDIO +int X509_CRL_print_fp(FILE *fp, X509_CRL *x) +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + X509err(X509_F_X509_CRL_PRINT_FP, ERR_R_BUF_LIB); + return 0; + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = X509_CRL_print(b, x); + BIO_free(b); + return ret; +} +#endif + +int X509_CRL_print(BIO *out, X509_CRL *x) +{ + return X509_CRL_print_ex(out, x, XN_FLAG_COMPAT); +} + +int X509_CRL_print_ex(BIO *out, X509_CRL *x, unsigned long nmflag) +{ + STACK_OF(X509_REVOKED) *rev; + X509_REVOKED *r; + const X509_ALGOR *sig_alg; + const ASN1_BIT_STRING *sig; + long l; + int i; + + BIO_printf(out, "Certificate Revocation List (CRL):\n"); + l = X509_CRL_get_version(x); + if (l >= 0 && l <= 1) + BIO_printf(out, "%8sVersion %ld (0x%lx)\n", "", l + 1, (unsigned long)l); + else + BIO_printf(out, "%8sVersion unknown (%ld)\n", "", l); + X509_CRL_get0_signature(x, &sig, &sig_alg); + BIO_puts(out, " "); + X509_signature_print(out, sig_alg, NULL); + BIO_printf(out, "%8sIssuer: ", ""); + X509_NAME_print_ex(out, X509_CRL_get_issuer(x), 0, nmflag); + BIO_puts(out, "\n"); + BIO_printf(out, "%8sLast Update: ", ""); + ASN1_TIME_print(out, X509_CRL_get0_lastUpdate(x)); + BIO_printf(out, "\n%8sNext Update: ", ""); + if (X509_CRL_get0_nextUpdate(x)) + ASN1_TIME_print(out, X509_CRL_get0_nextUpdate(x)); + else + BIO_printf(out, "NONE"); + BIO_printf(out, "\n"); + + X509V3_extensions_print(out, "CRL extensions", + X509_CRL_get0_extensions(x), 0, 8); + + rev = X509_CRL_get_REVOKED(x); + + if (sk_X509_REVOKED_num(rev) > 0) + BIO_printf(out, "Revoked Certificates:\n"); + else + BIO_printf(out, "No Revoked Certificates.\n"); + + for (i = 0; i < sk_X509_REVOKED_num(rev); i++) { + r = sk_X509_REVOKED_value(rev, i); + BIO_printf(out, " Serial Number: "); + i2a_ASN1_INTEGER(out, X509_REVOKED_get0_serialNumber(r)); + BIO_printf(out, "\n Revocation Date: "); + ASN1_TIME_print(out, X509_REVOKED_get0_revocationDate(r)); + BIO_printf(out, "\n"); + X509V3_extensions_print(out, "CRL entry extensions", + X509_REVOKED_get0_extensions(r), 0, 8); + } + X509_signature_print(out, sig_alg, sig); + + return 1; + +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/t_req.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/t_req.c new file mode 100644 index 000000000..2d4c591b7 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/t_req.c @@ -0,0 +1,210 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include +#include + +#ifndef OPENSSL_NO_STDIO +int X509_REQ_print_fp(FILE *fp, X509_REQ *x) +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + X509err(X509_F_X509_REQ_PRINT_FP, ERR_R_BUF_LIB); + return 0; + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = X509_REQ_print(b, x); + BIO_free(b); + return ret; +} +#endif + +int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflags, + unsigned long cflag) +{ + long l; + int i; + EVP_PKEY *pkey; + STACK_OF(X509_EXTENSION) *exts; + char mlch = ' '; + int nmindent = 0; + + if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) { + mlch = '\n'; + nmindent = 12; + } + + if (nmflags == X509_FLAG_COMPAT) + nmindent = 16; + + if (!(cflag & X509_FLAG_NO_HEADER)) { + if (BIO_write(bp, "Certificate Request:\n", 21) <= 0) + goto err; + if (BIO_write(bp, " Data:\n", 10) <= 0) + goto err; + } + if (!(cflag & X509_FLAG_NO_VERSION)) { + l = X509_REQ_get_version(x); + if (l >= 0 && l <= 2) { + if (BIO_printf(bp, "%8sVersion: %ld (0x%lx)\n", "", l + 1, (unsigned long)l) <= 0) + goto err; + } else { + if (BIO_printf(bp, "%8sVersion: Unknown (%ld)\n", "", l) <= 0) + goto err; + } + } + if (!(cflag & X509_FLAG_NO_SUBJECT)) { + if (BIO_printf(bp, " Subject:%c", mlch) <= 0) + goto err; + if (X509_NAME_print_ex(bp, X509_REQ_get_subject_name(x), + nmindent, nmflags) < 0) + goto err; + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + } + if (!(cflag & X509_FLAG_NO_PUBKEY)) { + X509_PUBKEY *xpkey; + ASN1_OBJECT *koid; + if (BIO_write(bp, " Subject Public Key Info:\n", 33) <= 0) + goto err; + if (BIO_printf(bp, "%12sPublic Key Algorithm: ", "") <= 0) + goto err; + xpkey = X509_REQ_get_X509_PUBKEY(x); + X509_PUBKEY_get0_param(&koid, NULL, NULL, NULL, xpkey); + if (i2a_ASN1_OBJECT(bp, koid) <= 0) + goto err; + if (BIO_puts(bp, "\n") <= 0) + goto err; + + pkey = X509_REQ_get0_pubkey(x); + if (pkey == NULL) { + if (BIO_printf(bp, "%12sUnable to load Public Key\n", "") <= 0) + goto err; + ERR_print_errors(bp); + } else { + if (EVP_PKEY_print_public(bp, pkey, 16, NULL) <= 0) + goto err; + } + } + + if (!(cflag & X509_FLAG_NO_ATTRIBUTES)) { + /* may not be */ + if (BIO_printf(bp, "%8sAttributes:\n", "") <= 0) + goto err; + + if (X509_REQ_get_attr_count(x) == 0) { + if (BIO_printf(bp, "%12sa0:00\n", "") <= 0) + goto err; + } else { + for (i = 0; i < X509_REQ_get_attr_count(x); i++) { + ASN1_TYPE *at; + X509_ATTRIBUTE *a; + ASN1_BIT_STRING *bs = NULL; + ASN1_OBJECT *aobj; + int j, type = 0, count = 1, ii = 0; + + a = X509_REQ_get_attr(x, i); + aobj = X509_ATTRIBUTE_get0_object(a); + if (X509_REQ_extension_nid(OBJ_obj2nid(aobj))) + continue; + if (BIO_printf(bp, "%12s", "") <= 0) + goto err; + if ((j = i2a_ASN1_OBJECT(bp, aobj)) > 0) { + ii = 0; + count = X509_ATTRIBUTE_count(a); + get_next: + at = X509_ATTRIBUTE_get0_type(a, ii); + type = at->type; + bs = at->value.asn1_string; + } + for (j = 25 - j; j > 0; j--) + if (BIO_write(bp, " ", 1) != 1) + goto err; + if (BIO_puts(bp, ":") <= 0) + goto err; + switch (type) { + case V_ASN1_PRINTABLESTRING: + case V_ASN1_T61STRING: + case V_ASN1_NUMERICSTRING: + case V_ASN1_UTF8STRING: + case V_ASN1_IA5STRING: + if (BIO_write(bp, (char *)bs->data, bs->length) + != bs->length) + goto err; + if (BIO_puts(bp, "\n") <= 0) + goto err; + break; + default: + if (BIO_puts(bp, "unable to print attribute\n") <= 0) + goto err; + break; + } + if (++ii < count) + goto get_next; + } + } + } + if (!(cflag & X509_FLAG_NO_EXTENSIONS)) { + exts = X509_REQ_get_extensions(x); + if (exts) { + if (BIO_printf(bp, "%8sRequested Extensions:\n", "") <= 0) + goto err; + for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { + ASN1_OBJECT *obj; + X509_EXTENSION *ex; + int critical; + ex = sk_X509_EXTENSION_value(exts, i); + if (BIO_printf(bp, "%12s", "") <= 0) + goto err; + obj = X509_EXTENSION_get_object(ex); + if (i2a_ASN1_OBJECT(bp, obj) <= 0) + goto err; + critical = X509_EXTENSION_get_critical(ex); + if (BIO_printf(bp, ": %s\n", critical ? "critical" : "") <= 0) + goto err; + if (!X509V3_EXT_print(bp, ex, cflag, 16)) { + if (BIO_printf(bp, "%16s", "") <= 0 + || ASN1_STRING_print(bp, + X509_EXTENSION_get_data(ex)) <= 0) + goto err; + } + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + } + sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); + } + } + + if (!(cflag & X509_FLAG_NO_SIGDUMP)) { + const X509_ALGOR *sig_alg; + const ASN1_BIT_STRING *sig; + X509_REQ_get0_signature(x, &sig, &sig_alg); + if (!X509_signature_print(bp, sig_alg, sig)) + goto err; + } + + return 1; + err: + X509err(X509_F_X509_REQ_PRINT_EX, ERR_R_BUF_LIB); + return 0; +} + +int X509_REQ_print(BIO *bp, X509_REQ *x) +{ + return X509_REQ_print_ex(bp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/t_x509.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/t_x509.c new file mode 100644 index 000000000..ccacbe7cb --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/t_x509.c @@ -0,0 +1,379 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include "internal/asn1_int.h" + +#ifndef OPENSSL_NO_STDIO +int X509_print_fp(FILE *fp, X509 *x) +{ + return X509_print_ex_fp(fp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT); +} + +int X509_print_ex_fp(FILE *fp, X509 *x, unsigned long nmflag, + unsigned long cflag) +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + X509err(X509_F_X509_PRINT_EX_FP, ERR_R_BUF_LIB); + return 0; + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = X509_print_ex(b, x, nmflag, cflag); + BIO_free(b); + return ret; +} +#endif + +int X509_print(BIO *bp, X509 *x) +{ + return X509_print_ex(bp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT); +} + +int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags, + unsigned long cflag) +{ + long l; + int ret = 0, i; + char *m = NULL, mlch = ' '; + int nmindent = 0; + ASN1_INTEGER *bs; + EVP_PKEY *pkey = NULL; + const char *neg; + + if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) { + mlch = '\n'; + nmindent = 12; + } + + if (nmflags == X509_FLAG_COMPAT) + nmindent = 16; + + if (!(cflag & X509_FLAG_NO_HEADER)) { + if (BIO_write(bp, "Certificate:\n", 13) <= 0) + goto err; + if (BIO_write(bp, " Data:\n", 10) <= 0) + goto err; + } + if (!(cflag & X509_FLAG_NO_VERSION)) { + l = X509_get_version(x); + if (l >= 0 && l <= 2) { + if (BIO_printf(bp, "%8sVersion: %ld (0x%lx)\n", "", l + 1, (unsigned long)l) <= 0) + goto err; + } else { + if (BIO_printf(bp, "%8sVersion: Unknown (%ld)\n", "", l) <= 0) + goto err; + } + } + if (!(cflag & X509_FLAG_NO_SERIAL)) { + + if (BIO_write(bp, " Serial Number:", 22) <= 0) + goto err; + + bs = X509_get_serialNumber(x); + if (bs->length <= (int)sizeof(long)) { + ERR_set_mark(); + l = ASN1_INTEGER_get(bs); + ERR_pop_to_mark(); + } else { + l = -1; + } + if (l != -1) { + unsigned long ul; + if (bs->type == V_ASN1_NEG_INTEGER) { + ul = 0 - (unsigned long)l; + neg = "-"; + } else { + ul = l; + neg = ""; + } + if (BIO_printf(bp, " %s%lu (%s0x%lx)\n", neg, ul, neg, ul) <= 0) + goto err; + } else { + neg = (bs->type == V_ASN1_NEG_INTEGER) ? " (Negative)" : ""; + if (BIO_printf(bp, "\n%12s%s", "", neg) <= 0) + goto err; + + for (i = 0; i < bs->length; i++) { + if (BIO_printf(bp, "%02x%c", bs->data[i], + ((i + 1 == bs->length) ? '\n' : ':')) <= 0) + goto err; + } + } + + } + + if (!(cflag & X509_FLAG_NO_SIGNAME)) { + const X509_ALGOR *tsig_alg = X509_get0_tbs_sigalg(x); + + if (BIO_puts(bp, " ") <= 0) + goto err; + if (X509_signature_print(bp, tsig_alg, NULL) <= 0) + goto err; + } + + if (!(cflag & X509_FLAG_NO_ISSUER)) { + if (BIO_printf(bp, " Issuer:%c", mlch) <= 0) + goto err; + if (X509_NAME_print_ex(bp, X509_get_issuer_name(x), nmindent, nmflags) + < 0) + goto err; + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + } + if (!(cflag & X509_FLAG_NO_VALIDITY)) { + if (BIO_write(bp, " Validity\n", 17) <= 0) + goto err; + if (BIO_write(bp, " Not Before: ", 24) <= 0) + goto err; + if (!ASN1_TIME_print(bp, X509_get0_notBefore(x))) + goto err; + if (BIO_write(bp, "\n Not After : ", 25) <= 0) + goto err; + if (!ASN1_TIME_print(bp, X509_get0_notAfter(x))) + goto err; + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + } + if (!(cflag & X509_FLAG_NO_SUBJECT)) { + if (BIO_printf(bp, " Subject:%c", mlch) <= 0) + goto err; + if (X509_NAME_print_ex + (bp, X509_get_subject_name(x), nmindent, nmflags) < 0) + goto err; + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + } + if (!(cflag & X509_FLAG_NO_PUBKEY)) { + X509_PUBKEY *xpkey = X509_get_X509_PUBKEY(x); + ASN1_OBJECT *xpoid; + X509_PUBKEY_get0_param(&xpoid, NULL, NULL, NULL, xpkey); + if (BIO_write(bp, " Subject Public Key Info:\n", 33) <= 0) + goto err; + if (BIO_printf(bp, "%12sPublic Key Algorithm: ", "") <= 0) + goto err; + if (i2a_ASN1_OBJECT(bp, xpoid) <= 0) + goto err; + if (BIO_puts(bp, "\n") <= 0) + goto err; + + pkey = X509_get0_pubkey(x); + if (pkey == NULL) { + BIO_printf(bp, "%12sUnable to load Public Key\n", ""); + ERR_print_errors(bp); + } else { + EVP_PKEY_print_public(bp, pkey, 16, NULL); + } + } + + if (!(cflag & X509_FLAG_NO_IDS)) { + const ASN1_BIT_STRING *iuid, *suid; + X509_get0_uids(x, &iuid, &suid); + if (iuid != NULL) { + if (BIO_printf(bp, "%8sIssuer Unique ID: ", "") <= 0) + goto err; + if (!X509_signature_dump(bp, iuid, 12)) + goto err; + } + if (suid != NULL) { + if (BIO_printf(bp, "%8sSubject Unique ID: ", "") <= 0) + goto err; + if (!X509_signature_dump(bp, suid, 12)) + goto err; + } + } + + if (!(cflag & X509_FLAG_NO_EXTENSIONS)) + X509V3_extensions_print(bp, "X509v3 extensions", + X509_get0_extensions(x), cflag, 8); + + if (!(cflag & X509_FLAG_NO_SIGDUMP)) { + const X509_ALGOR *sig_alg; + const ASN1_BIT_STRING *sig; + X509_get0_signature(&sig, &sig_alg, x); + if (X509_signature_print(bp, sig_alg, sig) <= 0) + goto err; + } + if (!(cflag & X509_FLAG_NO_AUX)) { + if (!X509_aux_print(bp, x, 0)) + goto err; + } + ret = 1; + err: + OPENSSL_free(m); + return ret; +} + +int X509_ocspid_print(BIO *bp, X509 *x) +{ + unsigned char *der = NULL; + unsigned char *dertmp; + int derlen; + int i; + unsigned char SHA1md[SHA_DIGEST_LENGTH]; + ASN1_BIT_STRING *keybstr; + X509_NAME *subj; + + /* + * display the hash of the subject as it would appear in OCSP requests + */ + if (BIO_printf(bp, " Subject OCSP hash: ") <= 0) + goto err; + subj = X509_get_subject_name(x); + derlen = i2d_X509_NAME(subj, NULL); + if ((der = dertmp = OPENSSL_malloc(derlen)) == NULL) + goto err; + i2d_X509_NAME(subj, &dertmp); + + if (!EVP_Digest(der, derlen, SHA1md, NULL, EVP_sha1(), NULL)) + goto err; + for (i = 0; i < SHA_DIGEST_LENGTH; i++) { + if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0) + goto err; + } + OPENSSL_free(der); + der = NULL; + + /* + * display the hash of the public key as it would appear in OCSP requests + */ + if (BIO_printf(bp, "\n Public key OCSP hash: ") <= 0) + goto err; + + keybstr = X509_get0_pubkey_bitstr(x); + + if (keybstr == NULL) + goto err; + + if (!EVP_Digest(ASN1_STRING_get0_data(keybstr), + ASN1_STRING_length(keybstr), SHA1md, NULL, EVP_sha1(), + NULL)) + goto err; + for (i = 0; i < SHA_DIGEST_LENGTH; i++) { + if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0) + goto err; + } + BIO_printf(bp, "\n"); + + return 1; + err: + OPENSSL_free(der); + return 0; +} + +int X509_signature_dump(BIO *bp, const ASN1_STRING *sig, int indent) +{ + const unsigned char *s; + int i, n; + + n = sig->length; + s = sig->data; + for (i = 0; i < n; i++) { + if ((i % 18) == 0) { + if (BIO_write(bp, "\n", 1) <= 0) + return 0; + if (BIO_indent(bp, indent, indent) <= 0) + return 0; + } + if (BIO_printf(bp, "%02x%s", s[i], ((i + 1) == n) ? "" : ":") <= 0) + return 0; + } + if (BIO_write(bp, "\n", 1) != 1) + return 0; + + return 1; +} + +int X509_signature_print(BIO *bp, const X509_ALGOR *sigalg, + const ASN1_STRING *sig) +{ + int sig_nid; + if (BIO_puts(bp, " Signature Algorithm: ") <= 0) + return 0; + if (i2a_ASN1_OBJECT(bp, sigalg->algorithm) <= 0) + return 0; + + sig_nid = OBJ_obj2nid(sigalg->algorithm); + if (sig_nid != NID_undef) { + int pkey_nid, dig_nid; + const EVP_PKEY_ASN1_METHOD *ameth; + if (OBJ_find_sigid_algs(sig_nid, &dig_nid, &pkey_nid)) { + ameth = EVP_PKEY_asn1_find(NULL, pkey_nid); + if (ameth && ameth->sig_print) + return ameth->sig_print(bp, sigalg, sig, 9, 0); + } + } + if (sig) + return X509_signature_dump(bp, sig, 9); + else if (BIO_puts(bp, "\n") <= 0) + return 0; + return 1; +} + +int X509_aux_print(BIO *out, X509 *x, int indent) +{ + char oidstr[80], first; + STACK_OF(ASN1_OBJECT) *trust, *reject; + const unsigned char *alias, *keyid; + int keyidlen; + int i; + if (X509_trusted(x) == 0) + return 1; + trust = X509_get0_trust_objects(x); + reject = X509_get0_reject_objects(x); + if (trust) { + first = 1; + BIO_printf(out, "%*sTrusted Uses:\n%*s", indent, "", indent + 2, ""); + for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) { + if (!first) + BIO_puts(out, ", "); + else + first = 0; + OBJ_obj2txt(oidstr, sizeof(oidstr), + sk_ASN1_OBJECT_value(trust, i), 0); + BIO_puts(out, oidstr); + } + BIO_puts(out, "\n"); + } else + BIO_printf(out, "%*sNo Trusted Uses.\n", indent, ""); + if (reject) { + first = 1; + BIO_printf(out, "%*sRejected Uses:\n%*s", indent, "", indent + 2, ""); + for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) { + if (!first) + BIO_puts(out, ", "); + else + first = 0; + OBJ_obj2txt(oidstr, sizeof(oidstr), + sk_ASN1_OBJECT_value(reject, i), 0); + BIO_puts(out, oidstr); + } + BIO_puts(out, "\n"); + } else + BIO_printf(out, "%*sNo Rejected Uses.\n", indent, ""); + alias = X509_alias_get0(x, NULL); + if (alias) + BIO_printf(out, "%*sAlias: %s\n", indent, "", alias); + keyid = X509_keyid_get0(x, &keyidlen); + if (keyid) { + BIO_printf(out, "%*sKey Id: ", indent, ""); + for (i = 0; i < keyidlen; i++) + BIO_printf(out, "%s%02X", i ? ":" : "", keyid[i]); + BIO_write(out, "\n", 1); + } + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_att.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_att.c new file mode 100644 index 000000000..63895efe4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_att.c @@ -0,0 +1,329 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include +#include "x509_lcl.h" + +int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x) +{ + return sk_X509_ATTRIBUTE_num(x); +} + +int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid, + int lastpos) +{ + const ASN1_OBJECT *obj = OBJ_nid2obj(nid); + + if (obj == NULL) + return -2; + return X509at_get_attr_by_OBJ(x, obj, lastpos); +} + +int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk, + const ASN1_OBJECT *obj, int lastpos) +{ + int n; + X509_ATTRIBUTE *ex; + + if (sk == NULL) + return -1; + lastpos++; + if (lastpos < 0) + lastpos = 0; + n = sk_X509_ATTRIBUTE_num(sk); + for (; lastpos < n; lastpos++) { + ex = sk_X509_ATTRIBUTE_value(sk, lastpos); + if (OBJ_cmp(ex->object, obj) == 0) + return lastpos; + } + return -1; +} + +X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc) +{ + if (x == NULL || sk_X509_ATTRIBUTE_num(x) <= loc || loc < 0) + return NULL; + + return sk_X509_ATTRIBUTE_value(x, loc); +} + +X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc) +{ + X509_ATTRIBUTE *ret; + + if (x == NULL || sk_X509_ATTRIBUTE_num(x) <= loc || loc < 0) + return NULL; + ret = sk_X509_ATTRIBUTE_delete(x, loc); + return ret; +} + +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x, + X509_ATTRIBUTE *attr) +{ + X509_ATTRIBUTE *new_attr = NULL; + STACK_OF(X509_ATTRIBUTE) *sk = NULL; + + if (x == NULL) { + X509err(X509_F_X509AT_ADD1_ATTR, ERR_R_PASSED_NULL_PARAMETER); + goto err2; + } + + if (*x == NULL) { + if ((sk = sk_X509_ATTRIBUTE_new_null()) == NULL) + goto err; + } else + sk = *x; + + if ((new_attr = X509_ATTRIBUTE_dup(attr)) == NULL) + goto err2; + if (!sk_X509_ATTRIBUTE_push(sk, new_attr)) + goto err; + if (*x == NULL) + *x = sk; + return sk; + err: + X509err(X509_F_X509AT_ADD1_ATTR, ERR_R_MALLOC_FAILURE); + err2: + X509_ATTRIBUTE_free(new_attr); + sk_X509_ATTRIBUTE_free(sk); + return NULL; +} + +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE) + **x, const ASN1_OBJECT *obj, + int type, + const unsigned char *bytes, + int len) +{ + X509_ATTRIBUTE *attr; + STACK_OF(X509_ATTRIBUTE) *ret; + attr = X509_ATTRIBUTE_create_by_OBJ(NULL, obj, type, bytes, len); + if (!attr) + return 0; + ret = X509at_add1_attr(x, attr); + X509_ATTRIBUTE_free(attr); + return ret; +} + +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE) + **x, int nid, int type, + const unsigned char *bytes, + int len) +{ + X509_ATTRIBUTE *attr; + STACK_OF(X509_ATTRIBUTE) *ret; + attr = X509_ATTRIBUTE_create_by_NID(NULL, nid, type, bytes, len); + if (!attr) + return 0; + ret = X509at_add1_attr(x, attr); + X509_ATTRIBUTE_free(attr); + return ret; +} + +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) + **x, const char *attrname, + int type, + const unsigned char *bytes, + int len) +{ + X509_ATTRIBUTE *attr; + STACK_OF(X509_ATTRIBUTE) *ret; + attr = X509_ATTRIBUTE_create_by_txt(NULL, attrname, type, bytes, len); + if (!attr) + return 0; + ret = X509at_add1_attr(x, attr); + X509_ATTRIBUTE_free(attr); + return ret; +} + +void *X509at_get0_data_by_OBJ(STACK_OF(X509_ATTRIBUTE) *x, + const ASN1_OBJECT *obj, int lastpos, int type) +{ + int i; + X509_ATTRIBUTE *at; + i = X509at_get_attr_by_OBJ(x, obj, lastpos); + if (i == -1) + return NULL; + if ((lastpos <= -2) && (X509at_get_attr_by_OBJ(x, obj, i) != -1)) + return NULL; + at = X509at_get_attr(x, i); + if (lastpos <= -3 && (X509_ATTRIBUTE_count(at) != 1)) + return NULL; + return X509_ATTRIBUTE_get0_data(at, 0, type, NULL); +} + +X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid, + int atrtype, const void *data, + int len) +{ + ASN1_OBJECT *obj; + X509_ATTRIBUTE *ret; + + obj = OBJ_nid2obj(nid); + if (obj == NULL) { + X509err(X509_F_X509_ATTRIBUTE_CREATE_BY_NID, X509_R_UNKNOWN_NID); + return NULL; + } + ret = X509_ATTRIBUTE_create_by_OBJ(attr, obj, atrtype, data, len); + if (ret == NULL) + ASN1_OBJECT_free(obj); + return ret; +} + +X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr, + const ASN1_OBJECT *obj, + int atrtype, const void *data, + int len) +{ + X509_ATTRIBUTE *ret; + + if ((attr == NULL) || (*attr == NULL)) { + if ((ret = X509_ATTRIBUTE_new()) == NULL) { + X509err(X509_F_X509_ATTRIBUTE_CREATE_BY_OBJ, + ERR_R_MALLOC_FAILURE); + return NULL; + } + } else + ret = *attr; + + if (!X509_ATTRIBUTE_set1_object(ret, obj)) + goto err; + if (!X509_ATTRIBUTE_set1_data(ret, atrtype, data, len)) + goto err; + + if ((attr != NULL) && (*attr == NULL)) + *attr = ret; + return ret; + err: + if ((attr == NULL) || (ret != *attr)) + X509_ATTRIBUTE_free(ret); + return NULL; +} + +X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr, + const char *atrname, int type, + const unsigned char *bytes, + int len) +{ + ASN1_OBJECT *obj; + X509_ATTRIBUTE *nattr; + + obj = OBJ_txt2obj(atrname, 0); + if (obj == NULL) { + X509err(X509_F_X509_ATTRIBUTE_CREATE_BY_TXT, + X509_R_INVALID_FIELD_NAME); + ERR_add_error_data(2, "name=", atrname); + return NULL; + } + nattr = X509_ATTRIBUTE_create_by_OBJ(attr, obj, type, bytes, len); + ASN1_OBJECT_free(obj); + return nattr; +} + +int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj) +{ + if ((attr == NULL) || (obj == NULL)) + return 0; + ASN1_OBJECT_free(attr->object); + attr->object = OBJ_dup(obj); + return attr->object != NULL; +} + +int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, + const void *data, int len) +{ + ASN1_TYPE *ttmp = NULL; + ASN1_STRING *stmp = NULL; + int atype = 0; + if (!attr) + return 0; + if (attrtype & MBSTRING_FLAG) { + stmp = ASN1_STRING_set_by_NID(NULL, data, len, attrtype, + OBJ_obj2nid(attr->object)); + if (!stmp) { + X509err(X509_F_X509_ATTRIBUTE_SET1_DATA, ERR_R_ASN1_LIB); + return 0; + } + atype = stmp->type; + } else if (len != -1) { + if ((stmp = ASN1_STRING_type_new(attrtype)) == NULL) + goto err; + if (!ASN1_STRING_set(stmp, data, len)) + goto err; + atype = attrtype; + } + /* + * This is a bit naughty because the attribute should really have at + * least one value but some types use and zero length SET and require + * this. + */ + if (attrtype == 0) { + ASN1_STRING_free(stmp); + return 1; + } + if ((ttmp = ASN1_TYPE_new()) == NULL) + goto err; + if ((len == -1) && !(attrtype & MBSTRING_FLAG)) { + if (!ASN1_TYPE_set1(ttmp, attrtype, data)) + goto err; + } else { + ASN1_TYPE_set(ttmp, atype, stmp); + stmp = NULL; + } + if (!sk_ASN1_TYPE_push(attr->set, ttmp)) + goto err; + return 1; + err: + X509err(X509_F_X509_ATTRIBUTE_SET1_DATA, ERR_R_MALLOC_FAILURE); + ASN1_TYPE_free(ttmp); + ASN1_STRING_free(stmp); + return 0; +} + +int X509_ATTRIBUTE_count(const X509_ATTRIBUTE *attr) +{ + if (attr == NULL) + return 0; + return sk_ASN1_TYPE_num(attr->set); +} + +ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr) +{ + if (attr == NULL) + return NULL; + return attr->object; +} + +void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx, + int atrtype, void *data) +{ + ASN1_TYPE *ttmp; + ttmp = X509_ATTRIBUTE_get0_type(attr, idx); + if (!ttmp) + return NULL; + if (atrtype != ASN1_TYPE_get(ttmp)) { + X509err(X509_F_X509_ATTRIBUTE_GET0_DATA, X509_R_WRONG_TYPE); + return NULL; + } + return ttmp->value.ptr; +} + +ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx) +{ + if (attr == NULL) + return NULL; + return sk_ASN1_TYPE_value(attr->set, idx); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_cmp.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_cmp.c new file mode 100644 index 000000000..02fad0c67 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_cmp.c @@ -0,0 +1,458 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "internal/x509_int.h" + +int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b) +{ + int i; + const X509_CINF *ai, *bi; + + ai = &a->cert_info; + bi = &b->cert_info; + i = ASN1_INTEGER_cmp(&ai->serialNumber, &bi->serialNumber); + if (i) + return i; + return X509_NAME_cmp(ai->issuer, bi->issuer); +} + +#ifndef OPENSSL_NO_MD5 +unsigned long X509_issuer_and_serial_hash(X509 *a) +{ + unsigned long ret = 0; + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + unsigned char md[16]; + char *f; + + if (ctx == NULL) + goto err; + f = X509_NAME_oneline(a->cert_info.issuer, NULL, 0); + if (!EVP_DigestInit_ex(ctx, EVP_md5(), NULL)) + goto err; + if (!EVP_DigestUpdate(ctx, (unsigned char *)f, strlen(f))) + goto err; + OPENSSL_free(f); + if (!EVP_DigestUpdate + (ctx, (unsigned char *)a->cert_info.serialNumber.data, + (unsigned long)a->cert_info.serialNumber.length)) + goto err; + if (!EVP_DigestFinal_ex(ctx, &(md[0]), NULL)) + goto err; + ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) | + ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L) + ) & 0xffffffffL; + err: + EVP_MD_CTX_free(ctx); + return ret; +} +#endif + +int X509_issuer_name_cmp(const X509 *a, const X509 *b) +{ + return X509_NAME_cmp(a->cert_info.issuer, b->cert_info.issuer); +} + +int X509_subject_name_cmp(const X509 *a, const X509 *b) +{ + return X509_NAME_cmp(a->cert_info.subject, b->cert_info.subject); +} + +int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b) +{ + return X509_NAME_cmp(a->crl.issuer, b->crl.issuer); +} + +int X509_CRL_match(const X509_CRL *a, const X509_CRL *b) +{ + return memcmp(a->sha1_hash, b->sha1_hash, 20); +} + +X509_NAME *X509_get_issuer_name(const X509 *a) +{ + return a->cert_info.issuer; +} + +unsigned long X509_issuer_name_hash(X509 *x) +{ + return X509_NAME_hash(x->cert_info.issuer); +} + +#ifndef OPENSSL_NO_MD5 +unsigned long X509_issuer_name_hash_old(X509 *x) +{ + return X509_NAME_hash_old(x->cert_info.issuer); +} +#endif + +X509_NAME *X509_get_subject_name(const X509 *a) +{ + return a->cert_info.subject; +} + +ASN1_INTEGER *X509_get_serialNumber(X509 *a) +{ + return &a->cert_info.serialNumber; +} + +const ASN1_INTEGER *X509_get0_serialNumber(const X509 *a) +{ + return &a->cert_info.serialNumber; +} + +unsigned long X509_subject_name_hash(X509 *x) +{ + return X509_NAME_hash(x->cert_info.subject); +} + +#ifndef OPENSSL_NO_MD5 +unsigned long X509_subject_name_hash_old(X509 *x) +{ + return X509_NAME_hash_old(x->cert_info.subject); +} +#endif + +/* + * Compare two certificates: they must be identical for this to work. NB: + * Although "cmp" operations are generally prototyped to take "const" + * arguments (eg. for use in STACKs), the way X509 handling is - these + * operations may involve ensuring the hashes are up-to-date and ensuring + * certain cert information is cached. So this is the point where the + * "depth-first" constification tree has to halt with an evil cast. + */ +int X509_cmp(const X509 *a, const X509 *b) +{ + int rv; + /* ensure hash is valid */ + X509_check_purpose((X509 *)a, -1, 0); + X509_check_purpose((X509 *)b, -1, 0); + + rv = memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH); + if (rv) + return rv; + /* Check for match against stored encoding too */ + if (!a->cert_info.enc.modified && !b->cert_info.enc.modified) { + if (a->cert_info.enc.len < b->cert_info.enc.len) + return -1; + if (a->cert_info.enc.len > b->cert_info.enc.len) + return 1; + return memcmp(a->cert_info.enc.enc, b->cert_info.enc.enc, + a->cert_info.enc.len); + } + return rv; +} + +int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b) +{ + int ret; + + /* Ensure canonical encoding is present and up to date */ + + if (!a->canon_enc || a->modified) { + ret = i2d_X509_NAME((X509_NAME *)a, NULL); + if (ret < 0) + return -2; + } + + if (!b->canon_enc || b->modified) { + ret = i2d_X509_NAME((X509_NAME *)b, NULL); + if (ret < 0) + return -2; + } + + ret = a->canon_enclen - b->canon_enclen; + + if (ret != 0 || a->canon_enclen == 0) + return ret; + + return memcmp(a->canon_enc, b->canon_enc, a->canon_enclen); + +} + +unsigned long X509_NAME_hash(X509_NAME *x) +{ + unsigned long ret = 0; + unsigned char md[SHA_DIGEST_LENGTH]; + + /* Make sure X509_NAME structure contains valid cached encoding */ + i2d_X509_NAME(x, NULL); + if (!EVP_Digest(x->canon_enc, x->canon_enclen, md, NULL, EVP_sha1(), + NULL)) + return 0; + + ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) | + ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L) + ) & 0xffffffffL; + return ret; +} + +#ifndef OPENSSL_NO_MD5 +/* + * I now DER encode the name and hash it. Since I cache the DER encoding, + * this is reasonably efficient. + */ + +unsigned long X509_NAME_hash_old(X509_NAME *x) +{ + EVP_MD_CTX *md_ctx = EVP_MD_CTX_new(); + unsigned long ret = 0; + unsigned char md[16]; + + if (md_ctx == NULL) + return ret; + + /* Make sure X509_NAME structure contains valid cached encoding */ + i2d_X509_NAME(x, NULL); + EVP_MD_CTX_set_flags(md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); + if (EVP_DigestInit_ex(md_ctx, EVP_md5(), NULL) + && EVP_DigestUpdate(md_ctx, x->bytes->data, x->bytes->length) + && EVP_DigestFinal_ex(md_ctx, md, NULL)) + ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) | + ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L) + ) & 0xffffffffL; + EVP_MD_CTX_free(md_ctx); + + return ret; +} +#endif + +/* Search a stack of X509 for a match */ +X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, X509_NAME *name, + ASN1_INTEGER *serial) +{ + int i; + X509 x, *x509 = NULL; + + if (!sk) + return NULL; + + x.cert_info.serialNumber = *serial; + x.cert_info.issuer = name; + + for (i = 0; i < sk_X509_num(sk); i++) { + x509 = sk_X509_value(sk, i); + if (X509_issuer_and_serial_cmp(x509, &x) == 0) + return x509; + } + return NULL; +} + +X509 *X509_find_by_subject(STACK_OF(X509) *sk, X509_NAME *name) +{ + X509 *x509; + int i; + + for (i = 0; i < sk_X509_num(sk); i++) { + x509 = sk_X509_value(sk, i); + if (X509_NAME_cmp(X509_get_subject_name(x509), name) == 0) + return x509; + } + return NULL; +} + +EVP_PKEY *X509_get0_pubkey(const X509 *x) +{ + if (x == NULL) + return NULL; + return X509_PUBKEY_get0(x->cert_info.key); +} + +EVP_PKEY *X509_get_pubkey(X509 *x) +{ + if (x == NULL) + return NULL; + return X509_PUBKEY_get(x->cert_info.key); +} + +int X509_check_private_key(const X509 *x, const EVP_PKEY *k) +{ + const EVP_PKEY *xk; + int ret; + + xk = X509_get0_pubkey(x); + + if (xk) + ret = EVP_PKEY_cmp(xk, k); + else + ret = -2; + + switch (ret) { + case 1: + break; + case 0: + X509err(X509_F_X509_CHECK_PRIVATE_KEY, X509_R_KEY_VALUES_MISMATCH); + break; + case -1: + X509err(X509_F_X509_CHECK_PRIVATE_KEY, X509_R_KEY_TYPE_MISMATCH); + break; + case -2: + X509err(X509_F_X509_CHECK_PRIVATE_KEY, X509_R_UNKNOWN_KEY_TYPE); + } + if (ret > 0) + return 1; + return 0; +} + +/* + * Check a suite B algorithm is permitted: pass in a public key and the NID + * of its signature (or 0 if no signature). The pflags is a pointer to a + * flags field which must contain the suite B verification flags. + */ + +#ifndef OPENSSL_NO_EC + +static int check_suite_b(EVP_PKEY *pkey, int sign_nid, unsigned long *pflags) +{ + const EC_GROUP *grp = NULL; + int curve_nid; + if (pkey && EVP_PKEY_id(pkey) == EVP_PKEY_EC) + grp = EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey)); + if (!grp) + return X509_V_ERR_SUITE_B_INVALID_ALGORITHM; + curve_nid = EC_GROUP_get_curve_name(grp); + /* Check curve is consistent with LOS */ + if (curve_nid == NID_secp384r1) { /* P-384 */ + /* + * Check signature algorithm is consistent with curve. + */ + if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA384) + return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM; + if (!(*pflags & X509_V_FLAG_SUITEB_192_LOS)) + return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED; + /* If we encounter P-384 we cannot use P-256 later */ + *pflags &= ~X509_V_FLAG_SUITEB_128_LOS_ONLY; + } else if (curve_nid == NID_X9_62_prime256v1) { /* P-256 */ + if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA256) + return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM; + if (!(*pflags & X509_V_FLAG_SUITEB_128_LOS_ONLY)) + return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED; + } else + return X509_V_ERR_SUITE_B_INVALID_CURVE; + + return X509_V_OK; +} + +int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain, + unsigned long flags) +{ + int rv, i, sign_nid; + EVP_PKEY *pk; + unsigned long tflags = flags; + + if (!(flags & X509_V_FLAG_SUITEB_128_LOS)) + return X509_V_OK; + + /* If no EE certificate passed in must be first in chain */ + if (x == NULL) { + x = sk_X509_value(chain, 0); + i = 1; + } else + i = 0; + + pk = X509_get0_pubkey(x); + + /* + * With DANE-EE(3) success, or DANE-EE(3)/PKIX-EE(1) failure we don't build + * a chain all, just report trust success or failure, but must also report + * Suite-B errors if applicable. This is indicated via a NULL chain + * pointer. All we need to do is check the leaf key algorithm. + */ + if (chain == NULL) + return check_suite_b(pk, -1, &tflags); + + if (X509_get_version(x) != 2) { + rv = X509_V_ERR_SUITE_B_INVALID_VERSION; + /* Correct error depth */ + i = 0; + goto end; + } + + /* Check EE key only */ + rv = check_suite_b(pk, -1, &tflags); + if (rv != X509_V_OK) { + /* Correct error depth */ + i = 0; + goto end; + } + for (; i < sk_X509_num(chain); i++) { + sign_nid = X509_get_signature_nid(x); + x = sk_X509_value(chain, i); + if (X509_get_version(x) != 2) { + rv = X509_V_ERR_SUITE_B_INVALID_VERSION; + goto end; + } + pk = X509_get0_pubkey(x); + rv = check_suite_b(pk, sign_nid, &tflags); + if (rv != X509_V_OK) + goto end; + } + + /* Final check: root CA signature */ + rv = check_suite_b(pk, X509_get_signature_nid(x), &tflags); + end: + if (rv != X509_V_OK) { + /* Invalid signature or LOS errors are for previous cert */ + if ((rv == X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM + || rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED) && i) + i--; + /* + * If we have LOS error and flags changed then we are signing P-384 + * with P-256. Use more meaningful error. + */ + if (rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED && flags != tflags) + rv = X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256; + if (perror_depth) + *perror_depth = i; + } + return rv; +} + +int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags) +{ + int sign_nid; + if (!(flags & X509_V_FLAG_SUITEB_128_LOS)) + return X509_V_OK; + sign_nid = OBJ_obj2nid(crl->crl.sig_alg.algorithm); + return check_suite_b(pk, sign_nid, &flags); +} + +#else +int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain, + unsigned long flags) +{ + return 0; +} + +int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags) +{ + return 0; +} + +#endif +/* + * Not strictly speaking an "up_ref" as a STACK doesn't have a reference + * count but it has the same effect by duping the STACK and upping the ref of + * each X509 structure. + */ +STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain) +{ + STACK_OF(X509) *ret; + int i; + ret = sk_X509_dup(chain); + for (i = 0; i < sk_X509_num(ret); i++) { + X509 *x = sk_X509_value(ret, i); + X509_up_ref(x); + } + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_d2.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_d2.c new file mode 100644 index 000000000..099ffda1e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_d2.c @@ -0,0 +1,57 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include + +int X509_STORE_set_default_paths(X509_STORE *ctx) +{ + X509_LOOKUP *lookup; + + lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_file()); + if (lookup == NULL) + return 0; + X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); + + lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_hash_dir()); + if (lookup == NULL) + return 0; + X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); + + /* clear any errors */ + ERR_clear_error(); + + return 1; +} + +int X509_STORE_load_locations(X509_STORE *ctx, const char *file, + const char *path) +{ + X509_LOOKUP *lookup; + + if (file != NULL) { + lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_file()); + if (lookup == NULL) + return 0; + if (X509_LOOKUP_load_file(lookup, file, X509_FILETYPE_PEM) != 1) + return 0; + } + if (path != NULL) { + lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_hash_dir()); + if (lookup == NULL) + return 0; + if (X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) != 1) + return 0; + } + if ((path == NULL) && (file == NULL)) + return 0; + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_def.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_def.c new file mode 100644 index 000000000..bfa8d7d85 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_def.c @@ -0,0 +1,43 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include + +const char *X509_get_default_private_dir(void) +{ + return X509_PRIVATE_DIR; +} + +const char *X509_get_default_cert_area(void) +{ + return X509_CERT_AREA; +} + +const char *X509_get_default_cert_dir(void) +{ + return X509_CERT_DIR; +} + +const char *X509_get_default_cert_file(void) +{ + return X509_CERT_FILE; +} + +const char *X509_get_default_cert_dir_env(void) +{ + return X509_CERT_DIR_EVP; +} + +const char *X509_get_default_cert_file_env(void) +{ + return X509_CERT_FILE_EVP; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_err.c new file mode 100644 index 000000000..739708e24 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_err.c @@ -0,0 +1,181 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA X509_str_functs[] = { + {ERR_PACK(ERR_LIB_X509, X509_F_ADD_CERT_DIR, 0), "add_cert_dir"}, + {ERR_PACK(ERR_LIB_X509, X509_F_BUILD_CHAIN, 0), "build_chain"}, + {ERR_PACK(ERR_LIB_X509, X509_F_BY_FILE_CTRL, 0), "by_file_ctrl"}, + {ERR_PACK(ERR_LIB_X509, X509_F_CHECK_NAME_CONSTRAINTS, 0), + "check_name_constraints"}, + {ERR_PACK(ERR_LIB_X509, X509_F_CHECK_POLICY, 0), "check_policy"}, + {ERR_PACK(ERR_LIB_X509, X509_F_DANE_I2D, 0), "dane_i2d"}, + {ERR_PACK(ERR_LIB_X509, X509_F_DIR_CTRL, 0), "dir_ctrl"}, + {ERR_PACK(ERR_LIB_X509, X509_F_GET_CERT_BY_SUBJECT, 0), + "get_cert_by_subject"}, + {ERR_PACK(ERR_LIB_X509, X509_F_I2D_X509_AUX, 0), "i2d_X509_AUX"}, + {ERR_PACK(ERR_LIB_X509, X509_F_LOOKUP_CERTS_SK, 0), "lookup_certs_sk"}, + {ERR_PACK(ERR_LIB_X509, X509_F_NETSCAPE_SPKI_B64_DECODE, 0), + "NETSCAPE_SPKI_b64_decode"}, + {ERR_PACK(ERR_LIB_X509, X509_F_NETSCAPE_SPKI_B64_ENCODE, 0), + "NETSCAPE_SPKI_b64_encode"}, + {ERR_PACK(ERR_LIB_X509, X509_F_NEW_DIR, 0), "new_dir"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509AT_ADD1_ATTR, 0), "X509at_add1_attr"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509V3_ADD_EXT, 0), "X509v3_add_ext"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_CREATE_BY_NID, 0), + "X509_ATTRIBUTE_create_by_NID"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_CREATE_BY_OBJ, 0), + "X509_ATTRIBUTE_create_by_OBJ"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_CREATE_BY_TXT, 0), + "X509_ATTRIBUTE_create_by_txt"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_GET0_DATA, 0), + "X509_ATTRIBUTE_get0_data"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_SET1_DATA, 0), + "X509_ATTRIBUTE_set1_data"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_CHECK_PRIVATE_KEY, 0), + "X509_check_private_key"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_CRL_DIFF, 0), "X509_CRL_diff"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_CRL_METHOD_NEW, 0), + "X509_CRL_METHOD_new"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_CRL_PRINT_FP, 0), "X509_CRL_print_fp"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_EXTENSION_CREATE_BY_NID, 0), + "X509_EXTENSION_create_by_NID"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_EXTENSION_CREATE_BY_OBJ, 0), + "X509_EXTENSION_create_by_OBJ"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_GET_PUBKEY_PARAMETERS, 0), + "X509_get_pubkey_parameters"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_LOAD_CERT_CRL_FILE, 0), + "X509_load_cert_crl_file"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_LOAD_CERT_FILE, 0), + "X509_load_cert_file"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_LOAD_CRL_FILE, 0), + "X509_load_crl_file"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_LOOKUP_METH_NEW, 0), + "X509_LOOKUP_meth_new"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_LOOKUP_NEW, 0), "X509_LOOKUP_new"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_ADD_ENTRY, 0), + "X509_NAME_add_entry"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_CANON, 0), "x509_name_canon"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_ENTRY_CREATE_BY_NID, 0), + "X509_NAME_ENTRY_create_by_NID"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_ENTRY_CREATE_BY_TXT, 0), + "X509_NAME_ENTRY_create_by_txt"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_ENTRY_SET_OBJECT, 0), + "X509_NAME_ENTRY_set_object"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_ONELINE, 0), "X509_NAME_oneline"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_PRINT, 0), "X509_NAME_print"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_OBJECT_NEW, 0), "X509_OBJECT_new"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_PRINT_EX_FP, 0), "X509_print_ex_fp"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_PUBKEY_DECODE, 0), + "x509_pubkey_decode"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_PUBKEY_GET0, 0), "X509_PUBKEY_get0"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_PUBKEY_SET, 0), "X509_PUBKEY_set"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_CHECK_PRIVATE_KEY, 0), + "X509_REQ_check_private_key"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_PRINT_EX, 0), "X509_REQ_print_ex"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_PRINT_FP, 0), "X509_REQ_print_fp"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_TO_X509, 0), "X509_REQ_to_X509"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_ADD_CERT, 0), + "X509_STORE_add_cert"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_ADD_CRL, 0), + "X509_STORE_add_crl"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_ADD_LOOKUP, 0), + "X509_STORE_add_lookup"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_CTX_GET1_ISSUER, 0), + "X509_STORE_CTX_get1_issuer"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_CTX_INIT, 0), + "X509_STORE_CTX_init"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_CTX_NEW, 0), + "X509_STORE_CTX_new"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_CTX_PURPOSE_INHERIT, 0), + "X509_STORE_CTX_purpose_inherit"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_NEW, 0), "X509_STORE_new"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_TO_X509_REQ, 0), "X509_to_X509_REQ"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_TRUST_ADD, 0), "X509_TRUST_add"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_TRUST_SET, 0), "X509_TRUST_set"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_VERIFY_CERT, 0), "X509_verify_cert"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_VERIFY_PARAM_NEW, 0), + "X509_VERIFY_PARAM_new"}, + {0, NULL} +}; + +static const ERR_STRING_DATA X509_str_reasons[] = { + {ERR_PACK(ERR_LIB_X509, 0, X509_R_AKID_MISMATCH), "akid mismatch"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_BAD_SELECTOR), "bad selector"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_BAD_X509_FILETYPE), "bad x509 filetype"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_BASE64_DECODE_ERROR), + "base64 decode error"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_CANT_CHECK_DH_KEY), "cant check dh key"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_CERT_ALREADY_IN_HASH_TABLE), + "cert already in hash table"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_CRL_ALREADY_DELTA), "crl already delta"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_CRL_VERIFY_FAILURE), + "crl verify failure"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_IDP_MISMATCH), "idp mismatch"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_DIRECTORY), "invalid directory"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_FIELD_NAME), + "invalid field name"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_TRUST), "invalid trust"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_ISSUER_MISMATCH), "issuer mismatch"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_KEY_TYPE_MISMATCH), "key type mismatch"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_KEY_VALUES_MISMATCH), + "key values mismatch"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_LOADING_CERT_DIR), "loading cert dir"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_LOADING_DEFAULTS), "loading defaults"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_METHOD_NOT_SUPPORTED), + "method not supported"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_NAME_TOO_LONG), "name too long"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_NEWER_CRL_NOT_NEWER), + "newer crl not newer"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_NO_CERTIFICATE_FOUND), + "no certificate found"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_NO_CERTIFICATE_OR_CRL_FOUND), + "no certificate or crl found"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY), + "no cert set for us to verify"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_NO_CRL_FOUND), "no crl found"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_NO_CRL_NUMBER), "no crl number"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_PUBLIC_KEY_DECODE_ERROR), + "public key decode error"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_PUBLIC_KEY_ENCODE_ERROR), + "public key encode error"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_SHOULD_RETRY), "should retry"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN), + "unable to find parameters in chain"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY), + "unable to get certs public key"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_KEY_TYPE), "unknown key type"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_NID), "unknown nid"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_PURPOSE_ID), + "unknown purpose id"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_TRUST_ID), "unknown trust id"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNSUPPORTED_ALGORITHM), + "unsupported algorithm"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_WRONG_LOOKUP_TYPE), "wrong lookup type"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_WRONG_TYPE), "wrong type"}, + {0, NULL} +}; + +#endif + +int ERR_load_X509_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(X509_str_functs[0].error) == NULL) { + ERR_load_strings_const(X509_str_functs); + ERR_load_strings_const(X509_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_ext.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_ext.c new file mode 100644 index 000000000..2db843760 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_ext.c @@ -0,0 +1,159 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "internal/x509_int.h" +#include + +int X509_CRL_get_ext_count(const X509_CRL *x) +{ + return X509v3_get_ext_count(x->crl.extensions); +} + +int X509_CRL_get_ext_by_NID(const X509_CRL *x, int nid, int lastpos) +{ + return X509v3_get_ext_by_NID(x->crl.extensions, nid, lastpos); +} + +int X509_CRL_get_ext_by_OBJ(const X509_CRL *x, const ASN1_OBJECT *obj, + int lastpos) +{ + return X509v3_get_ext_by_OBJ(x->crl.extensions, obj, lastpos); +} + +int X509_CRL_get_ext_by_critical(const X509_CRL *x, int crit, int lastpos) +{ + return X509v3_get_ext_by_critical(x->crl.extensions, crit, lastpos); +} + +X509_EXTENSION *X509_CRL_get_ext(const X509_CRL *x, int loc) +{ + return X509v3_get_ext(x->crl.extensions, loc); +} + +X509_EXTENSION *X509_CRL_delete_ext(X509_CRL *x, int loc) +{ + return X509v3_delete_ext(x->crl.extensions, loc); +} + +void *X509_CRL_get_ext_d2i(const X509_CRL *x, int nid, int *crit, int *idx) +{ + return X509V3_get_d2i(x->crl.extensions, nid, crit, idx); +} + +int X509_CRL_add1_ext_i2d(X509_CRL *x, int nid, void *value, int crit, + unsigned long flags) +{ + return X509V3_add1_i2d(&x->crl.extensions, nid, value, crit, flags); +} + +int X509_CRL_add_ext(X509_CRL *x, X509_EXTENSION *ex, int loc) +{ + return (X509v3_add_ext(&(x->crl.extensions), ex, loc) != NULL); +} + +int X509_get_ext_count(const X509 *x) +{ + return X509v3_get_ext_count(x->cert_info.extensions); +} + +int X509_get_ext_by_NID(const X509 *x, int nid, int lastpos) +{ + return X509v3_get_ext_by_NID(x->cert_info.extensions, nid, lastpos); +} + +int X509_get_ext_by_OBJ(const X509 *x, const ASN1_OBJECT *obj, int lastpos) +{ + return X509v3_get_ext_by_OBJ(x->cert_info.extensions, obj, lastpos); +} + +int X509_get_ext_by_critical(const X509 *x, int crit, int lastpos) +{ + return (X509v3_get_ext_by_critical + (x->cert_info.extensions, crit, lastpos)); +} + +X509_EXTENSION *X509_get_ext(const X509 *x, int loc) +{ + return X509v3_get_ext(x->cert_info.extensions, loc); +} + +X509_EXTENSION *X509_delete_ext(X509 *x, int loc) +{ + return X509v3_delete_ext(x->cert_info.extensions, loc); +} + +int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc) +{ + return (X509v3_add_ext(&(x->cert_info.extensions), ex, loc) != NULL); +} + +void *X509_get_ext_d2i(const X509 *x, int nid, int *crit, int *idx) +{ + return X509V3_get_d2i(x->cert_info.extensions, nid, crit, idx); +} + +int X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit, + unsigned long flags) +{ + return X509V3_add1_i2d(&x->cert_info.extensions, nid, value, crit, + flags); +} + +int X509_REVOKED_get_ext_count(const X509_REVOKED *x) +{ + return X509v3_get_ext_count(x->extensions); +} + +int X509_REVOKED_get_ext_by_NID(const X509_REVOKED *x, int nid, int lastpos) +{ + return X509v3_get_ext_by_NID(x->extensions, nid, lastpos); +} + +int X509_REVOKED_get_ext_by_OBJ(const X509_REVOKED *x, const ASN1_OBJECT *obj, + int lastpos) +{ + return X509v3_get_ext_by_OBJ(x->extensions, obj, lastpos); +} + +int X509_REVOKED_get_ext_by_critical(const X509_REVOKED *x, int crit, int lastpos) +{ + return X509v3_get_ext_by_critical(x->extensions, crit, lastpos); +} + +X509_EXTENSION *X509_REVOKED_get_ext(const X509_REVOKED *x, int loc) +{ + return X509v3_get_ext(x->extensions, loc); +} + +X509_EXTENSION *X509_REVOKED_delete_ext(X509_REVOKED *x, int loc) +{ + return X509v3_delete_ext(x->extensions, loc); +} + +int X509_REVOKED_add_ext(X509_REVOKED *x, X509_EXTENSION *ex, int loc) +{ + return (X509v3_add_ext(&(x->extensions), ex, loc) != NULL); +} + +void *X509_REVOKED_get_ext_d2i(const X509_REVOKED *x, int nid, int *crit, int *idx) +{ + return X509V3_get_d2i(x->extensions, nid, crit, idx); +} + +int X509_REVOKED_add1_ext_i2d(X509_REVOKED *x, int nid, void *value, int crit, + unsigned long flags) +{ + return X509V3_add1_i2d(&x->extensions, nid, value, crit, flags); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_lcl.h b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_lcl.h new file mode 100644 index 000000000..c517a7745 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_lcl.h @@ -0,0 +1,147 @@ +/* + * Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/refcount.h" + +/* + * This structure holds all parameters associated with a verify operation by + * including an X509_VERIFY_PARAM structure in related structures the + * parameters used can be customized + */ + +struct X509_VERIFY_PARAM_st { + char *name; + time_t check_time; /* Time to use */ + uint32_t inh_flags; /* Inheritance flags */ + unsigned long flags; /* Various verify flags */ + int purpose; /* purpose to check untrusted certificates */ + int trust; /* trust setting to check */ + int depth; /* Verify depth */ + int auth_level; /* Security level for chain verification */ + STACK_OF(ASN1_OBJECT) *policies; /* Permissible policies */ + /* Peer identity details */ + STACK_OF(OPENSSL_STRING) *hosts; /* Set of acceptable names */ + unsigned int hostflags; /* Flags to control matching features */ + char *peername; /* Matching hostname in peer certificate */ + char *email; /* If not NULL email address to match */ + size_t emaillen; + unsigned char *ip; /* If not NULL IP address to match */ + size_t iplen; /* Length of IP address */ +}; + +/* No error callback if depth < 0 */ +int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth); + +/* a sequence of these are used */ +struct x509_attributes_st { + ASN1_OBJECT *object; + STACK_OF(ASN1_TYPE) *set; +}; + +struct X509_extension_st { + ASN1_OBJECT *object; + ASN1_BOOLEAN critical; + ASN1_OCTET_STRING value; +}; + +/* + * Method to handle CRL access. In general a CRL could be very large (several + * Mb) and can consume large amounts of resources if stored in memory by + * multiple processes. This method allows general CRL operations to be + * redirected to more efficient callbacks: for example a CRL entry database. + */ + +#define X509_CRL_METHOD_DYNAMIC 1 + +struct x509_crl_method_st { + int flags; + int (*crl_init) (X509_CRL *crl); + int (*crl_free) (X509_CRL *crl); + int (*crl_lookup) (X509_CRL *crl, X509_REVOKED **ret, + ASN1_INTEGER *ser, X509_NAME *issuer); + int (*crl_verify) (X509_CRL *crl, EVP_PKEY *pk); +}; + +struct x509_lookup_method_st { + char *name; + int (*new_item) (X509_LOOKUP *ctx); + void (*free) (X509_LOOKUP *ctx); + int (*init) (X509_LOOKUP *ctx); + int (*shutdown) (X509_LOOKUP *ctx); + int (*ctrl) (X509_LOOKUP *ctx, int cmd, const char *argc, long argl, + char **ret); + int (*get_by_subject) (X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + X509_NAME *name, X509_OBJECT *ret); + int (*get_by_issuer_serial) (X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + X509_NAME *name, ASN1_INTEGER *serial, + X509_OBJECT *ret); + int (*get_by_fingerprint) (X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + const unsigned char *bytes, int len, + X509_OBJECT *ret); + int (*get_by_alias) (X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + const char *str, int len, X509_OBJECT *ret); +}; + +/* This is the functions plus an instance of the local variables. */ +struct x509_lookup_st { + int init; /* have we been started */ + int skip; /* don't use us. */ + X509_LOOKUP_METHOD *method; /* the functions */ + void *method_data; /* method data */ + X509_STORE *store_ctx; /* who owns us */ +}; + +/* + * This is used to hold everything. It is used for all certificate + * validation. Once we have a certificate chain, the 'verify' function is + * then called to actually check the cert chain. + */ +struct x509_store_st { + /* The following is a cache of trusted certs */ + int cache; /* if true, stash any hits */ + STACK_OF(X509_OBJECT) *objs; /* Cache of all objects */ + /* These are external lookup methods */ + STACK_OF(X509_LOOKUP) *get_cert_methods; + X509_VERIFY_PARAM *param; + /* Callbacks for various operations */ + /* called to verify a certificate */ + int (*verify) (X509_STORE_CTX *ctx); + /* error callback */ + int (*verify_cb) (int ok, X509_STORE_CTX *ctx); + /* get issuers cert from ctx */ + int (*get_issuer) (X509 **issuer, X509_STORE_CTX *ctx, X509 *x); + /* check issued */ + int (*check_issued) (X509_STORE_CTX *ctx, X509 *x, X509 *issuer); + /* Check revocation status of chain */ + int (*check_revocation) (X509_STORE_CTX *ctx); + /* retrieve CRL */ + int (*get_crl) (X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x); + /* Check CRL validity */ + int (*check_crl) (X509_STORE_CTX *ctx, X509_CRL *crl); + /* Check certificate against CRL */ + int (*cert_crl) (X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); + /* Check policy status of the chain */ + int (*check_policy) (X509_STORE_CTX *ctx); + STACK_OF(X509) *(*lookup_certs) (X509_STORE_CTX *ctx, X509_NAME *nm); + STACK_OF(X509_CRL) *(*lookup_crls) (X509_STORE_CTX *ctx, X509_NAME *nm); + int (*cleanup) (X509_STORE_CTX *ctx); + CRYPTO_EX_DATA ex_data; + CRYPTO_REF_COUNT references; + CRYPTO_RWLOCK *lock; +}; + +typedef struct lookup_dir_hashes_st BY_DIR_HASH; +typedef struct lookup_dir_entry_st BY_DIR_ENTRY; +DEFINE_STACK_OF(BY_DIR_HASH) +DEFINE_STACK_OF(BY_DIR_ENTRY) +typedef STACK_OF(X509_NAME_ENTRY) STACK_OF_X509_NAME_ENTRY; +DEFINE_STACK_OF(STACK_OF_X509_NAME_ENTRY) + +void x509_set_signature_info(X509_SIG_INFO *siginf, const X509_ALGOR *alg, + const ASN1_STRING *sig); diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_lu.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_lu.c new file mode 100644 index 000000000..be39015b0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_lu.c @@ -0,0 +1,898 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include "internal/refcount.h" +#include +#include "internal/x509_int.h" +#include +#include "x509_lcl.h" + +X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method) +{ + X509_LOOKUP *ret = OPENSSL_zalloc(sizeof(*ret)); + + if (ret == NULL) { + X509err(X509_F_X509_LOOKUP_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + ret->method = method; + if (method->new_item != NULL && method->new_item(ret) == 0) { + OPENSSL_free(ret); + return NULL; + } + return ret; +} + +void X509_LOOKUP_free(X509_LOOKUP *ctx) +{ + if (ctx == NULL) + return; + if ((ctx->method != NULL) && (ctx->method->free != NULL)) + (*ctx->method->free) (ctx); + OPENSSL_free(ctx); +} + +int X509_STORE_lock(X509_STORE *s) +{ + return CRYPTO_THREAD_write_lock(s->lock); +} + +int X509_STORE_unlock(X509_STORE *s) +{ + return CRYPTO_THREAD_unlock(s->lock); +} + +int X509_LOOKUP_init(X509_LOOKUP *ctx) +{ + if (ctx->method == NULL) + return 0; + if (ctx->method->init != NULL) + return ctx->method->init(ctx); + else + return 1; +} + +int X509_LOOKUP_shutdown(X509_LOOKUP *ctx) +{ + if (ctx->method == NULL) + return 0; + if (ctx->method->shutdown != NULL) + return ctx->method->shutdown(ctx); + else + return 1; +} + +int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, + char **ret) +{ + if (ctx->method == NULL) + return -1; + if (ctx->method->ctrl != NULL) + return ctx->method->ctrl(ctx, cmd, argc, argl, ret); + else + return 1; +} + +int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + X509_NAME *name, X509_OBJECT *ret) +{ + if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL)) + return 0; + if (ctx->skip) + return 0; + return ctx->method->get_by_subject(ctx, type, name, ret); +} + +int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + X509_NAME *name, ASN1_INTEGER *serial, + X509_OBJECT *ret) +{ + if ((ctx->method == NULL) || (ctx->method->get_by_issuer_serial == NULL)) + return 0; + return ctx->method->get_by_issuer_serial(ctx, type, name, serial, ret); +} + +int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + const unsigned char *bytes, int len, + X509_OBJECT *ret) +{ + if ((ctx->method == NULL) || (ctx->method->get_by_fingerprint == NULL)) + return 0; + return ctx->method->get_by_fingerprint(ctx, type, bytes, len, ret); +} + +int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + const char *str, int len, X509_OBJECT *ret) +{ + if ((ctx->method == NULL) || (ctx->method->get_by_alias == NULL)) + return 0; + return ctx->method->get_by_alias(ctx, type, str, len, ret); +} + +int X509_LOOKUP_set_method_data(X509_LOOKUP *ctx, void *data) +{ + ctx->method_data = data; + return 1; +} + +void *X509_LOOKUP_get_method_data(const X509_LOOKUP *ctx) +{ + return ctx->method_data; +} + +X509_STORE *X509_LOOKUP_get_store(const X509_LOOKUP *ctx) +{ + return ctx->store_ctx; +} + + +static int x509_object_cmp(const X509_OBJECT *const *a, + const X509_OBJECT *const *b) +{ + int ret; + + ret = ((*a)->type - (*b)->type); + if (ret) + return ret; + switch ((*a)->type) { + case X509_LU_X509: + ret = X509_subject_name_cmp((*a)->data.x509, (*b)->data.x509); + break; + case X509_LU_CRL: + ret = X509_CRL_cmp((*a)->data.crl, (*b)->data.crl); + break; + case X509_LU_NONE: + /* abort(); */ + return 0; + } + return ret; +} + +X509_STORE *X509_STORE_new(void) +{ + X509_STORE *ret = OPENSSL_zalloc(sizeof(*ret)); + + if (ret == NULL) { + X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + if ((ret->objs = sk_X509_OBJECT_new(x509_object_cmp)) == NULL) { + X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE); + goto err; + } + ret->cache = 1; + if ((ret->get_cert_methods = sk_X509_LOOKUP_new_null()) == NULL) { + X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE); + goto err; + } + + if ((ret->param = X509_VERIFY_PARAM_new()) == NULL) { + X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE, ret, &ret->ex_data)) { + X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE); + goto err; + } + + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) { + X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE); + goto err; + } + + ret->references = 1; + return ret; + +err: + X509_VERIFY_PARAM_free(ret->param); + sk_X509_OBJECT_free(ret->objs); + sk_X509_LOOKUP_free(ret->get_cert_methods); + OPENSSL_free(ret); + return NULL; +} + +void X509_STORE_free(X509_STORE *vfy) +{ + int i; + STACK_OF(X509_LOOKUP) *sk; + X509_LOOKUP *lu; + + if (vfy == NULL) + return; + CRYPTO_DOWN_REF(&vfy->references, &i, vfy->lock); + REF_PRINT_COUNT("X509_STORE", vfy); + if (i > 0) + return; + REF_ASSERT_ISNT(i < 0); + + sk = vfy->get_cert_methods; + for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) { + lu = sk_X509_LOOKUP_value(sk, i); + X509_LOOKUP_shutdown(lu); + X509_LOOKUP_free(lu); + } + sk_X509_LOOKUP_free(sk); + sk_X509_OBJECT_pop_free(vfy->objs, X509_OBJECT_free); + + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE, vfy, &vfy->ex_data); + X509_VERIFY_PARAM_free(vfy->param); + CRYPTO_THREAD_lock_free(vfy->lock); + OPENSSL_free(vfy); +} + +int X509_STORE_up_ref(X509_STORE *vfy) +{ + int i; + + if (CRYPTO_UP_REF(&vfy->references, &i, vfy->lock) <= 0) + return 0; + + REF_PRINT_COUNT("X509_STORE", a); + REF_ASSERT_ISNT(i < 2); + return ((i > 1) ? 1 : 0); +} + +X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m) +{ + int i; + STACK_OF(X509_LOOKUP) *sk; + X509_LOOKUP *lu; + + sk = v->get_cert_methods; + for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) { + lu = sk_X509_LOOKUP_value(sk, i); + if (m == lu->method) { + return lu; + } + } + /* a new one */ + lu = X509_LOOKUP_new(m); + if (lu == NULL) { + X509err(X509_F_X509_STORE_ADD_LOOKUP, ERR_R_MALLOC_FAILURE); + return NULL; + } + + lu->store_ctx = v; + if (sk_X509_LOOKUP_push(v->get_cert_methods, lu)) + return lu; + /* malloc failed */ + X509err(X509_F_X509_STORE_ADD_LOOKUP, ERR_R_MALLOC_FAILURE); + X509_LOOKUP_free(lu); + return NULL; +} + +X509_OBJECT *X509_STORE_CTX_get_obj_by_subject(X509_STORE_CTX *vs, + X509_LOOKUP_TYPE type, + X509_NAME *name) +{ + X509_OBJECT *ret = X509_OBJECT_new(); + + if (ret == NULL) + return NULL; + if (!X509_STORE_CTX_get_by_subject(vs, type, name, ret)) { + X509_OBJECT_free(ret); + return NULL; + } + return ret; +} + +int X509_STORE_CTX_get_by_subject(X509_STORE_CTX *vs, X509_LOOKUP_TYPE type, + X509_NAME *name, X509_OBJECT *ret) +{ + X509_STORE *ctx = vs->ctx; + X509_LOOKUP *lu; + X509_OBJECT stmp, *tmp; + int i, j; + + if (ctx == NULL) + return 0; + + CRYPTO_THREAD_write_lock(ctx->lock); + tmp = X509_OBJECT_retrieve_by_subject(ctx->objs, type, name); + CRYPTO_THREAD_unlock(ctx->lock); + + if (tmp == NULL || type == X509_LU_CRL) { + for (i = 0; i < sk_X509_LOOKUP_num(ctx->get_cert_methods); i++) { + lu = sk_X509_LOOKUP_value(ctx->get_cert_methods, i); + j = X509_LOOKUP_by_subject(lu, type, name, &stmp); + if (j) { + tmp = &stmp; + break; + } + } + if (tmp == NULL) + return 0; + } + + ret->type = tmp->type; + ret->data.ptr = tmp->data.ptr; + + X509_OBJECT_up_ref_count(ret); + + return 1; +} + +static int x509_store_add(X509_STORE *ctx, void *x, int crl) { + X509_OBJECT *obj; + int ret = 0, added = 0; + + if (x == NULL) + return 0; + obj = X509_OBJECT_new(); + if (obj == NULL) + return 0; + + if (crl) { + obj->type = X509_LU_CRL; + obj->data.crl = (X509_CRL *)x; + } else { + obj->type = X509_LU_X509; + obj->data.x509 = (X509 *)x; + } + X509_OBJECT_up_ref_count(obj); + + CRYPTO_THREAD_write_lock(ctx->lock); + + if (X509_OBJECT_retrieve_match(ctx->objs, obj)) { + ret = 1; + } else { + added = sk_X509_OBJECT_push(ctx->objs, obj); + ret = added != 0; + } + + CRYPTO_THREAD_unlock(ctx->lock); + + if (added == 0) /* obj not pushed */ + X509_OBJECT_free(obj); + + return ret; +} + +int X509_STORE_add_cert(X509_STORE *ctx, X509 *x) +{ + if (!x509_store_add(ctx, x, 0)) { + X509err(X509_F_X509_STORE_ADD_CERT, ERR_R_MALLOC_FAILURE); + return 0; + } + return 1; +} + +int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x) +{ + if (!x509_store_add(ctx, x, 1)) { + X509err(X509_F_X509_STORE_ADD_CRL, ERR_R_MALLOC_FAILURE); + return 0; + } + return 1; +} + +int X509_OBJECT_up_ref_count(X509_OBJECT *a) +{ + switch (a->type) { + case X509_LU_NONE: + break; + case X509_LU_X509: + return X509_up_ref(a->data.x509); + case X509_LU_CRL: + return X509_CRL_up_ref(a->data.crl); + } + return 1; +} + +X509 *X509_OBJECT_get0_X509(const X509_OBJECT *a) +{ + if (a == NULL || a->type != X509_LU_X509) + return NULL; + return a->data.x509; +} + +X509_CRL *X509_OBJECT_get0_X509_CRL(X509_OBJECT *a) +{ + if (a == NULL || a->type != X509_LU_CRL) + return NULL; + return a->data.crl; +} + +X509_LOOKUP_TYPE X509_OBJECT_get_type(const X509_OBJECT *a) +{ + return a->type; +} + +X509_OBJECT *X509_OBJECT_new(void) +{ + X509_OBJECT *ret = OPENSSL_zalloc(sizeof(*ret)); + + if (ret == NULL) { + X509err(X509_F_X509_OBJECT_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + ret->type = X509_LU_NONE; + return ret; +} + +static void x509_object_free_internal(X509_OBJECT *a) +{ + if (a == NULL) + return; + switch (a->type) { + case X509_LU_NONE: + break; + case X509_LU_X509: + X509_free(a->data.x509); + break; + case X509_LU_CRL: + X509_CRL_free(a->data.crl); + break; + } +} + +int X509_OBJECT_set1_X509(X509_OBJECT *a, X509 *obj) +{ + if (a == NULL || !X509_up_ref(obj)) + return 0; + + x509_object_free_internal(a); + a->type = X509_LU_X509; + a->data.x509 = obj; + return 1; +} + +int X509_OBJECT_set1_X509_CRL(X509_OBJECT *a, X509_CRL *obj) +{ + if (a == NULL || !X509_CRL_up_ref(obj)) + return 0; + + x509_object_free_internal(a); + a->type = X509_LU_CRL; + a->data.crl = obj; + return 1; +} + +void X509_OBJECT_free(X509_OBJECT *a) +{ + x509_object_free_internal(a); + OPENSSL_free(a); +} + +static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type, + X509_NAME *name, int *pnmatch) +{ + X509_OBJECT stmp; + X509 x509_s; + X509_CRL crl_s; + int idx; + + stmp.type = type; + switch (type) { + case X509_LU_X509: + stmp.data.x509 = &x509_s; + x509_s.cert_info.subject = name; + break; + case X509_LU_CRL: + stmp.data.crl = &crl_s; + crl_s.crl.issuer = name; + break; + case X509_LU_NONE: + /* abort(); */ + return -1; + } + + idx = sk_X509_OBJECT_find(h, &stmp); + if (idx >= 0 && pnmatch) { + int tidx; + const X509_OBJECT *tobj, *pstmp; + *pnmatch = 1; + pstmp = &stmp; + for (tidx = idx + 1; tidx < sk_X509_OBJECT_num(h); tidx++) { + tobj = sk_X509_OBJECT_value(h, tidx); + if (x509_object_cmp(&tobj, &pstmp)) + break; + (*pnmatch)++; + } + } + return idx; +} + +int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type, + X509_NAME *name) +{ + return x509_object_idx_cnt(h, type, name, NULL); +} + +X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, + X509_LOOKUP_TYPE type, + X509_NAME *name) +{ + int idx; + idx = X509_OBJECT_idx_by_subject(h, type, name); + if (idx == -1) + return NULL; + return sk_X509_OBJECT_value(h, idx); +} + +STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *v) +{ + return v->objs; +} + +STACK_OF(X509) *X509_STORE_CTX_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm) +{ + int i, idx, cnt; + STACK_OF(X509) *sk = NULL; + X509 *x; + X509_OBJECT *obj; + + if (ctx->ctx == NULL) + return NULL; + + CRYPTO_THREAD_write_lock(ctx->ctx->lock); + idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt); + if (idx < 0) { + /* + * Nothing found in cache: do lookup to possibly add new objects to + * cache + */ + X509_OBJECT *xobj = X509_OBJECT_new(); + + CRYPTO_THREAD_unlock(ctx->ctx->lock); + if (xobj == NULL) + return NULL; + if (!X509_STORE_CTX_get_by_subject(ctx, X509_LU_X509, nm, xobj)) { + X509_OBJECT_free(xobj); + return NULL; + } + X509_OBJECT_free(xobj); + CRYPTO_THREAD_write_lock(ctx->ctx->lock); + idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt); + if (idx < 0) { + CRYPTO_THREAD_unlock(ctx->ctx->lock); + return NULL; + } + } + + sk = sk_X509_new_null(); + for (i = 0; i < cnt; i++, idx++) { + obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx); + x = obj->data.x509; + X509_up_ref(x); + if (!sk_X509_push(sk, x)) { + CRYPTO_THREAD_unlock(ctx->ctx->lock); + X509_free(x); + sk_X509_pop_free(sk, X509_free); + return NULL; + } + } + CRYPTO_THREAD_unlock(ctx->ctx->lock); + return sk; +} + +STACK_OF(X509_CRL) *X509_STORE_CTX_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm) +{ + int i, idx, cnt; + STACK_OF(X509_CRL) *sk = sk_X509_CRL_new_null(); + X509_CRL *x; + X509_OBJECT *obj, *xobj = X509_OBJECT_new(); + + /* Always do lookup to possibly add new CRLs to cache */ + if (sk == NULL + || xobj == NULL + || ctx->ctx == NULL + || !X509_STORE_CTX_get_by_subject(ctx, X509_LU_CRL, nm, xobj)) { + X509_OBJECT_free(xobj); + sk_X509_CRL_free(sk); + return NULL; + } + X509_OBJECT_free(xobj); + CRYPTO_THREAD_write_lock(ctx->ctx->lock); + idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_CRL, nm, &cnt); + if (idx < 0) { + CRYPTO_THREAD_unlock(ctx->ctx->lock); + sk_X509_CRL_free(sk); + return NULL; + } + + for (i = 0; i < cnt; i++, idx++) { + obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx); + x = obj->data.crl; + X509_CRL_up_ref(x); + if (!sk_X509_CRL_push(sk, x)) { + CRYPTO_THREAD_unlock(ctx->ctx->lock); + X509_CRL_free(x); + sk_X509_CRL_pop_free(sk, X509_CRL_free); + return NULL; + } + } + CRYPTO_THREAD_unlock(ctx->ctx->lock); + return sk; +} + +X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, + X509_OBJECT *x) +{ + int idx, i, num; + X509_OBJECT *obj; + + idx = sk_X509_OBJECT_find(h, x); + if (idx < 0) + return NULL; + if ((x->type != X509_LU_X509) && (x->type != X509_LU_CRL)) + return sk_X509_OBJECT_value(h, idx); + for (i = idx, num = sk_X509_OBJECT_num(h); i < num; i++) { + obj = sk_X509_OBJECT_value(h, i); + if (x509_object_cmp((const X509_OBJECT **)&obj, + (const X509_OBJECT **)&x)) + return NULL; + if (x->type == X509_LU_X509) { + if (!X509_cmp(obj->data.x509, x->data.x509)) + return obj; + } else if (x->type == X509_LU_CRL) { + if (!X509_CRL_match(obj->data.crl, x->data.crl)) + return obj; + } else + return obj; + } + return NULL; +} + +/*- + * Try to get issuer certificate from store. Due to limitations + * of the API this can only retrieve a single certificate matching + * a given subject name. However it will fill the cache with all + * matching certificates, so we can examine the cache for all + * matches. + * + * Return values are: + * 1 lookup successful. + * 0 certificate not found. + * -1 some other error. + */ +int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) +{ + X509_NAME *xn; + X509_OBJECT *obj = X509_OBJECT_new(), *pobj = NULL; + int i, ok, idx, ret; + + if (obj == NULL) + return -1; + *issuer = NULL; + xn = X509_get_issuer_name(x); + ok = X509_STORE_CTX_get_by_subject(ctx, X509_LU_X509, xn, obj); + if (ok != 1) { + X509_OBJECT_free(obj); + return 0; + } + /* If certificate matches all OK */ + if (ctx->check_issued(ctx, x, obj->data.x509)) { + if (x509_check_cert_time(ctx, obj->data.x509, -1)) { + *issuer = obj->data.x509; + X509_up_ref(*issuer); + X509_OBJECT_free(obj); + return 1; + } + } + X509_OBJECT_free(obj); + + if (ctx->ctx == NULL) + return 0; + + /* Else find index of first cert accepted by 'check_issued' */ + ret = 0; + CRYPTO_THREAD_write_lock(ctx->ctx->lock); + idx = X509_OBJECT_idx_by_subject(ctx->ctx->objs, X509_LU_X509, xn); + if (idx != -1) { /* should be true as we've had at least one + * match */ + /* Look through all matching certs for suitable issuer */ + for (i = idx; i < sk_X509_OBJECT_num(ctx->ctx->objs); i++) { + pobj = sk_X509_OBJECT_value(ctx->ctx->objs, i); + /* See if we've run past the matches */ + if (pobj->type != X509_LU_X509) + break; + if (X509_NAME_cmp(xn, X509_get_subject_name(pobj->data.x509))) + break; + if (ctx->check_issued(ctx, x, pobj->data.x509)) { + *issuer = pobj->data.x509; + ret = 1; + /* + * If times check, exit with match, + * otherwise keep looking. Leave last + * match in issuer so we return nearest + * match if no certificate time is OK. + */ + + if (x509_check_cert_time(ctx, *issuer, -1)) + break; + } + } + } + CRYPTO_THREAD_unlock(ctx->ctx->lock); + if (*issuer) + X509_up_ref(*issuer); + return ret; +} + +int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags) +{ + return X509_VERIFY_PARAM_set_flags(ctx->param, flags); +} + +int X509_STORE_set_depth(X509_STORE *ctx, int depth) +{ + X509_VERIFY_PARAM_set_depth(ctx->param, depth); + return 1; +} + +int X509_STORE_set_purpose(X509_STORE *ctx, int purpose) +{ + return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose); +} + +int X509_STORE_set_trust(X509_STORE *ctx, int trust) +{ + return X509_VERIFY_PARAM_set_trust(ctx->param, trust); +} + +int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *param) +{ + return X509_VERIFY_PARAM_set1(ctx->param, param); +} + +X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *ctx) +{ + return ctx->param; +} + +void X509_STORE_set_verify(X509_STORE *ctx, X509_STORE_CTX_verify_fn verify) +{ + ctx->verify = verify; +} + +X509_STORE_CTX_verify_fn X509_STORE_get_verify(X509_STORE *ctx) +{ + return ctx->verify; +} + +void X509_STORE_set_verify_cb(X509_STORE *ctx, + X509_STORE_CTX_verify_cb verify_cb) +{ + ctx->verify_cb = verify_cb; +} + +X509_STORE_CTX_verify_cb X509_STORE_get_verify_cb(X509_STORE *ctx) +{ + return ctx->verify_cb; +} + +void X509_STORE_set_get_issuer(X509_STORE *ctx, + X509_STORE_CTX_get_issuer_fn get_issuer) +{ + ctx->get_issuer = get_issuer; +} + +X509_STORE_CTX_get_issuer_fn X509_STORE_get_get_issuer(X509_STORE *ctx) +{ + return ctx->get_issuer; +} + +void X509_STORE_set_check_issued(X509_STORE *ctx, + X509_STORE_CTX_check_issued_fn check_issued) +{ + ctx->check_issued = check_issued; +} + +X509_STORE_CTX_check_issued_fn X509_STORE_get_check_issued(X509_STORE *ctx) +{ + return ctx->check_issued; +} + +void X509_STORE_set_check_revocation(X509_STORE *ctx, + X509_STORE_CTX_check_revocation_fn check_revocation) +{ + ctx->check_revocation = check_revocation; +} + +X509_STORE_CTX_check_revocation_fn X509_STORE_get_check_revocation(X509_STORE *ctx) +{ + return ctx->check_revocation; +} + +void X509_STORE_set_get_crl(X509_STORE *ctx, + X509_STORE_CTX_get_crl_fn get_crl) +{ + ctx->get_crl = get_crl; +} + +X509_STORE_CTX_get_crl_fn X509_STORE_get_get_crl(X509_STORE *ctx) +{ + return ctx->get_crl; +} + +void X509_STORE_set_check_crl(X509_STORE *ctx, + X509_STORE_CTX_check_crl_fn check_crl) +{ + ctx->check_crl = check_crl; +} + +X509_STORE_CTX_check_crl_fn X509_STORE_get_check_crl(X509_STORE *ctx) +{ + return ctx->check_crl; +} + +void X509_STORE_set_cert_crl(X509_STORE *ctx, + X509_STORE_CTX_cert_crl_fn cert_crl) +{ + ctx->cert_crl = cert_crl; +} + +X509_STORE_CTX_cert_crl_fn X509_STORE_get_cert_crl(X509_STORE *ctx) +{ + return ctx->cert_crl; +} + +void X509_STORE_set_check_policy(X509_STORE *ctx, + X509_STORE_CTX_check_policy_fn check_policy) +{ + ctx->check_policy = check_policy; +} + +X509_STORE_CTX_check_policy_fn X509_STORE_get_check_policy(X509_STORE *ctx) +{ + return ctx->check_policy; +} + +void X509_STORE_set_lookup_certs(X509_STORE *ctx, + X509_STORE_CTX_lookup_certs_fn lookup_certs) +{ + ctx->lookup_certs = lookup_certs; +} + +X509_STORE_CTX_lookup_certs_fn X509_STORE_get_lookup_certs(X509_STORE *ctx) +{ + return ctx->lookup_certs; +} + +void X509_STORE_set_lookup_crls(X509_STORE *ctx, + X509_STORE_CTX_lookup_crls_fn lookup_crls) +{ + ctx->lookup_crls = lookup_crls; +} + +X509_STORE_CTX_lookup_crls_fn X509_STORE_get_lookup_crls(X509_STORE *ctx) +{ + return ctx->lookup_crls; +} + +void X509_STORE_set_cleanup(X509_STORE *ctx, + X509_STORE_CTX_cleanup_fn ctx_cleanup) +{ + ctx->cleanup = ctx_cleanup; +} + +X509_STORE_CTX_cleanup_fn X509_STORE_get_cleanup(X509_STORE *ctx) +{ + return ctx->cleanup; +} + +int X509_STORE_set_ex_data(X509_STORE *ctx, int idx, void *data) +{ + return CRYPTO_set_ex_data(&ctx->ex_data, idx, data); +} + +void *X509_STORE_get_ex_data(X509_STORE *ctx, int idx) +{ + return CRYPTO_get_ex_data(&ctx->ex_data, idx); +} + +X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx) +{ + return ctx->ctx; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_meth.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_meth.c new file mode 100644 index 000000000..9dc587a09 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_meth.c @@ -0,0 +1,166 @@ +/* + * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include + +#include "internal/cryptlib.h" +#include +#include +#include +#include "x509_lcl.h" + +X509_LOOKUP_METHOD *X509_LOOKUP_meth_new(const char *name) +{ + X509_LOOKUP_METHOD *method = OPENSSL_zalloc(sizeof(X509_LOOKUP_METHOD)); + + if (method != NULL) { + method->name = OPENSSL_strdup(name); + if (method->name == NULL) { + X509err(X509_F_X509_LOOKUP_METH_NEW, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + return method; + +err: + OPENSSL_free(method); + return NULL; +} + +void X509_LOOKUP_meth_free(X509_LOOKUP_METHOD *method) +{ + if (method != NULL) + OPENSSL_free(method->name); + OPENSSL_free(method); +} + +int X509_LOOKUP_meth_set_new_item(X509_LOOKUP_METHOD *method, + int (*new_item) (X509_LOOKUP *ctx)) +{ + method->new_item = new_item; + return 1; +} + +int (*X509_LOOKUP_meth_get_new_item(const X509_LOOKUP_METHOD* method)) + (X509_LOOKUP *ctx) +{ + return method->new_item; +} + +int X509_LOOKUP_meth_set_free( + X509_LOOKUP_METHOD *method, + void (*free_fn) (X509_LOOKUP *ctx)) +{ + method->free = free_fn; + return 1; +} + +void (*X509_LOOKUP_meth_get_free(const X509_LOOKUP_METHOD* method)) + (X509_LOOKUP *ctx) +{ + return method->free; +} + +int X509_LOOKUP_meth_set_init(X509_LOOKUP_METHOD *method, + int (*init) (X509_LOOKUP *ctx)) +{ + method->init = init; + return 1; +} + +int (*X509_LOOKUP_meth_get_init(const X509_LOOKUP_METHOD* method)) + (X509_LOOKUP *ctx) +{ + return method->init; +} + +int X509_LOOKUP_meth_set_shutdown( + X509_LOOKUP_METHOD *method, + int (*shutdown) (X509_LOOKUP *ctx)) +{ + method->shutdown = shutdown; + return 1; +} + +int (*X509_LOOKUP_meth_get_shutdown(const X509_LOOKUP_METHOD* method)) + (X509_LOOKUP *ctx) +{ + return method->shutdown; +} + +int X509_LOOKUP_meth_set_ctrl( + X509_LOOKUP_METHOD *method, + X509_LOOKUP_ctrl_fn ctrl) +{ + method->ctrl = ctrl; + return 1; +} + +X509_LOOKUP_ctrl_fn X509_LOOKUP_meth_get_ctrl(const X509_LOOKUP_METHOD *method) +{ + return method->ctrl; +} + +int X509_LOOKUP_meth_set_get_by_subject(X509_LOOKUP_METHOD *method, + X509_LOOKUP_get_by_subject_fn get_by_subject) +{ + method->get_by_subject = get_by_subject; + return 1; +} + +X509_LOOKUP_get_by_subject_fn X509_LOOKUP_meth_get_get_by_subject( + const X509_LOOKUP_METHOD *method) +{ + return method->get_by_subject; +} + + +int X509_LOOKUP_meth_set_get_by_issuer_serial(X509_LOOKUP_METHOD *method, + X509_LOOKUP_get_by_issuer_serial_fn get_by_issuer_serial) +{ + method->get_by_issuer_serial = get_by_issuer_serial; + return 1; +} + +X509_LOOKUP_get_by_issuer_serial_fn + X509_LOOKUP_meth_get_get_by_issuer_serial(const X509_LOOKUP_METHOD *method) +{ + return method->get_by_issuer_serial; +} + + +int X509_LOOKUP_meth_set_get_by_fingerprint(X509_LOOKUP_METHOD *method, + X509_LOOKUP_get_by_fingerprint_fn get_by_fingerprint) +{ + method->get_by_fingerprint = get_by_fingerprint; + return 1; +} + +X509_LOOKUP_get_by_fingerprint_fn X509_LOOKUP_meth_get_get_by_fingerprint( + const X509_LOOKUP_METHOD *method) +{ + return method->get_by_fingerprint; +} + +int X509_LOOKUP_meth_set_get_by_alias(X509_LOOKUP_METHOD *method, + X509_LOOKUP_get_by_alias_fn get_by_alias) +{ + method->get_by_alias = get_by_alias; + return 1; +} + +X509_LOOKUP_get_by_alias_fn X509_LOOKUP_meth_get_get_by_alias( + const X509_LOOKUP_METHOD *method) +{ + return method->get_by_alias; +} + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_obj.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_obj.c new file mode 100644 index 000000000..85c39415c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_obj.c @@ -0,0 +1,181 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include "internal/x509_int.h" + +/* + * Limit to ensure we don't overflow: much greater than + * anything encountered in practice. + */ + +#define NAME_ONELINE_MAX (1024 * 1024) + +char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len) +{ + const X509_NAME_ENTRY *ne; + int i; + int n, lold, l, l1, l2, num, j, type; + const char *s; + char *p; + unsigned char *q; + BUF_MEM *b = NULL; + static const char hex[17] = "0123456789ABCDEF"; + int gs_doit[4]; + char tmp_buf[80]; +#ifdef CHARSET_EBCDIC + unsigned char ebcdic_buf[1024]; +#endif + + if (buf == NULL) { + if ((b = BUF_MEM_new()) == NULL) + goto err; + if (!BUF_MEM_grow(b, 200)) + goto err; + b->data[0] = '\0'; + len = 200; + } else if (len == 0) { + return NULL; + } + if (a == NULL) { + if (b) { + buf = b->data; + OPENSSL_free(b); + } + strncpy(buf, "NO X509_NAME", len); + buf[len - 1] = '\0'; + return buf; + } + + len--; /* space for '\0' */ + l = 0; + for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) { + ne = sk_X509_NAME_ENTRY_value(a->entries, i); + n = OBJ_obj2nid(ne->object); + if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) { + i2t_ASN1_OBJECT(tmp_buf, sizeof(tmp_buf), ne->object); + s = tmp_buf; + } + l1 = strlen(s); + + type = ne->value->type; + num = ne->value->length; + if (num > NAME_ONELINE_MAX) { + X509err(X509_F_X509_NAME_ONELINE, X509_R_NAME_TOO_LONG); + goto end; + } + q = ne->value->data; +#ifdef CHARSET_EBCDIC + if (type == V_ASN1_GENERALSTRING || + type == V_ASN1_VISIBLESTRING || + type == V_ASN1_PRINTABLESTRING || + type == V_ASN1_TELETEXSTRING || + type == V_ASN1_IA5STRING) { + if (num > (int)sizeof(ebcdic_buf)) + num = sizeof(ebcdic_buf); + ascii2ebcdic(ebcdic_buf, q, num); + q = ebcdic_buf; + } +#endif + + if ((type == V_ASN1_GENERALSTRING) && ((num % 4) == 0)) { + gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 0; + for (j = 0; j < num; j++) + if (q[j] != 0) + gs_doit[j & 3] = 1; + + if (gs_doit[0] | gs_doit[1] | gs_doit[2]) + gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 1; + else { + gs_doit[0] = gs_doit[1] = gs_doit[2] = 0; + gs_doit[3] = 1; + } + } else + gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 1; + + for (l2 = j = 0; j < num; j++) { + if (!gs_doit[j & 3]) + continue; + l2++; +#ifndef CHARSET_EBCDIC + if ((q[j] < ' ') || (q[j] > '~')) + l2 += 3; +#else + if ((os_toascii[q[j]] < os_toascii[' ']) || + (os_toascii[q[j]] > os_toascii['~'])) + l2 += 3; +#endif + } + + lold = l; + l += 1 + l1 + 1 + l2; + if (l > NAME_ONELINE_MAX) { + X509err(X509_F_X509_NAME_ONELINE, X509_R_NAME_TOO_LONG); + goto end; + } + if (b != NULL) { + if (!BUF_MEM_grow(b, l + 1)) + goto err; + p = &(b->data[lold]); + } else if (l > len) { + break; + } else + p = &(buf[lold]); + *(p++) = '/'; + memcpy(p, s, (unsigned int)l1); + p += l1; + *(p++) = '='; + +#ifndef CHARSET_EBCDIC /* q was assigned above already. */ + q = ne->value->data; +#endif + + for (j = 0; j < num; j++) { + if (!gs_doit[j & 3]) + continue; +#ifndef CHARSET_EBCDIC + n = q[j]; + if ((n < ' ') || (n > '~')) { + *(p++) = '\\'; + *(p++) = 'x'; + *(p++) = hex[(n >> 4) & 0x0f]; + *(p++) = hex[n & 0x0f]; + } else + *(p++) = n; +#else + n = os_toascii[q[j]]; + if ((n < os_toascii[' ']) || (n > os_toascii['~'])) { + *(p++) = '\\'; + *(p++) = 'x'; + *(p++) = hex[(n >> 4) & 0x0f]; + *(p++) = hex[n & 0x0f]; + } else + *(p++) = q[j]; +#endif + } + *p = '\0'; + } + if (b != NULL) { + p = b->data; + OPENSSL_free(b); + } else + p = buf; + if (i == 0) + *p = '\0'; + return p; + err: + X509err(X509_F_X509_NAME_ONELINE, ERR_R_MALLOC_FAILURE); + end: + BUF_MEM_free(b); + return NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_r2x.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_r2x.c new file mode 100644 index 000000000..3d72787d3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_r2x.c @@ -0,0 +1,67 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "internal/x509_int.h" +#include +#include + +X509 *X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey) +{ + X509 *ret = NULL; + X509_CINF *xi = NULL; + X509_NAME *xn; + EVP_PKEY *pubkey = NULL; + + if ((ret = X509_new()) == NULL) { + X509err(X509_F_X509_REQ_TO_X509, ERR_R_MALLOC_FAILURE); + return NULL; + } + + /* duplicate the request */ + xi = &ret->cert_info; + + if (sk_X509_ATTRIBUTE_num(r->req_info.attributes) != 0) { + if ((xi->version = ASN1_INTEGER_new()) == NULL) + goto err; + if (!ASN1_INTEGER_set(xi->version, 2)) + goto err; +/*- xi->extensions=ri->attributes; <- bad, should not ever be done + ri->attributes=NULL; */ + } + + xn = X509_REQ_get_subject_name(r); + if (X509_set_subject_name(ret, xn) == 0) + goto err; + if (X509_set_issuer_name(ret, xn) == 0) + goto err; + + if (X509_gmtime_adj(xi->validity.notBefore, 0) == NULL) + goto err; + if (X509_gmtime_adj(xi->validity.notAfter, (long)60 * 60 * 24 * days) == + NULL) + goto err; + + pubkey = X509_REQ_get0_pubkey(r); + if (pubkey == NULL || !X509_set_pubkey(ret, pubkey)) + goto err; + + if (!X509_sign(ret, pkey, EVP_md5())) + goto err; + return ret; + + err: + X509_free(ret); + return NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_req.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_req.c new file mode 100644 index 000000000..0bdbb81db --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_req.c @@ -0,0 +1,298 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include "internal/x509_int.h" +#include +#include +#include + +X509_REQ *X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md) +{ + X509_REQ *ret; + X509_REQ_INFO *ri; + int i; + EVP_PKEY *pktmp; + + ret = X509_REQ_new(); + if (ret == NULL) { + X509err(X509_F_X509_TO_X509_REQ, ERR_R_MALLOC_FAILURE); + goto err; + } + + ri = &ret->req_info; + + ri->version->length = 1; + ri->version->data = OPENSSL_malloc(1); + if (ri->version->data == NULL) + goto err; + ri->version->data[0] = 0; /* version == 0 */ + + if (!X509_REQ_set_subject_name(ret, X509_get_subject_name(x))) + goto err; + + pktmp = X509_get0_pubkey(x); + if (pktmp == NULL) + goto err; + i = X509_REQ_set_pubkey(ret, pktmp); + if (!i) + goto err; + + if (pkey != NULL) { + if (!X509_REQ_sign(ret, pkey, md)) + goto err; + } + return ret; + err: + X509_REQ_free(ret); + return NULL; +} + +EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *req) +{ + if (req == NULL) + return NULL; + return X509_PUBKEY_get(req->req_info.pubkey); +} + +EVP_PKEY *X509_REQ_get0_pubkey(X509_REQ *req) +{ + if (req == NULL) + return NULL; + return X509_PUBKEY_get0(req->req_info.pubkey); +} + +X509_PUBKEY *X509_REQ_get_X509_PUBKEY(X509_REQ *req) +{ + return req->req_info.pubkey; +} + +int X509_REQ_check_private_key(X509_REQ *x, EVP_PKEY *k) +{ + EVP_PKEY *xk = NULL; + int ok = 0; + + xk = X509_REQ_get_pubkey(x); + switch (EVP_PKEY_cmp(xk, k)) { + case 1: + ok = 1; + break; + case 0: + X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY, + X509_R_KEY_VALUES_MISMATCH); + break; + case -1: + X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY, X509_R_KEY_TYPE_MISMATCH); + break; + case -2: +#ifndef OPENSSL_NO_EC + if (EVP_PKEY_id(k) == EVP_PKEY_EC) { + X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY, ERR_R_EC_LIB); + break; + } +#endif +#ifndef OPENSSL_NO_DH + if (EVP_PKEY_id(k) == EVP_PKEY_DH) { + /* No idea */ + X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY, + X509_R_CANT_CHECK_DH_KEY); + break; + } +#endif + X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY, X509_R_UNKNOWN_KEY_TYPE); + } + + EVP_PKEY_free(xk); + return ok; +} + +/* + * It seems several organisations had the same idea of including a list of + * extensions in a certificate request. There are at least two OIDs that are + * used and there may be more: so the list is configurable. + */ + +static int ext_nid_list[] = { NID_ext_req, NID_ms_ext_req, NID_undef }; + +static int *ext_nids = ext_nid_list; + +int X509_REQ_extension_nid(int req_nid) +{ + int i, nid; + for (i = 0;; i++) { + nid = ext_nids[i]; + if (nid == NID_undef) + return 0; + else if (req_nid == nid) + return 1; + } +} + +int *X509_REQ_get_extension_nids(void) +{ + return ext_nids; +} + +void X509_REQ_set_extension_nids(int *nids) +{ + ext_nids = nids; +} + +STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req) +{ + X509_ATTRIBUTE *attr; + ASN1_TYPE *ext = NULL; + int idx, *pnid; + const unsigned char *p; + + if ((req == NULL) || !ext_nids) + return NULL; + for (pnid = ext_nids; *pnid != NID_undef; pnid++) { + idx = X509_REQ_get_attr_by_NID(req, *pnid, -1); + if (idx == -1) + continue; + attr = X509_REQ_get_attr(req, idx); + ext = X509_ATTRIBUTE_get0_type(attr, 0); + break; + } + if (!ext || (ext->type != V_ASN1_SEQUENCE)) + return NULL; + p = ext->value.sequence->data; + return (STACK_OF(X509_EXTENSION) *) + ASN1_item_d2i(NULL, &p, ext->value.sequence->length, + ASN1_ITEM_rptr(X509_EXTENSIONS)); +} + +/* + * Add a STACK_OF extensions to a certificate request: allow alternative OIDs + * in case we want to create a non standard one. + */ + +int X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts, + int nid) +{ + int extlen; + int rv = 0; + unsigned char *ext = NULL; + /* Generate encoding of extensions */ + extlen = ASN1_item_i2d((ASN1_VALUE *)exts, &ext, + ASN1_ITEM_rptr(X509_EXTENSIONS)); + if (extlen <= 0) + return 0; + rv = X509_REQ_add1_attr_by_NID(req, nid, V_ASN1_SEQUENCE, ext, extlen); + OPENSSL_free(ext); + return rv; +} + +/* This is the normal usage: use the "official" OID */ +int X509_REQ_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts) +{ + return X509_REQ_add_extensions_nid(req, exts, NID_ext_req); +} + +/* Request attribute functions */ + +int X509_REQ_get_attr_count(const X509_REQ *req) +{ + return X509at_get_attr_count(req->req_info.attributes); +} + +int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, int lastpos) +{ + return X509at_get_attr_by_NID(req->req_info.attributes, nid, lastpos); +} + +int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, const ASN1_OBJECT *obj, + int lastpos) +{ + return X509at_get_attr_by_OBJ(req->req_info.attributes, obj, lastpos); +} + +X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc) +{ + return X509at_get_attr(req->req_info.attributes, loc); +} + +X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc) +{ + return X509at_delete_attr(req->req_info.attributes, loc); +} + +int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr) +{ + if (X509at_add1_attr(&req->req_info.attributes, attr)) + return 1; + return 0; +} + +int X509_REQ_add1_attr_by_OBJ(X509_REQ *req, + const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, int len) +{ + if (X509at_add1_attr_by_OBJ(&req->req_info.attributes, obj, + type, bytes, len)) + return 1; + return 0; +} + +int X509_REQ_add1_attr_by_NID(X509_REQ *req, + int nid, int type, + const unsigned char *bytes, int len) +{ + if (X509at_add1_attr_by_NID(&req->req_info.attributes, nid, + type, bytes, len)) + return 1; + return 0; +} + +int X509_REQ_add1_attr_by_txt(X509_REQ *req, + const char *attrname, int type, + const unsigned char *bytes, int len) +{ + if (X509at_add1_attr_by_txt(&req->req_info.attributes, attrname, + type, bytes, len)) + return 1; + return 0; +} + +long X509_REQ_get_version(const X509_REQ *req) +{ + return ASN1_INTEGER_get(req->req_info.version); +} + +X509_NAME *X509_REQ_get_subject_name(const X509_REQ *req) +{ + return req->req_info.subject; +} + +void X509_REQ_get0_signature(const X509_REQ *req, const ASN1_BIT_STRING **psig, + const X509_ALGOR **palg) +{ + if (psig != NULL) + *psig = req->signature; + if (palg != NULL) + *palg = &req->sig_alg; +} + +int X509_REQ_get_signature_nid(const X509_REQ *req) +{ + return OBJ_obj2nid(req->sig_alg.algorithm); +} + +int i2d_re_X509_REQ_tbs(X509_REQ *req, unsigned char **pp) +{ + req->req_info.enc.modified = 1; + return i2d_X509_REQ_INFO(&req->req_info, pp); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_set.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_set.c new file mode 100644 index 000000000..3ab6bf351 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_set.c @@ -0,0 +1,237 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include "internal/refcount.h" +#include +#include +#include +#include +#include +#include "internal/asn1_int.h" +#include "internal/x509_int.h" +#include "x509_lcl.h" + +int X509_set_version(X509 *x, long version) +{ + if (x == NULL) + return 0; + if (version == 0) { + ASN1_INTEGER_free(x->cert_info.version); + x->cert_info.version = NULL; + return 1; + } + if (x->cert_info.version == NULL) { + if ((x->cert_info.version = ASN1_INTEGER_new()) == NULL) + return 0; + } + return ASN1_INTEGER_set(x->cert_info.version, version); +} + +int X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial) +{ + ASN1_INTEGER *in; + + if (x == NULL) + return 0; + in = &x->cert_info.serialNumber; + if (in != serial) + return ASN1_STRING_copy(in, serial); + return 1; +} + +int X509_set_issuer_name(X509 *x, X509_NAME *name) +{ + if (x == NULL) + return 0; + return X509_NAME_set(&x->cert_info.issuer, name); +} + +int X509_set_subject_name(X509 *x, X509_NAME *name) +{ + if (x == NULL) + return 0; + return X509_NAME_set(&x->cert_info.subject, name); +} + +int x509_set1_time(ASN1_TIME **ptm, const ASN1_TIME *tm) +{ + ASN1_TIME *in; + in = *ptm; + if (in != tm) { + in = ASN1_STRING_dup(tm); + if (in != NULL) { + ASN1_TIME_free(*ptm); + *ptm = in; + } + } + return (in != NULL); +} + +int X509_set1_notBefore(X509 *x, const ASN1_TIME *tm) +{ + if (x == NULL) + return 0; + return x509_set1_time(&x->cert_info.validity.notBefore, tm); +} + +int X509_set1_notAfter(X509 *x, const ASN1_TIME *tm) +{ + if (x == NULL) + return 0; + return x509_set1_time(&x->cert_info.validity.notAfter, tm); +} + +int X509_set_pubkey(X509 *x, EVP_PKEY *pkey) +{ + if (x == NULL) + return 0; + return X509_PUBKEY_set(&(x->cert_info.key), pkey); +} + +int X509_up_ref(X509 *x) +{ + int i; + + if (CRYPTO_UP_REF(&x->references, &i, x->lock) <= 0) + return 0; + + REF_PRINT_COUNT("X509", x); + REF_ASSERT_ISNT(i < 2); + return ((i > 1) ? 1 : 0); +} + +long X509_get_version(const X509 *x) +{ + return ASN1_INTEGER_get(x->cert_info.version); +} + +const ASN1_TIME *X509_get0_notBefore(const X509 *x) +{ + return x->cert_info.validity.notBefore; +} + +const ASN1_TIME *X509_get0_notAfter(const X509 *x) +{ + return x->cert_info.validity.notAfter; +} + +ASN1_TIME *X509_getm_notBefore(const X509 *x) +{ + return x->cert_info.validity.notBefore; +} + +ASN1_TIME *X509_getm_notAfter(const X509 *x) +{ + return x->cert_info.validity.notAfter; +} + +int X509_get_signature_type(const X509 *x) +{ + return EVP_PKEY_type(OBJ_obj2nid(x->sig_alg.algorithm)); +} + +X509_PUBKEY *X509_get_X509_PUBKEY(const X509 *x) +{ + return x->cert_info.key; +} + +const STACK_OF(X509_EXTENSION) *X509_get0_extensions(const X509 *x) +{ + return x->cert_info.extensions; +} + +void X509_get0_uids(const X509 *x, const ASN1_BIT_STRING **piuid, + const ASN1_BIT_STRING **psuid) +{ + if (piuid != NULL) + *piuid = x->cert_info.issuerUID; + if (psuid != NULL) + *psuid = x->cert_info.subjectUID; +} + +const X509_ALGOR *X509_get0_tbs_sigalg(const X509 *x) +{ + return &x->cert_info.signature; +} + +int X509_SIG_INFO_get(const X509_SIG_INFO *siginf, int *mdnid, int *pknid, + int *secbits, uint32_t *flags) +{ + if (mdnid != NULL) + *mdnid = siginf->mdnid; + if (pknid != NULL) + *pknid = siginf->pknid; + if (secbits != NULL) + *secbits = siginf->secbits; + if (flags != NULL) + *flags = siginf->flags; + return (siginf->flags & X509_SIG_INFO_VALID) != 0; +} + +void X509_SIG_INFO_set(X509_SIG_INFO *siginf, int mdnid, int pknid, + int secbits, uint32_t flags) +{ + siginf->mdnid = mdnid; + siginf->pknid = pknid; + siginf->secbits = secbits; + siginf->flags = flags; +} + +int X509_get_signature_info(X509 *x, int *mdnid, int *pknid, int *secbits, + uint32_t *flags) +{ + X509_check_purpose(x, -1, -1); + return X509_SIG_INFO_get(&x->siginf, mdnid, pknid, secbits, flags); +} + +static void x509_sig_info_init(X509_SIG_INFO *siginf, const X509_ALGOR *alg, + const ASN1_STRING *sig) +{ + int pknid, mdnid; + const EVP_MD *md; + + siginf->mdnid = NID_undef; + siginf->pknid = NID_undef; + siginf->secbits = -1; + siginf->flags = 0; + if (!OBJ_find_sigid_algs(OBJ_obj2nid(alg->algorithm), &mdnid, &pknid) + || pknid == NID_undef) + return; + siginf->pknid = pknid; + if (mdnid == NID_undef) { + /* If we have one, use a custom handler for this algorithm */ + const EVP_PKEY_ASN1_METHOD *ameth = EVP_PKEY_asn1_find(NULL, pknid); + if (ameth == NULL || ameth->siginf_set == NULL + || ameth->siginf_set(siginf, alg, sig) == 0) + return; + siginf->flags |= X509_SIG_INFO_VALID; + return; + } + siginf->flags |= X509_SIG_INFO_VALID; + siginf->mdnid = mdnid; + md = EVP_get_digestbynid(mdnid); + if (md == NULL) + return; + /* Security bits: half number of bits in digest */ + siginf->secbits = EVP_MD_size(md) * 4; + switch (mdnid) { + case NID_sha1: + case NID_sha256: + case NID_sha384: + case NID_sha512: + siginf->flags |= X509_SIG_INFO_TLS; + } +} + +void x509_init_sig_info(X509 *x) +{ + x509_sig_info_init(&x->siginf, &x->sig_alg, &x->signature); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_trs.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_trs.c new file mode 100644 index 000000000..d749af4d5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_trs.c @@ -0,0 +1,299 @@ +/* + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include "internal/x509_int.h" + +static int tr_cmp(const X509_TRUST *const *a, const X509_TRUST *const *b); +static void trtable_free(X509_TRUST *p); + +static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags); +static int trust_1oid(X509_TRUST *trust, X509 *x, int flags); +static int trust_compat(X509_TRUST *trust, X509 *x, int flags); + +static int obj_trust(int id, X509 *x, int flags); +static int (*default_trust) (int id, X509 *x, int flags) = obj_trust; + +/* + * WARNING: the following table should be kept in order of trust and without + * any gaps so we can just subtract the minimum trust value to get an index + * into the table + */ + +static X509_TRUST trstandard[] = { + {X509_TRUST_COMPAT, 0, trust_compat, "compatible", 0, NULL}, + {X509_TRUST_SSL_CLIENT, 0, trust_1oidany, "SSL Client", NID_client_auth, + NULL}, + {X509_TRUST_SSL_SERVER, 0, trust_1oidany, "SSL Server", NID_server_auth, + NULL}, + {X509_TRUST_EMAIL, 0, trust_1oidany, "S/MIME email", NID_email_protect, + NULL}, + {X509_TRUST_OBJECT_SIGN, 0, trust_1oidany, "Object Signer", NID_code_sign, + NULL}, + {X509_TRUST_OCSP_SIGN, 0, trust_1oid, "OCSP responder", NID_OCSP_sign, + NULL}, + {X509_TRUST_OCSP_REQUEST, 0, trust_1oid, "OCSP request", NID_ad_OCSP, + NULL}, + {X509_TRUST_TSA, 0, trust_1oidany, "TSA server", NID_time_stamp, NULL} +}; + +#define X509_TRUST_COUNT OSSL_NELEM(trstandard) + +static STACK_OF(X509_TRUST) *trtable = NULL; + +static int tr_cmp(const X509_TRUST *const *a, const X509_TRUST *const *b) +{ + return (*a)->trust - (*b)->trust; +} + +int (*X509_TRUST_set_default(int (*trust) (int, X509 *, int))) (int, X509 *, + int) { + int (*oldtrust) (int, X509 *, int); + oldtrust = default_trust; + default_trust = trust; + return oldtrust; +} + +int X509_check_trust(X509 *x, int id, int flags) +{ + X509_TRUST *pt; + int idx; + + /* We get this as a default value */ + if (id == X509_TRUST_DEFAULT) + return obj_trust(NID_anyExtendedKeyUsage, x, + flags | X509_TRUST_DO_SS_COMPAT); + idx = X509_TRUST_get_by_id(id); + if (idx == -1) + return default_trust(id, x, flags); + pt = X509_TRUST_get0(idx); + return pt->check_trust(pt, x, flags); +} + +int X509_TRUST_get_count(void) +{ + if (!trtable) + return X509_TRUST_COUNT; + return sk_X509_TRUST_num(trtable) + X509_TRUST_COUNT; +} + +X509_TRUST *X509_TRUST_get0(int idx) +{ + if (idx < 0) + return NULL; + if (idx < (int)X509_TRUST_COUNT) + return trstandard + idx; + return sk_X509_TRUST_value(trtable, idx - X509_TRUST_COUNT); +} + +int X509_TRUST_get_by_id(int id) +{ + X509_TRUST tmp; + int idx; + + if ((id >= X509_TRUST_MIN) && (id <= X509_TRUST_MAX)) + return id - X509_TRUST_MIN; + if (trtable == NULL) + return -1; + tmp.trust = id; + idx = sk_X509_TRUST_find(trtable, &tmp); + if (idx < 0) + return -1; + return idx + X509_TRUST_COUNT; +} + +int X509_TRUST_set(int *t, int trust) +{ + if (X509_TRUST_get_by_id(trust) == -1) { + X509err(X509_F_X509_TRUST_SET, X509_R_INVALID_TRUST); + return 0; + } + *t = trust; + return 1; +} + +int X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int), + const char *name, int arg1, void *arg2) +{ + int idx; + X509_TRUST *trtmp; + /* + * This is set according to what we change: application can't set it + */ + flags &= ~X509_TRUST_DYNAMIC; + /* This will always be set for application modified trust entries */ + flags |= X509_TRUST_DYNAMIC_NAME; + /* Get existing entry if any */ + idx = X509_TRUST_get_by_id(id); + /* Need a new entry */ + if (idx == -1) { + if ((trtmp = OPENSSL_malloc(sizeof(*trtmp))) == NULL) { + X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE); + return 0; + } + trtmp->flags = X509_TRUST_DYNAMIC; + } else + trtmp = X509_TRUST_get0(idx); + + /* OPENSSL_free existing name if dynamic */ + if (trtmp->flags & X509_TRUST_DYNAMIC_NAME) + OPENSSL_free(trtmp->name); + /* dup supplied name */ + if ((trtmp->name = OPENSSL_strdup(name)) == NULL) { + X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE); + goto err; + } + /* Keep the dynamic flag of existing entry */ + trtmp->flags &= X509_TRUST_DYNAMIC; + /* Set all other flags */ + trtmp->flags |= flags; + + trtmp->trust = id; + trtmp->check_trust = ck; + trtmp->arg1 = arg1; + trtmp->arg2 = arg2; + + /* If its a new entry manage the dynamic table */ + if (idx == -1) { + if (trtable == NULL + && (trtable = sk_X509_TRUST_new(tr_cmp)) == NULL) { + X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE); + goto err;; + } + if (!sk_X509_TRUST_push(trtable, trtmp)) { + X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE); + goto err; + } + } + return 1; + err: + if (idx == -1) { + OPENSSL_free(trtmp->name); + OPENSSL_free(trtmp); + } + return 0; +} + +static void trtable_free(X509_TRUST *p) +{ + if (!p) + return; + if (p->flags & X509_TRUST_DYNAMIC) { + if (p->flags & X509_TRUST_DYNAMIC_NAME) + OPENSSL_free(p->name); + OPENSSL_free(p); + } +} + +void X509_TRUST_cleanup(void) +{ + sk_X509_TRUST_pop_free(trtable, trtable_free); + trtable = NULL; +} + +int X509_TRUST_get_flags(const X509_TRUST *xp) +{ + return xp->flags; +} + +char *X509_TRUST_get0_name(const X509_TRUST *xp) +{ + return xp->name; +} + +int X509_TRUST_get_trust(const X509_TRUST *xp) +{ + return xp->trust; +} + +static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags) +{ + /* + * Declare the chain verified if the desired trust OID is not rejected in + * any auxiliary trust info for this certificate, and the OID is either + * expressly trusted, or else either "anyEKU" is trusted, or the + * certificate is self-signed. + */ + flags |= X509_TRUST_DO_SS_COMPAT | X509_TRUST_OK_ANY_EKU; + return obj_trust(trust->arg1, x, flags); +} + +static int trust_1oid(X509_TRUST *trust, X509 *x, int flags) +{ + /* + * Declare the chain verified only if the desired trust OID is not + * rejected and is expressly trusted. Neither "anyEKU" nor "compat" + * trust in self-signed certificates apply. + */ + flags &= ~(X509_TRUST_DO_SS_COMPAT | X509_TRUST_OK_ANY_EKU); + return obj_trust(trust->arg1, x, flags); +} + +static int trust_compat(X509_TRUST *trust, X509 *x, int flags) +{ + /* Call for side-effect of computing hash and caching extensions */ + X509_check_purpose(x, -1, 0); + if ((flags & X509_TRUST_NO_SS_COMPAT) == 0 && x->ex_flags & EXFLAG_SS) + return X509_TRUST_TRUSTED; + else + return X509_TRUST_UNTRUSTED; +} + +static int obj_trust(int id, X509 *x, int flags) +{ + X509_CERT_AUX *ax = x->aux; + int i; + + if (ax && ax->reject) { + for (i = 0; i < sk_ASN1_OBJECT_num(ax->reject); i++) { + ASN1_OBJECT *obj = sk_ASN1_OBJECT_value(ax->reject, i); + int nid = OBJ_obj2nid(obj); + + if (nid == id || (nid == NID_anyExtendedKeyUsage && + (flags & X509_TRUST_OK_ANY_EKU))) + return X509_TRUST_REJECTED; + } + } + + if (ax && ax->trust) { + for (i = 0; i < sk_ASN1_OBJECT_num(ax->trust); i++) { + ASN1_OBJECT *obj = sk_ASN1_OBJECT_value(ax->trust, i); + int nid = OBJ_obj2nid(obj); + + if (nid == id || (nid == NID_anyExtendedKeyUsage && + (flags & X509_TRUST_OK_ANY_EKU))) + return X509_TRUST_TRUSTED; + } + /* + * Reject when explicit trust EKU are set and none match. + * + * Returning untrusted is enough for for full chains that end in + * self-signed roots, because when explicit trust is specified it + * suppresses the default blanket trust of self-signed objects. + * + * But for partial chains, this is not enough, because absent a similar + * trust-self-signed policy, non matching EKUs are indistinguishable + * from lack of EKU constraints. + * + * Therefore, failure to match any trusted purpose must trigger an + * explicit reject. + */ + return X509_TRUST_REJECTED; + } + + if ((flags & X509_TRUST_DO_SS_COMPAT) == 0) + return X509_TRUST_UNTRUSTED; + + /* + * Not rejected, and there is no list of accepted uses, try compat. + */ + return trust_compat(NULL, x, flags); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_txt.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_txt.c new file mode 100644 index 000000000..4755b39eb --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_txt.c @@ -0,0 +1,182 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include + +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include + +const char *X509_verify_cert_error_string(long n) +{ + switch ((int)n) { + case X509_V_OK: + return "ok"; + case X509_V_ERR_UNSPECIFIED: + return "unspecified certificate verification error"; + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: + return "unable to get issuer certificate"; + case X509_V_ERR_UNABLE_TO_GET_CRL: + return "unable to get certificate CRL"; + case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: + return "unable to decrypt certificate's signature"; + case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: + return "unable to decrypt CRL's signature"; + case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: + return "unable to decode issuer public key"; + case X509_V_ERR_CERT_SIGNATURE_FAILURE: + return "certificate signature failure"; + case X509_V_ERR_CRL_SIGNATURE_FAILURE: + return "CRL signature failure"; + case X509_V_ERR_CERT_NOT_YET_VALID: + return "certificate is not yet valid"; + case X509_V_ERR_CERT_HAS_EXPIRED: + return "certificate has expired"; + case X509_V_ERR_CRL_NOT_YET_VALID: + return "CRL is not yet valid"; + case X509_V_ERR_CRL_HAS_EXPIRED: + return "CRL has expired"; + case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: + return "format error in certificate's notBefore field"; + case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: + return "format error in certificate's notAfter field"; + case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: + return "format error in CRL's lastUpdate field"; + case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: + return "format error in CRL's nextUpdate field"; + case X509_V_ERR_OUT_OF_MEM: + return "out of memory"; + case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: + return "self signed certificate"; + case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: + return "self signed certificate in certificate chain"; + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: + return "unable to get local issuer certificate"; + case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: + return "unable to verify the first certificate"; + case X509_V_ERR_CERT_CHAIN_TOO_LONG: + return "certificate chain too long"; + case X509_V_ERR_CERT_REVOKED: + return "certificate revoked"; + case X509_V_ERR_INVALID_CA: + return "invalid CA certificate"; + case X509_V_ERR_PATH_LENGTH_EXCEEDED: + return "path length constraint exceeded"; + case X509_V_ERR_INVALID_PURPOSE: + return "unsupported certificate purpose"; + case X509_V_ERR_CERT_UNTRUSTED: + return "certificate not trusted"; + case X509_V_ERR_CERT_REJECTED: + return "certificate rejected"; + case X509_V_ERR_SUBJECT_ISSUER_MISMATCH: + return "subject issuer mismatch"; + case X509_V_ERR_AKID_SKID_MISMATCH: + return "authority and subject key identifier mismatch"; + case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: + return "authority and issuer serial number mismatch"; + case X509_V_ERR_KEYUSAGE_NO_CERTSIGN: + return "key usage does not include certificate signing"; + case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER: + return "unable to get CRL issuer certificate"; + case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION: + return "unhandled critical extension"; + case X509_V_ERR_KEYUSAGE_NO_CRL_SIGN: + return "key usage does not include CRL signing"; + case X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION: + return "unhandled critical CRL extension"; + case X509_V_ERR_INVALID_NON_CA: + return "invalid non-CA certificate (has CA markings)"; + case X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED: + return "proxy path length constraint exceeded"; + case X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE: + return "key usage does not include digital signature"; + case X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED: + return + "proxy certificates not allowed, please set the appropriate flag"; + case X509_V_ERR_INVALID_EXTENSION: + return "invalid or inconsistent certificate extension"; + case X509_V_ERR_INVALID_POLICY_EXTENSION: + return "invalid or inconsistent certificate policy extension"; + case X509_V_ERR_NO_EXPLICIT_POLICY: + return "no explicit policy"; + case X509_V_ERR_DIFFERENT_CRL_SCOPE: + return "Different CRL scope"; + case X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE: + return "Unsupported extension feature"; + case X509_V_ERR_UNNESTED_RESOURCE: + return "RFC 3779 resource not subset of parent's resources"; + case X509_V_ERR_PERMITTED_VIOLATION: + return "permitted subtree violation"; + case X509_V_ERR_EXCLUDED_VIOLATION: + return "excluded subtree violation"; + case X509_V_ERR_SUBTREE_MINMAX: + return "name constraints minimum and maximum not supported"; + case X509_V_ERR_APPLICATION_VERIFICATION: + return "application verification failure"; + case X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE: + return "unsupported name constraint type"; + case X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX: + return "unsupported or invalid name constraint syntax"; + case X509_V_ERR_UNSUPPORTED_NAME_SYNTAX: + return "unsupported or invalid name syntax"; + case X509_V_ERR_CRL_PATH_VALIDATION_ERROR: + return "CRL path validation error"; + case X509_V_ERR_PATH_LOOP: + return "Path Loop"; + case X509_V_ERR_SUITE_B_INVALID_VERSION: + return "Suite B: certificate version invalid"; + case X509_V_ERR_SUITE_B_INVALID_ALGORITHM: + return "Suite B: invalid public key algorithm"; + case X509_V_ERR_SUITE_B_INVALID_CURVE: + return "Suite B: invalid ECC curve"; + case X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM: + return "Suite B: invalid signature algorithm"; + case X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED: + return "Suite B: curve not allowed for this LOS"; + case X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256: + return "Suite B: cannot sign P-384 with P-256"; + case X509_V_ERR_HOSTNAME_MISMATCH: + return "Hostname mismatch"; + case X509_V_ERR_EMAIL_MISMATCH: + return "Email address mismatch"; + case X509_V_ERR_IP_ADDRESS_MISMATCH: + return "IP address mismatch"; + case X509_V_ERR_DANE_NO_MATCH: + return "No matching DANE TLSA records"; + case X509_V_ERR_EE_KEY_TOO_SMALL: + return "EE certificate key too weak"; + case X509_V_ERR_CA_KEY_TOO_SMALL: + return "CA certificate key too weak"; + case X509_V_ERR_CA_MD_TOO_WEAK: + return "CA signature digest algorithm too weak"; + case X509_V_ERR_INVALID_CALL: + return "Invalid certificate verification context"; + case X509_V_ERR_STORE_LOOKUP: + return "Issuer certificate lookup error"; + case X509_V_ERR_NO_VALID_SCTS: + return "Certificate Transparency required, but no valid SCTs found"; + case X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION: + return "proxy subject name violation"; + case X509_V_ERR_OCSP_VERIFY_NEEDED: + return "OCSP verification needed"; + case X509_V_ERR_OCSP_VERIFY_FAILED: + return "OCSP verification failed"; + case X509_V_ERR_OCSP_CERT_UNKNOWN: + return "OCSP unknown cert"; + + default: + /* Printing an error number into a static buffer is not thread-safe */ + return "unknown certificate verification error"; + } +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_v3.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_v3.c new file mode 100644 index 000000000..75ae767d6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_v3.c @@ -0,0 +1,235 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include +#include "x509_lcl.h" + +int X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x) +{ + if (x == NULL) + return 0; + return sk_X509_EXTENSION_num(x); +} + +int X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x, int nid, + int lastpos) +{ + ASN1_OBJECT *obj; + + obj = OBJ_nid2obj(nid); + if (obj == NULL) + return -2; + return X509v3_get_ext_by_OBJ(x, obj, lastpos); +} + +int X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *sk, + const ASN1_OBJECT *obj, int lastpos) +{ + int n; + X509_EXTENSION *ex; + + if (sk == NULL) + return -1; + lastpos++; + if (lastpos < 0) + lastpos = 0; + n = sk_X509_EXTENSION_num(sk); + for (; lastpos < n; lastpos++) { + ex = sk_X509_EXTENSION_value(sk, lastpos); + if (OBJ_cmp(ex->object, obj) == 0) + return lastpos; + } + return -1; +} + +int X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *sk, int crit, + int lastpos) +{ + int n; + X509_EXTENSION *ex; + + if (sk == NULL) + return -1; + lastpos++; + if (lastpos < 0) + lastpos = 0; + n = sk_X509_EXTENSION_num(sk); + for (; lastpos < n; lastpos++) { + ex = sk_X509_EXTENSION_value(sk, lastpos); + if (((ex->critical > 0) && crit) || ((ex->critical <= 0) && !crit)) + return lastpos; + } + return -1; +} + +X509_EXTENSION *X509v3_get_ext(const STACK_OF(X509_EXTENSION) *x, int loc) +{ + if (x == NULL || sk_X509_EXTENSION_num(x) <= loc || loc < 0) + return NULL; + else + return sk_X509_EXTENSION_value(x, loc); +} + +X509_EXTENSION *X509v3_delete_ext(STACK_OF(X509_EXTENSION) *x, int loc) +{ + X509_EXTENSION *ret; + + if (x == NULL || sk_X509_EXTENSION_num(x) <= loc || loc < 0) + return NULL; + ret = sk_X509_EXTENSION_delete(x, loc); + return ret; +} + +STACK_OF(X509_EXTENSION) *X509v3_add_ext(STACK_OF(X509_EXTENSION) **x, + X509_EXTENSION *ex, int loc) +{ + X509_EXTENSION *new_ex = NULL; + int n; + STACK_OF(X509_EXTENSION) *sk = NULL; + + if (x == NULL) { + X509err(X509_F_X509V3_ADD_EXT, ERR_R_PASSED_NULL_PARAMETER); + goto err2; + } + + if (*x == NULL) { + if ((sk = sk_X509_EXTENSION_new_null()) == NULL) + goto err; + } else + sk = *x; + + n = sk_X509_EXTENSION_num(sk); + if (loc > n) + loc = n; + else if (loc < 0) + loc = n; + + if ((new_ex = X509_EXTENSION_dup(ex)) == NULL) + goto err2; + if (!sk_X509_EXTENSION_insert(sk, new_ex, loc)) + goto err; + if (*x == NULL) + *x = sk; + return sk; + err: + X509err(X509_F_X509V3_ADD_EXT, ERR_R_MALLOC_FAILURE); + err2: + X509_EXTENSION_free(new_ex); + if (x != NULL && *x == NULL) + sk_X509_EXTENSION_free(sk); + return NULL; +} + +X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, int nid, + int crit, + ASN1_OCTET_STRING *data) +{ + ASN1_OBJECT *obj; + X509_EXTENSION *ret; + + obj = OBJ_nid2obj(nid); + if (obj == NULL) { + X509err(X509_F_X509_EXTENSION_CREATE_BY_NID, X509_R_UNKNOWN_NID); + return NULL; + } + ret = X509_EXTENSION_create_by_OBJ(ex, obj, crit, data); + if (ret == NULL) + ASN1_OBJECT_free(obj); + return ret; +} + +X509_EXTENSION *X509_EXTENSION_create_by_OBJ(X509_EXTENSION **ex, + const ASN1_OBJECT *obj, int crit, + ASN1_OCTET_STRING *data) +{ + X509_EXTENSION *ret; + + if ((ex == NULL) || (*ex == NULL)) { + if ((ret = X509_EXTENSION_new()) == NULL) { + X509err(X509_F_X509_EXTENSION_CREATE_BY_OBJ, + ERR_R_MALLOC_FAILURE); + return NULL; + } + } else + ret = *ex; + + if (!X509_EXTENSION_set_object(ret, obj)) + goto err; + if (!X509_EXTENSION_set_critical(ret, crit)) + goto err; + if (!X509_EXTENSION_set_data(ret, data)) + goto err; + + if ((ex != NULL) && (*ex == NULL)) + *ex = ret; + return ret; + err: + if ((ex == NULL) || (ret != *ex)) + X509_EXTENSION_free(ret); + return NULL; +} + +int X509_EXTENSION_set_object(X509_EXTENSION *ex, const ASN1_OBJECT *obj) +{ + if ((ex == NULL) || (obj == NULL)) + return 0; + ASN1_OBJECT_free(ex->object); + ex->object = OBJ_dup(obj); + return ex->object != NULL; +} + +int X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit) +{ + if (ex == NULL) + return 0; + ex->critical = (crit) ? 0xFF : -1; + return 1; +} + +int X509_EXTENSION_set_data(X509_EXTENSION *ex, ASN1_OCTET_STRING *data) +{ + int i; + + if (ex == NULL) + return 0; + i = ASN1_OCTET_STRING_set(&ex->value, data->data, data->length); + if (!i) + return 0; + return 1; +} + +ASN1_OBJECT *X509_EXTENSION_get_object(X509_EXTENSION *ex) +{ + if (ex == NULL) + return NULL; + return ex->object; +} + +ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ex) +{ + if (ex == NULL) + return NULL; + return &ex->value; +} + +int X509_EXTENSION_get_critical(const X509_EXTENSION *ex) +{ + if (ex == NULL) + return 0; + if (ex->critical > 0) + return 1; + return 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_vfy.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_vfy.c new file mode 100644 index 000000000..4ced716e3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_vfy.c @@ -0,0 +1,3275 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include + +#include "internal/ctype.h" +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include +#include +#include "internal/dane.h" +#include "internal/x509_int.h" +#include "x509_lcl.h" + +/* CRL score values */ + +/* No unhandled critical extensions */ + +#define CRL_SCORE_NOCRITICAL 0x100 + +/* certificate is within CRL scope */ + +#define CRL_SCORE_SCOPE 0x080 + +/* CRL times valid */ + +#define CRL_SCORE_TIME 0x040 + +/* Issuer name matches certificate */ + +#define CRL_SCORE_ISSUER_NAME 0x020 + +/* If this score or above CRL is probably valid */ + +#define CRL_SCORE_VALID (CRL_SCORE_NOCRITICAL|CRL_SCORE_TIME|CRL_SCORE_SCOPE) + +/* CRL issuer is certificate issuer */ + +#define CRL_SCORE_ISSUER_CERT 0x018 + +/* CRL issuer is on certificate path */ + +#define CRL_SCORE_SAME_PATH 0x008 + +/* CRL issuer matches CRL AKID */ + +#define CRL_SCORE_AKID 0x004 + +/* Have a delta CRL with valid times */ + +#define CRL_SCORE_TIME_DELTA 0x002 + +static int build_chain(X509_STORE_CTX *ctx); +static int verify_chain(X509_STORE_CTX *ctx); +static int dane_verify(X509_STORE_CTX *ctx); +static int null_callback(int ok, X509_STORE_CTX *e); +static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer); +static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x); +static int check_chain_extensions(X509_STORE_CTX *ctx); +static int check_name_constraints(X509_STORE_CTX *ctx); +static int check_id(X509_STORE_CTX *ctx); +static int check_trust(X509_STORE_CTX *ctx, int num_untrusted); +static int check_revocation(X509_STORE_CTX *ctx); +static int check_cert(X509_STORE_CTX *ctx); +static int check_policy(X509_STORE_CTX *ctx); +static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x); +static int check_dane_issuer(X509_STORE_CTX *ctx, int depth); +static int check_key_level(X509_STORE_CTX *ctx, X509 *cert); +static int check_sig_level(X509_STORE_CTX *ctx, X509 *cert); + +static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer, + unsigned int *preasons, X509_CRL *crl, X509 *x); +static int get_crl_delta(X509_STORE_CTX *ctx, + X509_CRL **pcrl, X509_CRL **pdcrl, X509 *x); +static void get_delta_sk(X509_STORE_CTX *ctx, X509_CRL **dcrl, + int *pcrl_score, X509_CRL *base, + STACK_OF(X509_CRL) *crls); +static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl, X509 **pissuer, + int *pcrl_score); +static int crl_crldp_check(X509 *x, X509_CRL *crl, int crl_score, + unsigned int *preasons); +static int check_crl_path(X509_STORE_CTX *ctx, X509 *x); +static int check_crl_chain(X509_STORE_CTX *ctx, + STACK_OF(X509) *cert_path, + STACK_OF(X509) *crl_path); + +static int internal_verify(X509_STORE_CTX *ctx); + +static int null_callback(int ok, X509_STORE_CTX *e) +{ + return ok; +} + +/* Return 1 is a certificate is self signed */ +static int cert_self_signed(X509 *x) +{ + /* + * FIXME: x509v3_cache_extensions() needs to detect more failures and not + * set EXFLAG_SET when that happens. Especially, if the failures are + * parse errors, rather than memory pressure! + */ + X509_check_purpose(x, -1, 0); + if (x->ex_flags & EXFLAG_SS) + return 1; + else + return 0; +} + +/* Given a certificate try and find an exact match in the store */ + +static X509 *lookup_cert_match(X509_STORE_CTX *ctx, X509 *x) +{ + STACK_OF(X509) *certs; + X509 *xtmp = NULL; + int i; + /* Lookup all certs with matching subject name */ + certs = ctx->lookup_certs(ctx, X509_get_subject_name(x)); + if (certs == NULL) + return NULL; + /* Look for exact match */ + for (i = 0; i < sk_X509_num(certs); i++) { + xtmp = sk_X509_value(certs, i); + if (!X509_cmp(xtmp, x)) + break; + } + if (i < sk_X509_num(certs)) + X509_up_ref(xtmp); + else + xtmp = NULL; + sk_X509_pop_free(certs, X509_free); + return xtmp; +} + +/*- + * Inform the verify callback of an error. + * If B is not NULL it is the error cert, otherwise use the chain cert at + * B. + * If B is not X509_V_OK, that's the error value, otherwise leave + * unchanged (presumably set by the caller). + * + * Returns 0 to abort verification with an error, non-zero to continue. + */ +static int verify_cb_cert(X509_STORE_CTX *ctx, X509 *x, int depth, int err) +{ + ctx->error_depth = depth; + ctx->current_cert = (x != NULL) ? x : sk_X509_value(ctx->chain, depth); + if (err != X509_V_OK) + ctx->error = err; + return ctx->verify_cb(0, ctx); +} + +/*- + * Inform the verify callback of an error, CRL-specific variant. Here, the + * error depth and certificate are already set, we just specify the error + * number. + * + * Returns 0 to abort verification with an error, non-zero to continue. + */ +static int verify_cb_crl(X509_STORE_CTX *ctx, int err) +{ + ctx->error = err; + return ctx->verify_cb(0, ctx); +} + +static int check_auth_level(X509_STORE_CTX *ctx) +{ + int i; + int num = sk_X509_num(ctx->chain); + + if (ctx->param->auth_level <= 0) + return 1; + + for (i = 0; i < num; ++i) { + X509 *cert = sk_X509_value(ctx->chain, i); + + /* + * We've already checked the security of the leaf key, so here we only + * check the security of issuer keys. + */ + if (i > 0 && !check_key_level(ctx, cert) && + verify_cb_cert(ctx, cert, i, X509_V_ERR_CA_KEY_TOO_SMALL) == 0) + return 0; + /* + * We also check the signature algorithm security of all certificates + * except those of the trust anchor at index num-1. + */ + if (i < num - 1 && !check_sig_level(ctx, cert) && + verify_cb_cert(ctx, cert, i, X509_V_ERR_CA_MD_TOO_WEAK) == 0) + return 0; + } + return 1; +} + +static int verify_chain(X509_STORE_CTX *ctx) +{ + int err; + int ok; + + /* + * Before either returning with an error, or continuing with CRL checks, + * instantiate chain public key parameters. + */ + if ((ok = build_chain(ctx)) == 0 || + (ok = check_chain_extensions(ctx)) == 0 || + (ok = check_auth_level(ctx)) == 0 || + (ok = check_id(ctx)) == 0 || 1) + X509_get_pubkey_parameters(NULL, ctx->chain); + if (ok == 0 || (ok = ctx->check_revocation(ctx)) == 0) + return ok; + + err = X509_chain_check_suiteb(&ctx->error_depth, NULL, ctx->chain, + ctx->param->flags); + if (err != X509_V_OK) { + if ((ok = verify_cb_cert(ctx, NULL, ctx->error_depth, err)) == 0) + return ok; + } + + /* Verify chain signatures and expiration times */ + ok = (ctx->verify != NULL) ? ctx->verify(ctx) : internal_verify(ctx); + if (!ok) + return ok; + + if ((ok = check_name_constraints(ctx)) == 0) + return ok; + +#ifndef OPENSSL_NO_RFC3779 + /* RFC 3779 path validation, now that CRL check has been done */ + if ((ok = X509v3_asid_validate_path(ctx)) == 0) + return ok; + if ((ok = X509v3_addr_validate_path(ctx)) == 0) + return ok; +#endif + + /* If we get this far evaluate policies */ + if (ctx->param->flags & X509_V_FLAG_POLICY_CHECK) + ok = ctx->check_policy(ctx); + return ok; +} + +int X509_verify_cert(X509_STORE_CTX *ctx) +{ + SSL_DANE *dane = ctx->dane; + int ret; + + if (ctx->cert == NULL) { + X509err(X509_F_X509_VERIFY_CERT, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY); + ctx->error = X509_V_ERR_INVALID_CALL; + return -1; + } + + if (ctx->chain != NULL) { + /* + * This X509_STORE_CTX has already been used to verify a cert. We + * cannot do another one. + */ + X509err(X509_F_X509_VERIFY_CERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ctx->error = X509_V_ERR_INVALID_CALL; + return -1; + } + + /* + * first we make sure the chain we are going to build is present and that + * the first entry is in place + */ + if (((ctx->chain = sk_X509_new_null()) == NULL) || + (!sk_X509_push(ctx->chain, ctx->cert))) { + X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + return -1; + } + X509_up_ref(ctx->cert); + ctx->num_untrusted = 1; + + /* If the peer's public key is too weak, we can stop early. */ + if (!check_key_level(ctx, ctx->cert) && + !verify_cb_cert(ctx, ctx->cert, 0, X509_V_ERR_EE_KEY_TOO_SMALL)) + return 0; + + if (DANETLS_ENABLED(dane)) + ret = dane_verify(ctx); + else + ret = verify_chain(ctx); + + /* + * Safety-net. If we are returning an error, we must also set ctx->error, + * so that the chain is not considered verified should the error be ignored + * (e.g. TLS with SSL_VERIFY_NONE). + */ + if (ret <= 0 && ctx->error == X509_V_OK) + ctx->error = X509_V_ERR_UNSPECIFIED; + return ret; +} + +/* + * Given a STACK_OF(X509) find the issuer of cert (if any) + */ +static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x) +{ + int i; + X509 *issuer, *rv = NULL; + + for (i = 0; i < sk_X509_num(sk); i++) { + issuer = sk_X509_value(sk, i); + if (ctx->check_issued(ctx, x, issuer)) { + rv = issuer; + if (x509_check_cert_time(ctx, rv, -1)) + break; + } + } + return rv; +} + +/* Given a possible certificate and issuer check them */ + +static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer) +{ + int ret; + if (x == issuer) + return cert_self_signed(x); + ret = X509_check_issued(issuer, x); + if (ret == X509_V_OK) { + int i; + X509 *ch; + /* Special case: single self signed certificate */ + if (cert_self_signed(x) && sk_X509_num(ctx->chain) == 1) + return 1; + for (i = 0; i < sk_X509_num(ctx->chain); i++) { + ch = sk_X509_value(ctx->chain, i); + if (ch == issuer || !X509_cmp(ch, issuer)) { + ret = X509_V_ERR_PATH_LOOP; + break; + } + } + } + + return (ret == X509_V_OK); +} + +/* Alternative lookup method: look from a STACK stored in other_ctx */ + +static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) +{ + *issuer = find_issuer(ctx, ctx->other_ctx, x); + if (*issuer) { + X509_up_ref(*issuer); + return 1; + } else + return 0; +} + +static STACK_OF(X509) *lookup_certs_sk(X509_STORE_CTX *ctx, X509_NAME *nm) +{ + STACK_OF(X509) *sk = NULL; + X509 *x; + int i; + + for (i = 0; i < sk_X509_num(ctx->other_ctx); i++) { + x = sk_X509_value(ctx->other_ctx, i); + if (X509_NAME_cmp(nm, X509_get_subject_name(x)) == 0) { + if (sk == NULL) + sk = sk_X509_new_null(); + if (sk == NULL || sk_X509_push(sk, x) == 0) { + sk_X509_pop_free(sk, X509_free); + X509err(X509_F_LOOKUP_CERTS_SK, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + return NULL; + } + X509_up_ref(x); + } + } + return sk; +} + +/* + * Check EE or CA certificate purpose. For trusted certificates explicit local + * auxiliary trust can be used to override EKU-restrictions. + */ +static int check_purpose(X509_STORE_CTX *ctx, X509 *x, int purpose, int depth, + int must_be_ca) +{ + int tr_ok = X509_TRUST_UNTRUSTED; + + /* + * For trusted certificates we want to see whether any auxiliary trust + * settings trump the purpose constraints. + * + * This is complicated by the fact that the trust ordinals in + * ctx->param->trust are entirely independent of the purpose ordinals in + * ctx->param->purpose! + * + * What connects them is their mutual initialization via calls from + * X509_STORE_CTX_set_default() into X509_VERIFY_PARAM_lookup() which sets + * related values of both param->trust and param->purpose. It is however + * typically possible to infer associated trust values from a purpose value + * via the X509_PURPOSE API. + * + * Therefore, we can only check for trust overrides when the purpose we're + * checking is the same as ctx->param->purpose and ctx->param->trust is + * also set. + */ + if (depth >= ctx->num_untrusted && purpose == ctx->param->purpose) + tr_ok = X509_check_trust(x, ctx->param->trust, X509_TRUST_NO_SS_COMPAT); + + switch (tr_ok) { + case X509_TRUST_TRUSTED: + return 1; + case X509_TRUST_REJECTED: + break; + default: + switch (X509_check_purpose(x, purpose, must_be_ca > 0)) { + case 1: + return 1; + case 0: + break; + default: + if ((ctx->param->flags & X509_V_FLAG_X509_STRICT) == 0) + return 1; + } + break; + } + + return verify_cb_cert(ctx, x, depth, X509_V_ERR_INVALID_PURPOSE); +} + +/* + * Check a certificate chains extensions for consistency with the supplied + * purpose + */ + +static int check_chain_extensions(X509_STORE_CTX *ctx) +{ + int i, must_be_ca, plen = 0; + X509 *x; + int proxy_path_length = 0; + int purpose; + int allow_proxy_certs; + int num = sk_X509_num(ctx->chain); + + /*- + * must_be_ca can have 1 of 3 values: + * -1: we accept both CA and non-CA certificates, to allow direct + * use of self-signed certificates (which are marked as CA). + * 0: we only accept non-CA certificates. This is currently not + * used, but the possibility is present for future extensions. + * 1: we only accept CA certificates. This is currently used for + * all certificates in the chain except the leaf certificate. + */ + must_be_ca = -1; + + /* CRL path validation */ + if (ctx->parent) { + allow_proxy_certs = 0; + purpose = X509_PURPOSE_CRL_SIGN; + } else { + allow_proxy_certs = + ! !(ctx->param->flags & X509_V_FLAG_ALLOW_PROXY_CERTS); + purpose = ctx->param->purpose; + } + + for (i = 0; i < num; i++) { + int ret; + x = sk_X509_value(ctx->chain, i); + if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) + && (x->ex_flags & EXFLAG_CRITICAL)) { + if (!verify_cb_cert(ctx, x, i, + X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION)) + return 0; + } + if (!allow_proxy_certs && (x->ex_flags & EXFLAG_PROXY)) { + if (!verify_cb_cert(ctx, x, i, + X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED)) + return 0; + } + ret = X509_check_ca(x); + switch (must_be_ca) { + case -1: + if ((ctx->param->flags & X509_V_FLAG_X509_STRICT) + && (ret != 1) && (ret != 0)) { + ret = 0; + ctx->error = X509_V_ERR_INVALID_CA; + } else + ret = 1; + break; + case 0: + if (ret != 0) { + ret = 0; + ctx->error = X509_V_ERR_INVALID_NON_CA; + } else + ret = 1; + break; + default: + /* X509_V_FLAG_X509_STRICT is implicit for intermediate CAs */ + if ((ret == 0) + || ((i + 1 < num || ctx->param->flags & X509_V_FLAG_X509_STRICT) + && (ret != 1))) { + ret = 0; + ctx->error = X509_V_ERR_INVALID_CA; + } else + ret = 1; + break; + } + if (ret == 0 && !verify_cb_cert(ctx, x, i, X509_V_OK)) + return 0; + /* check_purpose() makes the callback as needed */ + if (purpose > 0 && !check_purpose(ctx, x, purpose, i, must_be_ca)) + return 0; + /* Check pathlen */ + if ((i > 1) && (x->ex_pathlen != -1) + && (plen > (x->ex_pathlen + proxy_path_length))) { + if (!verify_cb_cert(ctx, x, i, X509_V_ERR_PATH_LENGTH_EXCEEDED)) + return 0; + } + /* Increment path length if not a self issued intermediate CA */ + if (i > 0 && (x->ex_flags & EXFLAG_SI) == 0) + plen++; + /* + * If this certificate is a proxy certificate, the next certificate + * must be another proxy certificate or a EE certificate. If not, + * the next certificate must be a CA certificate. + */ + if (x->ex_flags & EXFLAG_PROXY) { + /* + * RFC3820, 4.1.3 (b)(1) stipulates that if pCPathLengthConstraint + * is less than max_path_length, the former should be copied to + * the latter, and 4.1.4 (a) stipulates that max_path_length + * should be verified to be larger than zero and decrement it. + * + * Because we're checking the certs in the reverse order, we start + * with verifying that proxy_path_length isn't larger than pcPLC, + * and copy the latter to the former if it is, and finally, + * increment proxy_path_length. + */ + if (x->ex_pcpathlen != -1) { + if (proxy_path_length > x->ex_pcpathlen) { + if (!verify_cb_cert(ctx, x, i, + X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED)) + return 0; + } + proxy_path_length = x->ex_pcpathlen; + } + proxy_path_length++; + must_be_ca = 0; + } else + must_be_ca = 1; + } + return 1; +} + +static int has_san_id(X509 *x, int gtype) +{ + int i; + int ret = 0; + GENERAL_NAMES *gs = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); + + if (gs == NULL) + return 0; + + for (i = 0; i < sk_GENERAL_NAME_num(gs); i++) { + GENERAL_NAME *g = sk_GENERAL_NAME_value(gs, i); + + if (g->type == gtype) { + ret = 1; + break; + } + } + GENERAL_NAMES_free(gs); + return ret; +} + +static int check_name_constraints(X509_STORE_CTX *ctx) +{ + int i; + + /* Check name constraints for all certificates */ + for (i = sk_X509_num(ctx->chain) - 1; i >= 0; i--) { + X509 *x = sk_X509_value(ctx->chain, i); + int j; + + /* Ignore self issued certs unless last in chain */ + if (i && (x->ex_flags & EXFLAG_SI)) + continue; + + /* + * Proxy certificates policy has an extra constraint, where the + * certificate subject MUST be the issuer with a single CN entry + * added. + * (RFC 3820: 3.4, 4.1.3 (a)(4)) + */ + if (x->ex_flags & EXFLAG_PROXY) { + X509_NAME *tmpsubject = X509_get_subject_name(x); + X509_NAME *tmpissuer = X509_get_issuer_name(x); + X509_NAME_ENTRY *tmpentry = NULL; + int last_object_nid = 0; + int err = X509_V_OK; + int last_object_loc = X509_NAME_entry_count(tmpsubject) - 1; + + /* Check that there are at least two RDNs */ + if (last_object_loc < 1) { + err = X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION; + goto proxy_name_done; + } + + /* + * Check that there is exactly one more RDN in subject as + * there is in issuer. + */ + if (X509_NAME_entry_count(tmpsubject) + != X509_NAME_entry_count(tmpissuer) + 1) { + err = X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION; + goto proxy_name_done; + } + + /* + * Check that the last subject component isn't part of a + * multivalued RDN + */ + if (X509_NAME_ENTRY_set(X509_NAME_get_entry(tmpsubject, + last_object_loc)) + == X509_NAME_ENTRY_set(X509_NAME_get_entry(tmpsubject, + last_object_loc - 1))) { + err = X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION; + goto proxy_name_done; + } + + /* + * Check that the last subject RDN is a commonName, and that + * all the previous RDNs match the issuer exactly + */ + tmpsubject = X509_NAME_dup(tmpsubject); + if (tmpsubject == NULL) { + X509err(X509_F_CHECK_NAME_CONSTRAINTS, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + return 0; + } + + tmpentry = + X509_NAME_delete_entry(tmpsubject, last_object_loc); + last_object_nid = + OBJ_obj2nid(X509_NAME_ENTRY_get_object(tmpentry)); + + if (last_object_nid != NID_commonName + || X509_NAME_cmp(tmpsubject, tmpissuer) != 0) { + err = X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION; + } + + X509_NAME_ENTRY_free(tmpentry); + X509_NAME_free(tmpsubject); + + proxy_name_done: + if (err != X509_V_OK + && !verify_cb_cert(ctx, x, i, err)) + return 0; + } + + /* + * Check against constraints for all certificates higher in chain + * including trust anchor. Trust anchor not strictly speaking needed + * but if it includes constraints it is to be assumed it expects them + * to be obeyed. + */ + for (j = sk_X509_num(ctx->chain) - 1; j > i; j--) { + NAME_CONSTRAINTS *nc = sk_X509_value(ctx->chain, j)->nc; + + if (nc) { + int rv = NAME_CONSTRAINTS_check(x, nc); + + /* If EE certificate check commonName too */ + if (rv == X509_V_OK && i == 0 + && (ctx->param->hostflags + & X509_CHECK_FLAG_NEVER_CHECK_SUBJECT) == 0 + && ((ctx->param->hostflags + & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT) != 0 + || !has_san_id(x, GEN_DNS))) + rv = NAME_CONSTRAINTS_check_CN(x, nc); + + switch (rv) { + case X509_V_OK: + break; + case X509_V_ERR_OUT_OF_MEM: + return 0; + default: + if (!verify_cb_cert(ctx, x, i, rv)) + return 0; + break; + } + } + } + } + return 1; +} + +static int check_id_error(X509_STORE_CTX *ctx, int errcode) +{ + return verify_cb_cert(ctx, ctx->cert, 0, errcode); +} + +static int check_hosts(X509 *x, X509_VERIFY_PARAM *vpm) +{ + int i; + int n = sk_OPENSSL_STRING_num(vpm->hosts); + char *name; + + if (vpm->peername != NULL) { + OPENSSL_free(vpm->peername); + vpm->peername = NULL; + } + for (i = 0; i < n; ++i) { + name = sk_OPENSSL_STRING_value(vpm->hosts, i); + if (X509_check_host(x, name, 0, vpm->hostflags, &vpm->peername) > 0) + return 1; + } + return n == 0; +} + +static int check_id(X509_STORE_CTX *ctx) +{ + X509_VERIFY_PARAM *vpm = ctx->param; + X509 *x = ctx->cert; + if (vpm->hosts && check_hosts(x, vpm) <= 0) { + if (!check_id_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH)) + return 0; + } + if (vpm->email && X509_check_email(x, vpm->email, vpm->emaillen, 0) <= 0) { + if (!check_id_error(ctx, X509_V_ERR_EMAIL_MISMATCH)) + return 0; + } + if (vpm->ip && X509_check_ip(x, vpm->ip, vpm->iplen, 0) <= 0) { + if (!check_id_error(ctx, X509_V_ERR_IP_ADDRESS_MISMATCH)) + return 0; + } + return 1; +} + +static int check_trust(X509_STORE_CTX *ctx, int num_untrusted) +{ + int i; + X509 *x = NULL; + X509 *mx; + SSL_DANE *dane = ctx->dane; + int num = sk_X509_num(ctx->chain); + int trust; + + /* + * Check for a DANE issuer at depth 1 or greater, if it is a DANE-TA(2) + * match, we're done, otherwise we'll merely record the match depth. + */ + if (DANETLS_HAS_TA(dane) && num_untrusted > 0 && num_untrusted < num) { + switch (trust = check_dane_issuer(ctx, num_untrusted)) { + case X509_TRUST_TRUSTED: + case X509_TRUST_REJECTED: + return trust; + } + } + + /* + * Check trusted certificates in chain at depth num_untrusted and up. + * Note, that depths 0..num_untrusted-1 may also contain trusted + * certificates, but the caller is expected to have already checked those, + * and wants to incrementally check just any added since. + */ + for (i = num_untrusted; i < num; i++) { + x = sk_X509_value(ctx->chain, i); + trust = X509_check_trust(x, ctx->param->trust, 0); + /* If explicitly trusted return trusted */ + if (trust == X509_TRUST_TRUSTED) + goto trusted; + if (trust == X509_TRUST_REJECTED) + goto rejected; + } + + /* + * If we are looking at a trusted certificate, and accept partial chains, + * the chain is PKIX trusted. + */ + if (num_untrusted < num) { + if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) + goto trusted; + return X509_TRUST_UNTRUSTED; + } + + if (num_untrusted == num && ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) { + /* + * Last-resort call with no new trusted certificates, check the leaf + * for a direct trust store match. + */ + i = 0; + x = sk_X509_value(ctx->chain, i); + mx = lookup_cert_match(ctx, x); + if (!mx) + return X509_TRUST_UNTRUSTED; + + /* + * Check explicit auxiliary trust/reject settings. If none are set, + * we'll accept X509_TRUST_UNTRUSTED when not self-signed. + */ + trust = X509_check_trust(mx, ctx->param->trust, 0); + if (trust == X509_TRUST_REJECTED) { + X509_free(mx); + goto rejected; + } + + /* Replace leaf with trusted match */ + (void) sk_X509_set(ctx->chain, 0, mx); + X509_free(x); + ctx->num_untrusted = 0; + goto trusted; + } + + /* + * If no trusted certs in chain at all return untrusted and allow + * standard (no issuer cert) etc errors to be indicated. + */ + return X509_TRUST_UNTRUSTED; + + rejected: + if (!verify_cb_cert(ctx, x, i, X509_V_ERR_CERT_REJECTED)) + return X509_TRUST_REJECTED; + return X509_TRUST_UNTRUSTED; + + trusted: + if (!DANETLS_ENABLED(dane)) + return X509_TRUST_TRUSTED; + if (dane->pdpth < 0) + dane->pdpth = num_untrusted; + /* With DANE, PKIX alone is not trusted until we have both */ + if (dane->mdpth >= 0) + return X509_TRUST_TRUSTED; + return X509_TRUST_UNTRUSTED; +} + +static int check_revocation(X509_STORE_CTX *ctx) +{ + int i = 0, last = 0, ok = 0; + if (!(ctx->param->flags & X509_V_FLAG_CRL_CHECK)) + return 1; + if (ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL) + last = sk_X509_num(ctx->chain) - 1; + else { + /* If checking CRL paths this isn't the EE certificate */ + if (ctx->parent) + return 1; + last = 0; + } + for (i = 0; i <= last; i++) { + ctx->error_depth = i; + ok = check_cert(ctx); + if (!ok) + return ok; + } + return 1; +} + +static int check_cert(X509_STORE_CTX *ctx) +{ + X509_CRL *crl = NULL, *dcrl = NULL; + int ok = 0; + int cnum = ctx->error_depth; + X509 *x = sk_X509_value(ctx->chain, cnum); + + ctx->current_cert = x; + ctx->current_issuer = NULL; + ctx->current_crl_score = 0; + ctx->current_reasons = 0; + + if (x->ex_flags & EXFLAG_PROXY) + return 1; + + while (ctx->current_reasons != CRLDP_ALL_REASONS) { + unsigned int last_reasons = ctx->current_reasons; + + /* Try to retrieve relevant CRL */ + if (ctx->get_crl) + ok = ctx->get_crl(ctx, &crl, x); + else + ok = get_crl_delta(ctx, &crl, &dcrl, x); + /* + * If error looking up CRL, nothing we can do except notify callback + */ + if (!ok) { + ok = verify_cb_crl(ctx, X509_V_ERR_UNABLE_TO_GET_CRL); + goto done; + } + ctx->current_crl = crl; + ok = ctx->check_crl(ctx, crl); + if (!ok) + goto done; + + if (dcrl) { + ok = ctx->check_crl(ctx, dcrl); + if (!ok) + goto done; + ok = ctx->cert_crl(ctx, dcrl, x); + if (!ok) + goto done; + } else + ok = 1; + + /* Don't look in full CRL if delta reason is removefromCRL */ + if (ok != 2) { + ok = ctx->cert_crl(ctx, crl, x); + if (!ok) + goto done; + } + + X509_CRL_free(crl); + X509_CRL_free(dcrl); + crl = NULL; + dcrl = NULL; + /* + * If reasons not updated we won't get anywhere by another iteration, + * so exit loop. + */ + if (last_reasons == ctx->current_reasons) { + ok = verify_cb_crl(ctx, X509_V_ERR_UNABLE_TO_GET_CRL); + goto done; + } + } + done: + X509_CRL_free(crl); + X509_CRL_free(dcrl); + + ctx->current_crl = NULL; + return ok; +} + +/* Check CRL times against values in X509_STORE_CTX */ + +static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify) +{ + time_t *ptime; + int i; + + if (notify) + ctx->current_crl = crl; + if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) + ptime = &ctx->param->check_time; + else if (ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME) + return 1; + else + ptime = NULL; + + i = X509_cmp_time(X509_CRL_get0_lastUpdate(crl), ptime); + if (i == 0) { + if (!notify) + return 0; + if (!verify_cb_crl(ctx, X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD)) + return 0; + } + + if (i > 0) { + if (!notify) + return 0; + if (!verify_cb_crl(ctx, X509_V_ERR_CRL_NOT_YET_VALID)) + return 0; + } + + if (X509_CRL_get0_nextUpdate(crl)) { + i = X509_cmp_time(X509_CRL_get0_nextUpdate(crl), ptime); + + if (i == 0) { + if (!notify) + return 0; + if (!verify_cb_crl(ctx, X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD)) + return 0; + } + /* Ignore expiry of base CRL is delta is valid */ + if ((i < 0) && !(ctx->current_crl_score & CRL_SCORE_TIME_DELTA)) { + if (!notify) + return 0; + if (!verify_cb_crl(ctx, X509_V_ERR_CRL_HAS_EXPIRED)) + return 0; + } + } + + if (notify) + ctx->current_crl = NULL; + + return 1; +} + +static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509_CRL **pdcrl, + X509 **pissuer, int *pscore, unsigned int *preasons, + STACK_OF(X509_CRL) *crls) +{ + int i, crl_score, best_score = *pscore; + unsigned int reasons, best_reasons = 0; + X509 *x = ctx->current_cert; + X509_CRL *crl, *best_crl = NULL; + X509 *crl_issuer = NULL, *best_crl_issuer = NULL; + + for (i = 0; i < sk_X509_CRL_num(crls); i++) { + crl = sk_X509_CRL_value(crls, i); + reasons = *preasons; + crl_score = get_crl_score(ctx, &crl_issuer, &reasons, crl, x); + if (crl_score < best_score || crl_score == 0) + continue; + /* If current CRL is equivalent use it if it is newer */ + if (crl_score == best_score && best_crl != NULL) { + int day, sec; + if (ASN1_TIME_diff(&day, &sec, X509_CRL_get0_lastUpdate(best_crl), + X509_CRL_get0_lastUpdate(crl)) == 0) + continue; + /* + * ASN1_TIME_diff never returns inconsistent signs for |day| + * and |sec|. + */ + if (day <= 0 && sec <= 0) + continue; + } + best_crl = crl; + best_crl_issuer = crl_issuer; + best_score = crl_score; + best_reasons = reasons; + } + + if (best_crl) { + X509_CRL_free(*pcrl); + *pcrl = best_crl; + *pissuer = best_crl_issuer; + *pscore = best_score; + *preasons = best_reasons; + X509_CRL_up_ref(best_crl); + X509_CRL_free(*pdcrl); + *pdcrl = NULL; + get_delta_sk(ctx, pdcrl, pscore, best_crl, crls); + } + + if (best_score >= CRL_SCORE_VALID) + return 1; + + return 0; +} + +/* + * Compare two CRL extensions for delta checking purposes. They should be + * both present or both absent. If both present all fields must be identical. + */ + +static int crl_extension_match(X509_CRL *a, X509_CRL *b, int nid) +{ + ASN1_OCTET_STRING *exta, *extb; + int i; + i = X509_CRL_get_ext_by_NID(a, nid, -1); + if (i >= 0) { + /* Can't have multiple occurrences */ + if (X509_CRL_get_ext_by_NID(a, nid, i) != -1) + return 0; + exta = X509_EXTENSION_get_data(X509_CRL_get_ext(a, i)); + } else + exta = NULL; + + i = X509_CRL_get_ext_by_NID(b, nid, -1); + + if (i >= 0) { + + if (X509_CRL_get_ext_by_NID(b, nid, i) != -1) + return 0; + extb = X509_EXTENSION_get_data(X509_CRL_get_ext(b, i)); + } else + extb = NULL; + + if (!exta && !extb) + return 1; + + if (!exta || !extb) + return 0; + + if (ASN1_OCTET_STRING_cmp(exta, extb)) + return 0; + + return 1; +} + +/* See if a base and delta are compatible */ + +static int check_delta_base(X509_CRL *delta, X509_CRL *base) +{ + /* Delta CRL must be a delta */ + if (!delta->base_crl_number) + return 0; + /* Base must have a CRL number */ + if (!base->crl_number) + return 0; + /* Issuer names must match */ + if (X509_NAME_cmp(X509_CRL_get_issuer(base), X509_CRL_get_issuer(delta))) + return 0; + /* AKID and IDP must match */ + if (!crl_extension_match(delta, base, NID_authority_key_identifier)) + return 0; + if (!crl_extension_match(delta, base, NID_issuing_distribution_point)) + return 0; + /* Delta CRL base number must not exceed Full CRL number. */ + if (ASN1_INTEGER_cmp(delta->base_crl_number, base->crl_number) > 0) + return 0; + /* Delta CRL number must exceed full CRL number */ + if (ASN1_INTEGER_cmp(delta->crl_number, base->crl_number) > 0) + return 1; + return 0; +} + +/* + * For a given base CRL find a delta... maybe extend to delta scoring or + * retrieve a chain of deltas... + */ + +static void get_delta_sk(X509_STORE_CTX *ctx, X509_CRL **dcrl, int *pscore, + X509_CRL *base, STACK_OF(X509_CRL) *crls) +{ + X509_CRL *delta; + int i; + if (!(ctx->param->flags & X509_V_FLAG_USE_DELTAS)) + return; + if (!((ctx->current_cert->ex_flags | base->flags) & EXFLAG_FRESHEST)) + return; + for (i = 0; i < sk_X509_CRL_num(crls); i++) { + delta = sk_X509_CRL_value(crls, i); + if (check_delta_base(delta, base)) { + if (check_crl_time(ctx, delta, 0)) + *pscore |= CRL_SCORE_TIME_DELTA; + X509_CRL_up_ref(delta); + *dcrl = delta; + return; + } + } + *dcrl = NULL; +} + +/* + * For a given CRL return how suitable it is for the supplied certificate + * 'x'. The return value is a mask of several criteria. If the issuer is not + * the certificate issuer this is returned in *pissuer. The reasons mask is + * also used to determine if the CRL is suitable: if no new reasons the CRL + * is rejected, otherwise reasons is updated. + */ + +static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer, + unsigned int *preasons, X509_CRL *crl, X509 *x) +{ + + int crl_score = 0; + unsigned int tmp_reasons = *preasons, crl_reasons; + + /* First see if we can reject CRL straight away */ + + /* Invalid IDP cannot be processed */ + if (crl->idp_flags & IDP_INVALID) + return 0; + /* Reason codes or indirect CRLs need extended CRL support */ + if (!(ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT)) { + if (crl->idp_flags & (IDP_INDIRECT | IDP_REASONS)) + return 0; + } else if (crl->idp_flags & IDP_REASONS) { + /* If no new reasons reject */ + if (!(crl->idp_reasons & ~tmp_reasons)) + return 0; + } + /* Don't process deltas at this stage */ + else if (crl->base_crl_number) + return 0; + /* If issuer name doesn't match certificate need indirect CRL */ + if (X509_NAME_cmp(X509_get_issuer_name(x), X509_CRL_get_issuer(crl))) { + if (!(crl->idp_flags & IDP_INDIRECT)) + return 0; + } else + crl_score |= CRL_SCORE_ISSUER_NAME; + + if (!(crl->flags & EXFLAG_CRITICAL)) + crl_score |= CRL_SCORE_NOCRITICAL; + + /* Check expiry */ + if (check_crl_time(ctx, crl, 0)) + crl_score |= CRL_SCORE_TIME; + + /* Check authority key ID and locate certificate issuer */ + crl_akid_check(ctx, crl, pissuer, &crl_score); + + /* If we can't locate certificate issuer at this point forget it */ + + if (!(crl_score & CRL_SCORE_AKID)) + return 0; + + /* Check cert for matching CRL distribution points */ + + if (crl_crldp_check(x, crl, crl_score, &crl_reasons)) { + /* If no new reasons reject */ + if (!(crl_reasons & ~tmp_reasons)) + return 0; + tmp_reasons |= crl_reasons; + crl_score |= CRL_SCORE_SCOPE; + } + + *preasons = tmp_reasons; + + return crl_score; + +} + +static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl, + X509 **pissuer, int *pcrl_score) +{ + X509 *crl_issuer = NULL; + X509_NAME *cnm = X509_CRL_get_issuer(crl); + int cidx = ctx->error_depth; + int i; + + if (cidx != sk_X509_num(ctx->chain) - 1) + cidx++; + + crl_issuer = sk_X509_value(ctx->chain, cidx); + + if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) { + if (*pcrl_score & CRL_SCORE_ISSUER_NAME) { + *pcrl_score |= CRL_SCORE_AKID | CRL_SCORE_ISSUER_CERT; + *pissuer = crl_issuer; + return; + } + } + + for (cidx++; cidx < sk_X509_num(ctx->chain); cidx++) { + crl_issuer = sk_X509_value(ctx->chain, cidx); + if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm)) + continue; + if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) { + *pcrl_score |= CRL_SCORE_AKID | CRL_SCORE_SAME_PATH; + *pissuer = crl_issuer; + return; + } + } + + /* Anything else needs extended CRL support */ + + if (!(ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT)) + return; + + /* + * Otherwise the CRL issuer is not on the path. Look for it in the set of + * untrusted certificates. + */ + for (i = 0; i < sk_X509_num(ctx->untrusted); i++) { + crl_issuer = sk_X509_value(ctx->untrusted, i); + if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm)) + continue; + if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) { + *pissuer = crl_issuer; + *pcrl_score |= CRL_SCORE_AKID; + return; + } + } +} + +/* + * Check the path of a CRL issuer certificate. This creates a new + * X509_STORE_CTX and populates it with most of the parameters from the + * parent. This could be optimised somewhat since a lot of path checking will + * be duplicated by the parent, but this will rarely be used in practice. + */ + +static int check_crl_path(X509_STORE_CTX *ctx, X509 *x) +{ + X509_STORE_CTX crl_ctx; + int ret; + + /* Don't allow recursive CRL path validation */ + if (ctx->parent) + return 0; + if (!X509_STORE_CTX_init(&crl_ctx, ctx->ctx, x, ctx->untrusted)) + return -1; + + crl_ctx.crls = ctx->crls; + /* Copy verify params across */ + X509_STORE_CTX_set0_param(&crl_ctx, ctx->param); + + crl_ctx.parent = ctx; + crl_ctx.verify_cb = ctx->verify_cb; + + /* Verify CRL issuer */ + ret = X509_verify_cert(&crl_ctx); + if (ret <= 0) + goto err; + + /* Check chain is acceptable */ + ret = check_crl_chain(ctx, ctx->chain, crl_ctx.chain); + err: + X509_STORE_CTX_cleanup(&crl_ctx); + return ret; +} + +/* + * RFC3280 says nothing about the relationship between CRL path and + * certificate path, which could lead to situations where a certificate could + * be revoked or validated by a CA not authorised to do so. RFC5280 is more + * strict and states that the two paths must end in the same trust anchor, + * though some discussions remain... until this is resolved we use the + * RFC5280 version + */ + +static int check_crl_chain(X509_STORE_CTX *ctx, + STACK_OF(X509) *cert_path, + STACK_OF(X509) *crl_path) +{ + X509 *cert_ta, *crl_ta; + cert_ta = sk_X509_value(cert_path, sk_X509_num(cert_path) - 1); + crl_ta = sk_X509_value(crl_path, sk_X509_num(crl_path) - 1); + if (!X509_cmp(cert_ta, crl_ta)) + return 1; + return 0; +} + +/*- + * Check for match between two dist point names: three separate cases. + * 1. Both are relative names and compare X509_NAME types. + * 2. One full, one relative. Compare X509_NAME to GENERAL_NAMES. + * 3. Both are full names and compare two GENERAL_NAMES. + * 4. One is NULL: automatic match. + */ + +static int idp_check_dp(DIST_POINT_NAME *a, DIST_POINT_NAME *b) +{ + X509_NAME *nm = NULL; + GENERAL_NAMES *gens = NULL; + GENERAL_NAME *gena, *genb; + int i, j; + if (!a || !b) + return 1; + if (a->type == 1) { + if (!a->dpname) + return 0; + /* Case 1: two X509_NAME */ + if (b->type == 1) { + if (!b->dpname) + return 0; + if (!X509_NAME_cmp(a->dpname, b->dpname)) + return 1; + else + return 0; + } + /* Case 2: set name and GENERAL_NAMES appropriately */ + nm = a->dpname; + gens = b->name.fullname; + } else if (b->type == 1) { + if (!b->dpname) + return 0; + /* Case 2: set name and GENERAL_NAMES appropriately */ + gens = a->name.fullname; + nm = b->dpname; + } + + /* Handle case 2 with one GENERAL_NAMES and one X509_NAME */ + if (nm) { + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { + gena = sk_GENERAL_NAME_value(gens, i); + if (gena->type != GEN_DIRNAME) + continue; + if (!X509_NAME_cmp(nm, gena->d.directoryName)) + return 1; + } + return 0; + } + + /* Else case 3: two GENERAL_NAMES */ + + for (i = 0; i < sk_GENERAL_NAME_num(a->name.fullname); i++) { + gena = sk_GENERAL_NAME_value(a->name.fullname, i); + for (j = 0; j < sk_GENERAL_NAME_num(b->name.fullname); j++) { + genb = sk_GENERAL_NAME_value(b->name.fullname, j); + if (!GENERAL_NAME_cmp(gena, genb)) + return 1; + } + } + + return 0; + +} + +static int crldp_check_crlissuer(DIST_POINT *dp, X509_CRL *crl, int crl_score) +{ + int i; + X509_NAME *nm = X509_CRL_get_issuer(crl); + /* If no CRLissuer return is successful iff don't need a match */ + if (!dp->CRLissuer) + return ! !(crl_score & CRL_SCORE_ISSUER_NAME); + for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++) { + GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i); + if (gen->type != GEN_DIRNAME) + continue; + if (!X509_NAME_cmp(gen->d.directoryName, nm)) + return 1; + } + return 0; +} + +/* Check CRLDP and IDP */ + +static int crl_crldp_check(X509 *x, X509_CRL *crl, int crl_score, + unsigned int *preasons) +{ + int i; + if (crl->idp_flags & IDP_ONLYATTR) + return 0; + if (x->ex_flags & EXFLAG_CA) { + if (crl->idp_flags & IDP_ONLYUSER) + return 0; + } else { + if (crl->idp_flags & IDP_ONLYCA) + return 0; + } + *preasons = crl->idp_reasons; + for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++) { + DIST_POINT *dp = sk_DIST_POINT_value(x->crldp, i); + if (crldp_check_crlissuer(dp, crl, crl_score)) { + if (!crl->idp || idp_check_dp(dp->distpoint, crl->idp->distpoint)) { + *preasons &= dp->dp_reasons; + return 1; + } + } + } + if ((!crl->idp || !crl->idp->distpoint) + && (crl_score & CRL_SCORE_ISSUER_NAME)) + return 1; + return 0; +} + +/* + * Retrieve CRL corresponding to current certificate. If deltas enabled try + * to find a delta CRL too + */ + +static int get_crl_delta(X509_STORE_CTX *ctx, + X509_CRL **pcrl, X509_CRL **pdcrl, X509 *x) +{ + int ok; + X509 *issuer = NULL; + int crl_score = 0; + unsigned int reasons; + X509_CRL *crl = NULL, *dcrl = NULL; + STACK_OF(X509_CRL) *skcrl; + X509_NAME *nm = X509_get_issuer_name(x); + + reasons = ctx->current_reasons; + ok = get_crl_sk(ctx, &crl, &dcrl, + &issuer, &crl_score, &reasons, ctx->crls); + if (ok) + goto done; + + /* Lookup CRLs from store */ + + skcrl = ctx->lookup_crls(ctx, nm); + + /* If no CRLs found and a near match from get_crl_sk use that */ + if (!skcrl && crl) + goto done; + + get_crl_sk(ctx, &crl, &dcrl, &issuer, &crl_score, &reasons, skcrl); + + sk_X509_CRL_pop_free(skcrl, X509_CRL_free); + + done: + /* If we got any kind of CRL use it and return success */ + if (crl) { + ctx->current_issuer = issuer; + ctx->current_crl_score = crl_score; + ctx->current_reasons = reasons; + *pcrl = crl; + *pdcrl = dcrl; + return 1; + } + return 0; +} + +/* Check CRL validity */ +static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl) +{ + X509 *issuer = NULL; + EVP_PKEY *ikey = NULL; + int cnum = ctx->error_depth; + int chnum = sk_X509_num(ctx->chain) - 1; + + /* if we have an alternative CRL issuer cert use that */ + if (ctx->current_issuer) + issuer = ctx->current_issuer; + /* + * Else find CRL issuer: if not last certificate then issuer is next + * certificate in chain. + */ + else if (cnum < chnum) + issuer = sk_X509_value(ctx->chain, cnum + 1); + else { + issuer = sk_X509_value(ctx->chain, chnum); + /* If not self signed, can't check signature */ + if (!ctx->check_issued(ctx, issuer, issuer) && + !verify_cb_crl(ctx, X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER)) + return 0; + } + + if (issuer == NULL) + return 1; + + /* + * Skip most tests for deltas because they have already been done + */ + if (!crl->base_crl_number) { + /* Check for cRLSign bit if keyUsage present */ + if ((issuer->ex_flags & EXFLAG_KUSAGE) && + !(issuer->ex_kusage & KU_CRL_SIGN) && + !verify_cb_crl(ctx, X509_V_ERR_KEYUSAGE_NO_CRL_SIGN)) + return 0; + + if (!(ctx->current_crl_score & CRL_SCORE_SCOPE) && + !verify_cb_crl(ctx, X509_V_ERR_DIFFERENT_CRL_SCOPE)) + return 0; + + if (!(ctx->current_crl_score & CRL_SCORE_SAME_PATH) && + check_crl_path(ctx, ctx->current_issuer) <= 0 && + !verify_cb_crl(ctx, X509_V_ERR_CRL_PATH_VALIDATION_ERROR)) + return 0; + + if ((crl->idp_flags & IDP_INVALID) && + !verify_cb_crl(ctx, X509_V_ERR_INVALID_EXTENSION)) + return 0; + } + + if (!(ctx->current_crl_score & CRL_SCORE_TIME) && + !check_crl_time(ctx, crl, 1)) + return 0; + + /* Attempt to get issuer certificate public key */ + ikey = X509_get0_pubkey(issuer); + + if (!ikey && + !verify_cb_crl(ctx, X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY)) + return 0; + + if (ikey) { + int rv = X509_CRL_check_suiteb(crl, ikey, ctx->param->flags); + + if (rv != X509_V_OK && !verify_cb_crl(ctx, rv)) + return 0; + /* Verify CRL signature */ + if (X509_CRL_verify(crl, ikey) <= 0 && + !verify_cb_crl(ctx, X509_V_ERR_CRL_SIGNATURE_FAILURE)) + return 0; + } + return 1; +} + +/* Check certificate against CRL */ +static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x) +{ + X509_REVOKED *rev; + + /* + * The rules changed for this... previously if a CRL contained unhandled + * critical extensions it could still be used to indicate a certificate + * was revoked. This has since been changed since critical extensions can + * change the meaning of CRL entries. + */ + if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) + && (crl->flags & EXFLAG_CRITICAL) && + !verify_cb_crl(ctx, X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION)) + return 0; + /* + * Look for serial number of certificate in CRL. If found, make sure + * reason is not removeFromCRL. + */ + if (X509_CRL_get0_by_cert(crl, &rev, x)) { + if (rev->reason == CRL_REASON_REMOVE_FROM_CRL) + return 2; + if (!verify_cb_crl(ctx, X509_V_ERR_CERT_REVOKED)) + return 0; + } + + return 1; +} + +static int check_policy(X509_STORE_CTX *ctx) +{ + int ret; + + if (ctx->parent) + return 1; + /* + * With DANE, the trust anchor might be a bare public key, not a + * certificate! In that case our chain does not have the trust anchor + * certificate as a top-most element. This comports well with RFC5280 + * chain verification, since there too, the trust anchor is not part of the + * chain to be verified. In particular, X509_policy_check() does not look + * at the TA cert, but assumes that it is present as the top-most chain + * element. We therefore temporarily push a NULL cert onto the chain if it + * was verified via a bare public key, and pop it off right after the + * X509_policy_check() call. + */ + if (ctx->bare_ta_signed && !sk_X509_push(ctx->chain, NULL)) { + X509err(X509_F_CHECK_POLICY, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + return 0; + } + ret = X509_policy_check(&ctx->tree, &ctx->explicit_policy, ctx->chain, + ctx->param->policies, ctx->param->flags); + if (ctx->bare_ta_signed) + sk_X509_pop(ctx->chain); + + if (ret == X509_PCY_TREE_INTERNAL) { + X509err(X509_F_CHECK_POLICY, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + return 0; + } + /* Invalid or inconsistent extensions */ + if (ret == X509_PCY_TREE_INVALID) { + int i; + + /* Locate certificates with bad extensions and notify callback. */ + for (i = 1; i < sk_X509_num(ctx->chain); i++) { + X509 *x = sk_X509_value(ctx->chain, i); + + if (!(x->ex_flags & EXFLAG_INVALID_POLICY)) + continue; + if (!verify_cb_cert(ctx, x, i, + X509_V_ERR_INVALID_POLICY_EXTENSION)) + return 0; + } + return 1; + } + if (ret == X509_PCY_TREE_FAILURE) { + ctx->current_cert = NULL; + ctx->error = X509_V_ERR_NO_EXPLICIT_POLICY; + return ctx->verify_cb(0, ctx); + } + if (ret != X509_PCY_TREE_VALID) { + X509err(X509_F_CHECK_POLICY, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (ctx->param->flags & X509_V_FLAG_NOTIFY_POLICY) { + ctx->current_cert = NULL; + /* + * Verification errors need to be "sticky", a callback may have allowed + * an SSL handshake to continue despite an error, and we must then + * remain in an error state. Therefore, we MUST NOT clear earlier + * verification errors by setting the error to X509_V_OK. + */ + if (!ctx->verify_cb(2, ctx)) + return 0; + } + + return 1; +} + +/*- + * Check certificate validity times. + * If depth >= 0, invoke verification callbacks on error, otherwise just return + * the validation status. + * + * Return 1 on success, 0 otherwise. + */ +int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth) +{ + time_t *ptime; + int i; + + if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) + ptime = &ctx->param->check_time; + else if (ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME) + return 1; + else + ptime = NULL; + + i = X509_cmp_time(X509_get0_notBefore(x), ptime); + if (i >= 0 && depth < 0) + return 0; + if (i == 0 && !verify_cb_cert(ctx, x, depth, + X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD)) + return 0; + if (i > 0 && !verify_cb_cert(ctx, x, depth, X509_V_ERR_CERT_NOT_YET_VALID)) + return 0; + + i = X509_cmp_time(X509_get0_notAfter(x), ptime); + if (i <= 0 && depth < 0) + return 0; + if (i == 0 && !verify_cb_cert(ctx, x, depth, + X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD)) + return 0; + if (i < 0 && !verify_cb_cert(ctx, x, depth, X509_V_ERR_CERT_HAS_EXPIRED)) + return 0; + return 1; +} + +static int internal_verify(X509_STORE_CTX *ctx) +{ + int n = sk_X509_num(ctx->chain) - 1; + X509 *xi = sk_X509_value(ctx->chain, n); + X509 *xs; + + /* + * With DANE-verified bare public key TA signatures, it remains only to + * check the timestamps of the top certificate. We report the issuer as + * NULL, since all we have is a bare key. + */ + if (ctx->bare_ta_signed) { + xs = xi; + xi = NULL; + goto check_cert; + } + + if (ctx->check_issued(ctx, xi, xi)) + xs = xi; + else { + if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) { + xs = xi; + goto check_cert; + } + if (n <= 0) + return verify_cb_cert(ctx, xi, 0, + X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE); + n--; + ctx->error_depth = n; + xs = sk_X509_value(ctx->chain, n); + } + + /* + * Do not clear ctx->error=0, it must be "sticky", only the user's callback + * is allowed to reset errors (at its own peril). + */ + while (n >= 0) { + EVP_PKEY *pkey; + + /* + * Skip signature check for self signed certificates unless explicitly + * asked for. It doesn't add any security and just wastes time. If + * the issuer's public key is unusable, report the issuer certificate + * and its depth (rather than the depth of the subject). + */ + if (xs != xi || (ctx->param->flags & X509_V_FLAG_CHECK_SS_SIGNATURE)) { + if ((pkey = X509_get0_pubkey(xi)) == NULL) { + if (!verify_cb_cert(ctx, xi, xi != xs ? n+1 : n, + X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY)) + return 0; + } else if (X509_verify(xs, pkey) <= 0) { + if (!verify_cb_cert(ctx, xs, n, + X509_V_ERR_CERT_SIGNATURE_FAILURE)) + return 0; + } + } + + check_cert: + /* Calls verify callback as needed */ + if (!x509_check_cert_time(ctx, xs, n)) + return 0; + + /* + * Signal success at this depth. However, the previous error (if any) + * is retained. + */ + ctx->current_issuer = xi; + ctx->current_cert = xs; + ctx->error_depth = n; + if (!ctx->verify_cb(1, ctx)) + return 0; + + if (--n >= 0) { + xi = xs; + xs = sk_X509_value(ctx->chain, n); + } + } + return 1; +} + +int X509_cmp_current_time(const ASN1_TIME *ctm) +{ + return X509_cmp_time(ctm, NULL); +} + +int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time) +{ + static const size_t utctime_length = sizeof("YYMMDDHHMMSSZ") - 1; + static const size_t generalizedtime_length = sizeof("YYYYMMDDHHMMSSZ") - 1; + ASN1_TIME *asn1_cmp_time = NULL; + int i, day, sec, ret = 0; + + /* + * Note that ASN.1 allows much more slack in the time format than RFC5280. + * In RFC5280, the representation is fixed: + * UTCTime: YYMMDDHHMMSSZ + * GeneralizedTime: YYYYMMDDHHMMSSZ + * + * We do NOT currently enforce the following RFC 5280 requirement: + * "CAs conforming to this profile MUST always encode certificate + * validity dates through the year 2049 as UTCTime; certificate validity + * dates in 2050 or later MUST be encoded as GeneralizedTime." + */ + switch (ctm->type) { + case V_ASN1_UTCTIME: + if (ctm->length != (int)(utctime_length)) + return 0; + break; + case V_ASN1_GENERALIZEDTIME: + if (ctm->length != (int)(generalizedtime_length)) + return 0; + break; + default: + return 0; + } + + /** + * Verify the format: the ASN.1 functions we use below allow a more + * flexible format than what's mandated by RFC 5280. + * Digit and date ranges will be verified in the conversion methods. + */ + for (i = 0; i < ctm->length - 1; i++) { + if (!ossl_isdigit(ctm->data[i])) + return 0; + } + if (ctm->data[ctm->length - 1] != 'Z') + return 0; + + /* + * There is ASN1_UTCTIME_cmp_time_t but no + * ASN1_GENERALIZEDTIME_cmp_time_t or ASN1_TIME_cmp_time_t, + * so we go through ASN.1 + */ + asn1_cmp_time = X509_time_adj(NULL, 0, cmp_time); + if (asn1_cmp_time == NULL) + goto err; + if (!ASN1_TIME_diff(&day, &sec, ctm, asn1_cmp_time)) + goto err; + + /* + * X509_cmp_time comparison is <=. + * The return value 0 is reserved for errors. + */ + ret = (day >= 0 && sec >= 0) ? -1 : 1; + + err: + ASN1_TIME_free(asn1_cmp_time); + return ret; +} + +ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj) +{ + return X509_time_adj(s, adj, NULL); +} + +ASN1_TIME *X509_time_adj(ASN1_TIME *s, long offset_sec, time_t *in_tm) +{ + return X509_time_adj_ex(s, 0, offset_sec, in_tm); +} + +ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s, + int offset_day, long offset_sec, time_t *in_tm) +{ + time_t t; + + if (in_tm) + t = *in_tm; + else + time(&t); + + if (s && !(s->flags & ASN1_STRING_FLAG_MSTRING)) { + if (s->type == V_ASN1_UTCTIME) + return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec); + if (s->type == V_ASN1_GENERALIZEDTIME) + return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec); + } + return ASN1_TIME_adj(s, t, offset_day, offset_sec); +} + +int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain) +{ + EVP_PKEY *ktmp = NULL, *ktmp2; + int i, j; + + if ((pkey != NULL) && !EVP_PKEY_missing_parameters(pkey)) + return 1; + + for (i = 0; i < sk_X509_num(chain); i++) { + ktmp = X509_get0_pubkey(sk_X509_value(chain, i)); + if (ktmp == NULL) { + X509err(X509_F_X509_GET_PUBKEY_PARAMETERS, + X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY); + return 0; + } + if (!EVP_PKEY_missing_parameters(ktmp)) + break; + } + if (ktmp == NULL) { + X509err(X509_F_X509_GET_PUBKEY_PARAMETERS, + X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN); + return 0; + } + + /* first, populate the other certs */ + for (j = i - 1; j >= 0; j--) { + ktmp2 = X509_get0_pubkey(sk_X509_value(chain, j)); + EVP_PKEY_copy_parameters(ktmp2, ktmp); + } + + if (pkey != NULL) + EVP_PKEY_copy_parameters(pkey, ktmp); + return 1; +} + +/* Make a delta CRL as the diff between two full CRLs */ + +X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer, + EVP_PKEY *skey, const EVP_MD *md, unsigned int flags) +{ + X509_CRL *crl = NULL; + int i; + STACK_OF(X509_REVOKED) *revs = NULL; + /* CRLs can't be delta already */ + if (base->base_crl_number || newer->base_crl_number) { + X509err(X509_F_X509_CRL_DIFF, X509_R_CRL_ALREADY_DELTA); + return NULL; + } + /* Base and new CRL must have a CRL number */ + if (!base->crl_number || !newer->crl_number) { + X509err(X509_F_X509_CRL_DIFF, X509_R_NO_CRL_NUMBER); + return NULL; + } + /* Issuer names must match */ + if (X509_NAME_cmp(X509_CRL_get_issuer(base), X509_CRL_get_issuer(newer))) { + X509err(X509_F_X509_CRL_DIFF, X509_R_ISSUER_MISMATCH); + return NULL; + } + /* AKID and IDP must match */ + if (!crl_extension_match(base, newer, NID_authority_key_identifier)) { + X509err(X509_F_X509_CRL_DIFF, X509_R_AKID_MISMATCH); + return NULL; + } + if (!crl_extension_match(base, newer, NID_issuing_distribution_point)) { + X509err(X509_F_X509_CRL_DIFF, X509_R_IDP_MISMATCH); + return NULL; + } + /* Newer CRL number must exceed full CRL number */ + if (ASN1_INTEGER_cmp(newer->crl_number, base->crl_number) <= 0) { + X509err(X509_F_X509_CRL_DIFF, X509_R_NEWER_CRL_NOT_NEWER); + return NULL; + } + /* CRLs must verify */ + if (skey && (X509_CRL_verify(base, skey) <= 0 || + X509_CRL_verify(newer, skey) <= 0)) { + X509err(X509_F_X509_CRL_DIFF, X509_R_CRL_VERIFY_FAILURE); + return NULL; + } + /* Create new CRL */ + crl = X509_CRL_new(); + if (crl == NULL || !X509_CRL_set_version(crl, 1)) + goto memerr; + /* Set issuer name */ + if (!X509_CRL_set_issuer_name(crl, X509_CRL_get_issuer(newer))) + goto memerr; + + if (!X509_CRL_set1_lastUpdate(crl, X509_CRL_get0_lastUpdate(newer))) + goto memerr; + if (!X509_CRL_set1_nextUpdate(crl, X509_CRL_get0_nextUpdate(newer))) + goto memerr; + + /* Set base CRL number: must be critical */ + + if (!X509_CRL_add1_ext_i2d(crl, NID_delta_crl, base->crl_number, 1, 0)) + goto memerr; + + /* + * Copy extensions across from newest CRL to delta: this will set CRL + * number to correct value too. + */ + + for (i = 0; i < X509_CRL_get_ext_count(newer); i++) { + X509_EXTENSION *ext; + ext = X509_CRL_get_ext(newer, i); + if (!X509_CRL_add_ext(crl, ext, -1)) + goto memerr; + } + + /* Go through revoked entries, copying as needed */ + + revs = X509_CRL_get_REVOKED(newer); + + for (i = 0; i < sk_X509_REVOKED_num(revs); i++) { + X509_REVOKED *rvn, *rvtmp; + rvn = sk_X509_REVOKED_value(revs, i); + /* + * Add only if not also in base. TODO: need something cleverer here + * for some more complex CRLs covering multiple CAs. + */ + if (!X509_CRL_get0_by_serial(base, &rvtmp, &rvn->serialNumber)) { + rvtmp = X509_REVOKED_dup(rvn); + if (!rvtmp) + goto memerr; + if (!X509_CRL_add0_revoked(crl, rvtmp)) { + X509_REVOKED_free(rvtmp); + goto memerr; + } + } + } + /* TODO: optionally prune deleted entries */ + + if (skey && md && !X509_CRL_sign(crl, skey, md)) + goto memerr; + + return crl; + + memerr: + X509err(X509_F_X509_CRL_DIFF, ERR_R_MALLOC_FAILURE); + X509_CRL_free(crl); + return NULL; +} + +int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data) +{ + return CRYPTO_set_ex_data(&ctx->ex_data, idx, data); +} + +void *X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx) +{ + return CRYPTO_get_ex_data(&ctx->ex_data, idx); +} + +int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx) +{ + return ctx->error; +} + +void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int err) +{ + ctx->error = err; +} + +int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx) +{ + return ctx->error_depth; +} + +void X509_STORE_CTX_set_error_depth(X509_STORE_CTX *ctx, int depth) +{ + ctx->error_depth = depth; +} + +X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx) +{ + return ctx->current_cert; +} + +void X509_STORE_CTX_set_current_cert(X509_STORE_CTX *ctx, X509 *x) +{ + ctx->current_cert = x; +} + +STACK_OF(X509) *X509_STORE_CTX_get0_chain(X509_STORE_CTX *ctx) +{ + return ctx->chain; +} + +STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx) +{ + if (!ctx->chain) + return NULL; + return X509_chain_up_ref(ctx->chain); +} + +X509 *X509_STORE_CTX_get0_current_issuer(X509_STORE_CTX *ctx) +{ + return ctx->current_issuer; +} + +X509_CRL *X509_STORE_CTX_get0_current_crl(X509_STORE_CTX *ctx) +{ + return ctx->current_crl; +} + +X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(X509_STORE_CTX *ctx) +{ + return ctx->parent; +} + +void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x) +{ + ctx->cert = x; +} + +void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk) +{ + ctx->crls = sk; +} + +int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose) +{ + /* + * XXX: Why isn't this function always used to set the associated trust? + * Should there even be a VPM->trust field at all? Or should the trust + * always be inferred from the purpose by X509_STORE_CTX_init(). + */ + return X509_STORE_CTX_purpose_inherit(ctx, 0, purpose, 0); +} + +int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust) +{ + /* + * XXX: See above, this function would only be needed when the default + * trust for the purpose needs an override in a corner case. + */ + return X509_STORE_CTX_purpose_inherit(ctx, 0, 0, trust); +} + +/* + * This function is used to set the X509_STORE_CTX purpose and trust values. + * This is intended to be used when another structure has its own trust and + * purpose values which (if set) will be inherited by the ctx. If they aren't + * set then we will usually have a default purpose in mind which should then + * be used to set the trust value. An example of this is SSL use: an SSL + * structure will have its own purpose and trust settings which the + * application can set: if they aren't set then we use the default of SSL + * client/server. + */ + +int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose, + int purpose, int trust) +{ + int idx; + /* If purpose not set use default */ + if (!purpose) + purpose = def_purpose; + /* If we have a purpose then check it is valid */ + if (purpose) { + X509_PURPOSE *ptmp; + idx = X509_PURPOSE_get_by_id(purpose); + if (idx == -1) { + X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT, + X509_R_UNKNOWN_PURPOSE_ID); + return 0; + } + ptmp = X509_PURPOSE_get0(idx); + if (ptmp->trust == X509_TRUST_DEFAULT) { + idx = X509_PURPOSE_get_by_id(def_purpose); + /* + * XXX: In the two callers above def_purpose is always 0, which is + * not a known value, so idx will always be -1. How is the + * X509_TRUST_DEFAULT case actually supposed to be handled? + */ + if (idx == -1) { + X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT, + X509_R_UNKNOWN_PURPOSE_ID); + return 0; + } + ptmp = X509_PURPOSE_get0(idx); + } + /* If trust not set then get from purpose default */ + if (!trust) + trust = ptmp->trust; + } + if (trust) { + idx = X509_TRUST_get_by_id(trust); + if (idx == -1) { + X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT, + X509_R_UNKNOWN_TRUST_ID); + return 0; + } + } + + if (purpose && !ctx->param->purpose) + ctx->param->purpose = purpose; + if (trust && !ctx->param->trust) + ctx->param->trust = trust; + return 1; +} + +X509_STORE_CTX *X509_STORE_CTX_new(void) +{ + X509_STORE_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); + + if (ctx == NULL) { + X509err(X509_F_X509_STORE_CTX_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + return ctx; +} + +void X509_STORE_CTX_free(X509_STORE_CTX *ctx) +{ + if (ctx == NULL) + return; + + X509_STORE_CTX_cleanup(ctx); + OPENSSL_free(ctx); +} + +int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, + STACK_OF(X509) *chain) +{ + int ret = 1; + + ctx->ctx = store; + ctx->cert = x509; + ctx->untrusted = chain; + ctx->crls = NULL; + ctx->num_untrusted = 0; + ctx->other_ctx = NULL; + ctx->valid = 0; + ctx->chain = NULL; + ctx->error = 0; + ctx->explicit_policy = 0; + ctx->error_depth = 0; + ctx->current_cert = NULL; + ctx->current_issuer = NULL; + ctx->current_crl = NULL; + ctx->current_crl_score = 0; + ctx->current_reasons = 0; + ctx->tree = NULL; + ctx->parent = NULL; + ctx->dane = NULL; + ctx->bare_ta_signed = 0; + /* Zero ex_data to make sure we're cleanup-safe */ + memset(&ctx->ex_data, 0, sizeof(ctx->ex_data)); + + /* store->cleanup is always 0 in OpenSSL, if set must be idempotent */ + if (store) + ctx->cleanup = store->cleanup; + else + ctx->cleanup = 0; + + if (store && store->check_issued) + ctx->check_issued = store->check_issued; + else + ctx->check_issued = check_issued; + + if (store && store->get_issuer) + ctx->get_issuer = store->get_issuer; + else + ctx->get_issuer = X509_STORE_CTX_get1_issuer; + + if (store && store->verify_cb) + ctx->verify_cb = store->verify_cb; + else + ctx->verify_cb = null_callback; + + if (store && store->verify) + ctx->verify = store->verify; + else + ctx->verify = internal_verify; + + if (store && store->check_revocation) + ctx->check_revocation = store->check_revocation; + else + ctx->check_revocation = check_revocation; + + if (store && store->get_crl) + ctx->get_crl = store->get_crl; + else + ctx->get_crl = NULL; + + if (store && store->check_crl) + ctx->check_crl = store->check_crl; + else + ctx->check_crl = check_crl; + + if (store && store->cert_crl) + ctx->cert_crl = store->cert_crl; + else + ctx->cert_crl = cert_crl; + + if (store && store->check_policy) + ctx->check_policy = store->check_policy; + else + ctx->check_policy = check_policy; + + if (store && store->lookup_certs) + ctx->lookup_certs = store->lookup_certs; + else + ctx->lookup_certs = X509_STORE_CTX_get1_certs; + + if (store && store->lookup_crls) + ctx->lookup_crls = store->lookup_crls; + else + ctx->lookup_crls = X509_STORE_CTX_get1_crls; + + ctx->param = X509_VERIFY_PARAM_new(); + if (ctx->param == NULL) { + X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* + * Inherit callbacks and flags from X509_STORE if not set use defaults. + */ + if (store) + ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param); + else + ctx->param->inh_flags |= X509_VP_FLAG_DEFAULT | X509_VP_FLAG_ONCE; + + if (ret) + ret = X509_VERIFY_PARAM_inherit(ctx->param, + X509_VERIFY_PARAM_lookup("default")); + + if (ret == 0) { + X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* + * XXX: For now, continue to inherit trust from VPM, but infer from the + * purpose if this still yields the default value. + */ + if (ctx->param->trust == X509_TRUST_DEFAULT) { + int idx = X509_PURPOSE_get_by_id(ctx->param->purpose); + X509_PURPOSE *xp = X509_PURPOSE_get0(idx); + + if (xp != NULL) + ctx->param->trust = X509_PURPOSE_get_trust(xp); + } + + if (CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, + &ctx->ex_data)) + return 1; + X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE); + + err: + /* + * On error clean up allocated storage, if the store context was not + * allocated with X509_STORE_CTX_new() this is our last chance to do so. + */ + X509_STORE_CTX_cleanup(ctx); + return 0; +} + +/* + * Set alternative lookup method: just a STACK of trusted certificates. This + * avoids X509_STORE nastiness where it isn't needed. + */ +void X509_STORE_CTX_set0_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) +{ + ctx->other_ctx = sk; + ctx->get_issuer = get_issuer_sk; + ctx->lookup_certs = lookup_certs_sk; +} + +void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx) +{ + /* + * We need to be idempotent because, unfortunately, free() also calls + * cleanup(), so the natural call sequence new(), init(), cleanup(), free() + * calls cleanup() for the same object twice! Thus we must zero the + * pointers below after they're freed! + */ + /* Seems to always be 0 in OpenSSL, do this at most once. */ + if (ctx->cleanup != NULL) { + ctx->cleanup(ctx); + ctx->cleanup = NULL; + } + if (ctx->param != NULL) { + if (ctx->parent == NULL) + X509_VERIFY_PARAM_free(ctx->param); + ctx->param = NULL; + } + X509_policy_tree_free(ctx->tree); + ctx->tree = NULL; + sk_X509_pop_free(ctx->chain, X509_free); + ctx->chain = NULL; + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, &(ctx->ex_data)); + memset(&ctx->ex_data, 0, sizeof(ctx->ex_data)); +} + +void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth) +{ + X509_VERIFY_PARAM_set_depth(ctx->param, depth); +} + +void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags) +{ + X509_VERIFY_PARAM_set_flags(ctx->param, flags); +} + +void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags, + time_t t) +{ + X509_VERIFY_PARAM_set_time(ctx->param, t); +} + +X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx) +{ + return ctx->cert; +} + +STACK_OF(X509) *X509_STORE_CTX_get0_untrusted(X509_STORE_CTX *ctx) +{ + return ctx->untrusted; +} + +void X509_STORE_CTX_set0_untrusted(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) +{ + ctx->untrusted = sk; +} + +void X509_STORE_CTX_set0_verified_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) +{ + sk_X509_pop_free(ctx->chain, X509_free); + ctx->chain = sk; +} + +void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx, + X509_STORE_CTX_verify_cb verify_cb) +{ + ctx->verify_cb = verify_cb; +} + +X509_STORE_CTX_verify_cb X509_STORE_CTX_get_verify_cb(X509_STORE_CTX *ctx) +{ + return ctx->verify_cb; +} + +void X509_STORE_CTX_set_verify(X509_STORE_CTX *ctx, + X509_STORE_CTX_verify_fn verify) +{ + ctx->verify = verify; +} + +X509_STORE_CTX_verify_fn X509_STORE_CTX_get_verify(X509_STORE_CTX *ctx) +{ + return ctx->verify; +} + +X509_STORE_CTX_get_issuer_fn X509_STORE_CTX_get_get_issuer(X509_STORE_CTX *ctx) +{ + return ctx->get_issuer; +} + +X509_STORE_CTX_check_issued_fn X509_STORE_CTX_get_check_issued(X509_STORE_CTX *ctx) +{ + return ctx->check_issued; +} + +X509_STORE_CTX_check_revocation_fn X509_STORE_CTX_get_check_revocation(X509_STORE_CTX *ctx) +{ + return ctx->check_revocation; +} + +X509_STORE_CTX_get_crl_fn X509_STORE_CTX_get_get_crl(X509_STORE_CTX *ctx) +{ + return ctx->get_crl; +} + +X509_STORE_CTX_check_crl_fn X509_STORE_CTX_get_check_crl(X509_STORE_CTX *ctx) +{ + return ctx->check_crl; +} + +X509_STORE_CTX_cert_crl_fn X509_STORE_CTX_get_cert_crl(X509_STORE_CTX *ctx) +{ + return ctx->cert_crl; +} + +X509_STORE_CTX_check_policy_fn X509_STORE_CTX_get_check_policy(X509_STORE_CTX *ctx) +{ + return ctx->check_policy; +} + +X509_STORE_CTX_lookup_certs_fn X509_STORE_CTX_get_lookup_certs(X509_STORE_CTX *ctx) +{ + return ctx->lookup_certs; +} + +X509_STORE_CTX_lookup_crls_fn X509_STORE_CTX_get_lookup_crls(X509_STORE_CTX *ctx) +{ + return ctx->lookup_crls; +} + +X509_STORE_CTX_cleanup_fn X509_STORE_CTX_get_cleanup(X509_STORE_CTX *ctx) +{ + return ctx->cleanup; +} + +X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx) +{ + return ctx->tree; +} + +int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx) +{ + return ctx->explicit_policy; +} + +int X509_STORE_CTX_get_num_untrusted(X509_STORE_CTX *ctx) +{ + return ctx->num_untrusted; +} + +int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name) +{ + const X509_VERIFY_PARAM *param; + param = X509_VERIFY_PARAM_lookup(name); + if (!param) + return 0; + return X509_VERIFY_PARAM_inherit(ctx->param, param); +} + +X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx) +{ + return ctx->param; +} + +void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param) +{ + X509_VERIFY_PARAM_free(ctx->param); + ctx->param = param; +} + +void X509_STORE_CTX_set0_dane(X509_STORE_CTX *ctx, SSL_DANE *dane) +{ + ctx->dane = dane; +} + +static unsigned char *dane_i2d( + X509 *cert, + uint8_t selector, + unsigned int *i2dlen) +{ + unsigned char *buf = NULL; + int len; + + /* + * Extract ASN.1 DER form of certificate or public key. + */ + switch (selector) { + case DANETLS_SELECTOR_CERT: + len = i2d_X509(cert, &buf); + break; + case DANETLS_SELECTOR_SPKI: + len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), &buf); + break; + default: + X509err(X509_F_DANE_I2D, X509_R_BAD_SELECTOR); + return NULL; + } + + if (len < 0 || buf == NULL) { + X509err(X509_F_DANE_I2D, ERR_R_MALLOC_FAILURE); + return NULL; + } + + *i2dlen = (unsigned int)len; + return buf; +} + +#define DANETLS_NONE 256 /* impossible uint8_t */ + +static int dane_match(X509_STORE_CTX *ctx, X509 *cert, int depth) +{ + SSL_DANE *dane = ctx->dane; + unsigned usage = DANETLS_NONE; + unsigned selector = DANETLS_NONE; + unsigned ordinal = DANETLS_NONE; + unsigned mtype = DANETLS_NONE; + unsigned char *i2dbuf = NULL; + unsigned int i2dlen = 0; + unsigned char mdbuf[EVP_MAX_MD_SIZE]; + unsigned char *cmpbuf = NULL; + unsigned int cmplen = 0; + int i; + int recnum; + int matched = 0; + danetls_record *t = NULL; + uint32_t mask; + + mask = (depth == 0) ? DANETLS_EE_MASK : DANETLS_TA_MASK; + + /* + * The trust store is not applicable with DANE-TA(2) + */ + if (depth >= ctx->num_untrusted) + mask &= DANETLS_PKIX_MASK; + + /* + * If we've previously matched a PKIX-?? record, no need to test any + * further PKIX-?? records, it remains to just build the PKIX chain. + * Had the match been a DANE-?? record, we'd be done already. + */ + if (dane->mdpth >= 0) + mask &= ~DANETLS_PKIX_MASK; + + /*- + * https://tools.ietf.org/html/rfc7671#section-5.1 + * https://tools.ietf.org/html/rfc7671#section-5.2 + * https://tools.ietf.org/html/rfc7671#section-5.3 + * https://tools.ietf.org/html/rfc7671#section-5.4 + * + * We handle DANE-EE(3) records first as they require no chain building + * and no expiration or hostname checks. We also process digests with + * higher ordinals first and ignore lower priorities except Full(0) which + * is always processed (last). If none match, we then process PKIX-EE(1). + * + * NOTE: This relies on DANE usages sorting before the corresponding PKIX + * usages in SSL_dane_tlsa_add(), and also on descending sorting of digest + * priorities. See twin comment in ssl/ssl_lib.c. + * + * We expect that most TLSA RRsets will have just a single usage, so we + * don't go out of our way to cache multiple selector-specific i2d buffers + * across usages, but if the selector happens to remain the same as switch + * usages, that's OK. Thus, a set of "3 1 1", "3 0 1", "1 1 1", "1 0 1", + * records would result in us generating each of the certificate and public + * key DER forms twice, but more typically we'd just see multiple "3 1 1" + * or multiple "3 0 1" records. + * + * As soon as we find a match at any given depth, we stop, because either + * we've matched a DANE-?? record and the peer is authenticated, or, after + * exhausting all DANE-?? records, we've matched a PKIX-?? record, which is + * sufficient for DANE, and what remains to do is ordinary PKIX validation. + */ + recnum = (dane->umask & mask) ? sk_danetls_record_num(dane->trecs) : 0; + for (i = 0; matched == 0 && i < recnum; ++i) { + t = sk_danetls_record_value(dane->trecs, i); + if ((DANETLS_USAGE_BIT(t->usage) & mask) == 0) + continue; + if (t->usage != usage) { + usage = t->usage; + + /* Reset digest agility for each usage/selector pair */ + mtype = DANETLS_NONE; + ordinal = dane->dctx->mdord[t->mtype]; + } + if (t->selector != selector) { + selector = t->selector; + + /* Update per-selector state */ + OPENSSL_free(i2dbuf); + i2dbuf = dane_i2d(cert, selector, &i2dlen); + if (i2dbuf == NULL) + return -1; + + /* Reset digest agility for each usage/selector pair */ + mtype = DANETLS_NONE; + ordinal = dane->dctx->mdord[t->mtype]; + } else if (t->mtype != DANETLS_MATCHING_FULL) { + /*- + * Digest agility: + * + * + * + * For a fixed selector, after processing all records with the + * highest mtype ordinal, ignore all mtypes with lower ordinals + * other than "Full". + */ + if (dane->dctx->mdord[t->mtype] < ordinal) + continue; + } + + /* + * Each time we hit a (new selector or) mtype, re-compute the relevant + * digest, more complex caching is not worth the code space. + */ + if (t->mtype != mtype) { + const EVP_MD *md = dane->dctx->mdevp[mtype = t->mtype]; + cmpbuf = i2dbuf; + cmplen = i2dlen; + + if (md != NULL) { + cmpbuf = mdbuf; + if (!EVP_Digest(i2dbuf, i2dlen, cmpbuf, &cmplen, md, 0)) { + matched = -1; + break; + } + } + } + + /* + * Squirrel away the certificate and depth if we have a match. Any + * DANE match is dispositive, but with PKIX we still need to build a + * full chain. + */ + if (cmplen == t->dlen && + memcmp(cmpbuf, t->data, cmplen) == 0) { + if (DANETLS_USAGE_BIT(usage) & DANETLS_DANE_MASK) + matched = 1; + if (matched || dane->mdpth < 0) { + dane->mdpth = depth; + dane->mtlsa = t; + OPENSSL_free(dane->mcert); + dane->mcert = cert; + X509_up_ref(cert); + } + break; + } + } + + /* Clear the one-element DER cache */ + OPENSSL_free(i2dbuf); + return matched; +} + +static int check_dane_issuer(X509_STORE_CTX *ctx, int depth) +{ + SSL_DANE *dane = ctx->dane; + int matched = 0; + X509 *cert; + + if (!DANETLS_HAS_TA(dane) || depth == 0) + return X509_TRUST_UNTRUSTED; + + /* + * Record any DANE trust-anchor matches, for the first depth to test, if + * there's one at that depth. (This'll be false for length 1 chains looking + * for an exact match for the leaf certificate). + */ + cert = sk_X509_value(ctx->chain, depth); + if (cert != NULL && (matched = dane_match(ctx, cert, depth)) < 0) + return X509_TRUST_REJECTED; + if (matched > 0) { + ctx->num_untrusted = depth - 1; + return X509_TRUST_TRUSTED; + } + + return X509_TRUST_UNTRUSTED; +} + +static int check_dane_pkeys(X509_STORE_CTX *ctx) +{ + SSL_DANE *dane = ctx->dane; + danetls_record *t; + int num = ctx->num_untrusted; + X509 *cert = sk_X509_value(ctx->chain, num - 1); + int recnum = sk_danetls_record_num(dane->trecs); + int i; + + for (i = 0; i < recnum; ++i) { + t = sk_danetls_record_value(dane->trecs, i); + if (t->usage != DANETLS_USAGE_DANE_TA || + t->selector != DANETLS_SELECTOR_SPKI || + t->mtype != DANETLS_MATCHING_FULL || + X509_verify(cert, t->spki) <= 0) + continue; + + /* Clear any PKIX-?? matches that failed to extend to a full chain */ + X509_free(dane->mcert); + dane->mcert = NULL; + + /* Record match via a bare TA public key */ + ctx->bare_ta_signed = 1; + dane->mdpth = num - 1; + dane->mtlsa = t; + + /* Prune any excess chain certificates */ + num = sk_X509_num(ctx->chain); + for (; num > ctx->num_untrusted; --num) + X509_free(sk_X509_pop(ctx->chain)); + + return X509_TRUST_TRUSTED; + } + + return X509_TRUST_UNTRUSTED; +} + +static void dane_reset(SSL_DANE *dane) +{ + /* + * Reset state to verify another chain, or clear after failure. + */ + X509_free(dane->mcert); + dane->mcert = NULL; + dane->mtlsa = NULL; + dane->mdpth = -1; + dane->pdpth = -1; +} + +static int check_leaf_suiteb(X509_STORE_CTX *ctx, X509 *cert) +{ + int err = X509_chain_check_suiteb(NULL, cert, NULL, ctx->param->flags); + + if (err == X509_V_OK) + return 1; + return verify_cb_cert(ctx, cert, 0, err); +} + +static int dane_verify(X509_STORE_CTX *ctx) +{ + X509 *cert = ctx->cert; + SSL_DANE *dane = ctx->dane; + int matched; + int done; + + dane_reset(dane); + + /*- + * When testing the leaf certificate, if we match a DANE-EE(3) record, + * dane_match() returns 1 and we're done. If however we match a PKIX-EE(1) + * record, the match depth and matching TLSA record are recorded, but the + * return value is 0, because we still need to find a PKIX trust-anchor. + * Therefore, when DANE authentication is enabled (required), we're done + * if: + * + matched < 0, internal error. + * + matched == 1, we matched a DANE-EE(3) record + * + matched == 0, mdepth < 0 (no PKIX-EE match) and there are no + * DANE-TA(2) or PKIX-TA(0) to test. + */ + matched = dane_match(ctx, ctx->cert, 0); + done = matched != 0 || (!DANETLS_HAS_TA(dane) && dane->mdpth < 0); + + if (done) + X509_get_pubkey_parameters(NULL, ctx->chain); + + if (matched > 0) { + /* Callback invoked as needed */ + if (!check_leaf_suiteb(ctx, cert)) + return 0; + /* Callback invoked as needed */ + if ((dane->flags & DANE_FLAG_NO_DANE_EE_NAMECHECKS) == 0 && + !check_id(ctx)) + return 0; + /* Bypass internal_verify(), issue depth 0 success callback */ + ctx->error_depth = 0; + ctx->current_cert = cert; + return ctx->verify_cb(1, ctx); + } + + if (matched < 0) { + ctx->error_depth = 0; + ctx->current_cert = cert; + ctx->error = X509_V_ERR_OUT_OF_MEM; + return -1; + } + + if (done) { + /* Fail early, TA-based success is not possible */ + if (!check_leaf_suiteb(ctx, cert)) + return 0; + return verify_cb_cert(ctx, cert, 0, X509_V_ERR_DANE_NO_MATCH); + } + + /* + * Chain verification for usages 0/1/2. TLSA record matching of depth > 0 + * certificates happens in-line with building the rest of the chain. + */ + return verify_chain(ctx); +} + +/* Get issuer, without duplicate suppression */ +static int get_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *cert) +{ + STACK_OF(X509) *saved_chain = ctx->chain; + int ok; + + ctx->chain = NULL; + ok = ctx->get_issuer(issuer, ctx, cert); + ctx->chain = saved_chain; + + return ok; +} + +static int build_chain(X509_STORE_CTX *ctx) +{ + SSL_DANE *dane = ctx->dane; + int num = sk_X509_num(ctx->chain); + X509 *cert = sk_X509_value(ctx->chain, num - 1); + int ss = cert_self_signed(cert); + STACK_OF(X509) *sktmp = NULL; + unsigned int search; + int may_trusted = 0; + int may_alternate = 0; + int trust = X509_TRUST_UNTRUSTED; + int alt_untrusted = 0; + int depth; + int ok = 0; + int i; + + /* Our chain starts with a single untrusted element. */ + if (!ossl_assert(num == 1 && ctx->num_untrusted == num)) { + X509err(X509_F_BUILD_CHAIN, ERR_R_INTERNAL_ERROR); + ctx->error = X509_V_ERR_UNSPECIFIED; + return 0; + } + +#define S_DOUNTRUSTED (1 << 0) /* Search untrusted chain */ +#define S_DOTRUSTED (1 << 1) /* Search trusted store */ +#define S_DOALTERNATE (1 << 2) /* Retry with pruned alternate chain */ + /* + * Set up search policy, untrusted if possible, trusted-first if enabled. + * If we're doing DANE and not doing PKIX-TA/PKIX-EE, we never look in the + * trust_store, otherwise we might look there first. If not trusted-first, + * and alternate chains are not disabled, try building an alternate chain + * if no luck with untrusted first. + */ + search = (ctx->untrusted != NULL) ? S_DOUNTRUSTED : 0; + if (DANETLS_HAS_PKIX(dane) || !DANETLS_HAS_DANE(dane)) { + if (search == 0 || ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) + search |= S_DOTRUSTED; + else if (!(ctx->param->flags & X509_V_FLAG_NO_ALT_CHAINS)) + may_alternate = 1; + may_trusted = 1; + } + + /* + * Shallow-copy the stack of untrusted certificates (with TLS, this is + * typically the content of the peer's certificate message) so can make + * multiple passes over it, while free to remove elements as we go. + */ + if (ctx->untrusted && (sktmp = sk_X509_dup(ctx->untrusted)) == NULL) { + X509err(X509_F_BUILD_CHAIN, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + return 0; + } + + /* + * If we got any "DANE-TA(2) Cert(0) Full(0)" trust-anchors from DNS, add + * them to our working copy of the untrusted certificate stack. Since the + * caller of X509_STORE_CTX_init() may have provided only a leaf cert with + * no corresponding stack of untrusted certificates, we may need to create + * an empty stack first. [ At present only the ssl library provides DANE + * support, and ssl_verify_cert_chain() always provides a non-null stack + * containing at least the leaf certificate, but we must be prepared for + * this to change. ] + */ + if (DANETLS_ENABLED(dane) && dane->certs != NULL) { + if (sktmp == NULL && (sktmp = sk_X509_new_null()) == NULL) { + X509err(X509_F_BUILD_CHAIN, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + return 0; + } + for (i = 0; i < sk_X509_num(dane->certs); ++i) { + if (!sk_X509_push(sktmp, sk_X509_value(dane->certs, i))) { + sk_X509_free(sktmp); + X509err(X509_F_BUILD_CHAIN, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + return 0; + } + } + } + + /* + * Still absurdly large, but arithmetically safe, a lower hard upper bound + * might be reasonable. + */ + if (ctx->param->depth > INT_MAX/2) + ctx->param->depth = INT_MAX/2; + + /* + * Try to Extend the chain until we reach an ultimately trusted issuer. + * Build chains up to one longer the limit, later fail if we hit the limit, + * with an X509_V_ERR_CERT_CHAIN_TOO_LONG error code. + */ + depth = ctx->param->depth + 1; + + while (search != 0) { + X509 *x; + X509 *xtmp = NULL; + + /* + * Look in the trust store if enabled for first lookup, or we've run + * out of untrusted issuers and search here is not disabled. When we + * reach the depth limit, we stop extending the chain, if by that point + * we've not found a trust-anchor, any trusted chain would be too long. + * + * The error reported to the application verify callback is at the + * maximal valid depth with the current certificate equal to the last + * not ultimately-trusted issuer. For example, with verify_depth = 0, + * the callback will report errors at depth=1 when the immediate issuer + * of the leaf certificate is not a trust anchor. No attempt will be + * made to locate an issuer for that certificate, since such a chain + * would be a-priori too long. + */ + if ((search & S_DOTRUSTED) != 0) { + i = num = sk_X509_num(ctx->chain); + if ((search & S_DOALTERNATE) != 0) { + /* + * As high up the chain as we can, look for an alternative + * trusted issuer of an untrusted certificate that currently + * has an untrusted issuer. We use the alt_untrusted variable + * to track how far up the chain we find the first match. It + * is only if and when we find a match, that we prune the chain + * and reset ctx->num_untrusted to the reduced count of + * untrusted certificates. While we're searching for such a + * match (which may never be found), it is neither safe nor + * wise to preemptively modify either the chain or + * ctx->num_untrusted. + * + * Note, like ctx->num_untrusted, alt_untrusted is a count of + * untrusted certificates, not a "depth". + */ + i = alt_untrusted; + } + x = sk_X509_value(ctx->chain, i-1); + + ok = (depth < num) ? 0 : get_issuer(&xtmp, ctx, x); + + if (ok < 0) { + trust = X509_TRUST_REJECTED; + ctx->error = X509_V_ERR_STORE_LOOKUP; + search = 0; + continue; + } + + if (ok > 0) { + /* + * Alternative trusted issuer for a mid-chain untrusted cert? + * Pop the untrusted cert's successors and retry. We might now + * be able to complete a valid chain via the trust store. Note + * that despite the current trust-store match we might still + * fail complete the chain to a suitable trust-anchor, in which + * case we may prune some more untrusted certificates and try + * again. Thus the S_DOALTERNATE bit may yet be turned on + * again with an even shorter untrusted chain! + * + * If in the process we threw away our matching PKIX-TA trust + * anchor, reset DANE trust. We might find a suitable trusted + * certificate among the ones from the trust store. + */ + if ((search & S_DOALTERNATE) != 0) { + if (!ossl_assert(num > i && i > 0 && ss == 0)) { + X509err(X509_F_BUILD_CHAIN, ERR_R_INTERNAL_ERROR); + X509_free(xtmp); + trust = X509_TRUST_REJECTED; + ctx->error = X509_V_ERR_UNSPECIFIED; + search = 0; + continue; + } + search &= ~S_DOALTERNATE; + for (; num > i; --num) + X509_free(sk_X509_pop(ctx->chain)); + ctx->num_untrusted = num; + + if (DANETLS_ENABLED(dane) && + dane->mdpth >= ctx->num_untrusted) { + dane->mdpth = -1; + X509_free(dane->mcert); + dane->mcert = NULL; + } + if (DANETLS_ENABLED(dane) && + dane->pdpth >= ctx->num_untrusted) + dane->pdpth = -1; + } + + /* + * Self-signed untrusted certificates get replaced by their + * trusted matching issuer. Otherwise, grow the chain. + */ + if (ss == 0) { + if (!sk_X509_push(ctx->chain, x = xtmp)) { + X509_free(xtmp); + X509err(X509_F_BUILD_CHAIN, ERR_R_MALLOC_FAILURE); + trust = X509_TRUST_REJECTED; + ctx->error = X509_V_ERR_OUT_OF_MEM; + search = 0; + continue; + } + ss = cert_self_signed(x); + } else if (num == ctx->num_untrusted) { + /* + * We have a self-signed certificate that has the same + * subject name (and perhaps keyid and/or serial number) as + * a trust-anchor. We must have an exact match to avoid + * possible impersonation via key substitution etc. + */ + if (X509_cmp(x, xtmp) != 0) { + /* Self-signed untrusted mimic. */ + X509_free(xtmp); + ok = 0; + } else { + X509_free(x); + ctx->num_untrusted = --num; + (void) sk_X509_set(ctx->chain, num, x = xtmp); + } + } + + /* + * We've added a new trusted certificate to the chain, recheck + * trust. If not done, and not self-signed look deeper. + * Whether or not we're doing "trusted first", we no longer + * look for untrusted certificates from the peer's chain. + * + * At this point ctx->num_trusted and num must reflect the + * correct number of untrusted certificates, since the DANE + * logic in check_trust() depends on distinguishing CAs from + * "the wire" from CAs from the trust store. In particular, the + * certificate at depth "num" should be the new trusted + * certificate with ctx->num_untrusted <= num. + */ + if (ok) { + if (!ossl_assert(ctx->num_untrusted <= num)) { + X509err(X509_F_BUILD_CHAIN, ERR_R_INTERNAL_ERROR); + trust = X509_TRUST_REJECTED; + ctx->error = X509_V_ERR_UNSPECIFIED; + search = 0; + continue; + } + search &= ~S_DOUNTRUSTED; + switch (trust = check_trust(ctx, num)) { + case X509_TRUST_TRUSTED: + case X509_TRUST_REJECTED: + search = 0; + continue; + } + if (ss == 0) + continue; + } + } + + /* + * No dispositive decision, and either self-signed or no match, if + * we were doing untrusted-first, and alt-chains are not disabled, + * do that, by repeatedly losing one untrusted element at a time, + * and trying to extend the shorted chain. + */ + if ((search & S_DOUNTRUSTED) == 0) { + /* Continue search for a trusted issuer of a shorter chain? */ + if ((search & S_DOALTERNATE) != 0 && --alt_untrusted > 0) + continue; + /* Still no luck and no fallbacks left? */ + if (!may_alternate || (search & S_DOALTERNATE) != 0 || + ctx->num_untrusted < 2) + break; + /* Search for a trusted issuer of a shorter chain */ + search |= S_DOALTERNATE; + alt_untrusted = ctx->num_untrusted - 1; + ss = 0; + } + } + + /* + * Extend chain with peer-provided certificates + */ + if ((search & S_DOUNTRUSTED) != 0) { + num = sk_X509_num(ctx->chain); + if (!ossl_assert(num == ctx->num_untrusted)) { + X509err(X509_F_BUILD_CHAIN, ERR_R_INTERNAL_ERROR); + trust = X509_TRUST_REJECTED; + ctx->error = X509_V_ERR_UNSPECIFIED; + search = 0; + continue; + } + x = sk_X509_value(ctx->chain, num-1); + + /* + * Once we run out of untrusted issuers, we stop looking for more + * and start looking only in the trust store if enabled. + */ + xtmp = (ss || depth < num) ? NULL : find_issuer(ctx, sktmp, x); + if (xtmp == NULL) { + search &= ~S_DOUNTRUSTED; + if (may_trusted) + search |= S_DOTRUSTED; + continue; + } + + /* Drop this issuer from future consideration */ + (void) sk_X509_delete_ptr(sktmp, xtmp); + + if (!sk_X509_push(ctx->chain, xtmp)) { + X509err(X509_F_BUILD_CHAIN, ERR_R_MALLOC_FAILURE); + trust = X509_TRUST_REJECTED; + ctx->error = X509_V_ERR_OUT_OF_MEM; + search = 0; + continue; + } + + X509_up_ref(x = xtmp); + ++ctx->num_untrusted; + ss = cert_self_signed(xtmp); + + /* + * Check for DANE-TA trust of the topmost untrusted certificate. + */ + switch (trust = check_dane_issuer(ctx, ctx->num_untrusted - 1)) { + case X509_TRUST_TRUSTED: + case X509_TRUST_REJECTED: + search = 0; + continue; + } + } + } + sk_X509_free(sktmp); + + /* + * Last chance to make a trusted chain, either bare DANE-TA public-key + * signers, or else direct leaf PKIX trust. + */ + num = sk_X509_num(ctx->chain); + if (num <= depth) { + if (trust == X509_TRUST_UNTRUSTED && DANETLS_HAS_DANE_TA(dane)) + trust = check_dane_pkeys(ctx); + if (trust == X509_TRUST_UNTRUSTED && num == ctx->num_untrusted) + trust = check_trust(ctx, num); + } + + switch (trust) { + case X509_TRUST_TRUSTED: + return 1; + case X509_TRUST_REJECTED: + /* Callback already issued */ + return 0; + case X509_TRUST_UNTRUSTED: + default: + num = sk_X509_num(ctx->chain); + if (num > depth) + return verify_cb_cert(ctx, NULL, num-1, + X509_V_ERR_CERT_CHAIN_TOO_LONG); + if (DANETLS_ENABLED(dane) && + (!DANETLS_HAS_PKIX(dane) || dane->pdpth >= 0)) + return verify_cb_cert(ctx, NULL, num-1, X509_V_ERR_DANE_NO_MATCH); + if (ss && sk_X509_num(ctx->chain) == 1) + return verify_cb_cert(ctx, NULL, num-1, + X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT); + if (ss) + return verify_cb_cert(ctx, NULL, num-1, + X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN); + if (ctx->num_untrusted < num) + return verify_cb_cert(ctx, NULL, num-1, + X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT); + return verify_cb_cert(ctx, NULL, num-1, + X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY); + } +} + +static const int minbits_table[] = { 80, 112, 128, 192, 256 }; +static const int NUM_AUTH_LEVELS = OSSL_NELEM(minbits_table); + +/* + * Check whether the public key of ``cert`` meets the security level of + * ``ctx``. + * + * Returns 1 on success, 0 otherwise. + */ +static int check_key_level(X509_STORE_CTX *ctx, X509 *cert) +{ + EVP_PKEY *pkey = X509_get0_pubkey(cert); + int level = ctx->param->auth_level; + + /* + * At security level zero, return without checking for a supported public + * key type. Some engines support key types not understood outside the + * engine, and we only need to understand the key when enforcing a security + * floor. + */ + if (level <= 0) + return 1; + + /* Unsupported or malformed keys are not secure */ + if (pkey == NULL) + return 0; + + if (level > NUM_AUTH_LEVELS) + level = NUM_AUTH_LEVELS; + + return EVP_PKEY_security_bits(pkey) >= minbits_table[level - 1]; +} + +/* + * Check whether the signature digest algorithm of ``cert`` meets the security + * level of ``ctx``. Should not be checked for trust anchors (whether + * self-signed or otherwise). + * + * Returns 1 on success, 0 otherwise. + */ +static int check_sig_level(X509_STORE_CTX *ctx, X509 *cert) +{ + int secbits = -1; + int level = ctx->param->auth_level; + + if (level <= 0) + return 1; + if (level > NUM_AUTH_LEVELS) + level = NUM_AUTH_LEVELS; + + if (!X509_get_signature_info(cert, NULL, NULL, &secbits, NULL)) + return 0; + + return secbits >= minbits_table[level - 1]; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_vpm.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_vpm.c new file mode 100644 index 000000000..aea186295 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509_vpm.c @@ -0,0 +1,602 @@ +/* + * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "internal/x509_int.h" + +#include "x509_lcl.h" + +/* X509_VERIFY_PARAM functions */ + +#define SET_HOST 0 +#define ADD_HOST 1 + +static char *str_copy(const char *s) +{ + return OPENSSL_strdup(s); +} + +static void str_free(char *s) +{ + OPENSSL_free(s); +} + +static int int_x509_param_set_hosts(X509_VERIFY_PARAM *vpm, int mode, + const char *name, size_t namelen) +{ + char *copy; + + /* + * Refuse names with embedded NUL bytes, except perhaps as final byte. + * XXX: Do we need to push an error onto the error stack? + */ + if (namelen == 0 || name == NULL) + namelen = name ? strlen(name) : 0; + else if (name && memchr(name, '\0', namelen > 1 ? namelen - 1 : namelen)) + return 0; + if (namelen > 0 && name[namelen - 1] == '\0') + --namelen; + + if (mode == SET_HOST) { + sk_OPENSSL_STRING_pop_free(vpm->hosts, str_free); + vpm->hosts = NULL; + } + if (name == NULL || namelen == 0) + return 1; + + copy = OPENSSL_strndup(name, namelen); + if (copy == NULL) + return 0; + + if (vpm->hosts == NULL && + (vpm->hosts = sk_OPENSSL_STRING_new_null()) == NULL) { + OPENSSL_free(copy); + return 0; + } + + if (!sk_OPENSSL_STRING_push(vpm->hosts, copy)) { + OPENSSL_free(copy); + if (sk_OPENSSL_STRING_num(vpm->hosts) == 0) { + sk_OPENSSL_STRING_free(vpm->hosts); + vpm->hosts = NULL; + } + return 0; + } + + return 1; +} + + +X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void) +{ + X509_VERIFY_PARAM *param; + + param = OPENSSL_zalloc(sizeof(*param)); + if (param == NULL) { + X509err(X509_F_X509_VERIFY_PARAM_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + param->trust = X509_TRUST_DEFAULT; + /* param->inh_flags = X509_VP_FLAG_DEFAULT; */ + param->depth = -1; + param->auth_level = -1; /* -1 means unset, 0 is explicit */ + return param; +} + +void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param) +{ + if (param == NULL) + return; + sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free); + sk_OPENSSL_STRING_pop_free(param->hosts, str_free); + OPENSSL_free(param->peername); + OPENSSL_free(param->email); + OPENSSL_free(param->ip); + OPENSSL_free(param); +} + +/*- + * This function determines how parameters are "inherited" from one structure + * to another. There are several different ways this can happen. + * + * 1. If a child structure needs to have its values initialized from a parent + * they are simply copied across. For example SSL_CTX copied to SSL. + * 2. If the structure should take on values only if they are currently unset. + * For example the values in an SSL structure will take appropriate value + * for SSL servers or clients but only if the application has not set new + * ones. + * + * The "inh_flags" field determines how this function behaves. + * + * Normally any values which are set in the default are not copied from the + * destination and verify flags are ORed together. + * + * If X509_VP_FLAG_DEFAULT is set then anything set in the source is copied + * to the destination. Effectively the values in "to" become default values + * which will be used only if nothing new is set in "from". + * + * If X509_VP_FLAG_OVERWRITE is set then all value are copied across whether + * they are set or not. Flags is still Ored though. + * + * If X509_VP_FLAG_RESET_FLAGS is set then the flags value is copied instead + * of ORed. + * + * If X509_VP_FLAG_LOCKED is set then no values are copied. + * + * If X509_VP_FLAG_ONCE is set then the current inh_flags setting is zeroed + * after the next call. + */ + +/* Macro to test if a field should be copied from src to dest */ + +#define test_x509_verify_param_copy(field, def) \ + (to_overwrite || \ + ((src->field != def) && (to_default || (dest->field == def)))) + +/* Macro to test and copy a field if necessary */ + +#define x509_verify_param_copy(field, def) \ + if (test_x509_verify_param_copy(field, def)) \ + dest->field = src->field + +int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest, + const X509_VERIFY_PARAM *src) +{ + unsigned long inh_flags; + int to_default, to_overwrite; + if (!src) + return 1; + inh_flags = dest->inh_flags | src->inh_flags; + + if (inh_flags & X509_VP_FLAG_ONCE) + dest->inh_flags = 0; + + if (inh_flags & X509_VP_FLAG_LOCKED) + return 1; + + if (inh_flags & X509_VP_FLAG_DEFAULT) + to_default = 1; + else + to_default = 0; + + if (inh_flags & X509_VP_FLAG_OVERWRITE) + to_overwrite = 1; + else + to_overwrite = 0; + + x509_verify_param_copy(purpose, 0); + x509_verify_param_copy(trust, X509_TRUST_DEFAULT); + x509_verify_param_copy(depth, -1); + x509_verify_param_copy(auth_level, -1); + + /* If overwrite or check time not set, copy across */ + + if (to_overwrite || !(dest->flags & X509_V_FLAG_USE_CHECK_TIME)) { + dest->check_time = src->check_time; + dest->flags &= ~X509_V_FLAG_USE_CHECK_TIME; + /* Don't need to copy flag: that is done below */ + } + + if (inh_flags & X509_VP_FLAG_RESET_FLAGS) + dest->flags = 0; + + dest->flags |= src->flags; + + if (test_x509_verify_param_copy(policies, NULL)) { + if (!X509_VERIFY_PARAM_set1_policies(dest, src->policies)) + return 0; + } + + /* Copy the host flags if and only if we're copying the host list */ + if (test_x509_verify_param_copy(hosts, NULL)) { + sk_OPENSSL_STRING_pop_free(dest->hosts, str_free); + dest->hosts = NULL; + if (src->hosts) { + dest->hosts = + sk_OPENSSL_STRING_deep_copy(src->hosts, str_copy, str_free); + if (dest->hosts == NULL) + return 0; + dest->hostflags = src->hostflags; + } + } + + if (test_x509_verify_param_copy(email, NULL)) { + if (!X509_VERIFY_PARAM_set1_email(dest, src->email, src->emaillen)) + return 0; + } + + if (test_x509_verify_param_copy(ip, NULL)) { + if (!X509_VERIFY_PARAM_set1_ip(dest, src->ip, src->iplen)) + return 0; + } + + return 1; +} + +int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to, + const X509_VERIFY_PARAM *from) +{ + unsigned long save_flags = to->inh_flags; + int ret; + to->inh_flags |= X509_VP_FLAG_DEFAULT; + ret = X509_VERIFY_PARAM_inherit(to, from); + to->inh_flags = save_flags; + return ret; +} + +static int int_x509_param_set1(char **pdest, size_t *pdestlen, + const char *src, size_t srclen) +{ + void *tmp; + if (src) { + if (srclen == 0) + srclen = strlen(src); + + tmp = OPENSSL_memdup(src, srclen); + if (tmp == NULL) + return 0; + } else { + tmp = NULL; + srclen = 0; + } + OPENSSL_free(*pdest); + *pdest = tmp; + if (pdestlen != NULL) + *pdestlen = srclen; + return 1; +} + +int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name) +{ + OPENSSL_free(param->name); + param->name = OPENSSL_strdup(name); + if (param->name) + return 1; + return 0; +} + +int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags) +{ + param->flags |= flags; + if (flags & X509_V_FLAG_POLICY_MASK) + param->flags |= X509_V_FLAG_POLICY_CHECK; + return 1; +} + +int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param, + unsigned long flags) +{ + param->flags &= ~flags; + return 1; +} + +unsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param) +{ + return param->flags; +} + +uint32_t X509_VERIFY_PARAM_get_inh_flags(const X509_VERIFY_PARAM *param) +{ + return param->inh_flags; +} + +int X509_VERIFY_PARAM_set_inh_flags(X509_VERIFY_PARAM *param, uint32_t flags) +{ + param->inh_flags = flags; + return 1; +} + +int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose) +{ + return X509_PURPOSE_set(¶m->purpose, purpose); +} + +int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust) +{ + return X509_TRUST_set(¶m->trust, trust); +} + +void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth) +{ + param->depth = depth; +} + +void X509_VERIFY_PARAM_set_auth_level(X509_VERIFY_PARAM *param, int auth_level) +{ + param->auth_level = auth_level; +} + +time_t X509_VERIFY_PARAM_get_time(const X509_VERIFY_PARAM *param) +{ + return param->check_time; +} + +void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t) +{ + param->check_time = t; + param->flags |= X509_V_FLAG_USE_CHECK_TIME; +} + +int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param, + ASN1_OBJECT *policy) +{ + if (!param->policies) { + param->policies = sk_ASN1_OBJECT_new_null(); + if (!param->policies) + return 0; + } + if (!sk_ASN1_OBJECT_push(param->policies, policy)) + return 0; + return 1; +} + +int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param, + STACK_OF(ASN1_OBJECT) *policies) +{ + int i; + ASN1_OBJECT *oid, *doid; + + if (!param) + return 0; + sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free); + + if (!policies) { + param->policies = NULL; + return 1; + } + + param->policies = sk_ASN1_OBJECT_new_null(); + if (!param->policies) + return 0; + + for (i = 0; i < sk_ASN1_OBJECT_num(policies); i++) { + oid = sk_ASN1_OBJECT_value(policies, i); + doid = OBJ_dup(oid); + if (!doid) + return 0; + if (!sk_ASN1_OBJECT_push(param->policies, doid)) { + ASN1_OBJECT_free(doid); + return 0; + } + } + param->flags |= X509_V_FLAG_POLICY_CHECK; + return 1; +} + +int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param, + const char *name, size_t namelen) +{ + return int_x509_param_set_hosts(param, SET_HOST, name, namelen); +} + +int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param, + const char *name, size_t namelen) +{ + return int_x509_param_set_hosts(param, ADD_HOST, name, namelen); +} + +void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param, + unsigned int flags) +{ + param->hostflags = flags; +} + +unsigned int X509_VERIFY_PARAM_get_hostflags(const X509_VERIFY_PARAM *param) +{ + return param->hostflags; +} + +char *X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *param) +{ + return param->peername; +} + +/* + * Move peername from one param structure to another, freeing any name present + * at the target. If the source is a NULL parameter structure, free and zero + * the target peername. + */ +void X509_VERIFY_PARAM_move_peername(X509_VERIFY_PARAM *to, + X509_VERIFY_PARAM *from) +{ + char *peername = (from != NULL) ? from->peername : NULL; + + if (to->peername != peername) { + OPENSSL_free(to->peername); + to->peername = peername; + } + if (from) + from->peername = NULL; +} + +int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, + const char *email, size_t emaillen) +{ + return int_x509_param_set1(¶m->email, ¶m->emaillen, + email, emaillen); +} + +int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, + const unsigned char *ip, size_t iplen) +{ + if (iplen != 0 && iplen != 4 && iplen != 16) + return 0; + return int_x509_param_set1((char **)¶m->ip, ¶m->iplen, + (char *)ip, iplen); +} + +int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc) +{ + unsigned char ipout[16]; + size_t iplen; + + iplen = (size_t)a2i_ipadd(ipout, ipasc); + if (iplen == 0) + return 0; + return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen); +} + +int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param) +{ + return param->depth; +} + +int X509_VERIFY_PARAM_get_auth_level(const X509_VERIFY_PARAM *param) +{ + return param->auth_level; +} + +const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param) +{ + return param->name; +} + +#define vpm_empty_id NULL, 0U, NULL, NULL, 0, NULL, 0 + +/* + * Default verify parameters: these are used for various applications and can + * be overridden by the user specified table. NB: the 'name' field *must* be + * in alphabetical order because it will be searched using OBJ_search. + */ + +static const X509_VERIFY_PARAM default_table[] = { + { + "default", /* X509 default parameters */ + 0, /* Check time */ + 0, /* internal flags */ + X509_V_FLAG_TRUSTED_FIRST, /* flags */ + 0, /* purpose */ + 0, /* trust */ + 100, /* depth */ + -1, /* auth_level */ + NULL, /* policies */ + vpm_empty_id}, + { + "pkcs7", /* S/MIME sign parameters */ + 0, /* Check time */ + 0, /* internal flags */ + 0, /* flags */ + X509_PURPOSE_SMIME_SIGN, /* purpose */ + X509_TRUST_EMAIL, /* trust */ + -1, /* depth */ + -1, /* auth_level */ + NULL, /* policies */ + vpm_empty_id}, + { + "smime_sign", /* S/MIME sign parameters */ + 0, /* Check time */ + 0, /* internal flags */ + 0, /* flags */ + X509_PURPOSE_SMIME_SIGN, /* purpose */ + X509_TRUST_EMAIL, /* trust */ + -1, /* depth */ + -1, /* auth_level */ + NULL, /* policies */ + vpm_empty_id}, + { + "ssl_client", /* SSL/TLS client parameters */ + 0, /* Check time */ + 0, /* internal flags */ + 0, /* flags */ + X509_PURPOSE_SSL_CLIENT, /* purpose */ + X509_TRUST_SSL_CLIENT, /* trust */ + -1, /* depth */ + -1, /* auth_level */ + NULL, /* policies */ + vpm_empty_id}, + { + "ssl_server", /* SSL/TLS server parameters */ + 0, /* Check time */ + 0, /* internal flags */ + 0, /* flags */ + X509_PURPOSE_SSL_SERVER, /* purpose */ + X509_TRUST_SSL_SERVER, /* trust */ + -1, /* depth */ + -1, /* auth_level */ + NULL, /* policies */ + vpm_empty_id} +}; + +static STACK_OF(X509_VERIFY_PARAM) *param_table = NULL; + +static int table_cmp(const X509_VERIFY_PARAM *a, const X509_VERIFY_PARAM *b) +{ + return strcmp(a->name, b->name); +} + +DECLARE_OBJ_BSEARCH_CMP_FN(X509_VERIFY_PARAM, X509_VERIFY_PARAM, table); +IMPLEMENT_OBJ_BSEARCH_CMP_FN(X509_VERIFY_PARAM, X509_VERIFY_PARAM, table); + +static int param_cmp(const X509_VERIFY_PARAM *const *a, + const X509_VERIFY_PARAM *const *b) +{ + return strcmp((*a)->name, (*b)->name); +} + +int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param) +{ + int idx; + X509_VERIFY_PARAM *ptmp; + if (param_table == NULL) { + param_table = sk_X509_VERIFY_PARAM_new(param_cmp); + if (param_table == NULL) + return 0; + } else { + idx = sk_X509_VERIFY_PARAM_find(param_table, param); + if (idx >= 0) { + ptmp = sk_X509_VERIFY_PARAM_delete(param_table, idx); + X509_VERIFY_PARAM_free(ptmp); + } + } + if (!sk_X509_VERIFY_PARAM_push(param_table, param)) + return 0; + return 1; +} + +int X509_VERIFY_PARAM_get_count(void) +{ + int num = OSSL_NELEM(default_table); + if (param_table) + num += sk_X509_VERIFY_PARAM_num(param_table); + return num; +} + +const X509_VERIFY_PARAM *X509_VERIFY_PARAM_get0(int id) +{ + int num = OSSL_NELEM(default_table); + if (id < num) + return default_table + id; + return sk_X509_VERIFY_PARAM_value(param_table, id - num); +} + +const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name) +{ + int idx; + X509_VERIFY_PARAM pm; + + pm.name = (char *)name; + if (param_table != NULL) { + idx = sk_X509_VERIFY_PARAM_find(param_table, &pm); + if (idx >= 0) + return sk_X509_VERIFY_PARAM_value(param_table, idx); + } + return OBJ_bsearch_table(&pm, default_table, OSSL_NELEM(default_table)); +} + +void X509_VERIFY_PARAM_table_cleanup(void) +{ + sk_X509_VERIFY_PARAM_pop_free(param_table, X509_VERIFY_PARAM_free); + param_table = NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509cset.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509cset.c new file mode 100644 index 000000000..7645ce375 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509cset.c @@ -0,0 +1,183 @@ +/* + * Copyright 2001-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include "internal/refcount.h" +#include +#include +#include +#include +#include "internal/x509_int.h" + +int X509_CRL_set_version(X509_CRL *x, long version) +{ + if (x == NULL) + return 0; + if (x->crl.version == NULL) { + if ((x->crl.version = ASN1_INTEGER_new()) == NULL) + return 0; + } + return ASN1_INTEGER_set(x->crl.version, version); +} + +int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name) +{ + if (x == NULL) + return 0; + return X509_NAME_set(&x->crl.issuer, name); +} + +int X509_CRL_set1_lastUpdate(X509_CRL *x, const ASN1_TIME *tm) +{ + if (x == NULL) + return 0; + return x509_set1_time(&x->crl.lastUpdate, tm); +} + +int X509_CRL_set1_nextUpdate(X509_CRL *x, const ASN1_TIME *tm) +{ + if (x == NULL) + return 0; + return x509_set1_time(&x->crl.nextUpdate, tm); +} + +int X509_CRL_sort(X509_CRL *c) +{ + int i; + X509_REVOKED *r; + /* + * sort the data so it will be written in serial number order + */ + sk_X509_REVOKED_sort(c->crl.revoked); + for (i = 0; i < sk_X509_REVOKED_num(c->crl.revoked); i++) { + r = sk_X509_REVOKED_value(c->crl.revoked, i); + r->sequence = i; + } + c->crl.enc.modified = 1; + return 1; +} + +int X509_CRL_up_ref(X509_CRL *crl) +{ + int i; + + if (CRYPTO_UP_REF(&crl->references, &i, crl->lock) <= 0) + return 0; + + REF_PRINT_COUNT("X509_CRL", crl); + REF_ASSERT_ISNT(i < 2); + return ((i > 1) ? 1 : 0); +} + +long X509_CRL_get_version(const X509_CRL *crl) +{ + return ASN1_INTEGER_get(crl->crl.version); +} + +const ASN1_TIME *X509_CRL_get0_lastUpdate(const X509_CRL *crl) +{ + return crl->crl.lastUpdate; +} + +const ASN1_TIME *X509_CRL_get0_nextUpdate(const X509_CRL *crl) +{ + return crl->crl.nextUpdate; +} + +#if OPENSSL_API_COMPAT < 0x10100000L +ASN1_TIME *X509_CRL_get_lastUpdate(X509_CRL *crl) +{ + return crl->crl.lastUpdate; +} + +ASN1_TIME *X509_CRL_get_nextUpdate(X509_CRL *crl) +{ + return crl->crl.nextUpdate; +} +#endif + +X509_NAME *X509_CRL_get_issuer(const X509_CRL *crl) +{ + return crl->crl.issuer; +} + +const STACK_OF(X509_EXTENSION) *X509_CRL_get0_extensions(const X509_CRL *crl) +{ + return crl->crl.extensions; +} + +STACK_OF(X509_REVOKED) *X509_CRL_get_REVOKED(X509_CRL *crl) +{ + return crl->crl.revoked; +} + +void X509_CRL_get0_signature(const X509_CRL *crl, const ASN1_BIT_STRING **psig, + const X509_ALGOR **palg) +{ + if (psig != NULL) + *psig = &crl->signature; + if (palg != NULL) + *palg = &crl->sig_alg; +} + +int X509_CRL_get_signature_nid(const X509_CRL *crl) +{ + return OBJ_obj2nid(crl->sig_alg.algorithm); +} + +const ASN1_TIME *X509_REVOKED_get0_revocationDate(const X509_REVOKED *x) +{ + return x->revocationDate; +} + +int X509_REVOKED_set_revocationDate(X509_REVOKED *x, ASN1_TIME *tm) +{ + ASN1_TIME *in; + + if (x == NULL) + return 0; + in = x->revocationDate; + if (in != tm) { + in = ASN1_STRING_dup(tm); + if (in != NULL) { + ASN1_TIME_free(x->revocationDate); + x->revocationDate = in; + } + } + return (in != NULL); +} + +const ASN1_INTEGER *X509_REVOKED_get0_serialNumber(const X509_REVOKED *x) +{ + return &x->serialNumber; +} + +int X509_REVOKED_set_serialNumber(X509_REVOKED *x, ASN1_INTEGER *serial) +{ + ASN1_INTEGER *in; + + if (x == NULL) + return 0; + in = &x->serialNumber; + if (in != serial) + return ASN1_STRING_copy(in, serial); + return 1; +} + +const STACK_OF(X509_EXTENSION) *X509_REVOKED_get0_extensions(const X509_REVOKED *r) +{ + return r->extensions; +} + +int i2d_re_X509_CRL_tbs(X509_CRL *crl, unsigned char **pp) +{ + crl->crl.enc.modified = 1; + return i2d_X509_CRL_INFO(&crl->crl, pp); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509name.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509name.c new file mode 100644 index 000000000..64a73e793 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509name.c @@ -0,0 +1,360 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include "internal/x509_int.h" + +int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len) +{ + ASN1_OBJECT *obj; + + obj = OBJ_nid2obj(nid); + if (obj == NULL) + return -1; + return X509_NAME_get_text_by_OBJ(name, obj, buf, len); +} + +int X509_NAME_get_text_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, + char *buf, int len) +{ + int i; + const ASN1_STRING *data; + + i = X509_NAME_get_index_by_OBJ(name, obj, -1); + if (i < 0) + return -1; + data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i)); + if (buf == NULL) + return data->length; + if (len <= 0) + return 0; + i = (data->length > (len - 1)) ? (len - 1) : data->length; + memcpy(buf, data->data, i); + buf[i] = '\0'; + return i; +} + +int X509_NAME_entry_count(const X509_NAME *name) +{ + if (name == NULL) + return 0; + return sk_X509_NAME_ENTRY_num(name->entries); +} + +int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos) +{ + ASN1_OBJECT *obj; + + obj = OBJ_nid2obj(nid); + if (obj == NULL) + return -2; + return X509_NAME_get_index_by_OBJ(name, obj, lastpos); +} + +/* NOTE: you should be passing -1, not 0 as lastpos */ +int X509_NAME_get_index_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, int lastpos) +{ + int n; + X509_NAME_ENTRY *ne; + STACK_OF(X509_NAME_ENTRY) *sk; + + if (name == NULL) + return -1; + if (lastpos < 0) + lastpos = -1; + sk = name->entries; + n = sk_X509_NAME_ENTRY_num(sk); + for (lastpos++; lastpos < n; lastpos++) { + ne = sk_X509_NAME_ENTRY_value(sk, lastpos); + if (OBJ_cmp(ne->object, obj) == 0) + return lastpos; + } + return -1; +} + +X509_NAME_ENTRY *X509_NAME_get_entry(const X509_NAME *name, int loc) +{ + if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc + || loc < 0) + return NULL; + + return sk_X509_NAME_ENTRY_value(name->entries, loc); +} + +X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc) +{ + X509_NAME_ENTRY *ret; + int i, n, set_prev, set_next; + STACK_OF(X509_NAME_ENTRY) *sk; + + if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc + || loc < 0) + return NULL; + + sk = name->entries; + ret = sk_X509_NAME_ENTRY_delete(sk, loc); + n = sk_X509_NAME_ENTRY_num(sk); + name->modified = 1; + if (loc == n) + return ret; + + /* else we need to fixup the set field */ + if (loc != 0) + set_prev = (sk_X509_NAME_ENTRY_value(sk, loc - 1))->set; + else + set_prev = ret->set - 1; + set_next = sk_X509_NAME_ENTRY_value(sk, loc)->set; + + /*- + * set_prev is the previous set + * set is the current set + * set_next is the following + * prev 1 1 1 1 1 1 1 1 + * set 1 1 2 2 + * next 1 1 2 2 2 2 3 2 + * so basically only if prev and next differ by 2, then + * re-number down by 1 + */ + if (set_prev + 1 < set_next) + for (i = loc; i < n; i++) + sk_X509_NAME_ENTRY_value(sk, i)->set--; + return ret; +} + +int X509_NAME_add_entry_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, int len, int loc, + int set) +{ + X509_NAME_ENTRY *ne; + int ret; + + ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len); + if (!ne) + return 0; + ret = X509_NAME_add_entry(name, ne, loc, set); + X509_NAME_ENTRY_free(ne); + return ret; +} + +int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type, + const unsigned char *bytes, int len, int loc, + int set) +{ + X509_NAME_ENTRY *ne; + int ret; + ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len); + if (!ne) + return 0; + ret = X509_NAME_add_entry(name, ne, loc, set); + X509_NAME_ENTRY_free(ne); + return ret; +} + +int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type, + const unsigned char *bytes, int len, int loc, + int set) +{ + X509_NAME_ENTRY *ne; + int ret; + ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len); + if (!ne) + return 0; + ret = X509_NAME_add_entry(name, ne, loc, set); + X509_NAME_ENTRY_free(ne); + return ret; +} + +/* + * if set is -1, append to previous set, 0 'a new one', and 1, prepend to the + * guy we are about to stomp on. + */ +int X509_NAME_add_entry(X509_NAME *name, const X509_NAME_ENTRY *ne, int loc, + int set) +{ + X509_NAME_ENTRY *new_name = NULL; + int n, i, inc; + STACK_OF(X509_NAME_ENTRY) *sk; + + if (name == NULL) + return 0; + sk = name->entries; + n = sk_X509_NAME_ENTRY_num(sk); + if (loc > n) + loc = n; + else if (loc < 0) + loc = n; + inc = (set == 0); + name->modified = 1; + + if (set == -1) { + if (loc == 0) { + set = 0; + inc = 1; + } else { + set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set; + } + } else { /* if (set >= 0) */ + + if (loc >= n) { + if (loc != 0) + set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set + 1; + else + set = 0; + } else + set = sk_X509_NAME_ENTRY_value(sk, loc)->set; + } + + /* + * X509_NAME_ENTRY_dup is ASN1 generated code, that can't be easily + * const'ified; harmless cast since dup() don't modify its input. + */ + if ((new_name = X509_NAME_ENTRY_dup((X509_NAME_ENTRY *)ne)) == NULL) + goto err; + new_name->set = set; + if (!sk_X509_NAME_ENTRY_insert(sk, new_name, loc)) { + X509err(X509_F_X509_NAME_ADD_ENTRY, ERR_R_MALLOC_FAILURE); + goto err; + } + if (inc) { + n = sk_X509_NAME_ENTRY_num(sk); + for (i = loc + 1; i < n; i++) + sk_X509_NAME_ENTRY_value(sk, i)->set += 1; + } + return 1; + err: + X509_NAME_ENTRY_free(new_name); + return 0; +} + +X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne, + const char *field, int type, + const unsigned char *bytes, + int len) +{ + ASN1_OBJECT *obj; + X509_NAME_ENTRY *nentry; + + obj = OBJ_txt2obj(field, 0); + if (obj == NULL) { + X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_TXT, + X509_R_INVALID_FIELD_NAME); + ERR_add_error_data(2, "name=", field); + return NULL; + } + nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len); + ASN1_OBJECT_free(obj); + return nentry; +} + +X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid, + int type, + const unsigned char *bytes, + int len) +{ + ASN1_OBJECT *obj; + X509_NAME_ENTRY *nentry; + + obj = OBJ_nid2obj(nid); + if (obj == NULL) { + X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_NID, X509_R_UNKNOWN_NID); + return NULL; + } + nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len); + ASN1_OBJECT_free(obj); + return nentry; +} + +X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne, + const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, + int len) +{ + X509_NAME_ENTRY *ret; + + if ((ne == NULL) || (*ne == NULL)) { + if ((ret = X509_NAME_ENTRY_new()) == NULL) + return NULL; + } else + ret = *ne; + + if (!X509_NAME_ENTRY_set_object(ret, obj)) + goto err; + if (!X509_NAME_ENTRY_set_data(ret, type, bytes, len)) + goto err; + + if ((ne != NULL) && (*ne == NULL)) + *ne = ret; + return ret; + err: + if ((ne == NULL) || (ret != *ne)) + X509_NAME_ENTRY_free(ret); + return NULL; +} + +int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, const ASN1_OBJECT *obj) +{ + if ((ne == NULL) || (obj == NULL)) { + X509err(X509_F_X509_NAME_ENTRY_SET_OBJECT, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + ASN1_OBJECT_free(ne->object); + ne->object = OBJ_dup(obj); + return ((ne->object == NULL) ? 0 : 1); +} + +int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type, + const unsigned char *bytes, int len) +{ + int i; + + if ((ne == NULL) || ((bytes == NULL) && (len != 0))) + return 0; + if ((type > 0) && (type & MBSTRING_FLAG)) + return ASN1_STRING_set_by_NID(&ne->value, bytes, + len, type, + OBJ_obj2nid(ne->object)) ? 1 : 0; + if (len < 0) + len = strlen((const char *)bytes); + i = ASN1_STRING_set(ne->value, bytes, len); + if (!i) + return 0; + if (type != V_ASN1_UNDEF) { + if (type == V_ASN1_APP_CHOOSE) + ne->value->type = ASN1_PRINTABLE_type(bytes, len); + else + ne->value->type = type; + } + return 1; +} + +ASN1_OBJECT *X509_NAME_ENTRY_get_object(const X509_NAME_ENTRY *ne) +{ + if (ne == NULL) + return NULL; + return ne->object; +} + +ASN1_STRING *X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY *ne) +{ + if (ne == NULL) + return NULL; + return ne->value; +} + +int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne) +{ + return ne->set; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509rset.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509rset.c new file mode 100644 index 000000000..e8921b82a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509rset.c @@ -0,0 +1,40 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "internal/x509_int.h" + +int X509_REQ_set_version(X509_REQ *x, long version) +{ + if (x == NULL) + return 0; + x->req_info.enc.modified = 1; + return ASN1_INTEGER_set(x->req_info.version, version); +} + +int X509_REQ_set_subject_name(X509_REQ *x, X509_NAME *name) +{ + if (x == NULL) + return 0; + x->req_info.enc.modified = 1; + return X509_NAME_set(&x->req_info.subject, name); +} + +int X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey) +{ + if (x == NULL) + return 0; + x->req_info.enc.modified = 1; + return X509_PUBKEY_set(&x->req_info.pubkey, pkey); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509spki.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509spki.c new file mode 100644 index 000000000..fd8162af6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509spki.c @@ -0,0 +1,75 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include + +int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey) +{ + if ((x == NULL) || (x->spkac == NULL)) + return 0; + return X509_PUBKEY_set(&(x->spkac->pubkey), pkey); +} + +EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *x) +{ + if ((x == NULL) || (x->spkac == NULL)) + return NULL; + return X509_PUBKEY_get(x->spkac->pubkey); +} + +/* Load a Netscape SPKI from a base64 encoded string */ + +NETSCAPE_SPKI *NETSCAPE_SPKI_b64_decode(const char *str, int len) +{ + unsigned char *spki_der; + const unsigned char *p; + int spki_len; + NETSCAPE_SPKI *spki; + if (len <= 0) + len = strlen(str); + if ((spki_der = OPENSSL_malloc(len + 1)) == NULL) { + X509err(X509_F_NETSCAPE_SPKI_B64_DECODE, ERR_R_MALLOC_FAILURE); + return NULL; + } + spki_len = EVP_DecodeBlock(spki_der, (const unsigned char *)str, len); + if (spki_len < 0) { + X509err(X509_F_NETSCAPE_SPKI_B64_DECODE, X509_R_BASE64_DECODE_ERROR); + OPENSSL_free(spki_der); + return NULL; + } + p = spki_der; + spki = d2i_NETSCAPE_SPKI(NULL, &p, spki_len); + OPENSSL_free(spki_der); + return spki; +} + +/* Generate a base64 encoded string from an SPKI */ + +char *NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *spki) +{ + unsigned char *der_spki, *p; + char *b64_str; + int der_len; + der_len = i2d_NETSCAPE_SPKI(spki, NULL); + der_spki = OPENSSL_malloc(der_len); + b64_str = OPENSSL_malloc(der_len * 2); + if (der_spki == NULL || b64_str == NULL) { + X509err(X509_F_NETSCAPE_SPKI_B64_ENCODE, ERR_R_MALLOC_FAILURE); + OPENSSL_free(der_spki); + OPENSSL_free(b64_str); + return NULL; + } + p = der_spki; + i2d_NETSCAPE_SPKI(spki, &p); + EVP_EncodeBlock((unsigned char *)b64_str, der_spki, der_len); + OPENSSL_free(der_spki); + return b64_str; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509type.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509type.c new file mode 100644 index 000000000..0e33b424b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x509type.c @@ -0,0 +1,84 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include + +int X509_certificate_type(const X509 *x, const EVP_PKEY *pkey) +{ + const EVP_PKEY *pk; + int ret = 0, i; + + if (x == NULL) + return 0; + + if (pkey == NULL) + pk = X509_get0_pubkey(x); + else + pk = pkey; + + if (pk == NULL) + return 0; + + switch (EVP_PKEY_id(pk)) { + case EVP_PKEY_RSA: + ret = EVP_PK_RSA | EVP_PKT_SIGN; +/* if (!sign only extension) */ + ret |= EVP_PKT_ENC; + break; + case EVP_PKEY_RSA_PSS: + ret = EVP_PK_RSA | EVP_PKT_SIGN; + break; + case EVP_PKEY_DSA: + ret = EVP_PK_DSA | EVP_PKT_SIGN; + break; + case EVP_PKEY_EC: + ret = EVP_PK_EC | EVP_PKT_SIGN | EVP_PKT_EXCH; + break; + case EVP_PKEY_ED448: + case EVP_PKEY_ED25519: + ret = EVP_PKT_SIGN; + break; + case EVP_PKEY_DH: + ret = EVP_PK_DH | EVP_PKT_EXCH; + break; + case NID_id_GostR3410_2001: + case NID_id_GostR3410_2012_256: + case NID_id_GostR3410_2012_512: + ret = EVP_PKT_EXCH | EVP_PKT_SIGN; + break; + default: + break; + } + + i = X509_get_signature_nid(x); + if (i && OBJ_find_sigid_algs(i, NULL, &i)) { + + switch (i) { + case NID_rsaEncryption: + case NID_rsa: + ret |= EVP_PKS_RSA; + break; + case NID_dsa: + case NID_dsa_2: + ret |= EVP_PKS_DSA; + break; + case NID_X9_62_id_ecPublicKey: + ret |= EVP_PKS_EC; + break; + default: + break; + } + } + + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_all.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_all.c new file mode 100644 index 000000000..24e411460 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_all.c @@ -0,0 +1,525 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "internal/x509_int.h" +#include +#include +#include +#include + +int X509_verify(X509 *a, EVP_PKEY *r) +{ + if (X509_ALGOR_cmp(&a->sig_alg, &a->cert_info.signature)) + return 0; + return (ASN1_item_verify(ASN1_ITEM_rptr(X509_CINF), &a->sig_alg, + &a->signature, &a->cert_info, r)); +} + +int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r) +{ + return (ASN1_item_verify(ASN1_ITEM_rptr(X509_REQ_INFO), + &a->sig_alg, a->signature, &a->req_info, r)); +} + +int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *a, EVP_PKEY *r) +{ + return (ASN1_item_verify(ASN1_ITEM_rptr(NETSCAPE_SPKAC), + &a->sig_algor, a->signature, a->spkac, r)); +} + +int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md) +{ + x->cert_info.enc.modified = 1; + return (ASN1_item_sign(ASN1_ITEM_rptr(X509_CINF), &x->cert_info.signature, + &x->sig_alg, &x->signature, &x->cert_info, pkey, + md)); +} + +int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx) +{ + x->cert_info.enc.modified = 1; + return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CINF), + &x->cert_info.signature, + &x->sig_alg, &x->signature, &x->cert_info, ctx); +} + +#ifndef OPENSSL_NO_OCSP +int X509_http_nbio(OCSP_REQ_CTX *rctx, X509 **pcert) +{ + return OCSP_REQ_CTX_nbio_d2i(rctx, + (ASN1_VALUE **)pcert, ASN1_ITEM_rptr(X509)); +} +#endif + +int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md) +{ + return (ASN1_item_sign(ASN1_ITEM_rptr(X509_REQ_INFO), &x->sig_alg, NULL, + x->signature, &x->req_info, pkey, md)); +} + +int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx) +{ + return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_REQ_INFO), + &x->sig_alg, NULL, x->signature, &x->req_info, + ctx); +} + +int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md) +{ + x->crl.enc.modified = 1; + return (ASN1_item_sign(ASN1_ITEM_rptr(X509_CRL_INFO), &x->crl.sig_alg, + &x->sig_alg, &x->signature, &x->crl, pkey, md)); +} + +int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx) +{ + x->crl.enc.modified = 1; + return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CRL_INFO), + &x->crl.sig_alg, &x->sig_alg, &x->signature, + &x->crl, ctx); +} + +#ifndef OPENSSL_NO_OCSP +int X509_CRL_http_nbio(OCSP_REQ_CTX *rctx, X509_CRL **pcrl) +{ + return OCSP_REQ_CTX_nbio_d2i(rctx, + (ASN1_VALUE **)pcrl, + ASN1_ITEM_rptr(X509_CRL)); +} +#endif + +int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md) +{ + return (ASN1_item_sign(ASN1_ITEM_rptr(NETSCAPE_SPKAC), &x->sig_algor, NULL, + x->signature, x->spkac, pkey, md)); +} + +#ifndef OPENSSL_NO_STDIO +X509 *d2i_X509_fp(FILE *fp, X509 **x509) +{ + return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509), fp, x509); +} + +int i2d_X509_fp(FILE *fp, X509 *x509) +{ + return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509), fp, x509); +} +#endif + +X509 *d2i_X509_bio(BIO *bp, X509 **x509) +{ + return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509), bp, x509); +} + +int i2d_X509_bio(BIO *bp, X509 *x509) +{ + return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509), bp, x509); +} + +#ifndef OPENSSL_NO_STDIO +X509_CRL *d2i_X509_CRL_fp(FILE *fp, X509_CRL **crl) +{ + return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_CRL), fp, crl); +} + +int i2d_X509_CRL_fp(FILE *fp, X509_CRL *crl) +{ + return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_CRL), fp, crl); +} +#endif + +X509_CRL *d2i_X509_CRL_bio(BIO *bp, X509_CRL **crl) +{ + return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_CRL), bp, crl); +} + +int i2d_X509_CRL_bio(BIO *bp, X509_CRL *crl) +{ + return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_CRL), bp, crl); +} + +#ifndef OPENSSL_NO_STDIO +PKCS7 *d2i_PKCS7_fp(FILE *fp, PKCS7 **p7) +{ + return ASN1_item_d2i_fp(ASN1_ITEM_rptr(PKCS7), fp, p7); +} + +int i2d_PKCS7_fp(FILE *fp, PKCS7 *p7) +{ + return ASN1_item_i2d_fp(ASN1_ITEM_rptr(PKCS7), fp, p7); +} +#endif + +PKCS7 *d2i_PKCS7_bio(BIO *bp, PKCS7 **p7) +{ + return ASN1_item_d2i_bio(ASN1_ITEM_rptr(PKCS7), bp, p7); +} + +int i2d_PKCS7_bio(BIO *bp, PKCS7 *p7) +{ + return ASN1_item_i2d_bio(ASN1_ITEM_rptr(PKCS7), bp, p7); +} + +#ifndef OPENSSL_NO_STDIO +X509_REQ *d2i_X509_REQ_fp(FILE *fp, X509_REQ **req) +{ + return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_REQ), fp, req); +} + +int i2d_X509_REQ_fp(FILE *fp, X509_REQ *req) +{ + return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_REQ), fp, req); +} +#endif + +X509_REQ *d2i_X509_REQ_bio(BIO *bp, X509_REQ **req) +{ + return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_REQ), bp, req); +} + +int i2d_X509_REQ_bio(BIO *bp, X509_REQ *req) +{ + return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_REQ), bp, req); +} + +#ifndef OPENSSL_NO_RSA + +# ifndef OPENSSL_NO_STDIO +RSA *d2i_RSAPrivateKey_fp(FILE *fp, RSA **rsa) +{ + return ASN1_item_d2i_fp(ASN1_ITEM_rptr(RSAPrivateKey), fp, rsa); +} + +int i2d_RSAPrivateKey_fp(FILE *fp, RSA *rsa) +{ + return ASN1_item_i2d_fp(ASN1_ITEM_rptr(RSAPrivateKey), fp, rsa); +} + +RSA *d2i_RSAPublicKey_fp(FILE *fp, RSA **rsa) +{ + return ASN1_item_d2i_fp(ASN1_ITEM_rptr(RSAPublicKey), fp, rsa); +} + +RSA *d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa) +{ + return ASN1_d2i_fp((void *(*)(void)) + RSA_new, (D2I_OF(void)) d2i_RSA_PUBKEY, fp, + (void **)rsa); +} + +int i2d_RSAPublicKey_fp(FILE *fp, RSA *rsa) +{ + return ASN1_item_i2d_fp(ASN1_ITEM_rptr(RSAPublicKey), fp, rsa); +} + +int i2d_RSA_PUBKEY_fp(FILE *fp, RSA *rsa) +{ + return ASN1_i2d_fp((I2D_OF(void))i2d_RSA_PUBKEY, fp, rsa); +} +# endif + +RSA *d2i_RSAPrivateKey_bio(BIO *bp, RSA **rsa) +{ + return ASN1_item_d2i_bio(ASN1_ITEM_rptr(RSAPrivateKey), bp, rsa); +} + +int i2d_RSAPrivateKey_bio(BIO *bp, RSA *rsa) +{ + return ASN1_item_i2d_bio(ASN1_ITEM_rptr(RSAPrivateKey), bp, rsa); +} + +RSA *d2i_RSAPublicKey_bio(BIO *bp, RSA **rsa) +{ + return ASN1_item_d2i_bio(ASN1_ITEM_rptr(RSAPublicKey), bp, rsa); +} + +RSA *d2i_RSA_PUBKEY_bio(BIO *bp, RSA **rsa) +{ + return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSA_PUBKEY, bp, rsa); +} + +int i2d_RSAPublicKey_bio(BIO *bp, RSA *rsa) +{ + return ASN1_item_i2d_bio(ASN1_ITEM_rptr(RSAPublicKey), bp, rsa); +} + +int i2d_RSA_PUBKEY_bio(BIO *bp, RSA *rsa) +{ + return ASN1_i2d_bio_of(RSA, i2d_RSA_PUBKEY, bp, rsa); +} +#endif + +#ifndef OPENSSL_NO_DSA +# ifndef OPENSSL_NO_STDIO +DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa) +{ + return ASN1_d2i_fp_of(DSA, DSA_new, d2i_DSAPrivateKey, fp, dsa); +} + +int i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa) +{ + return ASN1_i2d_fp_of_const(DSA, i2d_DSAPrivateKey, fp, dsa); +} + +DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa) +{ + return ASN1_d2i_fp_of(DSA, DSA_new, d2i_DSA_PUBKEY, fp, dsa); +} + +int i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa) +{ + return ASN1_i2d_fp_of(DSA, i2d_DSA_PUBKEY, fp, dsa); +} +# endif + +DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa) +{ + return ASN1_d2i_bio_of(DSA, DSA_new, d2i_DSAPrivateKey, bp, dsa); +} + +int i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa) +{ + return ASN1_i2d_bio_of_const(DSA, i2d_DSAPrivateKey, bp, dsa); +} + +DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa) +{ + return ASN1_d2i_bio_of(DSA, DSA_new, d2i_DSA_PUBKEY, bp, dsa); +} + +int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa) +{ + return ASN1_i2d_bio_of(DSA, i2d_DSA_PUBKEY, bp, dsa); +} + +#endif + +#ifndef OPENSSL_NO_EC +# ifndef OPENSSL_NO_STDIO +EC_KEY *d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey) +{ + return ASN1_d2i_fp_of(EC_KEY, EC_KEY_new, d2i_EC_PUBKEY, fp, eckey); +} + +int i2d_EC_PUBKEY_fp(FILE *fp, EC_KEY *eckey) +{ + return ASN1_i2d_fp_of(EC_KEY, i2d_EC_PUBKEY, fp, eckey); +} + +EC_KEY *d2i_ECPrivateKey_fp(FILE *fp, EC_KEY **eckey) +{ + return ASN1_d2i_fp_of(EC_KEY, EC_KEY_new, d2i_ECPrivateKey, fp, eckey); +} + +int i2d_ECPrivateKey_fp(FILE *fp, EC_KEY *eckey) +{ + return ASN1_i2d_fp_of(EC_KEY, i2d_ECPrivateKey, fp, eckey); +} +# endif +EC_KEY *d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **eckey) +{ + return ASN1_d2i_bio_of(EC_KEY, EC_KEY_new, d2i_EC_PUBKEY, bp, eckey); +} + +int i2d_EC_PUBKEY_bio(BIO *bp, EC_KEY *ecdsa) +{ + return ASN1_i2d_bio_of(EC_KEY, i2d_EC_PUBKEY, bp, ecdsa); +} + +EC_KEY *d2i_ECPrivateKey_bio(BIO *bp, EC_KEY **eckey) +{ + return ASN1_d2i_bio_of(EC_KEY, EC_KEY_new, d2i_ECPrivateKey, bp, eckey); +} + +int i2d_ECPrivateKey_bio(BIO *bp, EC_KEY *eckey) +{ + return ASN1_i2d_bio_of(EC_KEY, i2d_ECPrivateKey, bp, eckey); +} +#endif + +int X509_pubkey_digest(const X509 *data, const EVP_MD *type, + unsigned char *md, unsigned int *len) +{ + ASN1_BIT_STRING *key; + key = X509_get0_pubkey_bitstr(data); + if (!key) + return 0; + return EVP_Digest(key->data, key->length, md, len, type, NULL); +} + +int X509_digest(const X509 *data, const EVP_MD *type, unsigned char *md, + unsigned int *len) +{ + if (type == EVP_sha1() && (data->ex_flags & EXFLAG_SET) != 0) { + /* Asking for SHA1 and we already computed it. */ + if (len != NULL) + *len = sizeof(data->sha1_hash); + memcpy(md, data->sha1_hash, sizeof(data->sha1_hash)); + return 1; + } + return (ASN1_item_digest + (ASN1_ITEM_rptr(X509), type, (char *)data, md, len)); +} + +int X509_CRL_digest(const X509_CRL *data, const EVP_MD *type, + unsigned char *md, unsigned int *len) +{ + if (type == EVP_sha1() && (data->flags & EXFLAG_SET) != 0) { + /* Asking for SHA1; always computed in CRL d2i. */ + if (len != NULL) + *len = sizeof(data->sha1_hash); + memcpy(md, data->sha1_hash, sizeof(data->sha1_hash)); + return 1; + } + return (ASN1_item_digest + (ASN1_ITEM_rptr(X509_CRL), type, (char *)data, md, len)); +} + +int X509_REQ_digest(const X509_REQ *data, const EVP_MD *type, + unsigned char *md, unsigned int *len) +{ + return (ASN1_item_digest + (ASN1_ITEM_rptr(X509_REQ), type, (char *)data, md, len)); +} + +int X509_NAME_digest(const X509_NAME *data, const EVP_MD *type, + unsigned char *md, unsigned int *len) +{ + return (ASN1_item_digest + (ASN1_ITEM_rptr(X509_NAME), type, (char *)data, md, len)); +} + +int PKCS7_ISSUER_AND_SERIAL_digest(PKCS7_ISSUER_AND_SERIAL *data, + const EVP_MD *type, unsigned char *md, + unsigned int *len) +{ + return (ASN1_item_digest(ASN1_ITEM_rptr(PKCS7_ISSUER_AND_SERIAL), type, + (char *)data, md, len)); +} + +#ifndef OPENSSL_NO_STDIO +X509_SIG *d2i_PKCS8_fp(FILE *fp, X509_SIG **p8) +{ + return ASN1_d2i_fp_of(X509_SIG, X509_SIG_new, d2i_X509_SIG, fp, p8); +} + +int i2d_PKCS8_fp(FILE *fp, X509_SIG *p8) +{ + return ASN1_i2d_fp_of(X509_SIG, i2d_X509_SIG, fp, p8); +} +#endif + +X509_SIG *d2i_PKCS8_bio(BIO *bp, X509_SIG **p8) +{ + return ASN1_d2i_bio_of(X509_SIG, X509_SIG_new, d2i_X509_SIG, bp, p8); +} + +int i2d_PKCS8_bio(BIO *bp, X509_SIG *p8) +{ + return ASN1_i2d_bio_of(X509_SIG, i2d_X509_SIG, bp, p8); +} + +#ifndef OPENSSL_NO_STDIO +PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, + PKCS8_PRIV_KEY_INFO **p8inf) +{ + return ASN1_d2i_fp_of(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_new, + d2i_PKCS8_PRIV_KEY_INFO, fp, p8inf); +} + +int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, PKCS8_PRIV_KEY_INFO *p8inf) +{ + return ASN1_i2d_fp_of(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO, fp, + p8inf); +} + +int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key) +{ + PKCS8_PRIV_KEY_INFO *p8inf; + int ret; + p8inf = EVP_PKEY2PKCS8(key); + if (!p8inf) + return 0; + ret = i2d_PKCS8_PRIV_KEY_INFO_fp(fp, p8inf); + PKCS8_PRIV_KEY_INFO_free(p8inf); + return ret; +} + +int i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *pkey) +{ + return ASN1_i2d_fp_of(EVP_PKEY, i2d_PrivateKey, fp, pkey); +} + +EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a) +{ + return ASN1_d2i_fp_of(EVP_PKEY, EVP_PKEY_new, d2i_AutoPrivateKey, fp, a); +} + +int i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey) +{ + return ASN1_i2d_fp_of(EVP_PKEY, i2d_PUBKEY, fp, pkey); +} + +EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a) +{ + return ASN1_d2i_fp_of(EVP_PKEY, EVP_PKEY_new, d2i_PUBKEY, fp, a); +} + +#endif + +PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, + PKCS8_PRIV_KEY_INFO **p8inf) +{ + return ASN1_d2i_bio_of(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_new, + d2i_PKCS8_PRIV_KEY_INFO, bp, p8inf); +} + +int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, PKCS8_PRIV_KEY_INFO *p8inf) +{ + return ASN1_i2d_bio_of(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO, bp, + p8inf); +} + +int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key) +{ + PKCS8_PRIV_KEY_INFO *p8inf; + int ret; + p8inf = EVP_PKEY2PKCS8(key); + if (!p8inf) + return 0; + ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf); + PKCS8_PRIV_KEY_INFO_free(p8inf); + return ret; +} + +int i2d_PrivateKey_bio(BIO *bp, EVP_PKEY *pkey) +{ + return ASN1_i2d_bio_of(EVP_PKEY, i2d_PrivateKey, bp, pkey); +} + +EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a) +{ + return ASN1_d2i_bio_of(EVP_PKEY, EVP_PKEY_new, d2i_AutoPrivateKey, bp, a); +} + +int i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey) +{ + return ASN1_i2d_bio_of(EVP_PKEY, i2d_PUBKEY, bp, pkey); +} + +EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a) +{ + return ASN1_d2i_bio_of(EVP_PKEY, EVP_PKEY_new, d2i_PUBKEY, bp, a); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_attrib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_attrib.c new file mode 100644 index 000000000..9a41e547c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_attrib.c @@ -0,0 +1,55 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include "x509_lcl.h" + +/*- + * X509_ATTRIBUTE: this has the following form: + * + * typedef struct x509_attributes_st + * { + * ASN1_OBJECT *object; + * STACK_OF(ASN1_TYPE) *set; + * } X509_ATTRIBUTE; + * + */ + +ASN1_SEQUENCE(X509_ATTRIBUTE) = { + ASN1_SIMPLE(X509_ATTRIBUTE, object, ASN1_OBJECT), + ASN1_SET_OF(X509_ATTRIBUTE, set, ASN1_ANY) +} ASN1_SEQUENCE_END(X509_ATTRIBUTE) + +IMPLEMENT_ASN1_FUNCTIONS(X509_ATTRIBUTE) +IMPLEMENT_ASN1_DUP_FUNCTION(X509_ATTRIBUTE) + +X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value) +{ + X509_ATTRIBUTE *ret = NULL; + ASN1_TYPE *val = NULL; + + if ((ret = X509_ATTRIBUTE_new()) == NULL) + return NULL; + ret->object = OBJ_nid2obj(nid); + if ((val = ASN1_TYPE_new()) == NULL) + goto err; + if (!sk_ASN1_TYPE_push(ret->set, val)) + goto err; + + ASN1_TYPE_set(val, atrtype, value); + return ret; + err: + X509_ATTRIBUTE_free(ret); + ASN1_TYPE_free(val); + return NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_crl.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_crl.c new file mode 100644 index 000000000..12ab3cca4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_crl.c @@ -0,0 +1,478 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include "internal/x509_int.h" +#include +#include "x509_lcl.h" + +static int X509_REVOKED_cmp(const X509_REVOKED *const *a, + const X509_REVOKED *const *b); +static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp); + +ASN1_SEQUENCE(X509_REVOKED) = { + ASN1_EMBED(X509_REVOKED,serialNumber, ASN1_INTEGER), + ASN1_SIMPLE(X509_REVOKED,revocationDate, ASN1_TIME), + ASN1_SEQUENCE_OF_OPT(X509_REVOKED,extensions, X509_EXTENSION) +} ASN1_SEQUENCE_END(X509_REVOKED) + +static int def_crl_verify(X509_CRL *crl, EVP_PKEY *r); +static int def_crl_lookup(X509_CRL *crl, + X509_REVOKED **ret, ASN1_INTEGER *serial, + X509_NAME *issuer); + +static X509_CRL_METHOD int_crl_meth = { + 0, + 0, 0, + def_crl_lookup, + def_crl_verify +}; + +static const X509_CRL_METHOD *default_crl_method = &int_crl_meth; + +/* + * The X509_CRL_INFO structure needs a bit of customisation. Since we cache + * the original encoding the signature won't be affected by reordering of the + * revoked field. + */ +static int crl_inf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + X509_CRL_INFO *a = (X509_CRL_INFO *)*pval; + + if (!a || !a->revoked) + return 1; + switch (operation) { + /* + * Just set cmp function here. We don't sort because that would + * affect the output of X509_CRL_print(). + */ + case ASN1_OP_D2I_POST: + (void)sk_X509_REVOKED_set_cmp_func(a->revoked, X509_REVOKED_cmp); + break; + } + return 1; +} + + +ASN1_SEQUENCE_enc(X509_CRL_INFO, enc, crl_inf_cb) = { + ASN1_OPT(X509_CRL_INFO, version, ASN1_INTEGER), + ASN1_EMBED(X509_CRL_INFO, sig_alg, X509_ALGOR), + ASN1_SIMPLE(X509_CRL_INFO, issuer, X509_NAME), + ASN1_SIMPLE(X509_CRL_INFO, lastUpdate, ASN1_TIME), + ASN1_OPT(X509_CRL_INFO, nextUpdate, ASN1_TIME), + ASN1_SEQUENCE_OF_OPT(X509_CRL_INFO, revoked, X509_REVOKED), + ASN1_EXP_SEQUENCE_OF_OPT(X509_CRL_INFO, extensions, X509_EXTENSION, 0) +} ASN1_SEQUENCE_END_enc(X509_CRL_INFO, X509_CRL_INFO) + +/* + * Set CRL entry issuer according to CRL certificate issuer extension. Check + * for unhandled critical CRL entry extensions. + */ + +static int crl_set_issuers(X509_CRL *crl) +{ + + int i, j; + GENERAL_NAMES *gens, *gtmp; + STACK_OF(X509_REVOKED) *revoked; + + revoked = X509_CRL_get_REVOKED(crl); + + gens = NULL; + for (i = 0; i < sk_X509_REVOKED_num(revoked); i++) { + X509_REVOKED *rev = sk_X509_REVOKED_value(revoked, i); + STACK_OF(X509_EXTENSION) *exts; + ASN1_ENUMERATED *reason; + X509_EXTENSION *ext; + gtmp = X509_REVOKED_get_ext_d2i(rev, + NID_certificate_issuer, &j, NULL); + if (!gtmp && (j != -1)) { + crl->flags |= EXFLAG_INVALID; + return 1; + } + + if (gtmp) { + gens = gtmp; + if (!crl->issuers) { + crl->issuers = sk_GENERAL_NAMES_new_null(); + if (!crl->issuers) + return 0; + } + if (!sk_GENERAL_NAMES_push(crl->issuers, gtmp)) + return 0; + } + rev->issuer = gens; + + reason = X509_REVOKED_get_ext_d2i(rev, NID_crl_reason, &j, NULL); + if (!reason && (j != -1)) { + crl->flags |= EXFLAG_INVALID; + return 1; + } + + if (reason) { + rev->reason = ASN1_ENUMERATED_get(reason); + ASN1_ENUMERATED_free(reason); + } else + rev->reason = CRL_REASON_NONE; + + /* Check for critical CRL entry extensions */ + + exts = rev->extensions; + + for (j = 0; j < sk_X509_EXTENSION_num(exts); j++) { + ext = sk_X509_EXTENSION_value(exts, j); + if (X509_EXTENSION_get_critical(ext)) { + if (OBJ_obj2nid(X509_EXTENSION_get_object(ext)) == NID_certificate_issuer) + continue; + crl->flags |= EXFLAG_CRITICAL; + break; + } + } + + } + + return 1; + +} + +/* + * The X509_CRL structure needs a bit of customisation. Cache some extensions + * and hash of the whole CRL. + */ +static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + X509_CRL *crl = (X509_CRL *)*pval; + STACK_OF(X509_EXTENSION) *exts; + X509_EXTENSION *ext; + int idx; + + switch (operation) { + case ASN1_OP_D2I_PRE: + if (crl->meth->crl_free) { + if (!crl->meth->crl_free(crl)) + return 0; + } + AUTHORITY_KEYID_free(crl->akid); + ISSUING_DIST_POINT_free(crl->idp); + ASN1_INTEGER_free(crl->crl_number); + ASN1_INTEGER_free(crl->base_crl_number); + sk_GENERAL_NAMES_pop_free(crl->issuers, GENERAL_NAMES_free); + /* fall thru */ + + case ASN1_OP_NEW_POST: + crl->idp = NULL; + crl->akid = NULL; + crl->flags = 0; + crl->idp_flags = 0; + crl->idp_reasons = CRLDP_ALL_REASONS; + crl->meth = default_crl_method; + crl->meth_data = NULL; + crl->issuers = NULL; + crl->crl_number = NULL; + crl->base_crl_number = NULL; + break; + + case ASN1_OP_D2I_POST: + X509_CRL_digest(crl, EVP_sha1(), crl->sha1_hash, NULL); + crl->idp = X509_CRL_get_ext_d2i(crl, + NID_issuing_distribution_point, NULL, + NULL); + if (crl->idp) + setup_idp(crl, crl->idp); + + crl->akid = X509_CRL_get_ext_d2i(crl, + NID_authority_key_identifier, NULL, + NULL); + + crl->crl_number = X509_CRL_get_ext_d2i(crl, + NID_crl_number, NULL, NULL); + + crl->base_crl_number = X509_CRL_get_ext_d2i(crl, + NID_delta_crl, NULL, + NULL); + /* Delta CRLs must have CRL number */ + if (crl->base_crl_number && !crl->crl_number) + crl->flags |= EXFLAG_INVALID; + + /* + * See if we have any unhandled critical CRL extensions and indicate + * this in a flag. We only currently handle IDP so anything else + * critical sets the flag. This code accesses the X509_CRL structure + * directly: applications shouldn't do this. + */ + + exts = crl->crl.extensions; + + for (idx = 0; idx < sk_X509_EXTENSION_num(exts); idx++) { + int nid; + ext = sk_X509_EXTENSION_value(exts, idx); + nid = OBJ_obj2nid(X509_EXTENSION_get_object(ext)); + if (nid == NID_freshest_crl) + crl->flags |= EXFLAG_FRESHEST; + if (X509_EXTENSION_get_critical(ext)) { + /* We handle IDP and deltas */ + if ((nid == NID_issuing_distribution_point) + || (nid == NID_authority_key_identifier) + || (nid == NID_delta_crl)) + continue; + crl->flags |= EXFLAG_CRITICAL; + break; + } + } + + if (!crl_set_issuers(crl)) + return 0; + + if (crl->meth->crl_init) { + if (crl->meth->crl_init(crl) == 0) + return 0; + } + + crl->flags |= EXFLAG_SET; + break; + + case ASN1_OP_FREE_POST: + if (crl->meth->crl_free) { + if (!crl->meth->crl_free(crl)) + return 0; + } + AUTHORITY_KEYID_free(crl->akid); + ISSUING_DIST_POINT_free(crl->idp); + ASN1_INTEGER_free(crl->crl_number); + ASN1_INTEGER_free(crl->base_crl_number); + sk_GENERAL_NAMES_pop_free(crl->issuers, GENERAL_NAMES_free); + break; + } + return 1; +} + +/* Convert IDP into a more convenient form */ + +static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp) +{ + int idp_only = 0; + /* Set various flags according to IDP */ + crl->idp_flags |= IDP_PRESENT; + if (idp->onlyuser > 0) { + idp_only++; + crl->idp_flags |= IDP_ONLYUSER; + } + if (idp->onlyCA > 0) { + idp_only++; + crl->idp_flags |= IDP_ONLYCA; + } + if (idp->onlyattr > 0) { + idp_only++; + crl->idp_flags |= IDP_ONLYATTR; + } + + if (idp_only > 1) + crl->idp_flags |= IDP_INVALID; + + if (idp->indirectCRL > 0) + crl->idp_flags |= IDP_INDIRECT; + + if (idp->onlysomereasons) { + crl->idp_flags |= IDP_REASONS; + if (idp->onlysomereasons->length > 0) + crl->idp_reasons = idp->onlysomereasons->data[0]; + if (idp->onlysomereasons->length > 1) + crl->idp_reasons |= (idp->onlysomereasons->data[1] << 8); + crl->idp_reasons &= CRLDP_ALL_REASONS; + } + + DIST_POINT_set_dpname(idp->distpoint, X509_CRL_get_issuer(crl)); +} + +ASN1_SEQUENCE_ref(X509_CRL, crl_cb) = { + ASN1_EMBED(X509_CRL, crl, X509_CRL_INFO), + ASN1_EMBED(X509_CRL, sig_alg, X509_ALGOR), + ASN1_EMBED(X509_CRL, signature, ASN1_BIT_STRING) +} ASN1_SEQUENCE_END_ref(X509_CRL, X509_CRL) + +IMPLEMENT_ASN1_FUNCTIONS(X509_REVOKED) + +IMPLEMENT_ASN1_DUP_FUNCTION(X509_REVOKED) + +IMPLEMENT_ASN1_FUNCTIONS(X509_CRL_INFO) + +IMPLEMENT_ASN1_FUNCTIONS(X509_CRL) + +IMPLEMENT_ASN1_DUP_FUNCTION(X509_CRL) + +static int X509_REVOKED_cmp(const X509_REVOKED *const *a, + const X509_REVOKED *const *b) +{ + return (ASN1_STRING_cmp((ASN1_STRING *)&(*a)->serialNumber, + (ASN1_STRING *)&(*b)->serialNumber)); +} + +int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev) +{ + X509_CRL_INFO *inf; + + inf = &crl->crl; + if (inf->revoked == NULL) + inf->revoked = sk_X509_REVOKED_new(X509_REVOKED_cmp); + if (inf->revoked == NULL || !sk_X509_REVOKED_push(inf->revoked, rev)) { + ASN1err(ASN1_F_X509_CRL_ADD0_REVOKED, ERR_R_MALLOC_FAILURE); + return 0; + } + inf->enc.modified = 1; + return 1; +} + +int X509_CRL_verify(X509_CRL *crl, EVP_PKEY *r) +{ + if (crl->meth->crl_verify) + return crl->meth->crl_verify(crl, r); + return 0; +} + +int X509_CRL_get0_by_serial(X509_CRL *crl, + X509_REVOKED **ret, ASN1_INTEGER *serial) +{ + if (crl->meth->crl_lookup) + return crl->meth->crl_lookup(crl, ret, serial, NULL); + return 0; +} + +int X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x) +{ + if (crl->meth->crl_lookup) + return crl->meth->crl_lookup(crl, ret, + X509_get_serialNumber(x), + X509_get_issuer_name(x)); + return 0; +} + +static int def_crl_verify(X509_CRL *crl, EVP_PKEY *r) +{ + return (ASN1_item_verify(ASN1_ITEM_rptr(X509_CRL_INFO), + &crl->sig_alg, &crl->signature, &crl->crl, r)); +} + +static int crl_revoked_issuer_match(X509_CRL *crl, X509_NAME *nm, + X509_REVOKED *rev) +{ + int i; + + if (!rev->issuer) { + if (!nm) + return 1; + if (!X509_NAME_cmp(nm, X509_CRL_get_issuer(crl))) + return 1; + return 0; + } + + if (!nm) + nm = X509_CRL_get_issuer(crl); + + for (i = 0; i < sk_GENERAL_NAME_num(rev->issuer); i++) { + GENERAL_NAME *gen = sk_GENERAL_NAME_value(rev->issuer, i); + if (gen->type != GEN_DIRNAME) + continue; + if (!X509_NAME_cmp(nm, gen->d.directoryName)) + return 1; + } + return 0; + +} + +static int def_crl_lookup(X509_CRL *crl, + X509_REVOKED **ret, ASN1_INTEGER *serial, + X509_NAME *issuer) +{ + X509_REVOKED rtmp, *rev; + int idx, num; + + if (crl->crl.revoked == NULL) + return 0; + + /* + * Sort revoked into serial number order if not already sorted. Do this + * under a lock to avoid race condition. + */ + if (!sk_X509_REVOKED_is_sorted(crl->crl.revoked)) { + CRYPTO_THREAD_write_lock(crl->lock); + sk_X509_REVOKED_sort(crl->crl.revoked); + CRYPTO_THREAD_unlock(crl->lock); + } + rtmp.serialNumber = *serial; + idx = sk_X509_REVOKED_find(crl->crl.revoked, &rtmp); + if (idx < 0) + return 0; + /* Need to look for matching name */ + for (num = sk_X509_REVOKED_num(crl->crl.revoked); idx < num; idx++) { + rev = sk_X509_REVOKED_value(crl->crl.revoked, idx); + if (ASN1_INTEGER_cmp(&rev->serialNumber, serial)) + return 0; + if (crl_revoked_issuer_match(crl, issuer, rev)) { + if (ret) + *ret = rev; + if (rev->reason == CRL_REASON_REMOVE_FROM_CRL) + return 2; + return 1; + } + } + return 0; +} + +void X509_CRL_set_default_method(const X509_CRL_METHOD *meth) +{ + if (meth == NULL) + default_crl_method = &int_crl_meth; + else + default_crl_method = meth; +} + +X509_CRL_METHOD *X509_CRL_METHOD_new(int (*crl_init) (X509_CRL *crl), + int (*crl_free) (X509_CRL *crl), + int (*crl_lookup) (X509_CRL *crl, + X509_REVOKED **ret, + ASN1_INTEGER *ser, + X509_NAME *issuer), + int (*crl_verify) (X509_CRL *crl, + EVP_PKEY *pk)) +{ + X509_CRL_METHOD *m = OPENSSL_malloc(sizeof(*m)); + + if (m == NULL) { + X509err(X509_F_X509_CRL_METHOD_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + m->crl_init = crl_init; + m->crl_free = crl_free; + m->crl_lookup = crl_lookup; + m->crl_verify = crl_verify; + m->flags = X509_CRL_METHOD_DYNAMIC; + return m; +} + +void X509_CRL_METHOD_free(X509_CRL_METHOD *m) +{ + if (m == NULL || !(m->flags & X509_CRL_METHOD_DYNAMIC)) + return; + OPENSSL_free(m); +} + +void X509_CRL_set_meth_data(X509_CRL *crl, void *dat) +{ + crl->meth_data = dat; +} + +void *X509_CRL_get_meth_data(X509_CRL *crl) +{ + return crl->meth_data; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_exten.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_exten.c new file mode 100644 index 000000000..f10f4a4d8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_exten.c @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include "x509_lcl.h" + +ASN1_SEQUENCE(X509_EXTENSION) = { + ASN1_SIMPLE(X509_EXTENSION, object, ASN1_OBJECT), + ASN1_OPT(X509_EXTENSION, critical, ASN1_BOOLEAN), + ASN1_EMBED(X509_EXTENSION, value, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(X509_EXTENSION) + +ASN1_ITEM_TEMPLATE(X509_EXTENSIONS) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Extension, X509_EXTENSION) +ASN1_ITEM_TEMPLATE_END(X509_EXTENSIONS) + +IMPLEMENT_ASN1_FUNCTIONS(X509_EXTENSION) +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(X509_EXTENSIONS, X509_EXTENSIONS, X509_EXTENSIONS) +IMPLEMENT_ASN1_DUP_FUNCTION(X509_EXTENSION) diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_name.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_name.c new file mode 100644 index 000000000..a1e9bbdb6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_name.c @@ -0,0 +1,551 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/ctype.h" +#include "internal/cryptlib.h" +#include +#include +#include "internal/x509_int.h" +#include "internal/asn1_int.h" +#include "x509_lcl.h" + +/* + * Maximum length of X509_NAME: much larger than anything we should + * ever see in practice. + */ + +#define X509_NAME_MAX (1024 * 1024) + +static int x509_name_ex_d2i(ASN1_VALUE **val, + const unsigned char **in, long len, + const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx); + +static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out, + const ASN1_ITEM *it, int tag, int aclass); +static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it); +static void x509_name_ex_free(ASN1_VALUE **val, const ASN1_ITEM *it); + +static int x509_name_encode(X509_NAME *a); +static int x509_name_canon(X509_NAME *a); +static int asn1_string_canon(ASN1_STRING *out, const ASN1_STRING *in); +static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) * intname, + unsigned char **in); + +static int x509_name_ex_print(BIO *out, ASN1_VALUE **pval, + int indent, + const char *fname, const ASN1_PCTX *pctx); + +ASN1_SEQUENCE(X509_NAME_ENTRY) = { + ASN1_SIMPLE(X509_NAME_ENTRY, object, ASN1_OBJECT), + ASN1_SIMPLE(X509_NAME_ENTRY, value, ASN1_PRINTABLE) +} ASN1_SEQUENCE_END(X509_NAME_ENTRY) + +IMPLEMENT_ASN1_FUNCTIONS(X509_NAME_ENTRY) +IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME_ENTRY) + +/* + * For the "Name" type we need a SEQUENCE OF { SET OF X509_NAME_ENTRY } so + * declare two template wrappers for this + */ + +ASN1_ITEM_TEMPLATE(X509_NAME_ENTRIES) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, RDNS, X509_NAME_ENTRY) +static_ASN1_ITEM_TEMPLATE_END(X509_NAME_ENTRIES) + +ASN1_ITEM_TEMPLATE(X509_NAME_INTERNAL) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Name, X509_NAME_ENTRIES) +static_ASN1_ITEM_TEMPLATE_END(X509_NAME_INTERNAL) + +/* + * Normally that's where it would end: we'd have two nested STACK structures + * representing the ASN1. Unfortunately X509_NAME uses a completely different + * form and caches encodings so we have to process the internal form and + * convert to the external form. + */ + +static const ASN1_EXTERN_FUNCS x509_name_ff = { + NULL, + x509_name_ex_new, + x509_name_ex_free, + 0, /* Default clear behaviour is OK */ + x509_name_ex_d2i, + x509_name_ex_i2d, + x509_name_ex_print +}; + +IMPLEMENT_EXTERN_ASN1(X509_NAME, V_ASN1_SEQUENCE, x509_name_ff) + +IMPLEMENT_ASN1_FUNCTIONS(X509_NAME) + +IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME) + +static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it) +{ + X509_NAME *ret = OPENSSL_zalloc(sizeof(*ret)); + + if (ret == NULL) + goto memerr; + if ((ret->entries = sk_X509_NAME_ENTRY_new_null()) == NULL) + goto memerr; + if ((ret->bytes = BUF_MEM_new()) == NULL) + goto memerr; + ret->modified = 1; + *val = (ASN1_VALUE *)ret; + return 1; + + memerr: + ASN1err(ASN1_F_X509_NAME_EX_NEW, ERR_R_MALLOC_FAILURE); + if (ret) { + sk_X509_NAME_ENTRY_free(ret->entries); + OPENSSL_free(ret); + } + return 0; +} + +static void x509_name_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + X509_NAME *a; + + if (!pval || !*pval) + return; + a = (X509_NAME *)*pval; + + BUF_MEM_free(a->bytes); + sk_X509_NAME_ENTRY_pop_free(a->entries, X509_NAME_ENTRY_free); + OPENSSL_free(a->canon_enc); + OPENSSL_free(a); + *pval = NULL; +} + +static void local_sk_X509_NAME_ENTRY_free(STACK_OF(X509_NAME_ENTRY) *ne) +{ + sk_X509_NAME_ENTRY_free(ne); +} + +static void local_sk_X509_NAME_ENTRY_pop_free(STACK_OF(X509_NAME_ENTRY) *ne) +{ + sk_X509_NAME_ENTRY_pop_free(ne, X509_NAME_ENTRY_free); +} + +static int x509_name_ex_d2i(ASN1_VALUE **val, + const unsigned char **in, long len, + const ASN1_ITEM *it, int tag, int aclass, + char opt, ASN1_TLC *ctx) +{ + const unsigned char *p = *in, *q; + union { + STACK_OF(STACK_OF_X509_NAME_ENTRY) *s; + ASN1_VALUE *a; + } intname = { + NULL + }; + union { + X509_NAME *x; + ASN1_VALUE *a; + } nm = { + NULL + }; + int i, j, ret; + STACK_OF(X509_NAME_ENTRY) *entries; + X509_NAME_ENTRY *entry; + if (len > X509_NAME_MAX) + len = X509_NAME_MAX; + q = p; + + /* Get internal representation of Name */ + ret = ASN1_item_ex_d2i(&intname.a, + &p, len, ASN1_ITEM_rptr(X509_NAME_INTERNAL), + tag, aclass, opt, ctx); + + if (ret <= 0) + return ret; + + if (*val) + x509_name_ex_free(val, NULL); + if (!x509_name_ex_new(&nm.a, NULL)) + goto err; + /* We've decoded it: now cache encoding */ + if (!BUF_MEM_grow(nm.x->bytes, p - q)) + goto err; + memcpy(nm.x->bytes->data, q, p - q); + + /* Convert internal representation to X509_NAME structure */ + for (i = 0; i < sk_STACK_OF_X509_NAME_ENTRY_num(intname.s); i++) { + entries = sk_STACK_OF_X509_NAME_ENTRY_value(intname.s, i); + for (j = 0; j < sk_X509_NAME_ENTRY_num(entries); j++) { + entry = sk_X509_NAME_ENTRY_value(entries, j); + entry->set = i; + if (!sk_X509_NAME_ENTRY_push(nm.x->entries, entry)) + goto err; + sk_X509_NAME_ENTRY_set(entries, j, NULL); + } + } + ret = x509_name_canon(nm.x); + if (!ret) + goto err; + sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s, + local_sk_X509_NAME_ENTRY_free); + nm.x->modified = 0; + *val = nm.a; + *in = p; + return ret; + + err: + if (nm.x != NULL) + X509_NAME_free(nm.x); + sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s, + local_sk_X509_NAME_ENTRY_pop_free); + ASN1err(ASN1_F_X509_NAME_EX_D2I, ERR_R_NESTED_ASN1_ERROR); + return 0; +} + +static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out, + const ASN1_ITEM *it, int tag, int aclass) +{ + int ret; + X509_NAME *a = (X509_NAME *)*val; + if (a->modified) { + ret = x509_name_encode(a); + if (ret < 0) + return ret; + ret = x509_name_canon(a); + if (ret < 0) + return ret; + } + ret = a->bytes->length; + if (out != NULL) { + memcpy(*out, a->bytes->data, ret); + *out += ret; + } + return ret; +} + +static int x509_name_encode(X509_NAME *a) +{ + union { + STACK_OF(STACK_OF_X509_NAME_ENTRY) *s; + ASN1_VALUE *a; + } intname = { + NULL + }; + int len; + unsigned char *p; + STACK_OF(X509_NAME_ENTRY) *entries = NULL; + X509_NAME_ENTRY *entry; + int i, set = -1; + intname.s = sk_STACK_OF_X509_NAME_ENTRY_new_null(); + if (!intname.s) + goto memerr; + for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) { + entry = sk_X509_NAME_ENTRY_value(a->entries, i); + if (entry->set != set) { + entries = sk_X509_NAME_ENTRY_new_null(); + if (!entries) + goto memerr; + if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname.s, entries)) { + sk_X509_NAME_ENTRY_free(entries); + goto memerr; + } + set = entry->set; + } + if (!sk_X509_NAME_ENTRY_push(entries, entry)) + goto memerr; + } + len = ASN1_item_ex_i2d(&intname.a, NULL, + ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1); + if (!BUF_MEM_grow(a->bytes, len)) + goto memerr; + p = (unsigned char *)a->bytes->data; + ASN1_item_ex_i2d(&intname.a, + &p, ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1); + sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s, + local_sk_X509_NAME_ENTRY_free); + a->modified = 0; + return len; + memerr: + sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s, + local_sk_X509_NAME_ENTRY_free); + ASN1err(ASN1_F_X509_NAME_ENCODE, ERR_R_MALLOC_FAILURE); + return -1; +} + +static int x509_name_ex_print(BIO *out, ASN1_VALUE **pval, + int indent, + const char *fname, const ASN1_PCTX *pctx) +{ + if (X509_NAME_print_ex(out, (const X509_NAME *)*pval, + indent, pctx->nm_flags) <= 0) + return 0; + return 2; +} + +/* + * This function generates the canonical encoding of the Name structure. In + * it all strings are converted to UTF8, leading, trailing and multiple + * spaces collapsed, converted to lower case and the leading SEQUENCE header + * removed. In future we could also normalize the UTF8 too. By doing this + * comparison of Name structures can be rapidly performed by just using + * memcmp() of the canonical encoding. By omitting the leading SEQUENCE name + * constraints of type dirName can also be checked with a simple memcmp(). + */ + +static int x509_name_canon(X509_NAME *a) +{ + unsigned char *p; + STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname; + STACK_OF(X509_NAME_ENTRY) *entries = NULL; + X509_NAME_ENTRY *entry, *tmpentry = NULL; + int i, set = -1, ret = 0, len; + + OPENSSL_free(a->canon_enc); + a->canon_enc = NULL; + /* Special case: empty X509_NAME => null encoding */ + if (sk_X509_NAME_ENTRY_num(a->entries) == 0) { + a->canon_enclen = 0; + return 1; + } + intname = sk_STACK_OF_X509_NAME_ENTRY_new_null(); + if (intname == NULL) { + X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE); + goto err; + } + for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) { + entry = sk_X509_NAME_ENTRY_value(a->entries, i); + if (entry->set != set) { + entries = sk_X509_NAME_ENTRY_new_null(); + if (entries == NULL) + goto err; + if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname, entries)) { + sk_X509_NAME_ENTRY_free(entries); + X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE); + goto err; + } + set = entry->set; + } + tmpentry = X509_NAME_ENTRY_new(); + if (tmpentry == NULL) { + X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE); + goto err; + } + tmpentry->object = OBJ_dup(entry->object); + if (tmpentry->object == NULL) { + X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!asn1_string_canon(tmpentry->value, entry->value)) + goto err; + if (!sk_X509_NAME_ENTRY_push(entries, tmpentry)) { + X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE); + goto err; + } + tmpentry = NULL; + } + + /* Finally generate encoding */ + len = i2d_name_canon(intname, NULL); + if (len < 0) + goto err; + a->canon_enclen = len; + + p = OPENSSL_malloc(a->canon_enclen); + if (p == NULL) { + X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE); + goto err; + } + + a->canon_enc = p; + + i2d_name_canon(intname, &p); + + ret = 1; + + err: + X509_NAME_ENTRY_free(tmpentry); + sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname, + local_sk_X509_NAME_ENTRY_pop_free); + return ret; +} + +/* Bitmap of all the types of string that will be canonicalized. */ + +#define ASN1_MASK_CANON \ + (B_ASN1_UTF8STRING | B_ASN1_BMPSTRING | B_ASN1_UNIVERSALSTRING \ + | B_ASN1_PRINTABLESTRING | B_ASN1_T61STRING | B_ASN1_IA5STRING \ + | B_ASN1_VISIBLESTRING) + +static int asn1_string_canon(ASN1_STRING *out, const ASN1_STRING *in) +{ + unsigned char *to, *from; + int len, i; + + /* If type not in bitmask just copy string across */ + if (!(ASN1_tag2bit(in->type) & ASN1_MASK_CANON)) { + if (!ASN1_STRING_copy(out, in)) + return 0; + return 1; + } + + out->type = V_ASN1_UTF8STRING; + out->length = ASN1_STRING_to_UTF8(&out->data, in); + if (out->length == -1) + return 0; + + to = out->data; + from = to; + + len = out->length; + + /* + * Convert string in place to canonical form. Ultimately we may need to + * handle a wider range of characters but for now ignore anything with + * MSB set and rely on the ossl_isspace() to fail on bad characters without + * needing isascii or range checks as well. + */ + + /* Ignore leading spaces */ + while (len > 0 && ossl_isspace(*from)) { + from++; + len--; + } + + to = from + len; + + /* Ignore trailing spaces */ + while (len > 0 && ossl_isspace(to[-1])) { + to--; + len--; + } + + to = out->data; + + i = 0; + while (i < len) { + /* If not ASCII set just copy across */ + if (!ossl_isascii(*from)) { + *to++ = *from++; + i++; + } + /* Collapse multiple spaces */ + else if (ossl_isspace(*from)) { + /* Copy one space across */ + *to++ = ' '; + /* + * Ignore subsequent spaces. Note: don't need to check len here + * because we know the last character is a non-space so we can't + * overflow. + */ + do { + from++; + i++; + } + while (ossl_isspace(*from)); + } else { + *to++ = ossl_tolower(*from); + from++; + i++; + } + } + + out->length = to - out->data; + + return 1; + +} + +static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) * _intname, + unsigned char **in) +{ + int i, len, ltmp; + ASN1_VALUE *v; + STACK_OF(ASN1_VALUE) *intname = (STACK_OF(ASN1_VALUE) *)_intname; + + len = 0; + for (i = 0; i < sk_ASN1_VALUE_num(intname); i++) { + v = sk_ASN1_VALUE_value(intname, i); + ltmp = ASN1_item_ex_i2d(&v, in, + ASN1_ITEM_rptr(X509_NAME_ENTRIES), -1, -1); + if (ltmp < 0) + return ltmp; + len += ltmp; + } + return len; +} + +int X509_NAME_set(X509_NAME **xn, X509_NAME *name) +{ + if (*xn == name) + return *xn != NULL; + if ((name = X509_NAME_dup(name)) == NULL) + return 0; + X509_NAME_free(*xn); + *xn = name; + return 1; +} + +int X509_NAME_print(BIO *bp, const X509_NAME *name, int obase) +{ + char *s, *c, *b; + int l, i; + + l = 80 - 2 - obase; + + b = X509_NAME_oneline(name, NULL, 0); + if (!b) + return 0; + if (!*b) { + OPENSSL_free(b); + return 1; + } + s = b + 1; /* skip the first slash */ + + c = s; + for (;;) { + if (((*s == '/') && + (ossl_isupper(s[1]) && ((s[2] == '=') || + (ossl_isupper(s[2]) && (s[3] == '=')) + ))) || (*s == '\0')) + { + i = s - c; + if (BIO_write(bp, c, i) != i) + goto err; + c = s + 1; /* skip following slash */ + if (*s != '\0') { + if (BIO_write(bp, ", ", 2) != 2) + goto err; + } + l--; + } + if (*s == '\0') + break; + s++; + l--; + } + + OPENSSL_free(b); + return 1; + err: + X509err(X509_F_X509_NAME_PRINT, ERR_R_BUF_LIB); + OPENSSL_free(b); + return 0; +} + +int X509_NAME_get0_der(X509_NAME *nm, const unsigned char **pder, + size_t *pderlen) +{ + /* Make sure encoding is valid */ + if (i2d_X509_NAME(nm, NULL) <= 0) + return 0; + if (pder != NULL) + *pder = (unsigned char *)nm->bytes->data; + if (pderlen != NULL) + *pderlen = nm->bytes->length; + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_pubkey.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_pubkey.c new file mode 100644 index 000000000..1c87b8268 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_pubkey.c @@ -0,0 +1,375 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include "internal/asn1_int.h" +#include "internal/evp_int.h" +#include "internal/x509_int.h" +#include +#include + +struct X509_pubkey_st { + X509_ALGOR *algor; + ASN1_BIT_STRING *public_key; + EVP_PKEY *pkey; +}; + +static int x509_pubkey_decode(EVP_PKEY **pk, X509_PUBKEY *key); + +/* Minor tweak to operation: free up EVP_PKEY */ +static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + if (operation == ASN1_OP_FREE_POST) { + X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval; + EVP_PKEY_free(pubkey->pkey); + } else if (operation == ASN1_OP_D2I_POST) { + /* Attempt to decode public key and cache in pubkey structure. */ + X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval; + EVP_PKEY_free(pubkey->pkey); + pubkey->pkey = NULL; + /* + * Opportunistically decode the key but remove any non fatal errors + * from the queue. Subsequent explicit attempts to decode/use the key + * will return an appropriate error. + */ + ERR_set_mark(); + if (x509_pubkey_decode(&pubkey->pkey, pubkey) == -1) + return 0; + ERR_pop_to_mark(); + } + return 1; +} + +ASN1_SEQUENCE_cb(X509_PUBKEY, pubkey_cb) = { + ASN1_SIMPLE(X509_PUBKEY, algor, X509_ALGOR), + ASN1_SIMPLE(X509_PUBKEY, public_key, ASN1_BIT_STRING) +} ASN1_SEQUENCE_END_cb(X509_PUBKEY, X509_PUBKEY) + +IMPLEMENT_ASN1_FUNCTIONS(X509_PUBKEY) + +int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey) +{ + X509_PUBKEY *pk = NULL; + + if (x == NULL) + return 0; + + if ((pk = X509_PUBKEY_new()) == NULL) + goto error; + + if (pkey->ameth) { + if (pkey->ameth->pub_encode) { + if (!pkey->ameth->pub_encode(pk, pkey)) { + X509err(X509_F_X509_PUBKEY_SET, + X509_R_PUBLIC_KEY_ENCODE_ERROR); + goto error; + } + } else { + X509err(X509_F_X509_PUBKEY_SET, X509_R_METHOD_NOT_SUPPORTED); + goto error; + } + } else { + X509err(X509_F_X509_PUBKEY_SET, X509_R_UNSUPPORTED_ALGORITHM); + goto error; + } + + X509_PUBKEY_free(*x); + *x = pk; + pk->pkey = pkey; + EVP_PKEY_up_ref(pkey); + return 1; + + error: + X509_PUBKEY_free(pk); + return 0; +} + +/* + * Attempt to decode a public key. + * Returns 1 on success, 0 for a decode failure and -1 for a fatal + * error e.g. malloc failure. + */ + + +static int x509_pubkey_decode(EVP_PKEY **ppkey, X509_PUBKEY *key) +{ + EVP_PKEY *pkey = EVP_PKEY_new(); + + if (pkey == NULL) { + X509err(X509_F_X509_PUBKEY_DECODE, ERR_R_MALLOC_FAILURE); + return -1; + } + + if (!EVP_PKEY_set_type(pkey, OBJ_obj2nid(key->algor->algorithm))) { + X509err(X509_F_X509_PUBKEY_DECODE, X509_R_UNSUPPORTED_ALGORITHM); + goto error; + } + + if (pkey->ameth->pub_decode) { + /* + * Treat any failure of pub_decode as a decode error. In + * future we could have different return codes for decode + * errors and fatal errors such as malloc failure. + */ + if (!pkey->ameth->pub_decode(pkey, key)) { + X509err(X509_F_X509_PUBKEY_DECODE, X509_R_PUBLIC_KEY_DECODE_ERROR); + goto error; + } + } else { + X509err(X509_F_X509_PUBKEY_DECODE, X509_R_METHOD_NOT_SUPPORTED); + goto error; + } + + *ppkey = pkey; + return 1; + + error: + EVP_PKEY_free(pkey); + return 0; +} + +EVP_PKEY *X509_PUBKEY_get0(X509_PUBKEY *key) +{ + EVP_PKEY *ret = NULL; + + if (key == NULL || key->public_key == NULL) + return NULL; + + if (key->pkey != NULL) + return key->pkey; + + /* + * When the key ASN.1 is initially parsed an attempt is made to + * decode the public key and cache the EVP_PKEY structure. If this + * operation fails the cached value will be NULL. Parsing continues + * to allow parsing of unknown key types or unsupported forms. + * We repeat the decode operation so the appropriate errors are left + * in the queue. + */ + x509_pubkey_decode(&ret, key); + /* If decode doesn't fail something bad happened */ + if (ret != NULL) { + X509err(X509_F_X509_PUBKEY_GET0, ERR_R_INTERNAL_ERROR); + EVP_PKEY_free(ret); + } + + return NULL; +} + +EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key) +{ + EVP_PKEY *ret = X509_PUBKEY_get0(key); + if (ret != NULL) + EVP_PKEY_up_ref(ret); + return ret; +} + +/* + * Now two pseudo ASN1 routines that take an EVP_PKEY structure and encode or + * decode as X509_PUBKEY + */ + +EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length) +{ + X509_PUBKEY *xpk; + EVP_PKEY *pktmp; + const unsigned char *q; + q = *pp; + xpk = d2i_X509_PUBKEY(NULL, &q, length); + if (!xpk) + return NULL; + pktmp = X509_PUBKEY_get(xpk); + X509_PUBKEY_free(xpk); + if (!pktmp) + return NULL; + *pp = q; + if (a) { + EVP_PKEY_free(*a); + *a = pktmp; + } + return pktmp; +} + +int i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp) +{ + X509_PUBKEY *xpk = NULL; + int ret; + if (!a) + return 0; + if (!X509_PUBKEY_set(&xpk, a)) + return -1; + ret = i2d_X509_PUBKEY(xpk, pp); + X509_PUBKEY_free(xpk); + return ret; +} + +/* + * The following are equivalents but which return RSA and DSA keys + */ +#ifndef OPENSSL_NO_RSA +RSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp, long length) +{ + EVP_PKEY *pkey; + RSA *key; + const unsigned char *q; + q = *pp; + pkey = d2i_PUBKEY(NULL, &q, length); + if (!pkey) + return NULL; + key = EVP_PKEY_get1_RSA(pkey); + EVP_PKEY_free(pkey); + if (!key) + return NULL; + *pp = q; + if (a) { + RSA_free(*a); + *a = key; + } + return key; +} + +int i2d_RSA_PUBKEY(RSA *a, unsigned char **pp) +{ + EVP_PKEY *pktmp; + int ret; + if (!a) + return 0; + pktmp = EVP_PKEY_new(); + if (pktmp == NULL) { + ASN1err(ASN1_F_I2D_RSA_PUBKEY, ERR_R_MALLOC_FAILURE); + return -1; + } + EVP_PKEY_set1_RSA(pktmp, a); + ret = i2d_PUBKEY(pktmp, pp); + EVP_PKEY_free(pktmp); + return ret; +} +#endif + +#ifndef OPENSSL_NO_DSA +DSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp, long length) +{ + EVP_PKEY *pkey; + DSA *key; + const unsigned char *q; + q = *pp; + pkey = d2i_PUBKEY(NULL, &q, length); + if (!pkey) + return NULL; + key = EVP_PKEY_get1_DSA(pkey); + EVP_PKEY_free(pkey); + if (!key) + return NULL; + *pp = q; + if (a) { + DSA_free(*a); + *a = key; + } + return key; +} + +int i2d_DSA_PUBKEY(DSA *a, unsigned char **pp) +{ + EVP_PKEY *pktmp; + int ret; + if (!a) + return 0; + pktmp = EVP_PKEY_new(); + if (pktmp == NULL) { + ASN1err(ASN1_F_I2D_DSA_PUBKEY, ERR_R_MALLOC_FAILURE); + return -1; + } + EVP_PKEY_set1_DSA(pktmp, a); + ret = i2d_PUBKEY(pktmp, pp); + EVP_PKEY_free(pktmp); + return ret; +} +#endif + +#ifndef OPENSSL_NO_EC +EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length) +{ + EVP_PKEY *pkey; + EC_KEY *key; + const unsigned char *q; + q = *pp; + pkey = d2i_PUBKEY(NULL, &q, length); + if (!pkey) + return NULL; + key = EVP_PKEY_get1_EC_KEY(pkey); + EVP_PKEY_free(pkey); + if (!key) + return NULL; + *pp = q; + if (a) { + EC_KEY_free(*a); + *a = key; + } + return key; +} + +int i2d_EC_PUBKEY(EC_KEY *a, unsigned char **pp) +{ + EVP_PKEY *pktmp; + int ret; + if (!a) + return 0; + if ((pktmp = EVP_PKEY_new()) == NULL) { + ASN1err(ASN1_F_I2D_EC_PUBKEY, ERR_R_MALLOC_FAILURE); + return -1; + } + EVP_PKEY_set1_EC_KEY(pktmp, a); + ret = i2d_PUBKEY(pktmp, pp); + EVP_PKEY_free(pktmp); + return ret; +} +#endif + +int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *aobj, + int ptype, void *pval, + unsigned char *penc, int penclen) +{ + if (!X509_ALGOR_set0(pub->algor, aobj, ptype, pval)) + return 0; + if (penc) { + OPENSSL_free(pub->public_key->data); + pub->public_key->data = penc; + pub->public_key->length = penclen; + /* Set number of unused bits to zero */ + pub->public_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + pub->public_key->flags |= ASN1_STRING_FLAG_BITS_LEFT; + } + return 1; +} + +int X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg, + const unsigned char **pk, int *ppklen, + X509_ALGOR **pa, X509_PUBKEY *pub) +{ + if (ppkalg) + *ppkalg = pub->algor->algorithm; + if (pk) { + *pk = pub->public_key->data; + *ppklen = pub->public_key->length; + } + if (pa) + *pa = pub->algor; + return 1; +} + +ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x) +{ + if (x == NULL) + return NULL; + return x->cert_info.key->public_key; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_req.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_req.c new file mode 100644 index 000000000..c2da95a73 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_req.c @@ -0,0 +1,68 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include "internal/x509_int.h" + +/*- + * X509_REQ_INFO is handled in an unusual way to get round + * invalid encodings. Some broken certificate requests don't + * encode the attributes field if it is empty. This is in + * violation of PKCS#10 but we need to tolerate it. We do + * this by making the attributes field OPTIONAL then using + * the callback to initialise it to an empty STACK. + * + * This means that the field will be correctly encoded unless + * we NULL out the field. + * + * As a result we no longer need the req_kludge field because + * the information is now contained in the attributes field: + * 1. If it is NULL then it's the invalid omission. + * 2. If it is empty it is the correct encoding. + * 3. If it is not empty then some attributes are present. + * + */ + +static int rinf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + X509_REQ_INFO *rinf = (X509_REQ_INFO *)*pval; + + if (operation == ASN1_OP_NEW_POST) { + rinf->attributes = sk_X509_ATTRIBUTE_new_null(); + if (!rinf->attributes) + return 0; + } + return 1; +} + +ASN1_SEQUENCE_enc(X509_REQ_INFO, enc, rinf_cb) = { + ASN1_SIMPLE(X509_REQ_INFO, version, ASN1_INTEGER), + ASN1_SIMPLE(X509_REQ_INFO, subject, X509_NAME), + ASN1_SIMPLE(X509_REQ_INFO, pubkey, X509_PUBKEY), + /* This isn't really OPTIONAL but it gets round invalid + * encodings + */ + ASN1_IMP_SET_OF_OPT(X509_REQ_INFO, attributes, X509_ATTRIBUTE, 0) +} ASN1_SEQUENCE_END_enc(X509_REQ_INFO, X509_REQ_INFO) + +IMPLEMENT_ASN1_FUNCTIONS(X509_REQ_INFO) + +ASN1_SEQUENCE_ref(X509_REQ, 0) = { + ASN1_EMBED(X509_REQ, req_info, X509_REQ_INFO), + ASN1_EMBED(X509_REQ, sig_alg, X509_ALGOR), + ASN1_SIMPLE(X509_REQ, signature, ASN1_BIT_STRING) +} ASN1_SEQUENCE_END_ref(X509_REQ, X509_REQ) + +IMPLEMENT_ASN1_FUNCTIONS(X509_REQ) + +IMPLEMENT_ASN1_DUP_FUNCTION(X509_REQ) diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_x509.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_x509.c new file mode 100644 index 000000000..afe59c46c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_x509.c @@ -0,0 +1,247 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "internal/x509_int.h" + +ASN1_SEQUENCE_enc(X509_CINF, enc, 0) = { + ASN1_EXP_OPT(X509_CINF, version, ASN1_INTEGER, 0), + ASN1_EMBED(X509_CINF, serialNumber, ASN1_INTEGER), + ASN1_EMBED(X509_CINF, signature, X509_ALGOR), + ASN1_SIMPLE(X509_CINF, issuer, X509_NAME), + ASN1_EMBED(X509_CINF, validity, X509_VAL), + ASN1_SIMPLE(X509_CINF, subject, X509_NAME), + ASN1_SIMPLE(X509_CINF, key, X509_PUBKEY), + ASN1_IMP_OPT(X509_CINF, issuerUID, ASN1_BIT_STRING, 1), + ASN1_IMP_OPT(X509_CINF, subjectUID, ASN1_BIT_STRING, 2), + ASN1_EXP_SEQUENCE_OF_OPT(X509_CINF, extensions, X509_EXTENSION, 3) +} ASN1_SEQUENCE_END_enc(X509_CINF, X509_CINF) + +IMPLEMENT_ASN1_FUNCTIONS(X509_CINF) +/* X509 top level structure needs a bit of customisation */ + +extern void policy_cache_free(X509_POLICY_CACHE *cache); + +static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + X509 *ret = (X509 *)*pval; + + switch (operation) { + + case ASN1_OP_D2I_PRE: + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data); + X509_CERT_AUX_free(ret->aux); + ASN1_OCTET_STRING_free(ret->skid); + AUTHORITY_KEYID_free(ret->akid); + CRL_DIST_POINTS_free(ret->crldp); + policy_cache_free(ret->policy_cache); + GENERAL_NAMES_free(ret->altname); + NAME_CONSTRAINTS_free(ret->nc); +#ifndef OPENSSL_NO_RFC3779 + sk_IPAddressFamily_pop_free(ret->rfc3779_addr, IPAddressFamily_free); + ASIdentifiers_free(ret->rfc3779_asid); +#endif + + /* fall thru */ + + case ASN1_OP_NEW_POST: + ret->ex_cached = 0; + ret->ex_kusage = 0; + ret->ex_xkusage = 0; + ret->ex_nscert = 0; + ret->ex_flags = 0; + ret->ex_pathlen = -1; + ret->ex_pcpathlen = -1; + ret->skid = NULL; + ret->akid = NULL; + ret->policy_cache = NULL; + ret->altname = NULL; + ret->nc = NULL; +#ifndef OPENSSL_NO_RFC3779 + ret->rfc3779_addr = NULL; + ret->rfc3779_asid = NULL; +#endif + ret->aux = NULL; + ret->crldp = NULL; + if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data)) + return 0; + break; + + case ASN1_OP_FREE_POST: + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data); + X509_CERT_AUX_free(ret->aux); + ASN1_OCTET_STRING_free(ret->skid); + AUTHORITY_KEYID_free(ret->akid); + CRL_DIST_POINTS_free(ret->crldp); + policy_cache_free(ret->policy_cache); + GENERAL_NAMES_free(ret->altname); + NAME_CONSTRAINTS_free(ret->nc); +#ifndef OPENSSL_NO_RFC3779 + sk_IPAddressFamily_pop_free(ret->rfc3779_addr, IPAddressFamily_free); + ASIdentifiers_free(ret->rfc3779_asid); +#endif + break; + + } + + return 1; + +} + +ASN1_SEQUENCE_ref(X509, x509_cb) = { + ASN1_EMBED(X509, cert_info, X509_CINF), + ASN1_EMBED(X509, sig_alg, X509_ALGOR), + ASN1_EMBED(X509, signature, ASN1_BIT_STRING) +} ASN1_SEQUENCE_END_ref(X509, X509) + +IMPLEMENT_ASN1_FUNCTIONS(X509) + +IMPLEMENT_ASN1_DUP_FUNCTION(X509) + +int X509_set_ex_data(X509 *r, int idx, void *arg) +{ + return CRYPTO_set_ex_data(&r->ex_data, idx, arg); +} + +void *X509_get_ex_data(X509 *r, int idx) +{ + return CRYPTO_get_ex_data(&r->ex_data, idx); +} + +/* + * X509_AUX ASN1 routines. X509_AUX is the name given to a certificate with + * extra info tagged on the end. Since these functions set how a certificate + * is trusted they should only be used when the certificate comes from a + * reliable source such as local storage. + */ + +X509 *d2i_X509_AUX(X509 **a, const unsigned char **pp, long length) +{ + const unsigned char *q; + X509 *ret; + int freeret = 0; + + /* Save start position */ + q = *pp; + + if (a == NULL || *a == NULL) + freeret = 1; + ret = d2i_X509(a, &q, length); + /* If certificate unreadable then forget it */ + if (ret == NULL) + return NULL; + /* update length */ + length -= q - *pp; + if (length > 0 && !d2i_X509_CERT_AUX(&ret->aux, &q, length)) + goto err; + *pp = q; + return ret; + err: + if (freeret) { + X509_free(ret); + if (a) + *a = NULL; + } + return NULL; +} + +/* + * Serialize trusted certificate to *pp or just return the required buffer + * length if pp == NULL. We ultimately want to avoid modifying *pp in the + * error path, but that depends on similar hygiene in lower-level functions. + * Here we avoid compounding the problem. + */ +static int i2d_x509_aux_internal(X509 *a, unsigned char **pp) +{ + int length, tmplen; + unsigned char *start = pp != NULL ? *pp : NULL; + + /* + * This might perturb *pp on error, but fixing that belongs in i2d_X509() + * not here. It should be that if a == NULL length is zero, but we check + * both just in case. + */ + length = i2d_X509(a, pp); + if (length <= 0 || a == NULL) + return length; + + tmplen = i2d_X509_CERT_AUX(a->aux, pp); + if (tmplen < 0) { + if (start != NULL) + *pp = start; + return tmplen; + } + length += tmplen; + + return length; +} + +/* + * Serialize trusted certificate to *pp, or just return the required buffer + * length if pp == NULL. + * + * When pp is not NULL, but *pp == NULL, we allocate the buffer, but since + * we're writing two ASN.1 objects back to back, we can't have i2d_X509() do + * the allocation, nor can we allow i2d_X509_CERT_AUX() to increment the + * allocated buffer. + */ +int i2d_X509_AUX(X509 *a, unsigned char **pp) +{ + int length; + unsigned char *tmp; + + /* Buffer provided by caller */ + if (pp == NULL || *pp != NULL) + return i2d_x509_aux_internal(a, pp); + + /* Obtain the combined length */ + if ((length = i2d_x509_aux_internal(a, NULL)) <= 0) + return length; + + /* Allocate requisite combined storage */ + *pp = tmp = OPENSSL_malloc(length); + if (tmp == NULL) { + X509err(X509_F_I2D_X509_AUX, ERR_R_MALLOC_FAILURE); + return -1; + } + + /* Encode, but keep *pp at the originally malloced pointer */ + length = i2d_x509_aux_internal(a, &tmp); + if (length <= 0) { + OPENSSL_free(*pp); + *pp = NULL; + } + return length; +} + +int i2d_re_X509_tbs(X509 *x, unsigned char **pp) +{ + x->cert_info.enc.modified = 1; + return i2d_X509_CINF(&x->cert_info, pp); +} + +void X509_get0_signature(const ASN1_BIT_STRING **psig, + const X509_ALGOR **palg, const X509 *x) +{ + if (psig) + *psig = &x->signature; + if (palg) + *palg = &x->sig_alg; +} + +int X509_get_signature_nid(const X509 *x) +{ + return OBJ_obj2nid(x->sig_alg.algorithm); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_x509a.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_x509a.c new file mode 100644 index 000000000..8c9ad71d1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509/x_x509a.c @@ -0,0 +1,169 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include "internal/x509_int.h" + +/* + * X509_CERT_AUX routines. These are used to encode additional user + * modifiable data about a certificate. This data is appended to the X509 + * encoding when the *_X509_AUX routines are used. This means that the + * "traditional" X509 routines will simply ignore the extra data. + */ + +static X509_CERT_AUX *aux_get(X509 *x); + +ASN1_SEQUENCE(X509_CERT_AUX) = { + ASN1_SEQUENCE_OF_OPT(X509_CERT_AUX, trust, ASN1_OBJECT), + ASN1_IMP_SEQUENCE_OF_OPT(X509_CERT_AUX, reject, ASN1_OBJECT, 0), + ASN1_OPT(X509_CERT_AUX, alias, ASN1_UTF8STRING), + ASN1_OPT(X509_CERT_AUX, keyid, ASN1_OCTET_STRING), + ASN1_IMP_SEQUENCE_OF_OPT(X509_CERT_AUX, other, X509_ALGOR, 1) +} ASN1_SEQUENCE_END(X509_CERT_AUX) + +IMPLEMENT_ASN1_FUNCTIONS(X509_CERT_AUX) + +int X509_trusted(const X509 *x) +{ + return x->aux ? 1 : 0; +} + +static X509_CERT_AUX *aux_get(X509 *x) +{ + if (x == NULL) + return NULL; + if (x->aux == NULL && (x->aux = X509_CERT_AUX_new()) == NULL) + return NULL; + return x->aux; +} + +int X509_alias_set1(X509 *x, const unsigned char *name, int len) +{ + X509_CERT_AUX *aux; + if (!name) { + if (!x || !x->aux || !x->aux->alias) + return 1; + ASN1_UTF8STRING_free(x->aux->alias); + x->aux->alias = NULL; + return 1; + } + if ((aux = aux_get(x)) == NULL) + return 0; + if (aux->alias == NULL && (aux->alias = ASN1_UTF8STRING_new()) == NULL) + return 0; + return ASN1_STRING_set(aux->alias, name, len); +} + +int X509_keyid_set1(X509 *x, const unsigned char *id, int len) +{ + X509_CERT_AUX *aux; + if (!id) { + if (!x || !x->aux || !x->aux->keyid) + return 1; + ASN1_OCTET_STRING_free(x->aux->keyid); + x->aux->keyid = NULL; + return 1; + } + if ((aux = aux_get(x)) == NULL) + return 0; + if (aux->keyid == NULL + && (aux->keyid = ASN1_OCTET_STRING_new()) == NULL) + return 0; + return ASN1_STRING_set(aux->keyid, id, len); +} + +unsigned char *X509_alias_get0(X509 *x, int *len) +{ + if (!x->aux || !x->aux->alias) + return NULL; + if (len) + *len = x->aux->alias->length; + return x->aux->alias->data; +} + +unsigned char *X509_keyid_get0(X509 *x, int *len) +{ + if (!x->aux || !x->aux->keyid) + return NULL; + if (len) + *len = x->aux->keyid->length; + return x->aux->keyid->data; +} + +int X509_add1_trust_object(X509 *x, const ASN1_OBJECT *obj) +{ + X509_CERT_AUX *aux; + ASN1_OBJECT *objtmp = NULL; + if (obj) { + objtmp = OBJ_dup(obj); + if (!objtmp) + return 0; + } + if ((aux = aux_get(x)) == NULL) + goto err; + if (aux->trust == NULL + && (aux->trust = sk_ASN1_OBJECT_new_null()) == NULL) + goto err; + if (!objtmp || sk_ASN1_OBJECT_push(aux->trust, objtmp)) + return 1; + err: + ASN1_OBJECT_free(objtmp); + return 0; +} + +int X509_add1_reject_object(X509 *x, const ASN1_OBJECT *obj) +{ + X509_CERT_AUX *aux; + ASN1_OBJECT *objtmp; + if ((objtmp = OBJ_dup(obj)) == NULL) + return 0; + if ((aux = aux_get(x)) == NULL) + goto err; + if (aux->reject == NULL + && (aux->reject = sk_ASN1_OBJECT_new_null()) == NULL) + goto err; + return sk_ASN1_OBJECT_push(aux->reject, objtmp); + err: + ASN1_OBJECT_free(objtmp); + return 0; +} + +void X509_trust_clear(X509 *x) +{ + if (x->aux) { + sk_ASN1_OBJECT_pop_free(x->aux->trust, ASN1_OBJECT_free); + x->aux->trust = NULL; + } +} + +void X509_reject_clear(X509 *x) +{ + if (x->aux) { + sk_ASN1_OBJECT_pop_free(x->aux->reject, ASN1_OBJECT_free); + x->aux->reject = NULL; + } +} + +STACK_OF(ASN1_OBJECT) *X509_get0_trust_objects(X509 *x) +{ + if (x->aux != NULL) + return x->aux->trust; + return NULL; +} + +STACK_OF(ASN1_OBJECT) *X509_get0_reject_objects(X509 *x) +{ + if (x->aux != NULL) + return x->aux->reject; + return NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/build.info b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/build.info new file mode 100644 index 000000000..4ab648849 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/build.info @@ -0,0 +1,8 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + v3_bcons.c v3_bitst.c v3_conf.c v3_extku.c v3_ia5.c v3_lib.c \ + v3_prn.c v3_utl.c v3err.c v3_genn.c v3_alt.c v3_skey.c v3_akey.c v3_pku.c \ + v3_int.c v3_enum.c v3_sxnet.c v3_cpols.c v3_crld.c v3_purp.c v3_info.c \ + v3_akeya.c v3_pmaps.c v3_pcons.c v3_ncons.c v3_pcia.c v3_pci.c \ + pcy_cache.c pcy_node.c pcy_data.c pcy_map.c pcy_tree.c pcy_lib.c \ + v3_asid.c v3_addr.c v3_tlsf.c v3_admis.c diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/ext_dat.h b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/ext_dat.h new file mode 100644 index 000000000..762e264bb --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/ext_dat.h @@ -0,0 +1,25 @@ +/* + * Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +int name_cmp(const char *name, const char *cmp); + +extern const X509V3_EXT_METHOD v3_bcons, v3_nscert, v3_key_usage, v3_ext_ku; +extern const X509V3_EXT_METHOD v3_pkey_usage_period, v3_sxnet, v3_info, v3_sinfo; +extern const X509V3_EXT_METHOD v3_ns_ia5_list[8], v3_alt[3], v3_skey_id, v3_akey_id; +extern const X509V3_EXT_METHOD v3_crl_num, v3_crl_reason, v3_crl_invdate; +extern const X509V3_EXT_METHOD v3_delta_crl, v3_cpols, v3_crld, v3_freshest_crl; +extern const X509V3_EXT_METHOD v3_ocsp_nonce, v3_ocsp_accresp, v3_ocsp_acutoff; +extern const X509V3_EXT_METHOD v3_ocsp_crlid, v3_ocsp_nocheck, v3_ocsp_serviceloc; +extern const X509V3_EXT_METHOD v3_crl_hold, v3_pci; +extern const X509V3_EXT_METHOD v3_policy_mappings, v3_policy_constraints; +extern const X509V3_EXT_METHOD v3_name_constraints, v3_inhibit_anyp, v3_idp; +extern const X509V3_EXT_METHOD v3_addr, v3_asid; +extern const X509V3_EXT_METHOD v3_ct_scts[3]; +extern const X509V3_EXT_METHOD v3_tls_feature; +extern const X509V3_EXT_METHOD v3_ext_admission; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/pcy_cache.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/pcy_cache.c new file mode 100644 index 000000000..623870b1f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/pcy_cache.c @@ -0,0 +1,224 @@ +/* + * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include +#include +#include "internal/x509_int.h" + +#include "pcy_int.h" + +static int policy_data_cmp(const X509_POLICY_DATA *const *a, + const X509_POLICY_DATA *const *b); +static int policy_cache_set_int(long *out, ASN1_INTEGER *value); + +/* + * Set cache entry according to CertificatePolicies extension. Note: this + * destroys the passed CERTIFICATEPOLICIES structure. + */ + +static int policy_cache_create(X509 *x, + CERTIFICATEPOLICIES *policies, int crit) +{ + int i, num, ret = 0; + X509_POLICY_CACHE *cache = x->policy_cache; + X509_POLICY_DATA *data = NULL; + POLICYINFO *policy; + + if ((num = sk_POLICYINFO_num(policies)) <= 0) + goto bad_policy; + cache->data = sk_X509_POLICY_DATA_new(policy_data_cmp); + if (cache->data == NULL) { + X509V3err(X509V3_F_POLICY_CACHE_CREATE, ERR_R_MALLOC_FAILURE); + goto just_cleanup; + } + for (i = 0; i < num; i++) { + policy = sk_POLICYINFO_value(policies, i); + data = policy_data_new(policy, NULL, crit); + if (data == NULL) { + X509V3err(X509V3_F_POLICY_CACHE_CREATE, ERR_R_MALLOC_FAILURE); + goto just_cleanup; + } + /* + * Duplicate policy OIDs are illegal: reject if matches found. + */ + if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) { + if (cache->anyPolicy) { + ret = -1; + goto bad_policy; + } + cache->anyPolicy = data; + } else if (sk_X509_POLICY_DATA_find(cache->data, data) >=0 ) { + ret = -1; + goto bad_policy; + } else if (!sk_X509_POLICY_DATA_push(cache->data, data)) { + X509V3err(X509V3_F_POLICY_CACHE_CREATE, ERR_R_MALLOC_FAILURE); + goto bad_policy; + } + data = NULL; + } + ret = 1; + + bad_policy: + if (ret == -1) + x->ex_flags |= EXFLAG_INVALID_POLICY; + policy_data_free(data); + just_cleanup: + sk_POLICYINFO_pop_free(policies, POLICYINFO_free); + if (ret <= 0) { + sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free); + cache->data = NULL; + } + return ret; +} + +static int policy_cache_new(X509 *x) +{ + X509_POLICY_CACHE *cache; + ASN1_INTEGER *ext_any = NULL; + POLICY_CONSTRAINTS *ext_pcons = NULL; + CERTIFICATEPOLICIES *ext_cpols = NULL; + POLICY_MAPPINGS *ext_pmaps = NULL; + int i; + + if (x->policy_cache != NULL) + return 1; + cache = OPENSSL_malloc(sizeof(*cache)); + if (cache == NULL) { + X509V3err(X509V3_F_POLICY_CACHE_NEW, ERR_R_MALLOC_FAILURE); + return 0; + } + cache->anyPolicy = NULL; + cache->data = NULL; + cache->any_skip = -1; + cache->explicit_skip = -1; + cache->map_skip = -1; + + x->policy_cache = cache; + + /* + * Handle requireExplicitPolicy *first*. Need to process this even if we + * don't have any policies. + */ + ext_pcons = X509_get_ext_d2i(x, NID_policy_constraints, &i, NULL); + + if (!ext_pcons) { + if (i != -1) + goto bad_cache; + } else { + if (!ext_pcons->requireExplicitPolicy + && !ext_pcons->inhibitPolicyMapping) + goto bad_cache; + if (!policy_cache_set_int(&cache->explicit_skip, + ext_pcons->requireExplicitPolicy)) + goto bad_cache; + if (!policy_cache_set_int(&cache->map_skip, + ext_pcons->inhibitPolicyMapping)) + goto bad_cache; + } + + /* Process CertificatePolicies */ + + ext_cpols = X509_get_ext_d2i(x, NID_certificate_policies, &i, NULL); + /* + * If no CertificatePolicies extension or problem decoding then there is + * no point continuing because the valid policies will be NULL. + */ + if (!ext_cpols) { + /* If not absent some problem with extension */ + if (i != -1) + goto bad_cache; + return 1; + } + + i = policy_cache_create(x, ext_cpols, i); + + /* NB: ext_cpols freed by policy_cache_set_policies */ + + if (i <= 0) + return i; + + ext_pmaps = X509_get_ext_d2i(x, NID_policy_mappings, &i, NULL); + + if (!ext_pmaps) { + /* If not absent some problem with extension */ + if (i != -1) + goto bad_cache; + } else { + i = policy_cache_set_mapping(x, ext_pmaps); + if (i <= 0) + goto bad_cache; + } + + ext_any = X509_get_ext_d2i(x, NID_inhibit_any_policy, &i, NULL); + + if (!ext_any) { + if (i != -1) + goto bad_cache; + } else if (!policy_cache_set_int(&cache->any_skip, ext_any)) + goto bad_cache; + goto just_cleanup; + + bad_cache: + x->ex_flags |= EXFLAG_INVALID_POLICY; + + just_cleanup: + POLICY_CONSTRAINTS_free(ext_pcons); + ASN1_INTEGER_free(ext_any); + return 1; + +} + +void policy_cache_free(X509_POLICY_CACHE *cache) +{ + if (!cache) + return; + policy_data_free(cache->anyPolicy); + sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free); + OPENSSL_free(cache); +} + +const X509_POLICY_CACHE *policy_cache_set(X509 *x) +{ + + if (x->policy_cache == NULL) { + CRYPTO_THREAD_write_lock(x->lock); + policy_cache_new(x); + CRYPTO_THREAD_unlock(x->lock); + } + + return x->policy_cache; + +} + +X509_POLICY_DATA *policy_cache_find_data(const X509_POLICY_CACHE *cache, + const ASN1_OBJECT *id) +{ + int idx; + X509_POLICY_DATA tmp; + tmp.valid_policy = (ASN1_OBJECT *)id; + idx = sk_X509_POLICY_DATA_find(cache->data, &tmp); + return sk_X509_POLICY_DATA_value(cache->data, idx); +} + +static int policy_data_cmp(const X509_POLICY_DATA *const *a, + const X509_POLICY_DATA *const *b) +{ + return OBJ_cmp((*a)->valid_policy, (*b)->valid_policy); +} + +static int policy_cache_set_int(long *out, ASN1_INTEGER *value) +{ + if (value == NULL) + return 1; + if (value->type == V_ASN1_NEG_INTEGER) + return 0; + *out = ASN1_INTEGER_get(value); + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/pcy_data.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/pcy_data.c new file mode 100644 index 000000000..bd3bb0e40 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/pcy_data.c @@ -0,0 +1,81 @@ +/* + * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include +#include + +#include "pcy_int.h" + +/* Policy Node routines */ + +void policy_data_free(X509_POLICY_DATA *data) +{ + if (data == NULL) + return; + ASN1_OBJECT_free(data->valid_policy); + /* Don't free qualifiers if shared */ + if (!(data->flags & POLICY_DATA_FLAG_SHARED_QUALIFIERS)) + sk_POLICYQUALINFO_pop_free(data->qualifier_set, POLICYQUALINFO_free); + sk_ASN1_OBJECT_pop_free(data->expected_policy_set, ASN1_OBJECT_free); + OPENSSL_free(data); +} + +/* + * Create a data based on an existing policy. If 'id' is NULL use the OID in + * the policy, otherwise use 'id'. This behaviour covers the two types of + * data in RFC3280: data with from a CertificatePolicies extension and + * additional data with just the qualifiers of anyPolicy and ID from another + * source. + */ + +X509_POLICY_DATA *policy_data_new(POLICYINFO *policy, + const ASN1_OBJECT *cid, int crit) +{ + X509_POLICY_DATA *ret; + ASN1_OBJECT *id; + + if (policy == NULL && cid == NULL) + return NULL; + if (cid) { + id = OBJ_dup(cid); + if (id == NULL) + return NULL; + } else + id = NULL; + ret = OPENSSL_zalloc(sizeof(*ret)); + if (ret == NULL) { + X509V3err(X509V3_F_POLICY_DATA_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + ret->expected_policy_set = sk_ASN1_OBJECT_new_null(); + if (ret->expected_policy_set == NULL) { + OPENSSL_free(ret); + ASN1_OBJECT_free(id); + X509V3err(X509V3_F_POLICY_DATA_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (crit) + ret->flags = POLICY_DATA_FLAG_CRITICAL; + + if (id) + ret->valid_policy = id; + else { + ret->valid_policy = policy->policyid; + policy->policyid = NULL; + } + + if (policy) { + ret->qualifier_set = policy->qualifiers; + policy->qualifiers = NULL; + } + + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/pcy_int.h b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/pcy_int.h new file mode 100644 index 000000000..5daf78de4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/pcy_int.h @@ -0,0 +1,167 @@ +/* + * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +typedef struct X509_POLICY_DATA_st X509_POLICY_DATA; + +DEFINE_STACK_OF(X509_POLICY_DATA) + +/* Internal structures */ + +/* + * This structure and the field names correspond to the Policy 'node' of + * RFC3280. NB this structure contains no pointers to parent or child data: + * X509_POLICY_NODE contains that. This means that the main policy data can + * be kept static and cached with the certificate. + */ + +struct X509_POLICY_DATA_st { + unsigned int flags; + /* Policy OID and qualifiers for this data */ + ASN1_OBJECT *valid_policy; + STACK_OF(POLICYQUALINFO) *qualifier_set; + STACK_OF(ASN1_OBJECT) *expected_policy_set; +}; + +/* X509_POLICY_DATA flags values */ + +/* + * This flag indicates the structure has been mapped using a policy mapping + * extension. If policy mapping is not active its references get deleted. + */ + +#define POLICY_DATA_FLAG_MAPPED 0x1 + +/* + * This flag indicates the data doesn't correspond to a policy in Certificate + * Policies: it has been mapped to any policy. + */ + +#define POLICY_DATA_FLAG_MAPPED_ANY 0x2 + +/* AND with flags to see if any mapping has occurred */ + +#define POLICY_DATA_FLAG_MAP_MASK 0x3 + +/* qualifiers are shared and shouldn't be freed */ + +#define POLICY_DATA_FLAG_SHARED_QUALIFIERS 0x4 + +/* Parent node is an extra node and should be freed */ + +#define POLICY_DATA_FLAG_EXTRA_NODE 0x8 + +/* Corresponding CertificatePolicies is critical */ + +#define POLICY_DATA_FLAG_CRITICAL 0x10 + +/* This structure is cached with a certificate */ + +struct X509_POLICY_CACHE_st { + /* anyPolicy data or NULL if no anyPolicy */ + X509_POLICY_DATA *anyPolicy; + /* other policy data */ + STACK_OF(X509_POLICY_DATA) *data; + /* If InhibitAnyPolicy present this is its value or -1 if absent. */ + long any_skip; + /* + * If policyConstraints and requireExplicitPolicy present this is its + * value or -1 if absent. + */ + long explicit_skip; + /* + * If policyConstraints and policyMapping present this is its value or -1 + * if absent. + */ + long map_skip; +}; + +/* + * #define POLICY_CACHE_FLAG_CRITICAL POLICY_DATA_FLAG_CRITICAL + */ + +/* This structure represents the relationship between nodes */ + +struct X509_POLICY_NODE_st { + /* node data this refers to */ + const X509_POLICY_DATA *data; + /* Parent node */ + X509_POLICY_NODE *parent; + /* Number of child nodes */ + int nchild; +}; + +struct X509_POLICY_LEVEL_st { + /* Cert for this level */ + X509 *cert; + /* nodes at this level */ + STACK_OF(X509_POLICY_NODE) *nodes; + /* anyPolicy node */ + X509_POLICY_NODE *anyPolicy; + /* Extra data */ + /* + * STACK_OF(X509_POLICY_DATA) *extra_data; + */ + unsigned int flags; +}; + +struct X509_POLICY_TREE_st { + /* This is the tree 'level' data */ + X509_POLICY_LEVEL *levels; + int nlevel; + /* + * Extra policy data when additional nodes (not from the certificate) are + * required. + */ + STACK_OF(X509_POLICY_DATA) *extra_data; + /* This is the authority constrained policy set */ + STACK_OF(X509_POLICY_NODE) *auth_policies; + STACK_OF(X509_POLICY_NODE) *user_policies; + unsigned int flags; +}; + +/* Set if anyPolicy present in user policies */ +#define POLICY_FLAG_ANY_POLICY 0x2 + +/* Useful macros */ + +#define node_data_critical(data) (data->flags & POLICY_DATA_FLAG_CRITICAL) +#define node_critical(node) node_data_critical(node->data) + +/* Internal functions */ + +X509_POLICY_DATA *policy_data_new(POLICYINFO *policy, const ASN1_OBJECT *id, + int crit); +void policy_data_free(X509_POLICY_DATA *data); + +X509_POLICY_DATA *policy_cache_find_data(const X509_POLICY_CACHE *cache, + const ASN1_OBJECT *id); +int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps); + +STACK_OF(X509_POLICY_NODE) *policy_node_cmp_new(void); + +void policy_cache_init(void); + +void policy_cache_free(X509_POLICY_CACHE *cache); + +X509_POLICY_NODE *level_find_node(const X509_POLICY_LEVEL *level, + const X509_POLICY_NODE *parent, + const ASN1_OBJECT *id); + +X509_POLICY_NODE *tree_find_sk(STACK_OF(X509_POLICY_NODE) *sk, + const ASN1_OBJECT *id); + +X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level, + X509_POLICY_DATA *data, + X509_POLICY_NODE *parent, + X509_POLICY_TREE *tree); +void policy_node_free(X509_POLICY_NODE *node); +int policy_node_match(const X509_POLICY_LEVEL *lvl, + const X509_POLICY_NODE *node, const ASN1_OBJECT *oid); + +const X509_POLICY_CACHE *policy_cache_set(X509 *x); diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/pcy_lib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/pcy_lib.c new file mode 100644 index 000000000..67f7eafc6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/pcy_lib.c @@ -0,0 +1,108 @@ +/* + * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include +#include + +#include "pcy_int.h" + +/* accessor functions */ + +/* X509_POLICY_TREE stuff */ + +int X509_policy_tree_level_count(const X509_POLICY_TREE *tree) +{ + if (!tree) + return 0; + return tree->nlevel; +} + +X509_POLICY_LEVEL *X509_policy_tree_get0_level(const X509_POLICY_TREE *tree, + int i) +{ + if (!tree || (i < 0) || (i >= tree->nlevel)) + return NULL; + return tree->levels + i; +} + +STACK_OF(X509_POLICY_NODE) *X509_policy_tree_get0_policies(const + X509_POLICY_TREE + *tree) +{ + if (!tree) + return NULL; + return tree->auth_policies; +} + +STACK_OF(X509_POLICY_NODE) *X509_policy_tree_get0_user_policies(const + X509_POLICY_TREE + *tree) +{ + if (!tree) + return NULL; + if (tree->flags & POLICY_FLAG_ANY_POLICY) + return tree->auth_policies; + else + return tree->user_policies; +} + +/* X509_POLICY_LEVEL stuff */ + +int X509_policy_level_node_count(X509_POLICY_LEVEL *level) +{ + int n; + if (!level) + return 0; + if (level->anyPolicy) + n = 1; + else + n = 0; + if (level->nodes) + n += sk_X509_POLICY_NODE_num(level->nodes); + return n; +} + +X509_POLICY_NODE *X509_policy_level_get0_node(X509_POLICY_LEVEL *level, int i) +{ + if (!level) + return NULL; + if (level->anyPolicy) { + if (i == 0) + return level->anyPolicy; + i--; + } + return sk_X509_POLICY_NODE_value(level->nodes, i); +} + +/* X509_POLICY_NODE stuff */ + +const ASN1_OBJECT *X509_policy_node_get0_policy(const X509_POLICY_NODE *node) +{ + if (!node) + return NULL; + return node->data->valid_policy; +} + +STACK_OF(POLICYQUALINFO) *X509_policy_node_get0_qualifiers(const + X509_POLICY_NODE + *node) +{ + if (!node) + return NULL; + return node->data->qualifier_set; +} + +const X509_POLICY_NODE *X509_policy_node_get0_parent(const X509_POLICY_NODE + *node) +{ + if (!node) + return NULL; + return node->parent; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/pcy_map.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/pcy_map.c new file mode 100644 index 000000000..ab9dd21b7 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/pcy_map.c @@ -0,0 +1,81 @@ +/* + * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include +#include +#include "internal/x509_int.h" + +#include "pcy_int.h" + +/* + * Set policy mapping entries in cache. Note: this modifies the passed + * POLICY_MAPPINGS structure + */ + +int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps) +{ + POLICY_MAPPING *map; + X509_POLICY_DATA *data; + X509_POLICY_CACHE *cache = x->policy_cache; + int i; + int ret = 0; + if (sk_POLICY_MAPPING_num(maps) == 0) { + ret = -1; + goto bad_mapping; + } + for (i = 0; i < sk_POLICY_MAPPING_num(maps); i++) { + map = sk_POLICY_MAPPING_value(maps, i); + /* Reject if map to or from anyPolicy */ + if ((OBJ_obj2nid(map->subjectDomainPolicy) == NID_any_policy) + || (OBJ_obj2nid(map->issuerDomainPolicy) == NID_any_policy)) { + ret = -1; + goto bad_mapping; + } + + /* Attempt to find matching policy data */ + data = policy_cache_find_data(cache, map->issuerDomainPolicy); + /* If we don't have anyPolicy can't map */ + if (data == NULL && !cache->anyPolicy) + continue; + + /* Create a NODE from anyPolicy */ + if (data == NULL) { + data = policy_data_new(NULL, map->issuerDomainPolicy, + cache->anyPolicy->flags + & POLICY_DATA_FLAG_CRITICAL); + if (data == NULL) + goto bad_mapping; + data->qualifier_set = cache->anyPolicy->qualifier_set; + /* + * map->issuerDomainPolicy = NULL; + */ + data->flags |= POLICY_DATA_FLAG_MAPPED_ANY; + data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS; + if (!sk_X509_POLICY_DATA_push(cache->data, data)) { + policy_data_free(data); + goto bad_mapping; + } + } else + data->flags |= POLICY_DATA_FLAG_MAPPED; + if (!sk_ASN1_OBJECT_push(data->expected_policy_set, + map->subjectDomainPolicy)) + goto bad_mapping; + map->subjectDomainPolicy = NULL; + + } + + ret = 1; + bad_mapping: + if (ret == -1) + x->ex_flags |= EXFLAG_INVALID_POLICY; + sk_POLICY_MAPPING_pop_free(maps, POLICY_MAPPING_free); + return ret; + +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/pcy_node.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/pcy_node.c new file mode 100644 index 000000000..1ffe98498 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/pcy_node.c @@ -0,0 +1,147 @@ +/* + * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include + +#include "pcy_int.h" + +static int node_cmp(const X509_POLICY_NODE *const *a, + const X509_POLICY_NODE *const *b) +{ + return OBJ_cmp((*a)->data->valid_policy, (*b)->data->valid_policy); +} + +STACK_OF(X509_POLICY_NODE) *policy_node_cmp_new(void) +{ + return sk_X509_POLICY_NODE_new(node_cmp); +} + +X509_POLICY_NODE *tree_find_sk(STACK_OF(X509_POLICY_NODE) *nodes, + const ASN1_OBJECT *id) +{ + X509_POLICY_DATA n; + X509_POLICY_NODE l; + int idx; + + n.valid_policy = (ASN1_OBJECT *)id; + l.data = &n; + + idx = sk_X509_POLICY_NODE_find(nodes, &l); + return sk_X509_POLICY_NODE_value(nodes, idx); + +} + +X509_POLICY_NODE *level_find_node(const X509_POLICY_LEVEL *level, + const X509_POLICY_NODE *parent, + const ASN1_OBJECT *id) +{ + X509_POLICY_NODE *node; + int i; + for (i = 0; i < sk_X509_POLICY_NODE_num(level->nodes); i++) { + node = sk_X509_POLICY_NODE_value(level->nodes, i); + if (node->parent == parent) { + if (!OBJ_cmp(node->data->valid_policy, id)) + return node; + } + } + return NULL; +} + +X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level, + X509_POLICY_DATA *data, + X509_POLICY_NODE *parent, + X509_POLICY_TREE *tree) +{ + X509_POLICY_NODE *node; + + node = OPENSSL_zalloc(sizeof(*node)); + if (node == NULL) { + X509V3err(X509V3_F_LEVEL_ADD_NODE, ERR_R_MALLOC_FAILURE); + return NULL; + } + node->data = data; + node->parent = parent; + if (level) { + if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) { + if (level->anyPolicy) + goto node_error; + level->anyPolicy = node; + } else { + + if (level->nodes == NULL) + level->nodes = policy_node_cmp_new(); + if (level->nodes == NULL) { + X509V3err(X509V3_F_LEVEL_ADD_NODE, ERR_R_MALLOC_FAILURE); + goto node_error; + } + if (!sk_X509_POLICY_NODE_push(level->nodes, node)) { + X509V3err(X509V3_F_LEVEL_ADD_NODE, ERR_R_MALLOC_FAILURE); + goto node_error; + } + } + } + + if (tree) { + if (tree->extra_data == NULL) + tree->extra_data = sk_X509_POLICY_DATA_new_null(); + if (tree->extra_data == NULL){ + X509V3err(X509V3_F_LEVEL_ADD_NODE, ERR_R_MALLOC_FAILURE); + goto node_error; + } + if (!sk_X509_POLICY_DATA_push(tree->extra_data, data)) { + X509V3err(X509V3_F_LEVEL_ADD_NODE, ERR_R_MALLOC_FAILURE); + goto node_error; + } + } + + if (parent) + parent->nchild++; + + return node; + + node_error: + policy_node_free(node); + return NULL; +} + +void policy_node_free(X509_POLICY_NODE *node) +{ + OPENSSL_free(node); +} + +/* + * See if a policy node matches a policy OID. If mapping enabled look through + * expected policy set otherwise just valid policy. + */ + +int policy_node_match(const X509_POLICY_LEVEL *lvl, + const X509_POLICY_NODE *node, const ASN1_OBJECT *oid) +{ + int i; + ASN1_OBJECT *policy_oid; + const X509_POLICY_DATA *x = node->data; + + if ((lvl->flags & X509_V_FLAG_INHIBIT_MAP) + || !(x->flags & POLICY_DATA_FLAG_MAP_MASK)) { + if (!OBJ_cmp(x->valid_policy, oid)) + return 1; + return 0; + } + + for (i = 0; i < sk_ASN1_OBJECT_num(x->expected_policy_set); i++) { + policy_oid = sk_ASN1_OBJECT_value(x->expected_policy_set, i); + if (!OBJ_cmp(policy_oid, oid)) + return 1; + } + return 0; + +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/pcy_tree.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/pcy_tree.c new file mode 100644 index 000000000..87f51d001 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/pcy_tree.c @@ -0,0 +1,703 @@ +/* + * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include +#include + +#include "pcy_int.h" + +/* + * Enable this to print out the complete policy tree at various point during + * evaluation. + */ + +/* + * #define OPENSSL_POLICY_DEBUG + */ + +#ifdef OPENSSL_POLICY_DEBUG + +static void expected_print(BIO *err, X509_POLICY_LEVEL *lev, + X509_POLICY_NODE *node, int indent) +{ + if ((lev->flags & X509_V_FLAG_INHIBIT_MAP) + || !(node->data->flags & POLICY_DATA_FLAG_MAP_MASK)) + BIO_puts(err, " Not Mapped\n"); + else { + int i; + STACK_OF(ASN1_OBJECT) *pset = node->data->expected_policy_set; + ASN1_OBJECT *oid; + BIO_puts(err, " Expected: "); + for (i = 0; i < sk_ASN1_OBJECT_num(pset); i++) { + oid = sk_ASN1_OBJECT_value(pset, i); + if (i) + BIO_puts(err, ", "); + i2a_ASN1_OBJECT(err, oid); + } + BIO_puts(err, "\n"); + } +} + +static void tree_print(char *str, X509_POLICY_TREE *tree, + X509_POLICY_LEVEL *curr) +{ + BIO *err = BIO_new_fp(stderr, BIO_NOCLOSE); + X509_POLICY_LEVEL *plev; + + if (err == NULL) + return; + if (!curr) + curr = tree->levels + tree->nlevel; + else + curr++; + + BIO_printf(err, "Level print after %s\n", str); + BIO_printf(err, "Printing Up to Level %ld\n", curr - tree->levels); + for (plev = tree->levels; plev != curr; plev++) { + int i; + + BIO_printf(err, "Level %ld, flags = %x\n", + (long)(plev - tree->levels), plev->flags); + for (i = 0; i < sk_X509_POLICY_NODE_num(plev->nodes); i++) { + X509_POLICY_NODE *node = sk_X509_POLICY_NODE_value(plev->nodes, i); + + X509_POLICY_NODE_print(err, node, 2); + expected_print(err, plev, node, 2); + BIO_printf(err, " Flags: %x\n", node->data->flags); + } + if (plev->anyPolicy) + X509_POLICY_NODE_print(err, plev->anyPolicy, 2); + } + BIO_free(err); +} +#endif + +/*- + * Return value: <= 0 on error, or positive bit mask: + * + * X509_PCY_TREE_VALID: valid tree + * X509_PCY_TREE_EMPTY: empty tree (including bare TA case) + * X509_PCY_TREE_EXPLICIT: explicit policy required + */ +static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, + unsigned int flags) +{ + X509_POLICY_TREE *tree; + X509_POLICY_LEVEL *level; + const X509_POLICY_CACHE *cache; + X509_POLICY_DATA *data = NULL; + int ret = X509_PCY_TREE_VALID; + int n = sk_X509_num(certs) - 1; /* RFC5280 paths omit the TA */ + int explicit_policy = (flags & X509_V_FLAG_EXPLICIT_POLICY) ? 0 : n+1; + int any_skip = (flags & X509_V_FLAG_INHIBIT_ANY) ? 0 : n+1; + int map_skip = (flags & X509_V_FLAG_INHIBIT_MAP) ? 0 : n+1; + int i; + + *ptree = NULL; + + /* Can't do anything with just a trust anchor */ + if (n == 0) + return X509_PCY_TREE_EMPTY; + + /* + * First setup the policy cache in all n non-TA certificates, this will be + * used in X509_verify_cert() which will invoke the verify callback for all + * certificates with invalid policy extensions. + */ + for (i = n - 1; i >= 0; i--) { + X509 *x = sk_X509_value(certs, i); + + /* Call for side-effect of computing hash and caching extensions */ + X509_check_purpose(x, -1, 0); + + /* If cache is NULL, likely ENOMEM: return immediately */ + if (policy_cache_set(x) == NULL) + return X509_PCY_TREE_INTERNAL; + } + + /* + * At this point check for invalid policies and required explicit policy. + * Note that the explicit_policy counter is a count-down to zero, with the + * requirement kicking in if and once it does that. The counter is + * decremented for every non-self-issued certificate in the path, but may + * be further reduced by policy constraints in a non-leaf certificate. + * + * The ultimate policy set is the intersection of all the policies along + * the path, if we hit a certificate with an empty policy set, and explicit + * policy is required we're done. + */ + for (i = n - 1; + i >= 0 && (explicit_policy > 0 || (ret & X509_PCY_TREE_EMPTY) == 0); + i--) { + X509 *x = sk_X509_value(certs, i); + uint32_t ex_flags = X509_get_extension_flags(x); + + /* All the policies are already cached, we can return early */ + if (ex_flags & EXFLAG_INVALID_POLICY) + return X509_PCY_TREE_INVALID; + + /* Access the cache which we now know exists */ + cache = policy_cache_set(x); + + if ((ret & X509_PCY_TREE_VALID) && cache->data == NULL) + ret = X509_PCY_TREE_EMPTY; + if (explicit_policy > 0) { + if (!(ex_flags & EXFLAG_SI)) + explicit_policy--; + if ((cache->explicit_skip >= 0) + && (cache->explicit_skip < explicit_policy)) + explicit_policy = cache->explicit_skip; + } + } + + if (explicit_policy == 0) + ret |= X509_PCY_TREE_EXPLICIT; + if ((ret & X509_PCY_TREE_VALID) == 0) + return ret; + + /* If we get this far initialize the tree */ + if ((tree = OPENSSL_zalloc(sizeof(*tree))) == NULL) { + X509V3err(X509V3_F_TREE_INIT, ERR_R_MALLOC_FAILURE); + return X509_PCY_TREE_INTERNAL; + } + + /* + * http://tools.ietf.org/html/rfc5280#section-6.1.2, figure 3. + * + * The top level is implicitly for the trust anchor with valid expected + * policies of anyPolicy. (RFC 5280 has the TA at depth 0 and the leaf at + * depth n, we have the leaf at depth 0 and the TA at depth n). + */ + if ((tree->levels = OPENSSL_zalloc(sizeof(*tree->levels)*(n+1))) == NULL) { + OPENSSL_free(tree); + X509V3err(X509V3_F_TREE_INIT, ERR_R_MALLOC_FAILURE); + return X509_PCY_TREE_INTERNAL; + } + tree->nlevel = n+1; + level = tree->levels; + if ((data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0)) == NULL) + goto bad_tree; + if (level_add_node(level, data, NULL, tree) == NULL) { + policy_data_free(data); + goto bad_tree; + } + + /* + * In this pass initialize all the tree levels and whether anyPolicy and + * policy mapping are inhibited at each level. + */ + for (i = n - 1; i >= 0; i--) { + X509 *x = sk_X509_value(certs, i); + uint32_t ex_flags = X509_get_extension_flags(x); + + /* Access the cache which we now know exists */ + cache = policy_cache_set(x); + + X509_up_ref(x); + (++level)->cert = x; + + if (!cache->anyPolicy) + level->flags |= X509_V_FLAG_INHIBIT_ANY; + + /* Determine inhibit any and inhibit map flags */ + if (any_skip == 0) { + /* + * Any matching allowed only if certificate is self issued and not + * the last in the chain. + */ + if (!(ex_flags & EXFLAG_SI) || (i == 0)) + level->flags |= X509_V_FLAG_INHIBIT_ANY; + } else { + if (!(ex_flags & EXFLAG_SI)) + any_skip--; + if ((cache->any_skip >= 0) && (cache->any_skip < any_skip)) + any_skip = cache->any_skip; + } + + if (map_skip == 0) + level->flags |= X509_V_FLAG_INHIBIT_MAP; + else { + if (!(ex_flags & EXFLAG_SI)) + map_skip--; + if ((cache->map_skip >= 0) && (cache->map_skip < map_skip)) + map_skip = cache->map_skip; + } + } + + *ptree = tree; + return ret; + + bad_tree: + X509_policy_tree_free(tree); + return X509_PCY_TREE_INTERNAL; +} + +/* + * Return value: 1 on success, 0 otherwise + */ +static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr, + X509_POLICY_DATA *data) +{ + X509_POLICY_LEVEL *last = curr - 1; + int i, matched = 0; + + /* Iterate through all in nodes linking matches */ + for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) { + X509_POLICY_NODE *node = sk_X509_POLICY_NODE_value(last->nodes, i); + + if (policy_node_match(last, node, data->valid_policy)) { + if (level_add_node(curr, data, node, NULL) == NULL) + return 0; + matched = 1; + } + } + if (!matched && last->anyPolicy) { + if (level_add_node(curr, data, last->anyPolicy, NULL) == NULL) + return 0; + } + return 1; +} + +/* + * This corresponds to RFC3280 6.1.3(d)(1): link any data from + * CertificatePolicies onto matching parent or anyPolicy if no match. + * + * Return value: 1 on success, 0 otherwise. + */ +static int tree_link_nodes(X509_POLICY_LEVEL *curr, + const X509_POLICY_CACHE *cache) +{ + int i; + + for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++) { + X509_POLICY_DATA *data = sk_X509_POLICY_DATA_value(cache->data, i); + + /* Look for matching nodes in previous level */ + if (!tree_link_matching_nodes(curr, data)) + return 0; + } + return 1; +} + +/* + * This corresponds to RFC3280 6.1.3(d)(2): Create new data for any unmatched + * policies in the parent and link to anyPolicy. + * + * Return value: 1 on success, 0 otherwise. + */ +static int tree_add_unmatched(X509_POLICY_LEVEL *curr, + const X509_POLICY_CACHE *cache, + const ASN1_OBJECT *id, + X509_POLICY_NODE *node, X509_POLICY_TREE *tree) +{ + X509_POLICY_DATA *data; + + if (id == NULL) + id = node->data->valid_policy; + /* + * Create a new node with qualifiers from anyPolicy and id from unmatched + * node. + */ + if ((data = policy_data_new(NULL, id, node_critical(node))) == NULL) + return 0; + + /* Curr may not have anyPolicy */ + data->qualifier_set = cache->anyPolicy->qualifier_set; + data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS; + if (level_add_node(curr, data, node, tree) == NULL) { + policy_data_free(data); + return 0; + } + return 1; +} + +/* + * Return value: 1 on success, 0 otherwise. + */ +static int tree_link_unmatched(X509_POLICY_LEVEL *curr, + const X509_POLICY_CACHE *cache, + X509_POLICY_NODE *node, X509_POLICY_TREE *tree) +{ + const X509_POLICY_LEVEL *last = curr - 1; + int i; + + if ((last->flags & X509_V_FLAG_INHIBIT_MAP) + || !(node->data->flags & POLICY_DATA_FLAG_MAPPED)) { + /* If no policy mapping: matched if one child present */ + if (node->nchild) + return 1; + if (!tree_add_unmatched(curr, cache, NULL, node, tree)) + return 0; + /* Add it */ + } else { + /* If mapping: matched if one child per expected policy set */ + STACK_OF(ASN1_OBJECT) *expset = node->data->expected_policy_set; + if (node->nchild == sk_ASN1_OBJECT_num(expset)) + return 1; + /* Locate unmatched nodes */ + for (i = 0; i < sk_ASN1_OBJECT_num(expset); i++) { + ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(expset, i); + if (level_find_node(curr, node, oid)) + continue; + if (!tree_add_unmatched(curr, cache, oid, node, tree)) + return 0; + } + + } + return 1; +} + +/* + * Return value: 1 on success, 0 otherwise + */ +static int tree_link_any(X509_POLICY_LEVEL *curr, + const X509_POLICY_CACHE *cache, + X509_POLICY_TREE *tree) +{ + int i; + X509_POLICY_NODE *node; + X509_POLICY_LEVEL *last = curr - 1; + + for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) { + node = sk_X509_POLICY_NODE_value(last->nodes, i); + + if (!tree_link_unmatched(curr, cache, node, tree)) + return 0; + } + /* Finally add link to anyPolicy */ + if (last->anyPolicy && + level_add_node(curr, cache->anyPolicy, last->anyPolicy, NULL) == NULL) + return 0; + return 1; +} + +/*- + * Prune the tree: delete any child mapped child data on the current level then + * proceed up the tree deleting any data with no children. If we ever have no + * data on a level we can halt because the tree will be empty. + * + * Return value: <= 0 error, otherwise one of: + * + * X509_PCY_TREE_VALID: valid tree + * X509_PCY_TREE_EMPTY: empty tree + */ +static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr) +{ + STACK_OF(X509_POLICY_NODE) *nodes; + X509_POLICY_NODE *node; + int i; + nodes = curr->nodes; + if (curr->flags & X509_V_FLAG_INHIBIT_MAP) { + for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) { + node = sk_X509_POLICY_NODE_value(nodes, i); + /* Delete any mapped data: see RFC3280 XXXX */ + if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK) { + node->parent->nchild--; + OPENSSL_free(node); + (void)sk_X509_POLICY_NODE_delete(nodes, i); + } + } + } + + for (;;) { + --curr; + nodes = curr->nodes; + for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) { + node = sk_X509_POLICY_NODE_value(nodes, i); + if (node->nchild == 0) { + node->parent->nchild--; + OPENSSL_free(node); + (void)sk_X509_POLICY_NODE_delete(nodes, i); + } + } + if (curr->anyPolicy && !curr->anyPolicy->nchild) { + if (curr->anyPolicy->parent) + curr->anyPolicy->parent->nchild--; + OPENSSL_free(curr->anyPolicy); + curr->anyPolicy = NULL; + } + if (curr == tree->levels) { + /* If we zapped anyPolicy at top then tree is empty */ + if (!curr->anyPolicy) + return X509_PCY_TREE_EMPTY; + break; + } + } + return X509_PCY_TREE_VALID; +} + +/* + * Return value: 1 on success, 0 otherwise. + */ +static int tree_add_auth_node(STACK_OF(X509_POLICY_NODE) **pnodes, + X509_POLICY_NODE *pcy) +{ + if (*pnodes == NULL && + (*pnodes = policy_node_cmp_new()) == NULL) + return 0; + if (sk_X509_POLICY_NODE_find(*pnodes, pcy) >= 0) + return 1; + return sk_X509_POLICY_NODE_push(*pnodes, pcy) != 0; +} + +#define TREE_CALC_FAILURE 0 +#define TREE_CALC_OK_NOFREE 1 +#define TREE_CALC_OK_DOFREE 2 + +/*- + * Calculate the authority set based on policy tree. The 'pnodes' parameter is + * used as a store for the set of policy nodes used to calculate the user set. + * If the authority set is not anyPolicy then pnodes will just point to the + * authority set. If however the authority set is anyPolicy then the set of + * valid policies (other than anyPolicy) is store in pnodes. + * + * Return value: + * TREE_CALC_FAILURE on failure, + * TREE_CALC_OK_NOFREE on success and pnodes need not be freed, + * TREE_CALC_OK_DOFREE on success and pnodes needs to be freed + */ +static int tree_calculate_authority_set(X509_POLICY_TREE *tree, + STACK_OF(X509_POLICY_NODE) **pnodes) +{ + X509_POLICY_LEVEL *curr; + X509_POLICY_NODE *node, *anyptr; + STACK_OF(X509_POLICY_NODE) **addnodes; + int i, j; + curr = tree->levels + tree->nlevel - 1; + + /* If last level contains anyPolicy set is anyPolicy */ + if (curr->anyPolicy) { + if (!tree_add_auth_node(&tree->auth_policies, curr->anyPolicy)) + return TREE_CALC_FAILURE; + addnodes = pnodes; + } else + /* Add policies to authority set */ + addnodes = &tree->auth_policies; + + curr = tree->levels; + for (i = 1; i < tree->nlevel; i++) { + /* + * If no anyPolicy node on this this level it can't appear on lower + * levels so end search. + */ + if ((anyptr = curr->anyPolicy) == NULL) + break; + curr++; + for (j = 0; j < sk_X509_POLICY_NODE_num(curr->nodes); j++) { + node = sk_X509_POLICY_NODE_value(curr->nodes, j); + if ((node->parent == anyptr) + && !tree_add_auth_node(addnodes, node)) { + if (addnodes == pnodes) { + sk_X509_POLICY_NODE_free(*pnodes); + *pnodes = NULL; + } + return TREE_CALC_FAILURE; + } + } + } + if (addnodes == pnodes) + return TREE_CALC_OK_DOFREE; + + *pnodes = tree->auth_policies; + return TREE_CALC_OK_NOFREE; +} + +/* + * Return value: 1 on success, 0 otherwise. + */ +static int tree_calculate_user_set(X509_POLICY_TREE *tree, + STACK_OF(ASN1_OBJECT) *policy_oids, + STACK_OF(X509_POLICY_NODE) *auth_nodes) +{ + int i; + X509_POLICY_NODE *node; + ASN1_OBJECT *oid; + X509_POLICY_NODE *anyPolicy; + X509_POLICY_DATA *extra; + + /* + * Check if anyPolicy present in authority constrained policy set: this + * will happen if it is a leaf node. + */ + if (sk_ASN1_OBJECT_num(policy_oids) <= 0) + return 1; + + anyPolicy = tree->levels[tree->nlevel - 1].anyPolicy; + + for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) { + oid = sk_ASN1_OBJECT_value(policy_oids, i); + if (OBJ_obj2nid(oid) == NID_any_policy) { + tree->flags |= POLICY_FLAG_ANY_POLICY; + return 1; + } + } + + for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) { + oid = sk_ASN1_OBJECT_value(policy_oids, i); + node = tree_find_sk(auth_nodes, oid); + if (!node) { + if (!anyPolicy) + continue; + /* + * Create a new node with policy ID from user set and qualifiers + * from anyPolicy. + */ + extra = policy_data_new(NULL, oid, node_critical(anyPolicy)); + if (extra == NULL) + return 0; + extra->qualifier_set = anyPolicy->data->qualifier_set; + extra->flags = POLICY_DATA_FLAG_SHARED_QUALIFIERS + | POLICY_DATA_FLAG_EXTRA_NODE; + node = level_add_node(NULL, extra, anyPolicy->parent, tree); + } + if (!tree->user_policies) { + tree->user_policies = sk_X509_POLICY_NODE_new_null(); + if (!tree->user_policies) + return 1; + } + if (!sk_X509_POLICY_NODE_push(tree->user_policies, node)) + return 0; + } + return 1; +} + +/*- + * Return value: <= 0 error, otherwise one of: + * X509_PCY_TREE_VALID: valid tree + * X509_PCY_TREE_EMPTY: empty tree + * (see tree_prune()). + */ +static int tree_evaluate(X509_POLICY_TREE *tree) +{ + int ret, i; + X509_POLICY_LEVEL *curr = tree->levels + 1; + const X509_POLICY_CACHE *cache; + + for (i = 1; i < tree->nlevel; i++, curr++) { + cache = policy_cache_set(curr->cert); + if (!tree_link_nodes(curr, cache)) + return X509_PCY_TREE_INTERNAL; + + if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY) + && !tree_link_any(curr, cache, tree)) + return X509_PCY_TREE_INTERNAL; +#ifdef OPENSSL_POLICY_DEBUG + tree_print("before tree_prune()", tree, curr); +#endif + ret = tree_prune(tree, curr); + if (ret != X509_PCY_TREE_VALID) + return ret; + } + return X509_PCY_TREE_VALID; +} + +static void exnode_free(X509_POLICY_NODE *node) +{ + if (node->data && (node->data->flags & POLICY_DATA_FLAG_EXTRA_NODE)) + OPENSSL_free(node); +} + +void X509_policy_tree_free(X509_POLICY_TREE *tree) +{ + X509_POLICY_LEVEL *curr; + int i; + + if (!tree) + return; + + sk_X509_POLICY_NODE_free(tree->auth_policies); + sk_X509_POLICY_NODE_pop_free(tree->user_policies, exnode_free); + + for (i = 0, curr = tree->levels; i < tree->nlevel; i++, curr++) { + X509_free(curr->cert); + sk_X509_POLICY_NODE_pop_free(curr->nodes, policy_node_free); + policy_node_free(curr->anyPolicy); + } + + sk_X509_POLICY_DATA_pop_free(tree->extra_data, policy_data_free); + OPENSSL_free(tree->levels); + OPENSSL_free(tree); + +} + +/*- + * Application policy checking function. + * Return codes: + * X509_PCY_TREE_FAILURE: Failure to satisfy explicit policy + * X509_PCY_TREE_INVALID: Inconsistent or invalid extensions + * X509_PCY_TREE_INTERNAL: Internal error, most likely malloc + * X509_PCY_TREE_VALID: Success (null tree if empty or bare TA) + */ +int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy, + STACK_OF(X509) *certs, + STACK_OF(ASN1_OBJECT) *policy_oids, unsigned int flags) +{ + int init_ret; + int ret; + int calc_ret; + X509_POLICY_TREE *tree = NULL; + STACK_OF(X509_POLICY_NODE) *nodes, *auth_nodes = NULL; + + *ptree = NULL; + *pexplicit_policy = 0; + init_ret = tree_init(&tree, certs, flags); + + if (init_ret <= 0) + return init_ret; + + if ((init_ret & X509_PCY_TREE_EXPLICIT) == 0) { + if (init_ret & X509_PCY_TREE_EMPTY) { + X509_policy_tree_free(tree); + return X509_PCY_TREE_VALID; + } + } else { + *pexplicit_policy = 1; + /* Tree empty and requireExplicit True: Error */ + if (init_ret & X509_PCY_TREE_EMPTY) + return X509_PCY_TREE_FAILURE; + } + + ret = tree_evaluate(tree); +#ifdef OPENSSL_POLICY_DEBUG + tree_print("tree_evaluate()", tree, NULL); +#endif + if (ret <= 0) + goto error; + + if (ret == X509_PCY_TREE_EMPTY) { + X509_policy_tree_free(tree); + if (init_ret & X509_PCY_TREE_EXPLICIT) + return X509_PCY_TREE_FAILURE; + return X509_PCY_TREE_VALID; + } + + /* Tree is not empty: continue */ + + if ((calc_ret = tree_calculate_authority_set(tree, &auth_nodes)) == 0) + goto error; + ret = tree_calculate_user_set(tree, policy_oids, auth_nodes); + if (calc_ret == TREE_CALC_OK_DOFREE) + sk_X509_POLICY_NODE_free(auth_nodes); + if (!ret) + goto error; + + *ptree = tree; + + if (init_ret & X509_PCY_TREE_EXPLICIT) { + nodes = X509_policy_tree_get0_user_policies(tree); + if (sk_X509_POLICY_NODE_num(nodes) <= 0) + return X509_PCY_TREE_FAILURE; + } + return X509_PCY_TREE_VALID; + + error: + X509_policy_tree_free(tree); + return X509_PCY_TREE_INTERNAL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/standard_exts.h b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/standard_exts.h new file mode 100644 index 000000000..944f4de02 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/standard_exts.h @@ -0,0 +1,78 @@ +/* + * Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This table will be searched using OBJ_bsearch so it *must* kept in order + * of the ext_nid values. + */ + +static const X509V3_EXT_METHOD *standard_exts[] = { + &v3_nscert, + &v3_ns_ia5_list[0], + &v3_ns_ia5_list[1], + &v3_ns_ia5_list[2], + &v3_ns_ia5_list[3], + &v3_ns_ia5_list[4], + &v3_ns_ia5_list[5], + &v3_ns_ia5_list[6], + &v3_skey_id, + &v3_key_usage, + &v3_pkey_usage_period, + &v3_alt[0], + &v3_alt[1], + &v3_bcons, + &v3_crl_num, + &v3_cpols, + &v3_akey_id, + &v3_crld, + &v3_ext_ku, + &v3_delta_crl, + &v3_crl_reason, +#ifndef OPENSSL_NO_OCSP + &v3_crl_invdate, +#endif + &v3_sxnet, + &v3_info, +#ifndef OPENSSL_NO_RFC3779 + &v3_addr, + &v3_asid, +#endif +#ifndef OPENSSL_NO_OCSP + &v3_ocsp_nonce, + &v3_ocsp_crlid, + &v3_ocsp_accresp, + &v3_ocsp_nocheck, + &v3_ocsp_acutoff, + &v3_ocsp_serviceloc, +#endif + &v3_sinfo, + &v3_policy_constraints, +#ifndef OPENSSL_NO_OCSP + &v3_crl_hold, +#endif + &v3_pci, + &v3_name_constraints, + &v3_policy_mappings, + &v3_inhibit_anyp, + &v3_idp, + &v3_alt[2], + &v3_freshest_crl, +#ifndef OPENSSL_NO_CT + &v3_ct_scts[0], + &v3_ct_scts[1], + &v3_ct_scts[2], +#endif + &v3_tls_feature, + &v3_ext_admission +}; + +/* Number of standard extensions */ + +#define STANDARD_EXTENSION_COUNT OSSL_NELEM(standard_exts) + diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_addr.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_addr.c new file mode 100644 index 000000000..bb58e0484 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_addr.c @@ -0,0 +1,1315 @@ +/* + * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Implementation of RFC 3779 section 2.2. + */ + +#include +#include + +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include "internal/x509_int.h" +#include "ext_dat.h" + +#ifndef OPENSSL_NO_RFC3779 + +/* + * OpenSSL ASN.1 template translation of RFC 3779 2.2.3. + */ + +ASN1_SEQUENCE(IPAddressRange) = { + ASN1_SIMPLE(IPAddressRange, min, ASN1_BIT_STRING), + ASN1_SIMPLE(IPAddressRange, max, ASN1_BIT_STRING) +} ASN1_SEQUENCE_END(IPAddressRange) + +ASN1_CHOICE(IPAddressOrRange) = { + ASN1_SIMPLE(IPAddressOrRange, u.addressPrefix, ASN1_BIT_STRING), + ASN1_SIMPLE(IPAddressOrRange, u.addressRange, IPAddressRange) +} ASN1_CHOICE_END(IPAddressOrRange) + +ASN1_CHOICE(IPAddressChoice) = { + ASN1_SIMPLE(IPAddressChoice, u.inherit, ASN1_NULL), + ASN1_SEQUENCE_OF(IPAddressChoice, u.addressesOrRanges, IPAddressOrRange) +} ASN1_CHOICE_END(IPAddressChoice) + +ASN1_SEQUENCE(IPAddressFamily) = { + ASN1_SIMPLE(IPAddressFamily, addressFamily, ASN1_OCTET_STRING), + ASN1_SIMPLE(IPAddressFamily, ipAddressChoice, IPAddressChoice) +} ASN1_SEQUENCE_END(IPAddressFamily) + +ASN1_ITEM_TEMPLATE(IPAddrBlocks) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, + IPAddrBlocks, IPAddressFamily) +static_ASN1_ITEM_TEMPLATE_END(IPAddrBlocks) + +IMPLEMENT_ASN1_FUNCTIONS(IPAddressRange) +IMPLEMENT_ASN1_FUNCTIONS(IPAddressOrRange) +IMPLEMENT_ASN1_FUNCTIONS(IPAddressChoice) +IMPLEMENT_ASN1_FUNCTIONS(IPAddressFamily) + +/* + * How much buffer space do we need for a raw address? + */ +#define ADDR_RAW_BUF_LEN 16 + +/* + * What's the address length associated with this AFI? + */ +static int length_from_afi(const unsigned afi) +{ + switch (afi) { + case IANA_AFI_IPV4: + return 4; + case IANA_AFI_IPV6: + return 16; + default: + return 0; + } +} + +/* + * Extract the AFI from an IPAddressFamily. + */ +unsigned int X509v3_addr_get_afi(const IPAddressFamily *f) +{ + if (f == NULL + || f->addressFamily == NULL + || f->addressFamily->data == NULL + || f->addressFamily->length < 2) + return 0; + return (f->addressFamily->data[0] << 8) | f->addressFamily->data[1]; +} + +/* + * Expand the bitstring form of an address into a raw byte array. + * At the moment this is coded for simplicity, not speed. + */ +static int addr_expand(unsigned char *addr, + const ASN1_BIT_STRING *bs, + const int length, const unsigned char fill) +{ + if (bs->length < 0 || bs->length > length) + return 0; + if (bs->length > 0) { + memcpy(addr, bs->data, bs->length); + if ((bs->flags & 7) != 0) { + unsigned char mask = 0xFF >> (8 - (bs->flags & 7)); + if (fill == 0) + addr[bs->length - 1] &= ~mask; + else + addr[bs->length - 1] |= mask; + } + } + memset(addr + bs->length, fill, length - bs->length); + return 1; +} + +/* + * Extract the prefix length from a bitstring. + */ +#define addr_prefixlen(bs) ((int) ((bs)->length * 8 - ((bs)->flags & 7))) + +/* + * i2r handler for one address bitstring. + */ +static int i2r_address(BIO *out, + const unsigned afi, + const unsigned char fill, const ASN1_BIT_STRING *bs) +{ + unsigned char addr[ADDR_RAW_BUF_LEN]; + int i, n; + + if (bs->length < 0) + return 0; + switch (afi) { + case IANA_AFI_IPV4: + if (!addr_expand(addr, bs, 4, fill)) + return 0; + BIO_printf(out, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); + break; + case IANA_AFI_IPV6: + if (!addr_expand(addr, bs, 16, fill)) + return 0; + for (n = 16; n > 1 && addr[n - 1] == 0x00 && addr[n - 2] == 0x00; + n -= 2) ; + for (i = 0; i < n; i += 2) + BIO_printf(out, "%x%s", (addr[i] << 8) | addr[i + 1], + (i < 14 ? ":" : "")); + if (i < 16) + BIO_puts(out, ":"); + if (i == 0) + BIO_puts(out, ":"); + break; + default: + for (i = 0; i < bs->length; i++) + BIO_printf(out, "%s%02x", (i > 0 ? ":" : ""), bs->data[i]); + BIO_printf(out, "[%d]", (int)(bs->flags & 7)); + break; + } + return 1; +} + +/* + * i2r handler for a sequence of addresses and ranges. + */ +static int i2r_IPAddressOrRanges(BIO *out, + const int indent, + const IPAddressOrRanges *aors, + const unsigned afi) +{ + int i; + for (i = 0; i < sk_IPAddressOrRange_num(aors); i++) { + const IPAddressOrRange *aor = sk_IPAddressOrRange_value(aors, i); + BIO_printf(out, "%*s", indent, ""); + switch (aor->type) { + case IPAddressOrRange_addressPrefix: + if (!i2r_address(out, afi, 0x00, aor->u.addressPrefix)) + return 0; + BIO_printf(out, "/%d\n", addr_prefixlen(aor->u.addressPrefix)); + continue; + case IPAddressOrRange_addressRange: + if (!i2r_address(out, afi, 0x00, aor->u.addressRange->min)) + return 0; + BIO_puts(out, "-"); + if (!i2r_address(out, afi, 0xFF, aor->u.addressRange->max)) + return 0; + BIO_puts(out, "\n"); + continue; + } + } + return 1; +} + +/* + * i2r handler for an IPAddrBlocks extension. + */ +static int i2r_IPAddrBlocks(const X509V3_EXT_METHOD *method, + void *ext, BIO *out, int indent) +{ + const IPAddrBlocks *addr = ext; + int i; + for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { + IPAddressFamily *f = sk_IPAddressFamily_value(addr, i); + const unsigned int afi = X509v3_addr_get_afi(f); + switch (afi) { + case IANA_AFI_IPV4: + BIO_printf(out, "%*sIPv4", indent, ""); + break; + case IANA_AFI_IPV6: + BIO_printf(out, "%*sIPv6", indent, ""); + break; + default: + BIO_printf(out, "%*sUnknown AFI %u", indent, "", afi); + break; + } + if (f->addressFamily->length > 2) { + switch (f->addressFamily->data[2]) { + case 1: + BIO_puts(out, " (Unicast)"); + break; + case 2: + BIO_puts(out, " (Multicast)"); + break; + case 3: + BIO_puts(out, " (Unicast/Multicast)"); + break; + case 4: + BIO_puts(out, " (MPLS)"); + break; + case 64: + BIO_puts(out, " (Tunnel)"); + break; + case 65: + BIO_puts(out, " (VPLS)"); + break; + case 66: + BIO_puts(out, " (BGP MDT)"); + break; + case 128: + BIO_puts(out, " (MPLS-labeled VPN)"); + break; + default: + BIO_printf(out, " (Unknown SAFI %u)", + (unsigned)f->addressFamily->data[2]); + break; + } + } + switch (f->ipAddressChoice->type) { + case IPAddressChoice_inherit: + BIO_puts(out, ": inherit\n"); + break; + case IPAddressChoice_addressesOrRanges: + BIO_puts(out, ":\n"); + if (!i2r_IPAddressOrRanges(out, + indent + 2, + f->ipAddressChoice-> + u.addressesOrRanges, afi)) + return 0; + break; + } + } + return 1; +} + +/* + * Sort comparison function for a sequence of IPAddressOrRange + * elements. + * + * There's no sane answer we can give if addr_expand() fails, and an + * assertion failure on externally supplied data is seriously uncool, + * so we just arbitrarily declare that if given invalid inputs this + * function returns -1. If this messes up your preferred sort order + * for garbage input, tough noogies. + */ +static int IPAddressOrRange_cmp(const IPAddressOrRange *a, + const IPAddressOrRange *b, const int length) +{ + unsigned char addr_a[ADDR_RAW_BUF_LEN], addr_b[ADDR_RAW_BUF_LEN]; + int prefixlen_a = 0, prefixlen_b = 0; + int r; + + switch (a->type) { + case IPAddressOrRange_addressPrefix: + if (!addr_expand(addr_a, a->u.addressPrefix, length, 0x00)) + return -1; + prefixlen_a = addr_prefixlen(a->u.addressPrefix); + break; + case IPAddressOrRange_addressRange: + if (!addr_expand(addr_a, a->u.addressRange->min, length, 0x00)) + return -1; + prefixlen_a = length * 8; + break; + } + + switch (b->type) { + case IPAddressOrRange_addressPrefix: + if (!addr_expand(addr_b, b->u.addressPrefix, length, 0x00)) + return -1; + prefixlen_b = addr_prefixlen(b->u.addressPrefix); + break; + case IPAddressOrRange_addressRange: + if (!addr_expand(addr_b, b->u.addressRange->min, length, 0x00)) + return -1; + prefixlen_b = length * 8; + break; + } + + if ((r = memcmp(addr_a, addr_b, length)) != 0) + return r; + else + return prefixlen_a - prefixlen_b; +} + +/* + * IPv4-specific closure over IPAddressOrRange_cmp, since sk_sort() + * comparison routines are only allowed two arguments. + */ +static int v4IPAddressOrRange_cmp(const IPAddressOrRange *const *a, + const IPAddressOrRange *const *b) +{ + return IPAddressOrRange_cmp(*a, *b, 4); +} + +/* + * IPv6-specific closure over IPAddressOrRange_cmp, since sk_sort() + * comparison routines are only allowed two arguments. + */ +static int v6IPAddressOrRange_cmp(const IPAddressOrRange *const *a, + const IPAddressOrRange *const *b) +{ + return IPAddressOrRange_cmp(*a, *b, 16); +} + +/* + * Calculate whether a range collapses to a prefix. + * See last paragraph of RFC 3779 2.2.3.7. + */ +static int range_should_be_prefix(const unsigned char *min, + const unsigned char *max, const int length) +{ + unsigned char mask; + int i, j; + + if (memcmp(min, max, length) <= 0) + return -1; + for (i = 0; i < length && min[i] == max[i]; i++) ; + for (j = length - 1; j >= 0 && min[j] == 0x00 && max[j] == 0xFF; j--) ; + if (i < j) + return -1; + if (i > j) + return i * 8; + mask = min[i] ^ max[i]; + switch (mask) { + case 0x01: + j = 7; + break; + case 0x03: + j = 6; + break; + case 0x07: + j = 5; + break; + case 0x0F: + j = 4; + break; + case 0x1F: + j = 3; + break; + case 0x3F: + j = 2; + break; + case 0x7F: + j = 1; + break; + default: + return -1; + } + if ((min[i] & mask) != 0 || (max[i] & mask) != mask) + return -1; + else + return i * 8 + j; +} + +/* + * Construct a prefix. + */ +static int make_addressPrefix(IPAddressOrRange **result, + unsigned char *addr, const int prefixlen) +{ + int bytelen = (prefixlen + 7) / 8, bitlen = prefixlen % 8; + IPAddressOrRange *aor = IPAddressOrRange_new(); + + if (aor == NULL) + return 0; + aor->type = IPAddressOrRange_addressPrefix; + if (aor->u.addressPrefix == NULL && + (aor->u.addressPrefix = ASN1_BIT_STRING_new()) == NULL) + goto err; + if (!ASN1_BIT_STRING_set(aor->u.addressPrefix, addr, bytelen)) + goto err; + aor->u.addressPrefix->flags &= ~7; + aor->u.addressPrefix->flags |= ASN1_STRING_FLAG_BITS_LEFT; + if (bitlen > 0) { + aor->u.addressPrefix->data[bytelen - 1] &= ~(0xFF >> bitlen); + aor->u.addressPrefix->flags |= 8 - bitlen; + } + + *result = aor; + return 1; + + err: + IPAddressOrRange_free(aor); + return 0; +} + +/* + * Construct a range. If it can be expressed as a prefix, + * return a prefix instead. Doing this here simplifies + * the rest of the code considerably. + */ +static int make_addressRange(IPAddressOrRange **result, + unsigned char *min, + unsigned char *max, const int length) +{ + IPAddressOrRange *aor; + int i, prefixlen; + + if ((prefixlen = range_should_be_prefix(min, max, length)) >= 0) + return make_addressPrefix(result, min, prefixlen); + + if ((aor = IPAddressOrRange_new()) == NULL) + return 0; + aor->type = IPAddressOrRange_addressRange; + if ((aor->u.addressRange = IPAddressRange_new()) == NULL) + goto err; + if (aor->u.addressRange->min == NULL && + (aor->u.addressRange->min = ASN1_BIT_STRING_new()) == NULL) + goto err; + if (aor->u.addressRange->max == NULL && + (aor->u.addressRange->max = ASN1_BIT_STRING_new()) == NULL) + goto err; + + for (i = length; i > 0 && min[i - 1] == 0x00; --i) ; + if (!ASN1_BIT_STRING_set(aor->u.addressRange->min, min, i)) + goto err; + aor->u.addressRange->min->flags &= ~7; + aor->u.addressRange->min->flags |= ASN1_STRING_FLAG_BITS_LEFT; + if (i > 0) { + unsigned char b = min[i - 1]; + int j = 1; + while ((b & (0xFFU >> j)) != 0) + ++j; + aor->u.addressRange->min->flags |= 8 - j; + } + + for (i = length; i > 0 && max[i - 1] == 0xFF; --i) ; + if (!ASN1_BIT_STRING_set(aor->u.addressRange->max, max, i)) + goto err; + aor->u.addressRange->max->flags &= ~7; + aor->u.addressRange->max->flags |= ASN1_STRING_FLAG_BITS_LEFT; + if (i > 0) { + unsigned char b = max[i - 1]; + int j = 1; + while ((b & (0xFFU >> j)) != (0xFFU >> j)) + ++j; + aor->u.addressRange->max->flags |= 8 - j; + } + + *result = aor; + return 1; + + err: + IPAddressOrRange_free(aor); + return 0; +} + +/* + * Construct a new address family or find an existing one. + */ +static IPAddressFamily *make_IPAddressFamily(IPAddrBlocks *addr, + const unsigned afi, + const unsigned *safi) +{ + IPAddressFamily *f; + unsigned char key[3]; + int keylen; + int i; + + key[0] = (afi >> 8) & 0xFF; + key[1] = afi & 0xFF; + if (safi != NULL) { + key[2] = *safi & 0xFF; + keylen = 3; + } else { + keylen = 2; + } + + for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { + f = sk_IPAddressFamily_value(addr, i); + if (f->addressFamily->length == keylen && + !memcmp(f->addressFamily->data, key, keylen)) + return f; + } + + if ((f = IPAddressFamily_new()) == NULL) + goto err; + if (f->ipAddressChoice == NULL && + (f->ipAddressChoice = IPAddressChoice_new()) == NULL) + goto err; + if (f->addressFamily == NULL && + (f->addressFamily = ASN1_OCTET_STRING_new()) == NULL) + goto err; + if (!ASN1_OCTET_STRING_set(f->addressFamily, key, keylen)) + goto err; + if (!sk_IPAddressFamily_push(addr, f)) + goto err; + + return f; + + err: + IPAddressFamily_free(f); + return NULL; +} + +/* + * Add an inheritance element. + */ +int X509v3_addr_add_inherit(IPAddrBlocks *addr, + const unsigned afi, const unsigned *safi) +{ + IPAddressFamily *f = make_IPAddressFamily(addr, afi, safi); + if (f == NULL || + f->ipAddressChoice == NULL || + (f->ipAddressChoice->type == IPAddressChoice_addressesOrRanges && + f->ipAddressChoice->u.addressesOrRanges != NULL)) + return 0; + if (f->ipAddressChoice->type == IPAddressChoice_inherit && + f->ipAddressChoice->u.inherit != NULL) + return 1; + if (f->ipAddressChoice->u.inherit == NULL && + (f->ipAddressChoice->u.inherit = ASN1_NULL_new()) == NULL) + return 0; + f->ipAddressChoice->type = IPAddressChoice_inherit; + return 1; +} + +/* + * Construct an IPAddressOrRange sequence, or return an existing one. + */ +static IPAddressOrRanges *make_prefix_or_range(IPAddrBlocks *addr, + const unsigned afi, + const unsigned *safi) +{ + IPAddressFamily *f = make_IPAddressFamily(addr, afi, safi); + IPAddressOrRanges *aors = NULL; + + if (f == NULL || + f->ipAddressChoice == NULL || + (f->ipAddressChoice->type == IPAddressChoice_inherit && + f->ipAddressChoice->u.inherit != NULL)) + return NULL; + if (f->ipAddressChoice->type == IPAddressChoice_addressesOrRanges) + aors = f->ipAddressChoice->u.addressesOrRanges; + if (aors != NULL) + return aors; + if ((aors = sk_IPAddressOrRange_new_null()) == NULL) + return NULL; + switch (afi) { + case IANA_AFI_IPV4: + (void)sk_IPAddressOrRange_set_cmp_func(aors, v4IPAddressOrRange_cmp); + break; + case IANA_AFI_IPV6: + (void)sk_IPAddressOrRange_set_cmp_func(aors, v6IPAddressOrRange_cmp); + break; + } + f->ipAddressChoice->type = IPAddressChoice_addressesOrRanges; + f->ipAddressChoice->u.addressesOrRanges = aors; + return aors; +} + +/* + * Add a prefix. + */ +int X509v3_addr_add_prefix(IPAddrBlocks *addr, + const unsigned afi, + const unsigned *safi, + unsigned char *a, const int prefixlen) +{ + IPAddressOrRanges *aors = make_prefix_or_range(addr, afi, safi); + IPAddressOrRange *aor; + if (aors == NULL || !make_addressPrefix(&aor, a, prefixlen)) + return 0; + if (sk_IPAddressOrRange_push(aors, aor)) + return 1; + IPAddressOrRange_free(aor); + return 0; +} + +/* + * Add a range. + */ +int X509v3_addr_add_range(IPAddrBlocks *addr, + const unsigned afi, + const unsigned *safi, + unsigned char *min, unsigned char *max) +{ + IPAddressOrRanges *aors = make_prefix_or_range(addr, afi, safi); + IPAddressOrRange *aor; + int length = length_from_afi(afi); + if (aors == NULL) + return 0; + if (!make_addressRange(&aor, min, max, length)) + return 0; + if (sk_IPAddressOrRange_push(aors, aor)) + return 1; + IPAddressOrRange_free(aor); + return 0; +} + +/* + * Extract min and max values from an IPAddressOrRange. + */ +static int extract_min_max(IPAddressOrRange *aor, + unsigned char *min, unsigned char *max, int length) +{ + if (aor == NULL || min == NULL || max == NULL) + return 0; + switch (aor->type) { + case IPAddressOrRange_addressPrefix: + return (addr_expand(min, aor->u.addressPrefix, length, 0x00) && + addr_expand(max, aor->u.addressPrefix, length, 0xFF)); + case IPAddressOrRange_addressRange: + return (addr_expand(min, aor->u.addressRange->min, length, 0x00) && + addr_expand(max, aor->u.addressRange->max, length, 0xFF)); + } + return 0; +} + +/* + * Public wrapper for extract_min_max(). + */ +int X509v3_addr_get_range(IPAddressOrRange *aor, + const unsigned afi, + unsigned char *min, + unsigned char *max, const int length) +{ + int afi_length = length_from_afi(afi); + if (aor == NULL || min == NULL || max == NULL || + afi_length == 0 || length < afi_length || + (aor->type != IPAddressOrRange_addressPrefix && + aor->type != IPAddressOrRange_addressRange) || + !extract_min_max(aor, min, max, afi_length)) + return 0; + + return afi_length; +} + +/* + * Sort comparison function for a sequence of IPAddressFamily. + * + * The last paragraph of RFC 3779 2.2.3.3 is slightly ambiguous about + * the ordering: I can read it as meaning that IPv6 without a SAFI + * comes before IPv4 with a SAFI, which seems pretty weird. The + * examples in appendix B suggest that the author intended the + * null-SAFI rule to apply only within a single AFI, which is what I + * would have expected and is what the following code implements. + */ +static int IPAddressFamily_cmp(const IPAddressFamily *const *a_, + const IPAddressFamily *const *b_) +{ + const ASN1_OCTET_STRING *a = (*a_)->addressFamily; + const ASN1_OCTET_STRING *b = (*b_)->addressFamily; + int len = ((a->length <= b->length) ? a->length : b->length); + int cmp = memcmp(a->data, b->data, len); + return cmp ? cmp : a->length - b->length; +} + +/* + * Check whether an IPAddrBLocks is in canonical form. + */ +int X509v3_addr_is_canonical(IPAddrBlocks *addr) +{ + unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; + unsigned char b_min[ADDR_RAW_BUF_LEN], b_max[ADDR_RAW_BUF_LEN]; + IPAddressOrRanges *aors; + int i, j, k; + + /* + * Empty extension is canonical. + */ + if (addr == NULL) + return 1; + + /* + * Check whether the top-level list is in order. + */ + for (i = 0; i < sk_IPAddressFamily_num(addr) - 1; i++) { + const IPAddressFamily *a = sk_IPAddressFamily_value(addr, i); + const IPAddressFamily *b = sk_IPAddressFamily_value(addr, i + 1); + if (IPAddressFamily_cmp(&a, &b) >= 0) + return 0; + } + + /* + * Top level's ok, now check each address family. + */ + for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { + IPAddressFamily *f = sk_IPAddressFamily_value(addr, i); + int length = length_from_afi(X509v3_addr_get_afi(f)); + + /* + * Inheritance is canonical. Anything other than inheritance or + * a SEQUENCE OF IPAddressOrRange is an ASN.1 error or something. + */ + if (f == NULL || f->ipAddressChoice == NULL) + return 0; + switch (f->ipAddressChoice->type) { + case IPAddressChoice_inherit: + continue; + case IPAddressChoice_addressesOrRanges: + break; + default: + return 0; + } + + /* + * It's an IPAddressOrRanges sequence, check it. + */ + aors = f->ipAddressChoice->u.addressesOrRanges; + if (sk_IPAddressOrRange_num(aors) == 0) + return 0; + for (j = 0; j < sk_IPAddressOrRange_num(aors) - 1; j++) { + IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); + IPAddressOrRange *b = sk_IPAddressOrRange_value(aors, j + 1); + + if (!extract_min_max(a, a_min, a_max, length) || + !extract_min_max(b, b_min, b_max, length)) + return 0; + + /* + * Punt misordered list, overlapping start, or inverted range. + */ + if (memcmp(a_min, b_min, length) >= 0 || + memcmp(a_min, a_max, length) > 0 || + memcmp(b_min, b_max, length) > 0) + return 0; + + /* + * Punt if adjacent or overlapping. Check for adjacency by + * subtracting one from b_min first. + */ + for (k = length - 1; k >= 0 && b_min[k]-- == 0x00; k--) ; + if (memcmp(a_max, b_min, length) >= 0) + return 0; + + /* + * Check for range that should be expressed as a prefix. + */ + if (a->type == IPAddressOrRange_addressRange && + range_should_be_prefix(a_min, a_max, length) >= 0) + return 0; + } + + /* + * Check range to see if it's inverted or should be a + * prefix. + */ + j = sk_IPAddressOrRange_num(aors) - 1; + { + IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); + if (a != NULL && a->type == IPAddressOrRange_addressRange) { + if (!extract_min_max(a, a_min, a_max, length)) + return 0; + if (memcmp(a_min, a_max, length) > 0 || + range_should_be_prefix(a_min, a_max, length) >= 0) + return 0; + } + } + } + + /* + * If we made it through all that, we're happy. + */ + return 1; +} + +/* + * Whack an IPAddressOrRanges into canonical form. + */ +static int IPAddressOrRanges_canonize(IPAddressOrRanges *aors, + const unsigned afi) +{ + int i, j, length = length_from_afi(afi); + + /* + * Sort the IPAddressOrRanges sequence. + */ + sk_IPAddressOrRange_sort(aors); + + /* + * Clean up representation issues, punt on duplicates or overlaps. + */ + for (i = 0; i < sk_IPAddressOrRange_num(aors) - 1; i++) { + IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, i); + IPAddressOrRange *b = sk_IPAddressOrRange_value(aors, i + 1); + unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; + unsigned char b_min[ADDR_RAW_BUF_LEN], b_max[ADDR_RAW_BUF_LEN]; + + if (!extract_min_max(a, a_min, a_max, length) || + !extract_min_max(b, b_min, b_max, length)) + return 0; + + /* + * Punt inverted ranges. + */ + if (memcmp(a_min, a_max, length) > 0 || + memcmp(b_min, b_max, length) > 0) + return 0; + + /* + * Punt overlaps. + */ + if (memcmp(a_max, b_min, length) >= 0) + return 0; + + /* + * Merge if a and b are adjacent. We check for + * adjacency by subtracting one from b_min first. + */ + for (j = length - 1; j >= 0 && b_min[j]-- == 0x00; j--) ; + if (memcmp(a_max, b_min, length) == 0) { + IPAddressOrRange *merged; + if (!make_addressRange(&merged, a_min, b_max, length)) + return 0; + (void)sk_IPAddressOrRange_set(aors, i, merged); + (void)sk_IPAddressOrRange_delete(aors, i + 1); + IPAddressOrRange_free(a); + IPAddressOrRange_free(b); + --i; + continue; + } + } + + /* + * Check for inverted final range. + */ + j = sk_IPAddressOrRange_num(aors) - 1; + { + IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); + if (a != NULL && a->type == IPAddressOrRange_addressRange) { + unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; + if (!extract_min_max(a, a_min, a_max, length)) + return 0; + if (memcmp(a_min, a_max, length) > 0) + return 0; + } + } + + return 1; +} + +/* + * Whack an IPAddrBlocks extension into canonical form. + */ +int X509v3_addr_canonize(IPAddrBlocks *addr) +{ + int i; + for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { + IPAddressFamily *f = sk_IPAddressFamily_value(addr, i); + if (f->ipAddressChoice->type == IPAddressChoice_addressesOrRanges && + !IPAddressOrRanges_canonize(f->ipAddressChoice-> + u.addressesOrRanges, + X509v3_addr_get_afi(f))) + return 0; + } + (void)sk_IPAddressFamily_set_cmp_func(addr, IPAddressFamily_cmp); + sk_IPAddressFamily_sort(addr); + if (!ossl_assert(X509v3_addr_is_canonical(addr))) + return 0; + return 1; +} + +/* + * v2i handler for the IPAddrBlocks extension. + */ +static void *v2i_IPAddrBlocks(const struct v3_ext_method *method, + struct v3_ext_ctx *ctx, + STACK_OF(CONF_VALUE) *values) +{ + static const char v4addr_chars[] = "0123456789."; + static const char v6addr_chars[] = "0123456789.:abcdefABCDEF"; + IPAddrBlocks *addr = NULL; + char *s = NULL, *t; + int i; + + if ((addr = sk_IPAddressFamily_new(IPAddressFamily_cmp)) == NULL) { + X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE); + return NULL; + } + + for (i = 0; i < sk_CONF_VALUE_num(values); i++) { + CONF_VALUE *val = sk_CONF_VALUE_value(values, i); + unsigned char min[ADDR_RAW_BUF_LEN], max[ADDR_RAW_BUF_LEN]; + unsigned afi, *safi = NULL, safi_; + const char *addr_chars = NULL; + int prefixlen, i1, i2, delim, length; + + if (!name_cmp(val->name, "IPv4")) { + afi = IANA_AFI_IPV4; + } else if (!name_cmp(val->name, "IPv6")) { + afi = IANA_AFI_IPV6; + } else if (!name_cmp(val->name, "IPv4-SAFI")) { + afi = IANA_AFI_IPV4; + safi = &safi_; + } else if (!name_cmp(val->name, "IPv6-SAFI")) { + afi = IANA_AFI_IPV6; + safi = &safi_; + } else { + X509V3err(X509V3_F_V2I_IPADDRBLOCKS, + X509V3_R_EXTENSION_NAME_ERROR); + X509V3_conf_err(val); + goto err; + } + + switch (afi) { + case IANA_AFI_IPV4: + addr_chars = v4addr_chars; + break; + case IANA_AFI_IPV6: + addr_chars = v6addr_chars; + break; + } + + length = length_from_afi(afi); + + /* + * Handle SAFI, if any, and OPENSSL_strdup() so we can null-terminate + * the other input values. + */ + if (safi != NULL) { + *safi = strtoul(val->value, &t, 0); + t += strspn(t, " \t"); + if (*safi > 0xFF || *t++ != ':') { + X509V3err(X509V3_F_V2I_IPADDRBLOCKS, X509V3_R_INVALID_SAFI); + X509V3_conf_err(val); + goto err; + } + t += strspn(t, " \t"); + s = OPENSSL_strdup(t); + } else { + s = OPENSSL_strdup(val->value); + } + if (s == NULL) { + X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* + * Check for inheritance. Not worth additional complexity to + * optimize this (seldom-used) case. + */ + if (strcmp(s, "inherit") == 0) { + if (!X509v3_addr_add_inherit(addr, afi, safi)) { + X509V3err(X509V3_F_V2I_IPADDRBLOCKS, + X509V3_R_INVALID_INHERITANCE); + X509V3_conf_err(val); + goto err; + } + OPENSSL_free(s); + s = NULL; + continue; + } + + i1 = strspn(s, addr_chars); + i2 = i1 + strspn(s + i1, " \t"); + delim = s[i2++]; + s[i1] = '\0'; + + if (a2i_ipadd(min, s) != length) { + X509V3err(X509V3_F_V2I_IPADDRBLOCKS, X509V3_R_INVALID_IPADDRESS); + X509V3_conf_err(val); + goto err; + } + + switch (delim) { + case '/': + prefixlen = (int)strtoul(s + i2, &t, 10); + if (t == s + i2 || *t != '\0') { + X509V3err(X509V3_F_V2I_IPADDRBLOCKS, + X509V3_R_EXTENSION_VALUE_ERROR); + X509V3_conf_err(val); + goto err; + } + if (!X509v3_addr_add_prefix(addr, afi, safi, min, prefixlen)) { + X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE); + goto err; + } + break; + case '-': + i1 = i2 + strspn(s + i2, " \t"); + i2 = i1 + strspn(s + i1, addr_chars); + if (i1 == i2 || s[i2] != '\0') { + X509V3err(X509V3_F_V2I_IPADDRBLOCKS, + X509V3_R_EXTENSION_VALUE_ERROR); + X509V3_conf_err(val); + goto err; + } + if (a2i_ipadd(max, s + i1) != length) { + X509V3err(X509V3_F_V2I_IPADDRBLOCKS, + X509V3_R_INVALID_IPADDRESS); + X509V3_conf_err(val); + goto err; + } + if (memcmp(min, max, length_from_afi(afi)) > 0) { + X509V3err(X509V3_F_V2I_IPADDRBLOCKS, + X509V3_R_EXTENSION_VALUE_ERROR); + X509V3_conf_err(val); + goto err; + } + if (!X509v3_addr_add_range(addr, afi, safi, min, max)) { + X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE); + goto err; + } + break; + case '\0': + if (!X509v3_addr_add_prefix(addr, afi, safi, min, length * 8)) { + X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE); + goto err; + } + break; + default: + X509V3err(X509V3_F_V2I_IPADDRBLOCKS, + X509V3_R_EXTENSION_VALUE_ERROR); + X509V3_conf_err(val); + goto err; + } + + OPENSSL_free(s); + s = NULL; + } + + /* + * Canonize the result, then we're done. + */ + if (!X509v3_addr_canonize(addr)) + goto err; + return addr; + + err: + OPENSSL_free(s); + sk_IPAddressFamily_pop_free(addr, IPAddressFamily_free); + return NULL; +} + +/* + * OpenSSL dispatch + */ +const X509V3_EXT_METHOD v3_addr = { + NID_sbgp_ipAddrBlock, /* nid */ + 0, /* flags */ + ASN1_ITEM_ref(IPAddrBlocks), /* template */ + 0, 0, 0, 0, /* old functions, ignored */ + 0, /* i2s */ + 0, /* s2i */ + 0, /* i2v */ + v2i_IPAddrBlocks, /* v2i */ + i2r_IPAddrBlocks, /* i2r */ + 0, /* r2i */ + NULL /* extension-specific data */ +}; + +/* + * Figure out whether extension sues inheritance. + */ +int X509v3_addr_inherits(IPAddrBlocks *addr) +{ + int i; + if (addr == NULL) + return 0; + for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { + IPAddressFamily *f = sk_IPAddressFamily_value(addr, i); + if (f->ipAddressChoice->type == IPAddressChoice_inherit) + return 1; + } + return 0; +} + +/* + * Figure out whether parent contains child. + */ +static int addr_contains(IPAddressOrRanges *parent, + IPAddressOrRanges *child, int length) +{ + unsigned char p_min[ADDR_RAW_BUF_LEN], p_max[ADDR_RAW_BUF_LEN]; + unsigned char c_min[ADDR_RAW_BUF_LEN], c_max[ADDR_RAW_BUF_LEN]; + int p, c; + + if (child == NULL || parent == child) + return 1; + if (parent == NULL) + return 0; + + p = 0; + for (c = 0; c < sk_IPAddressOrRange_num(child); c++) { + if (!extract_min_max(sk_IPAddressOrRange_value(child, c), + c_min, c_max, length)) + return -1; + for (;; p++) { + if (p >= sk_IPAddressOrRange_num(parent)) + return 0; + if (!extract_min_max(sk_IPAddressOrRange_value(parent, p), + p_min, p_max, length)) + return 0; + if (memcmp(p_max, c_max, length) < 0) + continue; + if (memcmp(p_min, c_min, length) > 0) + return 0; + break; + } + } + + return 1; +} + +/* + * Test whether a is a subset of b. + */ +int X509v3_addr_subset(IPAddrBlocks *a, IPAddrBlocks *b) +{ + int i; + if (a == NULL || a == b) + return 1; + if (b == NULL || X509v3_addr_inherits(a) || X509v3_addr_inherits(b)) + return 0; + (void)sk_IPAddressFamily_set_cmp_func(b, IPAddressFamily_cmp); + for (i = 0; i < sk_IPAddressFamily_num(a); i++) { + IPAddressFamily *fa = sk_IPAddressFamily_value(a, i); + int j = sk_IPAddressFamily_find(b, fa); + IPAddressFamily *fb; + fb = sk_IPAddressFamily_value(b, j); + if (fb == NULL) + return 0; + if (!addr_contains(fb->ipAddressChoice->u.addressesOrRanges, + fa->ipAddressChoice->u.addressesOrRanges, + length_from_afi(X509v3_addr_get_afi(fb)))) + return 0; + } + return 1; +} + +/* + * Validation error handling via callback. + */ +#define validation_err(_err_) \ + do { \ + if (ctx != NULL) { \ + ctx->error = _err_; \ + ctx->error_depth = i; \ + ctx->current_cert = x; \ + ret = ctx->verify_cb(0, ctx); \ + } else { \ + ret = 0; \ + } \ + if (!ret) \ + goto done; \ + } while (0) + +/* + * Core code for RFC 3779 2.3 path validation. + * + * Returns 1 for success, 0 on error. + * + * When returning 0, ctx->error MUST be set to an appropriate value other than + * X509_V_OK. + */ +static int addr_validate_path_internal(X509_STORE_CTX *ctx, + STACK_OF(X509) *chain, + IPAddrBlocks *ext) +{ + IPAddrBlocks *child = NULL; + int i, j, ret = 1; + X509 *x; + + if (!ossl_assert(chain != NULL && sk_X509_num(chain) > 0) + || !ossl_assert(ctx != NULL || ext != NULL) + || !ossl_assert(ctx == NULL || ctx->verify_cb != NULL)) { + if (ctx != NULL) + ctx->error = X509_V_ERR_UNSPECIFIED; + return 0; + } + + /* + * Figure out where to start. If we don't have an extension to + * check, we're done. Otherwise, check canonical form and + * set up for walking up the chain. + */ + if (ext != NULL) { + i = -1; + x = NULL; + } else { + i = 0; + x = sk_X509_value(chain, i); + if ((ext = x->rfc3779_addr) == NULL) + goto done; + } + if (!X509v3_addr_is_canonical(ext)) + validation_err(X509_V_ERR_INVALID_EXTENSION); + (void)sk_IPAddressFamily_set_cmp_func(ext, IPAddressFamily_cmp); + if ((child = sk_IPAddressFamily_dup(ext)) == NULL) { + X509V3err(X509V3_F_ADDR_VALIDATE_PATH_INTERNAL, + ERR_R_MALLOC_FAILURE); + if (ctx != NULL) + ctx->error = X509_V_ERR_OUT_OF_MEM; + ret = 0; + goto done; + } + + /* + * Now walk up the chain. No cert may list resources that its + * parent doesn't list. + */ + for (i++; i < sk_X509_num(chain); i++) { + x = sk_X509_value(chain, i); + if (!X509v3_addr_is_canonical(x->rfc3779_addr)) + validation_err(X509_V_ERR_INVALID_EXTENSION); + if (x->rfc3779_addr == NULL) { + for (j = 0; j < sk_IPAddressFamily_num(child); j++) { + IPAddressFamily *fc = sk_IPAddressFamily_value(child, j); + if (fc->ipAddressChoice->type != IPAddressChoice_inherit) { + validation_err(X509_V_ERR_UNNESTED_RESOURCE); + break; + } + } + continue; + } + (void)sk_IPAddressFamily_set_cmp_func(x->rfc3779_addr, + IPAddressFamily_cmp); + for (j = 0; j < sk_IPAddressFamily_num(child); j++) { + IPAddressFamily *fc = sk_IPAddressFamily_value(child, j); + int k = sk_IPAddressFamily_find(x->rfc3779_addr, fc); + IPAddressFamily *fp = + sk_IPAddressFamily_value(x->rfc3779_addr, k); + if (fp == NULL) { + if (fc->ipAddressChoice->type == + IPAddressChoice_addressesOrRanges) { + validation_err(X509_V_ERR_UNNESTED_RESOURCE); + break; + } + continue; + } + if (fp->ipAddressChoice->type == + IPAddressChoice_addressesOrRanges) { + if (fc->ipAddressChoice->type == IPAddressChoice_inherit + || addr_contains(fp->ipAddressChoice->u.addressesOrRanges, + fc->ipAddressChoice->u.addressesOrRanges, + length_from_afi(X509v3_addr_get_afi(fc)))) + sk_IPAddressFamily_set(child, j, fp); + else + validation_err(X509_V_ERR_UNNESTED_RESOURCE); + } + } + } + + /* + * Trust anchor can't inherit. + */ + if (x->rfc3779_addr != NULL) { + for (j = 0; j < sk_IPAddressFamily_num(x->rfc3779_addr); j++) { + IPAddressFamily *fp = + sk_IPAddressFamily_value(x->rfc3779_addr, j); + if (fp->ipAddressChoice->type == IPAddressChoice_inherit + && sk_IPAddressFamily_find(child, fp) >= 0) + validation_err(X509_V_ERR_UNNESTED_RESOURCE); + } + } + + done: + sk_IPAddressFamily_free(child); + return ret; +} + +#undef validation_err + +/* + * RFC 3779 2.3 path validation -- called from X509_verify_cert(). + */ +int X509v3_addr_validate_path(X509_STORE_CTX *ctx) +{ + if (ctx->chain == NULL + || sk_X509_num(ctx->chain) == 0 + || ctx->verify_cb == NULL) { + ctx->error = X509_V_ERR_UNSPECIFIED; + return 0; + } + return addr_validate_path_internal(ctx, ctx->chain, NULL); +} + +/* + * RFC 3779 2.3 path validation of an extension. + * Test whether chain covers extension. + */ +int X509v3_addr_validate_resource_set(STACK_OF(X509) *chain, + IPAddrBlocks *ext, int allow_inheritance) +{ + if (ext == NULL) + return 1; + if (chain == NULL || sk_X509_num(chain) == 0) + return 0; + if (!allow_inheritance && X509v3_addr_inherits(ext)) + return 0; + return addr_validate_path_internal(NULL, chain, ext); +} + +#endif /* OPENSSL_NO_RFC3779 */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_admis.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_admis.c new file mode 100644 index 000000000..c8e75191b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_admis.c @@ -0,0 +1,356 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include + +#include + +#include + +#include "v3_admis.h" +#include "ext_dat.h" + + +ASN1_SEQUENCE(NAMING_AUTHORITY) = { + ASN1_OPT(NAMING_AUTHORITY, namingAuthorityId, ASN1_OBJECT), + ASN1_OPT(NAMING_AUTHORITY, namingAuthorityUrl, ASN1_IA5STRING), + ASN1_OPT(NAMING_AUTHORITY, namingAuthorityText, DIRECTORYSTRING), +} ASN1_SEQUENCE_END(NAMING_AUTHORITY) + +ASN1_SEQUENCE(PROFESSION_INFO) = { + ASN1_EXP_OPT(PROFESSION_INFO, namingAuthority, NAMING_AUTHORITY, 0), + ASN1_SEQUENCE_OF(PROFESSION_INFO, professionItems, DIRECTORYSTRING), + ASN1_SEQUENCE_OF_OPT(PROFESSION_INFO, professionOIDs, ASN1_OBJECT), + ASN1_OPT(PROFESSION_INFO, registrationNumber, ASN1_PRINTABLESTRING), + ASN1_OPT(PROFESSION_INFO, addProfessionInfo, ASN1_OCTET_STRING), +} ASN1_SEQUENCE_END(PROFESSION_INFO) + +ASN1_SEQUENCE(ADMISSIONS) = { + ASN1_EXP_OPT(ADMISSIONS, admissionAuthority, GENERAL_NAME, 0), + ASN1_EXP_OPT(ADMISSIONS, namingAuthority, NAMING_AUTHORITY, 1), + ASN1_SEQUENCE_OF(ADMISSIONS, professionInfos, PROFESSION_INFO), +} ASN1_SEQUENCE_END(ADMISSIONS) + +ASN1_SEQUENCE(ADMISSION_SYNTAX) = { + ASN1_OPT(ADMISSION_SYNTAX, admissionAuthority, GENERAL_NAME), + ASN1_SEQUENCE_OF(ADMISSION_SYNTAX, contentsOfAdmissions, ADMISSIONS), +} ASN1_SEQUENCE_END(ADMISSION_SYNTAX) + +IMPLEMENT_ASN1_FUNCTIONS(NAMING_AUTHORITY) +IMPLEMENT_ASN1_FUNCTIONS(PROFESSION_INFO) +IMPLEMENT_ASN1_FUNCTIONS(ADMISSIONS) +IMPLEMENT_ASN1_FUNCTIONS(ADMISSION_SYNTAX) + +static int i2r_ADMISSION_SYNTAX(const struct v3_ext_method *method, void *in, + BIO *bp, int ind); + +const X509V3_EXT_METHOD v3_ext_admission = { + NID_x509ExtAdmission, /* .ext_nid = */ + 0, /* .ext_flags = */ + ASN1_ITEM_ref(ADMISSION_SYNTAX), /* .it = */ + NULL, NULL, NULL, NULL, + NULL, /* .i2s = */ + NULL, /* .s2i = */ + NULL, /* .i2v = */ + NULL, /* .v2i = */ + &i2r_ADMISSION_SYNTAX, /* .i2r = */ + NULL, /* .r2i = */ + NULL /* extension-specific data */ +}; + + +static int i2r_NAMING_AUTHORITY(const struct v3_ext_method *method, void *in, + BIO *bp, int ind) +{ + NAMING_AUTHORITY * namingAuthority = (NAMING_AUTHORITY*) in; + + if (namingAuthority == NULL) + return 0; + + if (namingAuthority->namingAuthorityId == NULL + && namingAuthority->namingAuthorityText == NULL + && namingAuthority->namingAuthorityUrl == NULL) + return 0; + + if (BIO_printf(bp, "%*snamingAuthority: ", ind, "") <= 0) + goto err; + + if (namingAuthority->namingAuthorityId != NULL) { + char objbuf[128]; + const char *ln = OBJ_nid2ln(OBJ_obj2nid(namingAuthority->namingAuthorityId)); + + if (BIO_printf(bp, "%*s admissionAuthorityId: ", ind, "") <= 0) + goto err; + + OBJ_obj2txt(objbuf, sizeof(objbuf), namingAuthority->namingAuthorityId, 1); + + if (BIO_printf(bp, "%s%s%s%s\n", ln ? ln : "", + ln ? " (" : "", objbuf, ln ? ")" : "") <= 0) + goto err; + } + if (namingAuthority->namingAuthorityText != NULL) { + if (BIO_printf(bp, "%*s namingAuthorityText: ", ind, "") <= 0 + || ASN1_STRING_print(bp, namingAuthority->namingAuthorityText) <= 0 + || BIO_printf(bp, "\n") <= 0) + goto err; + } + if (namingAuthority->namingAuthorityUrl != NULL ) { + if (BIO_printf(bp, "%*s namingAuthorityUrl: ", ind, "") <= 0 + || ASN1_STRING_print(bp, namingAuthority->namingAuthorityUrl) <= 0 + || BIO_printf(bp, "\n") <= 0) + goto err; + } + return 1; + +err: + return 0; +} + +static int i2r_ADMISSION_SYNTAX(const struct v3_ext_method *method, void *in, + BIO *bp, int ind) +{ + ADMISSION_SYNTAX * admission = (ADMISSION_SYNTAX *)in; + int i, j, k; + + if (admission->admissionAuthority != NULL) { + if (BIO_printf(bp, "%*sadmissionAuthority:\n", ind, "") <= 0 + || BIO_printf(bp, "%*s ", ind, "") <= 0 + || GENERAL_NAME_print(bp, admission->admissionAuthority) <= 0 + || BIO_printf(bp, "\n") <= 0) + goto err; + } + + for (i = 0; i < sk_ADMISSIONS_num(admission->contentsOfAdmissions); i++) { + ADMISSIONS* entry = sk_ADMISSIONS_value(admission->contentsOfAdmissions, i); + + if (BIO_printf(bp, "%*sEntry %0d:\n", ind, "", 1 + i) <= 0) goto err; + + if (entry->admissionAuthority != NULL) { + if (BIO_printf(bp, "%*s admissionAuthority:\n", ind, "") <= 0 + || BIO_printf(bp, "%*s ", ind, "") <= 0 + || GENERAL_NAME_print(bp, entry->admissionAuthority) <= 0 + || BIO_printf(bp, "\n") <= 0) + goto err; + } + + if (entry->namingAuthority != NULL) { + if (i2r_NAMING_AUTHORITY(method, entry->namingAuthority, bp, ind) <= 0) + goto err; + } + + for (j = 0; j < sk_PROFESSION_INFO_num(entry->professionInfos); j++) { + PROFESSION_INFO* pinfo = sk_PROFESSION_INFO_value(entry->professionInfos, j); + + if (BIO_printf(bp, "%*s Profession Info Entry %0d:\n", ind, "", 1 + j) <= 0) + goto err; + + if (pinfo->registrationNumber != NULL) { + if (BIO_printf(bp, "%*s registrationNumber: ", ind, "") <= 0 + || ASN1_STRING_print(bp, pinfo->registrationNumber) <= 0 + || BIO_printf(bp, "\n") <= 0) + goto err; + } + + if (pinfo->namingAuthority != NULL) { + if (i2r_NAMING_AUTHORITY(method, pinfo->namingAuthority, bp, ind + 2) <= 0) + goto err; + } + + if (pinfo->professionItems != NULL) { + + if (BIO_printf(bp, "%*s Info Entries:\n", ind, "") <= 0) + goto err; + for (k = 0; k < sk_ASN1_STRING_num(pinfo->professionItems); k++) { + ASN1_STRING* val = sk_ASN1_STRING_value(pinfo->professionItems, k); + + if (BIO_printf(bp, "%*s ", ind, "") <= 0 + || ASN1_STRING_print(bp, val) <= 0 + || BIO_printf(bp, "\n") <= 0) + goto err; + } + } + + if (pinfo->professionOIDs != NULL) { + if (BIO_printf(bp, "%*s Profession OIDs:\n", ind, "") <= 0) + goto err; + for (k = 0; k < sk_ASN1_OBJECT_num(pinfo->professionOIDs); k++) { + ASN1_OBJECT* obj = sk_ASN1_OBJECT_value(pinfo->professionOIDs, k); + const char *ln = OBJ_nid2ln(OBJ_obj2nid(obj)); + char objbuf[128]; + + OBJ_obj2txt(objbuf, sizeof(objbuf), obj, 1); + if (BIO_printf(bp, "%*s %s%s%s%s\n", ind, "", + ln ? ln : "", ln ? " (" : "", + objbuf, ln ? ")" : "") <= 0) + goto err; + } + } + } + } + return 1; + +err: + return -1; +} + +const ASN1_OBJECT *NAMING_AUTHORITY_get0_authorityId(const NAMING_AUTHORITY *n) +{ + return n->namingAuthorityId; +} + +void NAMING_AUTHORITY_set0_authorityId(NAMING_AUTHORITY *n, ASN1_OBJECT* id) +{ + ASN1_OBJECT_free(n->namingAuthorityId); + n->namingAuthorityId = id; +} + +const ASN1_IA5STRING *NAMING_AUTHORITY_get0_authorityURL( + const NAMING_AUTHORITY *n) +{ + return n->namingAuthorityUrl; +} + +void NAMING_AUTHORITY_set0_authorityURL(NAMING_AUTHORITY *n, ASN1_IA5STRING* u) +{ + ASN1_IA5STRING_free(n->namingAuthorityUrl); + n->namingAuthorityUrl = u; +} + +const ASN1_STRING *NAMING_AUTHORITY_get0_authorityText( + const NAMING_AUTHORITY *n) +{ + return n->namingAuthorityText; +} + +void NAMING_AUTHORITY_set0_authorityText(NAMING_AUTHORITY *n, ASN1_STRING* t) +{ + ASN1_IA5STRING_free(n->namingAuthorityText); + n->namingAuthorityText = t; +} + +const GENERAL_NAME *ADMISSION_SYNTAX_get0_admissionAuthority(const ADMISSION_SYNTAX *as) +{ + return as->admissionAuthority; +} + +void ADMISSION_SYNTAX_set0_admissionAuthority(ADMISSION_SYNTAX *as, + GENERAL_NAME *aa) +{ + GENERAL_NAME_free(as->admissionAuthority); + as->admissionAuthority = aa; +} + +const STACK_OF(ADMISSIONS) *ADMISSION_SYNTAX_get0_contentsOfAdmissions(const ADMISSION_SYNTAX *as) +{ + return as->contentsOfAdmissions; +} + +void ADMISSION_SYNTAX_set0_contentsOfAdmissions(ADMISSION_SYNTAX *as, + STACK_OF(ADMISSIONS) *a) +{ + sk_ADMISSIONS_pop_free(as->contentsOfAdmissions, ADMISSIONS_free); + as->contentsOfAdmissions = a; +} + +const GENERAL_NAME *ADMISSIONS_get0_admissionAuthority(const ADMISSIONS *a) +{ + return a->admissionAuthority; +} + +void ADMISSIONS_set0_admissionAuthority(ADMISSIONS *a, GENERAL_NAME *aa) +{ + GENERAL_NAME_free(a->admissionAuthority); + a->admissionAuthority = aa; +} + +const NAMING_AUTHORITY *ADMISSIONS_get0_namingAuthority(const ADMISSIONS *a) +{ + return a->namingAuthority; +} + +void ADMISSIONS_set0_namingAuthority(ADMISSIONS *a, NAMING_AUTHORITY *na) +{ + NAMING_AUTHORITY_free(a->namingAuthority); + a->namingAuthority = na; +} + +const PROFESSION_INFOS *ADMISSIONS_get0_professionInfos(const ADMISSIONS *a) +{ + return a->professionInfos; +} + +void ADMISSIONS_set0_professionInfos(ADMISSIONS *a, PROFESSION_INFOS *pi) +{ + sk_PROFESSION_INFO_pop_free(a->professionInfos, PROFESSION_INFO_free); + a->professionInfos = pi; +} + +const ASN1_OCTET_STRING *PROFESSION_INFO_get0_addProfessionInfo(const PROFESSION_INFO *pi) +{ + return pi->addProfessionInfo; +} + +void PROFESSION_INFO_set0_addProfessionInfo(PROFESSION_INFO *pi, + ASN1_OCTET_STRING *aos) +{ + ASN1_OCTET_STRING_free(pi->addProfessionInfo); + pi->addProfessionInfo = aos; +} + +const NAMING_AUTHORITY *PROFESSION_INFO_get0_namingAuthority(const PROFESSION_INFO *pi) +{ + return pi->namingAuthority; +} + +void PROFESSION_INFO_set0_namingAuthority(PROFESSION_INFO *pi, + NAMING_AUTHORITY *na) +{ + NAMING_AUTHORITY_free(pi->namingAuthority); + pi->namingAuthority = na; +} + +const STACK_OF(ASN1_STRING) *PROFESSION_INFO_get0_professionItems(const PROFESSION_INFO *pi) +{ + return pi->professionItems; +} + +void PROFESSION_INFO_set0_professionItems(PROFESSION_INFO *pi, + STACK_OF(ASN1_STRING) *as) +{ + sk_ASN1_STRING_pop_free(pi->professionItems, ASN1_STRING_free); + pi->professionItems = as; +} + +const STACK_OF(ASN1_OBJECT) *PROFESSION_INFO_get0_professionOIDs(const PROFESSION_INFO *pi) +{ + return pi->professionOIDs; +} + +void PROFESSION_INFO_set0_professionOIDs(PROFESSION_INFO *pi, + STACK_OF(ASN1_OBJECT) *po) +{ + sk_ASN1_OBJECT_pop_free(pi->professionOIDs, ASN1_OBJECT_free); + pi->professionOIDs = po; +} + +const ASN1_PRINTABLESTRING *PROFESSION_INFO_get0_registrationNumber(const PROFESSION_INFO *pi) +{ + return pi->registrationNumber; +} + +void PROFESSION_INFO_set0_registrationNumber(PROFESSION_INFO *pi, + ASN1_PRINTABLESTRING *rn) +{ + ASN1_PRINTABLESTRING_free(pi->registrationNumber); + pi->registrationNumber = rn; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_admis.h b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_admis.h new file mode 100644 index 000000000..fa23fc761 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_admis.h @@ -0,0 +1,38 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_V3_ADMISSION_H +# define HEADER_V3_ADMISSION_H + +struct NamingAuthority_st { + ASN1_OBJECT* namingAuthorityId; + ASN1_IA5STRING* namingAuthorityUrl; + ASN1_STRING* namingAuthorityText; /* i.e. DIRECTORYSTRING */ +}; + +struct ProfessionInfo_st { + NAMING_AUTHORITY* namingAuthority; + STACK_OF(ASN1_STRING)* professionItems; /* i.e. DIRECTORYSTRING */ + STACK_OF(ASN1_OBJECT)* professionOIDs; + ASN1_PRINTABLESTRING* registrationNumber; + ASN1_OCTET_STRING* addProfessionInfo; +}; + +struct Admissions_st { + GENERAL_NAME* admissionAuthority; + NAMING_AUTHORITY* namingAuthority; + STACK_OF(PROFESSION_INFO)* professionInfos; +}; + +struct AdmissionSyntax_st { + GENERAL_NAME* admissionAuthority; + STACK_OF(ADMISSIONS)* contentsOfAdmissions; +}; + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_akey.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_akey.c new file mode 100644 index 000000000..d9f770433 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_akey.c @@ -0,0 +1,160 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "ext_dat.h" + +static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, + AUTHORITY_KEYID *akeyid, + STACK_OF(CONF_VALUE) + *extlist); +static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *values); + +const X509V3_EXT_METHOD v3_akey_id = { + NID_authority_key_identifier, + X509V3_EXT_MULTILINE, ASN1_ITEM_ref(AUTHORITY_KEYID), + 0, 0, 0, 0, + 0, 0, + (X509V3_EXT_I2V) i2v_AUTHORITY_KEYID, + (X509V3_EXT_V2I)v2i_AUTHORITY_KEYID, + 0, 0, + NULL +}; + +static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, + AUTHORITY_KEYID *akeyid, + STACK_OF(CONF_VALUE) + *extlist) +{ + char *tmp; + if (akeyid->keyid) { + tmp = OPENSSL_buf2hexstr(akeyid->keyid->data, akeyid->keyid->length); + X509V3_add_value("keyid", tmp, &extlist); + OPENSSL_free(tmp); + } + if (akeyid->issuer) + extlist = i2v_GENERAL_NAMES(NULL, akeyid->issuer, extlist); + if (akeyid->serial) { + tmp = OPENSSL_buf2hexstr(akeyid->serial->data, akeyid->serial->length); + X509V3_add_value("serial", tmp, &extlist); + OPENSSL_free(tmp); + } + return extlist; +} + +/*- + * Currently two options: + * keyid: use the issuers subject keyid, the value 'always' means its is + * an error if the issuer certificate doesn't have a key id. + * issuer: use the issuers cert issuer and serial number. The default is + * to only use this if keyid is not present. With the option 'always' + * this is always included. + */ + +static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *values) +{ + char keyid = 0, issuer = 0; + int i; + CONF_VALUE *cnf; + ASN1_OCTET_STRING *ikeyid = NULL; + X509_NAME *isname = NULL; + GENERAL_NAMES *gens = NULL; + GENERAL_NAME *gen = NULL; + ASN1_INTEGER *serial = NULL; + X509_EXTENSION *ext; + X509 *cert; + AUTHORITY_KEYID *akeyid; + + for (i = 0; i < sk_CONF_VALUE_num(values); i++) { + cnf = sk_CONF_VALUE_value(values, i); + if (strcmp(cnf->name, "keyid") == 0) { + keyid = 1; + if (cnf->value && strcmp(cnf->value, "always") == 0) + keyid = 2; + } else if (strcmp(cnf->name, "issuer") == 0) { + issuer = 1; + if (cnf->value && strcmp(cnf->value, "always") == 0) + issuer = 2; + } else { + X509V3err(X509V3_F_V2I_AUTHORITY_KEYID, X509V3_R_UNKNOWN_OPTION); + ERR_add_error_data(2, "name=", cnf->name); + return NULL; + } + } + + if (!ctx || !ctx->issuer_cert) { + if (ctx && (ctx->flags == CTX_TEST)) + return AUTHORITY_KEYID_new(); + X509V3err(X509V3_F_V2I_AUTHORITY_KEYID, + X509V3_R_NO_ISSUER_CERTIFICATE); + return NULL; + } + + cert = ctx->issuer_cert; + + if (keyid) { + i = X509_get_ext_by_NID(cert, NID_subject_key_identifier, -1); + if ((i >= 0) && (ext = X509_get_ext(cert, i))) + ikeyid = X509V3_EXT_d2i(ext); + if (keyid == 2 && !ikeyid) { + X509V3err(X509V3_F_V2I_AUTHORITY_KEYID, + X509V3_R_UNABLE_TO_GET_ISSUER_KEYID); + return NULL; + } + } + + if ((issuer && !ikeyid) || (issuer == 2)) { + isname = X509_NAME_dup(X509_get_issuer_name(cert)); + serial = ASN1_INTEGER_dup(X509_get_serialNumber(cert)); + if (!isname || !serial) { + X509V3err(X509V3_F_V2I_AUTHORITY_KEYID, + X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS); + goto err; + } + } + + if ((akeyid = AUTHORITY_KEYID_new()) == NULL) + goto err; + + if (isname) { + if ((gens = sk_GENERAL_NAME_new_null()) == NULL + || (gen = GENERAL_NAME_new()) == NULL + || !sk_GENERAL_NAME_push(gens, gen)) { + X509V3err(X509V3_F_V2I_AUTHORITY_KEYID, ERR_R_MALLOC_FAILURE); + goto err; + } + gen->type = GEN_DIRNAME; + gen->d.dirn = isname; + } + + akeyid->issuer = gens; + gen = NULL; + gens = NULL; + akeyid->serial = serial; + akeyid->keyid = ikeyid; + + return akeyid; + + err: + sk_GENERAL_NAME_free(gens); + GENERAL_NAME_free(gen); + X509_NAME_free(isname); + ASN1_INTEGER_free(serial); + ASN1_OCTET_STRING_free(ikeyid); + return NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_akeya.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_akeya.c new file mode 100644 index 000000000..d6dd6bcb9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_akeya.c @@ -0,0 +1,23 @@ +/* + * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include + +ASN1_SEQUENCE(AUTHORITY_KEYID) = { + ASN1_IMP_OPT(AUTHORITY_KEYID, keyid, ASN1_OCTET_STRING, 0), + ASN1_IMP_SEQUENCE_OF_OPT(AUTHORITY_KEYID, issuer, GENERAL_NAME, 1), + ASN1_IMP_OPT(AUTHORITY_KEYID, serial, ASN1_INTEGER, 2) +} ASN1_SEQUENCE_END(AUTHORITY_KEYID) + +IMPLEMENT_ASN1_FUNCTIONS(AUTHORITY_KEYID) diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_alt.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_alt.c new file mode 100644 index 000000000..832e6d128 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_alt.c @@ -0,0 +1,592 @@ +/* + * Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include "ext_dat.h" + +static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval); +static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval); +static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p); +static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens); +static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx); +static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx); + +const X509V3_EXT_METHOD v3_alt[3] = { + {NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES), + 0, 0, 0, 0, + 0, 0, + (X509V3_EXT_I2V) i2v_GENERAL_NAMES, + (X509V3_EXT_V2I)v2i_subject_alt, + NULL, NULL, NULL}, + + {NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES), + 0, 0, 0, 0, + 0, 0, + (X509V3_EXT_I2V) i2v_GENERAL_NAMES, + (X509V3_EXT_V2I)v2i_issuer_alt, + NULL, NULL, NULL}, + + {NID_certificate_issuer, 0, ASN1_ITEM_ref(GENERAL_NAMES), + 0, 0, 0, 0, + 0, 0, + (X509V3_EXT_I2V) i2v_GENERAL_NAMES, + NULL, NULL, NULL, NULL}, +}; + +STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method, + GENERAL_NAMES *gens, + STACK_OF(CONF_VALUE) *ret) +{ + int i; + GENERAL_NAME *gen; + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { + gen = sk_GENERAL_NAME_value(gens, i); + ret = i2v_GENERAL_NAME(method, gen, ret); + } + if (!ret) + return sk_CONF_VALUE_new_null(); + return ret; +} + +STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, + GENERAL_NAME *gen, + STACK_OF(CONF_VALUE) *ret) +{ + unsigned char *p; + char oline[256], htmp[5]; + int i; + + switch (gen->type) { + case GEN_OTHERNAME: + if (!X509V3_add_value("othername", "", &ret)) + return NULL; + break; + + case GEN_X400: + if (!X509V3_add_value("X400Name", "", &ret)) + return NULL; + break; + + case GEN_EDIPARTY: + if (!X509V3_add_value("EdiPartyName", "", &ret)) + return NULL; + break; + + case GEN_EMAIL: + if (!X509V3_add_value_uchar("email", gen->d.ia5->data, &ret)) + return NULL; + break; + + case GEN_DNS: + if (!X509V3_add_value_uchar("DNS", gen->d.ia5->data, &ret)) + return NULL; + break; + + case GEN_URI: + if (!X509V3_add_value_uchar("URI", gen->d.ia5->data, &ret)) + return NULL; + break; + + case GEN_DIRNAME: + if (X509_NAME_oneline(gen->d.dirn, oline, sizeof(oline)) == NULL + || !X509V3_add_value("DirName", oline, &ret)) + return NULL; + break; + + case GEN_IPADD: + p = gen->d.ip->data; + if (gen->d.ip->length == 4) + BIO_snprintf(oline, sizeof(oline), "%d.%d.%d.%d", + p[0], p[1], p[2], p[3]); + else if (gen->d.ip->length == 16) { + oline[0] = 0; + for (i = 0; i < 8; i++) { + BIO_snprintf(htmp, sizeof(htmp), "%X", p[0] << 8 | p[1]); + p += 2; + strcat(oline, htmp); + if (i != 7) + strcat(oline, ":"); + } + } else { + if (!X509V3_add_value("IP Address", "", &ret)) + return NULL; + break; + } + if (!X509V3_add_value("IP Address", oline, &ret)) + return NULL; + break; + + case GEN_RID: + i2t_ASN1_OBJECT(oline, 256, gen->d.rid); + if (!X509V3_add_value("Registered ID", oline, &ret)) + return NULL; + break; + } + return ret; +} + +int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen) +{ + unsigned char *p; + int i; + switch (gen->type) { + case GEN_OTHERNAME: + BIO_printf(out, "othername:"); + break; + + case GEN_X400: + BIO_printf(out, "X400Name:"); + break; + + case GEN_EDIPARTY: + /* Maybe fix this: it is supported now */ + BIO_printf(out, "EdiPartyName:"); + break; + + case GEN_EMAIL: + BIO_printf(out, "email:%s", gen->d.ia5->data); + break; + + case GEN_DNS: + BIO_printf(out, "DNS:%s", gen->d.ia5->data); + break; + + case GEN_URI: + BIO_printf(out, "URI:%s", gen->d.ia5->data); + break; + + case GEN_DIRNAME: + BIO_printf(out, "DirName:"); + X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE); + break; + + case GEN_IPADD: + p = gen->d.ip->data; + if (gen->d.ip->length == 4) + BIO_printf(out, "IP Address:%d.%d.%d.%d", p[0], p[1], p[2], p[3]); + else if (gen->d.ip->length == 16) { + BIO_printf(out, "IP Address"); + for (i = 0; i < 8; i++) { + BIO_printf(out, ":%X", p[0] << 8 | p[1]); + p += 2; + } + BIO_puts(out, "\n"); + } else { + BIO_printf(out, "IP Address:"); + break; + } + break; + + case GEN_RID: + BIO_printf(out, "Registered ID:"); + i2a_ASN1_OBJECT(out, gen->d.rid); + break; + } + return 1; +} + +static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval) +{ + const int num = sk_CONF_VALUE_num(nval); + GENERAL_NAMES *gens = sk_GENERAL_NAME_new_reserve(NULL, num); + int i; + + if (gens == NULL) { + X509V3err(X509V3_F_V2I_ISSUER_ALT, ERR_R_MALLOC_FAILURE); + sk_GENERAL_NAME_free(gens); + return NULL; + } + for (i = 0; i < num; i++) { + CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i); + + if (!name_cmp(cnf->name, "issuer") + && cnf->value && strcmp(cnf->value, "copy") == 0) { + if (!copy_issuer(ctx, gens)) + goto err; + } else { + GENERAL_NAME *gen = v2i_GENERAL_NAME(method, ctx, cnf); + + if (gen == NULL) + goto err; + sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */ + } + } + return gens; + err: + sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); + return NULL; +} + +/* Append subject altname of issuer to issuer alt name of subject */ + +static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens) +{ + GENERAL_NAMES *ialt; + GENERAL_NAME *gen; + X509_EXTENSION *ext; + int i, num; + + if (ctx && (ctx->flags == CTX_TEST)) + return 1; + if (!ctx || !ctx->issuer_cert) { + X509V3err(X509V3_F_COPY_ISSUER, X509V3_R_NO_ISSUER_DETAILS); + goto err; + } + i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1); + if (i < 0) + return 1; + if ((ext = X509_get_ext(ctx->issuer_cert, i)) == NULL + || (ialt = X509V3_EXT_d2i(ext)) == NULL) { + X509V3err(X509V3_F_COPY_ISSUER, X509V3_R_ISSUER_DECODE_ERROR); + goto err; + } + + num = sk_GENERAL_NAME_num(ialt); + if (!sk_GENERAL_NAME_reserve(gens, num)) { + X509V3err(X509V3_F_COPY_ISSUER, ERR_R_MALLOC_FAILURE); + goto err; + } + + for (i = 0; i < num; i++) { + gen = sk_GENERAL_NAME_value(ialt, i); + sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */ + } + sk_GENERAL_NAME_free(ialt); + + return 1; + + err: + return 0; + +} + +static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval) +{ + GENERAL_NAMES *gens; + CONF_VALUE *cnf; + const int num = sk_CONF_VALUE_num(nval); + int i; + + gens = sk_GENERAL_NAME_new_reserve(NULL, num); + if (gens == NULL) { + X509V3err(X509V3_F_V2I_SUBJECT_ALT, ERR_R_MALLOC_FAILURE); + sk_GENERAL_NAME_free(gens); + return NULL; + } + + for (i = 0; i < num; i++) { + cnf = sk_CONF_VALUE_value(nval, i); + if (!name_cmp(cnf->name, "email") + && cnf->value && strcmp(cnf->value, "copy") == 0) { + if (!copy_email(ctx, gens, 0)) + goto err; + } else if (!name_cmp(cnf->name, "email") + && cnf->value && strcmp(cnf->value, "move") == 0) { + if (!copy_email(ctx, gens, 1)) + goto err; + } else { + GENERAL_NAME *gen; + if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL) + goto err; + sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */ + } + } + return gens; + err: + sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); + return NULL; +} + +/* + * Copy any email addresses in a certificate or request to GENERAL_NAMES + */ + +static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p) +{ + X509_NAME *nm; + ASN1_IA5STRING *email = NULL; + X509_NAME_ENTRY *ne; + GENERAL_NAME *gen = NULL; + int i = -1; + + if (ctx != NULL && ctx->flags == CTX_TEST) + return 1; + if (ctx == NULL + || (ctx->subject_cert == NULL && ctx->subject_req == NULL)) { + X509V3err(X509V3_F_COPY_EMAIL, X509V3_R_NO_SUBJECT_DETAILS); + goto err; + } + /* Find the subject name */ + if (ctx->subject_cert) + nm = X509_get_subject_name(ctx->subject_cert); + else + nm = X509_REQ_get_subject_name(ctx->subject_req); + + /* Now add any email address(es) to STACK */ + while ((i = X509_NAME_get_index_by_NID(nm, + NID_pkcs9_emailAddress, i)) >= 0) { + ne = X509_NAME_get_entry(nm, i); + email = ASN1_STRING_dup(X509_NAME_ENTRY_get_data(ne)); + if (move_p) { + X509_NAME_delete_entry(nm, i); + X509_NAME_ENTRY_free(ne); + i--; + } + if (email == NULL || (gen = GENERAL_NAME_new()) == NULL) { + X509V3err(X509V3_F_COPY_EMAIL, ERR_R_MALLOC_FAILURE); + goto err; + } + gen->d.ia5 = email; + email = NULL; + gen->type = GEN_EMAIL; + if (!sk_GENERAL_NAME_push(gens, gen)) { + X509V3err(X509V3_F_COPY_EMAIL, ERR_R_MALLOC_FAILURE); + goto err; + } + gen = NULL; + } + + return 1; + + err: + GENERAL_NAME_free(gen); + ASN1_IA5STRING_free(email); + return 0; + +} + +GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) +{ + GENERAL_NAME *gen; + GENERAL_NAMES *gens; + CONF_VALUE *cnf; + const int num = sk_CONF_VALUE_num(nval); + int i; + + gens = sk_GENERAL_NAME_new_reserve(NULL, num); + if (gens == NULL) { + X509V3err(X509V3_F_V2I_GENERAL_NAMES, ERR_R_MALLOC_FAILURE); + sk_GENERAL_NAME_free(gens); + return NULL; + } + + for (i = 0; i < num; i++) { + cnf = sk_CONF_VALUE_value(nval, i); + if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL) + goto err; + sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */ + } + return gens; + err: + sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); + return NULL; +} + +GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, CONF_VALUE *cnf) +{ + return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0); +} + +GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out, + const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, int gen_type, const char *value, + int is_nc) +{ + char is_string = 0; + GENERAL_NAME *gen = NULL; + + if (!value) { + X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_MISSING_VALUE); + return NULL; + } + + if (out) + gen = out; + else { + gen = GENERAL_NAME_new(); + if (gen == NULL) { + X509V3err(X509V3_F_A2I_GENERAL_NAME, ERR_R_MALLOC_FAILURE); + return NULL; + } + } + + switch (gen_type) { + case GEN_URI: + case GEN_EMAIL: + case GEN_DNS: + is_string = 1; + break; + + case GEN_RID: + { + ASN1_OBJECT *obj; + if ((obj = OBJ_txt2obj(value, 0)) == NULL) { + X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_BAD_OBJECT); + ERR_add_error_data(2, "value=", value); + goto err; + } + gen->d.rid = obj; + } + break; + + case GEN_IPADD: + if (is_nc) + gen->d.ip = a2i_IPADDRESS_NC(value); + else + gen->d.ip = a2i_IPADDRESS(value); + if (gen->d.ip == NULL) { + X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_BAD_IP_ADDRESS); + ERR_add_error_data(2, "value=", value); + goto err; + } + break; + + case GEN_DIRNAME: + if (!do_dirname(gen, value, ctx)) { + X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_DIRNAME_ERROR); + goto err; + } + break; + + case GEN_OTHERNAME: + if (!do_othername(gen, value, ctx)) { + X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_OTHERNAME_ERROR); + goto err; + } + break; + default: + X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_UNSUPPORTED_TYPE); + goto err; + } + + if (is_string) { + if ((gen->d.ia5 = ASN1_IA5STRING_new()) == NULL || + !ASN1_STRING_set(gen->d.ia5, (unsigned char *)value, + strlen(value))) { + X509V3err(X509V3_F_A2I_GENERAL_NAME, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + gen->type = gen_type; + + return gen; + + err: + if (!out) + GENERAL_NAME_free(gen); + return NULL; +} + +GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out, + const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc) +{ + int type; + + char *name, *value; + + name = cnf->name; + value = cnf->value; + + if (!value) { + X509V3err(X509V3_F_V2I_GENERAL_NAME_EX, X509V3_R_MISSING_VALUE); + return NULL; + } + + if (!name_cmp(name, "email")) + type = GEN_EMAIL; + else if (!name_cmp(name, "URI")) + type = GEN_URI; + else if (!name_cmp(name, "DNS")) + type = GEN_DNS; + else if (!name_cmp(name, "RID")) + type = GEN_RID; + else if (!name_cmp(name, "IP")) + type = GEN_IPADD; + else if (!name_cmp(name, "dirName")) + type = GEN_DIRNAME; + else if (!name_cmp(name, "otherName")) + type = GEN_OTHERNAME; + else { + X509V3err(X509V3_F_V2I_GENERAL_NAME_EX, X509V3_R_UNSUPPORTED_OPTION); + ERR_add_error_data(2, "name=", name); + return NULL; + } + + return a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc); + +} + +static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx) +{ + char *objtmp = NULL, *p; + int objlen; + + if ((p = strchr(value, ';')) == NULL) + return 0; + if ((gen->d.otherName = OTHERNAME_new()) == NULL) + return 0; + /* + * Free this up because we will overwrite it. no need to free type_id + * because it is static + */ + ASN1_TYPE_free(gen->d.otherName->value); + if ((gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx)) == NULL) + return 0; + objlen = p - value; + objtmp = OPENSSL_strndup(value, objlen); + if (objtmp == NULL) + return 0; + gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0); + OPENSSL_free(objtmp); + if (!gen->d.otherName->type_id) + return 0; + return 1; +} + +static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx) +{ + int ret = 0; + STACK_OF(CONF_VALUE) *sk = NULL; + X509_NAME *nm; + + if ((nm = X509_NAME_new()) == NULL) + goto err; + sk = X509V3_get_section(ctx, value); + if (!sk) { + X509V3err(X509V3_F_DO_DIRNAME, X509V3_R_SECTION_NOT_FOUND); + ERR_add_error_data(2, "section=", value); + goto err; + } + /* FIXME: should allow other character types... */ + ret = X509V3_NAME_from_section(nm, sk, MBSTRING_ASC); + if (!ret) + goto err; + gen->d.dirn = nm; + +err: + if (ret == 0) + X509_NAME_free(nm); + X509V3_section_free(ctx, sk); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_asid.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_asid.c new file mode 100644 index 000000000..089f2ae29 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_asid.c @@ -0,0 +1,880 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Implementation of RFC 3779 section 3.2. + */ + +#include +#include +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include "internal/x509_int.h" +#include +#include "ext_dat.h" + +#ifndef OPENSSL_NO_RFC3779 + +/* + * OpenSSL ASN.1 template translation of RFC 3779 3.2.3. + */ + +ASN1_SEQUENCE(ASRange) = { + ASN1_SIMPLE(ASRange, min, ASN1_INTEGER), + ASN1_SIMPLE(ASRange, max, ASN1_INTEGER) +} ASN1_SEQUENCE_END(ASRange) + +ASN1_CHOICE(ASIdOrRange) = { + ASN1_SIMPLE(ASIdOrRange, u.id, ASN1_INTEGER), + ASN1_SIMPLE(ASIdOrRange, u.range, ASRange) +} ASN1_CHOICE_END(ASIdOrRange) + +ASN1_CHOICE(ASIdentifierChoice) = { + ASN1_SIMPLE(ASIdentifierChoice, u.inherit, ASN1_NULL), + ASN1_SEQUENCE_OF(ASIdentifierChoice, u.asIdsOrRanges, ASIdOrRange) +} ASN1_CHOICE_END(ASIdentifierChoice) + +ASN1_SEQUENCE(ASIdentifiers) = { + ASN1_EXP_OPT(ASIdentifiers, asnum, ASIdentifierChoice, 0), + ASN1_EXP_OPT(ASIdentifiers, rdi, ASIdentifierChoice, 1) +} ASN1_SEQUENCE_END(ASIdentifiers) + +IMPLEMENT_ASN1_FUNCTIONS(ASRange) +IMPLEMENT_ASN1_FUNCTIONS(ASIdOrRange) +IMPLEMENT_ASN1_FUNCTIONS(ASIdentifierChoice) +IMPLEMENT_ASN1_FUNCTIONS(ASIdentifiers) + +/* + * i2r method for an ASIdentifierChoice. + */ +static int i2r_ASIdentifierChoice(BIO *out, + ASIdentifierChoice *choice, + int indent, const char *msg) +{ + int i; + char *s; + if (choice == NULL) + return 1; + BIO_printf(out, "%*s%s:\n", indent, "", msg); + switch (choice->type) { + case ASIdentifierChoice_inherit: + BIO_printf(out, "%*sinherit\n", indent + 2, ""); + break; + case ASIdentifierChoice_asIdsOrRanges: + for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges); i++) { + ASIdOrRange *aor = + sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); + switch (aor->type) { + case ASIdOrRange_id: + if ((s = i2s_ASN1_INTEGER(NULL, aor->u.id)) == NULL) + return 0; + BIO_printf(out, "%*s%s\n", indent + 2, "", s); + OPENSSL_free(s); + break; + case ASIdOrRange_range: + if ((s = i2s_ASN1_INTEGER(NULL, aor->u.range->min)) == NULL) + return 0; + BIO_printf(out, "%*s%s-", indent + 2, "", s); + OPENSSL_free(s); + if ((s = i2s_ASN1_INTEGER(NULL, aor->u.range->max)) == NULL) + return 0; + BIO_printf(out, "%s\n", s); + OPENSSL_free(s); + break; + default: + return 0; + } + } + break; + default: + return 0; + } + return 1; +} + +/* + * i2r method for an ASIdentifier extension. + */ +static int i2r_ASIdentifiers(const X509V3_EXT_METHOD *method, + void *ext, BIO *out, int indent) +{ + ASIdentifiers *asid = ext; + return (i2r_ASIdentifierChoice(out, asid->asnum, indent, + "Autonomous System Numbers") && + i2r_ASIdentifierChoice(out, asid->rdi, indent, + "Routing Domain Identifiers")); +} + +/* + * Sort comparison function for a sequence of ASIdOrRange elements. + */ +static int ASIdOrRange_cmp(const ASIdOrRange *const *a_, + const ASIdOrRange *const *b_) +{ + const ASIdOrRange *a = *a_, *b = *b_; + + assert((a->type == ASIdOrRange_id && a->u.id != NULL) || + (a->type == ASIdOrRange_range && a->u.range != NULL && + a->u.range->min != NULL && a->u.range->max != NULL)); + + assert((b->type == ASIdOrRange_id && b->u.id != NULL) || + (b->type == ASIdOrRange_range && b->u.range != NULL && + b->u.range->min != NULL && b->u.range->max != NULL)); + + if (a->type == ASIdOrRange_id && b->type == ASIdOrRange_id) + return ASN1_INTEGER_cmp(a->u.id, b->u.id); + + if (a->type == ASIdOrRange_range && b->type == ASIdOrRange_range) { + int r = ASN1_INTEGER_cmp(a->u.range->min, b->u.range->min); + return r != 0 ? r : ASN1_INTEGER_cmp(a->u.range->max, + b->u.range->max); + } + + if (a->type == ASIdOrRange_id) + return ASN1_INTEGER_cmp(a->u.id, b->u.range->min); + else + return ASN1_INTEGER_cmp(a->u.range->min, b->u.id); +} + +/* + * Add an inherit element. + */ +int X509v3_asid_add_inherit(ASIdentifiers *asid, int which) +{ + ASIdentifierChoice **choice; + if (asid == NULL) + return 0; + switch (which) { + case V3_ASID_ASNUM: + choice = &asid->asnum; + break; + case V3_ASID_RDI: + choice = &asid->rdi; + break; + default: + return 0; + } + if (*choice == NULL) { + if ((*choice = ASIdentifierChoice_new()) == NULL) + return 0; + if (((*choice)->u.inherit = ASN1_NULL_new()) == NULL) + return 0; + (*choice)->type = ASIdentifierChoice_inherit; + } + return (*choice)->type == ASIdentifierChoice_inherit; +} + +/* + * Add an ID or range to an ASIdentifierChoice. + */ +int X509v3_asid_add_id_or_range(ASIdentifiers *asid, + int which, ASN1_INTEGER *min, ASN1_INTEGER *max) +{ + ASIdentifierChoice **choice; + ASIdOrRange *aor; + if (asid == NULL) + return 0; + switch (which) { + case V3_ASID_ASNUM: + choice = &asid->asnum; + break; + case V3_ASID_RDI: + choice = &asid->rdi; + break; + default: + return 0; + } + if (*choice != NULL && (*choice)->type == ASIdentifierChoice_inherit) + return 0; + if (*choice == NULL) { + if ((*choice = ASIdentifierChoice_new()) == NULL) + return 0; + (*choice)->u.asIdsOrRanges = sk_ASIdOrRange_new(ASIdOrRange_cmp); + if ((*choice)->u.asIdsOrRanges == NULL) + return 0; + (*choice)->type = ASIdentifierChoice_asIdsOrRanges; + } + if ((aor = ASIdOrRange_new()) == NULL) + return 0; + if (max == NULL) { + aor->type = ASIdOrRange_id; + aor->u.id = min; + } else { + aor->type = ASIdOrRange_range; + if ((aor->u.range = ASRange_new()) == NULL) + goto err; + ASN1_INTEGER_free(aor->u.range->min); + aor->u.range->min = min; + ASN1_INTEGER_free(aor->u.range->max); + aor->u.range->max = max; + } + if (!(sk_ASIdOrRange_push((*choice)->u.asIdsOrRanges, aor))) + goto err; + return 1; + + err: + ASIdOrRange_free(aor); + return 0; +} + +/* + * Extract min and max values from an ASIdOrRange. + */ +static int extract_min_max(ASIdOrRange *aor, + ASN1_INTEGER **min, ASN1_INTEGER **max) +{ + if (!ossl_assert(aor != NULL)) + return 0; + switch (aor->type) { + case ASIdOrRange_id: + *min = aor->u.id; + *max = aor->u.id; + return 1; + case ASIdOrRange_range: + *min = aor->u.range->min; + *max = aor->u.range->max; + return 1; + } + + return 0; +} + +/* + * Check whether an ASIdentifierChoice is in canonical form. + */ +static int ASIdentifierChoice_is_canonical(ASIdentifierChoice *choice) +{ + ASN1_INTEGER *a_max_plus_one = NULL; + BIGNUM *bn = NULL; + int i, ret = 0; + + /* + * Empty element or inheritance is canonical. + */ + if (choice == NULL || choice->type == ASIdentifierChoice_inherit) + return 1; + + /* + * If not a list, or if empty list, it's broken. + */ + if (choice->type != ASIdentifierChoice_asIdsOrRanges || + sk_ASIdOrRange_num(choice->u.asIdsOrRanges) == 0) + return 0; + + /* + * It's a list, check it. + */ + for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; i++) { + ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); + ASIdOrRange *b = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i + 1); + ASN1_INTEGER *a_min = NULL, *a_max = NULL, *b_min = NULL, *b_max = + NULL; + + if (!extract_min_max(a, &a_min, &a_max) + || !extract_min_max(b, &b_min, &b_max)) + goto done; + + /* + * Punt misordered list, overlapping start, or inverted range. + */ + if (ASN1_INTEGER_cmp(a_min, b_min) >= 0 || + ASN1_INTEGER_cmp(a_min, a_max) > 0 || + ASN1_INTEGER_cmp(b_min, b_max) > 0) + goto done; + + /* + * Calculate a_max + 1 to check for adjacency. + */ + if ((bn == NULL && (bn = BN_new()) == NULL) || + ASN1_INTEGER_to_BN(a_max, bn) == NULL || + !BN_add_word(bn, 1) || + (a_max_plus_one = + BN_to_ASN1_INTEGER(bn, a_max_plus_one)) == NULL) { + X509V3err(X509V3_F_ASIDENTIFIERCHOICE_IS_CANONICAL, + ERR_R_MALLOC_FAILURE); + goto done; + } + + /* + * Punt if adjacent or overlapping. + */ + if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) >= 0) + goto done; + } + + /* + * Check for inverted range. + */ + i = sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; + { + ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); + ASN1_INTEGER *a_min, *a_max; + if (a != NULL && a->type == ASIdOrRange_range) { + if (!extract_min_max(a, &a_min, &a_max) + || ASN1_INTEGER_cmp(a_min, a_max) > 0) + goto done; + } + } + + ret = 1; + + done: + ASN1_INTEGER_free(a_max_plus_one); + BN_free(bn); + return ret; +} + +/* + * Check whether an ASIdentifier extension is in canonical form. + */ +int X509v3_asid_is_canonical(ASIdentifiers *asid) +{ + return (asid == NULL || + (ASIdentifierChoice_is_canonical(asid->asnum) && + ASIdentifierChoice_is_canonical(asid->rdi))); +} + +/* + * Whack an ASIdentifierChoice into canonical form. + */ +static int ASIdentifierChoice_canonize(ASIdentifierChoice *choice) +{ + ASN1_INTEGER *a_max_plus_one = NULL; + BIGNUM *bn = NULL; + int i, ret = 0; + + /* + * Nothing to do for empty element or inheritance. + */ + if (choice == NULL || choice->type == ASIdentifierChoice_inherit) + return 1; + + /* + * If not a list, or if empty list, it's broken. + */ + if (choice->type != ASIdentifierChoice_asIdsOrRanges || + sk_ASIdOrRange_num(choice->u.asIdsOrRanges) == 0) { + X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE, + X509V3_R_EXTENSION_VALUE_ERROR); + return 0; + } + + /* + * We have a non-empty list. Sort it. + */ + sk_ASIdOrRange_sort(choice->u.asIdsOrRanges); + + /* + * Now check for errors and suboptimal encoding, rejecting the + * former and fixing the latter. + */ + for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; i++) { + ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); + ASIdOrRange *b = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i + 1); + ASN1_INTEGER *a_min = NULL, *a_max = NULL, *b_min = NULL, *b_max = + NULL; + + if (!extract_min_max(a, &a_min, &a_max) + || !extract_min_max(b, &b_min, &b_max)) + goto done; + + /* + * Make sure we're properly sorted (paranoia). + */ + if (!ossl_assert(ASN1_INTEGER_cmp(a_min, b_min) <= 0)) + goto done; + + /* + * Punt inverted ranges. + */ + if (ASN1_INTEGER_cmp(a_min, a_max) > 0 || + ASN1_INTEGER_cmp(b_min, b_max) > 0) + goto done; + + /* + * Check for overlaps. + */ + if (ASN1_INTEGER_cmp(a_max, b_min) >= 0) { + X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE, + X509V3_R_EXTENSION_VALUE_ERROR); + goto done; + } + + /* + * Calculate a_max + 1 to check for adjacency. + */ + if ((bn == NULL && (bn = BN_new()) == NULL) || + ASN1_INTEGER_to_BN(a_max, bn) == NULL || + !BN_add_word(bn, 1) || + (a_max_plus_one = + BN_to_ASN1_INTEGER(bn, a_max_plus_one)) == NULL) { + X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE, + ERR_R_MALLOC_FAILURE); + goto done; + } + + /* + * If a and b are adjacent, merge them. + */ + if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) == 0) { + ASRange *r; + switch (a->type) { + case ASIdOrRange_id: + if ((r = OPENSSL_malloc(sizeof(*r))) == NULL) { + X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE, + ERR_R_MALLOC_FAILURE); + goto done; + } + r->min = a_min; + r->max = b_max; + a->type = ASIdOrRange_range; + a->u.range = r; + break; + case ASIdOrRange_range: + ASN1_INTEGER_free(a->u.range->max); + a->u.range->max = b_max; + break; + } + switch (b->type) { + case ASIdOrRange_id: + b->u.id = NULL; + break; + case ASIdOrRange_range: + b->u.range->max = NULL; + break; + } + ASIdOrRange_free(b); + (void)sk_ASIdOrRange_delete(choice->u.asIdsOrRanges, i + 1); + i--; + continue; + } + } + + /* + * Check for final inverted range. + */ + i = sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; + { + ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); + ASN1_INTEGER *a_min, *a_max; + if (a != NULL && a->type == ASIdOrRange_range) { + if (!extract_min_max(a, &a_min, &a_max) + || ASN1_INTEGER_cmp(a_min, a_max) > 0) + goto done; + } + } + + /* Paranoia */ + if (!ossl_assert(ASIdentifierChoice_is_canonical(choice))) + goto done; + + ret = 1; + + done: + ASN1_INTEGER_free(a_max_plus_one); + BN_free(bn); + return ret; +} + +/* + * Whack an ASIdentifier extension into canonical form. + */ +int X509v3_asid_canonize(ASIdentifiers *asid) +{ + return (asid == NULL || + (ASIdentifierChoice_canonize(asid->asnum) && + ASIdentifierChoice_canonize(asid->rdi))); +} + +/* + * v2i method for an ASIdentifier extension. + */ +static void *v2i_ASIdentifiers(const struct v3_ext_method *method, + struct v3_ext_ctx *ctx, + STACK_OF(CONF_VALUE) *values) +{ + ASN1_INTEGER *min = NULL, *max = NULL; + ASIdentifiers *asid = NULL; + int i; + + if ((asid = ASIdentifiers_new()) == NULL) { + X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE); + return NULL; + } + + for (i = 0; i < sk_CONF_VALUE_num(values); i++) { + CONF_VALUE *val = sk_CONF_VALUE_value(values, i); + int i1 = 0, i2 = 0, i3 = 0, is_range = 0, which = 0; + + /* + * Figure out whether this is an AS or an RDI. + */ + if (!name_cmp(val->name, "AS")) { + which = V3_ASID_ASNUM; + } else if (!name_cmp(val->name, "RDI")) { + which = V3_ASID_RDI; + } else { + X509V3err(X509V3_F_V2I_ASIDENTIFIERS, + X509V3_R_EXTENSION_NAME_ERROR); + X509V3_conf_err(val); + goto err; + } + + /* + * Handle inheritance. + */ + if (strcmp(val->value, "inherit") == 0) { + if (X509v3_asid_add_inherit(asid, which)) + continue; + X509V3err(X509V3_F_V2I_ASIDENTIFIERS, + X509V3_R_INVALID_INHERITANCE); + X509V3_conf_err(val); + goto err; + } + + /* + * Number, range, or mistake, pick it apart and figure out which. + */ + i1 = strspn(val->value, "0123456789"); + if (val->value[i1] == '\0') { + is_range = 0; + } else { + is_range = 1; + i2 = i1 + strspn(val->value + i1, " \t"); + if (val->value[i2] != '-') { + X509V3err(X509V3_F_V2I_ASIDENTIFIERS, + X509V3_R_INVALID_ASNUMBER); + X509V3_conf_err(val); + goto err; + } + i2++; + i2 = i2 + strspn(val->value + i2, " \t"); + i3 = i2 + strspn(val->value + i2, "0123456789"); + if (val->value[i3] != '\0') { + X509V3err(X509V3_F_V2I_ASIDENTIFIERS, + X509V3_R_INVALID_ASRANGE); + X509V3_conf_err(val); + goto err; + } + } + + /* + * Syntax is ok, read and add it. + */ + if (!is_range) { + if (!X509V3_get_value_int(val, &min)) { + X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE); + goto err; + } + } else { + char *s = OPENSSL_strdup(val->value); + if (s == NULL) { + X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE); + goto err; + } + s[i1] = '\0'; + min = s2i_ASN1_INTEGER(NULL, s); + max = s2i_ASN1_INTEGER(NULL, s + i2); + OPENSSL_free(s); + if (min == NULL || max == NULL) { + X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE); + goto err; + } + if (ASN1_INTEGER_cmp(min, max) > 0) { + X509V3err(X509V3_F_V2I_ASIDENTIFIERS, + X509V3_R_EXTENSION_VALUE_ERROR); + goto err; + } + } + if (!X509v3_asid_add_id_or_range(asid, which, min, max)) { + X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE); + goto err; + } + min = max = NULL; + } + + /* + * Canonize the result, then we're done. + */ + if (!X509v3_asid_canonize(asid)) + goto err; + return asid; + + err: + ASIdentifiers_free(asid); + ASN1_INTEGER_free(min); + ASN1_INTEGER_free(max); + return NULL; +} + +/* + * OpenSSL dispatch. + */ +const X509V3_EXT_METHOD v3_asid = { + NID_sbgp_autonomousSysNum, /* nid */ + 0, /* flags */ + ASN1_ITEM_ref(ASIdentifiers), /* template */ + 0, 0, 0, 0, /* old functions, ignored */ + 0, /* i2s */ + 0, /* s2i */ + 0, /* i2v */ + v2i_ASIdentifiers, /* v2i */ + i2r_ASIdentifiers, /* i2r */ + 0, /* r2i */ + NULL /* extension-specific data */ +}; + +/* + * Figure out whether extension uses inheritance. + */ +int X509v3_asid_inherits(ASIdentifiers *asid) +{ + return (asid != NULL && + ((asid->asnum != NULL && + asid->asnum->type == ASIdentifierChoice_inherit) || + (asid->rdi != NULL && + asid->rdi->type == ASIdentifierChoice_inherit))); +} + +/* + * Figure out whether parent contains child. + */ +static int asid_contains(ASIdOrRanges *parent, ASIdOrRanges *child) +{ + ASN1_INTEGER *p_min = NULL, *p_max = NULL, *c_min = NULL, *c_max = NULL; + int p, c; + + if (child == NULL || parent == child) + return 1; + if (parent == NULL) + return 0; + + p = 0; + for (c = 0; c < sk_ASIdOrRange_num(child); c++) { + if (!extract_min_max(sk_ASIdOrRange_value(child, c), &c_min, &c_max)) + return 0; + for (;; p++) { + if (p >= sk_ASIdOrRange_num(parent)) + return 0; + if (!extract_min_max(sk_ASIdOrRange_value(parent, p), &p_min, + &p_max)) + return 0; + if (ASN1_INTEGER_cmp(p_max, c_max) < 0) + continue; + if (ASN1_INTEGER_cmp(p_min, c_min) > 0) + return 0; + break; + } + } + + return 1; +} + +/* + * Test whether a is a subset of b. + */ +int X509v3_asid_subset(ASIdentifiers *a, ASIdentifiers *b) +{ + return (a == NULL || + a == b || + (b != NULL && + !X509v3_asid_inherits(a) && + !X509v3_asid_inherits(b) && + asid_contains(b->asnum->u.asIdsOrRanges, + a->asnum->u.asIdsOrRanges) && + asid_contains(b->rdi->u.asIdsOrRanges, + a->rdi->u.asIdsOrRanges))); +} + +/* + * Validation error handling via callback. + */ +#define validation_err(_err_) \ + do { \ + if (ctx != NULL) { \ + ctx->error = _err_; \ + ctx->error_depth = i; \ + ctx->current_cert = x; \ + ret = ctx->verify_cb(0, ctx); \ + } else { \ + ret = 0; \ + } \ + if (!ret) \ + goto done; \ + } while (0) + +/* + * Core code for RFC 3779 3.3 path validation. + */ +static int asid_validate_path_internal(X509_STORE_CTX *ctx, + STACK_OF(X509) *chain, + ASIdentifiers *ext) +{ + ASIdOrRanges *child_as = NULL, *child_rdi = NULL; + int i, ret = 1, inherit_as = 0, inherit_rdi = 0; + X509 *x; + + if (!ossl_assert(chain != NULL && sk_X509_num(chain) > 0) + || !ossl_assert(ctx != NULL || ext != NULL) + || !ossl_assert(ctx == NULL || ctx->verify_cb != NULL)) { + if (ctx != NULL) + ctx->error = X509_V_ERR_UNSPECIFIED; + return 0; + } + + + /* + * Figure out where to start. If we don't have an extension to + * check, we're done. Otherwise, check canonical form and + * set up for walking up the chain. + */ + if (ext != NULL) { + i = -1; + x = NULL; + } else { + i = 0; + x = sk_X509_value(chain, i); + if ((ext = x->rfc3779_asid) == NULL) + goto done; + } + if (!X509v3_asid_is_canonical(ext)) + validation_err(X509_V_ERR_INVALID_EXTENSION); + if (ext->asnum != NULL) { + switch (ext->asnum->type) { + case ASIdentifierChoice_inherit: + inherit_as = 1; + break; + case ASIdentifierChoice_asIdsOrRanges: + child_as = ext->asnum->u.asIdsOrRanges; + break; + } + } + if (ext->rdi != NULL) { + switch (ext->rdi->type) { + case ASIdentifierChoice_inherit: + inherit_rdi = 1; + break; + case ASIdentifierChoice_asIdsOrRanges: + child_rdi = ext->rdi->u.asIdsOrRanges; + break; + } + } + + /* + * Now walk up the chain. Extensions must be in canonical form, no + * cert may list resources that its parent doesn't list. + */ + for (i++; i < sk_X509_num(chain); i++) { + x = sk_X509_value(chain, i); + if (!ossl_assert(x != NULL)) { + if (ctx != NULL) + ctx->error = X509_V_ERR_UNSPECIFIED; + return 0; + } + if (x->rfc3779_asid == NULL) { + if (child_as != NULL || child_rdi != NULL) + validation_err(X509_V_ERR_UNNESTED_RESOURCE); + continue; + } + if (!X509v3_asid_is_canonical(x->rfc3779_asid)) + validation_err(X509_V_ERR_INVALID_EXTENSION); + if (x->rfc3779_asid->asnum == NULL && child_as != NULL) { + validation_err(X509_V_ERR_UNNESTED_RESOURCE); + child_as = NULL; + inherit_as = 0; + } + if (x->rfc3779_asid->asnum != NULL && + x->rfc3779_asid->asnum->type == + ASIdentifierChoice_asIdsOrRanges) { + if (inherit_as + || asid_contains(x->rfc3779_asid->asnum->u.asIdsOrRanges, + child_as)) { + child_as = x->rfc3779_asid->asnum->u.asIdsOrRanges; + inherit_as = 0; + } else { + validation_err(X509_V_ERR_UNNESTED_RESOURCE); + } + } + if (x->rfc3779_asid->rdi == NULL && child_rdi != NULL) { + validation_err(X509_V_ERR_UNNESTED_RESOURCE); + child_rdi = NULL; + inherit_rdi = 0; + } + if (x->rfc3779_asid->rdi != NULL && + x->rfc3779_asid->rdi->type == ASIdentifierChoice_asIdsOrRanges) { + if (inherit_rdi || + asid_contains(x->rfc3779_asid->rdi->u.asIdsOrRanges, + child_rdi)) { + child_rdi = x->rfc3779_asid->rdi->u.asIdsOrRanges; + inherit_rdi = 0; + } else { + validation_err(X509_V_ERR_UNNESTED_RESOURCE); + } + } + } + + /* + * Trust anchor can't inherit. + */ + if (!ossl_assert(x != NULL)) { + if (ctx != NULL) + ctx->error = X509_V_ERR_UNSPECIFIED; + return 0; + } + if (x->rfc3779_asid != NULL) { + if (x->rfc3779_asid->asnum != NULL && + x->rfc3779_asid->asnum->type == ASIdentifierChoice_inherit) + validation_err(X509_V_ERR_UNNESTED_RESOURCE); + if (x->rfc3779_asid->rdi != NULL && + x->rfc3779_asid->rdi->type == ASIdentifierChoice_inherit) + validation_err(X509_V_ERR_UNNESTED_RESOURCE); + } + + done: + return ret; +} + +#undef validation_err + +/* + * RFC 3779 3.3 path validation -- called from X509_verify_cert(). + */ +int X509v3_asid_validate_path(X509_STORE_CTX *ctx) +{ + if (ctx->chain == NULL + || sk_X509_num(ctx->chain) == 0 + || ctx->verify_cb == NULL) { + ctx->error = X509_V_ERR_UNSPECIFIED; + return 0; + } + return asid_validate_path_internal(ctx, ctx->chain, NULL); +} + +/* + * RFC 3779 3.3 path validation of an extension. + * Test whether chain covers extension. + */ +int X509v3_asid_validate_resource_set(STACK_OF(X509) *chain, + ASIdentifiers *ext, int allow_inheritance) +{ + if (ext == NULL) + return 1; + if (chain == NULL || sk_X509_num(chain) == 0) + return 0; + if (!allow_inheritance && X509v3_asid_inherits(ext)) + return 0; + return asid_validate_path_internal(NULL, chain, ext); +} + +#endif /* OPENSSL_NO_RFC3779 */ diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_bcons.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_bcons.c new file mode 100644 index 000000000..3bbf15550 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_bcons.c @@ -0,0 +1,84 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "ext_dat.h" + +static STACK_OF(CONF_VALUE) *i2v_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method, + BASIC_CONSTRAINTS *bcons, + STACK_OF(CONF_VALUE) + *extlist); +static BASIC_CONSTRAINTS *v2i_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *values); + +const X509V3_EXT_METHOD v3_bcons = { + NID_basic_constraints, 0, + ASN1_ITEM_ref(BASIC_CONSTRAINTS), + 0, 0, 0, 0, + 0, 0, + (X509V3_EXT_I2V) i2v_BASIC_CONSTRAINTS, + (X509V3_EXT_V2I)v2i_BASIC_CONSTRAINTS, + NULL, NULL, + NULL +}; + +ASN1_SEQUENCE(BASIC_CONSTRAINTS) = { + ASN1_OPT(BASIC_CONSTRAINTS, ca, ASN1_FBOOLEAN), + ASN1_OPT(BASIC_CONSTRAINTS, pathlen, ASN1_INTEGER) +} ASN1_SEQUENCE_END(BASIC_CONSTRAINTS) + +IMPLEMENT_ASN1_FUNCTIONS(BASIC_CONSTRAINTS) + +static STACK_OF(CONF_VALUE) *i2v_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method, + BASIC_CONSTRAINTS *bcons, + STACK_OF(CONF_VALUE) + *extlist) +{ + X509V3_add_value_bool("CA", bcons->ca, &extlist); + X509V3_add_value_int("pathlen", bcons->pathlen, &extlist); + return extlist; +} + +static BASIC_CONSTRAINTS *v2i_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *values) +{ + BASIC_CONSTRAINTS *bcons = NULL; + CONF_VALUE *val; + int i; + + if ((bcons = BASIC_CONSTRAINTS_new()) == NULL) { + X509V3err(X509V3_F_V2I_BASIC_CONSTRAINTS, ERR_R_MALLOC_FAILURE); + return NULL; + } + for (i = 0; i < sk_CONF_VALUE_num(values); i++) { + val = sk_CONF_VALUE_value(values, i); + if (strcmp(val->name, "CA") == 0) { + if (!X509V3_get_value_bool(val, &bcons->ca)) + goto err; + } else if (strcmp(val->name, "pathlen") == 0) { + if (!X509V3_get_value_int(val, &bcons->pathlen)) + goto err; + } else { + X509V3err(X509V3_F_V2I_BASIC_CONSTRAINTS, X509V3_R_INVALID_NAME); + X509V3_conf_err(val); + goto err; + } + } + return bcons; + err: + BASIC_CONSTRAINTS_free(bcons); + return NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_bitst.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_bitst.c new file mode 100644 index 000000000..4802116ba --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_bitst.c @@ -0,0 +1,93 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include "ext_dat.h" + +static BIT_STRING_BITNAME ns_cert_type_table[] = { + {0, "SSL Client", "client"}, + {1, "SSL Server", "server"}, + {2, "S/MIME", "email"}, + {3, "Object Signing", "objsign"}, + {4, "Unused", "reserved"}, + {5, "SSL CA", "sslCA"}, + {6, "S/MIME CA", "emailCA"}, + {7, "Object Signing CA", "objCA"}, + {-1, NULL, NULL} +}; + +static BIT_STRING_BITNAME key_usage_type_table[] = { + {0, "Digital Signature", "digitalSignature"}, + {1, "Non Repudiation", "nonRepudiation"}, + {2, "Key Encipherment", "keyEncipherment"}, + {3, "Data Encipherment", "dataEncipherment"}, + {4, "Key Agreement", "keyAgreement"}, + {5, "Certificate Sign", "keyCertSign"}, + {6, "CRL Sign", "cRLSign"}, + {7, "Encipher Only", "encipherOnly"}, + {8, "Decipher Only", "decipherOnly"}, + {-1, NULL, NULL} +}; + +const X509V3_EXT_METHOD v3_nscert = +EXT_BITSTRING(NID_netscape_cert_type, ns_cert_type_table); +const X509V3_EXT_METHOD v3_key_usage = +EXT_BITSTRING(NID_key_usage, key_usage_type_table); + +STACK_OF(CONF_VALUE) *i2v_ASN1_BIT_STRING(X509V3_EXT_METHOD *method, + ASN1_BIT_STRING *bits, + STACK_OF(CONF_VALUE) *ret) +{ + BIT_STRING_BITNAME *bnam; + for (bnam = method->usr_data; bnam->lname; bnam++) { + if (ASN1_BIT_STRING_get_bit(bits, bnam->bitnum)) + X509V3_add_value(bnam->lname, NULL, &ret); + } + return ret; +} + +ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval) +{ + CONF_VALUE *val; + ASN1_BIT_STRING *bs; + int i; + BIT_STRING_BITNAME *bnam; + if ((bs = ASN1_BIT_STRING_new()) == NULL) { + X509V3err(X509V3_F_V2I_ASN1_BIT_STRING, ERR_R_MALLOC_FAILURE); + return NULL; + } + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + val = sk_CONF_VALUE_value(nval, i); + for (bnam = method->usr_data; bnam->lname; bnam++) { + if (strcmp(bnam->sname, val->name) == 0 + || strcmp(bnam->lname, val->name) == 0) { + if (!ASN1_BIT_STRING_set_bit(bs, bnam->bitnum, 1)) { + X509V3err(X509V3_F_V2I_ASN1_BIT_STRING, + ERR_R_MALLOC_FAILURE); + ASN1_BIT_STRING_free(bs); + return NULL; + } + break; + } + } + if (!bnam->lname) { + X509V3err(X509V3_F_V2I_ASN1_BIT_STRING, + X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT); + X509V3_conf_err(val); + ASN1_BIT_STRING_free(bs); + return NULL; + } + } + return bs; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_conf.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_conf.c new file mode 100644 index 000000000..7acaebfa2 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_conf.c @@ -0,0 +1,511 @@ +/* + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* extension creation utilities */ + +#include +#include "internal/ctype.h" +#include "internal/cryptlib.h" +#include +#include +#include "internal/x509_int.h" +#include + +static int v3_check_critical(const char **value); +static int v3_check_generic(const char **value); +static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid, + int crit, const char *value); +static X509_EXTENSION *v3_generic_extension(const char *ext, const char *value, + int crit, int type, + X509V3_CTX *ctx); +static char *conf_lhash_get_string(void *db, const char *section, const char *value); +static STACK_OF(CONF_VALUE) *conf_lhash_get_section(void *db, const char *section); +static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, + int ext_nid, int crit, void *ext_struc); +static unsigned char *generic_asn1(const char *value, X509V3_CTX *ctx, + long *ext_len); +/* CONF *conf: Config file */ +/* char *name: Name */ +/* char *value: Value */ +X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, const char *name, + const char *value) +{ + int crit; + int ext_type; + X509_EXTENSION *ret; + crit = v3_check_critical(&value); + if ((ext_type = v3_check_generic(&value))) + return v3_generic_extension(name, value, crit, ext_type, ctx); + ret = do_ext_nconf(conf, ctx, OBJ_sn2nid(name), crit, value); + if (!ret) { + X509V3err(X509V3_F_X509V3_EXT_NCONF, X509V3_R_ERROR_IN_EXTENSION); + ERR_add_error_data(4, "name=", name, ", value=", value); + } + return ret; +} + +/* CONF *conf: Config file */ +/* char *value: Value */ +X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid, + const char *value) +{ + int crit; + int ext_type; + crit = v3_check_critical(&value); + if ((ext_type = v3_check_generic(&value))) + return v3_generic_extension(OBJ_nid2sn(ext_nid), + value, crit, ext_type, ctx); + return do_ext_nconf(conf, ctx, ext_nid, crit, value); +} + +/* CONF *conf: Config file */ +/* char *value: Value */ +static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid, + int crit, const char *value) +{ + const X509V3_EXT_METHOD *method; + X509_EXTENSION *ext; + STACK_OF(CONF_VALUE) *nval; + void *ext_struc; + + if (ext_nid == NID_undef) { + X509V3err(X509V3_F_DO_EXT_NCONF, X509V3_R_UNKNOWN_EXTENSION_NAME); + return NULL; + } + if ((method = X509V3_EXT_get_nid(ext_nid)) == NULL) { + X509V3err(X509V3_F_DO_EXT_NCONF, X509V3_R_UNKNOWN_EXTENSION); + return NULL; + } + /* Now get internal extension representation based on type */ + if (method->v2i) { + if (*value == '@') + nval = NCONF_get_section(conf, value + 1); + else + nval = X509V3_parse_list(value); + if (nval == NULL || sk_CONF_VALUE_num(nval) <= 0) { + X509V3err(X509V3_F_DO_EXT_NCONF, + X509V3_R_INVALID_EXTENSION_STRING); + ERR_add_error_data(4, "name=", OBJ_nid2sn(ext_nid), ",section=", + value); + if (*value != '@') + sk_CONF_VALUE_pop_free(nval, X509V3_conf_free); + return NULL; + } + ext_struc = method->v2i(method, ctx, nval); + if (*value != '@') + sk_CONF_VALUE_pop_free(nval, X509V3_conf_free); + if (!ext_struc) + return NULL; + } else if (method->s2i) { + if ((ext_struc = method->s2i(method, ctx, value)) == NULL) + return NULL; + } else if (method->r2i) { + if (!ctx->db || !ctx->db_meth) { + X509V3err(X509V3_F_DO_EXT_NCONF, X509V3_R_NO_CONFIG_DATABASE); + return NULL; + } + if ((ext_struc = method->r2i(method, ctx, value)) == NULL) + return NULL; + } else { + X509V3err(X509V3_F_DO_EXT_NCONF, + X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED); + ERR_add_error_data(2, "name=", OBJ_nid2sn(ext_nid)); + return NULL; + } + + ext = do_ext_i2d(method, ext_nid, crit, ext_struc); + if (method->it) + ASN1_item_free(ext_struc, ASN1_ITEM_ptr(method->it)); + else + method->ext_free(ext_struc); + return ext; + +} + +static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, + int ext_nid, int crit, void *ext_struc) +{ + unsigned char *ext_der = NULL; + int ext_len; + ASN1_OCTET_STRING *ext_oct = NULL; + X509_EXTENSION *ext; + /* Convert internal representation to DER */ + if (method->it) { + ext_der = NULL; + ext_len = + ASN1_item_i2d(ext_struc, &ext_der, ASN1_ITEM_ptr(method->it)); + if (ext_len < 0) + goto merr; + } else { + unsigned char *p; + + ext_len = method->i2d(ext_struc, NULL); + if ((ext_der = OPENSSL_malloc(ext_len)) == NULL) + goto merr; + p = ext_der; + method->i2d(ext_struc, &p); + } + if ((ext_oct = ASN1_OCTET_STRING_new()) == NULL) + goto merr; + ext_oct->data = ext_der; + ext_der = NULL; + ext_oct->length = ext_len; + + ext = X509_EXTENSION_create_by_NID(NULL, ext_nid, crit, ext_oct); + if (!ext) + goto merr; + ASN1_OCTET_STRING_free(ext_oct); + + return ext; + + merr: + X509V3err(X509V3_F_DO_EXT_I2D, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ext_der); + ASN1_OCTET_STRING_free(ext_oct); + return NULL; + +} + +/* Given an internal structure, nid and critical flag create an extension */ + +X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc) +{ + const X509V3_EXT_METHOD *method; + + if ((method = X509V3_EXT_get_nid(ext_nid)) == NULL) { + X509V3err(X509V3_F_X509V3_EXT_I2D, X509V3_R_UNKNOWN_EXTENSION); + return NULL; + } + return do_ext_i2d(method, ext_nid, crit, ext_struc); +} + +/* Check the extension string for critical flag */ +static int v3_check_critical(const char **value) +{ + const char *p = *value; + if ((strlen(p) < 9) || strncmp(p, "critical,", 9)) + return 0; + p += 9; + while (ossl_isspace(*p)) + p++; + *value = p; + return 1; +} + +/* Check extension string for generic extension and return the type */ +static int v3_check_generic(const char **value) +{ + int gen_type = 0; + const char *p = *value; + if ((strlen(p) >= 4) && strncmp(p, "DER:", 4) == 0) { + p += 4; + gen_type = 1; + } else if ((strlen(p) >= 5) && strncmp(p, "ASN1:", 5) == 0) { + p += 5; + gen_type = 2; + } else + return 0; + + while (ossl_isspace(*p)) + p++; + *value = p; + return gen_type; +} + +/* Create a generic extension: for now just handle DER type */ +static X509_EXTENSION *v3_generic_extension(const char *ext, const char *value, + int crit, int gen_type, + X509V3_CTX *ctx) +{ + unsigned char *ext_der = NULL; + long ext_len = 0; + ASN1_OBJECT *obj = NULL; + ASN1_OCTET_STRING *oct = NULL; + X509_EXTENSION *extension = NULL; + + if ((obj = OBJ_txt2obj(ext, 0)) == NULL) { + X509V3err(X509V3_F_V3_GENERIC_EXTENSION, + X509V3_R_EXTENSION_NAME_ERROR); + ERR_add_error_data(2, "name=", ext); + goto err; + } + + if (gen_type == 1) + ext_der = OPENSSL_hexstr2buf(value, &ext_len); + else if (gen_type == 2) + ext_der = generic_asn1(value, ctx, &ext_len); + + if (ext_der == NULL) { + X509V3err(X509V3_F_V3_GENERIC_EXTENSION, + X509V3_R_EXTENSION_VALUE_ERROR); + ERR_add_error_data(2, "value=", value); + goto err; + } + + if ((oct = ASN1_OCTET_STRING_new()) == NULL) { + X509V3err(X509V3_F_V3_GENERIC_EXTENSION, ERR_R_MALLOC_FAILURE); + goto err; + } + + oct->data = ext_der; + oct->length = ext_len; + ext_der = NULL; + + extension = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct); + + err: + ASN1_OBJECT_free(obj); + ASN1_OCTET_STRING_free(oct); + OPENSSL_free(ext_der); + return extension; + +} + +static unsigned char *generic_asn1(const char *value, X509V3_CTX *ctx, + long *ext_len) +{ + ASN1_TYPE *typ; + unsigned char *ext_der = NULL; + typ = ASN1_generate_v3(value, ctx); + if (typ == NULL) + return NULL; + *ext_len = i2d_ASN1_TYPE(typ, &ext_der); + ASN1_TYPE_free(typ); + return ext_der; +} + +static void delete_ext(STACK_OF(X509_EXTENSION) *sk, X509_EXTENSION *dext) +{ + int idx; + ASN1_OBJECT *obj; + obj = X509_EXTENSION_get_object(dext); + while ((idx = X509v3_get_ext_by_OBJ(sk, obj, -1)) >= 0) { + X509_EXTENSION *tmpext = X509v3_get_ext(sk, idx); + X509v3_delete_ext(sk, idx); + X509_EXTENSION_free(tmpext); + } +} + +/* + * This is the main function: add a bunch of extensions based on a config + * file section to an extension STACK. + */ + +int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, const char *section, + STACK_OF(X509_EXTENSION) **sk) +{ + X509_EXTENSION *ext; + STACK_OF(CONF_VALUE) *nval; + CONF_VALUE *val; + int i; + + if ((nval = NCONF_get_section(conf, section)) == NULL) + return 0; + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + val = sk_CONF_VALUE_value(nval, i); + if ((ext = X509V3_EXT_nconf(conf, ctx, val->name, val->value)) == NULL) + return 0; + if (ctx->flags == X509V3_CTX_REPLACE) + delete_ext(*sk, ext); + if (sk != NULL) { + if (X509v3_add_ext(sk, ext, -1) == NULL) { + X509_EXTENSION_free(ext); + return 0; + } + } + X509_EXTENSION_free(ext); + } + return 1; +} + +/* + * Convenience functions to add extensions to a certificate, CRL and request + */ + +int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section, + X509 *cert) +{ + STACK_OF(X509_EXTENSION) **sk = NULL; + if (cert) + sk = &cert->cert_info.extensions; + return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk); +} + +/* Same as above but for a CRL */ + +int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section, + X509_CRL *crl) +{ + STACK_OF(X509_EXTENSION) **sk = NULL; + if (crl) + sk = &crl->crl.extensions; + return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk); +} + +/* Add extensions to certificate request */ + +int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section, + X509_REQ *req) +{ + STACK_OF(X509_EXTENSION) *extlist = NULL, **sk = NULL; + int i; + if (req) + sk = &extlist; + i = X509V3_EXT_add_nconf_sk(conf, ctx, section, sk); + if (!i || !sk) + return i; + i = X509_REQ_add_extensions(req, extlist); + sk_X509_EXTENSION_pop_free(extlist, X509_EXTENSION_free); + return i; +} + +/* Config database functions */ + +char *X509V3_get_string(X509V3_CTX *ctx, const char *name, const char *section) +{ + if (!ctx->db || !ctx->db_meth || !ctx->db_meth->get_string) { + X509V3err(X509V3_F_X509V3_GET_STRING, X509V3_R_OPERATION_NOT_DEFINED); + return NULL; + } + if (ctx->db_meth->get_string) + return ctx->db_meth->get_string(ctx->db, name, section); + return NULL; +} + +STACK_OF(CONF_VALUE) *X509V3_get_section(X509V3_CTX *ctx, const char *section) +{ + if (!ctx->db || !ctx->db_meth || !ctx->db_meth->get_section) { + X509V3err(X509V3_F_X509V3_GET_SECTION, + X509V3_R_OPERATION_NOT_DEFINED); + return NULL; + } + if (ctx->db_meth->get_section) + return ctx->db_meth->get_section(ctx->db, section); + return NULL; +} + +void X509V3_string_free(X509V3_CTX *ctx, char *str) +{ + if (!str) + return; + if (ctx->db_meth->free_string) + ctx->db_meth->free_string(ctx->db, str); +} + +void X509V3_section_free(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section) +{ + if (!section) + return; + if (ctx->db_meth->free_section) + ctx->db_meth->free_section(ctx->db, section); +} + +static char *nconf_get_string(void *db, const char *section, const char *value) +{ + return NCONF_get_string(db, section, value); +} + +static STACK_OF(CONF_VALUE) *nconf_get_section(void *db, const char *section) +{ + return NCONF_get_section(db, section); +} + +static X509V3_CONF_METHOD nconf_method = { + nconf_get_string, + nconf_get_section, + NULL, + NULL +}; + +void X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf) +{ + ctx->db_meth = &nconf_method; + ctx->db = conf; +} + +void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subj, X509_REQ *req, + X509_CRL *crl, int flags) +{ + ctx->issuer_cert = issuer; + ctx->subject_cert = subj; + ctx->crl = crl; + ctx->subject_req = req; + ctx->flags = flags; +} + +/* Old conf compatibility functions */ + +X509_EXTENSION *X509V3_EXT_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, + const char *name, const char *value) +{ + CONF ctmp; + CONF_set_nconf(&ctmp, conf); + return X509V3_EXT_nconf(&ctmp, ctx, name, value); +} + +/* LHASH *conf: Config file */ +/* char *value: Value */ +X509_EXTENSION *X509V3_EXT_conf_nid(LHASH_OF(CONF_VALUE) *conf, + X509V3_CTX *ctx, int ext_nid, const char *value) +{ + CONF ctmp; + CONF_set_nconf(&ctmp, conf); + return X509V3_EXT_nconf_nid(&ctmp, ctx, ext_nid, value); +} + +static char *conf_lhash_get_string(void *db, const char *section, const char *value) +{ + return CONF_get_string(db, section, value); +} + +static STACK_OF(CONF_VALUE) *conf_lhash_get_section(void *db, const char *section) +{ + return CONF_get_section(db, section); +} + +static X509V3_CONF_METHOD conf_lhash_method = { + conf_lhash_get_string, + conf_lhash_get_section, + NULL, + NULL +}; + +void X509V3_set_conf_lhash(X509V3_CTX *ctx, LHASH_OF(CONF_VALUE) *lhash) +{ + ctx->db_meth = &conf_lhash_method; + ctx->db = lhash; +} + +int X509V3_EXT_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, + const char *section, X509 *cert) +{ + CONF ctmp; + CONF_set_nconf(&ctmp, conf); + return X509V3_EXT_add_nconf(&ctmp, ctx, section, cert); +} + +/* Same as above but for a CRL */ + +int X509V3_EXT_CRL_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, + const char *section, X509_CRL *crl) +{ + CONF ctmp; + CONF_set_nconf(&ctmp, conf); + return X509V3_EXT_CRL_add_nconf(&ctmp, ctx, section, crl); +} + +/* Add extensions to certificate request */ + +int X509V3_EXT_REQ_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, + const char *section, X509_REQ *req) +{ + CONF ctmp; + CONF_set_nconf(&ctmp, conf); + return X509V3_EXT_REQ_add_nconf(&ctmp, ctx, section, req); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_cpols.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_cpols.c new file mode 100644 index 000000000..7a47fd38b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_cpols.c @@ -0,0 +1,491 @@ +/* + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include + +#include "pcy_int.h" +#include "ext_dat.h" + +/* Certificate policies extension support: this one is a bit complex... */ + +static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol, + BIO *out, int indent); +static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, const char *value); +static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals, + int indent); +static void print_notice(BIO *out, USERNOTICE *notice, int indent); +static POLICYINFO *policy_section(X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *polstrs, int ia5org); +static POLICYQUALINFO *notice_section(X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *unot, int ia5org); +static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos); +static int displaytext_str2tag(const char *tagstr, unsigned int *tag_len); +static int displaytext_get_tag_len(const char *tagstr); + +const X509V3_EXT_METHOD v3_cpols = { + NID_certificate_policies, 0, ASN1_ITEM_ref(CERTIFICATEPOLICIES), + 0, 0, 0, 0, + 0, 0, + 0, 0, + (X509V3_EXT_I2R)i2r_certpol, + (X509V3_EXT_R2I)r2i_certpol, + NULL +}; + +ASN1_ITEM_TEMPLATE(CERTIFICATEPOLICIES) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CERTIFICATEPOLICIES, POLICYINFO) +ASN1_ITEM_TEMPLATE_END(CERTIFICATEPOLICIES) + +IMPLEMENT_ASN1_FUNCTIONS(CERTIFICATEPOLICIES) + +ASN1_SEQUENCE(POLICYINFO) = { + ASN1_SIMPLE(POLICYINFO, policyid, ASN1_OBJECT), + ASN1_SEQUENCE_OF_OPT(POLICYINFO, qualifiers, POLICYQUALINFO) +} ASN1_SEQUENCE_END(POLICYINFO) + +IMPLEMENT_ASN1_FUNCTIONS(POLICYINFO) + +ASN1_ADB_TEMPLATE(policydefault) = ASN1_SIMPLE(POLICYQUALINFO, d.other, ASN1_ANY); + +ASN1_ADB(POLICYQUALINFO) = { + ADB_ENTRY(NID_id_qt_cps, ASN1_SIMPLE(POLICYQUALINFO, d.cpsuri, ASN1_IA5STRING)), + ADB_ENTRY(NID_id_qt_unotice, ASN1_SIMPLE(POLICYQUALINFO, d.usernotice, USERNOTICE)) +} ASN1_ADB_END(POLICYQUALINFO, 0, pqualid, 0, &policydefault_tt, NULL); + +ASN1_SEQUENCE(POLICYQUALINFO) = { + ASN1_SIMPLE(POLICYQUALINFO, pqualid, ASN1_OBJECT), + ASN1_ADB_OBJECT(POLICYQUALINFO) +} ASN1_SEQUENCE_END(POLICYQUALINFO) + +IMPLEMENT_ASN1_FUNCTIONS(POLICYQUALINFO) + +ASN1_SEQUENCE(USERNOTICE) = { + ASN1_OPT(USERNOTICE, noticeref, NOTICEREF), + ASN1_OPT(USERNOTICE, exptext, DISPLAYTEXT) +} ASN1_SEQUENCE_END(USERNOTICE) + +IMPLEMENT_ASN1_FUNCTIONS(USERNOTICE) + +ASN1_SEQUENCE(NOTICEREF) = { + ASN1_SIMPLE(NOTICEREF, organization, DISPLAYTEXT), + ASN1_SEQUENCE_OF(NOTICEREF, noticenos, ASN1_INTEGER) +} ASN1_SEQUENCE_END(NOTICEREF) + +IMPLEMENT_ASN1_FUNCTIONS(NOTICEREF) + +static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, const char *value) +{ + STACK_OF(POLICYINFO) *pols; + char *pstr; + POLICYINFO *pol; + ASN1_OBJECT *pobj; + STACK_OF(CONF_VALUE) *vals = X509V3_parse_list(value); + CONF_VALUE *cnf; + const int num = sk_CONF_VALUE_num(vals); + int i, ia5org; + + if (vals == NULL) { + X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_X509V3_LIB); + return NULL; + } + + pols = sk_POLICYINFO_new_reserve(NULL, num); + if (pols == NULL) { + X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE); + goto err; + } + + ia5org = 0; + for (i = 0; i < num; i++) { + cnf = sk_CONF_VALUE_value(vals, i); + + if (cnf->value || !cnf->name) { + X509V3err(X509V3_F_R2I_CERTPOL, + X509V3_R_INVALID_POLICY_IDENTIFIER); + X509V3_conf_err(cnf); + goto err; + } + pstr = cnf->name; + if (strcmp(pstr, "ia5org") == 0) { + ia5org = 1; + continue; + } else if (*pstr == '@') { + STACK_OF(CONF_VALUE) *polsect; + polsect = X509V3_get_section(ctx, pstr + 1); + if (!polsect) { + X509V3err(X509V3_F_R2I_CERTPOL, X509V3_R_INVALID_SECTION); + + X509V3_conf_err(cnf); + goto err; + } + pol = policy_section(ctx, polsect, ia5org); + X509V3_section_free(ctx, polsect); + if (pol == NULL) + goto err; + } else { + if ((pobj = OBJ_txt2obj(cnf->name, 0)) == NULL) { + X509V3err(X509V3_F_R2I_CERTPOL, + X509V3_R_INVALID_OBJECT_IDENTIFIER); + X509V3_conf_err(cnf); + goto err; + } + pol = POLICYINFO_new(); + if (pol == NULL) { + ASN1_OBJECT_free(pobj); + X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE); + goto err; + } + pol->policyid = pobj; + } + if (!sk_POLICYINFO_push(pols, pol)) { + POLICYINFO_free(pol); + X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE); + goto err; + } + } + sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); + return pols; + err: + sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); + sk_POLICYINFO_pop_free(pols, POLICYINFO_free); + return NULL; +} + +static POLICYINFO *policy_section(X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *polstrs, int ia5org) +{ + int i; + CONF_VALUE *cnf; + POLICYINFO *pol; + POLICYQUALINFO *qual; + + if ((pol = POLICYINFO_new()) == NULL) + goto merr; + for (i = 0; i < sk_CONF_VALUE_num(polstrs); i++) { + cnf = sk_CONF_VALUE_value(polstrs, i); + if (strcmp(cnf->name, "policyIdentifier") == 0) { + ASN1_OBJECT *pobj; + if ((pobj = OBJ_txt2obj(cnf->value, 0)) == NULL) { + X509V3err(X509V3_F_POLICY_SECTION, + X509V3_R_INVALID_OBJECT_IDENTIFIER); + X509V3_conf_err(cnf); + goto err; + } + pol->policyid = pobj; + + } else if (!name_cmp(cnf->name, "CPS")) { + if (pol->qualifiers == NULL) + pol->qualifiers = sk_POLICYQUALINFO_new_null(); + if ((qual = POLICYQUALINFO_new()) == NULL) + goto merr; + if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual)) + goto merr; + if ((qual->pqualid = OBJ_nid2obj(NID_id_qt_cps)) == NULL) { + X509V3err(X509V3_F_POLICY_SECTION, ERR_R_INTERNAL_ERROR); + goto err; + } + if ((qual->d.cpsuri = ASN1_IA5STRING_new()) == NULL) + goto merr; + if (!ASN1_STRING_set(qual->d.cpsuri, cnf->value, + strlen(cnf->value))) + goto merr; + } else if (!name_cmp(cnf->name, "userNotice")) { + STACK_OF(CONF_VALUE) *unot; + if (*cnf->value != '@') { + X509V3err(X509V3_F_POLICY_SECTION, + X509V3_R_EXPECTED_A_SECTION_NAME); + X509V3_conf_err(cnf); + goto err; + } + unot = X509V3_get_section(ctx, cnf->value + 1); + if (!unot) { + X509V3err(X509V3_F_POLICY_SECTION, X509V3_R_INVALID_SECTION); + + X509V3_conf_err(cnf); + goto err; + } + qual = notice_section(ctx, unot, ia5org); + X509V3_section_free(ctx, unot); + if (!qual) + goto err; + if (!pol->qualifiers) + pol->qualifiers = sk_POLICYQUALINFO_new_null(); + if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual)) + goto merr; + } else { + X509V3err(X509V3_F_POLICY_SECTION, X509V3_R_INVALID_OPTION); + + X509V3_conf_err(cnf); + goto err; + } + } + if (!pol->policyid) { + X509V3err(X509V3_F_POLICY_SECTION, X509V3_R_NO_POLICY_IDENTIFIER); + goto err; + } + + return pol; + + merr: + X509V3err(X509V3_F_POLICY_SECTION, ERR_R_MALLOC_FAILURE); + + err: + POLICYINFO_free(pol); + return NULL; +} + +static int displaytext_get_tag_len(const char *tagstr) +{ + char *colon = strchr(tagstr, ':'); + + return (colon == NULL) ? -1 : colon - tagstr; +} + +static int displaytext_str2tag(const char *tagstr, unsigned int *tag_len) +{ + int len; + + *tag_len = 0; + len = displaytext_get_tag_len(tagstr); + + if (len == -1) + return V_ASN1_VISIBLESTRING; + *tag_len = len; + if (len == sizeof("UTF8") - 1 && strncmp(tagstr, "UTF8", len) == 0) + return V_ASN1_UTF8STRING; + if (len == sizeof("UTF8String") - 1 && strncmp(tagstr, "UTF8String", len) == 0) + return V_ASN1_UTF8STRING; + if (len == sizeof("BMP") - 1 && strncmp(tagstr, "BMP", len) == 0) + return V_ASN1_BMPSTRING; + if (len == sizeof("BMPSTRING") - 1 && strncmp(tagstr, "BMPSTRING", len) == 0) + return V_ASN1_BMPSTRING; + if (len == sizeof("VISIBLE") - 1 && strncmp(tagstr, "VISIBLE", len) == 0) + return V_ASN1_VISIBLESTRING; + if (len == sizeof("VISIBLESTRING") - 1 && strncmp(tagstr, "VISIBLESTRING", len) == 0) + return V_ASN1_VISIBLESTRING; + *tag_len = 0; + return V_ASN1_VISIBLESTRING; +} + +static POLICYQUALINFO *notice_section(X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *unot, int ia5org) +{ + int i, ret, len, tag; + unsigned int tag_len; + CONF_VALUE *cnf; + USERNOTICE *not; + POLICYQUALINFO *qual; + char *value = NULL; + + if ((qual = POLICYQUALINFO_new()) == NULL) + goto merr; + if ((qual->pqualid = OBJ_nid2obj(NID_id_qt_unotice)) == NULL) { + X509V3err(X509V3_F_NOTICE_SECTION, ERR_R_INTERNAL_ERROR); + goto err; + } + if ((not = USERNOTICE_new()) == NULL) + goto merr; + qual->d.usernotice = not; + for (i = 0; i < sk_CONF_VALUE_num(unot); i++) { + cnf = sk_CONF_VALUE_value(unot, i); + value = cnf->value; + if (strcmp(cnf->name, "explicitText") == 0) { + tag = displaytext_str2tag(value, &tag_len); + if ((not->exptext = ASN1_STRING_type_new(tag)) == NULL) + goto merr; + if (tag_len != 0) + value += tag_len + 1; + len = strlen(value); + if (!ASN1_STRING_set(not->exptext, value, len)) + goto merr; + } else if (strcmp(cnf->name, "organization") == 0) { + NOTICEREF *nref; + if (!not->noticeref) { + if ((nref = NOTICEREF_new()) == NULL) + goto merr; + not->noticeref = nref; + } else + nref = not->noticeref; + if (ia5org) + nref->organization->type = V_ASN1_IA5STRING; + else + nref->organization->type = V_ASN1_VISIBLESTRING; + if (!ASN1_STRING_set(nref->organization, cnf->value, + strlen(cnf->value))) + goto merr; + } else if (strcmp(cnf->name, "noticeNumbers") == 0) { + NOTICEREF *nref; + STACK_OF(CONF_VALUE) *nos; + if (!not->noticeref) { + if ((nref = NOTICEREF_new()) == NULL) + goto merr; + not->noticeref = nref; + } else + nref = not->noticeref; + nos = X509V3_parse_list(cnf->value); + if (!nos || !sk_CONF_VALUE_num(nos)) { + X509V3err(X509V3_F_NOTICE_SECTION, X509V3_R_INVALID_NUMBERS); + X509V3_conf_err(cnf); + sk_CONF_VALUE_pop_free(nos, X509V3_conf_free); + goto err; + } + ret = nref_nos(nref->noticenos, nos); + sk_CONF_VALUE_pop_free(nos, X509V3_conf_free); + if (!ret) + goto err; + } else { + X509V3err(X509V3_F_NOTICE_SECTION, X509V3_R_INVALID_OPTION); + X509V3_conf_err(cnf); + goto err; + } + } + + if (not->noticeref && + (!not->noticeref->noticenos || !not->noticeref->organization)) { + X509V3err(X509V3_F_NOTICE_SECTION, + X509V3_R_NEED_ORGANIZATION_AND_NUMBERS); + goto err; + } + + return qual; + + merr: + X509V3err(X509V3_F_NOTICE_SECTION, ERR_R_MALLOC_FAILURE); + + err: + POLICYQUALINFO_free(qual); + return NULL; +} + +static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos) +{ + CONF_VALUE *cnf; + ASN1_INTEGER *aint; + + int i; + + for (i = 0; i < sk_CONF_VALUE_num(nos); i++) { + cnf = sk_CONF_VALUE_value(nos, i); + if ((aint = s2i_ASN1_INTEGER(NULL, cnf->name)) == NULL) { + X509V3err(X509V3_F_NREF_NOS, X509V3_R_INVALID_NUMBER); + goto err; + } + if (!sk_ASN1_INTEGER_push(nnums, aint)) + goto merr; + } + return 1; + + merr: + ASN1_INTEGER_free(aint); + X509V3err(X509V3_F_NREF_NOS, ERR_R_MALLOC_FAILURE); + + err: + return 0; +} + +static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol, + BIO *out, int indent) +{ + int i; + POLICYINFO *pinfo; + /* First print out the policy OIDs */ + for (i = 0; i < sk_POLICYINFO_num(pol); i++) { + pinfo = sk_POLICYINFO_value(pol, i); + BIO_printf(out, "%*sPolicy: ", indent, ""); + i2a_ASN1_OBJECT(out, pinfo->policyid); + BIO_puts(out, "\n"); + if (pinfo->qualifiers) + print_qualifiers(out, pinfo->qualifiers, indent + 2); + } + return 1; +} + +static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals, + int indent) +{ + POLICYQUALINFO *qualinfo; + int i; + for (i = 0; i < sk_POLICYQUALINFO_num(quals); i++) { + qualinfo = sk_POLICYQUALINFO_value(quals, i); + switch (OBJ_obj2nid(qualinfo->pqualid)) { + case NID_id_qt_cps: + BIO_printf(out, "%*sCPS: %s\n", indent, "", + qualinfo->d.cpsuri->data); + break; + + case NID_id_qt_unotice: + BIO_printf(out, "%*sUser Notice:\n", indent, ""); + print_notice(out, qualinfo->d.usernotice, indent + 2); + break; + + default: + BIO_printf(out, "%*sUnknown Qualifier: ", indent + 2, ""); + + i2a_ASN1_OBJECT(out, qualinfo->pqualid); + BIO_puts(out, "\n"); + break; + } + } +} + +static void print_notice(BIO *out, USERNOTICE *notice, int indent) +{ + int i; + if (notice->noticeref) { + NOTICEREF *ref; + ref = notice->noticeref; + BIO_printf(out, "%*sOrganization: %s\n", indent, "", + ref->organization->data); + BIO_printf(out, "%*sNumber%s: ", indent, "", + sk_ASN1_INTEGER_num(ref->noticenos) > 1 ? "s" : ""); + for (i = 0; i < sk_ASN1_INTEGER_num(ref->noticenos); i++) { + ASN1_INTEGER *num; + char *tmp; + num = sk_ASN1_INTEGER_value(ref->noticenos, i); + if (i) + BIO_puts(out, ", "); + if (num == NULL) + BIO_puts(out, "(null)"); + else { + tmp = i2s_ASN1_INTEGER(NULL, num); + if (tmp == NULL) + return; + BIO_puts(out, tmp); + OPENSSL_free(tmp); + } + } + BIO_puts(out, "\n"); + } + if (notice->exptext) + BIO_printf(out, "%*sExplicit Text: %s\n", indent, "", + notice->exptext->data); +} + +void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent) +{ + const X509_POLICY_DATA *dat = node->data; + + BIO_printf(out, "%*sPolicy: ", indent, ""); + + i2a_ASN1_OBJECT(out, dat->valid_policy); + BIO_puts(out, "\n"); + BIO_printf(out, "%*s%s\n", indent + 2, "", + node_data_critical(dat) ? "Critical" : "Non Critical"); + if (dat->qualifier_set) + print_qualifiers(out, dat->qualifier_set, indent + 2); + else + BIO_printf(out, "%*sNo Qualifiers\n", indent + 2, ""); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_crld.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_crld.c new file mode 100644 index 000000000..6cba4240a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_crld.c @@ -0,0 +1,506 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include + +#include "internal/x509_int.h" +#include "ext_dat.h" + +static void *v2i_crld(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); +static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out, + int indent); + +const X509V3_EXT_METHOD v3_crld = { + NID_crl_distribution_points, 0, ASN1_ITEM_ref(CRL_DIST_POINTS), + 0, 0, 0, 0, + 0, 0, + 0, + v2i_crld, + i2r_crldp, 0, + NULL +}; + +const X509V3_EXT_METHOD v3_freshest_crl = { + NID_freshest_crl, 0, ASN1_ITEM_ref(CRL_DIST_POINTS), + 0, 0, 0, 0, + 0, 0, + 0, + v2i_crld, + i2r_crldp, 0, + NULL +}; + +static STACK_OF(GENERAL_NAME) *gnames_from_sectname(X509V3_CTX *ctx, + char *sect) +{ + STACK_OF(CONF_VALUE) *gnsect; + STACK_OF(GENERAL_NAME) *gens; + if (*sect == '@') + gnsect = X509V3_get_section(ctx, sect + 1); + else + gnsect = X509V3_parse_list(sect); + if (!gnsect) { + X509V3err(X509V3_F_GNAMES_FROM_SECTNAME, X509V3_R_SECTION_NOT_FOUND); + return NULL; + } + gens = v2i_GENERAL_NAMES(NULL, ctx, gnsect); + if (*sect == '@') + X509V3_section_free(ctx, gnsect); + else + sk_CONF_VALUE_pop_free(gnsect, X509V3_conf_free); + return gens; +} + +static int set_dist_point_name(DIST_POINT_NAME **pdp, X509V3_CTX *ctx, + CONF_VALUE *cnf) +{ + STACK_OF(GENERAL_NAME) *fnm = NULL; + STACK_OF(X509_NAME_ENTRY) *rnm = NULL; + + if (strncmp(cnf->name, "fullname", 9) == 0) { + fnm = gnames_from_sectname(ctx, cnf->value); + if (!fnm) + goto err; + } else if (strcmp(cnf->name, "relativename") == 0) { + int ret; + STACK_OF(CONF_VALUE) *dnsect; + X509_NAME *nm; + nm = X509_NAME_new(); + if (nm == NULL) + return -1; + dnsect = X509V3_get_section(ctx, cnf->value); + if (!dnsect) { + X509V3err(X509V3_F_SET_DIST_POINT_NAME, + X509V3_R_SECTION_NOT_FOUND); + return -1; + } + ret = X509V3_NAME_from_section(nm, dnsect, MBSTRING_ASC); + X509V3_section_free(ctx, dnsect); + rnm = nm->entries; + nm->entries = NULL; + X509_NAME_free(nm); + if (!ret || sk_X509_NAME_ENTRY_num(rnm) <= 0) + goto err; + /* + * Since its a name fragment can't have more than one RDNSequence + */ + if (sk_X509_NAME_ENTRY_value(rnm, + sk_X509_NAME_ENTRY_num(rnm) - 1)->set) { + X509V3err(X509V3_F_SET_DIST_POINT_NAME, + X509V3_R_INVALID_MULTIPLE_RDNS); + goto err; + } + } else + return 0; + + if (*pdp) { + X509V3err(X509V3_F_SET_DIST_POINT_NAME, + X509V3_R_DISTPOINT_ALREADY_SET); + goto err; + } + + *pdp = DIST_POINT_NAME_new(); + if (*pdp == NULL) + goto err; + if (fnm) { + (*pdp)->type = 0; + (*pdp)->name.fullname = fnm; + } else { + (*pdp)->type = 1; + (*pdp)->name.relativename = rnm; + } + + return 1; + + err: + sk_GENERAL_NAME_pop_free(fnm, GENERAL_NAME_free); + sk_X509_NAME_ENTRY_pop_free(rnm, X509_NAME_ENTRY_free); + return -1; +} + +static const BIT_STRING_BITNAME reason_flags[] = { + {0, "Unused", "unused"}, + {1, "Key Compromise", "keyCompromise"}, + {2, "CA Compromise", "CACompromise"}, + {3, "Affiliation Changed", "affiliationChanged"}, + {4, "Superseded", "superseded"}, + {5, "Cessation Of Operation", "cessationOfOperation"}, + {6, "Certificate Hold", "certificateHold"}, + {7, "Privilege Withdrawn", "privilegeWithdrawn"}, + {8, "AA Compromise", "AACompromise"}, + {-1, NULL, NULL} +}; + +static int set_reasons(ASN1_BIT_STRING **preas, char *value) +{ + STACK_OF(CONF_VALUE) *rsk = NULL; + const BIT_STRING_BITNAME *pbn; + const char *bnam; + int i, ret = 0; + rsk = X509V3_parse_list(value); + if (rsk == NULL) + return 0; + if (*preas != NULL) + goto err; + for (i = 0; i < sk_CONF_VALUE_num(rsk); i++) { + bnam = sk_CONF_VALUE_value(rsk, i)->name; + if (*preas == NULL) { + *preas = ASN1_BIT_STRING_new(); + if (*preas == NULL) + goto err; + } + for (pbn = reason_flags; pbn->lname; pbn++) { + if (strcmp(pbn->sname, bnam) == 0) { + if (!ASN1_BIT_STRING_set_bit(*preas, pbn->bitnum, 1)) + goto err; + break; + } + } + if (!pbn->lname) + goto err; + } + ret = 1; + + err: + sk_CONF_VALUE_pop_free(rsk, X509V3_conf_free); + return ret; +} + +static int print_reasons(BIO *out, const char *rname, + ASN1_BIT_STRING *rflags, int indent) +{ + int first = 1; + const BIT_STRING_BITNAME *pbn; + BIO_printf(out, "%*s%s:\n%*s", indent, "", rname, indent + 2, ""); + for (pbn = reason_flags; pbn->lname; pbn++) { + if (ASN1_BIT_STRING_get_bit(rflags, pbn->bitnum)) { + if (first) + first = 0; + else + BIO_puts(out, ", "); + BIO_puts(out, pbn->lname); + } + } + if (first) + BIO_puts(out, "\n"); + else + BIO_puts(out, "\n"); + return 1; +} + +static DIST_POINT *crldp_from_section(X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval) +{ + int i; + CONF_VALUE *cnf; + DIST_POINT *point = DIST_POINT_new(); + + if (point == NULL) + goto err; + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + int ret; + cnf = sk_CONF_VALUE_value(nval, i); + ret = set_dist_point_name(&point->distpoint, ctx, cnf); + if (ret > 0) + continue; + if (ret < 0) + goto err; + if (strcmp(cnf->name, "reasons") == 0) { + if (!set_reasons(&point->reasons, cnf->value)) + goto err; + } else if (strcmp(cnf->name, "CRLissuer") == 0) { + point->CRLissuer = gnames_from_sectname(ctx, cnf->value); + if (!point->CRLissuer) + goto err; + } + } + + return point; + + err: + DIST_POINT_free(point); + return NULL; +} + +static void *v2i_crld(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) +{ + STACK_OF(DIST_POINT) *crld; + GENERAL_NAMES *gens = NULL; + GENERAL_NAME *gen = NULL; + CONF_VALUE *cnf; + const int num = sk_CONF_VALUE_num(nval); + int i; + + crld = sk_DIST_POINT_new_reserve(NULL, num); + if (crld == NULL) + goto merr; + for (i = 0; i < num; i++) { + DIST_POINT *point; + + cnf = sk_CONF_VALUE_value(nval, i); + if (!cnf->value) { + STACK_OF(CONF_VALUE) *dpsect; + dpsect = X509V3_get_section(ctx, cnf->name); + if (!dpsect) + goto err; + point = crldp_from_section(ctx, dpsect); + X509V3_section_free(ctx, dpsect); + if (!point) + goto err; + sk_DIST_POINT_push(crld, point); /* no failure as it was reserved */ + } else { + if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL) + goto err; + if ((gens = GENERAL_NAMES_new()) == NULL) + goto merr; + if (!sk_GENERAL_NAME_push(gens, gen)) + goto merr; + gen = NULL; + if ((point = DIST_POINT_new()) == NULL) + goto merr; + sk_DIST_POINT_push(crld, point); /* no failure as it was reserved */ + if ((point->distpoint = DIST_POINT_NAME_new()) == NULL) + goto merr; + point->distpoint->name.fullname = gens; + point->distpoint->type = 0; + gens = NULL; + } + } + return crld; + + merr: + X509V3err(X509V3_F_V2I_CRLD, ERR_R_MALLOC_FAILURE); + err: + GENERAL_NAME_free(gen); + GENERAL_NAMES_free(gens); + sk_DIST_POINT_pop_free(crld, DIST_POINT_free); + return NULL; +} + +static int dpn_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + void *exarg) +{ + DIST_POINT_NAME *dpn = (DIST_POINT_NAME *)*pval; + + switch (operation) { + case ASN1_OP_NEW_POST: + dpn->dpname = NULL; + break; + + case ASN1_OP_FREE_POST: + X509_NAME_free(dpn->dpname); + break; + } + return 1; +} + + +ASN1_CHOICE_cb(DIST_POINT_NAME, dpn_cb) = { + ASN1_IMP_SEQUENCE_OF(DIST_POINT_NAME, name.fullname, GENERAL_NAME, 0), + ASN1_IMP_SET_OF(DIST_POINT_NAME, name.relativename, X509_NAME_ENTRY, 1) +} ASN1_CHOICE_END_cb(DIST_POINT_NAME, DIST_POINT_NAME, type) + + +IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT_NAME) + +ASN1_SEQUENCE(DIST_POINT) = { + ASN1_EXP_OPT(DIST_POINT, distpoint, DIST_POINT_NAME, 0), + ASN1_IMP_OPT(DIST_POINT, reasons, ASN1_BIT_STRING, 1), + ASN1_IMP_SEQUENCE_OF_OPT(DIST_POINT, CRLissuer, GENERAL_NAME, 2) +} ASN1_SEQUENCE_END(DIST_POINT) + +IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT) + +ASN1_ITEM_TEMPLATE(CRL_DIST_POINTS) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CRLDistributionPoints, DIST_POINT) +ASN1_ITEM_TEMPLATE_END(CRL_DIST_POINTS) + +IMPLEMENT_ASN1_FUNCTIONS(CRL_DIST_POINTS) + +ASN1_SEQUENCE(ISSUING_DIST_POINT) = { + ASN1_EXP_OPT(ISSUING_DIST_POINT, distpoint, DIST_POINT_NAME, 0), + ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyuser, ASN1_FBOOLEAN, 1), + ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyCA, ASN1_FBOOLEAN, 2), + ASN1_IMP_OPT(ISSUING_DIST_POINT, onlysomereasons, ASN1_BIT_STRING, 3), + ASN1_IMP_OPT(ISSUING_DIST_POINT, indirectCRL, ASN1_FBOOLEAN, 4), + ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyattr, ASN1_FBOOLEAN, 5) +} ASN1_SEQUENCE_END(ISSUING_DIST_POINT) + +IMPLEMENT_ASN1_FUNCTIONS(ISSUING_DIST_POINT) + +static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out, + int indent); +static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval); + +const X509V3_EXT_METHOD v3_idp = { + NID_issuing_distribution_point, X509V3_EXT_MULTILINE, + ASN1_ITEM_ref(ISSUING_DIST_POINT), + 0, 0, 0, 0, + 0, 0, + 0, + v2i_idp, + i2r_idp, 0, + NULL +}; + +static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval) +{ + ISSUING_DIST_POINT *idp = NULL; + CONF_VALUE *cnf; + char *name, *val; + int i, ret; + idp = ISSUING_DIST_POINT_new(); + if (idp == NULL) + goto merr; + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + cnf = sk_CONF_VALUE_value(nval, i); + name = cnf->name; + val = cnf->value; + ret = set_dist_point_name(&idp->distpoint, ctx, cnf); + if (ret > 0) + continue; + if (ret < 0) + goto err; + if (strcmp(name, "onlyuser") == 0) { + if (!X509V3_get_value_bool(cnf, &idp->onlyuser)) + goto err; + } else if (strcmp(name, "onlyCA") == 0) { + if (!X509V3_get_value_bool(cnf, &idp->onlyCA)) + goto err; + } else if (strcmp(name, "onlyAA") == 0) { + if (!X509V3_get_value_bool(cnf, &idp->onlyattr)) + goto err; + } else if (strcmp(name, "indirectCRL") == 0) { + if (!X509V3_get_value_bool(cnf, &idp->indirectCRL)) + goto err; + } else if (strcmp(name, "onlysomereasons") == 0) { + if (!set_reasons(&idp->onlysomereasons, val)) + goto err; + } else { + X509V3err(X509V3_F_V2I_IDP, X509V3_R_INVALID_NAME); + X509V3_conf_err(cnf); + goto err; + } + } + return idp; + + merr: + X509V3err(X509V3_F_V2I_IDP, ERR_R_MALLOC_FAILURE); + err: + ISSUING_DIST_POINT_free(idp); + return NULL; +} + +static int print_gens(BIO *out, STACK_OF(GENERAL_NAME) *gens, int indent) +{ + int i; + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { + BIO_printf(out, "%*s", indent + 2, ""); + GENERAL_NAME_print(out, sk_GENERAL_NAME_value(gens, i)); + BIO_puts(out, "\n"); + } + return 1; +} + +static int print_distpoint(BIO *out, DIST_POINT_NAME *dpn, int indent) +{ + if (dpn->type == 0) { + BIO_printf(out, "%*sFull Name:\n", indent, ""); + print_gens(out, dpn->name.fullname, indent); + } else { + X509_NAME ntmp; + ntmp.entries = dpn->name.relativename; + BIO_printf(out, "%*sRelative Name:\n%*s", indent, "", indent + 2, ""); + X509_NAME_print_ex(out, &ntmp, 0, XN_FLAG_ONELINE); + BIO_puts(out, "\n"); + } + return 1; +} + +static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out, + int indent) +{ + ISSUING_DIST_POINT *idp = pidp; + if (idp->distpoint) + print_distpoint(out, idp->distpoint, indent); + if (idp->onlyuser > 0) + BIO_printf(out, "%*sOnly User Certificates\n", indent, ""); + if (idp->onlyCA > 0) + BIO_printf(out, "%*sOnly CA Certificates\n", indent, ""); + if (idp->indirectCRL > 0) + BIO_printf(out, "%*sIndirect CRL\n", indent, ""); + if (idp->onlysomereasons) + print_reasons(out, "Only Some Reasons", idp->onlysomereasons, indent); + if (idp->onlyattr > 0) + BIO_printf(out, "%*sOnly Attribute Certificates\n", indent, ""); + if (!idp->distpoint && (idp->onlyuser <= 0) && (idp->onlyCA <= 0) + && (idp->indirectCRL <= 0) && !idp->onlysomereasons + && (idp->onlyattr <= 0)) + BIO_printf(out, "%*s\n", indent, ""); + + return 1; +} + +static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out, + int indent) +{ + STACK_OF(DIST_POINT) *crld = pcrldp; + DIST_POINT *point; + int i; + for (i = 0; i < sk_DIST_POINT_num(crld); i++) { + BIO_puts(out, "\n"); + point = sk_DIST_POINT_value(crld, i); + if (point->distpoint) + print_distpoint(out, point->distpoint, indent); + if (point->reasons) + print_reasons(out, "Reasons", point->reasons, indent); + if (point->CRLissuer) { + BIO_printf(out, "%*sCRL Issuer:\n", indent, ""); + print_gens(out, point->CRLissuer, indent); + } + } + return 1; +} + +int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname) +{ + int i; + STACK_OF(X509_NAME_ENTRY) *frag; + X509_NAME_ENTRY *ne; + if (!dpn || (dpn->type != 1)) + return 1; + frag = dpn->name.relativename; + dpn->dpname = X509_NAME_dup(iname); + if (!dpn->dpname) + return 0; + for (i = 0; i < sk_X509_NAME_ENTRY_num(frag); i++) { + ne = sk_X509_NAME_ENTRY_value(frag, i); + if (!X509_NAME_add_entry(dpn->dpname, ne, -1, i ? 0 : 1)) { + X509_NAME_free(dpn->dpname); + dpn->dpname = NULL; + return 0; + } + } + /* generate cached encoding of name */ + if (i2d_X509_NAME(dpn->dpname, NULL) < 0) { + X509_NAME_free(dpn->dpname); + dpn->dpname = NULL; + return 0; + } + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_enum.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_enum.c new file mode 100644 index 000000000..3b0f19744 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_enum.c @@ -0,0 +1,53 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include "ext_dat.h" + +static ENUMERATED_NAMES crl_reasons[] = { + {CRL_REASON_UNSPECIFIED, "Unspecified", "unspecified"}, + {CRL_REASON_KEY_COMPROMISE, "Key Compromise", "keyCompromise"}, + {CRL_REASON_CA_COMPROMISE, "CA Compromise", "CACompromise"}, + {CRL_REASON_AFFILIATION_CHANGED, "Affiliation Changed", + "affiliationChanged"}, + {CRL_REASON_SUPERSEDED, "Superseded", "superseded"}, + {CRL_REASON_CESSATION_OF_OPERATION, + "Cessation Of Operation", "cessationOfOperation"}, + {CRL_REASON_CERTIFICATE_HOLD, "Certificate Hold", "certificateHold"}, + {CRL_REASON_REMOVE_FROM_CRL, "Remove From CRL", "removeFromCRL"}, + {CRL_REASON_PRIVILEGE_WITHDRAWN, "Privilege Withdrawn", + "privilegeWithdrawn"}, + {CRL_REASON_AA_COMPROMISE, "AA Compromise", "AACompromise"}, + {-1, NULL, NULL} +}; + +const X509V3_EXT_METHOD v3_crl_reason = { + NID_crl_reason, 0, ASN1_ITEM_ref(ASN1_ENUMERATED), + 0, 0, 0, 0, + (X509V3_EXT_I2S)i2s_ASN1_ENUMERATED_TABLE, + 0, + 0, 0, 0, 0, + crl_reasons +}; + +char *i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *method, + const ASN1_ENUMERATED *e) +{ + ENUMERATED_NAMES *enam; + long strval; + + strval = ASN1_ENUMERATED_get(e); + for (enam = method->usr_data; enam->lname; enam++) { + if (strval == enam->bitnum) + return OPENSSL_strdup(enam->lname); + } + return i2s_ASN1_ENUMERATED(method, e); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_extku.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_extku.c new file mode 100644 index 000000000..91b24376e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_extku.c @@ -0,0 +1,103 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include "ext_dat.h" + +static void *v2i_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval); +static STACK_OF(CONF_VALUE) *i2v_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD + *method, void *eku, STACK_OF(CONF_VALUE) + *extlist); + +const X509V3_EXT_METHOD v3_ext_ku = { + NID_ext_key_usage, 0, + ASN1_ITEM_ref(EXTENDED_KEY_USAGE), + 0, 0, 0, 0, + 0, 0, + i2v_EXTENDED_KEY_USAGE, + v2i_EXTENDED_KEY_USAGE, + 0, 0, + NULL +}; + +/* NB OCSP acceptable responses also is a SEQUENCE OF OBJECT */ +const X509V3_EXT_METHOD v3_ocsp_accresp = { + NID_id_pkix_OCSP_acceptableResponses, 0, + ASN1_ITEM_ref(EXTENDED_KEY_USAGE), + 0, 0, 0, 0, + 0, 0, + i2v_EXTENDED_KEY_USAGE, + v2i_EXTENDED_KEY_USAGE, + 0, 0, + NULL +}; + +ASN1_ITEM_TEMPLATE(EXTENDED_KEY_USAGE) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, EXTENDED_KEY_USAGE, ASN1_OBJECT) +ASN1_ITEM_TEMPLATE_END(EXTENDED_KEY_USAGE) + +IMPLEMENT_ASN1_FUNCTIONS(EXTENDED_KEY_USAGE) + +static STACK_OF(CONF_VALUE) *i2v_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD + *method, void *a, STACK_OF(CONF_VALUE) + *ext_list) +{ + EXTENDED_KEY_USAGE *eku = a; + int i; + ASN1_OBJECT *obj; + char obj_tmp[80]; + for (i = 0; i < sk_ASN1_OBJECT_num(eku); i++) { + obj = sk_ASN1_OBJECT_value(eku, i); + i2t_ASN1_OBJECT(obj_tmp, 80, obj); + X509V3_add_value(NULL, obj_tmp, &ext_list); + } + return ext_list; +} + +static void *v2i_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval) +{ + EXTENDED_KEY_USAGE *extku; + char *extval; + ASN1_OBJECT *objtmp; + CONF_VALUE *val; + const int num = sk_CONF_VALUE_num(nval); + int i; + + extku = sk_ASN1_OBJECT_new_reserve(NULL, num); + if (extku == NULL) { + X509V3err(X509V3_F_V2I_EXTENDED_KEY_USAGE, ERR_R_MALLOC_FAILURE); + sk_ASN1_OBJECT_free(extku); + return NULL; + } + + for (i = 0; i < num; i++) { + val = sk_CONF_VALUE_value(nval, i); + if (val->value) + extval = val->value; + else + extval = val->name; + if ((objtmp = OBJ_txt2obj(extval, 0)) == NULL) { + sk_ASN1_OBJECT_pop_free(extku, ASN1_OBJECT_free); + X509V3err(X509V3_F_V2I_EXTENDED_KEY_USAGE, + X509V3_R_INVALID_OBJECT_IDENTIFIER); + X509V3_conf_err(val); + return NULL; + } + sk_ASN1_OBJECT_push(extku, objtmp); /* no failure as it was reserved */ + } + return extku; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_genn.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_genn.c new file mode 100644 index 000000000..85fc3fc24 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_genn.c @@ -0,0 +1,201 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include + +ASN1_SEQUENCE(OTHERNAME) = { + ASN1_SIMPLE(OTHERNAME, type_id, ASN1_OBJECT), + /* Maybe have a true ANY DEFINED BY later */ + ASN1_EXP(OTHERNAME, value, ASN1_ANY, 0) +} ASN1_SEQUENCE_END(OTHERNAME) + +IMPLEMENT_ASN1_FUNCTIONS(OTHERNAME) + +ASN1_SEQUENCE(EDIPARTYNAME) = { + ASN1_IMP_OPT(EDIPARTYNAME, nameAssigner, DIRECTORYSTRING, 0), + ASN1_IMP_OPT(EDIPARTYNAME, partyName, DIRECTORYSTRING, 1) +} ASN1_SEQUENCE_END(EDIPARTYNAME) + +IMPLEMENT_ASN1_FUNCTIONS(EDIPARTYNAME) + +ASN1_CHOICE(GENERAL_NAME) = { + ASN1_IMP(GENERAL_NAME, d.otherName, OTHERNAME, GEN_OTHERNAME), + ASN1_IMP(GENERAL_NAME, d.rfc822Name, ASN1_IA5STRING, GEN_EMAIL), + ASN1_IMP(GENERAL_NAME, d.dNSName, ASN1_IA5STRING, GEN_DNS), + /* Don't decode this */ + ASN1_IMP(GENERAL_NAME, d.x400Address, ASN1_SEQUENCE, GEN_X400), + /* X509_NAME is a CHOICE type so use EXPLICIT */ + ASN1_EXP(GENERAL_NAME, d.directoryName, X509_NAME, GEN_DIRNAME), + ASN1_IMP(GENERAL_NAME, d.ediPartyName, EDIPARTYNAME, GEN_EDIPARTY), + ASN1_IMP(GENERAL_NAME, d.uniformResourceIdentifier, ASN1_IA5STRING, GEN_URI), + ASN1_IMP(GENERAL_NAME, d.iPAddress, ASN1_OCTET_STRING, GEN_IPADD), + ASN1_IMP(GENERAL_NAME, d.registeredID, ASN1_OBJECT, GEN_RID) +} ASN1_CHOICE_END(GENERAL_NAME) + +IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAME) + +ASN1_ITEM_TEMPLATE(GENERAL_NAMES) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, GeneralNames, GENERAL_NAME) +ASN1_ITEM_TEMPLATE_END(GENERAL_NAMES) + +IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAMES) + +GENERAL_NAME *GENERAL_NAME_dup(GENERAL_NAME *a) +{ + return (GENERAL_NAME *)ASN1_dup((i2d_of_void *)i2d_GENERAL_NAME, + (d2i_of_void *)d2i_GENERAL_NAME, + (char *)a); +} + +/* Returns 0 if they are equal, != 0 otherwise. */ +int GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b) +{ + int result = -1; + + if (!a || !b || a->type != b->type) + return -1; + switch (a->type) { + case GEN_X400: + case GEN_EDIPARTY: + result = ASN1_TYPE_cmp(a->d.other, b->d.other); + break; + + case GEN_OTHERNAME: + result = OTHERNAME_cmp(a->d.otherName, b->d.otherName); + break; + + case GEN_EMAIL: + case GEN_DNS: + case GEN_URI: + result = ASN1_STRING_cmp(a->d.ia5, b->d.ia5); + break; + + case GEN_DIRNAME: + result = X509_NAME_cmp(a->d.dirn, b->d.dirn); + break; + + case GEN_IPADD: + result = ASN1_OCTET_STRING_cmp(a->d.ip, b->d.ip); + break; + + case GEN_RID: + result = OBJ_cmp(a->d.rid, b->d.rid); + break; + } + return result; +} + +/* Returns 0 if they are equal, != 0 otherwise. */ +int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b) +{ + int result = -1; + + if (!a || !b) + return -1; + /* Check their type first. */ + if ((result = OBJ_cmp(a->type_id, b->type_id)) != 0) + return result; + /* Check the value. */ + result = ASN1_TYPE_cmp(a->value, b->value); + return result; +} + +void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value) +{ + switch (type) { + case GEN_X400: + case GEN_EDIPARTY: + a->d.other = value; + break; + + case GEN_OTHERNAME: + a->d.otherName = value; + break; + + case GEN_EMAIL: + case GEN_DNS: + case GEN_URI: + a->d.ia5 = value; + break; + + case GEN_DIRNAME: + a->d.dirn = value; + break; + + case GEN_IPADD: + a->d.ip = value; + break; + + case GEN_RID: + a->d.rid = value; + break; + } + a->type = type; +} + +void *GENERAL_NAME_get0_value(GENERAL_NAME *a, int *ptype) +{ + if (ptype) + *ptype = a->type; + switch (a->type) { + case GEN_X400: + case GEN_EDIPARTY: + return a->d.other; + + case GEN_OTHERNAME: + return a->d.otherName; + + case GEN_EMAIL: + case GEN_DNS: + case GEN_URI: + return a->d.ia5; + + case GEN_DIRNAME: + return a->d.dirn; + + case GEN_IPADD: + return a->d.ip; + + case GEN_RID: + return a->d.rid; + + default: + return NULL; + } +} + +int GENERAL_NAME_set0_othername(GENERAL_NAME *gen, + ASN1_OBJECT *oid, ASN1_TYPE *value) +{ + OTHERNAME *oth; + oth = OTHERNAME_new(); + if (oth == NULL) + return 0; + ASN1_TYPE_free(oth->value); + oth->type_id = oid; + oth->value = value; + GENERAL_NAME_set0_value(gen, GEN_OTHERNAME, oth); + return 1; +} + +int GENERAL_NAME_get0_otherName(GENERAL_NAME *gen, + ASN1_OBJECT **poid, ASN1_TYPE **pvalue) +{ + if (gen->type != GEN_OTHERNAME) + return 0; + if (poid) + *poid = gen->d.otherName->type_id; + if (pvalue) + *pvalue = gen->d.otherName->value; + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_ia5.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_ia5.c new file mode 100644 index 000000000..c1170d461 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_ia5.c @@ -0,0 +1,65 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include "ext_dat.h" + +const X509V3_EXT_METHOD v3_ns_ia5_list[8] = { + EXT_IA5STRING(NID_netscape_base_url), + EXT_IA5STRING(NID_netscape_revocation_url), + EXT_IA5STRING(NID_netscape_ca_revocation_url), + EXT_IA5STRING(NID_netscape_renewal_url), + EXT_IA5STRING(NID_netscape_ca_policy_url), + EXT_IA5STRING(NID_netscape_ssl_server_name), + EXT_IA5STRING(NID_netscape_comment), + EXT_END +}; + +char *i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method, ASN1_IA5STRING *ia5) +{ + char *tmp; + + if (!ia5 || !ia5->length) + return NULL; + if ((tmp = OPENSSL_malloc(ia5->length + 1)) == NULL) { + X509V3err(X509V3_F_I2S_ASN1_IA5STRING, ERR_R_MALLOC_FAILURE); + return NULL; + } + memcpy(tmp, ia5->data, ia5->length); + tmp[ia5->length] = 0; + return tmp; +} + +ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, const char *str) +{ + ASN1_IA5STRING *ia5; + if (!str) { + X509V3err(X509V3_F_S2I_ASN1_IA5STRING, + X509V3_R_INVALID_NULL_ARGUMENT); + return NULL; + } + if ((ia5 = ASN1_IA5STRING_new()) == NULL) + goto err; + if (!ASN1_STRING_set((ASN1_STRING *)ia5, str, strlen(str))) { + ASN1_IA5STRING_free(ia5); + return NULL; + } +#ifdef CHARSET_EBCDIC + ebcdic2ascii(ia5->data, ia5->data, ia5->length); +#endif /* CHARSET_EBCDIC */ + return ia5; + err: + X509V3err(X509V3_F_S2I_ASN1_IA5STRING, ERR_R_MALLOC_FAILURE); + return NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_info.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_info.c new file mode 100644 index 000000000..7af9e23ae --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_info.c @@ -0,0 +1,162 @@ +/* + * Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "ext_dat.h" + +static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD + *method, AUTHORITY_INFO_ACCESS + *ainfo, STACK_OF(CONF_VALUE) + *ret); +static AUTHORITY_INFO_ACCESS *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD + *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) + *nval); + +const X509V3_EXT_METHOD v3_info = { NID_info_access, X509V3_EXT_MULTILINE, + ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS), + 0, 0, 0, 0, + 0, 0, + (X509V3_EXT_I2V) i2v_AUTHORITY_INFO_ACCESS, + (X509V3_EXT_V2I)v2i_AUTHORITY_INFO_ACCESS, + 0, 0, + NULL +}; + +const X509V3_EXT_METHOD v3_sinfo = { NID_sinfo_access, X509V3_EXT_MULTILINE, + ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS), + 0, 0, 0, 0, + 0, 0, + (X509V3_EXT_I2V) i2v_AUTHORITY_INFO_ACCESS, + (X509V3_EXT_V2I)v2i_AUTHORITY_INFO_ACCESS, + 0, 0, + NULL +}; + +ASN1_SEQUENCE(ACCESS_DESCRIPTION) = { + ASN1_SIMPLE(ACCESS_DESCRIPTION, method, ASN1_OBJECT), + ASN1_SIMPLE(ACCESS_DESCRIPTION, location, GENERAL_NAME) +} ASN1_SEQUENCE_END(ACCESS_DESCRIPTION) + +IMPLEMENT_ASN1_FUNCTIONS(ACCESS_DESCRIPTION) + +ASN1_ITEM_TEMPLATE(AUTHORITY_INFO_ACCESS) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, GeneralNames, ACCESS_DESCRIPTION) +ASN1_ITEM_TEMPLATE_END(AUTHORITY_INFO_ACCESS) + +IMPLEMENT_ASN1_FUNCTIONS(AUTHORITY_INFO_ACCESS) + +static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS( + X509V3_EXT_METHOD *method, AUTHORITY_INFO_ACCESS *ainfo, + STACK_OF(CONF_VALUE) *ret) +{ + ACCESS_DESCRIPTION *desc; + int i, nlen; + char objtmp[80], *ntmp; + CONF_VALUE *vtmp; + STACK_OF(CONF_VALUE) *tret = ret; + + for (i = 0; i < sk_ACCESS_DESCRIPTION_num(ainfo); i++) { + STACK_OF(CONF_VALUE) *tmp; + + desc = sk_ACCESS_DESCRIPTION_value(ainfo, i); + tmp = i2v_GENERAL_NAME(method, desc->location, tret); + if (tmp == NULL) + goto err; + tret = tmp; + vtmp = sk_CONF_VALUE_value(tret, i); + i2t_ASN1_OBJECT(objtmp, sizeof(objtmp), desc->method); + nlen = strlen(objtmp) + 3 + strlen(vtmp->name) + 1; + ntmp = OPENSSL_malloc(nlen); + if (ntmp == NULL) + goto err; + BIO_snprintf(ntmp, nlen, "%s - %s", objtmp, vtmp->name); + OPENSSL_free(vtmp->name); + vtmp->name = ntmp; + } + if (ret == NULL && tret == NULL) + return sk_CONF_VALUE_new_null(); + + return tret; + err: + X509V3err(X509V3_F_I2V_AUTHORITY_INFO_ACCESS, ERR_R_MALLOC_FAILURE); + if (ret == NULL && tret != NULL) + sk_CONF_VALUE_pop_free(tret, X509V3_conf_free); + return NULL; +} + +static AUTHORITY_INFO_ACCESS *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD + *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) + *nval) +{ + AUTHORITY_INFO_ACCESS *ainfo = NULL; + CONF_VALUE *cnf, ctmp; + ACCESS_DESCRIPTION *acc; + int i, objlen; + const int num = sk_CONF_VALUE_num(nval); + char *objtmp, *ptmp; + + if ((ainfo = sk_ACCESS_DESCRIPTION_new_reserve(NULL, num)) == NULL) { + X509V3err(X509V3_F_V2I_AUTHORITY_INFO_ACCESS, ERR_R_MALLOC_FAILURE); + return NULL; + } + for (i = 0; i < num; i++) { + cnf = sk_CONF_VALUE_value(nval, i); + if ((acc = ACCESS_DESCRIPTION_new()) == NULL) { + X509V3err(X509V3_F_V2I_AUTHORITY_INFO_ACCESS, + ERR_R_MALLOC_FAILURE); + goto err; + } + sk_ACCESS_DESCRIPTION_push(ainfo, acc); /* Cannot fail due to reserve */ + ptmp = strchr(cnf->name, ';'); + if (!ptmp) { + X509V3err(X509V3_F_V2I_AUTHORITY_INFO_ACCESS, + X509V3_R_INVALID_SYNTAX); + goto err; + } + objlen = ptmp - cnf->name; + ctmp.name = ptmp + 1; + ctmp.value = cnf->value; + if (!v2i_GENERAL_NAME_ex(acc->location, method, ctx, &ctmp, 0)) + goto err; + if ((objtmp = OPENSSL_strndup(cnf->name, objlen)) == NULL) { + X509V3err(X509V3_F_V2I_AUTHORITY_INFO_ACCESS, + ERR_R_MALLOC_FAILURE); + goto err; + } + acc->method = OBJ_txt2obj(objtmp, 0); + if (!acc->method) { + X509V3err(X509V3_F_V2I_AUTHORITY_INFO_ACCESS, + X509V3_R_BAD_OBJECT); + ERR_add_error_data(2, "value=", objtmp); + OPENSSL_free(objtmp); + goto err; + } + OPENSSL_free(objtmp); + + } + return ainfo; + err: + sk_ACCESS_DESCRIPTION_pop_free(ainfo, ACCESS_DESCRIPTION_free); + return NULL; +} + +int i2a_ACCESS_DESCRIPTION(BIO *bp, const ACCESS_DESCRIPTION *a) +{ + i2a_ASN1_OBJECT(bp, a->method); + return 2; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_int.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_int.c new file mode 100644 index 000000000..690c90e8f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_int.c @@ -0,0 +1,43 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include "ext_dat.h" + +const X509V3_EXT_METHOD v3_crl_num = { + NID_crl_number, 0, ASN1_ITEM_ref(ASN1_INTEGER), + 0, 0, 0, 0, + (X509V3_EXT_I2S)i2s_ASN1_INTEGER, + 0, + 0, 0, 0, 0, NULL +}; + +const X509V3_EXT_METHOD v3_delta_crl = { + NID_delta_crl, 0, ASN1_ITEM_ref(ASN1_INTEGER), + 0, 0, 0, 0, + (X509V3_EXT_I2S)i2s_ASN1_INTEGER, + 0, + 0, 0, 0, 0, NULL +}; + +static void *s2i_asn1_int(X509V3_EXT_METHOD *meth, X509V3_CTX *ctx, + const char *value) +{ + return s2i_ASN1_INTEGER(meth, value); +} + +const X509V3_EXT_METHOD v3_inhibit_anyp = { + NID_inhibit_any_policy, 0, ASN1_ITEM_ref(ASN1_INTEGER), + 0, 0, 0, 0, + (X509V3_EXT_I2S)i2s_ASN1_INTEGER, + (X509V3_EXT_S2I)s2i_asn1_int, + 0, 0, 0, 0, NULL +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_lib.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_lib.c new file mode 100644 index 000000000..97c1cbc20 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_lib.c @@ -0,0 +1,303 @@ +/* + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* X509 v3 extension utilities */ + +#include +#include "internal/cryptlib.h" +#include +#include + +#include "ext_dat.h" + +static STACK_OF(X509V3_EXT_METHOD) *ext_list = NULL; + +static int ext_cmp(const X509V3_EXT_METHOD *const *a, + const X509V3_EXT_METHOD *const *b); +static void ext_list_free(X509V3_EXT_METHOD *ext); + +int X509V3_EXT_add(X509V3_EXT_METHOD *ext) +{ + if (ext_list == NULL + && (ext_list = sk_X509V3_EXT_METHOD_new(ext_cmp)) == NULL) { + X509V3err(X509V3_F_X509V3_EXT_ADD, ERR_R_MALLOC_FAILURE); + return 0; + } + if (!sk_X509V3_EXT_METHOD_push(ext_list, ext)) { + X509V3err(X509V3_F_X509V3_EXT_ADD, ERR_R_MALLOC_FAILURE); + return 0; + } + return 1; +} + +static int ext_cmp(const X509V3_EXT_METHOD *const *a, + const X509V3_EXT_METHOD *const *b) +{ + return ((*a)->ext_nid - (*b)->ext_nid); +} + +DECLARE_OBJ_BSEARCH_CMP_FN(const X509V3_EXT_METHOD *, + const X509V3_EXT_METHOD *, ext); +IMPLEMENT_OBJ_BSEARCH_CMP_FN(const X509V3_EXT_METHOD *, + const X509V3_EXT_METHOD *, ext); + +#include "standard_exts.h" + +const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid) +{ + X509V3_EXT_METHOD tmp; + const X509V3_EXT_METHOD *t = &tmp, *const *ret; + int idx; + + if (nid < 0) + return NULL; + tmp.ext_nid = nid; + ret = OBJ_bsearch_ext(&t, standard_exts, STANDARD_EXTENSION_COUNT); + if (ret) + return *ret; + if (!ext_list) + return NULL; + idx = sk_X509V3_EXT_METHOD_find(ext_list, &tmp); + return sk_X509V3_EXT_METHOD_value(ext_list, idx); +} + +const X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *ext) +{ + int nid; + if ((nid = OBJ_obj2nid(X509_EXTENSION_get_object(ext))) == NID_undef) + return NULL; + return X509V3_EXT_get_nid(nid); +} + +int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist) +{ + for (; extlist->ext_nid != -1; extlist++) + if (!X509V3_EXT_add(extlist)) + return 0; + return 1; +} + +int X509V3_EXT_add_alias(int nid_to, int nid_from) +{ + const X509V3_EXT_METHOD *ext; + X509V3_EXT_METHOD *tmpext; + + if ((ext = X509V3_EXT_get_nid(nid_from)) == NULL) { + X509V3err(X509V3_F_X509V3_EXT_ADD_ALIAS, X509V3_R_EXTENSION_NOT_FOUND); + return 0; + } + if ((tmpext = OPENSSL_malloc(sizeof(*tmpext))) == NULL) { + X509V3err(X509V3_F_X509V3_EXT_ADD_ALIAS, ERR_R_MALLOC_FAILURE); + return 0; + } + *tmpext = *ext; + tmpext->ext_nid = nid_to; + tmpext->ext_flags |= X509V3_EXT_DYNAMIC; + return X509V3_EXT_add(tmpext); +} + +void X509V3_EXT_cleanup(void) +{ + sk_X509V3_EXT_METHOD_pop_free(ext_list, ext_list_free); + ext_list = NULL; +} + +static void ext_list_free(X509V3_EXT_METHOD *ext) +{ + if (ext->ext_flags & X509V3_EXT_DYNAMIC) + OPENSSL_free(ext); +} + +/* + * Legacy function: we don't need to add standard extensions any more because + * they are now kept in ext_dat.h. + */ + +int X509V3_add_standard_extensions(void) +{ + return 1; +} + +/* Return an extension internal structure */ + +void *X509V3_EXT_d2i(X509_EXTENSION *ext) +{ + const X509V3_EXT_METHOD *method; + const unsigned char *p; + ASN1_STRING *extvalue; + int extlen; + + if ((method = X509V3_EXT_get(ext)) == NULL) + return NULL; + extvalue = X509_EXTENSION_get_data(ext); + p = ASN1_STRING_get0_data(extvalue); + extlen = ASN1_STRING_length(extvalue); + if (method->it) + return ASN1_item_d2i(NULL, &p, extlen, ASN1_ITEM_ptr(method->it)); + return method->d2i(NULL, &p, extlen); +} + +/*- + * Get critical flag and decoded version of extension from a NID. + * The "idx" variable returns the last found extension and can + * be used to retrieve multiple extensions of the same NID. + * However multiple extensions with the same NID is usually + * due to a badly encoded certificate so if idx is NULL we + * choke if multiple extensions exist. + * The "crit" variable is set to the critical value. + * The return value is the decoded extension or NULL on + * error. The actual error can have several different causes, + * the value of *crit reflects the cause: + * >= 0, extension found but not decoded (reflects critical value). + * -1 extension not found. + * -2 extension occurs more than once. + */ + +void *X509V3_get_d2i(const STACK_OF(X509_EXTENSION) *x, int nid, int *crit, + int *idx) +{ + int lastpos, i; + X509_EXTENSION *ex, *found_ex = NULL; + + if (!x) { + if (idx) + *idx = -1; + if (crit) + *crit = -1; + return NULL; + } + if (idx) + lastpos = *idx + 1; + else + lastpos = 0; + if (lastpos < 0) + lastpos = 0; + for (i = lastpos; i < sk_X509_EXTENSION_num(x); i++) { + ex = sk_X509_EXTENSION_value(x, i); + if (OBJ_obj2nid(X509_EXTENSION_get_object(ex)) == nid) { + if (idx) { + *idx = i; + found_ex = ex; + break; + } else if (found_ex) { + /* Found more than one */ + if (crit) + *crit = -2; + return NULL; + } + found_ex = ex; + } + } + if (found_ex) { + /* Found it */ + if (crit) + *crit = X509_EXTENSION_get_critical(found_ex); + return X509V3_EXT_d2i(found_ex); + } + + /* Extension not found */ + if (idx) + *idx = -1; + if (crit) + *crit = -1; + return NULL; +} + +/* + * This function is a general extension append, replace and delete utility. + * The precise operation is governed by the 'flags' value. The 'crit' and + * 'value' arguments (if relevant) are the extensions internal structure. + */ + +int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value, + int crit, unsigned long flags) +{ + int errcode, extidx = -1; + X509_EXTENSION *ext = NULL, *extmp; + STACK_OF(X509_EXTENSION) *ret = NULL; + unsigned long ext_op = flags & X509V3_ADD_OP_MASK; + + /* + * If appending we don't care if it exists, otherwise look for existing + * extension. + */ + if (ext_op != X509V3_ADD_APPEND) + extidx = X509v3_get_ext_by_NID(*x, nid, -1); + + /* See if extension exists */ + if (extidx >= 0) { + /* If keep existing, nothing to do */ + if (ext_op == X509V3_ADD_KEEP_EXISTING) + return 1; + /* If default then its an error */ + if (ext_op == X509V3_ADD_DEFAULT) { + errcode = X509V3_R_EXTENSION_EXISTS; + goto err; + } + /* If delete, just delete it */ + if (ext_op == X509V3_ADD_DELETE) { + if (!sk_X509_EXTENSION_delete(*x, extidx)) + return -1; + return 1; + } + } else { + /* + * If replace existing or delete, error since extension must exist + */ + if ((ext_op == X509V3_ADD_REPLACE_EXISTING) || + (ext_op == X509V3_ADD_DELETE)) { + errcode = X509V3_R_EXTENSION_NOT_FOUND; + goto err; + } + } + + /* + * If we get this far then we have to create an extension: could have + * some flags for alternative encoding schemes... + */ + + ext = X509V3_EXT_i2d(nid, crit, value); + + if (!ext) { + X509V3err(X509V3_F_X509V3_ADD1_I2D, + X509V3_R_ERROR_CREATING_EXTENSION); + return 0; + } + + /* If extension exists replace it.. */ + if (extidx >= 0) { + extmp = sk_X509_EXTENSION_value(*x, extidx); + X509_EXTENSION_free(extmp); + if (!sk_X509_EXTENSION_set(*x, extidx, ext)) + return -1; + return 1; + } + + ret = *x; + if (*x == NULL + && (ret = sk_X509_EXTENSION_new_null()) == NULL) + goto m_fail; + if (!sk_X509_EXTENSION_push(ret, ext)) + goto m_fail; + + *x = ret; + return 1; + + m_fail: + /* X509V3err(X509V3_F_X509V3_ADD1_I2D, ERR_R_MALLOC_FAILURE); */ + if (ret != *x) + sk_X509_EXTENSION_free(ret); + X509_EXTENSION_free(ext); + return -1; + + err: + if (!(flags & X509V3_ADD_SILENT)) + X509V3err(X509V3_F_X509V3_ADD1_I2D, errcode); + return 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_ncons.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_ncons.c new file mode 100644 index 000000000..9a2cd5af0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_ncons.c @@ -0,0 +1,675 @@ +/* + * Copyright 2003-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include "internal/numbers.h" +#include +#include "internal/asn1_int.h" +#include +#include +#include + +#include "internal/x509_int.h" +#include "ext_dat.h" + +static void *v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval); +static int i2r_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, void *a, + BIO *bp, int ind); +static int do_i2r_name_constraints(const X509V3_EXT_METHOD *method, + STACK_OF(GENERAL_SUBTREE) *trees, BIO *bp, + int ind, const char *name); +static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip); + +static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc); +static int nc_match_single(GENERAL_NAME *sub, GENERAL_NAME *gen); +static int nc_dn(X509_NAME *sub, X509_NAME *nm); +static int nc_dns(ASN1_IA5STRING *sub, ASN1_IA5STRING *dns); +static int nc_email(ASN1_IA5STRING *sub, ASN1_IA5STRING *eml); +static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base); +static int nc_ip(ASN1_OCTET_STRING *ip, ASN1_OCTET_STRING *base); + +const X509V3_EXT_METHOD v3_name_constraints = { + NID_name_constraints, 0, + ASN1_ITEM_ref(NAME_CONSTRAINTS), + 0, 0, 0, 0, + 0, 0, + 0, v2i_NAME_CONSTRAINTS, + i2r_NAME_CONSTRAINTS, 0, + NULL +}; + +ASN1_SEQUENCE(GENERAL_SUBTREE) = { + ASN1_SIMPLE(GENERAL_SUBTREE, base, GENERAL_NAME), + ASN1_IMP_OPT(GENERAL_SUBTREE, minimum, ASN1_INTEGER, 0), + ASN1_IMP_OPT(GENERAL_SUBTREE, maximum, ASN1_INTEGER, 1) +} ASN1_SEQUENCE_END(GENERAL_SUBTREE) + +ASN1_SEQUENCE(NAME_CONSTRAINTS) = { + ASN1_IMP_SEQUENCE_OF_OPT(NAME_CONSTRAINTS, permittedSubtrees, + GENERAL_SUBTREE, 0), + ASN1_IMP_SEQUENCE_OF_OPT(NAME_CONSTRAINTS, excludedSubtrees, + GENERAL_SUBTREE, 1), +} ASN1_SEQUENCE_END(NAME_CONSTRAINTS) + + +IMPLEMENT_ASN1_ALLOC_FUNCTIONS(GENERAL_SUBTREE) +IMPLEMENT_ASN1_ALLOC_FUNCTIONS(NAME_CONSTRAINTS) + +/* + * We cannot use strncasecmp here because that applies locale specific rules. + * For example in Turkish 'I' is not the uppercase character for 'i'. We need to + * do a simple ASCII case comparison ignoring the locale (that is why we use + * numeric constants below). + */ +static int ia5ncasecmp(const char *s1, const char *s2, size_t n) +{ + for (; n > 0; n--, s1++, s2++) { + if (*s1 != *s2) { + unsigned char c1 = (unsigned char)*s1, c2 = (unsigned char)*s2; + + /* Convert to lower case */ + if (c1 >= 0x41 /* A */ && c1 <= 0x5A /* Z */) + c1 += 0x20; + if (c2 >= 0x41 /* A */ && c2 <= 0x5A /* Z */) + c2 += 0x20; + + if (c1 == c2) + continue; + + if (c1 < c2) + return -1; + + /* c1 > c2 */ + return 1; + } else if (*s1 == 0) { + /* If we get here we know that *s2 == 0 too */ + return 0; + } + } + + return 0; +} + +static int ia5casecmp(const char *s1, const char *s2) +{ + return ia5ncasecmp(s1, s2, SIZE_MAX); +} + +static void *v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) +{ + int i; + CONF_VALUE tval, *val; + STACK_OF(GENERAL_SUBTREE) **ptree = NULL; + NAME_CONSTRAINTS *ncons = NULL; + GENERAL_SUBTREE *sub = NULL; + + ncons = NAME_CONSTRAINTS_new(); + if (ncons == NULL) + goto memerr; + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + val = sk_CONF_VALUE_value(nval, i); + if (strncmp(val->name, "permitted", 9) == 0 && val->name[9]) { + ptree = &ncons->permittedSubtrees; + tval.name = val->name + 10; + } else if (strncmp(val->name, "excluded", 8) == 0 && val->name[8]) { + ptree = &ncons->excludedSubtrees; + tval.name = val->name + 9; + } else { + X509V3err(X509V3_F_V2I_NAME_CONSTRAINTS, X509V3_R_INVALID_SYNTAX); + goto err; + } + tval.value = val->value; + sub = GENERAL_SUBTREE_new(); + if (sub == NULL) + goto memerr; + if (!v2i_GENERAL_NAME_ex(sub->base, method, ctx, &tval, 1)) + goto err; + if (*ptree == NULL) + *ptree = sk_GENERAL_SUBTREE_new_null(); + if (*ptree == NULL || !sk_GENERAL_SUBTREE_push(*ptree, sub)) + goto memerr; + sub = NULL; + } + + return ncons; + + memerr: + X509V3err(X509V3_F_V2I_NAME_CONSTRAINTS, ERR_R_MALLOC_FAILURE); + err: + NAME_CONSTRAINTS_free(ncons); + GENERAL_SUBTREE_free(sub); + + return NULL; +} + +static int i2r_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, void *a, + BIO *bp, int ind) +{ + NAME_CONSTRAINTS *ncons = a; + do_i2r_name_constraints(method, ncons->permittedSubtrees, + bp, ind, "Permitted"); + do_i2r_name_constraints(method, ncons->excludedSubtrees, + bp, ind, "Excluded"); + return 1; +} + +static int do_i2r_name_constraints(const X509V3_EXT_METHOD *method, + STACK_OF(GENERAL_SUBTREE) *trees, + BIO *bp, int ind, const char *name) +{ + GENERAL_SUBTREE *tree; + int i; + if (sk_GENERAL_SUBTREE_num(trees) > 0) + BIO_printf(bp, "%*s%s:\n", ind, "", name); + for (i = 0; i < sk_GENERAL_SUBTREE_num(trees); i++) { + tree = sk_GENERAL_SUBTREE_value(trees, i); + BIO_printf(bp, "%*s", ind + 2, ""); + if (tree->base->type == GEN_IPADD) + print_nc_ipadd(bp, tree->base->d.ip); + else + GENERAL_NAME_print(bp, tree->base); + BIO_puts(bp, "\n"); + } + return 1; +} + +static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip) +{ + int i, len; + unsigned char *p; + p = ip->data; + len = ip->length; + BIO_puts(bp, "IP:"); + if (len == 8) { + BIO_printf(bp, "%d.%d.%d.%d/%d.%d.%d.%d", + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); + } else if (len == 32) { + for (i = 0; i < 16; i++) { + BIO_printf(bp, "%X", p[0] << 8 | p[1]); + p += 2; + if (i == 7) + BIO_puts(bp, "/"); + else if (i != 15) + BIO_puts(bp, ":"); + } + } else + BIO_printf(bp, "IP Address:"); + return 1; +} + +#define NAME_CHECK_MAX (1 << 20) + +static int add_lengths(int *out, int a, int b) +{ + /* sk_FOO_num(NULL) returns -1 but is effectively 0 when iterating. */ + if (a < 0) + a = 0; + if (b < 0) + b = 0; + + if (a > INT_MAX - b) + return 0; + *out = a + b; + return 1; +} + +/*- + * Check a certificate conforms to a specified set of constraints. + * Return values: + * X509_V_OK: All constraints obeyed. + * X509_V_ERR_PERMITTED_VIOLATION: Permitted subtree violation. + * X509_V_ERR_EXCLUDED_VIOLATION: Excluded subtree violation. + * X509_V_ERR_SUBTREE_MINMAX: Min or max values present and matching type. + * X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE: Unsupported constraint type. + * X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX: bad unsupported constraint syntax. + * X509_V_ERR_UNSUPPORTED_NAME_SYNTAX: bad or unsupported syntax of name + */ + +int NAME_CONSTRAINTS_check(X509 *x, NAME_CONSTRAINTS *nc) +{ + int r, i, name_count, constraint_count; + X509_NAME *nm; + + nm = X509_get_subject_name(x); + + /* + * Guard against certificates with an excessive number of names or + * constraints causing a computationally expensive name constraints check. + */ + if (!add_lengths(&name_count, X509_NAME_entry_count(nm), + sk_GENERAL_NAME_num(x->altname)) + || !add_lengths(&constraint_count, + sk_GENERAL_SUBTREE_num(nc->permittedSubtrees), + sk_GENERAL_SUBTREE_num(nc->excludedSubtrees)) + || (name_count > 0 && constraint_count > NAME_CHECK_MAX / name_count)) + return X509_V_ERR_UNSPECIFIED; + + if (X509_NAME_entry_count(nm) > 0) { + GENERAL_NAME gntmp; + gntmp.type = GEN_DIRNAME; + gntmp.d.directoryName = nm; + + r = nc_match(&gntmp, nc); + + if (r != X509_V_OK) + return r; + + gntmp.type = GEN_EMAIL; + + /* Process any email address attributes in subject name */ + + for (i = -1;;) { + const X509_NAME_ENTRY *ne; + + i = X509_NAME_get_index_by_NID(nm, NID_pkcs9_emailAddress, i); + if (i == -1) + break; + ne = X509_NAME_get_entry(nm, i); + gntmp.d.rfc822Name = X509_NAME_ENTRY_get_data(ne); + if (gntmp.d.rfc822Name->type != V_ASN1_IA5STRING) + return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + + r = nc_match(&gntmp, nc); + + if (r != X509_V_OK) + return r; + } + + } + + for (i = 0; i < sk_GENERAL_NAME_num(x->altname); i++) { + GENERAL_NAME *gen = sk_GENERAL_NAME_value(x->altname, i); + r = nc_match(gen, nc); + if (r != X509_V_OK) + return r; + } + + return X509_V_OK; + +} + +static int cn2dnsid(ASN1_STRING *cn, unsigned char **dnsid, size_t *idlen) +{ + int utf8_length; + unsigned char *utf8_value; + int i; + int isdnsname = 0; + + /* Don't leave outputs uninitialized */ + *dnsid = NULL; + *idlen = 0; + + /*- + * Per RFC 6125, DNS-IDs representing internationalized domain names appear + * in certificates in A-label encoded form: + * + * https://tools.ietf.org/html/rfc6125#section-6.4.2 + * + * The same applies to CNs which are intended to represent DNS names. + * However, while in the SAN DNS-IDs are IA5Strings, as CNs they may be + * needlessly encoded in 16-bit Unicode. We perform a conversion to UTF-8 + * to ensure that we get an ASCII representation of any CNs that are + * representable as ASCII, but just not encoded as ASCII. The UTF-8 form + * may contain some non-ASCII octets, and that's fine, such CNs are not + * valid legacy DNS names. + * + * Note, 'int' is the return type of ASN1_STRING_to_UTF8() so that's what + * we must use for 'utf8_length'. + */ + if ((utf8_length = ASN1_STRING_to_UTF8(&utf8_value, cn)) < 0) + return X509_V_ERR_OUT_OF_MEM; + + /* + * Some certificates have had names that include a *trailing* NUL byte. + * Remove these harmless NUL characters. They would otherwise yield false + * alarms with the following embedded NUL check. + */ + while (utf8_length > 0 && utf8_value[utf8_length - 1] == '\0') + --utf8_length; + + /* Reject *embedded* NULs */ + if ((size_t)utf8_length != strlen((char *)utf8_value)) { + OPENSSL_free(utf8_value); + return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + } + + /* + * XXX: Deviation from strict DNS name syntax, also check names with '_' + * Check DNS name syntax, any '-' or '.' must be internal, + * and on either side of each '.' we can't have a '-' or '.'. + * + * If the name has just one label, we don't consider it a DNS name. This + * means that "CN=sometld" cannot be precluded by DNS name constraints, but + * that is not a problem. + */ + for (i = 0; i < utf8_length; ++i) { + unsigned char c = utf8_value[i]; + + if ((c >= 'a' && c <= 'z') + || (c >= 'A' && c <= 'Z') + || (c >= '0' && c <= '9') + || c == '_') + continue; + + /* Dot and hyphen cannot be first or last. */ + if (i > 0 && i < utf8_length - 1) { + if (c == '-') + continue; + /* + * Next to a dot the preceding and following characters must not be + * another dot or a hyphen. Otherwise, record that the name is + * plausible, since it has two or more labels. + */ + if (c == '.' + && utf8_value[i + 1] != '.' + && utf8_value[i - 1] != '-' + && utf8_value[i + 1] != '-') { + isdnsname = 1; + continue; + } + } + isdnsname = 0; + break; + } + + if (isdnsname) { + *dnsid = utf8_value; + *idlen = (size_t)utf8_length; + return X509_V_OK; + } + OPENSSL_free(utf8_value); + return X509_V_OK; +} + +/* + * Check CN against DNS-ID name constraints. + */ +int NAME_CONSTRAINTS_check_CN(X509 *x, NAME_CONSTRAINTS *nc) +{ + int r, i; + X509_NAME *nm = X509_get_subject_name(x); + ASN1_STRING stmp; + GENERAL_NAME gntmp; + + stmp.flags = 0; + stmp.type = V_ASN1_IA5STRING; + gntmp.type = GEN_DNS; + gntmp.d.dNSName = &stmp; + + /* Process any commonName attributes in subject name */ + + for (i = -1;;) { + X509_NAME_ENTRY *ne; + ASN1_STRING *cn; + unsigned char *idval; + size_t idlen; + + i = X509_NAME_get_index_by_NID(nm, NID_commonName, i); + if (i == -1) + break; + ne = X509_NAME_get_entry(nm, i); + cn = X509_NAME_ENTRY_get_data(ne); + + /* Only process attributes that look like host names */ + if ((r = cn2dnsid(cn, &idval, &idlen)) != X509_V_OK) + return r; + if (idlen == 0) + continue; + + stmp.length = idlen; + stmp.data = idval; + r = nc_match(&gntmp, nc); + OPENSSL_free(idval); + if (r != X509_V_OK) + return r; + } + return X509_V_OK; +} + +static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc) +{ + GENERAL_SUBTREE *sub; + int i, r, match = 0; + + /* + * Permitted subtrees: if any subtrees exist of matching the type at + * least one subtree must match. + */ + + for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->permittedSubtrees); i++) { + sub = sk_GENERAL_SUBTREE_value(nc->permittedSubtrees, i); + if (gen->type != sub->base->type) + continue; + if (sub->minimum || sub->maximum) + return X509_V_ERR_SUBTREE_MINMAX; + /* If we already have a match don't bother trying any more */ + if (match == 2) + continue; + if (match == 0) + match = 1; + r = nc_match_single(gen, sub->base); + if (r == X509_V_OK) + match = 2; + else if (r != X509_V_ERR_PERMITTED_VIOLATION) + return r; + } + + if (match == 1) + return X509_V_ERR_PERMITTED_VIOLATION; + + /* Excluded subtrees: must not match any of these */ + + for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->excludedSubtrees); i++) { + sub = sk_GENERAL_SUBTREE_value(nc->excludedSubtrees, i); + if (gen->type != sub->base->type) + continue; + if (sub->minimum || sub->maximum) + return X509_V_ERR_SUBTREE_MINMAX; + + r = nc_match_single(gen, sub->base); + if (r == X509_V_OK) + return X509_V_ERR_EXCLUDED_VIOLATION; + else if (r != X509_V_ERR_PERMITTED_VIOLATION) + return r; + + } + + return X509_V_OK; + +} + +static int nc_match_single(GENERAL_NAME *gen, GENERAL_NAME *base) +{ + switch (base->type) { + case GEN_DIRNAME: + return nc_dn(gen->d.directoryName, base->d.directoryName); + + case GEN_DNS: + return nc_dns(gen->d.dNSName, base->d.dNSName); + + case GEN_EMAIL: + return nc_email(gen->d.rfc822Name, base->d.rfc822Name); + + case GEN_URI: + return nc_uri(gen->d.uniformResourceIdentifier, + base->d.uniformResourceIdentifier); + + case GEN_IPADD: + return nc_ip(gen->d.iPAddress, base->d.iPAddress); + + default: + return X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE; + } + +} + +/* + * directoryName name constraint matching. The canonical encoding of + * X509_NAME makes this comparison easy. It is matched if the subtree is a + * subset of the name. + */ + +static int nc_dn(X509_NAME *nm, X509_NAME *base) +{ + /* Ensure canonical encodings are up to date. */ + if (nm->modified && i2d_X509_NAME(nm, NULL) < 0) + return X509_V_ERR_OUT_OF_MEM; + if (base->modified && i2d_X509_NAME(base, NULL) < 0) + return X509_V_ERR_OUT_OF_MEM; + if (base->canon_enclen > nm->canon_enclen) + return X509_V_ERR_PERMITTED_VIOLATION; + if (memcmp(base->canon_enc, nm->canon_enc, base->canon_enclen)) + return X509_V_ERR_PERMITTED_VIOLATION; + return X509_V_OK; +} + +static int nc_dns(ASN1_IA5STRING *dns, ASN1_IA5STRING *base) +{ + char *baseptr = (char *)base->data; + char *dnsptr = (char *)dns->data; + /* Empty matches everything */ + if (!*baseptr) + return X509_V_OK; + /* + * Otherwise can add zero or more components on the left so compare RHS + * and if dns is longer and expect '.' as preceding character. + */ + if (dns->length > base->length) { + dnsptr += dns->length - base->length; + if (*baseptr != '.' && dnsptr[-1] != '.') + return X509_V_ERR_PERMITTED_VIOLATION; + } + + if (ia5casecmp(baseptr, dnsptr)) + return X509_V_ERR_PERMITTED_VIOLATION; + + return X509_V_OK; + +} + +static int nc_email(ASN1_IA5STRING *eml, ASN1_IA5STRING *base) +{ + const char *baseptr = (char *)base->data; + const char *emlptr = (char *)eml->data; + + const char *baseat = strchr(baseptr, '@'); + const char *emlat = strchr(emlptr, '@'); + if (!emlat) + return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + /* Special case: initial '.' is RHS match */ + if (!baseat && (*baseptr == '.')) { + if (eml->length > base->length) { + emlptr += eml->length - base->length; + if (ia5casecmp(baseptr, emlptr) == 0) + return X509_V_OK; + } + return X509_V_ERR_PERMITTED_VIOLATION; + } + + /* If we have anything before '@' match local part */ + + if (baseat) { + if (baseat != baseptr) { + if ((baseat - baseptr) != (emlat - emlptr)) + return X509_V_ERR_PERMITTED_VIOLATION; + /* Case sensitive match of local part */ + if (strncmp(baseptr, emlptr, emlat - emlptr)) + return X509_V_ERR_PERMITTED_VIOLATION; + } + /* Position base after '@' */ + baseptr = baseat + 1; + } + emlptr = emlat + 1; + /* Just have hostname left to match: case insensitive */ + if (ia5casecmp(baseptr, emlptr)) + return X509_V_ERR_PERMITTED_VIOLATION; + + return X509_V_OK; + +} + +static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base) +{ + const char *baseptr = (char *)base->data; + const char *hostptr = (char *)uri->data; + const char *p = strchr(hostptr, ':'); + int hostlen; + /* Check for foo:// and skip past it */ + if (!p || (p[1] != '/') || (p[2] != '/')) + return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + hostptr = p + 3; + + /* Determine length of hostname part of URI */ + + /* Look for a port indicator as end of hostname first */ + + p = strchr(hostptr, ':'); + /* Otherwise look for trailing slash */ + if (!p) + p = strchr(hostptr, '/'); + + if (!p) + hostlen = strlen(hostptr); + else + hostlen = p - hostptr; + + if (hostlen == 0) + return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + + /* Special case: initial '.' is RHS match */ + if (*baseptr == '.') { + if (hostlen > base->length) { + p = hostptr + hostlen - base->length; + if (ia5ncasecmp(p, baseptr, base->length) == 0) + return X509_V_OK; + } + return X509_V_ERR_PERMITTED_VIOLATION; + } + + if ((base->length != (int)hostlen) + || ia5ncasecmp(hostptr, baseptr, hostlen)) + return X509_V_ERR_PERMITTED_VIOLATION; + + return X509_V_OK; + +} + +static int nc_ip(ASN1_OCTET_STRING *ip, ASN1_OCTET_STRING *base) +{ + int hostlen, baselen, i; + unsigned char *hostptr, *baseptr, *maskptr; + hostptr = ip->data; + hostlen = ip->length; + baseptr = base->data; + baselen = base->length; + + /* Invalid if not IPv4 or IPv6 */ + if (!((hostlen == 4) || (hostlen == 16))) + return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + if (!((baselen == 8) || (baselen == 32))) + return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + + /* Do not match IPv4 with IPv6 */ + if (hostlen * 2 != baselen) + return X509_V_ERR_PERMITTED_VIOLATION; + + maskptr = base->data + hostlen; + + /* Considering possible not aligned base ipAddress */ + /* Not checking for wrong mask definition: i.e.: 255.0.255.0 */ + for (i = 0; i < hostlen; i++) + if ((hostptr[i] & maskptr[i]) != (baseptr[i] & maskptr[i])) + return X509_V_ERR_PERMITTED_VIOLATION; + + return X509_V_OK; + +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_pci.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_pci.c new file mode 100644 index 000000000..3d124fa6d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_pci.c @@ -0,0 +1,325 @@ +/* + * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This file is dual-licensed and is also available under the following + * terms: + * + * Copyright (c) 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include "ext_dat.h" + +static int i2r_pci(X509V3_EXT_METHOD *method, PROXY_CERT_INFO_EXTENSION *ext, + BIO *out, int indent); +static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, char *str); + +const X509V3_EXT_METHOD v3_pci = + { NID_proxyCertInfo, 0, ASN1_ITEM_ref(PROXY_CERT_INFO_EXTENSION), + 0, 0, 0, 0, + 0, 0, + NULL, NULL, + (X509V3_EXT_I2R)i2r_pci, + (X509V3_EXT_R2I)r2i_pci, + NULL, +}; + +static int i2r_pci(X509V3_EXT_METHOD *method, PROXY_CERT_INFO_EXTENSION *pci, + BIO *out, int indent) +{ + BIO_printf(out, "%*sPath Length Constraint: ", indent, ""); + if (pci->pcPathLengthConstraint) + i2a_ASN1_INTEGER(out, pci->pcPathLengthConstraint); + else + BIO_printf(out, "infinite"); + BIO_puts(out, "\n"); + BIO_printf(out, "%*sPolicy Language: ", indent, ""); + i2a_ASN1_OBJECT(out, pci->proxyPolicy->policyLanguage); + BIO_puts(out, "\n"); + if (pci->proxyPolicy->policy && pci->proxyPolicy->policy->data) + BIO_printf(out, "%*sPolicy Text: %s\n", indent, "", + pci->proxyPolicy->policy->data); + return 1; +} + +static int process_pci_value(CONF_VALUE *val, + ASN1_OBJECT **language, ASN1_INTEGER **pathlen, + ASN1_OCTET_STRING **policy) +{ + int free_policy = 0; + + if (strcmp(val->name, "language") == 0) { + if (*language) { + X509V3err(X509V3_F_PROCESS_PCI_VALUE, + X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED); + X509V3_conf_err(val); + return 0; + } + if ((*language = OBJ_txt2obj(val->value, 0)) == NULL) { + X509V3err(X509V3_F_PROCESS_PCI_VALUE, + X509V3_R_INVALID_OBJECT_IDENTIFIER); + X509V3_conf_err(val); + return 0; + } + } else if (strcmp(val->name, "pathlen") == 0) { + if (*pathlen) { + X509V3err(X509V3_F_PROCESS_PCI_VALUE, + X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED); + X509V3_conf_err(val); + return 0; + } + if (!X509V3_get_value_int(val, pathlen)) { + X509V3err(X509V3_F_PROCESS_PCI_VALUE, + X509V3_R_POLICY_PATH_LENGTH); + X509V3_conf_err(val); + return 0; + } + } else if (strcmp(val->name, "policy") == 0) { + unsigned char *tmp_data = NULL; + long val_len; + if (!*policy) { + *policy = ASN1_OCTET_STRING_new(); + if (*policy == NULL) { + X509V3err(X509V3_F_PROCESS_PCI_VALUE, ERR_R_MALLOC_FAILURE); + X509V3_conf_err(val); + return 0; + } + free_policy = 1; + } + if (strncmp(val->value, "hex:", 4) == 0) { + unsigned char *tmp_data2 = + OPENSSL_hexstr2buf(val->value + 4, &val_len); + + if (!tmp_data2) { + X509V3_conf_err(val); + goto err; + } + + tmp_data = OPENSSL_realloc((*policy)->data, + (*policy)->length + val_len + 1); + if (tmp_data) { + (*policy)->data = tmp_data; + memcpy(&(*policy)->data[(*policy)->length], + tmp_data2, val_len); + (*policy)->length += val_len; + (*policy)->data[(*policy)->length] = '\0'; + } else { + OPENSSL_free(tmp_data2); + /* + * realloc failure implies the original data space is b0rked + * too! + */ + OPENSSL_free((*policy)->data); + (*policy)->data = NULL; + (*policy)->length = 0; + X509V3err(X509V3_F_PROCESS_PCI_VALUE, ERR_R_MALLOC_FAILURE); + X509V3_conf_err(val); + goto err; + } + OPENSSL_free(tmp_data2); + } else if (strncmp(val->value, "file:", 5) == 0) { + unsigned char buf[2048]; + int n; + BIO *b = BIO_new_file(val->value + 5, "r"); + if (!b) { + X509V3err(X509V3_F_PROCESS_PCI_VALUE, ERR_R_BIO_LIB); + X509V3_conf_err(val); + goto err; + } + while ((n = BIO_read(b, buf, sizeof(buf))) > 0 + || (n == 0 && BIO_should_retry(b))) { + if (!n) + continue; + + tmp_data = OPENSSL_realloc((*policy)->data, + (*policy)->length + n + 1); + + if (!tmp_data) { + OPENSSL_free((*policy)->data); + (*policy)->data = NULL; + (*policy)->length = 0; + X509V3err(X509V3_F_PROCESS_PCI_VALUE, + ERR_R_MALLOC_FAILURE); + X509V3_conf_err(val); + BIO_free_all(b); + goto err; + } + + (*policy)->data = tmp_data; + memcpy(&(*policy)->data[(*policy)->length], buf, n); + (*policy)->length += n; + (*policy)->data[(*policy)->length] = '\0'; + } + BIO_free_all(b); + + if (n < 0) { + X509V3err(X509V3_F_PROCESS_PCI_VALUE, ERR_R_BIO_LIB); + X509V3_conf_err(val); + goto err; + } + } else if (strncmp(val->value, "text:", 5) == 0) { + val_len = strlen(val->value + 5); + tmp_data = OPENSSL_realloc((*policy)->data, + (*policy)->length + val_len + 1); + if (tmp_data) { + (*policy)->data = tmp_data; + memcpy(&(*policy)->data[(*policy)->length], + val->value + 5, val_len); + (*policy)->length += val_len; + (*policy)->data[(*policy)->length] = '\0'; + } else { + /* + * realloc failure implies the original data space is b0rked + * too! + */ + OPENSSL_free((*policy)->data); + (*policy)->data = NULL; + (*policy)->length = 0; + X509V3err(X509V3_F_PROCESS_PCI_VALUE, ERR_R_MALLOC_FAILURE); + X509V3_conf_err(val); + goto err; + } + } else { + X509V3err(X509V3_F_PROCESS_PCI_VALUE, + X509V3_R_INCORRECT_POLICY_SYNTAX_TAG); + X509V3_conf_err(val); + goto err; + } + if (!tmp_data) { + X509V3err(X509V3_F_PROCESS_PCI_VALUE, ERR_R_MALLOC_FAILURE); + X509V3_conf_err(val); + goto err; + } + } + return 1; + err: + if (free_policy) { + ASN1_OCTET_STRING_free(*policy); + *policy = NULL; + } + return 0; +} + +static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, char *value) +{ + PROXY_CERT_INFO_EXTENSION *pci = NULL; + STACK_OF(CONF_VALUE) *vals; + ASN1_OBJECT *language = NULL; + ASN1_INTEGER *pathlen = NULL; + ASN1_OCTET_STRING *policy = NULL; + int i, j; + + vals = X509V3_parse_list(value); + for (i = 0; i < sk_CONF_VALUE_num(vals); i++) { + CONF_VALUE *cnf = sk_CONF_VALUE_value(vals, i); + if (!cnf->name || (*cnf->name != '@' && !cnf->value)) { + X509V3err(X509V3_F_R2I_PCI, + X509V3_R_INVALID_PROXY_POLICY_SETTING); + X509V3_conf_err(cnf); + goto err; + } + if (*cnf->name == '@') { + STACK_OF(CONF_VALUE) *sect; + int success_p = 1; + + sect = X509V3_get_section(ctx, cnf->name + 1); + if (!sect) { + X509V3err(X509V3_F_R2I_PCI, X509V3_R_INVALID_SECTION); + X509V3_conf_err(cnf); + goto err; + } + for (j = 0; success_p && j < sk_CONF_VALUE_num(sect); j++) { + success_p = + process_pci_value(sk_CONF_VALUE_value(sect, j), + &language, &pathlen, &policy); + } + X509V3_section_free(ctx, sect); + if (!success_p) + goto err; + } else { + if (!process_pci_value(cnf, &language, &pathlen, &policy)) { + X509V3_conf_err(cnf); + goto err; + } + } + } + + /* Language is mandatory */ + if (!language) { + X509V3err(X509V3_F_R2I_PCI, + X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED); + goto err; + } + i = OBJ_obj2nid(language); + if ((i == NID_Independent || i == NID_id_ppl_inheritAll) && policy) { + X509V3err(X509V3_F_R2I_PCI, + X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY); + goto err; + } + + pci = PROXY_CERT_INFO_EXTENSION_new(); + if (pci == NULL) { + X509V3err(X509V3_F_R2I_PCI, ERR_R_MALLOC_FAILURE); + goto err; + } + + pci->proxyPolicy->policyLanguage = language; + language = NULL; + pci->proxyPolicy->policy = policy; + policy = NULL; + pci->pcPathLengthConstraint = pathlen; + pathlen = NULL; + goto end; + err: + ASN1_OBJECT_free(language); + ASN1_INTEGER_free(pathlen); + pathlen = NULL; + ASN1_OCTET_STRING_free(policy); + policy = NULL; + PROXY_CERT_INFO_EXTENSION_free(pci); + pci = NULL; + end: + sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); + return pci; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_pcia.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_pcia.c new file mode 100644 index 000000000..8d6af60e5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_pcia.c @@ -0,0 +1,64 @@ +/* + * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This file is dual-licensed and is also available under the following + * terms: + * + * Copyright (c) 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +ASN1_SEQUENCE(PROXY_POLICY) = + { + ASN1_SIMPLE(PROXY_POLICY,policyLanguage,ASN1_OBJECT), + ASN1_OPT(PROXY_POLICY,policy,ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(PROXY_POLICY) + +IMPLEMENT_ASN1_FUNCTIONS(PROXY_POLICY) + +ASN1_SEQUENCE(PROXY_CERT_INFO_EXTENSION) = + { + ASN1_OPT(PROXY_CERT_INFO_EXTENSION,pcPathLengthConstraint,ASN1_INTEGER), + ASN1_SIMPLE(PROXY_CERT_INFO_EXTENSION,proxyPolicy,PROXY_POLICY) +} ASN1_SEQUENCE_END(PROXY_CERT_INFO_EXTENSION) + +IMPLEMENT_ASN1_FUNCTIONS(PROXY_CERT_INFO_EXTENSION) diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_pcons.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_pcons.c new file mode 100644 index 000000000..24f7ff49e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_pcons.c @@ -0,0 +1,91 @@ +/* + * Copyright 2003-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "ext_dat.h" + +static STACK_OF(CONF_VALUE) *i2v_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD + *method, void *bcons, STACK_OF(CONF_VALUE) + *extlist); +static void *v2i_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *values); + +const X509V3_EXT_METHOD v3_policy_constraints = { + NID_policy_constraints, 0, + ASN1_ITEM_ref(POLICY_CONSTRAINTS), + 0, 0, 0, 0, + 0, 0, + i2v_POLICY_CONSTRAINTS, + v2i_POLICY_CONSTRAINTS, + NULL, NULL, + NULL +}; + +ASN1_SEQUENCE(POLICY_CONSTRAINTS) = { + ASN1_IMP_OPT(POLICY_CONSTRAINTS, requireExplicitPolicy, ASN1_INTEGER,0), + ASN1_IMP_OPT(POLICY_CONSTRAINTS, inhibitPolicyMapping, ASN1_INTEGER,1) +} ASN1_SEQUENCE_END(POLICY_CONSTRAINTS) + +IMPLEMENT_ASN1_ALLOC_FUNCTIONS(POLICY_CONSTRAINTS) + +static STACK_OF(CONF_VALUE) *i2v_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD + *method, void *a, STACK_OF(CONF_VALUE) + *extlist) +{ + POLICY_CONSTRAINTS *pcons = a; + X509V3_add_value_int("Require Explicit Policy", + pcons->requireExplicitPolicy, &extlist); + X509V3_add_value_int("Inhibit Policy Mapping", + pcons->inhibitPolicyMapping, &extlist); + return extlist; +} + +static void *v2i_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *values) +{ + POLICY_CONSTRAINTS *pcons = NULL; + CONF_VALUE *val; + int i; + + if ((pcons = POLICY_CONSTRAINTS_new()) == NULL) { + X509V3err(X509V3_F_V2I_POLICY_CONSTRAINTS, ERR_R_MALLOC_FAILURE); + return NULL; + } + for (i = 0; i < sk_CONF_VALUE_num(values); i++) { + val = sk_CONF_VALUE_value(values, i); + if (strcmp(val->name, "requireExplicitPolicy") == 0) { + if (!X509V3_get_value_int(val, &pcons->requireExplicitPolicy)) + goto err; + } else if (strcmp(val->name, "inhibitPolicyMapping") == 0) { + if (!X509V3_get_value_int(val, &pcons->inhibitPolicyMapping)) + goto err; + } else { + X509V3err(X509V3_F_V2I_POLICY_CONSTRAINTS, X509V3_R_INVALID_NAME); + X509V3_conf_err(val); + goto err; + } + } + if (!pcons->inhibitPolicyMapping && !pcons->requireExplicitPolicy) { + X509V3err(X509V3_F_V2I_POLICY_CONSTRAINTS, + X509V3_R_ILLEGAL_EMPTY_EXTENSION); + goto err; + } + + return pcons; + err: + POLICY_CONSTRAINTS_free(pcons); + return NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_pku.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_pku.c new file mode 100644 index 000000000..5a7e7d972 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_pku.c @@ -0,0 +1,52 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include "ext_dat.h" + +static int i2r_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method, + PKEY_USAGE_PERIOD *usage, BIO *out, + int indent); + +const X509V3_EXT_METHOD v3_pkey_usage_period = { + NID_private_key_usage_period, 0, ASN1_ITEM_ref(PKEY_USAGE_PERIOD), + 0, 0, 0, 0, + 0, 0, 0, 0, + (X509V3_EXT_I2R)i2r_PKEY_USAGE_PERIOD, NULL, + NULL +}; + +ASN1_SEQUENCE(PKEY_USAGE_PERIOD) = { + ASN1_IMP_OPT(PKEY_USAGE_PERIOD, notBefore, ASN1_GENERALIZEDTIME, 0), + ASN1_IMP_OPT(PKEY_USAGE_PERIOD, notAfter, ASN1_GENERALIZEDTIME, 1) +} ASN1_SEQUENCE_END(PKEY_USAGE_PERIOD) + +IMPLEMENT_ASN1_FUNCTIONS(PKEY_USAGE_PERIOD) + +static int i2r_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method, + PKEY_USAGE_PERIOD *usage, BIO *out, + int indent) +{ + BIO_printf(out, "%*s", indent, ""); + if (usage->notBefore) { + BIO_write(out, "Not Before: ", 12); + ASN1_GENERALIZEDTIME_print(out, usage->notBefore); + if (usage->notAfter) + BIO_write(out, ", ", 2); + } + if (usage->notAfter) { + BIO_write(out, "Not After: ", 11); + ASN1_GENERALIZEDTIME_print(out, usage->notAfter); + } + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_pmaps.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_pmaps.c new file mode 100644 index 000000000..5b6a2af0f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_pmaps.c @@ -0,0 +1,112 @@ +/* + * Copyright 2003-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include "ext_dat.h" + +static void *v2i_POLICY_MAPPINGS(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); +static STACK_OF(CONF_VALUE) *i2v_POLICY_MAPPINGS(const X509V3_EXT_METHOD + *method, void *pmps, STACK_OF(CONF_VALUE) + *extlist); + +const X509V3_EXT_METHOD v3_policy_mappings = { + NID_policy_mappings, 0, + ASN1_ITEM_ref(POLICY_MAPPINGS), + 0, 0, 0, 0, + 0, 0, + i2v_POLICY_MAPPINGS, + v2i_POLICY_MAPPINGS, + 0, 0, + NULL +}; + +ASN1_SEQUENCE(POLICY_MAPPING) = { + ASN1_SIMPLE(POLICY_MAPPING, issuerDomainPolicy, ASN1_OBJECT), + ASN1_SIMPLE(POLICY_MAPPING, subjectDomainPolicy, ASN1_OBJECT) +} ASN1_SEQUENCE_END(POLICY_MAPPING) + +ASN1_ITEM_TEMPLATE(POLICY_MAPPINGS) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, POLICY_MAPPINGS, + POLICY_MAPPING) +ASN1_ITEM_TEMPLATE_END(POLICY_MAPPINGS) + +IMPLEMENT_ASN1_ALLOC_FUNCTIONS(POLICY_MAPPING) + +static STACK_OF(CONF_VALUE) *i2v_POLICY_MAPPINGS(const X509V3_EXT_METHOD + *method, void *a, STACK_OF(CONF_VALUE) + *ext_list) +{ + POLICY_MAPPINGS *pmaps = a; + POLICY_MAPPING *pmap; + int i; + char obj_tmp1[80]; + char obj_tmp2[80]; + + for (i = 0; i < sk_POLICY_MAPPING_num(pmaps); i++) { + pmap = sk_POLICY_MAPPING_value(pmaps, i); + i2t_ASN1_OBJECT(obj_tmp1, 80, pmap->issuerDomainPolicy); + i2t_ASN1_OBJECT(obj_tmp2, 80, pmap->subjectDomainPolicy); + X509V3_add_value(obj_tmp1, obj_tmp2, &ext_list); + } + return ext_list; +} + +static void *v2i_POLICY_MAPPINGS(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) +{ + POLICY_MAPPING *pmap = NULL; + ASN1_OBJECT *obj1 = NULL, *obj2 = NULL; + CONF_VALUE *val; + POLICY_MAPPINGS *pmaps; + const int num = sk_CONF_VALUE_num(nval); + int i; + + if ((pmaps = sk_POLICY_MAPPING_new_reserve(NULL, num)) == NULL) { + X509V3err(X509V3_F_V2I_POLICY_MAPPINGS, ERR_R_MALLOC_FAILURE); + return NULL; + } + + for (i = 0; i < num; i++) { + val = sk_CONF_VALUE_value(nval, i); + if (!val->value || !val->name) { + X509V3err(X509V3_F_V2I_POLICY_MAPPINGS, + X509V3_R_INVALID_OBJECT_IDENTIFIER); + X509V3_conf_err(val); + goto err; + } + obj1 = OBJ_txt2obj(val->name, 0); + obj2 = OBJ_txt2obj(val->value, 0); + if (!obj1 || !obj2) { + X509V3err(X509V3_F_V2I_POLICY_MAPPINGS, + X509V3_R_INVALID_OBJECT_IDENTIFIER); + X509V3_conf_err(val); + goto err; + } + pmap = POLICY_MAPPING_new(); + if (pmap == NULL) { + X509V3err(X509V3_F_V2I_POLICY_MAPPINGS, ERR_R_MALLOC_FAILURE); + goto err; + } + pmap->issuerDomainPolicy = obj1; + pmap->subjectDomainPolicy = obj2; + obj1 = obj2 = NULL; + sk_POLICY_MAPPING_push(pmaps, pmap); /* no failure as it was reserved */ + } + return pmaps; + err: + ASN1_OBJECT_free(obj1); + ASN1_OBJECT_free(obj2); + sk_POLICY_MAPPING_pop_free(pmaps, POLICY_MAPPING_free); + return NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_prn.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_prn.c new file mode 100644 index 000000000..f384c342a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_prn.c @@ -0,0 +1,210 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* X509 v3 extension utilities */ + +#include +#include "internal/cryptlib.h" +#include +#include + +/* Extension printing routines */ + +static int unknown_ext_print(BIO *out, const unsigned char *ext, int extlen, + unsigned long flag, int indent, int supported); + +/* Print out a name+value stack */ + +void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent, + int ml) +{ + int i; + CONF_VALUE *nval; + if (!val) + return; + if (!ml || !sk_CONF_VALUE_num(val)) { + BIO_printf(out, "%*s", indent, ""); + if (!sk_CONF_VALUE_num(val)) + BIO_puts(out, "\n"); + } + for (i = 0; i < sk_CONF_VALUE_num(val); i++) { + if (ml) + BIO_printf(out, "%*s", indent, ""); + else if (i > 0) + BIO_printf(out, ", "); + nval = sk_CONF_VALUE_value(val, i); + if (!nval->name) + BIO_puts(out, nval->value); + else if (!nval->value) + BIO_puts(out, nval->name); +#ifndef CHARSET_EBCDIC + else + BIO_printf(out, "%s:%s", nval->name, nval->value); +#else + else { + int len; + char *tmp; + len = strlen(nval->value) + 1; + tmp = OPENSSL_malloc(len); + if (tmp != NULL) { + ascii2ebcdic(tmp, nval->value, len); + BIO_printf(out, "%s:%s", nval->name, tmp); + OPENSSL_free(tmp); + } + } +#endif + if (ml) + BIO_puts(out, "\n"); + } +} + +/* Main routine: print out a general extension */ + +int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, + int indent) +{ + void *ext_str = NULL; + char *value = NULL; + ASN1_OCTET_STRING *extoct; + const unsigned char *p; + int extlen; + const X509V3_EXT_METHOD *method; + STACK_OF(CONF_VALUE) *nval = NULL; + int ok = 1; + + extoct = X509_EXTENSION_get_data(ext); + p = ASN1_STRING_get0_data(extoct); + extlen = ASN1_STRING_length(extoct); + + if ((method = X509V3_EXT_get(ext)) == NULL) + return unknown_ext_print(out, p, extlen, flag, indent, 0); + if (method->it) + ext_str = ASN1_item_d2i(NULL, &p, extlen, ASN1_ITEM_ptr(method->it)); + else + ext_str = method->d2i(NULL, &p, extlen); + + if (!ext_str) + return unknown_ext_print(out, p, extlen, flag, indent, 1); + + if (method->i2s) { + if ((value = method->i2s(method, ext_str)) == NULL) { + ok = 0; + goto err; + } +#ifndef CHARSET_EBCDIC + BIO_printf(out, "%*s%s", indent, "", value); +#else + { + int len; + char *tmp; + len = strlen(value) + 1; + tmp = OPENSSL_malloc(len); + if (tmp != NULL) { + ascii2ebcdic(tmp, value, len); + BIO_printf(out, "%*s%s", indent, "", tmp); + OPENSSL_free(tmp); + } + } +#endif + } else if (method->i2v) { + if ((nval = method->i2v(method, ext_str, NULL)) == NULL) { + ok = 0; + goto err; + } + X509V3_EXT_val_prn(out, nval, indent, + method->ext_flags & X509V3_EXT_MULTILINE); + } else if (method->i2r) { + if (!method->i2r(method, ext_str, out, indent)) + ok = 0; + } else + ok = 0; + + err: + sk_CONF_VALUE_pop_free(nval, X509V3_conf_free); + OPENSSL_free(value); + if (method->it) + ASN1_item_free(ext_str, ASN1_ITEM_ptr(method->it)); + else + method->ext_free(ext_str); + return ok; +} + +int X509V3_extensions_print(BIO *bp, const char *title, + const STACK_OF(X509_EXTENSION) *exts, + unsigned long flag, int indent) +{ + int i, j; + + if (sk_X509_EXTENSION_num(exts) <= 0) + return 1; + + if (title) { + BIO_printf(bp, "%*s%s:\n", indent, "", title); + indent += 4; + } + + for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { + ASN1_OBJECT *obj; + X509_EXTENSION *ex; + ex = sk_X509_EXTENSION_value(exts, i); + if (indent && BIO_printf(bp, "%*s", indent, "") <= 0) + return 0; + obj = X509_EXTENSION_get_object(ex); + i2a_ASN1_OBJECT(bp, obj); + j = X509_EXTENSION_get_critical(ex); + if (BIO_printf(bp, ": %s\n", j ? "critical" : "") <= 0) + return 0; + if (!X509V3_EXT_print(bp, ex, flag, indent + 4)) { + BIO_printf(bp, "%*s", indent + 4, ""); + ASN1_STRING_print(bp, X509_EXTENSION_get_data(ex)); + } + if (BIO_write(bp, "\n", 1) <= 0) + return 0; + } + return 1; +} + +static int unknown_ext_print(BIO *out, const unsigned char *ext, int extlen, + unsigned long flag, int indent, int supported) +{ + switch (flag & X509V3_EXT_UNKNOWN_MASK) { + + case X509V3_EXT_DEFAULT: + return 0; + + case X509V3_EXT_ERROR_UNKNOWN: + if (supported) + BIO_printf(out, "%*s", indent, ""); + else + BIO_printf(out, "%*s", indent, ""); + return 1; + + case X509V3_EXT_PARSE_UNKNOWN: + return ASN1_parse_dump(out, ext, extlen, indent, -1); + case X509V3_EXT_DUMP_UNKNOWN: + return BIO_dump_indent(out, (const char *)ext, extlen, indent); + + default: + return 1; + } +} + +#ifndef OPENSSL_NO_STDIO +int X509V3_EXT_print_fp(FILE *fp, X509_EXTENSION *ext, int flag, int indent) +{ + BIO *bio_tmp; + int ret; + + if ((bio_tmp = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) + return 0; + ret = X509V3_EXT_print(bio_tmp, ext, flag, indent); + BIO_free(bio_tmp); + return ret; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_purp.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_purp.c new file mode 100644 index 000000000..70b0397d9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_purp.c @@ -0,0 +1,890 @@ +/* + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include "internal/numbers.h" +#include +#include +#include "internal/x509_int.h" +#include "internal/tsan_assist.h" + +static void x509v3_cache_extensions(X509 *x); + +static int check_ssl_ca(const X509 *x); +static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, + int ca); +static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, + int ca); +static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, + int ca); +static int purpose_smime(const X509 *x, int ca); +static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, + int ca); +static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, + int ca); +static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, + int ca); +static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x, + int ca); +static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca); +static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca); + +static int xp_cmp(const X509_PURPOSE *const *a, const X509_PURPOSE *const *b); +static void xptable_free(X509_PURPOSE *p); + +static X509_PURPOSE xstandard[] = { + {X509_PURPOSE_SSL_CLIENT, X509_TRUST_SSL_CLIENT, 0, + check_purpose_ssl_client, "SSL client", "sslclient", NULL}, + {X509_PURPOSE_SSL_SERVER, X509_TRUST_SSL_SERVER, 0, + check_purpose_ssl_server, "SSL server", "sslserver", NULL}, + {X509_PURPOSE_NS_SSL_SERVER, X509_TRUST_SSL_SERVER, 0, + check_purpose_ns_ssl_server, "Netscape SSL server", "nssslserver", NULL}, + {X509_PURPOSE_SMIME_SIGN, X509_TRUST_EMAIL, 0, check_purpose_smime_sign, + "S/MIME signing", "smimesign", NULL}, + {X509_PURPOSE_SMIME_ENCRYPT, X509_TRUST_EMAIL, 0, + check_purpose_smime_encrypt, "S/MIME encryption", "smimeencrypt", NULL}, + {X509_PURPOSE_CRL_SIGN, X509_TRUST_COMPAT, 0, check_purpose_crl_sign, + "CRL signing", "crlsign", NULL}, + {X509_PURPOSE_ANY, X509_TRUST_DEFAULT, 0, no_check, "Any Purpose", "any", + NULL}, + {X509_PURPOSE_OCSP_HELPER, X509_TRUST_COMPAT, 0, ocsp_helper, + "OCSP helper", "ocsphelper", NULL}, + {X509_PURPOSE_TIMESTAMP_SIGN, X509_TRUST_TSA, 0, + check_purpose_timestamp_sign, "Time Stamp signing", "timestampsign", + NULL}, +}; + +#define X509_PURPOSE_COUNT OSSL_NELEM(xstandard) + +static STACK_OF(X509_PURPOSE) *xptable = NULL; + +static int xp_cmp(const X509_PURPOSE *const *a, const X509_PURPOSE *const *b) +{ + return (*a)->purpose - (*b)->purpose; +} + +/* + * As much as I'd like to make X509_check_purpose use a "const" X509* I + * really can't because it does recalculate hashes and do other non-const + * things. + */ +int X509_check_purpose(X509 *x, int id, int ca) +{ + int idx; + const X509_PURPOSE *pt; + + x509v3_cache_extensions(x); + + /* Return if side-effect only call */ + if (id == -1) + return 1; + idx = X509_PURPOSE_get_by_id(id); + if (idx == -1) + return -1; + pt = X509_PURPOSE_get0(idx); + return pt->check_purpose(pt, x, ca); +} + +int X509_PURPOSE_set(int *p, int purpose) +{ + if (X509_PURPOSE_get_by_id(purpose) == -1) { + X509V3err(X509V3_F_X509_PURPOSE_SET, X509V3_R_INVALID_PURPOSE); + return 0; + } + *p = purpose; + return 1; +} + +int X509_PURPOSE_get_count(void) +{ + if (!xptable) + return X509_PURPOSE_COUNT; + return sk_X509_PURPOSE_num(xptable) + X509_PURPOSE_COUNT; +} + +X509_PURPOSE *X509_PURPOSE_get0(int idx) +{ + if (idx < 0) + return NULL; + if (idx < (int)X509_PURPOSE_COUNT) + return xstandard + idx; + return sk_X509_PURPOSE_value(xptable, idx - X509_PURPOSE_COUNT); +} + +int X509_PURPOSE_get_by_sname(const char *sname) +{ + int i; + X509_PURPOSE *xptmp; + for (i = 0; i < X509_PURPOSE_get_count(); i++) { + xptmp = X509_PURPOSE_get0(i); + if (strcmp(xptmp->sname, sname) == 0) + return i; + } + return -1; +} + +int X509_PURPOSE_get_by_id(int purpose) +{ + X509_PURPOSE tmp; + int idx; + + if ((purpose >= X509_PURPOSE_MIN) && (purpose <= X509_PURPOSE_MAX)) + return purpose - X509_PURPOSE_MIN; + if (xptable == NULL) + return -1; + tmp.purpose = purpose; + idx = sk_X509_PURPOSE_find(xptable, &tmp); + if (idx < 0) + return -1; + return idx + X509_PURPOSE_COUNT; +} + +int X509_PURPOSE_add(int id, int trust, int flags, + int (*ck) (const X509_PURPOSE *, const X509 *, int), + const char *name, const char *sname, void *arg) +{ + int idx; + X509_PURPOSE *ptmp; + /* + * This is set according to what we change: application can't set it + */ + flags &= ~X509_PURPOSE_DYNAMIC; + /* This will always be set for application modified trust entries */ + flags |= X509_PURPOSE_DYNAMIC_NAME; + /* Get existing entry if any */ + idx = X509_PURPOSE_get_by_id(id); + /* Need a new entry */ + if (idx == -1) { + if ((ptmp = OPENSSL_malloc(sizeof(*ptmp))) == NULL) { + X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE); + return 0; + } + ptmp->flags = X509_PURPOSE_DYNAMIC; + } else + ptmp = X509_PURPOSE_get0(idx); + + /* OPENSSL_free existing name if dynamic */ + if (ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) { + OPENSSL_free(ptmp->name); + OPENSSL_free(ptmp->sname); + } + /* dup supplied name */ + ptmp->name = OPENSSL_strdup(name); + ptmp->sname = OPENSSL_strdup(sname); + if (!ptmp->name || !ptmp->sname) { + X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE); + goto err; + } + /* Keep the dynamic flag of existing entry */ + ptmp->flags &= X509_PURPOSE_DYNAMIC; + /* Set all other flags */ + ptmp->flags |= flags; + + ptmp->purpose = id; + ptmp->trust = trust; + ptmp->check_purpose = ck; + ptmp->usr_data = arg; + + /* If its a new entry manage the dynamic table */ + if (idx == -1) { + if (xptable == NULL + && (xptable = sk_X509_PURPOSE_new(xp_cmp)) == NULL) { + X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!sk_X509_PURPOSE_push(xptable, ptmp)) { + X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE); + goto err; + } + } + return 1; + err: + if (idx == -1) { + OPENSSL_free(ptmp->name); + OPENSSL_free(ptmp->sname); + OPENSSL_free(ptmp); + } + return 0; +} + +static void xptable_free(X509_PURPOSE *p) +{ + if (!p) + return; + if (p->flags & X509_PURPOSE_DYNAMIC) { + if (p->flags & X509_PURPOSE_DYNAMIC_NAME) { + OPENSSL_free(p->name); + OPENSSL_free(p->sname); + } + OPENSSL_free(p); + } +} + +void X509_PURPOSE_cleanup(void) +{ + sk_X509_PURPOSE_pop_free(xptable, xptable_free); + xptable = NULL; +} + +int X509_PURPOSE_get_id(const X509_PURPOSE *xp) +{ + return xp->purpose; +} + +char *X509_PURPOSE_get0_name(const X509_PURPOSE *xp) +{ + return xp->name; +} + +char *X509_PURPOSE_get0_sname(const X509_PURPOSE *xp) +{ + return xp->sname; +} + +int X509_PURPOSE_get_trust(const X509_PURPOSE *xp) +{ + return xp->trust; +} + +static int nid_cmp(const int *a, const int *b) +{ + return *a - *b; +} + +DECLARE_OBJ_BSEARCH_CMP_FN(int, int, nid); +IMPLEMENT_OBJ_BSEARCH_CMP_FN(int, int, nid); + +int X509_supported_extension(X509_EXTENSION *ex) +{ + /* + * This table is a list of the NIDs of supported extensions: that is + * those which are used by the verify process. If an extension is + * critical and doesn't appear in this list then the verify process will + * normally reject the certificate. The list must be kept in numerical + * order because it will be searched using bsearch. + */ + + static const int supported_nids[] = { + NID_netscape_cert_type, /* 71 */ + NID_key_usage, /* 83 */ + NID_subject_alt_name, /* 85 */ + NID_basic_constraints, /* 87 */ + NID_certificate_policies, /* 89 */ + NID_crl_distribution_points, /* 103 */ + NID_ext_key_usage, /* 126 */ +#ifndef OPENSSL_NO_RFC3779 + NID_sbgp_ipAddrBlock, /* 290 */ + NID_sbgp_autonomousSysNum, /* 291 */ +#endif + NID_policy_constraints, /* 401 */ + NID_proxyCertInfo, /* 663 */ + NID_name_constraints, /* 666 */ + NID_policy_mappings, /* 747 */ + NID_inhibit_any_policy /* 748 */ + }; + + int ex_nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex)); + + if (ex_nid == NID_undef) + return 0; + + if (OBJ_bsearch_nid(&ex_nid, supported_nids, OSSL_NELEM(supported_nids))) + return 1; + return 0; +} + +static void setup_dp(X509 *x, DIST_POINT *dp) +{ + X509_NAME *iname = NULL; + int i; + if (dp->reasons) { + if (dp->reasons->length > 0) + dp->dp_reasons = dp->reasons->data[0]; + if (dp->reasons->length > 1) + dp->dp_reasons |= (dp->reasons->data[1] << 8); + dp->dp_reasons &= CRLDP_ALL_REASONS; + } else + dp->dp_reasons = CRLDP_ALL_REASONS; + if (!dp->distpoint || (dp->distpoint->type != 1)) + return; + for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++) { + GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i); + if (gen->type == GEN_DIRNAME) { + iname = gen->d.directoryName; + break; + } + } + if (!iname) + iname = X509_get_issuer_name(x); + + DIST_POINT_set_dpname(dp->distpoint, iname); + +} + +static void setup_crldp(X509 *x) +{ + int i; + x->crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL); + for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++) + setup_dp(x, sk_DIST_POINT_value(x->crldp, i)); +} + +#define V1_ROOT (EXFLAG_V1|EXFLAG_SS) +#define ku_reject(x, usage) \ + (((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage))) +#define xku_reject(x, usage) \ + (((x)->ex_flags & EXFLAG_XKUSAGE) && !((x)->ex_xkusage & (usage))) +#define ns_reject(x, usage) \ + (((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage))) + +static void x509v3_cache_extensions(X509 *x) +{ + BASIC_CONSTRAINTS *bs; + PROXY_CERT_INFO_EXTENSION *pci; + ASN1_BIT_STRING *usage; + ASN1_BIT_STRING *ns; + EXTENDED_KEY_USAGE *extusage; + X509_EXTENSION *ex; + int i; + +#ifdef tsan_ld_acq + /* fast lock-free check, see end of the function for details. */ + if (tsan_ld_acq((TSAN_QUALIFIER int *)&x->ex_cached)) + return; +#endif + + CRYPTO_THREAD_write_lock(x->lock); + if (x->ex_flags & EXFLAG_SET) { + CRYPTO_THREAD_unlock(x->lock); + return; + } + + X509_digest(x, EVP_sha1(), x->sha1_hash, NULL); + /* V1 should mean no extensions ... */ + if (!X509_get_version(x)) + x->ex_flags |= EXFLAG_V1; + /* Handle basic constraints */ + if ((bs = X509_get_ext_d2i(x, NID_basic_constraints, NULL, NULL))) { + if (bs->ca) + x->ex_flags |= EXFLAG_CA; + if (bs->pathlen) { + if ((bs->pathlen->type == V_ASN1_NEG_INTEGER) + || !bs->ca) { + x->ex_flags |= EXFLAG_INVALID; + x->ex_pathlen = 0; + } else + x->ex_pathlen = ASN1_INTEGER_get(bs->pathlen); + } else + x->ex_pathlen = -1; + BASIC_CONSTRAINTS_free(bs); + x->ex_flags |= EXFLAG_BCONS; + } + /* Handle proxy certificates */ + if ((pci = X509_get_ext_d2i(x, NID_proxyCertInfo, NULL, NULL))) { + if (x->ex_flags & EXFLAG_CA + || X509_get_ext_by_NID(x, NID_subject_alt_name, -1) >= 0 + || X509_get_ext_by_NID(x, NID_issuer_alt_name, -1) >= 0) { + x->ex_flags |= EXFLAG_INVALID; + } + if (pci->pcPathLengthConstraint) { + x->ex_pcpathlen = ASN1_INTEGER_get(pci->pcPathLengthConstraint); + } else + x->ex_pcpathlen = -1; + PROXY_CERT_INFO_EXTENSION_free(pci); + x->ex_flags |= EXFLAG_PROXY; + } + /* Handle key usage */ + if ((usage = X509_get_ext_d2i(x, NID_key_usage, NULL, NULL))) { + if (usage->length > 0) { + x->ex_kusage = usage->data[0]; + if (usage->length > 1) + x->ex_kusage |= usage->data[1] << 8; + } else + x->ex_kusage = 0; + x->ex_flags |= EXFLAG_KUSAGE; + ASN1_BIT_STRING_free(usage); + } + x->ex_xkusage = 0; + if ((extusage = X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL))) { + x->ex_flags |= EXFLAG_XKUSAGE; + for (i = 0; i < sk_ASN1_OBJECT_num(extusage); i++) { + switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(extusage, i))) { + case NID_server_auth: + x->ex_xkusage |= XKU_SSL_SERVER; + break; + + case NID_client_auth: + x->ex_xkusage |= XKU_SSL_CLIENT; + break; + + case NID_email_protect: + x->ex_xkusage |= XKU_SMIME; + break; + + case NID_code_sign: + x->ex_xkusage |= XKU_CODE_SIGN; + break; + + case NID_ms_sgc: + case NID_ns_sgc: + x->ex_xkusage |= XKU_SGC; + break; + + case NID_OCSP_sign: + x->ex_xkusage |= XKU_OCSP_SIGN; + break; + + case NID_time_stamp: + x->ex_xkusage |= XKU_TIMESTAMP; + break; + + case NID_dvcs: + x->ex_xkusage |= XKU_DVCS; + break; + + case NID_anyExtendedKeyUsage: + x->ex_xkusage |= XKU_ANYEKU; + break; + } + } + sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free); + } + + if ((ns = X509_get_ext_d2i(x, NID_netscape_cert_type, NULL, NULL))) { + if (ns->length > 0) + x->ex_nscert = ns->data[0]; + else + x->ex_nscert = 0; + x->ex_flags |= EXFLAG_NSCERT; + ASN1_BIT_STRING_free(ns); + } + x->skid = X509_get_ext_d2i(x, NID_subject_key_identifier, NULL, NULL); + x->akid = X509_get_ext_d2i(x, NID_authority_key_identifier, NULL, NULL); + /* Does subject name match issuer ? */ + if (!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x))) { + x->ex_flags |= EXFLAG_SI; + /* If SKID matches AKID also indicate self signed */ + if (X509_check_akid(x, x->akid) == X509_V_OK && + !ku_reject(x, KU_KEY_CERT_SIGN)) + x->ex_flags |= EXFLAG_SS; + } + x->altname = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); + x->nc = X509_get_ext_d2i(x, NID_name_constraints, &i, NULL); + if (!x->nc && (i != -1)) + x->ex_flags |= EXFLAG_INVALID; + setup_crldp(x); + +#ifndef OPENSSL_NO_RFC3779 + x->rfc3779_addr = X509_get_ext_d2i(x, NID_sbgp_ipAddrBlock, NULL, NULL); + x->rfc3779_asid = X509_get_ext_d2i(x, NID_sbgp_autonomousSysNum, + NULL, NULL); +#endif + for (i = 0; i < X509_get_ext_count(x); i++) { + ex = X509_get_ext(x, i); + if (OBJ_obj2nid(X509_EXTENSION_get_object(ex)) + == NID_freshest_crl) + x->ex_flags |= EXFLAG_FRESHEST; + if (!X509_EXTENSION_get_critical(ex)) + continue; + if (!X509_supported_extension(ex)) { + x->ex_flags |= EXFLAG_CRITICAL; + break; + } + } + x509_init_sig_info(x); + x->ex_flags |= EXFLAG_SET; +#ifdef tsan_st_rel + tsan_st_rel((TSAN_QUALIFIER int *)&x->ex_cached, 1); + /* + * Above store triggers fast lock-free check in the beginning of the + * function. But one has to ensure that the structure is "stable", i.e. + * all stores are visible on all processors. Hence the release fence. + */ +#endif + CRYPTO_THREAD_unlock(x->lock); +} + +/*- + * CA checks common to all purposes + * return codes: + * 0 not a CA + * 1 is a CA + * 2 basicConstraints absent so "maybe" a CA + * 3 basicConstraints absent but self signed V1. + * 4 basicConstraints absent but keyUsage present and keyCertSign asserted. + */ + +static int check_ca(const X509 *x) +{ + /* keyUsage if present should allow cert signing */ + if (ku_reject(x, KU_KEY_CERT_SIGN)) + return 0; + if (x->ex_flags & EXFLAG_BCONS) { + if (x->ex_flags & EXFLAG_CA) + return 1; + /* If basicConstraints says not a CA then say so */ + else + return 0; + } else { + /* we support V1 roots for... uh, I don't really know why. */ + if ((x->ex_flags & V1_ROOT) == V1_ROOT) + return 3; + /* + * If key usage present it must have certSign so tolerate it + */ + else if (x->ex_flags & EXFLAG_KUSAGE) + return 4; + /* Older certificates could have Netscape-specific CA types */ + else if (x->ex_flags & EXFLAG_NSCERT && x->ex_nscert & NS_ANY_CA) + return 5; + /* can this still be regarded a CA certificate? I doubt it */ + return 0; + } +} + +void X509_set_proxy_flag(X509 *x) +{ + x->ex_flags |= EXFLAG_PROXY; +} + +void X509_set_proxy_pathlen(X509 *x, long l) +{ + x->ex_pcpathlen = l; +} + +int X509_check_ca(X509 *x) +{ + x509v3_cache_extensions(x); + + return check_ca(x); +} + +/* Check SSL CA: common checks for SSL client and server */ +static int check_ssl_ca(const X509 *x) +{ + int ca_ret; + ca_ret = check_ca(x); + if (!ca_ret) + return 0; + /* check nsCertType if present */ + if (ca_ret != 5 || x->ex_nscert & NS_SSL_CA) + return ca_ret; + else + return 0; +} + +static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, + int ca) +{ + if (xku_reject(x, XKU_SSL_CLIENT)) + return 0; + if (ca) + return check_ssl_ca(x); + /* We need to do digital signatures or key agreement */ + if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT)) + return 0; + /* nsCertType if present should allow SSL client use */ + if (ns_reject(x, NS_SSL_CLIENT)) + return 0; + return 1; +} + +/* + * Key usage needed for TLS/SSL server: digital signature, encipherment or + * key agreement. The ssl code can check this more thoroughly for individual + * key types. + */ +#define KU_TLS \ + KU_DIGITAL_SIGNATURE|KU_KEY_ENCIPHERMENT|KU_KEY_AGREEMENT + +static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, + int ca) +{ + if (xku_reject(x, XKU_SSL_SERVER | XKU_SGC)) + return 0; + if (ca) + return check_ssl_ca(x); + + if (ns_reject(x, NS_SSL_SERVER)) + return 0; + if (ku_reject(x, KU_TLS)) + return 0; + + return 1; + +} + +static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, + int ca) +{ + int ret; + ret = check_purpose_ssl_server(xp, x, ca); + if (!ret || ca) + return ret; + /* We need to encipher or Netscape complains */ + if (ku_reject(x, KU_KEY_ENCIPHERMENT)) + return 0; + return ret; +} + +/* common S/MIME checks */ +static int purpose_smime(const X509 *x, int ca) +{ + if (xku_reject(x, XKU_SMIME)) + return 0; + if (ca) { + int ca_ret; + ca_ret = check_ca(x); + if (!ca_ret) + return 0; + /* check nsCertType if present */ + if (ca_ret != 5 || x->ex_nscert & NS_SMIME_CA) + return ca_ret; + else + return 0; + } + if (x->ex_flags & EXFLAG_NSCERT) { + if (x->ex_nscert & NS_SMIME) + return 1; + /* Workaround for some buggy certificates */ + if (x->ex_nscert & NS_SSL_CLIENT) + return 2; + return 0; + } + return 1; +} + +static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, + int ca) +{ + int ret; + ret = purpose_smime(x, ca); + if (!ret || ca) + return ret; + if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_NON_REPUDIATION)) + return 0; + return ret; +} + +static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, + int ca) +{ + int ret; + ret = purpose_smime(x, ca); + if (!ret || ca) + return ret; + if (ku_reject(x, KU_KEY_ENCIPHERMENT)) + return 0; + return ret; +} + +static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, + int ca) +{ + if (ca) { + int ca_ret; + if ((ca_ret = check_ca(x)) != 2) + return ca_ret; + else + return 0; + } + if (ku_reject(x, KU_CRL_SIGN)) + return 0; + return 1; +} + +/* + * OCSP helper: this is *not* a full OCSP check. It just checks that each CA + * is valid. Additional checks must be made on the chain. + */ + +static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca) +{ + /* + * Must be a valid CA. Should we really support the "I don't know" value + * (2)? + */ + if (ca) + return check_ca(x); + /* leaf certificate is checked in OCSP_verify() */ + return 1; +} + +static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x, + int ca) +{ + int i_ext; + + /* If ca is true we must return if this is a valid CA certificate. */ + if (ca) + return check_ca(x); + + /* + * Check the optional key usage field: + * if Key Usage is present, it must be one of digitalSignature + * and/or nonRepudiation (other values are not consistent and shall + * be rejected). + */ + if ((x->ex_flags & EXFLAG_KUSAGE) + && ((x->ex_kusage & ~(KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)) || + !(x->ex_kusage & (KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)))) + return 0; + + /* Only time stamp key usage is permitted and it's required. */ + if (!(x->ex_flags & EXFLAG_XKUSAGE) || x->ex_xkusage != XKU_TIMESTAMP) + return 0; + + /* Extended Key Usage MUST be critical */ + i_ext = X509_get_ext_by_NID(x, NID_ext_key_usage, -1); + if (i_ext >= 0) { + X509_EXTENSION *ext = X509_get_ext((X509 *)x, i_ext); + if (!X509_EXTENSION_get_critical(ext)) + return 0; + } + + return 1; +} + +static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca) +{ + return 1; +} + +/*- + * Various checks to see if one certificate issued the second. + * This can be used to prune a set of possible issuer certificates + * which have been looked up using some simple method such as by + * subject name. + * These are: + * 1. Check issuer_name(subject) == subject_name(issuer) + * 2. If akid(subject) exists check it matches issuer + * 3. If key_usage(issuer) exists check it supports certificate signing + * returns 0 for OK, positive for reason for mismatch, reasons match + * codes for X509_verify_cert() + */ + +int X509_check_issued(X509 *issuer, X509 *subject) +{ + if (X509_NAME_cmp(X509_get_subject_name(issuer), + X509_get_issuer_name(subject))) + return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; + + x509v3_cache_extensions(issuer); + x509v3_cache_extensions(subject); + + if (subject->akid) { + int ret = X509_check_akid(issuer, subject->akid); + if (ret != X509_V_OK) + return ret; + } + + if (subject->ex_flags & EXFLAG_PROXY) { + if (ku_reject(issuer, KU_DIGITAL_SIGNATURE)) + return X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE; + } else if (ku_reject(issuer, KU_KEY_CERT_SIGN)) + return X509_V_ERR_KEYUSAGE_NO_CERTSIGN; + return X509_V_OK; +} + +int X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid) +{ + + if (!akid) + return X509_V_OK; + + /* Check key ids (if present) */ + if (akid->keyid && issuer->skid && + ASN1_OCTET_STRING_cmp(akid->keyid, issuer->skid)) + return X509_V_ERR_AKID_SKID_MISMATCH; + /* Check serial number */ + if (akid->serial && + ASN1_INTEGER_cmp(X509_get_serialNumber(issuer), akid->serial)) + return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH; + /* Check issuer name */ + if (akid->issuer) { + /* + * Ugh, for some peculiar reason AKID includes SEQUENCE OF + * GeneralName. So look for a DirName. There may be more than one but + * we only take any notice of the first. + */ + GENERAL_NAMES *gens; + GENERAL_NAME *gen; + X509_NAME *nm = NULL; + int i; + gens = akid->issuer; + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { + gen = sk_GENERAL_NAME_value(gens, i); + if (gen->type == GEN_DIRNAME) { + nm = gen->d.dirn; + break; + } + } + if (nm && X509_NAME_cmp(nm, X509_get_issuer_name(issuer))) + return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH; + } + return X509_V_OK; +} + +uint32_t X509_get_extension_flags(X509 *x) +{ + /* Call for side-effect of computing hash and caching extensions */ + X509_check_purpose(x, -1, -1); + return x->ex_flags; +} + +uint32_t X509_get_key_usage(X509 *x) +{ + /* Call for side-effect of computing hash and caching extensions */ + X509_check_purpose(x, -1, -1); + if (x->ex_flags & EXFLAG_KUSAGE) + return x->ex_kusage; + return UINT32_MAX; +} + +uint32_t X509_get_extended_key_usage(X509 *x) +{ + /* Call for side-effect of computing hash and caching extensions */ + X509_check_purpose(x, -1, -1); + if (x->ex_flags & EXFLAG_XKUSAGE) + return x->ex_xkusage; + return UINT32_MAX; +} + +const ASN1_OCTET_STRING *X509_get0_subject_key_id(X509 *x) +{ + /* Call for side-effect of computing hash and caching extensions */ + X509_check_purpose(x, -1, -1); + return x->skid; +} + +const ASN1_OCTET_STRING *X509_get0_authority_key_id(X509 *x) +{ + /* Call for side-effect of computing hash and caching extensions */ + X509_check_purpose(x, -1, -1); + return (x->akid != NULL ? x->akid->keyid : NULL); +} + +long X509_get_pathlen(X509 *x) +{ + /* Called for side effect of caching extensions */ + if (X509_check_purpose(x, -1, -1) != 1 + || (x->ex_flags & EXFLAG_BCONS) == 0) + return -1; + return x->ex_pathlen; +} + +long X509_get_proxy_pathlen(X509 *x) +{ + /* Called for side effect of caching extensions */ + if (X509_check_purpose(x, -1, -1) != 1 + || (x->ex_flags & EXFLAG_PROXY) == 0) + return -1; + return x->ex_pcpathlen; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_skey.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_skey.c new file mode 100644 index 000000000..749f51b2f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_skey.c @@ -0,0 +1,106 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include "internal/x509_int.h" +#include "ext_dat.h" + +static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, char *str); +const X509V3_EXT_METHOD v3_skey_id = { + NID_subject_key_identifier, 0, ASN1_ITEM_ref(ASN1_OCTET_STRING), + 0, 0, 0, 0, + (X509V3_EXT_I2S)i2s_ASN1_OCTET_STRING, + (X509V3_EXT_S2I)s2i_skey_id, + 0, 0, 0, 0, + NULL +}; + +char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, + const ASN1_OCTET_STRING *oct) +{ + return OPENSSL_buf2hexstr(oct->data, oct->length); +} + +ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, const char *str) +{ + ASN1_OCTET_STRING *oct; + long length; + + if ((oct = ASN1_OCTET_STRING_new()) == NULL) { + X509V3err(X509V3_F_S2I_ASN1_OCTET_STRING, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if ((oct->data = OPENSSL_hexstr2buf(str, &length)) == NULL) { + ASN1_OCTET_STRING_free(oct); + return NULL; + } + + oct->length = length; + + return oct; + +} + +static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, char *str) +{ + ASN1_OCTET_STRING *oct; + X509_PUBKEY *pubkey; + const unsigned char *pk; + int pklen; + unsigned char pkey_dig[EVP_MAX_MD_SIZE]; + unsigned int diglen; + + if (strcmp(str, "hash")) + return s2i_ASN1_OCTET_STRING(method, ctx, str); + + if ((oct = ASN1_OCTET_STRING_new()) == NULL) { + X509V3err(X509V3_F_S2I_SKEY_ID, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (ctx && (ctx->flags == CTX_TEST)) + return oct; + + if (!ctx || (!ctx->subject_req && !ctx->subject_cert)) { + X509V3err(X509V3_F_S2I_SKEY_ID, X509V3_R_NO_PUBLIC_KEY); + goto err; + } + + if (ctx->subject_req) + pubkey = ctx->subject_req->req_info.pubkey; + else + pubkey = ctx->subject_cert->cert_info.key; + + if (pubkey == NULL) { + X509V3err(X509V3_F_S2I_SKEY_ID, X509V3_R_NO_PUBLIC_KEY); + goto err; + } + + X509_PUBKEY_get0_param(NULL, &pk, &pklen, NULL, pubkey); + + if (!EVP_Digest(pk, pklen, pkey_dig, &diglen, EVP_sha1(), NULL)) + goto err; + + if (!ASN1_OCTET_STRING_set(oct, pkey_dig, diglen)) { + X509V3err(X509V3_F_S2I_SKEY_ID, ERR_R_MALLOC_FAILURE); + goto err; + } + + return oct; + + err: + ASN1_OCTET_STRING_free(oct); + return NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_sxnet.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_sxnet.c new file mode 100644 index 000000000..89cda01be --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_sxnet.c @@ -0,0 +1,226 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "ext_dat.h" + +/* Support for Thawte strong extranet extension */ + +#define SXNET_TEST + +static int sxnet_i2r(X509V3_EXT_METHOD *method, SXNET *sx, BIO *out, + int indent); +#ifdef SXNET_TEST +static SXNET *sxnet_v2i(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval); +#endif +const X509V3_EXT_METHOD v3_sxnet = { + NID_sxnet, X509V3_EXT_MULTILINE, ASN1_ITEM_ref(SXNET), + 0, 0, 0, 0, + 0, 0, + 0, +#ifdef SXNET_TEST + (X509V3_EXT_V2I)sxnet_v2i, +#else + 0, +#endif + (X509V3_EXT_I2R)sxnet_i2r, + 0, + NULL +}; + +ASN1_SEQUENCE(SXNETID) = { + ASN1_SIMPLE(SXNETID, zone, ASN1_INTEGER), + ASN1_SIMPLE(SXNETID, user, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(SXNETID) + +IMPLEMENT_ASN1_FUNCTIONS(SXNETID) + +ASN1_SEQUENCE(SXNET) = { + ASN1_SIMPLE(SXNET, version, ASN1_INTEGER), + ASN1_SEQUENCE_OF(SXNET, ids, SXNETID) +} ASN1_SEQUENCE_END(SXNET) + +IMPLEMENT_ASN1_FUNCTIONS(SXNET) + +static int sxnet_i2r(X509V3_EXT_METHOD *method, SXNET *sx, BIO *out, + int indent) +{ + long v; + char *tmp; + SXNETID *id; + int i; + v = ASN1_INTEGER_get(sx->version); + BIO_printf(out, "%*sVersion: %ld (0x%lX)", indent, "", v + 1, v); + for (i = 0; i < sk_SXNETID_num(sx->ids); i++) { + id = sk_SXNETID_value(sx->ids, i); + tmp = i2s_ASN1_INTEGER(NULL, id->zone); + BIO_printf(out, "\n%*sZone: %s, User: ", indent, "", tmp); + OPENSSL_free(tmp); + ASN1_STRING_print(out, id->user); + } + return 1; +} + +#ifdef SXNET_TEST + +/* + * NBB: this is used for testing only. It should *not* be used for anything + * else because it will just take static IDs from the configuration file and + * they should really be separate values for each user. + */ + +static SXNET *sxnet_v2i(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval) +{ + CONF_VALUE *cnf; + SXNET *sx = NULL; + int i; + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + cnf = sk_CONF_VALUE_value(nval, i); + if (!SXNET_add_id_asc(&sx, cnf->name, cnf->value, -1)) + return NULL; + } + return sx; +} + +#endif + +/* Strong Extranet utility functions */ + +/* Add an id given the zone as an ASCII number */ + +int SXNET_add_id_asc(SXNET **psx, const char *zone, const char *user, int userlen) +{ + ASN1_INTEGER *izone; + + if ((izone = s2i_ASN1_INTEGER(NULL, zone)) == NULL) { + X509V3err(X509V3_F_SXNET_ADD_ID_ASC, X509V3_R_ERROR_CONVERTING_ZONE); + return 0; + } + return SXNET_add_id_INTEGER(psx, izone, user, userlen); +} + +/* Add an id given the zone as an unsigned long */ + +int SXNET_add_id_ulong(SXNET **psx, unsigned long lzone, const char *user, + int userlen) +{ + ASN1_INTEGER *izone; + + if ((izone = ASN1_INTEGER_new()) == NULL + || !ASN1_INTEGER_set(izone, lzone)) { + X509V3err(X509V3_F_SXNET_ADD_ID_ULONG, ERR_R_MALLOC_FAILURE); + ASN1_INTEGER_free(izone); + return 0; + } + return SXNET_add_id_INTEGER(psx, izone, user, userlen); + +} + +/* + * Add an id given the zone as an ASN1_INTEGER. Note this version uses the + * passed integer and doesn't make a copy so don't free it up afterwards. + */ + +int SXNET_add_id_INTEGER(SXNET **psx, ASN1_INTEGER *zone, const char *user, + int userlen) +{ + SXNET *sx = NULL; + SXNETID *id = NULL; + if (!psx || !zone || !user) { + X509V3err(X509V3_F_SXNET_ADD_ID_INTEGER, + X509V3_R_INVALID_NULL_ARGUMENT); + return 0; + } + if (userlen == -1) + userlen = strlen(user); + if (userlen > 64) { + X509V3err(X509V3_F_SXNET_ADD_ID_INTEGER, X509V3_R_USER_TOO_LONG); + return 0; + } + if (*psx == NULL) { + if ((sx = SXNET_new()) == NULL) + goto err; + if (!ASN1_INTEGER_set(sx->version, 0)) + goto err; + *psx = sx; + } else + sx = *psx; + if (SXNET_get_id_INTEGER(sx, zone)) { + X509V3err(X509V3_F_SXNET_ADD_ID_INTEGER, X509V3_R_DUPLICATE_ZONE_ID); + return 0; + } + + if ((id = SXNETID_new()) == NULL) + goto err; + if (userlen == -1) + userlen = strlen(user); + + if (!ASN1_OCTET_STRING_set(id->user, (const unsigned char *)user, userlen)) + goto err; + if (!sk_SXNETID_push(sx->ids, id)) + goto err; + id->zone = zone; + return 1; + + err: + X509V3err(X509V3_F_SXNET_ADD_ID_INTEGER, ERR_R_MALLOC_FAILURE); + SXNETID_free(id); + SXNET_free(sx); + *psx = NULL; + return 0; +} + +ASN1_OCTET_STRING *SXNET_get_id_asc(SXNET *sx, const char *zone) +{ + ASN1_INTEGER *izone; + ASN1_OCTET_STRING *oct; + + if ((izone = s2i_ASN1_INTEGER(NULL, zone)) == NULL) { + X509V3err(X509V3_F_SXNET_GET_ID_ASC, X509V3_R_ERROR_CONVERTING_ZONE); + return NULL; + } + oct = SXNET_get_id_INTEGER(sx, izone); + ASN1_INTEGER_free(izone); + return oct; +} + +ASN1_OCTET_STRING *SXNET_get_id_ulong(SXNET *sx, unsigned long lzone) +{ + ASN1_INTEGER *izone; + ASN1_OCTET_STRING *oct; + + if ((izone = ASN1_INTEGER_new()) == NULL + || !ASN1_INTEGER_set(izone, lzone)) { + X509V3err(X509V3_F_SXNET_GET_ID_ULONG, ERR_R_MALLOC_FAILURE); + ASN1_INTEGER_free(izone); + return NULL; + } + oct = SXNET_get_id_INTEGER(sx, izone); + ASN1_INTEGER_free(izone); + return oct; +} + +ASN1_OCTET_STRING *SXNET_get_id_INTEGER(SXNET *sx, ASN1_INTEGER *zone) +{ + SXNETID *id; + int i; + for (i = 0; i < sk_SXNETID_num(sx->ids); i++) { + id = sk_SXNETID_value(sx->ids, i); + if (!ASN1_INTEGER_cmp(id->zone, zone)) + return id->user; + } + return NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_tlsf.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_tlsf.c new file mode 100644 index 000000000..7fd6ef17d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_tlsf.c @@ -0,0 +1,137 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "e_os.h" +#include "internal/cryptlib.h" +#include +#include "internal/o_str.h" +#include +#include +#include +#include "ext_dat.h" + +static STACK_OF(CONF_VALUE) *i2v_TLS_FEATURE(const X509V3_EXT_METHOD *method, + TLS_FEATURE *tls_feature, + STACK_OF(CONF_VALUE) *ext_list); +static TLS_FEATURE *v2i_TLS_FEATURE(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval); + +ASN1_ITEM_TEMPLATE(TLS_FEATURE) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, TLS_FEATURE, ASN1_INTEGER) +static_ASN1_ITEM_TEMPLATE_END(TLS_FEATURE) + +IMPLEMENT_ASN1_ALLOC_FUNCTIONS(TLS_FEATURE) + +const X509V3_EXT_METHOD v3_tls_feature = { + NID_tlsfeature, 0, + ASN1_ITEM_ref(TLS_FEATURE), + 0, 0, 0, 0, + 0, 0, + (X509V3_EXT_I2V)i2v_TLS_FEATURE, + (X509V3_EXT_V2I)v2i_TLS_FEATURE, + 0, 0, + NULL +}; + + +typedef struct { + long num; + const char *name; +} TLS_FEATURE_NAME; + +static TLS_FEATURE_NAME tls_feature_tbl[] = { + { 5, "status_request" }, + { 17, "status_request_v2" } +}; + +/* + * i2v_TLS_FEATURE converts the TLS_FEATURE structure tls_feature into the + * STACK_OF(CONF_VALUE) structure ext_list. STACK_OF(CONF_VALUE) is the format + * used by the CONF library to represent a multi-valued extension. ext_list is + * returned. + */ +static STACK_OF(CONF_VALUE) *i2v_TLS_FEATURE(const X509V3_EXT_METHOD *method, + TLS_FEATURE *tls_feature, + STACK_OF(CONF_VALUE) *ext_list) +{ + int i; + size_t j; + ASN1_INTEGER *ai; + long tlsextid; + for (i = 0; i < sk_ASN1_INTEGER_num(tls_feature); i++) { + ai = sk_ASN1_INTEGER_value(tls_feature, i); + tlsextid = ASN1_INTEGER_get(ai); + for (j = 0; j < OSSL_NELEM(tls_feature_tbl); j++) + if (tlsextid == tls_feature_tbl[j].num) + break; + if (j < OSSL_NELEM(tls_feature_tbl)) + X509V3_add_value(NULL, tls_feature_tbl[j].name, &ext_list); + else + X509V3_add_value_int(NULL, ai, &ext_list); + } + return ext_list; +} + +/* + * v2i_TLS_FEATURE converts the multi-valued extension nval into a TLS_FEATURE + * structure, which is returned if the conversion is successful. In case of + * error, NULL is returned. + */ +static TLS_FEATURE *v2i_TLS_FEATURE(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) +{ + TLS_FEATURE *tlsf; + char *extval, *endptr; + ASN1_INTEGER *ai; + CONF_VALUE *val; + int i; + size_t j; + long tlsextid; + + if ((tlsf = sk_ASN1_INTEGER_new_null()) == NULL) { + X509V3err(X509V3_F_V2I_TLS_FEATURE, ERR_R_MALLOC_FAILURE); + return NULL; + } + + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + val = sk_CONF_VALUE_value(nval, i); + if (val->value) + extval = val->value; + else + extval = val->name; + + for (j = 0; j < OSSL_NELEM(tls_feature_tbl); j++) + if (strcasecmp(extval, tls_feature_tbl[j].name) == 0) + break; + if (j < OSSL_NELEM(tls_feature_tbl)) + tlsextid = tls_feature_tbl[j].num; + else { + tlsextid = strtol(extval, &endptr, 10); + if (((*endptr) != '\0') || (extval == endptr) || (tlsextid < 0) || + (tlsextid > 65535)) { + X509V3err(X509V3_F_V2I_TLS_FEATURE, X509V3_R_INVALID_SYNTAX); + X509V3_conf_err(val); + goto err; + } + } + + if ((ai = ASN1_INTEGER_new()) == NULL + || !ASN1_INTEGER_set(ai, tlsextid) + || sk_ASN1_INTEGER_push(tlsf, ai) <= 0) { + X509V3err(X509V3_F_V2I_TLS_FEATURE, ERR_R_MALLOC_FAILURE); + goto err; + } + } + return tlsf; + + err: + sk_ASN1_INTEGER_pop_free(tlsf, ASN1_INTEGER_free); + return NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_utl.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_utl.c new file mode 100644 index 000000000..c9b40d2c7 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3_utl.c @@ -0,0 +1,1239 @@ +/* + * Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* X509 v3 extension utilities */ + +#include "e_os.h" +#include "internal/cryptlib.h" +#include +#include "internal/ctype.h" +#include +#include +#include +#include "internal/x509_int.h" +#include +#include "ext_dat.h" + +static char *strip_spaces(char *name); +static int sk_strcmp(const char *const *a, const char *const *b); +static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name, + GENERAL_NAMES *gens); +static void str_free(OPENSSL_STRING str); +static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, const ASN1_IA5STRING *email); + +static int ipv4_from_asc(unsigned char *v4, const char *in); +static int ipv6_from_asc(unsigned char *v6, const char *in); +static int ipv6_cb(const char *elem, int len, void *usr); +static int ipv6_hex(unsigned char *out, const char *in, int inlen); + +/* Add a CONF_VALUE name value pair to stack */ + +int X509V3_add_value(const char *name, const char *value, + STACK_OF(CONF_VALUE) **extlist) +{ + CONF_VALUE *vtmp = NULL; + char *tname = NULL, *tvalue = NULL; + int sk_allocated = (*extlist == NULL); + + if (name && (tname = OPENSSL_strdup(name)) == NULL) + goto err; + if (value && (tvalue = OPENSSL_strdup(value)) == NULL) + goto err; + if ((vtmp = OPENSSL_malloc(sizeof(*vtmp))) == NULL) + goto err; + if (sk_allocated && (*extlist = sk_CONF_VALUE_new_null()) == NULL) + goto err; + vtmp->section = NULL; + vtmp->name = tname; + vtmp->value = tvalue; + if (!sk_CONF_VALUE_push(*extlist, vtmp)) + goto err; + return 1; + err: + X509V3err(X509V3_F_X509V3_ADD_VALUE, ERR_R_MALLOC_FAILURE); + if (sk_allocated) { + sk_CONF_VALUE_free(*extlist); + *extlist = NULL; + } + OPENSSL_free(vtmp); + OPENSSL_free(tname); + OPENSSL_free(tvalue); + return 0; +} + +int X509V3_add_value_uchar(const char *name, const unsigned char *value, + STACK_OF(CONF_VALUE) **extlist) +{ + return X509V3_add_value(name, (const char *)value, extlist); +} + +/* Free function for STACK_OF(CONF_VALUE) */ + +void X509V3_conf_free(CONF_VALUE *conf) +{ + if (!conf) + return; + OPENSSL_free(conf->name); + OPENSSL_free(conf->value); + OPENSSL_free(conf->section); + OPENSSL_free(conf); +} + +int X509V3_add_value_bool(const char *name, int asn1_bool, + STACK_OF(CONF_VALUE) **extlist) +{ + if (asn1_bool) + return X509V3_add_value(name, "TRUE", extlist); + return X509V3_add_value(name, "FALSE", extlist); +} + +int X509V3_add_value_bool_nf(const char *name, int asn1_bool, + STACK_OF(CONF_VALUE) **extlist) +{ + if (asn1_bool) + return X509V3_add_value(name, "TRUE", extlist); + return 1; +} + +static char *bignum_to_string(const BIGNUM *bn) +{ + char *tmp, *ret; + size_t len; + + /* + * Display large numbers in hex and small numbers in decimal. Converting to + * decimal takes quadratic time and is no more useful than hex for large + * numbers. + */ + if (BN_num_bits(bn) < 128) + return BN_bn2dec(bn); + + tmp = BN_bn2hex(bn); + if (tmp == NULL) + return NULL; + + len = strlen(tmp) + 3; + ret = OPENSSL_malloc(len); + if (ret == NULL) { + X509V3err(X509V3_F_BIGNUM_TO_STRING, ERR_R_MALLOC_FAILURE); + OPENSSL_free(tmp); + return NULL; + } + + /* Prepend "0x", but place it after the "-" if negative. */ + if (tmp[0] == '-') { + OPENSSL_strlcpy(ret, "-0x", len); + OPENSSL_strlcat(ret, tmp + 1, len); + } else { + OPENSSL_strlcpy(ret, "0x", len); + OPENSSL_strlcat(ret, tmp, len); + } + OPENSSL_free(tmp); + return ret; +} + +char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, const ASN1_ENUMERATED *a) +{ + BIGNUM *bntmp = NULL; + char *strtmp = NULL; + + if (!a) + return NULL; + if ((bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) == NULL + || (strtmp = bignum_to_string(bntmp)) == NULL) + X509V3err(X509V3_F_I2S_ASN1_ENUMERATED, ERR_R_MALLOC_FAILURE); + BN_free(bntmp); + return strtmp; +} + +char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, const ASN1_INTEGER *a) +{ + BIGNUM *bntmp = NULL; + char *strtmp = NULL; + + if (!a) + return NULL; + if ((bntmp = ASN1_INTEGER_to_BN(a, NULL)) == NULL + || (strtmp = bignum_to_string(bntmp)) == NULL) + X509V3err(X509V3_F_I2S_ASN1_INTEGER, ERR_R_MALLOC_FAILURE); + BN_free(bntmp); + return strtmp; +} + +ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, const char *value) +{ + BIGNUM *bn = NULL; + ASN1_INTEGER *aint; + int isneg, ishex; + int ret; + if (value == NULL) { + X509V3err(X509V3_F_S2I_ASN1_INTEGER, X509V3_R_INVALID_NULL_VALUE); + return NULL; + } + bn = BN_new(); + if (bn == NULL) { + X509V3err(X509V3_F_S2I_ASN1_INTEGER, ERR_R_MALLOC_FAILURE); + return NULL; + } + if (value[0] == '-') { + value++; + isneg = 1; + } else + isneg = 0; + + if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) { + value += 2; + ishex = 1; + } else + ishex = 0; + + if (ishex) + ret = BN_hex2bn(&bn, value); + else + ret = BN_dec2bn(&bn, value); + + if (!ret || value[ret]) { + BN_free(bn); + X509V3err(X509V3_F_S2I_ASN1_INTEGER, X509V3_R_BN_DEC2BN_ERROR); + return NULL; + } + + if (isneg && BN_is_zero(bn)) + isneg = 0; + + aint = BN_to_ASN1_INTEGER(bn, NULL); + BN_free(bn); + if (!aint) { + X509V3err(X509V3_F_S2I_ASN1_INTEGER, + X509V3_R_BN_TO_ASN1_INTEGER_ERROR); + return NULL; + } + if (isneg) + aint->type |= V_ASN1_NEG; + return aint; +} + +int X509V3_add_value_int(const char *name, const ASN1_INTEGER *aint, + STACK_OF(CONF_VALUE) **extlist) +{ + char *strtmp; + int ret; + + if (!aint) + return 1; + if ((strtmp = i2s_ASN1_INTEGER(NULL, aint)) == NULL) + return 0; + ret = X509V3_add_value(name, strtmp, extlist); + OPENSSL_free(strtmp); + return ret; +} + +int X509V3_get_value_bool(const CONF_VALUE *value, int *asn1_bool) +{ + const char *btmp; + + if ((btmp = value->value) == NULL) + goto err; + if (strcmp(btmp, "TRUE") == 0 + || strcmp(btmp, "true") == 0 + || strcmp(btmp, "Y") == 0 + || strcmp(btmp, "y") == 0 + || strcmp(btmp, "YES") == 0 + || strcmp(btmp, "yes") == 0) { + *asn1_bool = 0xff; + return 1; + } + if (strcmp(btmp, "FALSE") == 0 + || strcmp(btmp, "false") == 0 + || strcmp(btmp, "N") == 0 + || strcmp(btmp, "n") == 0 + || strcmp(btmp, "NO") == 0 + || strcmp(btmp, "no") == 0) { + *asn1_bool = 0; + return 1; + } + err: + X509V3err(X509V3_F_X509V3_GET_VALUE_BOOL, + X509V3_R_INVALID_BOOLEAN_STRING); + X509V3_conf_err(value); + return 0; +} + +int X509V3_get_value_int(const CONF_VALUE *value, ASN1_INTEGER **aint) +{ + ASN1_INTEGER *itmp; + + if ((itmp = s2i_ASN1_INTEGER(NULL, value->value)) == NULL) { + X509V3_conf_err(value); + return 0; + } + *aint = itmp; + return 1; +} + +#define HDR_NAME 1 +#define HDR_VALUE 2 + +/* + * #define DEBUG + */ + +STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line) +{ + char *p, *q, c; + char *ntmp, *vtmp; + STACK_OF(CONF_VALUE) *values = NULL; + char *linebuf; + int state; + /* We are going to modify the line so copy it first */ + linebuf = OPENSSL_strdup(line); + if (linebuf == NULL) { + X509V3err(X509V3_F_X509V3_PARSE_LIST, ERR_R_MALLOC_FAILURE); + goto err; + } + state = HDR_NAME; + ntmp = NULL; + /* Go through all characters */ + for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && (c != '\n'); + p++) { + + switch (state) { + case HDR_NAME: + if (c == ':') { + state = HDR_VALUE; + *p = 0; + ntmp = strip_spaces(q); + if (!ntmp) { + X509V3err(X509V3_F_X509V3_PARSE_LIST, + X509V3_R_INVALID_NULL_NAME); + goto err; + } + q = p + 1; + } else if (c == ',') { + *p = 0; + ntmp = strip_spaces(q); + q = p + 1; + if (!ntmp) { + X509V3err(X509V3_F_X509V3_PARSE_LIST, + X509V3_R_INVALID_NULL_NAME); + goto err; + } + X509V3_add_value(ntmp, NULL, &values); + } + break; + + case HDR_VALUE: + if (c == ',') { + state = HDR_NAME; + *p = 0; + vtmp = strip_spaces(q); + if (!vtmp) { + X509V3err(X509V3_F_X509V3_PARSE_LIST, + X509V3_R_INVALID_NULL_VALUE); + goto err; + } + X509V3_add_value(ntmp, vtmp, &values); + ntmp = NULL; + q = p + 1; + } + + } + } + + if (state == HDR_VALUE) { + vtmp = strip_spaces(q); + if (!vtmp) { + X509V3err(X509V3_F_X509V3_PARSE_LIST, + X509V3_R_INVALID_NULL_VALUE); + goto err; + } + X509V3_add_value(ntmp, vtmp, &values); + } else { + ntmp = strip_spaces(q); + if (!ntmp) { + X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME); + goto err; + } + X509V3_add_value(ntmp, NULL, &values); + } + OPENSSL_free(linebuf); + return values; + + err: + OPENSSL_free(linebuf); + sk_CONF_VALUE_pop_free(values, X509V3_conf_free); + return NULL; + +} + +/* Delete leading and trailing spaces from a string */ +static char *strip_spaces(char *name) +{ + char *p, *q; + /* Skip over leading spaces */ + p = name; + while (*p && ossl_isspace(*p)) + p++; + if (!*p) + return NULL; + q = p + strlen(p) - 1; + while ((q != p) && ossl_isspace(*q)) + q--; + if (p != q) + q[1] = 0; + if (!*p) + return NULL; + return p; +} + + +/* + * V2I name comparison function: returns zero if 'name' matches cmp or cmp.* + */ + +int name_cmp(const char *name, const char *cmp) +{ + int len, ret; + char c; + len = strlen(cmp); + if ((ret = strncmp(name, cmp, len))) + return ret; + c = name[len]; + if (!c || (c == '.')) + return 0; + return 1; +} + +static int sk_strcmp(const char *const *a, const char *const *b) +{ + return strcmp(*a, *b); +} + +STACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x) +{ + GENERAL_NAMES *gens; + STACK_OF(OPENSSL_STRING) *ret; + + gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); + ret = get_email(X509_get_subject_name(x), gens); + sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); + return ret; +} + +STACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x) +{ + AUTHORITY_INFO_ACCESS *info; + STACK_OF(OPENSSL_STRING) *ret = NULL; + int i; + + info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL); + if (!info) + return NULL; + for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) { + ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i); + if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) { + if (ad->location->type == GEN_URI) { + if (!append_ia5 + (&ret, ad->location->d.uniformResourceIdentifier)) + break; + } + } + } + AUTHORITY_INFO_ACCESS_free(info); + return ret; +} + +STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x) +{ + GENERAL_NAMES *gens; + STACK_OF(X509_EXTENSION) *exts; + STACK_OF(OPENSSL_STRING) *ret; + + exts = X509_REQ_get_extensions(x); + gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL); + ret = get_email(X509_REQ_get_subject_name(x), gens); + sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); + sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); + return ret; +} + +static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name, + GENERAL_NAMES *gens) +{ + STACK_OF(OPENSSL_STRING) *ret = NULL; + X509_NAME_ENTRY *ne; + const ASN1_IA5STRING *email; + GENERAL_NAME *gen; + int i = -1; + + /* Now add any email address(es) to STACK */ + /* First supplied X509_NAME */ + while ((i = X509_NAME_get_index_by_NID(name, + NID_pkcs9_emailAddress, i)) >= 0) { + ne = X509_NAME_get_entry(name, i); + email = X509_NAME_ENTRY_get_data(ne); + if (!append_ia5(&ret, email)) + return NULL; + } + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { + gen = sk_GENERAL_NAME_value(gens, i); + if (gen->type != GEN_EMAIL) + continue; + if (!append_ia5(&ret, gen->d.ia5)) + return NULL; + } + return ret; +} + +static void str_free(OPENSSL_STRING str) +{ + OPENSSL_free(str); +} + +static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, const ASN1_IA5STRING *email) +{ + char *emtmp; + /* First some sanity checks */ + if (email->type != V_ASN1_IA5STRING) + return 1; + if (!email->data || !email->length) + return 1; + if (*sk == NULL) + *sk = sk_OPENSSL_STRING_new(sk_strcmp); + if (*sk == NULL) + return 0; + /* Don't add duplicates */ + if (sk_OPENSSL_STRING_find(*sk, (char *)email->data) != -1) + return 1; + emtmp = OPENSSL_strdup((char *)email->data); + if (emtmp == NULL || !sk_OPENSSL_STRING_push(*sk, emtmp)) { + OPENSSL_free(emtmp); /* free on push failure */ + X509_email_free(*sk); + *sk = NULL; + return 0; + } + return 1; +} + +void X509_email_free(STACK_OF(OPENSSL_STRING) *sk) +{ + sk_OPENSSL_STRING_pop_free(sk, str_free); +} + +typedef int (*equal_fn) (const unsigned char *pattern, size_t pattern_len, + const unsigned char *subject, size_t subject_len, + unsigned int flags); + +/* Skip pattern prefix to match "wildcard" subject */ +static void skip_prefix(const unsigned char **p, size_t *plen, + size_t subject_len, + unsigned int flags) +{ + const unsigned char *pattern = *p; + size_t pattern_len = *plen; + + /* + * If subject starts with a leading '.' followed by more octets, and + * pattern is longer, compare just an equal-length suffix with the + * full subject (starting at the '.'), provided the prefix contains + * no NULs. + */ + if ((flags & _X509_CHECK_FLAG_DOT_SUBDOMAINS) == 0) + return; + + while (pattern_len > subject_len && *pattern) { + if ((flags & X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS) && + *pattern == '.') + break; + ++pattern; + --pattern_len; + } + + /* Skip if entire prefix acceptable */ + if (pattern_len == subject_len) { + *p = pattern; + *plen = pattern_len; + } +} + +/* Compare while ASCII ignoring case. */ +static int equal_nocase(const unsigned char *pattern, size_t pattern_len, + const unsigned char *subject, size_t subject_len, + unsigned int flags) +{ + skip_prefix(&pattern, &pattern_len, subject_len, flags); + if (pattern_len != subject_len) + return 0; + while (pattern_len) { + unsigned char l = *pattern; + unsigned char r = *subject; + /* The pattern must not contain NUL characters. */ + if (l == 0) + return 0; + if (l != r) { + if ('A' <= l && l <= 'Z') + l = (l - 'A') + 'a'; + if ('A' <= r && r <= 'Z') + r = (r - 'A') + 'a'; + if (l != r) + return 0; + } + ++pattern; + ++subject; + --pattern_len; + } + return 1; +} + +/* Compare using memcmp. */ +static int equal_case(const unsigned char *pattern, size_t pattern_len, + const unsigned char *subject, size_t subject_len, + unsigned int flags) +{ + skip_prefix(&pattern, &pattern_len, subject_len, flags); + if (pattern_len != subject_len) + return 0; + return !memcmp(pattern, subject, pattern_len); +} + +/* + * RFC 5280, section 7.5, requires that only the domain is compared in a + * case-insensitive manner. + */ +static int equal_email(const unsigned char *a, size_t a_len, + const unsigned char *b, size_t b_len, + unsigned int unused_flags) +{ + size_t i = a_len; + if (a_len != b_len) + return 0; + /* + * We search backwards for the '@' character, so that we do not have to + * deal with quoted local-parts. The domain part is compared in a + * case-insensitive manner. + */ + while (i > 0) { + --i; + if (a[i] == '@' || b[i] == '@') { + if (!equal_nocase(a + i, a_len - i, b + i, a_len - i, 0)) + return 0; + break; + } + } + if (i == 0) + i = a_len; + return equal_case(a, i, b, i, 0); +} + +/* + * Compare the prefix and suffix with the subject, and check that the + * characters in-between are valid. + */ +static int wildcard_match(const unsigned char *prefix, size_t prefix_len, + const unsigned char *suffix, size_t suffix_len, + const unsigned char *subject, size_t subject_len, + unsigned int flags) +{ + const unsigned char *wildcard_start; + const unsigned char *wildcard_end; + const unsigned char *p; + int allow_multi = 0; + int allow_idna = 0; + + if (subject_len < prefix_len + suffix_len) + return 0; + if (!equal_nocase(prefix, prefix_len, subject, prefix_len, flags)) + return 0; + wildcard_start = subject + prefix_len; + wildcard_end = subject + (subject_len - suffix_len); + if (!equal_nocase(wildcard_end, suffix_len, suffix, suffix_len, flags)) + return 0; + /* + * If the wildcard makes up the entire first label, it must match at + * least one character. + */ + if (prefix_len == 0 && *suffix == '.') { + if (wildcard_start == wildcard_end) + return 0; + allow_idna = 1; + if (flags & X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS) + allow_multi = 1; + } + /* IDNA labels cannot match partial wildcards */ + if (!allow_idna && + subject_len >= 4 && strncasecmp((char *)subject, "xn--", 4) == 0) + return 0; + /* The wildcard may match a literal '*' */ + if (wildcard_end == wildcard_start + 1 && *wildcard_start == '*') + return 1; + /* + * Check that the part matched by the wildcard contains only + * permitted characters and only matches a single label unless + * allow_multi is set. + */ + for (p = wildcard_start; p != wildcard_end; ++p) + if (!(('0' <= *p && *p <= '9') || + ('A' <= *p && *p <= 'Z') || + ('a' <= *p && *p <= 'z') || + *p == '-' || (allow_multi && *p == '.'))) + return 0; + return 1; +} + +#define LABEL_START (1 << 0) +#define LABEL_END (1 << 1) +#define LABEL_HYPHEN (1 << 2) +#define LABEL_IDNA (1 << 3) + +static const unsigned char *valid_star(const unsigned char *p, size_t len, + unsigned int flags) +{ + const unsigned char *star = 0; + size_t i; + int state = LABEL_START; + int dots = 0; + for (i = 0; i < len; ++i) { + /* + * Locate first and only legal wildcard, either at the start + * or end of a non-IDNA first and not final label. + */ + if (p[i] == '*') { + int atstart = (state & LABEL_START); + int atend = (i == len - 1 || p[i + 1] == '.'); + /*- + * At most one wildcard per pattern. + * No wildcards in IDNA labels. + * No wildcards after the first label. + */ + if (star != NULL || (state & LABEL_IDNA) != 0 || dots) + return NULL; + /* Only full-label '*.example.com' wildcards? */ + if ((flags & X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS) + && (!atstart || !atend)) + return NULL; + /* No 'foo*bar' wildcards */ + if (!atstart && !atend) + return NULL; + star = &p[i]; + state &= ~LABEL_START; + } else if (('a' <= p[i] && p[i] <= 'z') + || ('A' <= p[i] && p[i] <= 'Z') + || ('0' <= p[i] && p[i] <= '9')) { + if ((state & LABEL_START) != 0 + && len - i >= 4 && strncasecmp((char *)&p[i], "xn--", 4) == 0) + state |= LABEL_IDNA; + state &= ~(LABEL_HYPHEN | LABEL_START); + } else if (p[i] == '.') { + if ((state & (LABEL_HYPHEN | LABEL_START)) != 0) + return NULL; + state = LABEL_START; + ++dots; + } else if (p[i] == '-') { + /* no domain/subdomain starts with '-' */ + if ((state & LABEL_START) != 0) + return NULL; + state |= LABEL_HYPHEN; + } else + return NULL; + } + + /* + * The final label must not end in a hyphen or ".", and + * there must be at least two dots after the star. + */ + if ((state & (LABEL_START | LABEL_HYPHEN)) != 0 || dots < 2) + return NULL; + return star; +} + +/* Compare using wildcards. */ +static int equal_wildcard(const unsigned char *pattern, size_t pattern_len, + const unsigned char *subject, size_t subject_len, + unsigned int flags) +{ + const unsigned char *star = NULL; + + /* + * Subject names starting with '.' can only match a wildcard pattern + * via a subject sub-domain pattern suffix match. + */ + if (!(subject_len > 1 && subject[0] == '.')) + star = valid_star(pattern, pattern_len, flags); + if (star == NULL) + return equal_nocase(pattern, pattern_len, + subject, subject_len, flags); + return wildcard_match(pattern, star - pattern, + star + 1, (pattern + pattern_len) - star - 1, + subject, subject_len, flags); +} + +/* + * Compare an ASN1_STRING to a supplied string. If they match return 1. If + * cmp_type > 0 only compare if string matches the type, otherwise convert it + * to UTF8. + */ + +static int do_check_string(const ASN1_STRING *a, int cmp_type, equal_fn equal, + unsigned int flags, const char *b, size_t blen, + char **peername) +{ + int rv = 0; + + if (!a->data || !a->length) + return 0; + if (cmp_type > 0) { + if (cmp_type != a->type) + return 0; + if (cmp_type == V_ASN1_IA5STRING) + rv = equal(a->data, a->length, (unsigned char *)b, blen, flags); + else if (a->length == (int)blen && !memcmp(a->data, b, blen)) + rv = 1; + if (rv > 0 && peername) + *peername = OPENSSL_strndup((char *)a->data, a->length); + } else { + int astrlen; + unsigned char *astr; + astrlen = ASN1_STRING_to_UTF8(&astr, a); + if (astrlen < 0) { + /* + * -1 could be an internal malloc failure or a decoding error from + * malformed input; we can't distinguish. + */ + return -1; + } + rv = equal(astr, astrlen, (unsigned char *)b, blen, flags); + if (rv > 0 && peername) + *peername = OPENSSL_strndup((char *)astr, astrlen); + OPENSSL_free(astr); + } + return rv; +} + +static int do_x509_check(X509 *x, const char *chk, size_t chklen, + unsigned int flags, int check_type, char **peername) +{ + GENERAL_NAMES *gens = NULL; + X509_NAME *name = NULL; + int i; + int cnid = NID_undef; + int alt_type; + int san_present = 0; + int rv = 0; + equal_fn equal; + + /* See below, this flag is internal-only */ + flags &= ~_X509_CHECK_FLAG_DOT_SUBDOMAINS; + if (check_type == GEN_EMAIL) { + cnid = NID_pkcs9_emailAddress; + alt_type = V_ASN1_IA5STRING; + equal = equal_email; + } else if (check_type == GEN_DNS) { + cnid = NID_commonName; + /* Implicit client-side DNS sub-domain pattern */ + if (chklen > 1 && chk[0] == '.') + flags |= _X509_CHECK_FLAG_DOT_SUBDOMAINS; + alt_type = V_ASN1_IA5STRING; + if (flags & X509_CHECK_FLAG_NO_WILDCARDS) + equal = equal_nocase; + else + equal = equal_wildcard; + } else { + alt_type = V_ASN1_OCTET_STRING; + equal = equal_case; + } + + if (chklen == 0) + chklen = strlen(chk); + + gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); + if (gens) { + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { + GENERAL_NAME *gen; + ASN1_STRING *cstr; + gen = sk_GENERAL_NAME_value(gens, i); + if (gen->type != check_type) + continue; + san_present = 1; + if (check_type == GEN_EMAIL) + cstr = gen->d.rfc822Name; + else if (check_type == GEN_DNS) + cstr = gen->d.dNSName; + else + cstr = gen->d.iPAddress; + /* Positive on success, negative on error! */ + if ((rv = do_check_string(cstr, alt_type, equal, flags, + chk, chklen, peername)) != 0) + break; + } + GENERAL_NAMES_free(gens); + if (rv != 0) + return rv; + if (san_present && !(flags & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT)) + return 0; + } + + /* We're done if CN-ID is not pertinent */ + if (cnid == NID_undef || (flags & X509_CHECK_FLAG_NEVER_CHECK_SUBJECT)) + return 0; + + i = -1; + name = X509_get_subject_name(x); + while ((i = X509_NAME_get_index_by_NID(name, cnid, i)) >= 0) { + const X509_NAME_ENTRY *ne = X509_NAME_get_entry(name, i); + const ASN1_STRING *str = X509_NAME_ENTRY_get_data(ne); + + /* Positive on success, negative on error! */ + if ((rv = do_check_string(str, -1, equal, flags, + chk, chklen, peername)) != 0) + return rv; + } + return 0; +} + +int X509_check_host(X509 *x, const char *chk, size_t chklen, + unsigned int flags, char **peername) +{ + if (chk == NULL) + return -2; + /* + * Embedded NULs are disallowed, except as the last character of a + * string of length 2 or more (tolerate caller including terminating + * NUL in string length). + */ + if (chklen == 0) + chklen = strlen(chk); + else if (memchr(chk, '\0', chklen > 1 ? chklen - 1 : chklen)) + return -2; + if (chklen > 1 && chk[chklen - 1] == '\0') + --chklen; + return do_x509_check(x, chk, chklen, flags, GEN_DNS, peername); +} + +int X509_check_email(X509 *x, const char *chk, size_t chklen, + unsigned int flags) +{ + if (chk == NULL) + return -2; + /* + * Embedded NULs are disallowed, except as the last character of a + * string of length 2 or more (tolerate caller including terminating + * NUL in string length). + */ + if (chklen == 0) + chklen = strlen((char *)chk); + else if (memchr(chk, '\0', chklen > 1 ? chklen - 1 : chklen)) + return -2; + if (chklen > 1 && chk[chklen - 1] == '\0') + --chklen; + return do_x509_check(x, chk, chklen, flags, GEN_EMAIL, NULL); +} + +int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen, + unsigned int flags) +{ + if (chk == NULL) + return -2; + return do_x509_check(x, (char *)chk, chklen, flags, GEN_IPADD, NULL); +} + +int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags) +{ + unsigned char ipout[16]; + size_t iplen; + + if (ipasc == NULL) + return -2; + iplen = (size_t)a2i_ipadd(ipout, ipasc); + if (iplen == 0) + return -2; + return do_x509_check(x, (char *)ipout, iplen, flags, GEN_IPADD, NULL); +} + +/* + * Convert IP addresses both IPv4 and IPv6 into an OCTET STRING compatible + * with RFC3280. + */ + +ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc) +{ + unsigned char ipout[16]; + ASN1_OCTET_STRING *ret; + int iplen; + + /* If string contains a ':' assume IPv6 */ + + iplen = a2i_ipadd(ipout, ipasc); + + if (!iplen) + return NULL; + + ret = ASN1_OCTET_STRING_new(); + if (ret == NULL) + return NULL; + if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) { + ASN1_OCTET_STRING_free(ret); + return NULL; + } + return ret; +} + +ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc) +{ + ASN1_OCTET_STRING *ret = NULL; + unsigned char ipout[32]; + char *iptmp = NULL, *p; + int iplen1, iplen2; + p = strchr(ipasc, '/'); + if (!p) + return NULL; + iptmp = OPENSSL_strdup(ipasc); + if (!iptmp) + return NULL; + p = iptmp + (p - ipasc); + *p++ = 0; + + iplen1 = a2i_ipadd(ipout, iptmp); + + if (!iplen1) + goto err; + + iplen2 = a2i_ipadd(ipout + iplen1, p); + + OPENSSL_free(iptmp); + iptmp = NULL; + + if (!iplen2 || (iplen1 != iplen2)) + goto err; + + ret = ASN1_OCTET_STRING_new(); + if (ret == NULL) + goto err; + if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2)) + goto err; + + return ret; + + err: + OPENSSL_free(iptmp); + ASN1_OCTET_STRING_free(ret); + return NULL; +} + +int a2i_ipadd(unsigned char *ipout, const char *ipasc) +{ + /* If string contains a ':' assume IPv6 */ + + if (strchr(ipasc, ':')) { + if (!ipv6_from_asc(ipout, ipasc)) + return 0; + return 16; + } else { + if (!ipv4_from_asc(ipout, ipasc)) + return 0; + return 4; + } +} + +static int ipv4_from_asc(unsigned char *v4, const char *in) +{ + int a0, a1, a2, a3; + if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4) + return 0; + if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255) + || (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255)) + return 0; + v4[0] = a0; + v4[1] = a1; + v4[2] = a2; + v4[3] = a3; + return 1; +} + +typedef struct { + /* Temporary store for IPV6 output */ + unsigned char tmp[16]; + /* Total number of bytes in tmp */ + int total; + /* The position of a zero (corresponding to '::') */ + int zero_pos; + /* Number of zeroes */ + int zero_cnt; +} IPV6_STAT; + +static int ipv6_from_asc(unsigned char *v6, const char *in) +{ + IPV6_STAT v6stat; + v6stat.total = 0; + v6stat.zero_pos = -1; + v6stat.zero_cnt = 0; + /* + * Treat the IPv6 representation as a list of values separated by ':'. + * The presence of a '::' will parse as one, two or three zero length + * elements. + */ + if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat)) + return 0; + + /* Now for some sanity checks */ + + if (v6stat.zero_pos == -1) { + /* If no '::' must have exactly 16 bytes */ + if (v6stat.total != 16) + return 0; + } else { + /* If '::' must have less than 16 bytes */ + if (v6stat.total == 16) + return 0; + /* More than three zeroes is an error */ + if (v6stat.zero_cnt > 3) + return 0; + /* Can only have three zeroes if nothing else present */ + else if (v6stat.zero_cnt == 3) { + if (v6stat.total > 0) + return 0; + } + /* Can only have two zeroes if at start or end */ + else if (v6stat.zero_cnt == 2) { + if ((v6stat.zero_pos != 0) + && (v6stat.zero_pos != v6stat.total)) + return 0; + } else + /* Can only have one zero if *not* start or end */ + { + if ((v6stat.zero_pos == 0) + || (v6stat.zero_pos == v6stat.total)) + return 0; + } + } + + /* Format result */ + + if (v6stat.zero_pos >= 0) { + /* Copy initial part */ + memcpy(v6, v6stat.tmp, v6stat.zero_pos); + /* Zero middle */ + memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total); + /* Copy final part */ + if (v6stat.total != v6stat.zero_pos) + memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total, + v6stat.tmp + v6stat.zero_pos, + v6stat.total - v6stat.zero_pos); + } else + memcpy(v6, v6stat.tmp, 16); + + return 1; +} + +static int ipv6_cb(const char *elem, int len, void *usr) +{ + IPV6_STAT *s = usr; + /* Error if 16 bytes written */ + if (s->total == 16) + return 0; + if (len == 0) { + /* Zero length element, corresponds to '::' */ + if (s->zero_pos == -1) + s->zero_pos = s->total; + /* If we've already got a :: its an error */ + else if (s->zero_pos != s->total) + return 0; + s->zero_cnt++; + } else { + /* If more than 4 characters could be final a.b.c.d form */ + if (len > 4) { + /* Need at least 4 bytes left */ + if (s->total > 12) + return 0; + /* Must be end of string */ + if (elem[len]) + return 0; + if (!ipv4_from_asc(s->tmp + s->total, elem)) + return 0; + s->total += 4; + } else { + if (!ipv6_hex(s->tmp + s->total, elem, len)) + return 0; + s->total += 2; + } + } + return 1; +} + +/* + * Convert a string of up to 4 hex digits into the corresponding IPv6 form. + */ + +static int ipv6_hex(unsigned char *out, const char *in, int inlen) +{ + unsigned char c; + unsigned int num = 0; + int x; + + if (inlen > 4) + return 0; + while (inlen--) { + c = *in++; + num <<= 4; + x = OPENSSL_hexchar2int(c); + if (x < 0) + return 0; + num |= (char)x; + } + out[0] = num >> 8; + out[1] = num & 0xff; + return 1; +} + +int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE) *dn_sk, + unsigned long chtype) +{ + CONF_VALUE *v; + int i, mval, spec_char, plus_char; + char *p, *type; + if (!nm) + return 0; + + for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) { + v = sk_CONF_VALUE_value(dn_sk, i); + type = v->name; + /* + * Skip past any leading X. X: X, etc to allow for multiple instances + */ + for (p = type; *p; p++) { +#ifndef CHARSET_EBCDIC + spec_char = ((*p == ':') || (*p == ',') || (*p == '.')); +#else + spec_char = ((*p == os_toascii[':']) || (*p == os_toascii[',']) + || (*p == os_toascii['.'])); +#endif + if (spec_char) { + p++; + if (*p) + type = p; + break; + } + } +#ifndef CHARSET_EBCDIC + plus_char = (*type == '+'); +#else + plus_char = (*type == os_toascii['+']); +#endif + if (plus_char) { + mval = -1; + type++; + } else + mval = 0; + if (!X509_NAME_add_entry_by_txt(nm, type, chtype, + (unsigned char *)v->value, -1, -1, + mval)) + return 0; + + } + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3err.c b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3err.c new file mode 100644 index 000000000..4f2ea52a4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x509v3/v3err.c @@ -0,0 +1,257 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA X509V3_str_functs[] = { + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_A2I_GENERAL_NAME, 0), + "a2i_GENERAL_NAME"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_ADDR_VALIDATE_PATH_INTERNAL, 0), + "addr_validate_path_internal"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_ASIDENTIFIERCHOICE_CANONIZE, 0), + "ASIdentifierChoice_canonize"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_ASIDENTIFIERCHOICE_IS_CANONICAL, 0), + "ASIdentifierChoice_is_canonical"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_BIGNUM_TO_STRING, 0), + "bignum_to_string"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_COPY_EMAIL, 0), "copy_email"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_COPY_ISSUER, 0), "copy_issuer"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_DO_DIRNAME, 0), "do_dirname"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_DO_EXT_I2D, 0), "do_ext_i2d"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_DO_EXT_NCONF, 0), "do_ext_nconf"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_GNAMES_FROM_SECTNAME, 0), + "gnames_from_sectname"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_I2S_ASN1_ENUMERATED, 0), + "i2s_ASN1_ENUMERATED"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_I2S_ASN1_IA5STRING, 0), + "i2s_ASN1_IA5STRING"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_I2S_ASN1_INTEGER, 0), + "i2s_ASN1_INTEGER"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_I2V_AUTHORITY_INFO_ACCESS, 0), + "i2v_AUTHORITY_INFO_ACCESS"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_LEVEL_ADD_NODE, 0), "level_add_node"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_NOTICE_SECTION, 0), "notice_section"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_NREF_NOS, 0), "nref_nos"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_POLICY_CACHE_CREATE, 0), + "policy_cache_create"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_POLICY_CACHE_NEW, 0), + "policy_cache_new"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_POLICY_DATA_NEW, 0), "policy_data_new"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_POLICY_SECTION, 0), "policy_section"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_PROCESS_PCI_VALUE, 0), + "process_pci_value"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_R2I_CERTPOL, 0), "r2i_certpol"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_R2I_PCI, 0), "r2i_pci"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_S2I_ASN1_IA5STRING, 0), + "s2i_ASN1_IA5STRING"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_S2I_ASN1_INTEGER, 0), + "s2i_ASN1_INTEGER"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_S2I_ASN1_OCTET_STRING, 0), + "s2i_ASN1_OCTET_STRING"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_S2I_SKEY_ID, 0), "s2i_skey_id"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_SET_DIST_POINT_NAME, 0), + "set_dist_point_name"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_SXNET_ADD_ID_ASC, 0), + "SXNET_add_id_asc"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_SXNET_ADD_ID_INTEGER, 0), + "SXNET_add_id_INTEGER"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_SXNET_ADD_ID_ULONG, 0), + "SXNET_add_id_ulong"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_SXNET_GET_ID_ASC, 0), + "SXNET_get_id_asc"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_SXNET_GET_ID_ULONG, 0), + "SXNET_get_id_ulong"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_TREE_INIT, 0), "tree_init"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_ASIDENTIFIERS, 0), + "v2i_ASIdentifiers"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_ASN1_BIT_STRING, 0), + "v2i_ASN1_BIT_STRING"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_AUTHORITY_INFO_ACCESS, 0), + "v2i_AUTHORITY_INFO_ACCESS"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_AUTHORITY_KEYID, 0), + "v2i_AUTHORITY_KEYID"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_BASIC_CONSTRAINTS, 0), + "v2i_BASIC_CONSTRAINTS"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_CRLD, 0), "v2i_crld"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_EXTENDED_KEY_USAGE, 0), + "v2i_EXTENDED_KEY_USAGE"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_GENERAL_NAMES, 0), + "v2i_GENERAL_NAMES"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_GENERAL_NAME_EX, 0), + "v2i_GENERAL_NAME_ex"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_IDP, 0), "v2i_idp"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_IPADDRBLOCKS, 0), + "v2i_IPAddrBlocks"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_ISSUER_ALT, 0), "v2i_issuer_alt"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_NAME_CONSTRAINTS, 0), + "v2i_NAME_CONSTRAINTS"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_POLICY_CONSTRAINTS, 0), + "v2i_POLICY_CONSTRAINTS"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_POLICY_MAPPINGS, 0), + "v2i_POLICY_MAPPINGS"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_SUBJECT_ALT, 0), "v2i_subject_alt"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V2I_TLS_FEATURE, 0), "v2i_TLS_FEATURE"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_V3_GENERIC_EXTENSION, 0), + "v3_generic_extension"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_ADD1_I2D, 0), "X509V3_add1_i2d"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_ADD_VALUE, 0), + "X509V3_add_value"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_EXT_ADD, 0), "X509V3_EXT_add"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_EXT_ADD_ALIAS, 0), + "X509V3_EXT_add_alias"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_EXT_I2D, 0), "X509V3_EXT_i2d"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_EXT_NCONF, 0), + "X509V3_EXT_nconf"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_GET_SECTION, 0), + "X509V3_get_section"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_GET_STRING, 0), + "X509V3_get_string"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_GET_VALUE_BOOL, 0), + "X509V3_get_value_bool"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_PARSE_LIST, 0), + "X509V3_parse_list"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509_PURPOSE_ADD, 0), + "X509_PURPOSE_add"}, + {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509_PURPOSE_SET, 0), + "X509_PURPOSE_set"}, + {0, NULL} +}; + +static const ERR_STRING_DATA X509V3_str_reasons[] = { + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_BAD_IP_ADDRESS), "bad ip address"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_BAD_OBJECT), "bad object"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_BN_DEC2BN_ERROR), "bn dec2bn error"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_BN_TO_ASN1_INTEGER_ERROR), + "bn to asn1 integer error"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_DIRNAME_ERROR), "dirname error"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_DISTPOINT_ALREADY_SET), + "distpoint already set"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_DUPLICATE_ZONE_ID), + "duplicate zone id"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ERROR_CONVERTING_ZONE), + "error converting zone"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ERROR_CREATING_EXTENSION), + "error creating extension"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ERROR_IN_EXTENSION), + "error in extension"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXPECTED_A_SECTION_NAME), + "expected a section name"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_EXISTS), + "extension exists"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_NAME_ERROR), + "extension name error"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_NOT_FOUND), + "extension not found"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED), + "extension setting not supported"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_VALUE_ERROR), + "extension value error"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ILLEGAL_EMPTY_EXTENSION), + "illegal empty extension"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INCORRECT_POLICY_SYNTAX_TAG), + "incorrect policy syntax tag"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_ASNUMBER), + "invalid asnumber"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_ASRANGE), "invalid asrange"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_BOOLEAN_STRING), + "invalid boolean string"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_EXTENSION_STRING), + "invalid extension string"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_INHERITANCE), + "invalid inheritance"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_IPADDRESS), + "invalid ipaddress"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_MULTIPLE_RDNS), + "invalid multiple rdns"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NAME), "invalid name"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NULL_ARGUMENT), + "invalid null argument"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NULL_NAME), + "invalid null name"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NULL_VALUE), + "invalid null value"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NUMBER), "invalid number"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NUMBERS), "invalid numbers"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_OBJECT_IDENTIFIER), + "invalid object identifier"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_OPTION), "invalid option"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_POLICY_IDENTIFIER), + "invalid policy identifier"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_PROXY_POLICY_SETTING), + "invalid proxy policy setting"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_PURPOSE), "invalid purpose"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_SAFI), "invalid safi"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_SECTION), "invalid section"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_SYNTAX), "invalid syntax"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ISSUER_DECODE_ERROR), + "issuer decode error"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_MISSING_VALUE), "missing value"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NEED_ORGANIZATION_AND_NUMBERS), + "need organization and numbers"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_CONFIG_DATABASE), + "no config database"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_ISSUER_CERTIFICATE), + "no issuer certificate"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_ISSUER_DETAILS), + "no issuer details"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_POLICY_IDENTIFIER), + "no policy identifier"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED), + "no proxy cert policy language defined"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_PUBLIC_KEY), "no public key"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_SUBJECT_DETAILS), + "no subject details"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_OPERATION_NOT_DEFINED), + "operation not defined"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_OTHERNAME_ERROR), "othername error"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED), + "policy language already defined"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_PATH_LENGTH), + "policy path length"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED), + "policy path length already defined"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY), + "policy when proxy language requires no policy"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_SECTION_NOT_FOUND), + "section not found"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS), + "unable to get issuer details"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNABLE_TO_GET_ISSUER_KEYID), + "unable to get issuer keyid"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT), + "unknown bit string argument"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_EXTENSION), + "unknown extension"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_EXTENSION_NAME), + "unknown extension name"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_OPTION), "unknown option"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNSUPPORTED_OPTION), + "unsupported option"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNSUPPORTED_TYPE), + "unsupported type"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_USER_TOO_LONG), "user too long"}, + {0, NULL} +}; + +#endif + +int ERR_load_X509V3_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(X509V3_str_functs[0].error) == NULL) { + ERR_load_strings_const(X509V3_str_functs); + ERR_load_strings_const(X509V3_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x86_64cpuid.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/x86_64cpuid.pl new file mode 100644 index 000000000..6423e803b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x86_64cpuid.pl @@ -0,0 +1,495 @@ +#! /usr/bin/env perl +# Copyright 2005-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +*STDOUT=*OUT; + +($arg1,$arg2,$arg3,$arg4)=$win64?("%rcx","%rdx","%r8", "%r9") : # Win64 order + ("%rdi","%rsi","%rdx","%rcx"); # Unix order + +print<<___; +.extern OPENSSL_cpuid_setup +.hidden OPENSSL_cpuid_setup +.section .init + call OPENSSL_cpuid_setup + +.hidden OPENSSL_ia32cap_P +.comm OPENSSL_ia32cap_P,16,4 + +.text + +.globl OPENSSL_atomic_add +.type OPENSSL_atomic_add,\@abi-omnipotent +.align 16 +OPENSSL_atomic_add: + movl ($arg1),%eax +.Lspin: leaq ($arg2,%rax),%r8 + .byte 0xf0 # lock + cmpxchgl %r8d,($arg1) + jne .Lspin + movl %r8d,%eax + .byte 0x48,0x98 # cltq/cdqe + ret +.size OPENSSL_atomic_add,.-OPENSSL_atomic_add + +.globl OPENSSL_rdtsc +.type OPENSSL_rdtsc,\@abi-omnipotent +.align 16 +OPENSSL_rdtsc: + rdtsc + shl \$32,%rdx + or %rdx,%rax + ret +.size OPENSSL_rdtsc,.-OPENSSL_rdtsc + +.globl OPENSSL_ia32_cpuid +.type OPENSSL_ia32_cpuid,\@function,1 +.align 16 +OPENSSL_ia32_cpuid: +.cfi_startproc + mov %rbx,%r8 # save %rbx +.cfi_register %rbx,%r8 + + xor %eax,%eax + mov %rax,8(%rdi) # clear extended feature flags + cpuid + mov %eax,%r11d # max value for standard query level + + xor %eax,%eax + cmp \$0x756e6547,%ebx # "Genu" + setne %al + mov %eax,%r9d + cmp \$0x49656e69,%edx # "ineI" + setne %al + or %eax,%r9d + cmp \$0x6c65746e,%ecx # "ntel" + setne %al + or %eax,%r9d # 0 indicates Intel CPU + jz .Lintel + + cmp \$0x68747541,%ebx # "Auth" + setne %al + mov %eax,%r10d + cmp \$0x69746E65,%edx # "enti" + setne %al + or %eax,%r10d + cmp \$0x444D4163,%ecx # "cAMD" + setne %al + or %eax,%r10d # 0 indicates AMD CPU + jnz .Lintel + + # AMD specific + mov \$0x80000000,%eax + cpuid + cmp \$0x80000001,%eax + jb .Lintel + mov %eax,%r10d + mov \$0x80000001,%eax + cpuid + or %ecx,%r9d + and \$0x00000801,%r9d # isolate AMD XOP bit, 1<<11 + + cmp \$0x80000008,%r10d + jb .Lintel + + mov \$0x80000008,%eax + cpuid + movzb %cl,%r10 # number of cores - 1 + inc %r10 # number of cores + + mov \$1,%eax + cpuid + bt \$28,%edx # test hyper-threading bit + jnc .Lgeneric + shr \$16,%ebx # number of logical processors + cmp %r10b,%bl + ja .Lgeneric + and \$0xefffffff,%edx # ~(1<<28) + jmp .Lgeneric + +.Lintel: + cmp \$4,%r11d + mov \$-1,%r10d + jb .Lnocacheinfo + + mov \$4,%eax + mov \$0,%ecx # query L1D + cpuid + mov %eax,%r10d + shr \$14,%r10d + and \$0xfff,%r10d # number of cores -1 per L1D + +.Lnocacheinfo: + mov \$1,%eax + cpuid + movd %eax,%xmm0 # put aside processor id + and \$0xbfefffff,%edx # force reserved bits to 0 + cmp \$0,%r9d + jne .Lnotintel + or \$0x40000000,%edx # set reserved bit#30 on Intel CPUs + and \$15,%ah + cmp \$15,%ah # examine Family ID + jne .LnotP4 + or \$0x00100000,%edx # set reserved bit#20 to engage RC4_CHAR +.LnotP4: + cmp \$6,%ah + jne .Lnotintel + and \$0x0fff0ff0,%eax + cmp \$0x00050670,%eax # Knights Landing + je .Lknights + cmp \$0x00080650,%eax # Knights Mill (according to sde) + jne .Lnotintel +.Lknights: + and \$0xfbffffff,%ecx # clear XSAVE flag to mimic Silvermont + +.Lnotintel: + bt \$28,%edx # test hyper-threading bit + jnc .Lgeneric + and \$0xefffffff,%edx # ~(1<<28) + cmp \$0,%r10d + je .Lgeneric + + or \$0x10000000,%edx # 1<<28 + shr \$16,%ebx + cmp \$1,%bl # see if cache is shared + ja .Lgeneric + and \$0xefffffff,%edx # ~(1<<28) +.Lgeneric: + and \$0x00000800,%r9d # isolate AMD XOP flag + and \$0xfffff7ff,%ecx + or %ecx,%r9d # merge AMD XOP flag + + mov %edx,%r10d # %r9d:%r10d is copy of %ecx:%edx + + cmp \$7,%r11d + jb .Lno_extended_info + mov \$7,%eax + xor %ecx,%ecx + cpuid + bt \$26,%r9d # check XSAVE bit, cleared on Knights + jc .Lnotknights + and \$0xfff7ffff,%ebx # clear ADCX/ADOX flag +.Lnotknights: + movd %xmm0,%eax # restore processor id + and \$0x0fff0ff0,%eax + cmp \$0x00050650,%eax # Skylake-X + jne .Lnotskylakex + and \$0xfffeffff,%ebx # ~(1<<16) + # suppress AVX512F flag on Skylake-X +.Lnotskylakex: + mov %ebx,8(%rdi) # save extended feature flags + mov %ecx,12(%rdi) +.Lno_extended_info: + + bt \$27,%r9d # check OSXSAVE bit + jnc .Lclear_avx + xor %ecx,%ecx # XCR0 + .byte 0x0f,0x01,0xd0 # xgetbv + and \$0xe6,%eax # isolate XMM, YMM and ZMM state support + cmp \$0xe6,%eax + je .Ldone + andl \$0x3fdeffff,8(%rdi) # ~(1<<31|1<<30|1<<21|1<<16) + # clear AVX512F+BW+VL+FIMA, all of + # them are EVEX-encoded, which requires + # ZMM state support even if one uses + # only XMM and YMM :-( + and \$6,%eax # isolate XMM and YMM state support + cmp \$6,%eax + je .Ldone +.Lclear_avx: + mov \$0xefffe7ff,%eax # ~(1<<28|1<<12|1<<11) + and %eax,%r9d # clear AVX, FMA and AMD XOP bits + mov \$0x3fdeffdf,%eax # ~(1<<31|1<<30|1<<21|1<<16|1<<5) + and %eax,8(%rdi) # clear AVX2 and AVX512* bits +.Ldone: + shl \$32,%r9 + mov %r10d,%eax + mov %r8,%rbx # restore %rbx +.cfi_restore %rbx + or %r9,%rax + ret +.cfi_endproc +.size OPENSSL_ia32_cpuid,.-OPENSSL_ia32_cpuid + +.globl OPENSSL_cleanse +.type OPENSSL_cleanse,\@abi-omnipotent +.align 16 +OPENSSL_cleanse: + xor %rax,%rax + cmp \$15,$arg2 + jae .Lot + cmp \$0,$arg2 + je .Lret +.Little: + mov %al,($arg1) + sub \$1,$arg2 + lea 1($arg1),$arg1 + jnz .Little +.Lret: + ret +.align 16 +.Lot: + test \$7,$arg1 + jz .Laligned + mov %al,($arg1) + lea -1($arg2),$arg2 + lea 1($arg1),$arg1 + jmp .Lot +.Laligned: + mov %rax,($arg1) + lea -8($arg2),$arg2 + test \$-8,$arg2 + lea 8($arg1),$arg1 + jnz .Laligned + cmp \$0,$arg2 + jne .Little + ret +.size OPENSSL_cleanse,.-OPENSSL_cleanse + +.globl CRYPTO_memcmp +.type CRYPTO_memcmp,\@abi-omnipotent +.align 16 +CRYPTO_memcmp: + xor %rax,%rax + xor %r10,%r10 + cmp \$0,$arg3 + je .Lno_data + cmp \$16,$arg3 + jne .Loop_cmp + mov ($arg1),%r10 + mov 8($arg1),%r11 + mov \$1,$arg3 + xor ($arg2),%r10 + xor 8($arg2),%r11 + or %r11,%r10 + cmovnz $arg3,%rax + ret + +.align 16 +.Loop_cmp: + mov ($arg1),%r10b + lea 1($arg1),$arg1 + xor ($arg2),%r10b + lea 1($arg2),$arg2 + or %r10b,%al + dec $arg3 + jnz .Loop_cmp + neg %rax + shr \$63,%rax +.Lno_data: + ret +.size CRYPTO_memcmp,.-CRYPTO_memcmp +___ + +print<<___ if (!$win64); +.globl OPENSSL_wipe_cpu +.type OPENSSL_wipe_cpu,\@abi-omnipotent +.align 16 +OPENSSL_wipe_cpu: + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 + pxor %xmm6,%xmm6 + pxor %xmm7,%xmm7 + pxor %xmm8,%xmm8 + pxor %xmm9,%xmm9 + pxor %xmm10,%xmm10 + pxor %xmm11,%xmm11 + pxor %xmm12,%xmm12 + pxor %xmm13,%xmm13 + pxor %xmm14,%xmm14 + pxor %xmm15,%xmm15 + xorq %rcx,%rcx + xorq %rdx,%rdx + xorq %rsi,%rsi + xorq %rdi,%rdi + xorq %r8,%r8 + xorq %r9,%r9 + xorq %r10,%r10 + xorq %r11,%r11 + leaq 8(%rsp),%rax + ret +.size OPENSSL_wipe_cpu,.-OPENSSL_wipe_cpu +___ +print<<___ if ($win64); +.globl OPENSSL_wipe_cpu +.type OPENSSL_wipe_cpu,\@abi-omnipotent +.align 16 +OPENSSL_wipe_cpu: + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 + xorq %rcx,%rcx + xorq %rdx,%rdx + xorq %r8,%r8 + xorq %r9,%r9 + xorq %r10,%r10 + xorq %r11,%r11 + leaq 8(%rsp),%rax + ret +.size OPENSSL_wipe_cpu,.-OPENSSL_wipe_cpu +___ +{ +my $out="%r10"; +my $cnt="%rcx"; +my $max="%r11"; +my $lasttick="%r8d"; +my $lastdiff="%r9d"; +my $redzone=win64?8:-8; + +print<<___; +.globl OPENSSL_instrument_bus +.type OPENSSL_instrument_bus,\@abi-omnipotent +.align 16 +OPENSSL_instrument_bus: + mov $arg1,$out # tribute to Win64 + mov $arg2,$cnt + mov $arg2,$max + + rdtsc # collect 1st tick + mov %eax,$lasttick # lasttick = tick + mov \$0,$lastdiff # lastdiff = 0 + clflush ($out) + .byte 0xf0 # lock + add $lastdiff,($out) + jmp .Loop +.align 16 +.Loop: rdtsc + mov %eax,%edx + sub $lasttick,%eax + mov %edx,$lasttick + mov %eax,$lastdiff + clflush ($out) + .byte 0xf0 # lock + add %eax,($out) + lea 4($out),$out + sub \$1,$cnt + jnz .Loop + + mov $max,%rax + ret +.size OPENSSL_instrument_bus,.-OPENSSL_instrument_bus + +.globl OPENSSL_instrument_bus2 +.type OPENSSL_instrument_bus2,\@abi-omnipotent +.align 16 +OPENSSL_instrument_bus2: + mov $arg1,$out # tribute to Win64 + mov $arg2,$cnt + mov $arg3,$max + mov $cnt,$redzone(%rsp) + + rdtsc # collect 1st tick + mov %eax,$lasttick # lasttick = tick + mov \$0,$lastdiff # lastdiff = 0 + + clflush ($out) + .byte 0xf0 # lock + add $lastdiff,($out) + + rdtsc # collect 1st diff + mov %eax,%edx + sub $lasttick,%eax # diff + mov %edx,$lasttick # lasttick = tick + mov %eax,$lastdiff # lastdiff = diff +.Loop2: + clflush ($out) + .byte 0xf0 # lock + add %eax,($out) # accumulate diff + + sub \$1,$max + jz .Ldone2 + + rdtsc + mov %eax,%edx + sub $lasttick,%eax # diff + mov %edx,$lasttick # lasttick = tick + cmp $lastdiff,%eax + mov %eax,$lastdiff # lastdiff = diff + mov \$0,%edx + setne %dl + sub %rdx,$cnt # conditional --$cnt + lea ($out,%rdx,4),$out # conditional ++$out + jnz .Loop2 + +.Ldone2: + mov $redzone(%rsp),%rax + sub $cnt,%rax + ret +.size OPENSSL_instrument_bus2,.-OPENSSL_instrument_bus2 +___ +} + +sub gen_random { +my $rdop = shift; +print<<___; +.globl OPENSSL_ia32_${rdop}_bytes +.type OPENSSL_ia32_${rdop}_bytes,\@abi-omnipotent +.align 16 +OPENSSL_ia32_${rdop}_bytes: + xor %rax, %rax # return value + cmp \$0,$arg2 + je .Ldone_${rdop}_bytes + + mov \$8,%r11 +.Loop_${rdop}_bytes: + ${rdop} %r10 + jc .Lbreak_${rdop}_bytes + dec %r11 + jnz .Loop_${rdop}_bytes + jmp .Ldone_${rdop}_bytes + +.align 16 +.Lbreak_${rdop}_bytes: + cmp \$8,$arg2 + jb .Ltail_${rdop}_bytes + mov %r10,($arg1) + lea 8($arg1),$arg1 + add \$8,%rax + sub \$8,$arg2 + jz .Ldone_${rdop}_bytes + mov \$8,%r11 + jmp .Loop_${rdop}_bytes + +.align 16 +.Ltail_${rdop}_bytes: + mov %r10b,($arg1) + lea 1($arg1),$arg1 + inc %rax + shr \$8,%r10 + dec $arg2 + jnz .Ltail_${rdop}_bytes + +.Ldone_${rdop}_bytes: + xor %r10,%r10 # Clear sensitive data from register + ret +.size OPENSSL_ia32_${rdop}_bytes,.-OPENSSL_ia32_${rdop}_bytes +___ +} +gen_random("rdrand"); +gen_random("rdseed"); + +close STDOUT; # flush diff --git a/trunk/3rdparty/openssl-1.1-fit/crypto/x86cpuid.pl b/trunk/3rdparty/openssl-1.1-fit/crypto/x86cpuid.pl new file mode 100644 index 000000000..d43dda4d9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/crypto/x86cpuid.pl @@ -0,0 +1,509 @@ +#! /usr/bin/env perl +# Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC, "${dir}perlasm", "perlasm"); +require "x86asm.pl"; + +$output = pop; +open OUT,">$output"; +*STDOUT=*OUT; + +&asm_init($ARGV[0]); + +for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); } + +&function_begin("OPENSSL_ia32_cpuid"); + &xor ("edx","edx"); + &pushf (); + &pop ("eax"); + &mov ("ecx","eax"); + &xor ("eax",1<<21); + &push ("eax"); + &popf (); + &pushf (); + &pop ("eax"); + &xor ("ecx","eax"); + &xor ("eax","eax"); + &mov ("esi",&wparam(0)); + &mov (&DWP(8,"esi"),"eax"); # clear extended feature flags + &bt ("ecx",21); + &jnc (&label("nocpuid")); + &cpuid (); + &mov ("edi","eax"); # max value for standard query level + + &xor ("eax","eax"); + &cmp ("ebx",0x756e6547); # "Genu" + &setne (&LB("eax")); + &mov ("ebp","eax"); + &cmp ("edx",0x49656e69); # "ineI" + &setne (&LB("eax")); + &or ("ebp","eax"); + &cmp ("ecx",0x6c65746e); # "ntel" + &setne (&LB("eax")); + &or ("ebp","eax"); # 0 indicates Intel CPU + &jz (&label("intel")); + + &cmp ("ebx",0x68747541); # "Auth" + &setne (&LB("eax")); + &mov ("esi","eax"); + &cmp ("edx",0x69746E65); # "enti" + &setne (&LB("eax")); + &or ("esi","eax"); + &cmp ("ecx",0x444D4163); # "cAMD" + &setne (&LB("eax")); + &or ("esi","eax"); # 0 indicates AMD CPU + &jnz (&label("intel")); + + # AMD specific + &mov ("eax",0x80000000); + &cpuid (); + &cmp ("eax",0x80000001); + &jb (&label("intel")); + &mov ("esi","eax"); + &mov ("eax",0x80000001); + &cpuid (); + &or ("ebp","ecx"); + &and ("ebp",1<<11|1); # isolate XOP bit + &cmp ("esi",0x80000008); + &jb (&label("intel")); + + &mov ("eax",0x80000008); + &cpuid (); + &movz ("esi",&LB("ecx")); # number of cores - 1 + &inc ("esi"); # number of cores + + &mov ("eax",1); + &xor ("ecx","ecx"); + &cpuid (); + &bt ("edx",28); + &jnc (&label("generic")); + &shr ("ebx",16); + &and ("ebx",0xff); + &cmp ("ebx","esi"); + &ja (&label("generic")); + &and ("edx",0xefffffff); # clear hyper-threading bit + &jmp (&label("generic")); + +&set_label("intel"); + &cmp ("edi",4); + &mov ("esi",-1); + &jb (&label("nocacheinfo")); + + &mov ("eax",4); + &mov ("ecx",0); # query L1D + &cpuid (); + &mov ("esi","eax"); + &shr ("esi",14); + &and ("esi",0xfff); # number of cores -1 per L1D + +&set_label("nocacheinfo"); + &mov ("eax",1); + &xor ("ecx","ecx"); + &cpuid (); + &and ("edx",0xbfefffff); # force reserved bits #20, #30 to 0 + &cmp ("ebp",0); + &jne (&label("notintel")); + &or ("edx",1<<30); # set reserved bit#30 on Intel CPUs + &and (&HB("eax"),15); # family ID + &cmp (&HB("eax"),15); # P4? + &jne (&label("notintel")); + &or ("edx",1<<20); # set reserved bit#20 to engage RC4_CHAR +&set_label("notintel"); + &bt ("edx",28); # test hyper-threading bit + &jnc (&label("generic")); + &and ("edx",0xefffffff); + &cmp ("esi",0); + &je (&label("generic")); + + &or ("edx",0x10000000); + &shr ("ebx",16); + &cmp (&LB("ebx"),1); + &ja (&label("generic")); + &and ("edx",0xefffffff); # clear hyper-threading bit if not + +&set_label("generic"); + &and ("ebp",1<<11); # isolate AMD XOP flag + &and ("ecx",0xfffff7ff); # force 11th bit to 0 + &mov ("esi","edx"); # %ebp:%esi is copy of %ecx:%edx + &or ("ebp","ecx"); # merge AMD XOP flag + + &cmp ("edi",7); + &mov ("edi",&wparam(0)); + &jb (&label("no_extended_info")); + &mov ("eax",7); + &xor ("ecx","ecx"); + &cpuid (); + &mov (&DWP(8,"edi"),"ebx"); # save extended feature flag +&set_label("no_extended_info"); + + &bt ("ebp",27); # check OSXSAVE bit + &jnc (&label("clear_avx")); + &xor ("ecx","ecx"); + &data_byte(0x0f,0x01,0xd0); # xgetbv + &and ("eax",6); + &cmp ("eax",6); + &je (&label("done")); + &cmp ("eax",2); + &je (&label("clear_avx")); +&set_label("clear_xmm"); + &and ("ebp",0xfdfffffd); # clear AESNI and PCLMULQDQ bits + &and ("esi",0xfeffffff); # clear FXSR +&set_label("clear_avx"); + &and ("ebp",0xefffe7ff); # clear AVX, FMA and AMD XOP bits + &and (&DWP(8,"edi"),0xffffffdf); # clear AVX2 +&set_label("done"); + &mov ("eax","esi"); + &mov ("edx","ebp"); +&set_label("nocpuid"); +&function_end("OPENSSL_ia32_cpuid"); + +&external_label("OPENSSL_ia32cap_P"); + +&function_begin_B("OPENSSL_rdtsc","EXTRN\t_OPENSSL_ia32cap_P:DWORD"); + &xor ("eax","eax"); + &xor ("edx","edx"); + &picmeup("ecx","OPENSSL_ia32cap_P"); + &bt (&DWP(0,"ecx"),4); + &jnc (&label("notsc")); + &rdtsc (); +&set_label("notsc"); + &ret (); +&function_end_B("OPENSSL_rdtsc"); + +# This works in Ring 0 only [read DJGPP+MS-DOS+privileged DPMI host], +# but it's safe to call it on any [supported] 32-bit platform... +# Just check for [non-]zero return value... +&function_begin_B("OPENSSL_instrument_halt","EXTRN\t_OPENSSL_ia32cap_P:DWORD"); + &picmeup("ecx","OPENSSL_ia32cap_P"); + &bt (&DWP(0,"ecx"),4); + &jnc (&label("nohalt")); # no TSC + + &data_word(0x9058900e); # push %cs; pop %eax + &and ("eax",3); + &jnz (&label("nohalt")); # not enough privileges + + &pushf (); + &pop ("eax"); + &bt ("eax",9); + &jnc (&label("nohalt")); # interrupts are disabled + + &rdtsc (); + &push ("edx"); + &push ("eax"); + &halt (); + &rdtsc (); + + &sub ("eax",&DWP(0,"esp")); + &sbb ("edx",&DWP(4,"esp")); + &add ("esp",8); + &ret (); + +&set_label("nohalt"); + &xor ("eax","eax"); + &xor ("edx","edx"); + &ret (); +&function_end_B("OPENSSL_instrument_halt"); + +# Essentially there is only one use for this function. Under DJGPP: +# +# #include +# ... +# i=OPENSSL_far_spin(_dos_ds,0x46c); +# ... +# to obtain the number of spins till closest timer interrupt. + +&function_begin_B("OPENSSL_far_spin"); + &pushf (); + &pop ("eax"); + &bt ("eax",9); + &jnc (&label("nospin")); # interrupts are disabled + + &mov ("eax",&DWP(4,"esp")); + &mov ("ecx",&DWP(8,"esp")); + &data_word (0x90d88e1e); # push %ds, mov %eax,%ds + &xor ("eax","eax"); + &mov ("edx",&DWP(0,"ecx")); + &jmp (&label("spin")); + + &align (16); +&set_label("spin"); + &inc ("eax"); + &cmp ("edx",&DWP(0,"ecx")); + &je (&label("spin")); + + &data_word (0x1f909090); # pop %ds + &ret (); + +&set_label("nospin"); + &xor ("eax","eax"); + &xor ("edx","edx"); + &ret (); +&function_end_B("OPENSSL_far_spin"); + +&function_begin_B("OPENSSL_wipe_cpu","EXTRN\t_OPENSSL_ia32cap_P:DWORD"); + &xor ("eax","eax"); + &xor ("edx","edx"); + &picmeup("ecx","OPENSSL_ia32cap_P"); + &mov ("ecx",&DWP(0,"ecx")); + &bt (&DWP(0,"ecx"),1); + &jnc (&label("no_x87")); + if ($sse2) { + &and ("ecx",1<<26|1<<24); # check SSE2 and FXSR bits + &cmp ("ecx",1<<26|1<<24); + &jne (&label("no_sse2")); + &pxor ("xmm0","xmm0"); + &pxor ("xmm1","xmm1"); + &pxor ("xmm2","xmm2"); + &pxor ("xmm3","xmm3"); + &pxor ("xmm4","xmm4"); + &pxor ("xmm5","xmm5"); + &pxor ("xmm6","xmm6"); + &pxor ("xmm7","xmm7"); + &set_label("no_sse2"); + } + # just a bunch of fldz to zap the fp/mm bank followed by finit... + &data_word(0xeed9eed9,0xeed9eed9,0xeed9eed9,0xeed9eed9,0x90e3db9b); +&set_label("no_x87"); + &lea ("eax",&DWP(4,"esp")); + &ret (); +&function_end_B("OPENSSL_wipe_cpu"); + +&function_begin_B("OPENSSL_atomic_add"); + &mov ("edx",&DWP(4,"esp")); # fetch the pointer, 1st arg + &mov ("ecx",&DWP(8,"esp")); # fetch the increment, 2nd arg + &push ("ebx"); + &nop (); + &mov ("eax",&DWP(0,"edx")); +&set_label("spin"); + &lea ("ebx",&DWP(0,"eax","ecx")); + &nop (); + &data_word(0x1ab10ff0); # lock; cmpxchg %ebx,(%edx) # %eax is involved and is always reloaded + &jne (&label("spin")); + &mov ("eax","ebx"); # OpenSSL expects the new value + &pop ("ebx"); + &ret (); +&function_end_B("OPENSSL_atomic_add"); + +&function_begin_B("OPENSSL_cleanse"); + &mov ("edx",&wparam(0)); + &mov ("ecx",&wparam(1)); + &xor ("eax","eax"); + &cmp ("ecx",7); + &jae (&label("lot")); + &cmp ("ecx",0); + &je (&label("ret")); +&set_label("little"); + &mov (&BP(0,"edx"),"al"); + &sub ("ecx",1); + &lea ("edx",&DWP(1,"edx")); + &jnz (&label("little")); +&set_label("ret"); + &ret (); + +&set_label("lot",16); + &test ("edx",3); + &jz (&label("aligned")); + &mov (&BP(0,"edx"),"al"); + &lea ("ecx",&DWP(-1,"ecx")); + &lea ("edx",&DWP(1,"edx")); + &jmp (&label("lot")); +&set_label("aligned"); + &mov (&DWP(0,"edx"),"eax"); + &lea ("ecx",&DWP(-4,"ecx")); + &test ("ecx",-4); + &lea ("edx",&DWP(4,"edx")); + &jnz (&label("aligned")); + &cmp ("ecx",0); + &jne (&label("little")); + &ret (); +&function_end_B("OPENSSL_cleanse"); + +&function_begin_B("CRYPTO_memcmp"); + &push ("esi"); + &push ("edi"); + &mov ("esi",&wparam(0)); + &mov ("edi",&wparam(1)); + &mov ("ecx",&wparam(2)); + &xor ("eax","eax"); + &xor ("edx","edx"); + &cmp ("ecx",0); + &je (&label("no_data")); +&set_label("loop"); + &mov ("dl",&BP(0,"esi")); + &lea ("esi",&DWP(1,"esi")); + &xor ("dl",&BP(0,"edi")); + &lea ("edi",&DWP(1,"edi")); + &or ("al","dl"); + &dec ("ecx"); + &jnz (&label("loop")); + &neg ("eax"); + &shr ("eax",31); +&set_label("no_data"); + &pop ("edi"); + &pop ("esi"); + &ret (); +&function_end_B("CRYPTO_memcmp"); +{ +my $lasttick = "esi"; +my $lastdiff = "ebx"; +my $out = "edi"; +my $cnt = "ecx"; +my $max = "ebp"; + +&function_begin("OPENSSL_instrument_bus"); + &mov ("eax",0); + if ($sse2) { + &picmeup("edx","OPENSSL_ia32cap_P"); + &bt (&DWP(0,"edx"),4); + &jnc (&label("nogo")); # no TSC + &bt (&DWP(0,"edx"),19); + &jnc (&label("nogo")); # no CLFLUSH + + &mov ($out,&wparam(0)); # load arguments + &mov ($cnt,&wparam(1)); + + # collect 1st tick + &rdtsc (); + &mov ($lasttick,"eax"); # lasttick = tick + &mov ($lastdiff,0); # lastdiff = 0 + &clflush(&DWP(0,$out)); + &data_byte(0xf0); # lock + &add (&DWP(0,$out),$lastdiff); + &jmp (&label("loop")); + +&set_label("loop",16); + &rdtsc (); + &mov ("edx","eax"); # put aside tick (yes, I neglect edx) + &sub ("eax",$lasttick); # diff + &mov ($lasttick,"edx"); # lasttick = tick + &mov ($lastdiff,"eax"); # lastdiff = diff + &clflush(&DWP(0,$out)); + &data_byte(0xf0); # lock + &add (&DWP(0,$out),"eax"); # accumulate diff + &lea ($out,&DWP(4,$out)); # ++$out + &sub ($cnt,1); # --$cnt + &jnz (&label("loop")); + + &mov ("eax",&wparam(1)); +&set_label("nogo"); + } +&function_end("OPENSSL_instrument_bus"); + +&function_begin("OPENSSL_instrument_bus2"); + &mov ("eax",0); + if ($sse2) { + &picmeup("edx","OPENSSL_ia32cap_P"); + &bt (&DWP(0,"edx"),4); + &jnc (&label("nogo")); # no TSC + &bt (&DWP(0,"edx"),19); + &jnc (&label("nogo")); # no CLFLUSH + + &mov ($out,&wparam(0)); # load arguments + &mov ($cnt,&wparam(1)); + &mov ($max,&wparam(2)); + + &rdtsc (); # collect 1st tick + &mov ($lasttick,"eax"); # lasttick = tick + &mov ($lastdiff,0); # lastdiff = 0 + + &clflush(&DWP(0,$out)); + &data_byte(0xf0); # lock + &add (&DWP(0,$out),$lastdiff); + + &rdtsc (); # collect 1st diff + &mov ("edx","eax"); # put aside tick (yes, I neglect edx) + &sub ("eax",$lasttick); # diff + &mov ($lasttick,"edx"); # lasttick = tick + &mov ($lastdiff,"eax"); # lastdiff = diff + &jmp (&label("loop2")); + +&set_label("loop2",16); + &clflush(&DWP(0,$out)); + &data_byte(0xf0); # lock + &add (&DWP(0,$out),"eax"); # accumulate diff + + &sub ($max,1); + &jz (&label("done2")); + + &rdtsc (); + &mov ("edx","eax"); # put aside tick (yes, I neglect edx) + &sub ("eax",$lasttick); # diff + &mov ($lasttick,"edx"); # lasttick = tick + &cmp ("eax",$lastdiff); + &mov ($lastdiff,"eax"); # lastdiff = diff + &mov ("edx",0); + &setne ("dl"); + &sub ($cnt,"edx"); # conditional --$cnt + &lea ($out,&DWP(0,$out,"edx",4)); # conditional ++$out + &jnz (&label("loop2")); + +&set_label("done2"); + &mov ("eax",&wparam(1)); + &sub ("eax",$cnt); +&set_label("nogo"); + } +&function_end("OPENSSL_instrument_bus2"); +} + +sub gen_random { +my $rdop = shift; +&function_begin_B("OPENSSL_ia32_${rdop}_bytes"); + &push ("edi"); + &push ("ebx"); + &xor ("eax","eax"); # return value + &mov ("edi",&wparam(0)); + &mov ("ebx",&wparam(1)); + + &cmp ("ebx",0); + &je (&label("done")); + + &mov ("ecx",8); +&set_label("loop"); + &${rdop}("edx"); + &jc (&label("break")); + &loop (&label("loop")); + &jmp (&label("done")); + +&set_label("break",16); + &cmp ("ebx",4); + &jb (&label("tail")); + &mov (&DWP(0,"edi"),"edx"); + &lea ("edi",&DWP(4,"edi")); + &add ("eax",4); + &sub ("ebx",4); + &jz (&label("done")); + &mov ("ecx",8); + &jmp (&label("loop")); + +&set_label("tail",16); + &mov (&BP(0,"edi"),"dl"); + &lea ("edi",&DWP(1,"edi")); + &inc ("eax"); + &shr ("edx",8); + &dec ("ebx"); + &jnz (&label("tail")); + +&set_label("done"); + &xor ("edx","edx"); # Clear random value from registers + &pop ("ebx"); + &pop ("edi"); + &ret (); +&function_end_B("OPENSSL_ia32_${rdop}_bytes"); +} +&gen_random("rdrand"); +&gen_random("rdseed"); + +&initseg("OPENSSL_cpuid_setup"); + +&hidden("OPENSSL_cpuid_setup"); +&hidden("OPENSSL_ia32cap_P"); + +&asm_finish(); + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/e_os.h b/trunk/3rdparty/openssl-1.1-fit/e_os.h new file mode 100644 index 000000000..8e6efa961 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/e_os.h @@ -0,0 +1,334 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_E_OS_H +# define HEADER_E_OS_H + +# include +# include + +# include +# include +# include "internal/nelem.h" + +/* + * contains what we can justify to make visible to the + * outside; this file e_os.h is not part of the exported interface. + */ + +# ifndef DEVRANDOM +/* + * set this to a comma-separated list of 'random' device files to try out. By + * default, we will try to read at least one of these files + */ +# if defined(__s390__) +# define DEVRANDOM "/dev/prandom","/dev/urandom","/dev/hwrng","/dev/random" +# else +# define DEVRANDOM "/dev/urandom","/dev/random","/dev/srandom" +# endif +# endif +# if !defined(OPENSSL_NO_EGD) && !defined(DEVRANDOM_EGD) +/* + * set this to a comma-separated list of 'egd' sockets to try out. These + * sockets will be tried in the order listed in case accessing the device + * files listed in DEVRANDOM did not return enough randomness. + */ +# define DEVRANDOM_EGD "/var/run/egd-pool","/dev/egd-pool","/etc/egd-pool","/etc/entropy" +# endif + +# if defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI) +# define NO_CHMOD +# define NO_SYSLOG +# endif + +# define get_last_sys_error() errno +# define clear_sys_error() errno=0 +# define set_sys_error(e) errno=(e) + +/******************************************************************** + The Microsoft section + ********************************************************************/ +# if defined(OPENSSL_SYS_WIN32) && !defined(WIN32) +# define WIN32 +# endif +# if defined(OPENSSL_SYS_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +# endif +# if defined(OPENSSL_SYS_MSDOS) && !defined(MSDOS) +# define MSDOS +# endif + +# ifdef WIN32 +# undef get_last_sys_error +# undef clear_sys_error +# undef set_sys_error +# define get_last_sys_error() GetLastError() +# define clear_sys_error() SetLastError(0) +# define set_sys_error(e) SetLastError(e) +# if !defined(WINNT) +# define WIN_CONSOLE_BUG +# endif +# else +# endif + +# if (defined(WINDOWS) || defined(MSDOS)) + +# ifdef __DJGPP__ +# include +# include +# define _setmode setmode +# define _O_TEXT O_TEXT +# define _O_BINARY O_BINARY +# define HAS_LFN_SUPPORT(name) (pathconf((name), _PC_NAME_MAX) > 12) +# undef DEVRANDOM_EGD /* Neither MS-DOS nor FreeDOS provide 'egd' sockets. */ +# undef DEVRANDOM +# define DEVRANDOM "/dev/urandom\x24" +# endif /* __DJGPP__ */ + +# ifndef S_IFDIR +# define S_IFDIR _S_IFDIR +# endif + +# ifndef S_IFMT +# define S_IFMT _S_IFMT +# endif + +# if !defined(WINNT) && !defined(__DJGPP__) +# define NO_SYSLOG +# endif + +# ifdef WINDOWS +# if !defined(_WIN32_WCE) && !defined(_WIN32_WINNT) + /* + * Defining _WIN32_WINNT here in e_os.h implies certain "discipline." + * Most notably we ought to check for availability of each specific + * routine that was introduced after denoted _WIN32_WINNT with + * GetProcAddress(). Normally newer functions are masked with higher + * _WIN32_WINNT in SDK headers. So that if you wish to use them in + * some module, you'd need to override _WIN32_WINNT definition in + * the target module in order to "reach for" prototypes, but replace + * calls to new functions with indirect calls. Alternatively it + * might be possible to achieve the goal by /DELAYLOAD-ing .DLLs + * and check for current OS version instead. + */ +# define _WIN32_WINNT 0x0501 +# endif +# if defined(_WIN32_WINNT) || defined(_WIN32_WCE) + /* + * Just like defining _WIN32_WINNT including winsock2.h implies + * certain "discipline" for maintaining [broad] binary compatibility. + * As long as structures are invariant among Winsock versions, + * it's sufficient to check for specific Winsock2 API availability + * at run-time [DSO_global_lookup is recommended]... + */ +# include +# include + /* yes, they have to be #included prior to */ +# endif +# include +# include +# include +# include +# if defined(_WIN32_WCE) && !defined(EACCES) +# define EACCES 13 +# endif +# include +# ifdef _WIN64 +# define strlen(s) _strlen31(s) +/* cut strings to 2GB */ +static __inline unsigned int _strlen31(const char *str) +{ + unsigned int len = 0; + while (*str && len < 0x80000000U) + str++, len++; + return len & 0x7FFFFFFF; +} +# endif +# include +# if defined(_MSC_VER) && !defined(_WIN32_WCE) && !defined(_DLL) && defined(stdin) +# if _MSC_VER>=1300 && _MSC_VER<1600 +# undef stdin +# undef stdout +# undef stderr +FILE *__iob_func(); +# define stdin (&__iob_func()[0]) +# define stdout (&__iob_func()[1]) +# define stderr (&__iob_func()[2]) +# elif _MSC_VER<1300 && defined(I_CAN_LIVE_WITH_LNK4049) +# undef stdin +# undef stdout +# undef stderr + /* + * pre-1300 has __p__iob(), but it's available only in msvcrt.lib, + * or in other words with /MD. Declaring implicit import, i.e. with + * _imp_ prefix, works correctly with all compiler options, but + * without /MD results in LINK warning LNK4049: 'locally defined + * symbol "__iob" imported'. + */ +extern FILE *_imp___iob; +# define stdin (&_imp___iob[0]) +# define stdout (&_imp___iob[1]) +# define stderr (&_imp___iob[2]) +# endif +# endif +# endif +# include +# include + +# ifdef OPENSSL_SYS_WINCE +# define OPENSSL_NO_POSIX_IO +# endif + +# define EXIT(n) exit(n) +# define LIST_SEPARATOR_CHAR ';' +# ifndef W_OK +# define W_OK 2 +# endif +# ifndef R_OK +# define R_OK 4 +# endif +# ifdef OPENSSL_SYS_WINCE +# define DEFAULT_HOME "" +# else +# define DEFAULT_HOME "C:" +# endif + +/* Avoid Visual Studio 13 GetVersion deprecated problems */ +# if defined(_MSC_VER) && _MSC_VER>=1800 +# define check_winnt() (1) +# define check_win_minplat(x) (1) +# else +# define check_winnt() (GetVersion() < 0x80000000) +# define check_win_minplat(x) (LOBYTE(LOWORD(GetVersion())) >= (x)) +# endif + +# else /* The non-microsoft world */ + +# if defined(OPENSSL_SYS_VXWORKS) +# include +# else +# include +# endif + +# ifdef OPENSSL_SYS_VMS +# define VMS 1 + /* + * some programs don't include stdlib, so exit() and others give implicit + * function warnings + */ +# include +# if defined(__DECC) +# include +# else +# include +# endif +# define LIST_SEPARATOR_CHAR ',' + /* We don't have any well-defined random devices on VMS, yet... */ +# undef DEVRANDOM + /*- + We need to do this since VMS has the following coding on status codes: + + Bits 0-2: status type: 0 = warning, 1 = success, 2 = error, 3 = info ... + The important thing to know is that odd numbers are considered + good, while even ones are considered errors. + Bits 3-15: actual status number + Bits 16-27: facility number. 0 is considered "unknown" + Bits 28-31: control bits. If bit 28 is set, the shell won't try to + output the message (which, for random codes, just looks ugly) + + So, what we do here is to change 0 to 1 to get the default success status, + and everything else is shifted up to fit into the status number field, and + the status is tagged as an error, which is what is wanted here. + + Finally, we add the VMS C facility code 0x35a000, because there are some + programs, such as Perl, that will reinterpret the code back to something + POSIX. 'man perlvms' explains it further. + + NOTE: the perlvms manual wants to turn all codes 2 to 255 into success + codes (status type = 1). I couldn't disagree more. Fortunately, the + status type doesn't seem to bother Perl. + -- Richard Levitte + */ +# define EXIT(n) exit((n) ? (((n) << 3) | 2 | 0x10000000 | 0x35a000) : 1) + +# define DEFAULT_HOME "SYS$LOGIN:" + +# else + /* !defined VMS */ +# ifdef OPENSSL_UNISTD +# include OPENSSL_UNISTD +# else +# include +# endif +# include +# ifdef OPENSSL_SYS_WIN32_CYGWIN +# include +# include +# endif + +# define LIST_SEPARATOR_CHAR ':' +# define EXIT(n) exit(n) +# endif + +# endif + +/***********************************************/ + +# if defined(OPENSSL_SYS_WINDOWS) +# define strcasecmp _stricmp +# define strncasecmp _strnicmp +# if (_MSC_VER >= 1310) +# define open _open +# define fdopen _fdopen +# define close _close +# ifndef strdup +# define strdup _strdup +# endif +# define unlink _unlink +# define fileno _fileno +# endif +# else +# include +# endif + +/* vxworks */ +# if defined(OPENSSL_SYS_VXWORKS) +# include +# include +# include +# include +# include +# include + +# define TTY_STRUCT int +# define sleep(a) taskDelay((a) * sysClkRateGet()) + +/* + * NOTE: these are implemented by helpers in database app! if the database is + * not linked, we need to implement them elsewhere + */ +struct hostent *gethostbyname(const char *name); +struct hostent *gethostbyaddr(const char *addr, int length, int type); +struct servent *getservbyname(const char *name, const char *proto); + +# endif +/* end vxworks */ + +# ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +# define CRYPTO_memcmp memcmp +# endif + +/* unistd.h defines _POSIX_VERSION */ +# if !defined(OPENSSL_NO_SECURE_MEMORY) && defined(OPENSSL_SYS_UNIX) \ + && ( (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L) \ + || defined(__sun) || defined(__hpux) || defined(__sgi) \ + || defined(__osf__) ) +# define OPENSSL_SECURE_MEMORY /* secure memory is implemented */ +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/engines/asm/e_padlock-x86.pl b/trunk/3rdparty/openssl-1.1-fit/engines/asm/e_padlock-x86.pl new file mode 100644 index 000000000..5b097ce3e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/engines/asm/e_padlock-x86.pl @@ -0,0 +1,627 @@ +#! /usr/bin/env perl +# Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# September 2011 +# +# Assembler helpers for Padlock engine. Compared to original engine +# version relying on inline assembler and compiled with gcc 3.4.6 it +# was measured to provide ~100% improvement on misaligned data in ECB +# mode and ~75% in CBC mode. For aligned data improvement can be +# observed for short inputs only, e.g. 45% for 64-byte messages in +# ECB mode, 20% in CBC. Difference in performance for aligned vs. +# misaligned data depends on misalignment and is either ~1.8x or 2.9x. +# These are approximately same factors as for hardware support, so +# there is little reason to rely on the latter. On the contrary, it +# might actually hurt performance in mixture of aligned and misaligned +# buffers, because a) if you choose to flip 'align' flag in control +# word on per-buffer basis, then you'd have to reload key context, +# which incurs penalty; b) if you choose to set 'align' flag +# permanently, it limits performance even for aligned data to ~1/2. +# All above mentioned results were collected on 1.5GHz C7. Nano on the +# other hand handles unaligned data more gracefully. Depending on +# algorithm and how unaligned data is, hardware can be up to 70% more +# efficient than below software alignment procedures, nor does 'align' +# flag have affect on aligned performance [if has any meaning at all]. +# Therefore suggestion is to unconditionally set 'align' flag on Nano +# for optimal performance. + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../crypto/perlasm"); +require "x86asm.pl"; + +$output=pop; +open STDOUT,">$output"; + +&asm_init($ARGV[0]); + +%PADLOCK_PREFETCH=(ecb=>128, cbc=>64); # prefetch errata +$PADLOCK_CHUNK=512; # Must be a power of 2 larger than 16 + +$ctx="edx"; +$out="edi"; +$inp="esi"; +$len="ecx"; +$chunk="ebx"; + +&function_begin_B("padlock_capability"); + &push ("ebx"); + &pushf (); + &pop ("eax"); + &mov ("ecx","eax"); + &xor ("eax",1<<21); + &push ("eax"); + &popf (); + &pushf (); + &pop ("eax"); + &xor ("ecx","eax"); + &xor ("eax","eax"); + &bt ("ecx",21); + &jnc (&label("noluck")); + &cpuid (); + &xor ("eax","eax"); + &cmp ("ebx","0x".unpack("H*",'tneC')); + &jne (&label("zhaoxin")); + &cmp ("edx","0x".unpack("H*",'Hrua')); + &jne (&label("noluck")); + &cmp ("ecx","0x".unpack("H*",'slua')); + &jne (&label("noluck")); + &jmp (&label("zhaoxinEnd")); +&set_label("zhaoxin"); + &cmp ("ebx","0x".unpack("H*",'hS ')); + &jne (&label("noluck")); + &cmp ("edx","0x".unpack("H*",'hgna')); + &jne (&label("noluck")); + &cmp ("ecx","0x".unpack("H*",' ia')); + &jne (&label("noluck")); +&set_label("zhaoxinEnd"); + &mov ("eax",0xC0000000); + &cpuid (); + &mov ("edx","eax"); + &xor ("eax","eax"); + &cmp ("edx",0xC0000001); + &jb (&label("noluck")); + &mov ("eax",1); + &cpuid (); + &or ("eax",0x0f); + &xor ("ebx","ebx"); + &and ("eax",0x0fff); + &cmp ("eax",0x06ff); # check for Nano + &sete ("bl"); + &mov ("eax",0xC0000001); + &push ("ebx"); + &cpuid (); + &pop ("ebx"); + &mov ("eax","edx"); + &shl ("ebx",4); # bit#4 denotes Nano + &and ("eax",0xffffffef); + &or ("eax","ebx") +&set_label("noluck"); + &pop ("ebx"); + &ret (); +&function_end_B("padlock_capability") + +&function_begin_B("padlock_key_bswap"); + &mov ("edx",&wparam(0)); + &mov ("ecx",&DWP(240,"edx")); +&set_label("bswap_loop"); + &mov ("eax",&DWP(0,"edx")); + &bswap ("eax"); + &mov (&DWP(0,"edx"),"eax"); + &lea ("edx",&DWP(4,"edx")); + &sub ("ecx",1); + &jnz (&label("bswap_loop")); + &ret (); +&function_end_B("padlock_key_bswap"); + +# This is heuristic key context tracing. At first one +# believes that one should use atomic swap instructions, +# but it's not actually necessary. Point is that if +# padlock_saved_context was changed by another thread +# after we've read it and before we compare it with ctx, +# our key *shall* be reloaded upon thread context switch +# and we are therefore set in either case... +&static_label("padlock_saved_context"); + +&function_begin_B("padlock_verify_context"); + &mov ($ctx,&wparam(0)); + &lea ("eax",($::win32 or $::coff) ? &DWP(&label("padlock_saved_context")) : + &DWP(&label("padlock_saved_context")."-".&label("verify_pic_point"))); + &pushf (); + &call ("_padlock_verify_ctx"); +&set_label("verify_pic_point"); + &lea ("esp",&DWP(4,"esp")); + &ret (); +&function_end_B("padlock_verify_context"); + +&function_begin_B("_padlock_verify_ctx"); + &add ("eax",&DWP(0,"esp")) if(!($::win32 or $::coff));# &padlock_saved_context + &bt (&DWP(4,"esp"),30); # eflags + &jnc (&label("verified")); + &cmp ($ctx,&DWP(0,"eax")); + &je (&label("verified")); + &pushf (); + &popf (); +&set_label("verified"); + &mov (&DWP(0,"eax"),$ctx); + &ret (); +&function_end_B("_padlock_verify_ctx"); + +&function_begin_B("padlock_reload_key"); + &pushf (); + &popf (); + &ret (); +&function_end_B("padlock_reload_key"); + +&function_begin_B("padlock_aes_block"); + &push ("edi"); + &push ("esi"); + &push ("ebx"); + &mov ($out,&wparam(0)); # must be 16-byte aligned + &mov ($inp,&wparam(1)); # must be 16-byte aligned + &mov ($ctx,&wparam(2)); + &mov ($len,1); + &lea ("ebx",&DWP(32,$ctx)); # key + &lea ($ctx,&DWP(16,$ctx)); # control word + &data_byte(0xf3,0x0f,0xa7,0xc8); # rep xcryptecb + &pop ("ebx"); + &pop ("esi"); + &pop ("edi"); + &ret (); +&function_end_B("padlock_aes_block"); + +sub generate_mode { +my ($mode,$opcode) = @_; +# int padlock_$mode_encrypt(void *out, const void *inp, +# struct padlock_cipher_data *ctx, size_t len); +&function_begin("padlock_${mode}_encrypt"); + &mov ($out,&wparam(0)); + &mov ($inp,&wparam(1)); + &mov ($ctx,&wparam(2)); + &mov ($len,&wparam(3)); + &test ($ctx,15); + &jnz (&label("${mode}_abort")); + &test ($len,15); + &jnz (&label("${mode}_abort")); + &lea ("eax",($::win32 or $::coff) ? &DWP(&label("padlock_saved_context")) : + &DWP(&label("padlock_saved_context")."-".&label("${mode}_pic_point"))); + &pushf (); + &cld (); + &call ("_padlock_verify_ctx"); +&set_label("${mode}_pic_point"); + &lea ($ctx,&DWP(16,$ctx)); # control word + &xor ("eax","eax"); + if ($mode eq "ctr32") { + &movq ("mm0",&QWP(-16,$ctx)); # load [upper part of] counter + } else { + &xor ("ebx","ebx"); + &test (&DWP(0,$ctx),1<<5); # align bit in control word + &jnz (&label("${mode}_aligned")); + &test ($out,0x0f); + &setz ("al"); # !out_misaligned + &test ($inp,0x0f); + &setz ("bl"); # !inp_misaligned + &test ("eax","ebx"); + &jnz (&label("${mode}_aligned")); + &neg ("eax"); + } + &mov ($chunk,$PADLOCK_CHUNK); + ¬ ("eax"); # out_misaligned?-1:0 + &lea ("ebp",&DWP(-24,"esp")); + &cmp ($len,$chunk); + &cmovc ($chunk,$len); # chunk=len>PADLOCK_CHUNK?PADLOCK_CHUNK:len + &and ("eax",$chunk); # out_misaligned?chunk:0 + &mov ($chunk,$len); + &neg ("eax"); + &and ($chunk,$PADLOCK_CHUNK-1); # chunk=len%PADLOCK_CHUNK + &lea ("esp",&DWP(0,"eax","ebp")); # alloca + &mov ("eax",$PADLOCK_CHUNK); + &cmovz ($chunk,"eax"); # chunk=chunk?:PADLOCK_CHUNK + &mov ("eax","ebp"); + &and ("ebp",-16); + &and ("esp",-16); + &mov (&DWP(16,"ebp"),"eax"); + if ($PADLOCK_PREFETCH{$mode}) { + &cmp ($len,$chunk); + &ja (&label("${mode}_loop")); + &mov ("eax",$inp); # check if prefetch crosses page + &cmp ("ebp","esp"); + &cmove ("eax",$out); + &add ("eax",$len); + &neg ("eax"); + &and ("eax",0xfff); # distance to page boundary + &cmp ("eax",$PADLOCK_PREFETCH{$mode}); + &mov ("eax",-$PADLOCK_PREFETCH{$mode}); + &cmovae ("eax",$chunk); # mask=distanceExceptionCode == STATUS_ACCESS_VIOLATION + &jne (&label("ret")); + &add (&DWP(184,"ecx"),4); # skip over rep sha* + &mov ("eax",0); # ExceptionContinueExecution +&set_label("ret"); + &ret (); +&function_end_B("_win32_segv_handler"); +&safeseh("_win32_segv_handler") if ($::win32); + +&function_begin_B("padlock_sha1_oneshot"); + &push ("edi"); + &push ("esi"); + &xor ("eax","eax"); + &mov ("edi",&wparam(0)); + &mov ("esi",&wparam(1)); + &mov ("ecx",&wparam(2)); + if ($::win32 or $::coff) { + &push (&::islabel("_win32_segv_handler")); + &data_byte(0x64,0xff,0x30); # push %fs:(%eax) + &data_byte(0x64,0x89,0x20); # mov %esp,%fs:(%eax) + } + &mov ("edx","esp"); # put aside %esp + &add ("esp",-128); # 32 is enough but spec says 128 + &movups ("xmm0",&QWP(0,"edi")); # copy-in context + &and ("esp",-16); + &mov ("eax",&DWP(16,"edi")); + &movaps (&QWP(0,"esp"),"xmm0"); + &mov ("edi","esp"); + &mov (&DWP(16,"esp"),"eax"); + &xor ("eax","eax"); + &data_byte(0xf3,0x0f,0xa6,0xc8); # rep xsha1 + &movaps ("xmm0",&QWP(0,"esp")); + &mov ("eax",&DWP(16,"esp")); + &mov ("esp","edx"); # restore %esp + if ($::win32 or $::coff) { + &data_byte(0x64,0x8f,0x05,0,0,0,0); # pop %fs:0 + &lea ("esp",&DWP(4,"esp")); + } + &mov ("edi",&wparam(0)); + &movups (&QWP(0,"edi"),"xmm0"); # copy-out context + &mov (&DWP(16,"edi"),"eax"); + &pop ("esi"); + &pop ("edi"); + &ret (); +&function_end_B("padlock_sha1_oneshot"); + +&function_begin_B("padlock_sha1_blocks"); + &push ("edi"); + &push ("esi"); + &mov ("edi",&wparam(0)); + &mov ("esi",&wparam(1)); + &mov ("edx","esp"); # put aside %esp + &mov ("ecx",&wparam(2)); + &add ("esp",-128); + &movups ("xmm0",&QWP(0,"edi")); # copy-in context + &and ("esp",-16); + &mov ("eax",&DWP(16,"edi")); + &movaps (&QWP(0,"esp"),"xmm0"); + &mov ("edi","esp"); + &mov (&DWP(16,"esp"),"eax"); + &mov ("eax",-1); + &data_byte(0xf3,0x0f,0xa6,0xc8); # rep xsha1 + &movaps ("xmm0",&QWP(0,"esp")); + &mov ("eax",&DWP(16,"esp")); + &mov ("esp","edx"); # restore %esp + &mov ("edi",&wparam(0)); + &movups (&QWP(0,"edi"),"xmm0"); # copy-out context + &mov (&DWP(16,"edi"),"eax"); + &pop ("esi"); + &pop ("edi"); + &ret (); +&function_end_B("padlock_sha1_blocks"); + +&function_begin_B("padlock_sha256_oneshot"); + &push ("edi"); + &push ("esi"); + &xor ("eax","eax"); + &mov ("edi",&wparam(0)); + &mov ("esi",&wparam(1)); + &mov ("ecx",&wparam(2)); + if ($::win32 or $::coff) { + &push (&::islabel("_win32_segv_handler")); + &data_byte(0x64,0xff,0x30); # push %fs:(%eax) + &data_byte(0x64,0x89,0x20); # mov %esp,%fs:(%eax) + } + &mov ("edx","esp"); # put aside %esp + &add ("esp",-128); + &movups ("xmm0",&QWP(0,"edi")); # copy-in context + &and ("esp",-16); + &movups ("xmm1",&QWP(16,"edi")); + &movaps (&QWP(0,"esp"),"xmm0"); + &mov ("edi","esp"); + &movaps (&QWP(16,"esp"),"xmm1"); + &xor ("eax","eax"); + &data_byte(0xf3,0x0f,0xa6,0xd0); # rep xsha256 + &movaps ("xmm0",&QWP(0,"esp")); + &movaps ("xmm1",&QWP(16,"esp")); + &mov ("esp","edx"); # restore %esp + if ($::win32 or $::coff) { + &data_byte(0x64,0x8f,0x05,0,0,0,0); # pop %fs:0 + &lea ("esp",&DWP(4,"esp")); + } + &mov ("edi",&wparam(0)); + &movups (&QWP(0,"edi"),"xmm0"); # copy-out context + &movups (&QWP(16,"edi"),"xmm1"); + &pop ("esi"); + &pop ("edi"); + &ret (); +&function_end_B("padlock_sha256_oneshot"); + +&function_begin_B("padlock_sha256_blocks"); + &push ("edi"); + &push ("esi"); + &mov ("edi",&wparam(0)); + &mov ("esi",&wparam(1)); + &mov ("ecx",&wparam(2)); + &mov ("edx","esp"); # put aside %esp + &add ("esp",-128); + &movups ("xmm0",&QWP(0,"edi")); # copy-in context + &and ("esp",-16); + &movups ("xmm1",&QWP(16,"edi")); + &movaps (&QWP(0,"esp"),"xmm0"); + &mov ("edi","esp"); + &movaps (&QWP(16,"esp"),"xmm1"); + &mov ("eax",-1); + &data_byte(0xf3,0x0f,0xa6,0xd0); # rep xsha256 + &movaps ("xmm0",&QWP(0,"esp")); + &movaps ("xmm1",&QWP(16,"esp")); + &mov ("esp","edx"); # restore %esp + &mov ("edi",&wparam(0)); + &movups (&QWP(0,"edi"),"xmm0"); # copy-out context + &movups (&QWP(16,"edi"),"xmm1"); + &pop ("esi"); + &pop ("edi"); + &ret (); +&function_end_B("padlock_sha256_blocks"); + +&function_begin_B("padlock_sha512_blocks"); + &push ("edi"); + &push ("esi"); + &mov ("edi",&wparam(0)); + &mov ("esi",&wparam(1)); + &mov ("ecx",&wparam(2)); + &mov ("edx","esp"); # put aside %esp + &add ("esp",-128); + &movups ("xmm0",&QWP(0,"edi")); # copy-in context + &and ("esp",-16); + &movups ("xmm1",&QWP(16,"edi")); + &movups ("xmm2",&QWP(32,"edi")); + &movups ("xmm3",&QWP(48,"edi")); + &movaps (&QWP(0,"esp"),"xmm0"); + &mov ("edi","esp"); + &movaps (&QWP(16,"esp"),"xmm1"); + &movaps (&QWP(32,"esp"),"xmm2"); + &movaps (&QWP(48,"esp"),"xmm3"); + &data_byte(0xf3,0x0f,0xa6,0xe0); # rep xsha512 + &movaps ("xmm0",&QWP(0,"esp")); + &movaps ("xmm1",&QWP(16,"esp")); + &movaps ("xmm2",&QWP(32,"esp")); + &movaps ("xmm3",&QWP(48,"esp")); + &mov ("esp","edx"); # restore %esp + &mov ("edi",&wparam(0)); + &movups (&QWP(0,"edi"),"xmm0"); # copy-out context + &movups (&QWP(16,"edi"),"xmm1"); + &movups (&QWP(32,"edi"),"xmm2"); + &movups (&QWP(48,"edi"),"xmm3"); + &pop ("esi"); + &pop ("edi"); + &ret (); +&function_end_B("padlock_sha512_blocks"); + +&asciz ("VIA Padlock x86 module, CRYPTOGAMS by "); +&align (16); + +&dataseg(); +# Essentially this variable belongs in thread local storage. +# Having this variable global on the other hand can only cause +# few bogus key reloads [if any at all on signle-CPU system], +# so we accept the penalty... +&set_label("padlock_saved_context",4); +&data_word(0); + +&asm_finish(); + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/engines/asm/e_padlock-x86_64.pl b/trunk/3rdparty/openssl-1.1-fit/engines/asm/e_padlock-x86_64.pl new file mode 100644 index 000000000..09b0aaa48 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/engines/asm/e_padlock-x86_64.pl @@ -0,0 +1,583 @@ +#! /usr/bin/env perl +# Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== + +# September 2011 +# +# Assembler helpers for Padlock engine. See even e_padlock-x86.pl for +# details. + +$flavour = shift; +$output = shift; +if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../crypto/perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +*STDOUT=*OUT; + +$code=".text\n"; + +%PADLOCK_PREFETCH=(ecb=>128, cbc=>64, ctr32=>32); # prefetch errata +$PADLOCK_CHUNK=512; # Must be a power of 2 between 32 and 2^20 + +$ctx="%rdx"; +$out="%rdi"; +$inp="%rsi"; +$len="%rcx"; +$chunk="%rbx"; + +($arg1,$arg2,$arg3,$arg4)=$win64?("%rcx","%rdx","%r8", "%r9") : # Win64 order + ("%rdi","%rsi","%rdx","%rcx"); # Unix order + +$code.=<<___; +.globl padlock_capability +.type padlock_capability,\@abi-omnipotent +.align 16 +padlock_capability: + mov %rbx,%r8 + xor %eax,%eax + cpuid + xor %eax,%eax + cmp \$`"0x".unpack("H*",'tneC')`,%ebx + jne .Lzhaoxin + cmp \$`"0x".unpack("H*",'Hrua')`,%edx + jne .Lnoluck + cmp \$`"0x".unpack("H*",'slua')`,%ecx + jne .Lnoluck + jmp .LzhaoxinEnd +.Lzhaoxin: + cmp \$`"0x".unpack("H*",'hS ')`,%ebx + jne .Lnoluck + cmp \$`"0x".unpack("H*",'hgna')`,%edx + jne .Lnoluck + cmp \$`"0x".unpack("H*",' ia')`,%ecx + jne .Lnoluck +.LzhaoxinEnd: + mov \$0xC0000000,%eax + cpuid + mov %eax,%edx + xor %eax,%eax + cmp \$0xC0000001,%edx + jb .Lnoluck + mov \$0xC0000001,%eax + cpuid + mov %edx,%eax + and \$0xffffffef,%eax + or \$0x10,%eax # set Nano bit#4 +.Lnoluck: + mov %r8,%rbx + ret +.size padlock_capability,.-padlock_capability + +.globl padlock_key_bswap +.type padlock_key_bswap,\@abi-omnipotent,0 +.align 16 +padlock_key_bswap: + mov 240($arg1),%edx +.Lbswap_loop: + mov ($arg1),%eax + bswap %eax + mov %eax,($arg1) + lea 4($arg1),$arg1 + sub \$1,%edx + jnz .Lbswap_loop + ret +.size padlock_key_bswap,.-padlock_key_bswap + +.globl padlock_verify_context +.type padlock_verify_context,\@abi-omnipotent +.align 16 +padlock_verify_context: + mov $arg1,$ctx + pushf + lea .Lpadlock_saved_context(%rip),%rax + call _padlock_verify_ctx + lea 8(%rsp),%rsp + ret +.size padlock_verify_context,.-padlock_verify_context + +.type _padlock_verify_ctx,\@abi-omnipotent +.align 16 +_padlock_verify_ctx: + mov 8(%rsp),%r8 + bt \$30,%r8 + jnc .Lverified + cmp (%rax),$ctx + je .Lverified + pushf + popf +.Lverified: + mov $ctx,(%rax) + ret +.size _padlock_verify_ctx,.-_padlock_verify_ctx + +.globl padlock_reload_key +.type padlock_reload_key,\@abi-omnipotent +.align 16 +padlock_reload_key: + pushf + popf + ret +.size padlock_reload_key,.-padlock_reload_key + +.globl padlock_aes_block +.type padlock_aes_block,\@function,3 +.align 16 +padlock_aes_block: + mov %rbx,%r8 + mov \$1,$len + lea 32($ctx),%rbx # key + lea 16($ctx),$ctx # control word + .byte 0xf3,0x0f,0xa7,0xc8 # rep xcryptecb + mov %r8,%rbx + ret +.size padlock_aes_block,.-padlock_aes_block + +.globl padlock_xstore +.type padlock_xstore,\@function,2 +.align 16 +padlock_xstore: + mov %esi,%edx + .byte 0x0f,0xa7,0xc0 # xstore + ret +.size padlock_xstore,.-padlock_xstore + +.globl padlock_sha1_oneshot +.type padlock_sha1_oneshot,\@function,3 +.align 16 +padlock_sha1_oneshot: + mov %rdx,%rcx + mov %rdi,%rdx # put aside %rdi + movups (%rdi),%xmm0 # copy-in context + sub \$128+8,%rsp + mov 16(%rdi),%eax + movaps %xmm0,(%rsp) + mov %rsp,%rdi + mov %eax,16(%rsp) + xor %rax,%rax + .byte 0xf3,0x0f,0xa6,0xc8 # rep xsha1 + movaps (%rsp),%xmm0 + mov 16(%rsp),%eax + add \$128+8,%rsp + movups %xmm0,(%rdx) # copy-out context + mov %eax,16(%rdx) + ret +.size padlock_sha1_oneshot,.-padlock_sha1_oneshot + +.globl padlock_sha1_blocks +.type padlock_sha1_blocks,\@function,3 +.align 16 +padlock_sha1_blocks: + mov %rdx,%rcx + mov %rdi,%rdx # put aside %rdi + movups (%rdi),%xmm0 # copy-in context + sub \$128+8,%rsp + mov 16(%rdi),%eax + movaps %xmm0,(%rsp) + mov %rsp,%rdi + mov %eax,16(%rsp) + mov \$-1,%rax + .byte 0xf3,0x0f,0xa6,0xc8 # rep xsha1 + movaps (%rsp),%xmm0 + mov 16(%rsp),%eax + add \$128+8,%rsp + movups %xmm0,(%rdx) # copy-out context + mov %eax,16(%rdx) + ret +.size padlock_sha1_blocks,.-padlock_sha1_blocks + +.globl padlock_sha256_oneshot +.type padlock_sha256_oneshot,\@function,3 +.align 16 +padlock_sha256_oneshot: + mov %rdx,%rcx + mov %rdi,%rdx # put aside %rdi + movups (%rdi),%xmm0 # copy-in context + sub \$128+8,%rsp + movups 16(%rdi),%xmm1 + movaps %xmm0,(%rsp) + mov %rsp,%rdi + movaps %xmm1,16(%rsp) + xor %rax,%rax + .byte 0xf3,0x0f,0xa6,0xd0 # rep xsha256 + movaps (%rsp),%xmm0 + movaps 16(%rsp),%xmm1 + add \$128+8,%rsp + movups %xmm0,(%rdx) # copy-out context + movups %xmm1,16(%rdx) + ret +.size padlock_sha256_oneshot,.-padlock_sha256_oneshot + +.globl padlock_sha256_blocks +.type padlock_sha256_blocks,\@function,3 +.align 16 +padlock_sha256_blocks: + mov %rdx,%rcx + mov %rdi,%rdx # put aside %rdi + movups (%rdi),%xmm0 # copy-in context + sub \$128+8,%rsp + movups 16(%rdi),%xmm1 + movaps %xmm0,(%rsp) + mov %rsp,%rdi + movaps %xmm1,16(%rsp) + mov \$-1,%rax + .byte 0xf3,0x0f,0xa6,0xd0 # rep xsha256 + movaps (%rsp),%xmm0 + movaps 16(%rsp),%xmm1 + add \$128+8,%rsp + movups %xmm0,(%rdx) # copy-out context + movups %xmm1,16(%rdx) + ret +.size padlock_sha256_blocks,.-padlock_sha256_blocks + +.globl padlock_sha512_blocks +.type padlock_sha512_blocks,\@function,3 +.align 16 +padlock_sha512_blocks: + mov %rdx,%rcx + mov %rdi,%rdx # put aside %rdi + movups (%rdi),%xmm0 # copy-in context + sub \$128+8,%rsp + movups 16(%rdi),%xmm1 + movups 32(%rdi),%xmm2 + movups 48(%rdi),%xmm3 + movaps %xmm0,(%rsp) + mov %rsp,%rdi + movaps %xmm1,16(%rsp) + movaps %xmm2,32(%rsp) + movaps %xmm3,48(%rsp) + .byte 0xf3,0x0f,0xa6,0xe0 # rep xha512 + movaps (%rsp),%xmm0 + movaps 16(%rsp),%xmm1 + movaps 32(%rsp),%xmm2 + movaps 48(%rsp),%xmm3 + add \$128+8,%rsp + movups %xmm0,(%rdx) # copy-out context + movups %xmm1,16(%rdx) + movups %xmm2,32(%rdx) + movups %xmm3,48(%rdx) + ret +.size padlock_sha512_blocks,.-padlock_sha512_blocks +___ + +sub generate_mode { +my ($mode,$opcode) = @_; +# int padlock_$mode_encrypt(void *out, const void *inp, +# struct padlock_cipher_data *ctx, size_t len); +$code.=<<___; +.globl padlock_${mode}_encrypt +.type padlock_${mode}_encrypt,\@function,4 +.align 16 +padlock_${mode}_encrypt: + push %rbp + push %rbx + + xor %eax,%eax + test \$15,$ctx + jnz .L${mode}_abort + test \$15,$len + jnz .L${mode}_abort + lea .Lpadlock_saved_context(%rip),%rax + pushf + cld + call _padlock_verify_ctx + lea 16($ctx),$ctx # control word + xor %eax,%eax + xor %ebx,%ebx + testl \$`1<<5`,($ctx) # align bit in control word + jnz .L${mode}_aligned + test \$0x0f,$out + setz %al # !out_misaligned + test \$0x0f,$inp + setz %bl # !inp_misaligned + test %ebx,%eax + jnz .L${mode}_aligned + neg %rax + mov \$$PADLOCK_CHUNK,$chunk + not %rax # out_misaligned?-1:0 + lea (%rsp),%rbp + cmp $chunk,$len + cmovc $len,$chunk # chunk=len>PADLOCK_CHUNK?PADLOCK_CHUNK:len + and $chunk,%rax # out_misaligned?chunk:0 + mov $len,$chunk + neg %rax + and \$$PADLOCK_CHUNK-1,$chunk # chunk%=PADLOCK_CHUNK + lea (%rax,%rbp),%rsp + mov \$$PADLOCK_CHUNK,%rax + cmovz %rax,$chunk # chunk=chunk?:PADLOCK_CHUNK +___ +$code.=<<___ if ($mode eq "ctr32"); +.L${mode}_reenter: + mov -4($ctx),%eax # pull 32-bit counter + bswap %eax + neg %eax + and \$`$PADLOCK_CHUNK/16-1`,%eax + mov \$$PADLOCK_CHUNK,$chunk + shl \$4,%eax + cmovz $chunk,%rax + cmp %rax,$len + cmova %rax,$chunk # don't let counter cross PADLOCK_CHUNK + cmovbe $len,$chunk +___ +$code.=<<___ if ($PADLOCK_PREFETCH{$mode}); + cmp $chunk,$len + ja .L${mode}_loop + mov $inp,%rax # check if prefetch crosses page + cmp %rsp,%rbp + cmove $out,%rax + add $len,%rax + neg %rax + and \$0xfff,%rax # distance to page boundary + cmp \$$PADLOCK_PREFETCH{$mode},%rax + mov \$-$PADLOCK_PREFETCH{$mode},%rax + cmovae $chunk,%rax # mask=distance" +.align 16 +.data +.align 8 +.Lpadlock_saved_context: + .quad 0 +___ +$code =~ s/\`([^\`]*)\`/eval($1)/gem; + +print $code; + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/engines/build.info b/trunk/3rdparty/openssl-1.1-fit/engines/build.info new file mode 100644 index 000000000..df173ea69 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/engines/build.info @@ -0,0 +1,43 @@ +IF[{- !$disabled{"engine"} -}] + + IF[{- $disabled{"dynamic-engine"} -}] + LIBS=../libcrypto + SOURCE[../libcrypto]=\ + e_padlock.c {- $target{padlock_asm_src} -} + IF[{- !$disabled{capieng} -}] + SOURCE[../libcrypto]=e_capi.c + ENDIF + IF[{- !$disabled{afalgeng} -}] + SOURCE[../libcrypto]=e_afalg.c + ENDIF + ELSE + ENGINES=padlock + SOURCE[padlock]=e_padlock.c {- $target{padlock_asm_src} -} + DEPEND[padlock]=../libcrypto + INCLUDE[padlock]=../include + IF[{- !$disabled{capieng} -}] + ENGINES=capi + SOURCE[capi]=e_capi.c + DEPEND[capi]=../libcrypto + INCLUDE[capi]=../include + ENDIF + IF[{- !$disabled{afalgeng} -}] + ENGINES=afalg + SOURCE[afalg]=e_afalg.c + DEPEND[afalg]=../libcrypto + INCLUDE[afalg]= ../include + ENDIF + + ENGINES_NO_INST=ossltest dasync + SOURCE[dasync]=e_dasync.c + DEPEND[dasync]=../libcrypto + INCLUDE[dasync]=../include + SOURCE[ossltest]=e_ossltest.c + DEPEND[ossltest]=../libcrypto + INCLUDE[ossltest]=../include + ENDIF + + GENERATE[e_padlock-x86.s]=asm/e_padlock-x86.pl \ + $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) + GENERATE[e_padlock-x86_64.s]=asm/e_padlock-x86_64.pl $(PERLASM_SCHEME) +ENDIF diff --git a/trunk/3rdparty/openssl-1.1-fit/engines/e_afalg.c b/trunk/3rdparty/openssl-1.1-fit/engines/e_afalg.c new file mode 100644 index 000000000..f09c396ed --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/engines/e_afalg.c @@ -0,0 +1,870 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Required for vmsplice */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif +#include +#include +#include + +#include +#include +#include +#include "internal/nelem.h" + +#include +#include +#define K_MAJ 4 +#define K_MIN1 1 +#define K_MIN2 0 +#if LINUX_VERSION_CODE < KERNEL_VERSION(K_MAJ, K_MIN1, K_MIN2) || \ + !defined(AF_ALG) +# ifndef PEDANTIC +# warning "AFALG ENGINE requires Kernel Headers >= 4.1.0" +# warning "Skipping Compilation of AFALG engine" +# endif +void engine_load_afalg_int(void); +void engine_load_afalg_int(void) +{ +} +#else + +# include +# include +# include + +# include +# include +# include + +# include "e_afalg.h" +# include "e_afalg_err.c" + +# ifndef SOL_ALG +# define SOL_ALG 279 +# endif + +# ifdef ALG_ZERO_COPY +# ifndef SPLICE_F_GIFT +# define SPLICE_F_GIFT (0x08) +# endif +# endif + +# define ALG_AES_IV_LEN 16 +# define ALG_IV_LEN(len) (sizeof(struct af_alg_iv) + (len)) +# define ALG_OP_TYPE unsigned int +# define ALG_OP_LEN (sizeof(ALG_OP_TYPE)) + +#define ALG_MAX_SALG_NAME 64 +#define ALG_MAX_SALG_TYPE 14 + +# ifdef OPENSSL_NO_DYNAMIC_ENGINE +void engine_load_afalg_int(void); +# endif + +/* Local Linkage Functions */ +static int afalg_init_aio(afalg_aio *aio); +static int afalg_fin_cipher_aio(afalg_aio *ptr, int sfd, + unsigned char *buf, size_t len); +static int afalg_create_sk(afalg_ctx *actx, const char *ciphertype, + const char *ciphername); +static int afalg_destroy(ENGINE *e); +static int afalg_init(ENGINE *e); +static int afalg_finish(ENGINE *e); +static const EVP_CIPHER *afalg_aes_cbc(int nid); +static cbc_handles *get_cipher_handle(int nid); +static int afalg_ciphers(ENGINE *e, const EVP_CIPHER **cipher, + const int **nids, int nid); +static int afalg_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); +static int afalg_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl); +static int afalg_cipher_cleanup(EVP_CIPHER_CTX *ctx); +static int afalg_chk_platform(void); + +/* Engine Id and Name */ +static const char *engine_afalg_id = "afalg"; +static const char *engine_afalg_name = "AFALG engine support"; + +static int afalg_cipher_nids[] = { + NID_aes_128_cbc, + NID_aes_192_cbc, + NID_aes_256_cbc, +}; + +static cbc_handles cbc_handle[] = {{AES_KEY_SIZE_128, NULL}, + {AES_KEY_SIZE_192, NULL}, + {AES_KEY_SIZE_256, NULL}}; + +static ossl_inline int io_setup(unsigned n, aio_context_t *ctx) +{ + return syscall(__NR_io_setup, n, ctx); +} + +static ossl_inline int eventfd(int n) +{ + return syscall(__NR_eventfd2, n, 0); +} + +static ossl_inline int io_destroy(aio_context_t ctx) +{ + return syscall(__NR_io_destroy, ctx); +} + +static ossl_inline int io_read(aio_context_t ctx, long n, struct iocb **iocb) +{ + return syscall(__NR_io_submit, ctx, n, iocb); +} + +static ossl_inline int io_getevents(aio_context_t ctx, long min, long max, + struct io_event *events, + struct timespec *timeout) +{ + return syscall(__NR_io_getevents, ctx, min, max, events, timeout); +} + +static void afalg_waitfd_cleanup(ASYNC_WAIT_CTX *ctx, const void *key, + OSSL_ASYNC_FD waitfd, void *custom) +{ + close(waitfd); +} + +static int afalg_setup_async_event_notification(afalg_aio *aio) +{ + ASYNC_JOB *job; + ASYNC_WAIT_CTX *waitctx; + void *custom = NULL; + int ret; + + if ((job = ASYNC_get_current_job()) != NULL) { + /* Async mode */ + waitctx = ASYNC_get_wait_ctx(job); + if (waitctx == NULL) { + ALG_WARN("%s(%d): ASYNC_get_wait_ctx error", __FILE__, __LINE__); + return 0; + } + /* Get waitfd from ASYNC_WAIT_CTX if it is already set */ + ret = ASYNC_WAIT_CTX_get_fd(waitctx, engine_afalg_id, + &aio->efd, &custom); + if (ret == 0) { + /* + * waitfd is not set in ASYNC_WAIT_CTX, create a new one + * and set it. efd will be signaled when AIO operation completes + */ + aio->efd = eventfd(0); + if (aio->efd == -1) { + ALG_PERR("%s(%d): Failed to get eventfd : ", __FILE__, + __LINE__); + AFALGerr(AFALG_F_AFALG_SETUP_ASYNC_EVENT_NOTIFICATION, + AFALG_R_EVENTFD_FAILED); + return 0; + } + ret = ASYNC_WAIT_CTX_set_wait_fd(waitctx, engine_afalg_id, + aio->efd, custom, + afalg_waitfd_cleanup); + if (ret == 0) { + ALG_WARN("%s(%d): Failed to set wait fd", __FILE__, __LINE__); + close(aio->efd); + return 0; + } + /* make fd non-blocking in async mode */ + if (fcntl(aio->efd, F_SETFL, O_NONBLOCK) != 0) { + ALG_WARN("%s(%d): Failed to set event fd as NONBLOCKING", + __FILE__, __LINE__); + } + } + aio->mode = MODE_ASYNC; + } else { + /* Sync mode */ + aio->efd = eventfd(0); + if (aio->efd == -1) { + ALG_PERR("%s(%d): Failed to get eventfd : ", __FILE__, __LINE__); + AFALGerr(AFALG_F_AFALG_SETUP_ASYNC_EVENT_NOTIFICATION, + AFALG_R_EVENTFD_FAILED); + return 0; + } + aio->mode = MODE_SYNC; + } + return 1; +} + +static int afalg_init_aio(afalg_aio *aio) +{ + int r = -1; + + /* Initialise for AIO */ + aio->aio_ctx = 0; + r = io_setup(MAX_INFLIGHTS, &aio->aio_ctx); + if (r < 0) { + ALG_PERR("%s(%d): io_setup error : ", __FILE__, __LINE__); + AFALGerr(AFALG_F_AFALG_INIT_AIO, AFALG_R_IO_SETUP_FAILED); + return 0; + } + + memset(aio->cbt, 0, sizeof(aio->cbt)); + aio->efd = -1; + aio->mode = MODE_UNINIT; + + return 1; +} + +static int afalg_fin_cipher_aio(afalg_aio *aio, int sfd, unsigned char *buf, + size_t len) +{ + int r; + int retry = 0; + unsigned int done = 0; + struct iocb *cb; + struct timespec timeout; + struct io_event events[MAX_INFLIGHTS]; + u_int64_t eval = 0; + + timeout.tv_sec = 0; + timeout.tv_nsec = 0; + + /* if efd has not been initialised yet do it here */ + if (aio->mode == MODE_UNINIT) { + r = afalg_setup_async_event_notification(aio); + if (r == 0) + return 0; + } + + cb = &(aio->cbt[0 % MAX_INFLIGHTS]); + memset(cb, '\0', sizeof(*cb)); + cb->aio_fildes = sfd; + cb->aio_lio_opcode = IOCB_CMD_PREAD; + /* + * The pointer has to be converted to unsigned value first to avoid + * sign extension on cast to 64 bit value in 32-bit builds + */ + cb->aio_buf = (size_t)buf; + cb->aio_offset = 0; + cb->aio_data = 0; + cb->aio_nbytes = len; + cb->aio_flags = IOCB_FLAG_RESFD; + cb->aio_resfd = aio->efd; + + /* + * Perform AIO read on AFALG socket, this in turn performs an async + * crypto operation in kernel space + */ + r = io_read(aio->aio_ctx, 1, &cb); + if (r < 0) { + ALG_PWARN("%s(%d): io_read failed : ", __FILE__, __LINE__); + return 0; + } + + do { + /* While AIO read is being performed pause job */ + ASYNC_pause_job(); + + /* Check for completion of AIO read */ + r = read(aio->efd, &eval, sizeof(eval)); + if (r < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK) + continue; + ALG_PERR("%s(%d): read failed for event fd : ", __FILE__, __LINE__); + return 0; + } else if (r == 0 || eval <= 0) { + ALG_WARN("%s(%d): eventfd read %d bytes, eval = %lu\n", __FILE__, + __LINE__, r, eval); + } + if (eval > 0) { + + /* Get results of AIO read */ + r = io_getevents(aio->aio_ctx, 1, MAX_INFLIGHTS, + events, &timeout); + if (r > 0) { + /* + * events.res indicates the actual status of the operation. + * Handle the error condition first. + */ + if (events[0].res < 0) { + /* + * Underlying operation cannot be completed at the time + * of previous submission. Resubmit for the operation. + */ + if (events[0].res == -EBUSY && retry++ < 3) { + r = io_read(aio->aio_ctx, 1, &cb); + if (r < 0) { + ALG_PERR("%s(%d): retry %d for io_read failed : ", + __FILE__, __LINE__, retry); + return 0; + } + continue; + } else { + /* + * Retries exceed for -EBUSY or unrecoverable error + * condition for this instance of operation. + */ + ALG_WARN + ("%s(%d): Crypto Operation failed with code %lld\n", + __FILE__, __LINE__, events[0].res); + return 0; + } + } + /* Operation successful. */ + done = 1; + } else if (r < 0) { + ALG_PERR("%s(%d): io_getevents failed : ", __FILE__, __LINE__); + return 0; + } else { + ALG_WARN("%s(%d): io_geteventd read 0 bytes\n", __FILE__, + __LINE__); + } + } + } while (!done); + + return 1; +} + +static ossl_inline void afalg_set_op_sk(struct cmsghdr *cmsg, + const ALG_OP_TYPE op) +{ + cmsg->cmsg_level = SOL_ALG; + cmsg->cmsg_type = ALG_SET_OP; + cmsg->cmsg_len = CMSG_LEN(ALG_OP_LEN); + memcpy(CMSG_DATA(cmsg), &op, ALG_OP_LEN); +} + +static void afalg_set_iv_sk(struct cmsghdr *cmsg, const unsigned char *iv, + const unsigned int len) +{ + struct af_alg_iv *aiv; + + cmsg->cmsg_level = SOL_ALG; + cmsg->cmsg_type = ALG_SET_IV; + cmsg->cmsg_len = CMSG_LEN(ALG_IV_LEN(len)); + aiv = (struct af_alg_iv *)CMSG_DATA(cmsg); + aiv->ivlen = len; + memcpy(aiv->iv, iv, len); +} + +static ossl_inline int afalg_set_key(afalg_ctx *actx, const unsigned char *key, + const int klen) +{ + int ret; + ret = setsockopt(actx->bfd, SOL_ALG, ALG_SET_KEY, key, klen); + if (ret < 0) { + ALG_PERR("%s(%d): Failed to set socket option : ", __FILE__, __LINE__); + AFALGerr(AFALG_F_AFALG_SET_KEY, AFALG_R_SOCKET_SET_KEY_FAILED); + return 0; + } + return 1; +} + +static int afalg_create_sk(afalg_ctx *actx, const char *ciphertype, + const char *ciphername) +{ + struct sockaddr_alg sa; + int r = -1; + + actx->bfd = actx->sfd = -1; + + memset(&sa, 0, sizeof(sa)); + sa.salg_family = AF_ALG; + strncpy((char *) sa.salg_type, ciphertype, ALG_MAX_SALG_TYPE); + sa.salg_type[ALG_MAX_SALG_TYPE-1] = '\0'; + strncpy((char *) sa.salg_name, ciphername, ALG_MAX_SALG_NAME); + sa.salg_name[ALG_MAX_SALG_NAME-1] = '\0'; + + actx->bfd = socket(AF_ALG, SOCK_SEQPACKET, 0); + if (actx->bfd == -1) { + ALG_PERR("%s(%d): Failed to open socket : ", __FILE__, __LINE__); + AFALGerr(AFALG_F_AFALG_CREATE_SK, AFALG_R_SOCKET_CREATE_FAILED); + goto err; + } + + r = bind(actx->bfd, (struct sockaddr *)&sa, sizeof(sa)); + if (r < 0) { + ALG_PERR("%s(%d): Failed to bind socket : ", __FILE__, __LINE__); + AFALGerr(AFALG_F_AFALG_CREATE_SK, AFALG_R_SOCKET_BIND_FAILED); + goto err; + } + + actx->sfd = accept(actx->bfd, NULL, 0); + if (actx->sfd < 0) { + ALG_PERR("%s(%d): Socket Accept Failed : ", __FILE__, __LINE__); + AFALGerr(AFALG_F_AFALG_CREATE_SK, AFALG_R_SOCKET_ACCEPT_FAILED); + goto err; + } + + return 1; + + err: + if (actx->bfd >= 0) + close(actx->bfd); + if (actx->sfd >= 0) + close(actx->sfd); + actx->bfd = actx->sfd = -1; + return 0; +} + +static int afalg_start_cipher_sk(afalg_ctx *actx, const unsigned char *in, + size_t inl, const unsigned char *iv, + unsigned int enc) +{ + struct msghdr msg = { 0 }; + struct cmsghdr *cmsg; + struct iovec iov; + ssize_t sbytes; +# ifdef ALG_ZERO_COPY + int ret; +# endif + char cbuf[CMSG_SPACE(ALG_IV_LEN(ALG_AES_IV_LEN)) + CMSG_SPACE(ALG_OP_LEN)]; + + memset(cbuf, 0, sizeof(cbuf)); + msg.msg_control = cbuf; + msg.msg_controllen = sizeof(cbuf); + + /* + * cipher direction (i.e. encrypt or decrypt) and iv are sent to the + * kernel as part of sendmsg()'s ancillary data + */ + cmsg = CMSG_FIRSTHDR(&msg); + afalg_set_op_sk(cmsg, enc); + cmsg = CMSG_NXTHDR(&msg, cmsg); + afalg_set_iv_sk(cmsg, iv, ALG_AES_IV_LEN); + + /* iov that describes input data */ + iov.iov_base = (unsigned char *)in; + iov.iov_len = inl; + + msg.msg_flags = MSG_MORE; + +# ifdef ALG_ZERO_COPY + /* + * ZERO_COPY mode + * Works best when buffer is 4k aligned + * OPENS: out of place processing (i.e. out != in) + */ + + /* Input data is not sent as part of call to sendmsg() */ + msg.msg_iovlen = 0; + msg.msg_iov = NULL; + + /* Sendmsg() sends iv and cipher direction to the kernel */ + sbytes = sendmsg(actx->sfd, &msg, 0); + if (sbytes < 0) { + ALG_PERR("%s(%d): sendmsg failed for zero copy cipher operation : ", + __FILE__, __LINE__); + return 0; + } + + /* + * vmsplice and splice are used to pin the user space input buffer for + * kernel space processing avoiding copys from user to kernel space + */ + ret = vmsplice(actx->zc_pipe[1], &iov, 1, SPLICE_F_GIFT); + if (ret < 0) { + ALG_PERR("%s(%d): vmsplice failed : ", __FILE__, __LINE__); + return 0; + } + + ret = splice(actx->zc_pipe[0], NULL, actx->sfd, NULL, inl, 0); + if (ret < 0) { + ALG_PERR("%s(%d): splice failed : ", __FILE__, __LINE__); + return 0; + } +# else + msg.msg_iovlen = 1; + msg.msg_iov = &iov; + + /* Sendmsg() sends iv, cipher direction and input data to the kernel */ + sbytes = sendmsg(actx->sfd, &msg, 0); + if (sbytes < 0) { + ALG_PERR("%s(%d): sendmsg failed for cipher operation : ", __FILE__, + __LINE__); + return 0; + } + + if (sbytes != (ssize_t) inl) { + ALG_WARN("Cipher operation send bytes %zd != inlen %zd\n", sbytes, + inl); + return 0; + } +# endif + + return 1; +} + +static int afalg_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + int ciphertype; + int ret; + afalg_ctx *actx; + char ciphername[ALG_MAX_SALG_NAME]; + + if (ctx == NULL || key == NULL) { + ALG_WARN("%s(%d): Null Parameter\n", __FILE__, __LINE__); + return 0; + } + + if (EVP_CIPHER_CTX_cipher(ctx) == NULL) { + ALG_WARN("%s(%d): Cipher object NULL\n", __FILE__, __LINE__); + return 0; + } + + actx = EVP_CIPHER_CTX_get_cipher_data(ctx); + if (actx == NULL) { + ALG_WARN("%s(%d): Cipher data NULL\n", __FILE__, __LINE__); + return 0; + } + + ciphertype = EVP_CIPHER_CTX_nid(ctx); + switch (ciphertype) { + case NID_aes_128_cbc: + case NID_aes_192_cbc: + case NID_aes_256_cbc: + strncpy(ciphername, "cbc(aes)", ALG_MAX_SALG_NAME); + break; + default: + ALG_WARN("%s(%d): Unsupported Cipher type %d\n", __FILE__, __LINE__, + ciphertype); + return 0; + } + ciphername[ALG_MAX_SALG_NAME-1]='\0'; + + if (ALG_AES_IV_LEN != EVP_CIPHER_CTX_iv_length(ctx)) { + ALG_WARN("%s(%d): Unsupported IV length :%d\n", __FILE__, __LINE__, + EVP_CIPHER_CTX_iv_length(ctx)); + return 0; + } + + /* Setup AFALG socket for crypto processing */ + ret = afalg_create_sk(actx, "skcipher", ciphername); + if (ret < 1) + return 0; + + + ret = afalg_set_key(actx, key, EVP_CIPHER_CTX_key_length(ctx)); + if (ret < 1) + goto err; + + /* Setup AIO ctx to allow async AFALG crypto processing */ + if (afalg_init_aio(&actx->aio) == 0) + goto err; + +# ifdef ALG_ZERO_COPY + pipe(actx->zc_pipe); +# endif + + actx->init_done = MAGIC_INIT_NUM; + + return 1; + +err: + close(actx->sfd); + close(actx->bfd); + return 0; +} + +static int afalg_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + afalg_ctx *actx; + int ret; + char nxtiv[ALG_AES_IV_LEN] = { 0 }; + + if (ctx == NULL || out == NULL || in == NULL) { + ALG_WARN("NULL parameter passed to function %s(%d)\n", __FILE__, + __LINE__); + return 0; + } + + actx = (afalg_ctx *) EVP_CIPHER_CTX_get_cipher_data(ctx); + if (actx == NULL || actx->init_done != MAGIC_INIT_NUM) { + ALG_WARN("%s afalg ctx passed\n", + ctx == NULL ? "NULL" : "Uninitialised"); + return 0; + } + + /* + * set iv now for decrypt operation as the input buffer can be + * overwritten for inplace operation where in = out. + */ + if (EVP_CIPHER_CTX_encrypting(ctx) == 0) { + memcpy(nxtiv, in + (inl - ALG_AES_IV_LEN), ALG_AES_IV_LEN); + } + + /* Send input data to kernel space */ + ret = afalg_start_cipher_sk(actx, (unsigned char *)in, inl, + EVP_CIPHER_CTX_iv(ctx), + EVP_CIPHER_CTX_encrypting(ctx)); + if (ret < 1) { + return 0; + } + + /* Perform async crypto operation in kernel space */ + ret = afalg_fin_cipher_aio(&actx->aio, actx->sfd, out, inl); + if (ret < 1) + return 0; + + if (EVP_CIPHER_CTX_encrypting(ctx)) { + memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), out + (inl - ALG_AES_IV_LEN), + ALG_AES_IV_LEN); + } else { + memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), nxtiv, ALG_AES_IV_LEN); + } + + return 1; +} + +static int afalg_cipher_cleanup(EVP_CIPHER_CTX *ctx) +{ + afalg_ctx *actx; + + if (ctx == NULL) { + ALG_WARN("NULL parameter passed to function %s(%d)\n", __FILE__, + __LINE__); + return 0; + } + + actx = (afalg_ctx *) EVP_CIPHER_CTX_get_cipher_data(ctx); + if (actx == NULL || actx->init_done != MAGIC_INIT_NUM) { + ALG_WARN("%s afalg ctx passed\n", + ctx == NULL ? "NULL" : "Uninitialised"); + return 0; + } + + close(actx->sfd); + close(actx->bfd); +# ifdef ALG_ZERO_COPY + close(actx->zc_pipe[0]); + close(actx->zc_pipe[1]); +# endif + /* close efd in sync mode, async mode is closed in afalg_waitfd_cleanup() */ + if (actx->aio.mode == MODE_SYNC) + close(actx->aio.efd); + io_destroy(actx->aio.aio_ctx); + + return 1; +} + +static cbc_handles *get_cipher_handle(int nid) +{ + switch (nid) { + case NID_aes_128_cbc: + return &cbc_handle[AES_CBC_128]; + case NID_aes_192_cbc: + return &cbc_handle[AES_CBC_192]; + case NID_aes_256_cbc: + return &cbc_handle[AES_CBC_256]; + default: + return NULL; + } +} + +static const EVP_CIPHER *afalg_aes_cbc(int nid) +{ + cbc_handles *cipher_handle = get_cipher_handle(nid); + if (cipher_handle->_hidden == NULL + && ((cipher_handle->_hidden = + EVP_CIPHER_meth_new(nid, + AES_BLOCK_SIZE, + cipher_handle->key_size)) == NULL + || !EVP_CIPHER_meth_set_iv_length(cipher_handle->_hidden, + AES_IV_LEN) + || !EVP_CIPHER_meth_set_flags(cipher_handle->_hidden, + EVP_CIPH_CBC_MODE | + EVP_CIPH_FLAG_DEFAULT_ASN1) + || !EVP_CIPHER_meth_set_init(cipher_handle->_hidden, + afalg_cipher_init) + || !EVP_CIPHER_meth_set_do_cipher(cipher_handle->_hidden, + afalg_do_cipher) + || !EVP_CIPHER_meth_set_cleanup(cipher_handle->_hidden, + afalg_cipher_cleanup) + || !EVP_CIPHER_meth_set_impl_ctx_size(cipher_handle->_hidden, + sizeof(afalg_ctx)))) { + EVP_CIPHER_meth_free(cipher_handle->_hidden); + cipher_handle->_hidden= NULL; + } + return cipher_handle->_hidden; +} + +static int afalg_ciphers(ENGINE *e, const EVP_CIPHER **cipher, + const int **nids, int nid) +{ + int r = 1; + + if (cipher == NULL) { + *nids = afalg_cipher_nids; + return (sizeof(afalg_cipher_nids) / sizeof(afalg_cipher_nids[0])); + } + + switch (nid) { + case NID_aes_128_cbc: + case NID_aes_192_cbc: + case NID_aes_256_cbc: + *cipher = afalg_aes_cbc(nid); + break; + default: + *cipher = NULL; + r = 0; + } + return r; +} + +static int bind_afalg(ENGINE *e) +{ + /* Ensure the afalg error handling is set up */ + unsigned short i; + ERR_load_AFALG_strings(); + + if (!ENGINE_set_id(e, engine_afalg_id) + || !ENGINE_set_name(e, engine_afalg_name) + || !ENGINE_set_destroy_function(e, afalg_destroy) + || !ENGINE_set_init_function(e, afalg_init) + || !ENGINE_set_finish_function(e, afalg_finish)) { + AFALGerr(AFALG_F_BIND_AFALG, AFALG_R_INIT_FAILED); + return 0; + } + + /* + * Create _hidden_aes_xxx_cbc by calling afalg_aes_xxx_cbc + * now, as bind_aflag can only be called by one thread at a + * time. + */ + for(i = 0; i < OSSL_NELEM(afalg_cipher_nids); i++) { + if (afalg_aes_cbc(afalg_cipher_nids[i]) == NULL) { + AFALGerr(AFALG_F_BIND_AFALG, AFALG_R_INIT_FAILED); + return 0; + } + } + + if (!ENGINE_set_ciphers(e, afalg_ciphers)) { + AFALGerr(AFALG_F_BIND_AFALG, AFALG_R_INIT_FAILED); + return 0; + } + + return 1; +} + +# ifndef OPENSSL_NO_DYNAMIC_ENGINE +static int bind_helper(ENGINE *e, const char *id) +{ + if (id && (strcmp(id, engine_afalg_id) != 0)) + return 0; + + if (!afalg_chk_platform()) + return 0; + + if (!bind_afalg(e)) + return 0; + return 1; +} + +IMPLEMENT_DYNAMIC_CHECK_FN() + IMPLEMENT_DYNAMIC_BIND_FN(bind_helper) +# endif + +static int afalg_chk_platform(void) +{ + int ret; + int i; + int kver[3] = { -1, -1, -1 }; + int sock; + char *str; + struct utsname ut; + + ret = uname(&ut); + if (ret != 0) { + AFALGerr(AFALG_F_AFALG_CHK_PLATFORM, + AFALG_R_FAILED_TO_GET_PLATFORM_INFO); + return 0; + } + + str = strtok(ut.release, "."); + for (i = 0; i < 3 && str != NULL; i++) { + kver[i] = atoi(str); + str = strtok(NULL, "."); + } + + if (KERNEL_VERSION(kver[0], kver[1], kver[2]) + < KERNEL_VERSION(K_MAJ, K_MIN1, K_MIN2)) { + ALG_ERR("ASYNC AFALG not supported this kernel(%d.%d.%d)\n", + kver[0], kver[1], kver[2]); + ALG_ERR("ASYNC AFALG requires kernel version %d.%d.%d or later\n", + K_MAJ, K_MIN1, K_MIN2); + AFALGerr(AFALG_F_AFALG_CHK_PLATFORM, + AFALG_R_KERNEL_DOES_NOT_SUPPORT_ASYNC_AFALG); + return 0; + } + + /* Test if we can actually create an AF_ALG socket */ + sock = socket(AF_ALG, SOCK_SEQPACKET, 0); + if (sock == -1) { + AFALGerr(AFALG_F_AFALG_CHK_PLATFORM, AFALG_R_SOCKET_CREATE_FAILED); + return 0; + } + close(sock); + + return 1; +} + +# ifdef OPENSSL_NO_DYNAMIC_ENGINE +static ENGINE *engine_afalg(void) +{ + ENGINE *ret = ENGINE_new(); + if (ret == NULL) + return NULL; + if (!bind_afalg(ret)) { + ENGINE_free(ret); + return NULL; + } + return ret; +} + +void engine_load_afalg_int(void) +{ + ENGINE *toadd; + + if (!afalg_chk_platform()) + return; + + toadd = engine_afalg(); + if (toadd == NULL) + return; + ENGINE_add(toadd); + ENGINE_free(toadd); + ERR_clear_error(); +} +# endif + +static int afalg_init(ENGINE *e) +{ + return 1; +} + +static int afalg_finish(ENGINE *e) +{ + return 1; +} + +static int free_cbc(void) +{ + short unsigned int i; + for(i = 0; i < OSSL_NELEM(afalg_cipher_nids); i++) { + EVP_CIPHER_meth_free(cbc_handle[i]._hidden); + cbc_handle[i]._hidden = NULL; + } + return 1; +} + +static int afalg_destroy(ENGINE *e) +{ + ERR_unload_AFALG_strings(); + free_cbc(); + return 1; +} + +#endif /* KERNEL VERSION */ diff --git a/trunk/3rdparty/openssl-1.1-fit/engines/e_afalg.ec b/trunk/3rdparty/openssl-1.1-fit/engines/e_afalg.ec new file mode 100644 index 000000000..6d7420fe5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/engines/e_afalg.ec @@ -0,0 +1,3 @@ +# The INPUT HEADER is scanned for declarations +# LIBNAME INPUT HEADER ERROR-TABLE FILE +L AFALG e_afalg_err.h e_afalg_err.c diff --git a/trunk/3rdparty/openssl-1.1-fit/engines/e_afalg.h b/trunk/3rdparty/openssl-1.1-fit/engines/e_afalg.h new file mode 100644 index 000000000..2c03c448d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/engines/e_afalg.h @@ -0,0 +1,95 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_AFALG_H +# define HEADER_AFALG_H + +# if defined(__GNUC__) && __GNUC__ >= 4 && \ + (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L) +# pragma GCC diagnostic ignored "-Wvariadic-macros" +# endif + +# ifdef ALG_DEBUG +# define ALG_DGB(x, ...) fprintf(stderr, "ALG_DBG: " x, __VA_ARGS__) +# define ALG_INFO(x, ...) fprintf(stderr, "ALG_INFO: " x, __VA_ARGS__) +# define ALG_WARN(x, ...) fprintf(stderr, "ALG_WARN: " x, __VA_ARGS__) +# else +# define ALG_DGB(x, ...) +# define ALG_INFO(x, ...) +# define ALG_WARN(x, ...) +# endif + +# define ALG_ERR(x, ...) fprintf(stderr, "ALG_ERR: " x, __VA_ARGS__) +# define ALG_PERR(x, ...) \ + do { \ + fprintf(stderr, "ALG_PERR: " x, __VA_ARGS__); \ + perror(NULL); \ + } while(0) +# define ALG_PWARN(x, ...) \ + do { \ + fprintf(stderr, "ALG_PERR: " x, __VA_ARGS__); \ + perror(NULL); \ + } while(0) + +# ifndef AES_BLOCK_SIZE +# define AES_BLOCK_SIZE 16 +# endif +# define AES_KEY_SIZE_128 16 +# define AES_KEY_SIZE_192 24 +# define AES_KEY_SIZE_256 32 +# define AES_IV_LEN 16 + +# define MAX_INFLIGHTS 1 + +typedef enum { + MODE_UNINIT = 0, + MODE_SYNC, + MODE_ASYNC +} op_mode; + +enum { + AES_CBC_128 = 0, + AES_CBC_192, + AES_CBC_256 +}; + +struct cbc_cipher_handles { + int key_size; + EVP_CIPHER *_hidden; +}; + +typedef struct cbc_cipher_handles cbc_handles; + +struct afalg_aio_st { + int efd; + op_mode mode; + aio_context_t aio_ctx; + struct io_event events[MAX_INFLIGHTS]; + struct iocb cbt[MAX_INFLIGHTS]; +}; +typedef struct afalg_aio_st afalg_aio; + +/* + * MAGIC Number to identify correct initialisation + * of afalg_ctx. + */ +# define MAGIC_INIT_NUM 0x1890671 + +struct afalg_ctx_st { + int init_done; + int sfd; + int bfd; +# ifdef ALG_ZERO_COPY + int zc_pipe[2]; +# endif + afalg_aio aio; +}; + +typedef struct afalg_ctx_st afalg_ctx; +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/engines/e_afalg.txt b/trunk/3rdparty/openssl-1.1-fit/engines/e_afalg.txt new file mode 100644 index 000000000..3b79305ac --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/engines/e_afalg.txt @@ -0,0 +1,30 @@ +# Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# Function codes +AFALG_F_AFALG_CHK_PLATFORM:100:afalg_chk_platform +AFALG_F_AFALG_CREATE_SK:101:afalg_create_sk +AFALG_F_AFALG_INIT_AIO:102:afalg_init_aio +AFALG_F_AFALG_SETUP_ASYNC_EVENT_NOTIFICATION:103:\ + afalg_setup_async_event_notification +AFALG_F_AFALG_SET_KEY:104:afalg_set_key +AFALG_F_BIND_AFALG:105:bind_afalg + +#Reason codes +AFALG_R_EVENTFD_FAILED:108:eventfd failed +AFALG_R_FAILED_TO_GET_PLATFORM_INFO:111:failed to get platform info +AFALG_R_INIT_FAILED:100:init failed +AFALG_R_IO_SETUP_FAILED:105:io setup failed +AFALG_R_KERNEL_DOES_NOT_SUPPORT_AFALG:101:kernel does not support afalg +AFALG_R_KERNEL_DOES_NOT_SUPPORT_ASYNC_AFALG:107:\ + kernel does not support async afalg +AFALG_R_MEM_ALLOC_FAILED:102:mem alloc failed +AFALG_R_SOCKET_ACCEPT_FAILED:110:socket accept failed +AFALG_R_SOCKET_BIND_FAILED:103:socket bind failed +AFALG_R_SOCKET_CREATE_FAILED:109:socket create failed +AFALG_R_SOCKET_OPERATION_FAILED:104:socket operation failed +AFALG_R_SOCKET_SET_KEY_FAILED:106:socket set key failed diff --git a/trunk/3rdparty/openssl-1.1-fit/engines/e_afalg_err.c b/trunk/3rdparty/openssl-1.1-fit/engines/e_afalg_err.c new file mode 100644 index 000000000..18fe9c34e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/engines/e_afalg_err.c @@ -0,0 +1,83 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "e_afalg_err.h" + +#ifndef OPENSSL_NO_ERR + +static ERR_STRING_DATA AFALG_str_functs[] = { + {ERR_PACK(0, AFALG_F_AFALG_CHK_PLATFORM, 0), "afalg_chk_platform"}, + {ERR_PACK(0, AFALG_F_AFALG_CREATE_SK, 0), "afalg_create_sk"}, + {ERR_PACK(0, AFALG_F_AFALG_INIT_AIO, 0), "afalg_init_aio"}, + {ERR_PACK(0, AFALG_F_AFALG_SETUP_ASYNC_EVENT_NOTIFICATION, 0), + "afalg_setup_async_event_notification"}, + {ERR_PACK(0, AFALG_F_AFALG_SET_KEY, 0), "afalg_set_key"}, + {ERR_PACK(0, AFALG_F_BIND_AFALG, 0), "bind_afalg"}, + {0, NULL} +}; + +static ERR_STRING_DATA AFALG_str_reasons[] = { + {ERR_PACK(0, 0, AFALG_R_EVENTFD_FAILED), "eventfd failed"}, + {ERR_PACK(0, 0, AFALG_R_FAILED_TO_GET_PLATFORM_INFO), + "failed to get platform info"}, + {ERR_PACK(0, 0, AFALG_R_INIT_FAILED), "init failed"}, + {ERR_PACK(0, 0, AFALG_R_IO_SETUP_FAILED), "io setup failed"}, + {ERR_PACK(0, 0, AFALG_R_KERNEL_DOES_NOT_SUPPORT_AFALG), + "kernel does not support afalg"}, + {ERR_PACK(0, 0, AFALG_R_KERNEL_DOES_NOT_SUPPORT_ASYNC_AFALG), + "kernel does not support async afalg"}, + {ERR_PACK(0, 0, AFALG_R_MEM_ALLOC_FAILED), "mem alloc failed"}, + {ERR_PACK(0, 0, AFALG_R_SOCKET_ACCEPT_FAILED), "socket accept failed"}, + {ERR_PACK(0, 0, AFALG_R_SOCKET_BIND_FAILED), "socket bind failed"}, + {ERR_PACK(0, 0, AFALG_R_SOCKET_CREATE_FAILED), "socket create failed"}, + {ERR_PACK(0, 0, AFALG_R_SOCKET_OPERATION_FAILED), + "socket operation failed"}, + {ERR_PACK(0, 0, AFALG_R_SOCKET_SET_KEY_FAILED), "socket set key failed"}, + {0, NULL} +}; + +#endif + +static int lib_code = 0; +static int error_loaded = 0; + +static int ERR_load_AFALG_strings(void) +{ + if (lib_code == 0) + lib_code = ERR_get_next_error_library(); + + if (!error_loaded) { +#ifndef OPENSSL_NO_ERR + ERR_load_strings(lib_code, AFALG_str_functs); + ERR_load_strings(lib_code, AFALG_str_reasons); +#endif + error_loaded = 1; + } + return 1; +} + +static void ERR_unload_AFALG_strings(void) +{ + if (error_loaded) { +#ifndef OPENSSL_NO_ERR + ERR_unload_strings(lib_code, AFALG_str_functs); + ERR_unload_strings(lib_code, AFALG_str_reasons); +#endif + error_loaded = 0; + } +} + +static void ERR_AFALG_error(int function, int reason, char *file, int line) +{ + if (lib_code == 0) + lib_code = ERR_get_next_error_library(); + ERR_PUT_error(lib_code, function, reason, file, line); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/engines/e_afalg_err.h b/trunk/3rdparty/openssl-1.1-fit/engines/e_afalg_err.h new file mode 100644 index 000000000..3eb1332bb --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/engines/e_afalg_err.h @@ -0,0 +1,43 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_AFALGERR_H +# define HEADER_AFALGERR_H + +# define AFALGerr(f, r) ERR_AFALG_error((f), (r), OPENSSL_FILE, OPENSSL_LINE) + + +/* + * AFALG function codes. + */ +# define AFALG_F_AFALG_CHK_PLATFORM 100 +# define AFALG_F_AFALG_CREATE_SK 101 +# define AFALG_F_AFALG_INIT_AIO 102 +# define AFALG_F_AFALG_SETUP_ASYNC_EVENT_NOTIFICATION 103 +# define AFALG_F_AFALG_SET_KEY 104 +# define AFALG_F_BIND_AFALG 105 + +/* + * AFALG reason codes. + */ +# define AFALG_R_EVENTFD_FAILED 108 +# define AFALG_R_FAILED_TO_GET_PLATFORM_INFO 111 +# define AFALG_R_INIT_FAILED 100 +# define AFALG_R_IO_SETUP_FAILED 105 +# define AFALG_R_KERNEL_DOES_NOT_SUPPORT_AFALG 101 +# define AFALG_R_KERNEL_DOES_NOT_SUPPORT_ASYNC_AFALG 107 +# define AFALG_R_MEM_ALLOC_FAILED 102 +# define AFALG_R_SOCKET_ACCEPT_FAILED 110 +# define AFALG_R_SOCKET_BIND_FAILED 103 +# define AFALG_R_SOCKET_CREATE_FAILED 109 +# define AFALG_R_SOCKET_OPERATION_FAILED 104 +# define AFALG_R_SOCKET_SET_KEY_FAILED 106 + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/engines/e_capi.c b/trunk/3rdparty/openssl-1.1-fit/engines/e_capi.c new file mode 100644 index 000000000..37202b81f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/engines/e_capi.c @@ -0,0 +1,1904 @@ +/* + * Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifdef _WIN32 +# ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x0400 +# endif +# include +# include + +# include +# include +# include +# include +# ifndef alloca +# define alloca _alloca +# endif + +# include + +# ifndef OPENSSL_NO_CAPIENG + +# include +# include +# include +# include + +/* + * This module uses several "new" interfaces, among which is + * CertGetCertificateContextProperty. CERT_KEY_PROV_INFO_PROP_ID is + * one of possible values you can pass to function in question. By + * checking if it's defined we can see if wincrypt.h and accompanying + * crypt32.lib are in shape. The native MingW32 headers up to and + * including __W32API_VERSION 3.14 lack of struct DSSPUBKEY and the + * defines CERT_STORE_PROV_SYSTEM_A and CERT_STORE_READONLY_FLAG, + * so we check for these too and avoid compiling. + * Yes, it's rather "weak" test and if compilation fails, + * then re-configure with -DOPENSSL_NO_CAPIENG. + */ +# if defined(CERT_KEY_PROV_INFO_PROP_ID) && \ + defined(CERT_STORE_PROV_SYSTEM_A) && \ + defined(CERT_STORE_READONLY_FLAG) +# define __COMPILE_CAPIENG +# endif /* CERT_KEY_PROV_INFO_PROP_ID */ +# endif /* OPENSSL_NO_CAPIENG */ +#endif /* _WIN32 */ + +#ifdef __COMPILE_CAPIENG + +# undef X509_EXTENSIONS + +/* Definitions which may be missing from earlier version of headers */ +# ifndef CERT_STORE_OPEN_EXISTING_FLAG +# define CERT_STORE_OPEN_EXISTING_FLAG 0x00004000 +# endif + +# ifndef CERT_STORE_CREATE_NEW_FLAG +# define CERT_STORE_CREATE_NEW_FLAG 0x00002000 +# endif + +# ifndef CERT_SYSTEM_STORE_CURRENT_USER +# define CERT_SYSTEM_STORE_CURRENT_USER 0x00010000 +# endif + +# ifndef ALG_SID_SHA_256 +# define ALG_SID_SHA_256 12 +# endif +# ifndef ALG_SID_SHA_384 +# define ALG_SID_SHA_384 13 +# endif +# ifndef ALG_SID_SHA_512 +# define ALG_SID_SHA_512 14 +# endif + +# ifndef CALG_SHA_256 +# define CALG_SHA_256 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_256) +# endif +# ifndef CALG_SHA_384 +# define CALG_SHA_384 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_384) +# endif +# ifndef CALG_SHA_512 +# define CALG_SHA_512 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_512) +# endif + +# ifndef PROV_RSA_AES +# define PROV_RSA_AES 24 +# endif + +# include +# include +# include + +# include "e_capi_err.h" +# include "e_capi_err.c" + +static const char *engine_capi_id = "capi"; +static const char *engine_capi_name = "CryptoAPI ENGINE"; + +typedef struct CAPI_CTX_st CAPI_CTX; +typedef struct CAPI_KEY_st CAPI_KEY; + +static void capi_addlasterror(void); +static void capi_adderror(DWORD err); + +static void CAPI_trace(CAPI_CTX *ctx, char *format, ...); + +static int capi_list_providers(CAPI_CTX *ctx, BIO *out); +static int capi_list_containers(CAPI_CTX *ctx, BIO *out); +int capi_list_certs(CAPI_CTX *ctx, BIO *out, char *storename); +void capi_free_key(CAPI_KEY *key); + +static PCCERT_CONTEXT capi_find_cert(CAPI_CTX *ctx, const char *id, + HCERTSTORE hstore); + +CAPI_KEY *capi_find_key(CAPI_CTX *ctx, const char *id); + +static EVP_PKEY *capi_load_privkey(ENGINE *eng, const char *key_id, + UI_METHOD *ui_method, void *callback_data); +static int capi_rsa_sign(int dtype, const unsigned char *m, + unsigned int m_len, unsigned char *sigret, + unsigned int *siglen, const RSA *rsa); +static int capi_rsa_priv_enc(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int capi_rsa_priv_dec(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int capi_rsa_free(RSA *rsa); + +# ifndef OPENSSL_NO_DSA +static DSA_SIG *capi_dsa_do_sign(const unsigned char *digest, int dlen, + DSA *dsa); +static int capi_dsa_free(DSA *dsa); +# endif + +static int capi_load_ssl_client_cert(ENGINE *e, SSL *ssl, + STACK_OF(X509_NAME) *ca_dn, X509 **pcert, + EVP_PKEY **pkey, STACK_OF(X509) **pother, + UI_METHOD *ui_method, + void *callback_data); + +static int cert_select_simple(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs); +# ifdef OPENSSL_CAPIENG_DIALOG +static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs); +# endif + +void engine_load_capi_int(void); + +typedef PCCERT_CONTEXT(WINAPI *CERTDLG)(HCERTSTORE, HWND, LPCWSTR, + LPCWSTR, DWORD, DWORD, void *); +typedef HWND(WINAPI *GETCONSWIN)(void); + +/* + * This structure contains CAPI ENGINE specific data: it contains various + * global options and affects how other functions behave. + */ + +# define CAPI_DBG_TRACE 2 +# define CAPI_DBG_ERROR 1 + +struct CAPI_CTX_st { + int debug_level; + char *debug_file; + /* Parameters to use for container lookup */ + DWORD keytype; + LPSTR cspname; + DWORD csptype; + /* Certificate store name to use */ + LPSTR storename; + LPSTR ssl_client_store; + /* System store flags */ + DWORD store_flags; +/* Lookup string meanings in load_private_key */ +# define CAPI_LU_SUBSTR 1 /* Substring of subject: uses "storename" */ +# define CAPI_LU_FNAME 2 /* Friendly name: uses storename */ +# define CAPI_LU_CONTNAME 3 /* Container name: uses cspname, keytype */ + int lookup_method; +/* Info to dump with dumpcerts option */ +# define CAPI_DMP_SUMMARY 0x1 /* Issuer and serial name strings */ +# define CAPI_DMP_FNAME 0x2 /* Friendly name */ +# define CAPI_DMP_FULL 0x4 /* Full X509_print dump */ +# define CAPI_DMP_PEM 0x8 /* Dump PEM format certificate */ +# define CAPI_DMP_PSKEY 0x10 /* Dump pseudo key (if possible) */ +# define CAPI_DMP_PKEYINFO 0x20 /* Dump key info (if possible) */ + DWORD dump_flags; + int (*client_cert_select) (ENGINE *e, SSL *ssl, STACK_OF(X509) *certs); + CERTDLG certselectdlg; + GETCONSWIN getconswindow; +}; + +static CAPI_CTX *capi_ctx_new(void); +static void capi_ctx_free(CAPI_CTX *ctx); +static int capi_ctx_set_provname(CAPI_CTX *ctx, LPSTR pname, DWORD type, + int check); +static int capi_ctx_set_provname_idx(CAPI_CTX *ctx, int idx); + +# define CAPI_CMD_LIST_CERTS ENGINE_CMD_BASE +# define CAPI_CMD_LOOKUP_CERT (ENGINE_CMD_BASE + 1) +# define CAPI_CMD_DEBUG_LEVEL (ENGINE_CMD_BASE + 2) +# define CAPI_CMD_DEBUG_FILE (ENGINE_CMD_BASE + 3) +# define CAPI_CMD_KEYTYPE (ENGINE_CMD_BASE + 4) +# define CAPI_CMD_LIST_CSPS (ENGINE_CMD_BASE + 5) +# define CAPI_CMD_SET_CSP_IDX (ENGINE_CMD_BASE + 6) +# define CAPI_CMD_SET_CSP_NAME (ENGINE_CMD_BASE + 7) +# define CAPI_CMD_SET_CSP_TYPE (ENGINE_CMD_BASE + 8) +# define CAPI_CMD_LIST_CONTAINERS (ENGINE_CMD_BASE + 9) +# define CAPI_CMD_LIST_OPTIONS (ENGINE_CMD_BASE + 10) +# define CAPI_CMD_LOOKUP_METHOD (ENGINE_CMD_BASE + 11) +# define CAPI_CMD_STORE_NAME (ENGINE_CMD_BASE + 12) +# define CAPI_CMD_STORE_FLAGS (ENGINE_CMD_BASE + 13) + +static const ENGINE_CMD_DEFN capi_cmd_defns[] = { + {CAPI_CMD_LIST_CERTS, + "list_certs", + "List all certificates in store", + ENGINE_CMD_FLAG_NO_INPUT}, + {CAPI_CMD_LOOKUP_CERT, + "lookup_cert", + "Lookup and output certificates", + ENGINE_CMD_FLAG_STRING}, + {CAPI_CMD_DEBUG_LEVEL, + "debug_level", + "debug level (1=errors, 2=trace)", + ENGINE_CMD_FLAG_NUMERIC}, + {CAPI_CMD_DEBUG_FILE, + "debug_file", + "debugging filename)", + ENGINE_CMD_FLAG_STRING}, + {CAPI_CMD_KEYTYPE, + "key_type", + "Key type: 1=AT_KEYEXCHANGE (default), 2=AT_SIGNATURE", + ENGINE_CMD_FLAG_NUMERIC}, + {CAPI_CMD_LIST_CSPS, + "list_csps", + "List all CSPs", + ENGINE_CMD_FLAG_NO_INPUT}, + {CAPI_CMD_SET_CSP_IDX, + "csp_idx", + "Set CSP by index", + ENGINE_CMD_FLAG_NUMERIC}, + {CAPI_CMD_SET_CSP_NAME, + "csp_name", + "Set CSP name, (default CSP used if not specified)", + ENGINE_CMD_FLAG_STRING}, + {CAPI_CMD_SET_CSP_TYPE, + "csp_type", + "Set CSP type, (default RSA_PROV_FULL)", + ENGINE_CMD_FLAG_NUMERIC}, + {CAPI_CMD_LIST_CONTAINERS, + "list_containers", + "list container names", + ENGINE_CMD_FLAG_NO_INPUT}, + {CAPI_CMD_LIST_OPTIONS, + "list_options", + "Set list options (1=summary,2=friendly name, 4=full printout, 8=PEM output, 16=XXX, " + "32=private key info)", + ENGINE_CMD_FLAG_NUMERIC}, + {CAPI_CMD_LOOKUP_METHOD, + "lookup_method", + "Set key lookup method (1=substring, 2=friendlyname, 3=container name)", + ENGINE_CMD_FLAG_NUMERIC}, + {CAPI_CMD_STORE_NAME, + "store_name", + "certificate store name, default \"MY\"", + ENGINE_CMD_FLAG_STRING}, + {CAPI_CMD_STORE_FLAGS, + "store_flags", + "Certificate store flags: 1 = system store", + ENGINE_CMD_FLAG_NUMERIC}, + + {0, NULL, NULL, 0} +}; + +static int capi_idx = -1; +static int rsa_capi_idx = -1; +static int dsa_capi_idx = -1; +static int cert_capi_idx = -1; + +static int capi_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)) +{ + int ret = 1; + CAPI_CTX *ctx; + BIO *out; + LPSTR tmpstr; + if (capi_idx == -1) { + CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_ENGINE_NOT_INITIALIZED); + return 0; + } + ctx = ENGINE_get_ex_data(e, capi_idx); + out = BIO_new_fp(stdout, BIO_NOCLOSE); + if (out == NULL) { + CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_FILE_OPEN_ERROR); + return 0; + } + switch (cmd) { + case CAPI_CMD_LIST_CSPS: + ret = capi_list_providers(ctx, out); + break; + + case CAPI_CMD_LIST_CERTS: + ret = capi_list_certs(ctx, out, NULL); + break; + + case CAPI_CMD_LOOKUP_CERT: + ret = capi_list_certs(ctx, out, p); + break; + + case CAPI_CMD_LIST_CONTAINERS: + ret = capi_list_containers(ctx, out); + break; + + case CAPI_CMD_STORE_NAME: + tmpstr = OPENSSL_strdup(p); + if (tmpstr != NULL) { + OPENSSL_free(ctx->storename); + ctx->storename = tmpstr; + CAPI_trace(ctx, "Setting store name to %s\n", p); + } else { + CAPIerr(CAPI_F_CAPI_CTRL, ERR_R_MALLOC_FAILURE); + ret = 0; + } + break; + + case CAPI_CMD_STORE_FLAGS: + if (i & 1) { + ctx->store_flags |= CERT_SYSTEM_STORE_LOCAL_MACHINE; + ctx->store_flags &= ~CERT_SYSTEM_STORE_CURRENT_USER; + } else { + ctx->store_flags |= CERT_SYSTEM_STORE_CURRENT_USER; + ctx->store_flags &= ~CERT_SYSTEM_STORE_LOCAL_MACHINE; + } + CAPI_trace(ctx, "Setting flags to %d\n", i); + break; + + case CAPI_CMD_DEBUG_LEVEL: + ctx->debug_level = (int)i; + CAPI_trace(ctx, "Setting debug level to %d\n", ctx->debug_level); + break; + + case CAPI_CMD_DEBUG_FILE: + tmpstr = OPENSSL_strdup(p); + if (tmpstr != NULL) { + ctx->debug_file = tmpstr; + CAPI_trace(ctx, "Setting debug file to %s\n", ctx->debug_file); + } else { + CAPIerr(CAPI_F_CAPI_CTRL, ERR_R_MALLOC_FAILURE); + ret = 0; + } + break; + + case CAPI_CMD_KEYTYPE: + ctx->keytype = i; + CAPI_trace(ctx, "Setting key type to %d\n", ctx->keytype); + break; + + case CAPI_CMD_SET_CSP_IDX: + ret = capi_ctx_set_provname_idx(ctx, i); + break; + + case CAPI_CMD_LIST_OPTIONS: + ctx->dump_flags = i; + break; + + case CAPI_CMD_LOOKUP_METHOD: + if (i < 1 || i > 3) { + CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_INVALID_LOOKUP_METHOD); + BIO_free(out); + return 0; + } + ctx->lookup_method = i; + break; + + case CAPI_CMD_SET_CSP_NAME: + ret = capi_ctx_set_provname(ctx, p, ctx->csptype, 1); + break; + + case CAPI_CMD_SET_CSP_TYPE: + ctx->csptype = i; + break; + + default: + CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_UNKNOWN_COMMAND); + ret = 0; + } + + BIO_free(out); + return ret; + +} + +static RSA_METHOD *capi_rsa_method = NULL; +# ifndef OPENSSL_NO_DSA +static DSA_METHOD *capi_dsa_method = NULL; +# endif + +static int use_aes_csp = 0; +static const WCHAR rsa_aes_cspname[] = + L"Microsoft Enhanced RSA and AES Cryptographic Provider"; +static const WCHAR rsa_enh_cspname[] = + L"Microsoft Enhanced Cryptographic Provider v1.0"; + +static int capi_init(ENGINE *e) +{ + CAPI_CTX *ctx; + const RSA_METHOD *ossl_rsa_meth; +# ifndef OPENSSL_NO_DSA + const DSA_METHOD *ossl_dsa_meth; +# endif + HCRYPTPROV hprov; + + if (capi_idx < 0) { + capi_idx = ENGINE_get_ex_new_index(0, NULL, NULL, NULL, 0); + if (capi_idx < 0) + goto memerr; + + cert_capi_idx = X509_get_ex_new_index(0, NULL, NULL, NULL, 0); + + /* Setup RSA_METHOD */ + rsa_capi_idx = RSA_get_ex_new_index(0, NULL, NULL, NULL, 0); + ossl_rsa_meth = RSA_PKCS1_OpenSSL(); + if ( !RSA_meth_set_pub_enc(capi_rsa_method, + RSA_meth_get_pub_enc(ossl_rsa_meth)) + || !RSA_meth_set_pub_dec(capi_rsa_method, + RSA_meth_get_pub_dec(ossl_rsa_meth)) + || !RSA_meth_set_priv_enc(capi_rsa_method, capi_rsa_priv_enc) + || !RSA_meth_set_priv_dec(capi_rsa_method, capi_rsa_priv_dec) + || !RSA_meth_set_mod_exp(capi_rsa_method, + RSA_meth_get_mod_exp(ossl_rsa_meth)) + || !RSA_meth_set_bn_mod_exp(capi_rsa_method, + RSA_meth_get_bn_mod_exp(ossl_rsa_meth)) + || !RSA_meth_set_finish(capi_rsa_method, capi_rsa_free) + || !RSA_meth_set_sign(capi_rsa_method, capi_rsa_sign)) { + goto memerr; + } + +# ifndef OPENSSL_NO_DSA + /* Setup DSA Method */ + dsa_capi_idx = DSA_get_ex_new_index(0, NULL, NULL, NULL, 0); + ossl_dsa_meth = DSA_OpenSSL(); + if ( !DSA_meth_set_sign(capi_dsa_method, capi_dsa_do_sign) + || !DSA_meth_set_verify(capi_dsa_method, + DSA_meth_get_verify(ossl_dsa_meth)) + || !DSA_meth_set_finish(capi_dsa_method, capi_dsa_free) + || !DSA_meth_set_mod_exp(capi_dsa_method, + DSA_meth_get_mod_exp(ossl_dsa_meth)) + || !DSA_meth_set_bn_mod_exp(capi_dsa_method, + DSA_meth_get_bn_mod_exp(ossl_dsa_meth))) { + goto memerr; + } +# endif + } + + ctx = capi_ctx_new(); + if (ctx == NULL) + goto memerr; + + ENGINE_set_ex_data(e, capi_idx, ctx); + +# ifdef OPENSSL_CAPIENG_DIALOG + { + HMODULE cryptui = LoadLibrary(TEXT("CRYPTUI.DLL")); + HMODULE kernel = GetModuleHandle(TEXT("KERNEL32.DLL")); + if (cryptui) + ctx->certselectdlg = + (CERTDLG) GetProcAddress(cryptui, + "CryptUIDlgSelectCertificateFromStore"); + if (kernel) + ctx->getconswindow = + (GETCONSWIN) GetProcAddress(kernel, "GetConsoleWindow"); + if (cryptui && !OPENSSL_isservice()) + ctx->client_cert_select = cert_select_dialog; + } +# endif + + /* See if there is RSA+AES CSP */ + if (CryptAcquireContextW(&hprov, NULL, rsa_aes_cspname, PROV_RSA_AES, + CRYPT_VERIFYCONTEXT)) { + use_aes_csp = 1; + CryptReleaseContext(hprov, 0); + } + + return 1; + + memerr: + CAPIerr(CAPI_F_CAPI_INIT, ERR_R_MALLOC_FAILURE); + return 0; + + return 1; +} + +static int capi_destroy(ENGINE *e) +{ + RSA_meth_free(capi_rsa_method); + capi_rsa_method = NULL; +# ifndef OPENSSL_NO_DSA + DSA_meth_free(capi_dsa_method); + capi_dsa_method = NULL; +# endif + ERR_unload_CAPI_strings(); + return 1; +} + +static int capi_finish(ENGINE *e) +{ + CAPI_CTX *ctx; + ctx = ENGINE_get_ex_data(e, capi_idx); + capi_ctx_free(ctx); + ENGINE_set_ex_data(e, capi_idx, NULL); + return 1; +} + +/* + * CryptoAPI key application data. This contains a handle to the private key + * container (for sign operations) and a handle to the key (for decrypt + * operations). + */ + +struct CAPI_KEY_st { + /* Associated certificate context (if any) */ + PCCERT_CONTEXT pcert; + HCRYPTPROV hprov; + HCRYPTKEY key; + DWORD keyspec; +}; + +static int bind_capi(ENGINE *e) +{ + capi_rsa_method = RSA_meth_new("CryptoAPI RSA method", 0); + if (capi_rsa_method == NULL) + return 0; +# ifndef OPENSSL_NO_DSA + capi_dsa_method = DSA_meth_new("CryptoAPI DSA method", 0); + if (capi_dsa_method == NULL) + goto memerr; +# endif + if (!ENGINE_set_id(e, engine_capi_id) + || !ENGINE_set_name(e, engine_capi_name) + || !ENGINE_set_flags(e, ENGINE_FLAGS_NO_REGISTER_ALL) + || !ENGINE_set_init_function(e, capi_init) + || !ENGINE_set_finish_function(e, capi_finish) + || !ENGINE_set_destroy_function(e, capi_destroy) + || !ENGINE_set_RSA(e, capi_rsa_method) +# ifndef OPENSSL_NO_DSA + || !ENGINE_set_DSA(e, capi_dsa_method) +# endif + || !ENGINE_set_load_privkey_function(e, capi_load_privkey) + || !ENGINE_set_load_ssl_client_cert_function(e, + capi_load_ssl_client_cert) + || !ENGINE_set_cmd_defns(e, capi_cmd_defns) + || !ENGINE_set_ctrl_function(e, capi_ctrl)) + goto memerr; + ERR_load_CAPI_strings(); + + return 1; + memerr: + RSA_meth_free(capi_rsa_method); + capi_rsa_method = NULL; +# ifndef OPENSSL_NO_DSA + DSA_meth_free(capi_dsa_method); + capi_dsa_method = NULL; +# endif + return 0; +} + +# ifndef OPENSSL_NO_DYNAMIC_ENGINE +static int bind_helper(ENGINE *e, const char *id) +{ + if (id && (strcmp(id, engine_capi_id) != 0)) + return 0; + if (!bind_capi(e)) + return 0; + return 1; +} + +IMPLEMENT_DYNAMIC_CHECK_FN() +IMPLEMENT_DYNAMIC_BIND_FN(bind_helper) +# else +static ENGINE *engine_capi(void) +{ + ENGINE *ret = ENGINE_new(); + if (ret == NULL) + return NULL; + if (!bind_capi(ret)) { + ENGINE_free(ret); + return NULL; + } + return ret; +} + +void engine_load_capi_int(void) +{ + /* Copied from eng_[openssl|dyn].c */ + ENGINE *toadd = engine_capi(); + if (!toadd) + return; + ENGINE_add(toadd); + ENGINE_free(toadd); + ERR_clear_error(); +} +# endif + +static int lend_tobn(BIGNUM *bn, unsigned char *bin, int binlen) +{ + int i; + /* + * Reverse buffer in place: since this is a keyblob structure that will + * be freed up after conversion anyway it doesn't matter if we change + * it. + */ + for (i = 0; i < binlen / 2; i++) { + unsigned char c; + c = bin[i]; + bin[i] = bin[binlen - i - 1]; + bin[binlen - i - 1] = c; + } + + if (!BN_bin2bn(bin, binlen, bn)) + return 0; + return 1; +} + +/* Given a CAPI_KEY get an EVP_PKEY structure */ + +static EVP_PKEY *capi_get_pkey(ENGINE *eng, CAPI_KEY *key) +{ + unsigned char *pubkey = NULL; + DWORD len; + BLOBHEADER *bh; + RSA *rkey = NULL; + DSA *dkey = NULL; + EVP_PKEY *ret = NULL; + if (!CryptExportKey(key->key, 0, PUBLICKEYBLOB, 0, NULL, &len)) { + CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_PUBKEY_EXPORT_LENGTH_ERROR); + capi_addlasterror(); + return NULL; + } + + pubkey = OPENSSL_malloc(len); + + if (pubkey == NULL) + goto memerr; + + if (!CryptExportKey(key->key, 0, PUBLICKEYBLOB, 0, pubkey, &len)) { + CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_PUBKEY_EXPORT_ERROR); + capi_addlasterror(); + goto err; + } + + bh = (BLOBHEADER *) pubkey; + if (bh->bType != PUBLICKEYBLOB) { + CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_INVALID_PUBLIC_KEY_BLOB); + goto err; + } + if (bh->aiKeyAlg == CALG_RSA_SIGN || bh->aiKeyAlg == CALG_RSA_KEYX) { + RSAPUBKEY *rp; + DWORD rsa_modlen; + BIGNUM *e = NULL, *n = NULL; + unsigned char *rsa_modulus; + rp = (RSAPUBKEY *) (bh + 1); + if (rp->magic != 0x31415352) { + char magstr[10]; + BIO_snprintf(magstr, 10, "%lx", rp->magic); + CAPIerr(CAPI_F_CAPI_GET_PKEY, + CAPI_R_INVALID_RSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER); + ERR_add_error_data(2, "magic=0x", magstr); + goto err; + } + rsa_modulus = (unsigned char *)(rp + 1); + rkey = RSA_new_method(eng); + if (!rkey) + goto memerr; + + e = BN_new(); + n = BN_new(); + + if (e == NULL || n == NULL) { + BN_free(e); + BN_free(n); + goto memerr; + } + + RSA_set0_key(rkey, n, e, NULL); + + if (!BN_set_word(e, rp->pubexp)) + goto memerr; + + rsa_modlen = rp->bitlen / 8; + if (!lend_tobn(n, rsa_modulus, rsa_modlen)) + goto memerr; + + RSA_set_ex_data(rkey, rsa_capi_idx, key); + + if ((ret = EVP_PKEY_new()) == NULL) + goto memerr; + + EVP_PKEY_assign_RSA(ret, rkey); + rkey = NULL; + +# ifndef OPENSSL_NO_DSA + } else if (bh->aiKeyAlg == CALG_DSS_SIGN) { + DSSPUBKEY *dp; + DWORD dsa_plen; + unsigned char *btmp; + BIGNUM *p, *q, *g, *pub_key; + dp = (DSSPUBKEY *) (bh + 1); + if (dp->magic != 0x31535344) { + char magstr[10]; + BIO_snprintf(magstr, 10, "%lx", dp->magic); + CAPIerr(CAPI_F_CAPI_GET_PKEY, + CAPI_R_INVALID_DSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER); + ERR_add_error_data(2, "magic=0x", magstr); + goto err; + } + dsa_plen = dp->bitlen / 8; + btmp = (unsigned char *)(dp + 1); + dkey = DSA_new_method(eng); + if (!dkey) + goto memerr; + p = BN_new(); + q = BN_new(); + g = BN_new(); + pub_key = BN_new(); + if (p == NULL || q == NULL || g == NULL || pub_key == NULL) { + BN_free(p); + BN_free(q); + BN_free(g); + BN_free(pub_key); + goto memerr; + } + DSA_set0_pqg(dkey, p, q, g); + DSA_set0_key(dkey, pub_key, NULL); + if (!lend_tobn(p, btmp, dsa_plen)) + goto memerr; + btmp += dsa_plen; + if (!lend_tobn(q, btmp, 20)) + goto memerr; + btmp += 20; + if (!lend_tobn(g, btmp, dsa_plen)) + goto memerr; + btmp += dsa_plen; + if (!lend_tobn(pub_key, btmp, dsa_plen)) + goto memerr; + btmp += dsa_plen; + + DSA_set_ex_data(dkey, dsa_capi_idx, key); + + if ((ret = EVP_PKEY_new()) == NULL) + goto memerr; + + EVP_PKEY_assign_DSA(ret, dkey); + dkey = NULL; +# endif + } else { + char algstr[10]; + BIO_snprintf(algstr, 10, "%ux", bh->aiKeyAlg); + CAPIerr(CAPI_F_CAPI_GET_PKEY, + CAPI_R_UNSUPPORTED_PUBLIC_KEY_ALGORITHM); + ERR_add_error_data(2, "aiKeyAlg=0x", algstr); + goto err; + } + + err: + OPENSSL_free(pubkey); + if (!ret) { + RSA_free(rkey); +# ifndef OPENSSL_NO_DSA + DSA_free(dkey); +# endif + } + + return ret; + + memerr: + CAPIerr(CAPI_F_CAPI_GET_PKEY, ERR_R_MALLOC_FAILURE); + goto err; + +} + +static EVP_PKEY *capi_load_privkey(ENGINE *eng, const char *key_id, + UI_METHOD *ui_method, void *callback_data) +{ + CAPI_CTX *ctx; + CAPI_KEY *key; + EVP_PKEY *ret; + ctx = ENGINE_get_ex_data(eng, capi_idx); + + if (!ctx) { + CAPIerr(CAPI_F_CAPI_LOAD_PRIVKEY, CAPI_R_CANT_FIND_CAPI_CONTEXT); + return NULL; + } + + key = capi_find_key(ctx, key_id); + + if (!key) + return NULL; + + ret = capi_get_pkey(eng, key); + + if (!ret) + capi_free_key(key); + return ret; + +} + +/* CryptoAPI RSA operations */ + +int capi_rsa_priv_enc(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) +{ + CAPIerr(CAPI_F_CAPI_RSA_PRIV_ENC, CAPI_R_FUNCTION_NOT_SUPPORTED); + return -1; +} + +int capi_rsa_sign(int dtype, const unsigned char *m, unsigned int m_len, + unsigned char *sigret, unsigned int *siglen, const RSA *rsa) +{ + ALG_ID alg; + HCRYPTHASH hash; + DWORD slen; + unsigned int i; + int ret = -1; + CAPI_KEY *capi_key; + CAPI_CTX *ctx; + + ctx = ENGINE_get_ex_data(RSA_get0_engine(rsa), capi_idx); + + CAPI_trace(ctx, "Called CAPI_rsa_sign()\n"); + + capi_key = RSA_get_ex_data(rsa, rsa_capi_idx); + if (!capi_key) { + CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_GET_KEY); + return -1; + } + /* Convert the signature type to a CryptoAPI algorithm ID */ + switch (dtype) { + case NID_sha256: + alg = CALG_SHA_256; + break; + + case NID_sha384: + alg = CALG_SHA_384; + break; + + case NID_sha512: + alg = CALG_SHA_512; + break; + + case NID_sha1: + alg = CALG_SHA1; + break; + + case NID_md5: + alg = CALG_MD5; + break; + + case NID_md5_sha1: + alg = CALG_SSL3_SHAMD5; + break; + default: + { + char algstr[10]; + BIO_snprintf(algstr, 10, "%x", dtype); + CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_UNSUPPORTED_ALGORITHM_NID); + ERR_add_error_data(2, "NID=0x", algstr); + return -1; + } + } + + /* Create the hash object */ + if (!CryptCreateHash(capi_key->hprov, alg, 0, 0, &hash)) { + CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_CREATE_HASH_OBJECT); + capi_addlasterror(); + return -1; + } + /* Set the hash value to the value passed */ + + if (!CryptSetHashParam(hash, HP_HASHVAL, (unsigned char *)m, 0)) { + CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_SET_HASH_VALUE); + capi_addlasterror(); + goto err; + } + + /* Finally sign it */ + slen = RSA_size(rsa); + if (!CryptSignHash(hash, capi_key->keyspec, NULL, 0, sigret, &slen)) { + CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_ERROR_SIGNING_HASH); + capi_addlasterror(); + goto err; + } else { + ret = 1; + /* Inplace byte reversal of signature */ + for (i = 0; i < slen / 2; i++) { + unsigned char c; + c = sigret[i]; + sigret[i] = sigret[slen - i - 1]; + sigret[slen - i - 1] = c; + } + *siglen = slen; + } + + /* Now cleanup */ + + err: + CryptDestroyHash(hash); + + return ret; +} + +int capi_rsa_priv_dec(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) +{ + int i; + unsigned char *tmpbuf; + CAPI_KEY *capi_key; + CAPI_CTX *ctx; + DWORD flags = 0; + DWORD dlen; + + if (flen <= 0) + return flen; + + ctx = ENGINE_get_ex_data(RSA_get0_engine(rsa), capi_idx); + + CAPI_trace(ctx, "Called capi_rsa_priv_dec()\n"); + + capi_key = RSA_get_ex_data(rsa, rsa_capi_idx); + if (!capi_key) { + CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_CANT_GET_KEY); + return -1; + } + + switch (padding) { + case RSA_PKCS1_PADDING: + /* Nothing to do */ + break; +#ifdef CRYPT_DECRYPT_RSA_NO_PADDING_CHECK + case RSA_NO_PADDING: + flags = CRYPT_DECRYPT_RSA_NO_PADDING_CHECK; + break; +#endif + default: + { + char errstr[10]; + BIO_snprintf(errstr, 10, "%d", padding); + CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_UNSUPPORTED_PADDING); + ERR_add_error_data(2, "padding=", errstr); + return -1; + } + } + + /* Create temp reverse order version of input */ + if ((tmpbuf = OPENSSL_malloc(flen)) == NULL) { + CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, ERR_R_MALLOC_FAILURE); + return -1; + } + for (i = 0; i < flen; i++) + tmpbuf[flen - i - 1] = from[i]; + + /* Finally decrypt it */ + dlen = flen; + if (!CryptDecrypt(capi_key->key, 0, TRUE, flags, tmpbuf, &dlen)) { + CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_DECRYPT_ERROR); + capi_addlasterror(); + OPENSSL_cleanse(tmpbuf, dlen); + OPENSSL_free(tmpbuf); + return -1; + } else { + memcpy(to, tmpbuf, (flen = (int)dlen)); + } + OPENSSL_cleanse(tmpbuf, flen); + OPENSSL_free(tmpbuf); + + return flen; +} + +static int capi_rsa_free(RSA *rsa) +{ + CAPI_KEY *capi_key; + capi_key = RSA_get_ex_data(rsa, rsa_capi_idx); + capi_free_key(capi_key); + RSA_set_ex_data(rsa, rsa_capi_idx, 0); + return 1; +} + +# ifndef OPENSSL_NO_DSA +/* CryptoAPI DSA operations */ + +static DSA_SIG *capi_dsa_do_sign(const unsigned char *digest, int dlen, + DSA *dsa) +{ + HCRYPTHASH hash; + DWORD slen; + DSA_SIG *ret = NULL; + CAPI_KEY *capi_key; + CAPI_CTX *ctx; + unsigned char csigbuf[40]; + + ctx = ENGINE_get_ex_data(DSA_get0_engine(dsa), capi_idx); + + CAPI_trace(ctx, "Called CAPI_dsa_do_sign()\n"); + + capi_key = DSA_get_ex_data(dsa, dsa_capi_idx); + + if (!capi_key) { + CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_GET_KEY); + return NULL; + } + + if (dlen != 20) { + CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_INVALID_DIGEST_LENGTH); + return NULL; + } + + /* Create the hash object */ + if (!CryptCreateHash(capi_key->hprov, CALG_SHA1, 0, 0, &hash)) { + CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_CREATE_HASH_OBJECT); + capi_addlasterror(); + return NULL; + } + + /* Set the hash value to the value passed */ + if (!CryptSetHashParam(hash, HP_HASHVAL, (unsigned char *)digest, 0)) { + CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_SET_HASH_VALUE); + capi_addlasterror(); + goto err; + } + + /* Finally sign it */ + slen = sizeof(csigbuf); + if (!CryptSignHash(hash, capi_key->keyspec, NULL, 0, csigbuf, &slen)) { + CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_ERROR_SIGNING_HASH); + capi_addlasterror(); + goto err; + } else { + BIGNUM *r = BN_new(), *s = BN_new(); + + if (r == NULL || s == NULL + || !lend_tobn(r, csigbuf, 20) + || !lend_tobn(s, csigbuf + 20, 20) + || (ret = DSA_SIG_new()) == NULL) { + BN_free(r); /* BN_free checks for BIGNUM * being NULL */ + BN_free(s); + goto err; + } + DSA_SIG_set0(ret, r, s); + } + + /* Now cleanup */ + + err: + OPENSSL_cleanse(csigbuf, 40); + CryptDestroyHash(hash); + return ret; +} + +static int capi_dsa_free(DSA *dsa) +{ + CAPI_KEY *capi_key; + capi_key = DSA_get_ex_data(dsa, dsa_capi_idx); + capi_free_key(capi_key); + DSA_set_ex_data(dsa, dsa_capi_idx, 0); + return 1; +} +# endif + +static void capi_vtrace(CAPI_CTX *ctx, int level, char *format, + va_list argptr) +{ + BIO *out; + + if (!ctx || (ctx->debug_level < level) || (!ctx->debug_file)) + return; + out = BIO_new_file(ctx->debug_file, "a+"); + if (out == NULL) { + CAPIerr(CAPI_F_CAPI_VTRACE, CAPI_R_FILE_OPEN_ERROR); + return; + } + BIO_vprintf(out, format, argptr); + BIO_free(out); +} + +static void CAPI_trace(CAPI_CTX *ctx, char *format, ...) +{ + va_list args; + va_start(args, format); + capi_vtrace(ctx, CAPI_DBG_TRACE, format, args); + va_end(args); +} + +static void capi_addlasterror(void) +{ + capi_adderror(GetLastError()); +} + +static void capi_adderror(DWORD err) +{ + char errstr[10]; + BIO_snprintf(errstr, 10, "%lX", err); + ERR_add_error_data(2, "Error code= 0x", errstr); +} + +static char *wide_to_asc(LPCWSTR wstr) +{ + char *str; + int len_0, sz; + + if (!wstr) + return NULL; + len_0 = (int)wcslen(wstr) + 1; /* WideCharToMultiByte expects int */ + sz = WideCharToMultiByte(CP_ACP, 0, wstr, len_0, NULL, 0, NULL, NULL); + if (!sz) { + CAPIerr(CAPI_F_WIDE_TO_ASC, CAPI_R_WIN32_ERROR); + return NULL; + } + str = OPENSSL_malloc(sz); + if (str == NULL) { + CAPIerr(CAPI_F_WIDE_TO_ASC, ERR_R_MALLOC_FAILURE); + return NULL; + } + if (!WideCharToMultiByte(CP_ACP, 0, wstr, len_0, str, sz, NULL, NULL)) { + OPENSSL_free(str); + CAPIerr(CAPI_F_WIDE_TO_ASC, CAPI_R_WIN32_ERROR); + return NULL; + } + return str; +} + +static int capi_get_provname(CAPI_CTX *ctx, LPSTR *pname, DWORD *ptype, + DWORD idx) +{ + DWORD len, err; + LPTSTR name; + CAPI_trace(ctx, "capi_get_provname, index=%d\n", idx); + if (!CryptEnumProviders(idx, NULL, 0, ptype, NULL, &len)) { + err = GetLastError(); + if (err == ERROR_NO_MORE_ITEMS) + return 2; + CAPIerr(CAPI_F_CAPI_GET_PROVNAME, CAPI_R_CRYPTENUMPROVIDERS_ERROR); + capi_adderror(err); + return 0; + } + name = OPENSSL_malloc(len); + if (name == NULL) { + CAPIerr(CAPI_F_CAPI_GET_PROVNAME, ERR_R_MALLOC_FAILURE); + return 0; + } + if (!CryptEnumProviders(idx, NULL, 0, ptype, name, &len)) { + err = GetLastError(); + OPENSSL_free(name); + if (err == ERROR_NO_MORE_ITEMS) + return 2; + CAPIerr(CAPI_F_CAPI_GET_PROVNAME, CAPI_R_CRYPTENUMPROVIDERS_ERROR); + capi_adderror(err); + return 0; + } + if (sizeof(TCHAR) != sizeof(char)) { + *pname = wide_to_asc((WCHAR *)name); + OPENSSL_free(name); + if (*pname == NULL) + return 0; + } else { + *pname = (char *)name; + } + CAPI_trace(ctx, "capi_get_provname, returned name=%s, type=%d\n", *pname, + *ptype); + + return 1; +} + +static int capi_list_providers(CAPI_CTX *ctx, BIO *out) +{ + DWORD idx, ptype; + int ret; + LPSTR provname = NULL; + CAPI_trace(ctx, "capi_list_providers\n"); + BIO_printf(out, "Available CSPs:\n"); + for (idx = 0;; idx++) { + ret = capi_get_provname(ctx, &provname, &ptype, idx); + if (ret == 2) + break; + if (ret == 0) + break; + BIO_printf(out, "%lu. %s, type %lu\n", idx, provname, ptype); + OPENSSL_free(provname); + } + return 1; +} + +static int capi_list_containers(CAPI_CTX *ctx, BIO *out) +{ + int ret = 1; + HCRYPTPROV hprov; + DWORD err, idx, flags, buflen = 0, clen; + LPSTR cname; + LPWSTR cspname = NULL; + + CAPI_trace(ctx, "Listing containers CSP=%s, type = %d\n", ctx->cspname, + ctx->csptype); + if (ctx->cspname != NULL) { + if ((clen = MultiByteToWideChar(CP_ACP, 0, ctx->cspname, -1, + NULL, 0))) { + cspname = alloca(clen * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, ctx->cspname, -1, (WCHAR *)cspname, + clen); + } + if (cspname == NULL) { + CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, ERR_R_MALLOC_FAILURE); + capi_addlasterror(); + return 0; + } + } + if (!CryptAcquireContextW(&hprov, NULL, cspname, ctx->csptype, + CRYPT_VERIFYCONTEXT)) { + CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, + CAPI_R_CRYPTACQUIRECONTEXT_ERROR); + capi_addlasterror(); + return 0; + } + if (!CryptGetProvParam(hprov, PP_ENUMCONTAINERS, NULL, &buflen, + CRYPT_FIRST)) { + CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_ENUMCONTAINERS_ERROR); + capi_addlasterror(); + CryptReleaseContext(hprov, 0); + return 0; + } + CAPI_trace(ctx, "Got max container len %d\n", buflen); + if (buflen == 0) + buflen = 1024; + cname = OPENSSL_malloc(buflen); + if (cname == NULL) { + CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, ERR_R_MALLOC_FAILURE); + goto err; + } + + for (idx = 0;; idx++) { + clen = buflen; + cname[0] = 0; + + if (idx == 0) + flags = CRYPT_FIRST; + else + flags = 0; + if (!CryptGetProvParam(hprov, PP_ENUMCONTAINERS, (BYTE *)cname, + &clen, flags)) { + err = GetLastError(); + if (err == ERROR_NO_MORE_ITEMS) + goto done; + CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_ENUMCONTAINERS_ERROR); + capi_adderror(err); + goto err; + } + CAPI_trace(ctx, "Container name %s, len=%d, index=%d, flags=%d\n", + cname, clen, idx, flags); + if (!cname[0] && (clen == buflen)) { + CAPI_trace(ctx, "Enumerate bug: using workaround\n"); + goto done; + } + BIO_printf(out, "%lu. %s\n", idx, cname); + } + err: + + ret = 0; + + done: + OPENSSL_free(cname); + CryptReleaseContext(hprov, 0); + + return ret; +} + +static CRYPT_KEY_PROV_INFO *capi_get_prov_info(CAPI_CTX *ctx, + PCCERT_CONTEXT cert) +{ + DWORD len; + CRYPT_KEY_PROV_INFO *pinfo; + + if (!CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, + NULL, &len)) + return NULL; + pinfo = OPENSSL_malloc(len); + if (pinfo == NULL) { + CAPIerr(CAPI_F_CAPI_GET_PROV_INFO, ERR_R_MALLOC_FAILURE); + return NULL; + } + if (!CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, + pinfo, &len)) { + CAPIerr(CAPI_F_CAPI_GET_PROV_INFO, + CAPI_R_ERROR_GETTING_KEY_PROVIDER_INFO); + capi_addlasterror(); + OPENSSL_free(pinfo); + return NULL; + } + return pinfo; +} + +static void capi_dump_prov_info(CAPI_CTX *ctx, BIO *out, + CRYPT_KEY_PROV_INFO *pinfo) +{ + char *provname = NULL, *contname = NULL; + if (!pinfo) { + BIO_printf(out, " No Private Key\n"); + return; + } + provname = wide_to_asc(pinfo->pwszProvName); + contname = wide_to_asc(pinfo->pwszContainerName); + if (!provname || !contname) + goto err; + + BIO_printf(out, " Private Key Info:\n"); + BIO_printf(out, " Provider Name: %s, Provider Type %lu\n", provname, + pinfo->dwProvType); + BIO_printf(out, " Container Name: %s, Key Type %lu\n", contname, + pinfo->dwKeySpec); + err: + OPENSSL_free(provname); + OPENSSL_free(contname); +} + +static char *capi_cert_get_fname(CAPI_CTX *ctx, PCCERT_CONTEXT cert) +{ + LPWSTR wfname; + DWORD dlen; + + CAPI_trace(ctx, "capi_cert_get_fname\n"); + if (!CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID, + NULL, &dlen)) + return NULL; + wfname = OPENSSL_malloc(dlen); + if (wfname == NULL) + return NULL; + if (CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID, + wfname, &dlen)) { + char *fname = wide_to_asc(wfname); + OPENSSL_free(wfname); + return fname; + } + CAPIerr(CAPI_F_CAPI_CERT_GET_FNAME, CAPI_R_ERROR_GETTING_FRIENDLY_NAME); + capi_addlasterror(); + + OPENSSL_free(wfname); + return NULL; +} + +static void capi_dump_cert(CAPI_CTX *ctx, BIO *out, PCCERT_CONTEXT cert) +{ + X509 *x; + const unsigned char *p; + unsigned long flags = ctx->dump_flags; + if (flags & CAPI_DMP_FNAME) { + char *fname; + fname = capi_cert_get_fname(ctx, cert); + if (fname) { + BIO_printf(out, " Friendly Name \"%s\"\n", fname); + OPENSSL_free(fname); + } else { + BIO_printf(out, " \n"); + } + } + + p = cert->pbCertEncoded; + x = d2i_X509(NULL, &p, cert->cbCertEncoded); + if (!x) + BIO_printf(out, " \n"); + if (flags & CAPI_DMP_SUMMARY) { + BIO_printf(out, " Subject: "); + X509_NAME_print_ex(out, X509_get_subject_name(x), 0, XN_FLAG_ONELINE); + BIO_printf(out, "\n Issuer: "); + X509_NAME_print_ex(out, X509_get_issuer_name(x), 0, XN_FLAG_ONELINE); + BIO_printf(out, "\n"); + } + if (flags & CAPI_DMP_FULL) + X509_print_ex(out, x, XN_FLAG_ONELINE, 0); + + if (flags & CAPI_DMP_PKEYINFO) { + CRYPT_KEY_PROV_INFO *pinfo; + pinfo = capi_get_prov_info(ctx, cert); + capi_dump_prov_info(ctx, out, pinfo); + OPENSSL_free(pinfo); + } + + if (flags & CAPI_DMP_PEM) + PEM_write_bio_X509(out, x); + X509_free(x); +} + +static HCERTSTORE capi_open_store(CAPI_CTX *ctx, char *storename) +{ + HCERTSTORE hstore; + + if (!storename) + storename = ctx->storename; + if (!storename) + storename = "MY"; + CAPI_trace(ctx, "Opening certificate store %s\n", storename); + + hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0, + ctx->store_flags, storename); + if (!hstore) { + CAPIerr(CAPI_F_CAPI_OPEN_STORE, CAPI_R_ERROR_OPENING_STORE); + capi_addlasterror(); + } + return hstore; +} + +int capi_list_certs(CAPI_CTX *ctx, BIO *out, char *id) +{ + char *storename; + int idx; + int ret = 1; + HCERTSTORE hstore; + PCCERT_CONTEXT cert = NULL; + + storename = ctx->storename; + if (!storename) + storename = "MY"; + CAPI_trace(ctx, "Listing certs for store %s\n", storename); + + hstore = capi_open_store(ctx, storename); + if (!hstore) + return 0; + if (id) { + cert = capi_find_cert(ctx, id, hstore); + if (!cert) { + ret = 0; + goto err; + } + capi_dump_cert(ctx, out, cert); + CertFreeCertificateContext(cert); + } else { + for (idx = 0;; idx++) { + cert = CertEnumCertificatesInStore(hstore, cert); + if (!cert) + break; + BIO_printf(out, "Certificate %d\n", idx); + capi_dump_cert(ctx, out, cert); + } + } + err: + CertCloseStore(hstore, 0); + return ret; +} + +static PCCERT_CONTEXT capi_find_cert(CAPI_CTX *ctx, const char *id, + HCERTSTORE hstore) +{ + PCCERT_CONTEXT cert = NULL; + char *fname = NULL; + int match; + switch (ctx->lookup_method) { + case CAPI_LU_SUBSTR: + return CertFindCertificateInStore(hstore, X509_ASN_ENCODING, 0, + CERT_FIND_SUBJECT_STR_A, id, NULL); + case CAPI_LU_FNAME: + for (;;) { + cert = CertEnumCertificatesInStore(hstore, cert); + if (!cert) + return NULL; + fname = capi_cert_get_fname(ctx, cert); + if (fname) { + if (strcmp(fname, id)) + match = 0; + else + match = 1; + OPENSSL_free(fname); + if (match) + return cert; + } + } + default: + return NULL; + } +} + +static CAPI_KEY *capi_get_key(CAPI_CTX *ctx, const WCHAR *contname, + const WCHAR *provname, DWORD ptype, + DWORD keyspec) +{ + DWORD dwFlags = 0; + CAPI_KEY *key = OPENSSL_malloc(sizeof(*key)); + + if (key == NULL) + return NULL; + /* If PROV_RSA_AES supported use it instead */ + if (ptype == PROV_RSA_FULL && use_aes_csp && + wcscmp(provname, rsa_enh_cspname) == 0) { + provname = rsa_aes_cspname; + ptype = PROV_RSA_AES; + } + if (ctx && ctx->debug_level >= CAPI_DBG_TRACE && ctx->debug_file) { + /* + * above 'if' is [complementary] copy from CAPI_trace and serves + * as optimization to minimize [below] malloc-ations + */ + char *_contname = wide_to_asc(contname); + char *_provname = wide_to_asc(provname); + + CAPI_trace(ctx, "capi_get_key, contname=%s, provname=%s, type=%d\n", + _contname, _provname, ptype); + OPENSSL_free(_provname); + OPENSSL_free(_contname); + } + if (ctx->store_flags & CERT_SYSTEM_STORE_LOCAL_MACHINE) + dwFlags = CRYPT_MACHINE_KEYSET; + if (!CryptAcquireContextW(&key->hprov, contname, provname, ptype, + dwFlags)) { + CAPIerr(CAPI_F_CAPI_GET_KEY, CAPI_R_CRYPTACQUIRECONTEXT_ERROR); + capi_addlasterror(); + goto err; + } + if (!CryptGetUserKey(key->hprov, keyspec, &key->key)) { + CAPIerr(CAPI_F_CAPI_GET_KEY, CAPI_R_GETUSERKEY_ERROR); + capi_addlasterror(); + CryptReleaseContext(key->hprov, 0); + goto err; + } + key->keyspec = keyspec; + key->pcert = NULL; + return key; + + err: + OPENSSL_free(key); + return NULL; +} + +static CAPI_KEY *capi_get_cert_key(CAPI_CTX *ctx, PCCERT_CONTEXT cert) +{ + CAPI_KEY *key = NULL; + CRYPT_KEY_PROV_INFO *pinfo = NULL; + + pinfo = capi_get_prov_info(ctx, cert); + + if (pinfo != NULL) + key = capi_get_key(ctx, pinfo->pwszContainerName, pinfo->pwszProvName, + pinfo->dwProvType, pinfo->dwKeySpec); + + OPENSSL_free(pinfo); + return key; +} + +CAPI_KEY *capi_find_key(CAPI_CTX *ctx, const char *id) +{ + PCCERT_CONTEXT cert; + HCERTSTORE hstore; + CAPI_KEY *key = NULL; + + switch (ctx->lookup_method) { + case CAPI_LU_SUBSTR: + case CAPI_LU_FNAME: + hstore = capi_open_store(ctx, NULL); + if (!hstore) + return NULL; + cert = capi_find_cert(ctx, id, hstore); + if (cert) { + key = capi_get_cert_key(ctx, cert); + CertFreeCertificateContext(cert); + } + CertCloseStore(hstore, 0); + break; + + case CAPI_LU_CONTNAME: + { + WCHAR *contname, *provname; + DWORD len; + + if ((len = MultiByteToWideChar(CP_ACP, 0, id, -1, NULL, 0)) && + (contname = alloca(len * sizeof(WCHAR)), + MultiByteToWideChar(CP_ACP, 0, id, -1, contname, len)) && + (len = MultiByteToWideChar(CP_ACP, 0, ctx->cspname, -1, + NULL, 0)) && + (provname = alloca(len * sizeof(WCHAR)), + MultiByteToWideChar(CP_ACP, 0, ctx->cspname, -1, + provname, len))) + key = capi_get_key(ctx, contname, provname, + ctx->csptype, ctx->keytype); + } + break; + } + + return key; +} + +void capi_free_key(CAPI_KEY *key) +{ + if (!key) + return; + CryptDestroyKey(key->key); + CryptReleaseContext(key->hprov, 0); + if (key->pcert) + CertFreeCertificateContext(key->pcert); + OPENSSL_free(key); +} + +/* Initialize a CAPI_CTX structure */ + +static CAPI_CTX *capi_ctx_new(void) +{ + CAPI_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); + + if (ctx == NULL) { + CAPIerr(CAPI_F_CAPI_CTX_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + ctx->csptype = PROV_RSA_FULL; + ctx->dump_flags = CAPI_DMP_SUMMARY | CAPI_DMP_FNAME; + ctx->keytype = AT_KEYEXCHANGE; + ctx->store_flags = CERT_STORE_OPEN_EXISTING_FLAG | + CERT_STORE_READONLY_FLAG | CERT_SYSTEM_STORE_CURRENT_USER; + ctx->lookup_method = CAPI_LU_SUBSTR; + ctx->client_cert_select = cert_select_simple; + return ctx; +} + +static void capi_ctx_free(CAPI_CTX *ctx) +{ + CAPI_trace(ctx, "Calling capi_ctx_free with %lx\n", ctx); + if (!ctx) + return; + OPENSSL_free(ctx->cspname); + OPENSSL_free(ctx->debug_file); + OPENSSL_free(ctx->storename); + OPENSSL_free(ctx->ssl_client_store); + OPENSSL_free(ctx); +} + +static int capi_ctx_set_provname(CAPI_CTX *ctx, LPSTR pname, DWORD type, + int check) +{ + LPSTR tmpcspname; + + CAPI_trace(ctx, "capi_ctx_set_provname, name=%s, type=%d\n", pname, type); + if (check) { + HCRYPTPROV hprov; + LPWSTR name = NULL; + DWORD len; + + if ((len = MultiByteToWideChar(CP_ACP, 0, pname, -1, NULL, 0))) { + name = alloca(len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pname, -1, (WCHAR *)name, len); + } + if (name == NULL || !CryptAcquireContextW(&hprov, NULL, name, type, + CRYPT_VERIFYCONTEXT)) { + CAPIerr(CAPI_F_CAPI_CTX_SET_PROVNAME, + CAPI_R_CRYPTACQUIRECONTEXT_ERROR); + capi_addlasterror(); + return 0; + } + CryptReleaseContext(hprov, 0); + } + tmpcspname = OPENSSL_strdup(pname); + if (tmpcspname == NULL) { + CAPIerr(CAPI_F_CAPI_CTX_SET_PROVNAME, ERR_R_MALLOC_FAILURE); + return 0; + } + OPENSSL_free(ctx->cspname); + ctx->cspname = tmpcspname; + ctx->csptype = type; + return 1; +} + +static int capi_ctx_set_provname_idx(CAPI_CTX *ctx, int idx) +{ + LPSTR pname; + DWORD type; + int res; + if (capi_get_provname(ctx, &pname, &type, idx) != 1) + return 0; + res = capi_ctx_set_provname(ctx, pname, type, 0); + OPENSSL_free(pname); + return res; +} + +static int cert_issuer_match(STACK_OF(X509_NAME) *ca_dn, X509 *x) +{ + int i; + X509_NAME *nm; + /* Special case: empty list: match anything */ + if (sk_X509_NAME_num(ca_dn) <= 0) + return 1; + for (i = 0; i < sk_X509_NAME_num(ca_dn); i++) { + nm = sk_X509_NAME_value(ca_dn, i); + if (!X509_NAME_cmp(nm, X509_get_issuer_name(x))) + return 1; + } + return 0; +} + +static int capi_load_ssl_client_cert(ENGINE *e, SSL *ssl, + STACK_OF(X509_NAME) *ca_dn, X509 **pcert, + EVP_PKEY **pkey, STACK_OF(X509) **pother, + UI_METHOD *ui_method, + void *callback_data) +{ + STACK_OF(X509) *certs = NULL; + X509 *x; + char *storename; + const unsigned char *p; + int i, client_cert_idx; + HCERTSTORE hstore; + PCCERT_CONTEXT cert = NULL, excert = NULL; + CAPI_CTX *ctx; + CAPI_KEY *key; + ctx = ENGINE_get_ex_data(e, capi_idx); + + *pcert = NULL; + *pkey = NULL; + + storename = ctx->ssl_client_store; + if (!storename) + storename = "MY"; + + hstore = capi_open_store(ctx, storename); + if (!hstore) + return 0; + /* Enumerate all certificates collect any matches */ + for (i = 0;; i++) { + cert = CertEnumCertificatesInStore(hstore, cert); + if (!cert) + break; + p = cert->pbCertEncoded; + x = d2i_X509(NULL, &p, cert->cbCertEncoded); + if (!x) { + CAPI_trace(ctx, "Can't Parse Certificate %d\n", i); + continue; + } + if (cert_issuer_match(ca_dn, x) + && X509_check_purpose(x, X509_PURPOSE_SSL_CLIENT, 0)) { + key = capi_get_cert_key(ctx, cert); + if (!key) { + X509_free(x); + continue; + } + /* + * Match found: attach extra data to it so we can retrieve the + * key later. + */ + excert = CertDuplicateCertificateContext(cert); + key->pcert = excert; + X509_set_ex_data(x, cert_capi_idx, key); + + if (!certs) + certs = sk_X509_new_null(); + + sk_X509_push(certs, x); + } else { + X509_free(x); + } + } + + if (cert) + CertFreeCertificateContext(cert); + if (hstore) + CertCloseStore(hstore, 0); + + if (!certs) + return 0; + + /* Select the appropriate certificate */ + + client_cert_idx = ctx->client_cert_select(e, ssl, certs); + + /* Set the selected certificate and free the rest */ + + for (i = 0; i < sk_X509_num(certs); i++) { + x = sk_X509_value(certs, i); + if (i == client_cert_idx) + *pcert = x; + else { + key = X509_get_ex_data(x, cert_capi_idx); + capi_free_key(key); + X509_free(x); + } + } + + sk_X509_free(certs); + + if (!*pcert) + return 0; + + /* Setup key for selected certificate */ + + key = X509_get_ex_data(*pcert, cert_capi_idx); + *pkey = capi_get_pkey(e, key); + X509_set_ex_data(*pcert, cert_capi_idx, NULL); + + return 1; + +} + +/* Simple client cert selection function: always select first */ + +static int cert_select_simple(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs) +{ + return 0; +} + +# ifdef OPENSSL_CAPIENG_DIALOG + +/* + * More complex cert selection function, using standard function + * CryptUIDlgSelectCertificateFromStore() to produce a dialog box. + */ + +/* + * Definitions which are in cryptuiapi.h but this is not present in older + * versions of headers. + */ + +# ifndef CRYPTUI_SELECT_LOCATION_COLUMN +# define CRYPTUI_SELECT_LOCATION_COLUMN 0x000000010 +# define CRYPTUI_SELECT_INTENDEDUSE_COLUMN 0x000000004 +# endif + +# define dlg_title L"OpenSSL Application SSL Client Certificate Selection" +# define dlg_prompt L"Select a certificate to use for authentication" +# define dlg_columns CRYPTUI_SELECT_LOCATION_COLUMN \ + |CRYPTUI_SELECT_INTENDEDUSE_COLUMN + +static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs) +{ + X509 *x; + HCERTSTORE dstore; + PCCERT_CONTEXT cert; + CAPI_CTX *ctx; + CAPI_KEY *key; + HWND hwnd; + int i, idx = -1; + if (sk_X509_num(certs) == 1) + return 0; + ctx = ENGINE_get_ex_data(e, capi_idx); + /* Create an in memory store of certificates */ + dstore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, + CERT_STORE_CREATE_NEW_FLAG, NULL); + if (!dstore) { + CAPIerr(CAPI_F_CERT_SELECT_DIALOG, CAPI_R_ERROR_CREATING_STORE); + capi_addlasterror(); + goto err; + } + /* Add all certificates to store */ + for (i = 0; i < sk_X509_num(certs); i++) { + x = sk_X509_value(certs, i); + key = X509_get_ex_data(x, cert_capi_idx); + + if (!CertAddCertificateContextToStore(dstore, key->pcert, + CERT_STORE_ADD_NEW, NULL)) { + CAPIerr(CAPI_F_CERT_SELECT_DIALOG, CAPI_R_ERROR_ADDING_CERT); + capi_addlasterror(); + goto err; + } + + } + hwnd = GetForegroundWindow(); + if (!hwnd) + hwnd = GetActiveWindow(); + if (!hwnd && ctx->getconswindow) + hwnd = ctx->getconswindow(); + /* Call dialog to select one */ + cert = ctx->certselectdlg(dstore, hwnd, dlg_title, dlg_prompt, + dlg_columns, 0, NULL); + + /* Find matching cert from list */ + if (cert) { + for (i = 0; i < sk_X509_num(certs); i++) { + x = sk_X509_value(certs, i); + key = X509_get_ex_data(x, cert_capi_idx); + if (CertCompareCertificate + (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, cert->pCertInfo, + key->pcert->pCertInfo)) { + idx = i; + break; + } + } + } + + err: + if (dstore) + CertCloseStore(dstore, 0); + return idx; + +} +# endif + +#else /* !__COMPILE_CAPIENG */ +# include +# ifndef OPENSSL_NO_DYNAMIC_ENGINE +OPENSSL_EXPORT + int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns); +OPENSSL_EXPORT + int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) +{ + return 0; +} + +IMPLEMENT_DYNAMIC_CHECK_FN() +# else +void engine_load_capi_int(void); +void engine_load_capi_int(void) +{ +} +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/engines/e_capi.ec b/trunk/3rdparty/openssl-1.1-fit/engines/e_capi.ec new file mode 100644 index 000000000..d9c7aa510 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/engines/e_capi.ec @@ -0,0 +1,3 @@ +# The INPUT HEADER is scanned for declarations +# LIBNAME INPUT HEADER ERROR-TABLE FILE +L CAPI e_capi_err.h e_capi_err.c diff --git a/trunk/3rdparty/openssl-1.1-fit/engines/e_capi.txt b/trunk/3rdparty/openssl-1.1-fit/engines/e_capi.txt new file mode 100644 index 000000000..3f34cdf6b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/engines/e_capi.txt @@ -0,0 +1,62 @@ +# Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# Function codes +CAPI_F_CAPI_CERT_GET_FNAME:99:capi_cert_get_fname +CAPI_F_CAPI_CTRL:100:capi_ctrl +CAPI_F_CAPI_CTX_NEW:101:capi_ctx_new +CAPI_F_CAPI_CTX_SET_PROVNAME:102:capi_ctx_set_provname +CAPI_F_CAPI_DSA_DO_SIGN:114:capi_dsa_do_sign +CAPI_F_CAPI_GET_KEY:103:capi_get_key +CAPI_F_CAPI_GET_PKEY:115:capi_get_pkey +CAPI_F_CAPI_GET_PROVNAME:104:capi_get_provname +CAPI_F_CAPI_GET_PROV_INFO:105:capi_get_prov_info +CAPI_F_CAPI_INIT:106:capi_init +CAPI_F_CAPI_LIST_CONTAINERS:107:capi_list_containers +CAPI_F_CAPI_LOAD_PRIVKEY:108:capi_load_privkey +CAPI_F_CAPI_OPEN_STORE:109:capi_open_store +CAPI_F_CAPI_RSA_PRIV_DEC:110:capi_rsa_priv_dec +CAPI_F_CAPI_RSA_PRIV_ENC:111:capi_rsa_priv_enc +CAPI_F_CAPI_RSA_SIGN:112:capi_rsa_sign +CAPI_F_CAPI_VTRACE:118:capi_vtrace +CAPI_F_CERT_SELECT_DIALOG:117:cert_select_dialog +CAPI_F_CLIENT_CERT_SELECT:116:* +CAPI_F_WIDE_TO_ASC:113:wide_to_asc + +#Reason codes +CAPI_R_CANT_CREATE_HASH_OBJECT:100:cant create hash object +CAPI_R_CANT_FIND_CAPI_CONTEXT:101:cant find capi context +CAPI_R_CANT_GET_KEY:102:cant get key +CAPI_R_CANT_SET_HASH_VALUE:103:cant set hash value +CAPI_R_CRYPTACQUIRECONTEXT_ERROR:104:cryptacquirecontext error +CAPI_R_CRYPTENUMPROVIDERS_ERROR:105:cryptenumproviders error +CAPI_R_DECRYPT_ERROR:106:decrypt error +CAPI_R_ENGINE_NOT_INITIALIZED:107:engine not initialized +CAPI_R_ENUMCONTAINERS_ERROR:108:enumcontainers error +CAPI_R_ERROR_ADDING_CERT:109:error adding cert +CAPI_R_ERROR_CREATING_STORE:110:error creating store +CAPI_R_ERROR_GETTING_FRIENDLY_NAME:111:error getting friendly name +CAPI_R_ERROR_GETTING_KEY_PROVIDER_INFO:112:error getting key provider info +CAPI_R_ERROR_OPENING_STORE:113:error opening store +CAPI_R_ERROR_SIGNING_HASH:114:error signing hash +CAPI_R_FILE_OPEN_ERROR:115:file open error +CAPI_R_FUNCTION_NOT_SUPPORTED:116:function not supported +CAPI_R_GETUSERKEY_ERROR:117:getuserkey error +CAPI_R_INVALID_DIGEST_LENGTH:118:invalid digest length +CAPI_R_INVALID_DSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER:119:\ + invalid dsa public key blob magic number +CAPI_R_INVALID_LOOKUP_METHOD:120:invalid lookup method +CAPI_R_INVALID_PUBLIC_KEY_BLOB:121:invalid public key blob +CAPI_R_INVALID_RSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER:122:\ + invalid rsa public key blob magic number +CAPI_R_PUBKEY_EXPORT_ERROR:123:pubkey export error +CAPI_R_PUBKEY_EXPORT_LENGTH_ERROR:124:pubkey export length error +CAPI_R_UNKNOWN_COMMAND:125:unknown command +CAPI_R_UNSUPPORTED_ALGORITHM_NID:126:unsupported algorithm nid +CAPI_R_UNSUPPORTED_PADDING:127:unsupported padding +CAPI_R_UNSUPPORTED_PUBLIC_KEY_ALGORITHM:128:unsupported public key algorithm +CAPI_R_WIN32_ERROR:129:win32 error diff --git a/trunk/3rdparty/openssl-1.1-fit/engines/e_capi_err.c b/trunk/3rdparty/openssl-1.1-fit/engines/e_capi_err.c new file mode 100644 index 000000000..b72bc51a8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/engines/e_capi_err.c @@ -0,0 +1,119 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "e_capi_err.h" + +#ifndef OPENSSL_NO_ERR + +static ERR_STRING_DATA CAPI_str_functs[] = { + {ERR_PACK(0, CAPI_F_CAPI_CERT_GET_FNAME, 0), "capi_cert_get_fname"}, + {ERR_PACK(0, CAPI_F_CAPI_CTRL, 0), "capi_ctrl"}, + {ERR_PACK(0, CAPI_F_CAPI_CTX_NEW, 0), "capi_ctx_new"}, + {ERR_PACK(0, CAPI_F_CAPI_CTX_SET_PROVNAME, 0), "capi_ctx_set_provname"}, + {ERR_PACK(0, CAPI_F_CAPI_DSA_DO_SIGN, 0), "capi_dsa_do_sign"}, + {ERR_PACK(0, CAPI_F_CAPI_GET_KEY, 0), "capi_get_key"}, + {ERR_PACK(0, CAPI_F_CAPI_GET_PKEY, 0), "capi_get_pkey"}, + {ERR_PACK(0, CAPI_F_CAPI_GET_PROVNAME, 0), "capi_get_provname"}, + {ERR_PACK(0, CAPI_F_CAPI_GET_PROV_INFO, 0), "capi_get_prov_info"}, + {ERR_PACK(0, CAPI_F_CAPI_INIT, 0), "capi_init"}, + {ERR_PACK(0, CAPI_F_CAPI_LIST_CONTAINERS, 0), "capi_list_containers"}, + {ERR_PACK(0, CAPI_F_CAPI_LOAD_PRIVKEY, 0), "capi_load_privkey"}, + {ERR_PACK(0, CAPI_F_CAPI_OPEN_STORE, 0), "capi_open_store"}, + {ERR_PACK(0, CAPI_F_CAPI_RSA_PRIV_DEC, 0), "capi_rsa_priv_dec"}, + {ERR_PACK(0, CAPI_F_CAPI_RSA_PRIV_ENC, 0), "capi_rsa_priv_enc"}, + {ERR_PACK(0, CAPI_F_CAPI_RSA_SIGN, 0), "capi_rsa_sign"}, + {ERR_PACK(0, CAPI_F_CAPI_VTRACE, 0), "capi_vtrace"}, + {ERR_PACK(0, CAPI_F_CERT_SELECT_DIALOG, 0), "cert_select_dialog"}, + {ERR_PACK(0, CAPI_F_CLIENT_CERT_SELECT, 0), ""}, + {ERR_PACK(0, CAPI_F_WIDE_TO_ASC, 0), "wide_to_asc"}, + {0, NULL} +}; + +static ERR_STRING_DATA CAPI_str_reasons[] = { + {ERR_PACK(0, 0, CAPI_R_CANT_CREATE_HASH_OBJECT), "cant create hash object"}, + {ERR_PACK(0, 0, CAPI_R_CANT_FIND_CAPI_CONTEXT), "cant find capi context"}, + {ERR_PACK(0, 0, CAPI_R_CANT_GET_KEY), "cant get key"}, + {ERR_PACK(0, 0, CAPI_R_CANT_SET_HASH_VALUE), "cant set hash value"}, + {ERR_PACK(0, 0, CAPI_R_CRYPTACQUIRECONTEXT_ERROR), + "cryptacquirecontext error"}, + {ERR_PACK(0, 0, CAPI_R_CRYPTENUMPROVIDERS_ERROR), + "cryptenumproviders error"}, + {ERR_PACK(0, 0, CAPI_R_DECRYPT_ERROR), "decrypt error"}, + {ERR_PACK(0, 0, CAPI_R_ENGINE_NOT_INITIALIZED), "engine not initialized"}, + {ERR_PACK(0, 0, CAPI_R_ENUMCONTAINERS_ERROR), "enumcontainers error"}, + {ERR_PACK(0, 0, CAPI_R_ERROR_ADDING_CERT), "error adding cert"}, + {ERR_PACK(0, 0, CAPI_R_ERROR_CREATING_STORE), "error creating store"}, + {ERR_PACK(0, 0, CAPI_R_ERROR_GETTING_FRIENDLY_NAME), + "error getting friendly name"}, + {ERR_PACK(0, 0, CAPI_R_ERROR_GETTING_KEY_PROVIDER_INFO), + "error getting key provider info"}, + {ERR_PACK(0, 0, CAPI_R_ERROR_OPENING_STORE), "error opening store"}, + {ERR_PACK(0, 0, CAPI_R_ERROR_SIGNING_HASH), "error signing hash"}, + {ERR_PACK(0, 0, CAPI_R_FILE_OPEN_ERROR), "file open error"}, + {ERR_PACK(0, 0, CAPI_R_FUNCTION_NOT_SUPPORTED), "function not supported"}, + {ERR_PACK(0, 0, CAPI_R_GETUSERKEY_ERROR), "getuserkey error"}, + {ERR_PACK(0, 0, CAPI_R_INVALID_DIGEST_LENGTH), "invalid digest length"}, + {ERR_PACK(0, 0, CAPI_R_INVALID_DSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER), + "invalid dsa public key blob magic number"}, + {ERR_PACK(0, 0, CAPI_R_INVALID_LOOKUP_METHOD), "invalid lookup method"}, + {ERR_PACK(0, 0, CAPI_R_INVALID_PUBLIC_KEY_BLOB), "invalid public key blob"}, + {ERR_PACK(0, 0, CAPI_R_INVALID_RSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER), + "invalid rsa public key blob magic number"}, + {ERR_PACK(0, 0, CAPI_R_PUBKEY_EXPORT_ERROR), "pubkey export error"}, + {ERR_PACK(0, 0, CAPI_R_PUBKEY_EXPORT_LENGTH_ERROR), + "pubkey export length error"}, + {ERR_PACK(0, 0, CAPI_R_UNKNOWN_COMMAND), "unknown command"}, + {ERR_PACK(0, 0, CAPI_R_UNSUPPORTED_ALGORITHM_NID), + "unsupported algorithm nid"}, + {ERR_PACK(0, 0, CAPI_R_UNSUPPORTED_PADDING), "unsupported padding"}, + {ERR_PACK(0, 0, CAPI_R_UNSUPPORTED_PUBLIC_KEY_ALGORITHM), + "unsupported public key algorithm"}, + {ERR_PACK(0, 0, CAPI_R_WIN32_ERROR), "win32 error"}, + {0, NULL} +}; + +#endif + +static int lib_code = 0; +static int error_loaded = 0; + +static int ERR_load_CAPI_strings(void) +{ + if (lib_code == 0) + lib_code = ERR_get_next_error_library(); + + if (!error_loaded) { +#ifndef OPENSSL_NO_ERR + ERR_load_strings(lib_code, CAPI_str_functs); + ERR_load_strings(lib_code, CAPI_str_reasons); +#endif + error_loaded = 1; + } + return 1; +} + +static void ERR_unload_CAPI_strings(void) +{ + if (error_loaded) { +#ifndef OPENSSL_NO_ERR + ERR_unload_strings(lib_code, CAPI_str_functs); + ERR_unload_strings(lib_code, CAPI_str_reasons); +#endif + error_loaded = 0; + } +} + +static void ERR_CAPI_error(int function, int reason, char *file, int line) +{ + if (lib_code == 0) + lib_code = ERR_get_next_error_library(); + ERR_PUT_error(lib_code, function, reason, file, line); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/engines/e_capi_err.h b/trunk/3rdparty/openssl-1.1-fit/engines/e_capi_err.h new file mode 100644 index 000000000..e034c98ca --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/engines/e_capi_err.h @@ -0,0 +1,75 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_CAPIERR_H +# define HEADER_CAPIERR_H + +# define CAPIerr(f, r) ERR_CAPI_error((f), (r), OPENSSL_FILE, OPENSSL_LINE) + + +/* + * CAPI function codes. + */ +# define CAPI_F_CAPI_CERT_GET_FNAME 99 +# define CAPI_F_CAPI_CTRL 100 +# define CAPI_F_CAPI_CTX_NEW 101 +# define CAPI_F_CAPI_CTX_SET_PROVNAME 102 +# define CAPI_F_CAPI_DSA_DO_SIGN 114 +# define CAPI_F_CAPI_GET_KEY 103 +# define CAPI_F_CAPI_GET_PKEY 115 +# define CAPI_F_CAPI_GET_PROVNAME 104 +# define CAPI_F_CAPI_GET_PROV_INFO 105 +# define CAPI_F_CAPI_INIT 106 +# define CAPI_F_CAPI_LIST_CONTAINERS 107 +# define CAPI_F_CAPI_LOAD_PRIVKEY 108 +# define CAPI_F_CAPI_OPEN_STORE 109 +# define CAPI_F_CAPI_RSA_PRIV_DEC 110 +# define CAPI_F_CAPI_RSA_PRIV_ENC 111 +# define CAPI_F_CAPI_RSA_SIGN 112 +# define CAPI_F_CAPI_VTRACE 118 +# define CAPI_F_CERT_SELECT_DIALOG 117 +# define CAPI_F_CLIENT_CERT_SELECT 116 +# define CAPI_F_WIDE_TO_ASC 113 + +/* + * CAPI reason codes. + */ +# define CAPI_R_CANT_CREATE_HASH_OBJECT 100 +# define CAPI_R_CANT_FIND_CAPI_CONTEXT 101 +# define CAPI_R_CANT_GET_KEY 102 +# define CAPI_R_CANT_SET_HASH_VALUE 103 +# define CAPI_R_CRYPTACQUIRECONTEXT_ERROR 104 +# define CAPI_R_CRYPTENUMPROVIDERS_ERROR 105 +# define CAPI_R_DECRYPT_ERROR 106 +# define CAPI_R_ENGINE_NOT_INITIALIZED 107 +# define CAPI_R_ENUMCONTAINERS_ERROR 108 +# define CAPI_R_ERROR_ADDING_CERT 109 +# define CAPI_R_ERROR_CREATING_STORE 110 +# define CAPI_R_ERROR_GETTING_FRIENDLY_NAME 111 +# define CAPI_R_ERROR_GETTING_KEY_PROVIDER_INFO 112 +# define CAPI_R_ERROR_OPENING_STORE 113 +# define CAPI_R_ERROR_SIGNING_HASH 114 +# define CAPI_R_FILE_OPEN_ERROR 115 +# define CAPI_R_FUNCTION_NOT_SUPPORTED 116 +# define CAPI_R_GETUSERKEY_ERROR 117 +# define CAPI_R_INVALID_DIGEST_LENGTH 118 +# define CAPI_R_INVALID_DSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER 119 +# define CAPI_R_INVALID_LOOKUP_METHOD 120 +# define CAPI_R_INVALID_PUBLIC_KEY_BLOB 121 +# define CAPI_R_INVALID_RSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER 122 +# define CAPI_R_PUBKEY_EXPORT_ERROR 123 +# define CAPI_R_PUBKEY_EXPORT_LENGTH_ERROR 124 +# define CAPI_R_UNKNOWN_COMMAND 125 +# define CAPI_R_UNSUPPORTED_ALGORITHM_NID 126 +# define CAPI_R_UNSUPPORTED_PADDING 127 +# define CAPI_R_UNSUPPORTED_PUBLIC_KEY_ALGORITHM 128 +# define CAPI_R_WIN32_ERROR 129 + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/engines/e_dasync.c b/trunk/3rdparty/openssl-1.1-fit/engines/e_dasync.c new file mode 100644 index 000000000..5cdacb66a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/engines/e_dasync.c @@ -0,0 +1,785 @@ +/* + * Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#if defined(_WIN32) +# include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(OPENSSL_SYS_UNIX) && defined(OPENSSL_THREADS) +# undef ASYNC_POSIX +# define ASYNC_POSIX +# include +#elif defined(_WIN32) +# undef ASYNC_WIN +# define ASYNC_WIN +#endif + +#include "e_dasync_err.c" + +/* Engine Id and Name */ +static const char *engine_dasync_id = "dasync"; +static const char *engine_dasync_name = "Dummy Async engine support"; + + +/* Engine Lifetime functions */ +static int dasync_destroy(ENGINE *e); +static int dasync_init(ENGINE *e); +static int dasync_finish(ENGINE *e); +void engine_load_dasync_int(void); + + +/* Set up digests. Just SHA1 for now */ +static int dasync_digests(ENGINE *e, const EVP_MD **digest, + const int **nids, int nid); + +static void dummy_pause_job(void); + +/* SHA1 */ +static int dasync_sha1_init(EVP_MD_CTX *ctx); +static int dasync_sha1_update(EVP_MD_CTX *ctx, const void *data, + size_t count); +static int dasync_sha1_final(EVP_MD_CTX *ctx, unsigned char *md); + +/* + * Holds the EVP_MD object for sha1 in this engine. Set up once only during + * engine bind and can then be reused many times. + */ +static EVP_MD *_hidden_sha1_md = NULL; +static const EVP_MD *dasync_sha1(void) +{ + return _hidden_sha1_md; +} +static void destroy_digests(void) +{ + EVP_MD_meth_free(_hidden_sha1_md); + _hidden_sha1_md = NULL; +} + +static int dasync_digest_nids(const int **nids) +{ + static int digest_nids[2] = { 0, 0 }; + static int pos = 0; + static int init = 0; + + if (!init) { + const EVP_MD *md; + if ((md = dasync_sha1()) != NULL) + digest_nids[pos++] = EVP_MD_type(md); + digest_nids[pos] = 0; + init = 1; + } + *nids = digest_nids; + return pos; +} + +/* RSA */ + +static int dasync_pub_enc(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int dasync_pub_dec(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int dasync_rsa_priv_enc(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int dasync_rsa_priv_dec(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int dasync_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, + BN_CTX *ctx); + +static int dasync_rsa_init(RSA *rsa); +static int dasync_rsa_finish(RSA *rsa); + +static RSA_METHOD *dasync_rsa_method = NULL; + +/* AES */ + +static int dasync_aes128_cbc_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, + void *ptr); +static int dasync_aes128_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); +static int dasync_aes128_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl); +static int dasync_aes128_cbc_cleanup(EVP_CIPHER_CTX *ctx); + +static int dasync_aes128_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type, + int arg, void *ptr); +static int dasync_aes128_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX *ctx, + const unsigned char *key, + const unsigned char *iv, + int enc); +static int dasync_aes128_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, + unsigned char *out, + const unsigned char *in, + size_t inl); +static int dasync_aes128_cbc_hmac_sha1_cleanup(EVP_CIPHER_CTX *ctx); + +struct dasync_pipeline_ctx { + void *inner_cipher_data; + unsigned int numpipes; + unsigned char **inbufs; + unsigned char **outbufs; + size_t *lens; + unsigned char tlsaad[SSL_MAX_PIPELINES][EVP_AEAD_TLS1_AAD_LEN]; + unsigned int aadctr; +}; + +/* + * Holds the EVP_CIPHER object for aes_128_cbc in this engine. Set up once only + * during engine bind and can then be reused many times. + */ +static EVP_CIPHER *_hidden_aes_128_cbc = NULL; +static const EVP_CIPHER *dasync_aes_128_cbc(void) +{ + return _hidden_aes_128_cbc; +} + +/* + * Holds the EVP_CIPHER object for aes_128_cbc_hmac_sha1 in this engine. Set up + * once only during engine bind and can then be reused many times. + * + * This 'stitched' cipher depends on the EVP_aes_128_cbc_hmac_sha1() cipher, + * which is implemented only if the AES-NI instruction set extension is available + * (see OPENSSL_IA32CAP(3)). If that's not the case, then this cipher will not + * be available either. + * + * Note: Since it is a legacy mac-then-encrypt cipher, modern TLS peers (which + * negotiate the encrypt-then-mac extension) won't negotiate it anyway. + */ +static EVP_CIPHER *_hidden_aes_128_cbc_hmac_sha1 = NULL; +static const EVP_CIPHER *dasync_aes_128_cbc_hmac_sha1(void) +{ + return _hidden_aes_128_cbc_hmac_sha1; +} + +static void destroy_ciphers(void) +{ + EVP_CIPHER_meth_free(_hidden_aes_128_cbc); + EVP_CIPHER_meth_free(_hidden_aes_128_cbc_hmac_sha1); + _hidden_aes_128_cbc = NULL; + _hidden_aes_128_cbc_hmac_sha1 = NULL; +} + +static int dasync_ciphers(ENGINE *e, const EVP_CIPHER **cipher, + const int **nids, int nid); + +static int dasync_cipher_nids[] = { + NID_aes_128_cbc, + NID_aes_128_cbc_hmac_sha1, + 0 +}; + +static int bind_dasync(ENGINE *e) +{ + /* Setup RSA_METHOD */ + if ((dasync_rsa_method = RSA_meth_new("Dummy Async RSA method", 0)) == NULL + || RSA_meth_set_pub_enc(dasync_rsa_method, dasync_pub_enc) == 0 + || RSA_meth_set_pub_dec(dasync_rsa_method, dasync_pub_dec) == 0 + || RSA_meth_set_priv_enc(dasync_rsa_method, dasync_rsa_priv_enc) == 0 + || RSA_meth_set_priv_dec(dasync_rsa_method, dasync_rsa_priv_dec) == 0 + || RSA_meth_set_mod_exp(dasync_rsa_method, dasync_rsa_mod_exp) == 0 + || RSA_meth_set_bn_mod_exp(dasync_rsa_method, BN_mod_exp_mont) == 0 + || RSA_meth_set_init(dasync_rsa_method, dasync_rsa_init) == 0 + || RSA_meth_set_finish(dasync_rsa_method, dasync_rsa_finish) == 0) { + DASYNCerr(DASYNC_F_BIND_DASYNC, DASYNC_R_INIT_FAILED); + return 0; + } + + /* Ensure the dasync error handling is set up */ + ERR_load_DASYNC_strings(); + + if (!ENGINE_set_id(e, engine_dasync_id) + || !ENGINE_set_name(e, engine_dasync_name) + || !ENGINE_set_RSA(e, dasync_rsa_method) + || !ENGINE_set_digests(e, dasync_digests) + || !ENGINE_set_ciphers(e, dasync_ciphers) + || !ENGINE_set_destroy_function(e, dasync_destroy) + || !ENGINE_set_init_function(e, dasync_init) + || !ENGINE_set_finish_function(e, dasync_finish)) { + DASYNCerr(DASYNC_F_BIND_DASYNC, DASYNC_R_INIT_FAILED); + return 0; + } + + /* + * Set up the EVP_CIPHER and EVP_MD objects for the ciphers/digests + * supplied by this engine + */ + _hidden_sha1_md = EVP_MD_meth_new(NID_sha1, NID_sha1WithRSAEncryption); + if (_hidden_sha1_md == NULL + || !EVP_MD_meth_set_result_size(_hidden_sha1_md, SHA_DIGEST_LENGTH) + || !EVP_MD_meth_set_input_blocksize(_hidden_sha1_md, SHA_CBLOCK) + || !EVP_MD_meth_set_app_datasize(_hidden_sha1_md, + sizeof(EVP_MD *) + sizeof(SHA_CTX)) + || !EVP_MD_meth_set_flags(_hidden_sha1_md, EVP_MD_FLAG_DIGALGID_ABSENT) + || !EVP_MD_meth_set_init(_hidden_sha1_md, dasync_sha1_init) + || !EVP_MD_meth_set_update(_hidden_sha1_md, dasync_sha1_update) + || !EVP_MD_meth_set_final(_hidden_sha1_md, dasync_sha1_final)) { + EVP_MD_meth_free(_hidden_sha1_md); + _hidden_sha1_md = NULL; + } + + _hidden_aes_128_cbc = EVP_CIPHER_meth_new(NID_aes_128_cbc, + 16 /* block size */, + 16 /* key len */); + if (_hidden_aes_128_cbc == NULL + || !EVP_CIPHER_meth_set_iv_length(_hidden_aes_128_cbc,16) + || !EVP_CIPHER_meth_set_flags(_hidden_aes_128_cbc, + EVP_CIPH_FLAG_DEFAULT_ASN1 + | EVP_CIPH_CBC_MODE + | EVP_CIPH_FLAG_PIPELINE) + || !EVP_CIPHER_meth_set_init(_hidden_aes_128_cbc, + dasync_aes128_init_key) + || !EVP_CIPHER_meth_set_do_cipher(_hidden_aes_128_cbc, + dasync_aes128_cbc_cipher) + || !EVP_CIPHER_meth_set_cleanup(_hidden_aes_128_cbc, + dasync_aes128_cbc_cleanup) + || !EVP_CIPHER_meth_set_ctrl(_hidden_aes_128_cbc, + dasync_aes128_cbc_ctrl) + || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_aes_128_cbc, + sizeof(struct dasync_pipeline_ctx))) { + EVP_CIPHER_meth_free(_hidden_aes_128_cbc); + _hidden_aes_128_cbc = NULL; + } + + _hidden_aes_128_cbc_hmac_sha1 = EVP_CIPHER_meth_new( + NID_aes_128_cbc_hmac_sha1, + 16 /* block size */, + 16 /* key len */); + if (_hidden_aes_128_cbc_hmac_sha1 == NULL + || !EVP_CIPHER_meth_set_iv_length(_hidden_aes_128_cbc_hmac_sha1,16) + || !EVP_CIPHER_meth_set_flags(_hidden_aes_128_cbc_hmac_sha1, + EVP_CIPH_CBC_MODE + | EVP_CIPH_FLAG_DEFAULT_ASN1 + | EVP_CIPH_FLAG_AEAD_CIPHER + | EVP_CIPH_FLAG_PIPELINE) + || !EVP_CIPHER_meth_set_init(_hidden_aes_128_cbc_hmac_sha1, + dasync_aes128_cbc_hmac_sha1_init_key) + || !EVP_CIPHER_meth_set_do_cipher(_hidden_aes_128_cbc_hmac_sha1, + dasync_aes128_cbc_hmac_sha1_cipher) + || !EVP_CIPHER_meth_set_cleanup(_hidden_aes_128_cbc_hmac_sha1, + dasync_aes128_cbc_hmac_sha1_cleanup) + || !EVP_CIPHER_meth_set_ctrl(_hidden_aes_128_cbc_hmac_sha1, + dasync_aes128_cbc_hmac_sha1_ctrl) + || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_aes_128_cbc_hmac_sha1, + sizeof(struct dasync_pipeline_ctx))) { + EVP_CIPHER_meth_free(_hidden_aes_128_cbc_hmac_sha1); + _hidden_aes_128_cbc_hmac_sha1 = NULL; + } + + return 1; +} + +# ifndef OPENSSL_NO_DYNAMIC_ENGINE +static int bind_helper(ENGINE *e, const char *id) +{ + if (id && (strcmp(id, engine_dasync_id) != 0)) + return 0; + if (!bind_dasync(e)) + return 0; + return 1; +} + +IMPLEMENT_DYNAMIC_CHECK_FN() + IMPLEMENT_DYNAMIC_BIND_FN(bind_helper) +# endif + +static ENGINE *engine_dasync(void) +{ + ENGINE *ret = ENGINE_new(); + if (!ret) + return NULL; + if (!bind_dasync(ret)) { + ENGINE_free(ret); + return NULL; + } + return ret; +} + +void engine_load_dasync_int(void) +{ + ENGINE *toadd = engine_dasync(); + if (!toadd) + return; + ENGINE_add(toadd); + ENGINE_free(toadd); + ERR_clear_error(); +} + +static int dasync_init(ENGINE *e) +{ + return 1; +} + + +static int dasync_finish(ENGINE *e) +{ + return 1; +} + + +static int dasync_destroy(ENGINE *e) +{ + destroy_digests(); + destroy_ciphers(); + RSA_meth_free(dasync_rsa_method); + ERR_unload_DASYNC_strings(); + return 1; +} + +static int dasync_digests(ENGINE *e, const EVP_MD **digest, + const int **nids, int nid) +{ + int ok = 1; + if (!digest) { + /* We are returning a list of supported nids */ + return dasync_digest_nids(nids); + } + /* We are being asked for a specific digest */ + switch (nid) { + case NID_sha1: + *digest = dasync_sha1(); + break; + default: + ok = 0; + *digest = NULL; + break; + } + return ok; +} + +static int dasync_ciphers(ENGINE *e, const EVP_CIPHER **cipher, + const int **nids, int nid) +{ + int ok = 1; + if (cipher == NULL) { + /* We are returning a list of supported nids */ + *nids = dasync_cipher_nids; + return (sizeof(dasync_cipher_nids) - + 1) / sizeof(dasync_cipher_nids[0]); + } + /* We are being asked for a specific cipher */ + switch (nid) { + case NID_aes_128_cbc: + *cipher = dasync_aes_128_cbc(); + break; + case NID_aes_128_cbc_hmac_sha1: + *cipher = dasync_aes_128_cbc_hmac_sha1(); + break; + default: + ok = 0; + *cipher = NULL; + break; + } + return ok; +} + +static void wait_cleanup(ASYNC_WAIT_CTX *ctx, const void *key, + OSSL_ASYNC_FD readfd, void *pvwritefd) +{ + OSSL_ASYNC_FD *pwritefd = (OSSL_ASYNC_FD *)pvwritefd; +#if defined(ASYNC_WIN) + CloseHandle(readfd); + CloseHandle(*pwritefd); +#elif defined(ASYNC_POSIX) + close(readfd); + close(*pwritefd); +#endif + OPENSSL_free(pwritefd); +} + +#define DUMMY_CHAR 'X' + +static void dummy_pause_job(void) { + ASYNC_JOB *job; + ASYNC_WAIT_CTX *waitctx; + OSSL_ASYNC_FD pipefds[2] = {0, 0}; + OSSL_ASYNC_FD *writefd; +#if defined(ASYNC_WIN) + DWORD numwritten, numread; + char buf = DUMMY_CHAR; +#elif defined(ASYNC_POSIX) + char buf = DUMMY_CHAR; +#endif + + if ((job = ASYNC_get_current_job()) == NULL) + return; + + waitctx = ASYNC_get_wait_ctx(job); + + if (ASYNC_WAIT_CTX_get_fd(waitctx, engine_dasync_id, &pipefds[0], + (void **)&writefd)) { + pipefds[1] = *writefd; + } else { + writefd = OPENSSL_malloc(sizeof(*writefd)); + if (writefd == NULL) + return; +#if defined(ASYNC_WIN) + if (CreatePipe(&pipefds[0], &pipefds[1], NULL, 256) == 0) { + OPENSSL_free(writefd); + return; + } +#elif defined(ASYNC_POSIX) + if (pipe(pipefds) != 0) { + OPENSSL_free(writefd); + return; + } +#endif + *writefd = pipefds[1]; + + if (!ASYNC_WAIT_CTX_set_wait_fd(waitctx, engine_dasync_id, pipefds[0], + writefd, wait_cleanup)) { + wait_cleanup(waitctx, engine_dasync_id, pipefds[0], writefd); + return; + } + } + /* + * In the Dummy async engine we are cheating. We signal that the job + * is complete by waking it before the call to ASYNC_pause_job(). A real + * async engine would only wake when the job was actually complete + */ +#if defined(ASYNC_WIN) + WriteFile(pipefds[1], &buf, 1, &numwritten, NULL); +#elif defined(ASYNC_POSIX) + if (write(pipefds[1], &buf, 1) < 0) + return; +#endif + + /* Ignore errors - we carry on anyway */ + ASYNC_pause_job(); + + /* Clear the wake signal */ +#if defined(ASYNC_WIN) + ReadFile(pipefds[0], &buf, 1, &numread, NULL); +#elif defined(ASYNC_POSIX) + if (read(pipefds[0], &buf, 1) < 0) + return; +#endif +} + +/* + * SHA1 implementation. At the moment we just defer to the standard + * implementation + */ +#undef data +#define data(ctx) ((SHA_CTX *)EVP_MD_CTX_md_data(ctx)) +static int dasync_sha1_init(EVP_MD_CTX *ctx) +{ + dummy_pause_job(); + + return SHA1_Init(data(ctx)); +} + +static int dasync_sha1_update(EVP_MD_CTX *ctx, const void *data, + size_t count) +{ + dummy_pause_job(); + + return SHA1_Update(data(ctx), data, (size_t)count); +} + +static int dasync_sha1_final(EVP_MD_CTX *ctx, unsigned char *md) +{ + dummy_pause_job(); + + return SHA1_Final(md, data(ctx)); +} + +/* + * RSA implementation + */ + +static int dasync_pub_enc(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) { + /* Ignore errors - we carry on anyway */ + dummy_pause_job(); + return RSA_meth_get_pub_enc(RSA_PKCS1_OpenSSL()) + (flen, from, to, rsa, padding); +} + +static int dasync_pub_dec(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) { + /* Ignore errors - we carry on anyway */ + dummy_pause_job(); + return RSA_meth_get_pub_dec(RSA_PKCS1_OpenSSL()) + (flen, from, to, rsa, padding); +} + +static int dasync_rsa_priv_enc(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) +{ + /* Ignore errors - we carry on anyway */ + dummy_pause_job(); + return RSA_meth_get_priv_enc(RSA_PKCS1_OpenSSL()) + (flen, from, to, rsa, padding); +} + +static int dasync_rsa_priv_dec(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) +{ + /* Ignore errors - we carry on anyway */ + dummy_pause_job(); + return RSA_meth_get_priv_dec(RSA_PKCS1_OpenSSL()) + (flen, from, to, rsa, padding); +} + +static int dasync_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) +{ + /* Ignore errors - we carry on anyway */ + dummy_pause_job(); + return RSA_meth_get_mod_exp(RSA_PKCS1_OpenSSL())(r0, I, rsa, ctx); +} + +static int dasync_rsa_init(RSA *rsa) +{ + return RSA_meth_get_init(RSA_PKCS1_OpenSSL())(rsa); +} +static int dasync_rsa_finish(RSA *rsa) +{ + return RSA_meth_get_finish(RSA_PKCS1_OpenSSL())(rsa); +} + +/* Cipher helper functions */ + +static int dasync_cipher_ctrl_helper(EVP_CIPHER_CTX *ctx, int type, int arg, + void *ptr, int aeadcapable) +{ + int ret; + struct dasync_pipeline_ctx *pipe_ctx = + (struct dasync_pipeline_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); + + if (pipe_ctx == NULL) + return 0; + + switch (type) { + case EVP_CTRL_SET_PIPELINE_OUTPUT_BUFS: + pipe_ctx->numpipes = arg; + pipe_ctx->outbufs = (unsigned char **)ptr; + break; + + case EVP_CTRL_SET_PIPELINE_INPUT_BUFS: + pipe_ctx->numpipes = arg; + pipe_ctx->inbufs = (unsigned char **)ptr; + break; + + case EVP_CTRL_SET_PIPELINE_INPUT_LENS: + pipe_ctx->numpipes = arg; + pipe_ctx->lens = (size_t *)ptr; + break; + + case EVP_CTRL_AEAD_SET_MAC_KEY: + if (!aeadcapable) + return -1; + EVP_CIPHER_CTX_set_cipher_data(ctx, pipe_ctx->inner_cipher_data); + ret = EVP_CIPHER_meth_get_ctrl(EVP_aes_128_cbc_hmac_sha1()) + (ctx, type, arg, ptr); + EVP_CIPHER_CTX_set_cipher_data(ctx, pipe_ctx); + return ret; + + case EVP_CTRL_AEAD_TLS1_AAD: + { + unsigned char *p = ptr; + unsigned int len; + + if (!aeadcapable || arg != EVP_AEAD_TLS1_AAD_LEN) + return -1; + + if (pipe_ctx->aadctr >= SSL_MAX_PIPELINES) + return -1; + + memcpy(pipe_ctx->tlsaad[pipe_ctx->aadctr], ptr, + EVP_AEAD_TLS1_AAD_LEN); + pipe_ctx->aadctr++; + + len = p[arg - 2] << 8 | p[arg - 1]; + + if (EVP_CIPHER_CTX_encrypting(ctx)) { + if ((p[arg - 4] << 8 | p[arg - 3]) >= TLS1_1_VERSION) { + if (len < AES_BLOCK_SIZE) + return 0; + len -= AES_BLOCK_SIZE; + } + + return ((len + SHA_DIGEST_LENGTH + AES_BLOCK_SIZE) + & -AES_BLOCK_SIZE) - len; + } else { + return SHA_DIGEST_LENGTH; + } + } + + default: + return 0; + } + + return 1; +} + +static int dasync_cipher_init_key_helper(EVP_CIPHER_CTX *ctx, + const unsigned char *key, + const unsigned char *iv, int enc, + const EVP_CIPHER *cipher) +{ + int ret; + struct dasync_pipeline_ctx *pipe_ctx = + (struct dasync_pipeline_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); + + if (pipe_ctx->inner_cipher_data == NULL + && EVP_CIPHER_impl_ctx_size(cipher) != 0) { + pipe_ctx->inner_cipher_data = OPENSSL_zalloc( + EVP_CIPHER_impl_ctx_size(cipher)); + if (pipe_ctx->inner_cipher_data == NULL) { + DASYNCerr(DASYNC_F_DASYNC_CIPHER_INIT_KEY_HELPER, + ERR_R_MALLOC_FAILURE); + return 0; + } + } + + pipe_ctx->numpipes = 0; + pipe_ctx->aadctr = 0; + + EVP_CIPHER_CTX_set_cipher_data(ctx, pipe_ctx->inner_cipher_data); + ret = EVP_CIPHER_meth_get_init(cipher)(ctx, key, iv, enc); + EVP_CIPHER_CTX_set_cipher_data(ctx, pipe_ctx); + + return ret; +} + +static int dasync_cipher_helper(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl, + const EVP_CIPHER *cipher) +{ + int ret = 1; + unsigned int i, pipes; + struct dasync_pipeline_ctx *pipe_ctx = + (struct dasync_pipeline_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); + + pipes = pipe_ctx->numpipes; + EVP_CIPHER_CTX_set_cipher_data(ctx, pipe_ctx->inner_cipher_data); + if (pipes == 0) { + if (pipe_ctx->aadctr != 0) { + if (pipe_ctx->aadctr != 1) + return -1; + EVP_CIPHER_meth_get_ctrl(cipher) + (ctx, EVP_CTRL_AEAD_TLS1_AAD, + EVP_AEAD_TLS1_AAD_LEN, + pipe_ctx->tlsaad[0]); + } + ret = EVP_CIPHER_meth_get_do_cipher(cipher) + (ctx, out, in, inl); + } else { + if (pipe_ctx->aadctr > 0 && pipe_ctx->aadctr != pipes) + return -1; + for (i = 0; i < pipes; i++) { + if (pipe_ctx->aadctr > 0) { + EVP_CIPHER_meth_get_ctrl(cipher) + (ctx, EVP_CTRL_AEAD_TLS1_AAD, + EVP_AEAD_TLS1_AAD_LEN, + pipe_ctx->tlsaad[i]); + } + ret = ret && EVP_CIPHER_meth_get_do_cipher(cipher) + (ctx, pipe_ctx->outbufs[i], pipe_ctx->inbufs[i], + pipe_ctx->lens[i]); + } + pipe_ctx->numpipes = 0; + } + pipe_ctx->aadctr = 0; + EVP_CIPHER_CTX_set_cipher_data(ctx, pipe_ctx); + return ret; +} + +static int dasync_cipher_cleanup_helper(EVP_CIPHER_CTX *ctx, + const EVP_CIPHER *cipher) +{ + struct dasync_pipeline_ctx *pipe_ctx = + (struct dasync_pipeline_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); + + OPENSSL_clear_free(pipe_ctx->inner_cipher_data, + EVP_CIPHER_impl_ctx_size(cipher)); + + return 1; +} + +/* + * AES128 CBC Implementation + */ + +static int dasync_aes128_cbc_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, + void *ptr) +{ + return dasync_cipher_ctrl_helper(ctx, type, arg, ptr, 0); +} + +static int dasync_aes128_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + return dasync_cipher_init_key_helper(ctx, key, iv, enc, EVP_aes_128_cbc()); +} + +static int dasync_aes128_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + return dasync_cipher_helper(ctx, out, in, inl, EVP_aes_128_cbc()); +} + +static int dasync_aes128_cbc_cleanup(EVP_CIPHER_CTX *ctx) +{ + return dasync_cipher_cleanup_helper(ctx, EVP_aes_128_cbc()); +} + + +/* + * AES128 CBC HMAC SHA1 Implementation + */ + +static int dasync_aes128_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type, + int arg, void *ptr) +{ + return dasync_cipher_ctrl_helper(ctx, type, arg, ptr, 1); +} + +static int dasync_aes128_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX *ctx, + const unsigned char *key, + const unsigned char *iv, + int enc) +{ + /* + * We can safely assume that EVP_aes_128_cbc_hmac_sha1() != NULL, + * see comment before the definition of dasync_aes_128_cbc_hmac_sha1(). + */ + return dasync_cipher_init_key_helper(ctx, key, iv, enc, + EVP_aes_128_cbc_hmac_sha1()); +} + +static int dasync_aes128_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, + unsigned char *out, + const unsigned char *in, + size_t inl) +{ + return dasync_cipher_helper(ctx, out, in, inl, EVP_aes_128_cbc_hmac_sha1()); +} + +static int dasync_aes128_cbc_hmac_sha1_cleanup(EVP_CIPHER_CTX *ctx) +{ + /* + * We can safely assume that EVP_aes_128_cbc_hmac_sha1() != NULL, + * see comment before the definition of dasync_aes_128_cbc_hmac_sha1(). + */ + return dasync_cipher_cleanup_helper(ctx, EVP_aes_128_cbc_hmac_sha1()); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/engines/e_dasync.ec b/trunk/3rdparty/openssl-1.1-fit/engines/e_dasync.ec new file mode 100644 index 000000000..3d56ebcc5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/engines/e_dasync.ec @@ -0,0 +1,3 @@ +# The INPUT HEADER is scanned for declarations +# LIBNAME INPUT HEADER ERROR-TABLE FILE +L DASYNC e_dasync_err.h e_dasync_err.c diff --git a/trunk/3rdparty/openssl-1.1-fit/engines/e_dasync.txt b/trunk/3rdparty/openssl-1.1-fit/engines/e_dasync.txt new file mode 100644 index 000000000..bff64bcf2 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/engines/e_dasync.txt @@ -0,0 +1,22 @@ +# Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# Function codes +DASYNC_F_BIND_DASYNC:107:bind_dasync +DASYNC_F_CIPHER_AES_128_CBC_CODE:100:* +DASYNC_F_DASYNC_AES128_CBC_HMAC_SHA1_INIT_KEY:109:* +DASYNC_F_DASYNC_AES128_INIT_KEY:108:* +DASYNC_F_DASYNC_BN_MOD_EXP:101:* +DASYNC_F_DASYNC_CIPHER_INIT_KEY_HELPER:110:dasync_cipher_init_key_helper +DASYNC_F_DASYNC_MOD_EXP:102:* +DASYNC_F_DASYNC_PRIVATE_DECRYPT:103:* +DASYNC_F_DASYNC_PRIVATE_ENCRYPT:104:* +DASYNC_F_DASYNC_PUBLIC_DECRYPT:105:* +DASYNC_F_DASYNC_PUBLIC_ENCRYPT:106:* + +#Reason codes +DASYNC_R_INIT_FAILED:100:init failed diff --git a/trunk/3rdparty/openssl-1.1-fit/engines/e_dasync_err.c b/trunk/3rdparty/openssl-1.1-fit/engines/e_dasync_err.c new file mode 100644 index 000000000..794fb710c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/engines/e_dasync_err.c @@ -0,0 +1,73 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "e_dasync_err.h" + +#ifndef OPENSSL_NO_ERR + +static ERR_STRING_DATA DASYNC_str_functs[] = { + {ERR_PACK(0, DASYNC_F_BIND_DASYNC, 0), "bind_dasync"}, + {ERR_PACK(0, DASYNC_F_CIPHER_AES_128_CBC_CODE, 0), ""}, + {ERR_PACK(0, DASYNC_F_DASYNC_AES128_CBC_HMAC_SHA1_INIT_KEY, 0), ""}, + {ERR_PACK(0, DASYNC_F_DASYNC_AES128_INIT_KEY, 0), ""}, + {ERR_PACK(0, DASYNC_F_DASYNC_BN_MOD_EXP, 0), ""}, + {ERR_PACK(0, DASYNC_F_DASYNC_CIPHER_INIT_KEY_HELPER, 0), + "dasync_cipher_init_key_helper"}, + {ERR_PACK(0, DASYNC_F_DASYNC_MOD_EXP, 0), ""}, + {ERR_PACK(0, DASYNC_F_DASYNC_PRIVATE_DECRYPT, 0), ""}, + {ERR_PACK(0, DASYNC_F_DASYNC_PRIVATE_ENCRYPT, 0), ""}, + {ERR_PACK(0, DASYNC_F_DASYNC_PUBLIC_DECRYPT, 0), ""}, + {ERR_PACK(0, DASYNC_F_DASYNC_PUBLIC_ENCRYPT, 0), ""}, + {0, NULL} +}; + +static ERR_STRING_DATA DASYNC_str_reasons[] = { + {ERR_PACK(0, 0, DASYNC_R_INIT_FAILED), "init failed"}, + {0, NULL} +}; + +#endif + +static int lib_code = 0; +static int error_loaded = 0; + +static int ERR_load_DASYNC_strings(void) +{ + if (lib_code == 0) + lib_code = ERR_get_next_error_library(); + + if (!error_loaded) { +#ifndef OPENSSL_NO_ERR + ERR_load_strings(lib_code, DASYNC_str_functs); + ERR_load_strings(lib_code, DASYNC_str_reasons); +#endif + error_loaded = 1; + } + return 1; +} + +static void ERR_unload_DASYNC_strings(void) +{ + if (error_loaded) { +#ifndef OPENSSL_NO_ERR + ERR_unload_strings(lib_code, DASYNC_str_functs); + ERR_unload_strings(lib_code, DASYNC_str_reasons); +#endif + error_loaded = 0; + } +} + +static void ERR_DASYNC_error(int function, int reason, char *file, int line) +{ + if (lib_code == 0) + lib_code = ERR_get_next_error_library(); + ERR_PUT_error(lib_code, function, reason, file, line); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/engines/e_dasync_err.h b/trunk/3rdparty/openssl-1.1-fit/engines/e_dasync_err.h new file mode 100644 index 000000000..7c2c02787 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/engines/e_dasync_err.h @@ -0,0 +1,37 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_DASYNCERR_H +# define HEADER_DASYNCERR_H + +# define DASYNCerr(f, r) ERR_DASYNC_error((f), (r), OPENSSL_FILE, OPENSSL_LINE) + + +/* + * DASYNC function codes. + */ +# define DASYNC_F_BIND_DASYNC 107 +# define DASYNC_F_CIPHER_AES_128_CBC_CODE 100 +# define DASYNC_F_DASYNC_AES128_CBC_HMAC_SHA1_INIT_KEY 109 +# define DASYNC_F_DASYNC_AES128_INIT_KEY 108 +# define DASYNC_F_DASYNC_BN_MOD_EXP 101 +# define DASYNC_F_DASYNC_CIPHER_INIT_KEY_HELPER 110 +# define DASYNC_F_DASYNC_MOD_EXP 102 +# define DASYNC_F_DASYNC_PRIVATE_DECRYPT 103 +# define DASYNC_F_DASYNC_PRIVATE_ENCRYPT 104 +# define DASYNC_F_DASYNC_PUBLIC_DECRYPT 105 +# define DASYNC_F_DASYNC_PUBLIC_ENCRYPT 106 + +/* + * DASYNC reason codes. + */ +# define DASYNC_R_INIT_FAILED 100 + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/engines/e_ossltest.c b/trunk/3rdparty/openssl-1.1-fit/engines/e_ossltest.c new file mode 100644 index 000000000..64376247c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/engines/e_ossltest.c @@ -0,0 +1,696 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This is the OSSLTEST engine. It provides deliberately crippled digest + * implementations for test purposes. It is highly insecure and must NOT be + * used for any purpose except testing + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "e_ossltest_err.c" + +/* Engine Id and Name */ +static const char *engine_ossltest_id = "ossltest"; +static const char *engine_ossltest_name = "OpenSSL Test engine support"; + + +/* Engine Lifetime functions */ +static int ossltest_destroy(ENGINE *e); +static int ossltest_init(ENGINE *e); +static int ossltest_finish(ENGINE *e); +void ENGINE_load_ossltest(void); + + +/* Set up digests */ +static int ossltest_digests(ENGINE *e, const EVP_MD **digest, + const int **nids, int nid); +static const RAND_METHOD *ossltest_rand_method(void); + +/* MD5 */ +static int digest_md5_init(EVP_MD_CTX *ctx); +static int digest_md5_update(EVP_MD_CTX *ctx, const void *data, + size_t count); +static int digest_md5_final(EVP_MD_CTX *ctx, unsigned char *md); + +static EVP_MD *_hidden_md5_md = NULL; +static const EVP_MD *digest_md5(void) +{ + if (_hidden_md5_md == NULL) { + EVP_MD *md; + + if ((md = EVP_MD_meth_new(NID_md5, NID_md5WithRSAEncryption)) == NULL + || !EVP_MD_meth_set_result_size(md, MD5_DIGEST_LENGTH) + || !EVP_MD_meth_set_input_blocksize(md, MD5_CBLOCK) + || !EVP_MD_meth_set_app_datasize(md, + sizeof(EVP_MD *) + sizeof(MD5_CTX)) + || !EVP_MD_meth_set_flags(md, 0) + || !EVP_MD_meth_set_init(md, digest_md5_init) + || !EVP_MD_meth_set_update(md, digest_md5_update) + || !EVP_MD_meth_set_final(md, digest_md5_final)) { + EVP_MD_meth_free(md); + md = NULL; + } + _hidden_md5_md = md; + } + return _hidden_md5_md; +} + +/* SHA1 */ +static int digest_sha1_init(EVP_MD_CTX *ctx); +static int digest_sha1_update(EVP_MD_CTX *ctx, const void *data, + size_t count); +static int digest_sha1_final(EVP_MD_CTX *ctx, unsigned char *md); + +static EVP_MD *_hidden_sha1_md = NULL; +static const EVP_MD *digest_sha1(void) +{ + if (_hidden_sha1_md == NULL) { + EVP_MD *md; + + if ((md = EVP_MD_meth_new(NID_sha1, NID_sha1WithRSAEncryption)) == NULL + || !EVP_MD_meth_set_result_size(md, SHA_DIGEST_LENGTH) + || !EVP_MD_meth_set_input_blocksize(md, SHA_CBLOCK) + || !EVP_MD_meth_set_app_datasize(md, + sizeof(EVP_MD *) + sizeof(SHA_CTX)) + || !EVP_MD_meth_set_flags(md, EVP_MD_FLAG_DIGALGID_ABSENT) + || !EVP_MD_meth_set_init(md, digest_sha1_init) + || !EVP_MD_meth_set_update(md, digest_sha1_update) + || !EVP_MD_meth_set_final(md, digest_sha1_final)) { + EVP_MD_meth_free(md); + md = NULL; + } + _hidden_sha1_md = md; + } + return _hidden_sha1_md; +} + +/* SHA256 */ +static int digest_sha256_init(EVP_MD_CTX *ctx); +static int digest_sha256_update(EVP_MD_CTX *ctx, const void *data, + size_t count); +static int digest_sha256_final(EVP_MD_CTX *ctx, unsigned char *md); + +static EVP_MD *_hidden_sha256_md = NULL; +static const EVP_MD *digest_sha256(void) +{ + if (_hidden_sha256_md == NULL) { + EVP_MD *md; + + if ((md = EVP_MD_meth_new(NID_sha256, NID_sha256WithRSAEncryption)) == NULL + || !EVP_MD_meth_set_result_size(md, SHA256_DIGEST_LENGTH) + || !EVP_MD_meth_set_input_blocksize(md, SHA256_CBLOCK) + || !EVP_MD_meth_set_app_datasize(md, + sizeof(EVP_MD *) + sizeof(SHA256_CTX)) + || !EVP_MD_meth_set_flags(md, EVP_MD_FLAG_DIGALGID_ABSENT) + || !EVP_MD_meth_set_init(md, digest_sha256_init) + || !EVP_MD_meth_set_update(md, digest_sha256_update) + || !EVP_MD_meth_set_final(md, digest_sha256_final)) { + EVP_MD_meth_free(md); + md = NULL; + } + _hidden_sha256_md = md; + } + return _hidden_sha256_md; +} + +/* SHA384/SHA512 */ +static int digest_sha384_init(EVP_MD_CTX *ctx); +static int digest_sha512_init(EVP_MD_CTX *ctx); +static int digest_sha512_update(EVP_MD_CTX *ctx, const void *data, + size_t count); +static int digest_sha384_final(EVP_MD_CTX *ctx, unsigned char *md); +static int digest_sha512_final(EVP_MD_CTX *ctx, unsigned char *md); + +static EVP_MD *_hidden_sha384_md = NULL; +static const EVP_MD *digest_sha384(void) +{ + if (_hidden_sha384_md == NULL) { + EVP_MD *md; + + if ((md = EVP_MD_meth_new(NID_sha384, NID_sha384WithRSAEncryption)) == NULL + || !EVP_MD_meth_set_result_size(md, SHA384_DIGEST_LENGTH) + || !EVP_MD_meth_set_input_blocksize(md, SHA512_CBLOCK) + || !EVP_MD_meth_set_app_datasize(md, + sizeof(EVP_MD *) + sizeof(SHA512_CTX)) + || !EVP_MD_meth_set_flags(md, EVP_MD_FLAG_DIGALGID_ABSENT) + || !EVP_MD_meth_set_init(md, digest_sha384_init) + || !EVP_MD_meth_set_update(md, digest_sha512_update) + || !EVP_MD_meth_set_final(md, digest_sha384_final)) { + EVP_MD_meth_free(md); + md = NULL; + } + _hidden_sha384_md = md; + } + return _hidden_sha384_md; +} +static EVP_MD *_hidden_sha512_md = NULL; +static const EVP_MD *digest_sha512(void) +{ + if (_hidden_sha512_md == NULL) { + EVP_MD *md; + + if ((md = EVP_MD_meth_new(NID_sha512, NID_sha512WithRSAEncryption)) == NULL + || !EVP_MD_meth_set_result_size(md, SHA512_DIGEST_LENGTH) + || !EVP_MD_meth_set_input_blocksize(md, SHA512_CBLOCK) + || !EVP_MD_meth_set_app_datasize(md, + sizeof(EVP_MD *) + sizeof(SHA512_CTX)) + || !EVP_MD_meth_set_flags(md, EVP_MD_FLAG_DIGALGID_ABSENT) + || !EVP_MD_meth_set_init(md, digest_sha512_init) + || !EVP_MD_meth_set_update(md, digest_sha512_update) + || !EVP_MD_meth_set_final(md, digest_sha512_final)) { + EVP_MD_meth_free(md); + md = NULL; + } + _hidden_sha512_md = md; + } + return _hidden_sha512_md; +} +static void destroy_digests(void) +{ + EVP_MD_meth_free(_hidden_md5_md); + _hidden_md5_md = NULL; + EVP_MD_meth_free(_hidden_sha1_md); + _hidden_sha1_md = NULL; + EVP_MD_meth_free(_hidden_sha256_md); + _hidden_sha256_md = NULL; + EVP_MD_meth_free(_hidden_sha384_md); + _hidden_sha384_md = NULL; + EVP_MD_meth_free(_hidden_sha512_md); + _hidden_sha512_md = NULL; +} +static int ossltest_digest_nids(const int **nids) +{ + static int digest_nids[6] = { 0, 0, 0, 0, 0, 0 }; + static int pos = 0; + static int init = 0; + + if (!init) { + const EVP_MD *md; + if ((md = digest_md5()) != NULL) + digest_nids[pos++] = EVP_MD_type(md); + if ((md = digest_sha1()) != NULL) + digest_nids[pos++] = EVP_MD_type(md); + if ((md = digest_sha256()) != NULL) + digest_nids[pos++] = EVP_MD_type(md); + if ((md = digest_sha384()) != NULL) + digest_nids[pos++] = EVP_MD_type(md); + if ((md = digest_sha512()) != NULL) + digest_nids[pos++] = EVP_MD_type(md); + digest_nids[pos] = 0; + init = 1; + } + *nids = digest_nids; + return pos; +} + +/* Setup ciphers */ +static int ossltest_ciphers(ENGINE *, const EVP_CIPHER **, + const int **, int); + +static int ossltest_cipher_nids[] = { + NID_aes_128_cbc, NID_aes_128_gcm, 0 +}; + +/* AES128 */ + +int ossltest_aes128_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); +int ossltest_aes128_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl); +int ossltest_aes128_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); +int ossltest_aes128_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl); +static int ossltest_aes128_gcm_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, + void *ptr); + +static EVP_CIPHER *_hidden_aes_128_cbc = NULL; +static const EVP_CIPHER *ossltest_aes_128_cbc(void) +{ + if (_hidden_aes_128_cbc == NULL + && ((_hidden_aes_128_cbc = EVP_CIPHER_meth_new(NID_aes_128_cbc, + 16 /* block size */, + 16 /* key len */)) == NULL + || !EVP_CIPHER_meth_set_iv_length(_hidden_aes_128_cbc,16) + || !EVP_CIPHER_meth_set_flags(_hidden_aes_128_cbc, + EVP_CIPH_FLAG_DEFAULT_ASN1 + | EVP_CIPH_CBC_MODE) + || !EVP_CIPHER_meth_set_init(_hidden_aes_128_cbc, + ossltest_aes128_init_key) + || !EVP_CIPHER_meth_set_do_cipher(_hidden_aes_128_cbc, + ossltest_aes128_cbc_cipher) + || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_aes_128_cbc, + EVP_CIPHER_impl_ctx_size(EVP_aes_128_cbc())))) { + EVP_CIPHER_meth_free(_hidden_aes_128_cbc); + _hidden_aes_128_cbc = NULL; + } + return _hidden_aes_128_cbc; +} +static EVP_CIPHER *_hidden_aes_128_gcm = NULL; + +#define AES_GCM_FLAGS (EVP_CIPH_FLAG_DEFAULT_ASN1 \ + | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \ + | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \ + | EVP_CIPH_CUSTOM_COPY |EVP_CIPH_FLAG_AEAD_CIPHER \ + | EVP_CIPH_GCM_MODE) + +static const EVP_CIPHER *ossltest_aes_128_gcm(void) +{ + if (_hidden_aes_128_gcm == NULL + && ((_hidden_aes_128_gcm = EVP_CIPHER_meth_new(NID_aes_128_gcm, + 1 /* block size */, + 16 /* key len */)) == NULL + || !EVP_CIPHER_meth_set_iv_length(_hidden_aes_128_gcm,12) + || !EVP_CIPHER_meth_set_flags(_hidden_aes_128_gcm, AES_GCM_FLAGS) + || !EVP_CIPHER_meth_set_init(_hidden_aes_128_gcm, + ossltest_aes128_gcm_init_key) + || !EVP_CIPHER_meth_set_do_cipher(_hidden_aes_128_gcm, + ossltest_aes128_gcm_cipher) + || !EVP_CIPHER_meth_set_ctrl(_hidden_aes_128_gcm, + ossltest_aes128_gcm_ctrl) + || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_aes_128_gcm, + EVP_CIPHER_impl_ctx_size(EVP_aes_128_gcm())))) { + EVP_CIPHER_meth_free(_hidden_aes_128_gcm); + _hidden_aes_128_gcm = NULL; + } + return _hidden_aes_128_gcm; +} + +static void destroy_ciphers(void) +{ + EVP_CIPHER_meth_free(_hidden_aes_128_cbc); + EVP_CIPHER_meth_free(_hidden_aes_128_gcm); + _hidden_aes_128_cbc = NULL; +} + +static int bind_ossltest(ENGINE *e) +{ + /* Ensure the ossltest error handling is set up */ + ERR_load_OSSLTEST_strings(); + + if (!ENGINE_set_id(e, engine_ossltest_id) + || !ENGINE_set_name(e, engine_ossltest_name) + || !ENGINE_set_digests(e, ossltest_digests) + || !ENGINE_set_ciphers(e, ossltest_ciphers) + || !ENGINE_set_RAND(e, ossltest_rand_method()) + || !ENGINE_set_destroy_function(e, ossltest_destroy) + || !ENGINE_set_init_function(e, ossltest_init) + || !ENGINE_set_finish_function(e, ossltest_finish)) { + OSSLTESTerr(OSSLTEST_F_BIND_OSSLTEST, OSSLTEST_R_INIT_FAILED); + return 0; + } + + return 1; +} + +#ifndef OPENSSL_NO_DYNAMIC_ENGINE +static int bind_helper(ENGINE *e, const char *id) +{ + if (id && (strcmp(id, engine_ossltest_id) != 0)) + return 0; + if (!bind_ossltest(e)) + return 0; + return 1; +} + +IMPLEMENT_DYNAMIC_CHECK_FN() + IMPLEMENT_DYNAMIC_BIND_FN(bind_helper) +#endif + +static ENGINE *engine_ossltest(void) +{ + ENGINE *ret = ENGINE_new(); + if (ret == NULL) + return NULL; + if (!bind_ossltest(ret)) { + ENGINE_free(ret); + return NULL; + } + return ret; +} + +void ENGINE_load_ossltest(void) +{ + /* Copied from eng_[openssl|dyn].c */ + ENGINE *toadd = engine_ossltest(); + if (!toadd) + return; + ENGINE_add(toadd); + ENGINE_free(toadd); + ERR_clear_error(); +} + + +static int ossltest_init(ENGINE *e) +{ + return 1; +} + + +static int ossltest_finish(ENGINE *e) +{ + return 1; +} + + +static int ossltest_destroy(ENGINE *e) +{ + destroy_digests(); + destroy_ciphers(); + ERR_unload_OSSLTEST_strings(); + return 1; +} + +static int ossltest_digests(ENGINE *e, const EVP_MD **digest, + const int **nids, int nid) +{ + int ok = 1; + if (!digest) { + /* We are returning a list of supported nids */ + return ossltest_digest_nids(nids); + } + /* We are being asked for a specific digest */ + switch (nid) { + case NID_md5: + *digest = digest_md5(); + break; + case NID_sha1: + *digest = digest_sha1(); + break; + case NID_sha256: + *digest = digest_sha256(); + break; + case NID_sha384: + *digest = digest_sha384(); + break; + case NID_sha512: + *digest = digest_sha512(); + break; + default: + ok = 0; + *digest = NULL; + break; + } + return ok; +} + +static int ossltest_ciphers(ENGINE *e, const EVP_CIPHER **cipher, + const int **nids, int nid) +{ + int ok = 1; + if (!cipher) { + /* We are returning a list of supported nids */ + *nids = ossltest_cipher_nids; + return (sizeof(ossltest_cipher_nids) - 1) + / sizeof(ossltest_cipher_nids[0]); + } + /* We are being asked for a specific cipher */ + switch (nid) { + case NID_aes_128_cbc: + *cipher = ossltest_aes_128_cbc(); + break; + case NID_aes_128_gcm: + *cipher = ossltest_aes_128_gcm(); + break; + default: + ok = 0; + *cipher = NULL; + break; + } + return ok; +} + +static void fill_known_data(unsigned char *md, unsigned int len) +{ + unsigned int i; + + for (i=0; i 0) { + fill_known_data(md, MD5_DIGEST_LENGTH); + } + return ret; +} + +/* + * SHA1 implementation. + */ +#undef data +#define data(ctx) ((SHA_CTX *)EVP_MD_CTX_md_data(ctx)) +static int digest_sha1_init(EVP_MD_CTX *ctx) +{ + return SHA1_Init(data(ctx)); +} + +static int digest_sha1_update(EVP_MD_CTX *ctx, const void *data, + size_t count) +{ + return SHA1_Update(data(ctx), data, (size_t)count); +} + +static int digest_sha1_final(EVP_MD_CTX *ctx, unsigned char *md) +{ + int ret; + ret = SHA1_Final(md, data(ctx)); + + if (ret > 0) { + fill_known_data(md, SHA_DIGEST_LENGTH); + } + return ret; +} + +/* + * SHA256 implementation. + */ +#undef data +#define data(ctx) ((SHA256_CTX *)EVP_MD_CTX_md_data(ctx)) +static int digest_sha256_init(EVP_MD_CTX *ctx) +{ + return SHA256_Init(data(ctx)); +} + +static int digest_sha256_update(EVP_MD_CTX *ctx, const void *data, + size_t count) +{ + return SHA256_Update(data(ctx), data, (size_t)count); +} + +static int digest_sha256_final(EVP_MD_CTX *ctx, unsigned char *md) +{ + int ret; + ret = SHA256_Final(md, data(ctx)); + + if (ret > 0) { + fill_known_data(md, SHA256_DIGEST_LENGTH); + } + return ret; +} + +/* + * SHA384/512 implementation. + */ +#undef data +#define data(ctx) ((SHA512_CTX *)EVP_MD_CTX_md_data(ctx)) +static int digest_sha384_init(EVP_MD_CTX *ctx) +{ + return SHA384_Init(data(ctx)); +} + +static int digest_sha512_init(EVP_MD_CTX *ctx) +{ + return SHA512_Init(data(ctx)); +} + +static int digest_sha512_update(EVP_MD_CTX *ctx, const void *data, + size_t count) +{ + return SHA512_Update(data(ctx), data, (size_t)count); +} + +static int digest_sha384_final(EVP_MD_CTX *ctx, unsigned char *md) +{ + int ret; + /* Actually uses SHA512_Final! */ + ret = SHA512_Final(md, data(ctx)); + + if (ret > 0) { + fill_known_data(md, SHA384_DIGEST_LENGTH); + } + return ret; +} + +static int digest_sha512_final(EVP_MD_CTX *ctx, unsigned char *md) +{ + int ret; + ret = SHA512_Final(md, data(ctx)); + + if (ret > 0) { + fill_known_data(md, SHA512_DIGEST_LENGTH); + } + return ret; +} + +/* + * AES128 Implementation + */ + +int ossltest_aes128_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + return EVP_CIPHER_meth_get_init(EVP_aes_128_cbc()) (ctx, key, iv, enc); +} + +int ossltest_aes128_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + unsigned char *tmpbuf; + int ret; + + tmpbuf = OPENSSL_malloc(inl); + + /* OPENSSL_malloc will return NULL if inl == 0 */ + if (tmpbuf == NULL && inl > 0) + return -1; + + /* Remember what we were asked to encrypt */ + if (tmpbuf != NULL) + memcpy(tmpbuf, in, inl); + + /* Go through the motions of encrypting it */ + ret = EVP_CIPHER_meth_get_do_cipher(EVP_aes_128_cbc())(ctx, out, in, inl); + + /* Throw it all away and just use the plaintext as the output */ + if (tmpbuf != NULL) + memcpy(out, tmpbuf, inl); + OPENSSL_free(tmpbuf); + + return ret; +} + +int ossltest_aes128_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + return EVP_CIPHER_meth_get_init(EVP_aes_128_gcm()) (ctx, key, iv, enc); +} + + +int ossltest_aes128_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + unsigned char *tmpbuf = OPENSSL_malloc(inl); + + /* OPENSSL_malloc will return NULL if inl == 0 */ + if (tmpbuf == NULL && inl > 0) + return -1; + + /* Remember what we were asked to encrypt */ + if (tmpbuf != NULL) + memcpy(tmpbuf, in, inl); + + /* Go through the motions of encrypting it */ + EVP_CIPHER_meth_get_do_cipher(EVP_aes_128_gcm())(ctx, out, in, inl); + + /* Throw it all away and just use the plaintext as the output */ + if (tmpbuf != NULL && out != NULL) + memcpy(out, tmpbuf, inl); + OPENSSL_free(tmpbuf); + + return inl; +} + +static int ossltest_aes128_gcm_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, + void *ptr) +{ + /* Pass the ctrl down */ + int ret = EVP_CIPHER_meth_get_ctrl(EVP_aes_128_gcm())(ctx, type, arg, ptr); + + if (ret <= 0) + return ret; + + switch(type) { + case EVP_CTRL_AEAD_GET_TAG: + /* Always give the same tag */ + memset(ptr, 0, EVP_GCM_TLS_TAG_LEN); + break; + + default: + break; + } + + return 1; +} + +static int ossltest_rand_bytes(unsigned char *buf, int num) +{ + unsigned char val = 1; + + while (--num >= 0) + *buf++ = val++; + return 1; +} + +static int ossltest_rand_status(void) +{ + return 1; +} + +static const RAND_METHOD *ossltest_rand_method(void) +{ + + static RAND_METHOD osslt_rand_meth = { + NULL, + ossltest_rand_bytes, + NULL, + NULL, + ossltest_rand_bytes, + ossltest_rand_status + }; + + return &osslt_rand_meth; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/engines/e_ossltest.ec b/trunk/3rdparty/openssl-1.1-fit/engines/e_ossltest.ec new file mode 100644 index 000000000..a4a55ecb3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/engines/e_ossltest.ec @@ -0,0 +1,3 @@ +# The INPUT HEADER is scanned for declarations +# LIBNAME INPUT HEADER ERROR-TABLE FILE +L OSSLTEST e_ossltest_err.h e_ossltest_err.c diff --git a/trunk/3rdparty/openssl-1.1-fit/engines/e_ossltest.txt b/trunk/3rdparty/openssl-1.1-fit/engines/e_ossltest.txt new file mode 100644 index 000000000..2b2e31a07 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/engines/e_ossltest.txt @@ -0,0 +1,13 @@ +# Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# Function codes +OSSLTEST_F_BIND_OSSLTEST:100:bind_ossltest +OSSLTEST_F_OSSLTEST_AES128_INIT_KEY:101:* + +#Reason codes +OSSLTEST_R_INIT_FAILED:100:init failed diff --git a/trunk/3rdparty/openssl-1.1-fit/engines/e_ossltest_err.c b/trunk/3rdparty/openssl-1.1-fit/engines/e_ossltest_err.c new file mode 100644 index 000000000..920a13a69 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/engines/e_ossltest_err.c @@ -0,0 +1,63 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "e_ossltest_err.h" + +#ifndef OPENSSL_NO_ERR + +static ERR_STRING_DATA OSSLTEST_str_functs[] = { + {ERR_PACK(0, OSSLTEST_F_BIND_OSSLTEST, 0), "bind_ossltest"}, + {ERR_PACK(0, OSSLTEST_F_OSSLTEST_AES128_INIT_KEY, 0), ""}, + {0, NULL} +}; + +static ERR_STRING_DATA OSSLTEST_str_reasons[] = { + {ERR_PACK(0, 0, OSSLTEST_R_INIT_FAILED), "init failed"}, + {0, NULL} +}; + +#endif + +static int lib_code = 0; +static int error_loaded = 0; + +static int ERR_load_OSSLTEST_strings(void) +{ + if (lib_code == 0) + lib_code = ERR_get_next_error_library(); + + if (!error_loaded) { +#ifndef OPENSSL_NO_ERR + ERR_load_strings(lib_code, OSSLTEST_str_functs); + ERR_load_strings(lib_code, OSSLTEST_str_reasons); +#endif + error_loaded = 1; + } + return 1; +} + +static void ERR_unload_OSSLTEST_strings(void) +{ + if (error_loaded) { +#ifndef OPENSSL_NO_ERR + ERR_unload_strings(lib_code, OSSLTEST_str_functs); + ERR_unload_strings(lib_code, OSSLTEST_str_reasons); +#endif + error_loaded = 0; + } +} + +static void ERR_OSSLTEST_error(int function, int reason, char *file, int line) +{ + if (lib_code == 0) + lib_code = ERR_get_next_error_library(); + ERR_PUT_error(lib_code, function, reason, file, line); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/engines/e_ossltest_err.h b/trunk/3rdparty/openssl-1.1-fit/engines/e_ossltest_err.h new file mode 100644 index 000000000..e745c1a23 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/engines/e_ossltest_err.h @@ -0,0 +1,28 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_OSSLTESTERR_H +# define HEADER_OSSLTESTERR_H + +# define OSSLTESTerr(f, r) ERR_OSSLTEST_error((f), (r), OPENSSL_FILE, OPENSSL_LINE) + + +/* + * OSSLTEST function codes. + */ +# define OSSLTEST_F_BIND_OSSLTEST 100 +# define OSSLTEST_F_OSSLTEST_AES128_INIT_KEY 101 + +/* + * OSSLTEST reason codes. + */ +# define OSSLTEST_R_INIT_FAILED 100 + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/engines/e_padlock.c b/trunk/3rdparty/openssl-1.1-fit/engines/e_padlock.c new file mode 100644 index 000000000..f6b1f1698 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/engines/e_padlock.c @@ -0,0 +1,747 @@ +/* + * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef OPENSSL_NO_HW +# ifndef OPENSSL_NO_HW_PADLOCK + +/* Attempt to have a single source for both 0.9.7 and 0.9.8 :-) */ +# if (OPENSSL_VERSION_NUMBER >= 0x00908000L) +# ifndef OPENSSL_NO_DYNAMIC_ENGINE +# define DYNAMIC_ENGINE +# endif +# elif (OPENSSL_VERSION_NUMBER >= 0x00907000L) +# ifdef ENGINE_DYNAMIC_SUPPORT +# define DYNAMIC_ENGINE +# endif +# else +# error "Only OpenSSL >= 0.9.7 is supported" +# endif + +/* + * VIA PadLock AES is available *ONLY* on some x86 CPUs. Not only that it + * doesn't exist elsewhere, but it even can't be compiled on other platforms! + */ + +# undef COMPILE_HW_PADLOCK +# if !defined(I386_ONLY) && defined(PADLOCK_ASM) +# define COMPILE_HW_PADLOCK +# ifdef OPENSSL_NO_DYNAMIC_ENGINE +static ENGINE *ENGINE_padlock(void); +# endif +# endif + +# ifdef OPENSSL_NO_DYNAMIC_ENGINE +void engine_load_padlock_int(void); +void engine_load_padlock_int(void) +{ +/* On non-x86 CPUs it just returns. */ +# ifdef COMPILE_HW_PADLOCK + ENGINE *toadd = ENGINE_padlock(); + if (!toadd) + return; + ENGINE_add(toadd); + ENGINE_free(toadd); + ERR_clear_error(); +# endif +} + +# endif + +# ifdef COMPILE_HW_PADLOCK + +/* Function for ENGINE detection and control */ +static int padlock_available(void); +static int padlock_init(ENGINE *e); + +/* RNG Stuff */ +static RAND_METHOD padlock_rand; + +/* Cipher Stuff */ +static int padlock_ciphers(ENGINE *e, const EVP_CIPHER **cipher, + const int **nids, int nid); + +/* Engine names */ +static const char *padlock_id = "padlock"; +static char padlock_name[100]; + +/* Available features */ +static int padlock_use_ace = 0; /* Advanced Cryptography Engine */ +static int padlock_use_rng = 0; /* Random Number Generator */ + +/* ===== Engine "management" functions ===== */ + +/* Prepare the ENGINE structure for registration */ +static int padlock_bind_helper(ENGINE *e) +{ + /* Check available features */ + padlock_available(); + + /* + * RNG is currently disabled for reasons discussed in commentary just + * before padlock_rand_bytes function. + */ + padlock_use_rng = 0; + + /* Generate a nice engine name with available features */ + BIO_snprintf(padlock_name, sizeof(padlock_name), + "VIA PadLock (%s, %s)", + padlock_use_rng ? "RNG" : "no-RNG", + padlock_use_ace ? "ACE" : "no-ACE"); + + /* Register everything or return with an error */ + if (!ENGINE_set_id(e, padlock_id) || + !ENGINE_set_name(e, padlock_name) || + !ENGINE_set_init_function(e, padlock_init) || + (padlock_use_ace && !ENGINE_set_ciphers(e, padlock_ciphers)) || + (padlock_use_rng && !ENGINE_set_RAND(e, &padlock_rand))) { + return 0; + } + + /* Everything looks good */ + return 1; +} + +# ifdef OPENSSL_NO_DYNAMIC_ENGINE +/* Constructor */ +static ENGINE *ENGINE_padlock(void) +{ + ENGINE *eng = ENGINE_new(); + + if (eng == NULL) { + return NULL; + } + + if (!padlock_bind_helper(eng)) { + ENGINE_free(eng); + return NULL; + } + + return eng; +} +# endif + +/* Check availability of the engine */ +static int padlock_init(ENGINE *e) +{ + return (padlock_use_rng || padlock_use_ace); +} + +/* + * This stuff is needed if this ENGINE is being compiled into a + * self-contained shared-library. + */ +# ifdef DYNAMIC_ENGINE +static int padlock_bind_fn(ENGINE *e, const char *id) +{ + if (id && (strcmp(id, padlock_id) != 0)) { + return 0; + } + + if (!padlock_bind_helper(e)) { + return 0; + } + + return 1; +} + +IMPLEMENT_DYNAMIC_CHECK_FN() +IMPLEMENT_DYNAMIC_BIND_FN(padlock_bind_fn) +# endif /* DYNAMIC_ENGINE */ +/* ===== Here comes the "real" engine ===== */ + +/* Some AES-related constants */ +# define AES_BLOCK_SIZE 16 +# define AES_KEY_SIZE_128 16 +# define AES_KEY_SIZE_192 24 +# define AES_KEY_SIZE_256 32 + /* + * Here we store the status information relevant to the current context. + */ + /* + * BIG FAT WARNING: Inline assembler in PADLOCK_XCRYPT_ASM() depends on + * the order of items in this structure. Don't blindly modify, reorder, + * etc! + */ +struct padlock_cipher_data { + unsigned char iv[AES_BLOCK_SIZE]; /* Initialization vector */ + union { + unsigned int pad[4]; + struct { + int rounds:4; + int dgst:1; /* n/a in C3 */ + int align:1; /* n/a in C3 */ + int ciphr:1; /* n/a in C3 */ + unsigned int keygen:1; + int interm:1; + unsigned int encdec:1; + int ksize:2; + } b; + } cword; /* Control word */ + AES_KEY ks; /* Encryption key */ +}; + +/* Interface to assembler module */ +unsigned int padlock_capability(void); +void padlock_key_bswap(AES_KEY *key); +void padlock_verify_context(struct padlock_cipher_data *ctx); +void padlock_reload_key(void); +void padlock_aes_block(void *out, const void *inp, + struct padlock_cipher_data *ctx); +int padlock_ecb_encrypt(void *out, const void *inp, + struct padlock_cipher_data *ctx, size_t len); +int padlock_cbc_encrypt(void *out, const void *inp, + struct padlock_cipher_data *ctx, size_t len); +int padlock_cfb_encrypt(void *out, const void *inp, + struct padlock_cipher_data *ctx, size_t len); +int padlock_ofb_encrypt(void *out, const void *inp, + struct padlock_cipher_data *ctx, size_t len); +int padlock_ctr32_encrypt(void *out, const void *inp, + struct padlock_cipher_data *ctx, size_t len); +int padlock_xstore(void *out, int edx); +void padlock_sha1_oneshot(void *ctx, const void *inp, size_t len); +void padlock_sha1(void *ctx, const void *inp, size_t len); +void padlock_sha256_oneshot(void *ctx, const void *inp, size_t len); +void padlock_sha256(void *ctx, const void *inp, size_t len); + +/* + * Load supported features of the CPU to see if the PadLock is available. + */ +static int padlock_available(void) +{ + unsigned int edx = padlock_capability(); + + /* Fill up some flags */ + padlock_use_ace = ((edx & (0x3 << 6)) == (0x3 << 6)); + padlock_use_rng = ((edx & (0x3 << 2)) == (0x3 << 2)); + + return padlock_use_ace + padlock_use_rng; +} + +/* ===== AES encryption/decryption ===== */ + +# if defined(NID_aes_128_cfb128) && ! defined (NID_aes_128_cfb) +# define NID_aes_128_cfb NID_aes_128_cfb128 +# endif + +# if defined(NID_aes_128_ofb128) && ! defined (NID_aes_128_ofb) +# define NID_aes_128_ofb NID_aes_128_ofb128 +# endif + +# if defined(NID_aes_192_cfb128) && ! defined (NID_aes_192_cfb) +# define NID_aes_192_cfb NID_aes_192_cfb128 +# endif + +# if defined(NID_aes_192_ofb128) && ! defined (NID_aes_192_ofb) +# define NID_aes_192_ofb NID_aes_192_ofb128 +# endif + +# if defined(NID_aes_256_cfb128) && ! defined (NID_aes_256_cfb) +# define NID_aes_256_cfb NID_aes_256_cfb128 +# endif + +# if defined(NID_aes_256_ofb128) && ! defined (NID_aes_256_ofb) +# define NID_aes_256_ofb NID_aes_256_ofb128 +# endif + +/* List of supported ciphers. */ +static const int padlock_cipher_nids[] = { + NID_aes_128_ecb, + NID_aes_128_cbc, + NID_aes_128_cfb, + NID_aes_128_ofb, + NID_aes_128_ctr, + + NID_aes_192_ecb, + NID_aes_192_cbc, + NID_aes_192_cfb, + NID_aes_192_ofb, + NID_aes_192_ctr, + + NID_aes_256_ecb, + NID_aes_256_cbc, + NID_aes_256_cfb, + NID_aes_256_ofb, + NID_aes_256_ctr +}; + +static int padlock_cipher_nids_num = (sizeof(padlock_cipher_nids) / + sizeof(padlock_cipher_nids[0])); + +/* Function prototypes ... */ +static int padlock_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); + +# define NEAREST_ALIGNED(ptr) ( (unsigned char *)(ptr) + \ + ( (0x10 - ((size_t)(ptr) & 0x0F)) & 0x0F ) ) +# define ALIGNED_CIPHER_DATA(ctx) ((struct padlock_cipher_data *)\ + NEAREST_ALIGNED(EVP_CIPHER_CTX_get_cipher_data(ctx))) + +static int +padlock_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, + const unsigned char *in_arg, size_t nbytes) +{ + return padlock_ecb_encrypt(out_arg, in_arg, + ALIGNED_CIPHER_DATA(ctx), nbytes); +} + +static int +padlock_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, + const unsigned char *in_arg, size_t nbytes) +{ + struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx); + int ret; + + memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), AES_BLOCK_SIZE); + if ((ret = padlock_cbc_encrypt(out_arg, in_arg, cdata, nbytes))) + memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, AES_BLOCK_SIZE); + return ret; +} + +static int +padlock_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, + const unsigned char *in_arg, size_t nbytes) +{ + struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx); + size_t chunk; + + if ((chunk = EVP_CIPHER_CTX_num(ctx))) { /* borrow chunk variable */ + unsigned char *ivp = EVP_CIPHER_CTX_iv_noconst(ctx); + + if (chunk >= AES_BLOCK_SIZE) + return 0; /* bogus value */ + + if (EVP_CIPHER_CTX_encrypting(ctx)) + while (chunk < AES_BLOCK_SIZE && nbytes != 0) { + ivp[chunk] = *(out_arg++) = *(in_arg++) ^ ivp[chunk]; + chunk++, nbytes--; + } else + while (chunk < AES_BLOCK_SIZE && nbytes != 0) { + unsigned char c = *(in_arg++); + *(out_arg++) = c ^ ivp[chunk]; + ivp[chunk++] = c, nbytes--; + } + + EVP_CIPHER_CTX_set_num(ctx, chunk % AES_BLOCK_SIZE); + } + + if (nbytes == 0) + return 1; + + memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), AES_BLOCK_SIZE); + + if ((chunk = nbytes & ~(AES_BLOCK_SIZE - 1))) { + if (!padlock_cfb_encrypt(out_arg, in_arg, cdata, chunk)) + return 0; + nbytes -= chunk; + } + + if (nbytes) { + unsigned char *ivp = cdata->iv; + + out_arg += chunk; + in_arg += chunk; + EVP_CIPHER_CTX_set_num(ctx, nbytes); + if (cdata->cword.b.encdec) { + cdata->cword.b.encdec = 0; + padlock_reload_key(); + padlock_aes_block(ivp, ivp, cdata); + cdata->cword.b.encdec = 1; + padlock_reload_key(); + while (nbytes) { + unsigned char c = *(in_arg++); + *(out_arg++) = c ^ *ivp; + *(ivp++) = c, nbytes--; + } + } else { + padlock_reload_key(); + padlock_aes_block(ivp, ivp, cdata); + padlock_reload_key(); + while (nbytes) { + *ivp = *(out_arg++) = *(in_arg++) ^ *ivp; + ivp++, nbytes--; + } + } + } + + memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, AES_BLOCK_SIZE); + + return 1; +} + +static int +padlock_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, + const unsigned char *in_arg, size_t nbytes) +{ + struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx); + size_t chunk; + + /* + * ctx->num is maintained in byte-oriented modes, such as CFB and OFB... + */ + if ((chunk = EVP_CIPHER_CTX_num(ctx))) { /* borrow chunk variable */ + unsigned char *ivp = EVP_CIPHER_CTX_iv_noconst(ctx); + + if (chunk >= AES_BLOCK_SIZE) + return 0; /* bogus value */ + + while (chunk < AES_BLOCK_SIZE && nbytes != 0) { + *(out_arg++) = *(in_arg++) ^ ivp[chunk]; + chunk++, nbytes--; + } + + EVP_CIPHER_CTX_set_num(ctx, chunk % AES_BLOCK_SIZE); + } + + if (nbytes == 0) + return 1; + + memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), AES_BLOCK_SIZE); + + if ((chunk = nbytes & ~(AES_BLOCK_SIZE - 1))) { + if (!padlock_ofb_encrypt(out_arg, in_arg, cdata, chunk)) + return 0; + nbytes -= chunk; + } + + if (nbytes) { + unsigned char *ivp = cdata->iv; + + out_arg += chunk; + in_arg += chunk; + EVP_CIPHER_CTX_set_num(ctx, nbytes); + padlock_reload_key(); /* empirically found */ + padlock_aes_block(ivp, ivp, cdata); + padlock_reload_key(); /* empirically found */ + while (nbytes) { + *(out_arg++) = *(in_arg++) ^ *ivp; + ivp++, nbytes--; + } + } + + memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, AES_BLOCK_SIZE); + + return 1; +} + +static void padlock_ctr32_encrypt_glue(const unsigned char *in, + unsigned char *out, size_t blocks, + struct padlock_cipher_data *ctx, + const unsigned char *ivec) +{ + memcpy(ctx->iv, ivec, AES_BLOCK_SIZE); + padlock_ctr32_encrypt(out, in, ctx, AES_BLOCK_SIZE * blocks); +} + +static int +padlock_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, + const unsigned char *in_arg, size_t nbytes) +{ + struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx); + unsigned int num = EVP_CIPHER_CTX_num(ctx); + + CRYPTO_ctr128_encrypt_ctr32(in_arg, out_arg, nbytes, + cdata, EVP_CIPHER_CTX_iv_noconst(ctx), + EVP_CIPHER_CTX_buf_noconst(ctx), &num, + (ctr128_f) padlock_ctr32_encrypt_glue); + + EVP_CIPHER_CTX_set_num(ctx, (size_t)num); + return 1; +} + +# define EVP_CIPHER_block_size_ECB AES_BLOCK_SIZE +# define EVP_CIPHER_block_size_CBC AES_BLOCK_SIZE +# define EVP_CIPHER_block_size_OFB 1 +# define EVP_CIPHER_block_size_CFB 1 +# define EVP_CIPHER_block_size_CTR 1 + +/* + * Declaring so many ciphers by hand would be a pain. Instead introduce a bit + * of preprocessor magic :-) + */ +# define DECLARE_AES_EVP(ksize,lmode,umode) \ +static EVP_CIPHER *_hidden_aes_##ksize##_##lmode = NULL; \ +static const EVP_CIPHER *padlock_aes_##ksize##_##lmode(void) \ +{ \ + if (_hidden_aes_##ksize##_##lmode == NULL \ + && ((_hidden_aes_##ksize##_##lmode = \ + EVP_CIPHER_meth_new(NID_aes_##ksize##_##lmode, \ + EVP_CIPHER_block_size_##umode, \ + AES_KEY_SIZE_##ksize)) == NULL \ + || !EVP_CIPHER_meth_set_iv_length(_hidden_aes_##ksize##_##lmode, \ + AES_BLOCK_SIZE) \ + || !EVP_CIPHER_meth_set_flags(_hidden_aes_##ksize##_##lmode, \ + 0 | EVP_CIPH_##umode##_MODE) \ + || !EVP_CIPHER_meth_set_init(_hidden_aes_##ksize##_##lmode, \ + padlock_aes_init_key) \ + || !EVP_CIPHER_meth_set_do_cipher(_hidden_aes_##ksize##_##lmode, \ + padlock_##lmode##_cipher) \ + || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_aes_##ksize##_##lmode, \ + sizeof(struct padlock_cipher_data) + 16) \ + || !EVP_CIPHER_meth_set_set_asn1_params(_hidden_aes_##ksize##_##lmode, \ + EVP_CIPHER_set_asn1_iv) \ + || !EVP_CIPHER_meth_set_get_asn1_params(_hidden_aes_##ksize##_##lmode, \ + EVP_CIPHER_get_asn1_iv))) { \ + EVP_CIPHER_meth_free(_hidden_aes_##ksize##_##lmode); \ + _hidden_aes_##ksize##_##lmode = NULL; \ + } \ + return _hidden_aes_##ksize##_##lmode; \ +} + +DECLARE_AES_EVP(128, ecb, ECB) +DECLARE_AES_EVP(128, cbc, CBC) +DECLARE_AES_EVP(128, cfb, CFB) +DECLARE_AES_EVP(128, ofb, OFB) +DECLARE_AES_EVP(128, ctr, CTR) + +DECLARE_AES_EVP(192, ecb, ECB) +DECLARE_AES_EVP(192, cbc, CBC) +DECLARE_AES_EVP(192, cfb, CFB) +DECLARE_AES_EVP(192, ofb, OFB) +DECLARE_AES_EVP(192, ctr, CTR) + +DECLARE_AES_EVP(256, ecb, ECB) +DECLARE_AES_EVP(256, cbc, CBC) +DECLARE_AES_EVP(256, cfb, CFB) +DECLARE_AES_EVP(256, ofb, OFB) +DECLARE_AES_EVP(256, ctr, CTR) + +static int +padlock_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, + int nid) +{ + /* No specific cipher => return a list of supported nids ... */ + if (!cipher) { + *nids = padlock_cipher_nids; + return padlock_cipher_nids_num; + } + + /* ... or the requested "cipher" otherwise */ + switch (nid) { + case NID_aes_128_ecb: + *cipher = padlock_aes_128_ecb(); + break; + case NID_aes_128_cbc: + *cipher = padlock_aes_128_cbc(); + break; + case NID_aes_128_cfb: + *cipher = padlock_aes_128_cfb(); + break; + case NID_aes_128_ofb: + *cipher = padlock_aes_128_ofb(); + break; + case NID_aes_128_ctr: + *cipher = padlock_aes_128_ctr(); + break; + + case NID_aes_192_ecb: + *cipher = padlock_aes_192_ecb(); + break; + case NID_aes_192_cbc: + *cipher = padlock_aes_192_cbc(); + break; + case NID_aes_192_cfb: + *cipher = padlock_aes_192_cfb(); + break; + case NID_aes_192_ofb: + *cipher = padlock_aes_192_ofb(); + break; + case NID_aes_192_ctr: + *cipher = padlock_aes_192_ctr(); + break; + + case NID_aes_256_ecb: + *cipher = padlock_aes_256_ecb(); + break; + case NID_aes_256_cbc: + *cipher = padlock_aes_256_cbc(); + break; + case NID_aes_256_cfb: + *cipher = padlock_aes_256_cfb(); + break; + case NID_aes_256_ofb: + *cipher = padlock_aes_256_ofb(); + break; + case NID_aes_256_ctr: + *cipher = padlock_aes_256_ctr(); + break; + + default: + /* Sorry, we don't support this NID */ + *cipher = NULL; + return 0; + } + + return 1; +} + +/* Prepare the encryption key for PadLock usage */ +static int +padlock_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + struct padlock_cipher_data *cdata; + int key_len = EVP_CIPHER_CTX_key_length(ctx) * 8; + unsigned long mode = EVP_CIPHER_CTX_mode(ctx); + + if (key == NULL) + return 0; /* ERROR */ + + cdata = ALIGNED_CIPHER_DATA(ctx); + memset(cdata, 0, sizeof(*cdata)); + + /* Prepare Control word. */ + if (mode == EVP_CIPH_OFB_MODE || mode == EVP_CIPH_CTR_MODE) + cdata->cword.b.encdec = 0; + else + cdata->cword.b.encdec = (EVP_CIPHER_CTX_encrypting(ctx) == 0); + cdata->cword.b.rounds = 10 + (key_len - 128) / 32; + cdata->cword.b.ksize = (key_len - 128) / 64; + + switch (key_len) { + case 128: + /* + * PadLock can generate an extended key for AES128 in hardware + */ + memcpy(cdata->ks.rd_key, key, AES_KEY_SIZE_128); + cdata->cword.b.keygen = 0; + break; + + case 192: + case 256: + /* + * Generate an extended AES key in software. Needed for AES192/AES256 + */ + /* + * Well, the above applies to Stepping 8 CPUs and is listed as + * hardware errata. They most likely will fix it at some point and + * then a check for stepping would be due here. + */ + if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) + && !enc) + AES_set_decrypt_key(key, key_len, &cdata->ks); + else + AES_set_encrypt_key(key, key_len, &cdata->ks); +# ifndef AES_ASM + /* + * OpenSSL C functions use byte-swapped extended key. + */ + padlock_key_bswap(&cdata->ks); +# endif + cdata->cword.b.keygen = 1; + break; + + default: + /* ERROR */ + return 0; + } + + /* + * This is done to cover for cases when user reuses the + * context for new key. The catch is that if we don't do + * this, padlock_eas_cipher might proceed with old key... + */ + padlock_reload_key(); + + return 1; +} + +/* ===== Random Number Generator ===== */ +/* + * This code is not engaged. The reason is that it does not comply + * with recommendations for VIA RNG usage for secure applications + * (posted at http://www.via.com.tw/en/viac3/c3.jsp) nor does it + * provide meaningful error control... + */ +/* + * Wrapper that provides an interface between the API and the raw PadLock + * RNG + */ +static int padlock_rand_bytes(unsigned char *output, int count) +{ + unsigned int eax, buf; + + while (count >= 8) { + eax = padlock_xstore(output, 0); + if (!(eax & (1 << 6))) + return 0; /* RNG disabled */ + /* this ---vv--- covers DC bias, Raw Bits and String Filter */ + if (eax & (0x1F << 10)) + return 0; + if ((eax & 0x1F) == 0) + continue; /* no data, retry... */ + if ((eax & 0x1F) != 8) + return 0; /* fatal failure... */ + output += 8; + count -= 8; + } + while (count > 0) { + eax = padlock_xstore(&buf, 3); + if (!(eax & (1 << 6))) + return 0; /* RNG disabled */ + /* this ---vv--- covers DC bias, Raw Bits and String Filter */ + if (eax & (0x1F << 10)) + return 0; + if ((eax & 0x1F) == 0) + continue; /* no data, retry... */ + if ((eax & 0x1F) != 1) + return 0; /* fatal failure... */ + *output++ = (unsigned char)buf; + count--; + } + OPENSSL_cleanse(&buf, sizeof(buf)); + + return 1; +} + +/* Dummy but necessary function */ +static int padlock_rand_status(void) +{ + return 1; +} + +/* Prepare structure for registration */ +static RAND_METHOD padlock_rand = { + NULL, /* seed */ + padlock_rand_bytes, /* bytes */ + NULL, /* cleanup */ + NULL, /* add */ + padlock_rand_bytes, /* pseudorand */ + padlock_rand_status, /* rand status */ +}; + +# endif /* COMPILE_HW_PADLOCK */ +# endif /* !OPENSSL_NO_HW_PADLOCK */ +#endif /* !OPENSSL_NO_HW */ + +#if defined(OPENSSL_NO_HW) || defined(OPENSSL_NO_HW_PADLOCK) \ + || !defined(COMPILE_HW_PADLOCK) +# ifndef OPENSSL_NO_DYNAMIC_ENGINE +OPENSSL_EXPORT + int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns); +OPENSSL_EXPORT + int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) +{ + return 0; +} + +IMPLEMENT_DYNAMIC_CHECK_FN() +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/external/perl/Downloaded.txt b/trunk/3rdparty/openssl-1.1-fit/external/perl/Downloaded.txt new file mode 100644 index 000000000..af0c20a3e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/external/perl/Downloaded.txt @@ -0,0 +1,13 @@ +Intro +----- + +If we find a useful Perl module that isn't one of the core Perl +modules, we may choose to bundle it with the OpenSSL source. + +Here, we simply list those modules and where we downloaded them from. + +Downloaded and bundled Perl modules +----------------------------------- + +Text::Template 1.46 was downloaded from +http://search.cpan.org/CPAN/authors/id/M/MJ/MJD/Text-Template-1.46.tar.gz diff --git a/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/Artistic b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/Artistic new file mode 100644 index 000000000..5f221241e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/Artistic @@ -0,0 +1,131 @@ + + + + + The "Artistic License" + + Preamble + +The intent of this document is to state the conditions under which a +Package may be copied, such that the Copyright Holder maintains some +semblance of artistic control over the development of the package, +while giving the users of the package the right to use and distribute +the Package in a more-or-less customary fashion, plus the right to make +reasonable modifications. + +Definitions: + + "Package" refers to the collection of files distributed by the + Copyright Holder, and derivatives of that collection of files + created through textual modification. + + "Standard Version" refers to such a Package if it has not been + modified, or has been modified in accordance with the wishes + of the Copyright Holder as specified below. + + "Copyright Holder" is whoever is named in the copyright or + copyrights for the package. + + "You" is you, if you're thinking about copying or distributing + this Package. + + "Reasonable copying fee" is whatever you can justify on the + basis of media cost, duplication charges, time of people involved, + and so on. (You will not be required to justify it to the + Copyright Holder, but only to the computing community at large + as a market that must bear the fee.) + + "Freely Available" means that no fee is charged for the item + itself, though there may be fees involved in handling the item. + It also means that recipients of the item may redistribute it + under the same conditions they received it. + +1. You may make and give away verbatim copies of the source form of the +Standard Version of this Package without restriction, provided that you +duplicate all of the original copyright notices and associated disclaimers. + +2. You may apply bug fixes, portability fixes and other modifications +derived from the Public Domain or from the Copyright Holder. A Package +modified in such a way shall still be considered the Standard Version. + +3. You may otherwise modify your copy of this Package in any way, provided +that you insert a prominent notice in each changed file stating how and +when you changed that file, and provided that you do at least ONE of the +following: + + a) place your modifications in the Public Domain or otherwise make them + Freely Available, such as by posting said modifications to Usenet or + an equivalent medium, or placing the modifications on a major archive + site such as uunet.uu.net, or by allowing the Copyright Holder to include + your modifications in the Standard Version of the Package. + + b) use the modified Package only within your corporation or organization. + + c) rename any non-standard executables so the names do not conflict + with standard executables, which must also be provided, and provide + a separate manual page for each non-standard executable that clearly + documents how it differs from the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +4. You may distribute the programs of this Package in object code or +executable form, provided that you do at least ONE of the following: + + a) distribute a Standard Version of the executables and library files, + together with instructions (in the manual page or equivalent) on where + to get the Standard Version. + + b) accompany the distribution with the machine-readable source of + the Package with your modifications. + + c) give non-standard executables non-standard names, and clearly + document the differences in manual pages (or equivalent), together + with instructions on where to get the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +5. You may charge a reasonable copying fee for any distribution of this +Package. You may charge any fee you choose for support of this +Package. You may not charge a fee for this Package itself. However, +you may distribute this Package in aggregate with other (possibly +commercial) programs as part of a larger (possibly commercial) software +distribution provided that you do not advertise this Package as a +product of your own. You may embed this Package's interpreter within +an executable of yours (by linking); this shall be construed as a mere +form of aggregation, provided that the complete Standard Version of the +interpreter is so embedded. + +6. The scripts and library files supplied as input to or produced as +output from the programs of this Package do not automatically fall +under the copyright of this Package, but belong to whoever generated +them, and may be sold commercially, and may be aggregated with this +Package. If such scripts or library files are aggregated with this +Package via the so-called "undump" or "unexec" methods of producing a +binary executable image, then distribution of such an image shall +neither be construed as a distribution of this Package nor shall it +fall under the restrictions of Paragraphs 3 and 4, provided that you do +not represent such an executable image as a Standard Version of this +Package. + +7. C subroutines (or comparably compiled subroutines in other +languages) supplied by you and linked into this Package in order to +emulate subroutines and variables of the language defined by this +Package shall not be considered part of this Package, but are the +equivalent of input as in Paragraph 6, provided these subroutines do +not change the language in any way that would cause it to fail the +regression tests for the language. + +8. Aggregation of this Package with a commercial distribution is always +permitted provided that the use of this Package is embedded; that is, +when no overt attempt is made to make this Package's interfaces visible +to the end user of the commercial distribution. Such use shall not be +construed as a distribution of this Package. + +9. The name of the Copyright Holder may not be used to endorse or promote +products derived from this software without specific prior written permission. + +10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + The End diff --git a/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/COPYING b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/COPYING new file mode 100644 index 000000000..a3f6b12ee --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/INSTALL b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/INSTALL new file mode 100644 index 000000000..7c5e4c6bd --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/INSTALL @@ -0,0 +1,31 @@ + +To install: + + perl Makefile.PL + +to construct the Makefile, then + + make test + +to test the package. If it fails any tests, please send me the output +of `make test' and `perl -V'. I'll tell you whether it is safe to go +ahead, or I'll provide a fix. + +If it passes the tests, use + + make install + +to install it. + +Detailed documentation is at the bottom of the lib/Text/Template.pm +file. You may be able to view it with the following command: + + perldoc Text::Template + +Or: + + perldoc lib/Text/Template.pm + +If you have problems, send me mail: + +mjd-perl-template+@plover.com diff --git a/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/MANIFEST b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/MANIFEST new file mode 100644 index 000000000..22460fe8b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/MANIFEST @@ -0,0 +1,25 @@ +MANIFEST +COPYING +Artistic +Makefile.PL +INSTALL +README +lib/Text/Template.pm +lib/Text/Template/Preprocess.pm +t/00-version.t +t/01-basic.t +t/02-hash.t +t/03-out.t +t/04-safe.t +t/05-safe2.t +t/06-ofh.t +t/07-safe3.t +t/08-exported.t +t/09-error.t +t/10-delimiters.t +t/11-prepend.t +t/12-preprocess.t +t/13-taint.t +t/14-broken.t +META.yml Module meta-data (added by MakeMaker) +META.json Module JSON meta-data (added by MakeMaker) diff --git a/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/META.json b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/META.json new file mode 100644 index 000000000..6b335eb94 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/META.json @@ -0,0 +1,39 @@ +{ + "abstract" : "unknown", + "author" : [ + "unknown" + ], + "dynamic_config" : 1, + "generated_by" : "ExtUtils::MakeMaker version 6.62, CPAN::Meta::Converter version 2.120630", + "license" : [ + "unknown" + ], + "meta-spec" : { + "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "version" : "2" + }, + "name" : "Text-Template", + "no_index" : { + "directory" : [ + "t", + "inc" + ] + }, + "prereqs" : { + "build" : { + "requires" : { + "ExtUtils::MakeMaker" : "0" + } + }, + "configure" : { + "requires" : { + "ExtUtils::MakeMaker" : "0" + } + }, + "runtime" : { + "requires" : {} + } + }, + "release_status" : "stable", + "version" : "1.46" +} diff --git a/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/META.yml b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/META.yml new file mode 100644 index 000000000..a2e271594 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/META.yml @@ -0,0 +1,21 @@ +--- +abstract: unknown +author: + - unknown +build_requires: + ExtUtils::MakeMaker: 0 +configure_requires: + ExtUtils::MakeMaker: 0 +dynamic_config: 1 +generated_by: 'ExtUtils::MakeMaker version 6.62, CPAN::Meta::Converter version 2.120630' +license: unknown +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: 1.4 +name: Text-Template +no_index: + directory: + - t + - inc +requires: {} +version: 1.46 diff --git a/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/Makefile.PL b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/Makefile.PL new file mode 100644 index 000000000..491e03cb0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/Makefile.PL @@ -0,0 +1,7 @@ +use ExtUtils::MakeMaker; +WriteMakefile( + NAME => 'Text::Template', + VERSION_FROM => 'lib/Text/Template.pm', +# 'linkext' => {LINKTYPE => ''}, + 'dist' => {COMPRESS => 'gzip', SUFFIX => 'gz'}, +); diff --git a/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/README b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/README new file mode 100644 index 000000000..e184d8cd2 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/README @@ -0,0 +1,339 @@ + +Text::Template v1.46 + +This is a library for generating form letters, building HTML pages, or +filling in templates generally. A `template' is a piece of text that +has little Perl programs embedded in it here and there. When you +`fill in' a template, you evaluate the little programs and replace +them with their values. + +Here's an example of a template: + + Dear {$title} {$lastname}, + + It has come to our attention that you are delinquent in your + {$monthname[$last_paid_month]} payment. Please remit + ${sprintf("%.2f", $amount)} immediately, or your patellae may + be needlessly endangered. + + Love, + + Mark "{nickname(rand 20)}" Dominus + + +The result of filling in this template is a string, which might look +something like this: + + Dear Mr. Gates, + + It has come to our attention that you are delinquent in your + February payment. Please remit + $392.12 immediately, or your patellae may + be needlessly endangered. + + + Love, + + Mark "Vizopteryx" Dominus + +You can store a template in a file outside your program. People can +modify the template without modifying the program. You can separate +the formatting details from the main code, and put the formatting +parts of the program into the template. That prevents code bloat and +encourages functional separation. + +You can fill in the template in a `Safe' compartment. This means that +if you don't trust the person who wrote the code in the template, you +won't have to worry that they are tampering with your program when you +execute it. + +---------------------------------------------------------------- + +Text::Template was originally released some time in late 1995 or early +1996. After three years of study and investigation, I rewrote it from +scratch in January 1999. The new version, 1.0, was much faster, +delivered better functionality and was almost 100% backward-compatible +with the previous beta versions. + +I have added a number of useful features and conveniences since the +1.0 release, while still retaining backward compatibility. With one +merely cosmetic change, the current version of Text::Template passes +the test suite that the old beta versions passed. + +Questions or comments should be addressed to +mjd-perl-template+@plover.com. This address goes directly to me, and +not to anyone else; it is not a mailing list address. + +To receive occasional announcements of new versions of T::T, send an +empty note to mjd-perl-template-request@plover.com. This mailing list +is not for discussion; it is for announcements only. Therefore, there +is no address for sending messages to the list. + +You can get the most recent version of Text::Template, news, comments, +and other collateral information from +. + +---------------------------------------------------------------- + +What's new in v1.46 since v1.44: + + Thanks to Rik Signes, there is a new + Text::Template->append_text_to_output method, which + Text::Template always uses whenever it wants to emit output. + You can subclass this to get control over the output, for + example for postprocessing. + + A spurious warning is no longer emitted when the TYPE + parameter to ->new is omitted. + +---------------------------------------------------------------- +What's new in v1.44 since v1.43: + +This is a maintentance release. There are no feature changes. + + _scrubpkg, which was responsible for eptying out temporary + packages after the module had done with them, wasn't always + working; the result was memory-leaks in long-running + applications. This should be fixed now, and there is a test + in the test suite for it. + + Minor changes to the test suite to prevent spurious errors. + + Minor documentation changes. + +---------------------------------------------------------------- +What's new in v1.43 since v1.42: + + The ->new method now fails immediately and sets + $Text::Template::ERROR if the file that is named by a filename + argument does not exist or cannot be opened for some other + reason. Formerly, the constructor would succeed and the + ->fill_in call would fail. + +---------------------------------------------------------------- + +What's new in v1.42 since v1.41: + +This is a maintentance release. There are no feature changes. + + Fixed a bug relating to use of UNTAINT under perl 5.005_03 and + possibly other versions. + + Taint-related tests are now more comprehensive. +---------------------------------------------------------------- + +What's new in v1.41 since v1.40: + +This is a maintentance release. There are no feature changes. + + Tests now work correctly on Windows systems and possibly on + other non-unix systems. + +---------------------------------------------------------------- + +What's new in v1.40 since v1.31: + + New UNTAINT option tells the module that it is safe to 'eval' + code even though it has come from a file or filehandle. + + Code added to prevent memory leaks when filling many + templates. Thanks to Itamar Almeida de Carvalho. + + Bug fix: $OUT was not correctly initialized when used in + conjunction with SAFE. + + You may now use a glob ref when passing a filehandle to the + ->new funcion. Formerly, a glob was reuqired. + + New subclass: Text::Template::Preprocess. Just like + Text::Template, but you may supply a PREPROCESS option in the + constructor or the fill_in call; this is a function which + receives each code fragment prior to evaluation, and which may + modify and return the fragment; the modified fragment is what + is evaluated. + + Error messages passed to BROKEN subroutines will now report + the correct line number of the template at which the error + occurred: + + Illegal division by zero at template line 37. + + If the template comes from a file, the filename will be + reported as well: + + Illegal division by zero at catalog.tmpl line 37. + + + INCOMPATIBLE CHANGE: + + The format of the default error message has changed. It used + to look like: + + Program fragment at line 30 delivered error ``Illegal division by zero'' + + It now looks like: + + Program fragment delivered error ``Illegal division by zero at catalog.tmpl line 37'' + + Note that the default message used to report the line number + at which the program fragment began; it now reports the line + number at which the error actually occurred. + +---------------------------------------------------------------- +What's new in v1.31 since v1.23: + + Just bug fixes---fill_in_string was failing. Thanks to + Donald L. Greer Jr. for the test case. + +---------------------------------------------------------------- +What's new in v1.23 since v1.22: + + Small bug fix: DELIMITER and other arguments were being + ignored in calls to fill_in_file and fill_this_in. (Thanks to + Jonathan Roy for reporting this.) + +---------------------------------------------------------------- +What's new in v1.22 since v1.20: + + You can now specify that certain Perl statements be prepended + to the beginning of every program fragment in a template, + either per template, or for all templates, or for the duration + of only one call to fill_in. This is useful, for example, if + you want to enable `strict' checks in your templates but you + don't want to manually add `use strict' to the front of every + program fragment everywhere. + +---------------------------------------------------------------- +What's new in v1.20 since v1.12: + + You can now specify that the program fragment delimiters are + strings other than { and }. This has three interesting + effects: First, it changes the delimiter strings. Second, it + disables the special meaning of \, so you have to be really, + really sure that the delimiters will not appear in your + templates. And third, because of the simplifications + introduced by the elimination of \ processing, template + parsing is 20-25% faster. + + See the manual section on `Alternative Delimiters'. + + Fixed bug having to do with undefined values in HASH options. + In particular, Text::Template no longer generates a warning if + you try to give a variable an undefined value. + +---------------------------------------------------------------- + +What's new in v1.12 since v1.11: + + I forgot to say that Text::Template ISA Exporter, so the + exported functions never got exported. Duhhh! + + Template TYPEs are now case-insensitive. The `new' method now + diagnoses attempts to use an invalid TYPE. + + More tests for these things. + +---------------------------------------------------------------- + +What's new in v1.11 since v1.10: + + Fixed a bug in the way backslashes were processed. The 1.10 + behavior was incompatible with the beta versions and was also + inconvenient. (`\n' in templates was replaced with `n' before + it was given to Perl for evaluation.) The new behavior is + also incompatible with the beta versions, but it is only a + little bit incompatible, and it is probbaly better. + + Documentation for the new behavior, and tests for the bug. + +---------------------------------------------------------------- + +What's new in v1.10 since v1.03: + + New OUTPUT option delivers template results directly to a + filehandle instead of making them into a string. Saves space + and time. + + PACKAGE and HASH now work intelligently with SAFE. + + Fragments may now output data directly to the template, rather + than having to arrange to return it as a return value at the + end. This means that where you used to have to write this: + + { my $blist = ''; + foreach $i (@items) { + $blist .= qq{ * $i\n}; + } + $blist; + } + + You can now write this instead, because $OUT is special. + + { foreach $i (@items) { + $OUT.= " * $i\n"; + } + } + + (`A spoonful of sugar makes the medicine go down.') + + Fixed some small bugs. Worked around a bug in Perl that does + the wrong thing with $x = when $x contains a glob. + + More documentation. Errors fixed. + + Lots more tests. + +---------------------------------------------------------------- + +What's new in v1.03 since v1.0: + + Code added to support HASH option to fill_in. + (Incl. `_gensym' function.) + + Documentation for HASH. + + New test file for HASH. + + Note about failure of lexical variables to propagate into + templates. Why does this surprise people? + + Bug fix: program fragments are evaluated in an environment with + `no strict' by default. Otherwise, you get a lot of `Global + symbol "$v" requires explicit package name' failures. Why didn't + the test program pick this up? Because the only variable the test + program ever used was `$a', which is exempt. Duhhhhh. + + Fixed the test program. + + Various minor documentation fixes. + + + +---------------------------------------------------------------- + +Improvements of 1.0 over the old 0.1beta: + +New features: + + At least twice as fast + + Better support for filling out the same template more than once + + Now supports evaluation of program fragments in Safe + compartments. (Thanks, Jonathan!) + + Better argument syntax + + More convenience functions + + The parser is much better and simpler. + + Once a template is parsed, the parsed version is stored so that + it needn't be parsed again. + + BROKEN function behavior is rationalized. You can now pass an + arbitrary argument to your BROKEN function, or return a value + from it to the main program. + + Documentation overhauled. + diff --git a/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/lib/Text/Template.pm b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/lib/Text/Template.pm new file mode 100644 index 000000000..dc4f3bac7 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/lib/Text/Template.pm @@ -0,0 +1,1973 @@ +# -*- perl -*- +# Text::Template.pm +# +# Fill in `templates' +# +# Copyright 2013 M. J. Dominus. +# You may copy and distribute this program under the +# same terms as Perl iteself. +# If in doubt, write to mjd-perl-template+@plover.com for a license. +# +# Version 1.46 + +package Text::Template; +require 5.004; +use Exporter; +@ISA = qw(Exporter); +@EXPORT_OK = qw(fill_in_file fill_in_string TTerror); +use vars '$ERROR'; +use strict; + +$Text::Template::VERSION = '1.46'; +my %GLOBAL_PREPEND = ('Text::Template' => ''); + +sub Version { + $Text::Template::VERSION; +} + +sub _param { + my $kk; + my ($k, %h) = @_; + for $kk ($k, "\u$k", "\U$k", "-$k", "-\u$k", "-\U$k") { + return $h{$kk} if exists $h{$kk}; + } + return; +} + +sub always_prepend +{ + my $pack = shift; + my $old = $GLOBAL_PREPEND{$pack}; + $GLOBAL_PREPEND{$pack} = shift; + $old; +} + +{ + my %LEGAL_TYPE; + BEGIN { + %LEGAL_TYPE = map {$_=>1} qw(FILE FILEHANDLE STRING ARRAY); + } + sub new { + my $pack = shift; + my %a = @_; + my $stype = uc(_param('type', %a) || "FILE"); + my $source = _param('source', %a); + my $untaint = _param('untaint', %a); + my $prepend = _param('prepend', %a); + my $alt_delim = _param('delimiters', %a); + my $broken = _param('broken', %a); + unless (defined $source) { + require Carp; + Carp::croak("Usage: $ {pack}::new(TYPE => ..., SOURCE => ...)"); + } + unless ($LEGAL_TYPE{$stype}) { + require Carp; + Carp::croak("Illegal value `$stype' for TYPE parameter"); + } + my $self = {TYPE => $stype, + PREPEND => $prepend, + UNTAINT => $untaint, + BROKEN => $broken, + (defined $alt_delim ? (DELIM => $alt_delim) : ()), + }; + # Under 5.005_03, if any of $stype, $prepend, $untaint, or $broken + # are tainted, all the others become tainted too as a result of + # sharing the expression with them. We install $source separately + # to prevent it from acquiring a spurious taint. + $self->{SOURCE} = $source; + + bless $self => $pack; + return unless $self->_acquire_data; + + $self; + } +} + +# Convert template objects of various types to type STRING, +# in which the template data is embedded in the object itself. +sub _acquire_data { + my ($self) = @_; + my $type = $self->{TYPE}; + if ($type eq 'STRING') { + # nothing necessary + } elsif ($type eq 'FILE') { + my $data = _load_text($self->{SOURCE}); + unless (defined $data) { + # _load_text already set $ERROR + return undef; + } + if ($self->{UNTAINT} && _is_clean($self->{SOURCE})) { + _unconditionally_untaint($data); + } + $self->{TYPE} = 'STRING'; + $self->{FILENAME} = $self->{SOURCE}; + $self->{SOURCE} = $data; + } elsif ($type eq 'ARRAY') { + $self->{TYPE} = 'STRING'; + $self->{SOURCE} = join '', @{$self->{SOURCE}}; + } elsif ($type eq 'FILEHANDLE') { + $self->{TYPE} = 'STRING'; + local $/; + my $fh = $self->{SOURCE}; + my $data = <$fh>; # Extra assignment avoids bug in Solaris perl5.00[45]. + if ($self->{UNTAINT}) { + _unconditionally_untaint($data); + } + $self->{SOURCE} = $data; + } else { + # This should have been caught long ago, so it represents a + # drastic `can't-happen' sort of failure + my $pack = ref $self; + die "Can only acquire data for $pack objects of subtype STRING, but this is $type; aborting"; + } + $self->{DATA_ACQUIRED} = 1; +} + +sub source { + my ($self) = @_; + $self->_acquire_data unless $self->{DATA_ACQUIRED}; + return $self->{SOURCE}; +} + +sub set_source_data { + my ($self, $newdata) = @_; + $self->{SOURCE} = $newdata; + $self->{DATA_ACQUIRED} = 1; + $self->{TYPE} = 'STRING'; + 1; +} + +sub compile { + my $self = shift; + + return 1 if $self->{TYPE} eq 'PREPARSED'; + + return undef unless $self->_acquire_data; + unless ($self->{TYPE} eq 'STRING') { + my $pack = ref $self; + # This should have been caught long ago, so it represents a + # drastic `can't-happen' sort of failure + die "Can only compile $pack objects of subtype STRING, but this is $self->{TYPE}; aborting"; + } + + my @tokens; + my $delim_pats = shift() || $self->{DELIM}; + + + + my ($t_open, $t_close) = ('{', '}'); + my $DELIM; # Regex matches a delimiter if $delim_pats + if (defined $delim_pats) { + ($t_open, $t_close) = @$delim_pats; + $DELIM = "(?:(?:\Q$t_open\E)|(?:\Q$t_close\E))"; + @tokens = split /($DELIM|\n)/, $self->{SOURCE}; + } else { + @tokens = split /(\\\\(?=\\*[{}])|\\[{}]|[{}\n])/, $self->{SOURCE}; + } + my $state = 'TEXT'; + my $depth = 0; + my $lineno = 1; + my @content; + my $cur_item = ''; + my $prog_start; + while (@tokens) { + my $t = shift @tokens; + next if $t eq ''; + if ($t eq $t_open) { # Brace or other opening delimiter + if ($depth == 0) { + push @content, [$state, $cur_item, $lineno] if $cur_item ne ''; + $cur_item = ''; + $state = 'PROG'; + $prog_start = $lineno; + } else { + $cur_item .= $t; + } + $depth++; + } elsif ($t eq $t_close) { # Brace or other closing delimiter + $depth--; + if ($depth < 0) { + $ERROR = "Unmatched close brace at line $lineno"; + return undef; + } elsif ($depth == 0) { + push @content, [$state, $cur_item, $prog_start] if $cur_item ne ''; + $state = 'TEXT'; + $cur_item = ''; + } else { + $cur_item .= $t; + } + } elsif (!$delim_pats && $t eq '\\\\') { # precedes \\\..\\\{ or \\\..\\\} + $cur_item .= '\\'; + } elsif (!$delim_pats && $t =~ /^\\([{}])$/) { # Escaped (literal) brace? + $cur_item .= $1; + } elsif ($t eq "\n") { # Newline + $lineno++; + $cur_item .= $t; + } else { # Anything else + $cur_item .= $t; + } + } + + if ($state eq 'PROG') { + $ERROR = "End of data inside program text that began at line $prog_start"; + return undef; + } elsif ($state eq 'TEXT') { + push @content, [$state, $cur_item, $lineno] if $cur_item ne ''; + } else { + die "Can't happen error #1"; + } + + $self->{TYPE} = 'PREPARSED'; + $self->{SOURCE} = \@content; + 1; +} + +sub prepend_text { + my ($self) = @_; + my $t = $self->{PREPEND}; + unless (defined $t) { + $t = $GLOBAL_PREPEND{ref $self}; + unless (defined $t) { + $t = $GLOBAL_PREPEND{'Text::Template'}; + } + } + $self->{PREPEND} = $_[1] if $#_ >= 1; + return $t; +} + +sub fill_in { + my $fi_self = shift; + my %fi_a = @_; + + unless ($fi_self->{TYPE} eq 'PREPARSED') { + my $delims = _param('delimiters', %fi_a); + my @delim_arg = (defined $delims ? ($delims) : ()); + $fi_self->compile(@delim_arg) + or return undef; + } + + my $fi_varhash = _param('hash', %fi_a); + my $fi_package = _param('package', %fi_a) ; + my $fi_broken = + _param('broken', %fi_a) || $fi_self->{BROKEN} || \&_default_broken; + my $fi_broken_arg = _param('broken_arg', %fi_a) || []; + my $fi_safe = _param('safe', %fi_a); + my $fi_ofh = _param('output', %fi_a); + my $fi_eval_package; + my $fi_scrub_package = 0; + my $fi_filename = _param('filename') || $fi_self->{FILENAME} || 'template'; + + my $fi_prepend = _param('prepend', %fi_a); + unless (defined $fi_prepend) { + $fi_prepend = $fi_self->prepend_text; + } + + if (defined $fi_safe) { + $fi_eval_package = 'main'; + } elsif (defined $fi_package) { + $fi_eval_package = $fi_package; + } elsif (defined $fi_varhash) { + $fi_eval_package = _gensym(); + $fi_scrub_package = 1; + } else { + $fi_eval_package = caller; + } + + my $fi_install_package; + if (defined $fi_varhash) { + if (defined $fi_package) { + $fi_install_package = $fi_package; + } elsif (defined $fi_safe) { + $fi_install_package = $fi_safe->root; + } else { + $fi_install_package = $fi_eval_package; # The gensymmed one + } + _install_hash($fi_varhash => $fi_install_package); + } + + if (defined $fi_package && defined $fi_safe) { + no strict 'refs'; + # Big fat magic here: Fix it so that the user-specified package + # is the default one available in the safe compartment. + *{$fi_safe->root . '::'} = \%{$fi_package . '::'}; # LOD + } + + my $fi_r = ''; + my $fi_item; + foreach $fi_item (@{$fi_self->{SOURCE}}) { + my ($fi_type, $fi_text, $fi_lineno) = @$fi_item; + if ($fi_type eq 'TEXT') { + $fi_self->append_text_to_output( + text => $fi_text, + handle => $fi_ofh, + out => \$fi_r, + type => $fi_type, + ); + } elsif ($fi_type eq 'PROG') { + no strict; + my $fi_lcomment = "#line $fi_lineno $fi_filename"; + my $fi_progtext = + "package $fi_eval_package; $fi_prepend;\n$fi_lcomment\n$fi_text;"; + my $fi_res; + my $fi_eval_err = ''; + if ($fi_safe) { + $fi_safe->reval(q{undef $OUT}); + $fi_res = $fi_safe->reval($fi_progtext); + $fi_eval_err = $@; + my $OUT = $fi_safe->reval('$OUT'); + $fi_res = $OUT if defined $OUT; + } else { + my $OUT; + $fi_res = eval $fi_progtext; + $fi_eval_err = $@; + $fi_res = $OUT if defined $OUT; + } + + # If the value of the filled-in text really was undef, + # change it to an explicit empty string to avoid undefined + # value warnings later. + $fi_res = '' unless defined $fi_res; + + if ($fi_eval_err) { + $fi_res = $fi_broken->(text => $fi_text, + error => $fi_eval_err, + lineno => $fi_lineno, + arg => $fi_broken_arg, + ); + if (defined $fi_res) { + $fi_self->append_text_to_output( + text => $fi_res, + handle => $fi_ofh, + out => \$fi_r, + type => $fi_type, + ); + } else { + return $fi_res; # Undefined means abort processing + } + } else { + $fi_self->append_text_to_output( + text => $fi_res, + handle => $fi_ofh, + out => \$fi_r, + type => $fi_type, + ); + } + } else { + die "Can't happen error #2"; + } + } + + _scrubpkg($fi_eval_package) if $fi_scrub_package; + defined $fi_ofh ? 1 : $fi_r; +} + +sub append_text_to_output { + my ($self, %arg) = @_; + + if (defined $arg{handle}) { + print { $arg{handle} } $arg{text}; + } else { + ${ $arg{out} } .= $arg{text}; + } + + return; +} + +sub fill_this_in { + my $pack = shift; + my $text = shift; + my $templ = $pack->new(TYPE => 'STRING', SOURCE => $text, @_) + or return undef; + $templ->compile or return undef; + my $result = $templ->fill_in(@_); + $result; +} + +sub fill_in_string { + my $string = shift; + my $package = _param('package', @_); + push @_, 'package' => scalar(caller) unless defined $package; + Text::Template->fill_this_in($string, @_); +} + +sub fill_in_file { + my $fn = shift; + my $templ = Text::Template->new(TYPE => 'FILE', SOURCE => $fn, @_) + or return undef; + $templ->compile or return undef; + my $text = $templ->fill_in(@_); + $text; +} + +sub _default_broken { + my %a = @_; + my $prog_text = $a{text}; + my $err = $a{error}; + my $lineno = $a{lineno}; + chomp $err; +# $err =~ s/\s+at .*//s; + "Program fragment delivered error ``$err''"; +} + +sub _load_text { + my $fn = shift; + local *F; + unless (open F, $fn) { + $ERROR = "Couldn't open file $fn: $!"; + return undef; + } + local $/; + ; +} + +sub _is_clean { + my $z; + eval { ($z = join('', @_)), eval '#' . substr($z,0,0); 1 } # LOD +} + +sub _unconditionally_untaint { + for (@_) { + ($_) = /(.*)/s; + } +} + +{ + my $seqno = 0; + sub _gensym { + __PACKAGE__ . '::GEN' . $seqno++; + } + sub _scrubpkg { + my $s = shift; + $s =~ s/^Text::Template:://; + no strict 'refs'; + my $hash = $Text::Template::{$s."::"}; + foreach my $key (keys %$hash) { + undef $hash->{$key}; + } + } +} + +# Given a hashful of variables (or a list of such hashes) +# install the variables into the specified package, +# overwriting whatever variables were there before. +sub _install_hash { + my $hashlist = shift; + my $dest = shift; + if (UNIVERSAL::isa($hashlist, 'HASH')) { + $hashlist = [$hashlist]; + } + my $hash; + foreach $hash (@$hashlist) { + my $name; + foreach $name (keys %$hash) { + my $val = $hash->{$name}; + no strict 'refs'; + local *SYM = *{"$ {dest}::$name"}; + if (! defined $val) { + delete ${"$ {dest}::"}{$name}; + } elsif (ref $val) { + *SYM = $val; + } else { + *SYM = \$val; + } + } + } +} + +sub TTerror { $ERROR } + +1; + + +=head1 NAME + +Text::Template - Expand template text with embedded Perl + +=head1 VERSION + +This file documents C version B<1.46> + +=head1 SYNOPSIS + + use Text::Template; + + + $template = Text::Template->new(TYPE => 'FILE', SOURCE => 'filename.tmpl'); + $template = Text::Template->new(TYPE => 'ARRAY', SOURCE => [ ... ] ); + $template = Text::Template->new(TYPE => 'FILEHANDLE', SOURCE => $fh ); + $template = Text::Template->new(TYPE => 'STRING', SOURCE => '...' ); + $template = Text::Template->new(PREPEND => q{use strict;}, ...); + + # Use a different template file syntax: + $template = Text::Template->new(DELIMITERS => [$open, $close], ...); + + $recipient = 'King'; + $text = $template->fill_in(); # Replaces `{$recipient}' with `King' + print $text; + + $T::recipient = 'Josh'; + $text = $template->fill_in(PACKAGE => T); + + # Pass many variables explicitly + $hash = { recipient => 'Abed-Nego', + friends => [ 'me', 'you' ], + enemies => { loathsome => 'Bill Gates', + fearsome => 'Larry Ellison' }, + }; + $text = $template->fill_in(HASH => $hash, ...); + # $recipient is Abed-Nego, + # @friends is ( 'me', 'you' ), + # %enemies is ( loathsome => ..., fearsome => ... ) + + + # Call &callback in case of programming errors in template + $text = $template->fill_in(BROKEN => \&callback, BROKEN_ARG => $ref, ...); + + # Evaluate program fragments in Safe compartment with restricted permissions + $text = $template->fill_in(SAFE => $compartment, ...); + + # Print result text instead of returning it + $success = $template->fill_in(OUTPUT => \*FILEHANDLE, ...); + + # Parse template with different template file syntax: + $text = $template->fill_in(DELIMITERS => [$open, $close], ...); + # Note that this is *faster* than using the default delimiters + + # Prepend specified perl code to each fragment before evaluating: + $text = $template->fill_in(PREPEND => q{use strict 'vars';}, ...); + + use Text::Template 'fill_in_string'; + $text = fill_in_string( < 'T', ...); + Dear {$recipient}, + Pay me at once. + Love, + G.V. + EOM + + use Text::Template 'fill_in_file'; + $text = fill_in_file($filename, ...); + + # All templates will always have `use strict vars' attached to all fragments + Text::Template->always_prepend(q{use strict 'vars';}); + +=head1 DESCRIPTION + +This is a library for generating form letters, building HTML pages, or +filling in templates generally. A `template' is a piece of text that +has little Perl programs embedded in it here and there. When you +`fill in' a template, you evaluate the little programs and replace +them with their values. + +You can store a template in a file outside your program. People can +modify the template without modifying the program. You can separate +the formatting details from the main code, and put the formatting +parts of the program into the template. That prevents code bloat and +encourages functional separation. + +=head2 Example + +Here's an example of a template, which we'll suppose is stored in the +file C: + + Dear {$title} {$lastname}, + + It has come to our attention that you are delinquent in your + {$monthname[$last_paid_month]} payment. Please remit + ${sprintf("%.2f", $amount)} immediately, or your patellae may + be needlessly endangered. + + Love, + + Mark "Vizopteryx" Dominus + + +The result of filling in this template is a string, which might look +something like this: + + Dear Mr. Gates, + + It has come to our attention that you are delinquent in your + February payment. Please remit + $392.12 immediately, or your patellae may + be needlessly endangered. + + + Love, + + Mark "Vizopteryx" Dominus + +Here is a complete program that transforms the example +template into the example result, and prints it out: + + use Text::Template; + + my $template = Text::Template->new(SOURCE => 'formletter.tmpl') + or die "Couldn't construct template: $Text::Template::ERROR"; + + my @monthname = qw(January February March April May June + July August September October November December); + my %vars = (title => 'Mr.', + firstname => 'Bill', + lastname => 'Gates', + last_paid_month => 1, # February + amount => 392.12, + monthname => \@monthname, + ); + + my $result = $template->fill_in(HASH => \%vars); + + if (defined $result) { print $result } + else { die "Couldn't fill in template: $Text::Template::ERROR" } + + +=head2 Philosophy + +When people make a template module like this one, they almost always +start by inventing a special syntax for substitutions. For example, +they build it so that a string like C<%%VAR%%> is replaced with the +value of C<$VAR>. Then they realize the need extra formatting, so +they put in some special syntax for formatting. Then they need a +loop, so they invent a loop syntax. Pretty soon they have a new +little template language. + +This approach has two problems: First, their little language is +crippled. If you need to do something the author hasn't thought of, +you lose. Second: Who wants to learn another language? You already +know Perl, so why not use it? + +C templates are programmed in I. You embed Perl +code in your template, with C<{> at the beginning and C<}> at the end. +If you want a variable interpolated, you write it the way you would in +Perl. If you need to make a loop, you can use any of the Perl loop +constructions. All the Perl built-in functions are available. + +=head1 Details + +=head2 Template Parsing + +The C module scans the template source. An open brace +C<{> begins a program fragment, which continues until the matching +close brace C<}>. When the template is filled in, the program +fragments are evaluated, and each one is replaced with the resulting +value to yield the text that is returned. + +A backslash C<\> in front of a brace (or another backslash that is in +front of a brace) escapes its special meaning. The result of filling +out this template: + + \{ The sum of 1 and 2 is {1+2} \} + +is + + { The sum of 1 and 2 is 3 } + +If you have an unmatched brace, C will return a +failure code and a warning about where the problem is. Backslashes +that do not precede a brace are passed through unchanged. If you have +a template like this: + + { "String that ends in a newline.\n" } + +The backslash inside the string is passed through to Perl unchanged, +so the C<\n> really does turn into a newline. See the note at the end +for details about the way backslashes work. Backslash processing is +I done when you specify alternative delimiters with the +C option. (See L<"Alternative Delimiters">, below.) + +Each program fragment should be a sequence of Perl statements, which +are evaluated the usual way. The result of the last statement +executed will be evaluted in scalar context; the result of this +statement is a string, which is interpolated into the template in +place of the program fragment itself. + +The fragments are evaluated in order, and side effects from earlier +fragments will persist into later fragments: + + {$x = @things; ''}The Lord High Chamberlain has gotten {$x} + things for me this year. + { $diff = $x - 17; + $more = 'more' + if ($diff == 0) { + $diff = 'no'; + } elsif ($diff < 0) { + $more = 'fewer'; + } + ''; + } + That is {$diff} {$more} than he gave me last year. + +The value of C<$x> set in the first line will persist into the next +fragment that begins on the third line, and the values of C<$diff> and +C<$more> set in the second fragment will persist and be interpolated +into the last line. The output will look something like this: + + The Lord High Chamberlain has gotten 42 + things for me this year. + + That is 25 more than he gave me last year. + +That is all the syntax there is. + +=head2 The C<$OUT> variable + +There is one special trick you can play in a template. Here is the +motivation for it: Suppose you are going to pass an array, C<@items>, +into the template, and you want the template to generate a bulleted +list with a header, like this: + + Here is a list of the things I have got for you since 1907: + * Ivory + * Apes + * Peacocks + * ... + +One way to do it is with a template like this: + + Here is a list of the things I have got for you since 1907: + { my $blist = ''; + foreach $i (@items) { + $blist .= qq{ * $i\n}; + } + $blist; + } + +Here we construct the list in a variable called C<$blist>, which we +return at the end. This is a little cumbersome. There is a shortcut. + +Inside of templates, there is a special variable called C<$OUT>. +Anything you append to this variable will appear in the output of the +template. Also, if you use C<$OUT> in a program fragment, the normal +behavior, of replacing the fragment with its return value, is +disabled; instead the fragment is replaced with the value of C<$OUT>. +This means that you can write the template above like this: + + Here is a list of the things I have got for you since 1907: + { foreach $i (@items) { + $OUT .= " * $i\n"; + } + } + +C<$OUT> is reinitialized to the empty string at the start of each +program fragment. It is private to C, so +you can't use a variable named C<$OUT> in your template without +invoking the special behavior. + +=head2 General Remarks + +All C functions return C on failure, and set the +variable C<$Text::Template::ERROR> to contain an explanation of what +went wrong. For example, if you try to create a template from a file +that does not exist, C<$Text::Template::ERROR> will contain something like: + + Couldn't open file xyz.tmpl: No such file or directory + +=head2 C + + $template = new Text::Template ( TYPE => ..., SOURCE => ... ); + +This creates and returns a new template object. C returns +C and sets C<$Text::Template::ERROR> if it can't create the +template object. C says where the template source code will +come from. C says what kind of object the source is. + +The most common type of source is a file: + + new Text::Template ( TYPE => 'FILE', SOURCE => $filename ); + +This reads the template from the specified file. The filename is +opened with the Perl C command, so it can be a pipe or anything +else that makes sense with C. + +The C can also be C, in which case the C should +be a string: + + new Text::Template ( TYPE => 'STRING', + SOURCE => "This is the actual template!" ); + +The C can be C, in which case the source should be a +reference to an array of strings. The concatenation of these strings +is the template: + + new Text::Template ( TYPE => 'ARRAY', + SOURCE => [ "This is ", "the actual", + " template!", + ] + ); + +The C can be FILEHANDLE, in which case the source should be an +open filehandle (such as you got from the C or C +packages, or a glob, or a reference to a glob). In this case +C will read the text from the filehandle up to +end-of-file, and that text is the template: + + # Read template source code from STDIN: + new Text::Template ( TYPE => 'FILEHANDLE', + SOURCE => \*STDIN ); + + +If you omit the C attribute, it's taken to be C. +C is required. If you omit it, the program will abort. + +The words C and C can be spelled any of the following ways: + + TYPE SOURCE + Type Source + type source + -TYPE -SOURCE + -Type -Source + -type -source + +Pick a style you like and stick with it. + +=over 4 + +=item C + +You may also add a C option. If this option is present, +its value should be a reference to an array of two strings. The first +string is the string that signals the beginning of each program +fragment, and the second string is the string that signals the end of +each program fragment. See L<"Alternative Delimiters">, below. + +=item C + +If your program is running in taint mode, you may have problems if +your templates are stored in files. Data read from files is +considered 'untrustworthy', and taint mode will not allow you to +evaluate the Perl code in the file. (It is afraid that a malicious +person might have tampered with the file.) + +In some environments, however, local files are trustworthy. You can +tell C that a certain file is trustworthy by supplying +C 1> in the call to C. This will tell +C to disable taint checks on template code that has +come from a file, as long as the filename itself is considered +trustworthy. It will also disable taint checks on template code that +comes from a filehandle. When used with C 'string'> or C 'array'>, it has no effect. + +See L for more complete information about tainting. + +Thanks to Steve Palincsar, Gerard Vreeswijk, and Dr. Christoph Baehr +for help with this feature. + +=item C + +This option is passed along to the C call unless it is +overridden in the arguments to C. See L feature +and using C in templates> below. + +=item C + +This option is passed along to the C call unless it is +overridden in the arguments to C. See L> below. + +=back + +=head2 C + + $template->compile() + +Loads all the template text from the template's source, parses and +compiles it. If successful, returns true; otherwise returns false and +sets C<$Text::Template::ERROR>. If the template is already compiled, +it returns true and does nothing. + +You don't usually need to invoke this function, because C +(see below) compiles the template if it isn't compiled already. + +If there is an argument to this function, it must be a reference to an +array containing alternative delimiter strings. See C<"Alternative +Delimiters">, below. + +=head2 C + + $template->fill_in(OPTIONS); + +Fills in a template. Returns the resulting text if successful. +Otherwise, returns C and sets C<$Text::Template::ERROR>. + +The I are a hash, or a list of key-value pairs. You can +write the key names in any of the six usual styles as above; this +means that where this manual says C (for example) you can +actually use any of + + PACKAGE Package package -PACKAGE -Package -package + +Pick a style you like and stick with it. The all-lowercase versions +may yield spurious warnings about + + Ambiguous use of package => resolved to "package" + +so you might like to avoid them and use the capitalized versions. + +At present, there are eight legal options: C, C, +C, C, C, C, and C. + +=over 4 + +=item C + +C specifies the name of a package in which the program +fragments should be evaluated. The default is to use the package from +which C was called. For example, consider this template: + + The value of the variable x is {$x}. + +If you use C<$template-Efill_in(PACKAGE =E 'R')> , then the C<$x> in +the template is actually replaced with the value of C<$R::x>. If you +omit the C option, C<$x> will be replaced with the value of +the C<$x> variable in the package that actually called C. + +You should almost always use C. If you don't, and your +template makes changes to variables, those changes will be propagated +back into the main program. Evaluating the template in a private +package helps prevent this. The template can still modify variables +in your program if it wants to, but it will have to do so explicitly. +See the section at the end on `Security'. + +Here's an example of using C: + + Your Royal Highness, + + Enclosed please find a list of things I have gotten + for you since 1907: + + { foreach $item (@items) { + $item_no++; + $OUT .= " $item_no. \u$item\n"; + } + } + + Signed, + Lord High Chamberlain + +We want to pass in an array which will be assigned to the array +C<@items>. Here's how to do that: + + + @items = ('ivory', 'apes', 'peacocks', ); + $template->fill_in(); + +This is not very safe. The reason this isn't as safe is that if you +had a variable named C<$item_no> in scope in your program at the point +you called C, its value would be clobbered by the act of +filling out the template. The problem is the same as if you had +written a subroutine that used those variables in the same way that +the template does. (C<$OUT> is special in templates and is always +safe.) + +One solution to this is to make the C<$item_no> variable private to the +template by declaring it with C. If the template does this, you +are safe. + +But if you use the C option, you will probably be safe even +if the template does I declare its variables with C: + + @Q::items = ('ivory', 'apes', 'peacocks', ); + $template->fill_in(PACKAGE => 'Q'); + +In this case the template will clobber the variable C<$Q::item_no>, +which is not related to the one your program was using. + +Templates cannot affect variables in the main program that are +declared with C, unless you give the template references to those +variables. + +=item C + +You may not want to put the template variables into a package. +Packages can be hard to manage: You can't copy them, for example. +C provides an alternative. + +The value for C should be a reference to a hash that maps +variable names to values. For example, + + $template->fill_in(HASH => { recipient => "The King", + items => ['gold', 'frankincense', 'myrrh'], + object => \$self, + }); + +will fill out the template and use C<"The King"> as the value of +C<$recipient> and the list of items as the value of C<@items>. Note +that we pass an array reference, but inside the template it appears as +an array. In general, anything other than a simple string or number +should be passed by reference. + +We also want to pass an object, which is in C<$self>; note that we +pass a reference to the object, C<\$self> instead. Since we've passed +a reference to a scalar, inside the template the object appears as +C<$object>. + +The full details of how it works are a little involved, so you might +want to skip to the next section. + +Suppose the key in the hash is I and the value is I. + +=over 4 + +=item * + +If the I is C, then any variables named C<$key>, +C<@key>, C<%key>, etc., are undefined. + +=item * + +If the I is a string or a number, then C<$key> is set to that +value in the template. + +=item * + +For anything else, you must pass a reference. + +If the I is a reference to an array, then C<@key> is set to +that array. If the I is a reference to a hash, then C<%key> is +set to that hash. Similarly if I is any other kind of +reference. This means that + + var => "foo" + +and + + var => \"foo" + +have almost exactly the same effect. (The difference is that in the +former case, the value is copied, and in the latter case it is +aliased.) + +=item * + +In particular, if you want the template to get an object or any kind, +you must pass a reference to it: + + $template->fill_in(HASH => { database_handle => \$dbh, ... }); + +If you do this, the template will have a variable C<$database_handle> +which is the database handle object. If you leave out the C<\>, the +template will have a hash C<%database_handle>, which exposes the +internal structure of the database handle object; you don't want that. + +=back + +Normally, the way this works is by allocating a private package, +loading all the variables into the package, and then filling out the +template as if you had specified that package. A new package is +allocated each time. However, if you I use the C +option, C loads the variables into the package you +specified, and they stay there after the call returns. Subsequent +calls to C that use the same package will pick up the values +you loaded in. + +If the argument of C is a reference to an array instead of a +reference to a hash, then the array should contain a list of hashes +whose contents are loaded into the template package one after the +other. You can use this feature if you want to combine several sets +of variables. For example, one set of variables might be the defaults +for a fill-in form, and the second set might be the user inputs, which +override the defaults when they are present: + + $template->fill_in(HASH => [\%defaults, \%user_input]); + +You can also use this to set two variables with the same name: + + $template->fill_in(HASH => [{ v => "The King" }, + { v => [1,2,3] }, + ] + ); + +This sets C<$v> to C<"The King"> and C<@v> to C<(1,2,3)>. + +=item C + +If any of the program fragments fails to compile or aborts for any +reason, and you have set the C option to a function reference, +C will invoke the function. This function is called +the I function>. The C function will tell +C what to do next. + +If the C function returns C, C will +immediately abort processing the template and return the text that it +has accumulated so far. If your function does this, it should set a +flag that you can examine after C returns so that you can +tell whether there was a premature return or not. + +If the C function returns any other value, that value will be +interpolated into the template as if that value had been the return +value of the program fragment to begin with. For example, if the +C function returns an error string, the error string will be +interpolated into the output of the template in place of the program +fragment that cased the error. + +If you don't specify a C function, C supplies +a default one that returns something like + + Program fragment delivered error ``Illegal division by 0 at + template line 37'' + +(Note that the format of this message has changed slightly since +version 1.31.) The return value of the C function is +interpolated into the template at the place the error occurred, so +that this template: + + (3+4)*5 = { 3+4)*5 } + +yields this result: + + (3+4)*5 = Program fragment delivered error ``syntax error at template line 1'' + +If you specify a value for the C attribute, it should be a +reference to a function that C can call instead of the +default function. + +C will pass a hash to the C function. +The hash will have at least these three members: + +=over 4 + +=item C + +The source code of the program fragment that failed + +=item C + +The text of the error message (C<$@>) generated by eval. + +The text has been modified to omit the trailing newline and to include +the name of the template file (if there was one). The line number +counts from the beginning of the template, not from the beginning of +the failed program fragment. + +=item C + +The line number of the template at which the program fragment began. + +=back + +There may also be an C member. See C, below + +=item C + +If you supply the C option to C, the value of the +option is passed to the C function whenever it is called. The +default C function ignores the C, but you can +write a custom C function that uses the C to get +more information about what went wrong. + +The C function could also use the C as a reference +to store an error message or some other information that it wants to +communicate back to the caller. For example: + + $error = ''; + + sub my_broken { + my %args = @_; + my $err_ref = $args{arg}; + ... + $$err_ref = "Some error message"; + return undef; + } + + $template->fill_in(BROKEN => \&my_broken, + BROKEN_ARG => \$error, + ); + + if ($error) { + die "It didn't work: $error"; + } + +If one of the program fragments in the template fails, it will call +the C function, C, and pass it the C, +which is a reference to C<$error>. C can store an error +message into C<$error> this way. Then the function that called +C can see if C has left an error message for it +to find, and proceed accordingly. + +=item C + +If you give C a C option, its value should be a safe +compartment object from the C package. All evaluation of +program fragments will be performed in this compartment. See L +for full details about such compartments and how to restrict the +operations that can be performed in them. + +If you use the C option with C, the package you specify +will be placed into the safe compartment and evaluation will take +place in that package as usual. + +If not, C operation is a little different from the default. +Usually, if you don't specify a package, evaluation of program +fragments occurs in the package from which the template was invoked. +But in C mode the evaluation occurs inside the safe compartment +and cannot affect the calling package. Normally, if you use C +without C, the hash variables are imported into a private, +one-use-only package. But if you use C and C together +without C, the hash variables will just be loaded into the +root namespace of the C compartment. + +=item C + +If your template is going to generate a lot of text that you are just +going to print out again anyway, you can save memory by having +C print out the text as it is generated instead of +making it into a big string and returning the string. If you supply +the C option to C, the value should be a filehandle. +The generated text will be printed to this filehandle as it is +constructed. For example: + + $template->fill_in(OUTPUT => \*STDOUT, ...); + +fills in the C<$template> as usual, but the results are immediately +printed to STDOUT. This may result in the output appearing more +quickly than it would have otherwise. + +If you use C, the return value from C is still true on +success and false on failure, but the complete text is not returned to +the caller. + +=item C + +You can have some Perl code prepended automatically to the beginning +of every program fragment. See L feature and using +C in templates> below. + +=item C + +If this option is present, its value should be a reference to a list +of two strings. The first string is the string that signals the +beginning of each program fragment, and the second string is the +string that signals the end of each program fragment. See +L<"Alternative Delimiters">, below. + +If you specify C in the call to C, they override +any delimiters you set when you created the template object with +C. + +=back + +=head1 Convenience Functions + +=head2 C + +The basic way to fill in a template is to create a template object and +then call C on it. This is useful if you want to fill in +the same template more than once. + +In some programs, this can be cumbersome. C accepts a +string, which contains the template, and a list of options, which are +passed to C as above. It constructs the template object for +you, fills it in as specified, and returns the results. It returns +C and sets C<$Text::Template::ERROR> if it couldn't generate +any results. + +An example: + + $Q::name = 'Donald'; + $Q::amount = 141.61; + $Q::part = 'hyoid bone'; + + $text = Text::Template->fill_this_in( <<'EOM', PACKAGE => Q); + Dear {$name}, + You owe me \\${sprintf('%.2f', $amount)}. + Pay or I will break your {$part}. + Love, + Grand Vizopteryx of Irkutsk. + EOM + +Notice how we included the template in-line in the program by using a +`here document' with the CE> notation. + +C is a deprecated feature. It is only here for +backwards compatibility, and may be removed in some far-future version +in C. You should use C instead. It +is described in the next section. + +=head2 C + +It is stupid that C is a class method. It should have +been just an imported function, so that you could omit the +C> in the example above. But I made the mistake +four years ago and it is too late to change it. + +C is exactly like C except that it is +not a method and you can omit the C> and just say + + print fill_in_string(<<'EOM', ...); + Dear {$name}, + ... + EOM + +To use C, you need to say + + use Text::Template 'fill_in_string'; + +at the top of your program. You should probably use +C instead of C. + +=head2 C + +If you import C, you can say + + $text = fill_in_file(filename, ...); + +The C<...> are passed to C as above. The filename is the +name of the file that contains the template you want to fill in. It +returns the result text. or C, as usual. + +If you are going to fill in the same file more than once in the same +program you should use the longer C / C sequence instead. +It will be a lot faster because it only has to read and parse the file +once. + +=head2 Including files into templates + +People always ask for this. ``Why don't you have an include +function?'' they want to know. The short answer is this is Perl, and +Perl already has an include function. If you want it, you can just put + + {qx{cat filename}} + +into your template. VoilE. + +If you don't want to use C, you can write a little four-line +function that opens a file and dumps out its contents, and call it +from the template. I wrote one for you. In the template, you can say + + {Text::Template::_load_text(filename)} + +If that is too verbose, here is a trick. Suppose the template package +that you are going to be mentioning in the C call is package +C. Then in the main program, write + + *Q::include = \&Text::Template::_load_text; + +This imports the C<_load_text> function into package C with the +name C. From then on, any template that you fill in with +package C can say + + {include(filename)} + +to insert the text from the named file at that point. If you are +using the C option instead, just put C +\&Text::Template::_load_text> into the hash instead of importing it +explicitly. + +Suppose you don't want to insert a plain text file, but rather you +want to include one template within another? Just use C +in the template itself: + + {Text::Template::fill_in_file(filename)} + +You can do the same importing trick if this is too much to type. + +=head1 Miscellaneous + +=head2 C variables + +People are frequently surprised when this doesn't work: + + my $recipient = 'The King'; + my $text = fill_in_file('formletter.tmpl'); + +The text C doesn't get into the form letter. Why not? +Because C<$recipient> is a C variable, and the whole point of +C variables is that they're private and inaccessible except in the +scope in which they're declared. The template is not part of that +scope, so the template can't see C<$recipient>. + +If that's not the behavior you want, don't use C. C means a +private variable, and in this case you don't want the variable to be +private. Put the variables into package variables in some other +package, and use the C option to C: + + $Q::recipient = $recipient; + my $text = fill_in_file('formletter.tmpl', PACKAGE => 'Q'); + + +or pass the names and values in a hash with the C option: + + my $text = fill_in_file('formletter.tmpl', HASH => { recipient => $recipient }); + +=head2 Security Matters + +All variables are evaluated in the package you specify with the +C option of C. if you use this option, and if your +templates don't do anything egregiously stupid, you won't have to +worry that evaluation of the little programs will creep out into the +rest of your program and wreck something. + +Nevertheless, there's really no way (except with C) to protect +against a template that says + + { $Important::Secret::Security::Enable = 0; + # Disable security checks in this program + } + +or + + { $/ = "ho ho ho"; # Sabotage future uses of . + # $/ is always a global variable + } + +or even + + { system("rm -rf /") } + +so B go filling in templates unless you're sure you know what's +in them. If you're worried, or you can't trust the person who wrote +the template, use the C option. + +A final warning: program fragments run a small risk of accidentally +clobbering local variables in the C function itself. These +variables all have names that begin with C<$fi_>, so if you stay away +from those names you'll be safe. (Of course, if you're a real wizard +you can tamper with them deliberately for exciting effects; this is +actually how C<$OUT> works.) I can fix this, but it will make the +package slower to do it, so I would prefer not to. If you are worried +about this, send me mail and I will show you what to do about it. + +=head2 Alternative Delimiters + +Lorenzo Valdettaro pointed out that if you are using C +to generate TeX output, the choice of braces as the program fragment +delimiters makes you suffer suffer suffer. Starting in version 1.20, +you can change the choice of delimiters to something other than curly +braces. + +In either the C call or the C call, you can specify +an alternative set of delimiters with the C option. For +example, if you would like code fragments to be delimited by C<[@--> +and C<--@]> instead of C<{> and C<}>, use + + ... DELIMITERS => [ '[@--', '--@]' ], ... + +Note that these delimiters are I, not regexes. (I +tried for regexes, but it complicates the lexical analysis too much.) +Note also that C disables the special meaning of the +backslash, so if you want to include the delimiters in the literal +text of your template file, you are out of luck---it is up to you to +choose delimiters that do not conflict with what you are doing. The +delimiter strings may still appear inside of program fragments as long +as they nest properly. This means that if for some reason you +absolutely must have a program fragment that mentions one of the +delimiters, like this: + + [@-- + print "Oh no, a delimiter: --@]\n" + --@] + +you may be able to make it work by doing this instead: + + [@-- + # Fake matching delimiter in a comment: [@-- + print "Oh no, a delimiter: --@]\n" + --@] + +It may be safer to choose delimiters that begin with a newline +character. + +Because the parsing of templates is simplified by the absence of +backslash escapes, using alternative C may speed up the +parsing process by 20-25%. This shows that my original choice of C<{> +and C<}> was very bad. + +=head2 C feature and using C in templates + +Suppose you would like to use C in your templates to detect +undeclared variables and the like. But each code fragment is a +separate lexical scope, so you have to turn on C at the top of +each and every code fragment: + + { use strict; + use vars '$foo'; + $foo = 14; + ... + } + + ... + + { # we forgot to put `use strict' here + my $result = $boo + 12; # $boo is misspelled and should be $foo + # No error is raised on `$boo' + } + +Because we didn't put C at the top of the second fragment, +it was only active in the first fragment, and we didn't get any +C checking in the second fragment. Then we mispelled C<$foo> +and the error wasn't caught. + +C version 1.22 and higher has a new feature to make +this easier. You can specify that any text at all be automatically +added to the beginning of each program fragment. + +When you make a call to C, you can specify a + + PREPEND => 'some perl statements here' + +option; the statements will be prepended to each program fragment for +that one call only. Suppose that the C call included a + + PREPEND => 'use strict;' + +option, and that the template looked like this: + + { use vars '$foo'; + $foo = 14; + ... + } + + ... + + { my $result = $boo + 12; # $boo is misspelled and should be $foo + ... + } + +The code in the second fragment would fail, because C<$boo> has not +been declared. C was implied, even though you did not +write it explicitly, because the C option added it for you +automatically. + +There are two other ways to do this. At the time you create the +template object with C, you can also supply a C option, +in which case the statements will be prepended each time you fill in +that template. If the C call has its own C option, +this overrides the one specified at the time you created the +template. Finally, you can make the class method call + + Text::Template->always_prepend('perl statements'); + +If you do this, then call calls to C for I template will +attach the perl statements to the beginning of each program fragment, +except where overridden by C options to C or C. + +=head2 Prepending in Derived Classes + +This section is technical, and you should skip it on the first few +readings. + +Normally there are three places that prepended text could come from. +It could come from the C option in the C call, from +the C option in the C call that created the template +object, or from the argument of the C call. +C looks for these three things in order and takes the +first one that it finds. + +In a subclass of C, this last possibility is +ambiguous. Suppose C is a subclass of C. Should + + Text::Template->always_prepend(...); + +affect objects in class C? The answer is that you can have it +either way. + +The C value for C is normally stored +in a hash variable named C<%GLOBAL_PREPEND> under the key +C. When C looks to see what text to +prepend, it first looks in the template object itself, and if not, it +looks in C<$GLOBAL_PREPEND{I}> where I is the class to +which the template object belongs. If it doesn't find any value, it +looks in C<$GLOBAL_PREPEND{'Text::Template'}>. This means that +objects in class C I be affected by + + Text::Template->always_prepend(...); + +I there is also a call to + + Derived->always_prepend(...); + +So when you're designing your derived class, you can arrange to have +your objects ignore C calls by simply +putting Calways_prepend('')> at the top of your module. + +Of course, there is also a final escape hatch: Templates support a +C that is used to look up the appropriate text to be +prepended at C time. Your derived class can override this +method to get an arbitrary effect. + +=head2 JavaScript + +Jennifer D. St Clair asks: + + > Most of my pages contain JavaScript and Stylesheets. + > How do I change the template identifier? + +Jennifer is worried about the braces in the JavaScript being taken as +the delimiters of the Perl program fragments. Of course, disaster +will ensue when perl tries to evaluate these as if they were Perl +programs. The best choice is to find some unambiguous delimiter +strings that you can use in your template instead of curly braces, and +then use the C option. However, if you can't do this for +some reason, there are two easy workarounds: + +1. You can put C<\> in front of C<{>, C<}>, or C<\> to remove its +special meaning. So, for example, instead of + + if (br== "n3") { + // etc. + } + +you can put + + if (br== "n3") \{ + // etc. + \} + +and it'll come out of the template engine the way you want. + +But here is another method that is probably better. To see how it +works, first consider what happens if you put this into a template: + + { 'foo' } + +Since it's in braces, it gets evaluated, and obviously, this is going +to turn into + + foo + +So now here's the trick: In Perl, C is the same as C<'...'>. +So if we wrote + + {q{foo}} + +it would turn into + + foo + +So for your JavaScript, just write + + {q{if (br== "n3") { + // etc. + }} + } + +and it'll come out as + + if (br== "n3") { + // etc. + } + +which is what you want. + + +=head2 Shut Up! + +People sometimes try to put an initialization section at the top of +their templates, like this: + + { ... + $var = 17; + } + +Then they complain because there is a C<17> at the top of the output +that they didn't want to have there. + +Remember that a program fragment is replaced with its own return +value, and that in Perl the return value of a code block is the value +of the last expression that was evaluated, which in this case is 17. +If it didn't do that, you wouldn't be able to write C<{$recipient}> +and have the recipient filled in. + +To prevent the 17 from appearing in the output is very simple: + + { ... + $var = 17; + ''; + } + +Now the last expression evaluated yields the empty string, which is +invisible. If you don't like the way this looks, use + + { ... + $var = 17; + ($SILENTLY); + } + +instead. Presumably, C<$SILENTLY> has no value, so nothing will be +interpolated. This is what is known as a `trick'. + +=head2 Compatibility + +Every effort has been made to make this module compatible with older +versions. The only known exceptions follow: + +The output format of the default C subroutine has changed +twice, most recently between versions 1.31 and 1.40. + +Starting in version 1.10, the C<$OUT> variable is arrogated for a +special meaning. If you had templates before version 1.10 that +happened to use a variable named C<$OUT>, you will have to change them +to use some other variable or all sorts of strangeness will result. + +Between versions 0.1b and 1.00 the behavior of the \ metacharacter +changed. In 0.1b, \\ was special everywhere, and the template +processor always replaced it with a single backslash before passing +the code to Perl for evaluation. The rule now is more complicated but +probably more convenient. See the section on backslash processing, +below, for a full discussion. + +=head2 Backslash Processing + +In C beta versions, the backslash was special whenever +it appeared before a brace or another backslash. That meant that +while C<{"\n"}> did indeed generate a newline, C<{"\\"}> did not +generate a backslash, because the code passed to Perl for evaluation +was C<"\"> which is a syntax error. If you wanted a backslash, you +would have had to write C<{"\\\\"}>. + +In C versions 1.00 through 1.10, there was a bug: +Backslash was special everywhere. In these versions, C<{"\n"}> +generated the letter C. + +The bug has been corrected in version 1.11, but I did not go back to +exactly the old rule, because I did not like the idea of having to +write C<{"\\\\"}> to get one backslash. The rule is now more +complicated to remember, but probably easier to use. The rule is now: +Backslashes are always passed to Perl unchanged I they occur +as part of a sequence like C<\\\\\\{> or C<\\\\\\}>. In these +contexts, they are special; C<\\> is replaced with C<\>, and C<\{> and +C<\}> signal a literal brace. + +Examples: + + \{ foo \} + +is I evaluated, because the C<\> before the braces signals that +they should be taken literally. The result in the output looks like this: + + { foo } + + +This is a syntax error: + + { "foo}" } + +because C thinks that the code ends at the first C<}>, +and then gets upset when it sees the second one. To make this work +correctly, use + + { "foo\}" } + +This passes C<"foo}"> to Perl for evaluation. Note there's no C<\> in +the evaluated code. If you really want a C<\> in the evaluated code, +use + + { "foo\\\}" } + +This passes C<"foo\}"> to Perl for evaluation. + +Starting with C version 1.20, backslash processing is +disabled if you use the C option to specify alternative +delimiter strings. + +=head2 A short note about C<$Text::Template::ERROR> + +In the past some people have fretted about `violating the package +boundary' by examining a variable inside the C +package. Don't feel this way. C<$Text::Template::ERROR> is part of +the published, official interface to this package. It is perfectly OK +to inspect this variable. The interface is not going to change. + +If it really, really bothers you, you can import a function called +C that returns the current value of the C<$ERROR> variable. +So you can say: + + use Text::Template 'TTerror'; + + my $template = new Text::Template (SOURCE => $filename); + unless ($template) { + my $err = TTerror; + die "Couldn't make template: $err; aborting"; + } + +I don't see what benefit this has over just doing this: + + use Text::Template; + + my $template = new Text::Template (SOURCE => $filename) + or die "Couldn't make template: $Text::Template::ERROR; aborting"; + +But if it makes you happy to do it that way, go ahead. + +=head2 Sticky Widgets in Template Files + +The C module provides functions for `sticky widgets', which are +form input controls that retain their values from one page to the +next. Sometimes people want to know how to include these widgets +into their template output. + +It's totally straightforward. Just call the C functions from +inside the template: + + { $q->checkbox_group(NAME => 'toppings', + LINEBREAK => true, + COLUMNS => 3, + VALUES => \@toppings, + ); + } + +=head2 Automatic preprocessing of program fragments + +It may be useful to preprocess the program fragments before they are +evaluated. See C for more details. + +=head2 Automatic postprocessing of template hunks + +It may be useful to process hunks of output before they are appended to +the result text. For this, subclass and replace the C +method. It is passed a list of pairs with these entries: + + handle - a filehandle to which to print the desired output + out - a ref to a string to which to append, to use if handle is not given + text - the text that will be appended + type - where the text came from: TEXT for literal text, PROG for code + +=head2 Author + +Mark Jason Dominus, Plover Systems + +Please send questions and other remarks about this software to +C + +You can join a very low-volume (E10 messages per year) mailing +list for announcements about this package. Send an empty note to +C to join. + +For updates, visit C. + +=head2 Support? + +This software is version 1.46. It may have bugs. Suggestions and bug +reports are always welcome. Send them to +C. (That is my address, not the address +of the mailing list. The mailing list address is a secret.) + +=head1 LICENSE + + Text::Template version 1.46 + Copyright 2013 Mark Jason Dominus + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. You may also can + redistribute it and/or modify it under the terms of the Perl + Artistic License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received copies of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +=head1 THANKS + +Many thanks to the following people for offering support, +encouragement, advice, bug reports, and all the other good stuff. + +David H. Adler / +Joel Appelbaum / +Klaus Arnhold / +AntEnio AragEo / +Kevin Atteson / +Chris.Brezil / +Mike Brodhead / +Tom Brown / +Dr. Frank Bucolo / +Tim Bunce / +Juan E. Camacho / +Itamar Almeida de Carvalho / +Joseph Cheek / +Gene Damon / +San Deng / +Bob Dougherty / +Marek Grac / +Dan Franklin / +gary at dls.net / +Todd A. Green / +Donald L. Greer Jr. / +Michelangelo Grigni / +Zac Hansen / +Tom Henry / +Jarko Hietaniemi / +Matt X. Hunter / +Robert M. Ioffe / +Daniel LaLiberte / +Reuven M. Lerner / +Trip Lilley / +Yannis Livassof / +Val Luck / +Kevin Madsen / +David Marshall / +James Mastros / +Joel Meulenberg / +Jason Moore / +Sergey Myasnikov / +Chris Nandor / +Bek Oberin / +Steve Palincsar / +Ron Pero / +Hans Persson / +Sean Roehnelt / +Jonathan Roy / +Shabbir J. Safdar / +Jennifer D. St Clair / +Uwe Schneider / +Randal L. Schwartz / +Michael G Schwern / +Yonat Sharon / +Brian C. Shensky / +Niklas Skoglund / +Tom Snee / +Fred Steinberg / +Hans Stoop / +Michael J. Suzio / +Dennis Taylor / +James H. Thompson / +Shad Todd / +Lieven Tomme / +Lorenzo Valdettaro / +Larry Virden / +Andy Wardley / +Archie Warnock / +Chris Wesley / +Matt Womer / +Andrew G Wood / +Daini Xie / +Michaely Yeung + +Special thanks to: + +=over 2 + +=item Jonathan Roy + +for telling me how to do the C support (I spent two years +worrying about it, and then Jonathan pointed out that it was trivial.) + +=item Ranjit Bhatnagar + +for demanding less verbose fragments like they have in ASP, for +helping me figure out the Right Thing, and, especially, for talking me +out of adding any new syntax. These discussions resulted in the +C<$OUT> feature. + +=back + +=head2 Bugs and Caveats + +C variables in C are still susceptible to being clobbered +by template evaluation. They all begin with C, so avoid those +names in your templates. + +The line number information will be wrong if the template's lines are +not terminated by C<"\n">. You should let me know if this is a +problem. If you do, I will fix it. + +The C<$OUT> variable has a special meaning in templates, so you cannot +use it as if it were a regular variable. + +There are not quite enough tests in the test suite. + +=cut diff --git a/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/lib/Text/Template/Preprocess.pm b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/lib/Text/Template/Preprocess.pm new file mode 100644 index 000000000..1e41037bd --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/lib/Text/Template/Preprocess.pm @@ -0,0 +1,144 @@ + +package Text::Template::Preprocess; +use Text::Template; +@ISA = qw(Text::Template); +$Text::Template::Preprocess::VERSION = 1.46; + +sub fill_in { + my $self = shift; + my (%args) = @_; + my $pp = $args{PREPROCESSOR} || $self->{PREPROCESSOR} ; + if ($pp) { + local $_ = $self->source(); +# print "# fill_in: before <$_>\n"; + &$pp; +# print "# fill_in: after <$_>\n"; + $self->set_source_data($_); + } + $self->SUPER::fill_in(@_); +} + +sub preprocessor { + my ($self, $pp) = @_; + my $old_pp = $self->{PREPROCESSOR}; + $self->{PREPROCESSOR} = $pp if @_ > 1; # OK to pass $pp=undef + $old_pp; +} + +1; + + +=head1 NAME + +Text::Template::Preprocess - Expand template text with embedded Perl + +=head1 VERSION + +This file documents C version B<1.46> + +=head1 SYNOPSIS + + use Text::Template::Preprocess; + + my $t = Text::Template::Preprocess->new(...); # identical to Text::Template + + # Fill in template, but preprocess each code fragment with pp(). + my $result = $t->fill_in(..., PREPROCESSOR => \&pp); + + my $old_pp = $t->preprocessor(\&new_pp); + +=head1 DESCRIPTION + +C provides a new C option to +C. If the C option is supplied, it must be a +reference to a preprocessor subroutine. When filling out a template, +C will use this subroutine to preprocess +the program fragment prior to evaluating the code. + +The preprocessor subroutine will be called repeatedly, once for each +program fragment. The program fragment will be in C<$_>. The +subroutine should modify the contents of C<$_> and return. +C will then execute contents of C<$_> and +insert the result into the appropriate part of the template. + +C objects also support a utility method, +C, which sets a new preprocessor for the object. This +preprocessor is used for all subsequent calls to C except +where overridden by an explicit C option. +C returns the previous default preprocessor function, +or undefined if there wasn't one. When invoked with no arguments, +C returns the object's current default preprocessor +function without changing it. + +In all other respects, C is identical to +C. + +=head1 WHY? + +One possible purpose: If your files contain a lot of JavaScript, like +this: + + + Plain text here... + { perl code } + + { more perl code } + More plain text... + +You don't want C to confuse the curly braces in the +JavaScript program with executable Perl code. One strategy: + + sub quote_scripts { + s()(q{$1})gsi; + } + +Then use C \"e_scripts>. This will transform + + + +=head1 SEE ALSO + +L + +=head1 AUTHOR + + +Mark Jason Dominus, Plover Systems + +Please send questions and other remarks about this software to +C + +You can join a very low-volume (E10 messages per year) mailing +list for announcements about this package. Send an empty note to +C to join. + +For updates, visit C. + +=head1 LICENSE + + Text::Template::Preprocess version 1.46 + Copyright 2013 Mark Jason Dominus + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. You may also can + redistribute it and/or modify it under the terms of the Perl + Artistic License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received copies of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +=cut + diff --git a/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/00-version.t b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/00-version.t new file mode 100644 index 000000000..5f9560f89 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/00-version.t @@ -0,0 +1,11 @@ +#!perl + +use Text::Template; +print "1..1\n"; + +if ($Text::Template::VERSION == 1.46) { + print "ok 1\n"; +} else { + print "not ok 1\n"; +} + diff --git a/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/01-basic.t b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/01-basic.t new file mode 100644 index 000000000..be43390c6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/01-basic.t @@ -0,0 +1,266 @@ +#!perl +# +# Tests of basic, essential functionality +# + +use Text::Template; +$X::v = $Y::v = 0; # Suppress `var used only once' + +print "1..31\n"; + +$n=1; + +$template_1 = < {\$v} +We will evaluate 1+1 here -> {1 + 1} +EOM + +# (1) Construct temporary template file for testing +# file operations +$TEMPFILE = "tt$$"; +open(TMP, "> $TEMPFILE") or print "not ok $n\n" && &abort("Couldn\'t write tempfile $TEMPFILE: $!"); +print TMP $template_1; +close TMP; +print "ok $n\n"; $n++; + +# (2) Build template from file +$template = new Text::Template ('type' => 'FILE', 'source' => $TEMPFILE); +if (defined($template)) { + print "ok $n\n"; +} else { + print "not ok $n $Text::Template::ERROR\n"; +} +$n++; + +# (3) Fill in template from file +$X::v = "abc"; +$resultX = < abc +We will evaluate 1+1 here -> 2 +EOM +$Y::v = "ABC"; +$resultY = < ABC +We will evaluate 1+1 here -> 2 +EOM + +$text = $template->fill_in('package' => X); +if ($text eq $resultX) { + print "ok $n\n"; +} else { + print "not ok $n\n"; +} +$n++; + +# (4) Fill in same template again +$text = $template->fill_in('package' => Y); +if ($text eq $resultY) { + print "ok $n\n"; +} else { + print "not ok $n\n"; +} +$n++; + + + +# (5) Simple test of `fill_this_in' +$text = Text::Template->fill_this_in( $template_1, 'package' => X); +if ($text eq $resultX) { + print "ok $n\n"; +} else { + print "not ok $n\n"; +} +$n++; + +# (6) test creation of template from filehandle +if (open (TMPL, "< $TEMPFILE")) { + $template = new Text::Template ('type' => 'FILEHANDLE', + 'source' => *TMPL); + if (defined($template)) { + print "ok $n\n"; + } else { + print "not ok $n $Text::Template::ERROR\n"; + } + $n++; + +# (7) test filling in of template from filehandle + $text = $template->fill_in('package' => X); + if ($text eq $resultX) { + print "ok $n\n"; + } else { + print "not ok $n\n"; + } + $n++; + +# (8) test second fill_in on same template object + $text = $template->fill_in('package' => Y); + if ($text eq $resultY) { + print "ok $n\n"; + } else { + print "not ok $n\n"; + } + $n++; + close TMPL; +} else { + print "not ok $n\n"; $n++; + print "not ok $n\n"; $n++; + print "not ok $n\n"; $n++; +} + + +# (9) test creation of template from array +$template = new Text::Template + ('type' => 'ARRAY', + 'source' => [ + 'We will put value of $v (which is "abc") here -> {$v}', + "\n", + 'We will evaluate 1+1 here -> {1+1}', + "\n", + ]); +if (defined($template)) { + print "ok $n\n"; +} else { + print "not ok $n $Text::Template::ERROR\n"; +} +$n++; + +# (10) test filling in of template from array +$text = $template->fill_in('package' => X); +if ($text eq $resultX) { + print "ok $n\n"; +} else { + print "not ok $n\n"; +} +$n++; + +# (11) test second fill_in on same array template object +$text = $template->fill_in('package' => Y); +if ($text eq $resultY) { + print "ok $n\n"; +} else { + print "not ok $n\n"; + print STDERR "$resultX\n---\n$text"; + unless (!defined($text)) { print STDERR "ERROR: $Text::Template::ERROR\n"}; +} +$n++; + + + +# (12) Make sure \ is working properly +# Test added for version 1.11 +my $tmpl = Text::Template->new(TYPE => 'STRING', + SOURCE => 'B{"\\}"}C{"\\{"}D', + ); +# This should fail if the \ are not interpreted properly. +my $text = $tmpl->fill_in(); +print +($text eq "B}C{D" ? '' : 'not '), "ok $n\n"; +$n++; + +# (13) Make sure \ is working properly +# Test added for version 1.11 +$tmpl = Text::Template->new(TYPE => 'STRING', + SOURCE => qq{A{"\t"}B}, + ); +# Symptom of old problem: ALL \ were special in templates, so +# The lexer would return (A, PROGTEXT("t"), B), and the +# result text would be AtB instead of A(tab)B. +$text = $tmpl->fill_in(); + +print +($text eq "A\tB" ? '' : 'not '), "ok $n\n"; +$n++; + +# (14-27) Make sure \ is working properly +# Test added for version 1.11 +# This is a sort of general test. +my @tests = ('{""}' => '', # (14) + '{"}"}' => undef, # (15) + '{"\\}"}' => '}', # One backslash + '{"\\\\}"}' => undef, # Two backslashes + '{"\\\\\\}"}' => '}', # Three backslashes + '{"\\\\\\\\}"}' => undef, # Four backslashes + '{"\\\\\\\\\\}"}' => '\}', # Five backslashes (20) + '{"x20"}' => 'x20', + '{"\\x20"}' => ' ', # One backslash + '{"\\\\x20"}' => '\\x20', # Two backslashes + '{"\\\\\\x20"}' => '\\ ', # Three backslashes + '{"\\\\\\\\x20"}' => '\\\\x20', # Four backslashes (25) + '{"\\\\\\\\\\x20"}' => '\\\\ ', # Five backslashes + '{"\\x20\\}"}' => ' }', # (27) + ); + +my $i; +for ($i=0; $i<@tests; $i+=2) { + my $tmpl = Text::Template->new(TYPE => 'STRING', + SOURCE => $tests[$i], + ); + my $text = $tmpl->fill_in; + my $result = $tests[$i+1]; + my $ok = (! defined $text && ! defined $result + || $text eq $result); + unless ($ok) { + print STDERR "($n) expected .$result., got .$text.\n"; + } + print +($ok ? '' : 'not '), "ok $n\n"; + $n++; +} + + +# (28-30) I discovered that you can't pass a glob ref as your filehandle. +# MJD 20010827 +# (28) test creation of template from filehandle +if (open (TMPL, "< $TEMPFILE")) { + $template = new Text::Template ('type' => 'FILEHANDLE', + 'source' => \*TMPL); + if (defined($template)) { + print "ok $n\n"; + } else { + print "not ok $n $Text::Template::ERROR\n"; + } + $n++; + +# (29) test filling in of template from filehandle + $text = $template->fill_in('package' => X); + if ($text eq $resultX) { + print "ok $n\n"; + } else { + print "not ok $n\n"; + } + $n++; + +# (30) test second fill_in on same template object + $text = $template->fill_in('package' => Y); + if ($text eq $resultY) { + print "ok $n\n"; + } else { + print "not ok $n\n"; + } + $n++; + close TMPL; +} else { + print "not ok $n\n"; $n++; + print "not ok $n\n"; $n++; + print "not ok $n\n"; $n++; +} + +# (31) Test _scrubpkg for leakiness +$Text::Template::GEN0::test = 1; +Text::Template::_scrubpkg('Text::Template::GEN0'); +if ($Text::Template::GEN0::test) { + print "not ok $n\n"; +} else { + print "ok $n\n"; +} +$n++; + + +END {unlink $TEMPFILE;} + +exit; + + + + +sub abort { + unlink $TEMPFILE; + die $_[0]; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/02-hash.t b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/02-hash.t new file mode 100644 index 000000000..29ba51a40 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/02-hash.t @@ -0,0 +1,111 @@ +#!perl +# +# test apparatus for Text::Template module +# still incomplete. + +use Text::Template; + +die "This is the test program for Text::Template version 1.46. +You are using version $Text::Template::VERSION instead. +That does not make sense.\n +Aborting" + unless $Text::Template::VERSION == 1.46; + + +print "1..12\n"; + +$n=1; + +$template = 'We will put value of $v (which is "good") here -> {$v}'; + +$v = 'oops (main)'; +$Q::v = 'oops (Q)'; + +$vars = { 'v' => \'good' }; + +# (1) Build template from string +$template = new Text::Template ('type' => 'STRING', 'source' => $template); +print +($template ? '' : 'not '), "ok $n\n"; +$n++; + +# (2) Fill in template in anonymous package +$result2 = 'We will put value of $v (which is "good") here -> good'; +$text = $template->fill_in(HASH => $vars); +print +($text eq $result2 ? '' : 'not '), "ok $n\n"; +$n++; + +# (3) Did we clobber the main variable? +print +($v eq 'oops (main)' ? '' : 'not '), "ok $n\n"; +$n++; + +# (4) Fill in same template again +$result4 = 'We will put value of $v (which is "good") here -> good'; +$text = $template->fill_in(HASH => $vars); +print +($text eq $result4 ? '' : 'not '), "ok $n\n"; +$n++; + +# (5) Now with a package +$result5 = 'We will put value of $v (which is "good") here -> good'; +$text = $template->fill_in(HASH => $vars, PACKAGE => 'Q'); +print +($text eq $result5 ? '' : 'not '), "ok $n\n"; +$n++; + +# (6) We expect to have clobbered the Q variable. +print +($Q::v eq 'good' ? '' : 'not '), "ok $n\n"; +$n++; + +# (7) Now let's try it without a package +$result7 = 'We will put value of $v (which is "good") here -> good'; +$text = $template->fill_in(HASH => $vars); +print +($text eq $result7 ? '' : 'not '), "ok $n\n"; +$n++; + +# (8-11) Now what does it do when we pass a hash with undefined values? +# Roy says it does something bad. (Added for 1.20.) +my $WARNINGS = 0; +{ + local $SIG{__WARN__} = sub {$WARNINGS++}; + local $^W = 1; # Make sure this is on for this test + $template8 = 'We will put value of $v (which is "good") here -> {defined $v ? "bad" : "good"}'; + $result8 = 'We will put value of $v (which is "good") here -> good'; + my $template = + new Text::Template ('type' => 'STRING', 'source' => $template8); + my $text = $template->fill_in(HASH => {'v' => undef}); + # (8) Did we generate a warning? + print +($WARNINGS == 0 ? '' : 'not '), "ok $n\n"; + $n++; + + # (9) Was the output correct? + print +($text eq $result8 ? '' : 'not '), "ok $n\n"; + $n++; + + # (10-11) Let's try that again, with a twist this time + $WARNINGS = 0; + $text = $template->fill_in(HASH => [{'v' => 17}, {'v' => undef}]); + # (10) Did we generate a warning? + print +($WARNINGS == 0 ? '' : 'not '), "ok $n\n"; + $n++; + + # (11) Was the output correct? + if ($] < 5.005) { + print "ok $n # skipped -- not supported before 5.005\n"; + } else { + print +($text eq $result8 ? '' : 'not '), "ok $n\n"; + } + $n++; +} + + +# (12) Now we'll test the multiple-hash option (Added for 1.20.) +$text = Text::Template::fill_in_string(q{$v: {$v}. @v: [{"@v"}].}, + HASH => [{'v' => 17}, + {'v' => ['a', 'b', 'c']}, + {'v' => \23}, + ]); +$result = q{$v: 23. @v: [a b c].}; +print +($text eq $result ? '' : 'not '), "ok $n\n"; +$n++; + + +exit; + diff --git a/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/03-out.t b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/03-out.t new file mode 100644 index 000000000..0ba65a54d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/03-out.t @@ -0,0 +1,56 @@ +#!perl +# +# test apparatus for Text::Template module +# still incomplete. +# + +use Text::Template; + +die "This is the test program for Text::Template version 1.46 +You are using version $Text::Template::VERSION instead. +That does not make sense.\n +Aborting" + unless $Text::Template::VERSION == 1.46; + +print "1..1\n"; + +$n=1; + +$template = q{ +This line should have a 3: {1+2} + +This line should have several numbers: +{ $t = ''; foreach $n (1 .. 20) { $t .= $n . ' ' } $t } +}; + +$templateOUT = q{ +This line should have a 3: { $OUT = 1+2 } + +This line should have several numbers: +{ foreach $n (1 .. 20) { $OUT .= $n . ' ' } } +}; + +# Build templates from string +$template = new Text::Template ('type' => 'STRING', 'source' => $template) + or die; +$templateOUT = new Text::Template ('type' => 'STRING', 'source' => $templateOUT) + or die; + +# Fill in templates +$text = $template->fill_in() + or die; +$textOUT = $templateOUT->fill_in() + or die; + +# (1) They should be the same +print +($text eq $textOUT ? '' : 'not '), "ok $n\n"; +$n++; + +# Missing: Test this feature in Safe compartments; +# it's a totally different code path. +# Decision: Put that into safe.t, because that file should +# be skipped when Safe.pm is unavailable. + + +exit; + diff --git a/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/04-safe.t b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/04-safe.t new file mode 100644 index 000000000..4c07121b4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/04-safe.t @@ -0,0 +1,161 @@ +#!perl +# +# test apparatus for Text::Template module +# still incomplete. + +use Text::Template; + +BEGIN { + eval "use Safe"; + if ($@) { + print "1..0\n"; + exit 0; + } +} + +die "This is the test program for Text::Template version 1.46. +You are using version $Text::Template::VERSION instead. +That does not make sense.\n +Aborting" + unless $Text::Template::VERSION == 1.46; + +print "1..16\n"; + +if ($^O eq 'MacOS') { + $BADOP = qq{}; + $FAILURE = q{}; +} else { + $BADOP = qq{kill 0}; + $FAILURE = q{Program fragment at line 1 delivered error ``kill trapped by operation mask''}; +} + +$n=1; +$v = $v = 119; + +$c = new Safe or die; + +$goodtemplate = q{This should succeed: { $v }}; +$goodoutput = q{This should succeed: 119}; + +$template1 = new Text::Template ('type' => 'STRING', 'source' => $goodtemplate) + or die; +$template2 = new Text::Template ('type' => 'STRING', 'source' => $goodtemplate) + or die; + +$text1 = $template1->fill_in(); +$text2 = $template1->fill_in(SAFE => $c); +$ERR2 = $@; +$text3 = $template2->fill_in(SAFE => $c); +$ERR3 = $@; + +# (1)(2)(3) None of these should have failed. +print +(defined $text1 ? '' : 'not '), "ok $n\n"; +$n++; +print +(defined $text2 ? '' : 'not '), "ok $n\n"; +$n++; +print +(defined $text3 ? '' : 'not '), "ok $n\n"; +$n++; + +# (4) Safe and non-safe fills of different template objects with the +# same template text should yield the same result. +# print +($text1 eq $text3 ? '' : 'not '), "ok $n\n"; +# (4) voided this test: it's not true, because the unsafe fill +# uses package main, while the safe fill uses the secret safe package. +# We could alias the secret safe package to be identical to main, +# but that wouldn't be safe. If you want the aliasing, you have to +# request it explicitly with `PACKAGE'. +print "ok $n\n"; +$n++; + +# (5) Safe and non-safe fills of the same template object +# should yield the same result. +# (5) voided this test for the same reason as #4. +# print +($text1 eq $text2 ? '' : 'not '), "ok $n\n"; +print "ok $n\n"; +$n++; + +# (6) Make sure the output was actually correct +print +($text1 eq $goodoutput ? '' : 'not '), "ok $n\n"; +$n++; + + +$badtemplate = qq{This should fail: { $BADOP; 'NOFAIL' }}; +$badnosafeoutput = q{This should fail: NOFAIL}; +$badsafeoutput = q{This should fail: Program fragment delivered error ``kill trapped by operation mask at template line 1.''}; + +$template1 = new Text::Template ('type' => 'STRING', 'source' => $badtemplate) + or die; +$template2 = new Text::Template ('type' => 'STRING', 'source' => $badtemplate) + or die; + +$text1 = $template1->fill_in(); +$text2 = $template1->fill_in(SAFE => $c); +$ERR2 = $@; +$text3 = $template2->fill_in(SAFE => $c); +$ERR3 = $@; +$text4 = $template1->fill_in(); + +# (7)(8)(9)(10) None of these should have failed. +print +(defined $text1 ? '' : 'not '), "ok $n\n"; +$n++; +print +(defined $text2 ? '' : 'not '), "ok $n\n"; +$n++; +print +(defined $text3 ? '' : 'not '), "ok $n\n"; +$n++; +print +(defined $text4 ? '' : 'not '), "ok $n\n"; +$n++; + +# (11) text1 and text4 should be the same (using safe in between +# didn't change anything.) +print +($text1 eq $text4 ? '' : 'not '), "ok $n\n"; +$n++; + +# (12) text2 and text3 should be the same (same template text in different +# objects +print +($text2 eq $text3 ? '' : 'not '), "ok $n\n"; +$n++; + +# (13) text1 should yield badnosafeoutput +print +($text1 eq $badnosafeoutput ? '' : 'not '), "ok $n\n"; +$n++; + +# (14) text2 should yield badsafeoutput +$text2 =~ s/'kill'/kill/; # 5.8.1 added quote marks around the op name +print "# expected: <$badsafeoutput>\n# got : <$text2>\n"; +print +($text2 eq $badsafeoutput ? '' : 'not '), "ok $n\n"; +$n++; + + +$template = q{{$x=1}{$x+1}}; + +$template1 = new Text::Template ('type' => 'STRING', 'source' => $template) + or die; +$template2 = new Text::Template ('type' => 'STRING', 'source' => $template) + or die; + +$text1 = $template1->fill_in(); +$text2 = $template1->fill_in(SAFE => new Safe); + +# (15) Do effects persist in safe compartments? +print +($text1 eq $text2 ? '' : 'not '), "ok $n\n"; +$n++; + +# (16) Try the BROKEN routine in safe compartments +sub my_broken { + my %a = @_; $a{error} =~ s/ at.*//s; + "OK! text:$a{text} error:$a{error} lineno:$a{lineno} arg:$a{arg}" ; +} +$templateB = new Text::Template (TYPE => 'STRING', SOURCE => '{die}') + or die; +$text1 = $templateB->fill_in(BROKEN => \&my_broken, + BROKEN_ARG => 'barg', + SAFE => new Safe, + ); +$result1 = qq{OK! text:die error:Died lineno:1 arg:barg}; +print +($text1 eq $result1 ? '' : 'not '), "ok $n\n"; +$n++; + + + +exit; + diff --git a/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/05-safe2.t b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/05-safe2.t new file mode 100644 index 000000000..03534770f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/05-safe2.t @@ -0,0 +1,105 @@ +#!perl +# +# test apparatus for Text::Template module +# still incomplete. + +use Text::Template; + +BEGIN { + eval "use Safe"; + if ($@) { + print "1..0\n"; + exit 0; + } +} + +die "This is the test program for Text::Template version 1.46. +You are using version $Text::Template::VERSION instead. +That does not make sense.\n +Aborting" + unless $Text::Template::VERSION == 1.46; + +print "1..12\n"; +$n = 1; + +$c = new Safe or die; + +# Test handling of packages and importing. +$c->reval('$P = "safe root"'); +$P = $P = 'main'; +$Q::P = $Q::P = 'Q'; + +# How to effectively test the gensymming? + +$t = new Text::Template TYPE => 'STRING', SOURCE => 'package is {$P}' + or die; + +# (1) Default behavior: Inherit from calling package, `main' in this case. +$text = $t->fill_in(); +print +($text eq 'package is main' ? '' : 'not '), "ok $n\n"; +$n++; + +# (2) When a package is specified, we should use that package instead. +$text = $t->fill_in(PACKAGE => 'Q'); +print +($text eq 'package is Q' ? '' : 'not '), "ok $n\n"; +$n++; + +# (3) When no package is specified in safe mode, we should use the +# default safe root. +$text = $t->fill_in(SAFE => $c); +print +($text eq 'package is safe root' ? '' : 'not '), "ok $n\n"; +$n++; + +# (4) When a package is specified in safe mode, we should use the +# default safe root, after aliasing to the specified package +$text = $t->fill_in(SAFE => $c, PACKAGE => Q); +print +($text eq 'package is Q' ? '' : 'not '), "ok $n\n"; +$n++; + +# Now let's see if hash vars are installed properly into safe templates +$t = new Text::Template TYPE => 'STRING', SOURCE => 'hash is {$H}' + or die; + +# (5) First in default mode +$text = $t->fill_in(HASH => {H => 'good5'} ); +print +($text eq 'hash is good5' ? '' : 'not '), "ok $n\n"; +$n++; + +# (6) Now in packages +$text = $t->fill_in(HASH => {H => 'good6'}, PACKAGE => 'Q' ); +print +($text eq 'hash is good6' ? '' : 'not '), "ok $n\n"; +$n++; + +# (7) Now in the default root of the safe compartment +$text = $t->fill_in(HASH => {H => 'good7'}, SAFE => $c ); +print +($text eq 'hash is good7' ? '' : 'not '), "ok $n\n"; +$n++; + +# (8) Now in the default root after aliasing to a package that +# got the hash stuffed in +$text = $t->fill_in(HASH => {H => 'good8'}, SAFE => $c, PACKAGE => 'Q2' ); +print +($text eq 'hash is good8' ? '' : 'not '), "ok $n\n"; +$n++; + +# Now let's make sure that none of the packages leaked on each other. +# (9) This var should NOT have been installed into the main package +print +(defined $H ? 'not ' : ''), "ok $n\n"; +$H=$H; +$n++; + +# (10) good6 was overwritten in test 7, so there's nothing to test for here. +print "ok $n\n"; +$n++; + +# (11) this value overwrote the one from test 6. +print +($Q::H eq 'good7' ? '' : 'not '), "ok $n\n"; +$Q::H = $Q::H; +$n++; + +# (12) +print +($Q2::H eq 'good8' ? '' : 'not '), "ok $n\n"; +$Q2::H = $Q2::H; +$n++; + + + diff --git a/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/06-ofh.t b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/06-ofh.t new file mode 100644 index 000000000..6865ad194 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/06-ofh.t @@ -0,0 +1,39 @@ +#!perl +# +# test apparatus for Text::Template module +# still incomplete. + +use Text::Template; + +die "This is the test program for Text::Template version 1.46. +You are using version $Text::Template::VERSION instead. +That does not make sense.\n +Aborting" + unless $Text::Template::VERSION == 1.46; + +print "1..2\n"; + +$n=1; + +$template = new Text::Template TYPE => STRING, SOURCE => q{My process ID is {$$}}; +$of = "t$$"; +END { unlink $of } +open O, "> $of" or die; + +$text = $template->fill_in(OUTPUT => \*O); + +# (1) No $text should have been constructed. Return value should be true. +print +($text eq '1' ? '' : 'not '), "ok $n\n"; +$n++; + +close O or die; +open I, "< $of" or die; +{ local $/; $t = } +close I; + +# (2) The text should have been printed to the file +print +($t eq "My process ID is $$" ? '' : 'not '), "ok $n\n"; +$n++; + +exit; + diff --git a/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/07-safe3.t b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/07-safe3.t new file mode 100644 index 000000000..5f438f614 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/07-safe3.t @@ -0,0 +1,91 @@ +#!perl +# +# test apparatus for Text::Template module + +use Text::Template; + +BEGIN { + eval "use Safe"; + if ($@) { + print "1..0\n"; + exit 0; + } +} + +die "This is the test program for Text::Template version 1.46. +You are using version $Text::Template::VERSION instead. +That does not make sense.\n +Aborting" + unless $Text::Template::VERSION == 1.46; + +print "1..3\n"; + +$n=1; + +# Test the OUT feature with safe compartments + +$template = q{ +This line should have a 3: {1+2} + +This line should have several numbers: +{ $t = ''; foreach $n (1 .. 20) { $t .= $n . ' ' } $t } +}; + +$templateOUT = q{ +This line should have a 3: { $OUT = 1+2 } + +This line should have several numbers: +{ foreach $n (1 .. 20) { $OUT .= $n . ' ' } } +}; + +$c = new Safe; + +# Build templates from string +$template = new Text::Template ('type' => 'STRING', 'source' => $template, + SAFE => $c) + or die; +$templateOUT = new Text::Template ('type' => 'STRING', 'source' => $templateOUT, + SAFE => $c) + or die; + +# Fill in templates +$text = $template->fill_in() + or die; +$textOUT = $templateOUT->fill_in() + or die; + +# (1) They should be the same +print +($text eq $textOUT ? '' : 'not '), "ok $n\n"; +$n++; + +# (2-3) "Joel Appelbaum" <000701c0ac2c$aed1d6e0$0201a8c0@prime> +# "Contrary to the documentation the $OUT variable is not always +# undefined at the start of each program fragment. The $OUT variable +# is never undefined after it is used once if you are using the SAFE +# option. The result is that every fragment after the fragment that +# $OUT was used in is replaced by the old $OUT value instead of the +# result of the fragment. This holds true even after the +# Text::Template object goes out of scope and a new one is created!" +# +# Also reported by Daini Xie. + +{ + my $template = q{{$OUT = 'x'}y{$OUT .= 'z'}}; + my $expected = "xyz"; + my $s = Safe->new; + my $o = Text::Template->new(type => 'string', + source => $template, + ); + for (1..2) { + my $r = $o->fill_in(SAFE => $s); + if ($r ne $expected) { + print "not ok $n # <$r>\n"; + } else { + print "ok $n\n"; + } + $n++; + } +} + +exit; + diff --git a/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/08-exported.t b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/08-exported.t new file mode 100644 index 000000000..ef9cfafde --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/08-exported.t @@ -0,0 +1,75 @@ +#!perl +# +# test apparatus for Text::Template module +# still incomplete. + +use Text::Template 'fill_in_file', 'fill_in_string'; + +die "This is the test program for Text::Template version 1.46. +You are using version $Text::Template::VERSION instead. +That does not make sense.\n +Aborting" + unless $Text::Template::VERSION == 1.46; + +print "1..6\n"; + +$n=1; +$Q::n = $Q::n = 119; + +# (1) Test fill_in_string +$out = fill_in_string('The value of $n is {$n}.', PACKAGE => 'Q' ); +print +($out eq 'The value of $n is 119.' ? '' : 'not '), "ok $n\n"; +$n++; + +# (2) Test fill_in_file +$TEMPFILE = "tt$$"; +open F, "> $TEMPFILE" or die "Couldn't open test file: $!; aborting"; +print F 'The value of $n is {$n}.', "\n"; +close F or die "Couldn't write test file: $!; aborting"; +$R::n = $R::n = 8128; + +$out = fill_in_file($TEMPFILE, PACKAGE => 'R'); +print +($out eq "The value of \$n is 8128.\n" ? '' : 'not '), "ok $n\n"; +$n++; + +# (3) Jonathan Roy reported this bug: +open F, "> $TEMPFILE" or die "Couldn't open test file: $!; aborting"; +print F "With a message here? [% \$var %]\n"; +close F or die "Couldn't close test file: $!; aborting"; +$out = fill_in_file($TEMPFILE, DELIMITERS => ['[%', '%]'], + HASH => { "var" => \"It is good!" }); +print +($out eq "With a message here? It is good!\n" ? '' : 'not '), "ok $n\n"; +$n++; + +# (4) It probably occurs in fill_this_in also: +$out = + Text::Template->fill_this_in("With a message here? [% \$var %]\n", + DELIMITERS => ['[%', '%]'], + HASH => { "var" => \"It is good!" }); +print +($out eq "With a message here? It is good!\n" ? '' : 'not '), "ok $n\n"; +$n++; + +# (5) This test failed in 1.25. It was supplied by Donald L. Greer Jr. +# Note that it's different from (1) in that there's no explicit +# package=> argument. +use vars qw($string $foo $r); +$string='Hello {$foo}'; +$foo="Don"; +$r = fill_in_string($string); +print (($r eq 'Hello Don' ? '' : 'not '), 'ok ', $n++, "\n"); + +# (6) This test failed in 1.25. It's a variation on (5) +package Q2; +use Text::Template 'fill_in_string'; +use vars qw($string $foo $r); +$string='Hello {$foo}'; +$foo="Don"; +$r = fill_in_string($string); +print (($r eq 'Hello Don' ? '' : 'not '), 'ok ', $main::n++, "\n"); + +package main; + +END { $TEMPFILE && unlink $TEMPFILE } + +exit; + diff --git a/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/09-error.t b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/09-error.t new file mode 100644 index 000000000..40f9fac6c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/09-error.t @@ -0,0 +1,63 @@ +#!perl +# +# test apparatus for Text::Template module +# still incomplete. + +use Text::Template; + +die "This is the test program for Text::Template version 1.46. +You are using version $Text::Template::VERSION instead. +That does not make sense.\n +Aborting" + unless $Text::Template::VERSION == 1.46; + +print "1..5\n"; +$n = 1; + +# (1-2) Missing source +eval { + Text::Template->new(); +}; +unless ($@ =~ /^\QUsage: Text::Template::new(TYPE => ..., SOURCE => ...)/) { + print STDERR $@; + print "not "; +} +print "ok $n\n"; +$n++; + +eval { + Text::Template->new(TYPE => 'FILE'); +}; +if ($@ =~ /^\QUsage: Text::Template::new(TYPE => ..., SOURCE => ...)/) { + print "ok $n\n"; +} else { + print STDERR $@; + print "not ok $n\n"; +} +$n++; + +# (3) Invalid type +eval { + Text::Template->new(TYPE => 'wlunch', SOURCE => 'fish food'); +}; +if ($@ =~ /^\QIllegal value `WLUNCH' for TYPE parameter/) { + print "ok $n\n"; +} else { + print STDERR $@; + print "not ok $n\n"; +} +$n++; + +# (4-5) File does not exist +my $o = Text::Template->new(TYPE => 'file', + SOURCE => 'this file does not exist'); +print $o ? "not ok $n\n" : "ok $n\n"; +$n++; +print defined($Text::Template::ERROR) + && $Text::Template::ERROR =~ /^Couldn't open file/ + ? "ok $n\n" : "not ok $n\n"; +$n++; + + +exit; + diff --git a/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/10-delimiters.t b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/10-delimiters.t new file mode 100644 index 000000000..f74d591cc --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/10-delimiters.t @@ -0,0 +1,99 @@ +#!perl +# +# Tests for user-specified delimiter functions +# These tests first appeared in version 1.20. + +use Text::Template; + +die "This is the test program for Text::Template version 1.46. +You are using version $Text::Template::VERSION instead. +That does not make sense.\n +Aborting" + unless $Text::Template::VERSION == 1.46; + +print "1..18\n"; +$n = 1; + +# (1) Try a simple delimiter: <<..>> +# First with the delimiters specified at object creation time +$V = $V = 119; +$template = q{The value of $V is <<$V>>.}; +$result = q{The value of $V is 119.}; +$template1 = Text::Template->new(TYPE => STRING, + SOURCE => $template, + DELIMITERS => ['<<', '>>'] + ) + or die "Couldn't construct template object: $Text::Template::ERROR; aborting"; +$text = $template1->fill_in(); +print +($text eq $result ? '' : 'not '), "ok $n\n"; +$n++; + +# (2) Now with delimiter choice deferred until fill-in time. +$template1 = Text::Template->new(TYPE => STRING, SOURCE => $template); +$text = $template1->fill_in(DELIMITERS => ['<<', '>>']); +print +($text eq $result ? '' : 'not '), "ok $n\n"; +$n++; + +# (3) Now we'll try using regex metacharacters +# First with the delimiters specified at object creation time +$template = q{The value of $V is [$V].}; +$template1 = Text::Template->new(TYPE => STRING, + SOURCE => $template, + DELIMITERS => ['[', ']'] + ) + or die "Couldn't construct template object: $Text::Template::ERROR; aborting"; +$text = $template1->fill_in(); +print +($text eq $result ? '' : 'not '), "ok $n\n"; +$n++; + +# (4) Now with delimiter choice deferred until fill-in time. +$template1 = Text::Template->new(TYPE => STRING, SOURCE => $template); +$text = $template1->fill_in(DELIMITERS => ['[', ']']); +print +($text eq $result ? '' : 'not '), "ok $n\n"; +$n++; + + + +# (5-18) Make sure \ is working properly +# (That is to say, it is ignored.) +# These tests are similar to those in 01-basic.t. +my @tests = ('{""}' => '', # (5) + + # Backslashes don't matter + '{"}"}' => undef, + '{"\\}"}' => undef, # One backslash + '{"\\\\}"}' => undef, # Two backslashes + '{"\\\\\\}"}' => undef, # Three backslashes + '{"\\\\\\\\}"}' => undef, # Four backslashes (10) + '{"\\\\\\\\\\}"}' => undef, # Five backslashes + + # Backslashes are always passed directly to Perl + '{"x20"}' => 'x20', + '{"\\x20"}' => ' ', # One backslash + '{"\\\\x20"}' => '\\x20', # Two backslashes + '{"\\\\\\x20"}' => '\\ ', # Three backslashes (15) + '{"\\\\\\\\x20"}' => '\\\\x20', # Four backslashes + '{"\\\\\\\\\\x20"}' => '\\\\ ', # Five backslashes + '{"\\x20\\}"}' => undef, # (18) + ); + +my $i; +for ($i=0; $i<@tests; $i+=2) { + my $tmpl = Text::Template->new(TYPE => 'STRING', + SOURCE => $tests[$i], + DELIMITERS => ['{', '}'], + ); + my $text = $tmpl->fill_in; + my $result = $tests[$i+1]; + my $ok = (! defined $text && ! defined $result + || $text eq $result); + unless ($ok) { + print STDERR "($n) expected .$result., got .$text.\n"; + } + print +($ok ? '' : 'not '), "ok $n\n"; + $n++; +} + + +exit; + diff --git a/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/11-prepend.t b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/11-prepend.t new file mode 100644 index 000000000..fe242e589 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/11-prepend.t @@ -0,0 +1,94 @@ +#!perl +# +# Tests for PREPEND features +# These tests first appeared in version 1.22. + +use Text::Template; + +die "This is the test program for Text::Template version 1.46 +You are using version $Text::Template::VERSION instead. +That does not make sense.\n +Aborting" + unless $Text::Template::VERSION == 1.46; + +print "1..9\n"; +my $n = 1; + +@Emptyclass1::ISA = 'Text::Template'; +@Emptyclass2::ISA = 'Text::Template'; + +my $tin = q{The value of $foo is: {$foo}}; + +Text::Template->always_prepend(q{$foo = "global"}); + +$tmpl1 = Text::Template->new(TYPE => 'STRING', + SOURCE => $tin, + ); + +$tmpl2 = Text::Template->new(TYPE => 'STRING', + SOURCE => $tin, + PREPEND => q{$foo = "template"}, + ); + +$tmpl1->compile; +$tmpl2->compile; + +$t1 = $tmpl1->fill_in(PACKAGE => 'T1'); +$t2 = $tmpl2->fill_in(PACKAGE => 'T2'); +$t3 = $tmpl2->fill_in(PREPEND => q{$foo = "fillin"}, PACKAGE => 'T3'); + +($t1 eq 'The value of $foo is: global') or print "not "; +print "ok $n\n"; $n++; +($t2 eq 'The value of $foo is: template') or print "not "; +print "ok $n\n"; $n++; +($t3 eq 'The value of $foo is: fillin') or print "not "; +print "ok $n\n"; $n++; + +Emptyclass1->always_prepend(q{$foo = 'Emptyclass global';}); +$tmpl1 = Emptyclass1->new(TYPE => 'STRING', + SOURCE => $tin, + ); + +$tmpl2 = Emptyclass1->new(TYPE => 'STRING', + SOURCE => $tin, + PREPEND => q{$foo = "template"}, + ); + +$tmpl1->compile; +$tmpl2->compile; + +$t1 = $tmpl1->fill_in(PACKAGE => 'T4'); +$t2 = $tmpl2->fill_in(PACKAGE => 'T5'); +$t3 = $tmpl2->fill_in(PREPEND => q{$foo = "fillin"}, PACKAGE => 'T6'); + +($t1 eq 'The value of $foo is: Emptyclass global') or print "not "; +print "ok $n\n"; $n++; +($t2 eq 'The value of $foo is: template') or print "not "; +print "ok $n\n"; $n++; +($t3 eq 'The value of $foo is: fillin') or print "not "; +print "ok $n\n"; $n++; + +$tmpl1 = Emptyclass2->new(TYPE => 'STRING', + SOURCE => $tin, + ); + +$tmpl2 = Emptyclass2->new(TYPE => 'STRING', + SOURCE => $tin, + PREPEND => q{$foo = "template"}, + ); + +$tmpl1->compile; +$tmpl2->compile; + +$t1 = $tmpl1->fill_in(PACKAGE => 'T4'); +$t2 = $tmpl2->fill_in(PACKAGE => 'T5'); +$t3 = $tmpl2->fill_in(PREPEND => q{$foo = "fillin"}, PACKAGE => 'T6'); + +($t1 eq 'The value of $foo is: global') or print "not "; +print "ok $n\n"; $n++; +($t2 eq 'The value of $foo is: template') or print "not "; +print "ok $n\n"; $n++; +($t3 eq 'The value of $foo is: fillin') or print "not "; +print "ok $n\n"; $n++; + + diff --git a/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/12-preprocess.t b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/12-preprocess.t new file mode 100644 index 000000000..60b6b0c65 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/12-preprocess.t @@ -0,0 +1,52 @@ +#!perl +# +# Tests for PREPROCESSOR features +# These tests first appeared in version 1.25. + +use Text::Template::Preprocess; + +die "This is the test program for Text::Template::Preprocess version 1.46. +You are using version $Text::Template::Preprocess::VERSION instead. +That does not make sense.\n +Aborting" + unless $Text::Template::Preprocess::VERSION == 1.46; + +$TMPFILE = "tt$$"; + +print "1..8\n"; +my $n = 1; + +my $py = sub { tr/x/y/ }; +my $pz = sub { tr/x/z/ }; + +my $t = 'xxx The value of $x is {$x}'; +my $outx = 'xxx The value of $x is 119'; +my $outy = 'yyy The value of $y is 23'; +my $outz = 'zzz The value of $z is 5'; +open TF, "> $TMPFILE" or die "Couldn't open test file: $!; aborting"; +print TF $t; +close TF; + +@result = ($outx, $outy, $outz, $outz); +for my $trial (1, 0) { + for my $test (0 .. 3) { + my $tmpl; + if ($trial == 0) { + $tmpl = new Text::Template::Preprocess + (TYPE => 'STRING', SOURCE => $t) or die; + } else { + open TF, "< $TMPFILE" or die "Couldn't open test file: $!; aborting"; + $tmpl = new Text::Template::Preprocess + (TYPE => 'FILEHANDLE', SOURCE => \*TF) or die; + } + $tmpl->preprocessor($py) if ($test & 1) == 1; + my @args = ((($test & 2) == 2) ? (PREPROCESSOR => $pz) : ()); + my $o = $tmpl->fill_in(@args, + HASH => {x => 119, 'y' => 23, z => 5}); +# print STDERR "$o/$result[$test]\n"; + print +(($o eq $result[$test]) ? '' : 'not '), "ok $n\n"; + $n++; + } +} + +unlink $TMPFILE; diff --git a/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/13-taint.t b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/13-taint.t new file mode 100644 index 000000000..d92a37463 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/13-taint.t @@ -0,0 +1,119 @@ +#!perl -T +# Tests for taint-mode features + +use lib 'blib/lib'; +use Text::Template; + +die "This is the test program for Text::Template version 1.46. +You are using version $Text::Template::VERSION instead. +That does not make sense.\n +Aborting" + unless $Text::Template::VERSION == 1.46; + +my $r = int(rand(10000)); +my $file = "tt$r"; + +# makes its arguments tainted +sub taint { + for (@_) { + $_ .= substr($0,0,0); # LOD + } +} + + +print "1..21\n"; + +my $n =1; +print "ok ", $n++, "\n"; + +my $template = 'The value of $n is {$n}.'; + +open T, "> $file" or die "Couldn't write temporary file $file: $!"; +print T $template, "\n"; +close T or die "Couldn't finish temporary file $file: $!"; + +sub should_fail { + my $obj = Text::Template->new(@_); + eval {$obj->fill_in()}; + if ($@) { + print "ok $n # $@\n"; + } else { + print "not ok $n # (didn't fail)\n"; + } + $n++; +} + +sub should_work { + my $obj = Text::Template->new(@_); + eval {$obj->fill_in()}; + if ($@) { + print "not ok $n # $@\n"; + } else { + print "ok $n\n"; + } + $n++; +} + +sub should_be_tainted { + if (Text::Template::_is_clean($_[0])) { + print "not ok $n\n"; $n++; return; + } + print "ok $n\n"; $n++; return; +} + +sub should_be_clean { + unless (Text::Template::_is_clean($_[0])) { + print "not ok $n\n"; $n++; return; + } + print "ok $n\n"; $n++; return; +} + +# Tainted filename should die with and without UNTAINT option +# untainted filename should die without UNTAINT option +# filehandle should die without UNTAINT option +# string and array with tainted data should die either way + +# (2)-(7) +my $tfile = $file; +taint($tfile); +should_be_tainted($tfile); +should_be_clean($file); +should_fail TYPE => 'file', SOURCE => $tfile; +should_fail TYPE => 'file', SOURCE => $tfile, UNTAINT => 1; +should_fail TYPE => 'file', SOURCE => $file; +should_work TYPE => 'file', SOURCE => $file, UNTAINT => 1; + +# (8-9) +open H, "< $file" or die "Couldn't open $file for reading: $!; aborting"; +should_fail TYPE => 'filehandle', SOURCE => \*H; +close H; +open H, "< $file" or die "Couldn't open $file for reading: $!; aborting"; +should_work TYPE => 'filehandle', SOURCE => \*H, UNTAINT => 1; +close H; + +# (10-15) +my $ttemplate = $template; +taint($ttemplate); +should_be_tainted($ttemplate); +should_be_clean($template); +should_fail TYPE => 'string', SOURCE => $ttemplate; +should_fail TYPE => 'string', SOURCE => $ttemplate, UNTAINT => 1; +should_work TYPE => 'string', SOURCE => $template; +should_work TYPE => 'string', SOURCE => $template, UNTAINT => 1; + +# (16-19) +my $array = [ $template ]; +my $tarray = [ $ttemplate ]; +should_fail TYPE => 'array', SOURCE => $tarray; +should_fail TYPE => 'array', SOURCE => $tarray, UNTAINT => 1; +should_work TYPE => 'array', SOURCE => $array; +should_work TYPE => 'array', SOURCE => $array, UNTAINT => 1; + +# (20-21) Test _unconditionally_untaint utility function +Text::Template::_unconditionally_untaint($ttemplate); +should_be_clean($ttemplate); +Text::Template::_unconditionally_untaint($tfile); +should_be_clean($tfile); + +END { unlink $file } + diff --git a/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/14-broken.t b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/14-broken.t new file mode 100644 index 000000000..d362395cf --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/external/perl/Text-Template-1.46/t/14-broken.t @@ -0,0 +1,82 @@ +#!perl +# test apparatus for Text::Template module + +use Text::Template; + +print "1..5\n"; + +$n=1; + +die "This is the test program for Text::Template version 1.46. +You are using version $Text::Template::VERSION instead. +That does not make sense.\n +Aborting" + unless $Text::Template::VERSION == 1.46; + +# (1) basic error delivery +{ my $r = Text::Template->new(TYPE => 'string', + SOURCE => '{1/0}', + )->fill_in(); + if ($r eq q{Program fragment delivered error ``Illegal division by zero at template line 1.''}) { + print "ok $n\n"; + } else { + print "not ok $n\n# $r\n"; + } + $n++; +} + +# (2) BROKEN sub called in ->new? +{ my $r = Text::Template->new(TYPE => 'string', + SOURCE => '{1/0}', + BROKEN => sub {'---'}, + )->fill_in(); + if ($r eq q{---}) { + print "ok $n\n"; + } else { + print "not ok $n\n# $r\n"; + } + $n++; +} + +# (3) BROKEN sub called in ->fill_in? +{ my $r = Text::Template->new(TYPE => 'string', + SOURCE => '{1/0}', + )->fill_in(BROKEN => sub {'---'}); + if ($r eq q{---}) { + print "ok $n\n"; + } else { + print "not ok $n\n# $r\n"; + } + $n++; +} + +# (4) BROKEN sub passed correct args when called in ->new? +{ my $r = Text::Template->new(TYPE => 'string', + SOURCE => '{1/0}', + BROKEN => sub { my %a = @_; + qq{$a{lineno},$a{error},$a{text}} + }, + )->fill_in(); + if ($r eq qq{1,Illegal division by zero at template line 1.\n,1/0}) { + print "ok $n\n"; + } else { + print "not ok $n\n# $r\n"; + } + $n++; +} + +# (5) BROKEN sub passed correct args when called in ->fill_in? +{ my $r = Text::Template->new(TYPE => 'string', + SOURCE => '{1/0}', + )->fill_in(BROKEN => + sub { my %a = @_; + qq{$a{lineno},$a{error},$a{text}} + }); + if ($r eq qq{1,Illegal division by zero at template line 1.\n,1/0}) { + print "ok $n\n"; + } else { + print "not ok $n\n# $r\n"; + } + $n++; +} + diff --git a/trunk/3rdparty/openssl-1.1-fit/external/perl/transfer/Text/Template.pm b/trunk/3rdparty/openssl-1.1-fit/external/perl/transfer/Text/Template.pm new file mode 100644 index 000000000..b21f87531 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/external/perl/transfer/Text/Template.pm @@ -0,0 +1,23 @@ +# Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# Quick transfer to the downloaded Text::Template + +package transfer::Text::Template; +$VERSION = 1.46; + +BEGIN { + use File::Spec::Functions; + use File::Basename; + use lib catdir(dirname(__FILE__), "..", "..", "Text-Template-1.46", "lib"); + # Some unpackers on VMS convert periods in directory names to underscores + use lib catdir(dirname(__FILE__), "..", "..", "Text-Template-1_46", "lib"); + use Text::Template; + shift @INC; # Takes away the effect of use lib + shift @INC; # Takes away the effect of use lib +} +1; diff --git a/trunk/3rdparty/openssl-1.1-fit/fuzz/README.md b/trunk/3rdparty/openssl-1.1-fit/fuzz/README.md new file mode 100644 index 000000000..44c73f857 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/fuzz/README.md @@ -0,0 +1,131 @@ +# I Can Haz Fuzz? + +LibFuzzer +========= + +Or, how to fuzz OpenSSL with [libfuzzer](http://llvm.org/docs/LibFuzzer.html). + +Starting from a vanilla+OpenSSH server Ubuntu install. + +Use Chrome's handy recent build of clang. Older versions may also work. + + $ sudo apt-get install git + $ mkdir git-work + $ git clone https://chromium.googlesource.com/chromium/src/tools/clang + $ clang/scripts/update.py + +You may want to git pull and re-run the update from time to time. + +Update your path: + + $ PATH=~/third_party/llvm-build/Release+Asserts/bin/:$PATH + +Get and build libFuzzer (there is a git mirror at +https://github.com/llvm-mirror/llvm/tree/master/lib/Fuzzer if you prefer): + + $ cd + $ sudo apt-get install subversion + $ mkdir svn-work + $ cd svn-work + $ svn co https://llvm.org/svn/llvm-project/compiler-rt/trunk/lib/fuzzer Fuzzer + $ cd Fuzzer + $ clang++ -c -g -O2 -std=c++11 *.cpp + $ ar r libFuzzer.a *.o + $ ranlib libFuzzer.a + +Configure for fuzzing: + + $ CC=clang ./config enable-fuzz-libfuzzer \ + --with-fuzzer-include=../../svn-work/Fuzzer \ + --with-fuzzer-lib=../../svn-work/Fuzzer/libFuzzer.a \ + -DPEDANTIC enable-asan enable-ubsan no-shared \ + -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION \ + -fsanitize-coverage=trace-pc-guard,indirect-calls,trace-cmp \ + enable-ec_nistp_64_gcc_128 -fno-sanitize=alignment enable-tls1_3 \ + enable-weak-ssl-ciphers enable-rc5 enable-md2 \ + enable-ssl3 enable-ssl3-method enable-nextprotoneg \ + --debug + $ sudo apt-get install make + $ LDCMD=clang++ make -j + $ fuzz/helper.py $FUZZER + +Where $FUZZER is one of the executables in `fuzz/`. + +If you get a crash, you should find a corresponding input file in +`fuzz/corpora/$FUZZER-crash/`. + +AFL +=== + +Configure for fuzzing: + + $ sudo apt-get install afl-clang + $ CC=afl-clang-fast ./config enable-fuzz-afl no-shared -DPEDANTIC \ + enable-tls1_3 enable-weak-ssl-ciphers enable-rc5 enable-md2 \ + enable-ssl3 enable-ssl3-method enable-nextprotoneg \ + enable-ec_nistp_64_gcc_128 -fno-sanitize=alignment \ + --debug + $ make + +The following options can also be enabled: enable-asan, enable-ubsan, enable-msan + +Run one of the fuzzers: + + $ afl-fuzz -i fuzz/corpora/$FUZZER -o fuzz/corpora/$FUZZER/out fuzz/$FUZZER + +Where $FUZZER is one of the executables in `fuzz/`. + +Reproducing issues +================== + +If a fuzzer generates a reproducible error, you can reproduce the problem using +the fuzz/*-test binaries and the file generated by the fuzzer. They binaries +don't need to be build for fuzzing, there is no need to set CC or the call +config with enable-fuzz-* or -fsanitize-coverage, but some of the other options +above might be needed. For instance the enable-asan or enable-ubsan option might +be useful to show you when the problem happens. For the client and server fuzzer +it might be needed to use -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION to +reproduce the generated random numbers. + +To reproduce the crash you can run: + + $ fuzz/$FUZZER-test $file + +Random numbers +============== + +The client and server fuzzer normally generate random numbers as part of the TLS +connection setup. This results in the coverage of the fuzzing corpus changing +depending on the random numbers. This also has an effect for coverage of the +rest of the test suite and you see the coverage change for each commit even when +no code has been modified. + +Since we want to maximize the coverage of the fuzzing corpus, the client and +server fuzzer will use predictable numbers instead of the random numbers. This +is controlled by the FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION define. + +The coverage depends on the way the numbers are generated. We don't disable any +check of hashes, but the corpus has the correct hash in it for the random +numbers that were generated. For instance the client fuzzer will always generate +the same client hello with the same random number in it, and so the server, as +emulated by the file, can be generated for that client hello. + +Coverage changes +================ + +Since the corpus depends on the default behaviour of the client and the server, +changes in what they send by default will have an impact on the coverage. The +corpus will need to be updated in that case. + +Updating the corpus +=================== + +The client and server corpus is generated with multiple config options: +- The options as documented above +- Without enable-ec_nistp_64_gcc_128 and without --debug +- With no-asm +- Using 32 bit +- A default config, plus options needed to generate the fuzzer. + +The libfuzzer merge option is used to add the additional coverage +from each config to the minimal set. diff --git a/trunk/3rdparty/openssl-1.1-fit/fuzz/asn1.c b/trunk/3rdparty/openssl-1.1-fit/fuzz/asn1.c new file mode 100644 index 000000000..fd2271bf5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/fuzz/asn1.c @@ -0,0 +1,352 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL licenses, (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * https://www.openssl.org/source/license.html + * or in the file LICENSE in the source distribution. + */ + +/* + * Fuzz ASN.1 parsing for various data structures. Specify which on the + * command line: + * + * asn1 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "fuzzer.h" + +#include "rand.inc" + +static ASN1_ITEM_EXP *item_type[] = { + ASN1_ITEM_ref(ACCESS_DESCRIPTION), +#ifndef OPENSSL_NO_RFC3779 + ASN1_ITEM_ref(ASIdentifierChoice), + ASN1_ITEM_ref(ASIdentifiers), + ASN1_ITEM_ref(ASIdOrRange), +#endif + ASN1_ITEM_ref(ASN1_ANY), + ASN1_ITEM_ref(ASN1_BIT_STRING), + ASN1_ITEM_ref(ASN1_BMPSTRING), + ASN1_ITEM_ref(ASN1_BOOLEAN), + ASN1_ITEM_ref(ASN1_ENUMERATED), + ASN1_ITEM_ref(ASN1_FBOOLEAN), + ASN1_ITEM_ref(ASN1_GENERALIZEDTIME), + ASN1_ITEM_ref(ASN1_GENERALSTRING), + ASN1_ITEM_ref(ASN1_IA5STRING), + ASN1_ITEM_ref(ASN1_INTEGER), + ASN1_ITEM_ref(ASN1_NULL), + ASN1_ITEM_ref(ASN1_OBJECT), + ASN1_ITEM_ref(ASN1_OCTET_STRING), + ASN1_ITEM_ref(ASN1_OCTET_STRING_NDEF), + ASN1_ITEM_ref(ASN1_PRINTABLE), + ASN1_ITEM_ref(ASN1_PRINTABLESTRING), + ASN1_ITEM_ref(ASN1_SEQUENCE), + ASN1_ITEM_ref(ASN1_SEQUENCE_ANY), + ASN1_ITEM_ref(ASN1_SET_ANY), + ASN1_ITEM_ref(ASN1_T61STRING), + ASN1_ITEM_ref(ASN1_TBOOLEAN), + ASN1_ITEM_ref(ASN1_TIME), + ASN1_ITEM_ref(ASN1_UNIVERSALSTRING), + ASN1_ITEM_ref(ASN1_UTCTIME), + ASN1_ITEM_ref(ASN1_UTF8STRING), + ASN1_ITEM_ref(ASN1_VISIBLESTRING), +#ifndef OPENSSL_NO_RFC3779 + ASN1_ITEM_ref(ASRange), +#endif + ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS), + ASN1_ITEM_ref(AUTHORITY_KEYID), + ASN1_ITEM_ref(BASIC_CONSTRAINTS), + ASN1_ITEM_ref(BIGNUM), + ASN1_ITEM_ref(CBIGNUM), + ASN1_ITEM_ref(CERTIFICATEPOLICIES), +#ifndef OPENSSL_NO_CMS + ASN1_ITEM_ref(CMS_ContentInfo), + ASN1_ITEM_ref(CMS_ReceiptRequest), + ASN1_ITEM_ref(CRL_DIST_POINTS), +#endif +#ifndef OPENSSL_NO_DH + ASN1_ITEM_ref(DHparams), +#endif + ASN1_ITEM_ref(DIRECTORYSTRING), + ASN1_ITEM_ref(DISPLAYTEXT), + ASN1_ITEM_ref(DIST_POINT), + ASN1_ITEM_ref(DIST_POINT_NAME), +#ifndef OPENSSL_NO_EC + ASN1_ITEM_ref(ECPARAMETERS), + ASN1_ITEM_ref(ECPKPARAMETERS), +#endif + ASN1_ITEM_ref(EDIPARTYNAME), + ASN1_ITEM_ref(EXTENDED_KEY_USAGE), + ASN1_ITEM_ref(GENERAL_NAME), + ASN1_ITEM_ref(GENERAL_NAMES), + ASN1_ITEM_ref(GENERAL_SUBTREE), +#ifndef OPENSSL_NO_RFC3779 + ASN1_ITEM_ref(IPAddressChoice), + ASN1_ITEM_ref(IPAddressFamily), + ASN1_ITEM_ref(IPAddressOrRange), + ASN1_ITEM_ref(IPAddressRange), +#endif + ASN1_ITEM_ref(ISSUING_DIST_POINT), +#if OPENSSL_API_COMPAT < 0x10200000L + ASN1_ITEM_ref(LONG), +#endif + ASN1_ITEM_ref(NAME_CONSTRAINTS), + ASN1_ITEM_ref(NETSCAPE_CERT_SEQUENCE), + ASN1_ITEM_ref(NETSCAPE_SPKAC), + ASN1_ITEM_ref(NETSCAPE_SPKI), + ASN1_ITEM_ref(NOTICEREF), +#ifndef OPENSSL_NO_OCSP + ASN1_ITEM_ref(OCSP_BASICRESP), + ASN1_ITEM_ref(OCSP_CERTID), + ASN1_ITEM_ref(OCSP_CERTSTATUS), + ASN1_ITEM_ref(OCSP_CRLID), + ASN1_ITEM_ref(OCSP_ONEREQ), + ASN1_ITEM_ref(OCSP_REQINFO), + ASN1_ITEM_ref(OCSP_REQUEST), + ASN1_ITEM_ref(OCSP_RESPBYTES), + ASN1_ITEM_ref(OCSP_RESPDATA), + ASN1_ITEM_ref(OCSP_RESPID), + ASN1_ITEM_ref(OCSP_RESPONSE), + ASN1_ITEM_ref(OCSP_REVOKEDINFO), + ASN1_ITEM_ref(OCSP_SERVICELOC), + ASN1_ITEM_ref(OCSP_SIGNATURE), + ASN1_ITEM_ref(OCSP_SINGLERESP), +#endif + ASN1_ITEM_ref(OTHERNAME), + ASN1_ITEM_ref(PBE2PARAM), + ASN1_ITEM_ref(PBEPARAM), + ASN1_ITEM_ref(PBKDF2PARAM), + ASN1_ITEM_ref(PKCS12), + ASN1_ITEM_ref(PKCS12_AUTHSAFES), + ASN1_ITEM_ref(PKCS12_BAGS), + ASN1_ITEM_ref(PKCS12_MAC_DATA), + ASN1_ITEM_ref(PKCS12_SAFEBAG), + ASN1_ITEM_ref(PKCS12_SAFEBAGS), + ASN1_ITEM_ref(PKCS7), + ASN1_ITEM_ref(PKCS7_ATTR_SIGN), + ASN1_ITEM_ref(PKCS7_ATTR_VERIFY), + ASN1_ITEM_ref(PKCS7_DIGEST), + ASN1_ITEM_ref(PKCS7_ENC_CONTENT), + ASN1_ITEM_ref(PKCS7_ENCRYPT), + ASN1_ITEM_ref(PKCS7_ENVELOPE), + ASN1_ITEM_ref(PKCS7_ISSUER_AND_SERIAL), + ASN1_ITEM_ref(PKCS7_RECIP_INFO), + ASN1_ITEM_ref(PKCS7_SIGNED), + ASN1_ITEM_ref(PKCS7_SIGN_ENVELOPE), + ASN1_ITEM_ref(PKCS7_SIGNER_INFO), + ASN1_ITEM_ref(PKCS8_PRIV_KEY_INFO), + ASN1_ITEM_ref(PKEY_USAGE_PERIOD), + ASN1_ITEM_ref(POLICY_CONSTRAINTS), + ASN1_ITEM_ref(POLICYINFO), + ASN1_ITEM_ref(POLICY_MAPPING), + ASN1_ITEM_ref(POLICY_MAPPINGS), + ASN1_ITEM_ref(POLICYQUALINFO), + ASN1_ITEM_ref(PROXY_CERT_INFO_EXTENSION), + ASN1_ITEM_ref(PROXY_POLICY), + ASN1_ITEM_ref(RSA_OAEP_PARAMS), + ASN1_ITEM_ref(RSAPrivateKey), + ASN1_ITEM_ref(RSA_PSS_PARAMS), + ASN1_ITEM_ref(RSAPublicKey), + ASN1_ITEM_ref(SXNET), + ASN1_ITEM_ref(SXNETID), + ASN1_ITEM_ref(USERNOTICE), + ASN1_ITEM_ref(X509), + ASN1_ITEM_ref(X509_ALGOR), + ASN1_ITEM_ref(X509_ALGORS), + ASN1_ITEM_ref(X509_ATTRIBUTE), + ASN1_ITEM_ref(X509_CERT_AUX), + ASN1_ITEM_ref(X509_CINF), + ASN1_ITEM_ref(X509_CRL), + ASN1_ITEM_ref(X509_CRL_INFO), + ASN1_ITEM_ref(X509_EXTENSION), + ASN1_ITEM_ref(X509_EXTENSIONS), + ASN1_ITEM_ref(X509_NAME), + ASN1_ITEM_ref(X509_NAME_ENTRY), + ASN1_ITEM_ref(X509_PUBKEY), + ASN1_ITEM_ref(X509_REQ), + ASN1_ITEM_ref(X509_REQ_INFO), + ASN1_ITEM_ref(X509_REVOKED), + ASN1_ITEM_ref(X509_SIG), + ASN1_ITEM_ref(X509_VAL), +#if OPENSSL_API_COMPAT < 0x10200000L + ASN1_ITEM_ref(ZLONG), +#endif + ASN1_ITEM_ref(INT32), + ASN1_ITEM_ref(ZINT32), + ASN1_ITEM_ref(UINT32), + ASN1_ITEM_ref(ZUINT32), + ASN1_ITEM_ref(INT64), + ASN1_ITEM_ref(ZINT64), + ASN1_ITEM_ref(UINT64), + ASN1_ITEM_ref(ZUINT64), + NULL +}; + +static ASN1_PCTX *pctx; + +#define DO_TEST(TYPE, D2I, I2D, PRINT) { \ + const unsigned char *p = buf; \ + unsigned char *der = NULL; \ + TYPE *type = D2I(NULL, &p, len); \ + \ + if (type != NULL) { \ + int len2; \ + BIO *bio = BIO_new(BIO_s_null()); \ + \ + PRINT(bio, type); \ + BIO_free(bio); \ + len2 = I2D(type, &der); \ + if (len2 != 0) {} \ + OPENSSL_free(der); \ + TYPE ## _free(type); \ + } \ +} + +#define DO_TEST_PRINT_OFFSET(TYPE, D2I, I2D, PRINT) { \ + const unsigned char *p = buf; \ + unsigned char *der = NULL; \ + TYPE *type = D2I(NULL, &p, len); \ + \ + if (type != NULL) { \ + BIO *bio = BIO_new(BIO_s_null()); \ + \ + PRINT(bio, type, 0); \ + BIO_free(bio); \ + I2D(type, &der); \ + OPENSSL_free(der); \ + TYPE ## _free(type); \ + } \ +} + +#define DO_TEST_PRINT_PCTX(TYPE, D2I, I2D, PRINT) { \ + const unsigned char *p = buf; \ + unsigned char *der = NULL; \ + TYPE *type = D2I(NULL, &p, len); \ + \ + if (type != NULL) { \ + BIO *bio = BIO_new(BIO_s_null()); \ + \ + PRINT(bio, type, 0, pctx); \ + BIO_free(bio); \ + I2D(type, &der); \ + OPENSSL_free(der); \ + TYPE ## _free(type); \ + } \ +} + + +#define DO_TEST_NO_PRINT(TYPE, D2I, I2D) { \ + const unsigned char *p = buf; \ + unsigned char *der = NULL; \ + TYPE *type = D2I(NULL, &p, len); \ + \ + if (type != NULL) { \ + BIO *bio = BIO_new(BIO_s_null()); \ + \ + BIO_free(bio); \ + I2D(type, &der); \ + OPENSSL_free(der); \ + TYPE ## _free(type); \ + } \ +} + + +int FuzzerInitialize(int *argc, char ***argv) +{ + pctx = ASN1_PCTX_new(); + ASN1_PCTX_set_flags(pctx, ASN1_PCTX_FLAGS_SHOW_ABSENT | + ASN1_PCTX_FLAGS_SHOW_SEQUENCE | ASN1_PCTX_FLAGS_SHOW_SSOF | + ASN1_PCTX_FLAGS_SHOW_TYPE | ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME); + ASN1_PCTX_set_str_flags(pctx, ASN1_STRFLGS_UTF8_CONVERT | + ASN1_STRFLGS_SHOW_TYPE | ASN1_STRFLGS_DUMP_ALL); + + OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); + OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL); + ERR_get_state(); + CRYPTO_free_ex_index(0, -1); + FuzzerSetRand(); + + return 1; +} + +int FuzzerTestOneInput(const uint8_t *buf, size_t len) +{ + int n; + + + for (n = 0; item_type[n] != NULL; ++n) { + const uint8_t *b = buf; + unsigned char *der = NULL; + const ASN1_ITEM *i = ASN1_ITEM_ptr(item_type[n]); + ASN1_VALUE *o = ASN1_item_d2i(NULL, &b, len, i); + + if (o != NULL) { + BIO *bio = BIO_new(BIO_s_null()); + + ASN1_item_print(bio, o, 4, i, pctx); + BIO_free(bio); + ASN1_item_i2d(o, &der, i); + OPENSSL_free(der); + ASN1_item_free(o, i); + } + } + +#ifndef OPENSSL_NO_TS + DO_TEST(TS_REQ, d2i_TS_REQ, i2d_TS_REQ, TS_REQ_print_bio); + DO_TEST(TS_MSG_IMPRINT, d2i_TS_MSG_IMPRINT, i2d_TS_MSG_IMPRINT, TS_MSG_IMPRINT_print_bio); + DO_TEST(TS_RESP, d2i_TS_RESP, i2d_TS_RESP, TS_RESP_print_bio); + DO_TEST(TS_STATUS_INFO, d2i_TS_STATUS_INFO, i2d_TS_STATUS_INFO, TS_STATUS_INFO_print_bio); + DO_TEST(TS_TST_INFO, d2i_TS_TST_INFO, i2d_TS_TST_INFO, TS_TST_INFO_print_bio); + DO_TEST_NO_PRINT(TS_ACCURACY, d2i_TS_ACCURACY, i2d_TS_ACCURACY); + DO_TEST_NO_PRINT(ESS_ISSUER_SERIAL, d2i_ESS_ISSUER_SERIAL, i2d_ESS_ISSUER_SERIAL); + DO_TEST_NO_PRINT(ESS_CERT_ID, d2i_ESS_CERT_ID, i2d_ESS_CERT_ID); + DO_TEST_NO_PRINT(ESS_SIGNING_CERT, d2i_ESS_SIGNING_CERT, i2d_ESS_SIGNING_CERT); +#endif +#ifndef OPENSSL_NO_DH + DO_TEST(DH, d2i_DHparams, i2d_DHparams, DHparams_print); + DO_TEST(DH, d2i_DHxparams, i2d_DHxparams, DHparams_print); +#endif +#ifndef OPENSSL_NO_DSA + DO_TEST_NO_PRINT(DSA_SIG, d2i_DSA_SIG, i2d_DSA_SIG); + DO_TEST_PRINT_OFFSET(DSA, d2i_DSAPrivateKey, i2d_DSAPrivateKey, DSA_print); + DO_TEST_PRINT_OFFSET(DSA, d2i_DSAPublicKey, i2d_DSAPublicKey, DSA_print); + DO_TEST(DSA, d2i_DSAparams, i2d_DSAparams, DSAparams_print); +#endif + DO_TEST_PRINT_OFFSET(RSA, d2i_RSAPublicKey, i2d_RSAPublicKey, RSA_print); +#ifndef OPENSSL_NO_EC + DO_TEST_PRINT_OFFSET(EC_GROUP, d2i_ECPKParameters, i2d_ECPKParameters, ECPKParameters_print); + DO_TEST_PRINT_OFFSET(EC_KEY, d2i_ECPrivateKey, i2d_ECPrivateKey, EC_KEY_print); + DO_TEST(EC_KEY, d2i_ECParameters, i2d_ECParameters, ECParameters_print); + DO_TEST_NO_PRINT(ECDSA_SIG, d2i_ECDSA_SIG, i2d_ECDSA_SIG); +#endif + DO_TEST_PRINT_PCTX(EVP_PKEY, d2i_AutoPrivateKey, i2d_PrivateKey, EVP_PKEY_print_private); + DO_TEST(SSL_SESSION, d2i_SSL_SESSION, i2d_SSL_SESSION, SSL_SESSION_print); + + ERR_clear_error(); + + return 0; +} + +void FuzzerCleanup(void) +{ + ASN1_PCTX_free(pctx); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/fuzz/asn1parse.c b/trunk/3rdparty/openssl-1.1-fit/fuzz/asn1parse.c new file mode 100644 index 000000000..cf5ef72a1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/fuzz/asn1parse.c @@ -0,0 +1,43 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL licenses, (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * https://www.openssl.org/source/license.html + * or in the file LICENSE in the source distribution. + */ + +/* + * Fuzz the parser used for dumping ASN.1 using "openssl asn1parse". + */ + +#include +#include +#include +#include +#include +#include "fuzzer.h" + +static BIO *bio_out; + +int FuzzerInitialize(int *argc, char ***argv) +{ + bio_out = BIO_new_file("/dev/null", "w"); + OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); + ERR_get_state(); + CRYPTO_free_ex_index(0, -1); + return 1; +} + +int FuzzerTestOneInput(const uint8_t *buf, size_t len) +{ + (void)ASN1_parse_dump(bio_out, buf, len, 0, 0); + ERR_clear_error(); + return 0; +} + +void FuzzerCleanup(void) +{ + BIO_free(bio_out); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/fuzz/bignum.c b/trunk/3rdparty/openssl-1.1-fit/fuzz/bignum.c new file mode 100644 index 000000000..c5136601b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/fuzz/bignum.c @@ -0,0 +1,109 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL licenses, (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * https://www.openssl.org/source/license.html + * or in the file LICENSE in the source distribution. + */ + +/* + * Confirm that a^b mod c agrees when calculated cleverly vs naively, for + * random a, b and c. + */ + +#include +#include +#include +#include "fuzzer.h" + + +int FuzzerInitialize(int *argc, char ***argv) +{ + OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); + ERR_get_state(); + + return 1; +} + +int FuzzerTestOneInput(const uint8_t *buf, size_t len) +{ + int success = 0; + size_t l1 = 0, l2 = 0, l3 = 0; + int s1 = 0, s3 = 0; + BN_CTX *ctx; + BIGNUM *b1; + BIGNUM *b2; + BIGNUM *b3; + BIGNUM *b4; + BIGNUM *b5; + + b1 = BN_new(); + b2 = BN_new(); + b3 = BN_new(); + b4 = BN_new(); + b5 = BN_new(); + ctx = BN_CTX_new(); + + /* Divide the input into three parts, using the values of the first two + * bytes to choose lengths, which generate b1, b2 and b3. Use three bits + * of the third byte to choose signs for the three numbers. + */ + if (len > 2) { + len -= 3; + l1 = (buf[0] * len) / 255; + ++buf; + l2 = (buf[0] * (len - l1)) / 255; + ++buf; + l3 = len - l1 - l2; + + s1 = buf[0] & 1; + s3 = buf[0] & 4; + ++buf; + } + OPENSSL_assert(BN_bin2bn(buf, l1, b1) == b1); + BN_set_negative(b1, s1); + OPENSSL_assert(BN_bin2bn(buf + l1, l2, b2) == b2); + OPENSSL_assert(BN_bin2bn(buf + l1 + l2, l3, b3) == b3); + BN_set_negative(b3, s3); + + /* mod 0 is undefined */ + if (BN_is_zero(b3)) { + success = 1; + goto done; + } + + OPENSSL_assert(BN_mod_exp(b4, b1, b2, b3, ctx)); + OPENSSL_assert(BN_mod_exp_simple(b5, b1, b2, b3, ctx)); + + success = BN_cmp(b4, b5) == 0; + if (!success) { + BN_print_fp(stdout, b1); + putchar('\n'); + BN_print_fp(stdout, b2); + putchar('\n'); + BN_print_fp(stdout, b3); + putchar('\n'); + BN_print_fp(stdout, b4); + putchar('\n'); + BN_print_fp(stdout, b5); + putchar('\n'); + } + + done: + OPENSSL_assert(success); + BN_free(b1); + BN_free(b2); + BN_free(b3); + BN_free(b4); + BN_free(b5); + BN_CTX_free(ctx); + ERR_clear_error(); + + return 0; +} + +void FuzzerCleanup(void) +{ +} diff --git a/trunk/3rdparty/openssl-1.1-fit/fuzz/bndiv.c b/trunk/3rdparty/openssl-1.1-fit/fuzz/bndiv.c new file mode 100644 index 000000000..e9c70bbd4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/fuzz/bndiv.c @@ -0,0 +1,131 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL licenses, (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * https://www.openssl.org/source/license.html + * or in the file LICENSE in the source distribution. + */ + +/* + * Confirm that if (d, r) = a / b, then b * d + r == a, and that sign(d) == + * sign(a), and 0 <= r <= b + */ + +#include +#include +#include +#include "fuzzer.h" + +/* 256 kB */ +#define MAX_LEN (256 * 1000) + +static BN_CTX *ctx; +static BIGNUM *b1; +static BIGNUM *b2; +static BIGNUM *b3; +static BIGNUM *b4; +static BIGNUM *b5; + +int FuzzerInitialize(int *argc, char ***argv) +{ + b1 = BN_new(); + b2 = BN_new(); + b3 = BN_new(); + b4 = BN_new(); + b5 = BN_new(); + ctx = BN_CTX_new(); + + OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); + ERR_get_state(); + + return 1; +} + +int FuzzerTestOneInput(const uint8_t *buf, size_t len) +{ + int success = 0; + size_t l1 = 0, l2 = 0; + /* s1 and s2 will be the signs for b1 and b2. */ + int s1 = 0, s2 = 0; + + /* limit the size of the input to avoid timeout */ + if (len > MAX_LEN) + len = MAX_LEN; + + /* We are going to split the buffer in two, sizes l1 and l2, giving b1 and + * b2. + */ + if (len > 0) { + --len; + /* Use first byte to divide the remaining buffer into 3Fths. I admit + * this disallows some number sizes. If it matters, better ideas are + * welcome (Ben). + */ + l1 = ((buf[0] & 0x3f) * len) / 0x3f; + s1 = buf[0] & 0x40; + s2 = buf[0] & 0x80; + ++buf; + l2 = len - l1; + } + OPENSSL_assert(BN_bin2bn(buf, l1, b1) == b1); + BN_set_negative(b1, s1); + OPENSSL_assert(BN_bin2bn(buf + l1, l2, b2) == b2); + BN_set_negative(b2, s2); + + /* divide by 0 is an error */ + if (BN_is_zero(b2)) { + success = 1; + goto done; + } + + OPENSSL_assert(BN_div(b3, b4, b1, b2, ctx)); + if (BN_is_zero(b1)) + success = BN_is_zero(b3) && BN_is_zero(b4); + else if (BN_is_negative(b1)) + success = (BN_is_negative(b3) != BN_is_negative(b2) || BN_is_zero(b3)) + && (BN_is_negative(b4) || BN_is_zero(b4)); + else + success = (BN_is_negative(b3) == BN_is_negative(b2) || BN_is_zero(b3)) + && (!BN_is_negative(b4) || BN_is_zero(b4)); + OPENSSL_assert(BN_mul(b5, b3, b2, ctx)); + OPENSSL_assert(BN_add(b5, b5, b4)); + + success = success && BN_cmp(b5, b1) == 0; + if (!success) { + BN_print_fp(stdout, b1); + putchar('\n'); + BN_print_fp(stdout, b2); + putchar('\n'); + BN_print_fp(stdout, b3); + putchar('\n'); + BN_print_fp(stdout, b4); + putchar('\n'); + BN_print_fp(stdout, b5); + putchar('\n'); + printf("%d %d %d %d %d %d %d\n", BN_is_negative(b1), + BN_is_negative(b2), + BN_is_negative(b3), BN_is_negative(b4), BN_is_zero(b4), + BN_is_negative(b3) != BN_is_negative(b2) + && (BN_is_negative(b4) || BN_is_zero(b4)), + BN_cmp(b5, b1)); + puts("----\n"); + } + + done: + OPENSSL_assert(success); + ERR_clear_error(); + + return 0; +} + +void FuzzerCleanup(void) +{ + BN_free(b1); + BN_free(b2); + BN_free(b3); + BN_free(b4); + BN_free(b5); + BN_CTX_free(ctx); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/fuzz/build.info b/trunk/3rdparty/openssl-1.1-fit/fuzz/build.info new file mode 100644 index 000000000..cde03d344 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/fuzz/build.info @@ -0,0 +1,121 @@ +{- use File::Spec::Functions; + our $ex_inc = $withargs{fuzzer_include} && + (file_name_is_absolute($withargs{fuzzer_include}) ? + $withargs{fuzzer_include} : catdir(updir(), $withargs{fuzzer_include})); + our $ex_lib = $withargs{fuzzer_lib} && + (file_name_is_absolute($withargs{fuzzer_lib}) ? + $withargs{fuzzer_lib} : catfile(updir(), $withargs{fuzzer_lib})); + "" +-} + +IF[{- !$disabled{"fuzz-afl"} || !$disabled{"fuzz-libfuzzer"} -}] + PROGRAMS_NO_INST=asn1 asn1parse bignum bndiv client conf crl server x509 + + IF[{- !$disabled{"cms"} -}] + PROGRAMS_NO_INST=cms + ENDIF + + IF[{- !$disabled{"ct"} -}] + PROGRAMS_NO_INST=ct + ENDIF + + SOURCE[asn1]=asn1.c driver.c + INCLUDE[asn1]=../include {- $ex_inc -} + DEPEND[asn1]=../libcrypto ../libssl {- $ex_lib -} + + SOURCE[asn1parse]=asn1parse.c driver.c + INCLUDE[asn1parse]=../include {- $ex_inc -} + DEPEND[asn1parse]=../libcrypto {- $ex_lib -} + + SOURCE[bignum]=bignum.c driver.c + INCLUDE[bignum]=../include {- $ex_inc -} + DEPEND[bignum]=../libcrypto {- $ex_lib -} + + SOURCE[bndiv]=bndiv.c driver.c + INCLUDE[bndiv]=../include {- $ex_inc -} + DEPEND[bndiv]=../libcrypto {- $ex_lib -} + + SOURCE[client]=client.c driver.c + INCLUDE[client]=../include {- $ex_inc -} + DEPEND[client]=../libcrypto ../libssl {- $ex_lib -} + + SOURCE[cms]=cms.c driver.c + INCLUDE[cms]=../include {- $ex_inc -} + DEPEND[cms]=../libcrypto {- $ex_lib -} + + SOURCE[conf]=conf.c driver.c + INCLUDE[conf]=../include {- $ex_inc -} + DEPEND[conf]=../libcrypto {- $ex_lib -} + + SOURCE[crl]=crl.c driver.c + INCLUDE[crl]=../include {- $ex_inc -} + DEPEND[crl]=../libcrypto {- $ex_lib -} + + SOURCE[ct]=ct.c driver.c + INCLUDE[ct]=../include {- $ex_inc -} + DEPEND[ct]=../libcrypto {- $ex_lib -} + + SOURCE[server]=server.c driver.c + INCLUDE[server]=../include {- $ex_inc -} + DEPEND[server]=../libcrypto ../libssl {- $ex_lib -} + + SOURCE[x509]=x509.c driver.c + INCLUDE[x509]=../include {- $ex_inc -} + DEPEND[x509]=../libcrypto {- $ex_lib -} +ENDIF + +IF[{- !$disabled{tests} -}] + PROGRAMS_NO_INST=asn1-test asn1parse-test bignum-test bndiv-test client-test conf-test crl-test server-test x509-test + + IF[{- !$disabled{"cms"} -}] + PROGRAMS_NO_INST=cms-test + ENDIF + + IF[{- !$disabled{"ct"} -}] + PROGRAMS_NO_INST=ct-test + ENDIF + + SOURCE[asn1-test]=asn1.c test-corpus.c + INCLUDE[asn1-test]=../include + DEPEND[asn1-test]=../libcrypto ../libssl + + SOURCE[asn1parse-test]=asn1parse.c test-corpus.c + INCLUDE[asn1parse-test]=../include + DEPEND[asn1parse-test]=../libcrypto + + SOURCE[bignum-test]=bignum.c test-corpus.c + INCLUDE[bignum-test]=../include + DEPEND[bignum-test]=../libcrypto + + SOURCE[bndiv-test]=bndiv.c test-corpus.c + INCLUDE[bndiv-test]=../include + DEPEND[bndiv-test]=../libcrypto + + SOURCE[client-test]=client.c test-corpus.c + INCLUDE[client-test]=../include + DEPEND[client-test]=../libcrypto ../libssl + + SOURCE[cms-test]=cms.c test-corpus.c + INCLUDE[cms-test]=../include + DEPEND[cms-test]=../libcrypto + + SOURCE[conf-test]=conf.c test-corpus.c + INCLUDE[conf-test]=../include + DEPEND[conf-test]=../libcrypto + + SOURCE[crl-test]=crl.c test-corpus.c + INCLUDE[crl-test]=../include + DEPEND[crl-test]=../libcrypto + + SOURCE[ct-test]=ct.c test-corpus.c + INCLUDE[ct-test]=../include + DEPEND[ct-test]=../libcrypto + + SOURCE[server-test]=server.c test-corpus.c + INCLUDE[server-test]=../include + DEPEND[server-test]=../libcrypto ../libssl + + SOURCE[x509-test]=x509.c test-corpus.c + INCLUDE[x509-test]=../include + DEPEND[x509-test]=../libcrypto +ENDIF diff --git a/trunk/3rdparty/openssl-1.1-fit/fuzz/client.c b/trunk/3rdparty/openssl-1.1-fit/fuzz/client.c new file mode 100644 index 000000000..7ce609ca6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/fuzz/client.c @@ -0,0 +1,102 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL licenses, (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * https://www.openssl.org/source/license.html + * or in the file LICENSE in the source distribution. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "fuzzer.h" + +#include "rand.inc" + +/* unused, to avoid warning. */ +static int idx; + +#define FUZZTIME 1485898104 + +#define TIME_IMPL(t) { if (t != NULL) *t = FUZZTIME; return FUZZTIME; } + +/* + * This might not work in all cases (and definitely not on Windows + * because of the way linkers are) and callees can still get the + * current time instead of the fixed time. This will just result + * in things not being fully reproducible and have a slightly + * different coverage. + */ +#if !defined(_WIN32) +time_t time(time_t *t) TIME_IMPL(t) +#endif + +int FuzzerInitialize(int *argc, char ***argv) +{ + STACK_OF(SSL_COMP) *comp_methods; + + OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS | OPENSSL_INIT_ASYNC, NULL); + OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL); + ERR_get_state(); + CRYPTO_free_ex_index(0, -1); + idx = SSL_get_ex_data_X509_STORE_CTX_idx(); + FuzzerSetRand(); + comp_methods = SSL_COMP_get_compression_methods(); + if (comp_methods != NULL) + sk_SSL_COMP_sort(comp_methods); + + return 1; +} + +int FuzzerTestOneInput(const uint8_t *buf, size_t len) +{ + SSL *client; + BIO *in; + BIO *out; + SSL_CTX *ctx; + + if (len == 0) + return 0; + + /* + * TODO: use the ossltest engine (optionally?) to disable crypto checks. + */ + + /* This only fuzzes the initial flow from the client so far. */ + ctx = SSL_CTX_new(SSLv23_method()); + + client = SSL_new(ctx); + OPENSSL_assert(SSL_set_min_proto_version(client, 0) == 1); + OPENSSL_assert(SSL_set_cipher_list(client, "ALL:eNULL:@SECLEVEL=0") == 1); + SSL_set_tlsext_host_name(client, "localhost"); + in = BIO_new(BIO_s_mem()); + out = BIO_new(BIO_s_mem()); + SSL_set_bio(client, in, out); + SSL_set_connect_state(client); + OPENSSL_assert((size_t)BIO_write(in, buf, len) == len); + if (SSL_do_handshake(client) == 1) { + /* Keep reading application data until error or EOF. */ + uint8_t tmp[1024]; + for (;;) { + if (SSL_read(client, tmp, sizeof(tmp)) <= 0) { + break; + } + } + } + SSL_free(client); + ERR_clear_error(); + SSL_CTX_free(ctx); + + return 0; +} + +void FuzzerCleanup(void) +{ +} diff --git a/trunk/3rdparty/openssl-1.1-fit/fuzz/cms.c b/trunk/3rdparty/openssl-1.1-fit/fuzz/cms.c new file mode 100644 index 000000000..959ef9365 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/fuzz/cms.c @@ -0,0 +1,55 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL licenses, (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * https://www.openssl.org/source/license.html + * or in the file LICENSE in the source distribution. + */ + +/* + * Test CMS DER parsing. + */ + +#include +#include +#include +#include "fuzzer.h" + +int FuzzerInitialize(int *argc, char ***argv) +{ + OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); + ERR_get_state(); + CRYPTO_free_ex_index(0, -1); + return 1; +} + +int FuzzerTestOneInput(const uint8_t *buf, size_t len) +{ + CMS_ContentInfo *cms; + BIO *in; + + if (len == 0) + return 0; + + in = BIO_new(BIO_s_mem()); + OPENSSL_assert((size_t)BIO_write(in, buf, len) == len); + cms = d2i_CMS_bio(in, NULL); + if (cms != NULL) { + BIO *out = BIO_new(BIO_s_null()); + + i2d_CMS_bio(out, cms); + BIO_free(out); + CMS_ContentInfo_free(cms); + } + + BIO_free(in); + ERR_clear_error(); + + return 0; +} + +void FuzzerCleanup(void) +{ +} diff --git a/trunk/3rdparty/openssl-1.1-fit/fuzz/conf.c b/trunk/3rdparty/openssl-1.1-fit/fuzz/conf.c new file mode 100644 index 000000000..87fe85709 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/fuzz/conf.c @@ -0,0 +1,48 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL licenses, (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * https://www.openssl.org/source/license.html + * or in the file LICENSE in the source distribution. + */ + +/* + * Test configuration parsing. + */ + +#include +#include +#include "fuzzer.h" + +int FuzzerInitialize(int *argc, char ***argv) +{ + OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); + ERR_get_state(); + return 1; +} + +int FuzzerTestOneInput(const uint8_t *buf, size_t len) +{ + CONF *conf; + BIO *in; + long eline; + + if (len == 0) + return 0; + + conf = NCONF_new(NULL); + in = BIO_new(BIO_s_mem()); + OPENSSL_assert((size_t)BIO_write(in, buf, len) == len); + NCONF_load_bio(conf, in, &eline); + NCONF_free(conf); + BIO_free(in); + ERR_clear_error(); + + return 0; +} + +void FuzzerCleanup(void) +{ +} diff --git a/trunk/3rdparty/openssl-1.1-fit/fuzz/crl.c b/trunk/3rdparty/openssl-1.1-fit/fuzz/crl.c new file mode 100644 index 000000000..e4b0192f0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/fuzz/crl.c @@ -0,0 +1,47 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL licenses, (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * https://www.openssl.org/source/license.html + * or in the file LICENSE in the source distribution. + */ + +#include +#include +#include +#include "fuzzer.h" + +int FuzzerInitialize(int *argc, char ***argv) +{ + OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); + ERR_get_state(); + CRYPTO_free_ex_index(0, -1); + return 1; +} + +int FuzzerTestOneInput(const uint8_t *buf, size_t len) +{ + const unsigned char *p = buf; + unsigned char *der = NULL; + + X509_CRL *crl = d2i_X509_CRL(NULL, &p, len); + if (crl != NULL) { + BIO *bio = BIO_new(BIO_s_null()); + X509_CRL_print(bio, crl); + BIO_free(bio); + + i2d_X509_CRL(crl, &der); + OPENSSL_free(der); + + X509_CRL_free(crl); + } + ERR_clear_error(); + + return 0; +} + +void FuzzerCleanup(void) +{ +} diff --git a/trunk/3rdparty/openssl-1.1-fit/fuzz/ct.c b/trunk/3rdparty/openssl-1.1-fit/fuzz/ct.c new file mode 100644 index 000000000..72dd79871 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/fuzz/ct.c @@ -0,0 +1,51 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL licenses, (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * https://www.openssl.org/source/license.html + * or in the file LICENSE in the source distribution. + */ + +/* + * Fuzz the SCT parser. + */ + +#include +#include +#include +#include "fuzzer.h" + +int FuzzerInitialize(int *argc, char ***argv) +{ + OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); + CRYPTO_free_ex_index(0, -1); + ERR_get_state(); + return 1; +} + +int FuzzerTestOneInput(const uint8_t *buf, size_t len) +{ + const uint8_t **pp = &buf; + unsigned char *der = NULL; + STACK_OF(SCT) *scts = d2i_SCT_LIST(NULL, pp, len); + if (scts != NULL) { + BIO *bio = BIO_new(BIO_s_null()); + SCT_LIST_print(scts, bio, 4, "\n", NULL); + BIO_free(bio); + + if (i2d_SCT_LIST(scts, &der)) { + /* Silence unused result warning */ + } + OPENSSL_free(der); + + SCT_LIST_free(scts); + } + ERR_clear_error(); + return 0; +} + +void FuzzerCleanup(void) +{ +} diff --git a/trunk/3rdparty/openssl-1.1-fit/fuzz/driver.c b/trunk/3rdparty/openssl-1.1-fit/fuzz/driver.c new file mode 100644 index 000000000..54d67de20 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/fuzz/driver.c @@ -0,0 +1,55 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL licenses, (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * https://www.openssl.org/source/license.html + * or in the file LICENSE in the source distribution. + */ +#include +#include +#include +#include +#include "fuzzer.h" + +#ifndef OPENSSL_NO_FUZZ_LIBFUZZER + +int LLVMFuzzerInitialize(int *argc, char ***argv); +int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len); + +int LLVMFuzzerInitialize(int *argc, char ***argv) +{ + return FuzzerInitialize(argc, argv); +} + +int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) +{ + return FuzzerTestOneInput(buf, len); +} + +#elif !defined(OPENSSL_NO_FUZZ_AFL) + +#define BUF_SIZE 65536 + +int main(int argc, char** argv) +{ + FuzzerInitialize(&argc, &argv); + + while (__AFL_LOOP(10000)) { + uint8_t *buf = malloc(BUF_SIZE); + size_t size = read(0, buf, BUF_SIZE); + + FuzzerTestOneInput(buf, size); + free(buf); + } + + FuzzerCleanup(); + return 0; +} + +#else + +#error "Unsupported fuzzer" + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/fuzz/fuzzer.h b/trunk/3rdparty/openssl-1.1-fit/fuzz/fuzzer.h new file mode 100644 index 000000000..fcc0d2527 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/fuzz/fuzzer.h @@ -0,0 +1,14 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL licenses, (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * https://www.openssl.org/source/license.html + * or in the file LICENSE in the source distribution. + */ + +int FuzzerTestOneInput(const uint8_t *buf, size_t len); +int FuzzerInitialize(int *argc, char ***argv); +void FuzzerCleanup(void); +void FuzzerSetRand(void); diff --git a/trunk/3rdparty/openssl-1.1-fit/fuzz/helper.py b/trunk/3rdparty/openssl-1.1-fit/fuzz/helper.py new file mode 100755 index 000000000..e83ea00c0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/fuzz/helper.py @@ -0,0 +1,52 @@ +#!/usr/bin/python +# +# Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +"""Fuzzing helper, creates and uses corpus/crash directories. + +fuzzer.py +""" + +import os +import subprocess +import sys + +FUZZER = sys.argv[1] + +THIS_DIR = os.path.abspath(os.path.dirname(__file__)) +CORPORA_DIR = os.path.abspath(os.path.join(THIS_DIR, "corpora")) + +FUZZER_DIR = os.path.abspath(os.path.join(CORPORA_DIR, FUZZER)) +if not os.path.isdir(FUZZER_DIR): + os.mkdir(FUZZER_DIR) + +corpora = [] + +def _create(d): + dd = os.path.abspath(os.path.join(CORPORA_DIR, d)) + if not os.path.isdir(dd): + os.mkdir(dd) + corpora.append(dd) + +def _add(d): + dd = os.path.abspath(os.path.join(CORPORA_DIR, d)) + if os.path.isdir(dd): + corpora.append(dd) + +def main(): + _create(FUZZER) + _create(FUZZER + "-crash") + _add(FUZZER + "-seed") + + cmd = ([os.path.abspath(os.path.join(THIS_DIR, FUZZER))] + sys.argv[2:] + + ["-artifact_prefix=" + corpora[1] + "/"] + corpora) + print(" ".join(cmd)) + subprocess.call(cmd) + +if __name__ == "__main__": + main() diff --git a/trunk/3rdparty/openssl-1.1-fit/fuzz/mkfuzzoids.pl b/trunk/3rdparty/openssl-1.1-fit/fuzz/mkfuzzoids.pl new file mode 100755 index 000000000..0153a031a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/fuzz/mkfuzzoids.pl @@ -0,0 +1,32 @@ +#! /usr/bin/env perl +# Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +my $obj_dat_h = $ARGV[0]; + +# Output year depends on the date on the input file and the script. +my $YEAR = [localtime([stat($0)]->[9])]->[5] + 1900; +my $iYEAR = [localtime([stat($obj_dat_h)]->[9])]->[5] + 1900; +$YEAR = $iYEAR if $iYEAR > $YEAR; + +open IN, '<', $obj_dat_h + || die "Couldn't open $obj_dat_h : $!\n"; + +while() { + s|\R$||; # Better chomp + + next unless m|^\s+((0x[0-9A-F][0-9A-F],)*)\s+/\*\s\[\s*\d+\]\s(OBJ_\w+)\s\*/$|; + + my $OID = $1; + my $OBJname = $3; + + $OID =~ s|0x|\\x|g; + $OID =~ s|,||g; + + print "$OBJname=\"$OID\"\n"; +} +close IN; diff --git a/trunk/3rdparty/openssl-1.1-fit/fuzz/oids.txt b/trunk/3rdparty/openssl-1.1-fit/fuzz/oids.txt new file mode 100644 index 000000000..fe363fd37 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/fuzz/oids.txt @@ -0,0 +1,1065 @@ +OBJ_rsadsi="\x2A\x86\x48\x86\xF7\x0D" +OBJ_pkcs="\x2A\x86\x48\x86\xF7\x0D\x01" +OBJ_md2="\x2A\x86\x48\x86\xF7\x0D\x02\x02" +OBJ_md5="\x2A\x86\x48\x86\xF7\x0D\x02\x05" +OBJ_rc4="\x2A\x86\x48\x86\xF7\x0D\x03\x04" +OBJ_rsaEncryption="\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01" +OBJ_md2WithRSAEncryption="\x2A\x86\x48\x86\xF7\x0D\x01\x01\x02" +OBJ_md5WithRSAEncryption="\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04" +OBJ_pbeWithMD2AndDES_CBC="\x2A\x86\x48\x86\xF7\x0D\x01\x05\x01" +OBJ_pbeWithMD5AndDES_CBC="\x2A\x86\x48\x86\xF7\x0D\x01\x05\x03" +OBJ_X500="\x55" +OBJ_X509="\x55\x04" +OBJ_commonName="\x55\x04\x03" +OBJ_countryName="\x55\x04\x06" +OBJ_localityName="\x55\x04\x07" +OBJ_stateOrProvinceName="\x55\x04\x08" +OBJ_organizationName="\x55\x04\x0A" +OBJ_organizationalUnitName="\x55\x04\x0B" +OBJ_rsa="\x55\x08\x01\x01" +OBJ_pkcs7="\x2A\x86\x48\x86\xF7\x0D\x01\x07" +OBJ_pkcs7_data="\x2A\x86\x48\x86\xF7\x0D\x01\x07\x01" +OBJ_pkcs7_signed="\x2A\x86\x48\x86\xF7\x0D\x01\x07\x02" +OBJ_pkcs7_enveloped="\x2A\x86\x48\x86\xF7\x0D\x01\x07\x03" +OBJ_pkcs7_signedAndEnveloped="\x2A\x86\x48\x86\xF7\x0D\x01\x07\x04" +OBJ_pkcs7_digest="\x2A\x86\x48\x86\xF7\x0D\x01\x07\x05" +OBJ_pkcs7_encrypted="\x2A\x86\x48\x86\xF7\x0D\x01\x07\x06" +OBJ_pkcs3="\x2A\x86\x48\x86\xF7\x0D\x01\x03" +OBJ_dhKeyAgreement="\x2A\x86\x48\x86\xF7\x0D\x01\x03\x01" +OBJ_des_ecb="\x2B\x0E\x03\x02\x06" +OBJ_des_cfb64="\x2B\x0E\x03\x02\x09" +OBJ_des_cbc="\x2B\x0E\x03\x02\x07" +OBJ_des_ede_ecb="\x2B\x0E\x03\x02\x11" +OBJ_idea_cbc="\x2B\x06\x01\x04\x01\x81\x3C\x07\x01\x01\x02" +OBJ_rc2_cbc="\x2A\x86\x48\x86\xF7\x0D\x03\x02" +OBJ_sha="\x2B\x0E\x03\x02\x12" +OBJ_shaWithRSAEncryption="\x2B\x0E\x03\x02\x0F" +OBJ_des_ede3_cbc="\x2A\x86\x48\x86\xF7\x0D\x03\x07" +OBJ_des_ofb64="\x2B\x0E\x03\x02\x08" +OBJ_pkcs9="\x2A\x86\x48\x86\xF7\x0D\x01\x09" +OBJ_pkcs9_emailAddress="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01" +OBJ_pkcs9_unstructuredName="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x02" +OBJ_pkcs9_contentType="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x03" +OBJ_pkcs9_messageDigest="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x04" +OBJ_pkcs9_signingTime="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x05" +OBJ_pkcs9_countersignature="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x06" +OBJ_pkcs9_challengePassword="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x07" +OBJ_pkcs9_unstructuredAddress="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x08" +OBJ_pkcs9_extCertAttributes="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x09" +OBJ_netscape="\x60\x86\x48\x01\x86\xF8\x42" +OBJ_netscape_cert_extension="\x60\x86\x48\x01\x86\xF8\x42\x01" +OBJ_netscape_data_type="\x60\x86\x48\x01\x86\xF8\x42\x02" +OBJ_sha1="\x2B\x0E\x03\x02\x1A" +OBJ_sha1WithRSAEncryption="\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05" +OBJ_dsaWithSHA="\x2B\x0E\x03\x02\x0D" +OBJ_dsa_2="\x2B\x0E\x03\x02\x0C" +OBJ_pbeWithSHA1AndRC2_CBC="\x2A\x86\x48\x86\xF7\x0D\x01\x05\x0B" +OBJ_id_pbkdf2="\x2A\x86\x48\x86\xF7\x0D\x01\x05\x0C" +OBJ_dsaWithSHA1_2="\x2B\x0E\x03\x02\x1B" +OBJ_netscape_cert_type="\x60\x86\x48\x01\x86\xF8\x42\x01\x01" +OBJ_netscape_base_url="\x60\x86\x48\x01\x86\xF8\x42\x01\x02" +OBJ_netscape_revocation_url="\x60\x86\x48\x01\x86\xF8\x42\x01\x03" +OBJ_netscape_ca_revocation_url="\x60\x86\x48\x01\x86\xF8\x42\x01\x04" +OBJ_netscape_renewal_url="\x60\x86\x48\x01\x86\xF8\x42\x01\x07" +OBJ_netscape_ca_policy_url="\x60\x86\x48\x01\x86\xF8\x42\x01\x08" +OBJ_netscape_ssl_server_name="\x60\x86\x48\x01\x86\xF8\x42\x01\x0C" +OBJ_netscape_comment="\x60\x86\x48\x01\x86\xF8\x42\x01\x0D" +OBJ_netscape_cert_sequence="\x60\x86\x48\x01\x86\xF8\x42\x02\x05" +OBJ_id_ce="\x55\x1D" +OBJ_subject_key_identifier="\x55\x1D\x0E" +OBJ_key_usage="\x55\x1D\x0F" +OBJ_private_key_usage_period="\x55\x1D\x10" +OBJ_subject_alt_name="\x55\x1D\x11" +OBJ_issuer_alt_name="\x55\x1D\x12" +OBJ_basic_constraints="\x55\x1D\x13" +OBJ_crl_number="\x55\x1D\x14" +OBJ_certificate_policies="\x55\x1D\x20" +OBJ_authority_key_identifier="\x55\x1D\x23" +OBJ_bf_cbc="\x2B\x06\x01\x04\x01\x97\x55\x01\x02" +OBJ_mdc2="\x55\x08\x03\x65" +OBJ_mdc2WithRSA="\x55\x08\x03\x64" +OBJ_givenName="\x55\x04\x2A" +OBJ_surname="\x55\x04\x04" +OBJ_initials="\x55\x04\x2B" +OBJ_uniqueIdentifier="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x2C" +OBJ_crl_distribution_points="\x55\x1D\x1F" +OBJ_md5WithRSA="\x2B\x0E\x03\x02\x03" +OBJ_serialNumber="\x55\x04\x05" +OBJ_title="\x55\x04\x0C" +OBJ_description="\x55\x04\x0D" +OBJ_cast5_cbc="\x2A\x86\x48\x86\xF6\x7D\x07\x42\x0A" +OBJ_pbeWithMD5AndCast5_CBC="\x2A\x86\x48\x86\xF6\x7D\x07\x42\x0C" +OBJ_dsaWithSHA1="\x2A\x86\x48\xCE\x38\x04\x03" +OBJ_sha1WithRSA="\x2B\x0E\x03\x02\x1D" +OBJ_dsa="\x2A\x86\x48\xCE\x38\x04\x01" +OBJ_ripemd160="\x2B\x24\x03\x02\x01" +OBJ_ripemd160WithRSA="\x2B\x24\x03\x03\x01\x02" +OBJ_rc5_cbc="\x2A\x86\x48\x86\xF7\x0D\x03\x08" +OBJ_zlib_compression="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x03\x08" +OBJ_ext_key_usage="\x55\x1D\x25" +OBJ_id_pkix="\x2B\x06\x01\x05\x05\x07" +OBJ_id_kp="\x2B\x06\x01\x05\x05\x07\x03" +OBJ_server_auth="\x2B\x06\x01\x05\x05\x07\x03\x01" +OBJ_client_auth="\x2B\x06\x01\x05\x05\x07\x03\x02" +OBJ_code_sign="\x2B\x06\x01\x05\x05\x07\x03\x03" +OBJ_email_protect="\x2B\x06\x01\x05\x05\x07\x03\x04" +OBJ_time_stamp="\x2B\x06\x01\x05\x05\x07\x03\x08" +OBJ_ms_code_ind="\x2B\x06\x01\x04\x01\x82\x37\x02\x01\x15" +OBJ_ms_code_com="\x2B\x06\x01\x04\x01\x82\x37\x02\x01\x16" +OBJ_ms_ctl_sign="\x2B\x06\x01\x04\x01\x82\x37\x0A\x03\x01" +OBJ_ms_sgc="\x2B\x06\x01\x04\x01\x82\x37\x0A\x03\x03" +OBJ_ms_efs="\x2B\x06\x01\x04\x01\x82\x37\x0A\x03\x04" +OBJ_ns_sgc="\x60\x86\x48\x01\x86\xF8\x42\x04\x01" +OBJ_delta_crl="\x55\x1D\x1B" +OBJ_crl_reason="\x55\x1D\x15" +OBJ_invalidity_date="\x55\x1D\x18" +OBJ_sxnet="\x2B\x65\x01\x04\x01" +OBJ_pbe_WithSHA1And128BitRC4="\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x01\x01" +OBJ_pbe_WithSHA1And40BitRC4="\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x01\x02" +OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC="\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x01\x03" +OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC="\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x01\x04" +OBJ_pbe_WithSHA1And128BitRC2_CBC="\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x01\x05" +OBJ_pbe_WithSHA1And40BitRC2_CBC="\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x01\x06" +OBJ_keyBag="\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x0A\x01\x01" +OBJ_pkcs8ShroudedKeyBag="\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x0A\x01\x02" +OBJ_certBag="\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x0A\x01\x03" +OBJ_crlBag="\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x0A\x01\x04" +OBJ_secretBag="\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x0A\x01\x05" +OBJ_safeContentsBag="\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x0A\x01\x06" +OBJ_friendlyName="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x14" +OBJ_localKeyID="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x15" +OBJ_x509Certificate="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x16\x01" +OBJ_sdsiCertificate="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x16\x02" +OBJ_x509Crl="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x17\x01" +OBJ_pbes2="\x2A\x86\x48\x86\xF7\x0D\x01\x05\x0D" +OBJ_pbmac1="\x2A\x86\x48\x86\xF7\x0D\x01\x05\x0E" +OBJ_hmacWithSHA1="\x2A\x86\x48\x86\xF7\x0D\x02\x07" +OBJ_id_qt_cps="\x2B\x06\x01\x05\x05\x07\x02\x01" +OBJ_id_qt_unotice="\x2B\x06\x01\x05\x05\x07\x02\x02" +OBJ_SMIMECapabilities="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x0F" +OBJ_pbeWithMD2AndRC2_CBC="\x2A\x86\x48\x86\xF7\x0D\x01\x05\x04" +OBJ_pbeWithMD5AndRC2_CBC="\x2A\x86\x48\x86\xF7\x0D\x01\x05\x06" +OBJ_pbeWithSHA1AndDES_CBC="\x2A\x86\x48\x86\xF7\x0D\x01\x05\x0A" +OBJ_ms_ext_req="\x2B\x06\x01\x04\x01\x82\x37\x02\x01\x0E" +OBJ_ext_req="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x0E" +OBJ_name="\x55\x04\x29" +OBJ_dnQualifier="\x55\x04\x2E" +OBJ_id_pe="\x2B\x06\x01\x05\x05\x07\x01" +OBJ_id_ad="\x2B\x06\x01\x05\x05\x07\x30" +OBJ_info_access="\x2B\x06\x01\x05\x05\x07\x01\x01" +OBJ_ad_OCSP="\x2B\x06\x01\x05\x05\x07\x30\x01" +OBJ_ad_ca_issuers="\x2B\x06\x01\x05\x05\x07\x30\x02" +OBJ_OCSP_sign="\x2B\x06\x01\x05\x05\x07\x03\x09" +OBJ_member_body="\x2A" +OBJ_ISO_US="\x2A\x86\x48" +OBJ_X9_57="\x2A\x86\x48\xCE\x38" +OBJ_X9cm="\x2A\x86\x48\xCE\x38\x04" +OBJ_pkcs1="\x2A\x86\x48\x86\xF7\x0D\x01\x01" +OBJ_pkcs5="\x2A\x86\x48\x86\xF7\x0D\x01\x05" +OBJ_SMIME="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10" +OBJ_id_smime_mod="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x00" +OBJ_id_smime_ct="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x01" +OBJ_id_smime_aa="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02" +OBJ_id_smime_alg="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x03" +OBJ_id_smime_cd="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x04" +OBJ_id_smime_spq="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x05" +OBJ_id_smime_cti="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x06" +OBJ_id_smime_mod_cms="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x00\x01" +OBJ_id_smime_mod_ess="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x00\x02" +OBJ_id_smime_mod_oid="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x00\x03" +OBJ_id_smime_mod_msg_v3="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x00\x04" +OBJ_id_smime_mod_ets_eSignature_88="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x00\x05" +OBJ_id_smime_mod_ets_eSignature_97="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x00\x06" +OBJ_id_smime_mod_ets_eSigPolicy_88="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x00\x07" +OBJ_id_smime_mod_ets_eSigPolicy_97="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x00\x08" +OBJ_id_smime_ct_receipt="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x01\x01" +OBJ_id_smime_ct_authData="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x01\x02" +OBJ_id_smime_ct_publishCert="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x01\x03" +OBJ_id_smime_ct_TSTInfo="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x01\x04" +OBJ_id_smime_ct_TDTInfo="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x01\x05" +OBJ_id_smime_ct_contentInfo="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x01\x06" +OBJ_id_smime_ct_DVCSRequestData="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x01\x07" +OBJ_id_smime_ct_DVCSResponseData="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x01\x08" +OBJ_id_smime_aa_receiptRequest="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x01" +OBJ_id_smime_aa_securityLabel="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x02" +OBJ_id_smime_aa_mlExpandHistory="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x03" +OBJ_id_smime_aa_contentHint="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x04" +OBJ_id_smime_aa_msgSigDigest="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x05" +OBJ_id_smime_aa_encapContentType="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x06" +OBJ_id_smime_aa_contentIdentifier="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x07" +OBJ_id_smime_aa_macValue="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x08" +OBJ_id_smime_aa_equivalentLabels="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x09" +OBJ_id_smime_aa_contentReference="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x0A" +OBJ_id_smime_aa_encrypKeyPref="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x0B" +OBJ_id_smime_aa_signingCertificate="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x0C" +OBJ_id_smime_aa_smimeEncryptCerts="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x0D" +OBJ_id_smime_aa_timeStampToken="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x0E" +OBJ_id_smime_aa_ets_sigPolicyId="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x0F" +OBJ_id_smime_aa_ets_commitmentType="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x10" +OBJ_id_smime_aa_ets_signerLocation="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x11" +OBJ_id_smime_aa_ets_signerAttr="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x12" +OBJ_id_smime_aa_ets_otherSigCert="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x13" +OBJ_id_smime_aa_ets_contentTimestamp="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x14" +OBJ_id_smime_aa_ets_CertificateRefs="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x15" +OBJ_id_smime_aa_ets_RevocationRefs="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x16" +OBJ_id_smime_aa_ets_certValues="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x17" +OBJ_id_smime_aa_ets_revocationValues="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x18" +OBJ_id_smime_aa_ets_escTimeStamp="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x19" +OBJ_id_smime_aa_ets_certCRLTimestamp="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x1A" +OBJ_id_smime_aa_ets_archiveTimeStamp="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x1B" +OBJ_id_smime_aa_signatureType="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x1C" +OBJ_id_smime_aa_dvcs_dvc="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x1D" +OBJ_id_smime_alg_ESDHwith3DES="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x03\x01" +OBJ_id_smime_alg_ESDHwithRC2="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x03\x02" +OBJ_id_smime_alg_3DESwrap="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x03\x03" +OBJ_id_smime_alg_RC2wrap="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x03\x04" +OBJ_id_smime_alg_ESDH="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x03\x05" +OBJ_id_smime_alg_CMS3DESwrap="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x03\x06" +OBJ_id_smime_alg_CMSRC2wrap="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x03\x07" +OBJ_id_smime_cd_ldap="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x04\x01" +OBJ_id_smime_spq_ets_sqt_uri="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x05\x01" +OBJ_id_smime_spq_ets_sqt_unotice="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x05\x02" +OBJ_id_smime_cti_ets_proofOfOrigin="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x06\x01" +OBJ_id_smime_cti_ets_proofOfReceipt="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x06\x02" +OBJ_id_smime_cti_ets_proofOfDelivery="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x06\x03" +OBJ_id_smime_cti_ets_proofOfSender="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x06\x04" +OBJ_id_smime_cti_ets_proofOfApproval="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x06\x05" +OBJ_id_smime_cti_ets_proofOfCreation="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x06\x06" +OBJ_md4="\x2A\x86\x48\x86\xF7\x0D\x02\x04" +OBJ_id_pkix_mod="\x2B\x06\x01\x05\x05\x07\x00" +OBJ_id_qt="\x2B\x06\x01\x05\x05\x07\x02" +OBJ_id_it="\x2B\x06\x01\x05\x05\x07\x04" +OBJ_id_pkip="\x2B\x06\x01\x05\x05\x07\x05" +OBJ_id_alg="\x2B\x06\x01\x05\x05\x07\x06" +OBJ_id_cmc="\x2B\x06\x01\x05\x05\x07\x07" +OBJ_id_on="\x2B\x06\x01\x05\x05\x07\x08" +OBJ_id_pda="\x2B\x06\x01\x05\x05\x07\x09" +OBJ_id_aca="\x2B\x06\x01\x05\x05\x07\x0A" +OBJ_id_qcs="\x2B\x06\x01\x05\x05\x07\x0B" +OBJ_id_cct="\x2B\x06\x01\x05\x05\x07\x0C" +OBJ_id_pkix1_explicit_88="\x2B\x06\x01\x05\x05\x07\x00\x01" +OBJ_id_pkix1_implicit_88="\x2B\x06\x01\x05\x05\x07\x00\x02" +OBJ_id_pkix1_explicit_93="\x2B\x06\x01\x05\x05\x07\x00\x03" +OBJ_id_pkix1_implicit_93="\x2B\x06\x01\x05\x05\x07\x00\x04" +OBJ_id_mod_crmf="\x2B\x06\x01\x05\x05\x07\x00\x05" +OBJ_id_mod_cmc="\x2B\x06\x01\x05\x05\x07\x00\x06" +OBJ_id_mod_kea_profile_88="\x2B\x06\x01\x05\x05\x07\x00\x07" +OBJ_id_mod_kea_profile_93="\x2B\x06\x01\x05\x05\x07\x00\x08" +OBJ_id_mod_cmp="\x2B\x06\x01\x05\x05\x07\x00\x09" +OBJ_id_mod_qualified_cert_88="\x2B\x06\x01\x05\x05\x07\x00\x0A" +OBJ_id_mod_qualified_cert_93="\x2B\x06\x01\x05\x05\x07\x00\x0B" +OBJ_id_mod_attribute_cert="\x2B\x06\x01\x05\x05\x07\x00\x0C" +OBJ_id_mod_timestamp_protocol="\x2B\x06\x01\x05\x05\x07\x00\x0D" +OBJ_id_mod_ocsp="\x2B\x06\x01\x05\x05\x07\x00\x0E" +OBJ_id_mod_dvcs="\x2B\x06\x01\x05\x05\x07\x00\x0F" +OBJ_id_mod_cmp2000="\x2B\x06\x01\x05\x05\x07\x00\x10" +OBJ_biometricInfo="\x2B\x06\x01\x05\x05\x07\x01\x02" +OBJ_qcStatements="\x2B\x06\x01\x05\x05\x07\x01\x03" +OBJ_ac_auditEntity="\x2B\x06\x01\x05\x05\x07\x01\x04" +OBJ_ac_targeting="\x2B\x06\x01\x05\x05\x07\x01\x05" +OBJ_aaControls="\x2B\x06\x01\x05\x05\x07\x01\x06" +OBJ_sbgp_ipAddrBlock="\x2B\x06\x01\x05\x05\x07\x01\x07" +OBJ_sbgp_autonomousSysNum="\x2B\x06\x01\x05\x05\x07\x01\x08" +OBJ_sbgp_routerIdentifier="\x2B\x06\x01\x05\x05\x07\x01\x09" +OBJ_textNotice="\x2B\x06\x01\x05\x05\x07\x02\x03" +OBJ_ipsecEndSystem="\x2B\x06\x01\x05\x05\x07\x03\x05" +OBJ_ipsecTunnel="\x2B\x06\x01\x05\x05\x07\x03\x06" +OBJ_ipsecUser="\x2B\x06\x01\x05\x05\x07\x03\x07" +OBJ_dvcs="\x2B\x06\x01\x05\x05\x07\x03\x0A" +OBJ_id_it_caProtEncCert="\x2B\x06\x01\x05\x05\x07\x04\x01" +OBJ_id_it_signKeyPairTypes="\x2B\x06\x01\x05\x05\x07\x04\x02" +OBJ_id_it_encKeyPairTypes="\x2B\x06\x01\x05\x05\x07\x04\x03" +OBJ_id_it_preferredSymmAlg="\x2B\x06\x01\x05\x05\x07\x04\x04" +OBJ_id_it_caKeyUpdateInfo="\x2B\x06\x01\x05\x05\x07\x04\x05" +OBJ_id_it_currentCRL="\x2B\x06\x01\x05\x05\x07\x04\x06" +OBJ_id_it_unsupportedOIDs="\x2B\x06\x01\x05\x05\x07\x04\x07" +OBJ_id_it_subscriptionRequest="\x2B\x06\x01\x05\x05\x07\x04\x08" +OBJ_id_it_subscriptionResponse="\x2B\x06\x01\x05\x05\x07\x04\x09" +OBJ_id_it_keyPairParamReq="\x2B\x06\x01\x05\x05\x07\x04\x0A" +OBJ_id_it_keyPairParamRep="\x2B\x06\x01\x05\x05\x07\x04\x0B" +OBJ_id_it_revPassphrase="\x2B\x06\x01\x05\x05\x07\x04\x0C" +OBJ_id_it_implicitConfirm="\x2B\x06\x01\x05\x05\x07\x04\x0D" +OBJ_id_it_confirmWaitTime="\x2B\x06\x01\x05\x05\x07\x04\x0E" +OBJ_id_it_origPKIMessage="\x2B\x06\x01\x05\x05\x07\x04\x0F" +OBJ_id_regCtrl="\x2B\x06\x01\x05\x05\x07\x05\x01" +OBJ_id_regInfo="\x2B\x06\x01\x05\x05\x07\x05\x02" +OBJ_id_regCtrl_regToken="\x2B\x06\x01\x05\x05\x07\x05\x01\x01" +OBJ_id_regCtrl_authenticator="\x2B\x06\x01\x05\x05\x07\x05\x01\x02" +OBJ_id_regCtrl_pkiPublicationInfo="\x2B\x06\x01\x05\x05\x07\x05\x01\x03" +OBJ_id_regCtrl_pkiArchiveOptions="\x2B\x06\x01\x05\x05\x07\x05\x01\x04" +OBJ_id_regCtrl_oldCertID="\x2B\x06\x01\x05\x05\x07\x05\x01\x05" +OBJ_id_regCtrl_protocolEncrKey="\x2B\x06\x01\x05\x05\x07\x05\x01\x06" +OBJ_id_regInfo_utf8Pairs="\x2B\x06\x01\x05\x05\x07\x05\x02\x01" +OBJ_id_regInfo_certReq="\x2B\x06\x01\x05\x05\x07\x05\x02\x02" +OBJ_id_alg_des40="\x2B\x06\x01\x05\x05\x07\x06\x01" +OBJ_id_alg_noSignature="\x2B\x06\x01\x05\x05\x07\x06\x02" +OBJ_id_alg_dh_sig_hmac_sha1="\x2B\x06\x01\x05\x05\x07\x06\x03" +OBJ_id_alg_dh_pop="\x2B\x06\x01\x05\x05\x07\x06\x04" +OBJ_id_cmc_statusInfo="\x2B\x06\x01\x05\x05\x07\x07\x01" +OBJ_id_cmc_identification="\x2B\x06\x01\x05\x05\x07\x07\x02" +OBJ_id_cmc_identityProof="\x2B\x06\x01\x05\x05\x07\x07\x03" +OBJ_id_cmc_dataReturn="\x2B\x06\x01\x05\x05\x07\x07\x04" +OBJ_id_cmc_transactionId="\x2B\x06\x01\x05\x05\x07\x07\x05" +OBJ_id_cmc_senderNonce="\x2B\x06\x01\x05\x05\x07\x07\x06" +OBJ_id_cmc_recipientNonce="\x2B\x06\x01\x05\x05\x07\x07\x07" +OBJ_id_cmc_addExtensions="\x2B\x06\x01\x05\x05\x07\x07\x08" +OBJ_id_cmc_encryptedPOP="\x2B\x06\x01\x05\x05\x07\x07\x09" +OBJ_id_cmc_decryptedPOP="\x2B\x06\x01\x05\x05\x07\x07\x0A" +OBJ_id_cmc_lraPOPWitness="\x2B\x06\x01\x05\x05\x07\x07\x0B" +OBJ_id_cmc_getCert="\x2B\x06\x01\x05\x05\x07\x07\x0F" +OBJ_id_cmc_getCRL="\x2B\x06\x01\x05\x05\x07\x07\x10" +OBJ_id_cmc_revokeRequest="\x2B\x06\x01\x05\x05\x07\x07\x11" +OBJ_id_cmc_regInfo="\x2B\x06\x01\x05\x05\x07\x07\x12" +OBJ_id_cmc_responseInfo="\x2B\x06\x01\x05\x05\x07\x07\x13" +OBJ_id_cmc_queryPending="\x2B\x06\x01\x05\x05\x07\x07\x15" +OBJ_id_cmc_popLinkRandom="\x2B\x06\x01\x05\x05\x07\x07\x16" +OBJ_id_cmc_popLinkWitness="\x2B\x06\x01\x05\x05\x07\x07\x17" +OBJ_id_cmc_confirmCertAcceptance="\x2B\x06\x01\x05\x05\x07\x07\x18" +OBJ_id_on_personalData="\x2B\x06\x01\x05\x05\x07\x08\x01" +OBJ_id_pda_dateOfBirth="\x2B\x06\x01\x05\x05\x07\x09\x01" +OBJ_id_pda_placeOfBirth="\x2B\x06\x01\x05\x05\x07\x09\x02" +OBJ_id_pda_gender="\x2B\x06\x01\x05\x05\x07\x09\x03" +OBJ_id_pda_countryOfCitizenship="\x2B\x06\x01\x05\x05\x07\x09\x04" +OBJ_id_pda_countryOfResidence="\x2B\x06\x01\x05\x05\x07\x09\x05" +OBJ_id_aca_authenticationInfo="\x2B\x06\x01\x05\x05\x07\x0A\x01" +OBJ_id_aca_accessIdentity="\x2B\x06\x01\x05\x05\x07\x0A\x02" +OBJ_id_aca_chargingIdentity="\x2B\x06\x01\x05\x05\x07\x0A\x03" +OBJ_id_aca_group="\x2B\x06\x01\x05\x05\x07\x0A\x04" +OBJ_id_aca_role="\x2B\x06\x01\x05\x05\x07\x0A\x05" +OBJ_id_qcs_pkixQCSyntax_v1="\x2B\x06\x01\x05\x05\x07\x0B\x01" +OBJ_id_cct_crs="\x2B\x06\x01\x05\x05\x07\x0C\x01" +OBJ_id_cct_PKIData="\x2B\x06\x01\x05\x05\x07\x0C\x02" +OBJ_id_cct_PKIResponse="\x2B\x06\x01\x05\x05\x07\x0C\x03" +OBJ_ad_timeStamping="\x2B\x06\x01\x05\x05\x07\x30\x03" +OBJ_ad_dvcs="\x2B\x06\x01\x05\x05\x07\x30\x04" +OBJ_id_pkix_OCSP_basic="\x2B\x06\x01\x05\x05\x07\x30\x01\x01" +OBJ_id_pkix_OCSP_Nonce="\x2B\x06\x01\x05\x05\x07\x30\x01\x02" +OBJ_id_pkix_OCSP_CrlID="\x2B\x06\x01\x05\x05\x07\x30\x01\x03" +OBJ_id_pkix_OCSP_acceptableResponses="\x2B\x06\x01\x05\x05\x07\x30\x01\x04" +OBJ_id_pkix_OCSP_noCheck="\x2B\x06\x01\x05\x05\x07\x30\x01\x05" +OBJ_id_pkix_OCSP_archiveCutoff="\x2B\x06\x01\x05\x05\x07\x30\x01\x06" +OBJ_id_pkix_OCSP_serviceLocator="\x2B\x06\x01\x05\x05\x07\x30\x01\x07" +OBJ_id_pkix_OCSP_extendedStatus="\x2B\x06\x01\x05\x05\x07\x30\x01\x08" +OBJ_id_pkix_OCSP_valid="\x2B\x06\x01\x05\x05\x07\x30\x01\x09" +OBJ_id_pkix_OCSP_path="\x2B\x06\x01\x05\x05\x07\x30\x01\x0A" +OBJ_id_pkix_OCSP_trustRoot="\x2B\x06\x01\x05\x05\x07\x30\x01\x0B" +OBJ_algorithm="\x2B\x0E\x03\x02" +OBJ_rsaSignature="\x2B\x0E\x03\x02\x0B" +OBJ_X500algorithms="\x55\x08" +OBJ_org="\x2B" +OBJ_dod="\x2B\x06" +OBJ_iana="\x2B\x06\x01" +OBJ_Directory="\x2B\x06\x01\x01" +OBJ_Management="\x2B\x06\x01\x02" +OBJ_Experimental="\x2B\x06\x01\x03" +OBJ_Private="\x2B\x06\x01\x04" +OBJ_Security="\x2B\x06\x01\x05" +OBJ_SNMPv2="\x2B\x06\x01\x06" +OBJ_Mail="\x2B\x06\x01\x07" +OBJ_Enterprises="\x2B\x06\x01\x04\x01" +OBJ_dcObject="\x2B\x06\x01\x04\x01\x8B\x3A\x82\x58" +OBJ_domainComponent="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19" +OBJ_Domain="\x09\x92\x26\x89\x93\xF2\x2C\x64\x04\x0D" +OBJ_selected_attribute_types="\x55\x01\x05" +OBJ_clearance="\x55\x01\x05\x37" +OBJ_md4WithRSAEncryption="\x2A\x86\x48\x86\xF7\x0D\x01\x01\x03" +OBJ_ac_proxying="\x2B\x06\x01\x05\x05\x07\x01\x0A" +OBJ_sinfo_access="\x2B\x06\x01\x05\x05\x07\x01\x0B" +OBJ_id_aca_encAttrs="\x2B\x06\x01\x05\x05\x07\x0A\x06" +OBJ_role="\x55\x04\x48" +OBJ_policy_constraints="\x55\x1D\x24" +OBJ_target_information="\x55\x1D\x37" +OBJ_no_rev_avail="\x55\x1D\x38" +OBJ_ansi_X9_62="\x2A\x86\x48\xCE\x3D" +OBJ_X9_62_prime_field="\x2A\x86\x48\xCE\x3D\x01\x01" +OBJ_X9_62_characteristic_two_field="\x2A\x86\x48\xCE\x3D\x01\x02" +OBJ_X9_62_id_ecPublicKey="\x2A\x86\x48\xCE\x3D\x02\x01" +OBJ_X9_62_prime192v1="\x2A\x86\x48\xCE\x3D\x03\x01\x01" +OBJ_X9_62_prime192v2="\x2A\x86\x48\xCE\x3D\x03\x01\x02" +OBJ_X9_62_prime192v3="\x2A\x86\x48\xCE\x3D\x03\x01\x03" +OBJ_X9_62_prime239v1="\x2A\x86\x48\xCE\x3D\x03\x01\x04" +OBJ_X9_62_prime239v2="\x2A\x86\x48\xCE\x3D\x03\x01\x05" +OBJ_X9_62_prime239v3="\x2A\x86\x48\xCE\x3D\x03\x01\x06" +OBJ_X9_62_prime256v1="\x2A\x86\x48\xCE\x3D\x03\x01\x07" +OBJ_ecdsa_with_SHA1="\x2A\x86\x48\xCE\x3D\x04\x01" +OBJ_ms_csp_name="\x2B\x06\x01\x04\x01\x82\x37\x11\x01" +OBJ_aes_128_ecb="\x60\x86\x48\x01\x65\x03\x04\x01\x01" +OBJ_aes_128_cbc="\x60\x86\x48\x01\x65\x03\x04\x01\x02" +OBJ_aes_128_ofb128="\x60\x86\x48\x01\x65\x03\x04\x01\x03" +OBJ_aes_128_cfb128="\x60\x86\x48\x01\x65\x03\x04\x01\x04" +OBJ_aes_192_ecb="\x60\x86\x48\x01\x65\x03\x04\x01\x15" +OBJ_aes_192_cbc="\x60\x86\x48\x01\x65\x03\x04\x01\x16" +OBJ_aes_192_ofb128="\x60\x86\x48\x01\x65\x03\x04\x01\x17" +OBJ_aes_192_cfb128="\x60\x86\x48\x01\x65\x03\x04\x01\x18" +OBJ_aes_256_ecb="\x60\x86\x48\x01\x65\x03\x04\x01\x29" +OBJ_aes_256_cbc="\x60\x86\x48\x01\x65\x03\x04\x01\x2A" +OBJ_aes_256_ofb128="\x60\x86\x48\x01\x65\x03\x04\x01\x2B" +OBJ_aes_256_cfb128="\x60\x86\x48\x01\x65\x03\x04\x01\x2C" +OBJ_hold_instruction_code="\x55\x1D\x17" +OBJ_hold_instruction_none="\x2A\x86\x48\xCE\x38\x02\x01" +OBJ_hold_instruction_call_issuer="\x2A\x86\x48\xCE\x38\x02\x02" +OBJ_hold_instruction_reject="\x2A\x86\x48\xCE\x38\x02\x03" +OBJ_data="\x09" +OBJ_pss="\x09\x92\x26" +OBJ_ucl="\x09\x92\x26\x89\x93\xF2\x2C" +OBJ_pilot="\x09\x92\x26\x89\x93\xF2\x2C\x64" +OBJ_pilotAttributeType="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01" +OBJ_pilotAttributeSyntax="\x09\x92\x26\x89\x93\xF2\x2C\x64\x03" +OBJ_pilotObjectClass="\x09\x92\x26\x89\x93\xF2\x2C\x64\x04" +OBJ_pilotGroups="\x09\x92\x26\x89\x93\xF2\x2C\x64\x0A" +OBJ_iA5StringSyntax="\x09\x92\x26\x89\x93\xF2\x2C\x64\x03\x04" +OBJ_caseIgnoreIA5StringSyntax="\x09\x92\x26\x89\x93\xF2\x2C\x64\x03\x05" +OBJ_pilotObject="\x09\x92\x26\x89\x93\xF2\x2C\x64\x04\x03" +OBJ_pilotPerson="\x09\x92\x26\x89\x93\xF2\x2C\x64\x04\x04" +OBJ_account="\x09\x92\x26\x89\x93\xF2\x2C\x64\x04\x05" +OBJ_document="\x09\x92\x26\x89\x93\xF2\x2C\x64\x04\x06" +OBJ_room="\x09\x92\x26\x89\x93\xF2\x2C\x64\x04\x07" +OBJ_documentSeries="\x09\x92\x26\x89\x93\xF2\x2C\x64\x04\x09" +OBJ_rFC822localPart="\x09\x92\x26\x89\x93\xF2\x2C\x64\x04\x0E" +OBJ_dNSDomain="\x09\x92\x26\x89\x93\xF2\x2C\x64\x04\x0F" +OBJ_domainRelatedObject="\x09\x92\x26\x89\x93\xF2\x2C\x64\x04\x11" +OBJ_friendlyCountry="\x09\x92\x26\x89\x93\xF2\x2C\x64\x04\x12" +OBJ_simpleSecurityObject="\x09\x92\x26\x89\x93\xF2\x2C\x64\x04\x13" +OBJ_pilotOrganization="\x09\x92\x26\x89\x93\xF2\x2C\x64\x04\x14" +OBJ_pilotDSA="\x09\x92\x26\x89\x93\xF2\x2C\x64\x04\x15" +OBJ_qualityLabelledData="\x09\x92\x26\x89\x93\xF2\x2C\x64\x04\x16" +OBJ_userId="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x01" +OBJ_textEncodedORAddress="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x02" +OBJ_rfc822Mailbox="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x03" +OBJ_info="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x04" +OBJ_favouriteDrink="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x05" +OBJ_roomNumber="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x06" +OBJ_photo="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x07" +OBJ_userClass="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x08" +OBJ_host="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x09" +OBJ_manager="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x0A" +OBJ_documentIdentifier="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x0B" +OBJ_documentTitle="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x0C" +OBJ_documentVersion="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x0D" +OBJ_documentAuthor="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x0E" +OBJ_documentLocation="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x0F" +OBJ_homeTelephoneNumber="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x14" +OBJ_secretary="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x15" +OBJ_otherMailbox="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x16" +OBJ_lastModifiedTime="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x17" +OBJ_lastModifiedBy="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x18" +OBJ_aRecord="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x1A" +OBJ_pilotAttributeType27="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x1B" +OBJ_mXRecord="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x1C" +OBJ_nSRecord="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x1D" +OBJ_sOARecord="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x1E" +OBJ_cNAMERecord="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x1F" +OBJ_associatedDomain="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x25" +OBJ_associatedName="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x26" +OBJ_homePostalAddress="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x27" +OBJ_personalTitle="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x28" +OBJ_mobileTelephoneNumber="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x29" +OBJ_pagerTelephoneNumber="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x2A" +OBJ_friendlyCountryName="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x2B" +OBJ_organizationalStatus="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x2D" +OBJ_janetMailbox="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x2E" +OBJ_mailPreferenceOption="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x2F" +OBJ_buildingName="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x30" +OBJ_dSAQuality="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x31" +OBJ_singleLevelQuality="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x32" +OBJ_subtreeMinimumQuality="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x33" +OBJ_subtreeMaximumQuality="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x34" +OBJ_personalSignature="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x35" +OBJ_dITRedirect="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x36" +OBJ_audio="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x37" +OBJ_documentPublisher="\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x38" +OBJ_x500UniqueIdentifier="\x55\x04\x2D" +OBJ_mime_mhs="\x2B\x06\x01\x07\x01" +OBJ_mime_mhs_headings="\x2B\x06\x01\x07\x01\x01" +OBJ_mime_mhs_bodies="\x2B\x06\x01\x07\x01\x02" +OBJ_id_hex_partial_message="\x2B\x06\x01\x07\x01\x01\x01" +OBJ_id_hex_multipart_message="\x2B\x06\x01\x07\x01\x01\x02" +OBJ_generationQualifier="\x55\x04\x2C" +OBJ_pseudonym="\x55\x04\x41" +OBJ_id_set="\x67\x2A" +OBJ_set_ctype="\x67\x2A\x00" +OBJ_set_msgExt="\x67\x2A\x01" +OBJ_set_attr="\x67\x2A\x03" +OBJ_set_policy="\x67\x2A\x05" +OBJ_set_certExt="\x67\x2A\x07" +OBJ_set_brand="\x67\x2A\x08" +OBJ_setct_PANData="\x67\x2A\x00\x00" +OBJ_setct_PANToken="\x67\x2A\x00\x01" +OBJ_setct_PANOnly="\x67\x2A\x00\x02" +OBJ_setct_OIData="\x67\x2A\x00\x03" +OBJ_setct_PI="\x67\x2A\x00\x04" +OBJ_setct_PIData="\x67\x2A\x00\x05" +OBJ_setct_PIDataUnsigned="\x67\x2A\x00\x06" +OBJ_setct_HODInput="\x67\x2A\x00\x07" +OBJ_setct_AuthResBaggage="\x67\x2A\x00\x08" +OBJ_setct_AuthRevReqBaggage="\x67\x2A\x00\x09" +OBJ_setct_AuthRevResBaggage="\x67\x2A\x00\x0A" +OBJ_setct_CapTokenSeq="\x67\x2A\x00\x0B" +OBJ_setct_PInitResData="\x67\x2A\x00\x0C" +OBJ_setct_PI_TBS="\x67\x2A\x00\x0D" +OBJ_setct_PResData="\x67\x2A\x00\x0E" +OBJ_setct_AuthReqTBS="\x67\x2A\x00\x10" +OBJ_setct_AuthResTBS="\x67\x2A\x00\x11" +OBJ_setct_AuthResTBSX="\x67\x2A\x00\x12" +OBJ_setct_AuthTokenTBS="\x67\x2A\x00\x13" +OBJ_setct_CapTokenData="\x67\x2A\x00\x14" +OBJ_setct_CapTokenTBS="\x67\x2A\x00\x15" +OBJ_setct_AcqCardCodeMsg="\x67\x2A\x00\x16" +OBJ_setct_AuthRevReqTBS="\x67\x2A\x00\x17" +OBJ_setct_AuthRevResData="\x67\x2A\x00\x18" +OBJ_setct_AuthRevResTBS="\x67\x2A\x00\x19" +OBJ_setct_CapReqTBS="\x67\x2A\x00\x1A" +OBJ_setct_CapReqTBSX="\x67\x2A\x00\x1B" +OBJ_setct_CapResData="\x67\x2A\x00\x1C" +OBJ_setct_CapRevReqTBS="\x67\x2A\x00\x1D" +OBJ_setct_CapRevReqTBSX="\x67\x2A\x00\x1E" +OBJ_setct_CapRevResData="\x67\x2A\x00\x1F" +OBJ_setct_CredReqTBS="\x67\x2A\x00\x20" +OBJ_setct_CredReqTBSX="\x67\x2A\x00\x21" +OBJ_setct_CredResData="\x67\x2A\x00\x22" +OBJ_setct_CredRevReqTBS="\x67\x2A\x00\x23" +OBJ_setct_CredRevReqTBSX="\x67\x2A\x00\x24" +OBJ_setct_CredRevResData="\x67\x2A\x00\x25" +OBJ_setct_PCertReqData="\x67\x2A\x00\x26" +OBJ_setct_PCertResTBS="\x67\x2A\x00\x27" +OBJ_setct_BatchAdminReqData="\x67\x2A\x00\x28" +OBJ_setct_BatchAdminResData="\x67\x2A\x00\x29" +OBJ_setct_CardCInitResTBS="\x67\x2A\x00\x2A" +OBJ_setct_MeAqCInitResTBS="\x67\x2A\x00\x2B" +OBJ_setct_RegFormResTBS="\x67\x2A\x00\x2C" +OBJ_setct_CertReqData="\x67\x2A\x00\x2D" +OBJ_setct_CertReqTBS="\x67\x2A\x00\x2E" +OBJ_setct_CertResData="\x67\x2A\x00\x2F" +OBJ_setct_CertInqReqTBS="\x67\x2A\x00\x30" +OBJ_setct_ErrorTBS="\x67\x2A\x00\x31" +OBJ_setct_PIDualSignedTBE="\x67\x2A\x00\x32" +OBJ_setct_PIUnsignedTBE="\x67\x2A\x00\x33" +OBJ_setct_AuthReqTBE="\x67\x2A\x00\x34" +OBJ_setct_AuthResTBE="\x67\x2A\x00\x35" +OBJ_setct_AuthResTBEX="\x67\x2A\x00\x36" +OBJ_setct_AuthTokenTBE="\x67\x2A\x00\x37" +OBJ_setct_CapTokenTBE="\x67\x2A\x00\x38" +OBJ_setct_CapTokenTBEX="\x67\x2A\x00\x39" +OBJ_setct_AcqCardCodeMsgTBE="\x67\x2A\x00\x3A" +OBJ_setct_AuthRevReqTBE="\x67\x2A\x00\x3B" +OBJ_setct_AuthRevResTBE="\x67\x2A\x00\x3C" +OBJ_setct_AuthRevResTBEB="\x67\x2A\x00\x3D" +OBJ_setct_CapReqTBE="\x67\x2A\x00\x3E" +OBJ_setct_CapReqTBEX="\x67\x2A\x00\x3F" +OBJ_setct_CapResTBE="\x67\x2A\x00\x40" +OBJ_setct_CapRevReqTBE="\x67\x2A\x00\x41" +OBJ_setct_CapRevReqTBEX="\x67\x2A\x00\x42" +OBJ_setct_CapRevResTBE="\x67\x2A\x00\x43" +OBJ_setct_CredReqTBE="\x67\x2A\x00\x44" +OBJ_setct_CredReqTBEX="\x67\x2A\x00\x45" +OBJ_setct_CredResTBE="\x67\x2A\x00\x46" +OBJ_setct_CredRevReqTBE="\x67\x2A\x00\x47" +OBJ_setct_CredRevReqTBEX="\x67\x2A\x00\x48" +OBJ_setct_CredRevResTBE="\x67\x2A\x00\x49" +OBJ_setct_BatchAdminReqTBE="\x67\x2A\x00\x4A" +OBJ_setct_BatchAdminResTBE="\x67\x2A\x00\x4B" +OBJ_setct_RegFormReqTBE="\x67\x2A\x00\x4C" +OBJ_setct_CertReqTBE="\x67\x2A\x00\x4D" +OBJ_setct_CertReqTBEX="\x67\x2A\x00\x4E" +OBJ_setct_CertResTBE="\x67\x2A\x00\x4F" +OBJ_setct_CRLNotificationTBS="\x67\x2A\x00\x50" +OBJ_setct_CRLNotificationResTBS="\x67\x2A\x00\x51" +OBJ_setct_BCIDistributionTBS="\x67\x2A\x00\x52" +OBJ_setext_genCrypt="\x67\x2A\x01\x01" +OBJ_setext_miAuth="\x67\x2A\x01\x03" +OBJ_setext_pinSecure="\x67\x2A\x01\x04" +OBJ_setext_pinAny="\x67\x2A\x01\x05" +OBJ_setext_track2="\x67\x2A\x01\x07" +OBJ_setext_cv="\x67\x2A\x01\x08" +OBJ_set_policy_root="\x67\x2A\x05\x00" +OBJ_setCext_hashedRoot="\x67\x2A\x07\x00" +OBJ_setCext_certType="\x67\x2A\x07\x01" +OBJ_setCext_merchData="\x67\x2A\x07\x02" +OBJ_setCext_cCertRequired="\x67\x2A\x07\x03" +OBJ_setCext_tunneling="\x67\x2A\x07\x04" +OBJ_setCext_setExt="\x67\x2A\x07\x05" +OBJ_setCext_setQualf="\x67\x2A\x07\x06" +OBJ_setCext_PGWYcapabilities="\x67\x2A\x07\x07" +OBJ_setCext_TokenIdentifier="\x67\x2A\x07\x08" +OBJ_setCext_Track2Data="\x67\x2A\x07\x09" +OBJ_setCext_TokenType="\x67\x2A\x07\x0A" +OBJ_setCext_IssuerCapabilities="\x67\x2A\x07\x0B" +OBJ_setAttr_Cert="\x67\x2A\x03\x00" +OBJ_setAttr_PGWYcap="\x67\x2A\x03\x01" +OBJ_setAttr_TokenType="\x67\x2A\x03\x02" +OBJ_setAttr_IssCap="\x67\x2A\x03\x03" +OBJ_set_rootKeyThumb="\x67\x2A\x03\x00\x00" +OBJ_set_addPolicy="\x67\x2A\x03\x00\x01" +OBJ_setAttr_Token_EMV="\x67\x2A\x03\x02\x01" +OBJ_setAttr_Token_B0Prime="\x67\x2A\x03\x02\x02" +OBJ_setAttr_IssCap_CVM="\x67\x2A\x03\x03\x03" +OBJ_setAttr_IssCap_T2="\x67\x2A\x03\x03\x04" +OBJ_setAttr_IssCap_Sig="\x67\x2A\x03\x03\x05" +OBJ_setAttr_GenCryptgrm="\x67\x2A\x03\x03\x03\x01" +OBJ_setAttr_T2Enc="\x67\x2A\x03\x03\x04\x01" +OBJ_setAttr_T2cleartxt="\x67\x2A\x03\x03\x04\x02" +OBJ_setAttr_TokICCsig="\x67\x2A\x03\x03\x05\x01" +OBJ_setAttr_SecDevSig="\x67\x2A\x03\x03\x05\x02" +OBJ_set_brand_IATA_ATA="\x67\x2A\x08\x01" +OBJ_set_brand_Diners="\x67\x2A\x08\x1E" +OBJ_set_brand_AmericanExpress="\x67\x2A\x08\x22" +OBJ_set_brand_JCB="\x67\x2A\x08\x23" +OBJ_set_brand_Visa="\x67\x2A\x08\x04" +OBJ_set_brand_MasterCard="\x67\x2A\x08\x05" +OBJ_set_brand_Novus="\x67\x2A\x08\xAE\x7B" +OBJ_des_cdmf="\x2A\x86\x48\x86\xF7\x0D\x03\x0A" +OBJ_rsaOAEPEncryptionSET="\x2A\x86\x48\x86\xF7\x0D\x01\x01\x06" +OBJ_international_organizations="\x67" +OBJ_ms_smartcard_login="\x2B\x06\x01\x04\x01\x82\x37\x14\x02\x02" +OBJ_ms_upn="\x2B\x06\x01\x04\x01\x82\x37\x14\x02\x03" +OBJ_streetAddress="\x55\x04\x09" +OBJ_postalCode="\x55\x04\x11" +OBJ_id_ppl="\x2B\x06\x01\x05\x05\x07\x15" +OBJ_proxyCertInfo="\x2B\x06\x01\x05\x05\x07\x01\x0E" +OBJ_id_ppl_anyLanguage="\x2B\x06\x01\x05\x05\x07\x15\x00" +OBJ_id_ppl_inheritAll="\x2B\x06\x01\x05\x05\x07\x15\x01" +OBJ_name_constraints="\x55\x1D\x1E" +OBJ_Independent="\x2B\x06\x01\x05\x05\x07\x15\x02" +OBJ_sha256WithRSAEncryption="\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B" +OBJ_sha384WithRSAEncryption="\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0C" +OBJ_sha512WithRSAEncryption="\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0D" +OBJ_sha224WithRSAEncryption="\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0E" +OBJ_sha256="\x60\x86\x48\x01\x65\x03\x04\x02\x01" +OBJ_sha384="\x60\x86\x48\x01\x65\x03\x04\x02\x02" +OBJ_sha512="\x60\x86\x48\x01\x65\x03\x04\x02\x03" +OBJ_sha224="\x60\x86\x48\x01\x65\x03\x04\x02\x04" +OBJ_identified_organization="\x2B" +OBJ_certicom_arc="\x2B\x81\x04" +OBJ_wap="\x67\x2B" +OBJ_wap_wsg="\x67\x2B\x01" +OBJ_X9_62_id_characteristic_two_basis="\x2A\x86\x48\xCE\x3D\x01\x02\x03" +OBJ_X9_62_onBasis="\x2A\x86\x48\xCE\x3D\x01\x02\x03\x01" +OBJ_X9_62_tpBasis="\x2A\x86\x48\xCE\x3D\x01\x02\x03\x02" +OBJ_X9_62_ppBasis="\x2A\x86\x48\xCE\x3D\x01\x02\x03\x03" +OBJ_X9_62_c2pnb163v1="\x2A\x86\x48\xCE\x3D\x03\x00\x01" +OBJ_X9_62_c2pnb163v2="\x2A\x86\x48\xCE\x3D\x03\x00\x02" +OBJ_X9_62_c2pnb163v3="\x2A\x86\x48\xCE\x3D\x03\x00\x03" +OBJ_X9_62_c2pnb176v1="\x2A\x86\x48\xCE\x3D\x03\x00\x04" +OBJ_X9_62_c2tnb191v1="\x2A\x86\x48\xCE\x3D\x03\x00\x05" +OBJ_X9_62_c2tnb191v2="\x2A\x86\x48\xCE\x3D\x03\x00\x06" +OBJ_X9_62_c2tnb191v3="\x2A\x86\x48\xCE\x3D\x03\x00\x07" +OBJ_X9_62_c2onb191v4="\x2A\x86\x48\xCE\x3D\x03\x00\x08" +OBJ_X9_62_c2onb191v5="\x2A\x86\x48\xCE\x3D\x03\x00\x09" +OBJ_X9_62_c2pnb208w1="\x2A\x86\x48\xCE\x3D\x03\x00\x0A" +OBJ_X9_62_c2tnb239v1="\x2A\x86\x48\xCE\x3D\x03\x00\x0B" +OBJ_X9_62_c2tnb239v2="\x2A\x86\x48\xCE\x3D\x03\x00\x0C" +OBJ_X9_62_c2tnb239v3="\x2A\x86\x48\xCE\x3D\x03\x00\x0D" +OBJ_X9_62_c2onb239v4="\x2A\x86\x48\xCE\x3D\x03\x00\x0E" +OBJ_X9_62_c2onb239v5="\x2A\x86\x48\xCE\x3D\x03\x00\x0F" +OBJ_X9_62_c2pnb272w1="\x2A\x86\x48\xCE\x3D\x03\x00\x10" +OBJ_X9_62_c2pnb304w1="\x2A\x86\x48\xCE\x3D\x03\x00\x11" +OBJ_X9_62_c2tnb359v1="\x2A\x86\x48\xCE\x3D\x03\x00\x12" +OBJ_X9_62_c2pnb368w1="\x2A\x86\x48\xCE\x3D\x03\x00\x13" +OBJ_X9_62_c2tnb431r1="\x2A\x86\x48\xCE\x3D\x03\x00\x14" +OBJ_secp112r1="\x2B\x81\x04\x00\x06" +OBJ_secp112r2="\x2B\x81\x04\x00\x07" +OBJ_secp128r1="\x2B\x81\x04\x00\x1C" +OBJ_secp128r2="\x2B\x81\x04\x00\x1D" +OBJ_secp160k1="\x2B\x81\x04\x00\x09" +OBJ_secp160r1="\x2B\x81\x04\x00\x08" +OBJ_secp160r2="\x2B\x81\x04\x00\x1E" +OBJ_secp192k1="\x2B\x81\x04\x00\x1F" +OBJ_secp224k1="\x2B\x81\x04\x00\x20" +OBJ_secp224r1="\x2B\x81\x04\x00\x21" +OBJ_secp256k1="\x2B\x81\x04\x00\x0A" +OBJ_secp384r1="\x2B\x81\x04\x00\x22" +OBJ_secp521r1="\x2B\x81\x04\x00\x23" +OBJ_sect113r1="\x2B\x81\x04\x00\x04" +OBJ_sect113r2="\x2B\x81\x04\x00\x05" +OBJ_sect131r1="\x2B\x81\x04\x00\x16" +OBJ_sect131r2="\x2B\x81\x04\x00\x17" +OBJ_sect163k1="\x2B\x81\x04\x00\x01" +OBJ_sect163r1="\x2B\x81\x04\x00\x02" +OBJ_sect163r2="\x2B\x81\x04\x00\x0F" +OBJ_sect193r1="\x2B\x81\x04\x00\x18" +OBJ_sect193r2="\x2B\x81\x04\x00\x19" +OBJ_sect233k1="\x2B\x81\x04\x00\x1A" +OBJ_sect233r1="\x2B\x81\x04\x00\x1B" +OBJ_sect239k1="\x2B\x81\x04\x00\x03" +OBJ_sect283k1="\x2B\x81\x04\x00\x10" +OBJ_sect283r1="\x2B\x81\x04\x00\x11" +OBJ_sect409k1="\x2B\x81\x04\x00\x24" +OBJ_sect409r1="\x2B\x81\x04\x00\x25" +OBJ_sect571k1="\x2B\x81\x04\x00\x26" +OBJ_sect571r1="\x2B\x81\x04\x00\x27" +OBJ_wap_wsg_idm_ecid_wtls1="\x67\x2B\x01\x04\x01" +OBJ_wap_wsg_idm_ecid_wtls3="\x67\x2B\x01\x04\x03" +OBJ_wap_wsg_idm_ecid_wtls4="\x67\x2B\x01\x04\x04" +OBJ_wap_wsg_idm_ecid_wtls5="\x67\x2B\x01\x04\x05" +OBJ_wap_wsg_idm_ecid_wtls6="\x67\x2B\x01\x04\x06" +OBJ_wap_wsg_idm_ecid_wtls7="\x67\x2B\x01\x04\x07" +OBJ_wap_wsg_idm_ecid_wtls8="\x67\x2B\x01\x04\x08" +OBJ_wap_wsg_idm_ecid_wtls9="\x67\x2B\x01\x04\x09" +OBJ_wap_wsg_idm_ecid_wtls10="\x67\x2B\x01\x04\x0A" +OBJ_wap_wsg_idm_ecid_wtls11="\x67\x2B\x01\x04\x0B" +OBJ_wap_wsg_idm_ecid_wtls12="\x67\x2B\x01\x04\x0C" +OBJ_any_policy="\x55\x1D\x20\x00" +OBJ_policy_mappings="\x55\x1D\x21" +OBJ_inhibit_any_policy="\x55\x1D\x36" +OBJ_camellia_128_cbc="\x2A\x83\x08\x8C\x9A\x4B\x3D\x01\x01\x01\x02" +OBJ_camellia_192_cbc="\x2A\x83\x08\x8C\x9A\x4B\x3D\x01\x01\x01\x03" +OBJ_camellia_256_cbc="\x2A\x83\x08\x8C\x9A\x4B\x3D\x01\x01\x01\x04" +OBJ_camellia_128_ecb="\x03\xA2\x31\x05\x03\x01\x09\x01" +OBJ_camellia_192_ecb="\x03\xA2\x31\x05\x03\x01\x09\x15" +OBJ_camellia_256_ecb="\x03\xA2\x31\x05\x03\x01\x09\x29" +OBJ_camellia_128_cfb128="\x03\xA2\x31\x05\x03\x01\x09\x04" +OBJ_camellia_192_cfb128="\x03\xA2\x31\x05\x03\x01\x09\x18" +OBJ_camellia_256_cfb128="\x03\xA2\x31\x05\x03\x01\x09\x2C" +OBJ_camellia_128_ofb128="\x03\xA2\x31\x05\x03\x01\x09\x03" +OBJ_camellia_192_ofb128="\x03\xA2\x31\x05\x03\x01\x09\x17" +OBJ_camellia_256_ofb128="\x03\xA2\x31\x05\x03\x01\x09\x2B" +OBJ_subject_directory_attributes="\x55\x1D\x09" +OBJ_issuing_distribution_point="\x55\x1D\x1C" +OBJ_certificate_issuer="\x55\x1D\x1D" +OBJ_kisa="\x2A\x83\x1A\x8C\x9A\x44" +OBJ_seed_ecb="\x2A\x83\x1A\x8C\x9A\x44\x01\x03" +OBJ_seed_cbc="\x2A\x83\x1A\x8C\x9A\x44\x01\x04" +OBJ_seed_ofb128="\x2A\x83\x1A\x8C\x9A\x44\x01\x06" +OBJ_seed_cfb128="\x2A\x83\x1A\x8C\x9A\x44\x01\x05" +OBJ_hmac_md5="\x2B\x06\x01\x05\x05\x08\x01\x01" +OBJ_hmac_sha1="\x2B\x06\x01\x05\x05\x08\x01\x02" +OBJ_id_PasswordBasedMAC="\x2A\x86\x48\x86\xF6\x7D\x07\x42\x0D" +OBJ_id_DHBasedMac="\x2A\x86\x48\x86\xF6\x7D\x07\x42\x1E" +OBJ_id_it_suppLangTags="\x2B\x06\x01\x05\x05\x07\x04\x10" +OBJ_caRepository="\x2B\x06\x01\x05\x05\x07\x30\x05" +OBJ_id_smime_ct_compressedData="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x01\x09" +OBJ_id_ct_asciiTextWithCRLF="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x01\x1B" +OBJ_id_aes128_wrap="\x60\x86\x48\x01\x65\x03\x04\x01\x05" +OBJ_id_aes192_wrap="\x60\x86\x48\x01\x65\x03\x04\x01\x19" +OBJ_id_aes256_wrap="\x60\x86\x48\x01\x65\x03\x04\x01\x2D" +OBJ_ecdsa_with_Recommended="\x2A\x86\x48\xCE\x3D\x04\x02" +OBJ_ecdsa_with_Specified="\x2A\x86\x48\xCE\x3D\x04\x03" +OBJ_ecdsa_with_SHA224="\x2A\x86\x48\xCE\x3D\x04\x03\x01" +OBJ_ecdsa_with_SHA256="\x2A\x86\x48\xCE\x3D\x04\x03\x02" +OBJ_ecdsa_with_SHA384="\x2A\x86\x48\xCE\x3D\x04\x03\x03" +OBJ_ecdsa_with_SHA512="\x2A\x86\x48\xCE\x3D\x04\x03\x04" +OBJ_hmacWithMD5="\x2A\x86\x48\x86\xF7\x0D\x02\x06" +OBJ_hmacWithSHA224="\x2A\x86\x48\x86\xF7\x0D\x02\x08" +OBJ_hmacWithSHA256="\x2A\x86\x48\x86\xF7\x0D\x02\x09" +OBJ_hmacWithSHA384="\x2A\x86\x48\x86\xF7\x0D\x02\x0A" +OBJ_hmacWithSHA512="\x2A\x86\x48\x86\xF7\x0D\x02\x0B" +OBJ_dsa_with_SHA224="\x60\x86\x48\x01\x65\x03\x04\x03\x01" +OBJ_dsa_with_SHA256="\x60\x86\x48\x01\x65\x03\x04\x03\x02" +OBJ_whirlpool="\x28\xCF\x06\x03\x00\x37" +OBJ_cryptopro="\x2A\x85\x03\x02\x02" +OBJ_cryptocom="\x2A\x85\x03\x02\x09" +OBJ_id_GostR3411_94_with_GostR3410_2001="\x2A\x85\x03\x02\x02\x03" +OBJ_id_GostR3411_94_with_GostR3410_94="\x2A\x85\x03\x02\x02\x04" +OBJ_id_GostR3411_94="\x2A\x85\x03\x02\x02\x09" +OBJ_id_HMACGostR3411_94="\x2A\x85\x03\x02\x02\x0A" +OBJ_id_GostR3410_2001="\x2A\x85\x03\x02\x02\x13" +OBJ_id_GostR3410_94="\x2A\x85\x03\x02\x02\x14" +OBJ_id_Gost28147_89="\x2A\x85\x03\x02\x02\x15" +OBJ_id_Gost28147_89_MAC="\x2A\x85\x03\x02\x02\x16" +OBJ_id_GostR3411_94_prf="\x2A\x85\x03\x02\x02\x17" +OBJ_id_GostR3410_2001DH="\x2A\x85\x03\x02\x02\x62" +OBJ_id_GostR3410_94DH="\x2A\x85\x03\x02\x02\x63" +OBJ_id_Gost28147_89_CryptoPro_KeyMeshing="\x2A\x85\x03\x02\x02\x0E\x01" +OBJ_id_Gost28147_89_None_KeyMeshing="\x2A\x85\x03\x02\x02\x0E\x00" +OBJ_id_GostR3411_94_TestParamSet="\x2A\x85\x03\x02\x02\x1E\x00" +OBJ_id_GostR3411_94_CryptoProParamSet="\x2A\x85\x03\x02\x02\x1E\x01" +OBJ_id_Gost28147_89_TestParamSet="\x2A\x85\x03\x02\x02\x1F\x00" +OBJ_id_Gost28147_89_CryptoPro_A_ParamSet="\x2A\x85\x03\x02\x02\x1F\x01" +OBJ_id_Gost28147_89_CryptoPro_B_ParamSet="\x2A\x85\x03\x02\x02\x1F\x02" +OBJ_id_Gost28147_89_CryptoPro_C_ParamSet="\x2A\x85\x03\x02\x02\x1F\x03" +OBJ_id_Gost28147_89_CryptoPro_D_ParamSet="\x2A\x85\x03\x02\x02\x1F\x04" +OBJ_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet="\x2A\x85\x03\x02\x02\x1F\x05" +OBJ_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet="\x2A\x85\x03\x02\x02\x1F\x06" +OBJ_id_Gost28147_89_CryptoPro_RIC_1_ParamSet="\x2A\x85\x03\x02\x02\x1F\x07" +OBJ_id_GostR3410_94_TestParamSet="\x2A\x85\x03\x02\x02\x20\x00" +OBJ_id_GostR3410_94_CryptoPro_A_ParamSet="\x2A\x85\x03\x02\x02\x20\x02" +OBJ_id_GostR3410_94_CryptoPro_B_ParamSet="\x2A\x85\x03\x02\x02\x20\x03" +OBJ_id_GostR3410_94_CryptoPro_C_ParamSet="\x2A\x85\x03\x02\x02\x20\x04" +OBJ_id_GostR3410_94_CryptoPro_D_ParamSet="\x2A\x85\x03\x02\x02\x20\x05" +OBJ_id_GostR3410_94_CryptoPro_XchA_ParamSet="\x2A\x85\x03\x02\x02\x21\x01" +OBJ_id_GostR3410_94_CryptoPro_XchB_ParamSet="\x2A\x85\x03\x02\x02\x21\x02" +OBJ_id_GostR3410_94_CryptoPro_XchC_ParamSet="\x2A\x85\x03\x02\x02\x21\x03" +OBJ_id_GostR3410_2001_TestParamSet="\x2A\x85\x03\x02\x02\x23\x00" +OBJ_id_GostR3410_2001_CryptoPro_A_ParamSet="\x2A\x85\x03\x02\x02\x23\x01" +OBJ_id_GostR3410_2001_CryptoPro_B_ParamSet="\x2A\x85\x03\x02\x02\x23\x02" +OBJ_id_GostR3410_2001_CryptoPro_C_ParamSet="\x2A\x85\x03\x02\x02\x23\x03" +OBJ_id_GostR3410_2001_CryptoPro_XchA_ParamSet="\x2A\x85\x03\x02\x02\x24\x00" +OBJ_id_GostR3410_2001_CryptoPro_XchB_ParamSet="\x2A\x85\x03\x02\x02\x24\x01" +OBJ_id_GostR3410_94_a="\x2A\x85\x03\x02\x02\x14\x01" +OBJ_id_GostR3410_94_aBis="\x2A\x85\x03\x02\x02\x14\x02" +OBJ_id_GostR3410_94_b="\x2A\x85\x03\x02\x02\x14\x03" +OBJ_id_GostR3410_94_bBis="\x2A\x85\x03\x02\x02\x14\x04" +OBJ_id_Gost28147_89_cc="\x2A\x85\x03\x02\x09\x01\x06\x01" +OBJ_id_GostR3410_94_cc="\x2A\x85\x03\x02\x09\x01\x05\x03" +OBJ_id_GostR3410_2001_cc="\x2A\x85\x03\x02\x09\x01\x05\x04" +OBJ_id_GostR3411_94_with_GostR3410_94_cc="\x2A\x85\x03\x02\x09\x01\x03\x03" +OBJ_id_GostR3411_94_with_GostR3410_2001_cc="\x2A\x85\x03\x02\x09\x01\x03\x04" +OBJ_id_GostR3410_2001_ParamSet_cc="\x2A\x85\x03\x02\x09\x01\x08\x01" +OBJ_LocalKeySet="\x2B\x06\x01\x04\x01\x82\x37\x11\x02" +OBJ_freshest_crl="\x55\x1D\x2E" +OBJ_id_on_permanentIdentifier="\x2B\x06\x01\x05\x05\x07\x08\x03" +OBJ_searchGuide="\x55\x04\x0E" +OBJ_businessCategory="\x55\x04\x0F" +OBJ_postalAddress="\x55\x04\x10" +OBJ_postOfficeBox="\x55\x04\x12" +OBJ_physicalDeliveryOfficeName="\x55\x04\x13" +OBJ_telephoneNumber="\x55\x04\x14" +OBJ_telexNumber="\x55\x04\x15" +OBJ_teletexTerminalIdentifier="\x55\x04\x16" +OBJ_facsimileTelephoneNumber="\x55\x04\x17" +OBJ_x121Address="\x55\x04\x18" +OBJ_internationaliSDNNumber="\x55\x04\x19" +OBJ_registeredAddress="\x55\x04\x1A" +OBJ_destinationIndicator="\x55\x04\x1B" +OBJ_preferredDeliveryMethod="\x55\x04\x1C" +OBJ_presentationAddress="\x55\x04\x1D" +OBJ_supportedApplicationContext="\x55\x04\x1E" +OBJ_member="\x55\x04\x1F" +OBJ_owner="\x55\x04\x20" +OBJ_roleOccupant="\x55\x04\x21" +OBJ_seeAlso="\x55\x04\x22" +OBJ_userPassword="\x55\x04\x23" +OBJ_userCertificate="\x55\x04\x24" +OBJ_cACertificate="\x55\x04\x25" +OBJ_authorityRevocationList="\x55\x04\x26" +OBJ_certificateRevocationList="\x55\x04\x27" +OBJ_crossCertificatePair="\x55\x04\x28" +OBJ_enhancedSearchGuide="\x55\x04\x2F" +OBJ_protocolInformation="\x55\x04\x30" +OBJ_distinguishedName="\x55\x04\x31" +OBJ_uniqueMember="\x55\x04\x32" +OBJ_houseIdentifier="\x55\x04\x33" +OBJ_supportedAlgorithms="\x55\x04\x34" +OBJ_deltaRevocationList="\x55\x04\x35" +OBJ_dmdName="\x55\x04\x36" +OBJ_id_alg_PWRI_KEK="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x03\x09" +OBJ_aes_128_gcm="\x60\x86\x48\x01\x65\x03\x04\x01\x06" +OBJ_aes_128_ccm="\x60\x86\x48\x01\x65\x03\x04\x01\x07" +OBJ_id_aes128_wrap_pad="\x60\x86\x48\x01\x65\x03\x04\x01\x08" +OBJ_aes_192_gcm="\x60\x86\x48\x01\x65\x03\x04\x01\x1A" +OBJ_aes_192_ccm="\x60\x86\x48\x01\x65\x03\x04\x01\x1B" +OBJ_id_aes192_wrap_pad="\x60\x86\x48\x01\x65\x03\x04\x01\x1C" +OBJ_aes_256_gcm="\x60\x86\x48\x01\x65\x03\x04\x01\x2E" +OBJ_aes_256_ccm="\x60\x86\x48\x01\x65\x03\x04\x01\x2F" +OBJ_id_aes256_wrap_pad="\x60\x86\x48\x01\x65\x03\x04\x01\x30" +OBJ_id_camellia128_wrap="\x2A\x83\x08\x8C\x9A\x4B\x3D\x01\x01\x03\x02" +OBJ_id_camellia192_wrap="\x2A\x83\x08\x8C\x9A\x4B\x3D\x01\x01\x03\x03" +OBJ_id_camellia256_wrap="\x2A\x83\x08\x8C\x9A\x4B\x3D\x01\x01\x03\x04" +OBJ_anyExtendedKeyUsage="\x55\x1D\x25\x00" +OBJ_mgf1="\x2A\x86\x48\x86\xF7\x0D\x01\x01\x08" +OBJ_rsassaPss="\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0A" +OBJ_aes_128_xts="\x2B\x6F\x02\x8C\x53\x00\x01\x01" +OBJ_aes_256_xts="\x2B\x6F\x02\x8C\x53\x00\x01\x02" +OBJ_rsaesOaep="\x2A\x86\x48\x86\xF7\x0D\x01\x01\x07" +OBJ_dhpublicnumber="\x2A\x86\x48\xCE\x3E\x02\x01" +OBJ_brainpoolP160r1="\x2B\x24\x03\x03\x02\x08\x01\x01\x01" +OBJ_brainpoolP160t1="\x2B\x24\x03\x03\x02\x08\x01\x01\x02" +OBJ_brainpoolP192r1="\x2B\x24\x03\x03\x02\x08\x01\x01\x03" +OBJ_brainpoolP192t1="\x2B\x24\x03\x03\x02\x08\x01\x01\x04" +OBJ_brainpoolP224r1="\x2B\x24\x03\x03\x02\x08\x01\x01\x05" +OBJ_brainpoolP224t1="\x2B\x24\x03\x03\x02\x08\x01\x01\x06" +OBJ_brainpoolP256r1="\x2B\x24\x03\x03\x02\x08\x01\x01\x07" +OBJ_brainpoolP256t1="\x2B\x24\x03\x03\x02\x08\x01\x01\x08" +OBJ_brainpoolP320r1="\x2B\x24\x03\x03\x02\x08\x01\x01\x09" +OBJ_brainpoolP320t1="\x2B\x24\x03\x03\x02\x08\x01\x01\x0A" +OBJ_brainpoolP384r1="\x2B\x24\x03\x03\x02\x08\x01\x01\x0B" +OBJ_brainpoolP384t1="\x2B\x24\x03\x03\x02\x08\x01\x01\x0C" +OBJ_brainpoolP512r1="\x2B\x24\x03\x03\x02\x08\x01\x01\x0D" +OBJ_brainpoolP512t1="\x2B\x24\x03\x03\x02\x08\x01\x01\x0E" +OBJ_pSpecified="\x2A\x86\x48\x86\xF7\x0D\x01\x01\x09" +OBJ_dhSinglePass_stdDH_sha1kdf_scheme="\x2B\x81\x05\x10\x86\x48\x3F\x00\x02" +OBJ_dhSinglePass_stdDH_sha224kdf_scheme="\x2B\x81\x04\x01\x0B\x00" +OBJ_dhSinglePass_stdDH_sha256kdf_scheme="\x2B\x81\x04\x01\x0B\x01" +OBJ_dhSinglePass_stdDH_sha384kdf_scheme="\x2B\x81\x04\x01\x0B\x02" +OBJ_dhSinglePass_stdDH_sha512kdf_scheme="\x2B\x81\x04\x01\x0B\x03" +OBJ_dhSinglePass_cofactorDH_sha1kdf_scheme="\x2B\x81\x05\x10\x86\x48\x3F\x00\x03" +OBJ_dhSinglePass_cofactorDH_sha224kdf_scheme="\x2B\x81\x04\x01\x0E\x00" +OBJ_dhSinglePass_cofactorDH_sha256kdf_scheme="\x2B\x81\x04\x01\x0E\x01" +OBJ_dhSinglePass_cofactorDH_sha384kdf_scheme="\x2B\x81\x04\x01\x0E\x02" +OBJ_dhSinglePass_cofactorDH_sha512kdf_scheme="\x2B\x81\x04\x01\x0E\x03" +OBJ_ct_precert_scts="\x2B\x06\x01\x04\x01\xD6\x79\x02\x04\x02" +OBJ_ct_precert_poison="\x2B\x06\x01\x04\x01\xD6\x79\x02\x04\x03" +OBJ_ct_precert_signer="\x2B\x06\x01\x04\x01\xD6\x79\x02\x04\x04" +OBJ_ct_cert_scts="\x2B\x06\x01\x04\x01\xD6\x79\x02\x04\x05" +OBJ_jurisdictionLocalityName="\x2B\x06\x01\x04\x01\x82\x37\x3C\x02\x01\x01" +OBJ_jurisdictionStateOrProvinceName="\x2B\x06\x01\x04\x01\x82\x37\x3C\x02\x01\x02" +OBJ_jurisdictionCountryName="\x2B\x06\x01\x04\x01\x82\x37\x3C\x02\x01\x03" +OBJ_camellia_128_gcm="\x03\xA2\x31\x05\x03\x01\x09\x06" +OBJ_camellia_128_ccm="\x03\xA2\x31\x05\x03\x01\x09\x07" +OBJ_camellia_128_ctr="\x03\xA2\x31\x05\x03\x01\x09\x09" +OBJ_camellia_128_cmac="\x03\xA2\x31\x05\x03\x01\x09\x0A" +OBJ_camellia_192_gcm="\x03\xA2\x31\x05\x03\x01\x09\x1A" +OBJ_camellia_192_ccm="\x03\xA2\x31\x05\x03\x01\x09\x1B" +OBJ_camellia_192_ctr="\x03\xA2\x31\x05\x03\x01\x09\x1D" +OBJ_camellia_192_cmac="\x03\xA2\x31\x05\x03\x01\x09\x1E" +OBJ_camellia_256_gcm="\x03\xA2\x31\x05\x03\x01\x09\x2E" +OBJ_camellia_256_ccm="\x03\xA2\x31\x05\x03\x01\x09\x2F" +OBJ_camellia_256_ctr="\x03\xA2\x31\x05\x03\x01\x09\x31" +OBJ_camellia_256_cmac="\x03\xA2\x31\x05\x03\x01\x09\x32" +OBJ_id_scrypt="\x2B\x06\x01\x04\x01\xDA\x47\x04\x0B" +OBJ_id_tc26="\x2A\x85\x03\x07\x01" +OBJ_id_tc26_algorithms="\x2A\x85\x03\x07\x01\x01" +OBJ_id_tc26_sign="\x2A\x85\x03\x07\x01\x01\x01" +OBJ_id_GostR3410_2012_256="\x2A\x85\x03\x07\x01\x01\x01\x01" +OBJ_id_GostR3410_2012_512="\x2A\x85\x03\x07\x01\x01\x01\x02" +OBJ_id_tc26_digest="\x2A\x85\x03\x07\x01\x01\x02" +OBJ_id_GostR3411_2012_256="\x2A\x85\x03\x07\x01\x01\x02\x02" +OBJ_id_GostR3411_2012_512="\x2A\x85\x03\x07\x01\x01\x02\x03" +OBJ_id_tc26_signwithdigest="\x2A\x85\x03\x07\x01\x01\x03" +OBJ_id_tc26_signwithdigest_gost3410_2012_256="\x2A\x85\x03\x07\x01\x01\x03\x02" +OBJ_id_tc26_signwithdigest_gost3410_2012_512="\x2A\x85\x03\x07\x01\x01\x03\x03" +OBJ_id_tc26_mac="\x2A\x85\x03\x07\x01\x01\x04" +OBJ_id_tc26_hmac_gost_3411_2012_256="\x2A\x85\x03\x07\x01\x01\x04\x01" +OBJ_id_tc26_hmac_gost_3411_2012_512="\x2A\x85\x03\x07\x01\x01\x04\x02" +OBJ_id_tc26_cipher="\x2A\x85\x03\x07\x01\x01\x05" +OBJ_id_tc26_agreement="\x2A\x85\x03\x07\x01\x01\x06" +OBJ_id_tc26_agreement_gost_3410_2012_256="\x2A\x85\x03\x07\x01\x01\x06\x01" +OBJ_id_tc26_agreement_gost_3410_2012_512="\x2A\x85\x03\x07\x01\x01\x06\x02" +OBJ_id_tc26_constants="\x2A\x85\x03\x07\x01\x02" +OBJ_id_tc26_sign_constants="\x2A\x85\x03\x07\x01\x02\x01" +OBJ_id_tc26_gost_3410_2012_512_constants="\x2A\x85\x03\x07\x01\x02\x01\x02" +OBJ_id_tc26_gost_3410_2012_512_paramSetTest="\x2A\x85\x03\x07\x01\x02\x01\x02\x00" +OBJ_id_tc26_gost_3410_2012_512_paramSetA="\x2A\x85\x03\x07\x01\x02\x01\x02\x01" +OBJ_id_tc26_gost_3410_2012_512_paramSetB="\x2A\x85\x03\x07\x01\x02\x01\x02\x02" +OBJ_id_tc26_digest_constants="\x2A\x85\x03\x07\x01\x02\x02" +OBJ_id_tc26_cipher_constants="\x2A\x85\x03\x07\x01\x02\x05" +OBJ_id_tc26_gost_28147_constants="\x2A\x85\x03\x07\x01\x02\x05\x01" +OBJ_id_tc26_gost_28147_param_Z="\x2A\x85\x03\x07\x01\x02\x05\x01\x01" +OBJ_INN="\x2A\x85\x03\x03\x81\x03\x01\x01" +OBJ_OGRN="\x2A\x85\x03\x64\x01" +OBJ_SNILS="\x2A\x85\x03\x64\x03" +OBJ_subjectSignTool="\x2A\x85\x03\x64\x6F" +OBJ_issuerSignTool="\x2A\x85\x03\x64\x70" +OBJ_tlsfeature="\x2B\x06\x01\x05\x05\x07\x01\x18" +OBJ_ipsec_IKE="\x2B\x06\x01\x05\x05\x07\x03\x11" +OBJ_capwapAC="\x2B\x06\x01\x05\x05\x07\x03\x12" +OBJ_capwapWTP="\x2B\x06\x01\x05\x05\x07\x03\x13" +OBJ_sshClient="\x2B\x06\x01\x05\x05\x07\x03\x15" +OBJ_sshServer="\x2B\x06\x01\x05\x05\x07\x03\x16" +OBJ_sendRouter="\x2B\x06\x01\x05\x05\x07\x03\x17" +OBJ_sendProxiedRouter="\x2B\x06\x01\x05\x05\x07\x03\x18" +OBJ_sendOwner="\x2B\x06\x01\x05\x05\x07\x03\x19" +OBJ_sendProxiedOwner="\x2B\x06\x01\x05\x05\x07\x03\x1A" +OBJ_id_pkinit="\x2B\x06\x01\x05\x02\x03" +OBJ_pkInitClientAuth="\x2B\x06\x01\x05\x02\x03\x04" +OBJ_pkInitKDC="\x2B\x06\x01\x05\x02\x03\x05" +OBJ_X25519="\x2B\x65\x6E" +OBJ_X448="\x2B\x65\x6F" +OBJ_blake2b512="\x2B\x06\x01\x04\x01\x8D\x3A\x0C\x02\x01\x10" +OBJ_blake2s256="\x2B\x06\x01\x04\x01\x8D\x3A\x0C\x02\x02\x08" +OBJ_id_smime_ct_contentCollection="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x01\x13" +OBJ_id_smime_ct_authEnvelopedData="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x01\x17" +OBJ_id_ct_xml="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x01\x1C" +OBJ_aria_128_ecb="\x2A\x83\x1A\x8C\x9A\x6E\x01\x01\x01" +OBJ_aria_128_cbc="\x2A\x83\x1A\x8C\x9A\x6E\x01\x01\x02" +OBJ_aria_128_cfb128="\x2A\x83\x1A\x8C\x9A\x6E\x01\x01\x03" +OBJ_aria_128_ofb128="\x2A\x83\x1A\x8C\x9A\x6E\x01\x01\x04" +OBJ_aria_128_ctr="\x2A\x83\x1A\x8C\x9A\x6E\x01\x01\x05" +OBJ_aria_192_ecb="\x2A\x83\x1A\x8C\x9A\x6E\x01\x01\x06" +OBJ_aria_192_cbc="\x2A\x83\x1A\x8C\x9A\x6E\x01\x01\x07" +OBJ_aria_192_cfb128="\x2A\x83\x1A\x8C\x9A\x6E\x01\x01\x08" +OBJ_aria_192_ofb128="\x2A\x83\x1A\x8C\x9A\x6E\x01\x01\x09" +OBJ_aria_192_ctr="\x2A\x83\x1A\x8C\x9A\x6E\x01\x01\x0A" +OBJ_aria_256_ecb="\x2A\x83\x1A\x8C\x9A\x6E\x01\x01\x0B" +OBJ_aria_256_cbc="\x2A\x83\x1A\x8C\x9A\x6E\x01\x01\x0C" +OBJ_aria_256_cfb128="\x2A\x83\x1A\x8C\x9A\x6E\x01\x01\x0D" +OBJ_aria_256_ofb128="\x2A\x83\x1A\x8C\x9A\x6E\x01\x01\x0E" +OBJ_aria_256_ctr="\x2A\x83\x1A\x8C\x9A\x6E\x01\x01\x0F" +OBJ_id_smime_aa_signingCertificateV2="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x2F" +OBJ_ED25519="\x2B\x65\x70" +OBJ_ED448="\x2B\x65\x71" +OBJ_organizationIdentifier="\x55\x04\x61" +OBJ_countryCode3c="\x55\x04\x62" +OBJ_countryCode3n="\x55\x04\x63" +OBJ_dnsName="\x55\x04\x64" +OBJ_x509ExtAdmission="\x2B\x24\x08\x03\x03" +OBJ_sha512_224="\x60\x86\x48\x01\x65\x03\x04\x02\x05" +OBJ_sha512_256="\x60\x86\x48\x01\x65\x03\x04\x02\x06" +OBJ_sha3_224="\x60\x86\x48\x01\x65\x03\x04\x02\x07" +OBJ_sha3_256="\x60\x86\x48\x01\x65\x03\x04\x02\x08" +OBJ_sha3_384="\x60\x86\x48\x01\x65\x03\x04\x02\x09" +OBJ_sha3_512="\x60\x86\x48\x01\x65\x03\x04\x02\x0A" +OBJ_shake128="\x60\x86\x48\x01\x65\x03\x04\x02\x0B" +OBJ_shake256="\x60\x86\x48\x01\x65\x03\x04\x02\x0C" +OBJ_hmac_sha3_224="\x60\x86\x48\x01\x65\x03\x04\x02\x0D" +OBJ_hmac_sha3_256="\x60\x86\x48\x01\x65\x03\x04\x02\x0E" +OBJ_hmac_sha3_384="\x60\x86\x48\x01\x65\x03\x04\x02\x0F" +OBJ_hmac_sha3_512="\x60\x86\x48\x01\x65\x03\x04\x02\x10" +OBJ_dsa_with_SHA384="\x60\x86\x48\x01\x65\x03\x04\x03\x03" +OBJ_dsa_with_SHA512="\x60\x86\x48\x01\x65\x03\x04\x03\x04" +OBJ_dsa_with_SHA3_224="\x60\x86\x48\x01\x65\x03\x04\x03\x05" +OBJ_dsa_with_SHA3_256="\x60\x86\x48\x01\x65\x03\x04\x03\x06" +OBJ_dsa_with_SHA3_384="\x60\x86\x48\x01\x65\x03\x04\x03\x07" +OBJ_dsa_with_SHA3_512="\x60\x86\x48\x01\x65\x03\x04\x03\x08" +OBJ_ecdsa_with_SHA3_224="\x60\x86\x48\x01\x65\x03\x04\x03\x09" +OBJ_ecdsa_with_SHA3_256="\x60\x86\x48\x01\x65\x03\x04\x03\x0A" +OBJ_ecdsa_with_SHA3_384="\x60\x86\x48\x01\x65\x03\x04\x03\x0B" +OBJ_ecdsa_with_SHA3_512="\x60\x86\x48\x01\x65\x03\x04\x03\x0C" +OBJ_RSA_SHA3_224="\x60\x86\x48\x01\x65\x03\x04\x03\x0D" +OBJ_RSA_SHA3_256="\x60\x86\x48\x01\x65\x03\x04\x03\x0E" +OBJ_RSA_SHA3_384="\x60\x86\x48\x01\x65\x03\x04\x03\x0F" +OBJ_RSA_SHA3_512="\x60\x86\x48\x01\x65\x03\x04\x03\x10" +OBJ_aria_128_ccm="\x2A\x83\x1A\x8C\x9A\x6E\x01\x01\x25" +OBJ_aria_192_ccm="\x2A\x83\x1A\x8C\x9A\x6E\x01\x01\x26" +OBJ_aria_256_ccm="\x2A\x83\x1A\x8C\x9A\x6E\x01\x01\x27" +OBJ_aria_128_gcm="\x2A\x83\x1A\x8C\x9A\x6E\x01\x01\x22" +OBJ_aria_192_gcm="\x2A\x83\x1A\x8C\x9A\x6E\x01\x01\x23" +OBJ_aria_256_gcm="\x2A\x83\x1A\x8C\x9A\x6E\x01\x01\x24" +OBJ_cmcCA="\x2B\x06\x01\x05\x05\x07\x03\x1B" +OBJ_cmcRA="\x2B\x06\x01\x05\x05\x07\x03\x1C" +OBJ_sm4_ecb="\x2A\x81\x1C\xCF\x55\x01\x68\x01" +OBJ_sm4_cbc="\x2A\x81\x1C\xCF\x55\x01\x68\x02" +OBJ_sm4_ofb128="\x2A\x81\x1C\xCF\x55\x01\x68\x03" +OBJ_sm4_cfb1="\x2A\x81\x1C\xCF\x55\x01\x68\x05" +OBJ_sm4_cfb128="\x2A\x81\x1C\xCF\x55\x01\x68\x04" +OBJ_sm4_cfb8="\x2A\x81\x1C\xCF\x55\x01\x68\x06" +OBJ_sm4_ctr="\x2A\x81\x1C\xCF\x55\x01\x68\x07" +OBJ_ISO_CN="\x2A\x81\x1C" +OBJ_oscca="\x2A\x81\x1C\xCF\x55" +OBJ_sm_scheme="\x2A\x81\x1C\xCF\x55\x01" +OBJ_sm3="\x2A\x81\x1C\xCF\x55\x01\x83\x11" +OBJ_sm3WithRSAEncryption="\x2A\x81\x1C\xCF\x55\x01\x83\x78" +OBJ_sha512_224WithRSAEncryption="\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0F" +OBJ_sha512_256WithRSAEncryption="\x2A\x86\x48\x86\xF7\x0D\x01\x01\x10" +OBJ_id_tc26_gost_3410_2012_256_constants="\x2A\x85\x03\x07\x01\x02\x01\x01" +OBJ_id_tc26_gost_3410_2012_256_paramSetA="\x2A\x85\x03\x07\x01\x02\x01\x01\x01" +OBJ_id_tc26_gost_3410_2012_512_paramSetC="\x2A\x85\x03\x07\x01\x02\x01\x02\x03" +OBJ_ISO_UA="\x2A\x86\x24" +OBJ_ua_pki="\x2A\x86\x24\x02\x01\x01\x01" +OBJ_dstu28147="\x2A\x86\x24\x02\x01\x01\x01\x01\x01\x01" +OBJ_dstu28147_ofb="\x2A\x86\x24\x02\x01\x01\x01\x01\x01\x01\x02" +OBJ_dstu28147_cfb="\x2A\x86\x24\x02\x01\x01\x01\x01\x01\x01\x03" +OBJ_dstu28147_wrap="\x2A\x86\x24\x02\x01\x01\x01\x01\x01\x01\x05" +OBJ_hmacWithDstu34311="\x2A\x86\x24\x02\x01\x01\x01\x01\x01\x02" +OBJ_dstu34311="\x2A\x86\x24\x02\x01\x01\x01\x01\x02\x01" +OBJ_dstu4145le="\x2A\x86\x24\x02\x01\x01\x01\x01\x03\x01\x01" +OBJ_dstu4145be="\x2A\x86\x24\x02\x01\x01\x01\x01\x03\x01\x01\x01\x01" +OBJ_uacurve0="\x2A\x86\x24\x02\x01\x01\x01\x01\x03\x01\x01\x02\x00" +OBJ_uacurve1="\x2A\x86\x24\x02\x01\x01\x01\x01\x03\x01\x01\x02\x01" +OBJ_uacurve2="\x2A\x86\x24\x02\x01\x01\x01\x01\x03\x01\x01\x02\x02" +OBJ_uacurve3="\x2A\x86\x24\x02\x01\x01\x01\x01\x03\x01\x01\x02\x03" +OBJ_uacurve4="\x2A\x86\x24\x02\x01\x01\x01\x01\x03\x01\x01\x02\x04" +OBJ_uacurve5="\x2A\x86\x24\x02\x01\x01\x01\x01\x03\x01\x01\x02\x05" +OBJ_uacurve6="\x2A\x86\x24\x02\x01\x01\x01\x01\x03\x01\x01\x02\x06" +OBJ_uacurve7="\x2A\x86\x24\x02\x01\x01\x01\x01\x03\x01\x01\x02\x07" +OBJ_uacurve8="\x2A\x86\x24\x02\x01\x01\x01\x01\x03\x01\x01\x02\x08" +OBJ_uacurve9="\x2A\x86\x24\x02\x01\x01\x01\x01\x03\x01\x01\x02\x09" +OBJ_ieee="\x2B\x6F" +OBJ_ieee_siswg="\x2B\x6F\x02\x8C\x53" +OBJ_sm2="\x2A\x81\x1C\xCF\x55\x01\x82\x2D" +OBJ_id_tc26_cipher_gostr3412_2015_magma="\x2A\x85\x03\x07\x01\x01\x05\x01" +OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm="\x2A\x85\x03\x07\x01\x01\x05\x01\x01" +OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac="\x2A\x85\x03\x07\x01\x01\x05\x01\x02" +OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik="\x2A\x85\x03\x07\x01\x01\x05\x02" +OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm="\x2A\x85\x03\x07\x01\x01\x05\x02\x01" +OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac="\x2A\x85\x03\x07\x01\x01\x05\x02\x02" +OBJ_id_tc26_wrap="\x2A\x85\x03\x07\x01\x01\x07" +OBJ_id_tc26_wrap_gostr3412_2015_magma="\x2A\x85\x03\x07\x01\x01\x07\x01" +OBJ_id_tc26_wrap_gostr3412_2015_magma_kexp15="\x2A\x85\x03\x07\x01\x01\x07\x01\x01" +OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik="\x2A\x85\x03\x07\x01\x01\x07\x02" +OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15="\x2A\x85\x03\x07\x01\x01\x07\x01\x01" +OBJ_id_tc26_gost_3410_2012_256_paramSetB="\x2A\x85\x03\x07\x01\x02\x01\x01\x02" +OBJ_id_tc26_gost_3410_2012_256_paramSetC="\x2A\x85\x03\x07\x01\x02\x01\x01\x03" +OBJ_id_tc26_gost_3410_2012_256_paramSetD="\x2A\x85\x03\x07\x01\x02\x01\x01\x04" +OBJ_hmacWithSHA512_224="\x2A\x86\x48\x86\xF7\x0D\x02\x0C" +OBJ_hmacWithSHA512_256="\x2A\x86\x48\x86\xF7\x0D\x02\x0D" diff --git a/trunk/3rdparty/openssl-1.1-fit/fuzz/rand.inc b/trunk/3rdparty/openssl-1.1-fit/fuzz/rand.inc new file mode 100644 index 000000000..f8b3277b9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/fuzz/rand.inc @@ -0,0 +1,40 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL licenses, (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * https://www.openssl.org/source/license.html + * or in the file LICENSE in the source distribution. + */ +#include + +static int fuzz_bytes(unsigned char *buf, int num) +{ + unsigned char val = 1; + + while (--num >= 0) + *buf++ = val++; + return 1; +} + +static int fuzz_status(void) +{ + return 1; +} + +static RAND_METHOD fuzz_rand_method = { + NULL, + fuzz_bytes, + NULL, + NULL, + fuzz_bytes, + fuzz_status +}; + +void FuzzerSetRand(void) +{ + RAND_set_rand_method(&fuzz_rand_method); +} + + diff --git a/trunk/3rdparty/openssl-1.1-fit/fuzz/server.c b/trunk/3rdparty/openssl-1.1-fit/fuzz/server.c new file mode 100644 index 000000000..2d392ac88 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/fuzz/server.c @@ -0,0 +1,650 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL licenses, (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * https://www.openssl.org/source/license.html + * or in the file LICENSE in the source distribution. + */ + +/* Shamelessly copied from BoringSSL and converted to C. */ + +/* Test first part of SSL server handshake. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "fuzzer.h" + +#include "rand.inc" + +static const uint8_t kCertificateDER[] = { + 0x30, 0x82, 0x02, 0xff, 0x30, 0x82, 0x01, 0xe7, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x11, 0x00, 0xb1, 0x84, 0xee, 0x34, 0x99, 0x98, 0x76, 0xfb, + 0x6f, 0xb2, 0x15, 0xc8, 0x47, 0x79, 0x05, 0x9b, 0x30, 0x0d, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, + 0x12, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x07, + 0x41, 0x63, 0x6d, 0x65, 0x20, 0x43, 0x6f, 0x30, 0x1e, 0x17, 0x0d, 0x31, + 0x35, 0x31, 0x31, 0x30, 0x37, 0x30, 0x30, 0x32, 0x34, 0x35, 0x36, 0x5a, + 0x17, 0x0d, 0x31, 0x36, 0x31, 0x31, 0x30, 0x36, 0x30, 0x30, 0x32, 0x34, + 0x35, 0x36, 0x5a, 0x30, 0x12, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, + 0x04, 0x0a, 0x13, 0x07, 0x41, 0x63, 0x6d, 0x65, 0x20, 0x43, 0x6f, 0x30, + 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, + 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xce, 0x47, 0xcb, 0x11, + 0xbb, 0xd2, 0x9d, 0x8e, 0x9e, 0xd2, 0x1e, 0x14, 0xaf, 0xc7, 0xea, 0xb6, + 0xc9, 0x38, 0x2a, 0x6f, 0xb3, 0x7e, 0xfb, 0xbc, 0xfc, 0x59, 0x42, 0xb9, + 0x56, 0xf0, 0x4c, 0x3f, 0xf7, 0x31, 0x84, 0xbe, 0xac, 0x03, 0x9e, 0x71, + 0x91, 0x85, 0xd8, 0x32, 0xbd, 0x00, 0xea, 0xac, 0x65, 0xf6, 0x03, 0xc8, + 0x0f, 0x8b, 0xfd, 0x6e, 0x58, 0x88, 0x04, 0x41, 0x92, 0x74, 0xa6, 0x57, + 0x2e, 0x8e, 0x88, 0xd5, 0x3d, 0xda, 0x14, 0x3e, 0x63, 0x88, 0x22, 0xe3, + 0x53, 0xe9, 0xba, 0x39, 0x09, 0xac, 0xfb, 0xd0, 0x4c, 0xf2, 0x3c, 0x20, + 0xd6, 0x97, 0xe6, 0xed, 0xf1, 0x62, 0x1e, 0xe5, 0xc9, 0x48, 0xa0, 0xca, + 0x2e, 0x3c, 0x14, 0x5a, 0x82, 0xd4, 0xed, 0xb1, 0xe3, 0x43, 0xc1, 0x2a, + 0x59, 0xa5, 0xb9, 0xc8, 0x48, 0xa7, 0x39, 0x23, 0x74, 0xa7, 0x37, 0xb0, + 0x6f, 0xc3, 0x64, 0x99, 0x6c, 0xa2, 0x82, 0xc8, 0xf6, 0xdb, 0x86, 0x40, + 0xce, 0xd1, 0x85, 0x9f, 0xce, 0x69, 0xf4, 0x15, 0x2a, 0x23, 0xca, 0xea, + 0xb7, 0x7b, 0xdf, 0xfb, 0x43, 0x5f, 0xff, 0x7a, 0x49, 0x49, 0x0e, 0xe7, + 0x02, 0x51, 0x45, 0x13, 0xe8, 0x90, 0x64, 0x21, 0x0c, 0x26, 0x2b, 0x5d, + 0xfc, 0xe4, 0xb5, 0x86, 0x89, 0x43, 0x22, 0x4c, 0xf3, 0x3b, 0xf3, 0x09, + 0xc4, 0xa4, 0x10, 0x80, 0xf2, 0x46, 0xe2, 0x46, 0x8f, 0x76, 0x50, 0xbf, + 0xaf, 0x2b, 0x90, 0x1b, 0x78, 0xc7, 0xcf, 0xc1, 0x77, 0xd0, 0xfb, 0xa9, + 0xfb, 0xc9, 0x66, 0x5a, 0xc5, 0x9b, 0x31, 0x41, 0x67, 0x01, 0xbe, 0x33, + 0x10, 0xba, 0x05, 0x58, 0xed, 0x76, 0x53, 0xde, 0x5d, 0xc1, 0xe8, 0xbb, + 0x9f, 0xf1, 0xcd, 0xfb, 0xdf, 0x64, 0x7f, 0xd7, 0x18, 0xab, 0x0f, 0x94, + 0x28, 0x95, 0x4a, 0xcc, 0x6a, 0xa9, 0x50, 0xc7, 0x05, 0x47, 0x10, 0x41, + 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x0e, 0x06, + 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, + 0xa0, 0x30, 0x13, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x0c, 0x30, 0x0a, + 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x30, 0x0c, + 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, + 0x30, 0x19, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, 0x12, 0x30, 0x10, 0x82, + 0x0e, 0x66, 0x75, 0x7a, 0x7a, 0x2e, 0x62, 0x6f, 0x72, 0x69, 0x6e, 0x67, + 0x73, 0x73, 0x6c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x92, + 0xde, 0xef, 0x96, 0x06, 0x7b, 0xff, 0x71, 0x7d, 0x4e, 0xa0, 0x7d, 0xae, + 0xb8, 0x22, 0xb4, 0x2c, 0xf7, 0x96, 0x9c, 0x37, 0x1d, 0x8f, 0xe7, 0xd9, + 0x47, 0xff, 0x3f, 0xe9, 0x35, 0x95, 0x0e, 0xdd, 0xdc, 0x7f, 0xc8, 0x8a, + 0x1e, 0x36, 0x1d, 0x38, 0x47, 0xfc, 0x76, 0xd2, 0x1f, 0x98, 0xa1, 0x36, + 0xac, 0xc8, 0x70, 0x38, 0x0a, 0x3d, 0x51, 0x8d, 0x0f, 0x03, 0x1b, 0xef, + 0x62, 0xa1, 0xcb, 0x2b, 0x4a, 0x8c, 0x12, 0x2b, 0x54, 0x50, 0x9a, 0x6b, + 0xfe, 0xaf, 0xd9, 0xf6, 0xbf, 0x58, 0x11, 0x58, 0x5e, 0xe5, 0x86, 0x1e, + 0x3b, 0x6b, 0x30, 0x7e, 0x72, 0x89, 0xe8, 0x6b, 0x7b, 0xb7, 0xaf, 0xef, + 0x8b, 0xa9, 0x3e, 0xb0, 0xcd, 0x0b, 0xef, 0xb0, 0x0c, 0x96, 0x2b, 0xc5, + 0x3b, 0xd5, 0xf1, 0xc2, 0xae, 0x3a, 0x60, 0xd9, 0x0f, 0x75, 0x37, 0x55, + 0x4d, 0x62, 0xd2, 0xed, 0x96, 0xac, 0x30, 0x6b, 0xda, 0xa1, 0x48, 0x17, + 0x96, 0x23, 0x85, 0x9a, 0x57, 0x77, 0xe9, 0x22, 0xa2, 0x37, 0x03, 0xba, + 0x49, 0x77, 0x40, 0x3b, 0x76, 0x4b, 0xda, 0xc1, 0x04, 0x57, 0x55, 0x34, + 0x22, 0x83, 0x45, 0x29, 0xab, 0x2e, 0x11, 0xff, 0x0d, 0xab, 0x55, 0xb1, + 0xa7, 0x58, 0x59, 0x05, 0x25, 0xf9, 0x1e, 0x3d, 0xb7, 0xac, 0x04, 0x39, + 0x2c, 0xf9, 0xaf, 0xb8, 0x68, 0xfb, 0x8e, 0x35, 0x71, 0x32, 0xff, 0x70, + 0xe9, 0x46, 0x6d, 0x5c, 0x06, 0x90, 0x88, 0x23, 0x48, 0x0c, 0x50, 0xeb, + 0x0a, 0xa9, 0xae, 0xe8, 0xfc, 0xbe, 0xa5, 0x76, 0x94, 0xd7, 0x64, 0x22, + 0x38, 0x98, 0x17, 0xa4, 0x3a, 0xa7, 0x59, 0x9f, 0x1d, 0x3b, 0x75, 0x90, + 0x1a, 0x81, 0xef, 0x19, 0xfb, 0x2b, 0xb7, 0xa7, 0x64, 0x61, 0x22, 0xa4, + 0x6f, 0x7b, 0xfa, 0x58, 0xbb, 0x8c, 0x4e, 0x77, 0x67, 0xd0, 0x5d, 0x58, + 0x76, 0x8a, 0xbb, +}; + +static const uint8_t kRSAPrivateKeyDER[] = { + 0x30, 0x82, 0x04, 0xa5, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, + 0xce, 0x47, 0xcb, 0x11, 0xbb, 0xd2, 0x9d, 0x8e, 0x9e, 0xd2, 0x1e, 0x14, + 0xaf, 0xc7, 0xea, 0xb6, 0xc9, 0x38, 0x2a, 0x6f, 0xb3, 0x7e, 0xfb, 0xbc, + 0xfc, 0x59, 0x42, 0xb9, 0x56, 0xf0, 0x4c, 0x3f, 0xf7, 0x31, 0x84, 0xbe, + 0xac, 0x03, 0x9e, 0x71, 0x91, 0x85, 0xd8, 0x32, 0xbd, 0x00, 0xea, 0xac, + 0x65, 0xf6, 0x03, 0xc8, 0x0f, 0x8b, 0xfd, 0x6e, 0x58, 0x88, 0x04, 0x41, + 0x92, 0x74, 0xa6, 0x57, 0x2e, 0x8e, 0x88, 0xd5, 0x3d, 0xda, 0x14, 0x3e, + 0x63, 0x88, 0x22, 0xe3, 0x53, 0xe9, 0xba, 0x39, 0x09, 0xac, 0xfb, 0xd0, + 0x4c, 0xf2, 0x3c, 0x20, 0xd6, 0x97, 0xe6, 0xed, 0xf1, 0x62, 0x1e, 0xe5, + 0xc9, 0x48, 0xa0, 0xca, 0x2e, 0x3c, 0x14, 0x5a, 0x82, 0xd4, 0xed, 0xb1, + 0xe3, 0x43, 0xc1, 0x2a, 0x59, 0xa5, 0xb9, 0xc8, 0x48, 0xa7, 0x39, 0x23, + 0x74, 0xa7, 0x37, 0xb0, 0x6f, 0xc3, 0x64, 0x99, 0x6c, 0xa2, 0x82, 0xc8, + 0xf6, 0xdb, 0x86, 0x40, 0xce, 0xd1, 0x85, 0x9f, 0xce, 0x69, 0xf4, 0x15, + 0x2a, 0x23, 0xca, 0xea, 0xb7, 0x7b, 0xdf, 0xfb, 0x43, 0x5f, 0xff, 0x7a, + 0x49, 0x49, 0x0e, 0xe7, 0x02, 0x51, 0x45, 0x13, 0xe8, 0x90, 0x64, 0x21, + 0x0c, 0x26, 0x2b, 0x5d, 0xfc, 0xe4, 0xb5, 0x86, 0x89, 0x43, 0x22, 0x4c, + 0xf3, 0x3b, 0xf3, 0x09, 0xc4, 0xa4, 0x10, 0x80, 0xf2, 0x46, 0xe2, 0x46, + 0x8f, 0x76, 0x50, 0xbf, 0xaf, 0x2b, 0x90, 0x1b, 0x78, 0xc7, 0xcf, 0xc1, + 0x77, 0xd0, 0xfb, 0xa9, 0xfb, 0xc9, 0x66, 0x5a, 0xc5, 0x9b, 0x31, 0x41, + 0x67, 0x01, 0xbe, 0x33, 0x10, 0xba, 0x05, 0x58, 0xed, 0x76, 0x53, 0xde, + 0x5d, 0xc1, 0xe8, 0xbb, 0x9f, 0xf1, 0xcd, 0xfb, 0xdf, 0x64, 0x7f, 0xd7, + 0x18, 0xab, 0x0f, 0x94, 0x28, 0x95, 0x4a, 0xcc, 0x6a, 0xa9, 0x50, 0xc7, + 0x05, 0x47, 0x10, 0x41, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, + 0x01, 0x00, 0xa8, 0x47, 0xb9, 0x4a, 0x06, 0x47, 0x93, 0x71, 0x3d, 0xef, + 0x7b, 0xca, 0xb4, 0x7c, 0x0a, 0xe6, 0x82, 0xd0, 0xe7, 0x0d, 0xa9, 0x08, + 0xf6, 0xa4, 0xfd, 0xd8, 0x73, 0xae, 0x6f, 0x56, 0x29, 0x5e, 0x25, 0x72, + 0xa8, 0x30, 0x44, 0x73, 0xcf, 0x56, 0x26, 0xb9, 0x61, 0xde, 0x42, 0x81, + 0xf4, 0xf0, 0x1f, 0x5d, 0xcb, 0x47, 0xf2, 0x26, 0xe9, 0xe0, 0x93, 0x28, + 0xa3, 0x10, 0x3b, 0x42, 0x1e, 0x51, 0x11, 0x12, 0x06, 0x5e, 0xaf, 0xce, + 0xb0, 0xa5, 0x14, 0xdd, 0x82, 0x58, 0xa1, 0xa4, 0x12, 0xdf, 0x65, 0x1d, + 0x51, 0x70, 0x64, 0xd5, 0x58, 0x68, 0x11, 0xa8, 0x6a, 0x23, 0xc2, 0xbf, + 0xa1, 0x25, 0x24, 0x47, 0xb3, 0xa4, 0x3c, 0x83, 0x96, 0xb7, 0x1f, 0xf4, + 0x44, 0xd4, 0xd1, 0xe9, 0xfc, 0x33, 0x68, 0x5e, 0xe2, 0x68, 0x99, 0x9c, + 0x91, 0xe8, 0x72, 0xc9, 0xd7, 0x8c, 0x80, 0x20, 0x8e, 0x77, 0x83, 0x4d, + 0xe4, 0xab, 0xf9, 0x74, 0xa1, 0xdf, 0xd3, 0xc0, 0x0d, 0x5b, 0x05, 0x51, + 0xc2, 0x6f, 0xb2, 0x91, 0x02, 0xec, 0xc0, 0x02, 0x1a, 0x5c, 0x91, 0x05, + 0xf1, 0xe3, 0xfa, 0x65, 0xc2, 0xad, 0x24, 0xe6, 0xe5, 0x3c, 0xb6, 0x16, + 0xf1, 0xa1, 0x67, 0x1a, 0x9d, 0x37, 0x56, 0xbf, 0x01, 0xd7, 0x3b, 0x35, + 0x30, 0x57, 0x73, 0xf4, 0xf0, 0x5e, 0xa7, 0xe8, 0x0a, 0xc1, 0x94, 0x17, + 0xcf, 0x0a, 0xbd, 0xf5, 0x31, 0xa7, 0x2d, 0xf7, 0xf5, 0xd9, 0x8c, 0xc2, + 0x01, 0xbd, 0xda, 0x16, 0x8e, 0xb9, 0x30, 0x40, 0xa6, 0x6e, 0xbd, 0xcd, + 0x4d, 0x84, 0x67, 0x4e, 0x0b, 0xce, 0xd5, 0xef, 0xf8, 0x08, 0x63, 0x02, + 0xc6, 0xc7, 0xf7, 0x67, 0x92, 0xe2, 0x23, 0x9d, 0x27, 0x22, 0x1d, 0xc6, + 0x67, 0x5e, 0x66, 0xbf, 0x03, 0xb8, 0xa9, 0x67, 0xd4, 0x39, 0xd8, 0x75, + 0xfa, 0xe8, 0xed, 0x56, 0xb8, 0x81, 0x02, 0x81, 0x81, 0x00, 0xf7, 0x46, + 0x68, 0xc6, 0x13, 0xf8, 0xba, 0x0f, 0x83, 0xdb, 0x05, 0xa8, 0x25, 0x00, + 0x70, 0x9c, 0x9e, 0x8b, 0x12, 0x34, 0x0d, 0x96, 0xcf, 0x0d, 0x98, 0x9b, + 0x8d, 0x9c, 0x96, 0x78, 0xd1, 0x3c, 0x01, 0x8c, 0xb9, 0x35, 0x5c, 0x20, + 0x42, 0xb4, 0x38, 0xe3, 0xd6, 0x54, 0xe7, 0x55, 0xd6, 0x26, 0x8a, 0x0c, + 0xf6, 0x1f, 0xe0, 0x04, 0xc1, 0x22, 0x42, 0x19, 0x61, 0xc4, 0x94, 0x7c, + 0x07, 0x2e, 0x80, 0x52, 0xfe, 0x8d, 0xe6, 0x92, 0x3a, 0x91, 0xfe, 0x72, + 0x99, 0xe1, 0x2a, 0x73, 0x76, 0xb1, 0x24, 0x20, 0x67, 0xde, 0x28, 0xcb, + 0x0e, 0xe6, 0x52, 0xb5, 0xfa, 0xfb, 0x8b, 0x1e, 0x6a, 0x1d, 0x09, 0x26, + 0xb9, 0xa7, 0x61, 0xba, 0xf8, 0x79, 0xd2, 0x66, 0x57, 0x28, 0xd7, 0x31, + 0xb5, 0x0b, 0x27, 0x19, 0x1e, 0x6f, 0x46, 0xfc, 0x54, 0x95, 0xeb, 0x78, + 0x01, 0xb6, 0xd9, 0x79, 0x5a, 0x4d, 0x02, 0x81, 0x81, 0x00, 0xd5, 0x8f, + 0x16, 0x53, 0x2f, 0x57, 0x93, 0xbf, 0x09, 0x75, 0xbf, 0x63, 0x40, 0x3d, + 0x27, 0xfd, 0x23, 0x21, 0xde, 0x9b, 0xe9, 0x73, 0x3f, 0x49, 0x02, 0xd2, + 0x38, 0x96, 0xcf, 0xc3, 0xba, 0x92, 0x07, 0x87, 0x52, 0xa9, 0x35, 0xe3, + 0x0c, 0xe4, 0x2f, 0x05, 0x7b, 0x37, 0xa5, 0x40, 0x9c, 0x3b, 0x94, 0xf7, + 0xad, 0xa0, 0xee, 0x3a, 0xa8, 0xfb, 0x1f, 0x11, 0x1f, 0xd8, 0x9a, 0x80, + 0x42, 0x3d, 0x7f, 0xa4, 0xb8, 0x9a, 0xaa, 0xea, 0x72, 0xc1, 0xe3, 0xed, + 0x06, 0x60, 0x92, 0x37, 0xf9, 0xba, 0xfb, 0x9e, 0xed, 0x05, 0xa6, 0xd4, + 0x72, 0x68, 0x4f, 0x63, 0xfe, 0xd6, 0x10, 0x0d, 0x4f, 0x0a, 0x93, 0xc6, + 0xb9, 0xd7, 0xaf, 0xfd, 0xd9, 0x57, 0x7d, 0xcb, 0x75, 0xe8, 0x93, 0x2b, + 0xae, 0x4f, 0xea, 0xd7, 0x30, 0x0b, 0x58, 0x44, 0x82, 0x0f, 0x84, 0x5d, + 0x62, 0x11, 0x78, 0xea, 0x5f, 0xc5, 0x02, 0x81, 0x81, 0x00, 0x82, 0x0c, + 0xc1, 0xe6, 0x0b, 0x72, 0xf1, 0x48, 0x5f, 0xac, 0xbd, 0x98, 0xe5, 0x7d, + 0x09, 0xbd, 0x15, 0x95, 0x47, 0x09, 0xa1, 0x6c, 0x03, 0x91, 0xbf, 0x05, + 0x70, 0xc1, 0x3e, 0x52, 0x64, 0x99, 0x0e, 0xa7, 0x98, 0x70, 0xfb, 0xf6, + 0xeb, 0x9e, 0x25, 0x9d, 0x8e, 0x88, 0x30, 0xf2, 0xf0, 0x22, 0x6c, 0xd0, + 0xcc, 0x51, 0x8f, 0x5c, 0x70, 0xc7, 0x37, 0xc4, 0x69, 0xab, 0x1d, 0xfc, + 0xed, 0x3a, 0x03, 0xbb, 0xa2, 0xad, 0xb6, 0xea, 0x89, 0x6b, 0x67, 0x4b, + 0x96, 0xaa, 0xd9, 0xcc, 0xc8, 0x4b, 0xfa, 0x18, 0x21, 0x08, 0xb2, 0xa3, + 0xb9, 0x3e, 0x61, 0x99, 0xdc, 0x5a, 0x97, 0x9c, 0x73, 0x6a, 0xb9, 0xf9, + 0x68, 0x03, 0x24, 0x5f, 0x55, 0x77, 0x9c, 0xb4, 0xbe, 0x7a, 0x78, 0x53, + 0x68, 0x48, 0x69, 0x53, 0xc8, 0xb1, 0xf5, 0xbf, 0x98, 0x2d, 0x11, 0x1e, + 0x98, 0xa8, 0x36, 0x50, 0xa0, 0xb1, 0x02, 0x81, 0x81, 0x00, 0x90, 0x88, + 0x30, 0x71, 0xc7, 0xfe, 0x9b, 0x6d, 0x95, 0x37, 0x6d, 0x79, 0xfc, 0x85, + 0xe7, 0x44, 0x78, 0xbc, 0x79, 0x6e, 0x47, 0x86, 0xc9, 0xf3, 0xdd, 0xc6, + 0xec, 0xa9, 0x94, 0x9f, 0x40, 0xeb, 0x87, 0xd0, 0xdb, 0xee, 0xcd, 0x1b, + 0x87, 0x23, 0xff, 0x76, 0xd4, 0x37, 0x8a, 0xcd, 0xb9, 0x6e, 0xd1, 0x98, + 0xf6, 0x97, 0x8d, 0xe3, 0x81, 0x6d, 0xc3, 0x4e, 0xd1, 0xa0, 0xc4, 0x9f, + 0xbd, 0x34, 0xe5, 0xe8, 0x53, 0x4f, 0xca, 0x10, 0xb5, 0xed, 0xe7, 0x16, + 0x09, 0x54, 0xde, 0x60, 0xa7, 0xd1, 0x16, 0x6e, 0x2e, 0xb7, 0xbe, 0x7a, + 0xd5, 0x9b, 0x26, 0xef, 0xe4, 0x0e, 0x77, 0xfa, 0xa9, 0xdd, 0xdc, 0xb9, + 0x88, 0x19, 0x23, 0x70, 0xc7, 0xe1, 0x60, 0xaf, 0x8c, 0x73, 0x04, 0xf7, + 0x71, 0x17, 0x81, 0x36, 0x75, 0xbb, 0x97, 0xd7, 0x75, 0xb6, 0x8e, 0xbc, + 0xac, 0x9c, 0x6a, 0x9b, 0x24, 0x89, 0x02, 0x81, 0x80, 0x5a, 0x2b, 0xc7, + 0x6b, 0x8c, 0x65, 0xdb, 0x04, 0x73, 0xab, 0x25, 0xe1, 0x5b, 0xbc, 0x3c, + 0xcf, 0x5a, 0x3c, 0x04, 0xae, 0x97, 0x2e, 0xfd, 0xa4, 0x97, 0x1f, 0x05, + 0x17, 0x27, 0xac, 0x7c, 0x30, 0x85, 0xb4, 0x82, 0x3f, 0x5b, 0xb7, 0x94, + 0x3b, 0x7f, 0x6c, 0x0c, 0xc7, 0x16, 0xc6, 0xa0, 0xbd, 0x80, 0xb0, 0x81, + 0xde, 0xa0, 0x23, 0xa6, 0xf6, 0x75, 0x33, 0x51, 0x35, 0xa2, 0x75, 0x55, + 0x70, 0x4d, 0x42, 0xbb, 0xcf, 0x54, 0xe4, 0xdb, 0x2d, 0x88, 0xa0, 0x7a, + 0xf2, 0x17, 0xa7, 0xdd, 0x13, 0x44, 0x9f, 0x5f, 0x6b, 0x2c, 0x42, 0x42, + 0x8b, 0x13, 0x4d, 0xf9, 0x5b, 0xf8, 0x33, 0x42, 0xd9, 0x9e, 0x50, 0x1c, + 0x7c, 0xbc, 0xfa, 0x62, 0x85, 0x0b, 0xcf, 0x99, 0xda, 0x9e, 0x04, 0x90, + 0xb2, 0xc6, 0xb2, 0x0a, 0x2a, 0x7c, 0x6d, 0x6a, 0x40, 0xfc, 0xf5, 0x50, + 0x98, 0x46, 0x89, 0x82, 0x40, +}; + + +#ifndef OPENSSL_NO_EC +/* + * -----BEGIN EC PRIVATE KEY----- + * MHcCAQEEIJLyl7hJjpQL/RhP1x2zS79xdiPJQB683gWeqcqHPeZkoAoGCCqGSM49 + * AwEHoUQDQgAEdsjygVYjjaKBF4CNECVllNf017p5/MxNSWDoTHy9I2GeDwEDDazI + * D/xy8JiYjtPKVE/Zqwbmivp2UwtH28a7NQ== + * -----END EC PRIVATE KEY----- + */ +static const char ECDSAPrivateKeyPEM[] = { + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x45, + 0x43, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, 0x45, + 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x48, 0x63, 0x43, 0x41, + 0x51, 0x45, 0x45, 0x49, 0x4a, 0x4c, 0x79, 0x6c, 0x37, 0x68, 0x4a, 0x6a, + 0x70, 0x51, 0x4c, 0x2f, 0x52, 0x68, 0x50, 0x31, 0x78, 0x32, 0x7a, 0x53, + 0x37, 0x39, 0x78, 0x64, 0x69, 0x50, 0x4a, 0x51, 0x42, 0x36, 0x38, 0x33, + 0x67, 0x57, 0x65, 0x71, 0x63, 0x71, 0x48, 0x50, 0x65, 0x5a, 0x6b, 0x6f, + 0x41, 0x6f, 0x47, 0x43, 0x43, 0x71, 0x47, 0x53, 0x4d, 0x34, 0x39, 0x0a, + 0x41, 0x77, 0x45, 0x48, 0x6f, 0x55, 0x51, 0x44, 0x51, 0x67, 0x41, 0x45, + 0x64, 0x73, 0x6a, 0x79, 0x67, 0x56, 0x59, 0x6a, 0x6a, 0x61, 0x4b, 0x42, + 0x46, 0x34, 0x43, 0x4e, 0x45, 0x43, 0x56, 0x6c, 0x6c, 0x4e, 0x66, 0x30, + 0x31, 0x37, 0x70, 0x35, 0x2f, 0x4d, 0x78, 0x4e, 0x53, 0x57, 0x44, 0x6f, + 0x54, 0x48, 0x79, 0x39, 0x49, 0x32, 0x47, 0x65, 0x44, 0x77, 0x45, 0x44, + 0x44, 0x61, 0x7a, 0x49, 0x0a, 0x44, 0x2f, 0x78, 0x79, 0x38, 0x4a, 0x69, + 0x59, 0x6a, 0x74, 0x50, 0x4b, 0x56, 0x45, 0x2f, 0x5a, 0x71, 0x77, 0x62, + 0x6d, 0x69, 0x76, 0x70, 0x32, 0x55, 0x77, 0x74, 0x48, 0x32, 0x38, 0x61, + 0x37, 0x4e, 0x51, 0x3d, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, + 0x4e, 0x44, 0x20, 0x45, 0x43, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, + 0x45, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a +}; + +/* + * -----BEGIN CERTIFICATE----- + * MIIBXzCCAQagAwIBAgIJAK6/Yvf/ain6MAoGCCqGSM49BAMCMBIxEDAOBgNVBAoM + * B0FjbWUgQ28wHhcNMTYxMjI1MTEzOTI3WhcNMjYxMjI1MTEzOTI3WjASMRAwDgYD + * VQQKDAdBY21lIENvMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEdsjygVYjjaKB + * F4CNECVllNf017p5/MxNSWDoTHy9I2GeDwEDDazID/xy8JiYjtPKVE/Zqwbmivp2 + * UwtH28a7NaNFMEMwCQYDVR0TBAIwADALBgNVHQ8EBAMCBaAwEwYDVR0lBAwwCgYI + * KwYBBQUHAwEwFAYDVR0RBA0wC4IJbG9jYWxob3N0MAoGCCqGSM49BAMCA0cAMEQC + * IEzr3t/jejVE9oSnBp8c3P2p+lDLVRrB8zxLyjZvirUXAiAyQPaE9MNcL8/nRpuu + * 99I1enCSmWIAJ57IwuJ/n1d45Q== + * -----END CERTIFICATE----- + */ +static const char ECDSACertPEM[] = { + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43, + 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x42, 0x58, 0x7a, 0x43, 0x43, + 0x41, 0x51, 0x61, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x4a, + 0x41, 0x4b, 0x36, 0x2f, 0x59, 0x76, 0x66, 0x2f, 0x61, 0x69, 0x6e, 0x36, + 0x4d, 0x41, 0x6f, 0x47, 0x43, 0x43, 0x71, 0x47, 0x53, 0x4d, 0x34, 0x39, + 0x42, 0x41, 0x4d, 0x43, 0x4d, 0x42, 0x49, 0x78, 0x45, 0x44, 0x41, 0x4f, + 0x42, 0x67, 0x4e, 0x56, 0x42, 0x41, 0x6f, 0x4d, 0x0a, 0x42, 0x30, 0x46, + 0x6a, 0x62, 0x57, 0x55, 0x67, 0x51, 0x32, 0x38, 0x77, 0x48, 0x68, 0x63, + 0x4e, 0x4d, 0x54, 0x59, 0x78, 0x4d, 0x6a, 0x49, 0x31, 0x4d, 0x54, 0x45, + 0x7a, 0x4f, 0x54, 0x49, 0x33, 0x57, 0x68, 0x63, 0x4e, 0x4d, 0x6a, 0x59, + 0x78, 0x4d, 0x6a, 0x49, 0x31, 0x4d, 0x54, 0x45, 0x7a, 0x4f, 0x54, 0x49, + 0x33, 0x57, 0x6a, 0x41, 0x53, 0x4d, 0x52, 0x41, 0x77, 0x44, 0x67, 0x59, + 0x44, 0x0a, 0x56, 0x51, 0x51, 0x4b, 0x44, 0x41, 0x64, 0x42, 0x59, 0x32, + 0x31, 0x6c, 0x49, 0x45, 0x4e, 0x76, 0x4d, 0x46, 0x6b, 0x77, 0x45, 0x77, + 0x59, 0x48, 0x4b, 0x6f, 0x5a, 0x49, 0x7a, 0x6a, 0x30, 0x43, 0x41, 0x51, + 0x59, 0x49, 0x4b, 0x6f, 0x5a, 0x49, 0x7a, 0x6a, 0x30, 0x44, 0x41, 0x51, + 0x63, 0x44, 0x51, 0x67, 0x41, 0x45, 0x64, 0x73, 0x6a, 0x79, 0x67, 0x56, + 0x59, 0x6a, 0x6a, 0x61, 0x4b, 0x42, 0x0a, 0x46, 0x34, 0x43, 0x4e, 0x45, + 0x43, 0x56, 0x6c, 0x6c, 0x4e, 0x66, 0x30, 0x31, 0x37, 0x70, 0x35, 0x2f, + 0x4d, 0x78, 0x4e, 0x53, 0x57, 0x44, 0x6f, 0x54, 0x48, 0x79, 0x39, 0x49, + 0x32, 0x47, 0x65, 0x44, 0x77, 0x45, 0x44, 0x44, 0x61, 0x7a, 0x49, 0x44, + 0x2f, 0x78, 0x79, 0x38, 0x4a, 0x69, 0x59, 0x6a, 0x74, 0x50, 0x4b, 0x56, + 0x45, 0x2f, 0x5a, 0x71, 0x77, 0x62, 0x6d, 0x69, 0x76, 0x70, 0x32, 0x0a, + 0x55, 0x77, 0x74, 0x48, 0x32, 0x38, 0x61, 0x37, 0x4e, 0x61, 0x4e, 0x46, + 0x4d, 0x45, 0x4d, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x52, 0x30, 0x54, + 0x42, 0x41, 0x49, 0x77, 0x41, 0x44, 0x41, 0x4c, 0x42, 0x67, 0x4e, 0x56, + 0x48, 0x51, 0x38, 0x45, 0x42, 0x41, 0x4d, 0x43, 0x42, 0x61, 0x41, 0x77, + 0x45, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x6c, 0x42, 0x41, 0x77, 0x77, + 0x43, 0x67, 0x59, 0x49, 0x0a, 0x4b, 0x77, 0x59, 0x42, 0x42, 0x51, 0x55, + 0x48, 0x41, 0x77, 0x45, 0x77, 0x46, 0x41, 0x59, 0x44, 0x56, 0x52, 0x30, + 0x52, 0x42, 0x41, 0x30, 0x77, 0x43, 0x34, 0x49, 0x4a, 0x62, 0x47, 0x39, + 0x6a, 0x59, 0x57, 0x78, 0x6f, 0x62, 0x33, 0x4e, 0x30, 0x4d, 0x41, 0x6f, + 0x47, 0x43, 0x43, 0x71, 0x47, 0x53, 0x4d, 0x34, 0x39, 0x42, 0x41, 0x4d, + 0x43, 0x41, 0x30, 0x63, 0x41, 0x4d, 0x45, 0x51, 0x43, 0x0a, 0x49, 0x45, + 0x7a, 0x72, 0x33, 0x74, 0x2f, 0x6a, 0x65, 0x6a, 0x56, 0x45, 0x39, 0x6f, + 0x53, 0x6e, 0x42, 0x70, 0x38, 0x63, 0x33, 0x50, 0x32, 0x70, 0x2b, 0x6c, + 0x44, 0x4c, 0x56, 0x52, 0x72, 0x42, 0x38, 0x7a, 0x78, 0x4c, 0x79, 0x6a, + 0x5a, 0x76, 0x69, 0x72, 0x55, 0x58, 0x41, 0x69, 0x41, 0x79, 0x51, 0x50, + 0x61, 0x45, 0x39, 0x4d, 0x4e, 0x63, 0x4c, 0x38, 0x2f, 0x6e, 0x52, 0x70, + 0x75, 0x75, 0x0a, 0x39, 0x39, 0x49, 0x31, 0x65, 0x6e, 0x43, 0x53, 0x6d, + 0x57, 0x49, 0x41, 0x4a, 0x35, 0x37, 0x49, 0x77, 0x75, 0x4a, 0x2f, 0x6e, + 0x31, 0x64, 0x34, 0x35, 0x51, 0x3d, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, + 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a +}; +#endif + +#ifndef OPENSSL_NO_DSA +/* + * -----BEGIN DSA PRIVATE KEY----- + * MIIBuwIBAAKBgQDdkFKzNABLOha7Eqj7004+p5fhtR6bxpujToMmSZTYi8igVVXP + * Wzf03ULKS5UKjA6WpR6EiZAhm+PdxusZ5xfAuRZLdKy0bgxn1f348Rwh+EQNaEM8 + * 0TGcnw5ijwKmSw5yyHPDWdiHzoqEBlhAf8Nl22YTXax/clsc/pu/RRLAdwIVAIEg + * QqWRf/1EIZZcgM65Qpd65YuxAoGBAKBauV/RuloFHoSy5iWXESDywiS380tN5974 + * GukGwoYdZo5uSIH6ahpeNSef0MbHGAzr7ZVEnhCQfRAwH1gRvSHoq/Rbmcvtd3r+ + * QtQHOwvQHgLAynhI4i73c794czHaR+439bmcaSwDnQduRM85Mho/jiiZzAVPxBmG + * POIMWNXXAoGAI6Ep5IE7yn3JzkXO9B6tC3bbDM+ZzuuInwZLbtZ8lim7Dsqabg4k + * 2YbE4R95Bnfwnjsyl80mq/DbQN5lAHBvjDrkC6ItojBGKI3+iIrqGUEJdxvl4ulj + * F0PmSD7zvIG8BfocKOel+EHH0YryExiW6krV1KW2ZRmJrqSFw6KCjV0CFFQFbPfU + * xy5PmKytJmXR8BmppkIO + * -----END DSA PRIVATE KEY----- + */ +static const char DSAPrivateKeyPEM[] = { + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x44, + 0x53, 0x41, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, + 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x42, + 0x75, 0x77, 0x49, 0x42, 0x41, 0x41, 0x4b, 0x42, 0x67, 0x51, 0x44, 0x64, + 0x6b, 0x46, 0x4b, 0x7a, 0x4e, 0x41, 0x42, 0x4c, 0x4f, 0x68, 0x61, 0x37, + 0x45, 0x71, 0x6a, 0x37, 0x30, 0x30, 0x34, 0x2b, 0x70, 0x35, 0x66, 0x68, + 0x74, 0x52, 0x36, 0x62, 0x78, 0x70, 0x75, 0x6a, 0x54, 0x6f, 0x4d, 0x6d, + 0x53, 0x5a, 0x54, 0x59, 0x69, 0x38, 0x69, 0x67, 0x56, 0x56, 0x58, 0x50, + 0x0a, 0x57, 0x7a, 0x66, 0x30, 0x33, 0x55, 0x4c, 0x4b, 0x53, 0x35, 0x55, + 0x4b, 0x6a, 0x41, 0x36, 0x57, 0x70, 0x52, 0x36, 0x45, 0x69, 0x5a, 0x41, + 0x68, 0x6d, 0x2b, 0x50, 0x64, 0x78, 0x75, 0x73, 0x5a, 0x35, 0x78, 0x66, + 0x41, 0x75, 0x52, 0x5a, 0x4c, 0x64, 0x4b, 0x79, 0x30, 0x62, 0x67, 0x78, + 0x6e, 0x31, 0x66, 0x33, 0x34, 0x38, 0x52, 0x77, 0x68, 0x2b, 0x45, 0x51, + 0x4e, 0x61, 0x45, 0x4d, 0x38, 0x0a, 0x30, 0x54, 0x47, 0x63, 0x6e, 0x77, + 0x35, 0x69, 0x6a, 0x77, 0x4b, 0x6d, 0x53, 0x77, 0x35, 0x79, 0x79, 0x48, + 0x50, 0x44, 0x57, 0x64, 0x69, 0x48, 0x7a, 0x6f, 0x71, 0x45, 0x42, 0x6c, + 0x68, 0x41, 0x66, 0x38, 0x4e, 0x6c, 0x32, 0x32, 0x59, 0x54, 0x58, 0x61, + 0x78, 0x2f, 0x63, 0x6c, 0x73, 0x63, 0x2f, 0x70, 0x75, 0x2f, 0x52, 0x52, + 0x4c, 0x41, 0x64, 0x77, 0x49, 0x56, 0x41, 0x49, 0x45, 0x67, 0x0a, 0x51, + 0x71, 0x57, 0x52, 0x66, 0x2f, 0x31, 0x45, 0x49, 0x5a, 0x5a, 0x63, 0x67, + 0x4d, 0x36, 0x35, 0x51, 0x70, 0x64, 0x36, 0x35, 0x59, 0x75, 0x78, 0x41, + 0x6f, 0x47, 0x42, 0x41, 0x4b, 0x42, 0x61, 0x75, 0x56, 0x2f, 0x52, 0x75, + 0x6c, 0x6f, 0x46, 0x48, 0x6f, 0x53, 0x79, 0x35, 0x69, 0x57, 0x58, 0x45, + 0x53, 0x44, 0x79, 0x77, 0x69, 0x53, 0x33, 0x38, 0x30, 0x74, 0x4e, 0x35, + 0x39, 0x37, 0x34, 0x0a, 0x47, 0x75, 0x6b, 0x47, 0x77, 0x6f, 0x59, 0x64, + 0x5a, 0x6f, 0x35, 0x75, 0x53, 0x49, 0x48, 0x36, 0x61, 0x68, 0x70, 0x65, + 0x4e, 0x53, 0x65, 0x66, 0x30, 0x4d, 0x62, 0x48, 0x47, 0x41, 0x7a, 0x72, + 0x37, 0x5a, 0x56, 0x45, 0x6e, 0x68, 0x43, 0x51, 0x66, 0x52, 0x41, 0x77, + 0x48, 0x31, 0x67, 0x52, 0x76, 0x53, 0x48, 0x6f, 0x71, 0x2f, 0x52, 0x62, + 0x6d, 0x63, 0x76, 0x74, 0x64, 0x33, 0x72, 0x2b, 0x0a, 0x51, 0x74, 0x51, + 0x48, 0x4f, 0x77, 0x76, 0x51, 0x48, 0x67, 0x4c, 0x41, 0x79, 0x6e, 0x68, + 0x49, 0x34, 0x69, 0x37, 0x33, 0x63, 0x37, 0x39, 0x34, 0x63, 0x7a, 0x48, + 0x61, 0x52, 0x2b, 0x34, 0x33, 0x39, 0x62, 0x6d, 0x63, 0x61, 0x53, 0x77, + 0x44, 0x6e, 0x51, 0x64, 0x75, 0x52, 0x4d, 0x38, 0x35, 0x4d, 0x68, 0x6f, + 0x2f, 0x6a, 0x69, 0x69, 0x5a, 0x7a, 0x41, 0x56, 0x50, 0x78, 0x42, 0x6d, + 0x47, 0x0a, 0x50, 0x4f, 0x49, 0x4d, 0x57, 0x4e, 0x58, 0x58, 0x41, 0x6f, + 0x47, 0x41, 0x49, 0x36, 0x45, 0x70, 0x35, 0x49, 0x45, 0x37, 0x79, 0x6e, + 0x33, 0x4a, 0x7a, 0x6b, 0x58, 0x4f, 0x39, 0x42, 0x36, 0x74, 0x43, 0x33, + 0x62, 0x62, 0x44, 0x4d, 0x2b, 0x5a, 0x7a, 0x75, 0x75, 0x49, 0x6e, 0x77, + 0x5a, 0x4c, 0x62, 0x74, 0x5a, 0x38, 0x6c, 0x69, 0x6d, 0x37, 0x44, 0x73, + 0x71, 0x61, 0x62, 0x67, 0x34, 0x6b, 0x0a, 0x32, 0x59, 0x62, 0x45, 0x34, + 0x52, 0x39, 0x35, 0x42, 0x6e, 0x66, 0x77, 0x6e, 0x6a, 0x73, 0x79, 0x6c, + 0x38, 0x30, 0x6d, 0x71, 0x2f, 0x44, 0x62, 0x51, 0x4e, 0x35, 0x6c, 0x41, + 0x48, 0x42, 0x76, 0x6a, 0x44, 0x72, 0x6b, 0x43, 0x36, 0x49, 0x74, 0x6f, + 0x6a, 0x42, 0x47, 0x4b, 0x49, 0x33, 0x2b, 0x69, 0x49, 0x72, 0x71, 0x47, + 0x55, 0x45, 0x4a, 0x64, 0x78, 0x76, 0x6c, 0x34, 0x75, 0x6c, 0x6a, 0x0a, + 0x46, 0x30, 0x50, 0x6d, 0x53, 0x44, 0x37, 0x7a, 0x76, 0x49, 0x47, 0x38, + 0x42, 0x66, 0x6f, 0x63, 0x4b, 0x4f, 0x65, 0x6c, 0x2b, 0x45, 0x48, 0x48, + 0x30, 0x59, 0x72, 0x79, 0x45, 0x78, 0x69, 0x57, 0x36, 0x6b, 0x72, 0x56, + 0x31, 0x4b, 0x57, 0x32, 0x5a, 0x52, 0x6d, 0x4a, 0x72, 0x71, 0x53, 0x46, + 0x77, 0x36, 0x4b, 0x43, 0x6a, 0x56, 0x30, 0x43, 0x46, 0x46, 0x51, 0x46, + 0x62, 0x50, 0x66, 0x55, 0x0a, 0x78, 0x79, 0x35, 0x50, 0x6d, 0x4b, 0x79, + 0x74, 0x4a, 0x6d, 0x58, 0x52, 0x38, 0x42, 0x6d, 0x70, 0x70, 0x6b, 0x49, + 0x4f, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x44, + 0x53, 0x41, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, + 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a +}; + +/* + * -----BEGIN CERTIFICATE----- + * MIICqTCCAmegAwIBAgIJAILDGUk37fWGMAsGCWCGSAFlAwQDAjASMRAwDgYDVQQK + * DAdBY21lIENvMB4XDTE2MTIyNTEzMjUzNloXDTI2MTIyNTEzMjUzNlowEjEQMA4G + * A1UECgwHQWNtZSBDbzCCAbcwggEsBgcqhkjOOAQBMIIBHwKBgQDdkFKzNABLOha7 + * Eqj7004+p5fhtR6bxpujToMmSZTYi8igVVXPWzf03ULKS5UKjA6WpR6EiZAhm+Pd + * xusZ5xfAuRZLdKy0bgxn1f348Rwh+EQNaEM80TGcnw5ijwKmSw5yyHPDWdiHzoqE + * BlhAf8Nl22YTXax/clsc/pu/RRLAdwIVAIEgQqWRf/1EIZZcgM65Qpd65YuxAoGB + * AKBauV/RuloFHoSy5iWXESDywiS380tN5974GukGwoYdZo5uSIH6ahpeNSef0MbH + * GAzr7ZVEnhCQfRAwH1gRvSHoq/Rbmcvtd3r+QtQHOwvQHgLAynhI4i73c794czHa + * R+439bmcaSwDnQduRM85Mho/jiiZzAVPxBmGPOIMWNXXA4GEAAKBgCOhKeSBO8p9 + * yc5FzvQerQt22wzPmc7riJ8GS27WfJYpuw7Kmm4OJNmGxOEfeQZ38J47MpfNJqvw + * 20DeZQBwb4w65AuiLaIwRiiN/oiK6hlBCXcb5eLpYxdD5kg+87yBvAX6HCjnpfhB + * x9GK8hMYlupK1dSltmUZia6khcOigo1do0UwQzAJBgNVHRMEAjAAMAsGA1UdDwQE + * AwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATAUBgNVHREEDTALgglsb2NhbGhvc3Qw + * CwYJYIZIAWUDBAMCAy8AMCwCFClxInXTRWNJEWdi5ilNr/fbM1bKAhQy4B7wtmfd + * I+zV6g3w9qBkNqStpA== + * -----END CERTIFICATE----- + */ +static const char DSACertPEM[] = { + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43, + 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43, 0x71, 0x54, 0x43, 0x43, + 0x41, 0x6d, 0x65, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x4a, + 0x41, 0x49, 0x4c, 0x44, 0x47, 0x55, 0x6b, 0x33, 0x37, 0x66, 0x57, 0x47, + 0x4d, 0x41, 0x73, 0x47, 0x43, 0x57, 0x43, 0x47, 0x53, 0x41, 0x46, 0x6c, + 0x41, 0x77, 0x51, 0x44, 0x41, 0x6a, 0x41, 0x53, 0x4d, 0x52, 0x41, 0x77, + 0x44, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4b, 0x0a, 0x44, 0x41, 0x64, + 0x42, 0x59, 0x32, 0x31, 0x6c, 0x49, 0x45, 0x4e, 0x76, 0x4d, 0x42, 0x34, + 0x58, 0x44, 0x54, 0x45, 0x32, 0x4d, 0x54, 0x49, 0x79, 0x4e, 0x54, 0x45, + 0x7a, 0x4d, 0x6a, 0x55, 0x7a, 0x4e, 0x6c, 0x6f, 0x58, 0x44, 0x54, 0x49, + 0x32, 0x4d, 0x54, 0x49, 0x79, 0x4e, 0x54, 0x45, 0x7a, 0x4d, 0x6a, 0x55, + 0x7a, 0x4e, 0x6c, 0x6f, 0x77, 0x45, 0x6a, 0x45, 0x51, 0x4d, 0x41, 0x34, + 0x47, 0x0a, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x48, 0x51, 0x57, + 0x4e, 0x74, 0x5a, 0x53, 0x42, 0x44, 0x62, 0x7a, 0x43, 0x43, 0x41, 0x62, + 0x63, 0x77, 0x67, 0x67, 0x45, 0x73, 0x42, 0x67, 0x63, 0x71, 0x68, 0x6b, + 0x6a, 0x4f, 0x4f, 0x41, 0x51, 0x42, 0x4d, 0x49, 0x49, 0x42, 0x48, 0x77, + 0x4b, 0x42, 0x67, 0x51, 0x44, 0x64, 0x6b, 0x46, 0x4b, 0x7a, 0x4e, 0x41, + 0x42, 0x4c, 0x4f, 0x68, 0x61, 0x37, 0x0a, 0x45, 0x71, 0x6a, 0x37, 0x30, + 0x30, 0x34, 0x2b, 0x70, 0x35, 0x66, 0x68, 0x74, 0x52, 0x36, 0x62, 0x78, + 0x70, 0x75, 0x6a, 0x54, 0x6f, 0x4d, 0x6d, 0x53, 0x5a, 0x54, 0x59, 0x69, + 0x38, 0x69, 0x67, 0x56, 0x56, 0x58, 0x50, 0x57, 0x7a, 0x66, 0x30, 0x33, + 0x55, 0x4c, 0x4b, 0x53, 0x35, 0x55, 0x4b, 0x6a, 0x41, 0x36, 0x57, 0x70, + 0x52, 0x36, 0x45, 0x69, 0x5a, 0x41, 0x68, 0x6d, 0x2b, 0x50, 0x64, 0x0a, + 0x78, 0x75, 0x73, 0x5a, 0x35, 0x78, 0x66, 0x41, 0x75, 0x52, 0x5a, 0x4c, + 0x64, 0x4b, 0x79, 0x30, 0x62, 0x67, 0x78, 0x6e, 0x31, 0x66, 0x33, 0x34, + 0x38, 0x52, 0x77, 0x68, 0x2b, 0x45, 0x51, 0x4e, 0x61, 0x45, 0x4d, 0x38, + 0x30, 0x54, 0x47, 0x63, 0x6e, 0x77, 0x35, 0x69, 0x6a, 0x77, 0x4b, 0x6d, + 0x53, 0x77, 0x35, 0x79, 0x79, 0x48, 0x50, 0x44, 0x57, 0x64, 0x69, 0x48, + 0x7a, 0x6f, 0x71, 0x45, 0x0a, 0x42, 0x6c, 0x68, 0x41, 0x66, 0x38, 0x4e, + 0x6c, 0x32, 0x32, 0x59, 0x54, 0x58, 0x61, 0x78, 0x2f, 0x63, 0x6c, 0x73, + 0x63, 0x2f, 0x70, 0x75, 0x2f, 0x52, 0x52, 0x4c, 0x41, 0x64, 0x77, 0x49, + 0x56, 0x41, 0x49, 0x45, 0x67, 0x51, 0x71, 0x57, 0x52, 0x66, 0x2f, 0x31, + 0x45, 0x49, 0x5a, 0x5a, 0x63, 0x67, 0x4d, 0x36, 0x35, 0x51, 0x70, 0x64, + 0x36, 0x35, 0x59, 0x75, 0x78, 0x41, 0x6f, 0x47, 0x42, 0x0a, 0x41, 0x4b, + 0x42, 0x61, 0x75, 0x56, 0x2f, 0x52, 0x75, 0x6c, 0x6f, 0x46, 0x48, 0x6f, + 0x53, 0x79, 0x35, 0x69, 0x57, 0x58, 0x45, 0x53, 0x44, 0x79, 0x77, 0x69, + 0x53, 0x33, 0x38, 0x30, 0x74, 0x4e, 0x35, 0x39, 0x37, 0x34, 0x47, 0x75, + 0x6b, 0x47, 0x77, 0x6f, 0x59, 0x64, 0x5a, 0x6f, 0x35, 0x75, 0x53, 0x49, + 0x48, 0x36, 0x61, 0x68, 0x70, 0x65, 0x4e, 0x53, 0x65, 0x66, 0x30, 0x4d, + 0x62, 0x48, 0x0a, 0x47, 0x41, 0x7a, 0x72, 0x37, 0x5a, 0x56, 0x45, 0x6e, + 0x68, 0x43, 0x51, 0x66, 0x52, 0x41, 0x77, 0x48, 0x31, 0x67, 0x52, 0x76, + 0x53, 0x48, 0x6f, 0x71, 0x2f, 0x52, 0x62, 0x6d, 0x63, 0x76, 0x74, 0x64, + 0x33, 0x72, 0x2b, 0x51, 0x74, 0x51, 0x48, 0x4f, 0x77, 0x76, 0x51, 0x48, + 0x67, 0x4c, 0x41, 0x79, 0x6e, 0x68, 0x49, 0x34, 0x69, 0x37, 0x33, 0x63, + 0x37, 0x39, 0x34, 0x63, 0x7a, 0x48, 0x61, 0x0a, 0x52, 0x2b, 0x34, 0x33, + 0x39, 0x62, 0x6d, 0x63, 0x61, 0x53, 0x77, 0x44, 0x6e, 0x51, 0x64, 0x75, + 0x52, 0x4d, 0x38, 0x35, 0x4d, 0x68, 0x6f, 0x2f, 0x6a, 0x69, 0x69, 0x5a, + 0x7a, 0x41, 0x56, 0x50, 0x78, 0x42, 0x6d, 0x47, 0x50, 0x4f, 0x49, 0x4d, + 0x57, 0x4e, 0x58, 0x58, 0x41, 0x34, 0x47, 0x45, 0x41, 0x41, 0x4b, 0x42, + 0x67, 0x43, 0x4f, 0x68, 0x4b, 0x65, 0x53, 0x42, 0x4f, 0x38, 0x70, 0x39, + 0x0a, 0x79, 0x63, 0x35, 0x46, 0x7a, 0x76, 0x51, 0x65, 0x72, 0x51, 0x74, + 0x32, 0x32, 0x77, 0x7a, 0x50, 0x6d, 0x63, 0x37, 0x72, 0x69, 0x4a, 0x38, + 0x47, 0x53, 0x32, 0x37, 0x57, 0x66, 0x4a, 0x59, 0x70, 0x75, 0x77, 0x37, + 0x4b, 0x6d, 0x6d, 0x34, 0x4f, 0x4a, 0x4e, 0x6d, 0x47, 0x78, 0x4f, 0x45, + 0x66, 0x65, 0x51, 0x5a, 0x33, 0x38, 0x4a, 0x34, 0x37, 0x4d, 0x70, 0x66, + 0x4e, 0x4a, 0x71, 0x76, 0x77, 0x0a, 0x32, 0x30, 0x44, 0x65, 0x5a, 0x51, + 0x42, 0x77, 0x62, 0x34, 0x77, 0x36, 0x35, 0x41, 0x75, 0x69, 0x4c, 0x61, + 0x49, 0x77, 0x52, 0x69, 0x69, 0x4e, 0x2f, 0x6f, 0x69, 0x4b, 0x36, 0x68, + 0x6c, 0x42, 0x43, 0x58, 0x63, 0x62, 0x35, 0x65, 0x4c, 0x70, 0x59, 0x78, + 0x64, 0x44, 0x35, 0x6b, 0x67, 0x2b, 0x38, 0x37, 0x79, 0x42, 0x76, 0x41, + 0x58, 0x36, 0x48, 0x43, 0x6a, 0x6e, 0x70, 0x66, 0x68, 0x42, 0x0a, 0x78, + 0x39, 0x47, 0x4b, 0x38, 0x68, 0x4d, 0x59, 0x6c, 0x75, 0x70, 0x4b, 0x31, + 0x64, 0x53, 0x6c, 0x74, 0x6d, 0x55, 0x5a, 0x69, 0x61, 0x36, 0x6b, 0x68, + 0x63, 0x4f, 0x69, 0x67, 0x6f, 0x31, 0x64, 0x6f, 0x30, 0x55, 0x77, 0x51, + 0x7a, 0x41, 0x4a, 0x42, 0x67, 0x4e, 0x56, 0x48, 0x52, 0x4d, 0x45, 0x41, + 0x6a, 0x41, 0x41, 0x4d, 0x41, 0x73, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, + 0x77, 0x51, 0x45, 0x0a, 0x41, 0x77, 0x49, 0x46, 0x6f, 0x44, 0x41, 0x54, + 0x42, 0x67, 0x4e, 0x56, 0x48, 0x53, 0x55, 0x45, 0x44, 0x44, 0x41, 0x4b, + 0x42, 0x67, 0x67, 0x72, 0x42, 0x67, 0x45, 0x46, 0x42, 0x51, 0x63, 0x44, + 0x41, 0x54, 0x41, 0x55, 0x42, 0x67, 0x4e, 0x56, 0x48, 0x52, 0x45, 0x45, + 0x44, 0x54, 0x41, 0x4c, 0x67, 0x67, 0x6c, 0x73, 0x62, 0x32, 0x4e, 0x68, + 0x62, 0x47, 0x68, 0x76, 0x63, 0x33, 0x51, 0x77, 0x0a, 0x43, 0x77, 0x59, + 0x4a, 0x59, 0x49, 0x5a, 0x49, 0x41, 0x57, 0x55, 0x44, 0x42, 0x41, 0x4d, + 0x43, 0x41, 0x79, 0x38, 0x41, 0x4d, 0x43, 0x77, 0x43, 0x46, 0x43, 0x6c, + 0x78, 0x49, 0x6e, 0x58, 0x54, 0x52, 0x57, 0x4e, 0x4a, 0x45, 0x57, 0x64, + 0x69, 0x35, 0x69, 0x6c, 0x4e, 0x72, 0x2f, 0x66, 0x62, 0x4d, 0x31, 0x62, + 0x4b, 0x41, 0x68, 0x51, 0x79, 0x34, 0x42, 0x37, 0x77, 0x74, 0x6d, 0x66, + 0x64, 0x0a, 0x49, 0x2b, 0x7a, 0x56, 0x36, 0x67, 0x33, 0x77, 0x39, 0x71, + 0x42, 0x6b, 0x4e, 0x71, 0x53, 0x74, 0x70, 0x41, 0x3d, 0x3d, 0x0a, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, + 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x0a +}; +#endif + +/* unused, to avoid warning. */ +static int idx; + +#define FUZZTIME 1485898104 + +#define TIME_IMPL(t) { if (t != NULL) *t = FUZZTIME; return FUZZTIME; } + +/* + * This might not work in all cases (and definitely not on Windows + * because of the way linkers are) and callees can still get the + * current time instead of the fixed time. This will just result + * in things not being fully reproducible and have a slightly + * different coverage. + */ +#if !defined(_WIN32) +time_t time(time_t *t) TIME_IMPL(t) +#endif + +int FuzzerInitialize(int *argc, char ***argv) +{ + STACK_OF(SSL_COMP) *comp_methods; + + OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS | OPENSSL_INIT_ASYNC, NULL); + OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL); + ERR_get_state(); + CRYPTO_free_ex_index(0, -1); + idx = SSL_get_ex_data_X509_STORE_CTX_idx(); + FuzzerSetRand(); + comp_methods = SSL_COMP_get_compression_methods(); + if (comp_methods != NULL) + sk_SSL_COMP_sort(comp_methods); + + return 1; +} + +int FuzzerTestOneInput(const uint8_t *buf, size_t len) +{ + SSL *server; + BIO *in; + BIO *out; +#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DSA) + BIO *bio_buf; +#endif + SSL_CTX *ctx; + int ret; + RSA *privkey; + const uint8_t *bufp; + EVP_PKEY *pkey; + X509 *cert; +#ifndef OPENSSL_NO_EC + EC_KEY *ecdsakey = NULL; +#endif +#ifndef OPENSSL_NO_DSA + DSA *dsakey = NULL; +#endif + uint8_t opt; + + if (len < 2) + return 0; + + /* + * TODO: use the ossltest engine (optionally?) to disable crypto checks. + */ + + /* This only fuzzes the initial flow from the client so far. */ + ctx = SSL_CTX_new(SSLv23_method()); + + ret = SSL_CTX_set_min_proto_version(ctx, 0); + OPENSSL_assert(ret == 1); + ret = SSL_CTX_set_cipher_list(ctx, "ALL:eNULL:@SECLEVEL=0"); + OPENSSL_assert(ret == 1); + + /* RSA */ + bufp = kRSAPrivateKeyDER; + privkey = d2i_RSAPrivateKey(NULL, &bufp, sizeof(kRSAPrivateKeyDER)); + OPENSSL_assert(privkey != NULL); + pkey = EVP_PKEY_new(); + EVP_PKEY_assign_RSA(pkey, privkey); + ret = SSL_CTX_use_PrivateKey(ctx, pkey); + OPENSSL_assert(ret == 1); + EVP_PKEY_free(pkey); + + bufp = kCertificateDER; + cert = d2i_X509(NULL, &bufp, sizeof(kCertificateDER)); + OPENSSL_assert(cert != NULL); + ret = SSL_CTX_use_certificate(ctx, cert); + OPENSSL_assert(ret == 1); + X509_free(cert); + +#ifndef OPENSSL_NO_EC + /* ECDSA */ + bio_buf = BIO_new(BIO_s_mem()); + OPENSSL_assert((size_t)BIO_write(bio_buf, ECDSAPrivateKeyPEM, sizeof(ECDSAPrivateKeyPEM)) == sizeof(ECDSAPrivateKeyPEM)); + ecdsakey = PEM_read_bio_ECPrivateKey(bio_buf, NULL, NULL, NULL); + ERR_print_errors_fp(stderr); + OPENSSL_assert(ecdsakey != NULL); + BIO_free(bio_buf); + pkey = EVP_PKEY_new(); + EVP_PKEY_assign_EC_KEY(pkey, ecdsakey); + ret = SSL_CTX_use_PrivateKey(ctx, pkey); + OPENSSL_assert(ret == 1); + EVP_PKEY_free(pkey); + + bio_buf = BIO_new(BIO_s_mem()); + OPENSSL_assert((size_t)BIO_write(bio_buf, ECDSACertPEM, sizeof(ECDSACertPEM)) == sizeof(ECDSACertPEM)); + cert = PEM_read_bio_X509(bio_buf, NULL, NULL, NULL); + OPENSSL_assert(cert != NULL); + BIO_free(bio_buf); + ret = SSL_CTX_use_certificate(ctx, cert); + OPENSSL_assert(ret == 1); + X509_free(cert); +#endif + +#ifndef OPENSSL_NO_DSA + /* DSA */ + bio_buf = BIO_new(BIO_s_mem()); + OPENSSL_assert((size_t)BIO_write(bio_buf, DSAPrivateKeyPEM, sizeof(DSAPrivateKeyPEM)) == sizeof(DSAPrivateKeyPEM)); + dsakey = PEM_read_bio_DSAPrivateKey(bio_buf, NULL, NULL, NULL); + ERR_print_errors_fp(stderr); + OPENSSL_assert(dsakey != NULL); + BIO_free(bio_buf); + pkey = EVP_PKEY_new(); + EVP_PKEY_assign_DSA(pkey, dsakey); + ret = SSL_CTX_use_PrivateKey(ctx, pkey); + OPENSSL_assert(ret == 1); + EVP_PKEY_free(pkey); + + bio_buf = BIO_new(BIO_s_mem()); + OPENSSL_assert((size_t)BIO_write(bio_buf, DSACertPEM, sizeof(DSACertPEM)) == sizeof(DSACertPEM)); + cert = PEM_read_bio_X509(bio_buf, NULL, NULL, NULL); + OPENSSL_assert(cert != NULL); + BIO_free(bio_buf); + ret = SSL_CTX_use_certificate(ctx, cert); + OPENSSL_assert(ret == 1); + X509_free(cert); +#endif + + /* TODO: Set up support for SRP and PSK */ + + server = SSL_new(ctx); + in = BIO_new(BIO_s_mem()); + out = BIO_new(BIO_s_mem()); + SSL_set_bio(server, in, out); + SSL_set_accept_state(server); + + opt = (uint8_t)buf[len-1]; + len--; + + OPENSSL_assert((size_t)BIO_write(in, buf, len) == len); + + if ((opt & 0x01) != 0) + { + do { + char early_buf[16384]; + size_t early_len; + ret = SSL_read_early_data(server, early_buf, sizeof(early_buf), &early_len); + + if (ret != SSL_READ_EARLY_DATA_SUCCESS) + break; + } while (1); + } + + if (SSL_do_handshake(server) == 1) { + /* Keep reading application data until error or EOF. */ + uint8_t tmp[1024]; + for (;;) { + if (SSL_read(server, tmp, sizeof(tmp)) <= 0) { + break; + } + } + } + SSL_free(server); + ERR_clear_error(); + SSL_CTX_free(ctx); + + return 0; +} + +void FuzzerCleanup(void) +{ +} diff --git a/trunk/3rdparty/openssl-1.1-fit/fuzz/test-corpus.c b/trunk/3rdparty/openssl-1.1-fit/fuzz/test-corpus.c new file mode 100644 index 000000000..86be5337e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/fuzz/test-corpus.c @@ -0,0 +1,104 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL licenses, (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * https://www.openssl.org/source/license.html + * or in the file LICENSE in the source distribution. + */ + +/* + * Given a list of files, run each of them through the fuzzer. Note that + * failure will be indicated by some kind of crash. Switching on things like + * asan improves the test. + */ + +#include +#include +#include +#include +#include +#include "fuzzer.h" +#include "internal/o_dir.h" + +#if defined(_WIN32) && defined(_MAX_PATH) +# define PATH_MAX _MAX_PATH +#endif + +#ifndef PATH_MAX +# define PATH_MAX 4096 +#endif + +# if !defined(S_ISREG) +# define S_ISREG(m) ((m) & S_IFREG) +# endif + +static void testfile(const char *pathname) +{ + struct stat st; + FILE *f; + unsigned char *buf; + size_t s; + + if (stat(pathname, &st) < 0 || !S_ISREG(st.st_mode)) + return; + printf("# %s\n", pathname); + fflush(stdout); + f = fopen(pathname, "rb"); + if (f == NULL) + return; + buf = malloc(st.st_size); + if (buf != NULL) { + s = fread(buf, 1, st.st_size, f); + OPENSSL_assert(s == (size_t)st.st_size); + FuzzerTestOneInput(buf, s); + free(buf); + } + fclose(f); +} + +int main(int argc, char **argv) { + int n; + + FuzzerInitialize(&argc, &argv); + + for (n = 1; n < argc; ++n) { + size_t dirname_len = strlen(argv[n]); + const char *filename = NULL; + char *pathname = NULL; + OPENSSL_DIR_CTX *ctx = NULL; + int wasdir = 0; + + /* + * We start with trying to read the given path as a directory. + */ + while ((filename = OPENSSL_DIR_read(&ctx, argv[n])) != NULL) { + wasdir = 1; + if (pathname == NULL) { + pathname = malloc(PATH_MAX); + if (pathname == NULL) + break; + strcpy(pathname, argv[n]); +#ifdef __VMS + if (strchr(":<]", pathname[dirname_len - 1]) == NULL) +#endif + pathname[dirname_len++] = '/'; + pathname[dirname_len] = '\0'; + } + strcpy(pathname + dirname_len, filename); + testfile(pathname); + } + OPENSSL_DIR_end(&ctx); + + /* If it wasn't a directory, treat it as a file instead */ + if (!wasdir) + testfile(argv[n]); + + free(pathname); + } + + FuzzerCleanup(); + + return 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/fuzz/x509.c b/trunk/3rdparty/openssl-1.1-fit/fuzz/x509.c new file mode 100644 index 000000000..926287da4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/fuzz/x509.c @@ -0,0 +1,51 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL licenses, (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * https://www.openssl.org/source/license.html + * or in the file LICENSE in the source distribution. + */ + +#include +#include +#include +#include +#include "fuzzer.h" + +#include "rand.inc" + +int FuzzerInitialize(int *argc, char ***argv) +{ + OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); + ERR_get_state(); + CRYPTO_free_ex_index(0, -1); + FuzzerSetRand(); + return 1; +} + +int FuzzerTestOneInput(const uint8_t *buf, size_t len) +{ + const unsigned char *p = buf; + unsigned char *der = NULL; + + X509 *x509 = d2i_X509(NULL, &p, len); + if (x509 != NULL) { + BIO *bio = BIO_new(BIO_s_null()); + /* This will load and print the public key as well as extensions */ + X509_print(bio, x509); + BIO_free(bio); + + i2d_X509(x509, &der); + OPENSSL_free(der); + + X509_free(x509); + } + ERR_clear_error(); + return 0; +} + +void FuzzerCleanup(void) +{ +} diff --git a/trunk/3rdparty/openssl-1.1-fit/include/internal/__DECC_INCLUDE_EPILOGUE.H b/trunk/3rdparty/openssl-1.1-fit/include/internal/__DECC_INCLUDE_EPILOGUE.H new file mode 100644 index 000000000..c350018ad --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/internal/__DECC_INCLUDE_EPILOGUE.H @@ -0,0 +1,16 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This file is only used by HP C on VMS, and is included automatically + * after each header file from this directory + */ + +/* restore state. Must correspond to the save in __decc_include_prologue.h */ +#pragma names restore diff --git a/trunk/3rdparty/openssl-1.1-fit/include/internal/__DECC_INCLUDE_PROLOGUE.H b/trunk/3rdparty/openssl-1.1-fit/include/internal/__DECC_INCLUDE_PROLOGUE.H new file mode 100644 index 000000000..9a9c777f9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/internal/__DECC_INCLUDE_PROLOGUE.H @@ -0,0 +1,20 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This file is only used by HP C on VMS, and is included automatically + * after each header file from this directory + */ + +/* save state */ +#pragma names save +/* have the compiler shorten symbols larger than 31 chars to 23 chars + * followed by a 8 hex char CRC + */ +#pragma names as_is,shortened diff --git a/trunk/3rdparty/openssl-1.1-fit/include/internal/bio.h b/trunk/3rdparty/openssl-1.1-fit/include/internal/bio.h new file mode 100644 index 000000000..c343b2762 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/internal/bio.h @@ -0,0 +1,33 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +struct bio_method_st { + int type; + char *name; + int (*bwrite) (BIO *, const char *, size_t, size_t *); + int (*bwrite_old) (BIO *, const char *, int); + int (*bread) (BIO *, char *, size_t, size_t *); + int (*bread_old) (BIO *, char *, int); + int (*bputs) (BIO *, const char *); + int (*bgets) (BIO *, char *, int); + long (*ctrl) (BIO *, int, long, void *); + int (*create) (BIO *); + int (*destroy) (BIO *); + long (*callback_ctrl) (BIO *, int, BIO_info_cb *); +}; + +void bio_free_ex_data(BIO *bio); +void bio_cleanup(void); + + +/* Old style to new style BIO_METHOD conversion functions */ +int bwrite_conv(BIO *bio, const char *data, size_t datal, size_t *written); +int bread_conv(BIO *bio, char *data, size_t datal, size_t *read); diff --git a/trunk/3rdparty/openssl-1.1-fit/include/internal/comp.h b/trunk/3rdparty/openssl-1.1-fit/include/internal/comp.h new file mode 100644 index 000000000..ac6e38b47 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/internal/comp.h @@ -0,0 +1,12 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +void comp_zlib_cleanup_int(void); diff --git a/trunk/3rdparty/openssl-1.1-fit/include/internal/conf.h b/trunk/3rdparty/openssl-1.1-fit/include/internal/conf.h new file mode 100644 index 000000000..29bc9f963 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/internal/conf.h @@ -0,0 +1,30 @@ +/* + * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_INTERNAL_CONF_H +# define HEADER_INTERNAL_CONF_H + +#include + +#define DEFAULT_CONF_MFLAGS \ + (CONF_MFLAGS_DEFAULT_SECTION | \ + CONF_MFLAGS_IGNORE_MISSING_FILE | \ + CONF_MFLAGS_IGNORE_RETURN_CODES) + +struct ossl_init_settings_st { + char *filename; + char *appname; + unsigned long flags; +}; + +int openssl_config_int(const OPENSSL_INIT_SETTINGS *); +void openssl_no_config_int(void); +void conf_modules_free_int(void); + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/internal/constant_time_locl.h b/trunk/3rdparty/openssl-1.1-fit/include/internal/constant_time_locl.h new file mode 100644 index 000000000..cde30f406 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/internal/constant_time_locl.h @@ -0,0 +1,333 @@ +/* + * Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_CONSTANT_TIME_LOCL_H +# define HEADER_CONSTANT_TIME_LOCL_H + +# include +# include +# include /* For 'ossl_inline' */ + +/*- + * The boolean methods return a bitmask of all ones (0xff...f) for true + * and 0 for false. This is useful for choosing a value based on the result + * of a conditional in constant time. For example, + * if (a < b) { + * c = a; + * } else { + * c = b; + * } + * can be written as + * unsigned int lt = constant_time_lt(a, b); + * c = constant_time_select(lt, a, b); + */ + +/* Returns the given value with the MSB copied to all the other bits. */ +static ossl_inline unsigned int constant_time_msb(unsigned int a); +/* Convenience method for uint32_t. */ +static ossl_inline uint32_t constant_time_msb_32(uint32_t a); +/* Convenience method for uint64_t. */ +static ossl_inline uint64_t constant_time_msb_64(uint64_t a); + +/* Returns 0xff..f if a < b and 0 otherwise. */ +static ossl_inline unsigned int constant_time_lt(unsigned int a, + unsigned int b); +/* Convenience method for getting an 8-bit mask. */ +static ossl_inline unsigned char constant_time_lt_8(unsigned int a, + unsigned int b); +/* Convenience method for uint64_t. */ +static ossl_inline uint64_t constant_time_lt_64(uint64_t a, uint64_t b); + +/* Returns 0xff..f if a >= b and 0 otherwise. */ +static ossl_inline unsigned int constant_time_ge(unsigned int a, + unsigned int b); +/* Convenience method for getting an 8-bit mask. */ +static ossl_inline unsigned char constant_time_ge_8(unsigned int a, + unsigned int b); + +/* Returns 0xff..f if a == 0 and 0 otherwise. */ +static ossl_inline unsigned int constant_time_is_zero(unsigned int a); +/* Convenience method for getting an 8-bit mask. */ +static ossl_inline unsigned char constant_time_is_zero_8(unsigned int a); +/* Convenience method for getting a 32-bit mask. */ +static ossl_inline uint32_t constant_time_is_zero_32(uint32_t a); + +/* Returns 0xff..f if a == b and 0 otherwise. */ +static ossl_inline unsigned int constant_time_eq(unsigned int a, + unsigned int b); +/* Convenience method for getting an 8-bit mask. */ +static ossl_inline unsigned char constant_time_eq_8(unsigned int a, + unsigned int b); +/* Signed integers. */ +static ossl_inline unsigned int constant_time_eq_int(int a, int b); +/* Convenience method for getting an 8-bit mask. */ +static ossl_inline unsigned char constant_time_eq_int_8(int a, int b); + +/*- + * Returns (mask & a) | (~mask & b). + * + * When |mask| is all 1s or all 0s (as returned by the methods above), + * the select methods return either |a| (if |mask| is nonzero) or |b| + * (if |mask| is zero). + */ +static ossl_inline unsigned int constant_time_select(unsigned int mask, + unsigned int a, + unsigned int b); +/* Convenience method for unsigned chars. */ +static ossl_inline unsigned char constant_time_select_8(unsigned char mask, + unsigned char a, + unsigned char b); + +/* Convenience method for uint32_t. */ +static ossl_inline uint32_t constant_time_select_32(uint32_t mask, uint32_t a, + uint32_t b); + +/* Convenience method for uint64_t. */ +static ossl_inline uint64_t constant_time_select_64(uint64_t mask, uint64_t a, + uint64_t b); +/* Convenience method for signed integers. */ +static ossl_inline int constant_time_select_int(unsigned int mask, int a, + int b); + + +static ossl_inline unsigned int constant_time_msb(unsigned int a) +{ + return 0 - (a >> (sizeof(a) * 8 - 1)); +} + + +static ossl_inline uint32_t constant_time_msb_32(uint32_t a) +{ + return 0 - (a >> 31); +} + +static ossl_inline uint64_t constant_time_msb_64(uint64_t a) +{ + return 0 - (a >> 63); +} + +static ossl_inline size_t constant_time_msb_s(size_t a) +{ + return 0 - (a >> (sizeof(a) * 8 - 1)); +} + +static ossl_inline unsigned int constant_time_lt(unsigned int a, + unsigned int b) +{ + return constant_time_msb(a ^ ((a ^ b) | ((a - b) ^ b))); +} + +static ossl_inline size_t constant_time_lt_s(size_t a, size_t b) +{ + return constant_time_msb_s(a ^ ((a ^ b) | ((a - b) ^ b))); +} + +static ossl_inline unsigned char constant_time_lt_8(unsigned int a, + unsigned int b) +{ + return (unsigned char)constant_time_lt(a, b); +} + +static ossl_inline uint64_t constant_time_lt_64(uint64_t a, uint64_t b) +{ + return constant_time_msb_64(a ^ ((a ^ b) | ((a - b) ^ b))); +} + +static ossl_inline unsigned int constant_time_ge(unsigned int a, + unsigned int b) +{ + return ~constant_time_lt(a, b); +} + +static ossl_inline size_t constant_time_ge_s(size_t a, size_t b) +{ + return ~constant_time_lt_s(a, b); +} + +static ossl_inline unsigned char constant_time_ge_8(unsigned int a, + unsigned int b) +{ + return (unsigned char)constant_time_ge(a, b); +} + +static ossl_inline unsigned char constant_time_ge_8_s(size_t a, size_t b) +{ + return (unsigned char)constant_time_ge_s(a, b); +} + +static ossl_inline unsigned int constant_time_is_zero(unsigned int a) +{ + return constant_time_msb(~a & (a - 1)); +} + +static ossl_inline size_t constant_time_is_zero_s(size_t a) +{ + return constant_time_msb_s(~a & (a - 1)); +} + +static ossl_inline unsigned char constant_time_is_zero_8(unsigned int a) +{ + return (unsigned char)constant_time_is_zero(a); +} + +static ossl_inline uint32_t constant_time_is_zero_32(uint32_t a) +{ + return constant_time_msb_32(~a & (a - 1)); +} + +static ossl_inline unsigned int constant_time_eq(unsigned int a, + unsigned int b) +{ + return constant_time_is_zero(a ^ b); +} + +static ossl_inline size_t constant_time_eq_s(size_t a, size_t b) +{ + return constant_time_is_zero_s(a ^ b); +} + +static ossl_inline unsigned char constant_time_eq_8(unsigned int a, + unsigned int b) +{ + return (unsigned char)constant_time_eq(a, b); +} + +static ossl_inline unsigned char constant_time_eq_8_s(size_t a, size_t b) +{ + return (unsigned char)constant_time_eq_s(a, b); +} + +static ossl_inline unsigned int constant_time_eq_int(int a, int b) +{ + return constant_time_eq((unsigned)(a), (unsigned)(b)); +} + +static ossl_inline unsigned char constant_time_eq_int_8(int a, int b) +{ + return constant_time_eq_8((unsigned)(a), (unsigned)(b)); +} + +static ossl_inline unsigned int constant_time_select(unsigned int mask, + unsigned int a, + unsigned int b) +{ + return (mask & a) | (~mask & b); +} + +static ossl_inline size_t constant_time_select_s(size_t mask, + size_t a, + size_t b) +{ + return (mask & a) | (~mask & b); +} + +static ossl_inline unsigned char constant_time_select_8(unsigned char mask, + unsigned char a, + unsigned char b) +{ + return (unsigned char)constant_time_select(mask, a, b); +} + +static ossl_inline int constant_time_select_int(unsigned int mask, int a, + int b) +{ + return (int)constant_time_select(mask, (unsigned)(a), (unsigned)(b)); +} + +static ossl_inline int constant_time_select_int_s(size_t mask, int a, int b) +{ + return (int)constant_time_select((unsigned)mask, (unsigned)(a), + (unsigned)(b)); +} + +static ossl_inline uint32_t constant_time_select_32(uint32_t mask, uint32_t a, + uint32_t b) +{ + return (mask & a) | (~mask & b); +} + +static ossl_inline uint64_t constant_time_select_64(uint64_t mask, uint64_t a, + uint64_t b) +{ + return (mask & a) | (~mask & b); +} + +/* + * mask must be 0xFFFFFFFF or 0x00000000. + * + * if (mask) { + * uint32_t tmp = *a; + * + * *a = *b; + * *b = tmp; + * } + */ +static ossl_inline void constant_time_cond_swap_32(uint32_t mask, uint32_t *a, + uint32_t *b) +{ + uint32_t xor = *a ^ *b; + + xor &= mask; + *a ^= xor; + *b ^= xor; +} + +/* + * mask must be 0xFFFFFFFF or 0x00000000. + * + * if (mask) { + * uint64_t tmp = *a; + * + * *a = *b; + * *b = tmp; + * } + */ +static ossl_inline void constant_time_cond_swap_64(uint64_t mask, uint64_t *a, + uint64_t *b) +{ + uint64_t xor = *a ^ *b; + + xor &= mask; + *a ^= xor; + *b ^= xor; +} + +/* + * table is a two dimensional array of bytes. Each row has rowsize elements. + * Copies row number idx into out. rowsize and numrows are not considered + * private. + */ +static ossl_inline void constant_time_lookup(void *out, + const void *table, + size_t rowsize, + size_t numrows, + size_t idx) +{ + size_t i, j; + const unsigned char *tablec = (const unsigned char *)table; + unsigned char *outc = (unsigned char *)out; + unsigned char mask; + + memset(out, 0, rowsize); + + /* Note idx may underflow - but that is well defined */ + for (i = 0; i < numrows; i++, idx--) { + mask = (unsigned char)constant_time_is_zero_s(idx); + for (j = 0; j < rowsize; j++) + *(outc + j) |= constant_time_select_8(mask, *(tablec++), 0); + } +} + +/* + * Expected usage pattern is to unconditionally set error and then + * wipe it if there was no actual error. |clear| is 1 or 0. + */ +void err_clear_last_constant_time(int clear); + +#endif /* HEADER_CONSTANT_TIME_LOCL_H */ diff --git a/trunk/3rdparty/openssl-1.1-fit/include/internal/cryptlib.h b/trunk/3rdparty/openssl-1.1-fit/include/internal/cryptlib.h new file mode 100644 index 000000000..b4d76d5f2 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/internal/cryptlib.h @@ -0,0 +1,98 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_CRYPTLIB_H +# define HEADER_CRYPTLIB_H + +# include +# include + +# ifdef OPENSSL_USE_APPLINK +# undef BIO_FLAGS_UPLINK +# define BIO_FLAGS_UPLINK 0x8000 +# include "ms/uplink.h" +# endif + +# include +# include +# include +# include +# include "internal/nelem.h" + +#ifdef NDEBUG +# define ossl_assert(x) ((x) != 0) +#else +__owur static ossl_inline int ossl_assert_int(int expr, const char *exprstr, + const char *file, int line) +{ + if (!expr) + OPENSSL_die(exprstr, file, line); + + return expr; +} + +# define ossl_assert(x) ossl_assert_int((x) != 0, "Assertion failed: "#x, \ + __FILE__, __LINE__) + +#endif + +typedef struct ex_callback_st EX_CALLBACK; + +DEFINE_STACK_OF(EX_CALLBACK) + +typedef struct app_mem_info_st APP_INFO; + +typedef struct mem_st MEM; +DEFINE_LHASH_OF(MEM); + +# define OPENSSL_CONF "openssl.cnf" + +# ifndef OPENSSL_SYS_VMS +# define X509_CERT_AREA OPENSSLDIR +# define X509_CERT_DIR OPENSSLDIR "/certs" +# define X509_CERT_FILE OPENSSLDIR "/cert.pem" +# define X509_PRIVATE_DIR OPENSSLDIR "/private" +# define CTLOG_FILE OPENSSLDIR "/ct_log_list.cnf" +# else +# define X509_CERT_AREA "OSSL$DATAROOT:[000000]" +# define X509_CERT_DIR "OSSL$DATAROOT:[CERTS]" +# define X509_CERT_FILE "OSSL$DATAROOT:[000000]cert.pem" +# define X509_PRIVATE_DIR "OSSL$DATAROOT:[PRIVATE]" +# define CTLOG_FILE "OSSL$DATAROOT:[000000]ct_log_list.cnf" +# endif + +# define X509_CERT_DIR_EVP "SSL_CERT_DIR" +# define X509_CERT_FILE_EVP "SSL_CERT_FILE" +# define CTLOG_FILE_EVP "CTLOG_FILE" + +/* size of string representations */ +# define DECIMAL_SIZE(type) ((sizeof(type)*8+2)/3+1) +# define HEX_SIZE(type) (sizeof(type)*2) + +void OPENSSL_cpuid_setup(void); +extern unsigned int OPENSSL_ia32cap_P[]; +void OPENSSL_showfatal(const char *fmta, ...); +void crypto_cleanup_all_ex_data_int(void); +int openssl_init_fork_handlers(void); + +char *ossl_safe_getenv(const char *name); + +extern CRYPTO_RWLOCK *memdbg_lock; +int openssl_strerror_r(int errnum, char *buf, size_t buflen); +# if !defined(OPENSSL_NO_STDIO) +FILE *openssl_fopen(const char *filename, const char *mode); +# else +void *openssl_fopen(const char *filename, const char *mode); +# endif + +uint32_t OPENSSL_rdtsc(void); +size_t OPENSSL_instrument_bus(unsigned int *, size_t); +size_t OPENSSL_instrument_bus2(unsigned int *, size_t, size_t); + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/internal/dane.h b/trunk/3rdparty/openssl-1.1-fit/include/internal/dane.h new file mode 100644 index 000000000..a1cb5488b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/internal/dane.h @@ -0,0 +1,103 @@ +/* + * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_INTERNAL_DANE_H +#define HEADER_INTERNAL_DANE_H + +#include + +/*- + * Certificate usages: + * https://tools.ietf.org/html/rfc6698#section-2.1.1 + */ +#define DANETLS_USAGE_PKIX_TA 0 +#define DANETLS_USAGE_PKIX_EE 1 +#define DANETLS_USAGE_DANE_TA 2 +#define DANETLS_USAGE_DANE_EE 3 +#define DANETLS_USAGE_LAST DANETLS_USAGE_DANE_EE + +/*- + * Selectors: + * https://tools.ietf.org/html/rfc6698#section-2.1.2 + */ +#define DANETLS_SELECTOR_CERT 0 +#define DANETLS_SELECTOR_SPKI 1 +#define DANETLS_SELECTOR_LAST DANETLS_SELECTOR_SPKI + +/*- + * Matching types: + * https://tools.ietf.org/html/rfc6698#section-2.1.3 + */ +#define DANETLS_MATCHING_FULL 0 +#define DANETLS_MATCHING_2256 1 +#define DANETLS_MATCHING_2512 2 +#define DANETLS_MATCHING_LAST DANETLS_MATCHING_2512 + +typedef struct danetls_record_st { + uint8_t usage; + uint8_t selector; + uint8_t mtype; + unsigned char *data; + size_t dlen; + EVP_PKEY *spki; +} danetls_record; + +DEFINE_STACK_OF(danetls_record) + +/* + * Shared DANE context + */ +struct dane_ctx_st { + const EVP_MD **mdevp; /* mtype -> digest */ + uint8_t *mdord; /* mtype -> preference */ + uint8_t mdmax; /* highest supported mtype */ + unsigned long flags; /* feature bitmask */ +}; + +/* + * Per connection DANE state + */ +struct ssl_dane_st { + struct dane_ctx_st *dctx; + STACK_OF(danetls_record) *trecs; + STACK_OF(X509) *certs; /* DANE-TA(2) Cert(0) Full(0) certs */ + danetls_record *mtlsa; /* Matching TLSA record */ + X509 *mcert; /* DANE matched cert */ + uint32_t umask; /* Usages present */ + int mdpth; /* Depth of matched cert */ + int pdpth; /* Depth of PKIX trust */ + unsigned long flags; /* feature bitmask */ +}; + +#define DANETLS_ENABLED(dane) \ + ((dane) != NULL && sk_danetls_record_num((dane)->trecs) > 0) + +#define DANETLS_USAGE_BIT(u) (((uint32_t)1) << u) + +#define DANETLS_PKIX_TA_MASK (DANETLS_USAGE_BIT(DANETLS_USAGE_PKIX_TA)) +#define DANETLS_PKIX_EE_MASK (DANETLS_USAGE_BIT(DANETLS_USAGE_PKIX_EE)) +#define DANETLS_DANE_TA_MASK (DANETLS_USAGE_BIT(DANETLS_USAGE_DANE_TA)) +#define DANETLS_DANE_EE_MASK (DANETLS_USAGE_BIT(DANETLS_USAGE_DANE_EE)) + +#define DANETLS_PKIX_MASK (DANETLS_PKIX_TA_MASK | DANETLS_PKIX_EE_MASK) +#define DANETLS_DANE_MASK (DANETLS_DANE_TA_MASK | DANETLS_DANE_EE_MASK) +#define DANETLS_TA_MASK (DANETLS_PKIX_TA_MASK | DANETLS_DANE_TA_MASK) +#define DANETLS_EE_MASK (DANETLS_PKIX_EE_MASK | DANETLS_DANE_EE_MASK) + +#define DANETLS_HAS_PKIX(dane) ((dane) && ((dane)->umask & DANETLS_PKIX_MASK)) +#define DANETLS_HAS_DANE(dane) ((dane) && ((dane)->umask & DANETLS_DANE_MASK)) +#define DANETLS_HAS_TA(dane) ((dane) && ((dane)->umask & DANETLS_TA_MASK)) +#define DANETLS_HAS_EE(dane) ((dane) && ((dane)->umask & DANETLS_EE_MASK)) + +#define DANETLS_HAS_PKIX_TA(dane) ((dane)&&((dane)->umask & DANETLS_PKIX_TA_MASK)) +#define DANETLS_HAS_PKIX_EE(dane) ((dane)&&((dane)->umask & DANETLS_PKIX_EE_MASK)) +#define DANETLS_HAS_DANE_TA(dane) ((dane)&&((dane)->umask & DANETLS_DANE_TA_MASK)) +#define DANETLS_HAS_DANE_EE(dane) ((dane)&&((dane)->umask & DANETLS_DANE_EE_MASK)) + +#endif /* HEADER_INTERNAL_DANE_H */ diff --git a/trunk/3rdparty/openssl-1.1-fit/include/internal/dso.h b/trunk/3rdparty/openssl-1.1-fit/include/internal/dso.h new file mode 100644 index 000000000..eb5f7d53c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/internal/dso.h @@ -0,0 +1,165 @@ +/* + * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_DSO_H +# define HEADER_DSO_H + +# include +# include "internal/dsoerr.h" + +/* These values are used as commands to DSO_ctrl() */ +# define DSO_CTRL_GET_FLAGS 1 +# define DSO_CTRL_SET_FLAGS 2 +# define DSO_CTRL_OR_FLAGS 3 + +/* + * By default, DSO_load() will translate the provided filename into a form + * typical for the platform using the dso_name_converter function of the + * method. Eg. win32 will transform "blah" into "blah.dll", and dlfcn will + * transform it into "libblah.so". This callback could even utilise the + * DSO_METHOD's converter too if it only wants to override behaviour for + * one or two possible DSO methods. However, the following flag can be + * set in a DSO to prevent *any* native name-translation at all - eg. if + * the caller has prompted the user for a path to a driver library so the + * filename should be interpreted as-is. + */ +# define DSO_FLAG_NO_NAME_TRANSLATION 0x01 +/* + * An extra flag to give if only the extension should be added as + * translation. This is obviously only of importance on Unix and other + * operating systems where the translation also may prefix the name with + * something, like 'lib', and ignored everywhere else. This flag is also + * ignored if DSO_FLAG_NO_NAME_TRANSLATION is used at the same time. + */ +# define DSO_FLAG_NAME_TRANSLATION_EXT_ONLY 0x02 + +/* + * Don't unload the DSO when we call DSO_free() + */ +# define DSO_FLAG_NO_UNLOAD_ON_FREE 0x04 + +/* + * This flag loads the library with public symbols. Meaning: The exported + * symbols of this library are public to all libraries loaded after this + * library. At the moment only implemented in unix. + */ +# define DSO_FLAG_GLOBAL_SYMBOLS 0x20 + +typedef void (*DSO_FUNC_TYPE) (void); + +typedef struct dso_st DSO; +typedef struct dso_meth_st DSO_METHOD; + +/* + * The function prototype used for method functions (or caller-provided + * callbacks) that transform filenames. They are passed a DSO structure + * pointer (or NULL if they are to be used independently of a DSO object) and + * a filename to transform. They should either return NULL (if there is an + * error condition) or a newly allocated string containing the transformed + * form that the caller will need to free with OPENSSL_free() when done. + */ +typedef char *(*DSO_NAME_CONVERTER_FUNC)(DSO *, const char *); +/* + * The function prototype used for method functions (or caller-provided + * callbacks) that merge two file specifications. They are passed a DSO + * structure pointer (or NULL if they are to be used independently of a DSO + * object) and two file specifications to merge. They should either return + * NULL (if there is an error condition) or a newly allocated string + * containing the result of merging that the caller will need to free with + * OPENSSL_free() when done. Here, merging means that bits and pieces are + * taken from each of the file specifications and added together in whatever + * fashion that is sensible for the DSO method in question. The only rule + * that really applies is that if the two specification contain pieces of the + * same type, the copy from the first string takes priority. One could see + * it as the first specification is the one given by the user and the second + * being a bunch of defaults to add on if they're missing in the first. + */ +typedef char *(*DSO_MERGER_FUNC)(DSO *, const char *, const char *); + +DSO *DSO_new(void); +int DSO_free(DSO *dso); +int DSO_flags(DSO *dso); +int DSO_up_ref(DSO *dso); +long DSO_ctrl(DSO *dso, int cmd, long larg, void *parg); + +/* + * These functions can be used to get/set the platform-independent filename + * used for a DSO. NB: set will fail if the DSO is already loaded. + */ +const char *DSO_get_filename(DSO *dso); +int DSO_set_filename(DSO *dso, const char *filename); +/* + * This function will invoke the DSO's name_converter callback to translate a + * filename, or if the callback isn't set it will instead use the DSO_METHOD's + * converter. If "filename" is NULL, the "filename" in the DSO itself will be + * used. If the DSO_FLAG_NO_NAME_TRANSLATION flag is set, then the filename is + * simply duplicated. NB: This function is usually called from within a + * DSO_METHOD during the processing of a DSO_load() call, and is exposed so + * that caller-created DSO_METHODs can do the same thing. A non-NULL return + * value will need to be OPENSSL_free()'d. + */ +char *DSO_convert_filename(DSO *dso, const char *filename); +/* + * This function will invoke the DSO's merger callback to merge two file + * specifications, or if the callback isn't set it will instead use the + * DSO_METHOD's merger. A non-NULL return value will need to be + * OPENSSL_free()'d. + */ +char *DSO_merge(DSO *dso, const char *filespec1, const char *filespec2); + +/* + * The all-singing all-dancing load function, you normally pass NULL for the + * first and third parameters. Use DSO_up_ref and DSO_free for subsequent + * reference count handling. Any flags passed in will be set in the + * constructed DSO after its init() function but before the load operation. + * If 'dso' is non-NULL, 'flags' is ignored. + */ +DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth, int flags); + +/* This function binds to a function inside a shared library. */ +DSO_FUNC_TYPE DSO_bind_func(DSO *dso, const char *symname); + +/* + * This method is the default, but will beg, borrow, or steal whatever method + * should be the default on any particular platform (including + * DSO_METH_null() if necessary). + */ +DSO_METHOD *DSO_METHOD_openssl(void); + +/* + * This function writes null-terminated pathname of DSO module containing + * 'addr' into 'sz' large caller-provided 'path' and returns the number of + * characters [including trailing zero] written to it. If 'sz' is 0 or + * negative, 'path' is ignored and required amount of characters [including + * trailing zero] to accommodate pathname is returned. If 'addr' is NULL, then + * pathname of cryptolib itself is returned. Negative or zero return value + * denotes error. + */ +int DSO_pathbyaddr(void *addr, char *path, int sz); + +/* + * Like DSO_pathbyaddr() but instead returns a handle to the DSO for the symbol + * or NULL on error. + */ +DSO *DSO_dsobyaddr(void *addr, int flags); + +/* + * This function should be used with caution! It looks up symbols in *all* + * loaded modules and if module gets unloaded by somebody else attempt to + * dereference the pointer is doomed to have fatal consequences. Primary + * usage for this function is to probe *core* system functionality, e.g. + * check if getnameinfo(3) is available at run-time without bothering about + * OS-specific details such as libc.so.versioning or where does it actually + * reside: in libc itself or libsocket. + */ +void *DSO_global_lookup(const char *name); + +int ERR_load_DSO_strings(void); + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/internal/dsoerr.h b/trunk/3rdparty/openssl-1.1-fit/include/internal/dsoerr.h new file mode 100644 index 000000000..a54a18545 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/internal/dsoerr.h @@ -0,0 +1,83 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_DSOERR_H +# define HEADER_DSOERR_H + +# include + +# ifndef OPENSSL_NO_DSO + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_DSO_strings(void); + +/* + * DSO function codes. + */ +# define DSO_F_DLFCN_BIND_FUNC 100 +# define DSO_F_DLFCN_LOAD 102 +# define DSO_F_DLFCN_MERGER 130 +# define DSO_F_DLFCN_NAME_CONVERTER 123 +# define DSO_F_DLFCN_UNLOAD 103 +# define DSO_F_DL_BIND_FUNC 104 +# define DSO_F_DL_LOAD 106 +# define DSO_F_DL_MERGER 131 +# define DSO_F_DL_NAME_CONVERTER 124 +# define DSO_F_DL_UNLOAD 107 +# define DSO_F_DSO_BIND_FUNC 108 +# define DSO_F_DSO_CONVERT_FILENAME 126 +# define DSO_F_DSO_CTRL 110 +# define DSO_F_DSO_FREE 111 +# define DSO_F_DSO_GET_FILENAME 127 +# define DSO_F_DSO_GLOBAL_LOOKUP 139 +# define DSO_F_DSO_LOAD 112 +# define DSO_F_DSO_MERGE 132 +# define DSO_F_DSO_NEW_METHOD 113 +# define DSO_F_DSO_PATHBYADDR 105 +# define DSO_F_DSO_SET_FILENAME 129 +# define DSO_F_DSO_UP_REF 114 +# define DSO_F_VMS_BIND_SYM 115 +# define DSO_F_VMS_LOAD 116 +# define DSO_F_VMS_MERGER 133 +# define DSO_F_VMS_UNLOAD 117 +# define DSO_F_WIN32_BIND_FUNC 101 +# define DSO_F_WIN32_GLOBALLOOKUP 142 +# define DSO_F_WIN32_JOINER 135 +# define DSO_F_WIN32_LOAD 120 +# define DSO_F_WIN32_MERGER 134 +# define DSO_F_WIN32_NAME_CONVERTER 125 +# define DSO_F_WIN32_PATHBYADDR 109 +# define DSO_F_WIN32_SPLITTER 136 +# define DSO_F_WIN32_UNLOAD 121 + +/* + * DSO reason codes. + */ +# define DSO_R_CTRL_FAILED 100 +# define DSO_R_DSO_ALREADY_LOADED 110 +# define DSO_R_EMPTY_FILE_STRUCTURE 113 +# define DSO_R_FAILURE 114 +# define DSO_R_FILENAME_TOO_BIG 101 +# define DSO_R_FINISH_FAILED 102 +# define DSO_R_INCORRECT_FILE_SYNTAX 115 +# define DSO_R_LOAD_FAILED 103 +# define DSO_R_NAME_TRANSLATION_FAILED 109 +# define DSO_R_NO_FILENAME 111 +# define DSO_R_NULL_HANDLE 104 +# define DSO_R_SET_FILENAME_FAILED 112 +# define DSO_R_STACK_ERROR 105 +# define DSO_R_SYM_FAILURE 106 +# define DSO_R_UNLOAD_FAILED 107 +# define DSO_R_UNSUPPORTED 108 + +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/internal/err.h b/trunk/3rdparty/openssl-1.1-fit/include/internal/err.h new file mode 100644 index 000000000..d46b8bdb2 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/internal/err.h @@ -0,0 +1,15 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef INTERNAL_ERR_H +# define INTERNAL_ERR_H + +void err_free_strings_int(void); + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/internal/nelem.h b/trunk/3rdparty/openssl-1.1-fit/include/internal/nelem.h new file mode 100644 index 000000000..d65a21a9f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/internal/nelem.h @@ -0,0 +1,14 @@ +/* + * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_NELEM_H +# define HEADER_NELEM_H + +# define OSSL_NELEM(x) (sizeof(x)/sizeof((x)[0])) +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/internal/numbers.h b/trunk/3rdparty/openssl-1.1-fit/include/internal/numbers.h new file mode 100644 index 000000000..31931df3c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/internal/numbers.h @@ -0,0 +1,68 @@ +/* + * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_NUMBERS_H +# define HEADER_NUMBERS_H + +# include + +# if (-1 & 3) == 0x03 /* Two's complement */ + +# define __MAXUINT__(T) ((T) -1) +# define __MAXINT__(T) ((T) ((((T) 1) << ((sizeof(T) * CHAR_BIT) - 1)) ^ __MAXUINT__(T))) +# define __MININT__(T) (-__MAXINT__(T) - 1) + +# elif (-1 & 3) == 0x02 /* One's complement */ + +# define __MAXUINT__(T) (((T) -1) + 1) +# define __MAXINT__(T) ((T) ((((T) 1) << ((sizeof(T) * CHAR_BIT) - 1)) ^ __MAXUINT__(T))) +# define __MININT__(T) (-__MAXINT__(T)) + +# elif (-1 & 3) == 0x01 /* Sign/magnitude */ + +# define __MAXINT__(T) ((T) (((((T) 1) << ((sizeof(T) * CHAR_BIT) - 2)) - 1) | (((T) 1) << ((sizeof(T) * CHAR_BIT) - 2)))) +# define __MAXUINT__(T) ((T) (__MAXINT__(T) | (((T) 1) << ((sizeof(T) * CHAR_BIT) - 1)))) +# define __MININT__(T) (-__MAXINT__(T)) + +# else + +# error "do not know the integer encoding on this architecture" + +# endif + +# ifndef INT8_MAX +# define INT8_MIN __MININT__(int8_t) +# define INT8_MAX __MAXINT__(int8_t) +# define UINT8_MAX __MAXUINT__(uint8_t) +# endif + +# ifndef INT16_MAX +# define INT16_MIN __MININT__(int16_t) +# define INT16_MAX __MAXINT__(int16_t) +# define UINT16_MAX __MAXUINT__(uint16_t) +# endif + +# ifndef INT32_MAX +# define INT32_MIN __MININT__(int32_t) +# define INT32_MAX __MAXINT__(int32_t) +# define UINT32_MAX __MAXUINT__(uint32_t) +# endif + +# ifndef INT64_MAX +# define INT64_MIN __MININT__(int64_t) +# define INT64_MAX __MAXINT__(int64_t) +# define UINT64_MAX __MAXUINT__(uint64_t) +# endif + +# ifndef SIZE_MAX +# define SIZE_MAX __MAXUINT__(size_t) +# endif + +#endif + diff --git a/trunk/3rdparty/openssl-1.1-fit/include/internal/o_dir.h b/trunk/3rdparty/openssl-1.1-fit/include/internal/o_dir.h new file mode 100644 index 000000000..e7b55e0c1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/internal/o_dir.h @@ -0,0 +1,52 @@ +/* + * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This file is dual-licensed and is also available under the following + * terms: + * + * Copyright (c) 2004, Richard Levitte + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef O_DIR_H +# define O_DIR_H + +typedef struct OPENSSL_dir_context_st OPENSSL_DIR_CTX; + +/* + * returns NULL on error or end-of-directory. If it is end-of-directory, + * errno will be zero + */ +const char *OPENSSL_DIR_read(OPENSSL_DIR_CTX **ctx, const char *directory); +/* returns 1 on success, 0 on error */ +int OPENSSL_DIR_end(OPENSSL_DIR_CTX **ctx); + +#endif /* LPDIR_H */ diff --git a/trunk/3rdparty/openssl-1.1-fit/include/internal/o_str.h b/trunk/3rdparty/openssl-1.1-fit/include/internal/o_str.h new file mode 100644 index 000000000..86403c9ee --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/internal/o_str.h @@ -0,0 +1,17 @@ +/* + * Copyright 2003-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_O_STR_H +# define HEADER_O_STR_H + +# include /* to get size_t */ + +int OPENSSL_memcmp(const void *p1, const void *p2, size_t n); + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/internal/refcount.h b/trunk/3rdparty/openssl-1.1-fit/include/internal/refcount.h new file mode 100644 index 000000000..75d70a641 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/internal/refcount.h @@ -0,0 +1,140 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ +#ifndef HEADER_INTERNAL_REFCOUNT_H +# define HEADER_INTERNAL_REFCOUNT_H + +/* Used to checking reference counts, most while doing perl5 stuff :-) */ +# if defined(OPENSSL_NO_STDIO) +# if defined(REF_PRINT) +# error "REF_PRINT requires stdio" +# endif +# endif + +# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L \ + && !defined(__STDC_NO_ATOMICS__) +# include +# define HAVE_C11_ATOMICS +# endif + +# if defined(HAVE_C11_ATOMICS) && defined(ATOMIC_INT_LOCK_FREE) \ + && ATOMIC_INT_LOCK_FREE > 0 + +# define HAVE_ATOMICS 1 + +typedef _Atomic int CRYPTO_REF_COUNT; + +static inline int CRYPTO_UP_REF(_Atomic int *val, int *ret, void *lock) +{ + *ret = atomic_fetch_add_explicit(val, 1, memory_order_relaxed) + 1; + return 1; +} + +/* + * Changes to shared structure other than reference counter have to be + * serialized. And any kind of serialization implies a release fence. This + * means that by the time reference counter is decremented all other + * changes are visible on all processors. Hence decrement itself can be + * relaxed. In case it hits zero, object will be destructed. Since it's + * last use of the object, destructor programmer might reason that access + * to mutable members doesn't have to be serialized anymore, which would + * otherwise imply an acquire fence. Hence conditional acquire fence... + */ +static inline int CRYPTO_DOWN_REF(_Atomic int *val, int *ret, void *lock) +{ + *ret = atomic_fetch_sub_explicit(val, 1, memory_order_relaxed) - 1; + if (*ret == 0) + atomic_thread_fence(memory_order_acquire); + return 1; +} + +# elif defined(__GNUC__) && defined(__ATOMIC_RELAXED) && __GCC_ATOMIC_INT_LOCK_FREE > 0 + +# define HAVE_ATOMICS 1 + +typedef int CRYPTO_REF_COUNT; + +static __inline__ int CRYPTO_UP_REF(int *val, int *ret, void *lock) +{ + *ret = __atomic_fetch_add(val, 1, __ATOMIC_RELAXED) + 1; + return 1; +} + +static __inline__ int CRYPTO_DOWN_REF(int *val, int *ret, void *lock) +{ + *ret = __atomic_fetch_sub(val, 1, __ATOMIC_RELAXED) - 1; + if (*ret == 0) + __atomic_thread_fence(__ATOMIC_ACQUIRE); + return 1; +} + +# elif defined(_MSC_VER) && _MSC_VER>=1200 + +# define HAVE_ATOMICS 1 + +typedef volatile int CRYPTO_REF_COUNT; + +# if (defined(_M_ARM) && _M_ARM>=7) || defined(_M_ARM64) +# include +# if defined(_M_ARM64) && !defined(_ARM_BARRIER_ISH) +# define _ARM_BARRIER_ISH _ARM64_BARRIER_ISH +# endif + +static __inline int CRYPTO_UP_REF(volatile int *val, int *ret, void *lock) +{ + *ret = _InterlockedExchangeAdd_nf(val, 1) + 1; + return 1; +} + +static __inline int CRYPTO_DOWN_REF(volatile int *val, int *ret, void *lock) +{ + *ret = _InterlockedExchangeAdd_nf(val, -1) - 1; + if (*ret == 0) + __dmb(_ARM_BARRIER_ISH); + return 1; +} +# else +# pragma intrinsic(_InterlockedExchangeAdd) + +static __inline int CRYPTO_UP_REF(volatile int *val, int *ret, void *lock) +{ + *ret = _InterlockedExchangeAdd(val, 1) + 1; + return 1; +} + +static __inline int CRYPTO_DOWN_REF(volatile int *val, int *ret, void *lock) +{ + *ret = _InterlockedExchangeAdd(val, -1) - 1; + return 1; +} +# endif + +# else + +typedef int CRYPTO_REF_COUNT; + +# define CRYPTO_UP_REF(val, ret, lock) CRYPTO_atomic_add(val, 1, ret, lock) +# define CRYPTO_DOWN_REF(val, ret, lock) CRYPTO_atomic_add(val, -1, ret, lock) + +# endif + +# if !defined(NDEBUG) && !defined(OPENSSL_NO_STDIO) +# define REF_ASSERT_ISNT(test) \ + (void)((test) ? (OPENSSL_die("refcount error", __FILE__, __LINE__), 1) : 0) +# else +# define REF_ASSERT_ISNT(i) +# endif + +# ifdef REF_PRINT +# define REF_PRINT_COUNT(a, b) \ + fprintf(stderr, "%p:%4d:%s\n", b, b->references, a) +# else +# define REF_PRINT_COUNT(a, b) +# endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/internal/sockets.h b/trunk/3rdparty/openssl-1.1-fit/include/internal/sockets.h new file mode 100644 index 000000000..5bb0355f0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/internal/sockets.h @@ -0,0 +1,155 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + + +#ifndef HEADER_INTERNAL_SOCKETS +# define HEADER_INTERNAL_SOCKETS + +# if defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI) +# define NO_SYS_PARAM_H +# endif +# ifdef WIN32 +# define NO_SYS_UN_H +# endif +# ifdef OPENSSL_SYS_VMS +# define NO_SYS_PARAM_H +# define NO_SYS_UN_H +# endif + +# ifdef OPENSSL_NO_SOCK + +# elif defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) +# if defined(__DJGPP__) +# include +# include +# include +# include +# elif defined(_WIN32_WCE) && _WIN32_WCE<410 +# define getservbyname _masked_declaration_getservbyname +# endif +# if !defined(IPPROTO_IP) + /* winsock[2].h was included already? */ +# include +# endif +# ifdef getservbyname + /* this is used to be wcecompat/include/winsock_extras.h */ +# undef getservbyname +struct servent *PASCAL getservbyname(const char *, const char *); +# endif + +# ifdef _WIN64 +/* + * Even though sizeof(SOCKET) is 8, it's safe to cast it to int, because + * the value constitutes an index in per-process table of limited size + * and not a real pointer. And we also depend on fact that all processors + * Windows run on happen to be two's-complement, which allows to + * interchange INVALID_SOCKET and -1. + */ +# define socket(d,t,p) ((int)socket(d,t,p)) +# define accept(s,f,l) ((int)accept(s,f,l)) +# endif + +# else + +# ifndef NO_SYS_PARAM_H +# include +# endif +# ifdef OPENSSL_SYS_VXWORKS +# include +# endif + +# include +# if defined(OPENSSL_SYS_VMS_NODECC) +# include +# include +# include +# else +# include +# ifndef NO_SYS_UN_H +# include +# ifndef UNIX_PATH_MAX +# define UNIX_PATH_MAX sizeof(((struct sockaddr_un *)NULL)->sun_path) +# endif +# endif +# ifdef FILIO_H +# include /* FIONBIO in some SVR4, e.g. unixware, solaris */ +# endif +# include +# include +# include +# endif + +# ifdef OPENSSL_SYS_AIX +# include +# endif + +# ifndef VMS +# include +# else +# if !defined(TCPIP_TYPE_SOCKETSHR) && defined(__VMS_VER) && (__VMS_VER > 70000000) + /* ioctl is only in VMS > 7.0 and when socketshr is not used */ +# include +# endif +# include +# if defined(TCPIP_TYPE_SOCKETSHR) +# include +# endif +# endif + +# ifndef INVALID_SOCKET +# define INVALID_SOCKET (-1) +# endif +# endif + +/* + * Some IPv6 implementations are broken, you can disable them in known + * bad versions. + */ +# if !defined(OPENSSL_USE_IPV6) +# if defined(AF_INET6) +# define OPENSSL_USE_IPV6 1 +# else +# define OPENSSL_USE_IPV6 0 +# endif +# endif + +# define get_last_socket_error() errno +# define clear_socket_error() errno=0 + +# if defined(OPENSSL_SYS_WINDOWS) +# undef get_last_socket_error +# undef clear_socket_error +# define get_last_socket_error() WSAGetLastError() +# define clear_socket_error() WSASetLastError(0) +# define readsocket(s,b,n) recv((s),(b),(n),0) +# define writesocket(s,b,n) send((s),(b),(n),0) +# elif defined(__DJGPP__) +# define WATT32 +# define WATT32_NO_OLDIES +# define closesocket(s) close_s(s) +# define readsocket(s,b,n) read_s(s,b,n) +# define writesocket(s,b,n) send(s,b,n,0) +# elif defined(OPENSSL_SYS_VMS) +# define ioctlsocket(a,b,c) ioctl(a,b,c) +# define closesocket(s) close(s) +# define readsocket(s,b,n) recv((s),(b),(n),0) +# define writesocket(s,b,n) send((s),(b),(n),0) +# elif defined(OPENSSL_SYS_VXWORKS) +# define ioctlsocket(a,b,c) ioctl((a),(b),(int)(c)) +# define closesocket(s) close(s) +# define readsocket(s,b,n) read((s),(b),(n)) +# define writesocket(s,b,n) write((s),(char *)(b),(n)) +# else +# define ioctlsocket(a,b,c) ioctl(a,b,c) +# define closesocket(s) close(s) +# define readsocket(s,b,n) read((s),(b),(n)) +# define writesocket(s,b,n) write((s),(b),(n)) +# endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/internal/sslconf.h b/trunk/3rdparty/openssl-1.1-fit/include/internal/sslconf.h new file mode 100644 index 000000000..d538f8614 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/internal/sslconf.h @@ -0,0 +1,20 @@ +/* + * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_SSLCONF_H +# define HEADER_SSLCONF_H + +typedef struct ssl_conf_cmd_st SSL_CONF_CMD; + +const SSL_CONF_CMD *conf_ssl_get(size_t idx, const char **name, size_t *cnt); +int conf_ssl_name_find(const char *name, size_t *idx); +void conf_ssl_get_cmd(const SSL_CONF_CMD *cmd, size_t idx, char **cmdstr, + char **arg); + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/internal/thread_once.h b/trunk/3rdparty/openssl-1.1-fit/include/internal/thread_once.h new file mode 100644 index 000000000..8a25d04d2 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/internal/thread_once.h @@ -0,0 +1,137 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +/* + * DEFINE_RUN_ONCE: Define an initialiser function that should be run exactly + * once. It takes no arguments and returns and int result (1 for success or + * 0 for failure). Typical usage might be: + * + * DEFINE_RUN_ONCE(myinitfunc) + * { + * do_some_initialisation(); + * if (init_is_successful()) + * return 1; + * + * return 0; + * } + */ +#define DEFINE_RUN_ONCE(init) \ + static int init(void); \ + int init##_ossl_ret_ = 0; \ + void init##_ossl_(void) \ + { \ + init##_ossl_ret_ = init(); \ + } \ + static int init(void) + +/* + * DECLARE_RUN_ONCE: Declare an initialiser function that should be run exactly + * once that has been defined in another file via DEFINE_RUN_ONCE(). + */ +#define DECLARE_RUN_ONCE(init) \ + extern int init##_ossl_ret_; \ + void init##_ossl_(void); + +/* + * DEFINE_RUN_ONCE_STATIC: Define an initialiser function that should be run + * exactly once. This function will be declared as static within the file. It + * takes no arguments and returns and int result (1 for success or 0 for + * failure). Typical usage might be: + * + * DEFINE_RUN_ONCE_STATIC(myinitfunc) + * { + * do_some_initialisation(); + * if (init_is_successful()) + * return 1; + * + * return 0; + * } + */ +#define DEFINE_RUN_ONCE_STATIC(init) \ + static int init(void); \ + static int init##_ossl_ret_ = 0; \ + static void init##_ossl_(void) \ + { \ + init##_ossl_ret_ = init(); \ + } \ + static int init(void) + +/* + * DEFINE_RUN_ONCE_STATIC_ALT: Define an alternative initialiser function. This + * function will be declared as static within the file. It takes no arguments + * and returns an int result (1 for success or 0 for failure). An alternative + * initialiser function is expected to be associated with a primary initialiser + * function defined via DEFINE_ONCE_STATIC where both functions use the same + * CRYPTO_ONCE object to synchronise. Where an alternative initialiser function + * is used only one of the primary or the alternative initialiser function will + * ever be called - and that function will be called exactly once. Definitition + * of an alternative initialiser function MUST occur AFTER the definition of the + * primary initialiser function. + * + * Typical usage might be: + * + * DEFINE_RUN_ONCE_STATIC(myinitfunc) + * { + * do_some_initialisation(); + * if (init_is_successful()) + * return 1; + * + * return 0; + * } + * + * DEFINE_RUN_ONCE_STATIC_ALT(myaltinitfunc, myinitfunc) + * { + * do_some_alternative_initialisation(); + * if (init_is_successful()) + * return 1; + * + * return 0; + * } + */ +#define DEFINE_RUN_ONCE_STATIC_ALT(initalt, init) \ + static int initalt(void); \ + static void initalt##_ossl_(void) \ + { \ + init##_ossl_ret_ = initalt(); \ + } \ + static int initalt(void) + +/* + * RUN_ONCE - use CRYPTO_THREAD_run_once, and check if the init succeeded + * @once: pointer to static object of type CRYPTO_ONCE + * @init: function name that was previously given to DEFINE_RUN_ONCE, + * DEFINE_RUN_ONCE_STATIC or DECLARE_RUN_ONCE. This function + * must return 1 for success or 0 for failure. + * + * The return value is 1 on success (*) or 0 in case of error. + * + * (*) by convention, since the init function must return 1 on success. + */ +#define RUN_ONCE(once, init) \ + (CRYPTO_THREAD_run_once(once, init##_ossl_) ? init##_ossl_ret_ : 0) + +/* + * RUN_ONCE_ALT - use CRYPTO_THREAD_run_once, to run an alternative initialiser + * function and check if that initialisation succeeded + * @once: pointer to static object of type CRYPTO_ONCE + * @initalt: alternative initialiser function name that was previously given to + * DEFINE_RUN_ONCE_STATIC_ALT. This function must return 1 for + * success or 0 for failure. + * @init: primary initialiser function name that was previously given to + * DEFINE_RUN_ONCE_STATIC. This function must return 1 for success or + * 0 for failure. + * + * The return value is 1 on success (*) or 0 in case of error. + * + * (*) by convention, since the init function must return 1 on success. + */ +#define RUN_ONCE_ALT(once, initalt, init) \ + (CRYPTO_THREAD_run_once(once, initalt##_ossl_) ? init##_ossl_ret_ : 0) diff --git a/trunk/3rdparty/openssl-1.1-fit/include/internal/tsan_assist.h b/trunk/3rdparty/openssl-1.1-fit/include/internal/tsan_assist.h new file mode 100644 index 000000000..38ba0c7eb --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/internal/tsan_assist.h @@ -0,0 +1,144 @@ +/* + * Copyright 2018-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Contemporary compilers implement lock-free atomic memory access + * primitives that facilitate writing "thread-opportunistic" or even real + * multi-threading low-overhead code. "Thread-opportunistic" is when + * exact result is not required, e.g. some statistics, or execution flow + * doesn't have to be unambiguous. Simplest example is lazy "constant" + * initialization when one can synchronize on variable itself, e.g. + * + * if (var == NOT_YET_INITIALIZED) + * var = function_returning_same_value(); + * + * This does work provided that loads and stores are single-instuction + * operations (and integer ones are on *all* supported platforms), but + * it upsets Thread Sanitizer. Suggested solution is + * + * if (tsan_load(&var) == NOT_YET_INITIALIZED) + * tsan_store(&var, function_returning_same_value()); + * + * Production machine code would be the same, so one can wonder why + * bother. Having Thread Sanitizer accept "thread-opportunistic" code + * allows to move on trouble-shooting real bugs. + * + * Resolving Thread Sanitizer nits was the initial purpose for this module, + * but it was later extended with more nuanced primitives that are useful + * even in "non-opportunistic" scenarios. Most notably verifying if a shared + * structure is fully initialized and bypassing the initialization lock. + * It's suggested to view macros defined in this module as "annotations" for + * thread-safe lock-free code, "Thread-Safe ANnotations"... + * + * It's assumed that ATOMIC_{LONG|INT}_LOCK_FREE are assigned same value as + * ATOMIC_POINTER_LOCK_FREE. And check for >= 2 ensures that corresponding + * code is inlined. It should be noted that statistics counters become + * accurate in such case. + * + * Special note about TSAN_QUALIFIER. It might be undesired to use it in + * a shared header. Because whether operation on specific variable or member + * is atomic or not might be irrelevant in other modules. In such case one + * can use TSAN_QUALIFIER in cast specifically when it has to count. + */ + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L \ + && !defined(__STDC_NO_ATOMICS__) +# include + +# if defined(ATOMIC_POINTER_LOCK_FREE) \ + && ATOMIC_POINTER_LOCK_FREE >= 2 +# define TSAN_QUALIFIER _Atomic +# define tsan_load(ptr) atomic_load_explicit((ptr), memory_order_relaxed) +# define tsan_store(ptr, val) atomic_store_explicit((ptr), (val), memory_order_relaxed) +# define tsan_counter(ptr) atomic_fetch_add_explicit((ptr), 1, memory_order_relaxed) +# define tsan_decr(ptr) atomic_fetch_add_explicit((ptr), -1, memory_order_relaxed) +# define tsan_ld_acq(ptr) atomic_load_explicit((ptr), memory_order_acquire) +# define tsan_st_rel(ptr, val) atomic_store_explicit((ptr), (val), memory_order_release) +# endif + +#elif defined(__GNUC__) && defined(__ATOMIC_RELAXED) + +# if defined(__GCC_ATOMIC_POINTER_LOCK_FREE) \ + && __GCC_ATOMIC_POINTER_LOCK_FREE >= 2 +# define TSAN_QUALIFIER volatile +# define tsan_load(ptr) __atomic_load_n((ptr), __ATOMIC_RELAXED) +# define tsan_store(ptr, val) __atomic_store_n((ptr), (val), __ATOMIC_RELAXED) +# define tsan_counter(ptr) __atomic_fetch_add((ptr), 1, __ATOMIC_RELAXED) +# define tsan_decr(ptr) __atomic_fetch_add((ptr), -1, __ATOMIC_RELAXED) +# define tsan_ld_acq(ptr) __atomic_load_n((ptr), __ATOMIC_ACQUIRE) +# define tsan_st_rel(ptr, val) __atomic_store_n((ptr), (val), __ATOMIC_RELEASE) +# endif + +#elif defined(_MSC_VER) && _MSC_VER>=1200 \ + && (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64) || \ + defined(_M_ARM64) || (defined(_M_ARM) && _M_ARM >= 7)) +/* + * There is subtle dependency on /volatile: command-line option. + * "ms" implies same semantic as memory_order_acquire for loads and + * memory_order_release for stores, while "iso" - memory_order_relaxed for + * either. Real complication is that defaults are different on x86 and ARM. + * There is explanation for that, "ms" is backward compatible with earlier + * compiler versions, while multi-processor ARM can be viewed as brand new + * platform to MSC and its users, and with non-relaxed semantic taking toll + * with additional instructions and penalties, it kind of makes sense to + * default to "iso"... + */ +# define TSAN_QUALIFIER volatile +# if defined(_M_ARM) || defined(_M_ARM64) +# define _InterlockedExchangeAdd _InterlockedExchangeAdd_nf +# pragma intrinsic(_InterlockedExchangeAdd_nf) +# pragma intrinsic(__iso_volatile_load32, __iso_volatile_store32) +# ifdef _WIN64 +# define _InterlockedExchangeAdd64 _InterlockedExchangeAdd64_nf +# pragma intrinsic(_InterlockedExchangeAdd64_nf) +# pragma intrinsic(__iso_volatile_load64, __iso_volatile_store64) +# define tsan_load(ptr) (sizeof(*(ptr)) == 8 ? __iso_volatile_load64(ptr) \ + : __iso_volatile_load32(ptr)) +# define tsan_store(ptr, val) (sizeof(*(ptr)) == 8 ? __iso_volatile_store64((ptr), (val)) \ + : __iso_volatile_store32((ptr), (val))) +# else +# define tsan_load(ptr) __iso_volatile_load32(ptr) +# define tsan_store(ptr, val) __iso_volatile_store32((ptr), (val)) +# endif +# else +# define tsan_load(ptr) (*(ptr)) +# define tsan_store(ptr, val) (*(ptr) = (val)) +# endif +# pragma intrinsic(_InterlockedExchangeAdd) +# ifdef _WIN64 +# pragma intrinsic(_InterlockedExchangeAdd64) +# define tsan_counter(ptr) (sizeof(*(ptr)) == 8 ? _InterlockedExchangeAdd64((ptr), 1) \ + : _InterlockedExchangeAdd((ptr), 1)) +# define tsan_decr(ptr) (sizeof(*(ptr)) == 8 ? _InterlockedExchangeAdd64((ptr), -1) \ + : _InterlockedExchangeAdd((ptr), -1)) +# else +# define tsan_counter(ptr) _InterlockedExchangeAdd((ptr), 1) +# define tsan_decr(ptr) _InterlockedExchangeAdd((ptr), -1) +# endif +# if !defined(_ISO_VOLATILE) +# define tsan_ld_acq(ptr) (*(ptr)) +# define tsan_st_rel(ptr, val) (*(ptr) = (val)) +# endif + +#endif + +#ifndef TSAN_QUALIFIER + +# define TSAN_QUALIFIER volatile +# define tsan_load(ptr) (*(ptr)) +# define tsan_store(ptr, val) (*(ptr) = (val)) +# define tsan_counter(ptr) ((*(ptr))++) +# define tsan_decr(ptr) ((*(ptr))--) +/* + * Lack of tsan_ld_acq and tsan_ld_rel means that compiler support is not + * sophisticated enough to support them. Code that relies on them should be + * protected with #ifdef tsan_ld_acq with locked fallback. + */ + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/__DECC_INCLUDE_EPILOGUE.H b/trunk/3rdparty/openssl-1.1-fit/include/openssl/__DECC_INCLUDE_EPILOGUE.H new file mode 100644 index 000000000..c350018ad --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/__DECC_INCLUDE_EPILOGUE.H @@ -0,0 +1,16 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This file is only used by HP C on VMS, and is included automatically + * after each header file from this directory + */ + +/* restore state. Must correspond to the save in __decc_include_prologue.h */ +#pragma names restore diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/__DECC_INCLUDE_PROLOGUE.H b/trunk/3rdparty/openssl-1.1-fit/include/openssl/__DECC_INCLUDE_PROLOGUE.H new file mode 100644 index 000000000..9a9c777f9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/__DECC_INCLUDE_PROLOGUE.H @@ -0,0 +1,20 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This file is only used by HP C on VMS, and is included automatically + * after each header file from this directory + */ + +/* save state */ +#pragma names save +/* have the compiler shorten symbols larger than 31 chars to 23 chars + * followed by a 8 hex char CRC + */ +#pragma names as_is,shortened diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/aes.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/aes.h new file mode 100644 index 000000000..245c552ab --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/aes.h @@ -0,0 +1,92 @@ +/* + * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_AES_H +# define HEADER_AES_H + +# include + +# include +# ifdef __cplusplus +extern "C" { +# endif + +# define AES_ENCRYPT 1 +# define AES_DECRYPT 0 + +/* + * Because array size can't be a const in C, the following two are macros. + * Both sizes are in bytes. + */ +# define AES_MAXNR 14 +# define AES_BLOCK_SIZE 16 + +/* This should be a hidden type, but EVP requires that the size be known */ +struct aes_key_st { +# ifdef AES_LONG + unsigned long rd_key[4 * (AES_MAXNR + 1)]; +# else + unsigned int rd_key[4 * (AES_MAXNR + 1)]; +# endif + int rounds; +}; +typedef struct aes_key_st AES_KEY; + +const char *AES_options(void); + +int AES_set_encrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key); +int AES_set_decrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key); + +void AES_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key); +void AES_decrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key); + +void AES_ecb_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key, const int enc); +void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, const int enc); +void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, int *num, const int enc); +void AES_cfb1_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, int *num, const int enc); +void AES_cfb8_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, int *num, const int enc); +void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, int *num); +/* NB: the IV is _two_ blocks long */ +void AES_ige_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, const int enc); +/* NB: the IV is _four_ blocks long */ +void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + const AES_KEY *key2, const unsigned char *ivec, + const int enc); + +int AES_wrap_key(AES_KEY *key, const unsigned char *iv, + unsigned char *out, + const unsigned char *in, unsigned int inlen); +int AES_unwrap_key(AES_KEY *key, const unsigned char *iv, + unsigned char *out, + const unsigned char *in, unsigned int inlen); + + +# ifdef __cplusplus +} +# endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/asn1.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/asn1.h new file mode 100644 index 000000000..9522eec18 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/asn1.h @@ -0,0 +1,886 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_ASN1_H +# define HEADER_ASN1_H + +# include +# include +# include +# include +# include +# include +# include + +# include +# if OPENSSL_API_COMPAT < 0x10100000L +# include +# endif + +# ifdef OPENSSL_BUILD_SHLIBCRYPTO +# undef OPENSSL_EXTERN +# define OPENSSL_EXTERN OPENSSL_EXPORT +# endif + +#ifdef __cplusplus +extern "C" { +#endif + +# define V_ASN1_UNIVERSAL 0x00 +# define V_ASN1_APPLICATION 0x40 +# define V_ASN1_CONTEXT_SPECIFIC 0x80 +# define V_ASN1_PRIVATE 0xc0 + +# define V_ASN1_CONSTRUCTED 0x20 +# define V_ASN1_PRIMITIVE_TAG 0x1f +# define V_ASN1_PRIMATIVE_TAG /*compat*/ V_ASN1_PRIMITIVE_TAG + +# define V_ASN1_APP_CHOOSE -2/* let the recipient choose */ +# define V_ASN1_OTHER -3/* used in ASN1_TYPE */ +# define V_ASN1_ANY -4/* used in ASN1 template code */ + +# define V_ASN1_UNDEF -1 +/* ASN.1 tag values */ +# define V_ASN1_EOC 0 +# define V_ASN1_BOOLEAN 1 /**/ +# define V_ASN1_INTEGER 2 +# define V_ASN1_BIT_STRING 3 +# define V_ASN1_OCTET_STRING 4 +# define V_ASN1_NULL 5 +# define V_ASN1_OBJECT 6 +# define V_ASN1_OBJECT_DESCRIPTOR 7 +# define V_ASN1_EXTERNAL 8 +# define V_ASN1_REAL 9 +# define V_ASN1_ENUMERATED 10 +# define V_ASN1_UTF8STRING 12 +# define V_ASN1_SEQUENCE 16 +# define V_ASN1_SET 17 +# define V_ASN1_NUMERICSTRING 18 /**/ +# define V_ASN1_PRINTABLESTRING 19 +# define V_ASN1_T61STRING 20 +# define V_ASN1_TELETEXSTRING 20/* alias */ +# define V_ASN1_VIDEOTEXSTRING 21 /**/ +# define V_ASN1_IA5STRING 22 +# define V_ASN1_UTCTIME 23 +# define V_ASN1_GENERALIZEDTIME 24 /**/ +# define V_ASN1_GRAPHICSTRING 25 /**/ +# define V_ASN1_ISO64STRING 26 /**/ +# define V_ASN1_VISIBLESTRING 26/* alias */ +# define V_ASN1_GENERALSTRING 27 /**/ +# define V_ASN1_UNIVERSALSTRING 28 /**/ +# define V_ASN1_BMPSTRING 30 + +/* + * NB the constants below are used internally by ASN1_INTEGER + * and ASN1_ENUMERATED to indicate the sign. They are *not* on + * the wire tag values. + */ + +# define V_ASN1_NEG 0x100 +# define V_ASN1_NEG_INTEGER (2 | V_ASN1_NEG) +# define V_ASN1_NEG_ENUMERATED (10 | V_ASN1_NEG) + +/* For use with d2i_ASN1_type_bytes() */ +# define B_ASN1_NUMERICSTRING 0x0001 +# define B_ASN1_PRINTABLESTRING 0x0002 +# define B_ASN1_T61STRING 0x0004 +# define B_ASN1_TELETEXSTRING 0x0004 +# define B_ASN1_VIDEOTEXSTRING 0x0008 +# define B_ASN1_IA5STRING 0x0010 +# define B_ASN1_GRAPHICSTRING 0x0020 +# define B_ASN1_ISO64STRING 0x0040 +# define B_ASN1_VISIBLESTRING 0x0040 +# define B_ASN1_GENERALSTRING 0x0080 +# define B_ASN1_UNIVERSALSTRING 0x0100 +# define B_ASN1_OCTET_STRING 0x0200 +# define B_ASN1_BIT_STRING 0x0400 +# define B_ASN1_BMPSTRING 0x0800 +# define B_ASN1_UNKNOWN 0x1000 +# define B_ASN1_UTF8STRING 0x2000 +# define B_ASN1_UTCTIME 0x4000 +# define B_ASN1_GENERALIZEDTIME 0x8000 +# define B_ASN1_SEQUENCE 0x10000 +/* For use with ASN1_mbstring_copy() */ +# define MBSTRING_FLAG 0x1000 +# define MBSTRING_UTF8 (MBSTRING_FLAG) +# define MBSTRING_ASC (MBSTRING_FLAG|1) +# define MBSTRING_BMP (MBSTRING_FLAG|2) +# define MBSTRING_UNIV (MBSTRING_FLAG|4) +# define SMIME_OLDMIME 0x400 +# define SMIME_CRLFEOL 0x800 +# define SMIME_STREAM 0x1000 + struct X509_algor_st; +DEFINE_STACK_OF(X509_ALGOR) + +# define ASN1_STRING_FLAG_BITS_LEFT 0x08/* Set if 0x07 has bits left value */ +/* + * This indicates that the ASN1_STRING is not a real value but just a place + * holder for the location where indefinite length constructed data should be + * inserted in the memory buffer + */ +# define ASN1_STRING_FLAG_NDEF 0x010 + +/* + * This flag is used by the CMS code to indicate that a string is not + * complete and is a place holder for content when it had all been accessed. + * The flag will be reset when content has been written to it. + */ + +# define ASN1_STRING_FLAG_CONT 0x020 +/* + * This flag is used by ASN1 code to indicate an ASN1_STRING is an MSTRING + * type. + */ +# define ASN1_STRING_FLAG_MSTRING 0x040 +/* String is embedded and only content should be freed */ +# define ASN1_STRING_FLAG_EMBED 0x080 +/* String should be parsed in RFC 5280's time format */ +# define ASN1_STRING_FLAG_X509_TIME 0x100 +/* This is the base type that holds just about everything :-) */ +struct asn1_string_st { + int length; + int type; + unsigned char *data; + /* + * The value of the following field depends on the type being held. It + * is mostly being used for BIT_STRING so if the input data has a + * non-zero 'unused bits' value, it will be handled correctly + */ + long flags; +}; + +/* + * ASN1_ENCODING structure: this is used to save the received encoding of an + * ASN1 type. This is useful to get round problems with invalid encodings + * which can break signatures. + */ + +typedef struct ASN1_ENCODING_st { + unsigned char *enc; /* DER encoding */ + long len; /* Length of encoding */ + int modified; /* set to 1 if 'enc' is invalid */ +} ASN1_ENCODING; + +/* Used with ASN1 LONG type: if a long is set to this it is omitted */ +# define ASN1_LONG_UNDEF 0x7fffffffL + +# define STABLE_FLAGS_MALLOC 0x01 +/* + * A zero passed to ASN1_STRING_TABLE_new_add for the flags is interpreted + * as "don't change" and STABLE_FLAGS_MALLOC is always set. By setting + * STABLE_FLAGS_MALLOC only we can clear the existing value. Use the alias + * STABLE_FLAGS_CLEAR to reflect this. + */ +# define STABLE_FLAGS_CLEAR STABLE_FLAGS_MALLOC +# define STABLE_NO_MASK 0x02 +# define DIRSTRING_TYPE \ + (B_ASN1_PRINTABLESTRING|B_ASN1_T61STRING|B_ASN1_BMPSTRING|B_ASN1_UTF8STRING) +# define PKCS9STRING_TYPE (DIRSTRING_TYPE|B_ASN1_IA5STRING) + +typedef struct asn1_string_table_st { + int nid; + long minsize; + long maxsize; + unsigned long mask; + unsigned long flags; +} ASN1_STRING_TABLE; + +DEFINE_STACK_OF(ASN1_STRING_TABLE) + +/* size limits: this stuff is taken straight from RFC2459 */ + +# define ub_name 32768 +# define ub_common_name 64 +# define ub_locality_name 128 +# define ub_state_name 128 +# define ub_organization_name 64 +# define ub_organization_unit_name 64 +# define ub_title 64 +# define ub_email_address 128 + +/* + * Declarations for template structures: for full definitions see asn1t.h + */ +typedef struct ASN1_TEMPLATE_st ASN1_TEMPLATE; +typedef struct ASN1_TLC_st ASN1_TLC; +/* This is just an opaque pointer */ +typedef struct ASN1_VALUE_st ASN1_VALUE; + +/* Declare ASN1 functions: the implement macro in in asn1t.h */ + +# define DECLARE_ASN1_FUNCTIONS(type) DECLARE_ASN1_FUNCTIONS_name(type, type) + +# define DECLARE_ASN1_ALLOC_FUNCTIONS(type) \ + DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, type) + +# define DECLARE_ASN1_FUNCTIONS_name(type, name) \ + DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \ + DECLARE_ASN1_ENCODE_FUNCTIONS(type, name, name) + +# define DECLARE_ASN1_FUNCTIONS_fname(type, itname, name) \ + DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \ + DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) + +# define DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) \ + type *d2i_##name(type **a, const unsigned char **in, long len); \ + int i2d_##name(type *a, unsigned char **out); \ + DECLARE_ASN1_ITEM(itname) + +# define DECLARE_ASN1_ENCODE_FUNCTIONS_const(type, name) \ + type *d2i_##name(type **a, const unsigned char **in, long len); \ + int i2d_##name(const type *a, unsigned char **out); \ + DECLARE_ASN1_ITEM(name) + +# define DECLARE_ASN1_NDEF_FUNCTION(name) \ + int i2d_##name##_NDEF(name *a, unsigned char **out); + +# define DECLARE_ASN1_FUNCTIONS_const(name) \ + DECLARE_ASN1_ALLOC_FUNCTIONS(name) \ + DECLARE_ASN1_ENCODE_FUNCTIONS_const(name, name) + +# define DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \ + type *name##_new(void); \ + void name##_free(type *a); + +# define DECLARE_ASN1_PRINT_FUNCTION(stname) \ + DECLARE_ASN1_PRINT_FUNCTION_fname(stname, stname) + +# define DECLARE_ASN1_PRINT_FUNCTION_fname(stname, fname) \ + int fname##_print_ctx(BIO *out, stname *x, int indent, \ + const ASN1_PCTX *pctx); + +# define D2I_OF(type) type *(*)(type **,const unsigned char **,long) +# define I2D_OF(type) int (*)(type *,unsigned char **) +# define I2D_OF_const(type) int (*)(const type *,unsigned char **) + +# define CHECKED_D2I_OF(type, d2i) \ + ((d2i_of_void*) (1 ? d2i : ((D2I_OF(type))0))) +# define CHECKED_I2D_OF(type, i2d) \ + ((i2d_of_void*) (1 ? i2d : ((I2D_OF(type))0))) +# define CHECKED_NEW_OF(type, xnew) \ + ((void *(*)(void)) (1 ? xnew : ((type *(*)(void))0))) +# define CHECKED_PTR_OF(type, p) \ + ((void*) (1 ? p : (type*)0)) +# define CHECKED_PPTR_OF(type, p) \ + ((void**) (1 ? p : (type**)0)) + +# define TYPEDEF_D2I_OF(type) typedef type *d2i_of_##type(type **,const unsigned char **,long) +# define TYPEDEF_I2D_OF(type) typedef int i2d_of_##type(type *,unsigned char **) +# define TYPEDEF_D2I2D_OF(type) TYPEDEF_D2I_OF(type); TYPEDEF_I2D_OF(type) + +TYPEDEF_D2I2D_OF(void); + +/*- + * The following macros and typedefs allow an ASN1_ITEM + * to be embedded in a structure and referenced. Since + * the ASN1_ITEM pointers need to be globally accessible + * (possibly from shared libraries) they may exist in + * different forms. On platforms that support it the + * ASN1_ITEM structure itself will be globally exported. + * Other platforms will export a function that returns + * an ASN1_ITEM pointer. + * + * To handle both cases transparently the macros below + * should be used instead of hard coding an ASN1_ITEM + * pointer in a structure. + * + * The structure will look like this: + * + * typedef struct SOMETHING_st { + * ... + * ASN1_ITEM_EXP *iptr; + * ... + * } SOMETHING; + * + * It would be initialised as e.g.: + * + * SOMETHING somevar = {...,ASN1_ITEM_ref(X509),...}; + * + * and the actual pointer extracted with: + * + * const ASN1_ITEM *it = ASN1_ITEM_ptr(somevar.iptr); + * + * Finally an ASN1_ITEM pointer can be extracted from an + * appropriate reference with: ASN1_ITEM_rptr(X509). This + * would be used when a function takes an ASN1_ITEM * argument. + * + */ + +# ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION + +/* ASN1_ITEM pointer exported type */ +typedef const ASN1_ITEM ASN1_ITEM_EXP; + +/* Macro to obtain ASN1_ITEM pointer from exported type */ +# define ASN1_ITEM_ptr(iptr) (iptr) + +/* Macro to include ASN1_ITEM pointer from base type */ +# define ASN1_ITEM_ref(iptr) (&(iptr##_it)) + +# define ASN1_ITEM_rptr(ref) (&(ref##_it)) + +# define DECLARE_ASN1_ITEM(name) \ + OPENSSL_EXTERN const ASN1_ITEM name##_it; + +# else + +/* + * Platforms that can't easily handle shared global variables are declared as + * functions returning ASN1_ITEM pointers. + */ + +/* ASN1_ITEM pointer exported type */ +typedef const ASN1_ITEM *ASN1_ITEM_EXP (void); + +/* Macro to obtain ASN1_ITEM pointer from exported type */ +# define ASN1_ITEM_ptr(iptr) (iptr()) + +/* Macro to include ASN1_ITEM pointer from base type */ +# define ASN1_ITEM_ref(iptr) (iptr##_it) + +# define ASN1_ITEM_rptr(ref) (ref##_it()) + +# define DECLARE_ASN1_ITEM(name) \ + const ASN1_ITEM * name##_it(void); + +# endif + +/* Parameters used by ASN1_STRING_print_ex() */ + +/* + * These determine which characters to escape: RFC2253 special characters, + * control characters and MSB set characters + */ + +# define ASN1_STRFLGS_ESC_2253 1 +# define ASN1_STRFLGS_ESC_CTRL 2 +# define ASN1_STRFLGS_ESC_MSB 4 + +/* + * This flag determines how we do escaping: normally RC2253 backslash only, + * set this to use backslash and quote. + */ + +# define ASN1_STRFLGS_ESC_QUOTE 8 + +/* These three flags are internal use only. */ + +/* Character is a valid PrintableString character */ +# define CHARTYPE_PRINTABLESTRING 0x10 +/* Character needs escaping if it is the first character */ +# define CHARTYPE_FIRST_ESC_2253 0x20 +/* Character needs escaping if it is the last character */ +# define CHARTYPE_LAST_ESC_2253 0x40 + +/* + * NB the internal flags are safely reused below by flags handled at the top + * level. + */ + +/* + * If this is set we convert all character strings to UTF8 first + */ + +# define ASN1_STRFLGS_UTF8_CONVERT 0x10 + +/* + * If this is set we don't attempt to interpret content: just assume all + * strings are 1 byte per character. This will produce some pretty odd + * looking output! + */ + +# define ASN1_STRFLGS_IGNORE_TYPE 0x20 + +/* If this is set we include the string type in the output */ +# define ASN1_STRFLGS_SHOW_TYPE 0x40 + +/* + * This determines which strings to display and which to 'dump' (hex dump of + * content octets or DER encoding). We can only dump non character strings or + * everything. If we don't dump 'unknown' they are interpreted as character + * strings with 1 octet per character and are subject to the usual escaping + * options. + */ + +# define ASN1_STRFLGS_DUMP_ALL 0x80 +# define ASN1_STRFLGS_DUMP_UNKNOWN 0x100 + +/* + * These determine what 'dumping' does, we can dump the content octets or the + * DER encoding: both use the RFC2253 #XXXXX notation. + */ + +# define ASN1_STRFLGS_DUMP_DER 0x200 + +/* + * This flag specifies that RC2254 escaping shall be performed. + */ +#define ASN1_STRFLGS_ESC_2254 0x400 + +/* + * All the string flags consistent with RFC2253, escaping control characters + * isn't essential in RFC2253 but it is advisable anyway. + */ + +# define ASN1_STRFLGS_RFC2253 (ASN1_STRFLGS_ESC_2253 | \ + ASN1_STRFLGS_ESC_CTRL | \ + ASN1_STRFLGS_ESC_MSB | \ + ASN1_STRFLGS_UTF8_CONVERT | \ + ASN1_STRFLGS_DUMP_UNKNOWN | \ + ASN1_STRFLGS_DUMP_DER) + +DEFINE_STACK_OF(ASN1_INTEGER) + +DEFINE_STACK_OF(ASN1_GENERALSTRING) + +DEFINE_STACK_OF(ASN1_UTF8STRING) + +typedef struct asn1_type_st { + int type; + union { + char *ptr; + ASN1_BOOLEAN boolean; + ASN1_STRING *asn1_string; + ASN1_OBJECT *object; + ASN1_INTEGER *integer; + ASN1_ENUMERATED *enumerated; + ASN1_BIT_STRING *bit_string; + ASN1_OCTET_STRING *octet_string; + ASN1_PRINTABLESTRING *printablestring; + ASN1_T61STRING *t61string; + ASN1_IA5STRING *ia5string; + ASN1_GENERALSTRING *generalstring; + ASN1_BMPSTRING *bmpstring; + ASN1_UNIVERSALSTRING *universalstring; + ASN1_UTCTIME *utctime; + ASN1_GENERALIZEDTIME *generalizedtime; + ASN1_VISIBLESTRING *visiblestring; + ASN1_UTF8STRING *utf8string; + /* + * set and sequence are left complete and still contain the set or + * sequence bytes + */ + ASN1_STRING *set; + ASN1_STRING *sequence; + ASN1_VALUE *asn1_value; + } value; +} ASN1_TYPE; + +DEFINE_STACK_OF(ASN1_TYPE) + +typedef STACK_OF(ASN1_TYPE) ASN1_SEQUENCE_ANY; + +DECLARE_ASN1_ENCODE_FUNCTIONS_const(ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY) +DECLARE_ASN1_ENCODE_FUNCTIONS_const(ASN1_SEQUENCE_ANY, ASN1_SET_ANY) + +/* This is used to contain a list of bit names */ +typedef struct BIT_STRING_BITNAME_st { + int bitnum; + const char *lname; + const char *sname; +} BIT_STRING_BITNAME; + +# define B_ASN1_TIME \ + B_ASN1_UTCTIME | \ + B_ASN1_GENERALIZEDTIME + +# define B_ASN1_PRINTABLE \ + B_ASN1_NUMERICSTRING| \ + B_ASN1_PRINTABLESTRING| \ + B_ASN1_T61STRING| \ + B_ASN1_IA5STRING| \ + B_ASN1_BIT_STRING| \ + B_ASN1_UNIVERSALSTRING|\ + B_ASN1_BMPSTRING|\ + B_ASN1_UTF8STRING|\ + B_ASN1_SEQUENCE|\ + B_ASN1_UNKNOWN + +# define B_ASN1_DIRECTORYSTRING \ + B_ASN1_PRINTABLESTRING| \ + B_ASN1_TELETEXSTRING|\ + B_ASN1_BMPSTRING|\ + B_ASN1_UNIVERSALSTRING|\ + B_ASN1_UTF8STRING + +# define B_ASN1_DISPLAYTEXT \ + B_ASN1_IA5STRING| \ + B_ASN1_VISIBLESTRING| \ + B_ASN1_BMPSTRING|\ + B_ASN1_UTF8STRING + +DECLARE_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE) + +int ASN1_TYPE_get(const ASN1_TYPE *a); +void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value); +int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value); +int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b); + +ASN1_TYPE *ASN1_TYPE_pack_sequence(const ASN1_ITEM *it, void *s, ASN1_TYPE **t); +void *ASN1_TYPE_unpack_sequence(const ASN1_ITEM *it, const ASN1_TYPE *t); + +ASN1_OBJECT *ASN1_OBJECT_new(void); +void ASN1_OBJECT_free(ASN1_OBJECT *a); +int i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp); +ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, + long length); + +DECLARE_ASN1_ITEM(ASN1_OBJECT) + +DEFINE_STACK_OF(ASN1_OBJECT) + +ASN1_STRING *ASN1_STRING_new(void); +void ASN1_STRING_free(ASN1_STRING *a); +void ASN1_STRING_clear_free(ASN1_STRING *a); +int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str); +ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *a); +ASN1_STRING *ASN1_STRING_type_new(int type); +int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b); + /* + * Since this is used to store all sorts of things, via macros, for now, + * make its data void * + */ +int ASN1_STRING_set(ASN1_STRING *str, const void *data, int len); +void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len); +int ASN1_STRING_length(const ASN1_STRING *x); +void ASN1_STRING_length_set(ASN1_STRING *x, int n); +int ASN1_STRING_type(const ASN1_STRING *x); +DEPRECATEDIN_1_1_0(unsigned char *ASN1_STRING_data(ASN1_STRING *x)) +const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x); + +DECLARE_ASN1_FUNCTIONS(ASN1_BIT_STRING) +int ASN1_BIT_STRING_set(ASN1_BIT_STRING *a, unsigned char *d, int length); +int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value); +int ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n); +int ASN1_BIT_STRING_check(const ASN1_BIT_STRING *a, + const unsigned char *flags, int flags_len); + +int ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs, + BIT_STRING_BITNAME *tbl, int indent); +int ASN1_BIT_STRING_num_asc(const char *name, BIT_STRING_BITNAME *tbl); +int ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, const char *name, int value, + BIT_STRING_BITNAME *tbl); + +DECLARE_ASN1_FUNCTIONS(ASN1_INTEGER) +ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp, + long length); +ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x); +int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y); + +DECLARE_ASN1_FUNCTIONS(ASN1_ENUMERATED) + +int ASN1_UTCTIME_check(const ASN1_UTCTIME *a); +ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t); +ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, + int offset_day, long offset_sec); +int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str); +int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t); + +int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *a); +ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s, + time_t t); +ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, + time_t t, int offset_day, + long offset_sec); +int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str); + +int ASN1_TIME_diff(int *pday, int *psec, + const ASN1_TIME *from, const ASN1_TIME *to); + +DECLARE_ASN1_FUNCTIONS(ASN1_OCTET_STRING) +ASN1_OCTET_STRING *ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *a); +int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a, + const ASN1_OCTET_STRING *b); +int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *str, const unsigned char *data, + int len); + +DECLARE_ASN1_FUNCTIONS(ASN1_VISIBLESTRING) +DECLARE_ASN1_FUNCTIONS(ASN1_UNIVERSALSTRING) +DECLARE_ASN1_FUNCTIONS(ASN1_UTF8STRING) +DECLARE_ASN1_FUNCTIONS(ASN1_NULL) +DECLARE_ASN1_FUNCTIONS(ASN1_BMPSTRING) + +int UTF8_getc(const unsigned char *str, int len, unsigned long *val); +int UTF8_putc(unsigned char *str, int len, unsigned long value); + +DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE) + +DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING) +DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, DISPLAYTEXT) +DECLARE_ASN1_FUNCTIONS(ASN1_PRINTABLESTRING) +DECLARE_ASN1_FUNCTIONS(ASN1_T61STRING) +DECLARE_ASN1_FUNCTIONS(ASN1_IA5STRING) +DECLARE_ASN1_FUNCTIONS(ASN1_GENERALSTRING) +DECLARE_ASN1_FUNCTIONS(ASN1_UTCTIME) +DECLARE_ASN1_FUNCTIONS(ASN1_GENERALIZEDTIME) +DECLARE_ASN1_FUNCTIONS(ASN1_TIME) + +DECLARE_ASN1_ITEM(ASN1_OCTET_STRING_NDEF) + +ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t); +ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t, + int offset_day, long offset_sec); +int ASN1_TIME_check(const ASN1_TIME *t); +ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(const ASN1_TIME *t, + ASN1_GENERALIZEDTIME **out); +int ASN1_TIME_set_string(ASN1_TIME *s, const char *str); +int ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str); +int ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm); +int ASN1_TIME_normalize(ASN1_TIME *s); +int ASN1_TIME_cmp_time_t(const ASN1_TIME *s, time_t t); +int ASN1_TIME_compare(const ASN1_TIME *a, const ASN1_TIME *b); + +int i2a_ASN1_INTEGER(BIO *bp, const ASN1_INTEGER *a); +int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size); +int i2a_ASN1_ENUMERATED(BIO *bp, const ASN1_ENUMERATED *a); +int a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size); +int i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a); +int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size); +int i2a_ASN1_STRING(BIO *bp, const ASN1_STRING *a, int type); +int i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *a); + +int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num); +ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data, int len, + const char *sn, const char *ln); + +int ASN1_INTEGER_get_int64(int64_t *pr, const ASN1_INTEGER *a); +int ASN1_INTEGER_set_int64(ASN1_INTEGER *a, int64_t r); +int ASN1_INTEGER_get_uint64(uint64_t *pr, const ASN1_INTEGER *a); +int ASN1_INTEGER_set_uint64(ASN1_INTEGER *a, uint64_t r); + +int ASN1_INTEGER_set(ASN1_INTEGER *a, long v); +long ASN1_INTEGER_get(const ASN1_INTEGER *a); +ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai); +BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn); + +int ASN1_ENUMERATED_get_int64(int64_t *pr, const ASN1_ENUMERATED *a); +int ASN1_ENUMERATED_set_int64(ASN1_ENUMERATED *a, int64_t r); + + +int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v); +long ASN1_ENUMERATED_get(const ASN1_ENUMERATED *a); +ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(const BIGNUM *bn, ASN1_ENUMERATED *ai); +BIGNUM *ASN1_ENUMERATED_to_BN(const ASN1_ENUMERATED *ai, BIGNUM *bn); + +/* General */ +/* given a string, return the correct type, max is the maximum length */ +int ASN1_PRINTABLE_type(const unsigned char *s, int max); + +unsigned long ASN1_tag2bit(int tag); + +/* SPECIALS */ +int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag, + int *pclass, long omax); +int ASN1_check_infinite_end(unsigned char **p, long len); +int ASN1_const_check_infinite_end(const unsigned char **p, long len); +void ASN1_put_object(unsigned char **pp, int constructed, int length, + int tag, int xclass); +int ASN1_put_eoc(unsigned char **pp); +int ASN1_object_size(int constructed, int length, int tag); + +/* Used to implement other functions */ +void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x); + +# define ASN1_dup_of(type,i2d,d2i,x) \ + ((type*)ASN1_dup(CHECKED_I2D_OF(type, i2d), \ + CHECKED_D2I_OF(type, d2i), \ + CHECKED_PTR_OF(type, x))) + +# define ASN1_dup_of_const(type,i2d,d2i,x) \ + ((type*)ASN1_dup(CHECKED_I2D_OF(const type, i2d), \ + CHECKED_D2I_OF(type, d2i), \ + CHECKED_PTR_OF(const type, x))) + +void *ASN1_item_dup(const ASN1_ITEM *it, void *x); + +/* ASN1 alloc/free macros for when a type is only used internally */ + +# define M_ASN1_new_of(type) (type *)ASN1_item_new(ASN1_ITEM_rptr(type)) +# define M_ASN1_free_of(x, type) \ + ASN1_item_free(CHECKED_PTR_OF(type, x), ASN1_ITEM_rptr(type)) + +# ifndef OPENSSL_NO_STDIO +void *ASN1_d2i_fp(void *(*xnew) (void), d2i_of_void *d2i, FILE *in, void **x); + +# define ASN1_d2i_fp_of(type,xnew,d2i,in,x) \ + ((type*)ASN1_d2i_fp(CHECKED_NEW_OF(type, xnew), \ + CHECKED_D2I_OF(type, d2i), \ + in, \ + CHECKED_PPTR_OF(type, x))) + +void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x); +int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x); + +# define ASN1_i2d_fp_of(type,i2d,out,x) \ + (ASN1_i2d_fp(CHECKED_I2D_OF(type, i2d), \ + out, \ + CHECKED_PTR_OF(type, x))) + +# define ASN1_i2d_fp_of_const(type,i2d,out,x) \ + (ASN1_i2d_fp(CHECKED_I2D_OF(const type, i2d), \ + out, \ + CHECKED_PTR_OF(const type, x))) + +int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x); +int ASN1_STRING_print_ex_fp(FILE *fp, const ASN1_STRING *str, unsigned long flags); +# endif + +int ASN1_STRING_to_UTF8(unsigned char **out, const ASN1_STRING *in); + +void *ASN1_d2i_bio(void *(*xnew) (void), d2i_of_void *d2i, BIO *in, void **x); + +# define ASN1_d2i_bio_of(type,xnew,d2i,in,x) \ + ((type*)ASN1_d2i_bio( CHECKED_NEW_OF(type, xnew), \ + CHECKED_D2I_OF(type, d2i), \ + in, \ + CHECKED_PPTR_OF(type, x))) + +void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x); +int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, unsigned char *x); + +# define ASN1_i2d_bio_of(type,i2d,out,x) \ + (ASN1_i2d_bio(CHECKED_I2D_OF(type, i2d), \ + out, \ + CHECKED_PTR_OF(type, x))) + +# define ASN1_i2d_bio_of_const(type,i2d,out,x) \ + (ASN1_i2d_bio(CHECKED_I2D_OF(const type, i2d), \ + out, \ + CHECKED_PTR_OF(const type, x))) + +int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x); +int ASN1_UTCTIME_print(BIO *fp, const ASN1_UTCTIME *a); +int ASN1_GENERALIZEDTIME_print(BIO *fp, const ASN1_GENERALIZEDTIME *a); +int ASN1_TIME_print(BIO *fp, const ASN1_TIME *a); +int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v); +int ASN1_STRING_print_ex(BIO *out, const ASN1_STRING *str, unsigned long flags); +int ASN1_buf_print(BIO *bp, const unsigned char *buf, size_t buflen, int off); +int ASN1_bn_print(BIO *bp, const char *number, const BIGNUM *num, + unsigned char *buf, int off); +int ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent); +int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent, + int dump); +const char *ASN1_tag2str(int tag); + +/* Used to load and write Netscape format cert */ + +int ASN1_UNIVERSALSTRING_to_string(ASN1_UNIVERSALSTRING *s); + +int ASN1_TYPE_set_octetstring(ASN1_TYPE *a, unsigned char *data, int len); +int ASN1_TYPE_get_octetstring(const ASN1_TYPE *a, unsigned char *data, int max_len); +int ASN1_TYPE_set_int_octetstring(ASN1_TYPE *a, long num, + unsigned char *data, int len); +int ASN1_TYPE_get_int_octetstring(const ASN1_TYPE *a, long *num, + unsigned char *data, int max_len); + +void *ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it); + +ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, + ASN1_OCTET_STRING **oct); + +void ASN1_STRING_set_default_mask(unsigned long mask); +int ASN1_STRING_set_default_mask_asc(const char *p); +unsigned long ASN1_STRING_get_default_mask(void); +int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len, + int inform, unsigned long mask); +int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, + int inform, unsigned long mask, + long minsize, long maxsize); + +ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, + const unsigned char *in, int inlen, + int inform, int nid); +ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid); +int ASN1_STRING_TABLE_add(int, long, long, unsigned long, unsigned long); +void ASN1_STRING_TABLE_cleanup(void); + +/* ASN1 template functions */ + +/* Old API compatible functions */ +ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it); +void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it); +ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **val, const unsigned char **in, + long len, const ASN1_ITEM *it); +int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it); +int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out, + const ASN1_ITEM *it); + +void ASN1_add_oid_module(void); +void ASN1_add_stable_module(void); + +ASN1_TYPE *ASN1_generate_nconf(const char *str, CONF *nconf); +ASN1_TYPE *ASN1_generate_v3(const char *str, X509V3_CTX *cnf); +int ASN1_str2mask(const char *str, unsigned long *pmask); + +/* ASN1 Print flags */ + +/* Indicate missing OPTIONAL fields */ +# define ASN1_PCTX_FLAGS_SHOW_ABSENT 0x001 +/* Mark start and end of SEQUENCE */ +# define ASN1_PCTX_FLAGS_SHOW_SEQUENCE 0x002 +/* Mark start and end of SEQUENCE/SET OF */ +# define ASN1_PCTX_FLAGS_SHOW_SSOF 0x004 +/* Show the ASN1 type of primitives */ +# define ASN1_PCTX_FLAGS_SHOW_TYPE 0x008 +/* Don't show ASN1 type of ANY */ +# define ASN1_PCTX_FLAGS_NO_ANY_TYPE 0x010 +/* Don't show ASN1 type of MSTRINGs */ +# define ASN1_PCTX_FLAGS_NO_MSTRING_TYPE 0x020 +/* Don't show field names in SEQUENCE */ +# define ASN1_PCTX_FLAGS_NO_FIELD_NAME 0x040 +/* Show structure names of each SEQUENCE field */ +# define ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME 0x080 +/* Don't show structure name even at top level */ +# define ASN1_PCTX_FLAGS_NO_STRUCT_NAME 0x100 + +int ASN1_item_print(BIO *out, ASN1_VALUE *ifld, int indent, + const ASN1_ITEM *it, const ASN1_PCTX *pctx); +ASN1_PCTX *ASN1_PCTX_new(void); +void ASN1_PCTX_free(ASN1_PCTX *p); +unsigned long ASN1_PCTX_get_flags(const ASN1_PCTX *p); +void ASN1_PCTX_set_flags(ASN1_PCTX *p, unsigned long flags); +unsigned long ASN1_PCTX_get_nm_flags(const ASN1_PCTX *p); +void ASN1_PCTX_set_nm_flags(ASN1_PCTX *p, unsigned long flags); +unsigned long ASN1_PCTX_get_cert_flags(const ASN1_PCTX *p); +void ASN1_PCTX_set_cert_flags(ASN1_PCTX *p, unsigned long flags); +unsigned long ASN1_PCTX_get_oid_flags(const ASN1_PCTX *p); +void ASN1_PCTX_set_oid_flags(ASN1_PCTX *p, unsigned long flags); +unsigned long ASN1_PCTX_get_str_flags(const ASN1_PCTX *p); +void ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags); + +ASN1_SCTX *ASN1_SCTX_new(int (*scan_cb) (ASN1_SCTX *ctx)); +void ASN1_SCTX_free(ASN1_SCTX *p); +const ASN1_ITEM *ASN1_SCTX_get_item(ASN1_SCTX *p); +const ASN1_TEMPLATE *ASN1_SCTX_get_template(ASN1_SCTX *p); +unsigned long ASN1_SCTX_get_flags(ASN1_SCTX *p); +void ASN1_SCTX_set_app_data(ASN1_SCTX *p, void *data); +void *ASN1_SCTX_get_app_data(ASN1_SCTX *p); + +const BIO_METHOD *BIO_f_asn1(void); + +BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it); + +int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags, + const ASN1_ITEM *it); +int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags, + const char *hdr, const ASN1_ITEM *it); +int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags, + int ctype_nid, int econt_nid, + STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it); +ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it); +int SMIME_crlf_copy(BIO *in, BIO *out, int flags); +int SMIME_text(BIO *in, BIO *out); + +const ASN1_ITEM *ASN1_ITEM_lookup(const char *name); +const ASN1_ITEM *ASN1_ITEM_get(size_t i); + +# ifdef __cplusplus +} +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/asn1_mac.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/asn1_mac.h new file mode 100644 index 000000000..7ac1782a3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/asn1_mac.h @@ -0,0 +1,10 @@ +/* + * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#error "This file is obsolete; please update your software." diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/asn1err.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/asn1err.h new file mode 100644 index 000000000..5a91126db --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/asn1err.h @@ -0,0 +1,252 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_ASN1ERR_H +# define HEADER_ASN1ERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_ASN1_strings(void); + +/* + * ASN1 function codes. + */ +# define ASN1_F_A2D_ASN1_OBJECT 100 +# define ASN1_F_A2I_ASN1_INTEGER 102 +# define ASN1_F_A2I_ASN1_STRING 103 +# define ASN1_F_APPEND_EXP 176 +# define ASN1_F_ASN1_BIO_INIT 113 +# define ASN1_F_ASN1_BIT_STRING_SET_BIT 183 +# define ASN1_F_ASN1_CB 177 +# define ASN1_F_ASN1_CHECK_TLEN 104 +# define ASN1_F_ASN1_COLLECT 106 +# define ASN1_F_ASN1_D2I_EX_PRIMITIVE 108 +# define ASN1_F_ASN1_D2I_FP 109 +# define ASN1_F_ASN1_D2I_READ_BIO 107 +# define ASN1_F_ASN1_DIGEST 184 +# define ASN1_F_ASN1_DO_ADB 110 +# define ASN1_F_ASN1_DO_LOCK 233 +# define ASN1_F_ASN1_DUP 111 +# define ASN1_F_ASN1_ENC_SAVE 115 +# define ASN1_F_ASN1_EX_C2I 204 +# define ASN1_F_ASN1_FIND_END 190 +# define ASN1_F_ASN1_GENERALIZEDTIME_ADJ 216 +# define ASN1_F_ASN1_GENERATE_V3 178 +# define ASN1_F_ASN1_GET_INT64 224 +# define ASN1_F_ASN1_GET_OBJECT 114 +# define ASN1_F_ASN1_GET_UINT64 225 +# define ASN1_F_ASN1_I2D_BIO 116 +# define ASN1_F_ASN1_I2D_FP 117 +# define ASN1_F_ASN1_ITEM_D2I_FP 206 +# define ASN1_F_ASN1_ITEM_DUP 191 +# define ASN1_F_ASN1_ITEM_EMBED_D2I 120 +# define ASN1_F_ASN1_ITEM_EMBED_NEW 121 +# define ASN1_F_ASN1_ITEM_FLAGS_I2D 118 +# define ASN1_F_ASN1_ITEM_I2D_BIO 192 +# define ASN1_F_ASN1_ITEM_I2D_FP 193 +# define ASN1_F_ASN1_ITEM_PACK 198 +# define ASN1_F_ASN1_ITEM_SIGN 195 +# define ASN1_F_ASN1_ITEM_SIGN_CTX 220 +# define ASN1_F_ASN1_ITEM_UNPACK 199 +# define ASN1_F_ASN1_ITEM_VERIFY 197 +# define ASN1_F_ASN1_MBSTRING_NCOPY 122 +# define ASN1_F_ASN1_OBJECT_NEW 123 +# define ASN1_F_ASN1_OUTPUT_DATA 214 +# define ASN1_F_ASN1_PCTX_NEW 205 +# define ASN1_F_ASN1_PRIMITIVE_NEW 119 +# define ASN1_F_ASN1_SCTX_NEW 221 +# define ASN1_F_ASN1_SIGN 128 +# define ASN1_F_ASN1_STR2TYPE 179 +# define ASN1_F_ASN1_STRING_GET_INT64 227 +# define ASN1_F_ASN1_STRING_GET_UINT64 230 +# define ASN1_F_ASN1_STRING_SET 186 +# define ASN1_F_ASN1_STRING_TABLE_ADD 129 +# define ASN1_F_ASN1_STRING_TO_BN 228 +# define ASN1_F_ASN1_STRING_TYPE_NEW 130 +# define ASN1_F_ASN1_TEMPLATE_EX_D2I 132 +# define ASN1_F_ASN1_TEMPLATE_NEW 133 +# define ASN1_F_ASN1_TEMPLATE_NOEXP_D2I 131 +# define ASN1_F_ASN1_TIME_ADJ 217 +# define ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING 134 +# define ASN1_F_ASN1_TYPE_GET_OCTETSTRING 135 +# define ASN1_F_ASN1_UTCTIME_ADJ 218 +# define ASN1_F_ASN1_VERIFY 137 +# define ASN1_F_B64_READ_ASN1 209 +# define ASN1_F_B64_WRITE_ASN1 210 +# define ASN1_F_BIO_NEW_NDEF 208 +# define ASN1_F_BITSTR_CB 180 +# define ASN1_F_BN_TO_ASN1_STRING 229 +# define ASN1_F_C2I_ASN1_BIT_STRING 189 +# define ASN1_F_C2I_ASN1_INTEGER 194 +# define ASN1_F_C2I_ASN1_OBJECT 196 +# define ASN1_F_C2I_IBUF 226 +# define ASN1_F_C2I_UINT64_INT 101 +# define ASN1_F_COLLECT_DATA 140 +# define ASN1_F_D2I_ASN1_OBJECT 147 +# define ASN1_F_D2I_ASN1_UINTEGER 150 +# define ASN1_F_D2I_AUTOPRIVATEKEY 207 +# define ASN1_F_D2I_PRIVATEKEY 154 +# define ASN1_F_D2I_PUBLICKEY 155 +# define ASN1_F_DO_BUF 142 +# define ASN1_F_DO_CREATE 124 +# define ASN1_F_DO_DUMP 125 +# define ASN1_F_DO_TCREATE 222 +# define ASN1_F_I2A_ASN1_OBJECT 126 +# define ASN1_F_I2D_ASN1_BIO_STREAM 211 +# define ASN1_F_I2D_ASN1_OBJECT 143 +# define ASN1_F_I2D_DSA_PUBKEY 161 +# define ASN1_F_I2D_EC_PUBKEY 181 +# define ASN1_F_I2D_PRIVATEKEY 163 +# define ASN1_F_I2D_PUBLICKEY 164 +# define ASN1_F_I2D_RSA_PUBKEY 165 +# define ASN1_F_LONG_C2I 166 +# define ASN1_F_NDEF_PREFIX 127 +# define ASN1_F_NDEF_SUFFIX 136 +# define ASN1_F_OID_MODULE_INIT 174 +# define ASN1_F_PARSE_TAGGING 182 +# define ASN1_F_PKCS5_PBE2_SET_IV 167 +# define ASN1_F_PKCS5_PBE2_SET_SCRYPT 231 +# define ASN1_F_PKCS5_PBE_SET 202 +# define ASN1_F_PKCS5_PBE_SET0_ALGOR 215 +# define ASN1_F_PKCS5_PBKDF2_SET 219 +# define ASN1_F_PKCS5_SCRYPT_SET 232 +# define ASN1_F_SMIME_READ_ASN1 212 +# define ASN1_F_SMIME_TEXT 213 +# define ASN1_F_STABLE_GET 138 +# define ASN1_F_STBL_MODULE_INIT 223 +# define ASN1_F_UINT32_C2I 105 +# define ASN1_F_UINT32_NEW 139 +# define ASN1_F_UINT64_C2I 112 +# define ASN1_F_UINT64_NEW 141 +# define ASN1_F_X509_CRL_ADD0_REVOKED 169 +# define ASN1_F_X509_INFO_NEW 170 +# define ASN1_F_X509_NAME_ENCODE 203 +# define ASN1_F_X509_NAME_EX_D2I 158 +# define ASN1_F_X509_NAME_EX_NEW 171 +# define ASN1_F_X509_PKEY_NEW 173 + +/* + * ASN1 reason codes. + */ +# define ASN1_R_ADDING_OBJECT 171 +# define ASN1_R_ASN1_PARSE_ERROR 203 +# define ASN1_R_ASN1_SIG_PARSE_ERROR 204 +# define ASN1_R_AUX_ERROR 100 +# define ASN1_R_BAD_OBJECT_HEADER 102 +# define ASN1_R_BMPSTRING_IS_WRONG_LENGTH 214 +# define ASN1_R_BN_LIB 105 +# define ASN1_R_BOOLEAN_IS_WRONG_LENGTH 106 +# define ASN1_R_BUFFER_TOO_SMALL 107 +# define ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER 108 +# define ASN1_R_CONTEXT_NOT_INITIALISED 217 +# define ASN1_R_DATA_IS_WRONG 109 +# define ASN1_R_DECODE_ERROR 110 +# define ASN1_R_DEPTH_EXCEEDED 174 +# define ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED 198 +# define ASN1_R_ENCODE_ERROR 112 +# define ASN1_R_ERROR_GETTING_TIME 173 +# define ASN1_R_ERROR_LOADING_SECTION 172 +# define ASN1_R_ERROR_SETTING_CIPHER_PARAMS 114 +# define ASN1_R_EXPECTING_AN_INTEGER 115 +# define ASN1_R_EXPECTING_AN_OBJECT 116 +# define ASN1_R_EXPLICIT_LENGTH_MISMATCH 119 +# define ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED 120 +# define ASN1_R_FIELD_MISSING 121 +# define ASN1_R_FIRST_NUM_TOO_LARGE 122 +# define ASN1_R_HEADER_TOO_LONG 123 +# define ASN1_R_ILLEGAL_BITSTRING_FORMAT 175 +# define ASN1_R_ILLEGAL_BOOLEAN 176 +# define ASN1_R_ILLEGAL_CHARACTERS 124 +# define ASN1_R_ILLEGAL_FORMAT 177 +# define ASN1_R_ILLEGAL_HEX 178 +# define ASN1_R_ILLEGAL_IMPLICIT_TAG 179 +# define ASN1_R_ILLEGAL_INTEGER 180 +# define ASN1_R_ILLEGAL_NEGATIVE_VALUE 226 +# define ASN1_R_ILLEGAL_NESTED_TAGGING 181 +# define ASN1_R_ILLEGAL_NULL 125 +# define ASN1_R_ILLEGAL_NULL_VALUE 182 +# define ASN1_R_ILLEGAL_OBJECT 183 +# define ASN1_R_ILLEGAL_OPTIONAL_ANY 126 +# define ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE 170 +# define ASN1_R_ILLEGAL_PADDING 221 +# define ASN1_R_ILLEGAL_TAGGED_ANY 127 +# define ASN1_R_ILLEGAL_TIME_VALUE 184 +# define ASN1_R_ILLEGAL_ZERO_CONTENT 222 +# define ASN1_R_INTEGER_NOT_ASCII_FORMAT 185 +# define ASN1_R_INTEGER_TOO_LARGE_FOR_LONG 128 +# define ASN1_R_INVALID_BIT_STRING_BITS_LEFT 220 +# define ASN1_R_INVALID_BMPSTRING_LENGTH 129 +# define ASN1_R_INVALID_DIGIT 130 +# define ASN1_R_INVALID_MIME_TYPE 205 +# define ASN1_R_INVALID_MODIFIER 186 +# define ASN1_R_INVALID_NUMBER 187 +# define ASN1_R_INVALID_OBJECT_ENCODING 216 +# define ASN1_R_INVALID_SCRYPT_PARAMETERS 227 +# define ASN1_R_INVALID_SEPARATOR 131 +# define ASN1_R_INVALID_STRING_TABLE_VALUE 218 +# define ASN1_R_INVALID_UNIVERSALSTRING_LENGTH 133 +# define ASN1_R_INVALID_UTF8STRING 134 +# define ASN1_R_INVALID_VALUE 219 +# define ASN1_R_LIST_ERROR 188 +# define ASN1_R_MIME_NO_CONTENT_TYPE 206 +# define ASN1_R_MIME_PARSE_ERROR 207 +# define ASN1_R_MIME_SIG_PARSE_ERROR 208 +# define ASN1_R_MISSING_EOC 137 +# define ASN1_R_MISSING_SECOND_NUMBER 138 +# define ASN1_R_MISSING_VALUE 189 +# define ASN1_R_MSTRING_NOT_UNIVERSAL 139 +# define ASN1_R_MSTRING_WRONG_TAG 140 +# define ASN1_R_NESTED_ASN1_STRING 197 +# define ASN1_R_NESTED_TOO_DEEP 201 +# define ASN1_R_NON_HEX_CHARACTERS 141 +# define ASN1_R_NOT_ASCII_FORMAT 190 +# define ASN1_R_NOT_ENOUGH_DATA 142 +# define ASN1_R_NO_CONTENT_TYPE 209 +# define ASN1_R_NO_MATCHING_CHOICE_TYPE 143 +# define ASN1_R_NO_MULTIPART_BODY_FAILURE 210 +# define ASN1_R_NO_MULTIPART_BOUNDARY 211 +# define ASN1_R_NO_SIG_CONTENT_TYPE 212 +# define ASN1_R_NULL_IS_WRONG_LENGTH 144 +# define ASN1_R_OBJECT_NOT_ASCII_FORMAT 191 +# define ASN1_R_ODD_NUMBER_OF_CHARS 145 +# define ASN1_R_SECOND_NUMBER_TOO_LARGE 147 +# define ASN1_R_SEQUENCE_LENGTH_MISMATCH 148 +# define ASN1_R_SEQUENCE_NOT_CONSTRUCTED 149 +# define ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG 192 +# define ASN1_R_SHORT_LINE 150 +# define ASN1_R_SIG_INVALID_MIME_TYPE 213 +# define ASN1_R_STREAMING_NOT_SUPPORTED 202 +# define ASN1_R_STRING_TOO_LONG 151 +# define ASN1_R_STRING_TOO_SHORT 152 +# define ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 154 +# define ASN1_R_TIME_NOT_ASCII_FORMAT 193 +# define ASN1_R_TOO_LARGE 223 +# define ASN1_R_TOO_LONG 155 +# define ASN1_R_TOO_SMALL 224 +# define ASN1_R_TYPE_NOT_CONSTRUCTED 156 +# define ASN1_R_TYPE_NOT_PRIMITIVE 195 +# define ASN1_R_UNEXPECTED_EOC 159 +# define ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH 215 +# define ASN1_R_UNKNOWN_FORMAT 160 +# define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM 161 +# define ASN1_R_UNKNOWN_OBJECT_TYPE 162 +# define ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE 163 +# define ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM 199 +# define ASN1_R_UNKNOWN_TAG 194 +# define ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE 164 +# define ASN1_R_UNSUPPORTED_CIPHER 228 +# define ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE 167 +# define ASN1_R_UNSUPPORTED_TYPE 196 +# define ASN1_R_WRONG_INTEGER_TYPE 225 +# define ASN1_R_WRONG_PUBLIC_KEY_TYPE 200 +# define ASN1_R_WRONG_TAG 168 + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/asn1t.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/asn1t.h new file mode 100644 index 000000000..a450ba0d9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/asn1t.h @@ -0,0 +1,945 @@ +/* + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_ASN1T_H +# define HEADER_ASN1T_H + +# include +# include +# include + +# ifdef OPENSSL_BUILD_SHLIBCRYPTO +# undef OPENSSL_EXTERN +# define OPENSSL_EXTERN OPENSSL_EXPORT +# endif + +/* ASN1 template defines, structures and functions */ + +#ifdef __cplusplus +extern "C" { +#endif + +# ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION + +/* Macro to obtain ASN1_ADB pointer from a type (only used internally) */ +# define ASN1_ADB_ptr(iptr) ((const ASN1_ADB *)(iptr)) + +/* Macros for start and end of ASN1_ITEM definition */ + +# define ASN1_ITEM_start(itname) \ + const ASN1_ITEM itname##_it = { + +# define static_ASN1_ITEM_start(itname) \ + static const ASN1_ITEM itname##_it = { + +# define ASN1_ITEM_end(itname) \ + }; + +# else + +/* Macro to obtain ASN1_ADB pointer from a type (only used internally) */ +# define ASN1_ADB_ptr(iptr) ((const ASN1_ADB *)((iptr)())) + +/* Macros for start and end of ASN1_ITEM definition */ + +# define ASN1_ITEM_start(itname) \ + const ASN1_ITEM * itname##_it(void) \ + { \ + static const ASN1_ITEM local_it = { + +# define static_ASN1_ITEM_start(itname) \ + static ASN1_ITEM_start(itname) + +# define ASN1_ITEM_end(itname) \ + }; \ + return &local_it; \ + } + +# endif + +/* Macros to aid ASN1 template writing */ + +# define ASN1_ITEM_TEMPLATE(tname) \ + static const ASN1_TEMPLATE tname##_item_tt + +# define ASN1_ITEM_TEMPLATE_END(tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_PRIMITIVE,\ + -1,\ + &tname##_item_tt,\ + 0,\ + NULL,\ + 0,\ + #tname \ + ASN1_ITEM_end(tname) +# define static_ASN1_ITEM_TEMPLATE_END(tname) \ + ;\ + static_ASN1_ITEM_start(tname) \ + ASN1_ITYPE_PRIMITIVE,\ + -1,\ + &tname##_item_tt,\ + 0,\ + NULL,\ + 0,\ + #tname \ + ASN1_ITEM_end(tname) + +/* This is a ASN1 type which just embeds a template */ + +/*- + * This pair helps declare a SEQUENCE. We can do: + * + * ASN1_SEQUENCE(stname) = { + * ... SEQUENCE components ... + * } ASN1_SEQUENCE_END(stname) + * + * This will produce an ASN1_ITEM called stname_it + * for a structure called stname. + * + * If you want the same structure but a different + * name then use: + * + * ASN1_SEQUENCE(itname) = { + * ... SEQUENCE components ... + * } ASN1_SEQUENCE_END_name(stname, itname) + * + * This will create an item called itname_it using + * a structure called stname. + */ + +# define ASN1_SEQUENCE(tname) \ + static const ASN1_TEMPLATE tname##_seq_tt[] + +# define ASN1_SEQUENCE_END(stname) ASN1_SEQUENCE_END_name(stname, stname) + +# define static_ASN1_SEQUENCE_END(stname) static_ASN1_SEQUENCE_END_name(stname, stname) + +# define ASN1_SEQUENCE_END_name(stname, tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(stname),\ + #tname \ + ASN1_ITEM_end(tname) + +# define static_ASN1_SEQUENCE_END_name(stname, tname) \ + ;\ + static_ASN1_ITEM_start(tname) \ + ASN1_ITYPE_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +# define ASN1_NDEF_SEQUENCE(tname) \ + ASN1_SEQUENCE(tname) + +# define ASN1_NDEF_SEQUENCE_cb(tname, cb) \ + ASN1_SEQUENCE_cb(tname, cb) + +# define ASN1_SEQUENCE_cb(tname, cb) \ + static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \ + ASN1_SEQUENCE(tname) + +# define ASN1_BROKEN_SEQUENCE(tname) \ + static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_BROKEN, 0, 0, 0, 0}; \ + ASN1_SEQUENCE(tname) + +# define ASN1_SEQUENCE_ref(tname, cb) \ + static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_REFCOUNT, offsetof(tname, references), offsetof(tname, lock), cb, 0}; \ + ASN1_SEQUENCE(tname) + +# define ASN1_SEQUENCE_enc(tname, enc, cb) \ + static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_ENCODING, 0, 0, cb, offsetof(tname, enc)}; \ + ASN1_SEQUENCE(tname) + +# define ASN1_NDEF_SEQUENCE_END(tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_NDEF_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(tname),\ + #tname \ + ASN1_ITEM_end(tname) +# define static_ASN1_NDEF_SEQUENCE_END(tname) \ + ;\ + static_ASN1_ITEM_start(tname) \ + ASN1_ITYPE_NDEF_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(tname),\ + #tname \ + ASN1_ITEM_end(tname) + +# define ASN1_BROKEN_SEQUENCE_END(stname) ASN1_SEQUENCE_END_ref(stname, stname) +# define static_ASN1_BROKEN_SEQUENCE_END(stname) \ + static_ASN1_SEQUENCE_END_ref(stname, stname) + +# define ASN1_SEQUENCE_END_enc(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname) + +# define ASN1_SEQUENCE_END_cb(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname) +# define static_ASN1_SEQUENCE_END_cb(stname, tname) static_ASN1_SEQUENCE_END_ref(stname, tname) + +# define ASN1_SEQUENCE_END_ref(stname, tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + &tname##_aux,\ + sizeof(stname),\ + #tname \ + ASN1_ITEM_end(tname) +# define static_ASN1_SEQUENCE_END_ref(stname, tname) \ + ;\ + static_ASN1_ITEM_start(tname) \ + ASN1_ITYPE_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + &tname##_aux,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +# define ASN1_NDEF_SEQUENCE_END_cb(stname, tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_NDEF_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + &tname##_aux,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +/*- + * This pair helps declare a CHOICE type. We can do: + * + * ASN1_CHOICE(chname) = { + * ... CHOICE options ... + * ASN1_CHOICE_END(chname) + * + * This will produce an ASN1_ITEM called chname_it + * for a structure called chname. The structure + * definition must look like this: + * typedef struct { + * int type; + * union { + * ASN1_SOMETHING *opt1; + * ASN1_SOMEOTHER *opt2; + * } value; + * } chname; + * + * the name of the selector must be 'type'. + * to use an alternative selector name use the + * ASN1_CHOICE_END_selector() version. + */ + +# define ASN1_CHOICE(tname) \ + static const ASN1_TEMPLATE tname##_ch_tt[] + +# define ASN1_CHOICE_cb(tname, cb) \ + static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \ + ASN1_CHOICE(tname) + +# define ASN1_CHOICE_END(stname) ASN1_CHOICE_END_name(stname, stname) + +# define static_ASN1_CHOICE_END(stname) static_ASN1_CHOICE_END_name(stname, stname) + +# define ASN1_CHOICE_END_name(stname, tname) ASN1_CHOICE_END_selector(stname, tname, type) + +# define static_ASN1_CHOICE_END_name(stname, tname) static_ASN1_CHOICE_END_selector(stname, tname, type) + +# define ASN1_CHOICE_END_selector(stname, tname, selname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_CHOICE,\ + offsetof(stname,selname) ,\ + tname##_ch_tt,\ + sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +# define static_ASN1_CHOICE_END_selector(stname, tname, selname) \ + ;\ + static_ASN1_ITEM_start(tname) \ + ASN1_ITYPE_CHOICE,\ + offsetof(stname,selname) ,\ + tname##_ch_tt,\ + sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +# define ASN1_CHOICE_END_cb(stname, tname, selname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_CHOICE,\ + offsetof(stname,selname) ,\ + tname##_ch_tt,\ + sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\ + &tname##_aux,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +/* This helps with the template wrapper form of ASN1_ITEM */ + +# define ASN1_EX_TEMPLATE_TYPE(flags, tag, name, type) { \ + (flags), (tag), 0,\ + #name, ASN1_ITEM_ref(type) } + +/* These help with SEQUENCE or CHOICE components */ + +/* used to declare other types */ + +# define ASN1_EX_TYPE(flags, tag, stname, field, type) { \ + (flags), (tag), offsetof(stname, field),\ + #field, ASN1_ITEM_ref(type) } + +/* implicit and explicit helper macros */ + +# define ASN1_IMP_EX(stname, field, type, tag, ex) \ + ASN1_EX_TYPE(ASN1_TFLG_IMPLICIT | (ex), tag, stname, field, type) + +# define ASN1_EXP_EX(stname, field, type, tag, ex) \ + ASN1_EX_TYPE(ASN1_TFLG_EXPLICIT | (ex), tag, stname, field, type) + +/* Any defined by macros: the field used is in the table itself */ + +# ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION +# define ASN1_ADB_OBJECT(tblname) { ASN1_TFLG_ADB_OID, -1, 0, #tblname, (const ASN1_ITEM *)&(tblname##_adb) } +# define ASN1_ADB_INTEGER(tblname) { ASN1_TFLG_ADB_INT, -1, 0, #tblname, (const ASN1_ITEM *)&(tblname##_adb) } +# else +# define ASN1_ADB_OBJECT(tblname) { ASN1_TFLG_ADB_OID, -1, 0, #tblname, tblname##_adb } +# define ASN1_ADB_INTEGER(tblname) { ASN1_TFLG_ADB_INT, -1, 0, #tblname, tblname##_adb } +# endif +/* Plain simple type */ +# define ASN1_SIMPLE(stname, field, type) ASN1_EX_TYPE(0,0, stname, field, type) +/* Embedded simple type */ +# define ASN1_EMBED(stname, field, type) ASN1_EX_TYPE(ASN1_TFLG_EMBED,0, stname, field, type) + +/* OPTIONAL simple type */ +# define ASN1_OPT(stname, field, type) ASN1_EX_TYPE(ASN1_TFLG_OPTIONAL, 0, stname, field, type) +# define ASN1_OPT_EMBED(stname, field, type) ASN1_EX_TYPE(ASN1_TFLG_OPTIONAL|ASN1_TFLG_EMBED, 0, stname, field, type) + +/* IMPLICIT tagged simple type */ +# define ASN1_IMP(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, 0) +# define ASN1_IMP_EMBED(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_EMBED) + +/* IMPLICIT tagged OPTIONAL simple type */ +# define ASN1_IMP_OPT(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL) +# define ASN1_IMP_OPT_EMBED(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL|ASN1_TFLG_EMBED) + +/* Same as above but EXPLICIT */ + +# define ASN1_EXP(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, 0) +# define ASN1_EXP_EMBED(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_EMBED) +# define ASN1_EXP_OPT(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL) +# define ASN1_EXP_OPT_EMBED(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL|ASN1_TFLG_EMBED) + +/* SEQUENCE OF type */ +# define ASN1_SEQUENCE_OF(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, stname, field, type) + +/* OPTIONAL SEQUENCE OF */ +# define ASN1_SEQUENCE_OF_OPT(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type) + +/* Same as above but for SET OF */ + +# define ASN1_SET_OF(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SET_OF, 0, stname, field, type) + +# define ASN1_SET_OF_OPT(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type) + +/* Finally compound types of SEQUENCE, SET, IMPLICIT, EXPLICIT and OPTIONAL */ + +# define ASN1_IMP_SET_OF(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF) + +# define ASN1_EXP_SET_OF(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF) + +# define ASN1_IMP_SET_OF_OPT(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL) + +# define ASN1_EXP_SET_OF_OPT(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL) + +# define ASN1_IMP_SEQUENCE_OF(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF) + +# define ASN1_IMP_SEQUENCE_OF_OPT(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL) + +# define ASN1_EXP_SEQUENCE_OF(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF) + +# define ASN1_EXP_SEQUENCE_OF_OPT(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL) + +/* EXPLICIT using indefinite length constructed form */ +# define ASN1_NDEF_EXP(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_NDEF) + +/* EXPLICIT OPTIONAL using indefinite length constructed form */ +# define ASN1_NDEF_EXP_OPT(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL|ASN1_TFLG_NDEF) + +/* Macros for the ASN1_ADB structure */ + +# define ASN1_ADB(name) \ + static const ASN1_ADB_TABLE name##_adbtbl[] + +# ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION + +# define ASN1_ADB_END(name, flags, field, adb_cb, def, none) \ + ;\ + static const ASN1_ADB name##_adb = {\ + flags,\ + offsetof(name, field),\ + adb_cb,\ + name##_adbtbl,\ + sizeof(name##_adbtbl) / sizeof(ASN1_ADB_TABLE),\ + def,\ + none\ + } + +# else + +# define ASN1_ADB_END(name, flags, field, adb_cb, def, none) \ + ;\ + static const ASN1_ITEM *name##_adb(void) \ + { \ + static const ASN1_ADB internal_adb = \ + {\ + flags,\ + offsetof(name, field),\ + adb_cb,\ + name##_adbtbl,\ + sizeof(name##_adbtbl) / sizeof(ASN1_ADB_TABLE),\ + def,\ + none\ + }; \ + return (const ASN1_ITEM *) &internal_adb; \ + } \ + void dummy_function(void) + +# endif + +# define ADB_ENTRY(val, template) {val, template} + +# define ASN1_ADB_TEMPLATE(name) \ + static const ASN1_TEMPLATE name##_tt + +/* + * This is the ASN1 template structure that defines a wrapper round the + * actual type. It determines the actual position of the field in the value + * structure, various flags such as OPTIONAL and the field name. + */ + +struct ASN1_TEMPLATE_st { + unsigned long flags; /* Various flags */ + long tag; /* tag, not used if no tagging */ + unsigned long offset; /* Offset of this field in structure */ + const char *field_name; /* Field name */ + ASN1_ITEM_EXP *item; /* Relevant ASN1_ITEM or ASN1_ADB */ +}; + +/* Macro to extract ASN1_ITEM and ASN1_ADB pointer from ASN1_TEMPLATE */ + +# define ASN1_TEMPLATE_item(t) (t->item_ptr) +# define ASN1_TEMPLATE_adb(t) (t->item_ptr) + +typedef struct ASN1_ADB_TABLE_st ASN1_ADB_TABLE; +typedef struct ASN1_ADB_st ASN1_ADB; + +struct ASN1_ADB_st { + unsigned long flags; /* Various flags */ + unsigned long offset; /* Offset of selector field */ + int (*adb_cb)(long *psel); /* Application callback */ + const ASN1_ADB_TABLE *tbl; /* Table of possible types */ + long tblcount; /* Number of entries in tbl */ + const ASN1_TEMPLATE *default_tt; /* Type to use if no match */ + const ASN1_TEMPLATE *null_tt; /* Type to use if selector is NULL */ +}; + +struct ASN1_ADB_TABLE_st { + long value; /* NID for an object or value for an int */ + const ASN1_TEMPLATE tt; /* item for this value */ +}; + +/* template flags */ + +/* Field is optional */ +# define ASN1_TFLG_OPTIONAL (0x1) + +/* Field is a SET OF */ +# define ASN1_TFLG_SET_OF (0x1 << 1) + +/* Field is a SEQUENCE OF */ +# define ASN1_TFLG_SEQUENCE_OF (0x2 << 1) + +/* + * Special case: this refers to a SET OF that will be sorted into DER order + * when encoded *and* the corresponding STACK will be modified to match the + * new order. + */ +# define ASN1_TFLG_SET_ORDER (0x3 << 1) + +/* Mask for SET OF or SEQUENCE OF */ +# define ASN1_TFLG_SK_MASK (0x3 << 1) + +/* + * These flags mean the tag should be taken from the tag field. If EXPLICIT + * then the underlying type is used for the inner tag. + */ + +/* IMPLICIT tagging */ +# define ASN1_TFLG_IMPTAG (0x1 << 3) + +/* EXPLICIT tagging, inner tag from underlying type */ +# define ASN1_TFLG_EXPTAG (0x2 << 3) + +# define ASN1_TFLG_TAG_MASK (0x3 << 3) + +/* context specific IMPLICIT */ +# define ASN1_TFLG_IMPLICIT (ASN1_TFLG_IMPTAG|ASN1_TFLG_CONTEXT) + +/* context specific EXPLICIT */ +# define ASN1_TFLG_EXPLICIT (ASN1_TFLG_EXPTAG|ASN1_TFLG_CONTEXT) + +/* + * If tagging is in force these determine the type of tag to use. Otherwise + * the tag is determined by the underlying type. These values reflect the + * actual octet format. + */ + +/* Universal tag */ +# define ASN1_TFLG_UNIVERSAL (0x0<<6) +/* Application tag */ +# define ASN1_TFLG_APPLICATION (0x1<<6) +/* Context specific tag */ +# define ASN1_TFLG_CONTEXT (0x2<<6) +/* Private tag */ +# define ASN1_TFLG_PRIVATE (0x3<<6) + +# define ASN1_TFLG_TAG_CLASS (0x3<<6) + +/* + * These are for ANY DEFINED BY type. In this case the 'item' field points to + * an ASN1_ADB structure which contains a table of values to decode the + * relevant type + */ + +# define ASN1_TFLG_ADB_MASK (0x3<<8) + +# define ASN1_TFLG_ADB_OID (0x1<<8) + +# define ASN1_TFLG_ADB_INT (0x1<<9) + +/* + * This flag when present in a SEQUENCE OF, SET OF or EXPLICIT causes + * indefinite length constructed encoding to be used if required. + */ + +# define ASN1_TFLG_NDEF (0x1<<11) + +/* Field is embedded and not a pointer */ +# define ASN1_TFLG_EMBED (0x1 << 12) + +/* This is the actual ASN1 item itself */ + +struct ASN1_ITEM_st { + char itype; /* The item type, primitive, SEQUENCE, CHOICE + * or extern */ + long utype; /* underlying type */ + const ASN1_TEMPLATE *templates; /* If SEQUENCE or CHOICE this contains + * the contents */ + long tcount; /* Number of templates if SEQUENCE or CHOICE */ + const void *funcs; /* functions that handle this type */ + long size; /* Structure size (usually) */ + const char *sname; /* Structure name */ +}; + +/*- + * These are values for the itype field and + * determine how the type is interpreted. + * + * For PRIMITIVE types the underlying type + * determines the behaviour if items is NULL. + * + * Otherwise templates must contain a single + * template and the type is treated in the + * same way as the type specified in the template. + * + * For SEQUENCE types the templates field points + * to the members, the size field is the + * structure size. + * + * For CHOICE types the templates field points + * to each possible member (typically a union) + * and the 'size' field is the offset of the + * selector. + * + * The 'funcs' field is used for application + * specific functions. + * + * The EXTERN type uses a new style d2i/i2d. + * The new style should be used where possible + * because it avoids things like the d2i IMPLICIT + * hack. + * + * MSTRING is a multiple string type, it is used + * for a CHOICE of character strings where the + * actual strings all occupy an ASN1_STRING + * structure. In this case the 'utype' field + * has a special meaning, it is used as a mask + * of acceptable types using the B_ASN1 constants. + * + * NDEF_SEQUENCE is the same as SEQUENCE except + * that it will use indefinite length constructed + * encoding if requested. + * + */ + +# define ASN1_ITYPE_PRIMITIVE 0x0 + +# define ASN1_ITYPE_SEQUENCE 0x1 + +# define ASN1_ITYPE_CHOICE 0x2 + +# define ASN1_ITYPE_EXTERN 0x4 + +# define ASN1_ITYPE_MSTRING 0x5 + +# define ASN1_ITYPE_NDEF_SEQUENCE 0x6 + +/* + * Cache for ASN1 tag and length, so we don't keep re-reading it for things + * like CHOICE + */ + +struct ASN1_TLC_st { + char valid; /* Values below are valid */ + int ret; /* return value */ + long plen; /* length */ + int ptag; /* class value */ + int pclass; /* class value */ + int hdrlen; /* header length */ +}; + +/* Typedefs for ASN1 function pointers */ +typedef int ASN1_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, + const ASN1_ITEM *it, int tag, int aclass, char opt, + ASN1_TLC *ctx); + +typedef int ASN1_ex_i2d(ASN1_VALUE **pval, unsigned char **out, + const ASN1_ITEM *it, int tag, int aclass); +typedef int ASN1_ex_new_func(ASN1_VALUE **pval, const ASN1_ITEM *it); +typedef void ASN1_ex_free_func(ASN1_VALUE **pval, const ASN1_ITEM *it); + +typedef int ASN1_ex_print_func(BIO *out, ASN1_VALUE **pval, + int indent, const char *fname, + const ASN1_PCTX *pctx); + +typedef int ASN1_primitive_i2c(ASN1_VALUE **pval, unsigned char *cont, + int *putype, const ASN1_ITEM *it); +typedef int ASN1_primitive_c2i(ASN1_VALUE **pval, const unsigned char *cont, + int len, int utype, char *free_cont, + const ASN1_ITEM *it); +typedef int ASN1_primitive_print(BIO *out, ASN1_VALUE **pval, + const ASN1_ITEM *it, int indent, + const ASN1_PCTX *pctx); + +typedef struct ASN1_EXTERN_FUNCS_st { + void *app_data; + ASN1_ex_new_func *asn1_ex_new; + ASN1_ex_free_func *asn1_ex_free; + ASN1_ex_free_func *asn1_ex_clear; + ASN1_ex_d2i *asn1_ex_d2i; + ASN1_ex_i2d *asn1_ex_i2d; + ASN1_ex_print_func *asn1_ex_print; +} ASN1_EXTERN_FUNCS; + +typedef struct ASN1_PRIMITIVE_FUNCS_st { + void *app_data; + unsigned long flags; + ASN1_ex_new_func *prim_new; + ASN1_ex_free_func *prim_free; + ASN1_ex_free_func *prim_clear; + ASN1_primitive_c2i *prim_c2i; + ASN1_primitive_i2c *prim_i2c; + ASN1_primitive_print *prim_print; +} ASN1_PRIMITIVE_FUNCS; + +/* + * This is the ASN1_AUX structure: it handles various miscellaneous + * requirements. For example the use of reference counts and an informational + * callback. The "informational callback" is called at various points during + * the ASN1 encoding and decoding. It can be used to provide minor + * customisation of the structures used. This is most useful where the + * supplied routines *almost* do the right thing but need some extra help at + * a few points. If the callback returns zero then it is assumed a fatal + * error has occurred and the main operation should be abandoned. If major + * changes in the default behaviour are required then an external type is + * more appropriate. + */ + +typedef int ASN1_aux_cb(int operation, ASN1_VALUE **in, const ASN1_ITEM *it, + void *exarg); + +typedef struct ASN1_AUX_st { + void *app_data; + int flags; + int ref_offset; /* Offset of reference value */ + int ref_lock; /* Lock type to use */ + ASN1_aux_cb *asn1_cb; + int enc_offset; /* Offset of ASN1_ENCODING structure */ +} ASN1_AUX; + +/* For print related callbacks exarg points to this structure */ +typedef struct ASN1_PRINT_ARG_st { + BIO *out; + int indent; + const ASN1_PCTX *pctx; +} ASN1_PRINT_ARG; + +/* For streaming related callbacks exarg points to this structure */ +typedef struct ASN1_STREAM_ARG_st { + /* BIO to stream through */ + BIO *out; + /* BIO with filters appended */ + BIO *ndef_bio; + /* Streaming I/O boundary */ + unsigned char **boundary; +} ASN1_STREAM_ARG; + +/* Flags in ASN1_AUX */ + +/* Use a reference count */ +# define ASN1_AFLG_REFCOUNT 1 +/* Save the encoding of structure (useful for signatures) */ +# define ASN1_AFLG_ENCODING 2 +/* The Sequence length is invalid */ +# define ASN1_AFLG_BROKEN 4 + +/* operation values for asn1_cb */ + +# define ASN1_OP_NEW_PRE 0 +# define ASN1_OP_NEW_POST 1 +# define ASN1_OP_FREE_PRE 2 +# define ASN1_OP_FREE_POST 3 +# define ASN1_OP_D2I_PRE 4 +# define ASN1_OP_D2I_POST 5 +# define ASN1_OP_I2D_PRE 6 +# define ASN1_OP_I2D_POST 7 +# define ASN1_OP_PRINT_PRE 8 +# define ASN1_OP_PRINT_POST 9 +# define ASN1_OP_STREAM_PRE 10 +# define ASN1_OP_STREAM_POST 11 +# define ASN1_OP_DETACHED_PRE 12 +# define ASN1_OP_DETACHED_POST 13 + +/* Macro to implement a primitive type */ +# define IMPLEMENT_ASN1_TYPE(stname) IMPLEMENT_ASN1_TYPE_ex(stname, stname, 0) +# define IMPLEMENT_ASN1_TYPE_ex(itname, vname, ex) \ + ASN1_ITEM_start(itname) \ + ASN1_ITYPE_PRIMITIVE, V_##vname, NULL, 0, NULL, ex, #itname \ + ASN1_ITEM_end(itname) + +/* Macro to implement a multi string type */ +# define IMPLEMENT_ASN1_MSTRING(itname, mask) \ + ASN1_ITEM_start(itname) \ + ASN1_ITYPE_MSTRING, mask, NULL, 0, NULL, sizeof(ASN1_STRING), #itname \ + ASN1_ITEM_end(itname) + +# define IMPLEMENT_EXTERN_ASN1(sname, tag, fptrs) \ + ASN1_ITEM_start(sname) \ + ASN1_ITYPE_EXTERN, \ + tag, \ + NULL, \ + 0, \ + &fptrs, \ + 0, \ + #sname \ + ASN1_ITEM_end(sname) + +/* Macro to implement standard functions in terms of ASN1_ITEM structures */ + +# define IMPLEMENT_ASN1_FUNCTIONS(stname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, stname, stname) + +# define IMPLEMENT_ASN1_FUNCTIONS_name(stname, itname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, itname) + +# define IMPLEMENT_ASN1_FUNCTIONS_ENCODE_name(stname, itname) \ + IMPLEMENT_ASN1_FUNCTIONS_ENCODE_fname(stname, itname, itname) + +# define IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(stname) \ + IMPLEMENT_ASN1_ALLOC_FUNCTIONS_pfname(static, stname, stname, stname) + +# define IMPLEMENT_ASN1_ALLOC_FUNCTIONS(stname) \ + IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, stname, stname) + +# define IMPLEMENT_ASN1_ALLOC_FUNCTIONS_pfname(pre, stname, itname, fname) \ + pre stname *fname##_new(void) \ + { \ + return (stname *)ASN1_item_new(ASN1_ITEM_rptr(itname)); \ + } \ + pre void fname##_free(stname *a) \ + { \ + ASN1_item_free((ASN1_VALUE *)a, ASN1_ITEM_rptr(itname)); \ + } + +# define IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) \ + stname *fname##_new(void) \ + { \ + return (stname *)ASN1_item_new(ASN1_ITEM_rptr(itname)); \ + } \ + void fname##_free(stname *a) \ + { \ + ASN1_item_free((ASN1_VALUE *)a, ASN1_ITEM_rptr(itname)); \ + } + +# define IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, fname) \ + IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \ + IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) + +# define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \ + stname *d2i_##fname(stname **a, const unsigned char **in, long len) \ + { \ + return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\ + } \ + int i2d_##fname(stname *a, unsigned char **out) \ + { \ + return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\ + } + +# define IMPLEMENT_ASN1_NDEF_FUNCTION(stname) \ + int i2d_##stname##_NDEF(stname *a, unsigned char **out) \ + { \ + return ASN1_item_ndef_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(stname));\ + } + +# define IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(stname) \ + static stname *d2i_##stname(stname **a, \ + const unsigned char **in, long len) \ + { \ + return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, \ + ASN1_ITEM_rptr(stname)); \ + } \ + static int i2d_##stname(stname *a, unsigned char **out) \ + { \ + return ASN1_item_i2d((ASN1_VALUE *)a, out, \ + ASN1_ITEM_rptr(stname)); \ + } + +/* + * This includes evil casts to remove const: they will go away when full ASN1 + * constification is done. + */ +# define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \ + stname *d2i_##fname(stname **a, const unsigned char **in, long len) \ + { \ + return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\ + } \ + int i2d_##fname(const stname *a, unsigned char **out) \ + { \ + return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\ + } + +# define IMPLEMENT_ASN1_DUP_FUNCTION(stname) \ + stname * stname##_dup(stname *x) \ + { \ + return ASN1_item_dup(ASN1_ITEM_rptr(stname), x); \ + } + +# define IMPLEMENT_ASN1_PRINT_FUNCTION(stname) \ + IMPLEMENT_ASN1_PRINT_FUNCTION_fname(stname, stname, stname) + +# define IMPLEMENT_ASN1_PRINT_FUNCTION_fname(stname, itname, fname) \ + int fname##_print_ctx(BIO *out, stname *x, int indent, \ + const ASN1_PCTX *pctx) \ + { \ + return ASN1_item_print(out, (ASN1_VALUE *)x, indent, \ + ASN1_ITEM_rptr(itname), pctx); \ + } + +# define IMPLEMENT_ASN1_FUNCTIONS_const(name) \ + IMPLEMENT_ASN1_FUNCTIONS_const_fname(name, name, name) + +# define IMPLEMENT_ASN1_FUNCTIONS_const_fname(stname, itname, fname) \ + IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \ + IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) + +/* external definitions for primitive types */ + +DECLARE_ASN1_ITEM(ASN1_BOOLEAN) +DECLARE_ASN1_ITEM(ASN1_TBOOLEAN) +DECLARE_ASN1_ITEM(ASN1_FBOOLEAN) +DECLARE_ASN1_ITEM(ASN1_SEQUENCE) +DECLARE_ASN1_ITEM(CBIGNUM) +DECLARE_ASN1_ITEM(BIGNUM) +DECLARE_ASN1_ITEM(INT32) +DECLARE_ASN1_ITEM(ZINT32) +DECLARE_ASN1_ITEM(UINT32) +DECLARE_ASN1_ITEM(ZUINT32) +DECLARE_ASN1_ITEM(INT64) +DECLARE_ASN1_ITEM(ZINT64) +DECLARE_ASN1_ITEM(UINT64) +DECLARE_ASN1_ITEM(ZUINT64) + +# if OPENSSL_API_COMPAT < 0x10200000L +/* + * LONG and ZLONG are strongly discouraged for use as stored data, as the + * underlying C type (long) differs in size depending on the architecture. + * They are designed with 32-bit longs in mind. + */ +DECLARE_ASN1_ITEM(LONG) +DECLARE_ASN1_ITEM(ZLONG) +# endif + +DEFINE_STACK_OF(ASN1_VALUE) + +/* Functions used internally by the ASN1 code */ + +int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it); +void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it); + +int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, + const ASN1_ITEM *it, int tag, int aclass, char opt, + ASN1_TLC *ctx); + +int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, + const ASN1_ITEM *it, int tag, int aclass); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/async.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/async.h new file mode 100644 index 000000000..7052b8905 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/async.h @@ -0,0 +1,76 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#ifndef HEADER_ASYNC_H +# define HEADER_ASYNC_H + +#if defined(_WIN32) +# if defined(BASETYPES) || defined(_WINDEF_H) +/* application has to include to use this */ +#define OSSL_ASYNC_FD HANDLE +#define OSSL_BAD_ASYNC_FD INVALID_HANDLE_VALUE +# endif +#else +#define OSSL_ASYNC_FD int +#define OSSL_BAD_ASYNC_FD -1 +#endif +# include + + +# ifdef __cplusplus +extern "C" { +# endif + +typedef struct async_job_st ASYNC_JOB; +typedef struct async_wait_ctx_st ASYNC_WAIT_CTX; + +#define ASYNC_ERR 0 +#define ASYNC_NO_JOBS 1 +#define ASYNC_PAUSE 2 +#define ASYNC_FINISH 3 + +int ASYNC_init_thread(size_t max_size, size_t init_size); +void ASYNC_cleanup_thread(void); + +#ifdef OSSL_ASYNC_FD +ASYNC_WAIT_CTX *ASYNC_WAIT_CTX_new(void); +void ASYNC_WAIT_CTX_free(ASYNC_WAIT_CTX *ctx); +int ASYNC_WAIT_CTX_set_wait_fd(ASYNC_WAIT_CTX *ctx, const void *key, + OSSL_ASYNC_FD fd, + void *custom_data, + void (*cleanup)(ASYNC_WAIT_CTX *, const void *, + OSSL_ASYNC_FD, void *)); +int ASYNC_WAIT_CTX_get_fd(ASYNC_WAIT_CTX *ctx, const void *key, + OSSL_ASYNC_FD *fd, void **custom_data); +int ASYNC_WAIT_CTX_get_all_fds(ASYNC_WAIT_CTX *ctx, OSSL_ASYNC_FD *fd, + size_t *numfds); +int ASYNC_WAIT_CTX_get_changed_fds(ASYNC_WAIT_CTX *ctx, OSSL_ASYNC_FD *addfd, + size_t *numaddfds, OSSL_ASYNC_FD *delfd, + size_t *numdelfds); +int ASYNC_WAIT_CTX_clear_fd(ASYNC_WAIT_CTX *ctx, const void *key); +#endif + +int ASYNC_is_capable(void); + +int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *ctx, int *ret, + int (*func)(void *), void *args, size_t size); +int ASYNC_pause_job(void); + +ASYNC_JOB *ASYNC_get_current_job(void); +ASYNC_WAIT_CTX *ASYNC_get_wait_ctx(ASYNC_JOB *job); +void ASYNC_block_pause(void); +void ASYNC_unblock_pause(void); + + +# ifdef __cplusplus +} +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/asyncerr.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/asyncerr.h new file mode 100644 index 000000000..5497ba752 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/asyncerr.h @@ -0,0 +1,38 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_ASYNCERR_H +# define HEADER_ASYNCERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_ASYNC_strings(void); + +/* + * ASYNC function codes. + */ +# define ASYNC_F_ASYNC_CTX_NEW 100 +# define ASYNC_F_ASYNC_INIT_THREAD 101 +# define ASYNC_F_ASYNC_JOB_NEW 102 +# define ASYNC_F_ASYNC_PAUSE_JOB 103 +# define ASYNC_F_ASYNC_START_FUNC 104 +# define ASYNC_F_ASYNC_START_JOB 105 +# define ASYNC_F_ASYNC_WAIT_CTX_SET_WAIT_FD 106 + +/* + * ASYNC reason codes. + */ +# define ASYNC_R_FAILED_TO_SET_POOL 101 +# define ASYNC_R_FAILED_TO_SWAP_CONTEXT 102 +# define ASYNC_R_INIT_FAILED 105 +# define ASYNC_R_INVALID_POOL_SIZE 103 + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/bio.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/bio.h new file mode 100644 index 000000000..2888b42da --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/bio.h @@ -0,0 +1,804 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_BIO_H +# define HEADER_BIO_H + +# include + +# ifndef OPENSSL_NO_STDIO +# include +# endif +# include + +# include +# include + +# ifndef OPENSSL_NO_SCTP +# include +# endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* There are the classes of BIOs */ +# define BIO_TYPE_DESCRIPTOR 0x0100 /* socket, fd, connect or accept */ +# define BIO_TYPE_FILTER 0x0200 +# define BIO_TYPE_SOURCE_SINK 0x0400 + +/* These are the 'types' of BIOs */ +# define BIO_TYPE_NONE 0 +# define BIO_TYPE_MEM ( 1|BIO_TYPE_SOURCE_SINK) +# define BIO_TYPE_FILE ( 2|BIO_TYPE_SOURCE_SINK) + +# define BIO_TYPE_FD ( 4|BIO_TYPE_SOURCE_SINK|BIO_TYPE_DESCRIPTOR) +# define BIO_TYPE_SOCKET ( 5|BIO_TYPE_SOURCE_SINK|BIO_TYPE_DESCRIPTOR) +# define BIO_TYPE_NULL ( 6|BIO_TYPE_SOURCE_SINK) +# define BIO_TYPE_SSL ( 7|BIO_TYPE_FILTER) +# define BIO_TYPE_MD ( 8|BIO_TYPE_FILTER) +# define BIO_TYPE_BUFFER ( 9|BIO_TYPE_FILTER) +# define BIO_TYPE_CIPHER (10|BIO_TYPE_FILTER) +# define BIO_TYPE_BASE64 (11|BIO_TYPE_FILTER) +# define BIO_TYPE_CONNECT (12|BIO_TYPE_SOURCE_SINK|BIO_TYPE_DESCRIPTOR) +# define BIO_TYPE_ACCEPT (13|BIO_TYPE_SOURCE_SINK|BIO_TYPE_DESCRIPTOR) + +# define BIO_TYPE_NBIO_TEST (16|BIO_TYPE_FILTER)/* server proxy BIO */ +# define BIO_TYPE_NULL_FILTER (17|BIO_TYPE_FILTER) +# define BIO_TYPE_BIO (19|BIO_TYPE_SOURCE_SINK)/* half a BIO pair */ +# define BIO_TYPE_LINEBUFFER (20|BIO_TYPE_FILTER) +# define BIO_TYPE_DGRAM (21|BIO_TYPE_SOURCE_SINK|BIO_TYPE_DESCRIPTOR) +# define BIO_TYPE_ASN1 (22|BIO_TYPE_FILTER) +# define BIO_TYPE_COMP (23|BIO_TYPE_FILTER) +# ifndef OPENSSL_NO_SCTP +# define BIO_TYPE_DGRAM_SCTP (24|BIO_TYPE_SOURCE_SINK|BIO_TYPE_DESCRIPTOR) +# endif + +#define BIO_TYPE_START 128 + +/* + * BIO_FILENAME_READ|BIO_CLOSE to open or close on free. + * BIO_set_fp(in,stdin,BIO_NOCLOSE); + */ +# define BIO_NOCLOSE 0x00 +# define BIO_CLOSE 0x01 + +/* + * These are used in the following macros and are passed to BIO_ctrl() + */ +# define BIO_CTRL_RESET 1/* opt - rewind/zero etc */ +# define BIO_CTRL_EOF 2/* opt - are we at the eof */ +# define BIO_CTRL_INFO 3/* opt - extra tit-bits */ +# define BIO_CTRL_SET 4/* man - set the 'IO' type */ +# define BIO_CTRL_GET 5/* man - get the 'IO' type */ +# define BIO_CTRL_PUSH 6/* opt - internal, used to signify change */ +# define BIO_CTRL_POP 7/* opt - internal, used to signify change */ +# define BIO_CTRL_GET_CLOSE 8/* man - set the 'close' on free */ +# define BIO_CTRL_SET_CLOSE 9/* man - set the 'close' on free */ +# define BIO_CTRL_PENDING 10/* opt - is their more data buffered */ +# define BIO_CTRL_FLUSH 11/* opt - 'flush' buffered output */ +# define BIO_CTRL_DUP 12/* man - extra stuff for 'duped' BIO */ +# define BIO_CTRL_WPENDING 13/* opt - number of bytes still to write */ +# define BIO_CTRL_SET_CALLBACK 14/* opt - set callback function */ +# define BIO_CTRL_GET_CALLBACK 15/* opt - set callback function */ + +# define BIO_CTRL_PEEK 29/* BIO_f_buffer special */ +# define BIO_CTRL_SET_FILENAME 30/* BIO_s_file special */ + +/* dgram BIO stuff */ +# define BIO_CTRL_DGRAM_CONNECT 31/* BIO dgram special */ +# define BIO_CTRL_DGRAM_SET_CONNECTED 32/* allow for an externally connected + * socket to be passed in */ +# define BIO_CTRL_DGRAM_SET_RECV_TIMEOUT 33/* setsockopt, essentially */ +# define BIO_CTRL_DGRAM_GET_RECV_TIMEOUT 34/* getsockopt, essentially */ +# define BIO_CTRL_DGRAM_SET_SEND_TIMEOUT 35/* setsockopt, essentially */ +# define BIO_CTRL_DGRAM_GET_SEND_TIMEOUT 36/* getsockopt, essentially */ + +# define BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP 37/* flag whether the last */ +# define BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP 38/* I/O operation tiemd out */ + +/* #ifdef IP_MTU_DISCOVER */ +# define BIO_CTRL_DGRAM_MTU_DISCOVER 39/* set DF bit on egress packets */ +/* #endif */ + +# define BIO_CTRL_DGRAM_QUERY_MTU 40/* as kernel for current MTU */ +# define BIO_CTRL_DGRAM_GET_FALLBACK_MTU 47 +# define BIO_CTRL_DGRAM_GET_MTU 41/* get cached value for MTU */ +# define BIO_CTRL_DGRAM_SET_MTU 42/* set cached value for MTU. + * want to use this if asking + * the kernel fails */ + +# define BIO_CTRL_DGRAM_MTU_EXCEEDED 43/* check whether the MTU was + * exceed in the previous write + * operation */ + +# define BIO_CTRL_DGRAM_GET_PEER 46 +# define BIO_CTRL_DGRAM_SET_PEER 44/* Destination for the data */ + +# define BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT 45/* Next DTLS handshake timeout + * to adjust socket timeouts */ +# define BIO_CTRL_DGRAM_SET_DONT_FRAG 48 + +# define BIO_CTRL_DGRAM_GET_MTU_OVERHEAD 49 + +/* Deliberately outside of OPENSSL_NO_SCTP - used in bss_dgram.c */ +# define BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE 50 +# ifndef OPENSSL_NO_SCTP +/* SCTP stuff */ +# define BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY 51 +# define BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY 52 +# define BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD 53 +# define BIO_CTRL_DGRAM_SCTP_GET_SNDINFO 60 +# define BIO_CTRL_DGRAM_SCTP_SET_SNDINFO 61 +# define BIO_CTRL_DGRAM_SCTP_GET_RCVINFO 62 +# define BIO_CTRL_DGRAM_SCTP_SET_RCVINFO 63 +# define BIO_CTRL_DGRAM_SCTP_GET_PRINFO 64 +# define BIO_CTRL_DGRAM_SCTP_SET_PRINFO 65 +# define BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN 70 +# endif + +# define BIO_CTRL_DGRAM_SET_PEEK_MODE 71 + +/* modifiers */ +# define BIO_FP_READ 0x02 +# define BIO_FP_WRITE 0x04 +# define BIO_FP_APPEND 0x08 +# define BIO_FP_TEXT 0x10 + +# define BIO_FLAGS_READ 0x01 +# define BIO_FLAGS_WRITE 0x02 +# define BIO_FLAGS_IO_SPECIAL 0x04 +# define BIO_FLAGS_RWS (BIO_FLAGS_READ|BIO_FLAGS_WRITE|BIO_FLAGS_IO_SPECIAL) +# define BIO_FLAGS_SHOULD_RETRY 0x08 +# ifndef BIO_FLAGS_UPLINK +/* + * "UPLINK" flag denotes file descriptors provided by application. It + * defaults to 0, as most platforms don't require UPLINK interface. + */ +# define BIO_FLAGS_UPLINK 0 +# endif + +# define BIO_FLAGS_BASE64_NO_NL 0x100 + +/* + * This is used with memory BIOs: + * BIO_FLAGS_MEM_RDONLY means we shouldn't free up or change the data in any way; + * BIO_FLAGS_NONCLEAR_RST means we shouldn't clear data on reset. + */ +# define BIO_FLAGS_MEM_RDONLY 0x200 +# define BIO_FLAGS_NONCLEAR_RST 0x400 + +typedef union bio_addr_st BIO_ADDR; +typedef struct bio_addrinfo_st BIO_ADDRINFO; + +int BIO_get_new_index(void); +void BIO_set_flags(BIO *b, int flags); +int BIO_test_flags(const BIO *b, int flags); +void BIO_clear_flags(BIO *b, int flags); + +# define BIO_get_flags(b) BIO_test_flags(b, ~(0x0)) +# define BIO_set_retry_special(b) \ + BIO_set_flags(b, (BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY)) +# define BIO_set_retry_read(b) \ + BIO_set_flags(b, (BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY)) +# define BIO_set_retry_write(b) \ + BIO_set_flags(b, (BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY)) + +/* These are normally used internally in BIOs */ +# define BIO_clear_retry_flags(b) \ + BIO_clear_flags(b, (BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY)) +# define BIO_get_retry_flags(b) \ + BIO_test_flags(b, (BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY)) + +/* These should be used by the application to tell why we should retry */ +# define BIO_should_read(a) BIO_test_flags(a, BIO_FLAGS_READ) +# define BIO_should_write(a) BIO_test_flags(a, BIO_FLAGS_WRITE) +# define BIO_should_io_special(a) BIO_test_flags(a, BIO_FLAGS_IO_SPECIAL) +# define BIO_retry_type(a) BIO_test_flags(a, BIO_FLAGS_RWS) +# define BIO_should_retry(a) BIO_test_flags(a, BIO_FLAGS_SHOULD_RETRY) + +/* + * The next three are used in conjunction with the BIO_should_io_special() + * condition. After this returns true, BIO *BIO_get_retry_BIO(BIO *bio, int + * *reason); will walk the BIO stack and return the 'reason' for the special + * and the offending BIO. Given a BIO, BIO_get_retry_reason(bio) will return + * the code. + */ +/* + * Returned from the SSL bio when the certificate retrieval code had an error + */ +# define BIO_RR_SSL_X509_LOOKUP 0x01 +/* Returned from the connect BIO when a connect would have blocked */ +# define BIO_RR_CONNECT 0x02 +/* Returned from the accept BIO when an accept would have blocked */ +# define BIO_RR_ACCEPT 0x03 + +/* These are passed by the BIO callback */ +# define BIO_CB_FREE 0x01 +# define BIO_CB_READ 0x02 +# define BIO_CB_WRITE 0x03 +# define BIO_CB_PUTS 0x04 +# define BIO_CB_GETS 0x05 +# define BIO_CB_CTRL 0x06 + +/* + * The callback is called before and after the underling operation, The + * BIO_CB_RETURN flag indicates if it is after the call + */ +# define BIO_CB_RETURN 0x80 +# define BIO_CB_return(a) ((a)|BIO_CB_RETURN) +# define BIO_cb_pre(a) (!((a)&BIO_CB_RETURN)) +# define BIO_cb_post(a) ((a)&BIO_CB_RETURN) + +typedef long (*BIO_callback_fn)(BIO *b, int oper, const char *argp, int argi, + long argl, long ret); +typedef long (*BIO_callback_fn_ex)(BIO *b, int oper, const char *argp, + size_t len, int argi, + long argl, int ret, size_t *processed); +BIO_callback_fn BIO_get_callback(const BIO *b); +void BIO_set_callback(BIO *b, BIO_callback_fn callback); + +BIO_callback_fn_ex BIO_get_callback_ex(const BIO *b); +void BIO_set_callback_ex(BIO *b, BIO_callback_fn_ex callback); + +char *BIO_get_callback_arg(const BIO *b); +void BIO_set_callback_arg(BIO *b, char *arg); + +typedef struct bio_method_st BIO_METHOD; + +const char *BIO_method_name(const BIO *b); +int BIO_method_type(const BIO *b); + +typedef int BIO_info_cb(BIO *, int, int); +typedef BIO_info_cb bio_info_cb; /* backward compatibility */ + +DEFINE_STACK_OF(BIO) + +/* Prefix and suffix callback in ASN1 BIO */ +typedef int asn1_ps_func (BIO *b, unsigned char **pbuf, int *plen, + void *parg); + +# ifndef OPENSSL_NO_SCTP +/* SCTP parameter structs */ +struct bio_dgram_sctp_sndinfo { + uint16_t snd_sid; + uint16_t snd_flags; + uint32_t snd_ppid; + uint32_t snd_context; +}; + +struct bio_dgram_sctp_rcvinfo { + uint16_t rcv_sid; + uint16_t rcv_ssn; + uint16_t rcv_flags; + uint32_t rcv_ppid; + uint32_t rcv_tsn; + uint32_t rcv_cumtsn; + uint32_t rcv_context; +}; + +struct bio_dgram_sctp_prinfo { + uint16_t pr_policy; + uint32_t pr_value; +}; +# endif + +/* + * #define BIO_CONN_get_param_hostname BIO_ctrl + */ + +# define BIO_C_SET_CONNECT 100 +# define BIO_C_DO_STATE_MACHINE 101 +# define BIO_C_SET_NBIO 102 +/* # define BIO_C_SET_PROXY_PARAM 103 */ +# define BIO_C_SET_FD 104 +# define BIO_C_GET_FD 105 +# define BIO_C_SET_FILE_PTR 106 +# define BIO_C_GET_FILE_PTR 107 +# define BIO_C_SET_FILENAME 108 +# define BIO_C_SET_SSL 109 +# define BIO_C_GET_SSL 110 +# define BIO_C_SET_MD 111 +# define BIO_C_GET_MD 112 +# define BIO_C_GET_CIPHER_STATUS 113 +# define BIO_C_SET_BUF_MEM 114 +# define BIO_C_GET_BUF_MEM_PTR 115 +# define BIO_C_GET_BUFF_NUM_LINES 116 +# define BIO_C_SET_BUFF_SIZE 117 +# define BIO_C_SET_ACCEPT 118 +# define BIO_C_SSL_MODE 119 +# define BIO_C_GET_MD_CTX 120 +/* # define BIO_C_GET_PROXY_PARAM 121 */ +# define BIO_C_SET_BUFF_READ_DATA 122/* data to read first */ +# define BIO_C_GET_CONNECT 123 +# define BIO_C_GET_ACCEPT 124 +# define BIO_C_SET_SSL_RENEGOTIATE_BYTES 125 +# define BIO_C_GET_SSL_NUM_RENEGOTIATES 126 +# define BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT 127 +# define BIO_C_FILE_SEEK 128 +# define BIO_C_GET_CIPHER_CTX 129 +# define BIO_C_SET_BUF_MEM_EOF_RETURN 130/* return end of input + * value */ +# define BIO_C_SET_BIND_MODE 131 +# define BIO_C_GET_BIND_MODE 132 +# define BIO_C_FILE_TELL 133 +# define BIO_C_GET_SOCKS 134 +# define BIO_C_SET_SOCKS 135 + +# define BIO_C_SET_WRITE_BUF_SIZE 136/* for BIO_s_bio */ +# define BIO_C_GET_WRITE_BUF_SIZE 137 +# define BIO_C_MAKE_BIO_PAIR 138 +# define BIO_C_DESTROY_BIO_PAIR 139 +# define BIO_C_GET_WRITE_GUARANTEE 140 +# define BIO_C_GET_READ_REQUEST 141 +# define BIO_C_SHUTDOWN_WR 142 +# define BIO_C_NREAD0 143 +# define BIO_C_NREAD 144 +# define BIO_C_NWRITE0 145 +# define BIO_C_NWRITE 146 +# define BIO_C_RESET_READ_REQUEST 147 +# define BIO_C_SET_MD_CTX 148 + +# define BIO_C_SET_PREFIX 149 +# define BIO_C_GET_PREFIX 150 +# define BIO_C_SET_SUFFIX 151 +# define BIO_C_GET_SUFFIX 152 + +# define BIO_C_SET_EX_ARG 153 +# define BIO_C_GET_EX_ARG 154 + +# define BIO_C_SET_CONNECT_MODE 155 + +# define BIO_set_app_data(s,arg) BIO_set_ex_data(s,0,arg) +# define BIO_get_app_data(s) BIO_get_ex_data(s,0) + +# define BIO_set_nbio(b,n) BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL) + +# ifndef OPENSSL_NO_SOCK +/* IP families we support, for BIO_s_connect() and BIO_s_accept() */ +/* Note: the underlying operating system may not support some of them */ +# define BIO_FAMILY_IPV4 4 +# define BIO_FAMILY_IPV6 6 +# define BIO_FAMILY_IPANY 256 + +/* BIO_s_connect() */ +# define BIO_set_conn_hostname(b,name) BIO_ctrl(b,BIO_C_SET_CONNECT,0, \ + (char *)(name)) +# define BIO_set_conn_port(b,port) BIO_ctrl(b,BIO_C_SET_CONNECT,1, \ + (char *)(port)) +# define BIO_set_conn_address(b,addr) BIO_ctrl(b,BIO_C_SET_CONNECT,2, \ + (char *)(addr)) +# define BIO_set_conn_ip_family(b,f) BIO_int_ctrl(b,BIO_C_SET_CONNECT,3,f) +# define BIO_get_conn_hostname(b) ((const char *)BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,0)) +# define BIO_get_conn_port(b) ((const char *)BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,1)) +# define BIO_get_conn_address(b) ((const BIO_ADDR *)BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,2)) +# define BIO_get_conn_ip_family(b) BIO_ctrl(b,BIO_C_GET_CONNECT,3,NULL) +# define BIO_set_conn_mode(b,n) BIO_ctrl(b,BIO_C_SET_CONNECT_MODE,(n),NULL) + +/* BIO_s_accept() */ +# define BIO_set_accept_name(b,name) BIO_ctrl(b,BIO_C_SET_ACCEPT,0, \ + (char *)(name)) +# define BIO_set_accept_port(b,port) BIO_ctrl(b,BIO_C_SET_ACCEPT,1, \ + (char *)(port)) +# define BIO_get_accept_name(b) ((const char *)BIO_ptr_ctrl(b,BIO_C_GET_ACCEPT,0)) +# define BIO_get_accept_port(b) ((const char *)BIO_ptr_ctrl(b,BIO_C_GET_ACCEPT,1)) +# define BIO_get_peer_name(b) ((const char *)BIO_ptr_ctrl(b,BIO_C_GET_ACCEPT,2)) +# define BIO_get_peer_port(b) ((const char *)BIO_ptr_ctrl(b,BIO_C_GET_ACCEPT,3)) +/* #define BIO_set_nbio(b,n) BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL) */ +# define BIO_set_nbio_accept(b,n) BIO_ctrl(b,BIO_C_SET_ACCEPT,2,(n)?(void *)"a":NULL) +# define BIO_set_accept_bios(b,bio) BIO_ctrl(b,BIO_C_SET_ACCEPT,3, \ + (char *)(bio)) +# define BIO_set_accept_ip_family(b,f) BIO_int_ctrl(b,BIO_C_SET_ACCEPT,4,f) +# define BIO_get_accept_ip_family(b) BIO_ctrl(b,BIO_C_GET_ACCEPT,4,NULL) + +/* Aliases kept for backward compatibility */ +# define BIO_BIND_NORMAL 0 +# define BIO_BIND_REUSEADDR BIO_SOCK_REUSEADDR +# define BIO_BIND_REUSEADDR_IF_UNUSED BIO_SOCK_REUSEADDR +# define BIO_set_bind_mode(b,mode) BIO_ctrl(b,BIO_C_SET_BIND_MODE,mode,NULL) +# define BIO_get_bind_mode(b) BIO_ctrl(b,BIO_C_GET_BIND_MODE,0,NULL) + +/* BIO_s_accept() and BIO_s_connect() */ +# define BIO_do_connect(b) BIO_do_handshake(b) +# define BIO_do_accept(b) BIO_do_handshake(b) +# endif /* OPENSSL_NO_SOCK */ + +# define BIO_do_handshake(b) BIO_ctrl(b,BIO_C_DO_STATE_MACHINE,0,NULL) + +/* BIO_s_datagram(), BIO_s_fd(), BIO_s_socket(), BIO_s_accept() and BIO_s_connect() */ +# define BIO_set_fd(b,fd,c) BIO_int_ctrl(b,BIO_C_SET_FD,c,fd) +# define BIO_get_fd(b,c) BIO_ctrl(b,BIO_C_GET_FD,0,(char *)(c)) + +/* BIO_s_file() */ +# define BIO_set_fp(b,fp,c) BIO_ctrl(b,BIO_C_SET_FILE_PTR,c,(char *)(fp)) +# define BIO_get_fp(b,fpp) BIO_ctrl(b,BIO_C_GET_FILE_PTR,0,(char *)(fpp)) + +/* BIO_s_fd() and BIO_s_file() */ +# define BIO_seek(b,ofs) (int)BIO_ctrl(b,BIO_C_FILE_SEEK,ofs,NULL) +# define BIO_tell(b) (int)BIO_ctrl(b,BIO_C_FILE_TELL,0,NULL) + +/* + * name is cast to lose const, but might be better to route through a + * function so we can do it safely + */ +# ifdef CONST_STRICT +/* + * If you are wondering why this isn't defined, its because CONST_STRICT is + * purely a compile-time kludge to allow const to be checked. + */ +int BIO_read_filename(BIO *b, const char *name); +# else +# define BIO_read_filename(b,name) (int)BIO_ctrl(b,BIO_C_SET_FILENAME, \ + BIO_CLOSE|BIO_FP_READ,(char *)(name)) +# endif +# define BIO_write_filename(b,name) (int)BIO_ctrl(b,BIO_C_SET_FILENAME, \ + BIO_CLOSE|BIO_FP_WRITE,name) +# define BIO_append_filename(b,name) (int)BIO_ctrl(b,BIO_C_SET_FILENAME, \ + BIO_CLOSE|BIO_FP_APPEND,name) +# define BIO_rw_filename(b,name) (int)BIO_ctrl(b,BIO_C_SET_FILENAME, \ + BIO_CLOSE|BIO_FP_READ|BIO_FP_WRITE,name) + +/* + * WARNING WARNING, this ups the reference count on the read bio of the SSL + * structure. This is because the ssl read BIO is now pointed to by the + * next_bio field in the bio. So when you free the BIO, make sure you are + * doing a BIO_free_all() to catch the underlying BIO. + */ +# define BIO_set_ssl(b,ssl,c) BIO_ctrl(b,BIO_C_SET_SSL,c,(char *)(ssl)) +# define BIO_get_ssl(b,sslp) BIO_ctrl(b,BIO_C_GET_SSL,0,(char *)(sslp)) +# define BIO_set_ssl_mode(b,client) BIO_ctrl(b,BIO_C_SSL_MODE,client,NULL) +# define BIO_set_ssl_renegotiate_bytes(b,num) \ + BIO_ctrl(b,BIO_C_SET_SSL_RENEGOTIATE_BYTES,num,NULL) +# define BIO_get_num_renegotiates(b) \ + BIO_ctrl(b,BIO_C_GET_SSL_NUM_RENEGOTIATES,0,NULL) +# define BIO_set_ssl_renegotiate_timeout(b,seconds) \ + BIO_ctrl(b,BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT,seconds,NULL) + +/* defined in evp.h */ +/* #define BIO_set_md(b,md) BIO_ctrl(b,BIO_C_SET_MD,1,(char *)(md)) */ + +# define BIO_get_mem_data(b,pp) BIO_ctrl(b,BIO_CTRL_INFO,0,(char *)(pp)) +# define BIO_set_mem_buf(b,bm,c) BIO_ctrl(b,BIO_C_SET_BUF_MEM,c,(char *)(bm)) +# define BIO_get_mem_ptr(b,pp) BIO_ctrl(b,BIO_C_GET_BUF_MEM_PTR,0, \ + (char *)(pp)) +# define BIO_set_mem_eof_return(b,v) \ + BIO_ctrl(b,BIO_C_SET_BUF_MEM_EOF_RETURN,v,NULL) + +/* For the BIO_f_buffer() type */ +# define BIO_get_buffer_num_lines(b) BIO_ctrl(b,BIO_C_GET_BUFF_NUM_LINES,0,NULL) +# define BIO_set_buffer_size(b,size) BIO_ctrl(b,BIO_C_SET_BUFF_SIZE,size,NULL) +# define BIO_set_read_buffer_size(b,size) BIO_int_ctrl(b,BIO_C_SET_BUFF_SIZE,size,0) +# define BIO_set_write_buffer_size(b,size) BIO_int_ctrl(b,BIO_C_SET_BUFF_SIZE,size,1) +# define BIO_set_buffer_read_data(b,buf,num) BIO_ctrl(b,BIO_C_SET_BUFF_READ_DATA,num,buf) + +/* Don't use the next one unless you know what you are doing :-) */ +# define BIO_dup_state(b,ret) BIO_ctrl(b,BIO_CTRL_DUP,0,(char *)(ret)) + +# define BIO_reset(b) (int)BIO_ctrl(b,BIO_CTRL_RESET,0,NULL) +# define BIO_eof(b) (int)BIO_ctrl(b,BIO_CTRL_EOF,0,NULL) +# define BIO_set_close(b,c) (int)BIO_ctrl(b,BIO_CTRL_SET_CLOSE,(c),NULL) +# define BIO_get_close(b) (int)BIO_ctrl(b,BIO_CTRL_GET_CLOSE,0,NULL) +# define BIO_pending(b) (int)BIO_ctrl(b,BIO_CTRL_PENDING,0,NULL) +# define BIO_wpending(b) (int)BIO_ctrl(b,BIO_CTRL_WPENDING,0,NULL) +/* ...pending macros have inappropriate return type */ +size_t BIO_ctrl_pending(BIO *b); +size_t BIO_ctrl_wpending(BIO *b); +# define BIO_flush(b) (int)BIO_ctrl(b,BIO_CTRL_FLUSH,0,NULL) +# define BIO_get_info_callback(b,cbp) (int)BIO_ctrl(b,BIO_CTRL_GET_CALLBACK,0, \ + cbp) +# define BIO_set_info_callback(b,cb) (int)BIO_callback_ctrl(b,BIO_CTRL_SET_CALLBACK,cb) + +/* For the BIO_f_buffer() type */ +# define BIO_buffer_get_num_lines(b) BIO_ctrl(b,BIO_CTRL_GET,0,NULL) +# define BIO_buffer_peek(b,s,l) BIO_ctrl(b,BIO_CTRL_PEEK,(l),(s)) + +/* For BIO_s_bio() */ +# define BIO_set_write_buf_size(b,size) (int)BIO_ctrl(b,BIO_C_SET_WRITE_BUF_SIZE,size,NULL) +# define BIO_get_write_buf_size(b,size) (size_t)BIO_ctrl(b,BIO_C_GET_WRITE_BUF_SIZE,size,NULL) +# define BIO_make_bio_pair(b1,b2) (int)BIO_ctrl(b1,BIO_C_MAKE_BIO_PAIR,0,b2) +# define BIO_destroy_bio_pair(b) (int)BIO_ctrl(b,BIO_C_DESTROY_BIO_PAIR,0,NULL) +# define BIO_shutdown_wr(b) (int)BIO_ctrl(b, BIO_C_SHUTDOWN_WR, 0, NULL) +/* macros with inappropriate type -- but ...pending macros use int too: */ +# define BIO_get_write_guarantee(b) (int)BIO_ctrl(b,BIO_C_GET_WRITE_GUARANTEE,0,NULL) +# define BIO_get_read_request(b) (int)BIO_ctrl(b,BIO_C_GET_READ_REQUEST,0,NULL) +size_t BIO_ctrl_get_write_guarantee(BIO *b); +size_t BIO_ctrl_get_read_request(BIO *b); +int BIO_ctrl_reset_read_request(BIO *b); + +/* ctrl macros for dgram */ +# define BIO_ctrl_dgram_connect(b,peer) \ + (int)BIO_ctrl(b,BIO_CTRL_DGRAM_CONNECT,0, (char *)(peer)) +# define BIO_ctrl_set_connected(b,peer) \ + (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SET_CONNECTED, 0, (char *)(peer)) +# define BIO_dgram_recv_timedout(b) \ + (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP, 0, NULL) +# define BIO_dgram_send_timedout(b) \ + (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP, 0, NULL) +# define BIO_dgram_get_peer(b,peer) \ + (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_PEER, 0, (char *)(peer)) +# define BIO_dgram_set_peer(b,peer) \ + (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, (char *)(peer)) +# define BIO_dgram_get_mtu_overhead(b) \ + (unsigned int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_MTU_OVERHEAD, 0, NULL) + +#define BIO_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, l, p, newf, dupf, freef) +int BIO_set_ex_data(BIO *bio, int idx, void *data); +void *BIO_get_ex_data(BIO *bio, int idx); +uint64_t BIO_number_read(BIO *bio); +uint64_t BIO_number_written(BIO *bio); + +/* For BIO_f_asn1() */ +int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix, + asn1_ps_func *prefix_free); +int BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix, + asn1_ps_func **pprefix_free); +int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix, + asn1_ps_func *suffix_free); +int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix, + asn1_ps_func **psuffix_free); + +const BIO_METHOD *BIO_s_file(void); +BIO *BIO_new_file(const char *filename, const char *mode); +# ifndef OPENSSL_NO_STDIO +BIO *BIO_new_fp(FILE *stream, int close_flag); +# endif +BIO *BIO_new(const BIO_METHOD *type); +int BIO_free(BIO *a); +void BIO_set_data(BIO *a, void *ptr); +void *BIO_get_data(BIO *a); +void BIO_set_init(BIO *a, int init); +int BIO_get_init(BIO *a); +void BIO_set_shutdown(BIO *a, int shut); +int BIO_get_shutdown(BIO *a); +void BIO_vfree(BIO *a); +int BIO_up_ref(BIO *a); +int BIO_read(BIO *b, void *data, int dlen); +int BIO_read_ex(BIO *b, void *data, size_t dlen, size_t *readbytes); +int BIO_gets(BIO *bp, char *buf, int size); +int BIO_write(BIO *b, const void *data, int dlen); +int BIO_write_ex(BIO *b, const void *data, size_t dlen, size_t *written); +int BIO_puts(BIO *bp, const char *buf); +int BIO_indent(BIO *b, int indent, int max); +long BIO_ctrl(BIO *bp, int cmd, long larg, void *parg); +long BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp); +void *BIO_ptr_ctrl(BIO *bp, int cmd, long larg); +long BIO_int_ctrl(BIO *bp, int cmd, long larg, int iarg); +BIO *BIO_push(BIO *b, BIO *append); +BIO *BIO_pop(BIO *b); +void BIO_free_all(BIO *a); +BIO *BIO_find_type(BIO *b, int bio_type); +BIO *BIO_next(BIO *b); +void BIO_set_next(BIO *b, BIO *next); +BIO *BIO_get_retry_BIO(BIO *bio, int *reason); +int BIO_get_retry_reason(BIO *bio); +void BIO_set_retry_reason(BIO *bio, int reason); +BIO *BIO_dup_chain(BIO *in); + +int BIO_nread0(BIO *bio, char **buf); +int BIO_nread(BIO *bio, char **buf, int num); +int BIO_nwrite0(BIO *bio, char **buf); +int BIO_nwrite(BIO *bio, char **buf, int num); + +long BIO_debug_callback(BIO *bio, int cmd, const char *argp, int argi, + long argl, long ret); + +const BIO_METHOD *BIO_s_mem(void); +const BIO_METHOD *BIO_s_secmem(void); +BIO *BIO_new_mem_buf(const void *buf, int len); +# ifndef OPENSSL_NO_SOCK +const BIO_METHOD *BIO_s_socket(void); +const BIO_METHOD *BIO_s_connect(void); +const BIO_METHOD *BIO_s_accept(void); +# endif +const BIO_METHOD *BIO_s_fd(void); +const BIO_METHOD *BIO_s_log(void); +const BIO_METHOD *BIO_s_bio(void); +const BIO_METHOD *BIO_s_null(void); +const BIO_METHOD *BIO_f_null(void); +const BIO_METHOD *BIO_f_buffer(void); +const BIO_METHOD *BIO_f_linebuffer(void); +const BIO_METHOD *BIO_f_nbio_test(void); +# ifndef OPENSSL_NO_DGRAM +const BIO_METHOD *BIO_s_datagram(void); +int BIO_dgram_non_fatal_error(int error); +BIO *BIO_new_dgram(int fd, int close_flag); +# ifndef OPENSSL_NO_SCTP +const BIO_METHOD *BIO_s_datagram_sctp(void); +BIO *BIO_new_dgram_sctp(int fd, int close_flag); +int BIO_dgram_is_sctp(BIO *bio); +int BIO_dgram_sctp_notification_cb(BIO *b, + void (*handle_notifications) (BIO *bio, + void *context, + void *buf), + void *context); +int BIO_dgram_sctp_wait_for_dry(BIO *b); +int BIO_dgram_sctp_msg_waiting(BIO *b); +# endif +# endif + +# ifndef OPENSSL_NO_SOCK +int BIO_sock_should_retry(int i); +int BIO_sock_non_fatal_error(int error); +# endif + +int BIO_fd_should_retry(int i); +int BIO_fd_non_fatal_error(int error); +int BIO_dump_cb(int (*cb) (const void *data, size_t len, void *u), + void *u, const char *s, int len); +int BIO_dump_indent_cb(int (*cb) (const void *data, size_t len, void *u), + void *u, const char *s, int len, int indent); +int BIO_dump(BIO *b, const char *bytes, int len); +int BIO_dump_indent(BIO *b, const char *bytes, int len, int indent); +# ifndef OPENSSL_NO_STDIO +int BIO_dump_fp(FILE *fp, const char *s, int len); +int BIO_dump_indent_fp(FILE *fp, const char *s, int len, int indent); +# endif +int BIO_hex_string(BIO *out, int indent, int width, unsigned char *data, + int datalen); + +# ifndef OPENSSL_NO_SOCK +BIO_ADDR *BIO_ADDR_new(void); +int BIO_ADDR_rawmake(BIO_ADDR *ap, int family, + const void *where, size_t wherelen, unsigned short port); +void BIO_ADDR_free(BIO_ADDR *); +void BIO_ADDR_clear(BIO_ADDR *ap); +int BIO_ADDR_family(const BIO_ADDR *ap); +int BIO_ADDR_rawaddress(const BIO_ADDR *ap, void *p, size_t *l); +unsigned short BIO_ADDR_rawport(const BIO_ADDR *ap); +char *BIO_ADDR_hostname_string(const BIO_ADDR *ap, int numeric); +char *BIO_ADDR_service_string(const BIO_ADDR *ap, int numeric); +char *BIO_ADDR_path_string(const BIO_ADDR *ap); + +const BIO_ADDRINFO *BIO_ADDRINFO_next(const BIO_ADDRINFO *bai); +int BIO_ADDRINFO_family(const BIO_ADDRINFO *bai); +int BIO_ADDRINFO_socktype(const BIO_ADDRINFO *bai); +int BIO_ADDRINFO_protocol(const BIO_ADDRINFO *bai); +const BIO_ADDR *BIO_ADDRINFO_address(const BIO_ADDRINFO *bai); +void BIO_ADDRINFO_free(BIO_ADDRINFO *bai); + +enum BIO_hostserv_priorities { + BIO_PARSE_PRIO_HOST, BIO_PARSE_PRIO_SERV +}; +int BIO_parse_hostserv(const char *hostserv, char **host, char **service, + enum BIO_hostserv_priorities hostserv_prio); +enum BIO_lookup_type { + BIO_LOOKUP_CLIENT, BIO_LOOKUP_SERVER +}; +int BIO_lookup(const char *host, const char *service, + enum BIO_lookup_type lookup_type, + int family, int socktype, BIO_ADDRINFO **res); +int BIO_lookup_ex(const char *host, const char *service, + int lookup_type, int family, int socktype, int protocol, + BIO_ADDRINFO **res); +int BIO_sock_error(int sock); +int BIO_socket_ioctl(int fd, long type, void *arg); +int BIO_socket_nbio(int fd, int mode); +int BIO_sock_init(void); +# if OPENSSL_API_COMPAT < 0x10100000L +# define BIO_sock_cleanup() while(0) continue +# endif +int BIO_set_tcp_ndelay(int sock, int turn_on); + +DEPRECATEDIN_1_1_0(struct hostent *BIO_gethostbyname(const char *name)) +DEPRECATEDIN_1_1_0(int BIO_get_port(const char *str, unsigned short *port_ptr)) +DEPRECATEDIN_1_1_0(int BIO_get_host_ip(const char *str, unsigned char *ip)) +DEPRECATEDIN_1_1_0(int BIO_get_accept_socket(char *host_port, int mode)) +DEPRECATEDIN_1_1_0(int BIO_accept(int sock, char **ip_port)) + +union BIO_sock_info_u { + BIO_ADDR *addr; +}; +enum BIO_sock_info_type { + BIO_SOCK_INFO_ADDRESS +}; +int BIO_sock_info(int sock, + enum BIO_sock_info_type type, union BIO_sock_info_u *info); + +# define BIO_SOCK_REUSEADDR 0x01 +# define BIO_SOCK_V6_ONLY 0x02 +# define BIO_SOCK_KEEPALIVE 0x04 +# define BIO_SOCK_NONBLOCK 0x08 +# define BIO_SOCK_NODELAY 0x10 + +int BIO_socket(int domain, int socktype, int protocol, int options); +int BIO_connect(int sock, const BIO_ADDR *addr, int options); +int BIO_bind(int sock, const BIO_ADDR *addr, int options); +int BIO_listen(int sock, const BIO_ADDR *addr, int options); +int BIO_accept_ex(int accept_sock, BIO_ADDR *addr, int options); +int BIO_closesocket(int sock); + +BIO *BIO_new_socket(int sock, int close_flag); +BIO *BIO_new_connect(const char *host_port); +BIO *BIO_new_accept(const char *host_port); +# endif /* OPENSSL_NO_SOCK*/ + +BIO *BIO_new_fd(int fd, int close_flag); + +int BIO_new_bio_pair(BIO **bio1, size_t writebuf1, + BIO **bio2, size_t writebuf2); +/* + * If successful, returns 1 and in *bio1, *bio2 two BIO pair endpoints. + * Otherwise returns 0 and sets *bio1 and *bio2 to NULL. Size 0 uses default + * value. + */ + +void BIO_copy_next_retry(BIO *b); + +/* + * long BIO_ghbn_ctrl(int cmd,int iarg,char *parg); + */ + +# define ossl_bio__attr__(x) +# if defined(__GNUC__) && defined(__STDC_VERSION__) \ + && !defined(__APPLE__) + /* + * Because we support the 'z' modifier, which made its appearance in C99, + * we can't use __attribute__ with pre C99 dialects. + */ +# if __STDC_VERSION__ >= 199901L +# undef ossl_bio__attr__ +# define ossl_bio__attr__ __attribute__ +# if __GNUC__*10 + __GNUC_MINOR__ >= 44 +# define ossl_bio__printf__ __gnu_printf__ +# else +# define ossl_bio__printf__ __printf__ +# endif +# endif +# endif +int BIO_printf(BIO *bio, const char *format, ...) +ossl_bio__attr__((__format__(ossl_bio__printf__, 2, 3))); +int BIO_vprintf(BIO *bio, const char *format, va_list args) +ossl_bio__attr__((__format__(ossl_bio__printf__, 2, 0))); +int BIO_snprintf(char *buf, size_t n, const char *format, ...) +ossl_bio__attr__((__format__(ossl_bio__printf__, 3, 4))); +int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) +ossl_bio__attr__((__format__(ossl_bio__printf__, 3, 0))); +# undef ossl_bio__attr__ +# undef ossl_bio__printf__ + + +BIO_METHOD *BIO_meth_new(int type, const char *name); +void BIO_meth_free(BIO_METHOD *biom); +int (*BIO_meth_get_write(const BIO_METHOD *biom)) (BIO *, const char *, int); +int (*BIO_meth_get_write_ex(const BIO_METHOD *biom)) (BIO *, const char *, size_t, + size_t *); +int BIO_meth_set_write(BIO_METHOD *biom, + int (*write) (BIO *, const char *, int)); +int BIO_meth_set_write_ex(BIO_METHOD *biom, + int (*bwrite) (BIO *, const char *, size_t, size_t *)); +int (*BIO_meth_get_read(const BIO_METHOD *biom)) (BIO *, char *, int); +int (*BIO_meth_get_read_ex(const BIO_METHOD *biom)) (BIO *, char *, size_t, size_t *); +int BIO_meth_set_read(BIO_METHOD *biom, + int (*read) (BIO *, char *, int)); +int BIO_meth_set_read_ex(BIO_METHOD *biom, + int (*bread) (BIO *, char *, size_t, size_t *)); +int (*BIO_meth_get_puts(const BIO_METHOD *biom)) (BIO *, const char *); +int BIO_meth_set_puts(BIO_METHOD *biom, + int (*puts) (BIO *, const char *)); +int (*BIO_meth_get_gets(const BIO_METHOD *biom)) (BIO *, char *, int); +int BIO_meth_set_gets(BIO_METHOD *biom, + int (*gets) (BIO *, char *, int)); +long (*BIO_meth_get_ctrl(const BIO_METHOD *biom)) (BIO *, int, long, void *); +int BIO_meth_set_ctrl(BIO_METHOD *biom, + long (*ctrl) (BIO *, int, long, void *)); +int (*BIO_meth_get_create(const BIO_METHOD *bion)) (BIO *); +int BIO_meth_set_create(BIO_METHOD *biom, int (*create) (BIO *)); +int (*BIO_meth_get_destroy(const BIO_METHOD *biom)) (BIO *); +int BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy) (BIO *)); +long (*BIO_meth_get_callback_ctrl(const BIO_METHOD *biom)) + (BIO *, int, BIO_info_cb *); +int BIO_meth_set_callback_ctrl(BIO_METHOD *biom, + long (*callback_ctrl) (BIO *, int, + BIO_info_cb *)); + +# ifdef __cplusplus +} +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/bioerr.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/bioerr.h new file mode 100644 index 000000000..f119a59c3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/bioerr.h @@ -0,0 +1,120 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_BIOERR_H +# define HEADER_BIOERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_BIO_strings(void); + +/* + * BIO function codes. + */ +# define BIO_F_ACPT_STATE 100 +# define BIO_F_ADDRINFO_WRAP 148 +# define BIO_F_ADDR_STRINGS 134 +# define BIO_F_BIO_ACCEPT 101 +# define BIO_F_BIO_ACCEPT_EX 137 +# define BIO_F_BIO_ACCEPT_NEW 152 +# define BIO_F_BIO_ADDR_NEW 144 +# define BIO_F_BIO_BIND 147 +# define BIO_F_BIO_CALLBACK_CTRL 131 +# define BIO_F_BIO_CONNECT 138 +# define BIO_F_BIO_CONNECT_NEW 153 +# define BIO_F_BIO_CTRL 103 +# define BIO_F_BIO_GETS 104 +# define BIO_F_BIO_GET_HOST_IP 106 +# define BIO_F_BIO_GET_NEW_INDEX 102 +# define BIO_F_BIO_GET_PORT 107 +# define BIO_F_BIO_LISTEN 139 +# define BIO_F_BIO_LOOKUP 135 +# define BIO_F_BIO_LOOKUP_EX 143 +# define BIO_F_BIO_MAKE_PAIR 121 +# define BIO_F_BIO_METH_NEW 146 +# define BIO_F_BIO_NEW 108 +# define BIO_F_BIO_NEW_DGRAM_SCTP 145 +# define BIO_F_BIO_NEW_FILE 109 +# define BIO_F_BIO_NEW_MEM_BUF 126 +# define BIO_F_BIO_NREAD 123 +# define BIO_F_BIO_NREAD0 124 +# define BIO_F_BIO_NWRITE 125 +# define BIO_F_BIO_NWRITE0 122 +# define BIO_F_BIO_PARSE_HOSTSERV 136 +# define BIO_F_BIO_PUTS 110 +# define BIO_F_BIO_READ 111 +# define BIO_F_BIO_READ_EX 105 +# define BIO_F_BIO_READ_INTERN 120 +# define BIO_F_BIO_SOCKET 140 +# define BIO_F_BIO_SOCKET_NBIO 142 +# define BIO_F_BIO_SOCK_INFO 141 +# define BIO_F_BIO_SOCK_INIT 112 +# define BIO_F_BIO_WRITE 113 +# define BIO_F_BIO_WRITE_EX 119 +# define BIO_F_BIO_WRITE_INTERN 128 +# define BIO_F_BUFFER_CTRL 114 +# define BIO_F_CONN_CTRL 127 +# define BIO_F_CONN_STATE 115 +# define BIO_F_DGRAM_SCTP_NEW 149 +# define BIO_F_DGRAM_SCTP_READ 132 +# define BIO_F_DGRAM_SCTP_WRITE 133 +# define BIO_F_DOAPR_OUTCH 150 +# define BIO_F_FILE_CTRL 116 +# define BIO_F_FILE_READ 130 +# define BIO_F_LINEBUFFER_CTRL 129 +# define BIO_F_LINEBUFFER_NEW 151 +# define BIO_F_MEM_WRITE 117 +# define BIO_F_NBIOF_NEW 154 +# define BIO_F_SLG_WRITE 155 +# define BIO_F_SSL_NEW 118 + +/* + * BIO reason codes. + */ +# define BIO_R_ACCEPT_ERROR 100 +# define BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET 141 +# define BIO_R_AMBIGUOUS_HOST_OR_SERVICE 129 +# define BIO_R_BAD_FOPEN_MODE 101 +# define BIO_R_BROKEN_PIPE 124 +# define BIO_R_CONNECT_ERROR 103 +# define BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET 107 +# define BIO_R_GETSOCKNAME_ERROR 132 +# define BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS 133 +# define BIO_R_GETTING_SOCKTYPE 134 +# define BIO_R_INVALID_ARGUMENT 125 +# define BIO_R_INVALID_SOCKET 135 +# define BIO_R_IN_USE 123 +# define BIO_R_LENGTH_TOO_LONG 102 +# define BIO_R_LISTEN_V6_ONLY 136 +# define BIO_R_LOOKUP_RETURNED_NOTHING 142 +# define BIO_R_MALFORMED_HOST_OR_SERVICE 130 +# define BIO_R_NBIO_CONNECT_ERROR 110 +# define BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED 143 +# define BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED 144 +# define BIO_R_NO_PORT_DEFINED 113 +# define BIO_R_NO_SUCH_FILE 128 +# define BIO_R_NULL_PARAMETER 115 +# define BIO_R_UNABLE_TO_BIND_SOCKET 117 +# define BIO_R_UNABLE_TO_CREATE_SOCKET 118 +# define BIO_R_UNABLE_TO_KEEPALIVE 137 +# define BIO_R_UNABLE_TO_LISTEN_SOCKET 119 +# define BIO_R_UNABLE_TO_NODELAY 138 +# define BIO_R_UNABLE_TO_REUSEADDR 139 +# define BIO_R_UNAVAILABLE_IP_FAMILY 145 +# define BIO_R_UNINITIALIZED 120 +# define BIO_R_UNKNOWN_INFO_TYPE 140 +# define BIO_R_UNSUPPORTED_IP_FAMILY 146 +# define BIO_R_UNSUPPORTED_METHOD 121 +# define BIO_R_UNSUPPORTED_PROTOCOL_FAMILY 131 +# define BIO_R_WRITE_TO_READ_ONLY_BIO 126 +# define BIO_R_WSASTARTUP 122 + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/blowfish.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/blowfish.h new file mode 100644 index 000000000..cd3e460e9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/blowfish.h @@ -0,0 +1,61 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_BLOWFISH_H +# define HEADER_BLOWFISH_H + +# include + +# ifndef OPENSSL_NO_BF +# include +# ifdef __cplusplus +extern "C" { +# endif + +# define BF_ENCRYPT 1 +# define BF_DECRYPT 0 + +/*- + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * ! BF_LONG has to be at least 32 bits wide. ! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + */ +# define BF_LONG unsigned int + +# define BF_ROUNDS 16 +# define BF_BLOCK 8 + +typedef struct bf_key_st { + BF_LONG P[BF_ROUNDS + 2]; + BF_LONG S[4 * 256]; +} BF_KEY; + +void BF_set_key(BF_KEY *key, int len, const unsigned char *data); + +void BF_encrypt(BF_LONG *data, const BF_KEY *key); +void BF_decrypt(BF_LONG *data, const BF_KEY *key); + +void BF_ecb_encrypt(const unsigned char *in, unsigned char *out, + const BF_KEY *key, int enc); +void BF_cbc_encrypt(const unsigned char *in, unsigned char *out, long length, + const BF_KEY *schedule, unsigned char *ivec, int enc); +void BF_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, const BF_KEY *schedule, + unsigned char *ivec, int *num, int enc); +void BF_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, const BF_KEY *schedule, + unsigned char *ivec, int *num); +const char *BF_options(void); + +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/bn.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/bn.h new file mode 100644 index 000000000..8af05d00e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/bn.h @@ -0,0 +1,539 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_BN_H +# define HEADER_BN_H + +# include +# ifndef OPENSSL_NO_STDIO +# include +# endif +# include +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * 64-bit processor with LP64 ABI + */ +# ifdef SIXTY_FOUR_BIT_LONG +# define BN_ULONG unsigned long +# define BN_BYTES 8 +# endif + +/* + * 64-bit processor other than LP64 ABI + */ +# ifdef SIXTY_FOUR_BIT +# define BN_ULONG unsigned long long +# define BN_BYTES 8 +# endif + +# ifdef THIRTY_TWO_BIT +# define BN_ULONG unsigned int +# define BN_BYTES 4 +# endif + +# define BN_BITS2 (BN_BYTES * 8) +# define BN_BITS (BN_BITS2 * 2) +# define BN_TBIT ((BN_ULONG)1 << (BN_BITS2 - 1)) + +# define BN_FLG_MALLOCED 0x01 +# define BN_FLG_STATIC_DATA 0x02 + +/* + * avoid leaking exponent information through timing, + * BN_mod_exp_mont() will call BN_mod_exp_mont_consttime, + * BN_div() will call BN_div_no_branch, + * BN_mod_inverse() will call BN_mod_inverse_no_branch. + */ +# define BN_FLG_CONSTTIME 0x04 +# define BN_FLG_SECURE 0x08 + +# if OPENSSL_API_COMPAT < 0x00908000L +/* deprecated name for the flag */ +# define BN_FLG_EXP_CONSTTIME BN_FLG_CONSTTIME +# define BN_FLG_FREE 0x8000 /* used for debugging */ +# endif + +void BN_set_flags(BIGNUM *b, int n); +int BN_get_flags(const BIGNUM *b, int n); + +/* Values for |top| in BN_rand() */ +#define BN_RAND_TOP_ANY -1 +#define BN_RAND_TOP_ONE 0 +#define BN_RAND_TOP_TWO 1 + +/* Values for |bottom| in BN_rand() */ +#define BN_RAND_BOTTOM_ANY 0 +#define BN_RAND_BOTTOM_ODD 1 + +/* + * get a clone of a BIGNUM with changed flags, for *temporary* use only (the + * two BIGNUMs cannot be used in parallel!). Also only for *read only* use. The + * value |dest| should be a newly allocated BIGNUM obtained via BN_new() that + * has not been otherwise initialised or used. + */ +void BN_with_flags(BIGNUM *dest, const BIGNUM *b, int flags); + +/* Wrapper function to make using BN_GENCB easier */ +int BN_GENCB_call(BN_GENCB *cb, int a, int b); + +BN_GENCB *BN_GENCB_new(void); +void BN_GENCB_free(BN_GENCB *cb); + +/* Populate a BN_GENCB structure with an "old"-style callback */ +void BN_GENCB_set_old(BN_GENCB *gencb, void (*callback) (int, int, void *), + void *cb_arg); + +/* Populate a BN_GENCB structure with a "new"-style callback */ +void BN_GENCB_set(BN_GENCB *gencb, int (*callback) (int, int, BN_GENCB *), + void *cb_arg); + +void *BN_GENCB_get_arg(BN_GENCB *cb); + +# define BN_prime_checks 0 /* default: select number of iterations based + * on the size of the number */ + +/* + * BN_prime_checks_for_size() returns the number of Miller-Rabin iterations + * that will be done for checking that a random number is probably prime. The + * error rate for accepting a composite number as prime depends on the size of + * the prime |b|. The error rates used are for calculating an RSA key with 2 primes, + * and so the level is what you would expect for a key of double the size of the + * prime. + * + * This table is generated using the algorithm of FIPS PUB 186-4 + * Digital Signature Standard (DSS), section F.1, page 117. + * (https://dx.doi.org/10.6028/NIST.FIPS.186-4) + * + * The following magma script was used to generate the output: + * securitybits:=125; + * k:=1024; + * for t:=1 to 65 do + * for M:=3 to Floor(2*Sqrt(k-1)-1) do + * S:=0; + * // Sum over m + * for m:=3 to M do + * s:=0; + * // Sum over j + * for j:=2 to m do + * s+:=(RealField(32)!2)^-(j+(k-1)/j); + * end for; + * S+:=2^(m-(m-1)*t)*s; + * end for; + * A:=2^(k-2-M*t); + * B:=8*(Pi(RealField(32))^2-6)/3*2^(k-2)*S; + * pkt:=2.00743*Log(2)*k*2^-k*(A+B); + * seclevel:=Floor(-Log(2,pkt)); + * if seclevel ge securitybits then + * printf "k: %5o, security: %o bits (t: %o, M: %o)\n",k,seclevel,t,M; + * break; + * end if; + * end for; + * if seclevel ge securitybits then break; end if; + * end for; + * + * It can be run online at: + * http://magma.maths.usyd.edu.au/calc + * + * And will output: + * k: 1024, security: 129 bits (t: 6, M: 23) + * + * k is the number of bits of the prime, securitybits is the level we want to + * reach. + * + * prime length | RSA key size | # MR tests | security level + * -------------+--------------|------------+--------------- + * (b) >= 6394 | >= 12788 | 3 | 256 bit + * (b) >= 3747 | >= 7494 | 3 | 192 bit + * (b) >= 1345 | >= 2690 | 4 | 128 bit + * (b) >= 1080 | >= 2160 | 5 | 128 bit + * (b) >= 852 | >= 1704 | 5 | 112 bit + * (b) >= 476 | >= 952 | 5 | 80 bit + * (b) >= 400 | >= 800 | 6 | 80 bit + * (b) >= 347 | >= 694 | 7 | 80 bit + * (b) >= 308 | >= 616 | 8 | 80 bit + * (b) >= 55 | >= 110 | 27 | 64 bit + * (b) >= 6 | >= 12 | 34 | 64 bit + */ + +# define BN_prime_checks_for_size(b) ((b) >= 3747 ? 3 : \ + (b) >= 1345 ? 4 : \ + (b) >= 476 ? 5 : \ + (b) >= 400 ? 6 : \ + (b) >= 347 ? 7 : \ + (b) >= 308 ? 8 : \ + (b) >= 55 ? 27 : \ + /* b >= 6 */ 34) + +# define BN_num_bytes(a) ((BN_num_bits(a)+7)/8) + +int BN_abs_is_word(const BIGNUM *a, const BN_ULONG w); +int BN_is_zero(const BIGNUM *a); +int BN_is_one(const BIGNUM *a); +int BN_is_word(const BIGNUM *a, const BN_ULONG w); +int BN_is_odd(const BIGNUM *a); + +# define BN_one(a) (BN_set_word((a),1)) + +void BN_zero_ex(BIGNUM *a); + +# if OPENSSL_API_COMPAT >= 0x00908000L +# define BN_zero(a) BN_zero_ex(a) +# else +# define BN_zero(a) (BN_set_word((a),0)) +# endif + +const BIGNUM *BN_value_one(void); +char *BN_options(void); +BN_CTX *BN_CTX_new(void); +BN_CTX *BN_CTX_secure_new(void); +void BN_CTX_free(BN_CTX *c); +void BN_CTX_start(BN_CTX *ctx); +BIGNUM *BN_CTX_get(BN_CTX *ctx); +void BN_CTX_end(BN_CTX *ctx); +int BN_rand(BIGNUM *rnd, int bits, int top, int bottom); +int BN_priv_rand(BIGNUM *rnd, int bits, int top, int bottom); +int BN_rand_range(BIGNUM *rnd, const BIGNUM *range); +int BN_priv_rand_range(BIGNUM *rnd, const BIGNUM *range); +int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom); +int BN_pseudo_rand_range(BIGNUM *rnd, const BIGNUM *range); +int BN_num_bits(const BIGNUM *a); +int BN_num_bits_word(BN_ULONG l); +int BN_security_bits(int L, int N); +BIGNUM *BN_new(void); +BIGNUM *BN_secure_new(void); +void BN_clear_free(BIGNUM *a); +BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b); +void BN_swap(BIGNUM *a, BIGNUM *b); +BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret); +int BN_bn2bin(const BIGNUM *a, unsigned char *to); +int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen); +BIGNUM *BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret); +int BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen); +BIGNUM *BN_mpi2bn(const unsigned char *s, int len, BIGNUM *ret); +int BN_bn2mpi(const BIGNUM *a, unsigned char *to); +int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); +int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); +int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); +int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); +int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); +int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx); +/** BN_set_negative sets sign of a BIGNUM + * \param b pointer to the BIGNUM object + * \param n 0 if the BIGNUM b should be positive and a value != 0 otherwise + */ +void BN_set_negative(BIGNUM *b, int n); +/** BN_is_negative returns 1 if the BIGNUM is negative + * \param b pointer to the BIGNUM object + * \return 1 if a < 0 and 0 otherwise + */ +int BN_is_negative(const BIGNUM *b); + +int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, + BN_CTX *ctx); +# define BN_mod(rem,m,d,ctx) BN_div(NULL,(rem),(m),(d),(ctx)) +int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx); +int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, + BN_CTX *ctx); +int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m); +int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, + BN_CTX *ctx); +int BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m); +int BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, + BN_CTX *ctx); +int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx); +int BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx); +int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m); +int BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m, + BN_CTX *ctx); +int BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m); + +BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w); +BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w); +int BN_mul_word(BIGNUM *a, BN_ULONG w); +int BN_add_word(BIGNUM *a, BN_ULONG w); +int BN_sub_word(BIGNUM *a, BN_ULONG w); +int BN_set_word(BIGNUM *a, BN_ULONG w); +BN_ULONG BN_get_word(const BIGNUM *a); + +int BN_cmp(const BIGNUM *a, const BIGNUM *b); +void BN_free(BIGNUM *a); +int BN_is_bit_set(const BIGNUM *a, int n); +int BN_lshift(BIGNUM *r, const BIGNUM *a, int n); +int BN_lshift1(BIGNUM *r, const BIGNUM *a); +int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx); + +int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx); +int BN_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); +int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *in_mont); +int BN_mod_exp_mont_word(BIGNUM *r, BN_ULONG a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); +int BN_mod_exp2_mont(BIGNUM *r, const BIGNUM *a1, const BIGNUM *p1, + const BIGNUM *a2, const BIGNUM *p2, const BIGNUM *m, + BN_CTX *ctx, BN_MONT_CTX *m_ctx); +int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx); + +int BN_mask_bits(BIGNUM *a, int n); +# ifndef OPENSSL_NO_STDIO +int BN_print_fp(FILE *fp, const BIGNUM *a); +# endif +int BN_print(BIO *bio, const BIGNUM *a); +int BN_reciprocal(BIGNUM *r, const BIGNUM *m, int len, BN_CTX *ctx); +int BN_rshift(BIGNUM *r, const BIGNUM *a, int n); +int BN_rshift1(BIGNUM *r, const BIGNUM *a); +void BN_clear(BIGNUM *a); +BIGNUM *BN_dup(const BIGNUM *a); +int BN_ucmp(const BIGNUM *a, const BIGNUM *b); +int BN_set_bit(BIGNUM *a, int n); +int BN_clear_bit(BIGNUM *a, int n); +char *BN_bn2hex(const BIGNUM *a); +char *BN_bn2dec(const BIGNUM *a); +int BN_hex2bn(BIGNUM **a, const char *str); +int BN_dec2bn(BIGNUM **a, const char *str); +int BN_asc2bn(BIGNUM **a, const char *str); +int BN_gcd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); +int BN_kronecker(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); /* returns + * -2 for + * error */ +BIGNUM *BN_mod_inverse(BIGNUM *ret, + const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx); +BIGNUM *BN_mod_sqrt(BIGNUM *ret, + const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx); + +void BN_consttime_swap(BN_ULONG swap, BIGNUM *a, BIGNUM *b, int nwords); + +/* Deprecated versions */ +DEPRECATEDIN_0_9_8(BIGNUM *BN_generate_prime(BIGNUM *ret, int bits, int safe, + const BIGNUM *add, + const BIGNUM *rem, + void (*callback) (int, int, + void *), + void *cb_arg)) +DEPRECATEDIN_0_9_8(int + BN_is_prime(const BIGNUM *p, int nchecks, + void (*callback) (int, int, void *), + BN_CTX *ctx, void *cb_arg)) +DEPRECATEDIN_0_9_8(int + BN_is_prime_fasttest(const BIGNUM *p, int nchecks, + void (*callback) (int, int, void *), + BN_CTX *ctx, void *cb_arg, + int do_trial_division)) + +/* Newer versions */ +int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe, const BIGNUM *add, + const BIGNUM *rem, BN_GENCB *cb); +int BN_is_prime_ex(const BIGNUM *p, int nchecks, BN_CTX *ctx, BN_GENCB *cb); +int BN_is_prime_fasttest_ex(const BIGNUM *p, int nchecks, BN_CTX *ctx, + int do_trial_division, BN_GENCB *cb); + +int BN_X931_generate_Xpq(BIGNUM *Xp, BIGNUM *Xq, int nbits, BN_CTX *ctx); + +int BN_X931_derive_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2, + const BIGNUM *Xp, const BIGNUM *Xp1, + const BIGNUM *Xp2, const BIGNUM *e, BN_CTX *ctx, + BN_GENCB *cb); +int BN_X931_generate_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2, BIGNUM *Xp1, + BIGNUM *Xp2, const BIGNUM *Xp, const BIGNUM *e, + BN_CTX *ctx, BN_GENCB *cb); + +BN_MONT_CTX *BN_MONT_CTX_new(void); +int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + BN_MONT_CTX *mont, BN_CTX *ctx); +int BN_to_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont, + BN_CTX *ctx); +int BN_from_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont, + BN_CTX *ctx); +void BN_MONT_CTX_free(BN_MONT_CTX *mont); +int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx); +BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, BN_MONT_CTX *from); +BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_RWLOCK *lock, + const BIGNUM *mod, BN_CTX *ctx); + +/* BN_BLINDING flags */ +# define BN_BLINDING_NO_UPDATE 0x00000001 +# define BN_BLINDING_NO_RECREATE 0x00000002 + +BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod); +void BN_BLINDING_free(BN_BLINDING *b); +int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx); +int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx); +int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx); +int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *); +int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b, + BN_CTX *); + +int BN_BLINDING_is_current_thread(BN_BLINDING *b); +void BN_BLINDING_set_current_thread(BN_BLINDING *b); +int BN_BLINDING_lock(BN_BLINDING *b); +int BN_BLINDING_unlock(BN_BLINDING *b); + +unsigned long BN_BLINDING_get_flags(const BN_BLINDING *); +void BN_BLINDING_set_flags(BN_BLINDING *, unsigned long); +BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b, + const BIGNUM *e, BIGNUM *m, BN_CTX *ctx, + int (*bn_mod_exp) (BIGNUM *r, + const BIGNUM *a, + const BIGNUM *p, + const BIGNUM *m, + BN_CTX *ctx, + BN_MONT_CTX *m_ctx), + BN_MONT_CTX *m_ctx); + +DEPRECATEDIN_0_9_8(void BN_set_params(int mul, int high, int low, int mont)) +DEPRECATEDIN_0_9_8(int BN_get_params(int which)) /* 0, mul, 1 high, 2 low, 3 + * mont */ + +BN_RECP_CTX *BN_RECP_CTX_new(void); +void BN_RECP_CTX_free(BN_RECP_CTX *recp); +int BN_RECP_CTX_set(BN_RECP_CTX *recp, const BIGNUM *rdiv, BN_CTX *ctx); +int BN_mod_mul_reciprocal(BIGNUM *r, const BIGNUM *x, const BIGNUM *y, + BN_RECP_CTX *recp, BN_CTX *ctx); +int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx); +int BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, + BN_RECP_CTX *recp, BN_CTX *ctx); + +# ifndef OPENSSL_NO_EC2M + +/* + * Functions for arithmetic over binary polynomials represented by BIGNUMs. + * The BIGNUM::neg property of BIGNUMs representing binary polynomials is + * ignored. Note that input arguments are not const so that their bit arrays + * can be expanded to the appropriate size if needed. + */ + +/* + * r = a + b + */ +int BN_GF2m_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); +# define BN_GF2m_sub(r, a, b) BN_GF2m_add(r, a, b) +/* + * r=a mod p + */ +int BN_GF2m_mod(BIGNUM *r, const BIGNUM *a, const BIGNUM *p); +/* r = (a * b) mod p */ +int BN_GF2m_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *p, BN_CTX *ctx); +/* r = (a * a) mod p */ +int BN_GF2m_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx); +/* r = (1 / b) mod p */ +int BN_GF2m_mod_inv(BIGNUM *r, const BIGNUM *b, const BIGNUM *p, BN_CTX *ctx); +/* r = (a / b) mod p */ +int BN_GF2m_mod_div(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *p, BN_CTX *ctx); +/* r = (a ^ b) mod p */ +int BN_GF2m_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *p, BN_CTX *ctx); +/* r = sqrt(a) mod p */ +int BN_GF2m_mod_sqrt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + BN_CTX *ctx); +/* r^2 + r = a mod p */ +int BN_GF2m_mod_solve_quad(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + BN_CTX *ctx); +# define BN_GF2m_cmp(a, b) BN_ucmp((a), (b)) +/*- + * Some functions allow for representation of the irreducible polynomials + * as an unsigned int[], say p. The irreducible f(t) is then of the form: + * t^p[0] + t^p[1] + ... + t^p[k] + * where m = p[0] > p[1] > ... > p[k] = 0. + */ +/* r = a mod p */ +int BN_GF2m_mod_arr(BIGNUM *r, const BIGNUM *a, const int p[]); +/* r = (a * b) mod p */ +int BN_GF2m_mod_mul_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const int p[], BN_CTX *ctx); +/* r = (a * a) mod p */ +int BN_GF2m_mod_sqr_arr(BIGNUM *r, const BIGNUM *a, const int p[], + BN_CTX *ctx); +/* r = (1 / b) mod p */ +int BN_GF2m_mod_inv_arr(BIGNUM *r, const BIGNUM *b, const int p[], + BN_CTX *ctx); +/* r = (a / b) mod p */ +int BN_GF2m_mod_div_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const int p[], BN_CTX *ctx); +/* r = (a ^ b) mod p */ +int BN_GF2m_mod_exp_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const int p[], BN_CTX *ctx); +/* r = sqrt(a) mod p */ +int BN_GF2m_mod_sqrt_arr(BIGNUM *r, const BIGNUM *a, + const int p[], BN_CTX *ctx); +/* r^2 + r = a mod p */ +int BN_GF2m_mod_solve_quad_arr(BIGNUM *r, const BIGNUM *a, + const int p[], BN_CTX *ctx); +int BN_GF2m_poly2arr(const BIGNUM *a, int p[], int max); +int BN_GF2m_arr2poly(const int p[], BIGNUM *a); + +# endif + +/* + * faster mod functions for the 'NIST primes' 0 <= a < p^2 + */ +int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx); +int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx); +int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx); +int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx); +int BN_nist_mod_521(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx); + +const BIGNUM *BN_get0_nist_prime_192(void); +const BIGNUM *BN_get0_nist_prime_224(void); +const BIGNUM *BN_get0_nist_prime_256(void); +const BIGNUM *BN_get0_nist_prime_384(void); +const BIGNUM *BN_get0_nist_prime_521(void); + +int (*BN_nist_mod_func(const BIGNUM *p)) (BIGNUM *r, const BIGNUM *a, + const BIGNUM *field, BN_CTX *ctx); + +int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range, + const BIGNUM *priv, const unsigned char *message, + size_t message_len, BN_CTX *ctx); + +/* Primes from RFC 2409 */ +BIGNUM *BN_get_rfc2409_prime_768(BIGNUM *bn); +BIGNUM *BN_get_rfc2409_prime_1024(BIGNUM *bn); + +/* Primes from RFC 3526 */ +BIGNUM *BN_get_rfc3526_prime_1536(BIGNUM *bn); +BIGNUM *BN_get_rfc3526_prime_2048(BIGNUM *bn); +BIGNUM *BN_get_rfc3526_prime_3072(BIGNUM *bn); +BIGNUM *BN_get_rfc3526_prime_4096(BIGNUM *bn); +BIGNUM *BN_get_rfc3526_prime_6144(BIGNUM *bn); +BIGNUM *BN_get_rfc3526_prime_8192(BIGNUM *bn); + +# if OPENSSL_API_COMPAT < 0x10100000L +# define get_rfc2409_prime_768 BN_get_rfc2409_prime_768 +# define get_rfc2409_prime_1024 BN_get_rfc2409_prime_1024 +# define get_rfc3526_prime_1536 BN_get_rfc3526_prime_1536 +# define get_rfc3526_prime_2048 BN_get_rfc3526_prime_2048 +# define get_rfc3526_prime_3072 BN_get_rfc3526_prime_3072 +# define get_rfc3526_prime_4096 BN_get_rfc3526_prime_4096 +# define get_rfc3526_prime_6144 BN_get_rfc3526_prime_6144 +# define get_rfc3526_prime_8192 BN_get_rfc3526_prime_8192 +# endif + +int BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom); + + +# ifdef __cplusplus +} +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/bnerr.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/bnerr.h new file mode 100644 index 000000000..8a022cc06 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/bnerr.h @@ -0,0 +1,96 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_BNERR_H +# define HEADER_BNERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_BN_strings(void); + +/* + * BN function codes. + */ +# define BN_F_BNRAND 127 +# define BN_F_BNRAND_RANGE 138 +# define BN_F_BN_BLINDING_CONVERT_EX 100 +# define BN_F_BN_BLINDING_CREATE_PARAM 128 +# define BN_F_BN_BLINDING_INVERT_EX 101 +# define BN_F_BN_BLINDING_NEW 102 +# define BN_F_BN_BLINDING_UPDATE 103 +# define BN_F_BN_BN2DEC 104 +# define BN_F_BN_BN2HEX 105 +# define BN_F_BN_COMPUTE_WNAF 142 +# define BN_F_BN_CTX_GET 116 +# define BN_F_BN_CTX_NEW 106 +# define BN_F_BN_CTX_START 129 +# define BN_F_BN_DIV 107 +# define BN_F_BN_DIV_RECP 130 +# define BN_F_BN_EXP 123 +# define BN_F_BN_EXPAND_INTERNAL 120 +# define BN_F_BN_GENCB_NEW 143 +# define BN_F_BN_GENERATE_DSA_NONCE 140 +# define BN_F_BN_GENERATE_PRIME_EX 141 +# define BN_F_BN_GF2M_MOD 131 +# define BN_F_BN_GF2M_MOD_EXP 132 +# define BN_F_BN_GF2M_MOD_MUL 133 +# define BN_F_BN_GF2M_MOD_SOLVE_QUAD 134 +# define BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR 135 +# define BN_F_BN_GF2M_MOD_SQR 136 +# define BN_F_BN_GF2M_MOD_SQRT 137 +# define BN_F_BN_LSHIFT 145 +# define BN_F_BN_MOD_EXP2_MONT 118 +# define BN_F_BN_MOD_EXP_MONT 109 +# define BN_F_BN_MOD_EXP_MONT_CONSTTIME 124 +# define BN_F_BN_MOD_EXP_MONT_WORD 117 +# define BN_F_BN_MOD_EXP_RECP 125 +# define BN_F_BN_MOD_EXP_SIMPLE 126 +# define BN_F_BN_MOD_INVERSE 110 +# define BN_F_BN_MOD_INVERSE_NO_BRANCH 139 +# define BN_F_BN_MOD_LSHIFT_QUICK 119 +# define BN_F_BN_MOD_SQRT 121 +# define BN_F_BN_MONT_CTX_NEW 149 +# define BN_F_BN_MPI2BN 112 +# define BN_F_BN_NEW 113 +# define BN_F_BN_POOL_GET 147 +# define BN_F_BN_RAND 114 +# define BN_F_BN_RAND_RANGE 122 +# define BN_F_BN_RECP_CTX_NEW 150 +# define BN_F_BN_RSHIFT 146 +# define BN_F_BN_SET_WORDS 144 +# define BN_F_BN_STACK_PUSH 148 +# define BN_F_BN_USUB 115 + +/* + * BN reason codes. + */ +# define BN_R_ARG2_LT_ARG3 100 +# define BN_R_BAD_RECIPROCAL 101 +# define BN_R_BIGNUM_TOO_LONG 114 +# define BN_R_BITS_TOO_SMALL 118 +# define BN_R_CALLED_WITH_EVEN_MODULUS 102 +# define BN_R_DIV_BY_ZERO 103 +# define BN_R_ENCODING_ERROR 104 +# define BN_R_EXPAND_ON_STATIC_BIGNUM_DATA 105 +# define BN_R_INPUT_NOT_REDUCED 110 +# define BN_R_INVALID_LENGTH 106 +# define BN_R_INVALID_RANGE 115 +# define BN_R_INVALID_SHIFT 119 +# define BN_R_NOT_A_SQUARE 111 +# define BN_R_NOT_INITIALIZED 107 +# define BN_R_NO_INVERSE 108 +# define BN_R_NO_SOLUTION 116 +# define BN_R_PRIVATE_KEY_TOO_LARGE 117 +# define BN_R_P_IS_NOT_PRIME 112 +# define BN_R_TOO_MANY_ITERATIONS 113 +# define BN_R_TOO_MANY_TEMPORARY_VARIABLES 109 + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/buffer.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/buffer.h new file mode 100644 index 000000000..d2765766b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/buffer.h @@ -0,0 +1,58 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_BUFFER_H +# define HEADER_BUFFER_H + +# include +# ifndef HEADER_CRYPTO_H +# include +# endif +# include + + +#ifdef __cplusplus +extern "C" { +#endif + +# include +# include + +/* + * These names are outdated as of OpenSSL 1.1; a future release + * will move them to be deprecated. + */ +# define BUF_strdup(s) OPENSSL_strdup(s) +# define BUF_strndup(s, size) OPENSSL_strndup(s, size) +# define BUF_memdup(data, size) OPENSSL_memdup(data, size) +# define BUF_strlcpy(dst, src, size) OPENSSL_strlcpy(dst, src, size) +# define BUF_strlcat(dst, src, size) OPENSSL_strlcat(dst, src, size) +# define BUF_strnlen(str, maxlen) OPENSSL_strnlen(str, maxlen) + +struct buf_mem_st { + size_t length; /* current number of bytes */ + char *data; + size_t max; /* size of buffer */ + unsigned long flags; +}; + +# define BUF_MEM_FLAG_SECURE 0x01 + +BUF_MEM *BUF_MEM_new(void); +BUF_MEM *BUF_MEM_new_ex(unsigned long flags); +void BUF_MEM_free(BUF_MEM *a); +size_t BUF_MEM_grow(BUF_MEM *str, size_t len); +size_t BUF_MEM_grow_clean(BUF_MEM *str, size_t len); +void BUF_reverse(unsigned char *out, const unsigned char *in, size_t siz); + + +# ifdef __cplusplus +} +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/buffererr.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/buffererr.h new file mode 100644 index 000000000..3aee13232 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/buffererr.h @@ -0,0 +1,30 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_BUFERR_H +# define HEADER_BUFERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_BUF_strings(void); + +/* + * BUF function codes. + */ +# define BUF_F_BUF_MEM_GROW 100 +# define BUF_F_BUF_MEM_GROW_CLEAN 105 +# define BUF_F_BUF_MEM_NEW 101 + +/* + * BUF reason codes. + */ + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/camellia.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/camellia.h new file mode 100644 index 000000000..151f3c134 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/camellia.h @@ -0,0 +1,83 @@ +/* + * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_CAMELLIA_H +# define HEADER_CAMELLIA_H + +# include + +# ifndef OPENSSL_NO_CAMELLIA +# include +#ifdef __cplusplus +extern "C" { +#endif + +# define CAMELLIA_ENCRYPT 1 +# define CAMELLIA_DECRYPT 0 + +/* + * Because array size can't be a const in C, the following two are macros. + * Both sizes are in bytes. + */ + +/* This should be a hidden type, but EVP requires that the size be known */ + +# define CAMELLIA_BLOCK_SIZE 16 +# define CAMELLIA_TABLE_BYTE_LEN 272 +# define CAMELLIA_TABLE_WORD_LEN (CAMELLIA_TABLE_BYTE_LEN / 4) + +typedef unsigned int KEY_TABLE_TYPE[CAMELLIA_TABLE_WORD_LEN]; /* to match + * with WORD */ + +struct camellia_key_st { + union { + double d; /* ensures 64-bit align */ + KEY_TABLE_TYPE rd_key; + } u; + int grand_rounds; +}; +typedef struct camellia_key_st CAMELLIA_KEY; + +int Camellia_set_key(const unsigned char *userKey, const int bits, + CAMELLIA_KEY *key); + +void Camellia_encrypt(const unsigned char *in, unsigned char *out, + const CAMELLIA_KEY *key); +void Camellia_decrypt(const unsigned char *in, unsigned char *out, + const CAMELLIA_KEY *key); + +void Camellia_ecb_encrypt(const unsigned char *in, unsigned char *out, + const CAMELLIA_KEY *key, const int enc); +void Camellia_cbc_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char *ivec, const int enc); +void Camellia_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char *ivec, int *num, const int enc); +void Camellia_cfb1_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char *ivec, int *num, const int enc); +void Camellia_cfb8_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char *ivec, int *num, const int enc); +void Camellia_ofb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char *ivec, int *num); +void Camellia_ctr128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char ivec[CAMELLIA_BLOCK_SIZE], + unsigned char ecount_buf[CAMELLIA_BLOCK_SIZE], + unsigned int *num); + +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/cast.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/cast.h new file mode 100644 index 000000000..2cc89ae01 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/cast.h @@ -0,0 +1,53 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_CAST_H +# define HEADER_CAST_H + +# include + +# ifndef OPENSSL_NO_CAST +# ifdef __cplusplus +extern "C" { +# endif + +# define CAST_ENCRYPT 1 +# define CAST_DECRYPT 0 + +# define CAST_LONG unsigned int + +# define CAST_BLOCK 8 +# define CAST_KEY_LENGTH 16 + +typedef struct cast_key_st { + CAST_LONG data[32]; + int short_key; /* Use reduced rounds for short key */ +} CAST_KEY; + +void CAST_set_key(CAST_KEY *key, int len, const unsigned char *data); +void CAST_ecb_encrypt(const unsigned char *in, unsigned char *out, + const CAST_KEY *key, int enc); +void CAST_encrypt(CAST_LONG *data, const CAST_KEY *key); +void CAST_decrypt(CAST_LONG *data, const CAST_KEY *key); +void CAST_cbc_encrypt(const unsigned char *in, unsigned char *out, + long length, const CAST_KEY *ks, unsigned char *iv, + int enc); +void CAST_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, const CAST_KEY *schedule, + unsigned char *ivec, int *num, int enc); +void CAST_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, const CAST_KEY *schedule, + unsigned char *ivec, int *num); + +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/cmac.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/cmac.h new file mode 100644 index 000000000..3535a9abf --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/cmac.h @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_CMAC_H +# define HEADER_CMAC_H + +# ifndef OPENSSL_NO_CMAC + +#ifdef __cplusplus +extern "C" { +#endif + +# include + +/* Opaque */ +typedef struct CMAC_CTX_st CMAC_CTX; + +CMAC_CTX *CMAC_CTX_new(void); +void CMAC_CTX_cleanup(CMAC_CTX *ctx); +void CMAC_CTX_free(CMAC_CTX *ctx); +EVP_CIPHER_CTX *CMAC_CTX_get0_cipher_ctx(CMAC_CTX *ctx); +int CMAC_CTX_copy(CMAC_CTX *out, const CMAC_CTX *in); + +int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen, + const EVP_CIPHER *cipher, ENGINE *impl); +int CMAC_Update(CMAC_CTX *ctx, const void *data, size_t dlen); +int CMAC_Final(CMAC_CTX *ctx, unsigned char *out, size_t *poutlen); +int CMAC_resume(CMAC_CTX *ctx); + +#ifdef __cplusplus +} +#endif + +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/cms.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/cms.h new file mode 100644 index 000000000..ddf37e56f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/cms.h @@ -0,0 +1,342 @@ +/* + * Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_CMS_H +# define HEADER_CMS_H + +# include + +# ifndef OPENSSL_NO_CMS +# include +# include +# include +# ifdef __cplusplus +extern "C" { +# endif + +typedef struct CMS_ContentInfo_st CMS_ContentInfo; +typedef struct CMS_SignerInfo_st CMS_SignerInfo; +typedef struct CMS_CertificateChoices CMS_CertificateChoices; +typedef struct CMS_RevocationInfoChoice_st CMS_RevocationInfoChoice; +typedef struct CMS_RecipientInfo_st CMS_RecipientInfo; +typedef struct CMS_ReceiptRequest_st CMS_ReceiptRequest; +typedef struct CMS_Receipt_st CMS_Receipt; +typedef struct CMS_RecipientEncryptedKey_st CMS_RecipientEncryptedKey; +typedef struct CMS_OtherKeyAttribute_st CMS_OtherKeyAttribute; + +DEFINE_STACK_OF(CMS_SignerInfo) +DEFINE_STACK_OF(CMS_RecipientEncryptedKey) +DEFINE_STACK_OF(CMS_RecipientInfo) +DEFINE_STACK_OF(CMS_RevocationInfoChoice) +DECLARE_ASN1_FUNCTIONS(CMS_ContentInfo) +DECLARE_ASN1_FUNCTIONS(CMS_ReceiptRequest) +DECLARE_ASN1_PRINT_FUNCTION(CMS_ContentInfo) + +# define CMS_SIGNERINFO_ISSUER_SERIAL 0 +# define CMS_SIGNERINFO_KEYIDENTIFIER 1 + +# define CMS_RECIPINFO_NONE -1 +# define CMS_RECIPINFO_TRANS 0 +# define CMS_RECIPINFO_AGREE 1 +# define CMS_RECIPINFO_KEK 2 +# define CMS_RECIPINFO_PASS 3 +# define CMS_RECIPINFO_OTHER 4 + +/* S/MIME related flags */ + +# define CMS_TEXT 0x1 +# define CMS_NOCERTS 0x2 +# define CMS_NO_CONTENT_VERIFY 0x4 +# define CMS_NO_ATTR_VERIFY 0x8 +# define CMS_NOSIGS \ + (CMS_NO_CONTENT_VERIFY|CMS_NO_ATTR_VERIFY) +# define CMS_NOINTERN 0x10 +# define CMS_NO_SIGNER_CERT_VERIFY 0x20 +# define CMS_NOVERIFY 0x20 +# define CMS_DETACHED 0x40 +# define CMS_BINARY 0x80 +# define CMS_NOATTR 0x100 +# define CMS_NOSMIMECAP 0x200 +# define CMS_NOOLDMIMETYPE 0x400 +# define CMS_CRLFEOL 0x800 +# define CMS_STREAM 0x1000 +# define CMS_NOCRL 0x2000 +# define CMS_PARTIAL 0x4000 +# define CMS_REUSE_DIGEST 0x8000 +# define CMS_USE_KEYID 0x10000 +# define CMS_DEBUG_DECRYPT 0x20000 +# define CMS_KEY_PARAM 0x40000 +# define CMS_ASCIICRLF 0x80000 + +const ASN1_OBJECT *CMS_get0_type(const CMS_ContentInfo *cms); + +BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont); +int CMS_dataFinal(CMS_ContentInfo *cms, BIO *bio); + +ASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms); +int CMS_is_detached(CMS_ContentInfo *cms); +int CMS_set_detached(CMS_ContentInfo *cms, int detached); + +# ifdef HEADER_PEM_H +DECLARE_PEM_rw_const(CMS, CMS_ContentInfo) +# endif +int CMS_stream(unsigned char ***boundary, CMS_ContentInfo *cms); +CMS_ContentInfo *d2i_CMS_bio(BIO *bp, CMS_ContentInfo **cms); +int i2d_CMS_bio(BIO *bp, CMS_ContentInfo *cms); + +BIO *BIO_new_CMS(BIO *out, CMS_ContentInfo *cms); +int i2d_CMS_bio_stream(BIO *out, CMS_ContentInfo *cms, BIO *in, int flags); +int PEM_write_bio_CMS_stream(BIO *out, CMS_ContentInfo *cms, BIO *in, + int flags); +CMS_ContentInfo *SMIME_read_CMS(BIO *bio, BIO **bcont); +int SMIME_write_CMS(BIO *bio, CMS_ContentInfo *cms, BIO *data, int flags); + +int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, + unsigned int flags); + +CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, + STACK_OF(X509) *certs, BIO *data, + unsigned int flags); + +CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si, + X509 *signcert, EVP_PKEY *pkey, + STACK_OF(X509) *certs, unsigned int flags); + +int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags); +CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags); + +int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out, + unsigned int flags); +CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md, + unsigned int flags); + +int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms, + const unsigned char *key, size_t keylen, + BIO *dcont, BIO *out, unsigned int flags); + +CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher, + const unsigned char *key, + size_t keylen, unsigned int flags); + +int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph, + const unsigned char *key, size_t keylen); + +int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs, + X509_STORE *store, BIO *dcont, BIO *out, unsigned int flags); + +int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms, + STACK_OF(X509) *certs, + X509_STORE *store, unsigned int flags); + +STACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms); + +CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *in, + const EVP_CIPHER *cipher, unsigned int flags); + +int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pkey, X509 *cert, + BIO *dcont, BIO *out, unsigned int flags); + +int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert); +int CMS_decrypt_set1_key(CMS_ContentInfo *cms, + unsigned char *key, size_t keylen, + const unsigned char *id, size_t idlen); +int CMS_decrypt_set1_password(CMS_ContentInfo *cms, + unsigned char *pass, ossl_ssize_t passlen); + +STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms); +int CMS_RecipientInfo_type(CMS_RecipientInfo *ri); +EVP_PKEY_CTX *CMS_RecipientInfo_get0_pkey_ctx(CMS_RecipientInfo *ri); +CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher); +CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms, + X509 *recip, unsigned int flags); +int CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey); +int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert); +int CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri, + EVP_PKEY **pk, X509 **recip, + X509_ALGOR **palg); +int CMS_RecipientInfo_ktri_get0_signer_id(CMS_RecipientInfo *ri, + ASN1_OCTET_STRING **keyid, + X509_NAME **issuer, + ASN1_INTEGER **sno); + +CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid, + unsigned char *key, size_t keylen, + unsigned char *id, size_t idlen, + ASN1_GENERALIZEDTIME *date, + ASN1_OBJECT *otherTypeId, + ASN1_TYPE *otherType); + +int CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri, + X509_ALGOR **palg, + ASN1_OCTET_STRING **pid, + ASN1_GENERALIZEDTIME **pdate, + ASN1_OBJECT **potherid, + ASN1_TYPE **pothertype); + +int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri, + unsigned char *key, size_t keylen); + +int CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri, + const unsigned char *id, size_t idlen); + +int CMS_RecipientInfo_set0_password(CMS_RecipientInfo *ri, + unsigned char *pass, + ossl_ssize_t passlen); + +CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms, + int iter, int wrap_nid, + int pbe_nid, + unsigned char *pass, + ossl_ssize_t passlen, + const EVP_CIPHER *kekciph); + +int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri); +int CMS_RecipientInfo_encrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri); + +int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out, + unsigned int flags); +CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags); + +int CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid); +const ASN1_OBJECT *CMS_get0_eContentType(CMS_ContentInfo *cms); + +CMS_CertificateChoices *CMS_add0_CertificateChoices(CMS_ContentInfo *cms); +int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert); +int CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert); +STACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms); + +CMS_RevocationInfoChoice *CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms); +int CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl); +int CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl); +STACK_OF(X509_CRL) *CMS_get1_crls(CMS_ContentInfo *cms); + +int CMS_SignedData_init(CMS_ContentInfo *cms); +CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, + X509 *signer, EVP_PKEY *pk, const EVP_MD *md, + unsigned int flags); +EVP_PKEY_CTX *CMS_SignerInfo_get0_pkey_ctx(CMS_SignerInfo *si); +EVP_MD_CTX *CMS_SignerInfo_get0_md_ctx(CMS_SignerInfo *si); +STACK_OF(CMS_SignerInfo) *CMS_get0_SignerInfos(CMS_ContentInfo *cms); + +void CMS_SignerInfo_set1_signer_cert(CMS_SignerInfo *si, X509 *signer); +int CMS_SignerInfo_get0_signer_id(CMS_SignerInfo *si, + ASN1_OCTET_STRING **keyid, + X509_NAME **issuer, ASN1_INTEGER **sno); +int CMS_SignerInfo_cert_cmp(CMS_SignerInfo *si, X509 *cert); +int CMS_set1_signers_certs(CMS_ContentInfo *cms, STACK_OF(X509) *certs, + unsigned int flags); +void CMS_SignerInfo_get0_algs(CMS_SignerInfo *si, EVP_PKEY **pk, + X509 **signer, X509_ALGOR **pdig, + X509_ALGOR **psig); +ASN1_OCTET_STRING *CMS_SignerInfo_get0_signature(CMS_SignerInfo *si); +int CMS_SignerInfo_sign(CMS_SignerInfo *si); +int CMS_SignerInfo_verify(CMS_SignerInfo *si); +int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain); + +int CMS_add_smimecap(CMS_SignerInfo *si, STACK_OF(X509_ALGOR) *algs); +int CMS_add_simple_smimecap(STACK_OF(X509_ALGOR) **algs, + int algnid, int keysize); +int CMS_add_standard_smimecap(STACK_OF(X509_ALGOR) **smcap); + +int CMS_signed_get_attr_count(const CMS_SignerInfo *si); +int CMS_signed_get_attr_by_NID(const CMS_SignerInfo *si, int nid, + int lastpos); +int CMS_signed_get_attr_by_OBJ(const CMS_SignerInfo *si, const ASN1_OBJECT *obj, + int lastpos); +X509_ATTRIBUTE *CMS_signed_get_attr(const CMS_SignerInfo *si, int loc); +X509_ATTRIBUTE *CMS_signed_delete_attr(CMS_SignerInfo *si, int loc); +int CMS_signed_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr); +int CMS_signed_add1_attr_by_OBJ(CMS_SignerInfo *si, + const ASN1_OBJECT *obj, int type, + const void *bytes, int len); +int CMS_signed_add1_attr_by_NID(CMS_SignerInfo *si, + int nid, int type, + const void *bytes, int len); +int CMS_signed_add1_attr_by_txt(CMS_SignerInfo *si, + const char *attrname, int type, + const void *bytes, int len); +void *CMS_signed_get0_data_by_OBJ(CMS_SignerInfo *si, const ASN1_OBJECT *oid, + int lastpos, int type); + +int CMS_unsigned_get_attr_count(const CMS_SignerInfo *si); +int CMS_unsigned_get_attr_by_NID(const CMS_SignerInfo *si, int nid, + int lastpos); +int CMS_unsigned_get_attr_by_OBJ(const CMS_SignerInfo *si, + const ASN1_OBJECT *obj, int lastpos); +X509_ATTRIBUTE *CMS_unsigned_get_attr(const CMS_SignerInfo *si, int loc); +X509_ATTRIBUTE *CMS_unsigned_delete_attr(CMS_SignerInfo *si, int loc); +int CMS_unsigned_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr); +int CMS_unsigned_add1_attr_by_OBJ(CMS_SignerInfo *si, + const ASN1_OBJECT *obj, int type, + const void *bytes, int len); +int CMS_unsigned_add1_attr_by_NID(CMS_SignerInfo *si, + int nid, int type, + const void *bytes, int len); +int CMS_unsigned_add1_attr_by_txt(CMS_SignerInfo *si, + const char *attrname, int type, + const void *bytes, int len); +void *CMS_unsigned_get0_data_by_OBJ(CMS_SignerInfo *si, ASN1_OBJECT *oid, + int lastpos, int type); + +# ifdef HEADER_X509V3_H + +int CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr); +CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen, + int allorfirst, + STACK_OF(GENERAL_NAMES) + *receiptList, STACK_OF(GENERAL_NAMES) + *receiptsTo); +int CMS_add1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest *rr); +void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr, + ASN1_STRING **pcid, + int *pallorfirst, + STACK_OF(GENERAL_NAMES) **plist, + STACK_OF(GENERAL_NAMES) **prto); +# endif +int CMS_RecipientInfo_kari_get0_alg(CMS_RecipientInfo *ri, + X509_ALGOR **palg, + ASN1_OCTET_STRING **pukm); +STACK_OF(CMS_RecipientEncryptedKey) +*CMS_RecipientInfo_kari_get0_reks(CMS_RecipientInfo *ri); + +int CMS_RecipientInfo_kari_get0_orig_id(CMS_RecipientInfo *ri, + X509_ALGOR **pubalg, + ASN1_BIT_STRING **pubkey, + ASN1_OCTET_STRING **keyid, + X509_NAME **issuer, + ASN1_INTEGER **sno); + +int CMS_RecipientInfo_kari_orig_id_cmp(CMS_RecipientInfo *ri, X509 *cert); + +int CMS_RecipientEncryptedKey_get0_id(CMS_RecipientEncryptedKey *rek, + ASN1_OCTET_STRING **keyid, + ASN1_GENERALIZEDTIME **tm, + CMS_OtherKeyAttribute **other, + X509_NAME **issuer, ASN1_INTEGER **sno); +int CMS_RecipientEncryptedKey_cert_cmp(CMS_RecipientEncryptedKey *rek, + X509 *cert); +int CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk); +EVP_CIPHER_CTX *CMS_RecipientInfo_kari_get0_ctx(CMS_RecipientInfo *ri); +int CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo *cms, + CMS_RecipientInfo *ri, + CMS_RecipientEncryptedKey *rek); + +int CMS_SharedInfo_encode(unsigned char **pder, X509_ALGOR *kekalg, + ASN1_OCTET_STRING *ukm, int keylen); + +/* Backward compatibility for spelling errors. */ +# define CMS_R_UNKNOWN_DIGEST_ALGORITM CMS_R_UNKNOWN_DIGEST_ALGORITHM +# define CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE \ + CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE + +# ifdef __cplusplus +} +# endif +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/cmserr.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/cmserr.h new file mode 100644 index 000000000..3f8ae26da --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/cmserr.h @@ -0,0 +1,196 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_CMSERR_H +# define HEADER_CMSERR_H + +# include + +# ifndef OPENSSL_NO_CMS + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_CMS_strings(void); + +/* + * CMS function codes. + */ +# define CMS_F_CHECK_CONTENT 99 +# define CMS_F_CMS_ADD0_CERT 164 +# define CMS_F_CMS_ADD0_RECIPIENT_KEY 100 +# define CMS_F_CMS_ADD0_RECIPIENT_PASSWORD 165 +# define CMS_F_CMS_ADD1_RECEIPTREQUEST 158 +# define CMS_F_CMS_ADD1_RECIPIENT_CERT 101 +# define CMS_F_CMS_ADD1_SIGNER 102 +# define CMS_F_CMS_ADD1_SIGNINGTIME 103 +# define CMS_F_CMS_COMPRESS 104 +# define CMS_F_CMS_COMPRESSEDDATA_CREATE 105 +# define CMS_F_CMS_COMPRESSEDDATA_INIT_BIO 106 +# define CMS_F_CMS_COPY_CONTENT 107 +# define CMS_F_CMS_COPY_MESSAGEDIGEST 108 +# define CMS_F_CMS_DATA 109 +# define CMS_F_CMS_DATAFINAL 110 +# define CMS_F_CMS_DATAINIT 111 +# define CMS_F_CMS_DECRYPT 112 +# define CMS_F_CMS_DECRYPT_SET1_KEY 113 +# define CMS_F_CMS_DECRYPT_SET1_PASSWORD 166 +# define CMS_F_CMS_DECRYPT_SET1_PKEY 114 +# define CMS_F_CMS_DIGESTALGORITHM_FIND_CTX 115 +# define CMS_F_CMS_DIGESTALGORITHM_INIT_BIO 116 +# define CMS_F_CMS_DIGESTEDDATA_DO_FINAL 117 +# define CMS_F_CMS_DIGEST_VERIFY 118 +# define CMS_F_CMS_ENCODE_RECEIPT 161 +# define CMS_F_CMS_ENCRYPT 119 +# define CMS_F_CMS_ENCRYPTEDCONTENT_INIT 179 +# define CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO 120 +# define CMS_F_CMS_ENCRYPTEDDATA_DECRYPT 121 +# define CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT 122 +# define CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY 123 +# define CMS_F_CMS_ENVELOPEDDATA_CREATE 124 +# define CMS_F_CMS_ENVELOPEDDATA_INIT_BIO 125 +# define CMS_F_CMS_ENVELOPED_DATA_INIT 126 +# define CMS_F_CMS_ENV_ASN1_CTRL 171 +# define CMS_F_CMS_FINAL 127 +# define CMS_F_CMS_GET0_CERTIFICATE_CHOICES 128 +# define CMS_F_CMS_GET0_CONTENT 129 +# define CMS_F_CMS_GET0_ECONTENT_TYPE 130 +# define CMS_F_CMS_GET0_ENVELOPED 131 +# define CMS_F_CMS_GET0_REVOCATION_CHOICES 132 +# define CMS_F_CMS_GET0_SIGNED 133 +# define CMS_F_CMS_MSGSIGDIGEST_ADD1 162 +# define CMS_F_CMS_RECEIPTREQUEST_CREATE0 159 +# define CMS_F_CMS_RECEIPT_VERIFY 160 +# define CMS_F_CMS_RECIPIENTINFO_DECRYPT 134 +# define CMS_F_CMS_RECIPIENTINFO_ENCRYPT 169 +# define CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT 178 +# define CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ALG 175 +# define CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ORIG_ID 173 +# define CMS_F_CMS_RECIPIENTINFO_KARI_GET0_REKS 172 +# define CMS_F_CMS_RECIPIENTINFO_KARI_ORIG_ID_CMP 174 +# define CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT 135 +# define CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT 136 +# define CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID 137 +# define CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP 138 +# define CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP 139 +# define CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT 140 +# define CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT 141 +# define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS 142 +# define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID 143 +# define CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT 167 +# define CMS_F_CMS_RECIPIENTINFO_SET0_KEY 144 +# define CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD 168 +# define CMS_F_CMS_RECIPIENTINFO_SET0_PKEY 145 +# define CMS_F_CMS_SD_ASN1_CTRL 170 +# define CMS_F_CMS_SET1_IAS 176 +# define CMS_F_CMS_SET1_KEYID 177 +# define CMS_F_CMS_SET1_SIGNERIDENTIFIER 146 +# define CMS_F_CMS_SET_DETACHED 147 +# define CMS_F_CMS_SIGN 148 +# define CMS_F_CMS_SIGNED_DATA_INIT 149 +# define CMS_F_CMS_SIGNERINFO_CONTENT_SIGN 150 +# define CMS_F_CMS_SIGNERINFO_SIGN 151 +# define CMS_F_CMS_SIGNERINFO_VERIFY 152 +# define CMS_F_CMS_SIGNERINFO_VERIFY_CERT 153 +# define CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT 154 +# define CMS_F_CMS_SIGN_RECEIPT 163 +# define CMS_F_CMS_STREAM 155 +# define CMS_F_CMS_UNCOMPRESS 156 +# define CMS_F_CMS_VERIFY 157 +# define CMS_F_KEK_UNWRAP_KEY 180 + +/* + * CMS reason codes. + */ +# define CMS_R_ADD_SIGNER_ERROR 99 +# define CMS_R_CERTIFICATE_ALREADY_PRESENT 175 +# define CMS_R_CERTIFICATE_HAS_NO_KEYID 160 +# define CMS_R_CERTIFICATE_VERIFY_ERROR 100 +# define CMS_R_CIPHER_INITIALISATION_ERROR 101 +# define CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR 102 +# define CMS_R_CMS_DATAFINAL_ERROR 103 +# define CMS_R_CMS_LIB 104 +# define CMS_R_CONTENTIDENTIFIER_MISMATCH 170 +# define CMS_R_CONTENT_NOT_FOUND 105 +# define CMS_R_CONTENT_TYPE_MISMATCH 171 +# define CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA 106 +# define CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA 107 +# define CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA 108 +# define CMS_R_CONTENT_VERIFY_ERROR 109 +# define CMS_R_CTRL_ERROR 110 +# define CMS_R_CTRL_FAILURE 111 +# define CMS_R_DECRYPT_ERROR 112 +# define CMS_R_ERROR_GETTING_PUBLIC_KEY 113 +# define CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE 114 +# define CMS_R_ERROR_SETTING_KEY 115 +# define CMS_R_ERROR_SETTING_RECIPIENTINFO 116 +# define CMS_R_INVALID_ENCRYPTED_KEY_LENGTH 117 +# define CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER 176 +# define CMS_R_INVALID_KEY_LENGTH 118 +# define CMS_R_MD_BIO_INIT_ERROR 119 +# define CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH 120 +# define CMS_R_MESSAGEDIGEST_WRONG_LENGTH 121 +# define CMS_R_MSGSIGDIGEST_ERROR 172 +# define CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE 162 +# define CMS_R_MSGSIGDIGEST_WRONG_LENGTH 163 +# define CMS_R_NEED_ONE_SIGNER 164 +# define CMS_R_NOT_A_SIGNED_RECEIPT 165 +# define CMS_R_NOT_ENCRYPTED_DATA 122 +# define CMS_R_NOT_KEK 123 +# define CMS_R_NOT_KEY_AGREEMENT 181 +# define CMS_R_NOT_KEY_TRANSPORT 124 +# define CMS_R_NOT_PWRI 177 +# define CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE 125 +# define CMS_R_NO_CIPHER 126 +# define CMS_R_NO_CONTENT 127 +# define CMS_R_NO_CONTENT_TYPE 173 +# define CMS_R_NO_DEFAULT_DIGEST 128 +# define CMS_R_NO_DIGEST_SET 129 +# define CMS_R_NO_KEY 130 +# define CMS_R_NO_KEY_OR_CERT 174 +# define CMS_R_NO_MATCHING_DIGEST 131 +# define CMS_R_NO_MATCHING_RECIPIENT 132 +# define CMS_R_NO_MATCHING_SIGNATURE 166 +# define CMS_R_NO_MSGSIGDIGEST 167 +# define CMS_R_NO_PASSWORD 178 +# define CMS_R_NO_PRIVATE_KEY 133 +# define CMS_R_NO_PUBLIC_KEY 134 +# define CMS_R_NO_RECEIPT_REQUEST 168 +# define CMS_R_NO_SIGNERS 135 +# define CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 136 +# define CMS_R_RECEIPT_DECODE_ERROR 169 +# define CMS_R_RECIPIENT_ERROR 137 +# define CMS_R_SIGNER_CERTIFICATE_NOT_FOUND 138 +# define CMS_R_SIGNFINAL_ERROR 139 +# define CMS_R_SMIME_TEXT_ERROR 140 +# define CMS_R_STORE_INIT_ERROR 141 +# define CMS_R_TYPE_NOT_COMPRESSED_DATA 142 +# define CMS_R_TYPE_NOT_DATA 143 +# define CMS_R_TYPE_NOT_DIGESTED_DATA 144 +# define CMS_R_TYPE_NOT_ENCRYPTED_DATA 145 +# define CMS_R_TYPE_NOT_ENVELOPED_DATA 146 +# define CMS_R_UNABLE_TO_FINALIZE_CONTEXT 147 +# define CMS_R_UNKNOWN_CIPHER 148 +# define CMS_R_UNKNOWN_DIGEST_ALGORITHM 149 +# define CMS_R_UNKNOWN_ID 150 +# define CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM 151 +# define CMS_R_UNSUPPORTED_CONTENT_TYPE 152 +# define CMS_R_UNSUPPORTED_KEK_ALGORITHM 153 +# define CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM 179 +# define CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE 155 +# define CMS_R_UNSUPPORTED_RECIPIENT_TYPE 154 +# define CMS_R_UNSUPPORTED_TYPE 156 +# define CMS_R_UNWRAP_ERROR 157 +# define CMS_R_UNWRAP_FAILURE 180 +# define CMS_R_VERIFICATION_FAILURE 158 +# define CMS_R_WRAP_ERROR 159 + +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/comp.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/comp.h new file mode 100644 index 000000000..d814d3cf2 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/comp.h @@ -0,0 +1,53 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_COMP_H +# define HEADER_COMP_H + +# include + +# ifndef OPENSSL_NO_COMP +# include +# include +# ifdef __cplusplus +extern "C" { +# endif + + + +COMP_CTX *COMP_CTX_new(COMP_METHOD *meth); +const COMP_METHOD *COMP_CTX_get_method(const COMP_CTX *ctx); +int COMP_CTX_get_type(const COMP_CTX* comp); +int COMP_get_type(const COMP_METHOD *meth); +const char *COMP_get_name(const COMP_METHOD *meth); +void COMP_CTX_free(COMP_CTX *ctx); + +int COMP_compress_block(COMP_CTX *ctx, unsigned char *out, int olen, + unsigned char *in, int ilen); +int COMP_expand_block(COMP_CTX *ctx, unsigned char *out, int olen, + unsigned char *in, int ilen); + +COMP_METHOD *COMP_zlib(void); + +#if OPENSSL_API_COMPAT < 0x10100000L +#define COMP_zlib_cleanup() while(0) continue +#endif + +# ifdef HEADER_BIO_H +# ifdef ZLIB +const BIO_METHOD *BIO_f_zlib(void); +# endif +# endif + + +# ifdef __cplusplus +} +# endif +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/comperr.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/comperr.h new file mode 100644 index 000000000..edea63a68 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/comperr.h @@ -0,0 +1,40 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_COMPERR_H +# define HEADER_COMPERR_H + +# include + +# ifndef OPENSSL_NO_COMP + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_COMP_strings(void); + +/* + * COMP function codes. + */ +# define COMP_F_BIO_ZLIB_FLUSH 99 +# define COMP_F_BIO_ZLIB_NEW 100 +# define COMP_F_BIO_ZLIB_READ 101 +# define COMP_F_BIO_ZLIB_WRITE 102 +# define COMP_F_COMP_CTX_NEW 103 + +/* + * COMP reason codes. + */ +# define COMP_R_ZLIB_DEFLATE_ERROR 99 +# define COMP_R_ZLIB_INFLATE_ERROR 100 +# define COMP_R_ZLIB_NOT_SUPPORTED 101 + +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/conf.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/conf.h new file mode 100644 index 000000000..7336cd2f1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/conf.h @@ -0,0 +1,168 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_CONF_H +# define HEADER_CONF_H + +# include +# include +# include +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + char *section; + char *name; + char *value; +} CONF_VALUE; + +DEFINE_STACK_OF(CONF_VALUE) +DEFINE_LHASH_OF(CONF_VALUE); + +struct conf_st; +struct conf_method_st; +typedef struct conf_method_st CONF_METHOD; + +struct conf_method_st { + const char *name; + CONF *(*create) (CONF_METHOD *meth); + int (*init) (CONF *conf); + int (*destroy) (CONF *conf); + int (*destroy_data) (CONF *conf); + int (*load_bio) (CONF *conf, BIO *bp, long *eline); + int (*dump) (const CONF *conf, BIO *bp); + int (*is_number) (const CONF *conf, char c); + int (*to_int) (const CONF *conf, char c); + int (*load) (CONF *conf, const char *name, long *eline); +}; + +/* Module definitions */ + +typedef struct conf_imodule_st CONF_IMODULE; +typedef struct conf_module_st CONF_MODULE; + +DEFINE_STACK_OF(CONF_MODULE) +DEFINE_STACK_OF(CONF_IMODULE) + +/* DSO module function typedefs */ +typedef int conf_init_func (CONF_IMODULE *md, const CONF *cnf); +typedef void conf_finish_func (CONF_IMODULE *md); + +# define CONF_MFLAGS_IGNORE_ERRORS 0x1 +# define CONF_MFLAGS_IGNORE_RETURN_CODES 0x2 +# define CONF_MFLAGS_SILENT 0x4 +# define CONF_MFLAGS_NO_DSO 0x8 +# define CONF_MFLAGS_IGNORE_MISSING_FILE 0x10 +# define CONF_MFLAGS_DEFAULT_SECTION 0x20 + +int CONF_set_default_method(CONF_METHOD *meth); +void CONF_set_nconf(CONF *conf, LHASH_OF(CONF_VALUE) *hash); +LHASH_OF(CONF_VALUE) *CONF_load(LHASH_OF(CONF_VALUE) *conf, const char *file, + long *eline); +# ifndef OPENSSL_NO_STDIO +LHASH_OF(CONF_VALUE) *CONF_load_fp(LHASH_OF(CONF_VALUE) *conf, FILE *fp, + long *eline); +# endif +LHASH_OF(CONF_VALUE) *CONF_load_bio(LHASH_OF(CONF_VALUE) *conf, BIO *bp, + long *eline); +STACK_OF(CONF_VALUE) *CONF_get_section(LHASH_OF(CONF_VALUE) *conf, + const char *section); +char *CONF_get_string(LHASH_OF(CONF_VALUE) *conf, const char *group, + const char *name); +long CONF_get_number(LHASH_OF(CONF_VALUE) *conf, const char *group, + const char *name); +void CONF_free(LHASH_OF(CONF_VALUE) *conf); +#ifndef OPENSSL_NO_STDIO +int CONF_dump_fp(LHASH_OF(CONF_VALUE) *conf, FILE *out); +#endif +int CONF_dump_bio(LHASH_OF(CONF_VALUE) *conf, BIO *out); + +DEPRECATEDIN_1_1_0(void OPENSSL_config(const char *config_name)) + +#if OPENSSL_API_COMPAT < 0x10100000L +# define OPENSSL_no_config() \ + OPENSSL_init_crypto(OPENSSL_INIT_NO_LOAD_CONFIG, NULL) +#endif + +/* + * New conf code. The semantics are different from the functions above. If + * that wasn't the case, the above functions would have been replaced + */ + +struct conf_st { + CONF_METHOD *meth; + void *meth_data; + LHASH_OF(CONF_VALUE) *data; +}; + +CONF *NCONF_new(CONF_METHOD *meth); +CONF_METHOD *NCONF_default(void); +CONF_METHOD *NCONF_WIN32(void); +void NCONF_free(CONF *conf); +void NCONF_free_data(CONF *conf); + +int NCONF_load(CONF *conf, const char *file, long *eline); +# ifndef OPENSSL_NO_STDIO +int NCONF_load_fp(CONF *conf, FILE *fp, long *eline); +# endif +int NCONF_load_bio(CONF *conf, BIO *bp, long *eline); +STACK_OF(CONF_VALUE) *NCONF_get_section(const CONF *conf, + const char *section); +char *NCONF_get_string(const CONF *conf, const char *group, const char *name); +int NCONF_get_number_e(const CONF *conf, const char *group, const char *name, + long *result); +#ifndef OPENSSL_NO_STDIO +int NCONF_dump_fp(const CONF *conf, FILE *out); +#endif +int NCONF_dump_bio(const CONF *conf, BIO *out); + +#define NCONF_get_number(c,g,n,r) NCONF_get_number_e(c,g,n,r) + +/* Module functions */ + +int CONF_modules_load(const CONF *cnf, const char *appname, + unsigned long flags); +int CONF_modules_load_file(const char *filename, const char *appname, + unsigned long flags); +void CONF_modules_unload(int all); +void CONF_modules_finish(void); +#if OPENSSL_API_COMPAT < 0x10100000L +# define CONF_modules_free() while(0) continue +#endif +int CONF_module_add(const char *name, conf_init_func *ifunc, + conf_finish_func *ffunc); + +const char *CONF_imodule_get_name(const CONF_IMODULE *md); +const char *CONF_imodule_get_value(const CONF_IMODULE *md); +void *CONF_imodule_get_usr_data(const CONF_IMODULE *md); +void CONF_imodule_set_usr_data(CONF_IMODULE *md, void *usr_data); +CONF_MODULE *CONF_imodule_get_module(const CONF_IMODULE *md); +unsigned long CONF_imodule_get_flags(const CONF_IMODULE *md); +void CONF_imodule_set_flags(CONF_IMODULE *md, unsigned long flags); +void *CONF_module_get_usr_data(CONF_MODULE *pmod); +void CONF_module_set_usr_data(CONF_MODULE *pmod, void *usr_data); + +char *CONF_get1_default_config_file(void); + +int CONF_parse_list(const char *list, int sep, int nospc, + int (*list_cb) (const char *elem, int len, void *usr), + void *arg); + +void OPENSSL_load_builtin_modules(void); + + +# ifdef __cplusplus +} +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/conf_api.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/conf_api.h new file mode 100644 index 000000000..a0275ad79 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/conf_api.h @@ -0,0 +1,40 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_CONF_API_H +# define HEADER_CONF_API_H + +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Up until OpenSSL 0.9.5a, this was new_section */ +CONF_VALUE *_CONF_new_section(CONF *conf, const char *section); +/* Up until OpenSSL 0.9.5a, this was get_section */ +CONF_VALUE *_CONF_get_section(const CONF *conf, const char *section); +/* Up until OpenSSL 0.9.5a, this was CONF_get_section */ +STACK_OF(CONF_VALUE) *_CONF_get_section_values(const CONF *conf, + const char *section); + +int _CONF_add_string(CONF *conf, CONF_VALUE *section, CONF_VALUE *value); +char *_CONF_get_string(const CONF *conf, const char *section, + const char *name); +long _CONF_get_number(const CONF *conf, const char *section, + const char *name); + +int _CONF_new_data(CONF *conf); +void _CONF_free_data(CONF *conf); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/conferr.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/conferr.h new file mode 100644 index 000000000..d1c92f45d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/conferr.h @@ -0,0 +1,72 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_CONFERR_H +# define HEADER_CONFERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_CONF_strings(void); + +/* + * CONF function codes. + */ +# define CONF_F_CONF_DUMP_FP 104 +# define CONF_F_CONF_LOAD 100 +# define CONF_F_CONF_LOAD_FP 103 +# define CONF_F_CONF_PARSE_LIST 119 +# define CONF_F_DEF_LOAD 120 +# define CONF_F_DEF_LOAD_BIO 121 +# define CONF_F_GET_NEXT_FILE 107 +# define CONF_F_MODULE_ADD 122 +# define CONF_F_MODULE_INIT 115 +# define CONF_F_MODULE_LOAD_DSO 117 +# define CONF_F_MODULE_RUN 118 +# define CONF_F_NCONF_DUMP_BIO 105 +# define CONF_F_NCONF_DUMP_FP 106 +# define CONF_F_NCONF_GET_NUMBER_E 112 +# define CONF_F_NCONF_GET_SECTION 108 +# define CONF_F_NCONF_GET_STRING 109 +# define CONF_F_NCONF_LOAD 113 +# define CONF_F_NCONF_LOAD_BIO 110 +# define CONF_F_NCONF_LOAD_FP 114 +# define CONF_F_NCONF_NEW 111 +# define CONF_F_PROCESS_INCLUDE 116 +# define CONF_F_SSL_MODULE_INIT 123 +# define CONF_F_STR_COPY 101 + +/* + * CONF reason codes. + */ +# define CONF_R_ERROR_LOADING_DSO 110 +# define CONF_R_LIST_CANNOT_BE_NULL 115 +# define CONF_R_MISSING_CLOSE_SQUARE_BRACKET 100 +# define CONF_R_MISSING_EQUAL_SIGN 101 +# define CONF_R_MISSING_INIT_FUNCTION 112 +# define CONF_R_MODULE_INITIALIZATION_ERROR 109 +# define CONF_R_NO_CLOSE_BRACE 102 +# define CONF_R_NO_CONF 105 +# define CONF_R_NO_CONF_OR_ENVIRONMENT_VARIABLE 106 +# define CONF_R_NO_SECTION 107 +# define CONF_R_NO_SUCH_FILE 114 +# define CONF_R_NO_VALUE 108 +# define CONF_R_NUMBER_TOO_LARGE 121 +# define CONF_R_RECURSIVE_DIRECTORY_INCLUDE 111 +# define CONF_R_SSL_COMMAND_SECTION_EMPTY 117 +# define CONF_R_SSL_COMMAND_SECTION_NOT_FOUND 118 +# define CONF_R_SSL_SECTION_EMPTY 119 +# define CONF_R_SSL_SECTION_NOT_FOUND 120 +# define CONF_R_UNABLE_TO_CREATE_NEW_SECTION 103 +# define CONF_R_UNKNOWN_MODULE_NAME 113 +# define CONF_R_VARIABLE_EXPANSION_TOO_LONG 116 +# define CONF_R_VARIABLE_HAS_NO_VALUE 104 + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/crypto.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/crypto.h new file mode 100644 index 000000000..7d0b52623 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/crypto.h @@ -0,0 +1,445 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_CRYPTO_H +# define HEADER_CRYPTO_H + +# include +# include + +# include + +# ifndef OPENSSL_NO_STDIO +# include +# endif + +# include +# include +# include +# include +# include + +# ifdef CHARSET_EBCDIC +# include +# endif + +/* + * Resolve problems on some operating systems with symbol names that clash + * one way or another + */ +# include + +# if OPENSSL_API_COMPAT < 0x10100000L +# include +# endif + +#ifdef __cplusplus +extern "C" { +#endif + +# if OPENSSL_API_COMPAT < 0x10100000L +# define SSLeay OpenSSL_version_num +# define SSLeay_version OpenSSL_version +# define SSLEAY_VERSION_NUMBER OPENSSL_VERSION_NUMBER +# define SSLEAY_VERSION OPENSSL_VERSION +# define SSLEAY_CFLAGS OPENSSL_CFLAGS +# define SSLEAY_BUILT_ON OPENSSL_BUILT_ON +# define SSLEAY_PLATFORM OPENSSL_PLATFORM +# define SSLEAY_DIR OPENSSL_DIR + +/* + * Old type for allocating dynamic locks. No longer used. Use the new thread + * API instead. + */ +typedef struct { + int dummy; +} CRYPTO_dynlock; + +# endif /* OPENSSL_API_COMPAT */ + +typedef void CRYPTO_RWLOCK; + +CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void); +int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock); +int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock); +int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock); +void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock); + +int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock); + +/* + * The following can be used to detect memory leaks in the library. If + * used, it turns on malloc checking + */ +# define CRYPTO_MEM_CHECK_OFF 0x0 /* Control only */ +# define CRYPTO_MEM_CHECK_ON 0x1 /* Control and mode bit */ +# define CRYPTO_MEM_CHECK_ENABLE 0x2 /* Control and mode bit */ +# define CRYPTO_MEM_CHECK_DISABLE 0x3 /* Control only */ + +struct crypto_ex_data_st { + STACK_OF(void) *sk; +}; +DEFINE_STACK_OF(void) + +/* + * Per class, we have a STACK of function pointers. + */ +# define CRYPTO_EX_INDEX_SSL 0 +# define CRYPTO_EX_INDEX_SSL_CTX 1 +# define CRYPTO_EX_INDEX_SSL_SESSION 2 +# define CRYPTO_EX_INDEX_X509 3 +# define CRYPTO_EX_INDEX_X509_STORE 4 +# define CRYPTO_EX_INDEX_X509_STORE_CTX 5 +# define CRYPTO_EX_INDEX_DH 6 +# define CRYPTO_EX_INDEX_DSA 7 +# define CRYPTO_EX_INDEX_EC_KEY 8 +# define CRYPTO_EX_INDEX_RSA 9 +# define CRYPTO_EX_INDEX_ENGINE 10 +# define CRYPTO_EX_INDEX_UI 11 +# define CRYPTO_EX_INDEX_BIO 12 +# define CRYPTO_EX_INDEX_APP 13 +# define CRYPTO_EX_INDEX_UI_METHOD 14 +# define CRYPTO_EX_INDEX_DRBG 15 +# define CRYPTO_EX_INDEX__COUNT 16 + +/* No longer needed, so this is a no-op */ +#define OPENSSL_malloc_init() while(0) continue + +int CRYPTO_mem_ctrl(int mode); + +# define OPENSSL_malloc(num) \ + CRYPTO_malloc(num, OPENSSL_FILE, OPENSSL_LINE) +# define OPENSSL_zalloc(num) \ + CRYPTO_zalloc(num, OPENSSL_FILE, OPENSSL_LINE) +# define OPENSSL_realloc(addr, num) \ + CRYPTO_realloc(addr, num, OPENSSL_FILE, OPENSSL_LINE) +# define OPENSSL_clear_realloc(addr, old_num, num) \ + CRYPTO_clear_realloc(addr, old_num, num, OPENSSL_FILE, OPENSSL_LINE) +# define OPENSSL_clear_free(addr, num) \ + CRYPTO_clear_free(addr, num, OPENSSL_FILE, OPENSSL_LINE) +# define OPENSSL_free(addr) \ + CRYPTO_free(addr, OPENSSL_FILE, OPENSSL_LINE) +# define OPENSSL_memdup(str, s) \ + CRYPTO_memdup((str), s, OPENSSL_FILE, OPENSSL_LINE) +# define OPENSSL_strdup(str) \ + CRYPTO_strdup(str, OPENSSL_FILE, OPENSSL_LINE) +# define OPENSSL_strndup(str, n) \ + CRYPTO_strndup(str, n, OPENSSL_FILE, OPENSSL_LINE) +# define OPENSSL_secure_malloc(num) \ + CRYPTO_secure_malloc(num, OPENSSL_FILE, OPENSSL_LINE) +# define OPENSSL_secure_zalloc(num) \ + CRYPTO_secure_zalloc(num, OPENSSL_FILE, OPENSSL_LINE) +# define OPENSSL_secure_free(addr) \ + CRYPTO_secure_free(addr, OPENSSL_FILE, OPENSSL_LINE) +# define OPENSSL_secure_clear_free(addr, num) \ + CRYPTO_secure_clear_free(addr, num, OPENSSL_FILE, OPENSSL_LINE) +# define OPENSSL_secure_actual_size(ptr) \ + CRYPTO_secure_actual_size(ptr) + +size_t OPENSSL_strlcpy(char *dst, const char *src, size_t siz); +size_t OPENSSL_strlcat(char *dst, const char *src, size_t siz); +size_t OPENSSL_strnlen(const char *str, size_t maxlen); +char *OPENSSL_buf2hexstr(const unsigned char *buffer, long len); +unsigned char *OPENSSL_hexstr2buf(const char *str, long *len); +int OPENSSL_hexchar2int(unsigned char c); + +# define OPENSSL_MALLOC_MAX_NELEMS(type) (((1U<<(sizeof(int)*8-1))-1)/sizeof(type)) + +unsigned long OpenSSL_version_num(void); +const char *OpenSSL_version(int type); +# define OPENSSL_VERSION 0 +# define OPENSSL_CFLAGS 1 +# define OPENSSL_BUILT_ON 2 +# define OPENSSL_PLATFORM 3 +# define OPENSSL_DIR 4 +# define OPENSSL_ENGINES_DIR 5 + +int OPENSSL_issetugid(void); + +typedef void CRYPTO_EX_new (void *parent, void *ptr, CRYPTO_EX_DATA *ad, + int idx, long argl, void *argp); +typedef void CRYPTO_EX_free (void *parent, void *ptr, CRYPTO_EX_DATA *ad, + int idx, long argl, void *argp); +typedef int CRYPTO_EX_dup (CRYPTO_EX_DATA *to, const CRYPTO_EX_DATA *from, + void *from_d, int idx, long argl, void *argp); +__owur int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp, + CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func); +/* No longer use an index. */ +int CRYPTO_free_ex_index(int class_index, int idx); + +/* + * Initialise/duplicate/free CRYPTO_EX_DATA variables corresponding to a + * given class (invokes whatever per-class callbacks are applicable) + */ +int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad); +int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to, + const CRYPTO_EX_DATA *from); + +void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad); + +/* + * Get/set data in a CRYPTO_EX_DATA variable corresponding to a particular + * index (relative to the class type involved) + */ +int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int idx, void *val); +void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int idx); + +# if OPENSSL_API_COMPAT < 0x10100000L +/* + * This function cleans up all "ex_data" state. It mustn't be called under + * potential race-conditions. + */ +# define CRYPTO_cleanup_all_ex_data() while(0) continue + +/* + * The old locking functions have been removed completely without compatibility + * macros. This is because the old functions either could not properly report + * errors, or the returned error values were not clearly documented. + * Replacing the locking functions with no-ops would cause race condition + * issues in the affected applications. It is far better for them to fail at + * compile time. + * On the other hand, the locking callbacks are no longer used. Consequently, + * the callback management functions can be safely replaced with no-op macros. + */ +# define CRYPTO_num_locks() (1) +# define CRYPTO_set_locking_callback(func) +# define CRYPTO_get_locking_callback() (NULL) +# define CRYPTO_set_add_lock_callback(func) +# define CRYPTO_get_add_lock_callback() (NULL) + +/* + * These defines where used in combination with the old locking callbacks, + * they are not called anymore, but old code that's not called might still + * use them. + */ +# define CRYPTO_LOCK 1 +# define CRYPTO_UNLOCK 2 +# define CRYPTO_READ 4 +# define CRYPTO_WRITE 8 + +/* This structure is no longer used */ +typedef struct crypto_threadid_st { + int dummy; +} CRYPTO_THREADID; +/* Only use CRYPTO_THREADID_set_[numeric|pointer]() within callbacks */ +# define CRYPTO_THREADID_set_numeric(id, val) +# define CRYPTO_THREADID_set_pointer(id, ptr) +# define CRYPTO_THREADID_set_callback(threadid_func) (0) +# define CRYPTO_THREADID_get_callback() (NULL) +# define CRYPTO_THREADID_current(id) +# define CRYPTO_THREADID_cmp(a, b) (-1) +# define CRYPTO_THREADID_cpy(dest, src) +# define CRYPTO_THREADID_hash(id) (0UL) + +# if OPENSSL_API_COMPAT < 0x10000000L +# define CRYPTO_set_id_callback(func) +# define CRYPTO_get_id_callback() (NULL) +# define CRYPTO_thread_id() (0UL) +# endif /* OPENSSL_API_COMPAT < 0x10000000L */ + +# define CRYPTO_set_dynlock_create_callback(dyn_create_function) +# define CRYPTO_set_dynlock_lock_callback(dyn_lock_function) +# define CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function) +# define CRYPTO_get_dynlock_create_callback() (NULL) +# define CRYPTO_get_dynlock_lock_callback() (NULL) +# define CRYPTO_get_dynlock_destroy_callback() (NULL) +# endif /* OPENSSL_API_COMPAT < 0x10100000L */ + +int CRYPTO_set_mem_functions( + void *(*m) (size_t, const char *, int), + void *(*r) (void *, size_t, const char *, int), + void (*f) (void *, const char *, int)); +int CRYPTO_set_mem_debug(int flag); +void CRYPTO_get_mem_functions( + void *(**m) (size_t, const char *, int), + void *(**r) (void *, size_t, const char *, int), + void (**f) (void *, const char *, int)); + +void *CRYPTO_malloc(size_t num, const char *file, int line); +void *CRYPTO_zalloc(size_t num, const char *file, int line); +void *CRYPTO_memdup(const void *str, size_t siz, const char *file, int line); +char *CRYPTO_strdup(const char *str, const char *file, int line); +char *CRYPTO_strndup(const char *str, size_t s, const char *file, int line); +void CRYPTO_free(void *ptr, const char *file, int line); +void CRYPTO_clear_free(void *ptr, size_t num, const char *file, int line); +void *CRYPTO_realloc(void *addr, size_t num, const char *file, int line); +void *CRYPTO_clear_realloc(void *addr, size_t old_num, size_t num, + const char *file, int line); + +int CRYPTO_secure_malloc_init(size_t sz, int minsize); +int CRYPTO_secure_malloc_done(void); +void *CRYPTO_secure_malloc(size_t num, const char *file, int line); +void *CRYPTO_secure_zalloc(size_t num, const char *file, int line); +void CRYPTO_secure_free(void *ptr, const char *file, int line); +void CRYPTO_secure_clear_free(void *ptr, size_t num, + const char *file, int line); +int CRYPTO_secure_allocated(const void *ptr); +int CRYPTO_secure_malloc_initialized(void); +size_t CRYPTO_secure_actual_size(void *ptr); +size_t CRYPTO_secure_used(void); + +void OPENSSL_cleanse(void *ptr, size_t len); + +# ifndef OPENSSL_NO_CRYPTO_MDEBUG +# define OPENSSL_mem_debug_push(info) \ + CRYPTO_mem_debug_push(info, OPENSSL_FILE, OPENSSL_LINE) +# define OPENSSL_mem_debug_pop() \ + CRYPTO_mem_debug_pop() +int CRYPTO_mem_debug_push(const char *info, const char *file, int line); +int CRYPTO_mem_debug_pop(void); +void CRYPTO_get_alloc_counts(int *mcount, int *rcount, int *fcount); + +/*- + * Debugging functions (enabled by CRYPTO_set_mem_debug(1)) + * The flag argument has the following significance: + * 0: called before the actual memory allocation has taken place + * 1: called after the actual memory allocation has taken place + */ +void CRYPTO_mem_debug_malloc(void *addr, size_t num, int flag, + const char *file, int line); +void CRYPTO_mem_debug_realloc(void *addr1, void *addr2, size_t num, int flag, + const char *file, int line); +void CRYPTO_mem_debug_free(void *addr, int flag, + const char *file, int line); + +int CRYPTO_mem_leaks_cb(int (*cb) (const char *str, size_t len, void *u), + void *u); +# ifndef OPENSSL_NO_STDIO +int CRYPTO_mem_leaks_fp(FILE *); +# endif +int CRYPTO_mem_leaks(BIO *bio); +# endif + +/* die if we have to */ +ossl_noreturn void OPENSSL_die(const char *assertion, const char *file, int line); +# if OPENSSL_API_COMPAT < 0x10100000L +# define OpenSSLDie(f,l,a) OPENSSL_die((a),(f),(l)) +# endif +# define OPENSSL_assert(e) \ + (void)((e) ? 0 : (OPENSSL_die("assertion failed: " #e, OPENSSL_FILE, OPENSSL_LINE), 1)) + +int OPENSSL_isservice(void); + +int FIPS_mode(void); +int FIPS_mode_set(int r); + +void OPENSSL_init(void); +# ifdef OPENSSL_SYS_UNIX +void OPENSSL_fork_prepare(void); +void OPENSSL_fork_parent(void); +void OPENSSL_fork_child(void); +# endif + +struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result); +int OPENSSL_gmtime_adj(struct tm *tm, int offset_day, long offset_sec); +int OPENSSL_gmtime_diff(int *pday, int *psec, + const struct tm *from, const struct tm *to); + +/* + * CRYPTO_memcmp returns zero iff the |len| bytes at |a| and |b| are equal. + * It takes an amount of time dependent on |len|, but independent of the + * contents of |a| and |b|. Unlike memcmp, it cannot be used to put elements + * into a defined order as the return value when a != b is undefined, other + * than to be non-zero. + */ +int CRYPTO_memcmp(const void * in_a, const void * in_b, size_t len); + +/* Standard initialisation options */ +# define OPENSSL_INIT_NO_LOAD_CRYPTO_STRINGS 0x00000001L +# define OPENSSL_INIT_LOAD_CRYPTO_STRINGS 0x00000002L +# define OPENSSL_INIT_ADD_ALL_CIPHERS 0x00000004L +# define OPENSSL_INIT_ADD_ALL_DIGESTS 0x00000008L +# define OPENSSL_INIT_NO_ADD_ALL_CIPHERS 0x00000010L +# define OPENSSL_INIT_NO_ADD_ALL_DIGESTS 0x00000020L +# define OPENSSL_INIT_LOAD_CONFIG 0x00000040L +# define OPENSSL_INIT_NO_LOAD_CONFIG 0x00000080L +# define OPENSSL_INIT_ASYNC 0x00000100L +# define OPENSSL_INIT_ENGINE_RDRAND 0x00000200L +# define OPENSSL_INIT_ENGINE_DYNAMIC 0x00000400L +# define OPENSSL_INIT_ENGINE_OPENSSL 0x00000800L +# define OPENSSL_INIT_ENGINE_CRYPTODEV 0x00001000L +# define OPENSSL_INIT_ENGINE_CAPI 0x00002000L +# define OPENSSL_INIT_ENGINE_PADLOCK 0x00004000L +# define OPENSSL_INIT_ENGINE_AFALG 0x00008000L +/* OPENSSL_INIT_ZLIB 0x00010000L */ +# define OPENSSL_INIT_ATFORK 0x00020000L +/* OPENSSL_INIT_BASE_ONLY 0x00040000L */ +# define OPENSSL_INIT_NO_ATEXIT 0x00080000L +/* OPENSSL_INIT flag range 0xfff00000 reserved for OPENSSL_init_ssl() */ +/* Max OPENSSL_INIT flag value is 0x80000000 */ + +/* openssl and dasync not counted as builtin */ +# define OPENSSL_INIT_ENGINE_ALL_BUILTIN \ + (OPENSSL_INIT_ENGINE_RDRAND | OPENSSL_INIT_ENGINE_DYNAMIC \ + | OPENSSL_INIT_ENGINE_CRYPTODEV | OPENSSL_INIT_ENGINE_CAPI | \ + OPENSSL_INIT_ENGINE_PADLOCK) + + +/* Library initialisation functions */ +void OPENSSL_cleanup(void); +int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings); +int OPENSSL_atexit(void (*handler)(void)); +void OPENSSL_thread_stop(void); + +/* Low-level control of initialization */ +OPENSSL_INIT_SETTINGS *OPENSSL_INIT_new(void); +# ifndef OPENSSL_NO_STDIO +int OPENSSL_INIT_set_config_filename(OPENSSL_INIT_SETTINGS *settings, + const char *config_filename); +void OPENSSL_INIT_set_config_file_flags(OPENSSL_INIT_SETTINGS *settings, + unsigned long flags); +int OPENSSL_INIT_set_config_appname(OPENSSL_INIT_SETTINGS *settings, + const char *config_appname); +# endif +void OPENSSL_INIT_free(OPENSSL_INIT_SETTINGS *settings); + +# if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) +# if defined(_WIN32) +# if defined(BASETYPES) || defined(_WINDEF_H) +/* application has to include in order to use this */ +typedef DWORD CRYPTO_THREAD_LOCAL; +typedef DWORD CRYPTO_THREAD_ID; + +typedef LONG CRYPTO_ONCE; +# define CRYPTO_ONCE_STATIC_INIT 0 +# endif +# else +# include +typedef pthread_once_t CRYPTO_ONCE; +typedef pthread_key_t CRYPTO_THREAD_LOCAL; +typedef pthread_t CRYPTO_THREAD_ID; + +# define CRYPTO_ONCE_STATIC_INIT PTHREAD_ONCE_INIT +# endif +# endif + +# if !defined(CRYPTO_ONCE_STATIC_INIT) +typedef unsigned int CRYPTO_ONCE; +typedef unsigned int CRYPTO_THREAD_LOCAL; +typedef unsigned int CRYPTO_THREAD_ID; +# define CRYPTO_ONCE_STATIC_INIT 0 +# endif + +int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void)); + +int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *)); +void *CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL *key); +int CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL *key, void *val); +int CRYPTO_THREAD_cleanup_local(CRYPTO_THREAD_LOCAL *key); + +CRYPTO_THREAD_ID CRYPTO_THREAD_get_current_id(void); +int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b); + + +# ifdef __cplusplus +} +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/cryptoerr.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/cryptoerr.h new file mode 100644 index 000000000..10723d045 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/cryptoerr.h @@ -0,0 +1,56 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_CRYPTOERR_H +# define HEADER_CRYPTOERR_H + +# ifdef __cplusplus +extern "C" +# endif + +# include + +int ERR_load_CRYPTO_strings(void); + +/* + * CRYPTO function codes. + */ +# define CRYPTO_F_CMAC_CTX_NEW 120 +# define CRYPTO_F_CRYPTO_DUP_EX_DATA 110 +# define CRYPTO_F_CRYPTO_FREE_EX_DATA 111 +# define CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX 100 +# define CRYPTO_F_CRYPTO_MEMDUP 115 +# define CRYPTO_F_CRYPTO_NEW_EX_DATA 112 +# define CRYPTO_F_CRYPTO_OCB128_COPY_CTX 121 +# define CRYPTO_F_CRYPTO_OCB128_INIT 122 +# define CRYPTO_F_CRYPTO_SET_EX_DATA 102 +# define CRYPTO_F_FIPS_MODE_SET 109 +# define CRYPTO_F_GET_AND_LOCK 113 +# define CRYPTO_F_OPENSSL_ATEXIT 114 +# define CRYPTO_F_OPENSSL_BUF2HEXSTR 117 +# define CRYPTO_F_OPENSSL_FOPEN 119 +# define CRYPTO_F_OPENSSL_HEXSTR2BUF 118 +# define CRYPTO_F_OPENSSL_INIT_CRYPTO 116 +# define CRYPTO_F_OPENSSL_LH_NEW 126 +# define CRYPTO_F_OPENSSL_SK_DEEP_COPY 127 +# define CRYPTO_F_OPENSSL_SK_DUP 128 +# define CRYPTO_F_PKEY_HMAC_INIT 123 +# define CRYPTO_F_PKEY_POLY1305_INIT 124 +# define CRYPTO_F_PKEY_SIPHASH_INIT 125 +# define CRYPTO_F_SK_RESERVE 129 + +/* + * CRYPTO reason codes. + */ +# define CRYPTO_R_FIPS_MODE_NOT_SUPPORTED 101 +# define CRYPTO_R_ILLEGAL_HEX_DIGIT 102 +# define CRYPTO_R_ODD_NUMBER_OF_DIGITS 103 + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/ct.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ct.h new file mode 100644 index 000000000..d4262fa04 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ct.h @@ -0,0 +1,476 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_CT_H +# define HEADER_CT_H + +# include + +# ifndef OPENSSL_NO_CT +# include +# include +# include +# include +# ifdef __cplusplus +extern "C" { +# endif + + +/* Minimum RSA key size, from RFC6962 */ +# define SCT_MIN_RSA_BITS 2048 + +/* All hashes are SHA256 in v1 of Certificate Transparency */ +# define CT_V1_HASHLEN SHA256_DIGEST_LENGTH + +typedef enum { + CT_LOG_ENTRY_TYPE_NOT_SET = -1, + CT_LOG_ENTRY_TYPE_X509 = 0, + CT_LOG_ENTRY_TYPE_PRECERT = 1 +} ct_log_entry_type_t; + +typedef enum { + SCT_VERSION_NOT_SET = -1, + SCT_VERSION_V1 = 0 +} sct_version_t; + +typedef enum { + SCT_SOURCE_UNKNOWN, + SCT_SOURCE_TLS_EXTENSION, + SCT_SOURCE_X509V3_EXTENSION, + SCT_SOURCE_OCSP_STAPLED_RESPONSE +} sct_source_t; + +typedef enum { + SCT_VALIDATION_STATUS_NOT_SET, + SCT_VALIDATION_STATUS_UNKNOWN_LOG, + SCT_VALIDATION_STATUS_VALID, + SCT_VALIDATION_STATUS_INVALID, + SCT_VALIDATION_STATUS_UNVERIFIED, + SCT_VALIDATION_STATUS_UNKNOWN_VERSION +} sct_validation_status_t; + +DEFINE_STACK_OF(SCT) +DEFINE_STACK_OF(CTLOG) + +/****************************************** + * CT policy evaluation context functions * + ******************************************/ + +/* + * Creates a new, empty policy evaluation context. + * The caller is responsible for calling CT_POLICY_EVAL_CTX_free when finished + * with the CT_POLICY_EVAL_CTX. + */ +CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new(void); + +/* Deletes a policy evaluation context and anything it owns. */ +void CT_POLICY_EVAL_CTX_free(CT_POLICY_EVAL_CTX *ctx); + +/* Gets the peer certificate that the SCTs are for */ +X509* CT_POLICY_EVAL_CTX_get0_cert(const CT_POLICY_EVAL_CTX *ctx); + +/* + * Sets the certificate associated with the received SCTs. + * Increments the reference count of cert. + * Returns 1 on success, 0 otherwise. + */ +int CT_POLICY_EVAL_CTX_set1_cert(CT_POLICY_EVAL_CTX *ctx, X509 *cert); + +/* Gets the issuer of the aforementioned certificate */ +X509* CT_POLICY_EVAL_CTX_get0_issuer(const CT_POLICY_EVAL_CTX *ctx); + +/* + * Sets the issuer of the certificate associated with the received SCTs. + * Increments the reference count of issuer. + * Returns 1 on success, 0 otherwise. + */ +int CT_POLICY_EVAL_CTX_set1_issuer(CT_POLICY_EVAL_CTX *ctx, X509 *issuer); + +/* Gets the CT logs that are trusted sources of SCTs */ +const CTLOG_STORE *CT_POLICY_EVAL_CTX_get0_log_store(const CT_POLICY_EVAL_CTX *ctx); + +/* Sets the log store that is in use. It must outlive the CT_POLICY_EVAL_CTX. */ +void CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE(CT_POLICY_EVAL_CTX *ctx, + CTLOG_STORE *log_store); + +/* + * Gets the time, in milliseconds since the Unix epoch, that will be used as the + * current time when checking whether an SCT was issued in the future. + * Such SCTs will fail validation, as required by RFC6962. + */ +uint64_t CT_POLICY_EVAL_CTX_get_time(const CT_POLICY_EVAL_CTX *ctx); + +/* + * Sets the time to evaluate SCTs against, in milliseconds since the Unix epoch. + * If an SCT's timestamp is after this time, it will be interpreted as having + * been issued in the future. RFC6962 states that "TLS clients MUST reject SCTs + * whose timestamp is in the future", so an SCT will not validate in this case. + */ +void CT_POLICY_EVAL_CTX_set_time(CT_POLICY_EVAL_CTX *ctx, uint64_t time_in_ms); + +/***************** + * SCT functions * + *****************/ + +/* + * Creates a new, blank SCT. + * The caller is responsible for calling SCT_free when finished with the SCT. + */ +SCT *SCT_new(void); + +/* + * Creates a new SCT from some base64-encoded strings. + * The caller is responsible for calling SCT_free when finished with the SCT. + */ +SCT *SCT_new_from_base64(unsigned char version, + const char *logid_base64, + ct_log_entry_type_t entry_type, + uint64_t timestamp, + const char *extensions_base64, + const char *signature_base64); + +/* + * Frees the SCT and the underlying data structures. + */ +void SCT_free(SCT *sct); + +/* + * Free a stack of SCTs, and the underlying SCTs themselves. + * Intended to be compatible with X509V3_EXT_FREE. + */ +void SCT_LIST_free(STACK_OF(SCT) *a); + +/* + * Returns the version of the SCT. + */ +sct_version_t SCT_get_version(const SCT *sct); + +/* + * Set the version of an SCT. + * Returns 1 on success, 0 if the version is unrecognized. + */ +__owur int SCT_set_version(SCT *sct, sct_version_t version); + +/* + * Returns the log entry type of the SCT. + */ +ct_log_entry_type_t SCT_get_log_entry_type(const SCT *sct); + +/* + * Set the log entry type of an SCT. + * Returns 1 on success, 0 otherwise. + */ +__owur int SCT_set_log_entry_type(SCT *sct, ct_log_entry_type_t entry_type); + +/* + * Gets the ID of the log that an SCT came from. + * Ownership of the log ID remains with the SCT. + * Returns the length of the log ID. + */ +size_t SCT_get0_log_id(const SCT *sct, unsigned char **log_id); + +/* + * Set the log ID of an SCT to point directly to the *log_id specified. + * The SCT takes ownership of the specified pointer. + * Returns 1 on success, 0 otherwise. + */ +__owur int SCT_set0_log_id(SCT *sct, unsigned char *log_id, size_t log_id_len); + +/* + * Set the log ID of an SCT. + * This makes a copy of the log_id. + * Returns 1 on success, 0 otherwise. + */ +__owur int SCT_set1_log_id(SCT *sct, const unsigned char *log_id, + size_t log_id_len); + +/* + * Returns the timestamp for the SCT (epoch time in milliseconds). + */ +uint64_t SCT_get_timestamp(const SCT *sct); + +/* + * Set the timestamp of an SCT (epoch time in milliseconds). + */ +void SCT_set_timestamp(SCT *sct, uint64_t timestamp); + +/* + * Return the NID for the signature used by the SCT. + * For CT v1, this will be either NID_sha256WithRSAEncryption or + * NID_ecdsa_with_SHA256 (or NID_undef if incorrect/unset). + */ +int SCT_get_signature_nid(const SCT *sct); + +/* + * Set the signature type of an SCT + * For CT v1, this should be either NID_sha256WithRSAEncryption or + * NID_ecdsa_with_SHA256. + * Returns 1 on success, 0 otherwise. + */ +__owur int SCT_set_signature_nid(SCT *sct, int nid); + +/* + * Set *ext to point to the extension data for the SCT. ext must not be NULL. + * The SCT retains ownership of this pointer. + * Returns length of the data pointed to. + */ +size_t SCT_get0_extensions(const SCT *sct, unsigned char **ext); + +/* + * Set the extensions of an SCT to point directly to the *ext specified. + * The SCT takes ownership of the specified pointer. + */ +void SCT_set0_extensions(SCT *sct, unsigned char *ext, size_t ext_len); + +/* + * Set the extensions of an SCT. + * This takes a copy of the ext. + * Returns 1 on success, 0 otherwise. + */ +__owur int SCT_set1_extensions(SCT *sct, const unsigned char *ext, + size_t ext_len); + +/* + * Set *sig to point to the signature for the SCT. sig must not be NULL. + * The SCT retains ownership of this pointer. + * Returns length of the data pointed to. + */ +size_t SCT_get0_signature(const SCT *sct, unsigned char **sig); + +/* + * Set the signature of an SCT to point directly to the *sig specified. + * The SCT takes ownership of the specified pointer. + */ +void SCT_set0_signature(SCT *sct, unsigned char *sig, size_t sig_len); + +/* + * Set the signature of an SCT to be a copy of the *sig specified. + * Returns 1 on success, 0 otherwise. + */ +__owur int SCT_set1_signature(SCT *sct, const unsigned char *sig, + size_t sig_len); + +/* + * The origin of this SCT, e.g. TLS extension, OCSP response, etc. + */ +sct_source_t SCT_get_source(const SCT *sct); + +/* + * Set the origin of this SCT, e.g. TLS extension, OCSP response, etc. + * Returns 1 on success, 0 otherwise. + */ +__owur int SCT_set_source(SCT *sct, sct_source_t source); + +/* + * Returns a text string describing the validation status of |sct|. + */ +const char *SCT_validation_status_string(const SCT *sct); + +/* + * Pretty-prints an |sct| to |out|. + * It will be indented by the number of spaces specified by |indent|. + * If |logs| is not NULL, it will be used to lookup the CT log that the SCT came + * from, so that the log name can be printed. + */ +void SCT_print(const SCT *sct, BIO *out, int indent, const CTLOG_STORE *logs); + +/* + * Pretty-prints an |sct_list| to |out|. + * It will be indented by the number of spaces specified by |indent|. + * SCTs will be delimited by |separator|. + * If |logs| is not NULL, it will be used to lookup the CT log that each SCT + * came from, so that the log names can be printed. + */ +void SCT_LIST_print(const STACK_OF(SCT) *sct_list, BIO *out, int indent, + const char *separator, const CTLOG_STORE *logs); + +/* + * Gets the last result of validating this SCT. + * If it has not been validated yet, returns SCT_VALIDATION_STATUS_NOT_SET. + */ +sct_validation_status_t SCT_get_validation_status(const SCT *sct); + +/* + * Validates the given SCT with the provided context. + * Sets the "validation_status" field of the SCT. + * Returns 1 if the SCT is valid and the signature verifies. + * Returns 0 if the SCT is invalid or could not be verified. + * Returns -1 if an error occurs. + */ +__owur int SCT_validate(SCT *sct, const CT_POLICY_EVAL_CTX *ctx); + +/* + * Validates the given list of SCTs with the provided context. + * Sets the "validation_status" field of each SCT. + * Returns 1 if there are no invalid SCTs and all signatures verify. + * Returns 0 if at least one SCT is invalid or could not be verified. + * Returns a negative integer if an error occurs. + */ +__owur int SCT_LIST_validate(const STACK_OF(SCT) *scts, + CT_POLICY_EVAL_CTX *ctx); + + +/********************************* + * SCT parsing and serialisation * + *********************************/ + +/* + * Serialize (to TLS format) a stack of SCTs and return the length. + * "a" must not be NULL. + * If "pp" is NULL, just return the length of what would have been serialized. + * If "pp" is not NULL and "*pp" is null, function will allocate a new pointer + * for data that caller is responsible for freeing (only if function returns + * successfully). + * If "pp" is NULL and "*pp" is not NULL, caller is responsible for ensuring + * that "*pp" is large enough to accept all of the serialized data. + * Returns < 0 on error, >= 0 indicating bytes written (or would have been) + * on success. + */ +__owur int i2o_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **pp); + +/* + * Convert TLS format SCT list to a stack of SCTs. + * If "a" or "*a" is NULL, a new stack will be created that the caller is + * responsible for freeing (by calling SCT_LIST_free). + * "**pp" and "*pp" must not be NULL. + * Upon success, "*pp" will point to after the last bytes read, and a stack + * will be returned. + * Upon failure, a NULL pointer will be returned, and the position of "*pp" is + * not defined. + */ +STACK_OF(SCT) *o2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp, + size_t len); + +/* + * Serialize (to DER format) a stack of SCTs and return the length. + * "a" must not be NULL. + * If "pp" is NULL, just returns the length of what would have been serialized. + * If "pp" is not NULL and "*pp" is null, function will allocate a new pointer + * for data that caller is responsible for freeing (only if function returns + * successfully). + * If "pp" is NULL and "*pp" is not NULL, caller is responsible for ensuring + * that "*pp" is large enough to accept all of the serialized data. + * Returns < 0 on error, >= 0 indicating bytes written (or would have been) + * on success. + */ +__owur int i2d_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **pp); + +/* + * Parses an SCT list in DER format and returns it. + * If "a" or "*a" is NULL, a new stack will be created that the caller is + * responsible for freeing (by calling SCT_LIST_free). + * "**pp" and "*pp" must not be NULL. + * Upon success, "*pp" will point to after the last bytes read, and a stack + * will be returned. + * Upon failure, a NULL pointer will be returned, and the position of "*pp" is + * not defined. + */ +STACK_OF(SCT) *d2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp, + long len); + +/* + * Serialize (to TLS format) an |sct| and write it to |out|. + * If |out| is null, no SCT will be output but the length will still be returned. + * If |out| points to a null pointer, a string will be allocated to hold the + * TLS-format SCT. It is the responsibility of the caller to free it. + * If |out| points to an allocated string, the TLS-format SCT will be written + * to it. + * The length of the SCT in TLS format will be returned. + */ +__owur int i2o_SCT(const SCT *sct, unsigned char **out); + +/* + * Parses an SCT in TLS format and returns it. + * If |psct| is not null, it will end up pointing to the parsed SCT. If it + * already points to a non-null pointer, the pointer will be free'd. + * |in| should be a pointer to a string containing the TLS-format SCT. + * |in| will be advanced to the end of the SCT if parsing succeeds. + * |len| should be the length of the SCT in |in|. + * Returns NULL if an error occurs. + * If the SCT is an unsupported version, only the SCT's 'sct' and 'sct_len' + * fields will be populated (with |in| and |len| respectively). + */ +SCT *o2i_SCT(SCT **psct, const unsigned char **in, size_t len); + +/******************** + * CT log functions * + ********************/ + +/* + * Creates a new CT log instance with the given |public_key| and |name|. + * Takes ownership of |public_key| but copies |name|. + * Returns NULL if malloc fails or if |public_key| cannot be converted to DER. + * Should be deleted by the caller using CTLOG_free when no longer needed. + */ +CTLOG *CTLOG_new(EVP_PKEY *public_key, const char *name); + +/* + * Creates a new CTLOG instance with the base64-encoded SubjectPublicKeyInfo DER + * in |pkey_base64|. The |name| is a string to help users identify this log. + * Returns 1 on success, 0 on failure. + * Should be deleted by the caller using CTLOG_free when no longer needed. + */ +int CTLOG_new_from_base64(CTLOG ** ct_log, + const char *pkey_base64, const char *name); + +/* + * Deletes a CT log instance and its fields. + */ +void CTLOG_free(CTLOG *log); + +/* Gets the name of the CT log */ +const char *CTLOG_get0_name(const CTLOG *log); +/* Gets the ID of the CT log */ +void CTLOG_get0_log_id(const CTLOG *log, const uint8_t **log_id, + size_t *log_id_len); +/* Gets the public key of the CT log */ +EVP_PKEY *CTLOG_get0_public_key(const CTLOG *log); + +/************************** + * CT log store functions * + **************************/ + +/* + * Creates a new CT log store. + * Should be deleted by the caller using CTLOG_STORE_free when no longer needed. + */ +CTLOG_STORE *CTLOG_STORE_new(void); + +/* + * Deletes a CT log store and all of the CT log instances held within. + */ +void CTLOG_STORE_free(CTLOG_STORE *store); + +/* + * Finds a CT log in the store based on its log ID. + * Returns the CT log, or NULL if no match is found. + */ +const CTLOG *CTLOG_STORE_get0_log_by_id(const CTLOG_STORE *store, + const uint8_t *log_id, + size_t log_id_len); + +/* + * Loads a CT log list into a |store| from a |file|. + * Returns 1 if loading is successful, or 0 otherwise. + */ +__owur int CTLOG_STORE_load_file(CTLOG_STORE *store, const char *file); + +/* + * Loads the default CT log list into a |store|. + * See internal/cryptlib.h for the environment variable and file path that are + * consulted to find the default file. + * Returns 1 if loading is successful, or 0 otherwise. + */ +__owur int CTLOG_STORE_load_default_file(CTLOG_STORE *store); + +# ifdef __cplusplus +} +# endif +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/cterr.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/cterr.h new file mode 100644 index 000000000..764e1a220 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/cterr.h @@ -0,0 +1,76 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_CTERR_H +# define HEADER_CTERR_H + +# include + +# ifndef OPENSSL_NO_CT + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_CT_strings(void); + +/* + * CT function codes. + */ +# define CT_F_CTLOG_NEW 117 +# define CT_F_CTLOG_NEW_FROM_BASE64 118 +# define CT_F_CTLOG_NEW_FROM_CONF 119 +# define CT_F_CTLOG_STORE_LOAD_CTX_NEW 122 +# define CT_F_CTLOG_STORE_LOAD_FILE 123 +# define CT_F_CTLOG_STORE_LOAD_LOG 130 +# define CT_F_CTLOG_STORE_NEW 131 +# define CT_F_CT_BASE64_DECODE 124 +# define CT_F_CT_POLICY_EVAL_CTX_NEW 133 +# define CT_F_CT_V1_LOG_ID_FROM_PKEY 125 +# define CT_F_I2O_SCT 107 +# define CT_F_I2O_SCT_LIST 108 +# define CT_F_I2O_SCT_SIGNATURE 109 +# define CT_F_O2I_SCT 110 +# define CT_F_O2I_SCT_LIST 111 +# define CT_F_O2I_SCT_SIGNATURE 112 +# define CT_F_SCT_CTX_NEW 126 +# define CT_F_SCT_CTX_VERIFY 128 +# define CT_F_SCT_NEW 100 +# define CT_F_SCT_NEW_FROM_BASE64 127 +# define CT_F_SCT_SET0_LOG_ID 101 +# define CT_F_SCT_SET1_EXTENSIONS 114 +# define CT_F_SCT_SET1_LOG_ID 115 +# define CT_F_SCT_SET1_SIGNATURE 116 +# define CT_F_SCT_SET_LOG_ENTRY_TYPE 102 +# define CT_F_SCT_SET_SIGNATURE_NID 103 +# define CT_F_SCT_SET_VERSION 104 + +/* + * CT reason codes. + */ +# define CT_R_BASE64_DECODE_ERROR 108 +# define CT_R_INVALID_LOG_ID_LENGTH 100 +# define CT_R_LOG_CONF_INVALID 109 +# define CT_R_LOG_CONF_INVALID_KEY 110 +# define CT_R_LOG_CONF_MISSING_DESCRIPTION 111 +# define CT_R_LOG_CONF_MISSING_KEY 112 +# define CT_R_LOG_KEY_INVALID 113 +# define CT_R_SCT_FUTURE_TIMESTAMP 116 +# define CT_R_SCT_INVALID 104 +# define CT_R_SCT_INVALID_SIGNATURE 107 +# define CT_R_SCT_LIST_INVALID 105 +# define CT_R_SCT_LOG_ID_MISMATCH 114 +# define CT_R_SCT_NOT_SET 106 +# define CT_R_SCT_UNSUPPORTED_VERSION 115 +# define CT_R_UNRECOGNIZED_SIGNATURE_NID 101 +# define CT_R_UNSUPPORTED_ENTRY_TYPE 102 +# define CT_R_UNSUPPORTED_VERSION 103 + +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/des.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/des.h new file mode 100644 index 000000000..be4abbdfd --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/des.h @@ -0,0 +1,174 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_DES_H +# define HEADER_DES_H + +# include + +# ifndef OPENSSL_NO_DES +# ifdef __cplusplus +extern "C" { +# endif +# include + +typedef unsigned int DES_LONG; + +# ifdef OPENSSL_BUILD_SHLIBCRYPTO +# undef OPENSSL_EXTERN +# define OPENSSL_EXTERN OPENSSL_EXPORT +# endif + +typedef unsigned char DES_cblock[8]; +typedef /* const */ unsigned char const_DES_cblock[8]; +/* + * With "const", gcc 2.8.1 on Solaris thinks that DES_cblock * and + * const_DES_cblock * are incompatible pointer types. + */ + +typedef struct DES_ks { + union { + DES_cblock cblock; + /* + * make sure things are correct size on machines with 8 byte longs + */ + DES_LONG deslong[2]; + } ks[16]; +} DES_key_schedule; + +# define DES_KEY_SZ (sizeof(DES_cblock)) +# define DES_SCHEDULE_SZ (sizeof(DES_key_schedule)) + +# define DES_ENCRYPT 1 +# define DES_DECRYPT 0 + +# define DES_CBC_MODE 0 +# define DES_PCBC_MODE 1 + +# define DES_ecb2_encrypt(i,o,k1,k2,e) \ + DES_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e)) + +# define DES_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \ + DES_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e)) + +# define DES_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \ + DES_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e)) + +# define DES_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \ + DES_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n)) + +OPENSSL_DECLARE_GLOBAL(int, DES_check_key); /* defaults to false */ +# define DES_check_key OPENSSL_GLOBAL_REF(DES_check_key) + +const char *DES_options(void); +void DES_ecb3_encrypt(const_DES_cblock *input, DES_cblock *output, + DES_key_schedule *ks1, DES_key_schedule *ks2, + DES_key_schedule *ks3, int enc); +DES_LONG DES_cbc_cksum(const unsigned char *input, DES_cblock *output, + long length, DES_key_schedule *schedule, + const_DES_cblock *ivec); +/* DES_cbc_encrypt does not update the IV! Use DES_ncbc_encrypt instead. */ +void DES_cbc_encrypt(const unsigned char *input, unsigned char *output, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, int enc); +void DES_ncbc_encrypt(const unsigned char *input, unsigned char *output, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, int enc); +void DES_xcbc_encrypt(const unsigned char *input, unsigned char *output, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, const_DES_cblock *inw, + const_DES_cblock *outw, int enc); +void DES_cfb_encrypt(const unsigned char *in, unsigned char *out, int numbits, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, int enc); +void DES_ecb_encrypt(const_DES_cblock *input, DES_cblock *output, + DES_key_schedule *ks, int enc); + +/* + * This is the DES encryption function that gets called by just about every + * other DES routine in the library. You should not use this function except + * to implement 'modes' of DES. I say this because the functions that call + * this routine do the conversion from 'char *' to long, and this needs to be + * done to make sure 'non-aligned' memory access do not occur. The + * characters are loaded 'little endian'. Data is a pointer to 2 unsigned + * long's and ks is the DES_key_schedule to use. enc, is non zero specifies + * encryption, zero if decryption. + */ +void DES_encrypt1(DES_LONG *data, DES_key_schedule *ks, int enc); + +/* + * This functions is the same as DES_encrypt1() except that the DES initial + * permutation (IP) and final permutation (FP) have been left out. As for + * DES_encrypt1(), you should not use this function. It is used by the + * routines in the library that implement triple DES. IP() DES_encrypt2() + * DES_encrypt2() DES_encrypt2() FP() is the same as DES_encrypt1() + * DES_encrypt1() DES_encrypt1() except faster :-). + */ +void DES_encrypt2(DES_LONG *data, DES_key_schedule *ks, int enc); + +void DES_encrypt3(DES_LONG *data, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3); +void DES_decrypt3(DES_LONG *data, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3); +void DES_ede3_cbc_encrypt(const unsigned char *input, unsigned char *output, + long length, + DES_key_schedule *ks1, DES_key_schedule *ks2, + DES_key_schedule *ks3, DES_cblock *ivec, int enc); +void DES_ede3_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3, + DES_cblock *ivec, int *num, int enc); +void DES_ede3_cfb_encrypt(const unsigned char *in, unsigned char *out, + int numbits, long length, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3, + DES_cblock *ivec, int enc); +void DES_ede3_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3, + DES_cblock *ivec, int *num); +char *DES_fcrypt(const char *buf, const char *salt, char *ret); +char *DES_crypt(const char *buf, const char *salt); +void DES_ofb_encrypt(const unsigned char *in, unsigned char *out, int numbits, + long length, DES_key_schedule *schedule, + DES_cblock *ivec); +void DES_pcbc_encrypt(const unsigned char *input, unsigned char *output, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, int enc); +DES_LONG DES_quad_cksum(const unsigned char *input, DES_cblock output[], + long length, int out_count, DES_cblock *seed); +int DES_random_key(DES_cblock *ret); +void DES_set_odd_parity(DES_cblock *key); +int DES_check_key_parity(const_DES_cblock *key); +int DES_is_weak_key(const_DES_cblock *key); +/* + * DES_set_key (= set_key = DES_key_sched = key_sched) calls + * DES_set_key_checked if global variable DES_check_key is set, + * DES_set_key_unchecked otherwise. + */ +int DES_set_key(const_DES_cblock *key, DES_key_schedule *schedule); +int DES_key_sched(const_DES_cblock *key, DES_key_schedule *schedule); +int DES_set_key_checked(const_DES_cblock *key, DES_key_schedule *schedule); +void DES_set_key_unchecked(const_DES_cblock *key, DES_key_schedule *schedule); +void DES_string_to_key(const char *str, DES_cblock *key); +void DES_string_to_2keys(const char *str, DES_cblock *key1, DES_cblock *key2); +void DES_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, int *num, int enc); +void DES_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, int *num); + +# define DES_fixup_key_parity DES_set_odd_parity + +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/dh.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/dh.h new file mode 100644 index 000000000..3527540cd --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/dh.h @@ -0,0 +1,340 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_DH_H +# define HEADER_DH_H + +# include + +# ifndef OPENSSL_NO_DH +# include +# include +# include +# include +# if OPENSSL_API_COMPAT < 0x10100000L +# include +# endif +# include + +# ifdef __cplusplus +extern "C" { +# endif + +# ifndef OPENSSL_DH_MAX_MODULUS_BITS +# define OPENSSL_DH_MAX_MODULUS_BITS 10000 +# endif + +# define OPENSSL_DH_FIPS_MIN_MODULUS_BITS 1024 + +# define DH_FLAG_CACHE_MONT_P 0x01 + +# if OPENSSL_API_COMPAT < 0x10100000L +/* + * Does nothing. Previously this switched off constant time behaviour. + */ +# define DH_FLAG_NO_EXP_CONSTTIME 0x00 +# endif + +/* + * If this flag is set the DH method is FIPS compliant and can be used in + * FIPS mode. This is set in the validated module method. If an application + * sets this flag in its own methods it is its responsibility to ensure the + * result is compliant. + */ + +# define DH_FLAG_FIPS_METHOD 0x0400 + +/* + * If this flag is set the operations normally disabled in FIPS mode are + * permitted it is then the applications responsibility to ensure that the + * usage is compliant. + */ + +# define DH_FLAG_NON_FIPS_ALLOW 0x0400 + +/* Already defined in ossl_typ.h */ +/* typedef struct dh_st DH; */ +/* typedef struct dh_method DH_METHOD; */ + +DECLARE_ASN1_ITEM(DHparams) + +# define DH_GENERATOR_2 2 +/* #define DH_GENERATOR_3 3 */ +# define DH_GENERATOR_5 5 + +/* DH_check error codes */ +# define DH_CHECK_P_NOT_PRIME 0x01 +# define DH_CHECK_P_NOT_SAFE_PRIME 0x02 +# define DH_UNABLE_TO_CHECK_GENERATOR 0x04 +# define DH_NOT_SUITABLE_GENERATOR 0x08 +# define DH_CHECK_Q_NOT_PRIME 0x10 +# define DH_CHECK_INVALID_Q_VALUE 0x20 +# define DH_CHECK_INVALID_J_VALUE 0x40 + +/* DH_check_pub_key error codes */ +# define DH_CHECK_PUBKEY_TOO_SMALL 0x01 +# define DH_CHECK_PUBKEY_TOO_LARGE 0x02 +# define DH_CHECK_PUBKEY_INVALID 0x04 + +/* + * primes p where (p-1)/2 is prime too are called "safe"; we define this for + * backward compatibility: + */ +# define DH_CHECK_P_NOT_STRONG_PRIME DH_CHECK_P_NOT_SAFE_PRIME + +# define d2i_DHparams_fp(fp,x) \ + (DH *)ASN1_d2i_fp((char *(*)())DH_new, \ + (char *(*)())d2i_DHparams, \ + (fp), \ + (unsigned char **)(x)) +# define i2d_DHparams_fp(fp,x) \ + ASN1_i2d_fp(i2d_DHparams,(fp), (unsigned char *)(x)) +# define d2i_DHparams_bio(bp,x) \ + ASN1_d2i_bio_of(DH, DH_new, d2i_DHparams, bp, x) +# define i2d_DHparams_bio(bp,x) \ + ASN1_i2d_bio_of_const(DH,i2d_DHparams,bp,x) + +# define d2i_DHxparams_fp(fp,x) \ + (DH *)ASN1_d2i_fp((char *(*)())DH_new, \ + (char *(*)())d2i_DHxparams, \ + (fp), \ + (unsigned char **)(x)) +# define i2d_DHxparams_fp(fp,x) \ + ASN1_i2d_fp(i2d_DHxparams,(fp), (unsigned char *)(x)) +# define d2i_DHxparams_bio(bp,x) \ + ASN1_d2i_bio_of(DH, DH_new, d2i_DHxparams, bp, x) +# define i2d_DHxparams_bio(bp,x) \ + ASN1_i2d_bio_of_const(DH, i2d_DHxparams, bp, x) + +DH *DHparams_dup(DH *); + +const DH_METHOD *DH_OpenSSL(void); + +void DH_set_default_method(const DH_METHOD *meth); +const DH_METHOD *DH_get_default_method(void); +int DH_set_method(DH *dh, const DH_METHOD *meth); +DH *DH_new_method(ENGINE *engine); + +DH *DH_new(void); +void DH_free(DH *dh); +int DH_up_ref(DH *dh); +int DH_bits(const DH *dh); +int DH_size(const DH *dh); +int DH_security_bits(const DH *dh); +#define DH_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DH, l, p, newf, dupf, freef) +int DH_set_ex_data(DH *d, int idx, void *arg); +void *DH_get_ex_data(DH *d, int idx); + +/* Deprecated version */ +DEPRECATEDIN_0_9_8(DH *DH_generate_parameters(int prime_len, int generator, + void (*callback) (int, int, + void *), + void *cb_arg)) + +/* New version */ +int DH_generate_parameters_ex(DH *dh, int prime_len, int generator, + BN_GENCB *cb); + +int DH_check_params_ex(const DH *dh); +int DH_check_ex(const DH *dh); +int DH_check_pub_key_ex(const DH *dh, const BIGNUM *pub_key); +int DH_check_params(const DH *dh, int *ret); +int DH_check(const DH *dh, int *codes); +int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *codes); +int DH_generate_key(DH *dh); +int DH_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh); +int DH_compute_key_padded(unsigned char *key, const BIGNUM *pub_key, DH *dh); +DH *d2i_DHparams(DH **a, const unsigned char **pp, long length); +int i2d_DHparams(const DH *a, unsigned char **pp); +DH *d2i_DHxparams(DH **a, const unsigned char **pp, long length); +int i2d_DHxparams(const DH *a, unsigned char **pp); +# ifndef OPENSSL_NO_STDIO +int DHparams_print_fp(FILE *fp, const DH *x); +# endif +int DHparams_print(BIO *bp, const DH *x); + +/* RFC 5114 parameters */ +DH *DH_get_1024_160(void); +DH *DH_get_2048_224(void); +DH *DH_get_2048_256(void); + +/* Named parameters, currently RFC7919 */ +DH *DH_new_by_nid(int nid); +int DH_get_nid(const DH *dh); + +# ifndef OPENSSL_NO_CMS +/* RFC2631 KDF */ +int DH_KDF_X9_42(unsigned char *out, size_t outlen, + const unsigned char *Z, size_t Zlen, + ASN1_OBJECT *key_oid, + const unsigned char *ukm, size_t ukmlen, const EVP_MD *md); +# endif + +void DH_get0_pqg(const DH *dh, + const BIGNUM **p, const BIGNUM **q, const BIGNUM **g); +int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g); +void DH_get0_key(const DH *dh, + const BIGNUM **pub_key, const BIGNUM **priv_key); +int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key); +const BIGNUM *DH_get0_p(const DH *dh); +const BIGNUM *DH_get0_q(const DH *dh); +const BIGNUM *DH_get0_g(const DH *dh); +const BIGNUM *DH_get0_priv_key(const DH *dh); +const BIGNUM *DH_get0_pub_key(const DH *dh); +void DH_clear_flags(DH *dh, int flags); +int DH_test_flags(const DH *dh, int flags); +void DH_set_flags(DH *dh, int flags); +ENGINE *DH_get0_engine(DH *d); +long DH_get_length(const DH *dh); +int DH_set_length(DH *dh, long length); + +DH_METHOD *DH_meth_new(const char *name, int flags); +void DH_meth_free(DH_METHOD *dhm); +DH_METHOD *DH_meth_dup(const DH_METHOD *dhm); +const char *DH_meth_get0_name(const DH_METHOD *dhm); +int DH_meth_set1_name(DH_METHOD *dhm, const char *name); +int DH_meth_get_flags(const DH_METHOD *dhm); +int DH_meth_set_flags(DH_METHOD *dhm, int flags); +void *DH_meth_get0_app_data(const DH_METHOD *dhm); +int DH_meth_set0_app_data(DH_METHOD *dhm, void *app_data); +int (*DH_meth_get_generate_key(const DH_METHOD *dhm)) (DH *); +int DH_meth_set_generate_key(DH_METHOD *dhm, int (*generate_key) (DH *)); +int (*DH_meth_get_compute_key(const DH_METHOD *dhm)) + (unsigned char *key, const BIGNUM *pub_key, DH *dh); +int DH_meth_set_compute_key(DH_METHOD *dhm, + int (*compute_key) (unsigned char *key, const BIGNUM *pub_key, DH *dh)); +int (*DH_meth_get_bn_mod_exp(const DH_METHOD *dhm)) + (const DH *, BIGNUM *, const BIGNUM *, const BIGNUM *, const BIGNUM *, + BN_CTX *, BN_MONT_CTX *); +int DH_meth_set_bn_mod_exp(DH_METHOD *dhm, + int (*bn_mod_exp) (const DH *, BIGNUM *, const BIGNUM *, const BIGNUM *, + const BIGNUM *, BN_CTX *, BN_MONT_CTX *)); +int (*DH_meth_get_init(const DH_METHOD *dhm))(DH *); +int DH_meth_set_init(DH_METHOD *dhm, int (*init)(DH *)); +int (*DH_meth_get_finish(const DH_METHOD *dhm)) (DH *); +int DH_meth_set_finish(DH_METHOD *dhm, int (*finish) (DH *)); +int (*DH_meth_get_generate_params(const DH_METHOD *dhm)) + (DH *, int, int, BN_GENCB *); +int DH_meth_set_generate_params(DH_METHOD *dhm, + int (*generate_params) (DH *, int, int, BN_GENCB *)); + + +# define EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, \ + EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN, len, NULL) + +# define EVP_PKEY_CTX_set_dh_paramgen_subprime_len(ctx, len) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, \ + EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN, len, NULL) + +# define EVP_PKEY_CTX_set_dh_paramgen_type(ctx, typ) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, \ + EVP_PKEY_CTRL_DH_PARAMGEN_TYPE, typ, NULL) + +# define EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, gen) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, \ + EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR, gen, NULL) + +# define EVP_PKEY_CTX_set_dh_rfc5114(ctx, gen) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_PARAMGEN, \ + EVP_PKEY_CTRL_DH_RFC5114, gen, NULL) + +# define EVP_PKEY_CTX_set_dhx_rfc5114(ctx, gen) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_PARAMGEN, \ + EVP_PKEY_CTRL_DH_RFC5114, gen, NULL) + +# define EVP_PKEY_CTX_set_dh_nid(ctx, nid) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, \ + EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN, \ + EVP_PKEY_CTRL_DH_NID, nid, NULL) + +# define EVP_PKEY_CTX_set_dh_pad(ctx, pad) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_DH_PAD, pad, NULL) + +# define EVP_PKEY_CTX_set_dh_kdf_type(ctx, kdf) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_DH_KDF_TYPE, kdf, NULL) + +# define EVP_PKEY_CTX_get_dh_kdf_type(ctx) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_DH_KDF_TYPE, -2, NULL) + +# define EVP_PKEY_CTX_set0_dh_kdf_oid(ctx, oid) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_DH_KDF_OID, 0, (void *)(oid)) + +# define EVP_PKEY_CTX_get0_dh_kdf_oid(ctx, poid) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_GET_DH_KDF_OID, 0, (void *)(poid)) + +# define EVP_PKEY_CTX_set_dh_kdf_md(ctx, md) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_DH_KDF_MD, 0, (void *)(md)) + +# define EVP_PKEY_CTX_get_dh_kdf_md(ctx, pmd) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_GET_DH_KDF_MD, 0, (void *)(pmd)) + +# define EVP_PKEY_CTX_set_dh_kdf_outlen(ctx, len) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_DH_KDF_OUTLEN, len, NULL) + +# define EVP_PKEY_CTX_get_dh_kdf_outlen(ctx, plen) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN, 0, (void *)(plen)) + +# define EVP_PKEY_CTX_set0_dh_kdf_ukm(ctx, p, plen) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_DH_KDF_UKM, plen, (void *)(p)) + +# define EVP_PKEY_CTX_get0_dh_kdf_ukm(ctx, p) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_GET_DH_KDF_UKM, 0, (void *)(p)) + +# define EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN (EVP_PKEY_ALG_CTRL + 1) +# define EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR (EVP_PKEY_ALG_CTRL + 2) +# define EVP_PKEY_CTRL_DH_RFC5114 (EVP_PKEY_ALG_CTRL + 3) +# define EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN (EVP_PKEY_ALG_CTRL + 4) +# define EVP_PKEY_CTRL_DH_PARAMGEN_TYPE (EVP_PKEY_ALG_CTRL + 5) +# define EVP_PKEY_CTRL_DH_KDF_TYPE (EVP_PKEY_ALG_CTRL + 6) +# define EVP_PKEY_CTRL_DH_KDF_MD (EVP_PKEY_ALG_CTRL + 7) +# define EVP_PKEY_CTRL_GET_DH_KDF_MD (EVP_PKEY_ALG_CTRL + 8) +# define EVP_PKEY_CTRL_DH_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 9) +# define EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 10) +# define EVP_PKEY_CTRL_DH_KDF_UKM (EVP_PKEY_ALG_CTRL + 11) +# define EVP_PKEY_CTRL_GET_DH_KDF_UKM (EVP_PKEY_ALG_CTRL + 12) +# define EVP_PKEY_CTRL_DH_KDF_OID (EVP_PKEY_ALG_CTRL + 13) +# define EVP_PKEY_CTRL_GET_DH_KDF_OID (EVP_PKEY_ALG_CTRL + 14) +# define EVP_PKEY_CTRL_DH_NID (EVP_PKEY_ALG_CTRL + 15) +# define EVP_PKEY_CTRL_DH_PAD (EVP_PKEY_ALG_CTRL + 16) + +/* KDF types */ +# define EVP_PKEY_DH_KDF_NONE 1 +# ifndef OPENSSL_NO_CMS +# define EVP_PKEY_DH_KDF_X9_42 2 +# endif + + +# ifdef __cplusplus +} +# endif +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/dherr.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/dherr.h new file mode 100644 index 000000000..81e73f75c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/dherr.h @@ -0,0 +1,84 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_DHERR_H +# define HEADER_DHERR_H + +# include + +# ifndef OPENSSL_NO_DH + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_DH_strings(void); + +/* + * DH function codes. + */ +# define DH_F_COMPUTE_KEY 102 +# define DH_F_DHPARAMS_PRINT_FP 101 +# define DH_F_DH_BUILTIN_GENPARAMS 106 +# define DH_F_DH_CHECK_EX 121 +# define DH_F_DH_CHECK_PARAMS_EX 122 +# define DH_F_DH_CHECK_PUB_KEY_EX 123 +# define DH_F_DH_CMS_DECRYPT 114 +# define DH_F_DH_CMS_SET_PEERKEY 115 +# define DH_F_DH_CMS_SET_SHARED_INFO 116 +# define DH_F_DH_METH_DUP 117 +# define DH_F_DH_METH_NEW 118 +# define DH_F_DH_METH_SET1_NAME 119 +# define DH_F_DH_NEW_BY_NID 104 +# define DH_F_DH_NEW_METHOD 105 +# define DH_F_DH_PARAM_DECODE 107 +# define DH_F_DH_PKEY_PUBLIC_CHECK 124 +# define DH_F_DH_PRIV_DECODE 110 +# define DH_F_DH_PRIV_ENCODE 111 +# define DH_F_DH_PUB_DECODE 108 +# define DH_F_DH_PUB_ENCODE 109 +# define DH_F_DO_DH_PRINT 100 +# define DH_F_GENERATE_KEY 103 +# define DH_F_PKEY_DH_CTRL_STR 120 +# define DH_F_PKEY_DH_DERIVE 112 +# define DH_F_PKEY_DH_INIT 125 +# define DH_F_PKEY_DH_KEYGEN 113 + +/* + * DH reason codes. + */ +# define DH_R_BAD_GENERATOR 101 +# define DH_R_BN_DECODE_ERROR 109 +# define DH_R_BN_ERROR 106 +# define DH_R_CHECK_INVALID_J_VALUE 115 +# define DH_R_CHECK_INVALID_Q_VALUE 116 +# define DH_R_CHECK_PUBKEY_INVALID 122 +# define DH_R_CHECK_PUBKEY_TOO_LARGE 123 +# define DH_R_CHECK_PUBKEY_TOO_SMALL 124 +# define DH_R_CHECK_P_NOT_PRIME 117 +# define DH_R_CHECK_P_NOT_SAFE_PRIME 118 +# define DH_R_CHECK_Q_NOT_PRIME 119 +# define DH_R_DECODE_ERROR 104 +# define DH_R_INVALID_PARAMETER_NAME 110 +# define DH_R_INVALID_PARAMETER_NID 114 +# define DH_R_INVALID_PUBKEY 102 +# define DH_R_KDF_PARAMETER_ERROR 112 +# define DH_R_KEYS_NOT_SET 108 +# define DH_R_MISSING_PUBKEY 125 +# define DH_R_MODULUS_TOO_LARGE 103 +# define DH_R_NOT_SUITABLE_GENERATOR 120 +# define DH_R_NO_PARAMETERS_SET 107 +# define DH_R_NO_PRIVATE_VALUE 100 +# define DH_R_PARAMETER_ENCODING_ERROR 105 +# define DH_R_PEER_KEY_ERROR 111 +# define DH_R_SHARED_INFO_ERROR 113 +# define DH_R_UNABLE_TO_CHECK_GENERATOR 121 + +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/dsa.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/dsa.h new file mode 100644 index 000000000..822eff347 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/dsa.h @@ -0,0 +1,238 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_DSA_H +# define HEADER_DSA_H + +# include + +# ifndef OPENSSL_NO_DSA +# ifdef __cplusplus +extern "C" { +# endif +# include +# include +# include +# include +# include +# if OPENSSL_API_COMPAT < 0x10100000L +# include +# endif +# include + +# ifndef OPENSSL_DSA_MAX_MODULUS_BITS +# define OPENSSL_DSA_MAX_MODULUS_BITS 10000 +# endif + +# define OPENSSL_DSA_FIPS_MIN_MODULUS_BITS 1024 + +# define DSA_FLAG_CACHE_MONT_P 0x01 +# if OPENSSL_API_COMPAT < 0x10100000L +/* + * Does nothing. Previously this switched off constant time behaviour. + */ +# define DSA_FLAG_NO_EXP_CONSTTIME 0x00 +# endif + +/* + * If this flag is set the DSA method is FIPS compliant and can be used in + * FIPS mode. This is set in the validated module method. If an application + * sets this flag in its own methods it is its responsibility to ensure the + * result is compliant. + */ + +# define DSA_FLAG_FIPS_METHOD 0x0400 + +/* + * If this flag is set the operations normally disabled in FIPS mode are + * permitted it is then the applications responsibility to ensure that the + * usage is compliant. + */ + +# define DSA_FLAG_NON_FIPS_ALLOW 0x0400 +# define DSA_FLAG_FIPS_CHECKED 0x0800 + +/* Already defined in ossl_typ.h */ +/* typedef struct dsa_st DSA; */ +/* typedef struct dsa_method DSA_METHOD; */ + +typedef struct DSA_SIG_st DSA_SIG; + +# define d2i_DSAparams_fp(fp,x) (DSA *)ASN1_d2i_fp((char *(*)())DSA_new, \ + (char *(*)())d2i_DSAparams,(fp),(unsigned char **)(x)) +# define i2d_DSAparams_fp(fp,x) ASN1_i2d_fp(i2d_DSAparams,(fp), \ + (unsigned char *)(x)) +# define d2i_DSAparams_bio(bp,x) ASN1_d2i_bio_of(DSA,DSA_new,d2i_DSAparams,bp,x) +# define i2d_DSAparams_bio(bp,x) ASN1_i2d_bio_of_const(DSA,i2d_DSAparams,bp,x) + +DSA *DSAparams_dup(DSA *x); +DSA_SIG *DSA_SIG_new(void); +void DSA_SIG_free(DSA_SIG *a); +int i2d_DSA_SIG(const DSA_SIG *a, unsigned char **pp); +DSA_SIG *d2i_DSA_SIG(DSA_SIG **v, const unsigned char **pp, long length); +void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps); +int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s); + +DSA_SIG *DSA_do_sign(const unsigned char *dgst, int dlen, DSA *dsa); +int DSA_do_verify(const unsigned char *dgst, int dgst_len, + DSA_SIG *sig, DSA *dsa); + +const DSA_METHOD *DSA_OpenSSL(void); + +void DSA_set_default_method(const DSA_METHOD *); +const DSA_METHOD *DSA_get_default_method(void); +int DSA_set_method(DSA *dsa, const DSA_METHOD *); +const DSA_METHOD *DSA_get_method(DSA *d); + +DSA *DSA_new(void); +DSA *DSA_new_method(ENGINE *engine); +void DSA_free(DSA *r); +/* "up" the DSA object's reference count */ +int DSA_up_ref(DSA *r); +int DSA_size(const DSA *); +int DSA_bits(const DSA *d); +int DSA_security_bits(const DSA *d); + /* next 4 return -1 on error */ +DEPRECATEDIN_1_2_0(int DSA_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)) +int DSA_sign(int type, const unsigned char *dgst, int dlen, + unsigned char *sig, unsigned int *siglen, DSA *dsa); +int DSA_verify(int type, const unsigned char *dgst, int dgst_len, + const unsigned char *sigbuf, int siglen, DSA *dsa); +#define DSA_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DSA, l, p, newf, dupf, freef) +int DSA_set_ex_data(DSA *d, int idx, void *arg); +void *DSA_get_ex_data(DSA *d, int idx); + +DSA *d2i_DSAPublicKey(DSA **a, const unsigned char **pp, long length); +DSA *d2i_DSAPrivateKey(DSA **a, const unsigned char **pp, long length); +DSA *d2i_DSAparams(DSA **a, const unsigned char **pp, long length); + +/* Deprecated version */ +DEPRECATEDIN_0_9_8(DSA *DSA_generate_parameters(int bits, + unsigned char *seed, + int seed_len, + int *counter_ret, + unsigned long *h_ret, void + (*callback) (int, int, + void *), + void *cb_arg)) + +/* New version */ +int DSA_generate_parameters_ex(DSA *dsa, int bits, + const unsigned char *seed, int seed_len, + int *counter_ret, unsigned long *h_ret, + BN_GENCB *cb); + +int DSA_generate_key(DSA *a); +int i2d_DSAPublicKey(const DSA *a, unsigned char **pp); +int i2d_DSAPrivateKey(const DSA *a, unsigned char **pp); +int i2d_DSAparams(const DSA *a, unsigned char **pp); + +int DSAparams_print(BIO *bp, const DSA *x); +int DSA_print(BIO *bp, const DSA *x, int off); +# ifndef OPENSSL_NO_STDIO +int DSAparams_print_fp(FILE *fp, const DSA *x); +int DSA_print_fp(FILE *bp, const DSA *x, int off); +# endif + +# define DSS_prime_checks 64 +/* + * Primality test according to FIPS PUB 186-4, Appendix C.3. Since we only + * have one value here we set the number of checks to 64 which is the 128 bit + * security level that is the highest level and valid for creating a 3072 bit + * DSA key. + */ +# define DSA_is_prime(n, callback, cb_arg) \ + BN_is_prime(n, DSS_prime_checks, callback, NULL, cb_arg) + +# ifndef OPENSSL_NO_DH +/* + * Convert DSA structure (key or just parameters) into DH structure (be + * careful to avoid small subgroup attacks when using this!) + */ +DH *DSA_dup_DH(const DSA *r); +# endif + +# define EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, nbits) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN, \ + EVP_PKEY_CTRL_DSA_PARAMGEN_BITS, nbits, NULL) + +# define EVP_PKEY_CTRL_DSA_PARAMGEN_BITS (EVP_PKEY_ALG_CTRL + 1) +# define EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS (EVP_PKEY_ALG_CTRL + 2) +# define EVP_PKEY_CTRL_DSA_PARAMGEN_MD (EVP_PKEY_ALG_CTRL + 3) + +void DSA_get0_pqg(const DSA *d, + const BIGNUM **p, const BIGNUM **q, const BIGNUM **g); +int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g); +void DSA_get0_key(const DSA *d, + const BIGNUM **pub_key, const BIGNUM **priv_key); +int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key); +const BIGNUM *DSA_get0_p(const DSA *d); +const BIGNUM *DSA_get0_q(const DSA *d); +const BIGNUM *DSA_get0_g(const DSA *d); +const BIGNUM *DSA_get0_pub_key(const DSA *d); +const BIGNUM *DSA_get0_priv_key(const DSA *d); +void DSA_clear_flags(DSA *d, int flags); +int DSA_test_flags(const DSA *d, int flags); +void DSA_set_flags(DSA *d, int flags); +ENGINE *DSA_get0_engine(DSA *d); + +DSA_METHOD *DSA_meth_new(const char *name, int flags); +void DSA_meth_free(DSA_METHOD *dsam); +DSA_METHOD *DSA_meth_dup(const DSA_METHOD *dsam); +const char *DSA_meth_get0_name(const DSA_METHOD *dsam); +int DSA_meth_set1_name(DSA_METHOD *dsam, const char *name); +int DSA_meth_get_flags(const DSA_METHOD *dsam); +int DSA_meth_set_flags(DSA_METHOD *dsam, int flags); +void *DSA_meth_get0_app_data(const DSA_METHOD *dsam); +int DSA_meth_set0_app_data(DSA_METHOD *dsam, void *app_data); +DSA_SIG *(*DSA_meth_get_sign(const DSA_METHOD *dsam)) + (const unsigned char *, int, DSA *); +int DSA_meth_set_sign(DSA_METHOD *dsam, + DSA_SIG *(*sign) (const unsigned char *, int, DSA *)); +int (*DSA_meth_get_sign_setup(const DSA_METHOD *dsam)) + (DSA *, BN_CTX *, BIGNUM **, BIGNUM **); +int DSA_meth_set_sign_setup(DSA_METHOD *dsam, + int (*sign_setup) (DSA *, BN_CTX *, BIGNUM **, BIGNUM **)); +int (*DSA_meth_get_verify(const DSA_METHOD *dsam)) + (const unsigned char *, int, DSA_SIG *, DSA *); +int DSA_meth_set_verify(DSA_METHOD *dsam, + int (*verify) (const unsigned char *, int, DSA_SIG *, DSA *)); +int (*DSA_meth_get_mod_exp(const DSA_METHOD *dsam)) + (DSA *, BIGNUM *, const BIGNUM *, const BIGNUM *, const BIGNUM *, + const BIGNUM *, const BIGNUM *, BN_CTX *, BN_MONT_CTX *); +int DSA_meth_set_mod_exp(DSA_METHOD *dsam, + int (*mod_exp) (DSA *, BIGNUM *, const BIGNUM *, const BIGNUM *, + const BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *, + BN_MONT_CTX *)); +int (*DSA_meth_get_bn_mod_exp(const DSA_METHOD *dsam)) + (DSA *, BIGNUM *, const BIGNUM *, const BIGNUM *, const BIGNUM *, + BN_CTX *, BN_MONT_CTX *); +int DSA_meth_set_bn_mod_exp(DSA_METHOD *dsam, + int (*bn_mod_exp) (DSA *, BIGNUM *, const BIGNUM *, const BIGNUM *, + const BIGNUM *, BN_CTX *, BN_MONT_CTX *)); +int (*DSA_meth_get_init(const DSA_METHOD *dsam))(DSA *); +int DSA_meth_set_init(DSA_METHOD *dsam, int (*init)(DSA *)); +int (*DSA_meth_get_finish(const DSA_METHOD *dsam)) (DSA *); +int DSA_meth_set_finish(DSA_METHOD *dsam, int (*finish) (DSA *)); +int (*DSA_meth_get_paramgen(const DSA_METHOD *dsam)) + (DSA *, int, const unsigned char *, int, int *, unsigned long *, + BN_GENCB *); +int DSA_meth_set_paramgen(DSA_METHOD *dsam, + int (*paramgen) (DSA *, int, const unsigned char *, int, int *, + unsigned long *, BN_GENCB *)); +int (*DSA_meth_get_keygen(const DSA_METHOD *dsam)) (DSA *); +int DSA_meth_set_keygen(DSA_METHOD *dsam, int (*keygen) (DSA *)); + + +# ifdef __cplusplus +} +# endif +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/dsaerr.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/dsaerr.h new file mode 100644 index 000000000..d94f97bba --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/dsaerr.h @@ -0,0 +1,67 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_DSAERR_H +# define HEADER_DSAERR_H + +# include + +# ifndef OPENSSL_NO_DSA + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_DSA_strings(void); + +/* + * DSA function codes. + */ +# define DSA_F_DSAPARAMS_PRINT 100 +# define DSA_F_DSAPARAMS_PRINT_FP 101 +# define DSA_F_DSA_BUILTIN_PARAMGEN 125 +# define DSA_F_DSA_BUILTIN_PARAMGEN2 126 +# define DSA_F_DSA_DO_SIGN 112 +# define DSA_F_DSA_DO_VERIFY 113 +# define DSA_F_DSA_METH_DUP 127 +# define DSA_F_DSA_METH_NEW 128 +# define DSA_F_DSA_METH_SET1_NAME 129 +# define DSA_F_DSA_NEW_METHOD 103 +# define DSA_F_DSA_PARAM_DECODE 119 +# define DSA_F_DSA_PRINT_FP 105 +# define DSA_F_DSA_PRIV_DECODE 115 +# define DSA_F_DSA_PRIV_ENCODE 116 +# define DSA_F_DSA_PUB_DECODE 117 +# define DSA_F_DSA_PUB_ENCODE 118 +# define DSA_F_DSA_SIGN 106 +# define DSA_F_DSA_SIGN_SETUP 107 +# define DSA_F_DSA_SIG_NEW 102 +# define DSA_F_OLD_DSA_PRIV_DECODE 122 +# define DSA_F_PKEY_DSA_CTRL 120 +# define DSA_F_PKEY_DSA_CTRL_STR 104 +# define DSA_F_PKEY_DSA_KEYGEN 121 + +/* + * DSA reason codes. + */ +# define DSA_R_BAD_Q_VALUE 102 +# define DSA_R_BN_DECODE_ERROR 108 +# define DSA_R_BN_ERROR 109 +# define DSA_R_DECODE_ERROR 104 +# define DSA_R_INVALID_DIGEST_TYPE 106 +# define DSA_R_INVALID_PARAMETERS 112 +# define DSA_R_MISSING_PARAMETERS 101 +# define DSA_R_MODULUS_TOO_LARGE 103 +# define DSA_R_NO_PARAMETERS_SET 107 +# define DSA_R_PARAMETER_ENCODING_ERROR 105 +# define DSA_R_Q_NOT_PRIME 113 +# define DSA_R_SEED_LEN_SMALL 110 + +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/dtls1.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/dtls1.h new file mode 100644 index 000000000..a312e386c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/dtls1.h @@ -0,0 +1,55 @@ +/* + * Copyright 2005-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_DTLS1_H +# define HEADER_DTLS1_H + +#ifdef __cplusplus +extern "C" { +#endif + +# define DTLS1_VERSION 0xFEFF +# define DTLS1_2_VERSION 0xFEFD +# define DTLS_MIN_VERSION DTLS1_VERSION +# define DTLS_MAX_VERSION DTLS1_2_VERSION +# define DTLS1_VERSION_MAJOR 0xFE + +# define DTLS1_BAD_VER 0x0100 + +/* Special value for method supporting multiple versions */ +# define DTLS_ANY_VERSION 0x1FFFF + +/* lengths of messages */ +/* + * Actually the max cookie length in DTLS is 255. But we can't change this now + * due to compatibility concerns. + */ +# define DTLS1_COOKIE_LENGTH 256 + +# define DTLS1_RT_HEADER_LENGTH 13 + +# define DTLS1_HM_HEADER_LENGTH 12 + +# define DTLS1_HM_BAD_FRAGMENT -2 +# define DTLS1_HM_FRAGMENT_RETRY -3 + +# define DTLS1_CCS_HEADER_LENGTH 1 + +# define DTLS1_AL_HEADER_LENGTH 2 + +/* Timeout multipliers (timeout slice is defined in apps/timeouts.h */ +# define DTLS1_TMO_READ_COUNT 2 +# define DTLS1_TMO_WRITE_COUNT 2 + +# define DTLS1_TMO_ALERT_COUNT 12 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/e_os2.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/e_os2.h new file mode 100644 index 000000000..97a776cda --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/e_os2.h @@ -0,0 +1,300 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_E_OS2_H +# define HEADER_E_OS2_H + +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************************** + * Detect operating systems. This probably needs completing. + * The result is that at least one OPENSSL_SYS_os macro should be defined. + * However, if none is defined, Unix is assumed. + **/ + +# define OPENSSL_SYS_UNIX + +/* --------------------- Microsoft operating systems ---------------------- */ + +/* + * Note that MSDOS actually denotes 32-bit environments running on top of + * MS-DOS, such as DJGPP one. + */ +# if defined(OPENSSL_SYS_MSDOS) +# undef OPENSSL_SYS_UNIX +# endif + +/* + * For 32 bit environment, there seems to be the CygWin environment and then + * all the others that try to do the same thing Microsoft does... + */ +/* + * UEFI lives here because it might be built with a Microsoft toolchain and + * we need to avoid the false positive match on Windows. + */ +# if defined(OPENSSL_SYS_UEFI) +# undef OPENSSL_SYS_UNIX +# elif defined(OPENSSL_SYS_UWIN) +# undef OPENSSL_SYS_UNIX +# define OPENSSL_SYS_WIN32_UWIN +# else +# if defined(__CYGWIN__) || defined(OPENSSL_SYS_CYGWIN) +# define OPENSSL_SYS_WIN32_CYGWIN +# else +# if defined(_WIN32) || defined(OPENSSL_SYS_WIN32) +# undef OPENSSL_SYS_UNIX +# if !defined(OPENSSL_SYS_WIN32) +# define OPENSSL_SYS_WIN32 +# endif +# endif +# if defined(_WIN64) || defined(OPENSSL_SYS_WIN64) +# undef OPENSSL_SYS_UNIX +# if !defined(OPENSSL_SYS_WIN64) +# define OPENSSL_SYS_WIN64 +# endif +# endif +# if defined(OPENSSL_SYS_WINNT) +# undef OPENSSL_SYS_UNIX +# endif +# if defined(OPENSSL_SYS_WINCE) +# undef OPENSSL_SYS_UNIX +# endif +# endif +# endif + +/* Anything that tries to look like Microsoft is "Windows" */ +# if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN64) || defined(OPENSSL_SYS_WINNT) || defined(OPENSSL_SYS_WINCE) +# undef OPENSSL_SYS_UNIX +# define OPENSSL_SYS_WINDOWS +# ifndef OPENSSL_SYS_MSDOS +# define OPENSSL_SYS_MSDOS +# endif +# endif + +/* + * DLL settings. This part is a bit tough, because it's up to the + * application implementor how he or she will link the application, so it + * requires some macro to be used. + */ +# ifdef OPENSSL_SYS_WINDOWS +# ifndef OPENSSL_OPT_WINDLL +# if defined(_WINDLL) /* This is used when building OpenSSL to + * indicate that DLL linkage should be used */ +# define OPENSSL_OPT_WINDLL +# endif +# endif +# endif + +/* ------------------------------- OpenVMS -------------------------------- */ +# if defined(__VMS) || defined(VMS) || defined(OPENSSL_SYS_VMS) +# if !defined(OPENSSL_SYS_VMS) +# undef OPENSSL_SYS_UNIX +# endif +# define OPENSSL_SYS_VMS +# if defined(__DECC) +# define OPENSSL_SYS_VMS_DECC +# elif defined(__DECCXX) +# define OPENSSL_SYS_VMS_DECC +# define OPENSSL_SYS_VMS_DECCXX +# else +# define OPENSSL_SYS_VMS_NODECC +# endif +# endif + +/* -------------------------------- Unix ---------------------------------- */ +# ifdef OPENSSL_SYS_UNIX +# if defined(linux) || defined(__linux__) && !defined(OPENSSL_SYS_LINUX) +# define OPENSSL_SYS_LINUX +# endif +# if defined(_AIX) && !defined(OPENSSL_SYS_AIX) +# define OPENSSL_SYS_AIX +# endif +# endif + +/* -------------------------------- VOS ----------------------------------- */ +# if defined(__VOS__) && !defined(OPENSSL_SYS_VOS) +# define OPENSSL_SYS_VOS +# ifdef __HPPA__ +# define OPENSSL_SYS_VOS_HPPA +# endif +# ifdef __IA32__ +# define OPENSSL_SYS_VOS_IA32 +# endif +# endif + +/** + * That's it for OS-specific stuff + *****************************************************************************/ + +/* Specials for I/O an exit */ +# ifdef OPENSSL_SYS_MSDOS +# define OPENSSL_UNISTD_IO +# define OPENSSL_DECLARE_EXIT extern void exit(int); +# else +# define OPENSSL_UNISTD_IO OPENSSL_UNISTD +# define OPENSSL_DECLARE_EXIT /* declared in unistd.h */ +# endif + +/*- + * OPENSSL_EXTERN is normally used to declare a symbol with possible extra + * attributes to handle its presence in a shared library. + * OPENSSL_EXPORT is used to define a symbol with extra possible attributes + * to make it visible in a shared library. + * Care needs to be taken when a header file is used both to declare and + * define symbols. Basically, for any library that exports some global + * variables, the following code must be present in the header file that + * declares them, before OPENSSL_EXTERN is used: + * + * #ifdef SOME_BUILD_FLAG_MACRO + * # undef OPENSSL_EXTERN + * # define OPENSSL_EXTERN OPENSSL_EXPORT + * #endif + * + * The default is to have OPENSSL_EXPORT and OPENSSL_EXTERN + * have some generally sensible values. + */ + +# if defined(OPENSSL_SYS_WINDOWS) && defined(OPENSSL_OPT_WINDLL) +# define OPENSSL_EXPORT extern __declspec(dllexport) +# define OPENSSL_EXTERN extern __declspec(dllimport) +# else +# define OPENSSL_EXPORT extern +# define OPENSSL_EXTERN extern +# endif + +/*- + * Macros to allow global variables to be reached through function calls when + * required (if a shared library version requires it, for example. + * The way it's done allows definitions like this: + * + * // in foobar.c + * OPENSSL_IMPLEMENT_GLOBAL(int,foobar,0) + * // in foobar.h + * OPENSSL_DECLARE_GLOBAL(int,foobar); + * #define foobar OPENSSL_GLOBAL_REF(foobar) + */ +# ifdef OPENSSL_EXPORT_VAR_AS_FUNCTION +# define OPENSSL_IMPLEMENT_GLOBAL(type,name,value) \ + type *_shadow_##name(void) \ + { static type _hide_##name=value; return &_hide_##name; } +# define OPENSSL_DECLARE_GLOBAL(type,name) type *_shadow_##name(void) +# define OPENSSL_GLOBAL_REF(name) (*(_shadow_##name())) +# else +# define OPENSSL_IMPLEMENT_GLOBAL(type,name,value) type _shadow_##name=value; +# define OPENSSL_DECLARE_GLOBAL(type,name) OPENSSL_EXPORT type _shadow_##name +# define OPENSSL_GLOBAL_REF(name) _shadow_##name +# endif + +# ifdef _WIN32 +# ifdef _WIN64 +# define ossl_ssize_t __int64 +# define OSSL_SSIZE_MAX _I64_MAX +# else +# define ossl_ssize_t int +# define OSSL_SSIZE_MAX INT_MAX +# endif +# endif + +# if defined(OPENSSL_SYS_UEFI) && !defined(ossl_ssize_t) +# define ossl_ssize_t INTN +# define OSSL_SSIZE_MAX MAX_INTN +# endif + +# ifndef ossl_ssize_t +# define ossl_ssize_t ssize_t +# if defined(SSIZE_MAX) +# define OSSL_SSIZE_MAX SSIZE_MAX +# elif defined(_POSIX_SSIZE_MAX) +# define OSSL_SSIZE_MAX _POSIX_SSIZE_MAX +# else +# define OSSL_SSIZE_MAX ((ssize_t)(SIZE_MAX>>1)) +# endif +# endif + +# ifdef DEBUG_UNUSED +# define __owur __attribute__((__warn_unused_result__)) +# else +# define __owur +# endif + +/* Standard integer types */ +# if defined(OPENSSL_SYS_UEFI) +typedef INT8 int8_t; +typedef UINT8 uint8_t; +typedef INT16 int16_t; +typedef UINT16 uint16_t; +typedef INT32 int32_t; +typedef UINT32 uint32_t; +typedef INT64 int64_t; +typedef UINT64 uint64_t; +# elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ + defined(__osf__) || defined(__sgi) || defined(__hpux) || \ + defined(OPENSSL_SYS_VMS) || defined (__OpenBSD__) +# include +# elif defined(_MSC_VER) && _MSC_VER<=1500 +/* + * minimally required typdefs for systems not supporting inttypes.h or + * stdint.h: currently just older VC++ + */ +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef int int32_t; +typedef unsigned int uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +# else +# include +# endif + +/* ossl_inline: portable inline definition usable in public headers */ +# if !defined(inline) && !defined(__cplusplus) +# if defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L + /* just use inline */ +# define ossl_inline inline +# elif defined(__GNUC__) && __GNUC__>=2 +# define ossl_inline __inline__ +# elif defined(_MSC_VER) + /* + * Visual Studio: inline is available in C++ only, however + * __inline is available for C, see + * http://msdn.microsoft.com/en-us/library/z8y1yy88.aspx + */ +# define ossl_inline __inline +# else +# define ossl_inline +# endif +# else +# define ossl_inline inline +# endif + +# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +# define ossl_noreturn _Noreturn +# elif defined(__GNUC__) && __GNUC__ >= 2 +# define ossl_noreturn __attribute__((noreturn)) +# else +# define ossl_noreturn +# endif + +/* ossl_unused: portable unused attribute for use in public headers */ +# if defined(__GNUC__) +# define ossl_unused __attribute__((unused)) +# else +# define ossl_unused +# endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/ebcdic.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ebcdic.h new file mode 100644 index 000000000..aa0128559 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ebcdic.h @@ -0,0 +1,33 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_EBCDIC_H +# define HEADER_EBCDIC_H + +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Avoid name clashes with other applications */ +# define os_toascii _openssl_os_toascii +# define os_toebcdic _openssl_os_toebcdic +# define ebcdic2ascii _openssl_ebcdic2ascii +# define ascii2ebcdic _openssl_ascii2ebcdic + +extern const unsigned char os_toascii[256]; +extern const unsigned char os_toebcdic[256]; +void *ebcdic2ascii(void *dest, const void *srce, size_t count); +void *ascii2ebcdic(void *dest, const void *srce, size_t count); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/ec.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ec.h new file mode 100644 index 000000000..347cfb6d0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ec.h @@ -0,0 +1,1478 @@ +/* + * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_EC_H +# define HEADER_EC_H + +# include + +# ifndef OPENSSL_NO_EC +# include +# include +# if OPENSSL_API_COMPAT < 0x10100000L +# include +# endif +# include +# ifdef __cplusplus +extern "C" { +# endif + +# ifndef OPENSSL_ECC_MAX_FIELD_BITS +# define OPENSSL_ECC_MAX_FIELD_BITS 661 +# endif + +/** Enum for the point conversion form as defined in X9.62 (ECDSA) + * for the encoding of a elliptic curve point (x,y) */ +typedef enum { + /** the point is encoded as z||x, where the octet z specifies + * which solution of the quadratic equation y is */ + POINT_CONVERSION_COMPRESSED = 2, + /** the point is encoded as z||x||y, where z is the octet 0x04 */ + POINT_CONVERSION_UNCOMPRESSED = 4, + /** the point is encoded as z||x||y, where the octet z specifies + * which solution of the quadratic equation y is */ + POINT_CONVERSION_HYBRID = 6 +} point_conversion_form_t; + +typedef struct ec_method_st EC_METHOD; +typedef struct ec_group_st EC_GROUP; +typedef struct ec_point_st EC_POINT; +typedef struct ecpk_parameters_st ECPKPARAMETERS; +typedef struct ec_parameters_st ECPARAMETERS; + +/********************************************************************/ +/* EC_METHODs for curves over GF(p) */ +/********************************************************************/ + +/** Returns the basic GFp ec methods which provides the basis for the + * optimized methods. + * \return EC_METHOD object + */ +const EC_METHOD *EC_GFp_simple_method(void); + +/** Returns GFp methods using montgomery multiplication. + * \return EC_METHOD object + */ +const EC_METHOD *EC_GFp_mont_method(void); + +/** Returns GFp methods using optimized methods for NIST recommended curves + * \return EC_METHOD object + */ +const EC_METHOD *EC_GFp_nist_method(void); + +# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 +/** Returns 64-bit optimized methods for nistp224 + * \return EC_METHOD object + */ +const EC_METHOD *EC_GFp_nistp224_method(void); + +/** Returns 64-bit optimized methods for nistp256 + * \return EC_METHOD object + */ +const EC_METHOD *EC_GFp_nistp256_method(void); + +/** Returns 64-bit optimized methods for nistp521 + * \return EC_METHOD object + */ +const EC_METHOD *EC_GFp_nistp521_method(void); +# endif + +# ifndef OPENSSL_NO_EC2M +/********************************************************************/ +/* EC_METHOD for curves over GF(2^m) */ +/********************************************************************/ + +/** Returns the basic GF2m ec method + * \return EC_METHOD object + */ +const EC_METHOD *EC_GF2m_simple_method(void); + +# endif + +/********************************************************************/ +/* EC_GROUP functions */ +/********************************************************************/ + +/** Creates a new EC_GROUP object + * \param meth EC_METHOD to use + * \return newly created EC_GROUP object or NULL in case of an error. + */ +EC_GROUP *EC_GROUP_new(const EC_METHOD *meth); + +/** Frees a EC_GROUP object + * \param group EC_GROUP object to be freed. + */ +void EC_GROUP_free(EC_GROUP *group); + +/** Clears and frees a EC_GROUP object + * \param group EC_GROUP object to be cleared and freed. + */ +void EC_GROUP_clear_free(EC_GROUP *group); + +/** Copies EC_GROUP objects. Note: both EC_GROUPs must use the same EC_METHOD. + * \param dst destination EC_GROUP object + * \param src source EC_GROUP object + * \return 1 on success and 0 if an error occurred. + */ +int EC_GROUP_copy(EC_GROUP *dst, const EC_GROUP *src); + +/** Creates a new EC_GROUP object and copies the copies the content + * form src to the newly created EC_KEY object + * \param src source EC_GROUP object + * \return newly created EC_GROUP object or NULL in case of an error. + */ +EC_GROUP *EC_GROUP_dup(const EC_GROUP *src); + +/** Returns the EC_METHOD of the EC_GROUP object. + * \param group EC_GROUP object + * \return EC_METHOD used in this EC_GROUP object. + */ +const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group); + +/** Returns the field type of the EC_METHOD. + * \param meth EC_METHOD object + * \return NID of the underlying field type OID. + */ +int EC_METHOD_get_field_type(const EC_METHOD *meth); + +/** Sets the generator and it's order/cofactor of a EC_GROUP object. + * \param group EC_GROUP object + * \param generator EC_POINT object with the generator. + * \param order the order of the group generated by the generator. + * \param cofactor the index of the sub-group generated by the generator + * in the group of all points on the elliptic curve. + * \return 1 on success and 0 if an error occurred + */ +int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, + const BIGNUM *order, const BIGNUM *cofactor); + +/** Returns the generator of a EC_GROUP object. + * \param group EC_GROUP object + * \return the currently used generator (possibly NULL). + */ +const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group); + +/** Returns the montgomery data for order(Generator) + * \param group EC_GROUP object + * \return the currently used montgomery data (possibly NULL). +*/ +BN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group); + +/** Gets the order of a EC_GROUP + * \param group EC_GROUP object + * \param order BIGNUM to which the order is copied + * \param ctx unused + * \return 1 on success and 0 if an error occurred + */ +int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx); + +/** Gets the order of an EC_GROUP + * \param group EC_GROUP object + * \return the group order + */ +const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group); + +/** Gets the number of bits of the order of an EC_GROUP + * \param group EC_GROUP object + * \return number of bits of group order. + */ +int EC_GROUP_order_bits(const EC_GROUP *group); + +/** Gets the cofactor of a EC_GROUP + * \param group EC_GROUP object + * \param cofactor BIGNUM to which the cofactor is copied + * \param ctx unused + * \return 1 on success and 0 if an error occurred + */ +int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, + BN_CTX *ctx); + +/** Gets the cofactor of an EC_GROUP + * \param group EC_GROUP object + * \return the group cofactor + */ +const BIGNUM *EC_GROUP_get0_cofactor(const EC_GROUP *group); + +/** Sets the name of a EC_GROUP object + * \param group EC_GROUP object + * \param nid NID of the curve name OID + */ +void EC_GROUP_set_curve_name(EC_GROUP *group, int nid); + +/** Returns the curve name of a EC_GROUP object + * \param group EC_GROUP object + * \return NID of the curve name OID or 0 if not set. + */ +int EC_GROUP_get_curve_name(const EC_GROUP *group); + +void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag); +int EC_GROUP_get_asn1_flag(const EC_GROUP *group); + +void EC_GROUP_set_point_conversion_form(EC_GROUP *group, + point_conversion_form_t form); +point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *); + +unsigned char *EC_GROUP_get0_seed(const EC_GROUP *x); +size_t EC_GROUP_get_seed_len(const EC_GROUP *); +size_t EC_GROUP_set_seed(EC_GROUP *, const unsigned char *, size_t len); + +/** Sets the parameters of a ec curve defined by y^2 = x^3 + a*x + b (for GFp) + * or y^2 + x*y = x^3 + a*x^2 + b (for GF2m) + * \param group EC_GROUP object + * \param p BIGNUM with the prime number (GFp) or the polynomial + * defining the underlying field (GF2m) + * \param a BIGNUM with parameter a of the equation + * \param b BIGNUM with parameter b of the equation + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +int EC_GROUP_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx); + +/** Gets the parameters of the ec curve defined by y^2 = x^3 + a*x + b (for GFp) + * or y^2 + x*y = x^3 + a*x^2 + b (for GF2m) + * \param group EC_GROUP object + * \param p BIGNUM with the prime number (GFp) or the polynomial + * defining the underlying field (GF2m) + * \param a BIGNUM for parameter a of the equation + * \param b BIGNUM for parameter b of the equation + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +int EC_GROUP_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, + BN_CTX *ctx); + +/** Sets the parameters of an ec curve. Synonym for EC_GROUP_set_curve + * \param group EC_GROUP object + * \param p BIGNUM with the prime number (GFp) or the polynomial + * defining the underlying field (GF2m) + * \param a BIGNUM with parameter a of the equation + * \param b BIGNUM with parameter b of the equation + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +DEPRECATEDIN_1_2_0(int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *b, + BN_CTX *ctx)) + +/** Gets the parameters of an ec curve. Synonym for EC_GROUP_get_curve + * \param group EC_GROUP object + * \param p BIGNUM with the prime number (GFp) or the polynomial + * defining the underlying field (GF2m) + * \param a BIGNUM for parameter a of the equation + * \param b BIGNUM for parameter b of the equation + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +DEPRECATEDIN_1_2_0(int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, + BIGNUM *a, BIGNUM *b, + BN_CTX *ctx)) + +# ifndef OPENSSL_NO_EC2M +/** Sets the parameter of an ec curve. Synonym for EC_GROUP_set_curve + * \param group EC_GROUP object + * \param p BIGNUM with the prime number (GFp) or the polynomial + * defining the underlying field (GF2m) + * \param a BIGNUM with parameter a of the equation + * \param b BIGNUM with parameter b of the equation + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +DEPRECATEDIN_1_2_0(int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *b, + BN_CTX *ctx)) + +/** Gets the parameters of an ec curve. Synonym for EC_GROUP_get_curve + * \param group EC_GROUP object + * \param p BIGNUM with the prime number (GFp) or the polynomial + * defining the underlying field (GF2m) + * \param a BIGNUM for parameter a of the equation + * \param b BIGNUM for parameter b of the equation + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +DEPRECATEDIN_1_2_0(int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, + BIGNUM *a, BIGNUM *b, + BN_CTX *ctx)) +# endif +/** Returns the number of bits needed to represent a field element + * \param group EC_GROUP object + * \return number of bits needed to represent a field element + */ +int EC_GROUP_get_degree(const EC_GROUP *group); + +/** Checks whether the parameter in the EC_GROUP define a valid ec group + * \param group EC_GROUP object + * \param ctx BN_CTX object (optional) + * \return 1 if group is a valid ec group and 0 otherwise + */ +int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx); + +/** Checks whether the discriminant of the elliptic curve is zero or not + * \param group EC_GROUP object + * \param ctx BN_CTX object (optional) + * \return 1 if the discriminant is not zero and 0 otherwise + */ +int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx); + +/** Compares two EC_GROUP objects + * \param a first EC_GROUP object + * \param b second EC_GROUP object + * \param ctx BN_CTX object (optional) + * \return 0 if the groups are equal, 1 if not, or -1 on error + */ +int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx); + +/* + * EC_GROUP_new_GF*() calls EC_GROUP_new() and EC_GROUP_set_GF*() after + * choosing an appropriate EC_METHOD + */ + +/** Creates a new EC_GROUP object with the specified parameters defined + * over GFp (defined by the equation y^2 = x^3 + a*x + b) + * \param p BIGNUM with the prime number + * \param a BIGNUM with the parameter a of the equation + * \param b BIGNUM with the parameter b of the equation + * \param ctx BN_CTX object (optional) + * \return newly created EC_GROUP object with the specified parameters + */ +EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx); +# ifndef OPENSSL_NO_EC2M +/** Creates a new EC_GROUP object with the specified parameters defined + * over GF2m (defined by the equation y^2 + x*y = x^3 + a*x^2 + b) + * \param p BIGNUM with the polynomial defining the underlying field + * \param a BIGNUM with the parameter a of the equation + * \param b BIGNUM with the parameter b of the equation + * \param ctx BN_CTX object (optional) + * \return newly created EC_GROUP object with the specified parameters + */ +EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx); +# endif + +/** Creates a EC_GROUP object with a curve specified by a NID + * \param nid NID of the OID of the curve name + * \return newly created EC_GROUP object with specified curve or NULL + * if an error occurred + */ +EC_GROUP *EC_GROUP_new_by_curve_name(int nid); + +/** Creates a new EC_GROUP object from an ECPARAMETERS object + * \param params pointer to the ECPARAMETERS object + * \return newly created EC_GROUP object with specified curve or NULL + * if an error occurred + */ +EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params); + +/** Creates an ECPARAMETERS object for the given EC_GROUP object. + * \param group pointer to the EC_GROUP object + * \param params pointer to an existing ECPARAMETERS object or NULL + * \return pointer to the new ECPARAMETERS object or NULL + * if an error occurred. + */ +ECPARAMETERS *EC_GROUP_get_ecparameters(const EC_GROUP *group, + ECPARAMETERS *params); + +/** Creates a new EC_GROUP object from an ECPKPARAMETERS object + * \param params pointer to an existing ECPKPARAMETERS object, or NULL + * \return newly created EC_GROUP object with specified curve, or NULL + * if an error occurred + */ +EC_GROUP *EC_GROUP_new_from_ecpkparameters(const ECPKPARAMETERS *params); + +/** Creates an ECPKPARAMETERS object for the given EC_GROUP object. + * \param group pointer to the EC_GROUP object + * \param params pointer to an existing ECPKPARAMETERS object or NULL + * \return pointer to the new ECPKPARAMETERS object or NULL + * if an error occurred. + */ +ECPKPARAMETERS *EC_GROUP_get_ecpkparameters(const EC_GROUP *group, + ECPKPARAMETERS *params); + +/********************************************************************/ +/* handling of internal curves */ +/********************************************************************/ + +typedef struct { + int nid; + const char *comment; +} EC_builtin_curve; + +/* + * EC_builtin_curves(EC_builtin_curve *r, size_t size) returns number of all + * available curves or zero if a error occurred. In case r is not zero, + * nitems EC_builtin_curve structures are filled with the data of the first + * nitems internal groups + */ +size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems); + +const char *EC_curve_nid2nist(int nid); +int EC_curve_nist2nid(const char *name); + +/********************************************************************/ +/* EC_POINT functions */ +/********************************************************************/ + +/** Creates a new EC_POINT object for the specified EC_GROUP + * \param group EC_GROUP the underlying EC_GROUP object + * \return newly created EC_POINT object or NULL if an error occurred + */ +EC_POINT *EC_POINT_new(const EC_GROUP *group); + +/** Frees a EC_POINT object + * \param point EC_POINT object to be freed + */ +void EC_POINT_free(EC_POINT *point); + +/** Clears and frees a EC_POINT object + * \param point EC_POINT object to be cleared and freed + */ +void EC_POINT_clear_free(EC_POINT *point); + +/** Copies EC_POINT object + * \param dst destination EC_POINT object + * \param src source EC_POINT object + * \return 1 on success and 0 if an error occurred + */ +int EC_POINT_copy(EC_POINT *dst, const EC_POINT *src); + +/** Creates a new EC_POINT object and copies the content of the supplied + * EC_POINT + * \param src source EC_POINT object + * \param group underlying the EC_GROUP object + * \return newly created EC_POINT object or NULL if an error occurred + */ +EC_POINT *EC_POINT_dup(const EC_POINT *src, const EC_GROUP *group); + +/** Returns the EC_METHOD used in EC_POINT object + * \param point EC_POINT object + * \return the EC_METHOD used + */ +const EC_METHOD *EC_POINT_method_of(const EC_POINT *point); + +/** Sets a point to infinity (neutral element) + * \param group underlying EC_GROUP object + * \param point EC_POINT to set to infinity + * \return 1 on success and 0 if an error occurred + */ +int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point); + +/** Sets the jacobian projective coordinates of a EC_POINT over GFp + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM with the x-coordinate + * \param y BIGNUM with the y-coordinate + * \param z BIGNUM with the z-coordinate + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, + EC_POINT *p, const BIGNUM *x, + const BIGNUM *y, const BIGNUM *z, + BN_CTX *ctx); + +/** Gets the jacobian projective coordinates of a EC_POINT over GFp + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM for the x-coordinate + * \param y BIGNUM for the y-coordinate + * \param z BIGNUM for the z-coordinate + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, + const EC_POINT *p, BIGNUM *x, + BIGNUM *y, BIGNUM *z, + BN_CTX *ctx); + +/** Sets the affine coordinates of an EC_POINT + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM with the x-coordinate + * \param y BIGNUM with the y-coordinate + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +int EC_POINT_set_affine_coordinates(const EC_GROUP *group, EC_POINT *p, + const BIGNUM *x, const BIGNUM *y, + BN_CTX *ctx); + +/** Gets the affine coordinates of an EC_POINT. + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM for the x-coordinate + * \param y BIGNUM for the y-coordinate + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +int EC_POINT_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *p, + BIGNUM *x, BIGNUM *y, BN_CTX *ctx); + +/** Sets the affine coordinates of an EC_POINT. A synonym of + * EC_POINT_set_affine_coordinates + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM with the x-coordinate + * \param y BIGNUM with the y-coordinate + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +DEPRECATEDIN_1_2_0(int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, + EC_POINT *p, + const BIGNUM *x, + const BIGNUM *y, + BN_CTX *ctx)) + +/** Gets the affine coordinates of an EC_POINT. A synonym of + * EC_POINT_get_affine_coordinates + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM for the x-coordinate + * \param y BIGNUM for the y-coordinate + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +DEPRECATEDIN_1_2_0(int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, + const EC_POINT *p, + BIGNUM *x, + BIGNUM *y, + BN_CTX *ctx)) + +/** Sets the x9.62 compressed coordinates of a EC_POINT + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM with x-coordinate + * \param y_bit integer with the y-Bit (either 0 or 1) + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +int EC_POINT_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *p, + const BIGNUM *x, int y_bit, + BN_CTX *ctx); + +/** Sets the x9.62 compressed coordinates of a EC_POINT. A synonym of + * EC_POINT_set_compressed_coordinates + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM with x-coordinate + * \param y_bit integer with the y-Bit (either 0 or 1) + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +DEPRECATEDIN_1_2_0(int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, + EC_POINT *p, + const BIGNUM *x, + int y_bit, + BN_CTX *ctx)) +# ifndef OPENSSL_NO_EC2M +/** Sets the affine coordinates of an EC_POINT. A synonym of + * EC_POINT_set_affine_coordinates + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM with the x-coordinate + * \param y BIGNUM with the y-coordinate + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +DEPRECATEDIN_1_2_0(int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, + EC_POINT *p, + const BIGNUM *x, + const BIGNUM *y, + BN_CTX *ctx)) + +/** Gets the affine coordinates of an EC_POINT. A synonym of + * EC_POINT_get_affine_coordinates + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM for the x-coordinate + * \param y BIGNUM for the y-coordinate + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +DEPRECATEDIN_1_2_0(int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, + const EC_POINT *p, + BIGNUM *x, + BIGNUM *y, + BN_CTX *ctx)) + +/** Sets the x9.62 compressed coordinates of a EC_POINT. A synonym of + * EC_POINT_set_compressed_coordinates + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM with x-coordinate + * \param y_bit integer with the y-Bit (either 0 or 1) + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +DEPRECATEDIN_1_2_0(int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, + EC_POINT *p, + const BIGNUM *x, + int y_bit, + BN_CTX *ctx)) +# endif +/** Encodes a EC_POINT object to a octet string + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param form point conversion form + * \param buf memory buffer for the result. If NULL the function returns + * required buffer size. + * \param len length of the memory buffer + * \param ctx BN_CTX object (optional) + * \return the length of the encoded octet string or 0 if an error occurred + */ +size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *p, + point_conversion_form_t form, + unsigned char *buf, size_t len, BN_CTX *ctx); + +/** Decodes a EC_POINT from a octet string + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param buf memory buffer with the encoded ec point + * \param len length of the encoded ec point + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *p, + const unsigned char *buf, size_t len, BN_CTX *ctx); + +/** Encodes an EC_POINT object to an allocated octet string + * \param group underlying EC_GROUP object + * \param point EC_POINT object + * \param form point conversion form + * \param pbuf returns pointer to allocated buffer + * \param ctx BN_CTX object (optional) + * \return the length of the encoded octet string or 0 if an error occurred + */ +size_t EC_POINT_point2buf(const EC_GROUP *group, const EC_POINT *point, + point_conversion_form_t form, + unsigned char **pbuf, BN_CTX *ctx); + +/* other interfaces to point2oct/oct2point: */ +BIGNUM *EC_POINT_point2bn(const EC_GROUP *, const EC_POINT *, + point_conversion_form_t form, BIGNUM *, BN_CTX *); +EC_POINT *EC_POINT_bn2point(const EC_GROUP *, const BIGNUM *, + EC_POINT *, BN_CTX *); +char *EC_POINT_point2hex(const EC_GROUP *, const EC_POINT *, + point_conversion_form_t form, BN_CTX *); +EC_POINT *EC_POINT_hex2point(const EC_GROUP *, const char *, + EC_POINT *, BN_CTX *); + +/********************************************************************/ +/* functions for doing EC_POINT arithmetic */ +/********************************************************************/ + +/** Computes the sum of two EC_POINT + * \param group underlying EC_GROUP object + * \param r EC_POINT object for the result (r = a + b) + * \param a EC_POINT object with the first summand + * \param b EC_POINT object with the second summand + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, + const EC_POINT *b, BN_CTX *ctx); + +/** Computes the double of a EC_POINT + * \param group underlying EC_GROUP object + * \param r EC_POINT object for the result (r = 2 * a) + * \param a EC_POINT object + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, + BN_CTX *ctx); + +/** Computes the inverse of a EC_POINT + * \param group underlying EC_GROUP object + * \param a EC_POINT object to be inverted (it's used for the result as well) + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx); + +/** Checks whether the point is the neutral element of the group + * \param group the underlying EC_GROUP object + * \param p EC_POINT object + * \return 1 if the point is the neutral element and 0 otherwise + */ +int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *p); + +/** Checks whether the point is on the curve + * \param group underlying EC_GROUP object + * \param point EC_POINT object to check + * \param ctx BN_CTX object (optional) + * \return 1 if the point is on the curve, 0 if not, or -1 on error + */ +int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, + BN_CTX *ctx); + +/** Compares two EC_POINTs + * \param group underlying EC_GROUP object + * \param a first EC_POINT object + * \param b second EC_POINT object + * \param ctx BN_CTX object (optional) + * \return 1 if the points are not equal, 0 if they are, or -1 on error + */ +int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, + BN_CTX *ctx); + +int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx); +int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, + EC_POINT *points[], BN_CTX *ctx); + +/** Computes r = generator * n + sum_{i=0}^{num-1} p[i] * m[i] + * \param group underlying EC_GROUP object + * \param r EC_POINT object for the result + * \param n BIGNUM with the multiplier for the group generator (optional) + * \param num number further summands + * \param p array of size num of EC_POINT objects + * \param m array of size num of BIGNUM objects + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n, + size_t num, const EC_POINT *p[], const BIGNUM *m[], + BN_CTX *ctx); + +/** Computes r = generator * n + q * m + * \param group underlying EC_GROUP object + * \param r EC_POINT object for the result + * \param n BIGNUM with the multiplier for the group generator (optional) + * \param q EC_POINT object with the first factor of the second summand + * \param m BIGNUM with the second factor of the second summand + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n, + const EC_POINT *q, const BIGNUM *m, BN_CTX *ctx); + +/** Stores multiples of generator for faster point multiplication + * \param group EC_GROUP object + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx); + +/** Reports whether a precomputation has been done + * \param group EC_GROUP object + * \return 1 if a pre-computation has been done and 0 otherwise + */ +int EC_GROUP_have_precompute_mult(const EC_GROUP *group); + +/********************************************************************/ +/* ASN1 stuff */ +/********************************************************************/ + +DECLARE_ASN1_ITEM(ECPKPARAMETERS) +DECLARE_ASN1_ALLOC_FUNCTIONS(ECPKPARAMETERS) +DECLARE_ASN1_ITEM(ECPARAMETERS) +DECLARE_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS) + +/* + * EC_GROUP_get_basis_type() returns the NID of the basis type used to + * represent the field elements + */ +int EC_GROUP_get_basis_type(const EC_GROUP *); +# ifndef OPENSSL_NO_EC2M +int EC_GROUP_get_trinomial_basis(const EC_GROUP *, unsigned int *k); +int EC_GROUP_get_pentanomial_basis(const EC_GROUP *, unsigned int *k1, + unsigned int *k2, unsigned int *k3); +# endif + +# define OPENSSL_EC_EXPLICIT_CURVE 0x000 +# define OPENSSL_EC_NAMED_CURVE 0x001 + +EC_GROUP *d2i_ECPKParameters(EC_GROUP **, const unsigned char **in, long len); +int i2d_ECPKParameters(const EC_GROUP *, unsigned char **out); + +# define d2i_ECPKParameters_bio(bp,x) ASN1_d2i_bio_of(EC_GROUP,NULL,d2i_ECPKParameters,bp,x) +# define i2d_ECPKParameters_bio(bp,x) ASN1_i2d_bio_of_const(EC_GROUP,i2d_ECPKParameters,bp,x) +# define d2i_ECPKParameters_fp(fp,x) (EC_GROUP *)ASN1_d2i_fp(NULL, \ + (char *(*)())d2i_ECPKParameters,(fp),(unsigned char **)(x)) +# define i2d_ECPKParameters_fp(fp,x) ASN1_i2d_fp(i2d_ECPKParameters,(fp), \ + (unsigned char *)(x)) + +int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off); +# ifndef OPENSSL_NO_STDIO +int ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off); +# endif + +/********************************************************************/ +/* EC_KEY functions */ +/********************************************************************/ + +/* some values for the encoding_flag */ +# define EC_PKEY_NO_PARAMETERS 0x001 +# define EC_PKEY_NO_PUBKEY 0x002 + +/* some values for the flags field */ +# define EC_FLAG_NON_FIPS_ALLOW 0x1 +# define EC_FLAG_FIPS_CHECKED 0x2 +# define EC_FLAG_COFACTOR_ECDH 0x1000 + +/** Creates a new EC_KEY object. + * \return EC_KEY object or NULL if an error occurred. + */ +EC_KEY *EC_KEY_new(void); + +int EC_KEY_get_flags(const EC_KEY *key); + +void EC_KEY_set_flags(EC_KEY *key, int flags); + +void EC_KEY_clear_flags(EC_KEY *key, int flags); + +/** Creates a new EC_KEY object using a named curve as underlying + * EC_GROUP object. + * \param nid NID of the named curve. + * \return EC_KEY object or NULL if an error occurred. + */ +EC_KEY *EC_KEY_new_by_curve_name(int nid); + +/** Frees a EC_KEY object. + * \param key EC_KEY object to be freed. + */ +void EC_KEY_free(EC_KEY *key); + +/** Copies a EC_KEY object. + * \param dst destination EC_KEY object + * \param src src EC_KEY object + * \return dst or NULL if an error occurred. + */ +EC_KEY *EC_KEY_copy(EC_KEY *dst, const EC_KEY *src); + +/** Creates a new EC_KEY object and copies the content from src to it. + * \param src the source EC_KEY object + * \return newly created EC_KEY object or NULL if an error occurred. + */ +EC_KEY *EC_KEY_dup(const EC_KEY *src); + +/** Increases the internal reference count of a EC_KEY object. + * \param key EC_KEY object + * \return 1 on success and 0 if an error occurred. + */ +int EC_KEY_up_ref(EC_KEY *key); + +/** Returns the ENGINE object of a EC_KEY object + * \param eckey EC_KEY object + * \return the ENGINE object (possibly NULL). + */ +ENGINE *EC_KEY_get0_engine(const EC_KEY *eckey); + +/** Returns the EC_GROUP object of a EC_KEY object + * \param key EC_KEY object + * \return the EC_GROUP object (possibly NULL). + */ +const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key); + +/** Sets the EC_GROUP of a EC_KEY object. + * \param key EC_KEY object + * \param group EC_GROUP to use in the EC_KEY object (note: the EC_KEY + * object will use an own copy of the EC_GROUP). + * \return 1 on success and 0 if an error occurred. + */ +int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group); + +/** Returns the private key of a EC_KEY object. + * \param key EC_KEY object + * \return a BIGNUM with the private key (possibly NULL). + */ +const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key); + +/** Sets the private key of a EC_KEY object. + * \param key EC_KEY object + * \param prv BIGNUM with the private key (note: the EC_KEY object + * will use an own copy of the BIGNUM). + * \return 1 on success and 0 if an error occurred. + */ +int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *prv); + +/** Returns the public key of a EC_KEY object. + * \param key the EC_KEY object + * \return a EC_POINT object with the public key (possibly NULL) + */ +const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key); + +/** Sets the public key of a EC_KEY object. + * \param key EC_KEY object + * \param pub EC_POINT object with the public key (note: the EC_KEY object + * will use an own copy of the EC_POINT object). + * \return 1 on success and 0 if an error occurred. + */ +int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub); + +unsigned EC_KEY_get_enc_flags(const EC_KEY *key); +void EC_KEY_set_enc_flags(EC_KEY *eckey, unsigned int flags); +point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key); +void EC_KEY_set_conv_form(EC_KEY *eckey, point_conversion_form_t cform); + +#define EC_KEY_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_EC_KEY, l, p, newf, dupf, freef) +int EC_KEY_set_ex_data(EC_KEY *key, int idx, void *arg); +void *EC_KEY_get_ex_data(const EC_KEY *key, int idx); + +/* wrapper functions for the underlying EC_GROUP object */ +void EC_KEY_set_asn1_flag(EC_KEY *eckey, int asn1_flag); + +/** Creates a table of pre-computed multiples of the generator to + * accelerate further EC_KEY operations. + * \param key EC_KEY object + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred. + */ +int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx); + +/** Creates a new ec private (and optional a new public) key. + * \param key EC_KEY object + * \return 1 on success and 0 if an error occurred. + */ +int EC_KEY_generate_key(EC_KEY *key); + +/** Verifies that a private and/or public key is valid. + * \param key the EC_KEY object + * \return 1 on success and 0 otherwise. + */ +int EC_KEY_check_key(const EC_KEY *key); + +/** Indicates if an EC_KEY can be used for signing. + * \param eckey the EC_KEY object + * \return 1 if can can sign and 0 otherwise. + */ +int EC_KEY_can_sign(const EC_KEY *eckey); + +/** Sets a public key from affine coordinates performing + * necessary NIST PKV tests. + * \param key the EC_KEY object + * \param x public key x coordinate + * \param y public key y coordinate + * \return 1 on success and 0 otherwise. + */ +int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, + BIGNUM *y); + +/** Encodes an EC_KEY public key to an allocated octet string + * \param key key to encode + * \param form point conversion form + * \param pbuf returns pointer to allocated buffer + * \param ctx BN_CTX object (optional) + * \return the length of the encoded octet string or 0 if an error occurred + */ +size_t EC_KEY_key2buf(const EC_KEY *key, point_conversion_form_t form, + unsigned char **pbuf, BN_CTX *ctx); + +/** Decodes a EC_KEY public key from a octet string + * \param key key to decode + * \param buf memory buffer with the encoded ec point + * \param len length of the encoded ec point + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ + +int EC_KEY_oct2key(EC_KEY *key, const unsigned char *buf, size_t len, + BN_CTX *ctx); + +/** Decodes an EC_KEY private key from an octet string + * \param key key to decode + * \param buf memory buffer with the encoded private key + * \param len length of the encoded key + * \return 1 on success and 0 if an error occurred + */ + +int EC_KEY_oct2priv(EC_KEY *key, const unsigned char *buf, size_t len); + +/** Encodes a EC_KEY private key to an octet string + * \param key key to encode + * \param buf memory buffer for the result. If NULL the function returns + * required buffer size. + * \param len length of the memory buffer + * \return the length of the encoded octet string or 0 if an error occurred + */ + +size_t EC_KEY_priv2oct(const EC_KEY *key, unsigned char *buf, size_t len); + +/** Encodes an EC_KEY private key to an allocated octet string + * \param eckey key to encode + * \param pbuf returns pointer to allocated buffer + * \return the length of the encoded octet string or 0 if an error occurred + */ +size_t EC_KEY_priv2buf(const EC_KEY *eckey, unsigned char **pbuf); + +/********************************************************************/ +/* de- and encoding functions for SEC1 ECPrivateKey */ +/********************************************************************/ + +/** Decodes a private key from a memory buffer. + * \param key a pointer to a EC_KEY object which should be used (or NULL) + * \param in pointer to memory with the DER encoded private key + * \param len length of the DER encoded private key + * \return the decoded private key or NULL if an error occurred. + */ +EC_KEY *d2i_ECPrivateKey(EC_KEY **key, const unsigned char **in, long len); + +/** Encodes a private key object and stores the result in a buffer. + * \param key the EC_KEY object to encode + * \param out the buffer for the result (if NULL the function returns number + * of bytes needed). + * \return 1 on success and 0 if an error occurred. + */ +int i2d_ECPrivateKey(EC_KEY *key, unsigned char **out); + +/********************************************************************/ +/* de- and encoding functions for EC parameters */ +/********************************************************************/ + +/** Decodes ec parameter from a memory buffer. + * \param key a pointer to a EC_KEY object which should be used (or NULL) + * \param in pointer to memory with the DER encoded ec parameters + * \param len length of the DER encoded ec parameters + * \return a EC_KEY object with the decoded parameters or NULL if an error + * occurred. + */ +EC_KEY *d2i_ECParameters(EC_KEY **key, const unsigned char **in, long len); + +/** Encodes ec parameter and stores the result in a buffer. + * \param key the EC_KEY object with ec parameters to encode + * \param out the buffer for the result (if NULL the function returns number + * of bytes needed). + * \return 1 on success and 0 if an error occurred. + */ +int i2d_ECParameters(EC_KEY *key, unsigned char **out); + +/********************************************************************/ +/* de- and encoding functions for EC public key */ +/* (octet string, not DER -- hence 'o2i' and 'i2o') */ +/********************************************************************/ + +/** Decodes a ec public key from a octet string. + * \param key a pointer to a EC_KEY object which should be used + * \param in memory buffer with the encoded public key + * \param len length of the encoded public key + * \return EC_KEY object with decoded public key or NULL if an error + * occurred. + */ +EC_KEY *o2i_ECPublicKey(EC_KEY **key, const unsigned char **in, long len); + +/** Encodes a ec public key in an octet string. + * \param key the EC_KEY object with the public key + * \param out the buffer for the result (if NULL the function returns number + * of bytes needed). + * \return 1 on success and 0 if an error occurred + */ +int i2o_ECPublicKey(const EC_KEY *key, unsigned char **out); + +/** Prints out the ec parameters on human readable form. + * \param bp BIO object to which the information is printed + * \param key EC_KEY object + * \return 1 on success and 0 if an error occurred + */ +int ECParameters_print(BIO *bp, const EC_KEY *key); + +/** Prints out the contents of a EC_KEY object + * \param bp BIO object to which the information is printed + * \param key EC_KEY object + * \param off line offset + * \return 1 on success and 0 if an error occurred + */ +int EC_KEY_print(BIO *bp, const EC_KEY *key, int off); + +# ifndef OPENSSL_NO_STDIO +/** Prints out the ec parameters on human readable form. + * \param fp file descriptor to which the information is printed + * \param key EC_KEY object + * \return 1 on success and 0 if an error occurred + */ +int ECParameters_print_fp(FILE *fp, const EC_KEY *key); + +/** Prints out the contents of a EC_KEY object + * \param fp file descriptor to which the information is printed + * \param key EC_KEY object + * \param off line offset + * \return 1 on success and 0 if an error occurred + */ +int EC_KEY_print_fp(FILE *fp, const EC_KEY *key, int off); + +# endif + +const EC_KEY_METHOD *EC_KEY_OpenSSL(void); +const EC_KEY_METHOD *EC_KEY_get_default_method(void); +void EC_KEY_set_default_method(const EC_KEY_METHOD *meth); +const EC_KEY_METHOD *EC_KEY_get_method(const EC_KEY *key); +int EC_KEY_set_method(EC_KEY *key, const EC_KEY_METHOD *meth); +EC_KEY *EC_KEY_new_method(ENGINE *engine); + +/** The old name for ecdh_KDF_X9_63 + * The ECDH KDF specification has been mistakingly attributed to ANSI X9.62, + * it is actually specified in ANSI X9.63. + * This identifier is retained for backwards compatibility + */ +int ECDH_KDF_X9_62(unsigned char *out, size_t outlen, + const unsigned char *Z, size_t Zlen, + const unsigned char *sinfo, size_t sinfolen, + const EVP_MD *md); + +int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, + const EC_KEY *ecdh, + void *(*KDF) (const void *in, size_t inlen, + void *out, size_t *outlen)); + +typedef struct ECDSA_SIG_st ECDSA_SIG; + +/** Allocates and initialize a ECDSA_SIG structure + * \return pointer to a ECDSA_SIG structure or NULL if an error occurred + */ +ECDSA_SIG *ECDSA_SIG_new(void); + +/** frees a ECDSA_SIG structure + * \param sig pointer to the ECDSA_SIG structure + */ +void ECDSA_SIG_free(ECDSA_SIG *sig); + +/** DER encode content of ECDSA_SIG object (note: this function modifies *pp + * (*pp += length of the DER encoded signature)). + * \param sig pointer to the ECDSA_SIG object + * \param pp pointer to a unsigned char pointer for the output or NULL + * \return the length of the DER encoded ECDSA_SIG object or 0 + */ +int i2d_ECDSA_SIG(const ECDSA_SIG *sig, unsigned char **pp); + +/** Decodes a DER encoded ECDSA signature (note: this function changes *pp + * (*pp += len)). + * \param sig pointer to ECDSA_SIG pointer (may be NULL) + * \param pp memory buffer with the DER encoded signature + * \param len length of the buffer + * \return pointer to the decoded ECDSA_SIG structure (or NULL) + */ +ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **sig, const unsigned char **pp, long len); + +/** Accessor for r and s fields of ECDSA_SIG + * \param sig pointer to ECDSA_SIG structure + * \param pr pointer to BIGNUM pointer for r (may be NULL) + * \param ps pointer to BIGNUM pointer for s (may be NULL) + */ +void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps); + +/** Accessor for r field of ECDSA_SIG + * \param sig pointer to ECDSA_SIG structure + */ +const BIGNUM *ECDSA_SIG_get0_r(const ECDSA_SIG *sig); + +/** Accessor for s field of ECDSA_SIG + * \param sig pointer to ECDSA_SIG structure + */ +const BIGNUM *ECDSA_SIG_get0_s(const ECDSA_SIG *sig); + +/** Setter for r and s fields of ECDSA_SIG + * \param sig pointer to ECDSA_SIG structure + * \param r pointer to BIGNUM for r (may be NULL) + * \param s pointer to BIGNUM for s (may be NULL) + */ +int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s); + +/** Computes the ECDSA signature of the given hash value using + * the supplied private key and returns the created signature. + * \param dgst pointer to the hash value + * \param dgst_len length of the hash value + * \param eckey EC_KEY object containing a private EC key + * \return pointer to a ECDSA_SIG structure or NULL if an error occurred + */ +ECDSA_SIG *ECDSA_do_sign(const unsigned char *dgst, int dgst_len, + EC_KEY *eckey); + +/** Computes ECDSA signature of a given hash value using the supplied + * private key (note: sig must point to ECDSA_size(eckey) bytes of memory). + * \param dgst pointer to the hash value to sign + * \param dgstlen length of the hash value + * \param kinv BIGNUM with a pre-computed inverse k (optional) + * \param rp BIGNUM with a pre-computed rp value (optional), + * see ECDSA_sign_setup + * \param eckey EC_KEY object containing a private EC key + * \return pointer to a ECDSA_SIG structure or NULL if an error occurred + */ +ECDSA_SIG *ECDSA_do_sign_ex(const unsigned char *dgst, int dgstlen, + const BIGNUM *kinv, const BIGNUM *rp, + EC_KEY *eckey); + +/** Verifies that the supplied signature is a valid ECDSA + * signature of the supplied hash value using the supplied public key. + * \param dgst pointer to the hash value + * \param dgst_len length of the hash value + * \param sig ECDSA_SIG structure + * \param eckey EC_KEY object containing a public EC key + * \return 1 if the signature is valid, 0 if the signature is invalid + * and -1 on error + */ +int ECDSA_do_verify(const unsigned char *dgst, int dgst_len, + const ECDSA_SIG *sig, EC_KEY *eckey); + +/** Precompute parts of the signing operation + * \param eckey EC_KEY object containing a private EC key + * \param ctx BN_CTX object (optional) + * \param kinv BIGNUM pointer for the inverse of k + * \param rp BIGNUM pointer for x coordinate of k * generator + * \return 1 on success and 0 otherwise + */ +int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, BIGNUM **rp); + +/** Computes ECDSA signature of a given hash value using the supplied + * private key (note: sig must point to ECDSA_size(eckey) bytes of memory). + * \param type this parameter is ignored + * \param dgst pointer to the hash value to sign + * \param dgstlen length of the hash value + * \param sig memory for the DER encoded created signature + * \param siglen pointer to the length of the returned signature + * \param eckey EC_KEY object containing a private EC key + * \return 1 on success and 0 otherwise + */ +int ECDSA_sign(int type, const unsigned char *dgst, int dgstlen, + unsigned char *sig, unsigned int *siglen, EC_KEY *eckey); + +/** Computes ECDSA signature of a given hash value using the supplied + * private key (note: sig must point to ECDSA_size(eckey) bytes of memory). + * \param type this parameter is ignored + * \param dgst pointer to the hash value to sign + * \param dgstlen length of the hash value + * \param sig buffer to hold the DER encoded signature + * \param siglen pointer to the length of the returned signature + * \param kinv BIGNUM with a pre-computed inverse k (optional) + * \param rp BIGNUM with a pre-computed rp value (optional), + * see ECDSA_sign_setup + * \param eckey EC_KEY object containing a private EC key + * \return 1 on success and 0 otherwise + */ +int ECDSA_sign_ex(int type, const unsigned char *dgst, int dgstlen, + unsigned char *sig, unsigned int *siglen, + const BIGNUM *kinv, const BIGNUM *rp, EC_KEY *eckey); + +/** Verifies that the given signature is valid ECDSA signature + * of the supplied hash value using the specified public key. + * \param type this parameter is ignored + * \param dgst pointer to the hash value + * \param dgstlen length of the hash value + * \param sig pointer to the DER encoded signature + * \param siglen length of the DER encoded signature + * \param eckey EC_KEY object containing a public EC key + * \return 1 if the signature is valid, 0 if the signature is invalid + * and -1 on error + */ +int ECDSA_verify(int type, const unsigned char *dgst, int dgstlen, + const unsigned char *sig, int siglen, EC_KEY *eckey); + +/** Returns the maximum length of the DER encoded signature + * \param eckey EC_KEY object + * \return numbers of bytes required for the DER encoded signature + */ +int ECDSA_size(const EC_KEY *eckey); + +/********************************************************************/ +/* EC_KEY_METHOD constructors, destructors, writers and accessors */ +/********************************************************************/ + +EC_KEY_METHOD *EC_KEY_METHOD_new(const EC_KEY_METHOD *meth); +void EC_KEY_METHOD_free(EC_KEY_METHOD *meth); +void EC_KEY_METHOD_set_init(EC_KEY_METHOD *meth, + int (*init)(EC_KEY *key), + void (*finish)(EC_KEY *key), + int (*copy)(EC_KEY *dest, const EC_KEY *src), + int (*set_group)(EC_KEY *key, const EC_GROUP *grp), + int (*set_private)(EC_KEY *key, + const BIGNUM *priv_key), + int (*set_public)(EC_KEY *key, + const EC_POINT *pub_key)); + +void EC_KEY_METHOD_set_keygen(EC_KEY_METHOD *meth, + int (*keygen)(EC_KEY *key)); + +void EC_KEY_METHOD_set_compute_key(EC_KEY_METHOD *meth, + int (*ckey)(unsigned char **psec, + size_t *pseclen, + const EC_POINT *pub_key, + const EC_KEY *ecdh)); + +void EC_KEY_METHOD_set_sign(EC_KEY_METHOD *meth, + int (*sign)(int type, const unsigned char *dgst, + int dlen, unsigned char *sig, + unsigned int *siglen, + const BIGNUM *kinv, const BIGNUM *r, + EC_KEY *eckey), + int (*sign_setup)(EC_KEY *eckey, BN_CTX *ctx_in, + BIGNUM **kinvp, BIGNUM **rp), + ECDSA_SIG *(*sign_sig)(const unsigned char *dgst, + int dgst_len, + const BIGNUM *in_kinv, + const BIGNUM *in_r, + EC_KEY *eckey)); + +void EC_KEY_METHOD_set_verify(EC_KEY_METHOD *meth, + int (*verify)(int type, const unsigned + char *dgst, int dgst_len, + const unsigned char *sigbuf, + int sig_len, EC_KEY *eckey), + int (*verify_sig)(const unsigned char *dgst, + int dgst_len, + const ECDSA_SIG *sig, + EC_KEY *eckey)); + +void EC_KEY_METHOD_get_init(const EC_KEY_METHOD *meth, + int (**pinit)(EC_KEY *key), + void (**pfinish)(EC_KEY *key), + int (**pcopy)(EC_KEY *dest, const EC_KEY *src), + int (**pset_group)(EC_KEY *key, + const EC_GROUP *grp), + int (**pset_private)(EC_KEY *key, + const BIGNUM *priv_key), + int (**pset_public)(EC_KEY *key, + const EC_POINT *pub_key)); + +void EC_KEY_METHOD_get_keygen(const EC_KEY_METHOD *meth, + int (**pkeygen)(EC_KEY *key)); + +void EC_KEY_METHOD_get_compute_key(const EC_KEY_METHOD *meth, + int (**pck)(unsigned char **psec, + size_t *pseclen, + const EC_POINT *pub_key, + const EC_KEY *ecdh)); + +void EC_KEY_METHOD_get_sign(const EC_KEY_METHOD *meth, + int (**psign)(int type, const unsigned char *dgst, + int dlen, unsigned char *sig, + unsigned int *siglen, + const BIGNUM *kinv, const BIGNUM *r, + EC_KEY *eckey), + int (**psign_setup)(EC_KEY *eckey, BN_CTX *ctx_in, + BIGNUM **kinvp, BIGNUM **rp), + ECDSA_SIG *(**psign_sig)(const unsigned char *dgst, + int dgst_len, + const BIGNUM *in_kinv, + const BIGNUM *in_r, + EC_KEY *eckey)); + +void EC_KEY_METHOD_get_verify(const EC_KEY_METHOD *meth, + int (**pverify)(int type, const unsigned + char *dgst, int dgst_len, + const unsigned char *sigbuf, + int sig_len, EC_KEY *eckey), + int (**pverify_sig)(const unsigned char *dgst, + int dgst_len, + const ECDSA_SIG *sig, + EC_KEY *eckey)); + +# define ECParameters_dup(x) ASN1_dup_of(EC_KEY,i2d_ECParameters,d2i_ECParameters,x) + +# ifndef __cplusplus +# if defined(__SUNPRO_C) +# if __SUNPRO_C >= 0x520 +# pragma error_messages (default,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE) +# endif +# endif +# endif + +# define EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_PARAMGEN|EVP_PKEY_OP_KEYGEN, \ + EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, nid, NULL) + +# define EVP_PKEY_CTX_set_ec_param_enc(ctx, flag) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_PARAMGEN|EVP_PKEY_OP_KEYGEN, \ + EVP_PKEY_CTRL_EC_PARAM_ENC, flag, NULL) + +# define EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, flag) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_EC_ECDH_COFACTOR, flag, NULL) + +# define EVP_PKEY_CTX_get_ecdh_cofactor_mode(ctx) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_EC_ECDH_COFACTOR, -2, NULL) + +# define EVP_PKEY_CTX_set_ecdh_kdf_type(ctx, kdf) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_EC_KDF_TYPE, kdf, NULL) + +# define EVP_PKEY_CTX_get_ecdh_kdf_type(ctx) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_EC_KDF_TYPE, -2, NULL) + +# define EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_EC_KDF_MD, 0, (void *)(md)) + +# define EVP_PKEY_CTX_get_ecdh_kdf_md(ctx, pmd) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_GET_EC_KDF_MD, 0, (void *)(pmd)) + +# define EVP_PKEY_CTX_set_ecdh_kdf_outlen(ctx, len) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_EC_KDF_OUTLEN, len, NULL) + +# define EVP_PKEY_CTX_get_ecdh_kdf_outlen(ctx, plen) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN, 0, \ + (void *)(plen)) + +# define EVP_PKEY_CTX_set0_ecdh_kdf_ukm(ctx, p, plen) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_EC_KDF_UKM, plen, (void *)(p)) + +# define EVP_PKEY_CTX_get0_ecdh_kdf_ukm(ctx, p) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_GET_EC_KDF_UKM, 0, (void *)(p)) + +/* SM2 will skip the operation check so no need to pass operation here */ +# define EVP_PKEY_CTX_set1_id(ctx, id, id_len) \ + EVP_PKEY_CTX_ctrl(ctx, -1, -1, \ + EVP_PKEY_CTRL_SET1_ID, (int)id_len, (void*)(id)) + +# define EVP_PKEY_CTX_get1_id(ctx, id) \ + EVP_PKEY_CTX_ctrl(ctx, -1, -1, \ + EVP_PKEY_CTRL_GET1_ID, 0, (void*)(id)) + +# define EVP_PKEY_CTX_get1_id_len(ctx, id_len) \ + EVP_PKEY_CTX_ctrl(ctx, -1, -1, \ + EVP_PKEY_CTRL_GET1_ID_LEN, 0, (void*)(id_len)) + +# define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID (EVP_PKEY_ALG_CTRL + 1) +# define EVP_PKEY_CTRL_EC_PARAM_ENC (EVP_PKEY_ALG_CTRL + 2) +# define EVP_PKEY_CTRL_EC_ECDH_COFACTOR (EVP_PKEY_ALG_CTRL + 3) +# define EVP_PKEY_CTRL_EC_KDF_TYPE (EVP_PKEY_ALG_CTRL + 4) +# define EVP_PKEY_CTRL_EC_KDF_MD (EVP_PKEY_ALG_CTRL + 5) +# define EVP_PKEY_CTRL_GET_EC_KDF_MD (EVP_PKEY_ALG_CTRL + 6) +# define EVP_PKEY_CTRL_EC_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 7) +# define EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 8) +# define EVP_PKEY_CTRL_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 9) +# define EVP_PKEY_CTRL_GET_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 10) +# define EVP_PKEY_CTRL_SET1_ID (EVP_PKEY_ALG_CTRL + 11) +# define EVP_PKEY_CTRL_GET1_ID (EVP_PKEY_ALG_CTRL + 12) +# define EVP_PKEY_CTRL_GET1_ID_LEN (EVP_PKEY_ALG_CTRL + 13) +/* KDF types */ +# define EVP_PKEY_ECDH_KDF_NONE 1 +# define EVP_PKEY_ECDH_KDF_X9_63 2 +/** The old name for EVP_PKEY_ECDH_KDF_X9_63 + * The ECDH KDF specification has been mistakingly attributed to ANSI X9.62, + * it is actually specified in ANSI X9.63. + * This identifier is retained for backwards compatibility + */ +# define EVP_PKEY_ECDH_KDF_X9_62 EVP_PKEY_ECDH_KDF_X9_63 + + +# ifdef __cplusplus +} +# endif +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/ecdh.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ecdh.h new file mode 100644 index 000000000..681f3d5e5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ecdh.h @@ -0,0 +1,10 @@ +/* + * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/ecdsa.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ecdsa.h new file mode 100644 index 000000000..681f3d5e5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ecdsa.h @@ -0,0 +1,10 @@ +/* + * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/ecerr.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ecerr.h new file mode 100644 index 000000000..be313d285 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ecerr.h @@ -0,0 +1,271 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_ECERR_H +# define HEADER_ECERR_H + +# include + +# ifndef OPENSSL_NO_EC + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_EC_strings(void); + +/* + * EC function codes. + */ +# define EC_F_BN_TO_FELEM 224 +# define EC_F_D2I_ECPARAMETERS 144 +# define EC_F_D2I_ECPKPARAMETERS 145 +# define EC_F_D2I_ECPRIVATEKEY 146 +# define EC_F_DO_EC_KEY_PRINT 221 +# define EC_F_ECDH_CMS_DECRYPT 238 +# define EC_F_ECDH_CMS_SET_SHARED_INFO 239 +# define EC_F_ECDH_COMPUTE_KEY 246 +# define EC_F_ECDH_SIMPLE_COMPUTE_KEY 257 +# define EC_F_ECDSA_DO_SIGN_EX 251 +# define EC_F_ECDSA_DO_VERIFY 252 +# define EC_F_ECDSA_SIGN_EX 254 +# define EC_F_ECDSA_SIGN_SETUP 248 +# define EC_F_ECDSA_SIG_NEW 265 +# define EC_F_ECDSA_VERIFY 253 +# define EC_F_ECD_ITEM_VERIFY 270 +# define EC_F_ECKEY_PARAM2TYPE 223 +# define EC_F_ECKEY_PARAM_DECODE 212 +# define EC_F_ECKEY_PRIV_DECODE 213 +# define EC_F_ECKEY_PRIV_ENCODE 214 +# define EC_F_ECKEY_PUB_DECODE 215 +# define EC_F_ECKEY_PUB_ENCODE 216 +# define EC_F_ECKEY_TYPE2PARAM 220 +# define EC_F_ECPARAMETERS_PRINT 147 +# define EC_F_ECPARAMETERS_PRINT_FP 148 +# define EC_F_ECPKPARAMETERS_PRINT 149 +# define EC_F_ECPKPARAMETERS_PRINT_FP 150 +# define EC_F_ECP_NISTZ256_GET_AFFINE 240 +# define EC_F_ECP_NISTZ256_INV_MOD_ORD 275 +# define EC_F_ECP_NISTZ256_MULT_PRECOMPUTE 243 +# define EC_F_ECP_NISTZ256_POINTS_MUL 241 +# define EC_F_ECP_NISTZ256_PRE_COMP_NEW 244 +# define EC_F_ECP_NISTZ256_WINDOWED_MUL 242 +# define EC_F_ECX_KEY_OP 266 +# define EC_F_ECX_PRIV_ENCODE 267 +# define EC_F_ECX_PUB_ENCODE 268 +# define EC_F_EC_ASN1_GROUP2CURVE 153 +# define EC_F_EC_ASN1_GROUP2FIELDID 154 +# define EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY 208 +# define EC_F_EC_GF2M_SIMPLE_FIELD_INV 296 +# define EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT 159 +# define EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE 195 +# define EC_F_EC_GF2M_SIMPLE_LADDER_POST 285 +# define EC_F_EC_GF2M_SIMPLE_LADDER_PRE 288 +# define EC_F_EC_GF2M_SIMPLE_OCT2POINT 160 +# define EC_F_EC_GF2M_SIMPLE_POINT2OCT 161 +# define EC_F_EC_GF2M_SIMPLE_POINTS_MUL 289 +# define EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES 162 +# define EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES 163 +# define EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES 164 +# define EC_F_EC_GFP_MONT_FIELD_DECODE 133 +# define EC_F_EC_GFP_MONT_FIELD_ENCODE 134 +# define EC_F_EC_GFP_MONT_FIELD_INV 297 +# define EC_F_EC_GFP_MONT_FIELD_MUL 131 +# define EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE 209 +# define EC_F_EC_GFP_MONT_FIELD_SQR 132 +# define EC_F_EC_GFP_MONT_GROUP_SET_CURVE 189 +# define EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE 225 +# define EC_F_EC_GFP_NISTP224_POINTS_MUL 228 +# define EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES 226 +# define EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE 230 +# define EC_F_EC_GFP_NISTP256_POINTS_MUL 231 +# define EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES 232 +# define EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE 233 +# define EC_F_EC_GFP_NISTP521_POINTS_MUL 234 +# define EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES 235 +# define EC_F_EC_GFP_NIST_FIELD_MUL 200 +# define EC_F_EC_GFP_NIST_FIELD_SQR 201 +# define EC_F_EC_GFP_NIST_GROUP_SET_CURVE 202 +# define EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES 287 +# define EC_F_EC_GFP_SIMPLE_FIELD_INV 298 +# define EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT 165 +# define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE 166 +# define EC_F_EC_GFP_SIMPLE_MAKE_AFFINE 102 +# define EC_F_EC_GFP_SIMPLE_OCT2POINT 103 +# define EC_F_EC_GFP_SIMPLE_POINT2OCT 104 +# define EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE 137 +# define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES 167 +# define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES 168 +# define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES 169 +# define EC_F_EC_GROUP_CHECK 170 +# define EC_F_EC_GROUP_CHECK_DISCRIMINANT 171 +# define EC_F_EC_GROUP_COPY 106 +# define EC_F_EC_GROUP_GET_CURVE 291 +# define EC_F_EC_GROUP_GET_CURVE_GF2M 172 +# define EC_F_EC_GROUP_GET_CURVE_GFP 130 +# define EC_F_EC_GROUP_GET_DEGREE 173 +# define EC_F_EC_GROUP_GET_ECPARAMETERS 261 +# define EC_F_EC_GROUP_GET_ECPKPARAMETERS 262 +# define EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS 193 +# define EC_F_EC_GROUP_GET_TRINOMIAL_BASIS 194 +# define EC_F_EC_GROUP_NEW 108 +# define EC_F_EC_GROUP_NEW_BY_CURVE_NAME 174 +# define EC_F_EC_GROUP_NEW_FROM_DATA 175 +# define EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS 263 +# define EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS 264 +# define EC_F_EC_GROUP_SET_CURVE 292 +# define EC_F_EC_GROUP_SET_CURVE_GF2M 176 +# define EC_F_EC_GROUP_SET_CURVE_GFP 109 +# define EC_F_EC_GROUP_SET_GENERATOR 111 +# define EC_F_EC_GROUP_SET_SEED 286 +# define EC_F_EC_KEY_CHECK_KEY 177 +# define EC_F_EC_KEY_COPY 178 +# define EC_F_EC_KEY_GENERATE_KEY 179 +# define EC_F_EC_KEY_NEW 182 +# define EC_F_EC_KEY_NEW_METHOD 245 +# define EC_F_EC_KEY_OCT2PRIV 255 +# define EC_F_EC_KEY_PRINT 180 +# define EC_F_EC_KEY_PRINT_FP 181 +# define EC_F_EC_KEY_PRIV2BUF 279 +# define EC_F_EC_KEY_PRIV2OCT 256 +# define EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES 229 +# define EC_F_EC_KEY_SIMPLE_CHECK_KEY 258 +# define EC_F_EC_KEY_SIMPLE_OCT2PRIV 259 +# define EC_F_EC_KEY_SIMPLE_PRIV2OCT 260 +# define EC_F_EC_PKEY_CHECK 273 +# define EC_F_EC_PKEY_PARAM_CHECK 274 +# define EC_F_EC_POINTS_MAKE_AFFINE 136 +# define EC_F_EC_POINTS_MUL 290 +# define EC_F_EC_POINT_ADD 112 +# define EC_F_EC_POINT_BN2POINT 280 +# define EC_F_EC_POINT_CMP 113 +# define EC_F_EC_POINT_COPY 114 +# define EC_F_EC_POINT_DBL 115 +# define EC_F_EC_POINT_GET_AFFINE_COORDINATES 293 +# define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M 183 +# define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP 116 +# define EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP 117 +# define EC_F_EC_POINT_INVERT 210 +# define EC_F_EC_POINT_IS_AT_INFINITY 118 +# define EC_F_EC_POINT_IS_ON_CURVE 119 +# define EC_F_EC_POINT_MAKE_AFFINE 120 +# define EC_F_EC_POINT_NEW 121 +# define EC_F_EC_POINT_OCT2POINT 122 +# define EC_F_EC_POINT_POINT2BUF 281 +# define EC_F_EC_POINT_POINT2OCT 123 +# define EC_F_EC_POINT_SET_AFFINE_COORDINATES 294 +# define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M 185 +# define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP 124 +# define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES 295 +# define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M 186 +# define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP 125 +# define EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP 126 +# define EC_F_EC_POINT_SET_TO_INFINITY 127 +# define EC_F_EC_PRE_COMP_NEW 196 +# define EC_F_EC_SCALAR_MUL_LADDER 284 +# define EC_F_EC_WNAF_MUL 187 +# define EC_F_EC_WNAF_PRECOMPUTE_MULT 188 +# define EC_F_I2D_ECPARAMETERS 190 +# define EC_F_I2D_ECPKPARAMETERS 191 +# define EC_F_I2D_ECPRIVATEKEY 192 +# define EC_F_I2O_ECPUBLICKEY 151 +# define EC_F_NISTP224_PRE_COMP_NEW 227 +# define EC_F_NISTP256_PRE_COMP_NEW 236 +# define EC_F_NISTP521_PRE_COMP_NEW 237 +# define EC_F_O2I_ECPUBLICKEY 152 +# define EC_F_OLD_EC_PRIV_DECODE 222 +# define EC_F_OSSL_ECDH_COMPUTE_KEY 247 +# define EC_F_OSSL_ECDSA_SIGN_SIG 249 +# define EC_F_OSSL_ECDSA_VERIFY_SIG 250 +# define EC_F_PKEY_ECD_CTRL 271 +# define EC_F_PKEY_ECD_DIGESTSIGN 272 +# define EC_F_PKEY_ECD_DIGESTSIGN25519 276 +# define EC_F_PKEY_ECD_DIGESTSIGN448 277 +# define EC_F_PKEY_ECX_DERIVE 269 +# define EC_F_PKEY_EC_CTRL 197 +# define EC_F_PKEY_EC_CTRL_STR 198 +# define EC_F_PKEY_EC_DERIVE 217 +# define EC_F_PKEY_EC_INIT 282 +# define EC_F_PKEY_EC_KDF_DERIVE 283 +# define EC_F_PKEY_EC_KEYGEN 199 +# define EC_F_PKEY_EC_PARAMGEN 219 +# define EC_F_PKEY_EC_SIGN 218 +# define EC_F_VALIDATE_ECX_DERIVE 278 + +/* + * EC reason codes. + */ +# define EC_R_ASN1_ERROR 115 +# define EC_R_BAD_SIGNATURE 156 +# define EC_R_BIGNUM_OUT_OF_RANGE 144 +# define EC_R_BUFFER_TOO_SMALL 100 +# define EC_R_CANNOT_INVERT 165 +# define EC_R_COORDINATES_OUT_OF_RANGE 146 +# define EC_R_CURVE_DOES_NOT_SUPPORT_ECDH 160 +# define EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING 159 +# define EC_R_D2I_ECPKPARAMETERS_FAILURE 117 +# define EC_R_DECODE_ERROR 142 +# define EC_R_DISCRIMINANT_IS_ZERO 118 +# define EC_R_EC_GROUP_NEW_BY_NAME_FAILURE 119 +# define EC_R_FIELD_TOO_LARGE 143 +# define EC_R_GF2M_NOT_SUPPORTED 147 +# define EC_R_GROUP2PKPARAMETERS_FAILURE 120 +# define EC_R_I2D_ECPKPARAMETERS_FAILURE 121 +# define EC_R_INCOMPATIBLE_OBJECTS 101 +# define EC_R_INVALID_ARGUMENT 112 +# define EC_R_INVALID_COMPRESSED_POINT 110 +# define EC_R_INVALID_COMPRESSION_BIT 109 +# define EC_R_INVALID_CURVE 141 +# define EC_R_INVALID_DIGEST 151 +# define EC_R_INVALID_DIGEST_TYPE 138 +# define EC_R_INVALID_ENCODING 102 +# define EC_R_INVALID_FIELD 103 +# define EC_R_INVALID_FORM 104 +# define EC_R_INVALID_GROUP_ORDER 122 +# define EC_R_INVALID_KEY 116 +# define EC_R_INVALID_OUTPUT_LENGTH 161 +# define EC_R_INVALID_PEER_KEY 133 +# define EC_R_INVALID_PENTANOMIAL_BASIS 132 +# define EC_R_INVALID_PRIVATE_KEY 123 +# define EC_R_INVALID_TRINOMIAL_BASIS 137 +# define EC_R_KDF_PARAMETER_ERROR 148 +# define EC_R_KEYS_NOT_SET 140 +# define EC_R_LADDER_POST_FAILURE 136 +# define EC_R_LADDER_PRE_FAILURE 153 +# define EC_R_LADDER_STEP_FAILURE 162 +# define EC_R_MISSING_PARAMETERS 124 +# define EC_R_MISSING_PRIVATE_KEY 125 +# define EC_R_NEED_NEW_SETUP_VALUES 157 +# define EC_R_NOT_A_NIST_PRIME 135 +# define EC_R_NOT_IMPLEMENTED 126 +# define EC_R_NOT_INITIALIZED 111 +# define EC_R_NO_PARAMETERS_SET 139 +# define EC_R_NO_PRIVATE_VALUE 154 +# define EC_R_OPERATION_NOT_SUPPORTED 152 +# define EC_R_PASSED_NULL_PARAMETER 134 +# define EC_R_PEER_KEY_ERROR 149 +# define EC_R_PKPARAMETERS2GROUP_FAILURE 127 +# define EC_R_POINT_ARITHMETIC_FAILURE 155 +# define EC_R_POINT_AT_INFINITY 106 +# define EC_R_POINT_COORDINATES_BLIND_FAILURE 163 +# define EC_R_POINT_IS_NOT_ON_CURVE 107 +# define EC_R_RANDOM_NUMBER_GENERATION_FAILED 158 +# define EC_R_SHARED_INFO_ERROR 150 +# define EC_R_SLOT_FULL 108 +# define EC_R_UNDEFINED_GENERATOR 113 +# define EC_R_UNDEFINED_ORDER 128 +# define EC_R_UNKNOWN_COFACTOR 164 +# define EC_R_UNKNOWN_GROUP 129 +# define EC_R_UNKNOWN_ORDER 114 +# define EC_R_UNSUPPORTED_FIELD 131 +# define EC_R_WRONG_CURVE_PARAMETERS 145 +# define EC_R_WRONG_ORDER 130 + +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/engine.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/engine.h new file mode 100644 index 000000000..0780f0fb5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/engine.h @@ -0,0 +1,751 @@ +/* + * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_ENGINE_H +# define HEADER_ENGINE_H + +# include + +# ifndef OPENSSL_NO_ENGINE +# if OPENSSL_API_COMPAT < 0x10100000L +# include +# include +# include +# include +# include +# include +# include +# include +# endif +# include +# include +# include +# include +# ifdef __cplusplus +extern "C" { +# endif + +/* + * These flags are used to control combinations of algorithm (methods) by + * bitwise "OR"ing. + */ +# define ENGINE_METHOD_RSA (unsigned int)0x0001 +# define ENGINE_METHOD_DSA (unsigned int)0x0002 +# define ENGINE_METHOD_DH (unsigned int)0x0004 +# define ENGINE_METHOD_RAND (unsigned int)0x0008 +# define ENGINE_METHOD_CIPHERS (unsigned int)0x0040 +# define ENGINE_METHOD_DIGESTS (unsigned int)0x0080 +# define ENGINE_METHOD_PKEY_METHS (unsigned int)0x0200 +# define ENGINE_METHOD_PKEY_ASN1_METHS (unsigned int)0x0400 +# define ENGINE_METHOD_EC (unsigned int)0x0800 +/* Obvious all-or-nothing cases. */ +# define ENGINE_METHOD_ALL (unsigned int)0xFFFF +# define ENGINE_METHOD_NONE (unsigned int)0x0000 + +/* + * This(ese) flag(s) controls behaviour of the ENGINE_TABLE mechanism used + * internally to control registration of ENGINE implementations, and can be + * set by ENGINE_set_table_flags(). The "NOINIT" flag prevents attempts to + * initialise registered ENGINEs if they are not already initialised. + */ +# define ENGINE_TABLE_FLAG_NOINIT (unsigned int)0x0001 + +/* ENGINE flags that can be set by ENGINE_set_flags(). */ +/* Not used */ +/* #define ENGINE_FLAGS_MALLOCED 0x0001 */ + +/* + * This flag is for ENGINEs that wish to handle the various 'CMD'-related + * control commands on their own. Without this flag, ENGINE_ctrl() handles + * these control commands on behalf of the ENGINE using their "cmd_defns" + * data. + */ +# define ENGINE_FLAGS_MANUAL_CMD_CTRL (int)0x0002 + +/* + * This flag is for ENGINEs who return new duplicate structures when found + * via "ENGINE_by_id()". When an ENGINE must store state (eg. if + * ENGINE_ctrl() commands are called in sequence as part of some stateful + * process like key-generation setup and execution), it can set this flag - + * then each attempt to obtain the ENGINE will result in it being copied into + * a new structure. Normally, ENGINEs don't declare this flag so + * ENGINE_by_id() just increments the existing ENGINE's structural reference + * count. + */ +# define ENGINE_FLAGS_BY_ID_COPY (int)0x0004 + +/* + * This flag if for an ENGINE that does not want its methods registered as + * part of ENGINE_register_all_complete() for example if the methods are not + * usable as default methods. + */ + +# define ENGINE_FLAGS_NO_REGISTER_ALL (int)0x0008 + +/* + * ENGINEs can support their own command types, and these flags are used in + * ENGINE_CTRL_GET_CMD_FLAGS to indicate to the caller what kind of input + * each command expects. Currently only numeric and string input is + * supported. If a control command supports none of the _NUMERIC, _STRING, or + * _NO_INPUT options, then it is regarded as an "internal" control command - + * and not for use in config setting situations. As such, they're not + * available to the ENGINE_ctrl_cmd_string() function, only raw ENGINE_ctrl() + * access. Changes to this list of 'command types' should be reflected + * carefully in ENGINE_cmd_is_executable() and ENGINE_ctrl_cmd_string(). + */ + +/* accepts a 'long' input value (3rd parameter to ENGINE_ctrl) */ +# define ENGINE_CMD_FLAG_NUMERIC (unsigned int)0x0001 +/* + * accepts string input (cast from 'void*' to 'const char *', 4th parameter + * to ENGINE_ctrl) + */ +# define ENGINE_CMD_FLAG_STRING (unsigned int)0x0002 +/* + * Indicates that the control command takes *no* input. Ie. the control + * command is unparameterised. + */ +# define ENGINE_CMD_FLAG_NO_INPUT (unsigned int)0x0004 +/* + * Indicates that the control command is internal. This control command won't + * be shown in any output, and is only usable through the ENGINE_ctrl_cmd() + * function. + */ +# define ENGINE_CMD_FLAG_INTERNAL (unsigned int)0x0008 + +/* + * NB: These 3 control commands are deprecated and should not be used. + * ENGINEs relying on these commands should compile conditional support for + * compatibility (eg. if these symbols are defined) but should also migrate + * the same functionality to their own ENGINE-specific control functions that + * can be "discovered" by calling applications. The fact these control + * commands wouldn't be "executable" (ie. usable by text-based config) + * doesn't change the fact that application code can find and use them + * without requiring per-ENGINE hacking. + */ + +/* + * These flags are used to tell the ctrl function what should be done. All + * command numbers are shared between all engines, even if some don't make + * sense to some engines. In such a case, they do nothing but return the + * error ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED. + */ +# define ENGINE_CTRL_SET_LOGSTREAM 1 +# define ENGINE_CTRL_SET_PASSWORD_CALLBACK 2 +# define ENGINE_CTRL_HUP 3/* Close and reinitialise + * any handles/connections + * etc. */ +# define ENGINE_CTRL_SET_USER_INTERFACE 4/* Alternative to callback */ +# define ENGINE_CTRL_SET_CALLBACK_DATA 5/* User-specific data, used + * when calling the password + * callback and the user + * interface */ +# define ENGINE_CTRL_LOAD_CONFIGURATION 6/* Load a configuration, + * given a string that + * represents a file name + * or so */ +# define ENGINE_CTRL_LOAD_SECTION 7/* Load data from a given + * section in the already + * loaded configuration */ + +/* + * These control commands allow an application to deal with an arbitrary + * engine in a dynamic way. Warn: Negative return values indicate errors FOR + * THESE COMMANDS because zero is used to indicate 'end-of-list'. Other + * commands, including ENGINE-specific command types, return zero for an + * error. An ENGINE can choose to implement these ctrl functions, and can + * internally manage things however it chooses - it does so by setting the + * ENGINE_FLAGS_MANUAL_CMD_CTRL flag (using ENGINE_set_flags()). Otherwise + * the ENGINE_ctrl() code handles this on the ENGINE's behalf using the + * cmd_defns data (set using ENGINE_set_cmd_defns()). This means an ENGINE's + * ctrl() handler need only implement its own commands - the above "meta" + * commands will be taken care of. + */ + +/* + * Returns non-zero if the supplied ENGINE has a ctrl() handler. If "not", + * then all the remaining control commands will return failure, so it is + * worth checking this first if the caller is trying to "discover" the + * engine's capabilities and doesn't want errors generated unnecessarily. + */ +# define ENGINE_CTRL_HAS_CTRL_FUNCTION 10 +/* + * Returns a positive command number for the first command supported by the + * engine. Returns zero if no ctrl commands are supported. + */ +# define ENGINE_CTRL_GET_FIRST_CMD_TYPE 11 +/* + * The 'long' argument specifies a command implemented by the engine, and the + * return value is the next command supported, or zero if there are no more. + */ +# define ENGINE_CTRL_GET_NEXT_CMD_TYPE 12 +/* + * The 'void*' argument is a command name (cast from 'const char *'), and the + * return value is the command that corresponds to it. + */ +# define ENGINE_CTRL_GET_CMD_FROM_NAME 13 +/* + * The next two allow a command to be converted into its corresponding string + * form. In each case, the 'long' argument supplies the command. In the + * NAME_LEN case, the return value is the length of the command name (not + * counting a trailing EOL). In the NAME case, the 'void*' argument must be a + * string buffer large enough, and it will be populated with the name of the + * command (WITH a trailing EOL). + */ +# define ENGINE_CTRL_GET_NAME_LEN_FROM_CMD 14 +# define ENGINE_CTRL_GET_NAME_FROM_CMD 15 +/* The next two are similar but give a "short description" of a command. */ +# define ENGINE_CTRL_GET_DESC_LEN_FROM_CMD 16 +# define ENGINE_CTRL_GET_DESC_FROM_CMD 17 +/* + * With this command, the return value is the OR'd combination of + * ENGINE_CMD_FLAG_*** values that indicate what kind of input a given + * engine-specific ctrl command expects. + */ +# define ENGINE_CTRL_GET_CMD_FLAGS 18 + +/* + * ENGINE implementations should start the numbering of their own control + * commands from this value. (ie. ENGINE_CMD_BASE, ENGINE_CMD_BASE + 1, etc). + */ +# define ENGINE_CMD_BASE 200 + +/* + * NB: These 2 nCipher "chil" control commands are deprecated, and their + * functionality is now available through ENGINE-specific control commands + * (exposed through the above-mentioned 'CMD'-handling). Code using these 2 + * commands should be migrated to the more general command handling before + * these are removed. + */ + +/* Flags specific to the nCipher "chil" engine */ +# define ENGINE_CTRL_CHIL_SET_FORKCHECK 100 + /* + * Depending on the value of the (long)i argument, this sets or + * unsets the SimpleForkCheck flag in the CHIL API to enable or + * disable checking and workarounds for applications that fork(). + */ +# define ENGINE_CTRL_CHIL_NO_LOCKING 101 + /* + * This prevents the initialisation function from providing mutex + * callbacks to the nCipher library. + */ + +/* + * If an ENGINE supports its own specific control commands and wishes the + * framework to handle the above 'ENGINE_CMD_***'-manipulation commands on + * its behalf, it should supply a null-terminated array of ENGINE_CMD_DEFN + * entries to ENGINE_set_cmd_defns(). It should also implement a ctrl() + * handler that supports the stated commands (ie. the "cmd_num" entries as + * described by the array). NB: The array must be ordered in increasing order + * of cmd_num. "null-terminated" means that the last ENGINE_CMD_DEFN element + * has cmd_num set to zero and/or cmd_name set to NULL. + */ +typedef struct ENGINE_CMD_DEFN_st { + unsigned int cmd_num; /* The command number */ + const char *cmd_name; /* The command name itself */ + const char *cmd_desc; /* A short description of the command */ + unsigned int cmd_flags; /* The input the command expects */ +} ENGINE_CMD_DEFN; + +/* Generic function pointer */ +typedef int (*ENGINE_GEN_FUNC_PTR) (void); +/* Generic function pointer taking no arguments */ +typedef int (*ENGINE_GEN_INT_FUNC_PTR) (ENGINE *); +/* Specific control function pointer */ +typedef int (*ENGINE_CTRL_FUNC_PTR) (ENGINE *, int, long, void *, + void (*f) (void)); +/* Generic load_key function pointer */ +typedef EVP_PKEY *(*ENGINE_LOAD_KEY_PTR)(ENGINE *, const char *, + UI_METHOD *ui_method, + void *callback_data); +typedef int (*ENGINE_SSL_CLIENT_CERT_PTR) (ENGINE *, SSL *ssl, + STACK_OF(X509_NAME) *ca_dn, + X509 **pcert, EVP_PKEY **pkey, + STACK_OF(X509) **pother, + UI_METHOD *ui_method, + void *callback_data); +/*- + * These callback types are for an ENGINE's handler for cipher and digest logic. + * These handlers have these prototypes; + * int foo(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid); + * int foo(ENGINE *e, const EVP_MD **digest, const int **nids, int nid); + * Looking at how to implement these handlers in the case of cipher support, if + * the framework wants the EVP_CIPHER for 'nid', it will call; + * foo(e, &p_evp_cipher, NULL, nid); (return zero for failure) + * If the framework wants a list of supported 'nid's, it will call; + * foo(e, NULL, &p_nids, 0); (returns number of 'nids' or -1 for error) + */ +/* + * Returns to a pointer to the array of supported cipher 'nid's. If the + * second parameter is non-NULL it is set to the size of the returned array. + */ +typedef int (*ENGINE_CIPHERS_PTR) (ENGINE *, const EVP_CIPHER **, + const int **, int); +typedef int (*ENGINE_DIGESTS_PTR) (ENGINE *, const EVP_MD **, const int **, + int); +typedef int (*ENGINE_PKEY_METHS_PTR) (ENGINE *, EVP_PKEY_METHOD **, + const int **, int); +typedef int (*ENGINE_PKEY_ASN1_METHS_PTR) (ENGINE *, EVP_PKEY_ASN1_METHOD **, + const int **, int); +/* + * STRUCTURE functions ... all of these functions deal with pointers to + * ENGINE structures where the pointers have a "structural reference". This + * means that their reference is to allowed access to the structure but it + * does not imply that the structure is functional. To simply increment or + * decrement the structural reference count, use ENGINE_by_id and + * ENGINE_free. NB: This is not required when iterating using ENGINE_get_next + * as it will automatically decrement the structural reference count of the + * "current" ENGINE and increment the structural reference count of the + * ENGINE it returns (unless it is NULL). + */ + +/* Get the first/last "ENGINE" type available. */ +ENGINE *ENGINE_get_first(void); +ENGINE *ENGINE_get_last(void); +/* Iterate to the next/previous "ENGINE" type (NULL = end of the list). */ +ENGINE *ENGINE_get_next(ENGINE *e); +ENGINE *ENGINE_get_prev(ENGINE *e); +/* Add another "ENGINE" type into the array. */ +int ENGINE_add(ENGINE *e); +/* Remove an existing "ENGINE" type from the array. */ +int ENGINE_remove(ENGINE *e); +/* Retrieve an engine from the list by its unique "id" value. */ +ENGINE *ENGINE_by_id(const char *id); + +#if OPENSSL_API_COMPAT < 0x10100000L +# define ENGINE_load_openssl() \ + OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_OPENSSL, NULL) +# define ENGINE_load_dynamic() \ + OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_DYNAMIC, NULL) +# ifndef OPENSSL_NO_STATIC_ENGINE +# define ENGINE_load_padlock() \ + OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_PADLOCK, NULL) +# define ENGINE_load_capi() \ + OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_CAPI, NULL) +# define ENGINE_load_afalg() \ + OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_AFALG, NULL) +# endif +# define ENGINE_load_cryptodev() \ + OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_CRYPTODEV, NULL) +# define ENGINE_load_rdrand() \ + OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_RDRAND, NULL) +#endif +void ENGINE_load_builtin_engines(void); + +/* + * Get and set global flags (ENGINE_TABLE_FLAG_***) for the implementation + * "registry" handling. + */ +unsigned int ENGINE_get_table_flags(void); +void ENGINE_set_table_flags(unsigned int flags); + +/*- Manage registration of ENGINEs per "table". For each type, there are 3 + * functions; + * ENGINE_register_***(e) - registers the implementation from 'e' (if it has one) + * ENGINE_unregister_***(e) - unregister the implementation from 'e' + * ENGINE_register_all_***() - call ENGINE_register_***() for each 'e' in the list + * Cleanup is automatically registered from each table when required. + */ + +int ENGINE_register_RSA(ENGINE *e); +void ENGINE_unregister_RSA(ENGINE *e); +void ENGINE_register_all_RSA(void); + +int ENGINE_register_DSA(ENGINE *e); +void ENGINE_unregister_DSA(ENGINE *e); +void ENGINE_register_all_DSA(void); + +int ENGINE_register_EC(ENGINE *e); +void ENGINE_unregister_EC(ENGINE *e); +void ENGINE_register_all_EC(void); + +int ENGINE_register_DH(ENGINE *e); +void ENGINE_unregister_DH(ENGINE *e); +void ENGINE_register_all_DH(void); + +int ENGINE_register_RAND(ENGINE *e); +void ENGINE_unregister_RAND(ENGINE *e); +void ENGINE_register_all_RAND(void); + +int ENGINE_register_ciphers(ENGINE *e); +void ENGINE_unregister_ciphers(ENGINE *e); +void ENGINE_register_all_ciphers(void); + +int ENGINE_register_digests(ENGINE *e); +void ENGINE_unregister_digests(ENGINE *e); +void ENGINE_register_all_digests(void); + +int ENGINE_register_pkey_meths(ENGINE *e); +void ENGINE_unregister_pkey_meths(ENGINE *e); +void ENGINE_register_all_pkey_meths(void); + +int ENGINE_register_pkey_asn1_meths(ENGINE *e); +void ENGINE_unregister_pkey_asn1_meths(ENGINE *e); +void ENGINE_register_all_pkey_asn1_meths(void); + +/* + * These functions register all support from the above categories. Note, use + * of these functions can result in static linkage of code your application + * may not need. If you only need a subset of functionality, consider using + * more selective initialisation. + */ +int ENGINE_register_complete(ENGINE *e); +int ENGINE_register_all_complete(void); + +/* + * Send parameterised control commands to the engine. The possibilities to + * send down an integer, a pointer to data or a function pointer are + * provided. Any of the parameters may or may not be NULL, depending on the + * command number. In actuality, this function only requires a structural + * (rather than functional) reference to an engine, but many control commands + * may require the engine be functional. The caller should be aware of trying + * commands that require an operational ENGINE, and only use functional + * references in such situations. + */ +int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)); + +/* + * This function tests if an ENGINE-specific command is usable as a + * "setting". Eg. in an application's config file that gets processed through + * ENGINE_ctrl_cmd_string(). If this returns zero, it is not available to + * ENGINE_ctrl_cmd_string(), only ENGINE_ctrl(). + */ +int ENGINE_cmd_is_executable(ENGINE *e, int cmd); + +/* + * This function works like ENGINE_ctrl() with the exception of taking a + * command name instead of a command number, and can handle optional + * commands. See the comment on ENGINE_ctrl_cmd_string() for an explanation + * on how to use the cmd_name and cmd_optional. + */ +int ENGINE_ctrl_cmd(ENGINE *e, const char *cmd_name, + long i, void *p, void (*f) (void), int cmd_optional); + +/* + * This function passes a command-name and argument to an ENGINE. The + * cmd_name is converted to a command number and the control command is + * called using 'arg' as an argument (unless the ENGINE doesn't support such + * a command, in which case no control command is called). The command is + * checked for input flags, and if necessary the argument will be converted + * to a numeric value. If cmd_optional is non-zero, then if the ENGINE + * doesn't support the given cmd_name the return value will be success + * anyway. This function is intended for applications to use so that users + * (or config files) can supply engine-specific config data to the ENGINE at + * run-time to control behaviour of specific engines. As such, it shouldn't + * be used for calling ENGINE_ctrl() functions that return data, deal with + * binary data, or that are otherwise supposed to be used directly through + * ENGINE_ctrl() in application code. Any "return" data from an ENGINE_ctrl() + * operation in this function will be lost - the return value is interpreted + * as failure if the return value is zero, success otherwise, and this + * function returns a boolean value as a result. In other words, vendors of + * 'ENGINE'-enabled devices should write ENGINE implementations with + * parameterisations that work in this scheme, so that compliant ENGINE-based + * applications can work consistently with the same configuration for the + * same ENGINE-enabled devices, across applications. + */ +int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg, + int cmd_optional); + +/* + * These functions are useful for manufacturing new ENGINE structures. They + * don't address reference counting at all - one uses them to populate an + * ENGINE structure with personalised implementations of things prior to + * using it directly or adding it to the builtin ENGINE list in OpenSSL. + * These are also here so that the ENGINE structure doesn't have to be + * exposed and break binary compatibility! + */ +ENGINE *ENGINE_new(void); +int ENGINE_free(ENGINE *e); +int ENGINE_up_ref(ENGINE *e); +int ENGINE_set_id(ENGINE *e, const char *id); +int ENGINE_set_name(ENGINE *e, const char *name); +int ENGINE_set_RSA(ENGINE *e, const RSA_METHOD *rsa_meth); +int ENGINE_set_DSA(ENGINE *e, const DSA_METHOD *dsa_meth); +int ENGINE_set_EC(ENGINE *e, const EC_KEY_METHOD *ecdsa_meth); +int ENGINE_set_DH(ENGINE *e, const DH_METHOD *dh_meth); +int ENGINE_set_RAND(ENGINE *e, const RAND_METHOD *rand_meth); +int ENGINE_set_destroy_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR destroy_f); +int ENGINE_set_init_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR init_f); +int ENGINE_set_finish_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR finish_f); +int ENGINE_set_ctrl_function(ENGINE *e, ENGINE_CTRL_FUNC_PTR ctrl_f); +int ENGINE_set_load_privkey_function(ENGINE *e, + ENGINE_LOAD_KEY_PTR loadpriv_f); +int ENGINE_set_load_pubkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpub_f); +int ENGINE_set_load_ssl_client_cert_function(ENGINE *e, + ENGINE_SSL_CLIENT_CERT_PTR + loadssl_f); +int ENGINE_set_ciphers(ENGINE *e, ENGINE_CIPHERS_PTR f); +int ENGINE_set_digests(ENGINE *e, ENGINE_DIGESTS_PTR f); +int ENGINE_set_pkey_meths(ENGINE *e, ENGINE_PKEY_METHS_PTR f); +int ENGINE_set_pkey_asn1_meths(ENGINE *e, ENGINE_PKEY_ASN1_METHS_PTR f); +int ENGINE_set_flags(ENGINE *e, int flags); +int ENGINE_set_cmd_defns(ENGINE *e, const ENGINE_CMD_DEFN *defns); +/* These functions allow control over any per-structure ENGINE data. */ +#define ENGINE_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_ENGINE, l, p, newf, dupf, freef) +int ENGINE_set_ex_data(ENGINE *e, int idx, void *arg); +void *ENGINE_get_ex_data(const ENGINE *e, int idx); + +#if OPENSSL_API_COMPAT < 0x10100000L +/* + * This function previously cleaned up anything that needs it. Auto-deinit will + * now take care of it so it is no longer required to call this function. + */ +# define ENGINE_cleanup() while(0) continue +#endif + +/* + * These return values from within the ENGINE structure. These can be useful + * with functional references as well as structural references - it depends + * which you obtained. Using the result for functional purposes if you only + * obtained a structural reference may be problematic! + */ +const char *ENGINE_get_id(const ENGINE *e); +const char *ENGINE_get_name(const ENGINE *e); +const RSA_METHOD *ENGINE_get_RSA(const ENGINE *e); +const DSA_METHOD *ENGINE_get_DSA(const ENGINE *e); +const EC_KEY_METHOD *ENGINE_get_EC(const ENGINE *e); +const DH_METHOD *ENGINE_get_DH(const ENGINE *e); +const RAND_METHOD *ENGINE_get_RAND(const ENGINE *e); +ENGINE_GEN_INT_FUNC_PTR ENGINE_get_destroy_function(const ENGINE *e); +ENGINE_GEN_INT_FUNC_PTR ENGINE_get_init_function(const ENGINE *e); +ENGINE_GEN_INT_FUNC_PTR ENGINE_get_finish_function(const ENGINE *e); +ENGINE_CTRL_FUNC_PTR ENGINE_get_ctrl_function(const ENGINE *e); +ENGINE_LOAD_KEY_PTR ENGINE_get_load_privkey_function(const ENGINE *e); +ENGINE_LOAD_KEY_PTR ENGINE_get_load_pubkey_function(const ENGINE *e); +ENGINE_SSL_CLIENT_CERT_PTR ENGINE_get_ssl_client_cert_function(const ENGINE + *e); +ENGINE_CIPHERS_PTR ENGINE_get_ciphers(const ENGINE *e); +ENGINE_DIGESTS_PTR ENGINE_get_digests(const ENGINE *e); +ENGINE_PKEY_METHS_PTR ENGINE_get_pkey_meths(const ENGINE *e); +ENGINE_PKEY_ASN1_METHS_PTR ENGINE_get_pkey_asn1_meths(const ENGINE *e); +const EVP_CIPHER *ENGINE_get_cipher(ENGINE *e, int nid); +const EVP_MD *ENGINE_get_digest(ENGINE *e, int nid); +const EVP_PKEY_METHOD *ENGINE_get_pkey_meth(ENGINE *e, int nid); +const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth(ENGINE *e, int nid); +const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth_str(ENGINE *e, + const char *str, + int len); +const EVP_PKEY_ASN1_METHOD *ENGINE_pkey_asn1_find_str(ENGINE **pe, + const char *str, + int len); +const ENGINE_CMD_DEFN *ENGINE_get_cmd_defns(const ENGINE *e); +int ENGINE_get_flags(const ENGINE *e); + +/* + * FUNCTIONAL functions. These functions deal with ENGINE structures that + * have (or will) be initialised for use. Broadly speaking, the structural + * functions are useful for iterating the list of available engine types, + * creating new engine types, and other "list" operations. These functions + * actually deal with ENGINEs that are to be used. As such these functions + * can fail (if applicable) when particular engines are unavailable - eg. if + * a hardware accelerator is not attached or not functioning correctly. Each + * ENGINE has 2 reference counts; structural and functional. Every time a + * functional reference is obtained or released, a corresponding structural + * reference is automatically obtained or released too. + */ + +/* + * Initialise a engine type for use (or up its reference count if it's + * already in use). This will fail if the engine is not currently operational + * and cannot initialise. + */ +int ENGINE_init(ENGINE *e); +/* + * Free a functional reference to a engine type. This does not require a + * corresponding call to ENGINE_free as it also releases a structural + * reference. + */ +int ENGINE_finish(ENGINE *e); + +/* + * The following functions handle keys that are stored in some secondary + * location, handled by the engine. The storage may be on a card or + * whatever. + */ +EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id, + UI_METHOD *ui_method, void *callback_data); +EVP_PKEY *ENGINE_load_public_key(ENGINE *e, const char *key_id, + UI_METHOD *ui_method, void *callback_data); +int ENGINE_load_ssl_client_cert(ENGINE *e, SSL *s, + STACK_OF(X509_NAME) *ca_dn, X509 **pcert, + EVP_PKEY **ppkey, STACK_OF(X509) **pother, + UI_METHOD *ui_method, void *callback_data); + +/* + * This returns a pointer for the current ENGINE structure that is (by + * default) performing any RSA operations. The value returned is an + * incremented reference, so it should be free'd (ENGINE_finish) before it is + * discarded. + */ +ENGINE *ENGINE_get_default_RSA(void); +/* Same for the other "methods" */ +ENGINE *ENGINE_get_default_DSA(void); +ENGINE *ENGINE_get_default_EC(void); +ENGINE *ENGINE_get_default_DH(void); +ENGINE *ENGINE_get_default_RAND(void); +/* + * These functions can be used to get a functional reference to perform + * ciphering or digesting corresponding to "nid". + */ +ENGINE *ENGINE_get_cipher_engine(int nid); +ENGINE *ENGINE_get_digest_engine(int nid); +ENGINE *ENGINE_get_pkey_meth_engine(int nid); +ENGINE *ENGINE_get_pkey_asn1_meth_engine(int nid); + +/* + * This sets a new default ENGINE structure for performing RSA operations. If + * the result is non-zero (success) then the ENGINE structure will have had + * its reference count up'd so the caller should still free their own + * reference 'e'. + */ +int ENGINE_set_default_RSA(ENGINE *e); +int ENGINE_set_default_string(ENGINE *e, const char *def_list); +/* Same for the other "methods" */ +int ENGINE_set_default_DSA(ENGINE *e); +int ENGINE_set_default_EC(ENGINE *e); +int ENGINE_set_default_DH(ENGINE *e); +int ENGINE_set_default_RAND(ENGINE *e); +int ENGINE_set_default_ciphers(ENGINE *e); +int ENGINE_set_default_digests(ENGINE *e); +int ENGINE_set_default_pkey_meths(ENGINE *e); +int ENGINE_set_default_pkey_asn1_meths(ENGINE *e); + +/* + * The combination "set" - the flags are bitwise "OR"d from the + * ENGINE_METHOD_*** defines above. As with the "ENGINE_register_complete()" + * function, this function can result in unnecessary static linkage. If your + * application requires only specific functionality, consider using more + * selective functions. + */ +int ENGINE_set_default(ENGINE *e, unsigned int flags); + +void ENGINE_add_conf_module(void); + +/* Deprecated functions ... */ +/* int ENGINE_clear_defaults(void); */ + +/**************************/ +/* DYNAMIC ENGINE SUPPORT */ +/**************************/ + +/* Binary/behaviour compatibility levels */ +# define OSSL_DYNAMIC_VERSION (unsigned long)0x00030000 +/* + * Binary versions older than this are too old for us (whether we're a loader + * or a loadee) + */ +# define OSSL_DYNAMIC_OLDEST (unsigned long)0x00030000 + +/* + * When compiling an ENGINE entirely as an external shared library, loadable + * by the "dynamic" ENGINE, these types are needed. The 'dynamic_fns' + * structure type provides the calling application's (or library's) error + * functionality and memory management function pointers to the loaded + * library. These should be used/set in the loaded library code so that the + * loading application's 'state' will be used/changed in all operations. The + * 'static_state' pointer allows the loaded library to know if it shares the + * same static data as the calling application (or library), and thus whether + * these callbacks need to be set or not. + */ +typedef void *(*dyn_MEM_malloc_fn) (size_t, const char *, int); +typedef void *(*dyn_MEM_realloc_fn) (void *, size_t, const char *, int); +typedef void (*dyn_MEM_free_fn) (void *, const char *, int); +typedef struct st_dynamic_MEM_fns { + dyn_MEM_malloc_fn malloc_fn; + dyn_MEM_realloc_fn realloc_fn; + dyn_MEM_free_fn free_fn; +} dynamic_MEM_fns; +/* + * FIXME: Perhaps the memory and locking code (crypto.h) should declare and + * use these types so we (and any other dependent code) can simplify a bit?? + */ +/* The top-level structure */ +typedef struct st_dynamic_fns { + void *static_state; + dynamic_MEM_fns mem_fns; +} dynamic_fns; + +/* + * The version checking function should be of this prototype. NB: The + * ossl_version value passed in is the OSSL_DYNAMIC_VERSION of the loading + * code. If this function returns zero, it indicates a (potential) version + * incompatibility and the loaded library doesn't believe it can proceed. + * Otherwise, the returned value is the (latest) version supported by the + * loading library. The loader may still decide that the loaded code's + * version is unsatisfactory and could veto the load. The function is + * expected to be implemented with the symbol name "v_check", and a default + * implementation can be fully instantiated with + * IMPLEMENT_DYNAMIC_CHECK_FN(). + */ +typedef unsigned long (*dynamic_v_check_fn) (unsigned long ossl_version); +# define IMPLEMENT_DYNAMIC_CHECK_FN() \ + OPENSSL_EXPORT unsigned long v_check(unsigned long v); \ + OPENSSL_EXPORT unsigned long v_check(unsigned long v) { \ + if (v >= OSSL_DYNAMIC_OLDEST) return OSSL_DYNAMIC_VERSION; \ + return 0; } + +/* + * This function is passed the ENGINE structure to initialise with its own + * function and command settings. It should not adjust the structural or + * functional reference counts. If this function returns zero, (a) the load + * will be aborted, (b) the previous ENGINE state will be memcpy'd back onto + * the structure, and (c) the shared library will be unloaded. So + * implementations should do their own internal cleanup in failure + * circumstances otherwise they could leak. The 'id' parameter, if non-NULL, + * represents the ENGINE id that the loader is looking for. If this is NULL, + * the shared library can choose to return failure or to initialise a + * 'default' ENGINE. If non-NULL, the shared library must initialise only an + * ENGINE matching the passed 'id'. The function is expected to be + * implemented with the symbol name "bind_engine". A standard implementation + * can be instantiated with IMPLEMENT_DYNAMIC_BIND_FN(fn) where the parameter + * 'fn' is a callback function that populates the ENGINE structure and + * returns an int value (zero for failure). 'fn' should have prototype; + * [static] int fn(ENGINE *e, const char *id); + */ +typedef int (*dynamic_bind_engine) (ENGINE *e, const char *id, + const dynamic_fns *fns); +# define IMPLEMENT_DYNAMIC_BIND_FN(fn) \ + OPENSSL_EXPORT \ + int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns); \ + OPENSSL_EXPORT \ + int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) { \ + if (ENGINE_get_static_state() == fns->static_state) goto skip_cbs; \ + CRYPTO_set_mem_functions(fns->mem_fns.malloc_fn, \ + fns->mem_fns.realloc_fn, \ + fns->mem_fns.free_fn); \ + skip_cbs: \ + if (!fn(e, id)) return 0; \ + return 1; } + +/* + * If the loading application (or library) and the loaded ENGINE library + * share the same static data (eg. they're both dynamically linked to the + * same libcrypto.so) we need a way to avoid trying to set system callbacks - + * this would fail, and for the same reason that it's unnecessary to try. If + * the loaded ENGINE has (or gets from through the loader) its own copy of + * the libcrypto static data, we will need to set the callbacks. The easiest + * way to detect this is to have a function that returns a pointer to some + * static data and let the loading application and loaded ENGINE compare + * their respective values. + */ +void *ENGINE_get_static_state(void); + +# if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) +DEPRECATEDIN_1_1_0(void ENGINE_setup_bsd_cryptodev(void)) +# endif + + +# ifdef __cplusplus +} +# endif +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/engineerr.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/engineerr.h new file mode 100644 index 000000000..b4c036b21 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/engineerr.h @@ -0,0 +1,107 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_ENGINEERR_H +# define HEADER_ENGINEERR_H + +# include + +# ifndef OPENSSL_NO_ENGINE + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_ENGINE_strings(void); + +/* + * ENGINE function codes. + */ +# define ENGINE_F_DIGEST_UPDATE 198 +# define ENGINE_F_DYNAMIC_CTRL 180 +# define ENGINE_F_DYNAMIC_GET_DATA_CTX 181 +# define ENGINE_F_DYNAMIC_LOAD 182 +# define ENGINE_F_DYNAMIC_SET_DATA_CTX 183 +# define ENGINE_F_ENGINE_ADD 105 +# define ENGINE_F_ENGINE_BY_ID 106 +# define ENGINE_F_ENGINE_CMD_IS_EXECUTABLE 170 +# define ENGINE_F_ENGINE_CTRL 142 +# define ENGINE_F_ENGINE_CTRL_CMD 178 +# define ENGINE_F_ENGINE_CTRL_CMD_STRING 171 +# define ENGINE_F_ENGINE_FINISH 107 +# define ENGINE_F_ENGINE_GET_CIPHER 185 +# define ENGINE_F_ENGINE_GET_DIGEST 186 +# define ENGINE_F_ENGINE_GET_FIRST 195 +# define ENGINE_F_ENGINE_GET_LAST 196 +# define ENGINE_F_ENGINE_GET_NEXT 115 +# define ENGINE_F_ENGINE_GET_PKEY_ASN1_METH 193 +# define ENGINE_F_ENGINE_GET_PKEY_METH 192 +# define ENGINE_F_ENGINE_GET_PREV 116 +# define ENGINE_F_ENGINE_INIT 119 +# define ENGINE_F_ENGINE_LIST_ADD 120 +# define ENGINE_F_ENGINE_LIST_REMOVE 121 +# define ENGINE_F_ENGINE_LOAD_PRIVATE_KEY 150 +# define ENGINE_F_ENGINE_LOAD_PUBLIC_KEY 151 +# define ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT 194 +# define ENGINE_F_ENGINE_NEW 122 +# define ENGINE_F_ENGINE_PKEY_ASN1_FIND_STR 197 +# define ENGINE_F_ENGINE_REMOVE 123 +# define ENGINE_F_ENGINE_SET_DEFAULT_STRING 189 +# define ENGINE_F_ENGINE_SET_ID 129 +# define ENGINE_F_ENGINE_SET_NAME 130 +# define ENGINE_F_ENGINE_TABLE_REGISTER 184 +# define ENGINE_F_ENGINE_UNLOCKED_FINISH 191 +# define ENGINE_F_ENGINE_UP_REF 190 +# define ENGINE_F_INT_CLEANUP_ITEM 199 +# define ENGINE_F_INT_CTRL_HELPER 172 +# define ENGINE_F_INT_ENGINE_CONFIGURE 188 +# define ENGINE_F_INT_ENGINE_MODULE_INIT 187 +# define ENGINE_F_OSSL_HMAC_INIT 200 + +/* + * ENGINE reason codes. + */ +# define ENGINE_R_ALREADY_LOADED 100 +# define ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER 133 +# define ENGINE_R_CMD_NOT_EXECUTABLE 134 +# define ENGINE_R_COMMAND_TAKES_INPUT 135 +# define ENGINE_R_COMMAND_TAKES_NO_INPUT 136 +# define ENGINE_R_CONFLICTING_ENGINE_ID 103 +# define ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED 119 +# define ENGINE_R_DSO_FAILURE 104 +# define ENGINE_R_DSO_NOT_FOUND 132 +# define ENGINE_R_ENGINES_SECTION_ERROR 148 +# define ENGINE_R_ENGINE_CONFIGURATION_ERROR 102 +# define ENGINE_R_ENGINE_IS_NOT_IN_LIST 105 +# define ENGINE_R_ENGINE_SECTION_ERROR 149 +# define ENGINE_R_FAILED_LOADING_PRIVATE_KEY 128 +# define ENGINE_R_FAILED_LOADING_PUBLIC_KEY 129 +# define ENGINE_R_FINISH_FAILED 106 +# define ENGINE_R_ID_OR_NAME_MISSING 108 +# define ENGINE_R_INIT_FAILED 109 +# define ENGINE_R_INTERNAL_LIST_ERROR 110 +# define ENGINE_R_INVALID_ARGUMENT 143 +# define ENGINE_R_INVALID_CMD_NAME 137 +# define ENGINE_R_INVALID_CMD_NUMBER 138 +# define ENGINE_R_INVALID_INIT_VALUE 151 +# define ENGINE_R_INVALID_STRING 150 +# define ENGINE_R_NOT_INITIALISED 117 +# define ENGINE_R_NOT_LOADED 112 +# define ENGINE_R_NO_CONTROL_FUNCTION 120 +# define ENGINE_R_NO_INDEX 144 +# define ENGINE_R_NO_LOAD_FUNCTION 125 +# define ENGINE_R_NO_REFERENCE 130 +# define ENGINE_R_NO_SUCH_ENGINE 116 +# define ENGINE_R_UNIMPLEMENTED_CIPHER 146 +# define ENGINE_R_UNIMPLEMENTED_DIGEST 147 +# define ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD 101 +# define ENGINE_R_VERSION_INCOMPATIBILITY 145 + +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/err.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/err.h new file mode 100644 index 000000000..6cae1a365 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/err.h @@ -0,0 +1,273 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_ERR_H +# define HEADER_ERR_H + +# include + +# ifndef OPENSSL_NO_STDIO +# include +# include +# endif + +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# ifndef OPENSSL_NO_ERR +# define ERR_PUT_error(a,b,c,d,e) ERR_put_error(a,b,c,d,e) +# else +# define ERR_PUT_error(a,b,c,d,e) ERR_put_error(a,b,c,NULL,0) +# endif + +# include + +# define ERR_TXT_MALLOCED 0x01 +# define ERR_TXT_STRING 0x02 + +# define ERR_FLAG_MARK 0x01 + +# define ERR_NUM_ERRORS 16 +typedef struct err_state_st { + int err_flags[ERR_NUM_ERRORS]; + unsigned long err_buffer[ERR_NUM_ERRORS]; + char *err_data[ERR_NUM_ERRORS]; + int err_data_flags[ERR_NUM_ERRORS]; + const char *err_file[ERR_NUM_ERRORS]; + int err_line[ERR_NUM_ERRORS]; + int top, bottom; +} ERR_STATE; + +/* library */ +# define ERR_LIB_NONE 1 +# define ERR_LIB_SYS 2 +# define ERR_LIB_BN 3 +# define ERR_LIB_RSA 4 +# define ERR_LIB_DH 5 +# define ERR_LIB_EVP 6 +# define ERR_LIB_BUF 7 +# define ERR_LIB_OBJ 8 +# define ERR_LIB_PEM 9 +# define ERR_LIB_DSA 10 +# define ERR_LIB_X509 11 +/* #define ERR_LIB_METH 12 */ +# define ERR_LIB_ASN1 13 +# define ERR_LIB_CONF 14 +# define ERR_LIB_CRYPTO 15 +# define ERR_LIB_EC 16 +# define ERR_LIB_SSL 20 +/* #define ERR_LIB_SSL23 21 */ +/* #define ERR_LIB_SSL2 22 */ +/* #define ERR_LIB_SSL3 23 */ +/* #define ERR_LIB_RSAREF 30 */ +/* #define ERR_LIB_PROXY 31 */ +# define ERR_LIB_BIO 32 +# define ERR_LIB_PKCS7 33 +# define ERR_LIB_X509V3 34 +# define ERR_LIB_PKCS12 35 +# define ERR_LIB_RAND 36 +# define ERR_LIB_DSO 37 +# define ERR_LIB_ENGINE 38 +# define ERR_LIB_OCSP 39 +# define ERR_LIB_UI 40 +# define ERR_LIB_COMP 41 +# define ERR_LIB_ECDSA 42 +# define ERR_LIB_ECDH 43 +# define ERR_LIB_OSSL_STORE 44 +# define ERR_LIB_FIPS 45 +# define ERR_LIB_CMS 46 +# define ERR_LIB_TS 47 +# define ERR_LIB_HMAC 48 +/* # define ERR_LIB_JPAKE 49 */ +# define ERR_LIB_CT 50 +# define ERR_LIB_ASYNC 51 +# define ERR_LIB_KDF 52 +# define ERR_LIB_SM2 53 + +# define ERR_LIB_USER 128 + +# define SYSerr(f,r) ERR_PUT_error(ERR_LIB_SYS,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define BNerr(f,r) ERR_PUT_error(ERR_LIB_BN,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define RSAerr(f,r) ERR_PUT_error(ERR_LIB_RSA,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define DHerr(f,r) ERR_PUT_error(ERR_LIB_DH,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define EVPerr(f,r) ERR_PUT_error(ERR_LIB_EVP,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define BUFerr(f,r) ERR_PUT_error(ERR_LIB_BUF,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define OBJerr(f,r) ERR_PUT_error(ERR_LIB_OBJ,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define PEMerr(f,r) ERR_PUT_error(ERR_LIB_PEM,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define DSAerr(f,r) ERR_PUT_error(ERR_LIB_DSA,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define X509err(f,r) ERR_PUT_error(ERR_LIB_X509,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define ASN1err(f,r) ERR_PUT_error(ERR_LIB_ASN1,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define CONFerr(f,r) ERR_PUT_error(ERR_LIB_CONF,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define CRYPTOerr(f,r) ERR_PUT_error(ERR_LIB_CRYPTO,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define ECerr(f,r) ERR_PUT_error(ERR_LIB_EC,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define SSLerr(f,r) ERR_PUT_error(ERR_LIB_SSL,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define BIOerr(f,r) ERR_PUT_error(ERR_LIB_BIO,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define PKCS7err(f,r) ERR_PUT_error(ERR_LIB_PKCS7,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define X509V3err(f,r) ERR_PUT_error(ERR_LIB_X509V3,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define PKCS12err(f,r) ERR_PUT_error(ERR_LIB_PKCS12,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define RANDerr(f,r) ERR_PUT_error(ERR_LIB_RAND,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define DSOerr(f,r) ERR_PUT_error(ERR_LIB_DSO,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define ENGINEerr(f,r) ERR_PUT_error(ERR_LIB_ENGINE,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define OCSPerr(f,r) ERR_PUT_error(ERR_LIB_OCSP,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define UIerr(f,r) ERR_PUT_error(ERR_LIB_UI,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define COMPerr(f,r) ERR_PUT_error(ERR_LIB_COMP,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define ECDSAerr(f,r) ERR_PUT_error(ERR_LIB_ECDSA,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define ECDHerr(f,r) ERR_PUT_error(ERR_LIB_ECDH,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define OSSL_STOREerr(f,r) ERR_PUT_error(ERR_LIB_OSSL_STORE,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define FIPSerr(f,r) ERR_PUT_error(ERR_LIB_FIPS,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define CMSerr(f,r) ERR_PUT_error(ERR_LIB_CMS,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define TSerr(f,r) ERR_PUT_error(ERR_LIB_TS,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define HMACerr(f,r) ERR_PUT_error(ERR_LIB_HMAC,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define CTerr(f,r) ERR_PUT_error(ERR_LIB_CT,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define ASYNCerr(f,r) ERR_PUT_error(ERR_LIB_ASYNC,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define KDFerr(f,r) ERR_PUT_error(ERR_LIB_KDF,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define SM2err(f,r) ERR_PUT_error(ERR_LIB_SM2,(f),(r),OPENSSL_FILE,OPENSSL_LINE) + +# define ERR_PACK(l,f,r) ( \ + (((unsigned int)(l) & 0x0FF) << 24L) | \ + (((unsigned int)(f) & 0xFFF) << 12L) | \ + (((unsigned int)(r) & 0xFFF) ) ) +# define ERR_GET_LIB(l) (int)(((l) >> 24L) & 0x0FFL) +# define ERR_GET_FUNC(l) (int)(((l) >> 12L) & 0xFFFL) +# define ERR_GET_REASON(l) (int)( (l) & 0xFFFL) +# define ERR_FATAL_ERROR(l) (int)( (l) & ERR_R_FATAL) + +/* OS functions */ +# define SYS_F_FOPEN 1 +# define SYS_F_CONNECT 2 +# define SYS_F_GETSERVBYNAME 3 +# define SYS_F_SOCKET 4 +# define SYS_F_IOCTLSOCKET 5 +# define SYS_F_BIND 6 +# define SYS_F_LISTEN 7 +# define SYS_F_ACCEPT 8 +# define SYS_F_WSASTARTUP 9/* Winsock stuff */ +# define SYS_F_OPENDIR 10 +# define SYS_F_FREAD 11 +# define SYS_F_GETADDRINFO 12 +# define SYS_F_GETNAMEINFO 13 +# define SYS_F_SETSOCKOPT 14 +# define SYS_F_GETSOCKOPT 15 +# define SYS_F_GETSOCKNAME 16 +# define SYS_F_GETHOSTBYNAME 17 +# define SYS_F_FFLUSH 18 +# define SYS_F_OPEN 19 +# define SYS_F_CLOSE 20 +# define SYS_F_IOCTL 21 +# define SYS_F_STAT 22 +# define SYS_F_FCNTL 23 +# define SYS_F_FSTAT 24 + +/* reasons */ +# define ERR_R_SYS_LIB ERR_LIB_SYS/* 2 */ +# define ERR_R_BN_LIB ERR_LIB_BN/* 3 */ +# define ERR_R_RSA_LIB ERR_LIB_RSA/* 4 */ +# define ERR_R_DH_LIB ERR_LIB_DH/* 5 */ +# define ERR_R_EVP_LIB ERR_LIB_EVP/* 6 */ +# define ERR_R_BUF_LIB ERR_LIB_BUF/* 7 */ +# define ERR_R_OBJ_LIB ERR_LIB_OBJ/* 8 */ +# define ERR_R_PEM_LIB ERR_LIB_PEM/* 9 */ +# define ERR_R_DSA_LIB ERR_LIB_DSA/* 10 */ +# define ERR_R_X509_LIB ERR_LIB_X509/* 11 */ +# define ERR_R_ASN1_LIB ERR_LIB_ASN1/* 13 */ +# define ERR_R_EC_LIB ERR_LIB_EC/* 16 */ +# define ERR_R_BIO_LIB ERR_LIB_BIO/* 32 */ +# define ERR_R_PKCS7_LIB ERR_LIB_PKCS7/* 33 */ +# define ERR_R_X509V3_LIB ERR_LIB_X509V3/* 34 */ +# define ERR_R_ENGINE_LIB ERR_LIB_ENGINE/* 38 */ +# define ERR_R_UI_LIB ERR_LIB_UI/* 40 */ +# define ERR_R_ECDSA_LIB ERR_LIB_ECDSA/* 42 */ +# define ERR_R_OSSL_STORE_LIB ERR_LIB_OSSL_STORE/* 44 */ + +# define ERR_R_NESTED_ASN1_ERROR 58 +# define ERR_R_MISSING_ASN1_EOS 63 + +/* fatal error */ +# define ERR_R_FATAL 64 +# define ERR_R_MALLOC_FAILURE (1|ERR_R_FATAL) +# define ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED (2|ERR_R_FATAL) +# define ERR_R_PASSED_NULL_PARAMETER (3|ERR_R_FATAL) +# define ERR_R_INTERNAL_ERROR (4|ERR_R_FATAL) +# define ERR_R_DISABLED (5|ERR_R_FATAL) +# define ERR_R_INIT_FAIL (6|ERR_R_FATAL) +# define ERR_R_PASSED_INVALID_ARGUMENT (7) +# define ERR_R_OPERATION_FAIL (8|ERR_R_FATAL) + +/* + * 99 is the maximum possible ERR_R_... code, higher values are reserved for + * the individual libraries + */ + +typedef struct ERR_string_data_st { + unsigned long error; + const char *string; +} ERR_STRING_DATA; + +DEFINE_LHASH_OF(ERR_STRING_DATA); + +void ERR_put_error(int lib, int func, int reason, const char *file, int line); +void ERR_set_error_data(char *data, int flags); + +unsigned long ERR_get_error(void); +unsigned long ERR_get_error_line(const char **file, int *line); +unsigned long ERR_get_error_line_data(const char **file, int *line, + const char **data, int *flags); +unsigned long ERR_peek_error(void); +unsigned long ERR_peek_error_line(const char **file, int *line); +unsigned long ERR_peek_error_line_data(const char **file, int *line, + const char **data, int *flags); +unsigned long ERR_peek_last_error(void); +unsigned long ERR_peek_last_error_line(const char **file, int *line); +unsigned long ERR_peek_last_error_line_data(const char **file, int *line, + const char **data, int *flags); +void ERR_clear_error(void); +char *ERR_error_string(unsigned long e, char *buf); +void ERR_error_string_n(unsigned long e, char *buf, size_t len); +const char *ERR_lib_error_string(unsigned long e); +const char *ERR_func_error_string(unsigned long e); +const char *ERR_reason_error_string(unsigned long e); +void ERR_print_errors_cb(int (*cb) (const char *str, size_t len, void *u), + void *u); +# ifndef OPENSSL_NO_STDIO +void ERR_print_errors_fp(FILE *fp); +# endif +void ERR_print_errors(BIO *bp); +void ERR_add_error_data(int num, ...); +void ERR_add_error_vdata(int num, va_list args); +int ERR_load_strings(int lib, ERR_STRING_DATA *str); +int ERR_load_strings_const(const ERR_STRING_DATA *str); +int ERR_unload_strings(int lib, ERR_STRING_DATA *str); +int ERR_load_ERR_strings(void); + +#if OPENSSL_API_COMPAT < 0x10100000L +# define ERR_load_crypto_strings() \ + OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL) +# define ERR_free_strings() while(0) continue +#endif + +DEPRECATEDIN_1_1_0(void ERR_remove_thread_state(void *)) +DEPRECATEDIN_1_0_0(void ERR_remove_state(unsigned long pid)) +ERR_STATE *ERR_get_state(void); + +int ERR_get_next_error_library(void); + +int ERR_set_mark(void); +int ERR_pop_to_mark(void); +int ERR_clear_last_mark(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/evp.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/evp.h new file mode 100644 index 000000000..9f05b5a3b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/evp.h @@ -0,0 +1,1633 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_ENVELOPE_H +# define HEADER_ENVELOPE_H + +# include +# include +# include +# include +# include + +# define EVP_MAX_MD_SIZE 64/* longest known is SHA512 */ +# define EVP_MAX_KEY_LENGTH 64 +# define EVP_MAX_IV_LENGTH 16 +# define EVP_MAX_BLOCK_LENGTH 32 + +# define PKCS5_SALT_LEN 8 +/* Default PKCS#5 iteration count */ +# define PKCS5_DEFAULT_ITER 2048 + +# include + +# define EVP_PK_RSA 0x0001 +# define EVP_PK_DSA 0x0002 +# define EVP_PK_DH 0x0004 +# define EVP_PK_EC 0x0008 +# define EVP_PKT_SIGN 0x0010 +# define EVP_PKT_ENC 0x0020 +# define EVP_PKT_EXCH 0x0040 +# define EVP_PKS_RSA 0x0100 +# define EVP_PKS_DSA 0x0200 +# define EVP_PKS_EC 0x0400 + +# define EVP_PKEY_NONE NID_undef +# define EVP_PKEY_RSA NID_rsaEncryption +# define EVP_PKEY_RSA2 NID_rsa +# define EVP_PKEY_RSA_PSS NID_rsassaPss +# define EVP_PKEY_DSA NID_dsa +# define EVP_PKEY_DSA1 NID_dsa_2 +# define EVP_PKEY_DSA2 NID_dsaWithSHA +# define EVP_PKEY_DSA3 NID_dsaWithSHA1 +# define EVP_PKEY_DSA4 NID_dsaWithSHA1_2 +# define EVP_PKEY_DH NID_dhKeyAgreement +# define EVP_PKEY_DHX NID_dhpublicnumber +# define EVP_PKEY_EC NID_X9_62_id_ecPublicKey +# define EVP_PKEY_SM2 NID_sm2 +# define EVP_PKEY_HMAC NID_hmac +# define EVP_PKEY_CMAC NID_cmac +# define EVP_PKEY_SCRYPT NID_id_scrypt +# define EVP_PKEY_TLS1_PRF NID_tls1_prf +# define EVP_PKEY_HKDF NID_hkdf +# define EVP_PKEY_POLY1305 NID_poly1305 +# define EVP_PKEY_SIPHASH NID_siphash +# define EVP_PKEY_X25519 NID_X25519 +# define EVP_PKEY_ED25519 NID_ED25519 +# define EVP_PKEY_X448 NID_X448 +# define EVP_PKEY_ED448 NID_ED448 + +#ifdef __cplusplus +extern "C" { +#endif + +# define EVP_PKEY_MO_SIGN 0x0001 +# define EVP_PKEY_MO_VERIFY 0x0002 +# define EVP_PKEY_MO_ENCRYPT 0x0004 +# define EVP_PKEY_MO_DECRYPT 0x0008 + +# ifndef EVP_MD +EVP_MD *EVP_MD_meth_new(int md_type, int pkey_type); +EVP_MD *EVP_MD_meth_dup(const EVP_MD *md); +void EVP_MD_meth_free(EVP_MD *md); + +int EVP_MD_meth_set_input_blocksize(EVP_MD *md, int blocksize); +int EVP_MD_meth_set_result_size(EVP_MD *md, int resultsize); +int EVP_MD_meth_set_app_datasize(EVP_MD *md, int datasize); +int EVP_MD_meth_set_flags(EVP_MD *md, unsigned long flags); +int EVP_MD_meth_set_init(EVP_MD *md, int (*init)(EVP_MD_CTX *ctx)); +int EVP_MD_meth_set_update(EVP_MD *md, int (*update)(EVP_MD_CTX *ctx, + const void *data, + size_t count)); +int EVP_MD_meth_set_final(EVP_MD *md, int (*final)(EVP_MD_CTX *ctx, + unsigned char *md)); +int EVP_MD_meth_set_copy(EVP_MD *md, int (*copy)(EVP_MD_CTX *to, + const EVP_MD_CTX *from)); +int EVP_MD_meth_set_cleanup(EVP_MD *md, int (*cleanup)(EVP_MD_CTX *ctx)); +int EVP_MD_meth_set_ctrl(EVP_MD *md, int (*ctrl)(EVP_MD_CTX *ctx, int cmd, + int p1, void *p2)); + +int EVP_MD_meth_get_input_blocksize(const EVP_MD *md); +int EVP_MD_meth_get_result_size(const EVP_MD *md); +int EVP_MD_meth_get_app_datasize(const EVP_MD *md); +unsigned long EVP_MD_meth_get_flags(const EVP_MD *md); +int (*EVP_MD_meth_get_init(const EVP_MD *md))(EVP_MD_CTX *ctx); +int (*EVP_MD_meth_get_update(const EVP_MD *md))(EVP_MD_CTX *ctx, + const void *data, + size_t count); +int (*EVP_MD_meth_get_final(const EVP_MD *md))(EVP_MD_CTX *ctx, + unsigned char *md); +int (*EVP_MD_meth_get_copy(const EVP_MD *md))(EVP_MD_CTX *to, + const EVP_MD_CTX *from); +int (*EVP_MD_meth_get_cleanup(const EVP_MD *md))(EVP_MD_CTX *ctx); +int (*EVP_MD_meth_get_ctrl(const EVP_MD *md))(EVP_MD_CTX *ctx, int cmd, + int p1, void *p2); + +/* digest can only handle a single block */ +# define EVP_MD_FLAG_ONESHOT 0x0001 + +/* digest is extensible-output function, XOF */ +# define EVP_MD_FLAG_XOF 0x0002 + +/* DigestAlgorithmIdentifier flags... */ + +# define EVP_MD_FLAG_DIGALGID_MASK 0x0018 + +/* NULL or absent parameter accepted. Use NULL */ + +# define EVP_MD_FLAG_DIGALGID_NULL 0x0000 + +/* NULL or absent parameter accepted. Use NULL for PKCS#1 otherwise absent */ + +# define EVP_MD_FLAG_DIGALGID_ABSENT 0x0008 + +/* Custom handling via ctrl */ + +# define EVP_MD_FLAG_DIGALGID_CUSTOM 0x0018 + +/* Note if suitable for use in FIPS mode */ +# define EVP_MD_FLAG_FIPS 0x0400 + +/* Digest ctrls */ + +# define EVP_MD_CTRL_DIGALGID 0x1 +# define EVP_MD_CTRL_MICALG 0x2 +# define EVP_MD_CTRL_XOF_LEN 0x3 + +/* Minimum Algorithm specific ctrl value */ + +# define EVP_MD_CTRL_ALG_CTRL 0x1000 + +# endif /* !EVP_MD */ + +/* values for EVP_MD_CTX flags */ + +# define EVP_MD_CTX_FLAG_ONESHOT 0x0001/* digest update will be + * called once only */ +# define EVP_MD_CTX_FLAG_CLEANED 0x0002/* context has already been + * cleaned */ +# define EVP_MD_CTX_FLAG_REUSE 0x0004/* Don't free up ctx->md_data + * in EVP_MD_CTX_reset */ +/* + * FIPS and pad options are ignored in 1.0.0, definitions are here so we + * don't accidentally reuse the values for other purposes. + */ + +# define EVP_MD_CTX_FLAG_NON_FIPS_ALLOW 0x0008/* Allow use of non FIPS + * digest in FIPS mode */ + +/* + * The following PAD options are also currently ignored in 1.0.0, digest + * parameters are handled through EVP_DigestSign*() and EVP_DigestVerify*() + * instead. + */ +# define EVP_MD_CTX_FLAG_PAD_MASK 0xF0/* RSA mode to use */ +# define EVP_MD_CTX_FLAG_PAD_PKCS1 0x00/* PKCS#1 v1.5 mode */ +# define EVP_MD_CTX_FLAG_PAD_X931 0x10/* X9.31 mode */ +# define EVP_MD_CTX_FLAG_PAD_PSS 0x20/* PSS mode */ + +# define EVP_MD_CTX_FLAG_NO_INIT 0x0100/* Don't initialize md_data */ +/* + * Some functions such as EVP_DigestSign only finalise copies of internal + * contexts so additional data can be included after the finalisation call. + * This is inefficient if this functionality is not required: it is disabled + * if the following flag is set. + */ +# define EVP_MD_CTX_FLAG_FINALISE 0x0200 +/* NOTE: 0x0400 is reserved for internal usage in evp_int.h */ + +EVP_CIPHER *EVP_CIPHER_meth_new(int cipher_type, int block_size, int key_len); +EVP_CIPHER *EVP_CIPHER_meth_dup(const EVP_CIPHER *cipher); +void EVP_CIPHER_meth_free(EVP_CIPHER *cipher); + +int EVP_CIPHER_meth_set_iv_length(EVP_CIPHER *cipher, int iv_len); +int EVP_CIPHER_meth_set_flags(EVP_CIPHER *cipher, unsigned long flags); +int EVP_CIPHER_meth_set_impl_ctx_size(EVP_CIPHER *cipher, int ctx_size); +int EVP_CIPHER_meth_set_init(EVP_CIPHER *cipher, + int (*init) (EVP_CIPHER_CTX *ctx, + const unsigned char *key, + const unsigned char *iv, + int enc)); +int EVP_CIPHER_meth_set_do_cipher(EVP_CIPHER *cipher, + int (*do_cipher) (EVP_CIPHER_CTX *ctx, + unsigned char *out, + const unsigned char *in, + size_t inl)); +int EVP_CIPHER_meth_set_cleanup(EVP_CIPHER *cipher, + int (*cleanup) (EVP_CIPHER_CTX *)); +int EVP_CIPHER_meth_set_set_asn1_params(EVP_CIPHER *cipher, + int (*set_asn1_parameters) (EVP_CIPHER_CTX *, + ASN1_TYPE *)); +int EVP_CIPHER_meth_set_get_asn1_params(EVP_CIPHER *cipher, + int (*get_asn1_parameters) (EVP_CIPHER_CTX *, + ASN1_TYPE *)); +int EVP_CIPHER_meth_set_ctrl(EVP_CIPHER *cipher, + int (*ctrl) (EVP_CIPHER_CTX *, int type, + int arg, void *ptr)); + +int (*EVP_CIPHER_meth_get_init(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *ctx, + const unsigned char *key, + const unsigned char *iv, + int enc); +int (*EVP_CIPHER_meth_get_do_cipher(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *ctx, + unsigned char *out, + const unsigned char *in, + size_t inl); +int (*EVP_CIPHER_meth_get_cleanup(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *); +int (*EVP_CIPHER_meth_get_set_asn1_params(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *, + ASN1_TYPE *); +int (*EVP_CIPHER_meth_get_get_asn1_params(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *, + ASN1_TYPE *); +int (*EVP_CIPHER_meth_get_ctrl(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *, + int type, int arg, + void *ptr); + +/* Values for cipher flags */ + +/* Modes for ciphers */ + +# define EVP_CIPH_STREAM_CIPHER 0x0 +# define EVP_CIPH_ECB_MODE 0x1 +# define EVP_CIPH_CBC_MODE 0x2 +# define EVP_CIPH_CFB_MODE 0x3 +# define EVP_CIPH_OFB_MODE 0x4 +# define EVP_CIPH_CTR_MODE 0x5 +# define EVP_CIPH_GCM_MODE 0x6 +# define EVP_CIPH_CCM_MODE 0x7 +# define EVP_CIPH_XTS_MODE 0x10001 +# define EVP_CIPH_WRAP_MODE 0x10002 +# define EVP_CIPH_OCB_MODE 0x10003 +# define EVP_CIPH_MODE 0xF0007 +/* Set if variable length cipher */ +# define EVP_CIPH_VARIABLE_LENGTH 0x8 +/* Set if the iv handling should be done by the cipher itself */ +# define EVP_CIPH_CUSTOM_IV 0x10 +/* Set if the cipher's init() function should be called if key is NULL */ +# define EVP_CIPH_ALWAYS_CALL_INIT 0x20 +/* Call ctrl() to init cipher parameters */ +# define EVP_CIPH_CTRL_INIT 0x40 +/* Don't use standard key length function */ +# define EVP_CIPH_CUSTOM_KEY_LENGTH 0x80 +/* Don't use standard block padding */ +# define EVP_CIPH_NO_PADDING 0x100 +/* cipher handles random key generation */ +# define EVP_CIPH_RAND_KEY 0x200 +/* cipher has its own additional copying logic */ +# define EVP_CIPH_CUSTOM_COPY 0x400 +/* Allow use default ASN1 get/set iv */ +# define EVP_CIPH_FLAG_DEFAULT_ASN1 0x1000 +/* Buffer length in bits not bytes: CFB1 mode only */ +# define EVP_CIPH_FLAG_LENGTH_BITS 0x2000 +/* Note if suitable for use in FIPS mode */ +# define EVP_CIPH_FLAG_FIPS 0x4000 +/* Allow non FIPS cipher in FIPS mode */ +# define EVP_CIPH_FLAG_NON_FIPS_ALLOW 0x8000 +/* + * Cipher handles any and all padding logic as well as finalisation. + */ +# define EVP_CIPH_FLAG_CUSTOM_CIPHER 0x100000 +# define EVP_CIPH_FLAG_AEAD_CIPHER 0x200000 +# define EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK 0x400000 +/* Cipher can handle pipeline operations */ +# define EVP_CIPH_FLAG_PIPELINE 0X800000 + +/* + * Cipher context flag to indicate we can handle wrap mode: if allowed in + * older applications it could overflow buffers. + */ + +# define EVP_CIPHER_CTX_FLAG_WRAP_ALLOW 0x1 + +/* ctrl() values */ + +# define EVP_CTRL_INIT 0x0 +# define EVP_CTRL_SET_KEY_LENGTH 0x1 +# define EVP_CTRL_GET_RC2_KEY_BITS 0x2 +# define EVP_CTRL_SET_RC2_KEY_BITS 0x3 +# define EVP_CTRL_GET_RC5_ROUNDS 0x4 +# define EVP_CTRL_SET_RC5_ROUNDS 0x5 +# define EVP_CTRL_RAND_KEY 0x6 +# define EVP_CTRL_PBE_PRF_NID 0x7 +# define EVP_CTRL_COPY 0x8 +# define EVP_CTRL_AEAD_SET_IVLEN 0x9 +# define EVP_CTRL_AEAD_GET_TAG 0x10 +# define EVP_CTRL_AEAD_SET_TAG 0x11 +# define EVP_CTRL_AEAD_SET_IV_FIXED 0x12 +# define EVP_CTRL_GCM_SET_IVLEN EVP_CTRL_AEAD_SET_IVLEN +# define EVP_CTRL_GCM_GET_TAG EVP_CTRL_AEAD_GET_TAG +# define EVP_CTRL_GCM_SET_TAG EVP_CTRL_AEAD_SET_TAG +# define EVP_CTRL_GCM_SET_IV_FIXED EVP_CTRL_AEAD_SET_IV_FIXED +# define EVP_CTRL_GCM_IV_GEN 0x13 +# define EVP_CTRL_CCM_SET_IVLEN EVP_CTRL_AEAD_SET_IVLEN +# define EVP_CTRL_CCM_GET_TAG EVP_CTRL_AEAD_GET_TAG +# define EVP_CTRL_CCM_SET_TAG EVP_CTRL_AEAD_SET_TAG +# define EVP_CTRL_CCM_SET_IV_FIXED EVP_CTRL_AEAD_SET_IV_FIXED +# define EVP_CTRL_CCM_SET_L 0x14 +# define EVP_CTRL_CCM_SET_MSGLEN 0x15 +/* + * AEAD cipher deduces payload length and returns number of bytes required to + * store MAC and eventual padding. Subsequent call to EVP_Cipher even + * appends/verifies MAC. + */ +# define EVP_CTRL_AEAD_TLS1_AAD 0x16 +/* Used by composite AEAD ciphers, no-op in GCM, CCM... */ +# define EVP_CTRL_AEAD_SET_MAC_KEY 0x17 +/* Set the GCM invocation field, decrypt only */ +# define EVP_CTRL_GCM_SET_IV_INV 0x18 + +# define EVP_CTRL_TLS1_1_MULTIBLOCK_AAD 0x19 +# define EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT 0x1a +# define EVP_CTRL_TLS1_1_MULTIBLOCK_DECRYPT 0x1b +# define EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE 0x1c + +# define EVP_CTRL_SSL3_MASTER_SECRET 0x1d + +/* EVP_CTRL_SET_SBOX takes the char * specifying S-boxes */ +# define EVP_CTRL_SET_SBOX 0x1e +/* + * EVP_CTRL_SBOX_USED takes a 'size_t' and 'char *', pointing at a + * pre-allocated buffer with specified size + */ +# define EVP_CTRL_SBOX_USED 0x1f +/* EVP_CTRL_KEY_MESH takes 'size_t' number of bytes to mesh the key after, + * 0 switches meshing off + */ +# define EVP_CTRL_KEY_MESH 0x20 +/* EVP_CTRL_BLOCK_PADDING_MODE takes the padding mode */ +# define EVP_CTRL_BLOCK_PADDING_MODE 0x21 + +/* Set the output buffers to use for a pipelined operation */ +# define EVP_CTRL_SET_PIPELINE_OUTPUT_BUFS 0x22 +/* Set the input buffers to use for a pipelined operation */ +# define EVP_CTRL_SET_PIPELINE_INPUT_BUFS 0x23 +/* Set the input buffer lengths to use for a pipelined operation */ +# define EVP_CTRL_SET_PIPELINE_INPUT_LENS 0x24 + +/* Padding modes */ +#define EVP_PADDING_PKCS7 1 +#define EVP_PADDING_ISO7816_4 2 +#define EVP_PADDING_ANSI923 3 +#define EVP_PADDING_ISO10126 4 +#define EVP_PADDING_ZERO 5 + +/* RFC 5246 defines additional data to be 13 bytes in length */ +# define EVP_AEAD_TLS1_AAD_LEN 13 + +typedef struct { + unsigned char *out; + const unsigned char *inp; + size_t len; + unsigned int interleave; +} EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM; + +/* GCM TLS constants */ +/* Length of fixed part of IV derived from PRF */ +# define EVP_GCM_TLS_FIXED_IV_LEN 4 +/* Length of explicit part of IV part of TLS records */ +# define EVP_GCM_TLS_EXPLICIT_IV_LEN 8 +/* Length of tag for TLS */ +# define EVP_GCM_TLS_TAG_LEN 16 + +/* CCM TLS constants */ +/* Length of fixed part of IV derived from PRF */ +# define EVP_CCM_TLS_FIXED_IV_LEN 4 +/* Length of explicit part of IV part of TLS records */ +# define EVP_CCM_TLS_EXPLICIT_IV_LEN 8 +/* Total length of CCM IV length for TLS */ +# define EVP_CCM_TLS_IV_LEN 12 +/* Length of tag for TLS */ +# define EVP_CCM_TLS_TAG_LEN 16 +/* Length of CCM8 tag for TLS */ +# define EVP_CCM8_TLS_TAG_LEN 8 + +/* Length of tag for TLS */ +# define EVP_CHACHAPOLY_TLS_TAG_LEN 16 + +typedef struct evp_cipher_info_st { + const EVP_CIPHER *cipher; + unsigned char iv[EVP_MAX_IV_LENGTH]; +} EVP_CIPHER_INFO; + + +/* Password based encryption function */ +typedef int (EVP_PBE_KEYGEN) (EVP_CIPHER_CTX *ctx, const char *pass, + int passlen, ASN1_TYPE *param, + const EVP_CIPHER *cipher, const EVP_MD *md, + int en_de); + +# ifndef OPENSSL_NO_RSA +# define EVP_PKEY_assign_RSA(pkey,rsa) EVP_PKEY_assign((pkey),EVP_PKEY_RSA,\ + (char *)(rsa)) +# endif + +# ifndef OPENSSL_NO_DSA +# define EVP_PKEY_assign_DSA(pkey,dsa) EVP_PKEY_assign((pkey),EVP_PKEY_DSA,\ + (char *)(dsa)) +# endif + +# ifndef OPENSSL_NO_DH +# define EVP_PKEY_assign_DH(pkey,dh) EVP_PKEY_assign((pkey),EVP_PKEY_DH,\ + (char *)(dh)) +# endif + +# ifndef OPENSSL_NO_EC +# define EVP_PKEY_assign_EC_KEY(pkey,eckey) EVP_PKEY_assign((pkey),EVP_PKEY_EC,\ + (char *)(eckey)) +# endif +# ifndef OPENSSL_NO_SIPHASH +# define EVP_PKEY_assign_SIPHASH(pkey,shkey) EVP_PKEY_assign((pkey),EVP_PKEY_SIPHASH,\ + (char *)(shkey)) +# endif + +# ifndef OPENSSL_NO_POLY1305 +# define EVP_PKEY_assign_POLY1305(pkey,polykey) EVP_PKEY_assign((pkey),EVP_PKEY_POLY1305,\ + (char *)(polykey)) +# endif + +/* Add some extra combinations */ +# define EVP_get_digestbynid(a) EVP_get_digestbyname(OBJ_nid2sn(a)) +# define EVP_get_digestbyobj(a) EVP_get_digestbynid(OBJ_obj2nid(a)) +# define EVP_get_cipherbynid(a) EVP_get_cipherbyname(OBJ_nid2sn(a)) +# define EVP_get_cipherbyobj(a) EVP_get_cipherbynid(OBJ_obj2nid(a)) + +int EVP_MD_type(const EVP_MD *md); +# define EVP_MD_nid(e) EVP_MD_type(e) +# define EVP_MD_name(e) OBJ_nid2sn(EVP_MD_nid(e)) +int EVP_MD_pkey_type(const EVP_MD *md); +int EVP_MD_size(const EVP_MD *md); +int EVP_MD_block_size(const EVP_MD *md); +unsigned long EVP_MD_flags(const EVP_MD *md); + +const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx); +int (*EVP_MD_CTX_update_fn(EVP_MD_CTX *ctx))(EVP_MD_CTX *ctx, + const void *data, size_t count); +void EVP_MD_CTX_set_update_fn(EVP_MD_CTX *ctx, + int (*update) (EVP_MD_CTX *ctx, + const void *data, size_t count)); +# define EVP_MD_CTX_size(e) EVP_MD_size(EVP_MD_CTX_md(e)) +# define EVP_MD_CTX_block_size(e) EVP_MD_block_size(EVP_MD_CTX_md(e)) +# define EVP_MD_CTX_type(e) EVP_MD_type(EVP_MD_CTX_md(e)) +EVP_PKEY_CTX *EVP_MD_CTX_pkey_ctx(const EVP_MD_CTX *ctx); +void EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx); +void *EVP_MD_CTX_md_data(const EVP_MD_CTX *ctx); + +int EVP_CIPHER_nid(const EVP_CIPHER *cipher); +# define EVP_CIPHER_name(e) OBJ_nid2sn(EVP_CIPHER_nid(e)) +int EVP_CIPHER_block_size(const EVP_CIPHER *cipher); +int EVP_CIPHER_impl_ctx_size(const EVP_CIPHER *cipher); +int EVP_CIPHER_key_length(const EVP_CIPHER *cipher); +int EVP_CIPHER_iv_length(const EVP_CIPHER *cipher); +unsigned long EVP_CIPHER_flags(const EVP_CIPHER *cipher); +# define EVP_CIPHER_mode(e) (EVP_CIPHER_flags(e) & EVP_CIPH_MODE) + +const EVP_CIPHER *EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx); +int EVP_CIPHER_CTX_encrypting(const EVP_CIPHER_CTX *ctx); +int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx); +int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx); +int EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx); +int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx); +const unsigned char *EVP_CIPHER_CTX_iv(const EVP_CIPHER_CTX *ctx); +const unsigned char *EVP_CIPHER_CTX_original_iv(const EVP_CIPHER_CTX *ctx); +unsigned char *EVP_CIPHER_CTX_iv_noconst(EVP_CIPHER_CTX *ctx); +unsigned char *EVP_CIPHER_CTX_buf_noconst(EVP_CIPHER_CTX *ctx); +int EVP_CIPHER_CTX_num(const EVP_CIPHER_CTX *ctx); +void EVP_CIPHER_CTX_set_num(EVP_CIPHER_CTX *ctx, int num); +int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in); +void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx); +void EVP_CIPHER_CTX_set_app_data(EVP_CIPHER_CTX *ctx, void *data); +void *EVP_CIPHER_CTX_get_cipher_data(const EVP_CIPHER_CTX *ctx); +void *EVP_CIPHER_CTX_set_cipher_data(EVP_CIPHER_CTX *ctx, void *cipher_data); +# define EVP_CIPHER_CTX_type(c) EVP_CIPHER_type(EVP_CIPHER_CTX_cipher(c)) +# if OPENSSL_API_COMPAT < 0x10100000L +# define EVP_CIPHER_CTX_flags(c) EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(c)) +# endif +# define EVP_CIPHER_CTX_mode(c) EVP_CIPHER_mode(EVP_CIPHER_CTX_cipher(c)) + +# define EVP_ENCODE_LENGTH(l) ((((l)+2)/3*4)+((l)/48+1)*2+80) +# define EVP_DECODE_LENGTH(l) (((l)+3)/4*3+80) + +# define EVP_SignInit_ex(a,b,c) EVP_DigestInit_ex(a,b,c) +# define EVP_SignInit(a,b) EVP_DigestInit(a,b) +# define EVP_SignUpdate(a,b,c) EVP_DigestUpdate(a,b,c) +# define EVP_VerifyInit_ex(a,b,c) EVP_DigestInit_ex(a,b,c) +# define EVP_VerifyInit(a,b) EVP_DigestInit(a,b) +# define EVP_VerifyUpdate(a,b,c) EVP_DigestUpdate(a,b,c) +# define EVP_OpenUpdate(a,b,c,d,e) EVP_DecryptUpdate(a,b,c,d,e) +# define EVP_SealUpdate(a,b,c,d,e) EVP_EncryptUpdate(a,b,c,d,e) +# define EVP_DigestSignUpdate(a,b,c) EVP_DigestUpdate(a,b,c) +# define EVP_DigestVerifyUpdate(a,b,c) EVP_DigestUpdate(a,b,c) + +# ifdef CONST_STRICT +void BIO_set_md(BIO *, const EVP_MD *md); +# else +# define BIO_set_md(b,md) BIO_ctrl(b,BIO_C_SET_MD,0,(char *)(md)) +# endif +# define BIO_get_md(b,mdp) BIO_ctrl(b,BIO_C_GET_MD,0,(char *)(mdp)) +# define BIO_get_md_ctx(b,mdcp) BIO_ctrl(b,BIO_C_GET_MD_CTX,0, \ + (char *)(mdcp)) +# define BIO_set_md_ctx(b,mdcp) BIO_ctrl(b,BIO_C_SET_MD_CTX,0, \ + (char *)(mdcp)) +# define BIO_get_cipher_status(b) BIO_ctrl(b,BIO_C_GET_CIPHER_STATUS,0,NULL) +# define BIO_get_cipher_ctx(b,c_pp) BIO_ctrl(b,BIO_C_GET_CIPHER_CTX,0, \ + (char *)(c_pp)) + +/*__owur*/ int EVP_Cipher(EVP_CIPHER_CTX *c, + unsigned char *out, + const unsigned char *in, unsigned int inl); + +# define EVP_add_cipher_alias(n,alias) \ + OBJ_NAME_add((alias),OBJ_NAME_TYPE_CIPHER_METH|OBJ_NAME_ALIAS,(n)) +# define EVP_add_digest_alias(n,alias) \ + OBJ_NAME_add((alias),OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS,(n)) +# define EVP_delete_cipher_alias(alias) \ + OBJ_NAME_remove(alias,OBJ_NAME_TYPE_CIPHER_METH|OBJ_NAME_ALIAS); +# define EVP_delete_digest_alias(alias) \ + OBJ_NAME_remove(alias,OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS); + +int EVP_MD_CTX_ctrl(EVP_MD_CTX *ctx, int cmd, int p1, void *p2); +EVP_MD_CTX *EVP_MD_CTX_new(void); +int EVP_MD_CTX_reset(EVP_MD_CTX *ctx); +void EVP_MD_CTX_free(EVP_MD_CTX *ctx); +# define EVP_MD_CTX_create() EVP_MD_CTX_new() +# define EVP_MD_CTX_init(ctx) EVP_MD_CTX_reset((ctx)) +# define EVP_MD_CTX_destroy(ctx) EVP_MD_CTX_free((ctx)) +__owur int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in); +void EVP_MD_CTX_set_flags(EVP_MD_CTX *ctx, int flags); +void EVP_MD_CTX_clear_flags(EVP_MD_CTX *ctx, int flags); +int EVP_MD_CTX_test_flags(const EVP_MD_CTX *ctx, int flags); +__owur int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, + ENGINE *impl); +__owur int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, + size_t cnt); +__owur int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, + unsigned int *s); +__owur int EVP_Digest(const void *data, size_t count, + unsigned char *md, unsigned int *size, + const EVP_MD *type, ENGINE *impl); + +__owur int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in); +__owur int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type); +__owur int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, + unsigned int *s); +__owur int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md, + size_t len); + +int EVP_read_pw_string(char *buf, int length, const char *prompt, int verify); +int EVP_read_pw_string_min(char *buf, int minlen, int maxlen, + const char *prompt, int verify); +void EVP_set_pw_prompt(const char *prompt); +char *EVP_get_pw_prompt(void); + +__owur int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md, + const unsigned char *salt, + const unsigned char *data, int datal, int count, + unsigned char *key, unsigned char *iv); + +void EVP_CIPHER_CTX_set_flags(EVP_CIPHER_CTX *ctx, int flags); +void EVP_CIPHER_CTX_clear_flags(EVP_CIPHER_CTX *ctx, int flags); +int EVP_CIPHER_CTX_test_flags(const EVP_CIPHER_CTX *ctx, int flags); + +__owur int EVP_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + const unsigned char *key, const unsigned char *iv); +/*__owur*/ int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, + const EVP_CIPHER *cipher, ENGINE *impl, + const unsigned char *key, + const unsigned char *iv); +/*__owur*/ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, + int *outl, const unsigned char *in, int inl); +/*__owur*/ int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, + int *outl); +/*__owur*/ int EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, + int *outl); + +__owur int EVP_DecryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + const unsigned char *key, const unsigned char *iv); +/*__owur*/ int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, + const EVP_CIPHER *cipher, ENGINE *impl, + const unsigned char *key, + const unsigned char *iv); +/*__owur*/ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, + int *outl, const unsigned char *in, int inl); +__owur int EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, + int *outl); +/*__owur*/ int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, + int *outl); + +__owur int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + const unsigned char *key, const unsigned char *iv, + int enc); +/*__owur*/ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, + const EVP_CIPHER *cipher, ENGINE *impl, + const unsigned char *key, + const unsigned char *iv, int enc); +__owur int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, + int *outl, const unsigned char *in, int inl); +__owur int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, + int *outl); +__owur int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, + int *outl); + +__owur int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s, + EVP_PKEY *pkey); + +__owur int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, + size_t *siglen, const unsigned char *tbs, + size_t tbslen); + +__owur int EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf, + unsigned int siglen, EVP_PKEY *pkey); + +__owur int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret, + size_t siglen, const unsigned char *tbs, + size_t tbslen); + +/*__owur*/ int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, + const EVP_MD *type, ENGINE *e, + EVP_PKEY *pkey); +__owur int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, + size_t *siglen); + +__owur int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, + const EVP_MD *type, ENGINE *e, + EVP_PKEY *pkey); +__owur int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig, + size_t siglen); + +# ifndef OPENSSL_NO_RSA +__owur int EVP_OpenInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, + const unsigned char *ek, int ekl, + const unsigned char *iv, EVP_PKEY *priv); +__owur int EVP_OpenFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl); + +__owur int EVP_SealInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, + unsigned char **ek, int *ekl, unsigned char *iv, + EVP_PKEY **pubk, int npubk); +__owur int EVP_SealFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl); +# endif + +EVP_ENCODE_CTX *EVP_ENCODE_CTX_new(void); +void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx); +int EVP_ENCODE_CTX_copy(EVP_ENCODE_CTX *dctx, EVP_ENCODE_CTX *sctx); +int EVP_ENCODE_CTX_num(EVP_ENCODE_CTX *ctx); +void EVP_EncodeInit(EVP_ENCODE_CTX *ctx); +int EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl); +void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl); +int EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int n); + +void EVP_DecodeInit(EVP_ENCODE_CTX *ctx); +int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl); +int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned + char *out, int *outl); +int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n); + +# if OPENSSL_API_COMPAT < 0x10100000L +# define EVP_CIPHER_CTX_init(c) EVP_CIPHER_CTX_reset(c) +# define EVP_CIPHER_CTX_cleanup(c) EVP_CIPHER_CTX_reset(c) +# endif +EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void); +int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *c); +void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *c); +int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen); +int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *c, int pad); +int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr); +int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key); + +const BIO_METHOD *BIO_f_md(void); +const BIO_METHOD *BIO_f_base64(void); +const BIO_METHOD *BIO_f_cipher(void); +const BIO_METHOD *BIO_f_reliable(void); +__owur int BIO_set_cipher(BIO *b, const EVP_CIPHER *c, const unsigned char *k, + const unsigned char *i, int enc); + +const EVP_MD *EVP_md_null(void); +# ifndef OPENSSL_NO_MD2 +const EVP_MD *EVP_md2(void); +# endif +# ifndef OPENSSL_NO_MD4 +const EVP_MD *EVP_md4(void); +# endif +# ifndef OPENSSL_NO_MD5 +const EVP_MD *EVP_md5(void); +const EVP_MD *EVP_md5_sha1(void); +# endif +# ifndef OPENSSL_NO_BLAKE2 +const EVP_MD *EVP_blake2b512(void); +const EVP_MD *EVP_blake2s256(void); +# endif +const EVP_MD *EVP_sha1(void); +const EVP_MD *EVP_sha224(void); +const EVP_MD *EVP_sha256(void); +const EVP_MD *EVP_sha384(void); +const EVP_MD *EVP_sha512(void); +const EVP_MD *EVP_sha512_224(void); +const EVP_MD *EVP_sha512_256(void); +const EVP_MD *EVP_sha3_224(void); +const EVP_MD *EVP_sha3_256(void); +const EVP_MD *EVP_sha3_384(void); +const EVP_MD *EVP_sha3_512(void); +const EVP_MD *EVP_shake128(void); +const EVP_MD *EVP_shake256(void); +# ifndef OPENSSL_NO_MDC2 +const EVP_MD *EVP_mdc2(void); +# endif +# ifndef OPENSSL_NO_RMD160 +const EVP_MD *EVP_ripemd160(void); +# endif +# ifndef OPENSSL_NO_WHIRLPOOL +const EVP_MD *EVP_whirlpool(void); +# endif +# ifndef OPENSSL_NO_SM3 +const EVP_MD *EVP_sm3(void); +# endif +const EVP_CIPHER *EVP_enc_null(void); /* does nothing :-) */ +# ifndef OPENSSL_NO_DES +const EVP_CIPHER *EVP_des_ecb(void); +const EVP_CIPHER *EVP_des_ede(void); +const EVP_CIPHER *EVP_des_ede3(void); +const EVP_CIPHER *EVP_des_ede_ecb(void); +const EVP_CIPHER *EVP_des_ede3_ecb(void); +const EVP_CIPHER *EVP_des_cfb64(void); +# define EVP_des_cfb EVP_des_cfb64 +const EVP_CIPHER *EVP_des_cfb1(void); +const EVP_CIPHER *EVP_des_cfb8(void); +const EVP_CIPHER *EVP_des_ede_cfb64(void); +# define EVP_des_ede_cfb EVP_des_ede_cfb64 +const EVP_CIPHER *EVP_des_ede3_cfb64(void); +# define EVP_des_ede3_cfb EVP_des_ede3_cfb64 +const EVP_CIPHER *EVP_des_ede3_cfb1(void); +const EVP_CIPHER *EVP_des_ede3_cfb8(void); +const EVP_CIPHER *EVP_des_ofb(void); +const EVP_CIPHER *EVP_des_ede_ofb(void); +const EVP_CIPHER *EVP_des_ede3_ofb(void); +const EVP_CIPHER *EVP_des_cbc(void); +const EVP_CIPHER *EVP_des_ede_cbc(void); +const EVP_CIPHER *EVP_des_ede3_cbc(void); +const EVP_CIPHER *EVP_desx_cbc(void); +const EVP_CIPHER *EVP_des_ede3_wrap(void); +/* + * This should now be supported through the dev_crypto ENGINE. But also, why + * are rc4 and md5 declarations made here inside a "NO_DES" precompiler + * branch? + */ +# endif +# ifndef OPENSSL_NO_RC4 +const EVP_CIPHER *EVP_rc4(void); +const EVP_CIPHER *EVP_rc4_40(void); +# ifndef OPENSSL_NO_MD5 +const EVP_CIPHER *EVP_rc4_hmac_md5(void); +# endif +# endif +# ifndef OPENSSL_NO_IDEA +const EVP_CIPHER *EVP_idea_ecb(void); +const EVP_CIPHER *EVP_idea_cfb64(void); +# define EVP_idea_cfb EVP_idea_cfb64 +const EVP_CIPHER *EVP_idea_ofb(void); +const EVP_CIPHER *EVP_idea_cbc(void); +# endif +# ifndef OPENSSL_NO_RC2 +const EVP_CIPHER *EVP_rc2_ecb(void); +const EVP_CIPHER *EVP_rc2_cbc(void); +const EVP_CIPHER *EVP_rc2_40_cbc(void); +const EVP_CIPHER *EVP_rc2_64_cbc(void); +const EVP_CIPHER *EVP_rc2_cfb64(void); +# define EVP_rc2_cfb EVP_rc2_cfb64 +const EVP_CIPHER *EVP_rc2_ofb(void); +# endif +# ifndef OPENSSL_NO_BF +const EVP_CIPHER *EVP_bf_ecb(void); +const EVP_CIPHER *EVP_bf_cbc(void); +const EVP_CIPHER *EVP_bf_cfb64(void); +# define EVP_bf_cfb EVP_bf_cfb64 +const EVP_CIPHER *EVP_bf_ofb(void); +# endif +# ifndef OPENSSL_NO_CAST +const EVP_CIPHER *EVP_cast5_ecb(void); +const EVP_CIPHER *EVP_cast5_cbc(void); +const EVP_CIPHER *EVP_cast5_cfb64(void); +# define EVP_cast5_cfb EVP_cast5_cfb64 +const EVP_CIPHER *EVP_cast5_ofb(void); +# endif +# ifndef OPENSSL_NO_RC5 +const EVP_CIPHER *EVP_rc5_32_12_16_cbc(void); +const EVP_CIPHER *EVP_rc5_32_12_16_ecb(void); +const EVP_CIPHER *EVP_rc5_32_12_16_cfb64(void); +# define EVP_rc5_32_12_16_cfb EVP_rc5_32_12_16_cfb64 +const EVP_CIPHER *EVP_rc5_32_12_16_ofb(void); +# endif +const EVP_CIPHER *EVP_aes_128_ecb(void); +const EVP_CIPHER *EVP_aes_128_cbc(void); +const EVP_CIPHER *EVP_aes_128_cfb1(void); +const EVP_CIPHER *EVP_aes_128_cfb8(void); +const EVP_CIPHER *EVP_aes_128_cfb128(void); +# define EVP_aes_128_cfb EVP_aes_128_cfb128 +const EVP_CIPHER *EVP_aes_128_ofb(void); +const EVP_CIPHER *EVP_aes_128_ctr(void); +const EVP_CIPHER *EVP_aes_128_ccm(void); +const EVP_CIPHER *EVP_aes_128_gcm(void); +const EVP_CIPHER *EVP_aes_128_xts(void); +const EVP_CIPHER *EVP_aes_128_wrap(void); +const EVP_CIPHER *EVP_aes_128_wrap_pad(void); +# ifndef OPENSSL_NO_OCB +const EVP_CIPHER *EVP_aes_128_ocb(void); +# endif +const EVP_CIPHER *EVP_aes_192_ecb(void); +const EVP_CIPHER *EVP_aes_192_cbc(void); +const EVP_CIPHER *EVP_aes_192_cfb1(void); +const EVP_CIPHER *EVP_aes_192_cfb8(void); +const EVP_CIPHER *EVP_aes_192_cfb128(void); +# define EVP_aes_192_cfb EVP_aes_192_cfb128 +const EVP_CIPHER *EVP_aes_192_ofb(void); +const EVP_CIPHER *EVP_aes_192_ctr(void); +const EVP_CIPHER *EVP_aes_192_ccm(void); +const EVP_CIPHER *EVP_aes_192_gcm(void); +const EVP_CIPHER *EVP_aes_192_wrap(void); +const EVP_CIPHER *EVP_aes_192_wrap_pad(void); +# ifndef OPENSSL_NO_OCB +const EVP_CIPHER *EVP_aes_192_ocb(void); +# endif +const EVP_CIPHER *EVP_aes_256_ecb(void); +const EVP_CIPHER *EVP_aes_256_cbc(void); +const EVP_CIPHER *EVP_aes_256_cfb1(void); +const EVP_CIPHER *EVP_aes_256_cfb8(void); +const EVP_CIPHER *EVP_aes_256_cfb128(void); +# define EVP_aes_256_cfb EVP_aes_256_cfb128 +const EVP_CIPHER *EVP_aes_256_ofb(void); +const EVP_CIPHER *EVP_aes_256_ctr(void); +const EVP_CIPHER *EVP_aes_256_ccm(void); +const EVP_CIPHER *EVP_aes_256_gcm(void); +const EVP_CIPHER *EVP_aes_256_xts(void); +const EVP_CIPHER *EVP_aes_256_wrap(void); +const EVP_CIPHER *EVP_aes_256_wrap_pad(void); +# ifndef OPENSSL_NO_OCB +const EVP_CIPHER *EVP_aes_256_ocb(void); +# endif +const EVP_CIPHER *EVP_aes_128_cbc_hmac_sha1(void); +const EVP_CIPHER *EVP_aes_256_cbc_hmac_sha1(void); +const EVP_CIPHER *EVP_aes_128_cbc_hmac_sha256(void); +const EVP_CIPHER *EVP_aes_256_cbc_hmac_sha256(void); +# ifndef OPENSSL_NO_ARIA +const EVP_CIPHER *EVP_aria_128_ecb(void); +const EVP_CIPHER *EVP_aria_128_cbc(void); +const EVP_CIPHER *EVP_aria_128_cfb1(void); +const EVP_CIPHER *EVP_aria_128_cfb8(void); +const EVP_CIPHER *EVP_aria_128_cfb128(void); +# define EVP_aria_128_cfb EVP_aria_128_cfb128 +const EVP_CIPHER *EVP_aria_128_ctr(void); +const EVP_CIPHER *EVP_aria_128_ofb(void); +const EVP_CIPHER *EVP_aria_128_gcm(void); +const EVP_CIPHER *EVP_aria_128_ccm(void); +const EVP_CIPHER *EVP_aria_192_ecb(void); +const EVP_CIPHER *EVP_aria_192_cbc(void); +const EVP_CIPHER *EVP_aria_192_cfb1(void); +const EVP_CIPHER *EVP_aria_192_cfb8(void); +const EVP_CIPHER *EVP_aria_192_cfb128(void); +# define EVP_aria_192_cfb EVP_aria_192_cfb128 +const EVP_CIPHER *EVP_aria_192_ctr(void); +const EVP_CIPHER *EVP_aria_192_ofb(void); +const EVP_CIPHER *EVP_aria_192_gcm(void); +const EVP_CIPHER *EVP_aria_192_ccm(void); +const EVP_CIPHER *EVP_aria_256_ecb(void); +const EVP_CIPHER *EVP_aria_256_cbc(void); +const EVP_CIPHER *EVP_aria_256_cfb1(void); +const EVP_CIPHER *EVP_aria_256_cfb8(void); +const EVP_CIPHER *EVP_aria_256_cfb128(void); +# define EVP_aria_256_cfb EVP_aria_256_cfb128 +const EVP_CIPHER *EVP_aria_256_ctr(void); +const EVP_CIPHER *EVP_aria_256_ofb(void); +const EVP_CIPHER *EVP_aria_256_gcm(void); +const EVP_CIPHER *EVP_aria_256_ccm(void); +# endif +# ifndef OPENSSL_NO_CAMELLIA +const EVP_CIPHER *EVP_camellia_128_ecb(void); +const EVP_CIPHER *EVP_camellia_128_cbc(void); +const EVP_CIPHER *EVP_camellia_128_cfb1(void); +const EVP_CIPHER *EVP_camellia_128_cfb8(void); +const EVP_CIPHER *EVP_camellia_128_cfb128(void); +# define EVP_camellia_128_cfb EVP_camellia_128_cfb128 +const EVP_CIPHER *EVP_camellia_128_ofb(void); +const EVP_CIPHER *EVP_camellia_128_ctr(void); +const EVP_CIPHER *EVP_camellia_192_ecb(void); +const EVP_CIPHER *EVP_camellia_192_cbc(void); +const EVP_CIPHER *EVP_camellia_192_cfb1(void); +const EVP_CIPHER *EVP_camellia_192_cfb8(void); +const EVP_CIPHER *EVP_camellia_192_cfb128(void); +# define EVP_camellia_192_cfb EVP_camellia_192_cfb128 +const EVP_CIPHER *EVP_camellia_192_ofb(void); +const EVP_CIPHER *EVP_camellia_192_ctr(void); +const EVP_CIPHER *EVP_camellia_256_ecb(void); +const EVP_CIPHER *EVP_camellia_256_cbc(void); +const EVP_CIPHER *EVP_camellia_256_cfb1(void); +const EVP_CIPHER *EVP_camellia_256_cfb8(void); +const EVP_CIPHER *EVP_camellia_256_cfb128(void); +# define EVP_camellia_256_cfb EVP_camellia_256_cfb128 +const EVP_CIPHER *EVP_camellia_256_ofb(void); +const EVP_CIPHER *EVP_camellia_256_ctr(void); +# endif +# ifndef OPENSSL_NO_CHACHA +const EVP_CIPHER *EVP_chacha20(void); +# ifndef OPENSSL_NO_POLY1305 +const EVP_CIPHER *EVP_chacha20_poly1305(void); +# endif +# endif + +# ifndef OPENSSL_NO_SEED +const EVP_CIPHER *EVP_seed_ecb(void); +const EVP_CIPHER *EVP_seed_cbc(void); +const EVP_CIPHER *EVP_seed_cfb128(void); +# define EVP_seed_cfb EVP_seed_cfb128 +const EVP_CIPHER *EVP_seed_ofb(void); +# endif + +# ifndef OPENSSL_NO_SM4 +const EVP_CIPHER *EVP_sm4_ecb(void); +const EVP_CIPHER *EVP_sm4_cbc(void); +const EVP_CIPHER *EVP_sm4_cfb128(void); +# define EVP_sm4_cfb EVP_sm4_cfb128 +const EVP_CIPHER *EVP_sm4_ofb(void); +const EVP_CIPHER *EVP_sm4_ctr(void); +# endif + +# if OPENSSL_API_COMPAT < 0x10100000L +# define OPENSSL_add_all_algorithms_conf() \ + OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \ + | OPENSSL_INIT_ADD_ALL_DIGESTS \ + | OPENSSL_INIT_LOAD_CONFIG, NULL) +# define OPENSSL_add_all_algorithms_noconf() \ + OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \ + | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL) + +# ifdef OPENSSL_LOAD_CONF +# define OpenSSL_add_all_algorithms() OPENSSL_add_all_algorithms_conf() +# else +# define OpenSSL_add_all_algorithms() OPENSSL_add_all_algorithms_noconf() +# endif + +# define OpenSSL_add_all_ciphers() \ + OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS, NULL) +# define OpenSSL_add_all_digests() \ + OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_DIGESTS, NULL) + +# define EVP_cleanup() while(0) continue +# endif + +int EVP_add_cipher(const EVP_CIPHER *cipher); +int EVP_add_digest(const EVP_MD *digest); + +const EVP_CIPHER *EVP_get_cipherbyname(const char *name); +const EVP_MD *EVP_get_digestbyname(const char *name); + +void EVP_CIPHER_do_all(void (*fn) (const EVP_CIPHER *ciph, + const char *from, const char *to, void *x), + void *arg); +void EVP_CIPHER_do_all_sorted(void (*fn) + (const EVP_CIPHER *ciph, const char *from, + const char *to, void *x), void *arg); + +void EVP_MD_do_all(void (*fn) (const EVP_MD *ciph, + const char *from, const char *to, void *x), + void *arg); +void EVP_MD_do_all_sorted(void (*fn) + (const EVP_MD *ciph, const char *from, + const char *to, void *x), void *arg); + +int EVP_PKEY_decrypt_old(unsigned char *dec_key, + const unsigned char *enc_key, int enc_key_len, + EVP_PKEY *private_key); +int EVP_PKEY_encrypt_old(unsigned char *enc_key, + const unsigned char *key, int key_len, + EVP_PKEY *pub_key); +int EVP_PKEY_type(int type); +int EVP_PKEY_id(const EVP_PKEY *pkey); +int EVP_PKEY_base_id(const EVP_PKEY *pkey); +int EVP_PKEY_bits(const EVP_PKEY *pkey); +int EVP_PKEY_security_bits(const EVP_PKEY *pkey); +int EVP_PKEY_size(const EVP_PKEY *pkey); +int EVP_PKEY_set_type(EVP_PKEY *pkey, int type); +int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len); +int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type); +# ifndef OPENSSL_NO_ENGINE +int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *e); +# endif +int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key); +void *EVP_PKEY_get0(const EVP_PKEY *pkey); +const unsigned char *EVP_PKEY_get0_hmac(const EVP_PKEY *pkey, size_t *len); +# ifndef OPENSSL_NO_POLY1305 +const unsigned char *EVP_PKEY_get0_poly1305(const EVP_PKEY *pkey, size_t *len); +# endif +# ifndef OPENSSL_NO_SIPHASH +const unsigned char *EVP_PKEY_get0_siphash(const EVP_PKEY *pkey, size_t *len); +# endif + +# ifndef OPENSSL_NO_RSA +struct rsa_st; +int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, struct rsa_st *key); +struct rsa_st *EVP_PKEY_get0_RSA(EVP_PKEY *pkey); +struct rsa_st *EVP_PKEY_get1_RSA(EVP_PKEY *pkey); +# endif +# ifndef OPENSSL_NO_DSA +struct dsa_st; +int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, struct dsa_st *key); +struct dsa_st *EVP_PKEY_get0_DSA(EVP_PKEY *pkey); +struct dsa_st *EVP_PKEY_get1_DSA(EVP_PKEY *pkey); +# endif +# ifndef OPENSSL_NO_DH +struct dh_st; +int EVP_PKEY_set1_DH(EVP_PKEY *pkey, struct dh_st *key); +struct dh_st *EVP_PKEY_get0_DH(EVP_PKEY *pkey); +struct dh_st *EVP_PKEY_get1_DH(EVP_PKEY *pkey); +# endif +# ifndef OPENSSL_NO_EC +struct ec_key_st; +int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, struct ec_key_st *key); +struct ec_key_st *EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey); +struct ec_key_st *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey); +# endif + +EVP_PKEY *EVP_PKEY_new(void); +int EVP_PKEY_up_ref(EVP_PKEY *pkey); +void EVP_PKEY_free(EVP_PKEY *pkey); + +EVP_PKEY *d2i_PublicKey(int type, EVP_PKEY **a, const unsigned char **pp, + long length); +int i2d_PublicKey(EVP_PKEY *a, unsigned char **pp); + +EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp, + long length); +EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp, + long length); +int i2d_PrivateKey(EVP_PKEY *a, unsigned char **pp); + +int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from); +int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey); +int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode); +int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b); + +int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b); + +int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey, + int indent, ASN1_PCTX *pctx); +int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey, + int indent, ASN1_PCTX *pctx); +int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, + int indent, ASN1_PCTX *pctx); + +int EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid); + +int EVP_PKEY_set1_tls_encodedpoint(EVP_PKEY *pkey, + const unsigned char *pt, size_t ptlen); +size_t EVP_PKEY_get1_tls_encodedpoint(EVP_PKEY *pkey, unsigned char **ppt); + +int EVP_CIPHER_type(const EVP_CIPHER *ctx); + +/* calls methods */ +int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type); +int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type); + +/* These are used by EVP_CIPHER methods */ +int EVP_CIPHER_set_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type); +int EVP_CIPHER_get_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type); + +/* PKCS5 password based encryption */ +int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, + ASN1_TYPE *param, const EVP_CIPHER *cipher, + const EVP_MD *md, int en_de); +int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, + const unsigned char *salt, int saltlen, int iter, + int keylen, unsigned char *out); +int PKCS5_PBKDF2_HMAC(const char *pass, int passlen, + const unsigned char *salt, int saltlen, int iter, + const EVP_MD *digest, int keylen, unsigned char *out); +int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, + ASN1_TYPE *param, const EVP_CIPHER *cipher, + const EVP_MD *md, int en_de); + +#ifndef OPENSSL_NO_SCRYPT +int EVP_PBE_scrypt(const char *pass, size_t passlen, + const unsigned char *salt, size_t saltlen, + uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem, + unsigned char *key, size_t keylen); + +int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, + int passlen, ASN1_TYPE *param, + const EVP_CIPHER *c, const EVP_MD *md, int en_de); +#endif + +void PKCS5_PBE_add(void); + +int EVP_PBE_CipherInit(ASN1_OBJECT *pbe_obj, const char *pass, int passlen, + ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de); + +/* PBE type */ + +/* Can appear as the outermost AlgorithmIdentifier */ +# define EVP_PBE_TYPE_OUTER 0x0 +/* Is an PRF type OID */ +# define EVP_PBE_TYPE_PRF 0x1 +/* Is a PKCS#5 v2.0 KDF */ +# define EVP_PBE_TYPE_KDF 0x2 + +int EVP_PBE_alg_add_type(int pbe_type, int pbe_nid, int cipher_nid, + int md_nid, EVP_PBE_KEYGEN *keygen); +int EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md, + EVP_PBE_KEYGEN *keygen); +int EVP_PBE_find(int type, int pbe_nid, int *pcnid, int *pmnid, + EVP_PBE_KEYGEN **pkeygen); +void EVP_PBE_cleanup(void); +int EVP_PBE_get(int *ptype, int *ppbe_nid, size_t num); + +# define ASN1_PKEY_ALIAS 0x1 +# define ASN1_PKEY_DYNAMIC 0x2 +# define ASN1_PKEY_SIGPARAM_NULL 0x4 + +# define ASN1_PKEY_CTRL_PKCS7_SIGN 0x1 +# define ASN1_PKEY_CTRL_PKCS7_ENCRYPT 0x2 +# define ASN1_PKEY_CTRL_DEFAULT_MD_NID 0x3 +# define ASN1_PKEY_CTRL_CMS_SIGN 0x5 +# define ASN1_PKEY_CTRL_CMS_ENVELOPE 0x7 +# define ASN1_PKEY_CTRL_CMS_RI_TYPE 0x8 + +# define ASN1_PKEY_CTRL_SET1_TLS_ENCPT 0x9 +# define ASN1_PKEY_CTRL_GET1_TLS_ENCPT 0xa + +int EVP_PKEY_asn1_get_count(void); +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx); +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pe, int type); +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe, + const char *str, int len); +int EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth); +int EVP_PKEY_asn1_add_alias(int to, int from); +int EVP_PKEY_asn1_get0_info(int *ppkey_id, int *pkey_base_id, + int *ppkey_flags, const char **pinfo, + const char **ppem_str, + const EVP_PKEY_ASN1_METHOD *ameth); + +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_get0_asn1(const EVP_PKEY *pkey); +EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_new(int id, int flags, + const char *pem_str, + const char *info); +void EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst, + const EVP_PKEY_ASN1_METHOD *src); +void EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth); +void EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth, + int (*pub_decode) (EVP_PKEY *pk, + X509_PUBKEY *pub), + int (*pub_encode) (X509_PUBKEY *pub, + const EVP_PKEY *pk), + int (*pub_cmp) (const EVP_PKEY *a, + const EVP_PKEY *b), + int (*pub_print) (BIO *out, + const EVP_PKEY *pkey, + int indent, ASN1_PCTX *pctx), + int (*pkey_size) (const EVP_PKEY *pk), + int (*pkey_bits) (const EVP_PKEY *pk)); +void EVP_PKEY_asn1_set_private(EVP_PKEY_ASN1_METHOD *ameth, + int (*priv_decode) (EVP_PKEY *pk, + const PKCS8_PRIV_KEY_INFO + *p8inf), + int (*priv_encode) (PKCS8_PRIV_KEY_INFO *p8, + const EVP_PKEY *pk), + int (*priv_print) (BIO *out, + const EVP_PKEY *pkey, + int indent, + ASN1_PCTX *pctx)); +void EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth, + int (*param_decode) (EVP_PKEY *pkey, + const unsigned char **pder, + int derlen), + int (*param_encode) (const EVP_PKEY *pkey, + unsigned char **pder), + int (*param_missing) (const EVP_PKEY *pk), + int (*param_copy) (EVP_PKEY *to, + const EVP_PKEY *from), + int (*param_cmp) (const EVP_PKEY *a, + const EVP_PKEY *b), + int (*param_print) (BIO *out, + const EVP_PKEY *pkey, + int indent, + ASN1_PCTX *pctx)); + +void EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth, + void (*pkey_free) (EVP_PKEY *pkey)); +void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth, + int (*pkey_ctrl) (EVP_PKEY *pkey, int op, + long arg1, void *arg2)); +void EVP_PKEY_asn1_set_item(EVP_PKEY_ASN1_METHOD *ameth, + int (*item_verify) (EVP_MD_CTX *ctx, + const ASN1_ITEM *it, + void *asn, + X509_ALGOR *a, + ASN1_BIT_STRING *sig, + EVP_PKEY *pkey), + int (*item_sign) (EVP_MD_CTX *ctx, + const ASN1_ITEM *it, + void *asn, + X509_ALGOR *alg1, + X509_ALGOR *alg2, + ASN1_BIT_STRING *sig)); + +void EVP_PKEY_asn1_set_siginf(EVP_PKEY_ASN1_METHOD *ameth, + int (*siginf_set) (X509_SIG_INFO *siginf, + const X509_ALGOR *alg, + const ASN1_STRING *sig)); + +void EVP_PKEY_asn1_set_check(EVP_PKEY_ASN1_METHOD *ameth, + int (*pkey_check) (const EVP_PKEY *pk)); + +void EVP_PKEY_asn1_set_public_check(EVP_PKEY_ASN1_METHOD *ameth, + int (*pkey_pub_check) (const EVP_PKEY *pk)); + +void EVP_PKEY_asn1_set_param_check(EVP_PKEY_ASN1_METHOD *ameth, + int (*pkey_param_check) (const EVP_PKEY *pk)); + +void EVP_PKEY_asn1_set_set_priv_key(EVP_PKEY_ASN1_METHOD *ameth, + int (*set_priv_key) (EVP_PKEY *pk, + const unsigned char + *priv, + size_t len)); +void EVP_PKEY_asn1_set_set_pub_key(EVP_PKEY_ASN1_METHOD *ameth, + int (*set_pub_key) (EVP_PKEY *pk, + const unsigned char *pub, + size_t len)); +void EVP_PKEY_asn1_set_get_priv_key(EVP_PKEY_ASN1_METHOD *ameth, + int (*get_priv_key) (const EVP_PKEY *pk, + unsigned char *priv, + size_t *len)); +void EVP_PKEY_asn1_set_get_pub_key(EVP_PKEY_ASN1_METHOD *ameth, + int (*get_pub_key) (const EVP_PKEY *pk, + unsigned char *pub, + size_t *len)); + +void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth, + int (*pkey_security_bits) (const EVP_PKEY + *pk)); + +# define EVP_PKEY_OP_UNDEFINED 0 +# define EVP_PKEY_OP_PARAMGEN (1<<1) +# define EVP_PKEY_OP_KEYGEN (1<<2) +# define EVP_PKEY_OP_SIGN (1<<3) +# define EVP_PKEY_OP_VERIFY (1<<4) +# define EVP_PKEY_OP_VERIFYRECOVER (1<<5) +# define EVP_PKEY_OP_SIGNCTX (1<<6) +# define EVP_PKEY_OP_VERIFYCTX (1<<7) +# define EVP_PKEY_OP_ENCRYPT (1<<8) +# define EVP_PKEY_OP_DECRYPT (1<<9) +# define EVP_PKEY_OP_DERIVE (1<<10) + +# define EVP_PKEY_OP_TYPE_SIG \ + (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY | EVP_PKEY_OP_VERIFYRECOVER \ + | EVP_PKEY_OP_SIGNCTX | EVP_PKEY_OP_VERIFYCTX) + +# define EVP_PKEY_OP_TYPE_CRYPT \ + (EVP_PKEY_OP_ENCRYPT | EVP_PKEY_OP_DECRYPT) + +# define EVP_PKEY_OP_TYPE_NOGEN \ + (EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT | EVP_PKEY_OP_DERIVE) + +# define EVP_PKEY_OP_TYPE_GEN \ + (EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN) + +# define EVP_PKEY_CTX_set_signature_md(ctx, md) \ + EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, \ + EVP_PKEY_CTRL_MD, 0, (void *)(md)) + +# define EVP_PKEY_CTX_get_signature_md(ctx, pmd) \ + EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, \ + EVP_PKEY_CTRL_GET_MD, 0, (void *)(pmd)) + +# define EVP_PKEY_CTX_set_mac_key(ctx, key, len) \ + EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_KEYGEN, \ + EVP_PKEY_CTRL_SET_MAC_KEY, len, (void *)(key)) + +# define EVP_PKEY_CTRL_MD 1 +# define EVP_PKEY_CTRL_PEER_KEY 2 + +# define EVP_PKEY_CTRL_PKCS7_ENCRYPT 3 +# define EVP_PKEY_CTRL_PKCS7_DECRYPT 4 + +# define EVP_PKEY_CTRL_PKCS7_SIGN 5 + +# define EVP_PKEY_CTRL_SET_MAC_KEY 6 + +# define EVP_PKEY_CTRL_DIGESTINIT 7 + +/* Used by GOST key encryption in TLS */ +# define EVP_PKEY_CTRL_SET_IV 8 + +# define EVP_PKEY_CTRL_CMS_ENCRYPT 9 +# define EVP_PKEY_CTRL_CMS_DECRYPT 10 +# define EVP_PKEY_CTRL_CMS_SIGN 11 + +# define EVP_PKEY_CTRL_CIPHER 12 + +# define EVP_PKEY_CTRL_GET_MD 13 + +# define EVP_PKEY_CTRL_SET_DIGEST_SIZE 14 + +# define EVP_PKEY_ALG_CTRL 0x1000 + +# define EVP_PKEY_FLAG_AUTOARGLEN 2 +/* + * Method handles all operations: don't assume any digest related defaults. + */ +# define EVP_PKEY_FLAG_SIGCTX_CUSTOM 4 + +const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type); +EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags); +void EVP_PKEY_meth_get0_info(int *ppkey_id, int *pflags, + const EVP_PKEY_METHOD *meth); +void EVP_PKEY_meth_copy(EVP_PKEY_METHOD *dst, const EVP_PKEY_METHOD *src); +void EVP_PKEY_meth_free(EVP_PKEY_METHOD *pmeth); +int EVP_PKEY_meth_add0(const EVP_PKEY_METHOD *pmeth); +int EVP_PKEY_meth_remove(const EVP_PKEY_METHOD *pmeth); +size_t EVP_PKEY_meth_get_count(void); +const EVP_PKEY_METHOD *EVP_PKEY_meth_get0(size_t idx); + +EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e); +EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e); +EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *ctx); +void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx); + +int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, + int cmd, int p1, void *p2); +int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, + const char *value); +int EVP_PKEY_CTX_ctrl_uint64(EVP_PKEY_CTX *ctx, int keytype, int optype, + int cmd, uint64_t value); + +int EVP_PKEY_CTX_str2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *str); +int EVP_PKEY_CTX_hex2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *hex); + +int EVP_PKEY_CTX_md(EVP_PKEY_CTX *ctx, int optype, int cmd, const char *md); + +int EVP_PKEY_CTX_get_operation(EVP_PKEY_CTX *ctx); +void EVP_PKEY_CTX_set0_keygen_info(EVP_PKEY_CTX *ctx, int *dat, int datlen); + +EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e, + const unsigned char *key, int keylen); +EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e, + const unsigned char *priv, + size_t len); +EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *e, + const unsigned char *pub, + size_t len); +int EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey, unsigned char *priv, + size_t *len); +int EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, unsigned char *pub, + size_t *len); + +EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv, + size_t len, const EVP_CIPHER *cipher); + +void EVP_PKEY_CTX_set_data(EVP_PKEY_CTX *ctx, void *data); +void *EVP_PKEY_CTX_get_data(EVP_PKEY_CTX *ctx); +EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx); + +EVP_PKEY *EVP_PKEY_CTX_get0_peerkey(EVP_PKEY_CTX *ctx); + +void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data); +void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx); + +int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_sign(EVP_PKEY_CTX *ctx, + unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbslen); +int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_verify(EVP_PKEY_CTX *ctx, + const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen); +int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx, + unsigned char *rout, size_t *routlen, + const unsigned char *sig, size_t siglen); +int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen); +int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen); + +int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer); +int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen); + +typedef int EVP_PKEY_gen_cb(EVP_PKEY_CTX *ctx); + +int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey); +int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey); +int EVP_PKEY_check(EVP_PKEY_CTX *ctx); +int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx); +int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx); + +void EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb); +EVP_PKEY_gen_cb *EVP_PKEY_CTX_get_cb(EVP_PKEY_CTX *ctx); + +int EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx); + +void EVP_PKEY_meth_set_init(EVP_PKEY_METHOD *pmeth, + int (*init) (EVP_PKEY_CTX *ctx)); + +void EVP_PKEY_meth_set_copy(EVP_PKEY_METHOD *pmeth, + int (*copy) (EVP_PKEY_CTX *dst, + EVP_PKEY_CTX *src)); + +void EVP_PKEY_meth_set_cleanup(EVP_PKEY_METHOD *pmeth, + void (*cleanup) (EVP_PKEY_CTX *ctx)); + +void EVP_PKEY_meth_set_paramgen(EVP_PKEY_METHOD *pmeth, + int (*paramgen_init) (EVP_PKEY_CTX *ctx), + int (*paramgen) (EVP_PKEY_CTX *ctx, + EVP_PKEY *pkey)); + +void EVP_PKEY_meth_set_keygen(EVP_PKEY_METHOD *pmeth, + int (*keygen_init) (EVP_PKEY_CTX *ctx), + int (*keygen) (EVP_PKEY_CTX *ctx, + EVP_PKEY *pkey)); + +void EVP_PKEY_meth_set_sign(EVP_PKEY_METHOD *pmeth, + int (*sign_init) (EVP_PKEY_CTX *ctx), + int (*sign) (EVP_PKEY_CTX *ctx, + unsigned char *sig, size_t *siglen, + const unsigned char *tbs, + size_t tbslen)); + +void EVP_PKEY_meth_set_verify(EVP_PKEY_METHOD *pmeth, + int (*verify_init) (EVP_PKEY_CTX *ctx), + int (*verify) (EVP_PKEY_CTX *ctx, + const unsigned char *sig, + size_t siglen, + const unsigned char *tbs, + size_t tbslen)); + +void EVP_PKEY_meth_set_verify_recover(EVP_PKEY_METHOD *pmeth, + int (*verify_recover_init) (EVP_PKEY_CTX + *ctx), + int (*verify_recover) (EVP_PKEY_CTX + *ctx, + unsigned char + *sig, + size_t *siglen, + const unsigned + char *tbs, + size_t tbslen)); + +void EVP_PKEY_meth_set_signctx(EVP_PKEY_METHOD *pmeth, + int (*signctx_init) (EVP_PKEY_CTX *ctx, + EVP_MD_CTX *mctx), + int (*signctx) (EVP_PKEY_CTX *ctx, + unsigned char *sig, + size_t *siglen, + EVP_MD_CTX *mctx)); + +void EVP_PKEY_meth_set_verifyctx(EVP_PKEY_METHOD *pmeth, + int (*verifyctx_init) (EVP_PKEY_CTX *ctx, + EVP_MD_CTX *mctx), + int (*verifyctx) (EVP_PKEY_CTX *ctx, + const unsigned char *sig, + int siglen, + EVP_MD_CTX *mctx)); + +void EVP_PKEY_meth_set_encrypt(EVP_PKEY_METHOD *pmeth, + int (*encrypt_init) (EVP_PKEY_CTX *ctx), + int (*encryptfn) (EVP_PKEY_CTX *ctx, + unsigned char *out, + size_t *outlen, + const unsigned char *in, + size_t inlen)); + +void EVP_PKEY_meth_set_decrypt(EVP_PKEY_METHOD *pmeth, + int (*decrypt_init) (EVP_PKEY_CTX *ctx), + int (*decrypt) (EVP_PKEY_CTX *ctx, + unsigned char *out, + size_t *outlen, + const unsigned char *in, + size_t inlen)); + +void EVP_PKEY_meth_set_derive(EVP_PKEY_METHOD *pmeth, + int (*derive_init) (EVP_PKEY_CTX *ctx), + int (*derive) (EVP_PKEY_CTX *ctx, + unsigned char *key, + size_t *keylen)); + +void EVP_PKEY_meth_set_ctrl(EVP_PKEY_METHOD *pmeth, + int (*ctrl) (EVP_PKEY_CTX *ctx, int type, int p1, + void *p2), + int (*ctrl_str) (EVP_PKEY_CTX *ctx, + const char *type, + const char *value)); + +void EVP_PKEY_meth_set_check(EVP_PKEY_METHOD *pmeth, + int (*check) (EVP_PKEY *pkey)); + +void EVP_PKEY_meth_set_public_check(EVP_PKEY_METHOD *pmeth, + int (*check) (EVP_PKEY *pkey)); + +void EVP_PKEY_meth_set_param_check(EVP_PKEY_METHOD *pmeth, + int (*check) (EVP_PKEY *pkey)); + +void EVP_PKEY_meth_set_digest_custom(EVP_PKEY_METHOD *pmeth, + int (*digest_custom) (EVP_PKEY_CTX *ctx, + EVP_MD_CTX *mctx)); + +void EVP_PKEY_meth_get_init(const EVP_PKEY_METHOD *pmeth, + int (**pinit) (EVP_PKEY_CTX *ctx)); + +void EVP_PKEY_meth_get_copy(const EVP_PKEY_METHOD *pmeth, + int (**pcopy) (EVP_PKEY_CTX *dst, + EVP_PKEY_CTX *src)); + +void EVP_PKEY_meth_get_cleanup(const EVP_PKEY_METHOD *pmeth, + void (**pcleanup) (EVP_PKEY_CTX *ctx)); + +void EVP_PKEY_meth_get_paramgen(const EVP_PKEY_METHOD *pmeth, + int (**pparamgen_init) (EVP_PKEY_CTX *ctx), + int (**pparamgen) (EVP_PKEY_CTX *ctx, + EVP_PKEY *pkey)); + +void EVP_PKEY_meth_get_keygen(const EVP_PKEY_METHOD *pmeth, + int (**pkeygen_init) (EVP_PKEY_CTX *ctx), + int (**pkeygen) (EVP_PKEY_CTX *ctx, + EVP_PKEY *pkey)); + +void EVP_PKEY_meth_get_sign(const EVP_PKEY_METHOD *pmeth, + int (**psign_init) (EVP_PKEY_CTX *ctx), + int (**psign) (EVP_PKEY_CTX *ctx, + unsigned char *sig, size_t *siglen, + const unsigned char *tbs, + size_t tbslen)); + +void EVP_PKEY_meth_get_verify(const EVP_PKEY_METHOD *pmeth, + int (**pverify_init) (EVP_PKEY_CTX *ctx), + int (**pverify) (EVP_PKEY_CTX *ctx, + const unsigned char *sig, + size_t siglen, + const unsigned char *tbs, + size_t tbslen)); + +void EVP_PKEY_meth_get_verify_recover(const EVP_PKEY_METHOD *pmeth, + int (**pverify_recover_init) (EVP_PKEY_CTX + *ctx), + int (**pverify_recover) (EVP_PKEY_CTX + *ctx, + unsigned char + *sig, + size_t *siglen, + const unsigned + char *tbs, + size_t tbslen)); + +void EVP_PKEY_meth_get_signctx(const EVP_PKEY_METHOD *pmeth, + int (**psignctx_init) (EVP_PKEY_CTX *ctx, + EVP_MD_CTX *mctx), + int (**psignctx) (EVP_PKEY_CTX *ctx, + unsigned char *sig, + size_t *siglen, + EVP_MD_CTX *mctx)); + +void EVP_PKEY_meth_get_verifyctx(const EVP_PKEY_METHOD *pmeth, + int (**pverifyctx_init) (EVP_PKEY_CTX *ctx, + EVP_MD_CTX *mctx), + int (**pverifyctx) (EVP_PKEY_CTX *ctx, + const unsigned char *sig, + int siglen, + EVP_MD_CTX *mctx)); + +void EVP_PKEY_meth_get_encrypt(const EVP_PKEY_METHOD *pmeth, + int (**pencrypt_init) (EVP_PKEY_CTX *ctx), + int (**pencryptfn) (EVP_PKEY_CTX *ctx, + unsigned char *out, + size_t *outlen, + const unsigned char *in, + size_t inlen)); + +void EVP_PKEY_meth_get_decrypt(const EVP_PKEY_METHOD *pmeth, + int (**pdecrypt_init) (EVP_PKEY_CTX *ctx), + int (**pdecrypt) (EVP_PKEY_CTX *ctx, + unsigned char *out, + size_t *outlen, + const unsigned char *in, + size_t inlen)); + +void EVP_PKEY_meth_get_derive(const EVP_PKEY_METHOD *pmeth, + int (**pderive_init) (EVP_PKEY_CTX *ctx), + int (**pderive) (EVP_PKEY_CTX *ctx, + unsigned char *key, + size_t *keylen)); + +void EVP_PKEY_meth_get_ctrl(const EVP_PKEY_METHOD *pmeth, + int (**pctrl) (EVP_PKEY_CTX *ctx, int type, int p1, + void *p2), + int (**pctrl_str) (EVP_PKEY_CTX *ctx, + const char *type, + const char *value)); + +void EVP_PKEY_meth_get_check(const EVP_PKEY_METHOD *pmeth, + int (**pcheck) (EVP_PKEY *pkey)); + +void EVP_PKEY_meth_get_public_check(const EVP_PKEY_METHOD *pmeth, + int (**pcheck) (EVP_PKEY *pkey)); + +void EVP_PKEY_meth_get_param_check(const EVP_PKEY_METHOD *pmeth, + int (**pcheck) (EVP_PKEY *pkey)); + +void EVP_PKEY_meth_get_digest_custom(EVP_PKEY_METHOD *pmeth, + int (**pdigest_custom) (EVP_PKEY_CTX *ctx, + EVP_MD_CTX *mctx)); +void EVP_add_alg_module(void); + + +# ifdef __cplusplus +} +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/evperr.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/evperr.h new file mode 100644 index 000000000..84f03eb3c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/evperr.h @@ -0,0 +1,194 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_EVPERR_H +# define HEADER_EVPERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_EVP_strings(void); + +/* + * EVP function codes. + */ +# define EVP_F_AESNI_INIT_KEY 165 +# define EVP_F_AES_GCM_CTRL 196 +# define EVP_F_AES_INIT_KEY 133 +# define EVP_F_AES_OCB_CIPHER 169 +# define EVP_F_AES_T4_INIT_KEY 178 +# define EVP_F_AES_WRAP_CIPHER 170 +# define EVP_F_ALG_MODULE_INIT 177 +# define EVP_F_ARIA_CCM_INIT_KEY 175 +# define EVP_F_ARIA_GCM_CTRL 197 +# define EVP_F_ARIA_GCM_INIT_KEY 176 +# define EVP_F_ARIA_INIT_KEY 185 +# define EVP_F_B64_NEW 198 +# define EVP_F_CAMELLIA_INIT_KEY 159 +# define EVP_F_CHACHA20_POLY1305_CTRL 182 +# define EVP_F_CMLL_T4_INIT_KEY 179 +# define EVP_F_DES_EDE3_WRAP_CIPHER 171 +# define EVP_F_DO_SIGVER_INIT 161 +# define EVP_F_ENC_NEW 199 +# define EVP_F_EVP_CIPHERINIT_EX 123 +# define EVP_F_EVP_CIPHER_ASN1_TO_PARAM 204 +# define EVP_F_EVP_CIPHER_CTX_COPY 163 +# define EVP_F_EVP_CIPHER_CTX_CTRL 124 +# define EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH 122 +# define EVP_F_EVP_CIPHER_PARAM_TO_ASN1 205 +# define EVP_F_EVP_DECRYPTFINAL_EX 101 +# define EVP_F_EVP_DECRYPTUPDATE 166 +# define EVP_F_EVP_DIGESTFINALXOF 174 +# define EVP_F_EVP_DIGESTINIT_EX 128 +# define EVP_F_EVP_ENCRYPTDECRYPTUPDATE 219 +# define EVP_F_EVP_ENCRYPTFINAL_EX 127 +# define EVP_F_EVP_ENCRYPTUPDATE 167 +# define EVP_F_EVP_MD_CTX_COPY_EX 110 +# define EVP_F_EVP_MD_SIZE 162 +# define EVP_F_EVP_OPENINIT 102 +# define EVP_F_EVP_PBE_ALG_ADD 115 +# define EVP_F_EVP_PBE_ALG_ADD_TYPE 160 +# define EVP_F_EVP_PBE_CIPHERINIT 116 +# define EVP_F_EVP_PBE_SCRYPT 181 +# define EVP_F_EVP_PKCS82PKEY 111 +# define EVP_F_EVP_PKEY2PKCS8 113 +# define EVP_F_EVP_PKEY_ASN1_ADD0 188 +# define EVP_F_EVP_PKEY_CHECK 186 +# define EVP_F_EVP_PKEY_COPY_PARAMETERS 103 +# define EVP_F_EVP_PKEY_CTX_CTRL 137 +# define EVP_F_EVP_PKEY_CTX_CTRL_STR 150 +# define EVP_F_EVP_PKEY_CTX_DUP 156 +# define EVP_F_EVP_PKEY_CTX_MD 168 +# define EVP_F_EVP_PKEY_DECRYPT 104 +# define EVP_F_EVP_PKEY_DECRYPT_INIT 138 +# define EVP_F_EVP_PKEY_DECRYPT_OLD 151 +# define EVP_F_EVP_PKEY_DERIVE 153 +# define EVP_F_EVP_PKEY_DERIVE_INIT 154 +# define EVP_F_EVP_PKEY_DERIVE_SET_PEER 155 +# define EVP_F_EVP_PKEY_ENCRYPT 105 +# define EVP_F_EVP_PKEY_ENCRYPT_INIT 139 +# define EVP_F_EVP_PKEY_ENCRYPT_OLD 152 +# define EVP_F_EVP_PKEY_GET0_DH 119 +# define EVP_F_EVP_PKEY_GET0_DSA 120 +# define EVP_F_EVP_PKEY_GET0_EC_KEY 131 +# define EVP_F_EVP_PKEY_GET0_HMAC 183 +# define EVP_F_EVP_PKEY_GET0_POLY1305 184 +# define EVP_F_EVP_PKEY_GET0_RSA 121 +# define EVP_F_EVP_PKEY_GET0_SIPHASH 172 +# define EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY 202 +# define EVP_F_EVP_PKEY_GET_RAW_PUBLIC_KEY 203 +# define EVP_F_EVP_PKEY_KEYGEN 146 +# define EVP_F_EVP_PKEY_KEYGEN_INIT 147 +# define EVP_F_EVP_PKEY_METH_ADD0 194 +# define EVP_F_EVP_PKEY_METH_NEW 195 +# define EVP_F_EVP_PKEY_NEW 106 +# define EVP_F_EVP_PKEY_NEW_CMAC_KEY 193 +# define EVP_F_EVP_PKEY_NEW_RAW_PRIVATE_KEY 191 +# define EVP_F_EVP_PKEY_NEW_RAW_PUBLIC_KEY 192 +# define EVP_F_EVP_PKEY_PARAMGEN 148 +# define EVP_F_EVP_PKEY_PARAMGEN_INIT 149 +# define EVP_F_EVP_PKEY_PARAM_CHECK 189 +# define EVP_F_EVP_PKEY_PUBLIC_CHECK 190 +# define EVP_F_EVP_PKEY_SET1_ENGINE 187 +# define EVP_F_EVP_PKEY_SET_ALIAS_TYPE 206 +# define EVP_F_EVP_PKEY_SIGN 140 +# define EVP_F_EVP_PKEY_SIGN_INIT 141 +# define EVP_F_EVP_PKEY_VERIFY 142 +# define EVP_F_EVP_PKEY_VERIFY_INIT 143 +# define EVP_F_EVP_PKEY_VERIFY_RECOVER 144 +# define EVP_F_EVP_PKEY_VERIFY_RECOVER_INIT 145 +# define EVP_F_EVP_SIGNFINAL 107 +# define EVP_F_EVP_VERIFYFINAL 108 +# define EVP_F_INT_CTX_NEW 157 +# define EVP_F_OK_NEW 200 +# define EVP_F_PKCS5_PBE_KEYIVGEN 117 +# define EVP_F_PKCS5_V2_PBE_KEYIVGEN 118 +# define EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN 164 +# define EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN 180 +# define EVP_F_PKEY_SET_TYPE 158 +# define EVP_F_RC2_MAGIC_TO_METH 109 +# define EVP_F_RC5_CTRL 125 +# define EVP_F_S390X_AES_GCM_CTRL 201 +# define EVP_F_UPDATE 173 + +/* + * EVP reason codes. + */ +# define EVP_R_AES_KEY_SETUP_FAILED 143 +# define EVP_R_ARIA_KEY_SETUP_FAILED 176 +# define EVP_R_BAD_DECRYPT 100 +# define EVP_R_BUFFER_TOO_SMALL 155 +# define EVP_R_CAMELLIA_KEY_SETUP_FAILED 157 +# define EVP_R_CIPHER_PARAMETER_ERROR 122 +# define EVP_R_COMMAND_NOT_SUPPORTED 147 +# define EVP_R_COPY_ERROR 173 +# define EVP_R_CTRL_NOT_IMPLEMENTED 132 +# define EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED 133 +# define EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH 138 +# define EVP_R_DECODE_ERROR 114 +# define EVP_R_DIFFERENT_KEY_TYPES 101 +# define EVP_R_DIFFERENT_PARAMETERS 153 +# define EVP_R_ERROR_LOADING_SECTION 165 +# define EVP_R_ERROR_SETTING_FIPS_MODE 166 +# define EVP_R_EXPECTING_AN_HMAC_KEY 174 +# define EVP_R_EXPECTING_AN_RSA_KEY 127 +# define EVP_R_EXPECTING_A_DH_KEY 128 +# define EVP_R_EXPECTING_A_DSA_KEY 129 +# define EVP_R_EXPECTING_A_EC_KEY 142 +# define EVP_R_EXPECTING_A_POLY1305_KEY 164 +# define EVP_R_EXPECTING_A_SIPHASH_KEY 175 +# define EVP_R_FIPS_MODE_NOT_SUPPORTED 167 +# define EVP_R_GET_RAW_KEY_FAILED 182 +# define EVP_R_ILLEGAL_SCRYPT_PARAMETERS 171 +# define EVP_R_INITIALIZATION_ERROR 134 +# define EVP_R_INPUT_NOT_INITIALIZED 111 +# define EVP_R_INVALID_DIGEST 152 +# define EVP_R_INVALID_FIPS_MODE 168 +# define EVP_R_INVALID_KEY 163 +# define EVP_R_INVALID_KEY_LENGTH 130 +# define EVP_R_INVALID_OPERATION 148 +# define EVP_R_KEYGEN_FAILURE 120 +# define EVP_R_KEY_SETUP_FAILED 180 +# define EVP_R_MEMORY_LIMIT_EXCEEDED 172 +# define EVP_R_MESSAGE_DIGEST_IS_NULL 159 +# define EVP_R_METHOD_NOT_SUPPORTED 144 +# define EVP_R_MISSING_PARAMETERS 103 +# define EVP_R_NOT_XOF_OR_INVALID_LENGTH 178 +# define EVP_R_NO_CIPHER_SET 131 +# define EVP_R_NO_DEFAULT_DIGEST 158 +# define EVP_R_NO_DIGEST_SET 139 +# define EVP_R_NO_KEY_SET 154 +# define EVP_R_NO_OPERATION_SET 149 +# define EVP_R_ONLY_ONESHOT_SUPPORTED 177 +# define EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE 150 +# define EVP_R_OPERATON_NOT_INITIALIZED 151 +# define EVP_R_PARTIALLY_OVERLAPPING 162 +# define EVP_R_PBKDF2_ERROR 181 +# define EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED 179 +# define EVP_R_PRIVATE_KEY_DECODE_ERROR 145 +# define EVP_R_PRIVATE_KEY_ENCODE_ERROR 146 +# define EVP_R_PUBLIC_KEY_NOT_RSA 106 +# define EVP_R_UNKNOWN_CIPHER 160 +# define EVP_R_UNKNOWN_DIGEST 161 +# define EVP_R_UNKNOWN_OPTION 169 +# define EVP_R_UNKNOWN_PBE_ALGORITHM 121 +# define EVP_R_UNSUPPORTED_ALGORITHM 156 +# define EVP_R_UNSUPPORTED_CIPHER 107 +# define EVP_R_UNSUPPORTED_KEYLENGTH 123 +# define EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION 124 +# define EVP_R_UNSUPPORTED_KEY_SIZE 108 +# define EVP_R_UNSUPPORTED_NUMBER_OF_ROUNDS 135 +# define EVP_R_UNSUPPORTED_PRF 125 +# define EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM 118 +# define EVP_R_UNSUPPORTED_SALT_TYPE 126 +# define EVP_R_WRAP_MODE_NOT_ALLOWED 170 +# define EVP_R_WRONG_FINAL_BLOCK_LENGTH 109 + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/hmac.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/hmac.h new file mode 100644 index 000000000..458efc1d5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/hmac.h @@ -0,0 +1,51 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_HMAC_H +# define HEADER_HMAC_H + +# include + +# include + +# if OPENSSL_API_COMPAT < 0x10200000L +# define HMAC_MAX_MD_CBLOCK 128 /* Deprecated */ +# endif + +#ifdef __cplusplus +extern "C" { +#endif + +size_t HMAC_size(const HMAC_CTX *e); +HMAC_CTX *HMAC_CTX_new(void); +int HMAC_CTX_reset(HMAC_CTX *ctx); +void HMAC_CTX_free(HMAC_CTX *ctx); + +DEPRECATEDIN_1_1_0(__owur int HMAC_Init(HMAC_CTX *ctx, const void *key, int len, + const EVP_MD *md)) + +/*__owur*/ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, + const EVP_MD *md, ENGINE *impl); +/*__owur*/ int HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, + size_t len); +/*__owur*/ int HMAC_Final(HMAC_CTX *ctx, unsigned char *md, + unsigned int *len); +unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len, + const unsigned char *d, size_t n, unsigned char *md, + unsigned int *md_len); +__owur int HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx); + +void HMAC_CTX_set_flags(HMAC_CTX *ctx, unsigned long flags); +const EVP_MD *HMAC_CTX_get_md(const HMAC_CTX *ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/idea.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/idea.h new file mode 100644 index 000000000..4334f3ea7 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/idea.h @@ -0,0 +1,64 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_IDEA_H +# define HEADER_IDEA_H + +# include + +# ifndef OPENSSL_NO_IDEA +# ifdef __cplusplus +extern "C" { +# endif + +typedef unsigned int IDEA_INT; + +# define IDEA_ENCRYPT 1 +# define IDEA_DECRYPT 0 + +# define IDEA_BLOCK 8 +# define IDEA_KEY_LENGTH 16 + +typedef struct idea_key_st { + IDEA_INT data[9][6]; +} IDEA_KEY_SCHEDULE; + +const char *IDEA_options(void); +void IDEA_ecb_encrypt(const unsigned char *in, unsigned char *out, + IDEA_KEY_SCHEDULE *ks); +void IDEA_set_encrypt_key(const unsigned char *key, IDEA_KEY_SCHEDULE *ks); +void IDEA_set_decrypt_key(IDEA_KEY_SCHEDULE *ek, IDEA_KEY_SCHEDULE *dk); +void IDEA_cbc_encrypt(const unsigned char *in, unsigned char *out, + long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv, + int enc); +void IDEA_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv, + int *num, int enc); +void IDEA_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv, + int *num); +void IDEA_encrypt(unsigned long *in, IDEA_KEY_SCHEDULE *ks); + +# if OPENSSL_API_COMPAT < 0x10100000L +# define idea_options IDEA_options +# define idea_ecb_encrypt IDEA_ecb_encrypt +# define idea_set_encrypt_key IDEA_set_encrypt_key +# define idea_set_decrypt_key IDEA_set_decrypt_key +# define idea_cbc_encrypt IDEA_cbc_encrypt +# define idea_cfb64_encrypt IDEA_cfb64_encrypt +# define idea_ofb64_encrypt IDEA_ofb64_encrypt +# define idea_encrypt IDEA_encrypt +# endif + +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/kdf.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/kdf.h new file mode 100644 index 000000000..5abd4c371 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/kdf.h @@ -0,0 +1,97 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_KDF_H +# define HEADER_KDF_H + +# include +#ifdef __cplusplus +extern "C" { +#endif + +# define EVP_PKEY_CTRL_TLS_MD (EVP_PKEY_ALG_CTRL) +# define EVP_PKEY_CTRL_TLS_SECRET (EVP_PKEY_ALG_CTRL + 1) +# define EVP_PKEY_CTRL_TLS_SEED (EVP_PKEY_ALG_CTRL + 2) +# define EVP_PKEY_CTRL_HKDF_MD (EVP_PKEY_ALG_CTRL + 3) +# define EVP_PKEY_CTRL_HKDF_SALT (EVP_PKEY_ALG_CTRL + 4) +# define EVP_PKEY_CTRL_HKDF_KEY (EVP_PKEY_ALG_CTRL + 5) +# define EVP_PKEY_CTRL_HKDF_INFO (EVP_PKEY_ALG_CTRL + 6) +# define EVP_PKEY_CTRL_HKDF_MODE (EVP_PKEY_ALG_CTRL + 7) +# define EVP_PKEY_CTRL_PASS (EVP_PKEY_ALG_CTRL + 8) +# define EVP_PKEY_CTRL_SCRYPT_SALT (EVP_PKEY_ALG_CTRL + 9) +# define EVP_PKEY_CTRL_SCRYPT_N (EVP_PKEY_ALG_CTRL + 10) +# define EVP_PKEY_CTRL_SCRYPT_R (EVP_PKEY_ALG_CTRL + 11) +# define EVP_PKEY_CTRL_SCRYPT_P (EVP_PKEY_ALG_CTRL + 12) +# define EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES (EVP_PKEY_ALG_CTRL + 13) + +# define EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND 0 +# define EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY 1 +# define EVP_PKEY_HKDEF_MODE_EXPAND_ONLY 2 + +# define EVP_PKEY_CTX_set_tls1_prf_md(pctx, md) \ + EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_TLS_MD, 0, (void *)(md)) + +# define EVP_PKEY_CTX_set1_tls1_prf_secret(pctx, sec, seclen) \ + EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_TLS_SECRET, seclen, (void *)(sec)) + +# define EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed, seedlen) \ + EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_TLS_SEED, seedlen, (void *)(seed)) + +# define EVP_PKEY_CTX_set_hkdf_md(pctx, md) \ + EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_HKDF_MD, 0, (void *)(md)) + +# define EVP_PKEY_CTX_set1_hkdf_salt(pctx, salt, saltlen) \ + EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_HKDF_SALT, saltlen, (void *)(salt)) + +# define EVP_PKEY_CTX_set1_hkdf_key(pctx, key, keylen) \ + EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_HKDF_KEY, keylen, (void *)(key)) + +# define EVP_PKEY_CTX_add1_hkdf_info(pctx, info, infolen) \ + EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_HKDF_INFO, infolen, (void *)(info)) + +# define EVP_PKEY_CTX_hkdf_mode(pctx, mode) \ + EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_HKDF_MODE, mode, NULL) + +# define EVP_PKEY_CTX_set1_pbe_pass(pctx, pass, passlen) \ + EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_PASS, passlen, (void *)(pass)) + +# define EVP_PKEY_CTX_set1_scrypt_salt(pctx, salt, saltlen) \ + EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_SCRYPT_SALT, saltlen, (void *)(salt)) + +# define EVP_PKEY_CTX_set_scrypt_N(pctx, n) \ + EVP_PKEY_CTX_ctrl_uint64(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_SCRYPT_N, n) + +# define EVP_PKEY_CTX_set_scrypt_r(pctx, r) \ + EVP_PKEY_CTX_ctrl_uint64(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_SCRYPT_R, r) + +# define EVP_PKEY_CTX_set_scrypt_p(pctx, p) \ + EVP_PKEY_CTX_ctrl_uint64(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_SCRYPT_P, p) + +# define EVP_PKEY_CTX_set_scrypt_maxmem_bytes(pctx, maxmem_bytes) \ + EVP_PKEY_CTX_ctrl_uint64(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES, maxmem_bytes) + + +# ifdef __cplusplus +} +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/kdferr.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/kdferr.h new file mode 100644 index 000000000..6437c271d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/kdferr.h @@ -0,0 +1,51 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_KDFERR_H +# define HEADER_KDFERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_KDF_strings(void); + +/* + * KDF function codes. + */ +# define KDF_F_PKEY_HKDF_CTRL_STR 103 +# define KDF_F_PKEY_HKDF_DERIVE 102 +# define KDF_F_PKEY_HKDF_INIT 108 +# define KDF_F_PKEY_SCRYPT_CTRL_STR 104 +# define KDF_F_PKEY_SCRYPT_CTRL_UINT64 105 +# define KDF_F_PKEY_SCRYPT_DERIVE 109 +# define KDF_F_PKEY_SCRYPT_INIT 106 +# define KDF_F_PKEY_SCRYPT_SET_MEMBUF 107 +# define KDF_F_PKEY_TLS1_PRF_CTRL_STR 100 +# define KDF_F_PKEY_TLS1_PRF_DERIVE 101 +# define KDF_F_PKEY_TLS1_PRF_INIT 110 +# define KDF_F_TLS1_PRF_ALG 111 + +/* + * KDF reason codes. + */ +# define KDF_R_INVALID_DIGEST 100 +# define KDF_R_MISSING_ITERATION_COUNT 109 +# define KDF_R_MISSING_KEY 104 +# define KDF_R_MISSING_MESSAGE_DIGEST 105 +# define KDF_R_MISSING_PARAMETER 101 +# define KDF_R_MISSING_PASS 110 +# define KDF_R_MISSING_SALT 111 +# define KDF_R_MISSING_SECRET 107 +# define KDF_R_MISSING_SEED 106 +# define KDF_R_UNKNOWN_PARAMETER_TYPE 103 +# define KDF_R_VALUE_ERROR 108 +# define KDF_R_VALUE_MISSING 102 + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/lhash.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/lhash.h new file mode 100644 index 000000000..47b99d17f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/lhash.h @@ -0,0 +1,242 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Header for dynamic hash table routines Author - Eric Young + */ + +#ifndef HEADER_LHASH_H +# define HEADER_LHASH_H + +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct lhash_node_st OPENSSL_LH_NODE; +typedef int (*OPENSSL_LH_COMPFUNC) (const void *, const void *); +typedef unsigned long (*OPENSSL_LH_HASHFUNC) (const void *); +typedef void (*OPENSSL_LH_DOALL_FUNC) (void *); +typedef void (*OPENSSL_LH_DOALL_FUNCARG) (void *, void *); +typedef struct lhash_st OPENSSL_LHASH; + +/* + * Macros for declaring and implementing type-safe wrappers for LHASH + * callbacks. This way, callbacks can be provided to LHASH structures without + * function pointer casting and the macro-defined callbacks provide + * per-variable casting before deferring to the underlying type-specific + * callbacks. NB: It is possible to place a "static" in front of both the + * DECLARE and IMPLEMENT macros if the functions are strictly internal. + */ + +/* First: "hash" functions */ +# define DECLARE_LHASH_HASH_FN(name, o_type) \ + unsigned long name##_LHASH_HASH(const void *); +# define IMPLEMENT_LHASH_HASH_FN(name, o_type) \ + unsigned long name##_LHASH_HASH(const void *arg) { \ + const o_type *a = arg; \ + return name##_hash(a); } +# define LHASH_HASH_FN(name) name##_LHASH_HASH + +/* Second: "compare" functions */ +# define DECLARE_LHASH_COMP_FN(name, o_type) \ + int name##_LHASH_COMP(const void *, const void *); +# define IMPLEMENT_LHASH_COMP_FN(name, o_type) \ + int name##_LHASH_COMP(const void *arg1, const void *arg2) { \ + const o_type *a = arg1; \ + const o_type *b = arg2; \ + return name##_cmp(a,b); } +# define LHASH_COMP_FN(name) name##_LHASH_COMP + +/* Fourth: "doall_arg" functions */ +# define DECLARE_LHASH_DOALL_ARG_FN(name, o_type, a_type) \ + void name##_LHASH_DOALL_ARG(void *, void *); +# define IMPLEMENT_LHASH_DOALL_ARG_FN(name, o_type, a_type) \ + void name##_LHASH_DOALL_ARG(void *arg1, void *arg2) { \ + o_type *a = arg1; \ + a_type *b = arg2; \ + name##_doall_arg(a, b); } +# define LHASH_DOALL_ARG_FN(name) name##_LHASH_DOALL_ARG + + +# define LH_LOAD_MULT 256 + +int OPENSSL_LH_error(OPENSSL_LHASH *lh); +OPENSSL_LHASH *OPENSSL_LH_new(OPENSSL_LH_HASHFUNC h, OPENSSL_LH_COMPFUNC c); +void OPENSSL_LH_free(OPENSSL_LHASH *lh); +void *OPENSSL_LH_insert(OPENSSL_LHASH *lh, void *data); +void *OPENSSL_LH_delete(OPENSSL_LHASH *lh, const void *data); +void *OPENSSL_LH_retrieve(OPENSSL_LHASH *lh, const void *data); +void OPENSSL_LH_doall(OPENSSL_LHASH *lh, OPENSSL_LH_DOALL_FUNC func); +void OPENSSL_LH_doall_arg(OPENSSL_LHASH *lh, OPENSSL_LH_DOALL_FUNCARG func, void *arg); +unsigned long OPENSSL_LH_strhash(const char *c); +unsigned long OPENSSL_LH_num_items(const OPENSSL_LHASH *lh); +unsigned long OPENSSL_LH_get_down_load(const OPENSSL_LHASH *lh); +void OPENSSL_LH_set_down_load(OPENSSL_LHASH *lh, unsigned long down_load); + +# ifndef OPENSSL_NO_STDIO +void OPENSSL_LH_stats(const OPENSSL_LHASH *lh, FILE *fp); +void OPENSSL_LH_node_stats(const OPENSSL_LHASH *lh, FILE *fp); +void OPENSSL_LH_node_usage_stats(const OPENSSL_LHASH *lh, FILE *fp); +# endif +void OPENSSL_LH_stats_bio(const OPENSSL_LHASH *lh, BIO *out); +void OPENSSL_LH_node_stats_bio(const OPENSSL_LHASH *lh, BIO *out); +void OPENSSL_LH_node_usage_stats_bio(const OPENSSL_LHASH *lh, BIO *out); + +# if OPENSSL_API_COMPAT < 0x10100000L +# define _LHASH OPENSSL_LHASH +# define LHASH_NODE OPENSSL_LH_NODE +# define lh_error OPENSSL_LH_error +# define lh_new OPENSSL_LH_new +# define lh_free OPENSSL_LH_free +# define lh_insert OPENSSL_LH_insert +# define lh_delete OPENSSL_LH_delete +# define lh_retrieve OPENSSL_LH_retrieve +# define lh_doall OPENSSL_LH_doall +# define lh_doall_arg OPENSSL_LH_doall_arg +# define lh_strhash OPENSSL_LH_strhash +# define lh_num_items OPENSSL_LH_num_items +# ifndef OPENSSL_NO_STDIO +# define lh_stats OPENSSL_LH_stats +# define lh_node_stats OPENSSL_LH_node_stats +# define lh_node_usage_stats OPENSSL_LH_node_usage_stats +# endif +# define lh_stats_bio OPENSSL_LH_stats_bio +# define lh_node_stats_bio OPENSSL_LH_node_stats_bio +# define lh_node_usage_stats_bio OPENSSL_LH_node_usage_stats_bio +# endif + +/* Type checking... */ + +# define LHASH_OF(type) struct lhash_st_##type + +# define DEFINE_LHASH_OF(type) \ + LHASH_OF(type) { union lh_##type##_dummy { void* d1; unsigned long d2; int d3; } dummy; }; \ + static ossl_inline LHASH_OF(type) * \ + lh_##type##_new(unsigned long (*hfn)(const type *), \ + int (*cfn)(const type *, const type *)) \ + { \ + return (LHASH_OF(type) *) \ + OPENSSL_LH_new((OPENSSL_LH_HASHFUNC)hfn, (OPENSSL_LH_COMPFUNC)cfn); \ + } \ + static ossl_unused ossl_inline void lh_##type##_free(LHASH_OF(type) *lh) \ + { \ + OPENSSL_LH_free((OPENSSL_LHASH *)lh); \ + } \ + static ossl_unused ossl_inline type *lh_##type##_insert(LHASH_OF(type) *lh, type *d) \ + { \ + return (type *)OPENSSL_LH_insert((OPENSSL_LHASH *)lh, d); \ + } \ + static ossl_unused ossl_inline type *lh_##type##_delete(LHASH_OF(type) *lh, const type *d) \ + { \ + return (type *)OPENSSL_LH_delete((OPENSSL_LHASH *)lh, d); \ + } \ + static ossl_unused ossl_inline type *lh_##type##_retrieve(LHASH_OF(type) *lh, const type *d) \ + { \ + return (type *)OPENSSL_LH_retrieve((OPENSSL_LHASH *)lh, d); \ + } \ + static ossl_unused ossl_inline int lh_##type##_error(LHASH_OF(type) *lh) \ + { \ + return OPENSSL_LH_error((OPENSSL_LHASH *)lh); \ + } \ + static ossl_unused ossl_inline unsigned long lh_##type##_num_items(LHASH_OF(type) *lh) \ + { \ + return OPENSSL_LH_num_items((OPENSSL_LHASH *)lh); \ + } \ + static ossl_unused ossl_inline void lh_##type##_node_stats_bio(const LHASH_OF(type) *lh, BIO *out) \ + { \ + OPENSSL_LH_node_stats_bio((const OPENSSL_LHASH *)lh, out); \ + } \ + static ossl_unused ossl_inline void lh_##type##_node_usage_stats_bio(const LHASH_OF(type) *lh, BIO *out) \ + { \ + OPENSSL_LH_node_usage_stats_bio((const OPENSSL_LHASH *)lh, out); \ + } \ + static ossl_unused ossl_inline void lh_##type##_stats_bio(const LHASH_OF(type) *lh, BIO *out) \ + { \ + OPENSSL_LH_stats_bio((const OPENSSL_LHASH *)lh, out); \ + } \ + static ossl_unused ossl_inline unsigned long lh_##type##_get_down_load(LHASH_OF(type) *lh) \ + { \ + return OPENSSL_LH_get_down_load((OPENSSL_LHASH *)lh); \ + } \ + static ossl_unused ossl_inline void lh_##type##_set_down_load(LHASH_OF(type) *lh, unsigned long dl) \ + { \ + OPENSSL_LH_set_down_load((OPENSSL_LHASH *)lh, dl); \ + } \ + static ossl_unused ossl_inline void lh_##type##_doall(LHASH_OF(type) *lh, \ + void (*doall)(type *)) \ + { \ + OPENSSL_LH_doall((OPENSSL_LHASH *)lh, (OPENSSL_LH_DOALL_FUNC)doall); \ + } \ + LHASH_OF(type) + +#define IMPLEMENT_LHASH_DOALL_ARG_CONST(type, argtype) \ + int_implement_lhash_doall(type, argtype, const type) + +#define IMPLEMENT_LHASH_DOALL_ARG(type, argtype) \ + int_implement_lhash_doall(type, argtype, type) + +#define int_implement_lhash_doall(type, argtype, cbargtype) \ + static ossl_unused ossl_inline void \ + lh_##type##_doall_##argtype(LHASH_OF(type) *lh, \ + void (*fn)(cbargtype *, argtype *), \ + argtype *arg) \ + { \ + OPENSSL_LH_doall_arg((OPENSSL_LHASH *)lh, (OPENSSL_LH_DOALL_FUNCARG)fn, (void *)arg); \ + } \ + LHASH_OF(type) + +DEFINE_LHASH_OF(OPENSSL_STRING); +# ifdef _MSC_VER +/* + * push and pop this warning: + * warning C4090: 'function': different 'const' qualifiers + */ +# pragma warning (push) +# pragma warning (disable: 4090) +# endif + +DEFINE_LHASH_OF(OPENSSL_CSTRING); + +# ifdef _MSC_VER +# pragma warning (pop) +# endif + +/* + * If called without higher optimization (min. -xO3) the Oracle Developer + * Studio compiler generates code for the defined (static inline) functions + * above. + * This would later lead to the linker complaining about missing symbols when + * this header file is included but the resulting object is not linked against + * the Crypto library (openssl#6912). + */ +# ifdef __SUNPRO_C +# pragma weak OPENSSL_LH_new +# pragma weak OPENSSL_LH_free +# pragma weak OPENSSL_LH_insert +# pragma weak OPENSSL_LH_delete +# pragma weak OPENSSL_LH_retrieve +# pragma weak OPENSSL_LH_error +# pragma weak OPENSSL_LH_num_items +# pragma weak OPENSSL_LH_node_stats_bio +# pragma weak OPENSSL_LH_node_usage_stats_bio +# pragma weak OPENSSL_LH_stats_bio +# pragma weak OPENSSL_LH_get_down_load +# pragma weak OPENSSL_LH_set_down_load +# pragma weak OPENSSL_LH_doall +# pragma weak OPENSSL_LH_doall_arg +# endif /* __SUNPRO_C */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/md2.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/md2.h new file mode 100644 index 000000000..7faf8e3d6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/md2.h @@ -0,0 +1,44 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_MD2_H +# define HEADER_MD2_H + +# include + +# ifndef OPENSSL_NO_MD2 +# include +# ifdef __cplusplus +extern "C" { +# endif + +typedef unsigned char MD2_INT; + +# define MD2_DIGEST_LENGTH 16 +# define MD2_BLOCK 16 + +typedef struct MD2state_st { + unsigned int num; + unsigned char data[MD2_BLOCK]; + MD2_INT cksm[MD2_BLOCK]; + MD2_INT state[MD2_BLOCK]; +} MD2_CTX; + +const char *MD2_options(void); +int MD2_Init(MD2_CTX *c); +int MD2_Update(MD2_CTX *c, const unsigned char *data, size_t len); +int MD2_Final(unsigned char *md, MD2_CTX *c); +unsigned char *MD2(const unsigned char *d, size_t n, unsigned char *md); + +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/md4.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/md4.h new file mode 100644 index 000000000..940e29db4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/md4.h @@ -0,0 +1,51 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_MD4_H +# define HEADER_MD4_H + +# include + +# ifndef OPENSSL_NO_MD4 +# include +# include +# ifdef __cplusplus +extern "C" { +# endif + +/*- + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * ! MD4_LONG has to be at least 32 bits wide. ! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + */ +# define MD4_LONG unsigned int + +# define MD4_CBLOCK 64 +# define MD4_LBLOCK (MD4_CBLOCK/4) +# define MD4_DIGEST_LENGTH 16 + +typedef struct MD4state_st { + MD4_LONG A, B, C, D; + MD4_LONG Nl, Nh; + MD4_LONG data[MD4_LBLOCK]; + unsigned int num; +} MD4_CTX; + +int MD4_Init(MD4_CTX *c); +int MD4_Update(MD4_CTX *c, const void *data, size_t len); +int MD4_Final(unsigned char *md, MD4_CTX *c); +unsigned char *MD4(const unsigned char *d, size_t n, unsigned char *md); +void MD4_Transform(MD4_CTX *c, const unsigned char *b); + +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/md5.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/md5.h new file mode 100644 index 000000000..2deb77211 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/md5.h @@ -0,0 +1,50 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_MD5_H +# define HEADER_MD5_H + +# include + +# ifndef OPENSSL_NO_MD5 +# include +# include +# ifdef __cplusplus +extern "C" { +# endif + +/* + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * ! MD5_LONG has to be at least 32 bits wide. ! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + */ +# define MD5_LONG unsigned int + +# define MD5_CBLOCK 64 +# define MD5_LBLOCK (MD5_CBLOCK/4) +# define MD5_DIGEST_LENGTH 16 + +typedef struct MD5state_st { + MD5_LONG A, B, C, D; + MD5_LONG Nl, Nh; + MD5_LONG data[MD5_LBLOCK]; + unsigned int num; +} MD5_CTX; + +int MD5_Init(MD5_CTX *c); +int MD5_Update(MD5_CTX *c, const void *data, size_t len); +int MD5_Final(unsigned char *md, MD5_CTX *c); +unsigned char *MD5(const unsigned char *d, size_t n, unsigned char *md); +void MD5_Transform(MD5_CTX *c, const unsigned char *b); +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/mdc2.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/mdc2.h new file mode 100644 index 000000000..aabd2bfaa --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/mdc2.h @@ -0,0 +1,42 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_MDC2_H +# define HEADER_MDC2_H + +# include + +#ifndef OPENSSL_NO_MDC2 +# include +# include +# ifdef __cplusplus +extern "C" { +# endif + +# define MDC2_BLOCK 8 +# define MDC2_DIGEST_LENGTH 16 + +typedef struct mdc2_ctx_st { + unsigned int num; + unsigned char data[MDC2_BLOCK]; + DES_cblock h, hh; + int pad_type; /* either 1 or 2, default 1 */ +} MDC2_CTX; + +int MDC2_Init(MDC2_CTX *c); +int MDC2_Update(MDC2_CTX *c, const unsigned char *data, size_t len); +int MDC2_Final(unsigned char *md, MDC2_CTX *c); +unsigned char *MDC2(const unsigned char *d, size_t n, unsigned char *md); + +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/modes.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/modes.h new file mode 100644 index 000000000..d544f98d5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/modes.h @@ -0,0 +1,208 @@ +/* + * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_MODES_H +# define HEADER_MODES_H + +# include + +# ifdef __cplusplus +extern "C" { +# endif +typedef void (*block128_f) (const unsigned char in[16], + unsigned char out[16], const void *key); + +typedef void (*cbc128_f) (const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], int enc); + +typedef void (*ctr128_f) (const unsigned char *in, unsigned char *out, + size_t blocks, const void *key, + const unsigned char ivec[16]); + +typedef void (*ccm128_f) (const unsigned char *in, unsigned char *out, + size_t blocks, const void *key, + const unsigned char ivec[16], + unsigned char cmac[16]); + +void CRYPTO_cbc128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], block128_f block); +void CRYPTO_cbc128_decrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], block128_f block); + +void CRYPTO_ctr128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], + unsigned char ecount_buf[16], unsigned int *num, + block128_f block); + +void CRYPTO_ctr128_encrypt_ctr32(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], + unsigned char ecount_buf[16], + unsigned int *num, ctr128_f ctr); + +void CRYPTO_ofb128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], int *num, + block128_f block); + +void CRYPTO_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], int *num, + int enc, block128_f block); +void CRYPTO_cfb128_8_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const void *key, + unsigned char ivec[16], int *num, + int enc, block128_f block); +void CRYPTO_cfb128_1_encrypt(const unsigned char *in, unsigned char *out, + size_t bits, const void *key, + unsigned char ivec[16], int *num, + int enc, block128_f block); + +size_t CRYPTO_cts128_encrypt_block(const unsigned char *in, + unsigned char *out, size_t len, + const void *key, unsigned char ivec[16], + block128_f block); +size_t CRYPTO_cts128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], cbc128_f cbc); +size_t CRYPTO_cts128_decrypt_block(const unsigned char *in, + unsigned char *out, size_t len, + const void *key, unsigned char ivec[16], + block128_f block); +size_t CRYPTO_cts128_decrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], cbc128_f cbc); + +size_t CRYPTO_nistcts128_encrypt_block(const unsigned char *in, + unsigned char *out, size_t len, + const void *key, + unsigned char ivec[16], + block128_f block); +size_t CRYPTO_nistcts128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], cbc128_f cbc); +size_t CRYPTO_nistcts128_decrypt_block(const unsigned char *in, + unsigned char *out, size_t len, + const void *key, + unsigned char ivec[16], + block128_f block); +size_t CRYPTO_nistcts128_decrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], cbc128_f cbc); + +typedef struct gcm128_context GCM128_CONTEXT; + +GCM128_CONTEXT *CRYPTO_gcm128_new(void *key, block128_f block); +void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, void *key, block128_f block); +void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const unsigned char *iv, + size_t len); +int CRYPTO_gcm128_aad(GCM128_CONTEXT *ctx, const unsigned char *aad, + size_t len); +int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, + const unsigned char *in, unsigned char *out, + size_t len); +int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, + const unsigned char *in, unsigned char *out, + size_t len); +int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, + const unsigned char *in, unsigned char *out, + size_t len, ctr128_f stream); +int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, + const unsigned char *in, unsigned char *out, + size_t len, ctr128_f stream); +int CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx, const unsigned char *tag, + size_t len); +void CRYPTO_gcm128_tag(GCM128_CONTEXT *ctx, unsigned char *tag, size_t len); +void CRYPTO_gcm128_release(GCM128_CONTEXT *ctx); + +typedef struct ccm128_context CCM128_CONTEXT; + +void CRYPTO_ccm128_init(CCM128_CONTEXT *ctx, + unsigned int M, unsigned int L, void *key, + block128_f block); +int CRYPTO_ccm128_setiv(CCM128_CONTEXT *ctx, const unsigned char *nonce, + size_t nlen, size_t mlen); +void CRYPTO_ccm128_aad(CCM128_CONTEXT *ctx, const unsigned char *aad, + size_t alen); +int CRYPTO_ccm128_encrypt(CCM128_CONTEXT *ctx, const unsigned char *inp, + unsigned char *out, size_t len); +int CRYPTO_ccm128_decrypt(CCM128_CONTEXT *ctx, const unsigned char *inp, + unsigned char *out, size_t len); +int CRYPTO_ccm128_encrypt_ccm64(CCM128_CONTEXT *ctx, const unsigned char *inp, + unsigned char *out, size_t len, + ccm128_f stream); +int CRYPTO_ccm128_decrypt_ccm64(CCM128_CONTEXT *ctx, const unsigned char *inp, + unsigned char *out, size_t len, + ccm128_f stream); +size_t CRYPTO_ccm128_tag(CCM128_CONTEXT *ctx, unsigned char *tag, size_t len); + +typedef struct xts128_context XTS128_CONTEXT; + +int CRYPTO_xts128_encrypt(const XTS128_CONTEXT *ctx, + const unsigned char iv[16], + const unsigned char *inp, unsigned char *out, + size_t len, int enc); + +size_t CRYPTO_128_wrap(void *key, const unsigned char *iv, + unsigned char *out, + const unsigned char *in, size_t inlen, + block128_f block); + +size_t CRYPTO_128_unwrap(void *key, const unsigned char *iv, + unsigned char *out, + const unsigned char *in, size_t inlen, + block128_f block); +size_t CRYPTO_128_wrap_pad(void *key, const unsigned char *icv, + unsigned char *out, const unsigned char *in, + size_t inlen, block128_f block); +size_t CRYPTO_128_unwrap_pad(void *key, const unsigned char *icv, + unsigned char *out, const unsigned char *in, + size_t inlen, block128_f block); + +# ifndef OPENSSL_NO_OCB +typedef struct ocb128_context OCB128_CONTEXT; + +typedef void (*ocb128_f) (const unsigned char *in, unsigned char *out, + size_t blocks, const void *key, + size_t start_block_num, + unsigned char offset_i[16], + const unsigned char L_[][16], + unsigned char checksum[16]); + +OCB128_CONTEXT *CRYPTO_ocb128_new(void *keyenc, void *keydec, + block128_f encrypt, block128_f decrypt, + ocb128_f stream); +int CRYPTO_ocb128_init(OCB128_CONTEXT *ctx, void *keyenc, void *keydec, + block128_f encrypt, block128_f decrypt, + ocb128_f stream); +int CRYPTO_ocb128_copy_ctx(OCB128_CONTEXT *dest, OCB128_CONTEXT *src, + void *keyenc, void *keydec); +int CRYPTO_ocb128_setiv(OCB128_CONTEXT *ctx, const unsigned char *iv, + size_t len, size_t taglen); +int CRYPTO_ocb128_aad(OCB128_CONTEXT *ctx, const unsigned char *aad, + size_t len); +int CRYPTO_ocb128_encrypt(OCB128_CONTEXT *ctx, const unsigned char *in, + unsigned char *out, size_t len); +int CRYPTO_ocb128_decrypt(OCB128_CONTEXT *ctx, const unsigned char *in, + unsigned char *out, size_t len); +int CRYPTO_ocb128_finish(OCB128_CONTEXT *ctx, const unsigned char *tag, + size_t len); +int CRYPTO_ocb128_tag(OCB128_CONTEXT *ctx, unsigned char *tag, size_t len); +void CRYPTO_ocb128_cleanup(OCB128_CONTEXT *ctx); +# endif /* OPENSSL_NO_OCB */ + +# ifdef __cplusplus +} +# endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/obj_mac.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/obj_mac.h new file mode 100644 index 000000000..31fad4640 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/obj_mac.h @@ -0,0 +1,5198 @@ +/* + * WARNING: do not edit! + * Generated by crypto/objects/objects.pl + * + * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved. + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#define SN_undef "UNDEF" +#define LN_undef "undefined" +#define NID_undef 0 +#define OBJ_undef 0L + +#define SN_itu_t "ITU-T" +#define LN_itu_t "itu-t" +#define NID_itu_t 645 +#define OBJ_itu_t 0L + +#define NID_ccitt 404 +#define OBJ_ccitt OBJ_itu_t + +#define SN_iso "ISO" +#define LN_iso "iso" +#define NID_iso 181 +#define OBJ_iso 1L + +#define SN_joint_iso_itu_t "JOINT-ISO-ITU-T" +#define LN_joint_iso_itu_t "joint-iso-itu-t" +#define NID_joint_iso_itu_t 646 +#define OBJ_joint_iso_itu_t 2L + +#define NID_joint_iso_ccitt 393 +#define OBJ_joint_iso_ccitt OBJ_joint_iso_itu_t + +#define SN_member_body "member-body" +#define LN_member_body "ISO Member Body" +#define NID_member_body 182 +#define OBJ_member_body OBJ_iso,2L + +#define SN_identified_organization "identified-organization" +#define NID_identified_organization 676 +#define OBJ_identified_organization OBJ_iso,3L + +#define SN_hmac_md5 "HMAC-MD5" +#define LN_hmac_md5 "hmac-md5" +#define NID_hmac_md5 780 +#define OBJ_hmac_md5 OBJ_identified_organization,6L,1L,5L,5L,8L,1L,1L + +#define SN_hmac_sha1 "HMAC-SHA1" +#define LN_hmac_sha1 "hmac-sha1" +#define NID_hmac_sha1 781 +#define OBJ_hmac_sha1 OBJ_identified_organization,6L,1L,5L,5L,8L,1L,2L + +#define SN_x509ExtAdmission "x509ExtAdmission" +#define LN_x509ExtAdmission "Professional Information or basis for Admission" +#define NID_x509ExtAdmission 1093 +#define OBJ_x509ExtAdmission OBJ_identified_organization,36L,8L,3L,3L + +#define SN_certicom_arc "certicom-arc" +#define NID_certicom_arc 677 +#define OBJ_certicom_arc OBJ_identified_organization,132L + +#define SN_ieee "ieee" +#define NID_ieee 1170 +#define OBJ_ieee OBJ_identified_organization,111L + +#define SN_ieee_siswg "ieee-siswg" +#define LN_ieee_siswg "IEEE Security in Storage Working Group" +#define NID_ieee_siswg 1171 +#define OBJ_ieee_siswg OBJ_ieee,2L,1619L + +#define SN_international_organizations "international-organizations" +#define LN_international_organizations "International Organizations" +#define NID_international_organizations 647 +#define OBJ_international_organizations OBJ_joint_iso_itu_t,23L + +#define SN_wap "wap" +#define NID_wap 678 +#define OBJ_wap OBJ_international_organizations,43L + +#define SN_wap_wsg "wap-wsg" +#define NID_wap_wsg 679 +#define OBJ_wap_wsg OBJ_wap,1L + +#define SN_selected_attribute_types "selected-attribute-types" +#define LN_selected_attribute_types "Selected Attribute Types" +#define NID_selected_attribute_types 394 +#define OBJ_selected_attribute_types OBJ_joint_iso_itu_t,5L,1L,5L + +#define SN_clearance "clearance" +#define NID_clearance 395 +#define OBJ_clearance OBJ_selected_attribute_types,55L + +#define SN_ISO_US "ISO-US" +#define LN_ISO_US "ISO US Member Body" +#define NID_ISO_US 183 +#define OBJ_ISO_US OBJ_member_body,840L + +#define SN_X9_57 "X9-57" +#define LN_X9_57 "X9.57" +#define NID_X9_57 184 +#define OBJ_X9_57 OBJ_ISO_US,10040L + +#define SN_X9cm "X9cm" +#define LN_X9cm "X9.57 CM ?" +#define NID_X9cm 185 +#define OBJ_X9cm OBJ_X9_57,4L + +#define SN_ISO_CN "ISO-CN" +#define LN_ISO_CN "ISO CN Member Body" +#define NID_ISO_CN 1140 +#define OBJ_ISO_CN OBJ_member_body,156L + +#define SN_oscca "oscca" +#define NID_oscca 1141 +#define OBJ_oscca OBJ_ISO_CN,10197L + +#define SN_sm_scheme "sm-scheme" +#define NID_sm_scheme 1142 +#define OBJ_sm_scheme OBJ_oscca,1L + +#define SN_dsa "DSA" +#define LN_dsa "dsaEncryption" +#define NID_dsa 116 +#define OBJ_dsa OBJ_X9cm,1L + +#define SN_dsaWithSHA1 "DSA-SHA1" +#define LN_dsaWithSHA1 "dsaWithSHA1" +#define NID_dsaWithSHA1 113 +#define OBJ_dsaWithSHA1 OBJ_X9cm,3L + +#define SN_ansi_X9_62 "ansi-X9-62" +#define LN_ansi_X9_62 "ANSI X9.62" +#define NID_ansi_X9_62 405 +#define OBJ_ansi_X9_62 OBJ_ISO_US,10045L + +#define OBJ_X9_62_id_fieldType OBJ_ansi_X9_62,1L + +#define SN_X9_62_prime_field "prime-field" +#define NID_X9_62_prime_field 406 +#define OBJ_X9_62_prime_field OBJ_X9_62_id_fieldType,1L + +#define SN_X9_62_characteristic_two_field "characteristic-two-field" +#define NID_X9_62_characteristic_two_field 407 +#define OBJ_X9_62_characteristic_two_field OBJ_X9_62_id_fieldType,2L + +#define SN_X9_62_id_characteristic_two_basis "id-characteristic-two-basis" +#define NID_X9_62_id_characteristic_two_basis 680 +#define OBJ_X9_62_id_characteristic_two_basis OBJ_X9_62_characteristic_two_field,3L + +#define SN_X9_62_onBasis "onBasis" +#define NID_X9_62_onBasis 681 +#define OBJ_X9_62_onBasis OBJ_X9_62_id_characteristic_two_basis,1L + +#define SN_X9_62_tpBasis "tpBasis" +#define NID_X9_62_tpBasis 682 +#define OBJ_X9_62_tpBasis OBJ_X9_62_id_characteristic_two_basis,2L + +#define SN_X9_62_ppBasis "ppBasis" +#define NID_X9_62_ppBasis 683 +#define OBJ_X9_62_ppBasis OBJ_X9_62_id_characteristic_two_basis,3L + +#define OBJ_X9_62_id_publicKeyType OBJ_ansi_X9_62,2L + +#define SN_X9_62_id_ecPublicKey "id-ecPublicKey" +#define NID_X9_62_id_ecPublicKey 408 +#define OBJ_X9_62_id_ecPublicKey OBJ_X9_62_id_publicKeyType,1L + +#define OBJ_X9_62_ellipticCurve OBJ_ansi_X9_62,3L + +#define OBJ_X9_62_c_TwoCurve OBJ_X9_62_ellipticCurve,0L + +#define SN_X9_62_c2pnb163v1 "c2pnb163v1" +#define NID_X9_62_c2pnb163v1 684 +#define OBJ_X9_62_c2pnb163v1 OBJ_X9_62_c_TwoCurve,1L + +#define SN_X9_62_c2pnb163v2 "c2pnb163v2" +#define NID_X9_62_c2pnb163v2 685 +#define OBJ_X9_62_c2pnb163v2 OBJ_X9_62_c_TwoCurve,2L + +#define SN_X9_62_c2pnb163v3 "c2pnb163v3" +#define NID_X9_62_c2pnb163v3 686 +#define OBJ_X9_62_c2pnb163v3 OBJ_X9_62_c_TwoCurve,3L + +#define SN_X9_62_c2pnb176v1 "c2pnb176v1" +#define NID_X9_62_c2pnb176v1 687 +#define OBJ_X9_62_c2pnb176v1 OBJ_X9_62_c_TwoCurve,4L + +#define SN_X9_62_c2tnb191v1 "c2tnb191v1" +#define NID_X9_62_c2tnb191v1 688 +#define OBJ_X9_62_c2tnb191v1 OBJ_X9_62_c_TwoCurve,5L + +#define SN_X9_62_c2tnb191v2 "c2tnb191v2" +#define NID_X9_62_c2tnb191v2 689 +#define OBJ_X9_62_c2tnb191v2 OBJ_X9_62_c_TwoCurve,6L + +#define SN_X9_62_c2tnb191v3 "c2tnb191v3" +#define NID_X9_62_c2tnb191v3 690 +#define OBJ_X9_62_c2tnb191v3 OBJ_X9_62_c_TwoCurve,7L + +#define SN_X9_62_c2onb191v4 "c2onb191v4" +#define NID_X9_62_c2onb191v4 691 +#define OBJ_X9_62_c2onb191v4 OBJ_X9_62_c_TwoCurve,8L + +#define SN_X9_62_c2onb191v5 "c2onb191v5" +#define NID_X9_62_c2onb191v5 692 +#define OBJ_X9_62_c2onb191v5 OBJ_X9_62_c_TwoCurve,9L + +#define SN_X9_62_c2pnb208w1 "c2pnb208w1" +#define NID_X9_62_c2pnb208w1 693 +#define OBJ_X9_62_c2pnb208w1 OBJ_X9_62_c_TwoCurve,10L + +#define SN_X9_62_c2tnb239v1 "c2tnb239v1" +#define NID_X9_62_c2tnb239v1 694 +#define OBJ_X9_62_c2tnb239v1 OBJ_X9_62_c_TwoCurve,11L + +#define SN_X9_62_c2tnb239v2 "c2tnb239v2" +#define NID_X9_62_c2tnb239v2 695 +#define OBJ_X9_62_c2tnb239v2 OBJ_X9_62_c_TwoCurve,12L + +#define SN_X9_62_c2tnb239v3 "c2tnb239v3" +#define NID_X9_62_c2tnb239v3 696 +#define OBJ_X9_62_c2tnb239v3 OBJ_X9_62_c_TwoCurve,13L + +#define SN_X9_62_c2onb239v4 "c2onb239v4" +#define NID_X9_62_c2onb239v4 697 +#define OBJ_X9_62_c2onb239v4 OBJ_X9_62_c_TwoCurve,14L + +#define SN_X9_62_c2onb239v5 "c2onb239v5" +#define NID_X9_62_c2onb239v5 698 +#define OBJ_X9_62_c2onb239v5 OBJ_X9_62_c_TwoCurve,15L + +#define SN_X9_62_c2pnb272w1 "c2pnb272w1" +#define NID_X9_62_c2pnb272w1 699 +#define OBJ_X9_62_c2pnb272w1 OBJ_X9_62_c_TwoCurve,16L + +#define SN_X9_62_c2pnb304w1 "c2pnb304w1" +#define NID_X9_62_c2pnb304w1 700 +#define OBJ_X9_62_c2pnb304w1 OBJ_X9_62_c_TwoCurve,17L + +#define SN_X9_62_c2tnb359v1 "c2tnb359v1" +#define NID_X9_62_c2tnb359v1 701 +#define OBJ_X9_62_c2tnb359v1 OBJ_X9_62_c_TwoCurve,18L + +#define SN_X9_62_c2pnb368w1 "c2pnb368w1" +#define NID_X9_62_c2pnb368w1 702 +#define OBJ_X9_62_c2pnb368w1 OBJ_X9_62_c_TwoCurve,19L + +#define SN_X9_62_c2tnb431r1 "c2tnb431r1" +#define NID_X9_62_c2tnb431r1 703 +#define OBJ_X9_62_c2tnb431r1 OBJ_X9_62_c_TwoCurve,20L + +#define OBJ_X9_62_primeCurve OBJ_X9_62_ellipticCurve,1L + +#define SN_X9_62_prime192v1 "prime192v1" +#define NID_X9_62_prime192v1 409 +#define OBJ_X9_62_prime192v1 OBJ_X9_62_primeCurve,1L + +#define SN_X9_62_prime192v2 "prime192v2" +#define NID_X9_62_prime192v2 410 +#define OBJ_X9_62_prime192v2 OBJ_X9_62_primeCurve,2L + +#define SN_X9_62_prime192v3 "prime192v3" +#define NID_X9_62_prime192v3 411 +#define OBJ_X9_62_prime192v3 OBJ_X9_62_primeCurve,3L + +#define SN_X9_62_prime239v1 "prime239v1" +#define NID_X9_62_prime239v1 412 +#define OBJ_X9_62_prime239v1 OBJ_X9_62_primeCurve,4L + +#define SN_X9_62_prime239v2 "prime239v2" +#define NID_X9_62_prime239v2 413 +#define OBJ_X9_62_prime239v2 OBJ_X9_62_primeCurve,5L + +#define SN_X9_62_prime239v3 "prime239v3" +#define NID_X9_62_prime239v3 414 +#define OBJ_X9_62_prime239v3 OBJ_X9_62_primeCurve,6L + +#define SN_X9_62_prime256v1 "prime256v1" +#define NID_X9_62_prime256v1 415 +#define OBJ_X9_62_prime256v1 OBJ_X9_62_primeCurve,7L + +#define OBJ_X9_62_id_ecSigType OBJ_ansi_X9_62,4L + +#define SN_ecdsa_with_SHA1 "ecdsa-with-SHA1" +#define NID_ecdsa_with_SHA1 416 +#define OBJ_ecdsa_with_SHA1 OBJ_X9_62_id_ecSigType,1L + +#define SN_ecdsa_with_Recommended "ecdsa-with-Recommended" +#define NID_ecdsa_with_Recommended 791 +#define OBJ_ecdsa_with_Recommended OBJ_X9_62_id_ecSigType,2L + +#define SN_ecdsa_with_Specified "ecdsa-with-Specified" +#define NID_ecdsa_with_Specified 792 +#define OBJ_ecdsa_with_Specified OBJ_X9_62_id_ecSigType,3L + +#define SN_ecdsa_with_SHA224 "ecdsa-with-SHA224" +#define NID_ecdsa_with_SHA224 793 +#define OBJ_ecdsa_with_SHA224 OBJ_ecdsa_with_Specified,1L + +#define SN_ecdsa_with_SHA256 "ecdsa-with-SHA256" +#define NID_ecdsa_with_SHA256 794 +#define OBJ_ecdsa_with_SHA256 OBJ_ecdsa_with_Specified,2L + +#define SN_ecdsa_with_SHA384 "ecdsa-with-SHA384" +#define NID_ecdsa_with_SHA384 795 +#define OBJ_ecdsa_with_SHA384 OBJ_ecdsa_with_Specified,3L + +#define SN_ecdsa_with_SHA512 "ecdsa-with-SHA512" +#define NID_ecdsa_with_SHA512 796 +#define OBJ_ecdsa_with_SHA512 OBJ_ecdsa_with_Specified,4L + +#define OBJ_secg_ellipticCurve OBJ_certicom_arc,0L + +#define SN_secp112r1 "secp112r1" +#define NID_secp112r1 704 +#define OBJ_secp112r1 OBJ_secg_ellipticCurve,6L + +#define SN_secp112r2 "secp112r2" +#define NID_secp112r2 705 +#define OBJ_secp112r2 OBJ_secg_ellipticCurve,7L + +#define SN_secp128r1 "secp128r1" +#define NID_secp128r1 706 +#define OBJ_secp128r1 OBJ_secg_ellipticCurve,28L + +#define SN_secp128r2 "secp128r2" +#define NID_secp128r2 707 +#define OBJ_secp128r2 OBJ_secg_ellipticCurve,29L + +#define SN_secp160k1 "secp160k1" +#define NID_secp160k1 708 +#define OBJ_secp160k1 OBJ_secg_ellipticCurve,9L + +#define SN_secp160r1 "secp160r1" +#define NID_secp160r1 709 +#define OBJ_secp160r1 OBJ_secg_ellipticCurve,8L + +#define SN_secp160r2 "secp160r2" +#define NID_secp160r2 710 +#define OBJ_secp160r2 OBJ_secg_ellipticCurve,30L + +#define SN_secp192k1 "secp192k1" +#define NID_secp192k1 711 +#define OBJ_secp192k1 OBJ_secg_ellipticCurve,31L + +#define SN_secp224k1 "secp224k1" +#define NID_secp224k1 712 +#define OBJ_secp224k1 OBJ_secg_ellipticCurve,32L + +#define SN_secp224r1 "secp224r1" +#define NID_secp224r1 713 +#define OBJ_secp224r1 OBJ_secg_ellipticCurve,33L + +#define SN_secp256k1 "secp256k1" +#define NID_secp256k1 714 +#define OBJ_secp256k1 OBJ_secg_ellipticCurve,10L + +#define SN_secp384r1 "secp384r1" +#define NID_secp384r1 715 +#define OBJ_secp384r1 OBJ_secg_ellipticCurve,34L + +#define SN_secp521r1 "secp521r1" +#define NID_secp521r1 716 +#define OBJ_secp521r1 OBJ_secg_ellipticCurve,35L + +#define SN_sect113r1 "sect113r1" +#define NID_sect113r1 717 +#define OBJ_sect113r1 OBJ_secg_ellipticCurve,4L + +#define SN_sect113r2 "sect113r2" +#define NID_sect113r2 718 +#define OBJ_sect113r2 OBJ_secg_ellipticCurve,5L + +#define SN_sect131r1 "sect131r1" +#define NID_sect131r1 719 +#define OBJ_sect131r1 OBJ_secg_ellipticCurve,22L + +#define SN_sect131r2 "sect131r2" +#define NID_sect131r2 720 +#define OBJ_sect131r2 OBJ_secg_ellipticCurve,23L + +#define SN_sect163k1 "sect163k1" +#define NID_sect163k1 721 +#define OBJ_sect163k1 OBJ_secg_ellipticCurve,1L + +#define SN_sect163r1 "sect163r1" +#define NID_sect163r1 722 +#define OBJ_sect163r1 OBJ_secg_ellipticCurve,2L + +#define SN_sect163r2 "sect163r2" +#define NID_sect163r2 723 +#define OBJ_sect163r2 OBJ_secg_ellipticCurve,15L + +#define SN_sect193r1 "sect193r1" +#define NID_sect193r1 724 +#define OBJ_sect193r1 OBJ_secg_ellipticCurve,24L + +#define SN_sect193r2 "sect193r2" +#define NID_sect193r2 725 +#define OBJ_sect193r2 OBJ_secg_ellipticCurve,25L + +#define SN_sect233k1 "sect233k1" +#define NID_sect233k1 726 +#define OBJ_sect233k1 OBJ_secg_ellipticCurve,26L + +#define SN_sect233r1 "sect233r1" +#define NID_sect233r1 727 +#define OBJ_sect233r1 OBJ_secg_ellipticCurve,27L + +#define SN_sect239k1 "sect239k1" +#define NID_sect239k1 728 +#define OBJ_sect239k1 OBJ_secg_ellipticCurve,3L + +#define SN_sect283k1 "sect283k1" +#define NID_sect283k1 729 +#define OBJ_sect283k1 OBJ_secg_ellipticCurve,16L + +#define SN_sect283r1 "sect283r1" +#define NID_sect283r1 730 +#define OBJ_sect283r1 OBJ_secg_ellipticCurve,17L + +#define SN_sect409k1 "sect409k1" +#define NID_sect409k1 731 +#define OBJ_sect409k1 OBJ_secg_ellipticCurve,36L + +#define SN_sect409r1 "sect409r1" +#define NID_sect409r1 732 +#define OBJ_sect409r1 OBJ_secg_ellipticCurve,37L + +#define SN_sect571k1 "sect571k1" +#define NID_sect571k1 733 +#define OBJ_sect571k1 OBJ_secg_ellipticCurve,38L + +#define SN_sect571r1 "sect571r1" +#define NID_sect571r1 734 +#define OBJ_sect571r1 OBJ_secg_ellipticCurve,39L + +#define OBJ_wap_wsg_idm_ecid OBJ_wap_wsg,4L + +#define SN_wap_wsg_idm_ecid_wtls1 "wap-wsg-idm-ecid-wtls1" +#define NID_wap_wsg_idm_ecid_wtls1 735 +#define OBJ_wap_wsg_idm_ecid_wtls1 OBJ_wap_wsg_idm_ecid,1L + +#define SN_wap_wsg_idm_ecid_wtls3 "wap-wsg-idm-ecid-wtls3" +#define NID_wap_wsg_idm_ecid_wtls3 736 +#define OBJ_wap_wsg_idm_ecid_wtls3 OBJ_wap_wsg_idm_ecid,3L + +#define SN_wap_wsg_idm_ecid_wtls4 "wap-wsg-idm-ecid-wtls4" +#define NID_wap_wsg_idm_ecid_wtls4 737 +#define OBJ_wap_wsg_idm_ecid_wtls4 OBJ_wap_wsg_idm_ecid,4L + +#define SN_wap_wsg_idm_ecid_wtls5 "wap-wsg-idm-ecid-wtls5" +#define NID_wap_wsg_idm_ecid_wtls5 738 +#define OBJ_wap_wsg_idm_ecid_wtls5 OBJ_wap_wsg_idm_ecid,5L + +#define SN_wap_wsg_idm_ecid_wtls6 "wap-wsg-idm-ecid-wtls6" +#define NID_wap_wsg_idm_ecid_wtls6 739 +#define OBJ_wap_wsg_idm_ecid_wtls6 OBJ_wap_wsg_idm_ecid,6L + +#define SN_wap_wsg_idm_ecid_wtls7 "wap-wsg-idm-ecid-wtls7" +#define NID_wap_wsg_idm_ecid_wtls7 740 +#define OBJ_wap_wsg_idm_ecid_wtls7 OBJ_wap_wsg_idm_ecid,7L + +#define SN_wap_wsg_idm_ecid_wtls8 "wap-wsg-idm-ecid-wtls8" +#define NID_wap_wsg_idm_ecid_wtls8 741 +#define OBJ_wap_wsg_idm_ecid_wtls8 OBJ_wap_wsg_idm_ecid,8L + +#define SN_wap_wsg_idm_ecid_wtls9 "wap-wsg-idm-ecid-wtls9" +#define NID_wap_wsg_idm_ecid_wtls9 742 +#define OBJ_wap_wsg_idm_ecid_wtls9 OBJ_wap_wsg_idm_ecid,9L + +#define SN_wap_wsg_idm_ecid_wtls10 "wap-wsg-idm-ecid-wtls10" +#define NID_wap_wsg_idm_ecid_wtls10 743 +#define OBJ_wap_wsg_idm_ecid_wtls10 OBJ_wap_wsg_idm_ecid,10L + +#define SN_wap_wsg_idm_ecid_wtls11 "wap-wsg-idm-ecid-wtls11" +#define NID_wap_wsg_idm_ecid_wtls11 744 +#define OBJ_wap_wsg_idm_ecid_wtls11 OBJ_wap_wsg_idm_ecid,11L + +#define SN_wap_wsg_idm_ecid_wtls12 "wap-wsg-idm-ecid-wtls12" +#define NID_wap_wsg_idm_ecid_wtls12 745 +#define OBJ_wap_wsg_idm_ecid_wtls12 OBJ_wap_wsg_idm_ecid,12L + +#define SN_cast5_cbc "CAST5-CBC" +#define LN_cast5_cbc "cast5-cbc" +#define NID_cast5_cbc 108 +#define OBJ_cast5_cbc OBJ_ISO_US,113533L,7L,66L,10L + +#define SN_cast5_ecb "CAST5-ECB" +#define LN_cast5_ecb "cast5-ecb" +#define NID_cast5_ecb 109 + +#define SN_cast5_cfb64 "CAST5-CFB" +#define LN_cast5_cfb64 "cast5-cfb" +#define NID_cast5_cfb64 110 + +#define SN_cast5_ofb64 "CAST5-OFB" +#define LN_cast5_ofb64 "cast5-ofb" +#define NID_cast5_ofb64 111 + +#define LN_pbeWithMD5AndCast5_CBC "pbeWithMD5AndCast5CBC" +#define NID_pbeWithMD5AndCast5_CBC 112 +#define OBJ_pbeWithMD5AndCast5_CBC OBJ_ISO_US,113533L,7L,66L,12L + +#define SN_id_PasswordBasedMAC "id-PasswordBasedMAC" +#define LN_id_PasswordBasedMAC "password based MAC" +#define NID_id_PasswordBasedMAC 782 +#define OBJ_id_PasswordBasedMAC OBJ_ISO_US,113533L,7L,66L,13L + +#define SN_id_DHBasedMac "id-DHBasedMac" +#define LN_id_DHBasedMac "Diffie-Hellman based MAC" +#define NID_id_DHBasedMac 783 +#define OBJ_id_DHBasedMac OBJ_ISO_US,113533L,7L,66L,30L + +#define SN_rsadsi "rsadsi" +#define LN_rsadsi "RSA Data Security, Inc." +#define NID_rsadsi 1 +#define OBJ_rsadsi OBJ_ISO_US,113549L + +#define SN_pkcs "pkcs" +#define LN_pkcs "RSA Data Security, Inc. PKCS" +#define NID_pkcs 2 +#define OBJ_pkcs OBJ_rsadsi,1L + +#define SN_pkcs1 "pkcs1" +#define NID_pkcs1 186 +#define OBJ_pkcs1 OBJ_pkcs,1L + +#define LN_rsaEncryption "rsaEncryption" +#define NID_rsaEncryption 6 +#define OBJ_rsaEncryption OBJ_pkcs1,1L + +#define SN_md2WithRSAEncryption "RSA-MD2" +#define LN_md2WithRSAEncryption "md2WithRSAEncryption" +#define NID_md2WithRSAEncryption 7 +#define OBJ_md2WithRSAEncryption OBJ_pkcs1,2L + +#define SN_md4WithRSAEncryption "RSA-MD4" +#define LN_md4WithRSAEncryption "md4WithRSAEncryption" +#define NID_md4WithRSAEncryption 396 +#define OBJ_md4WithRSAEncryption OBJ_pkcs1,3L + +#define SN_md5WithRSAEncryption "RSA-MD5" +#define LN_md5WithRSAEncryption "md5WithRSAEncryption" +#define NID_md5WithRSAEncryption 8 +#define OBJ_md5WithRSAEncryption OBJ_pkcs1,4L + +#define SN_sha1WithRSAEncryption "RSA-SHA1" +#define LN_sha1WithRSAEncryption "sha1WithRSAEncryption" +#define NID_sha1WithRSAEncryption 65 +#define OBJ_sha1WithRSAEncryption OBJ_pkcs1,5L + +#define SN_rsaesOaep "RSAES-OAEP" +#define LN_rsaesOaep "rsaesOaep" +#define NID_rsaesOaep 919 +#define OBJ_rsaesOaep OBJ_pkcs1,7L + +#define SN_mgf1 "MGF1" +#define LN_mgf1 "mgf1" +#define NID_mgf1 911 +#define OBJ_mgf1 OBJ_pkcs1,8L + +#define SN_pSpecified "PSPECIFIED" +#define LN_pSpecified "pSpecified" +#define NID_pSpecified 935 +#define OBJ_pSpecified OBJ_pkcs1,9L + +#define SN_rsassaPss "RSASSA-PSS" +#define LN_rsassaPss "rsassaPss" +#define NID_rsassaPss 912 +#define OBJ_rsassaPss OBJ_pkcs1,10L + +#define SN_sha256WithRSAEncryption "RSA-SHA256" +#define LN_sha256WithRSAEncryption "sha256WithRSAEncryption" +#define NID_sha256WithRSAEncryption 668 +#define OBJ_sha256WithRSAEncryption OBJ_pkcs1,11L + +#define SN_sha384WithRSAEncryption "RSA-SHA384" +#define LN_sha384WithRSAEncryption "sha384WithRSAEncryption" +#define NID_sha384WithRSAEncryption 669 +#define OBJ_sha384WithRSAEncryption OBJ_pkcs1,12L + +#define SN_sha512WithRSAEncryption "RSA-SHA512" +#define LN_sha512WithRSAEncryption "sha512WithRSAEncryption" +#define NID_sha512WithRSAEncryption 670 +#define OBJ_sha512WithRSAEncryption OBJ_pkcs1,13L + +#define SN_sha224WithRSAEncryption "RSA-SHA224" +#define LN_sha224WithRSAEncryption "sha224WithRSAEncryption" +#define NID_sha224WithRSAEncryption 671 +#define OBJ_sha224WithRSAEncryption OBJ_pkcs1,14L + +#define SN_sha512_224WithRSAEncryption "RSA-SHA512/224" +#define LN_sha512_224WithRSAEncryption "sha512-224WithRSAEncryption" +#define NID_sha512_224WithRSAEncryption 1145 +#define OBJ_sha512_224WithRSAEncryption OBJ_pkcs1,15L + +#define SN_sha512_256WithRSAEncryption "RSA-SHA512/256" +#define LN_sha512_256WithRSAEncryption "sha512-256WithRSAEncryption" +#define NID_sha512_256WithRSAEncryption 1146 +#define OBJ_sha512_256WithRSAEncryption OBJ_pkcs1,16L + +#define SN_pkcs3 "pkcs3" +#define NID_pkcs3 27 +#define OBJ_pkcs3 OBJ_pkcs,3L + +#define LN_dhKeyAgreement "dhKeyAgreement" +#define NID_dhKeyAgreement 28 +#define OBJ_dhKeyAgreement OBJ_pkcs3,1L + +#define SN_pkcs5 "pkcs5" +#define NID_pkcs5 187 +#define OBJ_pkcs5 OBJ_pkcs,5L + +#define SN_pbeWithMD2AndDES_CBC "PBE-MD2-DES" +#define LN_pbeWithMD2AndDES_CBC "pbeWithMD2AndDES-CBC" +#define NID_pbeWithMD2AndDES_CBC 9 +#define OBJ_pbeWithMD2AndDES_CBC OBJ_pkcs5,1L + +#define SN_pbeWithMD5AndDES_CBC "PBE-MD5-DES" +#define LN_pbeWithMD5AndDES_CBC "pbeWithMD5AndDES-CBC" +#define NID_pbeWithMD5AndDES_CBC 10 +#define OBJ_pbeWithMD5AndDES_CBC OBJ_pkcs5,3L + +#define SN_pbeWithMD2AndRC2_CBC "PBE-MD2-RC2-64" +#define LN_pbeWithMD2AndRC2_CBC "pbeWithMD2AndRC2-CBC" +#define NID_pbeWithMD2AndRC2_CBC 168 +#define OBJ_pbeWithMD2AndRC2_CBC OBJ_pkcs5,4L + +#define SN_pbeWithMD5AndRC2_CBC "PBE-MD5-RC2-64" +#define LN_pbeWithMD5AndRC2_CBC "pbeWithMD5AndRC2-CBC" +#define NID_pbeWithMD5AndRC2_CBC 169 +#define OBJ_pbeWithMD5AndRC2_CBC OBJ_pkcs5,6L + +#define SN_pbeWithSHA1AndDES_CBC "PBE-SHA1-DES" +#define LN_pbeWithSHA1AndDES_CBC "pbeWithSHA1AndDES-CBC" +#define NID_pbeWithSHA1AndDES_CBC 170 +#define OBJ_pbeWithSHA1AndDES_CBC OBJ_pkcs5,10L + +#define SN_pbeWithSHA1AndRC2_CBC "PBE-SHA1-RC2-64" +#define LN_pbeWithSHA1AndRC2_CBC "pbeWithSHA1AndRC2-CBC" +#define NID_pbeWithSHA1AndRC2_CBC 68 +#define OBJ_pbeWithSHA1AndRC2_CBC OBJ_pkcs5,11L + +#define LN_id_pbkdf2 "PBKDF2" +#define NID_id_pbkdf2 69 +#define OBJ_id_pbkdf2 OBJ_pkcs5,12L + +#define LN_pbes2 "PBES2" +#define NID_pbes2 161 +#define OBJ_pbes2 OBJ_pkcs5,13L + +#define LN_pbmac1 "PBMAC1" +#define NID_pbmac1 162 +#define OBJ_pbmac1 OBJ_pkcs5,14L + +#define SN_pkcs7 "pkcs7" +#define NID_pkcs7 20 +#define OBJ_pkcs7 OBJ_pkcs,7L + +#define LN_pkcs7_data "pkcs7-data" +#define NID_pkcs7_data 21 +#define OBJ_pkcs7_data OBJ_pkcs7,1L + +#define LN_pkcs7_signed "pkcs7-signedData" +#define NID_pkcs7_signed 22 +#define OBJ_pkcs7_signed OBJ_pkcs7,2L + +#define LN_pkcs7_enveloped "pkcs7-envelopedData" +#define NID_pkcs7_enveloped 23 +#define OBJ_pkcs7_enveloped OBJ_pkcs7,3L + +#define LN_pkcs7_signedAndEnveloped "pkcs7-signedAndEnvelopedData" +#define NID_pkcs7_signedAndEnveloped 24 +#define OBJ_pkcs7_signedAndEnveloped OBJ_pkcs7,4L + +#define LN_pkcs7_digest "pkcs7-digestData" +#define NID_pkcs7_digest 25 +#define OBJ_pkcs7_digest OBJ_pkcs7,5L + +#define LN_pkcs7_encrypted "pkcs7-encryptedData" +#define NID_pkcs7_encrypted 26 +#define OBJ_pkcs7_encrypted OBJ_pkcs7,6L + +#define SN_pkcs9 "pkcs9" +#define NID_pkcs9 47 +#define OBJ_pkcs9 OBJ_pkcs,9L + +#define LN_pkcs9_emailAddress "emailAddress" +#define NID_pkcs9_emailAddress 48 +#define OBJ_pkcs9_emailAddress OBJ_pkcs9,1L + +#define LN_pkcs9_unstructuredName "unstructuredName" +#define NID_pkcs9_unstructuredName 49 +#define OBJ_pkcs9_unstructuredName OBJ_pkcs9,2L + +#define LN_pkcs9_contentType "contentType" +#define NID_pkcs9_contentType 50 +#define OBJ_pkcs9_contentType OBJ_pkcs9,3L + +#define LN_pkcs9_messageDigest "messageDigest" +#define NID_pkcs9_messageDigest 51 +#define OBJ_pkcs9_messageDigest OBJ_pkcs9,4L + +#define LN_pkcs9_signingTime "signingTime" +#define NID_pkcs9_signingTime 52 +#define OBJ_pkcs9_signingTime OBJ_pkcs9,5L + +#define LN_pkcs9_countersignature "countersignature" +#define NID_pkcs9_countersignature 53 +#define OBJ_pkcs9_countersignature OBJ_pkcs9,6L + +#define LN_pkcs9_challengePassword "challengePassword" +#define NID_pkcs9_challengePassword 54 +#define OBJ_pkcs9_challengePassword OBJ_pkcs9,7L + +#define LN_pkcs9_unstructuredAddress "unstructuredAddress" +#define NID_pkcs9_unstructuredAddress 55 +#define OBJ_pkcs9_unstructuredAddress OBJ_pkcs9,8L + +#define LN_pkcs9_extCertAttributes "extendedCertificateAttributes" +#define NID_pkcs9_extCertAttributes 56 +#define OBJ_pkcs9_extCertAttributes OBJ_pkcs9,9L + +#define SN_ext_req "extReq" +#define LN_ext_req "Extension Request" +#define NID_ext_req 172 +#define OBJ_ext_req OBJ_pkcs9,14L + +#define SN_SMIMECapabilities "SMIME-CAPS" +#define LN_SMIMECapabilities "S/MIME Capabilities" +#define NID_SMIMECapabilities 167 +#define OBJ_SMIMECapabilities OBJ_pkcs9,15L + +#define SN_SMIME "SMIME" +#define LN_SMIME "S/MIME" +#define NID_SMIME 188 +#define OBJ_SMIME OBJ_pkcs9,16L + +#define SN_id_smime_mod "id-smime-mod" +#define NID_id_smime_mod 189 +#define OBJ_id_smime_mod OBJ_SMIME,0L + +#define SN_id_smime_ct "id-smime-ct" +#define NID_id_smime_ct 190 +#define OBJ_id_smime_ct OBJ_SMIME,1L + +#define SN_id_smime_aa "id-smime-aa" +#define NID_id_smime_aa 191 +#define OBJ_id_smime_aa OBJ_SMIME,2L + +#define SN_id_smime_alg "id-smime-alg" +#define NID_id_smime_alg 192 +#define OBJ_id_smime_alg OBJ_SMIME,3L + +#define SN_id_smime_cd "id-smime-cd" +#define NID_id_smime_cd 193 +#define OBJ_id_smime_cd OBJ_SMIME,4L + +#define SN_id_smime_spq "id-smime-spq" +#define NID_id_smime_spq 194 +#define OBJ_id_smime_spq OBJ_SMIME,5L + +#define SN_id_smime_cti "id-smime-cti" +#define NID_id_smime_cti 195 +#define OBJ_id_smime_cti OBJ_SMIME,6L + +#define SN_id_smime_mod_cms "id-smime-mod-cms" +#define NID_id_smime_mod_cms 196 +#define OBJ_id_smime_mod_cms OBJ_id_smime_mod,1L + +#define SN_id_smime_mod_ess "id-smime-mod-ess" +#define NID_id_smime_mod_ess 197 +#define OBJ_id_smime_mod_ess OBJ_id_smime_mod,2L + +#define SN_id_smime_mod_oid "id-smime-mod-oid" +#define NID_id_smime_mod_oid 198 +#define OBJ_id_smime_mod_oid OBJ_id_smime_mod,3L + +#define SN_id_smime_mod_msg_v3 "id-smime-mod-msg-v3" +#define NID_id_smime_mod_msg_v3 199 +#define OBJ_id_smime_mod_msg_v3 OBJ_id_smime_mod,4L + +#define SN_id_smime_mod_ets_eSignature_88 "id-smime-mod-ets-eSignature-88" +#define NID_id_smime_mod_ets_eSignature_88 200 +#define OBJ_id_smime_mod_ets_eSignature_88 OBJ_id_smime_mod,5L + +#define SN_id_smime_mod_ets_eSignature_97 "id-smime-mod-ets-eSignature-97" +#define NID_id_smime_mod_ets_eSignature_97 201 +#define OBJ_id_smime_mod_ets_eSignature_97 OBJ_id_smime_mod,6L + +#define SN_id_smime_mod_ets_eSigPolicy_88 "id-smime-mod-ets-eSigPolicy-88" +#define NID_id_smime_mod_ets_eSigPolicy_88 202 +#define OBJ_id_smime_mod_ets_eSigPolicy_88 OBJ_id_smime_mod,7L + +#define SN_id_smime_mod_ets_eSigPolicy_97 "id-smime-mod-ets-eSigPolicy-97" +#define NID_id_smime_mod_ets_eSigPolicy_97 203 +#define OBJ_id_smime_mod_ets_eSigPolicy_97 OBJ_id_smime_mod,8L + +#define SN_id_smime_ct_receipt "id-smime-ct-receipt" +#define NID_id_smime_ct_receipt 204 +#define OBJ_id_smime_ct_receipt OBJ_id_smime_ct,1L + +#define SN_id_smime_ct_authData "id-smime-ct-authData" +#define NID_id_smime_ct_authData 205 +#define OBJ_id_smime_ct_authData OBJ_id_smime_ct,2L + +#define SN_id_smime_ct_publishCert "id-smime-ct-publishCert" +#define NID_id_smime_ct_publishCert 206 +#define OBJ_id_smime_ct_publishCert OBJ_id_smime_ct,3L + +#define SN_id_smime_ct_TSTInfo "id-smime-ct-TSTInfo" +#define NID_id_smime_ct_TSTInfo 207 +#define OBJ_id_smime_ct_TSTInfo OBJ_id_smime_ct,4L + +#define SN_id_smime_ct_TDTInfo "id-smime-ct-TDTInfo" +#define NID_id_smime_ct_TDTInfo 208 +#define OBJ_id_smime_ct_TDTInfo OBJ_id_smime_ct,5L + +#define SN_id_smime_ct_contentInfo "id-smime-ct-contentInfo" +#define NID_id_smime_ct_contentInfo 209 +#define OBJ_id_smime_ct_contentInfo OBJ_id_smime_ct,6L + +#define SN_id_smime_ct_DVCSRequestData "id-smime-ct-DVCSRequestData" +#define NID_id_smime_ct_DVCSRequestData 210 +#define OBJ_id_smime_ct_DVCSRequestData OBJ_id_smime_ct,7L + +#define SN_id_smime_ct_DVCSResponseData "id-smime-ct-DVCSResponseData" +#define NID_id_smime_ct_DVCSResponseData 211 +#define OBJ_id_smime_ct_DVCSResponseData OBJ_id_smime_ct,8L + +#define SN_id_smime_ct_compressedData "id-smime-ct-compressedData" +#define NID_id_smime_ct_compressedData 786 +#define OBJ_id_smime_ct_compressedData OBJ_id_smime_ct,9L + +#define SN_id_smime_ct_contentCollection "id-smime-ct-contentCollection" +#define NID_id_smime_ct_contentCollection 1058 +#define OBJ_id_smime_ct_contentCollection OBJ_id_smime_ct,19L + +#define SN_id_smime_ct_authEnvelopedData "id-smime-ct-authEnvelopedData" +#define NID_id_smime_ct_authEnvelopedData 1059 +#define OBJ_id_smime_ct_authEnvelopedData OBJ_id_smime_ct,23L + +#define SN_id_ct_asciiTextWithCRLF "id-ct-asciiTextWithCRLF" +#define NID_id_ct_asciiTextWithCRLF 787 +#define OBJ_id_ct_asciiTextWithCRLF OBJ_id_smime_ct,27L + +#define SN_id_ct_xml "id-ct-xml" +#define NID_id_ct_xml 1060 +#define OBJ_id_ct_xml OBJ_id_smime_ct,28L + +#define SN_id_smime_aa_receiptRequest "id-smime-aa-receiptRequest" +#define NID_id_smime_aa_receiptRequest 212 +#define OBJ_id_smime_aa_receiptRequest OBJ_id_smime_aa,1L + +#define SN_id_smime_aa_securityLabel "id-smime-aa-securityLabel" +#define NID_id_smime_aa_securityLabel 213 +#define OBJ_id_smime_aa_securityLabel OBJ_id_smime_aa,2L + +#define SN_id_smime_aa_mlExpandHistory "id-smime-aa-mlExpandHistory" +#define NID_id_smime_aa_mlExpandHistory 214 +#define OBJ_id_smime_aa_mlExpandHistory OBJ_id_smime_aa,3L + +#define SN_id_smime_aa_contentHint "id-smime-aa-contentHint" +#define NID_id_smime_aa_contentHint 215 +#define OBJ_id_smime_aa_contentHint OBJ_id_smime_aa,4L + +#define SN_id_smime_aa_msgSigDigest "id-smime-aa-msgSigDigest" +#define NID_id_smime_aa_msgSigDigest 216 +#define OBJ_id_smime_aa_msgSigDigest OBJ_id_smime_aa,5L + +#define SN_id_smime_aa_encapContentType "id-smime-aa-encapContentType" +#define NID_id_smime_aa_encapContentType 217 +#define OBJ_id_smime_aa_encapContentType OBJ_id_smime_aa,6L + +#define SN_id_smime_aa_contentIdentifier "id-smime-aa-contentIdentifier" +#define NID_id_smime_aa_contentIdentifier 218 +#define OBJ_id_smime_aa_contentIdentifier OBJ_id_smime_aa,7L + +#define SN_id_smime_aa_macValue "id-smime-aa-macValue" +#define NID_id_smime_aa_macValue 219 +#define OBJ_id_smime_aa_macValue OBJ_id_smime_aa,8L + +#define SN_id_smime_aa_equivalentLabels "id-smime-aa-equivalentLabels" +#define NID_id_smime_aa_equivalentLabels 220 +#define OBJ_id_smime_aa_equivalentLabels OBJ_id_smime_aa,9L + +#define SN_id_smime_aa_contentReference "id-smime-aa-contentReference" +#define NID_id_smime_aa_contentReference 221 +#define OBJ_id_smime_aa_contentReference OBJ_id_smime_aa,10L + +#define SN_id_smime_aa_encrypKeyPref "id-smime-aa-encrypKeyPref" +#define NID_id_smime_aa_encrypKeyPref 222 +#define OBJ_id_smime_aa_encrypKeyPref OBJ_id_smime_aa,11L + +#define SN_id_smime_aa_signingCertificate "id-smime-aa-signingCertificate" +#define NID_id_smime_aa_signingCertificate 223 +#define OBJ_id_smime_aa_signingCertificate OBJ_id_smime_aa,12L + +#define SN_id_smime_aa_smimeEncryptCerts "id-smime-aa-smimeEncryptCerts" +#define NID_id_smime_aa_smimeEncryptCerts 224 +#define OBJ_id_smime_aa_smimeEncryptCerts OBJ_id_smime_aa,13L + +#define SN_id_smime_aa_timeStampToken "id-smime-aa-timeStampToken" +#define NID_id_smime_aa_timeStampToken 225 +#define OBJ_id_smime_aa_timeStampToken OBJ_id_smime_aa,14L + +#define SN_id_smime_aa_ets_sigPolicyId "id-smime-aa-ets-sigPolicyId" +#define NID_id_smime_aa_ets_sigPolicyId 226 +#define OBJ_id_smime_aa_ets_sigPolicyId OBJ_id_smime_aa,15L + +#define SN_id_smime_aa_ets_commitmentType "id-smime-aa-ets-commitmentType" +#define NID_id_smime_aa_ets_commitmentType 227 +#define OBJ_id_smime_aa_ets_commitmentType OBJ_id_smime_aa,16L + +#define SN_id_smime_aa_ets_signerLocation "id-smime-aa-ets-signerLocation" +#define NID_id_smime_aa_ets_signerLocation 228 +#define OBJ_id_smime_aa_ets_signerLocation OBJ_id_smime_aa,17L + +#define SN_id_smime_aa_ets_signerAttr "id-smime-aa-ets-signerAttr" +#define NID_id_smime_aa_ets_signerAttr 229 +#define OBJ_id_smime_aa_ets_signerAttr OBJ_id_smime_aa,18L + +#define SN_id_smime_aa_ets_otherSigCert "id-smime-aa-ets-otherSigCert" +#define NID_id_smime_aa_ets_otherSigCert 230 +#define OBJ_id_smime_aa_ets_otherSigCert OBJ_id_smime_aa,19L + +#define SN_id_smime_aa_ets_contentTimestamp "id-smime-aa-ets-contentTimestamp" +#define NID_id_smime_aa_ets_contentTimestamp 231 +#define OBJ_id_smime_aa_ets_contentTimestamp OBJ_id_smime_aa,20L + +#define SN_id_smime_aa_ets_CertificateRefs "id-smime-aa-ets-CertificateRefs" +#define NID_id_smime_aa_ets_CertificateRefs 232 +#define OBJ_id_smime_aa_ets_CertificateRefs OBJ_id_smime_aa,21L + +#define SN_id_smime_aa_ets_RevocationRefs "id-smime-aa-ets-RevocationRefs" +#define NID_id_smime_aa_ets_RevocationRefs 233 +#define OBJ_id_smime_aa_ets_RevocationRefs OBJ_id_smime_aa,22L + +#define SN_id_smime_aa_ets_certValues "id-smime-aa-ets-certValues" +#define NID_id_smime_aa_ets_certValues 234 +#define OBJ_id_smime_aa_ets_certValues OBJ_id_smime_aa,23L + +#define SN_id_smime_aa_ets_revocationValues "id-smime-aa-ets-revocationValues" +#define NID_id_smime_aa_ets_revocationValues 235 +#define OBJ_id_smime_aa_ets_revocationValues OBJ_id_smime_aa,24L + +#define SN_id_smime_aa_ets_escTimeStamp "id-smime-aa-ets-escTimeStamp" +#define NID_id_smime_aa_ets_escTimeStamp 236 +#define OBJ_id_smime_aa_ets_escTimeStamp OBJ_id_smime_aa,25L + +#define SN_id_smime_aa_ets_certCRLTimestamp "id-smime-aa-ets-certCRLTimestamp" +#define NID_id_smime_aa_ets_certCRLTimestamp 237 +#define OBJ_id_smime_aa_ets_certCRLTimestamp OBJ_id_smime_aa,26L + +#define SN_id_smime_aa_ets_archiveTimeStamp "id-smime-aa-ets-archiveTimeStamp" +#define NID_id_smime_aa_ets_archiveTimeStamp 238 +#define OBJ_id_smime_aa_ets_archiveTimeStamp OBJ_id_smime_aa,27L + +#define SN_id_smime_aa_signatureType "id-smime-aa-signatureType" +#define NID_id_smime_aa_signatureType 239 +#define OBJ_id_smime_aa_signatureType OBJ_id_smime_aa,28L + +#define SN_id_smime_aa_dvcs_dvc "id-smime-aa-dvcs-dvc" +#define NID_id_smime_aa_dvcs_dvc 240 +#define OBJ_id_smime_aa_dvcs_dvc OBJ_id_smime_aa,29L + +#define SN_id_smime_aa_signingCertificateV2 "id-smime-aa-signingCertificateV2" +#define NID_id_smime_aa_signingCertificateV2 1086 +#define OBJ_id_smime_aa_signingCertificateV2 OBJ_id_smime_aa,47L + +#define SN_id_smime_alg_ESDHwith3DES "id-smime-alg-ESDHwith3DES" +#define NID_id_smime_alg_ESDHwith3DES 241 +#define OBJ_id_smime_alg_ESDHwith3DES OBJ_id_smime_alg,1L + +#define SN_id_smime_alg_ESDHwithRC2 "id-smime-alg-ESDHwithRC2" +#define NID_id_smime_alg_ESDHwithRC2 242 +#define OBJ_id_smime_alg_ESDHwithRC2 OBJ_id_smime_alg,2L + +#define SN_id_smime_alg_3DESwrap "id-smime-alg-3DESwrap" +#define NID_id_smime_alg_3DESwrap 243 +#define OBJ_id_smime_alg_3DESwrap OBJ_id_smime_alg,3L + +#define SN_id_smime_alg_RC2wrap "id-smime-alg-RC2wrap" +#define NID_id_smime_alg_RC2wrap 244 +#define OBJ_id_smime_alg_RC2wrap OBJ_id_smime_alg,4L + +#define SN_id_smime_alg_ESDH "id-smime-alg-ESDH" +#define NID_id_smime_alg_ESDH 245 +#define OBJ_id_smime_alg_ESDH OBJ_id_smime_alg,5L + +#define SN_id_smime_alg_CMS3DESwrap "id-smime-alg-CMS3DESwrap" +#define NID_id_smime_alg_CMS3DESwrap 246 +#define OBJ_id_smime_alg_CMS3DESwrap OBJ_id_smime_alg,6L + +#define SN_id_smime_alg_CMSRC2wrap "id-smime-alg-CMSRC2wrap" +#define NID_id_smime_alg_CMSRC2wrap 247 +#define OBJ_id_smime_alg_CMSRC2wrap OBJ_id_smime_alg,7L + +#define SN_id_alg_PWRI_KEK "id-alg-PWRI-KEK" +#define NID_id_alg_PWRI_KEK 893 +#define OBJ_id_alg_PWRI_KEK OBJ_id_smime_alg,9L + +#define SN_id_smime_cd_ldap "id-smime-cd-ldap" +#define NID_id_smime_cd_ldap 248 +#define OBJ_id_smime_cd_ldap OBJ_id_smime_cd,1L + +#define SN_id_smime_spq_ets_sqt_uri "id-smime-spq-ets-sqt-uri" +#define NID_id_smime_spq_ets_sqt_uri 249 +#define OBJ_id_smime_spq_ets_sqt_uri OBJ_id_smime_spq,1L + +#define SN_id_smime_spq_ets_sqt_unotice "id-smime-spq-ets-sqt-unotice" +#define NID_id_smime_spq_ets_sqt_unotice 250 +#define OBJ_id_smime_spq_ets_sqt_unotice OBJ_id_smime_spq,2L + +#define SN_id_smime_cti_ets_proofOfOrigin "id-smime-cti-ets-proofOfOrigin" +#define NID_id_smime_cti_ets_proofOfOrigin 251 +#define OBJ_id_smime_cti_ets_proofOfOrigin OBJ_id_smime_cti,1L + +#define SN_id_smime_cti_ets_proofOfReceipt "id-smime-cti-ets-proofOfReceipt" +#define NID_id_smime_cti_ets_proofOfReceipt 252 +#define OBJ_id_smime_cti_ets_proofOfReceipt OBJ_id_smime_cti,2L + +#define SN_id_smime_cti_ets_proofOfDelivery "id-smime-cti-ets-proofOfDelivery" +#define NID_id_smime_cti_ets_proofOfDelivery 253 +#define OBJ_id_smime_cti_ets_proofOfDelivery OBJ_id_smime_cti,3L + +#define SN_id_smime_cti_ets_proofOfSender "id-smime-cti-ets-proofOfSender" +#define NID_id_smime_cti_ets_proofOfSender 254 +#define OBJ_id_smime_cti_ets_proofOfSender OBJ_id_smime_cti,4L + +#define SN_id_smime_cti_ets_proofOfApproval "id-smime-cti-ets-proofOfApproval" +#define NID_id_smime_cti_ets_proofOfApproval 255 +#define OBJ_id_smime_cti_ets_proofOfApproval OBJ_id_smime_cti,5L + +#define SN_id_smime_cti_ets_proofOfCreation "id-smime-cti-ets-proofOfCreation" +#define NID_id_smime_cti_ets_proofOfCreation 256 +#define OBJ_id_smime_cti_ets_proofOfCreation OBJ_id_smime_cti,6L + +#define LN_friendlyName "friendlyName" +#define NID_friendlyName 156 +#define OBJ_friendlyName OBJ_pkcs9,20L + +#define LN_localKeyID "localKeyID" +#define NID_localKeyID 157 +#define OBJ_localKeyID OBJ_pkcs9,21L + +#define SN_ms_csp_name "CSPName" +#define LN_ms_csp_name "Microsoft CSP Name" +#define NID_ms_csp_name 417 +#define OBJ_ms_csp_name 1L,3L,6L,1L,4L,1L,311L,17L,1L + +#define SN_LocalKeySet "LocalKeySet" +#define LN_LocalKeySet "Microsoft Local Key set" +#define NID_LocalKeySet 856 +#define OBJ_LocalKeySet 1L,3L,6L,1L,4L,1L,311L,17L,2L + +#define OBJ_certTypes OBJ_pkcs9,22L + +#define LN_x509Certificate "x509Certificate" +#define NID_x509Certificate 158 +#define OBJ_x509Certificate OBJ_certTypes,1L + +#define LN_sdsiCertificate "sdsiCertificate" +#define NID_sdsiCertificate 159 +#define OBJ_sdsiCertificate OBJ_certTypes,2L + +#define OBJ_crlTypes OBJ_pkcs9,23L + +#define LN_x509Crl "x509Crl" +#define NID_x509Crl 160 +#define OBJ_x509Crl OBJ_crlTypes,1L + +#define OBJ_pkcs12 OBJ_pkcs,12L + +#define OBJ_pkcs12_pbeids OBJ_pkcs12,1L + +#define SN_pbe_WithSHA1And128BitRC4 "PBE-SHA1-RC4-128" +#define LN_pbe_WithSHA1And128BitRC4 "pbeWithSHA1And128BitRC4" +#define NID_pbe_WithSHA1And128BitRC4 144 +#define OBJ_pbe_WithSHA1And128BitRC4 OBJ_pkcs12_pbeids,1L + +#define SN_pbe_WithSHA1And40BitRC4 "PBE-SHA1-RC4-40" +#define LN_pbe_WithSHA1And40BitRC4 "pbeWithSHA1And40BitRC4" +#define NID_pbe_WithSHA1And40BitRC4 145 +#define OBJ_pbe_WithSHA1And40BitRC4 OBJ_pkcs12_pbeids,2L + +#define SN_pbe_WithSHA1And3_Key_TripleDES_CBC "PBE-SHA1-3DES" +#define LN_pbe_WithSHA1And3_Key_TripleDES_CBC "pbeWithSHA1And3-KeyTripleDES-CBC" +#define NID_pbe_WithSHA1And3_Key_TripleDES_CBC 146 +#define OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC OBJ_pkcs12_pbeids,3L + +#define SN_pbe_WithSHA1And2_Key_TripleDES_CBC "PBE-SHA1-2DES" +#define LN_pbe_WithSHA1And2_Key_TripleDES_CBC "pbeWithSHA1And2-KeyTripleDES-CBC" +#define NID_pbe_WithSHA1And2_Key_TripleDES_CBC 147 +#define OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC OBJ_pkcs12_pbeids,4L + +#define SN_pbe_WithSHA1And128BitRC2_CBC "PBE-SHA1-RC2-128" +#define LN_pbe_WithSHA1And128BitRC2_CBC "pbeWithSHA1And128BitRC2-CBC" +#define NID_pbe_WithSHA1And128BitRC2_CBC 148 +#define OBJ_pbe_WithSHA1And128BitRC2_CBC OBJ_pkcs12_pbeids,5L + +#define SN_pbe_WithSHA1And40BitRC2_CBC "PBE-SHA1-RC2-40" +#define LN_pbe_WithSHA1And40BitRC2_CBC "pbeWithSHA1And40BitRC2-CBC" +#define NID_pbe_WithSHA1And40BitRC2_CBC 149 +#define OBJ_pbe_WithSHA1And40BitRC2_CBC OBJ_pkcs12_pbeids,6L + +#define OBJ_pkcs12_Version1 OBJ_pkcs12,10L + +#define OBJ_pkcs12_BagIds OBJ_pkcs12_Version1,1L + +#define LN_keyBag "keyBag" +#define NID_keyBag 150 +#define OBJ_keyBag OBJ_pkcs12_BagIds,1L + +#define LN_pkcs8ShroudedKeyBag "pkcs8ShroudedKeyBag" +#define NID_pkcs8ShroudedKeyBag 151 +#define OBJ_pkcs8ShroudedKeyBag OBJ_pkcs12_BagIds,2L + +#define LN_certBag "certBag" +#define NID_certBag 152 +#define OBJ_certBag OBJ_pkcs12_BagIds,3L + +#define LN_crlBag "crlBag" +#define NID_crlBag 153 +#define OBJ_crlBag OBJ_pkcs12_BagIds,4L + +#define LN_secretBag "secretBag" +#define NID_secretBag 154 +#define OBJ_secretBag OBJ_pkcs12_BagIds,5L + +#define LN_safeContentsBag "safeContentsBag" +#define NID_safeContentsBag 155 +#define OBJ_safeContentsBag OBJ_pkcs12_BagIds,6L + +#define SN_md2 "MD2" +#define LN_md2 "md2" +#define NID_md2 3 +#define OBJ_md2 OBJ_rsadsi,2L,2L + +#define SN_md4 "MD4" +#define LN_md4 "md4" +#define NID_md4 257 +#define OBJ_md4 OBJ_rsadsi,2L,4L + +#define SN_md5 "MD5" +#define LN_md5 "md5" +#define NID_md5 4 +#define OBJ_md5 OBJ_rsadsi,2L,5L + +#define SN_md5_sha1 "MD5-SHA1" +#define LN_md5_sha1 "md5-sha1" +#define NID_md5_sha1 114 + +#define LN_hmacWithMD5 "hmacWithMD5" +#define NID_hmacWithMD5 797 +#define OBJ_hmacWithMD5 OBJ_rsadsi,2L,6L + +#define LN_hmacWithSHA1 "hmacWithSHA1" +#define NID_hmacWithSHA1 163 +#define OBJ_hmacWithSHA1 OBJ_rsadsi,2L,7L + +#define SN_sm2 "SM2" +#define LN_sm2 "sm2" +#define NID_sm2 1172 +#define OBJ_sm2 OBJ_sm_scheme,301L + +#define SN_sm3 "SM3" +#define LN_sm3 "sm3" +#define NID_sm3 1143 +#define OBJ_sm3 OBJ_sm_scheme,401L + +#define SN_sm3WithRSAEncryption "RSA-SM3" +#define LN_sm3WithRSAEncryption "sm3WithRSAEncryption" +#define NID_sm3WithRSAEncryption 1144 +#define OBJ_sm3WithRSAEncryption OBJ_sm_scheme,504L + +#define LN_hmacWithSHA224 "hmacWithSHA224" +#define NID_hmacWithSHA224 798 +#define OBJ_hmacWithSHA224 OBJ_rsadsi,2L,8L + +#define LN_hmacWithSHA256 "hmacWithSHA256" +#define NID_hmacWithSHA256 799 +#define OBJ_hmacWithSHA256 OBJ_rsadsi,2L,9L + +#define LN_hmacWithSHA384 "hmacWithSHA384" +#define NID_hmacWithSHA384 800 +#define OBJ_hmacWithSHA384 OBJ_rsadsi,2L,10L + +#define LN_hmacWithSHA512 "hmacWithSHA512" +#define NID_hmacWithSHA512 801 +#define OBJ_hmacWithSHA512 OBJ_rsadsi,2L,11L + +#define LN_hmacWithSHA512_224 "hmacWithSHA512-224" +#define NID_hmacWithSHA512_224 1193 +#define OBJ_hmacWithSHA512_224 OBJ_rsadsi,2L,12L + +#define LN_hmacWithSHA512_256 "hmacWithSHA512-256" +#define NID_hmacWithSHA512_256 1194 +#define OBJ_hmacWithSHA512_256 OBJ_rsadsi,2L,13L + +#define SN_rc2_cbc "RC2-CBC" +#define LN_rc2_cbc "rc2-cbc" +#define NID_rc2_cbc 37 +#define OBJ_rc2_cbc OBJ_rsadsi,3L,2L + +#define SN_rc2_ecb "RC2-ECB" +#define LN_rc2_ecb "rc2-ecb" +#define NID_rc2_ecb 38 + +#define SN_rc2_cfb64 "RC2-CFB" +#define LN_rc2_cfb64 "rc2-cfb" +#define NID_rc2_cfb64 39 + +#define SN_rc2_ofb64 "RC2-OFB" +#define LN_rc2_ofb64 "rc2-ofb" +#define NID_rc2_ofb64 40 + +#define SN_rc2_40_cbc "RC2-40-CBC" +#define LN_rc2_40_cbc "rc2-40-cbc" +#define NID_rc2_40_cbc 98 + +#define SN_rc2_64_cbc "RC2-64-CBC" +#define LN_rc2_64_cbc "rc2-64-cbc" +#define NID_rc2_64_cbc 166 + +#define SN_rc4 "RC4" +#define LN_rc4 "rc4" +#define NID_rc4 5 +#define OBJ_rc4 OBJ_rsadsi,3L,4L + +#define SN_rc4_40 "RC4-40" +#define LN_rc4_40 "rc4-40" +#define NID_rc4_40 97 + +#define SN_des_ede3_cbc "DES-EDE3-CBC" +#define LN_des_ede3_cbc "des-ede3-cbc" +#define NID_des_ede3_cbc 44 +#define OBJ_des_ede3_cbc OBJ_rsadsi,3L,7L + +#define SN_rc5_cbc "RC5-CBC" +#define LN_rc5_cbc "rc5-cbc" +#define NID_rc5_cbc 120 +#define OBJ_rc5_cbc OBJ_rsadsi,3L,8L + +#define SN_rc5_ecb "RC5-ECB" +#define LN_rc5_ecb "rc5-ecb" +#define NID_rc5_ecb 121 + +#define SN_rc5_cfb64 "RC5-CFB" +#define LN_rc5_cfb64 "rc5-cfb" +#define NID_rc5_cfb64 122 + +#define SN_rc5_ofb64 "RC5-OFB" +#define LN_rc5_ofb64 "rc5-ofb" +#define NID_rc5_ofb64 123 + +#define SN_ms_ext_req "msExtReq" +#define LN_ms_ext_req "Microsoft Extension Request" +#define NID_ms_ext_req 171 +#define OBJ_ms_ext_req 1L,3L,6L,1L,4L,1L,311L,2L,1L,14L + +#define SN_ms_code_ind "msCodeInd" +#define LN_ms_code_ind "Microsoft Individual Code Signing" +#define NID_ms_code_ind 134 +#define OBJ_ms_code_ind 1L,3L,6L,1L,4L,1L,311L,2L,1L,21L + +#define SN_ms_code_com "msCodeCom" +#define LN_ms_code_com "Microsoft Commercial Code Signing" +#define NID_ms_code_com 135 +#define OBJ_ms_code_com 1L,3L,6L,1L,4L,1L,311L,2L,1L,22L + +#define SN_ms_ctl_sign "msCTLSign" +#define LN_ms_ctl_sign "Microsoft Trust List Signing" +#define NID_ms_ctl_sign 136 +#define OBJ_ms_ctl_sign 1L,3L,6L,1L,4L,1L,311L,10L,3L,1L + +#define SN_ms_sgc "msSGC" +#define LN_ms_sgc "Microsoft Server Gated Crypto" +#define NID_ms_sgc 137 +#define OBJ_ms_sgc 1L,3L,6L,1L,4L,1L,311L,10L,3L,3L + +#define SN_ms_efs "msEFS" +#define LN_ms_efs "Microsoft Encrypted File System" +#define NID_ms_efs 138 +#define OBJ_ms_efs 1L,3L,6L,1L,4L,1L,311L,10L,3L,4L + +#define SN_ms_smartcard_login "msSmartcardLogin" +#define LN_ms_smartcard_login "Microsoft Smartcardlogin" +#define NID_ms_smartcard_login 648 +#define OBJ_ms_smartcard_login 1L,3L,6L,1L,4L,1L,311L,20L,2L,2L + +#define SN_ms_upn "msUPN" +#define LN_ms_upn "Microsoft Universal Principal Name" +#define NID_ms_upn 649 +#define OBJ_ms_upn 1L,3L,6L,1L,4L,1L,311L,20L,2L,3L + +#define SN_idea_cbc "IDEA-CBC" +#define LN_idea_cbc "idea-cbc" +#define NID_idea_cbc 34 +#define OBJ_idea_cbc 1L,3L,6L,1L,4L,1L,188L,7L,1L,1L,2L + +#define SN_idea_ecb "IDEA-ECB" +#define LN_idea_ecb "idea-ecb" +#define NID_idea_ecb 36 + +#define SN_idea_cfb64 "IDEA-CFB" +#define LN_idea_cfb64 "idea-cfb" +#define NID_idea_cfb64 35 + +#define SN_idea_ofb64 "IDEA-OFB" +#define LN_idea_ofb64 "idea-ofb" +#define NID_idea_ofb64 46 + +#define SN_bf_cbc "BF-CBC" +#define LN_bf_cbc "bf-cbc" +#define NID_bf_cbc 91 +#define OBJ_bf_cbc 1L,3L,6L,1L,4L,1L,3029L,1L,2L + +#define SN_bf_ecb "BF-ECB" +#define LN_bf_ecb "bf-ecb" +#define NID_bf_ecb 92 + +#define SN_bf_cfb64 "BF-CFB" +#define LN_bf_cfb64 "bf-cfb" +#define NID_bf_cfb64 93 + +#define SN_bf_ofb64 "BF-OFB" +#define LN_bf_ofb64 "bf-ofb" +#define NID_bf_ofb64 94 + +#define SN_id_pkix "PKIX" +#define NID_id_pkix 127 +#define OBJ_id_pkix 1L,3L,6L,1L,5L,5L,7L + +#define SN_id_pkix_mod "id-pkix-mod" +#define NID_id_pkix_mod 258 +#define OBJ_id_pkix_mod OBJ_id_pkix,0L + +#define SN_id_pe "id-pe" +#define NID_id_pe 175 +#define OBJ_id_pe OBJ_id_pkix,1L + +#define SN_id_qt "id-qt" +#define NID_id_qt 259 +#define OBJ_id_qt OBJ_id_pkix,2L + +#define SN_id_kp "id-kp" +#define NID_id_kp 128 +#define OBJ_id_kp OBJ_id_pkix,3L + +#define SN_id_it "id-it" +#define NID_id_it 260 +#define OBJ_id_it OBJ_id_pkix,4L + +#define SN_id_pkip "id-pkip" +#define NID_id_pkip 261 +#define OBJ_id_pkip OBJ_id_pkix,5L + +#define SN_id_alg "id-alg" +#define NID_id_alg 262 +#define OBJ_id_alg OBJ_id_pkix,6L + +#define SN_id_cmc "id-cmc" +#define NID_id_cmc 263 +#define OBJ_id_cmc OBJ_id_pkix,7L + +#define SN_id_on "id-on" +#define NID_id_on 264 +#define OBJ_id_on OBJ_id_pkix,8L + +#define SN_id_pda "id-pda" +#define NID_id_pda 265 +#define OBJ_id_pda OBJ_id_pkix,9L + +#define SN_id_aca "id-aca" +#define NID_id_aca 266 +#define OBJ_id_aca OBJ_id_pkix,10L + +#define SN_id_qcs "id-qcs" +#define NID_id_qcs 267 +#define OBJ_id_qcs OBJ_id_pkix,11L + +#define SN_id_cct "id-cct" +#define NID_id_cct 268 +#define OBJ_id_cct OBJ_id_pkix,12L + +#define SN_id_ppl "id-ppl" +#define NID_id_ppl 662 +#define OBJ_id_ppl OBJ_id_pkix,21L + +#define SN_id_ad "id-ad" +#define NID_id_ad 176 +#define OBJ_id_ad OBJ_id_pkix,48L + +#define SN_id_pkix1_explicit_88 "id-pkix1-explicit-88" +#define NID_id_pkix1_explicit_88 269 +#define OBJ_id_pkix1_explicit_88 OBJ_id_pkix_mod,1L + +#define SN_id_pkix1_implicit_88 "id-pkix1-implicit-88" +#define NID_id_pkix1_implicit_88 270 +#define OBJ_id_pkix1_implicit_88 OBJ_id_pkix_mod,2L + +#define SN_id_pkix1_explicit_93 "id-pkix1-explicit-93" +#define NID_id_pkix1_explicit_93 271 +#define OBJ_id_pkix1_explicit_93 OBJ_id_pkix_mod,3L + +#define SN_id_pkix1_implicit_93 "id-pkix1-implicit-93" +#define NID_id_pkix1_implicit_93 272 +#define OBJ_id_pkix1_implicit_93 OBJ_id_pkix_mod,4L + +#define SN_id_mod_crmf "id-mod-crmf" +#define NID_id_mod_crmf 273 +#define OBJ_id_mod_crmf OBJ_id_pkix_mod,5L + +#define SN_id_mod_cmc "id-mod-cmc" +#define NID_id_mod_cmc 274 +#define OBJ_id_mod_cmc OBJ_id_pkix_mod,6L + +#define SN_id_mod_kea_profile_88 "id-mod-kea-profile-88" +#define NID_id_mod_kea_profile_88 275 +#define OBJ_id_mod_kea_profile_88 OBJ_id_pkix_mod,7L + +#define SN_id_mod_kea_profile_93 "id-mod-kea-profile-93" +#define NID_id_mod_kea_profile_93 276 +#define OBJ_id_mod_kea_profile_93 OBJ_id_pkix_mod,8L + +#define SN_id_mod_cmp "id-mod-cmp" +#define NID_id_mod_cmp 277 +#define OBJ_id_mod_cmp OBJ_id_pkix_mod,9L + +#define SN_id_mod_qualified_cert_88 "id-mod-qualified-cert-88" +#define NID_id_mod_qualified_cert_88 278 +#define OBJ_id_mod_qualified_cert_88 OBJ_id_pkix_mod,10L + +#define SN_id_mod_qualified_cert_93 "id-mod-qualified-cert-93" +#define NID_id_mod_qualified_cert_93 279 +#define OBJ_id_mod_qualified_cert_93 OBJ_id_pkix_mod,11L + +#define SN_id_mod_attribute_cert "id-mod-attribute-cert" +#define NID_id_mod_attribute_cert 280 +#define OBJ_id_mod_attribute_cert OBJ_id_pkix_mod,12L + +#define SN_id_mod_timestamp_protocol "id-mod-timestamp-protocol" +#define NID_id_mod_timestamp_protocol 281 +#define OBJ_id_mod_timestamp_protocol OBJ_id_pkix_mod,13L + +#define SN_id_mod_ocsp "id-mod-ocsp" +#define NID_id_mod_ocsp 282 +#define OBJ_id_mod_ocsp OBJ_id_pkix_mod,14L + +#define SN_id_mod_dvcs "id-mod-dvcs" +#define NID_id_mod_dvcs 283 +#define OBJ_id_mod_dvcs OBJ_id_pkix_mod,15L + +#define SN_id_mod_cmp2000 "id-mod-cmp2000" +#define NID_id_mod_cmp2000 284 +#define OBJ_id_mod_cmp2000 OBJ_id_pkix_mod,16L + +#define SN_info_access "authorityInfoAccess" +#define LN_info_access "Authority Information Access" +#define NID_info_access 177 +#define OBJ_info_access OBJ_id_pe,1L + +#define SN_biometricInfo "biometricInfo" +#define LN_biometricInfo "Biometric Info" +#define NID_biometricInfo 285 +#define OBJ_biometricInfo OBJ_id_pe,2L + +#define SN_qcStatements "qcStatements" +#define NID_qcStatements 286 +#define OBJ_qcStatements OBJ_id_pe,3L + +#define SN_ac_auditEntity "ac-auditEntity" +#define NID_ac_auditEntity 287 +#define OBJ_ac_auditEntity OBJ_id_pe,4L + +#define SN_ac_targeting "ac-targeting" +#define NID_ac_targeting 288 +#define OBJ_ac_targeting OBJ_id_pe,5L + +#define SN_aaControls "aaControls" +#define NID_aaControls 289 +#define OBJ_aaControls OBJ_id_pe,6L + +#define SN_sbgp_ipAddrBlock "sbgp-ipAddrBlock" +#define NID_sbgp_ipAddrBlock 290 +#define OBJ_sbgp_ipAddrBlock OBJ_id_pe,7L + +#define SN_sbgp_autonomousSysNum "sbgp-autonomousSysNum" +#define NID_sbgp_autonomousSysNum 291 +#define OBJ_sbgp_autonomousSysNum OBJ_id_pe,8L + +#define SN_sbgp_routerIdentifier "sbgp-routerIdentifier" +#define NID_sbgp_routerIdentifier 292 +#define OBJ_sbgp_routerIdentifier OBJ_id_pe,9L + +#define SN_ac_proxying "ac-proxying" +#define NID_ac_proxying 397 +#define OBJ_ac_proxying OBJ_id_pe,10L + +#define SN_sinfo_access "subjectInfoAccess" +#define LN_sinfo_access "Subject Information Access" +#define NID_sinfo_access 398 +#define OBJ_sinfo_access OBJ_id_pe,11L + +#define SN_proxyCertInfo "proxyCertInfo" +#define LN_proxyCertInfo "Proxy Certificate Information" +#define NID_proxyCertInfo 663 +#define OBJ_proxyCertInfo OBJ_id_pe,14L + +#define SN_tlsfeature "tlsfeature" +#define LN_tlsfeature "TLS Feature" +#define NID_tlsfeature 1020 +#define OBJ_tlsfeature OBJ_id_pe,24L + +#define SN_id_qt_cps "id-qt-cps" +#define LN_id_qt_cps "Policy Qualifier CPS" +#define NID_id_qt_cps 164 +#define OBJ_id_qt_cps OBJ_id_qt,1L + +#define SN_id_qt_unotice "id-qt-unotice" +#define LN_id_qt_unotice "Policy Qualifier User Notice" +#define NID_id_qt_unotice 165 +#define OBJ_id_qt_unotice OBJ_id_qt,2L + +#define SN_textNotice "textNotice" +#define NID_textNotice 293 +#define OBJ_textNotice OBJ_id_qt,3L + +#define SN_server_auth "serverAuth" +#define LN_server_auth "TLS Web Server Authentication" +#define NID_server_auth 129 +#define OBJ_server_auth OBJ_id_kp,1L + +#define SN_client_auth "clientAuth" +#define LN_client_auth "TLS Web Client Authentication" +#define NID_client_auth 130 +#define OBJ_client_auth OBJ_id_kp,2L + +#define SN_code_sign "codeSigning" +#define LN_code_sign "Code Signing" +#define NID_code_sign 131 +#define OBJ_code_sign OBJ_id_kp,3L + +#define SN_email_protect "emailProtection" +#define LN_email_protect "E-mail Protection" +#define NID_email_protect 132 +#define OBJ_email_protect OBJ_id_kp,4L + +#define SN_ipsecEndSystem "ipsecEndSystem" +#define LN_ipsecEndSystem "IPSec End System" +#define NID_ipsecEndSystem 294 +#define OBJ_ipsecEndSystem OBJ_id_kp,5L + +#define SN_ipsecTunnel "ipsecTunnel" +#define LN_ipsecTunnel "IPSec Tunnel" +#define NID_ipsecTunnel 295 +#define OBJ_ipsecTunnel OBJ_id_kp,6L + +#define SN_ipsecUser "ipsecUser" +#define LN_ipsecUser "IPSec User" +#define NID_ipsecUser 296 +#define OBJ_ipsecUser OBJ_id_kp,7L + +#define SN_time_stamp "timeStamping" +#define LN_time_stamp "Time Stamping" +#define NID_time_stamp 133 +#define OBJ_time_stamp OBJ_id_kp,8L + +#define SN_OCSP_sign "OCSPSigning" +#define LN_OCSP_sign "OCSP Signing" +#define NID_OCSP_sign 180 +#define OBJ_OCSP_sign OBJ_id_kp,9L + +#define SN_dvcs "DVCS" +#define LN_dvcs "dvcs" +#define NID_dvcs 297 +#define OBJ_dvcs OBJ_id_kp,10L + +#define SN_ipsec_IKE "ipsecIKE" +#define LN_ipsec_IKE "ipsec Internet Key Exchange" +#define NID_ipsec_IKE 1022 +#define OBJ_ipsec_IKE OBJ_id_kp,17L + +#define SN_capwapAC "capwapAC" +#define LN_capwapAC "Ctrl/provision WAP Access" +#define NID_capwapAC 1023 +#define OBJ_capwapAC OBJ_id_kp,18L + +#define SN_capwapWTP "capwapWTP" +#define LN_capwapWTP "Ctrl/Provision WAP Termination" +#define NID_capwapWTP 1024 +#define OBJ_capwapWTP OBJ_id_kp,19L + +#define SN_sshClient "secureShellClient" +#define LN_sshClient "SSH Client" +#define NID_sshClient 1025 +#define OBJ_sshClient OBJ_id_kp,21L + +#define SN_sshServer "secureShellServer" +#define LN_sshServer "SSH Server" +#define NID_sshServer 1026 +#define OBJ_sshServer OBJ_id_kp,22L + +#define SN_sendRouter "sendRouter" +#define LN_sendRouter "Send Router" +#define NID_sendRouter 1027 +#define OBJ_sendRouter OBJ_id_kp,23L + +#define SN_sendProxiedRouter "sendProxiedRouter" +#define LN_sendProxiedRouter "Send Proxied Router" +#define NID_sendProxiedRouter 1028 +#define OBJ_sendProxiedRouter OBJ_id_kp,24L + +#define SN_sendOwner "sendOwner" +#define LN_sendOwner "Send Owner" +#define NID_sendOwner 1029 +#define OBJ_sendOwner OBJ_id_kp,25L + +#define SN_sendProxiedOwner "sendProxiedOwner" +#define LN_sendProxiedOwner "Send Proxied Owner" +#define NID_sendProxiedOwner 1030 +#define OBJ_sendProxiedOwner OBJ_id_kp,26L + +#define SN_cmcCA "cmcCA" +#define LN_cmcCA "CMC Certificate Authority" +#define NID_cmcCA 1131 +#define OBJ_cmcCA OBJ_id_kp,27L + +#define SN_cmcRA "cmcRA" +#define LN_cmcRA "CMC Registration Authority" +#define NID_cmcRA 1132 +#define OBJ_cmcRA OBJ_id_kp,28L + +#define SN_id_it_caProtEncCert "id-it-caProtEncCert" +#define NID_id_it_caProtEncCert 298 +#define OBJ_id_it_caProtEncCert OBJ_id_it,1L + +#define SN_id_it_signKeyPairTypes "id-it-signKeyPairTypes" +#define NID_id_it_signKeyPairTypes 299 +#define OBJ_id_it_signKeyPairTypes OBJ_id_it,2L + +#define SN_id_it_encKeyPairTypes "id-it-encKeyPairTypes" +#define NID_id_it_encKeyPairTypes 300 +#define OBJ_id_it_encKeyPairTypes OBJ_id_it,3L + +#define SN_id_it_preferredSymmAlg "id-it-preferredSymmAlg" +#define NID_id_it_preferredSymmAlg 301 +#define OBJ_id_it_preferredSymmAlg OBJ_id_it,4L + +#define SN_id_it_caKeyUpdateInfo "id-it-caKeyUpdateInfo" +#define NID_id_it_caKeyUpdateInfo 302 +#define OBJ_id_it_caKeyUpdateInfo OBJ_id_it,5L + +#define SN_id_it_currentCRL "id-it-currentCRL" +#define NID_id_it_currentCRL 303 +#define OBJ_id_it_currentCRL OBJ_id_it,6L + +#define SN_id_it_unsupportedOIDs "id-it-unsupportedOIDs" +#define NID_id_it_unsupportedOIDs 304 +#define OBJ_id_it_unsupportedOIDs OBJ_id_it,7L + +#define SN_id_it_subscriptionRequest "id-it-subscriptionRequest" +#define NID_id_it_subscriptionRequest 305 +#define OBJ_id_it_subscriptionRequest OBJ_id_it,8L + +#define SN_id_it_subscriptionResponse "id-it-subscriptionResponse" +#define NID_id_it_subscriptionResponse 306 +#define OBJ_id_it_subscriptionResponse OBJ_id_it,9L + +#define SN_id_it_keyPairParamReq "id-it-keyPairParamReq" +#define NID_id_it_keyPairParamReq 307 +#define OBJ_id_it_keyPairParamReq OBJ_id_it,10L + +#define SN_id_it_keyPairParamRep "id-it-keyPairParamRep" +#define NID_id_it_keyPairParamRep 308 +#define OBJ_id_it_keyPairParamRep OBJ_id_it,11L + +#define SN_id_it_revPassphrase "id-it-revPassphrase" +#define NID_id_it_revPassphrase 309 +#define OBJ_id_it_revPassphrase OBJ_id_it,12L + +#define SN_id_it_implicitConfirm "id-it-implicitConfirm" +#define NID_id_it_implicitConfirm 310 +#define OBJ_id_it_implicitConfirm OBJ_id_it,13L + +#define SN_id_it_confirmWaitTime "id-it-confirmWaitTime" +#define NID_id_it_confirmWaitTime 311 +#define OBJ_id_it_confirmWaitTime OBJ_id_it,14L + +#define SN_id_it_origPKIMessage "id-it-origPKIMessage" +#define NID_id_it_origPKIMessage 312 +#define OBJ_id_it_origPKIMessage OBJ_id_it,15L + +#define SN_id_it_suppLangTags "id-it-suppLangTags" +#define NID_id_it_suppLangTags 784 +#define OBJ_id_it_suppLangTags OBJ_id_it,16L + +#define SN_id_regCtrl "id-regCtrl" +#define NID_id_regCtrl 313 +#define OBJ_id_regCtrl OBJ_id_pkip,1L + +#define SN_id_regInfo "id-regInfo" +#define NID_id_regInfo 314 +#define OBJ_id_regInfo OBJ_id_pkip,2L + +#define SN_id_regCtrl_regToken "id-regCtrl-regToken" +#define NID_id_regCtrl_regToken 315 +#define OBJ_id_regCtrl_regToken OBJ_id_regCtrl,1L + +#define SN_id_regCtrl_authenticator "id-regCtrl-authenticator" +#define NID_id_regCtrl_authenticator 316 +#define OBJ_id_regCtrl_authenticator OBJ_id_regCtrl,2L + +#define SN_id_regCtrl_pkiPublicationInfo "id-regCtrl-pkiPublicationInfo" +#define NID_id_regCtrl_pkiPublicationInfo 317 +#define OBJ_id_regCtrl_pkiPublicationInfo OBJ_id_regCtrl,3L + +#define SN_id_regCtrl_pkiArchiveOptions "id-regCtrl-pkiArchiveOptions" +#define NID_id_regCtrl_pkiArchiveOptions 318 +#define OBJ_id_regCtrl_pkiArchiveOptions OBJ_id_regCtrl,4L + +#define SN_id_regCtrl_oldCertID "id-regCtrl-oldCertID" +#define NID_id_regCtrl_oldCertID 319 +#define OBJ_id_regCtrl_oldCertID OBJ_id_regCtrl,5L + +#define SN_id_regCtrl_protocolEncrKey "id-regCtrl-protocolEncrKey" +#define NID_id_regCtrl_protocolEncrKey 320 +#define OBJ_id_regCtrl_protocolEncrKey OBJ_id_regCtrl,6L + +#define SN_id_regInfo_utf8Pairs "id-regInfo-utf8Pairs" +#define NID_id_regInfo_utf8Pairs 321 +#define OBJ_id_regInfo_utf8Pairs OBJ_id_regInfo,1L + +#define SN_id_regInfo_certReq "id-regInfo-certReq" +#define NID_id_regInfo_certReq 322 +#define OBJ_id_regInfo_certReq OBJ_id_regInfo,2L + +#define SN_id_alg_des40 "id-alg-des40" +#define NID_id_alg_des40 323 +#define OBJ_id_alg_des40 OBJ_id_alg,1L + +#define SN_id_alg_noSignature "id-alg-noSignature" +#define NID_id_alg_noSignature 324 +#define OBJ_id_alg_noSignature OBJ_id_alg,2L + +#define SN_id_alg_dh_sig_hmac_sha1 "id-alg-dh-sig-hmac-sha1" +#define NID_id_alg_dh_sig_hmac_sha1 325 +#define OBJ_id_alg_dh_sig_hmac_sha1 OBJ_id_alg,3L + +#define SN_id_alg_dh_pop "id-alg-dh-pop" +#define NID_id_alg_dh_pop 326 +#define OBJ_id_alg_dh_pop OBJ_id_alg,4L + +#define SN_id_cmc_statusInfo "id-cmc-statusInfo" +#define NID_id_cmc_statusInfo 327 +#define OBJ_id_cmc_statusInfo OBJ_id_cmc,1L + +#define SN_id_cmc_identification "id-cmc-identification" +#define NID_id_cmc_identification 328 +#define OBJ_id_cmc_identification OBJ_id_cmc,2L + +#define SN_id_cmc_identityProof "id-cmc-identityProof" +#define NID_id_cmc_identityProof 329 +#define OBJ_id_cmc_identityProof OBJ_id_cmc,3L + +#define SN_id_cmc_dataReturn "id-cmc-dataReturn" +#define NID_id_cmc_dataReturn 330 +#define OBJ_id_cmc_dataReturn OBJ_id_cmc,4L + +#define SN_id_cmc_transactionId "id-cmc-transactionId" +#define NID_id_cmc_transactionId 331 +#define OBJ_id_cmc_transactionId OBJ_id_cmc,5L + +#define SN_id_cmc_senderNonce "id-cmc-senderNonce" +#define NID_id_cmc_senderNonce 332 +#define OBJ_id_cmc_senderNonce OBJ_id_cmc,6L + +#define SN_id_cmc_recipientNonce "id-cmc-recipientNonce" +#define NID_id_cmc_recipientNonce 333 +#define OBJ_id_cmc_recipientNonce OBJ_id_cmc,7L + +#define SN_id_cmc_addExtensions "id-cmc-addExtensions" +#define NID_id_cmc_addExtensions 334 +#define OBJ_id_cmc_addExtensions OBJ_id_cmc,8L + +#define SN_id_cmc_encryptedPOP "id-cmc-encryptedPOP" +#define NID_id_cmc_encryptedPOP 335 +#define OBJ_id_cmc_encryptedPOP OBJ_id_cmc,9L + +#define SN_id_cmc_decryptedPOP "id-cmc-decryptedPOP" +#define NID_id_cmc_decryptedPOP 336 +#define OBJ_id_cmc_decryptedPOP OBJ_id_cmc,10L + +#define SN_id_cmc_lraPOPWitness "id-cmc-lraPOPWitness" +#define NID_id_cmc_lraPOPWitness 337 +#define OBJ_id_cmc_lraPOPWitness OBJ_id_cmc,11L + +#define SN_id_cmc_getCert "id-cmc-getCert" +#define NID_id_cmc_getCert 338 +#define OBJ_id_cmc_getCert OBJ_id_cmc,15L + +#define SN_id_cmc_getCRL "id-cmc-getCRL" +#define NID_id_cmc_getCRL 339 +#define OBJ_id_cmc_getCRL OBJ_id_cmc,16L + +#define SN_id_cmc_revokeRequest "id-cmc-revokeRequest" +#define NID_id_cmc_revokeRequest 340 +#define OBJ_id_cmc_revokeRequest OBJ_id_cmc,17L + +#define SN_id_cmc_regInfo "id-cmc-regInfo" +#define NID_id_cmc_regInfo 341 +#define OBJ_id_cmc_regInfo OBJ_id_cmc,18L + +#define SN_id_cmc_responseInfo "id-cmc-responseInfo" +#define NID_id_cmc_responseInfo 342 +#define OBJ_id_cmc_responseInfo OBJ_id_cmc,19L + +#define SN_id_cmc_queryPending "id-cmc-queryPending" +#define NID_id_cmc_queryPending 343 +#define OBJ_id_cmc_queryPending OBJ_id_cmc,21L + +#define SN_id_cmc_popLinkRandom "id-cmc-popLinkRandom" +#define NID_id_cmc_popLinkRandom 344 +#define OBJ_id_cmc_popLinkRandom OBJ_id_cmc,22L + +#define SN_id_cmc_popLinkWitness "id-cmc-popLinkWitness" +#define NID_id_cmc_popLinkWitness 345 +#define OBJ_id_cmc_popLinkWitness OBJ_id_cmc,23L + +#define SN_id_cmc_confirmCertAcceptance "id-cmc-confirmCertAcceptance" +#define NID_id_cmc_confirmCertAcceptance 346 +#define OBJ_id_cmc_confirmCertAcceptance OBJ_id_cmc,24L + +#define SN_id_on_personalData "id-on-personalData" +#define NID_id_on_personalData 347 +#define OBJ_id_on_personalData OBJ_id_on,1L + +#define SN_id_on_permanentIdentifier "id-on-permanentIdentifier" +#define LN_id_on_permanentIdentifier "Permanent Identifier" +#define NID_id_on_permanentIdentifier 858 +#define OBJ_id_on_permanentIdentifier OBJ_id_on,3L + +#define SN_id_pda_dateOfBirth "id-pda-dateOfBirth" +#define NID_id_pda_dateOfBirth 348 +#define OBJ_id_pda_dateOfBirth OBJ_id_pda,1L + +#define SN_id_pda_placeOfBirth "id-pda-placeOfBirth" +#define NID_id_pda_placeOfBirth 349 +#define OBJ_id_pda_placeOfBirth OBJ_id_pda,2L + +#define SN_id_pda_gender "id-pda-gender" +#define NID_id_pda_gender 351 +#define OBJ_id_pda_gender OBJ_id_pda,3L + +#define SN_id_pda_countryOfCitizenship "id-pda-countryOfCitizenship" +#define NID_id_pda_countryOfCitizenship 352 +#define OBJ_id_pda_countryOfCitizenship OBJ_id_pda,4L + +#define SN_id_pda_countryOfResidence "id-pda-countryOfResidence" +#define NID_id_pda_countryOfResidence 353 +#define OBJ_id_pda_countryOfResidence OBJ_id_pda,5L + +#define SN_id_aca_authenticationInfo "id-aca-authenticationInfo" +#define NID_id_aca_authenticationInfo 354 +#define OBJ_id_aca_authenticationInfo OBJ_id_aca,1L + +#define SN_id_aca_accessIdentity "id-aca-accessIdentity" +#define NID_id_aca_accessIdentity 355 +#define OBJ_id_aca_accessIdentity OBJ_id_aca,2L + +#define SN_id_aca_chargingIdentity "id-aca-chargingIdentity" +#define NID_id_aca_chargingIdentity 356 +#define OBJ_id_aca_chargingIdentity OBJ_id_aca,3L + +#define SN_id_aca_group "id-aca-group" +#define NID_id_aca_group 357 +#define OBJ_id_aca_group OBJ_id_aca,4L + +#define SN_id_aca_role "id-aca-role" +#define NID_id_aca_role 358 +#define OBJ_id_aca_role OBJ_id_aca,5L + +#define SN_id_aca_encAttrs "id-aca-encAttrs" +#define NID_id_aca_encAttrs 399 +#define OBJ_id_aca_encAttrs OBJ_id_aca,6L + +#define SN_id_qcs_pkixQCSyntax_v1 "id-qcs-pkixQCSyntax-v1" +#define NID_id_qcs_pkixQCSyntax_v1 359 +#define OBJ_id_qcs_pkixQCSyntax_v1 OBJ_id_qcs,1L + +#define SN_id_cct_crs "id-cct-crs" +#define NID_id_cct_crs 360 +#define OBJ_id_cct_crs OBJ_id_cct,1L + +#define SN_id_cct_PKIData "id-cct-PKIData" +#define NID_id_cct_PKIData 361 +#define OBJ_id_cct_PKIData OBJ_id_cct,2L + +#define SN_id_cct_PKIResponse "id-cct-PKIResponse" +#define NID_id_cct_PKIResponse 362 +#define OBJ_id_cct_PKIResponse OBJ_id_cct,3L + +#define SN_id_ppl_anyLanguage "id-ppl-anyLanguage" +#define LN_id_ppl_anyLanguage "Any language" +#define NID_id_ppl_anyLanguage 664 +#define OBJ_id_ppl_anyLanguage OBJ_id_ppl,0L + +#define SN_id_ppl_inheritAll "id-ppl-inheritAll" +#define LN_id_ppl_inheritAll "Inherit all" +#define NID_id_ppl_inheritAll 665 +#define OBJ_id_ppl_inheritAll OBJ_id_ppl,1L + +#define SN_Independent "id-ppl-independent" +#define LN_Independent "Independent" +#define NID_Independent 667 +#define OBJ_Independent OBJ_id_ppl,2L + +#define SN_ad_OCSP "OCSP" +#define LN_ad_OCSP "OCSP" +#define NID_ad_OCSP 178 +#define OBJ_ad_OCSP OBJ_id_ad,1L + +#define SN_ad_ca_issuers "caIssuers" +#define LN_ad_ca_issuers "CA Issuers" +#define NID_ad_ca_issuers 179 +#define OBJ_ad_ca_issuers OBJ_id_ad,2L + +#define SN_ad_timeStamping "ad_timestamping" +#define LN_ad_timeStamping "AD Time Stamping" +#define NID_ad_timeStamping 363 +#define OBJ_ad_timeStamping OBJ_id_ad,3L + +#define SN_ad_dvcs "AD_DVCS" +#define LN_ad_dvcs "ad dvcs" +#define NID_ad_dvcs 364 +#define OBJ_ad_dvcs OBJ_id_ad,4L + +#define SN_caRepository "caRepository" +#define LN_caRepository "CA Repository" +#define NID_caRepository 785 +#define OBJ_caRepository OBJ_id_ad,5L + +#define OBJ_id_pkix_OCSP OBJ_ad_OCSP + +#define SN_id_pkix_OCSP_basic "basicOCSPResponse" +#define LN_id_pkix_OCSP_basic "Basic OCSP Response" +#define NID_id_pkix_OCSP_basic 365 +#define OBJ_id_pkix_OCSP_basic OBJ_id_pkix_OCSP,1L + +#define SN_id_pkix_OCSP_Nonce "Nonce" +#define LN_id_pkix_OCSP_Nonce "OCSP Nonce" +#define NID_id_pkix_OCSP_Nonce 366 +#define OBJ_id_pkix_OCSP_Nonce OBJ_id_pkix_OCSP,2L + +#define SN_id_pkix_OCSP_CrlID "CrlID" +#define LN_id_pkix_OCSP_CrlID "OCSP CRL ID" +#define NID_id_pkix_OCSP_CrlID 367 +#define OBJ_id_pkix_OCSP_CrlID OBJ_id_pkix_OCSP,3L + +#define SN_id_pkix_OCSP_acceptableResponses "acceptableResponses" +#define LN_id_pkix_OCSP_acceptableResponses "Acceptable OCSP Responses" +#define NID_id_pkix_OCSP_acceptableResponses 368 +#define OBJ_id_pkix_OCSP_acceptableResponses OBJ_id_pkix_OCSP,4L + +#define SN_id_pkix_OCSP_noCheck "noCheck" +#define LN_id_pkix_OCSP_noCheck "OCSP No Check" +#define NID_id_pkix_OCSP_noCheck 369 +#define OBJ_id_pkix_OCSP_noCheck OBJ_id_pkix_OCSP,5L + +#define SN_id_pkix_OCSP_archiveCutoff "archiveCutoff" +#define LN_id_pkix_OCSP_archiveCutoff "OCSP Archive Cutoff" +#define NID_id_pkix_OCSP_archiveCutoff 370 +#define OBJ_id_pkix_OCSP_archiveCutoff OBJ_id_pkix_OCSP,6L + +#define SN_id_pkix_OCSP_serviceLocator "serviceLocator" +#define LN_id_pkix_OCSP_serviceLocator "OCSP Service Locator" +#define NID_id_pkix_OCSP_serviceLocator 371 +#define OBJ_id_pkix_OCSP_serviceLocator OBJ_id_pkix_OCSP,7L + +#define SN_id_pkix_OCSP_extendedStatus "extendedStatus" +#define LN_id_pkix_OCSP_extendedStatus "Extended OCSP Status" +#define NID_id_pkix_OCSP_extendedStatus 372 +#define OBJ_id_pkix_OCSP_extendedStatus OBJ_id_pkix_OCSP,8L + +#define SN_id_pkix_OCSP_valid "valid" +#define NID_id_pkix_OCSP_valid 373 +#define OBJ_id_pkix_OCSP_valid OBJ_id_pkix_OCSP,9L + +#define SN_id_pkix_OCSP_path "path" +#define NID_id_pkix_OCSP_path 374 +#define OBJ_id_pkix_OCSP_path OBJ_id_pkix_OCSP,10L + +#define SN_id_pkix_OCSP_trustRoot "trustRoot" +#define LN_id_pkix_OCSP_trustRoot "Trust Root" +#define NID_id_pkix_OCSP_trustRoot 375 +#define OBJ_id_pkix_OCSP_trustRoot OBJ_id_pkix_OCSP,11L + +#define SN_algorithm "algorithm" +#define LN_algorithm "algorithm" +#define NID_algorithm 376 +#define OBJ_algorithm 1L,3L,14L,3L,2L + +#define SN_md5WithRSA "RSA-NP-MD5" +#define LN_md5WithRSA "md5WithRSA" +#define NID_md5WithRSA 104 +#define OBJ_md5WithRSA OBJ_algorithm,3L + +#define SN_des_ecb "DES-ECB" +#define LN_des_ecb "des-ecb" +#define NID_des_ecb 29 +#define OBJ_des_ecb OBJ_algorithm,6L + +#define SN_des_cbc "DES-CBC" +#define LN_des_cbc "des-cbc" +#define NID_des_cbc 31 +#define OBJ_des_cbc OBJ_algorithm,7L + +#define SN_des_ofb64 "DES-OFB" +#define LN_des_ofb64 "des-ofb" +#define NID_des_ofb64 45 +#define OBJ_des_ofb64 OBJ_algorithm,8L + +#define SN_des_cfb64 "DES-CFB" +#define LN_des_cfb64 "des-cfb" +#define NID_des_cfb64 30 +#define OBJ_des_cfb64 OBJ_algorithm,9L + +#define SN_rsaSignature "rsaSignature" +#define NID_rsaSignature 377 +#define OBJ_rsaSignature OBJ_algorithm,11L + +#define SN_dsa_2 "DSA-old" +#define LN_dsa_2 "dsaEncryption-old" +#define NID_dsa_2 67 +#define OBJ_dsa_2 OBJ_algorithm,12L + +#define SN_dsaWithSHA "DSA-SHA" +#define LN_dsaWithSHA "dsaWithSHA" +#define NID_dsaWithSHA 66 +#define OBJ_dsaWithSHA OBJ_algorithm,13L + +#define SN_shaWithRSAEncryption "RSA-SHA" +#define LN_shaWithRSAEncryption "shaWithRSAEncryption" +#define NID_shaWithRSAEncryption 42 +#define OBJ_shaWithRSAEncryption OBJ_algorithm,15L + +#define SN_des_ede_ecb "DES-EDE" +#define LN_des_ede_ecb "des-ede" +#define NID_des_ede_ecb 32 +#define OBJ_des_ede_ecb OBJ_algorithm,17L + +#define SN_des_ede3_ecb "DES-EDE3" +#define LN_des_ede3_ecb "des-ede3" +#define NID_des_ede3_ecb 33 + +#define SN_des_ede_cbc "DES-EDE-CBC" +#define LN_des_ede_cbc "des-ede-cbc" +#define NID_des_ede_cbc 43 + +#define SN_des_ede_cfb64 "DES-EDE-CFB" +#define LN_des_ede_cfb64 "des-ede-cfb" +#define NID_des_ede_cfb64 60 + +#define SN_des_ede3_cfb64 "DES-EDE3-CFB" +#define LN_des_ede3_cfb64 "des-ede3-cfb" +#define NID_des_ede3_cfb64 61 + +#define SN_des_ede_ofb64 "DES-EDE-OFB" +#define LN_des_ede_ofb64 "des-ede-ofb" +#define NID_des_ede_ofb64 62 + +#define SN_des_ede3_ofb64 "DES-EDE3-OFB" +#define LN_des_ede3_ofb64 "des-ede3-ofb" +#define NID_des_ede3_ofb64 63 + +#define SN_desx_cbc "DESX-CBC" +#define LN_desx_cbc "desx-cbc" +#define NID_desx_cbc 80 + +#define SN_sha "SHA" +#define LN_sha "sha" +#define NID_sha 41 +#define OBJ_sha OBJ_algorithm,18L + +#define SN_sha1 "SHA1" +#define LN_sha1 "sha1" +#define NID_sha1 64 +#define OBJ_sha1 OBJ_algorithm,26L + +#define SN_dsaWithSHA1_2 "DSA-SHA1-old" +#define LN_dsaWithSHA1_2 "dsaWithSHA1-old" +#define NID_dsaWithSHA1_2 70 +#define OBJ_dsaWithSHA1_2 OBJ_algorithm,27L + +#define SN_sha1WithRSA "RSA-SHA1-2" +#define LN_sha1WithRSA "sha1WithRSA" +#define NID_sha1WithRSA 115 +#define OBJ_sha1WithRSA OBJ_algorithm,29L + +#define SN_ripemd160 "RIPEMD160" +#define LN_ripemd160 "ripemd160" +#define NID_ripemd160 117 +#define OBJ_ripemd160 1L,3L,36L,3L,2L,1L + +#define SN_ripemd160WithRSA "RSA-RIPEMD160" +#define LN_ripemd160WithRSA "ripemd160WithRSA" +#define NID_ripemd160WithRSA 119 +#define OBJ_ripemd160WithRSA 1L,3L,36L,3L,3L,1L,2L + +#define SN_blake2b512 "BLAKE2b512" +#define LN_blake2b512 "blake2b512" +#define NID_blake2b512 1056 +#define OBJ_blake2b512 1L,3L,6L,1L,4L,1L,1722L,12L,2L,1L,16L + +#define SN_blake2s256 "BLAKE2s256" +#define LN_blake2s256 "blake2s256" +#define NID_blake2s256 1057 +#define OBJ_blake2s256 1L,3L,6L,1L,4L,1L,1722L,12L,2L,2L,8L + +#define SN_sxnet "SXNetID" +#define LN_sxnet "Strong Extranet ID" +#define NID_sxnet 143 +#define OBJ_sxnet 1L,3L,101L,1L,4L,1L + +#define SN_X500 "X500" +#define LN_X500 "directory services (X.500)" +#define NID_X500 11 +#define OBJ_X500 2L,5L + +#define SN_X509 "X509" +#define NID_X509 12 +#define OBJ_X509 OBJ_X500,4L + +#define SN_commonName "CN" +#define LN_commonName "commonName" +#define NID_commonName 13 +#define OBJ_commonName OBJ_X509,3L + +#define SN_surname "SN" +#define LN_surname "surname" +#define NID_surname 100 +#define OBJ_surname OBJ_X509,4L + +#define LN_serialNumber "serialNumber" +#define NID_serialNumber 105 +#define OBJ_serialNumber OBJ_X509,5L + +#define SN_countryName "C" +#define LN_countryName "countryName" +#define NID_countryName 14 +#define OBJ_countryName OBJ_X509,6L + +#define SN_localityName "L" +#define LN_localityName "localityName" +#define NID_localityName 15 +#define OBJ_localityName OBJ_X509,7L + +#define SN_stateOrProvinceName "ST" +#define LN_stateOrProvinceName "stateOrProvinceName" +#define NID_stateOrProvinceName 16 +#define OBJ_stateOrProvinceName OBJ_X509,8L + +#define SN_streetAddress "street" +#define LN_streetAddress "streetAddress" +#define NID_streetAddress 660 +#define OBJ_streetAddress OBJ_X509,9L + +#define SN_organizationName "O" +#define LN_organizationName "organizationName" +#define NID_organizationName 17 +#define OBJ_organizationName OBJ_X509,10L + +#define SN_organizationalUnitName "OU" +#define LN_organizationalUnitName "organizationalUnitName" +#define NID_organizationalUnitName 18 +#define OBJ_organizationalUnitName OBJ_X509,11L + +#define SN_title "title" +#define LN_title "title" +#define NID_title 106 +#define OBJ_title OBJ_X509,12L + +#define LN_description "description" +#define NID_description 107 +#define OBJ_description OBJ_X509,13L + +#define LN_searchGuide "searchGuide" +#define NID_searchGuide 859 +#define OBJ_searchGuide OBJ_X509,14L + +#define LN_businessCategory "businessCategory" +#define NID_businessCategory 860 +#define OBJ_businessCategory OBJ_X509,15L + +#define LN_postalAddress "postalAddress" +#define NID_postalAddress 861 +#define OBJ_postalAddress OBJ_X509,16L + +#define LN_postalCode "postalCode" +#define NID_postalCode 661 +#define OBJ_postalCode OBJ_X509,17L + +#define LN_postOfficeBox "postOfficeBox" +#define NID_postOfficeBox 862 +#define OBJ_postOfficeBox OBJ_X509,18L + +#define LN_physicalDeliveryOfficeName "physicalDeliveryOfficeName" +#define NID_physicalDeliveryOfficeName 863 +#define OBJ_physicalDeliveryOfficeName OBJ_X509,19L + +#define LN_telephoneNumber "telephoneNumber" +#define NID_telephoneNumber 864 +#define OBJ_telephoneNumber OBJ_X509,20L + +#define LN_telexNumber "telexNumber" +#define NID_telexNumber 865 +#define OBJ_telexNumber OBJ_X509,21L + +#define LN_teletexTerminalIdentifier "teletexTerminalIdentifier" +#define NID_teletexTerminalIdentifier 866 +#define OBJ_teletexTerminalIdentifier OBJ_X509,22L + +#define LN_facsimileTelephoneNumber "facsimileTelephoneNumber" +#define NID_facsimileTelephoneNumber 867 +#define OBJ_facsimileTelephoneNumber OBJ_X509,23L + +#define LN_x121Address "x121Address" +#define NID_x121Address 868 +#define OBJ_x121Address OBJ_X509,24L + +#define LN_internationaliSDNNumber "internationaliSDNNumber" +#define NID_internationaliSDNNumber 869 +#define OBJ_internationaliSDNNumber OBJ_X509,25L + +#define LN_registeredAddress "registeredAddress" +#define NID_registeredAddress 870 +#define OBJ_registeredAddress OBJ_X509,26L + +#define LN_destinationIndicator "destinationIndicator" +#define NID_destinationIndicator 871 +#define OBJ_destinationIndicator OBJ_X509,27L + +#define LN_preferredDeliveryMethod "preferredDeliveryMethod" +#define NID_preferredDeliveryMethod 872 +#define OBJ_preferredDeliveryMethod OBJ_X509,28L + +#define LN_presentationAddress "presentationAddress" +#define NID_presentationAddress 873 +#define OBJ_presentationAddress OBJ_X509,29L + +#define LN_supportedApplicationContext "supportedApplicationContext" +#define NID_supportedApplicationContext 874 +#define OBJ_supportedApplicationContext OBJ_X509,30L + +#define SN_member "member" +#define NID_member 875 +#define OBJ_member OBJ_X509,31L + +#define SN_owner "owner" +#define NID_owner 876 +#define OBJ_owner OBJ_X509,32L + +#define LN_roleOccupant "roleOccupant" +#define NID_roleOccupant 877 +#define OBJ_roleOccupant OBJ_X509,33L + +#define SN_seeAlso "seeAlso" +#define NID_seeAlso 878 +#define OBJ_seeAlso OBJ_X509,34L + +#define LN_userPassword "userPassword" +#define NID_userPassword 879 +#define OBJ_userPassword OBJ_X509,35L + +#define LN_userCertificate "userCertificate" +#define NID_userCertificate 880 +#define OBJ_userCertificate OBJ_X509,36L + +#define LN_cACertificate "cACertificate" +#define NID_cACertificate 881 +#define OBJ_cACertificate OBJ_X509,37L + +#define LN_authorityRevocationList "authorityRevocationList" +#define NID_authorityRevocationList 882 +#define OBJ_authorityRevocationList OBJ_X509,38L + +#define LN_certificateRevocationList "certificateRevocationList" +#define NID_certificateRevocationList 883 +#define OBJ_certificateRevocationList OBJ_X509,39L + +#define LN_crossCertificatePair "crossCertificatePair" +#define NID_crossCertificatePair 884 +#define OBJ_crossCertificatePair OBJ_X509,40L + +#define SN_name "name" +#define LN_name "name" +#define NID_name 173 +#define OBJ_name OBJ_X509,41L + +#define SN_givenName "GN" +#define LN_givenName "givenName" +#define NID_givenName 99 +#define OBJ_givenName OBJ_X509,42L + +#define SN_initials "initials" +#define LN_initials "initials" +#define NID_initials 101 +#define OBJ_initials OBJ_X509,43L + +#define LN_generationQualifier "generationQualifier" +#define NID_generationQualifier 509 +#define OBJ_generationQualifier OBJ_X509,44L + +#define LN_x500UniqueIdentifier "x500UniqueIdentifier" +#define NID_x500UniqueIdentifier 503 +#define OBJ_x500UniqueIdentifier OBJ_X509,45L + +#define SN_dnQualifier "dnQualifier" +#define LN_dnQualifier "dnQualifier" +#define NID_dnQualifier 174 +#define OBJ_dnQualifier OBJ_X509,46L + +#define LN_enhancedSearchGuide "enhancedSearchGuide" +#define NID_enhancedSearchGuide 885 +#define OBJ_enhancedSearchGuide OBJ_X509,47L + +#define LN_protocolInformation "protocolInformation" +#define NID_protocolInformation 886 +#define OBJ_protocolInformation OBJ_X509,48L + +#define LN_distinguishedName "distinguishedName" +#define NID_distinguishedName 887 +#define OBJ_distinguishedName OBJ_X509,49L + +#define LN_uniqueMember "uniqueMember" +#define NID_uniqueMember 888 +#define OBJ_uniqueMember OBJ_X509,50L + +#define LN_houseIdentifier "houseIdentifier" +#define NID_houseIdentifier 889 +#define OBJ_houseIdentifier OBJ_X509,51L + +#define LN_supportedAlgorithms "supportedAlgorithms" +#define NID_supportedAlgorithms 890 +#define OBJ_supportedAlgorithms OBJ_X509,52L + +#define LN_deltaRevocationList "deltaRevocationList" +#define NID_deltaRevocationList 891 +#define OBJ_deltaRevocationList OBJ_X509,53L + +#define SN_dmdName "dmdName" +#define NID_dmdName 892 +#define OBJ_dmdName OBJ_X509,54L + +#define LN_pseudonym "pseudonym" +#define NID_pseudonym 510 +#define OBJ_pseudonym OBJ_X509,65L + +#define SN_role "role" +#define LN_role "role" +#define NID_role 400 +#define OBJ_role OBJ_X509,72L + +#define LN_organizationIdentifier "organizationIdentifier" +#define NID_organizationIdentifier 1089 +#define OBJ_organizationIdentifier OBJ_X509,97L + +#define SN_countryCode3c "c3" +#define LN_countryCode3c "countryCode3c" +#define NID_countryCode3c 1090 +#define OBJ_countryCode3c OBJ_X509,98L + +#define SN_countryCode3n "n3" +#define LN_countryCode3n "countryCode3n" +#define NID_countryCode3n 1091 +#define OBJ_countryCode3n OBJ_X509,99L + +#define LN_dnsName "dnsName" +#define NID_dnsName 1092 +#define OBJ_dnsName OBJ_X509,100L + +#define SN_X500algorithms "X500algorithms" +#define LN_X500algorithms "directory services - algorithms" +#define NID_X500algorithms 378 +#define OBJ_X500algorithms OBJ_X500,8L + +#define SN_rsa "RSA" +#define LN_rsa "rsa" +#define NID_rsa 19 +#define OBJ_rsa OBJ_X500algorithms,1L,1L + +#define SN_mdc2WithRSA "RSA-MDC2" +#define LN_mdc2WithRSA "mdc2WithRSA" +#define NID_mdc2WithRSA 96 +#define OBJ_mdc2WithRSA OBJ_X500algorithms,3L,100L + +#define SN_mdc2 "MDC2" +#define LN_mdc2 "mdc2" +#define NID_mdc2 95 +#define OBJ_mdc2 OBJ_X500algorithms,3L,101L + +#define SN_id_ce "id-ce" +#define NID_id_ce 81 +#define OBJ_id_ce OBJ_X500,29L + +#define SN_subject_directory_attributes "subjectDirectoryAttributes" +#define LN_subject_directory_attributes "X509v3 Subject Directory Attributes" +#define NID_subject_directory_attributes 769 +#define OBJ_subject_directory_attributes OBJ_id_ce,9L + +#define SN_subject_key_identifier "subjectKeyIdentifier" +#define LN_subject_key_identifier "X509v3 Subject Key Identifier" +#define NID_subject_key_identifier 82 +#define OBJ_subject_key_identifier OBJ_id_ce,14L + +#define SN_key_usage "keyUsage" +#define LN_key_usage "X509v3 Key Usage" +#define NID_key_usage 83 +#define OBJ_key_usage OBJ_id_ce,15L + +#define SN_private_key_usage_period "privateKeyUsagePeriod" +#define LN_private_key_usage_period "X509v3 Private Key Usage Period" +#define NID_private_key_usage_period 84 +#define OBJ_private_key_usage_period OBJ_id_ce,16L + +#define SN_subject_alt_name "subjectAltName" +#define LN_subject_alt_name "X509v3 Subject Alternative Name" +#define NID_subject_alt_name 85 +#define OBJ_subject_alt_name OBJ_id_ce,17L + +#define SN_issuer_alt_name "issuerAltName" +#define LN_issuer_alt_name "X509v3 Issuer Alternative Name" +#define NID_issuer_alt_name 86 +#define OBJ_issuer_alt_name OBJ_id_ce,18L + +#define SN_basic_constraints "basicConstraints" +#define LN_basic_constraints "X509v3 Basic Constraints" +#define NID_basic_constraints 87 +#define OBJ_basic_constraints OBJ_id_ce,19L + +#define SN_crl_number "crlNumber" +#define LN_crl_number "X509v3 CRL Number" +#define NID_crl_number 88 +#define OBJ_crl_number OBJ_id_ce,20L + +#define SN_crl_reason "CRLReason" +#define LN_crl_reason "X509v3 CRL Reason Code" +#define NID_crl_reason 141 +#define OBJ_crl_reason OBJ_id_ce,21L + +#define SN_invalidity_date "invalidityDate" +#define LN_invalidity_date "Invalidity Date" +#define NID_invalidity_date 142 +#define OBJ_invalidity_date OBJ_id_ce,24L + +#define SN_delta_crl "deltaCRL" +#define LN_delta_crl "X509v3 Delta CRL Indicator" +#define NID_delta_crl 140 +#define OBJ_delta_crl OBJ_id_ce,27L + +#define SN_issuing_distribution_point "issuingDistributionPoint" +#define LN_issuing_distribution_point "X509v3 Issuing Distribution Point" +#define NID_issuing_distribution_point 770 +#define OBJ_issuing_distribution_point OBJ_id_ce,28L + +#define SN_certificate_issuer "certificateIssuer" +#define LN_certificate_issuer "X509v3 Certificate Issuer" +#define NID_certificate_issuer 771 +#define OBJ_certificate_issuer OBJ_id_ce,29L + +#define SN_name_constraints "nameConstraints" +#define LN_name_constraints "X509v3 Name Constraints" +#define NID_name_constraints 666 +#define OBJ_name_constraints OBJ_id_ce,30L + +#define SN_crl_distribution_points "crlDistributionPoints" +#define LN_crl_distribution_points "X509v3 CRL Distribution Points" +#define NID_crl_distribution_points 103 +#define OBJ_crl_distribution_points OBJ_id_ce,31L + +#define SN_certificate_policies "certificatePolicies" +#define LN_certificate_policies "X509v3 Certificate Policies" +#define NID_certificate_policies 89 +#define OBJ_certificate_policies OBJ_id_ce,32L + +#define SN_any_policy "anyPolicy" +#define LN_any_policy "X509v3 Any Policy" +#define NID_any_policy 746 +#define OBJ_any_policy OBJ_certificate_policies,0L + +#define SN_policy_mappings "policyMappings" +#define LN_policy_mappings "X509v3 Policy Mappings" +#define NID_policy_mappings 747 +#define OBJ_policy_mappings OBJ_id_ce,33L + +#define SN_authority_key_identifier "authorityKeyIdentifier" +#define LN_authority_key_identifier "X509v3 Authority Key Identifier" +#define NID_authority_key_identifier 90 +#define OBJ_authority_key_identifier OBJ_id_ce,35L + +#define SN_policy_constraints "policyConstraints" +#define LN_policy_constraints "X509v3 Policy Constraints" +#define NID_policy_constraints 401 +#define OBJ_policy_constraints OBJ_id_ce,36L + +#define SN_ext_key_usage "extendedKeyUsage" +#define LN_ext_key_usage "X509v3 Extended Key Usage" +#define NID_ext_key_usage 126 +#define OBJ_ext_key_usage OBJ_id_ce,37L + +#define SN_freshest_crl "freshestCRL" +#define LN_freshest_crl "X509v3 Freshest CRL" +#define NID_freshest_crl 857 +#define OBJ_freshest_crl OBJ_id_ce,46L + +#define SN_inhibit_any_policy "inhibitAnyPolicy" +#define LN_inhibit_any_policy "X509v3 Inhibit Any Policy" +#define NID_inhibit_any_policy 748 +#define OBJ_inhibit_any_policy OBJ_id_ce,54L + +#define SN_target_information "targetInformation" +#define LN_target_information "X509v3 AC Targeting" +#define NID_target_information 402 +#define OBJ_target_information OBJ_id_ce,55L + +#define SN_no_rev_avail "noRevAvail" +#define LN_no_rev_avail "X509v3 No Revocation Available" +#define NID_no_rev_avail 403 +#define OBJ_no_rev_avail OBJ_id_ce,56L + +#define SN_anyExtendedKeyUsage "anyExtendedKeyUsage" +#define LN_anyExtendedKeyUsage "Any Extended Key Usage" +#define NID_anyExtendedKeyUsage 910 +#define OBJ_anyExtendedKeyUsage OBJ_ext_key_usage,0L + +#define SN_netscape "Netscape" +#define LN_netscape "Netscape Communications Corp." +#define NID_netscape 57 +#define OBJ_netscape 2L,16L,840L,1L,113730L + +#define SN_netscape_cert_extension "nsCertExt" +#define LN_netscape_cert_extension "Netscape Certificate Extension" +#define NID_netscape_cert_extension 58 +#define OBJ_netscape_cert_extension OBJ_netscape,1L + +#define SN_netscape_data_type "nsDataType" +#define LN_netscape_data_type "Netscape Data Type" +#define NID_netscape_data_type 59 +#define OBJ_netscape_data_type OBJ_netscape,2L + +#define SN_netscape_cert_type "nsCertType" +#define LN_netscape_cert_type "Netscape Cert Type" +#define NID_netscape_cert_type 71 +#define OBJ_netscape_cert_type OBJ_netscape_cert_extension,1L + +#define SN_netscape_base_url "nsBaseUrl" +#define LN_netscape_base_url "Netscape Base Url" +#define NID_netscape_base_url 72 +#define OBJ_netscape_base_url OBJ_netscape_cert_extension,2L + +#define SN_netscape_revocation_url "nsRevocationUrl" +#define LN_netscape_revocation_url "Netscape Revocation Url" +#define NID_netscape_revocation_url 73 +#define OBJ_netscape_revocation_url OBJ_netscape_cert_extension,3L + +#define SN_netscape_ca_revocation_url "nsCaRevocationUrl" +#define LN_netscape_ca_revocation_url "Netscape CA Revocation Url" +#define NID_netscape_ca_revocation_url 74 +#define OBJ_netscape_ca_revocation_url OBJ_netscape_cert_extension,4L + +#define SN_netscape_renewal_url "nsRenewalUrl" +#define LN_netscape_renewal_url "Netscape Renewal Url" +#define NID_netscape_renewal_url 75 +#define OBJ_netscape_renewal_url OBJ_netscape_cert_extension,7L + +#define SN_netscape_ca_policy_url "nsCaPolicyUrl" +#define LN_netscape_ca_policy_url "Netscape CA Policy Url" +#define NID_netscape_ca_policy_url 76 +#define OBJ_netscape_ca_policy_url OBJ_netscape_cert_extension,8L + +#define SN_netscape_ssl_server_name "nsSslServerName" +#define LN_netscape_ssl_server_name "Netscape SSL Server Name" +#define NID_netscape_ssl_server_name 77 +#define OBJ_netscape_ssl_server_name OBJ_netscape_cert_extension,12L + +#define SN_netscape_comment "nsComment" +#define LN_netscape_comment "Netscape Comment" +#define NID_netscape_comment 78 +#define OBJ_netscape_comment OBJ_netscape_cert_extension,13L + +#define SN_netscape_cert_sequence "nsCertSequence" +#define LN_netscape_cert_sequence "Netscape Certificate Sequence" +#define NID_netscape_cert_sequence 79 +#define OBJ_netscape_cert_sequence OBJ_netscape_data_type,5L + +#define SN_ns_sgc "nsSGC" +#define LN_ns_sgc "Netscape Server Gated Crypto" +#define NID_ns_sgc 139 +#define OBJ_ns_sgc OBJ_netscape,4L,1L + +#define SN_org "ORG" +#define LN_org "org" +#define NID_org 379 +#define OBJ_org OBJ_iso,3L + +#define SN_dod "DOD" +#define LN_dod "dod" +#define NID_dod 380 +#define OBJ_dod OBJ_org,6L + +#define SN_iana "IANA" +#define LN_iana "iana" +#define NID_iana 381 +#define OBJ_iana OBJ_dod,1L + +#define OBJ_internet OBJ_iana + +#define SN_Directory "directory" +#define LN_Directory "Directory" +#define NID_Directory 382 +#define OBJ_Directory OBJ_internet,1L + +#define SN_Management "mgmt" +#define LN_Management "Management" +#define NID_Management 383 +#define OBJ_Management OBJ_internet,2L + +#define SN_Experimental "experimental" +#define LN_Experimental "Experimental" +#define NID_Experimental 384 +#define OBJ_Experimental OBJ_internet,3L + +#define SN_Private "private" +#define LN_Private "Private" +#define NID_Private 385 +#define OBJ_Private OBJ_internet,4L + +#define SN_Security "security" +#define LN_Security "Security" +#define NID_Security 386 +#define OBJ_Security OBJ_internet,5L + +#define SN_SNMPv2 "snmpv2" +#define LN_SNMPv2 "SNMPv2" +#define NID_SNMPv2 387 +#define OBJ_SNMPv2 OBJ_internet,6L + +#define LN_Mail "Mail" +#define NID_Mail 388 +#define OBJ_Mail OBJ_internet,7L + +#define SN_Enterprises "enterprises" +#define LN_Enterprises "Enterprises" +#define NID_Enterprises 389 +#define OBJ_Enterprises OBJ_Private,1L + +#define SN_dcObject "dcobject" +#define LN_dcObject "dcObject" +#define NID_dcObject 390 +#define OBJ_dcObject OBJ_Enterprises,1466L,344L + +#define SN_mime_mhs "mime-mhs" +#define LN_mime_mhs "MIME MHS" +#define NID_mime_mhs 504 +#define OBJ_mime_mhs OBJ_Mail,1L + +#define SN_mime_mhs_headings "mime-mhs-headings" +#define LN_mime_mhs_headings "mime-mhs-headings" +#define NID_mime_mhs_headings 505 +#define OBJ_mime_mhs_headings OBJ_mime_mhs,1L + +#define SN_mime_mhs_bodies "mime-mhs-bodies" +#define LN_mime_mhs_bodies "mime-mhs-bodies" +#define NID_mime_mhs_bodies 506 +#define OBJ_mime_mhs_bodies OBJ_mime_mhs,2L + +#define SN_id_hex_partial_message "id-hex-partial-message" +#define LN_id_hex_partial_message "id-hex-partial-message" +#define NID_id_hex_partial_message 507 +#define OBJ_id_hex_partial_message OBJ_mime_mhs_headings,1L + +#define SN_id_hex_multipart_message "id-hex-multipart-message" +#define LN_id_hex_multipart_message "id-hex-multipart-message" +#define NID_id_hex_multipart_message 508 +#define OBJ_id_hex_multipart_message OBJ_mime_mhs_headings,2L + +#define SN_zlib_compression "ZLIB" +#define LN_zlib_compression "zlib compression" +#define NID_zlib_compression 125 +#define OBJ_zlib_compression OBJ_id_smime_alg,8L + +#define OBJ_csor 2L,16L,840L,1L,101L,3L + +#define OBJ_nistAlgorithms OBJ_csor,4L + +#define OBJ_aes OBJ_nistAlgorithms,1L + +#define SN_aes_128_ecb "AES-128-ECB" +#define LN_aes_128_ecb "aes-128-ecb" +#define NID_aes_128_ecb 418 +#define OBJ_aes_128_ecb OBJ_aes,1L + +#define SN_aes_128_cbc "AES-128-CBC" +#define LN_aes_128_cbc "aes-128-cbc" +#define NID_aes_128_cbc 419 +#define OBJ_aes_128_cbc OBJ_aes,2L + +#define SN_aes_128_ofb128 "AES-128-OFB" +#define LN_aes_128_ofb128 "aes-128-ofb" +#define NID_aes_128_ofb128 420 +#define OBJ_aes_128_ofb128 OBJ_aes,3L + +#define SN_aes_128_cfb128 "AES-128-CFB" +#define LN_aes_128_cfb128 "aes-128-cfb" +#define NID_aes_128_cfb128 421 +#define OBJ_aes_128_cfb128 OBJ_aes,4L + +#define SN_id_aes128_wrap "id-aes128-wrap" +#define NID_id_aes128_wrap 788 +#define OBJ_id_aes128_wrap OBJ_aes,5L + +#define SN_aes_128_gcm "id-aes128-GCM" +#define LN_aes_128_gcm "aes-128-gcm" +#define NID_aes_128_gcm 895 +#define OBJ_aes_128_gcm OBJ_aes,6L + +#define SN_aes_128_ccm "id-aes128-CCM" +#define LN_aes_128_ccm "aes-128-ccm" +#define NID_aes_128_ccm 896 +#define OBJ_aes_128_ccm OBJ_aes,7L + +#define SN_id_aes128_wrap_pad "id-aes128-wrap-pad" +#define NID_id_aes128_wrap_pad 897 +#define OBJ_id_aes128_wrap_pad OBJ_aes,8L + +#define SN_aes_192_ecb "AES-192-ECB" +#define LN_aes_192_ecb "aes-192-ecb" +#define NID_aes_192_ecb 422 +#define OBJ_aes_192_ecb OBJ_aes,21L + +#define SN_aes_192_cbc "AES-192-CBC" +#define LN_aes_192_cbc "aes-192-cbc" +#define NID_aes_192_cbc 423 +#define OBJ_aes_192_cbc OBJ_aes,22L + +#define SN_aes_192_ofb128 "AES-192-OFB" +#define LN_aes_192_ofb128 "aes-192-ofb" +#define NID_aes_192_ofb128 424 +#define OBJ_aes_192_ofb128 OBJ_aes,23L + +#define SN_aes_192_cfb128 "AES-192-CFB" +#define LN_aes_192_cfb128 "aes-192-cfb" +#define NID_aes_192_cfb128 425 +#define OBJ_aes_192_cfb128 OBJ_aes,24L + +#define SN_id_aes192_wrap "id-aes192-wrap" +#define NID_id_aes192_wrap 789 +#define OBJ_id_aes192_wrap OBJ_aes,25L + +#define SN_aes_192_gcm "id-aes192-GCM" +#define LN_aes_192_gcm "aes-192-gcm" +#define NID_aes_192_gcm 898 +#define OBJ_aes_192_gcm OBJ_aes,26L + +#define SN_aes_192_ccm "id-aes192-CCM" +#define LN_aes_192_ccm "aes-192-ccm" +#define NID_aes_192_ccm 899 +#define OBJ_aes_192_ccm OBJ_aes,27L + +#define SN_id_aes192_wrap_pad "id-aes192-wrap-pad" +#define NID_id_aes192_wrap_pad 900 +#define OBJ_id_aes192_wrap_pad OBJ_aes,28L + +#define SN_aes_256_ecb "AES-256-ECB" +#define LN_aes_256_ecb "aes-256-ecb" +#define NID_aes_256_ecb 426 +#define OBJ_aes_256_ecb OBJ_aes,41L + +#define SN_aes_256_cbc "AES-256-CBC" +#define LN_aes_256_cbc "aes-256-cbc" +#define NID_aes_256_cbc 427 +#define OBJ_aes_256_cbc OBJ_aes,42L + +#define SN_aes_256_ofb128 "AES-256-OFB" +#define LN_aes_256_ofb128 "aes-256-ofb" +#define NID_aes_256_ofb128 428 +#define OBJ_aes_256_ofb128 OBJ_aes,43L + +#define SN_aes_256_cfb128 "AES-256-CFB" +#define LN_aes_256_cfb128 "aes-256-cfb" +#define NID_aes_256_cfb128 429 +#define OBJ_aes_256_cfb128 OBJ_aes,44L + +#define SN_id_aes256_wrap "id-aes256-wrap" +#define NID_id_aes256_wrap 790 +#define OBJ_id_aes256_wrap OBJ_aes,45L + +#define SN_aes_256_gcm "id-aes256-GCM" +#define LN_aes_256_gcm "aes-256-gcm" +#define NID_aes_256_gcm 901 +#define OBJ_aes_256_gcm OBJ_aes,46L + +#define SN_aes_256_ccm "id-aes256-CCM" +#define LN_aes_256_ccm "aes-256-ccm" +#define NID_aes_256_ccm 902 +#define OBJ_aes_256_ccm OBJ_aes,47L + +#define SN_id_aes256_wrap_pad "id-aes256-wrap-pad" +#define NID_id_aes256_wrap_pad 903 +#define OBJ_id_aes256_wrap_pad OBJ_aes,48L + +#define SN_aes_128_xts "AES-128-XTS" +#define LN_aes_128_xts "aes-128-xts" +#define NID_aes_128_xts 913 +#define OBJ_aes_128_xts OBJ_ieee_siswg,0L,1L,1L + +#define SN_aes_256_xts "AES-256-XTS" +#define LN_aes_256_xts "aes-256-xts" +#define NID_aes_256_xts 914 +#define OBJ_aes_256_xts OBJ_ieee_siswg,0L,1L,2L + +#define SN_aes_128_cfb1 "AES-128-CFB1" +#define LN_aes_128_cfb1 "aes-128-cfb1" +#define NID_aes_128_cfb1 650 + +#define SN_aes_192_cfb1 "AES-192-CFB1" +#define LN_aes_192_cfb1 "aes-192-cfb1" +#define NID_aes_192_cfb1 651 + +#define SN_aes_256_cfb1 "AES-256-CFB1" +#define LN_aes_256_cfb1 "aes-256-cfb1" +#define NID_aes_256_cfb1 652 + +#define SN_aes_128_cfb8 "AES-128-CFB8" +#define LN_aes_128_cfb8 "aes-128-cfb8" +#define NID_aes_128_cfb8 653 + +#define SN_aes_192_cfb8 "AES-192-CFB8" +#define LN_aes_192_cfb8 "aes-192-cfb8" +#define NID_aes_192_cfb8 654 + +#define SN_aes_256_cfb8 "AES-256-CFB8" +#define LN_aes_256_cfb8 "aes-256-cfb8" +#define NID_aes_256_cfb8 655 + +#define SN_aes_128_ctr "AES-128-CTR" +#define LN_aes_128_ctr "aes-128-ctr" +#define NID_aes_128_ctr 904 + +#define SN_aes_192_ctr "AES-192-CTR" +#define LN_aes_192_ctr "aes-192-ctr" +#define NID_aes_192_ctr 905 + +#define SN_aes_256_ctr "AES-256-CTR" +#define LN_aes_256_ctr "aes-256-ctr" +#define NID_aes_256_ctr 906 + +#define SN_aes_128_ocb "AES-128-OCB" +#define LN_aes_128_ocb "aes-128-ocb" +#define NID_aes_128_ocb 958 + +#define SN_aes_192_ocb "AES-192-OCB" +#define LN_aes_192_ocb "aes-192-ocb" +#define NID_aes_192_ocb 959 + +#define SN_aes_256_ocb "AES-256-OCB" +#define LN_aes_256_ocb "aes-256-ocb" +#define NID_aes_256_ocb 960 + +#define SN_des_cfb1 "DES-CFB1" +#define LN_des_cfb1 "des-cfb1" +#define NID_des_cfb1 656 + +#define SN_des_cfb8 "DES-CFB8" +#define LN_des_cfb8 "des-cfb8" +#define NID_des_cfb8 657 + +#define SN_des_ede3_cfb1 "DES-EDE3-CFB1" +#define LN_des_ede3_cfb1 "des-ede3-cfb1" +#define NID_des_ede3_cfb1 658 + +#define SN_des_ede3_cfb8 "DES-EDE3-CFB8" +#define LN_des_ede3_cfb8 "des-ede3-cfb8" +#define NID_des_ede3_cfb8 659 + +#define OBJ_nist_hashalgs OBJ_nistAlgorithms,2L + +#define SN_sha256 "SHA256" +#define LN_sha256 "sha256" +#define NID_sha256 672 +#define OBJ_sha256 OBJ_nist_hashalgs,1L + +#define SN_sha384 "SHA384" +#define LN_sha384 "sha384" +#define NID_sha384 673 +#define OBJ_sha384 OBJ_nist_hashalgs,2L + +#define SN_sha512 "SHA512" +#define LN_sha512 "sha512" +#define NID_sha512 674 +#define OBJ_sha512 OBJ_nist_hashalgs,3L + +#define SN_sha224 "SHA224" +#define LN_sha224 "sha224" +#define NID_sha224 675 +#define OBJ_sha224 OBJ_nist_hashalgs,4L + +#define SN_sha512_224 "SHA512-224" +#define LN_sha512_224 "sha512-224" +#define NID_sha512_224 1094 +#define OBJ_sha512_224 OBJ_nist_hashalgs,5L + +#define SN_sha512_256 "SHA512-256" +#define LN_sha512_256 "sha512-256" +#define NID_sha512_256 1095 +#define OBJ_sha512_256 OBJ_nist_hashalgs,6L + +#define SN_sha3_224 "SHA3-224" +#define LN_sha3_224 "sha3-224" +#define NID_sha3_224 1096 +#define OBJ_sha3_224 OBJ_nist_hashalgs,7L + +#define SN_sha3_256 "SHA3-256" +#define LN_sha3_256 "sha3-256" +#define NID_sha3_256 1097 +#define OBJ_sha3_256 OBJ_nist_hashalgs,8L + +#define SN_sha3_384 "SHA3-384" +#define LN_sha3_384 "sha3-384" +#define NID_sha3_384 1098 +#define OBJ_sha3_384 OBJ_nist_hashalgs,9L + +#define SN_sha3_512 "SHA3-512" +#define LN_sha3_512 "sha3-512" +#define NID_sha3_512 1099 +#define OBJ_sha3_512 OBJ_nist_hashalgs,10L + +#define SN_shake128 "SHAKE128" +#define LN_shake128 "shake128" +#define NID_shake128 1100 +#define OBJ_shake128 OBJ_nist_hashalgs,11L + +#define SN_shake256 "SHAKE256" +#define LN_shake256 "shake256" +#define NID_shake256 1101 +#define OBJ_shake256 OBJ_nist_hashalgs,12L + +#define SN_hmac_sha3_224 "id-hmacWithSHA3-224" +#define LN_hmac_sha3_224 "hmac-sha3-224" +#define NID_hmac_sha3_224 1102 +#define OBJ_hmac_sha3_224 OBJ_nist_hashalgs,13L + +#define SN_hmac_sha3_256 "id-hmacWithSHA3-256" +#define LN_hmac_sha3_256 "hmac-sha3-256" +#define NID_hmac_sha3_256 1103 +#define OBJ_hmac_sha3_256 OBJ_nist_hashalgs,14L + +#define SN_hmac_sha3_384 "id-hmacWithSHA3-384" +#define LN_hmac_sha3_384 "hmac-sha3-384" +#define NID_hmac_sha3_384 1104 +#define OBJ_hmac_sha3_384 OBJ_nist_hashalgs,15L + +#define SN_hmac_sha3_512 "id-hmacWithSHA3-512" +#define LN_hmac_sha3_512 "hmac-sha3-512" +#define NID_hmac_sha3_512 1105 +#define OBJ_hmac_sha3_512 OBJ_nist_hashalgs,16L + +#define OBJ_dsa_with_sha2 OBJ_nistAlgorithms,3L + +#define SN_dsa_with_SHA224 "dsa_with_SHA224" +#define NID_dsa_with_SHA224 802 +#define OBJ_dsa_with_SHA224 OBJ_dsa_with_sha2,1L + +#define SN_dsa_with_SHA256 "dsa_with_SHA256" +#define NID_dsa_with_SHA256 803 +#define OBJ_dsa_with_SHA256 OBJ_dsa_with_sha2,2L + +#define OBJ_sigAlgs OBJ_nistAlgorithms,3L + +#define SN_dsa_with_SHA384 "id-dsa-with-sha384" +#define LN_dsa_with_SHA384 "dsa_with_SHA384" +#define NID_dsa_with_SHA384 1106 +#define OBJ_dsa_with_SHA384 OBJ_sigAlgs,3L + +#define SN_dsa_with_SHA512 "id-dsa-with-sha512" +#define LN_dsa_with_SHA512 "dsa_with_SHA512" +#define NID_dsa_with_SHA512 1107 +#define OBJ_dsa_with_SHA512 OBJ_sigAlgs,4L + +#define SN_dsa_with_SHA3_224 "id-dsa-with-sha3-224" +#define LN_dsa_with_SHA3_224 "dsa_with_SHA3-224" +#define NID_dsa_with_SHA3_224 1108 +#define OBJ_dsa_with_SHA3_224 OBJ_sigAlgs,5L + +#define SN_dsa_with_SHA3_256 "id-dsa-with-sha3-256" +#define LN_dsa_with_SHA3_256 "dsa_with_SHA3-256" +#define NID_dsa_with_SHA3_256 1109 +#define OBJ_dsa_with_SHA3_256 OBJ_sigAlgs,6L + +#define SN_dsa_with_SHA3_384 "id-dsa-with-sha3-384" +#define LN_dsa_with_SHA3_384 "dsa_with_SHA3-384" +#define NID_dsa_with_SHA3_384 1110 +#define OBJ_dsa_with_SHA3_384 OBJ_sigAlgs,7L + +#define SN_dsa_with_SHA3_512 "id-dsa-with-sha3-512" +#define LN_dsa_with_SHA3_512 "dsa_with_SHA3-512" +#define NID_dsa_with_SHA3_512 1111 +#define OBJ_dsa_with_SHA3_512 OBJ_sigAlgs,8L + +#define SN_ecdsa_with_SHA3_224 "id-ecdsa-with-sha3-224" +#define LN_ecdsa_with_SHA3_224 "ecdsa_with_SHA3-224" +#define NID_ecdsa_with_SHA3_224 1112 +#define OBJ_ecdsa_with_SHA3_224 OBJ_sigAlgs,9L + +#define SN_ecdsa_with_SHA3_256 "id-ecdsa-with-sha3-256" +#define LN_ecdsa_with_SHA3_256 "ecdsa_with_SHA3-256" +#define NID_ecdsa_with_SHA3_256 1113 +#define OBJ_ecdsa_with_SHA3_256 OBJ_sigAlgs,10L + +#define SN_ecdsa_with_SHA3_384 "id-ecdsa-with-sha3-384" +#define LN_ecdsa_with_SHA3_384 "ecdsa_with_SHA3-384" +#define NID_ecdsa_with_SHA3_384 1114 +#define OBJ_ecdsa_with_SHA3_384 OBJ_sigAlgs,11L + +#define SN_ecdsa_with_SHA3_512 "id-ecdsa-with-sha3-512" +#define LN_ecdsa_with_SHA3_512 "ecdsa_with_SHA3-512" +#define NID_ecdsa_with_SHA3_512 1115 +#define OBJ_ecdsa_with_SHA3_512 OBJ_sigAlgs,12L + +#define SN_RSA_SHA3_224 "id-rsassa-pkcs1-v1_5-with-sha3-224" +#define LN_RSA_SHA3_224 "RSA-SHA3-224" +#define NID_RSA_SHA3_224 1116 +#define OBJ_RSA_SHA3_224 OBJ_sigAlgs,13L + +#define SN_RSA_SHA3_256 "id-rsassa-pkcs1-v1_5-with-sha3-256" +#define LN_RSA_SHA3_256 "RSA-SHA3-256" +#define NID_RSA_SHA3_256 1117 +#define OBJ_RSA_SHA3_256 OBJ_sigAlgs,14L + +#define SN_RSA_SHA3_384 "id-rsassa-pkcs1-v1_5-with-sha3-384" +#define LN_RSA_SHA3_384 "RSA-SHA3-384" +#define NID_RSA_SHA3_384 1118 +#define OBJ_RSA_SHA3_384 OBJ_sigAlgs,15L + +#define SN_RSA_SHA3_512 "id-rsassa-pkcs1-v1_5-with-sha3-512" +#define LN_RSA_SHA3_512 "RSA-SHA3-512" +#define NID_RSA_SHA3_512 1119 +#define OBJ_RSA_SHA3_512 OBJ_sigAlgs,16L + +#define SN_hold_instruction_code "holdInstructionCode" +#define LN_hold_instruction_code "Hold Instruction Code" +#define NID_hold_instruction_code 430 +#define OBJ_hold_instruction_code OBJ_id_ce,23L + +#define OBJ_holdInstruction OBJ_X9_57,2L + +#define SN_hold_instruction_none "holdInstructionNone" +#define LN_hold_instruction_none "Hold Instruction None" +#define NID_hold_instruction_none 431 +#define OBJ_hold_instruction_none OBJ_holdInstruction,1L + +#define SN_hold_instruction_call_issuer "holdInstructionCallIssuer" +#define LN_hold_instruction_call_issuer "Hold Instruction Call Issuer" +#define NID_hold_instruction_call_issuer 432 +#define OBJ_hold_instruction_call_issuer OBJ_holdInstruction,2L + +#define SN_hold_instruction_reject "holdInstructionReject" +#define LN_hold_instruction_reject "Hold Instruction Reject" +#define NID_hold_instruction_reject 433 +#define OBJ_hold_instruction_reject OBJ_holdInstruction,3L + +#define SN_data "data" +#define NID_data 434 +#define OBJ_data OBJ_itu_t,9L + +#define SN_pss "pss" +#define NID_pss 435 +#define OBJ_pss OBJ_data,2342L + +#define SN_ucl "ucl" +#define NID_ucl 436 +#define OBJ_ucl OBJ_pss,19200300L + +#define SN_pilot "pilot" +#define NID_pilot 437 +#define OBJ_pilot OBJ_ucl,100L + +#define LN_pilotAttributeType "pilotAttributeType" +#define NID_pilotAttributeType 438 +#define OBJ_pilotAttributeType OBJ_pilot,1L + +#define LN_pilotAttributeSyntax "pilotAttributeSyntax" +#define NID_pilotAttributeSyntax 439 +#define OBJ_pilotAttributeSyntax OBJ_pilot,3L + +#define LN_pilotObjectClass "pilotObjectClass" +#define NID_pilotObjectClass 440 +#define OBJ_pilotObjectClass OBJ_pilot,4L + +#define LN_pilotGroups "pilotGroups" +#define NID_pilotGroups 441 +#define OBJ_pilotGroups OBJ_pilot,10L + +#define LN_iA5StringSyntax "iA5StringSyntax" +#define NID_iA5StringSyntax 442 +#define OBJ_iA5StringSyntax OBJ_pilotAttributeSyntax,4L + +#define LN_caseIgnoreIA5StringSyntax "caseIgnoreIA5StringSyntax" +#define NID_caseIgnoreIA5StringSyntax 443 +#define OBJ_caseIgnoreIA5StringSyntax OBJ_pilotAttributeSyntax,5L + +#define LN_pilotObject "pilotObject" +#define NID_pilotObject 444 +#define OBJ_pilotObject OBJ_pilotObjectClass,3L + +#define LN_pilotPerson "pilotPerson" +#define NID_pilotPerson 445 +#define OBJ_pilotPerson OBJ_pilotObjectClass,4L + +#define SN_account "account" +#define NID_account 446 +#define OBJ_account OBJ_pilotObjectClass,5L + +#define SN_document "document" +#define NID_document 447 +#define OBJ_document OBJ_pilotObjectClass,6L + +#define SN_room "room" +#define NID_room 448 +#define OBJ_room OBJ_pilotObjectClass,7L + +#define LN_documentSeries "documentSeries" +#define NID_documentSeries 449 +#define OBJ_documentSeries OBJ_pilotObjectClass,9L + +#define SN_Domain "domain" +#define LN_Domain "Domain" +#define NID_Domain 392 +#define OBJ_Domain OBJ_pilotObjectClass,13L + +#define LN_rFC822localPart "rFC822localPart" +#define NID_rFC822localPart 450 +#define OBJ_rFC822localPart OBJ_pilotObjectClass,14L + +#define LN_dNSDomain "dNSDomain" +#define NID_dNSDomain 451 +#define OBJ_dNSDomain OBJ_pilotObjectClass,15L + +#define LN_domainRelatedObject "domainRelatedObject" +#define NID_domainRelatedObject 452 +#define OBJ_domainRelatedObject OBJ_pilotObjectClass,17L + +#define LN_friendlyCountry "friendlyCountry" +#define NID_friendlyCountry 453 +#define OBJ_friendlyCountry OBJ_pilotObjectClass,18L + +#define LN_simpleSecurityObject "simpleSecurityObject" +#define NID_simpleSecurityObject 454 +#define OBJ_simpleSecurityObject OBJ_pilotObjectClass,19L + +#define LN_pilotOrganization "pilotOrganization" +#define NID_pilotOrganization 455 +#define OBJ_pilotOrganization OBJ_pilotObjectClass,20L + +#define LN_pilotDSA "pilotDSA" +#define NID_pilotDSA 456 +#define OBJ_pilotDSA OBJ_pilotObjectClass,21L + +#define LN_qualityLabelledData "qualityLabelledData" +#define NID_qualityLabelledData 457 +#define OBJ_qualityLabelledData OBJ_pilotObjectClass,22L + +#define SN_userId "UID" +#define LN_userId "userId" +#define NID_userId 458 +#define OBJ_userId OBJ_pilotAttributeType,1L + +#define LN_textEncodedORAddress "textEncodedORAddress" +#define NID_textEncodedORAddress 459 +#define OBJ_textEncodedORAddress OBJ_pilotAttributeType,2L + +#define SN_rfc822Mailbox "mail" +#define LN_rfc822Mailbox "rfc822Mailbox" +#define NID_rfc822Mailbox 460 +#define OBJ_rfc822Mailbox OBJ_pilotAttributeType,3L + +#define SN_info "info" +#define NID_info 461 +#define OBJ_info OBJ_pilotAttributeType,4L + +#define LN_favouriteDrink "favouriteDrink" +#define NID_favouriteDrink 462 +#define OBJ_favouriteDrink OBJ_pilotAttributeType,5L + +#define LN_roomNumber "roomNumber" +#define NID_roomNumber 463 +#define OBJ_roomNumber OBJ_pilotAttributeType,6L + +#define SN_photo "photo" +#define NID_photo 464 +#define OBJ_photo OBJ_pilotAttributeType,7L + +#define LN_userClass "userClass" +#define NID_userClass 465 +#define OBJ_userClass OBJ_pilotAttributeType,8L + +#define SN_host "host" +#define NID_host 466 +#define OBJ_host OBJ_pilotAttributeType,9L + +#define SN_manager "manager" +#define NID_manager 467 +#define OBJ_manager OBJ_pilotAttributeType,10L + +#define LN_documentIdentifier "documentIdentifier" +#define NID_documentIdentifier 468 +#define OBJ_documentIdentifier OBJ_pilotAttributeType,11L + +#define LN_documentTitle "documentTitle" +#define NID_documentTitle 469 +#define OBJ_documentTitle OBJ_pilotAttributeType,12L + +#define LN_documentVersion "documentVersion" +#define NID_documentVersion 470 +#define OBJ_documentVersion OBJ_pilotAttributeType,13L + +#define LN_documentAuthor "documentAuthor" +#define NID_documentAuthor 471 +#define OBJ_documentAuthor OBJ_pilotAttributeType,14L + +#define LN_documentLocation "documentLocation" +#define NID_documentLocation 472 +#define OBJ_documentLocation OBJ_pilotAttributeType,15L + +#define LN_homeTelephoneNumber "homeTelephoneNumber" +#define NID_homeTelephoneNumber 473 +#define OBJ_homeTelephoneNumber OBJ_pilotAttributeType,20L + +#define SN_secretary "secretary" +#define NID_secretary 474 +#define OBJ_secretary OBJ_pilotAttributeType,21L + +#define LN_otherMailbox "otherMailbox" +#define NID_otherMailbox 475 +#define OBJ_otherMailbox OBJ_pilotAttributeType,22L + +#define LN_lastModifiedTime "lastModifiedTime" +#define NID_lastModifiedTime 476 +#define OBJ_lastModifiedTime OBJ_pilotAttributeType,23L + +#define LN_lastModifiedBy "lastModifiedBy" +#define NID_lastModifiedBy 477 +#define OBJ_lastModifiedBy OBJ_pilotAttributeType,24L + +#define SN_domainComponent "DC" +#define LN_domainComponent "domainComponent" +#define NID_domainComponent 391 +#define OBJ_domainComponent OBJ_pilotAttributeType,25L + +#define LN_aRecord "aRecord" +#define NID_aRecord 478 +#define OBJ_aRecord OBJ_pilotAttributeType,26L + +#define LN_pilotAttributeType27 "pilotAttributeType27" +#define NID_pilotAttributeType27 479 +#define OBJ_pilotAttributeType27 OBJ_pilotAttributeType,27L + +#define LN_mXRecord "mXRecord" +#define NID_mXRecord 480 +#define OBJ_mXRecord OBJ_pilotAttributeType,28L + +#define LN_nSRecord "nSRecord" +#define NID_nSRecord 481 +#define OBJ_nSRecord OBJ_pilotAttributeType,29L + +#define LN_sOARecord "sOARecord" +#define NID_sOARecord 482 +#define OBJ_sOARecord OBJ_pilotAttributeType,30L + +#define LN_cNAMERecord "cNAMERecord" +#define NID_cNAMERecord 483 +#define OBJ_cNAMERecord OBJ_pilotAttributeType,31L + +#define LN_associatedDomain "associatedDomain" +#define NID_associatedDomain 484 +#define OBJ_associatedDomain OBJ_pilotAttributeType,37L + +#define LN_associatedName "associatedName" +#define NID_associatedName 485 +#define OBJ_associatedName OBJ_pilotAttributeType,38L + +#define LN_homePostalAddress "homePostalAddress" +#define NID_homePostalAddress 486 +#define OBJ_homePostalAddress OBJ_pilotAttributeType,39L + +#define LN_personalTitle "personalTitle" +#define NID_personalTitle 487 +#define OBJ_personalTitle OBJ_pilotAttributeType,40L + +#define LN_mobileTelephoneNumber "mobileTelephoneNumber" +#define NID_mobileTelephoneNumber 488 +#define OBJ_mobileTelephoneNumber OBJ_pilotAttributeType,41L + +#define LN_pagerTelephoneNumber "pagerTelephoneNumber" +#define NID_pagerTelephoneNumber 489 +#define OBJ_pagerTelephoneNumber OBJ_pilotAttributeType,42L + +#define LN_friendlyCountryName "friendlyCountryName" +#define NID_friendlyCountryName 490 +#define OBJ_friendlyCountryName OBJ_pilotAttributeType,43L + +#define SN_uniqueIdentifier "uid" +#define LN_uniqueIdentifier "uniqueIdentifier" +#define NID_uniqueIdentifier 102 +#define OBJ_uniqueIdentifier OBJ_pilotAttributeType,44L + +#define LN_organizationalStatus "organizationalStatus" +#define NID_organizationalStatus 491 +#define OBJ_organizationalStatus OBJ_pilotAttributeType,45L + +#define LN_janetMailbox "janetMailbox" +#define NID_janetMailbox 492 +#define OBJ_janetMailbox OBJ_pilotAttributeType,46L + +#define LN_mailPreferenceOption "mailPreferenceOption" +#define NID_mailPreferenceOption 493 +#define OBJ_mailPreferenceOption OBJ_pilotAttributeType,47L + +#define LN_buildingName "buildingName" +#define NID_buildingName 494 +#define OBJ_buildingName OBJ_pilotAttributeType,48L + +#define LN_dSAQuality "dSAQuality" +#define NID_dSAQuality 495 +#define OBJ_dSAQuality OBJ_pilotAttributeType,49L + +#define LN_singleLevelQuality "singleLevelQuality" +#define NID_singleLevelQuality 496 +#define OBJ_singleLevelQuality OBJ_pilotAttributeType,50L + +#define LN_subtreeMinimumQuality "subtreeMinimumQuality" +#define NID_subtreeMinimumQuality 497 +#define OBJ_subtreeMinimumQuality OBJ_pilotAttributeType,51L + +#define LN_subtreeMaximumQuality "subtreeMaximumQuality" +#define NID_subtreeMaximumQuality 498 +#define OBJ_subtreeMaximumQuality OBJ_pilotAttributeType,52L + +#define LN_personalSignature "personalSignature" +#define NID_personalSignature 499 +#define OBJ_personalSignature OBJ_pilotAttributeType,53L + +#define LN_dITRedirect "dITRedirect" +#define NID_dITRedirect 500 +#define OBJ_dITRedirect OBJ_pilotAttributeType,54L + +#define SN_audio "audio" +#define NID_audio 501 +#define OBJ_audio OBJ_pilotAttributeType,55L + +#define LN_documentPublisher "documentPublisher" +#define NID_documentPublisher 502 +#define OBJ_documentPublisher OBJ_pilotAttributeType,56L + +#define SN_id_set "id-set" +#define LN_id_set "Secure Electronic Transactions" +#define NID_id_set 512 +#define OBJ_id_set OBJ_international_organizations,42L + +#define SN_set_ctype "set-ctype" +#define LN_set_ctype "content types" +#define NID_set_ctype 513 +#define OBJ_set_ctype OBJ_id_set,0L + +#define SN_set_msgExt "set-msgExt" +#define LN_set_msgExt "message extensions" +#define NID_set_msgExt 514 +#define OBJ_set_msgExt OBJ_id_set,1L + +#define SN_set_attr "set-attr" +#define NID_set_attr 515 +#define OBJ_set_attr OBJ_id_set,3L + +#define SN_set_policy "set-policy" +#define NID_set_policy 516 +#define OBJ_set_policy OBJ_id_set,5L + +#define SN_set_certExt "set-certExt" +#define LN_set_certExt "certificate extensions" +#define NID_set_certExt 517 +#define OBJ_set_certExt OBJ_id_set,7L + +#define SN_set_brand "set-brand" +#define NID_set_brand 518 +#define OBJ_set_brand OBJ_id_set,8L + +#define SN_setct_PANData "setct-PANData" +#define NID_setct_PANData 519 +#define OBJ_setct_PANData OBJ_set_ctype,0L + +#define SN_setct_PANToken "setct-PANToken" +#define NID_setct_PANToken 520 +#define OBJ_setct_PANToken OBJ_set_ctype,1L + +#define SN_setct_PANOnly "setct-PANOnly" +#define NID_setct_PANOnly 521 +#define OBJ_setct_PANOnly OBJ_set_ctype,2L + +#define SN_setct_OIData "setct-OIData" +#define NID_setct_OIData 522 +#define OBJ_setct_OIData OBJ_set_ctype,3L + +#define SN_setct_PI "setct-PI" +#define NID_setct_PI 523 +#define OBJ_setct_PI OBJ_set_ctype,4L + +#define SN_setct_PIData "setct-PIData" +#define NID_setct_PIData 524 +#define OBJ_setct_PIData OBJ_set_ctype,5L + +#define SN_setct_PIDataUnsigned "setct-PIDataUnsigned" +#define NID_setct_PIDataUnsigned 525 +#define OBJ_setct_PIDataUnsigned OBJ_set_ctype,6L + +#define SN_setct_HODInput "setct-HODInput" +#define NID_setct_HODInput 526 +#define OBJ_setct_HODInput OBJ_set_ctype,7L + +#define SN_setct_AuthResBaggage "setct-AuthResBaggage" +#define NID_setct_AuthResBaggage 527 +#define OBJ_setct_AuthResBaggage OBJ_set_ctype,8L + +#define SN_setct_AuthRevReqBaggage "setct-AuthRevReqBaggage" +#define NID_setct_AuthRevReqBaggage 528 +#define OBJ_setct_AuthRevReqBaggage OBJ_set_ctype,9L + +#define SN_setct_AuthRevResBaggage "setct-AuthRevResBaggage" +#define NID_setct_AuthRevResBaggage 529 +#define OBJ_setct_AuthRevResBaggage OBJ_set_ctype,10L + +#define SN_setct_CapTokenSeq "setct-CapTokenSeq" +#define NID_setct_CapTokenSeq 530 +#define OBJ_setct_CapTokenSeq OBJ_set_ctype,11L + +#define SN_setct_PInitResData "setct-PInitResData" +#define NID_setct_PInitResData 531 +#define OBJ_setct_PInitResData OBJ_set_ctype,12L + +#define SN_setct_PI_TBS "setct-PI-TBS" +#define NID_setct_PI_TBS 532 +#define OBJ_setct_PI_TBS OBJ_set_ctype,13L + +#define SN_setct_PResData "setct-PResData" +#define NID_setct_PResData 533 +#define OBJ_setct_PResData OBJ_set_ctype,14L + +#define SN_setct_AuthReqTBS "setct-AuthReqTBS" +#define NID_setct_AuthReqTBS 534 +#define OBJ_setct_AuthReqTBS OBJ_set_ctype,16L + +#define SN_setct_AuthResTBS "setct-AuthResTBS" +#define NID_setct_AuthResTBS 535 +#define OBJ_setct_AuthResTBS OBJ_set_ctype,17L + +#define SN_setct_AuthResTBSX "setct-AuthResTBSX" +#define NID_setct_AuthResTBSX 536 +#define OBJ_setct_AuthResTBSX OBJ_set_ctype,18L + +#define SN_setct_AuthTokenTBS "setct-AuthTokenTBS" +#define NID_setct_AuthTokenTBS 537 +#define OBJ_setct_AuthTokenTBS OBJ_set_ctype,19L + +#define SN_setct_CapTokenData "setct-CapTokenData" +#define NID_setct_CapTokenData 538 +#define OBJ_setct_CapTokenData OBJ_set_ctype,20L + +#define SN_setct_CapTokenTBS "setct-CapTokenTBS" +#define NID_setct_CapTokenTBS 539 +#define OBJ_setct_CapTokenTBS OBJ_set_ctype,21L + +#define SN_setct_AcqCardCodeMsg "setct-AcqCardCodeMsg" +#define NID_setct_AcqCardCodeMsg 540 +#define OBJ_setct_AcqCardCodeMsg OBJ_set_ctype,22L + +#define SN_setct_AuthRevReqTBS "setct-AuthRevReqTBS" +#define NID_setct_AuthRevReqTBS 541 +#define OBJ_setct_AuthRevReqTBS OBJ_set_ctype,23L + +#define SN_setct_AuthRevResData "setct-AuthRevResData" +#define NID_setct_AuthRevResData 542 +#define OBJ_setct_AuthRevResData OBJ_set_ctype,24L + +#define SN_setct_AuthRevResTBS "setct-AuthRevResTBS" +#define NID_setct_AuthRevResTBS 543 +#define OBJ_setct_AuthRevResTBS OBJ_set_ctype,25L + +#define SN_setct_CapReqTBS "setct-CapReqTBS" +#define NID_setct_CapReqTBS 544 +#define OBJ_setct_CapReqTBS OBJ_set_ctype,26L + +#define SN_setct_CapReqTBSX "setct-CapReqTBSX" +#define NID_setct_CapReqTBSX 545 +#define OBJ_setct_CapReqTBSX OBJ_set_ctype,27L + +#define SN_setct_CapResData "setct-CapResData" +#define NID_setct_CapResData 546 +#define OBJ_setct_CapResData OBJ_set_ctype,28L + +#define SN_setct_CapRevReqTBS "setct-CapRevReqTBS" +#define NID_setct_CapRevReqTBS 547 +#define OBJ_setct_CapRevReqTBS OBJ_set_ctype,29L + +#define SN_setct_CapRevReqTBSX "setct-CapRevReqTBSX" +#define NID_setct_CapRevReqTBSX 548 +#define OBJ_setct_CapRevReqTBSX OBJ_set_ctype,30L + +#define SN_setct_CapRevResData "setct-CapRevResData" +#define NID_setct_CapRevResData 549 +#define OBJ_setct_CapRevResData OBJ_set_ctype,31L + +#define SN_setct_CredReqTBS "setct-CredReqTBS" +#define NID_setct_CredReqTBS 550 +#define OBJ_setct_CredReqTBS OBJ_set_ctype,32L + +#define SN_setct_CredReqTBSX "setct-CredReqTBSX" +#define NID_setct_CredReqTBSX 551 +#define OBJ_setct_CredReqTBSX OBJ_set_ctype,33L + +#define SN_setct_CredResData "setct-CredResData" +#define NID_setct_CredResData 552 +#define OBJ_setct_CredResData OBJ_set_ctype,34L + +#define SN_setct_CredRevReqTBS "setct-CredRevReqTBS" +#define NID_setct_CredRevReqTBS 553 +#define OBJ_setct_CredRevReqTBS OBJ_set_ctype,35L + +#define SN_setct_CredRevReqTBSX "setct-CredRevReqTBSX" +#define NID_setct_CredRevReqTBSX 554 +#define OBJ_setct_CredRevReqTBSX OBJ_set_ctype,36L + +#define SN_setct_CredRevResData "setct-CredRevResData" +#define NID_setct_CredRevResData 555 +#define OBJ_setct_CredRevResData OBJ_set_ctype,37L + +#define SN_setct_PCertReqData "setct-PCertReqData" +#define NID_setct_PCertReqData 556 +#define OBJ_setct_PCertReqData OBJ_set_ctype,38L + +#define SN_setct_PCertResTBS "setct-PCertResTBS" +#define NID_setct_PCertResTBS 557 +#define OBJ_setct_PCertResTBS OBJ_set_ctype,39L + +#define SN_setct_BatchAdminReqData "setct-BatchAdminReqData" +#define NID_setct_BatchAdminReqData 558 +#define OBJ_setct_BatchAdminReqData OBJ_set_ctype,40L + +#define SN_setct_BatchAdminResData "setct-BatchAdminResData" +#define NID_setct_BatchAdminResData 559 +#define OBJ_setct_BatchAdminResData OBJ_set_ctype,41L + +#define SN_setct_CardCInitResTBS "setct-CardCInitResTBS" +#define NID_setct_CardCInitResTBS 560 +#define OBJ_setct_CardCInitResTBS OBJ_set_ctype,42L + +#define SN_setct_MeAqCInitResTBS "setct-MeAqCInitResTBS" +#define NID_setct_MeAqCInitResTBS 561 +#define OBJ_setct_MeAqCInitResTBS OBJ_set_ctype,43L + +#define SN_setct_RegFormResTBS "setct-RegFormResTBS" +#define NID_setct_RegFormResTBS 562 +#define OBJ_setct_RegFormResTBS OBJ_set_ctype,44L + +#define SN_setct_CertReqData "setct-CertReqData" +#define NID_setct_CertReqData 563 +#define OBJ_setct_CertReqData OBJ_set_ctype,45L + +#define SN_setct_CertReqTBS "setct-CertReqTBS" +#define NID_setct_CertReqTBS 564 +#define OBJ_setct_CertReqTBS OBJ_set_ctype,46L + +#define SN_setct_CertResData "setct-CertResData" +#define NID_setct_CertResData 565 +#define OBJ_setct_CertResData OBJ_set_ctype,47L + +#define SN_setct_CertInqReqTBS "setct-CertInqReqTBS" +#define NID_setct_CertInqReqTBS 566 +#define OBJ_setct_CertInqReqTBS OBJ_set_ctype,48L + +#define SN_setct_ErrorTBS "setct-ErrorTBS" +#define NID_setct_ErrorTBS 567 +#define OBJ_setct_ErrorTBS OBJ_set_ctype,49L + +#define SN_setct_PIDualSignedTBE "setct-PIDualSignedTBE" +#define NID_setct_PIDualSignedTBE 568 +#define OBJ_setct_PIDualSignedTBE OBJ_set_ctype,50L + +#define SN_setct_PIUnsignedTBE "setct-PIUnsignedTBE" +#define NID_setct_PIUnsignedTBE 569 +#define OBJ_setct_PIUnsignedTBE OBJ_set_ctype,51L + +#define SN_setct_AuthReqTBE "setct-AuthReqTBE" +#define NID_setct_AuthReqTBE 570 +#define OBJ_setct_AuthReqTBE OBJ_set_ctype,52L + +#define SN_setct_AuthResTBE "setct-AuthResTBE" +#define NID_setct_AuthResTBE 571 +#define OBJ_setct_AuthResTBE OBJ_set_ctype,53L + +#define SN_setct_AuthResTBEX "setct-AuthResTBEX" +#define NID_setct_AuthResTBEX 572 +#define OBJ_setct_AuthResTBEX OBJ_set_ctype,54L + +#define SN_setct_AuthTokenTBE "setct-AuthTokenTBE" +#define NID_setct_AuthTokenTBE 573 +#define OBJ_setct_AuthTokenTBE OBJ_set_ctype,55L + +#define SN_setct_CapTokenTBE "setct-CapTokenTBE" +#define NID_setct_CapTokenTBE 574 +#define OBJ_setct_CapTokenTBE OBJ_set_ctype,56L + +#define SN_setct_CapTokenTBEX "setct-CapTokenTBEX" +#define NID_setct_CapTokenTBEX 575 +#define OBJ_setct_CapTokenTBEX OBJ_set_ctype,57L + +#define SN_setct_AcqCardCodeMsgTBE "setct-AcqCardCodeMsgTBE" +#define NID_setct_AcqCardCodeMsgTBE 576 +#define OBJ_setct_AcqCardCodeMsgTBE OBJ_set_ctype,58L + +#define SN_setct_AuthRevReqTBE "setct-AuthRevReqTBE" +#define NID_setct_AuthRevReqTBE 577 +#define OBJ_setct_AuthRevReqTBE OBJ_set_ctype,59L + +#define SN_setct_AuthRevResTBE "setct-AuthRevResTBE" +#define NID_setct_AuthRevResTBE 578 +#define OBJ_setct_AuthRevResTBE OBJ_set_ctype,60L + +#define SN_setct_AuthRevResTBEB "setct-AuthRevResTBEB" +#define NID_setct_AuthRevResTBEB 579 +#define OBJ_setct_AuthRevResTBEB OBJ_set_ctype,61L + +#define SN_setct_CapReqTBE "setct-CapReqTBE" +#define NID_setct_CapReqTBE 580 +#define OBJ_setct_CapReqTBE OBJ_set_ctype,62L + +#define SN_setct_CapReqTBEX "setct-CapReqTBEX" +#define NID_setct_CapReqTBEX 581 +#define OBJ_setct_CapReqTBEX OBJ_set_ctype,63L + +#define SN_setct_CapResTBE "setct-CapResTBE" +#define NID_setct_CapResTBE 582 +#define OBJ_setct_CapResTBE OBJ_set_ctype,64L + +#define SN_setct_CapRevReqTBE "setct-CapRevReqTBE" +#define NID_setct_CapRevReqTBE 583 +#define OBJ_setct_CapRevReqTBE OBJ_set_ctype,65L + +#define SN_setct_CapRevReqTBEX "setct-CapRevReqTBEX" +#define NID_setct_CapRevReqTBEX 584 +#define OBJ_setct_CapRevReqTBEX OBJ_set_ctype,66L + +#define SN_setct_CapRevResTBE "setct-CapRevResTBE" +#define NID_setct_CapRevResTBE 585 +#define OBJ_setct_CapRevResTBE OBJ_set_ctype,67L + +#define SN_setct_CredReqTBE "setct-CredReqTBE" +#define NID_setct_CredReqTBE 586 +#define OBJ_setct_CredReqTBE OBJ_set_ctype,68L + +#define SN_setct_CredReqTBEX "setct-CredReqTBEX" +#define NID_setct_CredReqTBEX 587 +#define OBJ_setct_CredReqTBEX OBJ_set_ctype,69L + +#define SN_setct_CredResTBE "setct-CredResTBE" +#define NID_setct_CredResTBE 588 +#define OBJ_setct_CredResTBE OBJ_set_ctype,70L + +#define SN_setct_CredRevReqTBE "setct-CredRevReqTBE" +#define NID_setct_CredRevReqTBE 589 +#define OBJ_setct_CredRevReqTBE OBJ_set_ctype,71L + +#define SN_setct_CredRevReqTBEX "setct-CredRevReqTBEX" +#define NID_setct_CredRevReqTBEX 590 +#define OBJ_setct_CredRevReqTBEX OBJ_set_ctype,72L + +#define SN_setct_CredRevResTBE "setct-CredRevResTBE" +#define NID_setct_CredRevResTBE 591 +#define OBJ_setct_CredRevResTBE OBJ_set_ctype,73L + +#define SN_setct_BatchAdminReqTBE "setct-BatchAdminReqTBE" +#define NID_setct_BatchAdminReqTBE 592 +#define OBJ_setct_BatchAdminReqTBE OBJ_set_ctype,74L + +#define SN_setct_BatchAdminResTBE "setct-BatchAdminResTBE" +#define NID_setct_BatchAdminResTBE 593 +#define OBJ_setct_BatchAdminResTBE OBJ_set_ctype,75L + +#define SN_setct_RegFormReqTBE "setct-RegFormReqTBE" +#define NID_setct_RegFormReqTBE 594 +#define OBJ_setct_RegFormReqTBE OBJ_set_ctype,76L + +#define SN_setct_CertReqTBE "setct-CertReqTBE" +#define NID_setct_CertReqTBE 595 +#define OBJ_setct_CertReqTBE OBJ_set_ctype,77L + +#define SN_setct_CertReqTBEX "setct-CertReqTBEX" +#define NID_setct_CertReqTBEX 596 +#define OBJ_setct_CertReqTBEX OBJ_set_ctype,78L + +#define SN_setct_CertResTBE "setct-CertResTBE" +#define NID_setct_CertResTBE 597 +#define OBJ_setct_CertResTBE OBJ_set_ctype,79L + +#define SN_setct_CRLNotificationTBS "setct-CRLNotificationTBS" +#define NID_setct_CRLNotificationTBS 598 +#define OBJ_setct_CRLNotificationTBS OBJ_set_ctype,80L + +#define SN_setct_CRLNotificationResTBS "setct-CRLNotificationResTBS" +#define NID_setct_CRLNotificationResTBS 599 +#define OBJ_setct_CRLNotificationResTBS OBJ_set_ctype,81L + +#define SN_setct_BCIDistributionTBS "setct-BCIDistributionTBS" +#define NID_setct_BCIDistributionTBS 600 +#define OBJ_setct_BCIDistributionTBS OBJ_set_ctype,82L + +#define SN_setext_genCrypt "setext-genCrypt" +#define LN_setext_genCrypt "generic cryptogram" +#define NID_setext_genCrypt 601 +#define OBJ_setext_genCrypt OBJ_set_msgExt,1L + +#define SN_setext_miAuth "setext-miAuth" +#define LN_setext_miAuth "merchant initiated auth" +#define NID_setext_miAuth 602 +#define OBJ_setext_miAuth OBJ_set_msgExt,3L + +#define SN_setext_pinSecure "setext-pinSecure" +#define NID_setext_pinSecure 603 +#define OBJ_setext_pinSecure OBJ_set_msgExt,4L + +#define SN_setext_pinAny "setext-pinAny" +#define NID_setext_pinAny 604 +#define OBJ_setext_pinAny OBJ_set_msgExt,5L + +#define SN_setext_track2 "setext-track2" +#define NID_setext_track2 605 +#define OBJ_setext_track2 OBJ_set_msgExt,7L + +#define SN_setext_cv "setext-cv" +#define LN_setext_cv "additional verification" +#define NID_setext_cv 606 +#define OBJ_setext_cv OBJ_set_msgExt,8L + +#define SN_set_policy_root "set-policy-root" +#define NID_set_policy_root 607 +#define OBJ_set_policy_root OBJ_set_policy,0L + +#define SN_setCext_hashedRoot "setCext-hashedRoot" +#define NID_setCext_hashedRoot 608 +#define OBJ_setCext_hashedRoot OBJ_set_certExt,0L + +#define SN_setCext_certType "setCext-certType" +#define NID_setCext_certType 609 +#define OBJ_setCext_certType OBJ_set_certExt,1L + +#define SN_setCext_merchData "setCext-merchData" +#define NID_setCext_merchData 610 +#define OBJ_setCext_merchData OBJ_set_certExt,2L + +#define SN_setCext_cCertRequired "setCext-cCertRequired" +#define NID_setCext_cCertRequired 611 +#define OBJ_setCext_cCertRequired OBJ_set_certExt,3L + +#define SN_setCext_tunneling "setCext-tunneling" +#define NID_setCext_tunneling 612 +#define OBJ_setCext_tunneling OBJ_set_certExt,4L + +#define SN_setCext_setExt "setCext-setExt" +#define NID_setCext_setExt 613 +#define OBJ_setCext_setExt OBJ_set_certExt,5L + +#define SN_setCext_setQualf "setCext-setQualf" +#define NID_setCext_setQualf 614 +#define OBJ_setCext_setQualf OBJ_set_certExt,6L + +#define SN_setCext_PGWYcapabilities "setCext-PGWYcapabilities" +#define NID_setCext_PGWYcapabilities 615 +#define OBJ_setCext_PGWYcapabilities OBJ_set_certExt,7L + +#define SN_setCext_TokenIdentifier "setCext-TokenIdentifier" +#define NID_setCext_TokenIdentifier 616 +#define OBJ_setCext_TokenIdentifier OBJ_set_certExt,8L + +#define SN_setCext_Track2Data "setCext-Track2Data" +#define NID_setCext_Track2Data 617 +#define OBJ_setCext_Track2Data OBJ_set_certExt,9L + +#define SN_setCext_TokenType "setCext-TokenType" +#define NID_setCext_TokenType 618 +#define OBJ_setCext_TokenType OBJ_set_certExt,10L + +#define SN_setCext_IssuerCapabilities "setCext-IssuerCapabilities" +#define NID_setCext_IssuerCapabilities 619 +#define OBJ_setCext_IssuerCapabilities OBJ_set_certExt,11L + +#define SN_setAttr_Cert "setAttr-Cert" +#define NID_setAttr_Cert 620 +#define OBJ_setAttr_Cert OBJ_set_attr,0L + +#define SN_setAttr_PGWYcap "setAttr-PGWYcap" +#define LN_setAttr_PGWYcap "payment gateway capabilities" +#define NID_setAttr_PGWYcap 621 +#define OBJ_setAttr_PGWYcap OBJ_set_attr,1L + +#define SN_setAttr_TokenType "setAttr-TokenType" +#define NID_setAttr_TokenType 622 +#define OBJ_setAttr_TokenType OBJ_set_attr,2L + +#define SN_setAttr_IssCap "setAttr-IssCap" +#define LN_setAttr_IssCap "issuer capabilities" +#define NID_setAttr_IssCap 623 +#define OBJ_setAttr_IssCap OBJ_set_attr,3L + +#define SN_set_rootKeyThumb "set-rootKeyThumb" +#define NID_set_rootKeyThumb 624 +#define OBJ_set_rootKeyThumb OBJ_setAttr_Cert,0L + +#define SN_set_addPolicy "set-addPolicy" +#define NID_set_addPolicy 625 +#define OBJ_set_addPolicy OBJ_setAttr_Cert,1L + +#define SN_setAttr_Token_EMV "setAttr-Token-EMV" +#define NID_setAttr_Token_EMV 626 +#define OBJ_setAttr_Token_EMV OBJ_setAttr_TokenType,1L + +#define SN_setAttr_Token_B0Prime "setAttr-Token-B0Prime" +#define NID_setAttr_Token_B0Prime 627 +#define OBJ_setAttr_Token_B0Prime OBJ_setAttr_TokenType,2L + +#define SN_setAttr_IssCap_CVM "setAttr-IssCap-CVM" +#define NID_setAttr_IssCap_CVM 628 +#define OBJ_setAttr_IssCap_CVM OBJ_setAttr_IssCap,3L + +#define SN_setAttr_IssCap_T2 "setAttr-IssCap-T2" +#define NID_setAttr_IssCap_T2 629 +#define OBJ_setAttr_IssCap_T2 OBJ_setAttr_IssCap,4L + +#define SN_setAttr_IssCap_Sig "setAttr-IssCap-Sig" +#define NID_setAttr_IssCap_Sig 630 +#define OBJ_setAttr_IssCap_Sig OBJ_setAttr_IssCap,5L + +#define SN_setAttr_GenCryptgrm "setAttr-GenCryptgrm" +#define LN_setAttr_GenCryptgrm "generate cryptogram" +#define NID_setAttr_GenCryptgrm 631 +#define OBJ_setAttr_GenCryptgrm OBJ_setAttr_IssCap_CVM,1L + +#define SN_setAttr_T2Enc "setAttr-T2Enc" +#define LN_setAttr_T2Enc "encrypted track 2" +#define NID_setAttr_T2Enc 632 +#define OBJ_setAttr_T2Enc OBJ_setAttr_IssCap_T2,1L + +#define SN_setAttr_T2cleartxt "setAttr-T2cleartxt" +#define LN_setAttr_T2cleartxt "cleartext track 2" +#define NID_setAttr_T2cleartxt 633 +#define OBJ_setAttr_T2cleartxt OBJ_setAttr_IssCap_T2,2L + +#define SN_setAttr_TokICCsig "setAttr-TokICCsig" +#define LN_setAttr_TokICCsig "ICC or token signature" +#define NID_setAttr_TokICCsig 634 +#define OBJ_setAttr_TokICCsig OBJ_setAttr_IssCap_Sig,1L + +#define SN_setAttr_SecDevSig "setAttr-SecDevSig" +#define LN_setAttr_SecDevSig "secure device signature" +#define NID_setAttr_SecDevSig 635 +#define OBJ_setAttr_SecDevSig OBJ_setAttr_IssCap_Sig,2L + +#define SN_set_brand_IATA_ATA "set-brand-IATA-ATA" +#define NID_set_brand_IATA_ATA 636 +#define OBJ_set_brand_IATA_ATA OBJ_set_brand,1L + +#define SN_set_brand_Diners "set-brand-Diners" +#define NID_set_brand_Diners 637 +#define OBJ_set_brand_Diners OBJ_set_brand,30L + +#define SN_set_brand_AmericanExpress "set-brand-AmericanExpress" +#define NID_set_brand_AmericanExpress 638 +#define OBJ_set_brand_AmericanExpress OBJ_set_brand,34L + +#define SN_set_brand_JCB "set-brand-JCB" +#define NID_set_brand_JCB 639 +#define OBJ_set_brand_JCB OBJ_set_brand,35L + +#define SN_set_brand_Visa "set-brand-Visa" +#define NID_set_brand_Visa 640 +#define OBJ_set_brand_Visa OBJ_set_brand,4L + +#define SN_set_brand_MasterCard "set-brand-MasterCard" +#define NID_set_brand_MasterCard 641 +#define OBJ_set_brand_MasterCard OBJ_set_brand,5L + +#define SN_set_brand_Novus "set-brand-Novus" +#define NID_set_brand_Novus 642 +#define OBJ_set_brand_Novus OBJ_set_brand,6011L + +#define SN_des_cdmf "DES-CDMF" +#define LN_des_cdmf "des-cdmf" +#define NID_des_cdmf 643 +#define OBJ_des_cdmf OBJ_rsadsi,3L,10L + +#define SN_rsaOAEPEncryptionSET "rsaOAEPEncryptionSET" +#define NID_rsaOAEPEncryptionSET 644 +#define OBJ_rsaOAEPEncryptionSET OBJ_rsadsi,1L,1L,6L + +#define SN_ipsec3 "Oakley-EC2N-3" +#define LN_ipsec3 "ipsec3" +#define NID_ipsec3 749 + +#define SN_ipsec4 "Oakley-EC2N-4" +#define LN_ipsec4 "ipsec4" +#define NID_ipsec4 750 + +#define SN_whirlpool "whirlpool" +#define NID_whirlpool 804 +#define OBJ_whirlpool OBJ_iso,0L,10118L,3L,0L,55L + +#define SN_cryptopro "cryptopro" +#define NID_cryptopro 805 +#define OBJ_cryptopro OBJ_member_body,643L,2L,2L + +#define SN_cryptocom "cryptocom" +#define NID_cryptocom 806 +#define OBJ_cryptocom OBJ_member_body,643L,2L,9L + +#define SN_id_tc26 "id-tc26" +#define NID_id_tc26 974 +#define OBJ_id_tc26 OBJ_member_body,643L,7L,1L + +#define SN_id_GostR3411_94_with_GostR3410_2001 "id-GostR3411-94-with-GostR3410-2001" +#define LN_id_GostR3411_94_with_GostR3410_2001 "GOST R 34.11-94 with GOST R 34.10-2001" +#define NID_id_GostR3411_94_with_GostR3410_2001 807 +#define OBJ_id_GostR3411_94_with_GostR3410_2001 OBJ_cryptopro,3L + +#define SN_id_GostR3411_94_with_GostR3410_94 "id-GostR3411-94-with-GostR3410-94" +#define LN_id_GostR3411_94_with_GostR3410_94 "GOST R 34.11-94 with GOST R 34.10-94" +#define NID_id_GostR3411_94_with_GostR3410_94 808 +#define OBJ_id_GostR3411_94_with_GostR3410_94 OBJ_cryptopro,4L + +#define SN_id_GostR3411_94 "md_gost94" +#define LN_id_GostR3411_94 "GOST R 34.11-94" +#define NID_id_GostR3411_94 809 +#define OBJ_id_GostR3411_94 OBJ_cryptopro,9L + +#define SN_id_HMACGostR3411_94 "id-HMACGostR3411-94" +#define LN_id_HMACGostR3411_94 "HMAC GOST 34.11-94" +#define NID_id_HMACGostR3411_94 810 +#define OBJ_id_HMACGostR3411_94 OBJ_cryptopro,10L + +#define SN_id_GostR3410_2001 "gost2001" +#define LN_id_GostR3410_2001 "GOST R 34.10-2001" +#define NID_id_GostR3410_2001 811 +#define OBJ_id_GostR3410_2001 OBJ_cryptopro,19L + +#define SN_id_GostR3410_94 "gost94" +#define LN_id_GostR3410_94 "GOST R 34.10-94" +#define NID_id_GostR3410_94 812 +#define OBJ_id_GostR3410_94 OBJ_cryptopro,20L + +#define SN_id_Gost28147_89 "gost89" +#define LN_id_Gost28147_89 "GOST 28147-89" +#define NID_id_Gost28147_89 813 +#define OBJ_id_Gost28147_89 OBJ_cryptopro,21L + +#define SN_gost89_cnt "gost89-cnt" +#define NID_gost89_cnt 814 + +#define SN_gost89_cnt_12 "gost89-cnt-12" +#define NID_gost89_cnt_12 975 + +#define SN_gost89_cbc "gost89-cbc" +#define NID_gost89_cbc 1009 + +#define SN_gost89_ecb "gost89-ecb" +#define NID_gost89_ecb 1010 + +#define SN_gost89_ctr "gost89-ctr" +#define NID_gost89_ctr 1011 + +#define SN_id_Gost28147_89_MAC "gost-mac" +#define LN_id_Gost28147_89_MAC "GOST 28147-89 MAC" +#define NID_id_Gost28147_89_MAC 815 +#define OBJ_id_Gost28147_89_MAC OBJ_cryptopro,22L + +#define SN_gost_mac_12 "gost-mac-12" +#define NID_gost_mac_12 976 + +#define SN_id_GostR3411_94_prf "prf-gostr3411-94" +#define LN_id_GostR3411_94_prf "GOST R 34.11-94 PRF" +#define NID_id_GostR3411_94_prf 816 +#define OBJ_id_GostR3411_94_prf OBJ_cryptopro,23L + +#define SN_id_GostR3410_2001DH "id-GostR3410-2001DH" +#define LN_id_GostR3410_2001DH "GOST R 34.10-2001 DH" +#define NID_id_GostR3410_2001DH 817 +#define OBJ_id_GostR3410_2001DH OBJ_cryptopro,98L + +#define SN_id_GostR3410_94DH "id-GostR3410-94DH" +#define LN_id_GostR3410_94DH "GOST R 34.10-94 DH" +#define NID_id_GostR3410_94DH 818 +#define OBJ_id_GostR3410_94DH OBJ_cryptopro,99L + +#define SN_id_Gost28147_89_CryptoPro_KeyMeshing "id-Gost28147-89-CryptoPro-KeyMeshing" +#define NID_id_Gost28147_89_CryptoPro_KeyMeshing 819 +#define OBJ_id_Gost28147_89_CryptoPro_KeyMeshing OBJ_cryptopro,14L,1L + +#define SN_id_Gost28147_89_None_KeyMeshing "id-Gost28147-89-None-KeyMeshing" +#define NID_id_Gost28147_89_None_KeyMeshing 820 +#define OBJ_id_Gost28147_89_None_KeyMeshing OBJ_cryptopro,14L,0L + +#define SN_id_GostR3411_94_TestParamSet "id-GostR3411-94-TestParamSet" +#define NID_id_GostR3411_94_TestParamSet 821 +#define OBJ_id_GostR3411_94_TestParamSet OBJ_cryptopro,30L,0L + +#define SN_id_GostR3411_94_CryptoProParamSet "id-GostR3411-94-CryptoProParamSet" +#define NID_id_GostR3411_94_CryptoProParamSet 822 +#define OBJ_id_GostR3411_94_CryptoProParamSet OBJ_cryptopro,30L,1L + +#define SN_id_Gost28147_89_TestParamSet "id-Gost28147-89-TestParamSet" +#define NID_id_Gost28147_89_TestParamSet 823 +#define OBJ_id_Gost28147_89_TestParamSet OBJ_cryptopro,31L,0L + +#define SN_id_Gost28147_89_CryptoPro_A_ParamSet "id-Gost28147-89-CryptoPro-A-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_A_ParamSet 824 +#define OBJ_id_Gost28147_89_CryptoPro_A_ParamSet OBJ_cryptopro,31L,1L + +#define SN_id_Gost28147_89_CryptoPro_B_ParamSet "id-Gost28147-89-CryptoPro-B-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_B_ParamSet 825 +#define OBJ_id_Gost28147_89_CryptoPro_B_ParamSet OBJ_cryptopro,31L,2L + +#define SN_id_Gost28147_89_CryptoPro_C_ParamSet "id-Gost28147-89-CryptoPro-C-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_C_ParamSet 826 +#define OBJ_id_Gost28147_89_CryptoPro_C_ParamSet OBJ_cryptopro,31L,3L + +#define SN_id_Gost28147_89_CryptoPro_D_ParamSet "id-Gost28147-89-CryptoPro-D-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_D_ParamSet 827 +#define OBJ_id_Gost28147_89_CryptoPro_D_ParamSet OBJ_cryptopro,31L,4L + +#define SN_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet "id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet 828 +#define OBJ_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet OBJ_cryptopro,31L,5L + +#define SN_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet "id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet 829 +#define OBJ_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet OBJ_cryptopro,31L,6L + +#define SN_id_Gost28147_89_CryptoPro_RIC_1_ParamSet "id-Gost28147-89-CryptoPro-RIC-1-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_RIC_1_ParamSet 830 +#define OBJ_id_Gost28147_89_CryptoPro_RIC_1_ParamSet OBJ_cryptopro,31L,7L + +#define SN_id_GostR3410_94_TestParamSet "id-GostR3410-94-TestParamSet" +#define NID_id_GostR3410_94_TestParamSet 831 +#define OBJ_id_GostR3410_94_TestParamSet OBJ_cryptopro,32L,0L + +#define SN_id_GostR3410_94_CryptoPro_A_ParamSet "id-GostR3410-94-CryptoPro-A-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_A_ParamSet 832 +#define OBJ_id_GostR3410_94_CryptoPro_A_ParamSet OBJ_cryptopro,32L,2L + +#define SN_id_GostR3410_94_CryptoPro_B_ParamSet "id-GostR3410-94-CryptoPro-B-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_B_ParamSet 833 +#define OBJ_id_GostR3410_94_CryptoPro_B_ParamSet OBJ_cryptopro,32L,3L + +#define SN_id_GostR3410_94_CryptoPro_C_ParamSet "id-GostR3410-94-CryptoPro-C-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_C_ParamSet 834 +#define OBJ_id_GostR3410_94_CryptoPro_C_ParamSet OBJ_cryptopro,32L,4L + +#define SN_id_GostR3410_94_CryptoPro_D_ParamSet "id-GostR3410-94-CryptoPro-D-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_D_ParamSet 835 +#define OBJ_id_GostR3410_94_CryptoPro_D_ParamSet OBJ_cryptopro,32L,5L + +#define SN_id_GostR3410_94_CryptoPro_XchA_ParamSet "id-GostR3410-94-CryptoPro-XchA-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_XchA_ParamSet 836 +#define OBJ_id_GostR3410_94_CryptoPro_XchA_ParamSet OBJ_cryptopro,33L,1L + +#define SN_id_GostR3410_94_CryptoPro_XchB_ParamSet "id-GostR3410-94-CryptoPro-XchB-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_XchB_ParamSet 837 +#define OBJ_id_GostR3410_94_CryptoPro_XchB_ParamSet OBJ_cryptopro,33L,2L + +#define SN_id_GostR3410_94_CryptoPro_XchC_ParamSet "id-GostR3410-94-CryptoPro-XchC-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_XchC_ParamSet 838 +#define OBJ_id_GostR3410_94_CryptoPro_XchC_ParamSet OBJ_cryptopro,33L,3L + +#define SN_id_GostR3410_2001_TestParamSet "id-GostR3410-2001-TestParamSet" +#define NID_id_GostR3410_2001_TestParamSet 839 +#define OBJ_id_GostR3410_2001_TestParamSet OBJ_cryptopro,35L,0L + +#define SN_id_GostR3410_2001_CryptoPro_A_ParamSet "id-GostR3410-2001-CryptoPro-A-ParamSet" +#define NID_id_GostR3410_2001_CryptoPro_A_ParamSet 840 +#define OBJ_id_GostR3410_2001_CryptoPro_A_ParamSet OBJ_cryptopro,35L,1L + +#define SN_id_GostR3410_2001_CryptoPro_B_ParamSet "id-GostR3410-2001-CryptoPro-B-ParamSet" +#define NID_id_GostR3410_2001_CryptoPro_B_ParamSet 841 +#define OBJ_id_GostR3410_2001_CryptoPro_B_ParamSet OBJ_cryptopro,35L,2L + +#define SN_id_GostR3410_2001_CryptoPro_C_ParamSet "id-GostR3410-2001-CryptoPro-C-ParamSet" +#define NID_id_GostR3410_2001_CryptoPro_C_ParamSet 842 +#define OBJ_id_GostR3410_2001_CryptoPro_C_ParamSet OBJ_cryptopro,35L,3L + +#define SN_id_GostR3410_2001_CryptoPro_XchA_ParamSet "id-GostR3410-2001-CryptoPro-XchA-ParamSet" +#define NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet 843 +#define OBJ_id_GostR3410_2001_CryptoPro_XchA_ParamSet OBJ_cryptopro,36L,0L + +#define SN_id_GostR3410_2001_CryptoPro_XchB_ParamSet "id-GostR3410-2001-CryptoPro-XchB-ParamSet" +#define NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet 844 +#define OBJ_id_GostR3410_2001_CryptoPro_XchB_ParamSet OBJ_cryptopro,36L,1L + +#define SN_id_GostR3410_94_a "id-GostR3410-94-a" +#define NID_id_GostR3410_94_a 845 +#define OBJ_id_GostR3410_94_a OBJ_id_GostR3410_94,1L + +#define SN_id_GostR3410_94_aBis "id-GostR3410-94-aBis" +#define NID_id_GostR3410_94_aBis 846 +#define OBJ_id_GostR3410_94_aBis OBJ_id_GostR3410_94,2L + +#define SN_id_GostR3410_94_b "id-GostR3410-94-b" +#define NID_id_GostR3410_94_b 847 +#define OBJ_id_GostR3410_94_b OBJ_id_GostR3410_94,3L + +#define SN_id_GostR3410_94_bBis "id-GostR3410-94-bBis" +#define NID_id_GostR3410_94_bBis 848 +#define OBJ_id_GostR3410_94_bBis OBJ_id_GostR3410_94,4L + +#define SN_id_Gost28147_89_cc "id-Gost28147-89-cc" +#define LN_id_Gost28147_89_cc "GOST 28147-89 Cryptocom ParamSet" +#define NID_id_Gost28147_89_cc 849 +#define OBJ_id_Gost28147_89_cc OBJ_cryptocom,1L,6L,1L + +#define SN_id_GostR3410_94_cc "gost94cc" +#define LN_id_GostR3410_94_cc "GOST 34.10-94 Cryptocom" +#define NID_id_GostR3410_94_cc 850 +#define OBJ_id_GostR3410_94_cc OBJ_cryptocom,1L,5L,3L + +#define SN_id_GostR3410_2001_cc "gost2001cc" +#define LN_id_GostR3410_2001_cc "GOST 34.10-2001 Cryptocom" +#define NID_id_GostR3410_2001_cc 851 +#define OBJ_id_GostR3410_2001_cc OBJ_cryptocom,1L,5L,4L + +#define SN_id_GostR3411_94_with_GostR3410_94_cc "id-GostR3411-94-with-GostR3410-94-cc" +#define LN_id_GostR3411_94_with_GostR3410_94_cc "GOST R 34.11-94 with GOST R 34.10-94 Cryptocom" +#define NID_id_GostR3411_94_with_GostR3410_94_cc 852 +#define OBJ_id_GostR3411_94_with_GostR3410_94_cc OBJ_cryptocom,1L,3L,3L + +#define SN_id_GostR3411_94_with_GostR3410_2001_cc "id-GostR3411-94-with-GostR3410-2001-cc" +#define LN_id_GostR3411_94_with_GostR3410_2001_cc "GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom" +#define NID_id_GostR3411_94_with_GostR3410_2001_cc 853 +#define OBJ_id_GostR3411_94_with_GostR3410_2001_cc OBJ_cryptocom,1L,3L,4L + +#define SN_id_GostR3410_2001_ParamSet_cc "id-GostR3410-2001-ParamSet-cc" +#define LN_id_GostR3410_2001_ParamSet_cc "GOST R 3410-2001 Parameter Set Cryptocom" +#define NID_id_GostR3410_2001_ParamSet_cc 854 +#define OBJ_id_GostR3410_2001_ParamSet_cc OBJ_cryptocom,1L,8L,1L + +#define SN_id_tc26_algorithms "id-tc26-algorithms" +#define NID_id_tc26_algorithms 977 +#define OBJ_id_tc26_algorithms OBJ_id_tc26,1L + +#define SN_id_tc26_sign "id-tc26-sign" +#define NID_id_tc26_sign 978 +#define OBJ_id_tc26_sign OBJ_id_tc26_algorithms,1L + +#define SN_id_GostR3410_2012_256 "gost2012_256" +#define LN_id_GostR3410_2012_256 "GOST R 34.10-2012 with 256 bit modulus" +#define NID_id_GostR3410_2012_256 979 +#define OBJ_id_GostR3410_2012_256 OBJ_id_tc26_sign,1L + +#define SN_id_GostR3410_2012_512 "gost2012_512" +#define LN_id_GostR3410_2012_512 "GOST R 34.10-2012 with 512 bit modulus" +#define NID_id_GostR3410_2012_512 980 +#define OBJ_id_GostR3410_2012_512 OBJ_id_tc26_sign,2L + +#define SN_id_tc26_digest "id-tc26-digest" +#define NID_id_tc26_digest 981 +#define OBJ_id_tc26_digest OBJ_id_tc26_algorithms,2L + +#define SN_id_GostR3411_2012_256 "md_gost12_256" +#define LN_id_GostR3411_2012_256 "GOST R 34.11-2012 with 256 bit hash" +#define NID_id_GostR3411_2012_256 982 +#define OBJ_id_GostR3411_2012_256 OBJ_id_tc26_digest,2L + +#define SN_id_GostR3411_2012_512 "md_gost12_512" +#define LN_id_GostR3411_2012_512 "GOST R 34.11-2012 with 512 bit hash" +#define NID_id_GostR3411_2012_512 983 +#define OBJ_id_GostR3411_2012_512 OBJ_id_tc26_digest,3L + +#define SN_id_tc26_signwithdigest "id-tc26-signwithdigest" +#define NID_id_tc26_signwithdigest 984 +#define OBJ_id_tc26_signwithdigest OBJ_id_tc26_algorithms,3L + +#define SN_id_tc26_signwithdigest_gost3410_2012_256 "id-tc26-signwithdigest-gost3410-2012-256" +#define LN_id_tc26_signwithdigest_gost3410_2012_256 "GOST R 34.10-2012 with GOST R 34.11-2012 (256 bit)" +#define NID_id_tc26_signwithdigest_gost3410_2012_256 985 +#define OBJ_id_tc26_signwithdigest_gost3410_2012_256 OBJ_id_tc26_signwithdigest,2L + +#define SN_id_tc26_signwithdigest_gost3410_2012_512 "id-tc26-signwithdigest-gost3410-2012-512" +#define LN_id_tc26_signwithdigest_gost3410_2012_512 "GOST R 34.10-2012 with GOST R 34.11-2012 (512 bit)" +#define NID_id_tc26_signwithdigest_gost3410_2012_512 986 +#define OBJ_id_tc26_signwithdigest_gost3410_2012_512 OBJ_id_tc26_signwithdigest,3L + +#define SN_id_tc26_mac "id-tc26-mac" +#define NID_id_tc26_mac 987 +#define OBJ_id_tc26_mac OBJ_id_tc26_algorithms,4L + +#define SN_id_tc26_hmac_gost_3411_2012_256 "id-tc26-hmac-gost-3411-2012-256" +#define LN_id_tc26_hmac_gost_3411_2012_256 "HMAC GOST 34.11-2012 256 bit" +#define NID_id_tc26_hmac_gost_3411_2012_256 988 +#define OBJ_id_tc26_hmac_gost_3411_2012_256 OBJ_id_tc26_mac,1L + +#define SN_id_tc26_hmac_gost_3411_2012_512 "id-tc26-hmac-gost-3411-2012-512" +#define LN_id_tc26_hmac_gost_3411_2012_512 "HMAC GOST 34.11-2012 512 bit" +#define NID_id_tc26_hmac_gost_3411_2012_512 989 +#define OBJ_id_tc26_hmac_gost_3411_2012_512 OBJ_id_tc26_mac,2L + +#define SN_id_tc26_cipher "id-tc26-cipher" +#define NID_id_tc26_cipher 990 +#define OBJ_id_tc26_cipher OBJ_id_tc26_algorithms,5L + +#define SN_id_tc26_cipher_gostr3412_2015_magma "id-tc26-cipher-gostr3412-2015-magma" +#define NID_id_tc26_cipher_gostr3412_2015_magma 1173 +#define OBJ_id_tc26_cipher_gostr3412_2015_magma OBJ_id_tc26_cipher,1L + +#define SN_id_tc26_cipher_gostr3412_2015_magma_ctracpkm "id-tc26-cipher-gostr3412-2015-magma-ctracpkm" +#define NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm 1174 +#define OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm OBJ_id_tc26_cipher_gostr3412_2015_magma,1L + +#define SN_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac "id-tc26-cipher-gostr3412-2015-magma-ctracpkm-omac" +#define NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac 1175 +#define OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac OBJ_id_tc26_cipher_gostr3412_2015_magma,2L + +#define SN_id_tc26_cipher_gostr3412_2015_kuznyechik "id-tc26-cipher-gostr3412-2015-kuznyechik" +#define NID_id_tc26_cipher_gostr3412_2015_kuznyechik 1176 +#define OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik OBJ_id_tc26_cipher,2L + +#define SN_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm "id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm" +#define NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm 1177 +#define OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik,1L + +#define SN_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac "id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm-omac" +#define NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac 1178 +#define OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik,2L + +#define SN_id_tc26_agreement "id-tc26-agreement" +#define NID_id_tc26_agreement 991 +#define OBJ_id_tc26_agreement OBJ_id_tc26_algorithms,6L + +#define SN_id_tc26_agreement_gost_3410_2012_256 "id-tc26-agreement-gost-3410-2012-256" +#define NID_id_tc26_agreement_gost_3410_2012_256 992 +#define OBJ_id_tc26_agreement_gost_3410_2012_256 OBJ_id_tc26_agreement,1L + +#define SN_id_tc26_agreement_gost_3410_2012_512 "id-tc26-agreement-gost-3410-2012-512" +#define NID_id_tc26_agreement_gost_3410_2012_512 993 +#define OBJ_id_tc26_agreement_gost_3410_2012_512 OBJ_id_tc26_agreement,2L + +#define SN_id_tc26_wrap "id-tc26-wrap" +#define NID_id_tc26_wrap 1179 +#define OBJ_id_tc26_wrap OBJ_id_tc26_algorithms,7L + +#define SN_id_tc26_wrap_gostr3412_2015_magma "id-tc26-wrap-gostr3412-2015-magma" +#define NID_id_tc26_wrap_gostr3412_2015_magma 1180 +#define OBJ_id_tc26_wrap_gostr3412_2015_magma OBJ_id_tc26_wrap,1L + +#define SN_id_tc26_wrap_gostr3412_2015_magma_kexp15 "id-tc26-wrap-gostr3412-2015-magma-kexp15" +#define NID_id_tc26_wrap_gostr3412_2015_magma_kexp15 1181 +#define OBJ_id_tc26_wrap_gostr3412_2015_magma_kexp15 OBJ_id_tc26_wrap_gostr3412_2015_magma,1L + +#define SN_id_tc26_wrap_gostr3412_2015_kuznyechik "id-tc26-wrap-gostr3412-2015-kuznyechik" +#define NID_id_tc26_wrap_gostr3412_2015_kuznyechik 1182 +#define OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik OBJ_id_tc26_wrap,2L + +#define SN_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 "id-tc26-wrap-gostr3412-2015-kuznyechik-kexp15" +#define NID_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 1183 +#define OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 OBJ_id_tc26_wrap_gostr3412_2015_magma,1L + +#define SN_id_tc26_constants "id-tc26-constants" +#define NID_id_tc26_constants 994 +#define OBJ_id_tc26_constants OBJ_id_tc26,2L + +#define SN_id_tc26_sign_constants "id-tc26-sign-constants" +#define NID_id_tc26_sign_constants 995 +#define OBJ_id_tc26_sign_constants OBJ_id_tc26_constants,1L + +#define SN_id_tc26_gost_3410_2012_256_constants "id-tc26-gost-3410-2012-256-constants" +#define NID_id_tc26_gost_3410_2012_256_constants 1147 +#define OBJ_id_tc26_gost_3410_2012_256_constants OBJ_id_tc26_sign_constants,1L + +#define SN_id_tc26_gost_3410_2012_256_paramSetA "id-tc26-gost-3410-2012-256-paramSetA" +#define LN_id_tc26_gost_3410_2012_256_paramSetA "GOST R 34.10-2012 (256 bit) ParamSet A" +#define NID_id_tc26_gost_3410_2012_256_paramSetA 1148 +#define OBJ_id_tc26_gost_3410_2012_256_paramSetA OBJ_id_tc26_gost_3410_2012_256_constants,1L + +#define SN_id_tc26_gost_3410_2012_256_paramSetB "id-tc26-gost-3410-2012-256-paramSetB" +#define LN_id_tc26_gost_3410_2012_256_paramSetB "GOST R 34.10-2012 (256 bit) ParamSet B" +#define NID_id_tc26_gost_3410_2012_256_paramSetB 1184 +#define OBJ_id_tc26_gost_3410_2012_256_paramSetB OBJ_id_tc26_gost_3410_2012_256_constants,2L + +#define SN_id_tc26_gost_3410_2012_256_paramSetC "id-tc26-gost-3410-2012-256-paramSetC" +#define LN_id_tc26_gost_3410_2012_256_paramSetC "GOST R 34.10-2012 (256 bit) ParamSet C" +#define NID_id_tc26_gost_3410_2012_256_paramSetC 1185 +#define OBJ_id_tc26_gost_3410_2012_256_paramSetC OBJ_id_tc26_gost_3410_2012_256_constants,3L + +#define SN_id_tc26_gost_3410_2012_256_paramSetD "id-tc26-gost-3410-2012-256-paramSetD" +#define LN_id_tc26_gost_3410_2012_256_paramSetD "GOST R 34.10-2012 (256 bit) ParamSet D" +#define NID_id_tc26_gost_3410_2012_256_paramSetD 1186 +#define OBJ_id_tc26_gost_3410_2012_256_paramSetD OBJ_id_tc26_gost_3410_2012_256_constants,4L + +#define SN_id_tc26_gost_3410_2012_512_constants "id-tc26-gost-3410-2012-512-constants" +#define NID_id_tc26_gost_3410_2012_512_constants 996 +#define OBJ_id_tc26_gost_3410_2012_512_constants OBJ_id_tc26_sign_constants,2L + +#define SN_id_tc26_gost_3410_2012_512_paramSetTest "id-tc26-gost-3410-2012-512-paramSetTest" +#define LN_id_tc26_gost_3410_2012_512_paramSetTest "GOST R 34.10-2012 (512 bit) testing parameter set" +#define NID_id_tc26_gost_3410_2012_512_paramSetTest 997 +#define OBJ_id_tc26_gost_3410_2012_512_paramSetTest OBJ_id_tc26_gost_3410_2012_512_constants,0L + +#define SN_id_tc26_gost_3410_2012_512_paramSetA "id-tc26-gost-3410-2012-512-paramSetA" +#define LN_id_tc26_gost_3410_2012_512_paramSetA "GOST R 34.10-2012 (512 bit) ParamSet A" +#define NID_id_tc26_gost_3410_2012_512_paramSetA 998 +#define OBJ_id_tc26_gost_3410_2012_512_paramSetA OBJ_id_tc26_gost_3410_2012_512_constants,1L + +#define SN_id_tc26_gost_3410_2012_512_paramSetB "id-tc26-gost-3410-2012-512-paramSetB" +#define LN_id_tc26_gost_3410_2012_512_paramSetB "GOST R 34.10-2012 (512 bit) ParamSet B" +#define NID_id_tc26_gost_3410_2012_512_paramSetB 999 +#define OBJ_id_tc26_gost_3410_2012_512_paramSetB OBJ_id_tc26_gost_3410_2012_512_constants,2L + +#define SN_id_tc26_gost_3410_2012_512_paramSetC "id-tc26-gost-3410-2012-512-paramSetC" +#define LN_id_tc26_gost_3410_2012_512_paramSetC "GOST R 34.10-2012 (512 bit) ParamSet C" +#define NID_id_tc26_gost_3410_2012_512_paramSetC 1149 +#define OBJ_id_tc26_gost_3410_2012_512_paramSetC OBJ_id_tc26_gost_3410_2012_512_constants,3L + +#define SN_id_tc26_digest_constants "id-tc26-digest-constants" +#define NID_id_tc26_digest_constants 1000 +#define OBJ_id_tc26_digest_constants OBJ_id_tc26_constants,2L + +#define SN_id_tc26_cipher_constants "id-tc26-cipher-constants" +#define NID_id_tc26_cipher_constants 1001 +#define OBJ_id_tc26_cipher_constants OBJ_id_tc26_constants,5L + +#define SN_id_tc26_gost_28147_constants "id-tc26-gost-28147-constants" +#define NID_id_tc26_gost_28147_constants 1002 +#define OBJ_id_tc26_gost_28147_constants OBJ_id_tc26_cipher_constants,1L + +#define SN_id_tc26_gost_28147_param_Z "id-tc26-gost-28147-param-Z" +#define LN_id_tc26_gost_28147_param_Z "GOST 28147-89 TC26 parameter set" +#define NID_id_tc26_gost_28147_param_Z 1003 +#define OBJ_id_tc26_gost_28147_param_Z OBJ_id_tc26_gost_28147_constants,1L + +#define SN_INN "INN" +#define LN_INN "INN" +#define NID_INN 1004 +#define OBJ_INN OBJ_member_body,643L,3L,131L,1L,1L + +#define SN_OGRN "OGRN" +#define LN_OGRN "OGRN" +#define NID_OGRN 1005 +#define OBJ_OGRN OBJ_member_body,643L,100L,1L + +#define SN_SNILS "SNILS" +#define LN_SNILS "SNILS" +#define NID_SNILS 1006 +#define OBJ_SNILS OBJ_member_body,643L,100L,3L + +#define SN_subjectSignTool "subjectSignTool" +#define LN_subjectSignTool "Signing Tool of Subject" +#define NID_subjectSignTool 1007 +#define OBJ_subjectSignTool OBJ_member_body,643L,100L,111L + +#define SN_issuerSignTool "issuerSignTool" +#define LN_issuerSignTool "Signing Tool of Issuer" +#define NID_issuerSignTool 1008 +#define OBJ_issuerSignTool OBJ_member_body,643L,100L,112L + +#define SN_grasshopper_ecb "grasshopper-ecb" +#define NID_grasshopper_ecb 1012 + +#define SN_grasshopper_ctr "grasshopper-ctr" +#define NID_grasshopper_ctr 1013 + +#define SN_grasshopper_ofb "grasshopper-ofb" +#define NID_grasshopper_ofb 1014 + +#define SN_grasshopper_cbc "grasshopper-cbc" +#define NID_grasshopper_cbc 1015 + +#define SN_grasshopper_cfb "grasshopper-cfb" +#define NID_grasshopper_cfb 1016 + +#define SN_grasshopper_mac "grasshopper-mac" +#define NID_grasshopper_mac 1017 + +#define SN_magma_ecb "magma-ecb" +#define NID_magma_ecb 1187 + +#define SN_magma_ctr "magma-ctr" +#define NID_magma_ctr 1188 + +#define SN_magma_ofb "magma-ofb" +#define NID_magma_ofb 1189 + +#define SN_magma_cbc "magma-cbc" +#define NID_magma_cbc 1190 + +#define SN_magma_cfb "magma-cfb" +#define NID_magma_cfb 1191 + +#define SN_magma_mac "magma-mac" +#define NID_magma_mac 1192 + +#define SN_camellia_128_cbc "CAMELLIA-128-CBC" +#define LN_camellia_128_cbc "camellia-128-cbc" +#define NID_camellia_128_cbc 751 +#define OBJ_camellia_128_cbc 1L,2L,392L,200011L,61L,1L,1L,1L,2L + +#define SN_camellia_192_cbc "CAMELLIA-192-CBC" +#define LN_camellia_192_cbc "camellia-192-cbc" +#define NID_camellia_192_cbc 752 +#define OBJ_camellia_192_cbc 1L,2L,392L,200011L,61L,1L,1L,1L,3L + +#define SN_camellia_256_cbc "CAMELLIA-256-CBC" +#define LN_camellia_256_cbc "camellia-256-cbc" +#define NID_camellia_256_cbc 753 +#define OBJ_camellia_256_cbc 1L,2L,392L,200011L,61L,1L,1L,1L,4L + +#define SN_id_camellia128_wrap "id-camellia128-wrap" +#define NID_id_camellia128_wrap 907 +#define OBJ_id_camellia128_wrap 1L,2L,392L,200011L,61L,1L,1L,3L,2L + +#define SN_id_camellia192_wrap "id-camellia192-wrap" +#define NID_id_camellia192_wrap 908 +#define OBJ_id_camellia192_wrap 1L,2L,392L,200011L,61L,1L,1L,3L,3L + +#define SN_id_camellia256_wrap "id-camellia256-wrap" +#define NID_id_camellia256_wrap 909 +#define OBJ_id_camellia256_wrap 1L,2L,392L,200011L,61L,1L,1L,3L,4L + +#define OBJ_ntt_ds 0L,3L,4401L,5L + +#define OBJ_camellia OBJ_ntt_ds,3L,1L,9L + +#define SN_camellia_128_ecb "CAMELLIA-128-ECB" +#define LN_camellia_128_ecb "camellia-128-ecb" +#define NID_camellia_128_ecb 754 +#define OBJ_camellia_128_ecb OBJ_camellia,1L + +#define SN_camellia_128_ofb128 "CAMELLIA-128-OFB" +#define LN_camellia_128_ofb128 "camellia-128-ofb" +#define NID_camellia_128_ofb128 766 +#define OBJ_camellia_128_ofb128 OBJ_camellia,3L + +#define SN_camellia_128_cfb128 "CAMELLIA-128-CFB" +#define LN_camellia_128_cfb128 "camellia-128-cfb" +#define NID_camellia_128_cfb128 757 +#define OBJ_camellia_128_cfb128 OBJ_camellia,4L + +#define SN_camellia_128_gcm "CAMELLIA-128-GCM" +#define LN_camellia_128_gcm "camellia-128-gcm" +#define NID_camellia_128_gcm 961 +#define OBJ_camellia_128_gcm OBJ_camellia,6L + +#define SN_camellia_128_ccm "CAMELLIA-128-CCM" +#define LN_camellia_128_ccm "camellia-128-ccm" +#define NID_camellia_128_ccm 962 +#define OBJ_camellia_128_ccm OBJ_camellia,7L + +#define SN_camellia_128_ctr "CAMELLIA-128-CTR" +#define LN_camellia_128_ctr "camellia-128-ctr" +#define NID_camellia_128_ctr 963 +#define OBJ_camellia_128_ctr OBJ_camellia,9L + +#define SN_camellia_128_cmac "CAMELLIA-128-CMAC" +#define LN_camellia_128_cmac "camellia-128-cmac" +#define NID_camellia_128_cmac 964 +#define OBJ_camellia_128_cmac OBJ_camellia,10L + +#define SN_camellia_192_ecb "CAMELLIA-192-ECB" +#define LN_camellia_192_ecb "camellia-192-ecb" +#define NID_camellia_192_ecb 755 +#define OBJ_camellia_192_ecb OBJ_camellia,21L + +#define SN_camellia_192_ofb128 "CAMELLIA-192-OFB" +#define LN_camellia_192_ofb128 "camellia-192-ofb" +#define NID_camellia_192_ofb128 767 +#define OBJ_camellia_192_ofb128 OBJ_camellia,23L + +#define SN_camellia_192_cfb128 "CAMELLIA-192-CFB" +#define LN_camellia_192_cfb128 "camellia-192-cfb" +#define NID_camellia_192_cfb128 758 +#define OBJ_camellia_192_cfb128 OBJ_camellia,24L + +#define SN_camellia_192_gcm "CAMELLIA-192-GCM" +#define LN_camellia_192_gcm "camellia-192-gcm" +#define NID_camellia_192_gcm 965 +#define OBJ_camellia_192_gcm OBJ_camellia,26L + +#define SN_camellia_192_ccm "CAMELLIA-192-CCM" +#define LN_camellia_192_ccm "camellia-192-ccm" +#define NID_camellia_192_ccm 966 +#define OBJ_camellia_192_ccm OBJ_camellia,27L + +#define SN_camellia_192_ctr "CAMELLIA-192-CTR" +#define LN_camellia_192_ctr "camellia-192-ctr" +#define NID_camellia_192_ctr 967 +#define OBJ_camellia_192_ctr OBJ_camellia,29L + +#define SN_camellia_192_cmac "CAMELLIA-192-CMAC" +#define LN_camellia_192_cmac "camellia-192-cmac" +#define NID_camellia_192_cmac 968 +#define OBJ_camellia_192_cmac OBJ_camellia,30L + +#define SN_camellia_256_ecb "CAMELLIA-256-ECB" +#define LN_camellia_256_ecb "camellia-256-ecb" +#define NID_camellia_256_ecb 756 +#define OBJ_camellia_256_ecb OBJ_camellia,41L + +#define SN_camellia_256_ofb128 "CAMELLIA-256-OFB" +#define LN_camellia_256_ofb128 "camellia-256-ofb" +#define NID_camellia_256_ofb128 768 +#define OBJ_camellia_256_ofb128 OBJ_camellia,43L + +#define SN_camellia_256_cfb128 "CAMELLIA-256-CFB" +#define LN_camellia_256_cfb128 "camellia-256-cfb" +#define NID_camellia_256_cfb128 759 +#define OBJ_camellia_256_cfb128 OBJ_camellia,44L + +#define SN_camellia_256_gcm "CAMELLIA-256-GCM" +#define LN_camellia_256_gcm "camellia-256-gcm" +#define NID_camellia_256_gcm 969 +#define OBJ_camellia_256_gcm OBJ_camellia,46L + +#define SN_camellia_256_ccm "CAMELLIA-256-CCM" +#define LN_camellia_256_ccm "camellia-256-ccm" +#define NID_camellia_256_ccm 970 +#define OBJ_camellia_256_ccm OBJ_camellia,47L + +#define SN_camellia_256_ctr "CAMELLIA-256-CTR" +#define LN_camellia_256_ctr "camellia-256-ctr" +#define NID_camellia_256_ctr 971 +#define OBJ_camellia_256_ctr OBJ_camellia,49L + +#define SN_camellia_256_cmac "CAMELLIA-256-CMAC" +#define LN_camellia_256_cmac "camellia-256-cmac" +#define NID_camellia_256_cmac 972 +#define OBJ_camellia_256_cmac OBJ_camellia,50L + +#define SN_camellia_128_cfb1 "CAMELLIA-128-CFB1" +#define LN_camellia_128_cfb1 "camellia-128-cfb1" +#define NID_camellia_128_cfb1 760 + +#define SN_camellia_192_cfb1 "CAMELLIA-192-CFB1" +#define LN_camellia_192_cfb1 "camellia-192-cfb1" +#define NID_camellia_192_cfb1 761 + +#define SN_camellia_256_cfb1 "CAMELLIA-256-CFB1" +#define LN_camellia_256_cfb1 "camellia-256-cfb1" +#define NID_camellia_256_cfb1 762 + +#define SN_camellia_128_cfb8 "CAMELLIA-128-CFB8" +#define LN_camellia_128_cfb8 "camellia-128-cfb8" +#define NID_camellia_128_cfb8 763 + +#define SN_camellia_192_cfb8 "CAMELLIA-192-CFB8" +#define LN_camellia_192_cfb8 "camellia-192-cfb8" +#define NID_camellia_192_cfb8 764 + +#define SN_camellia_256_cfb8 "CAMELLIA-256-CFB8" +#define LN_camellia_256_cfb8 "camellia-256-cfb8" +#define NID_camellia_256_cfb8 765 + +#define OBJ_aria 1L,2L,410L,200046L,1L,1L + +#define SN_aria_128_ecb "ARIA-128-ECB" +#define LN_aria_128_ecb "aria-128-ecb" +#define NID_aria_128_ecb 1065 +#define OBJ_aria_128_ecb OBJ_aria,1L + +#define SN_aria_128_cbc "ARIA-128-CBC" +#define LN_aria_128_cbc "aria-128-cbc" +#define NID_aria_128_cbc 1066 +#define OBJ_aria_128_cbc OBJ_aria,2L + +#define SN_aria_128_cfb128 "ARIA-128-CFB" +#define LN_aria_128_cfb128 "aria-128-cfb" +#define NID_aria_128_cfb128 1067 +#define OBJ_aria_128_cfb128 OBJ_aria,3L + +#define SN_aria_128_ofb128 "ARIA-128-OFB" +#define LN_aria_128_ofb128 "aria-128-ofb" +#define NID_aria_128_ofb128 1068 +#define OBJ_aria_128_ofb128 OBJ_aria,4L + +#define SN_aria_128_ctr "ARIA-128-CTR" +#define LN_aria_128_ctr "aria-128-ctr" +#define NID_aria_128_ctr 1069 +#define OBJ_aria_128_ctr OBJ_aria,5L + +#define SN_aria_192_ecb "ARIA-192-ECB" +#define LN_aria_192_ecb "aria-192-ecb" +#define NID_aria_192_ecb 1070 +#define OBJ_aria_192_ecb OBJ_aria,6L + +#define SN_aria_192_cbc "ARIA-192-CBC" +#define LN_aria_192_cbc "aria-192-cbc" +#define NID_aria_192_cbc 1071 +#define OBJ_aria_192_cbc OBJ_aria,7L + +#define SN_aria_192_cfb128 "ARIA-192-CFB" +#define LN_aria_192_cfb128 "aria-192-cfb" +#define NID_aria_192_cfb128 1072 +#define OBJ_aria_192_cfb128 OBJ_aria,8L + +#define SN_aria_192_ofb128 "ARIA-192-OFB" +#define LN_aria_192_ofb128 "aria-192-ofb" +#define NID_aria_192_ofb128 1073 +#define OBJ_aria_192_ofb128 OBJ_aria,9L + +#define SN_aria_192_ctr "ARIA-192-CTR" +#define LN_aria_192_ctr "aria-192-ctr" +#define NID_aria_192_ctr 1074 +#define OBJ_aria_192_ctr OBJ_aria,10L + +#define SN_aria_256_ecb "ARIA-256-ECB" +#define LN_aria_256_ecb "aria-256-ecb" +#define NID_aria_256_ecb 1075 +#define OBJ_aria_256_ecb OBJ_aria,11L + +#define SN_aria_256_cbc "ARIA-256-CBC" +#define LN_aria_256_cbc "aria-256-cbc" +#define NID_aria_256_cbc 1076 +#define OBJ_aria_256_cbc OBJ_aria,12L + +#define SN_aria_256_cfb128 "ARIA-256-CFB" +#define LN_aria_256_cfb128 "aria-256-cfb" +#define NID_aria_256_cfb128 1077 +#define OBJ_aria_256_cfb128 OBJ_aria,13L + +#define SN_aria_256_ofb128 "ARIA-256-OFB" +#define LN_aria_256_ofb128 "aria-256-ofb" +#define NID_aria_256_ofb128 1078 +#define OBJ_aria_256_ofb128 OBJ_aria,14L + +#define SN_aria_256_ctr "ARIA-256-CTR" +#define LN_aria_256_ctr "aria-256-ctr" +#define NID_aria_256_ctr 1079 +#define OBJ_aria_256_ctr OBJ_aria,15L + +#define SN_aria_128_cfb1 "ARIA-128-CFB1" +#define LN_aria_128_cfb1 "aria-128-cfb1" +#define NID_aria_128_cfb1 1080 + +#define SN_aria_192_cfb1 "ARIA-192-CFB1" +#define LN_aria_192_cfb1 "aria-192-cfb1" +#define NID_aria_192_cfb1 1081 + +#define SN_aria_256_cfb1 "ARIA-256-CFB1" +#define LN_aria_256_cfb1 "aria-256-cfb1" +#define NID_aria_256_cfb1 1082 + +#define SN_aria_128_cfb8 "ARIA-128-CFB8" +#define LN_aria_128_cfb8 "aria-128-cfb8" +#define NID_aria_128_cfb8 1083 + +#define SN_aria_192_cfb8 "ARIA-192-CFB8" +#define LN_aria_192_cfb8 "aria-192-cfb8" +#define NID_aria_192_cfb8 1084 + +#define SN_aria_256_cfb8 "ARIA-256-CFB8" +#define LN_aria_256_cfb8 "aria-256-cfb8" +#define NID_aria_256_cfb8 1085 + +#define SN_aria_128_ccm "ARIA-128-CCM" +#define LN_aria_128_ccm "aria-128-ccm" +#define NID_aria_128_ccm 1120 +#define OBJ_aria_128_ccm OBJ_aria,37L + +#define SN_aria_192_ccm "ARIA-192-CCM" +#define LN_aria_192_ccm "aria-192-ccm" +#define NID_aria_192_ccm 1121 +#define OBJ_aria_192_ccm OBJ_aria,38L + +#define SN_aria_256_ccm "ARIA-256-CCM" +#define LN_aria_256_ccm "aria-256-ccm" +#define NID_aria_256_ccm 1122 +#define OBJ_aria_256_ccm OBJ_aria,39L + +#define SN_aria_128_gcm "ARIA-128-GCM" +#define LN_aria_128_gcm "aria-128-gcm" +#define NID_aria_128_gcm 1123 +#define OBJ_aria_128_gcm OBJ_aria,34L + +#define SN_aria_192_gcm "ARIA-192-GCM" +#define LN_aria_192_gcm "aria-192-gcm" +#define NID_aria_192_gcm 1124 +#define OBJ_aria_192_gcm OBJ_aria,35L + +#define SN_aria_256_gcm "ARIA-256-GCM" +#define LN_aria_256_gcm "aria-256-gcm" +#define NID_aria_256_gcm 1125 +#define OBJ_aria_256_gcm OBJ_aria,36L + +#define SN_kisa "KISA" +#define LN_kisa "kisa" +#define NID_kisa 773 +#define OBJ_kisa OBJ_member_body,410L,200004L + +#define SN_seed_ecb "SEED-ECB" +#define LN_seed_ecb "seed-ecb" +#define NID_seed_ecb 776 +#define OBJ_seed_ecb OBJ_kisa,1L,3L + +#define SN_seed_cbc "SEED-CBC" +#define LN_seed_cbc "seed-cbc" +#define NID_seed_cbc 777 +#define OBJ_seed_cbc OBJ_kisa,1L,4L + +#define SN_seed_cfb128 "SEED-CFB" +#define LN_seed_cfb128 "seed-cfb" +#define NID_seed_cfb128 779 +#define OBJ_seed_cfb128 OBJ_kisa,1L,5L + +#define SN_seed_ofb128 "SEED-OFB" +#define LN_seed_ofb128 "seed-ofb" +#define NID_seed_ofb128 778 +#define OBJ_seed_ofb128 OBJ_kisa,1L,6L + +#define SN_sm4_ecb "SM4-ECB" +#define LN_sm4_ecb "sm4-ecb" +#define NID_sm4_ecb 1133 +#define OBJ_sm4_ecb OBJ_sm_scheme,104L,1L + +#define SN_sm4_cbc "SM4-CBC" +#define LN_sm4_cbc "sm4-cbc" +#define NID_sm4_cbc 1134 +#define OBJ_sm4_cbc OBJ_sm_scheme,104L,2L + +#define SN_sm4_ofb128 "SM4-OFB" +#define LN_sm4_ofb128 "sm4-ofb" +#define NID_sm4_ofb128 1135 +#define OBJ_sm4_ofb128 OBJ_sm_scheme,104L,3L + +#define SN_sm4_cfb128 "SM4-CFB" +#define LN_sm4_cfb128 "sm4-cfb" +#define NID_sm4_cfb128 1137 +#define OBJ_sm4_cfb128 OBJ_sm_scheme,104L,4L + +#define SN_sm4_cfb1 "SM4-CFB1" +#define LN_sm4_cfb1 "sm4-cfb1" +#define NID_sm4_cfb1 1136 +#define OBJ_sm4_cfb1 OBJ_sm_scheme,104L,5L + +#define SN_sm4_cfb8 "SM4-CFB8" +#define LN_sm4_cfb8 "sm4-cfb8" +#define NID_sm4_cfb8 1138 +#define OBJ_sm4_cfb8 OBJ_sm_scheme,104L,6L + +#define SN_sm4_ctr "SM4-CTR" +#define LN_sm4_ctr "sm4-ctr" +#define NID_sm4_ctr 1139 +#define OBJ_sm4_ctr OBJ_sm_scheme,104L,7L + +#define SN_hmac "HMAC" +#define LN_hmac "hmac" +#define NID_hmac 855 + +#define SN_cmac "CMAC" +#define LN_cmac "cmac" +#define NID_cmac 894 + +#define SN_rc4_hmac_md5 "RC4-HMAC-MD5" +#define LN_rc4_hmac_md5 "rc4-hmac-md5" +#define NID_rc4_hmac_md5 915 + +#define SN_aes_128_cbc_hmac_sha1 "AES-128-CBC-HMAC-SHA1" +#define LN_aes_128_cbc_hmac_sha1 "aes-128-cbc-hmac-sha1" +#define NID_aes_128_cbc_hmac_sha1 916 + +#define SN_aes_192_cbc_hmac_sha1 "AES-192-CBC-HMAC-SHA1" +#define LN_aes_192_cbc_hmac_sha1 "aes-192-cbc-hmac-sha1" +#define NID_aes_192_cbc_hmac_sha1 917 + +#define SN_aes_256_cbc_hmac_sha1 "AES-256-CBC-HMAC-SHA1" +#define LN_aes_256_cbc_hmac_sha1 "aes-256-cbc-hmac-sha1" +#define NID_aes_256_cbc_hmac_sha1 918 + +#define SN_aes_128_cbc_hmac_sha256 "AES-128-CBC-HMAC-SHA256" +#define LN_aes_128_cbc_hmac_sha256 "aes-128-cbc-hmac-sha256" +#define NID_aes_128_cbc_hmac_sha256 948 + +#define SN_aes_192_cbc_hmac_sha256 "AES-192-CBC-HMAC-SHA256" +#define LN_aes_192_cbc_hmac_sha256 "aes-192-cbc-hmac-sha256" +#define NID_aes_192_cbc_hmac_sha256 949 + +#define SN_aes_256_cbc_hmac_sha256 "AES-256-CBC-HMAC-SHA256" +#define LN_aes_256_cbc_hmac_sha256 "aes-256-cbc-hmac-sha256" +#define NID_aes_256_cbc_hmac_sha256 950 + +#define SN_chacha20_poly1305 "ChaCha20-Poly1305" +#define LN_chacha20_poly1305 "chacha20-poly1305" +#define NID_chacha20_poly1305 1018 + +#define SN_chacha20 "ChaCha20" +#define LN_chacha20 "chacha20" +#define NID_chacha20 1019 + +#define SN_dhpublicnumber "dhpublicnumber" +#define LN_dhpublicnumber "X9.42 DH" +#define NID_dhpublicnumber 920 +#define OBJ_dhpublicnumber OBJ_ISO_US,10046L,2L,1L + +#define SN_brainpoolP160r1 "brainpoolP160r1" +#define NID_brainpoolP160r1 921 +#define OBJ_brainpoolP160r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,1L + +#define SN_brainpoolP160t1 "brainpoolP160t1" +#define NID_brainpoolP160t1 922 +#define OBJ_brainpoolP160t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,2L + +#define SN_brainpoolP192r1 "brainpoolP192r1" +#define NID_brainpoolP192r1 923 +#define OBJ_brainpoolP192r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,3L + +#define SN_brainpoolP192t1 "brainpoolP192t1" +#define NID_brainpoolP192t1 924 +#define OBJ_brainpoolP192t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,4L + +#define SN_brainpoolP224r1 "brainpoolP224r1" +#define NID_brainpoolP224r1 925 +#define OBJ_brainpoolP224r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,5L + +#define SN_brainpoolP224t1 "brainpoolP224t1" +#define NID_brainpoolP224t1 926 +#define OBJ_brainpoolP224t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,6L + +#define SN_brainpoolP256r1 "brainpoolP256r1" +#define NID_brainpoolP256r1 927 +#define OBJ_brainpoolP256r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,7L + +#define SN_brainpoolP256t1 "brainpoolP256t1" +#define NID_brainpoolP256t1 928 +#define OBJ_brainpoolP256t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,8L + +#define SN_brainpoolP320r1 "brainpoolP320r1" +#define NID_brainpoolP320r1 929 +#define OBJ_brainpoolP320r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,9L + +#define SN_brainpoolP320t1 "brainpoolP320t1" +#define NID_brainpoolP320t1 930 +#define OBJ_brainpoolP320t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,10L + +#define SN_brainpoolP384r1 "brainpoolP384r1" +#define NID_brainpoolP384r1 931 +#define OBJ_brainpoolP384r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,11L + +#define SN_brainpoolP384t1 "brainpoolP384t1" +#define NID_brainpoolP384t1 932 +#define OBJ_brainpoolP384t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,12L + +#define SN_brainpoolP512r1 "brainpoolP512r1" +#define NID_brainpoolP512r1 933 +#define OBJ_brainpoolP512r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,13L + +#define SN_brainpoolP512t1 "brainpoolP512t1" +#define NID_brainpoolP512t1 934 +#define OBJ_brainpoolP512t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,14L + +#define OBJ_x9_63_scheme 1L,3L,133L,16L,840L,63L,0L + +#define OBJ_secg_scheme OBJ_certicom_arc,1L + +#define SN_dhSinglePass_stdDH_sha1kdf_scheme "dhSinglePass-stdDH-sha1kdf-scheme" +#define NID_dhSinglePass_stdDH_sha1kdf_scheme 936 +#define OBJ_dhSinglePass_stdDH_sha1kdf_scheme OBJ_x9_63_scheme,2L + +#define SN_dhSinglePass_stdDH_sha224kdf_scheme "dhSinglePass-stdDH-sha224kdf-scheme" +#define NID_dhSinglePass_stdDH_sha224kdf_scheme 937 +#define OBJ_dhSinglePass_stdDH_sha224kdf_scheme OBJ_secg_scheme,11L,0L + +#define SN_dhSinglePass_stdDH_sha256kdf_scheme "dhSinglePass-stdDH-sha256kdf-scheme" +#define NID_dhSinglePass_stdDH_sha256kdf_scheme 938 +#define OBJ_dhSinglePass_stdDH_sha256kdf_scheme OBJ_secg_scheme,11L,1L + +#define SN_dhSinglePass_stdDH_sha384kdf_scheme "dhSinglePass-stdDH-sha384kdf-scheme" +#define NID_dhSinglePass_stdDH_sha384kdf_scheme 939 +#define OBJ_dhSinglePass_stdDH_sha384kdf_scheme OBJ_secg_scheme,11L,2L + +#define SN_dhSinglePass_stdDH_sha512kdf_scheme "dhSinglePass-stdDH-sha512kdf-scheme" +#define NID_dhSinglePass_stdDH_sha512kdf_scheme 940 +#define OBJ_dhSinglePass_stdDH_sha512kdf_scheme OBJ_secg_scheme,11L,3L + +#define SN_dhSinglePass_cofactorDH_sha1kdf_scheme "dhSinglePass-cofactorDH-sha1kdf-scheme" +#define NID_dhSinglePass_cofactorDH_sha1kdf_scheme 941 +#define OBJ_dhSinglePass_cofactorDH_sha1kdf_scheme OBJ_x9_63_scheme,3L + +#define SN_dhSinglePass_cofactorDH_sha224kdf_scheme "dhSinglePass-cofactorDH-sha224kdf-scheme" +#define NID_dhSinglePass_cofactorDH_sha224kdf_scheme 942 +#define OBJ_dhSinglePass_cofactorDH_sha224kdf_scheme OBJ_secg_scheme,14L,0L + +#define SN_dhSinglePass_cofactorDH_sha256kdf_scheme "dhSinglePass-cofactorDH-sha256kdf-scheme" +#define NID_dhSinglePass_cofactorDH_sha256kdf_scheme 943 +#define OBJ_dhSinglePass_cofactorDH_sha256kdf_scheme OBJ_secg_scheme,14L,1L + +#define SN_dhSinglePass_cofactorDH_sha384kdf_scheme "dhSinglePass-cofactorDH-sha384kdf-scheme" +#define NID_dhSinglePass_cofactorDH_sha384kdf_scheme 944 +#define OBJ_dhSinglePass_cofactorDH_sha384kdf_scheme OBJ_secg_scheme,14L,2L + +#define SN_dhSinglePass_cofactorDH_sha512kdf_scheme "dhSinglePass-cofactorDH-sha512kdf-scheme" +#define NID_dhSinglePass_cofactorDH_sha512kdf_scheme 945 +#define OBJ_dhSinglePass_cofactorDH_sha512kdf_scheme OBJ_secg_scheme,14L,3L + +#define SN_dh_std_kdf "dh-std-kdf" +#define NID_dh_std_kdf 946 + +#define SN_dh_cofactor_kdf "dh-cofactor-kdf" +#define NID_dh_cofactor_kdf 947 + +#define SN_ct_precert_scts "ct_precert_scts" +#define LN_ct_precert_scts "CT Precertificate SCTs" +#define NID_ct_precert_scts 951 +#define OBJ_ct_precert_scts 1L,3L,6L,1L,4L,1L,11129L,2L,4L,2L + +#define SN_ct_precert_poison "ct_precert_poison" +#define LN_ct_precert_poison "CT Precertificate Poison" +#define NID_ct_precert_poison 952 +#define OBJ_ct_precert_poison 1L,3L,6L,1L,4L,1L,11129L,2L,4L,3L + +#define SN_ct_precert_signer "ct_precert_signer" +#define LN_ct_precert_signer "CT Precertificate Signer" +#define NID_ct_precert_signer 953 +#define OBJ_ct_precert_signer 1L,3L,6L,1L,4L,1L,11129L,2L,4L,4L + +#define SN_ct_cert_scts "ct_cert_scts" +#define LN_ct_cert_scts "CT Certificate SCTs" +#define NID_ct_cert_scts 954 +#define OBJ_ct_cert_scts 1L,3L,6L,1L,4L,1L,11129L,2L,4L,5L + +#define SN_jurisdictionLocalityName "jurisdictionL" +#define LN_jurisdictionLocalityName "jurisdictionLocalityName" +#define NID_jurisdictionLocalityName 955 +#define OBJ_jurisdictionLocalityName 1L,3L,6L,1L,4L,1L,311L,60L,2L,1L,1L + +#define SN_jurisdictionStateOrProvinceName "jurisdictionST" +#define LN_jurisdictionStateOrProvinceName "jurisdictionStateOrProvinceName" +#define NID_jurisdictionStateOrProvinceName 956 +#define OBJ_jurisdictionStateOrProvinceName 1L,3L,6L,1L,4L,1L,311L,60L,2L,1L,2L + +#define SN_jurisdictionCountryName "jurisdictionC" +#define LN_jurisdictionCountryName "jurisdictionCountryName" +#define NID_jurisdictionCountryName 957 +#define OBJ_jurisdictionCountryName 1L,3L,6L,1L,4L,1L,311L,60L,2L,1L,3L + +#define SN_id_scrypt "id-scrypt" +#define LN_id_scrypt "scrypt" +#define NID_id_scrypt 973 +#define OBJ_id_scrypt 1L,3L,6L,1L,4L,1L,11591L,4L,11L + +#define SN_tls1_prf "TLS1-PRF" +#define LN_tls1_prf "tls1-prf" +#define NID_tls1_prf 1021 + +#define SN_hkdf "HKDF" +#define LN_hkdf "hkdf" +#define NID_hkdf 1036 + +#define SN_id_pkinit "id-pkinit" +#define NID_id_pkinit 1031 +#define OBJ_id_pkinit 1L,3L,6L,1L,5L,2L,3L + +#define SN_pkInitClientAuth "pkInitClientAuth" +#define LN_pkInitClientAuth "PKINIT Client Auth" +#define NID_pkInitClientAuth 1032 +#define OBJ_pkInitClientAuth OBJ_id_pkinit,4L + +#define SN_pkInitKDC "pkInitKDC" +#define LN_pkInitKDC "Signing KDC Response" +#define NID_pkInitKDC 1033 +#define OBJ_pkInitKDC OBJ_id_pkinit,5L + +#define SN_X25519 "X25519" +#define NID_X25519 1034 +#define OBJ_X25519 1L,3L,101L,110L + +#define SN_X448 "X448" +#define NID_X448 1035 +#define OBJ_X448 1L,3L,101L,111L + +#define SN_ED25519 "ED25519" +#define NID_ED25519 1087 +#define OBJ_ED25519 1L,3L,101L,112L + +#define SN_ED448 "ED448" +#define NID_ED448 1088 +#define OBJ_ED448 1L,3L,101L,113L + +#define SN_kx_rsa "KxRSA" +#define LN_kx_rsa "kx-rsa" +#define NID_kx_rsa 1037 + +#define SN_kx_ecdhe "KxECDHE" +#define LN_kx_ecdhe "kx-ecdhe" +#define NID_kx_ecdhe 1038 + +#define SN_kx_dhe "KxDHE" +#define LN_kx_dhe "kx-dhe" +#define NID_kx_dhe 1039 + +#define SN_kx_ecdhe_psk "KxECDHE-PSK" +#define LN_kx_ecdhe_psk "kx-ecdhe-psk" +#define NID_kx_ecdhe_psk 1040 + +#define SN_kx_dhe_psk "KxDHE-PSK" +#define LN_kx_dhe_psk "kx-dhe-psk" +#define NID_kx_dhe_psk 1041 + +#define SN_kx_rsa_psk "KxRSA_PSK" +#define LN_kx_rsa_psk "kx-rsa-psk" +#define NID_kx_rsa_psk 1042 + +#define SN_kx_psk "KxPSK" +#define LN_kx_psk "kx-psk" +#define NID_kx_psk 1043 + +#define SN_kx_srp "KxSRP" +#define LN_kx_srp "kx-srp" +#define NID_kx_srp 1044 + +#define SN_kx_gost "KxGOST" +#define LN_kx_gost "kx-gost" +#define NID_kx_gost 1045 + +#define SN_kx_any "KxANY" +#define LN_kx_any "kx-any" +#define NID_kx_any 1063 + +#define SN_auth_rsa "AuthRSA" +#define LN_auth_rsa "auth-rsa" +#define NID_auth_rsa 1046 + +#define SN_auth_ecdsa "AuthECDSA" +#define LN_auth_ecdsa "auth-ecdsa" +#define NID_auth_ecdsa 1047 + +#define SN_auth_psk "AuthPSK" +#define LN_auth_psk "auth-psk" +#define NID_auth_psk 1048 + +#define SN_auth_dss "AuthDSS" +#define LN_auth_dss "auth-dss" +#define NID_auth_dss 1049 + +#define SN_auth_gost01 "AuthGOST01" +#define LN_auth_gost01 "auth-gost01" +#define NID_auth_gost01 1050 + +#define SN_auth_gost12 "AuthGOST12" +#define LN_auth_gost12 "auth-gost12" +#define NID_auth_gost12 1051 + +#define SN_auth_srp "AuthSRP" +#define LN_auth_srp "auth-srp" +#define NID_auth_srp 1052 + +#define SN_auth_null "AuthNULL" +#define LN_auth_null "auth-null" +#define NID_auth_null 1053 + +#define SN_auth_any "AuthANY" +#define LN_auth_any "auth-any" +#define NID_auth_any 1064 + +#define SN_poly1305 "Poly1305" +#define LN_poly1305 "poly1305" +#define NID_poly1305 1061 + +#define SN_siphash "SipHash" +#define LN_siphash "siphash" +#define NID_siphash 1062 + +#define SN_ffdhe2048 "ffdhe2048" +#define NID_ffdhe2048 1126 + +#define SN_ffdhe3072 "ffdhe3072" +#define NID_ffdhe3072 1127 + +#define SN_ffdhe4096 "ffdhe4096" +#define NID_ffdhe4096 1128 + +#define SN_ffdhe6144 "ffdhe6144" +#define NID_ffdhe6144 1129 + +#define SN_ffdhe8192 "ffdhe8192" +#define NID_ffdhe8192 1130 + +#define SN_ISO_UA "ISO-UA" +#define NID_ISO_UA 1150 +#define OBJ_ISO_UA OBJ_member_body,804L + +#define SN_ua_pki "ua-pki" +#define NID_ua_pki 1151 +#define OBJ_ua_pki OBJ_ISO_UA,2L,1L,1L,1L + +#define SN_dstu28147 "dstu28147" +#define LN_dstu28147 "DSTU Gost 28147-2009" +#define NID_dstu28147 1152 +#define OBJ_dstu28147 OBJ_ua_pki,1L,1L,1L + +#define SN_dstu28147_ofb "dstu28147-ofb" +#define LN_dstu28147_ofb "DSTU Gost 28147-2009 OFB mode" +#define NID_dstu28147_ofb 1153 +#define OBJ_dstu28147_ofb OBJ_dstu28147,2L + +#define SN_dstu28147_cfb "dstu28147-cfb" +#define LN_dstu28147_cfb "DSTU Gost 28147-2009 CFB mode" +#define NID_dstu28147_cfb 1154 +#define OBJ_dstu28147_cfb OBJ_dstu28147,3L + +#define SN_dstu28147_wrap "dstu28147-wrap" +#define LN_dstu28147_wrap "DSTU Gost 28147-2009 key wrap" +#define NID_dstu28147_wrap 1155 +#define OBJ_dstu28147_wrap OBJ_dstu28147,5L + +#define SN_hmacWithDstu34311 "hmacWithDstu34311" +#define LN_hmacWithDstu34311 "HMAC DSTU Gost 34311-95" +#define NID_hmacWithDstu34311 1156 +#define OBJ_hmacWithDstu34311 OBJ_ua_pki,1L,1L,2L + +#define SN_dstu34311 "dstu34311" +#define LN_dstu34311 "DSTU Gost 34311-95" +#define NID_dstu34311 1157 +#define OBJ_dstu34311 OBJ_ua_pki,1L,2L,1L + +#define SN_dstu4145le "dstu4145le" +#define LN_dstu4145le "DSTU 4145-2002 little endian" +#define NID_dstu4145le 1158 +#define OBJ_dstu4145le OBJ_ua_pki,1L,3L,1L,1L + +#define SN_dstu4145be "dstu4145be" +#define LN_dstu4145be "DSTU 4145-2002 big endian" +#define NID_dstu4145be 1159 +#define OBJ_dstu4145be OBJ_dstu4145le,1L,1L + +#define SN_uacurve0 "uacurve0" +#define LN_uacurve0 "DSTU curve 0" +#define NID_uacurve0 1160 +#define OBJ_uacurve0 OBJ_dstu4145le,2L,0L + +#define SN_uacurve1 "uacurve1" +#define LN_uacurve1 "DSTU curve 1" +#define NID_uacurve1 1161 +#define OBJ_uacurve1 OBJ_dstu4145le,2L,1L + +#define SN_uacurve2 "uacurve2" +#define LN_uacurve2 "DSTU curve 2" +#define NID_uacurve2 1162 +#define OBJ_uacurve2 OBJ_dstu4145le,2L,2L + +#define SN_uacurve3 "uacurve3" +#define LN_uacurve3 "DSTU curve 3" +#define NID_uacurve3 1163 +#define OBJ_uacurve3 OBJ_dstu4145le,2L,3L + +#define SN_uacurve4 "uacurve4" +#define LN_uacurve4 "DSTU curve 4" +#define NID_uacurve4 1164 +#define OBJ_uacurve4 OBJ_dstu4145le,2L,4L + +#define SN_uacurve5 "uacurve5" +#define LN_uacurve5 "DSTU curve 5" +#define NID_uacurve5 1165 +#define OBJ_uacurve5 OBJ_dstu4145le,2L,5L + +#define SN_uacurve6 "uacurve6" +#define LN_uacurve6 "DSTU curve 6" +#define NID_uacurve6 1166 +#define OBJ_uacurve6 OBJ_dstu4145le,2L,6L + +#define SN_uacurve7 "uacurve7" +#define LN_uacurve7 "DSTU curve 7" +#define NID_uacurve7 1167 +#define OBJ_uacurve7 OBJ_dstu4145le,2L,7L + +#define SN_uacurve8 "uacurve8" +#define LN_uacurve8 "DSTU curve 8" +#define NID_uacurve8 1168 +#define OBJ_uacurve8 OBJ_dstu4145le,2L,8L + +#define SN_uacurve9 "uacurve9" +#define LN_uacurve9 "DSTU curve 9" +#define NID_uacurve9 1169 +#define OBJ_uacurve9 OBJ_dstu4145le,2L,9L diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/objects.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/objects.h new file mode 100644 index 000000000..5e8b5762f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/objects.h @@ -0,0 +1,175 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_OBJECTS_H +# define HEADER_OBJECTS_H + +# include +# include +# include +# include + +# define OBJ_NAME_TYPE_UNDEF 0x00 +# define OBJ_NAME_TYPE_MD_METH 0x01 +# define OBJ_NAME_TYPE_CIPHER_METH 0x02 +# define OBJ_NAME_TYPE_PKEY_METH 0x03 +# define OBJ_NAME_TYPE_COMP_METH 0x04 +# define OBJ_NAME_TYPE_NUM 0x05 + +# define OBJ_NAME_ALIAS 0x8000 + +# define OBJ_BSEARCH_VALUE_ON_NOMATCH 0x01 +# define OBJ_BSEARCH_FIRST_VALUE_ON_MATCH 0x02 + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct obj_name_st { + int type; + int alias; + const char *name; + const char *data; +} OBJ_NAME; + +# define OBJ_create_and_add_object(a,b,c) OBJ_create(a,b,c) + +int OBJ_NAME_init(void); +int OBJ_NAME_new_index(unsigned long (*hash_func) (const char *), + int (*cmp_func) (const char *, const char *), + void (*free_func) (const char *, int, const char *)); +const char *OBJ_NAME_get(const char *name, int type); +int OBJ_NAME_add(const char *name, int type, const char *data); +int OBJ_NAME_remove(const char *name, int type); +void OBJ_NAME_cleanup(int type); /* -1 for everything */ +void OBJ_NAME_do_all(int type, void (*fn) (const OBJ_NAME *, void *arg), + void *arg); +void OBJ_NAME_do_all_sorted(int type, + void (*fn) (const OBJ_NAME *, void *arg), + void *arg); + +ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *o); +ASN1_OBJECT *OBJ_nid2obj(int n); +const char *OBJ_nid2ln(int n); +const char *OBJ_nid2sn(int n); +int OBJ_obj2nid(const ASN1_OBJECT *o); +ASN1_OBJECT *OBJ_txt2obj(const char *s, int no_name); +int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name); +int OBJ_txt2nid(const char *s); +int OBJ_ln2nid(const char *s); +int OBJ_sn2nid(const char *s); +int OBJ_cmp(const ASN1_OBJECT *a, const ASN1_OBJECT *b); +const void *OBJ_bsearch_(const void *key, const void *base, int num, int size, + int (*cmp) (const void *, const void *)); +const void *OBJ_bsearch_ex_(const void *key, const void *base, int num, + int size, + int (*cmp) (const void *, const void *), + int flags); + +# define _DECLARE_OBJ_BSEARCH_CMP_FN(scope, type1, type2, nm) \ + static int nm##_cmp_BSEARCH_CMP_FN(const void *, const void *); \ + static int nm##_cmp(type1 const *, type2 const *); \ + scope type2 * OBJ_bsearch_##nm(type1 *key, type2 const *base, int num) + +# define DECLARE_OBJ_BSEARCH_CMP_FN(type1, type2, cmp) \ + _DECLARE_OBJ_BSEARCH_CMP_FN(static, type1, type2, cmp) +# define DECLARE_OBJ_BSEARCH_GLOBAL_CMP_FN(type1, type2, nm) \ + type2 * OBJ_bsearch_##nm(type1 *key, type2 const *base, int num) + +/*- + * Unsolved problem: if a type is actually a pointer type, like + * nid_triple is, then its impossible to get a const where you need + * it. Consider: + * + * typedef int nid_triple[3]; + * const void *a_; + * const nid_triple const *a = a_; + * + * The assignment discards a const because what you really want is: + * + * const int const * const *a = a_; + * + * But if you do that, you lose the fact that a is an array of 3 ints, + * which breaks comparison functions. + * + * Thus we end up having to cast, sadly, or unpack the + * declarations. Or, as I finally did in this case, declare nid_triple + * to be a struct, which it should have been in the first place. + * + * Ben, August 2008. + * + * Also, strictly speaking not all types need be const, but handling + * the non-constness means a lot of complication, and in practice + * comparison routines do always not touch their arguments. + */ + +# define IMPLEMENT_OBJ_BSEARCH_CMP_FN(type1, type2, nm) \ + static int nm##_cmp_BSEARCH_CMP_FN(const void *a_, const void *b_) \ + { \ + type1 const *a = a_; \ + type2 const *b = b_; \ + return nm##_cmp(a,b); \ + } \ + static type2 *OBJ_bsearch_##nm(type1 *key, type2 const *base, int num) \ + { \ + return (type2 *)OBJ_bsearch_(key, base, num, sizeof(type2), \ + nm##_cmp_BSEARCH_CMP_FN); \ + } \ + extern void dummy_prototype(void) + +# define IMPLEMENT_OBJ_BSEARCH_GLOBAL_CMP_FN(type1, type2, nm) \ + static int nm##_cmp_BSEARCH_CMP_FN(const void *a_, const void *b_) \ + { \ + type1 const *a = a_; \ + type2 const *b = b_; \ + return nm##_cmp(a,b); \ + } \ + type2 *OBJ_bsearch_##nm(type1 *key, type2 const *base, int num) \ + { \ + return (type2 *)OBJ_bsearch_(key, base, num, sizeof(type2), \ + nm##_cmp_BSEARCH_CMP_FN); \ + } \ + extern void dummy_prototype(void) + +# define OBJ_bsearch(type1,key,type2,base,num,cmp) \ + ((type2 *)OBJ_bsearch_(CHECKED_PTR_OF(type1,key),CHECKED_PTR_OF(type2,base), \ + num,sizeof(type2), \ + ((void)CHECKED_PTR_OF(type1,cmp##_type_1), \ + (void)CHECKED_PTR_OF(type2,cmp##_type_2), \ + cmp##_BSEARCH_CMP_FN))) + +# define OBJ_bsearch_ex(type1,key,type2,base,num,cmp,flags) \ + ((type2 *)OBJ_bsearch_ex_(CHECKED_PTR_OF(type1,key),CHECKED_PTR_OF(type2,base), \ + num,sizeof(type2), \ + ((void)CHECKED_PTR_OF(type1,cmp##_type_1), \ + (void)type_2=CHECKED_PTR_OF(type2,cmp##_type_2), \ + cmp##_BSEARCH_CMP_FN)),flags) + +int OBJ_new_nid(int num); +int OBJ_add_object(const ASN1_OBJECT *obj); +int OBJ_create(const char *oid, const char *sn, const char *ln); +#if OPENSSL_API_COMPAT < 0x10100000L +# define OBJ_cleanup() while(0) continue +#endif +int OBJ_create_objects(BIO *in); + +size_t OBJ_length(const ASN1_OBJECT *obj); +const unsigned char *OBJ_get0_data(const ASN1_OBJECT *obj); + +int OBJ_find_sigid_algs(int signid, int *pdig_nid, int *ppkey_nid); +int OBJ_find_sigid_by_algs(int *psignid, int dig_nid, int pkey_nid); +int OBJ_add_sigid(int signid, int dig_id, int pkey_id); +void OBJ_sigid_free(void); + + +# ifdef __cplusplus +} +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/objectserr.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/objectserr.h new file mode 100644 index 000000000..02308dfac --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/objectserr.h @@ -0,0 +1,38 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_OBJERR_H +# define HEADER_OBJERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_OBJ_strings(void); + +/* + * OBJ function codes. + */ +# define OBJ_F_OBJ_ADD_OBJECT 105 +# define OBJ_F_OBJ_ADD_SIGID 107 +# define OBJ_F_OBJ_CREATE 100 +# define OBJ_F_OBJ_DUP 101 +# define OBJ_F_OBJ_NAME_NEW_INDEX 106 +# define OBJ_F_OBJ_NID2LN 102 +# define OBJ_F_OBJ_NID2OBJ 103 +# define OBJ_F_OBJ_NID2SN 104 +# define OBJ_F_OBJ_TXT2OBJ 108 + +/* + * OBJ reason codes. + */ +# define OBJ_R_OID_EXISTS 102 +# define OBJ_R_UNKNOWN_NID 101 + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/ocsp.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ocsp.h new file mode 100644 index 000000000..0a17166b5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ocsp.h @@ -0,0 +1,352 @@ +/* + * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_OCSP_H +# define HEADER_OCSP_H + +#include + +/* + * These definitions are outside the OPENSSL_NO_OCSP guard because although for + * historical reasons they have OCSP_* names, they can actually be used + * independently of OCSP. E.g. see RFC5280 + */ +/*- + * CRLReason ::= ENUMERATED { + * unspecified (0), + * keyCompromise (1), + * cACompromise (2), + * affiliationChanged (3), + * superseded (4), + * cessationOfOperation (5), + * certificateHold (6), + * removeFromCRL (8) } + */ +# define OCSP_REVOKED_STATUS_NOSTATUS -1 +# define OCSP_REVOKED_STATUS_UNSPECIFIED 0 +# define OCSP_REVOKED_STATUS_KEYCOMPROMISE 1 +# define OCSP_REVOKED_STATUS_CACOMPROMISE 2 +# define OCSP_REVOKED_STATUS_AFFILIATIONCHANGED 3 +# define OCSP_REVOKED_STATUS_SUPERSEDED 4 +# define OCSP_REVOKED_STATUS_CESSATIONOFOPERATION 5 +# define OCSP_REVOKED_STATUS_CERTIFICATEHOLD 6 +# define OCSP_REVOKED_STATUS_REMOVEFROMCRL 8 + + +# ifndef OPENSSL_NO_OCSP + +# include +# include +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Various flags and values */ + +# define OCSP_DEFAULT_NONCE_LENGTH 16 + +# define OCSP_NOCERTS 0x1 +# define OCSP_NOINTERN 0x2 +# define OCSP_NOSIGS 0x4 +# define OCSP_NOCHAIN 0x8 +# define OCSP_NOVERIFY 0x10 +# define OCSP_NOEXPLICIT 0x20 +# define OCSP_NOCASIGN 0x40 +# define OCSP_NODELEGATED 0x80 +# define OCSP_NOCHECKS 0x100 +# define OCSP_TRUSTOTHER 0x200 +# define OCSP_RESPID_KEY 0x400 +# define OCSP_NOTIME 0x800 + +typedef struct ocsp_cert_id_st OCSP_CERTID; + +DEFINE_STACK_OF(OCSP_CERTID) + +typedef struct ocsp_one_request_st OCSP_ONEREQ; + +DEFINE_STACK_OF(OCSP_ONEREQ) + +typedef struct ocsp_req_info_st OCSP_REQINFO; +typedef struct ocsp_signature_st OCSP_SIGNATURE; +typedef struct ocsp_request_st OCSP_REQUEST; + +# define OCSP_RESPONSE_STATUS_SUCCESSFUL 0 +# define OCSP_RESPONSE_STATUS_MALFORMEDREQUEST 1 +# define OCSP_RESPONSE_STATUS_INTERNALERROR 2 +# define OCSP_RESPONSE_STATUS_TRYLATER 3 +# define OCSP_RESPONSE_STATUS_SIGREQUIRED 5 +# define OCSP_RESPONSE_STATUS_UNAUTHORIZED 6 + +typedef struct ocsp_resp_bytes_st OCSP_RESPBYTES; + +# define V_OCSP_RESPID_NAME 0 +# define V_OCSP_RESPID_KEY 1 + +DEFINE_STACK_OF(OCSP_RESPID) + +typedef struct ocsp_revoked_info_st OCSP_REVOKEDINFO; + +# define V_OCSP_CERTSTATUS_GOOD 0 +# define V_OCSP_CERTSTATUS_REVOKED 1 +# define V_OCSP_CERTSTATUS_UNKNOWN 2 + +typedef struct ocsp_cert_status_st OCSP_CERTSTATUS; +typedef struct ocsp_single_response_st OCSP_SINGLERESP; + +DEFINE_STACK_OF(OCSP_SINGLERESP) + +typedef struct ocsp_response_data_st OCSP_RESPDATA; + +typedef struct ocsp_basic_response_st OCSP_BASICRESP; + +typedef struct ocsp_crl_id_st OCSP_CRLID; +typedef struct ocsp_service_locator_st OCSP_SERVICELOC; + +# define PEM_STRING_OCSP_REQUEST "OCSP REQUEST" +# define PEM_STRING_OCSP_RESPONSE "OCSP RESPONSE" + +# define d2i_OCSP_REQUEST_bio(bp,p) ASN1_d2i_bio_of(OCSP_REQUEST,OCSP_REQUEST_new,d2i_OCSP_REQUEST,bp,p) + +# define d2i_OCSP_RESPONSE_bio(bp,p) ASN1_d2i_bio_of(OCSP_RESPONSE,OCSP_RESPONSE_new,d2i_OCSP_RESPONSE,bp,p) + +# define PEM_read_bio_OCSP_REQUEST(bp,x,cb) (OCSP_REQUEST *)PEM_ASN1_read_bio( \ + (char *(*)())d2i_OCSP_REQUEST,PEM_STRING_OCSP_REQUEST, \ + bp,(char **)(x),cb,NULL) + +# define PEM_read_bio_OCSP_RESPONSE(bp,x,cb)(OCSP_RESPONSE *)PEM_ASN1_read_bio(\ + (char *(*)())d2i_OCSP_RESPONSE,PEM_STRING_OCSP_RESPONSE, \ + bp,(char **)(x),cb,NULL) + +# define PEM_write_bio_OCSP_REQUEST(bp,o) \ + PEM_ASN1_write_bio((int (*)())i2d_OCSP_REQUEST,PEM_STRING_OCSP_REQUEST,\ + bp,(char *)(o), NULL,NULL,0,NULL,NULL) + +# define PEM_write_bio_OCSP_RESPONSE(bp,o) \ + PEM_ASN1_write_bio((int (*)())i2d_OCSP_RESPONSE,PEM_STRING_OCSP_RESPONSE,\ + bp,(char *)(o), NULL,NULL,0,NULL,NULL) + +# define i2d_OCSP_RESPONSE_bio(bp,o) ASN1_i2d_bio_of(OCSP_RESPONSE,i2d_OCSP_RESPONSE,bp,o) + +# define i2d_OCSP_REQUEST_bio(bp,o) ASN1_i2d_bio_of(OCSP_REQUEST,i2d_OCSP_REQUEST,bp,o) + +# define ASN1_BIT_STRING_digest(data,type,md,len) \ + ASN1_item_digest(ASN1_ITEM_rptr(ASN1_BIT_STRING),type,data,md,len) + +# define OCSP_CERTSTATUS_dup(cs)\ + (OCSP_CERTSTATUS*)ASN1_dup((int(*)())i2d_OCSP_CERTSTATUS,\ + (char *(*)())d2i_OCSP_CERTSTATUS,(char *)(cs)) + +OCSP_CERTID *OCSP_CERTID_dup(OCSP_CERTID *id); + +OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, const char *path, OCSP_REQUEST *req); +OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, const char *path, OCSP_REQUEST *req, + int maxline); +int OCSP_REQ_CTX_nbio(OCSP_REQ_CTX *rctx); +int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx); +OCSP_REQ_CTX *OCSP_REQ_CTX_new(BIO *io, int maxline); +void OCSP_REQ_CTX_free(OCSP_REQ_CTX *rctx); +void OCSP_set_max_response_length(OCSP_REQ_CTX *rctx, unsigned long len); +int OCSP_REQ_CTX_i2d(OCSP_REQ_CTX *rctx, const ASN1_ITEM *it, + ASN1_VALUE *val); +int OCSP_REQ_CTX_nbio_d2i(OCSP_REQ_CTX *rctx, ASN1_VALUE **pval, + const ASN1_ITEM *it); +BIO *OCSP_REQ_CTX_get0_mem_bio(OCSP_REQ_CTX *rctx); +int OCSP_REQ_CTX_http(OCSP_REQ_CTX *rctx, const char *op, const char *path); +int OCSP_REQ_CTX_set1_req(OCSP_REQ_CTX *rctx, OCSP_REQUEST *req); +int OCSP_REQ_CTX_add1_header(OCSP_REQ_CTX *rctx, + const char *name, const char *value); + +OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, const X509 *subject, + const X509 *issuer); + +OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst, + const X509_NAME *issuerName, + const ASN1_BIT_STRING *issuerKey, + const ASN1_INTEGER *serialNumber); + +OCSP_ONEREQ *OCSP_request_add0_id(OCSP_REQUEST *req, OCSP_CERTID *cid); + +int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len); +int OCSP_basic_add1_nonce(OCSP_BASICRESP *resp, unsigned char *val, int len); +int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs); +int OCSP_copy_nonce(OCSP_BASICRESP *resp, OCSP_REQUEST *req); + +int OCSP_request_set1_name(OCSP_REQUEST *req, X509_NAME *nm); +int OCSP_request_add1_cert(OCSP_REQUEST *req, X509 *cert); + +int OCSP_request_sign(OCSP_REQUEST *req, + X509 *signer, + EVP_PKEY *key, + const EVP_MD *dgst, + STACK_OF(X509) *certs, unsigned long flags); + +int OCSP_response_status(OCSP_RESPONSE *resp); +OCSP_BASICRESP *OCSP_response_get1_basic(OCSP_RESPONSE *resp); + +const ASN1_OCTET_STRING *OCSP_resp_get0_signature(const OCSP_BASICRESP *bs); +const X509_ALGOR *OCSP_resp_get0_tbs_sigalg(const OCSP_BASICRESP *bs); +const OCSP_RESPDATA *OCSP_resp_get0_respdata(const OCSP_BASICRESP *bs); +int OCSP_resp_get0_signer(OCSP_BASICRESP *bs, X509 **signer, + STACK_OF(X509) *extra_certs); + +int OCSP_resp_count(OCSP_BASICRESP *bs); +OCSP_SINGLERESP *OCSP_resp_get0(OCSP_BASICRESP *bs, int idx); +const ASN1_GENERALIZEDTIME *OCSP_resp_get0_produced_at(const OCSP_BASICRESP* bs); +const STACK_OF(X509) *OCSP_resp_get0_certs(const OCSP_BASICRESP *bs); +int OCSP_resp_get0_id(const OCSP_BASICRESP *bs, + const ASN1_OCTET_STRING **pid, + const X509_NAME **pname); +int OCSP_resp_get1_id(const OCSP_BASICRESP *bs, + ASN1_OCTET_STRING **pid, + X509_NAME **pname); + +int OCSP_resp_find(OCSP_BASICRESP *bs, OCSP_CERTID *id, int last); +int OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason, + ASN1_GENERALIZEDTIME **revtime, + ASN1_GENERALIZEDTIME **thisupd, + ASN1_GENERALIZEDTIME **nextupd); +int OCSP_resp_find_status(OCSP_BASICRESP *bs, OCSP_CERTID *id, int *status, + int *reason, + ASN1_GENERALIZEDTIME **revtime, + ASN1_GENERALIZEDTIME **thisupd, + ASN1_GENERALIZEDTIME **nextupd); +int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd, + ASN1_GENERALIZEDTIME *nextupd, long sec, long maxsec); + +int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs, + X509_STORE *store, unsigned long flags); + +int OCSP_parse_url(const char *url, char **phost, char **pport, char **ppath, + int *pssl); + +int OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b); +int OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b); + +int OCSP_request_onereq_count(OCSP_REQUEST *req); +OCSP_ONEREQ *OCSP_request_onereq_get0(OCSP_REQUEST *req, int i); +OCSP_CERTID *OCSP_onereq_get0_id(OCSP_ONEREQ *one); +int OCSP_id_get0_info(ASN1_OCTET_STRING **piNameHash, ASN1_OBJECT **pmd, + ASN1_OCTET_STRING **pikeyHash, + ASN1_INTEGER **pserial, OCSP_CERTID *cid); +int OCSP_request_is_signed(OCSP_REQUEST *req); +OCSP_RESPONSE *OCSP_response_create(int status, OCSP_BASICRESP *bs); +OCSP_SINGLERESP *OCSP_basic_add1_status(OCSP_BASICRESP *rsp, + OCSP_CERTID *cid, + int status, int reason, + ASN1_TIME *revtime, + ASN1_TIME *thisupd, + ASN1_TIME *nextupd); +int OCSP_basic_add1_cert(OCSP_BASICRESP *resp, X509 *cert); +int OCSP_basic_sign(OCSP_BASICRESP *brsp, + X509 *signer, EVP_PKEY *key, const EVP_MD *dgst, + STACK_OF(X509) *certs, unsigned long flags); +int OCSP_basic_sign_ctx(OCSP_BASICRESP *brsp, + X509 *signer, EVP_MD_CTX *ctx, + STACK_OF(X509) *certs, unsigned long flags); +int OCSP_RESPID_set_by_name(OCSP_RESPID *respid, X509 *cert); +int OCSP_RESPID_set_by_key(OCSP_RESPID *respid, X509 *cert); +int OCSP_RESPID_match(OCSP_RESPID *respid, X509 *cert); + +X509_EXTENSION *OCSP_crlID_new(const char *url, long *n, char *tim); + +X509_EXTENSION *OCSP_accept_responses_new(char **oids); + +X509_EXTENSION *OCSP_archive_cutoff_new(char *tim); + +X509_EXTENSION *OCSP_url_svcloc_new(X509_NAME *issuer, const char **urls); + +int OCSP_REQUEST_get_ext_count(OCSP_REQUEST *x); +int OCSP_REQUEST_get_ext_by_NID(OCSP_REQUEST *x, int nid, int lastpos); +int OCSP_REQUEST_get_ext_by_OBJ(OCSP_REQUEST *x, const ASN1_OBJECT *obj, + int lastpos); +int OCSP_REQUEST_get_ext_by_critical(OCSP_REQUEST *x, int crit, int lastpos); +X509_EXTENSION *OCSP_REQUEST_get_ext(OCSP_REQUEST *x, int loc); +X509_EXTENSION *OCSP_REQUEST_delete_ext(OCSP_REQUEST *x, int loc); +void *OCSP_REQUEST_get1_ext_d2i(OCSP_REQUEST *x, int nid, int *crit, + int *idx); +int OCSP_REQUEST_add1_ext_i2d(OCSP_REQUEST *x, int nid, void *value, int crit, + unsigned long flags); +int OCSP_REQUEST_add_ext(OCSP_REQUEST *x, X509_EXTENSION *ex, int loc); + +int OCSP_ONEREQ_get_ext_count(OCSP_ONEREQ *x); +int OCSP_ONEREQ_get_ext_by_NID(OCSP_ONEREQ *x, int nid, int lastpos); +int OCSP_ONEREQ_get_ext_by_OBJ(OCSP_ONEREQ *x, const ASN1_OBJECT *obj, int lastpos); +int OCSP_ONEREQ_get_ext_by_critical(OCSP_ONEREQ *x, int crit, int lastpos); +X509_EXTENSION *OCSP_ONEREQ_get_ext(OCSP_ONEREQ *x, int loc); +X509_EXTENSION *OCSP_ONEREQ_delete_ext(OCSP_ONEREQ *x, int loc); +void *OCSP_ONEREQ_get1_ext_d2i(OCSP_ONEREQ *x, int nid, int *crit, int *idx); +int OCSP_ONEREQ_add1_ext_i2d(OCSP_ONEREQ *x, int nid, void *value, int crit, + unsigned long flags); +int OCSP_ONEREQ_add_ext(OCSP_ONEREQ *x, X509_EXTENSION *ex, int loc); + +int OCSP_BASICRESP_get_ext_count(OCSP_BASICRESP *x); +int OCSP_BASICRESP_get_ext_by_NID(OCSP_BASICRESP *x, int nid, int lastpos); +int OCSP_BASICRESP_get_ext_by_OBJ(OCSP_BASICRESP *x, const ASN1_OBJECT *obj, + int lastpos); +int OCSP_BASICRESP_get_ext_by_critical(OCSP_BASICRESP *x, int crit, + int lastpos); +X509_EXTENSION *OCSP_BASICRESP_get_ext(OCSP_BASICRESP *x, int loc); +X509_EXTENSION *OCSP_BASICRESP_delete_ext(OCSP_BASICRESP *x, int loc); +void *OCSP_BASICRESP_get1_ext_d2i(OCSP_BASICRESP *x, int nid, int *crit, + int *idx); +int OCSP_BASICRESP_add1_ext_i2d(OCSP_BASICRESP *x, int nid, void *value, + int crit, unsigned long flags); +int OCSP_BASICRESP_add_ext(OCSP_BASICRESP *x, X509_EXTENSION *ex, int loc); + +int OCSP_SINGLERESP_get_ext_count(OCSP_SINGLERESP *x); +int OCSP_SINGLERESP_get_ext_by_NID(OCSP_SINGLERESP *x, int nid, int lastpos); +int OCSP_SINGLERESP_get_ext_by_OBJ(OCSP_SINGLERESP *x, const ASN1_OBJECT *obj, + int lastpos); +int OCSP_SINGLERESP_get_ext_by_critical(OCSP_SINGLERESP *x, int crit, + int lastpos); +X509_EXTENSION *OCSP_SINGLERESP_get_ext(OCSP_SINGLERESP *x, int loc); +X509_EXTENSION *OCSP_SINGLERESP_delete_ext(OCSP_SINGLERESP *x, int loc); +void *OCSP_SINGLERESP_get1_ext_d2i(OCSP_SINGLERESP *x, int nid, int *crit, + int *idx); +int OCSP_SINGLERESP_add1_ext_i2d(OCSP_SINGLERESP *x, int nid, void *value, + int crit, unsigned long flags); +int OCSP_SINGLERESP_add_ext(OCSP_SINGLERESP *x, X509_EXTENSION *ex, int loc); +const OCSP_CERTID *OCSP_SINGLERESP_get0_id(const OCSP_SINGLERESP *x); + +DECLARE_ASN1_FUNCTIONS(OCSP_SINGLERESP) +DECLARE_ASN1_FUNCTIONS(OCSP_CERTSTATUS) +DECLARE_ASN1_FUNCTIONS(OCSP_REVOKEDINFO) +DECLARE_ASN1_FUNCTIONS(OCSP_BASICRESP) +DECLARE_ASN1_FUNCTIONS(OCSP_RESPDATA) +DECLARE_ASN1_FUNCTIONS(OCSP_RESPID) +DECLARE_ASN1_FUNCTIONS(OCSP_RESPONSE) +DECLARE_ASN1_FUNCTIONS(OCSP_RESPBYTES) +DECLARE_ASN1_FUNCTIONS(OCSP_ONEREQ) +DECLARE_ASN1_FUNCTIONS(OCSP_CERTID) +DECLARE_ASN1_FUNCTIONS(OCSP_REQUEST) +DECLARE_ASN1_FUNCTIONS(OCSP_SIGNATURE) +DECLARE_ASN1_FUNCTIONS(OCSP_REQINFO) +DECLARE_ASN1_FUNCTIONS(OCSP_CRLID) +DECLARE_ASN1_FUNCTIONS(OCSP_SERVICELOC) + +const char *OCSP_response_status_str(long s); +const char *OCSP_cert_status_str(long s); +const char *OCSP_crl_reason_str(long s); + +int OCSP_REQUEST_print(BIO *bp, OCSP_REQUEST *a, unsigned long flags); +int OCSP_RESPONSE_print(BIO *bp, OCSP_RESPONSE *o, unsigned long flags); + +int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, + X509_STORE *st, unsigned long flags); + + +# ifdef __cplusplus +} +# endif +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/ocsperr.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ocsperr.h new file mode 100644 index 000000000..7d93b12d4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ocsperr.h @@ -0,0 +1,74 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_OCSPERR_H +# define HEADER_OCSPERR_H + +# include + +# ifndef OPENSSL_NO_OCSP + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_OCSP_strings(void); + +/* + * OCSP function codes. + */ +# define OCSP_F_D2I_OCSP_NONCE 102 +# define OCSP_F_OCSP_BASIC_ADD1_STATUS 103 +# define OCSP_F_OCSP_BASIC_SIGN 104 +# define OCSP_F_OCSP_BASIC_SIGN_CTX 119 +# define OCSP_F_OCSP_BASIC_VERIFY 105 +# define OCSP_F_OCSP_CERT_ID_NEW 101 +# define OCSP_F_OCSP_CHECK_DELEGATED 106 +# define OCSP_F_OCSP_CHECK_IDS 107 +# define OCSP_F_OCSP_CHECK_ISSUER 108 +# define OCSP_F_OCSP_CHECK_VALIDITY 115 +# define OCSP_F_OCSP_MATCH_ISSUERID 109 +# define OCSP_F_OCSP_PARSE_URL 114 +# define OCSP_F_OCSP_REQUEST_SIGN 110 +# define OCSP_F_OCSP_REQUEST_VERIFY 116 +# define OCSP_F_OCSP_RESPONSE_GET1_BASIC 111 +# define OCSP_F_PARSE_HTTP_LINE1 118 + +/* + * OCSP reason codes. + */ +# define OCSP_R_CERTIFICATE_VERIFY_ERROR 101 +# define OCSP_R_DIGEST_ERR 102 +# define OCSP_R_ERROR_IN_NEXTUPDATE_FIELD 122 +# define OCSP_R_ERROR_IN_THISUPDATE_FIELD 123 +# define OCSP_R_ERROR_PARSING_URL 121 +# define OCSP_R_MISSING_OCSPSIGNING_USAGE 103 +# define OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE 124 +# define OCSP_R_NOT_BASIC_RESPONSE 104 +# define OCSP_R_NO_CERTIFICATES_IN_CHAIN 105 +# define OCSP_R_NO_RESPONSE_DATA 108 +# define OCSP_R_NO_REVOKED_TIME 109 +# define OCSP_R_NO_SIGNER_KEY 130 +# define OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 110 +# define OCSP_R_REQUEST_NOT_SIGNED 128 +# define OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA 111 +# define OCSP_R_ROOT_CA_NOT_TRUSTED 112 +# define OCSP_R_SERVER_RESPONSE_ERROR 114 +# define OCSP_R_SERVER_RESPONSE_PARSE_ERROR 115 +# define OCSP_R_SIGNATURE_FAILURE 117 +# define OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND 118 +# define OCSP_R_STATUS_EXPIRED 125 +# define OCSP_R_STATUS_NOT_YET_VALID 126 +# define OCSP_R_STATUS_TOO_OLD 127 +# define OCSP_R_UNKNOWN_MESSAGE_DIGEST 119 +# define OCSP_R_UNKNOWN_NID 120 +# define OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE 129 + +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/opensslconf.h.in b/trunk/3rdparty/openssl-1.1-fit/include/openssl/opensslconf.h.in new file mode 100644 index 000000000..bc98cad51 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/opensslconf.h.in @@ -0,0 +1,155 @@ +/* + * {- join("\n * ", @autowarntext) -} + * + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef OPENSSL_ALGORITHM_DEFINES +# error OPENSSL_ALGORITHM_DEFINES no longer supported +#endif + +/* + * OpenSSL was configured with the following options: + */ + +{- if (@{$config{openssl_sys_defines}}) { + foreach (@{$config{openssl_sys_defines}}) { + $OUT .= "#ifndef $_\n"; + $OUT .= "# define $_ 1\n"; + $OUT .= "#endif\n"; + } + } + foreach (@{$config{openssl_api_defines}}) { + (my $macro, my $value) = $_ =~ /^(.*?)=(.*?)$/; + $OUT .= "#define $macro $value\n"; + } + if (@{$config{openssl_algorithm_defines}}) { + foreach (@{$config{openssl_algorithm_defines}}) { + $OUT .= "#ifndef $_\n"; + $OUT .= "# define $_\n"; + $OUT .= "#endif\n"; + } + } + if (@{$config{openssl_thread_defines}}) { + foreach (@{$config{openssl_thread_defines}}) { + $OUT .= "#ifndef $_\n"; + $OUT .= "# define $_\n"; + $OUT .= "#endif\n"; + } + } + if (@{$config{openssl_other_defines}}) { + foreach (@{$config{openssl_other_defines}}) { + $OUT .= "#ifndef $_\n"; + $OUT .= "# define $_\n"; + $OUT .= "#endif\n"; + } + } + ""; +-} + +/* + * Sometimes OPENSSSL_NO_xxx ends up with an empty file and some compilers + * don't like that. This will hopefully silence them. + */ +#define NON_EMPTY_TRANSLATION_UNIT static void *dummy = &dummy; + +/* + * Applications should use -DOPENSSL_API_COMPAT= to suppress the + * declarations of functions deprecated in or before . Otherwise, they + * still won't see them if the library has been built to disable deprecated + * functions. + */ +#ifndef DECLARE_DEPRECATED +# define DECLARE_DEPRECATED(f) f; +# ifdef __GNUC__ +# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 0) +# undef DECLARE_DEPRECATED +# define DECLARE_DEPRECATED(f) f __attribute__ ((deprecated)); +# endif +# endif +#endif + +#ifndef OPENSSL_FILE +# ifdef OPENSSL_NO_FILENAMES +# define OPENSSL_FILE "" +# define OPENSSL_LINE 0 +# else +# define OPENSSL_FILE __FILE__ +# define OPENSSL_LINE __LINE__ +# endif +#endif + +#ifndef OPENSSL_MIN_API +# define OPENSSL_MIN_API 0 +#endif + +#if !defined(OPENSSL_API_COMPAT) || OPENSSL_API_COMPAT < OPENSSL_MIN_API +# undef OPENSSL_API_COMPAT +# define OPENSSL_API_COMPAT OPENSSL_MIN_API +#endif + +/* + * Do not deprecate things to be deprecated in version 1.2.0 before the + * OpenSSL version number matches. + */ +#if OPENSSL_VERSION_NUMBER < 0x10200000L +# define DEPRECATEDIN_1_2_0(f) f; +#elif OPENSSL_API_COMPAT < 0x10200000L +# define DEPRECATEDIN_1_2_0(f) DECLARE_DEPRECATED(f) +#else +# define DEPRECATEDIN_1_2_0(f) +#endif + +#if OPENSSL_API_COMPAT < 0x10100000L +# define DEPRECATEDIN_1_1_0(f) DECLARE_DEPRECATED(f) +#else +# define DEPRECATEDIN_1_1_0(f) +#endif + +#if OPENSSL_API_COMPAT < 0x10000000L +# define DEPRECATEDIN_1_0_0(f) DECLARE_DEPRECATED(f) +#else +# define DEPRECATEDIN_1_0_0(f) +#endif + +#if OPENSSL_API_COMPAT < 0x00908000L +# define DEPRECATEDIN_0_9_8(f) DECLARE_DEPRECATED(f) +#else +# define DEPRECATEDIN_0_9_8(f) +#endif + +/* Generate 80386 code? */ +{- $config{processor} eq "386" ? "#define" : "#undef" -} I386_ONLY + +#undef OPENSSL_UNISTD +#define OPENSSL_UNISTD {- $target{unistd} -} + +{- $config{export_var_as_fn} ? "#define" : "#undef" -} OPENSSL_EXPORT_VAR_AS_FUNCTION + +/* + * The following are cipher-specific, but are part of the public API. + */ +#if !defined(OPENSSL_SYS_UEFI) +{- $config{bn_ll} ? "# define" : "# undef" -} BN_LLONG +/* Only one for the following should be defined */ +{- $config{b64l} ? "# define" : "# undef" -} SIXTY_FOUR_BIT_LONG +{- $config{b64} ? "# define" : "# undef" -} SIXTY_FOUR_BIT +{- $config{b32} ? "# define" : "# undef" -} THIRTY_TWO_BIT +#endif + +#define RC4_INT {- $config{rc4_int} -} + +#ifdef __cplusplus +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/opensslv.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/opensslv.h new file mode 100644 index 000000000..a4aa45bd2 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/opensslv.h @@ -0,0 +1,101 @@ +/* + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_OPENSSLV_H +# define HEADER_OPENSSLV_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*- + * Numeric release version identifier: + * MNNFFPPS: major minor fix patch status + * The status nibble has one of the values 0 for development, 1 to e for betas + * 1 to 14, and f for release. The patch level is exactly that. + * For example: + * 0.9.3-dev 0x00903000 + * 0.9.3-beta1 0x00903001 + * 0.9.3-beta2-dev 0x00903002 + * 0.9.3-beta2 0x00903002 (same as ...beta2-dev) + * 0.9.3 0x0090300f + * 0.9.3a 0x0090301f + * 0.9.4 0x0090400f + * 1.2.3z 0x102031af + * + * For continuity reasons (because 0.9.5 is already out, and is coded + * 0x00905100), between 0.9.5 and 0.9.6 the coding of the patch level + * part is slightly different, by setting the highest bit. This means + * that 0.9.5a looks like this: 0x0090581f. At 0.9.6, we can start + * with 0x0090600S... + * + * (Prior to 0.9.3-dev a different scheme was used: 0.9.2b is 0x0922.) + * (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for + * major minor fix final patch/beta) + */ +# define OPENSSL_VERSION_NUMBER 0x1010102fL +# define OPENSSL_VERSION_TEXT "OpenSSL 1.1.1b 26 Feb 2019" + +/*- + * The macros below are to be used for shared library (.so, .dll, ...) + * versioning. That kind of versioning works a bit differently between + * operating systems. The most usual scheme is to set a major and a minor + * number, and have the runtime loader check that the major number is equal + * to what it was at application link time, while the minor number has to + * be greater or equal to what it was at application link time. With this + * scheme, the version number is usually part of the file name, like this: + * + * libcrypto.so.0.9 + * + * Some unixen also make a softlink with the major version number only: + * + * libcrypto.so.0 + * + * On Tru64 and IRIX 6.x it works a little bit differently. There, the + * shared library version is stored in the file, and is actually a series + * of versions, separated by colons. The rightmost version present in the + * library when linking an application is stored in the application to be + * matched at run time. When the application is run, a check is done to + * see if the library version stored in the application matches any of the + * versions in the version string of the library itself. + * This version string can be constructed in any way, depending on what + * kind of matching is desired. However, to implement the same scheme as + * the one used in the other unixen, all compatible versions, from lowest + * to highest, should be part of the string. Consecutive builds would + * give the following versions strings: + * + * 3.0 + * 3.0:3.1 + * 3.0:3.1:3.2 + * 4.0 + * 4.0:4.1 + * + * Notice how version 4 is completely incompatible with version, and + * therefore give the breach you can see. + * + * There may be other schemes as well that I haven't yet discovered. + * + * So, here's the way it works here: first of all, the library version + * number doesn't need at all to match the overall OpenSSL version. + * However, it's nice and more understandable if it actually does. + * The current library version is stored in the macro SHLIB_VERSION_NUMBER, + * which is just a piece of text in the format "M.m.e" (Major, minor, edit). + * For the sake of Tru64, IRIX, and any other OS that behaves in similar ways, + * we need to keep a history of version numbers, which is done in the + * macro SHLIB_VERSION_HISTORY. The numbers are separated by colons and + * should only keep the versions that are binary compatible with the current. + */ +# define SHLIB_VERSION_HISTORY "" +# define SHLIB_VERSION_NUMBER "1.1" + + +#ifdef __cplusplus +} +#endif +#endif /* HEADER_OPENSSLV_H */ diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/ossl_typ.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ossl_typ.h new file mode 100644 index 000000000..7993ca28f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ossl_typ.h @@ -0,0 +1,196 @@ +/* + * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_OPENSSL_TYPES_H +# define HEADER_OPENSSL_TYPES_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +# include + +# ifdef NO_ASN1_TYPEDEFS +# define ASN1_INTEGER ASN1_STRING +# define ASN1_ENUMERATED ASN1_STRING +# define ASN1_BIT_STRING ASN1_STRING +# define ASN1_OCTET_STRING ASN1_STRING +# define ASN1_PRINTABLESTRING ASN1_STRING +# define ASN1_T61STRING ASN1_STRING +# define ASN1_IA5STRING ASN1_STRING +# define ASN1_UTCTIME ASN1_STRING +# define ASN1_GENERALIZEDTIME ASN1_STRING +# define ASN1_TIME ASN1_STRING +# define ASN1_GENERALSTRING ASN1_STRING +# define ASN1_UNIVERSALSTRING ASN1_STRING +# define ASN1_BMPSTRING ASN1_STRING +# define ASN1_VISIBLESTRING ASN1_STRING +# define ASN1_UTF8STRING ASN1_STRING +# define ASN1_BOOLEAN int +# define ASN1_NULL int +# else +typedef struct asn1_string_st ASN1_INTEGER; +typedef struct asn1_string_st ASN1_ENUMERATED; +typedef struct asn1_string_st ASN1_BIT_STRING; +typedef struct asn1_string_st ASN1_OCTET_STRING; +typedef struct asn1_string_st ASN1_PRINTABLESTRING; +typedef struct asn1_string_st ASN1_T61STRING; +typedef struct asn1_string_st ASN1_IA5STRING; +typedef struct asn1_string_st ASN1_GENERALSTRING; +typedef struct asn1_string_st ASN1_UNIVERSALSTRING; +typedef struct asn1_string_st ASN1_BMPSTRING; +typedef struct asn1_string_st ASN1_UTCTIME; +typedef struct asn1_string_st ASN1_TIME; +typedef struct asn1_string_st ASN1_GENERALIZEDTIME; +typedef struct asn1_string_st ASN1_VISIBLESTRING; +typedef struct asn1_string_st ASN1_UTF8STRING; +typedef struct asn1_string_st ASN1_STRING; +typedef int ASN1_BOOLEAN; +typedef int ASN1_NULL; +# endif + +typedef struct asn1_object_st ASN1_OBJECT; + +typedef struct ASN1_ITEM_st ASN1_ITEM; +typedef struct asn1_pctx_st ASN1_PCTX; +typedef struct asn1_sctx_st ASN1_SCTX; + +# ifdef _WIN32 +# undef X509_NAME +# undef X509_EXTENSIONS +# undef PKCS7_ISSUER_AND_SERIAL +# undef PKCS7_SIGNER_INFO +# undef OCSP_REQUEST +# undef OCSP_RESPONSE +# endif + +# ifdef BIGNUM +# undef BIGNUM +# endif +struct dane_st; +typedef struct bio_st BIO; +typedef struct bignum_st BIGNUM; +typedef struct bignum_ctx BN_CTX; +typedef struct bn_blinding_st BN_BLINDING; +typedef struct bn_mont_ctx_st BN_MONT_CTX; +typedef struct bn_recp_ctx_st BN_RECP_CTX; +typedef struct bn_gencb_st BN_GENCB; + +typedef struct buf_mem_st BUF_MEM; + +typedef struct evp_cipher_st EVP_CIPHER; +typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX; +typedef struct evp_md_st EVP_MD; +typedef struct evp_md_ctx_st EVP_MD_CTX; +typedef struct evp_pkey_st EVP_PKEY; + +typedef struct evp_pkey_asn1_method_st EVP_PKEY_ASN1_METHOD; + +typedef struct evp_pkey_method_st EVP_PKEY_METHOD; +typedef struct evp_pkey_ctx_st EVP_PKEY_CTX; + +typedef struct evp_Encode_Ctx_st EVP_ENCODE_CTX; + +typedef struct hmac_ctx_st HMAC_CTX; + +typedef struct dh_st DH; +typedef struct dh_method DH_METHOD; + +typedef struct dsa_st DSA; +typedef struct dsa_method DSA_METHOD; + +typedef struct rsa_st RSA; +typedef struct rsa_meth_st RSA_METHOD; + +typedef struct ec_key_st EC_KEY; +typedef struct ec_key_method_st EC_KEY_METHOD; + +typedef struct rand_meth_st RAND_METHOD; +typedef struct rand_drbg_st RAND_DRBG; + +typedef struct ssl_dane_st SSL_DANE; +typedef struct x509_st X509; +typedef struct X509_algor_st X509_ALGOR; +typedef struct X509_crl_st X509_CRL; +typedef struct x509_crl_method_st X509_CRL_METHOD; +typedef struct x509_revoked_st X509_REVOKED; +typedef struct X509_name_st X509_NAME; +typedef struct X509_pubkey_st X509_PUBKEY; +typedef struct x509_store_st X509_STORE; +typedef struct x509_store_ctx_st X509_STORE_CTX; + +typedef struct x509_object_st X509_OBJECT; +typedef struct x509_lookup_st X509_LOOKUP; +typedef struct x509_lookup_method_st X509_LOOKUP_METHOD; +typedef struct X509_VERIFY_PARAM_st X509_VERIFY_PARAM; + +typedef struct x509_sig_info_st X509_SIG_INFO; + +typedef struct pkcs8_priv_key_info_st PKCS8_PRIV_KEY_INFO; + +typedef struct v3_ext_ctx X509V3_CTX; +typedef struct conf_st CONF; +typedef struct ossl_init_settings_st OPENSSL_INIT_SETTINGS; + +typedef struct ui_st UI; +typedef struct ui_method_st UI_METHOD; + +typedef struct engine_st ENGINE; +typedef struct ssl_st SSL; +typedef struct ssl_ctx_st SSL_CTX; + +typedef struct comp_ctx_st COMP_CTX; +typedef struct comp_method_st COMP_METHOD; + +typedef struct X509_POLICY_NODE_st X509_POLICY_NODE; +typedef struct X509_POLICY_LEVEL_st X509_POLICY_LEVEL; +typedef struct X509_POLICY_TREE_st X509_POLICY_TREE; +typedef struct X509_POLICY_CACHE_st X509_POLICY_CACHE; + +typedef struct AUTHORITY_KEYID_st AUTHORITY_KEYID; +typedef struct DIST_POINT_st DIST_POINT; +typedef struct ISSUING_DIST_POINT_st ISSUING_DIST_POINT; +typedef struct NAME_CONSTRAINTS_st NAME_CONSTRAINTS; + +typedef struct crypto_ex_data_st CRYPTO_EX_DATA; + +typedef struct ocsp_req_ctx_st OCSP_REQ_CTX; +typedef struct ocsp_response_st OCSP_RESPONSE; +typedef struct ocsp_responder_id_st OCSP_RESPID; + +typedef struct sct_st SCT; +typedef struct sct_ctx_st SCT_CTX; +typedef struct ctlog_st CTLOG; +typedef struct ctlog_store_st CTLOG_STORE; +typedef struct ct_policy_eval_ctx_st CT_POLICY_EVAL_CTX; + +typedef struct ossl_store_info_st OSSL_STORE_INFO; +typedef struct ossl_store_search_st OSSL_STORE_SEARCH; + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \ + defined(INTMAX_MAX) && defined(UINTMAX_MAX) +typedef intmax_t ossl_intmax_t; +typedef uintmax_t ossl_uintmax_t; +#else +/* + * Not long long, because the C-library can only be expected to provide + * strtoll(), strtoull() at the same time as intmax_t and strtoimax(), + * strtoumax(). Since we use these for parsing arguments, we need the + * conversion functions, not just the sizes. + */ +typedef long ossl_intmax_t; +typedef unsigned long ossl_uintmax_t; +#endif + +#ifdef __cplusplus +} +#endif +#endif /* def HEADER_OPENSSL_TYPES_H */ diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/pem.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/pem.h new file mode 100644 index 000000000..2ef5b5d04 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/pem.h @@ -0,0 +1,378 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_PEM_H +# define HEADER_PEM_H + +# include +# include +# include +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# define PEM_BUFSIZE 1024 + +# define PEM_STRING_X509_OLD "X509 CERTIFICATE" +# define PEM_STRING_X509 "CERTIFICATE" +# define PEM_STRING_X509_TRUSTED "TRUSTED CERTIFICATE" +# define PEM_STRING_X509_REQ_OLD "NEW CERTIFICATE REQUEST" +# define PEM_STRING_X509_REQ "CERTIFICATE REQUEST" +# define PEM_STRING_X509_CRL "X509 CRL" +# define PEM_STRING_EVP_PKEY "ANY PRIVATE KEY" +# define PEM_STRING_PUBLIC "PUBLIC KEY" +# define PEM_STRING_RSA "RSA PRIVATE KEY" +# define PEM_STRING_RSA_PUBLIC "RSA PUBLIC KEY" +# define PEM_STRING_DSA "DSA PRIVATE KEY" +# define PEM_STRING_DSA_PUBLIC "DSA PUBLIC KEY" +# define PEM_STRING_PKCS7 "PKCS7" +# define PEM_STRING_PKCS7_SIGNED "PKCS #7 SIGNED DATA" +# define PEM_STRING_PKCS8 "ENCRYPTED PRIVATE KEY" +# define PEM_STRING_PKCS8INF "PRIVATE KEY" +# define PEM_STRING_DHPARAMS "DH PARAMETERS" +# define PEM_STRING_DHXPARAMS "X9.42 DH PARAMETERS" +# define PEM_STRING_SSL_SESSION "SSL SESSION PARAMETERS" +# define PEM_STRING_DSAPARAMS "DSA PARAMETERS" +# define PEM_STRING_ECDSA_PUBLIC "ECDSA PUBLIC KEY" +# define PEM_STRING_ECPARAMETERS "EC PARAMETERS" +# define PEM_STRING_ECPRIVATEKEY "EC PRIVATE KEY" +# define PEM_STRING_PARAMETERS "PARAMETERS" +# define PEM_STRING_CMS "CMS" + +# define PEM_TYPE_ENCRYPTED 10 +# define PEM_TYPE_MIC_ONLY 20 +# define PEM_TYPE_MIC_CLEAR 30 +# define PEM_TYPE_CLEAR 40 + +/* + * These macros make the PEM_read/PEM_write functions easier to maintain and + * write. Now they are all implemented with either: IMPLEMENT_PEM_rw(...) or + * IMPLEMENT_PEM_rw_cb(...) + */ + +# ifdef OPENSSL_NO_STDIO + +# define IMPLEMENT_PEM_read_fp(name, type, str, asn1) /**/ +# define IMPLEMENT_PEM_write_fp(name, type, str, asn1) /**/ +# define IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) /**/ +# define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) /**/ +# define IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) /**/ +# else + +# define IMPLEMENT_PEM_read_fp(name, type, str, asn1) \ +type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u)\ +{ \ +return PEM_ASN1_read((d2i_of_void *)d2i_##asn1, str,fp,(void **)x,cb,u); \ +} + +# define IMPLEMENT_PEM_write_fp(name, type, str, asn1) \ +int PEM_write_##name(FILE *fp, type *x) \ +{ \ +return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,x,NULL,NULL,0,NULL,NULL); \ +} + +# define IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) \ +int PEM_write_##name(FILE *fp, const type *x) \ +{ \ +return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,(void *)x,NULL,NULL,0,NULL,NULL); \ +} + +# define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) \ +int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, \ + void *u) \ + { \ + return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,x,enc,kstr,klen,cb,u); \ + } + +# define IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) \ +int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, \ + void *u) \ + { \ + return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,x,enc,kstr,klen,cb,u); \ + } + +# endif + +# define IMPLEMENT_PEM_read_bio(name, type, str, asn1) \ +type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb, void *u)\ +{ \ +return PEM_ASN1_read_bio((d2i_of_void *)d2i_##asn1, str,bp,(void **)x,cb,u); \ +} + +# define IMPLEMENT_PEM_write_bio(name, type, str, asn1) \ +int PEM_write_bio_##name(BIO *bp, type *x) \ +{ \ +return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,x,NULL,NULL,0,NULL,NULL); \ +} + +# define IMPLEMENT_PEM_write_bio_const(name, type, str, asn1) \ +int PEM_write_bio_##name(BIO *bp, const type *x) \ +{ \ +return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,(void *)x,NULL,NULL,0,NULL,NULL); \ +} + +# define IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1) \ +int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, void *u) \ + { \ + return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,x,enc,kstr,klen,cb,u); \ + } + +# define IMPLEMENT_PEM_write_cb_bio_const(name, type, str, asn1) \ +int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, void *u) \ + { \ + return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,(void *)x,enc,kstr,klen,cb,u); \ + } + +# define IMPLEMENT_PEM_write(name, type, str, asn1) \ + IMPLEMENT_PEM_write_bio(name, type, str, asn1) \ + IMPLEMENT_PEM_write_fp(name, type, str, asn1) + +# define IMPLEMENT_PEM_write_const(name, type, str, asn1) \ + IMPLEMENT_PEM_write_bio_const(name, type, str, asn1) \ + IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) + +# define IMPLEMENT_PEM_write_cb(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) + +# define IMPLEMENT_PEM_write_cb_const(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb_bio_const(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) + +# define IMPLEMENT_PEM_read(name, type, str, asn1) \ + IMPLEMENT_PEM_read_bio(name, type, str, asn1) \ + IMPLEMENT_PEM_read_fp(name, type, str, asn1) + +# define IMPLEMENT_PEM_rw(name, type, str, asn1) \ + IMPLEMENT_PEM_read(name, type, str, asn1) \ + IMPLEMENT_PEM_write(name, type, str, asn1) + +# define IMPLEMENT_PEM_rw_const(name, type, str, asn1) \ + IMPLEMENT_PEM_read(name, type, str, asn1) \ + IMPLEMENT_PEM_write_const(name, type, str, asn1) + +# define IMPLEMENT_PEM_rw_cb(name, type, str, asn1) \ + IMPLEMENT_PEM_read(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb(name, type, str, asn1) + +/* These are the same except they are for the declarations */ + +# if defined(OPENSSL_NO_STDIO) + +# define DECLARE_PEM_read_fp(name, type) /**/ +# define DECLARE_PEM_write_fp(name, type) /**/ +# define DECLARE_PEM_write_fp_const(name, type) /**/ +# define DECLARE_PEM_write_cb_fp(name, type) /**/ +# else + +# define DECLARE_PEM_read_fp(name, type) \ + type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u); + +# define DECLARE_PEM_write_fp(name, type) \ + int PEM_write_##name(FILE *fp, type *x); + +# define DECLARE_PEM_write_fp_const(name, type) \ + int PEM_write_##name(FILE *fp, const type *x); + +# define DECLARE_PEM_write_cb_fp(name, type) \ + int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, void *u); + +# endif + +# define DECLARE_PEM_read_bio(name, type) \ + type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb, void *u); + +# define DECLARE_PEM_write_bio(name, type) \ + int PEM_write_bio_##name(BIO *bp, type *x); + +# define DECLARE_PEM_write_bio_const(name, type) \ + int PEM_write_bio_##name(BIO *bp, const type *x); + +# define DECLARE_PEM_write_cb_bio(name, type) \ + int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, void *u); + +# define DECLARE_PEM_write(name, type) \ + DECLARE_PEM_write_bio(name, type) \ + DECLARE_PEM_write_fp(name, type) +# define DECLARE_PEM_write_const(name, type) \ + DECLARE_PEM_write_bio_const(name, type) \ + DECLARE_PEM_write_fp_const(name, type) +# define DECLARE_PEM_write_cb(name, type) \ + DECLARE_PEM_write_cb_bio(name, type) \ + DECLARE_PEM_write_cb_fp(name, type) +# define DECLARE_PEM_read(name, type) \ + DECLARE_PEM_read_bio(name, type) \ + DECLARE_PEM_read_fp(name, type) +# define DECLARE_PEM_rw(name, type) \ + DECLARE_PEM_read(name, type) \ + DECLARE_PEM_write(name, type) +# define DECLARE_PEM_rw_const(name, type) \ + DECLARE_PEM_read(name, type) \ + DECLARE_PEM_write_const(name, type) +# define DECLARE_PEM_rw_cb(name, type) \ + DECLARE_PEM_read(name, type) \ + DECLARE_PEM_write_cb(name, type) +typedef int pem_password_cb (char *buf, int size, int rwflag, void *userdata); + +int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher); +int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *len, + pem_password_cb *callback, void *u); + +int PEM_read_bio(BIO *bp, char **name, char **header, + unsigned char **data, long *len); +# define PEM_FLAG_SECURE 0x1 +# define PEM_FLAG_EAY_COMPATIBLE 0x2 +# define PEM_FLAG_ONLY_B64 0x4 +int PEM_read_bio_ex(BIO *bp, char **name, char **header, + unsigned char **data, long *len, unsigned int flags); +int PEM_bytes_read_bio_secmem(unsigned char **pdata, long *plen, char **pnm, + const char *name, BIO *bp, pem_password_cb *cb, + void *u); +int PEM_write_bio(BIO *bp, const char *name, const char *hdr, + const unsigned char *data, long len); +int PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm, + const char *name, BIO *bp, pem_password_cb *cb, + void *u); +void *PEM_ASN1_read_bio(d2i_of_void *d2i, const char *name, BIO *bp, void **x, + pem_password_cb *cb, void *u); +int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, void *x, + const EVP_CIPHER *enc, unsigned char *kstr, int klen, + pem_password_cb *cb, void *u); + +STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk, + pem_password_cb *cb, void *u); +int PEM_X509_INFO_write_bio(BIO *bp, X509_INFO *xi, EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cd, void *u); + +#ifndef OPENSSL_NO_STDIO +int PEM_read(FILE *fp, char **name, char **header, + unsigned char **data, long *len); +int PEM_write(FILE *fp, const char *name, const char *hdr, + const unsigned char *data, long len); +void *PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, void **x, + pem_password_cb *cb, void *u); +int PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp, + void *x, const EVP_CIPHER *enc, unsigned char *kstr, + int klen, pem_password_cb *callback, void *u); +STACK_OF(X509_INFO) *PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk, + pem_password_cb *cb, void *u); +#endif + +int PEM_SignInit(EVP_MD_CTX *ctx, EVP_MD *type); +int PEM_SignUpdate(EVP_MD_CTX *ctx, unsigned char *d, unsigned int cnt); +int PEM_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, + unsigned int *siglen, EVP_PKEY *pkey); + +/* The default pem_password_cb that's used internally */ +int PEM_def_callback(char *buf, int num, int rwflag, void *userdata); +void PEM_proc_type(char *buf, int type); +void PEM_dek_info(char *buf, const char *type, int len, char *str); + +# include + +DECLARE_PEM_rw(X509, X509) +DECLARE_PEM_rw(X509_AUX, X509) +DECLARE_PEM_rw(X509_REQ, X509_REQ) +DECLARE_PEM_write(X509_REQ_NEW, X509_REQ) +DECLARE_PEM_rw(X509_CRL, X509_CRL) +DECLARE_PEM_rw(PKCS7, PKCS7) +DECLARE_PEM_rw(NETSCAPE_CERT_SEQUENCE, NETSCAPE_CERT_SEQUENCE) +DECLARE_PEM_rw(PKCS8, X509_SIG) +DECLARE_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO) +# ifndef OPENSSL_NO_RSA +DECLARE_PEM_rw_cb(RSAPrivateKey, RSA) +DECLARE_PEM_rw_const(RSAPublicKey, RSA) +DECLARE_PEM_rw(RSA_PUBKEY, RSA) +# endif +# ifndef OPENSSL_NO_DSA +DECLARE_PEM_rw_cb(DSAPrivateKey, DSA) +DECLARE_PEM_rw(DSA_PUBKEY, DSA) +DECLARE_PEM_rw_const(DSAparams, DSA) +# endif +# ifndef OPENSSL_NO_EC +DECLARE_PEM_rw_const(ECPKParameters, EC_GROUP) +DECLARE_PEM_rw_cb(ECPrivateKey, EC_KEY) +DECLARE_PEM_rw(EC_PUBKEY, EC_KEY) +# endif +# ifndef OPENSSL_NO_DH +DECLARE_PEM_rw_const(DHparams, DH) +DECLARE_PEM_write_const(DHxparams, DH) +# endif +DECLARE_PEM_rw_cb(PrivateKey, EVP_PKEY) +DECLARE_PEM_rw(PUBKEY, EVP_PKEY) + +int PEM_write_bio_PrivateKey_traditional(BIO *bp, EVP_PKEY *x, + const EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cb, void *u); + +int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u); +int PEM_write_bio_PKCS8PrivateKey(BIO *, EVP_PKEY *, const EVP_CIPHER *, + char *, int, pem_password_cb *, void *); +int i2d_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc, + char *kstr, int klen, + pem_password_cb *cb, void *u); +int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u); +EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, + void *u); + +# ifndef OPENSSL_NO_STDIO +int i2d_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, + char *kstr, int klen, + pem_password_cb *cb, void *u); +int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u); +int PEM_write_PKCS8PrivateKey_nid(FILE *fp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u); + +EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, + void *u); + +int PEM_write_PKCS8PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, + char *kstr, int klen, pem_password_cb *cd, + void *u); +# endif +EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x); +int PEM_write_bio_Parameters(BIO *bp, EVP_PKEY *x); + +# ifndef OPENSSL_NO_DSA +EVP_PKEY *b2i_PrivateKey(const unsigned char **in, long length); +EVP_PKEY *b2i_PublicKey(const unsigned char **in, long length); +EVP_PKEY *b2i_PrivateKey_bio(BIO *in); +EVP_PKEY *b2i_PublicKey_bio(BIO *in); +int i2b_PrivateKey_bio(BIO *out, EVP_PKEY *pk); +int i2b_PublicKey_bio(BIO *out, EVP_PKEY *pk); +# ifndef OPENSSL_NO_RC4 +EVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u); +int i2b_PVK_bio(BIO *out, EVP_PKEY *pk, int enclevel, + pem_password_cb *cb, void *u); +# endif +# endif + +# ifdef __cplusplus +} +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/pem2.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/pem2.h new file mode 100644 index 000000000..038fe790a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/pem2.h @@ -0,0 +1,13 @@ +/* + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_PEM2_H +# define HEADER_PEM2_H +# include +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/pemerr.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/pemerr.h new file mode 100644 index 000000000..cd61b823d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/pemerr.h @@ -0,0 +1,99 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_PEMERR_H +# define HEADER_PEMERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_PEM_strings(void); + +/* + * PEM function codes. + */ +# define PEM_F_B2I_DSS 127 +# define PEM_F_B2I_PVK_BIO 128 +# define PEM_F_B2I_RSA 129 +# define PEM_F_CHECK_BITLEN_DSA 130 +# define PEM_F_CHECK_BITLEN_RSA 131 +# define PEM_F_D2I_PKCS8PRIVATEKEY_BIO 120 +# define PEM_F_D2I_PKCS8PRIVATEKEY_FP 121 +# define PEM_F_DO_B2I 132 +# define PEM_F_DO_B2I_BIO 133 +# define PEM_F_DO_BLOB_HEADER 134 +# define PEM_F_DO_I2B 146 +# define PEM_F_DO_PK8PKEY 126 +# define PEM_F_DO_PK8PKEY_FP 125 +# define PEM_F_DO_PVK_BODY 135 +# define PEM_F_DO_PVK_HEADER 136 +# define PEM_F_GET_HEADER_AND_DATA 143 +# define PEM_F_GET_NAME 144 +# define PEM_F_I2B_PVK 137 +# define PEM_F_I2B_PVK_BIO 138 +# define PEM_F_LOAD_IV 101 +# define PEM_F_PEM_ASN1_READ 102 +# define PEM_F_PEM_ASN1_READ_BIO 103 +# define PEM_F_PEM_ASN1_WRITE 104 +# define PEM_F_PEM_ASN1_WRITE_BIO 105 +# define PEM_F_PEM_DEF_CALLBACK 100 +# define PEM_F_PEM_DO_HEADER 106 +# define PEM_F_PEM_GET_EVP_CIPHER_INFO 107 +# define PEM_F_PEM_READ 108 +# define PEM_F_PEM_READ_BIO 109 +# define PEM_F_PEM_READ_BIO_DHPARAMS 141 +# define PEM_F_PEM_READ_BIO_EX 145 +# define PEM_F_PEM_READ_BIO_PARAMETERS 140 +# define PEM_F_PEM_READ_BIO_PRIVATEKEY 123 +# define PEM_F_PEM_READ_DHPARAMS 142 +# define PEM_F_PEM_READ_PRIVATEKEY 124 +# define PEM_F_PEM_SIGNFINAL 112 +# define PEM_F_PEM_WRITE 113 +# define PEM_F_PEM_WRITE_BIO 114 +# define PEM_F_PEM_WRITE_PRIVATEKEY 139 +# define PEM_F_PEM_X509_INFO_READ 115 +# define PEM_F_PEM_X509_INFO_READ_BIO 116 +# define PEM_F_PEM_X509_INFO_WRITE_BIO 117 + +/* + * PEM reason codes. + */ +# define PEM_R_BAD_BASE64_DECODE 100 +# define PEM_R_BAD_DECRYPT 101 +# define PEM_R_BAD_END_LINE 102 +# define PEM_R_BAD_IV_CHARS 103 +# define PEM_R_BAD_MAGIC_NUMBER 116 +# define PEM_R_BAD_PASSWORD_READ 104 +# define PEM_R_BAD_VERSION_NUMBER 117 +# define PEM_R_BIO_WRITE_FAILURE 118 +# define PEM_R_CIPHER_IS_NULL 127 +# define PEM_R_ERROR_CONVERTING_PRIVATE_KEY 115 +# define PEM_R_EXPECTING_PRIVATE_KEY_BLOB 119 +# define PEM_R_EXPECTING_PUBLIC_KEY_BLOB 120 +# define PEM_R_HEADER_TOO_LONG 128 +# define PEM_R_INCONSISTENT_HEADER 121 +# define PEM_R_KEYBLOB_HEADER_PARSE_ERROR 122 +# define PEM_R_KEYBLOB_TOO_SHORT 123 +# define PEM_R_MISSING_DEK_IV 129 +# define PEM_R_NOT_DEK_INFO 105 +# define PEM_R_NOT_ENCRYPTED 106 +# define PEM_R_NOT_PROC_TYPE 107 +# define PEM_R_NO_START_LINE 108 +# define PEM_R_PROBLEMS_GETTING_PASSWORD 109 +# define PEM_R_PVK_DATA_TOO_SHORT 124 +# define PEM_R_PVK_TOO_SHORT 125 +# define PEM_R_READ_KEY 111 +# define PEM_R_SHORT_HEADER 112 +# define PEM_R_UNEXPECTED_DEK_IV 130 +# define PEM_R_UNSUPPORTED_CIPHER 113 +# define PEM_R_UNSUPPORTED_ENCRYPTION 114 +# define PEM_R_UNSUPPORTED_KEY_COMPONENTS 126 + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/pkcs12.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/pkcs12.h new file mode 100644 index 000000000..3f43dad6d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/pkcs12.h @@ -0,0 +1,223 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_PKCS12_H +# define HEADER_PKCS12_H + +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# define PKCS12_KEY_ID 1 +# define PKCS12_IV_ID 2 +# define PKCS12_MAC_ID 3 + +/* Default iteration count */ +# ifndef PKCS12_DEFAULT_ITER +# define PKCS12_DEFAULT_ITER PKCS5_DEFAULT_ITER +# endif + +# define PKCS12_MAC_KEY_LENGTH 20 + +# define PKCS12_SALT_LEN 8 + +/* It's not clear if these are actually needed... */ +# define PKCS12_key_gen PKCS12_key_gen_utf8 +# define PKCS12_add_friendlyname PKCS12_add_friendlyname_utf8 + +/* MS key usage constants */ + +# define KEY_EX 0x10 +# define KEY_SIG 0x80 + +typedef struct PKCS12_MAC_DATA_st PKCS12_MAC_DATA; + +typedef struct PKCS12_st PKCS12; + +typedef struct PKCS12_SAFEBAG_st PKCS12_SAFEBAG; + +DEFINE_STACK_OF(PKCS12_SAFEBAG) + +typedef struct pkcs12_bag_st PKCS12_BAGS; + +# define PKCS12_ERROR 0 +# define PKCS12_OK 1 + +/* Compatibility macros */ + +#if OPENSSL_API_COMPAT < 0x10100000L + +# define M_PKCS12_bag_type PKCS12_bag_type +# define M_PKCS12_cert_bag_type PKCS12_cert_bag_type +# define M_PKCS12_crl_bag_type PKCS12_cert_bag_type + +# define PKCS12_certbag2x509 PKCS12_SAFEBAG_get1_cert +# define PKCS12_certbag2scrl PKCS12_SAFEBAG_get1_crl +# define PKCS12_bag_type PKCS12_SAFEBAG_get_nid +# define PKCS12_cert_bag_type PKCS12_SAFEBAG_get_bag_nid +# define PKCS12_x5092certbag PKCS12_SAFEBAG_create_cert +# define PKCS12_x509crl2certbag PKCS12_SAFEBAG_create_crl +# define PKCS12_MAKE_KEYBAG PKCS12_SAFEBAG_create0_p8inf +# define PKCS12_MAKE_SHKEYBAG PKCS12_SAFEBAG_create_pkcs8_encrypt + +#endif + +DEPRECATEDIN_1_1_0(ASN1_TYPE *PKCS12_get_attr(const PKCS12_SAFEBAG *bag, int attr_nid)) + +ASN1_TYPE *PKCS8_get_attr(PKCS8_PRIV_KEY_INFO *p8, int attr_nid); +int PKCS12_mac_present(const PKCS12 *p12); +void PKCS12_get0_mac(const ASN1_OCTET_STRING **pmac, + const X509_ALGOR **pmacalg, + const ASN1_OCTET_STRING **psalt, + const ASN1_INTEGER **piter, + const PKCS12 *p12); + +const ASN1_TYPE *PKCS12_SAFEBAG_get0_attr(const PKCS12_SAFEBAG *bag, + int attr_nid); +const ASN1_OBJECT *PKCS12_SAFEBAG_get0_type(const PKCS12_SAFEBAG *bag); +int PKCS12_SAFEBAG_get_nid(const PKCS12_SAFEBAG *bag); +int PKCS12_SAFEBAG_get_bag_nid(const PKCS12_SAFEBAG *bag); + +X509 *PKCS12_SAFEBAG_get1_cert(const PKCS12_SAFEBAG *bag); +X509_CRL *PKCS12_SAFEBAG_get1_crl(const PKCS12_SAFEBAG *bag); +const STACK_OF(PKCS12_SAFEBAG) * +PKCS12_SAFEBAG_get0_safes(const PKCS12_SAFEBAG *bag); +const PKCS8_PRIV_KEY_INFO *PKCS12_SAFEBAG_get0_p8inf(const PKCS12_SAFEBAG *bag); +const X509_SIG *PKCS12_SAFEBAG_get0_pkcs8(const PKCS12_SAFEBAG *bag); + +PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_cert(X509 *x509); +PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_crl(X509_CRL *crl); +PKCS12_SAFEBAG *PKCS12_SAFEBAG_create0_p8inf(PKCS8_PRIV_KEY_INFO *p8); +PKCS12_SAFEBAG *PKCS12_SAFEBAG_create0_pkcs8(X509_SIG *p8); +PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_pkcs8_encrypt(int pbe_nid, + const char *pass, + int passlen, + unsigned char *salt, + int saltlen, int iter, + PKCS8_PRIV_KEY_INFO *p8inf); + +PKCS12_SAFEBAG *PKCS12_item_pack_safebag(void *obj, const ASN1_ITEM *it, + int nid1, int nid2); +PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(const X509_SIG *p8, const char *pass, + int passlen); +PKCS8_PRIV_KEY_INFO *PKCS12_decrypt_skey(const PKCS12_SAFEBAG *bag, + const char *pass, int passlen); +X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher, + const char *pass, int passlen, unsigned char *salt, + int saltlen, int iter, PKCS8_PRIV_KEY_INFO *p8); +X509_SIG *PKCS8_set0_pbe(const char *pass, int passlen, + PKCS8_PRIV_KEY_INFO *p8inf, X509_ALGOR *pbe); +PKCS7 *PKCS12_pack_p7data(STACK_OF(PKCS12_SAFEBAG) *sk); +STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7data(PKCS7 *p7); +PKCS7 *PKCS12_pack_p7encdata(int pbe_nid, const char *pass, int passlen, + unsigned char *salt, int saltlen, int iter, + STACK_OF(PKCS12_SAFEBAG) *bags); +STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7encdata(PKCS7 *p7, const char *pass, + int passlen); + +int PKCS12_pack_authsafes(PKCS12 *p12, STACK_OF(PKCS7) *safes); +STACK_OF(PKCS7) *PKCS12_unpack_authsafes(const PKCS12 *p12); + +int PKCS12_add_localkeyid(PKCS12_SAFEBAG *bag, unsigned char *name, + int namelen); +int PKCS12_add_friendlyname_asc(PKCS12_SAFEBAG *bag, const char *name, + int namelen); +int PKCS12_add_friendlyname_utf8(PKCS12_SAFEBAG *bag, const char *name, + int namelen); +int PKCS12_add_CSPName_asc(PKCS12_SAFEBAG *bag, const char *name, + int namelen); +int PKCS12_add_friendlyname_uni(PKCS12_SAFEBAG *bag, + const unsigned char *name, int namelen); +int PKCS8_add_keyusage(PKCS8_PRIV_KEY_INFO *p8, int usage); +ASN1_TYPE *PKCS12_get_attr_gen(const STACK_OF(X509_ATTRIBUTE) *attrs, + int attr_nid); +char *PKCS12_get_friendlyname(PKCS12_SAFEBAG *bag); +const STACK_OF(X509_ATTRIBUTE) * +PKCS12_SAFEBAG_get0_attrs(const PKCS12_SAFEBAG *bag); +unsigned char *PKCS12_pbe_crypt(const X509_ALGOR *algor, + const char *pass, int passlen, + const unsigned char *in, int inlen, + unsigned char **data, int *datalen, + int en_de); +void *PKCS12_item_decrypt_d2i(const X509_ALGOR *algor, const ASN1_ITEM *it, + const char *pass, int passlen, + const ASN1_OCTET_STRING *oct, int zbuf); +ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt(X509_ALGOR *algor, + const ASN1_ITEM *it, + const char *pass, int passlen, + void *obj, int zbuf); +PKCS12 *PKCS12_init(int mode); +int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt, + int saltlen, int id, int iter, int n, + unsigned char *out, const EVP_MD *md_type); +int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt, + int saltlen, int id, int iter, int n, + unsigned char *out, const EVP_MD *md_type); +int PKCS12_key_gen_utf8(const char *pass, int passlen, unsigned char *salt, + int saltlen, int id, int iter, int n, + unsigned char *out, const EVP_MD *md_type); +int PKCS12_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, + ASN1_TYPE *param, const EVP_CIPHER *cipher, + const EVP_MD *md_type, int en_de); +int PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen, + unsigned char *mac, unsigned int *maclen); +int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen); +int PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen, + unsigned char *salt, int saltlen, int iter, + const EVP_MD *md_type); +int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt, + int saltlen, const EVP_MD *md_type); +unsigned char *OPENSSL_asc2uni(const char *asc, int asclen, + unsigned char **uni, int *unilen); +char *OPENSSL_uni2asc(const unsigned char *uni, int unilen); +unsigned char *OPENSSL_utf82uni(const char *asc, int asclen, + unsigned char **uni, int *unilen); +char *OPENSSL_uni2utf8(const unsigned char *uni, int unilen); + +DECLARE_ASN1_FUNCTIONS(PKCS12) +DECLARE_ASN1_FUNCTIONS(PKCS12_MAC_DATA) +DECLARE_ASN1_FUNCTIONS(PKCS12_SAFEBAG) +DECLARE_ASN1_FUNCTIONS(PKCS12_BAGS) + +DECLARE_ASN1_ITEM(PKCS12_SAFEBAGS) +DECLARE_ASN1_ITEM(PKCS12_AUTHSAFES) + +void PKCS12_PBE_add(void); +int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, + STACK_OF(X509) **ca); +PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, + X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert, + int iter, int mac_iter, int keytype); + +PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert); +PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags, + EVP_PKEY *key, int key_usage, int iter, + int key_nid, const char *pass); +int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags, + int safe_nid, int iter, const char *pass); +PKCS12 *PKCS12_add_safes(STACK_OF(PKCS7) *safes, int p7_nid); + +int i2d_PKCS12_bio(BIO *bp, PKCS12 *p12); +# ifndef OPENSSL_NO_STDIO +int i2d_PKCS12_fp(FILE *fp, PKCS12 *p12); +# endif +PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **p12); +# ifndef OPENSSL_NO_STDIO +PKCS12 *d2i_PKCS12_fp(FILE *fp, PKCS12 **p12); +# endif +int PKCS12_newpass(PKCS12 *p12, const char *oldpass, const char *newpass); + +# ifdef __cplusplus +} +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/pkcs12err.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/pkcs12err.h new file mode 100644 index 000000000..c7184ffe7 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/pkcs12err.h @@ -0,0 +1,77 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_PKCS12ERR_H +# define HEADER_PKCS12ERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_PKCS12_strings(void); + +/* + * PKCS12 function codes. + */ +# define PKCS12_F_OPENSSL_ASC2UNI 121 +# define PKCS12_F_OPENSSL_UNI2ASC 124 +# define PKCS12_F_OPENSSL_UNI2UTF8 127 +# define PKCS12_F_OPENSSL_UTF82UNI 129 +# define PKCS12_F_PKCS12_CREATE 105 +# define PKCS12_F_PKCS12_GEN_MAC 107 +# define PKCS12_F_PKCS12_INIT 109 +# define PKCS12_F_PKCS12_ITEM_DECRYPT_D2I 106 +# define PKCS12_F_PKCS12_ITEM_I2D_ENCRYPT 108 +# define PKCS12_F_PKCS12_ITEM_PACK_SAFEBAG 117 +# define PKCS12_F_PKCS12_KEY_GEN_ASC 110 +# define PKCS12_F_PKCS12_KEY_GEN_UNI 111 +# define PKCS12_F_PKCS12_KEY_GEN_UTF8 116 +# define PKCS12_F_PKCS12_NEWPASS 128 +# define PKCS12_F_PKCS12_PACK_P7DATA 114 +# define PKCS12_F_PKCS12_PACK_P7ENCDATA 115 +# define PKCS12_F_PKCS12_PARSE 118 +# define PKCS12_F_PKCS12_PBE_CRYPT 119 +# define PKCS12_F_PKCS12_PBE_KEYIVGEN 120 +# define PKCS12_F_PKCS12_SAFEBAG_CREATE0_P8INF 112 +# define PKCS12_F_PKCS12_SAFEBAG_CREATE0_PKCS8 113 +# define PKCS12_F_PKCS12_SAFEBAG_CREATE_PKCS8_ENCRYPT 133 +# define PKCS12_F_PKCS12_SETUP_MAC 122 +# define PKCS12_F_PKCS12_SET_MAC 123 +# define PKCS12_F_PKCS12_UNPACK_AUTHSAFES 130 +# define PKCS12_F_PKCS12_UNPACK_P7DATA 131 +# define PKCS12_F_PKCS12_VERIFY_MAC 126 +# define PKCS12_F_PKCS8_ENCRYPT 125 +# define PKCS12_F_PKCS8_SET0_PBE 132 + +/* + * PKCS12 reason codes. + */ +# define PKCS12_R_CANT_PACK_STRUCTURE 100 +# define PKCS12_R_CONTENT_TYPE_NOT_DATA 121 +# define PKCS12_R_DECODE_ERROR 101 +# define PKCS12_R_ENCODE_ERROR 102 +# define PKCS12_R_ENCRYPT_ERROR 103 +# define PKCS12_R_ERROR_SETTING_ENCRYPTED_DATA_TYPE 120 +# define PKCS12_R_INVALID_NULL_ARGUMENT 104 +# define PKCS12_R_INVALID_NULL_PKCS12_POINTER 105 +# define PKCS12_R_IV_GEN_ERROR 106 +# define PKCS12_R_KEY_GEN_ERROR 107 +# define PKCS12_R_MAC_ABSENT 108 +# define PKCS12_R_MAC_GENERATION_ERROR 109 +# define PKCS12_R_MAC_SETUP_ERROR 110 +# define PKCS12_R_MAC_STRING_SET_ERROR 111 +# define PKCS12_R_MAC_VERIFY_FAILURE 113 +# define PKCS12_R_PARSE_ERROR 114 +# define PKCS12_R_PKCS12_ALGOR_CIPHERINIT_ERROR 115 +# define PKCS12_R_PKCS12_CIPHERFINAL_ERROR 116 +# define PKCS12_R_PKCS12_PBE_CRYPT_ERROR 117 +# define PKCS12_R_UNKNOWN_DIGEST_ALGORITHM 118 +# define PKCS12_R_UNSUPPORTED_PKCS12_MODE 119 + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/pkcs7.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/pkcs7.h new file mode 100644 index 000000000..9b66e002d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/pkcs7.h @@ -0,0 +1,319 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_PKCS7_H +# define HEADER_PKCS7_H + +# include +# include +# include + +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/*- +Encryption_ID DES-CBC +Digest_ID MD5 +Digest_Encryption_ID rsaEncryption +Key_Encryption_ID rsaEncryption +*/ + +typedef struct pkcs7_issuer_and_serial_st { + X509_NAME *issuer; + ASN1_INTEGER *serial; +} PKCS7_ISSUER_AND_SERIAL; + +typedef struct pkcs7_signer_info_st { + ASN1_INTEGER *version; /* version 1 */ + PKCS7_ISSUER_AND_SERIAL *issuer_and_serial; + X509_ALGOR *digest_alg; + STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */ + X509_ALGOR *digest_enc_alg; + ASN1_OCTET_STRING *enc_digest; + STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */ + /* The private key to sign with */ + EVP_PKEY *pkey; +} PKCS7_SIGNER_INFO; + +DEFINE_STACK_OF(PKCS7_SIGNER_INFO) + +typedef struct pkcs7_recip_info_st { + ASN1_INTEGER *version; /* version 0 */ + PKCS7_ISSUER_AND_SERIAL *issuer_and_serial; + X509_ALGOR *key_enc_algor; + ASN1_OCTET_STRING *enc_key; + X509 *cert; /* get the pub-key from this */ +} PKCS7_RECIP_INFO; + +DEFINE_STACK_OF(PKCS7_RECIP_INFO) + +typedef struct pkcs7_signed_st { + ASN1_INTEGER *version; /* version 1 */ + STACK_OF(X509_ALGOR) *md_algs; /* md used */ + STACK_OF(X509) *cert; /* [ 0 ] */ + STACK_OF(X509_CRL) *crl; /* [ 1 ] */ + STACK_OF(PKCS7_SIGNER_INFO) *signer_info; + struct pkcs7_st *contents; +} PKCS7_SIGNED; +/* + * The above structure is very very similar to PKCS7_SIGN_ENVELOPE. How about + * merging the two + */ + +typedef struct pkcs7_enc_content_st { + ASN1_OBJECT *content_type; + X509_ALGOR *algorithm; + ASN1_OCTET_STRING *enc_data; /* [ 0 ] */ + const EVP_CIPHER *cipher; +} PKCS7_ENC_CONTENT; + +typedef struct pkcs7_enveloped_st { + ASN1_INTEGER *version; /* version 0 */ + STACK_OF(PKCS7_RECIP_INFO) *recipientinfo; + PKCS7_ENC_CONTENT *enc_data; +} PKCS7_ENVELOPE; + +typedef struct pkcs7_signedandenveloped_st { + ASN1_INTEGER *version; /* version 1 */ + STACK_OF(X509_ALGOR) *md_algs; /* md used */ + STACK_OF(X509) *cert; /* [ 0 ] */ + STACK_OF(X509_CRL) *crl; /* [ 1 ] */ + STACK_OF(PKCS7_SIGNER_INFO) *signer_info; + PKCS7_ENC_CONTENT *enc_data; + STACK_OF(PKCS7_RECIP_INFO) *recipientinfo; +} PKCS7_SIGN_ENVELOPE; + +typedef struct pkcs7_digest_st { + ASN1_INTEGER *version; /* version 0 */ + X509_ALGOR *md; /* md used */ + struct pkcs7_st *contents; + ASN1_OCTET_STRING *digest; +} PKCS7_DIGEST; + +typedef struct pkcs7_encrypted_st { + ASN1_INTEGER *version; /* version 0 */ + PKCS7_ENC_CONTENT *enc_data; +} PKCS7_ENCRYPT; + +typedef struct pkcs7_st { + /* + * The following is non NULL if it contains ASN1 encoding of this + * structure + */ + unsigned char *asn1; + long length; +# define PKCS7_S_HEADER 0 +# define PKCS7_S_BODY 1 +# define PKCS7_S_TAIL 2 + int state; /* used during processing */ + int detached; + ASN1_OBJECT *type; + /* content as defined by the type */ + /* + * all encryption/message digests are applied to the 'contents', leaving + * out the 'type' field. + */ + union { + char *ptr; + /* NID_pkcs7_data */ + ASN1_OCTET_STRING *data; + /* NID_pkcs7_signed */ + PKCS7_SIGNED *sign; + /* NID_pkcs7_enveloped */ + PKCS7_ENVELOPE *enveloped; + /* NID_pkcs7_signedAndEnveloped */ + PKCS7_SIGN_ENVELOPE *signed_and_enveloped; + /* NID_pkcs7_digest */ + PKCS7_DIGEST *digest; + /* NID_pkcs7_encrypted */ + PKCS7_ENCRYPT *encrypted; + /* Anything else */ + ASN1_TYPE *other; + } d; +} PKCS7; + +DEFINE_STACK_OF(PKCS7) + +# define PKCS7_OP_SET_DETACHED_SIGNATURE 1 +# define PKCS7_OP_GET_DETACHED_SIGNATURE 2 + +# define PKCS7_get_signed_attributes(si) ((si)->auth_attr) +# define PKCS7_get_attributes(si) ((si)->unauth_attr) + +# define PKCS7_type_is_signed(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_signed) +# define PKCS7_type_is_encrypted(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_encrypted) +# define PKCS7_type_is_enveloped(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_enveloped) +# define PKCS7_type_is_signedAndEnveloped(a) \ + (OBJ_obj2nid((a)->type) == NID_pkcs7_signedAndEnveloped) +# define PKCS7_type_is_data(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_data) +# define PKCS7_type_is_digest(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_digest) + +# define PKCS7_set_detached(p,v) \ + PKCS7_ctrl(p,PKCS7_OP_SET_DETACHED_SIGNATURE,v,NULL) +# define PKCS7_get_detached(p) \ + PKCS7_ctrl(p,PKCS7_OP_GET_DETACHED_SIGNATURE,0,NULL) + +# define PKCS7_is_detached(p7) (PKCS7_type_is_signed(p7) && PKCS7_get_detached(p7)) + +/* S/MIME related flags */ + +# define PKCS7_TEXT 0x1 +# define PKCS7_NOCERTS 0x2 +# define PKCS7_NOSIGS 0x4 +# define PKCS7_NOCHAIN 0x8 +# define PKCS7_NOINTERN 0x10 +# define PKCS7_NOVERIFY 0x20 +# define PKCS7_DETACHED 0x40 +# define PKCS7_BINARY 0x80 +# define PKCS7_NOATTR 0x100 +# define PKCS7_NOSMIMECAP 0x200 +# define PKCS7_NOOLDMIMETYPE 0x400 +# define PKCS7_CRLFEOL 0x800 +# define PKCS7_STREAM 0x1000 +# define PKCS7_NOCRL 0x2000 +# define PKCS7_PARTIAL 0x4000 +# define PKCS7_REUSE_DIGEST 0x8000 +# define PKCS7_NO_DUAL_CONTENT 0x10000 + +/* Flags: for compatibility with older code */ + +# define SMIME_TEXT PKCS7_TEXT +# define SMIME_NOCERTS PKCS7_NOCERTS +# define SMIME_NOSIGS PKCS7_NOSIGS +# define SMIME_NOCHAIN PKCS7_NOCHAIN +# define SMIME_NOINTERN PKCS7_NOINTERN +# define SMIME_NOVERIFY PKCS7_NOVERIFY +# define SMIME_DETACHED PKCS7_DETACHED +# define SMIME_BINARY PKCS7_BINARY +# define SMIME_NOATTR PKCS7_NOATTR + +/* CRLF ASCII canonicalisation */ +# define SMIME_ASCIICRLF 0x80000 + +DECLARE_ASN1_FUNCTIONS(PKCS7_ISSUER_AND_SERIAL) + +int PKCS7_ISSUER_AND_SERIAL_digest(PKCS7_ISSUER_AND_SERIAL *data, + const EVP_MD *type, unsigned char *md, + unsigned int *len); +# ifndef OPENSSL_NO_STDIO +PKCS7 *d2i_PKCS7_fp(FILE *fp, PKCS7 **p7); +int i2d_PKCS7_fp(FILE *fp, PKCS7 *p7); +# endif +PKCS7 *PKCS7_dup(PKCS7 *p7); +PKCS7 *d2i_PKCS7_bio(BIO *bp, PKCS7 **p7); +int i2d_PKCS7_bio(BIO *bp, PKCS7 *p7); +int i2d_PKCS7_bio_stream(BIO *out, PKCS7 *p7, BIO *in, int flags); +int PEM_write_bio_PKCS7_stream(BIO *out, PKCS7 *p7, BIO *in, int flags); + +DECLARE_ASN1_FUNCTIONS(PKCS7_SIGNER_INFO) +DECLARE_ASN1_FUNCTIONS(PKCS7_RECIP_INFO) +DECLARE_ASN1_FUNCTIONS(PKCS7_SIGNED) +DECLARE_ASN1_FUNCTIONS(PKCS7_ENC_CONTENT) +DECLARE_ASN1_FUNCTIONS(PKCS7_ENVELOPE) +DECLARE_ASN1_FUNCTIONS(PKCS7_SIGN_ENVELOPE) +DECLARE_ASN1_FUNCTIONS(PKCS7_DIGEST) +DECLARE_ASN1_FUNCTIONS(PKCS7_ENCRYPT) +DECLARE_ASN1_FUNCTIONS(PKCS7) + +DECLARE_ASN1_ITEM(PKCS7_ATTR_SIGN) +DECLARE_ASN1_ITEM(PKCS7_ATTR_VERIFY) + +DECLARE_ASN1_NDEF_FUNCTION(PKCS7) +DECLARE_ASN1_PRINT_FUNCTION(PKCS7) + +long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg); + +int PKCS7_set_type(PKCS7 *p7, int type); +int PKCS7_set0_type_other(PKCS7 *p7, int type, ASN1_TYPE *other); +int PKCS7_set_content(PKCS7 *p7, PKCS7 *p7_data); +int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey, + const EVP_MD *dgst); +int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si); +int PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *p7i); +int PKCS7_add_certificate(PKCS7 *p7, X509 *x509); +int PKCS7_add_crl(PKCS7 *p7, X509_CRL *x509); +int PKCS7_content_new(PKCS7 *p7, int nid); +int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, + BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si); +int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, + X509 *x509); + +BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio); +int PKCS7_dataFinal(PKCS7 *p7, BIO *bio); +BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert); + +PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509, + EVP_PKEY *pkey, const EVP_MD *dgst); +X509 *PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si); +int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md); +STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7); + +PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509); +void PKCS7_SIGNER_INFO_get0_algs(PKCS7_SIGNER_INFO *si, EVP_PKEY **pk, + X509_ALGOR **pdig, X509_ALGOR **psig); +void PKCS7_RECIP_INFO_get0_alg(PKCS7_RECIP_INFO *ri, X509_ALGOR **penc); +int PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri); +int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509); +int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher); +int PKCS7_stream(unsigned char ***boundary, PKCS7 *p7); + +PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx); +ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk); +int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int type, + void *data); +int PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype, + void *value); +ASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid); +ASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid); +int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si, + STACK_OF(X509_ATTRIBUTE) *sk); +int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, + STACK_OF(X509_ATTRIBUTE) *sk); + +PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, + BIO *data, int flags); + +PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, + X509 *signcert, EVP_PKEY *pkey, + const EVP_MD *md, int flags); + +int PKCS7_final(PKCS7 *p7, BIO *data, int flags); +int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, + BIO *indata, BIO *out, int flags); +STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, + int flags); +PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher, + int flags); +int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, + int flags); + +int PKCS7_add_attrib_smimecap(PKCS7_SIGNER_INFO *si, + STACK_OF(X509_ALGOR) *cap); +STACK_OF(X509_ALGOR) *PKCS7_get_smimecap(PKCS7_SIGNER_INFO *si); +int PKCS7_simple_smimecap(STACK_OF(X509_ALGOR) *sk, int nid, int arg); + +int PKCS7_add_attrib_content_type(PKCS7_SIGNER_INFO *si, ASN1_OBJECT *coid); +int PKCS7_add0_attrib_signing_time(PKCS7_SIGNER_INFO *si, ASN1_TIME *t); +int PKCS7_add1_attrib_digest(PKCS7_SIGNER_INFO *si, + const unsigned char *md, int mdlen); + +int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags); +PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont); + +BIO *BIO_new_PKCS7(BIO *out, PKCS7 *p7); + +# ifdef __cplusplus +} +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/pkcs7err.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/pkcs7err.h new file mode 100644 index 000000000..0ba418d78 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/pkcs7err.h @@ -0,0 +1,99 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_PKCS7ERR_H +# define HEADER_PKCS7ERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_PKCS7_strings(void); + +/* + * PKCS7 function codes. + */ +# define PKCS7_F_DO_PKCS7_SIGNED_ATTRIB 136 +# define PKCS7_F_PKCS7_ADD0_ATTRIB_SIGNING_TIME 135 +# define PKCS7_F_PKCS7_ADD_ATTRIB_SMIMECAP 118 +# define PKCS7_F_PKCS7_ADD_CERTIFICATE 100 +# define PKCS7_F_PKCS7_ADD_CRL 101 +# define PKCS7_F_PKCS7_ADD_RECIPIENT_INFO 102 +# define PKCS7_F_PKCS7_ADD_SIGNATURE 131 +# define PKCS7_F_PKCS7_ADD_SIGNER 103 +# define PKCS7_F_PKCS7_BIO_ADD_DIGEST 125 +# define PKCS7_F_PKCS7_COPY_EXISTING_DIGEST 138 +# define PKCS7_F_PKCS7_CTRL 104 +# define PKCS7_F_PKCS7_DATADECODE 112 +# define PKCS7_F_PKCS7_DATAFINAL 128 +# define PKCS7_F_PKCS7_DATAINIT 105 +# define PKCS7_F_PKCS7_DATAVERIFY 107 +# define PKCS7_F_PKCS7_DECRYPT 114 +# define PKCS7_F_PKCS7_DECRYPT_RINFO 133 +# define PKCS7_F_PKCS7_ENCODE_RINFO 132 +# define PKCS7_F_PKCS7_ENCRYPT 115 +# define PKCS7_F_PKCS7_FINAL 134 +# define PKCS7_F_PKCS7_FIND_DIGEST 127 +# define PKCS7_F_PKCS7_GET0_SIGNERS 124 +# define PKCS7_F_PKCS7_RECIP_INFO_SET 130 +# define PKCS7_F_PKCS7_SET_CIPHER 108 +# define PKCS7_F_PKCS7_SET_CONTENT 109 +# define PKCS7_F_PKCS7_SET_DIGEST 126 +# define PKCS7_F_PKCS7_SET_TYPE 110 +# define PKCS7_F_PKCS7_SIGN 116 +# define PKCS7_F_PKCS7_SIGNATUREVERIFY 113 +# define PKCS7_F_PKCS7_SIGNER_INFO_SET 129 +# define PKCS7_F_PKCS7_SIGNER_INFO_SIGN 139 +# define PKCS7_F_PKCS7_SIGN_ADD_SIGNER 137 +# define PKCS7_F_PKCS7_SIMPLE_SMIMECAP 119 +# define PKCS7_F_PKCS7_VERIFY 117 + +/* + * PKCS7 reason codes. + */ +# define PKCS7_R_CERTIFICATE_VERIFY_ERROR 117 +# define PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER 144 +# define PKCS7_R_CIPHER_NOT_INITIALIZED 116 +# define PKCS7_R_CONTENT_AND_DATA_PRESENT 118 +# define PKCS7_R_CTRL_ERROR 152 +# define PKCS7_R_DECRYPT_ERROR 119 +# define PKCS7_R_DIGEST_FAILURE 101 +# define PKCS7_R_ENCRYPTION_CTRL_FAILURE 149 +# define PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE 150 +# define PKCS7_R_ERROR_ADDING_RECIPIENT 120 +# define PKCS7_R_ERROR_SETTING_CIPHER 121 +# define PKCS7_R_INVALID_NULL_POINTER 143 +# define PKCS7_R_INVALID_SIGNED_DATA_TYPE 155 +# define PKCS7_R_NO_CONTENT 122 +# define PKCS7_R_NO_DEFAULT_DIGEST 151 +# define PKCS7_R_NO_MATCHING_DIGEST_TYPE_FOUND 154 +# define PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE 115 +# define PKCS7_R_NO_SIGNATURES_ON_DATA 123 +# define PKCS7_R_NO_SIGNERS 142 +# define PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE 104 +# define PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR 124 +# define PKCS7_R_PKCS7_ADD_SIGNER_ERROR 153 +# define PKCS7_R_PKCS7_DATASIGN 145 +# define PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 127 +# define PKCS7_R_SIGNATURE_FAILURE 105 +# define PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND 128 +# define PKCS7_R_SIGNING_CTRL_FAILURE 147 +# define PKCS7_R_SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE 148 +# define PKCS7_R_SMIME_TEXT_ERROR 129 +# define PKCS7_R_UNABLE_TO_FIND_CERTIFICATE 106 +# define PKCS7_R_UNABLE_TO_FIND_MEM_BIO 107 +# define PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST 108 +# define PKCS7_R_UNKNOWN_DIGEST_TYPE 109 +# define PKCS7_R_UNKNOWN_OPERATION 110 +# define PKCS7_R_UNSUPPORTED_CIPHER_TYPE 111 +# define PKCS7_R_UNSUPPORTED_CONTENT_TYPE 112 +# define PKCS7_R_WRONG_CONTENT_TYPE 113 +# define PKCS7_R_WRONG_PKCS7_TYPE 114 + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/rand.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/rand.h new file mode 100644 index 000000000..38a2a2718 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/rand.h @@ -0,0 +1,77 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_RAND_H +# define HEADER_RAND_H + +# include +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +struct rand_meth_st { + int (*seed) (const void *buf, int num); + int (*bytes) (unsigned char *buf, int num); + void (*cleanup) (void); + int (*add) (const void *buf, int num, double randomness); + int (*pseudorand) (unsigned char *buf, int num); + int (*status) (void); +}; + +int RAND_set_rand_method(const RAND_METHOD *meth); +const RAND_METHOD *RAND_get_rand_method(void); +# ifndef OPENSSL_NO_ENGINE +int RAND_set_rand_engine(ENGINE *engine); +# endif + +RAND_METHOD *RAND_OpenSSL(void); + +# if OPENSSL_API_COMPAT < 0x10100000L +# define RAND_cleanup() while(0) continue +# endif +int RAND_bytes(unsigned char *buf, int num); +int RAND_priv_bytes(unsigned char *buf, int num); +DEPRECATEDIN_1_1_0(int RAND_pseudo_bytes(unsigned char *buf, int num)) + +void RAND_seed(const void *buf, int num); +void RAND_keep_random_devices_open(int keep); + +# if defined(__ANDROID__) && defined(__NDK_FPABI__) +__NDK_FPABI__ /* __attribute__((pcs("aapcs"))) on ARM */ +# endif +void RAND_add(const void *buf, int num, double randomness); +int RAND_load_file(const char *file, long max_bytes); +int RAND_write_file(const char *file); +const char *RAND_file_name(char *file, size_t num); +int RAND_status(void); + +# ifndef OPENSSL_NO_EGD +int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes); +int RAND_egd(const char *path); +int RAND_egd_bytes(const char *path, int bytes); +# endif + +int RAND_poll(void); + +# if defined(_WIN32) && (defined(BASETYPES) || defined(_WINDEF_H)) +/* application has to include in order to use these */ +DEPRECATEDIN_1_1_0(void RAND_screen(void)) +DEPRECATEDIN_1_1_0(int RAND_event(UINT, WPARAM, LPARAM)) +# endif + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/rand_drbg.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/rand_drbg.h new file mode 100644 index 000000000..45b731b73 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/rand_drbg.h @@ -0,0 +1,130 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_DRBG_RAND_H +# define HEADER_DRBG_RAND_H + +# include +# include +# include + +/* + * RAND_DRBG flags + * + * Note: if new flags are added, the constant `rand_drbg_used_flags` + * in drbg_lib.c needs to be updated accordingly. + */ + +/* In CTR mode, disable derivation function ctr_df */ +# define RAND_DRBG_FLAG_CTR_NO_DF 0x1 + + +# if OPENSSL_API_COMPAT < 0x10200000L +/* This #define was replaced by an internal constant and should not be used. */ +# define RAND_DRBG_USED_FLAGS (RAND_DRBG_FLAG_CTR_NO_DF) +# endif + +/* + * Default security strength (in the sense of [NIST SP 800-90Ar1]) + * + * NIST SP 800-90Ar1 supports the strength of the DRBG being smaller than that + * of the cipher by collecting less entropy. The current DRBG implementation + * does not take RAND_DRBG_STRENGTH into account and sets the strength of the + * DRBG to that of the cipher. + * + * RAND_DRBG_STRENGTH is currently only used for the legacy RAND + * implementation. + * + * Currently supported ciphers are: NID_aes_128_ctr, NID_aes_192_ctr and + * NID_aes_256_ctr + */ +# define RAND_DRBG_STRENGTH 256 +/* Default drbg type */ +# define RAND_DRBG_TYPE NID_aes_256_ctr +/* Default drbg flags */ +# define RAND_DRBG_FLAGS 0 + + +# ifdef __cplusplus +extern "C" { +# endif + +/* + * Object lifetime functions. + */ +RAND_DRBG *RAND_DRBG_new(int type, unsigned int flags, RAND_DRBG *parent); +RAND_DRBG *RAND_DRBG_secure_new(int type, unsigned int flags, RAND_DRBG *parent); +int RAND_DRBG_set(RAND_DRBG *drbg, int type, unsigned int flags); +int RAND_DRBG_set_defaults(int type, unsigned int flags); +int RAND_DRBG_instantiate(RAND_DRBG *drbg, + const unsigned char *pers, size_t perslen); +int RAND_DRBG_uninstantiate(RAND_DRBG *drbg); +void RAND_DRBG_free(RAND_DRBG *drbg); + +/* + * Object "use" functions. + */ +int RAND_DRBG_reseed(RAND_DRBG *drbg, + const unsigned char *adin, size_t adinlen, + int prediction_resistance); +int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen, + int prediction_resistance, + const unsigned char *adin, size_t adinlen); +int RAND_DRBG_bytes(RAND_DRBG *drbg, unsigned char *out, size_t outlen); + +int RAND_DRBG_set_reseed_interval(RAND_DRBG *drbg, unsigned int interval); +int RAND_DRBG_set_reseed_time_interval(RAND_DRBG *drbg, time_t interval); + +int RAND_DRBG_set_reseed_defaults( + unsigned int master_reseed_interval, + unsigned int slave_reseed_interval, + time_t master_reseed_time_interval, + time_t slave_reseed_time_interval + ); + +RAND_DRBG *RAND_DRBG_get0_master(void); +RAND_DRBG *RAND_DRBG_get0_public(void); +RAND_DRBG *RAND_DRBG_get0_private(void); + +/* + * EXDATA + */ +# define RAND_DRBG_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DRBG, l, p, newf, dupf, freef) +int RAND_DRBG_set_ex_data(RAND_DRBG *drbg, int idx, void *arg); +void *RAND_DRBG_get_ex_data(const RAND_DRBG *drbg, int idx); + +/* + * Callback function typedefs + */ +typedef size_t (*RAND_DRBG_get_entropy_fn)(RAND_DRBG *drbg, + unsigned char **pout, + int entropy, size_t min_len, + size_t max_len, + int prediction_resistance); +typedef void (*RAND_DRBG_cleanup_entropy_fn)(RAND_DRBG *ctx, + unsigned char *out, size_t outlen); +typedef size_t (*RAND_DRBG_get_nonce_fn)(RAND_DRBG *drbg, unsigned char **pout, + int entropy, size_t min_len, + size_t max_len); +typedef void (*RAND_DRBG_cleanup_nonce_fn)(RAND_DRBG *drbg, + unsigned char *out, size_t outlen); + +int RAND_DRBG_set_callbacks(RAND_DRBG *drbg, + RAND_DRBG_get_entropy_fn get_entropy, + RAND_DRBG_cleanup_entropy_fn cleanup_entropy, + RAND_DRBG_get_nonce_fn get_nonce, + RAND_DRBG_cleanup_nonce_fn cleanup_nonce); + + +# ifdef __cplusplus +} +# endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/randerr.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/randerr.h new file mode 100644 index 000000000..599a2a18d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/randerr.h @@ -0,0 +1,89 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_RANDERR_H +# define HEADER_RANDERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_RAND_strings(void); + +/* + * RAND function codes. + */ +# define RAND_F_DRBG_BYTES 101 +# define RAND_F_DRBG_GET_ENTROPY 105 +# define RAND_F_DRBG_SETUP 117 +# define RAND_F_GET_ENTROPY 106 +# define RAND_F_RAND_BYTES 100 +# define RAND_F_RAND_DRBG_ENABLE_LOCKING 119 +# define RAND_F_RAND_DRBG_GENERATE 107 +# define RAND_F_RAND_DRBG_GET_ENTROPY 120 +# define RAND_F_RAND_DRBG_GET_NONCE 123 +# define RAND_F_RAND_DRBG_INSTANTIATE 108 +# define RAND_F_RAND_DRBG_NEW 109 +# define RAND_F_RAND_DRBG_RESEED 110 +# define RAND_F_RAND_DRBG_RESTART 102 +# define RAND_F_RAND_DRBG_SET 104 +# define RAND_F_RAND_DRBG_SET_DEFAULTS 121 +# define RAND_F_RAND_DRBG_UNINSTANTIATE 118 +# define RAND_F_RAND_LOAD_FILE 111 +# define RAND_F_RAND_POOL_ACQUIRE_ENTROPY 122 +# define RAND_F_RAND_POOL_ADD 103 +# define RAND_F_RAND_POOL_ADD_BEGIN 113 +# define RAND_F_RAND_POOL_ADD_END 114 +# define RAND_F_RAND_POOL_ATTACH 124 +# define RAND_F_RAND_POOL_BYTES_NEEDED 115 +# define RAND_F_RAND_POOL_NEW 116 +# define RAND_F_RAND_WRITE_FILE 112 + +/* + * RAND reason codes. + */ +# define RAND_R_ADDITIONAL_INPUT_TOO_LONG 102 +# define RAND_R_ALREADY_INSTANTIATED 103 +# define RAND_R_ARGUMENT_OUT_OF_RANGE 105 +# define RAND_R_CANNOT_OPEN_FILE 121 +# define RAND_R_DRBG_ALREADY_INITIALIZED 129 +# define RAND_R_DRBG_NOT_INITIALISED 104 +# define RAND_R_ENTROPY_INPUT_TOO_LONG 106 +# define RAND_R_ENTROPY_OUT_OF_RANGE 124 +# define RAND_R_ERROR_ENTROPY_POOL_WAS_IGNORED 127 +# define RAND_R_ERROR_INITIALISING_DRBG 107 +# define RAND_R_ERROR_INSTANTIATING_DRBG 108 +# define RAND_R_ERROR_RETRIEVING_ADDITIONAL_INPUT 109 +# define RAND_R_ERROR_RETRIEVING_ENTROPY 110 +# define RAND_R_ERROR_RETRIEVING_NONCE 111 +# define RAND_R_FAILED_TO_CREATE_LOCK 126 +# define RAND_R_FUNC_NOT_IMPLEMENTED 101 +# define RAND_R_FWRITE_ERROR 123 +# define RAND_R_GENERATE_ERROR 112 +# define RAND_R_INTERNAL_ERROR 113 +# define RAND_R_IN_ERROR_STATE 114 +# define RAND_R_NOT_A_REGULAR_FILE 122 +# define RAND_R_NOT_INSTANTIATED 115 +# define RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED 128 +# define RAND_R_PARENT_LOCKING_NOT_ENABLED 130 +# define RAND_R_PARENT_STRENGTH_TOO_WEAK 131 +# define RAND_R_PERSONALISATION_STRING_TOO_LONG 116 +# define RAND_R_PREDICTION_RESISTANCE_NOT_SUPPORTED 133 +# define RAND_R_PRNG_NOT_SEEDED 100 +# define RAND_R_RANDOM_POOL_OVERFLOW 125 +# define RAND_R_RANDOM_POOL_UNDERFLOW 134 +# define RAND_R_REQUEST_TOO_LARGE_FOR_DRBG 117 +# define RAND_R_RESEED_ERROR 118 +# define RAND_R_SELFTEST_FAILURE 119 +# define RAND_R_TOO_LITTLE_NONCE_REQUESTED 135 +# define RAND_R_TOO_MUCH_NONCE_REQUESTED 136 +# define RAND_R_UNSUPPORTED_DRBG_FLAGS 132 +# define RAND_R_UNSUPPORTED_DRBG_TYPE 120 + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/rc2.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/rc2.h new file mode 100644 index 000000000..585f9e4c3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/rc2.h @@ -0,0 +1,51 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_RC2_H +# define HEADER_RC2_H + +# include + +# ifndef OPENSSL_NO_RC2 +# ifdef __cplusplus +extern "C" { +# endif + +typedef unsigned int RC2_INT; + +# define RC2_ENCRYPT 1 +# define RC2_DECRYPT 0 + +# define RC2_BLOCK 8 +# define RC2_KEY_LENGTH 16 + +typedef struct rc2_key_st { + RC2_INT data[64]; +} RC2_KEY; + +void RC2_set_key(RC2_KEY *key, int len, const unsigned char *data, int bits); +void RC2_ecb_encrypt(const unsigned char *in, unsigned char *out, + RC2_KEY *key, int enc); +void RC2_encrypt(unsigned long *data, RC2_KEY *key); +void RC2_decrypt(unsigned long *data, RC2_KEY *key); +void RC2_cbc_encrypt(const unsigned char *in, unsigned char *out, long length, + RC2_KEY *ks, unsigned char *iv, int enc); +void RC2_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, RC2_KEY *schedule, unsigned char *ivec, + int *num, int enc); +void RC2_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, RC2_KEY *schedule, unsigned char *ivec, + int *num); + +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/rc4.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/rc4.h new file mode 100644 index 000000000..86803b37f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/rc4.h @@ -0,0 +1,36 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_RC4_H +# define HEADER_RC4_H + +# include + +# ifndef OPENSSL_NO_RC4 +# include +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct rc4_key_st { + RC4_INT x, y; + RC4_INT data[256]; +} RC4_KEY; + +const char *RC4_options(void); +void RC4_set_key(RC4_KEY *key, int len, const unsigned char *data); +void RC4(RC4_KEY *key, size_t len, const unsigned char *indata, + unsigned char *outdata); + +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/rc5.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/rc5.h new file mode 100644 index 000000000..793f88e4e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/rc5.h @@ -0,0 +1,63 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_RC5_H +# define HEADER_RC5_H + +# include + +# ifndef OPENSSL_NO_RC5 +# ifdef __cplusplus +extern "C" { +# endif + +# define RC5_ENCRYPT 1 +# define RC5_DECRYPT 0 + +# define RC5_32_INT unsigned int + +# define RC5_32_BLOCK 8 +# define RC5_32_KEY_LENGTH 16/* This is a default, max is 255 */ + +/* + * This are the only values supported. Tweak the code if you want more The + * most supported modes will be RC5-32/12/16 RC5-32/16/8 + */ +# define RC5_8_ROUNDS 8 +# define RC5_12_ROUNDS 12 +# define RC5_16_ROUNDS 16 + +typedef struct rc5_key_st { + /* Number of rounds */ + int rounds; + RC5_32_INT data[2 * (RC5_16_ROUNDS + 1)]; +} RC5_32_KEY; + +void RC5_32_set_key(RC5_32_KEY *key, int len, const unsigned char *data, + int rounds); +void RC5_32_ecb_encrypt(const unsigned char *in, unsigned char *out, + RC5_32_KEY *key, int enc); +void RC5_32_encrypt(unsigned long *data, RC5_32_KEY *key); +void RC5_32_decrypt(unsigned long *data, RC5_32_KEY *key); +void RC5_32_cbc_encrypt(const unsigned char *in, unsigned char *out, + long length, RC5_32_KEY *ks, unsigned char *iv, + int enc); +void RC5_32_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, RC5_32_KEY *schedule, + unsigned char *ivec, int *num, int enc); +void RC5_32_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, RC5_32_KEY *schedule, + unsigned char *ivec, int *num); + +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/ripemd.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ripemd.h new file mode 100644 index 000000000..c42026aa4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ripemd.h @@ -0,0 +1,47 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_RIPEMD_H +# define HEADER_RIPEMD_H + +# include + +#ifndef OPENSSL_NO_RMD160 +# include +# include +# ifdef __cplusplus +extern "C" { +# endif + +# define RIPEMD160_LONG unsigned int + +# define RIPEMD160_CBLOCK 64 +# define RIPEMD160_LBLOCK (RIPEMD160_CBLOCK/4) +# define RIPEMD160_DIGEST_LENGTH 20 + +typedef struct RIPEMD160state_st { + RIPEMD160_LONG A, B, C, D, E; + RIPEMD160_LONG Nl, Nh; + RIPEMD160_LONG data[RIPEMD160_LBLOCK]; + unsigned int num; +} RIPEMD160_CTX; + +int RIPEMD160_Init(RIPEMD160_CTX *c); +int RIPEMD160_Update(RIPEMD160_CTX *c, const void *data, size_t len); +int RIPEMD160_Final(unsigned char *md, RIPEMD160_CTX *c); +unsigned char *RIPEMD160(const unsigned char *d, size_t n, unsigned char *md); +void RIPEMD160_Transform(RIPEMD160_CTX *c, const unsigned char *b); + +# ifdef __cplusplus +} +# endif +# endif + + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/rsa.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/rsa.h new file mode 100644 index 000000000..cdce1264e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/rsa.h @@ -0,0 +1,512 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_RSA_H +# define HEADER_RSA_H + +# include + +# ifndef OPENSSL_NO_RSA +# include +# include +# include +# include +# if OPENSSL_API_COMPAT < 0x10100000L +# include +# endif +# include +# ifdef __cplusplus +extern "C" { +# endif + +/* The types RSA and RSA_METHOD are defined in ossl_typ.h */ + +# ifndef OPENSSL_RSA_MAX_MODULUS_BITS +# define OPENSSL_RSA_MAX_MODULUS_BITS 16384 +# endif + +# define OPENSSL_RSA_FIPS_MIN_MODULUS_BITS 1024 + +# ifndef OPENSSL_RSA_SMALL_MODULUS_BITS +# define OPENSSL_RSA_SMALL_MODULUS_BITS 3072 +# endif +# ifndef OPENSSL_RSA_MAX_PUBEXP_BITS + +/* exponent limit enforced for "large" modulus only */ +# define OPENSSL_RSA_MAX_PUBEXP_BITS 64 +# endif + +# define RSA_3 0x3L +# define RSA_F4 0x10001L + +/* based on RFC 8017 appendix A.1.2 */ +# define RSA_ASN1_VERSION_DEFAULT 0 +# define RSA_ASN1_VERSION_MULTI 1 + +# define RSA_DEFAULT_PRIME_NUM 2 + +# define RSA_METHOD_FLAG_NO_CHECK 0x0001/* don't check pub/private + * match */ + +# define RSA_FLAG_CACHE_PUBLIC 0x0002 +# define RSA_FLAG_CACHE_PRIVATE 0x0004 +# define RSA_FLAG_BLINDING 0x0008 +# define RSA_FLAG_THREAD_SAFE 0x0010 +/* + * This flag means the private key operations will be handled by rsa_mod_exp + * and that they do not depend on the private key components being present: + * for example a key stored in external hardware. Without this flag + * bn_mod_exp gets called when private key components are absent. + */ +# define RSA_FLAG_EXT_PKEY 0x0020 + +/* + * new with 0.9.6j and 0.9.7b; the built-in + * RSA implementation now uses blinding by + * default (ignoring RSA_FLAG_BLINDING), + * but other engines might not need it + */ +# define RSA_FLAG_NO_BLINDING 0x0080 +# if OPENSSL_API_COMPAT < 0x10100000L +/* + * Does nothing. Previously this switched off constant time behaviour. + */ +# define RSA_FLAG_NO_CONSTTIME 0x0000 +# endif +# if OPENSSL_API_COMPAT < 0x00908000L +/* deprecated name for the flag*/ +/* + * new with 0.9.7h; the built-in RSA + * implementation now uses constant time + * modular exponentiation for secret exponents + * by default. This flag causes the + * faster variable sliding window method to + * be used for all exponents. + */ +# define RSA_FLAG_NO_EXP_CONSTTIME RSA_FLAG_NO_CONSTTIME +# endif + +# define EVP_PKEY_CTX_set_rsa_padding(ctx, pad) \ + RSA_pkey_ctx_ctrl(ctx, -1, EVP_PKEY_CTRL_RSA_PADDING, pad, NULL) + +# define EVP_PKEY_CTX_get_rsa_padding(ctx, ppad) \ + RSA_pkey_ctx_ctrl(ctx, -1, EVP_PKEY_CTRL_GET_RSA_PADDING, 0, ppad) + +# define EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, len) \ + RSA_pkey_ctx_ctrl(ctx, (EVP_PKEY_OP_SIGN|EVP_PKEY_OP_VERIFY), \ + EVP_PKEY_CTRL_RSA_PSS_SALTLEN, len, NULL) +/* Salt length matches digest */ +# define RSA_PSS_SALTLEN_DIGEST -1 +/* Verify only: auto detect salt length */ +# define RSA_PSS_SALTLEN_AUTO -2 +/* Set salt length to maximum possible */ +# define RSA_PSS_SALTLEN_MAX -3 +/* Old compatible max salt length for sign only */ +# define RSA_PSS_SALTLEN_MAX_SIGN -2 + +# define EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(ctx, len) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN, \ + EVP_PKEY_CTRL_RSA_PSS_SALTLEN, len, NULL) + +# define EVP_PKEY_CTX_get_rsa_pss_saltlen(ctx, plen) \ + RSA_pkey_ctx_ctrl(ctx, (EVP_PKEY_OP_SIGN|EVP_PKEY_OP_VERIFY), \ + EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN, 0, plen) + +# define EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) \ + RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_KEYGEN, \ + EVP_PKEY_CTRL_RSA_KEYGEN_BITS, bits, NULL) + +# define EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, pubexp) \ + RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_KEYGEN, \ + EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, 0, pubexp) + +# define EVP_PKEY_CTX_set_rsa_keygen_primes(ctx, primes) \ + RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_KEYGEN, \ + EVP_PKEY_CTRL_RSA_KEYGEN_PRIMES, primes, NULL) + +# define EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md) \ + RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, \ + EVP_PKEY_CTRL_RSA_MGF1_MD, 0, (void *)(md)) + +# define EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(ctx, md) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN, \ + EVP_PKEY_CTRL_RSA_MGF1_MD, 0, (void *)(md)) + +# define EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, \ + EVP_PKEY_CTRL_RSA_OAEP_MD, 0, (void *)(md)) + +# define EVP_PKEY_CTX_get_rsa_mgf1_md(ctx, pmd) \ + RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, \ + EVP_PKEY_CTRL_GET_RSA_MGF1_MD, 0, (void *)(pmd)) + +# define EVP_PKEY_CTX_get_rsa_oaep_md(ctx, pmd) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, \ + EVP_PKEY_CTRL_GET_RSA_OAEP_MD, 0, (void *)(pmd)) + +# define EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, l, llen) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, \ + EVP_PKEY_CTRL_RSA_OAEP_LABEL, llen, (void *)(l)) + +# define EVP_PKEY_CTX_get0_rsa_oaep_label(ctx, l) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, \ + EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL, 0, (void *)(l)) + +# define EVP_PKEY_CTX_set_rsa_pss_keygen_md(ctx, md) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA_PSS, \ + EVP_PKEY_OP_KEYGEN, EVP_PKEY_CTRL_MD, \ + 0, (void *)(md)) + +# define EVP_PKEY_CTRL_RSA_PADDING (EVP_PKEY_ALG_CTRL + 1) +# define EVP_PKEY_CTRL_RSA_PSS_SALTLEN (EVP_PKEY_ALG_CTRL + 2) + +# define EVP_PKEY_CTRL_RSA_KEYGEN_BITS (EVP_PKEY_ALG_CTRL + 3) +# define EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP (EVP_PKEY_ALG_CTRL + 4) +# define EVP_PKEY_CTRL_RSA_MGF1_MD (EVP_PKEY_ALG_CTRL + 5) + +# define EVP_PKEY_CTRL_GET_RSA_PADDING (EVP_PKEY_ALG_CTRL + 6) +# define EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN (EVP_PKEY_ALG_CTRL + 7) +# define EVP_PKEY_CTRL_GET_RSA_MGF1_MD (EVP_PKEY_ALG_CTRL + 8) + +# define EVP_PKEY_CTRL_RSA_OAEP_MD (EVP_PKEY_ALG_CTRL + 9) +# define EVP_PKEY_CTRL_RSA_OAEP_LABEL (EVP_PKEY_ALG_CTRL + 10) + +# define EVP_PKEY_CTRL_GET_RSA_OAEP_MD (EVP_PKEY_ALG_CTRL + 11) +# define EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL (EVP_PKEY_ALG_CTRL + 12) + +# define EVP_PKEY_CTRL_RSA_KEYGEN_PRIMES (EVP_PKEY_ALG_CTRL + 13) + +# define RSA_PKCS1_PADDING 1 +# define RSA_SSLV23_PADDING 2 +# define RSA_NO_PADDING 3 +# define RSA_PKCS1_OAEP_PADDING 4 +# define RSA_X931_PADDING 5 +/* EVP_PKEY_ only */ +# define RSA_PKCS1_PSS_PADDING 6 + +# define RSA_PKCS1_PADDING_SIZE 11 + +# define RSA_set_app_data(s,arg) RSA_set_ex_data(s,0,arg) +# define RSA_get_app_data(s) RSA_get_ex_data(s,0) + +RSA *RSA_new(void); +RSA *RSA_new_method(ENGINE *engine); +int RSA_bits(const RSA *rsa); +int RSA_size(const RSA *rsa); +int RSA_security_bits(const RSA *rsa); + +int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d); +int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q); +int RSA_set0_crt_params(RSA *r,BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp); +int RSA_set0_multi_prime_params(RSA *r, BIGNUM *primes[], BIGNUM *exps[], + BIGNUM *coeffs[], int pnum); +void RSA_get0_key(const RSA *r, + const BIGNUM **n, const BIGNUM **e, const BIGNUM **d); +void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q); +int RSA_get_multi_prime_extra_count(const RSA *r); +int RSA_get0_multi_prime_factors(const RSA *r, const BIGNUM *primes[]); +void RSA_get0_crt_params(const RSA *r, + const BIGNUM **dmp1, const BIGNUM **dmq1, + const BIGNUM **iqmp); +int RSA_get0_multi_prime_crt_params(const RSA *r, const BIGNUM *exps[], + const BIGNUM *coeffs[]); +const BIGNUM *RSA_get0_n(const RSA *d); +const BIGNUM *RSA_get0_e(const RSA *d); +const BIGNUM *RSA_get0_d(const RSA *d); +const BIGNUM *RSA_get0_p(const RSA *d); +const BIGNUM *RSA_get0_q(const RSA *d); +const BIGNUM *RSA_get0_dmp1(const RSA *r); +const BIGNUM *RSA_get0_dmq1(const RSA *r); +const BIGNUM *RSA_get0_iqmp(const RSA *r); +void RSA_clear_flags(RSA *r, int flags); +int RSA_test_flags(const RSA *r, int flags); +void RSA_set_flags(RSA *r, int flags); +int RSA_get_version(RSA *r); +ENGINE *RSA_get0_engine(const RSA *r); + +/* Deprecated version */ +DEPRECATEDIN_0_9_8(RSA *RSA_generate_key(int bits, unsigned long e, void + (*callback) (int, int, void *), + void *cb_arg)) + +/* New version */ +int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb); +/* Multi-prime version */ +int RSA_generate_multi_prime_key(RSA *rsa, int bits, int primes, + BIGNUM *e, BN_GENCB *cb); + +int RSA_X931_derive_ex(RSA *rsa, BIGNUM *p1, BIGNUM *p2, BIGNUM *q1, + BIGNUM *q2, const BIGNUM *Xp1, const BIGNUM *Xp2, + const BIGNUM *Xp, const BIGNUM *Xq1, const BIGNUM *Xq2, + const BIGNUM *Xq, const BIGNUM *e, BN_GENCB *cb); +int RSA_X931_generate_key_ex(RSA *rsa, int bits, const BIGNUM *e, + BN_GENCB *cb); + +int RSA_check_key(const RSA *); +int RSA_check_key_ex(const RSA *, BN_GENCB *cb); + /* next 4 return -1 on error */ +int RSA_public_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +int RSA_private_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +int RSA_public_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +int RSA_private_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +void RSA_free(RSA *r); +/* "up" the RSA object's reference count */ +int RSA_up_ref(RSA *r); + +int RSA_flags(const RSA *r); + +void RSA_set_default_method(const RSA_METHOD *meth); +const RSA_METHOD *RSA_get_default_method(void); +const RSA_METHOD *RSA_null_method(void); +const RSA_METHOD *RSA_get_method(const RSA *rsa); +int RSA_set_method(RSA *rsa, const RSA_METHOD *meth); + +/* these are the actual RSA functions */ +const RSA_METHOD *RSA_PKCS1_OpenSSL(void); + +int RSA_pkey_ctx_ctrl(EVP_PKEY_CTX *ctx, int optype, int cmd, int p1, void *p2); + +DECLARE_ASN1_ENCODE_FUNCTIONS_const(RSA, RSAPublicKey) +DECLARE_ASN1_ENCODE_FUNCTIONS_const(RSA, RSAPrivateKey) + +typedef struct rsa_pss_params_st { + X509_ALGOR *hashAlgorithm; + X509_ALGOR *maskGenAlgorithm; + ASN1_INTEGER *saltLength; + ASN1_INTEGER *trailerField; + /* Decoded hash algorithm from maskGenAlgorithm */ + X509_ALGOR *maskHash; +} RSA_PSS_PARAMS; + +DECLARE_ASN1_FUNCTIONS(RSA_PSS_PARAMS) + +typedef struct rsa_oaep_params_st { + X509_ALGOR *hashFunc; + X509_ALGOR *maskGenFunc; + X509_ALGOR *pSourceFunc; + /* Decoded hash algorithm from maskGenFunc */ + X509_ALGOR *maskHash; +} RSA_OAEP_PARAMS; + +DECLARE_ASN1_FUNCTIONS(RSA_OAEP_PARAMS) + +# ifndef OPENSSL_NO_STDIO +int RSA_print_fp(FILE *fp, const RSA *r, int offset); +# endif + +int RSA_print(BIO *bp, const RSA *r, int offset); + +/* + * The following 2 functions sign and verify a X509_SIG ASN1 object inside + * PKCS#1 padded RSA encryption + */ +int RSA_sign(int type, const unsigned char *m, unsigned int m_length, + unsigned char *sigret, unsigned int *siglen, RSA *rsa); +int RSA_verify(int type, const unsigned char *m, unsigned int m_length, + const unsigned char *sigbuf, unsigned int siglen, RSA *rsa); + +/* + * The following 2 function sign and verify a ASN1_OCTET_STRING object inside + * PKCS#1 padded RSA encryption + */ +int RSA_sign_ASN1_OCTET_STRING(int type, + const unsigned char *m, unsigned int m_length, + unsigned char *sigret, unsigned int *siglen, + RSA *rsa); +int RSA_verify_ASN1_OCTET_STRING(int type, const unsigned char *m, + unsigned int m_length, unsigned char *sigbuf, + unsigned int siglen, RSA *rsa); + +int RSA_blinding_on(RSA *rsa, BN_CTX *ctx); +void RSA_blinding_off(RSA *rsa); +BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *ctx); + +int RSA_padding_add_PKCS1_type_1(unsigned char *to, int tlen, + const unsigned char *f, int fl); +int RSA_padding_check_PKCS1_type_1(unsigned char *to, int tlen, + const unsigned char *f, int fl, + int rsa_len); +int RSA_padding_add_PKCS1_type_2(unsigned char *to, int tlen, + const unsigned char *f, int fl); +int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen, + const unsigned char *f, int fl, + int rsa_len); +int PKCS1_MGF1(unsigned char *mask, long len, const unsigned char *seed, + long seedlen, const EVP_MD *dgst); +int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen, + const unsigned char *f, int fl, + const unsigned char *p, int pl); +int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen, + const unsigned char *f, int fl, int rsa_len, + const unsigned char *p, int pl); +int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen, + const unsigned char *from, int flen, + const unsigned char *param, int plen, + const EVP_MD *md, const EVP_MD *mgf1md); +int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen, + const unsigned char *from, int flen, + int num, const unsigned char *param, + int plen, const EVP_MD *md, + const EVP_MD *mgf1md); +int RSA_padding_add_SSLv23(unsigned char *to, int tlen, + const unsigned char *f, int fl); +int RSA_padding_check_SSLv23(unsigned char *to, int tlen, + const unsigned char *f, int fl, int rsa_len); +int RSA_padding_add_none(unsigned char *to, int tlen, const unsigned char *f, + int fl); +int RSA_padding_check_none(unsigned char *to, int tlen, + const unsigned char *f, int fl, int rsa_len); +int RSA_padding_add_X931(unsigned char *to, int tlen, const unsigned char *f, + int fl); +int RSA_padding_check_X931(unsigned char *to, int tlen, + const unsigned char *f, int fl, int rsa_len); +int RSA_X931_hash_id(int nid); + +int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash, + const EVP_MD *Hash, const unsigned char *EM, + int sLen); +int RSA_padding_add_PKCS1_PSS(RSA *rsa, unsigned char *EM, + const unsigned char *mHash, const EVP_MD *Hash, + int sLen); + +int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash, + const EVP_MD *Hash, const EVP_MD *mgf1Hash, + const unsigned char *EM, int sLen); + +int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM, + const unsigned char *mHash, + const EVP_MD *Hash, const EVP_MD *mgf1Hash, + int sLen); + +#define RSA_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_RSA, l, p, newf, dupf, freef) +int RSA_set_ex_data(RSA *r, int idx, void *arg); +void *RSA_get_ex_data(const RSA *r, int idx); + +RSA *RSAPublicKey_dup(RSA *rsa); +RSA *RSAPrivateKey_dup(RSA *rsa); + +/* + * If this flag is set the RSA method is FIPS compliant and can be used in + * FIPS mode. This is set in the validated module method. If an application + * sets this flag in its own methods it is its responsibility to ensure the + * result is compliant. + */ + +# define RSA_FLAG_FIPS_METHOD 0x0400 + +/* + * If this flag is set the operations normally disabled in FIPS mode are + * permitted it is then the applications responsibility to ensure that the + * usage is compliant. + */ + +# define RSA_FLAG_NON_FIPS_ALLOW 0x0400 +/* + * Application has decided PRNG is good enough to generate a key: don't + * check. + */ +# define RSA_FLAG_CHECKED 0x0800 + +RSA_METHOD *RSA_meth_new(const char *name, int flags); +void RSA_meth_free(RSA_METHOD *meth); +RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth); +const char *RSA_meth_get0_name(const RSA_METHOD *meth); +int RSA_meth_set1_name(RSA_METHOD *meth, const char *name); +int RSA_meth_get_flags(const RSA_METHOD *meth); +int RSA_meth_set_flags(RSA_METHOD *meth, int flags); +void *RSA_meth_get0_app_data(const RSA_METHOD *meth); +int RSA_meth_set0_app_data(RSA_METHOD *meth, void *app_data); +int (*RSA_meth_get_pub_enc(const RSA_METHOD *meth)) + (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +int RSA_meth_set_pub_enc(RSA_METHOD *rsa, + int (*pub_enc) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, + int padding)); +int (*RSA_meth_get_pub_dec(const RSA_METHOD *meth)) + (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +int RSA_meth_set_pub_dec(RSA_METHOD *rsa, + int (*pub_dec) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, + int padding)); +int (*RSA_meth_get_priv_enc(const RSA_METHOD *meth)) + (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +int RSA_meth_set_priv_enc(RSA_METHOD *rsa, + int (*priv_enc) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, + int padding)); +int (*RSA_meth_get_priv_dec(const RSA_METHOD *meth)) + (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +int RSA_meth_set_priv_dec(RSA_METHOD *rsa, + int (*priv_dec) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, + int padding)); +int (*RSA_meth_get_mod_exp(const RSA_METHOD *meth)) + (BIGNUM *r0, const BIGNUM *i, RSA *rsa, BN_CTX *ctx); +int RSA_meth_set_mod_exp(RSA_METHOD *rsa, + int (*mod_exp) (BIGNUM *r0, const BIGNUM *i, RSA *rsa, + BN_CTX *ctx)); +int (*RSA_meth_get_bn_mod_exp(const RSA_METHOD *meth)) + (BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); +int RSA_meth_set_bn_mod_exp(RSA_METHOD *rsa, + int (*bn_mod_exp) (BIGNUM *r, + const BIGNUM *a, + const BIGNUM *p, + const BIGNUM *m, + BN_CTX *ctx, + BN_MONT_CTX *m_ctx)); +int (*RSA_meth_get_init(const RSA_METHOD *meth)) (RSA *rsa); +int RSA_meth_set_init(RSA_METHOD *rsa, int (*init) (RSA *rsa)); +int (*RSA_meth_get_finish(const RSA_METHOD *meth)) (RSA *rsa); +int RSA_meth_set_finish(RSA_METHOD *rsa, int (*finish) (RSA *rsa)); +int (*RSA_meth_get_sign(const RSA_METHOD *meth)) + (int type, + const unsigned char *m, unsigned int m_length, + unsigned char *sigret, unsigned int *siglen, + const RSA *rsa); +int RSA_meth_set_sign(RSA_METHOD *rsa, + int (*sign) (int type, const unsigned char *m, + unsigned int m_length, + unsigned char *sigret, unsigned int *siglen, + const RSA *rsa)); +int (*RSA_meth_get_verify(const RSA_METHOD *meth)) + (int dtype, const unsigned char *m, + unsigned int m_length, const unsigned char *sigbuf, + unsigned int siglen, const RSA *rsa); +int RSA_meth_set_verify(RSA_METHOD *rsa, + int (*verify) (int dtype, const unsigned char *m, + unsigned int m_length, + const unsigned char *sigbuf, + unsigned int siglen, const RSA *rsa)); +int (*RSA_meth_get_keygen(const RSA_METHOD *meth)) + (RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb); +int RSA_meth_set_keygen(RSA_METHOD *rsa, + int (*keygen) (RSA *rsa, int bits, BIGNUM *e, + BN_GENCB *cb)); +int (*RSA_meth_get_multi_prime_keygen(const RSA_METHOD *meth)) + (RSA *rsa, int bits, int primes, BIGNUM *e, BN_GENCB *cb); +int RSA_meth_set_multi_prime_keygen(RSA_METHOD *meth, + int (*keygen) (RSA *rsa, int bits, + int primes, BIGNUM *e, + BN_GENCB *cb)); + +# ifdef __cplusplus +} +# endif +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/rsaerr.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/rsaerr.h new file mode 100644 index 000000000..d5bc01c10 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/rsaerr.h @@ -0,0 +1,162 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_RSAERR_H +# define HEADER_RSAERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_RSA_strings(void); + +/* + * RSA function codes. + */ +# define RSA_F_CHECK_PADDING_MD 140 +# define RSA_F_ENCODE_PKCS1 146 +# define RSA_F_INT_RSA_VERIFY 145 +# define RSA_F_OLD_RSA_PRIV_DECODE 147 +# define RSA_F_PKEY_PSS_INIT 165 +# define RSA_F_PKEY_RSA_CTRL 143 +# define RSA_F_PKEY_RSA_CTRL_STR 144 +# define RSA_F_PKEY_RSA_SIGN 142 +# define RSA_F_PKEY_RSA_VERIFY 149 +# define RSA_F_PKEY_RSA_VERIFYRECOVER 141 +# define RSA_F_RSA_ALGOR_TO_MD 156 +# define RSA_F_RSA_BUILTIN_KEYGEN 129 +# define RSA_F_RSA_CHECK_KEY 123 +# define RSA_F_RSA_CHECK_KEY_EX 160 +# define RSA_F_RSA_CMS_DECRYPT 159 +# define RSA_F_RSA_CMS_VERIFY 158 +# define RSA_F_RSA_ITEM_VERIFY 148 +# define RSA_F_RSA_METH_DUP 161 +# define RSA_F_RSA_METH_NEW 162 +# define RSA_F_RSA_METH_SET1_NAME 163 +# define RSA_F_RSA_MGF1_TO_MD 157 +# define RSA_F_RSA_MULTIP_INFO_NEW 166 +# define RSA_F_RSA_NEW_METHOD 106 +# define RSA_F_RSA_NULL 124 +# define RSA_F_RSA_NULL_PRIVATE_DECRYPT 132 +# define RSA_F_RSA_NULL_PRIVATE_ENCRYPT 133 +# define RSA_F_RSA_NULL_PUBLIC_DECRYPT 134 +# define RSA_F_RSA_NULL_PUBLIC_ENCRYPT 135 +# define RSA_F_RSA_OSSL_PRIVATE_DECRYPT 101 +# define RSA_F_RSA_OSSL_PRIVATE_ENCRYPT 102 +# define RSA_F_RSA_OSSL_PUBLIC_DECRYPT 103 +# define RSA_F_RSA_OSSL_PUBLIC_ENCRYPT 104 +# define RSA_F_RSA_PADDING_ADD_NONE 107 +# define RSA_F_RSA_PADDING_ADD_PKCS1_OAEP 121 +# define RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1 154 +# define RSA_F_RSA_PADDING_ADD_PKCS1_PSS 125 +# define RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1 152 +# define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1 108 +# define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2 109 +# define RSA_F_RSA_PADDING_ADD_SSLV23 110 +# define RSA_F_RSA_PADDING_ADD_X931 127 +# define RSA_F_RSA_PADDING_CHECK_NONE 111 +# define RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP 122 +# define RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1 153 +# define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1 112 +# define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2 113 +# define RSA_F_RSA_PADDING_CHECK_SSLV23 114 +# define RSA_F_RSA_PADDING_CHECK_X931 128 +# define RSA_F_RSA_PARAM_DECODE 164 +# define RSA_F_RSA_PRINT 115 +# define RSA_F_RSA_PRINT_FP 116 +# define RSA_F_RSA_PRIV_DECODE 150 +# define RSA_F_RSA_PRIV_ENCODE 138 +# define RSA_F_RSA_PSS_GET_PARAM 151 +# define RSA_F_RSA_PSS_TO_CTX 155 +# define RSA_F_RSA_PUB_DECODE 139 +# define RSA_F_RSA_SETUP_BLINDING 136 +# define RSA_F_RSA_SIGN 117 +# define RSA_F_RSA_SIGN_ASN1_OCTET_STRING 118 +# define RSA_F_RSA_VERIFY 119 +# define RSA_F_RSA_VERIFY_ASN1_OCTET_STRING 120 +# define RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1 126 +# define RSA_F_SETUP_TBUF 167 + +/* + * RSA reason codes. + */ +# define RSA_R_ALGORITHM_MISMATCH 100 +# define RSA_R_BAD_E_VALUE 101 +# define RSA_R_BAD_FIXED_HEADER_DECRYPT 102 +# define RSA_R_BAD_PAD_BYTE_COUNT 103 +# define RSA_R_BAD_SIGNATURE 104 +# define RSA_R_BLOCK_TYPE_IS_NOT_01 106 +# define RSA_R_BLOCK_TYPE_IS_NOT_02 107 +# define RSA_R_DATA_GREATER_THAN_MOD_LEN 108 +# define RSA_R_DATA_TOO_LARGE 109 +# define RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE 110 +# define RSA_R_DATA_TOO_LARGE_FOR_MODULUS 132 +# define RSA_R_DATA_TOO_SMALL 111 +# define RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE 122 +# define RSA_R_DIGEST_DOES_NOT_MATCH 158 +# define RSA_R_DIGEST_NOT_ALLOWED 145 +# define RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY 112 +# define RSA_R_DMP1_NOT_CONGRUENT_TO_D 124 +# define RSA_R_DMQ1_NOT_CONGRUENT_TO_D 125 +# define RSA_R_D_E_NOT_CONGRUENT_TO_1 123 +# define RSA_R_FIRST_OCTET_INVALID 133 +# define RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE 144 +# define RSA_R_INVALID_DIGEST 157 +# define RSA_R_INVALID_DIGEST_LENGTH 143 +# define RSA_R_INVALID_HEADER 137 +# define RSA_R_INVALID_LABEL 160 +# define RSA_R_INVALID_MESSAGE_LENGTH 131 +# define RSA_R_INVALID_MGF1_MD 156 +# define RSA_R_INVALID_MULTI_PRIME_KEY 167 +# define RSA_R_INVALID_OAEP_PARAMETERS 161 +# define RSA_R_INVALID_PADDING 138 +# define RSA_R_INVALID_PADDING_MODE 141 +# define RSA_R_INVALID_PSS_PARAMETERS 149 +# define RSA_R_INVALID_PSS_SALTLEN 146 +# define RSA_R_INVALID_SALT_LENGTH 150 +# define RSA_R_INVALID_TRAILER 139 +# define RSA_R_INVALID_X931_DIGEST 142 +# define RSA_R_IQMP_NOT_INVERSE_OF_Q 126 +# define RSA_R_KEY_PRIME_NUM_INVALID 165 +# define RSA_R_KEY_SIZE_TOO_SMALL 120 +# define RSA_R_LAST_OCTET_INVALID 134 +# define RSA_R_MGF1_DIGEST_NOT_ALLOWED 152 +# define RSA_R_MODULUS_TOO_LARGE 105 +# define RSA_R_MP_COEFFICIENT_NOT_INVERSE_OF_R 168 +# define RSA_R_MP_EXPONENT_NOT_CONGRUENT_TO_D 169 +# define RSA_R_MP_R_NOT_PRIME 170 +# define RSA_R_NO_PUBLIC_EXPONENT 140 +# define RSA_R_NULL_BEFORE_BLOCK_MISSING 113 +# define RSA_R_N_DOES_NOT_EQUAL_PRODUCT_OF_PRIMES 172 +# define RSA_R_N_DOES_NOT_EQUAL_P_Q 127 +# define RSA_R_OAEP_DECODING_ERROR 121 +# define RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE 148 +# define RSA_R_PADDING_CHECK_FAILED 114 +# define RSA_R_PKCS_DECODING_ERROR 159 +# define RSA_R_PSS_SALTLEN_TOO_SMALL 164 +# define RSA_R_P_NOT_PRIME 128 +# define RSA_R_Q_NOT_PRIME 129 +# define RSA_R_RSA_OPERATIONS_NOT_SUPPORTED 130 +# define RSA_R_SLEN_CHECK_FAILED 136 +# define RSA_R_SLEN_RECOVERY_FAILED 135 +# define RSA_R_SSLV3_ROLLBACK_ATTACK 115 +# define RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 116 +# define RSA_R_UNKNOWN_ALGORITHM_TYPE 117 +# define RSA_R_UNKNOWN_DIGEST 166 +# define RSA_R_UNKNOWN_MASK_DIGEST 151 +# define RSA_R_UNKNOWN_PADDING_TYPE 118 +# define RSA_R_UNSUPPORTED_ENCRYPTION_TYPE 162 +# define RSA_R_UNSUPPORTED_LABEL_SOURCE 163 +# define RSA_R_UNSUPPORTED_MASK_ALGORITHM 153 +# define RSA_R_UNSUPPORTED_MASK_PARAMETER 154 +# define RSA_R_UNSUPPORTED_SIGNATURE_TYPE 155 +# define RSA_R_VALUE_MISSING 147 +# define RSA_R_WRONG_SIGNATURE_LENGTH 119 + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/safestack.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/safestack.h new file mode 100644 index 000000000..38b557897 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/safestack.h @@ -0,0 +1,207 @@ +/* + * Copyright 1999-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_SAFESTACK_H +# define HEADER_SAFESTACK_H + +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# define STACK_OF(type) struct stack_st_##type + +# define SKM_DEFINE_STACK_OF(t1, t2, t3) \ + STACK_OF(t1); \ + typedef int (*sk_##t1##_compfunc)(const t3 * const *a, const t3 *const *b); \ + typedef void (*sk_##t1##_freefunc)(t3 *a); \ + typedef t3 * (*sk_##t1##_copyfunc)(const t3 *a); \ + static ossl_unused ossl_inline int sk_##t1##_num(const STACK_OF(t1) *sk) \ + { \ + return OPENSSL_sk_num((const OPENSSL_STACK *)sk); \ + } \ + static ossl_unused ossl_inline t2 *sk_##t1##_value(const STACK_OF(t1) *sk, int idx) \ + { \ + return (t2 *)OPENSSL_sk_value((const OPENSSL_STACK *)sk, idx); \ + } \ + static ossl_unused ossl_inline STACK_OF(t1) *sk_##t1##_new(sk_##t1##_compfunc compare) \ + { \ + return (STACK_OF(t1) *)OPENSSL_sk_new((OPENSSL_sk_compfunc)compare); \ + } \ + static ossl_unused ossl_inline STACK_OF(t1) *sk_##t1##_new_null(void) \ + { \ + return (STACK_OF(t1) *)OPENSSL_sk_new_null(); \ + } \ + static ossl_unused ossl_inline STACK_OF(t1) *sk_##t1##_new_reserve(sk_##t1##_compfunc compare, int n) \ + { \ + return (STACK_OF(t1) *)OPENSSL_sk_new_reserve((OPENSSL_sk_compfunc)compare, n); \ + } \ + static ossl_unused ossl_inline int sk_##t1##_reserve(STACK_OF(t1) *sk, int n) \ + { \ + return OPENSSL_sk_reserve((OPENSSL_STACK *)sk, n); \ + } \ + static ossl_unused ossl_inline void sk_##t1##_free(STACK_OF(t1) *sk) \ + { \ + OPENSSL_sk_free((OPENSSL_STACK *)sk); \ + } \ + static ossl_unused ossl_inline void sk_##t1##_zero(STACK_OF(t1) *sk) \ + { \ + OPENSSL_sk_zero((OPENSSL_STACK *)sk); \ + } \ + static ossl_unused ossl_inline t2 *sk_##t1##_delete(STACK_OF(t1) *sk, int i) \ + { \ + return (t2 *)OPENSSL_sk_delete((OPENSSL_STACK *)sk, i); \ + } \ + static ossl_unused ossl_inline t2 *sk_##t1##_delete_ptr(STACK_OF(t1) *sk, t2 *ptr) \ + { \ + return (t2 *)OPENSSL_sk_delete_ptr((OPENSSL_STACK *)sk, \ + (const void *)ptr); \ + } \ + static ossl_unused ossl_inline int sk_##t1##_push(STACK_OF(t1) *sk, t2 *ptr) \ + { \ + return OPENSSL_sk_push((OPENSSL_STACK *)sk, (const void *)ptr); \ + } \ + static ossl_unused ossl_inline int sk_##t1##_unshift(STACK_OF(t1) *sk, t2 *ptr) \ + { \ + return OPENSSL_sk_unshift((OPENSSL_STACK *)sk, (const void *)ptr); \ + } \ + static ossl_unused ossl_inline t2 *sk_##t1##_pop(STACK_OF(t1) *sk) \ + { \ + return (t2 *)OPENSSL_sk_pop((OPENSSL_STACK *)sk); \ + } \ + static ossl_unused ossl_inline t2 *sk_##t1##_shift(STACK_OF(t1) *sk) \ + { \ + return (t2 *)OPENSSL_sk_shift((OPENSSL_STACK *)sk); \ + } \ + static ossl_unused ossl_inline void sk_##t1##_pop_free(STACK_OF(t1) *sk, sk_##t1##_freefunc freefunc) \ + { \ + OPENSSL_sk_pop_free((OPENSSL_STACK *)sk, (OPENSSL_sk_freefunc)freefunc); \ + } \ + static ossl_unused ossl_inline int sk_##t1##_insert(STACK_OF(t1) *sk, t2 *ptr, int idx) \ + { \ + return OPENSSL_sk_insert((OPENSSL_STACK *)sk, (const void *)ptr, idx); \ + } \ + static ossl_unused ossl_inline t2 *sk_##t1##_set(STACK_OF(t1) *sk, int idx, t2 *ptr) \ + { \ + return (t2 *)OPENSSL_sk_set((OPENSSL_STACK *)sk, idx, (const void *)ptr); \ + } \ + static ossl_unused ossl_inline int sk_##t1##_find(STACK_OF(t1) *sk, t2 *ptr) \ + { \ + return OPENSSL_sk_find((OPENSSL_STACK *)sk, (const void *)ptr); \ + } \ + static ossl_unused ossl_inline int sk_##t1##_find_ex(STACK_OF(t1) *sk, t2 *ptr) \ + { \ + return OPENSSL_sk_find_ex((OPENSSL_STACK *)sk, (const void *)ptr); \ + } \ + static ossl_unused ossl_inline void sk_##t1##_sort(STACK_OF(t1) *sk) \ + { \ + OPENSSL_sk_sort((OPENSSL_STACK *)sk); \ + } \ + static ossl_unused ossl_inline int sk_##t1##_is_sorted(const STACK_OF(t1) *sk) \ + { \ + return OPENSSL_sk_is_sorted((const OPENSSL_STACK *)sk); \ + } \ + static ossl_unused ossl_inline STACK_OF(t1) * sk_##t1##_dup(const STACK_OF(t1) *sk) \ + { \ + return (STACK_OF(t1) *)OPENSSL_sk_dup((const OPENSSL_STACK *)sk); \ + } \ + static ossl_unused ossl_inline STACK_OF(t1) *sk_##t1##_deep_copy(const STACK_OF(t1) *sk, \ + sk_##t1##_copyfunc copyfunc, \ + sk_##t1##_freefunc freefunc) \ + { \ + return (STACK_OF(t1) *)OPENSSL_sk_deep_copy((const OPENSSL_STACK *)sk, \ + (OPENSSL_sk_copyfunc)copyfunc, \ + (OPENSSL_sk_freefunc)freefunc); \ + } \ + static ossl_unused ossl_inline sk_##t1##_compfunc sk_##t1##_set_cmp_func(STACK_OF(t1) *sk, sk_##t1##_compfunc compare) \ + { \ + return (sk_##t1##_compfunc)OPENSSL_sk_set_cmp_func((OPENSSL_STACK *)sk, (OPENSSL_sk_compfunc)compare); \ + } + +# define DEFINE_SPECIAL_STACK_OF(t1, t2) SKM_DEFINE_STACK_OF(t1, t2, t2) +# define DEFINE_STACK_OF(t) SKM_DEFINE_STACK_OF(t, t, t) +# define DEFINE_SPECIAL_STACK_OF_CONST(t1, t2) \ + SKM_DEFINE_STACK_OF(t1, const t2, t2) +# define DEFINE_STACK_OF_CONST(t) SKM_DEFINE_STACK_OF(t, const t, t) + +/*- + * Strings are special: normally an lhash entry will point to a single + * (somewhat) mutable object. In the case of strings: + * + * a) Instead of a single char, there is an array of chars, NUL-terminated. + * b) The string may have be immutable. + * + * So, they need their own declarations. Especially important for + * type-checking tools, such as Deputy. + * + * In practice, however, it appears to be hard to have a const + * string. For now, I'm settling for dealing with the fact it is a + * string at all. + */ +typedef char *OPENSSL_STRING; +typedef const char *OPENSSL_CSTRING; + +/*- + * Confusingly, LHASH_OF(STRING) deals with char ** throughout, but + * STACK_OF(STRING) is really more like STACK_OF(char), only, as mentioned + * above, instead of a single char each entry is a NUL-terminated array of + * chars. So, we have to implement STRING specially for STACK_OF. This is + * dealt with in the autogenerated macros below. + */ +DEFINE_SPECIAL_STACK_OF(OPENSSL_STRING, char) +DEFINE_SPECIAL_STACK_OF_CONST(OPENSSL_CSTRING, char) + +/* + * Similarly, we sometimes use a block of characters, NOT nul-terminated. + * These should also be distinguished from "normal" stacks. + */ +typedef void *OPENSSL_BLOCK; +DEFINE_SPECIAL_STACK_OF(OPENSSL_BLOCK, void) + +/* + * If called without higher optimization (min. -xO3) the Oracle Developer + * Studio compiler generates code for the defined (static inline) functions + * above. + * This would later lead to the linker complaining about missing symbols when + * this header file is included but the resulting object is not linked against + * the Crypto library (openssl#6912). + */ +# ifdef __SUNPRO_C +# pragma weak OPENSSL_sk_num +# pragma weak OPENSSL_sk_value +# pragma weak OPENSSL_sk_new +# pragma weak OPENSSL_sk_new_null +# pragma weak OPENSSL_sk_new_reserve +# pragma weak OPENSSL_sk_reserve +# pragma weak OPENSSL_sk_free +# pragma weak OPENSSL_sk_zero +# pragma weak OPENSSL_sk_delete +# pragma weak OPENSSL_sk_delete_ptr +# pragma weak OPENSSL_sk_push +# pragma weak OPENSSL_sk_unshift +# pragma weak OPENSSL_sk_pop +# pragma weak OPENSSL_sk_shift +# pragma weak OPENSSL_sk_pop_free +# pragma weak OPENSSL_sk_insert +# pragma weak OPENSSL_sk_set +# pragma weak OPENSSL_sk_find +# pragma weak OPENSSL_sk_find_ex +# pragma weak OPENSSL_sk_sort +# pragma weak OPENSSL_sk_is_sorted +# pragma weak OPENSSL_sk_dup +# pragma weak OPENSSL_sk_deep_copy +# pragma weak OPENSSL_sk_set_cmp_func +# endif /* __SUNPRO_C */ + +# ifdef __cplusplus +} +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/seed.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/seed.h new file mode 100644 index 000000000..de10b0857 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/seed.h @@ -0,0 +1,96 @@ +/* + * Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Copyright (c) 2007 KISA(Korea Information Security Agency). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Neither the name of author nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef HEADER_SEED_H +# define HEADER_SEED_H + +# include + +# ifndef OPENSSL_NO_SEED +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* look whether we need 'long' to get 32 bits */ +# ifdef AES_LONG +# ifndef SEED_LONG +# define SEED_LONG 1 +# endif +# endif + +# include + +# define SEED_BLOCK_SIZE 16 +# define SEED_KEY_LENGTH 16 + +typedef struct seed_key_st { +# ifdef SEED_LONG + unsigned long data[32]; +# else + unsigned int data[32]; +# endif +} SEED_KEY_SCHEDULE; + +void SEED_set_key(const unsigned char rawkey[SEED_KEY_LENGTH], + SEED_KEY_SCHEDULE *ks); + +void SEED_encrypt(const unsigned char s[SEED_BLOCK_SIZE], + unsigned char d[SEED_BLOCK_SIZE], + const SEED_KEY_SCHEDULE *ks); +void SEED_decrypt(const unsigned char s[SEED_BLOCK_SIZE], + unsigned char d[SEED_BLOCK_SIZE], + const SEED_KEY_SCHEDULE *ks); + +void SEED_ecb_encrypt(const unsigned char *in, unsigned char *out, + const SEED_KEY_SCHEDULE *ks, int enc); +void SEED_cbc_encrypt(const unsigned char *in, unsigned char *out, size_t len, + const SEED_KEY_SCHEDULE *ks, + unsigned char ivec[SEED_BLOCK_SIZE], int enc); +void SEED_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const SEED_KEY_SCHEDULE *ks, + unsigned char ivec[SEED_BLOCK_SIZE], int *num, + int enc); +void SEED_ofb128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const SEED_KEY_SCHEDULE *ks, + unsigned char ivec[SEED_BLOCK_SIZE], int *num); + +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/sha.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/sha.h new file mode 100644 index 000000000..6a1eb0de8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/sha.h @@ -0,0 +1,119 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_SHA_H +# define HEADER_SHA_H + +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/*- + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * ! SHA_LONG has to be at least 32 bits wide. ! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + */ +# define SHA_LONG unsigned int + +# define SHA_LBLOCK 16 +# define SHA_CBLOCK (SHA_LBLOCK*4)/* SHA treats input data as a + * contiguous array of 32 bit wide + * big-endian values. */ +# define SHA_LAST_BLOCK (SHA_CBLOCK-8) +# define SHA_DIGEST_LENGTH 20 + +typedef struct SHAstate_st { + SHA_LONG h0, h1, h2, h3, h4; + SHA_LONG Nl, Nh; + SHA_LONG data[SHA_LBLOCK]; + unsigned int num; +} SHA_CTX; + +int SHA1_Init(SHA_CTX *c); +int SHA1_Update(SHA_CTX *c, const void *data, size_t len); +int SHA1_Final(unsigned char *md, SHA_CTX *c); +unsigned char *SHA1(const unsigned char *d, size_t n, unsigned char *md); +void SHA1_Transform(SHA_CTX *c, const unsigned char *data); + +# define SHA256_CBLOCK (SHA_LBLOCK*4)/* SHA-256 treats input data as a + * contiguous array of 32 bit wide + * big-endian values. */ + +typedef struct SHA256state_st { + SHA_LONG h[8]; + SHA_LONG Nl, Nh; + SHA_LONG data[SHA_LBLOCK]; + unsigned int num, md_len; +} SHA256_CTX; + +int SHA224_Init(SHA256_CTX *c); +int SHA224_Update(SHA256_CTX *c, const void *data, size_t len); +int SHA224_Final(unsigned char *md, SHA256_CTX *c); +unsigned char *SHA224(const unsigned char *d, size_t n, unsigned char *md); +int SHA256_Init(SHA256_CTX *c); +int SHA256_Update(SHA256_CTX *c, const void *data, size_t len); +int SHA256_Final(unsigned char *md, SHA256_CTX *c); +unsigned char *SHA256(const unsigned char *d, size_t n, unsigned char *md); +void SHA256_Transform(SHA256_CTX *c, const unsigned char *data); + +# define SHA224_DIGEST_LENGTH 28 +# define SHA256_DIGEST_LENGTH 32 +# define SHA384_DIGEST_LENGTH 48 +# define SHA512_DIGEST_LENGTH 64 + +/* + * Unlike 32-bit digest algorithms, SHA-512 *relies* on SHA_LONG64 + * being exactly 64-bit wide. See Implementation Notes in sha512.c + * for further details. + */ +/* + * SHA-512 treats input data as a + * contiguous array of 64 bit + * wide big-endian values. + */ +# define SHA512_CBLOCK (SHA_LBLOCK*8) +# if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__) +# define SHA_LONG64 unsigned __int64 +# define U64(C) C##UI64 +# elif defined(__arch64__) +# define SHA_LONG64 unsigned long +# define U64(C) C##UL +# else +# define SHA_LONG64 unsigned long long +# define U64(C) C##ULL +# endif + +typedef struct SHA512state_st { + SHA_LONG64 h[8]; + SHA_LONG64 Nl, Nh; + union { + SHA_LONG64 d[SHA_LBLOCK]; + unsigned char p[SHA512_CBLOCK]; + } u; + unsigned int num, md_len; +} SHA512_CTX; + +int SHA384_Init(SHA512_CTX *c); +int SHA384_Update(SHA512_CTX *c, const void *data, size_t len); +int SHA384_Final(unsigned char *md, SHA512_CTX *c); +unsigned char *SHA384(const unsigned char *d, size_t n, unsigned char *md); +int SHA512_Init(SHA512_CTX *c); +int SHA512_Update(SHA512_CTX *c, const void *data, size_t len); +int SHA512_Final(unsigned char *md, SHA512_CTX *c); +unsigned char *SHA512(const unsigned char *d, size_t n, unsigned char *md); +void SHA512_Transform(SHA512_CTX *c, const unsigned char *data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/srp.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/srp.h new file mode 100644 index 000000000..aaf13558e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/srp.h @@ -0,0 +1,135 @@ +/* + * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2004, EdelKey Project. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + * + * Originally written by Christophe Renou and Peter Sylvester, + * for the EdelKey project. + */ + +#ifndef HEADER_SRP_H +# define HEADER_SRP_H + +#include + +#ifndef OPENSSL_NO_SRP +# include +# include +# include +# include +# include + +# ifdef __cplusplus +extern "C" { +# endif + +typedef struct SRP_gN_cache_st { + char *b64_bn; + BIGNUM *bn; +} SRP_gN_cache; + + +DEFINE_STACK_OF(SRP_gN_cache) + +typedef struct SRP_user_pwd_st { + /* Owned by us. */ + char *id; + BIGNUM *s; + BIGNUM *v; + /* Not owned by us. */ + const BIGNUM *g; + const BIGNUM *N; + /* Owned by us. */ + char *info; +} SRP_user_pwd; + +void SRP_user_pwd_free(SRP_user_pwd *user_pwd); + +DEFINE_STACK_OF(SRP_user_pwd) + +typedef struct SRP_VBASE_st { + STACK_OF(SRP_user_pwd) *users_pwd; + STACK_OF(SRP_gN_cache) *gN_cache; +/* to simulate a user */ + char *seed_key; + const BIGNUM *default_g; + const BIGNUM *default_N; +} SRP_VBASE; + +/* + * Internal structure storing N and g pair + */ +typedef struct SRP_gN_st { + char *id; + const BIGNUM *g; + const BIGNUM *N; +} SRP_gN; + +DEFINE_STACK_OF(SRP_gN) + +SRP_VBASE *SRP_VBASE_new(char *seed_key); +void SRP_VBASE_free(SRP_VBASE *vb); +int SRP_VBASE_init(SRP_VBASE *vb, char *verifier_file); + +/* This method ignores the configured seed and fails for an unknown user. */ +DEPRECATEDIN_1_1_0(SRP_user_pwd *SRP_VBASE_get_by_user(SRP_VBASE *vb, char *username)) +/* NOTE: unlike in SRP_VBASE_get_by_user, caller owns the returned pointer.*/ +SRP_user_pwd *SRP_VBASE_get1_by_user(SRP_VBASE *vb, char *username); + +char *SRP_create_verifier(const char *user, const char *pass, char **salt, + char **verifier, const char *N, const char *g); +int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt, + BIGNUM **verifier, const BIGNUM *N, + const BIGNUM *g); + +# define SRP_NO_ERROR 0 +# define SRP_ERR_VBASE_INCOMPLETE_FILE 1 +# define SRP_ERR_VBASE_BN_LIB 2 +# define SRP_ERR_OPEN_FILE 3 +# define SRP_ERR_MEMORY 4 + +# define DB_srptype 0 +# define DB_srpverifier 1 +# define DB_srpsalt 2 +# define DB_srpid 3 +# define DB_srpgN 4 +# define DB_srpinfo 5 +# undef DB_NUMBER +# define DB_NUMBER 6 + +# define DB_SRP_INDEX 'I' +# define DB_SRP_VALID 'V' +# define DB_SRP_REVOKED 'R' +# define DB_SRP_MODIF 'v' + +/* see srp.c */ +char *SRP_check_known_gN_param(const BIGNUM *g, const BIGNUM *N); +SRP_gN *SRP_get_default_gN(const char *id); + +/* server side .... */ +BIGNUM *SRP_Calc_server_key(const BIGNUM *A, const BIGNUM *v, const BIGNUM *u, + const BIGNUM *b, const BIGNUM *N); +BIGNUM *SRP_Calc_B(const BIGNUM *b, const BIGNUM *N, const BIGNUM *g, + const BIGNUM *v); +int SRP_Verify_A_mod_N(const BIGNUM *A, const BIGNUM *N); +BIGNUM *SRP_Calc_u(const BIGNUM *A, const BIGNUM *B, const BIGNUM *N); + +/* client side .... */ +BIGNUM *SRP_Calc_x(const BIGNUM *s, const char *user, const char *pass); +BIGNUM *SRP_Calc_A(const BIGNUM *a, const BIGNUM *N, const BIGNUM *g); +BIGNUM *SRP_Calc_client_key(const BIGNUM *N, const BIGNUM *B, const BIGNUM *g, + const BIGNUM *x, const BIGNUM *a, const BIGNUM *u); +int SRP_Verify_B_mod_N(const BIGNUM *B, const BIGNUM *N); + +# define SRP_MINIMAL_N 1024 + +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/srtp.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/srtp.h new file mode 100644 index 000000000..0b57c2356 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/srtp.h @@ -0,0 +1,50 @@ +/* + * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * DTLS code by Eric Rescorla + * + * Copyright (C) 2006, Network Resonance, Inc. Copyright (C) 2011, RTFM, Inc. + */ + +#ifndef HEADER_D1_SRTP_H +# define HEADER_D1_SRTP_H + +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# define SRTP_AES128_CM_SHA1_80 0x0001 +# define SRTP_AES128_CM_SHA1_32 0x0002 +# define SRTP_AES128_F8_SHA1_80 0x0003 +# define SRTP_AES128_F8_SHA1_32 0x0004 +# define SRTP_NULL_SHA1_80 0x0005 +# define SRTP_NULL_SHA1_32 0x0006 + +/* AEAD SRTP protection profiles from RFC 7714 */ +# define SRTP_AEAD_AES_128_GCM 0x0007 +# define SRTP_AEAD_AES_256_GCM 0x0008 + +# ifndef OPENSSL_NO_SRTP + +__owur int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx, const char *profiles); +__owur int SSL_set_tlsext_use_srtp(SSL *ssl, const char *profiles); + +__owur STACK_OF(SRTP_PROTECTION_PROFILE) *SSL_get_srtp_profiles(SSL *ssl); +__owur SRTP_PROTECTION_PROFILE *SSL_get_selected_srtp_profile(SSL *s); + +# endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/ssl.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ssl.h new file mode 100644 index 000000000..48e1152a2 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ssl.h @@ -0,0 +1,2438 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * Copyright 2005 Nokia. All rights reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_SSL_H +# define HEADER_SSL_H + +# include +# include +# include +# include +# if OPENSSL_API_COMPAT < 0x10100000L +# include +# include +# include +# endif +# include +# include +# include +# include + +# include +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* OpenSSL version number for ASN.1 encoding of the session information */ +/*- + * Version 0 - initial version + * Version 1 - added the optional peer certificate + */ +# define SSL_SESSION_ASN1_VERSION 0x0001 + +# define SSL_MAX_SSL_SESSION_ID_LENGTH 32 +# define SSL_MAX_SID_CTX_LENGTH 32 + +# define SSL_MIN_RSA_MODULUS_LENGTH_IN_BYTES (512/8) +# define SSL_MAX_KEY_ARG_LENGTH 8 +# define SSL_MAX_MASTER_KEY_LENGTH 48 + +/* The maximum number of encrypt/decrypt pipelines we can support */ +# define SSL_MAX_PIPELINES 32 + +/* text strings for the ciphers */ + +/* These are used to specify which ciphers to use and not to use */ + +# define SSL_TXT_LOW "LOW" +# define SSL_TXT_MEDIUM "MEDIUM" +# define SSL_TXT_HIGH "HIGH" +# define SSL_TXT_FIPS "FIPS" + +# define SSL_TXT_aNULL "aNULL" +# define SSL_TXT_eNULL "eNULL" +# define SSL_TXT_NULL "NULL" + +# define SSL_TXT_kRSA "kRSA" +# define SSL_TXT_kDHr "kDHr"/* this cipher class has been removed */ +# define SSL_TXT_kDHd "kDHd"/* this cipher class has been removed */ +# define SSL_TXT_kDH "kDH"/* this cipher class has been removed */ +# define SSL_TXT_kEDH "kEDH"/* alias for kDHE */ +# define SSL_TXT_kDHE "kDHE" +# define SSL_TXT_kECDHr "kECDHr"/* this cipher class has been removed */ +# define SSL_TXT_kECDHe "kECDHe"/* this cipher class has been removed */ +# define SSL_TXT_kECDH "kECDH"/* this cipher class has been removed */ +# define SSL_TXT_kEECDH "kEECDH"/* alias for kECDHE */ +# define SSL_TXT_kECDHE "kECDHE" +# define SSL_TXT_kPSK "kPSK" +# define SSL_TXT_kRSAPSK "kRSAPSK" +# define SSL_TXT_kECDHEPSK "kECDHEPSK" +# define SSL_TXT_kDHEPSK "kDHEPSK" +# define SSL_TXT_kGOST "kGOST" +# define SSL_TXT_kSRP "kSRP" + +# define SSL_TXT_aRSA "aRSA" +# define SSL_TXT_aDSS "aDSS" +# define SSL_TXT_aDH "aDH"/* this cipher class has been removed */ +# define SSL_TXT_aECDH "aECDH"/* this cipher class has been removed */ +# define SSL_TXT_aECDSA "aECDSA" +# define SSL_TXT_aPSK "aPSK" +# define SSL_TXT_aGOST94 "aGOST94" +# define SSL_TXT_aGOST01 "aGOST01" +# define SSL_TXT_aGOST12 "aGOST12" +# define SSL_TXT_aGOST "aGOST" +# define SSL_TXT_aSRP "aSRP" + +# define SSL_TXT_DSS "DSS" +# define SSL_TXT_DH "DH" +# define SSL_TXT_DHE "DHE"/* same as "kDHE:-ADH" */ +# define SSL_TXT_EDH "EDH"/* alias for DHE */ +# define SSL_TXT_ADH "ADH" +# define SSL_TXT_RSA "RSA" +# define SSL_TXT_ECDH "ECDH" +# define SSL_TXT_EECDH "EECDH"/* alias for ECDHE" */ +# define SSL_TXT_ECDHE "ECDHE"/* same as "kECDHE:-AECDH" */ +# define SSL_TXT_AECDH "AECDH" +# define SSL_TXT_ECDSA "ECDSA" +# define SSL_TXT_PSK "PSK" +# define SSL_TXT_SRP "SRP" + +# define SSL_TXT_DES "DES" +# define SSL_TXT_3DES "3DES" +# define SSL_TXT_RC4 "RC4" +# define SSL_TXT_RC2 "RC2" +# define SSL_TXT_IDEA "IDEA" +# define SSL_TXT_SEED "SEED" +# define SSL_TXT_AES128 "AES128" +# define SSL_TXT_AES256 "AES256" +# define SSL_TXT_AES "AES" +# define SSL_TXT_AES_GCM "AESGCM" +# define SSL_TXT_AES_CCM "AESCCM" +# define SSL_TXT_AES_CCM_8 "AESCCM8" +# define SSL_TXT_CAMELLIA128 "CAMELLIA128" +# define SSL_TXT_CAMELLIA256 "CAMELLIA256" +# define SSL_TXT_CAMELLIA "CAMELLIA" +# define SSL_TXT_CHACHA20 "CHACHA20" +# define SSL_TXT_GOST "GOST89" +# define SSL_TXT_ARIA "ARIA" +# define SSL_TXT_ARIA_GCM "ARIAGCM" +# define SSL_TXT_ARIA128 "ARIA128" +# define SSL_TXT_ARIA256 "ARIA256" + +# define SSL_TXT_MD5 "MD5" +# define SSL_TXT_SHA1 "SHA1" +# define SSL_TXT_SHA "SHA"/* same as "SHA1" */ +# define SSL_TXT_GOST94 "GOST94" +# define SSL_TXT_GOST89MAC "GOST89MAC" +# define SSL_TXT_GOST12 "GOST12" +# define SSL_TXT_GOST89MAC12 "GOST89MAC12" +# define SSL_TXT_SHA256 "SHA256" +# define SSL_TXT_SHA384 "SHA384" + +# define SSL_TXT_SSLV3 "SSLv3" +# define SSL_TXT_TLSV1 "TLSv1" +# define SSL_TXT_TLSV1_1 "TLSv1.1" +# define SSL_TXT_TLSV1_2 "TLSv1.2" + +# define SSL_TXT_ALL "ALL" + +/*- + * COMPLEMENTOF* definitions. These identifiers are used to (de-select) + * ciphers normally not being used. + * Example: "RC4" will activate all ciphers using RC4 including ciphers + * without authentication, which would normally disabled by DEFAULT (due + * the "!ADH" being part of default). Therefore "RC4:!COMPLEMENTOFDEFAULT" + * will make sure that it is also disabled in the specific selection. + * COMPLEMENTOF* identifiers are portable between version, as adjustments + * to the default cipher setup will also be included here. + * + * COMPLEMENTOFDEFAULT does not experience the same special treatment that + * DEFAULT gets, as only selection is being done and no sorting as needed + * for DEFAULT. + */ +# define SSL_TXT_CMPALL "COMPLEMENTOFALL" +# define SSL_TXT_CMPDEF "COMPLEMENTOFDEFAULT" + +/* + * The following cipher list is used by default. It also is substituted when + * an application-defined cipher list string starts with 'DEFAULT'. + * This applies to ciphersuites for TLSv1.2 and below. + */ +# define SSL_DEFAULT_CIPHER_LIST "ALL:!COMPLEMENTOFDEFAULT:!eNULL" +/* This is the default set of TLSv1.3 ciphersuites */ +# if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305) +# define TLS_DEFAULT_CIPHERSUITES "TLS_AES_256_GCM_SHA384:" \ + "TLS_CHACHA20_POLY1305_SHA256:" \ + "TLS_AES_128_GCM_SHA256" +# else +# define TLS_DEFAULT_CIPHERSUITES "TLS_AES_256_GCM_SHA384:" \ + "TLS_AES_128_GCM_SHA256" +#endif +/* + * As of OpenSSL 1.0.0, ssl_create_cipher_list() in ssl/ssl_ciph.c always + * starts with a reasonable order, and all we have to do for DEFAULT is + * throwing out anonymous and unencrypted ciphersuites! (The latter are not + * actually enabled by ALL, but "ALL:RSA" would enable some of them.) + */ + +/* Used in SSL_set_shutdown()/SSL_get_shutdown(); */ +# define SSL_SENT_SHUTDOWN 1 +# define SSL_RECEIVED_SHUTDOWN 2 + +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +# define SSL_FILETYPE_ASN1 X509_FILETYPE_ASN1 +# define SSL_FILETYPE_PEM X509_FILETYPE_PEM + +/* + * This is needed to stop compilers complaining about the 'struct ssl_st *' + * function parameters used to prototype callbacks in SSL_CTX. + */ +typedef struct ssl_st *ssl_crock_st; +typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT; +typedef struct ssl_method_st SSL_METHOD; +typedef struct ssl_cipher_st SSL_CIPHER; +typedef struct ssl_session_st SSL_SESSION; +typedef struct tls_sigalgs_st TLS_SIGALGS; +typedef struct ssl_conf_ctx_st SSL_CONF_CTX; +typedef struct ssl_comp_st SSL_COMP; + +STACK_OF(SSL_CIPHER); +STACK_OF(SSL_COMP); + +/* SRTP protection profiles for use with the use_srtp extension (RFC 5764)*/ +typedef struct srtp_protection_profile_st { + const char *name; + unsigned long id; +} SRTP_PROTECTION_PROFILE; + +DEFINE_STACK_OF(SRTP_PROTECTION_PROFILE) + +typedef int (*tls_session_ticket_ext_cb_fn)(SSL *s, const unsigned char *data, + int len, void *arg); +typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, + STACK_OF(SSL_CIPHER) *peer_ciphers, + const SSL_CIPHER **cipher, void *arg); + +/* Extension context codes */ +/* This extension is only allowed in TLS */ +#define SSL_EXT_TLS_ONLY 0x0001 +/* This extension is only allowed in DTLS */ +#define SSL_EXT_DTLS_ONLY 0x0002 +/* Some extensions may be allowed in DTLS but we don't implement them for it */ +#define SSL_EXT_TLS_IMPLEMENTATION_ONLY 0x0004 +/* Most extensions are not defined for SSLv3 but EXT_TYPE_renegotiate is */ +#define SSL_EXT_SSL3_ALLOWED 0x0008 +/* Extension is only defined for TLS1.2 and below */ +#define SSL_EXT_TLS1_2_AND_BELOW_ONLY 0x0010 +/* Extension is only defined for TLS1.3 and above */ +#define SSL_EXT_TLS1_3_ONLY 0x0020 +/* Ignore this extension during parsing if we are resuming */ +#define SSL_EXT_IGNORE_ON_RESUMPTION 0x0040 +#define SSL_EXT_CLIENT_HELLO 0x0080 +/* Really means TLS1.2 or below */ +#define SSL_EXT_TLS1_2_SERVER_HELLO 0x0100 +#define SSL_EXT_TLS1_3_SERVER_HELLO 0x0200 +#define SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS 0x0400 +#define SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST 0x0800 +#define SSL_EXT_TLS1_3_CERTIFICATE 0x1000 +#define SSL_EXT_TLS1_3_NEW_SESSION_TICKET 0x2000 +#define SSL_EXT_TLS1_3_CERTIFICATE_REQUEST 0x4000 + +/* Typedefs for handling custom extensions */ + +typedef int (*custom_ext_add_cb)(SSL *s, unsigned int ext_type, + const unsigned char **out, size_t *outlen, + int *al, void *add_arg); + +typedef void (*custom_ext_free_cb)(SSL *s, unsigned int ext_type, + const unsigned char *out, void *add_arg); + +typedef int (*custom_ext_parse_cb)(SSL *s, unsigned int ext_type, + const unsigned char *in, size_t inlen, + int *al, void *parse_arg); + + +typedef int (*SSL_custom_ext_add_cb_ex)(SSL *s, unsigned int ext_type, + unsigned int context, + const unsigned char **out, + size_t *outlen, X509 *x, + size_t chainidx, + int *al, void *add_arg); + +typedef void (*SSL_custom_ext_free_cb_ex)(SSL *s, unsigned int ext_type, + unsigned int context, + const unsigned char *out, + void *add_arg); + +typedef int (*SSL_custom_ext_parse_cb_ex)(SSL *s, unsigned int ext_type, + unsigned int context, + const unsigned char *in, + size_t inlen, X509 *x, + size_t chainidx, + int *al, void *parse_arg); + +/* Typedef for verification callback */ +typedef int (*SSL_verify_cb)(int preverify_ok, X509_STORE_CTX *x509_ctx); + +/* + * Some values are reserved until OpenSSL 1.2.0 because they were previously + * included in SSL_OP_ALL in a 1.1.x release. + * + * Reserved value (until OpenSSL 1.2.0) 0x00000001U + * Reserved value (until OpenSSL 1.2.0) 0x00000002U + */ +/* Allow initial connection to servers that don't support RI */ +# define SSL_OP_LEGACY_SERVER_CONNECT 0x00000004U + +/* Reserved value (until OpenSSL 1.2.0) 0x00000008U */ +# define SSL_OP_TLSEXT_PADDING 0x00000010U +/* Reserved value (until OpenSSL 1.2.0) 0x00000020U */ +# define SSL_OP_SAFARI_ECDHE_ECDSA_BUG 0x00000040U +/* + * Reserved value (until OpenSSL 1.2.0) 0x00000080U + * Reserved value (until OpenSSL 1.2.0) 0x00000100U + * Reserved value (until OpenSSL 1.2.0) 0x00000200U + */ + +/* In TLSv1.3 allow a non-(ec)dhe based kex_mode */ +# define SSL_OP_ALLOW_NO_DHE_KEX 0x00000400U + +/* + * Disable SSL 3.0/TLS 1.0 CBC vulnerability workaround that was added in + * OpenSSL 0.9.6d. Usually (depending on the application protocol) the + * workaround is not needed. Unfortunately some broken SSL/TLS + * implementations cannot handle it at all, which is why we include it in + * SSL_OP_ALL. Added in 0.9.6e + */ +# define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 0x00000800U + +/* DTLS options */ +# define SSL_OP_NO_QUERY_MTU 0x00001000U +/* Turn on Cookie Exchange (on relevant for servers) */ +# define SSL_OP_COOKIE_EXCHANGE 0x00002000U +/* Don't use RFC4507 ticket extension */ +# define SSL_OP_NO_TICKET 0x00004000U +# ifndef OPENSSL_NO_DTLS1_METHOD +/* Use Cisco's "speshul" version of DTLS_BAD_VER + * (only with deprecated DTLSv1_client_method()) */ +# define SSL_OP_CISCO_ANYCONNECT 0x00008000U +# endif + +/* As server, disallow session resumption on renegotiation */ +# define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0x00010000U +/* Don't use compression even if supported */ +# define SSL_OP_NO_COMPRESSION 0x00020000U +/* Permit unsafe legacy renegotiation */ +# define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x00040000U +/* Disable encrypt-then-mac */ +# define SSL_OP_NO_ENCRYPT_THEN_MAC 0x00080000U + +/* + * Enable TLSv1.3 Compatibility mode. This is on by default. A future version + * of OpenSSL may have this disabled by default. + */ +# define SSL_OP_ENABLE_MIDDLEBOX_COMPAT 0x00100000U + +/* Prioritize Chacha20Poly1305 when client does. + * Modifies SSL_OP_CIPHER_SERVER_PREFERENCE */ +# define SSL_OP_PRIORITIZE_CHACHA 0x00200000U + +/* + * Set on servers to choose the cipher according to the server's preferences + */ +# define SSL_OP_CIPHER_SERVER_PREFERENCE 0x00400000U +/* + * If set, a server will allow a client to issue a SSLv3.0 version number as + * latest version supported in the premaster secret, even when TLSv1.0 + * (version 3.1) was announced in the client hello. Normally this is + * forbidden to prevent version rollback attacks. + */ +# define SSL_OP_TLS_ROLLBACK_BUG 0x00800000U + +/* + * Switches off automatic TLSv1.3 anti-replay protection for early data. This + * is a server-side option only (no effect on the client). + */ +# define SSL_OP_NO_ANTI_REPLAY 0x01000000U + +# define SSL_OP_NO_SSLv3 0x02000000U +# define SSL_OP_NO_TLSv1 0x04000000U +# define SSL_OP_NO_TLSv1_2 0x08000000U +# define SSL_OP_NO_TLSv1_1 0x10000000U +# define SSL_OP_NO_TLSv1_3 0x20000000U + +# define SSL_OP_NO_DTLSv1 0x04000000U +# define SSL_OP_NO_DTLSv1_2 0x08000000U + +# define SSL_OP_NO_SSL_MASK (SSL_OP_NO_SSLv3|\ + SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2|SSL_OP_NO_TLSv1_3) +# define SSL_OP_NO_DTLS_MASK (SSL_OP_NO_DTLSv1|SSL_OP_NO_DTLSv1_2) + +/* Disallow all renegotiation */ +# define SSL_OP_NO_RENEGOTIATION 0x40000000U + +/* + * Make server add server-hello extension from early version of cryptopro + * draft, when GOST ciphersuite is negotiated. Required for interoperability + * with CryptoPro CSP 3.x + */ +# define SSL_OP_CRYPTOPRO_TLSEXT_BUG 0x80000000U + +/* + * SSL_OP_ALL: various bug workarounds that should be rather harmless. + * This used to be 0x000FFFFFL before 0.9.7. + * This used to be 0x80000BFFU before 1.1.1. + */ +# define SSL_OP_ALL (SSL_OP_CRYPTOPRO_TLSEXT_BUG|\ + SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS|\ + SSL_OP_LEGACY_SERVER_CONNECT|\ + SSL_OP_TLSEXT_PADDING|\ + SSL_OP_SAFARI_ECDHE_ECDSA_BUG) + +/* OBSOLETE OPTIONS: retained for compatibility */ + +/* Removed from OpenSSL 1.1.0. Was 0x00000001L */ +/* Related to removed SSLv2. */ +# define SSL_OP_MICROSOFT_SESS_ID_BUG 0x0 +/* Removed from OpenSSL 1.1.0. Was 0x00000002L */ +/* Related to removed SSLv2. */ +# define SSL_OP_NETSCAPE_CHALLENGE_BUG 0x0 +/* Removed from OpenSSL 0.9.8q and 1.0.0c. Was 0x00000008L */ +/* Dead forever, see CVE-2010-4180 */ +# define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 0x0 +/* Removed from OpenSSL 1.0.1h and 1.0.2. Was 0x00000010L */ +/* Refers to ancient SSLREF and SSLv2. */ +# define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 0x0 +/* Removed from OpenSSL 1.1.0. Was 0x00000020 */ +# define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 0x0 +/* Removed from OpenSSL 0.9.7h and 0.9.8b. Was 0x00000040L */ +# define SSL_OP_MSIE_SSLV2_RSA_PADDING 0x0 +/* Removed from OpenSSL 1.1.0. Was 0x00000080 */ +/* Ancient SSLeay version. */ +# define SSL_OP_SSLEAY_080_CLIENT_DH_BUG 0x0 +/* Removed from OpenSSL 1.1.0. Was 0x00000100L */ +# define SSL_OP_TLS_D5_BUG 0x0 +/* Removed from OpenSSL 1.1.0. Was 0x00000200L */ +# define SSL_OP_TLS_BLOCK_PADDING_BUG 0x0 +/* Removed from OpenSSL 1.1.0. Was 0x00080000L */ +# define SSL_OP_SINGLE_ECDH_USE 0x0 +/* Removed from OpenSSL 1.1.0. Was 0x00100000L */ +# define SSL_OP_SINGLE_DH_USE 0x0 +/* Removed from OpenSSL 1.0.1k and 1.0.2. Was 0x00200000L */ +# define SSL_OP_EPHEMERAL_RSA 0x0 +/* Removed from OpenSSL 1.1.0. Was 0x01000000L */ +# define SSL_OP_NO_SSLv2 0x0 +/* Removed from OpenSSL 1.0.1. Was 0x08000000L */ +# define SSL_OP_PKCS1_CHECK_1 0x0 +/* Removed from OpenSSL 1.0.1. Was 0x10000000L */ +# define SSL_OP_PKCS1_CHECK_2 0x0 +/* Removed from OpenSSL 1.1.0. Was 0x20000000L */ +# define SSL_OP_NETSCAPE_CA_DN_BUG 0x0 +/* Removed from OpenSSL 1.1.0. Was 0x40000000L */ +# define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0x0 + +/* + * Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success + * when just a single record has been written): + */ +# define SSL_MODE_ENABLE_PARTIAL_WRITE 0x00000001U +/* + * Make it possible to retry SSL_write() with changed buffer location (buffer + * contents must stay the same!); this is not the default to avoid the + * misconception that non-blocking SSL_write() behaves like non-blocking + * write(): + */ +# define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 0x00000002U +/* + * Never bother the application with retries if the transport is blocking: + */ +# define SSL_MODE_AUTO_RETRY 0x00000004U +/* Don't attempt to automatically build certificate chain */ +# define SSL_MODE_NO_AUTO_CHAIN 0x00000008U +/* + * Save RAM by releasing read and write buffers when they're empty. (SSL3 and + * TLS only.) Released buffers are freed. + */ +# define SSL_MODE_RELEASE_BUFFERS 0x00000010U +/* + * Send the current time in the Random fields of the ClientHello and + * ServerHello records for compatibility with hypothetical implementations + * that require it. + */ +# define SSL_MODE_SEND_CLIENTHELLO_TIME 0x00000020U +# define SSL_MODE_SEND_SERVERHELLO_TIME 0x00000040U +/* + * Send TLS_FALLBACK_SCSV in the ClientHello. To be set only by applications + * that reconnect with a downgraded protocol version; see + * draft-ietf-tls-downgrade-scsv-00 for details. DO NOT ENABLE THIS if your + * application attempts a normal handshake. Only use this in explicit + * fallback retries, following the guidance in + * draft-ietf-tls-downgrade-scsv-00. + */ +# define SSL_MODE_SEND_FALLBACK_SCSV 0x00000080U +/* + * Support Asynchronous operation + */ +# define SSL_MODE_ASYNC 0x00000100U + +/* + * When using DTLS/SCTP, include the terminating zero in the label + * used for computing the endpoint-pair shared secret. Required for + * interoperability with implementations having this bug like these + * older version of OpenSSL: + * - OpenSSL 1.0.0 series + * - OpenSSL 1.0.1 series + * - OpenSSL 1.0.2 series + * - OpenSSL 1.1.0 series + * - OpenSSL 1.1.1 and 1.1.1a + */ +# define SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG 0x00000400U + +/* Cert related flags */ +/* + * Many implementations ignore some aspects of the TLS standards such as + * enforcing certificate chain algorithms. When this is set we enforce them. + */ +# define SSL_CERT_FLAG_TLS_STRICT 0x00000001U + +/* Suite B modes, takes same values as certificate verify flags */ +# define SSL_CERT_FLAG_SUITEB_128_LOS_ONLY 0x10000 +/* Suite B 192 bit only mode */ +# define SSL_CERT_FLAG_SUITEB_192_LOS 0x20000 +/* Suite B 128 bit mode allowing 192 bit algorithms */ +# define SSL_CERT_FLAG_SUITEB_128_LOS 0x30000 + +/* Perform all sorts of protocol violations for testing purposes */ +# define SSL_CERT_FLAG_BROKEN_PROTOCOL 0x10000000 + +/* Flags for building certificate chains */ +/* Treat any existing certificates as untrusted CAs */ +# define SSL_BUILD_CHAIN_FLAG_UNTRUSTED 0x1 +/* Don't include root CA in chain */ +# define SSL_BUILD_CHAIN_FLAG_NO_ROOT 0x2 +/* Just check certificates already there */ +# define SSL_BUILD_CHAIN_FLAG_CHECK 0x4 +/* Ignore verification errors */ +# define SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR 0x8 +/* Clear verification errors from queue */ +# define SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR 0x10 + +/* Flags returned by SSL_check_chain */ +/* Certificate can be used with this session */ +# define CERT_PKEY_VALID 0x1 +/* Certificate can also be used for signing */ +# define CERT_PKEY_SIGN 0x2 +/* EE certificate signing algorithm OK */ +# define CERT_PKEY_EE_SIGNATURE 0x10 +/* CA signature algorithms OK */ +# define CERT_PKEY_CA_SIGNATURE 0x20 +/* EE certificate parameters OK */ +# define CERT_PKEY_EE_PARAM 0x40 +/* CA certificate parameters OK */ +# define CERT_PKEY_CA_PARAM 0x80 +/* Signing explicitly allowed as opposed to SHA1 fallback */ +# define CERT_PKEY_EXPLICIT_SIGN 0x100 +/* Client CA issuer names match (always set for server cert) */ +# define CERT_PKEY_ISSUER_NAME 0x200 +/* Cert type matches client types (always set for server cert) */ +# define CERT_PKEY_CERT_TYPE 0x400 +/* Cert chain suitable to Suite B */ +# define CERT_PKEY_SUITEB 0x800 + +# define SSL_CONF_FLAG_CMDLINE 0x1 +# define SSL_CONF_FLAG_FILE 0x2 +# define SSL_CONF_FLAG_CLIENT 0x4 +# define SSL_CONF_FLAG_SERVER 0x8 +# define SSL_CONF_FLAG_SHOW_ERRORS 0x10 +# define SSL_CONF_FLAG_CERTIFICATE 0x20 +# define SSL_CONF_FLAG_REQUIRE_PRIVATE 0x40 +/* Configuration value types */ +# define SSL_CONF_TYPE_UNKNOWN 0x0 +# define SSL_CONF_TYPE_STRING 0x1 +# define SSL_CONF_TYPE_FILE 0x2 +# define SSL_CONF_TYPE_DIR 0x3 +# define SSL_CONF_TYPE_NONE 0x4 + +/* Maximum length of the application-controlled segment of a a TLSv1.3 cookie */ +# define SSL_COOKIE_LENGTH 4096 + +/* + * Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value, they + * cannot be used to clear bits. + */ + +unsigned long SSL_CTX_get_options(const SSL_CTX *ctx); +unsigned long SSL_get_options(const SSL *s); +unsigned long SSL_CTX_clear_options(SSL_CTX *ctx, unsigned long op); +unsigned long SSL_clear_options(SSL *s, unsigned long op); +unsigned long SSL_CTX_set_options(SSL_CTX *ctx, unsigned long op); +unsigned long SSL_set_options(SSL *s, unsigned long op); + +# define SSL_CTX_set_mode(ctx,op) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL) +# define SSL_CTX_clear_mode(ctx,op) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_MODE,(op),NULL) +# define SSL_CTX_get_mode(ctx) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,0,NULL) +# define SSL_clear_mode(ssl,op) \ + SSL_ctrl((ssl),SSL_CTRL_CLEAR_MODE,(op),NULL) +# define SSL_set_mode(ssl,op) \ + SSL_ctrl((ssl),SSL_CTRL_MODE,(op),NULL) +# define SSL_get_mode(ssl) \ + SSL_ctrl((ssl),SSL_CTRL_MODE,0,NULL) +# define SSL_set_mtu(ssl, mtu) \ + SSL_ctrl((ssl),SSL_CTRL_SET_MTU,(mtu),NULL) +# define DTLS_set_link_mtu(ssl, mtu) \ + SSL_ctrl((ssl),DTLS_CTRL_SET_LINK_MTU,(mtu),NULL) +# define DTLS_get_link_min_mtu(ssl) \ + SSL_ctrl((ssl),DTLS_CTRL_GET_LINK_MIN_MTU,0,NULL) + +# define SSL_get_secure_renegotiation_support(ssl) \ + SSL_ctrl((ssl), SSL_CTRL_GET_RI_SUPPORT, 0, NULL) + +# ifndef OPENSSL_NO_HEARTBEATS +# define SSL_heartbeat(ssl) \ + SSL_ctrl((ssl),SSL_CTRL_DTLS_EXT_SEND_HEARTBEAT,0,NULL) +# endif + +# define SSL_CTX_set_cert_flags(ctx,op) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_CERT_FLAGS,(op),NULL) +# define SSL_set_cert_flags(s,op) \ + SSL_ctrl((s),SSL_CTRL_CERT_FLAGS,(op),NULL) +# define SSL_CTX_clear_cert_flags(ctx,op) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_CERT_FLAGS,(op),NULL) +# define SSL_clear_cert_flags(s,op) \ + SSL_ctrl((s),SSL_CTRL_CLEAR_CERT_FLAGS,(op),NULL) + +void SSL_CTX_set_msg_callback(SSL_CTX *ctx, + void (*cb) (int write_p, int version, + int content_type, const void *buf, + size_t len, SSL *ssl, void *arg)); +void SSL_set_msg_callback(SSL *ssl, + void (*cb) (int write_p, int version, + int content_type, const void *buf, + size_t len, SSL *ssl, void *arg)); +# define SSL_CTX_set_msg_callback_arg(ctx, arg) SSL_CTX_ctrl((ctx), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg)) +# define SSL_set_msg_callback_arg(ssl, arg) SSL_ctrl((ssl), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg)) + +# define SSL_get_extms_support(s) \ + SSL_ctrl((s),SSL_CTRL_GET_EXTMS_SUPPORT,0,NULL) + +# ifndef OPENSSL_NO_SRP + +/* see tls_srp.c */ +__owur int SSL_SRP_CTX_init(SSL *s); +__owur int SSL_CTX_SRP_CTX_init(SSL_CTX *ctx); +int SSL_SRP_CTX_free(SSL *ctx); +int SSL_CTX_SRP_CTX_free(SSL_CTX *ctx); +__owur int SSL_srp_server_param_with_username(SSL *s, int *ad); +__owur int SRP_Calc_A_param(SSL *s); + +# endif + +/* 100k max cert list */ +# define SSL_MAX_CERT_LIST_DEFAULT 1024*100 + +# define SSL_SESSION_CACHE_MAX_SIZE_DEFAULT (1024*20) + +/* + * This callback type is used inside SSL_CTX, SSL, and in the functions that + * set them. It is used to override the generation of SSL/TLS session IDs in + * a server. Return value should be zero on an error, non-zero to proceed. + * Also, callbacks should themselves check if the id they generate is unique + * otherwise the SSL handshake will fail with an error - callbacks can do + * this using the 'ssl' value they're passed by; + * SSL_has_matching_session_id(ssl, id, *id_len) The length value passed in + * is set at the maximum size the session ID can be. In SSLv3/TLSv1 it is 32 + * bytes. The callback can alter this length to be less if desired. It is + * also an error for the callback to set the size to zero. + */ +typedef int (*GEN_SESSION_CB) (SSL *ssl, unsigned char *id, + unsigned int *id_len); + +# define SSL_SESS_CACHE_OFF 0x0000 +# define SSL_SESS_CACHE_CLIENT 0x0001 +# define SSL_SESS_CACHE_SERVER 0x0002 +# define SSL_SESS_CACHE_BOTH (SSL_SESS_CACHE_CLIENT|SSL_SESS_CACHE_SERVER) +# define SSL_SESS_CACHE_NO_AUTO_CLEAR 0x0080 +/* enough comments already ... see SSL_CTX_set_session_cache_mode(3) */ +# define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP 0x0100 +# define SSL_SESS_CACHE_NO_INTERNAL_STORE 0x0200 +# define SSL_SESS_CACHE_NO_INTERNAL \ + (SSL_SESS_CACHE_NO_INTERNAL_LOOKUP|SSL_SESS_CACHE_NO_INTERNAL_STORE) + +LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx); +# define SSL_CTX_sess_number(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_NUMBER,0,NULL) +# define SSL_CTX_sess_connect(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT,0,NULL) +# define SSL_CTX_sess_connect_good(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_GOOD,0,NULL) +# define SSL_CTX_sess_connect_renegotiate(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_RENEGOTIATE,0,NULL) +# define SSL_CTX_sess_accept(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT,0,NULL) +# define SSL_CTX_sess_accept_renegotiate(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_RENEGOTIATE,0,NULL) +# define SSL_CTX_sess_accept_good(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_GOOD,0,NULL) +# define SSL_CTX_sess_hits(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_HIT,0,NULL) +# define SSL_CTX_sess_cb_hits(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CB_HIT,0,NULL) +# define SSL_CTX_sess_misses(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_MISSES,0,NULL) +# define SSL_CTX_sess_timeouts(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_TIMEOUTS,0,NULL) +# define SSL_CTX_sess_cache_full(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CACHE_FULL,0,NULL) + +void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx, + int (*new_session_cb) (struct ssl_st *ssl, + SSL_SESSION *sess)); +int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx)) (struct ssl_st *ssl, + SSL_SESSION *sess); +void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx, + void (*remove_session_cb) (struct ssl_ctx_st + *ctx, + SSL_SESSION *sess)); +void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx)) (struct ssl_ctx_st *ctx, + SSL_SESSION *sess); +void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx, + SSL_SESSION *(*get_session_cb) (struct ssl_st + *ssl, + const unsigned char + *data, int len, + int *copy)); +SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx)) (struct ssl_st *ssl, + const unsigned char *data, + int len, int *copy); +void SSL_CTX_set_info_callback(SSL_CTX *ctx, + void (*cb) (const SSL *ssl, int type, int val)); +void (*SSL_CTX_get_info_callback(SSL_CTX *ctx)) (const SSL *ssl, int type, + int val); +void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, + int (*client_cert_cb) (SSL *ssl, X509 **x509, + EVP_PKEY **pkey)); +int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx)) (SSL *ssl, X509 **x509, + EVP_PKEY **pkey); +# ifndef OPENSSL_NO_ENGINE +__owur int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e); +# endif +void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx, + int (*app_gen_cookie_cb) (SSL *ssl, + unsigned char + *cookie, + unsigned int + *cookie_len)); +void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx, + int (*app_verify_cookie_cb) (SSL *ssl, + const unsigned + char *cookie, + unsigned int + cookie_len)); + +void SSL_CTX_set_stateless_cookie_generate_cb( + SSL_CTX *ctx, + int (*gen_stateless_cookie_cb) (SSL *ssl, + unsigned char *cookie, + size_t *cookie_len)); +void SSL_CTX_set_stateless_cookie_verify_cb( + SSL_CTX *ctx, + int (*verify_stateless_cookie_cb) (SSL *ssl, + const unsigned char *cookie, + size_t cookie_len)); +# ifndef OPENSSL_NO_NEXTPROTONEG + +typedef int (*SSL_CTX_npn_advertised_cb_func)(SSL *ssl, + const unsigned char **out, + unsigned int *outlen, + void *arg); +void SSL_CTX_set_next_protos_advertised_cb(SSL_CTX *s, + SSL_CTX_npn_advertised_cb_func cb, + void *arg); +# define SSL_CTX_set_npn_advertised_cb SSL_CTX_set_next_protos_advertised_cb + +typedef int (*SSL_CTX_npn_select_cb_func)(SSL *s, + unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg); +void SSL_CTX_set_next_proto_select_cb(SSL_CTX *s, + SSL_CTX_npn_select_cb_func cb, + void *arg); +# define SSL_CTX_set_npn_select_cb SSL_CTX_set_next_proto_select_cb + +void SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data, + unsigned *len); +# define SSL_get0_npn_negotiated SSL_get0_next_proto_negotiated +# endif + +__owur int SSL_select_next_proto(unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen, + const unsigned char *client, + unsigned int client_len); + +# define OPENSSL_NPN_UNSUPPORTED 0 +# define OPENSSL_NPN_NEGOTIATED 1 +# define OPENSSL_NPN_NO_OVERLAP 2 + +__owur int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char *protos, + unsigned int protos_len); +__owur int SSL_set_alpn_protos(SSL *ssl, const unsigned char *protos, + unsigned int protos_len); +typedef int (*SSL_CTX_alpn_select_cb_func)(SSL *ssl, + const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg); +void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx, + SSL_CTX_alpn_select_cb_func cb, + void *arg); +void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data, + unsigned int *len); + +# ifndef OPENSSL_NO_PSK +/* + * the maximum length of the buffer given to callbacks containing the + * resulting identity/psk + */ +# define PSK_MAX_IDENTITY_LEN 128 +# define PSK_MAX_PSK_LEN 256 +typedef unsigned int (*SSL_psk_client_cb_func)(SSL *ssl, + const char *hint, + char *identity, + unsigned int max_identity_len, + unsigned char *psk, + unsigned int max_psk_len); +void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx, SSL_psk_client_cb_func cb); +void SSL_set_psk_client_callback(SSL *ssl, SSL_psk_client_cb_func cb); + +typedef unsigned int (*SSL_psk_server_cb_func)(SSL *ssl, + const char *identity, + unsigned char *psk, + unsigned int max_psk_len); +void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx, SSL_psk_server_cb_func cb); +void SSL_set_psk_server_callback(SSL *ssl, SSL_psk_server_cb_func cb); + +__owur int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint); +__owur int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint); +const char *SSL_get_psk_identity_hint(const SSL *s); +const char *SSL_get_psk_identity(const SSL *s); +# endif + +typedef int (*SSL_psk_find_session_cb_func)(SSL *ssl, + const unsigned char *identity, + size_t identity_len, + SSL_SESSION **sess); +typedef int (*SSL_psk_use_session_cb_func)(SSL *ssl, const EVP_MD *md, + const unsigned char **id, + size_t *idlen, + SSL_SESSION **sess); + +void SSL_set_psk_find_session_callback(SSL *s, SSL_psk_find_session_cb_func cb); +void SSL_CTX_set_psk_find_session_callback(SSL_CTX *ctx, + SSL_psk_find_session_cb_func cb); +void SSL_set_psk_use_session_callback(SSL *s, SSL_psk_use_session_cb_func cb); +void SSL_CTX_set_psk_use_session_callback(SSL_CTX *ctx, + SSL_psk_use_session_cb_func cb); + +/* Register callbacks to handle custom TLS Extensions for client or server. */ + +__owur int SSL_CTX_has_client_custom_ext(const SSL_CTX *ctx, + unsigned int ext_type); + +__owur int SSL_CTX_add_client_custom_ext(SSL_CTX *ctx, + unsigned int ext_type, + custom_ext_add_cb add_cb, + custom_ext_free_cb free_cb, + void *add_arg, + custom_ext_parse_cb parse_cb, + void *parse_arg); + +__owur int SSL_CTX_add_server_custom_ext(SSL_CTX *ctx, + unsigned int ext_type, + custom_ext_add_cb add_cb, + custom_ext_free_cb free_cb, + void *add_arg, + custom_ext_parse_cb parse_cb, + void *parse_arg); + +__owur int SSL_CTX_add_custom_ext(SSL_CTX *ctx, unsigned int ext_type, + unsigned int context, + SSL_custom_ext_add_cb_ex add_cb, + SSL_custom_ext_free_cb_ex free_cb, + void *add_arg, + SSL_custom_ext_parse_cb_ex parse_cb, + void *parse_arg); + +__owur int SSL_extension_supported(unsigned int ext_type); + +# define SSL_NOTHING 1 +# define SSL_WRITING 2 +# define SSL_READING 3 +# define SSL_X509_LOOKUP 4 +# define SSL_ASYNC_PAUSED 5 +# define SSL_ASYNC_NO_JOBS 6 +# define SSL_CLIENT_HELLO_CB 7 + +/* These will only be used when doing non-blocking IO */ +# define SSL_want_nothing(s) (SSL_want(s) == SSL_NOTHING) +# define SSL_want_read(s) (SSL_want(s) == SSL_READING) +# define SSL_want_write(s) (SSL_want(s) == SSL_WRITING) +# define SSL_want_x509_lookup(s) (SSL_want(s) == SSL_X509_LOOKUP) +# define SSL_want_async(s) (SSL_want(s) == SSL_ASYNC_PAUSED) +# define SSL_want_async_job(s) (SSL_want(s) == SSL_ASYNC_NO_JOBS) +# define SSL_want_client_hello_cb(s) (SSL_want(s) == SSL_CLIENT_HELLO_CB) + +# define SSL_MAC_FLAG_READ_MAC_STREAM 1 +# define SSL_MAC_FLAG_WRITE_MAC_STREAM 2 + +/* + * A callback for logging out TLS key material. This callback should log out + * |line| followed by a newline. + */ +typedef void (*SSL_CTX_keylog_cb_func)(const SSL *ssl, const char *line); + +/* + * SSL_CTX_set_keylog_callback configures a callback to log key material. This + * is intended for debugging use with tools like Wireshark. The cb function + * should log line followed by a newline. + */ +void SSL_CTX_set_keylog_callback(SSL_CTX *ctx, SSL_CTX_keylog_cb_func cb); + +/* + * SSL_CTX_get_keylog_callback returns the callback configured by + * SSL_CTX_set_keylog_callback. + */ +SSL_CTX_keylog_cb_func SSL_CTX_get_keylog_callback(const SSL_CTX *ctx); + +int SSL_CTX_set_max_early_data(SSL_CTX *ctx, uint32_t max_early_data); +uint32_t SSL_CTX_get_max_early_data(const SSL_CTX *ctx); +int SSL_set_max_early_data(SSL *s, uint32_t max_early_data); +uint32_t SSL_get_max_early_data(const SSL *s); +int SSL_CTX_set_recv_max_early_data(SSL_CTX *ctx, uint32_t recv_max_early_data); +uint32_t SSL_CTX_get_recv_max_early_data(const SSL_CTX *ctx); +int SSL_set_recv_max_early_data(SSL *s, uint32_t recv_max_early_data); +uint32_t SSL_get_recv_max_early_data(const SSL *s); + +#ifdef __cplusplus +} +#endif + +# include +# include +# include /* This is mostly sslv3 with a few tweaks */ +# include /* Datagram TLS */ +# include /* Support for the use_srtp extension */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * These need to be after the above set of includes due to a compiler bug + * in VisualStudio 2015 + */ +DEFINE_STACK_OF_CONST(SSL_CIPHER) +DEFINE_STACK_OF(SSL_COMP) + +/* compatibility */ +# define SSL_set_app_data(s,arg) (SSL_set_ex_data(s,0,(char *)(arg))) +# define SSL_get_app_data(s) (SSL_get_ex_data(s,0)) +# define SSL_SESSION_set_app_data(s,a) (SSL_SESSION_set_ex_data(s,0, \ + (char *)(a))) +# define SSL_SESSION_get_app_data(s) (SSL_SESSION_get_ex_data(s,0)) +# define SSL_CTX_get_app_data(ctx) (SSL_CTX_get_ex_data(ctx,0)) +# define SSL_CTX_set_app_data(ctx,arg) (SSL_CTX_set_ex_data(ctx,0, \ + (char *)(arg))) +DEPRECATEDIN_1_1_0(void SSL_set_debug(SSL *s, int debug)) + +/* TLSv1.3 KeyUpdate message types */ +/* -1 used so that this is an invalid value for the on-the-wire protocol */ +#define SSL_KEY_UPDATE_NONE -1 +/* Values as defined for the on-the-wire protocol */ +#define SSL_KEY_UPDATE_NOT_REQUESTED 0 +#define SSL_KEY_UPDATE_REQUESTED 1 + +/* + * The valid handshake states (one for each type message sent and one for each + * type of message received). There are also two "special" states: + * TLS = TLS or DTLS state + * DTLS = DTLS specific state + * CR/SR = Client Read/Server Read + * CW/SW = Client Write/Server Write + * + * The "special" states are: + * TLS_ST_BEFORE = No handshake has been initiated yet + * TLS_ST_OK = A handshake has been successfully completed + */ +typedef enum { + TLS_ST_BEFORE, + TLS_ST_OK, + DTLS_ST_CR_HELLO_VERIFY_REQUEST, + TLS_ST_CR_SRVR_HELLO, + TLS_ST_CR_CERT, + TLS_ST_CR_CERT_STATUS, + TLS_ST_CR_KEY_EXCH, + TLS_ST_CR_CERT_REQ, + TLS_ST_CR_SRVR_DONE, + TLS_ST_CR_SESSION_TICKET, + TLS_ST_CR_CHANGE, + TLS_ST_CR_FINISHED, + TLS_ST_CW_CLNT_HELLO, + TLS_ST_CW_CERT, + TLS_ST_CW_KEY_EXCH, + TLS_ST_CW_CERT_VRFY, + TLS_ST_CW_CHANGE, + TLS_ST_CW_NEXT_PROTO, + TLS_ST_CW_FINISHED, + TLS_ST_SW_HELLO_REQ, + TLS_ST_SR_CLNT_HELLO, + DTLS_ST_SW_HELLO_VERIFY_REQUEST, + TLS_ST_SW_SRVR_HELLO, + TLS_ST_SW_CERT, + TLS_ST_SW_KEY_EXCH, + TLS_ST_SW_CERT_REQ, + TLS_ST_SW_SRVR_DONE, + TLS_ST_SR_CERT, + TLS_ST_SR_KEY_EXCH, + TLS_ST_SR_CERT_VRFY, + TLS_ST_SR_NEXT_PROTO, + TLS_ST_SR_CHANGE, + TLS_ST_SR_FINISHED, + TLS_ST_SW_SESSION_TICKET, + TLS_ST_SW_CERT_STATUS, + TLS_ST_SW_CHANGE, + TLS_ST_SW_FINISHED, + TLS_ST_SW_ENCRYPTED_EXTENSIONS, + TLS_ST_CR_ENCRYPTED_EXTENSIONS, + TLS_ST_CR_CERT_VRFY, + TLS_ST_SW_CERT_VRFY, + TLS_ST_CR_HELLO_REQ, + TLS_ST_SW_KEY_UPDATE, + TLS_ST_CW_KEY_UPDATE, + TLS_ST_SR_KEY_UPDATE, + TLS_ST_CR_KEY_UPDATE, + TLS_ST_EARLY_DATA, + TLS_ST_PENDING_EARLY_DATA_END, + TLS_ST_CW_END_OF_EARLY_DATA, + TLS_ST_SR_END_OF_EARLY_DATA +} OSSL_HANDSHAKE_STATE; + +/* + * Most of the following state values are no longer used and are defined to be + * the closest equivalent value in the current state machine code. Not all + * defines have an equivalent and are set to a dummy value (-1). SSL_ST_CONNECT + * and SSL_ST_ACCEPT are still in use in the definition of SSL_CB_ACCEPT_LOOP, + * SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP and SSL_CB_CONNECT_EXIT. + */ + +# define SSL_ST_CONNECT 0x1000 +# define SSL_ST_ACCEPT 0x2000 + +# define SSL_ST_MASK 0x0FFF + +# define SSL_CB_LOOP 0x01 +# define SSL_CB_EXIT 0x02 +# define SSL_CB_READ 0x04 +# define SSL_CB_WRITE 0x08 +# define SSL_CB_ALERT 0x4000/* used in callback */ +# define SSL_CB_READ_ALERT (SSL_CB_ALERT|SSL_CB_READ) +# define SSL_CB_WRITE_ALERT (SSL_CB_ALERT|SSL_CB_WRITE) +# define SSL_CB_ACCEPT_LOOP (SSL_ST_ACCEPT|SSL_CB_LOOP) +# define SSL_CB_ACCEPT_EXIT (SSL_ST_ACCEPT|SSL_CB_EXIT) +# define SSL_CB_CONNECT_LOOP (SSL_ST_CONNECT|SSL_CB_LOOP) +# define SSL_CB_CONNECT_EXIT (SSL_ST_CONNECT|SSL_CB_EXIT) +# define SSL_CB_HANDSHAKE_START 0x10 +# define SSL_CB_HANDSHAKE_DONE 0x20 + +/* Is the SSL_connection established? */ +# define SSL_in_connect_init(a) (SSL_in_init(a) && !SSL_is_server(a)) +# define SSL_in_accept_init(a) (SSL_in_init(a) && SSL_is_server(a)) +int SSL_in_init(const SSL *s); +int SSL_in_before(const SSL *s); +int SSL_is_init_finished(const SSL *s); + +/* + * The following 3 states are kept in ssl->rlayer.rstate when reads fail, you + * should not need these + */ +# define SSL_ST_READ_HEADER 0xF0 +# define SSL_ST_READ_BODY 0xF1 +# define SSL_ST_READ_DONE 0xF2 + +/*- + * Obtain latest Finished message + * -- that we sent (SSL_get_finished) + * -- that we expected from peer (SSL_get_peer_finished). + * Returns length (0 == no Finished so far), copies up to 'count' bytes. + */ +size_t SSL_get_finished(const SSL *s, void *buf, size_t count); +size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count); + +/* + * use either SSL_VERIFY_NONE or SSL_VERIFY_PEER, the last 3 options are + * 'ored' with SSL_VERIFY_PEER if they are desired + */ +# define SSL_VERIFY_NONE 0x00 +# define SSL_VERIFY_PEER 0x01 +# define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02 +# define SSL_VERIFY_CLIENT_ONCE 0x04 +# define SSL_VERIFY_POST_HANDSHAKE 0x08 + +# if OPENSSL_API_COMPAT < 0x10100000L +# define OpenSSL_add_ssl_algorithms() SSL_library_init() +# define SSLeay_add_ssl_algorithms() SSL_library_init() +# endif + +/* More backward compatibility */ +# define SSL_get_cipher(s) \ + SSL_CIPHER_get_name(SSL_get_current_cipher(s)) +# define SSL_get_cipher_bits(s,np) \ + SSL_CIPHER_get_bits(SSL_get_current_cipher(s),np) +# define SSL_get_cipher_version(s) \ + SSL_CIPHER_get_version(SSL_get_current_cipher(s)) +# define SSL_get_cipher_name(s) \ + SSL_CIPHER_get_name(SSL_get_current_cipher(s)) +# define SSL_get_time(a) SSL_SESSION_get_time(a) +# define SSL_set_time(a,b) SSL_SESSION_set_time((a),(b)) +# define SSL_get_timeout(a) SSL_SESSION_get_timeout(a) +# define SSL_set_timeout(a,b) SSL_SESSION_set_timeout((a),(b)) + +# define d2i_SSL_SESSION_bio(bp,s_id) ASN1_d2i_bio_of(SSL_SESSION,SSL_SESSION_new,d2i_SSL_SESSION,bp,s_id) +# define i2d_SSL_SESSION_bio(bp,s_id) ASN1_i2d_bio_of(SSL_SESSION,i2d_SSL_SESSION,bp,s_id) + +DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION) +# define SSL_AD_REASON_OFFSET 1000/* offset to get SSL_R_... value + * from SSL_AD_... */ +/* These alert types are for SSLv3 and TLSv1 */ +# define SSL_AD_CLOSE_NOTIFY SSL3_AD_CLOSE_NOTIFY +/* fatal */ +# define SSL_AD_UNEXPECTED_MESSAGE SSL3_AD_UNEXPECTED_MESSAGE +/* fatal */ +# define SSL_AD_BAD_RECORD_MAC SSL3_AD_BAD_RECORD_MAC +# define SSL_AD_DECRYPTION_FAILED TLS1_AD_DECRYPTION_FAILED +# define SSL_AD_RECORD_OVERFLOW TLS1_AD_RECORD_OVERFLOW +/* fatal */ +# define SSL_AD_DECOMPRESSION_FAILURE SSL3_AD_DECOMPRESSION_FAILURE +/* fatal */ +# define SSL_AD_HANDSHAKE_FAILURE SSL3_AD_HANDSHAKE_FAILURE +/* Not for TLS */ +# define SSL_AD_NO_CERTIFICATE SSL3_AD_NO_CERTIFICATE +# define SSL_AD_BAD_CERTIFICATE SSL3_AD_BAD_CERTIFICATE +# define SSL_AD_UNSUPPORTED_CERTIFICATE SSL3_AD_UNSUPPORTED_CERTIFICATE +# define SSL_AD_CERTIFICATE_REVOKED SSL3_AD_CERTIFICATE_REVOKED +# define SSL_AD_CERTIFICATE_EXPIRED SSL3_AD_CERTIFICATE_EXPIRED +# define SSL_AD_CERTIFICATE_UNKNOWN SSL3_AD_CERTIFICATE_UNKNOWN +/* fatal */ +# define SSL_AD_ILLEGAL_PARAMETER SSL3_AD_ILLEGAL_PARAMETER +/* fatal */ +# define SSL_AD_UNKNOWN_CA TLS1_AD_UNKNOWN_CA +/* fatal */ +# define SSL_AD_ACCESS_DENIED TLS1_AD_ACCESS_DENIED +/* fatal */ +# define SSL_AD_DECODE_ERROR TLS1_AD_DECODE_ERROR +# define SSL_AD_DECRYPT_ERROR TLS1_AD_DECRYPT_ERROR +/* fatal */ +# define SSL_AD_EXPORT_RESTRICTION TLS1_AD_EXPORT_RESTRICTION +/* fatal */ +# define SSL_AD_PROTOCOL_VERSION TLS1_AD_PROTOCOL_VERSION +/* fatal */ +# define SSL_AD_INSUFFICIENT_SECURITY TLS1_AD_INSUFFICIENT_SECURITY +/* fatal */ +# define SSL_AD_INTERNAL_ERROR TLS1_AD_INTERNAL_ERROR +# define SSL_AD_USER_CANCELLED TLS1_AD_USER_CANCELLED +# define SSL_AD_NO_RENEGOTIATION TLS1_AD_NO_RENEGOTIATION +# define SSL_AD_MISSING_EXTENSION TLS13_AD_MISSING_EXTENSION +# define SSL_AD_CERTIFICATE_REQUIRED TLS13_AD_CERTIFICATE_REQUIRED +# define SSL_AD_UNSUPPORTED_EXTENSION TLS1_AD_UNSUPPORTED_EXTENSION +# define SSL_AD_CERTIFICATE_UNOBTAINABLE TLS1_AD_CERTIFICATE_UNOBTAINABLE +# define SSL_AD_UNRECOGNIZED_NAME TLS1_AD_UNRECOGNIZED_NAME +# define SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE +# define SSL_AD_BAD_CERTIFICATE_HASH_VALUE TLS1_AD_BAD_CERTIFICATE_HASH_VALUE +/* fatal */ +# define SSL_AD_UNKNOWN_PSK_IDENTITY TLS1_AD_UNKNOWN_PSK_IDENTITY +/* fatal */ +# define SSL_AD_INAPPROPRIATE_FALLBACK TLS1_AD_INAPPROPRIATE_FALLBACK +# define SSL_AD_NO_APPLICATION_PROTOCOL TLS1_AD_NO_APPLICATION_PROTOCOL +# define SSL_ERROR_NONE 0 +# define SSL_ERROR_SSL 1 +# define SSL_ERROR_WANT_READ 2 +# define SSL_ERROR_WANT_WRITE 3 +# define SSL_ERROR_WANT_X509_LOOKUP 4 +# define SSL_ERROR_SYSCALL 5/* look at error stack/return + * value/errno */ +# define SSL_ERROR_ZERO_RETURN 6 +# define SSL_ERROR_WANT_CONNECT 7 +# define SSL_ERROR_WANT_ACCEPT 8 +# define SSL_ERROR_WANT_ASYNC 9 +# define SSL_ERROR_WANT_ASYNC_JOB 10 +# define SSL_ERROR_WANT_CLIENT_HELLO_CB 11 +# define SSL_CTRL_SET_TMP_DH 3 +# define SSL_CTRL_SET_TMP_ECDH 4 +# define SSL_CTRL_SET_TMP_DH_CB 6 +# define SSL_CTRL_GET_CLIENT_CERT_REQUEST 9 +# define SSL_CTRL_GET_NUM_RENEGOTIATIONS 10 +# define SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS 11 +# define SSL_CTRL_GET_TOTAL_RENEGOTIATIONS 12 +# define SSL_CTRL_GET_FLAGS 13 +# define SSL_CTRL_EXTRA_CHAIN_CERT 14 +# define SSL_CTRL_SET_MSG_CALLBACK 15 +# define SSL_CTRL_SET_MSG_CALLBACK_ARG 16 +/* only applies to datagram connections */ +# define SSL_CTRL_SET_MTU 17 +/* Stats */ +# define SSL_CTRL_SESS_NUMBER 20 +# define SSL_CTRL_SESS_CONNECT 21 +# define SSL_CTRL_SESS_CONNECT_GOOD 22 +# define SSL_CTRL_SESS_CONNECT_RENEGOTIATE 23 +# define SSL_CTRL_SESS_ACCEPT 24 +# define SSL_CTRL_SESS_ACCEPT_GOOD 25 +# define SSL_CTRL_SESS_ACCEPT_RENEGOTIATE 26 +# define SSL_CTRL_SESS_HIT 27 +# define SSL_CTRL_SESS_CB_HIT 28 +# define SSL_CTRL_SESS_MISSES 29 +# define SSL_CTRL_SESS_TIMEOUTS 30 +# define SSL_CTRL_SESS_CACHE_FULL 31 +# define SSL_CTRL_MODE 33 +# define SSL_CTRL_GET_READ_AHEAD 40 +# define SSL_CTRL_SET_READ_AHEAD 41 +# define SSL_CTRL_SET_SESS_CACHE_SIZE 42 +# define SSL_CTRL_GET_SESS_CACHE_SIZE 43 +# define SSL_CTRL_SET_SESS_CACHE_MODE 44 +# define SSL_CTRL_GET_SESS_CACHE_MODE 45 +# define SSL_CTRL_GET_MAX_CERT_LIST 50 +# define SSL_CTRL_SET_MAX_CERT_LIST 51 +# define SSL_CTRL_SET_MAX_SEND_FRAGMENT 52 +/* see tls1.h for macros based on these */ +# define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB 53 +# define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG 54 +# define SSL_CTRL_SET_TLSEXT_HOSTNAME 55 +# define SSL_CTRL_SET_TLSEXT_DEBUG_CB 56 +# define SSL_CTRL_SET_TLSEXT_DEBUG_ARG 57 +# define SSL_CTRL_GET_TLSEXT_TICKET_KEYS 58 +# define SSL_CTRL_SET_TLSEXT_TICKET_KEYS 59 +/*# define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT 60 */ +/*# define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB 61 */ +/*# define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB_ARG 62 */ +# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB 63 +# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG 64 +# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE 65 +# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS 66 +# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS 67 +# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS 68 +# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS 69 +# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP 70 +# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP 71 +# define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB 72 +# define SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB 75 +# define SSL_CTRL_SET_SRP_VERIFY_PARAM_CB 76 +# define SSL_CTRL_SET_SRP_GIVE_CLIENT_PWD_CB 77 +# define SSL_CTRL_SET_SRP_ARG 78 +# define SSL_CTRL_SET_TLS_EXT_SRP_USERNAME 79 +# define SSL_CTRL_SET_TLS_EXT_SRP_STRENGTH 80 +# define SSL_CTRL_SET_TLS_EXT_SRP_PASSWORD 81 +# ifndef OPENSSL_NO_HEARTBEATS +# define SSL_CTRL_DTLS_EXT_SEND_HEARTBEAT 85 +# define SSL_CTRL_GET_DTLS_EXT_HEARTBEAT_PENDING 86 +# define SSL_CTRL_SET_DTLS_EXT_HEARTBEAT_NO_REQUESTS 87 +# endif +# define DTLS_CTRL_GET_TIMEOUT 73 +# define DTLS_CTRL_HANDLE_TIMEOUT 74 +# define SSL_CTRL_GET_RI_SUPPORT 76 +# define SSL_CTRL_CLEAR_MODE 78 +# define SSL_CTRL_SET_NOT_RESUMABLE_SESS_CB 79 +# define SSL_CTRL_GET_EXTRA_CHAIN_CERTS 82 +# define SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS 83 +# define SSL_CTRL_CHAIN 88 +# define SSL_CTRL_CHAIN_CERT 89 +# define SSL_CTRL_GET_GROUPS 90 +# define SSL_CTRL_SET_GROUPS 91 +# define SSL_CTRL_SET_GROUPS_LIST 92 +# define SSL_CTRL_GET_SHARED_GROUP 93 +# define SSL_CTRL_SET_SIGALGS 97 +# define SSL_CTRL_SET_SIGALGS_LIST 98 +# define SSL_CTRL_CERT_FLAGS 99 +# define SSL_CTRL_CLEAR_CERT_FLAGS 100 +# define SSL_CTRL_SET_CLIENT_SIGALGS 101 +# define SSL_CTRL_SET_CLIENT_SIGALGS_LIST 102 +# define SSL_CTRL_GET_CLIENT_CERT_TYPES 103 +# define SSL_CTRL_SET_CLIENT_CERT_TYPES 104 +# define SSL_CTRL_BUILD_CERT_CHAIN 105 +# define SSL_CTRL_SET_VERIFY_CERT_STORE 106 +# define SSL_CTRL_SET_CHAIN_CERT_STORE 107 +# define SSL_CTRL_GET_PEER_SIGNATURE_NID 108 +# define SSL_CTRL_GET_PEER_TMP_KEY 109 +# define SSL_CTRL_GET_RAW_CIPHERLIST 110 +# define SSL_CTRL_GET_EC_POINT_FORMATS 111 +# define SSL_CTRL_GET_CHAIN_CERTS 115 +# define SSL_CTRL_SELECT_CURRENT_CERT 116 +# define SSL_CTRL_SET_CURRENT_CERT 117 +# define SSL_CTRL_SET_DH_AUTO 118 +# define DTLS_CTRL_SET_LINK_MTU 120 +# define DTLS_CTRL_GET_LINK_MIN_MTU 121 +# define SSL_CTRL_GET_EXTMS_SUPPORT 122 +# define SSL_CTRL_SET_MIN_PROTO_VERSION 123 +# define SSL_CTRL_SET_MAX_PROTO_VERSION 124 +# define SSL_CTRL_SET_SPLIT_SEND_FRAGMENT 125 +# define SSL_CTRL_SET_MAX_PIPELINES 126 +# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_TYPE 127 +# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB 128 +# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG 129 +# define SSL_CTRL_GET_MIN_PROTO_VERSION 130 +# define SSL_CTRL_GET_MAX_PROTO_VERSION 131 +# define SSL_CTRL_GET_SIGNATURE_NID 132 +# define SSL_CTRL_GET_TMP_KEY 133 +# define SSL_CERT_SET_FIRST 1 +# define SSL_CERT_SET_NEXT 2 +# define SSL_CERT_SET_SERVER 3 +# define DTLSv1_get_timeout(ssl, arg) \ + SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)(arg)) +# define DTLSv1_handle_timeout(ssl) \ + SSL_ctrl(ssl,DTLS_CTRL_HANDLE_TIMEOUT,0, NULL) +# define SSL_num_renegotiations(ssl) \ + SSL_ctrl((ssl),SSL_CTRL_GET_NUM_RENEGOTIATIONS,0,NULL) +# define SSL_clear_num_renegotiations(ssl) \ + SSL_ctrl((ssl),SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS,0,NULL) +# define SSL_total_renegotiations(ssl) \ + SSL_ctrl((ssl),SSL_CTRL_GET_TOTAL_RENEGOTIATIONS,0,NULL) +# define SSL_CTX_set_tmp_dh(ctx,dh) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH,0,(char *)(dh)) +# define SSL_CTX_set_tmp_ecdh(ctx,ecdh) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_ECDH,0,(char *)(ecdh)) +# define SSL_CTX_set_dh_auto(ctx, onoff) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_DH_AUTO,onoff,NULL) +# define SSL_set_dh_auto(s, onoff) \ + SSL_ctrl(s,SSL_CTRL_SET_DH_AUTO,onoff,NULL) +# define SSL_set_tmp_dh(ssl,dh) \ + SSL_ctrl(ssl,SSL_CTRL_SET_TMP_DH,0,(char *)(dh)) +# define SSL_set_tmp_ecdh(ssl,ecdh) \ + SSL_ctrl(ssl,SSL_CTRL_SET_TMP_ECDH,0,(char *)(ecdh)) +# define SSL_CTX_add_extra_chain_cert(ctx,x509) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char *)(x509)) +# define SSL_CTX_get_extra_chain_certs(ctx,px509) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_EXTRA_CHAIN_CERTS,0,px509) +# define SSL_CTX_get_extra_chain_certs_only(ctx,px509) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_EXTRA_CHAIN_CERTS,1,px509) +# define SSL_CTX_clear_extra_chain_certs(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS,0,NULL) +# define SSL_CTX_set0_chain(ctx,sk) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN,0,(char *)(sk)) +# define SSL_CTX_set1_chain(ctx,sk) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN,1,(char *)(sk)) +# define SSL_CTX_add0_chain_cert(ctx,x509) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,0,(char *)(x509)) +# define SSL_CTX_add1_chain_cert(ctx,x509) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,1,(char *)(x509)) +# define SSL_CTX_get0_chain_certs(ctx,px509) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_CHAIN_CERTS,0,px509) +# define SSL_CTX_clear_chain_certs(ctx) \ + SSL_CTX_set0_chain(ctx,NULL) +# define SSL_CTX_build_cert_chain(ctx, flags) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL) +# define SSL_CTX_select_current_cert(ctx,x509) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SELECT_CURRENT_CERT,0,(char *)(x509)) +# define SSL_CTX_set_current_cert(ctx, op) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CURRENT_CERT, op, NULL) +# define SSL_CTX_set0_verify_cert_store(ctx,st) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)(st)) +# define SSL_CTX_set1_verify_cert_store(ctx,st) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_VERIFY_CERT_STORE,1,(char *)(st)) +# define SSL_CTX_set0_chain_cert_store(ctx,st) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CHAIN_CERT_STORE,0,(char *)(st)) +# define SSL_CTX_set1_chain_cert_store(ctx,st) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CHAIN_CERT_STORE,1,(char *)(st)) +# define SSL_set0_chain(ctx,sk) \ + SSL_ctrl(ctx,SSL_CTRL_CHAIN,0,(char *)(sk)) +# define SSL_set1_chain(ctx,sk) \ + SSL_ctrl(ctx,SSL_CTRL_CHAIN,1,(char *)(sk)) +# define SSL_add0_chain_cert(ctx,x509) \ + SSL_ctrl(ctx,SSL_CTRL_CHAIN_CERT,0,(char *)(x509)) +# define SSL_add1_chain_cert(ctx,x509) \ + SSL_ctrl(ctx,SSL_CTRL_CHAIN_CERT,1,(char *)(x509)) +# define SSL_get0_chain_certs(ctx,px509) \ + SSL_ctrl(ctx,SSL_CTRL_GET_CHAIN_CERTS,0,px509) +# define SSL_clear_chain_certs(ctx) \ + SSL_set0_chain(ctx,NULL) +# define SSL_build_cert_chain(s, flags) \ + SSL_ctrl(s,SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL) +# define SSL_select_current_cert(ctx,x509) \ + SSL_ctrl(ctx,SSL_CTRL_SELECT_CURRENT_CERT,0,(char *)(x509)) +# define SSL_set_current_cert(ctx,op) \ + SSL_ctrl(ctx,SSL_CTRL_SET_CURRENT_CERT, op, NULL) +# define SSL_set0_verify_cert_store(s,st) \ + SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)(st)) +# define SSL_set1_verify_cert_store(s,st) \ + SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,1,(char *)(st)) +# define SSL_set0_chain_cert_store(s,st) \ + SSL_ctrl(s,SSL_CTRL_SET_CHAIN_CERT_STORE,0,(char *)(st)) +# define SSL_set1_chain_cert_store(s,st) \ + SSL_ctrl(s,SSL_CTRL_SET_CHAIN_CERT_STORE,1,(char *)(st)) +# define SSL_get1_groups(ctx, s) \ + SSL_ctrl(ctx,SSL_CTRL_GET_GROUPS,0,(char *)(s)) +# define SSL_CTX_set1_groups(ctx, glist, glistlen) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_GROUPS,glistlen,(char *)(glist)) +# define SSL_CTX_set1_groups_list(ctx, s) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_GROUPS_LIST,0,(char *)(s)) +# define SSL_set1_groups(ctx, glist, glistlen) \ + SSL_ctrl(ctx,SSL_CTRL_SET_GROUPS,glistlen,(char *)(glist)) +# define SSL_set1_groups_list(ctx, s) \ + SSL_ctrl(ctx,SSL_CTRL_SET_GROUPS_LIST,0,(char *)(s)) +# define SSL_get_shared_group(s, n) \ + SSL_ctrl(s,SSL_CTRL_GET_SHARED_GROUP,n,NULL) +# define SSL_CTX_set1_sigalgs(ctx, slist, slistlen) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SIGALGS,slistlen,(int *)(slist)) +# define SSL_CTX_set1_sigalgs_list(ctx, s) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SIGALGS_LIST,0,(char *)(s)) +# define SSL_set1_sigalgs(ctx, slist, slistlen) \ + SSL_ctrl(ctx,SSL_CTRL_SET_SIGALGS,slistlen,(int *)(slist)) +# define SSL_set1_sigalgs_list(ctx, s) \ + SSL_ctrl(ctx,SSL_CTRL_SET_SIGALGS_LIST,0,(char *)(s)) +# define SSL_CTX_set1_client_sigalgs(ctx, slist, slistlen) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS,slistlen,(int *)(slist)) +# define SSL_CTX_set1_client_sigalgs_list(ctx, s) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS_LIST,0,(char *)(s)) +# define SSL_set1_client_sigalgs(ctx, slist, slistlen) \ + SSL_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS,clistlen,(int *)(slist)) +# define SSL_set1_client_sigalgs_list(ctx, s) \ + SSL_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS_LIST,0,(char *)(s)) +# define SSL_get0_certificate_types(s, clist) \ + SSL_ctrl(s, SSL_CTRL_GET_CLIENT_CERT_TYPES, 0, (char *)(clist)) +# define SSL_CTX_set1_client_certificate_types(ctx, clist, clistlen) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_CERT_TYPES,clistlen, \ + (char *)(clist)) +# define SSL_set1_client_certificate_types(s, clist, clistlen) \ + SSL_ctrl(s,SSL_CTRL_SET_CLIENT_CERT_TYPES,clistlen,(char *)(clist)) +# define SSL_get_signature_nid(s, pn) \ + SSL_ctrl(s,SSL_CTRL_GET_SIGNATURE_NID,0,pn) +# define SSL_get_peer_signature_nid(s, pn) \ + SSL_ctrl(s,SSL_CTRL_GET_PEER_SIGNATURE_NID,0,pn) +# define SSL_get_peer_tmp_key(s, pk) \ + SSL_ctrl(s,SSL_CTRL_GET_PEER_TMP_KEY,0,pk) +# define SSL_get_tmp_key(s, pk) \ + SSL_ctrl(s,SSL_CTRL_GET_TMP_KEY,0,pk) +# define SSL_get0_raw_cipherlist(s, plst) \ + SSL_ctrl(s,SSL_CTRL_GET_RAW_CIPHERLIST,0,plst) +# define SSL_get0_ec_point_formats(s, plst) \ + SSL_ctrl(s,SSL_CTRL_GET_EC_POINT_FORMATS,0,plst) +# define SSL_CTX_set_min_proto_version(ctx, version) \ + SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MIN_PROTO_VERSION, version, NULL) +# define SSL_CTX_set_max_proto_version(ctx, version) \ + SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MAX_PROTO_VERSION, version, NULL) +# define SSL_CTX_get_min_proto_version(ctx) \ + SSL_CTX_ctrl(ctx, SSL_CTRL_GET_MIN_PROTO_VERSION, 0, NULL) +# define SSL_CTX_get_max_proto_version(ctx) \ + SSL_CTX_ctrl(ctx, SSL_CTRL_GET_MAX_PROTO_VERSION, 0, NULL) +# define SSL_set_min_proto_version(s, version) \ + SSL_ctrl(s, SSL_CTRL_SET_MIN_PROTO_VERSION, version, NULL) +# define SSL_set_max_proto_version(s, version) \ + SSL_ctrl(s, SSL_CTRL_SET_MAX_PROTO_VERSION, version, NULL) +# define SSL_get_min_proto_version(s) \ + SSL_ctrl(s, SSL_CTRL_GET_MIN_PROTO_VERSION, 0, NULL) +# define SSL_get_max_proto_version(s) \ + SSL_ctrl(s, SSL_CTRL_GET_MAX_PROTO_VERSION, 0, NULL) + +/* Backwards compatibility, original 1.1.0 names */ +# define SSL_CTRL_GET_SERVER_TMP_KEY \ + SSL_CTRL_GET_PEER_TMP_KEY +# define SSL_get_server_tmp_key(s, pk) \ + SSL_get_peer_tmp_key(s, pk) + +/* + * The following symbol names are old and obsolete. They are kept + * for compatibility reasons only and should not be used anymore. + */ +# define SSL_CTRL_GET_CURVES SSL_CTRL_GET_GROUPS +# define SSL_CTRL_SET_CURVES SSL_CTRL_SET_GROUPS +# define SSL_CTRL_SET_CURVES_LIST SSL_CTRL_SET_GROUPS_LIST +# define SSL_CTRL_GET_SHARED_CURVE SSL_CTRL_GET_SHARED_GROUP + +# define SSL_get1_curves SSL_get1_groups +# define SSL_CTX_set1_curves SSL_CTX_set1_groups +# define SSL_CTX_set1_curves_list SSL_CTX_set1_groups_list +# define SSL_set1_curves SSL_set1_groups +# define SSL_set1_curves_list SSL_set1_groups_list +# define SSL_get_shared_curve SSL_get_shared_group + + +# if OPENSSL_API_COMPAT < 0x10100000L +/* Provide some compatibility macros for removed functionality. */ +# define SSL_CTX_need_tmp_RSA(ctx) 0 +# define SSL_CTX_set_tmp_rsa(ctx,rsa) 1 +# define SSL_need_tmp_RSA(ssl) 0 +# define SSL_set_tmp_rsa(ssl,rsa) 1 +# define SSL_CTX_set_ecdh_auto(dummy, onoff) ((onoff) != 0) +# define SSL_set_ecdh_auto(dummy, onoff) ((onoff) != 0) +/* + * We "pretend" to call the callback to avoid warnings about unused static + * functions. + */ +# define SSL_CTX_set_tmp_rsa_callback(ctx, cb) while(0) (cb)(NULL, 0, 0) +# define SSL_set_tmp_rsa_callback(ssl, cb) while(0) (cb)(NULL, 0, 0) +# endif +__owur const BIO_METHOD *BIO_f_ssl(void); +__owur BIO *BIO_new_ssl(SSL_CTX *ctx, int client); +__owur BIO *BIO_new_ssl_connect(SSL_CTX *ctx); +__owur BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx); +__owur int BIO_ssl_copy_session_id(BIO *to, BIO *from); +void BIO_ssl_shutdown(BIO *ssl_bio); + +__owur int SSL_CTX_set_cipher_list(SSL_CTX *, const char *str); +__owur SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth); +int SSL_CTX_up_ref(SSL_CTX *ctx); +void SSL_CTX_free(SSL_CTX *); +__owur long SSL_CTX_set_timeout(SSL_CTX *ctx, long t); +__owur long SSL_CTX_get_timeout(const SSL_CTX *ctx); +__owur X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *); +void SSL_CTX_set_cert_store(SSL_CTX *, X509_STORE *); +void SSL_CTX_set1_cert_store(SSL_CTX *, X509_STORE *); +__owur int SSL_want(const SSL *s); +__owur int SSL_clear(SSL *s); + +void SSL_CTX_flush_sessions(SSL_CTX *ctx, long tm); + +__owur const SSL_CIPHER *SSL_get_current_cipher(const SSL *s); +__owur const SSL_CIPHER *SSL_get_pending_cipher(const SSL *s); +__owur int SSL_CIPHER_get_bits(const SSL_CIPHER *c, int *alg_bits); +__owur const char *SSL_CIPHER_get_version(const SSL_CIPHER *c); +__owur const char *SSL_CIPHER_get_name(const SSL_CIPHER *c); +__owur const char *SSL_CIPHER_standard_name(const SSL_CIPHER *c); +__owur const char *OPENSSL_cipher_name(const char *rfc_name); +__owur uint32_t SSL_CIPHER_get_id(const SSL_CIPHER *c); +__owur uint16_t SSL_CIPHER_get_protocol_id(const SSL_CIPHER *c); +__owur int SSL_CIPHER_get_kx_nid(const SSL_CIPHER *c); +__owur int SSL_CIPHER_get_auth_nid(const SSL_CIPHER *c); +__owur const EVP_MD *SSL_CIPHER_get_handshake_digest(const SSL_CIPHER *c); +__owur int SSL_CIPHER_is_aead(const SSL_CIPHER *c); + +__owur int SSL_get_fd(const SSL *s); +__owur int SSL_get_rfd(const SSL *s); +__owur int SSL_get_wfd(const SSL *s); +__owur const char *SSL_get_cipher_list(const SSL *s, int n); +__owur char *SSL_get_shared_ciphers(const SSL *s, char *buf, int size); +__owur int SSL_get_read_ahead(const SSL *s); +__owur int SSL_pending(const SSL *s); +__owur int SSL_has_pending(const SSL *s); +# ifndef OPENSSL_NO_SOCK +__owur int SSL_set_fd(SSL *s, int fd); +__owur int SSL_set_rfd(SSL *s, int fd); +__owur int SSL_set_wfd(SSL *s, int fd); +# endif +void SSL_set0_rbio(SSL *s, BIO *rbio); +void SSL_set0_wbio(SSL *s, BIO *wbio); +void SSL_set_bio(SSL *s, BIO *rbio, BIO *wbio); +__owur BIO *SSL_get_rbio(const SSL *s); +__owur BIO *SSL_get_wbio(const SSL *s); +__owur int SSL_set_cipher_list(SSL *s, const char *str); +__owur int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str); +__owur int SSL_set_ciphersuites(SSL *s, const char *str); +void SSL_set_read_ahead(SSL *s, int yes); +__owur int SSL_get_verify_mode(const SSL *s); +__owur int SSL_get_verify_depth(const SSL *s); +__owur SSL_verify_cb SSL_get_verify_callback(const SSL *s); +void SSL_set_verify(SSL *s, int mode, SSL_verify_cb callback); +void SSL_set_verify_depth(SSL *s, int depth); +void SSL_set_cert_cb(SSL *s, int (*cb) (SSL *ssl, void *arg), void *arg); +# ifndef OPENSSL_NO_RSA +__owur int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa); +__owur int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const unsigned char *d, + long len); +# endif +__owur int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey); +__owur int SSL_use_PrivateKey_ASN1(int pk, SSL *ssl, const unsigned char *d, + long len); +__owur int SSL_use_certificate(SSL *ssl, X509 *x); +__owur int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len); +__owur int SSL_use_cert_and_key(SSL *ssl, X509 *x509, EVP_PKEY *privatekey, + STACK_OF(X509) *chain, int override); + + +/* serverinfo file format versions */ +# define SSL_SERVERINFOV1 1 +# define SSL_SERVERINFOV2 2 + +/* Set serverinfo data for the current active cert. */ +__owur int SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo, + size_t serverinfo_length); +__owur int SSL_CTX_use_serverinfo_ex(SSL_CTX *ctx, unsigned int version, + const unsigned char *serverinfo, + size_t serverinfo_length); +__owur int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file); + +#ifndef OPENSSL_NO_RSA +__owur int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type); +#endif + +__owur int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type); +__owur int SSL_use_certificate_file(SSL *ssl, const char *file, int type); + +#ifndef OPENSSL_NO_RSA +__owur int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, + int type); +#endif +__owur int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, + int type); +__owur int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, + int type); +/* PEM type */ +__owur int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file); +__owur int SSL_use_certificate_chain_file(SSL *ssl, const char *file); +__owur STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file); +__owur int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs, + const char *file); +int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs, + const char *dir); + +# if OPENSSL_API_COMPAT < 0x10100000L +# define SSL_load_error_strings() \ + OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS \ + | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL) +# endif + +__owur const char *SSL_state_string(const SSL *s); +__owur const char *SSL_rstate_string(const SSL *s); +__owur const char *SSL_state_string_long(const SSL *s); +__owur const char *SSL_rstate_string_long(const SSL *s); +__owur long SSL_SESSION_get_time(const SSL_SESSION *s); +__owur long SSL_SESSION_set_time(SSL_SESSION *s, long t); +__owur long SSL_SESSION_get_timeout(const SSL_SESSION *s); +__owur long SSL_SESSION_set_timeout(SSL_SESSION *s, long t); +__owur int SSL_SESSION_get_protocol_version(const SSL_SESSION *s); +__owur int SSL_SESSION_set_protocol_version(SSL_SESSION *s, int version); + +__owur const char *SSL_SESSION_get0_hostname(const SSL_SESSION *s); +__owur int SSL_SESSION_set1_hostname(SSL_SESSION *s, const char *hostname); +void SSL_SESSION_get0_alpn_selected(const SSL_SESSION *s, + const unsigned char **alpn, + size_t *len); +__owur int SSL_SESSION_set1_alpn_selected(SSL_SESSION *s, + const unsigned char *alpn, + size_t len); +__owur const SSL_CIPHER *SSL_SESSION_get0_cipher(const SSL_SESSION *s); +__owur int SSL_SESSION_set_cipher(SSL_SESSION *s, const SSL_CIPHER *cipher); +__owur int SSL_SESSION_has_ticket(const SSL_SESSION *s); +__owur unsigned long SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s); +void SSL_SESSION_get0_ticket(const SSL_SESSION *s, const unsigned char **tick, + size_t *len); +__owur uint32_t SSL_SESSION_get_max_early_data(const SSL_SESSION *s); +__owur int SSL_SESSION_set_max_early_data(SSL_SESSION *s, + uint32_t max_early_data); +__owur int SSL_copy_session_id(SSL *to, const SSL *from); +__owur X509 *SSL_SESSION_get0_peer(SSL_SESSION *s); +__owur int SSL_SESSION_set1_id_context(SSL_SESSION *s, + const unsigned char *sid_ctx, + unsigned int sid_ctx_len); +__owur int SSL_SESSION_set1_id(SSL_SESSION *s, const unsigned char *sid, + unsigned int sid_len); +__owur int SSL_SESSION_is_resumable(const SSL_SESSION *s); + +__owur SSL_SESSION *SSL_SESSION_new(void); +__owur SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *src); +const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, + unsigned int *len); +const unsigned char *SSL_SESSION_get0_id_context(const SSL_SESSION *s, + unsigned int *len); +__owur unsigned int SSL_SESSION_get_compress_id(const SSL_SESSION *s); +# ifndef OPENSSL_NO_STDIO +int SSL_SESSION_print_fp(FILE *fp, const SSL_SESSION *ses); +# endif +int SSL_SESSION_print(BIO *fp, const SSL_SESSION *ses); +int SSL_SESSION_print_keylog(BIO *bp, const SSL_SESSION *x); +int SSL_SESSION_up_ref(SSL_SESSION *ses); +void SSL_SESSION_free(SSL_SESSION *ses); +__owur int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp); +__owur int SSL_set_session(SSL *to, SSL_SESSION *session); +int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *session); +int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *session); +__owur int SSL_CTX_set_generate_session_id(SSL_CTX *ctx, GEN_SESSION_CB cb); +__owur int SSL_set_generate_session_id(SSL *s, GEN_SESSION_CB cb); +__owur int SSL_has_matching_session_id(const SSL *s, + const unsigned char *id, + unsigned int id_len); +SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, + long length); + +# ifdef HEADER_X509_H +__owur X509 *SSL_get_peer_certificate(const SSL *s); +# endif + +__owur STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s); + +__owur int SSL_CTX_get_verify_mode(const SSL_CTX *ctx); +__owur int SSL_CTX_get_verify_depth(const SSL_CTX *ctx); +__owur SSL_verify_cb SSL_CTX_get_verify_callback(const SSL_CTX *ctx); +void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, SSL_verify_cb callback); +void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth); +void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, + int (*cb) (X509_STORE_CTX *, void *), + void *arg); +void SSL_CTX_set_cert_cb(SSL_CTX *c, int (*cb) (SSL *ssl, void *arg), + void *arg); +# ifndef OPENSSL_NO_RSA +__owur int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa); +__owur int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, + long len); +# endif +__owur int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey); +__owur int SSL_CTX_use_PrivateKey_ASN1(int pk, SSL_CTX *ctx, + const unsigned char *d, long len); +__owur int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x); +__owur int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, + const unsigned char *d); +__owur int SSL_CTX_use_cert_and_key(SSL_CTX *ctx, X509 *x509, EVP_PKEY *privatekey, + STACK_OF(X509) *chain, int override); + +void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb); +void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u); +pem_password_cb *SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx); +void *SSL_CTX_get_default_passwd_cb_userdata(SSL_CTX *ctx); +void SSL_set_default_passwd_cb(SSL *s, pem_password_cb *cb); +void SSL_set_default_passwd_cb_userdata(SSL *s, void *u); +pem_password_cb *SSL_get_default_passwd_cb(SSL *s); +void *SSL_get_default_passwd_cb_userdata(SSL *s); + +__owur int SSL_CTX_check_private_key(const SSL_CTX *ctx); +__owur int SSL_check_private_key(const SSL *ctx); + +__owur int SSL_CTX_set_session_id_context(SSL_CTX *ctx, + const unsigned char *sid_ctx, + unsigned int sid_ctx_len); + +SSL *SSL_new(SSL_CTX *ctx); +int SSL_up_ref(SSL *s); +int SSL_is_dtls(const SSL *s); +__owur int SSL_set_session_id_context(SSL *ssl, const unsigned char *sid_ctx, + unsigned int sid_ctx_len); + +__owur int SSL_CTX_set_purpose(SSL_CTX *ctx, int purpose); +__owur int SSL_set_purpose(SSL *ssl, int purpose); +__owur int SSL_CTX_set_trust(SSL_CTX *ctx, int trust); +__owur int SSL_set_trust(SSL *ssl, int trust); + +__owur int SSL_set1_host(SSL *s, const char *hostname); +__owur int SSL_add1_host(SSL *s, const char *hostname); +__owur const char *SSL_get0_peername(SSL *s); +void SSL_set_hostflags(SSL *s, unsigned int flags); + +__owur int SSL_CTX_dane_enable(SSL_CTX *ctx); +__owur int SSL_CTX_dane_mtype_set(SSL_CTX *ctx, const EVP_MD *md, + uint8_t mtype, uint8_t ord); +__owur int SSL_dane_enable(SSL *s, const char *basedomain); +__owur int SSL_dane_tlsa_add(SSL *s, uint8_t usage, uint8_t selector, + uint8_t mtype, unsigned const char *data, size_t dlen); +__owur int SSL_get0_dane_authority(SSL *s, X509 **mcert, EVP_PKEY **mspki); +__owur int SSL_get0_dane_tlsa(SSL *s, uint8_t *usage, uint8_t *selector, + uint8_t *mtype, unsigned const char **data, + size_t *dlen); +/* + * Bridge opacity barrier between libcrypt and libssl, also needed to support + * offline testing in test/danetest.c + */ +SSL_DANE *SSL_get0_dane(SSL *ssl); +/* + * DANE flags + */ +unsigned long SSL_CTX_dane_set_flags(SSL_CTX *ctx, unsigned long flags); +unsigned long SSL_CTX_dane_clear_flags(SSL_CTX *ctx, unsigned long flags); +unsigned long SSL_dane_set_flags(SSL *ssl, unsigned long flags); +unsigned long SSL_dane_clear_flags(SSL *ssl, unsigned long flags); + +__owur int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm); +__owur int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm); + +__owur X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx); +__owur X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl); + +# ifndef OPENSSL_NO_SRP +int SSL_CTX_set_srp_username(SSL_CTX *ctx, char *name); +int SSL_CTX_set_srp_password(SSL_CTX *ctx, char *password); +int SSL_CTX_set_srp_strength(SSL_CTX *ctx, int strength); +int SSL_CTX_set_srp_client_pwd_callback(SSL_CTX *ctx, + char *(*cb) (SSL *, void *)); +int SSL_CTX_set_srp_verify_param_callback(SSL_CTX *ctx, + int (*cb) (SSL *, void *)); +int SSL_CTX_set_srp_username_callback(SSL_CTX *ctx, + int (*cb) (SSL *, int *, void *)); +int SSL_CTX_set_srp_cb_arg(SSL_CTX *ctx, void *arg); + +int SSL_set_srp_server_param(SSL *s, const BIGNUM *N, const BIGNUM *g, + BIGNUM *sa, BIGNUM *v, char *info); +int SSL_set_srp_server_param_pw(SSL *s, const char *user, const char *pass, + const char *grp); + +__owur BIGNUM *SSL_get_srp_g(SSL *s); +__owur BIGNUM *SSL_get_srp_N(SSL *s); + +__owur char *SSL_get_srp_username(SSL *s); +__owur char *SSL_get_srp_userinfo(SSL *s); +# endif + +/* + * ClientHello callback and helpers. + */ + +# define SSL_CLIENT_HELLO_SUCCESS 1 +# define SSL_CLIENT_HELLO_ERROR 0 +# define SSL_CLIENT_HELLO_RETRY (-1) + +typedef int (*SSL_client_hello_cb_fn) (SSL *s, int *al, void *arg); +void SSL_CTX_set_client_hello_cb(SSL_CTX *c, SSL_client_hello_cb_fn cb, + void *arg); +int SSL_client_hello_isv2(SSL *s); +unsigned int SSL_client_hello_get0_legacy_version(SSL *s); +size_t SSL_client_hello_get0_random(SSL *s, const unsigned char **out); +size_t SSL_client_hello_get0_session_id(SSL *s, const unsigned char **out); +size_t SSL_client_hello_get0_ciphers(SSL *s, const unsigned char **out); +size_t SSL_client_hello_get0_compression_methods(SSL *s, + const unsigned char **out); +int SSL_client_hello_get1_extensions_present(SSL *s, int **out, size_t *outlen); +int SSL_client_hello_get0_ext(SSL *s, unsigned int type, + const unsigned char **out, size_t *outlen); + +void SSL_certs_clear(SSL *s); +void SSL_free(SSL *ssl); +# ifdef OSSL_ASYNC_FD +/* + * Windows application developer has to include windows.h to use these. + */ +__owur int SSL_waiting_for_async(SSL *s); +__owur int SSL_get_all_async_fds(SSL *s, OSSL_ASYNC_FD *fds, size_t *numfds); +__owur int SSL_get_changed_async_fds(SSL *s, OSSL_ASYNC_FD *addfd, + size_t *numaddfds, OSSL_ASYNC_FD *delfd, + size_t *numdelfds); +# endif +__owur int SSL_accept(SSL *ssl); +__owur int SSL_stateless(SSL *s); +__owur int SSL_connect(SSL *ssl); +__owur int SSL_read(SSL *ssl, void *buf, int num); +__owur int SSL_read_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes); + +# define SSL_READ_EARLY_DATA_ERROR 0 +# define SSL_READ_EARLY_DATA_SUCCESS 1 +# define SSL_READ_EARLY_DATA_FINISH 2 + +__owur int SSL_read_early_data(SSL *s, void *buf, size_t num, + size_t *readbytes); +__owur int SSL_peek(SSL *ssl, void *buf, int num); +__owur int SSL_peek_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes); +__owur int SSL_write(SSL *ssl, const void *buf, int num); +__owur int SSL_write_ex(SSL *s, const void *buf, size_t num, size_t *written); +__owur int SSL_write_early_data(SSL *s, const void *buf, size_t num, + size_t *written); +long SSL_ctrl(SSL *ssl, int cmd, long larg, void *parg); +long SSL_callback_ctrl(SSL *, int, void (*)(void)); +long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg); +long SSL_CTX_callback_ctrl(SSL_CTX *, int, void (*)(void)); + +# define SSL_EARLY_DATA_NOT_SENT 0 +# define SSL_EARLY_DATA_REJECTED 1 +# define SSL_EARLY_DATA_ACCEPTED 2 + +__owur int SSL_get_early_data_status(const SSL *s); + +__owur int SSL_get_error(const SSL *s, int ret_code); +__owur const char *SSL_get_version(const SSL *s); + +/* This sets the 'default' SSL version that SSL_new() will create */ +__owur int SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *meth); + +# ifndef OPENSSL_NO_SSL3_METHOD +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *SSLv3_method(void)) /* SSLv3 */ +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *SSLv3_server_method(void)) +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *SSLv3_client_method(void)) +# endif + +#define SSLv23_method TLS_method +#define SSLv23_server_method TLS_server_method +#define SSLv23_client_method TLS_client_method + +/* Negotiate highest available SSL/TLS version */ +__owur const SSL_METHOD *TLS_method(void); +__owur const SSL_METHOD *TLS_server_method(void); +__owur const SSL_METHOD *TLS_client_method(void); + +# ifndef OPENSSL_NO_TLS1_METHOD +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_method(void)) /* TLSv1.0 */ +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_server_method(void)) +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_client_method(void)) +# endif + +# ifndef OPENSSL_NO_TLS1_1_METHOD +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_1_method(void)) /* TLSv1.1 */ +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_1_server_method(void)) +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_1_client_method(void)) +# endif + +# ifndef OPENSSL_NO_TLS1_2_METHOD +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_2_method(void)) /* TLSv1.2 */ +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_2_server_method(void)) +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_2_client_method(void)) +# endif + +# ifndef OPENSSL_NO_DTLS1_METHOD +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *DTLSv1_method(void)) /* DTLSv1.0 */ +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *DTLSv1_server_method(void)) +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *DTLSv1_client_method(void)) +# endif + +# ifndef OPENSSL_NO_DTLS1_2_METHOD +/* DTLSv1.2 */ +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *DTLSv1_2_method(void)) +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *DTLSv1_2_server_method(void)) +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *DTLSv1_2_client_method(void)) +# endif + +__owur const SSL_METHOD *DTLS_method(void); /* DTLS 1.0 and 1.2 */ +__owur const SSL_METHOD *DTLS_server_method(void); /* DTLS 1.0 and 1.2 */ +__owur const SSL_METHOD *DTLS_client_method(void); /* DTLS 1.0 and 1.2 */ + +__owur size_t DTLS_get_data_mtu(const SSL *s); + +__owur STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s); +__owur STACK_OF(SSL_CIPHER) *SSL_CTX_get_ciphers(const SSL_CTX *ctx); +__owur STACK_OF(SSL_CIPHER) *SSL_get_client_ciphers(const SSL *s); +__owur STACK_OF(SSL_CIPHER) *SSL_get1_supported_ciphers(SSL *s); + +__owur int SSL_do_handshake(SSL *s); +int SSL_key_update(SSL *s, int updatetype); +int SSL_get_key_update_type(const SSL *s); +int SSL_renegotiate(SSL *s); +int SSL_renegotiate_abbreviated(SSL *s); +__owur int SSL_renegotiate_pending(const SSL *s); +int SSL_shutdown(SSL *s); +__owur int SSL_verify_client_post_handshake(SSL *s); +void SSL_CTX_set_post_handshake_auth(SSL_CTX *ctx, int val); +void SSL_set_post_handshake_auth(SSL *s, int val); + +__owur const SSL_METHOD *SSL_CTX_get_ssl_method(const SSL_CTX *ctx); +__owur const SSL_METHOD *SSL_get_ssl_method(const SSL *s); +__owur int SSL_set_ssl_method(SSL *s, const SSL_METHOD *method); +__owur const char *SSL_alert_type_string_long(int value); +__owur const char *SSL_alert_type_string(int value); +__owur const char *SSL_alert_desc_string_long(int value); +__owur const char *SSL_alert_desc_string(int value); + +void SSL_set0_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list); +void SSL_CTX_set0_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list); +__owur const STACK_OF(X509_NAME) *SSL_get0_CA_list(const SSL *s); +__owur const STACK_OF(X509_NAME) *SSL_CTX_get0_CA_list(const SSL_CTX *ctx); +__owur int SSL_add1_to_CA_list(SSL *ssl, const X509 *x); +__owur int SSL_CTX_add1_to_CA_list(SSL_CTX *ctx, const X509 *x); +__owur const STACK_OF(X509_NAME) *SSL_get0_peer_CA_list(const SSL *s); + +void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list); +void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list); +__owur STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s); +__owur STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *s); +__owur int SSL_add_client_CA(SSL *ssl, X509 *x); +__owur int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x); + +void SSL_set_connect_state(SSL *s); +void SSL_set_accept_state(SSL *s); + +__owur long SSL_get_default_timeout(const SSL *s); + +# if OPENSSL_API_COMPAT < 0x10100000L +# define SSL_library_init() OPENSSL_init_ssl(0, NULL) +# endif + +__owur char *SSL_CIPHER_description(const SSL_CIPHER *, char *buf, int size); +__owur STACK_OF(X509_NAME) *SSL_dup_CA_list(const STACK_OF(X509_NAME) *sk); + +__owur SSL *SSL_dup(SSL *ssl); + +__owur X509 *SSL_get_certificate(const SSL *ssl); +/* + * EVP_PKEY + */ +struct evp_pkey_st *SSL_get_privatekey(const SSL *ssl); + +__owur X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx); +__owur EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx); + +void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx, int mode); +__owur int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx); +void SSL_set_quiet_shutdown(SSL *ssl, int mode); +__owur int SSL_get_quiet_shutdown(const SSL *ssl); +void SSL_set_shutdown(SSL *ssl, int mode); +__owur int SSL_get_shutdown(const SSL *ssl); +__owur int SSL_version(const SSL *ssl); +__owur int SSL_client_version(const SSL *s); +__owur int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx); +__owur int SSL_CTX_set_default_verify_dir(SSL_CTX *ctx); +__owur int SSL_CTX_set_default_verify_file(SSL_CTX *ctx); +__owur int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, + const char *CApath); +# define SSL_get0_session SSL_get_session/* just peek at pointer */ +__owur SSL_SESSION *SSL_get_session(const SSL *ssl); +__owur SSL_SESSION *SSL_get1_session(SSL *ssl); /* obtain a reference count */ +__owur SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl); +SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx); +void SSL_set_info_callback(SSL *ssl, + void (*cb) (const SSL *ssl, int type, int val)); +void (*SSL_get_info_callback(const SSL *ssl)) (const SSL *ssl, int type, + int val); +__owur OSSL_HANDSHAKE_STATE SSL_get_state(const SSL *ssl); + +void SSL_set_verify_result(SSL *ssl, long v); +__owur long SSL_get_verify_result(const SSL *ssl); +__owur STACK_OF(X509) *SSL_get0_verified_chain(const SSL *s); + +__owur size_t SSL_get_client_random(const SSL *ssl, unsigned char *out, + size_t outlen); +__owur size_t SSL_get_server_random(const SSL *ssl, unsigned char *out, + size_t outlen); +__owur size_t SSL_SESSION_get_master_key(const SSL_SESSION *sess, + unsigned char *out, size_t outlen); +__owur int SSL_SESSION_set1_master_key(SSL_SESSION *sess, + const unsigned char *in, size_t len); +uint8_t SSL_SESSION_get_max_fragment_length(const SSL_SESSION *sess); + +#define SSL_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, l, p, newf, dupf, freef) +__owur int SSL_set_ex_data(SSL *ssl, int idx, void *data); +void *SSL_get_ex_data(const SSL *ssl, int idx); +#define SSL_SESSION_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, l, p, newf, dupf, freef) +__owur int SSL_SESSION_set_ex_data(SSL_SESSION *ss, int idx, void *data); +void *SSL_SESSION_get_ex_data(const SSL_SESSION *ss, int idx); +#define SSL_CTX_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_CTX, l, p, newf, dupf, freef) +__owur int SSL_CTX_set_ex_data(SSL_CTX *ssl, int idx, void *data); +void *SSL_CTX_get_ex_data(const SSL_CTX *ssl, int idx); + +__owur int SSL_get_ex_data_X509_STORE_CTX_idx(void); + +# define SSL_CTX_sess_set_cache_size(ctx,t) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_SIZE,t,NULL) +# define SSL_CTX_sess_get_cache_size(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_SIZE,0,NULL) +# define SSL_CTX_set_session_cache_mode(ctx,m) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_MODE,m,NULL) +# define SSL_CTX_get_session_cache_mode(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_MODE,0,NULL) + +# define SSL_CTX_get_default_read_ahead(ctx) SSL_CTX_get_read_ahead(ctx) +# define SSL_CTX_set_default_read_ahead(ctx,m) SSL_CTX_set_read_ahead(ctx,m) +# define SSL_CTX_get_read_ahead(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_READ_AHEAD,0,NULL) +# define SSL_CTX_set_read_ahead(ctx,m) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_READ_AHEAD,m,NULL) +# define SSL_CTX_get_max_cert_list(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL) +# define SSL_CTX_set_max_cert_list(ctx,m) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL) +# define SSL_get_max_cert_list(ssl) \ + SSL_ctrl(ssl,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL) +# define SSL_set_max_cert_list(ssl,m) \ + SSL_ctrl(ssl,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL) + +# define SSL_CTX_set_max_send_fragment(ctx,m) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_SEND_FRAGMENT,m,NULL) +# define SSL_set_max_send_fragment(ssl,m) \ + SSL_ctrl(ssl,SSL_CTRL_SET_MAX_SEND_FRAGMENT,m,NULL) +# define SSL_CTX_set_split_send_fragment(ctx,m) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SPLIT_SEND_FRAGMENT,m,NULL) +# define SSL_set_split_send_fragment(ssl,m) \ + SSL_ctrl(ssl,SSL_CTRL_SET_SPLIT_SEND_FRAGMENT,m,NULL) +# define SSL_CTX_set_max_pipelines(ctx,m) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_PIPELINES,m,NULL) +# define SSL_set_max_pipelines(ssl,m) \ + SSL_ctrl(ssl,SSL_CTRL_SET_MAX_PIPELINES,m,NULL) + +void SSL_CTX_set_default_read_buffer_len(SSL_CTX *ctx, size_t len); +void SSL_set_default_read_buffer_len(SSL *s, size_t len); + +# ifndef OPENSSL_NO_DH +/* NB: the |keylength| is only applicable when is_export is true */ +void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx, + DH *(*dh) (SSL *ssl, int is_export, + int keylength)); +void SSL_set_tmp_dh_callback(SSL *ssl, + DH *(*dh) (SSL *ssl, int is_export, + int keylength)); +# endif + +__owur const COMP_METHOD *SSL_get_current_compression(const SSL *s); +__owur const COMP_METHOD *SSL_get_current_expansion(const SSL *s); +__owur const char *SSL_COMP_get_name(const COMP_METHOD *comp); +__owur const char *SSL_COMP_get0_name(const SSL_COMP *comp); +__owur int SSL_COMP_get_id(const SSL_COMP *comp); +STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void); +__owur STACK_OF(SSL_COMP) *SSL_COMP_set0_compression_methods(STACK_OF(SSL_COMP) + *meths); +# if OPENSSL_API_COMPAT < 0x10100000L +# define SSL_COMP_free_compression_methods() while(0) continue +# endif +__owur int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm); + +const SSL_CIPHER *SSL_CIPHER_find(SSL *ssl, const unsigned char *ptr); +int SSL_CIPHER_get_cipher_nid(const SSL_CIPHER *c); +int SSL_CIPHER_get_digest_nid(const SSL_CIPHER *c); +int SSL_bytes_to_cipher_list(SSL *s, const unsigned char *bytes, size_t len, + int isv2format, STACK_OF(SSL_CIPHER) **sk, + STACK_OF(SSL_CIPHER) **scsvs); + +/* TLS extensions functions */ +__owur int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len); + +__owur int SSL_set_session_ticket_ext_cb(SSL *s, + tls_session_ticket_ext_cb_fn cb, + void *arg); + +/* Pre-shared secret session resumption functions */ +__owur int SSL_set_session_secret_cb(SSL *s, + tls_session_secret_cb_fn session_secret_cb, + void *arg); + +void SSL_CTX_set_not_resumable_session_callback(SSL_CTX *ctx, + int (*cb) (SSL *ssl, + int + is_forward_secure)); + +void SSL_set_not_resumable_session_callback(SSL *ssl, + int (*cb) (SSL *ssl, + int is_forward_secure)); + +void SSL_CTX_set_record_padding_callback(SSL_CTX *ctx, + size_t (*cb) (SSL *ssl, int type, + size_t len, void *arg)); +void SSL_CTX_set_record_padding_callback_arg(SSL_CTX *ctx, void *arg); +void *SSL_CTX_get_record_padding_callback_arg(const SSL_CTX *ctx); +int SSL_CTX_set_block_padding(SSL_CTX *ctx, size_t block_size); + +void SSL_set_record_padding_callback(SSL *ssl, + size_t (*cb) (SSL *ssl, int type, + size_t len, void *arg)); +void SSL_set_record_padding_callback_arg(SSL *ssl, void *arg); +void *SSL_get_record_padding_callback_arg(const SSL *ssl); +int SSL_set_block_padding(SSL *ssl, size_t block_size); + +int SSL_set_num_tickets(SSL *s, size_t num_tickets); +size_t SSL_get_num_tickets(const SSL *s); +int SSL_CTX_set_num_tickets(SSL_CTX *ctx, size_t num_tickets); +size_t SSL_CTX_get_num_tickets(const SSL_CTX *ctx); + +# if OPENSSL_API_COMPAT < 0x10100000L +# define SSL_cache_hit(s) SSL_session_reused(s) +# endif + +__owur int SSL_session_reused(SSL *s); +__owur int SSL_is_server(const SSL *s); + +__owur __owur SSL_CONF_CTX *SSL_CONF_CTX_new(void); +int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx); +void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx); +unsigned int SSL_CONF_CTX_set_flags(SSL_CONF_CTX *cctx, unsigned int flags); +__owur unsigned int SSL_CONF_CTX_clear_flags(SSL_CONF_CTX *cctx, + unsigned int flags); +__owur int SSL_CONF_CTX_set1_prefix(SSL_CONF_CTX *cctx, const char *pre); + +void SSL_CONF_CTX_set_ssl(SSL_CONF_CTX *cctx, SSL *ssl); +void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx); + +__owur int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value); +__owur int SSL_CONF_cmd_argv(SSL_CONF_CTX *cctx, int *pargc, char ***pargv); +__owur int SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd); + +void SSL_add_ssl_module(void); +int SSL_config(SSL *s, const char *name); +int SSL_CTX_config(SSL_CTX *ctx, const char *name); + +# ifndef OPENSSL_NO_SSL_TRACE +void SSL_trace(int write_p, int version, int content_type, + const void *buf, size_t len, SSL *ssl, void *arg); +# endif + +# ifndef OPENSSL_NO_SOCK +int DTLSv1_listen(SSL *s, BIO_ADDR *client); +# endif + +# ifndef OPENSSL_NO_CT + +/* + * A callback for verifying that the received SCTs are sufficient. + * Expected to return 1 if they are sufficient, otherwise 0. + * May return a negative integer if an error occurs. + * A connection should be aborted if the SCTs are deemed insufficient. + */ +typedef int (*ssl_ct_validation_cb)(const CT_POLICY_EVAL_CTX *ctx, + const STACK_OF(SCT) *scts, void *arg); + +/* + * Sets a |callback| that is invoked upon receipt of ServerHelloDone to validate + * the received SCTs. + * If the callback returns a non-positive result, the connection is terminated. + * Call this function before beginning a handshake. + * If a NULL |callback| is provided, SCT validation is disabled. + * |arg| is arbitrary userdata that will be passed to the callback whenever it + * is invoked. Ownership of |arg| remains with the caller. + * + * NOTE: A side-effect of setting a CT callback is that an OCSP stapled response + * will be requested. + */ +int SSL_set_ct_validation_callback(SSL *s, ssl_ct_validation_cb callback, + void *arg); +int SSL_CTX_set_ct_validation_callback(SSL_CTX *ctx, + ssl_ct_validation_cb callback, + void *arg); +#define SSL_disable_ct(s) \ + ((void) SSL_set_validation_callback((s), NULL, NULL)) +#define SSL_CTX_disable_ct(ctx) \ + ((void) SSL_CTX_set_validation_callback((ctx), NULL, NULL)) + +/* + * The validation type enumerates the available behaviours of the built-in SSL + * CT validation callback selected via SSL_enable_ct() and SSL_CTX_enable_ct(). + * The underlying callback is a static function in libssl. + */ +enum { + SSL_CT_VALIDATION_PERMISSIVE = 0, + SSL_CT_VALIDATION_STRICT +}; + +/* + * Enable CT by setting up a callback that implements one of the built-in + * validation variants. The SSL_CT_VALIDATION_PERMISSIVE variant always + * continues the handshake, the application can make appropriate decisions at + * handshake completion. The SSL_CT_VALIDATION_STRICT variant requires at + * least one valid SCT, or else handshake termination will be requested. The + * handshake may continue anyway if SSL_VERIFY_NONE is in effect. + */ +int SSL_enable_ct(SSL *s, int validation_mode); +int SSL_CTX_enable_ct(SSL_CTX *ctx, int validation_mode); + +/* + * Report whether a non-NULL callback is enabled. + */ +int SSL_ct_is_enabled(const SSL *s); +int SSL_CTX_ct_is_enabled(const SSL_CTX *ctx); + +/* Gets the SCTs received from a connection */ +const STACK_OF(SCT) *SSL_get0_peer_scts(SSL *s); + +/* + * Loads the CT log list from the default location. + * If a CTLOG_STORE has previously been set using SSL_CTX_set_ctlog_store, + * the log information loaded from this file will be appended to the + * CTLOG_STORE. + * Returns 1 on success, 0 otherwise. + */ +int SSL_CTX_set_default_ctlog_list_file(SSL_CTX *ctx); + +/* + * Loads the CT log list from the specified file path. + * If a CTLOG_STORE has previously been set using SSL_CTX_set_ctlog_store, + * the log information loaded from this file will be appended to the + * CTLOG_STORE. + * Returns 1 on success, 0 otherwise. + */ +int SSL_CTX_set_ctlog_list_file(SSL_CTX *ctx, const char *path); + +/* + * Sets the CT log list used by all SSL connections created from this SSL_CTX. + * Ownership of the CTLOG_STORE is transferred to the SSL_CTX. + */ +void SSL_CTX_set0_ctlog_store(SSL_CTX *ctx, CTLOG_STORE *logs); + +/* + * Gets the CT log list used by all SSL connections created from this SSL_CTX. + * This will be NULL unless one of the following functions has been called: + * - SSL_CTX_set_default_ctlog_list_file + * - SSL_CTX_set_ctlog_list_file + * - SSL_CTX_set_ctlog_store + */ +const CTLOG_STORE *SSL_CTX_get0_ctlog_store(const SSL_CTX *ctx); + +# endif /* OPENSSL_NO_CT */ + +/* What the "other" parameter contains in security callback */ +/* Mask for type */ +# define SSL_SECOP_OTHER_TYPE 0xffff0000 +# define SSL_SECOP_OTHER_NONE 0 +# define SSL_SECOP_OTHER_CIPHER (1 << 16) +# define SSL_SECOP_OTHER_CURVE (2 << 16) +# define SSL_SECOP_OTHER_DH (3 << 16) +# define SSL_SECOP_OTHER_PKEY (4 << 16) +# define SSL_SECOP_OTHER_SIGALG (5 << 16) +# define SSL_SECOP_OTHER_CERT (6 << 16) + +/* Indicated operation refers to peer key or certificate */ +# define SSL_SECOP_PEER 0x1000 + +/* Values for "op" parameter in security callback */ + +/* Called to filter ciphers */ +/* Ciphers client supports */ +# define SSL_SECOP_CIPHER_SUPPORTED (1 | SSL_SECOP_OTHER_CIPHER) +/* Cipher shared by client/server */ +# define SSL_SECOP_CIPHER_SHARED (2 | SSL_SECOP_OTHER_CIPHER) +/* Sanity check of cipher server selects */ +# define SSL_SECOP_CIPHER_CHECK (3 | SSL_SECOP_OTHER_CIPHER) +/* Curves supported by client */ +# define SSL_SECOP_CURVE_SUPPORTED (4 | SSL_SECOP_OTHER_CURVE) +/* Curves shared by client/server */ +# define SSL_SECOP_CURVE_SHARED (5 | SSL_SECOP_OTHER_CURVE) +/* Sanity check of curve server selects */ +# define SSL_SECOP_CURVE_CHECK (6 | SSL_SECOP_OTHER_CURVE) +/* Temporary DH key */ +# define SSL_SECOP_TMP_DH (7 | SSL_SECOP_OTHER_PKEY) +/* SSL/TLS version */ +# define SSL_SECOP_VERSION (9 | SSL_SECOP_OTHER_NONE) +/* Session tickets */ +# define SSL_SECOP_TICKET (10 | SSL_SECOP_OTHER_NONE) +/* Supported signature algorithms sent to peer */ +# define SSL_SECOP_SIGALG_SUPPORTED (11 | SSL_SECOP_OTHER_SIGALG) +/* Shared signature algorithm */ +# define SSL_SECOP_SIGALG_SHARED (12 | SSL_SECOP_OTHER_SIGALG) +/* Sanity check signature algorithm allowed */ +# define SSL_SECOP_SIGALG_CHECK (13 | SSL_SECOP_OTHER_SIGALG) +/* Used to get mask of supported public key signature algorithms */ +# define SSL_SECOP_SIGALG_MASK (14 | SSL_SECOP_OTHER_SIGALG) +/* Use to see if compression is allowed */ +# define SSL_SECOP_COMPRESSION (15 | SSL_SECOP_OTHER_NONE) +/* EE key in certificate */ +# define SSL_SECOP_EE_KEY (16 | SSL_SECOP_OTHER_CERT) +/* CA key in certificate */ +# define SSL_SECOP_CA_KEY (17 | SSL_SECOP_OTHER_CERT) +/* CA digest algorithm in certificate */ +# define SSL_SECOP_CA_MD (18 | SSL_SECOP_OTHER_CERT) +/* Peer EE key in certificate */ +# define SSL_SECOP_PEER_EE_KEY (SSL_SECOP_EE_KEY | SSL_SECOP_PEER) +/* Peer CA key in certificate */ +# define SSL_SECOP_PEER_CA_KEY (SSL_SECOP_CA_KEY | SSL_SECOP_PEER) +/* Peer CA digest algorithm in certificate */ +# define SSL_SECOP_PEER_CA_MD (SSL_SECOP_CA_MD | SSL_SECOP_PEER) + +void SSL_set_security_level(SSL *s, int level); +__owur int SSL_get_security_level(const SSL *s); +void SSL_set_security_callback(SSL *s, + int (*cb) (const SSL *s, const SSL_CTX *ctx, + int op, int bits, int nid, + void *other, void *ex)); +int (*SSL_get_security_callback(const SSL *s)) (const SSL *s, + const SSL_CTX *ctx, int op, + int bits, int nid, void *other, + void *ex); +void SSL_set0_security_ex_data(SSL *s, void *ex); +__owur void *SSL_get0_security_ex_data(const SSL *s); + +void SSL_CTX_set_security_level(SSL_CTX *ctx, int level); +__owur int SSL_CTX_get_security_level(const SSL_CTX *ctx); +void SSL_CTX_set_security_callback(SSL_CTX *ctx, + int (*cb) (const SSL *s, const SSL_CTX *ctx, + int op, int bits, int nid, + void *other, void *ex)); +int (*SSL_CTX_get_security_callback(const SSL_CTX *ctx)) (const SSL *s, + const SSL_CTX *ctx, + int op, int bits, + int nid, + void *other, + void *ex); +void SSL_CTX_set0_security_ex_data(SSL_CTX *ctx, void *ex); +__owur void *SSL_CTX_get0_security_ex_data(const SSL_CTX *ctx); + +/* OPENSSL_INIT flag 0x010000 reserved for internal use */ +# define OPENSSL_INIT_NO_LOAD_SSL_STRINGS 0x00100000L +# define OPENSSL_INIT_LOAD_SSL_STRINGS 0x00200000L + +# define OPENSSL_INIT_SSL_DEFAULT \ + (OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_LOAD_CRYPTO_STRINGS) + +int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings); + +# ifndef OPENSSL_NO_UNIT_TEST +__owur const struct openssl_ssl_test_functions *SSL_test_functions(void); +# endif + +__owur int SSL_free_buffers(SSL *ssl); +__owur int SSL_alloc_buffers(SSL *ssl); + +/* Status codes passed to the decrypt session ticket callback. Some of these + * are for internal use only and are never passed to the callback. */ +typedef int SSL_TICKET_STATUS; + +/* Support for ticket appdata */ +/* fatal error, malloc failure */ +# define SSL_TICKET_FATAL_ERR_MALLOC 0 +/* fatal error, either from parsing or decrypting the ticket */ +# define SSL_TICKET_FATAL_ERR_OTHER 1 +/* No ticket present */ +# define SSL_TICKET_NONE 2 +/* Empty ticket present */ +# define SSL_TICKET_EMPTY 3 +/* the ticket couldn't be decrypted */ +# define SSL_TICKET_NO_DECRYPT 4 +/* a ticket was successfully decrypted */ +# define SSL_TICKET_SUCCESS 5 +/* same as above but the ticket needs to be renewed */ +# define SSL_TICKET_SUCCESS_RENEW 6 + +/* Return codes for the decrypt session ticket callback */ +typedef int SSL_TICKET_RETURN; + +/* An error occurred */ +#define SSL_TICKET_RETURN_ABORT 0 +/* Do not use the ticket, do not send a renewed ticket to the client */ +#define SSL_TICKET_RETURN_IGNORE 1 +/* Do not use the ticket, send a renewed ticket to the client */ +#define SSL_TICKET_RETURN_IGNORE_RENEW 2 +/* Use the ticket, do not send a renewed ticket to the client */ +#define SSL_TICKET_RETURN_USE 3 +/* Use the ticket, send a renewed ticket to the client */ +#define SSL_TICKET_RETURN_USE_RENEW 4 + +typedef int (*SSL_CTX_generate_session_ticket_fn)(SSL *s, void *arg); +typedef SSL_TICKET_RETURN (*SSL_CTX_decrypt_session_ticket_fn)(SSL *s, SSL_SESSION *ss, + const unsigned char *keyname, + size_t keyname_length, + SSL_TICKET_STATUS status, + void *arg); +int SSL_CTX_set_session_ticket_cb(SSL_CTX *ctx, + SSL_CTX_generate_session_ticket_fn gen_cb, + SSL_CTX_decrypt_session_ticket_fn dec_cb, + void *arg); +int SSL_SESSION_set1_ticket_appdata(SSL_SESSION *ss, const void *data, size_t len); +int SSL_SESSION_get0_ticket_appdata(SSL_SESSION *ss, void **data, size_t *len); + +extern const char SSL_version_str[]; + +typedef unsigned int (*DTLS_timer_cb)(SSL *s, unsigned int timer_us); + +void DTLS_set_timer_cb(SSL *s, DTLS_timer_cb cb); + + +typedef int (*SSL_allow_early_data_cb_fn)(SSL *s, void *arg); +void SSL_CTX_set_allow_early_data_cb(SSL_CTX *ctx, + SSL_allow_early_data_cb_fn cb, + void *arg); +void SSL_set_allow_early_data_cb(SSL *s, + SSL_allow_early_data_cb_fn cb, + void *arg); + +# ifdef __cplusplus +} +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/ssl2.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ssl2.h new file mode 100644 index 000000000..5321bd272 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ssl2.h @@ -0,0 +1,24 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_SSL2_H +# define HEADER_SSL2_H + +#ifdef __cplusplus +extern "C" { +#endif + +# define SSL2_VERSION 0x0002 + +# define SSL2_MT_CLIENT_HELLO 1 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/ssl3.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ssl3.h new file mode 100644 index 000000000..8d01fcc48 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ssl3.h @@ -0,0 +1,339 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_SSL3_H +# define HEADER_SSL3_H + +# include +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Signalling cipher suite value from RFC 5746 + * (TLS_EMPTY_RENEGOTIATION_INFO_SCSV) + */ +# define SSL3_CK_SCSV 0x030000FF + +/* + * Signalling cipher suite value from draft-ietf-tls-downgrade-scsv-00 + * (TLS_FALLBACK_SCSV) + */ +# define SSL3_CK_FALLBACK_SCSV 0x03005600 + +# define SSL3_CK_RSA_NULL_MD5 0x03000001 +# define SSL3_CK_RSA_NULL_SHA 0x03000002 +# define SSL3_CK_RSA_RC4_40_MD5 0x03000003 +# define SSL3_CK_RSA_RC4_128_MD5 0x03000004 +# define SSL3_CK_RSA_RC4_128_SHA 0x03000005 +# define SSL3_CK_RSA_RC2_40_MD5 0x03000006 +# define SSL3_CK_RSA_IDEA_128_SHA 0x03000007 +# define SSL3_CK_RSA_DES_40_CBC_SHA 0x03000008 +# define SSL3_CK_RSA_DES_64_CBC_SHA 0x03000009 +# define SSL3_CK_RSA_DES_192_CBC3_SHA 0x0300000A + +# define SSL3_CK_DH_DSS_DES_40_CBC_SHA 0x0300000B +# define SSL3_CK_DH_DSS_DES_64_CBC_SHA 0x0300000C +# define SSL3_CK_DH_DSS_DES_192_CBC3_SHA 0x0300000D +# define SSL3_CK_DH_RSA_DES_40_CBC_SHA 0x0300000E +# define SSL3_CK_DH_RSA_DES_64_CBC_SHA 0x0300000F +# define SSL3_CK_DH_RSA_DES_192_CBC3_SHA 0x03000010 + +# define SSL3_CK_DHE_DSS_DES_40_CBC_SHA 0x03000011 +# define SSL3_CK_EDH_DSS_DES_40_CBC_SHA SSL3_CK_DHE_DSS_DES_40_CBC_SHA +# define SSL3_CK_DHE_DSS_DES_64_CBC_SHA 0x03000012 +# define SSL3_CK_EDH_DSS_DES_64_CBC_SHA SSL3_CK_DHE_DSS_DES_64_CBC_SHA +# define SSL3_CK_DHE_DSS_DES_192_CBC3_SHA 0x03000013 +# define SSL3_CK_EDH_DSS_DES_192_CBC3_SHA SSL3_CK_DHE_DSS_DES_192_CBC3_SHA +# define SSL3_CK_DHE_RSA_DES_40_CBC_SHA 0x03000014 +# define SSL3_CK_EDH_RSA_DES_40_CBC_SHA SSL3_CK_DHE_RSA_DES_40_CBC_SHA +# define SSL3_CK_DHE_RSA_DES_64_CBC_SHA 0x03000015 +# define SSL3_CK_EDH_RSA_DES_64_CBC_SHA SSL3_CK_DHE_RSA_DES_64_CBC_SHA +# define SSL3_CK_DHE_RSA_DES_192_CBC3_SHA 0x03000016 +# define SSL3_CK_EDH_RSA_DES_192_CBC3_SHA SSL3_CK_DHE_RSA_DES_192_CBC3_SHA + +# define SSL3_CK_ADH_RC4_40_MD5 0x03000017 +# define SSL3_CK_ADH_RC4_128_MD5 0x03000018 +# define SSL3_CK_ADH_DES_40_CBC_SHA 0x03000019 +# define SSL3_CK_ADH_DES_64_CBC_SHA 0x0300001A +# define SSL3_CK_ADH_DES_192_CBC_SHA 0x0300001B + +/* a bundle of RFC standard cipher names, generated from ssl3_ciphers[] */ +# define SSL3_RFC_RSA_NULL_MD5 "TLS_RSA_WITH_NULL_MD5" +# define SSL3_RFC_RSA_NULL_SHA "TLS_RSA_WITH_NULL_SHA" +# define SSL3_RFC_RSA_DES_192_CBC3_SHA "TLS_RSA_WITH_3DES_EDE_CBC_SHA" +# define SSL3_RFC_DHE_DSS_DES_192_CBC3_SHA "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA" +# define SSL3_RFC_DHE_RSA_DES_192_CBC3_SHA "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA" +# define SSL3_RFC_ADH_DES_192_CBC_SHA "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA" +# define SSL3_RFC_RSA_IDEA_128_SHA "TLS_RSA_WITH_IDEA_CBC_SHA" +# define SSL3_RFC_RSA_RC4_128_MD5 "TLS_RSA_WITH_RC4_128_MD5" +# define SSL3_RFC_RSA_RC4_128_SHA "TLS_RSA_WITH_RC4_128_SHA" +# define SSL3_RFC_ADH_RC4_128_MD5 "TLS_DH_anon_WITH_RC4_128_MD5" + +# define SSL3_TXT_RSA_NULL_MD5 "NULL-MD5" +# define SSL3_TXT_RSA_NULL_SHA "NULL-SHA" +# define SSL3_TXT_RSA_RC4_40_MD5 "EXP-RC4-MD5" +# define SSL3_TXT_RSA_RC4_128_MD5 "RC4-MD5" +# define SSL3_TXT_RSA_RC4_128_SHA "RC4-SHA" +# define SSL3_TXT_RSA_RC2_40_MD5 "EXP-RC2-CBC-MD5" +# define SSL3_TXT_RSA_IDEA_128_SHA "IDEA-CBC-SHA" +# define SSL3_TXT_RSA_DES_40_CBC_SHA "EXP-DES-CBC-SHA" +# define SSL3_TXT_RSA_DES_64_CBC_SHA "DES-CBC-SHA" +# define SSL3_TXT_RSA_DES_192_CBC3_SHA "DES-CBC3-SHA" + +# define SSL3_TXT_DH_DSS_DES_40_CBC_SHA "EXP-DH-DSS-DES-CBC-SHA" +# define SSL3_TXT_DH_DSS_DES_64_CBC_SHA "DH-DSS-DES-CBC-SHA" +# define SSL3_TXT_DH_DSS_DES_192_CBC3_SHA "DH-DSS-DES-CBC3-SHA" +# define SSL3_TXT_DH_RSA_DES_40_CBC_SHA "EXP-DH-RSA-DES-CBC-SHA" +# define SSL3_TXT_DH_RSA_DES_64_CBC_SHA "DH-RSA-DES-CBC-SHA" +# define SSL3_TXT_DH_RSA_DES_192_CBC3_SHA "DH-RSA-DES-CBC3-SHA" + +# define SSL3_TXT_DHE_DSS_DES_40_CBC_SHA "EXP-DHE-DSS-DES-CBC-SHA" +# define SSL3_TXT_DHE_DSS_DES_64_CBC_SHA "DHE-DSS-DES-CBC-SHA" +# define SSL3_TXT_DHE_DSS_DES_192_CBC3_SHA "DHE-DSS-DES-CBC3-SHA" +# define SSL3_TXT_DHE_RSA_DES_40_CBC_SHA "EXP-DHE-RSA-DES-CBC-SHA" +# define SSL3_TXT_DHE_RSA_DES_64_CBC_SHA "DHE-RSA-DES-CBC-SHA" +# define SSL3_TXT_DHE_RSA_DES_192_CBC3_SHA "DHE-RSA-DES-CBC3-SHA" + +/* + * This next block of six "EDH" labels is for backward compatibility with + * older versions of OpenSSL. New code should use the six "DHE" labels above + * instead: + */ +# define SSL3_TXT_EDH_DSS_DES_40_CBC_SHA "EXP-EDH-DSS-DES-CBC-SHA" +# define SSL3_TXT_EDH_DSS_DES_64_CBC_SHA "EDH-DSS-DES-CBC-SHA" +# define SSL3_TXT_EDH_DSS_DES_192_CBC3_SHA "EDH-DSS-DES-CBC3-SHA" +# define SSL3_TXT_EDH_RSA_DES_40_CBC_SHA "EXP-EDH-RSA-DES-CBC-SHA" +# define SSL3_TXT_EDH_RSA_DES_64_CBC_SHA "EDH-RSA-DES-CBC-SHA" +# define SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA "EDH-RSA-DES-CBC3-SHA" + +# define SSL3_TXT_ADH_RC4_40_MD5 "EXP-ADH-RC4-MD5" +# define SSL3_TXT_ADH_RC4_128_MD5 "ADH-RC4-MD5" +# define SSL3_TXT_ADH_DES_40_CBC_SHA "EXP-ADH-DES-CBC-SHA" +# define SSL3_TXT_ADH_DES_64_CBC_SHA "ADH-DES-CBC-SHA" +# define SSL3_TXT_ADH_DES_192_CBC_SHA "ADH-DES-CBC3-SHA" + +# define SSL3_SSL_SESSION_ID_LENGTH 32 +# define SSL3_MAX_SSL_SESSION_ID_LENGTH 32 + +# define SSL3_MASTER_SECRET_SIZE 48 +# define SSL3_RANDOM_SIZE 32 +# define SSL3_SESSION_ID_SIZE 32 +# define SSL3_RT_HEADER_LENGTH 5 + +# define SSL3_HM_HEADER_LENGTH 4 + +# ifndef SSL3_ALIGN_PAYLOAD + /* + * Some will argue that this increases memory footprint, but it's not + * actually true. Point is that malloc has to return at least 64-bit aligned + * pointers, meaning that allocating 5 bytes wastes 3 bytes in either case. + * Suggested pre-gaping simply moves these wasted bytes from the end of + * allocated region to its front, but makes data payload aligned, which + * improves performance:-) + */ +# define SSL3_ALIGN_PAYLOAD 8 +# else +# if (SSL3_ALIGN_PAYLOAD&(SSL3_ALIGN_PAYLOAD-1))!=0 +# error "insane SSL3_ALIGN_PAYLOAD" +# undef SSL3_ALIGN_PAYLOAD +# endif +# endif + +/* + * This is the maximum MAC (digest) size used by the SSL library. Currently + * maximum of 20 is used by SHA1, but we reserve for future extension for + * 512-bit hashes. + */ + +# define SSL3_RT_MAX_MD_SIZE 64 + +/* + * Maximum block size used in all ciphersuites. Currently 16 for AES. + */ + +# define SSL_RT_MAX_CIPHER_BLOCK_SIZE 16 + +# define SSL3_RT_MAX_EXTRA (16384) + +/* Maximum plaintext length: defined by SSL/TLS standards */ +# define SSL3_RT_MAX_PLAIN_LENGTH 16384 +/* Maximum compression overhead: defined by SSL/TLS standards */ +# define SSL3_RT_MAX_COMPRESSED_OVERHEAD 1024 + +/* + * The standards give a maximum encryption overhead of 1024 bytes. In + * practice the value is lower than this. The overhead is the maximum number + * of padding bytes (256) plus the mac size. + */ +# define SSL3_RT_MAX_ENCRYPTED_OVERHEAD (256 + SSL3_RT_MAX_MD_SIZE) +# define SSL3_RT_MAX_TLS13_ENCRYPTED_OVERHEAD 256 + +/* + * OpenSSL currently only uses a padding length of at most one block so the + * send overhead is smaller. + */ + +# define SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD \ + (SSL_RT_MAX_CIPHER_BLOCK_SIZE + SSL3_RT_MAX_MD_SIZE) + +/* If compression isn't used don't include the compression overhead */ + +# ifdef OPENSSL_NO_COMP +# define SSL3_RT_MAX_COMPRESSED_LENGTH SSL3_RT_MAX_PLAIN_LENGTH +# else +# define SSL3_RT_MAX_COMPRESSED_LENGTH \ + (SSL3_RT_MAX_PLAIN_LENGTH+SSL3_RT_MAX_COMPRESSED_OVERHEAD) +# endif +# define SSL3_RT_MAX_ENCRYPTED_LENGTH \ + (SSL3_RT_MAX_ENCRYPTED_OVERHEAD+SSL3_RT_MAX_COMPRESSED_LENGTH) +# define SSL3_RT_MAX_TLS13_ENCRYPTED_LENGTH \ + (SSL3_RT_MAX_PLAIN_LENGTH + SSL3_RT_MAX_TLS13_ENCRYPTED_OVERHEAD) +# define SSL3_RT_MAX_PACKET_SIZE \ + (SSL3_RT_MAX_ENCRYPTED_LENGTH+SSL3_RT_HEADER_LENGTH) + +# define SSL3_MD_CLIENT_FINISHED_CONST "\x43\x4C\x4E\x54" +# define SSL3_MD_SERVER_FINISHED_CONST "\x53\x52\x56\x52" + +# define SSL3_VERSION 0x0300 +# define SSL3_VERSION_MAJOR 0x03 +# define SSL3_VERSION_MINOR 0x00 + +# define SSL3_RT_CHANGE_CIPHER_SPEC 20 +# define SSL3_RT_ALERT 21 +# define SSL3_RT_HANDSHAKE 22 +# define SSL3_RT_APPLICATION_DATA 23 +# define DTLS1_RT_HEARTBEAT 24 + +/* Pseudo content types to indicate additional parameters */ +# define TLS1_RT_CRYPTO 0x1000 +# define TLS1_RT_CRYPTO_PREMASTER (TLS1_RT_CRYPTO | 0x1) +# define TLS1_RT_CRYPTO_CLIENT_RANDOM (TLS1_RT_CRYPTO | 0x2) +# define TLS1_RT_CRYPTO_SERVER_RANDOM (TLS1_RT_CRYPTO | 0x3) +# define TLS1_RT_CRYPTO_MASTER (TLS1_RT_CRYPTO | 0x4) + +# define TLS1_RT_CRYPTO_READ 0x0000 +# define TLS1_RT_CRYPTO_WRITE 0x0100 +# define TLS1_RT_CRYPTO_MAC (TLS1_RT_CRYPTO | 0x5) +# define TLS1_RT_CRYPTO_KEY (TLS1_RT_CRYPTO | 0x6) +# define TLS1_RT_CRYPTO_IV (TLS1_RT_CRYPTO | 0x7) +# define TLS1_RT_CRYPTO_FIXED_IV (TLS1_RT_CRYPTO | 0x8) + +/* Pseudo content types for SSL/TLS header info */ +# define SSL3_RT_HEADER 0x100 +# define SSL3_RT_INNER_CONTENT_TYPE 0x101 + +# define SSL3_AL_WARNING 1 +# define SSL3_AL_FATAL 2 + +# define SSL3_AD_CLOSE_NOTIFY 0 +# define SSL3_AD_UNEXPECTED_MESSAGE 10/* fatal */ +# define SSL3_AD_BAD_RECORD_MAC 20/* fatal */ +# define SSL3_AD_DECOMPRESSION_FAILURE 30/* fatal */ +# define SSL3_AD_HANDSHAKE_FAILURE 40/* fatal */ +# define SSL3_AD_NO_CERTIFICATE 41 +# define SSL3_AD_BAD_CERTIFICATE 42 +# define SSL3_AD_UNSUPPORTED_CERTIFICATE 43 +# define SSL3_AD_CERTIFICATE_REVOKED 44 +# define SSL3_AD_CERTIFICATE_EXPIRED 45 +# define SSL3_AD_CERTIFICATE_UNKNOWN 46 +# define SSL3_AD_ILLEGAL_PARAMETER 47/* fatal */ + +# define TLS1_HB_REQUEST 1 +# define TLS1_HB_RESPONSE 2 + + +# define SSL3_CT_RSA_SIGN 1 +# define SSL3_CT_DSS_SIGN 2 +# define SSL3_CT_RSA_FIXED_DH 3 +# define SSL3_CT_DSS_FIXED_DH 4 +# define SSL3_CT_RSA_EPHEMERAL_DH 5 +# define SSL3_CT_DSS_EPHEMERAL_DH 6 +# define SSL3_CT_FORTEZZA_DMS 20 +/* + * SSL3_CT_NUMBER is used to size arrays and it must be large enough to + * contain all of the cert types defined for *either* SSLv3 and TLSv1. + */ +# define SSL3_CT_NUMBER 10 + +# if defined(TLS_CT_NUMBER) +# if TLS_CT_NUMBER != SSL3_CT_NUMBER +# error "SSL/TLS CT_NUMBER values do not match" +# endif +# endif + +/* No longer used as of OpenSSL 1.1.1 */ +# define SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS 0x0001 + +/* Removed from OpenSSL 1.1.0 */ +# define TLS1_FLAGS_TLS_PADDING_BUG 0x0 + +# define TLS1_FLAGS_SKIP_CERT_VERIFY 0x0010 + +/* Set if we encrypt then mac instead of usual mac then encrypt */ +# define TLS1_FLAGS_ENCRYPT_THEN_MAC_READ 0x0100 +# define TLS1_FLAGS_ENCRYPT_THEN_MAC TLS1_FLAGS_ENCRYPT_THEN_MAC_READ + +/* Set if extended master secret extension received from peer */ +# define TLS1_FLAGS_RECEIVED_EXTMS 0x0200 + +# define TLS1_FLAGS_ENCRYPT_THEN_MAC_WRITE 0x0400 + +# define TLS1_FLAGS_STATELESS 0x0800 + +# define SSL3_MT_HELLO_REQUEST 0 +# define SSL3_MT_CLIENT_HELLO 1 +# define SSL3_MT_SERVER_HELLO 2 +# define SSL3_MT_NEWSESSION_TICKET 4 +# define SSL3_MT_END_OF_EARLY_DATA 5 +# define SSL3_MT_ENCRYPTED_EXTENSIONS 8 +# define SSL3_MT_CERTIFICATE 11 +# define SSL3_MT_SERVER_KEY_EXCHANGE 12 +# define SSL3_MT_CERTIFICATE_REQUEST 13 +# define SSL3_MT_SERVER_DONE 14 +# define SSL3_MT_CERTIFICATE_VERIFY 15 +# define SSL3_MT_CLIENT_KEY_EXCHANGE 16 +# define SSL3_MT_FINISHED 20 +# define SSL3_MT_CERTIFICATE_URL 21 +# define SSL3_MT_CERTIFICATE_STATUS 22 +# define SSL3_MT_SUPPLEMENTAL_DATA 23 +# define SSL3_MT_KEY_UPDATE 24 +# ifndef OPENSSL_NO_NEXTPROTONEG +# define SSL3_MT_NEXT_PROTO 67 +# endif +# define SSL3_MT_MESSAGE_HASH 254 +# define DTLS1_MT_HELLO_VERIFY_REQUEST 3 + +/* Dummy message type for handling CCS like a normal handshake message */ +# define SSL3_MT_CHANGE_CIPHER_SPEC 0x0101 + +# define SSL3_MT_CCS 1 + +/* These are used when changing over to a new cipher */ +# define SSL3_CC_READ 0x001 +# define SSL3_CC_WRITE 0x002 +# define SSL3_CC_CLIENT 0x010 +# define SSL3_CC_SERVER 0x020 +# define SSL3_CC_EARLY 0x040 +# define SSL3_CC_HANDSHAKE 0x080 +# define SSL3_CC_APPLICATION 0x100 +# define SSL3_CHANGE_CIPHER_CLIENT_WRITE (SSL3_CC_CLIENT|SSL3_CC_WRITE) +# define SSL3_CHANGE_CIPHER_SERVER_READ (SSL3_CC_SERVER|SSL3_CC_READ) +# define SSL3_CHANGE_CIPHER_CLIENT_READ (SSL3_CC_CLIENT|SSL3_CC_READ) +# define SSL3_CHANGE_CIPHER_SERVER_WRITE (SSL3_CC_SERVER|SSL3_CC_WRITE) + +#ifdef __cplusplus +} +#endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/sslerr.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/sslerr.h new file mode 100644 index 000000000..a50a075b4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/sslerr.h @@ -0,0 +1,768 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_SSLERR_H +# define HEADER_SSLERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_SSL_strings(void); + +/* + * SSL function codes. + */ +# define SSL_F_ADD_CLIENT_KEY_SHARE_EXT 438 +# define SSL_F_ADD_KEY_SHARE 512 +# define SSL_F_BYTES_TO_CIPHER_LIST 519 +# define SSL_F_CHECK_SUITEB_CIPHER_LIST 331 +# define SSL_F_CIPHERSUITE_CB 622 +# define SSL_F_CONSTRUCT_CA_NAMES 552 +# define SSL_F_CONSTRUCT_KEY_EXCHANGE_TBS 553 +# define SSL_F_CONSTRUCT_STATEFUL_TICKET 636 +# define SSL_F_CONSTRUCT_STATELESS_TICKET 637 +# define SSL_F_CREATE_SYNTHETIC_MESSAGE_HASH 539 +# define SSL_F_CREATE_TICKET_PREQUEL 638 +# define SSL_F_CT_MOVE_SCTS 345 +# define SSL_F_CT_STRICT 349 +# define SSL_F_CUSTOM_EXT_ADD 554 +# define SSL_F_CUSTOM_EXT_PARSE 555 +# define SSL_F_D2I_SSL_SESSION 103 +# define SSL_F_DANE_CTX_ENABLE 347 +# define SSL_F_DANE_MTYPE_SET 393 +# define SSL_F_DANE_TLSA_ADD 394 +# define SSL_F_DERIVE_SECRET_KEY_AND_IV 514 +# define SSL_F_DO_DTLS1_WRITE 245 +# define SSL_F_DO_SSL3_WRITE 104 +# define SSL_F_DTLS1_BUFFER_RECORD 247 +# define SSL_F_DTLS1_CHECK_TIMEOUT_NUM 318 +# define SSL_F_DTLS1_HEARTBEAT 305 +# define SSL_F_DTLS1_HM_FRAGMENT_NEW 623 +# define SSL_F_DTLS1_PREPROCESS_FRAGMENT 288 +# define SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS 424 +# define SSL_F_DTLS1_PROCESS_RECORD 257 +# define SSL_F_DTLS1_READ_BYTES 258 +# define SSL_F_DTLS1_READ_FAILED 339 +# define SSL_F_DTLS1_RETRANSMIT_MESSAGE 390 +# define SSL_F_DTLS1_WRITE_APP_DATA_BYTES 268 +# define SSL_F_DTLS1_WRITE_BYTES 545 +# define SSL_F_DTLSV1_LISTEN 350 +# define SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC 371 +# define SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST 385 +# define SSL_F_DTLS_GET_REASSEMBLED_MESSAGE 370 +# define SSL_F_DTLS_PROCESS_HELLO_VERIFY 386 +# define SSL_F_DTLS_RECORD_LAYER_NEW 635 +# define SSL_F_DTLS_WAIT_FOR_DRY 592 +# define SSL_F_EARLY_DATA_COUNT_OK 532 +# define SSL_F_FINAL_EARLY_DATA 556 +# define SSL_F_FINAL_EC_PT_FORMATS 485 +# define SSL_F_FINAL_EMS 486 +# define SSL_F_FINAL_KEY_SHARE 503 +# define SSL_F_FINAL_MAXFRAGMENTLEN 557 +# define SSL_F_FINAL_RENEGOTIATE 483 +# define SSL_F_FINAL_SERVER_NAME 558 +# define SSL_F_FINAL_SIG_ALGS 497 +# define SSL_F_GET_CERT_VERIFY_TBS_DATA 588 +# define SSL_F_NSS_KEYLOG_INT 500 +# define SSL_F_OPENSSL_INIT_SSL 342 +# define SSL_F_OSSL_STATEM_CLIENT13_READ_TRANSITION 436 +# define SSL_F_OSSL_STATEM_CLIENT13_WRITE_TRANSITION 598 +# define SSL_F_OSSL_STATEM_CLIENT_CONSTRUCT_MESSAGE 430 +# define SSL_F_OSSL_STATEM_CLIENT_POST_PROCESS_MESSAGE 593 +# define SSL_F_OSSL_STATEM_CLIENT_PROCESS_MESSAGE 594 +# define SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION 417 +# define SSL_F_OSSL_STATEM_CLIENT_WRITE_TRANSITION 599 +# define SSL_F_OSSL_STATEM_SERVER13_READ_TRANSITION 437 +# define SSL_F_OSSL_STATEM_SERVER13_WRITE_TRANSITION 600 +# define SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE 431 +# define SSL_F_OSSL_STATEM_SERVER_POST_PROCESS_MESSAGE 601 +# define SSL_F_OSSL_STATEM_SERVER_POST_WORK 602 +# define SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE 603 +# define SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION 418 +# define SSL_F_OSSL_STATEM_SERVER_WRITE_TRANSITION 604 +# define SSL_F_PARSE_CA_NAMES 541 +# define SSL_F_PITEM_NEW 624 +# define SSL_F_PQUEUE_NEW 625 +# define SSL_F_PROCESS_KEY_SHARE_EXT 439 +# define SSL_F_READ_STATE_MACHINE 352 +# define SSL_F_SET_CLIENT_CIPHERSUITE 540 +# define SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET 595 +# define SSL_F_SRP_GENERATE_SERVER_MASTER_SECRET 589 +# define SSL_F_SRP_VERIFY_SERVER_PARAM 596 +# define SSL_F_SSL3_CHANGE_CIPHER_STATE 129 +# define SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM 130 +# define SSL_F_SSL3_CTRL 213 +# define SSL_F_SSL3_CTX_CTRL 133 +# define SSL_F_SSL3_DIGEST_CACHED_RECORDS 293 +# define SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC 292 +# define SSL_F_SSL3_ENC 608 +# define SSL_F_SSL3_FINAL_FINISH_MAC 285 +# define SSL_F_SSL3_FINISH_MAC 587 +# define SSL_F_SSL3_GENERATE_KEY_BLOCK 238 +# define SSL_F_SSL3_GENERATE_MASTER_SECRET 388 +# define SSL_F_SSL3_GET_RECORD 143 +# define SSL_F_SSL3_INIT_FINISHED_MAC 397 +# define SSL_F_SSL3_OUTPUT_CERT_CHAIN 147 +# define SSL_F_SSL3_READ_BYTES 148 +# define SSL_F_SSL3_READ_N 149 +# define SSL_F_SSL3_SETUP_KEY_BLOCK 157 +# define SSL_F_SSL3_SETUP_READ_BUFFER 156 +# define SSL_F_SSL3_SETUP_WRITE_BUFFER 291 +# define SSL_F_SSL3_WRITE_BYTES 158 +# define SSL_F_SSL3_WRITE_PENDING 159 +# define SSL_F_SSL_ADD_CERT_CHAIN 316 +# define SSL_F_SSL_ADD_CERT_TO_BUF 319 +# define SSL_F_SSL_ADD_CERT_TO_WPACKET 493 +# define SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT 298 +# define SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT 277 +# define SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT 307 +# define SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK 215 +# define SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK 216 +# define SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT 299 +# define SSL_F_SSL_ADD_SERVERHELLO_TLSEXT 278 +# define SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT 308 +# define SSL_F_SSL_BAD_METHOD 160 +# define SSL_F_SSL_BUILD_CERT_CHAIN 332 +# define SSL_F_SSL_BYTES_TO_CIPHER_LIST 161 +# define SSL_F_SSL_CACHE_CIPHERLIST 520 +# define SSL_F_SSL_CERT_ADD0_CHAIN_CERT 346 +# define SSL_F_SSL_CERT_DUP 221 +# define SSL_F_SSL_CERT_NEW 162 +# define SSL_F_SSL_CERT_SET0_CHAIN 340 +# define SSL_F_SSL_CHECK_PRIVATE_KEY 163 +# define SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT 280 +# define SSL_F_SSL_CHECK_SRP_EXT_CLIENTHELLO 606 +# define SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG 279 +# define SSL_F_SSL_CHOOSE_CLIENT_VERSION 607 +# define SSL_F_SSL_CIPHER_DESCRIPTION 626 +# define SSL_F_SSL_CIPHER_LIST_TO_BYTES 425 +# define SSL_F_SSL_CIPHER_PROCESS_RULESTR 230 +# define SSL_F_SSL_CIPHER_STRENGTH_SORT 231 +# define SSL_F_SSL_CLEAR 164 +# define SSL_F_SSL_CLIENT_HELLO_GET1_EXTENSIONS_PRESENT 627 +# define SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD 165 +# define SSL_F_SSL_CONF_CMD 334 +# define SSL_F_SSL_CREATE_CIPHER_LIST 166 +# define SSL_F_SSL_CTRL 232 +# define SSL_F_SSL_CTX_CHECK_PRIVATE_KEY 168 +# define SSL_F_SSL_CTX_ENABLE_CT 398 +# define SSL_F_SSL_CTX_MAKE_PROFILES 309 +# define SSL_F_SSL_CTX_NEW 169 +# define SSL_F_SSL_CTX_SET_ALPN_PROTOS 343 +# define SSL_F_SSL_CTX_SET_CIPHER_LIST 269 +# define SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE 290 +# define SSL_F_SSL_CTX_SET_CT_VALIDATION_CALLBACK 396 +# define SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT 219 +# define SSL_F_SSL_CTX_SET_SSL_VERSION 170 +# define SSL_F_SSL_CTX_SET_TLSEXT_MAX_FRAGMENT_LENGTH 551 +# define SSL_F_SSL_CTX_USE_CERTIFICATE 171 +# define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1 172 +# define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE 173 +# define SSL_F_SSL_CTX_USE_PRIVATEKEY 174 +# define SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1 175 +# define SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE 176 +# define SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT 272 +# define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY 177 +# define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1 178 +# define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE 179 +# define SSL_F_SSL_CTX_USE_SERVERINFO 336 +# define SSL_F_SSL_CTX_USE_SERVERINFO_EX 543 +# define SSL_F_SSL_CTX_USE_SERVERINFO_FILE 337 +# define SSL_F_SSL_DANE_DUP 403 +# define SSL_F_SSL_DANE_ENABLE 395 +# define SSL_F_SSL_DERIVE 590 +# define SSL_F_SSL_DO_CONFIG 391 +# define SSL_F_SSL_DO_HANDSHAKE 180 +# define SSL_F_SSL_DUP_CA_LIST 408 +# define SSL_F_SSL_ENABLE_CT 402 +# define SSL_F_SSL_GENERATE_PKEY_GROUP 559 +# define SSL_F_SSL_GENERATE_SESSION_ID 547 +# define SSL_F_SSL_GET_NEW_SESSION 181 +# define SSL_F_SSL_GET_PREV_SESSION 217 +# define SSL_F_SSL_GET_SERVER_CERT_INDEX 322 +# define SSL_F_SSL_GET_SIGN_PKEY 183 +# define SSL_F_SSL_HANDSHAKE_HASH 560 +# define SSL_F_SSL_INIT_WBIO_BUFFER 184 +# define SSL_F_SSL_KEY_UPDATE 515 +# define SSL_F_SSL_LOAD_CLIENT_CA_FILE 185 +# define SSL_F_SSL_LOG_MASTER_SECRET 498 +# define SSL_F_SSL_LOG_RSA_CLIENT_KEY_EXCHANGE 499 +# define SSL_F_SSL_MODULE_INIT 392 +# define SSL_F_SSL_NEW 186 +# define SSL_F_SSL_NEXT_PROTO_VALIDATE 565 +# define SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT 300 +# define SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT 302 +# define SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT 310 +# define SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT 301 +# define SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT 303 +# define SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT 311 +# define SSL_F_SSL_PEEK 270 +# define SSL_F_SSL_PEEK_EX 432 +# define SSL_F_SSL_PEEK_INTERNAL 522 +# define SSL_F_SSL_READ 223 +# define SSL_F_SSL_READ_EARLY_DATA 529 +# define SSL_F_SSL_READ_EX 434 +# define SSL_F_SSL_READ_INTERNAL 523 +# define SSL_F_SSL_RENEGOTIATE 516 +# define SSL_F_SSL_RENEGOTIATE_ABBREVIATED 546 +# define SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT 320 +# define SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT 321 +# define SSL_F_SSL_SESSION_DUP 348 +# define SSL_F_SSL_SESSION_NEW 189 +# define SSL_F_SSL_SESSION_PRINT_FP 190 +# define SSL_F_SSL_SESSION_SET1_ID 423 +# define SSL_F_SSL_SESSION_SET1_ID_CONTEXT 312 +# define SSL_F_SSL_SET_ALPN_PROTOS 344 +# define SSL_F_SSL_SET_CERT 191 +# define SSL_F_SSL_SET_CERT_AND_KEY 621 +# define SSL_F_SSL_SET_CIPHER_LIST 271 +# define SSL_F_SSL_SET_CT_VALIDATION_CALLBACK 399 +# define SSL_F_SSL_SET_FD 192 +# define SSL_F_SSL_SET_PKEY 193 +# define SSL_F_SSL_SET_RFD 194 +# define SSL_F_SSL_SET_SESSION 195 +# define SSL_F_SSL_SET_SESSION_ID_CONTEXT 218 +# define SSL_F_SSL_SET_SESSION_TICKET_EXT 294 +# define SSL_F_SSL_SET_TLSEXT_MAX_FRAGMENT_LENGTH 550 +# define SSL_F_SSL_SET_WFD 196 +# define SSL_F_SSL_SHUTDOWN 224 +# define SSL_F_SSL_SRP_CTX_INIT 313 +# define SSL_F_SSL_START_ASYNC_JOB 389 +# define SSL_F_SSL_UNDEFINED_FUNCTION 197 +# define SSL_F_SSL_UNDEFINED_VOID_FUNCTION 244 +# define SSL_F_SSL_USE_CERTIFICATE 198 +# define SSL_F_SSL_USE_CERTIFICATE_ASN1 199 +# define SSL_F_SSL_USE_CERTIFICATE_FILE 200 +# define SSL_F_SSL_USE_PRIVATEKEY 201 +# define SSL_F_SSL_USE_PRIVATEKEY_ASN1 202 +# define SSL_F_SSL_USE_PRIVATEKEY_FILE 203 +# define SSL_F_SSL_USE_PSK_IDENTITY_HINT 273 +# define SSL_F_SSL_USE_RSAPRIVATEKEY 204 +# define SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1 205 +# define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE 206 +# define SSL_F_SSL_VALIDATE_CT 400 +# define SSL_F_SSL_VERIFY_CERT_CHAIN 207 +# define SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE 616 +# define SSL_F_SSL_WRITE 208 +# define SSL_F_SSL_WRITE_EARLY_DATA 526 +# define SSL_F_SSL_WRITE_EARLY_FINISH 527 +# define SSL_F_SSL_WRITE_EX 433 +# define SSL_F_SSL_WRITE_INTERNAL 524 +# define SSL_F_STATE_MACHINE 353 +# define SSL_F_TLS12_CHECK_PEER_SIGALG 333 +# define SSL_F_TLS12_COPY_SIGALGS 533 +# define SSL_F_TLS13_CHANGE_CIPHER_STATE 440 +# define SSL_F_TLS13_ENC 609 +# define SSL_F_TLS13_FINAL_FINISH_MAC 605 +# define SSL_F_TLS13_GENERATE_SECRET 591 +# define SSL_F_TLS13_HKDF_EXPAND 561 +# define SSL_F_TLS13_RESTORE_HANDSHAKE_DIGEST_FOR_PHA 617 +# define SSL_F_TLS13_SAVE_HANDSHAKE_DIGEST_FOR_PHA 618 +# define SSL_F_TLS13_SETUP_KEY_BLOCK 441 +# define SSL_F_TLS1_CHANGE_CIPHER_STATE 209 +# define SSL_F_TLS1_CHECK_DUPLICATE_EXTENSIONS 341 +# define SSL_F_TLS1_ENC 401 +# define SSL_F_TLS1_EXPORT_KEYING_MATERIAL 314 +# define SSL_F_TLS1_GET_CURVELIST 338 +# define SSL_F_TLS1_PRF 284 +# define SSL_F_TLS1_SAVE_U16 628 +# define SSL_F_TLS1_SETUP_KEY_BLOCK 211 +# define SSL_F_TLS1_SET_GROUPS 629 +# define SSL_F_TLS1_SET_RAW_SIGALGS 630 +# define SSL_F_TLS1_SET_SERVER_SIGALGS 335 +# define SSL_F_TLS1_SET_SHARED_SIGALGS 631 +# define SSL_F_TLS1_SET_SIGALGS 632 +# define SSL_F_TLS_CHOOSE_SIGALG 513 +# define SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK 354 +# define SSL_F_TLS_COLLECT_EXTENSIONS 435 +# define SSL_F_TLS_CONSTRUCT_CERTIFICATE_AUTHORITIES 542 +# define SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST 372 +# define SSL_F_TLS_CONSTRUCT_CERT_STATUS 429 +# define SSL_F_TLS_CONSTRUCT_CERT_STATUS_BODY 494 +# define SSL_F_TLS_CONSTRUCT_CERT_VERIFY 496 +# define SSL_F_TLS_CONSTRUCT_CHANGE_CIPHER_SPEC 427 +# define SSL_F_TLS_CONSTRUCT_CKE_DHE 404 +# define SSL_F_TLS_CONSTRUCT_CKE_ECDHE 405 +# define SSL_F_TLS_CONSTRUCT_CKE_GOST 406 +# define SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE 407 +# define SSL_F_TLS_CONSTRUCT_CKE_RSA 409 +# define SSL_F_TLS_CONSTRUCT_CKE_SRP 410 +# define SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE 484 +# define SSL_F_TLS_CONSTRUCT_CLIENT_HELLO 487 +# define SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE 488 +# define SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY 489 +# define SSL_F_TLS_CONSTRUCT_CTOS_ALPN 466 +# define SSL_F_TLS_CONSTRUCT_CTOS_CERTIFICATE 355 +# define SSL_F_TLS_CONSTRUCT_CTOS_COOKIE 535 +# define SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA 530 +# define SSL_F_TLS_CONSTRUCT_CTOS_EC_PT_FORMATS 467 +# define SSL_F_TLS_CONSTRUCT_CTOS_EMS 468 +# define SSL_F_TLS_CONSTRUCT_CTOS_ETM 469 +# define SSL_F_TLS_CONSTRUCT_CTOS_HELLO 356 +# define SSL_F_TLS_CONSTRUCT_CTOS_KEY_EXCHANGE 357 +# define SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE 470 +# define SSL_F_TLS_CONSTRUCT_CTOS_MAXFRAGMENTLEN 549 +# define SSL_F_TLS_CONSTRUCT_CTOS_NPN 471 +# define SSL_F_TLS_CONSTRUCT_CTOS_PADDING 472 +# define SSL_F_TLS_CONSTRUCT_CTOS_POST_HANDSHAKE_AUTH 619 +# define SSL_F_TLS_CONSTRUCT_CTOS_PSK 501 +# define SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES 509 +# define SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE 473 +# define SSL_F_TLS_CONSTRUCT_CTOS_SCT 474 +# define SSL_F_TLS_CONSTRUCT_CTOS_SERVER_NAME 475 +# define SSL_F_TLS_CONSTRUCT_CTOS_SESSION_TICKET 476 +# define SSL_F_TLS_CONSTRUCT_CTOS_SIG_ALGS 477 +# define SSL_F_TLS_CONSTRUCT_CTOS_SRP 478 +# define SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST 479 +# define SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS 480 +# define SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS 481 +# define SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP 482 +# define SSL_F_TLS_CONSTRUCT_CTOS_VERIFY 358 +# define SSL_F_TLS_CONSTRUCT_ENCRYPTED_EXTENSIONS 443 +# define SSL_F_TLS_CONSTRUCT_END_OF_EARLY_DATA 536 +# define SSL_F_TLS_CONSTRUCT_EXTENSIONS 447 +# define SSL_F_TLS_CONSTRUCT_FINISHED 359 +# define SSL_F_TLS_CONSTRUCT_HELLO_REQUEST 373 +# define SSL_F_TLS_CONSTRUCT_HELLO_RETRY_REQUEST 510 +# define SSL_F_TLS_CONSTRUCT_KEY_UPDATE 517 +# define SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET 428 +# define SSL_F_TLS_CONSTRUCT_NEXT_PROTO 426 +# define SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE 490 +# define SSL_F_TLS_CONSTRUCT_SERVER_HELLO 491 +# define SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE 492 +# define SSL_F_TLS_CONSTRUCT_STOC_ALPN 451 +# define SSL_F_TLS_CONSTRUCT_STOC_CERTIFICATE 374 +# define SSL_F_TLS_CONSTRUCT_STOC_COOKIE 613 +# define SSL_F_TLS_CONSTRUCT_STOC_CRYPTOPRO_BUG 452 +# define SSL_F_TLS_CONSTRUCT_STOC_DONE 375 +# define SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA 531 +# define SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA_INFO 525 +# define SSL_F_TLS_CONSTRUCT_STOC_EC_PT_FORMATS 453 +# define SSL_F_TLS_CONSTRUCT_STOC_EMS 454 +# define SSL_F_TLS_CONSTRUCT_STOC_ETM 455 +# define SSL_F_TLS_CONSTRUCT_STOC_HELLO 376 +# define SSL_F_TLS_CONSTRUCT_STOC_KEY_EXCHANGE 377 +# define SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE 456 +# define SSL_F_TLS_CONSTRUCT_STOC_MAXFRAGMENTLEN 548 +# define SSL_F_TLS_CONSTRUCT_STOC_NEXT_PROTO_NEG 457 +# define SSL_F_TLS_CONSTRUCT_STOC_PSK 504 +# define SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE 458 +# define SSL_F_TLS_CONSTRUCT_STOC_SERVER_NAME 459 +# define SSL_F_TLS_CONSTRUCT_STOC_SESSION_TICKET 460 +# define SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST 461 +# define SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS 544 +# define SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS 611 +# define SSL_F_TLS_CONSTRUCT_STOC_USE_SRTP 462 +# define SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO 521 +# define SSL_F_TLS_FINISH_HANDSHAKE 597 +# define SSL_F_TLS_GET_MESSAGE_BODY 351 +# define SSL_F_TLS_GET_MESSAGE_HEADER 387 +# define SSL_F_TLS_HANDLE_ALPN 562 +# define SSL_F_TLS_HANDLE_STATUS_REQUEST 563 +# define SSL_F_TLS_PARSE_CERTIFICATE_AUTHORITIES 566 +# define SSL_F_TLS_PARSE_CLIENTHELLO_TLSEXT 449 +# define SSL_F_TLS_PARSE_CTOS_ALPN 567 +# define SSL_F_TLS_PARSE_CTOS_COOKIE 614 +# define SSL_F_TLS_PARSE_CTOS_EARLY_DATA 568 +# define SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS 569 +# define SSL_F_TLS_PARSE_CTOS_EMS 570 +# define SSL_F_TLS_PARSE_CTOS_KEY_SHARE 463 +# define SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN 571 +# define SSL_F_TLS_PARSE_CTOS_POST_HANDSHAKE_AUTH 620 +# define SSL_F_TLS_PARSE_CTOS_PSK 505 +# define SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES 572 +# define SSL_F_TLS_PARSE_CTOS_RENEGOTIATE 464 +# define SSL_F_TLS_PARSE_CTOS_SERVER_NAME 573 +# define SSL_F_TLS_PARSE_CTOS_SESSION_TICKET 574 +# define SSL_F_TLS_PARSE_CTOS_SIG_ALGS 575 +# define SSL_F_TLS_PARSE_CTOS_SIG_ALGS_CERT 615 +# define SSL_F_TLS_PARSE_CTOS_SRP 576 +# define SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST 577 +# define SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS 578 +# define SSL_F_TLS_PARSE_CTOS_USE_SRTP 465 +# define SSL_F_TLS_PARSE_STOC_ALPN 579 +# define SSL_F_TLS_PARSE_STOC_COOKIE 534 +# define SSL_F_TLS_PARSE_STOC_EARLY_DATA 538 +# define SSL_F_TLS_PARSE_STOC_EARLY_DATA_INFO 528 +# define SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS 580 +# define SSL_F_TLS_PARSE_STOC_KEY_SHARE 445 +# define SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN 581 +# define SSL_F_TLS_PARSE_STOC_NPN 582 +# define SSL_F_TLS_PARSE_STOC_PSK 502 +# define SSL_F_TLS_PARSE_STOC_RENEGOTIATE 448 +# define SSL_F_TLS_PARSE_STOC_SCT 564 +# define SSL_F_TLS_PARSE_STOC_SERVER_NAME 583 +# define SSL_F_TLS_PARSE_STOC_SESSION_TICKET 584 +# define SSL_F_TLS_PARSE_STOC_STATUS_REQUEST 585 +# define SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS 612 +# define SSL_F_TLS_PARSE_STOC_USE_SRTP 446 +# define SSL_F_TLS_POST_PROCESS_CLIENT_HELLO 378 +# define SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE 384 +# define SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE 360 +# define SSL_F_TLS_PROCESS_AS_HELLO_RETRY_REQUEST 610 +# define SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST 361 +# define SSL_F_TLS_PROCESS_CERT_STATUS 362 +# define SSL_F_TLS_PROCESS_CERT_STATUS_BODY 495 +# define SSL_F_TLS_PROCESS_CERT_VERIFY 379 +# define SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC 363 +# define SSL_F_TLS_PROCESS_CKE_DHE 411 +# define SSL_F_TLS_PROCESS_CKE_ECDHE 412 +# define SSL_F_TLS_PROCESS_CKE_GOST 413 +# define SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE 414 +# define SSL_F_TLS_PROCESS_CKE_RSA 415 +# define SSL_F_TLS_PROCESS_CKE_SRP 416 +# define SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE 380 +# define SSL_F_TLS_PROCESS_CLIENT_HELLO 381 +# define SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE 382 +# define SSL_F_TLS_PROCESS_ENCRYPTED_EXTENSIONS 444 +# define SSL_F_TLS_PROCESS_END_OF_EARLY_DATA 537 +# define SSL_F_TLS_PROCESS_FINISHED 364 +# define SSL_F_TLS_PROCESS_HELLO_REQ 507 +# define SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST 511 +# define SSL_F_TLS_PROCESS_INITIAL_SERVER_FLIGHT 442 +# define SSL_F_TLS_PROCESS_KEY_EXCHANGE 365 +# define SSL_F_TLS_PROCESS_KEY_UPDATE 518 +# define SSL_F_TLS_PROCESS_NEW_SESSION_TICKET 366 +# define SSL_F_TLS_PROCESS_NEXT_PROTO 383 +# define SSL_F_TLS_PROCESS_SERVER_CERTIFICATE 367 +# define SSL_F_TLS_PROCESS_SERVER_DONE 368 +# define SSL_F_TLS_PROCESS_SERVER_HELLO 369 +# define SSL_F_TLS_PROCESS_SKE_DHE 419 +# define SSL_F_TLS_PROCESS_SKE_ECDHE 420 +# define SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE 421 +# define SSL_F_TLS_PROCESS_SKE_SRP 422 +# define SSL_F_TLS_PSK_DO_BINDER 506 +# define SSL_F_TLS_SCAN_CLIENTHELLO_TLSEXT 450 +# define SSL_F_TLS_SETUP_HANDSHAKE 508 +# define SSL_F_USE_CERTIFICATE_CHAIN_FILE 220 +# define SSL_F_WPACKET_INTERN_INIT_LEN 633 +# define SSL_F_WPACKET_START_SUB_PACKET_LEN__ 634 +# define SSL_F_WRITE_STATE_MACHINE 586 + +/* + * SSL reason codes. + */ +# define SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY 291 +# define SSL_R_APP_DATA_IN_HANDSHAKE 100 +# define SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT 272 +# define SSL_R_AT_LEAST_TLS_1_0_NEEDED_IN_FIPS_MODE 143 +# define SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE 158 +# define SSL_R_BAD_CHANGE_CIPHER_SPEC 103 +# define SSL_R_BAD_CIPHER 186 +# define SSL_R_BAD_DATA 390 +# define SSL_R_BAD_DATA_RETURNED_BY_CALLBACK 106 +# define SSL_R_BAD_DECOMPRESSION 107 +# define SSL_R_BAD_DH_VALUE 102 +# define SSL_R_BAD_DIGEST_LENGTH 111 +# define SSL_R_BAD_EARLY_DATA 233 +# define SSL_R_BAD_ECC_CERT 304 +# define SSL_R_BAD_ECPOINT 306 +# define SSL_R_BAD_EXTENSION 110 +# define SSL_R_BAD_HANDSHAKE_LENGTH 332 +# define SSL_R_BAD_HANDSHAKE_STATE 236 +# define SSL_R_BAD_HELLO_REQUEST 105 +# define SSL_R_BAD_HRR_VERSION 263 +# define SSL_R_BAD_KEY_SHARE 108 +# define SSL_R_BAD_KEY_UPDATE 122 +# define SSL_R_BAD_LEGACY_VERSION 292 +# define SSL_R_BAD_LENGTH 271 +# define SSL_R_BAD_PACKET 240 +# define SSL_R_BAD_PACKET_LENGTH 115 +# define SSL_R_BAD_PROTOCOL_VERSION_NUMBER 116 +# define SSL_R_BAD_PSK 219 +# define SSL_R_BAD_PSK_IDENTITY 114 +# define SSL_R_BAD_RECORD_TYPE 443 +# define SSL_R_BAD_RSA_ENCRYPT 119 +# define SSL_R_BAD_SIGNATURE 123 +# define SSL_R_BAD_SRP_A_LENGTH 347 +# define SSL_R_BAD_SRP_PARAMETERS 371 +# define SSL_R_BAD_SRTP_MKI_VALUE 352 +# define SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST 353 +# define SSL_R_BAD_SSL_FILETYPE 124 +# define SSL_R_BAD_VALUE 384 +# define SSL_R_BAD_WRITE_RETRY 127 +# define SSL_R_BINDER_DOES_NOT_VERIFY 253 +# define SSL_R_BIO_NOT_SET 128 +# define SSL_R_BLOCK_CIPHER_PAD_IS_WRONG 129 +# define SSL_R_BN_LIB 130 +# define SSL_R_CALLBACK_FAILED 234 +# define SSL_R_CANNOT_CHANGE_CIPHER 109 +# define SSL_R_CA_DN_LENGTH_MISMATCH 131 +# define SSL_R_CA_KEY_TOO_SMALL 397 +# define SSL_R_CA_MD_TOO_WEAK 398 +# define SSL_R_CCS_RECEIVED_EARLY 133 +# define SSL_R_CERTIFICATE_VERIFY_FAILED 134 +# define SSL_R_CERT_CB_ERROR 377 +# define SSL_R_CERT_LENGTH_MISMATCH 135 +# define SSL_R_CIPHERSUITE_DIGEST_HAS_CHANGED 218 +# define SSL_R_CIPHER_CODE_WRONG_LENGTH 137 +# define SSL_R_CIPHER_OR_HASH_UNAVAILABLE 138 +# define SSL_R_CLIENTHELLO_TLSEXT 226 +# define SSL_R_COMPRESSED_LENGTH_TOO_LONG 140 +# define SSL_R_COMPRESSION_DISABLED 343 +# define SSL_R_COMPRESSION_FAILURE 141 +# define SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE 307 +# define SSL_R_COMPRESSION_LIBRARY_ERROR 142 +# define SSL_R_CONNECTION_TYPE_NOT_SET 144 +# define SSL_R_CONTEXT_NOT_DANE_ENABLED 167 +# define SSL_R_COOKIE_GEN_CALLBACK_FAILURE 400 +# define SSL_R_COOKIE_MISMATCH 308 +# define SSL_R_CUSTOM_EXT_HANDLER_ALREADY_INSTALLED 206 +# define SSL_R_DANE_ALREADY_ENABLED 172 +# define SSL_R_DANE_CANNOT_OVERRIDE_MTYPE_FULL 173 +# define SSL_R_DANE_NOT_ENABLED 175 +# define SSL_R_DANE_TLSA_BAD_CERTIFICATE 180 +# define SSL_R_DANE_TLSA_BAD_CERTIFICATE_USAGE 184 +# define SSL_R_DANE_TLSA_BAD_DATA_LENGTH 189 +# define SSL_R_DANE_TLSA_BAD_DIGEST_LENGTH 192 +# define SSL_R_DANE_TLSA_BAD_MATCHING_TYPE 200 +# define SSL_R_DANE_TLSA_BAD_PUBLIC_KEY 201 +# define SSL_R_DANE_TLSA_BAD_SELECTOR 202 +# define SSL_R_DANE_TLSA_NULL_DATA 203 +# define SSL_R_DATA_BETWEEN_CCS_AND_FINISHED 145 +# define SSL_R_DATA_LENGTH_TOO_LONG 146 +# define SSL_R_DECRYPTION_FAILED 147 +# define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC 281 +# define SSL_R_DH_KEY_TOO_SMALL 394 +# define SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG 148 +# define SSL_R_DIGEST_CHECK_FAILED 149 +# define SSL_R_DTLS_MESSAGE_TOO_BIG 334 +# define SSL_R_DUPLICATE_COMPRESSION_ID 309 +# define SSL_R_ECC_CERT_NOT_FOR_SIGNING 318 +# define SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE 374 +# define SSL_R_EE_KEY_TOO_SMALL 399 +# define SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST 354 +# define SSL_R_ENCRYPTED_LENGTH_TOO_LONG 150 +# define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST 151 +# define SSL_R_ERROR_SETTING_TLSA_BASE_DOMAIN 204 +# define SSL_R_EXCEEDS_MAX_FRAGMENT_SIZE 194 +# define SSL_R_EXCESSIVE_MESSAGE_SIZE 152 +# define SSL_R_EXTENSION_NOT_RECEIVED 279 +# define SSL_R_EXTRA_DATA_IN_MESSAGE 153 +# define SSL_R_EXT_LENGTH_MISMATCH 163 +# define SSL_R_FAILED_TO_INIT_ASYNC 405 +# define SSL_R_FRAGMENTED_CLIENT_HELLO 401 +# define SSL_R_GOT_A_FIN_BEFORE_A_CCS 154 +# define SSL_R_HTTPS_PROXY_REQUEST 155 +# define SSL_R_HTTP_REQUEST 156 +# define SSL_R_ILLEGAL_POINT_COMPRESSION 162 +# define SSL_R_ILLEGAL_SUITEB_DIGEST 380 +# define SSL_R_INAPPROPRIATE_FALLBACK 373 +# define SSL_R_INCONSISTENT_COMPRESSION 340 +# define SSL_R_INCONSISTENT_EARLY_DATA_ALPN 222 +# define SSL_R_INCONSISTENT_EARLY_DATA_SNI 231 +# define SSL_R_INCONSISTENT_EXTMS 104 +# define SSL_R_INSUFFICIENT_SECURITY 241 +# define SSL_R_INVALID_ALERT 205 +# define SSL_R_INVALID_CCS_MESSAGE 260 +# define SSL_R_INVALID_CERTIFICATE_OR_ALG 238 +# define SSL_R_INVALID_COMMAND 280 +# define SSL_R_INVALID_COMPRESSION_ALGORITHM 341 +# define SSL_R_INVALID_CONFIG 283 +# define SSL_R_INVALID_CONFIGURATION_NAME 113 +# define SSL_R_INVALID_CONTEXT 282 +# define SSL_R_INVALID_CT_VALIDATION_TYPE 212 +# define SSL_R_INVALID_KEY_UPDATE_TYPE 120 +# define SSL_R_INVALID_MAX_EARLY_DATA 174 +# define SSL_R_INVALID_NULL_CMD_NAME 385 +# define SSL_R_INVALID_SEQUENCE_NUMBER 402 +# define SSL_R_INVALID_SERVERINFO_DATA 388 +# define SSL_R_INVALID_SESSION_ID 999 +# define SSL_R_INVALID_SRP_USERNAME 357 +# define SSL_R_INVALID_STATUS_RESPONSE 328 +# define SSL_R_INVALID_TICKET_KEYS_LENGTH 325 +# define SSL_R_LENGTH_MISMATCH 159 +# define SSL_R_LENGTH_TOO_LONG 404 +# define SSL_R_LENGTH_TOO_SHORT 160 +# define SSL_R_LIBRARY_BUG 274 +# define SSL_R_LIBRARY_HAS_NO_CIPHERS 161 +# define SSL_R_MISSING_DSA_SIGNING_CERT 165 +# define SSL_R_MISSING_ECDSA_SIGNING_CERT 381 +# define SSL_R_MISSING_FATAL 256 +# define SSL_R_MISSING_PARAMETERS 290 +# define SSL_R_MISSING_RSA_CERTIFICATE 168 +# define SSL_R_MISSING_RSA_ENCRYPTING_CERT 169 +# define SSL_R_MISSING_RSA_SIGNING_CERT 170 +# define SSL_R_MISSING_SIGALGS_EXTENSION 112 +# define SSL_R_MISSING_SIGNING_CERT 221 +# define SSL_R_MISSING_SRP_PARAM 358 +# define SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION 209 +# define SSL_R_MISSING_TMP_DH_KEY 171 +# define SSL_R_MISSING_TMP_ECDH_KEY 311 +# define SSL_R_MIXED_HANDSHAKE_AND_NON_HANDSHAKE_DATA 293 +# define SSL_R_NOT_ON_RECORD_BOUNDARY 182 +# define SSL_R_NOT_REPLACING_CERTIFICATE 289 +# define SSL_R_NOT_SERVER 284 +# define SSL_R_NO_APPLICATION_PROTOCOL 235 +# define SSL_R_NO_CERTIFICATES_RETURNED 176 +# define SSL_R_NO_CERTIFICATE_ASSIGNED 177 +# define SSL_R_NO_CERTIFICATE_SET 179 +# define SSL_R_NO_CHANGE_FOLLOWING_HRR 214 +# define SSL_R_NO_CIPHERS_AVAILABLE 181 +# define SSL_R_NO_CIPHERS_SPECIFIED 183 +# define SSL_R_NO_CIPHER_MATCH 185 +# define SSL_R_NO_CLIENT_CERT_METHOD 331 +# define SSL_R_NO_COMPRESSION_SPECIFIED 187 +# define SSL_R_NO_COOKIE_CALLBACK_SET 287 +# define SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER 330 +# define SSL_R_NO_METHOD_SPECIFIED 188 +# define SSL_R_NO_PEM_EXTENSIONS 389 +# define SSL_R_NO_PRIVATE_KEY_ASSIGNED 190 +# define SSL_R_NO_PROTOCOLS_AVAILABLE 191 +# define SSL_R_NO_RENEGOTIATION 339 +# define SSL_R_NO_REQUIRED_DIGEST 324 +# define SSL_R_NO_SHARED_CIPHER 193 +# define SSL_R_NO_SHARED_GROUPS 410 +# define SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS 376 +# define SSL_R_NO_SRTP_PROFILES 359 +# define SSL_R_NO_SUITABLE_KEY_SHARE 101 +# define SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM 118 +# define SSL_R_NO_VALID_SCTS 216 +# define SSL_R_NO_VERIFY_COOKIE_CALLBACK 403 +# define SSL_R_NULL_SSL_CTX 195 +# define SSL_R_NULL_SSL_METHOD_PASSED 196 +# define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED 197 +# define SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED 344 +# define SSL_R_OVERFLOW_ERROR 237 +# define SSL_R_PACKET_LENGTH_TOO_LONG 198 +# define SSL_R_PARSE_TLSEXT 227 +# define SSL_R_PATH_TOO_LONG 270 +# define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE 199 +# define SSL_R_PEM_NAME_BAD_PREFIX 391 +# define SSL_R_PEM_NAME_TOO_SHORT 392 +# define SSL_R_PIPELINE_FAILURE 406 +# define SSL_R_POST_HANDSHAKE_AUTH_ENCODING_ERR 278 +# define SSL_R_PRIVATE_KEY_MISMATCH 288 +# define SSL_R_PROTOCOL_IS_SHUTDOWN 207 +# define SSL_R_PSK_IDENTITY_NOT_FOUND 223 +# define SSL_R_PSK_NO_CLIENT_CB 224 +# define SSL_R_PSK_NO_SERVER_CB 225 +# define SSL_R_READ_BIO_NOT_SET 211 +# define SSL_R_READ_TIMEOUT_EXPIRED 312 +# define SSL_R_RECORD_LENGTH_MISMATCH 213 +# define SSL_R_RECORD_TOO_SMALL 298 +# define SSL_R_RENEGOTIATE_EXT_TOO_LONG 335 +# define SSL_R_RENEGOTIATION_ENCODING_ERR 336 +# define SSL_R_RENEGOTIATION_MISMATCH 337 +# define SSL_R_REQUEST_PENDING 285 +# define SSL_R_REQUEST_SENT 286 +# define SSL_R_REQUIRED_CIPHER_MISSING 215 +# define SSL_R_REQUIRED_COMPRESSION_ALGORITHM_MISSING 342 +# define SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING 345 +# define SSL_R_SCT_VERIFICATION_FAILED 208 +# define SSL_R_SERVERHELLO_TLSEXT 275 +# define SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED 277 +# define SSL_R_SHUTDOWN_WHILE_IN_INIT 407 +# define SSL_R_SIGNATURE_ALGORITHMS_ERROR 360 +# define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE 220 +# define SSL_R_SRP_A_CALC 361 +# define SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES 362 +# define SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG 363 +# define SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE 364 +# define SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH 232 +# define SSL_R_SSL3_EXT_INVALID_SERVERNAME 319 +# define SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE 320 +# define SSL_R_SSL3_SESSION_ID_TOO_LONG 300 +# define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE 1042 +# define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020 +# define SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED 1045 +# define SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED 1044 +# define SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN 1046 +# define SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE 1030 +# define SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE 1040 +# define SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER 1047 +# define SSL_R_SSLV3_ALERT_NO_CERTIFICATE 1041 +# define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010 +# define SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE 1043 +# define SSL_R_SSL_COMMAND_SECTION_EMPTY 117 +# define SSL_R_SSL_COMMAND_SECTION_NOT_FOUND 125 +# define SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION 228 +# define SSL_R_SSL_HANDSHAKE_FAILURE 229 +# define SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS 230 +# define SSL_R_SSL_NEGATIVE_LENGTH 372 +# define SSL_R_SSL_SECTION_EMPTY 126 +# define SSL_R_SSL_SECTION_NOT_FOUND 136 +# define SSL_R_SSL_SESSION_ID_CALLBACK_FAILED 301 +# define SSL_R_SSL_SESSION_ID_CONFLICT 302 +# define SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG 273 +# define SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH 303 +# define SSL_R_SSL_SESSION_ID_TOO_LONG 408 +# define SSL_R_SSL_SESSION_VERSION_MISMATCH 210 +# define SSL_R_STILL_IN_INIT 121 +# define SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED 1116 +# define SSL_R_TLSV13_ALERT_MISSING_EXTENSION 1109 +# define SSL_R_TLSV1_ALERT_ACCESS_DENIED 1049 +# define SSL_R_TLSV1_ALERT_DECODE_ERROR 1050 +# define SSL_R_TLSV1_ALERT_DECRYPTION_FAILED 1021 +# define SSL_R_TLSV1_ALERT_DECRYPT_ERROR 1051 +# define SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION 1060 +# define SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK 1086 +# define SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY 1071 +# define SSL_R_TLSV1_ALERT_INTERNAL_ERROR 1080 +# define SSL_R_TLSV1_ALERT_NO_RENEGOTIATION 1100 +# define SSL_R_TLSV1_ALERT_PROTOCOL_VERSION 1070 +# define SSL_R_TLSV1_ALERT_RECORD_OVERFLOW 1022 +# define SSL_R_TLSV1_ALERT_UNKNOWN_CA 1048 +# define SSL_R_TLSV1_ALERT_USER_CANCELLED 1090 +# define SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE 1114 +# define SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE 1113 +# define SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE 1111 +# define SSL_R_TLSV1_UNRECOGNIZED_NAME 1112 +# define SSL_R_TLSV1_UNSUPPORTED_EXTENSION 1110 +# define SSL_R_TLS_HEARTBEAT_PEER_DOESNT_ACCEPT 365 +# define SSL_R_TLS_HEARTBEAT_PENDING 366 +# define SSL_R_TLS_ILLEGAL_EXPORTER_LABEL 367 +# define SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST 157 +# define SSL_R_TOO_MANY_KEY_UPDATES 132 +# define SSL_R_TOO_MANY_WARN_ALERTS 409 +# define SSL_R_TOO_MUCH_EARLY_DATA 164 +# define SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS 314 +# define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS 239 +# define SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES 242 +# define SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES 243 +# define SSL_R_UNEXPECTED_CCS_MESSAGE 262 +# define SSL_R_UNEXPECTED_END_OF_EARLY_DATA 178 +# define SSL_R_UNEXPECTED_MESSAGE 244 +# define SSL_R_UNEXPECTED_RECORD 245 +# define SSL_R_UNINITIALIZED 276 +# define SSL_R_UNKNOWN_ALERT_TYPE 246 +# define SSL_R_UNKNOWN_CERTIFICATE_TYPE 247 +# define SSL_R_UNKNOWN_CIPHER_RETURNED 248 +# define SSL_R_UNKNOWN_CIPHER_TYPE 249 +# define SSL_R_UNKNOWN_CMD_NAME 386 +# define SSL_R_UNKNOWN_COMMAND 139 +# define SSL_R_UNKNOWN_DIGEST 368 +# define SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE 250 +# define SSL_R_UNKNOWN_PKEY_TYPE 251 +# define SSL_R_UNKNOWN_PROTOCOL 252 +# define SSL_R_UNKNOWN_SSL_VERSION 254 +# define SSL_R_UNKNOWN_STATE 255 +# define SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED 338 +# define SSL_R_UNSOLICITED_EXTENSION 217 +# define SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM 257 +# define SSL_R_UNSUPPORTED_ELLIPTIC_CURVE 315 +# define SSL_R_UNSUPPORTED_PROTOCOL 258 +# define SSL_R_UNSUPPORTED_SSL_VERSION 259 +# define SSL_R_UNSUPPORTED_STATUS_TYPE 329 +# define SSL_R_USE_SRTP_NOT_NEGOTIATED 369 +# define SSL_R_VERSION_TOO_HIGH 166 +# define SSL_R_VERSION_TOO_LOW 396 +# define SSL_R_WRONG_CERTIFICATE_TYPE 383 +# define SSL_R_WRONG_CIPHER_RETURNED 261 +# define SSL_R_WRONG_CURVE 378 +# define SSL_R_WRONG_SIGNATURE_LENGTH 264 +# define SSL_R_WRONG_SIGNATURE_SIZE 265 +# define SSL_R_WRONG_SIGNATURE_TYPE 370 +# define SSL_R_WRONG_SSL_VERSION 266 +# define SSL_R_WRONG_VERSION_NUMBER 267 +# define SSL_R_X509_LIB 268 +# define SSL_R_X509_VERIFICATION_SETUP_PROBLEMS 269 + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/stack.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/stack.h new file mode 100644 index 000000000..cfc075057 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/stack.h @@ -0,0 +1,83 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_STACK_H +# define HEADER_STACK_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct stack_st OPENSSL_STACK; /* Use STACK_OF(...) instead */ + +typedef int (*OPENSSL_sk_compfunc)(const void *, const void *); +typedef void (*OPENSSL_sk_freefunc)(void *); +typedef void *(*OPENSSL_sk_copyfunc)(const void *); + +int OPENSSL_sk_num(const OPENSSL_STACK *); +void *OPENSSL_sk_value(const OPENSSL_STACK *, int); + +void *OPENSSL_sk_set(OPENSSL_STACK *st, int i, const void *data); + +OPENSSL_STACK *OPENSSL_sk_new(OPENSSL_sk_compfunc cmp); +OPENSSL_STACK *OPENSSL_sk_new_null(void); +OPENSSL_STACK *OPENSSL_sk_new_reserve(OPENSSL_sk_compfunc c, int n); +int OPENSSL_sk_reserve(OPENSSL_STACK *st, int n); +void OPENSSL_sk_free(OPENSSL_STACK *); +void OPENSSL_sk_pop_free(OPENSSL_STACK *st, void (*func) (void *)); +OPENSSL_STACK *OPENSSL_sk_deep_copy(const OPENSSL_STACK *, + OPENSSL_sk_copyfunc c, + OPENSSL_sk_freefunc f); +int OPENSSL_sk_insert(OPENSSL_STACK *sk, const void *data, int where); +void *OPENSSL_sk_delete(OPENSSL_STACK *st, int loc); +void *OPENSSL_sk_delete_ptr(OPENSSL_STACK *st, const void *p); +int OPENSSL_sk_find(OPENSSL_STACK *st, const void *data); +int OPENSSL_sk_find_ex(OPENSSL_STACK *st, const void *data); +int OPENSSL_sk_push(OPENSSL_STACK *st, const void *data); +int OPENSSL_sk_unshift(OPENSSL_STACK *st, const void *data); +void *OPENSSL_sk_shift(OPENSSL_STACK *st); +void *OPENSSL_sk_pop(OPENSSL_STACK *st); +void OPENSSL_sk_zero(OPENSSL_STACK *st); +OPENSSL_sk_compfunc OPENSSL_sk_set_cmp_func(OPENSSL_STACK *sk, + OPENSSL_sk_compfunc cmp); +OPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *st); +void OPENSSL_sk_sort(OPENSSL_STACK *st); +int OPENSSL_sk_is_sorted(const OPENSSL_STACK *st); + +# if OPENSSL_API_COMPAT < 0x10100000L +# define _STACK OPENSSL_STACK +# define sk_num OPENSSL_sk_num +# define sk_value OPENSSL_sk_value +# define sk_set OPENSSL_sk_set +# define sk_new OPENSSL_sk_new +# define sk_new_null OPENSSL_sk_new_null +# define sk_free OPENSSL_sk_free +# define sk_pop_free OPENSSL_sk_pop_free +# define sk_deep_copy OPENSSL_sk_deep_copy +# define sk_insert OPENSSL_sk_insert +# define sk_delete OPENSSL_sk_delete +# define sk_delete_ptr OPENSSL_sk_delete_ptr +# define sk_find OPENSSL_sk_find +# define sk_find_ex OPENSSL_sk_find_ex +# define sk_push OPENSSL_sk_push +# define sk_unshift OPENSSL_sk_unshift +# define sk_shift OPENSSL_sk_shift +# define sk_pop OPENSSL_sk_pop +# define sk_zero OPENSSL_sk_zero +# define sk_set_cmp_func OPENSSL_sk_set_cmp_func +# define sk_dup OPENSSL_sk_dup +# define sk_sort OPENSSL_sk_sort +# define sk_is_sorted OPENSSL_sk_is_sorted +# endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/store.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/store.h new file mode 100644 index 000000000..7b43e8bd0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/store.h @@ -0,0 +1,266 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_OSSL_STORE_H +# define HEADER_OSSL_STORE_H + +# include +# include +# include +# include + +# ifdef __cplusplus +extern "C" { +# endif + +/*- + * The main OSSL_STORE functions. + * ------------------------------ + * + * These allow applications to open a channel to a resource with supported + * data (keys, certs, crls, ...), read the data a piece at a time and decide + * what to do with it, and finally close. + */ + +typedef struct ossl_store_ctx_st OSSL_STORE_CTX; + +/* + * Typedef for the OSSL_STORE_INFO post processing callback. This can be used + * to massage the given OSSL_STORE_INFO, or to drop it entirely (by returning + * NULL). + */ +typedef OSSL_STORE_INFO *(*OSSL_STORE_post_process_info_fn)(OSSL_STORE_INFO *, + void *); + +/* + * Open a channel given a URI. The given UI method will be used any time the + * loader needs extra input, for example when a password or pin is needed, and + * will be passed the same user data every time it's needed in this context. + * + * Returns a context reference which represents the channel to communicate + * through. + */ +OSSL_STORE_CTX *OSSL_STORE_open(const char *uri, const UI_METHOD *ui_method, + void *ui_data, + OSSL_STORE_post_process_info_fn post_process, + void *post_process_data); + +/* + * Control / fine tune the OSSL_STORE channel. |cmd| determines what is to be + * done, and depends on the underlying loader (use OSSL_STORE_get0_scheme to + * determine which loader is used), except for common commands (see below). + * Each command takes different arguments. + */ +int OSSL_STORE_ctrl(OSSL_STORE_CTX *ctx, int cmd, ... /* args */); +int OSSL_STORE_vctrl(OSSL_STORE_CTX *ctx, int cmd, va_list args); + +/* + * Common ctrl commands that different loaders may choose to support. + */ +/* int on = 0 or 1; STORE_ctrl(ctx, STORE_C_USE_SECMEM, &on); */ +# define OSSL_STORE_C_USE_SECMEM 1 +/* Where custom commands start */ +# define OSSL_STORE_C_CUSTOM_START 100 + +/* + * Read one data item (a key, a cert, a CRL) that is supported by the OSSL_STORE + * functionality, given a context. + * Returns a OSSL_STORE_INFO pointer, from which OpenSSL typed data can be + * extracted with OSSL_STORE_INFO_get0_PKEY(), OSSL_STORE_INFO_get0_CERT(), ... + * NULL is returned on error, which may include that the data found at the URI + * can't be figured out for certain or is ambiguous. + */ +OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx); + +/* + * Check if end of data (end of file) is reached + * Returns 1 on end, 0 otherwise. + */ +int OSSL_STORE_eof(OSSL_STORE_CTX *ctx); + +/* + * Check if an error occured + * Returns 1 if it did, 0 otherwise. + */ +int OSSL_STORE_error(OSSL_STORE_CTX *ctx); + +/* + * Close the channel + * Returns 1 on success, 0 on error. + */ +int OSSL_STORE_close(OSSL_STORE_CTX *ctx); + + +/*- + * Extracting OpenSSL types from and creating new OSSL_STORE_INFOs + * --------------------------------------------------------------- + */ + +/* + * Types of data that can be ossl_stored in a OSSL_STORE_INFO. + * OSSL_STORE_INFO_NAME is typically found when getting a listing of + * available "files" / "tokens" / what have you. + */ +# define OSSL_STORE_INFO_NAME 1 /* char * */ +# define OSSL_STORE_INFO_PARAMS 2 /* EVP_PKEY * */ +# define OSSL_STORE_INFO_PKEY 3 /* EVP_PKEY * */ +# define OSSL_STORE_INFO_CERT 4 /* X509 * */ +# define OSSL_STORE_INFO_CRL 5 /* X509_CRL * */ + +/* + * Functions to generate OSSL_STORE_INFOs, one function for each type we + * support having in them, as well as a generic constructor. + * + * In all cases, ownership of the object is transfered to the OSSL_STORE_INFO + * and will therefore be freed when the OSSL_STORE_INFO is freed. + */ +OSSL_STORE_INFO *OSSL_STORE_INFO_new_NAME(char *name); +int OSSL_STORE_INFO_set0_NAME_description(OSSL_STORE_INFO *info, char *desc); +OSSL_STORE_INFO *OSSL_STORE_INFO_new_PARAMS(EVP_PKEY *params); +OSSL_STORE_INFO *OSSL_STORE_INFO_new_PKEY(EVP_PKEY *pkey); +OSSL_STORE_INFO *OSSL_STORE_INFO_new_CERT(X509 *x509); +OSSL_STORE_INFO *OSSL_STORE_INFO_new_CRL(X509_CRL *crl); + +/* + * Functions to try to extract data from a OSSL_STORE_INFO. + */ +int OSSL_STORE_INFO_get_type(const OSSL_STORE_INFO *info); +const char *OSSL_STORE_INFO_get0_NAME(const OSSL_STORE_INFO *info); +char *OSSL_STORE_INFO_get1_NAME(const OSSL_STORE_INFO *info); +const char *OSSL_STORE_INFO_get0_NAME_description(const OSSL_STORE_INFO *info); +char *OSSL_STORE_INFO_get1_NAME_description(const OSSL_STORE_INFO *info); +EVP_PKEY *OSSL_STORE_INFO_get0_PARAMS(const OSSL_STORE_INFO *info); +EVP_PKEY *OSSL_STORE_INFO_get1_PARAMS(const OSSL_STORE_INFO *info); +EVP_PKEY *OSSL_STORE_INFO_get0_PKEY(const OSSL_STORE_INFO *info); +EVP_PKEY *OSSL_STORE_INFO_get1_PKEY(const OSSL_STORE_INFO *info); +X509 *OSSL_STORE_INFO_get0_CERT(const OSSL_STORE_INFO *info); +X509 *OSSL_STORE_INFO_get1_CERT(const OSSL_STORE_INFO *info); +X509_CRL *OSSL_STORE_INFO_get0_CRL(const OSSL_STORE_INFO *info); +X509_CRL *OSSL_STORE_INFO_get1_CRL(const OSSL_STORE_INFO *info); + +const char *OSSL_STORE_INFO_type_string(int type); + +/* + * Free the OSSL_STORE_INFO + */ +void OSSL_STORE_INFO_free(OSSL_STORE_INFO *info); + + +/*- + * Functions to construct a search URI from a base URI and search criteria + * ----------------------------------------------------------------------- + */ + +/* OSSL_STORE search types */ +# define OSSL_STORE_SEARCH_BY_NAME 1 /* subject in certs, issuer in CRLs */ +# define OSSL_STORE_SEARCH_BY_ISSUER_SERIAL 2 +# define OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT 3 +# define OSSL_STORE_SEARCH_BY_ALIAS 4 + +/* To check what search types the scheme handler supports */ +int OSSL_STORE_supports_search(OSSL_STORE_CTX *ctx, int search_type); + +/* Search term constructors */ +/* + * The input is considered to be owned by the caller, and must therefore + * remain present throughout the lifetime of the returned OSSL_STORE_SEARCH + */ +OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_name(X509_NAME *name); +OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_issuer_serial(X509_NAME *name, + const ASN1_INTEGER + *serial); +OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_key_fingerprint(const EVP_MD *digest, + const unsigned char + *bytes, size_t len); +OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_alias(const char *alias); + +/* Search term destructor */ +void OSSL_STORE_SEARCH_free(OSSL_STORE_SEARCH *search); + +/* Search term accessors */ +int OSSL_STORE_SEARCH_get_type(const OSSL_STORE_SEARCH *criterion); +X509_NAME *OSSL_STORE_SEARCH_get0_name(OSSL_STORE_SEARCH *criterion); +const ASN1_INTEGER *OSSL_STORE_SEARCH_get0_serial(const OSSL_STORE_SEARCH + *criterion); +const unsigned char *OSSL_STORE_SEARCH_get0_bytes(const OSSL_STORE_SEARCH + *criterion, size_t *length); +const char *OSSL_STORE_SEARCH_get0_string(const OSSL_STORE_SEARCH *criterion); +const EVP_MD *OSSL_STORE_SEARCH_get0_digest(const OSSL_STORE_SEARCH *criterion); + +/* + * Add search criterion and expected return type (which can be unspecified) + * to the loading channel. This MUST happen before the first OSSL_STORE_load(). + */ +int OSSL_STORE_expect(OSSL_STORE_CTX *ctx, int expected_type); +int OSSL_STORE_find(OSSL_STORE_CTX *ctx, OSSL_STORE_SEARCH *search); + + +/*- + * Function to register a loader for the given URI scheme. + * ------------------------------------------------------- + * + * The loader receives all the main components of an URI except for the + * scheme. + */ + +typedef struct ossl_store_loader_st OSSL_STORE_LOADER; +OSSL_STORE_LOADER *OSSL_STORE_LOADER_new(ENGINE *e, const char *scheme); +const ENGINE *OSSL_STORE_LOADER_get0_engine(const OSSL_STORE_LOADER *loader); +const char *OSSL_STORE_LOADER_get0_scheme(const OSSL_STORE_LOADER *loader); +/* struct ossl_store_loader_ctx_st is defined differently by each loader */ +typedef struct ossl_store_loader_ctx_st OSSL_STORE_LOADER_CTX; +typedef OSSL_STORE_LOADER_CTX *(*OSSL_STORE_open_fn)(const OSSL_STORE_LOADER + *loader, + const char *uri, + const UI_METHOD *ui_method, + void *ui_data); +int OSSL_STORE_LOADER_set_open(OSSL_STORE_LOADER *loader, + OSSL_STORE_open_fn open_function); +typedef int (*OSSL_STORE_ctrl_fn)(OSSL_STORE_LOADER_CTX *ctx, int cmd, + va_list args); +int OSSL_STORE_LOADER_set_ctrl(OSSL_STORE_LOADER *loader, + OSSL_STORE_ctrl_fn ctrl_function); +typedef int (*OSSL_STORE_expect_fn)(OSSL_STORE_LOADER_CTX *ctx, int expected); +int OSSL_STORE_LOADER_set_expect(OSSL_STORE_LOADER *loader, + OSSL_STORE_expect_fn expect_function); +typedef int (*OSSL_STORE_find_fn)(OSSL_STORE_LOADER_CTX *ctx, + OSSL_STORE_SEARCH *criteria); +int OSSL_STORE_LOADER_set_find(OSSL_STORE_LOADER *loader, + OSSL_STORE_find_fn find_function); +typedef OSSL_STORE_INFO *(*OSSL_STORE_load_fn)(OSSL_STORE_LOADER_CTX *ctx, + const UI_METHOD *ui_method, + void *ui_data); +int OSSL_STORE_LOADER_set_load(OSSL_STORE_LOADER *loader, + OSSL_STORE_load_fn load_function); +typedef int (*OSSL_STORE_eof_fn)(OSSL_STORE_LOADER_CTX *ctx); +int OSSL_STORE_LOADER_set_eof(OSSL_STORE_LOADER *loader, + OSSL_STORE_eof_fn eof_function); +typedef int (*OSSL_STORE_error_fn)(OSSL_STORE_LOADER_CTX *ctx); +int OSSL_STORE_LOADER_set_error(OSSL_STORE_LOADER *loader, + OSSL_STORE_error_fn error_function); +typedef int (*OSSL_STORE_close_fn)(OSSL_STORE_LOADER_CTX *ctx); +int OSSL_STORE_LOADER_set_close(OSSL_STORE_LOADER *loader, + OSSL_STORE_close_fn close_function); +void OSSL_STORE_LOADER_free(OSSL_STORE_LOADER *loader); + +int OSSL_STORE_register_loader(OSSL_STORE_LOADER *loader); +OSSL_STORE_LOADER *OSSL_STORE_unregister_loader(const char *scheme); + +/*- + * Functions to list STORE loaders + * ------------------------------- + */ +int OSSL_STORE_do_all_loaders(void (*do_function) (const OSSL_STORE_LOADER + *loader, void *do_arg), + void *do_arg); + +# ifdef __cplusplus +} +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/storeerr.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/storeerr.h new file mode 100644 index 000000000..33d0ab790 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/storeerr.h @@ -0,0 +1,87 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_OSSL_STOREERR_H +# define HEADER_OSSL_STOREERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_OSSL_STORE_strings(void); + +/* + * OSSL_STORE function codes. + */ +# define OSSL_STORE_F_FILE_CTRL 129 +# define OSSL_STORE_F_FILE_FIND 138 +# define OSSL_STORE_F_FILE_GET_PASS 118 +# define OSSL_STORE_F_FILE_LOAD 119 +# define OSSL_STORE_F_FILE_LOAD_TRY_DECODE 124 +# define OSSL_STORE_F_FILE_NAME_TO_URI 126 +# define OSSL_STORE_F_FILE_OPEN 120 +# define OSSL_STORE_F_OSSL_STORE_ATTACH_PEM_BIO 127 +# define OSSL_STORE_F_OSSL_STORE_EXPECT 130 +# define OSSL_STORE_F_OSSL_STORE_FILE_ATTACH_PEM_BIO_INT 128 +# define OSSL_STORE_F_OSSL_STORE_FIND 131 +# define OSSL_STORE_F_OSSL_STORE_GET0_LOADER_INT 100 +# define OSSL_STORE_F_OSSL_STORE_INFO_GET1_CERT 101 +# define OSSL_STORE_F_OSSL_STORE_INFO_GET1_CRL 102 +# define OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME 103 +# define OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME_DESCRIPTION 135 +# define OSSL_STORE_F_OSSL_STORE_INFO_GET1_PARAMS 104 +# define OSSL_STORE_F_OSSL_STORE_INFO_GET1_PKEY 105 +# define OSSL_STORE_F_OSSL_STORE_INFO_NEW_CERT 106 +# define OSSL_STORE_F_OSSL_STORE_INFO_NEW_CRL 107 +# define OSSL_STORE_F_OSSL_STORE_INFO_NEW_EMBEDDED 123 +# define OSSL_STORE_F_OSSL_STORE_INFO_NEW_NAME 109 +# define OSSL_STORE_F_OSSL_STORE_INFO_NEW_PARAMS 110 +# define OSSL_STORE_F_OSSL_STORE_INFO_NEW_PKEY 111 +# define OSSL_STORE_F_OSSL_STORE_INFO_SET0_NAME_DESCRIPTION 134 +# define OSSL_STORE_F_OSSL_STORE_INIT_ONCE 112 +# define OSSL_STORE_F_OSSL_STORE_LOADER_NEW 113 +# define OSSL_STORE_F_OSSL_STORE_OPEN 114 +# define OSSL_STORE_F_OSSL_STORE_OPEN_INT 115 +# define OSSL_STORE_F_OSSL_STORE_REGISTER_LOADER_INT 117 +# define OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ALIAS 132 +# define OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ISSUER_SERIAL 133 +# define OSSL_STORE_F_OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT 136 +# define OSSL_STORE_F_OSSL_STORE_SEARCH_BY_NAME 137 +# define OSSL_STORE_F_OSSL_STORE_UNREGISTER_LOADER_INT 116 +# define OSSL_STORE_F_TRY_DECODE_PARAMS 121 +# define OSSL_STORE_F_TRY_DECODE_PKCS12 122 +# define OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED 125 + +/* + * OSSL_STORE reason codes. + */ +# define OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE 107 +# define OSSL_STORE_R_BAD_PASSWORD_READ 115 +# define OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC 113 +# define OSSL_STORE_R_FINGERPRINT_SIZE_DOES_NOT_MATCH_DIGEST 121 +# define OSSL_STORE_R_INVALID_SCHEME 106 +# define OSSL_STORE_R_IS_NOT_A 112 +# define OSSL_STORE_R_LOADER_INCOMPLETE 116 +# define OSSL_STORE_R_LOADING_STARTED 117 +# define OSSL_STORE_R_NOT_A_CERTIFICATE 100 +# define OSSL_STORE_R_NOT_A_CRL 101 +# define OSSL_STORE_R_NOT_A_KEY 102 +# define OSSL_STORE_R_NOT_A_NAME 103 +# define OSSL_STORE_R_NOT_PARAMETERS 104 +# define OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR 114 +# define OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE 108 +# define OSSL_STORE_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES 119 +# define OSSL_STORE_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED 109 +# define OSSL_STORE_R_UNREGISTERED_SCHEME 105 +# define OSSL_STORE_R_UNSUPPORTED_CONTENT_TYPE 110 +# define OSSL_STORE_R_UNSUPPORTED_OPERATION 118 +# define OSSL_STORE_R_UNSUPPORTED_SEARCH_TYPE 120 +# define OSSL_STORE_R_URI_AUTHORITY_UNSUPPORTED 111 + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/symhacks.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/symhacks.h new file mode 100644 index 000000000..156ea6e4e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/symhacks.h @@ -0,0 +1,37 @@ +/* + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_SYMHACKS_H +# define HEADER_SYMHACKS_H + +# include + +/* Case insensitive linking causes problems.... */ +# if defined(OPENSSL_SYS_VMS) +# undef ERR_load_CRYPTO_strings +# define ERR_load_CRYPTO_strings ERR_load_CRYPTOlib_strings +# undef OCSP_crlID_new +# define OCSP_crlID_new OCSP_crlID2_new + +# undef d2i_ECPARAMETERS +# define d2i_ECPARAMETERS d2i_UC_ECPARAMETERS +# undef i2d_ECPARAMETERS +# define i2d_ECPARAMETERS i2d_UC_ECPARAMETERS +# undef d2i_ECPKPARAMETERS +# define d2i_ECPKPARAMETERS d2i_UC_ECPKPARAMETERS +# undef i2d_ECPKPARAMETERS +# define i2d_ECPKPARAMETERS i2d_UC_ECPKPARAMETERS + +/* This one clashes with CMS_data_create */ +# undef cms_Data_create +# define cms_Data_create priv_cms_Data_create + +# endif + +#endif /* ! defined HEADER_VMS_IDHACKS_H */ diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/tls1.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/tls1.h new file mode 100644 index 000000000..e13b5dd4b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/tls1.h @@ -0,0 +1,1237 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * Copyright 2005 Nokia. All rights reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_TLS1_H +# define HEADER_TLS1_H + +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Default security level if not overridden at config time */ +# ifndef OPENSSL_TLS_SECURITY_LEVEL +# define OPENSSL_TLS_SECURITY_LEVEL 1 +# endif + +# define TLS1_VERSION 0x0301 +# define TLS1_1_VERSION 0x0302 +# define TLS1_2_VERSION 0x0303 +# define TLS1_3_VERSION 0x0304 +# define TLS_MAX_VERSION TLS1_3_VERSION + +/* Special value for method supporting multiple versions */ +# define TLS_ANY_VERSION 0x10000 + +# define TLS1_VERSION_MAJOR 0x03 +# define TLS1_VERSION_MINOR 0x01 + +# define TLS1_1_VERSION_MAJOR 0x03 +# define TLS1_1_VERSION_MINOR 0x02 + +# define TLS1_2_VERSION_MAJOR 0x03 +# define TLS1_2_VERSION_MINOR 0x03 + +# define TLS1_get_version(s) \ + ((SSL_version(s) >> 8) == TLS1_VERSION_MAJOR ? SSL_version(s) : 0) + +# define TLS1_get_client_version(s) \ + ((SSL_client_version(s) >> 8) == TLS1_VERSION_MAJOR ? SSL_client_version(s) : 0) + +# define TLS1_AD_DECRYPTION_FAILED 21 +# define TLS1_AD_RECORD_OVERFLOW 22 +# define TLS1_AD_UNKNOWN_CA 48/* fatal */ +# define TLS1_AD_ACCESS_DENIED 49/* fatal */ +# define TLS1_AD_DECODE_ERROR 50/* fatal */ +# define TLS1_AD_DECRYPT_ERROR 51 +# define TLS1_AD_EXPORT_RESTRICTION 60/* fatal */ +# define TLS1_AD_PROTOCOL_VERSION 70/* fatal */ +# define TLS1_AD_INSUFFICIENT_SECURITY 71/* fatal */ +# define TLS1_AD_INTERNAL_ERROR 80/* fatal */ +# define TLS1_AD_INAPPROPRIATE_FALLBACK 86/* fatal */ +# define TLS1_AD_USER_CANCELLED 90 +# define TLS1_AD_NO_RENEGOTIATION 100 +/* TLSv1.3 alerts */ +# define TLS13_AD_MISSING_EXTENSION 109 /* fatal */ +# define TLS13_AD_CERTIFICATE_REQUIRED 116 /* fatal */ +/* codes 110-114 are from RFC3546 */ +# define TLS1_AD_UNSUPPORTED_EXTENSION 110 +# define TLS1_AD_CERTIFICATE_UNOBTAINABLE 111 +# define TLS1_AD_UNRECOGNIZED_NAME 112 +# define TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE 113 +# define TLS1_AD_BAD_CERTIFICATE_HASH_VALUE 114 +# define TLS1_AD_UNKNOWN_PSK_IDENTITY 115/* fatal */ +# define TLS1_AD_NO_APPLICATION_PROTOCOL 120 /* fatal */ + +/* ExtensionType values from RFC3546 / RFC4366 / RFC6066 */ +# define TLSEXT_TYPE_server_name 0 +# define TLSEXT_TYPE_max_fragment_length 1 +# define TLSEXT_TYPE_client_certificate_url 2 +# define TLSEXT_TYPE_trusted_ca_keys 3 +# define TLSEXT_TYPE_truncated_hmac 4 +# define TLSEXT_TYPE_status_request 5 +/* ExtensionType values from RFC4681 */ +# define TLSEXT_TYPE_user_mapping 6 +/* ExtensionType values from RFC5878 */ +# define TLSEXT_TYPE_client_authz 7 +# define TLSEXT_TYPE_server_authz 8 +/* ExtensionType values from RFC6091 */ +# define TLSEXT_TYPE_cert_type 9 + +/* ExtensionType values from RFC4492 */ +/* + * Prior to TLSv1.3 the supported_groups extension was known as + * elliptic_curves + */ +# define TLSEXT_TYPE_supported_groups 10 +# define TLSEXT_TYPE_elliptic_curves TLSEXT_TYPE_supported_groups +# define TLSEXT_TYPE_ec_point_formats 11 + + +/* ExtensionType value from RFC5054 */ +# define TLSEXT_TYPE_srp 12 + +/* ExtensionType values from RFC5246 */ +# define TLSEXT_TYPE_signature_algorithms 13 + +/* ExtensionType value from RFC5764 */ +# define TLSEXT_TYPE_use_srtp 14 + +/* ExtensionType value from RFC5620 */ +# define TLSEXT_TYPE_heartbeat 15 + +/* ExtensionType value from RFC7301 */ +# define TLSEXT_TYPE_application_layer_protocol_negotiation 16 + +/* + * Extension type for Certificate Transparency + * https://tools.ietf.org/html/rfc6962#section-3.3.1 + */ +# define TLSEXT_TYPE_signed_certificate_timestamp 18 + +/* + * ExtensionType value for TLS padding extension. + * http://tools.ietf.org/html/draft-agl-tls-padding + */ +# define TLSEXT_TYPE_padding 21 + +/* ExtensionType value from RFC7366 */ +# define TLSEXT_TYPE_encrypt_then_mac 22 + +/* ExtensionType value from RFC7627 */ +# define TLSEXT_TYPE_extended_master_secret 23 + +/* ExtensionType value from RFC4507 */ +# define TLSEXT_TYPE_session_ticket 35 + +/* As defined for TLS1.3 */ +# define TLSEXT_TYPE_psk 41 +# define TLSEXT_TYPE_early_data 42 +# define TLSEXT_TYPE_supported_versions 43 +# define TLSEXT_TYPE_cookie 44 +# define TLSEXT_TYPE_psk_kex_modes 45 +# define TLSEXT_TYPE_certificate_authorities 47 +# define TLSEXT_TYPE_post_handshake_auth 49 +# define TLSEXT_TYPE_signature_algorithms_cert 50 +# define TLSEXT_TYPE_key_share 51 + +/* Temporary extension type */ +# define TLSEXT_TYPE_renegotiate 0xff01 + +# ifndef OPENSSL_NO_NEXTPROTONEG +/* This is not an IANA defined extension number */ +# define TLSEXT_TYPE_next_proto_neg 13172 +# endif + +/* NameType value from RFC3546 */ +# define TLSEXT_NAMETYPE_host_name 0 +/* status request value from RFC3546 */ +# define TLSEXT_STATUSTYPE_ocsp 1 + +/* ECPointFormat values from RFC4492 */ +# define TLSEXT_ECPOINTFORMAT_first 0 +# define TLSEXT_ECPOINTFORMAT_uncompressed 0 +# define TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime 1 +# define TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2 2 +# define TLSEXT_ECPOINTFORMAT_last 2 + +/* Signature and hash algorithms from RFC5246 */ +# define TLSEXT_signature_anonymous 0 +# define TLSEXT_signature_rsa 1 +# define TLSEXT_signature_dsa 2 +# define TLSEXT_signature_ecdsa 3 +# define TLSEXT_signature_gostr34102001 237 +# define TLSEXT_signature_gostr34102012_256 238 +# define TLSEXT_signature_gostr34102012_512 239 + +/* Total number of different signature algorithms */ +# define TLSEXT_signature_num 7 + +# define TLSEXT_hash_none 0 +# define TLSEXT_hash_md5 1 +# define TLSEXT_hash_sha1 2 +# define TLSEXT_hash_sha224 3 +# define TLSEXT_hash_sha256 4 +# define TLSEXT_hash_sha384 5 +# define TLSEXT_hash_sha512 6 +# define TLSEXT_hash_gostr3411 237 +# define TLSEXT_hash_gostr34112012_256 238 +# define TLSEXT_hash_gostr34112012_512 239 + +/* Total number of different digest algorithms */ + +# define TLSEXT_hash_num 10 + +/* Flag set for unrecognised algorithms */ +# define TLSEXT_nid_unknown 0x1000000 + +/* ECC curves */ + +# define TLSEXT_curve_P_256 23 +# define TLSEXT_curve_P_384 24 + +/* OpenSSL value to disable maximum fragment length extension */ +# define TLSEXT_max_fragment_length_DISABLED 0 +/* Allowed values for max fragment length extension */ +# define TLSEXT_max_fragment_length_512 1 +# define TLSEXT_max_fragment_length_1024 2 +# define TLSEXT_max_fragment_length_2048 3 +# define TLSEXT_max_fragment_length_4096 4 + +int SSL_CTX_set_tlsext_max_fragment_length(SSL_CTX *ctx, uint8_t mode); +int SSL_set_tlsext_max_fragment_length(SSL *ssl, uint8_t mode); + +# define TLSEXT_MAXLEN_host_name 255 + +__owur const char *SSL_get_servername(const SSL *s, const int type); +__owur int SSL_get_servername_type(const SSL *s); +/* + * SSL_export_keying_material exports a value derived from the master secret, + * as specified in RFC 5705. It writes |olen| bytes to |out| given a label and + * optional context. (Since a zero length context is allowed, the |use_context| + * flag controls whether a context is included.) It returns 1 on success and + * 0 or -1 otherwise. + */ +__owur int SSL_export_keying_material(SSL *s, unsigned char *out, size_t olen, + const char *label, size_t llen, + const unsigned char *context, + size_t contextlen, int use_context); + +/* + * SSL_export_keying_material_early exports a value derived from the + * early exporter master secret, as specified in + * https://tools.ietf.org/html/draft-ietf-tls-tls13-23. It writes + * |olen| bytes to |out| given a label and optional context. It + * returns 1 on success and 0 otherwise. + */ +__owur int SSL_export_keying_material_early(SSL *s, unsigned char *out, + size_t olen, const char *label, + size_t llen, + const unsigned char *context, + size_t contextlen); + +int SSL_get_peer_signature_type_nid(const SSL *s, int *pnid); +int SSL_get_signature_type_nid(const SSL *s, int *pnid); + +int SSL_get_sigalgs(SSL *s, int idx, + int *psign, int *phash, int *psignandhash, + unsigned char *rsig, unsigned char *rhash); + +int SSL_get_shared_sigalgs(SSL *s, int idx, + int *psign, int *phash, int *psignandhash, + unsigned char *rsig, unsigned char *rhash); + +__owur int SSL_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain); + +# define SSL_set_tlsext_host_name(s,name) \ + SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_HOSTNAME,TLSEXT_NAMETYPE_host_name,\ + (void *)name) + +# define SSL_set_tlsext_debug_callback(ssl, cb) \ + SSL_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_DEBUG_CB,\ + (void (*)(void))cb) + +# define SSL_set_tlsext_debug_arg(ssl, arg) \ + SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_DEBUG_ARG,0,arg) + +# define SSL_get_tlsext_status_type(ssl) \ + SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_TYPE,0,NULL) + +# define SSL_set_tlsext_status_type(ssl, type) \ + SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE,type,NULL) + +# define SSL_get_tlsext_status_exts(ssl, arg) \ + SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS,0,arg) + +# define SSL_set_tlsext_status_exts(ssl, arg) \ + SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS,0,arg) + +# define SSL_get_tlsext_status_ids(ssl, arg) \ + SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS,0,arg) + +# define SSL_set_tlsext_status_ids(ssl, arg) \ + SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS,0,arg) + +# define SSL_get_tlsext_status_ocsp_resp(ssl, arg) \ + SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP,0,arg) + +# define SSL_set_tlsext_status_ocsp_resp(ssl, arg, arglen) \ + SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP,arglen,arg) + +# define SSL_CTX_set_tlsext_servername_callback(ctx, cb) \ + SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_CB,\ + (void (*)(void))cb) + +# define SSL_TLSEXT_ERR_OK 0 +# define SSL_TLSEXT_ERR_ALERT_WARNING 1 +# define SSL_TLSEXT_ERR_ALERT_FATAL 2 +# define SSL_TLSEXT_ERR_NOACK 3 + +# define SSL_CTX_set_tlsext_servername_arg(ctx, arg) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG,0,arg) + +# define SSL_CTX_get_tlsext_ticket_keys(ctx, keys, keylen) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_TLSEXT_TICKET_KEYS,keylen,keys) +# define SSL_CTX_set_tlsext_ticket_keys(ctx, keys, keylen) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_TICKET_KEYS,keylen,keys) + +# define SSL_CTX_get_tlsext_status_cb(ssl, cb) \ + SSL_CTX_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB,0,(void *)cb) +# define SSL_CTX_set_tlsext_status_cb(ssl, cb) \ + SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB,\ + (void (*)(void))cb) + +# define SSL_CTX_get_tlsext_status_arg(ssl, arg) \ + SSL_CTX_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG,0,arg) +# define SSL_CTX_set_tlsext_status_arg(ssl, arg) \ + SSL_CTX_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG,0,arg) + +# define SSL_CTX_set_tlsext_status_type(ssl, type) \ + SSL_CTX_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE,type,NULL) + +# define SSL_CTX_get_tlsext_status_type(ssl) \ + SSL_CTX_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_TYPE,0,NULL) + +# define SSL_CTX_set_tlsext_ticket_key_cb(ssl, cb) \ + SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,\ + (void (*)(void))cb) + +# ifndef OPENSSL_NO_HEARTBEATS +# define SSL_DTLSEXT_HB_ENABLED 0x01 +# define SSL_DTLSEXT_HB_DONT_SEND_REQUESTS 0x02 +# define SSL_DTLSEXT_HB_DONT_RECV_REQUESTS 0x04 +# define SSL_get_dtlsext_heartbeat_pending(ssl) \ + SSL_ctrl(ssl,SSL_CTRL_GET_DTLS_EXT_HEARTBEAT_PENDING,0,NULL) +# define SSL_set_dtlsext_heartbeat_no_requests(ssl, arg) \ + SSL_ctrl(ssl,SSL_CTRL_SET_DTLS_EXT_HEARTBEAT_NO_REQUESTS,arg,NULL) + +# if OPENSSL_API_COMPAT < 0x10100000L +# define SSL_CTRL_TLS_EXT_SEND_HEARTBEAT \ + SSL_CTRL_DTLS_EXT_SEND_HEARTBEAT +# define SSL_CTRL_GET_TLS_EXT_HEARTBEAT_PENDING \ + SSL_CTRL_GET_DTLS_EXT_HEARTBEAT_PENDING +# define SSL_CTRL_SET_TLS_EXT_HEARTBEAT_NO_REQUESTS \ + SSL_CTRL_SET_DTLS_EXT_HEARTBEAT_NO_REQUESTS +# define SSL_TLSEXT_HB_ENABLED \ + SSL_DTLSEXT_HB_ENABLED +# define SSL_TLSEXT_HB_DONT_SEND_REQUESTS \ + SSL_DTLSEXT_HB_DONT_SEND_REQUESTS +# define SSL_TLSEXT_HB_DONT_RECV_REQUESTS \ + SSL_DTLSEXT_HB_DONT_RECV_REQUESTS +# define SSL_get_tlsext_heartbeat_pending(ssl) \ + SSL_get_dtlsext_heartbeat_pending(ssl) +# define SSL_set_tlsext_heartbeat_no_requests(ssl, arg) \ + SSL_set_dtlsext_heartbeat_no_requests(ssl,arg) +# endif +# endif + +/* PSK ciphersuites from 4279 */ +# define TLS1_CK_PSK_WITH_RC4_128_SHA 0x0300008A +# define TLS1_CK_PSK_WITH_3DES_EDE_CBC_SHA 0x0300008B +# define TLS1_CK_PSK_WITH_AES_128_CBC_SHA 0x0300008C +# define TLS1_CK_PSK_WITH_AES_256_CBC_SHA 0x0300008D +# define TLS1_CK_DHE_PSK_WITH_RC4_128_SHA 0x0300008E +# define TLS1_CK_DHE_PSK_WITH_3DES_EDE_CBC_SHA 0x0300008F +# define TLS1_CK_DHE_PSK_WITH_AES_128_CBC_SHA 0x03000090 +# define TLS1_CK_DHE_PSK_WITH_AES_256_CBC_SHA 0x03000091 +# define TLS1_CK_RSA_PSK_WITH_RC4_128_SHA 0x03000092 +# define TLS1_CK_RSA_PSK_WITH_3DES_EDE_CBC_SHA 0x03000093 +# define TLS1_CK_RSA_PSK_WITH_AES_128_CBC_SHA 0x03000094 +# define TLS1_CK_RSA_PSK_WITH_AES_256_CBC_SHA 0x03000095 + +/* PSK ciphersuites from 5487 */ +# define TLS1_CK_PSK_WITH_AES_128_GCM_SHA256 0x030000A8 +# define TLS1_CK_PSK_WITH_AES_256_GCM_SHA384 0x030000A9 +# define TLS1_CK_DHE_PSK_WITH_AES_128_GCM_SHA256 0x030000AA +# define TLS1_CK_DHE_PSK_WITH_AES_256_GCM_SHA384 0x030000AB +# define TLS1_CK_RSA_PSK_WITH_AES_128_GCM_SHA256 0x030000AC +# define TLS1_CK_RSA_PSK_WITH_AES_256_GCM_SHA384 0x030000AD +# define TLS1_CK_PSK_WITH_AES_128_CBC_SHA256 0x030000AE +# define TLS1_CK_PSK_WITH_AES_256_CBC_SHA384 0x030000AF +# define TLS1_CK_PSK_WITH_NULL_SHA256 0x030000B0 +# define TLS1_CK_PSK_WITH_NULL_SHA384 0x030000B1 +# define TLS1_CK_DHE_PSK_WITH_AES_128_CBC_SHA256 0x030000B2 +# define TLS1_CK_DHE_PSK_WITH_AES_256_CBC_SHA384 0x030000B3 +# define TLS1_CK_DHE_PSK_WITH_NULL_SHA256 0x030000B4 +# define TLS1_CK_DHE_PSK_WITH_NULL_SHA384 0x030000B5 +# define TLS1_CK_RSA_PSK_WITH_AES_128_CBC_SHA256 0x030000B6 +# define TLS1_CK_RSA_PSK_WITH_AES_256_CBC_SHA384 0x030000B7 +# define TLS1_CK_RSA_PSK_WITH_NULL_SHA256 0x030000B8 +# define TLS1_CK_RSA_PSK_WITH_NULL_SHA384 0x030000B9 + +/* NULL PSK ciphersuites from RFC4785 */ +# define TLS1_CK_PSK_WITH_NULL_SHA 0x0300002C +# define TLS1_CK_DHE_PSK_WITH_NULL_SHA 0x0300002D +# define TLS1_CK_RSA_PSK_WITH_NULL_SHA 0x0300002E + +/* AES ciphersuites from RFC3268 */ +# define TLS1_CK_RSA_WITH_AES_128_SHA 0x0300002F +# define TLS1_CK_DH_DSS_WITH_AES_128_SHA 0x03000030 +# define TLS1_CK_DH_RSA_WITH_AES_128_SHA 0x03000031 +# define TLS1_CK_DHE_DSS_WITH_AES_128_SHA 0x03000032 +# define TLS1_CK_DHE_RSA_WITH_AES_128_SHA 0x03000033 +# define TLS1_CK_ADH_WITH_AES_128_SHA 0x03000034 +# define TLS1_CK_RSA_WITH_AES_256_SHA 0x03000035 +# define TLS1_CK_DH_DSS_WITH_AES_256_SHA 0x03000036 +# define TLS1_CK_DH_RSA_WITH_AES_256_SHA 0x03000037 +# define TLS1_CK_DHE_DSS_WITH_AES_256_SHA 0x03000038 +# define TLS1_CK_DHE_RSA_WITH_AES_256_SHA 0x03000039 +# define TLS1_CK_ADH_WITH_AES_256_SHA 0x0300003A + +/* TLS v1.2 ciphersuites */ +# define TLS1_CK_RSA_WITH_NULL_SHA256 0x0300003B +# define TLS1_CK_RSA_WITH_AES_128_SHA256 0x0300003C +# define TLS1_CK_RSA_WITH_AES_256_SHA256 0x0300003D +# define TLS1_CK_DH_DSS_WITH_AES_128_SHA256 0x0300003E +# define TLS1_CK_DH_RSA_WITH_AES_128_SHA256 0x0300003F +# define TLS1_CK_DHE_DSS_WITH_AES_128_SHA256 0x03000040 + +/* Camellia ciphersuites from RFC4132 */ +# define TLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA 0x03000041 +# define TLS1_CK_DH_DSS_WITH_CAMELLIA_128_CBC_SHA 0x03000042 +# define TLS1_CK_DH_RSA_WITH_CAMELLIA_128_CBC_SHA 0x03000043 +# define TLS1_CK_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA 0x03000044 +# define TLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x03000045 +# define TLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA 0x03000046 + +/* TLS v1.2 ciphersuites */ +# define TLS1_CK_DHE_RSA_WITH_AES_128_SHA256 0x03000067 +# define TLS1_CK_DH_DSS_WITH_AES_256_SHA256 0x03000068 +# define TLS1_CK_DH_RSA_WITH_AES_256_SHA256 0x03000069 +# define TLS1_CK_DHE_DSS_WITH_AES_256_SHA256 0x0300006A +# define TLS1_CK_DHE_RSA_WITH_AES_256_SHA256 0x0300006B +# define TLS1_CK_ADH_WITH_AES_128_SHA256 0x0300006C +# define TLS1_CK_ADH_WITH_AES_256_SHA256 0x0300006D + +/* Camellia ciphersuites from RFC4132 */ +# define TLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA 0x03000084 +# define TLS1_CK_DH_DSS_WITH_CAMELLIA_256_CBC_SHA 0x03000085 +# define TLS1_CK_DH_RSA_WITH_CAMELLIA_256_CBC_SHA 0x03000086 +# define TLS1_CK_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA 0x03000087 +# define TLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x03000088 +# define TLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA 0x03000089 + +/* SEED ciphersuites from RFC4162 */ +# define TLS1_CK_RSA_WITH_SEED_SHA 0x03000096 +# define TLS1_CK_DH_DSS_WITH_SEED_SHA 0x03000097 +# define TLS1_CK_DH_RSA_WITH_SEED_SHA 0x03000098 +# define TLS1_CK_DHE_DSS_WITH_SEED_SHA 0x03000099 +# define TLS1_CK_DHE_RSA_WITH_SEED_SHA 0x0300009A +# define TLS1_CK_ADH_WITH_SEED_SHA 0x0300009B + +/* TLS v1.2 GCM ciphersuites from RFC5288 */ +# define TLS1_CK_RSA_WITH_AES_128_GCM_SHA256 0x0300009C +# define TLS1_CK_RSA_WITH_AES_256_GCM_SHA384 0x0300009D +# define TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256 0x0300009E +# define TLS1_CK_DHE_RSA_WITH_AES_256_GCM_SHA384 0x0300009F +# define TLS1_CK_DH_RSA_WITH_AES_128_GCM_SHA256 0x030000A0 +# define TLS1_CK_DH_RSA_WITH_AES_256_GCM_SHA384 0x030000A1 +# define TLS1_CK_DHE_DSS_WITH_AES_128_GCM_SHA256 0x030000A2 +# define TLS1_CK_DHE_DSS_WITH_AES_256_GCM_SHA384 0x030000A3 +# define TLS1_CK_DH_DSS_WITH_AES_128_GCM_SHA256 0x030000A4 +# define TLS1_CK_DH_DSS_WITH_AES_256_GCM_SHA384 0x030000A5 +# define TLS1_CK_ADH_WITH_AES_128_GCM_SHA256 0x030000A6 +# define TLS1_CK_ADH_WITH_AES_256_GCM_SHA384 0x030000A7 + +/* CCM ciphersuites from RFC6655 */ +# define TLS1_CK_RSA_WITH_AES_128_CCM 0x0300C09C +# define TLS1_CK_RSA_WITH_AES_256_CCM 0x0300C09D +# define TLS1_CK_DHE_RSA_WITH_AES_128_CCM 0x0300C09E +# define TLS1_CK_DHE_RSA_WITH_AES_256_CCM 0x0300C09F +# define TLS1_CK_RSA_WITH_AES_128_CCM_8 0x0300C0A0 +# define TLS1_CK_RSA_WITH_AES_256_CCM_8 0x0300C0A1 +# define TLS1_CK_DHE_RSA_WITH_AES_128_CCM_8 0x0300C0A2 +# define TLS1_CK_DHE_RSA_WITH_AES_256_CCM_8 0x0300C0A3 +# define TLS1_CK_PSK_WITH_AES_128_CCM 0x0300C0A4 +# define TLS1_CK_PSK_WITH_AES_256_CCM 0x0300C0A5 +# define TLS1_CK_DHE_PSK_WITH_AES_128_CCM 0x0300C0A6 +# define TLS1_CK_DHE_PSK_WITH_AES_256_CCM 0x0300C0A7 +# define TLS1_CK_PSK_WITH_AES_128_CCM_8 0x0300C0A8 +# define TLS1_CK_PSK_WITH_AES_256_CCM_8 0x0300C0A9 +# define TLS1_CK_DHE_PSK_WITH_AES_128_CCM_8 0x0300C0AA +# define TLS1_CK_DHE_PSK_WITH_AES_256_CCM_8 0x0300C0AB + +/* CCM ciphersuites from RFC7251 */ +# define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CCM 0x0300C0AC +# define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CCM 0x0300C0AD +# define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CCM_8 0x0300C0AE +# define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CCM_8 0x0300C0AF + +/* TLS 1.2 Camellia SHA-256 ciphersuites from RFC5932 */ +# define TLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA256 0x030000BA +# define TLS1_CK_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 0x030000BB +# define TLS1_CK_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 0x030000BC +# define TLS1_CK_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 0x030000BD +# define TLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0x030000BE +# define TLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA256 0x030000BF + +# define TLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA256 0x030000C0 +# define TLS1_CK_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 0x030000C1 +# define TLS1_CK_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 0x030000C2 +# define TLS1_CK_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 0x030000C3 +# define TLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 0x030000C4 +# define TLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA256 0x030000C5 + +/* ECC ciphersuites from RFC4492 */ +# define TLS1_CK_ECDH_ECDSA_WITH_NULL_SHA 0x0300C001 +# define TLS1_CK_ECDH_ECDSA_WITH_RC4_128_SHA 0x0300C002 +# define TLS1_CK_ECDH_ECDSA_WITH_DES_192_CBC3_SHA 0x0300C003 +# define TLS1_CK_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0x0300C004 +# define TLS1_CK_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0x0300C005 + +# define TLS1_CK_ECDHE_ECDSA_WITH_NULL_SHA 0x0300C006 +# define TLS1_CK_ECDHE_ECDSA_WITH_RC4_128_SHA 0x0300C007 +# define TLS1_CK_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA 0x0300C008 +# define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0x0300C009 +# define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0x0300C00A + +# define TLS1_CK_ECDH_RSA_WITH_NULL_SHA 0x0300C00B +# define TLS1_CK_ECDH_RSA_WITH_RC4_128_SHA 0x0300C00C +# define TLS1_CK_ECDH_RSA_WITH_DES_192_CBC3_SHA 0x0300C00D +# define TLS1_CK_ECDH_RSA_WITH_AES_128_CBC_SHA 0x0300C00E +# define TLS1_CK_ECDH_RSA_WITH_AES_256_CBC_SHA 0x0300C00F + +# define TLS1_CK_ECDHE_RSA_WITH_NULL_SHA 0x0300C010 +# define TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA 0x0300C011 +# define TLS1_CK_ECDHE_RSA_WITH_DES_192_CBC3_SHA 0x0300C012 +# define TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA 0x0300C013 +# define TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA 0x0300C014 + +# define TLS1_CK_ECDH_anon_WITH_NULL_SHA 0x0300C015 +# define TLS1_CK_ECDH_anon_WITH_RC4_128_SHA 0x0300C016 +# define TLS1_CK_ECDH_anon_WITH_DES_192_CBC3_SHA 0x0300C017 +# define TLS1_CK_ECDH_anon_WITH_AES_128_CBC_SHA 0x0300C018 +# define TLS1_CK_ECDH_anon_WITH_AES_256_CBC_SHA 0x0300C019 + +/* SRP ciphersuites from RFC 5054 */ +# define TLS1_CK_SRP_SHA_WITH_3DES_EDE_CBC_SHA 0x0300C01A +# define TLS1_CK_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA 0x0300C01B +# define TLS1_CK_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA 0x0300C01C +# define TLS1_CK_SRP_SHA_WITH_AES_128_CBC_SHA 0x0300C01D +# define TLS1_CK_SRP_SHA_RSA_WITH_AES_128_CBC_SHA 0x0300C01E +# define TLS1_CK_SRP_SHA_DSS_WITH_AES_128_CBC_SHA 0x0300C01F +# define TLS1_CK_SRP_SHA_WITH_AES_256_CBC_SHA 0x0300C020 +# define TLS1_CK_SRP_SHA_RSA_WITH_AES_256_CBC_SHA 0x0300C021 +# define TLS1_CK_SRP_SHA_DSS_WITH_AES_256_CBC_SHA 0x0300C022 + +/* ECDH HMAC based ciphersuites from RFC5289 */ +# define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_SHA256 0x0300C023 +# define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_SHA384 0x0300C024 +# define TLS1_CK_ECDH_ECDSA_WITH_AES_128_SHA256 0x0300C025 +# define TLS1_CK_ECDH_ECDSA_WITH_AES_256_SHA384 0x0300C026 +# define TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256 0x0300C027 +# define TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384 0x0300C028 +# define TLS1_CK_ECDH_RSA_WITH_AES_128_SHA256 0x0300C029 +# define TLS1_CK_ECDH_RSA_WITH_AES_256_SHA384 0x0300C02A + +/* ECDH GCM based ciphersuites from RFC5289 */ +# define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0x0300C02B +# define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0x0300C02C +# define TLS1_CK_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0x0300C02D +# define TLS1_CK_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0x0300C02E +# define TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0x0300C02F +# define TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0x0300C030 +# define TLS1_CK_ECDH_RSA_WITH_AES_128_GCM_SHA256 0x0300C031 +# define TLS1_CK_ECDH_RSA_WITH_AES_256_GCM_SHA384 0x0300C032 + +/* ECDHE PSK ciphersuites from RFC5489 */ +# define TLS1_CK_ECDHE_PSK_WITH_RC4_128_SHA 0x0300C033 +# define TLS1_CK_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA 0x0300C034 +# define TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA 0x0300C035 +# define TLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA 0x0300C036 + +# define TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA256 0x0300C037 +# define TLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA384 0x0300C038 + +/* NULL PSK ciphersuites from RFC4785 */ +# define TLS1_CK_ECDHE_PSK_WITH_NULL_SHA 0x0300C039 +# define TLS1_CK_ECDHE_PSK_WITH_NULL_SHA256 0x0300C03A +# define TLS1_CK_ECDHE_PSK_WITH_NULL_SHA384 0x0300C03B + +/* Camellia-CBC ciphersuites from RFC6367 */ +# define TLS1_CK_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0x0300C072 +# define TLS1_CK_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0x0300C073 +# define TLS1_CK_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0x0300C074 +# define TLS1_CK_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0x0300C075 +# define TLS1_CK_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0x0300C076 +# define TLS1_CK_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 0x0300C077 +# define TLS1_CK_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 0x0300C078 +# define TLS1_CK_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 0x0300C079 + +# define TLS1_CK_PSK_WITH_CAMELLIA_128_CBC_SHA256 0x0300C094 +# define TLS1_CK_PSK_WITH_CAMELLIA_256_CBC_SHA384 0x0300C095 +# define TLS1_CK_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0x0300C096 +# define TLS1_CK_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0x0300C097 +# define TLS1_CK_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 0x0300C098 +# define TLS1_CK_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 0x0300C099 +# define TLS1_CK_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0x0300C09A +# define TLS1_CK_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0x0300C09B + +/* draft-ietf-tls-chacha20-poly1305-03 */ +# define TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305 0x0300CCA8 +# define TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 0x0300CCA9 +# define TLS1_CK_DHE_RSA_WITH_CHACHA20_POLY1305 0x0300CCAA +# define TLS1_CK_PSK_WITH_CHACHA20_POLY1305 0x0300CCAB +# define TLS1_CK_ECDHE_PSK_WITH_CHACHA20_POLY1305 0x0300CCAC +# define TLS1_CK_DHE_PSK_WITH_CHACHA20_POLY1305 0x0300CCAD +# define TLS1_CK_RSA_PSK_WITH_CHACHA20_POLY1305 0x0300CCAE + +/* TLS v1.3 ciphersuites */ +# define TLS1_3_CK_AES_128_GCM_SHA256 0x03001301 +# define TLS1_3_CK_AES_256_GCM_SHA384 0x03001302 +# define TLS1_3_CK_CHACHA20_POLY1305_SHA256 0x03001303 +# define TLS1_3_CK_AES_128_CCM_SHA256 0x03001304 +# define TLS1_3_CK_AES_128_CCM_8_SHA256 0x03001305 + +/* Aria ciphersuites from RFC6209 */ +# define TLS1_CK_RSA_WITH_ARIA_128_GCM_SHA256 0x0300C050 +# define TLS1_CK_RSA_WITH_ARIA_256_GCM_SHA384 0x0300C051 +# define TLS1_CK_DHE_RSA_WITH_ARIA_128_GCM_SHA256 0x0300C052 +# define TLS1_CK_DHE_RSA_WITH_ARIA_256_GCM_SHA384 0x0300C053 +# define TLS1_CK_DH_RSA_WITH_ARIA_128_GCM_SHA256 0x0300C054 +# define TLS1_CK_DH_RSA_WITH_ARIA_256_GCM_SHA384 0x0300C055 +# define TLS1_CK_DHE_DSS_WITH_ARIA_128_GCM_SHA256 0x0300C056 +# define TLS1_CK_DHE_DSS_WITH_ARIA_256_GCM_SHA384 0x0300C057 +# define TLS1_CK_DH_DSS_WITH_ARIA_128_GCM_SHA256 0x0300C058 +# define TLS1_CK_DH_DSS_WITH_ARIA_256_GCM_SHA384 0x0300C059 +# define TLS1_CK_DH_anon_WITH_ARIA_128_GCM_SHA256 0x0300C05A +# define TLS1_CK_DH_anon_WITH_ARIA_256_GCM_SHA384 0x0300C05B +# define TLS1_CK_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 0x0300C05C +# define TLS1_CK_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 0x0300C05D +# define TLS1_CK_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 0x0300C05E +# define TLS1_CK_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 0x0300C05F +# define TLS1_CK_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 0x0300C060 +# define TLS1_CK_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 0x0300C061 +# define TLS1_CK_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 0x0300C062 +# define TLS1_CK_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 0x0300C063 +# define TLS1_CK_PSK_WITH_ARIA_128_GCM_SHA256 0x0300C06A +# define TLS1_CK_PSK_WITH_ARIA_256_GCM_SHA384 0x0300C06B +# define TLS1_CK_DHE_PSK_WITH_ARIA_128_GCM_SHA256 0x0300C06C +# define TLS1_CK_DHE_PSK_WITH_ARIA_256_GCM_SHA384 0x0300C06D +# define TLS1_CK_RSA_PSK_WITH_ARIA_128_GCM_SHA256 0x0300C06E +# define TLS1_CK_RSA_PSK_WITH_ARIA_256_GCM_SHA384 0x0300C06F + +/* a bundle of RFC standard cipher names, generated from ssl3_ciphers[] */ +# define TLS1_RFC_RSA_WITH_AES_128_SHA "TLS_RSA_WITH_AES_128_CBC_SHA" +# define TLS1_RFC_DHE_DSS_WITH_AES_128_SHA "TLS_DHE_DSS_WITH_AES_128_CBC_SHA" +# define TLS1_RFC_DHE_RSA_WITH_AES_128_SHA "TLS_DHE_RSA_WITH_AES_128_CBC_SHA" +# define TLS1_RFC_ADH_WITH_AES_128_SHA "TLS_DH_anon_WITH_AES_128_CBC_SHA" +# define TLS1_RFC_RSA_WITH_AES_256_SHA "TLS_RSA_WITH_AES_256_CBC_SHA" +# define TLS1_RFC_DHE_DSS_WITH_AES_256_SHA "TLS_DHE_DSS_WITH_AES_256_CBC_SHA" +# define TLS1_RFC_DHE_RSA_WITH_AES_256_SHA "TLS_DHE_RSA_WITH_AES_256_CBC_SHA" +# define TLS1_RFC_ADH_WITH_AES_256_SHA "TLS_DH_anon_WITH_AES_256_CBC_SHA" +# define TLS1_RFC_RSA_WITH_NULL_SHA256 "TLS_RSA_WITH_NULL_SHA256" +# define TLS1_RFC_RSA_WITH_AES_128_SHA256 "TLS_RSA_WITH_AES_128_CBC_SHA256" +# define TLS1_RFC_RSA_WITH_AES_256_SHA256 "TLS_RSA_WITH_AES_256_CBC_SHA256" +# define TLS1_RFC_DHE_DSS_WITH_AES_128_SHA256 "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256" +# define TLS1_RFC_DHE_RSA_WITH_AES_128_SHA256 "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256" +# define TLS1_RFC_DHE_DSS_WITH_AES_256_SHA256 "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256" +# define TLS1_RFC_DHE_RSA_WITH_AES_256_SHA256 "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256" +# define TLS1_RFC_ADH_WITH_AES_128_SHA256 "TLS_DH_anon_WITH_AES_128_CBC_SHA256" +# define TLS1_RFC_ADH_WITH_AES_256_SHA256 "TLS_DH_anon_WITH_AES_256_CBC_SHA256" +# define TLS1_RFC_RSA_WITH_AES_128_GCM_SHA256 "TLS_RSA_WITH_AES_128_GCM_SHA256" +# define TLS1_RFC_RSA_WITH_AES_256_GCM_SHA384 "TLS_RSA_WITH_AES_256_GCM_SHA384" +# define TLS1_RFC_DHE_RSA_WITH_AES_128_GCM_SHA256 "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256" +# define TLS1_RFC_DHE_RSA_WITH_AES_256_GCM_SHA384 "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384" +# define TLS1_RFC_DHE_DSS_WITH_AES_128_GCM_SHA256 "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256" +# define TLS1_RFC_DHE_DSS_WITH_AES_256_GCM_SHA384 "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384" +# define TLS1_RFC_ADH_WITH_AES_128_GCM_SHA256 "TLS_DH_anon_WITH_AES_128_GCM_SHA256" +# define TLS1_RFC_ADH_WITH_AES_256_GCM_SHA384 "TLS_DH_anon_WITH_AES_256_GCM_SHA384" +# define TLS1_RFC_RSA_WITH_AES_128_CCM "TLS_RSA_WITH_AES_128_CCM" +# define TLS1_RFC_RSA_WITH_AES_256_CCM "TLS_RSA_WITH_AES_256_CCM" +# define TLS1_RFC_DHE_RSA_WITH_AES_128_CCM "TLS_DHE_RSA_WITH_AES_128_CCM" +# define TLS1_RFC_DHE_RSA_WITH_AES_256_CCM "TLS_DHE_RSA_WITH_AES_256_CCM" +# define TLS1_RFC_RSA_WITH_AES_128_CCM_8 "TLS_RSA_WITH_AES_128_CCM_8" +# define TLS1_RFC_RSA_WITH_AES_256_CCM_8 "TLS_RSA_WITH_AES_256_CCM_8" +# define TLS1_RFC_DHE_RSA_WITH_AES_128_CCM_8 "TLS_DHE_RSA_WITH_AES_128_CCM_8" +# define TLS1_RFC_DHE_RSA_WITH_AES_256_CCM_8 "TLS_DHE_RSA_WITH_AES_256_CCM_8" +# define TLS1_RFC_PSK_WITH_AES_128_CCM "TLS_PSK_WITH_AES_128_CCM" +# define TLS1_RFC_PSK_WITH_AES_256_CCM "TLS_PSK_WITH_AES_256_CCM" +# define TLS1_RFC_DHE_PSK_WITH_AES_128_CCM "TLS_DHE_PSK_WITH_AES_128_CCM" +# define TLS1_RFC_DHE_PSK_WITH_AES_256_CCM "TLS_DHE_PSK_WITH_AES_256_CCM" +# define TLS1_RFC_PSK_WITH_AES_128_CCM_8 "TLS_PSK_WITH_AES_128_CCM_8" +# define TLS1_RFC_PSK_WITH_AES_256_CCM_8 "TLS_PSK_WITH_AES_256_CCM_8" +# define TLS1_RFC_DHE_PSK_WITH_AES_128_CCM_8 "TLS_PSK_DHE_WITH_AES_128_CCM_8" +# define TLS1_RFC_DHE_PSK_WITH_AES_256_CCM_8 "TLS_PSK_DHE_WITH_AES_256_CCM_8" +# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_128_CCM "TLS_ECDHE_ECDSA_WITH_AES_128_CCM" +# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_256_CCM "TLS_ECDHE_ECDSA_WITH_AES_256_CCM" +# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_128_CCM_8 "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8" +# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_256_CCM_8 "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8" +# define TLS1_3_RFC_AES_128_GCM_SHA256 "TLS_AES_128_GCM_SHA256" +# define TLS1_3_RFC_AES_256_GCM_SHA384 "TLS_AES_256_GCM_SHA384" +# define TLS1_3_RFC_CHACHA20_POLY1305_SHA256 "TLS_CHACHA20_POLY1305_SHA256" +# define TLS1_3_RFC_AES_128_CCM_SHA256 "TLS_AES_128_CCM_SHA256" +# define TLS1_3_RFC_AES_128_CCM_8_SHA256 "TLS_AES_128_CCM_8_SHA256" +# define TLS1_RFC_ECDHE_ECDSA_WITH_NULL_SHA "TLS_ECDHE_ECDSA_WITH_NULL_SHA" +# define TLS1_RFC_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA" +# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_128_CBC_SHA "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA" +# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_256_CBC_SHA "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA" +# define TLS1_RFC_ECDHE_RSA_WITH_NULL_SHA "TLS_ECDHE_RSA_WITH_NULL_SHA" +# define TLS1_RFC_ECDHE_RSA_WITH_DES_192_CBC3_SHA "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA" +# define TLS1_RFC_ECDHE_RSA_WITH_AES_128_CBC_SHA "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA" +# define TLS1_RFC_ECDHE_RSA_WITH_AES_256_CBC_SHA "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA" +# define TLS1_RFC_ECDH_anon_WITH_NULL_SHA "TLS_ECDH_anon_WITH_NULL_SHA" +# define TLS1_RFC_ECDH_anon_WITH_DES_192_CBC3_SHA "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA" +# define TLS1_RFC_ECDH_anon_WITH_AES_128_CBC_SHA "TLS_ECDH_anon_WITH_AES_128_CBC_SHA" +# define TLS1_RFC_ECDH_anon_WITH_AES_256_CBC_SHA "TLS_ECDH_anon_WITH_AES_256_CBC_SHA" +# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_128_SHA256 "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256" +# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_256_SHA384 "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384" +# define TLS1_RFC_ECDHE_RSA_WITH_AES_128_SHA256 "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256" +# define TLS1_RFC_ECDHE_RSA_WITH_AES_256_SHA384 "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384" +# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" +# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" +# define TLS1_RFC_ECDHE_RSA_WITH_AES_128_GCM_SHA256 "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" +# define TLS1_RFC_ECDHE_RSA_WITH_AES_256_GCM_SHA384 "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" +# define TLS1_RFC_PSK_WITH_NULL_SHA "TLS_PSK_WITH_NULL_SHA" +# define TLS1_RFC_DHE_PSK_WITH_NULL_SHA "TLS_DHE_PSK_WITH_NULL_SHA" +# define TLS1_RFC_RSA_PSK_WITH_NULL_SHA "TLS_RSA_PSK_WITH_NULL_SHA" +# define TLS1_RFC_PSK_WITH_3DES_EDE_CBC_SHA "TLS_PSK_WITH_3DES_EDE_CBC_SHA" +# define TLS1_RFC_PSK_WITH_AES_128_CBC_SHA "TLS_PSK_WITH_AES_128_CBC_SHA" +# define TLS1_RFC_PSK_WITH_AES_256_CBC_SHA "TLS_PSK_WITH_AES_256_CBC_SHA" +# define TLS1_RFC_DHE_PSK_WITH_3DES_EDE_CBC_SHA "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA" +# define TLS1_RFC_DHE_PSK_WITH_AES_128_CBC_SHA "TLS_DHE_PSK_WITH_AES_128_CBC_SHA" +# define TLS1_RFC_DHE_PSK_WITH_AES_256_CBC_SHA "TLS_DHE_PSK_WITH_AES_256_CBC_SHA" +# define TLS1_RFC_RSA_PSK_WITH_3DES_EDE_CBC_SHA "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA" +# define TLS1_RFC_RSA_PSK_WITH_AES_128_CBC_SHA "TLS_RSA_PSK_WITH_AES_128_CBC_SHA" +# define TLS1_RFC_RSA_PSK_WITH_AES_256_CBC_SHA "TLS_RSA_PSK_WITH_AES_256_CBC_SHA" +# define TLS1_RFC_PSK_WITH_AES_128_GCM_SHA256 "TLS_PSK_WITH_AES_128_GCM_SHA256" +# define TLS1_RFC_PSK_WITH_AES_256_GCM_SHA384 "TLS_PSK_WITH_AES_256_GCM_SHA384" +# define TLS1_RFC_DHE_PSK_WITH_AES_128_GCM_SHA256 "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256" +# define TLS1_RFC_DHE_PSK_WITH_AES_256_GCM_SHA384 "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384" +# define TLS1_RFC_RSA_PSK_WITH_AES_128_GCM_SHA256 "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256" +# define TLS1_RFC_RSA_PSK_WITH_AES_256_GCM_SHA384 "TLS_RSA_PSK_WITH_AES_256_GCM_SHA384" +# define TLS1_RFC_PSK_WITH_AES_128_CBC_SHA256 "TLS_PSK_WITH_AES_128_CBC_SHA256" +# define TLS1_RFC_PSK_WITH_AES_256_CBC_SHA384 "TLS_PSK_WITH_AES_256_CBC_SHA384" +# define TLS1_RFC_PSK_WITH_NULL_SHA256 "TLS_PSK_WITH_NULL_SHA256" +# define TLS1_RFC_PSK_WITH_NULL_SHA384 "TLS_PSK_WITH_NULL_SHA384" +# define TLS1_RFC_DHE_PSK_WITH_AES_128_CBC_SHA256 "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256" +# define TLS1_RFC_DHE_PSK_WITH_AES_256_CBC_SHA384 "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384" +# define TLS1_RFC_DHE_PSK_WITH_NULL_SHA256 "TLS_DHE_PSK_WITH_NULL_SHA256" +# define TLS1_RFC_DHE_PSK_WITH_NULL_SHA384 "TLS_DHE_PSK_WITH_NULL_SHA384" +# define TLS1_RFC_RSA_PSK_WITH_AES_128_CBC_SHA256 "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256" +# define TLS1_RFC_RSA_PSK_WITH_AES_256_CBC_SHA384 "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384" +# define TLS1_RFC_RSA_PSK_WITH_NULL_SHA256 "TLS_RSA_PSK_WITH_NULL_SHA256" +# define TLS1_RFC_RSA_PSK_WITH_NULL_SHA384 "TLS_RSA_PSK_WITH_NULL_SHA384" +# define TLS1_RFC_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA "TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA" +# define TLS1_RFC_ECDHE_PSK_WITH_AES_128_CBC_SHA "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA" +# define TLS1_RFC_ECDHE_PSK_WITH_AES_256_CBC_SHA "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA" +# define TLS1_RFC_ECDHE_PSK_WITH_AES_128_CBC_SHA256 "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256" +# define TLS1_RFC_ECDHE_PSK_WITH_AES_256_CBC_SHA384 "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384" +# define TLS1_RFC_ECDHE_PSK_WITH_NULL_SHA "TLS_ECDHE_PSK_WITH_NULL_SHA" +# define TLS1_RFC_ECDHE_PSK_WITH_NULL_SHA256 "TLS_ECDHE_PSK_WITH_NULL_SHA256" +# define TLS1_RFC_ECDHE_PSK_WITH_NULL_SHA384 "TLS_ECDHE_PSK_WITH_NULL_SHA384" +# define TLS1_RFC_SRP_SHA_WITH_3DES_EDE_CBC_SHA "TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA" +# define TLS1_RFC_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA "TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA" +# define TLS1_RFC_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA "TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA" +# define TLS1_RFC_SRP_SHA_WITH_AES_128_CBC_SHA "TLS_SRP_SHA_WITH_AES_128_CBC_SHA" +# define TLS1_RFC_SRP_SHA_RSA_WITH_AES_128_CBC_SHA "TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA" +# define TLS1_RFC_SRP_SHA_DSS_WITH_AES_128_CBC_SHA "TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA" +# define TLS1_RFC_SRP_SHA_WITH_AES_256_CBC_SHA "TLS_SRP_SHA_WITH_AES_256_CBC_SHA" +# define TLS1_RFC_SRP_SHA_RSA_WITH_AES_256_CBC_SHA "TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA" +# define TLS1_RFC_SRP_SHA_DSS_WITH_AES_256_CBC_SHA "TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA" +# define TLS1_RFC_DHE_RSA_WITH_CHACHA20_POLY1305 "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256" +# define TLS1_RFC_ECDHE_RSA_WITH_CHACHA20_POLY1305 "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" +# define TLS1_RFC_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" +# define TLS1_RFC_PSK_WITH_CHACHA20_POLY1305 "TLS_PSK_WITH_CHACHA20_POLY1305_SHA256" +# define TLS1_RFC_ECDHE_PSK_WITH_CHACHA20_POLY1305 "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256" +# define TLS1_RFC_DHE_PSK_WITH_CHACHA20_POLY1305 "TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256" +# define TLS1_RFC_RSA_PSK_WITH_CHACHA20_POLY1305 "TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256" +# define TLS1_RFC_RSA_WITH_CAMELLIA_128_CBC_SHA256 "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256" +# define TLS1_RFC_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256" +# define TLS1_RFC_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256" +# define TLS1_RFC_ADH_WITH_CAMELLIA_128_CBC_SHA256 "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256" +# define TLS1_RFC_RSA_WITH_CAMELLIA_256_CBC_SHA256 "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256" +# define TLS1_RFC_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256" +# define TLS1_RFC_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256" +# define TLS1_RFC_ADH_WITH_CAMELLIA_256_CBC_SHA256 "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256" +# define TLS1_RFC_RSA_WITH_CAMELLIA_256_CBC_SHA "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA" +# define TLS1_RFC_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA" +# define TLS1_RFC_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA" +# define TLS1_RFC_ADH_WITH_CAMELLIA_256_CBC_SHA "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA" +# define TLS1_RFC_RSA_WITH_CAMELLIA_128_CBC_SHA "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA" +# define TLS1_RFC_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA" +# define TLS1_RFC_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA" +# define TLS1_RFC_ADH_WITH_CAMELLIA_128_CBC_SHA "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA" +# define TLS1_RFC_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256" +# define TLS1_RFC_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384" +# define TLS1_RFC_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 "TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256" +# define TLS1_RFC_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 "TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384" +# define TLS1_RFC_PSK_WITH_CAMELLIA_128_CBC_SHA256 "TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256" +# define TLS1_RFC_PSK_WITH_CAMELLIA_256_CBC_SHA384 "TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384" +# define TLS1_RFC_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 "TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256" +# define TLS1_RFC_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 "TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384" +# define TLS1_RFC_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 "TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256" +# define TLS1_RFC_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 "TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384" +# define TLS1_RFC_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 "TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256" +# define TLS1_RFC_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 "TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384" +# define TLS1_RFC_RSA_WITH_SEED_SHA "TLS_RSA_WITH_SEED_CBC_SHA" +# define TLS1_RFC_DHE_DSS_WITH_SEED_SHA "TLS_DHE_DSS_WITH_SEED_CBC_SHA" +# define TLS1_RFC_DHE_RSA_WITH_SEED_SHA "TLS_DHE_RSA_WITH_SEED_CBC_SHA" +# define TLS1_RFC_ADH_WITH_SEED_SHA "TLS_DH_anon_WITH_SEED_CBC_SHA" +# define TLS1_RFC_ECDHE_PSK_WITH_RC4_128_SHA "TLS_ECDHE_PSK_WITH_RC4_128_SHA" +# define TLS1_RFC_ECDH_anon_WITH_RC4_128_SHA "TLS_ECDH_anon_WITH_RC4_128_SHA" +# define TLS1_RFC_ECDHE_ECDSA_WITH_RC4_128_SHA "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA" +# define TLS1_RFC_ECDHE_RSA_WITH_RC4_128_SHA "TLS_ECDHE_RSA_WITH_RC4_128_SHA" +# define TLS1_RFC_PSK_WITH_RC4_128_SHA "TLS_PSK_WITH_RC4_128_SHA" +# define TLS1_RFC_RSA_PSK_WITH_RC4_128_SHA "TLS_RSA_PSK_WITH_RC4_128_SHA" +# define TLS1_RFC_DHE_PSK_WITH_RC4_128_SHA "TLS_DHE_PSK_WITH_RC4_128_SHA" +# define TLS1_RFC_RSA_WITH_ARIA_128_GCM_SHA256 "TLS_RSA_WITH_ARIA_128_GCM_SHA256" +# define TLS1_RFC_RSA_WITH_ARIA_256_GCM_SHA384 "TLS_RSA_WITH_ARIA_256_GCM_SHA384" +# define TLS1_RFC_DHE_RSA_WITH_ARIA_128_GCM_SHA256 "TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256" +# define TLS1_RFC_DHE_RSA_WITH_ARIA_256_GCM_SHA384 "TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384" +# define TLS1_RFC_DH_RSA_WITH_ARIA_128_GCM_SHA256 "TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256" +# define TLS1_RFC_DH_RSA_WITH_ARIA_256_GCM_SHA384 "TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384" +# define TLS1_RFC_DHE_DSS_WITH_ARIA_128_GCM_SHA256 "TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256" +# define TLS1_RFC_DHE_DSS_WITH_ARIA_256_GCM_SHA384 "TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384" +# define TLS1_RFC_DH_DSS_WITH_ARIA_128_GCM_SHA256 "TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256" +# define TLS1_RFC_DH_DSS_WITH_ARIA_256_GCM_SHA384 "TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384" +# define TLS1_RFC_DH_anon_WITH_ARIA_128_GCM_SHA256 "TLS_DH_anon_WITH_ARIA_128_GCM_SHA256" +# define TLS1_RFC_DH_anon_WITH_ARIA_256_GCM_SHA384 "TLS_DH_anon_WITH_ARIA_256_GCM_SHA384" +# define TLS1_RFC_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 "TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256" +# define TLS1_RFC_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 "TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384" +# define TLS1_RFC_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 "TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256" +# define TLS1_RFC_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 "TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384" +# define TLS1_RFC_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 "TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256" +# define TLS1_RFC_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 "TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384" +# define TLS1_RFC_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 "TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256" +# define TLS1_RFC_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 "TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384" +# define TLS1_RFC_PSK_WITH_ARIA_128_GCM_SHA256 "TLS_PSK_WITH_ARIA_128_GCM_SHA256" +# define TLS1_RFC_PSK_WITH_ARIA_256_GCM_SHA384 "TLS_PSK_WITH_ARIA_256_GCM_SHA384" +# define TLS1_RFC_DHE_PSK_WITH_ARIA_128_GCM_SHA256 "TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256" +# define TLS1_RFC_DHE_PSK_WITH_ARIA_256_GCM_SHA384 "TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384" +# define TLS1_RFC_RSA_PSK_WITH_ARIA_128_GCM_SHA256 "TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256" +# define TLS1_RFC_RSA_PSK_WITH_ARIA_256_GCM_SHA384 "TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384" + + +/* + * XXX Backward compatibility alert: Older versions of OpenSSL gave some DHE + * ciphers names with "EDH" instead of "DHE". Going forward, we should be + * using DHE everywhere, though we may indefinitely maintain aliases for + * users or configurations that used "EDH" + */ +# define TLS1_TXT_DHE_DSS_WITH_RC4_128_SHA "DHE-DSS-RC4-SHA" + +# define TLS1_TXT_PSK_WITH_NULL_SHA "PSK-NULL-SHA" +# define TLS1_TXT_DHE_PSK_WITH_NULL_SHA "DHE-PSK-NULL-SHA" +# define TLS1_TXT_RSA_PSK_WITH_NULL_SHA "RSA-PSK-NULL-SHA" + +/* AES ciphersuites from RFC3268 */ +# define TLS1_TXT_RSA_WITH_AES_128_SHA "AES128-SHA" +# define TLS1_TXT_DH_DSS_WITH_AES_128_SHA "DH-DSS-AES128-SHA" +# define TLS1_TXT_DH_RSA_WITH_AES_128_SHA "DH-RSA-AES128-SHA" +# define TLS1_TXT_DHE_DSS_WITH_AES_128_SHA "DHE-DSS-AES128-SHA" +# define TLS1_TXT_DHE_RSA_WITH_AES_128_SHA "DHE-RSA-AES128-SHA" +# define TLS1_TXT_ADH_WITH_AES_128_SHA "ADH-AES128-SHA" + +# define TLS1_TXT_RSA_WITH_AES_256_SHA "AES256-SHA" +# define TLS1_TXT_DH_DSS_WITH_AES_256_SHA "DH-DSS-AES256-SHA" +# define TLS1_TXT_DH_RSA_WITH_AES_256_SHA "DH-RSA-AES256-SHA" +# define TLS1_TXT_DHE_DSS_WITH_AES_256_SHA "DHE-DSS-AES256-SHA" +# define TLS1_TXT_DHE_RSA_WITH_AES_256_SHA "DHE-RSA-AES256-SHA" +# define TLS1_TXT_ADH_WITH_AES_256_SHA "ADH-AES256-SHA" + +/* ECC ciphersuites from RFC4492 */ +# define TLS1_TXT_ECDH_ECDSA_WITH_NULL_SHA "ECDH-ECDSA-NULL-SHA" +# define TLS1_TXT_ECDH_ECDSA_WITH_RC4_128_SHA "ECDH-ECDSA-RC4-SHA" +# define TLS1_TXT_ECDH_ECDSA_WITH_DES_192_CBC3_SHA "ECDH-ECDSA-DES-CBC3-SHA" +# define TLS1_TXT_ECDH_ECDSA_WITH_AES_128_CBC_SHA "ECDH-ECDSA-AES128-SHA" +# define TLS1_TXT_ECDH_ECDSA_WITH_AES_256_CBC_SHA "ECDH-ECDSA-AES256-SHA" + +# define TLS1_TXT_ECDHE_ECDSA_WITH_NULL_SHA "ECDHE-ECDSA-NULL-SHA" +# define TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA "ECDHE-ECDSA-RC4-SHA" +# define TLS1_TXT_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA "ECDHE-ECDSA-DES-CBC3-SHA" +# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA "ECDHE-ECDSA-AES128-SHA" +# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA "ECDHE-ECDSA-AES256-SHA" + +# define TLS1_TXT_ECDH_RSA_WITH_NULL_SHA "ECDH-RSA-NULL-SHA" +# define TLS1_TXT_ECDH_RSA_WITH_RC4_128_SHA "ECDH-RSA-RC4-SHA" +# define TLS1_TXT_ECDH_RSA_WITH_DES_192_CBC3_SHA "ECDH-RSA-DES-CBC3-SHA" +# define TLS1_TXT_ECDH_RSA_WITH_AES_128_CBC_SHA "ECDH-RSA-AES128-SHA" +# define TLS1_TXT_ECDH_RSA_WITH_AES_256_CBC_SHA "ECDH-RSA-AES256-SHA" + +# define TLS1_TXT_ECDHE_RSA_WITH_NULL_SHA "ECDHE-RSA-NULL-SHA" +# define TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA "ECDHE-RSA-RC4-SHA" +# define TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA "ECDHE-RSA-DES-CBC3-SHA" +# define TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA "ECDHE-RSA-AES128-SHA" +# define TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA "ECDHE-RSA-AES256-SHA" + +# define TLS1_TXT_ECDH_anon_WITH_NULL_SHA "AECDH-NULL-SHA" +# define TLS1_TXT_ECDH_anon_WITH_RC4_128_SHA "AECDH-RC4-SHA" +# define TLS1_TXT_ECDH_anon_WITH_DES_192_CBC3_SHA "AECDH-DES-CBC3-SHA" +# define TLS1_TXT_ECDH_anon_WITH_AES_128_CBC_SHA "AECDH-AES128-SHA" +# define TLS1_TXT_ECDH_anon_WITH_AES_256_CBC_SHA "AECDH-AES256-SHA" + +/* PSK ciphersuites from RFC 4279 */ +# define TLS1_TXT_PSK_WITH_RC4_128_SHA "PSK-RC4-SHA" +# define TLS1_TXT_PSK_WITH_3DES_EDE_CBC_SHA "PSK-3DES-EDE-CBC-SHA" +# define TLS1_TXT_PSK_WITH_AES_128_CBC_SHA "PSK-AES128-CBC-SHA" +# define TLS1_TXT_PSK_WITH_AES_256_CBC_SHA "PSK-AES256-CBC-SHA" + +# define TLS1_TXT_DHE_PSK_WITH_RC4_128_SHA "DHE-PSK-RC4-SHA" +# define TLS1_TXT_DHE_PSK_WITH_3DES_EDE_CBC_SHA "DHE-PSK-3DES-EDE-CBC-SHA" +# define TLS1_TXT_DHE_PSK_WITH_AES_128_CBC_SHA "DHE-PSK-AES128-CBC-SHA" +# define TLS1_TXT_DHE_PSK_WITH_AES_256_CBC_SHA "DHE-PSK-AES256-CBC-SHA" +# define TLS1_TXT_RSA_PSK_WITH_RC4_128_SHA "RSA-PSK-RC4-SHA" +# define TLS1_TXT_RSA_PSK_WITH_3DES_EDE_CBC_SHA "RSA-PSK-3DES-EDE-CBC-SHA" +# define TLS1_TXT_RSA_PSK_WITH_AES_128_CBC_SHA "RSA-PSK-AES128-CBC-SHA" +# define TLS1_TXT_RSA_PSK_WITH_AES_256_CBC_SHA "RSA-PSK-AES256-CBC-SHA" + +/* PSK ciphersuites from RFC 5487 */ +# define TLS1_TXT_PSK_WITH_AES_128_GCM_SHA256 "PSK-AES128-GCM-SHA256" +# define TLS1_TXT_PSK_WITH_AES_256_GCM_SHA384 "PSK-AES256-GCM-SHA384" +# define TLS1_TXT_DHE_PSK_WITH_AES_128_GCM_SHA256 "DHE-PSK-AES128-GCM-SHA256" +# define TLS1_TXT_DHE_PSK_WITH_AES_256_GCM_SHA384 "DHE-PSK-AES256-GCM-SHA384" +# define TLS1_TXT_RSA_PSK_WITH_AES_128_GCM_SHA256 "RSA-PSK-AES128-GCM-SHA256" +# define TLS1_TXT_RSA_PSK_WITH_AES_256_GCM_SHA384 "RSA-PSK-AES256-GCM-SHA384" + +# define TLS1_TXT_PSK_WITH_AES_128_CBC_SHA256 "PSK-AES128-CBC-SHA256" +# define TLS1_TXT_PSK_WITH_AES_256_CBC_SHA384 "PSK-AES256-CBC-SHA384" +# define TLS1_TXT_PSK_WITH_NULL_SHA256 "PSK-NULL-SHA256" +# define TLS1_TXT_PSK_WITH_NULL_SHA384 "PSK-NULL-SHA384" + +# define TLS1_TXT_DHE_PSK_WITH_AES_128_CBC_SHA256 "DHE-PSK-AES128-CBC-SHA256" +# define TLS1_TXT_DHE_PSK_WITH_AES_256_CBC_SHA384 "DHE-PSK-AES256-CBC-SHA384" +# define TLS1_TXT_DHE_PSK_WITH_NULL_SHA256 "DHE-PSK-NULL-SHA256" +# define TLS1_TXT_DHE_PSK_WITH_NULL_SHA384 "DHE-PSK-NULL-SHA384" + +# define TLS1_TXT_RSA_PSK_WITH_AES_128_CBC_SHA256 "RSA-PSK-AES128-CBC-SHA256" +# define TLS1_TXT_RSA_PSK_WITH_AES_256_CBC_SHA384 "RSA-PSK-AES256-CBC-SHA384" +# define TLS1_TXT_RSA_PSK_WITH_NULL_SHA256 "RSA-PSK-NULL-SHA256" +# define TLS1_TXT_RSA_PSK_WITH_NULL_SHA384 "RSA-PSK-NULL-SHA384" + +/* SRP ciphersuite from RFC 5054 */ +# define TLS1_TXT_SRP_SHA_WITH_3DES_EDE_CBC_SHA "SRP-3DES-EDE-CBC-SHA" +# define TLS1_TXT_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA "SRP-RSA-3DES-EDE-CBC-SHA" +# define TLS1_TXT_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA "SRP-DSS-3DES-EDE-CBC-SHA" +# define TLS1_TXT_SRP_SHA_WITH_AES_128_CBC_SHA "SRP-AES-128-CBC-SHA" +# define TLS1_TXT_SRP_SHA_RSA_WITH_AES_128_CBC_SHA "SRP-RSA-AES-128-CBC-SHA" +# define TLS1_TXT_SRP_SHA_DSS_WITH_AES_128_CBC_SHA "SRP-DSS-AES-128-CBC-SHA" +# define TLS1_TXT_SRP_SHA_WITH_AES_256_CBC_SHA "SRP-AES-256-CBC-SHA" +# define TLS1_TXT_SRP_SHA_RSA_WITH_AES_256_CBC_SHA "SRP-RSA-AES-256-CBC-SHA" +# define TLS1_TXT_SRP_SHA_DSS_WITH_AES_256_CBC_SHA "SRP-DSS-AES-256-CBC-SHA" + +/* Camellia ciphersuites from RFC4132 */ +# define TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA "CAMELLIA128-SHA" +# define TLS1_TXT_DH_DSS_WITH_CAMELLIA_128_CBC_SHA "DH-DSS-CAMELLIA128-SHA" +# define TLS1_TXT_DH_RSA_WITH_CAMELLIA_128_CBC_SHA "DH-RSA-CAMELLIA128-SHA" +# define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA "DHE-DSS-CAMELLIA128-SHA" +# define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA "DHE-RSA-CAMELLIA128-SHA" +# define TLS1_TXT_ADH_WITH_CAMELLIA_128_CBC_SHA "ADH-CAMELLIA128-SHA" + +# define TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA "CAMELLIA256-SHA" +# define TLS1_TXT_DH_DSS_WITH_CAMELLIA_256_CBC_SHA "DH-DSS-CAMELLIA256-SHA" +# define TLS1_TXT_DH_RSA_WITH_CAMELLIA_256_CBC_SHA "DH-RSA-CAMELLIA256-SHA" +# define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA "DHE-DSS-CAMELLIA256-SHA" +# define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA "DHE-RSA-CAMELLIA256-SHA" +# define TLS1_TXT_ADH_WITH_CAMELLIA_256_CBC_SHA "ADH-CAMELLIA256-SHA" + +/* TLS 1.2 Camellia SHA-256 ciphersuites from RFC5932 */ +# define TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA256 "CAMELLIA128-SHA256" +# define TLS1_TXT_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 "DH-DSS-CAMELLIA128-SHA256" +# define TLS1_TXT_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 "DH-RSA-CAMELLIA128-SHA256" +# define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 "DHE-DSS-CAMELLIA128-SHA256" +# define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 "DHE-RSA-CAMELLIA128-SHA256" +# define TLS1_TXT_ADH_WITH_CAMELLIA_128_CBC_SHA256 "ADH-CAMELLIA128-SHA256" + +# define TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA256 "CAMELLIA256-SHA256" +# define TLS1_TXT_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 "DH-DSS-CAMELLIA256-SHA256" +# define TLS1_TXT_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 "DH-RSA-CAMELLIA256-SHA256" +# define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 "DHE-DSS-CAMELLIA256-SHA256" +# define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 "DHE-RSA-CAMELLIA256-SHA256" +# define TLS1_TXT_ADH_WITH_CAMELLIA_256_CBC_SHA256 "ADH-CAMELLIA256-SHA256" + +# define TLS1_TXT_PSK_WITH_CAMELLIA_128_CBC_SHA256 "PSK-CAMELLIA128-SHA256" +# define TLS1_TXT_PSK_WITH_CAMELLIA_256_CBC_SHA384 "PSK-CAMELLIA256-SHA384" +# define TLS1_TXT_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 "DHE-PSK-CAMELLIA128-SHA256" +# define TLS1_TXT_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 "DHE-PSK-CAMELLIA256-SHA384" +# define TLS1_TXT_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 "RSA-PSK-CAMELLIA128-SHA256" +# define TLS1_TXT_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 "RSA-PSK-CAMELLIA256-SHA384" +# define TLS1_TXT_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 "ECDHE-PSK-CAMELLIA128-SHA256" +# define TLS1_TXT_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 "ECDHE-PSK-CAMELLIA256-SHA384" + +/* SEED ciphersuites from RFC4162 */ +# define TLS1_TXT_RSA_WITH_SEED_SHA "SEED-SHA" +# define TLS1_TXT_DH_DSS_WITH_SEED_SHA "DH-DSS-SEED-SHA" +# define TLS1_TXT_DH_RSA_WITH_SEED_SHA "DH-RSA-SEED-SHA" +# define TLS1_TXT_DHE_DSS_WITH_SEED_SHA "DHE-DSS-SEED-SHA" +# define TLS1_TXT_DHE_RSA_WITH_SEED_SHA "DHE-RSA-SEED-SHA" +# define TLS1_TXT_ADH_WITH_SEED_SHA "ADH-SEED-SHA" + +/* TLS v1.2 ciphersuites */ +# define TLS1_TXT_RSA_WITH_NULL_SHA256 "NULL-SHA256" +# define TLS1_TXT_RSA_WITH_AES_128_SHA256 "AES128-SHA256" +# define TLS1_TXT_RSA_WITH_AES_256_SHA256 "AES256-SHA256" +# define TLS1_TXT_DH_DSS_WITH_AES_128_SHA256 "DH-DSS-AES128-SHA256" +# define TLS1_TXT_DH_RSA_WITH_AES_128_SHA256 "DH-RSA-AES128-SHA256" +# define TLS1_TXT_DHE_DSS_WITH_AES_128_SHA256 "DHE-DSS-AES128-SHA256" +# define TLS1_TXT_DHE_RSA_WITH_AES_128_SHA256 "DHE-RSA-AES128-SHA256" +# define TLS1_TXT_DH_DSS_WITH_AES_256_SHA256 "DH-DSS-AES256-SHA256" +# define TLS1_TXT_DH_RSA_WITH_AES_256_SHA256 "DH-RSA-AES256-SHA256" +# define TLS1_TXT_DHE_DSS_WITH_AES_256_SHA256 "DHE-DSS-AES256-SHA256" +# define TLS1_TXT_DHE_RSA_WITH_AES_256_SHA256 "DHE-RSA-AES256-SHA256" +# define TLS1_TXT_ADH_WITH_AES_128_SHA256 "ADH-AES128-SHA256" +# define TLS1_TXT_ADH_WITH_AES_256_SHA256 "ADH-AES256-SHA256" + +/* TLS v1.2 GCM ciphersuites from RFC5288 */ +# define TLS1_TXT_RSA_WITH_AES_128_GCM_SHA256 "AES128-GCM-SHA256" +# define TLS1_TXT_RSA_WITH_AES_256_GCM_SHA384 "AES256-GCM-SHA384" +# define TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256 "DHE-RSA-AES128-GCM-SHA256" +# define TLS1_TXT_DHE_RSA_WITH_AES_256_GCM_SHA384 "DHE-RSA-AES256-GCM-SHA384" +# define TLS1_TXT_DH_RSA_WITH_AES_128_GCM_SHA256 "DH-RSA-AES128-GCM-SHA256" +# define TLS1_TXT_DH_RSA_WITH_AES_256_GCM_SHA384 "DH-RSA-AES256-GCM-SHA384" +# define TLS1_TXT_DHE_DSS_WITH_AES_128_GCM_SHA256 "DHE-DSS-AES128-GCM-SHA256" +# define TLS1_TXT_DHE_DSS_WITH_AES_256_GCM_SHA384 "DHE-DSS-AES256-GCM-SHA384" +# define TLS1_TXT_DH_DSS_WITH_AES_128_GCM_SHA256 "DH-DSS-AES128-GCM-SHA256" +# define TLS1_TXT_DH_DSS_WITH_AES_256_GCM_SHA384 "DH-DSS-AES256-GCM-SHA384" +# define TLS1_TXT_ADH_WITH_AES_128_GCM_SHA256 "ADH-AES128-GCM-SHA256" +# define TLS1_TXT_ADH_WITH_AES_256_GCM_SHA384 "ADH-AES256-GCM-SHA384" + +/* CCM ciphersuites from RFC6655 */ +# define TLS1_TXT_RSA_WITH_AES_128_CCM "AES128-CCM" +# define TLS1_TXT_RSA_WITH_AES_256_CCM "AES256-CCM" +# define TLS1_TXT_DHE_RSA_WITH_AES_128_CCM "DHE-RSA-AES128-CCM" +# define TLS1_TXT_DHE_RSA_WITH_AES_256_CCM "DHE-RSA-AES256-CCM" + +# define TLS1_TXT_RSA_WITH_AES_128_CCM_8 "AES128-CCM8" +# define TLS1_TXT_RSA_WITH_AES_256_CCM_8 "AES256-CCM8" +# define TLS1_TXT_DHE_RSA_WITH_AES_128_CCM_8 "DHE-RSA-AES128-CCM8" +# define TLS1_TXT_DHE_RSA_WITH_AES_256_CCM_8 "DHE-RSA-AES256-CCM8" + +# define TLS1_TXT_PSK_WITH_AES_128_CCM "PSK-AES128-CCM" +# define TLS1_TXT_PSK_WITH_AES_256_CCM "PSK-AES256-CCM" +# define TLS1_TXT_DHE_PSK_WITH_AES_128_CCM "DHE-PSK-AES128-CCM" +# define TLS1_TXT_DHE_PSK_WITH_AES_256_CCM "DHE-PSK-AES256-CCM" + +# define TLS1_TXT_PSK_WITH_AES_128_CCM_8 "PSK-AES128-CCM8" +# define TLS1_TXT_PSK_WITH_AES_256_CCM_8 "PSK-AES256-CCM8" +# define TLS1_TXT_DHE_PSK_WITH_AES_128_CCM_8 "DHE-PSK-AES128-CCM8" +# define TLS1_TXT_DHE_PSK_WITH_AES_256_CCM_8 "DHE-PSK-AES256-CCM8" + +/* CCM ciphersuites from RFC7251 */ +# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CCM "ECDHE-ECDSA-AES128-CCM" +# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CCM "ECDHE-ECDSA-AES256-CCM" +# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CCM_8 "ECDHE-ECDSA-AES128-CCM8" +# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CCM_8 "ECDHE-ECDSA-AES256-CCM8" + +/* ECDH HMAC based ciphersuites from RFC5289 */ +# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_SHA256 "ECDHE-ECDSA-AES128-SHA256" +# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_SHA384 "ECDHE-ECDSA-AES256-SHA384" +# define TLS1_TXT_ECDH_ECDSA_WITH_AES_128_SHA256 "ECDH-ECDSA-AES128-SHA256" +# define TLS1_TXT_ECDH_ECDSA_WITH_AES_256_SHA384 "ECDH-ECDSA-AES256-SHA384" +# define TLS1_TXT_ECDHE_RSA_WITH_AES_128_SHA256 "ECDHE-RSA-AES128-SHA256" +# define TLS1_TXT_ECDHE_RSA_WITH_AES_256_SHA384 "ECDHE-RSA-AES256-SHA384" +# define TLS1_TXT_ECDH_RSA_WITH_AES_128_SHA256 "ECDH-RSA-AES128-SHA256" +# define TLS1_TXT_ECDH_RSA_WITH_AES_256_SHA384 "ECDH-RSA-AES256-SHA384" + +/* ECDH GCM based ciphersuites from RFC5289 */ +# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 "ECDHE-ECDSA-AES128-GCM-SHA256" +# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 "ECDHE-ECDSA-AES256-GCM-SHA384" +# define TLS1_TXT_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 "ECDH-ECDSA-AES128-GCM-SHA256" +# define TLS1_TXT_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 "ECDH-ECDSA-AES256-GCM-SHA384" +# define TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256 "ECDHE-RSA-AES128-GCM-SHA256" +# define TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384 "ECDHE-RSA-AES256-GCM-SHA384" +# define TLS1_TXT_ECDH_RSA_WITH_AES_128_GCM_SHA256 "ECDH-RSA-AES128-GCM-SHA256" +# define TLS1_TXT_ECDH_RSA_WITH_AES_256_GCM_SHA384 "ECDH-RSA-AES256-GCM-SHA384" + +/* TLS v1.2 PSK GCM ciphersuites from RFC5487 */ +# define TLS1_TXT_PSK_WITH_AES_128_GCM_SHA256 "PSK-AES128-GCM-SHA256" +# define TLS1_TXT_PSK_WITH_AES_256_GCM_SHA384 "PSK-AES256-GCM-SHA384" + +/* ECDHE PSK ciphersuites from RFC 5489 */ +# define TLS1_TXT_ECDHE_PSK_WITH_RC4_128_SHA "ECDHE-PSK-RC4-SHA" +# define TLS1_TXT_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA "ECDHE-PSK-3DES-EDE-CBC-SHA" +# define TLS1_TXT_ECDHE_PSK_WITH_AES_128_CBC_SHA "ECDHE-PSK-AES128-CBC-SHA" +# define TLS1_TXT_ECDHE_PSK_WITH_AES_256_CBC_SHA "ECDHE-PSK-AES256-CBC-SHA" + +# define TLS1_TXT_ECDHE_PSK_WITH_AES_128_CBC_SHA256 "ECDHE-PSK-AES128-CBC-SHA256" +# define TLS1_TXT_ECDHE_PSK_WITH_AES_256_CBC_SHA384 "ECDHE-PSK-AES256-CBC-SHA384" + +# define TLS1_TXT_ECDHE_PSK_WITH_NULL_SHA "ECDHE-PSK-NULL-SHA" +# define TLS1_TXT_ECDHE_PSK_WITH_NULL_SHA256 "ECDHE-PSK-NULL-SHA256" +# define TLS1_TXT_ECDHE_PSK_WITH_NULL_SHA384 "ECDHE-PSK-NULL-SHA384" + +/* Camellia-CBC ciphersuites from RFC6367 */ +# define TLS1_TXT_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 "ECDHE-ECDSA-CAMELLIA128-SHA256" +# define TLS1_TXT_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 "ECDHE-ECDSA-CAMELLIA256-SHA384" +# define TLS1_TXT_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 "ECDH-ECDSA-CAMELLIA128-SHA256" +# define TLS1_TXT_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 "ECDH-ECDSA-CAMELLIA256-SHA384" +# define TLS1_TXT_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 "ECDHE-RSA-CAMELLIA128-SHA256" +# define TLS1_TXT_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 "ECDHE-RSA-CAMELLIA256-SHA384" +# define TLS1_TXT_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 "ECDH-RSA-CAMELLIA128-SHA256" +# define TLS1_TXT_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 "ECDH-RSA-CAMELLIA256-SHA384" + +/* draft-ietf-tls-chacha20-poly1305-03 */ +# define TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305 "ECDHE-RSA-CHACHA20-POLY1305" +# define TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 "ECDHE-ECDSA-CHACHA20-POLY1305" +# define TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305 "DHE-RSA-CHACHA20-POLY1305" +# define TLS1_TXT_PSK_WITH_CHACHA20_POLY1305 "PSK-CHACHA20-POLY1305" +# define TLS1_TXT_ECDHE_PSK_WITH_CHACHA20_POLY1305 "ECDHE-PSK-CHACHA20-POLY1305" +# define TLS1_TXT_DHE_PSK_WITH_CHACHA20_POLY1305 "DHE-PSK-CHACHA20-POLY1305" +# define TLS1_TXT_RSA_PSK_WITH_CHACHA20_POLY1305 "RSA-PSK-CHACHA20-POLY1305" + +/* Aria ciphersuites from RFC6209 */ +# define TLS1_TXT_RSA_WITH_ARIA_128_GCM_SHA256 "ARIA128-GCM-SHA256" +# define TLS1_TXT_RSA_WITH_ARIA_256_GCM_SHA384 "ARIA256-GCM-SHA384" +# define TLS1_TXT_DHE_RSA_WITH_ARIA_128_GCM_SHA256 "DHE-RSA-ARIA128-GCM-SHA256" +# define TLS1_TXT_DHE_RSA_WITH_ARIA_256_GCM_SHA384 "DHE-RSA-ARIA256-GCM-SHA384" +# define TLS1_TXT_DH_RSA_WITH_ARIA_128_GCM_SHA256 "DH-RSA-ARIA128-GCM-SHA256" +# define TLS1_TXT_DH_RSA_WITH_ARIA_256_GCM_SHA384 "DH-RSA-ARIA256-GCM-SHA384" +# define TLS1_TXT_DHE_DSS_WITH_ARIA_128_GCM_SHA256 "DHE-DSS-ARIA128-GCM-SHA256" +# define TLS1_TXT_DHE_DSS_WITH_ARIA_256_GCM_SHA384 "DHE-DSS-ARIA256-GCM-SHA384" +# define TLS1_TXT_DH_DSS_WITH_ARIA_128_GCM_SHA256 "DH-DSS-ARIA128-GCM-SHA256" +# define TLS1_TXT_DH_DSS_WITH_ARIA_256_GCM_SHA384 "DH-DSS-ARIA256-GCM-SHA384" +# define TLS1_TXT_DH_anon_WITH_ARIA_128_GCM_SHA256 "ADH-ARIA128-GCM-SHA256" +# define TLS1_TXT_DH_anon_WITH_ARIA_256_GCM_SHA384 "ADH-ARIA256-GCM-SHA384" +# define TLS1_TXT_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 "ECDHE-ECDSA-ARIA128-GCM-SHA256" +# define TLS1_TXT_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 "ECDHE-ECDSA-ARIA256-GCM-SHA384" +# define TLS1_TXT_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 "ECDH-ECDSA-ARIA128-GCM-SHA256" +# define TLS1_TXT_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 "ECDH-ECDSA-ARIA256-GCM-SHA384" +# define TLS1_TXT_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 "ECDHE-ARIA128-GCM-SHA256" +# define TLS1_TXT_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 "ECDHE-ARIA256-GCM-SHA384" +# define TLS1_TXT_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 "ECDH-ARIA128-GCM-SHA256" +# define TLS1_TXT_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 "ECDH-ARIA256-GCM-SHA384" +# define TLS1_TXT_PSK_WITH_ARIA_128_GCM_SHA256 "PSK-ARIA128-GCM-SHA256" +# define TLS1_TXT_PSK_WITH_ARIA_256_GCM_SHA384 "PSK-ARIA256-GCM-SHA384" +# define TLS1_TXT_DHE_PSK_WITH_ARIA_128_GCM_SHA256 "DHE-PSK-ARIA128-GCM-SHA256" +# define TLS1_TXT_DHE_PSK_WITH_ARIA_256_GCM_SHA384 "DHE-PSK-ARIA256-GCM-SHA384" +# define TLS1_TXT_RSA_PSK_WITH_ARIA_128_GCM_SHA256 "RSA-PSK-ARIA128-GCM-SHA256" +# define TLS1_TXT_RSA_PSK_WITH_ARIA_256_GCM_SHA384 "RSA-PSK-ARIA256-GCM-SHA384" + +# define TLS_CT_RSA_SIGN 1 +# define TLS_CT_DSS_SIGN 2 +# define TLS_CT_RSA_FIXED_DH 3 +# define TLS_CT_DSS_FIXED_DH 4 +# define TLS_CT_ECDSA_SIGN 64 +# define TLS_CT_RSA_FIXED_ECDH 65 +# define TLS_CT_ECDSA_FIXED_ECDH 66 +# define TLS_CT_GOST01_SIGN 22 +# define TLS_CT_GOST12_SIGN 238 +# define TLS_CT_GOST12_512_SIGN 239 + +/* + * when correcting this number, correct also SSL3_CT_NUMBER in ssl3.h (see + * comment there) + */ +# define TLS_CT_NUMBER 10 + +# if defined(SSL3_CT_NUMBER) +# if TLS_CT_NUMBER != SSL3_CT_NUMBER +# error "SSL/TLS CT_NUMBER values do not match" +# endif +# endif + +# define TLS1_FINISH_MAC_LENGTH 12 + +# define TLS_MD_MAX_CONST_SIZE 22 +# define TLS_MD_CLIENT_FINISH_CONST "client finished" +# define TLS_MD_CLIENT_FINISH_CONST_SIZE 15 +# define TLS_MD_SERVER_FINISH_CONST "server finished" +# define TLS_MD_SERVER_FINISH_CONST_SIZE 15 +# define TLS_MD_KEY_EXPANSION_CONST "key expansion" +# define TLS_MD_KEY_EXPANSION_CONST_SIZE 13 +# define TLS_MD_CLIENT_WRITE_KEY_CONST "client write key" +# define TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE 16 +# define TLS_MD_SERVER_WRITE_KEY_CONST "server write key" +# define TLS_MD_SERVER_WRITE_KEY_CONST_SIZE 16 +# define TLS_MD_IV_BLOCK_CONST "IV block" +# define TLS_MD_IV_BLOCK_CONST_SIZE 8 +# define TLS_MD_MASTER_SECRET_CONST "master secret" +# define TLS_MD_MASTER_SECRET_CONST_SIZE 13 +# define TLS_MD_EXTENDED_MASTER_SECRET_CONST "extended master secret" +# define TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE 22 + +# ifdef CHARSET_EBCDIC +# undef TLS_MD_CLIENT_FINISH_CONST +/* + * client finished + */ +# define TLS_MD_CLIENT_FINISH_CONST "\x63\x6c\x69\x65\x6e\x74\x20\x66\x69\x6e\x69\x73\x68\x65\x64" + +# undef TLS_MD_SERVER_FINISH_CONST +/* + * server finished + */ +# define TLS_MD_SERVER_FINISH_CONST "\x73\x65\x72\x76\x65\x72\x20\x66\x69\x6e\x69\x73\x68\x65\x64" + +# undef TLS_MD_SERVER_WRITE_KEY_CONST +/* + * server write key + */ +# define TLS_MD_SERVER_WRITE_KEY_CONST "\x73\x65\x72\x76\x65\x72\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79" + +# undef TLS_MD_KEY_EXPANSION_CONST +/* + * key expansion + */ +# define TLS_MD_KEY_EXPANSION_CONST "\x6b\x65\x79\x20\x65\x78\x70\x61\x6e\x73\x69\x6f\x6e" + +# undef TLS_MD_CLIENT_WRITE_KEY_CONST +/* + * client write key + */ +# define TLS_MD_CLIENT_WRITE_KEY_CONST "\x63\x6c\x69\x65\x6e\x74\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79" + +# undef TLS_MD_SERVER_WRITE_KEY_CONST +/* + * server write key + */ +# define TLS_MD_SERVER_WRITE_KEY_CONST "\x73\x65\x72\x76\x65\x72\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79" + +# undef TLS_MD_IV_BLOCK_CONST +/* + * IV block + */ +# define TLS_MD_IV_BLOCK_CONST "\x49\x56\x20\x62\x6c\x6f\x63\x6b" + +# undef TLS_MD_MASTER_SECRET_CONST +/* + * master secret + */ +# define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" +# undef TLS_MD_EXTENDED_MASTER_SECRET_CONST +/* + * extended master secret + */ +# define TLS_MD_EXTENDED_MASTER_SECRET_CONST "\x65\x78\x74\x65\x63\x64\x65\x64\x20\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" +# endif + +/* TLS Session Ticket extension struct */ +struct tls_session_ticket_ext_st { + unsigned short length; + void *data; +}; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/ts.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ts.h new file mode 100644 index 000000000..3b58aa527 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ts.h @@ -0,0 +1,559 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_TS_H +# define HEADER_TS_H + +# include + +# ifndef OPENSSL_NO_TS +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# ifdef __cplusplus +extern "C" { +# endif + +# include +# include + +typedef struct TS_msg_imprint_st TS_MSG_IMPRINT; +typedef struct TS_req_st TS_REQ; +typedef struct TS_accuracy_st TS_ACCURACY; +typedef struct TS_tst_info_st TS_TST_INFO; + +/* Possible values for status. */ +# define TS_STATUS_GRANTED 0 +# define TS_STATUS_GRANTED_WITH_MODS 1 +# define TS_STATUS_REJECTION 2 +# define TS_STATUS_WAITING 3 +# define TS_STATUS_REVOCATION_WARNING 4 +# define TS_STATUS_REVOCATION_NOTIFICATION 5 + +/* Possible values for failure_info. */ +# define TS_INFO_BAD_ALG 0 +# define TS_INFO_BAD_REQUEST 2 +# define TS_INFO_BAD_DATA_FORMAT 5 +# define TS_INFO_TIME_NOT_AVAILABLE 14 +# define TS_INFO_UNACCEPTED_POLICY 15 +# define TS_INFO_UNACCEPTED_EXTENSION 16 +# define TS_INFO_ADD_INFO_NOT_AVAILABLE 17 +# define TS_INFO_SYSTEM_FAILURE 25 + + +typedef struct TS_status_info_st TS_STATUS_INFO; +typedef struct ESS_issuer_serial ESS_ISSUER_SERIAL; +typedef struct ESS_cert_id ESS_CERT_ID; +typedef struct ESS_signing_cert ESS_SIGNING_CERT; + +DEFINE_STACK_OF(ESS_CERT_ID) + +typedef struct ESS_cert_id_v2_st ESS_CERT_ID_V2; +typedef struct ESS_signing_cert_v2_st ESS_SIGNING_CERT_V2; + +DEFINE_STACK_OF(ESS_CERT_ID_V2) + +typedef struct TS_resp_st TS_RESP; + +TS_REQ *TS_REQ_new(void); +void TS_REQ_free(TS_REQ *a); +int i2d_TS_REQ(const TS_REQ *a, unsigned char **pp); +TS_REQ *d2i_TS_REQ(TS_REQ **a, const unsigned char **pp, long length); + +TS_REQ *TS_REQ_dup(TS_REQ *a); + +#ifndef OPENSSL_NO_STDIO +TS_REQ *d2i_TS_REQ_fp(FILE *fp, TS_REQ **a); +int i2d_TS_REQ_fp(FILE *fp, TS_REQ *a); +#endif +TS_REQ *d2i_TS_REQ_bio(BIO *fp, TS_REQ **a); +int i2d_TS_REQ_bio(BIO *fp, TS_REQ *a); + +TS_MSG_IMPRINT *TS_MSG_IMPRINT_new(void); +void TS_MSG_IMPRINT_free(TS_MSG_IMPRINT *a); +int i2d_TS_MSG_IMPRINT(const TS_MSG_IMPRINT *a, unsigned char **pp); +TS_MSG_IMPRINT *d2i_TS_MSG_IMPRINT(TS_MSG_IMPRINT **a, + const unsigned char **pp, long length); + +TS_MSG_IMPRINT *TS_MSG_IMPRINT_dup(TS_MSG_IMPRINT *a); + +#ifndef OPENSSL_NO_STDIO +TS_MSG_IMPRINT *d2i_TS_MSG_IMPRINT_fp(FILE *fp, TS_MSG_IMPRINT **a); +int i2d_TS_MSG_IMPRINT_fp(FILE *fp, TS_MSG_IMPRINT *a); +#endif +TS_MSG_IMPRINT *d2i_TS_MSG_IMPRINT_bio(BIO *bio, TS_MSG_IMPRINT **a); +int i2d_TS_MSG_IMPRINT_bio(BIO *bio, TS_MSG_IMPRINT *a); + +TS_RESP *TS_RESP_new(void); +void TS_RESP_free(TS_RESP *a); +int i2d_TS_RESP(const TS_RESP *a, unsigned char **pp); +TS_RESP *d2i_TS_RESP(TS_RESP **a, const unsigned char **pp, long length); +TS_TST_INFO *PKCS7_to_TS_TST_INFO(PKCS7 *token); +TS_RESP *TS_RESP_dup(TS_RESP *a); + +#ifndef OPENSSL_NO_STDIO +TS_RESP *d2i_TS_RESP_fp(FILE *fp, TS_RESP **a); +int i2d_TS_RESP_fp(FILE *fp, TS_RESP *a); +#endif +TS_RESP *d2i_TS_RESP_bio(BIO *bio, TS_RESP **a); +int i2d_TS_RESP_bio(BIO *bio, TS_RESP *a); + +TS_STATUS_INFO *TS_STATUS_INFO_new(void); +void TS_STATUS_INFO_free(TS_STATUS_INFO *a); +int i2d_TS_STATUS_INFO(const TS_STATUS_INFO *a, unsigned char **pp); +TS_STATUS_INFO *d2i_TS_STATUS_INFO(TS_STATUS_INFO **a, + const unsigned char **pp, long length); +TS_STATUS_INFO *TS_STATUS_INFO_dup(TS_STATUS_INFO *a); + +TS_TST_INFO *TS_TST_INFO_new(void); +void TS_TST_INFO_free(TS_TST_INFO *a); +int i2d_TS_TST_INFO(const TS_TST_INFO *a, unsigned char **pp); +TS_TST_INFO *d2i_TS_TST_INFO(TS_TST_INFO **a, const unsigned char **pp, + long length); +TS_TST_INFO *TS_TST_INFO_dup(TS_TST_INFO *a); + +#ifndef OPENSSL_NO_STDIO +TS_TST_INFO *d2i_TS_TST_INFO_fp(FILE *fp, TS_TST_INFO **a); +int i2d_TS_TST_INFO_fp(FILE *fp, TS_TST_INFO *a); +#endif +TS_TST_INFO *d2i_TS_TST_INFO_bio(BIO *bio, TS_TST_INFO **a); +int i2d_TS_TST_INFO_bio(BIO *bio, TS_TST_INFO *a); + +TS_ACCURACY *TS_ACCURACY_new(void); +void TS_ACCURACY_free(TS_ACCURACY *a); +int i2d_TS_ACCURACY(const TS_ACCURACY *a, unsigned char **pp); +TS_ACCURACY *d2i_TS_ACCURACY(TS_ACCURACY **a, const unsigned char **pp, + long length); +TS_ACCURACY *TS_ACCURACY_dup(TS_ACCURACY *a); + +ESS_ISSUER_SERIAL *ESS_ISSUER_SERIAL_new(void); +void ESS_ISSUER_SERIAL_free(ESS_ISSUER_SERIAL *a); +int i2d_ESS_ISSUER_SERIAL(const ESS_ISSUER_SERIAL *a, unsigned char **pp); +ESS_ISSUER_SERIAL *d2i_ESS_ISSUER_SERIAL(ESS_ISSUER_SERIAL **a, + const unsigned char **pp, + long length); +ESS_ISSUER_SERIAL *ESS_ISSUER_SERIAL_dup(ESS_ISSUER_SERIAL *a); + +ESS_CERT_ID *ESS_CERT_ID_new(void); +void ESS_CERT_ID_free(ESS_CERT_ID *a); +int i2d_ESS_CERT_ID(const ESS_CERT_ID *a, unsigned char **pp); +ESS_CERT_ID *d2i_ESS_CERT_ID(ESS_CERT_ID **a, const unsigned char **pp, + long length); +ESS_CERT_ID *ESS_CERT_ID_dup(ESS_CERT_ID *a); + +ESS_SIGNING_CERT *ESS_SIGNING_CERT_new(void); +void ESS_SIGNING_CERT_free(ESS_SIGNING_CERT *a); +int i2d_ESS_SIGNING_CERT(const ESS_SIGNING_CERT *a, unsigned char **pp); +ESS_SIGNING_CERT *d2i_ESS_SIGNING_CERT(ESS_SIGNING_CERT **a, + const unsigned char **pp, long length); +ESS_SIGNING_CERT *ESS_SIGNING_CERT_dup(ESS_SIGNING_CERT *a); + +ESS_CERT_ID_V2 *ESS_CERT_ID_V2_new(void); +void ESS_CERT_ID_V2_free(ESS_CERT_ID_V2 *a); +int i2d_ESS_CERT_ID_V2(const ESS_CERT_ID_V2 *a, unsigned char **pp); +ESS_CERT_ID_V2 *d2i_ESS_CERT_ID_V2(ESS_CERT_ID_V2 **a, + const unsigned char **pp, long length); +ESS_CERT_ID_V2 *ESS_CERT_ID_V2_dup(ESS_CERT_ID_V2 *a); + +ESS_SIGNING_CERT_V2 *ESS_SIGNING_CERT_V2_new(void); +void ESS_SIGNING_CERT_V2_free(ESS_SIGNING_CERT_V2 *a); +int i2d_ESS_SIGNING_CERT_V2(const ESS_SIGNING_CERT_V2 *a, unsigned char **pp); +ESS_SIGNING_CERT_V2 *d2i_ESS_SIGNING_CERT_V2(ESS_SIGNING_CERT_V2 **a, + const unsigned char **pp, + long length); +ESS_SIGNING_CERT_V2 *ESS_SIGNING_CERT_V2_dup(ESS_SIGNING_CERT_V2 *a); + +int TS_REQ_set_version(TS_REQ *a, long version); +long TS_REQ_get_version(const TS_REQ *a); + +int TS_STATUS_INFO_set_status(TS_STATUS_INFO *a, int i); +const ASN1_INTEGER *TS_STATUS_INFO_get0_status(const TS_STATUS_INFO *a); + +const STACK_OF(ASN1_UTF8STRING) * +TS_STATUS_INFO_get0_text(const TS_STATUS_INFO *a); + +const ASN1_BIT_STRING * +TS_STATUS_INFO_get0_failure_info(const TS_STATUS_INFO *a); + +int TS_REQ_set_msg_imprint(TS_REQ *a, TS_MSG_IMPRINT *msg_imprint); +TS_MSG_IMPRINT *TS_REQ_get_msg_imprint(TS_REQ *a); + +int TS_MSG_IMPRINT_set_algo(TS_MSG_IMPRINT *a, X509_ALGOR *alg); +X509_ALGOR *TS_MSG_IMPRINT_get_algo(TS_MSG_IMPRINT *a); + +int TS_MSG_IMPRINT_set_msg(TS_MSG_IMPRINT *a, unsigned char *d, int len); +ASN1_OCTET_STRING *TS_MSG_IMPRINT_get_msg(TS_MSG_IMPRINT *a); + +int TS_REQ_set_policy_id(TS_REQ *a, const ASN1_OBJECT *policy); +ASN1_OBJECT *TS_REQ_get_policy_id(TS_REQ *a); + +int TS_REQ_set_nonce(TS_REQ *a, const ASN1_INTEGER *nonce); +const ASN1_INTEGER *TS_REQ_get_nonce(const TS_REQ *a); + +int TS_REQ_set_cert_req(TS_REQ *a, int cert_req); +int TS_REQ_get_cert_req(const TS_REQ *a); + +STACK_OF(X509_EXTENSION) *TS_REQ_get_exts(TS_REQ *a); +void TS_REQ_ext_free(TS_REQ *a); +int TS_REQ_get_ext_count(TS_REQ *a); +int TS_REQ_get_ext_by_NID(TS_REQ *a, int nid, int lastpos); +int TS_REQ_get_ext_by_OBJ(TS_REQ *a, const ASN1_OBJECT *obj, int lastpos); +int TS_REQ_get_ext_by_critical(TS_REQ *a, int crit, int lastpos); +X509_EXTENSION *TS_REQ_get_ext(TS_REQ *a, int loc); +X509_EXTENSION *TS_REQ_delete_ext(TS_REQ *a, int loc); +int TS_REQ_add_ext(TS_REQ *a, X509_EXTENSION *ex, int loc); +void *TS_REQ_get_ext_d2i(TS_REQ *a, int nid, int *crit, int *idx); + +/* Function declarations for TS_REQ defined in ts/ts_req_print.c */ + +int TS_REQ_print_bio(BIO *bio, TS_REQ *a); + +/* Function declarations for TS_RESP defined in ts/ts_resp_utils.c */ + +int TS_RESP_set_status_info(TS_RESP *a, TS_STATUS_INFO *info); +TS_STATUS_INFO *TS_RESP_get_status_info(TS_RESP *a); + +/* Caller loses ownership of PKCS7 and TS_TST_INFO objects. */ +void TS_RESP_set_tst_info(TS_RESP *a, PKCS7 *p7, TS_TST_INFO *tst_info); +PKCS7 *TS_RESP_get_token(TS_RESP *a); +TS_TST_INFO *TS_RESP_get_tst_info(TS_RESP *a); + +int TS_TST_INFO_set_version(TS_TST_INFO *a, long version); +long TS_TST_INFO_get_version(const TS_TST_INFO *a); + +int TS_TST_INFO_set_policy_id(TS_TST_INFO *a, ASN1_OBJECT *policy_id); +ASN1_OBJECT *TS_TST_INFO_get_policy_id(TS_TST_INFO *a); + +int TS_TST_INFO_set_msg_imprint(TS_TST_INFO *a, TS_MSG_IMPRINT *msg_imprint); +TS_MSG_IMPRINT *TS_TST_INFO_get_msg_imprint(TS_TST_INFO *a); + +int TS_TST_INFO_set_serial(TS_TST_INFO *a, const ASN1_INTEGER *serial); +const ASN1_INTEGER *TS_TST_INFO_get_serial(const TS_TST_INFO *a); + +int TS_TST_INFO_set_time(TS_TST_INFO *a, const ASN1_GENERALIZEDTIME *gtime); +const ASN1_GENERALIZEDTIME *TS_TST_INFO_get_time(const TS_TST_INFO *a); + +int TS_TST_INFO_set_accuracy(TS_TST_INFO *a, TS_ACCURACY *accuracy); +TS_ACCURACY *TS_TST_INFO_get_accuracy(TS_TST_INFO *a); + +int TS_ACCURACY_set_seconds(TS_ACCURACY *a, const ASN1_INTEGER *seconds); +const ASN1_INTEGER *TS_ACCURACY_get_seconds(const TS_ACCURACY *a); + +int TS_ACCURACY_set_millis(TS_ACCURACY *a, const ASN1_INTEGER *millis); +const ASN1_INTEGER *TS_ACCURACY_get_millis(const TS_ACCURACY *a); + +int TS_ACCURACY_set_micros(TS_ACCURACY *a, const ASN1_INTEGER *micros); +const ASN1_INTEGER *TS_ACCURACY_get_micros(const TS_ACCURACY *a); + +int TS_TST_INFO_set_ordering(TS_TST_INFO *a, int ordering); +int TS_TST_INFO_get_ordering(const TS_TST_INFO *a); + +int TS_TST_INFO_set_nonce(TS_TST_INFO *a, const ASN1_INTEGER *nonce); +const ASN1_INTEGER *TS_TST_INFO_get_nonce(const TS_TST_INFO *a); + +int TS_TST_INFO_set_tsa(TS_TST_INFO *a, GENERAL_NAME *tsa); +GENERAL_NAME *TS_TST_INFO_get_tsa(TS_TST_INFO *a); + +STACK_OF(X509_EXTENSION) *TS_TST_INFO_get_exts(TS_TST_INFO *a); +void TS_TST_INFO_ext_free(TS_TST_INFO *a); +int TS_TST_INFO_get_ext_count(TS_TST_INFO *a); +int TS_TST_INFO_get_ext_by_NID(TS_TST_INFO *a, int nid, int lastpos); +int TS_TST_INFO_get_ext_by_OBJ(TS_TST_INFO *a, const ASN1_OBJECT *obj, + int lastpos); +int TS_TST_INFO_get_ext_by_critical(TS_TST_INFO *a, int crit, int lastpos); +X509_EXTENSION *TS_TST_INFO_get_ext(TS_TST_INFO *a, int loc); +X509_EXTENSION *TS_TST_INFO_delete_ext(TS_TST_INFO *a, int loc); +int TS_TST_INFO_add_ext(TS_TST_INFO *a, X509_EXTENSION *ex, int loc); +void *TS_TST_INFO_get_ext_d2i(TS_TST_INFO *a, int nid, int *crit, int *idx); + +/* + * Declarations related to response generation, defined in ts/ts_resp_sign.c. + */ + +/* Optional flags for response generation. */ + +/* Don't include the TSA name in response. */ +# define TS_TSA_NAME 0x01 + +/* Set ordering to true in response. */ +# define TS_ORDERING 0x02 + +/* + * Include the signer certificate and the other specified certificates in + * the ESS signing certificate attribute beside the PKCS7 signed data. + * Only the signer certificates is included by default. + */ +# define TS_ESS_CERT_ID_CHAIN 0x04 + +/* Forward declaration. */ +struct TS_resp_ctx; + +/* This must return a unique number less than 160 bits long. */ +typedef ASN1_INTEGER *(*TS_serial_cb) (struct TS_resp_ctx *, void *); + +/* + * This must return the seconds and microseconds since Jan 1, 1970 in the sec + * and usec variables allocated by the caller. Return non-zero for success + * and zero for failure. + */ +typedef int (*TS_time_cb) (struct TS_resp_ctx *, void *, long *sec, + long *usec); + +/* + * This must process the given extension. It can modify the TS_TST_INFO + * object of the context. Return values: !0 (processed), 0 (error, it must + * set the status info/failure info of the response). + */ +typedef int (*TS_extension_cb) (struct TS_resp_ctx *, X509_EXTENSION *, + void *); + +typedef struct TS_resp_ctx TS_RESP_CTX; + +DEFINE_STACK_OF_CONST(EVP_MD) + +/* Creates a response context that can be used for generating responses. */ +TS_RESP_CTX *TS_RESP_CTX_new(void); +void TS_RESP_CTX_free(TS_RESP_CTX *ctx); + +/* This parameter must be set. */ +int TS_RESP_CTX_set_signer_cert(TS_RESP_CTX *ctx, X509 *signer); + +/* This parameter must be set. */ +int TS_RESP_CTX_set_signer_key(TS_RESP_CTX *ctx, EVP_PKEY *key); + +int TS_RESP_CTX_set_signer_digest(TS_RESP_CTX *ctx, + const EVP_MD *signer_digest); +int TS_RESP_CTX_set_ess_cert_id_digest(TS_RESP_CTX *ctx, const EVP_MD *md); + +/* This parameter must be set. */ +int TS_RESP_CTX_set_def_policy(TS_RESP_CTX *ctx, const ASN1_OBJECT *def_policy); + +/* No additional certs are included in the response by default. */ +int TS_RESP_CTX_set_certs(TS_RESP_CTX *ctx, STACK_OF(X509) *certs); + +/* + * Adds a new acceptable policy, only the default policy is accepted by + * default. + */ +int TS_RESP_CTX_add_policy(TS_RESP_CTX *ctx, const ASN1_OBJECT *policy); + +/* + * Adds a new acceptable message digest. Note that no message digests are + * accepted by default. The md argument is shared with the caller. + */ +int TS_RESP_CTX_add_md(TS_RESP_CTX *ctx, const EVP_MD *md); + +/* Accuracy is not included by default. */ +int TS_RESP_CTX_set_accuracy(TS_RESP_CTX *ctx, + int secs, int millis, int micros); + +/* + * Clock precision digits, i.e. the number of decimal digits: '0' means sec, + * '3' msec, '6' usec, and so on. Default is 0. + */ +int TS_RESP_CTX_set_clock_precision_digits(TS_RESP_CTX *ctx, + unsigned clock_precision_digits); +/* At most we accept usec precision. */ +# define TS_MAX_CLOCK_PRECISION_DIGITS 6 + +/* Maximum status message length */ +# define TS_MAX_STATUS_LENGTH (1024 * 1024) + +/* No flags are set by default. */ +void TS_RESP_CTX_add_flags(TS_RESP_CTX *ctx, int flags); + +/* Default callback always returns a constant. */ +void TS_RESP_CTX_set_serial_cb(TS_RESP_CTX *ctx, TS_serial_cb cb, void *data); + +/* Default callback uses the gettimeofday() and gmtime() system calls. */ +void TS_RESP_CTX_set_time_cb(TS_RESP_CTX *ctx, TS_time_cb cb, void *data); + +/* + * Default callback rejects all extensions. The extension callback is called + * when the TS_TST_INFO object is already set up and not signed yet. + */ +/* FIXME: extension handling is not tested yet. */ +void TS_RESP_CTX_set_extension_cb(TS_RESP_CTX *ctx, + TS_extension_cb cb, void *data); + +/* The following methods can be used in the callbacks. */ +int TS_RESP_CTX_set_status_info(TS_RESP_CTX *ctx, + int status, const char *text); + +/* Sets the status info only if it is still TS_STATUS_GRANTED. */ +int TS_RESP_CTX_set_status_info_cond(TS_RESP_CTX *ctx, + int status, const char *text); + +int TS_RESP_CTX_add_failure_info(TS_RESP_CTX *ctx, int failure); + +/* The get methods below can be used in the extension callback. */ +TS_REQ *TS_RESP_CTX_get_request(TS_RESP_CTX *ctx); + +TS_TST_INFO *TS_RESP_CTX_get_tst_info(TS_RESP_CTX *ctx); + +/* + * Creates the signed TS_TST_INFO and puts it in TS_RESP. + * In case of errors it sets the status info properly. + * Returns NULL only in case of memory allocation/fatal error. + */ +TS_RESP *TS_RESP_create_response(TS_RESP_CTX *ctx, BIO *req_bio); + +/* + * Declarations related to response verification, + * they are defined in ts/ts_resp_verify.c. + */ + +int TS_RESP_verify_signature(PKCS7 *token, STACK_OF(X509) *certs, + X509_STORE *store, X509 **signer_out); + +/* Context structure for the generic verify method. */ + +/* Verify the signer's certificate and the signature of the response. */ +# define TS_VFY_SIGNATURE (1u << 0) +/* Verify the version number of the response. */ +# define TS_VFY_VERSION (1u << 1) +/* Verify if the policy supplied by the user matches the policy of the TSA. */ +# define TS_VFY_POLICY (1u << 2) +/* + * Verify the message imprint provided by the user. This flag should not be + * specified with TS_VFY_DATA. + */ +# define TS_VFY_IMPRINT (1u << 3) +/* + * Verify the message imprint computed by the verify method from the user + * provided data and the MD algorithm of the response. This flag should not + * be specified with TS_VFY_IMPRINT. + */ +# define TS_VFY_DATA (1u << 4) +/* Verify the nonce value. */ +# define TS_VFY_NONCE (1u << 5) +/* Verify if the TSA name field matches the signer certificate. */ +# define TS_VFY_SIGNER (1u << 6) +/* Verify if the TSA name field equals to the user provided name. */ +# define TS_VFY_TSA_NAME (1u << 7) + +/* You can use the following convenience constants. */ +# define TS_VFY_ALL_IMPRINT (TS_VFY_SIGNATURE \ + | TS_VFY_VERSION \ + | TS_VFY_POLICY \ + | TS_VFY_IMPRINT \ + | TS_VFY_NONCE \ + | TS_VFY_SIGNER \ + | TS_VFY_TSA_NAME) +# define TS_VFY_ALL_DATA (TS_VFY_SIGNATURE \ + | TS_VFY_VERSION \ + | TS_VFY_POLICY \ + | TS_VFY_DATA \ + | TS_VFY_NONCE \ + | TS_VFY_SIGNER \ + | TS_VFY_TSA_NAME) + +typedef struct TS_verify_ctx TS_VERIFY_CTX; + +int TS_RESP_verify_response(TS_VERIFY_CTX *ctx, TS_RESP *response); +int TS_RESP_verify_token(TS_VERIFY_CTX *ctx, PKCS7 *token); + +/* + * Declarations related to response verification context, + */ +TS_VERIFY_CTX *TS_VERIFY_CTX_new(void); +void TS_VERIFY_CTX_init(TS_VERIFY_CTX *ctx); +void TS_VERIFY_CTX_free(TS_VERIFY_CTX *ctx); +void TS_VERIFY_CTX_cleanup(TS_VERIFY_CTX *ctx); +int TS_VERIFY_CTX_set_flags(TS_VERIFY_CTX *ctx, int f); +int TS_VERIFY_CTX_add_flags(TS_VERIFY_CTX *ctx, int f); +BIO *TS_VERIFY_CTX_set_data(TS_VERIFY_CTX *ctx, BIO *b); +unsigned char *TS_VERIFY_CTX_set_imprint(TS_VERIFY_CTX *ctx, + unsigned char *hexstr, long len); +X509_STORE *TS_VERIFY_CTX_set_store(TS_VERIFY_CTX *ctx, X509_STORE *s); +STACK_OF(X509) *TS_VERIFY_CTS_set_certs(TS_VERIFY_CTX *ctx, STACK_OF(X509) *certs); + +/*- + * If ctx is NULL, it allocates and returns a new object, otherwise + * it returns ctx. It initialises all the members as follows: + * flags = TS_VFY_ALL_IMPRINT & ~(TS_VFY_TSA_NAME | TS_VFY_SIGNATURE) + * certs = NULL + * store = NULL + * policy = policy from the request or NULL if absent (in this case + * TS_VFY_POLICY is cleared from flags as well) + * md_alg = MD algorithm from request + * imprint, imprint_len = imprint from request + * data = NULL + * nonce, nonce_len = nonce from the request or NULL if absent (in this case + * TS_VFY_NONCE is cleared from flags as well) + * tsa_name = NULL + * Important: after calling this method TS_VFY_SIGNATURE should be added! + */ +TS_VERIFY_CTX *TS_REQ_to_TS_VERIFY_CTX(TS_REQ *req, TS_VERIFY_CTX *ctx); + +/* Function declarations for TS_RESP defined in ts/ts_resp_print.c */ + +int TS_RESP_print_bio(BIO *bio, TS_RESP *a); +int TS_STATUS_INFO_print_bio(BIO *bio, TS_STATUS_INFO *a); +int TS_TST_INFO_print_bio(BIO *bio, TS_TST_INFO *a); + +/* Common utility functions defined in ts/ts_lib.c */ + +int TS_ASN1_INTEGER_print_bio(BIO *bio, const ASN1_INTEGER *num); +int TS_OBJ_print_bio(BIO *bio, const ASN1_OBJECT *obj); +int TS_ext_print_bio(BIO *bio, const STACK_OF(X509_EXTENSION) *extensions); +int TS_X509_ALGOR_print_bio(BIO *bio, const X509_ALGOR *alg); +int TS_MSG_IMPRINT_print_bio(BIO *bio, TS_MSG_IMPRINT *msg); + +/* + * Function declarations for handling configuration options, defined in + * ts/ts_conf.c + */ + +X509 *TS_CONF_load_cert(const char *file); +STACK_OF(X509) *TS_CONF_load_certs(const char *file); +EVP_PKEY *TS_CONF_load_key(const char *file, const char *pass); +const char *TS_CONF_get_tsa_section(CONF *conf, const char *section); +int TS_CONF_set_serial(CONF *conf, const char *section, TS_serial_cb cb, + TS_RESP_CTX *ctx); +#ifndef OPENSSL_NO_ENGINE +int TS_CONF_set_crypto_device(CONF *conf, const char *section, + const char *device); +int TS_CONF_set_default_engine(const char *name); +#endif +int TS_CONF_set_signer_cert(CONF *conf, const char *section, + const char *cert, TS_RESP_CTX *ctx); +int TS_CONF_set_certs(CONF *conf, const char *section, const char *certs, + TS_RESP_CTX *ctx); +int TS_CONF_set_signer_key(CONF *conf, const char *section, + const char *key, const char *pass, + TS_RESP_CTX *ctx); +int TS_CONF_set_signer_digest(CONF *conf, const char *section, + const char *md, TS_RESP_CTX *ctx); +int TS_CONF_set_def_policy(CONF *conf, const char *section, + const char *policy, TS_RESP_CTX *ctx); +int TS_CONF_set_policies(CONF *conf, const char *section, TS_RESP_CTX *ctx); +int TS_CONF_set_digests(CONF *conf, const char *section, TS_RESP_CTX *ctx); +int TS_CONF_set_accuracy(CONF *conf, const char *section, TS_RESP_CTX *ctx); +int TS_CONF_set_clock_precision_digits(CONF *conf, const char *section, + TS_RESP_CTX *ctx); +int TS_CONF_set_ordering(CONF *conf, const char *section, TS_RESP_CTX *ctx); +int TS_CONF_set_tsa_name(CONF *conf, const char *section, TS_RESP_CTX *ctx); +int TS_CONF_set_ess_cert_id_chain(CONF *conf, const char *section, + TS_RESP_CTX *ctx); +int TS_CONF_set_ess_cert_id_digest(CONF *conf, const char *section, + TS_RESP_CTX *ctx); + +# ifdef __cplusplus +} +# endif +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/tserr.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/tserr.h new file mode 100644 index 000000000..3e0492565 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/tserr.h @@ -0,0 +1,128 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_TSERR_H +# define HEADER_TSERR_H + +# include + +# ifndef OPENSSL_NO_TS + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_TS_strings(void); + +/* + * TS function codes. + */ +# define TS_F_DEF_SERIAL_CB 110 +# define TS_F_DEF_TIME_CB 111 +# define TS_F_ESS_ADD_SIGNING_CERT 112 +# define TS_F_ESS_ADD_SIGNING_CERT_V2 147 +# define TS_F_ESS_CERT_ID_NEW_INIT 113 +# define TS_F_ESS_CERT_ID_V2_NEW_INIT 156 +# define TS_F_ESS_SIGNING_CERT_NEW_INIT 114 +# define TS_F_ESS_SIGNING_CERT_V2_NEW_INIT 157 +# define TS_F_INT_TS_RESP_VERIFY_TOKEN 149 +# define TS_F_PKCS7_TO_TS_TST_INFO 148 +# define TS_F_TS_ACCURACY_SET_MICROS 115 +# define TS_F_TS_ACCURACY_SET_MILLIS 116 +# define TS_F_TS_ACCURACY_SET_SECONDS 117 +# define TS_F_TS_CHECK_IMPRINTS 100 +# define TS_F_TS_CHECK_NONCES 101 +# define TS_F_TS_CHECK_POLICY 102 +# define TS_F_TS_CHECK_SIGNING_CERTS 103 +# define TS_F_TS_CHECK_STATUS_INFO 104 +# define TS_F_TS_COMPUTE_IMPRINT 145 +# define TS_F_TS_CONF_INVALID 151 +# define TS_F_TS_CONF_LOAD_CERT 153 +# define TS_F_TS_CONF_LOAD_CERTS 154 +# define TS_F_TS_CONF_LOAD_KEY 155 +# define TS_F_TS_CONF_LOOKUP_FAIL 152 +# define TS_F_TS_CONF_SET_DEFAULT_ENGINE 146 +# define TS_F_TS_GET_STATUS_TEXT 105 +# define TS_F_TS_MSG_IMPRINT_SET_ALGO 118 +# define TS_F_TS_REQ_SET_MSG_IMPRINT 119 +# define TS_F_TS_REQ_SET_NONCE 120 +# define TS_F_TS_REQ_SET_POLICY_ID 121 +# define TS_F_TS_RESP_CREATE_RESPONSE 122 +# define TS_F_TS_RESP_CREATE_TST_INFO 123 +# define TS_F_TS_RESP_CTX_ADD_FAILURE_INFO 124 +# define TS_F_TS_RESP_CTX_ADD_MD 125 +# define TS_F_TS_RESP_CTX_ADD_POLICY 126 +# define TS_F_TS_RESP_CTX_NEW 127 +# define TS_F_TS_RESP_CTX_SET_ACCURACY 128 +# define TS_F_TS_RESP_CTX_SET_CERTS 129 +# define TS_F_TS_RESP_CTX_SET_DEF_POLICY 130 +# define TS_F_TS_RESP_CTX_SET_SIGNER_CERT 131 +# define TS_F_TS_RESP_CTX_SET_STATUS_INFO 132 +# define TS_F_TS_RESP_GET_POLICY 133 +# define TS_F_TS_RESP_SET_GENTIME_WITH_PRECISION 134 +# define TS_F_TS_RESP_SET_STATUS_INFO 135 +# define TS_F_TS_RESP_SET_TST_INFO 150 +# define TS_F_TS_RESP_SIGN 136 +# define TS_F_TS_RESP_VERIFY_SIGNATURE 106 +# define TS_F_TS_TST_INFO_SET_ACCURACY 137 +# define TS_F_TS_TST_INFO_SET_MSG_IMPRINT 138 +# define TS_F_TS_TST_INFO_SET_NONCE 139 +# define TS_F_TS_TST_INFO_SET_POLICY_ID 140 +# define TS_F_TS_TST_INFO_SET_SERIAL 141 +# define TS_F_TS_TST_INFO_SET_TIME 142 +# define TS_F_TS_TST_INFO_SET_TSA 143 +# define TS_F_TS_VERIFY 108 +# define TS_F_TS_VERIFY_CERT 109 +# define TS_F_TS_VERIFY_CTX_NEW 144 + +/* + * TS reason codes. + */ +# define TS_R_BAD_PKCS7_TYPE 132 +# define TS_R_BAD_TYPE 133 +# define TS_R_CANNOT_LOAD_CERT 137 +# define TS_R_CANNOT_LOAD_KEY 138 +# define TS_R_CERTIFICATE_VERIFY_ERROR 100 +# define TS_R_COULD_NOT_SET_ENGINE 127 +# define TS_R_COULD_NOT_SET_TIME 115 +# define TS_R_DETACHED_CONTENT 134 +# define TS_R_ESS_ADD_SIGNING_CERT_ERROR 116 +# define TS_R_ESS_ADD_SIGNING_CERT_V2_ERROR 139 +# define TS_R_ESS_SIGNING_CERTIFICATE_ERROR 101 +# define TS_R_INVALID_NULL_POINTER 102 +# define TS_R_INVALID_SIGNER_CERTIFICATE_PURPOSE 117 +# define TS_R_MESSAGE_IMPRINT_MISMATCH 103 +# define TS_R_NONCE_MISMATCH 104 +# define TS_R_NONCE_NOT_RETURNED 105 +# define TS_R_NO_CONTENT 106 +# define TS_R_NO_TIME_STAMP_TOKEN 107 +# define TS_R_PKCS7_ADD_SIGNATURE_ERROR 118 +# define TS_R_PKCS7_ADD_SIGNED_ATTR_ERROR 119 +# define TS_R_PKCS7_TO_TS_TST_INFO_FAILED 129 +# define TS_R_POLICY_MISMATCH 108 +# define TS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 120 +# define TS_R_RESPONSE_SETUP_ERROR 121 +# define TS_R_SIGNATURE_FAILURE 109 +# define TS_R_THERE_MUST_BE_ONE_SIGNER 110 +# define TS_R_TIME_SYSCALL_ERROR 122 +# define TS_R_TOKEN_NOT_PRESENT 130 +# define TS_R_TOKEN_PRESENT 131 +# define TS_R_TSA_NAME_MISMATCH 111 +# define TS_R_TSA_UNTRUSTED 112 +# define TS_R_TST_INFO_SETUP_ERROR 123 +# define TS_R_TS_DATASIGN 124 +# define TS_R_UNACCEPTABLE_POLICY 125 +# define TS_R_UNSUPPORTED_MD_ALGORITHM 126 +# define TS_R_UNSUPPORTED_VERSION 113 +# define TS_R_VAR_BAD_VALUE 135 +# define TS_R_VAR_LOOKUP_FAILURE 136 +# define TS_R_WRONG_CONTENT_TYPE 114 + +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/txt_db.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/txt_db.h new file mode 100644 index 000000000..ec981a439 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/txt_db.h @@ -0,0 +1,57 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_TXT_DB_H +# define HEADER_TXT_DB_H + +# include +# include +# include +# include + +# define DB_ERROR_OK 0 +# define DB_ERROR_MALLOC 1 +# define DB_ERROR_INDEX_CLASH 2 +# define DB_ERROR_INDEX_OUT_OF_RANGE 3 +# define DB_ERROR_NO_INDEX 4 +# define DB_ERROR_INSERT_INDEX_CLASH 5 +# define DB_ERROR_WRONG_NUM_FIELDS 6 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef OPENSSL_STRING *OPENSSL_PSTRING; +DEFINE_SPECIAL_STACK_OF(OPENSSL_PSTRING, OPENSSL_STRING) + +typedef struct txt_db_st { + int num_fields; + STACK_OF(OPENSSL_PSTRING) *data; + LHASH_OF(OPENSSL_STRING) **index; + int (**qual) (OPENSSL_STRING *); + long error; + long arg1; + long arg2; + OPENSSL_STRING *arg_row; +} TXT_DB; + +TXT_DB *TXT_DB_read(BIO *in, int num); +long TXT_DB_write(BIO *out, TXT_DB *db); +int TXT_DB_create_index(TXT_DB *db, int field, int (*qual) (OPENSSL_STRING *), + OPENSSL_LH_HASHFUNC hash, OPENSSL_LH_COMPFUNC cmp); +void TXT_DB_free(TXT_DB *db); +OPENSSL_STRING *TXT_DB_get_by_index(TXT_DB *db, int idx, + OPENSSL_STRING *value); +int TXT_DB_insert(TXT_DB *db, OPENSSL_STRING *value); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/ui.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ui.h new file mode 100644 index 000000000..7c721ec81 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/ui.h @@ -0,0 +1,368 @@ +/* + * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_UI_H +# define HEADER_UI_H + +# include + +# if OPENSSL_API_COMPAT < 0x10100000L +# include +# endif +# include +# include +# include +# include + +/* For compatibility reasons, the macro OPENSSL_NO_UI is currently retained */ +# if OPENSSL_API_COMPAT < 0x10200000L +# ifdef OPENSSL_NO_UI_CONSOLE +# define OPENSSL_NO_UI +# endif +# endif + +# ifdef __cplusplus +extern "C" { +# endif + +/* + * All the following functions return -1 or NULL on error and in some cases + * (UI_process()) -2 if interrupted or in some other way cancelled. When + * everything is fine, they return 0, a positive value or a non-NULL pointer, + * all depending on their purpose. + */ + +/* Creators and destructor. */ +UI *UI_new(void); +UI *UI_new_method(const UI_METHOD *method); +void UI_free(UI *ui); + +/*- + The following functions are used to add strings to be printed and prompt + strings to prompt for data. The names are UI_{add,dup}__string + and UI_{add,dup}_input_boolean. + + UI_{add,dup}__string have the following meanings: + add add a text or prompt string. The pointers given to these + functions are used verbatim, no copying is done. + dup make a copy of the text or prompt string, then add the copy + to the collection of strings in the user interface. + + The function is a name for the functionality that the given + string shall be used for. It can be one of: + input use the string as data prompt. + verify use the string as verification prompt. This + is used to verify a previous input. + info use the string for informational output. + error use the string for error output. + Honestly, there's currently no difference between info and error for the + moment. + + UI_{add,dup}_input_boolean have the same semantics for "add" and "dup", + and are typically used when one wants to prompt for a yes/no response. + + All of the functions in this group take a UI and a prompt string. + The string input and verify addition functions also take a flag argument, + a buffer for the result to end up with, a minimum input size and a maximum + input size (the result buffer MUST be large enough to be able to contain + the maximum number of characters). Additionally, the verify addition + functions takes another buffer to compare the result against. + The boolean input functions take an action description string (which should + be safe to ignore if the expected user action is obvious, for example with + a dialog box with an OK button and a Cancel button), a string of acceptable + characters to mean OK and to mean Cancel. The two last strings are checked + to make sure they don't have common characters. Additionally, the same + flag argument as for the string input is taken, as well as a result buffer. + The result buffer is required to be at least one byte long. Depending on + the answer, the first character from the OK or the Cancel character strings + will be stored in the first byte of the result buffer. No NUL will be + added, so the result is *not* a string. + + On success, the all return an index of the added information. That index + is useful when retrieving results with UI_get0_result(). */ +int UI_add_input_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize); +int UI_dup_input_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize); +int UI_add_verify_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize, + const char *test_buf); +int UI_dup_verify_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize, + const char *test_buf); +int UI_add_input_boolean(UI *ui, const char *prompt, const char *action_desc, + const char *ok_chars, const char *cancel_chars, + int flags, char *result_buf); +int UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc, + const char *ok_chars, const char *cancel_chars, + int flags, char *result_buf); +int UI_add_info_string(UI *ui, const char *text); +int UI_dup_info_string(UI *ui, const char *text); +int UI_add_error_string(UI *ui, const char *text); +int UI_dup_error_string(UI *ui, const char *text); + +/* These are the possible flags. They can be or'ed together. */ +/* Use to have echoing of input */ +# define UI_INPUT_FLAG_ECHO 0x01 +/* + * Use a default password. Where that password is found is completely up to + * the application, it might for example be in the user data set with + * UI_add_user_data(). It is not recommended to have more than one input in + * each UI being marked with this flag, or the application might get + * confused. + */ +# define UI_INPUT_FLAG_DEFAULT_PWD 0x02 + +/*- + * The user of these routines may want to define flags of their own. The core + * UI won't look at those, but will pass them on to the method routines. They + * must use higher bits so they don't get confused with the UI bits above. + * UI_INPUT_FLAG_USER_BASE tells which is the lowest bit to use. A good + * example of use is this: + * + * #define MY_UI_FLAG1 (0x01 << UI_INPUT_FLAG_USER_BASE) + * +*/ +# define UI_INPUT_FLAG_USER_BASE 16 + +/*- + * The following function helps construct a prompt. object_desc is a + * textual short description of the object, for example "pass phrase", + * and object_name is the name of the object (might be a card name or + * a file name. + * The returned string shall always be allocated on the heap with + * OPENSSL_malloc(), and need to be free'd with OPENSSL_free(). + * + * If the ui_method doesn't contain a pointer to a user-defined prompt + * constructor, a default string is built, looking like this: + * + * "Enter {object_desc} for {object_name}:" + * + * So, if object_desc has the value "pass phrase" and object_name has + * the value "foo.key", the resulting string is: + * + * "Enter pass phrase for foo.key:" +*/ +char *UI_construct_prompt(UI *ui_method, + const char *object_desc, const char *object_name); + +/* + * The following function is used to store a pointer to user-specific data. + * Any previous such pointer will be returned and replaced. + * + * For callback purposes, this function makes a lot more sense than using + * ex_data, since the latter requires that different parts of OpenSSL or + * applications share the same ex_data index. + * + * Note that the UI_OpenSSL() method completely ignores the user data. Other + * methods may not, however. + */ +void *UI_add_user_data(UI *ui, void *user_data); +/* + * Alternatively, this function is used to duplicate the user data. + * This uses the duplicator method function. The destroy function will + * be used to free the user data in this case. + */ +int UI_dup_user_data(UI *ui, void *user_data); +/* We need a user data retrieving function as well. */ +void *UI_get0_user_data(UI *ui); + +/* Return the result associated with a prompt given with the index i. */ +const char *UI_get0_result(UI *ui, int i); +int UI_get_result_length(UI *ui, int i); + +/* When all strings have been added, process the whole thing. */ +int UI_process(UI *ui); + +/* + * Give a user interface parameterised control commands. This can be used to + * send down an integer, a data pointer or a function pointer, as well as be + * used to get information from a UI. + */ +int UI_ctrl(UI *ui, int cmd, long i, void *p, void (*f) (void)); + +/* The commands */ +/* + * Use UI_CONTROL_PRINT_ERRORS with the value 1 to have UI_process print the + * OpenSSL error stack before printing any info or added error messages and + * before any prompting. + */ +# define UI_CTRL_PRINT_ERRORS 1 +/* + * Check if a UI_process() is possible to do again with the same instance of + * a user interface. This makes UI_ctrl() return 1 if it is redoable, and 0 + * if not. + */ +# define UI_CTRL_IS_REDOABLE 2 + +/* Some methods may use extra data */ +# define UI_set_app_data(s,arg) UI_set_ex_data(s,0,arg) +# define UI_get_app_data(s) UI_get_ex_data(s,0) + +# define UI_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_UI, l, p, newf, dupf, freef) +int UI_set_ex_data(UI *r, int idx, void *arg); +void *UI_get_ex_data(UI *r, int idx); + +/* Use specific methods instead of the built-in one */ +void UI_set_default_method(const UI_METHOD *meth); +const UI_METHOD *UI_get_default_method(void); +const UI_METHOD *UI_get_method(UI *ui); +const UI_METHOD *UI_set_method(UI *ui, const UI_METHOD *meth); + +# ifndef OPENSSL_NO_UI_CONSOLE + +/* The method with all the built-in thingies */ +UI_METHOD *UI_OpenSSL(void); + +# endif + +/* + * NULL method. Literally does nothing, but may serve as a placeholder + * to avoid internal default. + */ +const UI_METHOD *UI_null(void); + +/* ---------- For method writers ---------- */ +/*- + A method contains a number of functions that implement the low level + of the User Interface. The functions are: + + an opener This function starts a session, maybe by opening + a channel to a tty, or by opening a window. + a writer This function is called to write a given string, + maybe to the tty, maybe as a field label in a + window. + a flusher This function is called to flush everything that + has been output so far. It can be used to actually + display a dialog box after it has been built. + a reader This function is called to read a given prompt, + maybe from the tty, maybe from a field in a + window. Note that it's called with all string + structures, not only the prompt ones, so it must + check such things itself. + a closer This function closes the session, maybe by closing + the channel to the tty, or closing the window. + + All these functions are expected to return: + + 0 on error. + 1 on success. + -1 on out-of-band events, for example if some prompting has + been canceled (by pressing Ctrl-C, for example). This is + only checked when returned by the flusher or the reader. + + The way this is used, the opener is first called, then the writer for all + strings, then the flusher, then the reader for all strings and finally the + closer. Note that if you want to prompt from a terminal or other command + line interface, the best is to have the reader also write the prompts + instead of having the writer do it. If you want to prompt from a dialog + box, the writer can be used to build up the contents of the box, and the + flusher to actually display the box and run the event loop until all data + has been given, after which the reader only grabs the given data and puts + them back into the UI strings. + + All method functions take a UI as argument. Additionally, the writer and + the reader take a UI_STRING. +*/ + +/* + * The UI_STRING type is the data structure that contains all the needed info + * about a string or a prompt, including test data for a verification prompt. + */ +typedef struct ui_string_st UI_STRING; +DEFINE_STACK_OF(UI_STRING) + +/* + * The different types of strings that are currently supported. This is only + * needed by method authors. + */ +enum UI_string_types { + UIT_NONE = 0, + UIT_PROMPT, /* Prompt for a string */ + UIT_VERIFY, /* Prompt for a string and verify */ + UIT_BOOLEAN, /* Prompt for a yes/no response */ + UIT_INFO, /* Send info to the user */ + UIT_ERROR /* Send an error message to the user */ +}; + +/* Create and manipulate methods */ +UI_METHOD *UI_create_method(const char *name); +void UI_destroy_method(UI_METHOD *ui_method); +int UI_method_set_opener(UI_METHOD *method, int (*opener) (UI *ui)); +int UI_method_set_writer(UI_METHOD *method, + int (*writer) (UI *ui, UI_STRING *uis)); +int UI_method_set_flusher(UI_METHOD *method, int (*flusher) (UI *ui)); +int UI_method_set_reader(UI_METHOD *method, + int (*reader) (UI *ui, UI_STRING *uis)); +int UI_method_set_closer(UI_METHOD *method, int (*closer) (UI *ui)); +int UI_method_set_data_duplicator(UI_METHOD *method, + void *(*duplicator) (UI *ui, void *ui_data), + void (*destructor)(UI *ui, void *ui_data)); +int UI_method_set_prompt_constructor(UI_METHOD *method, + char *(*prompt_constructor) (UI *ui, + const char + *object_desc, + const char + *object_name)); +int UI_method_set_ex_data(UI_METHOD *method, int idx, void *data); +int (*UI_method_get_opener(const UI_METHOD *method)) (UI *); +int (*UI_method_get_writer(const UI_METHOD *method)) (UI *, UI_STRING *); +int (*UI_method_get_flusher(const UI_METHOD *method)) (UI *); +int (*UI_method_get_reader(const UI_METHOD *method)) (UI *, UI_STRING *); +int (*UI_method_get_closer(const UI_METHOD *method)) (UI *); +char *(*UI_method_get_prompt_constructor(const UI_METHOD *method)) + (UI *, const char *, const char *); +void *(*UI_method_get_data_duplicator(const UI_METHOD *method)) (UI *, void *); +void (*UI_method_get_data_destructor(const UI_METHOD *method)) (UI *, void *); +const void *UI_method_get_ex_data(const UI_METHOD *method, int idx); + +/* + * The following functions are helpers for method writers to access relevant + * data from a UI_STRING. + */ + +/* Return type of the UI_STRING */ +enum UI_string_types UI_get_string_type(UI_STRING *uis); +/* Return input flags of the UI_STRING */ +int UI_get_input_flags(UI_STRING *uis); +/* Return the actual string to output (the prompt, info or error) */ +const char *UI_get0_output_string(UI_STRING *uis); +/* + * Return the optional action string to output (the boolean prompt + * instruction) + */ +const char *UI_get0_action_string(UI_STRING *uis); +/* Return the result of a prompt */ +const char *UI_get0_result_string(UI_STRING *uis); +int UI_get_result_string_length(UI_STRING *uis); +/* + * Return the string to test the result against. Only useful with verifies. + */ +const char *UI_get0_test_string(UI_STRING *uis); +/* Return the required minimum size of the result */ +int UI_get_result_minsize(UI_STRING *uis); +/* Return the required maximum size of the result */ +int UI_get_result_maxsize(UI_STRING *uis); +/* Set the result of a UI_STRING. */ +int UI_set_result(UI *ui, UI_STRING *uis, const char *result); +int UI_set_result_ex(UI *ui, UI_STRING *uis, const char *result, int len); + +/* A couple of popular utility functions */ +int UI_UTIL_read_pw_string(char *buf, int length, const char *prompt, + int verify); +int UI_UTIL_read_pw(char *buf, char *buff, int size, const char *prompt, + int verify); +UI_METHOD *UI_UTIL_wrap_read_pem_callback(pem_password_cb *cb, int rwflag); + + +# ifdef __cplusplus +} +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/uierr.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/uierr.h new file mode 100644 index 000000000..72fd9a9db --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/uierr.h @@ -0,0 +1,61 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_UIERR_H +# define HEADER_UIERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_UI_strings(void); + +/* + * UI function codes. + */ +# define UI_F_CLOSE_CONSOLE 115 +# define UI_F_ECHO_CONSOLE 116 +# define UI_F_GENERAL_ALLOCATE_BOOLEAN 108 +# define UI_F_GENERAL_ALLOCATE_PROMPT 109 +# define UI_F_NOECHO_CONSOLE 117 +# define UI_F_OPEN_CONSOLE 114 +# define UI_F_UI_CONSTRUCT_PROMPT 121 +# define UI_F_UI_CREATE_METHOD 112 +# define UI_F_UI_CTRL 111 +# define UI_F_UI_DUP_ERROR_STRING 101 +# define UI_F_UI_DUP_INFO_STRING 102 +# define UI_F_UI_DUP_INPUT_BOOLEAN 110 +# define UI_F_UI_DUP_INPUT_STRING 103 +# define UI_F_UI_DUP_USER_DATA 118 +# define UI_F_UI_DUP_VERIFY_STRING 106 +# define UI_F_UI_GET0_RESULT 107 +# define UI_F_UI_GET_RESULT_LENGTH 119 +# define UI_F_UI_NEW_METHOD 104 +# define UI_F_UI_PROCESS 113 +# define UI_F_UI_SET_RESULT 105 +# define UI_F_UI_SET_RESULT_EX 120 + +/* + * UI reason codes. + */ +# define UI_R_COMMON_OK_AND_CANCEL_CHARACTERS 104 +# define UI_R_INDEX_TOO_LARGE 102 +# define UI_R_INDEX_TOO_SMALL 103 +# define UI_R_NO_RESULT_BUFFER 105 +# define UI_R_PROCESSING_ERROR 107 +# define UI_R_RESULT_TOO_LARGE 100 +# define UI_R_RESULT_TOO_SMALL 101 +# define UI_R_SYSASSIGN_ERROR 109 +# define UI_R_SYSDASSGN_ERROR 110 +# define UI_R_SYSQIOW_ERROR 111 +# define UI_R_UNKNOWN_CONTROL_COMMAND 106 +# define UI_R_UNKNOWN_TTYGET_ERRNO_VALUE 108 +# define UI_R_USER_DATA_DUPLICATION_UNSUPPORTED 112 + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/whrlpool.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/whrlpool.h new file mode 100644 index 000000000..20ea3503b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/whrlpool.h @@ -0,0 +1,48 @@ +/* + * Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_WHRLPOOL_H +# define HEADER_WHRLPOOL_H + +#include + +# ifndef OPENSSL_NO_WHIRLPOOL +# include +# include +# ifdef __cplusplus +extern "C" { +# endif + +# define WHIRLPOOL_DIGEST_LENGTH (512/8) +# define WHIRLPOOL_BBLOCK 512 +# define WHIRLPOOL_COUNTER (256/8) + +typedef struct { + union { + unsigned char c[WHIRLPOOL_DIGEST_LENGTH]; + /* double q is here to ensure 64-bit alignment */ + double q[WHIRLPOOL_DIGEST_LENGTH / sizeof(double)]; + } H; + unsigned char data[WHIRLPOOL_BBLOCK / 8]; + unsigned int bitoff; + size_t bitlen[WHIRLPOOL_COUNTER / sizeof(size_t)]; +} WHIRLPOOL_CTX; + +int WHIRLPOOL_Init(WHIRLPOOL_CTX *c); +int WHIRLPOOL_Update(WHIRLPOOL_CTX *c, const void *inp, size_t bytes); +void WHIRLPOOL_BitUpdate(WHIRLPOOL_CTX *c, const void *inp, size_t bits); +int WHIRLPOOL_Final(unsigned char *md, WHIRLPOOL_CTX *c); +unsigned char *WHIRLPOOL(const void *inp, size_t bytes, unsigned char *md); + +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/x509.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/x509.h new file mode 100644 index 000000000..39ca0ba57 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/x509.h @@ -0,0 +1,1047 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_X509_H +# define HEADER_X509_H + +# include +# include +# include +# include +# include +# include +# include +# include +# include + +# if OPENSSL_API_COMPAT < 0x10100000L +# include +# include +# include +# endif + +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Flags for X509_get_signature_info() */ +/* Signature info is valid */ +# define X509_SIG_INFO_VALID 0x1 +/* Signature is suitable for TLS use */ +# define X509_SIG_INFO_TLS 0x2 + +# define X509_FILETYPE_PEM 1 +# define X509_FILETYPE_ASN1 2 +# define X509_FILETYPE_DEFAULT 3 + +# define X509v3_KU_DIGITAL_SIGNATURE 0x0080 +# define X509v3_KU_NON_REPUDIATION 0x0040 +# define X509v3_KU_KEY_ENCIPHERMENT 0x0020 +# define X509v3_KU_DATA_ENCIPHERMENT 0x0010 +# define X509v3_KU_KEY_AGREEMENT 0x0008 +# define X509v3_KU_KEY_CERT_SIGN 0x0004 +# define X509v3_KU_CRL_SIGN 0x0002 +# define X509v3_KU_ENCIPHER_ONLY 0x0001 +# define X509v3_KU_DECIPHER_ONLY 0x8000 +# define X509v3_KU_UNDEF 0xffff + +struct X509_algor_st { + ASN1_OBJECT *algorithm; + ASN1_TYPE *parameter; +} /* X509_ALGOR */ ; + +typedef STACK_OF(X509_ALGOR) X509_ALGORS; + +typedef struct X509_val_st { + ASN1_TIME *notBefore; + ASN1_TIME *notAfter; +} X509_VAL; + +typedef struct X509_sig_st X509_SIG; + +typedef struct X509_name_entry_st X509_NAME_ENTRY; + +DEFINE_STACK_OF(X509_NAME_ENTRY) + +DEFINE_STACK_OF(X509_NAME) + +# define X509_EX_V_NETSCAPE_HACK 0x8000 +# define X509_EX_V_INIT 0x0001 +typedef struct X509_extension_st X509_EXTENSION; + +typedef STACK_OF(X509_EXTENSION) X509_EXTENSIONS; + +DEFINE_STACK_OF(X509_EXTENSION) + +typedef struct x509_attributes_st X509_ATTRIBUTE; + +DEFINE_STACK_OF(X509_ATTRIBUTE) + +typedef struct X509_req_info_st X509_REQ_INFO; + +typedef struct X509_req_st X509_REQ; + +typedef struct x509_cert_aux_st X509_CERT_AUX; + +typedef struct x509_cinf_st X509_CINF; + +DEFINE_STACK_OF(X509) + +/* This is used for a table of trust checking functions */ + +typedef struct x509_trust_st { + int trust; + int flags; + int (*check_trust) (struct x509_trust_st *, X509 *, int); + char *name; + int arg1; + void *arg2; +} X509_TRUST; + +DEFINE_STACK_OF(X509_TRUST) + +/* standard trust ids */ + +# define X509_TRUST_DEFAULT 0 /* Only valid in purpose settings */ + +# define X509_TRUST_COMPAT 1 +# define X509_TRUST_SSL_CLIENT 2 +# define X509_TRUST_SSL_SERVER 3 +# define X509_TRUST_EMAIL 4 +# define X509_TRUST_OBJECT_SIGN 5 +# define X509_TRUST_OCSP_SIGN 6 +# define X509_TRUST_OCSP_REQUEST 7 +# define X509_TRUST_TSA 8 + +/* Keep these up to date! */ +# define X509_TRUST_MIN 1 +# define X509_TRUST_MAX 8 + +/* trust_flags values */ +# define X509_TRUST_DYNAMIC (1U << 0) +# define X509_TRUST_DYNAMIC_NAME (1U << 1) +/* No compat trust if self-signed, preempts "DO_SS" */ +# define X509_TRUST_NO_SS_COMPAT (1U << 2) +/* Compat trust if no explicit accepted trust EKUs */ +# define X509_TRUST_DO_SS_COMPAT (1U << 3) +/* Accept "anyEKU" as a wildcard trust OID */ +# define X509_TRUST_OK_ANY_EKU (1U << 4) + +/* check_trust return codes */ + +# define X509_TRUST_TRUSTED 1 +# define X509_TRUST_REJECTED 2 +# define X509_TRUST_UNTRUSTED 3 + +/* Flags for X509_print_ex() */ + +# define X509_FLAG_COMPAT 0 +# define X509_FLAG_NO_HEADER 1L +# define X509_FLAG_NO_VERSION (1L << 1) +# define X509_FLAG_NO_SERIAL (1L << 2) +# define X509_FLAG_NO_SIGNAME (1L << 3) +# define X509_FLAG_NO_ISSUER (1L << 4) +# define X509_FLAG_NO_VALIDITY (1L << 5) +# define X509_FLAG_NO_SUBJECT (1L << 6) +# define X509_FLAG_NO_PUBKEY (1L << 7) +# define X509_FLAG_NO_EXTENSIONS (1L << 8) +# define X509_FLAG_NO_SIGDUMP (1L << 9) +# define X509_FLAG_NO_AUX (1L << 10) +# define X509_FLAG_NO_ATTRIBUTES (1L << 11) +# define X509_FLAG_NO_IDS (1L << 12) + +/* Flags specific to X509_NAME_print_ex() */ + +/* The field separator information */ + +# define XN_FLAG_SEP_MASK (0xf << 16) + +# define XN_FLAG_COMPAT 0/* Traditional; use old X509_NAME_print */ +# define XN_FLAG_SEP_COMMA_PLUS (1 << 16)/* RFC2253 ,+ */ +# define XN_FLAG_SEP_CPLUS_SPC (2 << 16)/* ,+ spaced: more readable */ +# define XN_FLAG_SEP_SPLUS_SPC (3 << 16)/* ;+ spaced */ +# define XN_FLAG_SEP_MULTILINE (4 << 16)/* One line per field */ + +# define XN_FLAG_DN_REV (1 << 20)/* Reverse DN order */ + +/* How the field name is shown */ + +# define XN_FLAG_FN_MASK (0x3 << 21) + +# define XN_FLAG_FN_SN 0/* Object short name */ +# define XN_FLAG_FN_LN (1 << 21)/* Object long name */ +# define XN_FLAG_FN_OID (2 << 21)/* Always use OIDs */ +# define XN_FLAG_FN_NONE (3 << 21)/* No field names */ + +# define XN_FLAG_SPC_EQ (1 << 23)/* Put spaces round '=' */ + +/* + * This determines if we dump fields we don't recognise: RFC2253 requires + * this. + */ + +# define XN_FLAG_DUMP_UNKNOWN_FIELDS (1 << 24) + +# define XN_FLAG_FN_ALIGN (1 << 25)/* Align field names to 20 + * characters */ + +/* Complete set of RFC2253 flags */ + +# define XN_FLAG_RFC2253 (ASN1_STRFLGS_RFC2253 | \ + XN_FLAG_SEP_COMMA_PLUS | \ + XN_FLAG_DN_REV | \ + XN_FLAG_FN_SN | \ + XN_FLAG_DUMP_UNKNOWN_FIELDS) + +/* readable oneline form */ + +# define XN_FLAG_ONELINE (ASN1_STRFLGS_RFC2253 | \ + ASN1_STRFLGS_ESC_QUOTE | \ + XN_FLAG_SEP_CPLUS_SPC | \ + XN_FLAG_SPC_EQ | \ + XN_FLAG_FN_SN) + +/* readable multiline form */ + +# define XN_FLAG_MULTILINE (ASN1_STRFLGS_ESC_CTRL | \ + ASN1_STRFLGS_ESC_MSB | \ + XN_FLAG_SEP_MULTILINE | \ + XN_FLAG_SPC_EQ | \ + XN_FLAG_FN_LN | \ + XN_FLAG_FN_ALIGN) + +DEFINE_STACK_OF(X509_REVOKED) + +typedef struct X509_crl_info_st X509_CRL_INFO; + +DEFINE_STACK_OF(X509_CRL) + +typedef struct private_key_st { + int version; + /* The PKCS#8 data types */ + X509_ALGOR *enc_algor; + ASN1_OCTET_STRING *enc_pkey; /* encrypted pub key */ + /* When decrypted, the following will not be NULL */ + EVP_PKEY *dec_pkey; + /* used to encrypt and decrypt */ + int key_length; + char *key_data; + int key_free; /* true if we should auto free key_data */ + /* expanded version of 'enc_algor' */ + EVP_CIPHER_INFO cipher; +} X509_PKEY; + +typedef struct X509_info_st { + X509 *x509; + X509_CRL *crl; + X509_PKEY *x_pkey; + EVP_CIPHER_INFO enc_cipher; + int enc_len; + char *enc_data; +} X509_INFO; + +DEFINE_STACK_OF(X509_INFO) + +/* + * The next 2 structures and their 8 routines are used to manipulate Netscape's + * spki structures - useful if you are writing a CA web page + */ +typedef struct Netscape_spkac_st { + X509_PUBKEY *pubkey; + ASN1_IA5STRING *challenge; /* challenge sent in atlas >= PR2 */ +} NETSCAPE_SPKAC; + +typedef struct Netscape_spki_st { + NETSCAPE_SPKAC *spkac; /* signed public key and challenge */ + X509_ALGOR sig_algor; + ASN1_BIT_STRING *signature; +} NETSCAPE_SPKI; + +/* Netscape certificate sequence structure */ +typedef struct Netscape_certificate_sequence { + ASN1_OBJECT *type; + STACK_OF(X509) *certs; +} NETSCAPE_CERT_SEQUENCE; + +/*- Unused (and iv length is wrong) +typedef struct CBCParameter_st + { + unsigned char iv[8]; + } CBC_PARAM; +*/ + +/* Password based encryption structure */ + +typedef struct PBEPARAM_st { + ASN1_OCTET_STRING *salt; + ASN1_INTEGER *iter; +} PBEPARAM; + +/* Password based encryption V2 structures */ + +typedef struct PBE2PARAM_st { + X509_ALGOR *keyfunc; + X509_ALGOR *encryption; +} PBE2PARAM; + +typedef struct PBKDF2PARAM_st { +/* Usually OCTET STRING but could be anything */ + ASN1_TYPE *salt; + ASN1_INTEGER *iter; + ASN1_INTEGER *keylength; + X509_ALGOR *prf; +} PBKDF2PARAM; + +#ifndef OPENSSL_NO_SCRYPT +typedef struct SCRYPT_PARAMS_st { + ASN1_OCTET_STRING *salt; + ASN1_INTEGER *costParameter; + ASN1_INTEGER *blockSize; + ASN1_INTEGER *parallelizationParameter; + ASN1_INTEGER *keyLength; +} SCRYPT_PARAMS; +#endif + +#ifdef __cplusplus +} +#endif + +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# define X509_EXT_PACK_UNKNOWN 1 +# define X509_EXT_PACK_STRING 2 + +# define X509_extract_key(x) X509_get_pubkey(x)/*****/ +# define X509_REQ_extract_key(a) X509_REQ_get_pubkey(a) +# define X509_name_cmp(a,b) X509_NAME_cmp((a),(b)) + +void X509_CRL_set_default_method(const X509_CRL_METHOD *meth); +X509_CRL_METHOD *X509_CRL_METHOD_new(int (*crl_init) (X509_CRL *crl), + int (*crl_free) (X509_CRL *crl), + int (*crl_lookup) (X509_CRL *crl, + X509_REVOKED **ret, + ASN1_INTEGER *ser, + X509_NAME *issuer), + int (*crl_verify) (X509_CRL *crl, + EVP_PKEY *pk)); +void X509_CRL_METHOD_free(X509_CRL_METHOD *m); + +void X509_CRL_set_meth_data(X509_CRL *crl, void *dat); +void *X509_CRL_get_meth_data(X509_CRL *crl); + +const char *X509_verify_cert_error_string(long n); + +int X509_verify(X509 *a, EVP_PKEY *r); + +int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r); +int X509_CRL_verify(X509_CRL *a, EVP_PKEY *r); +int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *a, EVP_PKEY *r); + +NETSCAPE_SPKI *NETSCAPE_SPKI_b64_decode(const char *str, int len); +char *NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *x); +EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *x); +int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey); + +int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki); + +int X509_signature_dump(BIO *bp, const ASN1_STRING *sig, int indent); +int X509_signature_print(BIO *bp, const X509_ALGOR *alg, + const ASN1_STRING *sig); + +int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md); +int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx); +# ifndef OPENSSL_NO_OCSP +int X509_http_nbio(OCSP_REQ_CTX *rctx, X509 **pcert); +# endif +int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md); +int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx); +int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md); +int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx); +# ifndef OPENSSL_NO_OCSP +int X509_CRL_http_nbio(OCSP_REQ_CTX *rctx, X509_CRL **pcrl); +# endif +int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md); + +int X509_pubkey_digest(const X509 *data, const EVP_MD *type, + unsigned char *md, unsigned int *len); +int X509_digest(const X509 *data, const EVP_MD *type, + unsigned char *md, unsigned int *len); +int X509_CRL_digest(const X509_CRL *data, const EVP_MD *type, + unsigned char *md, unsigned int *len); +int X509_REQ_digest(const X509_REQ *data, const EVP_MD *type, + unsigned char *md, unsigned int *len); +int X509_NAME_digest(const X509_NAME *data, const EVP_MD *type, + unsigned char *md, unsigned int *len); + +# ifndef OPENSSL_NO_STDIO +X509 *d2i_X509_fp(FILE *fp, X509 **x509); +int i2d_X509_fp(FILE *fp, X509 *x509); +X509_CRL *d2i_X509_CRL_fp(FILE *fp, X509_CRL **crl); +int i2d_X509_CRL_fp(FILE *fp, X509_CRL *crl); +X509_REQ *d2i_X509_REQ_fp(FILE *fp, X509_REQ **req); +int i2d_X509_REQ_fp(FILE *fp, X509_REQ *req); +# ifndef OPENSSL_NO_RSA +RSA *d2i_RSAPrivateKey_fp(FILE *fp, RSA **rsa); +int i2d_RSAPrivateKey_fp(FILE *fp, RSA *rsa); +RSA *d2i_RSAPublicKey_fp(FILE *fp, RSA **rsa); +int i2d_RSAPublicKey_fp(FILE *fp, RSA *rsa); +RSA *d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa); +int i2d_RSA_PUBKEY_fp(FILE *fp, RSA *rsa); +# endif +# ifndef OPENSSL_NO_DSA +DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa); +int i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa); +DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa); +int i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa); +# endif +# ifndef OPENSSL_NO_EC +EC_KEY *d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey); +int i2d_EC_PUBKEY_fp(FILE *fp, EC_KEY *eckey); +EC_KEY *d2i_ECPrivateKey_fp(FILE *fp, EC_KEY **eckey); +int i2d_ECPrivateKey_fp(FILE *fp, EC_KEY *eckey); +# endif +X509_SIG *d2i_PKCS8_fp(FILE *fp, X509_SIG **p8); +int i2d_PKCS8_fp(FILE *fp, X509_SIG *p8); +PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, + PKCS8_PRIV_KEY_INFO **p8inf); +int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, PKCS8_PRIV_KEY_INFO *p8inf); +int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key); +int i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *pkey); +EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a); +int i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey); +EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a); +# endif + +X509 *d2i_X509_bio(BIO *bp, X509 **x509); +int i2d_X509_bio(BIO *bp, X509 *x509); +X509_CRL *d2i_X509_CRL_bio(BIO *bp, X509_CRL **crl); +int i2d_X509_CRL_bio(BIO *bp, X509_CRL *crl); +X509_REQ *d2i_X509_REQ_bio(BIO *bp, X509_REQ **req); +int i2d_X509_REQ_bio(BIO *bp, X509_REQ *req); +# ifndef OPENSSL_NO_RSA +RSA *d2i_RSAPrivateKey_bio(BIO *bp, RSA **rsa); +int i2d_RSAPrivateKey_bio(BIO *bp, RSA *rsa); +RSA *d2i_RSAPublicKey_bio(BIO *bp, RSA **rsa); +int i2d_RSAPublicKey_bio(BIO *bp, RSA *rsa); +RSA *d2i_RSA_PUBKEY_bio(BIO *bp, RSA **rsa); +int i2d_RSA_PUBKEY_bio(BIO *bp, RSA *rsa); +# endif +# ifndef OPENSSL_NO_DSA +DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa); +int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa); +DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa); +int i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa); +# endif +# ifndef OPENSSL_NO_EC +EC_KEY *d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **eckey); +int i2d_EC_PUBKEY_bio(BIO *bp, EC_KEY *eckey); +EC_KEY *d2i_ECPrivateKey_bio(BIO *bp, EC_KEY **eckey); +int i2d_ECPrivateKey_bio(BIO *bp, EC_KEY *eckey); +# endif +X509_SIG *d2i_PKCS8_bio(BIO *bp, X509_SIG **p8); +int i2d_PKCS8_bio(BIO *bp, X509_SIG *p8); +PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, + PKCS8_PRIV_KEY_INFO **p8inf); +int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, PKCS8_PRIV_KEY_INFO *p8inf); +int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key); +int i2d_PrivateKey_bio(BIO *bp, EVP_PKEY *pkey); +EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a); +int i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey); +EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a); + +X509 *X509_dup(X509 *x509); +X509_ATTRIBUTE *X509_ATTRIBUTE_dup(X509_ATTRIBUTE *xa); +X509_EXTENSION *X509_EXTENSION_dup(X509_EXTENSION *ex); +X509_CRL *X509_CRL_dup(X509_CRL *crl); +X509_REVOKED *X509_REVOKED_dup(X509_REVOKED *rev); +X509_REQ *X509_REQ_dup(X509_REQ *req); +X509_ALGOR *X509_ALGOR_dup(X509_ALGOR *xn); +int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype, + void *pval); +void X509_ALGOR_get0(const ASN1_OBJECT **paobj, int *pptype, + const void **ppval, const X509_ALGOR *algor); +void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md); +int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b); + +X509_NAME *X509_NAME_dup(X509_NAME *xn); +X509_NAME_ENTRY *X509_NAME_ENTRY_dup(X509_NAME_ENTRY *ne); + +int X509_cmp_time(const ASN1_TIME *s, time_t *t); +int X509_cmp_current_time(const ASN1_TIME *s); +ASN1_TIME *X509_time_adj(ASN1_TIME *s, long adj, time_t *t); +ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s, + int offset_day, long offset_sec, time_t *t); +ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj); + +const char *X509_get_default_cert_area(void); +const char *X509_get_default_cert_dir(void); +const char *X509_get_default_cert_file(void); +const char *X509_get_default_cert_dir_env(void); +const char *X509_get_default_cert_file_env(void); +const char *X509_get_default_private_dir(void); + +X509_REQ *X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md); +X509 *X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey); + +DECLARE_ASN1_FUNCTIONS(X509_ALGOR) +DECLARE_ASN1_ENCODE_FUNCTIONS(X509_ALGORS, X509_ALGORS, X509_ALGORS) +DECLARE_ASN1_FUNCTIONS(X509_VAL) + +DECLARE_ASN1_FUNCTIONS(X509_PUBKEY) + +int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey); +EVP_PKEY *X509_PUBKEY_get0(X509_PUBKEY *key); +EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key); +int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain); +long X509_get_pathlen(X509 *x); +int i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp); +EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length); +# ifndef OPENSSL_NO_RSA +int i2d_RSA_PUBKEY(RSA *a, unsigned char **pp); +RSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp, long length); +# endif +# ifndef OPENSSL_NO_DSA +int i2d_DSA_PUBKEY(DSA *a, unsigned char **pp); +DSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp, long length); +# endif +# ifndef OPENSSL_NO_EC +int i2d_EC_PUBKEY(EC_KEY *a, unsigned char **pp); +EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length); +# endif + +DECLARE_ASN1_FUNCTIONS(X509_SIG) +void X509_SIG_get0(const X509_SIG *sig, const X509_ALGOR **palg, + const ASN1_OCTET_STRING **pdigest); +void X509_SIG_getm(X509_SIG *sig, X509_ALGOR **palg, + ASN1_OCTET_STRING **pdigest); + +DECLARE_ASN1_FUNCTIONS(X509_REQ_INFO) +DECLARE_ASN1_FUNCTIONS(X509_REQ) + +DECLARE_ASN1_FUNCTIONS(X509_ATTRIBUTE) +X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value); + +DECLARE_ASN1_FUNCTIONS(X509_EXTENSION) +DECLARE_ASN1_ENCODE_FUNCTIONS(X509_EXTENSIONS, X509_EXTENSIONS, X509_EXTENSIONS) + +DECLARE_ASN1_FUNCTIONS(X509_NAME_ENTRY) + +DECLARE_ASN1_FUNCTIONS(X509_NAME) + +int X509_NAME_set(X509_NAME **xn, X509_NAME *name); + +DECLARE_ASN1_FUNCTIONS(X509_CINF) + +DECLARE_ASN1_FUNCTIONS(X509) +DECLARE_ASN1_FUNCTIONS(X509_CERT_AUX) + +#define X509_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509, l, p, newf, dupf, freef) +int X509_set_ex_data(X509 *r, int idx, void *arg); +void *X509_get_ex_data(X509 *r, int idx); +int i2d_X509_AUX(X509 *a, unsigned char **pp); +X509 *d2i_X509_AUX(X509 **a, const unsigned char **pp, long length); + +int i2d_re_X509_tbs(X509 *x, unsigned char **pp); + +int X509_SIG_INFO_get(const X509_SIG_INFO *siginf, int *mdnid, int *pknid, + int *secbits, uint32_t *flags); +void X509_SIG_INFO_set(X509_SIG_INFO *siginf, int mdnid, int pknid, + int secbits, uint32_t flags); + +int X509_get_signature_info(X509 *x, int *mdnid, int *pknid, int *secbits, + uint32_t *flags); + +void X509_get0_signature(const ASN1_BIT_STRING **psig, + const X509_ALGOR **palg, const X509 *x); +int X509_get_signature_nid(const X509 *x); + +int X509_trusted(const X509 *x); +int X509_alias_set1(X509 *x, const unsigned char *name, int len); +int X509_keyid_set1(X509 *x, const unsigned char *id, int len); +unsigned char *X509_alias_get0(X509 *x, int *len); +unsigned char *X509_keyid_get0(X509 *x, int *len); +int (*X509_TRUST_set_default(int (*trust) (int, X509 *, int))) (int, X509 *, + int); +int X509_TRUST_set(int *t, int trust); +int X509_add1_trust_object(X509 *x, const ASN1_OBJECT *obj); +int X509_add1_reject_object(X509 *x, const ASN1_OBJECT *obj); +void X509_trust_clear(X509 *x); +void X509_reject_clear(X509 *x); + +STACK_OF(ASN1_OBJECT) *X509_get0_trust_objects(X509 *x); +STACK_OF(ASN1_OBJECT) *X509_get0_reject_objects(X509 *x); + +DECLARE_ASN1_FUNCTIONS(X509_REVOKED) +DECLARE_ASN1_FUNCTIONS(X509_CRL_INFO) +DECLARE_ASN1_FUNCTIONS(X509_CRL) + +int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev); +int X509_CRL_get0_by_serial(X509_CRL *crl, + X509_REVOKED **ret, ASN1_INTEGER *serial); +int X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x); + +X509_PKEY *X509_PKEY_new(void); +void X509_PKEY_free(X509_PKEY *a); + +DECLARE_ASN1_FUNCTIONS(NETSCAPE_SPKI) +DECLARE_ASN1_FUNCTIONS(NETSCAPE_SPKAC) +DECLARE_ASN1_FUNCTIONS(NETSCAPE_CERT_SEQUENCE) + +X509_INFO *X509_INFO_new(void); +void X509_INFO_free(X509_INFO *a); +char *X509_NAME_oneline(const X509_NAME *a, char *buf, int size); + +int ASN1_verify(i2d_of_void *i2d, X509_ALGOR *algor1, + ASN1_BIT_STRING *signature, char *data, EVP_PKEY *pkey); + +int ASN1_digest(i2d_of_void *i2d, const EVP_MD *type, char *data, + unsigned char *md, unsigned int *len); + +int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1, + X509_ALGOR *algor2, ASN1_BIT_STRING *signature, + char *data, EVP_PKEY *pkey, const EVP_MD *type); + +int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *data, + unsigned char *md, unsigned int *len); + +int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *algor1, + ASN1_BIT_STRING *signature, void *data, EVP_PKEY *pkey); + +int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, + X509_ALGOR *algor2, ASN1_BIT_STRING *signature, void *data, + EVP_PKEY *pkey, const EVP_MD *type); +int ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1, + X509_ALGOR *algor2, ASN1_BIT_STRING *signature, + void *asn, EVP_MD_CTX *ctx); + +long X509_get_version(const X509 *x); +int X509_set_version(X509 *x, long version); +int X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial); +ASN1_INTEGER *X509_get_serialNumber(X509 *x); +const ASN1_INTEGER *X509_get0_serialNumber(const X509 *x); +int X509_set_issuer_name(X509 *x, X509_NAME *name); +X509_NAME *X509_get_issuer_name(const X509 *a); +int X509_set_subject_name(X509 *x, X509_NAME *name); +X509_NAME *X509_get_subject_name(const X509 *a); +const ASN1_TIME * X509_get0_notBefore(const X509 *x); +ASN1_TIME *X509_getm_notBefore(const X509 *x); +int X509_set1_notBefore(X509 *x, const ASN1_TIME *tm); +const ASN1_TIME *X509_get0_notAfter(const X509 *x); +ASN1_TIME *X509_getm_notAfter(const X509 *x); +int X509_set1_notAfter(X509 *x, const ASN1_TIME *tm); +int X509_set_pubkey(X509 *x, EVP_PKEY *pkey); +int X509_up_ref(X509 *x); +int X509_get_signature_type(const X509 *x); + +# if OPENSSL_API_COMPAT < 0x10100000L +# define X509_get_notBefore X509_getm_notBefore +# define X509_get_notAfter X509_getm_notAfter +# define X509_set_notBefore X509_set1_notBefore +# define X509_set_notAfter X509_set1_notAfter +#endif + + +/* + * This one is only used so that a binary form can output, as in + * i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &buf) + */ +X509_PUBKEY *X509_get_X509_PUBKEY(const X509 *x); +const STACK_OF(X509_EXTENSION) *X509_get0_extensions(const X509 *x); +void X509_get0_uids(const X509 *x, const ASN1_BIT_STRING **piuid, + const ASN1_BIT_STRING **psuid); +const X509_ALGOR *X509_get0_tbs_sigalg(const X509 *x); + +EVP_PKEY *X509_get0_pubkey(const X509 *x); +EVP_PKEY *X509_get_pubkey(X509 *x); +ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x); +int X509_certificate_type(const X509 *x, const EVP_PKEY *pubkey); + +long X509_REQ_get_version(const X509_REQ *req); +int X509_REQ_set_version(X509_REQ *x, long version); +X509_NAME *X509_REQ_get_subject_name(const X509_REQ *req); +int X509_REQ_set_subject_name(X509_REQ *req, X509_NAME *name); +void X509_REQ_get0_signature(const X509_REQ *req, const ASN1_BIT_STRING **psig, + const X509_ALGOR **palg); +int X509_REQ_get_signature_nid(const X509_REQ *req); +int i2d_re_X509_REQ_tbs(X509_REQ *req, unsigned char **pp); +int X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey); +EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *req); +EVP_PKEY *X509_REQ_get0_pubkey(X509_REQ *req); +X509_PUBKEY *X509_REQ_get_X509_PUBKEY(X509_REQ *req); +int X509_REQ_extension_nid(int nid); +int *X509_REQ_get_extension_nids(void); +void X509_REQ_set_extension_nids(int *nids); +STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req); +int X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts, + int nid); +int X509_REQ_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts); +int X509_REQ_get_attr_count(const X509_REQ *req); +int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, int lastpos); +int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, const ASN1_OBJECT *obj, + int lastpos); +X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc); +X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc); +int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr); +int X509_REQ_add1_attr_by_OBJ(X509_REQ *req, + const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, int len); +int X509_REQ_add1_attr_by_NID(X509_REQ *req, + int nid, int type, + const unsigned char *bytes, int len); +int X509_REQ_add1_attr_by_txt(X509_REQ *req, + const char *attrname, int type, + const unsigned char *bytes, int len); + +int X509_CRL_set_version(X509_CRL *x, long version); +int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name); +int X509_CRL_set1_lastUpdate(X509_CRL *x, const ASN1_TIME *tm); +int X509_CRL_set1_nextUpdate(X509_CRL *x, const ASN1_TIME *tm); +int X509_CRL_sort(X509_CRL *crl); +int X509_CRL_up_ref(X509_CRL *crl); + +# if OPENSSL_API_COMPAT < 0x10100000L +# define X509_CRL_set_lastUpdate X509_CRL_set1_lastUpdate +# define X509_CRL_set_nextUpdate X509_CRL_set1_nextUpdate +#endif + +long X509_CRL_get_version(const X509_CRL *crl); +const ASN1_TIME *X509_CRL_get0_lastUpdate(const X509_CRL *crl); +const ASN1_TIME *X509_CRL_get0_nextUpdate(const X509_CRL *crl); +DEPRECATEDIN_1_1_0(ASN1_TIME *X509_CRL_get_lastUpdate(X509_CRL *crl)) +DEPRECATEDIN_1_1_0(ASN1_TIME *X509_CRL_get_nextUpdate(X509_CRL *crl)) +X509_NAME *X509_CRL_get_issuer(const X509_CRL *crl); +const STACK_OF(X509_EXTENSION) *X509_CRL_get0_extensions(const X509_CRL *crl); +STACK_OF(X509_REVOKED) *X509_CRL_get_REVOKED(X509_CRL *crl); +void X509_CRL_get0_signature(const X509_CRL *crl, const ASN1_BIT_STRING **psig, + const X509_ALGOR **palg); +int X509_CRL_get_signature_nid(const X509_CRL *crl); +int i2d_re_X509_CRL_tbs(X509_CRL *req, unsigned char **pp); + +const ASN1_INTEGER *X509_REVOKED_get0_serialNumber(const X509_REVOKED *x); +int X509_REVOKED_set_serialNumber(X509_REVOKED *x, ASN1_INTEGER *serial); +const ASN1_TIME *X509_REVOKED_get0_revocationDate(const X509_REVOKED *x); +int X509_REVOKED_set_revocationDate(X509_REVOKED *r, ASN1_TIME *tm); +const STACK_OF(X509_EXTENSION) * +X509_REVOKED_get0_extensions(const X509_REVOKED *r); + +X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer, + EVP_PKEY *skey, const EVP_MD *md, unsigned int flags); + +int X509_REQ_check_private_key(X509_REQ *x509, EVP_PKEY *pkey); + +int X509_check_private_key(const X509 *x509, const EVP_PKEY *pkey); +int X509_chain_check_suiteb(int *perror_depth, + X509 *x, STACK_OF(X509) *chain, + unsigned long flags); +int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags); +STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain); + +int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b); +unsigned long X509_issuer_and_serial_hash(X509 *a); + +int X509_issuer_name_cmp(const X509 *a, const X509 *b); +unsigned long X509_issuer_name_hash(X509 *a); + +int X509_subject_name_cmp(const X509 *a, const X509 *b); +unsigned long X509_subject_name_hash(X509 *x); + +# ifndef OPENSSL_NO_MD5 +unsigned long X509_issuer_name_hash_old(X509 *a); +unsigned long X509_subject_name_hash_old(X509 *x); +# endif + +int X509_cmp(const X509 *a, const X509 *b); +int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b); +unsigned long X509_NAME_hash(X509_NAME *x); +unsigned long X509_NAME_hash_old(X509_NAME *x); + +int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b); +int X509_CRL_match(const X509_CRL *a, const X509_CRL *b); +int X509_aux_print(BIO *out, X509 *x, int indent); +# ifndef OPENSSL_NO_STDIO +int X509_print_ex_fp(FILE *bp, X509 *x, unsigned long nmflag, + unsigned long cflag); +int X509_print_fp(FILE *bp, X509 *x); +int X509_CRL_print_fp(FILE *bp, X509_CRL *x); +int X509_REQ_print_fp(FILE *bp, X509_REQ *req); +int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm, int indent, + unsigned long flags); +# endif + +int X509_NAME_print(BIO *bp, const X509_NAME *name, int obase); +int X509_NAME_print_ex(BIO *out, const X509_NAME *nm, int indent, + unsigned long flags); +int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflag, + unsigned long cflag); +int X509_print(BIO *bp, X509 *x); +int X509_ocspid_print(BIO *bp, X509 *x); +int X509_CRL_print_ex(BIO *out, X509_CRL *x, unsigned long nmflag); +int X509_CRL_print(BIO *bp, X509_CRL *x); +int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflag, + unsigned long cflag); +int X509_REQ_print(BIO *bp, X509_REQ *req); + +int X509_NAME_entry_count(const X509_NAME *name); +int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len); +int X509_NAME_get_text_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, + char *buf, int len); + +/* + * NOTE: you should be passing -1, not 0 as lastpos. The functions that use + * lastpos, search after that position on. + */ +int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos); +int X509_NAME_get_index_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, + int lastpos); +X509_NAME_ENTRY *X509_NAME_get_entry(const X509_NAME *name, int loc); +X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc); +int X509_NAME_add_entry(X509_NAME *name, const X509_NAME_ENTRY *ne, + int loc, int set); +int X509_NAME_add_entry_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, int len, int loc, + int set); +int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type, + const unsigned char *bytes, int len, int loc, + int set); +X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne, + const char *field, int type, + const unsigned char *bytes, + int len); +X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid, + int type, + const unsigned char *bytes, + int len); +int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type, + const unsigned char *bytes, int len, int loc, + int set); +X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne, + const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, + int len); +int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, const ASN1_OBJECT *obj); +int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type, + const unsigned char *bytes, int len); +ASN1_OBJECT *X509_NAME_ENTRY_get_object(const X509_NAME_ENTRY *ne); +ASN1_STRING * X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY *ne); +int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne); + +int X509_NAME_get0_der(X509_NAME *nm, const unsigned char **pder, + size_t *pderlen); + +int X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x); +int X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x, + int nid, int lastpos); +int X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *x, + const ASN1_OBJECT *obj, int lastpos); +int X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *x, + int crit, int lastpos); +X509_EXTENSION *X509v3_get_ext(const STACK_OF(X509_EXTENSION) *x, int loc); +X509_EXTENSION *X509v3_delete_ext(STACK_OF(X509_EXTENSION) *x, int loc); +STACK_OF(X509_EXTENSION) *X509v3_add_ext(STACK_OF(X509_EXTENSION) **x, + X509_EXTENSION *ex, int loc); + +int X509_get_ext_count(const X509 *x); +int X509_get_ext_by_NID(const X509 *x, int nid, int lastpos); +int X509_get_ext_by_OBJ(const X509 *x, const ASN1_OBJECT *obj, int lastpos); +int X509_get_ext_by_critical(const X509 *x, int crit, int lastpos); +X509_EXTENSION *X509_get_ext(const X509 *x, int loc); +X509_EXTENSION *X509_delete_ext(X509 *x, int loc); +int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc); +void *X509_get_ext_d2i(const X509 *x, int nid, int *crit, int *idx); +int X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit, + unsigned long flags); + +int X509_CRL_get_ext_count(const X509_CRL *x); +int X509_CRL_get_ext_by_NID(const X509_CRL *x, int nid, int lastpos); +int X509_CRL_get_ext_by_OBJ(const X509_CRL *x, const ASN1_OBJECT *obj, + int lastpos); +int X509_CRL_get_ext_by_critical(const X509_CRL *x, int crit, int lastpos); +X509_EXTENSION *X509_CRL_get_ext(const X509_CRL *x, int loc); +X509_EXTENSION *X509_CRL_delete_ext(X509_CRL *x, int loc); +int X509_CRL_add_ext(X509_CRL *x, X509_EXTENSION *ex, int loc); +void *X509_CRL_get_ext_d2i(const X509_CRL *x, int nid, int *crit, int *idx); +int X509_CRL_add1_ext_i2d(X509_CRL *x, int nid, void *value, int crit, + unsigned long flags); + +int X509_REVOKED_get_ext_count(const X509_REVOKED *x); +int X509_REVOKED_get_ext_by_NID(const X509_REVOKED *x, int nid, int lastpos); +int X509_REVOKED_get_ext_by_OBJ(const X509_REVOKED *x, const ASN1_OBJECT *obj, + int lastpos); +int X509_REVOKED_get_ext_by_critical(const X509_REVOKED *x, int crit, + int lastpos); +X509_EXTENSION *X509_REVOKED_get_ext(const X509_REVOKED *x, int loc); +X509_EXTENSION *X509_REVOKED_delete_ext(X509_REVOKED *x, int loc); +int X509_REVOKED_add_ext(X509_REVOKED *x, X509_EXTENSION *ex, int loc); +void *X509_REVOKED_get_ext_d2i(const X509_REVOKED *x, int nid, int *crit, + int *idx); +int X509_REVOKED_add1_ext_i2d(X509_REVOKED *x, int nid, void *value, int crit, + unsigned long flags); + +X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, + int nid, int crit, + ASN1_OCTET_STRING *data); +X509_EXTENSION *X509_EXTENSION_create_by_OBJ(X509_EXTENSION **ex, + const ASN1_OBJECT *obj, int crit, + ASN1_OCTET_STRING *data); +int X509_EXTENSION_set_object(X509_EXTENSION *ex, const ASN1_OBJECT *obj); +int X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit); +int X509_EXTENSION_set_data(X509_EXTENSION *ex, ASN1_OCTET_STRING *data); +ASN1_OBJECT *X509_EXTENSION_get_object(X509_EXTENSION *ex); +ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ne); +int X509_EXTENSION_get_critical(const X509_EXTENSION *ex); + +int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x); +int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid, + int lastpos); +int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk, + const ASN1_OBJECT *obj, int lastpos); +X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc); +X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc); +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x, + X509_ATTRIBUTE *attr); +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE) + **x, const ASN1_OBJECT *obj, + int type, + const unsigned char *bytes, + int len); +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE) + **x, int nid, int type, + const unsigned char *bytes, + int len); +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) + **x, const char *attrname, + int type, + const unsigned char *bytes, + int len); +void *X509at_get0_data_by_OBJ(STACK_OF(X509_ATTRIBUTE) *x, + const ASN1_OBJECT *obj, int lastpos, int type); +X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid, + int atrtype, const void *data, + int len); +X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr, + const ASN1_OBJECT *obj, + int atrtype, const void *data, + int len); +X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr, + const char *atrname, int type, + const unsigned char *bytes, + int len); +int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj); +int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, + const void *data, int len); +void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx, int atrtype, + void *data); +int X509_ATTRIBUTE_count(const X509_ATTRIBUTE *attr); +ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr); +ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx); + +int EVP_PKEY_get_attr_count(const EVP_PKEY *key); +int EVP_PKEY_get_attr_by_NID(const EVP_PKEY *key, int nid, int lastpos); +int EVP_PKEY_get_attr_by_OBJ(const EVP_PKEY *key, const ASN1_OBJECT *obj, + int lastpos); +X509_ATTRIBUTE *EVP_PKEY_get_attr(const EVP_PKEY *key, int loc); +X509_ATTRIBUTE *EVP_PKEY_delete_attr(EVP_PKEY *key, int loc); +int EVP_PKEY_add1_attr(EVP_PKEY *key, X509_ATTRIBUTE *attr); +int EVP_PKEY_add1_attr_by_OBJ(EVP_PKEY *key, + const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, int len); +int EVP_PKEY_add1_attr_by_NID(EVP_PKEY *key, + int nid, int type, + const unsigned char *bytes, int len); +int EVP_PKEY_add1_attr_by_txt(EVP_PKEY *key, + const char *attrname, int type, + const unsigned char *bytes, int len); + +int X509_verify_cert(X509_STORE_CTX *ctx); + +/* lookup a cert from a X509 STACK */ +X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, X509_NAME *name, + ASN1_INTEGER *serial); +X509 *X509_find_by_subject(STACK_OF(X509) *sk, X509_NAME *name); + +DECLARE_ASN1_FUNCTIONS(PBEPARAM) +DECLARE_ASN1_FUNCTIONS(PBE2PARAM) +DECLARE_ASN1_FUNCTIONS(PBKDF2PARAM) +#ifndef OPENSSL_NO_SCRYPT +DECLARE_ASN1_FUNCTIONS(SCRYPT_PARAMS) +#endif + +int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter, + const unsigned char *salt, int saltlen); + +X509_ALGOR *PKCS5_pbe_set(int alg, int iter, + const unsigned char *salt, int saltlen); +X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter, + unsigned char *salt, int saltlen); +X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter, + unsigned char *salt, int saltlen, + unsigned char *aiv, int prf_nid); + +#ifndef OPENSSL_NO_SCRYPT +X509_ALGOR *PKCS5_pbe2_set_scrypt(const EVP_CIPHER *cipher, + const unsigned char *salt, int saltlen, + unsigned char *aiv, uint64_t N, uint64_t r, + uint64_t p); +#endif + +X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen, + int prf_nid, int keylen); + +/* PKCS#8 utilities */ + +DECLARE_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO) + +EVP_PKEY *EVP_PKCS82PKEY(const PKCS8_PRIV_KEY_INFO *p8); +PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey); + +int PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj, + int version, int ptype, void *pval, + unsigned char *penc, int penclen); +int PKCS8_pkey_get0(const ASN1_OBJECT **ppkalg, + const unsigned char **pk, int *ppklen, + const X509_ALGOR **pa, const PKCS8_PRIV_KEY_INFO *p8); + +const STACK_OF(X509_ATTRIBUTE) * +PKCS8_pkey_get0_attrs(const PKCS8_PRIV_KEY_INFO *p8); +int PKCS8_pkey_add1_attr_by_NID(PKCS8_PRIV_KEY_INFO *p8, int nid, int type, + const unsigned char *bytes, int len); + +int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *aobj, + int ptype, void *pval, + unsigned char *penc, int penclen); +int X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg, + const unsigned char **pk, int *ppklen, + X509_ALGOR **pa, X509_PUBKEY *pub); + +int X509_check_trust(X509 *x, int id, int flags); +int X509_TRUST_get_count(void); +X509_TRUST *X509_TRUST_get0(int idx); +int X509_TRUST_get_by_id(int id); +int X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int), + const char *name, int arg1, void *arg2); +void X509_TRUST_cleanup(void); +int X509_TRUST_get_flags(const X509_TRUST *xp); +char *X509_TRUST_get0_name(const X509_TRUST *xp); +int X509_TRUST_get_trust(const X509_TRUST *xp); + +# ifdef __cplusplus +} +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/x509_vfy.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/x509_vfy.h new file mode 100644 index 000000000..adb8bce7c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/x509_vfy.h @@ -0,0 +1,628 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_X509_VFY_H +# define HEADER_X509_VFY_H + +/* + * Protect against recursion, x509.h and x509_vfy.h each include the other. + */ +# ifndef HEADER_X509_H +# include +# endif + +# include +# include +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/*- +SSL_CTX -> X509_STORE + -> X509_LOOKUP + ->X509_LOOKUP_METHOD + -> X509_LOOKUP + ->X509_LOOKUP_METHOD + +SSL -> X509_STORE_CTX + ->X509_STORE + +The X509_STORE holds the tables etc for verification stuff. +A X509_STORE_CTX is used while validating a single certificate. +The X509_STORE has X509_LOOKUPs for looking up certs. +The X509_STORE then calls a function to actually verify the +certificate chain. +*/ + +typedef enum { + X509_LU_NONE = 0, + X509_LU_X509, X509_LU_CRL +} X509_LOOKUP_TYPE; + +#if OPENSSL_API_COMPAT < 0x10100000L +#define X509_LU_RETRY -1 +#define X509_LU_FAIL 0 +#endif + +DEFINE_STACK_OF(X509_LOOKUP) +DEFINE_STACK_OF(X509_OBJECT) +DEFINE_STACK_OF(X509_VERIFY_PARAM) + +int X509_STORE_set_depth(X509_STORE *store, int depth); + +typedef int (*X509_STORE_CTX_verify_cb)(int, X509_STORE_CTX *); +typedef int (*X509_STORE_CTX_verify_fn)(X509_STORE_CTX *); +typedef int (*X509_STORE_CTX_get_issuer_fn)(X509 **issuer, + X509_STORE_CTX *ctx, X509 *x); +typedef int (*X509_STORE_CTX_check_issued_fn)(X509_STORE_CTX *ctx, + X509 *x, X509 *issuer); +typedef int (*X509_STORE_CTX_check_revocation_fn)(X509_STORE_CTX *ctx); +typedef int (*X509_STORE_CTX_get_crl_fn)(X509_STORE_CTX *ctx, + X509_CRL **crl, X509 *x); +typedef int (*X509_STORE_CTX_check_crl_fn)(X509_STORE_CTX *ctx, X509_CRL *crl); +typedef int (*X509_STORE_CTX_cert_crl_fn)(X509_STORE_CTX *ctx, + X509_CRL *crl, X509 *x); +typedef int (*X509_STORE_CTX_check_policy_fn)(X509_STORE_CTX *ctx); +typedef STACK_OF(X509) *(*X509_STORE_CTX_lookup_certs_fn)(X509_STORE_CTX *ctx, + X509_NAME *nm); +typedef STACK_OF(X509_CRL) *(*X509_STORE_CTX_lookup_crls_fn)(X509_STORE_CTX *ctx, + X509_NAME *nm); +typedef int (*X509_STORE_CTX_cleanup_fn)(X509_STORE_CTX *ctx); + + +void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth); + +# define X509_STORE_CTX_set_app_data(ctx,data) \ + X509_STORE_CTX_set_ex_data(ctx,0,data) +# define X509_STORE_CTX_get_app_data(ctx) \ + X509_STORE_CTX_get_ex_data(ctx,0) + +# define X509_L_FILE_LOAD 1 +# define X509_L_ADD_DIR 2 + +# define X509_LOOKUP_load_file(x,name,type) \ + X509_LOOKUP_ctrl((x),X509_L_FILE_LOAD,(name),(long)(type),NULL) + +# define X509_LOOKUP_add_dir(x,name,type) \ + X509_LOOKUP_ctrl((x),X509_L_ADD_DIR,(name),(long)(type),NULL) + +# define X509_V_OK 0 +# define X509_V_ERR_UNSPECIFIED 1 +# define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT 2 +# define X509_V_ERR_UNABLE_TO_GET_CRL 3 +# define X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE 4 +# define X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE 5 +# define X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY 6 +# define X509_V_ERR_CERT_SIGNATURE_FAILURE 7 +# define X509_V_ERR_CRL_SIGNATURE_FAILURE 8 +# define X509_V_ERR_CERT_NOT_YET_VALID 9 +# define X509_V_ERR_CERT_HAS_EXPIRED 10 +# define X509_V_ERR_CRL_NOT_YET_VALID 11 +# define X509_V_ERR_CRL_HAS_EXPIRED 12 +# define X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD 13 +# define X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD 14 +# define X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD 15 +# define X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD 16 +# define X509_V_ERR_OUT_OF_MEM 17 +# define X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT 18 +# define X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN 19 +# define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY 20 +# define X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE 21 +# define X509_V_ERR_CERT_CHAIN_TOO_LONG 22 +# define X509_V_ERR_CERT_REVOKED 23 +# define X509_V_ERR_INVALID_CA 24 +# define X509_V_ERR_PATH_LENGTH_EXCEEDED 25 +# define X509_V_ERR_INVALID_PURPOSE 26 +# define X509_V_ERR_CERT_UNTRUSTED 27 +# define X509_V_ERR_CERT_REJECTED 28 +/* These are 'informational' when looking for issuer cert */ +# define X509_V_ERR_SUBJECT_ISSUER_MISMATCH 29 +# define X509_V_ERR_AKID_SKID_MISMATCH 30 +# define X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH 31 +# define X509_V_ERR_KEYUSAGE_NO_CERTSIGN 32 +# define X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER 33 +# define X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION 34 +# define X509_V_ERR_KEYUSAGE_NO_CRL_SIGN 35 +# define X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION 36 +# define X509_V_ERR_INVALID_NON_CA 37 +# define X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED 38 +# define X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE 39 +# define X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED 40 +# define X509_V_ERR_INVALID_EXTENSION 41 +# define X509_V_ERR_INVALID_POLICY_EXTENSION 42 +# define X509_V_ERR_NO_EXPLICIT_POLICY 43 +# define X509_V_ERR_DIFFERENT_CRL_SCOPE 44 +# define X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE 45 +# define X509_V_ERR_UNNESTED_RESOURCE 46 +# define X509_V_ERR_PERMITTED_VIOLATION 47 +# define X509_V_ERR_EXCLUDED_VIOLATION 48 +# define X509_V_ERR_SUBTREE_MINMAX 49 +/* The application is not happy */ +# define X509_V_ERR_APPLICATION_VERIFICATION 50 +# define X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE 51 +# define X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX 52 +# define X509_V_ERR_UNSUPPORTED_NAME_SYNTAX 53 +# define X509_V_ERR_CRL_PATH_VALIDATION_ERROR 54 +/* Another issuer check debug option */ +# define X509_V_ERR_PATH_LOOP 55 +/* Suite B mode algorithm violation */ +# define X509_V_ERR_SUITE_B_INVALID_VERSION 56 +# define X509_V_ERR_SUITE_B_INVALID_ALGORITHM 57 +# define X509_V_ERR_SUITE_B_INVALID_CURVE 58 +# define X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM 59 +# define X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED 60 +# define X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256 61 +/* Host, email and IP check errors */ +# define X509_V_ERR_HOSTNAME_MISMATCH 62 +# define X509_V_ERR_EMAIL_MISMATCH 63 +# define X509_V_ERR_IP_ADDRESS_MISMATCH 64 +/* DANE TLSA errors */ +# define X509_V_ERR_DANE_NO_MATCH 65 +/* security level errors */ +# define X509_V_ERR_EE_KEY_TOO_SMALL 66 +# define X509_V_ERR_CA_KEY_TOO_SMALL 67 +# define X509_V_ERR_CA_MD_TOO_WEAK 68 +/* Caller error */ +# define X509_V_ERR_INVALID_CALL 69 +/* Issuer lookup error */ +# define X509_V_ERR_STORE_LOOKUP 70 +/* Certificate transparency */ +# define X509_V_ERR_NO_VALID_SCTS 71 + +# define X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION 72 +/* OCSP status errors */ +# define X509_V_ERR_OCSP_VERIFY_NEEDED 73 /* Need OCSP verification */ +# define X509_V_ERR_OCSP_VERIFY_FAILED 74 /* Couldn't verify cert through OCSP */ +# define X509_V_ERR_OCSP_CERT_UNKNOWN 75 /* Certificate wasn't recognized by the OCSP responder */ + +/* Certificate verify flags */ + +# if OPENSSL_API_COMPAT < 0x10100000L +# define X509_V_FLAG_CB_ISSUER_CHECK 0x0 /* Deprecated */ +# endif +/* Use check time instead of current time */ +# define X509_V_FLAG_USE_CHECK_TIME 0x2 +/* Lookup CRLs */ +# define X509_V_FLAG_CRL_CHECK 0x4 +/* Lookup CRLs for whole chain */ +# define X509_V_FLAG_CRL_CHECK_ALL 0x8 +/* Ignore unhandled critical extensions */ +# define X509_V_FLAG_IGNORE_CRITICAL 0x10 +/* Disable workarounds for broken certificates */ +# define X509_V_FLAG_X509_STRICT 0x20 +/* Enable proxy certificate validation */ +# define X509_V_FLAG_ALLOW_PROXY_CERTS 0x40 +/* Enable policy checking */ +# define X509_V_FLAG_POLICY_CHECK 0x80 +/* Policy variable require-explicit-policy */ +# define X509_V_FLAG_EXPLICIT_POLICY 0x100 +/* Policy variable inhibit-any-policy */ +# define X509_V_FLAG_INHIBIT_ANY 0x200 +/* Policy variable inhibit-policy-mapping */ +# define X509_V_FLAG_INHIBIT_MAP 0x400 +/* Notify callback that policy is OK */ +# define X509_V_FLAG_NOTIFY_POLICY 0x800 +/* Extended CRL features such as indirect CRLs, alternate CRL signing keys */ +# define X509_V_FLAG_EXTENDED_CRL_SUPPORT 0x1000 +/* Delta CRL support */ +# define X509_V_FLAG_USE_DELTAS 0x2000 +/* Check self-signed CA signature */ +# define X509_V_FLAG_CHECK_SS_SIGNATURE 0x4000 +/* Use trusted store first */ +# define X509_V_FLAG_TRUSTED_FIRST 0x8000 +/* Suite B 128 bit only mode: not normally used */ +# define X509_V_FLAG_SUITEB_128_LOS_ONLY 0x10000 +/* Suite B 192 bit only mode */ +# define X509_V_FLAG_SUITEB_192_LOS 0x20000 +/* Suite B 128 bit mode allowing 192 bit algorithms */ +# define X509_V_FLAG_SUITEB_128_LOS 0x30000 +/* Allow partial chains if at least one certificate is in trusted store */ +# define X509_V_FLAG_PARTIAL_CHAIN 0x80000 +/* + * If the initial chain is not trusted, do not attempt to build an alternative + * chain. Alternate chain checking was introduced in 1.1.0. Setting this flag + * will force the behaviour to match that of previous versions. + */ +# define X509_V_FLAG_NO_ALT_CHAINS 0x100000 +/* Do not check certificate/CRL validity against current time */ +# define X509_V_FLAG_NO_CHECK_TIME 0x200000 + +# define X509_VP_FLAG_DEFAULT 0x1 +# define X509_VP_FLAG_OVERWRITE 0x2 +# define X509_VP_FLAG_RESET_FLAGS 0x4 +# define X509_VP_FLAG_LOCKED 0x8 +# define X509_VP_FLAG_ONCE 0x10 + +/* Internal use: mask of policy related options */ +# define X509_V_FLAG_POLICY_MASK (X509_V_FLAG_POLICY_CHECK \ + | X509_V_FLAG_EXPLICIT_POLICY \ + | X509_V_FLAG_INHIBIT_ANY \ + | X509_V_FLAG_INHIBIT_MAP) + +int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type, + X509_NAME *name); +X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, + X509_LOOKUP_TYPE type, + X509_NAME *name); +X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, + X509_OBJECT *x); +int X509_OBJECT_up_ref_count(X509_OBJECT *a); +X509_OBJECT *X509_OBJECT_new(void); +void X509_OBJECT_free(X509_OBJECT *a); +X509_LOOKUP_TYPE X509_OBJECT_get_type(const X509_OBJECT *a); +X509 *X509_OBJECT_get0_X509(const X509_OBJECT *a); +int X509_OBJECT_set1_X509(X509_OBJECT *a, X509 *obj); +X509_CRL *X509_OBJECT_get0_X509_CRL(X509_OBJECT *a); +int X509_OBJECT_set1_X509_CRL(X509_OBJECT *a, X509_CRL *obj); +X509_STORE *X509_STORE_new(void); +void X509_STORE_free(X509_STORE *v); +int X509_STORE_lock(X509_STORE *ctx); +int X509_STORE_unlock(X509_STORE *ctx); +int X509_STORE_up_ref(X509_STORE *v); +STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *v); + +STACK_OF(X509) *X509_STORE_CTX_get1_certs(X509_STORE_CTX *st, X509_NAME *nm); +STACK_OF(X509_CRL) *X509_STORE_CTX_get1_crls(X509_STORE_CTX *st, X509_NAME *nm); +int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags); +int X509_STORE_set_purpose(X509_STORE *ctx, int purpose); +int X509_STORE_set_trust(X509_STORE *ctx, int trust); +int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *pm); +X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *ctx); + +void X509_STORE_set_verify(X509_STORE *ctx, X509_STORE_CTX_verify_fn verify); +#define X509_STORE_set_verify_func(ctx, func) \ + X509_STORE_set_verify((ctx),(func)) +void X509_STORE_CTX_set_verify(X509_STORE_CTX *ctx, + X509_STORE_CTX_verify_fn verify); +X509_STORE_CTX_verify_fn X509_STORE_get_verify(X509_STORE *ctx); +void X509_STORE_set_verify_cb(X509_STORE *ctx, + X509_STORE_CTX_verify_cb verify_cb); +# define X509_STORE_set_verify_cb_func(ctx,func) \ + X509_STORE_set_verify_cb((ctx),(func)) +X509_STORE_CTX_verify_cb X509_STORE_get_verify_cb(X509_STORE *ctx); +void X509_STORE_set_get_issuer(X509_STORE *ctx, + X509_STORE_CTX_get_issuer_fn get_issuer); +X509_STORE_CTX_get_issuer_fn X509_STORE_get_get_issuer(X509_STORE *ctx); +void X509_STORE_set_check_issued(X509_STORE *ctx, + X509_STORE_CTX_check_issued_fn check_issued); +X509_STORE_CTX_check_issued_fn X509_STORE_get_check_issued(X509_STORE *ctx); +void X509_STORE_set_check_revocation(X509_STORE *ctx, + X509_STORE_CTX_check_revocation_fn check_revocation); +X509_STORE_CTX_check_revocation_fn X509_STORE_get_check_revocation(X509_STORE *ctx); +void X509_STORE_set_get_crl(X509_STORE *ctx, + X509_STORE_CTX_get_crl_fn get_crl); +X509_STORE_CTX_get_crl_fn X509_STORE_get_get_crl(X509_STORE *ctx); +void X509_STORE_set_check_crl(X509_STORE *ctx, + X509_STORE_CTX_check_crl_fn check_crl); +X509_STORE_CTX_check_crl_fn X509_STORE_get_check_crl(X509_STORE *ctx); +void X509_STORE_set_cert_crl(X509_STORE *ctx, + X509_STORE_CTX_cert_crl_fn cert_crl); +X509_STORE_CTX_cert_crl_fn X509_STORE_get_cert_crl(X509_STORE *ctx); +void X509_STORE_set_check_policy(X509_STORE *ctx, + X509_STORE_CTX_check_policy_fn check_policy); +X509_STORE_CTX_check_policy_fn X509_STORE_get_check_policy(X509_STORE *ctx); +void X509_STORE_set_lookup_certs(X509_STORE *ctx, + X509_STORE_CTX_lookup_certs_fn lookup_certs); +X509_STORE_CTX_lookup_certs_fn X509_STORE_get_lookup_certs(X509_STORE *ctx); +void X509_STORE_set_lookup_crls(X509_STORE *ctx, + X509_STORE_CTX_lookup_crls_fn lookup_crls); +#define X509_STORE_set_lookup_crls_cb(ctx, func) \ + X509_STORE_set_lookup_crls((ctx), (func)) +X509_STORE_CTX_lookup_crls_fn X509_STORE_get_lookup_crls(X509_STORE *ctx); +void X509_STORE_set_cleanup(X509_STORE *ctx, + X509_STORE_CTX_cleanup_fn cleanup); +X509_STORE_CTX_cleanup_fn X509_STORE_get_cleanup(X509_STORE *ctx); + +#define X509_STORE_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE, l, p, newf, dupf, freef) +int X509_STORE_set_ex_data(X509_STORE *ctx, int idx, void *data); +void *X509_STORE_get_ex_data(X509_STORE *ctx, int idx); + +X509_STORE_CTX *X509_STORE_CTX_new(void); + +int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x); + +void X509_STORE_CTX_free(X509_STORE_CTX *ctx); +int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, + X509 *x509, STACK_OF(X509) *chain); +void X509_STORE_CTX_set0_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk); +void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx); + +X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx); +X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx); +STACK_OF(X509)* X509_STORE_CTX_get0_untrusted(X509_STORE_CTX *ctx); +void X509_STORE_CTX_set0_untrusted(X509_STORE_CTX *ctx, STACK_OF(X509) *sk); +void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx, + X509_STORE_CTX_verify_cb verify); +X509_STORE_CTX_verify_cb X509_STORE_CTX_get_verify_cb(X509_STORE_CTX *ctx); +X509_STORE_CTX_verify_fn X509_STORE_CTX_get_verify(X509_STORE_CTX *ctx); +X509_STORE_CTX_get_issuer_fn X509_STORE_CTX_get_get_issuer(X509_STORE_CTX *ctx); +X509_STORE_CTX_check_issued_fn X509_STORE_CTX_get_check_issued(X509_STORE_CTX *ctx); +X509_STORE_CTX_check_revocation_fn X509_STORE_CTX_get_check_revocation(X509_STORE_CTX *ctx); +X509_STORE_CTX_get_crl_fn X509_STORE_CTX_get_get_crl(X509_STORE_CTX *ctx); +X509_STORE_CTX_check_crl_fn X509_STORE_CTX_get_check_crl(X509_STORE_CTX *ctx); +X509_STORE_CTX_cert_crl_fn X509_STORE_CTX_get_cert_crl(X509_STORE_CTX *ctx); +X509_STORE_CTX_check_policy_fn X509_STORE_CTX_get_check_policy(X509_STORE_CTX *ctx); +X509_STORE_CTX_lookup_certs_fn X509_STORE_CTX_get_lookup_certs(X509_STORE_CTX *ctx); +X509_STORE_CTX_lookup_crls_fn X509_STORE_CTX_get_lookup_crls(X509_STORE_CTX *ctx); +X509_STORE_CTX_cleanup_fn X509_STORE_CTX_get_cleanup(X509_STORE_CTX *ctx); + +#if OPENSSL_API_COMPAT < 0x10100000L +# define X509_STORE_CTX_get_chain X509_STORE_CTX_get0_chain +# define X509_STORE_CTX_set_chain X509_STORE_CTX_set0_untrusted +# define X509_STORE_CTX_trusted_stack X509_STORE_CTX_set0_trusted_stack +# define X509_STORE_get_by_subject X509_STORE_CTX_get_by_subject +# define X509_STORE_get1_certs X509_STORE_CTX_get1_certs +# define X509_STORE_get1_crls X509_STORE_CTX_get1_crls +/* the following macro is misspelled; use X509_STORE_get1_certs instead */ +# define X509_STORE_get1_cert X509_STORE_CTX_get1_certs +/* the following macro is misspelled; use X509_STORE_get1_crls instead */ +# define X509_STORE_get1_crl X509_STORE_CTX_get1_crls +#endif + +X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m); +X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void); +X509_LOOKUP_METHOD *X509_LOOKUP_file(void); + +typedef int (*X509_LOOKUP_ctrl_fn)(X509_LOOKUP *ctx, int cmd, const char *argc, + long argl, char **ret); +typedef int (*X509_LOOKUP_get_by_subject_fn)(X509_LOOKUP *ctx, + X509_LOOKUP_TYPE type, + X509_NAME *name, + X509_OBJECT *ret); +typedef int (*X509_LOOKUP_get_by_issuer_serial_fn)(X509_LOOKUP *ctx, + X509_LOOKUP_TYPE type, + X509_NAME *name, + ASN1_INTEGER *serial, + X509_OBJECT *ret); +typedef int (*X509_LOOKUP_get_by_fingerprint_fn)(X509_LOOKUP *ctx, + X509_LOOKUP_TYPE type, + const unsigned char* bytes, + int len, + X509_OBJECT *ret); +typedef int (*X509_LOOKUP_get_by_alias_fn)(X509_LOOKUP *ctx, + X509_LOOKUP_TYPE type, + const char *str, + int len, + X509_OBJECT *ret); + +X509_LOOKUP_METHOD *X509_LOOKUP_meth_new(const char *name); +void X509_LOOKUP_meth_free(X509_LOOKUP_METHOD *method); + +int X509_LOOKUP_meth_set_new_item(X509_LOOKUP_METHOD *method, + int (*new_item) (X509_LOOKUP *ctx)); +int (*X509_LOOKUP_meth_get_new_item(const X509_LOOKUP_METHOD* method)) + (X509_LOOKUP *ctx); + +int X509_LOOKUP_meth_set_free(X509_LOOKUP_METHOD *method, + void (*free_fn) (X509_LOOKUP *ctx)); +void (*X509_LOOKUP_meth_get_free(const X509_LOOKUP_METHOD* method)) + (X509_LOOKUP *ctx); + +int X509_LOOKUP_meth_set_init(X509_LOOKUP_METHOD *method, + int (*init) (X509_LOOKUP *ctx)); +int (*X509_LOOKUP_meth_get_init(const X509_LOOKUP_METHOD* method)) + (X509_LOOKUP *ctx); + +int X509_LOOKUP_meth_set_shutdown(X509_LOOKUP_METHOD *method, + int (*shutdown) (X509_LOOKUP *ctx)); +int (*X509_LOOKUP_meth_get_shutdown(const X509_LOOKUP_METHOD* method)) + (X509_LOOKUP *ctx); + +int X509_LOOKUP_meth_set_ctrl(X509_LOOKUP_METHOD *method, + X509_LOOKUP_ctrl_fn ctrl_fn); +X509_LOOKUP_ctrl_fn X509_LOOKUP_meth_get_ctrl(const X509_LOOKUP_METHOD *method); + +int X509_LOOKUP_meth_set_get_by_subject(X509_LOOKUP_METHOD *method, + X509_LOOKUP_get_by_subject_fn fn); +X509_LOOKUP_get_by_subject_fn X509_LOOKUP_meth_get_get_by_subject( + const X509_LOOKUP_METHOD *method); + +int X509_LOOKUP_meth_set_get_by_issuer_serial(X509_LOOKUP_METHOD *method, + X509_LOOKUP_get_by_issuer_serial_fn fn); +X509_LOOKUP_get_by_issuer_serial_fn X509_LOOKUP_meth_get_get_by_issuer_serial( + const X509_LOOKUP_METHOD *method); + +int X509_LOOKUP_meth_set_get_by_fingerprint(X509_LOOKUP_METHOD *method, + X509_LOOKUP_get_by_fingerprint_fn fn); +X509_LOOKUP_get_by_fingerprint_fn X509_LOOKUP_meth_get_get_by_fingerprint( + const X509_LOOKUP_METHOD *method); + +int X509_LOOKUP_meth_set_get_by_alias(X509_LOOKUP_METHOD *method, + X509_LOOKUP_get_by_alias_fn fn); +X509_LOOKUP_get_by_alias_fn X509_LOOKUP_meth_get_get_by_alias( + const X509_LOOKUP_METHOD *method); + + +int X509_STORE_add_cert(X509_STORE *ctx, X509 *x); +int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x); + +int X509_STORE_CTX_get_by_subject(X509_STORE_CTX *vs, X509_LOOKUP_TYPE type, + X509_NAME *name, X509_OBJECT *ret); +X509_OBJECT *X509_STORE_CTX_get_obj_by_subject(X509_STORE_CTX *vs, + X509_LOOKUP_TYPE type, + X509_NAME *name); + +int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, + long argl, char **ret); + +int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type); +int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type); +int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type); + +X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method); +void X509_LOOKUP_free(X509_LOOKUP *ctx); +int X509_LOOKUP_init(X509_LOOKUP *ctx); +int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + X509_NAME *name, X509_OBJECT *ret); +int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + X509_NAME *name, ASN1_INTEGER *serial, + X509_OBJECT *ret); +int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + const unsigned char *bytes, int len, + X509_OBJECT *ret); +int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + const char *str, int len, X509_OBJECT *ret); +int X509_LOOKUP_set_method_data(X509_LOOKUP *ctx, void *data); +void *X509_LOOKUP_get_method_data(const X509_LOOKUP *ctx); +X509_STORE *X509_LOOKUP_get_store(const X509_LOOKUP *ctx); +int X509_LOOKUP_shutdown(X509_LOOKUP *ctx); + +int X509_STORE_load_locations(X509_STORE *ctx, + const char *file, const char *dir); +int X509_STORE_set_default_paths(X509_STORE *ctx); + +#define X509_STORE_CTX_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE_CTX, l, p, newf, dupf, freef) +int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data); +void *X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx); +int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx); +void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int s); +int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx); +void X509_STORE_CTX_set_error_depth(X509_STORE_CTX *ctx, int depth); +X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx); +void X509_STORE_CTX_set_current_cert(X509_STORE_CTX *ctx, X509 *x); +X509 *X509_STORE_CTX_get0_current_issuer(X509_STORE_CTX *ctx); +X509_CRL *X509_STORE_CTX_get0_current_crl(X509_STORE_CTX *ctx); +X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(X509_STORE_CTX *ctx); +STACK_OF(X509) *X509_STORE_CTX_get0_chain(X509_STORE_CTX *ctx); +STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx); +void X509_STORE_CTX_set_cert(X509_STORE_CTX *c, X509 *x); +void X509_STORE_CTX_set0_verified_chain(X509_STORE_CTX *c, STACK_OF(X509) *sk); +void X509_STORE_CTX_set0_crls(X509_STORE_CTX *c, STACK_OF(X509_CRL) *sk); +int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose); +int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust); +int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose, + int purpose, int trust); +void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags); +void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags, + time_t t); + +X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx); +int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx); +int X509_STORE_CTX_get_num_untrusted(X509_STORE_CTX *ctx); + +X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx); +void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param); +int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name); + +/* + * Bridge opacity barrier between libcrypt and libssl, also needed to support + * offline testing in test/danetest.c + */ +void X509_STORE_CTX_set0_dane(X509_STORE_CTX *ctx, SSL_DANE *dane); +#define DANE_FLAG_NO_DANE_EE_NAMECHECKS (1L << 0) + +/* X509_VERIFY_PARAM functions */ + +X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void); +void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param); +int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *to, + const X509_VERIFY_PARAM *from); +int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to, + const X509_VERIFY_PARAM *from); +int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name); +int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, + unsigned long flags); +int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param, + unsigned long flags); +unsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param); +int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose); +int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust); +void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth); +void X509_VERIFY_PARAM_set_auth_level(X509_VERIFY_PARAM *param, int auth_level); +time_t X509_VERIFY_PARAM_get_time(const X509_VERIFY_PARAM *param); +void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t); +int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param, + ASN1_OBJECT *policy); +int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param, + STACK_OF(ASN1_OBJECT) *policies); + +int X509_VERIFY_PARAM_set_inh_flags(X509_VERIFY_PARAM *param, + uint32_t flags); +uint32_t X509_VERIFY_PARAM_get_inh_flags(const X509_VERIFY_PARAM *param); + +int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param, + const char *name, size_t namelen); +int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param, + const char *name, size_t namelen); +void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param, + unsigned int flags); +unsigned int X509_VERIFY_PARAM_get_hostflags(const X509_VERIFY_PARAM *param); +char *X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *); +void X509_VERIFY_PARAM_move_peername(X509_VERIFY_PARAM *, X509_VERIFY_PARAM *); +int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, + const char *email, size_t emaillen); +int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, + const unsigned char *ip, size_t iplen); +int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, + const char *ipasc); + +int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param); +int X509_VERIFY_PARAM_get_auth_level(const X509_VERIFY_PARAM *param); +const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param); + +int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param); +int X509_VERIFY_PARAM_get_count(void); +const X509_VERIFY_PARAM *X509_VERIFY_PARAM_get0(int id); +const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name); +void X509_VERIFY_PARAM_table_cleanup(void); + +/* Non positive return values are errors */ +#define X509_PCY_TREE_FAILURE -2 /* Failure to satisfy explicit policy */ +#define X509_PCY_TREE_INVALID -1 /* Inconsistent or invalid extensions */ +#define X509_PCY_TREE_INTERNAL 0 /* Internal error, most likely malloc */ + +/* + * Positive return values form a bit mask, all but the first are internal to + * the library and don't appear in results from X509_policy_check(). + */ +#define X509_PCY_TREE_VALID 1 /* The policy tree is valid */ +#define X509_PCY_TREE_EMPTY 2 /* The policy tree is empty */ +#define X509_PCY_TREE_EXPLICIT 4 /* Explicit policy required */ + +int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy, + STACK_OF(X509) *certs, + STACK_OF(ASN1_OBJECT) *policy_oids, unsigned int flags); + +void X509_policy_tree_free(X509_POLICY_TREE *tree); + +int X509_policy_tree_level_count(const X509_POLICY_TREE *tree); +X509_POLICY_LEVEL *X509_policy_tree_get0_level(const X509_POLICY_TREE *tree, + int i); + +STACK_OF(X509_POLICY_NODE) *X509_policy_tree_get0_policies(const + X509_POLICY_TREE + *tree); + +STACK_OF(X509_POLICY_NODE) *X509_policy_tree_get0_user_policies(const + X509_POLICY_TREE + *tree); + +int X509_policy_level_node_count(X509_POLICY_LEVEL *level); + +X509_POLICY_NODE *X509_policy_level_get0_node(X509_POLICY_LEVEL *level, + int i); + +const ASN1_OBJECT *X509_policy_node_get0_policy(const X509_POLICY_NODE *node); + +STACK_OF(POLICYQUALINFO) *X509_policy_node_get0_qualifiers(const + X509_POLICY_NODE + *node); +const X509_POLICY_NODE *X509_policy_node_get0_parent(const X509_POLICY_NODE + *node); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/x509err.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/x509err.h new file mode 100644 index 000000000..b1d6a8709 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/x509err.h @@ -0,0 +1,125 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_X509ERR_H +# define HEADER_X509ERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_X509_strings(void); + +/* + * X509 function codes. + */ +# define X509_F_ADD_CERT_DIR 100 +# define X509_F_BUILD_CHAIN 106 +# define X509_F_BY_FILE_CTRL 101 +# define X509_F_CHECK_NAME_CONSTRAINTS 149 +# define X509_F_CHECK_POLICY 145 +# define X509_F_DANE_I2D 107 +# define X509_F_DIR_CTRL 102 +# define X509_F_GET_CERT_BY_SUBJECT 103 +# define X509_F_I2D_X509_AUX 151 +# define X509_F_LOOKUP_CERTS_SK 152 +# define X509_F_NETSCAPE_SPKI_B64_DECODE 129 +# define X509_F_NETSCAPE_SPKI_B64_ENCODE 130 +# define X509_F_NEW_DIR 153 +# define X509_F_X509AT_ADD1_ATTR 135 +# define X509_F_X509V3_ADD_EXT 104 +# define X509_F_X509_ATTRIBUTE_CREATE_BY_NID 136 +# define X509_F_X509_ATTRIBUTE_CREATE_BY_OBJ 137 +# define X509_F_X509_ATTRIBUTE_CREATE_BY_TXT 140 +# define X509_F_X509_ATTRIBUTE_GET0_DATA 139 +# define X509_F_X509_ATTRIBUTE_SET1_DATA 138 +# define X509_F_X509_CHECK_PRIVATE_KEY 128 +# define X509_F_X509_CRL_DIFF 105 +# define X509_F_X509_CRL_METHOD_NEW 154 +# define X509_F_X509_CRL_PRINT_FP 147 +# define X509_F_X509_EXTENSION_CREATE_BY_NID 108 +# define X509_F_X509_EXTENSION_CREATE_BY_OBJ 109 +# define X509_F_X509_GET_PUBKEY_PARAMETERS 110 +# define X509_F_X509_LOAD_CERT_CRL_FILE 132 +# define X509_F_X509_LOAD_CERT_FILE 111 +# define X509_F_X509_LOAD_CRL_FILE 112 +# define X509_F_X509_LOOKUP_METH_NEW 160 +# define X509_F_X509_LOOKUP_NEW 155 +# define X509_F_X509_NAME_ADD_ENTRY 113 +# define X509_F_X509_NAME_CANON 156 +# define X509_F_X509_NAME_ENTRY_CREATE_BY_NID 114 +# define X509_F_X509_NAME_ENTRY_CREATE_BY_TXT 131 +# define X509_F_X509_NAME_ENTRY_SET_OBJECT 115 +# define X509_F_X509_NAME_ONELINE 116 +# define X509_F_X509_NAME_PRINT 117 +# define X509_F_X509_OBJECT_NEW 150 +# define X509_F_X509_PRINT_EX_FP 118 +# define X509_F_X509_PUBKEY_DECODE 148 +# define X509_F_X509_PUBKEY_GET0 119 +# define X509_F_X509_PUBKEY_SET 120 +# define X509_F_X509_REQ_CHECK_PRIVATE_KEY 144 +# define X509_F_X509_REQ_PRINT_EX 121 +# define X509_F_X509_REQ_PRINT_FP 122 +# define X509_F_X509_REQ_TO_X509 123 +# define X509_F_X509_STORE_ADD_CERT 124 +# define X509_F_X509_STORE_ADD_CRL 125 +# define X509_F_X509_STORE_ADD_LOOKUP 157 +# define X509_F_X509_STORE_CTX_GET1_ISSUER 146 +# define X509_F_X509_STORE_CTX_INIT 143 +# define X509_F_X509_STORE_CTX_NEW 142 +# define X509_F_X509_STORE_CTX_PURPOSE_INHERIT 134 +# define X509_F_X509_STORE_NEW 158 +# define X509_F_X509_TO_X509_REQ 126 +# define X509_F_X509_TRUST_ADD 133 +# define X509_F_X509_TRUST_SET 141 +# define X509_F_X509_VERIFY_CERT 127 +# define X509_F_X509_VERIFY_PARAM_NEW 159 + +/* + * X509 reason codes. + */ +# define X509_R_AKID_MISMATCH 110 +# define X509_R_BAD_SELECTOR 133 +# define X509_R_BAD_X509_FILETYPE 100 +# define X509_R_BASE64_DECODE_ERROR 118 +# define X509_R_CANT_CHECK_DH_KEY 114 +# define X509_R_CERT_ALREADY_IN_HASH_TABLE 101 +# define X509_R_CRL_ALREADY_DELTA 127 +# define X509_R_CRL_VERIFY_FAILURE 131 +# define X509_R_IDP_MISMATCH 128 +# define X509_R_INVALID_DIRECTORY 113 +# define X509_R_INVALID_FIELD_NAME 119 +# define X509_R_INVALID_TRUST 123 +# define X509_R_ISSUER_MISMATCH 129 +# define X509_R_KEY_TYPE_MISMATCH 115 +# define X509_R_KEY_VALUES_MISMATCH 116 +# define X509_R_LOADING_CERT_DIR 103 +# define X509_R_LOADING_DEFAULTS 104 +# define X509_R_METHOD_NOT_SUPPORTED 124 +# define X509_R_NAME_TOO_LONG 134 +# define X509_R_NEWER_CRL_NOT_NEWER 132 +# define X509_R_NO_CERTIFICATE_FOUND 135 +# define X509_R_NO_CERTIFICATE_OR_CRL_FOUND 136 +# define X509_R_NO_CERT_SET_FOR_US_TO_VERIFY 105 +# define X509_R_NO_CRL_FOUND 137 +# define X509_R_NO_CRL_NUMBER 130 +# define X509_R_PUBLIC_KEY_DECODE_ERROR 125 +# define X509_R_PUBLIC_KEY_ENCODE_ERROR 126 +# define X509_R_SHOULD_RETRY 106 +# define X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN 107 +# define X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY 108 +# define X509_R_UNKNOWN_KEY_TYPE 117 +# define X509_R_UNKNOWN_NID 109 +# define X509_R_UNKNOWN_PURPOSE_ID 121 +# define X509_R_UNKNOWN_TRUST_ID 120 +# define X509_R_UNSUPPORTED_ALGORITHM 111 +# define X509_R_WRONG_LOOKUP_TYPE 112 +# define X509_R_WRONG_TYPE 122 + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/x509v3.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/x509v3.h new file mode 100644 index 000000000..fe1791c68 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/x509v3.h @@ -0,0 +1,935 @@ +/* + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_X509V3_H +# define HEADER_X509V3_H + +# include +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Forward reference */ +struct v3_ext_method; +struct v3_ext_ctx; + +/* Useful typedefs */ + +typedef void *(*X509V3_EXT_NEW)(void); +typedef void (*X509V3_EXT_FREE) (void *); +typedef void *(*X509V3_EXT_D2I)(void *, const unsigned char **, long); +typedef int (*X509V3_EXT_I2D) (void *, unsigned char **); +typedef STACK_OF(CONF_VALUE) * + (*X509V3_EXT_I2V) (const struct v3_ext_method *method, void *ext, + STACK_OF(CONF_VALUE) *extlist); +typedef void *(*X509V3_EXT_V2I)(const struct v3_ext_method *method, + struct v3_ext_ctx *ctx, + STACK_OF(CONF_VALUE) *values); +typedef char *(*X509V3_EXT_I2S)(const struct v3_ext_method *method, + void *ext); +typedef void *(*X509V3_EXT_S2I)(const struct v3_ext_method *method, + struct v3_ext_ctx *ctx, const char *str); +typedef int (*X509V3_EXT_I2R) (const struct v3_ext_method *method, void *ext, + BIO *out, int indent); +typedef void *(*X509V3_EXT_R2I)(const struct v3_ext_method *method, + struct v3_ext_ctx *ctx, const char *str); + +/* V3 extension structure */ + +struct v3_ext_method { + int ext_nid; + int ext_flags; +/* If this is set the following four fields are ignored */ + ASN1_ITEM_EXP *it; +/* Old style ASN1 calls */ + X509V3_EXT_NEW ext_new; + X509V3_EXT_FREE ext_free; + X509V3_EXT_D2I d2i; + X509V3_EXT_I2D i2d; +/* The following pair is used for string extensions */ + X509V3_EXT_I2S i2s; + X509V3_EXT_S2I s2i; +/* The following pair is used for multi-valued extensions */ + X509V3_EXT_I2V i2v; + X509V3_EXT_V2I v2i; +/* The following are used for raw extensions */ + X509V3_EXT_I2R i2r; + X509V3_EXT_R2I r2i; + void *usr_data; /* Any extension specific data */ +}; + +typedef struct X509V3_CONF_METHOD_st { + char *(*get_string) (void *db, const char *section, const char *value); + STACK_OF(CONF_VALUE) *(*get_section) (void *db, const char *section); + void (*free_string) (void *db, char *string); + void (*free_section) (void *db, STACK_OF(CONF_VALUE) *section); +} X509V3_CONF_METHOD; + +/* Context specific info */ +struct v3_ext_ctx { +# define CTX_TEST 0x1 +# define X509V3_CTX_REPLACE 0x2 + int flags; + X509 *issuer_cert; + X509 *subject_cert; + X509_REQ *subject_req; + X509_CRL *crl; + X509V3_CONF_METHOD *db_meth; + void *db; +/* Maybe more here */ +}; + +typedef struct v3_ext_method X509V3_EXT_METHOD; + +DEFINE_STACK_OF(X509V3_EXT_METHOD) + +/* ext_flags values */ +# define X509V3_EXT_DYNAMIC 0x1 +# define X509V3_EXT_CTX_DEP 0x2 +# define X509V3_EXT_MULTILINE 0x4 + +typedef BIT_STRING_BITNAME ENUMERATED_NAMES; + +typedef struct BASIC_CONSTRAINTS_st { + int ca; + ASN1_INTEGER *pathlen; +} BASIC_CONSTRAINTS; + +typedef struct PKEY_USAGE_PERIOD_st { + ASN1_GENERALIZEDTIME *notBefore; + ASN1_GENERALIZEDTIME *notAfter; +} PKEY_USAGE_PERIOD; + +typedef struct otherName_st { + ASN1_OBJECT *type_id; + ASN1_TYPE *value; +} OTHERNAME; + +typedef struct EDIPartyName_st { + ASN1_STRING *nameAssigner; + ASN1_STRING *partyName; +} EDIPARTYNAME; + +typedef struct GENERAL_NAME_st { +# define GEN_OTHERNAME 0 +# define GEN_EMAIL 1 +# define GEN_DNS 2 +# define GEN_X400 3 +# define GEN_DIRNAME 4 +# define GEN_EDIPARTY 5 +# define GEN_URI 6 +# define GEN_IPADD 7 +# define GEN_RID 8 + int type; + union { + char *ptr; + OTHERNAME *otherName; /* otherName */ + ASN1_IA5STRING *rfc822Name; + ASN1_IA5STRING *dNSName; + ASN1_TYPE *x400Address; + X509_NAME *directoryName; + EDIPARTYNAME *ediPartyName; + ASN1_IA5STRING *uniformResourceIdentifier; + ASN1_OCTET_STRING *iPAddress; + ASN1_OBJECT *registeredID; + /* Old names */ + ASN1_OCTET_STRING *ip; /* iPAddress */ + X509_NAME *dirn; /* dirn */ + ASN1_IA5STRING *ia5; /* rfc822Name, dNSName, + * uniformResourceIdentifier */ + ASN1_OBJECT *rid; /* registeredID */ + ASN1_TYPE *other; /* x400Address */ + } d; +} GENERAL_NAME; + +typedef struct ACCESS_DESCRIPTION_st { + ASN1_OBJECT *method; + GENERAL_NAME *location; +} ACCESS_DESCRIPTION; + +typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; + +typedef STACK_OF(ASN1_OBJECT) EXTENDED_KEY_USAGE; + +typedef STACK_OF(ASN1_INTEGER) TLS_FEATURE; + +DEFINE_STACK_OF(GENERAL_NAME) +typedef STACK_OF(GENERAL_NAME) GENERAL_NAMES; +DEFINE_STACK_OF(GENERAL_NAMES) + +DEFINE_STACK_OF(ACCESS_DESCRIPTION) + +typedef struct DIST_POINT_NAME_st { + int type; + union { + GENERAL_NAMES *fullname; + STACK_OF(X509_NAME_ENTRY) *relativename; + } name; +/* If relativename then this contains the full distribution point name */ + X509_NAME *dpname; +} DIST_POINT_NAME; +/* All existing reasons */ +# define CRLDP_ALL_REASONS 0x807f + +# define CRL_REASON_NONE -1 +# define CRL_REASON_UNSPECIFIED 0 +# define CRL_REASON_KEY_COMPROMISE 1 +# define CRL_REASON_CA_COMPROMISE 2 +# define CRL_REASON_AFFILIATION_CHANGED 3 +# define CRL_REASON_SUPERSEDED 4 +# define CRL_REASON_CESSATION_OF_OPERATION 5 +# define CRL_REASON_CERTIFICATE_HOLD 6 +# define CRL_REASON_REMOVE_FROM_CRL 8 +# define CRL_REASON_PRIVILEGE_WITHDRAWN 9 +# define CRL_REASON_AA_COMPROMISE 10 + +struct DIST_POINT_st { + DIST_POINT_NAME *distpoint; + ASN1_BIT_STRING *reasons; + GENERAL_NAMES *CRLissuer; + int dp_reasons; +}; + +typedef STACK_OF(DIST_POINT) CRL_DIST_POINTS; + +DEFINE_STACK_OF(DIST_POINT) + +struct AUTHORITY_KEYID_st { + ASN1_OCTET_STRING *keyid; + GENERAL_NAMES *issuer; + ASN1_INTEGER *serial; +}; + +/* Strong extranet structures */ + +typedef struct SXNET_ID_st { + ASN1_INTEGER *zone; + ASN1_OCTET_STRING *user; +} SXNETID; + +DEFINE_STACK_OF(SXNETID) + +typedef struct SXNET_st { + ASN1_INTEGER *version; + STACK_OF(SXNETID) *ids; +} SXNET; + +typedef struct NOTICEREF_st { + ASN1_STRING *organization; + STACK_OF(ASN1_INTEGER) *noticenos; +} NOTICEREF; + +typedef struct USERNOTICE_st { + NOTICEREF *noticeref; + ASN1_STRING *exptext; +} USERNOTICE; + +typedef struct POLICYQUALINFO_st { + ASN1_OBJECT *pqualid; + union { + ASN1_IA5STRING *cpsuri; + USERNOTICE *usernotice; + ASN1_TYPE *other; + } d; +} POLICYQUALINFO; + +DEFINE_STACK_OF(POLICYQUALINFO) + +typedef struct POLICYINFO_st { + ASN1_OBJECT *policyid; + STACK_OF(POLICYQUALINFO) *qualifiers; +} POLICYINFO; + +typedef STACK_OF(POLICYINFO) CERTIFICATEPOLICIES; + +DEFINE_STACK_OF(POLICYINFO) + +typedef struct POLICY_MAPPING_st { + ASN1_OBJECT *issuerDomainPolicy; + ASN1_OBJECT *subjectDomainPolicy; +} POLICY_MAPPING; + +DEFINE_STACK_OF(POLICY_MAPPING) + +typedef STACK_OF(POLICY_MAPPING) POLICY_MAPPINGS; + +typedef struct GENERAL_SUBTREE_st { + GENERAL_NAME *base; + ASN1_INTEGER *minimum; + ASN1_INTEGER *maximum; +} GENERAL_SUBTREE; + +DEFINE_STACK_OF(GENERAL_SUBTREE) + +struct NAME_CONSTRAINTS_st { + STACK_OF(GENERAL_SUBTREE) *permittedSubtrees; + STACK_OF(GENERAL_SUBTREE) *excludedSubtrees; +}; + +typedef struct POLICY_CONSTRAINTS_st { + ASN1_INTEGER *requireExplicitPolicy; + ASN1_INTEGER *inhibitPolicyMapping; +} POLICY_CONSTRAINTS; + +/* Proxy certificate structures, see RFC 3820 */ +typedef struct PROXY_POLICY_st { + ASN1_OBJECT *policyLanguage; + ASN1_OCTET_STRING *policy; +} PROXY_POLICY; + +typedef struct PROXY_CERT_INFO_EXTENSION_st { + ASN1_INTEGER *pcPathLengthConstraint; + PROXY_POLICY *proxyPolicy; +} PROXY_CERT_INFO_EXTENSION; + +DECLARE_ASN1_FUNCTIONS(PROXY_POLICY) +DECLARE_ASN1_FUNCTIONS(PROXY_CERT_INFO_EXTENSION) + +struct ISSUING_DIST_POINT_st { + DIST_POINT_NAME *distpoint; + int onlyuser; + int onlyCA; + ASN1_BIT_STRING *onlysomereasons; + int indirectCRL; + int onlyattr; +}; + +/* Values in idp_flags field */ +/* IDP present */ +# define IDP_PRESENT 0x1 +/* IDP values inconsistent */ +# define IDP_INVALID 0x2 +/* onlyuser true */ +# define IDP_ONLYUSER 0x4 +/* onlyCA true */ +# define IDP_ONLYCA 0x8 +/* onlyattr true */ +# define IDP_ONLYATTR 0x10 +/* indirectCRL true */ +# define IDP_INDIRECT 0x20 +/* onlysomereasons present */ +# define IDP_REASONS 0x40 + +# define X509V3_conf_err(val) ERR_add_error_data(6, \ + "section:", (val)->section, \ + ",name:", (val)->name, ",value:", (val)->value) + +# define X509V3_set_ctx_test(ctx) \ + X509V3_set_ctx(ctx, NULL, NULL, NULL, NULL, CTX_TEST) +# define X509V3_set_ctx_nodb(ctx) (ctx)->db = NULL; + +# define EXT_BITSTRING(nid, table) { nid, 0, ASN1_ITEM_ref(ASN1_BIT_STRING), \ + 0,0,0,0, \ + 0,0, \ + (X509V3_EXT_I2V)i2v_ASN1_BIT_STRING, \ + (X509V3_EXT_V2I)v2i_ASN1_BIT_STRING, \ + NULL, NULL, \ + table} + +# define EXT_IA5STRING(nid) { nid, 0, ASN1_ITEM_ref(ASN1_IA5STRING), \ + 0,0,0,0, \ + (X509V3_EXT_I2S)i2s_ASN1_IA5STRING, \ + (X509V3_EXT_S2I)s2i_ASN1_IA5STRING, \ + 0,0,0,0, \ + NULL} + +# define EXT_END { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + +/* X509_PURPOSE stuff */ + +# define EXFLAG_BCONS 0x1 +# define EXFLAG_KUSAGE 0x2 +# define EXFLAG_XKUSAGE 0x4 +# define EXFLAG_NSCERT 0x8 + +# define EXFLAG_CA 0x10 +/* Really self issued not necessarily self signed */ +# define EXFLAG_SI 0x20 +# define EXFLAG_V1 0x40 +# define EXFLAG_INVALID 0x80 +/* EXFLAG_SET is set to indicate that some values have been precomputed */ +# define EXFLAG_SET 0x100 +# define EXFLAG_CRITICAL 0x200 +# define EXFLAG_PROXY 0x400 + +# define EXFLAG_INVALID_POLICY 0x800 +# define EXFLAG_FRESHEST 0x1000 +/* Self signed */ +# define EXFLAG_SS 0x2000 + +# define KU_DIGITAL_SIGNATURE 0x0080 +# define KU_NON_REPUDIATION 0x0040 +# define KU_KEY_ENCIPHERMENT 0x0020 +# define KU_DATA_ENCIPHERMENT 0x0010 +# define KU_KEY_AGREEMENT 0x0008 +# define KU_KEY_CERT_SIGN 0x0004 +# define KU_CRL_SIGN 0x0002 +# define KU_ENCIPHER_ONLY 0x0001 +# define KU_DECIPHER_ONLY 0x8000 + +# define NS_SSL_CLIENT 0x80 +# define NS_SSL_SERVER 0x40 +# define NS_SMIME 0x20 +# define NS_OBJSIGN 0x10 +# define NS_SSL_CA 0x04 +# define NS_SMIME_CA 0x02 +# define NS_OBJSIGN_CA 0x01 +# define NS_ANY_CA (NS_SSL_CA|NS_SMIME_CA|NS_OBJSIGN_CA) + +# define XKU_SSL_SERVER 0x1 +# define XKU_SSL_CLIENT 0x2 +# define XKU_SMIME 0x4 +# define XKU_CODE_SIGN 0x8 +# define XKU_SGC 0x10 +# define XKU_OCSP_SIGN 0x20 +# define XKU_TIMESTAMP 0x40 +# define XKU_DVCS 0x80 +# define XKU_ANYEKU 0x100 + +# define X509_PURPOSE_DYNAMIC 0x1 +# define X509_PURPOSE_DYNAMIC_NAME 0x2 + +typedef struct x509_purpose_st { + int purpose; + int trust; /* Default trust ID */ + int flags; + int (*check_purpose) (const struct x509_purpose_st *, const X509 *, int); + char *name; + char *sname; + void *usr_data; +} X509_PURPOSE; + +# define X509_PURPOSE_SSL_CLIENT 1 +# define X509_PURPOSE_SSL_SERVER 2 +# define X509_PURPOSE_NS_SSL_SERVER 3 +# define X509_PURPOSE_SMIME_SIGN 4 +# define X509_PURPOSE_SMIME_ENCRYPT 5 +# define X509_PURPOSE_CRL_SIGN 6 +# define X509_PURPOSE_ANY 7 +# define X509_PURPOSE_OCSP_HELPER 8 +# define X509_PURPOSE_TIMESTAMP_SIGN 9 + +# define X509_PURPOSE_MIN 1 +# define X509_PURPOSE_MAX 9 + +/* Flags for X509V3_EXT_print() */ + +# define X509V3_EXT_UNKNOWN_MASK (0xfL << 16) +/* Return error for unknown extensions */ +# define X509V3_EXT_DEFAULT 0 +/* Print error for unknown extensions */ +# define X509V3_EXT_ERROR_UNKNOWN (1L << 16) +/* ASN1 parse unknown extensions */ +# define X509V3_EXT_PARSE_UNKNOWN (2L << 16) +/* BIO_dump unknown extensions */ +# define X509V3_EXT_DUMP_UNKNOWN (3L << 16) + +/* Flags for X509V3_add1_i2d */ + +# define X509V3_ADD_OP_MASK 0xfL +# define X509V3_ADD_DEFAULT 0L +# define X509V3_ADD_APPEND 1L +# define X509V3_ADD_REPLACE 2L +# define X509V3_ADD_REPLACE_EXISTING 3L +# define X509V3_ADD_KEEP_EXISTING 4L +# define X509V3_ADD_DELETE 5L +# define X509V3_ADD_SILENT 0x10 + +DEFINE_STACK_OF(X509_PURPOSE) + +DECLARE_ASN1_FUNCTIONS(BASIC_CONSTRAINTS) + +DECLARE_ASN1_FUNCTIONS(SXNET) +DECLARE_ASN1_FUNCTIONS(SXNETID) + +int SXNET_add_id_asc(SXNET **psx, const char *zone, const char *user, int userlen); +int SXNET_add_id_ulong(SXNET **psx, unsigned long lzone, const char *user, + int userlen); +int SXNET_add_id_INTEGER(SXNET **psx, ASN1_INTEGER *izone, const char *user, + int userlen); + +ASN1_OCTET_STRING *SXNET_get_id_asc(SXNET *sx, const char *zone); +ASN1_OCTET_STRING *SXNET_get_id_ulong(SXNET *sx, unsigned long lzone); +ASN1_OCTET_STRING *SXNET_get_id_INTEGER(SXNET *sx, ASN1_INTEGER *zone); + +DECLARE_ASN1_FUNCTIONS(AUTHORITY_KEYID) + +DECLARE_ASN1_FUNCTIONS(PKEY_USAGE_PERIOD) + +DECLARE_ASN1_FUNCTIONS(GENERAL_NAME) +GENERAL_NAME *GENERAL_NAME_dup(GENERAL_NAME *a); +int GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b); + +ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval); +STACK_OF(CONF_VALUE) *i2v_ASN1_BIT_STRING(X509V3_EXT_METHOD *method, + ASN1_BIT_STRING *bits, + STACK_OF(CONF_VALUE) *extlist); +char *i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method, ASN1_IA5STRING *ia5); +ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, const char *str); + +STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, + GENERAL_NAME *gen, + STACK_OF(CONF_VALUE) *ret); +int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen); + +DECLARE_ASN1_FUNCTIONS(GENERAL_NAMES) + +STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method, + GENERAL_NAMES *gen, + STACK_OF(CONF_VALUE) *extlist); +GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); + +DECLARE_ASN1_FUNCTIONS(OTHERNAME) +DECLARE_ASN1_FUNCTIONS(EDIPARTYNAME) +int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b); +void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value); +void *GENERAL_NAME_get0_value(GENERAL_NAME *a, int *ptype); +int GENERAL_NAME_set0_othername(GENERAL_NAME *gen, + ASN1_OBJECT *oid, ASN1_TYPE *value); +int GENERAL_NAME_get0_otherName(GENERAL_NAME *gen, + ASN1_OBJECT **poid, ASN1_TYPE **pvalue); + +char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, + const ASN1_OCTET_STRING *ia5); +ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, const char *str); + +DECLARE_ASN1_FUNCTIONS(EXTENDED_KEY_USAGE) +int i2a_ACCESS_DESCRIPTION(BIO *bp, const ACCESS_DESCRIPTION *a); + +DECLARE_ASN1_ALLOC_FUNCTIONS(TLS_FEATURE) + +DECLARE_ASN1_FUNCTIONS(CERTIFICATEPOLICIES) +DECLARE_ASN1_FUNCTIONS(POLICYINFO) +DECLARE_ASN1_FUNCTIONS(POLICYQUALINFO) +DECLARE_ASN1_FUNCTIONS(USERNOTICE) +DECLARE_ASN1_FUNCTIONS(NOTICEREF) + +DECLARE_ASN1_FUNCTIONS(CRL_DIST_POINTS) +DECLARE_ASN1_FUNCTIONS(DIST_POINT) +DECLARE_ASN1_FUNCTIONS(DIST_POINT_NAME) +DECLARE_ASN1_FUNCTIONS(ISSUING_DIST_POINT) + +int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname); + +int NAME_CONSTRAINTS_check(X509 *x, NAME_CONSTRAINTS *nc); +int NAME_CONSTRAINTS_check_CN(X509 *x, NAME_CONSTRAINTS *nc); + +DECLARE_ASN1_FUNCTIONS(ACCESS_DESCRIPTION) +DECLARE_ASN1_FUNCTIONS(AUTHORITY_INFO_ACCESS) + +DECLARE_ASN1_ITEM(POLICY_MAPPING) +DECLARE_ASN1_ALLOC_FUNCTIONS(POLICY_MAPPING) +DECLARE_ASN1_ITEM(POLICY_MAPPINGS) + +DECLARE_ASN1_ITEM(GENERAL_SUBTREE) +DECLARE_ASN1_ALLOC_FUNCTIONS(GENERAL_SUBTREE) + +DECLARE_ASN1_ITEM(NAME_CONSTRAINTS) +DECLARE_ASN1_ALLOC_FUNCTIONS(NAME_CONSTRAINTS) + +DECLARE_ASN1_ALLOC_FUNCTIONS(POLICY_CONSTRAINTS) +DECLARE_ASN1_ITEM(POLICY_CONSTRAINTS) + +GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out, + const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, int gen_type, + const char *value, int is_nc); + +# ifdef HEADER_CONF_H +GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, CONF_VALUE *cnf); +GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out, + const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, CONF_VALUE *cnf, + int is_nc); +void X509V3_conf_free(CONF_VALUE *val); + +X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid, + const char *value); +X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, const char *name, + const char *value); +int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, const char *section, + STACK_OF(X509_EXTENSION) **sk); +int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section, + X509 *cert); +int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section, + X509_REQ *req); +int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section, + X509_CRL *crl); + +X509_EXTENSION *X509V3_EXT_conf_nid(LHASH_OF(CONF_VALUE) *conf, + X509V3_CTX *ctx, int ext_nid, + const char *value); +X509_EXTENSION *X509V3_EXT_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, + const char *name, const char *value); +int X509V3_EXT_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, + const char *section, X509 *cert); +int X509V3_EXT_REQ_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, + const char *section, X509_REQ *req); +int X509V3_EXT_CRL_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, + const char *section, X509_CRL *crl); + +int X509V3_add_value_bool_nf(const char *name, int asn1_bool, + STACK_OF(CONF_VALUE) **extlist); +int X509V3_get_value_bool(const CONF_VALUE *value, int *asn1_bool); +int X509V3_get_value_int(const CONF_VALUE *value, ASN1_INTEGER **aint); +void X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf); +void X509V3_set_conf_lhash(X509V3_CTX *ctx, LHASH_OF(CONF_VALUE) *lhash); +# endif + +char *X509V3_get_string(X509V3_CTX *ctx, const char *name, const char *section); +STACK_OF(CONF_VALUE) *X509V3_get_section(X509V3_CTX *ctx, const char *section); +void X509V3_string_free(X509V3_CTX *ctx, char *str); +void X509V3_section_free(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section); +void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subject, + X509_REQ *req, X509_CRL *crl, int flags); + +int X509V3_add_value(const char *name, const char *value, + STACK_OF(CONF_VALUE) **extlist); +int X509V3_add_value_uchar(const char *name, const unsigned char *value, + STACK_OF(CONF_VALUE) **extlist); +int X509V3_add_value_bool(const char *name, int asn1_bool, + STACK_OF(CONF_VALUE) **extlist); +int X509V3_add_value_int(const char *name, const ASN1_INTEGER *aint, + STACK_OF(CONF_VALUE) **extlist); +char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *meth, const ASN1_INTEGER *aint); +ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *meth, const char *value); +char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *meth, const ASN1_ENUMERATED *aint); +char *i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *meth, + const ASN1_ENUMERATED *aint); +int X509V3_EXT_add(X509V3_EXT_METHOD *ext); +int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist); +int X509V3_EXT_add_alias(int nid_to, int nid_from); +void X509V3_EXT_cleanup(void); + +const X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *ext); +const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid); +int X509V3_add_standard_extensions(void); +STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line); +void *X509V3_EXT_d2i(X509_EXTENSION *ext); +void *X509V3_get_d2i(const STACK_OF(X509_EXTENSION) *x, int nid, int *crit, + int *idx); + +X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc); +int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value, + int crit, unsigned long flags); + +#if OPENSSL_API_COMPAT < 0x10100000L +/* The new declarations are in crypto.h, but the old ones were here. */ +# define hex_to_string OPENSSL_buf2hexstr +# define string_to_hex OPENSSL_hexstr2buf +#endif + +void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent, + int ml); +int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, + int indent); +#ifndef OPENSSL_NO_STDIO +int X509V3_EXT_print_fp(FILE *out, X509_EXTENSION *ext, int flag, int indent); +#endif +int X509V3_extensions_print(BIO *out, const char *title, + const STACK_OF(X509_EXTENSION) *exts, + unsigned long flag, int indent); + +int X509_check_ca(X509 *x); +int X509_check_purpose(X509 *x, int id, int ca); +int X509_supported_extension(X509_EXTENSION *ex); +int X509_PURPOSE_set(int *p, int purpose); +int X509_check_issued(X509 *issuer, X509 *subject); +int X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid); +void X509_set_proxy_flag(X509 *x); +void X509_set_proxy_pathlen(X509 *x, long l); +long X509_get_proxy_pathlen(X509 *x); + +uint32_t X509_get_extension_flags(X509 *x); +uint32_t X509_get_key_usage(X509 *x); +uint32_t X509_get_extended_key_usage(X509 *x); +const ASN1_OCTET_STRING *X509_get0_subject_key_id(X509 *x); +const ASN1_OCTET_STRING *X509_get0_authority_key_id(X509 *x); + +int X509_PURPOSE_get_count(void); +X509_PURPOSE *X509_PURPOSE_get0(int idx); +int X509_PURPOSE_get_by_sname(const char *sname); +int X509_PURPOSE_get_by_id(int id); +int X509_PURPOSE_add(int id, int trust, int flags, + int (*ck) (const X509_PURPOSE *, const X509 *, int), + const char *name, const char *sname, void *arg); +char *X509_PURPOSE_get0_name(const X509_PURPOSE *xp); +char *X509_PURPOSE_get0_sname(const X509_PURPOSE *xp); +int X509_PURPOSE_get_trust(const X509_PURPOSE *xp); +void X509_PURPOSE_cleanup(void); +int X509_PURPOSE_get_id(const X509_PURPOSE *); + +STACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x); +STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x); +void X509_email_free(STACK_OF(OPENSSL_STRING) *sk); +STACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x); +/* Flags for X509_check_* functions */ + +/* + * Always check subject name for host match even if subject alt names present + */ +# define X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT 0x1 +/* Disable wildcard matching for dnsName fields and common name. */ +# define X509_CHECK_FLAG_NO_WILDCARDS 0x2 +/* Wildcards must not match a partial label. */ +# define X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS 0x4 +/* Allow (non-partial) wildcards to match multiple labels. */ +# define X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS 0x8 +/* Constraint verifier subdomain patterns to match a single labels. */ +# define X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS 0x10 +/* Never check the subject CN */ +# define X509_CHECK_FLAG_NEVER_CHECK_SUBJECT 0x20 +/* + * Match reference identifiers starting with "." to any sub-domain. + * This is a non-public flag, turned on implicitly when the subject + * reference identity is a DNS name. + */ +# define _X509_CHECK_FLAG_DOT_SUBDOMAINS 0x8000 + +int X509_check_host(X509 *x, const char *chk, size_t chklen, + unsigned int flags, char **peername); +int X509_check_email(X509 *x, const char *chk, size_t chklen, + unsigned int flags); +int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen, + unsigned int flags); +int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags); + +ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc); +ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc); +int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE) *dn_sk, + unsigned long chtype); + +void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent); +DEFINE_STACK_OF(X509_POLICY_NODE) + +#ifndef OPENSSL_NO_RFC3779 +typedef struct ASRange_st { + ASN1_INTEGER *min, *max; +} ASRange; + +# define ASIdOrRange_id 0 +# define ASIdOrRange_range 1 + +typedef struct ASIdOrRange_st { + int type; + union { + ASN1_INTEGER *id; + ASRange *range; + } u; +} ASIdOrRange; + +typedef STACK_OF(ASIdOrRange) ASIdOrRanges; +DEFINE_STACK_OF(ASIdOrRange) + +# define ASIdentifierChoice_inherit 0 +# define ASIdentifierChoice_asIdsOrRanges 1 + +typedef struct ASIdentifierChoice_st { + int type; + union { + ASN1_NULL *inherit; + ASIdOrRanges *asIdsOrRanges; + } u; +} ASIdentifierChoice; + +typedef struct ASIdentifiers_st { + ASIdentifierChoice *asnum, *rdi; +} ASIdentifiers; + +DECLARE_ASN1_FUNCTIONS(ASRange) +DECLARE_ASN1_FUNCTIONS(ASIdOrRange) +DECLARE_ASN1_FUNCTIONS(ASIdentifierChoice) +DECLARE_ASN1_FUNCTIONS(ASIdentifiers) + +typedef struct IPAddressRange_st { + ASN1_BIT_STRING *min, *max; +} IPAddressRange; + +# define IPAddressOrRange_addressPrefix 0 +# define IPAddressOrRange_addressRange 1 + +typedef struct IPAddressOrRange_st { + int type; + union { + ASN1_BIT_STRING *addressPrefix; + IPAddressRange *addressRange; + } u; +} IPAddressOrRange; + +typedef STACK_OF(IPAddressOrRange) IPAddressOrRanges; +DEFINE_STACK_OF(IPAddressOrRange) + +# define IPAddressChoice_inherit 0 +# define IPAddressChoice_addressesOrRanges 1 + +typedef struct IPAddressChoice_st { + int type; + union { + ASN1_NULL *inherit; + IPAddressOrRanges *addressesOrRanges; + } u; +} IPAddressChoice; + +typedef struct IPAddressFamily_st { + ASN1_OCTET_STRING *addressFamily; + IPAddressChoice *ipAddressChoice; +} IPAddressFamily; + +typedef STACK_OF(IPAddressFamily) IPAddrBlocks; +DEFINE_STACK_OF(IPAddressFamily) + +DECLARE_ASN1_FUNCTIONS(IPAddressRange) +DECLARE_ASN1_FUNCTIONS(IPAddressOrRange) +DECLARE_ASN1_FUNCTIONS(IPAddressChoice) +DECLARE_ASN1_FUNCTIONS(IPAddressFamily) + +/* + * API tag for elements of the ASIdentifer SEQUENCE. + */ +# define V3_ASID_ASNUM 0 +# define V3_ASID_RDI 1 + +/* + * AFI values, assigned by IANA. It'd be nice to make the AFI + * handling code totally generic, but there are too many little things + * that would need to be defined for other address families for it to + * be worth the trouble. + */ +# define IANA_AFI_IPV4 1 +# define IANA_AFI_IPV6 2 + +/* + * Utilities to construct and extract values from RFC3779 extensions, + * since some of the encodings (particularly for IP address prefixes + * and ranges) are a bit tedious to work with directly. + */ +int X509v3_asid_add_inherit(ASIdentifiers *asid, int which); +int X509v3_asid_add_id_or_range(ASIdentifiers *asid, int which, + ASN1_INTEGER *min, ASN1_INTEGER *max); +int X509v3_addr_add_inherit(IPAddrBlocks *addr, + const unsigned afi, const unsigned *safi); +int X509v3_addr_add_prefix(IPAddrBlocks *addr, + const unsigned afi, const unsigned *safi, + unsigned char *a, const int prefixlen); +int X509v3_addr_add_range(IPAddrBlocks *addr, + const unsigned afi, const unsigned *safi, + unsigned char *min, unsigned char *max); +unsigned X509v3_addr_get_afi(const IPAddressFamily *f); +int X509v3_addr_get_range(IPAddressOrRange *aor, const unsigned afi, + unsigned char *min, unsigned char *max, + const int length); + +/* + * Canonical forms. + */ +int X509v3_asid_is_canonical(ASIdentifiers *asid); +int X509v3_addr_is_canonical(IPAddrBlocks *addr); +int X509v3_asid_canonize(ASIdentifiers *asid); +int X509v3_addr_canonize(IPAddrBlocks *addr); + +/* + * Tests for inheritance and containment. + */ +int X509v3_asid_inherits(ASIdentifiers *asid); +int X509v3_addr_inherits(IPAddrBlocks *addr); +int X509v3_asid_subset(ASIdentifiers *a, ASIdentifiers *b); +int X509v3_addr_subset(IPAddrBlocks *a, IPAddrBlocks *b); + +/* + * Check whether RFC 3779 extensions nest properly in chains. + */ +int X509v3_asid_validate_path(X509_STORE_CTX *); +int X509v3_addr_validate_path(X509_STORE_CTX *); +int X509v3_asid_validate_resource_set(STACK_OF(X509) *chain, + ASIdentifiers *ext, + int allow_inheritance); +int X509v3_addr_validate_resource_set(STACK_OF(X509) *chain, + IPAddrBlocks *ext, int allow_inheritance); + +#endif /* OPENSSL_NO_RFC3779 */ + +DEFINE_STACK_OF(ASN1_STRING) + +/* + * Admission Syntax + */ +typedef struct NamingAuthority_st NAMING_AUTHORITY; +typedef struct ProfessionInfo_st PROFESSION_INFO; +typedef struct Admissions_st ADMISSIONS; +typedef struct AdmissionSyntax_st ADMISSION_SYNTAX; +DECLARE_ASN1_FUNCTIONS(NAMING_AUTHORITY) +DECLARE_ASN1_FUNCTIONS(PROFESSION_INFO) +DECLARE_ASN1_FUNCTIONS(ADMISSIONS) +DECLARE_ASN1_FUNCTIONS(ADMISSION_SYNTAX) +DEFINE_STACK_OF(ADMISSIONS) +DEFINE_STACK_OF(PROFESSION_INFO) +typedef STACK_OF(PROFESSION_INFO) PROFESSION_INFOS; + +const ASN1_OBJECT *NAMING_AUTHORITY_get0_authorityId( + const NAMING_AUTHORITY *n); +const ASN1_IA5STRING *NAMING_AUTHORITY_get0_authorityURL( + const NAMING_AUTHORITY *n); +const ASN1_STRING *NAMING_AUTHORITY_get0_authorityText( + const NAMING_AUTHORITY *n); +void NAMING_AUTHORITY_set0_authorityId(NAMING_AUTHORITY *n, + ASN1_OBJECT* namingAuthorityId); +void NAMING_AUTHORITY_set0_authorityURL(NAMING_AUTHORITY *n, + ASN1_IA5STRING* namingAuthorityUrl); +void NAMING_AUTHORITY_set0_authorityText(NAMING_AUTHORITY *n, + ASN1_STRING* namingAuthorityText); + +const GENERAL_NAME *ADMISSION_SYNTAX_get0_admissionAuthority( + const ADMISSION_SYNTAX *as); +void ADMISSION_SYNTAX_set0_admissionAuthority( + ADMISSION_SYNTAX *as, GENERAL_NAME *aa); +const STACK_OF(ADMISSIONS) *ADMISSION_SYNTAX_get0_contentsOfAdmissions( + const ADMISSION_SYNTAX *as); +void ADMISSION_SYNTAX_set0_contentsOfAdmissions( + ADMISSION_SYNTAX *as, STACK_OF(ADMISSIONS) *a); +const GENERAL_NAME *ADMISSIONS_get0_admissionAuthority(const ADMISSIONS *a); +void ADMISSIONS_set0_admissionAuthority(ADMISSIONS *a, GENERAL_NAME *aa); +const NAMING_AUTHORITY *ADMISSIONS_get0_namingAuthority(const ADMISSIONS *a); +void ADMISSIONS_set0_namingAuthority(ADMISSIONS *a, NAMING_AUTHORITY *na); +const PROFESSION_INFOS *ADMISSIONS_get0_professionInfos(const ADMISSIONS *a); +void ADMISSIONS_set0_professionInfos(ADMISSIONS *a, PROFESSION_INFOS *pi); +const ASN1_OCTET_STRING *PROFESSION_INFO_get0_addProfessionInfo( + const PROFESSION_INFO *pi); +void PROFESSION_INFO_set0_addProfessionInfo( + PROFESSION_INFO *pi, ASN1_OCTET_STRING *aos); +const NAMING_AUTHORITY *PROFESSION_INFO_get0_namingAuthority( + const PROFESSION_INFO *pi); +void PROFESSION_INFO_set0_namingAuthority( + PROFESSION_INFO *pi, NAMING_AUTHORITY *na); +const STACK_OF(ASN1_STRING) *PROFESSION_INFO_get0_professionItems( + const PROFESSION_INFO *pi); +void PROFESSION_INFO_set0_professionItems( + PROFESSION_INFO *pi, STACK_OF(ASN1_STRING) *as); +const STACK_OF(ASN1_OBJECT) *PROFESSION_INFO_get0_professionOIDs( + const PROFESSION_INFO *pi); +void PROFESSION_INFO_set0_professionOIDs( + PROFESSION_INFO *pi, STACK_OF(ASN1_OBJECT) *po); +const ASN1_PRINTABLESTRING *PROFESSION_INFO_get0_registrationNumber( + const PROFESSION_INFO *pi); +void PROFESSION_INFO_set0_registrationNumber( + PROFESSION_INFO *pi, ASN1_PRINTABLESTRING *rn); + +# ifdef __cplusplus +} +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/include/openssl/x509v3err.h b/trunk/3rdparty/openssl-1.1-fit/include/openssl/x509v3err.h new file mode 100644 index 000000000..6b3df12b6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/include/openssl/x509v3err.h @@ -0,0 +1,158 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_X509V3ERR_H +# define HEADER_X509V3ERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_X509V3_strings(void); + +/* + * X509V3 function codes. + */ +# define X509V3_F_A2I_GENERAL_NAME 164 +# define X509V3_F_ADDR_VALIDATE_PATH_INTERNAL 166 +# define X509V3_F_ASIDENTIFIERCHOICE_CANONIZE 161 +# define X509V3_F_ASIDENTIFIERCHOICE_IS_CANONICAL 162 +# define X509V3_F_BIGNUM_TO_STRING 167 +# define X509V3_F_COPY_EMAIL 122 +# define X509V3_F_COPY_ISSUER 123 +# define X509V3_F_DO_DIRNAME 144 +# define X509V3_F_DO_EXT_I2D 135 +# define X509V3_F_DO_EXT_NCONF 151 +# define X509V3_F_GNAMES_FROM_SECTNAME 156 +# define X509V3_F_I2S_ASN1_ENUMERATED 121 +# define X509V3_F_I2S_ASN1_IA5STRING 149 +# define X509V3_F_I2S_ASN1_INTEGER 120 +# define X509V3_F_I2V_AUTHORITY_INFO_ACCESS 138 +# define X509V3_F_LEVEL_ADD_NODE 168 +# define X509V3_F_NOTICE_SECTION 132 +# define X509V3_F_NREF_NOS 133 +# define X509V3_F_POLICY_CACHE_CREATE 169 +# define X509V3_F_POLICY_CACHE_NEW 170 +# define X509V3_F_POLICY_DATA_NEW 171 +# define X509V3_F_POLICY_SECTION 131 +# define X509V3_F_PROCESS_PCI_VALUE 150 +# define X509V3_F_R2I_CERTPOL 130 +# define X509V3_F_R2I_PCI 155 +# define X509V3_F_S2I_ASN1_IA5STRING 100 +# define X509V3_F_S2I_ASN1_INTEGER 108 +# define X509V3_F_S2I_ASN1_OCTET_STRING 112 +# define X509V3_F_S2I_SKEY_ID 115 +# define X509V3_F_SET_DIST_POINT_NAME 158 +# define X509V3_F_SXNET_ADD_ID_ASC 125 +# define X509V3_F_SXNET_ADD_ID_INTEGER 126 +# define X509V3_F_SXNET_ADD_ID_ULONG 127 +# define X509V3_F_SXNET_GET_ID_ASC 128 +# define X509V3_F_SXNET_GET_ID_ULONG 129 +# define X509V3_F_TREE_INIT 172 +# define X509V3_F_V2I_ASIDENTIFIERS 163 +# define X509V3_F_V2I_ASN1_BIT_STRING 101 +# define X509V3_F_V2I_AUTHORITY_INFO_ACCESS 139 +# define X509V3_F_V2I_AUTHORITY_KEYID 119 +# define X509V3_F_V2I_BASIC_CONSTRAINTS 102 +# define X509V3_F_V2I_CRLD 134 +# define X509V3_F_V2I_EXTENDED_KEY_USAGE 103 +# define X509V3_F_V2I_GENERAL_NAMES 118 +# define X509V3_F_V2I_GENERAL_NAME_EX 117 +# define X509V3_F_V2I_IDP 157 +# define X509V3_F_V2I_IPADDRBLOCKS 159 +# define X509V3_F_V2I_ISSUER_ALT 153 +# define X509V3_F_V2I_NAME_CONSTRAINTS 147 +# define X509V3_F_V2I_POLICY_CONSTRAINTS 146 +# define X509V3_F_V2I_POLICY_MAPPINGS 145 +# define X509V3_F_V2I_SUBJECT_ALT 154 +# define X509V3_F_V2I_TLS_FEATURE 165 +# define X509V3_F_V3_GENERIC_EXTENSION 116 +# define X509V3_F_X509V3_ADD1_I2D 140 +# define X509V3_F_X509V3_ADD_VALUE 105 +# define X509V3_F_X509V3_EXT_ADD 104 +# define X509V3_F_X509V3_EXT_ADD_ALIAS 106 +# define X509V3_F_X509V3_EXT_I2D 136 +# define X509V3_F_X509V3_EXT_NCONF 152 +# define X509V3_F_X509V3_GET_SECTION 142 +# define X509V3_F_X509V3_GET_STRING 143 +# define X509V3_F_X509V3_GET_VALUE_BOOL 110 +# define X509V3_F_X509V3_PARSE_LIST 109 +# define X509V3_F_X509_PURPOSE_ADD 137 +# define X509V3_F_X509_PURPOSE_SET 141 + +/* + * X509V3 reason codes. + */ +# define X509V3_R_BAD_IP_ADDRESS 118 +# define X509V3_R_BAD_OBJECT 119 +# define X509V3_R_BN_DEC2BN_ERROR 100 +# define X509V3_R_BN_TO_ASN1_INTEGER_ERROR 101 +# define X509V3_R_DIRNAME_ERROR 149 +# define X509V3_R_DISTPOINT_ALREADY_SET 160 +# define X509V3_R_DUPLICATE_ZONE_ID 133 +# define X509V3_R_ERROR_CONVERTING_ZONE 131 +# define X509V3_R_ERROR_CREATING_EXTENSION 144 +# define X509V3_R_ERROR_IN_EXTENSION 128 +# define X509V3_R_EXPECTED_A_SECTION_NAME 137 +# define X509V3_R_EXTENSION_EXISTS 145 +# define X509V3_R_EXTENSION_NAME_ERROR 115 +# define X509V3_R_EXTENSION_NOT_FOUND 102 +# define X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED 103 +# define X509V3_R_EXTENSION_VALUE_ERROR 116 +# define X509V3_R_ILLEGAL_EMPTY_EXTENSION 151 +# define X509V3_R_INCORRECT_POLICY_SYNTAX_TAG 152 +# define X509V3_R_INVALID_ASNUMBER 162 +# define X509V3_R_INVALID_ASRANGE 163 +# define X509V3_R_INVALID_BOOLEAN_STRING 104 +# define X509V3_R_INVALID_EXTENSION_STRING 105 +# define X509V3_R_INVALID_INHERITANCE 165 +# define X509V3_R_INVALID_IPADDRESS 166 +# define X509V3_R_INVALID_MULTIPLE_RDNS 161 +# define X509V3_R_INVALID_NAME 106 +# define X509V3_R_INVALID_NULL_ARGUMENT 107 +# define X509V3_R_INVALID_NULL_NAME 108 +# define X509V3_R_INVALID_NULL_VALUE 109 +# define X509V3_R_INVALID_NUMBER 140 +# define X509V3_R_INVALID_NUMBERS 141 +# define X509V3_R_INVALID_OBJECT_IDENTIFIER 110 +# define X509V3_R_INVALID_OPTION 138 +# define X509V3_R_INVALID_POLICY_IDENTIFIER 134 +# define X509V3_R_INVALID_PROXY_POLICY_SETTING 153 +# define X509V3_R_INVALID_PURPOSE 146 +# define X509V3_R_INVALID_SAFI 164 +# define X509V3_R_INVALID_SECTION 135 +# define X509V3_R_INVALID_SYNTAX 143 +# define X509V3_R_ISSUER_DECODE_ERROR 126 +# define X509V3_R_MISSING_VALUE 124 +# define X509V3_R_NEED_ORGANIZATION_AND_NUMBERS 142 +# define X509V3_R_NO_CONFIG_DATABASE 136 +# define X509V3_R_NO_ISSUER_CERTIFICATE 121 +# define X509V3_R_NO_ISSUER_DETAILS 127 +# define X509V3_R_NO_POLICY_IDENTIFIER 139 +# define X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED 154 +# define X509V3_R_NO_PUBLIC_KEY 114 +# define X509V3_R_NO_SUBJECT_DETAILS 125 +# define X509V3_R_OPERATION_NOT_DEFINED 148 +# define X509V3_R_OTHERNAME_ERROR 147 +# define X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED 155 +# define X509V3_R_POLICY_PATH_LENGTH 156 +# define X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED 157 +# define X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY 159 +# define X509V3_R_SECTION_NOT_FOUND 150 +# define X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS 122 +# define X509V3_R_UNABLE_TO_GET_ISSUER_KEYID 123 +# define X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT 111 +# define X509V3_R_UNKNOWN_EXTENSION 129 +# define X509V3_R_UNKNOWN_EXTENSION_NAME 130 +# define X509V3_R_UNKNOWN_OPTION 120 +# define X509V3_R_UNSUPPORTED_OPTION 117 +# define X509V3_R_UNSUPPORTED_TYPE 167 +# define X509V3_R_USER_TOO_LONG 132 + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/ms/applink.c b/trunk/3rdparty/openssl-1.1-fit/ms/applink.c new file mode 100644 index 000000000..238dbff35 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ms/applink.c @@ -0,0 +1,138 @@ +/* + * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#define APPLINK_STDIN 1 +#define APPLINK_STDOUT 2 +#define APPLINK_STDERR 3 +#define APPLINK_FPRINTF 4 +#define APPLINK_FGETS 5 +#define APPLINK_FREAD 6 +#define APPLINK_FWRITE 7 +#define APPLINK_FSETMOD 8 +#define APPLINK_FEOF 9 +#define APPLINK_FCLOSE 10 /* should not be used */ + +#define APPLINK_FOPEN 11 /* solely for completeness */ +#define APPLINK_FSEEK 12 +#define APPLINK_FTELL 13 +#define APPLINK_FFLUSH 14 +#define APPLINK_FERROR 15 +#define APPLINK_CLEARERR 16 +#define APPLINK_FILENO 17 /* to be used with below */ + +#define APPLINK_OPEN 18 /* formally can't be used, as flags can vary */ +#define APPLINK_READ 19 +#define APPLINK_WRITE 20 +#define APPLINK_LSEEK 21 +#define APPLINK_CLOSE 22 +#define APPLINK_MAX 22 /* always same as last macro */ + +#ifndef APPMACROS_ONLY +# include +# include +# include + +static void *app_stdin(void) +{ + return stdin; +} + +static void *app_stdout(void) +{ + return stdout; +} + +static void *app_stderr(void) +{ + return stderr; +} + +static int app_feof(FILE *fp) +{ + return feof(fp); +} + +static int app_ferror(FILE *fp) +{ + return ferror(fp); +} + +static void app_clearerr(FILE *fp) +{ + clearerr(fp); +} + +static int app_fileno(FILE *fp) +{ + return _fileno(fp); +} + +static int app_fsetmod(FILE *fp, char mod) +{ + return _setmode(_fileno(fp), mod == 'b' ? _O_BINARY : _O_TEXT); +} + +#ifdef __cplusplus +extern "C" { +#endif + +__declspec(dllexport) +void ** +# if defined(__BORLANDC__) +/* + * __stdcall appears to be the only way to get the name + * decoration right with Borland C. Otherwise it works + * purely incidentally, as we pass no parameters. + */ +__stdcall +# else +__cdecl +# endif +OPENSSL_Applink(void) +{ + static int once = 1; + static void *OPENSSL_ApplinkTable[APPLINK_MAX + 1] = + { (void *)APPLINK_MAX }; + + if (once) { + OPENSSL_ApplinkTable[APPLINK_STDIN] = app_stdin; + OPENSSL_ApplinkTable[APPLINK_STDOUT] = app_stdout; + OPENSSL_ApplinkTable[APPLINK_STDERR] = app_stderr; + OPENSSL_ApplinkTable[APPLINK_FPRINTF] = fprintf; + OPENSSL_ApplinkTable[APPLINK_FGETS] = fgets; + OPENSSL_ApplinkTable[APPLINK_FREAD] = fread; + OPENSSL_ApplinkTable[APPLINK_FWRITE] = fwrite; + OPENSSL_ApplinkTable[APPLINK_FSETMOD] = app_fsetmod; + OPENSSL_ApplinkTable[APPLINK_FEOF] = app_feof; + OPENSSL_ApplinkTable[APPLINK_FCLOSE] = fclose; + + OPENSSL_ApplinkTable[APPLINK_FOPEN] = fopen; + OPENSSL_ApplinkTable[APPLINK_FSEEK] = fseek; + OPENSSL_ApplinkTable[APPLINK_FTELL] = ftell; + OPENSSL_ApplinkTable[APPLINK_FFLUSH] = fflush; + OPENSSL_ApplinkTable[APPLINK_FERROR] = app_ferror; + OPENSSL_ApplinkTable[APPLINK_CLEARERR] = app_clearerr; + OPENSSL_ApplinkTable[APPLINK_FILENO] = app_fileno; + + OPENSSL_ApplinkTable[APPLINK_OPEN] = _open; + OPENSSL_ApplinkTable[APPLINK_READ] = _read; + OPENSSL_ApplinkTable[APPLINK_WRITE] = _write; + OPENSSL_ApplinkTable[APPLINK_LSEEK] = _lseek; + OPENSSL_ApplinkTable[APPLINK_CLOSE] = _close; + + once = 0; + } + + return OPENSSL_ApplinkTable; +} + +#ifdef __cplusplus +} +#endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/ms/cmp.pl b/trunk/3rdparty/openssl-1.1-fit/ms/cmp.pl new file mode 100755 index 000000000..265ce56ed --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ms/cmp.pl @@ -0,0 +1,53 @@ +#! /usr/bin/env perl +# Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +($#ARGV == 1) || die "usage: cmp.pl \n"; + +open(IN0,"<$ARGV[0]") || die "unable to open $ARGV[0]\n"; +open(IN1,"<$ARGV[1]") || die "unable to open $ARGV[1]\n"; +binmode IN0; +binmode IN1; + +$tot=0; +$ret=1; +for (;;) +{ + $n1=sysread(IN0,$b1,4096); + $n2=sysread(IN1,$b2,4096); + + last if ($n1 != $n2); + last if ($b1 ne $b2); + last if ($n1 < 0); + if ($n1 == 0) + { + $ret=0; + last; + } + $tot+=$n1; +} + +close(IN0); +close(IN1); +if ($ret) +{ + printf STDERR "$ARGV[0] and $ARGV[1] are different\n"; + @a1=unpack("C*",$b1); + @a2=unpack("C*",$b2); + for ($i=0; $i<=$#a1; $i++) + { + if ($a1[$i] ne $a2[$i]) + { + printf "%02X %02X <<\n",$a1[$i],$a2[$i]; + last; + } + } + $nm=$tot+$n1; + $tot+=$i+1; + printf STDERR "diff at char $tot of $nm\n"; +} +exit($ret); diff --git a/trunk/3rdparty/openssl-1.1-fit/ms/uplink-common.pl b/trunk/3rdparty/openssl-1.1-fit/ms/uplink-common.pl new file mode 100755 index 000000000..e2ab59456 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ms/uplink-common.pl @@ -0,0 +1,28 @@ +#! /usr/bin/env perl +# Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# pull APPLINK_MAX value from applink.c... +$applink_c=$0; +$applink_c=~s|[^/\\]+$||g; +$applink_c.="applink.c"; +open(INPUT,$applink_c) || die "can't open $applink_c: $!"; +@max=grep {/APPLINK_MAX\s+(\d+)/} ; +close(INPUT); +($#max==0) or die "can't find APPLINK_MAX in $applink_c"; + +$max[0]=~/APPLINK_MAX\s+(\d+)/; +$N=$1; # number of entries in OPENSSL_UplinkTable not including + # OPENSSL_UplinkTable[0], which contains this value... + +1; + +# Idea is to fill the OPENSSL_UplinkTable with pointers to stubs +# which invoke 'void OPENSSL_Uplink (ULONG_PTR *table,int index)'; +# and then dereference themselves. Latter shall result in endless +# loop *unless* OPENSSL_Uplink does not replace 'table[index]' with +# something else, e.g. as 'table[index]=unimplemented;'... diff --git a/trunk/3rdparty/openssl-1.1-fit/ms/uplink-ia64.pl b/trunk/3rdparty/openssl-1.1-fit/ms/uplink-ia64.pl new file mode 100755 index 000000000..0636f13e7 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ms/uplink-ia64.pl @@ -0,0 +1,61 @@ +#! /usr/bin/env perl +# Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +$output = pop; +open STDOUT,">$output"; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}."); + +require "uplink-common.pl"; + +local $V=8; # max number of args uplink functions may accept... +my $loc0 = "r".(32+$V); +print <<___; +.text +.global OPENSSL_Uplink# +.type OPENSSL_Uplink#,\@function + +___ +for ($i=1;$i<=$N;$i++) { +print <<___; +.proc lazy$i# +lazy$i: + .prologue +{ .mii; .save ar.pfs,$loc0 + alloc loc0=ar.pfs,$V,3,2,0 + .save b0,loc1 + mov loc1=b0 + addl loc2=\@ltoff(OPENSSL_UplinkTable#),gp };; + .body +{ .mmi; ld8 out0=[loc2] + mov out1=$i };; +{ .mib; add loc2=8*$i,out0 + br.call.sptk.many b0=OPENSSL_Uplink# };; +{ .mmi; ld8 r31=[loc2];; + ld8 r30=[r31],8 };; +{ .mii; ld8 gp=[r31] + mov b6=r30 + mov b0=loc1 };; +{ .mib; mov ar.pfs=loc0 + br.many b6 };; +.endp lazy$i# + +___ +} +print <<___; +.data +.global OPENSSL_UplinkTable# +OPENSSL_UplinkTable: data8 $N // amount of following entries +___ +for ($i=1;$i<=$N;$i++) { print " data8 \@fptr(lazy$i#)\n"; } +print <<___; +.size OPENSSL_UplinkTable,.-OPENSSL_UplinkTable# +___ + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/ms/uplink-x86.pl b/trunk/3rdparty/openssl-1.1-fit/ms/uplink-x86.pl new file mode 100755 index 000000000..e79cff72d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ms/uplink-x86.pl @@ -0,0 +1,44 @@ +#! /usr/bin/env perl +# Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC, "${dir}.", "${dir}../crypto/perlasm"); +require "x86asm.pl"; + +require "uplink-common.pl"; + +$output = pop; +open STDOUT,">$output"; + +&asm_init($ARGV[0]); + +&external_label("OPENSSL_Uplink"); +&public_label("OPENSSL_UplinkTable"); + +for ($i=1;$i<=$N;$i++) { +&function_begin_B("_\$lazy${i}"); + &lea ("eax",&DWP(&label("OPENSSL_UplinkTable"))); + &push ($i); + &push ("eax"); + &call (&label("OPENSSL_Uplink")); + &pop ("eax"); + &add ("esp",4); + &jmp_ptr(&DWP(4*$i,"eax")); +&function_end_B("_\$lazy${i}"); +} + +&dataseg(); +&align(4); +&set_label("OPENSSL_UplinkTable"); +&data_word($N); +for ($i=1;$i<=$N;$i++) { +&data_word(&label("_\$lazy${i}")); +} +&asm_finish(); + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/ms/uplink-x86_64.pl b/trunk/3rdparty/openssl-1.1-fit/ms/uplink-x86_64.pl new file mode 100755 index 000000000..1f244504c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ms/uplink-x86_64.pl @@ -0,0 +1,71 @@ +#! /usr/bin/env perl +# Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +$output=pop; +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +open OUT,"| \"$^X\" \"${dir}../crypto/perlasm/x86_64-xlate.pl\" \"$output\""; +*STDOUT=*OUT; +push(@INC,"${dir}."); + +require "uplink-common.pl"; + +$prefix="_lazy"; + +print <<___; +.text +.extern OPENSSL_Uplink +.globl OPENSSL_UplinkTable +___ +for ($i=1;$i<=$N;$i++) { +print <<___; +.type $prefix${i},\@abi-omnipotent +.align 16 +$prefix${i}: + .byte 0x48,0x83,0xEC,0x28 # sub rsp,40 + mov %rcx,48(%rsp) + mov %rdx,56(%rsp) + mov %r8,64(%rsp) + mov %r9,72(%rsp) + lea OPENSSL_UplinkTable(%rip),%rcx + mov \$$i,%rdx + call OPENSSL_Uplink + mov 48(%rsp),%rcx + mov 56(%rsp),%rdx + mov 64(%rsp),%r8 + mov 72(%rsp),%r9 + lea OPENSSL_UplinkTable(%rip),%rax + add \$40,%rsp + jmp *8*$i(%rax) +$prefix${i}_end: +.size $prefix${i},.-$prefix${i} +___ +} +print <<___; +.data +OPENSSL_UplinkTable: + .quad $N +___ +for ($i=1;$i<=$N;$i++) { print " .quad $prefix$i\n"; } +print <<___; +.section .pdata,"r" +.align 4 +___ +for ($i=1;$i<=$N;$i++) { +print <<___; + .rva $prefix${i},$prefix${i}_end,${prefix}_unwind_info +___ +} +print <<___; +.section .xdata,"r" +.align 8 +${prefix}_unwind_info: + .byte 0x01,0x04,0x01,0x00 + .byte 0x04,0x42,0x00,0x00 +___ + +close STDOUT; diff --git a/trunk/3rdparty/openssl-1.1-fit/ms/uplink.c b/trunk/3rdparty/openssl-1.1-fit/ms/uplink.c new file mode 100644 index 000000000..cd4e96b78 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ms/uplink.c @@ -0,0 +1,135 @@ +/* + * Copyright 2004-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#if (defined(_WIN64) || defined(_WIN32_WCE)) && !defined(UNICODE) +# define UNICODE +#endif +#if defined(UNICODE) && !defined(_UNICODE) +# define _UNICODE +#endif +#if defined(_UNICODE) && !defined(UNICODE) +# define UNICODE +#endif + +#include +#include +#include +#include "uplink.h" +void OPENSSL_showfatal(const char *, ...); + +static TCHAR msg[128]; + +static void unimplemented(void) +{ + OPENSSL_showfatal(sizeof(TCHAR) == sizeof(char) ? "%s\n" : "%S\n", msg); + TerminateProcess(GetCurrentProcess(), 1); +} + +void OPENSSL_Uplink(volatile void **table, int index) +{ + static HMODULE volatile apphandle = NULL; + static void **volatile applinktable = NULL; + int len; + void (*func) (void) = unimplemented; + HANDLE h; + void **p; + + /* + * Note that the below code is not MT-safe in respect to msg buffer, but + * what's the worst thing that can happen? Error message might be + * misleading or corrupted. As error condition is fatal and should never + * be risen, I accept the risk... + */ + /* + * One can argue that I should have used InterlockedExchangePointer or + * something to update static variables and table[]. Well, store + * instructions are as atomic as they can get and assigned values are + * effectively constant... So that volatile qualifier should be + * sufficient [it prohibits compiler to reorder memory access + * instructions]. + */ + do { + len = _sntprintf(msg, sizeof(msg) / sizeof(TCHAR), + _T("OPENSSL_Uplink(%p,%02X): "), table, index); + _tcscpy(msg + len, _T("unimplemented function")); + + if ((h = apphandle) == NULL) { + if ((h = GetModuleHandle(NULL)) == NULL) { + apphandle = (HMODULE) - 1; + _tcscpy(msg + len, _T("no host application")); + break; + } + apphandle = h; + } + if ((h = apphandle) == (HMODULE) - 1) /* revalidate */ + break; + + if (applinktable == NULL) { + void **(*applink) (); + + applink = (void **(*)())GetProcAddress(h, "OPENSSL_Applink"); + if (applink == NULL) { + apphandle = (HMODULE) - 1; + _tcscpy(msg + len, _T("no OPENSSL_Applink")); + break; + } + p = (*applink) (); + if (p == NULL) { + apphandle = (HMODULE) - 1; + _tcscpy(msg + len, _T("no ApplinkTable")); + break; + } + applinktable = p; + } else + p = applinktable; + + if (index > (int)p[0]) + break; + + if (p[index]) + func = p[index]; + } while (0); + + table[index] = func; +} + +#if defined(_MSC_VER) && defined(_M_IX86) +# define LAZY(i) \ +__declspec(naked) static void lazy##i (void) { \ + _asm push i \ + _asm push OFFSET OPENSSL_UplinkTable \ + _asm call OPENSSL_Uplink \ + _asm add esp,8 \ + _asm jmp OPENSSL_UplinkTable+4*i } + +# if APPLINK_MAX>25 +# error "Add more stubs..." +# endif +/* make some in advance... */ +LAZY(1) LAZY(2) LAZY(3) LAZY(4) LAZY(5) + LAZY(6) LAZY(7) LAZY(8) LAZY(9) LAZY(10) + LAZY(11) LAZY(12) LAZY(13) LAZY(14) LAZY(15) + LAZY(16) LAZY(17) LAZY(18) LAZY(19) LAZY(20) + LAZY(21) LAZY(22) LAZY(23) LAZY(24) LAZY(25) +void *OPENSSL_UplinkTable[] = { + (void *)APPLINK_MAX, + lazy1, lazy2, lazy3, lazy4, lazy5, + lazy6, lazy7, lazy8, lazy9, lazy10, + lazy11, lazy12, lazy13, lazy14, lazy15, + lazy16, lazy17, lazy18, lazy19, lazy20, + lazy21, lazy22, lazy23, lazy24, lazy25, +}; +#endif + +#ifdef SELFTEST +main() +{ + UP_fprintf(UP_stdout, "hello, world!\n"); +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/ms/uplink.h b/trunk/3rdparty/openssl-1.1-fit/ms/uplink.h new file mode 100644 index 000000000..f6cd0380a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ms/uplink.h @@ -0,0 +1,38 @@ +/* + * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#define APPMACROS_ONLY +#include "applink.c" + +extern void *OPENSSL_UplinkTable[]; + +#define UP_stdin (*(void *(*)(void))OPENSSL_UplinkTable[APPLINK_STDIN])() +#define UP_stdout (*(void *(*)(void))OPENSSL_UplinkTable[APPLINK_STDOUT])() +#define UP_stderr (*(void *(*)(void))OPENSSL_UplinkTable[APPLINK_STDERR])() +#define UP_fprintf (*(int (*)(void *,const char *,...))OPENSSL_UplinkTable[APPLINK_FPRINTF]) +#define UP_fgets (*(char *(*)(char *,int,void *))OPENSSL_UplinkTable[APPLINK_FGETS]) +#define UP_fread (*(size_t (*)(void *,size_t,size_t,void *))OPENSSL_UplinkTable[APPLINK_FREAD]) +#define UP_fwrite (*(size_t (*)(const void *,size_t,size_t,void *))OPENSSL_UplinkTable[APPLINK_FWRITE]) +#define UP_fsetmod (*(int (*)(void *,char))OPENSSL_UplinkTable[APPLINK_FSETMOD]) +#define UP_feof (*(int (*)(void *))OPENSSL_UplinkTable[APPLINK_FEOF]) +#define UP_fclose (*(int (*)(void *))OPENSSL_UplinkTable[APPLINK_FCLOSE]) + +#define UP_fopen (*(void *(*)(const char *,const char *))OPENSSL_UplinkTable[APPLINK_FOPEN]) +#define UP_fseek (*(int (*)(void *,long,int))OPENSSL_UplinkTable[APPLINK_FSEEK]) +#define UP_ftell (*(long (*)(void *))OPENSSL_UplinkTable[APPLINK_FTELL]) +#define UP_fflush (*(int (*)(void *))OPENSSL_UplinkTable[APPLINK_FFLUSH]) +#define UP_ferror (*(int (*)(void *))OPENSSL_UplinkTable[APPLINK_FERROR]) +#define UP_clearerr (*(void (*)(void *))OPENSSL_UplinkTable[APPLINK_CLEARERR]) +#define UP_fileno (*(int (*)(void *))OPENSSL_UplinkTable[APPLINK_FILENO]) + +#define UP_open (*(int (*)(const char *,int,...))OPENSSL_UplinkTable[APPLINK_OPEN]) +#define UP_read (*(ossl_ssize_t (*)(int,void *,size_t))OPENSSL_UplinkTable[APPLINK_READ]) +#define UP_write (*(ossl_ssize_t (*)(int,const void *,size_t))OPENSSL_UplinkTable[APPLINK_WRITE]) +#define UP_lseek (*(long (*)(int,long,int))OPENSSL_UplinkTable[APPLINK_LSEEK]) +#define UP_close (*(int (*)(int))OPENSSL_UplinkTable[APPLINK_CLOSE]) diff --git a/trunk/3rdparty/openssl-1.1-fit/os-dep/haiku.h b/trunk/3rdparty/openssl-1.1-fit/os-dep/haiku.h new file mode 100644 index 000000000..7e908efaa --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/os-dep/haiku.h @@ -0,0 +1,2 @@ +#include +#include diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/bio_ssl.c b/trunk/3rdparty/openssl-1.1-fit/ssl/bio_ssl.c new file mode 100644 index 000000000..d1876d8b8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/bio_ssl.c @@ -0,0 +1,505 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include "internal/bio.h" +#include +#include "ssl_locl.h" + +static int ssl_write(BIO *h, const char *buf, size_t size, size_t *written); +static int ssl_read(BIO *b, char *buf, size_t size, size_t *readbytes); +static int ssl_puts(BIO *h, const char *str); +static long ssl_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int ssl_new(BIO *h); +static int ssl_free(BIO *data); +static long ssl_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); +typedef struct bio_ssl_st { + SSL *ssl; /* The ssl handle :-) */ + /* re-negotiate every time the total number of bytes is this size */ + int num_renegotiates; + unsigned long renegotiate_count; + size_t byte_count; + unsigned long renegotiate_timeout; + unsigned long last_time; +} BIO_SSL; + +static const BIO_METHOD methods_sslp = { + BIO_TYPE_SSL, + "ssl", + ssl_write, + NULL, /* ssl_write_old, */ + ssl_read, + NULL, /* ssl_read_old, */ + ssl_puts, + NULL, /* ssl_gets, */ + ssl_ctrl, + ssl_new, + ssl_free, + ssl_callback_ctrl, +}; + +const BIO_METHOD *BIO_f_ssl(void) +{ + return &methods_sslp; +} + +static int ssl_new(BIO *bi) +{ + BIO_SSL *bs = OPENSSL_zalloc(sizeof(*bs)); + + if (bs == NULL) { + BIOerr(BIO_F_SSL_NEW, ERR_R_MALLOC_FAILURE); + return 0; + } + BIO_set_init(bi, 0); + BIO_set_data(bi, bs); + /* Clear all flags */ + BIO_clear_flags(bi, ~0); + + return 1; +} + +static int ssl_free(BIO *a) +{ + BIO_SSL *bs; + + if (a == NULL) + return 0; + bs = BIO_get_data(a); + if (bs->ssl != NULL) + SSL_shutdown(bs->ssl); + if (BIO_get_shutdown(a)) { + if (BIO_get_init(a)) + SSL_free(bs->ssl); + /* Clear all flags */ + BIO_clear_flags(a, ~0); + BIO_set_init(a, 0); + } + OPENSSL_free(bs); + return 1; +} + +static int ssl_read(BIO *b, char *buf, size_t size, size_t *readbytes) +{ + int ret = 1; + BIO_SSL *sb; + SSL *ssl; + int retry_reason = 0; + int r = 0; + + if (buf == NULL) + return 0; + sb = BIO_get_data(b); + ssl = sb->ssl; + + BIO_clear_retry_flags(b); + + ret = ssl_read_internal(ssl, buf, size, readbytes); + + switch (SSL_get_error(ssl, ret)) { + case SSL_ERROR_NONE: + if (sb->renegotiate_count > 0) { + sb->byte_count += *readbytes; + if (sb->byte_count > sb->renegotiate_count) { + sb->byte_count = 0; + sb->num_renegotiates++; + SSL_renegotiate(ssl); + r = 1; + } + } + if ((sb->renegotiate_timeout > 0) && (!r)) { + unsigned long tm; + + tm = (unsigned long)time(NULL); + if (tm > sb->last_time + sb->renegotiate_timeout) { + sb->last_time = tm; + sb->num_renegotiates++; + SSL_renegotiate(ssl); + } + } + + break; + case SSL_ERROR_WANT_READ: + BIO_set_retry_read(b); + break; + case SSL_ERROR_WANT_WRITE: + BIO_set_retry_write(b); + break; + case SSL_ERROR_WANT_X509_LOOKUP: + BIO_set_retry_special(b); + retry_reason = BIO_RR_SSL_X509_LOOKUP; + break; + case SSL_ERROR_WANT_ACCEPT: + BIO_set_retry_special(b); + retry_reason = BIO_RR_ACCEPT; + break; + case SSL_ERROR_WANT_CONNECT: + BIO_set_retry_special(b); + retry_reason = BIO_RR_CONNECT; + break; + case SSL_ERROR_SYSCALL: + case SSL_ERROR_SSL: + case SSL_ERROR_ZERO_RETURN: + default: + break; + } + + BIO_set_retry_reason(b, retry_reason); + + return ret; +} + +static int ssl_write(BIO *b, const char *buf, size_t size, size_t *written) +{ + int ret, r = 0; + int retry_reason = 0; + SSL *ssl; + BIO_SSL *bs; + + if (buf == NULL) + return 0; + bs = BIO_get_data(b); + ssl = bs->ssl; + + BIO_clear_retry_flags(b); + + ret = ssl_write_internal(ssl, buf, size, written); + + switch (SSL_get_error(ssl, ret)) { + case SSL_ERROR_NONE: + if (bs->renegotiate_count > 0) { + bs->byte_count += *written; + if (bs->byte_count > bs->renegotiate_count) { + bs->byte_count = 0; + bs->num_renegotiates++; + SSL_renegotiate(ssl); + r = 1; + } + } + if ((bs->renegotiate_timeout > 0) && (!r)) { + unsigned long tm; + + tm = (unsigned long)time(NULL); + if (tm > bs->last_time + bs->renegotiate_timeout) { + bs->last_time = tm; + bs->num_renegotiates++; + SSL_renegotiate(ssl); + } + } + break; + case SSL_ERROR_WANT_WRITE: + BIO_set_retry_write(b); + break; + case SSL_ERROR_WANT_READ: + BIO_set_retry_read(b); + break; + case SSL_ERROR_WANT_X509_LOOKUP: + BIO_set_retry_special(b); + retry_reason = BIO_RR_SSL_X509_LOOKUP; + break; + case SSL_ERROR_WANT_CONNECT: + BIO_set_retry_special(b); + retry_reason = BIO_RR_CONNECT; + case SSL_ERROR_SYSCALL: + case SSL_ERROR_SSL: + default: + break; + } + + BIO_set_retry_reason(b, retry_reason); + + return ret; +} + +static long ssl_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + SSL **sslp, *ssl; + BIO_SSL *bs, *dbs; + BIO *dbio, *bio; + long ret = 1; + BIO *next; + + bs = BIO_get_data(b); + next = BIO_next(b); + ssl = bs->ssl; + if ((ssl == NULL) && (cmd != BIO_C_SET_SSL)) + return 0; + switch (cmd) { + case BIO_CTRL_RESET: + SSL_shutdown(ssl); + + if (ssl->handshake_func == ssl->method->ssl_connect) + SSL_set_connect_state(ssl); + else if (ssl->handshake_func == ssl->method->ssl_accept) + SSL_set_accept_state(ssl); + + if (!SSL_clear(ssl)) { + ret = 0; + break; + } + + if (next != NULL) + ret = BIO_ctrl(next, cmd, num, ptr); + else if (ssl->rbio != NULL) + ret = BIO_ctrl(ssl->rbio, cmd, num, ptr); + else + ret = 1; + break; + case BIO_CTRL_INFO: + ret = 0; + break; + case BIO_C_SSL_MODE: + if (num) /* client mode */ + SSL_set_connect_state(ssl); + else + SSL_set_accept_state(ssl); + break; + case BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT: + ret = bs->renegotiate_timeout; + if (num < 60) + num = 5; + bs->renegotiate_timeout = (unsigned long)num; + bs->last_time = (unsigned long)time(NULL); + break; + case BIO_C_SET_SSL_RENEGOTIATE_BYTES: + ret = bs->renegotiate_count; + if ((long)num >= 512) + bs->renegotiate_count = (unsigned long)num; + break; + case BIO_C_GET_SSL_NUM_RENEGOTIATES: + ret = bs->num_renegotiates; + break; + case BIO_C_SET_SSL: + if (ssl != NULL) { + ssl_free(b); + if (!ssl_new(b)) + return 0; + } + BIO_set_shutdown(b, num); + ssl = (SSL *)ptr; + bs->ssl = ssl; + bio = SSL_get_rbio(ssl); + if (bio != NULL) { + if (next != NULL) + BIO_push(bio, next); + BIO_set_next(b, bio); + BIO_up_ref(bio); + } + BIO_set_init(b, 1); + break; + case BIO_C_GET_SSL: + if (ptr != NULL) { + sslp = (SSL **)ptr; + *sslp = ssl; + } else + ret = 0; + break; + case BIO_CTRL_GET_CLOSE: + ret = BIO_get_shutdown(b); + break; + case BIO_CTRL_SET_CLOSE: + BIO_set_shutdown(b, (int)num); + break; + case BIO_CTRL_WPENDING: + ret = BIO_ctrl(ssl->wbio, cmd, num, ptr); + break; + case BIO_CTRL_PENDING: + ret = SSL_pending(ssl); + if (ret == 0) + ret = BIO_pending(ssl->rbio); + break; + case BIO_CTRL_FLUSH: + BIO_clear_retry_flags(b); + ret = BIO_ctrl(ssl->wbio, cmd, num, ptr); + BIO_copy_next_retry(b); + break; + case BIO_CTRL_PUSH: + if ((next != NULL) && (next != ssl->rbio)) { + /* + * We are going to pass ownership of next to the SSL object...but + * we don't own a reference to pass yet - so up ref + */ + BIO_up_ref(next); + SSL_set_bio(ssl, next, next); + } + break; + case BIO_CTRL_POP: + /* Only detach if we are the BIO explicitly being popped */ + if (b == ptr) { + /* This will clear the reference we obtained during push */ + SSL_set_bio(ssl, NULL, NULL); + } + break; + case BIO_C_DO_STATE_MACHINE: + BIO_clear_retry_flags(b); + + BIO_set_retry_reason(b, 0); + ret = (int)SSL_do_handshake(ssl); + + switch (SSL_get_error(ssl, (int)ret)) { + case SSL_ERROR_WANT_READ: + BIO_set_flags(b, BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY); + break; + case SSL_ERROR_WANT_WRITE: + BIO_set_flags(b, BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY); + break; + case SSL_ERROR_WANT_CONNECT: + BIO_set_flags(b, BIO_FLAGS_IO_SPECIAL | BIO_FLAGS_SHOULD_RETRY); + BIO_set_retry_reason(b, BIO_get_retry_reason(next)); + break; + case SSL_ERROR_WANT_X509_LOOKUP: + BIO_set_retry_special(b); + BIO_set_retry_reason(b, BIO_RR_SSL_X509_LOOKUP); + break; + default: + break; + } + break; + case BIO_CTRL_DUP: + dbio = (BIO *)ptr; + dbs = BIO_get_data(dbio); + SSL_free(dbs->ssl); + dbs->ssl = SSL_dup(ssl); + dbs->num_renegotiates = bs->num_renegotiates; + dbs->renegotiate_count = bs->renegotiate_count; + dbs->byte_count = bs->byte_count; + dbs->renegotiate_timeout = bs->renegotiate_timeout; + dbs->last_time = bs->last_time; + ret = (dbs->ssl != NULL); + break; + case BIO_C_GET_FD: + ret = BIO_ctrl(ssl->rbio, cmd, num, ptr); + break; + case BIO_CTRL_SET_CALLBACK: + ret = 0; /* use callback ctrl */ + break; + default: + ret = BIO_ctrl(ssl->rbio, cmd, num, ptr); + break; + } + return ret; +} + +static long ssl_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) +{ + SSL *ssl; + BIO_SSL *bs; + long ret = 1; + + bs = BIO_get_data(b); + ssl = bs->ssl; + switch (cmd) { + case BIO_CTRL_SET_CALLBACK: + ret = BIO_callback_ctrl(ssl->rbio, cmd, fp); + break; + default: + ret = 0; + break; + } + return ret; +} + +static int ssl_puts(BIO *bp, const char *str) +{ + int n, ret; + + n = strlen(str); + ret = BIO_write(bp, str, n); + return ret; +} + +BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx) +{ +#ifndef OPENSSL_NO_SOCK + BIO *ret = NULL, *buf = NULL, *ssl = NULL; + + if ((buf = BIO_new(BIO_f_buffer())) == NULL) + return NULL; + if ((ssl = BIO_new_ssl_connect(ctx)) == NULL) + goto err; + if ((ret = BIO_push(buf, ssl)) == NULL) + goto err; + return ret; + err: + BIO_free(buf); + BIO_free(ssl); +#endif + return NULL; +} + +BIO *BIO_new_ssl_connect(SSL_CTX *ctx) +{ +#ifndef OPENSSL_NO_SOCK + BIO *ret = NULL, *con = NULL, *ssl = NULL; + + if ((con = BIO_new(BIO_s_connect())) == NULL) + return NULL; + if ((ssl = BIO_new_ssl(ctx, 1)) == NULL) + goto err; + if ((ret = BIO_push(ssl, con)) == NULL) + goto err; + return ret; + err: + BIO_free(con); +#endif + return NULL; +} + +BIO *BIO_new_ssl(SSL_CTX *ctx, int client) +{ + BIO *ret; + SSL *ssl; + + if ((ret = BIO_new(BIO_f_ssl())) == NULL) + return NULL; + if ((ssl = SSL_new(ctx)) == NULL) { + BIO_free(ret); + return NULL; + } + if (client) + SSL_set_connect_state(ssl); + else + SSL_set_accept_state(ssl); + + BIO_set_ssl(ret, ssl, BIO_CLOSE); + return ret; +} + +int BIO_ssl_copy_session_id(BIO *t, BIO *f) +{ + BIO_SSL *tdata, *fdata; + t = BIO_find_type(t, BIO_TYPE_SSL); + f = BIO_find_type(f, BIO_TYPE_SSL); + if ((t == NULL) || (f == NULL)) + return 0; + tdata = BIO_get_data(t); + fdata = BIO_get_data(f); + if ((tdata->ssl == NULL) || (fdata->ssl == NULL)) + return 0; + if (!SSL_copy_session_id(tdata->ssl, (fdata->ssl))) + return 0; + return 1; +} + +void BIO_ssl_shutdown(BIO *b) +{ + BIO_SSL *bdata; + + for (; b != NULL; b = BIO_next(b)) { + if (BIO_method_type(b) != BIO_TYPE_SSL) + continue; + bdata = BIO_get_data(b); + if (bdata != NULL && bdata->ssl != NULL) + SSL_shutdown(bdata->ssl); + } +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/build.info b/trunk/3rdparty/openssl-1.1-fit/ssl/build.info new file mode 100644 index 000000000..bb2f1deb5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/build.info @@ -0,0 +1,15 @@ +LIBS=../libssl +SOURCE[../libssl]=\ + pqueue.c packet.c \ + statem/statem_srvr.c statem/statem_clnt.c s3_lib.c s3_enc.c record/rec_layer_s3.c \ + statem/statem_lib.c statem/extensions.c statem/extensions_srvr.c \ + statem/extensions_clnt.c statem/extensions_cust.c s3_cbc.c s3_msg.c \ + methods.c t1_lib.c t1_enc.c tls13_enc.c \ + d1_lib.c record/rec_layer_d1.c d1_msg.c \ + statem/statem_dtls.c d1_srtp.c \ + ssl_lib.c ssl_cert.c ssl_sess.c \ + ssl_ciph.c ssl_stat.c ssl_rsa.c \ + ssl_asn1.c ssl_txt.c ssl_init.c ssl_conf.c ssl_mcnf.c \ + bio_ssl.c ssl_err.c tls_srp.c t1_trce.c ssl_utst.c \ + record/ssl3_buffer.c record/ssl3_record.c record/dtls1_bitmap.c \ + statem/statem.c record/ssl3_record_tls13.c diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/d1_lib.c b/trunk/3rdparty/openssl-1.1-fit/ssl/d1_lib.c new file mode 100644 index 000000000..fcda32754 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/d1_lib.c @@ -0,0 +1,972 @@ +/* + * Copyright 2005-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "e_os.h" +#include +#include +#include +#include "ssl_locl.h" + +static void get_current_time(struct timeval *t); +static int dtls1_handshake_write(SSL *s); +static size_t dtls1_link_min_mtu(void); + +/* XDTLS: figure out the right values */ +static const size_t g_probable_mtu[] = { 1500, 512, 256 }; + +const SSL3_ENC_METHOD DTLSv1_enc_data = { + tls1_enc, + tls1_mac, + tls1_setup_key_block, + tls1_generate_master_secret, + tls1_change_cipher_state, + tls1_final_finish_mac, + TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE, + TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE, + tls1_alert_code, + tls1_export_keying_material, + SSL_ENC_FLAG_DTLS | SSL_ENC_FLAG_EXPLICIT_IV, + dtls1_set_handshake_header, + dtls1_close_construct_packet, + dtls1_handshake_write +}; + +const SSL3_ENC_METHOD DTLSv1_2_enc_data = { + tls1_enc, + tls1_mac, + tls1_setup_key_block, + tls1_generate_master_secret, + tls1_change_cipher_state, + tls1_final_finish_mac, + TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE, + TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE, + tls1_alert_code, + tls1_export_keying_material, + SSL_ENC_FLAG_DTLS | SSL_ENC_FLAG_EXPLICIT_IV | SSL_ENC_FLAG_SIGALGS + | SSL_ENC_FLAG_SHA256_PRF | SSL_ENC_FLAG_TLS1_2_CIPHERS, + dtls1_set_handshake_header, + dtls1_close_construct_packet, + dtls1_handshake_write +}; + +long dtls1_default_timeout(void) +{ + /* + * 2 hours, the 24 hours mentioned in the DTLSv1 spec is way too long for + * http, the cache would over fill + */ + return (60 * 60 * 2); +} + +int dtls1_new(SSL *s) +{ + DTLS1_STATE *d1; + + if (!DTLS_RECORD_LAYER_new(&s->rlayer)) { + return 0; + } + + if (!ssl3_new(s)) + return 0; + if ((d1 = OPENSSL_zalloc(sizeof(*d1))) == NULL) { + ssl3_free(s); + return 0; + } + + d1->buffered_messages = pqueue_new(); + d1->sent_messages = pqueue_new(); + + if (s->server) { + d1->cookie_len = sizeof(s->d1->cookie); + } + + d1->link_mtu = 0; + d1->mtu = 0; + + if (d1->buffered_messages == NULL || d1->sent_messages == NULL) { + pqueue_free(d1->buffered_messages); + pqueue_free(d1->sent_messages); + OPENSSL_free(d1); + ssl3_free(s); + return 0; + } + + s->d1 = d1; + + if (!s->method->ssl_clear(s)) + return 0; + + return 1; +} + +static void dtls1_clear_queues(SSL *s) +{ + dtls1_clear_received_buffer(s); + dtls1_clear_sent_buffer(s); +} + +void dtls1_clear_received_buffer(SSL *s) +{ + pitem *item = NULL; + hm_fragment *frag = NULL; + + while ((item = pqueue_pop(s->d1->buffered_messages)) != NULL) { + frag = (hm_fragment *)item->data; + dtls1_hm_fragment_free(frag); + pitem_free(item); + } +} + +void dtls1_clear_sent_buffer(SSL *s) +{ + pitem *item = NULL; + hm_fragment *frag = NULL; + + while ((item = pqueue_pop(s->d1->sent_messages)) != NULL) { + frag = (hm_fragment *)item->data; + dtls1_hm_fragment_free(frag); + pitem_free(item); + } +} + + +void dtls1_free(SSL *s) +{ + DTLS_RECORD_LAYER_free(&s->rlayer); + + ssl3_free(s); + + dtls1_clear_queues(s); + + pqueue_free(s->d1->buffered_messages); + pqueue_free(s->d1->sent_messages); + + OPENSSL_free(s->d1); + s->d1 = NULL; +} + +int dtls1_clear(SSL *s) +{ + pqueue *buffered_messages; + pqueue *sent_messages; + size_t mtu; + size_t link_mtu; + + DTLS_RECORD_LAYER_clear(&s->rlayer); + + if (s->d1) { + DTLS_timer_cb timer_cb = s->d1->timer_cb; + + buffered_messages = s->d1->buffered_messages; + sent_messages = s->d1->sent_messages; + mtu = s->d1->mtu; + link_mtu = s->d1->link_mtu; + + dtls1_clear_queues(s); + + memset(s->d1, 0, sizeof(*s->d1)); + + /* Restore the timer callback from previous state */ + s->d1->timer_cb = timer_cb; + + if (s->server) { + s->d1->cookie_len = sizeof(s->d1->cookie); + } + + if (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU) { + s->d1->mtu = mtu; + s->d1->link_mtu = link_mtu; + } + + s->d1->buffered_messages = buffered_messages; + s->d1->sent_messages = sent_messages; + } + + if (!ssl3_clear(s)) + return 0; + + if (s->method->version == DTLS_ANY_VERSION) + s->version = DTLS_MAX_VERSION; +#ifndef OPENSSL_NO_DTLS1_METHOD + else if (s->options & SSL_OP_CISCO_ANYCONNECT) + s->client_version = s->version = DTLS1_BAD_VER; +#endif + else + s->version = s->method->version; + + return 1; +} + +long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg) +{ + int ret = 0; + + switch (cmd) { + case DTLS_CTRL_GET_TIMEOUT: + if (dtls1_get_timeout(s, (struct timeval *)parg) != NULL) { + ret = 1; + } + break; + case DTLS_CTRL_HANDLE_TIMEOUT: + ret = dtls1_handle_timeout(s); + break; + case DTLS_CTRL_SET_LINK_MTU: + if (larg < (long)dtls1_link_min_mtu()) + return 0; + s->d1->link_mtu = larg; + return 1; + case DTLS_CTRL_GET_LINK_MIN_MTU: + return (long)dtls1_link_min_mtu(); + case SSL_CTRL_SET_MTU: + /* + * We may not have a BIO set yet so can't call dtls1_min_mtu() + * We'll have to make do with dtls1_link_min_mtu() and max overhead + */ + if (larg < (long)dtls1_link_min_mtu() - DTLS1_MAX_MTU_OVERHEAD) + return 0; + s->d1->mtu = larg; + return larg; + default: + ret = ssl3_ctrl(s, cmd, larg, parg); + break; + } + return ret; +} + +void dtls1_start_timer(SSL *s) +{ + unsigned int sec, usec; + +#ifndef OPENSSL_NO_SCTP + /* Disable timer for SCTP */ + if (BIO_dgram_is_sctp(SSL_get_wbio(s))) { + memset(&s->d1->next_timeout, 0, sizeof(s->d1->next_timeout)); + return; + } +#endif + + /* + * If timer is not set, initialize duration with 1 second or + * a user-specified value if the timer callback is installed. + */ + if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) { + + if (s->d1->timer_cb != NULL) + s->d1->timeout_duration_us = s->d1->timer_cb(s, 0); + else + s->d1->timeout_duration_us = 1000000; + } + + /* Set timeout to current time */ + get_current_time(&(s->d1->next_timeout)); + + /* Add duration to current time */ + + sec = s->d1->timeout_duration_us / 1000000; + usec = s->d1->timeout_duration_us - (sec * 1000000); + + s->d1->next_timeout.tv_sec += sec; + s->d1->next_timeout.tv_usec += usec; + + if (s->d1->next_timeout.tv_usec >= 1000000) { + s->d1->next_timeout.tv_sec++; + s->d1->next_timeout.tv_usec -= 1000000; + } + + BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, + &(s->d1->next_timeout)); +} + +struct timeval *dtls1_get_timeout(SSL *s, struct timeval *timeleft) +{ + struct timeval timenow; + + /* If no timeout is set, just return NULL */ + if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) { + return NULL; + } + + /* Get current time */ + get_current_time(&timenow); + + /* If timer already expired, set remaining time to 0 */ + if (s->d1->next_timeout.tv_sec < timenow.tv_sec || + (s->d1->next_timeout.tv_sec == timenow.tv_sec && + s->d1->next_timeout.tv_usec <= timenow.tv_usec)) { + memset(timeleft, 0, sizeof(*timeleft)); + return timeleft; + } + + /* Calculate time left until timer expires */ + memcpy(timeleft, &(s->d1->next_timeout), sizeof(struct timeval)); + timeleft->tv_sec -= timenow.tv_sec; + timeleft->tv_usec -= timenow.tv_usec; + if (timeleft->tv_usec < 0) { + timeleft->tv_sec--; + timeleft->tv_usec += 1000000; + } + + /* + * If remaining time is less than 15 ms, set it to 0 to prevent issues + * because of small divergences with socket timeouts. + */ + if (timeleft->tv_sec == 0 && timeleft->tv_usec < 15000) { + memset(timeleft, 0, sizeof(*timeleft)); + } + + return timeleft; +} + +int dtls1_is_timer_expired(SSL *s) +{ + struct timeval timeleft; + + /* Get time left until timeout, return false if no timer running */ + if (dtls1_get_timeout(s, &timeleft) == NULL) { + return 0; + } + + /* Return false if timer is not expired yet */ + if (timeleft.tv_sec > 0 || timeleft.tv_usec > 0) { + return 0; + } + + /* Timer expired, so return true */ + return 1; +} + +void dtls1_double_timeout(SSL *s) +{ + s->d1->timeout_duration_us *= 2; + if (s->d1->timeout_duration_us > 60000000) + s->d1->timeout_duration_us = 60000000; + dtls1_start_timer(s); +} + +void dtls1_stop_timer(SSL *s) +{ + /* Reset everything */ + memset(&s->d1->timeout, 0, sizeof(s->d1->timeout)); + memset(&s->d1->next_timeout, 0, sizeof(s->d1->next_timeout)); + s->d1->timeout_duration_us = 1000000; + BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, + &(s->d1->next_timeout)); + /* Clear retransmission buffer */ + dtls1_clear_sent_buffer(s); +} + +int dtls1_check_timeout_num(SSL *s) +{ + size_t mtu; + + s->d1->timeout.num_alerts++; + + /* Reduce MTU after 2 unsuccessful retransmissions */ + if (s->d1->timeout.num_alerts > 2 + && !(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) { + mtu = + BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL); + if (mtu < s->d1->mtu) + s->d1->mtu = mtu; + } + + if (s->d1->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT) { + /* fail the connection, enough alerts have been sent */ + SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_DTLS1_CHECK_TIMEOUT_NUM, + SSL_R_READ_TIMEOUT_EXPIRED); + return -1; + } + + return 0; +} + +int dtls1_handle_timeout(SSL *s) +{ + /* if no timer is expired, don't do anything */ + if (!dtls1_is_timer_expired(s)) { + return 0; + } + + if (s->d1->timer_cb != NULL) + s->d1->timeout_duration_us = s->d1->timer_cb(s, s->d1->timeout_duration_us); + else + dtls1_double_timeout(s); + + if (dtls1_check_timeout_num(s) < 0) { + /* SSLfatal() already called */ + return -1; + } + + s->d1->timeout.read_timeouts++; + if (s->d1->timeout.read_timeouts > DTLS1_TMO_READ_COUNT) { + s->d1->timeout.read_timeouts = 1; + } + + dtls1_start_timer(s); + /* Calls SSLfatal() if required */ + return dtls1_retransmit_buffered_messages(s); +} + +static void get_current_time(struct timeval *t) +{ +#if defined(_WIN32) + SYSTEMTIME st; + union { + unsigned __int64 ul; + FILETIME ft; + } now; + + GetSystemTime(&st); + SystemTimeToFileTime(&st, &now.ft); + /* re-bias to 1/1/1970 */ +# ifdef __MINGW32__ + now.ul -= 116444736000000000ULL; +# else + /* *INDENT-OFF* */ + now.ul -= 116444736000000000UI64; + /* *INDENT-ON* */ +# endif + t->tv_sec = (long)(now.ul / 10000000); + t->tv_usec = ((int)(now.ul % 10000000)) / 10; +#else + gettimeofday(t, NULL); +#endif +} + +#define LISTEN_SUCCESS 2 +#define LISTEN_SEND_VERIFY_REQUEST 1 + +#ifndef OPENSSL_NO_SOCK +int DTLSv1_listen(SSL *s, BIO_ADDR *client) +{ + int next, n, ret = 0; + unsigned char cookie[DTLS1_COOKIE_LENGTH]; + unsigned char seq[SEQ_NUM_SIZE]; + const unsigned char *data; + unsigned char *buf, *wbuf; + size_t fragoff, fraglen, msglen, reclen, align = 0; + unsigned int rectype, versmajor, msgseq, msgtype, clientvers, cookielen; + BIO *rbio, *wbio; + BIO_ADDR *tmpclient = NULL; + PACKET pkt, msgpkt, msgpayload, session, cookiepkt; + + if (s->handshake_func == NULL) { + /* Not properly initialized yet */ + SSL_set_accept_state(s); + } + + /* Ensure there is no state left over from a previous invocation */ + if (!SSL_clear(s)) + return -1; + + ERR_clear_error(); + + rbio = SSL_get_rbio(s); + wbio = SSL_get_wbio(s); + + if (!rbio || !wbio) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_BIO_NOT_SET); + return -1; + } + + /* + * Note: This check deliberately excludes DTLS1_BAD_VER because that version + * requires the MAC to be calculated *including* the first ClientHello + * (without the cookie). Since DTLSv1_listen is stateless that cannot be + * supported. DTLS1_BAD_VER must use cookies in a stateful manner (e.g. via + * SSL_accept) + */ + if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00)) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNSUPPORTED_SSL_VERSION); + return -1; + } + + if (!ssl3_setup_buffers(s)) { + /* SSLerr already called */ + return -1; + } + buf = RECORD_LAYER_get_rbuf(&s->rlayer)->buf; + wbuf = RECORD_LAYER_get_wbuf(&s->rlayer)[0].buf; +#if defined(SSL3_ALIGN_PAYLOAD) +# if SSL3_ALIGN_PAYLOAD != 0 + /* + * Using SSL3_RT_HEADER_LENGTH here instead of DTLS1_RT_HEADER_LENGTH for + * consistency with ssl3_read_n. In practice it should make no difference + * for sensible values of SSL3_ALIGN_PAYLOAD because the difference between + * SSL3_RT_HEADER_LENGTH and DTLS1_RT_HEADER_LENGTH is exactly 8 + */ + align = (size_t)buf + SSL3_RT_HEADER_LENGTH; + align = SSL3_ALIGN_PAYLOAD - 1 - ((align - 1) % SSL3_ALIGN_PAYLOAD); +# endif +#endif + buf += align; + + do { + /* Get a packet */ + + clear_sys_error(); + n = BIO_read(rbio, buf, SSL3_RT_MAX_PLAIN_LENGTH + + DTLS1_RT_HEADER_LENGTH); + if (n <= 0) { + if (BIO_should_retry(rbio)) { + /* Non-blocking IO */ + goto end; + } + return -1; + } + + if (!PACKET_buf_init(&pkt, buf, n)) { + SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_INTERNAL_ERROR); + return -1; + } + + /* + * Parse the received record. If there are any problems with it we just + * dump it - with no alert. RFC6347 says this "Unlike TLS, DTLS is + * resilient in the face of invalid records (e.g., invalid formatting, + * length, MAC, etc.). In general, invalid records SHOULD be silently + * discarded, thus preserving the association; however, an error MAY be + * logged for diagnostic purposes." + */ + + /* this packet contained a partial record, dump it */ + if (n < DTLS1_RT_HEADER_LENGTH) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_RECORD_TOO_SMALL); + goto end; + } + + if (s->msg_callback) + s->msg_callback(0, 0, SSL3_RT_HEADER, buf, + DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg); + + /* Get the record header */ + if (!PACKET_get_1(&pkt, &rectype) + || !PACKET_get_1(&pkt, &versmajor)) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH); + goto end; + } + + if (rectype != SSL3_RT_HANDSHAKE) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE); + goto end; + } + + /* + * Check record version number. We only check that the major version is + * the same. + */ + if (versmajor != DTLS1_VERSION_MAJOR) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_BAD_PROTOCOL_VERSION_NUMBER); + goto end; + } + + if (!PACKET_forward(&pkt, 1) + /* Save the sequence number: 64 bits, with top 2 bytes = epoch */ + || !PACKET_copy_bytes(&pkt, seq, SEQ_NUM_SIZE) + || !PACKET_get_length_prefixed_2(&pkt, &msgpkt)) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH); + goto end; + } + reclen = PACKET_remaining(&msgpkt); + /* + * We allow data remaining at the end of the packet because there could + * be a second record (but we ignore it) + */ + + /* This is an initial ClientHello so the epoch has to be 0 */ + if (seq[0] != 0 || seq[1] != 0) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE); + goto end; + } + + /* Get a pointer to the raw message for the later callback */ + data = PACKET_data(&msgpkt); + + /* Finished processing the record header, now process the message */ + if (!PACKET_get_1(&msgpkt, &msgtype) + || !PACKET_get_net_3_len(&msgpkt, &msglen) + || !PACKET_get_net_2(&msgpkt, &msgseq) + || !PACKET_get_net_3_len(&msgpkt, &fragoff) + || !PACKET_get_net_3_len(&msgpkt, &fraglen) + || !PACKET_get_sub_packet(&msgpkt, &msgpayload, fraglen) + || PACKET_remaining(&msgpkt) != 0) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH); + goto end; + } + + if (msgtype != SSL3_MT_CLIENT_HELLO) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE); + goto end; + } + + /* Message sequence number can only be 0 or 1 */ + if (msgseq > 2) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_INVALID_SEQUENCE_NUMBER); + goto end; + } + + /* + * We don't support fragment reassembly for ClientHellos whilst + * listening because that would require server side state (which is + * against the whole point of the ClientHello/HelloVerifyRequest + * mechanism). Instead we only look at the first ClientHello fragment + * and require that the cookie must be contained within it. + */ + if (fragoff != 0 || fraglen > msglen) { + /* Non initial ClientHello fragment (or bad fragment) */ + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_FRAGMENTED_CLIENT_HELLO); + goto end; + } + + if (s->msg_callback) + s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, data, + fraglen + DTLS1_HM_HEADER_LENGTH, s, + s->msg_callback_arg); + + if (!PACKET_get_net_2(&msgpayload, &clientvers)) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH); + goto end; + } + + /* + * Verify client version is supported + */ + if (DTLS_VERSION_LT(clientvers, (unsigned int)s->method->version) && + s->method->version != DTLS_ANY_VERSION) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_WRONG_VERSION_NUMBER); + goto end; + } + + if (!PACKET_forward(&msgpayload, SSL3_RANDOM_SIZE) + || !PACKET_get_length_prefixed_1(&msgpayload, &session) + || !PACKET_get_length_prefixed_1(&msgpayload, &cookiepkt)) { + /* + * Could be malformed or the cookie does not fit within the initial + * ClientHello fragment. Either way we can't handle it. + */ + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH); + goto end; + } + + /* + * Check if we have a cookie or not. If not we need to send a + * HelloVerifyRequest. + */ + if (PACKET_remaining(&cookiepkt) == 0) { + next = LISTEN_SEND_VERIFY_REQUEST; + } else { + /* + * We have a cookie, so lets check it. + */ + if (s->ctx->app_verify_cookie_cb == NULL) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_NO_VERIFY_COOKIE_CALLBACK); + /* This is fatal */ + return -1; + } + if (s->ctx->app_verify_cookie_cb(s, PACKET_data(&cookiepkt), + (unsigned int)PACKET_remaining(&cookiepkt)) == 0) { + /* + * We treat invalid cookies in the same was as no cookie as + * per RFC6347 + */ + next = LISTEN_SEND_VERIFY_REQUEST; + } else { + /* Cookie verification succeeded */ + next = LISTEN_SUCCESS; + } + } + + if (next == LISTEN_SEND_VERIFY_REQUEST) { + WPACKET wpkt; + unsigned int version; + size_t wreclen; + + /* + * There was no cookie in the ClientHello so we need to send a + * HelloVerifyRequest. If this fails we do not worry about trying + * to resend, we just drop it. + */ + + /* Generate the cookie */ + if (s->ctx->app_gen_cookie_cb == NULL || + s->ctx->app_gen_cookie_cb(s, cookie, &cookielen) == 0 || + cookielen > 255) { + SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_COOKIE_GEN_CALLBACK_FAILURE); + /* This is fatal */ + return -1; + } + + /* + * Special case: for hello verify request, client version 1.0 and we + * haven't decided which version to use yet send back using version + * 1.0 header: otherwise some clients will ignore it. + */ + version = (s->method->version == DTLS_ANY_VERSION) ? DTLS1_VERSION + : s->version; + + /* Construct the record and message headers */ + if (!WPACKET_init_static_len(&wpkt, + wbuf, + ssl_get_max_send_fragment(s) + + DTLS1_RT_HEADER_LENGTH, + 0) + || !WPACKET_put_bytes_u8(&wpkt, SSL3_RT_HANDSHAKE) + || !WPACKET_put_bytes_u16(&wpkt, version) + /* + * Record sequence number is always the same as in the + * received ClientHello + */ + || !WPACKET_memcpy(&wpkt, seq, SEQ_NUM_SIZE) + /* End of record, start sub packet for message */ + || !WPACKET_start_sub_packet_u16(&wpkt) + /* Message type */ + || !WPACKET_put_bytes_u8(&wpkt, + DTLS1_MT_HELLO_VERIFY_REQUEST) + /* + * Message length - doesn't follow normal TLS convention: + * the length isn't the last thing in the message header. + * We'll need to fill this in later when we know the + * length. Set it to zero for now + */ + || !WPACKET_put_bytes_u24(&wpkt, 0) + /* + * Message sequence number is always 0 for a + * HelloVerifyRequest + */ + || !WPACKET_put_bytes_u16(&wpkt, 0) + /* + * We never fragment a HelloVerifyRequest, so fragment + * offset is 0 + */ + || !WPACKET_put_bytes_u24(&wpkt, 0) + /* + * Fragment length is the same as message length, but + * this *is* the last thing in the message header so we + * can just start a sub-packet. No need to come back + * later for this one. + */ + || !WPACKET_start_sub_packet_u24(&wpkt) + /* Create the actual HelloVerifyRequest body */ + || !dtls_raw_hello_verify_request(&wpkt, cookie, cookielen) + /* Close message body */ + || !WPACKET_close(&wpkt) + /* Close record body */ + || !WPACKET_close(&wpkt) + || !WPACKET_get_total_written(&wpkt, &wreclen) + || !WPACKET_finish(&wpkt)) { + SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_INTERNAL_ERROR); + WPACKET_cleanup(&wpkt); + /* This is fatal */ + return -1; + } + + /* + * Fix up the message len in the message header. Its the same as the + * fragment len which has been filled in by WPACKET, so just copy + * that. Destination for the message len is after the record header + * plus one byte for the message content type. The source is the + * last 3 bytes of the message header + */ + memcpy(&wbuf[DTLS1_RT_HEADER_LENGTH + 1], + &wbuf[DTLS1_RT_HEADER_LENGTH + DTLS1_HM_HEADER_LENGTH - 3], + 3); + + if (s->msg_callback) + s->msg_callback(1, 0, SSL3_RT_HEADER, buf, + DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg); + + if ((tmpclient = BIO_ADDR_new()) == NULL) { + SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_MALLOC_FAILURE); + goto end; + } + + /* + * This is unnecessary if rbio and wbio are one and the same - but + * maybe they're not. We ignore errors here - some BIOs do not + * support this. + */ + if (BIO_dgram_get_peer(rbio, tmpclient) > 0) { + (void)BIO_dgram_set_peer(wbio, tmpclient); + } + BIO_ADDR_free(tmpclient); + tmpclient = NULL; + + /* TODO(size_t): convert this call */ + if (BIO_write(wbio, wbuf, wreclen) < (int)wreclen) { + if (BIO_should_retry(wbio)) { + /* + * Non-blocking IO...but we're stateless, so we're just + * going to drop this packet. + */ + goto end; + } + return -1; + } + + if (BIO_flush(wbio) <= 0) { + if (BIO_should_retry(wbio)) { + /* + * Non-blocking IO...but we're stateless, so we're just + * going to drop this packet. + */ + goto end; + } + return -1; + } + } + } while (next != LISTEN_SUCCESS); + + /* + * Set expected sequence numbers to continue the handshake. + */ + s->d1->handshake_read_seq = 1; + s->d1->handshake_write_seq = 1; + s->d1->next_handshake_write_seq = 1; + DTLS_RECORD_LAYER_set_write_sequence(&s->rlayer, seq); + + /* + * We are doing cookie exchange, so make sure we set that option in the + * SSL object + */ + SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE); + + /* + * Tell the state machine that we've done the initial hello verify + * exchange + */ + ossl_statem_set_hello_verify_done(s); + + /* + * Some BIOs may not support this. If we fail we clear the client address + */ + if (BIO_dgram_get_peer(rbio, client) <= 0) + BIO_ADDR_clear(client); + + /* Buffer the record in the processed_rcds queue */ + if (!dtls_buffer_listen_record(s, reclen, seq, align)) + return -1; + + ret = 1; + end: + BIO_ADDR_free(tmpclient); + return ret; +} +#endif + +static int dtls1_handshake_write(SSL *s) +{ + return dtls1_do_write(s, SSL3_RT_HANDSHAKE); +} + +int dtls1_shutdown(SSL *s) +{ + int ret; +#ifndef OPENSSL_NO_SCTP + BIO *wbio; + + wbio = SSL_get_wbio(s); + if (wbio != NULL && BIO_dgram_is_sctp(wbio) && + !(s->shutdown & SSL_SENT_SHUTDOWN)) { + ret = BIO_dgram_sctp_wait_for_dry(wbio); + if (ret < 0) + return -1; + + if (ret == 0) + BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN, 1, + NULL); + } +#endif + ret = ssl3_shutdown(s); +#ifndef OPENSSL_NO_SCTP + BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN, 0, NULL); +#endif + return ret; +} + +int dtls1_query_mtu(SSL *s) +{ + if (s->d1->link_mtu) { + s->d1->mtu = + s->d1->link_mtu - BIO_dgram_get_mtu_overhead(SSL_get_wbio(s)); + s->d1->link_mtu = 0; + } + + /* AHA! Figure out the MTU, and stick to the right size */ + if (s->d1->mtu < dtls1_min_mtu(s)) { + if (!(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) { + s->d1->mtu = + BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); + + /* + * I've seen the kernel return bogus numbers when it doesn't know + * (initial write), so just make sure we have a reasonable number + */ + if (s->d1->mtu < dtls1_min_mtu(s)) { + /* Set to min mtu */ + s->d1->mtu = dtls1_min_mtu(s); + BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SET_MTU, + (long)s->d1->mtu, NULL); + } + } else + return 0; + } + return 1; +} + +static size_t dtls1_link_min_mtu(void) +{ + return (g_probable_mtu[(sizeof(g_probable_mtu) / + sizeof(g_probable_mtu[0])) - 1]); +} + +size_t dtls1_min_mtu(SSL *s) +{ + return dtls1_link_min_mtu() - BIO_dgram_get_mtu_overhead(SSL_get_wbio(s)); +} + +size_t DTLS_get_data_mtu(const SSL *s) +{ + size_t mac_overhead, int_overhead, blocksize, ext_overhead; + const SSL_CIPHER *ciph = SSL_get_current_cipher(s); + size_t mtu = s->d1->mtu; + + if (ciph == NULL) + return 0; + + if (!ssl_cipher_get_overhead(ciph, &mac_overhead, &int_overhead, + &blocksize, &ext_overhead)) + return 0; + + if (SSL_READ_ETM(s)) + ext_overhead += mac_overhead; + else + int_overhead += mac_overhead; + + /* Subtract external overhead (e.g. IV/nonce, separate MAC) */ + if (ext_overhead + DTLS1_RT_HEADER_LENGTH >= mtu) + return 0; + mtu -= ext_overhead + DTLS1_RT_HEADER_LENGTH; + + /* Round encrypted payload down to cipher block size (for CBC etc.) + * No check for overflow since 'mtu % blocksize' cannot exceed mtu. */ + if (blocksize) + mtu -= (mtu % blocksize); + + /* Subtract internal overhead (e.g. CBC padding len byte) */ + if (int_overhead >= mtu) + return 0; + mtu -= int_overhead; + + return mtu; +} + +void DTLS_set_timer_cb(SSL *s, DTLS_timer_cb cb) +{ + s->d1->timer_cb = cb; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/d1_msg.c b/trunk/3rdparty/openssl-1.1-fit/ssl/d1_msg.c new file mode 100644 index 000000000..5906e88ca --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/d1_msg.c @@ -0,0 +1,73 @@ +/* + * Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "ssl_locl.h" + +int dtls1_write_app_data_bytes(SSL *s, int type, const void *buf_, size_t len, + size_t *written) +{ + int i; + + if (SSL_in_init(s) && !ossl_statem_get_in_handshake(s)) { + i = s->handshake_func(s); + if (i < 0) + return i; + if (i == 0) { + SSLerr(SSL_F_DTLS1_WRITE_APP_DATA_BYTES, + SSL_R_SSL_HANDSHAKE_FAILURE); + return -1; + } + } + + if (len > SSL3_RT_MAX_PLAIN_LENGTH) { + SSLerr(SSL_F_DTLS1_WRITE_APP_DATA_BYTES, SSL_R_DTLS_MESSAGE_TOO_BIG); + return -1; + } + + return dtls1_write_bytes(s, type, buf_, len, written); +} + +int dtls1_dispatch_alert(SSL *s) +{ + int i, j; + void (*cb) (const SSL *ssl, int type, int val) = NULL; + unsigned char buf[DTLS1_AL_HEADER_LENGTH]; + unsigned char *ptr = &buf[0]; + size_t written; + + s->s3->alert_dispatch = 0; + + memset(buf, 0, sizeof(buf)); + *ptr++ = s->s3->send_alert[0]; + *ptr++ = s->s3->send_alert[1]; + + i = do_dtls1_write(s, SSL3_RT_ALERT, &buf[0], sizeof(buf), 0, &written); + if (i <= 0) { + s->s3->alert_dispatch = 1; + /* fprintf( stderr, "not done with alert\n" ); */ + } else { + if (s->s3->send_alert[0] == SSL3_AL_FATAL) + (void)BIO_flush(s->wbio); + + if (s->msg_callback) + s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3->send_alert, + 2, s, s->msg_callback_arg); + + if (s->info_callback != NULL) + cb = s->info_callback; + else if (s->ctx->info_callback != NULL) + cb = s->ctx->info_callback; + + if (cb != NULL) { + j = (s->s3->send_alert[0] << 8) | s->s3->send_alert[1]; + cb(s, SSL_CB_WRITE_ALERT, j); + } + } + return i; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/d1_srtp.c b/trunk/3rdparty/openssl-1.1-fit/ssl/d1_srtp.c new file mode 100644 index 000000000..ff8f0c571 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/d1_srtp.c @@ -0,0 +1,139 @@ +/* + * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * DTLS code by Eric Rescorla + * + * Copyright (C) 2006, Network Resonance, Inc. Copyright (C) 2011, RTFM, Inc. + */ + +#include +#include +#include "ssl_locl.h" + +#ifndef OPENSSL_NO_SRTP + +static SRTP_PROTECTION_PROFILE srtp_known_profiles[] = { + { + "SRTP_AES128_CM_SHA1_80", + SRTP_AES128_CM_SHA1_80, + }, + { + "SRTP_AES128_CM_SHA1_32", + SRTP_AES128_CM_SHA1_32, + }, + { + "SRTP_AEAD_AES_128_GCM", + SRTP_AEAD_AES_128_GCM, + }, + { + "SRTP_AEAD_AES_256_GCM", + SRTP_AEAD_AES_256_GCM, + }, + {0} +}; + +static int find_profile_by_name(char *profile_name, + SRTP_PROTECTION_PROFILE **pptr, size_t len) +{ + SRTP_PROTECTION_PROFILE *p; + + p = srtp_known_profiles; + while (p->name) { + if ((len == strlen(p->name)) + && strncmp(p->name, profile_name, len) == 0) { + *pptr = p; + return 0; + } + + p++; + } + + return 1; +} + +static int ssl_ctx_make_profiles(const char *profiles_string, + STACK_OF(SRTP_PROTECTION_PROFILE) **out) +{ + STACK_OF(SRTP_PROTECTION_PROFILE) *profiles; + + char *col; + char *ptr = (char *)profiles_string; + SRTP_PROTECTION_PROFILE *p; + + if ((profiles = sk_SRTP_PROTECTION_PROFILE_new_null()) == NULL) { + SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES, + SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES); + return 1; + } + + do { + col = strchr(ptr, ':'); + + if (!find_profile_by_name(ptr, &p, col ? (size_t)(col - ptr) + : strlen(ptr))) { + if (sk_SRTP_PROTECTION_PROFILE_find(profiles, p) >= 0) { + SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES, + SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); + goto err; + } + + if (!sk_SRTP_PROTECTION_PROFILE_push(profiles, p)) { + SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES, + SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES); + goto err; + } + } else { + SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES, + SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE); + goto err; + } + + if (col) + ptr = col + 1; + } while (col); + + sk_SRTP_PROTECTION_PROFILE_free(*out); + + *out = profiles; + + return 0; + err: + sk_SRTP_PROTECTION_PROFILE_free(profiles); + return 1; +} + +int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx, const char *profiles) +{ + return ssl_ctx_make_profiles(profiles, &ctx->srtp_profiles); +} + +int SSL_set_tlsext_use_srtp(SSL *s, const char *profiles) +{ + return ssl_ctx_make_profiles(profiles, &s->srtp_profiles); +} + +STACK_OF(SRTP_PROTECTION_PROFILE) *SSL_get_srtp_profiles(SSL *s) +{ + if (s != NULL) { + if (s->srtp_profiles != NULL) { + return s->srtp_profiles; + } else if ((s->ctx != NULL) && (s->ctx->srtp_profiles != NULL)) { + return s->ctx->srtp_profiles; + } + } + + return NULL; +} + +SRTP_PROTECTION_PROFILE *SSL_get_selected_srtp_profile(SSL *s) +{ + return s->srtp_profile; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/methods.c b/trunk/3rdparty/openssl-1.1-fit/ssl/methods.c new file mode 100644 index 000000000..348efe467 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/methods.c @@ -0,0 +1,278 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "ssl_locl.h" + +/*- + * TLS/SSLv3 methods + */ + +IMPLEMENT_tls_meth_func(TLS_ANY_VERSION, 0, 0, + TLS_method, + ossl_statem_accept, + ossl_statem_connect, TLSv1_2_enc_data) +IMPLEMENT_tls_meth_func(TLS1_3_VERSION, 0, SSL_OP_NO_TLSv1_3, + tlsv1_3_method, + ossl_statem_accept, + ossl_statem_connect, TLSv1_3_enc_data) +#ifndef OPENSSL_NO_TLS1_2_METHOD +IMPLEMENT_tls_meth_func(TLS1_2_VERSION, 0, SSL_OP_NO_TLSv1_2, + tlsv1_2_method, + ossl_statem_accept, + ossl_statem_connect, TLSv1_2_enc_data) +#endif +#ifndef OPENSSL_NO_TLS1_1_METHOD +IMPLEMENT_tls_meth_func(TLS1_1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1_1, + tlsv1_1_method, + ossl_statem_accept, + ossl_statem_connect, TLSv1_1_enc_data) +#endif +#ifndef OPENSSL_NO_TLS1_METHOD +IMPLEMENT_tls_meth_func(TLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1, + tlsv1_method, + ossl_statem_accept, ossl_statem_connect, TLSv1_enc_data) +#endif +#ifndef OPENSSL_NO_SSL3_METHOD +IMPLEMENT_ssl3_meth_func(sslv3_method, ossl_statem_accept, ossl_statem_connect) +#endif +/*- + * TLS/SSLv3 server methods + */ +IMPLEMENT_tls_meth_func(TLS_ANY_VERSION, 0, 0, + TLS_server_method, + ossl_statem_accept, + ssl_undefined_function, TLSv1_2_enc_data) +IMPLEMENT_tls_meth_func(TLS1_3_VERSION, 0, SSL_OP_NO_TLSv1_3, + tlsv1_3_server_method, + ossl_statem_accept, + ssl_undefined_function, TLSv1_3_enc_data) +#ifndef OPENSSL_NO_TLS1_2_METHOD +IMPLEMENT_tls_meth_func(TLS1_2_VERSION, 0, SSL_OP_NO_TLSv1_2, + tlsv1_2_server_method, + ossl_statem_accept, + ssl_undefined_function, TLSv1_2_enc_data) +#endif +#ifndef OPENSSL_NO_TLS1_1_METHOD +IMPLEMENT_tls_meth_func(TLS1_1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1_1, + tlsv1_1_server_method, + ossl_statem_accept, + ssl_undefined_function, TLSv1_1_enc_data) +#endif +#ifndef OPENSSL_NO_TLS1_METHOD +IMPLEMENT_tls_meth_func(TLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1, + tlsv1_server_method, + ossl_statem_accept, + ssl_undefined_function, TLSv1_enc_data) +#endif +#ifndef OPENSSL_NO_SSL3_METHOD +IMPLEMENT_ssl3_meth_func(sslv3_server_method, + ossl_statem_accept, ssl_undefined_function) +#endif +/*- + * TLS/SSLv3 client methods + */ +IMPLEMENT_tls_meth_func(TLS_ANY_VERSION, 0, 0, + TLS_client_method, + ssl_undefined_function, + ossl_statem_connect, TLSv1_2_enc_data) +IMPLEMENT_tls_meth_func(TLS1_3_VERSION, 0, SSL_OP_NO_TLSv1_3, + tlsv1_3_client_method, + ssl_undefined_function, + ossl_statem_connect, TLSv1_3_enc_data) +#ifndef OPENSSL_NO_TLS1_2_METHOD +IMPLEMENT_tls_meth_func(TLS1_2_VERSION, 0, SSL_OP_NO_TLSv1_2, + tlsv1_2_client_method, + ssl_undefined_function, + ossl_statem_connect, TLSv1_2_enc_data) +#endif +#ifndef OPENSSL_NO_TLS1_1_METHOD +IMPLEMENT_tls_meth_func(TLS1_1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1_1, + tlsv1_1_client_method, + ssl_undefined_function, + ossl_statem_connect, TLSv1_1_enc_data) +#endif +#ifndef OPENSSL_NO_TLS1_METHOD +IMPLEMENT_tls_meth_func(TLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1, + tlsv1_client_method, + ssl_undefined_function, + ossl_statem_connect, TLSv1_enc_data) +#endif +#ifndef OPENSSL_NO_SSL3_METHOD +IMPLEMENT_ssl3_meth_func(sslv3_client_method, + ssl_undefined_function, ossl_statem_connect) +#endif +/*- + * DTLS methods + */ +#ifndef OPENSSL_NO_DTLS1_METHOD +IMPLEMENT_dtls1_meth_func(DTLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_DTLSv1, + dtlsv1_method, + ossl_statem_accept, + ossl_statem_connect, DTLSv1_enc_data) +#endif +#ifndef OPENSSL_NO_DTLS1_2_METHOD +IMPLEMENT_dtls1_meth_func(DTLS1_2_VERSION, 0, SSL_OP_NO_DTLSv1_2, + dtlsv1_2_method, + ossl_statem_accept, + ossl_statem_connect, DTLSv1_2_enc_data) +#endif +IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION, 0, 0, + DTLS_method, + ossl_statem_accept, + ossl_statem_connect, DTLSv1_2_enc_data) + +/*- + * DTLS server methods + */ +#ifndef OPENSSL_NO_DTLS1_METHOD +IMPLEMENT_dtls1_meth_func(DTLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_DTLSv1, + dtlsv1_server_method, + ossl_statem_accept, + ssl_undefined_function, DTLSv1_enc_data) +#endif +#ifndef OPENSSL_NO_DTLS1_2_METHOD +IMPLEMENT_dtls1_meth_func(DTLS1_2_VERSION, 0, SSL_OP_NO_DTLSv1_2, + dtlsv1_2_server_method, + ossl_statem_accept, + ssl_undefined_function, DTLSv1_2_enc_data) +#endif +IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION, 0, 0, + DTLS_server_method, + ossl_statem_accept, + ssl_undefined_function, DTLSv1_2_enc_data) + +/*- + * DTLS client methods + */ +#ifndef OPENSSL_NO_DTLS1_METHOD +IMPLEMENT_dtls1_meth_func(DTLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_DTLSv1, + dtlsv1_client_method, + ssl_undefined_function, + ossl_statem_connect, DTLSv1_enc_data) +IMPLEMENT_dtls1_meth_func(DTLS1_BAD_VER, SSL_METHOD_NO_SUITEB, SSL_OP_NO_DTLSv1, + dtls_bad_ver_client_method, + ssl_undefined_function, + ossl_statem_connect, DTLSv1_enc_data) +#endif +#ifndef OPENSSL_NO_DTLS1_2_METHOD +IMPLEMENT_dtls1_meth_func(DTLS1_2_VERSION, 0, SSL_OP_NO_DTLSv1_2, + dtlsv1_2_client_method, + ssl_undefined_function, + ossl_statem_connect, DTLSv1_2_enc_data) +#endif +IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION, 0, 0, + DTLS_client_method, + ssl_undefined_function, + ossl_statem_connect, DTLSv1_2_enc_data) +#if OPENSSL_API_COMPAT < 0x10100000L +# ifndef OPENSSL_NO_TLS1_2_METHOD +const SSL_METHOD *TLSv1_2_method(void) +{ + return tlsv1_2_method(); +} + +const SSL_METHOD *TLSv1_2_server_method(void) +{ + return tlsv1_2_server_method(); +} + +const SSL_METHOD *TLSv1_2_client_method(void) +{ + return tlsv1_2_client_method(); +} +# endif + +# ifndef OPENSSL_NO_TLS1_1_METHOD +const SSL_METHOD *TLSv1_1_method(void) +{ + return tlsv1_1_method(); +} + +const SSL_METHOD *TLSv1_1_server_method(void) +{ + return tlsv1_1_server_method(); +} + +const SSL_METHOD *TLSv1_1_client_method(void) +{ + return tlsv1_1_client_method(); +} +# endif + +# ifndef OPENSSL_NO_TLS1_METHOD +const SSL_METHOD *TLSv1_method(void) +{ + return tlsv1_method(); +} + +const SSL_METHOD *TLSv1_server_method(void) +{ + return tlsv1_server_method(); +} + +const SSL_METHOD *TLSv1_client_method(void) +{ + return tlsv1_client_method(); +} +# endif + +# ifndef OPENSSL_NO_SSL3_METHOD +const SSL_METHOD *SSLv3_method(void) +{ + return sslv3_method(); +} + +const SSL_METHOD *SSLv3_server_method(void) +{ + return sslv3_server_method(); +} + +const SSL_METHOD *SSLv3_client_method(void) +{ + return sslv3_client_method(); +} +# endif + +# ifndef OPENSSL_NO_DTLS1_2_METHOD +const SSL_METHOD *DTLSv1_2_method(void) +{ + return dtlsv1_2_method(); +} + +const SSL_METHOD *DTLSv1_2_server_method(void) +{ + return dtlsv1_2_server_method(); +} + +const SSL_METHOD *DTLSv1_2_client_method(void) +{ + return dtlsv1_2_client_method(); +} +# endif + +# ifndef OPENSSL_NO_DTLS1_METHOD +const SSL_METHOD *DTLSv1_method(void) +{ + return dtlsv1_method(); +} + +const SSL_METHOD *DTLSv1_server_method(void) +{ + return dtlsv1_server_method(); +} + +const SSL_METHOD *DTLSv1_client_method(void) +{ + return dtlsv1_client_method(); +} +# endif + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/packet.c b/trunk/3rdparty/openssl-1.1-fit/ssl/packet.c new file mode 100644 index 000000000..95031430e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/packet.c @@ -0,0 +1,424 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include "packet_locl.h" +#include + +#define DEFAULT_BUF_SIZE 256 + +int WPACKET_allocate_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes) +{ + if (!WPACKET_reserve_bytes(pkt, len, allocbytes)) + return 0; + + pkt->written += len; + pkt->curr += len; + return 1; +} + +int WPACKET_sub_allocate_bytes__(WPACKET *pkt, size_t len, + unsigned char **allocbytes, size_t lenbytes) +{ + if (!WPACKET_start_sub_packet_len__(pkt, lenbytes) + || !WPACKET_allocate_bytes(pkt, len, allocbytes) + || !WPACKET_close(pkt)) + return 0; + + return 1; +} + +#define GETBUF(p) (((p)->staticbuf != NULL) \ + ? (p)->staticbuf : (unsigned char *)(p)->buf->data) + +int WPACKET_reserve_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes) +{ + /* Internal API, so should not fail */ + if (!ossl_assert(pkt->subs != NULL && len != 0)) + return 0; + + if (pkt->maxsize - pkt->written < len) + return 0; + + if (pkt->staticbuf == NULL && (pkt->buf->length - pkt->written < len)) { + size_t newlen; + size_t reflen; + + reflen = (len > pkt->buf->length) ? len : pkt->buf->length; + + if (reflen > SIZE_MAX / 2) { + newlen = SIZE_MAX; + } else { + newlen = reflen * 2; + if (newlen < DEFAULT_BUF_SIZE) + newlen = DEFAULT_BUF_SIZE; + } + if (BUF_MEM_grow(pkt->buf, newlen) == 0) + return 0; + } + if (allocbytes != NULL) + *allocbytes = WPACKET_get_curr(pkt); + + return 1; +} + +int WPACKET_sub_reserve_bytes__(WPACKET *pkt, size_t len, + unsigned char **allocbytes, size_t lenbytes) +{ + if (!WPACKET_reserve_bytes(pkt, lenbytes + len, allocbytes)) + return 0; + + *allocbytes += lenbytes; + + return 1; +} + +static size_t maxmaxsize(size_t lenbytes) +{ + if (lenbytes >= sizeof(size_t) || lenbytes == 0) + return SIZE_MAX; + + return ((size_t)1 << (lenbytes * 8)) - 1 + lenbytes; +} + +static int wpacket_intern_init_len(WPACKET *pkt, size_t lenbytes) +{ + unsigned char *lenchars; + + pkt->curr = 0; + pkt->written = 0; + + if ((pkt->subs = OPENSSL_zalloc(sizeof(*pkt->subs))) == NULL) { + SSLerr(SSL_F_WPACKET_INTERN_INIT_LEN, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (lenbytes == 0) + return 1; + + pkt->subs->pwritten = lenbytes; + pkt->subs->lenbytes = lenbytes; + + if (!WPACKET_allocate_bytes(pkt, lenbytes, &lenchars)) { + OPENSSL_free(pkt->subs); + pkt->subs = NULL; + return 0; + } + pkt->subs->packet_len = lenchars - GETBUF(pkt); + + return 1; +} + +int WPACKET_init_static_len(WPACKET *pkt, unsigned char *buf, size_t len, + size_t lenbytes) +{ + size_t max = maxmaxsize(lenbytes); + + /* Internal API, so should not fail */ + if (!ossl_assert(buf != NULL && len > 0)) + return 0; + + pkt->staticbuf = buf; + pkt->buf = NULL; + pkt->maxsize = (max < len) ? max : len; + + return wpacket_intern_init_len(pkt, lenbytes); +} + +int WPACKET_init_len(WPACKET *pkt, BUF_MEM *buf, size_t lenbytes) +{ + /* Internal API, so should not fail */ + if (!ossl_assert(buf != NULL)) + return 0; + + pkt->staticbuf = NULL; + pkt->buf = buf; + pkt->maxsize = maxmaxsize(lenbytes); + + return wpacket_intern_init_len(pkt, lenbytes); +} + +int WPACKET_init(WPACKET *pkt, BUF_MEM *buf) +{ + return WPACKET_init_len(pkt, buf, 0); +} + +int WPACKET_set_flags(WPACKET *pkt, unsigned int flags) +{ + /* Internal API, so should not fail */ + if (!ossl_assert(pkt->subs != NULL)) + return 0; + + pkt->subs->flags = flags; + + return 1; +} + +/* Store the |value| of length |len| at location |data| */ +static int put_value(unsigned char *data, size_t value, size_t len) +{ + for (data += len - 1; len > 0; len--) { + *data = (unsigned char)(value & 0xff); + data--; + value >>= 8; + } + + /* Check whether we could fit the value in the assigned number of bytes */ + if (value > 0) + return 0; + + return 1; +} + + +/* + * Internal helper function used by WPACKET_close(), WPACKET_finish() and + * WPACKET_fill_lengths() to close a sub-packet and write out its length if + * necessary. If |doclose| is 0 then it goes through the motions of closing + * (i.e. it fills in all the lengths), but doesn't actually close anything. + */ +static int wpacket_intern_close(WPACKET *pkt, WPACKET_SUB *sub, int doclose) +{ + size_t packlen = pkt->written - sub->pwritten; + + if (packlen == 0 + && (sub->flags & WPACKET_FLAGS_NON_ZERO_LENGTH) != 0) + return 0; + + if (packlen == 0 + && sub->flags & WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH) { + /* We can't handle this case. Return an error */ + if (!doclose) + return 0; + + /* Deallocate any bytes allocated for the length of the WPACKET */ + if ((pkt->curr - sub->lenbytes) == sub->packet_len) { + pkt->written -= sub->lenbytes; + pkt->curr -= sub->lenbytes; + } + + /* Don't write out the packet length */ + sub->packet_len = 0; + sub->lenbytes = 0; + } + + /* Write out the WPACKET length if needed */ + if (sub->lenbytes > 0 + && !put_value(&GETBUF(pkt)[sub->packet_len], packlen, + sub->lenbytes)) + return 0; + + if (doclose) { + pkt->subs = sub->parent; + OPENSSL_free(sub); + } + + return 1; +} + +int WPACKET_fill_lengths(WPACKET *pkt) +{ + WPACKET_SUB *sub; + + if (!ossl_assert(pkt->subs != NULL)) + return 0; + + for (sub = pkt->subs; sub != NULL; sub = sub->parent) { + if (!wpacket_intern_close(pkt, sub, 0)) + return 0; + } + + return 1; +} + +int WPACKET_close(WPACKET *pkt) +{ + /* + * Internal API, so should not fail - but we do negative testing of this + * so no assert (otherwise the tests fail) + */ + if (pkt->subs == NULL || pkt->subs->parent == NULL) + return 0; + + return wpacket_intern_close(pkt, pkt->subs, 1); +} + +int WPACKET_finish(WPACKET *pkt) +{ + int ret; + + /* + * Internal API, so should not fail - but we do negative testing of this + * so no assert (otherwise the tests fail) + */ + if (pkt->subs == NULL || pkt->subs->parent != NULL) + return 0; + + ret = wpacket_intern_close(pkt, pkt->subs, 1); + if (ret) { + OPENSSL_free(pkt->subs); + pkt->subs = NULL; + } + + return ret; +} + +int WPACKET_start_sub_packet_len__(WPACKET *pkt, size_t lenbytes) +{ + WPACKET_SUB *sub; + unsigned char *lenchars; + + /* Internal API, so should not fail */ + if (!ossl_assert(pkt->subs != NULL)) + return 0; + + if ((sub = OPENSSL_zalloc(sizeof(*sub))) == NULL) { + SSLerr(SSL_F_WPACKET_START_SUB_PACKET_LEN__, ERR_R_MALLOC_FAILURE); + return 0; + } + + sub->parent = pkt->subs; + pkt->subs = sub; + sub->pwritten = pkt->written + lenbytes; + sub->lenbytes = lenbytes; + + if (lenbytes == 0) { + sub->packet_len = 0; + return 1; + } + + if (!WPACKET_allocate_bytes(pkt, lenbytes, &lenchars)) + return 0; + /* Convert to an offset in case the underlying BUF_MEM gets realloc'd */ + sub->packet_len = lenchars - GETBUF(pkt); + + return 1; +} + +int WPACKET_start_sub_packet(WPACKET *pkt) +{ + return WPACKET_start_sub_packet_len__(pkt, 0); +} + +int WPACKET_put_bytes__(WPACKET *pkt, unsigned int val, size_t size) +{ + unsigned char *data; + + /* Internal API, so should not fail */ + if (!ossl_assert(size <= sizeof(unsigned int)) + || !WPACKET_allocate_bytes(pkt, size, &data) + || !put_value(data, val, size)) + return 0; + + return 1; +} + +int WPACKET_set_max_size(WPACKET *pkt, size_t maxsize) +{ + WPACKET_SUB *sub; + size_t lenbytes; + + /* Internal API, so should not fail */ + if (!ossl_assert(pkt->subs != NULL)) + return 0; + + /* Find the WPACKET_SUB for the top level */ + for (sub = pkt->subs; sub->parent != NULL; sub = sub->parent) + continue; + + lenbytes = sub->lenbytes; + if (lenbytes == 0) + lenbytes = sizeof(pkt->maxsize); + + if (maxmaxsize(lenbytes) < maxsize || maxsize < pkt->written) + return 0; + + pkt->maxsize = maxsize; + + return 1; +} + +int WPACKET_memset(WPACKET *pkt, int ch, size_t len) +{ + unsigned char *dest; + + if (len == 0) + return 1; + + if (!WPACKET_allocate_bytes(pkt, len, &dest)) + return 0; + + memset(dest, ch, len); + + return 1; +} + +int WPACKET_memcpy(WPACKET *pkt, const void *src, size_t len) +{ + unsigned char *dest; + + if (len == 0) + return 1; + + if (!WPACKET_allocate_bytes(pkt, len, &dest)) + return 0; + + memcpy(dest, src, len); + + return 1; +} + +int WPACKET_sub_memcpy__(WPACKET *pkt, const void *src, size_t len, + size_t lenbytes) +{ + if (!WPACKET_start_sub_packet_len__(pkt, lenbytes) + || !WPACKET_memcpy(pkt, src, len) + || !WPACKET_close(pkt)) + return 0; + + return 1; +} + +int WPACKET_get_total_written(WPACKET *pkt, size_t *written) +{ + /* Internal API, so should not fail */ + if (!ossl_assert(written != NULL)) + return 0; + + *written = pkt->written; + + return 1; +} + +int WPACKET_get_length(WPACKET *pkt, size_t *len) +{ + /* Internal API, so should not fail */ + if (!ossl_assert(pkt->subs != NULL && len != NULL)) + return 0; + + *len = pkt->written - pkt->subs->pwritten; + + return 1; +} + +unsigned char *WPACKET_get_curr(WPACKET *pkt) +{ + return GETBUF(pkt) + pkt->curr; +} + +void WPACKET_cleanup(WPACKET *pkt) +{ + WPACKET_SUB *sub, *parent; + + for (sub = pkt->subs; sub != NULL; sub = parent) { + parent = sub->parent; + OPENSSL_free(sub); + } + pkt->subs = NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/packet_locl.h b/trunk/3rdparty/openssl-1.1-fit/ssl/packet_locl.h new file mode 100644 index 000000000..860360b8b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/packet_locl.h @@ -0,0 +1,874 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_PACKET_LOCL_H +# define HEADER_PACKET_LOCL_H + +# include +# include +# include +# include +# include + +# include "internal/numbers.h" + +typedef struct { + /* Pointer to where we are currently reading from */ + const unsigned char *curr; + /* Number of bytes remaining */ + size_t remaining; +} PACKET; + +/* Internal unchecked shorthand; don't use outside this file. */ +static ossl_inline void packet_forward(PACKET *pkt, size_t len) +{ + pkt->curr += len; + pkt->remaining -= len; +} + +/* + * Returns the number of bytes remaining to be read in the PACKET + */ +static ossl_inline size_t PACKET_remaining(const PACKET *pkt) +{ + return pkt->remaining; +} + +/* + * Returns a pointer to the first byte after the packet data. + * Useful for integrating with non-PACKET parsing code. + * Specifically, we use PACKET_end() to verify that a d2i_... call + * has consumed the entire packet contents. + */ +static ossl_inline const unsigned char *PACKET_end(const PACKET *pkt) +{ + return pkt->curr + pkt->remaining; +} + +/* + * Returns a pointer to the PACKET's current position. + * For use in non-PACKETized APIs. + */ +static ossl_inline const unsigned char *PACKET_data(const PACKET *pkt) +{ + return pkt->curr; +} + +/* + * Initialise a PACKET with |len| bytes held in |buf|. This does not make a + * copy of the data so |buf| must be present for the whole time that the PACKET + * is being used. + */ +__owur static ossl_inline int PACKET_buf_init(PACKET *pkt, + const unsigned char *buf, + size_t len) +{ + /* Sanity check for negative values. */ + if (len > (size_t)(SIZE_MAX / 2)) + return 0; + + pkt->curr = buf; + pkt->remaining = len; + return 1; +} + +/* Initialize a PACKET to hold zero bytes. */ +static ossl_inline void PACKET_null_init(PACKET *pkt) +{ + pkt->curr = NULL; + pkt->remaining = 0; +} + +/* + * Returns 1 if the packet has length |num| and its contents equal the |num| + * bytes read from |ptr|. Returns 0 otherwise (lengths or contents not equal). + * If lengths are equal, performs the comparison in constant time. + */ +__owur static ossl_inline int PACKET_equal(const PACKET *pkt, const void *ptr, + size_t num) +{ + if (PACKET_remaining(pkt) != num) + return 0; + return CRYPTO_memcmp(pkt->curr, ptr, num) == 0; +} + +/* + * Peek ahead and initialize |subpkt| with the next |len| bytes read from |pkt|. + * Data is not copied: the |subpkt| packet will share its underlying buffer with + * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|. + */ +__owur static ossl_inline int PACKET_peek_sub_packet(const PACKET *pkt, + PACKET *subpkt, size_t len) +{ + if (PACKET_remaining(pkt) < len) + return 0; + + return PACKET_buf_init(subpkt, pkt->curr, len); +} + +/* + * Initialize |subpkt| with the next |len| bytes read from |pkt|. Data is not + * copied: the |subpkt| packet will share its underlying buffer with the + * original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|. + */ +__owur static ossl_inline int PACKET_get_sub_packet(PACKET *pkt, + PACKET *subpkt, size_t len) +{ + if (!PACKET_peek_sub_packet(pkt, subpkt, len)) + return 0; + + packet_forward(pkt, len); + + return 1; +} + +/* + * Peek ahead at 2 bytes in network order from |pkt| and store the value in + * |*data| + */ +__owur static ossl_inline int PACKET_peek_net_2(const PACKET *pkt, + unsigned int *data) +{ + if (PACKET_remaining(pkt) < 2) + return 0; + + *data = ((unsigned int)(*pkt->curr)) << 8; + *data |= *(pkt->curr + 1); + + return 1; +} + +/* Equivalent of n2s */ +/* Get 2 bytes in network order from |pkt| and store the value in |*data| */ +__owur static ossl_inline int PACKET_get_net_2(PACKET *pkt, unsigned int *data) +{ + if (!PACKET_peek_net_2(pkt, data)) + return 0; + + packet_forward(pkt, 2); + + return 1; +} + +/* Same as PACKET_get_net_2() but for a size_t */ +__owur static ossl_inline int PACKET_get_net_2_len(PACKET *pkt, size_t *data) +{ + unsigned int i; + int ret = PACKET_get_net_2(pkt, &i); + + if (ret) + *data = (size_t)i; + + return ret; +} + +/* + * Peek ahead at 3 bytes in network order from |pkt| and store the value in + * |*data| + */ +__owur static ossl_inline int PACKET_peek_net_3(const PACKET *pkt, + unsigned long *data) +{ + if (PACKET_remaining(pkt) < 3) + return 0; + + *data = ((unsigned long)(*pkt->curr)) << 16; + *data |= ((unsigned long)(*(pkt->curr + 1))) << 8; + *data |= *(pkt->curr + 2); + + return 1; +} + +/* Equivalent of n2l3 */ +/* Get 3 bytes in network order from |pkt| and store the value in |*data| */ +__owur static ossl_inline int PACKET_get_net_3(PACKET *pkt, unsigned long *data) +{ + if (!PACKET_peek_net_3(pkt, data)) + return 0; + + packet_forward(pkt, 3); + + return 1; +} + +/* Same as PACKET_get_net_3() but for a size_t */ +__owur static ossl_inline int PACKET_get_net_3_len(PACKET *pkt, size_t *data) +{ + unsigned long i; + int ret = PACKET_get_net_3(pkt, &i); + + if (ret) + *data = (size_t)i; + + return ret; +} + +/* + * Peek ahead at 4 bytes in network order from |pkt| and store the value in + * |*data| + */ +__owur static ossl_inline int PACKET_peek_net_4(const PACKET *pkt, + unsigned long *data) +{ + if (PACKET_remaining(pkt) < 4) + return 0; + + *data = ((unsigned long)(*pkt->curr)) << 24; + *data |= ((unsigned long)(*(pkt->curr + 1))) << 16; + *data |= ((unsigned long)(*(pkt->curr + 2))) << 8; + *data |= *(pkt->curr + 3); + + return 1; +} + +/* Equivalent of n2l */ +/* Get 4 bytes in network order from |pkt| and store the value in |*data| */ +__owur static ossl_inline int PACKET_get_net_4(PACKET *pkt, unsigned long *data) +{ + if (!PACKET_peek_net_4(pkt, data)) + return 0; + + packet_forward(pkt, 4); + + return 1; +} + +/* Same as PACKET_get_net_4() but for a size_t */ +__owur static ossl_inline int PACKET_get_net_4_len(PACKET *pkt, size_t *data) +{ + unsigned long i; + int ret = PACKET_get_net_4(pkt, &i); + + if (ret) + *data = (size_t)i; + + return ret; +} + +/* Peek ahead at 1 byte from |pkt| and store the value in |*data| */ +__owur static ossl_inline int PACKET_peek_1(const PACKET *pkt, + unsigned int *data) +{ + if (!PACKET_remaining(pkt)) + return 0; + + *data = *pkt->curr; + + return 1; +} + +/* Get 1 byte from |pkt| and store the value in |*data| */ +__owur static ossl_inline int PACKET_get_1(PACKET *pkt, unsigned int *data) +{ + if (!PACKET_peek_1(pkt, data)) + return 0; + + packet_forward(pkt, 1); + + return 1; +} + +/* Same as PACKET_get_1() but for a size_t */ +__owur static ossl_inline int PACKET_get_1_len(PACKET *pkt, size_t *data) +{ + unsigned int i; + int ret = PACKET_get_1(pkt, &i); + + if (ret) + *data = (size_t)i; + + return ret; +} + +/* + * Peek ahead at 4 bytes in reverse network order from |pkt| and store the value + * in |*data| + */ +__owur static ossl_inline int PACKET_peek_4(const PACKET *pkt, + unsigned long *data) +{ + if (PACKET_remaining(pkt) < 4) + return 0; + + *data = *pkt->curr; + *data |= ((unsigned long)(*(pkt->curr + 1))) << 8; + *data |= ((unsigned long)(*(pkt->curr + 2))) << 16; + *data |= ((unsigned long)(*(pkt->curr + 3))) << 24; + + return 1; +} + +/* Equivalent of c2l */ +/* + * Get 4 bytes in reverse network order from |pkt| and store the value in + * |*data| + */ +__owur static ossl_inline int PACKET_get_4(PACKET *pkt, unsigned long *data) +{ + if (!PACKET_peek_4(pkt, data)) + return 0; + + packet_forward(pkt, 4); + + return 1; +} + +/* + * Peek ahead at |len| bytes from the |pkt| and store a pointer to them in + * |*data|. This just points at the underlying buffer that |pkt| is using. The + * caller should not free this data directly (it will be freed when the + * underlying buffer gets freed + */ +__owur static ossl_inline int PACKET_peek_bytes(const PACKET *pkt, + const unsigned char **data, + size_t len) +{ + if (PACKET_remaining(pkt) < len) + return 0; + + *data = pkt->curr; + + return 1; +} + +/* + * Read |len| bytes from the |pkt| and store a pointer to them in |*data|. This + * just points at the underlying buffer that |pkt| is using. The caller should + * not free this data directly (it will be freed when the underlying buffer gets + * freed + */ +__owur static ossl_inline int PACKET_get_bytes(PACKET *pkt, + const unsigned char **data, + size_t len) +{ + if (!PACKET_peek_bytes(pkt, data, len)) + return 0; + + packet_forward(pkt, len); + + return 1; +} + +/* Peek ahead at |len| bytes from |pkt| and copy them to |data| */ +__owur static ossl_inline int PACKET_peek_copy_bytes(const PACKET *pkt, + unsigned char *data, + size_t len) +{ + if (PACKET_remaining(pkt) < len) + return 0; + + memcpy(data, pkt->curr, len); + + return 1; +} + +/* + * Read |len| bytes from |pkt| and copy them to |data|. + * The caller is responsible for ensuring that |data| can hold |len| bytes. + */ +__owur static ossl_inline int PACKET_copy_bytes(PACKET *pkt, + unsigned char *data, size_t len) +{ + if (!PACKET_peek_copy_bytes(pkt, data, len)) + return 0; + + packet_forward(pkt, len); + + return 1; +} + +/* + * Copy packet data to |dest|, and set |len| to the number of copied bytes. + * If the packet has more than |dest_len| bytes, nothing is copied. + * Returns 1 if the packet data fits in |dest_len| bytes, 0 otherwise. + * Does not forward PACKET position (because it is typically the last thing + * done with a given PACKET). + */ +__owur static ossl_inline int PACKET_copy_all(const PACKET *pkt, + unsigned char *dest, + size_t dest_len, size_t *len) +{ + if (PACKET_remaining(pkt) > dest_len) { + *len = 0; + return 0; + } + *len = pkt->remaining; + memcpy(dest, pkt->curr, pkt->remaining); + return 1; +} + +/* + * Copy |pkt| bytes to a newly allocated buffer and store a pointer to the + * result in |*data|, and the length in |len|. + * If |*data| is not NULL, the old data is OPENSSL_free'd. + * If the packet is empty, or malloc fails, |*data| will be set to NULL. + * Returns 1 if the malloc succeeds and 0 otherwise. + * Does not forward PACKET position (because it is typically the last thing + * done with a given PACKET). + */ +__owur static ossl_inline int PACKET_memdup(const PACKET *pkt, + unsigned char **data, size_t *len) +{ + size_t length; + + OPENSSL_free(*data); + *data = NULL; + *len = 0; + + length = PACKET_remaining(pkt); + + if (length == 0) + return 1; + + *data = OPENSSL_memdup(pkt->curr, length); + if (*data == NULL) + return 0; + + *len = length; + return 1; +} + +/* + * Read a C string from |pkt| and copy to a newly allocated, NUL-terminated + * buffer. Store a pointer to the result in |*data|. + * If |*data| is not NULL, the old data is OPENSSL_free'd. + * If the data in |pkt| does not contain a NUL-byte, the entire data is + * copied and NUL-terminated. + * Returns 1 if the malloc succeeds and 0 otherwise. + * Does not forward PACKET position (because it is typically the last thing done + * with a given PACKET). + */ +__owur static ossl_inline int PACKET_strndup(const PACKET *pkt, char **data) +{ + OPENSSL_free(*data); + + /* This will succeed on an empty packet, unless pkt->curr == NULL. */ + *data = OPENSSL_strndup((const char *)pkt->curr, PACKET_remaining(pkt)); + return (*data != NULL); +} + +/* Returns 1 if |pkt| contains at least one 0-byte, 0 otherwise. */ +static ossl_inline int PACKET_contains_zero_byte(const PACKET *pkt) +{ + return memchr(pkt->curr, 0, pkt->remaining) != NULL; +} + +/* Move the current reading position forward |len| bytes */ +__owur static ossl_inline int PACKET_forward(PACKET *pkt, size_t len) +{ + if (PACKET_remaining(pkt) < len) + return 0; + + packet_forward(pkt, len); + + return 1; +} + +/* + * Reads a variable-length vector prefixed with a one-byte length, and stores + * the contents in |subpkt|. |pkt| can equal |subpkt|. + * Data is not copied: the |subpkt| packet will share its underlying buffer with + * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|. + * Upon failure, the original |pkt| and |subpkt| are not modified. + */ +__owur static ossl_inline int PACKET_get_length_prefixed_1(PACKET *pkt, + PACKET *subpkt) +{ + unsigned int length; + const unsigned char *data; + PACKET tmp = *pkt; + if (!PACKET_get_1(&tmp, &length) || + !PACKET_get_bytes(&tmp, &data, (size_t)length)) { + return 0; + } + + *pkt = tmp; + subpkt->curr = data; + subpkt->remaining = length; + + return 1; +} + +/* + * Like PACKET_get_length_prefixed_1, but additionally, fails when there are + * leftover bytes in |pkt|. + */ +__owur static ossl_inline int PACKET_as_length_prefixed_1(PACKET *pkt, + PACKET *subpkt) +{ + unsigned int length; + const unsigned char *data; + PACKET tmp = *pkt; + if (!PACKET_get_1(&tmp, &length) || + !PACKET_get_bytes(&tmp, &data, (size_t)length) || + PACKET_remaining(&tmp) != 0) { + return 0; + } + + *pkt = tmp; + subpkt->curr = data; + subpkt->remaining = length; + + return 1; +} + +/* + * Reads a variable-length vector prefixed with a two-byte length, and stores + * the contents in |subpkt|. |pkt| can equal |subpkt|. + * Data is not copied: the |subpkt| packet will share its underlying buffer with + * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|. + * Upon failure, the original |pkt| and |subpkt| are not modified. + */ +__owur static ossl_inline int PACKET_get_length_prefixed_2(PACKET *pkt, + PACKET *subpkt) +{ + unsigned int length; + const unsigned char *data; + PACKET tmp = *pkt; + + if (!PACKET_get_net_2(&tmp, &length) || + !PACKET_get_bytes(&tmp, &data, (size_t)length)) { + return 0; + } + + *pkt = tmp; + subpkt->curr = data; + subpkt->remaining = length; + + return 1; +} + +/* + * Like PACKET_get_length_prefixed_2, but additionally, fails when there are + * leftover bytes in |pkt|. + */ +__owur static ossl_inline int PACKET_as_length_prefixed_2(PACKET *pkt, + PACKET *subpkt) +{ + unsigned int length; + const unsigned char *data; + PACKET tmp = *pkt; + + if (!PACKET_get_net_2(&tmp, &length) || + !PACKET_get_bytes(&tmp, &data, (size_t)length) || + PACKET_remaining(&tmp) != 0) { + return 0; + } + + *pkt = tmp; + subpkt->curr = data; + subpkt->remaining = length; + + return 1; +} + +/* + * Reads a variable-length vector prefixed with a three-byte length, and stores + * the contents in |subpkt|. |pkt| can equal |subpkt|. + * Data is not copied: the |subpkt| packet will share its underlying buffer with + * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|. + * Upon failure, the original |pkt| and |subpkt| are not modified. + */ +__owur static ossl_inline int PACKET_get_length_prefixed_3(PACKET *pkt, + PACKET *subpkt) +{ + unsigned long length; + const unsigned char *data; + PACKET tmp = *pkt; + if (!PACKET_get_net_3(&tmp, &length) || + !PACKET_get_bytes(&tmp, &data, (size_t)length)) { + return 0; + } + + *pkt = tmp; + subpkt->curr = data; + subpkt->remaining = length; + + return 1; +} + +/* Writeable packets */ + +typedef struct wpacket_sub WPACKET_SUB; +struct wpacket_sub { + /* The parent WPACKET_SUB if we have one or NULL otherwise */ + WPACKET_SUB *parent; + + /* + * Offset into the buffer where the length of this WPACKET goes. We use an + * offset in case the buffer grows and gets reallocated. + */ + size_t packet_len; + + /* Number of bytes in the packet_len or 0 if we don't write the length */ + size_t lenbytes; + + /* Number of bytes written to the buf prior to this packet starting */ + size_t pwritten; + + /* Flags for this sub-packet */ + unsigned int flags; +}; + +typedef struct wpacket_st WPACKET; +struct wpacket_st { + /* The buffer where we store the output data */ + BUF_MEM *buf; + + /* Fixed sized buffer which can be used as an alternative to buf */ + unsigned char *staticbuf; + + /* + * Offset into the buffer where we are currently writing. We use an offset + * in case the buffer grows and gets reallocated. + */ + size_t curr; + + /* Number of bytes written so far */ + size_t written; + + /* Maximum number of bytes we will allow to be written to this WPACKET */ + size_t maxsize; + + /* Our sub-packets (always at least one if not finished) */ + WPACKET_SUB *subs; +}; + +/* Flags */ + +/* Default */ +#define WPACKET_FLAGS_NONE 0 + +/* Error on WPACKET_close() if no data written to the WPACKET */ +#define WPACKET_FLAGS_NON_ZERO_LENGTH 1 + +/* + * Abandon all changes on WPACKET_close() if no data written to the WPACKET, + * i.e. this does not write out a zero packet length + */ +#define WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH 2 + + +/* + * Initialise a WPACKET with the buffer in |buf|. The buffer must exist + * for the whole time that the WPACKET is being used. Additionally |lenbytes| of + * data is preallocated at the start of the buffer to store the length of the + * WPACKET once we know it. + */ +int WPACKET_init_len(WPACKET *pkt, BUF_MEM *buf, size_t lenbytes); + +/* + * Same as WPACKET_init_len except there is no preallocation of the WPACKET + * length. + */ +int WPACKET_init(WPACKET *pkt, BUF_MEM *buf); + +/* + * Same as WPACKET_init_len except we do not use a growable BUF_MEM structure. + * A fixed buffer of memory |buf| of size |len| is used instead. A failure will + * occur if you attempt to write beyond the end of the buffer + */ +int WPACKET_init_static_len(WPACKET *pkt, unsigned char *buf, size_t len, + size_t lenbytes); +/* + * Set the flags to be applied to the current sub-packet + */ +int WPACKET_set_flags(WPACKET *pkt, unsigned int flags); + +/* + * Closes the most recent sub-packet. It also writes out the length of the + * packet to the required location (normally the start of the WPACKET) if + * appropriate. The top level WPACKET should be closed using WPACKET_finish() + * instead of this function. + */ +int WPACKET_close(WPACKET *pkt); + +/* + * The same as WPACKET_close() but only for the top most WPACKET. Additionally + * frees memory resources for this WPACKET. + */ +int WPACKET_finish(WPACKET *pkt); + +/* + * Iterate through all the sub-packets and write out their lengths as if they + * were being closed. The lengths will be overwritten with the final lengths + * when the sub-packets are eventually closed (which may be different if more + * data is added to the WPACKET). This function fails if a sub-packet is of 0 + * length and WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH is set. + */ +int WPACKET_fill_lengths(WPACKET *pkt); + +/* + * Initialise a new sub-packet. Additionally |lenbytes| of data is preallocated + * at the start of the sub-packet to store its length once we know it. Don't + * call this directly. Use the convenience macros below instead. + */ +int WPACKET_start_sub_packet_len__(WPACKET *pkt, size_t lenbytes); + +/* + * Convenience macros for calling WPACKET_start_sub_packet_len with different + * lengths + */ +#define WPACKET_start_sub_packet_u8(pkt) \ + WPACKET_start_sub_packet_len__((pkt), 1) +#define WPACKET_start_sub_packet_u16(pkt) \ + WPACKET_start_sub_packet_len__((pkt), 2) +#define WPACKET_start_sub_packet_u24(pkt) \ + WPACKET_start_sub_packet_len__((pkt), 3) +#define WPACKET_start_sub_packet_u32(pkt) \ + WPACKET_start_sub_packet_len__((pkt), 4) + +/* + * Same as WPACKET_start_sub_packet_len__() except no bytes are pre-allocated + * for the sub-packet length. + */ +int WPACKET_start_sub_packet(WPACKET *pkt); + +/* + * Allocate bytes in the WPACKET for the output. This reserves the bytes + * and counts them as "written", but doesn't actually do the writing. A pointer + * to the allocated bytes is stored in |*allocbytes|. |allocbytes| may be NULL. + * WARNING: the allocated bytes must be filled in immediately, without further + * WPACKET_* calls. If not then the underlying buffer may be realloc'd and + * change its location. + */ +int WPACKET_allocate_bytes(WPACKET *pkt, size_t len, + unsigned char **allocbytes); + +/* + * The same as WPACKET_allocate_bytes() except additionally a new sub-packet is + * started for the allocated bytes, and then closed immediately afterwards. The + * number of length bytes for the sub-packet is in |lenbytes|. Don't call this + * directly. Use the convenience macros below instead. + */ +int WPACKET_sub_allocate_bytes__(WPACKET *pkt, size_t len, + unsigned char **allocbytes, size_t lenbytes); + +/* + * Convenience macros for calling WPACKET_sub_allocate_bytes with different + * lengths + */ +#define WPACKET_sub_allocate_bytes_u8(pkt, len, bytes) \ + WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 1) +#define WPACKET_sub_allocate_bytes_u16(pkt, len, bytes) \ + WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 2) +#define WPACKET_sub_allocate_bytes_u24(pkt, len, bytes) \ + WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 3) +#define WPACKET_sub_allocate_bytes_u32(pkt, len, bytes) \ + WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 4) + +/* + * The same as WPACKET_allocate_bytes() except the reserved bytes are not + * actually counted as written. Typically this will be for when we don't know + * how big arbitrary data is going to be up front, but we do know what the + * maximum size will be. If this function is used, then it should be immediately + * followed by a WPACKET_allocate_bytes() call before any other WPACKET + * functions are called (unless the write to the allocated bytes is abandoned). + * + * For example: If we are generating a signature, then the size of that + * signature may not be known in advance. We can use WPACKET_reserve_bytes() to + * handle this: + * + * if (!WPACKET_sub_reserve_bytes_u16(&pkt, EVP_PKEY_size(pkey), &sigbytes1) + * || EVP_SignFinal(md_ctx, sigbytes1, &siglen, pkey) <= 0 + * || !WPACKET_sub_allocate_bytes_u16(&pkt, siglen, &sigbytes2) + * || sigbytes1 != sigbytes2) + * goto err; + */ +int WPACKET_reserve_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes); + +/* + * The "reserve_bytes" equivalent of WPACKET_sub_allocate_bytes__() + */ +int WPACKET_sub_reserve_bytes__(WPACKET *pkt, size_t len, + unsigned char **allocbytes, size_t lenbytes); + +/* + * Convenience macros for WPACKET_sub_reserve_bytes with different lengths + */ +#define WPACKET_sub_reserve_bytes_u8(pkt, len, bytes) \ + WPACKET_reserve_bytes__((pkt), (len), (bytes), 1) +#define WPACKET_sub_reserve_bytes_u16(pkt, len, bytes) \ + WPACKET_sub_reserve_bytes__((pkt), (len), (bytes), 2) +#define WPACKET_sub_reserve_bytes_u24(pkt, len, bytes) \ + WPACKET_sub_reserve_bytes__((pkt), (len), (bytes), 3) +#define WPACKET_sub_reserve_bytes_u32(pkt, len, bytes) \ + WPACKET_sub_reserve_bytes__((pkt), (len), (bytes), 4) + +/* + * Write the value stored in |val| into the WPACKET. The value will consume + * |bytes| amount of storage. An error will occur if |val| cannot be + * accommodated in |bytes| storage, e.g. attempting to write the value 256 into + * 1 byte will fail. Don't call this directly. Use the convenience macros below + * instead. + */ +int WPACKET_put_bytes__(WPACKET *pkt, unsigned int val, size_t bytes); + +/* + * Convenience macros for calling WPACKET_put_bytes with different + * lengths + */ +#define WPACKET_put_bytes_u8(pkt, val) \ + WPACKET_put_bytes__((pkt), (val), 1) +#define WPACKET_put_bytes_u16(pkt, val) \ + WPACKET_put_bytes__((pkt), (val), 2) +#define WPACKET_put_bytes_u24(pkt, val) \ + WPACKET_put_bytes__((pkt), (val), 3) +#define WPACKET_put_bytes_u32(pkt, val) \ + WPACKET_put_bytes__((pkt), (val), 4) + +/* Set a maximum size that we will not allow the WPACKET to grow beyond */ +int WPACKET_set_max_size(WPACKET *pkt, size_t maxsize); + +/* Copy |len| bytes of data from |*src| into the WPACKET. */ +int WPACKET_memcpy(WPACKET *pkt, const void *src, size_t len); + +/* Set |len| bytes of data to |ch| into the WPACKET. */ +int WPACKET_memset(WPACKET *pkt, int ch, size_t len); + +/* + * Copy |len| bytes of data from |*src| into the WPACKET and prefix with its + * length (consuming |lenbytes| of data for the length). Don't call this + * directly. Use the convenience macros below instead. + */ +int WPACKET_sub_memcpy__(WPACKET *pkt, const void *src, size_t len, + size_t lenbytes); + +/* Convenience macros for calling WPACKET_sub_memcpy with different lengths */ +#define WPACKET_sub_memcpy_u8(pkt, src, len) \ + WPACKET_sub_memcpy__((pkt), (src), (len), 1) +#define WPACKET_sub_memcpy_u16(pkt, src, len) \ + WPACKET_sub_memcpy__((pkt), (src), (len), 2) +#define WPACKET_sub_memcpy_u24(pkt, src, len) \ + WPACKET_sub_memcpy__((pkt), (src), (len), 3) +#define WPACKET_sub_memcpy_u32(pkt, src, len) \ + WPACKET_sub_memcpy__((pkt), (src), (len), 4) + +/* + * Return the total number of bytes written so far to the underlying buffer + * including any storage allocated for length bytes + */ +int WPACKET_get_total_written(WPACKET *pkt, size_t *written); + +/* + * Returns the length of the current sub-packet. This excludes any bytes + * allocated for the length itself. + */ +int WPACKET_get_length(WPACKET *pkt, size_t *len); + +/* + * Returns a pointer to the current write location, but does not allocate any + * bytes. + */ +unsigned char *WPACKET_get_curr(WPACKET *pkt); + +/* Release resources in a WPACKET if a failure has occurred. */ +void WPACKET_cleanup(WPACKET *pkt); + +#endif /* HEADER_PACKET_LOCL_H */ diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/pqueue.c b/trunk/3rdparty/openssl-1.1-fit/ssl/pqueue.c new file mode 100644 index 000000000..548a7a443 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/pqueue.c @@ -0,0 +1,158 @@ +/* + * Copyright 2005-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "ssl_locl.h" +#include + +struct pqueue_st { + pitem *items; + int count; +}; + +pitem *pitem_new(unsigned char *prio64be, void *data) +{ + pitem *item = OPENSSL_malloc(sizeof(*item)); + + if (item == NULL) { + SSLerr(SSL_F_PITEM_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + memcpy(item->priority, prio64be, sizeof(item->priority)); + item->data = data; + item->next = NULL; + return item; +} + +void pitem_free(pitem *item) +{ + OPENSSL_free(item); +} + +pqueue *pqueue_new(void) +{ + pqueue *pq = OPENSSL_zalloc(sizeof(*pq)); + + if (pq == NULL) + SSLerr(SSL_F_PQUEUE_NEW, ERR_R_MALLOC_FAILURE); + + return pq; +} + +void pqueue_free(pqueue *pq) +{ + OPENSSL_free(pq); +} + +pitem *pqueue_insert(pqueue *pq, pitem *item) +{ + pitem *curr, *next; + + if (pq->items == NULL) { + pq->items = item; + return item; + } + + for (curr = NULL, next = pq->items; + next != NULL; curr = next, next = next->next) { + /* + * we can compare 64-bit value in big-endian encoding with memcmp:-) + */ + int cmp = memcmp(next->priority, item->priority, 8); + if (cmp > 0) { /* next > item */ + item->next = next; + + if (curr == NULL) + pq->items = item; + else + curr->next = item; + + return item; + } + + else if (cmp == 0) /* duplicates not allowed */ + return NULL; + } + + item->next = NULL; + curr->next = item; + + return item; +} + +pitem *pqueue_peek(pqueue *pq) +{ + return pq->items; +} + +pitem *pqueue_pop(pqueue *pq) +{ + pitem *item = pq->items; + + if (pq->items != NULL) + pq->items = pq->items->next; + + return item; +} + +pitem *pqueue_find(pqueue *pq, unsigned char *prio64be) +{ + pitem *next; + pitem *found = NULL; + + if (pq->items == NULL) + return NULL; + + for (next = pq->items; next->next != NULL; next = next->next) { + if (memcmp(next->priority, prio64be, 8) == 0) { + found = next; + break; + } + } + + /* check the one last node */ + if (memcmp(next->priority, prio64be, 8) == 0) + found = next; + + if (!found) + return NULL; + + return found; +} + +pitem *pqueue_iterator(pqueue *pq) +{ + return pqueue_peek(pq); +} + +pitem *pqueue_next(piterator *item) +{ + pitem *ret; + + if (item == NULL || *item == NULL) + return NULL; + + /* *item != NULL */ + ret = *item; + *item = (*item)->next; + + return ret; +} + +size_t pqueue_size(pqueue *pq) +{ + pitem *item = pq->items; + size_t count = 0; + + while (item != NULL) { + count++; + item = item->next; + } + return count; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/record/README b/trunk/3rdparty/openssl-1.1-fit/ssl/record/README new file mode 100644 index 000000000..987e9fd30 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/record/README @@ -0,0 +1,74 @@ +Record Layer Design +=================== + +This file provides some guidance on the thinking behind the design of the +record layer code to aid future maintenance. + +The record layer is divided into a number of components. At the time of writing +there are four: SSL3_RECORD, SSL3_BUFFER, DLTS1_BITMAP and RECORD_LAYER. Each +of these components is defined by: +1) A struct definition of the same name as the component +2) A set of source files that define the functions for that component +3) A set of accessor macros + +All struct definitions are in record.h. The functions and macros are either +defined in record.h or record_locl.h dependent on whether they are intended to +be private to the record layer, or whether they form part of the API to the rest +of libssl. + +The source files map to components as follows: + +dtls1_bitmap.c -> DTLS1_BITMAP component +ssl3_buffer.c -> SSL3_BUFFER component +ssl3_record.c -> SSL3_RECORD component +rec_layer_s3.c, rec_layer_d1.c -> RECORD_LAYER component + +The RECORD_LAYER component is a facade pattern, i.e. it provides a simplified +interface to the record layer for the rest of libssl. The other 3 components are +entirely private to the record layer and therefore should never be accessed +directly by libssl. + +Any component can directly access its own members - they are private to that +component, e.g. ssl3_buffer.c can access members of the SSL3_BUFFER struct +without using a macro. No component can directly access the members of another +component, e.g. ssl3_buffer cannot reach inside the RECORD_LAYER component to +directly access its members. Instead components use accessor macros, so if code +in ssl3_buffer.c wants to access the members of the RECORD_LAYER it uses the +RECORD_LAYER_* macros. + +Conceptually it looks like this: + + libssl + | +---------------------------|-----record.h-------------------------------------- + | + _______V______________ + | | + | RECORD_LAYER | + | | + | rec_layer_s3.c | + | ^ | + | _________|__________ | + || || + || DTLS1_RECORD_LAYER || + || || + || rec_layer_d1.c || + ||____________________|| + |______________________| + record_locl.h ^ ^ ^ + _________________| | |_________________ + | | | + _____V_________ ______V________ _______V________ + | | | | | | + | SSL3_BUFFER | | SSL3_RECORD | | DTLS1_BITMAP | + | |--->| | | | + | ssl3_buffer.c | | ssl3_record.c | | dtls1_bitmap.c | + |_______________| |_______________| |________________| + + +The two RECORD_LAYER source files build on each other, i.e. +the main one is rec_layer_s3.c which provides the core SSL/TLS layer. The second +one is rec_layer_d1.c which builds off of the SSL/TLS code to provide DTLS +specific capabilities. It uses some DTLS specific RECORD_LAYER component members +which should only be accessed from rec_layer_d1.c. These are held in the +DTLS1_RECORD_LAYER struct. diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/record/dtls1_bitmap.c b/trunk/3rdparty/openssl-1.1-fit/ssl/record/dtls1_bitmap.c new file mode 100644 index 000000000..5923c5371 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/record/dtls1_bitmap.c @@ -0,0 +1,78 @@ +/* + * Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "../ssl_locl.h" +#include "record_locl.h" + +/* mod 128 saturating subtract of two 64-bit values in big-endian order */ +static int satsub64be(const unsigned char *v1, const unsigned char *v2) +{ + int64_t ret; + uint64_t l1, l2; + + n2l8(v1, l1); + n2l8(v2, l2); + + ret = l1 - l2; + + /* We do not permit wrap-around */ + if (l1 > l2 && ret < 0) + return 128; + else if (l2 > l1 && ret > 0) + return -128; + + if (ret > 128) + return 128; + else if (ret < -128) + return -128; + else + return (int)ret; +} + +int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap) +{ + int cmp; + unsigned int shift; + const unsigned char *seq = s->rlayer.read_sequence; + + cmp = satsub64be(seq, bitmap->max_seq_num); + if (cmp > 0) { + SSL3_RECORD_set_seq_num(RECORD_LAYER_get_rrec(&s->rlayer), seq); + return 1; /* this record in new */ + } + shift = -cmp; + if (shift >= sizeof(bitmap->map) * 8) + return 0; /* stale, outside the window */ + else if (bitmap->map & (1UL << shift)) + return 0; /* record previously received */ + + SSL3_RECORD_set_seq_num(RECORD_LAYER_get_rrec(&s->rlayer), seq); + return 1; +} + +void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap) +{ + int cmp; + unsigned int shift; + const unsigned char *seq = RECORD_LAYER_get_read_sequence(&s->rlayer); + + cmp = satsub64be(seq, bitmap->max_seq_num); + if (cmp > 0) { + shift = cmp; + if (shift < sizeof(bitmap->map) * 8) + bitmap->map <<= shift, bitmap->map |= 1UL; + else + bitmap->map = 1UL; + memcpy(bitmap->max_seq_num, seq, SEQ_NUM_SIZE); + } else { + shift = -cmp; + if (shift < sizeof(bitmap->map) * 8) + bitmap->map |= 1UL << shift; + } +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/record/rec_layer_d1.c b/trunk/3rdparty/openssl-1.1-fit/ssl/record/rec_layer_d1.c new file mode 100644 index 000000000..cb5d54ef5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/record/rec_layer_d1.c @@ -0,0 +1,1059 @@ +/* + * Copyright 2005-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "../ssl_locl.h" +#include +#include +#include "record_locl.h" +#include "../packet_locl.h" +#include "internal/cryptlib.h" + +int DTLS_RECORD_LAYER_new(RECORD_LAYER *rl) +{ + DTLS_RECORD_LAYER *d; + + if ((d = OPENSSL_malloc(sizeof(*d))) == NULL) { + SSLerr(SSL_F_DTLS_RECORD_LAYER_NEW, ERR_R_MALLOC_FAILURE); + return 0; + } + + rl->d = d; + + d->unprocessed_rcds.q = pqueue_new(); + d->processed_rcds.q = pqueue_new(); + d->buffered_app_data.q = pqueue_new(); + + if (d->unprocessed_rcds.q == NULL || d->processed_rcds.q == NULL + || d->buffered_app_data.q == NULL) { + pqueue_free(d->unprocessed_rcds.q); + pqueue_free(d->processed_rcds.q); + pqueue_free(d->buffered_app_data.q); + OPENSSL_free(d); + rl->d = NULL; + return 0; + } + + return 1; +} + +void DTLS_RECORD_LAYER_free(RECORD_LAYER *rl) +{ + DTLS_RECORD_LAYER_clear(rl); + pqueue_free(rl->d->unprocessed_rcds.q); + pqueue_free(rl->d->processed_rcds.q); + pqueue_free(rl->d->buffered_app_data.q); + OPENSSL_free(rl->d); + rl->d = NULL; +} + +void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl) +{ + DTLS_RECORD_LAYER *d; + pitem *item = NULL; + DTLS1_RECORD_DATA *rdata; + pqueue *unprocessed_rcds; + pqueue *processed_rcds; + pqueue *buffered_app_data; + + d = rl->d; + + while ((item = pqueue_pop(d->unprocessed_rcds.q)) != NULL) { + rdata = (DTLS1_RECORD_DATA *)item->data; + OPENSSL_free(rdata->rbuf.buf); + OPENSSL_free(item->data); + pitem_free(item); + } + + while ((item = pqueue_pop(d->processed_rcds.q)) != NULL) { + rdata = (DTLS1_RECORD_DATA *)item->data; + OPENSSL_free(rdata->rbuf.buf); + OPENSSL_free(item->data); + pitem_free(item); + } + + while ((item = pqueue_pop(d->buffered_app_data.q)) != NULL) { + rdata = (DTLS1_RECORD_DATA *)item->data; + OPENSSL_free(rdata->rbuf.buf); + OPENSSL_free(item->data); + pitem_free(item); + } + + unprocessed_rcds = d->unprocessed_rcds.q; + processed_rcds = d->processed_rcds.q; + buffered_app_data = d->buffered_app_data.q; + memset(d, 0, sizeof(*d)); + d->unprocessed_rcds.q = unprocessed_rcds; + d->processed_rcds.q = processed_rcds; + d->buffered_app_data.q = buffered_app_data; +} + +void DTLS_RECORD_LAYER_set_saved_w_epoch(RECORD_LAYER *rl, unsigned short e) +{ + if (e == rl->d->w_epoch - 1) { + memcpy(rl->d->curr_write_sequence, + rl->write_sequence, sizeof(rl->write_sequence)); + memcpy(rl->write_sequence, + rl->d->last_write_sequence, sizeof(rl->write_sequence)); + } else if (e == rl->d->w_epoch + 1) { + memcpy(rl->d->last_write_sequence, + rl->write_sequence, sizeof(unsigned char[8])); + memcpy(rl->write_sequence, + rl->d->curr_write_sequence, sizeof(rl->write_sequence)); + } + rl->d->w_epoch = e; +} + +void DTLS_RECORD_LAYER_set_write_sequence(RECORD_LAYER *rl, unsigned char *seq) +{ + memcpy(rl->write_sequence, seq, SEQ_NUM_SIZE); +} + +/* copy buffered record into SSL structure */ +static int dtls1_copy_record(SSL *s, pitem *item) +{ + DTLS1_RECORD_DATA *rdata; + + rdata = (DTLS1_RECORD_DATA *)item->data; + + SSL3_BUFFER_release(&s->rlayer.rbuf); + + s->rlayer.packet = rdata->packet; + s->rlayer.packet_length = rdata->packet_length; + memcpy(&s->rlayer.rbuf, &(rdata->rbuf), sizeof(SSL3_BUFFER)); + memcpy(&s->rlayer.rrec, &(rdata->rrec), sizeof(SSL3_RECORD)); + + /* Set proper sequence number for mac calculation */ + memcpy(&(s->rlayer.read_sequence[2]), &(rdata->packet[5]), 6); + + return 1; +} + +int dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority) +{ + DTLS1_RECORD_DATA *rdata; + pitem *item; + + /* Limit the size of the queue to prevent DOS attacks */ + if (pqueue_size(queue->q) >= 100) + return 0; + + rdata = OPENSSL_malloc(sizeof(*rdata)); + item = pitem_new(priority, rdata); + if (rdata == NULL || item == NULL) { + OPENSSL_free(rdata); + pitem_free(item); + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_BUFFER_RECORD, + ERR_R_INTERNAL_ERROR); + return -1; + } + + rdata->packet = s->rlayer.packet; + rdata->packet_length = s->rlayer.packet_length; + memcpy(&(rdata->rbuf), &s->rlayer.rbuf, sizeof(SSL3_BUFFER)); + memcpy(&(rdata->rrec), &s->rlayer.rrec, sizeof(SSL3_RECORD)); + + item->data = rdata; + +#ifndef OPENSSL_NO_SCTP + /* Store bio_dgram_sctp_rcvinfo struct */ + if (BIO_dgram_is_sctp(SSL_get_rbio(s)) && + (SSL_get_state(s) == TLS_ST_SR_FINISHED + || SSL_get_state(s) == TLS_ST_CR_FINISHED)) { + BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_GET_RCVINFO, + sizeof(rdata->recordinfo), &rdata->recordinfo); + } +#endif + + s->rlayer.packet = NULL; + s->rlayer.packet_length = 0; + memset(&s->rlayer.rbuf, 0, sizeof(s->rlayer.rbuf)); + memset(&s->rlayer.rrec, 0, sizeof(s->rlayer.rrec)); + + if (!ssl3_setup_buffers(s)) { + /* SSLfatal() already called */ + OPENSSL_free(rdata->rbuf.buf); + OPENSSL_free(rdata); + pitem_free(item); + return -1; + } + + if (pqueue_insert(queue->q, item) == NULL) { + /* Must be a duplicate so ignore it */ + OPENSSL_free(rdata->rbuf.buf); + OPENSSL_free(rdata); + pitem_free(item); + } + + return 1; +} + +int dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue) +{ + pitem *item; + + item = pqueue_pop(queue->q); + if (item) { + dtls1_copy_record(s, item); + + OPENSSL_free(item->data); + pitem_free(item); + + return 1; + } + + return 0; +} + +/* + * retrieve a buffered record that belongs to the new epoch, i.e., not + * processed yet + */ +#define dtls1_get_unprocessed_record(s) \ + dtls1_retrieve_buffered_record((s), \ + &((s)->rlayer.d->unprocessed_rcds)) + +int dtls1_process_buffered_records(SSL *s) +{ + pitem *item; + SSL3_BUFFER *rb; + SSL3_RECORD *rr; + DTLS1_BITMAP *bitmap; + unsigned int is_next_epoch; + int replayok = 1; + + item = pqueue_peek(s->rlayer.d->unprocessed_rcds.q); + if (item) { + /* Check if epoch is current. */ + if (s->rlayer.d->unprocessed_rcds.epoch != s->rlayer.d->r_epoch) + return 1; /* Nothing to do. */ + + rr = RECORD_LAYER_get_rrec(&s->rlayer); + + rb = RECORD_LAYER_get_rbuf(&s->rlayer); + + if (SSL3_BUFFER_get_left(rb) > 0) { + /* + * We've still got data from the current packet to read. There could + * be a record from the new epoch in it - so don't overwrite it + * with the unprocessed records yet (we'll do it when we've + * finished reading the current packet). + */ + return 1; + } + + /* Process all the records. */ + while (pqueue_peek(s->rlayer.d->unprocessed_rcds.q)) { + dtls1_get_unprocessed_record(s); + bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch); + if (bitmap == NULL) { + /* + * Should not happen. This will only ever be NULL when the + * current record is from a different epoch. But that cannot + * be the case because we already checked the epoch above + */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS, + ERR_R_INTERNAL_ERROR); + return 0; + } +#ifndef OPENSSL_NO_SCTP + /* Only do replay check if no SCTP bio */ + if (!BIO_dgram_is_sctp(SSL_get_rbio(s))) +#endif + { + /* + * Check whether this is a repeat, or aged record. We did this + * check once already when we first received the record - but + * we might have updated the window since then due to + * records we subsequently processed. + */ + replayok = dtls1_record_replay_check(s, bitmap); + } + + if (!replayok || !dtls1_process_record(s, bitmap)) { + if (ossl_statem_in_error(s)) { + /* dtls1_process_record called SSLfatal() */ + return -1; + } + /* dump this record */ + rr->length = 0; + RECORD_LAYER_reset_packet_length(&s->rlayer); + continue; + } + + if (dtls1_buffer_record(s, &(s->rlayer.d->processed_rcds), + SSL3_RECORD_get_seq_num(s->rlayer.rrec)) < 0) { + /* SSLfatal() already called */ + return 0; + } + } + } + + /* + * sync epoch numbers once all the unprocessed records have been + * processed + */ + s->rlayer.d->processed_rcds.epoch = s->rlayer.d->r_epoch; + s->rlayer.d->unprocessed_rcds.epoch = s->rlayer.d->r_epoch + 1; + + return 1; +} + +/*- + * Return up to 'len' payload bytes received in 'type' records. + * 'type' is one of the following: + * + * - SSL3_RT_HANDSHAKE (when ssl3_get_message calls us) + * - SSL3_RT_APPLICATION_DATA (when ssl3_read calls us) + * - 0 (during a shutdown, no data has to be returned) + * + * If we don't have stored data to work from, read a SSL/TLS record first + * (possibly multiple records if we still don't have anything to return). + * + * This function must handle any surprises the peer may have for us, such as + * Alert records (e.g. close_notify) or renegotiation requests. ChangeCipherSpec + * messages are treated as if they were handshake messages *if* the |recd_type| + * argument is non NULL. + * Also if record payloads contain fragments too small to process, we store + * them until there is enough for the respective protocol (the record protocol + * may use arbitrary fragmentation and even interleaving): + * Change cipher spec protocol + * just 1 byte needed, no need for keeping anything stored + * Alert protocol + * 2 bytes needed (AlertLevel, AlertDescription) + * Handshake protocol + * 4 bytes needed (HandshakeType, uint24 length) -- we just have + * to detect unexpected Client Hello and Hello Request messages + * here, anything else is handled by higher layers + * Application data protocol + * none of our business + */ +int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, + size_t len, int peek, size_t *readbytes) +{ + int i, j, iret; + size_t n; + SSL3_RECORD *rr; + void (*cb) (const SSL *ssl, int type2, int val) = NULL; + + if (!SSL3_BUFFER_is_initialised(&s->rlayer.rbuf)) { + /* Not initialized yet */ + if (!ssl3_setup_buffers(s)) { + /* SSLfatal() already called */ + return -1; + } + } + + if ((type && (type != SSL3_RT_APPLICATION_DATA) && + (type != SSL3_RT_HANDSHAKE)) || + (peek && (type != SSL3_RT_APPLICATION_DATA))) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_READ_BYTES, + ERR_R_INTERNAL_ERROR); + return -1; + } + + if (!ossl_statem_get_in_handshake(s) && SSL_in_init(s)) { + /* type == SSL3_RT_APPLICATION_DATA */ + i = s->handshake_func(s); + /* SSLfatal() already called if appropriate */ + if (i < 0) + return i; + if (i == 0) + return -1; + } + + start: + s->rwstate = SSL_NOTHING; + + /*- + * s->s3->rrec.type - is the type of record + * s->s3->rrec.data, - data + * s->s3->rrec.off, - offset into 'data' for next read + * s->s3->rrec.length, - number of bytes. + */ + rr = s->rlayer.rrec; + + /* + * We are not handshaking and have no data yet, so process data buffered + * during the last handshake in advance, if any. + */ + if (SSL_is_init_finished(s) && SSL3_RECORD_get_length(rr) == 0) { + pitem *item; + item = pqueue_pop(s->rlayer.d->buffered_app_data.q); + if (item) { +#ifndef OPENSSL_NO_SCTP + /* Restore bio_dgram_sctp_rcvinfo struct */ + if (BIO_dgram_is_sctp(SSL_get_rbio(s))) { + DTLS1_RECORD_DATA *rdata = (DTLS1_RECORD_DATA *)item->data; + BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_SET_RCVINFO, + sizeof(rdata->recordinfo), &rdata->recordinfo); + } +#endif + + dtls1_copy_record(s, item); + + OPENSSL_free(item->data); + pitem_free(item); + } + } + + /* Check for timeout */ + if (dtls1_handle_timeout(s) > 0) { + goto start; + } else if (ossl_statem_in_error(s)) { + /* dtls1_handle_timeout() has failed with a fatal error */ + return -1; + } + + /* get new packet if necessary */ + if ((SSL3_RECORD_get_length(rr) == 0) + || (s->rlayer.rstate == SSL_ST_READ_BODY)) { + RECORD_LAYER_set_numrpipes(&s->rlayer, 0); + iret = dtls1_get_record(s); + if (iret <= 0) { + iret = dtls1_read_failed(s, iret); + /* + * Anything other than a timeout is an error. SSLfatal() already + * called if appropriate. + */ + if (iret <= 0) + return iret; + else + goto start; + } + RECORD_LAYER_set_numrpipes(&s->rlayer, 1); + } + + /* + * Reset the count of consecutive warning alerts if we've got a non-empty + * record that isn't an alert. + */ + if (SSL3_RECORD_get_type(rr) != SSL3_RT_ALERT + && SSL3_RECORD_get_length(rr) != 0) + s->rlayer.alert_count = 0; + + /* we now have a packet which can be read and processed */ + + if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec, + * reset by ssl3_get_finished */ + && (SSL3_RECORD_get_type(rr) != SSL3_RT_HANDSHAKE)) { + /* + * We now have application data between CCS and Finished. Most likely + * the packets were reordered on their way, so buffer the application + * data for later processing rather than dropping the connection. + */ + if (dtls1_buffer_record(s, &(s->rlayer.d->buffered_app_data), + SSL3_RECORD_get_seq_num(rr)) < 0) { + /* SSLfatal() already called */ + return -1; + } + SSL3_RECORD_set_length(rr, 0); + SSL3_RECORD_set_read(rr); + goto start; + } + + /* + * If the other end has shut down, throw anything we read away (even in + * 'peek' mode) + */ + if (s->shutdown & SSL_RECEIVED_SHUTDOWN) { + SSL3_RECORD_set_length(rr, 0); + SSL3_RECORD_set_read(rr); + s->rwstate = SSL_NOTHING; + return 0; + } + + if (type == SSL3_RECORD_get_type(rr) + || (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC + && type == SSL3_RT_HANDSHAKE && recvd_type != NULL)) { + /* + * SSL3_RT_APPLICATION_DATA or + * SSL3_RT_HANDSHAKE or + * SSL3_RT_CHANGE_CIPHER_SPEC + */ + /* + * make sure that we are not getting application data when we are + * doing a handshake for the first time + */ + if (SSL_in_init(s) && (type == SSL3_RT_APPLICATION_DATA) && + (s->enc_read_ctx == NULL)) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES, + SSL_R_APP_DATA_IN_HANDSHAKE); + return -1; + } + + if (recvd_type != NULL) + *recvd_type = SSL3_RECORD_get_type(rr); + + if (len == 0) { + /* + * Mark a zero length record as read. This ensures multiple calls to + * SSL_read() with a zero length buffer will eventually cause + * SSL_pending() to report data as being available. + */ + if (SSL3_RECORD_get_length(rr) == 0) + SSL3_RECORD_set_read(rr); + return 0; + } + + if (len > SSL3_RECORD_get_length(rr)) + n = SSL3_RECORD_get_length(rr); + else + n = len; + + memcpy(buf, &(SSL3_RECORD_get_data(rr)[SSL3_RECORD_get_off(rr)]), n); + if (peek) { + if (SSL3_RECORD_get_length(rr) == 0) + SSL3_RECORD_set_read(rr); + } else { + SSL3_RECORD_sub_length(rr, n); + SSL3_RECORD_add_off(rr, n); + if (SSL3_RECORD_get_length(rr) == 0) { + s->rlayer.rstate = SSL_ST_READ_HEADER; + SSL3_RECORD_set_off(rr, 0); + SSL3_RECORD_set_read(rr); + } + } +#ifndef OPENSSL_NO_SCTP + /* + * We might had to delay a close_notify alert because of reordered + * app data. If there was an alert and there is no message to read + * anymore, finally set shutdown. + */ + if (BIO_dgram_is_sctp(SSL_get_rbio(s)) && + s->d1->shutdown_received + && !BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) { + s->shutdown |= SSL_RECEIVED_SHUTDOWN; + return 0; + } +#endif + *readbytes = n; + return 1; + } + + /* + * If we get here, then type != rr->type; if we have a handshake message, + * then it was unexpected (Hello Request or Client Hello). + */ + + if (SSL3_RECORD_get_type(rr) == SSL3_RT_ALERT) { + unsigned int alert_level, alert_descr; + unsigned char *alert_bytes = SSL3_RECORD_get_data(rr) + + SSL3_RECORD_get_off(rr); + PACKET alert; + + if (!PACKET_buf_init(&alert, alert_bytes, SSL3_RECORD_get_length(rr)) + || !PACKET_get_1(&alert, &alert_level) + || !PACKET_get_1(&alert, &alert_descr) + || PACKET_remaining(&alert) != 0) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES, + SSL_R_INVALID_ALERT); + return -1; + } + + if (s->msg_callback) + s->msg_callback(0, s->version, SSL3_RT_ALERT, alert_bytes, 2, s, + s->msg_callback_arg); + + if (s->info_callback != NULL) + cb = s->info_callback; + else if (s->ctx->info_callback != NULL) + cb = s->ctx->info_callback; + + if (cb != NULL) { + j = (alert_level << 8) | alert_descr; + cb(s, SSL_CB_READ_ALERT, j); + } + + if (alert_level == SSL3_AL_WARNING) { + s->s3->warn_alert = alert_descr; + SSL3_RECORD_set_read(rr); + + s->rlayer.alert_count++; + if (s->rlayer.alert_count == MAX_WARN_ALERT_COUNT) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES, + SSL_R_TOO_MANY_WARN_ALERTS); + return -1; + } + + if (alert_descr == SSL_AD_CLOSE_NOTIFY) { +#ifndef OPENSSL_NO_SCTP + /* + * With SCTP and streams the socket may deliver app data + * after a close_notify alert. We have to check this first so + * that nothing gets discarded. + */ + if (BIO_dgram_is_sctp(SSL_get_rbio(s)) && + BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) { + s->d1->shutdown_received = 1; + s->rwstate = SSL_READING; + BIO_clear_retry_flags(SSL_get_rbio(s)); + BIO_set_retry_read(SSL_get_rbio(s)); + return -1; + } +#endif + s->shutdown |= SSL_RECEIVED_SHUTDOWN; + return 0; + } + } else if (alert_level == SSL3_AL_FATAL) { + char tmp[16]; + + s->rwstate = SSL_NOTHING; + s->s3->fatal_alert = alert_descr; + SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_DTLS1_READ_BYTES, + SSL_AD_REASON_OFFSET + alert_descr); + BIO_snprintf(tmp, sizeof tmp, "%d", alert_descr); + ERR_add_error_data(2, "SSL alert number ", tmp); + s->shutdown |= SSL_RECEIVED_SHUTDOWN; + SSL3_RECORD_set_read(rr); + SSL_CTX_remove_session(s->session_ctx, s->session); + return 0; + } else { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_DTLS1_READ_BYTES, + SSL_R_UNKNOWN_ALERT_TYPE); + return -1; + } + + goto start; + } + + if (s->shutdown & SSL_SENT_SHUTDOWN) { /* but we have not received a + * shutdown */ + s->rwstate = SSL_NOTHING; + SSL3_RECORD_set_length(rr, 0); + SSL3_RECORD_set_read(rr); + return 0; + } + + if (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC) { + /* + * We can't process a CCS now, because previous handshake messages + * are still missing, so just drop it. + */ + SSL3_RECORD_set_length(rr, 0); + SSL3_RECORD_set_read(rr); + goto start; + } + + /* + * Unexpected handshake message (Client Hello, or protocol violation) + */ + if ((SSL3_RECORD_get_type(rr) == SSL3_RT_HANDSHAKE) && + !ossl_statem_get_in_handshake(s)) { + struct hm_header_st msg_hdr; + + /* + * This may just be a stale retransmit. Also sanity check that we have + * at least enough record bytes for a message header + */ + if (SSL3_RECORD_get_epoch(rr) != s->rlayer.d->r_epoch + || SSL3_RECORD_get_length(rr) < DTLS1_HM_HEADER_LENGTH) { + SSL3_RECORD_set_length(rr, 0); + SSL3_RECORD_set_read(rr); + goto start; + } + + dtls1_get_message_header(rr->data, &msg_hdr); + + /* + * If we are server, we may have a repeated FINISHED of the client + * here, then retransmit our CCS and FINISHED. + */ + if (msg_hdr.type == SSL3_MT_FINISHED) { + if (dtls1_check_timeout_num(s) < 0) { + /* SSLfatal) already called */ + return -1; + } + + if (dtls1_retransmit_buffered_messages(s) <= 0) { + /* Fail if we encountered a fatal error */ + if (ossl_statem_in_error(s)) + return -1; + } + SSL3_RECORD_set_length(rr, 0); + SSL3_RECORD_set_read(rr); + if (!(s->mode & SSL_MODE_AUTO_RETRY)) { + if (SSL3_BUFFER_get_left(&s->rlayer.rbuf) == 0) { + /* no read-ahead left? */ + BIO *bio; + + s->rwstate = SSL_READING; + bio = SSL_get_rbio(s); + BIO_clear_retry_flags(bio); + BIO_set_retry_read(bio); + return -1; + } + } + goto start; + } + + /* + * To get here we must be trying to read app data but found handshake + * data. But if we're trying to read app data, and we're not in init + * (which is tested for at the top of this function) then init must be + * finished + */ + if (!ossl_assert(SSL_is_init_finished(s))) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_READ_BYTES, + ERR_R_INTERNAL_ERROR); + return -1; + } + + /* We found handshake data, so we're going back into init */ + ossl_statem_set_in_init(s, 1); + + i = s->handshake_func(s); + /* SSLfatal() called if appropriate */ + if (i < 0) + return i; + if (i == 0) + return -1; + + if (!(s->mode & SSL_MODE_AUTO_RETRY)) { + if (SSL3_BUFFER_get_left(&s->rlayer.rbuf) == 0) { + /* no read-ahead left? */ + BIO *bio; + /* + * In the case where we try to read application data, but we + * trigger an SSL handshake, we return -1 with the retry + * option set. Otherwise renegotiation may cause nasty + * problems in the blocking world + */ + s->rwstate = SSL_READING; + bio = SSL_get_rbio(s); + BIO_clear_retry_flags(bio); + BIO_set_retry_read(bio); + return -1; + } + } + goto start; + } + + switch (SSL3_RECORD_get_type(rr)) { + default: + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES, + SSL_R_UNEXPECTED_RECORD); + return -1; + case SSL3_RT_CHANGE_CIPHER_SPEC: + case SSL3_RT_ALERT: + case SSL3_RT_HANDSHAKE: + /* + * we already handled all of these, with the possible exception of + * SSL3_RT_HANDSHAKE when ossl_statem_get_in_handshake(s) is true, but + * that should not happen when type != rr->type + */ + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES, + ERR_R_INTERNAL_ERROR); + return -1; + case SSL3_RT_APPLICATION_DATA: + /* + * At this point, we were expecting handshake data, but have + * application data. If the library was running inside ssl3_read() + * (i.e. in_read_app_data is set) and it makes sense to read + * application data at this point (session renegotiation not yet + * started), we will indulge it. + */ + if (s->s3->in_read_app_data && + (s->s3->total_renegotiations != 0) && + ossl_statem_app_data_allowed(s)) { + s->s3->in_read_app_data = 2; + return -1; + } else { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS1_READ_BYTES, + SSL_R_UNEXPECTED_RECORD); + return -1; + } + } + /* not reached */ +} + +/* + * Call this to write data in records of type 'type' It will return <= 0 if + * not all data has been sent or non-blocking IO. + */ +int dtls1_write_bytes(SSL *s, int type, const void *buf, size_t len, + size_t *written) +{ + int i; + + if (!ossl_assert(len <= SSL3_RT_MAX_PLAIN_LENGTH)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_WRITE_BYTES, + ERR_R_INTERNAL_ERROR); + return -1; + } + s->rwstate = SSL_NOTHING; + i = do_dtls1_write(s, type, buf, len, 0, written); + return i; +} + +int do_dtls1_write(SSL *s, int type, const unsigned char *buf, + size_t len, int create_empty_fragment, size_t *written) +{ + unsigned char *p, *pseq; + int i, mac_size, clear = 0; + size_t prefix_len = 0; + int eivlen; + SSL3_RECORD wr; + SSL3_BUFFER *wb; + SSL_SESSION *sess; + + wb = &s->rlayer.wbuf[0]; + + /* + * first check if there is a SSL3_BUFFER still being written out. This + * will happen with non blocking IO + */ + if (!ossl_assert(SSL3_BUFFER_get_left(wb) == 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_DTLS1_WRITE, + ERR_R_INTERNAL_ERROR); + return 0; + } + + /* If we have an alert to send, lets send it */ + if (s->s3->alert_dispatch) { + i = s->method->ssl_dispatch_alert(s); + if (i <= 0) + return i; + /* if it went, fall through and send more stuff */ + } + + if (len == 0 && !create_empty_fragment) + return 0; + + if (len > ssl_get_max_send_fragment(s)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_DTLS1_WRITE, + SSL_R_EXCEEDS_MAX_FRAGMENT_SIZE); + return 0; + } + + sess = s->session; + + if ((sess == NULL) || + (s->enc_write_ctx == NULL) || (EVP_MD_CTX_md(s->write_hash) == NULL)) + clear = 1; + + if (clear) + mac_size = 0; + else { + mac_size = EVP_MD_CTX_size(s->write_hash); + if (mac_size < 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_DTLS1_WRITE, + SSL_R_EXCEEDS_MAX_FRAGMENT_SIZE); + return -1; + } + } + + p = SSL3_BUFFER_get_buf(wb) + prefix_len; + + /* write the header */ + + *(p++) = type & 0xff; + SSL3_RECORD_set_type(&wr, type); + /* + * Special case: for hello verify request, client version 1.0 and we + * haven't decided which version to use yet send back using version 1.0 + * header: otherwise some clients will ignore it. + */ + if (s->method->version == DTLS_ANY_VERSION && + s->max_proto_version != DTLS1_BAD_VER) { + *(p++) = DTLS1_VERSION >> 8; + *(p++) = DTLS1_VERSION & 0xff; + } else { + *(p++) = s->version >> 8; + *(p++) = s->version & 0xff; + } + + /* field where we are to write out packet epoch, seq num and len */ + pseq = p; + p += 10; + + /* Explicit IV length, block ciphers appropriate version flag */ + if (s->enc_write_ctx) { + int mode = EVP_CIPHER_CTX_mode(s->enc_write_ctx); + if (mode == EVP_CIPH_CBC_MODE) { + eivlen = EVP_CIPHER_CTX_iv_length(s->enc_write_ctx); + if (eivlen <= 1) + eivlen = 0; + } + /* Need explicit part of IV for GCM mode */ + else if (mode == EVP_CIPH_GCM_MODE) + eivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN; + else if (mode == EVP_CIPH_CCM_MODE) + eivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN; + else + eivlen = 0; + } else + eivlen = 0; + + /* lets setup the record stuff. */ + SSL3_RECORD_set_data(&wr, p + eivlen); /* make room for IV in case of CBC */ + SSL3_RECORD_set_length(&wr, len); + SSL3_RECORD_set_input(&wr, (unsigned char *)buf); + + /* + * we now 'read' from wr.input, wr.length bytes into wr.data + */ + + /* first we compress */ + if (s->compress != NULL) { + if (!ssl3_do_compress(s, &wr)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_DTLS1_WRITE, + SSL_R_COMPRESSION_FAILURE); + return -1; + } + } else { + memcpy(SSL3_RECORD_get_data(&wr), SSL3_RECORD_get_input(&wr), + SSL3_RECORD_get_length(&wr)); + SSL3_RECORD_reset_input(&wr); + } + + /* + * we should still have the output to wr.data and the input from + * wr.input. Length should be wr.length. wr.data still points in the + * wb->buf + */ + + if (!SSL_WRITE_ETM(s) && mac_size != 0) { + if (!s->method->ssl3_enc->mac(s, &wr, + &(p[SSL3_RECORD_get_length(&wr) + eivlen]), + 1)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_DTLS1_WRITE, + ERR_R_INTERNAL_ERROR); + return -1; + } + SSL3_RECORD_add_length(&wr, mac_size); + } + + /* this is true regardless of mac size */ + SSL3_RECORD_set_data(&wr, p); + SSL3_RECORD_reset_input(&wr); + + if (eivlen) + SSL3_RECORD_add_length(&wr, eivlen); + + if (s->method->ssl3_enc->enc(s, &wr, 1, 1) < 1) { + if (!ossl_statem_in_error(s)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_DTLS1_WRITE, + ERR_R_INTERNAL_ERROR); + } + return -1; + } + + if (SSL_WRITE_ETM(s) && mac_size != 0) { + if (!s->method->ssl3_enc->mac(s, &wr, + &(p[SSL3_RECORD_get_length(&wr)]), 1)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_DTLS1_WRITE, + ERR_R_INTERNAL_ERROR); + return -1; + } + SSL3_RECORD_add_length(&wr, mac_size); + } + + /* record length after mac and block padding */ + + /* there's only one epoch between handshake and app data */ + + s2n(s->rlayer.d->w_epoch, pseq); + + memcpy(pseq, &(s->rlayer.write_sequence[2]), 6); + pseq += 6; + s2n(SSL3_RECORD_get_length(&wr), pseq); + + if (s->msg_callback) + s->msg_callback(1, 0, SSL3_RT_HEADER, pseq - DTLS1_RT_HEADER_LENGTH, + DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg); + + /* + * we should now have wr.data pointing to the encrypted data, which is + * wr->length long + */ + SSL3_RECORD_set_type(&wr, type); /* not needed but helps for debugging */ + SSL3_RECORD_add_length(&wr, DTLS1_RT_HEADER_LENGTH); + + ssl3_record_sequence_update(&(s->rlayer.write_sequence[0])); + + if (create_empty_fragment) { + /* + * we are in a recursive call; just return the length, don't write + * out anything here + */ + *written = wr.length; + return 1; + } + + /* now let's set up wb */ + SSL3_BUFFER_set_left(wb, prefix_len + SSL3_RECORD_get_length(&wr)); + SSL3_BUFFER_set_offset(wb, 0); + + /* + * memorize arguments so that ssl3_write_pending can detect bad write + * retries later + */ + s->rlayer.wpend_tot = len; + s->rlayer.wpend_buf = buf; + s->rlayer.wpend_type = type; + s->rlayer.wpend_ret = len; + + /* we now just need to write the buffer. Calls SSLfatal() as required. */ + return ssl3_write_pending(s, type, buf, len, written); +} + +DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr, + unsigned int *is_next_epoch) +{ + + *is_next_epoch = 0; + + /* In current epoch, accept HM, CCS, DATA, & ALERT */ + if (rr->epoch == s->rlayer.d->r_epoch) + return &s->rlayer.d->bitmap; + + /* + * Only HM and ALERT messages can be from the next epoch and only if we + * have already processed all of the unprocessed records from the last + * epoch + */ + else if (rr->epoch == (unsigned long)(s->rlayer.d->r_epoch + 1) && + s->rlayer.d->unprocessed_rcds.epoch != s->rlayer.d->r_epoch && + (rr->type == SSL3_RT_HANDSHAKE || rr->type == SSL3_RT_ALERT)) { + *is_next_epoch = 1; + return &s->rlayer.d->next_bitmap; + } + + return NULL; +} + +void dtls1_reset_seq_numbers(SSL *s, int rw) +{ + unsigned char *seq; + unsigned int seq_bytes = sizeof(s->rlayer.read_sequence); + + if (rw & SSL3_CC_READ) { + seq = s->rlayer.read_sequence; + s->rlayer.d->r_epoch++; + memcpy(&s->rlayer.d->bitmap, &s->rlayer.d->next_bitmap, + sizeof(s->rlayer.d->bitmap)); + memset(&s->rlayer.d->next_bitmap, 0, sizeof(s->rlayer.d->next_bitmap)); + + /* + * We must not use any buffered messages received from the previous + * epoch + */ + dtls1_clear_received_buffer(s); + } else { + seq = s->rlayer.write_sequence; + memcpy(s->rlayer.d->last_write_sequence, seq, + sizeof(s->rlayer.write_sequence)); + s->rlayer.d->w_epoch++; + } + + memset(seq, 0, seq_bytes); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/record/rec_layer_s3.c b/trunk/3rdparty/openssl-1.1-fit/ssl/record/rec_layer_s3.c new file mode 100644 index 000000000..b2f97ef90 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/record/rec_layer_s3.c @@ -0,0 +1,1771 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "../ssl_locl.h" +#include +#include +#include +#include "record_locl.h" +#include "../packet_locl.h" + +#if defined(OPENSSL_SMALL_FOOTPRINT) || \ + !( defined(AES_ASM) && ( \ + defined(__x86_64) || defined(__x86_64__) || \ + defined(_M_AMD64) || defined(_M_X64) ) \ + ) +# undef EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK +# define EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK 0 +#endif + +void RECORD_LAYER_init(RECORD_LAYER *rl, SSL *s) +{ + rl->s = s; + RECORD_LAYER_set_first_record(&s->rlayer); + SSL3_RECORD_clear(rl->rrec, SSL_MAX_PIPELINES); +} + +void RECORD_LAYER_clear(RECORD_LAYER *rl) +{ + rl->rstate = SSL_ST_READ_HEADER; + + /* + * Do I need to clear read_ahead? As far as I can tell read_ahead did not + * previously get reset by SSL_clear...so I'll keep it that way..but is + * that right? + */ + + rl->packet = NULL; + rl->packet_length = 0; + rl->wnum = 0; + memset(rl->handshake_fragment, 0, sizeof(rl->handshake_fragment)); + rl->handshake_fragment_len = 0; + rl->wpend_tot = 0; + rl->wpend_type = 0; + rl->wpend_ret = 0; + rl->wpend_buf = NULL; + + SSL3_BUFFER_clear(&rl->rbuf); + ssl3_release_write_buffer(rl->s); + rl->numrpipes = 0; + SSL3_RECORD_clear(rl->rrec, SSL_MAX_PIPELINES); + + RECORD_LAYER_reset_read_sequence(rl); + RECORD_LAYER_reset_write_sequence(rl); + + if (rl->d) + DTLS_RECORD_LAYER_clear(rl); +} + +void RECORD_LAYER_release(RECORD_LAYER *rl) +{ + if (SSL3_BUFFER_is_initialised(&rl->rbuf)) + ssl3_release_read_buffer(rl->s); + if (rl->numwpipes > 0) + ssl3_release_write_buffer(rl->s); + SSL3_RECORD_release(rl->rrec, SSL_MAX_PIPELINES); +} + +/* Checks if we have unprocessed read ahead data pending */ +int RECORD_LAYER_read_pending(const RECORD_LAYER *rl) +{ + return SSL3_BUFFER_get_left(&rl->rbuf) != 0; +} + +/* Checks if we have decrypted unread record data pending */ +int RECORD_LAYER_processed_read_pending(const RECORD_LAYER *rl) +{ + size_t curr_rec = 0, num_recs = RECORD_LAYER_get_numrpipes(rl); + const SSL3_RECORD *rr = rl->rrec; + + while (curr_rec < num_recs && SSL3_RECORD_is_read(&rr[curr_rec])) + curr_rec++; + + return curr_rec < num_recs; +} + +int RECORD_LAYER_write_pending(const RECORD_LAYER *rl) +{ + return (rl->numwpipes > 0) + && SSL3_BUFFER_get_left(&rl->wbuf[rl->numwpipes - 1]) != 0; +} + +void RECORD_LAYER_reset_read_sequence(RECORD_LAYER *rl) +{ + memset(rl->read_sequence, 0, sizeof(rl->read_sequence)); +} + +void RECORD_LAYER_reset_write_sequence(RECORD_LAYER *rl) +{ + memset(rl->write_sequence, 0, sizeof(rl->write_sequence)); +} + +size_t ssl3_pending(const SSL *s) +{ + size_t i, num = 0; + + if (s->rlayer.rstate == SSL_ST_READ_BODY) + return 0; + + for (i = 0; i < RECORD_LAYER_get_numrpipes(&s->rlayer); i++) { + if (SSL3_RECORD_get_type(&s->rlayer.rrec[i]) + != SSL3_RT_APPLICATION_DATA) + return 0; + num += SSL3_RECORD_get_length(&s->rlayer.rrec[i]); + } + + return num; +} + +void SSL_CTX_set_default_read_buffer_len(SSL_CTX *ctx, size_t len) +{ + ctx->default_read_buf_len = len; +} + +void SSL_set_default_read_buffer_len(SSL *s, size_t len) +{ + SSL3_BUFFER_set_default_len(RECORD_LAYER_get_rbuf(&s->rlayer), len); +} + +const char *SSL_rstate_string_long(const SSL *s) +{ + switch (s->rlayer.rstate) { + case SSL_ST_READ_HEADER: + return "read header"; + case SSL_ST_READ_BODY: + return "read body"; + case SSL_ST_READ_DONE: + return "read done"; + default: + return "unknown"; + } +} + +const char *SSL_rstate_string(const SSL *s) +{ + switch (s->rlayer.rstate) { + case SSL_ST_READ_HEADER: + return "RH"; + case SSL_ST_READ_BODY: + return "RB"; + case SSL_ST_READ_DONE: + return "RD"; + default: + return "unknown"; + } +} + +/* + * Return values are as per SSL_read() + */ +int ssl3_read_n(SSL *s, size_t n, size_t max, int extend, int clearold, + size_t *readbytes) +{ + /* + * If extend == 0, obtain new n-byte packet; if extend == 1, increase + * packet by another n bytes. The packet will be in the sub-array of + * s->s3->rbuf.buf specified by s->packet and s->packet_length. (If + * s->rlayer.read_ahead is set, 'max' bytes may be stored in rbuf [plus + * s->packet_length bytes if extend == 1].) + * if clearold == 1, move the packet to the start of the buffer; if + * clearold == 0 then leave any old packets where they were + */ + size_t len, left, align = 0; + unsigned char *pkt; + SSL3_BUFFER *rb; + + if (n == 0) + return 0; + + rb = &s->rlayer.rbuf; + if (rb->buf == NULL) + if (!ssl3_setup_read_buffer(s)) { + /* SSLfatal() already called */ + return -1; + } + + left = rb->left; +#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0 + align = (size_t)rb->buf + SSL3_RT_HEADER_LENGTH; + align = SSL3_ALIGN_PAYLOAD - 1 - ((align - 1) % SSL3_ALIGN_PAYLOAD); +#endif + + if (!extend) { + /* start with empty packet ... */ + if (left == 0) + rb->offset = align; + else if (align != 0 && left >= SSL3_RT_HEADER_LENGTH) { + /* + * check if next packet length is large enough to justify payload + * alignment... + */ + pkt = rb->buf + rb->offset; + if (pkt[0] == SSL3_RT_APPLICATION_DATA + && (pkt[3] << 8 | pkt[4]) >= 128) { + /* + * Note that even if packet is corrupted and its length field + * is insane, we can only be led to wrong decision about + * whether memmove will occur or not. Header values has no + * effect on memmove arguments and therefore no buffer + * overrun can be triggered. + */ + memmove(rb->buf + align, pkt, left); + rb->offset = align; + } + } + s->rlayer.packet = rb->buf + rb->offset; + s->rlayer.packet_length = 0; + /* ... now we can act as if 'extend' was set */ + } + + len = s->rlayer.packet_length; + pkt = rb->buf + align; + /* + * Move any available bytes to front of buffer: 'len' bytes already + * pointed to by 'packet', 'left' extra ones at the end + */ + if (s->rlayer.packet != pkt && clearold == 1) { + memmove(pkt, s->rlayer.packet, len + left); + s->rlayer.packet = pkt; + rb->offset = len + align; + } + + /* + * For DTLS/UDP reads should not span multiple packets because the read + * operation returns the whole packet at once (as long as it fits into + * the buffer). + */ + if (SSL_IS_DTLS(s)) { + if (left == 0 && extend) + return 0; + if (left > 0 && n > left) + n = left; + } + + /* if there is enough in the buffer from a previous read, take some */ + if (left >= n) { + s->rlayer.packet_length += n; + rb->left = left - n; + rb->offset += n; + *readbytes = n; + return 1; + } + + /* else we need to read more data */ + + if (n > rb->len - rb->offset) { + /* does not happen */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_READ_N, + ERR_R_INTERNAL_ERROR); + return -1; + } + + /* We always act like read_ahead is set for DTLS */ + if (!s->rlayer.read_ahead && !SSL_IS_DTLS(s)) + /* ignore max parameter */ + max = n; + else { + if (max < n) + max = n; + if (max > rb->len - rb->offset) + max = rb->len - rb->offset; + } + + while (left < n) { + size_t bioread = 0; + int ret; + + /* + * Now we have len+left bytes at the front of s->s3->rbuf.buf and + * need to read in more until we have len+n (up to len+max if + * possible) + */ + + clear_sys_error(); + if (s->rbio != NULL) { + s->rwstate = SSL_READING; + /* TODO(size_t): Convert this function */ + ret = BIO_read(s->rbio, pkt + len + left, max - left); + if (ret >= 0) + bioread = ret; + } else { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_READ_N, + SSL_R_READ_BIO_NOT_SET); + ret = -1; + } + + if (ret <= 0) { + rb->left = left; + if (s->mode & SSL_MODE_RELEASE_BUFFERS && !SSL_IS_DTLS(s)) + if (len + left == 0) + ssl3_release_read_buffer(s); + return ret; + } + left += bioread; + /* + * reads should *never* span multiple packets for DTLS because the + * underlying transport protocol is message oriented as opposed to + * byte oriented as in the TLS case. + */ + if (SSL_IS_DTLS(s)) { + if (n > left) + n = left; /* makes the while condition false */ + } + } + + /* done reading, now the book-keeping */ + rb->offset += n; + rb->left = left - n; + s->rlayer.packet_length += n; + s->rwstate = SSL_NOTHING; + *readbytes = n; + return 1; +} + +/* + * Call this to write data in records of type 'type' It will return <= 0 if + * not all data has been sent or non-blocking IO. + */ +int ssl3_write_bytes(SSL *s, int type, const void *buf_, size_t len, + size_t *written) +{ + const unsigned char *buf = buf_; + size_t tot; + size_t n, max_send_fragment, split_send_fragment, maxpipes; +#if !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK + size_t nw; +#endif + SSL3_BUFFER *wb = &s->rlayer.wbuf[0]; + int i; + size_t tmpwrit; + + s->rwstate = SSL_NOTHING; + tot = s->rlayer.wnum; + /* + * ensure that if we end up with a smaller value of data to write out + * than the original len from a write which didn't complete for + * non-blocking I/O and also somehow ended up avoiding the check for + * this in ssl3_write_pending/SSL_R_BAD_WRITE_RETRY as it must never be + * possible to end up with (len-tot) as a large number that will then + * promptly send beyond the end of the users buffer ... so we trap and + * report the error in a way the user will notice + */ + if ((len < s->rlayer.wnum) + || ((wb->left != 0) && (len < (s->rlayer.wnum + s->rlayer.wpend_tot)))) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_WRITE_BYTES, + SSL_R_BAD_LENGTH); + return -1; + } + + if (s->early_data_state == SSL_EARLY_DATA_WRITING + && !early_data_count_ok(s, len, 0, 1)) { + /* SSLfatal() already called */ + return -1; + } + + s->rlayer.wnum = 0; + + /* + * When writing early data on the server side we could be "in_init" in + * between receiving the EoED and the CF - but we don't want to handle those + * messages yet. + */ + if (SSL_in_init(s) && !ossl_statem_get_in_handshake(s) + && s->early_data_state != SSL_EARLY_DATA_UNAUTH_WRITING) { + i = s->handshake_func(s); + /* SSLfatal() already called */ + if (i < 0) + return i; + if (i == 0) { + return -1; + } + } + + /* + * first check if there is a SSL3_BUFFER still being written out. This + * will happen with non blocking IO + */ + if (wb->left != 0) { + /* SSLfatal() already called if appropriate */ + i = ssl3_write_pending(s, type, &buf[tot], s->rlayer.wpend_tot, + &tmpwrit); + if (i <= 0) { + /* XXX should we ssl3_release_write_buffer if i<0? */ + s->rlayer.wnum = tot; + return i; + } + tot += tmpwrit; /* this might be last fragment */ + } +#if !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK + /* + * Depending on platform multi-block can deliver several *times* + * better performance. Downside is that it has to allocate + * jumbo buffer to accommodate up to 8 records, but the + * compromise is considered worthy. + */ + if (type == SSL3_RT_APPLICATION_DATA && + len >= 4 * (max_send_fragment = ssl_get_max_send_fragment(s)) && + s->compress == NULL && s->msg_callback == NULL && + !SSL_WRITE_ETM(s) && SSL_USE_EXPLICIT_IV(s) && + EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_write_ctx)) & + EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK) { + unsigned char aad[13]; + EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM mb_param; + size_t packlen; + int packleni; + + /* minimize address aliasing conflicts */ + if ((max_send_fragment & 0xfff) == 0) + max_send_fragment -= 512; + + if (tot == 0 || wb->buf == NULL) { /* allocate jumbo buffer */ + ssl3_release_write_buffer(s); + + packlen = EVP_CIPHER_CTX_ctrl(s->enc_write_ctx, + EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE, + (int)max_send_fragment, NULL); + + if (len >= 8 * max_send_fragment) + packlen *= 8; + else + packlen *= 4; + + if (!ssl3_setup_write_buffer(s, 1, packlen)) { + /* SSLfatal() already called */ + return -1; + } + } else if (tot == len) { /* done? */ + /* free jumbo buffer */ + ssl3_release_write_buffer(s); + *written = tot; + return 1; + } + + n = (len - tot); + for (;;) { + if (n < 4 * max_send_fragment) { + /* free jumbo buffer */ + ssl3_release_write_buffer(s); + break; + } + + if (s->s3->alert_dispatch) { + i = s->method->ssl_dispatch_alert(s); + if (i <= 0) { + /* SSLfatal() already called if appropriate */ + s->rlayer.wnum = tot; + return i; + } + } + + if (n >= 8 * max_send_fragment) + nw = max_send_fragment * (mb_param.interleave = 8); + else + nw = max_send_fragment * (mb_param.interleave = 4); + + memcpy(aad, s->rlayer.write_sequence, 8); + aad[8] = type; + aad[9] = (unsigned char)(s->version >> 8); + aad[10] = (unsigned char)(s->version); + aad[11] = 0; + aad[12] = 0; + mb_param.out = NULL; + mb_param.inp = aad; + mb_param.len = nw; + + packleni = EVP_CIPHER_CTX_ctrl(s->enc_write_ctx, + EVP_CTRL_TLS1_1_MULTIBLOCK_AAD, + sizeof(mb_param), &mb_param); + packlen = (size_t)packleni; + if (packleni <= 0 || packlen > wb->len) { /* never happens */ + /* free jumbo buffer */ + ssl3_release_write_buffer(s); + break; + } + + mb_param.out = wb->buf; + mb_param.inp = &buf[tot]; + mb_param.len = nw; + + if (EVP_CIPHER_CTX_ctrl(s->enc_write_ctx, + EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT, + sizeof(mb_param), &mb_param) <= 0) + return -1; + + s->rlayer.write_sequence[7] += mb_param.interleave; + if (s->rlayer.write_sequence[7] < mb_param.interleave) { + int j = 6; + while (j >= 0 && (++s->rlayer.write_sequence[j--]) == 0) ; + } + + wb->offset = 0; + wb->left = packlen; + + s->rlayer.wpend_tot = nw; + s->rlayer.wpend_buf = &buf[tot]; + s->rlayer.wpend_type = type; + s->rlayer.wpend_ret = nw; + + i = ssl3_write_pending(s, type, &buf[tot], nw, &tmpwrit); + if (i <= 0) { + /* SSLfatal() already called if appropriate */ + if (i < 0 && (!s->wbio || !BIO_should_retry(s->wbio))) { + /* free jumbo buffer */ + ssl3_release_write_buffer(s); + } + s->rlayer.wnum = tot; + return i; + } + if (tmpwrit == n) { + /* free jumbo buffer */ + ssl3_release_write_buffer(s); + *written = tot + tmpwrit; + return 1; + } + n -= tmpwrit; + tot += tmpwrit; + } + } else +#endif /* !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK */ + if (tot == len) { /* done? */ + if (s->mode & SSL_MODE_RELEASE_BUFFERS && !SSL_IS_DTLS(s)) + ssl3_release_write_buffer(s); + + *written = tot; + return 1; + } + + n = (len - tot); + + max_send_fragment = ssl_get_max_send_fragment(s); + split_send_fragment = ssl_get_split_send_fragment(s); + /* + * If max_pipelines is 0 then this means "undefined" and we default to + * 1 pipeline. Similarly if the cipher does not support pipelined + * processing then we also only use 1 pipeline, or if we're not using + * explicit IVs + */ + maxpipes = s->max_pipelines; + if (maxpipes > SSL_MAX_PIPELINES) { + /* + * We should have prevented this when we set max_pipelines so we + * shouldn't get here + */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_WRITE_BYTES, + ERR_R_INTERNAL_ERROR); + return -1; + } + if (maxpipes == 0 + || s->enc_write_ctx == NULL + || !(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_write_ctx)) + & EVP_CIPH_FLAG_PIPELINE) + || !SSL_USE_EXPLICIT_IV(s)) + maxpipes = 1; + if (max_send_fragment == 0 || split_send_fragment == 0 + || split_send_fragment > max_send_fragment) { + /* + * We should have prevented this when we set/get the split and max send + * fragments so we shouldn't get here + */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_WRITE_BYTES, + ERR_R_INTERNAL_ERROR); + return -1; + } + + for (;;) { + size_t pipelens[SSL_MAX_PIPELINES], tmppipelen, remain; + size_t numpipes, j; + + if (n == 0) + numpipes = 1; + else + numpipes = ((n - 1) / split_send_fragment) + 1; + if (numpipes > maxpipes) + numpipes = maxpipes; + + if (n / numpipes >= max_send_fragment) { + /* + * We have enough data to completely fill all available + * pipelines + */ + for (j = 0; j < numpipes; j++) { + pipelens[j] = max_send_fragment; + } + } else { + /* We can partially fill all available pipelines */ + tmppipelen = n / numpipes; + remain = n % numpipes; + for (j = 0; j < numpipes; j++) { + pipelens[j] = tmppipelen; + if (j < remain) + pipelens[j]++; + } + } + + i = do_ssl3_write(s, type, &(buf[tot]), pipelens, numpipes, 0, + &tmpwrit); + if (i <= 0) { + /* SSLfatal() already called if appropriate */ + /* XXX should we ssl3_release_write_buffer if i<0? */ + s->rlayer.wnum = tot; + return i; + } + + if (tmpwrit == n || + (type == SSL3_RT_APPLICATION_DATA && + (s->mode & SSL_MODE_ENABLE_PARTIAL_WRITE))) { + /* + * next chunk of data should get another prepended empty fragment + * in ciphersuites with known-IV weakness: + */ + s->s3->empty_fragment_done = 0; + + if ((i == (int)n) && s->mode & SSL_MODE_RELEASE_BUFFERS && + !SSL_IS_DTLS(s)) + ssl3_release_write_buffer(s); + + *written = tot + tmpwrit; + return 1; + } + + n -= tmpwrit; + tot += tmpwrit; + } +} + +int do_ssl3_write(SSL *s, int type, const unsigned char *buf, + size_t *pipelens, size_t numpipes, + int create_empty_fragment, size_t *written) +{ + WPACKET pkt[SSL_MAX_PIPELINES]; + SSL3_RECORD wr[SSL_MAX_PIPELINES]; + WPACKET *thispkt; + SSL3_RECORD *thiswr; + unsigned char *recordstart; + int i, mac_size, clear = 0; + size_t prefix_len = 0; + int eivlen = 0; + size_t align = 0; + SSL3_BUFFER *wb; + SSL_SESSION *sess; + size_t totlen = 0, len, wpinited = 0; + size_t j; + + for (j = 0; j < numpipes; j++) + totlen += pipelens[j]; + /* + * first check if there is a SSL3_BUFFER still being written out. This + * will happen with non blocking IO + */ + if (RECORD_LAYER_write_pending(&s->rlayer)) { + /* Calls SSLfatal() as required */ + return ssl3_write_pending(s, type, buf, totlen, written); + } + + /* If we have an alert to send, lets send it */ + if (s->s3->alert_dispatch) { + i = s->method->ssl_dispatch_alert(s); + if (i <= 0) { + /* SSLfatal() already called if appropriate */ + return i; + } + /* if it went, fall through and send more stuff */ + } + + if (s->rlayer.numwpipes < numpipes) { + if (!ssl3_setup_write_buffer(s, numpipes, 0)) { + /* SSLfatal() already called */ + return -1; + } + } + + if (totlen == 0 && !create_empty_fragment) + return 0; + + sess = s->session; + + if ((sess == NULL) || + (s->enc_write_ctx == NULL) || (EVP_MD_CTX_md(s->write_hash) == NULL)) { + clear = s->enc_write_ctx ? 0 : 1; /* must be AEAD cipher */ + mac_size = 0; + } else { + /* TODO(siz_t): Convert me */ + mac_size = EVP_MD_CTX_size(s->write_hash); + if (mac_size < 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + } + + /* + * 'create_empty_fragment' is true only when this function calls itself + */ + if (!clear && !create_empty_fragment && !s->s3->empty_fragment_done) { + /* + * countermeasure against known-IV weakness in CBC ciphersuites (see + * http://www.openssl.org/~bodo/tls-cbc.txt) + */ + + if (s->s3->need_empty_fragments && type == SSL3_RT_APPLICATION_DATA) { + /* + * recursive function call with 'create_empty_fragment' set; this + * prepares and buffers the data for an empty fragment (these + * 'prefix_len' bytes are sent out later together with the actual + * payload) + */ + size_t tmppipelen = 0; + int ret; + + ret = do_ssl3_write(s, type, buf, &tmppipelen, 1, 1, &prefix_len); + if (ret <= 0) { + /* SSLfatal() already called if appropriate */ + goto err; + } + + if (prefix_len > + (SSL3_RT_HEADER_LENGTH + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD)) { + /* insufficient space */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + } + + s->s3->empty_fragment_done = 1; + } + + if (create_empty_fragment) { + wb = &s->rlayer.wbuf[0]; +#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0 + /* + * extra fragment would be couple of cipher blocks, which would be + * multiple of SSL3_ALIGN_PAYLOAD, so if we want to align the real + * payload, then we can just pretend we simply have two headers. + */ + align = (size_t)SSL3_BUFFER_get_buf(wb) + 2 * SSL3_RT_HEADER_LENGTH; + align = SSL3_ALIGN_PAYLOAD - 1 - ((align - 1) % SSL3_ALIGN_PAYLOAD); +#endif + SSL3_BUFFER_set_offset(wb, align); + if (!WPACKET_init_static_len(&pkt[0], SSL3_BUFFER_get_buf(wb), + SSL3_BUFFER_get_len(wb), 0) + || !WPACKET_allocate_bytes(&pkt[0], align, NULL)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + wpinited = 1; + } else if (prefix_len) { + wb = &s->rlayer.wbuf[0]; + if (!WPACKET_init_static_len(&pkt[0], + SSL3_BUFFER_get_buf(wb), + SSL3_BUFFER_get_len(wb), 0) + || !WPACKET_allocate_bytes(&pkt[0], SSL3_BUFFER_get_offset(wb) + + prefix_len, NULL)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + wpinited = 1; + } else { + for (j = 0; j < numpipes; j++) { + thispkt = &pkt[j]; + + wb = &s->rlayer.wbuf[j]; +#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD != 0 + align = (size_t)SSL3_BUFFER_get_buf(wb) + SSL3_RT_HEADER_LENGTH; + align = SSL3_ALIGN_PAYLOAD - 1 - ((align - 1) % SSL3_ALIGN_PAYLOAD); +#endif + SSL3_BUFFER_set_offset(wb, align); + if (!WPACKET_init_static_len(thispkt, SSL3_BUFFER_get_buf(wb), + SSL3_BUFFER_get_len(wb), 0) + || !WPACKET_allocate_bytes(thispkt, align, NULL)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + wpinited++; + } + } + + /* Explicit IV length, block ciphers appropriate version flag */ + if (s->enc_write_ctx && SSL_USE_EXPLICIT_IV(s) && !SSL_TREAT_AS_TLS13(s)) { + int mode = EVP_CIPHER_CTX_mode(s->enc_write_ctx); + if (mode == EVP_CIPH_CBC_MODE) { + /* TODO(size_t): Convert me */ + eivlen = EVP_CIPHER_CTX_iv_length(s->enc_write_ctx); + if (eivlen <= 1) + eivlen = 0; + } else if (mode == EVP_CIPH_GCM_MODE) { + /* Need explicit part of IV for GCM mode */ + eivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN; + } else if (mode == EVP_CIPH_CCM_MODE) { + eivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN; + } + } + + totlen = 0; + /* Clear our SSL3_RECORD structures */ + memset(wr, 0, sizeof(wr)); + for (j = 0; j < numpipes; j++) { + unsigned int version = (s->version == TLS1_3_VERSION) ? TLS1_2_VERSION + : s->version; + unsigned char *compressdata = NULL; + size_t maxcomplen; + unsigned int rectype; + + thispkt = &pkt[j]; + thiswr = &wr[j]; + + /* + * In TLSv1.3, once encrypting, we always use application data for the + * record type + */ + if (SSL_TREAT_AS_TLS13(s) + && s->enc_write_ctx != NULL + && (s->statem.enc_write_state != ENC_WRITE_STATE_WRITE_PLAIN_ALERTS + || type != SSL3_RT_ALERT)) + rectype = SSL3_RT_APPLICATION_DATA; + else + rectype = type; + SSL3_RECORD_set_type(thiswr, rectype); + + /* + * Some servers hang if initial client hello is larger than 256 bytes + * and record version number > TLS 1.0 + */ + if (SSL_get_state(s) == TLS_ST_CW_CLNT_HELLO + && !s->renegotiate + && TLS1_get_version(s) > TLS1_VERSION + && s->hello_retry_request == SSL_HRR_NONE) + version = TLS1_VERSION; + SSL3_RECORD_set_rec_version(thiswr, version); + + maxcomplen = pipelens[j]; + if (s->compress != NULL) + maxcomplen += SSL3_RT_MAX_COMPRESSED_OVERHEAD; + + /* write the header */ + if (!WPACKET_put_bytes_u8(thispkt, rectype) + || !WPACKET_put_bytes_u16(thispkt, version) + || !WPACKET_start_sub_packet_u16(thispkt) + || (eivlen > 0 + && !WPACKET_allocate_bytes(thispkt, eivlen, NULL)) + || (maxcomplen > 0 + && !WPACKET_reserve_bytes(thispkt, maxcomplen, + &compressdata))) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* lets setup the record stuff. */ + SSL3_RECORD_set_data(thiswr, compressdata); + SSL3_RECORD_set_length(thiswr, pipelens[j]); + SSL3_RECORD_set_input(thiswr, (unsigned char *)&buf[totlen]); + totlen += pipelens[j]; + + /* + * we now 'read' from thiswr->input, thiswr->length bytes into + * thiswr->data + */ + + /* first we compress */ + if (s->compress != NULL) { + if (!ssl3_do_compress(s, thiswr) + || !WPACKET_allocate_bytes(thispkt, thiswr->length, NULL)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + SSL_R_COMPRESSION_FAILURE); + goto err; + } + } else { + if (!WPACKET_memcpy(thispkt, thiswr->input, thiswr->length)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + SSL3_RECORD_reset_input(&wr[j]); + } + + if (SSL_TREAT_AS_TLS13(s) + && s->enc_write_ctx != NULL + && (s->statem.enc_write_state != ENC_WRITE_STATE_WRITE_PLAIN_ALERTS + || type != SSL3_RT_ALERT)) { + size_t rlen, max_send_fragment; + + if (!WPACKET_put_bytes_u8(thispkt, type)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + SSL3_RECORD_add_length(thiswr, 1); + + /* Add TLS1.3 padding */ + max_send_fragment = ssl_get_max_send_fragment(s); + rlen = SSL3_RECORD_get_length(thiswr); + if (rlen < max_send_fragment) { + size_t padding = 0; + size_t max_padding = max_send_fragment - rlen; + if (s->record_padding_cb != NULL) { + padding = s->record_padding_cb(s, type, rlen, s->record_padding_arg); + } else if (s->block_padding > 0) { + size_t mask = s->block_padding - 1; + size_t remainder; + + /* optimize for power of 2 */ + if ((s->block_padding & mask) == 0) + remainder = rlen & mask; + else + remainder = rlen % s->block_padding; + /* don't want to add a block of padding if we don't have to */ + if (remainder == 0) + padding = 0; + else + padding = s->block_padding - remainder; + } + if (padding > 0) { + /* do not allow the record to exceed max plaintext length */ + if (padding > max_padding) + padding = max_padding; + if (!WPACKET_memset(thispkt, 0, padding)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + SSL3_RECORD_add_length(thiswr, padding); + } + } + } + + /* + * we should still have the output to thiswr->data and the input from + * wr->input. Length should be thiswr->length. thiswr->data still points + * in the wb->buf + */ + + if (!SSL_WRITE_ETM(s) && mac_size != 0) { + unsigned char *mac; + + if (!WPACKET_allocate_bytes(thispkt, mac_size, &mac) + || !s->method->ssl3_enc->mac(s, thiswr, mac, 1)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + } + + /* + * Reserve some bytes for any growth that may occur during encryption. + * This will be at most one cipher block or the tag length if using + * AEAD. SSL_RT_MAX_CIPHER_BLOCK_SIZE covers either case. + */ + if (!WPACKET_reserve_bytes(thispkt, SSL_RT_MAX_CIPHER_BLOCK_SIZE, + NULL) + /* + * We also need next the amount of bytes written to this + * sub-packet + */ + || !WPACKET_get_length(thispkt, &len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* Get a pointer to the start of this record excluding header */ + recordstart = WPACKET_get_curr(thispkt) - len; + + SSL3_RECORD_set_data(thiswr, recordstart); + SSL3_RECORD_reset_input(thiswr); + SSL3_RECORD_set_length(thiswr, len); + } + + if (s->statem.enc_write_state == ENC_WRITE_STATE_WRITE_PLAIN_ALERTS) { + /* + * We haven't actually negotiated the version yet, but we're trying to + * send early data - so we need to use the tls13enc function. + */ + if (tls13_enc(s, wr, numpipes, 1) < 1) { + if (!ossl_statem_in_error(s)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + } + goto err; + } + } else { + if (s->method->ssl3_enc->enc(s, wr, numpipes, 1) < 1) { + if (!ossl_statem_in_error(s)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + } + goto err; + } + } + + for (j = 0; j < numpipes; j++) { + size_t origlen; + + thispkt = &pkt[j]; + thiswr = &wr[j]; + + /* Allocate bytes for the encryption overhead */ + if (!WPACKET_get_length(thispkt, &origlen) + /* Encryption should never shrink the data! */ + || origlen > thiswr->length + || (thiswr->length > origlen + && !WPACKET_allocate_bytes(thispkt, + thiswr->length - origlen, NULL))) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + if (SSL_WRITE_ETM(s) && mac_size != 0) { + unsigned char *mac; + + if (!WPACKET_allocate_bytes(thispkt, mac_size, &mac) + || !s->method->ssl3_enc->mac(s, thiswr, mac, 1)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + SSL3_RECORD_add_length(thiswr, mac_size); + } + + if (!WPACKET_get_length(thispkt, &len) + || !WPACKET_close(thispkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + if (s->msg_callback) { + recordstart = WPACKET_get_curr(thispkt) - len + - SSL3_RT_HEADER_LENGTH; + s->msg_callback(1, 0, SSL3_RT_HEADER, recordstart, + SSL3_RT_HEADER_LENGTH, s, + s->msg_callback_arg); + + if (SSL_TREAT_AS_TLS13(s) && s->enc_write_ctx != NULL) { + unsigned char ctype = type; + + s->msg_callback(1, s->version, SSL3_RT_INNER_CONTENT_TYPE, + &ctype, 1, s, s->msg_callback_arg); + } + } + + if (!WPACKET_finish(thispkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* + * we should now have thiswr->data pointing to the encrypted data, which + * is thiswr->length long + */ + SSL3_RECORD_set_type(thiswr, type); /* not needed but helps for + * debugging */ + SSL3_RECORD_add_length(thiswr, SSL3_RT_HEADER_LENGTH); + + if (create_empty_fragment) { + /* + * we are in a recursive call; just return the length, don't write + * out anything here + */ + if (j > 0) { + /* We should never be pipelining an empty fragment!! */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE, + ERR_R_INTERNAL_ERROR); + goto err; + } + *written = SSL3_RECORD_get_length(thiswr); + return 1; + } + + /* now let's set up wb */ + SSL3_BUFFER_set_left(&s->rlayer.wbuf[j], + prefix_len + SSL3_RECORD_get_length(thiswr)); + } + + /* + * memorize arguments so that ssl3_write_pending can detect bad write + * retries later + */ + s->rlayer.wpend_tot = totlen; + s->rlayer.wpend_buf = buf; + s->rlayer.wpend_type = type; + s->rlayer.wpend_ret = totlen; + + /* we now just need to write the buffer */ + return ssl3_write_pending(s, type, buf, totlen, written); + err: + for (j = 0; j < wpinited; j++) + WPACKET_cleanup(&pkt[j]); + return -1; +} + +/* if s->s3->wbuf.left != 0, we need to call this + * + * Return values are as per SSL_write() + */ +int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, size_t len, + size_t *written) +{ + int i; + SSL3_BUFFER *wb = s->rlayer.wbuf; + size_t currbuf = 0; + size_t tmpwrit = 0; + + if ((s->rlayer.wpend_tot > len) + || (!(s->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER) + && (s->rlayer.wpend_buf != buf)) + || (s->rlayer.wpend_type != type)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_WRITE_PENDING, + SSL_R_BAD_WRITE_RETRY); + return -1; + } + + for (;;) { + /* Loop until we find a buffer we haven't written out yet */ + if (SSL3_BUFFER_get_left(&wb[currbuf]) == 0 + && currbuf < s->rlayer.numwpipes - 1) { + currbuf++; + continue; + } + clear_sys_error(); + if (s->wbio != NULL) { + s->rwstate = SSL_WRITING; + /* TODO(size_t): Convert this call */ + i = BIO_write(s->wbio, (char *) + &(SSL3_BUFFER_get_buf(&wb[currbuf]) + [SSL3_BUFFER_get_offset(&wb[currbuf])]), + (unsigned int)SSL3_BUFFER_get_left(&wb[currbuf])); + if (i >= 0) + tmpwrit = i; + } else { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_WRITE_PENDING, + SSL_R_BIO_NOT_SET); + i = -1; + } + if (i > 0 && tmpwrit == SSL3_BUFFER_get_left(&wb[currbuf])) { + SSL3_BUFFER_set_left(&wb[currbuf], 0); + SSL3_BUFFER_add_offset(&wb[currbuf], tmpwrit); + if (currbuf + 1 < s->rlayer.numwpipes) + continue; + s->rwstate = SSL_NOTHING; + *written = s->rlayer.wpend_ret; + return 1; + } else if (i <= 0) { + if (SSL_IS_DTLS(s)) { + /* + * For DTLS, just drop it. That's kind of the whole point in + * using a datagram service + */ + SSL3_BUFFER_set_left(&wb[currbuf], 0); + } + return i; + } + SSL3_BUFFER_add_offset(&wb[currbuf], tmpwrit); + SSL3_BUFFER_sub_left(&wb[currbuf], tmpwrit); + } +} + +/*- + * Return up to 'len' payload bytes received in 'type' records. + * 'type' is one of the following: + * + * - SSL3_RT_HANDSHAKE (when ssl3_get_message calls us) + * - SSL3_RT_APPLICATION_DATA (when ssl3_read calls us) + * - 0 (during a shutdown, no data has to be returned) + * + * If we don't have stored data to work from, read a SSL/TLS record first + * (possibly multiple records if we still don't have anything to return). + * + * This function must handle any surprises the peer may have for us, such as + * Alert records (e.g. close_notify) or renegotiation requests. ChangeCipherSpec + * messages are treated as if they were handshake messages *if* the |recd_type| + * argument is non NULL. + * Also if record payloads contain fragments too small to process, we store + * them until there is enough for the respective protocol (the record protocol + * may use arbitrary fragmentation and even interleaving): + * Change cipher spec protocol + * just 1 byte needed, no need for keeping anything stored + * Alert protocol + * 2 bytes needed (AlertLevel, AlertDescription) + * Handshake protocol + * 4 bytes needed (HandshakeType, uint24 length) -- we just have + * to detect unexpected Client Hello and Hello Request messages + * here, anything else is handled by higher layers + * Application data protocol + * none of our business + */ +int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, + size_t len, int peek, size_t *readbytes) +{ + int i, j, ret; + size_t n, curr_rec, num_recs, totalbytes; + SSL3_RECORD *rr; + SSL3_BUFFER *rbuf; + void (*cb) (const SSL *ssl, int type2, int val) = NULL; + int is_tls13 = SSL_IS_TLS13(s); + + rbuf = &s->rlayer.rbuf; + + if (!SSL3_BUFFER_is_initialised(rbuf)) { + /* Not initialized yet */ + if (!ssl3_setup_read_buffer(s)) { + /* SSLfatal() already called */ + return -1; + } + } + + if ((type && (type != SSL3_RT_APPLICATION_DATA) + && (type != SSL3_RT_HANDSHAKE)) || (peek + && (type != + SSL3_RT_APPLICATION_DATA))) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_READ_BYTES, + ERR_R_INTERNAL_ERROR); + return -1; + } + + if ((type == SSL3_RT_HANDSHAKE) && (s->rlayer.handshake_fragment_len > 0)) + /* (partially) satisfy request from storage */ + { + unsigned char *src = s->rlayer.handshake_fragment; + unsigned char *dst = buf; + unsigned int k; + + /* peek == 0 */ + n = 0; + while ((len > 0) && (s->rlayer.handshake_fragment_len > 0)) { + *dst++ = *src++; + len--; + s->rlayer.handshake_fragment_len--; + n++; + } + /* move any remaining fragment bytes: */ + for (k = 0; k < s->rlayer.handshake_fragment_len; k++) + s->rlayer.handshake_fragment[k] = *src++; + + if (recvd_type != NULL) + *recvd_type = SSL3_RT_HANDSHAKE; + + *readbytes = n; + return 1; + } + + /* + * Now s->rlayer.handshake_fragment_len == 0 if type == SSL3_RT_HANDSHAKE. + */ + + if (!ossl_statem_get_in_handshake(s) && SSL_in_init(s)) { + /* type == SSL3_RT_APPLICATION_DATA */ + i = s->handshake_func(s); + /* SSLfatal() already called */ + if (i < 0) + return i; + if (i == 0) + return -1; + } + start: + s->rwstate = SSL_NOTHING; + + /*- + * For each record 'i' up to |num_recs] + * rr[i].type - is the type of record + * rr[i].data, - data + * rr[i].off, - offset into 'data' for next read + * rr[i].length, - number of bytes. + */ + rr = s->rlayer.rrec; + num_recs = RECORD_LAYER_get_numrpipes(&s->rlayer); + + do { + /* get new records if necessary */ + if (num_recs == 0) { + ret = ssl3_get_record(s); + if (ret <= 0) { + /* SSLfatal() already called if appropriate */ + return ret; + } + num_recs = RECORD_LAYER_get_numrpipes(&s->rlayer); + if (num_recs == 0) { + /* Shouldn't happen */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_READ_BYTES, + ERR_R_INTERNAL_ERROR); + return -1; + } + } + /* Skip over any records we have already read */ + for (curr_rec = 0; + curr_rec < num_recs && SSL3_RECORD_is_read(&rr[curr_rec]); + curr_rec++) ; + if (curr_rec == num_recs) { + RECORD_LAYER_set_numrpipes(&s->rlayer, 0); + num_recs = 0; + curr_rec = 0; + } + } while (num_recs == 0); + rr = &rr[curr_rec]; + + if (s->rlayer.handshake_fragment_len > 0 + && SSL3_RECORD_get_type(rr) != SSL3_RT_HANDSHAKE + && SSL_IS_TLS13(s)) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_READ_BYTES, + SSL_R_MIXED_HANDSHAKE_AND_NON_HANDSHAKE_DATA); + return -1; + } + + /* + * Reset the count of consecutive warning alerts if we've got a non-empty + * record that isn't an alert. + */ + if (SSL3_RECORD_get_type(rr) != SSL3_RT_ALERT + && SSL3_RECORD_get_length(rr) != 0) + s->rlayer.alert_count = 0; + + /* we now have a packet which can be read and processed */ + + if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec, + * reset by ssl3_get_finished */ + && (SSL3_RECORD_get_type(rr) != SSL3_RT_HANDSHAKE)) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_READ_BYTES, + SSL_R_DATA_BETWEEN_CCS_AND_FINISHED); + return -1; + } + + /* + * If the other end has shut down, throw anything we read away (even in + * 'peek' mode) + */ + if (s->shutdown & SSL_RECEIVED_SHUTDOWN) { + SSL3_RECORD_set_length(rr, 0); + s->rwstate = SSL_NOTHING; + return 0; + } + + if (type == SSL3_RECORD_get_type(rr) + || (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC + && type == SSL3_RT_HANDSHAKE && recvd_type != NULL + && !is_tls13)) { + /* + * SSL3_RT_APPLICATION_DATA or + * SSL3_RT_HANDSHAKE or + * SSL3_RT_CHANGE_CIPHER_SPEC + */ + /* + * make sure that we are not getting application data when we are + * doing a handshake for the first time + */ + if (SSL_in_init(s) && (type == SSL3_RT_APPLICATION_DATA) && + (s->enc_read_ctx == NULL)) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_READ_BYTES, + SSL_R_APP_DATA_IN_HANDSHAKE); + return -1; + } + + if (type == SSL3_RT_HANDSHAKE + && SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC + && s->rlayer.handshake_fragment_len > 0) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_READ_BYTES, + SSL_R_CCS_RECEIVED_EARLY); + return -1; + } + + if (recvd_type != NULL) + *recvd_type = SSL3_RECORD_get_type(rr); + + if (len == 0) { + /* + * Mark a zero length record as read. This ensures multiple calls to + * SSL_read() with a zero length buffer will eventually cause + * SSL_pending() to report data as being available. + */ + if (SSL3_RECORD_get_length(rr) == 0) + SSL3_RECORD_set_read(rr); + return 0; + } + + totalbytes = 0; + do { + if (len - totalbytes > SSL3_RECORD_get_length(rr)) + n = SSL3_RECORD_get_length(rr); + else + n = len - totalbytes; + + memcpy(buf, &(rr->data[rr->off]), n); + buf += n; + if (peek) { + /* Mark any zero length record as consumed CVE-2016-6305 */ + if (SSL3_RECORD_get_length(rr) == 0) + SSL3_RECORD_set_read(rr); + } else { + SSL3_RECORD_sub_length(rr, n); + SSL3_RECORD_add_off(rr, n); + if (SSL3_RECORD_get_length(rr) == 0) { + s->rlayer.rstate = SSL_ST_READ_HEADER; + SSL3_RECORD_set_off(rr, 0); + SSL3_RECORD_set_read(rr); + } + } + if (SSL3_RECORD_get_length(rr) == 0 + || (peek && n == SSL3_RECORD_get_length(rr))) { + curr_rec++; + rr++; + } + totalbytes += n; + } while (type == SSL3_RT_APPLICATION_DATA && curr_rec < num_recs + && totalbytes < len); + if (totalbytes == 0) { + /* We must have read empty records. Get more data */ + goto start; + } + if (!peek && curr_rec == num_recs + && (s->mode & SSL_MODE_RELEASE_BUFFERS) + && SSL3_BUFFER_get_left(rbuf) == 0) + ssl3_release_read_buffer(s); + *readbytes = totalbytes; + return 1; + } + + /* + * If we get here, then type != rr->type; if we have a handshake message, + * then it was unexpected (Hello Request or Client Hello) or invalid (we + * were actually expecting a CCS). + */ + + /* + * Lets just double check that we've not got an SSLv2 record + */ + if (rr->rec_version == SSL2_VERSION) { + /* + * Should never happen. ssl3_get_record() should only give us an SSLv2 + * record back if this is the first packet and we are looking for an + * initial ClientHello. Therefore |type| should always be equal to + * |rr->type|. If not then something has gone horribly wrong + */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_READ_BYTES, + ERR_R_INTERNAL_ERROR); + return -1; + } + + if (s->method->version == TLS_ANY_VERSION + && (s->server || rr->type != SSL3_RT_ALERT)) { + /* + * If we've got this far and still haven't decided on what version + * we're using then this must be a client side alert we're dealing with + * (we don't allow heartbeats yet). We shouldn't be receiving anything + * other than a ClientHello if we are a server. + */ + s->version = rr->rec_version; + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_READ_BYTES, + SSL_R_UNEXPECTED_MESSAGE); + return -1; + } + + /*- + * s->rlayer.handshake_fragment_len == 4 iff rr->type == SSL3_RT_HANDSHAKE; + * (Possibly rr is 'empty' now, i.e. rr->length may be 0.) + */ + + if (SSL3_RECORD_get_type(rr) == SSL3_RT_ALERT) { + unsigned int alert_level, alert_descr; + unsigned char *alert_bytes = SSL3_RECORD_get_data(rr) + + SSL3_RECORD_get_off(rr); + PACKET alert; + + if (!PACKET_buf_init(&alert, alert_bytes, SSL3_RECORD_get_length(rr)) + || !PACKET_get_1(&alert, &alert_level) + || !PACKET_get_1(&alert, &alert_descr) + || PACKET_remaining(&alert) != 0) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_READ_BYTES, + SSL_R_INVALID_ALERT); + return -1; + } + + if (s->msg_callback) + s->msg_callback(0, s->version, SSL3_RT_ALERT, alert_bytes, 2, s, + s->msg_callback_arg); + + if (s->info_callback != NULL) + cb = s->info_callback; + else if (s->ctx->info_callback != NULL) + cb = s->ctx->info_callback; + + if (cb != NULL) { + j = (alert_level << 8) | alert_descr; + cb(s, SSL_CB_READ_ALERT, j); + } + + if (alert_level == SSL3_AL_WARNING + || (is_tls13 && alert_descr == SSL_AD_USER_CANCELLED)) { + s->s3->warn_alert = alert_descr; + SSL3_RECORD_set_read(rr); + + s->rlayer.alert_count++; + if (s->rlayer.alert_count == MAX_WARN_ALERT_COUNT) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_READ_BYTES, + SSL_R_TOO_MANY_WARN_ALERTS); + return -1; + } + } + + /* + * Apart from close_notify the only other warning alert in TLSv1.3 + * is user_cancelled - which we just ignore. + */ + if (is_tls13 && alert_descr == SSL_AD_USER_CANCELLED) { + goto start; + } else if (alert_descr == SSL_AD_CLOSE_NOTIFY + && (is_tls13 || alert_level == SSL3_AL_WARNING)) { + s->shutdown |= SSL_RECEIVED_SHUTDOWN; + return 0; + } else if (alert_level == SSL3_AL_FATAL || is_tls13) { + char tmp[16]; + + s->rwstate = SSL_NOTHING; + s->s3->fatal_alert = alert_descr; + SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_SSL3_READ_BYTES, + SSL_AD_REASON_OFFSET + alert_descr); + BIO_snprintf(tmp, sizeof tmp, "%d", alert_descr); + ERR_add_error_data(2, "SSL alert number ", tmp); + s->shutdown |= SSL_RECEIVED_SHUTDOWN; + SSL3_RECORD_set_read(rr); + SSL_CTX_remove_session(s->session_ctx, s->session); + return 0; + } else if (alert_descr == SSL_AD_NO_RENEGOTIATION) { + /* + * This is a warning but we receive it if we requested + * renegotiation and the peer denied it. Terminate with a fatal + * alert because if application tried to renegotiate it + * presumably had a good reason and expects it to succeed. In + * future we might have a renegotiation where we don't care if + * the peer refused it where we carry on. + */ + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_SSL3_READ_BYTES, + SSL_R_NO_RENEGOTIATION); + return -1; + } else if (alert_level == SSL3_AL_WARNING) { + /* We ignore any other warning alert in TLSv1.2 and below */ + goto start; + } + + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SSL3_READ_BYTES, + SSL_R_UNKNOWN_ALERT_TYPE); + return -1; + } + + if ((s->shutdown & SSL_SENT_SHUTDOWN) != 0) { + if (SSL3_RECORD_get_type(rr) == SSL3_RT_HANDSHAKE) { + BIO *rbio; + + /* + * We ignore any handshake messages sent to us unless they are + * TLSv1.3 in which case we want to process them. For all other + * handshake messages we can't do anything reasonable with them + * because we are unable to write any response due to having already + * sent close_notify. + */ + if (!SSL_IS_TLS13(s)) { + SSL3_RECORD_set_length(rr, 0); + SSL3_RECORD_set_read(rr); + + if ((s->mode & SSL_MODE_AUTO_RETRY) != 0) + goto start; + + s->rwstate = SSL_READING; + rbio = SSL_get_rbio(s); + BIO_clear_retry_flags(rbio); + BIO_set_retry_read(rbio); + return -1; + } + } else { + /* + * The peer is continuing to send application data, but we have + * already sent close_notify. If this was expected we should have + * been called via SSL_read() and this would have been handled + * above. + * No alert sent because we already sent close_notify + */ + SSL3_RECORD_set_length(rr, 0); + SSL3_RECORD_set_read(rr); + SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_SSL3_READ_BYTES, + SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY); + return -1; + } + } + + /* + * For handshake data we have 'fragment' storage, so fill that so that we + * can process the header at a fixed place. This is done after the + * "SHUTDOWN" code above to avoid filling the fragment storage with data + * that we're just going to discard. + */ + if (SSL3_RECORD_get_type(rr) == SSL3_RT_HANDSHAKE) { + size_t dest_maxlen = sizeof(s->rlayer.handshake_fragment); + unsigned char *dest = s->rlayer.handshake_fragment; + size_t *dest_len = &s->rlayer.handshake_fragment_len; + + n = dest_maxlen - *dest_len; /* available space in 'dest' */ + if (SSL3_RECORD_get_length(rr) < n) + n = SSL3_RECORD_get_length(rr); /* available bytes */ + + /* now move 'n' bytes: */ + memcpy(dest + *dest_len, + SSL3_RECORD_get_data(rr) + SSL3_RECORD_get_off(rr), n); + SSL3_RECORD_add_off(rr, n); + SSL3_RECORD_sub_length(rr, n); + *dest_len += n; + if (SSL3_RECORD_get_length(rr) == 0) + SSL3_RECORD_set_read(rr); + + if (*dest_len < dest_maxlen) + goto start; /* fragment was too small */ + } + + if (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_READ_BYTES, + SSL_R_CCS_RECEIVED_EARLY); + return -1; + } + + /* + * Unexpected handshake message (ClientHello, NewSessionTicket (TLS1.3) or + * protocol violation) + */ + if ((s->rlayer.handshake_fragment_len >= 4) + && !ossl_statem_get_in_handshake(s)) { + int ined = (s->early_data_state == SSL_EARLY_DATA_READING); + + /* We found handshake data, so we're going back into init */ + ossl_statem_set_in_init(s, 1); + + i = s->handshake_func(s); + /* SSLfatal() already called if appropriate */ + if (i < 0) + return i; + if (i == 0) { + return -1; + } + + /* + * If we were actually trying to read early data and we found a + * handshake message, then we don't want to continue to try and read + * the application data any more. It won't be "early" now. + */ + if (ined) + return -1; + + if (!(s->mode & SSL_MODE_AUTO_RETRY)) { + if (SSL3_BUFFER_get_left(rbuf) == 0) { + /* no read-ahead left? */ + BIO *bio; + /* + * In the case where we try to read application data, but we + * trigger an SSL handshake, we return -1 with the retry + * option set. Otherwise renegotiation may cause nasty + * problems in the blocking world + */ + s->rwstate = SSL_READING; + bio = SSL_get_rbio(s); + BIO_clear_retry_flags(bio); + BIO_set_retry_read(bio); + return -1; + } + } + goto start; + } + + switch (SSL3_RECORD_get_type(rr)) { + default: + /* + * TLS 1.0 and 1.1 say you SHOULD ignore unrecognised record types, but + * TLS 1.2 says you MUST send an unexpected message alert. We use the + * TLS 1.2 behaviour for all protocol versions to prevent issues where + * no progress is being made and the peer continually sends unrecognised + * record types, using up resources processing them. + */ + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_READ_BYTES, + SSL_R_UNEXPECTED_RECORD); + return -1; + case SSL3_RT_CHANGE_CIPHER_SPEC: + case SSL3_RT_ALERT: + case SSL3_RT_HANDSHAKE: + /* + * we already handled all of these, with the possible exception of + * SSL3_RT_HANDSHAKE when ossl_statem_get_in_handshake(s) is true, but + * that should not happen when type != rr->type + */ + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_READ_BYTES, + ERR_R_INTERNAL_ERROR); + return -1; + case SSL3_RT_APPLICATION_DATA: + /* + * At this point, we were expecting handshake data, but have + * application data. If the library was running inside ssl3_read() + * (i.e. in_read_app_data is set) and it makes sense to read + * application data at this point (session renegotiation not yet + * started), we will indulge it. + */ + if (ossl_statem_app_data_allowed(s)) { + s->s3->in_read_app_data = 2; + return -1; + } else if (ossl_statem_skip_early_data(s)) { + /* + * This can happen after a client sends a CH followed by early_data, + * but the server responds with a HelloRetryRequest. The server + * reads the next record from the client expecting to find a + * plaintext ClientHello but gets a record which appears to be + * application data. The trial decrypt "works" because null + * decryption was applied. We just skip it and move on to the next + * record. + */ + if (!early_data_count_ok(s, rr->length, + EARLY_DATA_CIPHERTEXT_OVERHEAD, 0)) { + /* SSLfatal() already called */ + return -1; + } + SSL3_RECORD_set_read(rr); + goto start; + } else { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_READ_BYTES, + SSL_R_UNEXPECTED_RECORD); + return -1; + } + } +} + +void ssl3_record_sequence_update(unsigned char *seq) +{ + int i; + + for (i = 7; i >= 0; i--) { + ++seq[i]; + if (seq[i] != 0) + break; + } +} + +/* + * Returns true if the current rrec was sent in SSLv2 backwards compatible + * format and false otherwise. + */ +int RECORD_LAYER_is_sslv2_record(RECORD_LAYER *rl) +{ + return SSL3_RECORD_is_sslv2_record(&rl->rrec[0]); +} + +/* + * Returns the length in bytes of the current rrec + */ +size_t RECORD_LAYER_get_rrec_length(RECORD_LAYER *rl) +{ + return SSL3_RECORD_get_length(&rl->rrec[0]); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/record/record.h b/trunk/3rdparty/openssl-1.1-fit/ssl/record/record.h new file mode 100644 index 000000000..af56206e0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/record/record.h @@ -0,0 +1,236 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/***************************************************************************** + * * + * These structures should be considered PRIVATE to the record layer. No * + * non-record layer code should be using these structures in any way. * + * * + *****************************************************************************/ + +typedef struct ssl3_buffer_st { + /* at least SSL3_RT_MAX_PACKET_SIZE bytes, see ssl3_setup_buffers() */ + unsigned char *buf; + /* default buffer size (or 0 if no default set) */ + size_t default_len; + /* buffer size */ + size_t len; + /* where to 'copy from' */ + size_t offset; + /* how many bytes left */ + size_t left; +} SSL3_BUFFER; + +#define SEQ_NUM_SIZE 8 + +typedef struct ssl3_record_st { + /* Record layer version */ + /* r */ + int rec_version; + /* type of record */ + /* r */ + int type; + /* How many bytes available */ + /* rw */ + size_t length; + /* + * How many bytes were available before padding was removed? This is used + * to implement the MAC check in constant time for CBC records. + */ + /* rw */ + size_t orig_len; + /* read/write offset into 'buf' */ + /* r */ + size_t off; + /* pointer to the record data */ + /* rw */ + unsigned char *data; + /* where the decode bytes are */ + /* rw */ + unsigned char *input; + /* only used with decompression - malloc()ed */ + /* r */ + unsigned char *comp; + /* Whether the data from this record has already been read or not */ + /* r */ + unsigned int read; + /* epoch number, needed by DTLS1 */ + /* r */ + unsigned long epoch; + /* sequence number, needed by DTLS1 */ + /* r */ + unsigned char seq_num[SEQ_NUM_SIZE]; +} SSL3_RECORD; + +typedef struct dtls1_bitmap_st { + /* Track 32 packets on 32-bit systems and 64 - on 64-bit systems */ + unsigned long map; + /* Max record number seen so far, 64-bit value in big-endian encoding */ + unsigned char max_seq_num[SEQ_NUM_SIZE]; +} DTLS1_BITMAP; + +typedef struct record_pqueue_st { + unsigned short epoch; + struct pqueue_st *q; +} record_pqueue; + +typedef struct dtls1_record_data_st { + unsigned char *packet; + size_t packet_length; + SSL3_BUFFER rbuf; + SSL3_RECORD rrec; +#ifndef OPENSSL_NO_SCTP + struct bio_dgram_sctp_rcvinfo recordinfo; +#endif +} DTLS1_RECORD_DATA; + +typedef struct dtls_record_layer_st { + /* + * The current data and handshake epoch. This is initially + * undefined, and starts at zero once the initial handshake is + * completed + */ + unsigned short r_epoch; + unsigned short w_epoch; + /* records being received in the current epoch */ + DTLS1_BITMAP bitmap; + /* renegotiation starts a new set of sequence numbers */ + DTLS1_BITMAP next_bitmap; + /* Received handshake records (processed and unprocessed) */ + record_pqueue unprocessed_rcds; + record_pqueue processed_rcds; + /* + * Buffered application records. Only for records between CCS and + * Finished to prevent either protocol violation or unnecessary message + * loss. + */ + record_pqueue buffered_app_data; + /* save last and current sequence numbers for retransmissions */ + unsigned char last_write_sequence[8]; + unsigned char curr_write_sequence[8]; +} DTLS_RECORD_LAYER; + +/***************************************************************************** + * * + * This structure should be considered "opaque" to anything outside of the * + * record layer. No non-record layer code should be accessing the members of * + * this structure. * + * * + *****************************************************************************/ + +typedef struct record_layer_st { + /* The parent SSL structure */ + SSL *s; + /* + * Read as many input bytes as possible (for + * non-blocking reads) + */ + int read_ahead; + /* where we are when reading */ + int rstate; + /* How many pipelines can be used to read data */ + size_t numrpipes; + /* How many pipelines can be used to write data */ + size_t numwpipes; + /* read IO goes into here */ + SSL3_BUFFER rbuf; + /* write IO goes into here */ + SSL3_BUFFER wbuf[SSL_MAX_PIPELINES]; + /* each decoded record goes in here */ + SSL3_RECORD rrec[SSL_MAX_PIPELINES]; + /* used internally to point at a raw packet */ + unsigned char *packet; + size_t packet_length; + /* number of bytes sent so far */ + size_t wnum; + unsigned char handshake_fragment[4]; + size_t handshake_fragment_len; + /* The number of consecutive empty records we have received */ + size_t empty_record_count; + /* partial write - check the numbers match */ + /* number bytes written */ + size_t wpend_tot; + int wpend_type; + /* number of bytes submitted */ + size_t wpend_ret; + const unsigned char *wpend_buf; + unsigned char read_sequence[SEQ_NUM_SIZE]; + unsigned char write_sequence[SEQ_NUM_SIZE]; + /* Set to true if this is the first record in a connection */ + unsigned int is_first_record; + /* Count of the number of consecutive warning alerts received */ + unsigned int alert_count; + DTLS_RECORD_LAYER *d; +} RECORD_LAYER; + +/***************************************************************************** + * * + * The following macros/functions represent the libssl internal API to the * + * record layer. Any libssl code may call these functions/macros * + * * + *****************************************************************************/ + +#define MIN_SSL2_RECORD_LEN 9 + +#define RECORD_LAYER_set_read_ahead(rl, ra) ((rl)->read_ahead = (ra)) +#define RECORD_LAYER_get_read_ahead(rl) ((rl)->read_ahead) +#define RECORD_LAYER_get_packet(rl) ((rl)->packet) +#define RECORD_LAYER_get_packet_length(rl) ((rl)->packet_length) +#define RECORD_LAYER_add_packet_length(rl, inc) ((rl)->packet_length += (inc)) +#define DTLS_RECORD_LAYER_get_w_epoch(rl) ((rl)->d->w_epoch) +#define DTLS_RECORD_LAYER_get_processed_rcds(rl) \ + ((rl)->d->processed_rcds) +#define DTLS_RECORD_LAYER_get_unprocessed_rcds(rl) \ + ((rl)->d->unprocessed_rcds) +#define RECORD_LAYER_get_rbuf(rl) (&(rl)->rbuf) +#define RECORD_LAYER_get_wbuf(rl) ((rl)->wbuf) + +void RECORD_LAYER_init(RECORD_LAYER *rl, SSL *s); +void RECORD_LAYER_clear(RECORD_LAYER *rl); +void RECORD_LAYER_release(RECORD_LAYER *rl); +int RECORD_LAYER_read_pending(const RECORD_LAYER *rl); +int RECORD_LAYER_processed_read_pending(const RECORD_LAYER *rl); +int RECORD_LAYER_write_pending(const RECORD_LAYER *rl); +void RECORD_LAYER_reset_read_sequence(RECORD_LAYER *rl); +void RECORD_LAYER_reset_write_sequence(RECORD_LAYER *rl); +int RECORD_LAYER_is_sslv2_record(RECORD_LAYER *rl); +size_t RECORD_LAYER_get_rrec_length(RECORD_LAYER *rl); +__owur size_t ssl3_pending(const SSL *s); +__owur int ssl3_write_bytes(SSL *s, int type, const void *buf, size_t len, + size_t *written); +int do_ssl3_write(SSL *s, int type, const unsigned char *buf, + size_t *pipelens, size_t numpipes, + int create_empty_fragment, size_t *written); +__owur int ssl3_read_bytes(SSL *s, int type, int *recvd_type, + unsigned char *buf, size_t len, int peek, + size_t *readbytes); +__owur int ssl3_setup_buffers(SSL *s); +__owur int ssl3_enc(SSL *s, SSL3_RECORD *inrecs, size_t n_recs, int send); +__owur int n_ssl3_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int send); +__owur int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, size_t len, + size_t *written); +__owur int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int send); +__owur int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int send); +__owur int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int send); +int DTLS_RECORD_LAYER_new(RECORD_LAYER *rl); +void DTLS_RECORD_LAYER_free(RECORD_LAYER *rl); +void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl); +void DTLS_RECORD_LAYER_set_saved_w_epoch(RECORD_LAYER *rl, unsigned short e); +void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl); +void DTLS_RECORD_LAYER_set_write_sequence(RECORD_LAYER *rl, unsigned char *seq); +__owur int dtls1_read_bytes(SSL *s, int type, int *recvd_type, + unsigned char *buf, size_t len, int peek, + size_t *readbytes); +__owur int dtls1_write_bytes(SSL *s, int type, const void *buf, size_t len, + size_t *written); +int do_dtls1_write(SSL *s, int type, const unsigned char *buf, + size_t len, int create_empty_fragment, size_t *written); +void dtls1_reset_seq_numbers(SSL *s, int rw); +int dtls_buffer_listen_record(SSL *s, size_t len, unsigned char *seq, + size_t off); diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/record/record_locl.h b/trunk/3rdparty/openssl-1.1-fit/ssl/record/record_locl.h new file mode 100644 index 000000000..5e8dd7f70 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/record/record_locl.h @@ -0,0 +1,116 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/***************************************************************************** + * * + * The following macros/functions are PRIVATE to the record layer. They * + * should NOT be used outside of the record layer. * + * * + *****************************************************************************/ + +#define MAX_WARN_ALERT_COUNT 5 + +/* Functions/macros provided by the RECORD_LAYER component */ + +#define RECORD_LAYER_get_rrec(rl) ((rl)->rrec) +#define RECORD_LAYER_set_packet(rl, p) ((rl)->packet = (p)) +#define RECORD_LAYER_reset_packet_length(rl) ((rl)->packet_length = 0) +#define RECORD_LAYER_get_rstate(rl) ((rl)->rstate) +#define RECORD_LAYER_set_rstate(rl, st) ((rl)->rstate = (st)) +#define RECORD_LAYER_get_read_sequence(rl) ((rl)->read_sequence) +#define RECORD_LAYER_get_write_sequence(rl) ((rl)->write_sequence) +#define RECORD_LAYER_get_numrpipes(rl) ((rl)->numrpipes) +#define RECORD_LAYER_set_numrpipes(rl, n) ((rl)->numrpipes = (n)) +#define RECORD_LAYER_inc_empty_record_count(rl) ((rl)->empty_record_count++) +#define RECORD_LAYER_reset_empty_record_count(rl) \ + ((rl)->empty_record_count = 0) +#define RECORD_LAYER_get_empty_record_count(rl) ((rl)->empty_record_count) +#define RECORD_LAYER_is_first_record(rl) ((rl)->is_first_record) +#define RECORD_LAYER_set_first_record(rl) ((rl)->is_first_record = 1) +#define RECORD_LAYER_clear_first_record(rl) ((rl)->is_first_record = 0) +#define DTLS_RECORD_LAYER_get_r_epoch(rl) ((rl)->d->r_epoch) + +__owur int ssl3_read_n(SSL *s, size_t n, size_t max, int extend, int clearold, + size_t *readbytes); + +DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr, + unsigned int *is_next_epoch); +int dtls1_process_buffered_records(SSL *s); +int dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue); +int dtls1_buffer_record(SSL *s, record_pqueue *q, unsigned char *priority); +void ssl3_record_sequence_update(unsigned char *seq); + +/* Functions provided by the DTLS1_BITMAP component */ + +int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap); +void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap); + +/* Macros/functions provided by the SSL3_BUFFER component */ + +#define SSL3_BUFFER_get_buf(b) ((b)->buf) +#define SSL3_BUFFER_set_buf(b, n) ((b)->buf = (n)) +#define SSL3_BUFFER_get_len(b) ((b)->len) +#define SSL3_BUFFER_set_len(b, l) ((b)->len = (l)) +#define SSL3_BUFFER_get_left(b) ((b)->left) +#define SSL3_BUFFER_set_left(b, l) ((b)->left = (l)) +#define SSL3_BUFFER_sub_left(b, l) ((b)->left -= (l)) +#define SSL3_BUFFER_get_offset(b) ((b)->offset) +#define SSL3_BUFFER_set_offset(b, o) ((b)->offset = (o)) +#define SSL3_BUFFER_add_offset(b, o) ((b)->offset += (o)) +#define SSL3_BUFFER_is_initialised(b) ((b)->buf != NULL) +#define SSL3_BUFFER_set_default_len(b, l) ((b)->default_len = (l)) + +void SSL3_BUFFER_clear(SSL3_BUFFER *b); +void SSL3_BUFFER_set_data(SSL3_BUFFER *b, const unsigned char *d, size_t n); +void SSL3_BUFFER_release(SSL3_BUFFER *b); +__owur int ssl3_setup_read_buffer(SSL *s); +__owur int ssl3_setup_write_buffer(SSL *s, size_t numwpipes, size_t len); +int ssl3_release_read_buffer(SSL *s); +int ssl3_release_write_buffer(SSL *s); + +/* Macros/functions provided by the SSL3_RECORD component */ + +#define SSL3_RECORD_get_type(r) ((r)->type) +#define SSL3_RECORD_set_type(r, t) ((r)->type = (t)) +#define SSL3_RECORD_set_rec_version(r, v) ((r)->rec_version = (v)) +#define SSL3_RECORD_get_length(r) ((r)->length) +#define SSL3_RECORD_set_length(r, l) ((r)->length = (l)) +#define SSL3_RECORD_add_length(r, l) ((r)->length += (l)) +#define SSL3_RECORD_sub_length(r, l) ((r)->length -= (l)) +#define SSL3_RECORD_get_data(r) ((r)->data) +#define SSL3_RECORD_set_data(r, d) ((r)->data = (d)) +#define SSL3_RECORD_get_input(r) ((r)->input) +#define SSL3_RECORD_set_input(r, i) ((r)->input = (i)) +#define SSL3_RECORD_reset_input(r) ((r)->input = (r)->data) +#define SSL3_RECORD_get_seq_num(r) ((r)->seq_num) +#define SSL3_RECORD_get_off(r) ((r)->off) +#define SSL3_RECORD_set_off(r, o) ((r)->off = (o)) +#define SSL3_RECORD_add_off(r, o) ((r)->off += (o)) +#define SSL3_RECORD_get_epoch(r) ((r)->epoch) +#define SSL3_RECORD_is_sslv2_record(r) \ + ((r)->rec_version == SSL2_VERSION) +#define SSL3_RECORD_is_read(r) ((r)->read) +#define SSL3_RECORD_set_read(r) ((r)->read = 1) + +void SSL3_RECORD_clear(SSL3_RECORD *r, size_t); +void SSL3_RECORD_release(SSL3_RECORD *r, size_t num_recs); +void SSL3_RECORD_set_seq_num(SSL3_RECORD *r, const unsigned char *seq_num); +int ssl3_get_record(SSL *s); +__owur int ssl3_do_compress(SSL *ssl, SSL3_RECORD *wr); +__owur int ssl3_do_uncompress(SSL *ssl, SSL3_RECORD *rr); +int ssl3_cbc_copy_mac(unsigned char *out, + const SSL3_RECORD *rec, size_t md_size); +__owur int ssl3_cbc_remove_padding(SSL3_RECORD *rec, + size_t block_size, size_t mac_size); +__owur int tls1_cbc_remove_padding(const SSL *s, + SSL3_RECORD *rec, + size_t block_size, size_t mac_size); +int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap); +__owur int dtls1_get_record(SSL *s); +int early_data_count_ok(SSL *s, size_t length, size_t overhead, int send); diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/record/ssl3_buffer.c b/trunk/3rdparty/openssl-1.1-fit/ssl/record/ssl3_buffer.c new file mode 100644 index 000000000..53bd4cb19 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/record/ssl3_buffer.c @@ -0,0 +1,179 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "../ssl_locl.h" +#include "record_locl.h" + +void SSL3_BUFFER_set_data(SSL3_BUFFER *b, const unsigned char *d, size_t n) +{ + if (d != NULL) + memcpy(b->buf, d, n); + b->left = n; + b->offset = 0; +} + +/* + * Clear the contents of an SSL3_BUFFER but retain any memory allocated. Also + * retains the default_len setting + */ +void SSL3_BUFFER_clear(SSL3_BUFFER *b) +{ + b->offset = 0; + b->left = 0; +} + +void SSL3_BUFFER_release(SSL3_BUFFER *b) +{ + OPENSSL_free(b->buf); + b->buf = NULL; +} + +int ssl3_setup_read_buffer(SSL *s) +{ + unsigned char *p; + size_t len, align = 0, headerlen; + SSL3_BUFFER *b; + + b = RECORD_LAYER_get_rbuf(&s->rlayer); + + if (SSL_IS_DTLS(s)) + headerlen = DTLS1_RT_HEADER_LENGTH; + else + headerlen = SSL3_RT_HEADER_LENGTH; + +#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0 + align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1); +#endif + + if (b->buf == NULL) { + len = SSL3_RT_MAX_PLAIN_LENGTH + + SSL3_RT_MAX_ENCRYPTED_OVERHEAD + headerlen + align; +#ifndef OPENSSL_NO_COMP + if (ssl_allow_compression(s)) + len += SSL3_RT_MAX_COMPRESSED_OVERHEAD; +#endif + if (b->default_len > len) + len = b->default_len; + if ((p = OPENSSL_malloc(len)) == NULL) { + /* + * We've got a malloc failure, and we're still initialising buffers. + * We assume we're so doomed that we won't even be able to send an + * alert. + */ + SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_SSL3_SETUP_READ_BUFFER, + ERR_R_MALLOC_FAILURE); + return 0; + } + b->buf = p; + b->len = len; + } + + RECORD_LAYER_set_packet(&s->rlayer, &(b->buf[0])); + return 1; +} + +int ssl3_setup_write_buffer(SSL *s, size_t numwpipes, size_t len) +{ + unsigned char *p; + size_t align = 0, headerlen; + SSL3_BUFFER *wb; + size_t currpipe; + + s->rlayer.numwpipes = numwpipes; + + if (len == 0) { + if (SSL_IS_DTLS(s)) + headerlen = DTLS1_RT_HEADER_LENGTH + 1; + else + headerlen = SSL3_RT_HEADER_LENGTH; + +#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0 + align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1); +#endif + + len = ssl_get_max_send_fragment(s) + + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD + headerlen + align; +#ifndef OPENSSL_NO_COMP + if (ssl_allow_compression(s)) + len += SSL3_RT_MAX_COMPRESSED_OVERHEAD; +#endif + if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)) + len += headerlen + align + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD; + } + + wb = RECORD_LAYER_get_wbuf(&s->rlayer); + for (currpipe = 0; currpipe < numwpipes; currpipe++) { + SSL3_BUFFER *thiswb = &wb[currpipe]; + + if (thiswb->buf != NULL && thiswb->len != len) { + OPENSSL_free(thiswb->buf); + thiswb->buf = NULL; /* force reallocation */ + } + + if (thiswb->buf == NULL) { + p = OPENSSL_malloc(len); + if (p == NULL) { + s->rlayer.numwpipes = currpipe; + /* + * We've got a malloc failure, and we're still initialising + * buffers. We assume we're so doomed that we won't even be able + * to send an alert. + */ + SSLfatal(s, SSL_AD_NO_ALERT, + SSL_F_SSL3_SETUP_WRITE_BUFFER, ERR_R_MALLOC_FAILURE); + return 0; + } + memset(thiswb, 0, sizeof(SSL3_BUFFER)); + thiswb->buf = p; + thiswb->len = len; + } + } + + return 1; +} + +int ssl3_setup_buffers(SSL *s) +{ + if (!ssl3_setup_read_buffer(s)) { + /* SSLfatal() already called */ + return 0; + } + if (!ssl3_setup_write_buffer(s, 1, 0)) { + /* SSLfatal() already called */ + return 0; + } + return 1; +} + +int ssl3_release_write_buffer(SSL *s) +{ + SSL3_BUFFER *wb; + size_t pipes; + + pipes = s->rlayer.numwpipes; + while (pipes > 0) { + wb = &RECORD_LAYER_get_wbuf(&s->rlayer)[pipes - 1]; + + OPENSSL_free(wb->buf); + wb->buf = NULL; + pipes--; + } + s->rlayer.numwpipes = 0; + return 1; +} + +int ssl3_release_read_buffer(SSL *s) +{ + SSL3_BUFFER *b; + + b = RECORD_LAYER_get_rbuf(&s->rlayer); + OPENSSL_free(b->buf); + b->buf = NULL; + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/record/ssl3_record.c b/trunk/3rdparty/openssl-1.1-fit/ssl/record/ssl3_record.c new file mode 100644 index 000000000..e59ac5a67 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/record/ssl3_record.c @@ -0,0 +1,2057 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "../ssl_locl.h" +#include "internal/constant_time_locl.h" +#include +#include "record_locl.h" +#include "internal/cryptlib.h" + +static const unsigned char ssl3_pad_1[48] = { + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36 +}; + +static const unsigned char ssl3_pad_2[48] = { + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c +}; + +/* + * Clear the contents of an SSL3_RECORD but retain any memory allocated + */ +void SSL3_RECORD_clear(SSL3_RECORD *r, size_t num_recs) +{ + unsigned char *comp; + size_t i; + + for (i = 0; i < num_recs; i++) { + comp = r[i].comp; + + memset(&r[i], 0, sizeof(*r)); + r[i].comp = comp; + } +} + +void SSL3_RECORD_release(SSL3_RECORD *r, size_t num_recs) +{ + size_t i; + + for (i = 0; i < num_recs; i++) { + OPENSSL_free(r[i].comp); + r[i].comp = NULL; + } +} + +void SSL3_RECORD_set_seq_num(SSL3_RECORD *r, const unsigned char *seq_num) +{ + memcpy(r->seq_num, seq_num, SEQ_NUM_SIZE); +} + +/* + * Peeks ahead into "read_ahead" data to see if we have a whole record waiting + * for us in the buffer. + */ +static int ssl3_record_app_data_waiting(SSL *s) +{ + SSL3_BUFFER *rbuf; + size_t left, len; + unsigned char *p; + + rbuf = RECORD_LAYER_get_rbuf(&s->rlayer); + + p = SSL3_BUFFER_get_buf(rbuf); + if (p == NULL) + return 0; + + left = SSL3_BUFFER_get_left(rbuf); + + if (left < SSL3_RT_HEADER_LENGTH) + return 0; + + p += SSL3_BUFFER_get_offset(rbuf); + + /* + * We only check the type and record length, we will sanity check version + * etc later + */ + if (*p != SSL3_RT_APPLICATION_DATA) + return 0; + + p += 3; + n2s(p, len); + + if (left < SSL3_RT_HEADER_LENGTH + len) + return 0; + + return 1; +} + +int early_data_count_ok(SSL *s, size_t length, size_t overhead, int send) +{ + uint32_t max_early_data; + SSL_SESSION *sess = s->session; + + /* + * If we are a client then we always use the max_early_data from the + * session/psksession. Otherwise we go with the lowest out of the max early + * data set in the session and the configured max_early_data. + */ + if (!s->server && sess->ext.max_early_data == 0) { + if (!ossl_assert(s->psksession != NULL + && s->psksession->ext.max_early_data > 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_EARLY_DATA_COUNT_OK, + ERR_R_INTERNAL_ERROR); + return 0; + } + sess = s->psksession; + } + + if (!s->server) + max_early_data = sess->ext.max_early_data; + else if (s->ext.early_data != SSL_EARLY_DATA_ACCEPTED) + max_early_data = s->recv_max_early_data; + else + max_early_data = s->recv_max_early_data < sess->ext.max_early_data + ? s->recv_max_early_data : sess->ext.max_early_data; + + if (max_early_data == 0) { + SSLfatal(s, send ? SSL_AD_INTERNAL_ERROR : SSL_AD_UNEXPECTED_MESSAGE, + SSL_F_EARLY_DATA_COUNT_OK, SSL_R_TOO_MUCH_EARLY_DATA); + return 0; + } + + /* If we are dealing with ciphertext we need to allow for the overhead */ + max_early_data += overhead; + + if (s->early_data_count + length > max_early_data) { + SSLfatal(s, send ? SSL_AD_INTERNAL_ERROR : SSL_AD_UNEXPECTED_MESSAGE, + SSL_F_EARLY_DATA_COUNT_OK, SSL_R_TOO_MUCH_EARLY_DATA); + return 0; + } + s->early_data_count += length; + + return 1; +} + +/* + * MAX_EMPTY_RECORDS defines the number of consecutive, empty records that + * will be processed per call to ssl3_get_record. Without this limit an + * attacker could send empty records at a faster rate than we can process and + * cause ssl3_get_record to loop forever. + */ +#define MAX_EMPTY_RECORDS 32 + +#define SSL2_RT_HEADER_LENGTH 2 +/*- + * Call this to get new input records. + * It will return <= 0 if more data is needed, normally due to an error + * or non-blocking IO. + * When it finishes, |numrpipes| records have been decoded. For each record 'i': + * rr[i].type - is the type of record + * rr[i].data, - data + * rr[i].length, - number of bytes + * Multiple records will only be returned if the record types are all + * SSL3_RT_APPLICATION_DATA. The number of records returned will always be <= + * |max_pipelines| + */ +/* used only by ssl3_read_bytes */ +int ssl3_get_record(SSL *s) +{ + int enc_err, rret; + int i; + size_t more, n; + SSL3_RECORD *rr, *thisrr; + SSL3_BUFFER *rbuf; + SSL_SESSION *sess; + unsigned char *p; + unsigned char md[EVP_MAX_MD_SIZE]; + unsigned int version; + size_t mac_size; + int imac_size; + size_t num_recs = 0, max_recs, j; + PACKET pkt, sslv2pkt; + size_t first_rec_len; + + rr = RECORD_LAYER_get_rrec(&s->rlayer); + rbuf = RECORD_LAYER_get_rbuf(&s->rlayer); + max_recs = s->max_pipelines; + if (max_recs == 0) + max_recs = 1; + sess = s->session; + + do { + thisrr = &rr[num_recs]; + + /* check if we have the header */ + if ((RECORD_LAYER_get_rstate(&s->rlayer) != SSL_ST_READ_BODY) || + (RECORD_LAYER_get_packet_length(&s->rlayer) + < SSL3_RT_HEADER_LENGTH)) { + size_t sslv2len; + unsigned int type; + + rret = ssl3_read_n(s, SSL3_RT_HEADER_LENGTH, + SSL3_BUFFER_get_len(rbuf), 0, + num_recs == 0 ? 1 : 0, &n); + if (rret <= 0) + return rret; /* error or non-blocking */ + RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_BODY); + + p = RECORD_LAYER_get_packet(&s->rlayer); + if (!PACKET_buf_init(&pkt, RECORD_LAYER_get_packet(&s->rlayer), + RECORD_LAYER_get_packet_length(&s->rlayer))) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GET_RECORD, + ERR_R_INTERNAL_ERROR); + return -1; + } + sslv2pkt = pkt; + if (!PACKET_get_net_2_len(&sslv2pkt, &sslv2len) + || !PACKET_get_1(&sslv2pkt, &type)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL3_GET_RECORD, + ERR_R_INTERNAL_ERROR); + return -1; + } + /* + * The first record received by the server may be a V2ClientHello. + */ + if (s->server && RECORD_LAYER_is_first_record(&s->rlayer) + && (sslv2len & 0x8000) != 0 + && (type == SSL2_MT_CLIENT_HELLO)) { + /* + * SSLv2 style record + * + * |num_recs| here will actually always be 0 because + * |num_recs > 0| only ever occurs when we are processing + * multiple app data records - which we know isn't the case here + * because it is an SSLv2ClientHello. We keep it using + * |num_recs| for the sake of consistency + */ + thisrr->type = SSL3_RT_HANDSHAKE; + thisrr->rec_version = SSL2_VERSION; + + thisrr->length = sslv2len & 0x7fff; + + if (thisrr->length > SSL3_BUFFER_get_len(rbuf) + - SSL2_RT_HEADER_LENGTH) { + SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD, + SSL_R_PACKET_LENGTH_TOO_LONG); + return -1; + } + + if (thisrr->length < MIN_SSL2_RECORD_LEN) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL3_GET_RECORD, + SSL_R_LENGTH_TOO_SHORT); + return -1; + } + } else { + /* SSLv3+ style record */ + if (s->msg_callback) + s->msg_callback(0, 0, SSL3_RT_HEADER, p, 5, s, + s->msg_callback_arg); + + /* Pull apart the header into the SSL3_RECORD */ + if (!PACKET_get_1(&pkt, &type) + || !PACKET_get_net_2(&pkt, &version) + || !PACKET_get_net_2_len(&pkt, &thisrr->length)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL3_GET_RECORD, + ERR_R_INTERNAL_ERROR); + return -1; + } + thisrr->type = type; + thisrr->rec_version = version; + + /* + * Lets check version. In TLSv1.3 we only check this field + * when encryption is occurring (see later check). For the + * ServerHello after an HRR we haven't actually selected TLSv1.3 + * yet, but we still treat it as TLSv1.3, so we must check for + * that explicitly + */ + if (!s->first_packet && !SSL_IS_TLS13(s) + && s->hello_retry_request != SSL_HRR_PENDING + && version != (unsigned int)s->version) { + if ((s->version & 0xFF00) == (version & 0xFF00) + && !s->enc_write_ctx && !s->write_hash) { + if (thisrr->type == SSL3_RT_ALERT) { + /* + * The record is using an incorrect version number, + * but what we've got appears to be an alert. We + * haven't read the body yet to check whether its a + * fatal or not - but chances are it is. We probably + * shouldn't send a fatal alert back. We'll just + * end. + */ + SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_SSL3_GET_RECORD, + SSL_R_WRONG_VERSION_NUMBER); + return -1; + } + /* + * Send back error using their minor version number :-) + */ + s->version = (unsigned short)version; + } + SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_SSL3_GET_RECORD, + SSL_R_WRONG_VERSION_NUMBER); + return -1; + } + + if ((version >> 8) != SSL3_VERSION_MAJOR) { + if (RECORD_LAYER_is_first_record(&s->rlayer)) { + /* Go back to start of packet, look at the five bytes + * that we have. */ + p = RECORD_LAYER_get_packet(&s->rlayer); + if (strncmp((char *)p, "GET ", 4) == 0 || + strncmp((char *)p, "POST ", 5) == 0 || + strncmp((char *)p, "HEAD ", 5) == 0 || + strncmp((char *)p, "PUT ", 4) == 0) { + SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_SSL3_GET_RECORD, + SSL_R_HTTP_REQUEST); + return -1; + } else if (strncmp((char *)p, "CONNE", 5) == 0) { + SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_SSL3_GET_RECORD, + SSL_R_HTTPS_PROXY_REQUEST); + return -1; + } + + /* Doesn't look like TLS - don't send an alert */ + SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_SSL3_GET_RECORD, + SSL_R_WRONG_VERSION_NUMBER); + return -1; + } else { + SSLfatal(s, SSL_AD_PROTOCOL_VERSION, + SSL_F_SSL3_GET_RECORD, + SSL_R_WRONG_VERSION_NUMBER); + return -1; + } + } + + if (SSL_IS_TLS13(s) && s->enc_read_ctx != NULL) { + if (thisrr->type != SSL3_RT_APPLICATION_DATA + && (thisrr->type != SSL3_RT_CHANGE_CIPHER_SPEC + || !SSL_IS_FIRST_HANDSHAKE(s)) + && (thisrr->type != SSL3_RT_ALERT + || s->statem.enc_read_state + != ENC_READ_STATE_ALLOW_PLAIN_ALERTS)) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, + SSL_F_SSL3_GET_RECORD, SSL_R_BAD_RECORD_TYPE); + return -1; + } + if (thisrr->rec_version != TLS1_2_VERSION) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL3_GET_RECORD, + SSL_R_WRONG_VERSION_NUMBER); + return -1; + } + } + + if (thisrr->length > + SSL3_BUFFER_get_len(rbuf) - SSL3_RT_HEADER_LENGTH) { + SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD, + SSL_R_PACKET_LENGTH_TOO_LONG); + return -1; + } + } + + /* now s->rlayer.rstate == SSL_ST_READ_BODY */ + } + + if (SSL_IS_TLS13(s)) { + if (thisrr->length > SSL3_RT_MAX_TLS13_ENCRYPTED_LENGTH) { + SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD, + SSL_R_ENCRYPTED_LENGTH_TOO_LONG); + return -1; + } + } else { + size_t len = SSL3_RT_MAX_ENCRYPTED_LENGTH; + +#ifndef OPENSSL_NO_COMP + /* + * If OPENSSL_NO_COMP is defined then SSL3_RT_MAX_ENCRYPTED_LENGTH + * does not include the compression overhead anyway. + */ + if (s->expand == NULL) + len -= SSL3_RT_MAX_COMPRESSED_OVERHEAD; +#endif + + if (thisrr->length > len) { + SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD, + SSL_R_ENCRYPTED_LENGTH_TOO_LONG); + return -1; + } + } + + /* + * s->rlayer.rstate == SSL_ST_READ_BODY, get and decode the data. + * Calculate how much more data we need to read for the rest of the + * record + */ + if (thisrr->rec_version == SSL2_VERSION) { + more = thisrr->length + SSL2_RT_HEADER_LENGTH + - SSL3_RT_HEADER_LENGTH; + } else { + more = thisrr->length; + } + if (more > 0) { + /* now s->packet_length == SSL3_RT_HEADER_LENGTH */ + + rret = ssl3_read_n(s, more, more, 1, 0, &n); + if (rret <= 0) + return rret; /* error or non-blocking io */ + } + + /* set state for later operations */ + RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_HEADER); + + /* + * At this point, s->packet_length == SSL3_RT_HEADER_LENGTH + * + thisrr->length, or s->packet_length == SSL2_RT_HEADER_LENGTH + * + thisrr->length and we have that many bytes in s->packet + */ + if (thisrr->rec_version == SSL2_VERSION) { + thisrr->input = + &(RECORD_LAYER_get_packet(&s->rlayer)[SSL2_RT_HEADER_LENGTH]); + } else { + thisrr->input = + &(RECORD_LAYER_get_packet(&s->rlayer)[SSL3_RT_HEADER_LENGTH]); + } + + /* + * ok, we can now read from 's->packet' data into 'thisrr' thisrr->input + * points at thisrr->length bytes, which need to be copied into + * thisrr->data by either the decryption or by the decompression When + * the data is 'copied' into the thisrr->data buffer, thisrr->input will + * be pointed at the new buffer + */ + + /* + * We now have - encrypted [ MAC [ compressed [ plain ] ] ] + * thisrr->length bytes of encrypted compressed stuff. + */ + + /* decrypt in place in 'thisrr->input' */ + thisrr->data = thisrr->input; + thisrr->orig_len = thisrr->length; + + /* Mark this record as not read by upper layers yet */ + thisrr->read = 0; + + num_recs++; + + /* we have pulled in a full packet so zero things */ + RECORD_LAYER_reset_packet_length(&s->rlayer); + RECORD_LAYER_clear_first_record(&s->rlayer); + } while (num_recs < max_recs + && thisrr->type == SSL3_RT_APPLICATION_DATA + && SSL_USE_EXPLICIT_IV(s) + && s->enc_read_ctx != NULL + && (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_read_ctx)) + & EVP_CIPH_FLAG_PIPELINE) + && ssl3_record_app_data_waiting(s)); + + if (num_recs == 1 + && thisrr->type == SSL3_RT_CHANGE_CIPHER_SPEC + && (SSL_IS_TLS13(s) || s->hello_retry_request != SSL_HRR_NONE) + && SSL_IS_FIRST_HANDSHAKE(s)) { + /* + * CCS messages must be exactly 1 byte long, containing the value 0x01 + */ + if (thisrr->length != 1 || thisrr->data[0] != 0x01) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SSL3_GET_RECORD, + SSL_R_INVALID_CCS_MESSAGE); + return -1; + } + /* + * CCS messages are ignored in TLSv1.3. We treat it like an empty + * handshake record + */ + thisrr->type = SSL3_RT_HANDSHAKE; + RECORD_LAYER_inc_empty_record_count(&s->rlayer); + if (RECORD_LAYER_get_empty_record_count(&s->rlayer) + > MAX_EMPTY_RECORDS) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_GET_RECORD, + SSL_R_UNEXPECTED_CCS_MESSAGE); + return -1; + } + thisrr->read = 1; + RECORD_LAYER_set_numrpipes(&s->rlayer, 1); + + return 1; + } + + /* + * If in encrypt-then-mac mode calculate mac from encrypted record. All + * the details below are public so no timing details can leak. + */ + if (SSL_READ_ETM(s) && s->read_hash) { + unsigned char *mac; + /* TODO(size_t): convert this to do size_t properly */ + imac_size = EVP_MD_CTX_size(s->read_hash); + if (!ossl_assert(imac_size >= 0 && imac_size <= EVP_MAX_MD_SIZE)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GET_RECORD, + ERR_LIB_EVP); + return -1; + } + mac_size = (size_t)imac_size; + for (j = 0; j < num_recs; j++) { + thisrr = &rr[j]; + + if (thisrr->length < mac_size) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL3_GET_RECORD, + SSL_R_LENGTH_TOO_SHORT); + return -1; + } + thisrr->length -= mac_size; + mac = thisrr->data + thisrr->length; + i = s->method->ssl3_enc->mac(s, thisrr, md, 0 /* not send */ ); + if (i == 0 || CRYPTO_memcmp(md, mac, mac_size) != 0) { + SSLfatal(s, SSL_AD_BAD_RECORD_MAC, SSL_F_SSL3_GET_RECORD, + SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC); + return -1; + } + } + } + + first_rec_len = rr[0].length; + + enc_err = s->method->ssl3_enc->enc(s, rr, num_recs, 0); + + /*- + * enc_err is: + * 0: (in non-constant time) if the record is publicly invalid. + * 1: if the padding is valid + * -1: if the padding is invalid + */ + if (enc_err == 0) { + if (ossl_statem_in_error(s)) { + /* SSLfatal() already got called */ + return -1; + } + if (num_recs == 1 && ossl_statem_skip_early_data(s)) { + /* + * Valid early_data that we cannot decrypt might fail here as + * publicly invalid. We treat it like an empty record. + */ + + thisrr = &rr[0]; + + if (!early_data_count_ok(s, thisrr->length, + EARLY_DATA_CIPHERTEXT_OVERHEAD, 0)) { + /* SSLfatal() already called */ + return -1; + } + + thisrr->length = 0; + thisrr->read = 1; + RECORD_LAYER_set_numrpipes(&s->rlayer, 1); + RECORD_LAYER_reset_read_sequence(&s->rlayer); + return 1; + } + SSLfatal(s, SSL_AD_DECRYPTION_FAILED, SSL_F_SSL3_GET_RECORD, + SSL_R_BLOCK_CIPHER_PAD_IS_WRONG); + return -1; + } +#ifdef SSL_DEBUG + printf("dec %lu\n", (unsigned long)rr[0].length); + { + size_t z; + for (z = 0; z < rr[0].length; z++) + printf("%02X%c", rr[0].data[z], ((z + 1) % 16) ? ' ' : '\n'); + } + printf("\n"); +#endif + + /* r->length is now the compressed data plus mac */ + if ((sess != NULL) && + (s->enc_read_ctx != NULL) && + (!SSL_READ_ETM(s) && EVP_MD_CTX_md(s->read_hash) != NULL)) { + /* s->read_hash != NULL => mac_size != -1 */ + unsigned char *mac = NULL; + unsigned char mac_tmp[EVP_MAX_MD_SIZE]; + + mac_size = EVP_MD_CTX_size(s->read_hash); + if (!ossl_assert(mac_size <= EVP_MAX_MD_SIZE)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GET_RECORD, + ERR_R_INTERNAL_ERROR); + return -1; + } + + for (j = 0; j < num_recs; j++) { + thisrr = &rr[j]; + /* + * orig_len is the length of the record before any padding was + * removed. This is public information, as is the MAC in use, + * therefore we can safely process the record in a different amount + * of time if it's too short to possibly contain a MAC. + */ + if (thisrr->orig_len < mac_size || + /* CBC records must have a padding length byte too. */ + (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE && + thisrr->orig_len < mac_size + 1)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL3_GET_RECORD, + SSL_R_LENGTH_TOO_SHORT); + return -1; + } + + if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE) { + /* + * We update the length so that the TLS header bytes can be + * constructed correctly but we need to extract the MAC in + * constant time from within the record, without leaking the + * contents of the padding bytes. + */ + mac = mac_tmp; + if (!ssl3_cbc_copy_mac(mac_tmp, thisrr, mac_size)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GET_RECORD, + ERR_R_INTERNAL_ERROR); + return -1; + } + thisrr->length -= mac_size; + } else { + /* + * In this case there's no padding, so |rec->orig_len| equals + * |rec->length| and we checked that there's enough bytes for + * |mac_size| above. + */ + thisrr->length -= mac_size; + mac = &thisrr->data[thisrr->length]; + } + + i = s->method->ssl3_enc->mac(s, thisrr, md, 0 /* not send */ ); + if (i == 0 || mac == NULL + || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0) + enc_err = -1; + if (thisrr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + mac_size) + enc_err = -1; + } + } + + if (enc_err < 0) { + if (ossl_statem_in_error(s)) { + /* We already called SSLfatal() */ + return -1; + } + if (num_recs == 1 && ossl_statem_skip_early_data(s)) { + /* + * We assume this is unreadable early_data - we treat it like an + * empty record + */ + + /* + * The record length may have been modified by the mac check above + * so we use the previously saved value + */ + if (!early_data_count_ok(s, first_rec_len, + EARLY_DATA_CIPHERTEXT_OVERHEAD, 0)) { + /* SSLfatal() already called */ + return -1; + } + + thisrr = &rr[0]; + thisrr->length = 0; + thisrr->read = 1; + RECORD_LAYER_set_numrpipes(&s->rlayer, 1); + RECORD_LAYER_reset_read_sequence(&s->rlayer); + return 1; + } + /* + * A separate 'decryption_failed' alert was introduced with TLS 1.0, + * SSL 3.0 only has 'bad_record_mac'. But unless a decryption + * failure is directly visible from the ciphertext anyway, we should + * not reveal which kind of error occurred -- this might become + * visible to an attacker (e.g. via a logfile) + */ + SSLfatal(s, SSL_AD_BAD_RECORD_MAC, SSL_F_SSL3_GET_RECORD, + SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC); + return -1; + } + + for (j = 0; j < num_recs; j++) { + thisrr = &rr[j]; + + /* thisrr->length is now just compressed */ + if (s->expand != NULL) { + if (thisrr->length > SSL3_RT_MAX_COMPRESSED_LENGTH) { + SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD, + SSL_R_COMPRESSED_LENGTH_TOO_LONG); + return -1; + } + if (!ssl3_do_uncompress(s, thisrr)) { + SSLfatal(s, SSL_AD_DECOMPRESSION_FAILURE, SSL_F_SSL3_GET_RECORD, + SSL_R_BAD_DECOMPRESSION); + return -1; + } + } + + if (SSL_IS_TLS13(s) + && s->enc_read_ctx != NULL + && thisrr->type != SSL3_RT_ALERT) { + size_t end; + + if (thisrr->length == 0 + || thisrr->type != SSL3_RT_APPLICATION_DATA) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_GET_RECORD, + SSL_R_BAD_RECORD_TYPE); + return -1; + } + + /* Strip trailing padding */ + for (end = thisrr->length - 1; end > 0 && thisrr->data[end] == 0; + end--) + continue; + + thisrr->length = end; + thisrr->type = thisrr->data[end]; + if (thisrr->type != SSL3_RT_APPLICATION_DATA + && thisrr->type != SSL3_RT_ALERT + && thisrr->type != SSL3_RT_HANDSHAKE) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_GET_RECORD, + SSL_R_BAD_RECORD_TYPE); + return -1; + } + if (s->msg_callback) + s->msg_callback(0, s->version, SSL3_RT_INNER_CONTENT_TYPE, + &thisrr->data[end], 1, s, s->msg_callback_arg); + } + + /* + * TLSv1.3 alert and handshake records are required to be non-zero in + * length. + */ + if (SSL_IS_TLS13(s) + && (thisrr->type == SSL3_RT_HANDSHAKE + || thisrr->type == SSL3_RT_ALERT) + && thisrr->length == 0) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_GET_RECORD, + SSL_R_BAD_LENGTH); + return -1; + } + + if (thisrr->length > SSL3_RT_MAX_PLAIN_LENGTH) { + SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD, + SSL_R_DATA_LENGTH_TOO_LONG); + return -1; + } + + /* If received packet overflows current Max Fragment Length setting */ + if (s->session != NULL && USE_MAX_FRAGMENT_LENGTH_EXT(s->session) + && thisrr->length > GET_MAX_FRAGMENT_LENGTH(s->session)) { + SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD, + SSL_R_DATA_LENGTH_TOO_LONG); + return -1; + } + + thisrr->off = 0; + /*- + * So at this point the following is true + * thisrr->type is the type of record + * thisrr->length == number of bytes in record + * thisrr->off == offset to first valid byte + * thisrr->data == where to take bytes from, increment after use :-). + */ + + /* just read a 0 length packet */ + if (thisrr->length == 0) { + RECORD_LAYER_inc_empty_record_count(&s->rlayer); + if (RECORD_LAYER_get_empty_record_count(&s->rlayer) + > MAX_EMPTY_RECORDS) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_GET_RECORD, + SSL_R_RECORD_TOO_SMALL); + return -1; + } + } else { + RECORD_LAYER_reset_empty_record_count(&s->rlayer); + } + } + + if (s->early_data_state == SSL_EARLY_DATA_READING) { + thisrr = &rr[0]; + if (thisrr->type == SSL3_RT_APPLICATION_DATA + && !early_data_count_ok(s, thisrr->length, 0, 0)) { + /* SSLfatal already called */ + return -1; + } + } + + RECORD_LAYER_set_numrpipes(&s->rlayer, num_recs); + return 1; +} + +int ssl3_do_uncompress(SSL *ssl, SSL3_RECORD *rr) +{ +#ifndef OPENSSL_NO_COMP + int i; + + if (rr->comp == NULL) { + rr->comp = (unsigned char *) + OPENSSL_malloc(SSL3_RT_MAX_ENCRYPTED_LENGTH); + } + if (rr->comp == NULL) + return 0; + + /* TODO(size_t): Convert this call */ + i = COMP_expand_block(ssl->expand, rr->comp, + SSL3_RT_MAX_PLAIN_LENGTH, rr->data, (int)rr->length); + if (i < 0) + return 0; + else + rr->length = i; + rr->data = rr->comp; +#endif + return 1; +} + +int ssl3_do_compress(SSL *ssl, SSL3_RECORD *wr) +{ +#ifndef OPENSSL_NO_COMP + int i; + + /* TODO(size_t): Convert this call */ + i = COMP_compress_block(ssl->compress, wr->data, + (int)(wr->length + SSL3_RT_MAX_COMPRESSED_OVERHEAD), + wr->input, (int)wr->length); + if (i < 0) + return 0; + else + wr->length = i; + + wr->input = wr->data; +#endif + return 1; +} + +/*- + * ssl3_enc encrypts/decrypts |n_recs| records in |inrecs|. Will call + * SSLfatal() for internal errors, but not otherwise. + * + * Returns: + * 0: (in non-constant time) if the record is publically invalid (i.e. too + * short etc). + * 1: if the record's padding is valid / the encryption was successful. + * -1: if the record's padding is invalid or, if sending, an internal error + * occurred. + */ +int ssl3_enc(SSL *s, SSL3_RECORD *inrecs, size_t n_recs, int sending) +{ + SSL3_RECORD *rec; + EVP_CIPHER_CTX *ds; + size_t l, i; + size_t bs, mac_size = 0; + int imac_size; + const EVP_CIPHER *enc; + + rec = inrecs; + /* + * We shouldn't ever be called with more than one record in the SSLv3 case + */ + if (n_recs != 1) + return 0; + if (sending) { + ds = s->enc_write_ctx; + if (s->enc_write_ctx == NULL) + enc = NULL; + else + enc = EVP_CIPHER_CTX_cipher(s->enc_write_ctx); + } else { + ds = s->enc_read_ctx; + if (s->enc_read_ctx == NULL) + enc = NULL; + else + enc = EVP_CIPHER_CTX_cipher(s->enc_read_ctx); + } + + if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) { + memmove(rec->data, rec->input, rec->length); + rec->input = rec->data; + } else { + l = rec->length; + /* TODO(size_t): Convert this call */ + bs = EVP_CIPHER_CTX_block_size(ds); + + /* COMPRESS */ + + if ((bs != 1) && sending) { + i = bs - (l % bs); + + /* we need to add 'i-1' padding bytes */ + l += i; + /* + * the last of these zero bytes will be overwritten with the + * padding length. + */ + memset(&rec->input[rec->length], 0, i); + rec->length += i; + rec->input[l - 1] = (unsigned char)(i - 1); + } + + if (!sending) { + if (l == 0 || l % bs != 0) + return 0; + /* otherwise, rec->length >= bs */ + } + + /* TODO(size_t): Convert this call */ + if (EVP_Cipher(ds, rec->data, rec->input, (unsigned int)l) < 1) + return -1; + + if (EVP_MD_CTX_md(s->read_hash) != NULL) { + /* TODO(size_t): convert me */ + imac_size = EVP_MD_CTX_size(s->read_hash); + if (imac_size < 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_ENC, + ERR_R_INTERNAL_ERROR); + return -1; + } + mac_size = (size_t)imac_size; + } + if ((bs != 1) && !sending) + return ssl3_cbc_remove_padding(rec, bs, mac_size); + } + return 1; +} + +#define MAX_PADDING 256 +/*- + * tls1_enc encrypts/decrypts |n_recs| in |recs|. Will call SSLfatal() for + * internal errors, but not otherwise. + * + * Returns: + * 0: (in non-constant time) if the record is publically invalid (i.e. too + * short etc). + * 1: if the record's padding is valid / the encryption was successful. + * -1: if the record's padding/AEAD-authenticator is invalid or, if sending, + * an internal error occurred. + */ +int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending) +{ + EVP_CIPHER_CTX *ds; + size_t reclen[SSL_MAX_PIPELINES]; + unsigned char buf[SSL_MAX_PIPELINES][EVP_AEAD_TLS1_AAD_LEN]; + int i, pad = 0, ret, tmpr; + size_t bs, mac_size = 0, ctr, padnum, loop; + unsigned char padval; + int imac_size; + const EVP_CIPHER *enc; + + if (n_recs == 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC, + ERR_R_INTERNAL_ERROR); + return 0; + } + + if (sending) { + if (EVP_MD_CTX_md(s->write_hash)) { + int n = EVP_MD_CTX_size(s->write_hash); + if (!ossl_assert(n >= 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC, + ERR_R_INTERNAL_ERROR); + return -1; + } + } + ds = s->enc_write_ctx; + if (s->enc_write_ctx == NULL) + enc = NULL; + else { + int ivlen; + enc = EVP_CIPHER_CTX_cipher(s->enc_write_ctx); + /* For TLSv1.1 and later explicit IV */ + if (SSL_USE_EXPLICIT_IV(s) + && EVP_CIPHER_mode(enc) == EVP_CIPH_CBC_MODE) + ivlen = EVP_CIPHER_iv_length(enc); + else + ivlen = 0; + if (ivlen > 1) { + for (ctr = 0; ctr < n_recs; ctr++) { + if (recs[ctr].data != recs[ctr].input) { + /* + * we can't write into the input stream: Can this ever + * happen?? (steve) + */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC, + ERR_R_INTERNAL_ERROR); + return -1; + } else if (RAND_bytes(recs[ctr].input, ivlen) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC, + ERR_R_INTERNAL_ERROR); + return -1; + } + } + } + } + } else { + if (EVP_MD_CTX_md(s->read_hash)) { + int n = EVP_MD_CTX_size(s->read_hash); + if (!ossl_assert(n >= 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC, + ERR_R_INTERNAL_ERROR); + return -1; + } + } + ds = s->enc_read_ctx; + if (s->enc_read_ctx == NULL) + enc = NULL; + else + enc = EVP_CIPHER_CTX_cipher(s->enc_read_ctx); + } + + if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) { + for (ctr = 0; ctr < n_recs; ctr++) { + memmove(recs[ctr].data, recs[ctr].input, recs[ctr].length); + recs[ctr].input = recs[ctr].data; + } + ret = 1; + } else { + bs = EVP_CIPHER_block_size(EVP_CIPHER_CTX_cipher(ds)); + + if (n_recs > 1) { + if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ds)) + & EVP_CIPH_FLAG_PIPELINE)) { + /* + * We shouldn't have been called with pipeline data if the + * cipher doesn't support pipelining + */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC, + SSL_R_PIPELINE_FAILURE); + return -1; + } + } + for (ctr = 0; ctr < n_recs; ctr++) { + reclen[ctr] = recs[ctr].length; + + if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ds)) + & EVP_CIPH_FLAG_AEAD_CIPHER) { + unsigned char *seq; + + seq = sending ? RECORD_LAYER_get_write_sequence(&s->rlayer) + : RECORD_LAYER_get_read_sequence(&s->rlayer); + + if (SSL_IS_DTLS(s)) { + /* DTLS does not support pipelining */ + unsigned char dtlsseq[9], *p = dtlsseq; + + s2n(sending ? DTLS_RECORD_LAYER_get_w_epoch(&s->rlayer) : + DTLS_RECORD_LAYER_get_r_epoch(&s->rlayer), p); + memcpy(p, &seq[2], 6); + memcpy(buf[ctr], dtlsseq, 8); + } else { + memcpy(buf[ctr], seq, 8); + for (i = 7; i >= 0; i--) { /* increment */ + ++seq[i]; + if (seq[i] != 0) + break; + } + } + + buf[ctr][8] = recs[ctr].type; + buf[ctr][9] = (unsigned char)(s->version >> 8); + buf[ctr][10] = (unsigned char)(s->version); + buf[ctr][11] = (unsigned char)(recs[ctr].length >> 8); + buf[ctr][12] = (unsigned char)(recs[ctr].length & 0xff); + pad = EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_AEAD_TLS1_AAD, + EVP_AEAD_TLS1_AAD_LEN, buf[ctr]); + if (pad <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC, + ERR_R_INTERNAL_ERROR); + return -1; + } + + if (sending) { + reclen[ctr] += pad; + recs[ctr].length += pad; + } + + } else if ((bs != 1) && sending) { + padnum = bs - (reclen[ctr] % bs); + + /* Add weird padding of upto 256 bytes */ + + if (padnum > MAX_PADDING) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC, + ERR_R_INTERNAL_ERROR); + return -1; + } + /* we need to add 'padnum' padding bytes of value padval */ + padval = (unsigned char)(padnum - 1); + for (loop = reclen[ctr]; loop < reclen[ctr] + padnum; loop++) + recs[ctr].input[loop] = padval; + reclen[ctr] += padnum; + recs[ctr].length += padnum; + } + + if (!sending) { + if (reclen[ctr] == 0 || reclen[ctr] % bs != 0) + return 0; + } + } + if (n_recs > 1) { + unsigned char *data[SSL_MAX_PIPELINES]; + + /* Set the output buffers */ + for (ctr = 0; ctr < n_recs; ctr++) { + data[ctr] = recs[ctr].data; + } + if (EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_SET_PIPELINE_OUTPUT_BUFS, + (int)n_recs, data) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC, + SSL_R_PIPELINE_FAILURE); + return -1; + } + /* Set the input buffers */ + for (ctr = 0; ctr < n_recs; ctr++) { + data[ctr] = recs[ctr].input; + } + if (EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_SET_PIPELINE_INPUT_BUFS, + (int)n_recs, data) <= 0 + || EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_SET_PIPELINE_INPUT_LENS, + (int)n_recs, reclen) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC, + SSL_R_PIPELINE_FAILURE); + return -1; + } + } + + /* TODO(size_t): Convert this call */ + tmpr = EVP_Cipher(ds, recs[0].data, recs[0].input, + (unsigned int)reclen[0]); + if ((EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ds)) + & EVP_CIPH_FLAG_CUSTOM_CIPHER) + ? (tmpr < 0) + : (tmpr == 0)) + return -1; /* AEAD can fail to verify MAC */ + + if (sending == 0) { + if (EVP_CIPHER_mode(enc) == EVP_CIPH_GCM_MODE) { + for (ctr = 0; ctr < n_recs; ctr++) { + recs[ctr].data += EVP_GCM_TLS_EXPLICIT_IV_LEN; + recs[ctr].input += EVP_GCM_TLS_EXPLICIT_IV_LEN; + recs[ctr].length -= EVP_GCM_TLS_EXPLICIT_IV_LEN; + } + } else if (EVP_CIPHER_mode(enc) == EVP_CIPH_CCM_MODE) { + for (ctr = 0; ctr < n_recs; ctr++) { + recs[ctr].data += EVP_CCM_TLS_EXPLICIT_IV_LEN; + recs[ctr].input += EVP_CCM_TLS_EXPLICIT_IV_LEN; + recs[ctr].length -= EVP_CCM_TLS_EXPLICIT_IV_LEN; + } + } + } + + ret = 1; + if (!SSL_READ_ETM(s) && EVP_MD_CTX_md(s->read_hash) != NULL) { + imac_size = EVP_MD_CTX_size(s->read_hash); + if (imac_size < 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC, + ERR_R_INTERNAL_ERROR); + return -1; + } + mac_size = (size_t)imac_size; + } + if ((bs != 1) && !sending) { + int tmpret; + for (ctr = 0; ctr < n_recs; ctr++) { + tmpret = tls1_cbc_remove_padding(s, &recs[ctr], bs, mac_size); + /* + * If tmpret == 0 then this means publicly invalid so we can + * short circuit things here. Otherwise we must respect constant + * time behaviour. + */ + if (tmpret == 0) + return 0; + ret = constant_time_select_int(constant_time_eq_int(tmpret, 1), + ret, -1); + } + } + if (pad && !sending) { + for (ctr = 0; ctr < n_recs; ctr++) { + recs[ctr].length -= pad; + } + } + } + return ret; +} + +int n_ssl3_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending) +{ + unsigned char *mac_sec, *seq; + const EVP_MD_CTX *hash; + unsigned char *p, rec_char; + size_t md_size; + size_t npad; + int t; + + if (sending) { + mac_sec = &(ssl->s3->write_mac_secret[0]); + seq = RECORD_LAYER_get_write_sequence(&ssl->rlayer); + hash = ssl->write_hash; + } else { + mac_sec = &(ssl->s3->read_mac_secret[0]); + seq = RECORD_LAYER_get_read_sequence(&ssl->rlayer); + hash = ssl->read_hash; + } + + t = EVP_MD_CTX_size(hash); + if (t < 0) + return 0; + md_size = t; + npad = (48 / md_size) * md_size; + + if (!sending && + EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE && + ssl3_cbc_record_digest_supported(hash)) { + /* + * This is a CBC-encrypted record. We must avoid leaking any + * timing-side channel information about how many blocks of data we + * are hashing because that gives an attacker a timing-oracle. + */ + + /*- + * npad is, at most, 48 bytes and that's with MD5: + * 16 + 48 + 8 (sequence bytes) + 1 + 2 = 75. + * + * With SHA-1 (the largest hash speced for SSLv3) the hash size + * goes up 4, but npad goes down by 8, resulting in a smaller + * total size. + */ + unsigned char header[75]; + size_t j = 0; + memcpy(header + j, mac_sec, md_size); + j += md_size; + memcpy(header + j, ssl3_pad_1, npad); + j += npad; + memcpy(header + j, seq, 8); + j += 8; + header[j++] = rec->type; + header[j++] = (unsigned char)(rec->length >> 8); + header[j++] = (unsigned char)(rec->length & 0xff); + + /* Final param == is SSLv3 */ + if (ssl3_cbc_digest_record(hash, + md, &md_size, + header, rec->input, + rec->length + md_size, rec->orig_len, + mac_sec, md_size, 1) <= 0) + return 0; + } else { + unsigned int md_size_u; + /* Chop the digest off the end :-) */ + EVP_MD_CTX *md_ctx = EVP_MD_CTX_new(); + + if (md_ctx == NULL) + return 0; + + rec_char = rec->type; + p = md; + s2n(rec->length, p); + if (EVP_MD_CTX_copy_ex(md_ctx, hash) <= 0 + || EVP_DigestUpdate(md_ctx, mac_sec, md_size) <= 0 + || EVP_DigestUpdate(md_ctx, ssl3_pad_1, npad) <= 0 + || EVP_DigestUpdate(md_ctx, seq, 8) <= 0 + || EVP_DigestUpdate(md_ctx, &rec_char, 1) <= 0 + || EVP_DigestUpdate(md_ctx, md, 2) <= 0 + || EVP_DigestUpdate(md_ctx, rec->input, rec->length) <= 0 + || EVP_DigestFinal_ex(md_ctx, md, NULL) <= 0 + || EVP_MD_CTX_copy_ex(md_ctx, hash) <= 0 + || EVP_DigestUpdate(md_ctx, mac_sec, md_size) <= 0 + || EVP_DigestUpdate(md_ctx, ssl3_pad_2, npad) <= 0 + || EVP_DigestUpdate(md_ctx, md, md_size) <= 0 + || EVP_DigestFinal_ex(md_ctx, md, &md_size_u) <= 0) { + EVP_MD_CTX_free(md_ctx); + return 0; + } + + EVP_MD_CTX_free(md_ctx); + } + + ssl3_record_sequence_update(seq); + return 1; +} + +int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending) +{ + unsigned char *seq; + EVP_MD_CTX *hash; + size_t md_size; + int i; + EVP_MD_CTX *hmac = NULL, *mac_ctx; + unsigned char header[13]; + int stream_mac = (sending ? (ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_STREAM) + : (ssl->mac_flags & SSL_MAC_FLAG_READ_MAC_STREAM)); + int t; + + if (sending) { + seq = RECORD_LAYER_get_write_sequence(&ssl->rlayer); + hash = ssl->write_hash; + } else { + seq = RECORD_LAYER_get_read_sequence(&ssl->rlayer); + hash = ssl->read_hash; + } + + t = EVP_MD_CTX_size(hash); + if (!ossl_assert(t >= 0)) + return 0; + md_size = t; + + /* I should fix this up TLS TLS TLS TLS TLS XXXXXXXX */ + if (stream_mac) { + mac_ctx = hash; + } else { + hmac = EVP_MD_CTX_new(); + if (hmac == NULL || !EVP_MD_CTX_copy(hmac, hash)) { + EVP_MD_CTX_free(hmac); + return 0; + } + mac_ctx = hmac; + } + + if (SSL_IS_DTLS(ssl)) { + unsigned char dtlsseq[8], *p = dtlsseq; + + s2n(sending ? DTLS_RECORD_LAYER_get_w_epoch(&ssl->rlayer) : + DTLS_RECORD_LAYER_get_r_epoch(&ssl->rlayer), p); + memcpy(p, &seq[2], 6); + + memcpy(header, dtlsseq, 8); + } else + memcpy(header, seq, 8); + + header[8] = rec->type; + header[9] = (unsigned char)(ssl->version >> 8); + header[10] = (unsigned char)(ssl->version); + header[11] = (unsigned char)(rec->length >> 8); + header[12] = (unsigned char)(rec->length & 0xff); + + if (!sending && !SSL_READ_ETM(ssl) && + EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE && + ssl3_cbc_record_digest_supported(mac_ctx)) { + /* + * This is a CBC-encrypted record. We must avoid leaking any + * timing-side channel information about how many blocks of data we + * are hashing because that gives an attacker a timing-oracle. + */ + /* Final param == not SSLv3 */ + if (ssl3_cbc_digest_record(mac_ctx, + md, &md_size, + header, rec->input, + rec->length + md_size, rec->orig_len, + ssl->s3->read_mac_secret, + ssl->s3->read_mac_secret_size, 0) <= 0) { + EVP_MD_CTX_free(hmac); + return 0; + } + } else { + /* TODO(size_t): Convert these calls */ + if (EVP_DigestSignUpdate(mac_ctx, header, sizeof(header)) <= 0 + || EVP_DigestSignUpdate(mac_ctx, rec->input, rec->length) <= 0 + || EVP_DigestSignFinal(mac_ctx, md, &md_size) <= 0) { + EVP_MD_CTX_free(hmac); + return 0; + } + } + + EVP_MD_CTX_free(hmac); + +#ifdef SSL_DEBUG + fprintf(stderr, "seq="); + { + int z; + for (z = 0; z < 8; z++) + fprintf(stderr, "%02X ", seq[z]); + fprintf(stderr, "\n"); + } + fprintf(stderr, "rec="); + { + size_t z; + for (z = 0; z < rec->length; z++) + fprintf(stderr, "%02X ", rec->data[z]); + fprintf(stderr, "\n"); + } +#endif + + if (!SSL_IS_DTLS(ssl)) { + for (i = 7; i >= 0; i--) { + ++seq[i]; + if (seq[i] != 0) + break; + } + } +#ifdef SSL_DEBUG + { + unsigned int z; + for (z = 0; z < md_size; z++) + fprintf(stderr, "%02X ", md[z]); + fprintf(stderr, "\n"); + } +#endif + return 1; +} + +/*- + * ssl3_cbc_remove_padding removes padding from the decrypted, SSLv3, CBC + * record in |rec| by updating |rec->length| in constant time. + * + * block_size: the block size of the cipher used to encrypt the record. + * returns: + * 0: (in non-constant time) if the record is publicly invalid. + * 1: if the padding was valid + * -1: otherwise. + */ +int ssl3_cbc_remove_padding(SSL3_RECORD *rec, + size_t block_size, size_t mac_size) +{ + size_t padding_length; + size_t good; + const size_t overhead = 1 /* padding length byte */ + mac_size; + + /* + * These lengths are all public so we can test them in non-constant time. + */ + if (overhead > rec->length) + return 0; + + padding_length = rec->data[rec->length - 1]; + good = constant_time_ge_s(rec->length, padding_length + overhead); + /* SSLv3 requires that the padding is minimal. */ + good &= constant_time_ge_s(block_size, padding_length + 1); + rec->length -= good & (padding_length + 1); + return constant_time_select_int_s(good, 1, -1); +} + +/*- + * tls1_cbc_remove_padding removes the CBC padding from the decrypted, TLS, CBC + * record in |rec| in constant time and returns 1 if the padding is valid and + * -1 otherwise. It also removes any explicit IV from the start of the record + * without leaking any timing about whether there was enough space after the + * padding was removed. + * + * block_size: the block size of the cipher used to encrypt the record. + * returns: + * 0: (in non-constant time) if the record is publicly invalid. + * 1: if the padding was valid + * -1: otherwise. + */ +int tls1_cbc_remove_padding(const SSL *s, + SSL3_RECORD *rec, + size_t block_size, size_t mac_size) +{ + size_t good; + size_t padding_length, to_check, i; + const size_t overhead = 1 /* padding length byte */ + mac_size; + /* Check if version requires explicit IV */ + if (SSL_USE_EXPLICIT_IV(s)) { + /* + * These lengths are all public so we can test them in non-constant + * time. + */ + if (overhead + block_size > rec->length) + return 0; + /* We can now safely skip explicit IV */ + rec->data += block_size; + rec->input += block_size; + rec->length -= block_size; + rec->orig_len -= block_size; + } else if (overhead > rec->length) + return 0; + + padding_length = rec->data[rec->length - 1]; + + if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_read_ctx)) & + EVP_CIPH_FLAG_AEAD_CIPHER) { + /* padding is already verified */ + rec->length -= padding_length + 1; + return 1; + } + + good = constant_time_ge_s(rec->length, overhead + padding_length); + /* + * The padding consists of a length byte at the end of the record and + * then that many bytes of padding, all with the same value as the length + * byte. Thus, with the length byte included, there are i+1 bytes of + * padding. We can't check just |padding_length+1| bytes because that + * leaks decrypted information. Therefore we always have to check the + * maximum amount of padding possible. (Again, the length of the record + * is public information so we can use it.) + */ + to_check = 256; /* maximum amount of padding, inc length byte. */ + if (to_check > rec->length) + to_check = rec->length; + + for (i = 0; i < to_check; i++) { + unsigned char mask = constant_time_ge_8_s(padding_length, i); + unsigned char b = rec->data[rec->length - 1 - i]; + /* + * The final |padding_length+1| bytes should all have the value + * |padding_length|. Therefore the XOR should be zero. + */ + good &= ~(mask & (padding_length ^ b)); + } + + /* + * If any of the final |padding_length+1| bytes had the wrong value, one + * or more of the lower eight bits of |good| will be cleared. + */ + good = constant_time_eq_s(0xff, good & 0xff); + rec->length -= good & (padding_length + 1); + + return constant_time_select_int_s(good, 1, -1); +} + +/*- + * ssl3_cbc_copy_mac copies |md_size| bytes from the end of |rec| to |out| in + * constant time (independent of the concrete value of rec->length, which may + * vary within a 256-byte window). + * + * ssl3_cbc_remove_padding or tls1_cbc_remove_padding must be called prior to + * this function. + * + * On entry: + * rec->orig_len >= md_size + * md_size <= EVP_MAX_MD_SIZE + * + * If CBC_MAC_ROTATE_IN_PLACE is defined then the rotation is performed with + * variable accesses in a 64-byte-aligned buffer. Assuming that this fits into + * a single or pair of cache-lines, then the variable memory accesses don't + * actually affect the timing. CPUs with smaller cache-lines [if any] are + * not multi-core and are not considered vulnerable to cache-timing attacks. + */ +#define CBC_MAC_ROTATE_IN_PLACE + +int ssl3_cbc_copy_mac(unsigned char *out, + const SSL3_RECORD *rec, size_t md_size) +{ +#if defined(CBC_MAC_ROTATE_IN_PLACE) + unsigned char rotated_mac_buf[64 + EVP_MAX_MD_SIZE]; + unsigned char *rotated_mac; +#else + unsigned char rotated_mac[EVP_MAX_MD_SIZE]; +#endif + + /* + * mac_end is the index of |rec->data| just after the end of the MAC. + */ + size_t mac_end = rec->length; + size_t mac_start = mac_end - md_size; + size_t in_mac; + /* + * scan_start contains the number of bytes that we can ignore because the + * MAC's position can only vary by 255 bytes. + */ + size_t scan_start = 0; + size_t i, j; + size_t rotate_offset; + + if (!ossl_assert(rec->orig_len >= md_size + && md_size <= EVP_MAX_MD_SIZE)) + return 0; + +#if defined(CBC_MAC_ROTATE_IN_PLACE) + rotated_mac = rotated_mac_buf + ((0 - (size_t)rotated_mac_buf) & 63); +#endif + + /* This information is public so it's safe to branch based on it. */ + if (rec->orig_len > md_size + 255 + 1) + scan_start = rec->orig_len - (md_size + 255 + 1); + + in_mac = 0; + rotate_offset = 0; + memset(rotated_mac, 0, md_size); + for (i = scan_start, j = 0; i < rec->orig_len; i++) { + size_t mac_started = constant_time_eq_s(i, mac_start); + size_t mac_ended = constant_time_lt_s(i, mac_end); + unsigned char b = rec->data[i]; + + in_mac |= mac_started; + in_mac &= mac_ended; + rotate_offset |= j & mac_started; + rotated_mac[j++] |= b & in_mac; + j &= constant_time_lt_s(j, md_size); + } + + /* Now rotate the MAC */ +#if defined(CBC_MAC_ROTATE_IN_PLACE) + j = 0; + for (i = 0; i < md_size; i++) { + /* in case cache-line is 32 bytes, touch second line */ + ((volatile unsigned char *)rotated_mac)[rotate_offset ^ 32]; + out[j++] = rotated_mac[rotate_offset++]; + rotate_offset &= constant_time_lt_s(rotate_offset, md_size); + } +#else + memset(out, 0, md_size); + rotate_offset = md_size - rotate_offset; + rotate_offset &= constant_time_lt_s(rotate_offset, md_size); + for (i = 0; i < md_size; i++) { + for (j = 0; j < md_size; j++) + out[j] |= rotated_mac[i] & constant_time_eq_8_s(j, rotate_offset); + rotate_offset++; + rotate_offset &= constant_time_lt_s(rotate_offset, md_size); + } +#endif + + return 1; +} + +int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap) +{ + int i; + int enc_err; + SSL_SESSION *sess; + SSL3_RECORD *rr; + int imac_size; + size_t mac_size; + unsigned char md[EVP_MAX_MD_SIZE]; + + rr = RECORD_LAYER_get_rrec(&s->rlayer); + sess = s->session; + + /* + * At this point, s->packet_length == SSL3_RT_HEADER_LNGTH + rr->length, + * and we have that many bytes in s->packet + */ + rr->input = &(RECORD_LAYER_get_packet(&s->rlayer)[DTLS1_RT_HEADER_LENGTH]); + + /* + * ok, we can now read from 's->packet' data into 'rr' rr->input points + * at rr->length bytes, which need to be copied into rr->data by either + * the decryption or by the decompression When the data is 'copied' into + * the rr->data buffer, rr->input will be pointed at the new buffer + */ + + /* + * We now have - encrypted [ MAC [ compressed [ plain ] ] ] rr->length + * bytes of encrypted compressed stuff. + */ + + /* check is not needed I believe */ + if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) { + SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_DTLS1_PROCESS_RECORD, + SSL_R_ENCRYPTED_LENGTH_TOO_LONG); + return 0; + } + + /* decrypt in place in 'rr->input' */ + rr->data = rr->input; + rr->orig_len = rr->length; + + if (SSL_READ_ETM(s) && s->read_hash) { + unsigned char *mac; + mac_size = EVP_MD_CTX_size(s->read_hash); + if (!ossl_assert(mac_size <= EVP_MAX_MD_SIZE)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_PROCESS_RECORD, + ERR_R_INTERNAL_ERROR); + return 0; + } + if (rr->orig_len < mac_size) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_DTLS1_PROCESS_RECORD, + SSL_R_LENGTH_TOO_SHORT); + return 0; + } + rr->length -= mac_size; + mac = rr->data + rr->length; + i = s->method->ssl3_enc->mac(s, rr, md, 0 /* not send */ ); + if (i == 0 || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0) { + SSLfatal(s, SSL_AD_BAD_RECORD_MAC, SSL_F_DTLS1_PROCESS_RECORD, + SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC); + return 0; + } + } + + enc_err = s->method->ssl3_enc->enc(s, rr, 1, 0); + /*- + * enc_err is: + * 0: (in non-constant time) if the record is publically invalid. + * 1: if the padding is valid + * -1: if the padding is invalid + */ + if (enc_err == 0) { + if (ossl_statem_in_error(s)) { + /* SSLfatal() got called */ + return 0; + } + /* For DTLS we simply ignore bad packets. */ + rr->length = 0; + RECORD_LAYER_reset_packet_length(&s->rlayer); + return 0; + } +#ifdef SSL_DEBUG + printf("dec %ld\n", rr->length); + { + size_t z; + for (z = 0; z < rr->length; z++) + printf("%02X%c", rr->data[z], ((z + 1) % 16) ? ' ' : '\n'); + } + printf("\n"); +#endif + + /* r->length is now the compressed data plus mac */ + if ((sess != NULL) && !SSL_READ_ETM(s) && + (s->enc_read_ctx != NULL) && (EVP_MD_CTX_md(s->read_hash) != NULL)) { + /* s->read_hash != NULL => mac_size != -1 */ + unsigned char *mac = NULL; + unsigned char mac_tmp[EVP_MAX_MD_SIZE]; + + /* TODO(size_t): Convert this to do size_t properly */ + imac_size = EVP_MD_CTX_size(s->read_hash); + if (imac_size < 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_PROCESS_RECORD, + ERR_LIB_EVP); + return 0; + } + mac_size = (size_t)imac_size; + if (!ossl_assert(mac_size <= EVP_MAX_MD_SIZE)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_PROCESS_RECORD, + ERR_R_INTERNAL_ERROR); + return 0; + } + + /* + * orig_len is the length of the record before any padding was + * removed. This is public information, as is the MAC in use, + * therefore we can safely process the record in a different amount + * of time if it's too short to possibly contain a MAC. + */ + if (rr->orig_len < mac_size || + /* CBC records must have a padding length byte too. */ + (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE && + rr->orig_len < mac_size + 1)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_DTLS1_PROCESS_RECORD, + SSL_R_LENGTH_TOO_SHORT); + return 0; + } + + if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE) { + /* + * We update the length so that the TLS header bytes can be + * constructed correctly but we need to extract the MAC in + * constant time from within the record, without leaking the + * contents of the padding bytes. + */ + mac = mac_tmp; + if (!ssl3_cbc_copy_mac(mac_tmp, rr, mac_size)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_PROCESS_RECORD, + ERR_R_INTERNAL_ERROR); + return 0; + } + rr->length -= mac_size; + } else { + /* + * In this case there's no padding, so |rec->orig_len| equals + * |rec->length| and we checked that there's enough bytes for + * |mac_size| above. + */ + rr->length -= mac_size; + mac = &rr->data[rr->length]; + } + + i = s->method->ssl3_enc->mac(s, rr, md, 0 /* not send */ ); + if (i == 0 || mac == NULL + || CRYPTO_memcmp(md, mac, mac_size) != 0) + enc_err = -1; + if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + mac_size) + enc_err = -1; + } + + if (enc_err < 0) { + /* decryption failed, silently discard message */ + rr->length = 0; + RECORD_LAYER_reset_packet_length(&s->rlayer); + return 0; + } + + /* r->length is now just compressed */ + if (s->expand != NULL) { + if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH) { + SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_DTLS1_PROCESS_RECORD, + SSL_R_COMPRESSED_LENGTH_TOO_LONG); + return 0; + } + if (!ssl3_do_uncompress(s, rr)) { + SSLfatal(s, SSL_AD_DECOMPRESSION_FAILURE, + SSL_F_DTLS1_PROCESS_RECORD, SSL_R_BAD_DECOMPRESSION); + return 0; + } + } + + if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH) { + SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_DTLS1_PROCESS_RECORD, + SSL_R_DATA_LENGTH_TOO_LONG); + return 0; + } + + rr->off = 0; + /*- + * So at this point the following is true + * ssl->s3->rrec.type is the type of record + * ssl->s3->rrec.length == number of bytes in record + * ssl->s3->rrec.off == offset to first valid byte + * ssl->s3->rrec.data == where to take bytes from, increment + * after use :-). + */ + + /* we have pulled in a full packet so zero things */ + RECORD_LAYER_reset_packet_length(&s->rlayer); + + /* Mark receipt of record. */ + dtls1_record_bitmap_update(s, bitmap); + + return 1; +} + +/* + * Retrieve a buffered record that belongs to the current epoch, i.e. processed + */ +#define dtls1_get_processed_record(s) \ + dtls1_retrieve_buffered_record((s), \ + &(DTLS_RECORD_LAYER_get_processed_rcds(&s->rlayer))) + +/*- + * Call this to get a new input record. + * It will return <= 0 if more data is needed, normally due to an error + * or non-blocking IO. + * When it finishes, one packet has been decoded and can be found in + * ssl->s3->rrec.type - is the type of record + * ssl->s3->rrec.data, - data + * ssl->s3->rrec.length, - number of bytes + */ +/* used only by dtls1_read_bytes */ +int dtls1_get_record(SSL *s) +{ + int ssl_major, ssl_minor; + int rret; + size_t more, n; + SSL3_RECORD *rr; + unsigned char *p = NULL; + unsigned short version; + DTLS1_BITMAP *bitmap; + unsigned int is_next_epoch; + + rr = RECORD_LAYER_get_rrec(&s->rlayer); + + again: + /* + * The epoch may have changed. If so, process all the pending records. + * This is a non-blocking operation. + */ + if (!dtls1_process_buffered_records(s)) { + /* SSLfatal() already called */ + return -1; + } + + /* if we're renegotiating, then there may be buffered records */ + if (dtls1_get_processed_record(s)) + return 1; + + /* get something from the wire */ + + /* check if we have the header */ + if ((RECORD_LAYER_get_rstate(&s->rlayer) != SSL_ST_READ_BODY) || + (RECORD_LAYER_get_packet_length(&s->rlayer) < DTLS1_RT_HEADER_LENGTH)) { + rret = ssl3_read_n(s, DTLS1_RT_HEADER_LENGTH, + SSL3_BUFFER_get_len(&s->rlayer.rbuf), 0, 1, &n); + /* read timeout is handled by dtls1_read_bytes */ + if (rret <= 0) { + /* SSLfatal() already called if appropriate */ + return rret; /* error or non-blocking */ + } + + /* this packet contained a partial record, dump it */ + if (RECORD_LAYER_get_packet_length(&s->rlayer) != + DTLS1_RT_HEADER_LENGTH) { + RECORD_LAYER_reset_packet_length(&s->rlayer); + goto again; + } + + RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_BODY); + + p = RECORD_LAYER_get_packet(&s->rlayer); + + if (s->msg_callback) + s->msg_callback(0, 0, SSL3_RT_HEADER, p, DTLS1_RT_HEADER_LENGTH, + s, s->msg_callback_arg); + + /* Pull apart the header into the DTLS1_RECORD */ + rr->type = *(p++); + ssl_major = *(p++); + ssl_minor = *(p++); + version = (ssl_major << 8) | ssl_minor; + + /* sequence number is 64 bits, with top 2 bytes = epoch */ + n2s(p, rr->epoch); + + memcpy(&(RECORD_LAYER_get_read_sequence(&s->rlayer)[2]), p, 6); + p += 6; + + n2s(p, rr->length); + rr->read = 0; + + /* + * Lets check the version. We tolerate alerts that don't have the exact + * version number (e.g. because of protocol version errors) + */ + if (!s->first_packet && rr->type != SSL3_RT_ALERT) { + if (version != s->version) { + /* unexpected version, silently discard */ + rr->length = 0; + rr->read = 1; + RECORD_LAYER_reset_packet_length(&s->rlayer); + goto again; + } + } + + if ((version & 0xff00) != (s->version & 0xff00)) { + /* wrong version, silently discard record */ + rr->length = 0; + rr->read = 1; + RECORD_LAYER_reset_packet_length(&s->rlayer); + goto again; + } + + if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) { + /* record too long, silently discard it */ + rr->length = 0; + rr->read = 1; + RECORD_LAYER_reset_packet_length(&s->rlayer); + goto again; + } + + /* If received packet overflows own-client Max Fragment Length setting */ + if (s->session != NULL && USE_MAX_FRAGMENT_LENGTH_EXT(s->session) + && rr->length > GET_MAX_FRAGMENT_LENGTH(s->session)) { + /* record too long, silently discard it */ + rr->length = 0; + rr->read = 1; + RECORD_LAYER_reset_packet_length(&s->rlayer); + goto again; + } + + /* now s->rlayer.rstate == SSL_ST_READ_BODY */ + } + + /* s->rlayer.rstate == SSL_ST_READ_BODY, get and decode the data */ + + if (rr->length > + RECORD_LAYER_get_packet_length(&s->rlayer) - DTLS1_RT_HEADER_LENGTH) { + /* now s->packet_length == DTLS1_RT_HEADER_LENGTH */ + more = rr->length; + rret = ssl3_read_n(s, more, more, 1, 1, &n); + /* this packet contained a partial record, dump it */ + if (rret <= 0 || n != more) { + if (ossl_statem_in_error(s)) { + /* ssl3_read_n() called SSLfatal() */ + return -1; + } + rr->length = 0; + rr->read = 1; + RECORD_LAYER_reset_packet_length(&s->rlayer); + goto again; + } + + /* + * now n == rr->length, and s->packet_length == + * DTLS1_RT_HEADER_LENGTH + rr->length + */ + } + /* set state for later operations */ + RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_HEADER); + + /* match epochs. NULL means the packet is dropped on the floor */ + bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch); + if (bitmap == NULL) { + rr->length = 0; + RECORD_LAYER_reset_packet_length(&s->rlayer); /* dump this record */ + goto again; /* get another record */ + } +#ifndef OPENSSL_NO_SCTP + /* Only do replay check if no SCTP bio */ + if (!BIO_dgram_is_sctp(SSL_get_rbio(s))) { +#endif + /* Check whether this is a repeat, or aged record. */ + /* + * TODO: Does it make sense to have replay protection in epoch 0 where + * we have no integrity negotiated yet? + */ + if (!dtls1_record_replay_check(s, bitmap)) { + rr->length = 0; + rr->read = 1; + RECORD_LAYER_reset_packet_length(&s->rlayer); /* dump this record */ + goto again; /* get another record */ + } +#ifndef OPENSSL_NO_SCTP + } +#endif + + /* just read a 0 length packet */ + if (rr->length == 0) { + rr->read = 1; + goto again; + } + + /* + * If this record is from the next epoch (either HM or ALERT), and a + * handshake is currently in progress, buffer it since it cannot be + * processed at this time. + */ + if (is_next_epoch) { + if ((SSL_in_init(s) || ossl_statem_get_in_handshake(s))) { + if (dtls1_buffer_record (s, + &(DTLS_RECORD_LAYER_get_unprocessed_rcds(&s->rlayer)), + rr->seq_num) < 0) { + /* SSLfatal() already called */ + return -1; + } + } + rr->length = 0; + rr->read = 1; + RECORD_LAYER_reset_packet_length(&s->rlayer); + goto again; + } + + if (!dtls1_process_record(s, bitmap)) { + if (ossl_statem_in_error(s)) { + /* dtls1_process_record() called SSLfatal */ + return -1; + } + rr->length = 0; + rr->read = 1; + RECORD_LAYER_reset_packet_length(&s->rlayer); /* dump this record */ + goto again; /* get another record */ + } + + return 1; + +} + +int dtls_buffer_listen_record(SSL *s, size_t len, unsigned char *seq, size_t off) +{ + SSL3_RECORD *rr; + + rr = RECORD_LAYER_get_rrec(&s->rlayer); + memset(rr, 0, sizeof(SSL3_RECORD)); + + rr->length = len; + rr->type = SSL3_RT_HANDSHAKE; + memcpy(rr->seq_num, seq, sizeof(rr->seq_num)); + rr->off = off; + + s->rlayer.packet = RECORD_LAYER_get_rbuf(&s->rlayer)->buf; + s->rlayer.packet_length = DTLS1_RT_HEADER_LENGTH + len; + rr->data = s->rlayer.packet + DTLS1_RT_HEADER_LENGTH; + + if (dtls1_buffer_record(s, &(s->rlayer.d->processed_rcds), + SSL3_RECORD_get_seq_num(s->rlayer.rrec)) <= 0) { + /* SSLfatal() already called */ + return 0; + } + + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/record/ssl3_record_tls13.c b/trunk/3rdparty/openssl-1.1-fit/ssl/record/ssl3_record_tls13.c new file mode 100644 index 000000000..a11ed483e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/record/ssl3_record_tls13.c @@ -0,0 +1,196 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "../ssl_locl.h" +#include "record_locl.h" +#include "internal/cryptlib.h" + +/*- + * tls13_enc encrypts/decrypts |n_recs| in |recs|. Will call SSLfatal() for + * internal errors, but not otherwise. + * + * Returns: + * 0: (in non-constant time) if the record is publically invalid (i.e. too + * short etc). + * 1: if the record encryption was successful. + * -1: if the record's AEAD-authenticator is invalid or, if sending, + * an internal error occurred. + */ +int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending) +{ + EVP_CIPHER_CTX *ctx; + unsigned char iv[EVP_MAX_IV_LENGTH], recheader[SSL3_RT_HEADER_LENGTH]; + size_t ivlen, taglen, offset, loop, hdrlen; + unsigned char *staticiv; + unsigned char *seq; + int lenu, lenf; + SSL3_RECORD *rec = &recs[0]; + uint32_t alg_enc; + WPACKET wpkt; + + if (n_recs != 1) { + /* Should not happen */ + /* TODO(TLS1.3): Support pipelining */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC, + ERR_R_INTERNAL_ERROR); + return -1; + } + + if (sending) { + ctx = s->enc_write_ctx; + staticiv = s->write_iv; + seq = RECORD_LAYER_get_write_sequence(&s->rlayer); + } else { + ctx = s->enc_read_ctx; + staticiv = s->read_iv; + seq = RECORD_LAYER_get_read_sequence(&s->rlayer); + } + + /* + * If we're sending an alert and ctx != NULL then we must be forcing + * plaintext alerts. If we're reading and ctx != NULL then we allow + * plaintext alerts at certain points in the handshake. If we've got this + * far then we have already validated that a plaintext alert is ok here. + */ + if (ctx == NULL || rec->type == SSL3_RT_ALERT) { + memmove(rec->data, rec->input, rec->length); + rec->input = rec->data; + return 1; + } + + ivlen = EVP_CIPHER_CTX_iv_length(ctx); + + if (s->early_data_state == SSL_EARLY_DATA_WRITING + || s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) { + if (s->session != NULL && s->session->ext.max_early_data > 0) { + alg_enc = s->session->cipher->algorithm_enc; + } else { + if (!ossl_assert(s->psksession != NULL + && s->psksession->ext.max_early_data > 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC, + ERR_R_INTERNAL_ERROR); + return -1; + } + alg_enc = s->psksession->cipher->algorithm_enc; + } + } else { + /* + * To get here we must have selected a ciphersuite - otherwise ctx would + * be NULL + */ + if (!ossl_assert(s->s3->tmp.new_cipher != NULL)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC, + ERR_R_INTERNAL_ERROR); + return -1; + } + alg_enc = s->s3->tmp.new_cipher->algorithm_enc; + } + + if (alg_enc & SSL_AESCCM) { + if (alg_enc & (SSL_AES128CCM8 | SSL_AES256CCM8)) + taglen = EVP_CCM8_TLS_TAG_LEN; + else + taglen = EVP_CCM_TLS_TAG_LEN; + if (sending && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, taglen, + NULL) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC, + ERR_R_INTERNAL_ERROR); + return -1; + } + } else if (alg_enc & SSL_AESGCM) { + taglen = EVP_GCM_TLS_TAG_LEN; + } else if (alg_enc & SSL_CHACHA20) { + taglen = EVP_CHACHAPOLY_TLS_TAG_LEN; + } else { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC, + ERR_R_INTERNAL_ERROR); + return -1; + } + + if (!sending) { + /* + * Take off tag. There must be at least one byte of content type as + * well as the tag + */ + if (rec->length < taglen + 1) + return 0; + rec->length -= taglen; + } + + /* Set up IV */ + if (ivlen < SEQ_NUM_SIZE) { + /* Should not happen */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC, + ERR_R_INTERNAL_ERROR); + return -1; + } + offset = ivlen - SEQ_NUM_SIZE; + memcpy(iv, staticiv, offset); + for (loop = 0; loop < SEQ_NUM_SIZE; loop++) + iv[offset + loop] = staticiv[offset + loop] ^ seq[loop]; + + /* Increment the sequence counter */ + for (loop = SEQ_NUM_SIZE; loop > 0; loop--) { + ++seq[loop - 1]; + if (seq[loop - 1] != 0) + break; + } + if (loop == 0) { + /* Sequence has wrapped */ + return -1; + } + + /* TODO(size_t): lenu/lenf should be a size_t but EVP doesn't support it */ + if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, sending) <= 0 + || (!sending && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, + taglen, + rec->data + rec->length) <= 0)) { + return -1; + } + + /* Set up the AAD */ + if (!WPACKET_init_static_len(&wpkt, recheader, sizeof(recheader), 0) + || !WPACKET_put_bytes_u8(&wpkt, rec->type) + || !WPACKET_put_bytes_u16(&wpkt, rec->rec_version) + || !WPACKET_put_bytes_u16(&wpkt, rec->length + taglen) + || !WPACKET_get_total_written(&wpkt, &hdrlen) + || hdrlen != SSL3_RT_HEADER_LENGTH + || !WPACKET_finish(&wpkt)) { + WPACKET_cleanup(&wpkt); + return -1; + } + + /* + * For CCM we must explicitly set the total plaintext length before we add + * any AAD. + */ + if (((alg_enc & SSL_AESCCM) != 0 + && EVP_CipherUpdate(ctx, NULL, &lenu, NULL, + (unsigned int)rec->length) <= 0) + || EVP_CipherUpdate(ctx, NULL, &lenu, recheader, + sizeof(recheader)) <= 0 + || EVP_CipherUpdate(ctx, rec->data, &lenu, rec->input, + (unsigned int)rec->length) <= 0 + || EVP_CipherFinal_ex(ctx, rec->data + lenu, &lenf) <= 0 + || (size_t)(lenu + lenf) != rec->length) { + return -1; + } + if (sending) { + /* Add the tag */ + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, taglen, + rec->data + rec->length) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_ENC, + ERR_R_INTERNAL_ERROR); + return -1; + } + rec->length += taglen; + } + + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/s3_cbc.c b/trunk/3rdparty/openssl-1.1-fit/ssl/s3_cbc.c new file mode 100644 index 000000000..8377d7fe1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/s3_cbc.c @@ -0,0 +1,487 @@ +/* + * Copyright 2012-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/constant_time_locl.h" +#include "ssl_locl.h" +#include "internal/cryptlib.h" + +#include +#include + +/* + * MAX_HASH_BIT_COUNT_BYTES is the maximum number of bytes in the hash's + * length field. (SHA-384/512 have 128-bit length.) + */ +#define MAX_HASH_BIT_COUNT_BYTES 16 + +/* + * MAX_HASH_BLOCK_SIZE is the maximum hash block size that we'll support. + * Currently SHA-384/512 has a 128-byte block size and that's the largest + * supported by TLS.) + */ +#define MAX_HASH_BLOCK_SIZE 128 + +/* + * u32toLE serialises an unsigned, 32-bit number (n) as four bytes at (p) in + * little-endian order. The value of p is advanced by four. + */ +#define u32toLE(n, p) \ + (*((p)++)=(unsigned char)(n), \ + *((p)++)=(unsigned char)(n>>8), \ + *((p)++)=(unsigned char)(n>>16), \ + *((p)++)=(unsigned char)(n>>24)) + +/* + * These functions serialize the state of a hash and thus perform the + * standard "final" operation without adding the padding and length that such + * a function typically does. + */ +static void tls1_md5_final_raw(void *ctx, unsigned char *md_out) +{ + MD5_CTX *md5 = ctx; + u32toLE(md5->A, md_out); + u32toLE(md5->B, md_out); + u32toLE(md5->C, md_out); + u32toLE(md5->D, md_out); +} + +static void tls1_sha1_final_raw(void *ctx, unsigned char *md_out) +{ + SHA_CTX *sha1 = ctx; + l2n(sha1->h0, md_out); + l2n(sha1->h1, md_out); + l2n(sha1->h2, md_out); + l2n(sha1->h3, md_out); + l2n(sha1->h4, md_out); +} + +static void tls1_sha256_final_raw(void *ctx, unsigned char *md_out) +{ + SHA256_CTX *sha256 = ctx; + unsigned i; + + for (i = 0; i < 8; i++) { + l2n(sha256->h[i], md_out); + } +} + +static void tls1_sha512_final_raw(void *ctx, unsigned char *md_out) +{ + SHA512_CTX *sha512 = ctx; + unsigned i; + + for (i = 0; i < 8; i++) { + l2n8(sha512->h[i], md_out); + } +} + +#undef LARGEST_DIGEST_CTX +#define LARGEST_DIGEST_CTX SHA512_CTX + +/* + * ssl3_cbc_record_digest_supported returns 1 iff |ctx| uses a hash function + * which ssl3_cbc_digest_record supports. + */ +char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx) +{ + switch (EVP_MD_CTX_type(ctx)) { + case NID_md5: + case NID_sha1: + case NID_sha224: + case NID_sha256: + case NID_sha384: + case NID_sha512: + return 1; + default: + return 0; + } +} + +/*- + * ssl3_cbc_digest_record computes the MAC of a decrypted, padded SSLv3/TLS + * record. + * + * ctx: the EVP_MD_CTX from which we take the hash function. + * ssl3_cbc_record_digest_supported must return true for this EVP_MD_CTX. + * md_out: the digest output. At most EVP_MAX_MD_SIZE bytes will be written. + * md_out_size: if non-NULL, the number of output bytes is written here. + * header: the 13-byte, TLS record header. + * data: the record data itself, less any preceding explicit IV. + * data_plus_mac_size: the secret, reported length of the data and MAC + * once the padding has been removed. + * data_plus_mac_plus_padding_size: the public length of the whole + * record, including padding. + * is_sslv3: non-zero if we are to use SSLv3. Otherwise, TLS. + * + * On entry: by virtue of having been through one of the remove_padding + * functions, above, we know that data_plus_mac_size is large enough to contain + * a padding byte and MAC. (If the padding was invalid, it might contain the + * padding too. ) + * Returns 1 on success or 0 on error + */ +int ssl3_cbc_digest_record(const EVP_MD_CTX *ctx, + unsigned char *md_out, + size_t *md_out_size, + const unsigned char header[13], + const unsigned char *data, + size_t data_plus_mac_size, + size_t data_plus_mac_plus_padding_size, + const unsigned char *mac_secret, + size_t mac_secret_length, char is_sslv3) +{ + union { + double align; + unsigned char c[sizeof(LARGEST_DIGEST_CTX)]; + } md_state; + void (*md_final_raw) (void *ctx, unsigned char *md_out); + void (*md_transform) (void *ctx, const unsigned char *block); + size_t md_size, md_block_size = 64; + size_t sslv3_pad_length = 40, header_length, variance_blocks, + len, max_mac_bytes, num_blocks, + num_starting_blocks, k, mac_end_offset, c, index_a, index_b; + size_t bits; /* at most 18 bits */ + unsigned char length_bytes[MAX_HASH_BIT_COUNT_BYTES]; + /* hmac_pad is the masked HMAC key. */ + unsigned char hmac_pad[MAX_HASH_BLOCK_SIZE]; + unsigned char first_block[MAX_HASH_BLOCK_SIZE]; + unsigned char mac_out[EVP_MAX_MD_SIZE]; + size_t i, j; + unsigned md_out_size_u; + EVP_MD_CTX *md_ctx = NULL; + /* + * mdLengthSize is the number of bytes in the length field that + * terminates * the hash. + */ + size_t md_length_size = 8; + char length_is_big_endian = 1; + int ret; + + /* + * This is a, hopefully redundant, check that allows us to forget about + * many possible overflows later in this function. + */ + if (!ossl_assert(data_plus_mac_plus_padding_size < 1024 * 1024)) + return 0; + + switch (EVP_MD_CTX_type(ctx)) { + case NID_md5: + if (MD5_Init((MD5_CTX *)md_state.c) <= 0) + return 0; + md_final_raw = tls1_md5_final_raw; + md_transform = + (void (*)(void *ctx, const unsigned char *block))MD5_Transform; + md_size = 16; + sslv3_pad_length = 48; + length_is_big_endian = 0; + break; + case NID_sha1: + if (SHA1_Init((SHA_CTX *)md_state.c) <= 0) + return 0; + md_final_raw = tls1_sha1_final_raw; + md_transform = + (void (*)(void *ctx, const unsigned char *block))SHA1_Transform; + md_size = 20; + break; + case NID_sha224: + if (SHA224_Init((SHA256_CTX *)md_state.c) <= 0) + return 0; + md_final_raw = tls1_sha256_final_raw; + md_transform = + (void (*)(void *ctx, const unsigned char *block))SHA256_Transform; + md_size = 224 / 8; + break; + case NID_sha256: + if (SHA256_Init((SHA256_CTX *)md_state.c) <= 0) + return 0; + md_final_raw = tls1_sha256_final_raw; + md_transform = + (void (*)(void *ctx, const unsigned char *block))SHA256_Transform; + md_size = 32; + break; + case NID_sha384: + if (SHA384_Init((SHA512_CTX *)md_state.c) <= 0) + return 0; + md_final_raw = tls1_sha512_final_raw; + md_transform = + (void (*)(void *ctx, const unsigned char *block))SHA512_Transform; + md_size = 384 / 8; + md_block_size = 128; + md_length_size = 16; + break; + case NID_sha512: + if (SHA512_Init((SHA512_CTX *)md_state.c) <= 0) + return 0; + md_final_raw = tls1_sha512_final_raw; + md_transform = + (void (*)(void *ctx, const unsigned char *block))SHA512_Transform; + md_size = 64; + md_block_size = 128; + md_length_size = 16; + break; + default: + /* + * ssl3_cbc_record_digest_supported should have been called first to + * check that the hash function is supported. + */ + if (md_out_size != NULL) + *md_out_size = 0; + return ossl_assert(0); + } + + if (!ossl_assert(md_length_size <= MAX_HASH_BIT_COUNT_BYTES) + || !ossl_assert(md_block_size <= MAX_HASH_BLOCK_SIZE) + || !ossl_assert(md_size <= EVP_MAX_MD_SIZE)) + return 0; + + header_length = 13; + if (is_sslv3) { + header_length = mac_secret_length + sslv3_pad_length + 8 /* sequence + * number */ + + 1 /* record type */ + + 2 /* record length */ ; + } + + /* + * variance_blocks is the number of blocks of the hash that we have to + * calculate in constant time because they could be altered by the + * padding value. In SSLv3, the padding must be minimal so the end of + * the plaintext varies by, at most, 15+20 = 35 bytes. (We conservatively + * assume that the MAC size varies from 0..20 bytes.) In case the 9 bytes + * of hash termination (0x80 + 64-bit length) don't fit in the final + * block, we say that the final two blocks can vary based on the padding. + * TLSv1 has MACs up to 48 bytes long (SHA-384) and the padding is not + * required to be minimal. Therefore we say that the final |variance_blocks| + * blocks can + * vary based on the padding. Later in the function, if the message is + * short and there obviously cannot be this many blocks then + * variance_blocks can be reduced. + */ + variance_blocks = is_sslv3 ? 2 : ( ((255 + 1 + md_size + md_block_size - 1) / md_block_size) + 1); + /* + * From now on we're dealing with the MAC, which conceptually has 13 + * bytes of `header' before the start of the data (TLS) or 71/75 bytes + * (SSLv3) + */ + len = data_plus_mac_plus_padding_size + header_length; + /* + * max_mac_bytes contains the maximum bytes of bytes in the MAC, + * including * |header|, assuming that there's no padding. + */ + max_mac_bytes = len - md_size - 1; + /* num_blocks is the maximum number of hash blocks. */ + num_blocks = + (max_mac_bytes + 1 + md_length_size + md_block_size - + 1) / md_block_size; + /* + * In order to calculate the MAC in constant time we have to handle the + * final blocks specially because the padding value could cause the end + * to appear somewhere in the final |variance_blocks| blocks and we can't + * leak where. However, |num_starting_blocks| worth of data can be hashed + * right away because no padding value can affect whether they are + * plaintext. + */ + num_starting_blocks = 0; + /* + * k is the starting byte offset into the conceptual header||data where + * we start processing. + */ + k = 0; + /* + * mac_end_offset is the index just past the end of the data to be MACed. + */ + mac_end_offset = data_plus_mac_size + header_length - md_size; + /* + * c is the index of the 0x80 byte in the final hash block that contains + * application data. + */ + c = mac_end_offset % md_block_size; + /* + * index_a is the hash block number that contains the 0x80 terminating + * value. + */ + index_a = mac_end_offset / md_block_size; + /* + * index_b is the hash block number that contains the 64-bit hash length, + * in bits. + */ + index_b = (mac_end_offset + md_length_size) / md_block_size; + /* + * bits is the hash-length in bits. It includes the additional hash block + * for the masked HMAC key, or whole of |header| in the case of SSLv3. + */ + + /* + * For SSLv3, if we're going to have any starting blocks then we need at + * least two because the header is larger than a single block. + */ + if (num_blocks > variance_blocks + (is_sslv3 ? 1 : 0)) { + num_starting_blocks = num_blocks - variance_blocks; + k = md_block_size * num_starting_blocks; + } + + bits = 8 * mac_end_offset; + if (!is_sslv3) { + /* + * Compute the initial HMAC block. For SSLv3, the padding and secret + * bytes are included in |header| because they take more than a + * single block. + */ + bits += 8 * md_block_size; + memset(hmac_pad, 0, md_block_size); + if (!ossl_assert(mac_secret_length <= sizeof(hmac_pad))) + return 0; + memcpy(hmac_pad, mac_secret, mac_secret_length); + for (i = 0; i < md_block_size; i++) + hmac_pad[i] ^= 0x36; + + md_transform(md_state.c, hmac_pad); + } + + if (length_is_big_endian) { + memset(length_bytes, 0, md_length_size - 4); + length_bytes[md_length_size - 4] = (unsigned char)(bits >> 24); + length_bytes[md_length_size - 3] = (unsigned char)(bits >> 16); + length_bytes[md_length_size - 2] = (unsigned char)(bits >> 8); + length_bytes[md_length_size - 1] = (unsigned char)bits; + } else { + memset(length_bytes, 0, md_length_size); + length_bytes[md_length_size - 5] = (unsigned char)(bits >> 24); + length_bytes[md_length_size - 6] = (unsigned char)(bits >> 16); + length_bytes[md_length_size - 7] = (unsigned char)(bits >> 8); + length_bytes[md_length_size - 8] = (unsigned char)bits; + } + + if (k > 0) { + if (is_sslv3) { + size_t overhang; + + /* + * The SSLv3 header is larger than a single block. overhang is + * the number of bytes beyond a single block that the header + * consumes: either 7 bytes (SHA1) or 11 bytes (MD5). There are no + * ciphersuites in SSLv3 that are not SHA1 or MD5 based and + * therefore we can be confident that the header_length will be + * greater than |md_block_size|. However we add a sanity check just + * in case + */ + if (header_length <= md_block_size) { + /* Should never happen */ + return 0; + } + overhang = header_length - md_block_size; + md_transform(md_state.c, header); + memcpy(first_block, header + md_block_size, overhang); + memcpy(first_block + overhang, data, md_block_size - overhang); + md_transform(md_state.c, first_block); + for (i = 1; i < k / md_block_size - 1; i++) + md_transform(md_state.c, data + md_block_size * i - overhang); + } else { + /* k is a multiple of md_block_size. */ + memcpy(first_block, header, 13); + memcpy(first_block + 13, data, md_block_size - 13); + md_transform(md_state.c, first_block); + for (i = 1; i < k / md_block_size; i++) + md_transform(md_state.c, data + md_block_size * i - 13); + } + } + + memset(mac_out, 0, sizeof(mac_out)); + + /* + * We now process the final hash blocks. For each block, we construct it + * in constant time. If the |i==index_a| then we'll include the 0x80 + * bytes and zero pad etc. For each block we selectively copy it, in + * constant time, to |mac_out|. + */ + for (i = num_starting_blocks; i <= num_starting_blocks + variance_blocks; + i++) { + unsigned char block[MAX_HASH_BLOCK_SIZE]; + unsigned char is_block_a = constant_time_eq_8_s(i, index_a); + unsigned char is_block_b = constant_time_eq_8_s(i, index_b); + for (j = 0; j < md_block_size; j++) { + unsigned char b = 0, is_past_c, is_past_cp1; + if (k < header_length) + b = header[k]; + else if (k < data_plus_mac_plus_padding_size + header_length) + b = data[k - header_length]; + k++; + + is_past_c = is_block_a & constant_time_ge_8_s(j, c); + is_past_cp1 = is_block_a & constant_time_ge_8_s(j, c + 1); + /* + * If this is the block containing the end of the application + * data, and we are at the offset for the 0x80 value, then + * overwrite b with 0x80. + */ + b = constant_time_select_8(is_past_c, 0x80, b); + /* + * If this block contains the end of the application data + * and we're past the 0x80 value then just write zero. + */ + b = b & ~is_past_cp1; + /* + * If this is index_b (the final block), but not index_a (the end + * of the data), then the 64-bit length didn't fit into index_a + * and we're having to add an extra block of zeros. + */ + b &= ~is_block_b | is_block_a; + + /* + * The final bytes of one of the blocks contains the length. + */ + if (j >= md_block_size - md_length_size) { + /* If this is index_b, write a length byte. */ + b = constant_time_select_8(is_block_b, + length_bytes[j - + (md_block_size - + md_length_size)], b); + } + block[j] = b; + } + + md_transform(md_state.c, block); + md_final_raw(md_state.c, block); + /* If this is index_b, copy the hash value to |mac_out|. */ + for (j = 0; j < md_size; j++) + mac_out[j] |= block[j] & is_block_b; + } + + md_ctx = EVP_MD_CTX_new(); + if (md_ctx == NULL) + goto err; + if (EVP_DigestInit_ex(md_ctx, EVP_MD_CTX_md(ctx), NULL /* engine */ ) <= 0) + goto err; + if (is_sslv3) { + /* We repurpose |hmac_pad| to contain the SSLv3 pad2 block. */ + memset(hmac_pad, 0x5c, sslv3_pad_length); + + if (EVP_DigestUpdate(md_ctx, mac_secret, mac_secret_length) <= 0 + || EVP_DigestUpdate(md_ctx, hmac_pad, sslv3_pad_length) <= 0 + || EVP_DigestUpdate(md_ctx, mac_out, md_size) <= 0) + goto err; + } else { + /* Complete the HMAC in the standard manner. */ + for (i = 0; i < md_block_size; i++) + hmac_pad[i] ^= 0x6a; + + if (EVP_DigestUpdate(md_ctx, hmac_pad, md_block_size) <= 0 + || EVP_DigestUpdate(md_ctx, mac_out, md_size) <= 0) + goto err; + } + /* TODO(size_t): Convert me */ + ret = EVP_DigestFinal(md_ctx, md_out, &md_out_size_u); + if (ret && md_out_size) + *md_out_size = md_out_size_u; + EVP_MD_CTX_free(md_ctx); + + return 1; + err: + EVP_MD_CTX_free(md_ctx); + return 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/s3_enc.c b/trunk/3rdparty/openssl-1.1-fit/ssl/s3_enc.c new file mode 100644 index 000000000..2e185e9fb --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/s3_enc.c @@ -0,0 +1,595 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2005 Nokia. All rights reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "ssl_locl.h" +#include +#include +#include "internal/cryptlib.h" + +static int ssl3_generate_key_block(SSL *s, unsigned char *km, int num) +{ + EVP_MD_CTX *m5; + EVP_MD_CTX *s1; + unsigned char buf[16], smd[SHA_DIGEST_LENGTH]; + unsigned char c = 'A'; + unsigned int i, j, k; + int ret = 0; + +#ifdef CHARSET_EBCDIC + c = os_toascii[c]; /* 'A' in ASCII */ +#endif + k = 0; + m5 = EVP_MD_CTX_new(); + s1 = EVP_MD_CTX_new(); + if (m5 == NULL || s1 == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GENERATE_KEY_BLOCK, + ERR_R_MALLOC_FAILURE); + goto err; + } + EVP_MD_CTX_set_flags(m5, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); + for (i = 0; (int)i < num; i += MD5_DIGEST_LENGTH) { + k++; + if (k > sizeof(buf)) { + /* bug: 'buf' is too small for this ciphersuite */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GENERATE_KEY_BLOCK, + ERR_R_INTERNAL_ERROR); + goto err; + } + + for (j = 0; j < k; j++) + buf[j] = c; + c++; + if (!EVP_DigestInit_ex(s1, EVP_sha1(), NULL) + || !EVP_DigestUpdate(s1, buf, k) + || !EVP_DigestUpdate(s1, s->session->master_key, + s->session->master_key_length) + || !EVP_DigestUpdate(s1, s->s3->server_random, SSL3_RANDOM_SIZE) + || !EVP_DigestUpdate(s1, s->s3->client_random, SSL3_RANDOM_SIZE) + || !EVP_DigestFinal_ex(s1, smd, NULL) + || !EVP_DigestInit_ex(m5, EVP_md5(), NULL) + || !EVP_DigestUpdate(m5, s->session->master_key, + s->session->master_key_length) + || !EVP_DigestUpdate(m5, smd, SHA_DIGEST_LENGTH)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GENERATE_KEY_BLOCK, + ERR_R_INTERNAL_ERROR); + goto err; + } + if ((int)(i + MD5_DIGEST_LENGTH) > num) { + if (!EVP_DigestFinal_ex(m5, smd, NULL)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_SSL3_GENERATE_KEY_BLOCK, ERR_R_INTERNAL_ERROR); + goto err; + } + memcpy(km, smd, (num - i)); + } else { + if (!EVP_DigestFinal_ex(m5, km, NULL)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_SSL3_GENERATE_KEY_BLOCK, ERR_R_INTERNAL_ERROR); + goto err; + } + } + + km += MD5_DIGEST_LENGTH; + } + OPENSSL_cleanse(smd, sizeof(smd)); + ret = 1; + err: + EVP_MD_CTX_free(m5); + EVP_MD_CTX_free(s1); + return ret; +} + +int ssl3_change_cipher_state(SSL *s, int which) +{ + unsigned char *p, *mac_secret; + unsigned char *ms, *key, *iv; + EVP_CIPHER_CTX *dd; + const EVP_CIPHER *c; +#ifndef OPENSSL_NO_COMP + COMP_METHOD *comp; +#endif + const EVP_MD *m; + int mdi; + size_t n, i, j, k, cl; + int reuse_dd = 0; + + c = s->s3->tmp.new_sym_enc; + m = s->s3->tmp.new_hash; + /* m == NULL will lead to a crash later */ + if (!ossl_assert(m != NULL)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE, + ERR_R_INTERNAL_ERROR); + goto err; + } +#ifndef OPENSSL_NO_COMP + if (s->s3->tmp.new_compression == NULL) + comp = NULL; + else + comp = s->s3->tmp.new_compression->method; +#endif + + if (which & SSL3_CC_READ) { + if (s->enc_read_ctx != NULL) { + reuse_dd = 1; + } else if ((s->enc_read_ctx = EVP_CIPHER_CTX_new()) == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE, + ERR_R_MALLOC_FAILURE); + goto err; + } else { + /* + * make sure it's initialised in case we exit later with an error + */ + EVP_CIPHER_CTX_reset(s->enc_read_ctx); + } + dd = s->enc_read_ctx; + + if (ssl_replace_hash(&s->read_hash, m) == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE, + ERR_R_INTERNAL_ERROR); + goto err; + } +#ifndef OPENSSL_NO_COMP + /* COMPRESS */ + COMP_CTX_free(s->expand); + s->expand = NULL; + if (comp != NULL) { + s->expand = COMP_CTX_new(comp); + if (s->expand == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_SSL3_CHANGE_CIPHER_STATE, + SSL_R_COMPRESSION_LIBRARY_ERROR); + goto err; + } + } +#endif + RECORD_LAYER_reset_read_sequence(&s->rlayer); + mac_secret = &(s->s3->read_mac_secret[0]); + } else { + s->statem.enc_write_state = ENC_WRITE_STATE_INVALID; + if (s->enc_write_ctx != NULL) { + reuse_dd = 1; + } else if ((s->enc_write_ctx = EVP_CIPHER_CTX_new()) == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE, + ERR_R_MALLOC_FAILURE); + goto err; + } else { + /* + * make sure it's initialised in case we exit later with an error + */ + EVP_CIPHER_CTX_reset(s->enc_write_ctx); + } + dd = s->enc_write_ctx; + if (ssl_replace_hash(&s->write_hash, m) == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE, + ERR_R_MALLOC_FAILURE); + goto err; + } +#ifndef OPENSSL_NO_COMP + /* COMPRESS */ + COMP_CTX_free(s->compress); + s->compress = NULL; + if (comp != NULL) { + s->compress = COMP_CTX_new(comp); + if (s->compress == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_SSL3_CHANGE_CIPHER_STATE, + SSL_R_COMPRESSION_LIBRARY_ERROR); + goto err; + } + } +#endif + RECORD_LAYER_reset_write_sequence(&s->rlayer); + mac_secret = &(s->s3->write_mac_secret[0]); + } + + if (reuse_dd) + EVP_CIPHER_CTX_reset(dd); + + p = s->s3->tmp.key_block; + mdi = EVP_MD_size(m); + if (mdi < 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE, + ERR_R_INTERNAL_ERROR); + goto err; + } + i = mdi; + cl = EVP_CIPHER_key_length(c); + j = cl; + k = EVP_CIPHER_iv_length(c); + if ((which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) || + (which == SSL3_CHANGE_CIPHER_SERVER_READ)) { + ms = &(p[0]); + n = i + i; + key = &(p[n]); + n += j + j; + iv = &(p[n]); + n += k + k; + } else { + n = i; + ms = &(p[n]); + n += i + j; + key = &(p[n]); + n += j + k; + iv = &(p[n]); + n += k; + } + + if (n > s->s3->tmp.key_block_length) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + memcpy(mac_secret, ms, i); + + if (!EVP_CipherInit_ex(dd, c, NULL, key, iv, (which & SSL3_CC_WRITE))) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + s->statem.enc_write_state = ENC_WRITE_STATE_VALID; + return 1; + err: + return 0; +} + +int ssl3_setup_key_block(SSL *s) +{ + unsigned char *p; + const EVP_CIPHER *c; + const EVP_MD *hash; + int num; + int ret = 0; + SSL_COMP *comp; + + if (s->s3->tmp.key_block_length != 0) + return 1; + + if (!ssl_cipher_get_evp(s->session, &c, &hash, NULL, NULL, &comp, 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_SETUP_KEY_BLOCK, + SSL_R_CIPHER_OR_HASH_UNAVAILABLE); + return 0; + } + + s->s3->tmp.new_sym_enc = c; + s->s3->tmp.new_hash = hash; +#ifdef OPENSSL_NO_COMP + s->s3->tmp.new_compression = NULL; +#else + s->s3->tmp.new_compression = comp; +#endif + + num = EVP_MD_size(hash); + if (num < 0) + return 0; + + num = EVP_CIPHER_key_length(c) + num + EVP_CIPHER_iv_length(c); + num *= 2; + + ssl3_cleanup_key_block(s); + + if ((p = OPENSSL_malloc(num)) == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_SETUP_KEY_BLOCK, + ERR_R_MALLOC_FAILURE); + return 0; + } + + s->s3->tmp.key_block_length = num; + s->s3->tmp.key_block = p; + + /* Calls SSLfatal() as required */ + ret = ssl3_generate_key_block(s, p, num); + + if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)) { + /* + * enable vulnerability countermeasure for CBC ciphers with known-IV + * problem (http://www.openssl.org/~bodo/tls-cbc.txt) + */ + s->s3->need_empty_fragments = 1; + + if (s->session->cipher != NULL) { + if (s->session->cipher->algorithm_enc == SSL_eNULL) + s->s3->need_empty_fragments = 0; + +#ifndef OPENSSL_NO_RC4 + if (s->session->cipher->algorithm_enc == SSL_RC4) + s->s3->need_empty_fragments = 0; +#endif + } + } + + return ret; +} + +void ssl3_cleanup_key_block(SSL *s) +{ + OPENSSL_clear_free(s->s3->tmp.key_block, s->s3->tmp.key_block_length); + s->s3->tmp.key_block = NULL; + s->s3->tmp.key_block_length = 0; +} + +int ssl3_init_finished_mac(SSL *s) +{ + BIO *buf = BIO_new(BIO_s_mem()); + + if (buf == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_INIT_FINISHED_MAC, + ERR_R_MALLOC_FAILURE); + return 0; + } + ssl3_free_digest_list(s); + s->s3->handshake_buffer = buf; + (void)BIO_set_close(s->s3->handshake_buffer, BIO_CLOSE); + return 1; +} + +/* + * Free digest list. Also frees handshake buffer since they are always freed + * together. + */ + +void ssl3_free_digest_list(SSL *s) +{ + BIO_free(s->s3->handshake_buffer); + s->s3->handshake_buffer = NULL; + EVP_MD_CTX_free(s->s3->handshake_dgst); + s->s3->handshake_dgst = NULL; +} + +int ssl3_finish_mac(SSL *s, const unsigned char *buf, size_t len) +{ + int ret; + + if (s->s3->handshake_dgst == NULL) { + /* Note: this writes to a memory BIO so a failure is a fatal error */ + if (len > INT_MAX) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINISH_MAC, + SSL_R_OVERFLOW_ERROR); + return 0; + } + ret = BIO_write(s->s3->handshake_buffer, (void *)buf, (int)len); + if (ret <= 0 || ret != (int)len) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINISH_MAC, + ERR_R_INTERNAL_ERROR); + return 0; + } + } else { + ret = EVP_DigestUpdate(s->s3->handshake_dgst, buf, len); + if (!ret) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINISH_MAC, + ERR_R_INTERNAL_ERROR); + return 0; + } + } + return 1; +} + +int ssl3_digest_cached_records(SSL *s, int keep) +{ + const EVP_MD *md; + long hdatalen; + void *hdata; + + if (s->s3->handshake_dgst == NULL) { + hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata); + if (hdatalen <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_DIGEST_CACHED_RECORDS, + SSL_R_BAD_HANDSHAKE_LENGTH); + return 0; + } + + s->s3->handshake_dgst = EVP_MD_CTX_new(); + if (s->s3->handshake_dgst == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_DIGEST_CACHED_RECORDS, + ERR_R_MALLOC_FAILURE); + return 0; + } + + md = ssl_handshake_md(s); + if (md == NULL || !EVP_DigestInit_ex(s->s3->handshake_dgst, md, NULL) + || !EVP_DigestUpdate(s->s3->handshake_dgst, hdata, hdatalen)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_DIGEST_CACHED_RECORDS, + ERR_R_INTERNAL_ERROR); + return 0; + } + } + if (keep == 0) { + BIO_free(s->s3->handshake_buffer); + s->s3->handshake_buffer = NULL; + } + + return 1; +} + +size_t ssl3_final_finish_mac(SSL *s, const char *sender, size_t len, + unsigned char *p) +{ + int ret; + EVP_MD_CTX *ctx = NULL; + + if (!ssl3_digest_cached_records(s, 0)) { + /* SSLfatal() already called */ + return 0; + } + + if (EVP_MD_CTX_type(s->s3->handshake_dgst) != NID_md5_sha1) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC, + SSL_R_NO_REQUIRED_DIGEST); + return 0; + } + + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC, + ERR_R_MALLOC_FAILURE); + return 0; + } + if (!EVP_MD_CTX_copy_ex(ctx, s->s3->handshake_dgst)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC, + ERR_R_INTERNAL_ERROR); + ret = 0; + goto err; + } + + ret = EVP_MD_CTX_size(ctx); + if (ret < 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC, + ERR_R_INTERNAL_ERROR); + ret = 0; + goto err; + } + + if ((sender != NULL && EVP_DigestUpdate(ctx, sender, len) <= 0) + || EVP_MD_CTX_ctrl(ctx, EVP_CTRL_SSL3_MASTER_SECRET, + (int)s->session->master_key_length, + s->session->master_key) <= 0 + || EVP_DigestFinal_ex(ctx, p, NULL) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC, + ERR_R_INTERNAL_ERROR); + ret = 0; + } + + err: + EVP_MD_CTX_free(ctx); + + return ret; +} + +int ssl3_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, + size_t len, size_t *secret_size) +{ + static const unsigned char *salt[3] = { +#ifndef CHARSET_EBCDIC + (const unsigned char *)"A", + (const unsigned char *)"BB", + (const unsigned char *)"CCC", +#else + (const unsigned char *)"\x41", + (const unsigned char *)"\x42\x42", + (const unsigned char *)"\x43\x43\x43", +#endif + }; + unsigned char buf[EVP_MAX_MD_SIZE]; + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + int i, ret = 1; + unsigned int n; + size_t ret_secret_size = 0; + + if (ctx == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GENERATE_MASTER_SECRET, + ERR_R_MALLOC_FAILURE); + return 0; + } + for (i = 0; i < 3; i++) { + if (EVP_DigestInit_ex(ctx, s->ctx->sha1, NULL) <= 0 + || EVP_DigestUpdate(ctx, salt[i], + strlen((const char *)salt[i])) <= 0 + || EVP_DigestUpdate(ctx, p, len) <= 0 + || EVP_DigestUpdate(ctx, &(s->s3->client_random[0]), + SSL3_RANDOM_SIZE) <= 0 + || EVP_DigestUpdate(ctx, &(s->s3->server_random[0]), + SSL3_RANDOM_SIZE) <= 0 + /* TODO(size_t) : convert me */ + || EVP_DigestFinal_ex(ctx, buf, &n) <= 0 + || EVP_DigestInit_ex(ctx, s->ctx->md5, NULL) <= 0 + || EVP_DigestUpdate(ctx, p, len) <= 0 + || EVP_DigestUpdate(ctx, buf, n) <= 0 + || EVP_DigestFinal_ex(ctx, out, &n) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_SSL3_GENERATE_MASTER_SECRET, ERR_R_INTERNAL_ERROR); + ret = 0; + break; + } + out += n; + ret_secret_size += n; + } + EVP_MD_CTX_free(ctx); + + OPENSSL_cleanse(buf, sizeof(buf)); + if (ret) + *secret_size = ret_secret_size; + return ret; +} + +int ssl3_alert_code(int code) +{ + switch (code) { + case SSL_AD_CLOSE_NOTIFY: + return SSL3_AD_CLOSE_NOTIFY; + case SSL_AD_UNEXPECTED_MESSAGE: + return SSL3_AD_UNEXPECTED_MESSAGE; + case SSL_AD_BAD_RECORD_MAC: + return SSL3_AD_BAD_RECORD_MAC; + case SSL_AD_DECRYPTION_FAILED: + return SSL3_AD_BAD_RECORD_MAC; + case SSL_AD_RECORD_OVERFLOW: + return SSL3_AD_BAD_RECORD_MAC; + case SSL_AD_DECOMPRESSION_FAILURE: + return SSL3_AD_DECOMPRESSION_FAILURE; + case SSL_AD_HANDSHAKE_FAILURE: + return SSL3_AD_HANDSHAKE_FAILURE; + case SSL_AD_NO_CERTIFICATE: + return SSL3_AD_NO_CERTIFICATE; + case SSL_AD_BAD_CERTIFICATE: + return SSL3_AD_BAD_CERTIFICATE; + case SSL_AD_UNSUPPORTED_CERTIFICATE: + return SSL3_AD_UNSUPPORTED_CERTIFICATE; + case SSL_AD_CERTIFICATE_REVOKED: + return SSL3_AD_CERTIFICATE_REVOKED; + case SSL_AD_CERTIFICATE_EXPIRED: + return SSL3_AD_CERTIFICATE_EXPIRED; + case SSL_AD_CERTIFICATE_UNKNOWN: + return SSL3_AD_CERTIFICATE_UNKNOWN; + case SSL_AD_ILLEGAL_PARAMETER: + return SSL3_AD_ILLEGAL_PARAMETER; + case SSL_AD_UNKNOWN_CA: + return SSL3_AD_BAD_CERTIFICATE; + case SSL_AD_ACCESS_DENIED: + return SSL3_AD_HANDSHAKE_FAILURE; + case SSL_AD_DECODE_ERROR: + return SSL3_AD_HANDSHAKE_FAILURE; + case SSL_AD_DECRYPT_ERROR: + return SSL3_AD_HANDSHAKE_FAILURE; + case SSL_AD_EXPORT_RESTRICTION: + return SSL3_AD_HANDSHAKE_FAILURE; + case SSL_AD_PROTOCOL_VERSION: + return SSL3_AD_HANDSHAKE_FAILURE; + case SSL_AD_INSUFFICIENT_SECURITY: + return SSL3_AD_HANDSHAKE_FAILURE; + case SSL_AD_INTERNAL_ERROR: + return SSL3_AD_HANDSHAKE_FAILURE; + case SSL_AD_USER_CANCELLED: + return SSL3_AD_HANDSHAKE_FAILURE; + case SSL_AD_NO_RENEGOTIATION: + return -1; /* Don't send it :-) */ + case SSL_AD_UNSUPPORTED_EXTENSION: + return SSL3_AD_HANDSHAKE_FAILURE; + case SSL_AD_CERTIFICATE_UNOBTAINABLE: + return SSL3_AD_HANDSHAKE_FAILURE; + case SSL_AD_UNRECOGNIZED_NAME: + return SSL3_AD_HANDSHAKE_FAILURE; + case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE: + return SSL3_AD_HANDSHAKE_FAILURE; + case SSL_AD_BAD_CERTIFICATE_HASH_VALUE: + return SSL3_AD_HANDSHAKE_FAILURE; + case SSL_AD_UNKNOWN_PSK_IDENTITY: + return TLS1_AD_UNKNOWN_PSK_IDENTITY; + case SSL_AD_INAPPROPRIATE_FALLBACK: + return TLS1_AD_INAPPROPRIATE_FALLBACK; + case SSL_AD_NO_APPLICATION_PROTOCOL: + return TLS1_AD_NO_APPLICATION_PROTOCOL; + case SSL_AD_CERTIFICATE_REQUIRED: + return SSL_AD_HANDSHAKE_FAILURE; + default: + return -1; + } +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/s3_lib.c b/trunk/3rdparty/openssl-1.1-fit/ssl/s3_lib.c new file mode 100644 index 000000000..99ae48199 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/s3_lib.c @@ -0,0 +1,4864 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * Copyright 2005 Nokia. All rights reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/nelem.h" +#include "ssl_locl.h" +#include +#include +#include +#include "internal/cryptlib.h" + +#define TLS13_NUM_CIPHERS OSSL_NELEM(tls13_ciphers) +#define SSL3_NUM_CIPHERS OSSL_NELEM(ssl3_ciphers) +#define SSL3_NUM_SCSVS OSSL_NELEM(ssl3_scsvs) + +/* TLSv1.3 downgrade protection sentinel values */ +const unsigned char tls11downgrade[] = { + 0x44, 0x4f, 0x57, 0x4e, 0x47, 0x52, 0x44, 0x00 +}; +const unsigned char tls12downgrade[] = { + 0x44, 0x4f, 0x57, 0x4e, 0x47, 0x52, 0x44, 0x01 +}; + +/* The list of available TLSv1.3 ciphers */ +static SSL_CIPHER tls13_ciphers[] = { + { + 1, + TLS1_3_RFC_AES_128_GCM_SHA256, + TLS1_3_RFC_AES_128_GCM_SHA256, + TLS1_3_CK_AES_128_GCM_SHA256, + SSL_kANY, + SSL_aANY, + SSL_AES128GCM, + SSL_AEAD, + TLS1_3_VERSION, TLS1_3_VERSION, + 0, 0, + SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256, + 128, + 128, + }, { + 1, + TLS1_3_RFC_AES_256_GCM_SHA384, + TLS1_3_RFC_AES_256_GCM_SHA384, + TLS1_3_CK_AES_256_GCM_SHA384, + SSL_kANY, + SSL_aANY, + SSL_AES256GCM, + SSL_AEAD, + TLS1_3_VERSION, TLS1_3_VERSION, + 0, 0, + SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA384, + 256, + 256, + }, +#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305) + { + 1, + TLS1_3_RFC_CHACHA20_POLY1305_SHA256, + TLS1_3_RFC_CHACHA20_POLY1305_SHA256, + TLS1_3_CK_CHACHA20_POLY1305_SHA256, + SSL_kANY, + SSL_aANY, + SSL_CHACHA20POLY1305, + SSL_AEAD, + TLS1_3_VERSION, TLS1_3_VERSION, + 0, 0, + SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256, + 256, + 256, + }, +#endif + { + 1, + TLS1_3_RFC_AES_128_CCM_SHA256, + TLS1_3_RFC_AES_128_CCM_SHA256, + TLS1_3_CK_AES_128_CCM_SHA256, + SSL_kANY, + SSL_aANY, + SSL_AES128CCM, + SSL_AEAD, + TLS1_3_VERSION, TLS1_3_VERSION, + 0, 0, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256, + 128, + 128, + }, { + 1, + TLS1_3_RFC_AES_128_CCM_8_SHA256, + TLS1_3_RFC_AES_128_CCM_8_SHA256, + TLS1_3_CK_AES_128_CCM_8_SHA256, + SSL_kANY, + SSL_aANY, + SSL_AES128CCM8, + SSL_AEAD, + TLS1_3_VERSION, TLS1_3_VERSION, + 0, 0, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256, + 128, + 128, + } +}; + +/* + * The list of available ciphers, mostly organized into the following + * groups: + * Always there + * EC + * PSK + * SRP (within that: RSA EC PSK) + * Cipher families: Chacha/poly, Camellia, Gost, IDEA, SEED + * Weak ciphers + */ +static SSL_CIPHER ssl3_ciphers[] = { + { + 1, + SSL3_TXT_RSA_NULL_MD5, + SSL3_RFC_RSA_NULL_MD5, + SSL3_CK_RSA_NULL_MD5, + SSL_kRSA, + SSL_aRSA, + SSL_eNULL, + SSL_MD5, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_STRONG_NONE, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 0, + 0, + }, + { + 1, + SSL3_TXT_RSA_NULL_SHA, + SSL3_RFC_RSA_NULL_SHA, + SSL3_CK_RSA_NULL_SHA, + SSL_kRSA, + SSL_aRSA, + SSL_eNULL, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_STRONG_NONE | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 0, + 0, + }, +#ifndef OPENSSL_NO_WEAK_SSL_CIPHERS + { + 1, + SSL3_TXT_RSA_DES_192_CBC3_SHA, + SSL3_RFC_RSA_DES_192_CBC3_SHA, + SSL3_CK_RSA_DES_192_CBC3_SHA, + SSL_kRSA, + SSL_aRSA, + SSL_3DES, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 112, + 168, + }, + { + 1, + SSL3_TXT_DHE_DSS_DES_192_CBC3_SHA, + SSL3_RFC_DHE_DSS_DES_192_CBC3_SHA, + SSL3_CK_DHE_DSS_DES_192_CBC3_SHA, + SSL_kDHE, + SSL_aDSS, + SSL_3DES, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 112, + 168, + }, + { + 1, + SSL3_TXT_DHE_RSA_DES_192_CBC3_SHA, + SSL3_RFC_DHE_RSA_DES_192_CBC3_SHA, + SSL3_CK_DHE_RSA_DES_192_CBC3_SHA, + SSL_kDHE, + SSL_aRSA, + SSL_3DES, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 112, + 168, + }, + { + 1, + SSL3_TXT_ADH_DES_192_CBC_SHA, + SSL3_RFC_ADH_DES_192_CBC_SHA, + SSL3_CK_ADH_DES_192_CBC_SHA, + SSL_kDHE, + SSL_aNULL, + SSL_3DES, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 112, + 168, + }, +#endif + { + 1, + TLS1_TXT_RSA_WITH_AES_128_SHA, + TLS1_RFC_RSA_WITH_AES_128_SHA, + TLS1_CK_RSA_WITH_AES_128_SHA, + SSL_kRSA, + SSL_aRSA, + SSL_AES128, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_DHE_DSS_WITH_AES_128_SHA, + TLS1_RFC_DHE_DSS_WITH_AES_128_SHA, + TLS1_CK_DHE_DSS_WITH_AES_128_SHA, + SSL_kDHE, + SSL_aDSS, + SSL_AES128, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_DHE_RSA_WITH_AES_128_SHA, + TLS1_RFC_DHE_RSA_WITH_AES_128_SHA, + TLS1_CK_DHE_RSA_WITH_AES_128_SHA, + SSL_kDHE, + SSL_aRSA, + SSL_AES128, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_ADH_WITH_AES_128_SHA, + TLS1_RFC_ADH_WITH_AES_128_SHA, + TLS1_CK_ADH_WITH_AES_128_SHA, + SSL_kDHE, + SSL_aNULL, + SSL_AES128, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_RSA_WITH_AES_256_SHA, + TLS1_RFC_RSA_WITH_AES_256_SHA, + TLS1_CK_RSA_WITH_AES_256_SHA, + SSL_kRSA, + SSL_aRSA, + SSL_AES256, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 256, + 256, + }, + { + 1, + TLS1_TXT_DHE_DSS_WITH_AES_256_SHA, + TLS1_RFC_DHE_DSS_WITH_AES_256_SHA, + TLS1_CK_DHE_DSS_WITH_AES_256_SHA, + SSL_kDHE, + SSL_aDSS, + SSL_AES256, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 256, + 256, + }, + { + 1, + TLS1_TXT_DHE_RSA_WITH_AES_256_SHA, + TLS1_RFC_DHE_RSA_WITH_AES_256_SHA, + TLS1_CK_DHE_RSA_WITH_AES_256_SHA, + SSL_kDHE, + SSL_aRSA, + SSL_AES256, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 256, + 256, + }, + { + 1, + TLS1_TXT_ADH_WITH_AES_256_SHA, + TLS1_RFC_ADH_WITH_AES_256_SHA, + TLS1_CK_ADH_WITH_AES_256_SHA, + SSL_kDHE, + SSL_aNULL, + SSL_AES256, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 256, + 256, + }, + { + 1, + TLS1_TXT_RSA_WITH_NULL_SHA256, + TLS1_RFC_RSA_WITH_NULL_SHA256, + TLS1_CK_RSA_WITH_NULL_SHA256, + SSL_kRSA, + SSL_aRSA, + SSL_eNULL, + SSL_SHA256, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_STRONG_NONE | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 0, + 0, + }, + { + 1, + TLS1_TXT_RSA_WITH_AES_128_SHA256, + TLS1_RFC_RSA_WITH_AES_128_SHA256, + TLS1_CK_RSA_WITH_AES_128_SHA256, + SSL_kRSA, + SSL_aRSA, + SSL_AES128, + SSL_SHA256, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_RSA_WITH_AES_256_SHA256, + TLS1_RFC_RSA_WITH_AES_256_SHA256, + TLS1_CK_RSA_WITH_AES_256_SHA256, + SSL_kRSA, + SSL_aRSA, + SSL_AES256, + SSL_SHA256, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 256, + 256, + }, + { + 1, + TLS1_TXT_DHE_DSS_WITH_AES_128_SHA256, + TLS1_RFC_DHE_DSS_WITH_AES_128_SHA256, + TLS1_CK_DHE_DSS_WITH_AES_128_SHA256, + SSL_kDHE, + SSL_aDSS, + SSL_AES128, + SSL_SHA256, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_DHE_RSA_WITH_AES_128_SHA256, + TLS1_RFC_DHE_RSA_WITH_AES_128_SHA256, + TLS1_CK_DHE_RSA_WITH_AES_128_SHA256, + SSL_kDHE, + SSL_aRSA, + SSL_AES128, + SSL_SHA256, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_DHE_DSS_WITH_AES_256_SHA256, + TLS1_RFC_DHE_DSS_WITH_AES_256_SHA256, + TLS1_CK_DHE_DSS_WITH_AES_256_SHA256, + SSL_kDHE, + SSL_aDSS, + SSL_AES256, + SSL_SHA256, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 256, + 256, + }, + { + 1, + TLS1_TXT_DHE_RSA_WITH_AES_256_SHA256, + TLS1_RFC_DHE_RSA_WITH_AES_256_SHA256, + TLS1_CK_DHE_RSA_WITH_AES_256_SHA256, + SSL_kDHE, + SSL_aRSA, + SSL_AES256, + SSL_SHA256, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 256, + 256, + }, + { + 1, + TLS1_TXT_ADH_WITH_AES_128_SHA256, + TLS1_RFC_ADH_WITH_AES_128_SHA256, + TLS1_CK_ADH_WITH_AES_128_SHA256, + SSL_kDHE, + SSL_aNULL, + SSL_AES128, + SSL_SHA256, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_ADH_WITH_AES_256_SHA256, + TLS1_RFC_ADH_WITH_AES_256_SHA256, + TLS1_CK_ADH_WITH_AES_256_SHA256, + SSL_kDHE, + SSL_aNULL, + SSL_AES256, + SSL_SHA256, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 256, + 256, + }, + { + 1, + TLS1_TXT_RSA_WITH_AES_128_GCM_SHA256, + TLS1_RFC_RSA_WITH_AES_128_GCM_SHA256, + TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, + SSL_kRSA, + SSL_aRSA, + SSL_AES128GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_RSA_WITH_AES_256_GCM_SHA384, + TLS1_RFC_RSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_RSA_WITH_AES_256_GCM_SHA384, + SSL_kRSA, + SSL_aRSA, + SSL_AES256GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 256, + 256, + }, + { + 1, + TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256, + TLS1_RFC_DHE_RSA_WITH_AES_128_GCM_SHA256, + TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256, + SSL_kDHE, + SSL_aRSA, + SSL_AES128GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_DHE_RSA_WITH_AES_256_GCM_SHA384, + TLS1_RFC_DHE_RSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_DHE_RSA_WITH_AES_256_GCM_SHA384, + SSL_kDHE, + SSL_aRSA, + SSL_AES256GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 256, + 256, + }, + { + 1, + TLS1_TXT_DHE_DSS_WITH_AES_128_GCM_SHA256, + TLS1_RFC_DHE_DSS_WITH_AES_128_GCM_SHA256, + TLS1_CK_DHE_DSS_WITH_AES_128_GCM_SHA256, + SSL_kDHE, + SSL_aDSS, + SSL_AES128GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_DHE_DSS_WITH_AES_256_GCM_SHA384, + TLS1_RFC_DHE_DSS_WITH_AES_256_GCM_SHA384, + TLS1_CK_DHE_DSS_WITH_AES_256_GCM_SHA384, + SSL_kDHE, + SSL_aDSS, + SSL_AES256GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 256, + 256, + }, + { + 1, + TLS1_TXT_ADH_WITH_AES_128_GCM_SHA256, + TLS1_RFC_ADH_WITH_AES_128_GCM_SHA256, + TLS1_CK_ADH_WITH_AES_128_GCM_SHA256, + SSL_kDHE, + SSL_aNULL, + SSL_AES128GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_ADH_WITH_AES_256_GCM_SHA384, + TLS1_RFC_ADH_WITH_AES_256_GCM_SHA384, + TLS1_CK_ADH_WITH_AES_256_GCM_SHA384, + SSL_kDHE, + SSL_aNULL, + SSL_AES256GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 256, + 256, + }, + { + 1, + TLS1_TXT_RSA_WITH_AES_128_CCM, + TLS1_RFC_RSA_WITH_AES_128_CCM, + TLS1_CK_RSA_WITH_AES_128_CCM, + SSL_kRSA, + SSL_aRSA, + SSL_AES128CCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_RSA_WITH_AES_256_CCM, + TLS1_RFC_RSA_WITH_AES_256_CCM, + TLS1_CK_RSA_WITH_AES_256_CCM, + SSL_kRSA, + SSL_aRSA, + SSL_AES256CCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 256, + 256, + }, + { + 1, + TLS1_TXT_DHE_RSA_WITH_AES_128_CCM, + TLS1_RFC_DHE_RSA_WITH_AES_128_CCM, + TLS1_CK_DHE_RSA_WITH_AES_128_CCM, + SSL_kDHE, + SSL_aRSA, + SSL_AES128CCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_DHE_RSA_WITH_AES_256_CCM, + TLS1_RFC_DHE_RSA_WITH_AES_256_CCM, + TLS1_CK_DHE_RSA_WITH_AES_256_CCM, + SSL_kDHE, + SSL_aRSA, + SSL_AES256CCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 256, + 256, + }, + { + 1, + TLS1_TXT_RSA_WITH_AES_128_CCM_8, + TLS1_RFC_RSA_WITH_AES_128_CCM_8, + TLS1_CK_RSA_WITH_AES_128_CCM_8, + SSL_kRSA, + SSL_aRSA, + SSL_AES128CCM8, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_RSA_WITH_AES_256_CCM_8, + TLS1_RFC_RSA_WITH_AES_256_CCM_8, + TLS1_CK_RSA_WITH_AES_256_CCM_8, + SSL_kRSA, + SSL_aRSA, + SSL_AES256CCM8, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 256, + 256, + }, + { + 1, + TLS1_TXT_DHE_RSA_WITH_AES_128_CCM_8, + TLS1_RFC_DHE_RSA_WITH_AES_128_CCM_8, + TLS1_CK_DHE_RSA_WITH_AES_128_CCM_8, + SSL_kDHE, + SSL_aRSA, + SSL_AES128CCM8, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_DHE_RSA_WITH_AES_256_CCM_8, + TLS1_RFC_DHE_RSA_WITH_AES_256_CCM_8, + TLS1_CK_DHE_RSA_WITH_AES_256_CCM_8, + SSL_kDHE, + SSL_aRSA, + SSL_AES256CCM8, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 256, + 256, + }, + { + 1, + TLS1_TXT_PSK_WITH_AES_128_CCM, + TLS1_RFC_PSK_WITH_AES_128_CCM, + TLS1_CK_PSK_WITH_AES_128_CCM, + SSL_kPSK, + SSL_aPSK, + SSL_AES128CCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_PSK_WITH_AES_256_CCM, + TLS1_RFC_PSK_WITH_AES_256_CCM, + TLS1_CK_PSK_WITH_AES_256_CCM, + SSL_kPSK, + SSL_aPSK, + SSL_AES256CCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 256, + 256, + }, + { + 1, + TLS1_TXT_DHE_PSK_WITH_AES_128_CCM, + TLS1_RFC_DHE_PSK_WITH_AES_128_CCM, + TLS1_CK_DHE_PSK_WITH_AES_128_CCM, + SSL_kDHEPSK, + SSL_aPSK, + SSL_AES128CCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_DHE_PSK_WITH_AES_256_CCM, + TLS1_RFC_DHE_PSK_WITH_AES_256_CCM, + TLS1_CK_DHE_PSK_WITH_AES_256_CCM, + SSL_kDHEPSK, + SSL_aPSK, + SSL_AES256CCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 256, + 256, + }, + { + 1, + TLS1_TXT_PSK_WITH_AES_128_CCM_8, + TLS1_RFC_PSK_WITH_AES_128_CCM_8, + TLS1_CK_PSK_WITH_AES_128_CCM_8, + SSL_kPSK, + SSL_aPSK, + SSL_AES128CCM8, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_PSK_WITH_AES_256_CCM_8, + TLS1_RFC_PSK_WITH_AES_256_CCM_8, + TLS1_CK_PSK_WITH_AES_256_CCM_8, + SSL_kPSK, + SSL_aPSK, + SSL_AES256CCM8, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 256, + 256, + }, + { + 1, + TLS1_TXT_DHE_PSK_WITH_AES_128_CCM_8, + TLS1_RFC_DHE_PSK_WITH_AES_128_CCM_8, + TLS1_CK_DHE_PSK_WITH_AES_128_CCM_8, + SSL_kDHEPSK, + SSL_aPSK, + SSL_AES128CCM8, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_DHE_PSK_WITH_AES_256_CCM_8, + TLS1_RFC_DHE_PSK_WITH_AES_256_CCM_8, + TLS1_CK_DHE_PSK_WITH_AES_256_CCM_8, + SSL_kDHEPSK, + SSL_aPSK, + SSL_AES256CCM8, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 256, + 256, + }, + { + 1, + TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CCM, + TLS1_RFC_ECDHE_ECDSA_WITH_AES_128_CCM, + TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CCM, + SSL_kECDHE, + SSL_aECDSA, + SSL_AES128CCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CCM, + TLS1_RFC_ECDHE_ECDSA_WITH_AES_256_CCM, + TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CCM, + SSL_kECDHE, + SSL_aECDSA, + SSL_AES256CCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 256, + 256, + }, + { + 1, + TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CCM_8, + TLS1_RFC_ECDHE_ECDSA_WITH_AES_128_CCM_8, + TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CCM_8, + SSL_kECDHE, + SSL_aECDSA, + SSL_AES128CCM8, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CCM_8, + TLS1_RFC_ECDHE_ECDSA_WITH_AES_256_CCM_8, + TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CCM_8, + SSL_kECDHE, + SSL_aECDSA, + SSL_AES256CCM8, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 256, + 256, + }, + { + 1, + TLS1_TXT_ECDHE_ECDSA_WITH_NULL_SHA, + TLS1_RFC_ECDHE_ECDSA_WITH_NULL_SHA, + TLS1_CK_ECDHE_ECDSA_WITH_NULL_SHA, + SSL_kECDHE, + SSL_aECDSA, + SSL_eNULL, + SSL_SHA1, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_STRONG_NONE | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 0, + 0, + }, +# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS + { + 1, + TLS1_TXT_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA, + TLS1_RFC_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA, + TLS1_CK_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA, + SSL_kECDHE, + SSL_aECDSA, + SSL_3DES, + SSL_SHA1, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 112, + 168, + }, +# endif + { + 1, + TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + TLS1_RFC_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + SSL_kECDHE, + SSL_aECDSA, + SSL_AES128, + SSL_SHA1, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + TLS1_RFC_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + SSL_kECDHE, + SSL_aECDSA, + SSL_AES256, + SSL_SHA1, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 256, + 256, + }, + { + 1, + TLS1_TXT_ECDHE_RSA_WITH_NULL_SHA, + TLS1_RFC_ECDHE_RSA_WITH_NULL_SHA, + TLS1_CK_ECDHE_RSA_WITH_NULL_SHA, + SSL_kECDHE, + SSL_aRSA, + SSL_eNULL, + SSL_SHA1, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_STRONG_NONE | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 0, + 0, + }, +# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS + { + 1, + TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA, + TLS1_RFC_ECDHE_RSA_WITH_DES_192_CBC3_SHA, + TLS1_CK_ECDHE_RSA_WITH_DES_192_CBC3_SHA, + SSL_kECDHE, + SSL_aRSA, + SSL_3DES, + SSL_SHA1, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 112, + 168, + }, +# endif + { + 1, + TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA, + TLS1_RFC_ECDHE_RSA_WITH_AES_128_CBC_SHA, + TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA, + SSL_kECDHE, + SSL_aRSA, + SSL_AES128, + SSL_SHA1, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA, + TLS1_RFC_ECDHE_RSA_WITH_AES_256_CBC_SHA, + TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA, + SSL_kECDHE, + SSL_aRSA, + SSL_AES256, + SSL_SHA1, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 256, + 256, + }, + { + 1, + TLS1_TXT_ECDH_anon_WITH_NULL_SHA, + TLS1_RFC_ECDH_anon_WITH_NULL_SHA, + TLS1_CK_ECDH_anon_WITH_NULL_SHA, + SSL_kECDHE, + SSL_aNULL, + SSL_eNULL, + SSL_SHA1, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_STRONG_NONE | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 0, + 0, + }, +# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS + { + 1, + TLS1_TXT_ECDH_anon_WITH_DES_192_CBC3_SHA, + TLS1_RFC_ECDH_anon_WITH_DES_192_CBC3_SHA, + TLS1_CK_ECDH_anon_WITH_DES_192_CBC3_SHA, + SSL_kECDHE, + SSL_aNULL, + SSL_3DES, + SSL_SHA1, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 112, + 168, + }, +# endif + { + 1, + TLS1_TXT_ECDH_anon_WITH_AES_128_CBC_SHA, + TLS1_RFC_ECDH_anon_WITH_AES_128_CBC_SHA, + TLS1_CK_ECDH_anon_WITH_AES_128_CBC_SHA, + SSL_kECDHE, + SSL_aNULL, + SSL_AES128, + SSL_SHA1, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_ECDH_anon_WITH_AES_256_CBC_SHA, + TLS1_RFC_ECDH_anon_WITH_AES_256_CBC_SHA, + TLS1_CK_ECDH_anon_WITH_AES_256_CBC_SHA, + SSL_kECDHE, + SSL_aNULL, + SSL_AES256, + SSL_SHA1, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 256, + 256, + }, + { + 1, + TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_SHA256, + TLS1_RFC_ECDHE_ECDSA_WITH_AES_128_SHA256, + TLS1_CK_ECDHE_ECDSA_WITH_AES_128_SHA256, + SSL_kECDHE, + SSL_aECDSA, + SSL_AES128, + SSL_SHA256, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_SHA384, + TLS1_RFC_ECDHE_ECDSA_WITH_AES_256_SHA384, + TLS1_CK_ECDHE_ECDSA_WITH_AES_256_SHA384, + SSL_kECDHE, + SSL_aECDSA, + SSL_AES256, + SSL_SHA384, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 256, + 256, + }, + { + 1, + TLS1_TXT_ECDHE_RSA_WITH_AES_128_SHA256, + TLS1_RFC_ECDHE_RSA_WITH_AES_128_SHA256, + TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256, + SSL_kECDHE, + SSL_aRSA, + SSL_AES128, + SSL_SHA256, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_ECDHE_RSA_WITH_AES_256_SHA384, + TLS1_RFC_ECDHE_RSA_WITH_AES_256_SHA384, + TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384, + SSL_kECDHE, + SSL_aRSA, + SSL_AES256, + SSL_SHA384, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 256, + 256, + }, + { + 1, + TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + TLS1_RFC_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + SSL_kECDHE, + SSL_aECDSA, + SSL_AES128GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS1_RFC_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + SSL_kECDHE, + SSL_aECDSA, + SSL_AES256GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 256, + 256, + }, + { + 1, + TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS1_RFC_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + SSL_kECDHE, + SSL_aRSA, + SSL_AES128GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS1_RFC_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + SSL_kECDHE, + SSL_aRSA, + SSL_AES256GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 256, + 256, + }, + { + 1, + TLS1_TXT_PSK_WITH_NULL_SHA, + TLS1_RFC_PSK_WITH_NULL_SHA, + TLS1_CK_PSK_WITH_NULL_SHA, + SSL_kPSK, + SSL_aPSK, + SSL_eNULL, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_STRONG_NONE | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 0, + 0, + }, + { + 1, + TLS1_TXT_DHE_PSK_WITH_NULL_SHA, + TLS1_RFC_DHE_PSK_WITH_NULL_SHA, + TLS1_CK_DHE_PSK_WITH_NULL_SHA, + SSL_kDHEPSK, + SSL_aPSK, + SSL_eNULL, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_STRONG_NONE | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 0, + 0, + }, + { + 1, + TLS1_TXT_RSA_PSK_WITH_NULL_SHA, + TLS1_RFC_RSA_PSK_WITH_NULL_SHA, + TLS1_CK_RSA_PSK_WITH_NULL_SHA, + SSL_kRSAPSK, + SSL_aRSA, + SSL_eNULL, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_STRONG_NONE | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 0, + 0, + }, +# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS + { + 1, + TLS1_TXT_PSK_WITH_3DES_EDE_CBC_SHA, + TLS1_RFC_PSK_WITH_3DES_EDE_CBC_SHA, + TLS1_CK_PSK_WITH_3DES_EDE_CBC_SHA, + SSL_kPSK, + SSL_aPSK, + SSL_3DES, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 112, + 168, + }, +# endif + { + 1, + TLS1_TXT_PSK_WITH_AES_128_CBC_SHA, + TLS1_RFC_PSK_WITH_AES_128_CBC_SHA, + TLS1_CK_PSK_WITH_AES_128_CBC_SHA, + SSL_kPSK, + SSL_aPSK, + SSL_AES128, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_PSK_WITH_AES_256_CBC_SHA, + TLS1_RFC_PSK_WITH_AES_256_CBC_SHA, + TLS1_CK_PSK_WITH_AES_256_CBC_SHA, + SSL_kPSK, + SSL_aPSK, + SSL_AES256, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 256, + 256, + }, +# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS + { + 1, + TLS1_TXT_DHE_PSK_WITH_3DES_EDE_CBC_SHA, + TLS1_RFC_DHE_PSK_WITH_3DES_EDE_CBC_SHA, + TLS1_CK_DHE_PSK_WITH_3DES_EDE_CBC_SHA, + SSL_kDHEPSK, + SSL_aPSK, + SSL_3DES, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 112, + 168, + }, +# endif + { + 1, + TLS1_TXT_DHE_PSK_WITH_AES_128_CBC_SHA, + TLS1_RFC_DHE_PSK_WITH_AES_128_CBC_SHA, + TLS1_CK_DHE_PSK_WITH_AES_128_CBC_SHA, + SSL_kDHEPSK, + SSL_aPSK, + SSL_AES128, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_DHE_PSK_WITH_AES_256_CBC_SHA, + TLS1_RFC_DHE_PSK_WITH_AES_256_CBC_SHA, + TLS1_CK_DHE_PSK_WITH_AES_256_CBC_SHA, + SSL_kDHEPSK, + SSL_aPSK, + SSL_AES256, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 256, + 256, + }, +# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS + { + 1, + TLS1_TXT_RSA_PSK_WITH_3DES_EDE_CBC_SHA, + TLS1_RFC_RSA_PSK_WITH_3DES_EDE_CBC_SHA, + TLS1_CK_RSA_PSK_WITH_3DES_EDE_CBC_SHA, + SSL_kRSAPSK, + SSL_aRSA, + SSL_3DES, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 112, + 168, + }, +# endif + { + 1, + TLS1_TXT_RSA_PSK_WITH_AES_128_CBC_SHA, + TLS1_RFC_RSA_PSK_WITH_AES_128_CBC_SHA, + TLS1_CK_RSA_PSK_WITH_AES_128_CBC_SHA, + SSL_kRSAPSK, + SSL_aRSA, + SSL_AES128, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_RSA_PSK_WITH_AES_256_CBC_SHA, + TLS1_RFC_RSA_PSK_WITH_AES_256_CBC_SHA, + TLS1_CK_RSA_PSK_WITH_AES_256_CBC_SHA, + SSL_kRSAPSK, + SSL_aRSA, + SSL_AES256, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 256, + 256, + }, + { + 1, + TLS1_TXT_PSK_WITH_AES_128_GCM_SHA256, + TLS1_RFC_PSK_WITH_AES_128_GCM_SHA256, + TLS1_CK_PSK_WITH_AES_128_GCM_SHA256, + SSL_kPSK, + SSL_aPSK, + SSL_AES128GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_PSK_WITH_AES_256_GCM_SHA384, + TLS1_RFC_PSK_WITH_AES_256_GCM_SHA384, + TLS1_CK_PSK_WITH_AES_256_GCM_SHA384, + SSL_kPSK, + SSL_aPSK, + SSL_AES256GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 256, + 256, + }, + { + 1, + TLS1_TXT_DHE_PSK_WITH_AES_128_GCM_SHA256, + TLS1_RFC_DHE_PSK_WITH_AES_128_GCM_SHA256, + TLS1_CK_DHE_PSK_WITH_AES_128_GCM_SHA256, + SSL_kDHEPSK, + SSL_aPSK, + SSL_AES128GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_DHE_PSK_WITH_AES_256_GCM_SHA384, + TLS1_RFC_DHE_PSK_WITH_AES_256_GCM_SHA384, + TLS1_CK_DHE_PSK_WITH_AES_256_GCM_SHA384, + SSL_kDHEPSK, + SSL_aPSK, + SSL_AES256GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 256, + 256, + }, + { + 1, + TLS1_TXT_RSA_PSK_WITH_AES_128_GCM_SHA256, + TLS1_RFC_RSA_PSK_WITH_AES_128_GCM_SHA256, + TLS1_CK_RSA_PSK_WITH_AES_128_GCM_SHA256, + SSL_kRSAPSK, + SSL_aRSA, + SSL_AES128GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_RSA_PSK_WITH_AES_256_GCM_SHA384, + TLS1_RFC_RSA_PSK_WITH_AES_256_GCM_SHA384, + TLS1_CK_RSA_PSK_WITH_AES_256_GCM_SHA384, + SSL_kRSAPSK, + SSL_aRSA, + SSL_AES256GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 256, + 256, + }, + { + 1, + TLS1_TXT_PSK_WITH_AES_128_CBC_SHA256, + TLS1_RFC_PSK_WITH_AES_128_CBC_SHA256, + TLS1_CK_PSK_WITH_AES_128_CBC_SHA256, + SSL_kPSK, + SSL_aPSK, + SSL_AES128, + SSL_SHA256, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_PSK_WITH_AES_256_CBC_SHA384, + TLS1_RFC_PSK_WITH_AES_256_CBC_SHA384, + TLS1_CK_PSK_WITH_AES_256_CBC_SHA384, + SSL_kPSK, + SSL_aPSK, + SSL_AES256, + SSL_SHA384, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 256, + 256, + }, + { + 1, + TLS1_TXT_PSK_WITH_NULL_SHA256, + TLS1_RFC_PSK_WITH_NULL_SHA256, + TLS1_CK_PSK_WITH_NULL_SHA256, + SSL_kPSK, + SSL_aPSK, + SSL_eNULL, + SSL_SHA256, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_STRONG_NONE | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 0, + 0, + }, + { + 1, + TLS1_TXT_PSK_WITH_NULL_SHA384, + TLS1_RFC_PSK_WITH_NULL_SHA384, + TLS1_CK_PSK_WITH_NULL_SHA384, + SSL_kPSK, + SSL_aPSK, + SSL_eNULL, + SSL_SHA384, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_STRONG_NONE | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 0, + 0, + }, + { + 1, + TLS1_TXT_DHE_PSK_WITH_AES_128_CBC_SHA256, + TLS1_RFC_DHE_PSK_WITH_AES_128_CBC_SHA256, + TLS1_CK_DHE_PSK_WITH_AES_128_CBC_SHA256, + SSL_kDHEPSK, + SSL_aPSK, + SSL_AES128, + SSL_SHA256, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_DHE_PSK_WITH_AES_256_CBC_SHA384, + TLS1_RFC_DHE_PSK_WITH_AES_256_CBC_SHA384, + TLS1_CK_DHE_PSK_WITH_AES_256_CBC_SHA384, + SSL_kDHEPSK, + SSL_aPSK, + SSL_AES256, + SSL_SHA384, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 256, + 256, + }, + { + 1, + TLS1_TXT_DHE_PSK_WITH_NULL_SHA256, + TLS1_RFC_DHE_PSK_WITH_NULL_SHA256, + TLS1_CK_DHE_PSK_WITH_NULL_SHA256, + SSL_kDHEPSK, + SSL_aPSK, + SSL_eNULL, + SSL_SHA256, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_STRONG_NONE | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 0, + 0, + }, + { + 1, + TLS1_TXT_DHE_PSK_WITH_NULL_SHA384, + TLS1_RFC_DHE_PSK_WITH_NULL_SHA384, + TLS1_CK_DHE_PSK_WITH_NULL_SHA384, + SSL_kDHEPSK, + SSL_aPSK, + SSL_eNULL, + SSL_SHA384, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_STRONG_NONE | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 0, + 0, + }, + { + 1, + TLS1_TXT_RSA_PSK_WITH_AES_128_CBC_SHA256, + TLS1_RFC_RSA_PSK_WITH_AES_128_CBC_SHA256, + TLS1_CK_RSA_PSK_WITH_AES_128_CBC_SHA256, + SSL_kRSAPSK, + SSL_aRSA, + SSL_AES128, + SSL_SHA256, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_RSA_PSK_WITH_AES_256_CBC_SHA384, + TLS1_RFC_RSA_PSK_WITH_AES_256_CBC_SHA384, + TLS1_CK_RSA_PSK_WITH_AES_256_CBC_SHA384, + SSL_kRSAPSK, + SSL_aRSA, + SSL_AES256, + SSL_SHA384, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 256, + 256, + }, + { + 1, + TLS1_TXT_RSA_PSK_WITH_NULL_SHA256, + TLS1_RFC_RSA_PSK_WITH_NULL_SHA256, + TLS1_CK_RSA_PSK_WITH_NULL_SHA256, + SSL_kRSAPSK, + SSL_aRSA, + SSL_eNULL, + SSL_SHA256, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_STRONG_NONE | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 0, + 0, + }, + { + 1, + TLS1_TXT_RSA_PSK_WITH_NULL_SHA384, + TLS1_RFC_RSA_PSK_WITH_NULL_SHA384, + TLS1_CK_RSA_PSK_WITH_NULL_SHA384, + SSL_kRSAPSK, + SSL_aRSA, + SSL_eNULL, + SSL_SHA384, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_STRONG_NONE | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 0, + 0, + }, +# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS + { + 1, + TLS1_TXT_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, + TLS1_RFC_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, + TLS1_CK_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, + SSL_kECDHEPSK, + SSL_aPSK, + SSL_3DES, + SSL_SHA1, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 112, + 168, + }, +# endif + { + 1, + TLS1_TXT_ECDHE_PSK_WITH_AES_128_CBC_SHA, + TLS1_RFC_ECDHE_PSK_WITH_AES_128_CBC_SHA, + TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA, + SSL_kECDHEPSK, + SSL_aPSK, + SSL_AES128, + SSL_SHA1, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_ECDHE_PSK_WITH_AES_256_CBC_SHA, + TLS1_RFC_ECDHE_PSK_WITH_AES_256_CBC_SHA, + TLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA, + SSL_kECDHEPSK, + SSL_aPSK, + SSL_AES256, + SSL_SHA1, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 256, + 256, + }, + { + 1, + TLS1_TXT_ECDHE_PSK_WITH_AES_128_CBC_SHA256, + TLS1_RFC_ECDHE_PSK_WITH_AES_128_CBC_SHA256, + TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA256, + SSL_kECDHEPSK, + SSL_aPSK, + SSL_AES128, + SSL_SHA256, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_ECDHE_PSK_WITH_AES_256_CBC_SHA384, + TLS1_RFC_ECDHE_PSK_WITH_AES_256_CBC_SHA384, + TLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA384, + SSL_kECDHEPSK, + SSL_aPSK, + SSL_AES256, + SSL_SHA384, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 256, + 256, + }, + { + 1, + TLS1_TXT_ECDHE_PSK_WITH_NULL_SHA, + TLS1_RFC_ECDHE_PSK_WITH_NULL_SHA, + TLS1_CK_ECDHE_PSK_WITH_NULL_SHA, + SSL_kECDHEPSK, + SSL_aPSK, + SSL_eNULL, + SSL_SHA1, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_STRONG_NONE | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 0, + 0, + }, + { + 1, + TLS1_TXT_ECDHE_PSK_WITH_NULL_SHA256, + TLS1_RFC_ECDHE_PSK_WITH_NULL_SHA256, + TLS1_CK_ECDHE_PSK_WITH_NULL_SHA256, + SSL_kECDHEPSK, + SSL_aPSK, + SSL_eNULL, + SSL_SHA256, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_STRONG_NONE | SSL_FIPS, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 0, + 0, + }, + { + 1, + TLS1_TXT_ECDHE_PSK_WITH_NULL_SHA384, + TLS1_RFC_ECDHE_PSK_WITH_NULL_SHA384, + TLS1_CK_ECDHE_PSK_WITH_NULL_SHA384, + SSL_kECDHEPSK, + SSL_aPSK, + SSL_eNULL, + SSL_SHA384, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_STRONG_NONE | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 0, + 0, + }, + +# ifndef OPENSSL_NO_WEAK_SSL_CIPHERS + { + 1, + TLS1_TXT_SRP_SHA_WITH_3DES_EDE_CBC_SHA, + TLS1_RFC_SRP_SHA_WITH_3DES_EDE_CBC_SHA, + TLS1_CK_SRP_SHA_WITH_3DES_EDE_CBC_SHA, + SSL_kSRP, + SSL_aSRP, + SSL_3DES, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_MEDIUM, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 112, + 168, + }, + { + 1, + TLS1_TXT_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA, + TLS1_RFC_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA, + TLS1_CK_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA, + SSL_kSRP, + SSL_aRSA, + SSL_3DES, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_MEDIUM, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 112, + 168, + }, + { + 1, + TLS1_TXT_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA, + TLS1_RFC_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA, + TLS1_CK_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA, + SSL_kSRP, + SSL_aDSS, + SSL_3DES, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_MEDIUM, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 112, + 168, + }, +# endif + { + 1, + TLS1_TXT_SRP_SHA_WITH_AES_128_CBC_SHA, + TLS1_RFC_SRP_SHA_WITH_AES_128_CBC_SHA, + TLS1_CK_SRP_SHA_WITH_AES_128_CBC_SHA, + SSL_kSRP, + SSL_aSRP, + SSL_AES128, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_HIGH, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_SRP_SHA_RSA_WITH_AES_128_CBC_SHA, + TLS1_RFC_SRP_SHA_RSA_WITH_AES_128_CBC_SHA, + TLS1_CK_SRP_SHA_RSA_WITH_AES_128_CBC_SHA, + SSL_kSRP, + SSL_aRSA, + SSL_AES128, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_HIGH, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_SRP_SHA_DSS_WITH_AES_128_CBC_SHA, + TLS1_RFC_SRP_SHA_DSS_WITH_AES_128_CBC_SHA, + TLS1_CK_SRP_SHA_DSS_WITH_AES_128_CBC_SHA, + SSL_kSRP, + SSL_aDSS, + SSL_AES128, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_SRP_SHA_WITH_AES_256_CBC_SHA, + TLS1_RFC_SRP_SHA_WITH_AES_256_CBC_SHA, + TLS1_CK_SRP_SHA_WITH_AES_256_CBC_SHA, + SSL_kSRP, + SSL_aSRP, + SSL_AES256, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_HIGH, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 256, + 256, + }, + { + 1, + TLS1_TXT_SRP_SHA_RSA_WITH_AES_256_CBC_SHA, + TLS1_RFC_SRP_SHA_RSA_WITH_AES_256_CBC_SHA, + TLS1_CK_SRP_SHA_RSA_WITH_AES_256_CBC_SHA, + SSL_kSRP, + SSL_aRSA, + SSL_AES256, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_HIGH, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 256, + 256, + }, + { + 1, + TLS1_TXT_SRP_SHA_DSS_WITH_AES_256_CBC_SHA, + TLS1_RFC_SRP_SHA_DSS_WITH_AES_256_CBC_SHA, + TLS1_CK_SRP_SHA_DSS_WITH_AES_256_CBC_SHA, + SSL_kSRP, + SSL_aDSS, + SSL_AES256, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 256, + 256, + }, + +#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305) + { + 1, + TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305, + TLS1_RFC_DHE_RSA_WITH_CHACHA20_POLY1305, + TLS1_CK_DHE_RSA_WITH_CHACHA20_POLY1305, + SSL_kDHE, + SSL_aRSA, + SSL_CHACHA20POLY1305, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 256, + 256, + }, + { + 1, + TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305, + TLS1_RFC_ECDHE_RSA_WITH_CHACHA20_POLY1305, + TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305, + SSL_kECDHE, + SSL_aRSA, + SSL_CHACHA20POLY1305, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 256, + 256, + }, + { + 1, + TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, + TLS1_RFC_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, + TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, + SSL_kECDHE, + SSL_aECDSA, + SSL_CHACHA20POLY1305, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 256, + 256, + }, + { + 1, + TLS1_TXT_PSK_WITH_CHACHA20_POLY1305, + TLS1_RFC_PSK_WITH_CHACHA20_POLY1305, + TLS1_CK_PSK_WITH_CHACHA20_POLY1305, + SSL_kPSK, + SSL_aPSK, + SSL_CHACHA20POLY1305, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 256, + 256, + }, + { + 1, + TLS1_TXT_ECDHE_PSK_WITH_CHACHA20_POLY1305, + TLS1_RFC_ECDHE_PSK_WITH_CHACHA20_POLY1305, + TLS1_CK_ECDHE_PSK_WITH_CHACHA20_POLY1305, + SSL_kECDHEPSK, + SSL_aPSK, + SSL_CHACHA20POLY1305, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 256, + 256, + }, + { + 1, + TLS1_TXT_DHE_PSK_WITH_CHACHA20_POLY1305, + TLS1_RFC_DHE_PSK_WITH_CHACHA20_POLY1305, + TLS1_CK_DHE_PSK_WITH_CHACHA20_POLY1305, + SSL_kDHEPSK, + SSL_aPSK, + SSL_CHACHA20POLY1305, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 256, + 256, + }, + { + 1, + TLS1_TXT_RSA_PSK_WITH_CHACHA20_POLY1305, + TLS1_RFC_RSA_PSK_WITH_CHACHA20_POLY1305, + TLS1_CK_RSA_PSK_WITH_CHACHA20_POLY1305, + SSL_kRSAPSK, + SSL_aRSA, + SSL_CHACHA20POLY1305, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 256, + 256, + }, +#endif /* !defined(OPENSSL_NO_CHACHA) && + * !defined(OPENSSL_NO_POLY1305) */ + +#ifndef OPENSSL_NO_CAMELLIA + { + 1, + TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA256, + TLS1_RFC_RSA_WITH_CAMELLIA_128_CBC_SHA256, + TLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA256, + SSL_kRSA, + SSL_aRSA, + SSL_CAMELLIA128, + SSL_SHA256, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256, + TLS1_RFC_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256, + TLS1_CK_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256, + SSL_kEDH, + SSL_aDSS, + SSL_CAMELLIA128, + SSL_SHA256, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, + TLS1_RFC_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, + TLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, + SSL_kEDH, + SSL_aRSA, + SSL_CAMELLIA128, + SSL_SHA256, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_ADH_WITH_CAMELLIA_128_CBC_SHA256, + TLS1_RFC_ADH_WITH_CAMELLIA_128_CBC_SHA256, + TLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA256, + SSL_kEDH, + SSL_aNULL, + SSL_CAMELLIA128, + SSL_SHA256, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA256, + TLS1_RFC_RSA_WITH_CAMELLIA_256_CBC_SHA256, + TLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA256, + SSL_kRSA, + SSL_aRSA, + SSL_CAMELLIA256, + SSL_SHA256, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 256, + 256, + }, + { + 1, + TLS1_TXT_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256, + TLS1_RFC_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256, + TLS1_CK_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256, + SSL_kEDH, + SSL_aDSS, + SSL_CAMELLIA256, + SSL_SHA256, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 256, + 256, + }, + { + 1, + TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, + TLS1_RFC_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, + TLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, + SSL_kEDH, + SSL_aRSA, + SSL_CAMELLIA256, + SSL_SHA256, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 256, + 256, + }, + { + 1, + TLS1_TXT_ADH_WITH_CAMELLIA_256_CBC_SHA256, + TLS1_RFC_ADH_WITH_CAMELLIA_256_CBC_SHA256, + TLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA256, + SSL_kEDH, + SSL_aNULL, + SSL_CAMELLIA256, + SSL_SHA256, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 256, + 256, + }, + { + 1, + TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA, + TLS1_RFC_RSA_WITH_CAMELLIA_256_CBC_SHA, + TLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA, + SSL_kRSA, + SSL_aRSA, + SSL_CAMELLIA256, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 256, + 256, + }, + { + 1, + TLS1_TXT_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA, + TLS1_RFC_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA, + TLS1_CK_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA, + SSL_kDHE, + SSL_aDSS, + SSL_CAMELLIA256, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 256, + 256, + }, + { + 1, + TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, + TLS1_RFC_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, + TLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, + SSL_kDHE, + SSL_aRSA, + SSL_CAMELLIA256, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 256, + 256, + }, + { + 1, + TLS1_TXT_ADH_WITH_CAMELLIA_256_CBC_SHA, + TLS1_RFC_ADH_WITH_CAMELLIA_256_CBC_SHA, + TLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA, + SSL_kDHE, + SSL_aNULL, + SSL_CAMELLIA256, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 256, + 256, + }, + { + 1, + TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA, + TLS1_RFC_RSA_WITH_CAMELLIA_128_CBC_SHA, + TLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA, + SSL_kRSA, + SSL_aRSA, + SSL_CAMELLIA128, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA, + TLS1_RFC_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA, + TLS1_CK_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA, + SSL_kDHE, + SSL_aDSS, + SSL_CAMELLIA128, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, + TLS1_RFC_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, + TLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, + SSL_kDHE, + SSL_aRSA, + SSL_CAMELLIA128, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_ADH_WITH_CAMELLIA_128_CBC_SHA, + TLS1_RFC_ADH_WITH_CAMELLIA_128_CBC_SHA, + TLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA, + SSL_kDHE, + SSL_aNULL, + SSL_CAMELLIA128, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, + TLS1_RFC_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, + TLS1_CK_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, + SSL_kECDHE, + SSL_aECDSA, + SSL_CAMELLIA128, + SSL_SHA256, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, + TLS1_RFC_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, + TLS1_CK_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, + SSL_kECDHE, + SSL_aECDSA, + SSL_CAMELLIA256, + SSL_SHA384, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 256, + 256, + }, + { + 1, + TLS1_TXT_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, + TLS1_RFC_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, + TLS1_CK_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, + SSL_kECDHE, + SSL_aRSA, + SSL_CAMELLIA128, + SSL_SHA256, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, + TLS1_RFC_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, + TLS1_CK_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, + SSL_kECDHE, + SSL_aRSA, + SSL_CAMELLIA256, + SSL_SHA384, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 256, + 256, + }, + { + 1, + TLS1_TXT_PSK_WITH_CAMELLIA_128_CBC_SHA256, + TLS1_RFC_PSK_WITH_CAMELLIA_128_CBC_SHA256, + TLS1_CK_PSK_WITH_CAMELLIA_128_CBC_SHA256, + SSL_kPSK, + SSL_aPSK, + SSL_CAMELLIA128, + SSL_SHA256, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_PSK_WITH_CAMELLIA_256_CBC_SHA384, + TLS1_RFC_PSK_WITH_CAMELLIA_256_CBC_SHA384, + TLS1_CK_PSK_WITH_CAMELLIA_256_CBC_SHA384, + SSL_kPSK, + SSL_aPSK, + SSL_CAMELLIA256, + SSL_SHA384, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 256, + 256, + }, + { + 1, + TLS1_TXT_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, + TLS1_RFC_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, + TLS1_CK_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, + SSL_kDHEPSK, + SSL_aPSK, + SSL_CAMELLIA128, + SSL_SHA256, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, + TLS1_RFC_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, + TLS1_CK_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, + SSL_kDHEPSK, + SSL_aPSK, + SSL_CAMELLIA256, + SSL_SHA384, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 256, + 256, + }, + { + 1, + TLS1_TXT_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, + TLS1_RFC_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, + TLS1_CK_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, + SSL_kRSAPSK, + SSL_aRSA, + SSL_CAMELLIA128, + SSL_SHA256, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, + TLS1_RFC_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, + TLS1_CK_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, + SSL_kRSAPSK, + SSL_aRSA, + SSL_CAMELLIA256, + SSL_SHA384, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 256, + 256, + }, + { + 1, + TLS1_TXT_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, + TLS1_RFC_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, + TLS1_CK_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, + SSL_kECDHEPSK, + SSL_aPSK, + SSL_CAMELLIA128, + SSL_SHA256, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, + TLS1_RFC_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, + TLS1_CK_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, + SSL_kECDHEPSK, + SSL_aPSK, + SSL_CAMELLIA256, + SSL_SHA384, + TLS1_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 256, + 256, + }, +#endif /* OPENSSL_NO_CAMELLIA */ + +#ifndef OPENSSL_NO_GOST + { + 1, + "GOST2001-GOST89-GOST89", + "TLS_GOSTR341001_WITH_28147_CNT_IMIT", + 0x3000081, + SSL_kGOST, + SSL_aGOST01, + SSL_eGOST2814789CNT, + SSL_GOST89MAC, + TLS1_VERSION, TLS1_2_VERSION, + 0, 0, + SSL_HIGH, + SSL_HANDSHAKE_MAC_GOST94 | TLS1_PRF_GOST94 | TLS1_STREAM_MAC, + 256, + 256, + }, + { + 1, + "GOST2001-NULL-GOST94", + "TLS_GOSTR341001_WITH_NULL_GOSTR3411", + 0x3000083, + SSL_kGOST, + SSL_aGOST01, + SSL_eNULL, + SSL_GOST94, + TLS1_VERSION, TLS1_2_VERSION, + 0, 0, + SSL_STRONG_NONE, + SSL_HANDSHAKE_MAC_GOST94 | TLS1_PRF_GOST94, + 0, + 0, + }, + { + 1, + "GOST2012-GOST8912-GOST8912", + NULL, + 0x0300ff85, + SSL_kGOST, + SSL_aGOST12 | SSL_aGOST01, + SSL_eGOST2814789CNT12, + SSL_GOST89MAC12, + TLS1_VERSION, TLS1_2_VERSION, + 0, 0, + SSL_HIGH, + SSL_HANDSHAKE_MAC_GOST12_256 | TLS1_PRF_GOST12_256 | TLS1_STREAM_MAC, + 256, + 256, + }, + { + 1, + "GOST2012-NULL-GOST12", + NULL, + 0x0300ff87, + SSL_kGOST, + SSL_aGOST12 | SSL_aGOST01, + SSL_eNULL, + SSL_GOST12_256, + TLS1_VERSION, TLS1_2_VERSION, + 0, 0, + SSL_STRONG_NONE, + SSL_HANDSHAKE_MAC_GOST12_256 | TLS1_PRF_GOST12_256 | TLS1_STREAM_MAC, + 0, + 0, + }, +#endif /* OPENSSL_NO_GOST */ + +#ifndef OPENSSL_NO_IDEA + { + 1, + SSL3_TXT_RSA_IDEA_128_SHA, + SSL3_RFC_RSA_IDEA_128_SHA, + SSL3_CK_RSA_IDEA_128_SHA, + SSL_kRSA, + SSL_aRSA, + SSL_IDEA, + SSL_SHA1, + SSL3_VERSION, TLS1_1_VERSION, + DTLS1_BAD_VER, DTLS1_VERSION, + SSL_NOT_DEFAULT | SSL_MEDIUM, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, +#endif + +#ifndef OPENSSL_NO_SEED + { + 1, + TLS1_TXT_RSA_WITH_SEED_SHA, + TLS1_RFC_RSA_WITH_SEED_SHA, + TLS1_CK_RSA_WITH_SEED_SHA, + SSL_kRSA, + SSL_aRSA, + SSL_SEED, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_MEDIUM, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_DHE_DSS_WITH_SEED_SHA, + TLS1_RFC_DHE_DSS_WITH_SEED_SHA, + TLS1_CK_DHE_DSS_WITH_SEED_SHA, + SSL_kDHE, + SSL_aDSS, + SSL_SEED, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_MEDIUM, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_DHE_RSA_WITH_SEED_SHA, + TLS1_RFC_DHE_RSA_WITH_SEED_SHA, + TLS1_CK_DHE_RSA_WITH_SEED_SHA, + SSL_kDHE, + SSL_aRSA, + SSL_SEED, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_MEDIUM, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_ADH_WITH_SEED_SHA, + TLS1_RFC_ADH_WITH_SEED_SHA, + TLS1_CK_ADH_WITH_SEED_SHA, + SSL_kDHE, + SSL_aNULL, + SSL_SEED, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + DTLS1_BAD_VER, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_MEDIUM, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, +#endif /* OPENSSL_NO_SEED */ + +#ifndef OPENSSL_NO_WEAK_SSL_CIPHERS + { + 1, + SSL3_TXT_RSA_RC4_128_MD5, + SSL3_RFC_RSA_RC4_128_MD5, + SSL3_CK_RSA_RC4_128_MD5, + SSL_kRSA, + SSL_aRSA, + SSL_RC4, + SSL_MD5, + SSL3_VERSION, TLS1_2_VERSION, + 0, 0, + SSL_NOT_DEFAULT | SSL_MEDIUM, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + SSL3_TXT_RSA_RC4_128_SHA, + SSL3_RFC_RSA_RC4_128_SHA, + SSL3_CK_RSA_RC4_128_SHA, + SSL_kRSA, + SSL_aRSA, + SSL_RC4, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + 0, 0, + SSL_NOT_DEFAULT | SSL_MEDIUM, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + SSL3_TXT_ADH_RC4_128_MD5, + SSL3_RFC_ADH_RC4_128_MD5, + SSL3_CK_ADH_RC4_128_MD5, + SSL_kDHE, + SSL_aNULL, + SSL_RC4, + SSL_MD5, + SSL3_VERSION, TLS1_2_VERSION, + 0, 0, + SSL_NOT_DEFAULT | SSL_MEDIUM, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_ECDHE_PSK_WITH_RC4_128_SHA, + TLS1_RFC_ECDHE_PSK_WITH_RC4_128_SHA, + TLS1_CK_ECDHE_PSK_WITH_RC4_128_SHA, + SSL_kECDHEPSK, + SSL_aPSK, + SSL_RC4, + SSL_SHA1, + TLS1_VERSION, TLS1_2_VERSION, + 0, 0, + SSL_NOT_DEFAULT | SSL_MEDIUM, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_ECDH_anon_WITH_RC4_128_SHA, + TLS1_RFC_ECDH_anon_WITH_RC4_128_SHA, + TLS1_CK_ECDH_anon_WITH_RC4_128_SHA, + SSL_kECDHE, + SSL_aNULL, + SSL_RC4, + SSL_SHA1, + TLS1_VERSION, TLS1_2_VERSION, + 0, 0, + SSL_NOT_DEFAULT | SSL_MEDIUM, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA, + TLS1_RFC_ECDHE_ECDSA_WITH_RC4_128_SHA, + TLS1_CK_ECDHE_ECDSA_WITH_RC4_128_SHA, + SSL_kECDHE, + SSL_aECDSA, + SSL_RC4, + SSL_SHA1, + TLS1_VERSION, TLS1_2_VERSION, + 0, 0, + SSL_NOT_DEFAULT | SSL_MEDIUM, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA, + TLS1_RFC_ECDHE_RSA_WITH_RC4_128_SHA, + TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA, + SSL_kECDHE, + SSL_aRSA, + SSL_RC4, + SSL_SHA1, + TLS1_VERSION, TLS1_2_VERSION, + 0, 0, + SSL_NOT_DEFAULT | SSL_MEDIUM, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_PSK_WITH_RC4_128_SHA, + TLS1_RFC_PSK_WITH_RC4_128_SHA, + TLS1_CK_PSK_WITH_RC4_128_SHA, + SSL_kPSK, + SSL_aPSK, + SSL_RC4, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + 0, 0, + SSL_NOT_DEFAULT | SSL_MEDIUM, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_RSA_PSK_WITH_RC4_128_SHA, + TLS1_RFC_RSA_PSK_WITH_RC4_128_SHA, + TLS1_CK_RSA_PSK_WITH_RC4_128_SHA, + SSL_kRSAPSK, + SSL_aRSA, + SSL_RC4, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + 0, 0, + SSL_NOT_DEFAULT | SSL_MEDIUM, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, + { + 1, + TLS1_TXT_DHE_PSK_WITH_RC4_128_SHA, + TLS1_RFC_DHE_PSK_WITH_RC4_128_SHA, + TLS1_CK_DHE_PSK_WITH_RC4_128_SHA, + SSL_kDHEPSK, + SSL_aPSK, + SSL_RC4, + SSL_SHA1, + SSL3_VERSION, TLS1_2_VERSION, + 0, 0, + SSL_NOT_DEFAULT | SSL_MEDIUM, + SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, + 128, + 128, + }, +#endif /* OPENSSL_NO_WEAK_SSL_CIPHERS */ + +#ifndef OPENSSL_NO_ARIA + { + 1, + TLS1_TXT_RSA_WITH_ARIA_128_GCM_SHA256, + TLS1_RFC_RSA_WITH_ARIA_128_GCM_SHA256, + TLS1_CK_RSA_WITH_ARIA_128_GCM_SHA256, + SSL_kRSA, + SSL_aRSA, + SSL_ARIA128GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_RSA_WITH_ARIA_256_GCM_SHA384, + TLS1_RFC_RSA_WITH_ARIA_256_GCM_SHA384, + TLS1_CK_RSA_WITH_ARIA_256_GCM_SHA384, + SSL_kRSA, + SSL_aRSA, + SSL_ARIA256GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 256, + 256, + }, + { + 1, + TLS1_TXT_DHE_RSA_WITH_ARIA_128_GCM_SHA256, + TLS1_RFC_DHE_RSA_WITH_ARIA_128_GCM_SHA256, + TLS1_CK_DHE_RSA_WITH_ARIA_128_GCM_SHA256, + SSL_kDHE, + SSL_aRSA, + SSL_ARIA128GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_DHE_RSA_WITH_ARIA_256_GCM_SHA384, + TLS1_RFC_DHE_RSA_WITH_ARIA_256_GCM_SHA384, + TLS1_CK_DHE_RSA_WITH_ARIA_256_GCM_SHA384, + SSL_kDHE, + SSL_aRSA, + SSL_ARIA256GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 256, + 256, + }, + { + 1, + TLS1_TXT_DHE_DSS_WITH_ARIA_128_GCM_SHA256, + TLS1_RFC_DHE_DSS_WITH_ARIA_128_GCM_SHA256, + TLS1_CK_DHE_DSS_WITH_ARIA_128_GCM_SHA256, + SSL_kDHE, + SSL_aDSS, + SSL_ARIA128GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_DHE_DSS_WITH_ARIA_256_GCM_SHA384, + TLS1_RFC_DHE_DSS_WITH_ARIA_256_GCM_SHA384, + TLS1_CK_DHE_DSS_WITH_ARIA_256_GCM_SHA384, + SSL_kDHE, + SSL_aDSS, + SSL_ARIA256GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 256, + 256, + }, + { + 1, + TLS1_TXT_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256, + TLS1_RFC_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256, + TLS1_CK_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256, + SSL_kECDHE, + SSL_aECDSA, + SSL_ARIA128GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384, + TLS1_RFC_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384, + TLS1_CK_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384, + SSL_kECDHE, + SSL_aECDSA, + SSL_ARIA256GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 256, + 256, + }, + { + 1, + TLS1_TXT_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256, + TLS1_RFC_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256, + TLS1_CK_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256, + SSL_kECDHE, + SSL_aRSA, + SSL_ARIA128GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384, + TLS1_RFC_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384, + TLS1_CK_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384, + SSL_kECDHE, + SSL_aRSA, + SSL_ARIA256GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 256, + 256, + }, + { + 1, + TLS1_TXT_PSK_WITH_ARIA_128_GCM_SHA256, + TLS1_RFC_PSK_WITH_ARIA_128_GCM_SHA256, + TLS1_CK_PSK_WITH_ARIA_128_GCM_SHA256, + SSL_kPSK, + SSL_aPSK, + SSL_ARIA128GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_PSK_WITH_ARIA_256_GCM_SHA384, + TLS1_RFC_PSK_WITH_ARIA_256_GCM_SHA384, + TLS1_CK_PSK_WITH_ARIA_256_GCM_SHA384, + SSL_kPSK, + SSL_aPSK, + SSL_ARIA256GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 256, + 256, + }, + { + 1, + TLS1_TXT_DHE_PSK_WITH_ARIA_128_GCM_SHA256, + TLS1_RFC_DHE_PSK_WITH_ARIA_128_GCM_SHA256, + TLS1_CK_DHE_PSK_WITH_ARIA_128_GCM_SHA256, + SSL_kDHEPSK, + SSL_aPSK, + SSL_ARIA128GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_DHE_PSK_WITH_ARIA_256_GCM_SHA384, + TLS1_RFC_DHE_PSK_WITH_ARIA_256_GCM_SHA384, + TLS1_CK_DHE_PSK_WITH_ARIA_256_GCM_SHA384, + SSL_kDHEPSK, + SSL_aPSK, + SSL_ARIA256GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 256, + 256, + }, + { + 1, + TLS1_TXT_RSA_PSK_WITH_ARIA_128_GCM_SHA256, + TLS1_RFC_RSA_PSK_WITH_ARIA_128_GCM_SHA256, + TLS1_CK_RSA_PSK_WITH_ARIA_128_GCM_SHA256, + SSL_kRSAPSK, + SSL_aRSA, + SSL_ARIA128GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, + }, + { + 1, + TLS1_TXT_RSA_PSK_WITH_ARIA_256_GCM_SHA384, + TLS1_RFC_RSA_PSK_WITH_ARIA_256_GCM_SHA384, + TLS1_CK_RSA_PSK_WITH_ARIA_256_GCM_SHA384, + SSL_kRSAPSK, + SSL_aRSA, + SSL_ARIA256GCM, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, + SSL_NOT_DEFAULT | SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, + 256, + 256, + }, +#endif /* OPENSSL_NO_ARIA */ +}; + +/* + * The list of known Signalling Cipher-Suite Value "ciphers", non-valid + * values stuffed into the ciphers field of the wire protocol for signalling + * purposes. + */ +static SSL_CIPHER ssl3_scsvs[] = { + { + 0, + "TLS_EMPTY_RENEGOTIATION_INFO_SCSV", + "TLS_EMPTY_RENEGOTIATION_INFO_SCSV", + SSL3_CK_SCSV, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, + "TLS_FALLBACK_SCSV", + "TLS_FALLBACK_SCSV", + SSL3_CK_FALLBACK_SCSV, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, +}; + +static int cipher_compare(const void *a, const void *b) +{ + const SSL_CIPHER *ap = (const SSL_CIPHER *)a; + const SSL_CIPHER *bp = (const SSL_CIPHER *)b; + + if (ap->id == bp->id) + return 0; + return ap->id < bp->id ? -1 : 1; +} + +void ssl_sort_cipher_list(void) +{ + qsort(tls13_ciphers, TLS13_NUM_CIPHERS, sizeof(tls13_ciphers[0]), + cipher_compare); + qsort(ssl3_ciphers, SSL3_NUM_CIPHERS, sizeof(ssl3_ciphers[0]), + cipher_compare); + qsort(ssl3_scsvs, SSL3_NUM_SCSVS, sizeof(ssl3_scsvs[0]), cipher_compare); +} + +static int ssl_undefined_function_1(SSL *ssl, unsigned char *r, size_t s, + const char * t, size_t u, + const unsigned char * v, size_t w, int x) +{ + (void)r; + (void)s; + (void)t; + (void)u; + (void)v; + (void)w; + (void)x; + return ssl_undefined_function(ssl); +} + +const SSL3_ENC_METHOD SSLv3_enc_data = { + ssl3_enc, + n_ssl3_mac, + ssl3_setup_key_block, + ssl3_generate_master_secret, + ssl3_change_cipher_state, + ssl3_final_finish_mac, + SSL3_MD_CLIENT_FINISHED_CONST, 4, + SSL3_MD_SERVER_FINISHED_CONST, 4, + ssl3_alert_code, + ssl_undefined_function_1, + 0, + ssl3_set_handshake_header, + tls_close_construct_packet, + ssl3_handshake_write +}; + +long ssl3_default_timeout(void) +{ + /* + * 2 hours, the 24 hours mentioned in the SSLv3 spec is way too long for + * http, the cache would over fill + */ + return (60 * 60 * 2); +} + +int ssl3_num_ciphers(void) +{ + return SSL3_NUM_CIPHERS; +} + +const SSL_CIPHER *ssl3_get_cipher(unsigned int u) +{ + if (u < SSL3_NUM_CIPHERS) + return &(ssl3_ciphers[SSL3_NUM_CIPHERS - 1 - u]); + else + return NULL; +} + +int ssl3_set_handshake_header(SSL *s, WPACKET *pkt, int htype) +{ + /* No header in the event of a CCS */ + if (htype == SSL3_MT_CHANGE_CIPHER_SPEC) + return 1; + + /* Set the content type and 3 bytes for the message len */ + if (!WPACKET_put_bytes_u8(pkt, htype) + || !WPACKET_start_sub_packet_u24(pkt)) + return 0; + + return 1; +} + +int ssl3_handshake_write(SSL *s) +{ + return ssl3_do_write(s, SSL3_RT_HANDSHAKE); +} + +int ssl3_new(SSL *s) +{ + SSL3_STATE *s3; + + if ((s3 = OPENSSL_zalloc(sizeof(*s3))) == NULL) + goto err; + s->s3 = s3; + +#ifndef OPENSSL_NO_SRP + if (!SSL_SRP_CTX_init(s)) + goto err; +#endif + + if (!s->method->ssl_clear(s)) + return 0; + + return 1; + err: + return 0; +} + +void ssl3_free(SSL *s) +{ + if (s == NULL || s->s3 == NULL) + return; + + ssl3_cleanup_key_block(s); + +#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH) + EVP_PKEY_free(s->s3->peer_tmp); + s->s3->peer_tmp = NULL; + EVP_PKEY_free(s->s3->tmp.pkey); + s->s3->tmp.pkey = NULL; +#endif + + OPENSSL_free(s->s3->tmp.ctype); + sk_X509_NAME_pop_free(s->s3->tmp.peer_ca_names, X509_NAME_free); + OPENSSL_free(s->s3->tmp.ciphers_raw); + OPENSSL_clear_free(s->s3->tmp.pms, s->s3->tmp.pmslen); + OPENSSL_free(s->s3->tmp.peer_sigalgs); + OPENSSL_free(s->s3->tmp.peer_cert_sigalgs); + ssl3_free_digest_list(s); + OPENSSL_free(s->s3->alpn_selected); + OPENSSL_free(s->s3->alpn_proposed); + +#ifndef OPENSSL_NO_SRP + SSL_SRP_CTX_free(s); +#endif + OPENSSL_clear_free(s->s3, sizeof(*s->s3)); + s->s3 = NULL; +} + +int ssl3_clear(SSL *s) +{ + ssl3_cleanup_key_block(s); + OPENSSL_free(s->s3->tmp.ctype); + sk_X509_NAME_pop_free(s->s3->tmp.peer_ca_names, X509_NAME_free); + OPENSSL_free(s->s3->tmp.ciphers_raw); + OPENSSL_clear_free(s->s3->tmp.pms, s->s3->tmp.pmslen); + OPENSSL_free(s->s3->tmp.peer_sigalgs); + OPENSSL_free(s->s3->tmp.peer_cert_sigalgs); + +#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH) + EVP_PKEY_free(s->s3->tmp.pkey); + EVP_PKEY_free(s->s3->peer_tmp); +#endif /* !OPENSSL_NO_EC */ + + ssl3_free_digest_list(s); + + OPENSSL_free(s->s3->alpn_selected); + OPENSSL_free(s->s3->alpn_proposed); + + /* NULL/zero-out everything in the s3 struct */ + memset(s->s3, 0, sizeof(*s->s3)); + + if (!ssl_free_wbio_buffer(s)) + return 0; + + s->version = SSL3_VERSION; + +#if !defined(OPENSSL_NO_NEXTPROTONEG) + OPENSSL_free(s->ext.npn); + s->ext.npn = NULL; + s->ext.npn_len = 0; +#endif + + return 1; +} + +#ifndef OPENSSL_NO_SRP +static char *srp_password_from_info_cb(SSL *s, void *arg) +{ + return OPENSSL_strdup(s->srp_ctx.info); +} +#endif + +static int ssl3_set_req_cert_type(CERT *c, const unsigned char *p, size_t len); + +long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg) +{ + int ret = 0; + + switch (cmd) { + case SSL_CTRL_GET_CLIENT_CERT_REQUEST: + break; + case SSL_CTRL_GET_NUM_RENEGOTIATIONS: + ret = s->s3->num_renegotiations; + break; + case SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS: + ret = s->s3->num_renegotiations; + s->s3->num_renegotiations = 0; + break; + case SSL_CTRL_GET_TOTAL_RENEGOTIATIONS: + ret = s->s3->total_renegotiations; + break; + case SSL_CTRL_GET_FLAGS: + ret = (int)(s->s3->flags); + break; +#ifndef OPENSSL_NO_DH + case SSL_CTRL_SET_TMP_DH: + { + DH *dh = (DH *)parg; + EVP_PKEY *pkdh = NULL; + if (dh == NULL) { + SSLerr(SSL_F_SSL3_CTRL, ERR_R_PASSED_NULL_PARAMETER); + return ret; + } + pkdh = ssl_dh_to_pkey(dh); + if (pkdh == NULL) { + SSLerr(SSL_F_SSL3_CTRL, ERR_R_MALLOC_FAILURE); + return 0; + } + if (!ssl_security(s, SSL_SECOP_TMP_DH, + EVP_PKEY_security_bits(pkdh), 0, pkdh)) { + SSLerr(SSL_F_SSL3_CTRL, SSL_R_DH_KEY_TOO_SMALL); + EVP_PKEY_free(pkdh); + return ret; + } + EVP_PKEY_free(s->cert->dh_tmp); + s->cert->dh_tmp = pkdh; + ret = 1; + } + break; + case SSL_CTRL_SET_TMP_DH_CB: + { + SSLerr(SSL_F_SSL3_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return ret; + } + case SSL_CTRL_SET_DH_AUTO: + s->cert->dh_tmp_auto = larg; + return 1; +#endif +#ifndef OPENSSL_NO_EC + case SSL_CTRL_SET_TMP_ECDH: + { + const EC_GROUP *group = NULL; + int nid; + + if (parg == NULL) { + SSLerr(SSL_F_SSL3_CTRL, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + group = EC_KEY_get0_group((const EC_KEY *)parg); + if (group == NULL) { + SSLerr(SSL_F_SSL3_CTRL, EC_R_MISSING_PARAMETERS); + return 0; + } + nid = EC_GROUP_get_curve_name(group); + if (nid == NID_undef) + return 0; + return tls1_set_groups(&s->ext.supportedgroups, + &s->ext.supportedgroups_len, + &nid, 1); + } + break; +#endif /* !OPENSSL_NO_EC */ + case SSL_CTRL_SET_TLSEXT_HOSTNAME: + /* + * TODO(OpenSSL1.2) + * This API is only used for a client to set what SNI it will request + * from the server, but we currently allow it to be used on servers + * as well, which is a programming error. Currently we just clear + * the field in SSL_do_handshake() for server SSLs, but when we can + * make ABI-breaking changes, we may want to make use of this API + * an error on server SSLs. + */ + if (larg == TLSEXT_NAMETYPE_host_name) { + size_t len; + + OPENSSL_free(s->ext.hostname); + s->ext.hostname = NULL; + + ret = 1; + if (parg == NULL) + break; + len = strlen((char *)parg); + if (len == 0 || len > TLSEXT_MAXLEN_host_name) { + SSLerr(SSL_F_SSL3_CTRL, SSL_R_SSL3_EXT_INVALID_SERVERNAME); + return 0; + } + if ((s->ext.hostname = OPENSSL_strdup((char *)parg)) == NULL) { + SSLerr(SSL_F_SSL3_CTRL, ERR_R_INTERNAL_ERROR); + return 0; + } + } else { + SSLerr(SSL_F_SSL3_CTRL, SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE); + return 0; + } + break; + case SSL_CTRL_SET_TLSEXT_DEBUG_ARG: + s->ext.debug_arg = parg; + ret = 1; + break; + + case SSL_CTRL_GET_TLSEXT_STATUS_REQ_TYPE: + ret = s->ext.status_type; + break; + + case SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE: + s->ext.status_type = larg; + ret = 1; + break; + + case SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS: + *(STACK_OF(X509_EXTENSION) **)parg = s->ext.ocsp.exts; + ret = 1; + break; + + case SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS: + s->ext.ocsp.exts = parg; + ret = 1; + break; + + case SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS: + *(STACK_OF(OCSP_RESPID) **)parg = s->ext.ocsp.ids; + ret = 1; + break; + + case SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS: + s->ext.ocsp.ids = parg; + ret = 1; + break; + + case SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP: + *(unsigned char **)parg = s->ext.ocsp.resp; + if (s->ext.ocsp.resp_len == 0 + || s->ext.ocsp.resp_len > LONG_MAX) + return -1; + return (long)s->ext.ocsp.resp_len; + + case SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP: + OPENSSL_free(s->ext.ocsp.resp); + s->ext.ocsp.resp = parg; + s->ext.ocsp.resp_len = larg; + ret = 1; + break; + +#ifndef OPENSSL_NO_HEARTBEATS + case SSL_CTRL_DTLS_EXT_SEND_HEARTBEAT: + case SSL_CTRL_GET_DTLS_EXT_HEARTBEAT_PENDING: + case SSL_CTRL_SET_DTLS_EXT_HEARTBEAT_NO_REQUESTS: + break; +#endif + + case SSL_CTRL_CHAIN: + if (larg) + return ssl_cert_set1_chain(s, NULL, (STACK_OF(X509) *)parg); + else + return ssl_cert_set0_chain(s, NULL, (STACK_OF(X509) *)parg); + + case SSL_CTRL_CHAIN_CERT: + if (larg) + return ssl_cert_add1_chain_cert(s, NULL, (X509 *)parg); + else + return ssl_cert_add0_chain_cert(s, NULL, (X509 *)parg); + + case SSL_CTRL_GET_CHAIN_CERTS: + *(STACK_OF(X509) **)parg = s->cert->key->chain; + break; + + case SSL_CTRL_SELECT_CURRENT_CERT: + return ssl_cert_select_current(s->cert, (X509 *)parg); + + case SSL_CTRL_SET_CURRENT_CERT: + if (larg == SSL_CERT_SET_SERVER) { + const SSL_CIPHER *cipher; + if (!s->server) + return 0; + cipher = s->s3->tmp.new_cipher; + if (cipher == NULL) + return 0; + /* + * No certificate for unauthenticated ciphersuites or using SRP + * authentication + */ + if (cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP)) + return 2; + if (s->s3->tmp.cert == NULL) + return 0; + s->cert->key = s->s3->tmp.cert; + return 1; + } + return ssl_cert_set_current(s->cert, larg); + +#ifndef OPENSSL_NO_EC + case SSL_CTRL_GET_GROUPS: + { + uint16_t *clist; + size_t clistlen; + + if (!s->session) + return 0; + clist = s->session->ext.supportedgroups; + clistlen = s->session->ext.supportedgroups_len; + if (parg) { + size_t i; + int *cptr = parg; + + for (i = 0; i < clistlen; i++) { + const TLS_GROUP_INFO *cinf = tls1_group_id_lookup(clist[i]); + + if (cinf != NULL) + cptr[i] = cinf->nid; + else + cptr[i] = TLSEXT_nid_unknown | clist[i]; + } + } + return (int)clistlen; + } + + case SSL_CTRL_SET_GROUPS: + return tls1_set_groups(&s->ext.supportedgroups, + &s->ext.supportedgroups_len, parg, larg); + + case SSL_CTRL_SET_GROUPS_LIST: + return tls1_set_groups_list(&s->ext.supportedgroups, + &s->ext.supportedgroups_len, parg); + + case SSL_CTRL_GET_SHARED_GROUP: + { + uint16_t id = tls1_shared_group(s, larg); + + if (larg != -1) { + const TLS_GROUP_INFO *ginf = tls1_group_id_lookup(id); + + return ginf == NULL ? 0 : ginf->nid; + } + return id; + } +#endif + case SSL_CTRL_SET_SIGALGS: + return tls1_set_sigalgs(s->cert, parg, larg, 0); + + case SSL_CTRL_SET_SIGALGS_LIST: + return tls1_set_sigalgs_list(s->cert, parg, 0); + + case SSL_CTRL_SET_CLIENT_SIGALGS: + return tls1_set_sigalgs(s->cert, parg, larg, 1); + + case SSL_CTRL_SET_CLIENT_SIGALGS_LIST: + return tls1_set_sigalgs_list(s->cert, parg, 1); + + case SSL_CTRL_GET_CLIENT_CERT_TYPES: + { + const unsigned char **pctype = parg; + if (s->server || !s->s3->tmp.cert_req) + return 0; + if (pctype) + *pctype = s->s3->tmp.ctype; + return s->s3->tmp.ctype_len; + } + + case SSL_CTRL_SET_CLIENT_CERT_TYPES: + if (!s->server) + return 0; + return ssl3_set_req_cert_type(s->cert, parg, larg); + + case SSL_CTRL_BUILD_CERT_CHAIN: + return ssl_build_cert_chain(s, NULL, larg); + + case SSL_CTRL_SET_VERIFY_CERT_STORE: + return ssl_cert_set_cert_store(s->cert, parg, 0, larg); + + case SSL_CTRL_SET_CHAIN_CERT_STORE: + return ssl_cert_set_cert_store(s->cert, parg, 1, larg); + + case SSL_CTRL_GET_PEER_SIGNATURE_NID: + if (s->s3->tmp.peer_sigalg == NULL) + return 0; + *(int *)parg = s->s3->tmp.peer_sigalg->hash; + return 1; + + case SSL_CTRL_GET_SIGNATURE_NID: + if (s->s3->tmp.sigalg == NULL) + return 0; + *(int *)parg = s->s3->tmp.sigalg->hash; + return 1; + + case SSL_CTRL_GET_PEER_TMP_KEY: +#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_EC) + if (s->session == NULL || s->s3->peer_tmp == NULL) { + return 0; + } else { + EVP_PKEY_up_ref(s->s3->peer_tmp); + *(EVP_PKEY **)parg = s->s3->peer_tmp; + return 1; + } +#else + return 0; +#endif + + case SSL_CTRL_GET_TMP_KEY: +#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_EC) + if (s->session == NULL || s->s3->tmp.pkey == NULL) { + return 0; + } else { + EVP_PKEY_up_ref(s->s3->tmp.pkey); + *(EVP_PKEY **)parg = s->s3->tmp.pkey; + return 1; + } +#else + return 0; +#endif + +#ifndef OPENSSL_NO_EC + case SSL_CTRL_GET_EC_POINT_FORMATS: + { + SSL_SESSION *sess = s->session; + const unsigned char **pformat = parg; + + if (sess == NULL || sess->ext.ecpointformats == NULL) + return 0; + *pformat = sess->ext.ecpointformats; + return (int)sess->ext.ecpointformats_len; + } +#endif + + default: + break; + } + return ret; +} + +long ssl3_callback_ctrl(SSL *s, int cmd, void (*fp) (void)) +{ + int ret = 0; + + switch (cmd) { +#ifndef OPENSSL_NO_DH + case SSL_CTRL_SET_TMP_DH_CB: + { + s->cert->dh_tmp_cb = (DH *(*)(SSL *, int, int))fp; + } + break; +#endif + case SSL_CTRL_SET_TLSEXT_DEBUG_CB: + s->ext.debug_cb = (void (*)(SSL *, int, int, + const unsigned char *, int, void *))fp; + break; + + case SSL_CTRL_SET_NOT_RESUMABLE_SESS_CB: + { + s->not_resumable_session_cb = (int (*)(SSL *, int))fp; + } + break; + default: + break; + } + return ret; +} + +long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) +{ + switch (cmd) { +#ifndef OPENSSL_NO_DH + case SSL_CTRL_SET_TMP_DH: + { + DH *dh = (DH *)parg; + EVP_PKEY *pkdh = NULL; + if (dh == NULL) { + SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + pkdh = ssl_dh_to_pkey(dh); + if (pkdh == NULL) { + SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_MALLOC_FAILURE); + return 0; + } + if (!ssl_ctx_security(ctx, SSL_SECOP_TMP_DH, + EVP_PKEY_security_bits(pkdh), 0, pkdh)) { + SSLerr(SSL_F_SSL3_CTX_CTRL, SSL_R_DH_KEY_TOO_SMALL); + EVP_PKEY_free(pkdh); + return 0; + } + EVP_PKEY_free(ctx->cert->dh_tmp); + ctx->cert->dh_tmp = pkdh; + return 1; + } + case SSL_CTRL_SET_TMP_DH_CB: + { + SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + case SSL_CTRL_SET_DH_AUTO: + ctx->cert->dh_tmp_auto = larg; + return 1; +#endif +#ifndef OPENSSL_NO_EC + case SSL_CTRL_SET_TMP_ECDH: + { + const EC_GROUP *group = NULL; + int nid; + + if (parg == NULL) { + SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + group = EC_KEY_get0_group((const EC_KEY *)parg); + if (group == NULL) { + SSLerr(SSL_F_SSL3_CTX_CTRL, EC_R_MISSING_PARAMETERS); + return 0; + } + nid = EC_GROUP_get_curve_name(group); + if (nid == NID_undef) + return 0; + return tls1_set_groups(&ctx->ext.supportedgroups, + &ctx->ext.supportedgroups_len, + &nid, 1); + } +#endif /* !OPENSSL_NO_EC */ + case SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG: + ctx->ext.servername_arg = parg; + break; + case SSL_CTRL_SET_TLSEXT_TICKET_KEYS: + case SSL_CTRL_GET_TLSEXT_TICKET_KEYS: + { + unsigned char *keys = parg; + long tick_keylen = (sizeof(ctx->ext.tick_key_name) + + sizeof(ctx->ext.secure->tick_hmac_key) + + sizeof(ctx->ext.secure->tick_aes_key)); + if (keys == NULL) + return tick_keylen; + if (larg != tick_keylen) { + SSLerr(SSL_F_SSL3_CTX_CTRL, SSL_R_INVALID_TICKET_KEYS_LENGTH); + return 0; + } + if (cmd == SSL_CTRL_SET_TLSEXT_TICKET_KEYS) { + memcpy(ctx->ext.tick_key_name, keys, + sizeof(ctx->ext.tick_key_name)); + memcpy(ctx->ext.secure->tick_hmac_key, + keys + sizeof(ctx->ext.tick_key_name), + sizeof(ctx->ext.secure->tick_hmac_key)); + memcpy(ctx->ext.secure->tick_aes_key, + keys + sizeof(ctx->ext.tick_key_name) + + sizeof(ctx->ext.secure->tick_hmac_key), + sizeof(ctx->ext.secure->tick_aes_key)); + } else { + memcpy(keys, ctx->ext.tick_key_name, + sizeof(ctx->ext.tick_key_name)); + memcpy(keys + sizeof(ctx->ext.tick_key_name), + ctx->ext.secure->tick_hmac_key, + sizeof(ctx->ext.secure->tick_hmac_key)); + memcpy(keys + sizeof(ctx->ext.tick_key_name) + + sizeof(ctx->ext.secure->tick_hmac_key), + ctx->ext.secure->tick_aes_key, + sizeof(ctx->ext.secure->tick_aes_key)); + } + return 1; + } + + case SSL_CTRL_GET_TLSEXT_STATUS_REQ_TYPE: + return ctx->ext.status_type; + + case SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE: + ctx->ext.status_type = larg; + break; + + case SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG: + ctx->ext.status_arg = parg; + return 1; + + case SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG: + *(void**)parg = ctx->ext.status_arg; + break; + + case SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB: + *(int (**)(SSL*, void*))parg = ctx->ext.status_cb; + break; + +#ifndef OPENSSL_NO_SRP + case SSL_CTRL_SET_TLS_EXT_SRP_USERNAME: + ctx->srp_ctx.srp_Mask |= SSL_kSRP; + OPENSSL_free(ctx->srp_ctx.login); + ctx->srp_ctx.login = NULL; + if (parg == NULL) + break; + if (strlen((const char *)parg) > 255 || strlen((const char *)parg) < 1) { + SSLerr(SSL_F_SSL3_CTX_CTRL, SSL_R_INVALID_SRP_USERNAME); + return 0; + } + if ((ctx->srp_ctx.login = OPENSSL_strdup((char *)parg)) == NULL) { + SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_INTERNAL_ERROR); + return 0; + } + break; + case SSL_CTRL_SET_TLS_EXT_SRP_PASSWORD: + ctx->srp_ctx.SRP_give_srp_client_pwd_callback = + srp_password_from_info_cb; + if (ctx->srp_ctx.info != NULL) + OPENSSL_free(ctx->srp_ctx.info); + if ((ctx->srp_ctx.info = BUF_strdup((char *)parg)) == NULL) { + SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_INTERNAL_ERROR); + return 0; + } + break; + case SSL_CTRL_SET_SRP_ARG: + ctx->srp_ctx.srp_Mask |= SSL_kSRP; + ctx->srp_ctx.SRP_cb_arg = parg; + break; + + case SSL_CTRL_SET_TLS_EXT_SRP_STRENGTH: + ctx->srp_ctx.strength = larg; + break; +#endif + +#ifndef OPENSSL_NO_EC + case SSL_CTRL_SET_GROUPS: + return tls1_set_groups(&ctx->ext.supportedgroups, + &ctx->ext.supportedgroups_len, + parg, larg); + + case SSL_CTRL_SET_GROUPS_LIST: + return tls1_set_groups_list(&ctx->ext.supportedgroups, + &ctx->ext.supportedgroups_len, + parg); +#endif + case SSL_CTRL_SET_SIGALGS: + return tls1_set_sigalgs(ctx->cert, parg, larg, 0); + + case SSL_CTRL_SET_SIGALGS_LIST: + return tls1_set_sigalgs_list(ctx->cert, parg, 0); + + case SSL_CTRL_SET_CLIENT_SIGALGS: + return tls1_set_sigalgs(ctx->cert, parg, larg, 1); + + case SSL_CTRL_SET_CLIENT_SIGALGS_LIST: + return tls1_set_sigalgs_list(ctx->cert, parg, 1); + + case SSL_CTRL_SET_CLIENT_CERT_TYPES: + return ssl3_set_req_cert_type(ctx->cert, parg, larg); + + case SSL_CTRL_BUILD_CERT_CHAIN: + return ssl_build_cert_chain(NULL, ctx, larg); + + case SSL_CTRL_SET_VERIFY_CERT_STORE: + return ssl_cert_set_cert_store(ctx->cert, parg, 0, larg); + + case SSL_CTRL_SET_CHAIN_CERT_STORE: + return ssl_cert_set_cert_store(ctx->cert, parg, 1, larg); + + /* A Thawte special :-) */ + case SSL_CTRL_EXTRA_CHAIN_CERT: + if (ctx->extra_certs == NULL) { + if ((ctx->extra_certs = sk_X509_new_null()) == NULL) { + SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_MALLOC_FAILURE); + return 0; + } + } + if (!sk_X509_push(ctx->extra_certs, (X509 *)parg)) { + SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_MALLOC_FAILURE); + return 0; + } + break; + + case SSL_CTRL_GET_EXTRA_CHAIN_CERTS: + if (ctx->extra_certs == NULL && larg == 0) + *(STACK_OF(X509) **)parg = ctx->cert->key->chain; + else + *(STACK_OF(X509) **)parg = ctx->extra_certs; + break; + + case SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS: + sk_X509_pop_free(ctx->extra_certs, X509_free); + ctx->extra_certs = NULL; + break; + + case SSL_CTRL_CHAIN: + if (larg) + return ssl_cert_set1_chain(NULL, ctx, (STACK_OF(X509) *)parg); + else + return ssl_cert_set0_chain(NULL, ctx, (STACK_OF(X509) *)parg); + + case SSL_CTRL_CHAIN_CERT: + if (larg) + return ssl_cert_add1_chain_cert(NULL, ctx, (X509 *)parg); + else + return ssl_cert_add0_chain_cert(NULL, ctx, (X509 *)parg); + + case SSL_CTRL_GET_CHAIN_CERTS: + *(STACK_OF(X509) **)parg = ctx->cert->key->chain; + break; + + case SSL_CTRL_SELECT_CURRENT_CERT: + return ssl_cert_select_current(ctx->cert, (X509 *)parg); + + case SSL_CTRL_SET_CURRENT_CERT: + return ssl_cert_set_current(ctx->cert, larg); + + default: + return 0; + } + return 1; +} + +long ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp) (void)) +{ + switch (cmd) { +#ifndef OPENSSL_NO_DH + case SSL_CTRL_SET_TMP_DH_CB: + { + ctx->cert->dh_tmp_cb = (DH *(*)(SSL *, int, int))fp; + } + break; +#endif + case SSL_CTRL_SET_TLSEXT_SERVERNAME_CB: + ctx->ext.servername_cb = (int (*)(SSL *, int *, void *))fp; + break; + + case SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB: + ctx->ext.status_cb = (int (*)(SSL *, void *))fp; + break; + + case SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB: + ctx->ext.ticket_key_cb = (int (*)(SSL *, unsigned char *, + unsigned char *, + EVP_CIPHER_CTX *, + HMAC_CTX *, int))fp; + break; + +#ifndef OPENSSL_NO_SRP + case SSL_CTRL_SET_SRP_VERIFY_PARAM_CB: + ctx->srp_ctx.srp_Mask |= SSL_kSRP; + ctx->srp_ctx.SRP_verify_param_callback = (int (*)(SSL *, void *))fp; + break; + case SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB: + ctx->srp_ctx.srp_Mask |= SSL_kSRP; + ctx->srp_ctx.TLS_ext_srp_username_callback = + (int (*)(SSL *, int *, void *))fp; + break; + case SSL_CTRL_SET_SRP_GIVE_CLIENT_PWD_CB: + ctx->srp_ctx.srp_Mask |= SSL_kSRP; + ctx->srp_ctx.SRP_give_srp_client_pwd_callback = + (char *(*)(SSL *, void *))fp; + break; +#endif + case SSL_CTRL_SET_NOT_RESUMABLE_SESS_CB: + { + ctx->not_resumable_session_cb = (int (*)(SSL *, int))fp; + } + break; + default: + return 0; + } + return 1; +} + +const SSL_CIPHER *ssl3_get_cipher_by_id(uint32_t id) +{ + SSL_CIPHER c; + const SSL_CIPHER *cp; + + c.id = id; + cp = OBJ_bsearch_ssl_cipher_id(&c, tls13_ciphers, TLS13_NUM_CIPHERS); + if (cp != NULL) + return cp; + cp = OBJ_bsearch_ssl_cipher_id(&c, ssl3_ciphers, SSL3_NUM_CIPHERS); + if (cp != NULL) + return cp; + return OBJ_bsearch_ssl_cipher_id(&c, ssl3_scsvs, SSL3_NUM_SCSVS); +} + +const SSL_CIPHER *ssl3_get_cipher_by_std_name(const char *stdname) +{ + SSL_CIPHER *c = NULL, *tbl; + SSL_CIPHER *alltabs[] = {tls13_ciphers, ssl3_ciphers}; + size_t i, j, tblsize[] = {TLS13_NUM_CIPHERS, SSL3_NUM_CIPHERS}; + + /* this is not efficient, necessary to optimize this? */ + for (j = 0; j < OSSL_NELEM(alltabs); j++) { + for (i = 0, tbl = alltabs[j]; i < tblsize[j]; i++, tbl++) { + if (tbl->stdname == NULL) + continue; + if (strcmp(stdname, tbl->stdname) == 0) { + c = tbl; + break; + } + } + } + if (c == NULL) { + tbl = ssl3_scsvs; + for (i = 0; i < SSL3_NUM_SCSVS; i++, tbl++) { + if (strcmp(stdname, tbl->stdname) == 0) { + c = tbl; + break; + } + } + } + return c; +} + +/* + * This function needs to check if the ciphers required are actually + * available + */ +const SSL_CIPHER *ssl3_get_cipher_by_char(const unsigned char *p) +{ + return ssl3_get_cipher_by_id(SSL3_CK_CIPHERSUITE_FLAG + | ((uint32_t)p[0] << 8L) + | (uint32_t)p[1]); +} + +int ssl3_put_cipher_by_char(const SSL_CIPHER *c, WPACKET *pkt, size_t *len) +{ + if ((c->id & 0xff000000) != SSL3_CK_CIPHERSUITE_FLAG) { + *len = 0; + return 1; + } + + if (!WPACKET_put_bytes_u16(pkt, c->id & 0xffff)) + return 0; + + *len = 2; + return 1; +} + +/* + * ssl3_choose_cipher - choose a cipher from those offered by the client + * @s: SSL connection + * @clnt: ciphers offered by the client + * @srvr: ciphers enabled on the server? + * + * Returns the selected cipher or NULL when no common ciphers. + */ +const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt, + STACK_OF(SSL_CIPHER) *srvr) +{ + const SSL_CIPHER *c, *ret = NULL; + STACK_OF(SSL_CIPHER) *prio, *allow; + int i, ii, ok, prefer_sha256 = 0; + unsigned long alg_k = 0, alg_a = 0, mask_k = 0, mask_a = 0; + const EVP_MD *mdsha256 = EVP_sha256(); +#ifndef OPENSSL_NO_CHACHA + STACK_OF(SSL_CIPHER) *prio_chacha = NULL; +#endif + + /* Let's see which ciphers we can support */ + + /* + * Do not set the compare functions, because this may lead to a + * reordering by "id". We want to keep the original ordering. We may pay + * a price in performance during sk_SSL_CIPHER_find(), but would have to + * pay with the price of sk_SSL_CIPHER_dup(). + */ + +#ifdef CIPHER_DEBUG + fprintf(stderr, "Server has %d from %p:\n", sk_SSL_CIPHER_num(srvr), + (void *)srvr); + for (i = 0; i < sk_SSL_CIPHER_num(srvr); ++i) { + c = sk_SSL_CIPHER_value(srvr, i); + fprintf(stderr, "%p:%s\n", (void *)c, c->name); + } + fprintf(stderr, "Client sent %d from %p:\n", sk_SSL_CIPHER_num(clnt), + (void *)clnt); + for (i = 0; i < sk_SSL_CIPHER_num(clnt); ++i) { + c = sk_SSL_CIPHER_value(clnt, i); + fprintf(stderr, "%p:%s\n", (void *)c, c->name); + } +#endif + + /* SUITE-B takes precedence over server preference and ChaCha priortiy */ + if (tls1_suiteb(s)) { + prio = srvr; + allow = clnt; + } else if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) { + prio = srvr; + allow = clnt; +#ifndef OPENSSL_NO_CHACHA + /* If ChaCha20 is at the top of the client preference list, + and there are ChaCha20 ciphers in the server list, then + temporarily prioritize all ChaCha20 ciphers in the servers list. */ + if (s->options & SSL_OP_PRIORITIZE_CHACHA && sk_SSL_CIPHER_num(clnt) > 0) { + c = sk_SSL_CIPHER_value(clnt, 0); + if (c->algorithm_enc == SSL_CHACHA20POLY1305) { + /* ChaCha20 is client preferred, check server... */ + int num = sk_SSL_CIPHER_num(srvr); + int found = 0; + for (i = 0; i < num; i++) { + c = sk_SSL_CIPHER_value(srvr, i); + if (c->algorithm_enc == SSL_CHACHA20POLY1305) { + found = 1; + break; + } + } + if (found) { + prio_chacha = sk_SSL_CIPHER_new_reserve(NULL, num); + /* if reserve fails, then there's likely a memory issue */ + if (prio_chacha != NULL) { + /* Put all ChaCha20 at the top, starting with the one we just found */ + sk_SSL_CIPHER_push(prio_chacha, c); + for (i++; i < num; i++) { + c = sk_SSL_CIPHER_value(srvr, i); + if (c->algorithm_enc == SSL_CHACHA20POLY1305) + sk_SSL_CIPHER_push(prio_chacha, c); + } + /* Pull in the rest */ + for (i = 0; i < num; i++) { + c = sk_SSL_CIPHER_value(srvr, i); + if (c->algorithm_enc != SSL_CHACHA20POLY1305) + sk_SSL_CIPHER_push(prio_chacha, c); + } + prio = prio_chacha; + } + } + } + } +# endif + } else { + prio = clnt; + allow = srvr; + } + + if (SSL_IS_TLS13(s)) { +#ifndef OPENSSL_NO_PSK + int j; + + /* + * If we allow "old" style PSK callbacks, and we have no certificate (so + * we're not going to succeed without a PSK anyway), and we're in + * TLSv1.3 then the default hash for a PSK is SHA-256 (as per the + * TLSv1.3 spec). Therefore we should prioritise ciphersuites using + * that. + */ + if (s->psk_server_callback != NULL) { + for (j = 0; j < SSL_PKEY_NUM && !ssl_has_cert(s, j); j++); + if (j == SSL_PKEY_NUM) { + /* There are no certificates */ + prefer_sha256 = 1; + } + } +#endif + } else { + tls1_set_cert_validity(s); + ssl_set_masks(s); + } + + for (i = 0; i < sk_SSL_CIPHER_num(prio); i++) { + c = sk_SSL_CIPHER_value(prio, i); + + /* Skip ciphers not supported by the protocol version */ + if (!SSL_IS_DTLS(s) && + ((s->version < c->min_tls) || (s->version > c->max_tls))) + continue; + if (SSL_IS_DTLS(s) && + (DTLS_VERSION_LT(s->version, c->min_dtls) || + DTLS_VERSION_GT(s->version, c->max_dtls))) + continue; + + /* + * Since TLS 1.3 ciphersuites can be used with any auth or + * key exchange scheme skip tests. + */ + if (!SSL_IS_TLS13(s)) { + mask_k = s->s3->tmp.mask_k; + mask_a = s->s3->tmp.mask_a; +#ifndef OPENSSL_NO_SRP + if (s->srp_ctx.srp_Mask & SSL_kSRP) { + mask_k |= SSL_kSRP; + mask_a |= SSL_aSRP; + } +#endif + + alg_k = c->algorithm_mkey; + alg_a = c->algorithm_auth; + +#ifndef OPENSSL_NO_PSK + /* with PSK there must be server callback set */ + if ((alg_k & SSL_PSK) && s->psk_server_callback == NULL) + continue; +#endif /* OPENSSL_NO_PSK */ + + ok = (alg_k & mask_k) && (alg_a & mask_a); +#ifdef CIPHER_DEBUG + fprintf(stderr, "%d:[%08lX:%08lX:%08lX:%08lX]%p:%s\n", ok, alg_k, + alg_a, mask_k, mask_a, (void *)c, c->name); +#endif + +#ifndef OPENSSL_NO_EC + /* + * if we are considering an ECC cipher suite that uses an ephemeral + * EC key check it + */ + if (alg_k & SSL_kECDHE) + ok = ok && tls1_check_ec_tmp_key(s, c->id); +#endif /* OPENSSL_NO_EC */ + + if (!ok) + continue; + } + ii = sk_SSL_CIPHER_find(allow, c); + if (ii >= 0) { + /* Check security callback permits this cipher */ + if (!ssl_security(s, SSL_SECOP_CIPHER_SHARED, + c->strength_bits, 0, (void *)c)) + continue; +#if !defined(OPENSSL_NO_EC) + if ((alg_k & SSL_kECDHE) && (alg_a & SSL_aECDSA) + && s->s3->is_probably_safari) { + if (!ret) + ret = sk_SSL_CIPHER_value(allow, ii); + continue; + } +#endif + if (prefer_sha256) { + const SSL_CIPHER *tmp = sk_SSL_CIPHER_value(allow, ii); + + if (ssl_md(tmp->algorithm2) == mdsha256) { + ret = tmp; + break; + } + if (ret == NULL) + ret = tmp; + continue; + } + ret = sk_SSL_CIPHER_value(allow, ii); + break; + } + } +#ifndef OPENSSL_NO_CHACHA + sk_SSL_CIPHER_free(prio_chacha); +#endif + return ret; +} + +int ssl3_get_req_cert_type(SSL *s, WPACKET *pkt) +{ + uint32_t alg_k, alg_a = 0; + + /* If we have custom certificate types set, use them */ + if (s->cert->ctype) + return WPACKET_memcpy(pkt, s->cert->ctype, s->cert->ctype_len); + /* Get mask of algorithms disabled by signature list */ + ssl_set_sig_mask(&alg_a, s, SSL_SECOP_SIGALG_MASK); + + alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + +#ifndef OPENSSL_NO_GOST + if (s->version >= TLS1_VERSION && (alg_k & SSL_kGOST)) + return WPACKET_put_bytes_u8(pkt, TLS_CT_GOST01_SIGN) + && WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_SIGN) + && WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_512_SIGN); +#endif + + if ((s->version == SSL3_VERSION) && (alg_k & SSL_kDHE)) { +#ifndef OPENSSL_NO_DH +# ifndef OPENSSL_NO_RSA + if (!WPACKET_put_bytes_u8(pkt, SSL3_CT_RSA_EPHEMERAL_DH)) + return 0; +# endif +# ifndef OPENSSL_NO_DSA + if (!WPACKET_put_bytes_u8(pkt, SSL3_CT_DSS_EPHEMERAL_DH)) + return 0; +# endif +#endif /* !OPENSSL_NO_DH */ + } +#ifndef OPENSSL_NO_RSA + if (!(alg_a & SSL_aRSA) && !WPACKET_put_bytes_u8(pkt, SSL3_CT_RSA_SIGN)) + return 0; +#endif +#ifndef OPENSSL_NO_DSA + if (!(alg_a & SSL_aDSS) && !WPACKET_put_bytes_u8(pkt, SSL3_CT_DSS_SIGN)) + return 0; +#endif +#ifndef OPENSSL_NO_EC + /* + * ECDSA certs can be used with RSA cipher suites too so we don't + * need to check for SSL_kECDH or SSL_kECDHE + */ + if (s->version >= TLS1_VERSION + && !(alg_a & SSL_aECDSA) + && !WPACKET_put_bytes_u8(pkt, TLS_CT_ECDSA_SIGN)) + return 0; +#endif + return 1; +} + +static int ssl3_set_req_cert_type(CERT *c, const unsigned char *p, size_t len) +{ + OPENSSL_free(c->ctype); + c->ctype = NULL; + c->ctype_len = 0; + if (p == NULL || len == 0) + return 1; + if (len > 0xff) + return 0; + c->ctype = OPENSSL_memdup(p, len); + if (c->ctype == NULL) + return 0; + c->ctype_len = len; + return 1; +} + +int ssl3_shutdown(SSL *s) +{ + int ret; + + /* + * Don't do anything much if we have not done the handshake or we don't + * want to send messages :-) + */ + if (s->quiet_shutdown || SSL_in_before(s)) { + s->shutdown = (SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); + return 1; + } + + if (!(s->shutdown & SSL_SENT_SHUTDOWN)) { + s->shutdown |= SSL_SENT_SHUTDOWN; + ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_CLOSE_NOTIFY); + /* + * our shutdown alert has been sent now, and if it still needs to be + * written, s->s3->alert_dispatch will be true + */ + if (s->s3->alert_dispatch) + return -1; /* return WANT_WRITE */ + } else if (s->s3->alert_dispatch) { + /* resend it if not sent */ + ret = s->method->ssl_dispatch_alert(s); + if (ret == -1) { + /* + * we only get to return -1 here the 2nd/Nth invocation, we must + * have already signalled return 0 upon a previous invocation, + * return WANT_WRITE + */ + return ret; + } + } else if (!(s->shutdown & SSL_RECEIVED_SHUTDOWN)) { + size_t readbytes; + /* + * If we are waiting for a close from our peer, we are closed + */ + s->method->ssl_read_bytes(s, 0, NULL, NULL, 0, 0, &readbytes); + if (!(s->shutdown & SSL_RECEIVED_SHUTDOWN)) { + return -1; /* return WANT_READ */ + } + } + + if ((s->shutdown == (SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN)) && + !s->s3->alert_dispatch) + return 1; + else + return 0; +} + +int ssl3_write(SSL *s, const void *buf, size_t len, size_t *written) +{ + clear_sys_error(); + if (s->s3->renegotiate) + ssl3_renegotiate_check(s, 0); + + return s->method->ssl_write_bytes(s, SSL3_RT_APPLICATION_DATA, buf, len, + written); +} + +static int ssl3_read_internal(SSL *s, void *buf, size_t len, int peek, + size_t *readbytes) +{ + int ret; + + clear_sys_error(); + if (s->s3->renegotiate) + ssl3_renegotiate_check(s, 0); + s->s3->in_read_app_data = 1; + ret = + s->method->ssl_read_bytes(s, SSL3_RT_APPLICATION_DATA, NULL, buf, len, + peek, readbytes); + if ((ret == -1) && (s->s3->in_read_app_data == 2)) { + /* + * ssl3_read_bytes decided to call s->handshake_func, which called + * ssl3_read_bytes to read handshake data. However, ssl3_read_bytes + * actually found application data and thinks that application data + * makes sense here; so disable handshake processing and try to read + * application data again. + */ + ossl_statem_set_in_handshake(s, 1); + ret = + s->method->ssl_read_bytes(s, SSL3_RT_APPLICATION_DATA, NULL, buf, + len, peek, readbytes); + ossl_statem_set_in_handshake(s, 0); + } else + s->s3->in_read_app_data = 0; + + return ret; +} + +int ssl3_read(SSL *s, void *buf, size_t len, size_t *readbytes) +{ + return ssl3_read_internal(s, buf, len, 0, readbytes); +} + +int ssl3_peek(SSL *s, void *buf, size_t len, size_t *readbytes) +{ + return ssl3_read_internal(s, buf, len, 1, readbytes); +} + +int ssl3_renegotiate(SSL *s) +{ + if (s->handshake_func == NULL) + return 1; + + s->s3->renegotiate = 1; + return 1; +} + +/* + * Check if we are waiting to do a renegotiation and if so whether now is a + * good time to do it. If |initok| is true then we are being called from inside + * the state machine so ignore the result of SSL_in_init(s). Otherwise we + * should not do a renegotiation if SSL_in_init(s) is true. Returns 1 if we + * should do a renegotiation now and sets up the state machine for it. Otherwise + * returns 0. + */ +int ssl3_renegotiate_check(SSL *s, int initok) +{ + int ret = 0; + + if (s->s3->renegotiate) { + if (!RECORD_LAYER_read_pending(&s->rlayer) + && !RECORD_LAYER_write_pending(&s->rlayer) + && (initok || !SSL_in_init(s))) { + /* + * if we are the server, and we have sent a 'RENEGOTIATE' + * message, we need to set the state machine into the renegotiate + * state. + */ + ossl_statem_set_renegotiate(s); + s->s3->renegotiate = 0; + s->s3->num_renegotiations++; + s->s3->total_renegotiations++; + ret = 1; + } + } + return ret; +} + +/* + * If we are using default SHA1+MD5 algorithms switch to new SHA256 PRF and + * handshake macs if required. + * + * If PSK and using SHA384 for TLS < 1.2 switch to default. + */ +long ssl_get_algorithm2(SSL *s) +{ + long alg2; + if (s->s3 == NULL || s->s3->tmp.new_cipher == NULL) + return -1; + alg2 = s->s3->tmp.new_cipher->algorithm2; + if (s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_SHA256_PRF) { + if (alg2 == (SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF)) + return SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256; + } else if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK) { + if (alg2 == (SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384)) + return SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF; + } + return alg2; +} + +/* + * Fill a ClientRandom or ServerRandom field of length len. Returns <= 0 on + * failure, 1 on success. + */ +int ssl_fill_hello_random(SSL *s, int server, unsigned char *result, size_t len, + DOWNGRADE dgrd) +{ + int send_time = 0, ret; + + if (len < 4) + return 0; + if (server) + send_time = (s->mode & SSL_MODE_SEND_SERVERHELLO_TIME) != 0; + else + send_time = (s->mode & SSL_MODE_SEND_CLIENTHELLO_TIME) != 0; + if (send_time) { + unsigned long Time = (unsigned long)time(NULL); + unsigned char *p = result; + + l2n(Time, p); + ret = RAND_bytes(p, len - 4); + } else { + ret = RAND_bytes(result, len); + } + + if (ret > 0) { + if (!ossl_assert(sizeof(tls11downgrade) < len) + || !ossl_assert(sizeof(tls12downgrade) < len)) + return 0; + if (dgrd == DOWNGRADE_TO_1_2) + memcpy(result + len - sizeof(tls12downgrade), tls12downgrade, + sizeof(tls12downgrade)); + else if (dgrd == DOWNGRADE_TO_1_1) + memcpy(result + len - sizeof(tls11downgrade), tls11downgrade, + sizeof(tls11downgrade)); + } + + return ret; +} + +int ssl_generate_master_secret(SSL *s, unsigned char *pms, size_t pmslen, + int free_pms) +{ + unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + int ret = 0; + + if (alg_k & SSL_PSK) { +#ifndef OPENSSL_NO_PSK + unsigned char *pskpms, *t; + size_t psklen = s->s3->tmp.psklen; + size_t pskpmslen; + + /* create PSK premaster_secret */ + + /* For plain PSK "other_secret" is psklen zeroes */ + if (alg_k & SSL_kPSK) + pmslen = psklen; + + pskpmslen = 4 + pmslen + psklen; + pskpms = OPENSSL_malloc(pskpmslen); + if (pskpms == NULL) + goto err; + t = pskpms; + s2n(pmslen, t); + if (alg_k & SSL_kPSK) + memset(t, 0, pmslen); + else + memcpy(t, pms, pmslen); + t += pmslen; + s2n(psklen, t); + memcpy(t, s->s3->tmp.psk, psklen); + + OPENSSL_clear_free(s->s3->tmp.psk, psklen); + s->s3->tmp.psk = NULL; + if (!s->method->ssl3_enc->generate_master_secret(s, + s->session->master_key,pskpms, pskpmslen, + &s->session->master_key_length)) { + OPENSSL_clear_free(pskpms, pskpmslen); + /* SSLfatal() already called */ + goto err; + } + OPENSSL_clear_free(pskpms, pskpmslen); +#else + /* Should never happen */ + goto err; +#endif + } else { + if (!s->method->ssl3_enc->generate_master_secret(s, + s->session->master_key, pms, pmslen, + &s->session->master_key_length)) { + /* SSLfatal() already called */ + goto err; + } + } + + ret = 1; + err: + if (pms) { + if (free_pms) + OPENSSL_clear_free(pms, pmslen); + else + OPENSSL_cleanse(pms, pmslen); + } + if (s->server == 0) + s->s3->tmp.pms = NULL; + return ret; +} + +/* Generate a private key from parameters */ +EVP_PKEY *ssl_generate_pkey(EVP_PKEY *pm) +{ + EVP_PKEY_CTX *pctx = NULL; + EVP_PKEY *pkey = NULL; + + if (pm == NULL) + return NULL; + pctx = EVP_PKEY_CTX_new(pm, NULL); + if (pctx == NULL) + goto err; + if (EVP_PKEY_keygen_init(pctx) <= 0) + goto err; + if (EVP_PKEY_keygen(pctx, &pkey) <= 0) { + EVP_PKEY_free(pkey); + pkey = NULL; + } + + err: + EVP_PKEY_CTX_free(pctx); + return pkey; +} +#ifndef OPENSSL_NO_EC +/* Generate a private key from a group ID */ +EVP_PKEY *ssl_generate_pkey_group(SSL *s, uint16_t id) +{ + EVP_PKEY_CTX *pctx = NULL; + EVP_PKEY *pkey = NULL; + const TLS_GROUP_INFO *ginf = tls1_group_id_lookup(id); + uint16_t gtype; + + if (ginf == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_PKEY_GROUP, + ERR_R_INTERNAL_ERROR); + goto err; + } + gtype = ginf->flags & TLS_CURVE_TYPE; + if (gtype == TLS_CURVE_CUSTOM) + pctx = EVP_PKEY_CTX_new_id(ginf->nid, NULL); + else + pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); + if (pctx == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_PKEY_GROUP, + ERR_R_MALLOC_FAILURE); + goto err; + } + if (EVP_PKEY_keygen_init(pctx) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_PKEY_GROUP, + ERR_R_EVP_LIB); + goto err; + } + if (gtype != TLS_CURVE_CUSTOM + && EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, ginf->nid) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_PKEY_GROUP, + ERR_R_EVP_LIB); + goto err; + } + if (EVP_PKEY_keygen(pctx, &pkey) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_PKEY_GROUP, + ERR_R_EVP_LIB); + EVP_PKEY_free(pkey); + pkey = NULL; + } + + err: + EVP_PKEY_CTX_free(pctx); + return pkey; +} + +/* + * Generate parameters from a group ID + */ +EVP_PKEY *ssl_generate_param_group(uint16_t id) +{ + EVP_PKEY_CTX *pctx = NULL; + EVP_PKEY *pkey = NULL; + const TLS_GROUP_INFO *ginf = tls1_group_id_lookup(id); + + if (ginf == NULL) + goto err; + + if ((ginf->flags & TLS_CURVE_TYPE) == TLS_CURVE_CUSTOM) { + pkey = EVP_PKEY_new(); + if (pkey != NULL && EVP_PKEY_set_type(pkey, ginf->nid)) + return pkey; + EVP_PKEY_free(pkey); + return NULL; + } + + pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); + if (pctx == NULL) + goto err; + if (EVP_PKEY_paramgen_init(pctx) <= 0) + goto err; + if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, ginf->nid) <= 0) + goto err; + if (EVP_PKEY_paramgen(pctx, &pkey) <= 0) { + EVP_PKEY_free(pkey); + pkey = NULL; + } + + err: + EVP_PKEY_CTX_free(pctx); + return pkey; +} +#endif + +/* Derive secrets for ECDH/DH */ +int ssl_derive(SSL *s, EVP_PKEY *privkey, EVP_PKEY *pubkey, int gensecret) +{ + int rv = 0; + unsigned char *pms = NULL; + size_t pmslen = 0; + EVP_PKEY_CTX *pctx; + + if (privkey == NULL || pubkey == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_DERIVE, + ERR_R_INTERNAL_ERROR); + return 0; + } + + pctx = EVP_PKEY_CTX_new(privkey, NULL); + + if (EVP_PKEY_derive_init(pctx) <= 0 + || EVP_PKEY_derive_set_peer(pctx, pubkey) <= 0 + || EVP_PKEY_derive(pctx, NULL, &pmslen) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_DERIVE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + pms = OPENSSL_malloc(pmslen); + if (pms == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_DERIVE, + ERR_R_MALLOC_FAILURE); + goto err; + } + + if (EVP_PKEY_derive(pctx, pms, &pmslen) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_DERIVE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + if (gensecret) { + /* SSLfatal() called as appropriate in the below functions */ + if (SSL_IS_TLS13(s)) { + /* + * If we are resuming then we already generated the early secret + * when we created the ClientHello, so don't recreate it. + */ + if (!s->hit) + rv = tls13_generate_secret(s, ssl_handshake_md(s), NULL, NULL, + 0, + (unsigned char *)&s->early_secret); + else + rv = 1; + + rv = rv && tls13_generate_handshake_secret(s, pms, pmslen); + } else { + rv = ssl_generate_master_secret(s, pms, pmslen, 0); + } + } else { + /* Save premaster secret */ + s->s3->tmp.pms = pms; + s->s3->tmp.pmslen = pmslen; + pms = NULL; + rv = 1; + } + + err: + OPENSSL_clear_free(pms, pmslen); + EVP_PKEY_CTX_free(pctx); + return rv; +} + +#ifndef OPENSSL_NO_DH +EVP_PKEY *ssl_dh_to_pkey(DH *dh) +{ + EVP_PKEY *ret; + if (dh == NULL) + return NULL; + ret = EVP_PKEY_new(); + if (EVP_PKEY_set1_DH(ret, dh) <= 0) { + EVP_PKEY_free(ret); + return NULL; + } + return ret; +} +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/s3_msg.c b/trunk/3rdparty/openssl-1.1-fit/ssl/s3_msg.c new file mode 100644 index 000000000..42382547f --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/s3_msg.c @@ -0,0 +1,104 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "ssl_locl.h" + +int ssl3_do_change_cipher_spec(SSL *s) +{ + int i; + + if (s->server) + i = SSL3_CHANGE_CIPHER_SERVER_READ; + else + i = SSL3_CHANGE_CIPHER_CLIENT_READ; + + if (s->s3->tmp.key_block == NULL) { + if (s->session == NULL || s->session->master_key_length == 0) { + /* might happen if dtls1_read_bytes() calls this */ + SSLerr(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC, SSL_R_CCS_RECEIVED_EARLY); + return 0; + } + + s->session->cipher = s->s3->tmp.new_cipher; + if (!s->method->ssl3_enc->setup_key_block(s)) + return 0; + } + + if (!s->method->ssl3_enc->change_cipher_state(s, i)) + return 0; + + return 1; +} + +int ssl3_send_alert(SSL *s, int level, int desc) +{ + /* Map tls/ssl alert value to correct one */ + if (SSL_TREAT_AS_TLS13(s)) + desc = tls13_alert_code(desc); + else + desc = s->method->ssl3_enc->alert_value(desc); + if (s->version == SSL3_VERSION && desc == SSL_AD_PROTOCOL_VERSION) + desc = SSL_AD_HANDSHAKE_FAILURE; /* SSL 3.0 does not have + * protocol_version alerts */ + if (desc < 0) + return -1; + /* If a fatal one, remove from cache */ + if ((level == SSL3_AL_FATAL) && (s->session != NULL)) + SSL_CTX_remove_session(s->session_ctx, s->session); + + s->s3->alert_dispatch = 1; + s->s3->send_alert[0] = level; + s->s3->send_alert[1] = desc; + if (!RECORD_LAYER_write_pending(&s->rlayer)) { + /* data still being written out? */ + return s->method->ssl_dispatch_alert(s); + } + /* + * else data is still being written out, we will get written some time in + * the future + */ + return -1; +} + +int ssl3_dispatch_alert(SSL *s) +{ + int i, j; + size_t alertlen; + void (*cb) (const SSL *ssl, int type, int val) = NULL; + size_t written; + + s->s3->alert_dispatch = 0; + alertlen = 2; + i = do_ssl3_write(s, SSL3_RT_ALERT, &s->s3->send_alert[0], &alertlen, 1, 0, + &written); + if (i <= 0) { + s->s3->alert_dispatch = 1; + } else { + /* + * Alert sent to BIO - now flush. If the message does not get sent due + * to non-blocking IO, we will not worry too much. + */ + (void)BIO_flush(s->wbio); + + if (s->msg_callback) + s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3->send_alert, + 2, s, s->msg_callback_arg); + + if (s->info_callback != NULL) + cb = s->info_callback; + else if (s->ctx->info_callback != NULL) + cb = s->ctx->info_callback; + + if (cb != NULL) { + j = (s->s3->send_alert[0] << 8) | s->s3->send_alert[1]; + cb(s, SSL_CB_WRITE_ALERT, j); + } + } + return i; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_asn1.c b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_asn1.c new file mode 100644 index 000000000..b56c5e96c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_asn1.c @@ -0,0 +1,393 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2005 Nokia. All rights reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "ssl_locl.h" +#include +#include + +typedef struct { + uint32_t version; + int32_t ssl_version; + ASN1_OCTET_STRING *cipher; + ASN1_OCTET_STRING *comp_id; + ASN1_OCTET_STRING *master_key; + ASN1_OCTET_STRING *session_id; + ASN1_OCTET_STRING *key_arg; + int64_t time; + int64_t timeout; + X509 *peer; + ASN1_OCTET_STRING *session_id_context; + int32_t verify_result; + ASN1_OCTET_STRING *tlsext_hostname; + uint64_t tlsext_tick_lifetime_hint; + uint32_t tlsext_tick_age_add; + ASN1_OCTET_STRING *tlsext_tick; +#ifndef OPENSSL_NO_PSK + ASN1_OCTET_STRING *psk_identity_hint; + ASN1_OCTET_STRING *psk_identity; +#endif +#ifndef OPENSSL_NO_SRP + ASN1_OCTET_STRING *srp_username; +#endif + uint64_t flags; + uint32_t max_early_data; + ASN1_OCTET_STRING *alpn_selected; + uint32_t tlsext_max_fragment_len_mode; + ASN1_OCTET_STRING *ticket_appdata; +} SSL_SESSION_ASN1; + +ASN1_SEQUENCE(SSL_SESSION_ASN1) = { + ASN1_EMBED(SSL_SESSION_ASN1, version, UINT32), + ASN1_EMBED(SSL_SESSION_ASN1, ssl_version, INT32), + ASN1_SIMPLE(SSL_SESSION_ASN1, cipher, ASN1_OCTET_STRING), + ASN1_SIMPLE(SSL_SESSION_ASN1, session_id, ASN1_OCTET_STRING), + ASN1_SIMPLE(SSL_SESSION_ASN1, master_key, ASN1_OCTET_STRING), + ASN1_IMP_OPT(SSL_SESSION_ASN1, key_arg, ASN1_OCTET_STRING, 0), + ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, time, ZINT64, 1), + ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, timeout, ZINT64, 2), + ASN1_EXP_OPT(SSL_SESSION_ASN1, peer, X509, 3), + ASN1_EXP_OPT(SSL_SESSION_ASN1, session_id_context, ASN1_OCTET_STRING, 4), + ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, verify_result, ZINT32, 5), + ASN1_EXP_OPT(SSL_SESSION_ASN1, tlsext_hostname, ASN1_OCTET_STRING, 6), +#ifndef OPENSSL_NO_PSK + ASN1_EXP_OPT(SSL_SESSION_ASN1, psk_identity_hint, ASN1_OCTET_STRING, 7), + ASN1_EXP_OPT(SSL_SESSION_ASN1, psk_identity, ASN1_OCTET_STRING, 8), +#endif + ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, tlsext_tick_lifetime_hint, ZUINT64, 9), + ASN1_EXP_OPT(SSL_SESSION_ASN1, tlsext_tick, ASN1_OCTET_STRING, 10), + ASN1_EXP_OPT(SSL_SESSION_ASN1, comp_id, ASN1_OCTET_STRING, 11), +#ifndef OPENSSL_NO_SRP + ASN1_EXP_OPT(SSL_SESSION_ASN1, srp_username, ASN1_OCTET_STRING, 12), +#endif + ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, flags, ZUINT64, 13), + ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, tlsext_tick_age_add, ZUINT32, 14), + ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, max_early_data, ZUINT32, 15), + ASN1_EXP_OPT(SSL_SESSION_ASN1, alpn_selected, ASN1_OCTET_STRING, 16), + ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, tlsext_max_fragment_len_mode, ZUINT32, 17), + ASN1_EXP_OPT(SSL_SESSION_ASN1, ticket_appdata, ASN1_OCTET_STRING, 18) +} static_ASN1_SEQUENCE_END(SSL_SESSION_ASN1) + +IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(SSL_SESSION_ASN1) + +/* Utility functions for i2d_SSL_SESSION */ + +/* Initialise OCTET STRING from buffer and length */ + +static void ssl_session_oinit(ASN1_OCTET_STRING **dest, ASN1_OCTET_STRING *os, + unsigned char *data, size_t len) +{ + os->data = data; + os->length = (int)len; + os->flags = 0; + *dest = os; +} + +/* Initialise OCTET STRING from string */ +static void ssl_session_sinit(ASN1_OCTET_STRING **dest, ASN1_OCTET_STRING *os, + char *data) +{ + if (data != NULL) + ssl_session_oinit(dest, os, (unsigned char *)data, strlen(data)); + else + *dest = NULL; +} + +int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp) +{ + + SSL_SESSION_ASN1 as; + + ASN1_OCTET_STRING cipher; + unsigned char cipher_data[2]; + ASN1_OCTET_STRING master_key, session_id, sid_ctx; + +#ifndef OPENSSL_NO_COMP + ASN1_OCTET_STRING comp_id; + unsigned char comp_id_data; +#endif + ASN1_OCTET_STRING tlsext_hostname, tlsext_tick; +#ifndef OPENSSL_NO_SRP + ASN1_OCTET_STRING srp_username; +#endif +#ifndef OPENSSL_NO_PSK + ASN1_OCTET_STRING psk_identity, psk_identity_hint; +#endif + ASN1_OCTET_STRING alpn_selected; + ASN1_OCTET_STRING ticket_appdata; + + long l; + + if ((in == NULL) || ((in->cipher == NULL) && (in->cipher_id == 0))) + return 0; + + memset(&as, 0, sizeof(as)); + + as.version = SSL_SESSION_ASN1_VERSION; + as.ssl_version = in->ssl_version; + + if (in->cipher == NULL) + l = in->cipher_id; + else + l = in->cipher->id; + cipher_data[0] = ((unsigned char)(l >> 8L)) & 0xff; + cipher_data[1] = ((unsigned char)(l)) & 0xff; + + ssl_session_oinit(&as.cipher, &cipher, cipher_data, 2); + +#ifndef OPENSSL_NO_COMP + if (in->compress_meth) { + comp_id_data = (unsigned char)in->compress_meth; + ssl_session_oinit(&as.comp_id, &comp_id, &comp_id_data, 1); + } +#endif + + ssl_session_oinit(&as.master_key, &master_key, + in->master_key, in->master_key_length); + + ssl_session_oinit(&as.session_id, &session_id, + in->session_id, in->session_id_length); + + ssl_session_oinit(&as.session_id_context, &sid_ctx, + in->sid_ctx, in->sid_ctx_length); + + as.time = in->time; + as.timeout = in->timeout; + as.verify_result = in->verify_result; + + as.peer = in->peer; + + ssl_session_sinit(&as.tlsext_hostname, &tlsext_hostname, + in->ext.hostname); + if (in->ext.tick) { + ssl_session_oinit(&as.tlsext_tick, &tlsext_tick, + in->ext.tick, in->ext.ticklen); + } + if (in->ext.tick_lifetime_hint > 0) + as.tlsext_tick_lifetime_hint = in->ext.tick_lifetime_hint; + as.tlsext_tick_age_add = in->ext.tick_age_add; +#ifndef OPENSSL_NO_PSK + ssl_session_sinit(&as.psk_identity_hint, &psk_identity_hint, + in->psk_identity_hint); + ssl_session_sinit(&as.psk_identity, &psk_identity, in->psk_identity); +#endif /* OPENSSL_NO_PSK */ +#ifndef OPENSSL_NO_SRP + ssl_session_sinit(&as.srp_username, &srp_username, in->srp_username); +#endif /* OPENSSL_NO_SRP */ + + as.flags = in->flags; + as.max_early_data = in->ext.max_early_data; + + if (in->ext.alpn_selected == NULL) + as.alpn_selected = NULL; + else + ssl_session_oinit(&as.alpn_selected, &alpn_selected, + in->ext.alpn_selected, in->ext.alpn_selected_len); + + as.tlsext_max_fragment_len_mode = in->ext.max_fragment_len_mode; + + if (in->ticket_appdata == NULL) + as.ticket_appdata = NULL; + else + ssl_session_oinit(&as.ticket_appdata, &ticket_appdata, + in->ticket_appdata, in->ticket_appdata_len); + + return i2d_SSL_SESSION_ASN1(&as, pp); + +} + +/* Utility functions for d2i_SSL_SESSION */ + +/* OPENSSL_strndup an OCTET STRING */ + +static int ssl_session_strndup(char **pdst, ASN1_OCTET_STRING *src) +{ + OPENSSL_free(*pdst); + *pdst = NULL; + if (src == NULL) + return 1; + *pdst = OPENSSL_strndup((char *)src->data, src->length); + if (*pdst == NULL) + return 0; + return 1; +} + +/* Copy an OCTET STRING, return error if it exceeds maximum length */ + +static int ssl_session_memcpy(unsigned char *dst, size_t *pdstlen, + ASN1_OCTET_STRING *src, size_t maxlen) +{ + if (src == NULL) { + *pdstlen = 0; + return 1; + } + if (src->length < 0 || src->length > (int)maxlen) + return 0; + memcpy(dst, src->data, src->length); + *pdstlen = src->length; + return 1; +} + +SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, + long length) +{ + long id; + size_t tmpl; + const unsigned char *p = *pp; + SSL_SESSION_ASN1 *as = NULL; + SSL_SESSION *ret = NULL; + + as = d2i_SSL_SESSION_ASN1(NULL, &p, length); + /* ASN.1 code returns suitable error */ + if (as == NULL) + goto err; + + if (!a || !*a) { + ret = SSL_SESSION_new(); + if (ret == NULL) + goto err; + } else { + ret = *a; + } + + if (as->version != SSL_SESSION_ASN1_VERSION) { + SSLerr(SSL_F_D2I_SSL_SESSION, SSL_R_UNKNOWN_SSL_VERSION); + goto err; + } + + if ((as->ssl_version >> 8) != SSL3_VERSION_MAJOR + && (as->ssl_version >> 8) != DTLS1_VERSION_MAJOR + && as->ssl_version != DTLS1_BAD_VER) { + SSLerr(SSL_F_D2I_SSL_SESSION, SSL_R_UNSUPPORTED_SSL_VERSION); + goto err; + } + + ret->ssl_version = (int)as->ssl_version; + + if (as->cipher->length != 2) { + SSLerr(SSL_F_D2I_SSL_SESSION, SSL_R_CIPHER_CODE_WRONG_LENGTH); + goto err; + } + + id = 0x03000000L | ((unsigned long)as->cipher->data[0] << 8L) + | (unsigned long)as->cipher->data[1]; + + ret->cipher_id = id; + ret->cipher = ssl3_get_cipher_by_id(id); + if (ret->cipher == NULL) + goto err; + + if (!ssl_session_memcpy(ret->session_id, &ret->session_id_length, + as->session_id, SSL3_MAX_SSL_SESSION_ID_LENGTH)) + goto err; + + if (!ssl_session_memcpy(ret->master_key, &tmpl, + as->master_key, TLS13_MAX_RESUMPTION_PSK_LENGTH)) + goto err; + + ret->master_key_length = tmpl; + + if (as->time != 0) + ret->time = (long)as->time; + else + ret->time = (long)time(NULL); + + if (as->timeout != 0) + ret->timeout = (long)as->timeout; + else + ret->timeout = 3; + + X509_free(ret->peer); + ret->peer = as->peer; + as->peer = NULL; + + if (!ssl_session_memcpy(ret->sid_ctx, &ret->sid_ctx_length, + as->session_id_context, SSL_MAX_SID_CTX_LENGTH)) + goto err; + + /* NB: this defaults to zero which is X509_V_OK */ + ret->verify_result = as->verify_result; + + if (!ssl_session_strndup(&ret->ext.hostname, as->tlsext_hostname)) + goto err; + +#ifndef OPENSSL_NO_PSK + if (!ssl_session_strndup(&ret->psk_identity_hint, as->psk_identity_hint)) + goto err; + if (!ssl_session_strndup(&ret->psk_identity, as->psk_identity)) + goto err; +#endif + + ret->ext.tick_lifetime_hint = (unsigned long)as->tlsext_tick_lifetime_hint; + ret->ext.tick_age_add = as->tlsext_tick_age_add; + OPENSSL_free(ret->ext.tick); + if (as->tlsext_tick != NULL) { + ret->ext.tick = as->tlsext_tick->data; + ret->ext.ticklen = as->tlsext_tick->length; + as->tlsext_tick->data = NULL; + } else { + ret->ext.tick = NULL; + } +#ifndef OPENSSL_NO_COMP + if (as->comp_id) { + if (as->comp_id->length != 1) { + SSLerr(SSL_F_D2I_SSL_SESSION, SSL_R_BAD_LENGTH); + goto err; + } + ret->compress_meth = as->comp_id->data[0]; + } else { + ret->compress_meth = 0; + } +#endif + +#ifndef OPENSSL_NO_SRP + if (!ssl_session_strndup(&ret->srp_username, as->srp_username)) + goto err; +#endif /* OPENSSL_NO_SRP */ + /* Flags defaults to zero which is fine */ + ret->flags = (int32_t)as->flags; + ret->ext.max_early_data = as->max_early_data; + + OPENSSL_free(ret->ext.alpn_selected); + if (as->alpn_selected != NULL) { + ret->ext.alpn_selected = as->alpn_selected->data; + ret->ext.alpn_selected_len = as->alpn_selected->length; + as->alpn_selected->data = NULL; + } else { + ret->ext.alpn_selected = NULL; + ret->ext.alpn_selected_len = 0; + } + + ret->ext.max_fragment_len_mode = as->tlsext_max_fragment_len_mode; + + OPENSSL_free(ret->ticket_appdata); + if (as->ticket_appdata != NULL) { + ret->ticket_appdata = as->ticket_appdata->data; + ret->ticket_appdata_len = as->ticket_appdata->length; + as->ticket_appdata->data = NULL; + } else { + ret->ticket_appdata = NULL; + ret->ticket_appdata_len = 0; + } + + M_ASN1_free_of(as, SSL_SESSION_ASN1); + + if ((a != NULL) && (*a == NULL)) + *a = ret; + *pp = p; + return ret; + + err: + M_ASN1_free_of(as, SSL_SESSION_ASN1); + if ((a == NULL) || (*a != ret)) + SSL_SESSION_free(ret); + return NULL; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_cert.c b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_cert.c new file mode 100644 index 000000000..331450789 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_cert.c @@ -0,0 +1,1040 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#include "internal/nelem.h" +#include "internal/o_dir.h" +#include +#include +#include +#include +#include +#include +#include "internal/refcount.h" +#include "ssl_locl.h" +#include "ssl_cert_table.h" +#include "internal/thread_once.h" + +static int ssl_security_default_callback(const SSL *s, const SSL_CTX *ctx, + int op, int bits, int nid, void *other, + void *ex); + +static CRYPTO_ONCE ssl_x509_store_ctx_once = CRYPTO_ONCE_STATIC_INIT; +static volatile int ssl_x509_store_ctx_idx = -1; + +DEFINE_RUN_ONCE_STATIC(ssl_x509_store_ctx_init) +{ + ssl_x509_store_ctx_idx = X509_STORE_CTX_get_ex_new_index(0, + "SSL for verify callback", + NULL, NULL, NULL); + return ssl_x509_store_ctx_idx >= 0; +} + +int SSL_get_ex_data_X509_STORE_CTX_idx(void) +{ + + if (!RUN_ONCE(&ssl_x509_store_ctx_once, ssl_x509_store_ctx_init)) + return -1; + return ssl_x509_store_ctx_idx; +} + +CERT *ssl_cert_new(void) +{ + CERT *ret = OPENSSL_zalloc(sizeof(*ret)); + + if (ret == NULL) { + SSLerr(SSL_F_SSL_CERT_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + ret->key = &(ret->pkeys[SSL_PKEY_RSA]); + ret->references = 1; + ret->sec_cb = ssl_security_default_callback; + ret->sec_level = OPENSSL_TLS_SECURITY_LEVEL; + ret->sec_ex = NULL; + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) { + SSLerr(SSL_F_SSL_CERT_NEW, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ret); + return NULL; + } + + return ret; +} + +CERT *ssl_cert_dup(CERT *cert) +{ + CERT *ret = OPENSSL_zalloc(sizeof(*ret)); + int i; + + if (ret == NULL) { + SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE); + return NULL; + } + + ret->references = 1; + ret->key = &ret->pkeys[cert->key - cert->pkeys]; + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) { + SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ret); + return NULL; + } +#ifndef OPENSSL_NO_DH + if (cert->dh_tmp != NULL) { + ret->dh_tmp = cert->dh_tmp; + EVP_PKEY_up_ref(ret->dh_tmp); + } + ret->dh_tmp_cb = cert->dh_tmp_cb; + ret->dh_tmp_auto = cert->dh_tmp_auto; +#endif + + for (i = 0; i < SSL_PKEY_NUM; i++) { + CERT_PKEY *cpk = cert->pkeys + i; + CERT_PKEY *rpk = ret->pkeys + i; + if (cpk->x509 != NULL) { + rpk->x509 = cpk->x509; + X509_up_ref(rpk->x509); + } + + if (cpk->privatekey != NULL) { + rpk->privatekey = cpk->privatekey; + EVP_PKEY_up_ref(cpk->privatekey); + } + + if (cpk->chain) { + rpk->chain = X509_chain_up_ref(cpk->chain); + if (!rpk->chain) { + SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE); + goto err; + } + } + if (cert->pkeys[i].serverinfo != NULL) { + /* Just copy everything. */ + ret->pkeys[i].serverinfo = + OPENSSL_malloc(cert->pkeys[i].serverinfo_length); + if (ret->pkeys[i].serverinfo == NULL) { + SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE); + goto err; + } + ret->pkeys[i].serverinfo_length = cert->pkeys[i].serverinfo_length; + memcpy(ret->pkeys[i].serverinfo, + cert->pkeys[i].serverinfo, cert->pkeys[i].serverinfo_length); + } + } + + /* Configured sigalgs copied across */ + if (cert->conf_sigalgs) { + ret->conf_sigalgs = OPENSSL_malloc(cert->conf_sigalgslen + * sizeof(*cert->conf_sigalgs)); + if (ret->conf_sigalgs == NULL) + goto err; + memcpy(ret->conf_sigalgs, cert->conf_sigalgs, + cert->conf_sigalgslen * sizeof(*cert->conf_sigalgs)); + ret->conf_sigalgslen = cert->conf_sigalgslen; + } else + ret->conf_sigalgs = NULL; + + if (cert->client_sigalgs) { + ret->client_sigalgs = OPENSSL_malloc(cert->client_sigalgslen + * sizeof(*cert->client_sigalgs)); + if (ret->client_sigalgs == NULL) + goto err; + memcpy(ret->client_sigalgs, cert->client_sigalgs, + cert->client_sigalgslen * sizeof(*cert->client_sigalgs)); + ret->client_sigalgslen = cert->client_sigalgslen; + } else + ret->client_sigalgs = NULL; + /* Shared sigalgs also NULL */ + ret->shared_sigalgs = NULL; + /* Copy any custom client certificate types */ + if (cert->ctype) { + ret->ctype = OPENSSL_memdup(cert->ctype, cert->ctype_len); + if (ret->ctype == NULL) + goto err; + ret->ctype_len = cert->ctype_len; + } + + ret->cert_flags = cert->cert_flags; + + ret->cert_cb = cert->cert_cb; + ret->cert_cb_arg = cert->cert_cb_arg; + + if (cert->verify_store) { + X509_STORE_up_ref(cert->verify_store); + ret->verify_store = cert->verify_store; + } + + if (cert->chain_store) { + X509_STORE_up_ref(cert->chain_store); + ret->chain_store = cert->chain_store; + } + + ret->sec_cb = cert->sec_cb; + ret->sec_level = cert->sec_level; + ret->sec_ex = cert->sec_ex; + + if (!custom_exts_copy(&ret->custext, &cert->custext)) + goto err; +#ifndef OPENSSL_NO_PSK + if (cert->psk_identity_hint) { + ret->psk_identity_hint = OPENSSL_strdup(cert->psk_identity_hint); + if (ret->psk_identity_hint == NULL) + goto err; + } +#endif + return ret; + + err: + ssl_cert_free(ret); + + return NULL; +} + +/* Free up and clear all certificates and chains */ + +void ssl_cert_clear_certs(CERT *c) +{ + int i; + if (c == NULL) + return; + for (i = 0; i < SSL_PKEY_NUM; i++) { + CERT_PKEY *cpk = c->pkeys + i; + X509_free(cpk->x509); + cpk->x509 = NULL; + EVP_PKEY_free(cpk->privatekey); + cpk->privatekey = NULL; + sk_X509_pop_free(cpk->chain, X509_free); + cpk->chain = NULL; + OPENSSL_free(cpk->serverinfo); + cpk->serverinfo = NULL; + cpk->serverinfo_length = 0; + } +} + +void ssl_cert_free(CERT *c) +{ + int i; + + if (c == NULL) + return; + CRYPTO_DOWN_REF(&c->references, &i, c->lock); + REF_PRINT_COUNT("CERT", c); + if (i > 0) + return; + REF_ASSERT_ISNT(i < 0); + +#ifndef OPENSSL_NO_DH + EVP_PKEY_free(c->dh_tmp); +#endif + + ssl_cert_clear_certs(c); + OPENSSL_free(c->conf_sigalgs); + OPENSSL_free(c->client_sigalgs); + OPENSSL_free(c->shared_sigalgs); + OPENSSL_free(c->ctype); + X509_STORE_free(c->verify_store); + X509_STORE_free(c->chain_store); + custom_exts_free(&c->custext); +#ifndef OPENSSL_NO_PSK + OPENSSL_free(c->psk_identity_hint); +#endif + CRYPTO_THREAD_lock_free(c->lock); + OPENSSL_free(c); +} + +int ssl_cert_set0_chain(SSL *s, SSL_CTX *ctx, STACK_OF(X509) *chain) +{ + int i, r; + CERT_PKEY *cpk = s ? s->cert->key : ctx->cert->key; + if (!cpk) + return 0; + for (i = 0; i < sk_X509_num(chain); i++) { + r = ssl_security_cert(s, ctx, sk_X509_value(chain, i), 0, 0); + if (r != 1) { + SSLerr(SSL_F_SSL_CERT_SET0_CHAIN, r); + return 0; + } + } + sk_X509_pop_free(cpk->chain, X509_free); + cpk->chain = chain; + return 1; +} + +int ssl_cert_set1_chain(SSL *s, SSL_CTX *ctx, STACK_OF(X509) *chain) +{ + STACK_OF(X509) *dchain; + if (!chain) + return ssl_cert_set0_chain(s, ctx, NULL); + dchain = X509_chain_up_ref(chain); + if (!dchain) + return 0; + if (!ssl_cert_set0_chain(s, ctx, dchain)) { + sk_X509_pop_free(dchain, X509_free); + return 0; + } + return 1; +} + +int ssl_cert_add0_chain_cert(SSL *s, SSL_CTX *ctx, X509 *x) +{ + int r; + CERT_PKEY *cpk = s ? s->cert->key : ctx->cert->key; + if (!cpk) + return 0; + r = ssl_security_cert(s, ctx, x, 0, 0); + if (r != 1) { + SSLerr(SSL_F_SSL_CERT_ADD0_CHAIN_CERT, r); + return 0; + } + if (!cpk->chain) + cpk->chain = sk_X509_new_null(); + if (!cpk->chain || !sk_X509_push(cpk->chain, x)) + return 0; + return 1; +} + +int ssl_cert_add1_chain_cert(SSL *s, SSL_CTX *ctx, X509 *x) +{ + if (!ssl_cert_add0_chain_cert(s, ctx, x)) + return 0; + X509_up_ref(x); + return 1; +} + +int ssl_cert_select_current(CERT *c, X509 *x) +{ + int i; + if (x == NULL) + return 0; + for (i = 0; i < SSL_PKEY_NUM; i++) { + CERT_PKEY *cpk = c->pkeys + i; + if (cpk->x509 == x && cpk->privatekey) { + c->key = cpk; + return 1; + } + } + + for (i = 0; i < SSL_PKEY_NUM; i++) { + CERT_PKEY *cpk = c->pkeys + i; + if (cpk->privatekey && cpk->x509 && !X509_cmp(cpk->x509, x)) { + c->key = cpk; + return 1; + } + } + return 0; +} + +int ssl_cert_set_current(CERT *c, long op) +{ + int i, idx; + if (!c) + return 0; + if (op == SSL_CERT_SET_FIRST) + idx = 0; + else if (op == SSL_CERT_SET_NEXT) { + idx = (int)(c->key - c->pkeys + 1); + if (idx >= SSL_PKEY_NUM) + return 0; + } else + return 0; + for (i = idx; i < SSL_PKEY_NUM; i++) { + CERT_PKEY *cpk = c->pkeys + i; + if (cpk->x509 && cpk->privatekey) { + c->key = cpk; + return 1; + } + } + return 0; +} + +void ssl_cert_set_cert_cb(CERT *c, int (*cb) (SSL *ssl, void *arg), void *arg) +{ + c->cert_cb = cb; + c->cert_cb_arg = arg; +} + +int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk) +{ + X509 *x; + int i = 0; + X509_STORE *verify_store; + X509_STORE_CTX *ctx = NULL; + X509_VERIFY_PARAM *param; + + if ((sk == NULL) || (sk_X509_num(sk) == 0)) + return 0; + + if (s->cert->verify_store) + verify_store = s->cert->verify_store; + else + verify_store = s->ctx->cert_store; + + ctx = X509_STORE_CTX_new(); + if (ctx == NULL) { + SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN, ERR_R_MALLOC_FAILURE); + return 0; + } + + x = sk_X509_value(sk, 0); + if (!X509_STORE_CTX_init(ctx, verify_store, x, sk)) { + SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN, ERR_R_X509_LIB); + goto end; + } + param = X509_STORE_CTX_get0_param(ctx); + /* + * XXX: Separate @AUTHSECLEVEL and @TLSSECLEVEL would be useful at some + * point, for now a single @SECLEVEL sets the same policy for TLS crypto + * and PKI authentication. + */ + X509_VERIFY_PARAM_set_auth_level(param, SSL_get_security_level(s)); + + /* Set suite B flags if needed */ + X509_STORE_CTX_set_flags(ctx, tls1_suiteb(s)); + if (!X509_STORE_CTX_set_ex_data + (ctx, SSL_get_ex_data_X509_STORE_CTX_idx(), s)) { + goto end; + } + + /* Verify via DANE if enabled */ + if (DANETLS_ENABLED(&s->dane)) + X509_STORE_CTX_set0_dane(ctx, &s->dane); + + /* + * We need to inherit the verify parameters. These can be determined by + * the context: if its a server it will verify SSL client certificates or + * vice versa. + */ + + X509_STORE_CTX_set_default(ctx, s->server ? "ssl_client" : "ssl_server"); + /* + * Anything non-default in "s->param" should overwrite anything in the ctx. + */ + X509_VERIFY_PARAM_set1(param, s->param); + + if (s->verify_callback) + X509_STORE_CTX_set_verify_cb(ctx, s->verify_callback); + + if (s->ctx->app_verify_callback != NULL) + i = s->ctx->app_verify_callback(ctx, s->ctx->app_verify_arg); + else + i = X509_verify_cert(ctx); + + s->verify_result = X509_STORE_CTX_get_error(ctx); + sk_X509_pop_free(s->verified_chain, X509_free); + s->verified_chain = NULL; + if (X509_STORE_CTX_get0_chain(ctx) != NULL) { + s->verified_chain = X509_STORE_CTX_get1_chain(ctx); + if (s->verified_chain == NULL) { + SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN, ERR_R_MALLOC_FAILURE); + i = 0; + } + } + + /* Move peername from the store context params to the SSL handle's */ + X509_VERIFY_PARAM_move_peername(s->param, param); + + end: + X509_STORE_CTX_free(ctx); + return i; +} + +static void set0_CA_list(STACK_OF(X509_NAME) **ca_list, + STACK_OF(X509_NAME) *name_list) +{ + sk_X509_NAME_pop_free(*ca_list, X509_NAME_free); + *ca_list = name_list; +} + +STACK_OF(X509_NAME) *SSL_dup_CA_list(const STACK_OF(X509_NAME) *sk) +{ + int i; + const int num = sk_X509_NAME_num(sk); + STACK_OF(X509_NAME) *ret; + X509_NAME *name; + + ret = sk_X509_NAME_new_reserve(NULL, num); + if (ret == NULL) { + SSLerr(SSL_F_SSL_DUP_CA_LIST, ERR_R_MALLOC_FAILURE); + return NULL; + } + for (i = 0; i < num; i++) { + name = X509_NAME_dup(sk_X509_NAME_value(sk, i)); + if (name == NULL) { + SSLerr(SSL_F_SSL_DUP_CA_LIST, ERR_R_MALLOC_FAILURE); + sk_X509_NAME_pop_free(ret, X509_NAME_free); + return NULL; + } + sk_X509_NAME_push(ret, name); /* Cannot fail after reserve call */ + } + return ret; +} + +void SSL_set0_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list) +{ + set0_CA_list(&s->ca_names, name_list); +} + +void SSL_CTX_set0_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list) +{ + set0_CA_list(&ctx->ca_names, name_list); +} + +const STACK_OF(X509_NAME) *SSL_CTX_get0_CA_list(const SSL_CTX *ctx) +{ + return ctx->ca_names; +} + +const STACK_OF(X509_NAME) *SSL_get0_CA_list(const SSL *s) +{ + return s->ca_names != NULL ? s->ca_names : s->ctx->ca_names; +} + +void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list) +{ + set0_CA_list(&ctx->client_ca_names, name_list); +} + +STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *ctx) +{ + return ctx->client_ca_names; +} + +void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list) +{ + set0_CA_list(&s->client_ca_names, name_list); +} + +const STACK_OF(X509_NAME) *SSL_get0_peer_CA_list(const SSL *s) +{ + return s->s3 != NULL ? s->s3->tmp.peer_ca_names : NULL; +} + +STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s) +{ + if (!s->server) + return s->s3 != NULL ? s->s3->tmp.peer_ca_names : NULL; + return s->client_ca_names != NULL ? s->client_ca_names + : s->ctx->client_ca_names; +} + +static int add_ca_name(STACK_OF(X509_NAME) **sk, const X509 *x) +{ + X509_NAME *name; + + if (x == NULL) + return 0; + if (*sk == NULL && ((*sk = sk_X509_NAME_new_null()) == NULL)) + return 0; + + if ((name = X509_NAME_dup(X509_get_subject_name(x))) == NULL) + return 0; + + if (!sk_X509_NAME_push(*sk, name)) { + X509_NAME_free(name); + return 0; + } + return 1; +} + +int SSL_add1_to_CA_list(SSL *ssl, const X509 *x) +{ + return add_ca_name(&ssl->ca_names, x); +} + +int SSL_CTX_add1_to_CA_list(SSL_CTX *ctx, const X509 *x) +{ + return add_ca_name(&ctx->ca_names, x); +} + +/* + * The following two are older names are to be replaced with + * SSL(_CTX)_add1_to_CA_list + */ +int SSL_add_client_CA(SSL *ssl, X509 *x) +{ + return add_ca_name(&ssl->client_ca_names, x); +} + +int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x) +{ + return add_ca_name(&ctx->client_ca_names, x); +} + +static int xname_cmp(const X509_NAME *a, const X509_NAME *b) +{ + unsigned char *abuf = NULL, *bbuf = NULL; + int alen, blen, ret; + + /* X509_NAME_cmp() itself casts away constness in this way, so + * assume it's safe: + */ + alen = i2d_X509_NAME((X509_NAME *)a, &abuf); + blen = i2d_X509_NAME((X509_NAME *)b, &bbuf); + + if (alen < 0 || blen < 0) + ret = -2; + else if (alen != blen) + ret = alen - blen; + else /* alen == blen */ + ret = memcmp(abuf, bbuf, alen); + + OPENSSL_free(abuf); + OPENSSL_free(bbuf); + + return ret; +} + +static int xname_sk_cmp(const X509_NAME *const *a, const X509_NAME *const *b) +{ + return xname_cmp(*a, *b); +} + +static unsigned long xname_hash(const X509_NAME *a) +{ + return X509_NAME_hash((X509_NAME *)a); +} + +/** + * Load CA certs from a file into a ::STACK. Note that it is somewhat misnamed; + * it doesn't really have anything to do with clients (except that a common use + * for a stack of CAs is to send it to the client). Actually, it doesn't have + * much to do with CAs, either, since it will load any old cert. + * \param file the file containing one or more certs. + * \return a ::STACK containing the certs. + */ +STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file) +{ + BIO *in = BIO_new(BIO_s_file()); + X509 *x = NULL; + X509_NAME *xn = NULL; + STACK_OF(X509_NAME) *ret = NULL; + LHASH_OF(X509_NAME) *name_hash = lh_X509_NAME_new(xname_hash, xname_cmp); + + if ((name_hash == NULL) || (in == NULL)) { + SSLerr(SSL_F_SSL_LOAD_CLIENT_CA_FILE, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!BIO_read_filename(in, file)) + goto err; + + for (;;) { + if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL) + break; + if (ret == NULL) { + ret = sk_X509_NAME_new_null(); + if (ret == NULL) { + SSLerr(SSL_F_SSL_LOAD_CLIENT_CA_FILE, ERR_R_MALLOC_FAILURE); + goto err; + } + } + if ((xn = X509_get_subject_name(x)) == NULL) + goto err; + /* check for duplicates */ + xn = X509_NAME_dup(xn); + if (xn == NULL) + goto err; + if (lh_X509_NAME_retrieve(name_hash, xn) != NULL) { + /* Duplicate. */ + X509_NAME_free(xn); + xn = NULL; + } else { + lh_X509_NAME_insert(name_hash, xn); + if (!sk_X509_NAME_push(ret, xn)) + goto err; + } + } + goto done; + + err: + X509_NAME_free(xn); + sk_X509_NAME_pop_free(ret, X509_NAME_free); + ret = NULL; + done: + BIO_free(in); + X509_free(x); + lh_X509_NAME_free(name_hash); + if (ret != NULL) + ERR_clear_error(); + return ret; +} + +/** + * Add a file of certs to a stack. + * \param stack the stack to add to. + * \param file the file to add from. All certs in this file that are not + * already in the stack will be added. + * \return 1 for success, 0 for failure. Note that in the case of failure some + * certs may have been added to \c stack. + */ + +int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, + const char *file) +{ + BIO *in; + X509 *x = NULL; + X509_NAME *xn = NULL; + int ret = 1; + int (*oldcmp) (const X509_NAME *const *a, const X509_NAME *const *b); + + oldcmp = sk_X509_NAME_set_cmp_func(stack, xname_sk_cmp); + + in = BIO_new(BIO_s_file()); + + if (in == NULL) { + SSLerr(SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!BIO_read_filename(in, file)) + goto err; + + for (;;) { + if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL) + break; + if ((xn = X509_get_subject_name(x)) == NULL) + goto err; + xn = X509_NAME_dup(xn); + if (xn == NULL) + goto err; + if (sk_X509_NAME_find(stack, xn) >= 0) { + /* Duplicate. */ + X509_NAME_free(xn); + } else if (!sk_X509_NAME_push(stack, xn)) { + X509_NAME_free(xn); + goto err; + } + } + + ERR_clear_error(); + goto done; + + err: + ret = 0; + done: + BIO_free(in); + X509_free(x); + (void)sk_X509_NAME_set_cmp_func(stack, oldcmp); + return ret; +} + +/** + * Add a directory of certs to a stack. + * \param stack the stack to append to. + * \param dir the directory to append from. All files in this directory will be + * examined as potential certs. Any that are acceptable to + * SSL_add_dir_cert_subjects_to_stack() that are not already in the stack will be + * included. + * \return 1 for success, 0 for failure. Note that in the case of failure some + * certs may have been added to \c stack. + */ + +int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, + const char *dir) +{ + OPENSSL_DIR_CTX *d = NULL; + const char *filename; + int ret = 0; + + /* Note that a side effect is that the CAs will be sorted by name */ + + while ((filename = OPENSSL_DIR_read(&d, dir))) { + char buf[1024]; + int r; + + if (strlen(dir) + strlen(filename) + 2 > sizeof(buf)) { + SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK, + SSL_R_PATH_TOO_LONG); + goto err; + } +#ifdef OPENSSL_SYS_VMS + r = BIO_snprintf(buf, sizeof(buf), "%s%s", dir, filename); +#else + r = BIO_snprintf(buf, sizeof(buf), "%s/%s", dir, filename); +#endif + if (r <= 0 || r >= (int)sizeof(buf)) + goto err; + if (!SSL_add_file_cert_subjects_to_stack(stack, buf)) + goto err; + } + + if (errno) { + SYSerr(SYS_F_OPENDIR, get_last_sys_error()); + ERR_add_error_data(3, "OPENSSL_DIR_read(&ctx, '", dir, "')"); + SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK, ERR_R_SYS_LIB); + goto err; + } + + ret = 1; + + err: + if (d) + OPENSSL_DIR_end(&d); + + return ret; +} + +/* Build a certificate chain for current certificate */ +int ssl_build_cert_chain(SSL *s, SSL_CTX *ctx, int flags) +{ + CERT *c = s ? s->cert : ctx->cert; + CERT_PKEY *cpk = c->key; + X509_STORE *chain_store = NULL; + X509_STORE_CTX *xs_ctx = NULL; + STACK_OF(X509) *chain = NULL, *untrusted = NULL; + X509 *x; + int i, rv = 0; + + if (!cpk->x509) { + SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, SSL_R_NO_CERTIFICATE_SET); + goto err; + } + /* Rearranging and check the chain: add everything to a store */ + if (flags & SSL_BUILD_CHAIN_FLAG_CHECK) { + chain_store = X509_STORE_new(); + if (chain_store == NULL) + goto err; + for (i = 0; i < sk_X509_num(cpk->chain); i++) { + x = sk_X509_value(cpk->chain, i); + if (!X509_STORE_add_cert(chain_store, x)) + goto err; + } + /* Add EE cert too: it might be self signed */ + if (!X509_STORE_add_cert(chain_store, cpk->x509)) + goto err; + } else { + if (c->chain_store) + chain_store = c->chain_store; + else if (s) + chain_store = s->ctx->cert_store; + else + chain_store = ctx->cert_store; + + if (flags & SSL_BUILD_CHAIN_FLAG_UNTRUSTED) + untrusted = cpk->chain; + } + + xs_ctx = X509_STORE_CTX_new(); + if (xs_ctx == NULL) { + SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!X509_STORE_CTX_init(xs_ctx, chain_store, cpk->x509, untrusted)) { + SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, ERR_R_X509_LIB); + goto err; + } + /* Set suite B flags if needed */ + X509_STORE_CTX_set_flags(xs_ctx, + c->cert_flags & SSL_CERT_FLAG_SUITEB_128_LOS); + + i = X509_verify_cert(xs_ctx); + if (i <= 0 && flags & SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR) { + if (flags & SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR) + ERR_clear_error(); + i = 1; + rv = 2; + } + if (i > 0) + chain = X509_STORE_CTX_get1_chain(xs_ctx); + if (i <= 0) { + SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, SSL_R_CERTIFICATE_VERIFY_FAILED); + i = X509_STORE_CTX_get_error(xs_ctx); + ERR_add_error_data(2, "Verify error:", + X509_verify_cert_error_string(i)); + + goto err; + } + /* Remove EE certificate from chain */ + x = sk_X509_shift(chain); + X509_free(x); + if (flags & SSL_BUILD_CHAIN_FLAG_NO_ROOT) { + if (sk_X509_num(chain) > 0) { + /* See if last cert is self signed */ + x = sk_X509_value(chain, sk_X509_num(chain) - 1); + if (X509_get_extension_flags(x) & EXFLAG_SS) { + x = sk_X509_pop(chain); + X509_free(x); + } + } + } + /* + * Check security level of all CA certificates: EE will have been checked + * already. + */ + for (i = 0; i < sk_X509_num(chain); i++) { + x = sk_X509_value(chain, i); + rv = ssl_security_cert(s, ctx, x, 0, 0); + if (rv != 1) { + SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, rv); + sk_X509_pop_free(chain, X509_free); + rv = 0; + goto err; + } + } + sk_X509_pop_free(cpk->chain, X509_free); + cpk->chain = chain; + if (rv == 0) + rv = 1; + err: + if (flags & SSL_BUILD_CHAIN_FLAG_CHECK) + X509_STORE_free(chain_store); + X509_STORE_CTX_free(xs_ctx); + + return rv; +} + +int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain, int ref) +{ + X509_STORE **pstore; + if (chain) + pstore = &c->chain_store; + else + pstore = &c->verify_store; + X509_STORE_free(*pstore); + *pstore = store; + if (ref && store) + X509_STORE_up_ref(store); + return 1; +} + +static int ssl_security_default_callback(const SSL *s, const SSL_CTX *ctx, + int op, int bits, int nid, void *other, + void *ex) +{ + int level, minbits; + static const int minbits_table[5] = { 80, 112, 128, 192, 256 }; + if (ctx) + level = SSL_CTX_get_security_level(ctx); + else + level = SSL_get_security_level(s); + + if (level <= 0) { + /* + * No EDH keys weaker than 1024-bits even at level 0, otherwise, + * anything goes. + */ + if (op == SSL_SECOP_TMP_DH && bits < 80) + return 0; + return 1; + } + if (level > 5) + level = 5; + minbits = minbits_table[level - 1]; + switch (op) { + case SSL_SECOP_CIPHER_SUPPORTED: + case SSL_SECOP_CIPHER_SHARED: + case SSL_SECOP_CIPHER_CHECK: + { + const SSL_CIPHER *c = other; + /* No ciphers below security level */ + if (bits < minbits) + return 0; + /* No unauthenticated ciphersuites */ + if (c->algorithm_auth & SSL_aNULL) + return 0; + /* No MD5 mac ciphersuites */ + if (c->algorithm_mac & SSL_MD5) + return 0; + /* SHA1 HMAC is 160 bits of security */ + if (minbits > 160 && c->algorithm_mac & SSL_SHA1) + return 0; + /* Level 2: no RC4 */ + if (level >= 2 && c->algorithm_enc == SSL_RC4) + return 0; + /* Level 3: forward secure ciphersuites only */ + if (level >= 3 && c->min_tls != TLS1_3_VERSION && + !(c->algorithm_mkey & (SSL_kEDH | SSL_kEECDH))) + return 0; + break; + } + case SSL_SECOP_VERSION: + if (!SSL_IS_DTLS(s)) { + /* SSLv3 not allowed at level 2 */ + if (nid <= SSL3_VERSION && level >= 2) + return 0; + /* TLS v1.1 and above only for level 3 */ + if (nid <= TLS1_VERSION && level >= 3) + return 0; + /* TLS v1.2 only for level 4 and above */ + if (nid <= TLS1_1_VERSION && level >= 4) + return 0; + } else { + /* DTLS v1.2 only for level 4 and above */ + if (DTLS_VERSION_LT(nid, DTLS1_2_VERSION) && level >= 4) + return 0; + } + break; + + case SSL_SECOP_COMPRESSION: + if (level >= 2) + return 0; + break; + case SSL_SECOP_TICKET: + if (level >= 3) + return 0; + break; + default: + if (bits < minbits) + return 0; + } + return 1; +} + +int ssl_security(const SSL *s, int op, int bits, int nid, void *other) +{ + return s->cert->sec_cb(s, NULL, op, bits, nid, other, s->cert->sec_ex); +} + +int ssl_ctx_security(const SSL_CTX *ctx, int op, int bits, int nid, void *other) +{ + return ctx->cert->sec_cb(NULL, ctx, op, bits, nid, other, + ctx->cert->sec_ex); +} + +int ssl_cert_lookup_by_nid(int nid, size_t *pidx) +{ + size_t i; + + for (i = 0; i < OSSL_NELEM(ssl_cert_info); i++) { + if (ssl_cert_info[i].nid == nid) { + *pidx = i; + return 1; + } + } + + return 0; +} + +const SSL_CERT_LOOKUP *ssl_cert_lookup_by_pkey(const EVP_PKEY *pk, size_t *pidx) +{ + int nid = EVP_PKEY_id(pk); + size_t tmpidx; + + if (nid == NID_undef) + return NULL; + + if (!ssl_cert_lookup_by_nid(nid, &tmpidx)) + return NULL; + + if (pidx != NULL) + *pidx = tmpidx; + + return &ssl_cert_info[tmpidx]; +} + +const SSL_CERT_LOOKUP *ssl_cert_lookup_by_idx(size_t idx) +{ + if (idx >= OSSL_NELEM(ssl_cert_info)) + return NULL; + return &ssl_cert_info[idx]; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_cert_table.h b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_cert_table.h new file mode 100644 index 000000000..0c47241c0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_cert_table.h @@ -0,0 +1,23 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Certificate table information. NB: table entries must match SSL_PKEY indices + */ +static const SSL_CERT_LOOKUP ssl_cert_info [] = { + {EVP_PKEY_RSA, SSL_aRSA}, /* SSL_PKEY_RSA */ + {EVP_PKEY_RSA_PSS, SSL_aRSA}, /* SSL_PKEY_RSA_PSS_SIGN */ + {EVP_PKEY_DSA, SSL_aDSS}, /* SSL_PKEY_DSA_SIGN */ + {EVP_PKEY_EC, SSL_aECDSA}, /* SSL_PKEY_ECC */ + {NID_id_GostR3410_2001, SSL_aGOST01}, /* SSL_PKEY_GOST01 */ + {NID_id_GostR3410_2012_256, SSL_aGOST12}, /* SSL_PKEY_GOST12_256 */ + {NID_id_GostR3410_2012_512, SSL_aGOST12}, /* SSL_PKEY_GOST12_512 */ + {EVP_PKEY_ED25519, SSL_aECDSA}, /* SSL_PKEY_ED25519 */ + {EVP_PKEY_ED448, SSL_aECDSA} /* SSL_PKEY_ED448 */ +}; diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_ciph.c b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_ciph.c new file mode 100644 index 000000000..b60d67aa0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_ciph.c @@ -0,0 +1,2163 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * Copyright 2005 Nokia. All rights reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include "internal/nelem.h" +#include "ssl_locl.h" +#include "internal/thread_once.h" +#include "internal/cryptlib.h" + +#define SSL_ENC_DES_IDX 0 +#define SSL_ENC_3DES_IDX 1 +#define SSL_ENC_RC4_IDX 2 +#define SSL_ENC_RC2_IDX 3 +#define SSL_ENC_IDEA_IDX 4 +#define SSL_ENC_NULL_IDX 5 +#define SSL_ENC_AES128_IDX 6 +#define SSL_ENC_AES256_IDX 7 +#define SSL_ENC_CAMELLIA128_IDX 8 +#define SSL_ENC_CAMELLIA256_IDX 9 +#define SSL_ENC_GOST89_IDX 10 +#define SSL_ENC_SEED_IDX 11 +#define SSL_ENC_AES128GCM_IDX 12 +#define SSL_ENC_AES256GCM_IDX 13 +#define SSL_ENC_AES128CCM_IDX 14 +#define SSL_ENC_AES256CCM_IDX 15 +#define SSL_ENC_AES128CCM8_IDX 16 +#define SSL_ENC_AES256CCM8_IDX 17 +#define SSL_ENC_GOST8912_IDX 18 +#define SSL_ENC_CHACHA_IDX 19 +#define SSL_ENC_ARIA128GCM_IDX 20 +#define SSL_ENC_ARIA256GCM_IDX 21 +#define SSL_ENC_NUM_IDX 22 + +/* NB: make sure indices in these tables match values above */ + +typedef struct { + uint32_t mask; + int nid; +} ssl_cipher_table; + +/* Table of NIDs for each cipher */ +static const ssl_cipher_table ssl_cipher_table_cipher[SSL_ENC_NUM_IDX] = { + {SSL_DES, NID_des_cbc}, /* SSL_ENC_DES_IDX 0 */ + {SSL_3DES, NID_des_ede3_cbc}, /* SSL_ENC_3DES_IDX 1 */ + {SSL_RC4, NID_rc4}, /* SSL_ENC_RC4_IDX 2 */ + {SSL_RC2, NID_rc2_cbc}, /* SSL_ENC_RC2_IDX 3 */ + {SSL_IDEA, NID_idea_cbc}, /* SSL_ENC_IDEA_IDX 4 */ + {SSL_eNULL, NID_undef}, /* SSL_ENC_NULL_IDX 5 */ + {SSL_AES128, NID_aes_128_cbc}, /* SSL_ENC_AES128_IDX 6 */ + {SSL_AES256, NID_aes_256_cbc}, /* SSL_ENC_AES256_IDX 7 */ + {SSL_CAMELLIA128, NID_camellia_128_cbc}, /* SSL_ENC_CAMELLIA128_IDX 8 */ + {SSL_CAMELLIA256, NID_camellia_256_cbc}, /* SSL_ENC_CAMELLIA256_IDX 9 */ + {SSL_eGOST2814789CNT, NID_gost89_cnt}, /* SSL_ENC_GOST89_IDX 10 */ + {SSL_SEED, NID_seed_cbc}, /* SSL_ENC_SEED_IDX 11 */ + {SSL_AES128GCM, NID_aes_128_gcm}, /* SSL_ENC_AES128GCM_IDX 12 */ + {SSL_AES256GCM, NID_aes_256_gcm}, /* SSL_ENC_AES256GCM_IDX 13 */ + {SSL_AES128CCM, NID_aes_128_ccm}, /* SSL_ENC_AES128CCM_IDX 14 */ + {SSL_AES256CCM, NID_aes_256_ccm}, /* SSL_ENC_AES256CCM_IDX 15 */ + {SSL_AES128CCM8, NID_aes_128_ccm}, /* SSL_ENC_AES128CCM8_IDX 16 */ + {SSL_AES256CCM8, NID_aes_256_ccm}, /* SSL_ENC_AES256CCM8_IDX 17 */ + {SSL_eGOST2814789CNT12, NID_gost89_cnt_12}, /* SSL_ENC_GOST8912_IDX 18 */ + {SSL_CHACHA20POLY1305, NID_chacha20_poly1305}, /* SSL_ENC_CHACHA_IDX 19 */ + {SSL_ARIA128GCM, NID_aria_128_gcm}, /* SSL_ENC_ARIA128GCM_IDX 20 */ + {SSL_ARIA256GCM, NID_aria_256_gcm}, /* SSL_ENC_ARIA256GCM_IDX 21 */ +}; + +static const EVP_CIPHER *ssl_cipher_methods[SSL_ENC_NUM_IDX]; + +#define SSL_COMP_NULL_IDX 0 +#define SSL_COMP_ZLIB_IDX 1 +#define SSL_COMP_NUM_IDX 2 + +static STACK_OF(SSL_COMP) *ssl_comp_methods = NULL; + +#ifndef OPENSSL_NO_COMP +static CRYPTO_ONCE ssl_load_builtin_comp_once = CRYPTO_ONCE_STATIC_INIT; +#endif + +/* + * Constant SSL_MAX_DIGEST equal to size of digests array should be defined + * in the ssl_locl.h + */ + +#define SSL_MD_NUM_IDX SSL_MAX_DIGEST + +/* NB: make sure indices in this table matches values above */ +static const ssl_cipher_table ssl_cipher_table_mac[SSL_MD_NUM_IDX] = { + {SSL_MD5, NID_md5}, /* SSL_MD_MD5_IDX 0 */ + {SSL_SHA1, NID_sha1}, /* SSL_MD_SHA1_IDX 1 */ + {SSL_GOST94, NID_id_GostR3411_94}, /* SSL_MD_GOST94_IDX 2 */ + {SSL_GOST89MAC, NID_id_Gost28147_89_MAC}, /* SSL_MD_GOST89MAC_IDX 3 */ + {SSL_SHA256, NID_sha256}, /* SSL_MD_SHA256_IDX 4 */ + {SSL_SHA384, NID_sha384}, /* SSL_MD_SHA384_IDX 5 */ + {SSL_GOST12_256, NID_id_GostR3411_2012_256}, /* SSL_MD_GOST12_256_IDX 6 */ + {SSL_GOST89MAC12, NID_gost_mac_12}, /* SSL_MD_GOST89MAC12_IDX 7 */ + {SSL_GOST12_512, NID_id_GostR3411_2012_512}, /* SSL_MD_GOST12_512_IDX 8 */ + {0, NID_md5_sha1}, /* SSL_MD_MD5_SHA1_IDX 9 */ + {0, NID_sha224}, /* SSL_MD_SHA224_IDX 10 */ + {0, NID_sha512} /* SSL_MD_SHA512_IDX 11 */ +}; + +static const EVP_MD *ssl_digest_methods[SSL_MD_NUM_IDX] = { + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +/* *INDENT-OFF* */ +static const ssl_cipher_table ssl_cipher_table_kx[] = { + {SSL_kRSA, NID_kx_rsa}, + {SSL_kECDHE, NID_kx_ecdhe}, + {SSL_kDHE, NID_kx_dhe}, + {SSL_kECDHEPSK, NID_kx_ecdhe_psk}, + {SSL_kDHEPSK, NID_kx_dhe_psk}, + {SSL_kRSAPSK, NID_kx_rsa_psk}, + {SSL_kPSK, NID_kx_psk}, + {SSL_kSRP, NID_kx_srp}, + {SSL_kGOST, NID_kx_gost}, + {SSL_kANY, NID_kx_any} +}; + +static const ssl_cipher_table ssl_cipher_table_auth[] = { + {SSL_aRSA, NID_auth_rsa}, + {SSL_aECDSA, NID_auth_ecdsa}, + {SSL_aPSK, NID_auth_psk}, + {SSL_aDSS, NID_auth_dss}, + {SSL_aGOST01, NID_auth_gost01}, + {SSL_aGOST12, NID_auth_gost12}, + {SSL_aSRP, NID_auth_srp}, + {SSL_aNULL, NID_auth_null}, + {SSL_aANY, NID_auth_any} +}; +/* *INDENT-ON* */ + +/* Utility function for table lookup */ +static int ssl_cipher_info_find(const ssl_cipher_table * table, + size_t table_cnt, uint32_t mask) +{ + size_t i; + for (i = 0; i < table_cnt; i++, table++) { + if (table->mask == mask) + return (int)i; + } + return -1; +} + +#define ssl_cipher_info_lookup(table, x) \ + ssl_cipher_info_find(table, OSSL_NELEM(table), x) + +/* + * PKEY_TYPE for GOST89MAC is known in advance, but, because implementation + * is engine-provided, we'll fill it only if corresponding EVP_PKEY_METHOD is + * found + */ +static int ssl_mac_pkey_id[SSL_MD_NUM_IDX] = { + /* MD5, SHA, GOST94, MAC89 */ + EVP_PKEY_HMAC, EVP_PKEY_HMAC, EVP_PKEY_HMAC, NID_undef, + /* SHA256, SHA384, GOST2012_256, MAC89-12 */ + EVP_PKEY_HMAC, EVP_PKEY_HMAC, EVP_PKEY_HMAC, NID_undef, + /* GOST2012_512 */ + EVP_PKEY_HMAC, + /* MD5/SHA1, SHA224, SHA512 */ + NID_undef, NID_undef, NID_undef +}; + +static size_t ssl_mac_secret_size[SSL_MD_NUM_IDX]; + +#define CIPHER_ADD 1 +#define CIPHER_KILL 2 +#define CIPHER_DEL 3 +#define CIPHER_ORD 4 +#define CIPHER_SPECIAL 5 +/* + * Bump the ciphers to the top of the list. + * This rule isn't currently supported by the public cipherstring API. + */ +#define CIPHER_BUMP 6 + +typedef struct cipher_order_st { + const SSL_CIPHER *cipher; + int active; + int dead; + struct cipher_order_st *next, *prev; +} CIPHER_ORDER; + +static const SSL_CIPHER cipher_aliases[] = { + /* "ALL" doesn't include eNULL (must be specifically enabled) */ + {0, SSL_TXT_ALL, NULL, 0, 0, 0, ~SSL_eNULL}, + /* "COMPLEMENTOFALL" */ + {0, SSL_TXT_CMPALL, NULL, 0, 0, 0, SSL_eNULL}, + + /* + * "COMPLEMENTOFDEFAULT" (does *not* include ciphersuites not found in + * ALL!) + */ + {0, SSL_TXT_CMPDEF, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, SSL_NOT_DEFAULT}, + + /* + * key exchange aliases (some of those using only a single bit here + * combine multiple key exchange algs according to the RFCs, e.g. kDHE + * combines DHE_DSS and DHE_RSA) + */ + {0, SSL_TXT_kRSA, NULL, 0, SSL_kRSA}, + + {0, SSL_TXT_kEDH, NULL, 0, SSL_kDHE}, + {0, SSL_TXT_kDHE, NULL, 0, SSL_kDHE}, + {0, SSL_TXT_DH, NULL, 0, SSL_kDHE}, + + {0, SSL_TXT_kEECDH, NULL, 0, SSL_kECDHE}, + {0, SSL_TXT_kECDHE, NULL, 0, SSL_kECDHE}, + {0, SSL_TXT_ECDH, NULL, 0, SSL_kECDHE}, + + {0, SSL_TXT_kPSK, NULL, 0, SSL_kPSK}, + {0, SSL_TXT_kRSAPSK, NULL, 0, SSL_kRSAPSK}, + {0, SSL_TXT_kECDHEPSK, NULL, 0, SSL_kECDHEPSK}, + {0, SSL_TXT_kDHEPSK, NULL, 0, SSL_kDHEPSK}, + {0, SSL_TXT_kSRP, NULL, 0, SSL_kSRP}, + {0, SSL_TXT_kGOST, NULL, 0, SSL_kGOST}, + + /* server authentication aliases */ + {0, SSL_TXT_aRSA, NULL, 0, 0, SSL_aRSA}, + {0, SSL_TXT_aDSS, NULL, 0, 0, SSL_aDSS}, + {0, SSL_TXT_DSS, NULL, 0, 0, SSL_aDSS}, + {0, SSL_TXT_aNULL, NULL, 0, 0, SSL_aNULL}, + {0, SSL_TXT_aECDSA, NULL, 0, 0, SSL_aECDSA}, + {0, SSL_TXT_ECDSA, NULL, 0, 0, SSL_aECDSA}, + {0, SSL_TXT_aPSK, NULL, 0, 0, SSL_aPSK}, + {0, SSL_TXT_aGOST01, NULL, 0, 0, SSL_aGOST01}, + {0, SSL_TXT_aGOST12, NULL, 0, 0, SSL_aGOST12}, + {0, SSL_TXT_aGOST, NULL, 0, 0, SSL_aGOST01 | SSL_aGOST12}, + {0, SSL_TXT_aSRP, NULL, 0, 0, SSL_aSRP}, + + /* aliases combining key exchange and server authentication */ + {0, SSL_TXT_EDH, NULL, 0, SSL_kDHE, ~SSL_aNULL}, + {0, SSL_TXT_DHE, NULL, 0, SSL_kDHE, ~SSL_aNULL}, + {0, SSL_TXT_EECDH, NULL, 0, SSL_kECDHE, ~SSL_aNULL}, + {0, SSL_TXT_ECDHE, NULL, 0, SSL_kECDHE, ~SSL_aNULL}, + {0, SSL_TXT_NULL, NULL, 0, 0, 0, SSL_eNULL}, + {0, SSL_TXT_RSA, NULL, 0, SSL_kRSA, SSL_aRSA}, + {0, SSL_TXT_ADH, NULL, 0, SSL_kDHE, SSL_aNULL}, + {0, SSL_TXT_AECDH, NULL, 0, SSL_kECDHE, SSL_aNULL}, + {0, SSL_TXT_PSK, NULL, 0, SSL_PSK}, + {0, SSL_TXT_SRP, NULL, 0, SSL_kSRP}, + + /* symmetric encryption aliases */ + {0, SSL_TXT_3DES, NULL, 0, 0, 0, SSL_3DES}, + {0, SSL_TXT_RC4, NULL, 0, 0, 0, SSL_RC4}, + {0, SSL_TXT_RC2, NULL, 0, 0, 0, SSL_RC2}, + {0, SSL_TXT_IDEA, NULL, 0, 0, 0, SSL_IDEA}, + {0, SSL_TXT_SEED, NULL, 0, 0, 0, SSL_SEED}, + {0, SSL_TXT_eNULL, NULL, 0, 0, 0, SSL_eNULL}, + {0, SSL_TXT_GOST, NULL, 0, 0, 0, SSL_eGOST2814789CNT | SSL_eGOST2814789CNT12}, + {0, SSL_TXT_AES128, NULL, 0, 0, 0, + SSL_AES128 | SSL_AES128GCM | SSL_AES128CCM | SSL_AES128CCM8}, + {0, SSL_TXT_AES256, NULL, 0, 0, 0, + SSL_AES256 | SSL_AES256GCM | SSL_AES256CCM | SSL_AES256CCM8}, + {0, SSL_TXT_AES, NULL, 0, 0, 0, SSL_AES}, + {0, SSL_TXT_AES_GCM, NULL, 0, 0, 0, SSL_AES128GCM | SSL_AES256GCM}, + {0, SSL_TXT_AES_CCM, NULL, 0, 0, 0, + SSL_AES128CCM | SSL_AES256CCM | SSL_AES128CCM8 | SSL_AES256CCM8}, + {0, SSL_TXT_AES_CCM_8, NULL, 0, 0, 0, SSL_AES128CCM8 | SSL_AES256CCM8}, + {0, SSL_TXT_CAMELLIA128, NULL, 0, 0, 0, SSL_CAMELLIA128}, + {0, SSL_TXT_CAMELLIA256, NULL, 0, 0, 0, SSL_CAMELLIA256}, + {0, SSL_TXT_CAMELLIA, NULL, 0, 0, 0, SSL_CAMELLIA}, + {0, SSL_TXT_CHACHA20, NULL, 0, 0, 0, SSL_CHACHA20}, + + {0, SSL_TXT_ARIA, NULL, 0, 0, 0, SSL_ARIA}, + {0, SSL_TXT_ARIA_GCM, NULL, 0, 0, 0, SSL_ARIA128GCM | SSL_ARIA256GCM}, + {0, SSL_TXT_ARIA128, NULL, 0, 0, 0, SSL_ARIA128GCM}, + {0, SSL_TXT_ARIA256, NULL, 0, 0, 0, SSL_ARIA256GCM}, + + /* MAC aliases */ + {0, SSL_TXT_MD5, NULL, 0, 0, 0, 0, SSL_MD5}, + {0, SSL_TXT_SHA1, NULL, 0, 0, 0, 0, SSL_SHA1}, + {0, SSL_TXT_SHA, NULL, 0, 0, 0, 0, SSL_SHA1}, + {0, SSL_TXT_GOST94, NULL, 0, 0, 0, 0, SSL_GOST94}, + {0, SSL_TXT_GOST89MAC, NULL, 0, 0, 0, 0, SSL_GOST89MAC | SSL_GOST89MAC12}, + {0, SSL_TXT_SHA256, NULL, 0, 0, 0, 0, SSL_SHA256}, + {0, SSL_TXT_SHA384, NULL, 0, 0, 0, 0, SSL_SHA384}, + {0, SSL_TXT_GOST12, NULL, 0, 0, 0, 0, SSL_GOST12_256}, + + /* protocol version aliases */ + {0, SSL_TXT_SSLV3, NULL, 0, 0, 0, 0, 0, SSL3_VERSION}, + {0, SSL_TXT_TLSV1, NULL, 0, 0, 0, 0, 0, TLS1_VERSION}, + {0, "TLSv1.0", NULL, 0, 0, 0, 0, 0, TLS1_VERSION}, + {0, SSL_TXT_TLSV1_2, NULL, 0, 0, 0, 0, 0, TLS1_2_VERSION}, + + /* strength classes */ + {0, SSL_TXT_LOW, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, SSL_LOW}, + {0, SSL_TXT_MEDIUM, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, SSL_MEDIUM}, + {0, SSL_TXT_HIGH, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, SSL_HIGH}, + /* FIPS 140-2 approved ciphersuite */ + {0, SSL_TXT_FIPS, NULL, 0, 0, 0, ~SSL_eNULL, 0, 0, 0, 0, 0, SSL_FIPS}, + + /* "EDH-" aliases to "DHE-" labels (for backward compatibility) */ + {0, SSL3_TXT_EDH_DSS_DES_192_CBC3_SHA, NULL, 0, + SSL_kDHE, SSL_aDSS, SSL_3DES, SSL_SHA1, 0, 0, 0, 0, SSL_HIGH | SSL_FIPS}, + {0, SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA, NULL, 0, + SSL_kDHE, SSL_aRSA, SSL_3DES, SSL_SHA1, 0, 0, 0, 0, SSL_HIGH | SSL_FIPS}, + +}; + +/* + * Search for public key algorithm with given name and return its pkey_id if + * it is available. Otherwise return 0 + */ +#ifdef OPENSSL_NO_ENGINE + +static int get_optional_pkey_id(const char *pkey_name) +{ + const EVP_PKEY_ASN1_METHOD *ameth; + int pkey_id = 0; + ameth = EVP_PKEY_asn1_find_str(NULL, pkey_name, -1); + if (ameth && EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, + ameth) > 0) + return pkey_id; + return 0; +} + +#else + +static int get_optional_pkey_id(const char *pkey_name) +{ + const EVP_PKEY_ASN1_METHOD *ameth; + ENGINE *tmpeng = NULL; + int pkey_id = 0; + ameth = EVP_PKEY_asn1_find_str(&tmpeng, pkey_name, -1); + if (ameth) { + if (EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, + ameth) <= 0) + pkey_id = 0; + } + ENGINE_finish(tmpeng); + return pkey_id; +} + +#endif + +/* masks of disabled algorithms */ +static uint32_t disabled_enc_mask; +static uint32_t disabled_mac_mask; +static uint32_t disabled_mkey_mask; +static uint32_t disabled_auth_mask; + +int ssl_load_ciphers(void) +{ + size_t i; + const ssl_cipher_table *t; + + disabled_enc_mask = 0; + ssl_sort_cipher_list(); + for (i = 0, t = ssl_cipher_table_cipher; i < SSL_ENC_NUM_IDX; i++, t++) { + if (t->nid == NID_undef) { + ssl_cipher_methods[i] = NULL; + } else { + const EVP_CIPHER *cipher = EVP_get_cipherbynid(t->nid); + ssl_cipher_methods[i] = cipher; + if (cipher == NULL) + disabled_enc_mask |= t->mask; + } + } + disabled_mac_mask = 0; + for (i = 0, t = ssl_cipher_table_mac; i < SSL_MD_NUM_IDX; i++, t++) { + const EVP_MD *md = EVP_get_digestbynid(t->nid); + ssl_digest_methods[i] = md; + if (md == NULL) { + disabled_mac_mask |= t->mask; + } else { + int tmpsize = EVP_MD_size(md); + if (!ossl_assert(tmpsize >= 0)) + return 0; + ssl_mac_secret_size[i] = tmpsize; + } + } + /* Make sure we can access MD5 and SHA1 */ + if (!ossl_assert(ssl_digest_methods[SSL_MD_MD5_IDX] != NULL)) + return 0; + if (!ossl_assert(ssl_digest_methods[SSL_MD_SHA1_IDX] != NULL)) + return 0; + + disabled_mkey_mask = 0; + disabled_auth_mask = 0; + +#ifdef OPENSSL_NO_RSA + disabled_mkey_mask |= SSL_kRSA | SSL_kRSAPSK; + disabled_auth_mask |= SSL_aRSA; +#endif +#ifdef OPENSSL_NO_DSA + disabled_auth_mask |= SSL_aDSS; +#endif +#ifdef OPENSSL_NO_DH + disabled_mkey_mask |= SSL_kDHE | SSL_kDHEPSK; +#endif +#ifdef OPENSSL_NO_EC + disabled_mkey_mask |= SSL_kECDHE | SSL_kECDHEPSK; + disabled_auth_mask |= SSL_aECDSA; +#endif +#ifdef OPENSSL_NO_PSK + disabled_mkey_mask |= SSL_PSK; + disabled_auth_mask |= SSL_aPSK; +#endif +#ifdef OPENSSL_NO_SRP + disabled_mkey_mask |= SSL_kSRP; +#endif + + /* + * Check for presence of GOST 34.10 algorithms, and if they are not + * present, disable appropriate auth and key exchange + */ + ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX] = get_optional_pkey_id("gost-mac"); + if (ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX]) + ssl_mac_secret_size[SSL_MD_GOST89MAC_IDX] = 32; + else + disabled_mac_mask |= SSL_GOST89MAC; + + ssl_mac_pkey_id[SSL_MD_GOST89MAC12_IDX] = + get_optional_pkey_id("gost-mac-12"); + if (ssl_mac_pkey_id[SSL_MD_GOST89MAC12_IDX]) + ssl_mac_secret_size[SSL_MD_GOST89MAC12_IDX] = 32; + else + disabled_mac_mask |= SSL_GOST89MAC12; + + if (!get_optional_pkey_id("gost2001")) + disabled_auth_mask |= SSL_aGOST01 | SSL_aGOST12; + if (!get_optional_pkey_id("gost2012_256")) + disabled_auth_mask |= SSL_aGOST12; + if (!get_optional_pkey_id("gost2012_512")) + disabled_auth_mask |= SSL_aGOST12; + /* + * Disable GOST key exchange if no GOST signature algs are available * + */ + if ((disabled_auth_mask & (SSL_aGOST01 | SSL_aGOST12)) == + (SSL_aGOST01 | SSL_aGOST12)) + disabled_mkey_mask |= SSL_kGOST; + + return 1; +} + +#ifndef OPENSSL_NO_COMP + +static int sk_comp_cmp(const SSL_COMP *const *a, const SSL_COMP *const *b) +{ + return ((*a)->id - (*b)->id); +} + +DEFINE_RUN_ONCE_STATIC(do_load_builtin_compressions) +{ + SSL_COMP *comp = NULL; + COMP_METHOD *method = COMP_zlib(); + + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE); + ssl_comp_methods = sk_SSL_COMP_new(sk_comp_cmp); + + if (COMP_get_type(method) != NID_undef && ssl_comp_methods != NULL) { + comp = OPENSSL_malloc(sizeof(*comp)); + if (comp != NULL) { + comp->method = method; + comp->id = SSL_COMP_ZLIB_IDX; + comp->name = COMP_get_name(method); + sk_SSL_COMP_push(ssl_comp_methods, comp); + sk_SSL_COMP_sort(ssl_comp_methods); + } + } + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE); + return 1; +} + +static int load_builtin_compressions(void) +{ + return RUN_ONCE(&ssl_load_builtin_comp_once, do_load_builtin_compressions); +} +#endif + +int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc, + const EVP_MD **md, int *mac_pkey_type, + size_t *mac_secret_size, SSL_COMP **comp, int use_etm) +{ + int i; + const SSL_CIPHER *c; + + c = s->cipher; + if (c == NULL) + return 0; + if (comp != NULL) { + SSL_COMP ctmp; +#ifndef OPENSSL_NO_COMP + if (!load_builtin_compressions()) { + /* + * Currently don't care, since a failure only means that + * ssl_comp_methods is NULL, which is perfectly OK + */ + } +#endif + *comp = NULL; + ctmp.id = s->compress_meth; + if (ssl_comp_methods != NULL) { + i = sk_SSL_COMP_find(ssl_comp_methods, &ctmp); + *comp = sk_SSL_COMP_value(ssl_comp_methods, i); + } + /* If were only interested in comp then return success */ + if ((enc == NULL) && (md == NULL)) + return 1; + } + + if ((enc == NULL) || (md == NULL)) + return 0; + + i = ssl_cipher_info_lookup(ssl_cipher_table_cipher, c->algorithm_enc); + + if (i == -1) { + *enc = NULL; + } else { + if (i == SSL_ENC_NULL_IDX) + *enc = EVP_enc_null(); + else + *enc = ssl_cipher_methods[i]; + } + + i = ssl_cipher_info_lookup(ssl_cipher_table_mac, c->algorithm_mac); + if (i == -1) { + *md = NULL; + if (mac_pkey_type != NULL) + *mac_pkey_type = NID_undef; + if (mac_secret_size != NULL) + *mac_secret_size = 0; + if (c->algorithm_mac == SSL_AEAD) + mac_pkey_type = NULL; + } else { + *md = ssl_digest_methods[i]; + if (mac_pkey_type != NULL) + *mac_pkey_type = ssl_mac_pkey_id[i]; + if (mac_secret_size != NULL) + *mac_secret_size = ssl_mac_secret_size[i]; + } + + if ((*enc != NULL) && + (*md != NULL || (EVP_CIPHER_flags(*enc) & EVP_CIPH_FLAG_AEAD_CIPHER)) + && (!mac_pkey_type || *mac_pkey_type != NID_undef)) { + const EVP_CIPHER *evp; + + if (use_etm) + return 1; + + if (s->ssl_version >> 8 != TLS1_VERSION_MAJOR || + s->ssl_version < TLS1_VERSION) + return 1; + + if (c->algorithm_enc == SSL_RC4 && + c->algorithm_mac == SSL_MD5 && + (evp = EVP_get_cipherbyname("RC4-HMAC-MD5"))) + *enc = evp, *md = NULL; + else if (c->algorithm_enc == SSL_AES128 && + c->algorithm_mac == SSL_SHA1 && + (evp = EVP_get_cipherbyname("AES-128-CBC-HMAC-SHA1"))) + *enc = evp, *md = NULL; + else if (c->algorithm_enc == SSL_AES256 && + c->algorithm_mac == SSL_SHA1 && + (evp = EVP_get_cipherbyname("AES-256-CBC-HMAC-SHA1"))) + *enc = evp, *md = NULL; + else if (c->algorithm_enc == SSL_AES128 && + c->algorithm_mac == SSL_SHA256 && + (evp = EVP_get_cipherbyname("AES-128-CBC-HMAC-SHA256"))) + *enc = evp, *md = NULL; + else if (c->algorithm_enc == SSL_AES256 && + c->algorithm_mac == SSL_SHA256 && + (evp = EVP_get_cipherbyname("AES-256-CBC-HMAC-SHA256"))) + *enc = evp, *md = NULL; + return 1; + } else { + return 0; + } +} + +const EVP_MD *ssl_md(int idx) +{ + idx &= SSL_HANDSHAKE_MAC_MASK; + if (idx < 0 || idx >= SSL_MD_NUM_IDX) + return NULL; + return ssl_digest_methods[idx]; +} + +const EVP_MD *ssl_handshake_md(SSL *s) +{ + return ssl_md(ssl_get_algorithm2(s)); +} + +const EVP_MD *ssl_prf_md(SSL *s) +{ + return ssl_md(ssl_get_algorithm2(s) >> TLS1_PRF_DGST_SHIFT); +} + +#define ITEM_SEP(a) \ + (((a) == ':') || ((a) == ' ') || ((a) == ';') || ((a) == ',')) + +static void ll_append_tail(CIPHER_ORDER **head, CIPHER_ORDER *curr, + CIPHER_ORDER **tail) +{ + if (curr == *tail) + return; + if (curr == *head) + *head = curr->next; + if (curr->prev != NULL) + curr->prev->next = curr->next; + if (curr->next != NULL) + curr->next->prev = curr->prev; + (*tail)->next = curr; + curr->prev = *tail; + curr->next = NULL; + *tail = curr; +} + +static void ll_append_head(CIPHER_ORDER **head, CIPHER_ORDER *curr, + CIPHER_ORDER **tail) +{ + if (curr == *head) + return; + if (curr == *tail) + *tail = curr->prev; + if (curr->next != NULL) + curr->next->prev = curr->prev; + if (curr->prev != NULL) + curr->prev->next = curr->next; + (*head)->prev = curr; + curr->next = *head; + curr->prev = NULL; + *head = curr; +} + +static void ssl_cipher_collect_ciphers(const SSL_METHOD *ssl_method, + int num_of_ciphers, + uint32_t disabled_mkey, + uint32_t disabled_auth, + uint32_t disabled_enc, + uint32_t disabled_mac, + CIPHER_ORDER *co_list, + CIPHER_ORDER **head_p, + CIPHER_ORDER **tail_p) +{ + int i, co_list_num; + const SSL_CIPHER *c; + + /* + * We have num_of_ciphers descriptions compiled in, depending on the + * method selected (SSLv3, TLSv1 etc). + * These will later be sorted in a linked list with at most num + * entries. + */ + + /* Get the initial list of ciphers */ + co_list_num = 0; /* actual count of ciphers */ + for (i = 0; i < num_of_ciphers; i++) { + c = ssl_method->get_cipher(i); + /* drop those that use any of that is not available */ + if (c == NULL || !c->valid) + continue; + if ((c->algorithm_mkey & disabled_mkey) || + (c->algorithm_auth & disabled_auth) || + (c->algorithm_enc & disabled_enc) || + (c->algorithm_mac & disabled_mac)) + continue; + if (((ssl_method->ssl3_enc->enc_flags & SSL_ENC_FLAG_DTLS) == 0) && + c->min_tls == 0) + continue; + if (((ssl_method->ssl3_enc->enc_flags & SSL_ENC_FLAG_DTLS) != 0) && + c->min_dtls == 0) + continue; + + co_list[co_list_num].cipher = c; + co_list[co_list_num].next = NULL; + co_list[co_list_num].prev = NULL; + co_list[co_list_num].active = 0; + co_list_num++; + } + + /* + * Prepare linked list from list entries + */ + if (co_list_num > 0) { + co_list[0].prev = NULL; + + if (co_list_num > 1) { + co_list[0].next = &co_list[1]; + + for (i = 1; i < co_list_num - 1; i++) { + co_list[i].prev = &co_list[i - 1]; + co_list[i].next = &co_list[i + 1]; + } + + co_list[co_list_num - 1].prev = &co_list[co_list_num - 2]; + } + + co_list[co_list_num - 1].next = NULL; + + *head_p = &co_list[0]; + *tail_p = &co_list[co_list_num - 1]; + } +} + +static void ssl_cipher_collect_aliases(const SSL_CIPHER **ca_list, + int num_of_group_aliases, + uint32_t disabled_mkey, + uint32_t disabled_auth, + uint32_t disabled_enc, + uint32_t disabled_mac, + CIPHER_ORDER *head) +{ + CIPHER_ORDER *ciph_curr; + const SSL_CIPHER **ca_curr; + int i; + uint32_t mask_mkey = ~disabled_mkey; + uint32_t mask_auth = ~disabled_auth; + uint32_t mask_enc = ~disabled_enc; + uint32_t mask_mac = ~disabled_mac; + + /* + * First, add the real ciphers as already collected + */ + ciph_curr = head; + ca_curr = ca_list; + while (ciph_curr != NULL) { + *ca_curr = ciph_curr->cipher; + ca_curr++; + ciph_curr = ciph_curr->next; + } + + /* + * Now we add the available ones from the cipher_aliases[] table. + * They represent either one or more algorithms, some of which + * in any affected category must be supported (set in enabled_mask), + * or represent a cipher strength value (will be added in any case because algorithms=0). + */ + for (i = 0; i < num_of_group_aliases; i++) { + uint32_t algorithm_mkey = cipher_aliases[i].algorithm_mkey; + uint32_t algorithm_auth = cipher_aliases[i].algorithm_auth; + uint32_t algorithm_enc = cipher_aliases[i].algorithm_enc; + uint32_t algorithm_mac = cipher_aliases[i].algorithm_mac; + + if (algorithm_mkey) + if ((algorithm_mkey & mask_mkey) == 0) + continue; + + if (algorithm_auth) + if ((algorithm_auth & mask_auth) == 0) + continue; + + if (algorithm_enc) + if ((algorithm_enc & mask_enc) == 0) + continue; + + if (algorithm_mac) + if ((algorithm_mac & mask_mac) == 0) + continue; + + *ca_curr = (SSL_CIPHER *)(cipher_aliases + i); + ca_curr++; + } + + *ca_curr = NULL; /* end of list */ +} + +static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey, + uint32_t alg_auth, uint32_t alg_enc, + uint32_t alg_mac, int min_tls, + uint32_t algo_strength, int rule, + int32_t strength_bits, CIPHER_ORDER **head_p, + CIPHER_ORDER **tail_p) +{ + CIPHER_ORDER *head, *tail, *curr, *next, *last; + const SSL_CIPHER *cp; + int reverse = 0; + +#ifdef CIPHER_DEBUG + fprintf(stderr, + "Applying rule %d with %08x/%08x/%08x/%08x/%08x %08x (%d)\n", + rule, alg_mkey, alg_auth, alg_enc, alg_mac, min_tls, + algo_strength, strength_bits); +#endif + + if (rule == CIPHER_DEL || rule == CIPHER_BUMP) + reverse = 1; /* needed to maintain sorting between currently + * deleted ciphers */ + + head = *head_p; + tail = *tail_p; + + if (reverse) { + next = tail; + last = head; + } else { + next = head; + last = tail; + } + + curr = NULL; + for (;;) { + if (curr == last) + break; + + curr = next; + + if (curr == NULL) + break; + + next = reverse ? curr->prev : curr->next; + + cp = curr->cipher; + + /* + * Selection criteria is either the value of strength_bits + * or the algorithms used. + */ + if (strength_bits >= 0) { + if (strength_bits != cp->strength_bits) + continue; + } else { +#ifdef CIPHER_DEBUG + fprintf(stderr, + "\nName: %s:\nAlgo = %08x/%08x/%08x/%08x/%08x Algo_strength = %08x\n", + cp->name, cp->algorithm_mkey, cp->algorithm_auth, + cp->algorithm_enc, cp->algorithm_mac, cp->min_tls, + cp->algo_strength); +#endif + if (cipher_id != 0 && (cipher_id != cp->id)) + continue; + if (alg_mkey && !(alg_mkey & cp->algorithm_mkey)) + continue; + if (alg_auth && !(alg_auth & cp->algorithm_auth)) + continue; + if (alg_enc && !(alg_enc & cp->algorithm_enc)) + continue; + if (alg_mac && !(alg_mac & cp->algorithm_mac)) + continue; + if (min_tls && (min_tls != cp->min_tls)) + continue; + if ((algo_strength & SSL_STRONG_MASK) + && !(algo_strength & SSL_STRONG_MASK & cp->algo_strength)) + continue; + if ((algo_strength & SSL_DEFAULT_MASK) + && !(algo_strength & SSL_DEFAULT_MASK & cp->algo_strength)) + continue; + } + +#ifdef CIPHER_DEBUG + fprintf(stderr, "Action = %d\n", rule); +#endif + + /* add the cipher if it has not been added yet. */ + if (rule == CIPHER_ADD) { + /* reverse == 0 */ + if (!curr->active) { + ll_append_tail(&head, curr, &tail); + curr->active = 1; + } + } + /* Move the added cipher to this location */ + else if (rule == CIPHER_ORD) { + /* reverse == 0 */ + if (curr->active) { + ll_append_tail(&head, curr, &tail); + } + } else if (rule == CIPHER_DEL) { + /* reverse == 1 */ + if (curr->active) { + /* + * most recently deleted ciphersuites get best positions for + * any future CIPHER_ADD (note that the CIPHER_DEL loop works + * in reverse to maintain the order) + */ + ll_append_head(&head, curr, &tail); + curr->active = 0; + } + } else if (rule == CIPHER_BUMP) { + if (curr->active) + ll_append_head(&head, curr, &tail); + } else if (rule == CIPHER_KILL) { + /* reverse == 0 */ + if (head == curr) + head = curr->next; + else + curr->prev->next = curr->next; + if (tail == curr) + tail = curr->prev; + curr->active = 0; + if (curr->next != NULL) + curr->next->prev = curr->prev; + if (curr->prev != NULL) + curr->prev->next = curr->next; + curr->next = NULL; + curr->prev = NULL; + } + } + + *head_p = head; + *tail_p = tail; +} + +static int ssl_cipher_strength_sort(CIPHER_ORDER **head_p, + CIPHER_ORDER **tail_p) +{ + int32_t max_strength_bits; + int i, *number_uses; + CIPHER_ORDER *curr; + + /* + * This routine sorts the ciphers with descending strength. The sorting + * must keep the pre-sorted sequence, so we apply the normal sorting + * routine as '+' movement to the end of the list. + */ + max_strength_bits = 0; + curr = *head_p; + while (curr != NULL) { + if (curr->active && (curr->cipher->strength_bits > max_strength_bits)) + max_strength_bits = curr->cipher->strength_bits; + curr = curr->next; + } + + number_uses = OPENSSL_zalloc(sizeof(int) * (max_strength_bits + 1)); + if (number_uses == NULL) { + SSLerr(SSL_F_SSL_CIPHER_STRENGTH_SORT, ERR_R_MALLOC_FAILURE); + return 0; + } + + /* + * Now find the strength_bits values actually used + */ + curr = *head_p; + while (curr != NULL) { + if (curr->active) + number_uses[curr->cipher->strength_bits]++; + curr = curr->next; + } + /* + * Go through the list of used strength_bits values in descending + * order. + */ + for (i = max_strength_bits; i >= 0; i--) + if (number_uses[i] > 0) + ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ORD, i, head_p, + tail_p); + + OPENSSL_free(number_uses); + return 1; +} + +static int ssl_cipher_process_rulestr(const char *rule_str, + CIPHER_ORDER **head_p, + CIPHER_ORDER **tail_p, + const SSL_CIPHER **ca_list, CERT *c) +{ + uint32_t alg_mkey, alg_auth, alg_enc, alg_mac, algo_strength; + int min_tls; + const char *l, *buf; + int j, multi, found, rule, retval, ok, buflen; + uint32_t cipher_id = 0; + char ch; + + retval = 1; + l = rule_str; + for ( ; ; ) { + ch = *l; + + if (ch == '\0') + break; /* done */ + if (ch == '-') { + rule = CIPHER_DEL; + l++; + } else if (ch == '+') { + rule = CIPHER_ORD; + l++; + } else if (ch == '!') { + rule = CIPHER_KILL; + l++; + } else if (ch == '@') { + rule = CIPHER_SPECIAL; + l++; + } else { + rule = CIPHER_ADD; + } + + if (ITEM_SEP(ch)) { + l++; + continue; + } + + alg_mkey = 0; + alg_auth = 0; + alg_enc = 0; + alg_mac = 0; + min_tls = 0; + algo_strength = 0; + + for (;;) { + ch = *l; + buf = l; + buflen = 0; +#ifndef CHARSET_EBCDIC + while (((ch >= 'A') && (ch <= 'Z')) || + ((ch >= '0') && (ch <= '9')) || + ((ch >= 'a') && (ch <= 'z')) || + (ch == '-') || (ch == '.') || (ch == '=')) +#else + while (isalnum((unsigned char)ch) || (ch == '-') || (ch == '.') + || (ch == '=')) +#endif + { + ch = *(++l); + buflen++; + } + + if (buflen == 0) { + /* + * We hit something we cannot deal with, + * it is no command or separator nor + * alphanumeric, so we call this an error. + */ + SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR, SSL_R_INVALID_COMMAND); + retval = found = 0; + l++; + break; + } + + if (rule == CIPHER_SPECIAL) { + found = 0; /* unused -- avoid compiler warning */ + break; /* special treatment */ + } + + /* check for multi-part specification */ + if (ch == '+') { + multi = 1; + l++; + } else { + multi = 0; + } + + /* + * Now search for the cipher alias in the ca_list. Be careful + * with the strncmp, because the "buflen" limitation + * will make the rule "ADH:SOME" and the cipher + * "ADH-MY-CIPHER" look like a match for buflen=3. + * So additionally check whether the cipher name found + * has the correct length. We can save a strlen() call: + * just checking for the '\0' at the right place is + * sufficient, we have to strncmp() anyway. (We cannot + * use strcmp(), because buf is not '\0' terminated.) + */ + j = found = 0; + cipher_id = 0; + while (ca_list[j]) { + if (strncmp(buf, ca_list[j]->name, buflen) == 0 + && (ca_list[j]->name[buflen] == '\0')) { + found = 1; + break; + } else + j++; + } + + if (!found) + break; /* ignore this entry */ + + if (ca_list[j]->algorithm_mkey) { + if (alg_mkey) { + alg_mkey &= ca_list[j]->algorithm_mkey; + if (!alg_mkey) { + found = 0; + break; + } + } else { + alg_mkey = ca_list[j]->algorithm_mkey; + } + } + + if (ca_list[j]->algorithm_auth) { + if (alg_auth) { + alg_auth &= ca_list[j]->algorithm_auth; + if (!alg_auth) { + found = 0; + break; + } + } else { + alg_auth = ca_list[j]->algorithm_auth; + } + } + + if (ca_list[j]->algorithm_enc) { + if (alg_enc) { + alg_enc &= ca_list[j]->algorithm_enc; + if (!alg_enc) { + found = 0; + break; + } + } else { + alg_enc = ca_list[j]->algorithm_enc; + } + } + + if (ca_list[j]->algorithm_mac) { + if (alg_mac) { + alg_mac &= ca_list[j]->algorithm_mac; + if (!alg_mac) { + found = 0; + break; + } + } else { + alg_mac = ca_list[j]->algorithm_mac; + } + } + + if (ca_list[j]->algo_strength & SSL_STRONG_MASK) { + if (algo_strength & SSL_STRONG_MASK) { + algo_strength &= + (ca_list[j]->algo_strength & SSL_STRONG_MASK) | + ~SSL_STRONG_MASK; + if (!(algo_strength & SSL_STRONG_MASK)) { + found = 0; + break; + } + } else { + algo_strength = ca_list[j]->algo_strength & SSL_STRONG_MASK; + } + } + + if (ca_list[j]->algo_strength & SSL_DEFAULT_MASK) { + if (algo_strength & SSL_DEFAULT_MASK) { + algo_strength &= + (ca_list[j]->algo_strength & SSL_DEFAULT_MASK) | + ~SSL_DEFAULT_MASK; + if (!(algo_strength & SSL_DEFAULT_MASK)) { + found = 0; + break; + } + } else { + algo_strength |= + ca_list[j]->algo_strength & SSL_DEFAULT_MASK; + } + } + + if (ca_list[j]->valid) { + /* + * explicit ciphersuite found; its protocol version does not + * become part of the search pattern! + */ + + cipher_id = ca_list[j]->id; + } else { + /* + * not an explicit ciphersuite; only in this case, the + * protocol version is considered part of the search pattern + */ + + if (ca_list[j]->min_tls) { + if (min_tls != 0 && min_tls != ca_list[j]->min_tls) { + found = 0; + break; + } else { + min_tls = ca_list[j]->min_tls; + } + } + } + + if (!multi) + break; + } + + /* + * Ok, we have the rule, now apply it + */ + if (rule == CIPHER_SPECIAL) { /* special command */ + ok = 0; + if ((buflen == 8) && strncmp(buf, "STRENGTH", 8) == 0) { + ok = ssl_cipher_strength_sort(head_p, tail_p); + } else if (buflen == 10 && strncmp(buf, "SECLEVEL=", 9) == 0) { + int level = buf[9] - '0'; + if (level < 0 || level > 5) { + SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR, + SSL_R_INVALID_COMMAND); + } else { + c->sec_level = level; + ok = 1; + } + } else { + SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR, SSL_R_INVALID_COMMAND); + } + if (ok == 0) + retval = 0; + /* + * We do not support any "multi" options + * together with "@", so throw away the + * rest of the command, if any left, until + * end or ':' is found. + */ + while ((*l != '\0') && !ITEM_SEP(*l)) + l++; + } else if (found) { + ssl_cipher_apply_rule(cipher_id, + alg_mkey, alg_auth, alg_enc, alg_mac, + min_tls, algo_strength, rule, -1, head_p, + tail_p); + } else { + while ((*l != '\0') && !ITEM_SEP(*l)) + l++; + } + if (*l == '\0') + break; /* done */ + } + + return retval; +} + +#ifndef OPENSSL_NO_EC +static int check_suiteb_cipher_list(const SSL_METHOD *meth, CERT *c, + const char **prule_str) +{ + unsigned int suiteb_flags = 0, suiteb_comb2 = 0; + if (strncmp(*prule_str, "SUITEB128ONLY", 13) == 0) { + suiteb_flags = SSL_CERT_FLAG_SUITEB_128_LOS_ONLY; + } else if (strncmp(*prule_str, "SUITEB128C2", 11) == 0) { + suiteb_comb2 = 1; + suiteb_flags = SSL_CERT_FLAG_SUITEB_128_LOS; + } else if (strncmp(*prule_str, "SUITEB128", 9) == 0) { + suiteb_flags = SSL_CERT_FLAG_SUITEB_128_LOS; + } else if (strncmp(*prule_str, "SUITEB192", 9) == 0) { + suiteb_flags = SSL_CERT_FLAG_SUITEB_192_LOS; + } + + if (suiteb_flags) { + c->cert_flags &= ~SSL_CERT_FLAG_SUITEB_128_LOS; + c->cert_flags |= suiteb_flags; + } else { + suiteb_flags = c->cert_flags & SSL_CERT_FLAG_SUITEB_128_LOS; + } + + if (!suiteb_flags) + return 1; + /* Check version: if TLS 1.2 ciphers allowed we can use Suite B */ + + if (!(meth->ssl3_enc->enc_flags & SSL_ENC_FLAG_TLS1_2_CIPHERS)) { + SSLerr(SSL_F_CHECK_SUITEB_CIPHER_LIST, + SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE); + return 0; + } +# ifndef OPENSSL_NO_EC + switch (suiteb_flags) { + case SSL_CERT_FLAG_SUITEB_128_LOS: + if (suiteb_comb2) + *prule_str = "ECDHE-ECDSA-AES256-GCM-SHA384"; + else + *prule_str = + "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384"; + break; + case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY: + *prule_str = "ECDHE-ECDSA-AES128-GCM-SHA256"; + break; + case SSL_CERT_FLAG_SUITEB_192_LOS: + *prule_str = "ECDHE-ECDSA-AES256-GCM-SHA384"; + break; + } + return 1; +# else + SSLerr(SSL_F_CHECK_SUITEB_CIPHER_LIST, SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE); + return 0; +# endif +} +#endif + +static int ciphersuite_cb(const char *elem, int len, void *arg) +{ + STACK_OF(SSL_CIPHER) *ciphersuites = (STACK_OF(SSL_CIPHER) *)arg; + const SSL_CIPHER *cipher; + /* Arbitrary sized temp buffer for the cipher name. Should be big enough */ + char name[80]; + + if (len > (int)(sizeof(name) - 1)) { + SSLerr(SSL_F_CIPHERSUITE_CB, SSL_R_NO_CIPHER_MATCH); + return 0; + } + + memcpy(name, elem, len); + name[len] = '\0'; + + cipher = ssl3_get_cipher_by_std_name(name); + if (cipher == NULL) { + SSLerr(SSL_F_CIPHERSUITE_CB, SSL_R_NO_CIPHER_MATCH); + return 0; + } + + if (!sk_SSL_CIPHER_push(ciphersuites, cipher)) { + SSLerr(SSL_F_CIPHERSUITE_CB, ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} + +static __owur int set_ciphersuites(STACK_OF(SSL_CIPHER) **currciphers, const char *str) +{ + STACK_OF(SSL_CIPHER) *newciphers = sk_SSL_CIPHER_new_null(); + + if (newciphers == NULL) + return 0; + + /* Parse the list. We explicitly allow an empty list */ + if (*str != '\0' + && !CONF_parse_list(str, ':', 1, ciphersuite_cb, newciphers)) { + sk_SSL_CIPHER_free(newciphers); + return 0; + } + sk_SSL_CIPHER_free(*currciphers); + *currciphers = newciphers; + + return 1; +} + +static int update_cipher_list_by_id(STACK_OF(SSL_CIPHER) **cipher_list_by_id, + STACK_OF(SSL_CIPHER) *cipherstack) +{ + STACK_OF(SSL_CIPHER) *tmp_cipher_list = sk_SSL_CIPHER_dup(cipherstack); + + if (tmp_cipher_list == NULL) { + return 0; + } + + sk_SSL_CIPHER_free(*cipher_list_by_id); + *cipher_list_by_id = tmp_cipher_list; + + (void)sk_SSL_CIPHER_set_cmp_func(*cipher_list_by_id, ssl_cipher_ptr_id_cmp); + sk_SSL_CIPHER_sort(*cipher_list_by_id); + + return 1; +} + +static int update_cipher_list(STACK_OF(SSL_CIPHER) **cipher_list, + STACK_OF(SSL_CIPHER) **cipher_list_by_id, + STACK_OF(SSL_CIPHER) *tls13_ciphersuites) +{ + int i; + STACK_OF(SSL_CIPHER) *tmp_cipher_list = sk_SSL_CIPHER_dup(*cipher_list); + + if (tmp_cipher_list == NULL) + return 0; + + /* + * Delete any existing TLSv1.3 ciphersuites. These are always first in the + * list. + */ + while (sk_SSL_CIPHER_num(tmp_cipher_list) > 0 + && sk_SSL_CIPHER_value(tmp_cipher_list, 0)->min_tls + == TLS1_3_VERSION) + sk_SSL_CIPHER_delete(tmp_cipher_list, 0); + + /* Insert the new TLSv1.3 ciphersuites */ + for (i = 0; i < sk_SSL_CIPHER_num(tls13_ciphersuites); i++) + sk_SSL_CIPHER_insert(tmp_cipher_list, + sk_SSL_CIPHER_value(tls13_ciphersuites, i), i); + + if (!update_cipher_list_by_id(cipher_list_by_id, tmp_cipher_list)) + return 0; + + sk_SSL_CIPHER_free(*cipher_list); + *cipher_list = tmp_cipher_list; + + return 1; +} + +int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str) +{ + int ret = set_ciphersuites(&(ctx->tls13_ciphersuites), str); + + if (ret && ctx->cipher_list != NULL) { + /* We already have a cipher_list, so we need to update it */ + return update_cipher_list(&ctx->cipher_list, &ctx->cipher_list_by_id, + ctx->tls13_ciphersuites); + } + + return ret; +} + +int SSL_set_ciphersuites(SSL *s, const char *str) +{ + int ret = set_ciphersuites(&(s->tls13_ciphersuites), str); + + if (ret && s->cipher_list != NULL) { + /* We already have a cipher_list, so we need to update it */ + return update_cipher_list(&s->cipher_list, &s->cipher_list_by_id, + s->tls13_ciphersuites); + } + + return ret; +} + +STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, + STACK_OF(SSL_CIPHER) *tls13_ciphersuites, + STACK_OF(SSL_CIPHER) **cipher_list, + STACK_OF(SSL_CIPHER) **cipher_list_by_id, + const char *rule_str, + CERT *c) +{ + int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases, i; + uint32_t disabled_mkey, disabled_auth, disabled_enc, disabled_mac; + STACK_OF(SSL_CIPHER) *cipherstack; + const char *rule_p; + CIPHER_ORDER *co_list = NULL, *head = NULL, *tail = NULL, *curr; + const SSL_CIPHER **ca_list = NULL; + + /* + * Return with error if nothing to do. + */ + if (rule_str == NULL || cipher_list == NULL || cipher_list_by_id == NULL) + return NULL; +#ifndef OPENSSL_NO_EC + if (!check_suiteb_cipher_list(ssl_method, c, &rule_str)) + return NULL; +#endif + + /* + * To reduce the work to do we only want to process the compiled + * in algorithms, so we first get the mask of disabled ciphers. + */ + + disabled_mkey = disabled_mkey_mask; + disabled_auth = disabled_auth_mask; + disabled_enc = disabled_enc_mask; + disabled_mac = disabled_mac_mask; + + /* + * Now we have to collect the available ciphers from the compiled + * in ciphers. We cannot get more than the number compiled in, so + * it is used for allocation. + */ + num_of_ciphers = ssl_method->num_ciphers(); + + co_list = OPENSSL_malloc(sizeof(*co_list) * num_of_ciphers); + if (co_list == NULL) { + SSLerr(SSL_F_SSL_CREATE_CIPHER_LIST, ERR_R_MALLOC_FAILURE); + return NULL; /* Failure */ + } + + ssl_cipher_collect_ciphers(ssl_method, num_of_ciphers, + disabled_mkey, disabled_auth, disabled_enc, + disabled_mac, co_list, &head, &tail); + + /* Now arrange all ciphers by preference. */ + + /* + * Everything else being equal, prefer ephemeral ECDH over other key + * exchange mechanisms. + * For consistency, prefer ECDSA over RSA (though this only matters if the + * server has both certificates, and is using the DEFAULT, or a client + * preference). + */ + ssl_cipher_apply_rule(0, SSL_kECDHE, SSL_aECDSA, 0, 0, 0, 0, CIPHER_ADD, + -1, &head, &tail); + ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_ADD, -1, &head, + &tail); + ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head, + &tail); + + /* Within each strength group, we prefer GCM over CHACHA... */ + ssl_cipher_apply_rule(0, 0, 0, SSL_AESGCM, 0, 0, 0, CIPHER_ADD, -1, + &head, &tail); + ssl_cipher_apply_rule(0, 0, 0, SSL_CHACHA20, 0, 0, 0, CIPHER_ADD, -1, + &head, &tail); + + /* + * ...and generally, our preferred cipher is AES. + * Note that AEADs will be bumped to take preference after sorting by + * strength. + */ + ssl_cipher_apply_rule(0, 0, 0, SSL_AES ^ SSL_AESGCM, 0, 0, 0, CIPHER_ADD, + -1, &head, &tail); + + /* Temporarily enable everything else for sorting */ + ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ADD, -1, &head, &tail); + + /* Low priority for MD5 */ + ssl_cipher_apply_rule(0, 0, 0, 0, SSL_MD5, 0, 0, CIPHER_ORD, -1, &head, + &tail); + + /* + * Move anonymous ciphers to the end. Usually, these will remain + * disabled. (For applications that allow them, they aren't too bad, but + * we prefer authenticated ciphers.) + */ + ssl_cipher_apply_rule(0, 0, SSL_aNULL, 0, 0, 0, 0, CIPHER_ORD, -1, &head, + &tail); + + ssl_cipher_apply_rule(0, SSL_kRSA, 0, 0, 0, 0, 0, CIPHER_ORD, -1, &head, + &tail); + ssl_cipher_apply_rule(0, SSL_kPSK, 0, 0, 0, 0, 0, CIPHER_ORD, -1, &head, + &tail); + + /* RC4 is sort-of broken -- move to the end */ + ssl_cipher_apply_rule(0, 0, 0, SSL_RC4, 0, 0, 0, CIPHER_ORD, -1, &head, + &tail); + + /* + * Now sort by symmetric encryption strength. The above ordering remains + * in force within each class + */ + if (!ssl_cipher_strength_sort(&head, &tail)) { + OPENSSL_free(co_list); + return NULL; + } + + /* + * Partially overrule strength sort to prefer TLS 1.2 ciphers/PRFs. + * TODO(openssl-team): is there an easier way to accomplish all this? + */ + ssl_cipher_apply_rule(0, 0, 0, 0, 0, TLS1_2_VERSION, 0, CIPHER_BUMP, -1, + &head, &tail); + + /* + * Irrespective of strength, enforce the following order: + * (EC)DHE + AEAD > (EC)DHE > rest of AEAD > rest. + * Within each group, ciphers remain sorted by strength and previous + * preference, i.e., + * 1) ECDHE > DHE + * 2) GCM > CHACHA + * 3) AES > rest + * 4) TLS 1.2 > legacy + * + * Because we now bump ciphers to the top of the list, we proceed in + * reverse order of preference. + */ + ssl_cipher_apply_rule(0, 0, 0, 0, SSL_AEAD, 0, 0, CIPHER_BUMP, -1, + &head, &tail); + ssl_cipher_apply_rule(0, SSL_kDHE | SSL_kECDHE, 0, 0, 0, 0, 0, + CIPHER_BUMP, -1, &head, &tail); + ssl_cipher_apply_rule(0, SSL_kDHE | SSL_kECDHE, 0, 0, SSL_AEAD, 0, 0, + CIPHER_BUMP, -1, &head, &tail); + + /* Now disable everything (maintaining the ordering!) */ + ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head, &tail); + + /* + * We also need cipher aliases for selecting based on the rule_str. + * There might be two types of entries in the rule_str: 1) names + * of ciphers themselves 2) aliases for groups of ciphers. + * For 1) we need the available ciphers and for 2) the cipher + * groups of cipher_aliases added together in one list (otherwise + * we would be happy with just the cipher_aliases table). + */ + num_of_group_aliases = OSSL_NELEM(cipher_aliases); + num_of_alias_max = num_of_ciphers + num_of_group_aliases + 1; + ca_list = OPENSSL_malloc(sizeof(*ca_list) * num_of_alias_max); + if (ca_list == NULL) { + OPENSSL_free(co_list); + SSLerr(SSL_F_SSL_CREATE_CIPHER_LIST, ERR_R_MALLOC_FAILURE); + return NULL; /* Failure */ + } + ssl_cipher_collect_aliases(ca_list, num_of_group_aliases, + disabled_mkey, disabled_auth, disabled_enc, + disabled_mac, head); + + /* + * If the rule_string begins with DEFAULT, apply the default rule + * before using the (possibly available) additional rules. + */ + ok = 1; + rule_p = rule_str; + if (strncmp(rule_str, "DEFAULT", 7) == 0) { + ok = ssl_cipher_process_rulestr(SSL_DEFAULT_CIPHER_LIST, + &head, &tail, ca_list, c); + rule_p += 7; + if (*rule_p == ':') + rule_p++; + } + + if (ok && (strlen(rule_p) > 0)) + ok = ssl_cipher_process_rulestr(rule_p, &head, &tail, ca_list, c); + + OPENSSL_free(ca_list); /* Not needed anymore */ + + if (!ok) { /* Rule processing failure */ + OPENSSL_free(co_list); + return NULL; + } + + /* + * Allocate new "cipherstack" for the result, return with error + * if we cannot get one. + */ + if ((cipherstack = sk_SSL_CIPHER_new_null()) == NULL) { + OPENSSL_free(co_list); + return NULL; + } + + /* Add TLSv1.3 ciphers first - we always prefer those if possible */ + for (i = 0; i < sk_SSL_CIPHER_num(tls13_ciphersuites); i++) { + if (!sk_SSL_CIPHER_push(cipherstack, + sk_SSL_CIPHER_value(tls13_ciphersuites, i))) { + sk_SSL_CIPHER_free(cipherstack); + return NULL; + } + } + + /* + * The cipher selection for the list is done. The ciphers are added + * to the resulting precedence to the STACK_OF(SSL_CIPHER). + */ + for (curr = head; curr != NULL; curr = curr->next) { + if (curr->active) { + if (!sk_SSL_CIPHER_push(cipherstack, curr->cipher)) { + OPENSSL_free(co_list); + sk_SSL_CIPHER_free(cipherstack); + return NULL; + } +#ifdef CIPHER_DEBUG + fprintf(stderr, "<%s>\n", curr->cipher->name); +#endif + } + } + OPENSSL_free(co_list); /* Not needed any longer */ + + if (!update_cipher_list_by_id(cipher_list_by_id, cipherstack)) { + sk_SSL_CIPHER_free(cipherstack); + return NULL; + } + sk_SSL_CIPHER_free(*cipher_list); + *cipher_list = cipherstack; + + return cipherstack; +} + +char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len) +{ + const char *ver; + const char *kx, *au, *enc, *mac; + uint32_t alg_mkey, alg_auth, alg_enc, alg_mac; + static const char *format = "%-23s %s Kx=%-8s Au=%-4s Enc=%-9s Mac=%-4s\n"; + + if (buf == NULL) { + len = 128; + if ((buf = OPENSSL_malloc(len)) == NULL) { + SSLerr(SSL_F_SSL_CIPHER_DESCRIPTION, ERR_R_MALLOC_FAILURE); + return NULL; + } + } else if (len < 128) { + return NULL; + } + + alg_mkey = cipher->algorithm_mkey; + alg_auth = cipher->algorithm_auth; + alg_enc = cipher->algorithm_enc; + alg_mac = cipher->algorithm_mac; + + ver = ssl_protocol_to_string(cipher->min_tls); + + switch (alg_mkey) { + case SSL_kRSA: + kx = "RSA"; + break; + case SSL_kDHE: + kx = "DH"; + break; + case SSL_kECDHE: + kx = "ECDH"; + break; + case SSL_kPSK: + kx = "PSK"; + break; + case SSL_kRSAPSK: + kx = "RSAPSK"; + break; + case SSL_kECDHEPSK: + kx = "ECDHEPSK"; + break; + case SSL_kDHEPSK: + kx = "DHEPSK"; + break; + case SSL_kSRP: + kx = "SRP"; + break; + case SSL_kGOST: + kx = "GOST"; + break; + case SSL_kANY: + kx = "any"; + break; + default: + kx = "unknown"; + } + + switch (alg_auth) { + case SSL_aRSA: + au = "RSA"; + break; + case SSL_aDSS: + au = "DSS"; + break; + case SSL_aNULL: + au = "None"; + break; + case SSL_aECDSA: + au = "ECDSA"; + break; + case SSL_aPSK: + au = "PSK"; + break; + case SSL_aSRP: + au = "SRP"; + break; + case SSL_aGOST01: + au = "GOST01"; + break; + /* New GOST ciphersuites have both SSL_aGOST12 and SSL_aGOST01 bits */ + case (SSL_aGOST12 | SSL_aGOST01): + au = "GOST12"; + break; + case SSL_aANY: + au = "any"; + break; + default: + au = "unknown"; + break; + } + + switch (alg_enc) { + case SSL_DES: + enc = "DES(56)"; + break; + case SSL_3DES: + enc = "3DES(168)"; + break; + case SSL_RC4: + enc = "RC4(128)"; + break; + case SSL_RC2: + enc = "RC2(128)"; + break; + case SSL_IDEA: + enc = "IDEA(128)"; + break; + case SSL_eNULL: + enc = "None"; + break; + case SSL_AES128: + enc = "AES(128)"; + break; + case SSL_AES256: + enc = "AES(256)"; + break; + case SSL_AES128GCM: + enc = "AESGCM(128)"; + break; + case SSL_AES256GCM: + enc = "AESGCM(256)"; + break; + case SSL_AES128CCM: + enc = "AESCCM(128)"; + break; + case SSL_AES256CCM: + enc = "AESCCM(256)"; + break; + case SSL_AES128CCM8: + enc = "AESCCM8(128)"; + break; + case SSL_AES256CCM8: + enc = "AESCCM8(256)"; + break; + case SSL_CAMELLIA128: + enc = "Camellia(128)"; + break; + case SSL_CAMELLIA256: + enc = "Camellia(256)"; + break; + case SSL_ARIA128GCM: + enc = "ARIAGCM(128)"; + break; + case SSL_ARIA256GCM: + enc = "ARIAGCM(256)"; + break; + case SSL_SEED: + enc = "SEED(128)"; + break; + case SSL_eGOST2814789CNT: + case SSL_eGOST2814789CNT12: + enc = "GOST89(256)"; + break; + case SSL_CHACHA20POLY1305: + enc = "CHACHA20/POLY1305(256)"; + break; + default: + enc = "unknown"; + break; + } + + switch (alg_mac) { + case SSL_MD5: + mac = "MD5"; + break; + case SSL_SHA1: + mac = "SHA1"; + break; + case SSL_SHA256: + mac = "SHA256"; + break; + case SSL_SHA384: + mac = "SHA384"; + break; + case SSL_AEAD: + mac = "AEAD"; + break; + case SSL_GOST89MAC: + case SSL_GOST89MAC12: + mac = "GOST89"; + break; + case SSL_GOST94: + mac = "GOST94"; + break; + case SSL_GOST12_256: + case SSL_GOST12_512: + mac = "GOST2012"; + break; + default: + mac = "unknown"; + break; + } + + BIO_snprintf(buf, len, format, cipher->name, ver, kx, au, enc, mac); + + return buf; +} + +const char *SSL_CIPHER_get_version(const SSL_CIPHER *c) +{ + if (c == NULL) + return "(NONE)"; + + /* + * Backwards-compatibility crutch. In almost all contexts we report TLS + * 1.0 as "TLSv1", but for ciphers we report "TLSv1.0". + */ + if (c->min_tls == TLS1_VERSION) + return "TLSv1.0"; + return ssl_protocol_to_string(c->min_tls); +} + +/* return the actual cipher being used */ +const char *SSL_CIPHER_get_name(const SSL_CIPHER *c) +{ + if (c != NULL) + return c->name; + return "(NONE)"; +} + +/* return the actual cipher being used in RFC standard name */ +const char *SSL_CIPHER_standard_name(const SSL_CIPHER *c) +{ + if (c != NULL) + return c->stdname; + return "(NONE)"; +} + +/* return the OpenSSL name based on given RFC standard name */ +const char *OPENSSL_cipher_name(const char *stdname) +{ + const SSL_CIPHER *c; + + if (stdname == NULL) + return "(NONE)"; + c = ssl3_get_cipher_by_std_name(stdname); + return SSL_CIPHER_get_name(c); +} + +/* number of bits for symmetric cipher */ +int SSL_CIPHER_get_bits(const SSL_CIPHER *c, int *alg_bits) +{ + int ret = 0; + + if (c != NULL) { + if (alg_bits != NULL) + *alg_bits = (int)c->alg_bits; + ret = (int)c->strength_bits; + } + return ret; +} + +uint32_t SSL_CIPHER_get_id(const SSL_CIPHER *c) +{ + return c->id; +} + +uint16_t SSL_CIPHER_get_protocol_id(const SSL_CIPHER *c) +{ + return c->id & 0xFFFF; +} + +SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n) +{ + SSL_COMP *ctmp; + int i, nn; + + if ((n == 0) || (sk == NULL)) + return NULL; + nn = sk_SSL_COMP_num(sk); + for (i = 0; i < nn; i++) { + ctmp = sk_SSL_COMP_value(sk, i); + if (ctmp->id == n) + return ctmp; + } + return NULL; +} + +#ifdef OPENSSL_NO_COMP +STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void) +{ + return NULL; +} + +STACK_OF(SSL_COMP) *SSL_COMP_set0_compression_methods(STACK_OF(SSL_COMP) + *meths) +{ + return meths; +} + +int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm) +{ + return 1; +} + +#else +STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void) +{ + load_builtin_compressions(); + return ssl_comp_methods; +} + +STACK_OF(SSL_COMP) *SSL_COMP_set0_compression_methods(STACK_OF(SSL_COMP) + *meths) +{ + STACK_OF(SSL_COMP) *old_meths = ssl_comp_methods; + ssl_comp_methods = meths; + return old_meths; +} + +static void cmeth_free(SSL_COMP *cm) +{ + OPENSSL_free(cm); +} + +void ssl_comp_free_compression_methods_int(void) +{ + STACK_OF(SSL_COMP) *old_meths = ssl_comp_methods; + ssl_comp_methods = NULL; + sk_SSL_COMP_pop_free(old_meths, cmeth_free); +} + +int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm) +{ + SSL_COMP *comp; + + if (cm == NULL || COMP_get_type(cm) == NID_undef) + return 1; + + /*- + * According to draft-ietf-tls-compression-04.txt, the + * compression number ranges should be the following: + * + * 0 to 63: methods defined by the IETF + * 64 to 192: external party methods assigned by IANA + * 193 to 255: reserved for private use + */ + if (id < 193 || id > 255) { + SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD, + SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE); + return 1; + } + + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE); + comp = OPENSSL_malloc(sizeof(*comp)); + if (comp == NULL) { + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE); + SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD, ERR_R_MALLOC_FAILURE); + return 1; + } + + comp->id = id; + comp->method = cm; + load_builtin_compressions(); + if (ssl_comp_methods && sk_SSL_COMP_find(ssl_comp_methods, comp) >= 0) { + OPENSSL_free(comp); + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE); + SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD, + SSL_R_DUPLICATE_COMPRESSION_ID); + return 1; + } + if (ssl_comp_methods == NULL || !sk_SSL_COMP_push(ssl_comp_methods, comp)) { + OPENSSL_free(comp); + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE); + SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD, ERR_R_MALLOC_FAILURE); + return 1; + } + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE); + return 0; +} +#endif + +const char *SSL_COMP_get_name(const COMP_METHOD *comp) +{ +#ifndef OPENSSL_NO_COMP + return comp ? COMP_get_name(comp) : NULL; +#else + return NULL; +#endif +} + +const char *SSL_COMP_get0_name(const SSL_COMP *comp) +{ +#ifndef OPENSSL_NO_COMP + return comp->name; +#else + return NULL; +#endif +} + +int SSL_COMP_get_id(const SSL_COMP *comp) +{ +#ifndef OPENSSL_NO_COMP + return comp->id; +#else + return -1; +#endif +} + +const SSL_CIPHER *ssl_get_cipher_by_char(SSL *ssl, const unsigned char *ptr, + int all) +{ + const SSL_CIPHER *c = ssl->method->get_cipher_by_char(ptr); + + if (c == NULL || (!all && c->valid == 0)) + return NULL; + return c; +} + +const SSL_CIPHER *SSL_CIPHER_find(SSL *ssl, const unsigned char *ptr) +{ + return ssl->method->get_cipher_by_char(ptr); +} + +int SSL_CIPHER_get_cipher_nid(const SSL_CIPHER *c) +{ + int i; + if (c == NULL) + return NID_undef; + i = ssl_cipher_info_lookup(ssl_cipher_table_cipher, c->algorithm_enc); + if (i == -1) + return NID_undef; + return ssl_cipher_table_cipher[i].nid; +} + +int SSL_CIPHER_get_digest_nid(const SSL_CIPHER *c) +{ + int i = ssl_cipher_info_lookup(ssl_cipher_table_mac, c->algorithm_mac); + + if (i == -1) + return NID_undef; + return ssl_cipher_table_mac[i].nid; +} + +int SSL_CIPHER_get_kx_nid(const SSL_CIPHER *c) +{ + int i = ssl_cipher_info_lookup(ssl_cipher_table_kx, c->algorithm_mkey); + + if (i == -1) + return NID_undef; + return ssl_cipher_table_kx[i].nid; +} + +int SSL_CIPHER_get_auth_nid(const SSL_CIPHER *c) +{ + int i = ssl_cipher_info_lookup(ssl_cipher_table_auth, c->algorithm_auth); + + if (i == -1) + return NID_undef; + return ssl_cipher_table_auth[i].nid; +} + +const EVP_MD *SSL_CIPHER_get_handshake_digest(const SSL_CIPHER *c) +{ + int idx = c->algorithm2 & SSL_HANDSHAKE_MAC_MASK; + + if (idx < 0 || idx >= SSL_MD_NUM_IDX) + return NULL; + return ssl_digest_methods[idx]; +} + +int SSL_CIPHER_is_aead(const SSL_CIPHER *c) +{ + return (c->algorithm_mac & SSL_AEAD) ? 1 : 0; +} + +int ssl_cipher_get_overhead(const SSL_CIPHER *c, size_t *mac_overhead, + size_t *int_overhead, size_t *blocksize, + size_t *ext_overhead) +{ + size_t mac = 0, in = 0, blk = 0, out = 0; + + /* Some hard-coded numbers for the CCM/Poly1305 MAC overhead + * because there are no handy #defines for those. */ + if (c->algorithm_enc & (SSL_AESGCM | SSL_ARIAGCM)) { + out = EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN; + } else if (c->algorithm_enc & (SSL_AES128CCM | SSL_AES256CCM)) { + out = EVP_CCM_TLS_EXPLICIT_IV_LEN + 16; + } else if (c->algorithm_enc & (SSL_AES128CCM8 | SSL_AES256CCM8)) { + out = EVP_CCM_TLS_EXPLICIT_IV_LEN + 8; + } else if (c->algorithm_enc & SSL_CHACHA20POLY1305) { + out = 16; + } else if (c->algorithm_mac & SSL_AEAD) { + /* We're supposed to have handled all the AEAD modes above */ + return 0; + } else { + /* Non-AEAD modes. Calculate MAC/cipher overhead separately */ + int digest_nid = SSL_CIPHER_get_digest_nid(c); + const EVP_MD *e_md = EVP_get_digestbynid(digest_nid); + + if (e_md == NULL) + return 0; + + mac = EVP_MD_size(e_md); + if (c->algorithm_enc != SSL_eNULL) { + int cipher_nid = SSL_CIPHER_get_cipher_nid(c); + const EVP_CIPHER *e_ciph = EVP_get_cipherbynid(cipher_nid); + + /* If it wasn't AEAD or SSL_eNULL, we expect it to be a + known CBC cipher. */ + if (e_ciph == NULL || + EVP_CIPHER_mode(e_ciph) != EVP_CIPH_CBC_MODE) + return 0; + + in = 1; /* padding length byte */ + out = EVP_CIPHER_iv_length(e_ciph); + blk = EVP_CIPHER_block_size(e_ciph); + } + } + + *mac_overhead = mac; + *int_overhead = in; + *blocksize = blk; + *ext_overhead = out; + + return 1; +} + +int ssl_cert_is_disabled(size_t idx) +{ + const SSL_CERT_LOOKUP *cl = ssl_cert_lookup_by_idx(idx); + + if (cl == NULL || (cl->amask & disabled_auth_mask) != 0) + return 1; + return 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_conf.c b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_conf.c new file mode 100644 index 000000000..9c202708d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_conf.c @@ -0,0 +1,993 @@ +/* + * Copyright 2012-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "ssl_locl.h" +#include +#include +#include +#include "internal/nelem.h" + +/* + * structure holding name tables. This is used for permitted elements in lists + * such as TLSv1. + */ + +typedef struct { + const char *name; + int namelen; + unsigned int name_flags; + unsigned long option_value; +} ssl_flag_tbl; + +/* Switch table: use for single command line switches like no_tls2 */ +typedef struct { + unsigned long option_value; + unsigned int name_flags; +} ssl_switch_tbl; + +/* Sense of name is inverted e.g. "TLSv1" will clear SSL_OP_NO_TLSv1 */ +#define SSL_TFLAG_INV 0x1 +/* Mask for type of flag referred to */ +#define SSL_TFLAG_TYPE_MASK 0xf00 +/* Flag is for options */ +#define SSL_TFLAG_OPTION 0x000 +/* Flag is for cert_flags */ +#define SSL_TFLAG_CERT 0x100 +/* Flag is for verify mode */ +#define SSL_TFLAG_VFY 0x200 +/* Option can only be used for clients */ +#define SSL_TFLAG_CLIENT SSL_CONF_FLAG_CLIENT +/* Option can only be used for servers */ +#define SSL_TFLAG_SERVER SSL_CONF_FLAG_SERVER +#define SSL_TFLAG_BOTH (SSL_TFLAG_CLIENT|SSL_TFLAG_SERVER) + +#define SSL_FLAG_TBL(str, flag) \ + {str, (int)(sizeof(str) - 1), SSL_TFLAG_BOTH, flag} +#define SSL_FLAG_TBL_SRV(str, flag) \ + {str, (int)(sizeof(str) - 1), SSL_TFLAG_SERVER, flag} +#define SSL_FLAG_TBL_CLI(str, flag) \ + {str, (int)(sizeof(str) - 1), SSL_TFLAG_CLIENT, flag} +#define SSL_FLAG_TBL_INV(str, flag) \ + {str, (int)(sizeof(str) - 1), SSL_TFLAG_INV|SSL_TFLAG_BOTH, flag} +#define SSL_FLAG_TBL_SRV_INV(str, flag) \ + {str, (int)(sizeof(str) - 1), SSL_TFLAG_INV|SSL_TFLAG_SERVER, flag} +#define SSL_FLAG_TBL_CERT(str, flag) \ + {str, (int)(sizeof(str) - 1), SSL_TFLAG_CERT|SSL_TFLAG_BOTH, flag} + +#define SSL_FLAG_VFY_CLI(str, flag) \ + {str, (int)(sizeof(str) - 1), SSL_TFLAG_VFY | SSL_TFLAG_CLIENT, flag} +#define SSL_FLAG_VFY_SRV(str, flag) \ + {str, (int)(sizeof(str) - 1), SSL_TFLAG_VFY | SSL_TFLAG_SERVER, flag} + +/* + * Opaque structure containing SSL configuration context. + */ + +struct ssl_conf_ctx_st { + /* + * Various flags indicating (among other things) which options we will + * recognise. + */ + unsigned int flags; + /* Prefix and length of commands */ + char *prefix; + size_t prefixlen; + /* SSL_CTX or SSL structure to perform operations on */ + SSL_CTX *ctx; + SSL *ssl; + /* Pointer to SSL or SSL_CTX options field or NULL if none */ + uint32_t *poptions; + /* Certificate filenames for each type */ + char *cert_filename[SSL_PKEY_NUM]; + /* Pointer to SSL or SSL_CTX cert_flags or NULL if none */ + uint32_t *pcert_flags; + /* Pointer to SSL or SSL_CTX verify_mode or NULL if none */ + uint32_t *pvfy_flags; + /* Pointer to SSL or SSL_CTX min_version field or NULL if none */ + int *min_version; + /* Pointer to SSL or SSL_CTX max_version field or NULL if none */ + int *max_version; + /* Current flag table being worked on */ + const ssl_flag_tbl *tbl; + /* Size of table */ + size_t ntbl; + /* Client CA names */ + STACK_OF(X509_NAME) *canames; +}; + +static void ssl_set_option(SSL_CONF_CTX *cctx, unsigned int name_flags, + unsigned long option_value, int onoff) +{ + uint32_t *pflags; + if (cctx->poptions == NULL) + return; + if (name_flags & SSL_TFLAG_INV) + onoff ^= 1; + switch (name_flags & SSL_TFLAG_TYPE_MASK) { + + case SSL_TFLAG_CERT: + pflags = cctx->pcert_flags; + break; + + case SSL_TFLAG_VFY: + pflags = cctx->pvfy_flags; + break; + + case SSL_TFLAG_OPTION: + pflags = cctx->poptions; + break; + + default: + return; + + } + if (onoff) + *pflags |= option_value; + else + *pflags &= ~option_value; +} + +static int ssl_match_option(SSL_CONF_CTX *cctx, const ssl_flag_tbl *tbl, + const char *name, int namelen, int onoff) +{ + /* If name not relevant for context skip */ + if (!(cctx->flags & tbl->name_flags & SSL_TFLAG_BOTH)) + return 0; + if (namelen == -1) { + if (strcmp(tbl->name, name)) + return 0; + } else if (tbl->namelen != namelen || strncasecmp(tbl->name, name, namelen)) + return 0; + ssl_set_option(cctx, tbl->name_flags, tbl->option_value, onoff); + return 1; +} + +static int ssl_set_option_list(const char *elem, int len, void *usr) +{ + SSL_CONF_CTX *cctx = usr; + size_t i; + const ssl_flag_tbl *tbl; + int onoff = 1; + /* + * len == -1 indicates not being called in list context, just for single + * command line switches, so don't allow +, -. + */ + if (elem == NULL) + return 0; + if (len != -1) { + if (*elem == '+') { + elem++; + len--; + onoff = 1; + } else if (*elem == '-') { + elem++; + len--; + onoff = 0; + } + } + for (i = 0, tbl = cctx->tbl; i < cctx->ntbl; i++, tbl++) { + if (ssl_match_option(cctx, tbl, elem, len, onoff)) + return 1; + } + return 0; +} + +/* Set supported signature algorithms */ +static int cmd_SignatureAlgorithms(SSL_CONF_CTX *cctx, const char *value) +{ + int rv; + if (cctx->ssl) + rv = SSL_set1_sigalgs_list(cctx->ssl, value); + /* NB: ctx == NULL performs syntax checking only */ + else + rv = SSL_CTX_set1_sigalgs_list(cctx->ctx, value); + return rv > 0; +} + +/* Set supported client signature algorithms */ +static int cmd_ClientSignatureAlgorithms(SSL_CONF_CTX *cctx, const char *value) +{ + int rv; + if (cctx->ssl) + rv = SSL_set1_client_sigalgs_list(cctx->ssl, value); + /* NB: ctx == NULL performs syntax checking only */ + else + rv = SSL_CTX_set1_client_sigalgs_list(cctx->ctx, value); + return rv > 0; +} + +static int cmd_Groups(SSL_CONF_CTX *cctx, const char *value) +{ + int rv; + if (cctx->ssl) + rv = SSL_set1_groups_list(cctx->ssl, value); + /* NB: ctx == NULL performs syntax checking only */ + else + rv = SSL_CTX_set1_groups_list(cctx->ctx, value); + return rv > 0; +} + +/* This is the old name for cmd_Groups - retained for backwards compatibility */ +static int cmd_Curves(SSL_CONF_CTX *cctx, const char *value) +{ + return cmd_Groups(cctx, value); +} + +#ifndef OPENSSL_NO_EC +/* ECDH temporary parameters */ +static int cmd_ECDHParameters(SSL_CONF_CTX *cctx, const char *value) +{ + int rv = 1; + EC_KEY *ecdh; + int nid; + + /* Ignore values supported by 1.0.2 for the automatic selection */ + if ((cctx->flags & SSL_CONF_FLAG_FILE) + && (strcasecmp(value, "+automatic") == 0 + || strcasecmp(value, "automatic") == 0)) + return 1; + if ((cctx->flags & SSL_CONF_FLAG_CMDLINE) && + strcmp(value, "auto") == 0) + return 1; + + nid = EC_curve_nist2nid(value); + if (nid == NID_undef) + nid = OBJ_sn2nid(value); + if (nid == 0) + return 0; + ecdh = EC_KEY_new_by_curve_name(nid); + if (!ecdh) + return 0; + if (cctx->ctx) + rv = SSL_CTX_set_tmp_ecdh(cctx->ctx, ecdh); + else if (cctx->ssl) + rv = SSL_set_tmp_ecdh(cctx->ssl, ecdh); + EC_KEY_free(ecdh); + + return rv > 0; +} +#endif +static int cmd_CipherString(SSL_CONF_CTX *cctx, const char *value) +{ + int rv = 1; + + if (cctx->ctx) + rv = SSL_CTX_set_cipher_list(cctx->ctx, value); + if (cctx->ssl) + rv = SSL_set_cipher_list(cctx->ssl, value); + return rv > 0; +} + +static int cmd_Ciphersuites(SSL_CONF_CTX *cctx, const char *value) +{ + int rv = 1; + + if (cctx->ctx) + rv = SSL_CTX_set_ciphersuites(cctx->ctx, value); + if (cctx->ssl) + rv = SSL_set_ciphersuites(cctx->ssl, value); + return rv > 0; +} + +static int cmd_Protocol(SSL_CONF_CTX *cctx, const char *value) +{ + static const ssl_flag_tbl ssl_protocol_list[] = { + SSL_FLAG_TBL_INV("ALL", SSL_OP_NO_SSL_MASK), + SSL_FLAG_TBL_INV("SSLv2", SSL_OP_NO_SSLv2), + SSL_FLAG_TBL_INV("SSLv3", SSL_OP_NO_SSLv3), + SSL_FLAG_TBL_INV("TLSv1", SSL_OP_NO_TLSv1), + SSL_FLAG_TBL_INV("TLSv1.1", SSL_OP_NO_TLSv1_1), + SSL_FLAG_TBL_INV("TLSv1.2", SSL_OP_NO_TLSv1_2), + SSL_FLAG_TBL_INV("TLSv1.3", SSL_OP_NO_TLSv1_3), + SSL_FLAG_TBL_INV("DTLSv1", SSL_OP_NO_DTLSv1), + SSL_FLAG_TBL_INV("DTLSv1.2", SSL_OP_NO_DTLSv1_2) + }; + cctx->tbl = ssl_protocol_list; + cctx->ntbl = OSSL_NELEM(ssl_protocol_list); + return CONF_parse_list(value, ',', 1, ssl_set_option_list, cctx); +} + +/* + * protocol_from_string - converts a protocol version string to a number + * + * Returns -1 on failure or the version on success + */ +static int protocol_from_string(const char *value) +{ + struct protocol_versions { + const char *name; + int version; + }; + static const struct protocol_versions versions[] = { + {"None", 0}, + {"SSLv3", SSL3_VERSION}, + {"TLSv1", TLS1_VERSION}, + {"TLSv1.1", TLS1_1_VERSION}, + {"TLSv1.2", TLS1_2_VERSION}, + {"TLSv1.3", TLS1_3_VERSION}, + {"DTLSv1", DTLS1_VERSION}, + {"DTLSv1.2", DTLS1_2_VERSION} + }; + size_t i; + size_t n = OSSL_NELEM(versions); + + for (i = 0; i < n; i++) + if (strcmp(versions[i].name, value) == 0) + return versions[i].version; + return -1; +} + +static int min_max_proto(SSL_CONF_CTX *cctx, const char *value, int *bound) +{ + int method_version; + int new_version; + + if (cctx->ctx != NULL) + method_version = cctx->ctx->method->version; + else if (cctx->ssl != NULL) + method_version = cctx->ssl->ctx->method->version; + else + return 0; + if ((new_version = protocol_from_string(value)) < 0) + return 0; + return ssl_set_version_bound(method_version, new_version, bound); +} + +/* + * cmd_MinProtocol - Set min protocol version + * @cctx: config structure to save settings in + * @value: The min protocol version in string form + * + * Returns 1 on success and 0 on failure. + */ +static int cmd_MinProtocol(SSL_CONF_CTX *cctx, const char *value) +{ + return min_max_proto(cctx, value, cctx->min_version); +} + +/* + * cmd_MaxProtocol - Set max protocol version + * @cctx: config structure to save settings in + * @value: The max protocol version in string form + * + * Returns 1 on success and 0 on failure. + */ +static int cmd_MaxProtocol(SSL_CONF_CTX *cctx, const char *value) +{ + return min_max_proto(cctx, value, cctx->max_version); +} + +static int cmd_Options(SSL_CONF_CTX *cctx, const char *value) +{ + static const ssl_flag_tbl ssl_option_list[] = { + SSL_FLAG_TBL_INV("SessionTicket", SSL_OP_NO_TICKET), + SSL_FLAG_TBL_INV("EmptyFragments", + SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS), + SSL_FLAG_TBL("Bugs", SSL_OP_ALL), + SSL_FLAG_TBL_INV("Compression", SSL_OP_NO_COMPRESSION), + SSL_FLAG_TBL_SRV("ServerPreference", SSL_OP_CIPHER_SERVER_PREFERENCE), + SSL_FLAG_TBL_SRV("NoResumptionOnRenegotiation", + SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION), + SSL_FLAG_TBL_SRV("DHSingle", SSL_OP_SINGLE_DH_USE), + SSL_FLAG_TBL_SRV("ECDHSingle", SSL_OP_SINGLE_ECDH_USE), + SSL_FLAG_TBL("UnsafeLegacyRenegotiation", + SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION), + SSL_FLAG_TBL_INV("EncryptThenMac", SSL_OP_NO_ENCRYPT_THEN_MAC), + SSL_FLAG_TBL("NoRenegotiation", SSL_OP_NO_RENEGOTIATION), + SSL_FLAG_TBL("AllowNoDHEKEX", SSL_OP_ALLOW_NO_DHE_KEX), + SSL_FLAG_TBL("PrioritizeChaCha", SSL_OP_PRIORITIZE_CHACHA), + SSL_FLAG_TBL("MiddleboxCompat", SSL_OP_ENABLE_MIDDLEBOX_COMPAT), + SSL_FLAG_TBL_INV("AntiReplay", SSL_OP_NO_ANTI_REPLAY) + }; + if (value == NULL) + return -3; + cctx->tbl = ssl_option_list; + cctx->ntbl = OSSL_NELEM(ssl_option_list); + return CONF_parse_list(value, ',', 1, ssl_set_option_list, cctx); +} + +static int cmd_VerifyMode(SSL_CONF_CTX *cctx, const char *value) +{ + static const ssl_flag_tbl ssl_vfy_list[] = { + SSL_FLAG_VFY_CLI("Peer", SSL_VERIFY_PEER), + SSL_FLAG_VFY_SRV("Request", SSL_VERIFY_PEER), + SSL_FLAG_VFY_SRV("Require", + SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT), + SSL_FLAG_VFY_SRV("Once", SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE), + SSL_FLAG_VFY_SRV("RequestPostHandshake", + SSL_VERIFY_PEER | SSL_VERIFY_POST_HANDSHAKE), + SSL_FLAG_VFY_SRV("RequirePostHandshake", + SSL_VERIFY_PEER | SSL_VERIFY_POST_HANDSHAKE | + SSL_VERIFY_FAIL_IF_NO_PEER_CERT), + }; + if (value == NULL) + return -3; + cctx->tbl = ssl_vfy_list; + cctx->ntbl = OSSL_NELEM(ssl_vfy_list); + return CONF_parse_list(value, ',', 1, ssl_set_option_list, cctx); +} + +static int cmd_Certificate(SSL_CONF_CTX *cctx, const char *value) +{ + int rv = 1; + CERT *c = NULL; + if (cctx->ctx) { + rv = SSL_CTX_use_certificate_chain_file(cctx->ctx, value); + c = cctx->ctx->cert; + } + if (cctx->ssl) { + rv = SSL_use_certificate_chain_file(cctx->ssl, value); + c = cctx->ssl->cert; + } + if (rv > 0 && c && cctx->flags & SSL_CONF_FLAG_REQUIRE_PRIVATE) { + char **pfilename = &cctx->cert_filename[c->key - c->pkeys]; + OPENSSL_free(*pfilename); + *pfilename = OPENSSL_strdup(value); + if (!*pfilename) + rv = 0; + } + + return rv > 0; +} + +static int cmd_PrivateKey(SSL_CONF_CTX *cctx, const char *value) +{ + int rv = 1; + if (!(cctx->flags & SSL_CONF_FLAG_CERTIFICATE)) + return -2; + if (cctx->ctx) + rv = SSL_CTX_use_PrivateKey_file(cctx->ctx, value, SSL_FILETYPE_PEM); + if (cctx->ssl) + rv = SSL_use_PrivateKey_file(cctx->ssl, value, SSL_FILETYPE_PEM); + return rv > 0; +} + +static int cmd_ServerInfoFile(SSL_CONF_CTX *cctx, const char *value) +{ + int rv = 1; + if (cctx->ctx) + rv = SSL_CTX_use_serverinfo_file(cctx->ctx, value); + return rv > 0; +} + +static int do_store(SSL_CONF_CTX *cctx, + const char *CAfile, const char *CApath, int verify_store) +{ + CERT *cert; + X509_STORE **st; + if (cctx->ctx) + cert = cctx->ctx->cert; + else if (cctx->ssl) + cert = cctx->ssl->cert; + else + return 1; + st = verify_store ? &cert->verify_store : &cert->chain_store; + if (*st == NULL) { + *st = X509_STORE_new(); + if (*st == NULL) + return 0; + } + return X509_STORE_load_locations(*st, CAfile, CApath) > 0; +} + +static int cmd_ChainCAPath(SSL_CONF_CTX *cctx, const char *value) +{ + return do_store(cctx, NULL, value, 0); +} + +static int cmd_ChainCAFile(SSL_CONF_CTX *cctx, const char *value) +{ + return do_store(cctx, value, NULL, 0); +} + +static int cmd_VerifyCAPath(SSL_CONF_CTX *cctx, const char *value) +{ + return do_store(cctx, NULL, value, 1); +} + +static int cmd_VerifyCAFile(SSL_CONF_CTX *cctx, const char *value) +{ + return do_store(cctx, value, NULL, 1); +} + +static int cmd_RequestCAFile(SSL_CONF_CTX *cctx, const char *value) +{ + if (cctx->canames == NULL) + cctx->canames = sk_X509_NAME_new_null(); + if (cctx->canames == NULL) + return 0; + return SSL_add_file_cert_subjects_to_stack(cctx->canames, value); +} + +static int cmd_ClientCAFile(SSL_CONF_CTX *cctx, const char *value) +{ + return cmd_RequestCAFile(cctx, value); +} + +static int cmd_RequestCAPath(SSL_CONF_CTX *cctx, const char *value) +{ + if (cctx->canames == NULL) + cctx->canames = sk_X509_NAME_new_null(); + if (cctx->canames == NULL) + return 0; + return SSL_add_dir_cert_subjects_to_stack(cctx->canames, value); +} + +static int cmd_ClientCAPath(SSL_CONF_CTX *cctx, const char *value) +{ + return cmd_RequestCAPath(cctx, value); +} + +#ifndef OPENSSL_NO_DH +static int cmd_DHParameters(SSL_CONF_CTX *cctx, const char *value) +{ + int rv = 0; + DH *dh = NULL; + BIO *in = NULL; + if (cctx->ctx || cctx->ssl) { + in = BIO_new(BIO_s_file()); + if (in == NULL) + goto end; + if (BIO_read_filename(in, value) <= 0) + goto end; + dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL); + if (dh == NULL) + goto end; + } else + return 1; + if (cctx->ctx) + rv = SSL_CTX_set_tmp_dh(cctx->ctx, dh); + if (cctx->ssl) + rv = SSL_set_tmp_dh(cctx->ssl, dh); + end: + DH_free(dh); + BIO_free(in); + return rv > 0; +} +#endif + +static int cmd_RecordPadding(SSL_CONF_CTX *cctx, const char *value) +{ + int rv = 0; + int block_size = atoi(value); + + /* + * All we care about is a non-negative value, + * the setters check the range + */ + if (block_size >= 0) { + if (cctx->ctx) + rv = SSL_CTX_set_block_padding(cctx->ctx, block_size); + if (cctx->ssl) + rv = SSL_set_block_padding(cctx->ssl, block_size); + } + return rv; +} + + +static int cmd_NumTickets(SSL_CONF_CTX *cctx, const char *value) +{ + int rv = 0; + int num_tickets = atoi(value); + + if (num_tickets >= 0) { + if (cctx->ctx) + rv = SSL_CTX_set_num_tickets(cctx->ctx, num_tickets); + if (cctx->ssl) + rv = SSL_set_num_tickets(cctx->ssl, num_tickets); + } + return rv; +} + +typedef struct { + int (*cmd) (SSL_CONF_CTX *cctx, const char *value); + const char *str_file; + const char *str_cmdline; + unsigned short flags; + unsigned short value_type; +} ssl_conf_cmd_tbl; + +/* Table of supported parameters */ + +#define SSL_CONF_CMD(name, cmdopt, flags, type) \ + {cmd_##name, #name, cmdopt, flags, type} + +#define SSL_CONF_CMD_STRING(name, cmdopt, flags) \ + SSL_CONF_CMD(name, cmdopt, flags, SSL_CONF_TYPE_STRING) + +#define SSL_CONF_CMD_SWITCH(name, flags) \ + {0, NULL, name, flags, SSL_CONF_TYPE_NONE} + +/* See apps/apps.h if you change this table. */ +static const ssl_conf_cmd_tbl ssl_conf_cmds[] = { + SSL_CONF_CMD_SWITCH("no_ssl3", 0), + SSL_CONF_CMD_SWITCH("no_tls1", 0), + SSL_CONF_CMD_SWITCH("no_tls1_1", 0), + SSL_CONF_CMD_SWITCH("no_tls1_2", 0), + SSL_CONF_CMD_SWITCH("no_tls1_3", 0), + SSL_CONF_CMD_SWITCH("bugs", 0), + SSL_CONF_CMD_SWITCH("no_comp", 0), + SSL_CONF_CMD_SWITCH("comp", 0), + SSL_CONF_CMD_SWITCH("ecdh_single", SSL_CONF_FLAG_SERVER), + SSL_CONF_CMD_SWITCH("no_ticket", 0), + SSL_CONF_CMD_SWITCH("serverpref", SSL_CONF_FLAG_SERVER), + SSL_CONF_CMD_SWITCH("legacy_renegotiation", 0), + SSL_CONF_CMD_SWITCH("legacy_server_connect", SSL_CONF_FLAG_SERVER), + SSL_CONF_CMD_SWITCH("no_renegotiation", 0), + SSL_CONF_CMD_SWITCH("no_resumption_on_reneg", SSL_CONF_FLAG_SERVER), + SSL_CONF_CMD_SWITCH("no_legacy_server_connect", SSL_CONF_FLAG_SERVER), + SSL_CONF_CMD_SWITCH("allow_no_dhe_kex", 0), + SSL_CONF_CMD_SWITCH("prioritize_chacha", SSL_CONF_FLAG_SERVER), + SSL_CONF_CMD_SWITCH("strict", 0), + SSL_CONF_CMD_SWITCH("no_middlebox", 0), + SSL_CONF_CMD_SWITCH("anti_replay", SSL_CONF_FLAG_SERVER), + SSL_CONF_CMD_SWITCH("no_anti_replay", SSL_CONF_FLAG_SERVER), + SSL_CONF_CMD_STRING(SignatureAlgorithms, "sigalgs", 0), + SSL_CONF_CMD_STRING(ClientSignatureAlgorithms, "client_sigalgs", 0), + SSL_CONF_CMD_STRING(Curves, "curves", 0), + SSL_CONF_CMD_STRING(Groups, "groups", 0), +#ifndef OPENSSL_NO_EC + SSL_CONF_CMD_STRING(ECDHParameters, "named_curve", SSL_CONF_FLAG_SERVER), +#endif + SSL_CONF_CMD_STRING(CipherString, "cipher", 0), + SSL_CONF_CMD_STRING(Ciphersuites, "ciphersuites", 0), + SSL_CONF_CMD_STRING(Protocol, NULL, 0), + SSL_CONF_CMD_STRING(MinProtocol, "min_protocol", 0), + SSL_CONF_CMD_STRING(MaxProtocol, "max_protocol", 0), + SSL_CONF_CMD_STRING(Options, NULL, 0), + SSL_CONF_CMD_STRING(VerifyMode, NULL, 0), + SSL_CONF_CMD(Certificate, "cert", SSL_CONF_FLAG_CERTIFICATE, + SSL_CONF_TYPE_FILE), + SSL_CONF_CMD(PrivateKey, "key", SSL_CONF_FLAG_CERTIFICATE, + SSL_CONF_TYPE_FILE), + SSL_CONF_CMD(ServerInfoFile, NULL, + SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE, + SSL_CONF_TYPE_FILE), + SSL_CONF_CMD(ChainCAPath, "chainCApath", SSL_CONF_FLAG_CERTIFICATE, + SSL_CONF_TYPE_DIR), + SSL_CONF_CMD(ChainCAFile, "chainCAfile", SSL_CONF_FLAG_CERTIFICATE, + SSL_CONF_TYPE_FILE), + SSL_CONF_CMD(VerifyCAPath, "verifyCApath", SSL_CONF_FLAG_CERTIFICATE, + SSL_CONF_TYPE_DIR), + SSL_CONF_CMD(VerifyCAFile, "verifyCAfile", SSL_CONF_FLAG_CERTIFICATE, + SSL_CONF_TYPE_FILE), + SSL_CONF_CMD(RequestCAFile, "requestCAFile", SSL_CONF_FLAG_CERTIFICATE, + SSL_CONF_TYPE_FILE), + SSL_CONF_CMD(ClientCAFile, NULL, + SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE, + SSL_CONF_TYPE_FILE), + SSL_CONF_CMD(RequestCAPath, NULL, SSL_CONF_FLAG_CERTIFICATE, + SSL_CONF_TYPE_DIR), + SSL_CONF_CMD(ClientCAPath, NULL, + SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE, + SSL_CONF_TYPE_DIR), +#ifndef OPENSSL_NO_DH + SSL_CONF_CMD(DHParameters, "dhparam", + SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE, + SSL_CONF_TYPE_FILE), +#endif + SSL_CONF_CMD_STRING(RecordPadding, "record_padding", 0), + SSL_CONF_CMD_STRING(NumTickets, "num_tickets", SSL_CONF_FLAG_SERVER), +}; + +/* Supported switches: must match order of switches in ssl_conf_cmds */ +static const ssl_switch_tbl ssl_cmd_switches[] = { + {SSL_OP_NO_SSLv3, 0}, /* no_ssl3 */ + {SSL_OP_NO_TLSv1, 0}, /* no_tls1 */ + {SSL_OP_NO_TLSv1_1, 0}, /* no_tls1_1 */ + {SSL_OP_NO_TLSv1_2, 0}, /* no_tls1_2 */ + {SSL_OP_NO_TLSv1_3, 0}, /* no_tls1_3 */ + {SSL_OP_ALL, 0}, /* bugs */ + {SSL_OP_NO_COMPRESSION, 0}, /* no_comp */ + {SSL_OP_NO_COMPRESSION, SSL_TFLAG_INV}, /* comp */ + {SSL_OP_SINGLE_ECDH_USE, 0}, /* ecdh_single */ + {SSL_OP_NO_TICKET, 0}, /* no_ticket */ + {SSL_OP_CIPHER_SERVER_PREFERENCE, 0}, /* serverpref */ + /* legacy_renegotiation */ + {SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION, 0}, + /* legacy_server_connect */ + {SSL_OP_LEGACY_SERVER_CONNECT, 0}, + /* no_renegotiation */ + {SSL_OP_NO_RENEGOTIATION, 0}, + /* no_resumption_on_reneg */ + {SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION, 0}, + /* no_legacy_server_connect */ + {SSL_OP_LEGACY_SERVER_CONNECT, SSL_TFLAG_INV}, + /* allow_no_dhe_kex */ + {SSL_OP_ALLOW_NO_DHE_KEX, 0}, + /* chacha reprioritization */ + {SSL_OP_PRIORITIZE_CHACHA, 0}, + {SSL_CERT_FLAG_TLS_STRICT, SSL_TFLAG_CERT}, /* strict */ + /* no_middlebox */ + {SSL_OP_ENABLE_MIDDLEBOX_COMPAT, SSL_TFLAG_INV}, + /* anti_replay */ + {SSL_OP_NO_ANTI_REPLAY, SSL_TFLAG_INV}, + /* no_anti_replay */ + {SSL_OP_NO_ANTI_REPLAY, 0}, +}; + +static int ssl_conf_cmd_skip_prefix(SSL_CONF_CTX *cctx, const char **pcmd) +{ + if (!pcmd || !*pcmd) + return 0; + /* If a prefix is set, check and skip */ + if (cctx->prefix) { + if (strlen(*pcmd) <= cctx->prefixlen) + return 0; + if (cctx->flags & SSL_CONF_FLAG_CMDLINE && + strncmp(*pcmd, cctx->prefix, cctx->prefixlen)) + return 0; + if (cctx->flags & SSL_CONF_FLAG_FILE && + strncasecmp(*pcmd, cctx->prefix, cctx->prefixlen)) + return 0; + *pcmd += cctx->prefixlen; + } else if (cctx->flags & SSL_CONF_FLAG_CMDLINE) { + if (**pcmd != '-' || !(*pcmd)[1]) + return 0; + *pcmd += 1; + } + return 1; +} + +/* Determine if a command is allowed according to cctx flags */ +static int ssl_conf_cmd_allowed(SSL_CONF_CTX *cctx, const ssl_conf_cmd_tbl * t) +{ + unsigned int tfl = t->flags; + unsigned int cfl = cctx->flags; + if ((tfl & SSL_CONF_FLAG_SERVER) && !(cfl & SSL_CONF_FLAG_SERVER)) + return 0; + if ((tfl & SSL_CONF_FLAG_CLIENT) && !(cfl & SSL_CONF_FLAG_CLIENT)) + return 0; + if ((tfl & SSL_CONF_FLAG_CERTIFICATE) + && !(cfl & SSL_CONF_FLAG_CERTIFICATE)) + return 0; + return 1; +} + +static const ssl_conf_cmd_tbl *ssl_conf_cmd_lookup(SSL_CONF_CTX *cctx, + const char *cmd) +{ + const ssl_conf_cmd_tbl *t; + size_t i; + if (cmd == NULL) + return NULL; + + /* Look for matching parameter name in table */ + for (i = 0, t = ssl_conf_cmds; i < OSSL_NELEM(ssl_conf_cmds); i++, t++) { + if (ssl_conf_cmd_allowed(cctx, t)) { + if (cctx->flags & SSL_CONF_FLAG_CMDLINE) { + if (t->str_cmdline && strcmp(t->str_cmdline, cmd) == 0) + return t; + } + if (cctx->flags & SSL_CONF_FLAG_FILE) { + if (t->str_file && strcasecmp(t->str_file, cmd) == 0) + return t; + } + } + } + return NULL; +} + +static int ctrl_switch_option(SSL_CONF_CTX *cctx, const ssl_conf_cmd_tbl * cmd) +{ + /* Find index of command in table */ + size_t idx = cmd - ssl_conf_cmds; + const ssl_switch_tbl *scmd; + /* Sanity check index */ + if (idx >= OSSL_NELEM(ssl_cmd_switches)) + return 0; + /* Obtain switches entry with same index */ + scmd = ssl_cmd_switches + idx; + ssl_set_option(cctx, scmd->name_flags, scmd->option_value, 1); + return 1; +} + +int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value) +{ + const ssl_conf_cmd_tbl *runcmd; + if (cmd == NULL) { + SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_INVALID_NULL_CMD_NAME); + return 0; + } + + if (!ssl_conf_cmd_skip_prefix(cctx, &cmd)) + return -2; + + runcmd = ssl_conf_cmd_lookup(cctx, cmd); + + if (runcmd) { + int rv; + if (runcmd->value_type == SSL_CONF_TYPE_NONE) { + return ctrl_switch_option(cctx, runcmd); + } + if (value == NULL) + return -3; + rv = runcmd->cmd(cctx, value); + if (rv > 0) + return 2; + if (rv == -2) + return -2; + if (cctx->flags & SSL_CONF_FLAG_SHOW_ERRORS) { + SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_BAD_VALUE); + ERR_add_error_data(4, "cmd=", cmd, ", value=", value); + } + return 0; + } + + if (cctx->flags & SSL_CONF_FLAG_SHOW_ERRORS) { + SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_UNKNOWN_CMD_NAME); + ERR_add_error_data(2, "cmd=", cmd); + } + + return -2; +} + +int SSL_CONF_cmd_argv(SSL_CONF_CTX *cctx, int *pargc, char ***pargv) +{ + int rv; + const char *arg = NULL, *argn; + if (pargc && *pargc == 0) + return 0; + if (!pargc || *pargc > 0) + arg = **pargv; + if (arg == NULL) + return 0; + if (!pargc || *pargc > 1) + argn = (*pargv)[1]; + else + argn = NULL; + cctx->flags &= ~SSL_CONF_FLAG_FILE; + cctx->flags |= SSL_CONF_FLAG_CMDLINE; + rv = SSL_CONF_cmd(cctx, arg, argn); + if (rv > 0) { + /* Success: update pargc, pargv */ + (*pargv) += rv; + if (pargc) + (*pargc) -= rv; + return rv; + } + /* Unknown switch: indicate no arguments processed */ + if (rv == -2) + return 0; + /* Some error occurred processing command, return fatal error */ + if (rv == 0) + return -1; + return rv; +} + +int SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd) +{ + if (ssl_conf_cmd_skip_prefix(cctx, &cmd)) { + const ssl_conf_cmd_tbl *runcmd; + runcmd = ssl_conf_cmd_lookup(cctx, cmd); + if (runcmd) + return runcmd->value_type; + } + return SSL_CONF_TYPE_UNKNOWN; +} + +SSL_CONF_CTX *SSL_CONF_CTX_new(void) +{ + SSL_CONF_CTX *ret = OPENSSL_zalloc(sizeof(*ret)); + + return ret; +} + +int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx) +{ + /* See if any certificates are missing private keys */ + size_t i; + CERT *c = NULL; + if (cctx->ctx) + c = cctx->ctx->cert; + else if (cctx->ssl) + c = cctx->ssl->cert; + if (c && cctx->flags & SSL_CONF_FLAG_REQUIRE_PRIVATE) { + for (i = 0; i < SSL_PKEY_NUM; i++) { + const char *p = cctx->cert_filename[i]; + /* + * If missing private key try to load one from certificate file + */ + if (p && !c->pkeys[i].privatekey) { + if (!cmd_PrivateKey(cctx, p)) + return 0; + } + } + } + if (cctx->canames) { + if (cctx->ssl) + SSL_set0_CA_list(cctx->ssl, cctx->canames); + else if (cctx->ctx) + SSL_CTX_set0_CA_list(cctx->ctx, cctx->canames); + else + sk_X509_NAME_pop_free(cctx->canames, X509_NAME_free); + cctx->canames = NULL; + } + return 1; +} + +void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx) +{ + if (cctx) { + size_t i; + for (i = 0; i < SSL_PKEY_NUM; i++) + OPENSSL_free(cctx->cert_filename[i]); + OPENSSL_free(cctx->prefix); + sk_X509_NAME_pop_free(cctx->canames, X509_NAME_free); + OPENSSL_free(cctx); + } +} + +unsigned int SSL_CONF_CTX_set_flags(SSL_CONF_CTX *cctx, unsigned int flags) +{ + cctx->flags |= flags; + return cctx->flags; +} + +unsigned int SSL_CONF_CTX_clear_flags(SSL_CONF_CTX *cctx, unsigned int flags) +{ + cctx->flags &= ~flags; + return cctx->flags; +} + +int SSL_CONF_CTX_set1_prefix(SSL_CONF_CTX *cctx, const char *pre) +{ + char *tmp = NULL; + if (pre) { + tmp = OPENSSL_strdup(pre); + if (tmp == NULL) + return 0; + } + OPENSSL_free(cctx->prefix); + cctx->prefix = tmp; + if (tmp) + cctx->prefixlen = strlen(tmp); + else + cctx->prefixlen = 0; + return 1; +} + +void SSL_CONF_CTX_set_ssl(SSL_CONF_CTX *cctx, SSL *ssl) +{ + cctx->ssl = ssl; + cctx->ctx = NULL; + if (ssl) { + cctx->poptions = &ssl->options; + cctx->min_version = &ssl->min_proto_version; + cctx->max_version = &ssl->max_proto_version; + cctx->pcert_flags = &ssl->cert->cert_flags; + cctx->pvfy_flags = &ssl->verify_mode; + } else { + cctx->poptions = NULL; + cctx->min_version = NULL; + cctx->max_version = NULL; + cctx->pcert_flags = NULL; + cctx->pvfy_flags = NULL; + } +} + +void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx) +{ + cctx->ctx = ctx; + cctx->ssl = NULL; + if (ctx) { + cctx->poptions = &ctx->options; + cctx->min_version = &ctx->min_proto_version; + cctx->max_version = &ctx->max_proto_version; + cctx->pcert_flags = &ctx->cert->cert_flags; + cctx->pvfy_flags = &ctx->verify_mode; + } else { + cctx->poptions = NULL; + cctx->min_version = NULL; + cctx->max_version = NULL; + cctx->pcert_flags = NULL; + cctx->pvfy_flags = NULL; + } +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_err.c b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_err.c new file mode 100644 index 000000000..4b12ed148 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_err.c @@ -0,0 +1,1277 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include + +#ifndef OPENSSL_NO_ERR + +static const ERR_STRING_DATA SSL_str_functs[] = { + {ERR_PACK(ERR_LIB_SSL, SSL_F_ADD_CLIENT_KEY_SHARE_EXT, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_ADD_KEY_SHARE, 0), "add_key_share"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_BYTES_TO_CIPHER_LIST, 0), + "bytes_to_cipher_list"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_CHECK_SUITEB_CIPHER_LIST, 0), + "check_suiteb_cipher_list"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_CIPHERSUITE_CB, 0), "ciphersuite_cb"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_CONSTRUCT_CA_NAMES, 0), "construct_ca_names"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_CONSTRUCT_KEY_EXCHANGE_TBS, 0), + "construct_key_exchange_tbs"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_CONSTRUCT_STATEFUL_TICKET, 0), + "construct_stateful_ticket"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_CONSTRUCT_STATELESS_TICKET, 0), + "construct_stateless_ticket"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_CREATE_SYNTHETIC_MESSAGE_HASH, 0), + "create_synthetic_message_hash"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_CREATE_TICKET_PREQUEL, 0), + "create_ticket_prequel"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_CT_MOVE_SCTS, 0), "ct_move_scts"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_CT_STRICT, 0), "ct_strict"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_CUSTOM_EXT_ADD, 0), "custom_ext_add"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_CUSTOM_EXT_PARSE, 0), "custom_ext_parse"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_D2I_SSL_SESSION, 0), "d2i_SSL_SESSION"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_DANE_CTX_ENABLE, 0), "dane_ctx_enable"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_DANE_MTYPE_SET, 0), "dane_mtype_set"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_DANE_TLSA_ADD, 0), "dane_tlsa_add"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_DERIVE_SECRET_KEY_AND_IV, 0), + "derive_secret_key_and_iv"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_DO_DTLS1_WRITE, 0), "do_dtls1_write"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_DO_SSL3_WRITE, 0), "do_ssl3_write"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS1_BUFFER_RECORD, 0), + "dtls1_buffer_record"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS1_CHECK_TIMEOUT_NUM, 0), + "dtls1_check_timeout_num"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS1_HEARTBEAT, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS1_HM_FRAGMENT_NEW, 0), + "dtls1_hm_fragment_new"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS1_PREPROCESS_FRAGMENT, 0), + "dtls1_preprocess_fragment"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS, 0), + "dtls1_process_buffered_records"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS1_PROCESS_RECORD, 0), + "dtls1_process_record"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS1_READ_BYTES, 0), "dtls1_read_bytes"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS1_READ_FAILED, 0), "dtls1_read_failed"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS1_RETRANSMIT_MESSAGE, 0), + "dtls1_retransmit_message"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS1_WRITE_APP_DATA_BYTES, 0), + "dtls1_write_app_data_bytes"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS1_WRITE_BYTES, 0), "dtls1_write_bytes"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLSV1_LISTEN, 0), "DTLSv1_listen"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC, 0), + "dtls_construct_change_cipher_spec"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST, 0), + "dtls_construct_hello_verify_request"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, 0), + "dtls_get_reassembled_message"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS_PROCESS_HELLO_VERIFY, 0), + "dtls_process_hello_verify"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS_RECORD_LAYER_NEW, 0), + "DTLS_RECORD_LAYER_new"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS_WAIT_FOR_DRY, 0), "dtls_wait_for_dry"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_EARLY_DATA_COUNT_OK, 0), + "early_data_count_ok"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_EARLY_DATA, 0), "final_early_data"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_EC_PT_FORMATS, 0), + "final_ec_pt_formats"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_EMS, 0), "final_ems"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_KEY_SHARE, 0), "final_key_share"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_MAXFRAGMENTLEN, 0), + "final_maxfragmentlen"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_RENEGOTIATE, 0), "final_renegotiate"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_SERVER_NAME, 0), "final_server_name"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_SIG_ALGS, 0), "final_sig_algs"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_GET_CERT_VERIFY_TBS_DATA, 0), + "get_cert_verify_tbs_data"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_NSS_KEYLOG_INT, 0), "nss_keylog_int"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_OPENSSL_INIT_SSL, 0), "OPENSSL_init_ssl"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_CLIENT13_READ_TRANSITION, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_CLIENT13_WRITE_TRANSITION, 0), + "ossl_statem_client13_write_transition"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_CLIENT_CONSTRUCT_MESSAGE, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_CLIENT_POST_PROCESS_MESSAGE, 0), + "ossl_statem_client_post_process_message"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_CLIENT_PROCESS_MESSAGE, 0), + "ossl_statem_client_process_message"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION, 0), + "ossl_statem_client_read_transition"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_CLIENT_WRITE_TRANSITION, 0), + "ossl_statem_client_write_transition"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER13_READ_TRANSITION, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER13_WRITE_TRANSITION, 0), + "ossl_statem_server13_write_transition"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_POST_PROCESS_MESSAGE, 0), + "ossl_statem_server_post_process_message"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_POST_WORK, 0), + "ossl_statem_server_post_work"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE, 0), + "ossl_statem_server_process_message"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION, 0), + "ossl_statem_server_read_transition"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_WRITE_TRANSITION, 0), + "ossl_statem_server_write_transition"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_PARSE_CA_NAMES, 0), "parse_ca_names"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_PITEM_NEW, 0), "pitem_new"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_PQUEUE_NEW, 0), "pqueue_new"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_PROCESS_KEY_SHARE_EXT, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_READ_STATE_MACHINE, 0), "read_state_machine"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SET_CLIENT_CIPHERSUITE, 0), + "set_client_ciphersuite"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET, 0), + "srp_generate_client_master_secret"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SRP_GENERATE_SERVER_MASTER_SECRET, 0), + "srp_generate_server_master_secret"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SRP_VERIFY_SERVER_PARAM, 0), + "srp_verify_server_param"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_CHANGE_CIPHER_STATE, 0), + "ssl3_change_cipher_state"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, 0), + "ssl3_check_cert_and_algorithm"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_CTRL, 0), "ssl3_ctrl"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_CTX_CTRL, 0), "ssl3_ctx_ctrl"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_DIGEST_CACHED_RECORDS, 0), + "ssl3_digest_cached_records"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC, 0), + "ssl3_do_change_cipher_spec"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_ENC, 0), "ssl3_enc"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_FINAL_FINISH_MAC, 0), + "ssl3_final_finish_mac"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_FINISH_MAC, 0), "ssl3_finish_mac"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_GENERATE_KEY_BLOCK, 0), + "ssl3_generate_key_block"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_GENERATE_MASTER_SECRET, 0), + "ssl3_generate_master_secret"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_GET_RECORD, 0), "ssl3_get_record"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_INIT_FINISHED_MAC, 0), + "ssl3_init_finished_mac"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_OUTPUT_CERT_CHAIN, 0), + "ssl3_output_cert_chain"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_READ_BYTES, 0), "ssl3_read_bytes"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_READ_N, 0), "ssl3_read_n"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_SETUP_KEY_BLOCK, 0), + "ssl3_setup_key_block"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_SETUP_READ_BUFFER, 0), + "ssl3_setup_read_buffer"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_SETUP_WRITE_BUFFER, 0), + "ssl3_setup_write_buffer"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_WRITE_BYTES, 0), "ssl3_write_bytes"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_WRITE_PENDING, 0), "ssl3_write_pending"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_ADD_CERT_CHAIN, 0), "ssl_add_cert_chain"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_ADD_CERT_TO_BUF, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_ADD_CERT_TO_WPACKET, 0), + "ssl_add_cert_to_wpacket"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK, 0), + "SSL_add_dir_cert_subjects_to_stack"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK, 0), + "SSL_add_file_cert_subjects_to_stack"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_BAD_METHOD, 0), "ssl_bad_method"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_BUILD_CERT_CHAIN, 0), + "ssl_build_cert_chain"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_BYTES_TO_CIPHER_LIST, 0), + "SSL_bytes_to_cipher_list"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CACHE_CIPHERLIST, 0), + "ssl_cache_cipherlist"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CERT_ADD0_CHAIN_CERT, 0), + "ssl_cert_add0_chain_cert"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CERT_DUP, 0), "ssl_cert_dup"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CERT_NEW, 0), "ssl_cert_new"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CERT_SET0_CHAIN, 0), + "ssl_cert_set0_chain"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CHECK_PRIVATE_KEY, 0), + "SSL_check_private_key"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CHECK_SRP_EXT_CLIENTHELLO, 0), + "ssl_check_srp_ext_ClientHello"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG, 0), + "ssl_check_srvr_ecc_cert_and_alg"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CHOOSE_CLIENT_VERSION, 0), + "ssl_choose_client_version"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CIPHER_DESCRIPTION, 0), + "SSL_CIPHER_description"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CIPHER_LIST_TO_BYTES, 0), + "ssl_cipher_list_to_bytes"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CIPHER_PROCESS_RULESTR, 0), + "ssl_cipher_process_rulestr"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CIPHER_STRENGTH_SORT, 0), + "ssl_cipher_strength_sort"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CLEAR, 0), "SSL_clear"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CLIENT_HELLO_GET1_EXTENSIONS_PRESENT, 0), + "SSL_client_hello_get1_extensions_present"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD, 0), + "SSL_COMP_add_compression_method"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CONF_CMD, 0), "SSL_CONF_cmd"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CREATE_CIPHER_LIST, 0), + "ssl_create_cipher_list"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTRL, 0), "SSL_ctrl"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_CHECK_PRIVATE_KEY, 0), + "SSL_CTX_check_private_key"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_ENABLE_CT, 0), "SSL_CTX_enable_ct"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_MAKE_PROFILES, 0), + "ssl_ctx_make_profiles"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_NEW, 0), "SSL_CTX_new"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_SET_ALPN_PROTOS, 0), + "SSL_CTX_set_alpn_protos"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_SET_CIPHER_LIST, 0), + "SSL_CTX_set_cipher_list"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE, 0), + "SSL_CTX_set_client_cert_engine"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_SET_CT_VALIDATION_CALLBACK, 0), + "SSL_CTX_set_ct_validation_callback"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT, 0), + "SSL_CTX_set_session_id_context"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_SET_SSL_VERSION, 0), + "SSL_CTX_set_ssl_version"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_SET_TLSEXT_MAX_FRAGMENT_LENGTH, 0), + "SSL_CTX_set_tlsext_max_fragment_length"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_CERTIFICATE, 0), + "SSL_CTX_use_certificate"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1, 0), + "SSL_CTX_use_certificate_ASN1"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, 0), + "SSL_CTX_use_certificate_file"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_PRIVATEKEY, 0), + "SSL_CTX_use_PrivateKey"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1, 0), + "SSL_CTX_use_PrivateKey_ASN1"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, 0), + "SSL_CTX_use_PrivateKey_file"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT, 0), + "SSL_CTX_use_psk_identity_hint"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_RSAPRIVATEKEY, 0), + "SSL_CTX_use_RSAPrivateKey"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1, 0), + "SSL_CTX_use_RSAPrivateKey_ASN1"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE, 0), + "SSL_CTX_use_RSAPrivateKey_file"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_SERVERINFO, 0), + "SSL_CTX_use_serverinfo"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_SERVERINFO_EX, 0), + "SSL_CTX_use_serverinfo_ex"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_SERVERINFO_FILE, 0), + "SSL_CTX_use_serverinfo_file"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_DANE_DUP, 0), "ssl_dane_dup"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_DANE_ENABLE, 0), "SSL_dane_enable"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_DERIVE, 0), "ssl_derive"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_DO_CONFIG, 0), "ssl_do_config"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_DO_HANDSHAKE, 0), "SSL_do_handshake"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_DUP_CA_LIST, 0), "SSL_dup_CA_list"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_ENABLE_CT, 0), "SSL_enable_ct"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_GENERATE_PKEY_GROUP, 0), + "ssl_generate_pkey_group"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_GENERATE_SESSION_ID, 0), + "ssl_generate_session_id"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_GET_NEW_SESSION, 0), + "ssl_get_new_session"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_GET_PREV_SESSION, 0), + "ssl_get_prev_session"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_GET_SERVER_CERT_INDEX, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_GET_SIGN_PKEY, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_HANDSHAKE_HASH, 0), "ssl_handshake_hash"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_INIT_WBIO_BUFFER, 0), + "ssl_init_wbio_buffer"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_KEY_UPDATE, 0), "SSL_key_update"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_LOAD_CLIENT_CA_FILE, 0), + "SSL_load_client_CA_file"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_LOG_MASTER_SECRET, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_LOG_RSA_CLIENT_KEY_EXCHANGE, 0), + "ssl_log_rsa_client_key_exchange"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_MODULE_INIT, 0), "ssl_module_init"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_NEW, 0), "SSL_new"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_NEXT_PROTO_VALIDATE, 0), + "ssl_next_proto_validate"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_PEEK, 0), "SSL_peek"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_PEEK_EX, 0), "SSL_peek_ex"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_PEEK_INTERNAL, 0), "ssl_peek_internal"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_READ, 0), "SSL_read"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_READ_EARLY_DATA, 0), + "SSL_read_early_data"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_READ_EX, 0), "SSL_read_ex"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_READ_INTERNAL, 0), "ssl_read_internal"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_RENEGOTIATE, 0), "SSL_renegotiate"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_RENEGOTIATE_ABBREVIATED, 0), + "SSL_renegotiate_abbreviated"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SESSION_DUP, 0), "ssl_session_dup"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SESSION_NEW, 0), "SSL_SESSION_new"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SESSION_PRINT_FP, 0), + "SSL_SESSION_print_fp"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SESSION_SET1_ID, 0), + "SSL_SESSION_set1_id"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SESSION_SET1_ID_CONTEXT, 0), + "SSL_SESSION_set1_id_context"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_ALPN_PROTOS, 0), + "SSL_set_alpn_protos"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_CERT, 0), "ssl_set_cert"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_CERT_AND_KEY, 0), + "ssl_set_cert_and_key"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_CIPHER_LIST, 0), + "SSL_set_cipher_list"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_CT_VALIDATION_CALLBACK, 0), + "SSL_set_ct_validation_callback"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_FD, 0), "SSL_set_fd"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_PKEY, 0), "ssl_set_pkey"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_RFD, 0), "SSL_set_rfd"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_SESSION, 0), "SSL_set_session"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_SESSION_ID_CONTEXT, 0), + "SSL_set_session_id_context"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_SESSION_TICKET_EXT, 0), + "SSL_set_session_ticket_ext"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_TLSEXT_MAX_FRAGMENT_LENGTH, 0), + "SSL_set_tlsext_max_fragment_length"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_WFD, 0), "SSL_set_wfd"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SHUTDOWN, 0), "SSL_shutdown"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SRP_CTX_INIT, 0), "SSL_SRP_CTX_init"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_START_ASYNC_JOB, 0), + "ssl_start_async_job"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_UNDEFINED_FUNCTION, 0), + "ssl_undefined_function"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_UNDEFINED_VOID_FUNCTION, 0), + "ssl_undefined_void_function"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_CERTIFICATE, 0), + "SSL_use_certificate"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_CERTIFICATE_ASN1, 0), + "SSL_use_certificate_ASN1"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_CERTIFICATE_FILE, 0), + "SSL_use_certificate_file"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_PRIVATEKEY, 0), "SSL_use_PrivateKey"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_PRIVATEKEY_ASN1, 0), + "SSL_use_PrivateKey_ASN1"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_PRIVATEKEY_FILE, 0), + "SSL_use_PrivateKey_file"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_PSK_IDENTITY_HINT, 0), + "SSL_use_psk_identity_hint"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_RSAPRIVATEKEY, 0), + "SSL_use_RSAPrivateKey"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1, 0), + "SSL_use_RSAPrivateKey_ASN1"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_USE_RSAPRIVATEKEY_FILE, 0), + "SSL_use_RSAPrivateKey_file"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_VALIDATE_CT, 0), "ssl_validate_ct"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_VERIFY_CERT_CHAIN, 0), + "ssl_verify_cert_chain"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, 0), + "SSL_verify_client_post_handshake"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_WRITE, 0), "SSL_write"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_WRITE_EARLY_DATA, 0), + "SSL_write_early_data"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_WRITE_EARLY_FINISH, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_WRITE_EX, 0), "SSL_write_ex"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_WRITE_INTERNAL, 0), "ssl_write_internal"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_STATE_MACHINE, 0), "state_machine"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS12_CHECK_PEER_SIGALG, 0), + "tls12_check_peer_sigalg"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS12_COPY_SIGALGS, 0), "tls12_copy_sigalgs"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS13_CHANGE_CIPHER_STATE, 0), + "tls13_change_cipher_state"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS13_ENC, 0), "tls13_enc"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS13_FINAL_FINISH_MAC, 0), + "tls13_final_finish_mac"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS13_GENERATE_SECRET, 0), + "tls13_generate_secret"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS13_HKDF_EXPAND, 0), "tls13_hkdf_expand"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS13_RESTORE_HANDSHAKE_DIGEST_FOR_PHA, 0), + "tls13_restore_handshake_digest_for_pha"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS13_SAVE_HANDSHAKE_DIGEST_FOR_PHA, 0), + "tls13_save_handshake_digest_for_pha"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS13_SETUP_KEY_BLOCK, 0), + "tls13_setup_key_block"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_CHANGE_CIPHER_STATE, 0), + "tls1_change_cipher_state"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_CHECK_DUPLICATE_EXTENSIONS, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_ENC, 0), "tls1_enc"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_EXPORT_KEYING_MATERIAL, 0), + "tls1_export_keying_material"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_GET_CURVELIST, 0), "tls1_get_curvelist"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_PRF, 0), "tls1_PRF"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_SAVE_U16, 0), "tls1_save_u16"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_SETUP_KEY_BLOCK, 0), + "tls1_setup_key_block"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_SET_GROUPS, 0), "tls1_set_groups"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_SET_RAW_SIGALGS, 0), + "tls1_set_raw_sigalgs"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_SET_SERVER_SIGALGS, 0), + "tls1_set_server_sigalgs"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_SET_SHARED_SIGALGS, 0), + "tls1_set_shared_sigalgs"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_SET_SIGALGS, 0), "tls1_set_sigalgs"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CHOOSE_SIGALG, 0), "tls_choose_sigalg"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK, 0), + "tls_client_key_exchange_post_work"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_COLLECT_EXTENSIONS, 0), + "tls_collect_extensions"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CERTIFICATE_AUTHORITIES, 0), + "tls_construct_certificate_authorities"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, 0), + "tls_construct_certificate_request"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CERT_STATUS, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CERT_STATUS_BODY, 0), + "tls_construct_cert_status_body"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CERT_VERIFY, 0), + "tls_construct_cert_verify"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CHANGE_CIPHER_SPEC, 0), + "tls_construct_change_cipher_spec"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CKE_DHE, 0), + "tls_construct_cke_dhe"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CKE_ECDHE, 0), + "tls_construct_cke_ecdhe"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CKE_GOST, 0), + "tls_construct_cke_gost"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, 0), + "tls_construct_cke_psk_preamble"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CKE_RSA, 0), + "tls_construct_cke_rsa"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CKE_SRP, 0), + "tls_construct_cke_srp"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE, 0), + "tls_construct_client_certificate"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, 0), + "tls_construct_client_hello"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, 0), + "tls_construct_client_key_exchange"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_ALPN, 0), + "tls_construct_ctos_alpn"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_CERTIFICATE, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_COOKIE, 0), + "tls_construct_ctos_cookie"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, 0), + "tls_construct_ctos_early_data"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_EC_PT_FORMATS, 0), + "tls_construct_ctos_ec_pt_formats"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_EMS, 0), + "tls_construct_ctos_ems"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_ETM, 0), + "tls_construct_ctos_etm"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_HELLO, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_KEY_EXCHANGE, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE, 0), + "tls_construct_ctos_key_share"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_MAXFRAGMENTLEN, 0), + "tls_construct_ctos_maxfragmentlen"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_NPN, 0), + "tls_construct_ctos_npn"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_PADDING, 0), + "tls_construct_ctos_padding"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_POST_HANDSHAKE_AUTH, 0), + "tls_construct_ctos_post_handshake_auth"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_PSK, 0), + "tls_construct_ctos_psk"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES, 0), + "tls_construct_ctos_psk_kex_modes"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE, 0), + "tls_construct_ctos_renegotiate"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_SCT, 0), + "tls_construct_ctos_sct"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_SERVER_NAME, 0), + "tls_construct_ctos_server_name"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_SESSION_TICKET, 0), + "tls_construct_ctos_session_ticket"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_SIG_ALGS, 0), + "tls_construct_ctos_sig_algs"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_SRP, 0), + "tls_construct_ctos_srp"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST, 0), + "tls_construct_ctos_status_request"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS, 0), + "tls_construct_ctos_supported_groups"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, 0), + "tls_construct_ctos_supported_versions"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP, 0), + "tls_construct_ctos_use_srtp"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_VERIFY, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_ENCRYPTED_EXTENSIONS, 0), + "tls_construct_encrypted_extensions"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_END_OF_EARLY_DATA, 0), + "tls_construct_end_of_early_data"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_EXTENSIONS, 0), + "tls_construct_extensions"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_FINISHED, 0), + "tls_construct_finished"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_HELLO_REQUEST, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_HELLO_RETRY_REQUEST, 0), + "tls_construct_hello_retry_request"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_KEY_UPDATE, 0), + "tls_construct_key_update"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, 0), + "tls_construct_new_session_ticket"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_NEXT_PROTO, 0), + "tls_construct_next_proto"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE, 0), + "tls_construct_server_certificate"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_SERVER_HELLO, 0), + "tls_construct_server_hello"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, 0), + "tls_construct_server_key_exchange"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_ALPN, 0), + "tls_construct_stoc_alpn"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_CERTIFICATE, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_COOKIE, 0), + "tls_construct_stoc_cookie"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_CRYPTOPRO_BUG, 0), + "tls_construct_stoc_cryptopro_bug"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_DONE, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA, 0), + "tls_construct_stoc_early_data"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA_INFO, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_EC_PT_FORMATS, 0), + "tls_construct_stoc_ec_pt_formats"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_EMS, 0), + "tls_construct_stoc_ems"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_ETM, 0), + "tls_construct_stoc_etm"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_HELLO, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_KEY_EXCHANGE, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, 0), + "tls_construct_stoc_key_share"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_MAXFRAGMENTLEN, 0), + "tls_construct_stoc_maxfragmentlen"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_NEXT_PROTO_NEG, 0), + "tls_construct_stoc_next_proto_neg"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_PSK, 0), + "tls_construct_stoc_psk"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE, 0), + "tls_construct_stoc_renegotiate"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_SERVER_NAME, 0), + "tls_construct_stoc_server_name"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_SESSION_TICKET, 0), + "tls_construct_stoc_session_ticket"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST, 0), + "tls_construct_stoc_status_request"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS, 0), + "tls_construct_stoc_supported_groups"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS, 0), + "tls_construct_stoc_supported_versions"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_USE_SRTP, 0), + "tls_construct_stoc_use_srtp"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, 0), + "tls_early_post_process_client_hello"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_FINISH_HANDSHAKE, 0), + "tls_finish_handshake"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_GET_MESSAGE_BODY, 0), + "tls_get_message_body"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_GET_MESSAGE_HEADER, 0), + "tls_get_message_header"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_HANDLE_ALPN, 0), "tls_handle_alpn"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_HANDLE_STATUS_REQUEST, 0), + "tls_handle_status_request"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CERTIFICATE_AUTHORITIES, 0), + "tls_parse_certificate_authorities"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CLIENTHELLO_TLSEXT, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_ALPN, 0), + "tls_parse_ctos_alpn"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_COOKIE, 0), + "tls_parse_ctos_cookie"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_EARLY_DATA, 0), + "tls_parse_ctos_early_data"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS, 0), + "tls_parse_ctos_ec_pt_formats"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_EMS, 0), "tls_parse_ctos_ems"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_KEY_SHARE, 0), + "tls_parse_ctos_key_share"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN, 0), + "tls_parse_ctos_maxfragmentlen"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_POST_HANDSHAKE_AUTH, 0), + "tls_parse_ctos_post_handshake_auth"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_PSK, 0), "tls_parse_ctos_psk"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES, 0), + "tls_parse_ctos_psk_kex_modes"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE, 0), + "tls_parse_ctos_renegotiate"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_SERVER_NAME, 0), + "tls_parse_ctos_server_name"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_SESSION_TICKET, 0), + "tls_parse_ctos_session_ticket"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_SIG_ALGS, 0), + "tls_parse_ctos_sig_algs"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_SIG_ALGS_CERT, 0), + "tls_parse_ctos_sig_algs_cert"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_SRP, 0), "tls_parse_ctos_srp"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, 0), + "tls_parse_ctos_status_request"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS, 0), + "tls_parse_ctos_supported_groups"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_USE_SRTP, 0), + "tls_parse_ctos_use_srtp"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_ALPN, 0), + "tls_parse_stoc_alpn"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_COOKIE, 0), + "tls_parse_stoc_cookie"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_EARLY_DATA, 0), + "tls_parse_stoc_early_data"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_EARLY_DATA_INFO, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS, 0), + "tls_parse_stoc_ec_pt_formats"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_KEY_SHARE, 0), + "tls_parse_stoc_key_share"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN, 0), + "tls_parse_stoc_maxfragmentlen"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_NPN, 0), "tls_parse_stoc_npn"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_PSK, 0), "tls_parse_stoc_psk"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_RENEGOTIATE, 0), + "tls_parse_stoc_renegotiate"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_SCT, 0), "tls_parse_stoc_sct"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_SERVER_NAME, 0), + "tls_parse_stoc_server_name"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_SESSION_TICKET, 0), + "tls_parse_stoc_session_ticket"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_STATUS_REQUEST, 0), + "tls_parse_stoc_status_request"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS, 0), + "tls_parse_stoc_supported_versions"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_USE_SRTP, 0), + "tls_parse_stoc_use_srtp"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_POST_PROCESS_CLIENT_HELLO, 0), + "tls_post_process_client_hello"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE, 0), + "tls_post_process_client_key_exchange"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE, 0), + "tls_prepare_client_certificate"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_AS_HELLO_RETRY_REQUEST, 0), + "tls_process_as_hello_retry_request"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, 0), + "tls_process_certificate_request"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CERT_STATUS, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CERT_STATUS_BODY, 0), + "tls_process_cert_status_body"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CERT_VERIFY, 0), + "tls_process_cert_verify"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, 0), + "tls_process_change_cipher_spec"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CKE_DHE, 0), + "tls_process_cke_dhe"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CKE_ECDHE, 0), + "tls_process_cke_ecdhe"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CKE_GOST, 0), + "tls_process_cke_gost"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, 0), + "tls_process_cke_psk_preamble"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CKE_RSA, 0), + "tls_process_cke_rsa"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CKE_SRP, 0), + "tls_process_cke_srp"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, 0), + "tls_process_client_certificate"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CLIENT_HELLO, 0), + "tls_process_client_hello"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, 0), + "tls_process_client_key_exchange"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_ENCRYPTED_EXTENSIONS, 0), + "tls_process_encrypted_extensions"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_END_OF_EARLY_DATA, 0), + "tls_process_end_of_early_data"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_FINISHED, 0), + "tls_process_finished"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_HELLO_REQ, 0), + "tls_process_hello_req"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST, 0), + "tls_process_hello_retry_request"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_INITIAL_SERVER_FLIGHT, 0), + "tls_process_initial_server_flight"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_KEY_EXCHANGE, 0), + "tls_process_key_exchange"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_KEY_UPDATE, 0), + "tls_process_key_update"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, 0), + "tls_process_new_session_ticket"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_NEXT_PROTO, 0), + "tls_process_next_proto"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, 0), + "tls_process_server_certificate"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_SERVER_DONE, 0), + "tls_process_server_done"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_SERVER_HELLO, 0), + "tls_process_server_hello"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_SKE_DHE, 0), + "tls_process_ske_dhe"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_SKE_ECDHE, 0), + "tls_process_ske_ecdhe"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE, 0), + "tls_process_ske_psk_preamble"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_SKE_SRP, 0), + "tls_process_ske_srp"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PSK_DO_BINDER, 0), "tls_psk_do_binder"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_SCAN_CLIENTHELLO_TLSEXT, 0), ""}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_SETUP_HANDSHAKE, 0), + "tls_setup_handshake"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_USE_CERTIFICATE_CHAIN_FILE, 0), + "use_certificate_chain_file"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_WPACKET_INTERN_INIT_LEN, 0), + "wpacket_intern_init_len"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_WPACKET_START_SUB_PACKET_LEN__, 0), + "WPACKET_start_sub_packet_len__"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_WRITE_STATE_MACHINE, 0), + "write_state_machine"}, + {0, NULL} +}; + +static const ERR_STRING_DATA SSL_str_reasons[] = { + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY), + "application data after close notify"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_APP_DATA_IN_HANDSHAKE), + "app data in handshake"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT), + "attempt to reuse session in different context"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_AT_LEAST_TLS_1_0_NEEDED_IN_FIPS_MODE), + "at least TLS 1.0 needed in FIPS mode"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE), + "at least (D)TLS 1.2 needed in Suite B mode"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_CHANGE_CIPHER_SPEC), + "bad change cipher spec"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_CIPHER), "bad cipher"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_DATA), "bad data"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_DATA_RETURNED_BY_CALLBACK), + "bad data returned by callback"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_DECOMPRESSION), "bad decompression"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_DH_VALUE), "bad dh value"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_DIGEST_LENGTH), "bad digest length"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_EARLY_DATA), "bad early data"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_ECC_CERT), "bad ecc cert"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_ECPOINT), "bad ecpoint"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_EXTENSION), "bad extension"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_HANDSHAKE_LENGTH), + "bad handshake length"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_HANDSHAKE_STATE), + "bad handshake state"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_HELLO_REQUEST), "bad hello request"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_HRR_VERSION), "bad hrr version"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_KEY_SHARE), "bad key share"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_KEY_UPDATE), "bad key update"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_LEGACY_VERSION), "bad legacy version"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_LENGTH), "bad length"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_PACKET), "bad packet"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_PACKET_LENGTH), "bad packet length"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_PROTOCOL_VERSION_NUMBER), + "bad protocol version number"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_PSK), "bad psk"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_PSK_IDENTITY), "bad psk identity"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_RECORD_TYPE), "bad record type"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_RSA_ENCRYPT), "bad rsa encrypt"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_SIGNATURE), "bad signature"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_SRP_A_LENGTH), "bad srp a length"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_SRP_PARAMETERS), "bad srp parameters"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_SRTP_MKI_VALUE), "bad srtp mki value"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST), + "bad srtp protection profile list"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_SSL_FILETYPE), "bad ssl filetype"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_VALUE), "bad value"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_WRITE_RETRY), "bad write retry"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BINDER_DOES_NOT_VERIFY), + "binder does not verify"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BIO_NOT_SET), "bio not set"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BLOCK_CIPHER_PAD_IS_WRONG), + "block cipher pad is wrong"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BN_LIB), "bn lib"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CALLBACK_FAILED), "callback failed"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CANNOT_CHANGE_CIPHER), + "cannot change cipher"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CA_DN_LENGTH_MISMATCH), + "ca dn length mismatch"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CA_KEY_TOO_SMALL), "ca key too small"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CA_MD_TOO_WEAK), "ca md too weak"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CCS_RECEIVED_EARLY), "ccs received early"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CERTIFICATE_VERIFY_FAILED), + "certificate verify failed"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CERT_CB_ERROR), "cert cb error"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CERT_LENGTH_MISMATCH), + "cert length mismatch"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CIPHERSUITE_DIGEST_HAS_CHANGED), + "ciphersuite digest has changed"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CIPHER_CODE_WRONG_LENGTH), + "cipher code wrong length"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CIPHER_OR_HASH_UNAVAILABLE), + "cipher or hash unavailable"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CLIENTHELLO_TLSEXT), "clienthello tlsext"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_COMPRESSED_LENGTH_TOO_LONG), + "compressed length too long"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_COMPRESSION_DISABLED), + "compression disabled"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_COMPRESSION_FAILURE), + "compression failure"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE), + "compression id not within private range"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_COMPRESSION_LIBRARY_ERROR), + "compression library error"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CONNECTION_TYPE_NOT_SET), + "connection type not set"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CONTEXT_NOT_DANE_ENABLED), + "context not dane enabled"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_COOKIE_GEN_CALLBACK_FAILURE), + "cookie gen callback failure"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_COOKIE_MISMATCH), "cookie mismatch"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CUSTOM_EXT_HANDLER_ALREADY_INSTALLED), + "custom ext handler already installed"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DANE_ALREADY_ENABLED), + "dane already enabled"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DANE_CANNOT_OVERRIDE_MTYPE_FULL), + "dane cannot override mtype full"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DANE_NOT_ENABLED), "dane not enabled"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DANE_TLSA_BAD_CERTIFICATE), + "dane tlsa bad certificate"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DANE_TLSA_BAD_CERTIFICATE_USAGE), + "dane tlsa bad certificate usage"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DANE_TLSA_BAD_DATA_LENGTH), + "dane tlsa bad data length"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DANE_TLSA_BAD_DIGEST_LENGTH), + "dane tlsa bad digest length"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DANE_TLSA_BAD_MATCHING_TYPE), + "dane tlsa bad matching type"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DANE_TLSA_BAD_PUBLIC_KEY), + "dane tlsa bad public key"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DANE_TLSA_BAD_SELECTOR), + "dane tlsa bad selector"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DANE_TLSA_NULL_DATA), + "dane tlsa null data"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DATA_BETWEEN_CCS_AND_FINISHED), + "data between ccs and finished"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DATA_LENGTH_TOO_LONG), + "data length too long"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DECRYPTION_FAILED), "decryption failed"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC), + "decryption failed or bad record mac"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DH_KEY_TOO_SMALL), "dh key too small"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG), + "dh public value length is wrong"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DIGEST_CHECK_FAILED), + "digest check failed"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DTLS_MESSAGE_TOO_BIG), + "dtls message too big"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DUPLICATE_COMPRESSION_ID), + "duplicate compression id"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ECC_CERT_NOT_FOR_SIGNING), + "ecc cert not for signing"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE), + "ecdh required for suiteb mode"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_EE_KEY_TOO_SMALL), "ee key too small"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST), + "empty srtp protection profile list"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ENCRYPTED_LENGTH_TOO_LONG), + "encrypted length too long"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST), + "error in received cipher list"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ERROR_SETTING_TLSA_BASE_DOMAIN), + "error setting tlsa base domain"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_EXCEEDS_MAX_FRAGMENT_SIZE), + "exceeds max fragment size"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_EXCESSIVE_MESSAGE_SIZE), + "excessive message size"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_EXTENSION_NOT_RECEIVED), + "extension not received"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_EXTRA_DATA_IN_MESSAGE), + "extra data in message"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_EXT_LENGTH_MISMATCH), + "ext length mismatch"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_FAILED_TO_INIT_ASYNC), + "failed to init async"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_FRAGMENTED_CLIENT_HELLO), + "fragmented client hello"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_GOT_A_FIN_BEFORE_A_CCS), + "got a fin before a ccs"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_HTTPS_PROXY_REQUEST), + "https proxy request"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_HTTP_REQUEST), "http request"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ILLEGAL_POINT_COMPRESSION), + "illegal point compression"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ILLEGAL_SUITEB_DIGEST), + "illegal Suite B digest"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INAPPROPRIATE_FALLBACK), + "inappropriate fallback"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INCONSISTENT_COMPRESSION), + "inconsistent compression"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INCONSISTENT_EARLY_DATA_ALPN), + "inconsistent early data alpn"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INCONSISTENT_EARLY_DATA_SNI), + "inconsistent early data sni"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INCONSISTENT_EXTMS), "inconsistent extms"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INSUFFICIENT_SECURITY), + "insufficient security"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_ALERT), "invalid alert"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_CCS_MESSAGE), + "invalid ccs message"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_CERTIFICATE_OR_ALG), + "invalid certificate or alg"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_COMMAND), "invalid command"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_COMPRESSION_ALGORITHM), + "invalid compression algorithm"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_CONFIG), "invalid config"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_CONFIGURATION_NAME), + "invalid configuration name"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_CONTEXT), "invalid context"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_CT_VALIDATION_TYPE), + "invalid ct validation type"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_KEY_UPDATE_TYPE), + "invalid key update type"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_MAX_EARLY_DATA), + "invalid max early data"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_NULL_CMD_NAME), + "invalid null cmd name"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_SEQUENCE_NUMBER), + "invalid sequence number"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_SERVERINFO_DATA), + "invalid serverinfo data"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_SESSION_ID), "invalid session id"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_SRP_USERNAME), + "invalid srp username"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_STATUS_RESPONSE), + "invalid status response"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_TICKET_KEYS_LENGTH), + "invalid ticket keys length"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_LENGTH_MISMATCH), "length mismatch"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_LENGTH_TOO_LONG), "length too long"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_LENGTH_TOO_SHORT), "length too short"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_LIBRARY_BUG), "library bug"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_LIBRARY_HAS_NO_CIPHERS), + "library has no ciphers"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_DSA_SIGNING_CERT), + "missing dsa signing cert"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_ECDSA_SIGNING_CERT), + "missing ecdsa signing cert"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_FATAL), "missing fatal"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_PARAMETERS), "missing parameters"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_RSA_CERTIFICATE), + "missing rsa certificate"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_RSA_ENCRYPTING_CERT), + "missing rsa encrypting cert"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_RSA_SIGNING_CERT), + "missing rsa signing cert"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_SIGALGS_EXTENSION), + "missing sigalgs extension"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_SIGNING_CERT), + "missing signing cert"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_SRP_PARAM), + "can't find SRP server param"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION), + "missing supported groups extension"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_TMP_DH_KEY), "missing tmp dh key"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_TMP_ECDH_KEY), + "missing tmp ecdh key"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MIXED_HANDSHAKE_AND_NON_HANDSHAKE_DATA), + "mixed handshake and non handshake data"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NOT_ON_RECORD_BOUNDARY), + "not on record boundary"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NOT_REPLACING_CERTIFICATE), + "not replacing certificate"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NOT_SERVER), "not server"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_APPLICATION_PROTOCOL), + "no application protocol"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_CERTIFICATES_RETURNED), + "no certificates returned"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_CERTIFICATE_ASSIGNED), + "no certificate assigned"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_CERTIFICATE_SET), "no certificate set"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_CHANGE_FOLLOWING_HRR), + "no change following hrr"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_CIPHERS_AVAILABLE), + "no ciphers available"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_CIPHERS_SPECIFIED), + "no ciphers specified"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_CIPHER_MATCH), "no cipher match"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_CLIENT_CERT_METHOD), + "no client cert method"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_COMPRESSION_SPECIFIED), + "no compression specified"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_COOKIE_CALLBACK_SET), + "no cookie callback set"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER), + "Peer haven't sent GOST certificate, required for selected ciphersuite"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_METHOD_SPECIFIED), + "no method specified"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_PEM_EXTENSIONS), "no pem extensions"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_PRIVATE_KEY_ASSIGNED), + "no private key assigned"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_PROTOCOLS_AVAILABLE), + "no protocols available"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_RENEGOTIATION), "no renegotiation"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_REQUIRED_DIGEST), "no required digest"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SHARED_CIPHER), "no shared cipher"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SHARED_GROUPS), "no shared groups"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS), + "no shared signature algorithms"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SRTP_PROFILES), "no srtp profiles"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SUITABLE_KEY_SHARE), + "no suitable key share"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM), + "no suitable signature algorithm"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_VALID_SCTS), "no valid scts"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_VERIFY_COOKIE_CALLBACK), + "no verify cookie callback"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NULL_SSL_CTX), "null ssl ctx"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NULL_SSL_METHOD_PASSED), + "null ssl method passed"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED), + "old session cipher not returned"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED), + "old session compression algorithm not returned"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_OVERFLOW_ERROR), "overflow error"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PACKET_LENGTH_TOO_LONG), + "packet length too long"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PARSE_TLSEXT), "parse tlsext"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PATH_TOO_LONG), "path too long"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE), + "peer did not return a certificate"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PEM_NAME_BAD_PREFIX), + "pem name bad prefix"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PEM_NAME_TOO_SHORT), "pem name too short"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PIPELINE_FAILURE), "pipeline failure"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_POST_HANDSHAKE_AUTH_ENCODING_ERR), + "post handshake auth encoding err"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PRIVATE_KEY_MISMATCH), + "private key mismatch"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PROTOCOL_IS_SHUTDOWN), + "protocol is shutdown"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PSK_IDENTITY_NOT_FOUND), + "psk identity not found"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PSK_NO_CLIENT_CB), "psk no client cb"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PSK_NO_SERVER_CB), "psk no server cb"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_READ_BIO_NOT_SET), "read bio not set"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_READ_TIMEOUT_EXPIRED), + "read timeout expired"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_RECORD_LENGTH_MISMATCH), + "record length mismatch"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_RECORD_TOO_SMALL), "record too small"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_RENEGOTIATE_EXT_TOO_LONG), + "renegotiate ext too long"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_RENEGOTIATION_ENCODING_ERR), + "renegotiation encoding err"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_RENEGOTIATION_MISMATCH), + "renegotiation mismatch"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_REQUEST_PENDING), "request pending"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_REQUEST_SENT), "request sent"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_REQUIRED_CIPHER_MISSING), + "required cipher missing"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_REQUIRED_COMPRESSION_ALGORITHM_MISSING), + "required compression algorithm missing"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING), + "scsv received when renegotiating"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SCT_VERIFICATION_FAILED), + "sct verification failed"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SERVERHELLO_TLSEXT), "serverhello tlsext"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED), + "session id context uninitialized"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHUTDOWN_WHILE_IN_INIT), + "shutdown while in init"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SIGNATURE_ALGORITHMS_ERROR), + "signature algorithms error"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE), + "signature for non signing certificate"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SRP_A_CALC), "error with the srp params"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES), + "srtp could not allocate profiles"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG), + "srtp protection profile list too long"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE), + "srtp unknown protection profile"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH), + "ssl3 ext invalid max fragment length"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL3_EXT_INVALID_SERVERNAME), + "ssl3 ext invalid servername"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE), + "ssl3 ext invalid servername type"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL3_SESSION_ID_TOO_LONG), + "ssl3 session id too long"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_BAD_CERTIFICATE), + "sslv3 alert bad certificate"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_BAD_RECORD_MAC), + "sslv3 alert bad record mac"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED), + "sslv3 alert certificate expired"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED), + "sslv3 alert certificate revoked"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN), + "sslv3 alert certificate unknown"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE), + "sslv3 alert decompression failure"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE), + "sslv3 alert handshake failure"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER), + "sslv3 alert illegal parameter"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_NO_CERTIFICATE), + "sslv3 alert no certificate"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE), + "sslv3 alert unexpected message"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE), + "sslv3 alert unsupported certificate"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL_COMMAND_SECTION_EMPTY), + "ssl command section empty"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL_COMMAND_SECTION_NOT_FOUND), + "ssl command section not found"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION), + "ssl ctx has no default ssl version"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL_HANDSHAKE_FAILURE), + "ssl handshake failure"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS), + "ssl library has no ciphers"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL_NEGATIVE_LENGTH), + "ssl negative length"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL_SECTION_EMPTY), "ssl section empty"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL_SECTION_NOT_FOUND), + "ssl section not found"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL_SESSION_ID_CALLBACK_FAILED), + "ssl session id callback failed"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL_SESSION_ID_CONFLICT), + "ssl session id conflict"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG), + "ssl session id context too long"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH), + "ssl session id has bad length"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL_SESSION_ID_TOO_LONG), + "ssl session id too long"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL_SESSION_VERSION_MISMATCH), + "ssl session version mismatch"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_STILL_IN_INIT), "still in init"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED), + "tlsv13 alert certificate required"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV13_ALERT_MISSING_EXTENSION), + "tlsv13 alert missing extension"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_ACCESS_DENIED), + "tlsv1 alert access denied"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_DECODE_ERROR), + "tlsv1 alert decode error"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_DECRYPTION_FAILED), + "tlsv1 alert decryption failed"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_DECRYPT_ERROR), + "tlsv1 alert decrypt error"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION), + "tlsv1 alert export restriction"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK), + "tlsv1 alert inappropriate fallback"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY), + "tlsv1 alert insufficient security"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_INTERNAL_ERROR), + "tlsv1 alert internal error"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_NO_RENEGOTIATION), + "tlsv1 alert no renegotiation"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_PROTOCOL_VERSION), + "tlsv1 alert protocol version"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_RECORD_OVERFLOW), + "tlsv1 alert record overflow"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_UNKNOWN_CA), + "tlsv1 alert unknown ca"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_USER_CANCELLED), + "tlsv1 alert user cancelled"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE), + "tlsv1 bad certificate hash value"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE), + "tlsv1 bad certificate status response"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE), + "tlsv1 certificate unobtainable"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_UNRECOGNIZED_NAME), + "tlsv1 unrecognized name"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_UNSUPPORTED_EXTENSION), + "tlsv1 unsupported extension"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_HEARTBEAT_PEER_DOESNT_ACCEPT), + "peer does not accept heartbeats"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_HEARTBEAT_PENDING), + "heartbeat request already pending"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL), + "tls illegal exporter label"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST), + "tls invalid ecpointformat list"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TOO_MANY_KEY_UPDATES), + "too many key updates"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TOO_MANY_WARN_ALERTS), + "too many warn alerts"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TOO_MUCH_EARLY_DATA), + "too much early data"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS), + "unable to find ecdh parameters"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS), + "unable to find public key parameters"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES), + "unable to load ssl3 md5 routines"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES), + "unable to load ssl3 sha1 routines"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_CCS_MESSAGE), + "unexpected ccs message"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_END_OF_EARLY_DATA), + "unexpected end of early data"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_MESSAGE), "unexpected message"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_RECORD), "unexpected record"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNINITIALIZED), "uninitialized"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_ALERT_TYPE), "unknown alert type"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_CERTIFICATE_TYPE), + "unknown certificate type"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_CIPHER_RETURNED), + "unknown cipher returned"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_CIPHER_TYPE), + "unknown cipher type"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_CMD_NAME), "unknown cmd name"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_COMMAND), "unknown command"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_DIGEST), "unknown digest"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE), + "unknown key exchange type"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_PKEY_TYPE), "unknown pkey type"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_PROTOCOL), "unknown protocol"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_SSL_VERSION), + "unknown ssl version"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_STATE), "unknown state"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED), + "unsafe legacy renegotiation disabled"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNSOLICITED_EXTENSION), + "unsolicited extension"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM), + "unsupported compression algorithm"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNSUPPORTED_ELLIPTIC_CURVE), + "unsupported elliptic curve"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNSUPPORTED_PROTOCOL), + "unsupported protocol"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNSUPPORTED_SSL_VERSION), + "unsupported ssl version"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNSUPPORTED_STATUS_TYPE), + "unsupported status type"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_USE_SRTP_NOT_NEGOTIATED), + "use srtp not negotiated"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_VERSION_TOO_HIGH), "version too high"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_VERSION_TOO_LOW), "version too low"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_CERTIFICATE_TYPE), + "wrong certificate type"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_CIPHER_RETURNED), + "wrong cipher returned"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_CURVE), "wrong curve"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_SIGNATURE_LENGTH), + "wrong signature length"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_SIGNATURE_SIZE), + "wrong signature size"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_SIGNATURE_TYPE), + "wrong signature type"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_SSL_VERSION), "wrong ssl version"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_VERSION_NUMBER), + "wrong version number"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_X509_LIB), "x509 lib"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_X509_VERIFICATION_SETUP_PROBLEMS), + "x509 verification setup problems"}, + {0, NULL} +}; + +#endif + +int ERR_load_SSL_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(SSL_str_functs[0].error) == NULL) { + ERR_load_strings_const(SSL_str_functs); + ERR_load_strings_const(SSL_str_reasons); + } +#endif + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_init.c b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_init.c new file mode 100644 index 000000000..f0969fa9b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_init.c @@ -0,0 +1,221 @@ +/* + * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "e_os.h" + +#include "internal/err.h" +#include +#include +#include "ssl_locl.h" +#include "internal/thread_once.h" + +static int stopped; + +static void ssl_library_stop(void); + +static CRYPTO_ONCE ssl_base = CRYPTO_ONCE_STATIC_INIT; +static int ssl_base_inited = 0; +DEFINE_RUN_ONCE_STATIC(ossl_init_ssl_base) +{ +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_ssl_base: " + "Adding SSL ciphers and digests\n"); +#endif +#ifndef OPENSSL_NO_DES + EVP_add_cipher(EVP_des_cbc()); + EVP_add_cipher(EVP_des_ede3_cbc()); +#endif +#ifndef OPENSSL_NO_IDEA + EVP_add_cipher(EVP_idea_cbc()); +#endif +#ifndef OPENSSL_NO_RC4 + EVP_add_cipher(EVP_rc4()); +# ifndef OPENSSL_NO_MD5 + EVP_add_cipher(EVP_rc4_hmac_md5()); +# endif +#endif +#ifndef OPENSSL_NO_RC2 + EVP_add_cipher(EVP_rc2_cbc()); + /* + * Not actually used for SSL/TLS but this makes PKCS#12 work if an + * application only calls SSL_library_init(). + */ + EVP_add_cipher(EVP_rc2_40_cbc()); +#endif + EVP_add_cipher(EVP_aes_128_cbc()); + EVP_add_cipher(EVP_aes_192_cbc()); + EVP_add_cipher(EVP_aes_256_cbc()); + EVP_add_cipher(EVP_aes_128_gcm()); + EVP_add_cipher(EVP_aes_256_gcm()); + EVP_add_cipher(EVP_aes_128_ccm()); + EVP_add_cipher(EVP_aes_256_ccm()); + EVP_add_cipher(EVP_aes_128_cbc_hmac_sha1()); + EVP_add_cipher(EVP_aes_256_cbc_hmac_sha1()); + EVP_add_cipher(EVP_aes_128_cbc_hmac_sha256()); + EVP_add_cipher(EVP_aes_256_cbc_hmac_sha256()); +#ifndef OPENSSL_NO_ARIA + EVP_add_cipher(EVP_aria_128_gcm()); + EVP_add_cipher(EVP_aria_256_gcm()); +#endif +#ifndef OPENSSL_NO_CAMELLIA + EVP_add_cipher(EVP_camellia_128_cbc()); + EVP_add_cipher(EVP_camellia_256_cbc()); +#endif +#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305) + EVP_add_cipher(EVP_chacha20_poly1305()); +#endif + +#ifndef OPENSSL_NO_SEED + EVP_add_cipher(EVP_seed_cbc()); +#endif + +#ifndef OPENSSL_NO_MD5 + EVP_add_digest(EVP_md5()); + EVP_add_digest_alias(SN_md5, "ssl3-md5"); + EVP_add_digest(EVP_md5_sha1()); +#endif + EVP_add_digest(EVP_sha1()); /* RSA with sha1 */ + EVP_add_digest_alias(SN_sha1, "ssl3-sha1"); + EVP_add_digest_alias(SN_sha1WithRSAEncryption, SN_sha1WithRSA); + EVP_add_digest(EVP_sha224()); + EVP_add_digest(EVP_sha256()); + EVP_add_digest(EVP_sha384()); + EVP_add_digest(EVP_sha512()); +#ifndef OPENSSL_NO_COMP +# ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_ssl_base: " + "SSL_COMP_get_compression_methods()\n"); +# endif + /* + * This will initialise the built-in compression algorithms. The value + * returned is a STACK_OF(SSL_COMP), but that can be discarded safely + */ + SSL_COMP_get_compression_methods(); +#endif + /* initialize cipher/digest methods table */ + if (!ssl_load_ciphers()) + return 0; + +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_ssl_base: " + "SSL_add_ssl_module()\n"); +#endif + /* + * We ignore an error return here. Not much we can do - but not that bad + * either. We can still safely continue. + */ + OPENSSL_atexit(ssl_library_stop); + ssl_base_inited = 1; + return 1; +} + +static CRYPTO_ONCE ssl_strings = CRYPTO_ONCE_STATIC_INIT; +static int ssl_strings_inited = 0; +DEFINE_RUN_ONCE_STATIC(ossl_init_load_ssl_strings) +{ + /* + * OPENSSL_NO_AUTOERRINIT is provided here to prevent at compile time + * pulling in all the error strings during static linking + */ +#if !defined(OPENSSL_NO_ERR) && !defined(OPENSSL_NO_AUTOERRINIT) +# ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_load_ssl_strings: " + "ERR_load_SSL_strings()\n"); +# endif + ERR_load_SSL_strings(); + ssl_strings_inited = 1; +#endif + return 1; +} + +DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_load_ssl_strings, + ossl_init_load_ssl_strings) +{ + /* Do nothing in this case */ + return 1; +} + +static void ssl_library_stop(void) +{ + /* Might be explicitly called and also by atexit */ + if (stopped) + return; + stopped = 1; + + if (ssl_base_inited) { +#ifndef OPENSSL_NO_COMP +# ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ssl_library_stop: " + "ssl_comp_free_compression_methods_int()\n"); +# endif + ssl_comp_free_compression_methods_int(); +#endif + } + + if (ssl_strings_inited) { +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ssl_library_stop: " + "err_free_strings_int()\n"); +#endif + /* + * If both crypto and ssl error strings are inited we will end up + * calling err_free_strings_int() twice - but that's ok. The second + * time will be a no-op. It's easier to do that than to try and track + * between the two libraries whether they have both been inited. + */ + err_free_strings_int(); + } +} + +/* + * If this function is called with a non NULL settings value then it must be + * called prior to any threads making calls to any OpenSSL functions, + * i.e. passing a non-null settings value is assumed to be single-threaded. + */ +int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS * settings) +{ + static int stoperrset = 0; + + if (stopped) { + if (!stoperrset) { + /* + * We only ever set this once to avoid getting into an infinite + * loop where the error system keeps trying to init and fails so + * sets an error etc + */ + stoperrset = 1; + SSLerr(SSL_F_OPENSSL_INIT_SSL, ERR_R_INIT_FAIL); + } + return 0; + } + + opts |= OPENSSL_INIT_ADD_ALL_CIPHERS + | OPENSSL_INIT_ADD_ALL_DIGESTS; +#ifndef OPENSSL_NO_AUTOLOAD_CONFIG + if ((opts & OPENSSL_INIT_NO_LOAD_CONFIG) == 0) + opts |= OPENSSL_INIT_LOAD_CONFIG; +#endif + + if (!OPENSSL_init_crypto(opts, settings)) + return 0; + + if (!RUN_ONCE(&ssl_base, ossl_init_ssl_base)) + return 0; + + if ((opts & OPENSSL_INIT_NO_LOAD_SSL_STRINGS) + && !RUN_ONCE_ALT(&ssl_strings, ossl_init_no_load_ssl_strings, + ossl_init_load_ssl_strings)) + return 0; + + if ((opts & OPENSSL_INIT_LOAD_SSL_STRINGS) + && !RUN_ONCE(&ssl_strings, ossl_init_load_ssl_strings)) + return 0; + + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_lib.c b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_lib.c new file mode 100644 index 000000000..4440a9ffe --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_lib.c @@ -0,0 +1,5581 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * Copyright 2005 Nokia. All rights reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "ssl_locl.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "internal/cryptlib.h" +#include "internal/refcount.h" + +const char SSL_version_str[] = OPENSSL_VERSION_TEXT; + +static int ssl_undefined_function_1(SSL *ssl, SSL3_RECORD *r, size_t s, int t) +{ + (void)r; + (void)s; + (void)t; + return ssl_undefined_function(ssl); +} + +static int ssl_undefined_function_2(SSL *ssl, SSL3_RECORD *r, unsigned char *s, + int t) +{ + (void)r; + (void)s; + (void)t; + return ssl_undefined_function(ssl); +} + +static int ssl_undefined_function_3(SSL *ssl, unsigned char *r, + unsigned char *s, size_t t, size_t *u) +{ + (void)r; + (void)s; + (void)t; + (void)u; + return ssl_undefined_function(ssl); +} + +static int ssl_undefined_function_4(SSL *ssl, int r) +{ + (void)r; + return ssl_undefined_function(ssl); +} + +static size_t ssl_undefined_function_5(SSL *ssl, const char *r, size_t s, + unsigned char *t) +{ + (void)r; + (void)s; + (void)t; + return ssl_undefined_function(ssl); +} + +static int ssl_undefined_function_6(int r) +{ + (void)r; + return ssl_undefined_function(NULL); +} + +static int ssl_undefined_function_7(SSL *ssl, unsigned char *r, size_t s, + const char *t, size_t u, + const unsigned char *v, size_t w, int x) +{ + (void)r; + (void)s; + (void)t; + (void)u; + (void)v; + (void)w; + (void)x; + return ssl_undefined_function(ssl); +} + +SSL3_ENC_METHOD ssl3_undef_enc_method = { + ssl_undefined_function_1, + ssl_undefined_function_2, + ssl_undefined_function, + ssl_undefined_function_3, + ssl_undefined_function_4, + ssl_undefined_function_5, + NULL, /* client_finished_label */ + 0, /* client_finished_label_len */ + NULL, /* server_finished_label */ + 0, /* server_finished_label_len */ + ssl_undefined_function_6, + ssl_undefined_function_7, +}; + +struct ssl_async_args { + SSL *s; + void *buf; + size_t num; + enum { READFUNC, WRITEFUNC, OTHERFUNC } type; + union { + int (*func_read) (SSL *, void *, size_t, size_t *); + int (*func_write) (SSL *, const void *, size_t, size_t *); + int (*func_other) (SSL *); + } f; +}; + +static const struct { + uint8_t mtype; + uint8_t ord; + int nid; +} dane_mds[] = { + { + DANETLS_MATCHING_FULL, 0, NID_undef + }, + { + DANETLS_MATCHING_2256, 1, NID_sha256 + }, + { + DANETLS_MATCHING_2512, 2, NID_sha512 + }, +}; + +static int dane_ctx_enable(struct dane_ctx_st *dctx) +{ + const EVP_MD **mdevp; + uint8_t *mdord; + uint8_t mdmax = DANETLS_MATCHING_LAST; + int n = ((int)mdmax) + 1; /* int to handle PrivMatch(255) */ + size_t i; + + if (dctx->mdevp != NULL) + return 1; + + mdevp = OPENSSL_zalloc(n * sizeof(*mdevp)); + mdord = OPENSSL_zalloc(n * sizeof(*mdord)); + + if (mdord == NULL || mdevp == NULL) { + OPENSSL_free(mdord); + OPENSSL_free(mdevp); + SSLerr(SSL_F_DANE_CTX_ENABLE, ERR_R_MALLOC_FAILURE); + return 0; + } + + /* Install default entries */ + for (i = 0; i < OSSL_NELEM(dane_mds); ++i) { + const EVP_MD *md; + + if (dane_mds[i].nid == NID_undef || + (md = EVP_get_digestbynid(dane_mds[i].nid)) == NULL) + continue; + mdevp[dane_mds[i].mtype] = md; + mdord[dane_mds[i].mtype] = dane_mds[i].ord; + } + + dctx->mdevp = mdevp; + dctx->mdord = mdord; + dctx->mdmax = mdmax; + + return 1; +} + +static void dane_ctx_final(struct dane_ctx_st *dctx) +{ + OPENSSL_free(dctx->mdevp); + dctx->mdevp = NULL; + + OPENSSL_free(dctx->mdord); + dctx->mdord = NULL; + dctx->mdmax = 0; +} + +static void tlsa_free(danetls_record *t) +{ + if (t == NULL) + return; + OPENSSL_free(t->data); + EVP_PKEY_free(t->spki); + OPENSSL_free(t); +} + +static void dane_final(SSL_DANE *dane) +{ + sk_danetls_record_pop_free(dane->trecs, tlsa_free); + dane->trecs = NULL; + + sk_X509_pop_free(dane->certs, X509_free); + dane->certs = NULL; + + X509_free(dane->mcert); + dane->mcert = NULL; + dane->mtlsa = NULL; + dane->mdpth = -1; + dane->pdpth = -1; +} + +/* + * dane_copy - Copy dane configuration, sans verification state. + */ +static int ssl_dane_dup(SSL *to, SSL *from) +{ + int num; + int i; + + if (!DANETLS_ENABLED(&from->dane)) + return 1; + + num = sk_danetls_record_num(from->dane.trecs); + dane_final(&to->dane); + to->dane.flags = from->dane.flags; + to->dane.dctx = &to->ctx->dane; + to->dane.trecs = sk_danetls_record_new_reserve(NULL, num); + + if (to->dane.trecs == NULL) { + SSLerr(SSL_F_SSL_DANE_DUP, ERR_R_MALLOC_FAILURE); + return 0; + } + + for (i = 0; i < num; ++i) { + danetls_record *t = sk_danetls_record_value(from->dane.trecs, i); + + if (SSL_dane_tlsa_add(to, t->usage, t->selector, t->mtype, + t->data, t->dlen) <= 0) + return 0; + } + return 1; +} + +static int dane_mtype_set(struct dane_ctx_st *dctx, + const EVP_MD *md, uint8_t mtype, uint8_t ord) +{ + int i; + + if (mtype == DANETLS_MATCHING_FULL && md != NULL) { + SSLerr(SSL_F_DANE_MTYPE_SET, SSL_R_DANE_CANNOT_OVERRIDE_MTYPE_FULL); + return 0; + } + + if (mtype > dctx->mdmax) { + const EVP_MD **mdevp; + uint8_t *mdord; + int n = ((int)mtype) + 1; + + mdevp = OPENSSL_realloc(dctx->mdevp, n * sizeof(*mdevp)); + if (mdevp == NULL) { + SSLerr(SSL_F_DANE_MTYPE_SET, ERR_R_MALLOC_FAILURE); + return -1; + } + dctx->mdevp = mdevp; + + mdord = OPENSSL_realloc(dctx->mdord, n * sizeof(*mdord)); + if (mdord == NULL) { + SSLerr(SSL_F_DANE_MTYPE_SET, ERR_R_MALLOC_FAILURE); + return -1; + } + dctx->mdord = mdord; + + /* Zero-fill any gaps */ + for (i = dctx->mdmax + 1; i < mtype; ++i) { + mdevp[i] = NULL; + mdord[i] = 0; + } + + dctx->mdmax = mtype; + } + + dctx->mdevp[mtype] = md; + /* Coerce ordinal of disabled matching types to 0 */ + dctx->mdord[mtype] = (md == NULL) ? 0 : ord; + + return 1; +} + +static const EVP_MD *tlsa_md_get(SSL_DANE *dane, uint8_t mtype) +{ + if (mtype > dane->dctx->mdmax) + return NULL; + return dane->dctx->mdevp[mtype]; +} + +static int dane_tlsa_add(SSL_DANE *dane, + uint8_t usage, + uint8_t selector, + uint8_t mtype, unsigned const char *data, size_t dlen) +{ + danetls_record *t; + const EVP_MD *md = NULL; + int ilen = (int)dlen; + int i; + int num; + + if (dane->trecs == NULL) { + SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_NOT_ENABLED); + return -1; + } + + if (ilen < 0 || dlen != (size_t)ilen) { + SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_DATA_LENGTH); + return 0; + } + + if (usage > DANETLS_USAGE_LAST) { + SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_CERTIFICATE_USAGE); + return 0; + } + + if (selector > DANETLS_SELECTOR_LAST) { + SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_SELECTOR); + return 0; + } + + if (mtype != DANETLS_MATCHING_FULL) { + md = tlsa_md_get(dane, mtype); + if (md == NULL) { + SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_MATCHING_TYPE); + return 0; + } + } + + if (md != NULL && dlen != (size_t)EVP_MD_size(md)) { + SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_DIGEST_LENGTH); + return 0; + } + if (!data) { + SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_NULL_DATA); + return 0; + } + + if ((t = OPENSSL_zalloc(sizeof(*t))) == NULL) { + SSLerr(SSL_F_DANE_TLSA_ADD, ERR_R_MALLOC_FAILURE); + return -1; + } + + t->usage = usage; + t->selector = selector; + t->mtype = mtype; + t->data = OPENSSL_malloc(dlen); + if (t->data == NULL) { + tlsa_free(t); + SSLerr(SSL_F_DANE_TLSA_ADD, ERR_R_MALLOC_FAILURE); + return -1; + } + memcpy(t->data, data, dlen); + t->dlen = dlen; + + /* Validate and cache full certificate or public key */ + if (mtype == DANETLS_MATCHING_FULL) { + const unsigned char *p = data; + X509 *cert = NULL; + EVP_PKEY *pkey = NULL; + + switch (selector) { + case DANETLS_SELECTOR_CERT: + if (!d2i_X509(&cert, &p, ilen) || p < data || + dlen != (size_t)(p - data)) { + tlsa_free(t); + SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_CERTIFICATE); + return 0; + } + if (X509_get0_pubkey(cert) == NULL) { + tlsa_free(t); + SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_CERTIFICATE); + return 0; + } + + if ((DANETLS_USAGE_BIT(usage) & DANETLS_TA_MASK) == 0) { + X509_free(cert); + break; + } + + /* + * For usage DANE-TA(2), we support authentication via "2 0 0" TLSA + * records that contain full certificates of trust-anchors that are + * not present in the wire chain. For usage PKIX-TA(0), we augment + * the chain with untrusted Full(0) certificates from DNS, in case + * they are missing from the chain. + */ + if ((dane->certs == NULL && + (dane->certs = sk_X509_new_null()) == NULL) || + !sk_X509_push(dane->certs, cert)) { + SSLerr(SSL_F_DANE_TLSA_ADD, ERR_R_MALLOC_FAILURE); + X509_free(cert); + tlsa_free(t); + return -1; + } + break; + + case DANETLS_SELECTOR_SPKI: + if (!d2i_PUBKEY(&pkey, &p, ilen) || p < data || + dlen != (size_t)(p - data)) { + tlsa_free(t); + SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_PUBLIC_KEY); + return 0; + } + + /* + * For usage DANE-TA(2), we support authentication via "2 1 0" TLSA + * records that contain full bare keys of trust-anchors that are + * not present in the wire chain. + */ + if (usage == DANETLS_USAGE_DANE_TA) + t->spki = pkey; + else + EVP_PKEY_free(pkey); + break; + } + } + + /*- + * Find the right insertion point for the new record. + * + * See crypto/x509/x509_vfy.c. We sort DANE-EE(3) records first, so that + * they can be processed first, as they require no chain building, and no + * expiration or hostname checks. Because DANE-EE(3) is numerically + * largest, this is accomplished via descending sort by "usage". + * + * We also sort in descending order by matching ordinal to simplify + * the implementation of digest agility in the verification code. + * + * The choice of order for the selector is not significant, so we + * use the same descending order for consistency. + */ + num = sk_danetls_record_num(dane->trecs); + for (i = 0; i < num; ++i) { + danetls_record *rec = sk_danetls_record_value(dane->trecs, i); + + if (rec->usage > usage) + continue; + if (rec->usage < usage) + break; + if (rec->selector > selector) + continue; + if (rec->selector < selector) + break; + if (dane->dctx->mdord[rec->mtype] > dane->dctx->mdord[mtype]) + continue; + break; + } + + if (!sk_danetls_record_insert(dane->trecs, t, i)) { + tlsa_free(t); + SSLerr(SSL_F_DANE_TLSA_ADD, ERR_R_MALLOC_FAILURE); + return -1; + } + dane->umask |= DANETLS_USAGE_BIT(usage); + + return 1; +} + +/* + * Return 0 if there is only one version configured and it was disabled + * at configure time. Return 1 otherwise. + */ +static int ssl_check_allowed_versions(int min_version, int max_version) +{ + int minisdtls = 0, maxisdtls = 0; + + /* Figure out if we're doing DTLS versions or TLS versions */ + if (min_version == DTLS1_BAD_VER + || min_version >> 8 == DTLS1_VERSION_MAJOR) + minisdtls = 1; + if (max_version == DTLS1_BAD_VER + || max_version >> 8 == DTLS1_VERSION_MAJOR) + maxisdtls = 1; + /* A wildcard version of 0 could be DTLS or TLS. */ + if ((minisdtls && !maxisdtls && max_version != 0) + || (maxisdtls && !minisdtls && min_version != 0)) { + /* Mixing DTLS and TLS versions will lead to sadness; deny it. */ + return 0; + } + + if (minisdtls || maxisdtls) { + /* Do DTLS version checks. */ + if (min_version == 0) + /* Ignore DTLS1_BAD_VER */ + min_version = DTLS1_VERSION; + if (max_version == 0) + max_version = DTLS1_2_VERSION; +#ifdef OPENSSL_NO_DTLS1_2 + if (max_version == DTLS1_2_VERSION) + max_version = DTLS1_VERSION; +#endif +#ifdef OPENSSL_NO_DTLS1 + if (min_version == DTLS1_VERSION) + min_version = DTLS1_2_VERSION; +#endif + /* Done massaging versions; do the check. */ + if (0 +#ifdef OPENSSL_NO_DTLS1 + || (DTLS_VERSION_GE(min_version, DTLS1_VERSION) + && DTLS_VERSION_GE(DTLS1_VERSION, max_version)) +#endif +#ifdef OPENSSL_NO_DTLS1_2 + || (DTLS_VERSION_GE(min_version, DTLS1_2_VERSION) + && DTLS_VERSION_GE(DTLS1_2_VERSION, max_version)) +#endif + ) + return 0; + } else { + /* Regular TLS version checks. */ + if (min_version == 0) + min_version = SSL3_VERSION; + if (max_version == 0) + max_version = TLS1_3_VERSION; +#ifdef OPENSSL_NO_TLS1_3 + if (max_version == TLS1_3_VERSION) + max_version = TLS1_2_VERSION; +#endif +#ifdef OPENSSL_NO_TLS1_2 + if (max_version == TLS1_2_VERSION) + max_version = TLS1_1_VERSION; +#endif +#ifdef OPENSSL_NO_TLS1_1 + if (max_version == TLS1_1_VERSION) + max_version = TLS1_VERSION; +#endif +#ifdef OPENSSL_NO_TLS1 + if (max_version == TLS1_VERSION) + max_version = SSL3_VERSION; +#endif +#ifdef OPENSSL_NO_SSL3 + if (min_version == SSL3_VERSION) + min_version = TLS1_VERSION; +#endif +#ifdef OPENSSL_NO_TLS1 + if (min_version == TLS1_VERSION) + min_version = TLS1_1_VERSION; +#endif +#ifdef OPENSSL_NO_TLS1_1 + if (min_version == TLS1_1_VERSION) + min_version = TLS1_2_VERSION; +#endif +#ifdef OPENSSL_NO_TLS1_2 + if (min_version == TLS1_2_VERSION) + min_version = TLS1_3_VERSION; +#endif + /* Done massaging versions; do the check. */ + if (0 +#ifdef OPENSSL_NO_SSL3 + || (min_version <= SSL3_VERSION && SSL3_VERSION <= max_version) +#endif +#ifdef OPENSSL_NO_TLS1 + || (min_version <= TLS1_VERSION && TLS1_VERSION <= max_version) +#endif +#ifdef OPENSSL_NO_TLS1_1 + || (min_version <= TLS1_1_VERSION && TLS1_1_VERSION <= max_version) +#endif +#ifdef OPENSSL_NO_TLS1_2 + || (min_version <= TLS1_2_VERSION && TLS1_2_VERSION <= max_version) +#endif +#ifdef OPENSSL_NO_TLS1_3 + || (min_version <= TLS1_3_VERSION && TLS1_3_VERSION <= max_version) +#endif + ) + return 0; + } + return 1; +} + +static void clear_ciphers(SSL *s) +{ + /* clear the current cipher */ + ssl_clear_cipher_ctx(s); + ssl_clear_hash_ctx(&s->read_hash); + ssl_clear_hash_ctx(&s->write_hash); +} + +int SSL_clear(SSL *s) +{ + if (s->method == NULL) { + SSLerr(SSL_F_SSL_CLEAR, SSL_R_NO_METHOD_SPECIFIED); + return 0; + } + + if (ssl_clear_bad_session(s)) { + SSL_SESSION_free(s->session); + s->session = NULL; + } + SSL_SESSION_free(s->psksession); + s->psksession = NULL; + OPENSSL_free(s->psksession_id); + s->psksession_id = NULL; + s->psksession_id_len = 0; + s->hello_retry_request = 0; + s->sent_tickets = 0; + + s->error = 0; + s->hit = 0; + s->shutdown = 0; + + if (s->renegotiate) { + SSLerr(SSL_F_SSL_CLEAR, ERR_R_INTERNAL_ERROR); + return 0; + } + + ossl_statem_clear(s); + + s->version = s->method->version; + s->client_version = s->version; + s->rwstate = SSL_NOTHING; + + BUF_MEM_free(s->init_buf); + s->init_buf = NULL; + clear_ciphers(s); + s->first_packet = 0; + + s->key_update = SSL_KEY_UPDATE_NONE; + + EVP_MD_CTX_free(s->pha_dgst); + s->pha_dgst = NULL; + + /* Reset DANE verification result state */ + s->dane.mdpth = -1; + s->dane.pdpth = -1; + X509_free(s->dane.mcert); + s->dane.mcert = NULL; + s->dane.mtlsa = NULL; + + /* Clear the verification result peername */ + X509_VERIFY_PARAM_move_peername(s->param, NULL); + + /* + * Check to see if we were changed into a different method, if so, revert + * back. + */ + if (s->method != s->ctx->method) { + s->method->ssl_free(s); + s->method = s->ctx->method; + if (!s->method->ssl_new(s)) + return 0; + } else { + if (!s->method->ssl_clear(s)) + return 0; + } + + RECORD_LAYER_clear(&s->rlayer); + + return 1; +} + +/** Used to change an SSL_CTXs default SSL method type */ +int SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *meth) +{ + STACK_OF(SSL_CIPHER) *sk; + + ctx->method = meth; + + if (!SSL_CTX_set_ciphersuites(ctx, TLS_DEFAULT_CIPHERSUITES)) { + SSLerr(SSL_F_SSL_CTX_SET_SSL_VERSION, SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS); + return 0; + } + sk = ssl_create_cipher_list(ctx->method, + ctx->tls13_ciphersuites, + &(ctx->cipher_list), + &(ctx->cipher_list_by_id), + SSL_DEFAULT_CIPHER_LIST, ctx->cert); + if ((sk == NULL) || (sk_SSL_CIPHER_num(sk) <= 0)) { + SSLerr(SSL_F_SSL_CTX_SET_SSL_VERSION, SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS); + return 0; + } + return 1; +} + +SSL *SSL_new(SSL_CTX *ctx) +{ + SSL *s; + + if (ctx == NULL) { + SSLerr(SSL_F_SSL_NEW, SSL_R_NULL_SSL_CTX); + return NULL; + } + if (ctx->method == NULL) { + SSLerr(SSL_F_SSL_NEW, SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION); + return NULL; + } + + s = OPENSSL_zalloc(sizeof(*s)); + if (s == NULL) + goto err; + + s->references = 1; + s->lock = CRYPTO_THREAD_lock_new(); + if (s->lock == NULL) { + OPENSSL_free(s); + s = NULL; + goto err; + } + + RECORD_LAYER_init(&s->rlayer, s); + + s->options = ctx->options; + s->dane.flags = ctx->dane.flags; + s->min_proto_version = ctx->min_proto_version; + s->max_proto_version = ctx->max_proto_version; + s->mode = ctx->mode; + s->max_cert_list = ctx->max_cert_list; + s->max_early_data = ctx->max_early_data; + s->recv_max_early_data = ctx->recv_max_early_data; + s->num_tickets = ctx->num_tickets; + s->pha_enabled = ctx->pha_enabled; + + /* Shallow copy of the ciphersuites stack */ + s->tls13_ciphersuites = sk_SSL_CIPHER_dup(ctx->tls13_ciphersuites); + if (s->tls13_ciphersuites == NULL) + goto err; + + /* + * Earlier library versions used to copy the pointer to the CERT, not + * its contents; only when setting new parameters for the per-SSL + * copy, ssl_cert_new would be called (and the direct reference to + * the per-SSL_CTX settings would be lost, but those still were + * indirectly accessed for various purposes, and for that reason they + * used to be known as s->ctx->default_cert). Now we don't look at the + * SSL_CTX's CERT after having duplicated it once. + */ + s->cert = ssl_cert_dup(ctx->cert); + if (s->cert == NULL) + goto err; + + RECORD_LAYER_set_read_ahead(&s->rlayer, ctx->read_ahead); + s->msg_callback = ctx->msg_callback; + s->msg_callback_arg = ctx->msg_callback_arg; + s->verify_mode = ctx->verify_mode; + s->not_resumable_session_cb = ctx->not_resumable_session_cb; + s->record_padding_cb = ctx->record_padding_cb; + s->record_padding_arg = ctx->record_padding_arg; + s->block_padding = ctx->block_padding; + s->sid_ctx_length = ctx->sid_ctx_length; + if (!ossl_assert(s->sid_ctx_length <= sizeof(s->sid_ctx))) + goto err; + memcpy(&s->sid_ctx, &ctx->sid_ctx, sizeof(s->sid_ctx)); + s->verify_callback = ctx->default_verify_callback; + s->generate_session_id = ctx->generate_session_id; + + s->param = X509_VERIFY_PARAM_new(); + if (s->param == NULL) + goto err; + X509_VERIFY_PARAM_inherit(s->param, ctx->param); + s->quiet_shutdown = ctx->quiet_shutdown; + + s->ext.max_fragment_len_mode = ctx->ext.max_fragment_len_mode; + s->max_send_fragment = ctx->max_send_fragment; + s->split_send_fragment = ctx->split_send_fragment; + s->max_pipelines = ctx->max_pipelines; + if (s->max_pipelines > 1) + RECORD_LAYER_set_read_ahead(&s->rlayer, 1); + if (ctx->default_read_buf_len > 0) + SSL_set_default_read_buffer_len(s, ctx->default_read_buf_len); + + SSL_CTX_up_ref(ctx); + s->ctx = ctx; + s->ext.debug_cb = 0; + s->ext.debug_arg = NULL; + s->ext.ticket_expected = 0; + s->ext.status_type = ctx->ext.status_type; + s->ext.status_expected = 0; + s->ext.ocsp.ids = NULL; + s->ext.ocsp.exts = NULL; + s->ext.ocsp.resp = NULL; + s->ext.ocsp.resp_len = 0; + SSL_CTX_up_ref(ctx); + s->session_ctx = ctx; +#ifndef OPENSSL_NO_EC + if (ctx->ext.ecpointformats) { + s->ext.ecpointformats = + OPENSSL_memdup(ctx->ext.ecpointformats, + ctx->ext.ecpointformats_len); + if (!s->ext.ecpointformats) + goto err; + s->ext.ecpointformats_len = + ctx->ext.ecpointformats_len; + } + if (ctx->ext.supportedgroups) { + s->ext.supportedgroups = + OPENSSL_memdup(ctx->ext.supportedgroups, + ctx->ext.supportedgroups_len + * sizeof(*ctx->ext.supportedgroups)); + if (!s->ext.supportedgroups) + goto err; + s->ext.supportedgroups_len = ctx->ext.supportedgroups_len; + } +#endif +#ifndef OPENSSL_NO_NEXTPROTONEG + s->ext.npn = NULL; +#endif + + if (s->ctx->ext.alpn) { + s->ext.alpn = OPENSSL_malloc(s->ctx->ext.alpn_len); + if (s->ext.alpn == NULL) + goto err; + memcpy(s->ext.alpn, s->ctx->ext.alpn, s->ctx->ext.alpn_len); + s->ext.alpn_len = s->ctx->ext.alpn_len; + } + + s->verified_chain = NULL; + s->verify_result = X509_V_OK; + + s->default_passwd_callback = ctx->default_passwd_callback; + s->default_passwd_callback_userdata = ctx->default_passwd_callback_userdata; + + s->method = ctx->method; + + s->key_update = SSL_KEY_UPDATE_NONE; + + s->allow_early_data_cb = ctx->allow_early_data_cb; + s->allow_early_data_cb_data = ctx->allow_early_data_cb_data; + + if (!s->method->ssl_new(s)) + goto err; + + s->server = (ctx->method->ssl_accept == ssl_undefined_function) ? 0 : 1; + + if (!SSL_clear(s)) + goto err; + + if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data)) + goto err; + +#ifndef OPENSSL_NO_PSK + s->psk_client_callback = ctx->psk_client_callback; + s->psk_server_callback = ctx->psk_server_callback; +#endif + s->psk_find_session_cb = ctx->psk_find_session_cb; + s->psk_use_session_cb = ctx->psk_use_session_cb; + + s->job = NULL; + +#ifndef OPENSSL_NO_CT + if (!SSL_set_ct_validation_callback(s, ctx->ct_validation_callback, + ctx->ct_validation_callback_arg)) + goto err; +#endif + + return s; + err: + SSL_free(s); + SSLerr(SSL_F_SSL_NEW, ERR_R_MALLOC_FAILURE); + return NULL; +} + +int SSL_is_dtls(const SSL *s) +{ + return SSL_IS_DTLS(s) ? 1 : 0; +} + +int SSL_up_ref(SSL *s) +{ + int i; + + if (CRYPTO_UP_REF(&s->references, &i, s->lock) <= 0) + return 0; + + REF_PRINT_COUNT("SSL", s); + REF_ASSERT_ISNT(i < 2); + return ((i > 1) ? 1 : 0); +} + +int SSL_CTX_set_session_id_context(SSL_CTX *ctx, const unsigned char *sid_ctx, + unsigned int sid_ctx_len) +{ + if (sid_ctx_len > sizeof(ctx->sid_ctx)) { + SSLerr(SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT, + SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG); + return 0; + } + ctx->sid_ctx_length = sid_ctx_len; + memcpy(ctx->sid_ctx, sid_ctx, sid_ctx_len); + + return 1; +} + +int SSL_set_session_id_context(SSL *ssl, const unsigned char *sid_ctx, + unsigned int sid_ctx_len) +{ + if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) { + SSLerr(SSL_F_SSL_SET_SESSION_ID_CONTEXT, + SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG); + return 0; + } + ssl->sid_ctx_length = sid_ctx_len; + memcpy(ssl->sid_ctx, sid_ctx, sid_ctx_len); + + return 1; +} + +int SSL_CTX_set_generate_session_id(SSL_CTX *ctx, GEN_SESSION_CB cb) +{ + CRYPTO_THREAD_write_lock(ctx->lock); + ctx->generate_session_id = cb; + CRYPTO_THREAD_unlock(ctx->lock); + return 1; +} + +int SSL_set_generate_session_id(SSL *ssl, GEN_SESSION_CB cb) +{ + CRYPTO_THREAD_write_lock(ssl->lock); + ssl->generate_session_id = cb; + CRYPTO_THREAD_unlock(ssl->lock); + return 1; +} + +int SSL_has_matching_session_id(const SSL *ssl, const unsigned char *id, + unsigned int id_len) +{ + /* + * A quick examination of SSL_SESSION_hash and SSL_SESSION_cmp shows how + * we can "construct" a session to give us the desired check - i.e. to + * find if there's a session in the hash table that would conflict with + * any new session built out of this id/id_len and the ssl_version in use + * by this SSL. + */ + SSL_SESSION r, *p; + + if (id_len > sizeof(r.session_id)) + return 0; + + r.ssl_version = ssl->version; + r.session_id_length = id_len; + memcpy(r.session_id, id, id_len); + + CRYPTO_THREAD_read_lock(ssl->session_ctx->lock); + p = lh_SSL_SESSION_retrieve(ssl->session_ctx->sessions, &r); + CRYPTO_THREAD_unlock(ssl->session_ctx->lock); + return (p != NULL); +} + +int SSL_CTX_set_purpose(SSL_CTX *s, int purpose) +{ + return X509_VERIFY_PARAM_set_purpose(s->param, purpose); +} + +int SSL_set_purpose(SSL *s, int purpose) +{ + return X509_VERIFY_PARAM_set_purpose(s->param, purpose); +} + +int SSL_CTX_set_trust(SSL_CTX *s, int trust) +{ + return X509_VERIFY_PARAM_set_trust(s->param, trust); +} + +int SSL_set_trust(SSL *s, int trust) +{ + return X509_VERIFY_PARAM_set_trust(s->param, trust); +} + +int SSL_set1_host(SSL *s, const char *hostname) +{ + return X509_VERIFY_PARAM_set1_host(s->param, hostname, 0); +} + +int SSL_add1_host(SSL *s, const char *hostname) +{ + return X509_VERIFY_PARAM_add1_host(s->param, hostname, 0); +} + +void SSL_set_hostflags(SSL *s, unsigned int flags) +{ + X509_VERIFY_PARAM_set_hostflags(s->param, flags); +} + +const char *SSL_get0_peername(SSL *s) +{ + return X509_VERIFY_PARAM_get0_peername(s->param); +} + +int SSL_CTX_dane_enable(SSL_CTX *ctx) +{ + return dane_ctx_enable(&ctx->dane); +} + +unsigned long SSL_CTX_dane_set_flags(SSL_CTX *ctx, unsigned long flags) +{ + unsigned long orig = ctx->dane.flags; + + ctx->dane.flags |= flags; + return orig; +} + +unsigned long SSL_CTX_dane_clear_flags(SSL_CTX *ctx, unsigned long flags) +{ + unsigned long orig = ctx->dane.flags; + + ctx->dane.flags &= ~flags; + return orig; +} + +int SSL_dane_enable(SSL *s, const char *basedomain) +{ + SSL_DANE *dane = &s->dane; + + if (s->ctx->dane.mdmax == 0) { + SSLerr(SSL_F_SSL_DANE_ENABLE, SSL_R_CONTEXT_NOT_DANE_ENABLED); + return 0; + } + if (dane->trecs != NULL) { + SSLerr(SSL_F_SSL_DANE_ENABLE, SSL_R_DANE_ALREADY_ENABLED); + return 0; + } + + /* + * Default SNI name. This rejects empty names, while set1_host below + * accepts them and disables host name checks. To avoid side-effects with + * invalid input, set the SNI name first. + */ + if (s->ext.hostname == NULL) { + if (!SSL_set_tlsext_host_name(s, basedomain)) { + SSLerr(SSL_F_SSL_DANE_ENABLE, SSL_R_ERROR_SETTING_TLSA_BASE_DOMAIN); + return -1; + } + } + + /* Primary RFC6125 reference identifier */ + if (!X509_VERIFY_PARAM_set1_host(s->param, basedomain, 0)) { + SSLerr(SSL_F_SSL_DANE_ENABLE, SSL_R_ERROR_SETTING_TLSA_BASE_DOMAIN); + return -1; + } + + dane->mdpth = -1; + dane->pdpth = -1; + dane->dctx = &s->ctx->dane; + dane->trecs = sk_danetls_record_new_null(); + + if (dane->trecs == NULL) { + SSLerr(SSL_F_SSL_DANE_ENABLE, ERR_R_MALLOC_FAILURE); + return -1; + } + return 1; +} + +unsigned long SSL_dane_set_flags(SSL *ssl, unsigned long flags) +{ + unsigned long orig = ssl->dane.flags; + + ssl->dane.flags |= flags; + return orig; +} + +unsigned long SSL_dane_clear_flags(SSL *ssl, unsigned long flags) +{ + unsigned long orig = ssl->dane.flags; + + ssl->dane.flags &= ~flags; + return orig; +} + +int SSL_get0_dane_authority(SSL *s, X509 **mcert, EVP_PKEY **mspki) +{ + SSL_DANE *dane = &s->dane; + + if (!DANETLS_ENABLED(dane) || s->verify_result != X509_V_OK) + return -1; + if (dane->mtlsa) { + if (mcert) + *mcert = dane->mcert; + if (mspki) + *mspki = (dane->mcert == NULL) ? dane->mtlsa->spki : NULL; + } + return dane->mdpth; +} + +int SSL_get0_dane_tlsa(SSL *s, uint8_t *usage, uint8_t *selector, + uint8_t *mtype, unsigned const char **data, size_t *dlen) +{ + SSL_DANE *dane = &s->dane; + + if (!DANETLS_ENABLED(dane) || s->verify_result != X509_V_OK) + return -1; + if (dane->mtlsa) { + if (usage) + *usage = dane->mtlsa->usage; + if (selector) + *selector = dane->mtlsa->selector; + if (mtype) + *mtype = dane->mtlsa->mtype; + if (data) + *data = dane->mtlsa->data; + if (dlen) + *dlen = dane->mtlsa->dlen; + } + return dane->mdpth; +} + +SSL_DANE *SSL_get0_dane(SSL *s) +{ + return &s->dane; +} + +int SSL_dane_tlsa_add(SSL *s, uint8_t usage, uint8_t selector, + uint8_t mtype, unsigned const char *data, size_t dlen) +{ + return dane_tlsa_add(&s->dane, usage, selector, mtype, data, dlen); +} + +int SSL_CTX_dane_mtype_set(SSL_CTX *ctx, const EVP_MD *md, uint8_t mtype, + uint8_t ord) +{ + return dane_mtype_set(&ctx->dane, md, mtype, ord); +} + +int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm) +{ + return X509_VERIFY_PARAM_set1(ctx->param, vpm); +} + +int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm) +{ + return X509_VERIFY_PARAM_set1(ssl->param, vpm); +} + +X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx) +{ + return ctx->param; +} + +X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl) +{ + return ssl->param; +} + +void SSL_certs_clear(SSL *s) +{ + ssl_cert_clear_certs(s->cert); +} + +void SSL_free(SSL *s) +{ + int i; + + if (s == NULL) + return; + CRYPTO_DOWN_REF(&s->references, &i, s->lock); + REF_PRINT_COUNT("SSL", s); + if (i > 0) + return; + REF_ASSERT_ISNT(i < 0); + + X509_VERIFY_PARAM_free(s->param); + dane_final(&s->dane); + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data); + + /* Ignore return value */ + ssl_free_wbio_buffer(s); + + BIO_free_all(s->wbio); + BIO_free_all(s->rbio); + + BUF_MEM_free(s->init_buf); + + /* add extra stuff */ + sk_SSL_CIPHER_free(s->cipher_list); + sk_SSL_CIPHER_free(s->cipher_list_by_id); + sk_SSL_CIPHER_free(s->tls13_ciphersuites); + + /* Make the next call work :-) */ + if (s->session != NULL) { + ssl_clear_bad_session(s); + SSL_SESSION_free(s->session); + } + SSL_SESSION_free(s->psksession); + OPENSSL_free(s->psksession_id); + + clear_ciphers(s); + + ssl_cert_free(s->cert); + /* Free up if allocated */ + + OPENSSL_free(s->ext.hostname); + SSL_CTX_free(s->session_ctx); +#ifndef OPENSSL_NO_EC + OPENSSL_free(s->ext.ecpointformats); + OPENSSL_free(s->ext.supportedgroups); +#endif /* OPENSSL_NO_EC */ + sk_X509_EXTENSION_pop_free(s->ext.ocsp.exts, X509_EXTENSION_free); +#ifndef OPENSSL_NO_OCSP + sk_OCSP_RESPID_pop_free(s->ext.ocsp.ids, OCSP_RESPID_free); +#endif +#ifndef OPENSSL_NO_CT + SCT_LIST_free(s->scts); + OPENSSL_free(s->ext.scts); +#endif + OPENSSL_free(s->ext.ocsp.resp); + OPENSSL_free(s->ext.alpn); + OPENSSL_free(s->ext.tls13_cookie); + OPENSSL_free(s->clienthello); + OPENSSL_free(s->pha_context); + EVP_MD_CTX_free(s->pha_dgst); + + sk_X509_NAME_pop_free(s->ca_names, X509_NAME_free); + sk_X509_NAME_pop_free(s->client_ca_names, X509_NAME_free); + + sk_X509_pop_free(s->verified_chain, X509_free); + + if (s->method != NULL) + s->method->ssl_free(s); + + RECORD_LAYER_release(&s->rlayer); + + SSL_CTX_free(s->ctx); + + ASYNC_WAIT_CTX_free(s->waitctx); + +#if !defined(OPENSSL_NO_NEXTPROTONEG) + OPENSSL_free(s->ext.npn); +#endif + +#ifndef OPENSSL_NO_SRTP + sk_SRTP_PROTECTION_PROFILE_free(s->srtp_profiles); +#endif + + CRYPTO_THREAD_lock_free(s->lock); + + OPENSSL_free(s); +} + +void SSL_set0_rbio(SSL *s, BIO *rbio) +{ + BIO_free_all(s->rbio); + s->rbio = rbio; +} + +void SSL_set0_wbio(SSL *s, BIO *wbio) +{ + /* + * If the output buffering BIO is still in place, remove it + */ + if (s->bbio != NULL) + s->wbio = BIO_pop(s->wbio); + + BIO_free_all(s->wbio); + s->wbio = wbio; + + /* Re-attach |bbio| to the new |wbio|. */ + if (s->bbio != NULL) + s->wbio = BIO_push(s->bbio, s->wbio); +} + +void SSL_set_bio(SSL *s, BIO *rbio, BIO *wbio) +{ + /* + * For historical reasons, this function has many different cases in + * ownership handling. + */ + + /* If nothing has changed, do nothing */ + if (rbio == SSL_get_rbio(s) && wbio == SSL_get_wbio(s)) + return; + + /* + * If the two arguments are equal then one fewer reference is granted by the + * caller than we want to take + */ + if (rbio != NULL && rbio == wbio) + BIO_up_ref(rbio); + + /* + * If only the wbio is changed only adopt one reference. + */ + if (rbio == SSL_get_rbio(s)) { + SSL_set0_wbio(s, wbio); + return; + } + /* + * There is an asymmetry here for historical reasons. If only the rbio is + * changed AND the rbio and wbio were originally different, then we only + * adopt one reference. + */ + if (wbio == SSL_get_wbio(s) && SSL_get_rbio(s) != SSL_get_wbio(s)) { + SSL_set0_rbio(s, rbio); + return; + } + + /* Otherwise, adopt both references. */ + SSL_set0_rbio(s, rbio); + SSL_set0_wbio(s, wbio); +} + +BIO *SSL_get_rbio(const SSL *s) +{ + return s->rbio; +} + +BIO *SSL_get_wbio(const SSL *s) +{ + if (s->bbio != NULL) { + /* + * If |bbio| is active, the true caller-configured BIO is its + * |next_bio|. + */ + return BIO_next(s->bbio); + } + return s->wbio; +} + +int SSL_get_fd(const SSL *s) +{ + return SSL_get_rfd(s); +} + +int SSL_get_rfd(const SSL *s) +{ + int ret = -1; + BIO *b, *r; + + b = SSL_get_rbio(s); + r = BIO_find_type(b, BIO_TYPE_DESCRIPTOR); + if (r != NULL) + BIO_get_fd(r, &ret); + return ret; +} + +int SSL_get_wfd(const SSL *s) +{ + int ret = -1; + BIO *b, *r; + + b = SSL_get_wbio(s); + r = BIO_find_type(b, BIO_TYPE_DESCRIPTOR); + if (r != NULL) + BIO_get_fd(r, &ret); + return ret; +} + +#ifndef OPENSSL_NO_SOCK +int SSL_set_fd(SSL *s, int fd) +{ + int ret = 0; + BIO *bio = NULL; + + bio = BIO_new(BIO_s_socket()); + + if (bio == NULL) { + SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB); + goto err; + } + BIO_set_fd(bio, fd, BIO_NOCLOSE); + SSL_set_bio(s, bio, bio); + ret = 1; + err: + return ret; +} + +int SSL_set_wfd(SSL *s, int fd) +{ + BIO *rbio = SSL_get_rbio(s); + + if (rbio == NULL || BIO_method_type(rbio) != BIO_TYPE_SOCKET + || (int)BIO_get_fd(rbio, NULL) != fd) { + BIO *bio = BIO_new(BIO_s_socket()); + + if (bio == NULL) { + SSLerr(SSL_F_SSL_SET_WFD, ERR_R_BUF_LIB); + return 0; + } + BIO_set_fd(bio, fd, BIO_NOCLOSE); + SSL_set0_wbio(s, bio); + } else { + BIO_up_ref(rbio); + SSL_set0_wbio(s, rbio); + } + return 1; +} + +int SSL_set_rfd(SSL *s, int fd) +{ + BIO *wbio = SSL_get_wbio(s); + + if (wbio == NULL || BIO_method_type(wbio) != BIO_TYPE_SOCKET + || ((int)BIO_get_fd(wbio, NULL) != fd)) { + BIO *bio = BIO_new(BIO_s_socket()); + + if (bio == NULL) { + SSLerr(SSL_F_SSL_SET_RFD, ERR_R_BUF_LIB); + return 0; + } + BIO_set_fd(bio, fd, BIO_NOCLOSE); + SSL_set0_rbio(s, bio); + } else { + BIO_up_ref(wbio); + SSL_set0_rbio(s, wbio); + } + + return 1; +} +#endif + +/* return length of latest Finished message we sent, copy to 'buf' */ +size_t SSL_get_finished(const SSL *s, void *buf, size_t count) +{ + size_t ret = 0; + + if (s->s3 != NULL) { + ret = s->s3->tmp.finish_md_len; + if (count > ret) + count = ret; + memcpy(buf, s->s3->tmp.finish_md, count); + } + return ret; +} + +/* return length of latest Finished message we expected, copy to 'buf' */ +size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count) +{ + size_t ret = 0; + + if (s->s3 != NULL) { + ret = s->s3->tmp.peer_finish_md_len; + if (count > ret) + count = ret; + memcpy(buf, s->s3->tmp.peer_finish_md, count); + } + return ret; +} + +int SSL_get_verify_mode(const SSL *s) +{ + return s->verify_mode; +} + +int SSL_get_verify_depth(const SSL *s) +{ + return X509_VERIFY_PARAM_get_depth(s->param); +} + +int (*SSL_get_verify_callback(const SSL *s)) (int, X509_STORE_CTX *) { + return s->verify_callback; +} + +int SSL_CTX_get_verify_mode(const SSL_CTX *ctx) +{ + return ctx->verify_mode; +} + +int SSL_CTX_get_verify_depth(const SSL_CTX *ctx) +{ + return X509_VERIFY_PARAM_get_depth(ctx->param); +} + +int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx)) (int, X509_STORE_CTX *) { + return ctx->default_verify_callback; +} + +void SSL_set_verify(SSL *s, int mode, + int (*callback) (int ok, X509_STORE_CTX *ctx)) +{ + s->verify_mode = mode; + if (callback != NULL) + s->verify_callback = callback; +} + +void SSL_set_verify_depth(SSL *s, int depth) +{ + X509_VERIFY_PARAM_set_depth(s->param, depth); +} + +void SSL_set_read_ahead(SSL *s, int yes) +{ + RECORD_LAYER_set_read_ahead(&s->rlayer, yes); +} + +int SSL_get_read_ahead(const SSL *s) +{ + return RECORD_LAYER_get_read_ahead(&s->rlayer); +} + +int SSL_pending(const SSL *s) +{ + size_t pending = s->method->ssl_pending(s); + + /* + * SSL_pending cannot work properly if read-ahead is enabled + * (SSL_[CTX_]ctrl(..., SSL_CTRL_SET_READ_AHEAD, 1, NULL)), and it is + * impossible to fix since SSL_pending cannot report errors that may be + * observed while scanning the new data. (Note that SSL_pending() is + * often used as a boolean value, so we'd better not return -1.) + * + * SSL_pending also cannot work properly if the value >INT_MAX. In that case + * we just return INT_MAX. + */ + return pending < INT_MAX ? (int)pending : INT_MAX; +} + +int SSL_has_pending(const SSL *s) +{ + /* + * Similar to SSL_pending() but returns a 1 to indicate that we have + * unprocessed data available or 0 otherwise (as opposed to the number of + * bytes available). Unlike SSL_pending() this will take into account + * read_ahead data. A 1 return simply indicates that we have unprocessed + * data. That data may not result in any application data, or we may fail + * to parse the records for some reason. + */ + if (RECORD_LAYER_processed_read_pending(&s->rlayer)) + return 1; + + return RECORD_LAYER_read_pending(&s->rlayer); +} + +X509 *SSL_get_peer_certificate(const SSL *s) +{ + X509 *r; + + if ((s == NULL) || (s->session == NULL)) + r = NULL; + else + r = s->session->peer; + + if (r == NULL) + return r; + + X509_up_ref(r); + + return r; +} + +STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s) +{ + STACK_OF(X509) *r; + + if ((s == NULL) || (s->session == NULL)) + r = NULL; + else + r = s->session->peer_chain; + + /* + * If we are a client, cert_chain includes the peer's own certificate; if + * we are a server, it does not. + */ + + return r; +} + +/* + * Now in theory, since the calling process own 't' it should be safe to + * modify. We need to be able to read f without being hassled + */ +int SSL_copy_session_id(SSL *t, const SSL *f) +{ + int i; + /* Do we need to to SSL locking? */ + if (!SSL_set_session(t, SSL_get_session(f))) { + return 0; + } + + /* + * what if we are setup for one protocol version but want to talk another + */ + if (t->method != f->method) { + t->method->ssl_free(t); + t->method = f->method; + if (t->method->ssl_new(t) == 0) + return 0; + } + + CRYPTO_UP_REF(&f->cert->references, &i, f->cert->lock); + ssl_cert_free(t->cert); + t->cert = f->cert; + if (!SSL_set_session_id_context(t, f->sid_ctx, (int)f->sid_ctx_length)) { + return 0; + } + + return 1; +} + +/* Fix this so it checks all the valid key/cert options */ +int SSL_CTX_check_private_key(const SSL_CTX *ctx) +{ + if ((ctx == NULL) || (ctx->cert->key->x509 == NULL)) { + SSLerr(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY, SSL_R_NO_CERTIFICATE_ASSIGNED); + return 0; + } + if (ctx->cert->key->privatekey == NULL) { + SSLerr(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY, SSL_R_NO_PRIVATE_KEY_ASSIGNED); + return 0; + } + return X509_check_private_key + (ctx->cert->key->x509, ctx->cert->key->privatekey); +} + +/* Fix this function so that it takes an optional type parameter */ +int SSL_check_private_key(const SSL *ssl) +{ + if (ssl == NULL) { + SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (ssl->cert->key->x509 == NULL) { + SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY, SSL_R_NO_CERTIFICATE_ASSIGNED); + return 0; + } + if (ssl->cert->key->privatekey == NULL) { + SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY, SSL_R_NO_PRIVATE_KEY_ASSIGNED); + return 0; + } + return X509_check_private_key(ssl->cert->key->x509, + ssl->cert->key->privatekey); +} + +int SSL_waiting_for_async(SSL *s) +{ + if (s->job) + return 1; + + return 0; +} + +int SSL_get_all_async_fds(SSL *s, OSSL_ASYNC_FD *fds, size_t *numfds) +{ + ASYNC_WAIT_CTX *ctx = s->waitctx; + + if (ctx == NULL) + return 0; + return ASYNC_WAIT_CTX_get_all_fds(ctx, fds, numfds); +} + +int SSL_get_changed_async_fds(SSL *s, OSSL_ASYNC_FD *addfd, size_t *numaddfds, + OSSL_ASYNC_FD *delfd, size_t *numdelfds) +{ + ASYNC_WAIT_CTX *ctx = s->waitctx; + + if (ctx == NULL) + return 0; + return ASYNC_WAIT_CTX_get_changed_fds(ctx, addfd, numaddfds, delfd, + numdelfds); +} + +int SSL_accept(SSL *s) +{ + if (s->handshake_func == NULL) { + /* Not properly initialized yet */ + SSL_set_accept_state(s); + } + + return SSL_do_handshake(s); +} + +int SSL_connect(SSL *s) +{ + if (s->handshake_func == NULL) { + /* Not properly initialized yet */ + SSL_set_connect_state(s); + } + + return SSL_do_handshake(s); +} + +long SSL_get_default_timeout(const SSL *s) +{ + return s->method->get_timeout(); +} + +static int ssl_start_async_job(SSL *s, struct ssl_async_args *args, + int (*func) (void *)) +{ + int ret; + if (s->waitctx == NULL) { + s->waitctx = ASYNC_WAIT_CTX_new(); + if (s->waitctx == NULL) + return -1; + } + switch (ASYNC_start_job(&s->job, s->waitctx, &ret, func, args, + sizeof(struct ssl_async_args))) { + case ASYNC_ERR: + s->rwstate = SSL_NOTHING; + SSLerr(SSL_F_SSL_START_ASYNC_JOB, SSL_R_FAILED_TO_INIT_ASYNC); + return -1; + case ASYNC_PAUSE: + s->rwstate = SSL_ASYNC_PAUSED; + return -1; + case ASYNC_NO_JOBS: + s->rwstate = SSL_ASYNC_NO_JOBS; + return -1; + case ASYNC_FINISH: + s->job = NULL; + return ret; + default: + s->rwstate = SSL_NOTHING; + SSLerr(SSL_F_SSL_START_ASYNC_JOB, ERR_R_INTERNAL_ERROR); + /* Shouldn't happen */ + return -1; + } +} + +static int ssl_io_intern(void *vargs) +{ + struct ssl_async_args *args; + SSL *s; + void *buf; + size_t num; + + args = (struct ssl_async_args *)vargs; + s = args->s; + buf = args->buf; + num = args->num; + switch (args->type) { + case READFUNC: + return args->f.func_read(s, buf, num, &s->asyncrw); + case WRITEFUNC: + return args->f.func_write(s, buf, num, &s->asyncrw); + case OTHERFUNC: + return args->f.func_other(s); + } + return -1; +} + +int ssl_read_internal(SSL *s, void *buf, size_t num, size_t *readbytes) +{ + if (s->handshake_func == NULL) { + SSLerr(SSL_F_SSL_READ_INTERNAL, SSL_R_UNINITIALIZED); + return -1; + } + + if (s->shutdown & SSL_RECEIVED_SHUTDOWN) { + s->rwstate = SSL_NOTHING; + return 0; + } + + if (s->early_data_state == SSL_EARLY_DATA_CONNECT_RETRY + || s->early_data_state == SSL_EARLY_DATA_ACCEPT_RETRY) { + SSLerr(SSL_F_SSL_READ_INTERNAL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + /* + * If we are a client and haven't received the ServerHello etc then we + * better do that + */ + ossl_statem_check_finish_init(s, 0); + + if ((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) { + struct ssl_async_args args; + int ret; + + args.s = s; + args.buf = buf; + args.num = num; + args.type = READFUNC; + args.f.func_read = s->method->ssl_read; + + ret = ssl_start_async_job(s, &args, ssl_io_intern); + *readbytes = s->asyncrw; + return ret; + } else { + return s->method->ssl_read(s, buf, num, readbytes); + } +} + +int SSL_read(SSL *s, void *buf, int num) +{ + int ret; + size_t readbytes; + + if (num < 0) { + SSLerr(SSL_F_SSL_READ, SSL_R_BAD_LENGTH); + return -1; + } + + ret = ssl_read_internal(s, buf, (size_t)num, &readbytes); + + /* + * The cast is safe here because ret should be <= INT_MAX because num is + * <= INT_MAX + */ + if (ret > 0) + ret = (int)readbytes; + + return ret; +} + +int SSL_read_ex(SSL *s, void *buf, size_t num, size_t *readbytes) +{ + int ret = ssl_read_internal(s, buf, num, readbytes); + + if (ret < 0) + ret = 0; + return ret; +} + +int SSL_read_early_data(SSL *s, void *buf, size_t num, size_t *readbytes) +{ + int ret; + + if (!s->server) { + SSLerr(SSL_F_SSL_READ_EARLY_DATA, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return SSL_READ_EARLY_DATA_ERROR; + } + + switch (s->early_data_state) { + case SSL_EARLY_DATA_NONE: + if (!SSL_in_before(s)) { + SSLerr(SSL_F_SSL_READ_EARLY_DATA, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return SSL_READ_EARLY_DATA_ERROR; + } + /* fall through */ + + case SSL_EARLY_DATA_ACCEPT_RETRY: + s->early_data_state = SSL_EARLY_DATA_ACCEPTING; + ret = SSL_accept(s); + if (ret <= 0) { + /* NBIO or error */ + s->early_data_state = SSL_EARLY_DATA_ACCEPT_RETRY; + return SSL_READ_EARLY_DATA_ERROR; + } + /* fall through */ + + case SSL_EARLY_DATA_READ_RETRY: + if (s->ext.early_data == SSL_EARLY_DATA_ACCEPTED) { + s->early_data_state = SSL_EARLY_DATA_READING; + ret = SSL_read_ex(s, buf, num, readbytes); + /* + * State machine will update early_data_state to + * SSL_EARLY_DATA_FINISHED_READING if we get an EndOfEarlyData + * message + */ + if (ret > 0 || (ret <= 0 && s->early_data_state + != SSL_EARLY_DATA_FINISHED_READING)) { + s->early_data_state = SSL_EARLY_DATA_READ_RETRY; + return ret > 0 ? SSL_READ_EARLY_DATA_SUCCESS + : SSL_READ_EARLY_DATA_ERROR; + } + } else { + s->early_data_state = SSL_EARLY_DATA_FINISHED_READING; + } + *readbytes = 0; + return SSL_READ_EARLY_DATA_FINISH; + + default: + SSLerr(SSL_F_SSL_READ_EARLY_DATA, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return SSL_READ_EARLY_DATA_ERROR; + } +} + +int SSL_get_early_data_status(const SSL *s) +{ + return s->ext.early_data; +} + +static int ssl_peek_internal(SSL *s, void *buf, size_t num, size_t *readbytes) +{ + if (s->handshake_func == NULL) { + SSLerr(SSL_F_SSL_PEEK_INTERNAL, SSL_R_UNINITIALIZED); + return -1; + } + + if (s->shutdown & SSL_RECEIVED_SHUTDOWN) { + return 0; + } + if ((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) { + struct ssl_async_args args; + int ret; + + args.s = s; + args.buf = buf; + args.num = num; + args.type = READFUNC; + args.f.func_read = s->method->ssl_peek; + + ret = ssl_start_async_job(s, &args, ssl_io_intern); + *readbytes = s->asyncrw; + return ret; + } else { + return s->method->ssl_peek(s, buf, num, readbytes); + } +} + +int SSL_peek(SSL *s, void *buf, int num) +{ + int ret; + size_t readbytes; + + if (num < 0) { + SSLerr(SSL_F_SSL_PEEK, SSL_R_BAD_LENGTH); + return -1; + } + + ret = ssl_peek_internal(s, buf, (size_t)num, &readbytes); + + /* + * The cast is safe here because ret should be <= INT_MAX because num is + * <= INT_MAX + */ + if (ret > 0) + ret = (int)readbytes; + + return ret; +} + + +int SSL_peek_ex(SSL *s, void *buf, size_t num, size_t *readbytes) +{ + int ret = ssl_peek_internal(s, buf, num, readbytes); + + if (ret < 0) + ret = 0; + return ret; +} + +int ssl_write_internal(SSL *s, const void *buf, size_t num, size_t *written) +{ + if (s->handshake_func == NULL) { + SSLerr(SSL_F_SSL_WRITE_INTERNAL, SSL_R_UNINITIALIZED); + return -1; + } + + if (s->shutdown & SSL_SENT_SHUTDOWN) { + s->rwstate = SSL_NOTHING; + SSLerr(SSL_F_SSL_WRITE_INTERNAL, SSL_R_PROTOCOL_IS_SHUTDOWN); + return -1; + } + + if (s->early_data_state == SSL_EARLY_DATA_CONNECT_RETRY + || s->early_data_state == SSL_EARLY_DATA_ACCEPT_RETRY + || s->early_data_state == SSL_EARLY_DATA_READ_RETRY) { + SSLerr(SSL_F_SSL_WRITE_INTERNAL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + /* If we are a client and haven't sent the Finished we better do that */ + ossl_statem_check_finish_init(s, 1); + + if ((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) { + int ret; + struct ssl_async_args args; + + args.s = s; + args.buf = (void *)buf; + args.num = num; + args.type = WRITEFUNC; + args.f.func_write = s->method->ssl_write; + + ret = ssl_start_async_job(s, &args, ssl_io_intern); + *written = s->asyncrw; + return ret; + } else { + return s->method->ssl_write(s, buf, num, written); + } +} + +int SSL_write(SSL *s, const void *buf, int num) +{ + int ret; + size_t written; + + if (num < 0) { + SSLerr(SSL_F_SSL_WRITE, SSL_R_BAD_LENGTH); + return -1; + } + + ret = ssl_write_internal(s, buf, (size_t)num, &written); + + /* + * The cast is safe here because ret should be <= INT_MAX because num is + * <= INT_MAX + */ + if (ret > 0) + ret = (int)written; + + return ret; +} + +int SSL_write_ex(SSL *s, const void *buf, size_t num, size_t *written) +{ + int ret = ssl_write_internal(s, buf, num, written); + + if (ret < 0) + ret = 0; + return ret; +} + +int SSL_write_early_data(SSL *s, const void *buf, size_t num, size_t *written) +{ + int ret, early_data_state; + size_t writtmp; + uint32_t partialwrite; + + switch (s->early_data_state) { + case SSL_EARLY_DATA_NONE: + if (s->server + || !SSL_in_before(s) + || ((s->session == NULL || s->session->ext.max_early_data == 0) + && (s->psk_use_session_cb == NULL))) { + SSLerr(SSL_F_SSL_WRITE_EARLY_DATA, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + /* fall through */ + + case SSL_EARLY_DATA_CONNECT_RETRY: + s->early_data_state = SSL_EARLY_DATA_CONNECTING; + ret = SSL_connect(s); + if (ret <= 0) { + /* NBIO or error */ + s->early_data_state = SSL_EARLY_DATA_CONNECT_RETRY; + return 0; + } + /* fall through */ + + case SSL_EARLY_DATA_WRITE_RETRY: + s->early_data_state = SSL_EARLY_DATA_WRITING; + /* + * We disable partial write for early data because we don't keep track + * of how many bytes we've written between the SSL_write_ex() call and + * the flush if the flush needs to be retried) + */ + partialwrite = s->mode & SSL_MODE_ENABLE_PARTIAL_WRITE; + s->mode &= ~SSL_MODE_ENABLE_PARTIAL_WRITE; + ret = SSL_write_ex(s, buf, num, &writtmp); + s->mode |= partialwrite; + if (!ret) { + s->early_data_state = SSL_EARLY_DATA_WRITE_RETRY; + return ret; + } + s->early_data_state = SSL_EARLY_DATA_WRITE_FLUSH; + /* fall through */ + + case SSL_EARLY_DATA_WRITE_FLUSH: + /* The buffering BIO is still in place so we need to flush it */ + if (statem_flush(s) != 1) + return 0; + *written = num; + s->early_data_state = SSL_EARLY_DATA_WRITE_RETRY; + return 1; + + case SSL_EARLY_DATA_FINISHED_READING: + case SSL_EARLY_DATA_READ_RETRY: + early_data_state = s->early_data_state; + /* We are a server writing to an unauthenticated client */ + s->early_data_state = SSL_EARLY_DATA_UNAUTH_WRITING; + ret = SSL_write_ex(s, buf, num, written); + /* The buffering BIO is still in place */ + if (ret) + (void)BIO_flush(s->wbio); + s->early_data_state = early_data_state; + return ret; + + default: + SSLerr(SSL_F_SSL_WRITE_EARLY_DATA, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } +} + +int SSL_shutdown(SSL *s) +{ + /* + * Note that this function behaves differently from what one might + * expect. Return values are 0 for no success (yet), 1 for success; but + * calling it once is usually not enough, even if blocking I/O is used + * (see ssl3_shutdown). + */ + + if (s->handshake_func == NULL) { + SSLerr(SSL_F_SSL_SHUTDOWN, SSL_R_UNINITIALIZED); + return -1; + } + + if (!SSL_in_init(s)) { + if ((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) { + struct ssl_async_args args; + + args.s = s; + args.type = OTHERFUNC; + args.f.func_other = s->method->ssl_shutdown; + + return ssl_start_async_job(s, &args, ssl_io_intern); + } else { + return s->method->ssl_shutdown(s); + } + } else { + SSLerr(SSL_F_SSL_SHUTDOWN, SSL_R_SHUTDOWN_WHILE_IN_INIT); + return -1; + } +} + +int SSL_key_update(SSL *s, int updatetype) +{ + /* + * TODO(TLS1.3): How will applications know whether TLSv1.3 has been + * negotiated, and that it is appropriate to call SSL_key_update() instead + * of SSL_renegotiate(). + */ + if (!SSL_IS_TLS13(s)) { + SSLerr(SSL_F_SSL_KEY_UPDATE, SSL_R_WRONG_SSL_VERSION); + return 0; + } + + if (updatetype != SSL_KEY_UPDATE_NOT_REQUESTED + && updatetype != SSL_KEY_UPDATE_REQUESTED) { + SSLerr(SSL_F_SSL_KEY_UPDATE, SSL_R_INVALID_KEY_UPDATE_TYPE); + return 0; + } + + if (!SSL_is_init_finished(s)) { + SSLerr(SSL_F_SSL_KEY_UPDATE, SSL_R_STILL_IN_INIT); + return 0; + } + + ossl_statem_set_in_init(s, 1); + s->key_update = updatetype; + return 1; +} + +int SSL_get_key_update_type(const SSL *s) +{ + return s->key_update; +} + +int SSL_renegotiate(SSL *s) +{ + if (SSL_IS_TLS13(s)) { + SSLerr(SSL_F_SSL_RENEGOTIATE, SSL_R_WRONG_SSL_VERSION); + return 0; + } + + if ((s->options & SSL_OP_NO_RENEGOTIATION)) { + SSLerr(SSL_F_SSL_RENEGOTIATE, SSL_R_NO_RENEGOTIATION); + return 0; + } + + s->renegotiate = 1; + s->new_session = 1; + + return s->method->ssl_renegotiate(s); +} + +int SSL_renegotiate_abbreviated(SSL *s) +{ + if (SSL_IS_TLS13(s)) { + SSLerr(SSL_F_SSL_RENEGOTIATE_ABBREVIATED, SSL_R_WRONG_SSL_VERSION); + return 0; + } + + if ((s->options & SSL_OP_NO_RENEGOTIATION)) { + SSLerr(SSL_F_SSL_RENEGOTIATE_ABBREVIATED, SSL_R_NO_RENEGOTIATION); + return 0; + } + + s->renegotiate = 1; + s->new_session = 0; + + return s->method->ssl_renegotiate(s); +} + +int SSL_renegotiate_pending(const SSL *s) +{ + /* + * becomes true when negotiation is requested; false again once a + * handshake has finished + */ + return (s->renegotiate != 0); +} + +long SSL_ctrl(SSL *s, int cmd, long larg, void *parg) +{ + long l; + + switch (cmd) { + case SSL_CTRL_GET_READ_AHEAD: + return RECORD_LAYER_get_read_ahead(&s->rlayer); + case SSL_CTRL_SET_READ_AHEAD: + l = RECORD_LAYER_get_read_ahead(&s->rlayer); + RECORD_LAYER_set_read_ahead(&s->rlayer, larg); + return l; + + case SSL_CTRL_SET_MSG_CALLBACK_ARG: + s->msg_callback_arg = parg; + return 1; + + case SSL_CTRL_MODE: + return (s->mode |= larg); + case SSL_CTRL_CLEAR_MODE: + return (s->mode &= ~larg); + case SSL_CTRL_GET_MAX_CERT_LIST: + return (long)s->max_cert_list; + case SSL_CTRL_SET_MAX_CERT_LIST: + if (larg < 0) + return 0; + l = (long)s->max_cert_list; + s->max_cert_list = (size_t)larg; + return l; + case SSL_CTRL_SET_MAX_SEND_FRAGMENT: + if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH) + return 0; + s->max_send_fragment = larg; + if (s->max_send_fragment < s->split_send_fragment) + s->split_send_fragment = s->max_send_fragment; + return 1; + case SSL_CTRL_SET_SPLIT_SEND_FRAGMENT: + if ((size_t)larg > s->max_send_fragment || larg == 0) + return 0; + s->split_send_fragment = larg; + return 1; + case SSL_CTRL_SET_MAX_PIPELINES: + if (larg < 1 || larg > SSL_MAX_PIPELINES) + return 0; + s->max_pipelines = larg; + if (larg > 1) + RECORD_LAYER_set_read_ahead(&s->rlayer, 1); + return 1; + case SSL_CTRL_GET_RI_SUPPORT: + if (s->s3) + return s->s3->send_connection_binding; + else + return 0; + case SSL_CTRL_CERT_FLAGS: + return (s->cert->cert_flags |= larg); + case SSL_CTRL_CLEAR_CERT_FLAGS: + return (s->cert->cert_flags &= ~larg); + + case SSL_CTRL_GET_RAW_CIPHERLIST: + if (parg) { + if (s->s3->tmp.ciphers_raw == NULL) + return 0; + *(unsigned char **)parg = s->s3->tmp.ciphers_raw; + return (int)s->s3->tmp.ciphers_rawlen; + } else { + return TLS_CIPHER_LEN; + } + case SSL_CTRL_GET_EXTMS_SUPPORT: + if (!s->session || SSL_in_init(s) || ossl_statem_get_in_handshake(s)) + return -1; + if (s->session->flags & SSL_SESS_FLAG_EXTMS) + return 1; + else + return 0; + case SSL_CTRL_SET_MIN_PROTO_VERSION: + return ssl_check_allowed_versions(larg, s->max_proto_version) + && ssl_set_version_bound(s->ctx->method->version, (int)larg, + &s->min_proto_version); + case SSL_CTRL_GET_MIN_PROTO_VERSION: + return s->min_proto_version; + case SSL_CTRL_SET_MAX_PROTO_VERSION: + return ssl_check_allowed_versions(s->min_proto_version, larg) + && ssl_set_version_bound(s->ctx->method->version, (int)larg, + &s->max_proto_version); + case SSL_CTRL_GET_MAX_PROTO_VERSION: + return s->max_proto_version; + default: + return s->method->ssl_ctrl(s, cmd, larg, parg); + } +} + +long SSL_callback_ctrl(SSL *s, int cmd, void (*fp) (void)) +{ + switch (cmd) { + case SSL_CTRL_SET_MSG_CALLBACK: + s->msg_callback = (void (*) + (int write_p, int version, int content_type, + const void *buf, size_t len, SSL *ssl, + void *arg))(fp); + return 1; + + default: + return s->method->ssl_callback_ctrl(s, cmd, fp); + } +} + +LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx) +{ + return ctx->sessions; +} + +long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) +{ + long l; + /* For some cases with ctx == NULL perform syntax checks */ + if (ctx == NULL) { + switch (cmd) { +#ifndef OPENSSL_NO_EC + case SSL_CTRL_SET_GROUPS_LIST: + return tls1_set_groups_list(NULL, NULL, parg); +#endif + case SSL_CTRL_SET_SIGALGS_LIST: + case SSL_CTRL_SET_CLIENT_SIGALGS_LIST: + return tls1_set_sigalgs_list(NULL, parg, 0); + default: + return 0; + } + } + + switch (cmd) { + case SSL_CTRL_GET_READ_AHEAD: + return ctx->read_ahead; + case SSL_CTRL_SET_READ_AHEAD: + l = ctx->read_ahead; + ctx->read_ahead = larg; + return l; + + case SSL_CTRL_SET_MSG_CALLBACK_ARG: + ctx->msg_callback_arg = parg; + return 1; + + case SSL_CTRL_GET_MAX_CERT_LIST: + return (long)ctx->max_cert_list; + case SSL_CTRL_SET_MAX_CERT_LIST: + if (larg < 0) + return 0; + l = (long)ctx->max_cert_list; + ctx->max_cert_list = (size_t)larg; + return l; + + case SSL_CTRL_SET_SESS_CACHE_SIZE: + if (larg < 0) + return 0; + l = (long)ctx->session_cache_size; + ctx->session_cache_size = (size_t)larg; + return l; + case SSL_CTRL_GET_SESS_CACHE_SIZE: + return (long)ctx->session_cache_size; + case SSL_CTRL_SET_SESS_CACHE_MODE: + l = ctx->session_cache_mode; + ctx->session_cache_mode = larg; + return l; + case SSL_CTRL_GET_SESS_CACHE_MODE: + return ctx->session_cache_mode; + + case SSL_CTRL_SESS_NUMBER: + return lh_SSL_SESSION_num_items(ctx->sessions); + case SSL_CTRL_SESS_CONNECT: + return tsan_load(&ctx->stats.sess_connect); + case SSL_CTRL_SESS_CONNECT_GOOD: + return tsan_load(&ctx->stats.sess_connect_good); + case SSL_CTRL_SESS_CONNECT_RENEGOTIATE: + return tsan_load(&ctx->stats.sess_connect_renegotiate); + case SSL_CTRL_SESS_ACCEPT: + return tsan_load(&ctx->stats.sess_accept); + case SSL_CTRL_SESS_ACCEPT_GOOD: + return tsan_load(&ctx->stats.sess_accept_good); + case SSL_CTRL_SESS_ACCEPT_RENEGOTIATE: + return tsan_load(&ctx->stats.sess_accept_renegotiate); + case SSL_CTRL_SESS_HIT: + return tsan_load(&ctx->stats.sess_hit); + case SSL_CTRL_SESS_CB_HIT: + return tsan_load(&ctx->stats.sess_cb_hit); + case SSL_CTRL_SESS_MISSES: + return tsan_load(&ctx->stats.sess_miss); + case SSL_CTRL_SESS_TIMEOUTS: + return tsan_load(&ctx->stats.sess_timeout); + case SSL_CTRL_SESS_CACHE_FULL: + return tsan_load(&ctx->stats.sess_cache_full); + case SSL_CTRL_MODE: + return (ctx->mode |= larg); + case SSL_CTRL_CLEAR_MODE: + return (ctx->mode &= ~larg); + case SSL_CTRL_SET_MAX_SEND_FRAGMENT: + if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH) + return 0; + ctx->max_send_fragment = larg; + if (ctx->max_send_fragment < ctx->split_send_fragment) + ctx->split_send_fragment = ctx->max_send_fragment; + return 1; + case SSL_CTRL_SET_SPLIT_SEND_FRAGMENT: + if ((size_t)larg > ctx->max_send_fragment || larg == 0) + return 0; + ctx->split_send_fragment = larg; + return 1; + case SSL_CTRL_SET_MAX_PIPELINES: + if (larg < 1 || larg > SSL_MAX_PIPELINES) + return 0; + ctx->max_pipelines = larg; + return 1; + case SSL_CTRL_CERT_FLAGS: + return (ctx->cert->cert_flags |= larg); + case SSL_CTRL_CLEAR_CERT_FLAGS: + return (ctx->cert->cert_flags &= ~larg); + case SSL_CTRL_SET_MIN_PROTO_VERSION: + return ssl_check_allowed_versions(larg, ctx->max_proto_version) + && ssl_set_version_bound(ctx->method->version, (int)larg, + &ctx->min_proto_version); + case SSL_CTRL_GET_MIN_PROTO_VERSION: + return ctx->min_proto_version; + case SSL_CTRL_SET_MAX_PROTO_VERSION: + return ssl_check_allowed_versions(ctx->min_proto_version, larg) + && ssl_set_version_bound(ctx->method->version, (int)larg, + &ctx->max_proto_version); + case SSL_CTRL_GET_MAX_PROTO_VERSION: + return ctx->max_proto_version; + default: + return ctx->method->ssl_ctx_ctrl(ctx, cmd, larg, parg); + } +} + +long SSL_CTX_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp) (void)) +{ + switch (cmd) { + case SSL_CTRL_SET_MSG_CALLBACK: + ctx->msg_callback = (void (*) + (int write_p, int version, int content_type, + const void *buf, size_t len, SSL *ssl, + void *arg))(fp); + return 1; + + default: + return ctx->method->ssl_ctx_callback_ctrl(ctx, cmd, fp); + } +} + +int ssl_cipher_id_cmp(const SSL_CIPHER *a, const SSL_CIPHER *b) +{ + if (a->id > b->id) + return 1; + if (a->id < b->id) + return -1; + return 0; +} + +int ssl_cipher_ptr_id_cmp(const SSL_CIPHER *const *ap, + const SSL_CIPHER *const *bp) +{ + if ((*ap)->id > (*bp)->id) + return 1; + if ((*ap)->id < (*bp)->id) + return -1; + return 0; +} + +/** return a STACK of the ciphers available for the SSL and in order of + * preference */ +STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s) +{ + if (s != NULL) { + if (s->cipher_list != NULL) { + return s->cipher_list; + } else if ((s->ctx != NULL) && (s->ctx->cipher_list != NULL)) { + return s->ctx->cipher_list; + } + } + return NULL; +} + +STACK_OF(SSL_CIPHER) *SSL_get_client_ciphers(const SSL *s) +{ + if ((s == NULL) || (s->session == NULL) || !s->server) + return NULL; + return s->session->ciphers; +} + +STACK_OF(SSL_CIPHER) *SSL_get1_supported_ciphers(SSL *s) +{ + STACK_OF(SSL_CIPHER) *sk = NULL, *ciphers; + int i; + + ciphers = SSL_get_ciphers(s); + if (!ciphers) + return NULL; + if (!ssl_set_client_disabled(s)) + return NULL; + for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { + const SSL_CIPHER *c = sk_SSL_CIPHER_value(ciphers, i); + if (!ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED, 0)) { + if (!sk) + sk = sk_SSL_CIPHER_new_null(); + if (!sk) + return NULL; + if (!sk_SSL_CIPHER_push(sk, c)) { + sk_SSL_CIPHER_free(sk); + return NULL; + } + } + } + return sk; +} + +/** return a STACK of the ciphers available for the SSL and in order of + * algorithm id */ +STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s) +{ + if (s != NULL) { + if (s->cipher_list_by_id != NULL) { + return s->cipher_list_by_id; + } else if ((s->ctx != NULL) && (s->ctx->cipher_list_by_id != NULL)) { + return s->ctx->cipher_list_by_id; + } + } + return NULL; +} + +/** The old interface to get the same thing as SSL_get_ciphers() */ +const char *SSL_get_cipher_list(const SSL *s, int n) +{ + const SSL_CIPHER *c; + STACK_OF(SSL_CIPHER) *sk; + + if (s == NULL) + return NULL; + sk = SSL_get_ciphers(s); + if ((sk == NULL) || (sk_SSL_CIPHER_num(sk) <= n)) + return NULL; + c = sk_SSL_CIPHER_value(sk, n); + if (c == NULL) + return NULL; + return c->name; +} + +/** return a STACK of the ciphers available for the SSL_CTX and in order of + * preference */ +STACK_OF(SSL_CIPHER) *SSL_CTX_get_ciphers(const SSL_CTX *ctx) +{ + if (ctx != NULL) + return ctx->cipher_list; + return NULL; +} + +/* + * Distinguish between ciphers controlled by set_ciphersuite() and + * set_cipher_list() when counting. + */ +static int cipher_list_tls12_num(STACK_OF(SSL_CIPHER) *sk) +{ + int i, num = 0; + const SSL_CIPHER *c; + + if (sk == NULL) + return 0; + for (i = 0; i < sk_SSL_CIPHER_num(sk); ++i) { + c = sk_SSL_CIPHER_value(sk, i); + if (c->min_tls >= TLS1_3_VERSION) + continue; + num++; + } + return num; +} + +/** specify the ciphers to be used by default by the SSL_CTX */ +int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) +{ + STACK_OF(SSL_CIPHER) *sk; + + sk = ssl_create_cipher_list(ctx->method, ctx->tls13_ciphersuites, + &ctx->cipher_list, &ctx->cipher_list_by_id, str, + ctx->cert); + /* + * ssl_create_cipher_list may return an empty stack if it was unable to + * find a cipher matching the given rule string (for example if the rule + * string specifies a cipher which has been disabled). This is not an + * error as far as ssl_create_cipher_list is concerned, and hence + * ctx->cipher_list and ctx->cipher_list_by_id has been updated. + */ + if (sk == NULL) + return 0; + else if (cipher_list_tls12_num(sk) == 0) { + SSLerr(SSL_F_SSL_CTX_SET_CIPHER_LIST, SSL_R_NO_CIPHER_MATCH); + return 0; + } + return 1; +} + +/** specify the ciphers to be used by the SSL */ +int SSL_set_cipher_list(SSL *s, const char *str) +{ + STACK_OF(SSL_CIPHER) *sk; + + sk = ssl_create_cipher_list(s->ctx->method, s->tls13_ciphersuites, + &s->cipher_list, &s->cipher_list_by_id, str, + s->cert); + /* see comment in SSL_CTX_set_cipher_list */ + if (sk == NULL) + return 0; + else if (cipher_list_tls12_num(sk) == 0) { + SSLerr(SSL_F_SSL_SET_CIPHER_LIST, SSL_R_NO_CIPHER_MATCH); + return 0; + } + return 1; +} + +char *SSL_get_shared_ciphers(const SSL *s, char *buf, int size) +{ + char *p; + STACK_OF(SSL_CIPHER) *clntsk, *srvrsk; + const SSL_CIPHER *c; + int i; + + if (!s->server + || s->session == NULL + || s->session->ciphers == NULL + || size < 2) + return NULL; + + p = buf; + clntsk = s->session->ciphers; + srvrsk = SSL_get_ciphers(s); + if (clntsk == NULL || srvrsk == NULL) + return NULL; + + if (sk_SSL_CIPHER_num(clntsk) == 0 || sk_SSL_CIPHER_num(srvrsk) == 0) + return NULL; + + for (i = 0; i < sk_SSL_CIPHER_num(clntsk); i++) { + int n; + + c = sk_SSL_CIPHER_value(clntsk, i); + if (sk_SSL_CIPHER_find(srvrsk, c) < 0) + continue; + + n = strlen(c->name); + if (n + 1 > size) { + if (p != buf) + --p; + *p = '\0'; + return buf; + } + strcpy(p, c->name); + p += n; + *(p++) = ':'; + size -= n + 1; + } + p[-1] = '\0'; + return buf; +} + +/** return a servername extension value if provided in Client Hello, or NULL. + * So far, only host_name types are defined (RFC 3546). + */ + +const char *SSL_get_servername(const SSL *s, const int type) +{ + if (type != TLSEXT_NAMETYPE_host_name) + return NULL; + + /* + * SNI is not negotiated in pre-TLS-1.3 resumption flows, so fake up an + * SNI value to return if we are resuming/resumed. N.B. that we still + * call the relevant callbacks for such resumption flows, and callbacks + * might error out if there is not a SNI value available. + */ + if (s->hit) + return s->session->ext.hostname; + return s->ext.hostname; +} + +int SSL_get_servername_type(const SSL *s) +{ + if (s->session + && (!s->ext.hostname ? s->session-> + ext.hostname : s->ext.hostname)) + return TLSEXT_NAMETYPE_host_name; + return -1; +} + +/* + * SSL_select_next_proto implements the standard protocol selection. It is + * expected that this function is called from the callback set by + * SSL_CTX_set_next_proto_select_cb. The protocol data is assumed to be a + * vector of 8-bit, length prefixed byte strings. The length byte itself is + * not included in the length. A byte string of length 0 is invalid. No byte + * string may be truncated. The current, but experimental algorithm for + * selecting the protocol is: 1) If the server doesn't support NPN then this + * is indicated to the callback. In this case, the client application has to + * abort the connection or have a default application level protocol. 2) If + * the server supports NPN, but advertises an empty list then the client + * selects the first protocol in its list, but indicates via the API that this + * fallback case was enacted. 3) Otherwise, the client finds the first + * protocol in the server's list that it supports and selects this protocol. + * This is because it's assumed that the server has better information about + * which protocol a client should use. 4) If the client doesn't support any + * of the server's advertised protocols, then this is treated the same as + * case 2. It returns either OPENSSL_NPN_NEGOTIATED if a common protocol was + * found, or OPENSSL_NPN_NO_OVERLAP if the fallback case was reached. + */ +int SSL_select_next_proto(unsigned char **out, unsigned char *outlen, + const unsigned char *server, + unsigned int server_len, + const unsigned char *client, unsigned int client_len) +{ + unsigned int i, j; + const unsigned char *result; + int status = OPENSSL_NPN_UNSUPPORTED; + + /* + * For each protocol in server preference order, see if we support it. + */ + for (i = 0; i < server_len;) { + for (j = 0; j < client_len;) { + if (server[i] == client[j] && + memcmp(&server[i + 1], &client[j + 1], server[i]) == 0) { + /* We found a match */ + result = &server[i]; + status = OPENSSL_NPN_NEGOTIATED; + goto found; + } + j += client[j]; + j++; + } + i += server[i]; + i++; + } + + /* There's no overlap between our protocols and the server's list. */ + result = client; + status = OPENSSL_NPN_NO_OVERLAP; + + found: + *out = (unsigned char *)result + 1; + *outlen = result[0]; + return status; +} + +#ifndef OPENSSL_NO_NEXTPROTONEG +/* + * SSL_get0_next_proto_negotiated sets *data and *len to point to the + * client's requested protocol for this connection and returns 0. If the + * client didn't request any protocol, then *data is set to NULL. Note that + * the client can request any protocol it chooses. The value returned from + * this function need not be a member of the list of supported protocols + * provided by the callback. + */ +void SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data, + unsigned *len) +{ + *data = s->ext.npn; + if (!*data) { + *len = 0; + } else { + *len = (unsigned int)s->ext.npn_len; + } +} + +/* + * SSL_CTX_set_npn_advertised_cb sets a callback that is called when + * a TLS server needs a list of supported protocols for Next Protocol + * Negotiation. The returned list must be in wire format. The list is + * returned by setting |out| to point to it and |outlen| to its length. This + * memory will not be modified, but one should assume that the SSL* keeps a + * reference to it. The callback should return SSL_TLSEXT_ERR_OK if it + * wishes to advertise. Otherwise, no such extension will be included in the + * ServerHello. + */ +void SSL_CTX_set_npn_advertised_cb(SSL_CTX *ctx, + SSL_CTX_npn_advertised_cb_func cb, + void *arg) +{ + ctx->ext.npn_advertised_cb = cb; + ctx->ext.npn_advertised_cb_arg = arg; +} + +/* + * SSL_CTX_set_next_proto_select_cb sets a callback that is called when a + * client needs to select a protocol from the server's provided list. |out| + * must be set to point to the selected protocol (which may be within |in|). + * The length of the protocol name must be written into |outlen|. The + * server's advertised protocols are provided in |in| and |inlen|. The + * callback can assume that |in| is syntactically valid. The client must + * select a protocol. It is fatal to the connection if this callback returns + * a value other than SSL_TLSEXT_ERR_OK. + */ +void SSL_CTX_set_npn_select_cb(SSL_CTX *ctx, + SSL_CTX_npn_select_cb_func cb, + void *arg) +{ + ctx->ext.npn_select_cb = cb; + ctx->ext.npn_select_cb_arg = arg; +} +#endif + +/* + * SSL_CTX_set_alpn_protos sets the ALPN protocol list on |ctx| to |protos|. + * |protos| must be in wire-format (i.e. a series of non-empty, 8-bit + * length-prefixed strings). Returns 0 on success. + */ +int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char *protos, + unsigned int protos_len) +{ + OPENSSL_free(ctx->ext.alpn); + ctx->ext.alpn = OPENSSL_memdup(protos, protos_len); + if (ctx->ext.alpn == NULL) { + SSLerr(SSL_F_SSL_CTX_SET_ALPN_PROTOS, ERR_R_MALLOC_FAILURE); + return 1; + } + ctx->ext.alpn_len = protos_len; + + return 0; +} + +/* + * SSL_set_alpn_protos sets the ALPN protocol list on |ssl| to |protos|. + * |protos| must be in wire-format (i.e. a series of non-empty, 8-bit + * length-prefixed strings). Returns 0 on success. + */ +int SSL_set_alpn_protos(SSL *ssl, const unsigned char *protos, + unsigned int protos_len) +{ + OPENSSL_free(ssl->ext.alpn); + ssl->ext.alpn = OPENSSL_memdup(protos, protos_len); + if (ssl->ext.alpn == NULL) { + SSLerr(SSL_F_SSL_SET_ALPN_PROTOS, ERR_R_MALLOC_FAILURE); + return 1; + } + ssl->ext.alpn_len = protos_len; + + return 0; +} + +/* + * SSL_CTX_set_alpn_select_cb sets a callback function on |ctx| that is + * called during ClientHello processing in order to select an ALPN protocol + * from the client's list of offered protocols. + */ +void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx, + SSL_CTX_alpn_select_cb_func cb, + void *arg) +{ + ctx->ext.alpn_select_cb = cb; + ctx->ext.alpn_select_cb_arg = arg; +} + +/* + * SSL_get0_alpn_selected gets the selected ALPN protocol (if any) from |ssl|. + * On return it sets |*data| to point to |*len| bytes of protocol name + * (not including the leading length-prefix byte). If the server didn't + * respond with a negotiated protocol then |*len| will be zero. + */ +void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data, + unsigned int *len) +{ + *data = NULL; + if (ssl->s3) + *data = ssl->s3->alpn_selected; + if (*data == NULL) + *len = 0; + else + *len = (unsigned int)ssl->s3->alpn_selected_len; +} + +int SSL_export_keying_material(SSL *s, unsigned char *out, size_t olen, + const char *label, size_t llen, + const unsigned char *context, size_t contextlen, + int use_context) +{ + if (s->version < TLS1_VERSION && s->version != DTLS1_BAD_VER) + return -1; + + return s->method->ssl3_enc->export_keying_material(s, out, olen, label, + llen, context, + contextlen, use_context); +} + +int SSL_export_keying_material_early(SSL *s, unsigned char *out, size_t olen, + const char *label, size_t llen, + const unsigned char *context, + size_t contextlen) +{ + if (s->version != TLS1_3_VERSION) + return 0; + + return tls13_export_keying_material_early(s, out, olen, label, llen, + context, contextlen); +} + +static unsigned long ssl_session_hash(const SSL_SESSION *a) +{ + const unsigned char *session_id = a->session_id; + unsigned long l; + unsigned char tmp_storage[4]; + + if (a->session_id_length < sizeof(tmp_storage)) { + memset(tmp_storage, 0, sizeof(tmp_storage)); + memcpy(tmp_storage, a->session_id, a->session_id_length); + session_id = tmp_storage; + } + + l = (unsigned long) + ((unsigned long)session_id[0]) | + ((unsigned long)session_id[1] << 8L) | + ((unsigned long)session_id[2] << 16L) | + ((unsigned long)session_id[3] << 24L); + return l; +} + +/* + * NB: If this function (or indeed the hash function which uses a sort of + * coarser function than this one) is changed, ensure + * SSL_CTX_has_matching_session_id() is checked accordingly. It relies on + * being able to construct an SSL_SESSION that will collide with any existing + * session with a matching session ID. + */ +static int ssl_session_cmp(const SSL_SESSION *a, const SSL_SESSION *b) +{ + if (a->ssl_version != b->ssl_version) + return 1; + if (a->session_id_length != b->session_id_length) + return 1; + return memcmp(a->session_id, b->session_id, a->session_id_length); +} + +/* + * These wrapper functions should remain rather than redeclaring + * SSL_SESSION_hash and SSL_SESSION_cmp for void* types and casting each + * variable. The reason is that the functions aren't static, they're exposed + * via ssl.h. + */ + +SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) +{ + SSL_CTX *ret = NULL; + + if (meth == NULL) { + SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_NULL_SSL_METHOD_PASSED); + return NULL; + } + + if (!OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL)) + return NULL; + + if (SSL_get_ex_data_X509_STORE_CTX_idx() < 0) { + SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_X509_VERIFICATION_SETUP_PROBLEMS); + goto err; + } + ret = OPENSSL_zalloc(sizeof(*ret)); + if (ret == NULL) + goto err; + + ret->method = meth; + ret->min_proto_version = 0; + ret->max_proto_version = 0; + ret->mode = SSL_MODE_AUTO_RETRY; + ret->session_cache_mode = SSL_SESS_CACHE_SERVER; + ret->session_cache_size = SSL_SESSION_CACHE_MAX_SIZE_DEFAULT; + /* We take the system default. */ + ret->session_timeout = meth->get_timeout(); + ret->references = 1; + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) { + SSLerr(SSL_F_SSL_CTX_NEW, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ret); + return NULL; + } + ret->max_cert_list = SSL_MAX_CERT_LIST_DEFAULT; + ret->verify_mode = SSL_VERIFY_NONE; + if ((ret->cert = ssl_cert_new()) == NULL) + goto err; + + ret->sessions = lh_SSL_SESSION_new(ssl_session_hash, ssl_session_cmp); + if (ret->sessions == NULL) + goto err; + ret->cert_store = X509_STORE_new(); + if (ret->cert_store == NULL) + goto err; +#ifndef OPENSSL_NO_CT + ret->ctlog_store = CTLOG_STORE_new(); + if (ret->ctlog_store == NULL) + goto err; +#endif + + if (!SSL_CTX_set_ciphersuites(ret, TLS_DEFAULT_CIPHERSUITES)) + goto err; + + if (!ssl_create_cipher_list(ret->method, + ret->tls13_ciphersuites, + &ret->cipher_list, &ret->cipher_list_by_id, + SSL_DEFAULT_CIPHER_LIST, ret->cert) + || sk_SSL_CIPHER_num(ret->cipher_list) <= 0) { + SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_LIBRARY_HAS_NO_CIPHERS); + goto err2; + } + + ret->param = X509_VERIFY_PARAM_new(); + if (ret->param == NULL) + goto err; + + if ((ret->md5 = EVP_get_digestbyname("ssl3-md5")) == NULL) { + SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES); + goto err2; + } + if ((ret->sha1 = EVP_get_digestbyname("ssl3-sha1")) == NULL) { + SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES); + goto err2; + } + + if ((ret->ca_names = sk_X509_NAME_new_null()) == NULL) + goto err; + + if ((ret->client_ca_names = sk_X509_NAME_new_null()) == NULL) + goto err; + + if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_CTX, ret, &ret->ex_data)) + goto err; + + if ((ret->ext.secure = OPENSSL_secure_zalloc(sizeof(*ret->ext.secure))) == NULL) + goto err; + + /* No compression for DTLS */ + if (!(meth->ssl3_enc->enc_flags & SSL_ENC_FLAG_DTLS)) + ret->comp_methods = SSL_COMP_get_compression_methods(); + + ret->max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH; + ret->split_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH; + + /* Setup RFC5077 ticket keys */ + if ((RAND_bytes(ret->ext.tick_key_name, + sizeof(ret->ext.tick_key_name)) <= 0) + || (RAND_priv_bytes(ret->ext.secure->tick_hmac_key, + sizeof(ret->ext.secure->tick_hmac_key)) <= 0) + || (RAND_priv_bytes(ret->ext.secure->tick_aes_key, + sizeof(ret->ext.secure->tick_aes_key)) <= 0)) + ret->options |= SSL_OP_NO_TICKET; + + if (RAND_priv_bytes(ret->ext.cookie_hmac_key, + sizeof(ret->ext.cookie_hmac_key)) <= 0) + goto err; + +#ifndef OPENSSL_NO_SRP + if (!SSL_CTX_SRP_CTX_init(ret)) + goto err; +#endif +#ifndef OPENSSL_NO_ENGINE +# ifdef OPENSSL_SSL_CLIENT_ENGINE_AUTO +# define eng_strx(x) #x +# define eng_str(x) eng_strx(x) + /* Use specific client engine automatically... ignore errors */ + { + ENGINE *eng; + eng = ENGINE_by_id(eng_str(OPENSSL_SSL_CLIENT_ENGINE_AUTO)); + if (!eng) { + ERR_clear_error(); + ENGINE_load_builtin_engines(); + eng = ENGINE_by_id(eng_str(OPENSSL_SSL_CLIENT_ENGINE_AUTO)); + } + if (!eng || !SSL_CTX_set_client_cert_engine(ret, eng)) + ERR_clear_error(); + } +# endif +#endif + /* + * Default is to connect to non-RI servers. When RI is more widely + * deployed might change this. + */ + ret->options |= SSL_OP_LEGACY_SERVER_CONNECT; + /* + * Disable compression by default to prevent CRIME. Applications can + * re-enable compression by configuring + * SSL_CTX_clear_options(ctx, SSL_OP_NO_COMPRESSION); + * or by using the SSL_CONF library. Similarly we also enable TLSv1.3 + * middlebox compatibility by default. This may be disabled by default in + * a later OpenSSL version. + */ + ret->options |= SSL_OP_NO_COMPRESSION | SSL_OP_ENABLE_MIDDLEBOX_COMPAT; + + ret->ext.status_type = TLSEXT_STATUSTYPE_nothing; + + /* + * We cannot usefully set a default max_early_data here (which gets + * propagated in SSL_new(), for the following reason: setting the + * SSL field causes tls_construct_stoc_early_data() to tell the + * client that early data will be accepted when constructing a TLS 1.3 + * session ticket, and the client will accordingly send us early data + * when using that ticket (if the client has early data to send). + * However, in order for the early data to actually be consumed by + * the application, the application must also have calls to + * SSL_read_early_data(); otherwise we'll just skip past the early data + * and ignore it. So, since the application must add calls to + * SSL_read_early_data(), we also require them to add + * calls to SSL_CTX_set_max_early_data() in order to use early data, + * eliminating the bandwidth-wasting early data in the case described + * above. + */ + ret->max_early_data = 0; + + /* + * Default recv_max_early_data is a fully loaded single record. Could be + * split across multiple records in practice. We set this differently to + * max_early_data so that, in the default case, we do not advertise any + * support for early_data, but if a client were to send us some (e.g. + * because of an old, stale ticket) then we will tolerate it and skip over + * it. + */ + ret->recv_max_early_data = SSL3_RT_MAX_PLAIN_LENGTH; + + /* By default we send two session tickets automatically in TLSv1.3 */ + ret->num_tickets = 2; + + ssl_ctx_system_config(ret); + + return ret; + err: + SSLerr(SSL_F_SSL_CTX_NEW, ERR_R_MALLOC_FAILURE); + err2: + SSL_CTX_free(ret); + return NULL; +} + +int SSL_CTX_up_ref(SSL_CTX *ctx) +{ + int i; + + if (CRYPTO_UP_REF(&ctx->references, &i, ctx->lock) <= 0) + return 0; + + REF_PRINT_COUNT("SSL_CTX", ctx); + REF_ASSERT_ISNT(i < 2); + return ((i > 1) ? 1 : 0); +} + +void SSL_CTX_free(SSL_CTX *a) +{ + int i; + + if (a == NULL) + return; + + CRYPTO_DOWN_REF(&a->references, &i, a->lock); + REF_PRINT_COUNT("SSL_CTX", a); + if (i > 0) + return; + REF_ASSERT_ISNT(i < 0); + + X509_VERIFY_PARAM_free(a->param); + dane_ctx_final(&a->dane); + + /* + * Free internal session cache. However: the remove_cb() may reference + * the ex_data of SSL_CTX, thus the ex_data store can only be removed + * after the sessions were flushed. + * As the ex_data handling routines might also touch the session cache, + * the most secure solution seems to be: empty (flush) the cache, then + * free ex_data, then finally free the cache. + * (See ticket [openssl.org #212].) + */ + if (a->sessions != NULL) + SSL_CTX_flush_sessions(a, 0); + + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_CTX, a, &a->ex_data); + lh_SSL_SESSION_free(a->sessions); + X509_STORE_free(a->cert_store); +#ifndef OPENSSL_NO_CT + CTLOG_STORE_free(a->ctlog_store); +#endif + sk_SSL_CIPHER_free(a->cipher_list); + sk_SSL_CIPHER_free(a->cipher_list_by_id); + sk_SSL_CIPHER_free(a->tls13_ciphersuites); + ssl_cert_free(a->cert); + sk_X509_NAME_pop_free(a->ca_names, X509_NAME_free); + sk_X509_NAME_pop_free(a->client_ca_names, X509_NAME_free); + sk_X509_pop_free(a->extra_certs, X509_free); + a->comp_methods = NULL; +#ifndef OPENSSL_NO_SRTP + sk_SRTP_PROTECTION_PROFILE_free(a->srtp_profiles); +#endif +#ifndef OPENSSL_NO_SRP + SSL_CTX_SRP_CTX_free(a); +#endif +#ifndef OPENSSL_NO_ENGINE + ENGINE_finish(a->client_cert_engine); +#endif + +#ifndef OPENSSL_NO_EC + OPENSSL_free(a->ext.ecpointformats); + OPENSSL_free(a->ext.supportedgroups); +#endif + OPENSSL_free(a->ext.alpn); + OPENSSL_secure_free(a->ext.secure); + + CRYPTO_THREAD_lock_free(a->lock); + + OPENSSL_free(a); +} + +void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb) +{ + ctx->default_passwd_callback = cb; +} + +void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u) +{ + ctx->default_passwd_callback_userdata = u; +} + +pem_password_cb *SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx) +{ + return ctx->default_passwd_callback; +} + +void *SSL_CTX_get_default_passwd_cb_userdata(SSL_CTX *ctx) +{ + return ctx->default_passwd_callback_userdata; +} + +void SSL_set_default_passwd_cb(SSL *s, pem_password_cb *cb) +{ + s->default_passwd_callback = cb; +} + +void SSL_set_default_passwd_cb_userdata(SSL *s, void *u) +{ + s->default_passwd_callback_userdata = u; +} + +pem_password_cb *SSL_get_default_passwd_cb(SSL *s) +{ + return s->default_passwd_callback; +} + +void *SSL_get_default_passwd_cb_userdata(SSL *s) +{ + return s->default_passwd_callback_userdata; +} + +void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, + int (*cb) (X509_STORE_CTX *, void *), + void *arg) +{ + ctx->app_verify_callback = cb; + ctx->app_verify_arg = arg; +} + +void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, + int (*cb) (int, X509_STORE_CTX *)) +{ + ctx->verify_mode = mode; + ctx->default_verify_callback = cb; +} + +void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth) +{ + X509_VERIFY_PARAM_set_depth(ctx->param, depth); +} + +void SSL_CTX_set_cert_cb(SSL_CTX *c, int (*cb) (SSL *ssl, void *arg), void *arg) +{ + ssl_cert_set_cert_cb(c->cert, cb, arg); +} + +void SSL_set_cert_cb(SSL *s, int (*cb) (SSL *ssl, void *arg), void *arg) +{ + ssl_cert_set_cert_cb(s->cert, cb, arg); +} + +void ssl_set_masks(SSL *s) +{ + CERT *c = s->cert; + uint32_t *pvalid = s->s3->tmp.valid_flags; + int rsa_enc, rsa_sign, dh_tmp, dsa_sign; + unsigned long mask_k, mask_a; +#ifndef OPENSSL_NO_EC + int have_ecc_cert, ecdsa_ok; +#endif + if (c == NULL) + return; + +#ifndef OPENSSL_NO_DH + dh_tmp = (c->dh_tmp != NULL || c->dh_tmp_cb != NULL || c->dh_tmp_auto); +#else + dh_tmp = 0; +#endif + + rsa_enc = pvalid[SSL_PKEY_RSA] & CERT_PKEY_VALID; + rsa_sign = pvalid[SSL_PKEY_RSA] & CERT_PKEY_VALID; + dsa_sign = pvalid[SSL_PKEY_DSA_SIGN] & CERT_PKEY_VALID; +#ifndef OPENSSL_NO_EC + have_ecc_cert = pvalid[SSL_PKEY_ECC] & CERT_PKEY_VALID; +#endif + mask_k = 0; + mask_a = 0; + +#ifdef CIPHER_DEBUG + fprintf(stderr, "dht=%d re=%d rs=%d ds=%d\n", + dh_tmp, rsa_enc, rsa_sign, dsa_sign); +#endif + +#ifndef OPENSSL_NO_GOST + if (ssl_has_cert(s, SSL_PKEY_GOST12_512)) { + mask_k |= SSL_kGOST; + mask_a |= SSL_aGOST12; + } + if (ssl_has_cert(s, SSL_PKEY_GOST12_256)) { + mask_k |= SSL_kGOST; + mask_a |= SSL_aGOST12; + } + if (ssl_has_cert(s, SSL_PKEY_GOST01)) { + mask_k |= SSL_kGOST; + mask_a |= SSL_aGOST01; + } +#endif + + if (rsa_enc) + mask_k |= SSL_kRSA; + + if (dh_tmp) + mask_k |= SSL_kDHE; + + /* + * If we only have an RSA-PSS certificate allow RSA authentication + * if TLS 1.2 and peer supports it. + */ + + if (rsa_enc || rsa_sign || (ssl_has_cert(s, SSL_PKEY_RSA_PSS_SIGN) + && pvalid[SSL_PKEY_RSA_PSS_SIGN] & CERT_PKEY_EXPLICIT_SIGN + && TLS1_get_version(s) == TLS1_2_VERSION)) + mask_a |= SSL_aRSA; + + if (dsa_sign) { + mask_a |= SSL_aDSS; + } + + mask_a |= SSL_aNULL; + + /* + * An ECC certificate may be usable for ECDH and/or ECDSA cipher suites + * depending on the key usage extension. + */ +#ifndef OPENSSL_NO_EC + if (have_ecc_cert) { + uint32_t ex_kusage; + ex_kusage = X509_get_key_usage(c->pkeys[SSL_PKEY_ECC].x509); + ecdsa_ok = ex_kusage & X509v3_KU_DIGITAL_SIGNATURE; + if (!(pvalid[SSL_PKEY_ECC] & CERT_PKEY_SIGN)) + ecdsa_ok = 0; + if (ecdsa_ok) + mask_a |= SSL_aECDSA; + } + /* Allow Ed25519 for TLS 1.2 if peer supports it */ + if (!(mask_a & SSL_aECDSA) && ssl_has_cert(s, SSL_PKEY_ED25519) + && pvalid[SSL_PKEY_ED25519] & CERT_PKEY_EXPLICIT_SIGN + && TLS1_get_version(s) == TLS1_2_VERSION) + mask_a |= SSL_aECDSA; + + /* Allow Ed448 for TLS 1.2 if peer supports it */ + if (!(mask_a & SSL_aECDSA) && ssl_has_cert(s, SSL_PKEY_ED448) + && pvalid[SSL_PKEY_ED448] & CERT_PKEY_EXPLICIT_SIGN + && TLS1_get_version(s) == TLS1_2_VERSION) + mask_a |= SSL_aECDSA; +#endif + +#ifndef OPENSSL_NO_EC + mask_k |= SSL_kECDHE; +#endif + +#ifndef OPENSSL_NO_PSK + mask_k |= SSL_kPSK; + mask_a |= SSL_aPSK; + if (mask_k & SSL_kRSA) + mask_k |= SSL_kRSAPSK; + if (mask_k & SSL_kDHE) + mask_k |= SSL_kDHEPSK; + if (mask_k & SSL_kECDHE) + mask_k |= SSL_kECDHEPSK; +#endif + + s->s3->tmp.mask_k = mask_k; + s->s3->tmp.mask_a = mask_a; +} + +#ifndef OPENSSL_NO_EC + +int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s) +{ + if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aECDSA) { + /* key usage, if present, must allow signing */ + if (!(X509_get_key_usage(x) & X509v3_KU_DIGITAL_SIGNATURE)) { + SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG, + SSL_R_ECC_CERT_NOT_FOR_SIGNING); + return 0; + } + } + return 1; /* all checks are ok */ +} + +#endif + +int ssl_get_server_cert_serverinfo(SSL *s, const unsigned char **serverinfo, + size_t *serverinfo_length) +{ + CERT_PKEY *cpk = s->s3->tmp.cert; + *serverinfo_length = 0; + + if (cpk == NULL || cpk->serverinfo == NULL) + return 0; + + *serverinfo = cpk->serverinfo; + *serverinfo_length = cpk->serverinfo_length; + return 1; +} + +void ssl_update_cache(SSL *s, int mode) +{ + int i; + + /* + * If the session_id_length is 0, we are not supposed to cache it, and it + * would be rather hard to do anyway :-) + */ + if (s->session->session_id_length == 0) + return; + + /* + * If sid_ctx_length is 0 there is no specific application context + * associated with this session, so when we try to resume it and + * SSL_VERIFY_PEER is requested to verify the client identity, we have no + * indication that this is actually a session for the proper application + * context, and the *handshake* will fail, not just the resumption attempt. + * Do not cache (on the server) these sessions that are not resumable + * (clients can set SSL_VERIFY_PEER without needing a sid_ctx set). + */ + if (s->server && s->session->sid_ctx_length == 0 + && (s->verify_mode & SSL_VERIFY_PEER) != 0) + return; + + i = s->session_ctx->session_cache_mode; + if ((i & mode) != 0 + && (!s->hit || SSL_IS_TLS13(s))) { + /* + * Add the session to the internal cache. In server side TLSv1.3 we + * normally don't do this because by default it's a full stateless ticket + * with only a dummy session id so there is no reason to cache it, + * unless: + * - we are doing early_data, in which case we cache so that we can + * detect replays + * - the application has set a remove_session_cb so needs to know about + * session timeout events + * - SSL_OP_NO_TICKET is set in which case it is a stateful ticket + */ + if ((i & SSL_SESS_CACHE_NO_INTERNAL_STORE) == 0 + && (!SSL_IS_TLS13(s) + || !s->server + || (s->max_early_data > 0 + && (s->options & SSL_OP_NO_ANTI_REPLAY) == 0) + || s->session_ctx->remove_session_cb != NULL + || (s->options & SSL_OP_NO_TICKET) != 0)) + SSL_CTX_add_session(s->session_ctx, s->session); + + /* + * Add the session to the external cache. We do this even in server side + * TLSv1.3 without early data because some applications just want to + * know about the creation of a session and aren't doing a full cache. + */ + if (s->session_ctx->new_session_cb != NULL) { + SSL_SESSION_up_ref(s->session); + if (!s->session_ctx->new_session_cb(s, s->session)) + SSL_SESSION_free(s->session); + } + } + + /* auto flush every 255 connections */ + if ((!(i & SSL_SESS_CACHE_NO_AUTO_CLEAR)) && ((i & mode) == mode)) { + TSAN_QUALIFIER int *stat; + if (mode & SSL_SESS_CACHE_CLIENT) + stat = &s->session_ctx->stats.sess_connect_good; + else + stat = &s->session_ctx->stats.sess_accept_good; + if ((tsan_load(stat) & 0xff) == 0xff) + SSL_CTX_flush_sessions(s->session_ctx, (unsigned long)time(NULL)); + } +} + +const SSL_METHOD *SSL_CTX_get_ssl_method(const SSL_CTX *ctx) +{ + return ctx->method; +} + +const SSL_METHOD *SSL_get_ssl_method(const SSL *s) +{ + return s->method; +} + +int SSL_set_ssl_method(SSL *s, const SSL_METHOD *meth) +{ + int ret = 1; + + if (s->method != meth) { + const SSL_METHOD *sm = s->method; + int (*hf) (SSL *) = s->handshake_func; + + if (sm->version == meth->version) + s->method = meth; + else { + sm->ssl_free(s); + s->method = meth; + ret = s->method->ssl_new(s); + } + + if (hf == sm->ssl_connect) + s->handshake_func = meth->ssl_connect; + else if (hf == sm->ssl_accept) + s->handshake_func = meth->ssl_accept; + } + return ret; +} + +int SSL_get_error(const SSL *s, int i) +{ + int reason; + unsigned long l; + BIO *bio; + + if (i > 0) + return SSL_ERROR_NONE; + + /* + * Make things return SSL_ERROR_SYSCALL when doing SSL_do_handshake etc, + * where we do encode the error + */ + if ((l = ERR_peek_error()) != 0) { + if (ERR_GET_LIB(l) == ERR_LIB_SYS) + return SSL_ERROR_SYSCALL; + else + return SSL_ERROR_SSL; + } + + if (SSL_want_read(s)) { + bio = SSL_get_rbio(s); + if (BIO_should_read(bio)) + return SSL_ERROR_WANT_READ; + else if (BIO_should_write(bio)) + /* + * This one doesn't make too much sense ... We never try to write + * to the rbio, and an application program where rbio and wbio + * are separate couldn't even know what it should wait for. + * However if we ever set s->rwstate incorrectly (so that we have + * SSL_want_read(s) instead of SSL_want_write(s)) and rbio and + * wbio *are* the same, this test works around that bug; so it + * might be safer to keep it. + */ + return SSL_ERROR_WANT_WRITE; + else if (BIO_should_io_special(bio)) { + reason = BIO_get_retry_reason(bio); + if (reason == BIO_RR_CONNECT) + return SSL_ERROR_WANT_CONNECT; + else if (reason == BIO_RR_ACCEPT) + return SSL_ERROR_WANT_ACCEPT; + else + return SSL_ERROR_SYSCALL; /* unknown */ + } + } + + if (SSL_want_write(s)) { + /* Access wbio directly - in order to use the buffered bio if present */ + bio = s->wbio; + if (BIO_should_write(bio)) + return SSL_ERROR_WANT_WRITE; + else if (BIO_should_read(bio)) + /* + * See above (SSL_want_read(s) with BIO_should_write(bio)) + */ + return SSL_ERROR_WANT_READ; + else if (BIO_should_io_special(bio)) { + reason = BIO_get_retry_reason(bio); + if (reason == BIO_RR_CONNECT) + return SSL_ERROR_WANT_CONNECT; + else if (reason == BIO_RR_ACCEPT) + return SSL_ERROR_WANT_ACCEPT; + else + return SSL_ERROR_SYSCALL; + } + } + if (SSL_want_x509_lookup(s)) + return SSL_ERROR_WANT_X509_LOOKUP; + if (SSL_want_async(s)) + return SSL_ERROR_WANT_ASYNC; + if (SSL_want_async_job(s)) + return SSL_ERROR_WANT_ASYNC_JOB; + if (SSL_want_client_hello_cb(s)) + return SSL_ERROR_WANT_CLIENT_HELLO_CB; + + if ((s->shutdown & SSL_RECEIVED_SHUTDOWN) && + (s->s3->warn_alert == SSL_AD_CLOSE_NOTIFY)) + return SSL_ERROR_ZERO_RETURN; + + return SSL_ERROR_SYSCALL; +} + +static int ssl_do_handshake_intern(void *vargs) +{ + struct ssl_async_args *args; + SSL *s; + + args = (struct ssl_async_args *)vargs; + s = args->s; + + return s->handshake_func(s); +} + +int SSL_do_handshake(SSL *s) +{ + int ret = 1; + + if (s->handshake_func == NULL) { + SSLerr(SSL_F_SSL_DO_HANDSHAKE, SSL_R_CONNECTION_TYPE_NOT_SET); + return -1; + } + + ossl_statem_check_finish_init(s, -1); + + s->method->ssl_renegotiate_check(s, 0); + + if (SSL_in_init(s) || SSL_in_before(s)) { + if ((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) { + struct ssl_async_args args; + + args.s = s; + + ret = ssl_start_async_job(s, &args, ssl_do_handshake_intern); + } else { + ret = s->handshake_func(s); + } + } + return ret; +} + +void SSL_set_accept_state(SSL *s) +{ + s->server = 1; + s->shutdown = 0; + ossl_statem_clear(s); + s->handshake_func = s->method->ssl_accept; + clear_ciphers(s); +} + +void SSL_set_connect_state(SSL *s) +{ + s->server = 0; + s->shutdown = 0; + ossl_statem_clear(s); + s->handshake_func = s->method->ssl_connect; + clear_ciphers(s); +} + +int ssl_undefined_function(SSL *s) +{ + SSLerr(SSL_F_SSL_UNDEFINED_FUNCTION, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; +} + +int ssl_undefined_void_function(void) +{ + SSLerr(SSL_F_SSL_UNDEFINED_VOID_FUNCTION, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; +} + +int ssl_undefined_const_function(const SSL *s) +{ + return 0; +} + +const SSL_METHOD *ssl_bad_method(int ver) +{ + SSLerr(SSL_F_SSL_BAD_METHOD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return NULL; +} + +const char *ssl_protocol_to_string(int version) +{ + switch(version) + { + case TLS1_3_VERSION: + return "TLSv1.3"; + + case TLS1_2_VERSION: + return "TLSv1.2"; + + case TLS1_1_VERSION: + return "TLSv1.1"; + + case TLS1_VERSION: + return "TLSv1"; + + case SSL3_VERSION: + return "SSLv3"; + + case DTLS1_BAD_VER: + return "DTLSv0.9"; + + case DTLS1_VERSION: + return "DTLSv1"; + + case DTLS1_2_VERSION: + return "DTLSv1.2"; + + default: + return "unknown"; + } +} + +const char *SSL_get_version(const SSL *s) +{ + return ssl_protocol_to_string(s->version); +} + +static int dup_ca_names(STACK_OF(X509_NAME) **dst, STACK_OF(X509_NAME) *src) +{ + STACK_OF(X509_NAME) *sk; + X509_NAME *xn; + int i; + + if (src == NULL) { + *dst = NULL; + return 1; + } + + if ((sk = sk_X509_NAME_new_null()) == NULL) + return 0; + for (i = 0; i < sk_X509_NAME_num(src); i++) { + xn = X509_NAME_dup(sk_X509_NAME_value(src, i)); + if (xn == NULL) { + sk_X509_NAME_pop_free(sk, X509_NAME_free); + return 0; + } + if (sk_X509_NAME_insert(sk, xn, i) == 0) { + X509_NAME_free(xn); + sk_X509_NAME_pop_free(sk, X509_NAME_free); + return 0; + } + } + *dst = sk; + + return 1; +} + +SSL *SSL_dup(SSL *s) +{ + SSL *ret; + int i; + + /* If we're not quiescent, just up_ref! */ + if (!SSL_in_init(s) || !SSL_in_before(s)) { + CRYPTO_UP_REF(&s->references, &i, s->lock); + return s; + } + + /* + * Otherwise, copy configuration state, and session if set. + */ + if ((ret = SSL_new(SSL_get_SSL_CTX(s))) == NULL) + return NULL; + + if (s->session != NULL) { + /* + * Arranges to share the same session via up_ref. This "copies" + * session-id, SSL_METHOD, sid_ctx, and 'cert' + */ + if (!SSL_copy_session_id(ret, s)) + goto err; + } else { + /* + * No session has been established yet, so we have to expect that + * s->cert or ret->cert will be changed later -- they should not both + * point to the same object, and thus we can't use + * SSL_copy_session_id. + */ + if (!SSL_set_ssl_method(ret, s->method)) + goto err; + + if (s->cert != NULL) { + ssl_cert_free(ret->cert); + ret->cert = ssl_cert_dup(s->cert); + if (ret->cert == NULL) + goto err; + } + + if (!SSL_set_session_id_context(ret, s->sid_ctx, + (int)s->sid_ctx_length)) + goto err; + } + + if (!ssl_dane_dup(ret, s)) + goto err; + ret->version = s->version; + ret->options = s->options; + ret->mode = s->mode; + SSL_set_max_cert_list(ret, SSL_get_max_cert_list(s)); + SSL_set_read_ahead(ret, SSL_get_read_ahead(s)); + ret->msg_callback = s->msg_callback; + ret->msg_callback_arg = s->msg_callback_arg; + SSL_set_verify(ret, SSL_get_verify_mode(s), SSL_get_verify_callback(s)); + SSL_set_verify_depth(ret, SSL_get_verify_depth(s)); + ret->generate_session_id = s->generate_session_id; + + SSL_set_info_callback(ret, SSL_get_info_callback(s)); + + /* copy app data, a little dangerous perhaps */ + if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL, &ret->ex_data, &s->ex_data)) + goto err; + + /* setup rbio, and wbio */ + if (s->rbio != NULL) { + if (!BIO_dup_state(s->rbio, (char *)&ret->rbio)) + goto err; + } + if (s->wbio != NULL) { + if (s->wbio != s->rbio) { + if (!BIO_dup_state(s->wbio, (char *)&ret->wbio)) + goto err; + } else { + BIO_up_ref(ret->rbio); + ret->wbio = ret->rbio; + } + } + + ret->server = s->server; + if (s->handshake_func) { + if (s->server) + SSL_set_accept_state(ret); + else + SSL_set_connect_state(ret); + } + ret->shutdown = s->shutdown; + ret->hit = s->hit; + + ret->default_passwd_callback = s->default_passwd_callback; + ret->default_passwd_callback_userdata = s->default_passwd_callback_userdata; + + X509_VERIFY_PARAM_inherit(ret->param, s->param); + + /* dup the cipher_list and cipher_list_by_id stacks */ + if (s->cipher_list != NULL) { + if ((ret->cipher_list = sk_SSL_CIPHER_dup(s->cipher_list)) == NULL) + goto err; + } + if (s->cipher_list_by_id != NULL) + if ((ret->cipher_list_by_id = sk_SSL_CIPHER_dup(s->cipher_list_by_id)) + == NULL) + goto err; + + /* Dup the client_CA list */ + if (!dup_ca_names(&ret->ca_names, s->ca_names) + || !dup_ca_names(&ret->client_ca_names, s->client_ca_names)) + goto err; + + return ret; + + err: + SSL_free(ret); + return NULL; +} + +void ssl_clear_cipher_ctx(SSL *s) +{ + if (s->enc_read_ctx != NULL) { + EVP_CIPHER_CTX_free(s->enc_read_ctx); + s->enc_read_ctx = NULL; + } + if (s->enc_write_ctx != NULL) { + EVP_CIPHER_CTX_free(s->enc_write_ctx); + s->enc_write_ctx = NULL; + } +#ifndef OPENSSL_NO_COMP + COMP_CTX_free(s->expand); + s->expand = NULL; + COMP_CTX_free(s->compress); + s->compress = NULL; +#endif +} + +X509 *SSL_get_certificate(const SSL *s) +{ + if (s->cert != NULL) + return s->cert->key->x509; + else + return NULL; +} + +EVP_PKEY *SSL_get_privatekey(const SSL *s) +{ + if (s->cert != NULL) + return s->cert->key->privatekey; + else + return NULL; +} + +X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx) +{ + if (ctx->cert != NULL) + return ctx->cert->key->x509; + else + return NULL; +} + +EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx) +{ + if (ctx->cert != NULL) + return ctx->cert->key->privatekey; + else + return NULL; +} + +const SSL_CIPHER *SSL_get_current_cipher(const SSL *s) +{ + if ((s->session != NULL) && (s->session->cipher != NULL)) + return s->session->cipher; + return NULL; +} + +const SSL_CIPHER *SSL_get_pending_cipher(const SSL *s) +{ + return s->s3->tmp.new_cipher; +} + +const COMP_METHOD *SSL_get_current_compression(const SSL *s) +{ +#ifndef OPENSSL_NO_COMP + return s->compress ? COMP_CTX_get_method(s->compress) : NULL; +#else + return NULL; +#endif +} + +const COMP_METHOD *SSL_get_current_expansion(const SSL *s) +{ +#ifndef OPENSSL_NO_COMP + return s->expand ? COMP_CTX_get_method(s->expand) : NULL; +#else + return NULL; +#endif +} + +int ssl_init_wbio_buffer(SSL *s) +{ + BIO *bbio; + + if (s->bbio != NULL) { + /* Already buffered. */ + return 1; + } + + bbio = BIO_new(BIO_f_buffer()); + if (bbio == NULL || !BIO_set_read_buffer_size(bbio, 1)) { + BIO_free(bbio); + SSLerr(SSL_F_SSL_INIT_WBIO_BUFFER, ERR_R_BUF_LIB); + return 0; + } + s->bbio = bbio; + s->wbio = BIO_push(bbio, s->wbio); + + return 1; +} + +int ssl_free_wbio_buffer(SSL *s) +{ + /* callers ensure s is never null */ + if (s->bbio == NULL) + return 1; + + s->wbio = BIO_pop(s->wbio); + BIO_free(s->bbio); + s->bbio = NULL; + + return 1; +} + +void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx, int mode) +{ + ctx->quiet_shutdown = mode; +} + +int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx) +{ + return ctx->quiet_shutdown; +} + +void SSL_set_quiet_shutdown(SSL *s, int mode) +{ + s->quiet_shutdown = mode; +} + +int SSL_get_quiet_shutdown(const SSL *s) +{ + return s->quiet_shutdown; +} + +void SSL_set_shutdown(SSL *s, int mode) +{ + s->shutdown = mode; +} + +int SSL_get_shutdown(const SSL *s) +{ + return s->shutdown; +} + +int SSL_version(const SSL *s) +{ + return s->version; +} + +int SSL_client_version(const SSL *s) +{ + return s->client_version; +} + +SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl) +{ + return ssl->ctx; +} + +SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx) +{ + CERT *new_cert; + if (ssl->ctx == ctx) + return ssl->ctx; + if (ctx == NULL) + ctx = ssl->session_ctx; + new_cert = ssl_cert_dup(ctx->cert); + if (new_cert == NULL) { + return NULL; + } + + if (!custom_exts_copy_flags(&new_cert->custext, &ssl->cert->custext)) { + ssl_cert_free(new_cert); + return NULL; + } + + ssl_cert_free(ssl->cert); + ssl->cert = new_cert; + + /* + * Program invariant: |sid_ctx| has fixed size (SSL_MAX_SID_CTX_LENGTH), + * so setter APIs must prevent invalid lengths from entering the system. + */ + if (!ossl_assert(ssl->sid_ctx_length <= sizeof(ssl->sid_ctx))) + return NULL; + + /* + * If the session ID context matches that of the parent SSL_CTX, + * inherit it from the new SSL_CTX as well. If however the context does + * not match (i.e., it was set per-ssl with SSL_set_session_id_context), + * leave it unchanged. + */ + if ((ssl->ctx != NULL) && + (ssl->sid_ctx_length == ssl->ctx->sid_ctx_length) && + (memcmp(ssl->sid_ctx, ssl->ctx->sid_ctx, ssl->sid_ctx_length) == 0)) { + ssl->sid_ctx_length = ctx->sid_ctx_length; + memcpy(&ssl->sid_ctx, &ctx->sid_ctx, sizeof(ssl->sid_ctx)); + } + + SSL_CTX_up_ref(ctx); + SSL_CTX_free(ssl->ctx); /* decrement reference count */ + ssl->ctx = ctx; + + return ssl->ctx; +} + +int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx) +{ + return X509_STORE_set_default_paths(ctx->cert_store); +} + +int SSL_CTX_set_default_verify_dir(SSL_CTX *ctx) +{ + X509_LOOKUP *lookup; + + lookup = X509_STORE_add_lookup(ctx->cert_store, X509_LOOKUP_hash_dir()); + if (lookup == NULL) + return 0; + X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); + + /* Clear any errors if the default directory does not exist */ + ERR_clear_error(); + + return 1; +} + +int SSL_CTX_set_default_verify_file(SSL_CTX *ctx) +{ + X509_LOOKUP *lookup; + + lookup = X509_STORE_add_lookup(ctx->cert_store, X509_LOOKUP_file()); + if (lookup == NULL) + return 0; + + X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); + + /* Clear any errors if the default file does not exist */ + ERR_clear_error(); + + return 1; +} + +int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, + const char *CApath) +{ + return X509_STORE_load_locations(ctx->cert_store, CAfile, CApath); +} + +void SSL_set_info_callback(SSL *ssl, + void (*cb) (const SSL *ssl, int type, int val)) +{ + ssl->info_callback = cb; +} + +/* + * One compiler (Diab DCC) doesn't like argument names in returned function + * pointer. + */ +void (*SSL_get_info_callback(const SSL *ssl)) (const SSL * /* ssl */ , + int /* type */ , + int /* val */ ) { + return ssl->info_callback; +} + +void SSL_set_verify_result(SSL *ssl, long arg) +{ + ssl->verify_result = arg; +} + +long SSL_get_verify_result(const SSL *ssl) +{ + return ssl->verify_result; +} + +size_t SSL_get_client_random(const SSL *ssl, unsigned char *out, size_t outlen) +{ + if (outlen == 0) + return sizeof(ssl->s3->client_random); + if (outlen > sizeof(ssl->s3->client_random)) + outlen = sizeof(ssl->s3->client_random); + memcpy(out, ssl->s3->client_random, outlen); + return outlen; +} + +size_t SSL_get_server_random(const SSL *ssl, unsigned char *out, size_t outlen) +{ + if (outlen == 0) + return sizeof(ssl->s3->server_random); + if (outlen > sizeof(ssl->s3->server_random)) + outlen = sizeof(ssl->s3->server_random); + memcpy(out, ssl->s3->server_random, outlen); + return outlen; +} + +size_t SSL_SESSION_get_master_key(const SSL_SESSION *session, + unsigned char *out, size_t outlen) +{ + if (outlen == 0) + return session->master_key_length; + if (outlen > session->master_key_length) + outlen = session->master_key_length; + memcpy(out, session->master_key, outlen); + return outlen; +} + +int SSL_SESSION_set1_master_key(SSL_SESSION *sess, const unsigned char *in, + size_t len) +{ + if (len > sizeof(sess->master_key)) + return 0; + + memcpy(sess->master_key, in, len); + sess->master_key_length = len; + return 1; +} + + +int SSL_set_ex_data(SSL *s, int idx, void *arg) +{ + return CRYPTO_set_ex_data(&s->ex_data, idx, arg); +} + +void *SSL_get_ex_data(const SSL *s, int idx) +{ + return CRYPTO_get_ex_data(&s->ex_data, idx); +} + +int SSL_CTX_set_ex_data(SSL_CTX *s, int idx, void *arg) +{ + return CRYPTO_set_ex_data(&s->ex_data, idx, arg); +} + +void *SSL_CTX_get_ex_data(const SSL_CTX *s, int idx) +{ + return CRYPTO_get_ex_data(&s->ex_data, idx); +} + +X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *ctx) +{ + return ctx->cert_store; +} + +void SSL_CTX_set_cert_store(SSL_CTX *ctx, X509_STORE *store) +{ + X509_STORE_free(ctx->cert_store); + ctx->cert_store = store; +} + +void SSL_CTX_set1_cert_store(SSL_CTX *ctx, X509_STORE *store) +{ + if (store != NULL) + X509_STORE_up_ref(store); + SSL_CTX_set_cert_store(ctx, store); +} + +int SSL_want(const SSL *s) +{ + return s->rwstate; +} + +/** + * \brief Set the callback for generating temporary DH keys. + * \param ctx the SSL context. + * \param dh the callback + */ + +#ifndef OPENSSL_NO_DH +void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx, + DH *(*dh) (SSL *ssl, int is_export, + int keylength)) +{ + SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_TMP_DH_CB, (void (*)(void))dh); +} + +void SSL_set_tmp_dh_callback(SSL *ssl, DH *(*dh) (SSL *ssl, int is_export, + int keylength)) +{ + SSL_callback_ctrl(ssl, SSL_CTRL_SET_TMP_DH_CB, (void (*)(void))dh); +} +#endif + +#ifndef OPENSSL_NO_PSK +int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint) +{ + if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN) { + SSLerr(SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT, SSL_R_DATA_LENGTH_TOO_LONG); + return 0; + } + OPENSSL_free(ctx->cert->psk_identity_hint); + if (identity_hint != NULL) { + ctx->cert->psk_identity_hint = OPENSSL_strdup(identity_hint); + if (ctx->cert->psk_identity_hint == NULL) + return 0; + } else + ctx->cert->psk_identity_hint = NULL; + return 1; +} + +int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint) +{ + if (s == NULL) + return 0; + + if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN) { + SSLerr(SSL_F_SSL_USE_PSK_IDENTITY_HINT, SSL_R_DATA_LENGTH_TOO_LONG); + return 0; + } + OPENSSL_free(s->cert->psk_identity_hint); + if (identity_hint != NULL) { + s->cert->psk_identity_hint = OPENSSL_strdup(identity_hint); + if (s->cert->psk_identity_hint == NULL) + return 0; + } else + s->cert->psk_identity_hint = NULL; + return 1; +} + +const char *SSL_get_psk_identity_hint(const SSL *s) +{ + if (s == NULL || s->session == NULL) + return NULL; + return s->session->psk_identity_hint; +} + +const char *SSL_get_psk_identity(const SSL *s) +{ + if (s == NULL || s->session == NULL) + return NULL; + return s->session->psk_identity; +} + +void SSL_set_psk_client_callback(SSL *s, SSL_psk_client_cb_func cb) +{ + s->psk_client_callback = cb; +} + +void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx, SSL_psk_client_cb_func cb) +{ + ctx->psk_client_callback = cb; +} + +void SSL_set_psk_server_callback(SSL *s, SSL_psk_server_cb_func cb) +{ + s->psk_server_callback = cb; +} + +void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx, SSL_psk_server_cb_func cb) +{ + ctx->psk_server_callback = cb; +} +#endif + +void SSL_set_psk_find_session_callback(SSL *s, SSL_psk_find_session_cb_func cb) +{ + s->psk_find_session_cb = cb; +} + +void SSL_CTX_set_psk_find_session_callback(SSL_CTX *ctx, + SSL_psk_find_session_cb_func cb) +{ + ctx->psk_find_session_cb = cb; +} + +void SSL_set_psk_use_session_callback(SSL *s, SSL_psk_use_session_cb_func cb) +{ + s->psk_use_session_cb = cb; +} + +void SSL_CTX_set_psk_use_session_callback(SSL_CTX *ctx, + SSL_psk_use_session_cb_func cb) +{ + ctx->psk_use_session_cb = cb; +} + +void SSL_CTX_set_msg_callback(SSL_CTX *ctx, + void (*cb) (int write_p, int version, + int content_type, const void *buf, + size_t len, SSL *ssl, void *arg)) +{ + SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb); +} + +void SSL_set_msg_callback(SSL *ssl, + void (*cb) (int write_p, int version, + int content_type, const void *buf, + size_t len, SSL *ssl, void *arg)) +{ + SSL_callback_ctrl(ssl, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb); +} + +void SSL_CTX_set_not_resumable_session_callback(SSL_CTX *ctx, + int (*cb) (SSL *ssl, + int + is_forward_secure)) +{ + SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_NOT_RESUMABLE_SESS_CB, + (void (*)(void))cb); +} + +void SSL_set_not_resumable_session_callback(SSL *ssl, + int (*cb) (SSL *ssl, + int is_forward_secure)) +{ + SSL_callback_ctrl(ssl, SSL_CTRL_SET_NOT_RESUMABLE_SESS_CB, + (void (*)(void))cb); +} + +void SSL_CTX_set_record_padding_callback(SSL_CTX *ctx, + size_t (*cb) (SSL *ssl, int type, + size_t len, void *arg)) +{ + ctx->record_padding_cb = cb; +} + +void SSL_CTX_set_record_padding_callback_arg(SSL_CTX *ctx, void *arg) +{ + ctx->record_padding_arg = arg; +} + +void *SSL_CTX_get_record_padding_callback_arg(const SSL_CTX *ctx) +{ + return ctx->record_padding_arg; +} + +int SSL_CTX_set_block_padding(SSL_CTX *ctx, size_t block_size) +{ + /* block size of 0 or 1 is basically no padding */ + if (block_size == 1) + ctx->block_padding = 0; + else if (block_size <= SSL3_RT_MAX_PLAIN_LENGTH) + ctx->block_padding = block_size; + else + return 0; + return 1; +} + +void SSL_set_record_padding_callback(SSL *ssl, + size_t (*cb) (SSL *ssl, int type, + size_t len, void *arg)) +{ + ssl->record_padding_cb = cb; +} + +void SSL_set_record_padding_callback_arg(SSL *ssl, void *arg) +{ + ssl->record_padding_arg = arg; +} + +void *SSL_get_record_padding_callback_arg(const SSL *ssl) +{ + return ssl->record_padding_arg; +} + +int SSL_set_block_padding(SSL *ssl, size_t block_size) +{ + /* block size of 0 or 1 is basically no padding */ + if (block_size == 1) + ssl->block_padding = 0; + else if (block_size <= SSL3_RT_MAX_PLAIN_LENGTH) + ssl->block_padding = block_size; + else + return 0; + return 1; +} + +int SSL_set_num_tickets(SSL *s, size_t num_tickets) +{ + s->num_tickets = num_tickets; + + return 1; +} + +size_t SSL_get_num_tickets(const SSL *s) +{ + return s->num_tickets; +} + +int SSL_CTX_set_num_tickets(SSL_CTX *ctx, size_t num_tickets) +{ + ctx->num_tickets = num_tickets; + + return 1; +} + +size_t SSL_CTX_get_num_tickets(const SSL_CTX *ctx) +{ + return ctx->num_tickets; +} + +/* + * Allocates new EVP_MD_CTX and sets pointer to it into given pointer + * variable, freeing EVP_MD_CTX previously stored in that variable, if any. + * If EVP_MD pointer is passed, initializes ctx with this |md|. + * Returns the newly allocated ctx; + */ + +EVP_MD_CTX *ssl_replace_hash(EVP_MD_CTX **hash, const EVP_MD *md) +{ + ssl_clear_hash_ctx(hash); + *hash = EVP_MD_CTX_new(); + if (*hash == NULL || (md && EVP_DigestInit_ex(*hash, md, NULL) <= 0)) { + EVP_MD_CTX_free(*hash); + *hash = NULL; + return NULL; + } + return *hash; +} + +void ssl_clear_hash_ctx(EVP_MD_CTX **hash) +{ + + EVP_MD_CTX_free(*hash); + *hash = NULL; +} + +/* Retrieve handshake hashes */ +int ssl_handshake_hash(SSL *s, unsigned char *out, size_t outlen, + size_t *hashlen) +{ + EVP_MD_CTX *ctx = NULL; + EVP_MD_CTX *hdgst = s->s3->handshake_dgst; + int hashleni = EVP_MD_CTX_size(hdgst); + int ret = 0; + + if (hashleni < 0 || (size_t)hashleni > outlen) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_HANDSHAKE_HASH, + ERR_R_INTERNAL_ERROR); + goto err; + } + + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) + goto err; + + if (!EVP_MD_CTX_copy_ex(ctx, hdgst) + || EVP_DigestFinal_ex(ctx, out, NULL) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_HANDSHAKE_HASH, + ERR_R_INTERNAL_ERROR); + goto err; + } + + *hashlen = hashleni; + + ret = 1; + err: + EVP_MD_CTX_free(ctx); + return ret; +} + +int SSL_session_reused(SSL *s) +{ + return s->hit; +} + +int SSL_is_server(const SSL *s) +{ + return s->server; +} + +#if OPENSSL_API_COMPAT < 0x10100000L +void SSL_set_debug(SSL *s, int debug) +{ + /* Old function was do-nothing anyway... */ + (void)s; + (void)debug; +} +#endif + +void SSL_set_security_level(SSL *s, int level) +{ + s->cert->sec_level = level; +} + +int SSL_get_security_level(const SSL *s) +{ + return s->cert->sec_level; +} + +void SSL_set_security_callback(SSL *s, + int (*cb) (const SSL *s, const SSL_CTX *ctx, + int op, int bits, int nid, + void *other, void *ex)) +{ + s->cert->sec_cb = cb; +} + +int (*SSL_get_security_callback(const SSL *s)) (const SSL *s, + const SSL_CTX *ctx, int op, + int bits, int nid, void *other, + void *ex) { + return s->cert->sec_cb; +} + +void SSL_set0_security_ex_data(SSL *s, void *ex) +{ + s->cert->sec_ex = ex; +} + +void *SSL_get0_security_ex_data(const SSL *s) +{ + return s->cert->sec_ex; +} + +void SSL_CTX_set_security_level(SSL_CTX *ctx, int level) +{ + ctx->cert->sec_level = level; +} + +int SSL_CTX_get_security_level(const SSL_CTX *ctx) +{ + return ctx->cert->sec_level; +} + +void SSL_CTX_set_security_callback(SSL_CTX *ctx, + int (*cb) (const SSL *s, const SSL_CTX *ctx, + int op, int bits, int nid, + void *other, void *ex)) +{ + ctx->cert->sec_cb = cb; +} + +int (*SSL_CTX_get_security_callback(const SSL_CTX *ctx)) (const SSL *s, + const SSL_CTX *ctx, + int op, int bits, + int nid, + void *other, + void *ex) { + return ctx->cert->sec_cb; +} + +void SSL_CTX_set0_security_ex_data(SSL_CTX *ctx, void *ex) +{ + ctx->cert->sec_ex = ex; +} + +void *SSL_CTX_get0_security_ex_data(const SSL_CTX *ctx) +{ + return ctx->cert->sec_ex; +} + +/* + * Get/Set/Clear options in SSL_CTX or SSL, formerly macros, now functions that + * can return unsigned long, instead of the generic long return value from the + * control interface. + */ +unsigned long SSL_CTX_get_options(const SSL_CTX *ctx) +{ + return ctx->options; +} + +unsigned long SSL_get_options(const SSL *s) +{ + return s->options; +} + +unsigned long SSL_CTX_set_options(SSL_CTX *ctx, unsigned long op) +{ + return ctx->options |= op; +} + +unsigned long SSL_set_options(SSL *s, unsigned long op) +{ + return s->options |= op; +} + +unsigned long SSL_CTX_clear_options(SSL_CTX *ctx, unsigned long op) +{ + return ctx->options &= ~op; +} + +unsigned long SSL_clear_options(SSL *s, unsigned long op) +{ + return s->options &= ~op; +} + +STACK_OF(X509) *SSL_get0_verified_chain(const SSL *s) +{ + return s->verified_chain; +} + +IMPLEMENT_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER, ssl_cipher_id); + +#ifndef OPENSSL_NO_CT + +/* + * Moves SCTs from the |src| stack to the |dst| stack. + * The source of each SCT will be set to |origin|. + * If |dst| points to a NULL pointer, a new stack will be created and owned by + * the caller. + * Returns the number of SCTs moved, or a negative integer if an error occurs. + */ +static int ct_move_scts(STACK_OF(SCT) **dst, STACK_OF(SCT) *src, + sct_source_t origin) +{ + int scts_moved = 0; + SCT *sct = NULL; + + if (*dst == NULL) { + *dst = sk_SCT_new_null(); + if (*dst == NULL) { + SSLerr(SSL_F_CT_MOVE_SCTS, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + while ((sct = sk_SCT_pop(src)) != NULL) { + if (SCT_set_source(sct, origin) != 1) + goto err; + + if (sk_SCT_push(*dst, sct) <= 0) + goto err; + scts_moved += 1; + } + + return scts_moved; + err: + if (sct != NULL) + sk_SCT_push(src, sct); /* Put the SCT back */ + return -1; +} + +/* + * Look for data collected during ServerHello and parse if found. + * Returns the number of SCTs extracted. + */ +static int ct_extract_tls_extension_scts(SSL *s) +{ + int scts_extracted = 0; + + if (s->ext.scts != NULL) { + const unsigned char *p = s->ext.scts; + STACK_OF(SCT) *scts = o2i_SCT_LIST(NULL, &p, s->ext.scts_len); + + scts_extracted = ct_move_scts(&s->scts, scts, SCT_SOURCE_TLS_EXTENSION); + + SCT_LIST_free(scts); + } + + return scts_extracted; +} + +/* + * Checks for an OCSP response and then attempts to extract any SCTs found if it + * contains an SCT X509 extension. They will be stored in |s->scts|. + * Returns: + * - The number of SCTs extracted, assuming an OCSP response exists. + * - 0 if no OCSP response exists or it contains no SCTs. + * - A negative integer if an error occurs. + */ +static int ct_extract_ocsp_response_scts(SSL *s) +{ +# ifndef OPENSSL_NO_OCSP + int scts_extracted = 0; + const unsigned char *p; + OCSP_BASICRESP *br = NULL; + OCSP_RESPONSE *rsp = NULL; + STACK_OF(SCT) *scts = NULL; + int i; + + if (s->ext.ocsp.resp == NULL || s->ext.ocsp.resp_len == 0) + goto err; + + p = s->ext.ocsp.resp; + rsp = d2i_OCSP_RESPONSE(NULL, &p, (int)s->ext.ocsp.resp_len); + if (rsp == NULL) + goto err; + + br = OCSP_response_get1_basic(rsp); + if (br == NULL) + goto err; + + for (i = 0; i < OCSP_resp_count(br); ++i) { + OCSP_SINGLERESP *single = OCSP_resp_get0(br, i); + + if (single == NULL) + continue; + + scts = + OCSP_SINGLERESP_get1_ext_d2i(single, NID_ct_cert_scts, NULL, NULL); + scts_extracted = + ct_move_scts(&s->scts, scts, SCT_SOURCE_OCSP_STAPLED_RESPONSE); + if (scts_extracted < 0) + goto err; + } + err: + SCT_LIST_free(scts); + OCSP_BASICRESP_free(br); + OCSP_RESPONSE_free(rsp); + return scts_extracted; +# else + /* Behave as if no OCSP response exists */ + return 0; +# endif +} + +/* + * Attempts to extract SCTs from the peer certificate. + * Return the number of SCTs extracted, or a negative integer if an error + * occurs. + */ +static int ct_extract_x509v3_extension_scts(SSL *s) +{ + int scts_extracted = 0; + X509 *cert = s->session != NULL ? s->session->peer : NULL; + + if (cert != NULL) { + STACK_OF(SCT) *scts = + X509_get_ext_d2i(cert, NID_ct_precert_scts, NULL, NULL); + + scts_extracted = + ct_move_scts(&s->scts, scts, SCT_SOURCE_X509V3_EXTENSION); + + SCT_LIST_free(scts); + } + + return scts_extracted; +} + +/* + * Attempts to find all received SCTs by checking TLS extensions, the OCSP + * response (if it exists) and X509v3 extensions in the certificate. + * Returns NULL if an error occurs. + */ +const STACK_OF(SCT) *SSL_get0_peer_scts(SSL *s) +{ + if (!s->scts_parsed) { + if (ct_extract_tls_extension_scts(s) < 0 || + ct_extract_ocsp_response_scts(s) < 0 || + ct_extract_x509v3_extension_scts(s) < 0) + goto err; + + s->scts_parsed = 1; + } + return s->scts; + err: + return NULL; +} + +static int ct_permissive(const CT_POLICY_EVAL_CTX * ctx, + const STACK_OF(SCT) *scts, void *unused_arg) +{ + return 1; +} + +static int ct_strict(const CT_POLICY_EVAL_CTX * ctx, + const STACK_OF(SCT) *scts, void *unused_arg) +{ + int count = scts != NULL ? sk_SCT_num(scts) : 0; + int i; + + for (i = 0; i < count; ++i) { + SCT *sct = sk_SCT_value(scts, i); + int status = SCT_get_validation_status(sct); + + if (status == SCT_VALIDATION_STATUS_VALID) + return 1; + } + SSLerr(SSL_F_CT_STRICT, SSL_R_NO_VALID_SCTS); + return 0; +} + +int SSL_set_ct_validation_callback(SSL *s, ssl_ct_validation_cb callback, + void *arg) +{ + /* + * Since code exists that uses the custom extension handler for CT, look + * for this and throw an error if they have already registered to use CT. + */ + if (callback != NULL && SSL_CTX_has_client_custom_ext(s->ctx, + TLSEXT_TYPE_signed_certificate_timestamp)) + { + SSLerr(SSL_F_SSL_SET_CT_VALIDATION_CALLBACK, + SSL_R_CUSTOM_EXT_HANDLER_ALREADY_INSTALLED); + return 0; + } + + if (callback != NULL) { + /* + * If we are validating CT, then we MUST accept SCTs served via OCSP + */ + if (!SSL_set_tlsext_status_type(s, TLSEXT_STATUSTYPE_ocsp)) + return 0; + } + + s->ct_validation_callback = callback; + s->ct_validation_callback_arg = arg; + + return 1; +} + +int SSL_CTX_set_ct_validation_callback(SSL_CTX *ctx, + ssl_ct_validation_cb callback, void *arg) +{ + /* + * Since code exists that uses the custom extension handler for CT, look for + * this and throw an error if they have already registered to use CT. + */ + if (callback != NULL && SSL_CTX_has_client_custom_ext(ctx, + TLSEXT_TYPE_signed_certificate_timestamp)) + { + SSLerr(SSL_F_SSL_CTX_SET_CT_VALIDATION_CALLBACK, + SSL_R_CUSTOM_EXT_HANDLER_ALREADY_INSTALLED); + return 0; + } + + ctx->ct_validation_callback = callback; + ctx->ct_validation_callback_arg = arg; + return 1; +} + +int SSL_ct_is_enabled(const SSL *s) +{ + return s->ct_validation_callback != NULL; +} + +int SSL_CTX_ct_is_enabled(const SSL_CTX *ctx) +{ + return ctx->ct_validation_callback != NULL; +} + +int ssl_validate_ct(SSL *s) +{ + int ret = 0; + X509 *cert = s->session != NULL ? s->session->peer : NULL; + X509 *issuer; + SSL_DANE *dane = &s->dane; + CT_POLICY_EVAL_CTX *ctx = NULL; + const STACK_OF(SCT) *scts; + + /* + * If no callback is set, the peer is anonymous, or its chain is invalid, + * skip SCT validation - just return success. Applications that continue + * handshakes without certificates, with unverified chains, or pinned leaf + * certificates are outside the scope of the WebPKI and CT. + * + * The above exclusions notwithstanding the vast majority of peers will + * have rather ordinary certificate chains validated by typical + * applications that perform certificate verification and therefore will + * process SCTs when enabled. + */ + if (s->ct_validation_callback == NULL || cert == NULL || + s->verify_result != X509_V_OK || + s->verified_chain == NULL || sk_X509_num(s->verified_chain) <= 1) + return 1; + + /* + * CT not applicable for chains validated via DANE-TA(2) or DANE-EE(3) + * trust-anchors. See https://tools.ietf.org/html/rfc7671#section-4.2 + */ + if (DANETLS_ENABLED(dane) && dane->mtlsa != NULL) { + switch (dane->mtlsa->usage) { + case DANETLS_USAGE_DANE_TA: + case DANETLS_USAGE_DANE_EE: + return 1; + } + } + + ctx = CT_POLICY_EVAL_CTX_new(); + if (ctx == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_VALIDATE_CT, + ERR_R_MALLOC_FAILURE); + goto end; + } + + issuer = sk_X509_value(s->verified_chain, 1); + CT_POLICY_EVAL_CTX_set1_cert(ctx, cert); + CT_POLICY_EVAL_CTX_set1_issuer(ctx, issuer); + CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE(ctx, s->ctx->ctlog_store); + CT_POLICY_EVAL_CTX_set_time( + ctx, (uint64_t)SSL_SESSION_get_time(SSL_get0_session(s)) * 1000); + + scts = SSL_get0_peer_scts(s); + + /* + * This function returns success (> 0) only when all the SCTs are valid, 0 + * when some are invalid, and < 0 on various internal errors (out of + * memory, etc.). Having some, or even all, invalid SCTs is not sufficient + * reason to abort the handshake, that decision is up to the callback. + * Therefore, we error out only in the unexpected case that the return + * value is negative. + * + * XXX: One might well argue that the return value of this function is an + * unfortunate design choice. Its job is only to determine the validation + * status of each of the provided SCTs. So long as it correctly separates + * the wheat from the chaff it should return success. Failure in this case + * ought to correspond to an inability to carry out its duties. + */ + if (SCT_LIST_validate(scts, ctx) < 0) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_SSL_VALIDATE_CT, + SSL_R_SCT_VERIFICATION_FAILED); + goto end; + } + + ret = s->ct_validation_callback(ctx, scts, s->ct_validation_callback_arg); + if (ret < 0) + ret = 0; /* This function returns 0 on failure */ + if (!ret) + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_SSL_VALIDATE_CT, + SSL_R_CALLBACK_FAILED); + + end: + CT_POLICY_EVAL_CTX_free(ctx); + /* + * With SSL_VERIFY_NONE the session may be cached and re-used despite a + * failure return code here. Also the application may wish the complete + * the handshake, and then disconnect cleanly at a higher layer, after + * checking the verification status of the completed connection. + * + * We therefore force a certificate verification failure which will be + * visible via SSL_get_verify_result() and cached as part of any resumed + * session. + * + * Note: the permissive callback is for information gathering only, always + * returns success, and does not affect verification status. Only the + * strict callback or a custom application-specified callback can trigger + * connection failure or record a verification error. + */ + if (ret <= 0) + s->verify_result = X509_V_ERR_NO_VALID_SCTS; + return ret; +} + +int SSL_CTX_enable_ct(SSL_CTX *ctx, int validation_mode) +{ + switch (validation_mode) { + default: + SSLerr(SSL_F_SSL_CTX_ENABLE_CT, SSL_R_INVALID_CT_VALIDATION_TYPE); + return 0; + case SSL_CT_VALIDATION_PERMISSIVE: + return SSL_CTX_set_ct_validation_callback(ctx, ct_permissive, NULL); + case SSL_CT_VALIDATION_STRICT: + return SSL_CTX_set_ct_validation_callback(ctx, ct_strict, NULL); + } +} + +int SSL_enable_ct(SSL *s, int validation_mode) +{ + switch (validation_mode) { + default: + SSLerr(SSL_F_SSL_ENABLE_CT, SSL_R_INVALID_CT_VALIDATION_TYPE); + return 0; + case SSL_CT_VALIDATION_PERMISSIVE: + return SSL_set_ct_validation_callback(s, ct_permissive, NULL); + case SSL_CT_VALIDATION_STRICT: + return SSL_set_ct_validation_callback(s, ct_strict, NULL); + } +} + +int SSL_CTX_set_default_ctlog_list_file(SSL_CTX *ctx) +{ + return CTLOG_STORE_load_default_file(ctx->ctlog_store); +} + +int SSL_CTX_set_ctlog_list_file(SSL_CTX *ctx, const char *path) +{ + return CTLOG_STORE_load_file(ctx->ctlog_store, path); +} + +void SSL_CTX_set0_ctlog_store(SSL_CTX *ctx, CTLOG_STORE * logs) +{ + CTLOG_STORE_free(ctx->ctlog_store); + ctx->ctlog_store = logs; +} + +const CTLOG_STORE *SSL_CTX_get0_ctlog_store(const SSL_CTX *ctx) +{ + return ctx->ctlog_store; +} + +#endif /* OPENSSL_NO_CT */ + +void SSL_CTX_set_client_hello_cb(SSL_CTX *c, SSL_client_hello_cb_fn cb, + void *arg) +{ + c->client_hello_cb = cb; + c->client_hello_cb_arg = arg; +} + +int SSL_client_hello_isv2(SSL *s) +{ + if (s->clienthello == NULL) + return 0; + return s->clienthello->isv2; +} + +unsigned int SSL_client_hello_get0_legacy_version(SSL *s) +{ + if (s->clienthello == NULL) + return 0; + return s->clienthello->legacy_version; +} + +size_t SSL_client_hello_get0_random(SSL *s, const unsigned char **out) +{ + if (s->clienthello == NULL) + return 0; + if (out != NULL) + *out = s->clienthello->random; + return SSL3_RANDOM_SIZE; +} + +size_t SSL_client_hello_get0_session_id(SSL *s, const unsigned char **out) +{ + if (s->clienthello == NULL) + return 0; + if (out != NULL) + *out = s->clienthello->session_id; + return s->clienthello->session_id_len; +} + +size_t SSL_client_hello_get0_ciphers(SSL *s, const unsigned char **out) +{ + if (s->clienthello == NULL) + return 0; + if (out != NULL) + *out = PACKET_data(&s->clienthello->ciphersuites); + return PACKET_remaining(&s->clienthello->ciphersuites); +} + +size_t SSL_client_hello_get0_compression_methods(SSL *s, const unsigned char **out) +{ + if (s->clienthello == NULL) + return 0; + if (out != NULL) + *out = s->clienthello->compressions; + return s->clienthello->compressions_len; +} + +int SSL_client_hello_get1_extensions_present(SSL *s, int **out, size_t *outlen) +{ + RAW_EXTENSION *ext; + int *present; + size_t num = 0, i; + + if (s->clienthello == NULL || out == NULL || outlen == NULL) + return 0; + for (i = 0; i < s->clienthello->pre_proc_exts_len; i++) { + ext = s->clienthello->pre_proc_exts + i; + if (ext->present) + num++; + } + if ((present = OPENSSL_malloc(sizeof(*present) * num)) == NULL) { + SSLerr(SSL_F_SSL_CLIENT_HELLO_GET1_EXTENSIONS_PRESENT, + ERR_R_MALLOC_FAILURE); + return 0; + } + for (i = 0; i < s->clienthello->pre_proc_exts_len; i++) { + ext = s->clienthello->pre_proc_exts + i; + if (ext->present) { + if (ext->received_order >= num) + goto err; + present[ext->received_order] = ext->type; + } + } + *out = present; + *outlen = num; + return 1; + err: + OPENSSL_free(present); + return 0; +} + +int SSL_client_hello_get0_ext(SSL *s, unsigned int type, const unsigned char **out, + size_t *outlen) +{ + size_t i; + RAW_EXTENSION *r; + + if (s->clienthello == NULL) + return 0; + for (i = 0; i < s->clienthello->pre_proc_exts_len; ++i) { + r = s->clienthello->pre_proc_exts + i; + if (r->present && r->type == type) { + if (out != NULL) + *out = PACKET_data(&r->data); + if (outlen != NULL) + *outlen = PACKET_remaining(&r->data); + return 1; + } + } + return 0; +} + +int SSL_free_buffers(SSL *ssl) +{ + RECORD_LAYER *rl = &ssl->rlayer; + + if (RECORD_LAYER_read_pending(rl) || RECORD_LAYER_write_pending(rl)) + return 0; + + RECORD_LAYER_release(rl); + return 1; +} + +int SSL_alloc_buffers(SSL *ssl) +{ + return ssl3_setup_buffers(ssl); +} + +void SSL_CTX_set_keylog_callback(SSL_CTX *ctx, SSL_CTX_keylog_cb_func cb) +{ + ctx->keylog_callback = cb; +} + +SSL_CTX_keylog_cb_func SSL_CTX_get_keylog_callback(const SSL_CTX *ctx) +{ + return ctx->keylog_callback; +} + +static int nss_keylog_int(const char *prefix, + SSL *ssl, + const uint8_t *parameter_1, + size_t parameter_1_len, + const uint8_t *parameter_2, + size_t parameter_2_len) +{ + char *out = NULL; + char *cursor = NULL; + size_t out_len = 0; + size_t i; + size_t prefix_len; + + if (ssl->ctx->keylog_callback == NULL) + return 1; + + /* + * Our output buffer will contain the following strings, rendered with + * space characters in between, terminated by a NULL character: first the + * prefix, then the first parameter, then the second parameter. The + * meaning of each parameter depends on the specific key material being + * logged. Note that the first and second parameters are encoded in + * hexadecimal, so we need a buffer that is twice their lengths. + */ + prefix_len = strlen(prefix); + out_len = prefix_len + (2 * parameter_1_len) + (2 * parameter_2_len) + 3; + if ((out = cursor = OPENSSL_malloc(out_len)) == NULL) { + SSLfatal(ssl, SSL_AD_INTERNAL_ERROR, SSL_F_NSS_KEYLOG_INT, + ERR_R_MALLOC_FAILURE); + return 0; + } + + strcpy(cursor, prefix); + cursor += prefix_len; + *cursor++ = ' '; + + for (i = 0; i < parameter_1_len; i++) { + sprintf(cursor, "%02x", parameter_1[i]); + cursor += 2; + } + *cursor++ = ' '; + + for (i = 0; i < parameter_2_len; i++) { + sprintf(cursor, "%02x", parameter_2[i]); + cursor += 2; + } + *cursor = '\0'; + + ssl->ctx->keylog_callback(ssl, (const char *)out); + OPENSSL_clear_free(out, out_len); + return 1; + +} + +int ssl_log_rsa_client_key_exchange(SSL *ssl, + const uint8_t *encrypted_premaster, + size_t encrypted_premaster_len, + const uint8_t *premaster, + size_t premaster_len) +{ + if (encrypted_premaster_len < 8) { + SSLfatal(ssl, SSL_AD_INTERNAL_ERROR, + SSL_F_SSL_LOG_RSA_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); + return 0; + } + + /* We only want the first 8 bytes of the encrypted premaster as a tag. */ + return nss_keylog_int("RSA", + ssl, + encrypted_premaster, + 8, + premaster, + premaster_len); +} + +int ssl_log_secret(SSL *ssl, + const char *label, + const uint8_t *secret, + size_t secret_len) +{ + return nss_keylog_int(label, + ssl, + ssl->s3->client_random, + SSL3_RANDOM_SIZE, + secret, + secret_len); +} + +#define SSLV2_CIPHER_LEN 3 + +int ssl_cache_cipherlist(SSL *s, PACKET *cipher_suites, int sslv2format) +{ + int n; + + n = sslv2format ? SSLV2_CIPHER_LEN : TLS_CIPHER_LEN; + + if (PACKET_remaining(cipher_suites) == 0) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SSL_CACHE_CIPHERLIST, + SSL_R_NO_CIPHERS_SPECIFIED); + return 0; + } + + if (PACKET_remaining(cipher_suites) % n != 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL_CACHE_CIPHERLIST, + SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST); + return 0; + } + + OPENSSL_free(s->s3->tmp.ciphers_raw); + s->s3->tmp.ciphers_raw = NULL; + s->s3->tmp.ciphers_rawlen = 0; + + if (sslv2format) { + size_t numciphers = PACKET_remaining(cipher_suites) / n; + PACKET sslv2ciphers = *cipher_suites; + unsigned int leadbyte; + unsigned char *raw; + + /* + * We store the raw ciphers list in SSLv3+ format so we need to do some + * preprocessing to convert the list first. If there are any SSLv2 only + * ciphersuites with a non-zero leading byte then we are going to + * slightly over allocate because we won't store those. But that isn't a + * problem. + */ + raw = OPENSSL_malloc(numciphers * TLS_CIPHER_LEN); + s->s3->tmp.ciphers_raw = raw; + if (raw == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CACHE_CIPHERLIST, + ERR_R_MALLOC_FAILURE); + return 0; + } + for (s->s3->tmp.ciphers_rawlen = 0; + PACKET_remaining(&sslv2ciphers) > 0; + raw += TLS_CIPHER_LEN) { + if (!PACKET_get_1(&sslv2ciphers, &leadbyte) + || (leadbyte == 0 + && !PACKET_copy_bytes(&sslv2ciphers, raw, + TLS_CIPHER_LEN)) + || (leadbyte != 0 + && !PACKET_forward(&sslv2ciphers, TLS_CIPHER_LEN))) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL_CACHE_CIPHERLIST, + SSL_R_BAD_PACKET); + OPENSSL_free(s->s3->tmp.ciphers_raw); + s->s3->tmp.ciphers_raw = NULL; + s->s3->tmp.ciphers_rawlen = 0; + return 0; + } + if (leadbyte == 0) + s->s3->tmp.ciphers_rawlen += TLS_CIPHER_LEN; + } + } else if (!PACKET_memdup(cipher_suites, &s->s3->tmp.ciphers_raw, + &s->s3->tmp.ciphers_rawlen)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CACHE_CIPHERLIST, + ERR_R_INTERNAL_ERROR); + return 0; + } + return 1; +} + +int SSL_bytes_to_cipher_list(SSL *s, const unsigned char *bytes, size_t len, + int isv2format, STACK_OF(SSL_CIPHER) **sk, + STACK_OF(SSL_CIPHER) **scsvs) +{ + PACKET pkt; + + if (!PACKET_buf_init(&pkt, bytes, len)) + return 0; + return bytes_to_cipher_list(s, &pkt, sk, scsvs, isv2format, 0); +} + +int bytes_to_cipher_list(SSL *s, PACKET *cipher_suites, + STACK_OF(SSL_CIPHER) **skp, + STACK_OF(SSL_CIPHER) **scsvs_out, + int sslv2format, int fatal) +{ + const SSL_CIPHER *c; + STACK_OF(SSL_CIPHER) *sk = NULL; + STACK_OF(SSL_CIPHER) *scsvs = NULL; + int n; + /* 3 = SSLV2_CIPHER_LEN > TLS_CIPHER_LEN = 2. */ + unsigned char cipher[SSLV2_CIPHER_LEN]; + + n = sslv2format ? SSLV2_CIPHER_LEN : TLS_CIPHER_LEN; + + if (PACKET_remaining(cipher_suites) == 0) { + if (fatal) + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_BYTES_TO_CIPHER_LIST, + SSL_R_NO_CIPHERS_SPECIFIED); + else + SSLerr(SSL_F_BYTES_TO_CIPHER_LIST, SSL_R_NO_CIPHERS_SPECIFIED); + return 0; + } + + if (PACKET_remaining(cipher_suites) % n != 0) { + if (fatal) + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_BYTES_TO_CIPHER_LIST, + SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST); + else + SSLerr(SSL_F_BYTES_TO_CIPHER_LIST, + SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST); + return 0; + } + + sk = sk_SSL_CIPHER_new_null(); + scsvs = sk_SSL_CIPHER_new_null(); + if (sk == NULL || scsvs == NULL) { + if (fatal) + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_BYTES_TO_CIPHER_LIST, + ERR_R_MALLOC_FAILURE); + else + SSLerr(SSL_F_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE); + goto err; + } + + while (PACKET_copy_bytes(cipher_suites, cipher, n)) { + /* + * SSLv3 ciphers wrapped in an SSLv2-compatible ClientHello have the + * first byte set to zero, while true SSLv2 ciphers have a non-zero + * first byte. We don't support any true SSLv2 ciphers, so skip them. + */ + if (sslv2format && cipher[0] != '\0') + continue; + + /* For SSLv2-compat, ignore leading 0-byte. */ + c = ssl_get_cipher_by_char(s, sslv2format ? &cipher[1] : cipher, 1); + if (c != NULL) { + if ((c->valid && !sk_SSL_CIPHER_push(sk, c)) || + (!c->valid && !sk_SSL_CIPHER_push(scsvs, c))) { + if (fatal) + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE); + else + SSLerr(SSL_F_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE); + goto err; + } + } + } + if (PACKET_remaining(cipher_suites) > 0) { + if (fatal) + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_BYTES_TO_CIPHER_LIST, + SSL_R_BAD_LENGTH); + else + SSLerr(SSL_F_BYTES_TO_CIPHER_LIST, SSL_R_BAD_LENGTH); + goto err; + } + + if (skp != NULL) + *skp = sk; + else + sk_SSL_CIPHER_free(sk); + if (scsvs_out != NULL) + *scsvs_out = scsvs; + else + sk_SSL_CIPHER_free(scsvs); + return 1; + err: + sk_SSL_CIPHER_free(sk); + sk_SSL_CIPHER_free(scsvs); + return 0; +} + +int SSL_CTX_set_max_early_data(SSL_CTX *ctx, uint32_t max_early_data) +{ + ctx->max_early_data = max_early_data; + + return 1; +} + +uint32_t SSL_CTX_get_max_early_data(const SSL_CTX *ctx) +{ + return ctx->max_early_data; +} + +int SSL_set_max_early_data(SSL *s, uint32_t max_early_data) +{ + s->max_early_data = max_early_data; + + return 1; +} + +uint32_t SSL_get_max_early_data(const SSL *s) +{ + return s->max_early_data; +} + +int SSL_CTX_set_recv_max_early_data(SSL_CTX *ctx, uint32_t recv_max_early_data) +{ + ctx->recv_max_early_data = recv_max_early_data; + + return 1; +} + +uint32_t SSL_CTX_get_recv_max_early_data(const SSL_CTX *ctx) +{ + return ctx->recv_max_early_data; +} + +int SSL_set_recv_max_early_data(SSL *s, uint32_t recv_max_early_data) +{ + s->recv_max_early_data = recv_max_early_data; + + return 1; +} + +uint32_t SSL_get_recv_max_early_data(const SSL *s) +{ + return s->recv_max_early_data; +} + +__owur unsigned int ssl_get_max_send_fragment(const SSL *ssl) +{ + /* Return any active Max Fragment Len extension */ + if (ssl->session != NULL && USE_MAX_FRAGMENT_LENGTH_EXT(ssl->session)) + return GET_MAX_FRAGMENT_LENGTH(ssl->session); + + /* return current SSL connection setting */ + return ssl->max_send_fragment; +} + +__owur unsigned int ssl_get_split_send_fragment(const SSL *ssl) +{ + /* Return a value regarding an active Max Fragment Len extension */ + if (ssl->session != NULL && USE_MAX_FRAGMENT_LENGTH_EXT(ssl->session) + && ssl->split_send_fragment > GET_MAX_FRAGMENT_LENGTH(ssl->session)) + return GET_MAX_FRAGMENT_LENGTH(ssl->session); + + /* else limit |split_send_fragment| to current |max_send_fragment| */ + if (ssl->split_send_fragment > ssl->max_send_fragment) + return ssl->max_send_fragment; + + /* return current SSL connection setting */ + return ssl->split_send_fragment; +} + +int SSL_stateless(SSL *s) +{ + int ret; + + /* Ensure there is no state left over from a previous invocation */ + if (!SSL_clear(s)) + return 0; + + ERR_clear_error(); + + s->s3->flags |= TLS1_FLAGS_STATELESS; + ret = SSL_accept(s); + s->s3->flags &= ~TLS1_FLAGS_STATELESS; + + if (ret > 0 && s->ext.cookieok) + return 1; + + if (s->hello_retry_request == SSL_HRR_PENDING && !ossl_statem_in_error(s)) + return 0; + + return -1; +} + +void SSL_CTX_set_post_handshake_auth(SSL_CTX *ctx, int val) +{ + ctx->pha_enabled = val; +} + +void SSL_set_post_handshake_auth(SSL *ssl, int val) +{ + ssl->pha_enabled = val; +} + +int SSL_verify_client_post_handshake(SSL *ssl) +{ + if (!SSL_IS_TLS13(ssl)) { + SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, SSL_R_WRONG_SSL_VERSION); + return 0; + } + if (!ssl->server) { + SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, SSL_R_NOT_SERVER); + return 0; + } + + if (!SSL_is_init_finished(ssl)) { + SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, SSL_R_STILL_IN_INIT); + return 0; + } + + switch (ssl->post_handshake_auth) { + case SSL_PHA_NONE: + SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, SSL_R_EXTENSION_NOT_RECEIVED); + return 0; + default: + case SSL_PHA_EXT_SENT: + SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, ERR_R_INTERNAL_ERROR); + return 0; + case SSL_PHA_EXT_RECEIVED: + break; + case SSL_PHA_REQUEST_PENDING: + SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, SSL_R_REQUEST_PENDING); + return 0; + case SSL_PHA_REQUESTED: + SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, SSL_R_REQUEST_SENT); + return 0; + } + + ssl->post_handshake_auth = SSL_PHA_REQUEST_PENDING; + + /* checks verify_mode and algorithm_auth */ + if (!send_certificate_request(ssl)) { + ssl->post_handshake_auth = SSL_PHA_EXT_RECEIVED; /* restore on error */ + SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, SSL_R_INVALID_CONFIG); + return 0; + } + + ossl_statem_set_in_init(ssl, 1); + return 1; +} + +int SSL_CTX_set_session_ticket_cb(SSL_CTX *ctx, + SSL_CTX_generate_session_ticket_fn gen_cb, + SSL_CTX_decrypt_session_ticket_fn dec_cb, + void *arg) +{ + ctx->generate_ticket_cb = gen_cb; + ctx->decrypt_ticket_cb = dec_cb; + ctx->ticket_cb_data = arg; + return 1; +} + +void SSL_CTX_set_allow_early_data_cb(SSL_CTX *ctx, + SSL_allow_early_data_cb_fn cb, + void *arg) +{ + ctx->allow_early_data_cb = cb; + ctx->allow_early_data_cb_data = arg; +} + +void SSL_set_allow_early_data_cb(SSL *s, + SSL_allow_early_data_cb_fn cb, + void *arg) +{ + s->allow_early_data_cb = cb; + s->allow_early_data_cb_data = arg; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_locl.h b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_locl.h new file mode 100644 index 000000000..f326399e0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_locl.h @@ -0,0 +1,2666 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * Copyright 2005 Nokia. All rights reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_SSL_LOCL_H +# define HEADER_SSL_LOCL_H + +# include "e_os.h" /* struct timeval for DTLS */ +# include +# include +# include +# include + +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include "record/record.h" +# include "statem/statem.h" +# include "packet_locl.h" +# include "internal/dane.h" +# include "internal/refcount.h" +# include "internal/tsan_assist.h" + +# ifdef OPENSSL_BUILD_SHLIBSSL +# undef OPENSSL_EXTERN +# define OPENSSL_EXTERN OPENSSL_EXPORT +# endif + +# define c2l(c,l) (l = ((unsigned long)(*((c)++))) , \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<<24)) + +/* NOTE - c is not incremented as per c2l */ +# define c2ln(c,l1,l2,n) { \ + c+=n; \ + l1=l2=0; \ + switch (n) { \ + case 8: l2 =((unsigned long)(*(--(c))))<<24; \ + case 7: l2|=((unsigned long)(*(--(c))))<<16; \ + case 6: l2|=((unsigned long)(*(--(c))))<< 8; \ + case 5: l2|=((unsigned long)(*(--(c)))); \ + case 4: l1 =((unsigned long)(*(--(c))))<<24; \ + case 3: l1|=((unsigned long)(*(--(c))))<<16; \ + case 2: l1|=((unsigned long)(*(--(c))))<< 8; \ + case 1: l1|=((unsigned long)(*(--(c)))); \ + } \ + } + +# define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24)&0xff)) + +# define n2l(c,l) (l =((unsigned long)(*((c)++)))<<24, \ + l|=((unsigned long)(*((c)++)))<<16, \ + l|=((unsigned long)(*((c)++)))<< 8, \ + l|=((unsigned long)(*((c)++)))) + +# define n2l8(c,l) (l =((uint64_t)(*((c)++)))<<56, \ + l|=((uint64_t)(*((c)++)))<<48, \ + l|=((uint64_t)(*((c)++)))<<40, \ + l|=((uint64_t)(*((c)++)))<<32, \ + l|=((uint64_t)(*((c)++)))<<24, \ + l|=((uint64_t)(*((c)++)))<<16, \ + l|=((uint64_t)(*((c)++)))<< 8, \ + l|=((uint64_t)(*((c)++)))) + + +# define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +# define l2n6(l,c) (*((c)++)=(unsigned char)(((l)>>40)&0xff), \ + *((c)++)=(unsigned char)(((l)>>32)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +# define l2n8(l,c) (*((c)++)=(unsigned char)(((l)>>56)&0xff), \ + *((c)++)=(unsigned char)(((l)>>48)&0xff), \ + *((c)++)=(unsigned char)(((l)>>40)&0xff), \ + *((c)++)=(unsigned char)(((l)>>32)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +/* NOTE - c is not incremented as per l2c */ +# define l2cn(l1,l2,c,n) { \ + c+=n; \ + switch (n) { \ + case 8: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \ + case 7: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \ + case 6: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \ + case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ + case 4: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \ + case 3: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \ + case 2: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \ + case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ + } \ + } + +# define n2s(c,s) ((s=(((unsigned int)((c)[0]))<< 8)| \ + (((unsigned int)((c)[1])) )),(c)+=2) +# define s2n(s,c) (((c)[0]=(unsigned char)(((s)>> 8)&0xff), \ + (c)[1]=(unsigned char)(((s) )&0xff)),(c)+=2) + +# define n2l3(c,l) ((l =(((unsigned long)((c)[0]))<<16)| \ + (((unsigned long)((c)[1]))<< 8)| \ + (((unsigned long)((c)[2])) )),(c)+=3) + +# define l2n3(l,c) (((c)[0]=(unsigned char)(((l)>>16)&0xff), \ + (c)[1]=(unsigned char)(((l)>> 8)&0xff), \ + (c)[2]=(unsigned char)(((l) )&0xff)),(c)+=3) + +/* + * DTLS version numbers are strange because they're inverted. Except for + * DTLS1_BAD_VER, which should be considered "lower" than the rest. + */ +# define dtls_ver_ordinal(v1) (((v1) == DTLS1_BAD_VER) ? 0xff00 : (v1)) +# define DTLS_VERSION_GT(v1, v2) (dtls_ver_ordinal(v1) < dtls_ver_ordinal(v2)) +# define DTLS_VERSION_GE(v1, v2) (dtls_ver_ordinal(v1) <= dtls_ver_ordinal(v2)) +# define DTLS_VERSION_LT(v1, v2) (dtls_ver_ordinal(v1) > dtls_ver_ordinal(v2)) +# define DTLS_VERSION_LE(v1, v2) (dtls_ver_ordinal(v1) >= dtls_ver_ordinal(v2)) + + +/* + * Define the Bitmasks for SSL_CIPHER.algorithms. + * This bits are used packed as dense as possible. If new methods/ciphers + * etc will be added, the bits a likely to change, so this information + * is for internal library use only, even though SSL_CIPHER.algorithms + * can be publicly accessed. + * Use the according functions for cipher management instead. + * + * The bit mask handling in the selection and sorting scheme in + * ssl_create_cipher_list() has only limited capabilities, reflecting + * that the different entities within are mutually exclusive: + * ONLY ONE BIT PER MASK CAN BE SET AT A TIME. + */ + +/* Bits for algorithm_mkey (key exchange algorithm) */ +/* RSA key exchange */ +# define SSL_kRSA 0x00000001U +/* tmp DH key no DH cert */ +# define SSL_kDHE 0x00000002U +/* synonym */ +# define SSL_kEDH SSL_kDHE +/* ephemeral ECDH */ +# define SSL_kECDHE 0x00000004U +/* synonym */ +# define SSL_kEECDH SSL_kECDHE +/* PSK */ +# define SSL_kPSK 0x00000008U +/* GOST key exchange */ +# define SSL_kGOST 0x00000010U +/* SRP */ +# define SSL_kSRP 0x00000020U + +# define SSL_kRSAPSK 0x00000040U +# define SSL_kECDHEPSK 0x00000080U +# define SSL_kDHEPSK 0x00000100U + +/* all PSK */ + +# define SSL_PSK (SSL_kPSK | SSL_kRSAPSK | SSL_kECDHEPSK | SSL_kDHEPSK) + +/* Any appropriate key exchange algorithm (for TLS 1.3 ciphersuites) */ +# define SSL_kANY 0x00000000U + +/* Bits for algorithm_auth (server authentication) */ +/* RSA auth */ +# define SSL_aRSA 0x00000001U +/* DSS auth */ +# define SSL_aDSS 0x00000002U +/* no auth (i.e. use ADH or AECDH) */ +# define SSL_aNULL 0x00000004U +/* ECDSA auth*/ +# define SSL_aECDSA 0x00000008U +/* PSK auth */ +# define SSL_aPSK 0x00000010U +/* GOST R 34.10-2001 signature auth */ +# define SSL_aGOST01 0x00000020U +/* SRP auth */ +# define SSL_aSRP 0x00000040U +/* GOST R 34.10-2012 signature auth */ +# define SSL_aGOST12 0x00000080U +/* Any appropriate signature auth (for TLS 1.3 ciphersuites) */ +# define SSL_aANY 0x00000000U +/* All bits requiring a certificate */ +#define SSL_aCERT \ + (SSL_aRSA | SSL_aDSS | SSL_aECDSA | SSL_aGOST01 | SSL_aGOST12) + +/* Bits for algorithm_enc (symmetric encryption) */ +# define SSL_DES 0x00000001U +# define SSL_3DES 0x00000002U +# define SSL_RC4 0x00000004U +# define SSL_RC2 0x00000008U +# define SSL_IDEA 0x00000010U +# define SSL_eNULL 0x00000020U +# define SSL_AES128 0x00000040U +# define SSL_AES256 0x00000080U +# define SSL_CAMELLIA128 0x00000100U +# define SSL_CAMELLIA256 0x00000200U +# define SSL_eGOST2814789CNT 0x00000400U +# define SSL_SEED 0x00000800U +# define SSL_AES128GCM 0x00001000U +# define SSL_AES256GCM 0x00002000U +# define SSL_AES128CCM 0x00004000U +# define SSL_AES256CCM 0x00008000U +# define SSL_AES128CCM8 0x00010000U +# define SSL_AES256CCM8 0x00020000U +# define SSL_eGOST2814789CNT12 0x00040000U +# define SSL_CHACHA20POLY1305 0x00080000U +# define SSL_ARIA128GCM 0x00100000U +# define SSL_ARIA256GCM 0x00200000U + +# define SSL_AESGCM (SSL_AES128GCM | SSL_AES256GCM) +# define SSL_AESCCM (SSL_AES128CCM | SSL_AES256CCM | SSL_AES128CCM8 | SSL_AES256CCM8) +# define SSL_AES (SSL_AES128|SSL_AES256|SSL_AESGCM|SSL_AESCCM) +# define SSL_CAMELLIA (SSL_CAMELLIA128|SSL_CAMELLIA256) +# define SSL_CHACHA20 (SSL_CHACHA20POLY1305) +# define SSL_ARIAGCM (SSL_ARIA128GCM | SSL_ARIA256GCM) +# define SSL_ARIA (SSL_ARIAGCM) + +/* Bits for algorithm_mac (symmetric authentication) */ + +# define SSL_MD5 0x00000001U +# define SSL_SHA1 0x00000002U +# define SSL_GOST94 0x00000004U +# define SSL_GOST89MAC 0x00000008U +# define SSL_SHA256 0x00000010U +# define SSL_SHA384 0x00000020U +/* Not a real MAC, just an indication it is part of cipher */ +# define SSL_AEAD 0x00000040U +# define SSL_GOST12_256 0x00000080U +# define SSL_GOST89MAC12 0x00000100U +# define SSL_GOST12_512 0x00000200U + +/* + * When adding new digest in the ssl_ciph.c and increment SSL_MD_NUM_IDX make + * sure to update this constant too + */ + +# define SSL_MD_MD5_IDX 0 +# define SSL_MD_SHA1_IDX 1 +# define SSL_MD_GOST94_IDX 2 +# define SSL_MD_GOST89MAC_IDX 3 +# define SSL_MD_SHA256_IDX 4 +# define SSL_MD_SHA384_IDX 5 +# define SSL_MD_GOST12_256_IDX 6 +# define SSL_MD_GOST89MAC12_IDX 7 +# define SSL_MD_GOST12_512_IDX 8 +# define SSL_MD_MD5_SHA1_IDX 9 +# define SSL_MD_SHA224_IDX 10 +# define SSL_MD_SHA512_IDX 11 +# define SSL_MAX_DIGEST 12 + +/* Bits for algorithm2 (handshake digests and other extra flags) */ + +/* Bits 0-7 are handshake MAC */ +# define SSL_HANDSHAKE_MAC_MASK 0xFF +# define SSL_HANDSHAKE_MAC_MD5_SHA1 SSL_MD_MD5_SHA1_IDX +# define SSL_HANDSHAKE_MAC_SHA256 SSL_MD_SHA256_IDX +# define SSL_HANDSHAKE_MAC_SHA384 SSL_MD_SHA384_IDX +# define SSL_HANDSHAKE_MAC_GOST94 SSL_MD_GOST94_IDX +# define SSL_HANDSHAKE_MAC_GOST12_256 SSL_MD_GOST12_256_IDX +# define SSL_HANDSHAKE_MAC_GOST12_512 SSL_MD_GOST12_512_IDX +# define SSL_HANDSHAKE_MAC_DEFAULT SSL_HANDSHAKE_MAC_MD5_SHA1 + +/* Bits 8-15 bits are PRF */ +# define TLS1_PRF_DGST_SHIFT 8 +# define TLS1_PRF_SHA1_MD5 (SSL_MD_MD5_SHA1_IDX << TLS1_PRF_DGST_SHIFT) +# define TLS1_PRF_SHA256 (SSL_MD_SHA256_IDX << TLS1_PRF_DGST_SHIFT) +# define TLS1_PRF_SHA384 (SSL_MD_SHA384_IDX << TLS1_PRF_DGST_SHIFT) +# define TLS1_PRF_GOST94 (SSL_MD_GOST94_IDX << TLS1_PRF_DGST_SHIFT) +# define TLS1_PRF_GOST12_256 (SSL_MD_GOST12_256_IDX << TLS1_PRF_DGST_SHIFT) +# define TLS1_PRF_GOST12_512 (SSL_MD_GOST12_512_IDX << TLS1_PRF_DGST_SHIFT) +# define TLS1_PRF (SSL_MD_MD5_SHA1_IDX << TLS1_PRF_DGST_SHIFT) + +/* + * Stream MAC for GOST ciphersuites from cryptopro draft (currently this also + * goes into algorithm2) + */ +# define TLS1_STREAM_MAC 0x10000 + +# define SSL_STRONG_MASK 0x0000001FU +# define SSL_DEFAULT_MASK 0X00000020U + +# define SSL_STRONG_NONE 0x00000001U +# define SSL_LOW 0x00000002U +# define SSL_MEDIUM 0x00000004U +# define SSL_HIGH 0x00000008U +# define SSL_FIPS 0x00000010U +# define SSL_NOT_DEFAULT 0x00000020U + +/* we have used 0000003f - 26 bits left to go */ + +/* Flag used on OpenSSL ciphersuite ids to indicate they are for SSLv3+ */ +# define SSL3_CK_CIPHERSUITE_FLAG 0x03000000 + +/* Check if an SSL structure is using DTLS */ +# define SSL_IS_DTLS(s) (s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_DTLS) + +/* Check if we are using TLSv1.3 */ +# define SSL_IS_TLS13(s) (!SSL_IS_DTLS(s) \ + && (s)->method->version >= TLS1_3_VERSION \ + && (s)->method->version != TLS_ANY_VERSION) + +# define SSL_TREAT_AS_TLS13(s) \ + (SSL_IS_TLS13(s) || (s)->early_data_state == SSL_EARLY_DATA_CONNECTING \ + || (s)->early_data_state == SSL_EARLY_DATA_CONNECT_RETRY \ + || (s)->early_data_state == SSL_EARLY_DATA_WRITING \ + || (s)->early_data_state == SSL_EARLY_DATA_WRITE_RETRY \ + || (s)->hello_retry_request == SSL_HRR_PENDING) + +# define SSL_IS_FIRST_HANDSHAKE(S) ((s)->s3->tmp.finish_md_len == 0 \ + || (s)->s3->tmp.peer_finish_md_len == 0) + +/* See if we need explicit IV */ +# define SSL_USE_EXPLICIT_IV(s) \ + (s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_EXPLICIT_IV) +/* + * See if we use signature algorithms extension and signature algorithm + * before signatures. + */ +# define SSL_USE_SIGALGS(s) \ + (s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_SIGALGS) +/* + * Allow TLS 1.2 ciphersuites: applies to DTLS 1.2 as well as TLS 1.2: may + * apply to others in future. + */ +# define SSL_USE_TLS1_2_CIPHERS(s) \ + (s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_TLS1_2_CIPHERS) +/* + * Determine if a client can use TLS 1.2 ciphersuites: can't rely on method + * flags because it may not be set to correct version yet. + */ +# define SSL_CLIENT_USE_TLS1_2_CIPHERS(s) \ + ((!SSL_IS_DTLS(s) && s->client_version >= TLS1_2_VERSION) || \ + (SSL_IS_DTLS(s) && DTLS_VERSION_GE(s->client_version, DTLS1_2_VERSION))) +/* + * Determine if a client should send signature algorithms extension: + * as with TLS1.2 cipher we can't rely on method flags. + */ +# define SSL_CLIENT_USE_SIGALGS(s) \ + SSL_CLIENT_USE_TLS1_2_CIPHERS(s) + +# define IS_MAX_FRAGMENT_LENGTH_EXT_VALID(value) \ + (((value) >= TLSEXT_max_fragment_length_512) && \ + ((value) <= TLSEXT_max_fragment_length_4096)) +# define USE_MAX_FRAGMENT_LENGTH_EXT(session) \ + IS_MAX_FRAGMENT_LENGTH_EXT_VALID(session->ext.max_fragment_len_mode) +# define GET_MAX_FRAGMENT_LENGTH(session) \ + (512U << (session->ext.max_fragment_len_mode - 1)) + +# define SSL_READ_ETM(s) (s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC_READ) +# define SSL_WRITE_ETM(s) (s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC_WRITE) + +/* Mostly for SSLv3 */ +# define SSL_PKEY_RSA 0 +# define SSL_PKEY_RSA_PSS_SIGN 1 +# define SSL_PKEY_DSA_SIGN 2 +# define SSL_PKEY_ECC 3 +# define SSL_PKEY_GOST01 4 +# define SSL_PKEY_GOST12_256 5 +# define SSL_PKEY_GOST12_512 6 +# define SSL_PKEY_ED25519 7 +# define SSL_PKEY_ED448 8 +# define SSL_PKEY_NUM 9 + +/*- + * SSL_kRSA <- RSA_ENC + * SSL_kDH <- DH_ENC & (RSA_ENC | RSA_SIGN | DSA_SIGN) + * SSL_kDHE <- RSA_ENC | RSA_SIGN | DSA_SIGN + * SSL_aRSA <- RSA_ENC | RSA_SIGN + * SSL_aDSS <- DSA_SIGN + */ + +/*- +#define CERT_INVALID 0 +#define CERT_PUBLIC_KEY 1 +#define CERT_PRIVATE_KEY 2 +*/ + +/* Post-Handshake Authentication state */ +typedef enum { + SSL_PHA_NONE = 0, + SSL_PHA_EXT_SENT, /* client-side only: extension sent */ + SSL_PHA_EXT_RECEIVED, /* server-side only: extension received */ + SSL_PHA_REQUEST_PENDING, /* server-side only: request pending */ + SSL_PHA_REQUESTED /* request received by client, or sent by server */ +} SSL_PHA_STATE; + +/* CipherSuite length. SSLv3 and all TLS versions. */ +# define TLS_CIPHER_LEN 2 +/* used to hold info on the particular ciphers used */ +struct ssl_cipher_st { + uint32_t valid; + const char *name; /* text name */ + const char *stdname; /* RFC name */ + uint32_t id; /* id, 4 bytes, first is version */ + /* + * changed in 1.0.0: these four used to be portions of a single value + * 'algorithms' + */ + uint32_t algorithm_mkey; /* key exchange algorithm */ + uint32_t algorithm_auth; /* server authentication */ + uint32_t algorithm_enc; /* symmetric encryption */ + uint32_t algorithm_mac; /* symmetric authentication */ + int min_tls; /* minimum SSL/TLS protocol version */ + int max_tls; /* maximum SSL/TLS protocol version */ + int min_dtls; /* minimum DTLS protocol version */ + int max_dtls; /* maximum DTLS protocol version */ + uint32_t algo_strength; /* strength and export flags */ + uint32_t algorithm2; /* Extra flags */ + int32_t strength_bits; /* Number of bits really used */ + uint32_t alg_bits; /* Number of bits for algorithm */ +}; + +/* Used to hold SSL/TLS functions */ +struct ssl_method_st { + int version; + unsigned flags; + unsigned long mask; + int (*ssl_new) (SSL *s); + int (*ssl_clear) (SSL *s); + void (*ssl_free) (SSL *s); + int (*ssl_accept) (SSL *s); + int (*ssl_connect) (SSL *s); + int (*ssl_read) (SSL *s, void *buf, size_t len, size_t *readbytes); + int (*ssl_peek) (SSL *s, void *buf, size_t len, size_t *readbytes); + int (*ssl_write) (SSL *s, const void *buf, size_t len, size_t *written); + int (*ssl_shutdown) (SSL *s); + int (*ssl_renegotiate) (SSL *s); + int (*ssl_renegotiate_check) (SSL *s, int); + int (*ssl_read_bytes) (SSL *s, int type, int *recvd_type, + unsigned char *buf, size_t len, int peek, + size_t *readbytes); + int (*ssl_write_bytes) (SSL *s, int type, const void *buf_, size_t len, + size_t *written); + int (*ssl_dispatch_alert) (SSL *s); + long (*ssl_ctrl) (SSL *s, int cmd, long larg, void *parg); + long (*ssl_ctx_ctrl) (SSL_CTX *ctx, int cmd, long larg, void *parg); + const SSL_CIPHER *(*get_cipher_by_char) (const unsigned char *ptr); + int (*put_cipher_by_char) (const SSL_CIPHER *cipher, WPACKET *pkt, + size_t *len); + size_t (*ssl_pending) (const SSL *s); + int (*num_ciphers) (void); + const SSL_CIPHER *(*get_cipher) (unsigned ncipher); + long (*get_timeout) (void); + const struct ssl3_enc_method *ssl3_enc; /* Extra SSLv3/TLS stuff */ + int (*ssl_version) (void); + long (*ssl_callback_ctrl) (SSL *s, int cb_id, void (*fp) (void)); + long (*ssl_ctx_callback_ctrl) (SSL_CTX *s, int cb_id, void (*fp) (void)); +}; + +/* + * Matches the length of PSK_MAX_PSK_LEN. We keep it the same value for + * consistency, even in the event of OPENSSL_NO_PSK being defined. + */ +# define TLS13_MAX_RESUMPTION_PSK_LENGTH 256 + +/*- + * Lets make this into an ASN.1 type structure as follows + * SSL_SESSION_ID ::= SEQUENCE { + * version INTEGER, -- structure version number + * SSLversion INTEGER, -- SSL version number + * Cipher OCTET STRING, -- the 3 byte cipher ID + * Session_ID OCTET STRING, -- the Session ID + * Master_key OCTET STRING, -- the master key + * Key_Arg [ 0 ] IMPLICIT OCTET STRING, -- the optional Key argument + * Time [ 1 ] EXPLICIT INTEGER, -- optional Start Time + * Timeout [ 2 ] EXPLICIT INTEGER, -- optional Timeout ins seconds + * Peer [ 3 ] EXPLICIT X509, -- optional Peer Certificate + * Session_ID_context [ 4 ] EXPLICIT OCTET STRING, -- the Session ID context + * Verify_result [ 5 ] EXPLICIT INTEGER, -- X509_V_... code for `Peer' + * HostName [ 6 ] EXPLICIT OCTET STRING, -- optional HostName from servername TLS extension + * PSK_identity_hint [ 7 ] EXPLICIT OCTET STRING, -- optional PSK identity hint + * PSK_identity [ 8 ] EXPLICIT OCTET STRING, -- optional PSK identity + * Ticket_lifetime_hint [9] EXPLICIT INTEGER, -- server's lifetime hint for session ticket + * Ticket [10] EXPLICIT OCTET STRING, -- session ticket (clients only) + * Compression_meth [11] EXPLICIT OCTET STRING, -- optional compression method + * SRP_username [ 12 ] EXPLICIT OCTET STRING -- optional SRP username + * flags [ 13 ] EXPLICIT INTEGER -- optional flags + * } + * Look in ssl/ssl_asn1.c for more details + * I'm using EXPLICIT tags so I can read the damn things using asn1parse :-). + */ +struct ssl_session_st { + int ssl_version; /* what ssl version session info is being kept + * in here? */ + size_t master_key_length; + + /* TLSv1.3 early_secret used for external PSKs */ + unsigned char early_secret[EVP_MAX_MD_SIZE]; + /* + * For <=TLS1.2 this is the master_key. For TLS1.3 this is the resumption + * PSK + */ + unsigned char master_key[TLS13_MAX_RESUMPTION_PSK_LENGTH]; + /* session_id - valid? */ + size_t session_id_length; + unsigned char session_id[SSL_MAX_SSL_SESSION_ID_LENGTH]; + /* + * this is used to determine whether the session is being reused in the + * appropriate context. It is up to the application to set this, via + * SSL_new + */ + size_t sid_ctx_length; + unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH]; +# ifndef OPENSSL_NO_PSK + char *psk_identity_hint; + char *psk_identity; +# endif + /* + * Used to indicate that session resumption is not allowed. Applications + * can also set this bit for a new session via not_resumable_session_cb + * to disable session caching and tickets. + */ + int not_resumable; + /* This is the cert and type for the other end. */ + X509 *peer; + int peer_type; + /* Certificate chain peer sent. */ + STACK_OF(X509) *peer_chain; + /* + * when app_verify_callback accepts a session where the peer's + * certificate is not ok, we must remember the error for session reuse: + */ + long verify_result; /* only for servers */ + CRYPTO_REF_COUNT references; + long timeout; + long time; + unsigned int compress_meth; /* Need to lookup the method */ + const SSL_CIPHER *cipher; + unsigned long cipher_id; /* when ASN.1 loaded, this needs to be used to + * load the 'cipher' structure */ + STACK_OF(SSL_CIPHER) *ciphers; /* ciphers offered by the client */ + CRYPTO_EX_DATA ex_data; /* application specific data */ + /* + * These are used to make removal of session-ids more efficient and to + * implement a maximum cache size. + */ + struct ssl_session_st *prev, *next; + + struct { + char *hostname; +# ifndef OPENSSL_NO_EC + size_t ecpointformats_len; + unsigned char *ecpointformats; /* peer's list */ +# endif /* OPENSSL_NO_EC */ + size_t supportedgroups_len; + uint16_t *supportedgroups; /* peer's list */ + /* RFC4507 info */ + unsigned char *tick; /* Session ticket */ + size_t ticklen; /* Session ticket length */ + /* Session lifetime hint in seconds */ + unsigned long tick_lifetime_hint; + uint32_t tick_age_add; + int tick_identity; + /* Max number of bytes that can be sent as early data */ + uint32_t max_early_data; + /* The ALPN protocol selected for this session */ + unsigned char *alpn_selected; + size_t alpn_selected_len; + /* + * Maximum Fragment Length as per RFC 4366. + * If this value does not contain RFC 4366 allowed values (1-4) then + * either the Maximum Fragment Length Negotiation failed or was not + * performed at all. + */ + uint8_t max_fragment_len_mode; + } ext; +# ifndef OPENSSL_NO_SRP + char *srp_username; +# endif + unsigned char *ticket_appdata; + size_t ticket_appdata_len; + uint32_t flags; + CRYPTO_RWLOCK *lock; +}; + +/* Extended master secret support */ +# define SSL_SESS_FLAG_EXTMS 0x1 + +# ifndef OPENSSL_NO_SRP + +typedef struct srp_ctx_st { + /* param for all the callbacks */ + void *SRP_cb_arg; + /* set client Hello login callback */ + int (*TLS_ext_srp_username_callback) (SSL *, int *, void *); + /* set SRP N/g param callback for verification */ + int (*SRP_verify_param_callback) (SSL *, void *); + /* set SRP client passwd callback */ + char *(*SRP_give_srp_client_pwd_callback) (SSL *, void *); + char *login; + BIGNUM *N, *g, *s, *B, *A; + BIGNUM *a, *b, *v; + char *info; + int strength; + unsigned long srp_Mask; +} SRP_CTX; + +# endif + +typedef enum { + SSL_EARLY_DATA_NONE = 0, + SSL_EARLY_DATA_CONNECT_RETRY, + SSL_EARLY_DATA_CONNECTING, + SSL_EARLY_DATA_WRITE_RETRY, + SSL_EARLY_DATA_WRITING, + SSL_EARLY_DATA_WRITE_FLUSH, + SSL_EARLY_DATA_UNAUTH_WRITING, + SSL_EARLY_DATA_FINISHED_WRITING, + SSL_EARLY_DATA_ACCEPT_RETRY, + SSL_EARLY_DATA_ACCEPTING, + SSL_EARLY_DATA_READ_RETRY, + SSL_EARLY_DATA_READING, + SSL_EARLY_DATA_FINISHED_READING +} SSL_EARLY_DATA_STATE; + +/* + * We check that the amount of unreadable early data doesn't exceed + * max_early_data. max_early_data is given in plaintext bytes. However if it is + * unreadable then we only know the number of ciphertext bytes. We also don't + * know how much the overhead should be because it depends on the ciphersuite. + * We make a small allowance. We assume 5 records of actual data plus the end + * of early data alert record. Each record has a tag and a content type byte. + * The longest tag length we know of is EVP_GCM_TLS_TAG_LEN. We don't count the + * content of the alert record either which is 2 bytes. + */ +# define EARLY_DATA_CIPHERTEXT_OVERHEAD ((6 * (EVP_GCM_TLS_TAG_LEN + 1)) + 2) + +/* + * The allowance we have between the client's calculated ticket age and our own. + * We allow for 10 seconds (units are in ms). If a ticket is presented and the + * client's age calculation is different by more than this than our own then we + * do not allow that ticket for early_data. + */ +# define TICKET_AGE_ALLOWANCE (10 * 1000) + +#define MAX_COMPRESSIONS_SIZE 255 + +struct ssl_comp_st { + int id; + const char *name; + COMP_METHOD *method; +}; + +typedef struct raw_extension_st { + /* Raw packet data for the extension */ + PACKET data; + /* Set to 1 if the extension is present or 0 otherwise */ + int present; + /* Set to 1 if we have already parsed the extension or 0 otherwise */ + int parsed; + /* The type of this extension, i.e. a TLSEXT_TYPE_* value */ + unsigned int type; + /* Track what order extensions are received in (0-based). */ + size_t received_order; +} RAW_EXTENSION; + +typedef struct { + unsigned int isv2; + unsigned int legacy_version; + unsigned char random[SSL3_RANDOM_SIZE]; + size_t session_id_len; + unsigned char session_id[SSL_MAX_SSL_SESSION_ID_LENGTH]; + size_t dtls_cookie_len; + unsigned char dtls_cookie[DTLS1_COOKIE_LENGTH]; + PACKET ciphersuites; + size_t compressions_len; + unsigned char compressions[MAX_COMPRESSIONS_SIZE]; + PACKET extensions; + size_t pre_proc_exts_len; + RAW_EXTENSION *pre_proc_exts; +} CLIENTHELLO_MSG; + +/* + * Extension index values NOTE: Any updates to these defines should be mirrored + * with equivalent updates to ext_defs in extensions.c + */ +typedef enum tlsext_index_en { + TLSEXT_IDX_renegotiate, + TLSEXT_IDX_server_name, + TLSEXT_IDX_max_fragment_length, + TLSEXT_IDX_srp, + TLSEXT_IDX_ec_point_formats, + TLSEXT_IDX_supported_groups, + TLSEXT_IDX_session_ticket, + TLSEXT_IDX_status_request, + TLSEXT_IDX_next_proto_neg, + TLSEXT_IDX_application_layer_protocol_negotiation, + TLSEXT_IDX_use_srtp, + TLSEXT_IDX_encrypt_then_mac, + TLSEXT_IDX_signed_certificate_timestamp, + TLSEXT_IDX_extended_master_secret, + TLSEXT_IDX_signature_algorithms_cert, + TLSEXT_IDX_post_handshake_auth, + TLSEXT_IDX_signature_algorithms, + TLSEXT_IDX_supported_versions, + TLSEXT_IDX_psk_kex_modes, + TLSEXT_IDX_key_share, + TLSEXT_IDX_cookie, + TLSEXT_IDX_cryptopro_bug, + TLSEXT_IDX_early_data, + TLSEXT_IDX_certificate_authorities, + TLSEXT_IDX_padding, + TLSEXT_IDX_psk, + /* Dummy index - must always be the last entry */ + TLSEXT_IDX_num_builtins +} TLSEXT_INDEX; + +DEFINE_LHASH_OF(SSL_SESSION); +/* Needed in ssl_cert.c */ +DEFINE_LHASH_OF(X509_NAME); + +# define TLSEXT_KEYNAME_LENGTH 16 +# define TLSEXT_TICK_KEY_LENGTH 32 + +typedef struct ssl_ctx_ext_secure_st { + unsigned char tick_hmac_key[TLSEXT_TICK_KEY_LENGTH]; + unsigned char tick_aes_key[TLSEXT_TICK_KEY_LENGTH]; +} SSL_CTX_EXT_SECURE; + +struct ssl_ctx_st { + const SSL_METHOD *method; + STACK_OF(SSL_CIPHER) *cipher_list; + /* same as above but sorted for lookup */ + STACK_OF(SSL_CIPHER) *cipher_list_by_id; + /* TLSv1.3 specific ciphersuites */ + STACK_OF(SSL_CIPHER) *tls13_ciphersuites; + struct x509_store_st /* X509_STORE */ *cert_store; + LHASH_OF(SSL_SESSION) *sessions; + /* + * Most session-ids that will be cached, default is + * SSL_SESSION_CACHE_MAX_SIZE_DEFAULT. 0 is unlimited. + */ + size_t session_cache_size; + struct ssl_session_st *session_cache_head; + struct ssl_session_st *session_cache_tail; + /* + * This can have one of 2 values, ored together, SSL_SESS_CACHE_CLIENT, + * SSL_SESS_CACHE_SERVER, Default is SSL_SESSION_CACHE_SERVER, which + * means only SSL_accept will cache SSL_SESSIONS. + */ + uint32_t session_cache_mode; + /* + * If timeout is not 0, it is the default timeout value set when + * SSL_new() is called. This has been put in to make life easier to set + * things up + */ + long session_timeout; + /* + * If this callback is not null, it will be called each time a session id + * is added to the cache. If this function returns 1, it means that the + * callback will do a SSL_SESSION_free() when it has finished using it. + * Otherwise, on 0, it means the callback has finished with it. If + * remove_session_cb is not null, it will be called when a session-id is + * removed from the cache. After the call, OpenSSL will + * SSL_SESSION_free() it. + */ + int (*new_session_cb) (struct ssl_st *ssl, SSL_SESSION *sess); + void (*remove_session_cb) (struct ssl_ctx_st *ctx, SSL_SESSION *sess); + SSL_SESSION *(*get_session_cb) (struct ssl_st *ssl, + const unsigned char *data, int len, + int *copy); + struct { + TSAN_QUALIFIER int sess_connect; /* SSL new conn - started */ + TSAN_QUALIFIER int sess_connect_renegotiate; /* SSL reneg - requested */ + TSAN_QUALIFIER int sess_connect_good; /* SSL new conne/reneg - finished */ + TSAN_QUALIFIER int sess_accept; /* SSL new accept - started */ + TSAN_QUALIFIER int sess_accept_renegotiate; /* SSL reneg - requested */ + TSAN_QUALIFIER int sess_accept_good; /* SSL accept/reneg - finished */ + TSAN_QUALIFIER int sess_miss; /* session lookup misses */ + TSAN_QUALIFIER int sess_timeout; /* reuse attempt on timeouted session */ + TSAN_QUALIFIER int sess_cache_full; /* session removed due to full cache */ + TSAN_QUALIFIER int sess_hit; /* session reuse actually done */ + TSAN_QUALIFIER int sess_cb_hit; /* session-id that was not in + * the cache was passed back via + * the callback. This indicates + * that the application is + * supplying session-id's from + * other processes - spooky + * :-) */ + } stats; + + CRYPTO_REF_COUNT references; + + /* if defined, these override the X509_verify_cert() calls */ + int (*app_verify_callback) (X509_STORE_CTX *, void *); + void *app_verify_arg; + /* + * before OpenSSL 0.9.7, 'app_verify_arg' was ignored + * ('app_verify_callback' was called with just one argument) + */ + + /* Default password callback. */ + pem_password_cb *default_passwd_callback; + + /* Default password callback user data. */ + void *default_passwd_callback_userdata; + + /* get client cert callback */ + int (*client_cert_cb) (SSL *ssl, X509 **x509, EVP_PKEY **pkey); + + /* cookie generate callback */ + int (*app_gen_cookie_cb) (SSL *ssl, unsigned char *cookie, + unsigned int *cookie_len); + + /* verify cookie callback */ + int (*app_verify_cookie_cb) (SSL *ssl, const unsigned char *cookie, + unsigned int cookie_len); + + /* TLS1.3 app-controlled cookie generate callback */ + int (*gen_stateless_cookie_cb) (SSL *ssl, unsigned char *cookie, + size_t *cookie_len); + + /* TLS1.3 verify app-controlled cookie callback */ + int (*verify_stateless_cookie_cb) (SSL *ssl, const unsigned char *cookie, + size_t cookie_len); + + CRYPTO_EX_DATA ex_data; + + const EVP_MD *md5; /* For SSLv3/TLSv1 'ssl3-md5' */ + const EVP_MD *sha1; /* For SSLv3/TLSv1 'ssl3->sha1' */ + + STACK_OF(X509) *extra_certs; + STACK_OF(SSL_COMP) *comp_methods; /* stack of SSL_COMP, SSLv3/TLSv1 */ + + /* Default values used when no per-SSL value is defined follow */ + + /* used if SSL's info_callback is NULL */ + void (*info_callback) (const SSL *ssl, int type, int val); + + /* + * What we put in certificate_authorities extension for TLS 1.3 + * (ClientHello and CertificateRequest) or just client cert requests for + * earlier versions. If client_ca_names is populated then it is only used + * for client cert requests, and in preference to ca_names. + */ + STACK_OF(X509_NAME) *ca_names; + STACK_OF(X509_NAME) *client_ca_names; + + /* + * Default values to use in SSL structures follow (these are copied by + * SSL_new) + */ + + uint32_t options; + uint32_t mode; + int min_proto_version; + int max_proto_version; + size_t max_cert_list; + + struct cert_st /* CERT */ *cert; + int read_ahead; + + /* callback that allows applications to peek at protocol messages */ + void (*msg_callback) (int write_p, int version, int content_type, + const void *buf, size_t len, SSL *ssl, void *arg); + void *msg_callback_arg; + + uint32_t verify_mode; + size_t sid_ctx_length; + unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH]; + /* called 'verify_callback' in the SSL */ + int (*default_verify_callback) (int ok, X509_STORE_CTX *ctx); + + /* Default generate session ID callback. */ + GEN_SESSION_CB generate_session_id; + + X509_VERIFY_PARAM *param; + + int quiet_shutdown; + +# ifndef OPENSSL_NO_CT + CTLOG_STORE *ctlog_store; /* CT Log Store */ + /* + * Validates that the SCTs (Signed Certificate Timestamps) are sufficient. + * If they are not, the connection should be aborted. + */ + ssl_ct_validation_cb ct_validation_callback; + void *ct_validation_callback_arg; +# endif + + /* + * If we're using more than one pipeline how should we divide the data + * up between the pipes? + */ + size_t split_send_fragment; + /* + * Maximum amount of data to send in one fragment. actual record size can + * be more than this due to padding and MAC overheads. + */ + size_t max_send_fragment; + + /* Up to how many pipelines should we use? If 0 then 1 is assumed */ + size_t max_pipelines; + + /* The default read buffer length to use (0 means not set) */ + size_t default_read_buf_len; + +# ifndef OPENSSL_NO_ENGINE + /* + * Engine to pass requests for client certs to + */ + ENGINE *client_cert_engine; +# endif + + /* ClientHello callback. Mostly for extensions, but not entirely. */ + SSL_client_hello_cb_fn client_hello_cb; + void *client_hello_cb_arg; + + /* TLS extensions. */ + struct { + /* TLS extensions servername callback */ + int (*servername_cb) (SSL *, int *, void *); + void *servername_arg; + /* RFC 4507 session ticket keys */ + unsigned char tick_key_name[TLSEXT_KEYNAME_LENGTH]; + SSL_CTX_EXT_SECURE *secure; + /* Callback to support customisation of ticket key setting */ + int (*ticket_key_cb) (SSL *ssl, + unsigned char *name, unsigned char *iv, + EVP_CIPHER_CTX *ectx, HMAC_CTX *hctx, int enc); + + /* certificate status request info */ + /* Callback for status request */ + int (*status_cb) (SSL *ssl, void *arg); + void *status_arg; + /* ext status type used for CSR extension (OCSP Stapling) */ + int status_type; + /* RFC 4366 Maximum Fragment Length Negotiation */ + uint8_t max_fragment_len_mode; + +# ifndef OPENSSL_NO_EC + /* EC extension values inherited by SSL structure */ + size_t ecpointformats_len; + unsigned char *ecpointformats; + size_t supportedgroups_len; + uint16_t *supportedgroups; +# endif /* OPENSSL_NO_EC */ + + /* + * ALPN information (we are in the process of transitioning from NPN to + * ALPN.) + */ + + /*- + * For a server, this contains a callback function that allows the + * server to select the protocol for the connection. + * out: on successful return, this must point to the raw protocol + * name (without the length prefix). + * outlen: on successful return, this contains the length of |*out|. + * in: points to the client's list of supported protocols in + * wire-format. + * inlen: the length of |in|. + */ + int (*alpn_select_cb) (SSL *s, + const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, void *arg); + void *alpn_select_cb_arg; + + /* + * For a client, this contains the list of supported protocols in wire + * format. + */ + unsigned char *alpn; + size_t alpn_len; + +# ifndef OPENSSL_NO_NEXTPROTONEG + /* Next protocol negotiation information */ + + /* + * For a server, this contains a callback function by which the set of + * advertised protocols can be provided. + */ + SSL_CTX_npn_advertised_cb_func npn_advertised_cb; + void *npn_advertised_cb_arg; + /* + * For a client, this contains a callback function that selects the next + * protocol from the list provided by the server. + */ + SSL_CTX_npn_select_cb_func npn_select_cb; + void *npn_select_cb_arg; +# endif + + unsigned char cookie_hmac_key[SHA256_DIGEST_LENGTH]; + } ext; + +# ifndef OPENSSL_NO_PSK + SSL_psk_client_cb_func psk_client_callback; + SSL_psk_server_cb_func psk_server_callback; +# endif + SSL_psk_find_session_cb_func psk_find_session_cb; + SSL_psk_use_session_cb_func psk_use_session_cb; + +# ifndef OPENSSL_NO_SRP + SRP_CTX srp_ctx; /* ctx for SRP authentication */ +# endif + + /* Shared DANE context */ + struct dane_ctx_st dane; + +# ifndef OPENSSL_NO_SRTP + /* SRTP profiles we are willing to do from RFC 5764 */ + STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles; +# endif + /* + * Callback for disabling session caching and ticket support on a session + * basis, depending on the chosen cipher. + */ + int (*not_resumable_session_cb) (SSL *ssl, int is_forward_secure); + + CRYPTO_RWLOCK *lock; + + /* + * Callback for logging key material for use with debugging tools like + * Wireshark. The callback should log `line` followed by a newline. + */ + SSL_CTX_keylog_cb_func keylog_callback; + + /* + * The maximum number of bytes advertised in session tickets that can be + * sent as early data. + */ + uint32_t max_early_data; + + /* + * The maximum number of bytes of early data that a server will tolerate + * (which should be at least as much as max_early_data). + */ + uint32_t recv_max_early_data; + + /* TLS1.3 padding callback */ + size_t (*record_padding_cb)(SSL *s, int type, size_t len, void *arg); + void *record_padding_arg; + size_t block_padding; + + /* Session ticket appdata */ + SSL_CTX_generate_session_ticket_fn generate_ticket_cb; + SSL_CTX_decrypt_session_ticket_fn decrypt_ticket_cb; + void *ticket_cb_data; + + /* The number of TLS1.3 tickets to automatically send */ + size_t num_tickets; + + /* Callback to determine if early_data is acceptable or not */ + SSL_allow_early_data_cb_fn allow_early_data_cb; + void *allow_early_data_cb_data; + + /* Do we advertise Post-handshake auth support? */ + int pha_enabled; +}; + +struct ssl_st { + /* + * protocol version (one of SSL2_VERSION, SSL3_VERSION, TLS1_VERSION, + * DTLS1_VERSION) + */ + int version; + /* SSLv3 */ + const SSL_METHOD *method; + /* + * There are 2 BIO's even though they are normally both the same. This + * is so data can be read and written to different handlers + */ + /* used by SSL_read */ + BIO *rbio; + /* used by SSL_write */ + BIO *wbio; + /* used during session-id reuse to concatenate messages */ + BIO *bbio; + /* + * This holds a variable that indicates what we were doing when a 0 or -1 + * is returned. This is needed for non-blocking IO so we know what + * request needs re-doing when in SSL_accept or SSL_connect + */ + int rwstate; + int (*handshake_func) (SSL *); + /* + * Imagine that here's a boolean member "init" that is switched as soon + * as SSL_set_{accept/connect}_state is called for the first time, so + * that "state" and "handshake_func" are properly initialized. But as + * handshake_func is == 0 until then, we use this test instead of an + * "init" member. + */ + /* are we the server side? */ + int server; + /* + * Generate a new session or reuse an old one. + * NB: For servers, the 'new' session may actually be a previously + * cached session or even the previous session unless + * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set + */ + int new_session; + /* don't send shutdown packets */ + int quiet_shutdown; + /* we have shut things down, 0x01 sent, 0x02 for received */ + int shutdown; + /* where we are */ + OSSL_STATEM statem; + SSL_EARLY_DATA_STATE early_data_state; + BUF_MEM *init_buf; /* buffer used during init */ + void *init_msg; /* pointer to handshake message body, set by + * ssl3_get_message() */ + size_t init_num; /* amount read/written */ + size_t init_off; /* amount read/written */ + struct ssl3_state_st *s3; /* SSLv3 variables */ + struct dtls1_state_st *d1; /* DTLSv1 variables */ + /* callback that allows applications to peek at protocol messages */ + void (*msg_callback) (int write_p, int version, int content_type, + const void *buf, size_t len, SSL *ssl, void *arg); + void *msg_callback_arg; + int hit; /* reusing a previous session */ + X509_VERIFY_PARAM *param; + /* Per connection DANE state */ + SSL_DANE dane; + /* crypto */ + STACK_OF(SSL_CIPHER) *cipher_list; + STACK_OF(SSL_CIPHER) *cipher_list_by_id; + /* TLSv1.3 specific ciphersuites */ + STACK_OF(SSL_CIPHER) *tls13_ciphersuites; + /* + * These are the ones being used, the ones in SSL_SESSION are the ones to + * be 'copied' into these ones + */ + uint32_t mac_flags; + /* + * The TLS1.3 secrets. + */ + unsigned char early_secret[EVP_MAX_MD_SIZE]; + unsigned char handshake_secret[EVP_MAX_MD_SIZE]; + unsigned char master_secret[EVP_MAX_MD_SIZE]; + unsigned char resumption_master_secret[EVP_MAX_MD_SIZE]; + unsigned char client_finished_secret[EVP_MAX_MD_SIZE]; + unsigned char server_finished_secret[EVP_MAX_MD_SIZE]; + unsigned char server_finished_hash[EVP_MAX_MD_SIZE]; + unsigned char handshake_traffic_hash[EVP_MAX_MD_SIZE]; + unsigned char client_app_traffic_secret[EVP_MAX_MD_SIZE]; + unsigned char server_app_traffic_secret[EVP_MAX_MD_SIZE]; + unsigned char exporter_master_secret[EVP_MAX_MD_SIZE]; + unsigned char early_exporter_master_secret[EVP_MAX_MD_SIZE]; + EVP_CIPHER_CTX *enc_read_ctx; /* cryptographic state */ + unsigned char read_iv[EVP_MAX_IV_LENGTH]; /* TLSv1.3 static read IV */ + EVP_MD_CTX *read_hash; /* used for mac generation */ + COMP_CTX *compress; /* compression */ + COMP_CTX *expand; /* uncompress */ + EVP_CIPHER_CTX *enc_write_ctx; /* cryptographic state */ + unsigned char write_iv[EVP_MAX_IV_LENGTH]; /* TLSv1.3 static write IV */ + EVP_MD_CTX *write_hash; /* used for mac generation */ + /* session info */ + /* client cert? */ + /* This is used to hold the server certificate used */ + struct cert_st /* CERT */ *cert; + + /* + * The hash of all messages prior to the CertificateVerify, and the length + * of that hash. + */ + unsigned char cert_verify_hash[EVP_MAX_MD_SIZE]; + size_t cert_verify_hash_len; + + /* Flag to indicate whether we should send a HelloRetryRequest or not */ + enum {SSL_HRR_NONE = 0, SSL_HRR_PENDING, SSL_HRR_COMPLETE} + hello_retry_request; + + /* + * the session_id_context is used to ensure sessions are only reused in + * the appropriate context + */ + size_t sid_ctx_length; + unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH]; + /* This can also be in the session once a session is established */ + SSL_SESSION *session; + /* TLSv1.3 PSK session */ + SSL_SESSION *psksession; + unsigned char *psksession_id; + size_t psksession_id_len; + /* Default generate session ID callback. */ + GEN_SESSION_CB generate_session_id; + /* + * The temporary TLSv1.3 session id. This isn't really a session id at all + * but is a random value sent in the legacy session id field. + */ + unsigned char tmp_session_id[SSL_MAX_SSL_SESSION_ID_LENGTH]; + size_t tmp_session_id_len; + /* Used in SSL3 */ + /* + * 0 don't care about verify failure. + * 1 fail if verify fails + */ + uint32_t verify_mode; + /* fail if callback returns 0 */ + int (*verify_callback) (int ok, X509_STORE_CTX *ctx); + /* optional informational callback */ + void (*info_callback) (const SSL *ssl, int type, int val); + /* error bytes to be written */ + int error; + /* actual code */ + int error_code; +# ifndef OPENSSL_NO_PSK + SSL_psk_client_cb_func psk_client_callback; + SSL_psk_server_cb_func psk_server_callback; +# endif + SSL_psk_find_session_cb_func psk_find_session_cb; + SSL_psk_use_session_cb_func psk_use_session_cb; + + SSL_CTX *ctx; + /* Verified chain of peer */ + STACK_OF(X509) *verified_chain; + long verify_result; + /* extra application data */ + CRYPTO_EX_DATA ex_data; + /* + * What we put in certificate_authorities extension for TLS 1.3 + * (ClientHello and CertificateRequest) or just client cert requests for + * earlier versions. If client_ca_names is populated then it is only used + * for client cert requests, and in preference to ca_names. + */ + STACK_OF(X509_NAME) *ca_names; + STACK_OF(X509_NAME) *client_ca_names; + CRYPTO_REF_COUNT references; + /* protocol behaviour */ + uint32_t options; + /* API behaviour */ + uint32_t mode; + int min_proto_version; + int max_proto_version; + size_t max_cert_list; + int first_packet; + /* + * What was passed in ClientHello.legacy_version. Used for RSA pre-master + * secret and SSLv3/TLS (<=1.2) rollback check + */ + int client_version; + /* + * If we're using more than one pipeline how should we divide the data + * up between the pipes? + */ + size_t split_send_fragment; + /* + * Maximum amount of data to send in one fragment. actual record size can + * be more than this due to padding and MAC overheads. + */ + size_t max_send_fragment; + /* Up to how many pipelines should we use? If 0 then 1 is assumed */ + size_t max_pipelines; + + struct { + /* Built-in extension flags */ + uint8_t extflags[TLSEXT_IDX_num_builtins]; + /* TLS extension debug callback */ + void (*debug_cb)(SSL *s, int client_server, int type, + const unsigned char *data, int len, void *arg); + void *debug_arg; + char *hostname; + /* certificate status request info */ + /* Status type or -1 if no status type */ + int status_type; + /* Raw extension data, if seen */ + unsigned char *scts; + /* Length of raw extension data, if seen */ + uint16_t scts_len; + /* Expect OCSP CertificateStatus message */ + int status_expected; + + struct { + /* OCSP status request only */ + STACK_OF(OCSP_RESPID) *ids; + X509_EXTENSIONS *exts; + /* OCSP response received or to be sent */ + unsigned char *resp; + size_t resp_len; + } ocsp; + + /* RFC4507 session ticket expected to be received or sent */ + int ticket_expected; +# ifndef OPENSSL_NO_EC + size_t ecpointformats_len; + /* our list */ + unsigned char *ecpointformats; +# endif /* OPENSSL_NO_EC */ + size_t supportedgroups_len; + /* our list */ + uint16_t *supportedgroups; + /* TLS Session Ticket extension override */ + TLS_SESSION_TICKET_EXT *session_ticket; + /* TLS Session Ticket extension callback */ + tls_session_ticket_ext_cb_fn session_ticket_cb; + void *session_ticket_cb_arg; + /* TLS pre-shared secret session resumption */ + tls_session_secret_cb_fn session_secret_cb; + void *session_secret_cb_arg; + /* + * For a client, this contains the list of supported protocols in wire + * format. + */ + unsigned char *alpn; + size_t alpn_len; + /* + * Next protocol negotiation. For the client, this is the protocol that + * we sent in NextProtocol and is set when handling ServerHello + * extensions. For a server, this is the client's selected_protocol from + * NextProtocol and is set when handling the NextProtocol message, before + * the Finished message. + */ + unsigned char *npn; + size_t npn_len; + + /* The available PSK key exchange modes */ + int psk_kex_mode; + + /* Set to one if we have negotiated ETM */ + int use_etm; + + /* Are we expecting to receive early data? */ + int early_data; + /* Is the session suitable for early data? */ + int early_data_ok; + + /* May be sent by a server in HRR. Must be echoed back in ClientHello */ + unsigned char *tls13_cookie; + size_t tls13_cookie_len; + /* Have we received a cookie from the client? */ + int cookieok; + + /* + * Maximum Fragment Length as per RFC 4366. + * If this member contains one of the allowed values (1-4) + * then we should include Maximum Fragment Length Negotiation + * extension in Client Hello. + * Please note that value of this member does not have direct + * effect. The actual (binding) value is stored in SSL_SESSION, + * as this extension is optional on server side. + */ + uint8_t max_fragment_len_mode; + } ext; + + /* + * Parsed form of the ClientHello, kept around across client_hello_cb + * calls. + */ + CLIENTHELLO_MSG *clienthello; + + /*- + * no further mod of servername + * 0 : call the servername extension callback. + * 1 : prepare 2, allow last ack just after in server callback. + * 2 : don't call servername callback, no ack in server hello + */ + int servername_done; +# ifndef OPENSSL_NO_CT + /* + * Validates that the SCTs (Signed Certificate Timestamps) are sufficient. + * If they are not, the connection should be aborted. + */ + ssl_ct_validation_cb ct_validation_callback; + /* User-supplied argument that is passed to the ct_validation_callback */ + void *ct_validation_callback_arg; + /* + * Consolidated stack of SCTs from all sources. + * Lazily populated by CT_get_peer_scts(SSL*) + */ + STACK_OF(SCT) *scts; + /* Have we attempted to find/parse SCTs yet? */ + int scts_parsed; +# endif + SSL_CTX *session_ctx; /* initial ctx, used to store sessions */ +# ifndef OPENSSL_NO_SRTP + /* What we'll do */ + STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles; + /* What's been chosen */ + SRTP_PROTECTION_PROFILE *srtp_profile; +# endif + /*- + * 1 if we are renegotiating. + * 2 if we are a server and are inside a handshake + * (i.e. not just sending a HelloRequest) + */ + int renegotiate; + /* If sending a KeyUpdate is pending */ + int key_update; + /* Post-handshake authentication state */ + SSL_PHA_STATE post_handshake_auth; + int pha_enabled; + uint8_t* pha_context; + size_t pha_context_len; + int certreqs_sent; + EVP_MD_CTX *pha_dgst; /* this is just the digest through ClientFinished */ + +# ifndef OPENSSL_NO_SRP + /* ctx for SRP authentication */ + SRP_CTX srp_ctx; +# endif + /* + * Callback for disabling session caching and ticket support on a session + * basis, depending on the chosen cipher. + */ + int (*not_resumable_session_cb) (SSL *ssl, int is_forward_secure); + RECORD_LAYER rlayer; + /* Default password callback. */ + pem_password_cb *default_passwd_callback; + /* Default password callback user data. */ + void *default_passwd_callback_userdata; + /* Async Job info */ + ASYNC_JOB *job; + ASYNC_WAIT_CTX *waitctx; + size_t asyncrw; + + /* + * The maximum number of bytes advertised in session tickets that can be + * sent as early data. + */ + uint32_t max_early_data; + /* + * The maximum number of bytes of early data that a server will tolerate + * (which should be at least as much as max_early_data). + */ + uint32_t recv_max_early_data; + + /* + * The number of bytes of early data received so far. If we accepted early + * data then this is a count of the plaintext bytes. If we rejected it then + * this is a count of the ciphertext bytes. + */ + uint32_t early_data_count; + + /* TLS1.3 padding callback */ + size_t (*record_padding_cb)(SSL *s, int type, size_t len, void *arg); + void *record_padding_arg; + size_t block_padding; + + CRYPTO_RWLOCK *lock; + RAND_DRBG *drbg; + + /* The number of TLS1.3 tickets to automatically send */ + size_t num_tickets; + /* The number of TLS1.3 tickets actually sent so far */ + size_t sent_tickets; + /* The next nonce value to use when we send a ticket on this connection */ + uint64_t next_ticket_nonce; + + /* Callback to determine if early_data is acceptable or not */ + SSL_allow_early_data_cb_fn allow_early_data_cb; + void *allow_early_data_cb_data; +}; + +/* + * Structure containing table entry of values associated with the signature + * algorithms (signature scheme) extension +*/ +typedef struct sigalg_lookup_st { + /* TLS 1.3 signature scheme name */ + const char *name; + /* Raw value used in extension */ + uint16_t sigalg; + /* NID of hash algorithm or NID_undef if no hash */ + int hash; + /* Index of hash algorithm or -1 if no hash algorithm */ + int hash_idx; + /* NID of signature algorithm */ + int sig; + /* Index of signature algorithm */ + int sig_idx; + /* Combined hash and signature NID, if any */ + int sigandhash; + /* Required public key curve (ECDSA only) */ + int curve; +} SIGALG_LOOKUP; + +typedef struct tls_group_info_st { + int nid; /* Curve NID */ + int secbits; /* Bits of security (from SP800-57) */ + uint16_t flags; /* Flags: currently just group type */ +} TLS_GROUP_INFO; + +/* flags values */ +# define TLS_CURVE_TYPE 0x3 /* Mask for group type */ +# define TLS_CURVE_PRIME 0x0 +# define TLS_CURVE_CHAR2 0x1 +# define TLS_CURVE_CUSTOM 0x2 + +typedef struct cert_pkey_st CERT_PKEY; + +/* + * Structure containing table entry of certificate info corresponding to + * CERT_PKEY entries + */ +typedef struct { + int nid; /* NID of pubic key algorithm */ + uint32_t amask; /* authmask corresponding to key type */ +} SSL_CERT_LOOKUP; + +typedef struct ssl3_state_st { + long flags; + size_t read_mac_secret_size; + unsigned char read_mac_secret[EVP_MAX_MD_SIZE]; + size_t write_mac_secret_size; + unsigned char write_mac_secret[EVP_MAX_MD_SIZE]; + unsigned char server_random[SSL3_RANDOM_SIZE]; + unsigned char client_random[SSL3_RANDOM_SIZE]; + /* flags for countermeasure against known-IV weakness */ + int need_empty_fragments; + int empty_fragment_done; + /* used during startup, digest all incoming/outgoing packets */ + BIO *handshake_buffer; + /* + * When handshake digest is determined, buffer is hashed and + * freed and MD_CTX for the required digest is stored here. + */ + EVP_MD_CTX *handshake_dgst; + /* + * Set whenever an expected ChangeCipherSpec message is processed. + * Unset when the peer's Finished message is received. + * Unexpected ChangeCipherSpec messages trigger a fatal alert. + */ + int change_cipher_spec; + int warn_alert; + int fatal_alert; + /* + * we allow one fatal and one warning alert to be outstanding, send close + * alert via the warning alert + */ + int alert_dispatch; + unsigned char send_alert[2]; + /* + * This flag is set when we should renegotiate ASAP, basically when there + * is no more data in the read or write buffers + */ + int renegotiate; + int total_renegotiations; + int num_renegotiations; + int in_read_app_data; + struct { + /* actually only need to be 16+20 for SSLv3 and 12 for TLS */ + unsigned char finish_md[EVP_MAX_MD_SIZE * 2]; + size_t finish_md_len; + unsigned char peer_finish_md[EVP_MAX_MD_SIZE * 2]; + size_t peer_finish_md_len; + size_t message_size; + int message_type; + /* used to hold the new cipher we are going to use */ + const SSL_CIPHER *new_cipher; +# if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH) + EVP_PKEY *pkey; /* holds short lived DH/ECDH key */ +# endif + /* used for certificate requests */ + int cert_req; + /* Certificate types in certificate request message. */ + uint8_t *ctype; + size_t ctype_len; + /* Certificate authorities list peer sent */ + STACK_OF(X509_NAME) *peer_ca_names; + size_t key_block_length; + unsigned char *key_block; + const EVP_CIPHER *new_sym_enc; + const EVP_MD *new_hash; + int new_mac_pkey_type; + size_t new_mac_secret_size; +# ifndef OPENSSL_NO_COMP + const SSL_COMP *new_compression; +# else + char *new_compression; +# endif + int cert_request; + /* Raw values of the cipher list from a client */ + unsigned char *ciphers_raw; + size_t ciphers_rawlen; + /* Temporary storage for premaster secret */ + unsigned char *pms; + size_t pmslen; +# ifndef OPENSSL_NO_PSK + /* Temporary storage for PSK key */ + unsigned char *psk; + size_t psklen; +# endif + /* Signature algorithm we actually use */ + const SIGALG_LOOKUP *sigalg; + /* Pointer to certificate we use */ + CERT_PKEY *cert; + /* + * signature algorithms peer reports: e.g. supported signature + * algorithms extension for server or as part of a certificate + * request for client. + * Keep track of the algorithms for TLS and X.509 usage separately. + */ + uint16_t *peer_sigalgs; + uint16_t *peer_cert_sigalgs; + /* Size of above arrays */ + size_t peer_sigalgslen; + size_t peer_cert_sigalgslen; + /* Sigalg peer actually uses */ + const SIGALG_LOOKUP *peer_sigalg; + /* + * Set if corresponding CERT_PKEY can be used with current + * SSL session: e.g. appropriate curve, signature algorithms etc. + * If zero it can't be used at all. + */ + uint32_t valid_flags[SSL_PKEY_NUM]; + /* + * For servers the following masks are for the key and auth algorithms + * that are supported by the certs below. For clients they are masks of + * *disabled* algorithms based on the current session. + */ + uint32_t mask_k; + uint32_t mask_a; + /* + * The following are used by the client to see if a cipher is allowed or + * not. It contains the minimum and maximum version the client's using + * based on what it knows so far. + */ + int min_ver; + int max_ver; + } tmp; + + /* Connection binding to prevent renegotiation attacks */ + unsigned char previous_client_finished[EVP_MAX_MD_SIZE]; + size_t previous_client_finished_len; + unsigned char previous_server_finished[EVP_MAX_MD_SIZE]; + size_t previous_server_finished_len; + int send_connection_binding; /* TODOEKR */ + +# ifndef OPENSSL_NO_NEXTPROTONEG + /* + * Set if we saw the Next Protocol Negotiation extension from our peer. + */ + int npn_seen; +# endif + + /* + * ALPN information (we are in the process of transitioning from NPN to + * ALPN.) + */ + + /* + * In a server these point to the selected ALPN protocol after the + * ClientHello has been processed. In a client these contain the protocol + * that the server selected once the ServerHello has been processed. + */ + unsigned char *alpn_selected; + size_t alpn_selected_len; + /* used by the server to know what options were proposed */ + unsigned char *alpn_proposed; + size_t alpn_proposed_len; + /* used by the client to know if it actually sent alpn */ + int alpn_sent; + +# ifndef OPENSSL_NO_EC + /* + * This is set to true if we believe that this is a version of Safari + * running on OS X 10.6 or newer. We wish to know this because Safari on + * 10.8 .. 10.8.3 has broken ECDHE-ECDSA support. + */ + char is_probably_safari; +# endif /* !OPENSSL_NO_EC */ + + /* For clients: peer temporary key */ +# if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH) + /* The group_id for the DH/ECDH key */ + uint16_t group_id; + EVP_PKEY *peer_tmp; +# endif + +} SSL3_STATE; + +/* DTLS structures */ + +# ifndef OPENSSL_NO_SCTP +# define DTLS1_SCTP_AUTH_LABEL "EXPORTER_DTLS_OVER_SCTP" +# endif + +/* Max MTU overhead we know about so far is 40 for IPv6 + 8 for UDP */ +# define DTLS1_MAX_MTU_OVERHEAD 48 + +/* + * Flag used in message reuse to indicate the buffer contains the record + * header as well as the handshake message header. + */ +# define DTLS1_SKIP_RECORD_HEADER 2 + +struct dtls1_retransmit_state { + EVP_CIPHER_CTX *enc_write_ctx; /* cryptographic state */ + EVP_MD_CTX *write_hash; /* used for mac generation */ + COMP_CTX *compress; /* compression */ + SSL_SESSION *session; + unsigned short epoch; +}; + +struct hm_header_st { + unsigned char type; + size_t msg_len; + unsigned short seq; + size_t frag_off; + size_t frag_len; + unsigned int is_ccs; + struct dtls1_retransmit_state saved_retransmit_state; +}; + +struct dtls1_timeout_st { + /* Number of read timeouts so far */ + unsigned int read_timeouts; + /* Number of write timeouts so far */ + unsigned int write_timeouts; + /* Number of alerts received so far */ + unsigned int num_alerts; +}; + +typedef struct hm_fragment_st { + struct hm_header_st msg_header; + unsigned char *fragment; + unsigned char *reassembly; +} hm_fragment; + +typedef struct pqueue_st pqueue; +typedef struct pitem_st pitem; + +struct pitem_st { + unsigned char priority[8]; /* 64-bit value in big-endian encoding */ + void *data; + pitem *next; +}; + +typedef struct pitem_st *piterator; + +pitem *pitem_new(unsigned char *prio64be, void *data); +void pitem_free(pitem *item); +pqueue *pqueue_new(void); +void pqueue_free(pqueue *pq); +pitem *pqueue_insert(pqueue *pq, pitem *item); +pitem *pqueue_peek(pqueue *pq); +pitem *pqueue_pop(pqueue *pq); +pitem *pqueue_find(pqueue *pq, unsigned char *prio64be); +pitem *pqueue_iterator(pqueue *pq); +pitem *pqueue_next(piterator *iter); +size_t pqueue_size(pqueue *pq); + +typedef struct dtls1_state_st { + unsigned char cookie[DTLS1_COOKIE_LENGTH]; + size_t cookie_len; + unsigned int cookie_verified; + /* handshake message numbers */ + unsigned short handshake_write_seq; + unsigned short next_handshake_write_seq; + unsigned short handshake_read_seq; + /* Buffered handshake messages */ + pqueue *buffered_messages; + /* Buffered (sent) handshake records */ + pqueue *sent_messages; + size_t link_mtu; /* max on-the-wire DTLS packet size */ + size_t mtu; /* max DTLS packet size */ + struct hm_header_st w_msg_hdr; + struct hm_header_st r_msg_hdr; + struct dtls1_timeout_st timeout; + /* + * Indicates when the last handshake msg sent will timeout + */ + struct timeval next_timeout; + /* Timeout duration */ + unsigned int timeout_duration_us; + + unsigned int retransmitting; +# ifndef OPENSSL_NO_SCTP + int shutdown_received; +# endif + + DTLS_timer_cb timer_cb; + +} DTLS1_STATE; + +# ifndef OPENSSL_NO_EC +/* + * From ECC-TLS draft, used in encoding the curve type in ECParameters + */ +# define EXPLICIT_PRIME_CURVE_TYPE 1 +# define EXPLICIT_CHAR2_CURVE_TYPE 2 +# define NAMED_CURVE_TYPE 3 +# endif /* OPENSSL_NO_EC */ + +struct cert_pkey_st { + X509 *x509; + EVP_PKEY *privatekey; + /* Chain for this certificate */ + STACK_OF(X509) *chain; + /*- + * serverinfo data for this certificate. The data is in TLS Extension + * wire format, specifically it's a series of records like: + * uint16_t extension_type; // (RFC 5246, 7.4.1.4, Extension) + * uint16_t length; + * uint8_t data[length]; + */ + unsigned char *serverinfo; + size_t serverinfo_length; +}; +/* Retrieve Suite B flags */ +# define tls1_suiteb(s) (s->cert->cert_flags & SSL_CERT_FLAG_SUITEB_128_LOS) +/* Uses to check strict mode: suite B modes are always strict */ +# define SSL_CERT_FLAGS_CHECK_TLS_STRICT \ + (SSL_CERT_FLAG_SUITEB_128_LOS|SSL_CERT_FLAG_TLS_STRICT) + +typedef enum { + ENDPOINT_CLIENT = 0, + ENDPOINT_SERVER, + ENDPOINT_BOTH +} ENDPOINT; + + +typedef struct { + unsigned short ext_type; + ENDPOINT role; + /* The context which this extension applies to */ + unsigned int context; + /* + * Per-connection flags relating to this extension type: not used if + * part of an SSL_CTX structure. + */ + uint32_t ext_flags; + SSL_custom_ext_add_cb_ex add_cb; + SSL_custom_ext_free_cb_ex free_cb; + void *add_arg; + SSL_custom_ext_parse_cb_ex parse_cb; + void *parse_arg; +} custom_ext_method; + +/* ext_flags values */ + +/* + * Indicates an extension has been received. Used to check for unsolicited or + * duplicate extensions. + */ +# define SSL_EXT_FLAG_RECEIVED 0x1 +/* + * Indicates an extension has been sent: used to enable sending of + * corresponding ServerHello extension. + */ +# define SSL_EXT_FLAG_SENT 0x2 + +typedef struct { + custom_ext_method *meths; + size_t meths_count; +} custom_ext_methods; + +typedef struct cert_st { + /* Current active set */ + /* + * ALWAYS points to an element of the pkeys array + * Probably it would make more sense to store + * an index, not a pointer. + */ + CERT_PKEY *key; +# ifndef OPENSSL_NO_DH + EVP_PKEY *dh_tmp; + DH *(*dh_tmp_cb) (SSL *ssl, int is_export, int keysize); + int dh_tmp_auto; +# endif + /* Flags related to certificates */ + uint32_t cert_flags; + CERT_PKEY pkeys[SSL_PKEY_NUM]; + /* Custom certificate types sent in certificate request message. */ + uint8_t *ctype; + size_t ctype_len; + /* + * supported signature algorithms. When set on a client this is sent in + * the client hello as the supported signature algorithms extension. For + * servers it represents the signature algorithms we are willing to use. + */ + uint16_t *conf_sigalgs; + /* Size of above array */ + size_t conf_sigalgslen; + /* + * Client authentication signature algorithms, if not set then uses + * conf_sigalgs. On servers these will be the signature algorithms sent + * to the client in a certificate request for TLS 1.2. On a client this + * represents the signature algorithms we are willing to use for client + * authentication. + */ + uint16_t *client_sigalgs; + /* Size of above array */ + size_t client_sigalgslen; + /* + * Signature algorithms shared by client and server: cached because these + * are used most often. + */ + const SIGALG_LOOKUP **shared_sigalgs; + size_t shared_sigalgslen; + /* + * Certificate setup callback: if set is called whenever a certificate + * may be required (client or server). the callback can then examine any + * appropriate parameters and setup any certificates required. This + * allows advanced applications to select certificates on the fly: for + * example based on supported signature algorithms or curves. + */ + int (*cert_cb) (SSL *ssl, void *arg); + void *cert_cb_arg; + /* + * Optional X509_STORE for chain building or certificate validation If + * NULL the parent SSL_CTX store is used instead. + */ + X509_STORE *chain_store; + X509_STORE *verify_store; + /* Custom extensions */ + custom_ext_methods custext; + /* Security callback */ + int (*sec_cb) (const SSL *s, const SSL_CTX *ctx, int op, int bits, int nid, + void *other, void *ex); + /* Security level */ + int sec_level; + void *sec_ex; +# ifndef OPENSSL_NO_PSK + /* If not NULL psk identity hint to use for servers */ + char *psk_identity_hint; +# endif + CRYPTO_REF_COUNT references; /* >1 only if SSL_copy_session_id is used */ + CRYPTO_RWLOCK *lock; +} CERT; + +# define FP_ICC (int (*)(const void *,const void *)) + +/* + * This is for the SSLv3/TLSv1.0 differences in crypto/hash stuff It is a bit + * of a mess of functions, but hell, think of it as an opaque structure :-) + */ +typedef struct ssl3_enc_method { + int (*enc) (SSL *, SSL3_RECORD *, size_t, int); + int (*mac) (SSL *, SSL3_RECORD *, unsigned char *, int); + int (*setup_key_block) (SSL *); + int (*generate_master_secret) (SSL *, unsigned char *, unsigned char *, + size_t, size_t *); + int (*change_cipher_state) (SSL *, int); + size_t (*final_finish_mac) (SSL *, const char *, size_t, unsigned char *); + const char *client_finished_label; + size_t client_finished_label_len; + const char *server_finished_label; + size_t server_finished_label_len; + int (*alert_value) (int); + int (*export_keying_material) (SSL *, unsigned char *, size_t, + const char *, size_t, + const unsigned char *, size_t, + int use_context); + /* Various flags indicating protocol version requirements */ + uint32_t enc_flags; + /* Set the handshake header */ + int (*set_handshake_header) (SSL *s, WPACKET *pkt, int type); + /* Close construction of the handshake message */ + int (*close_construct_packet) (SSL *s, WPACKET *pkt, int htype); + /* Write out handshake message */ + int (*do_write) (SSL *s); +} SSL3_ENC_METHOD; + +# define ssl_set_handshake_header(s, pkt, htype) \ + s->method->ssl3_enc->set_handshake_header((s), (pkt), (htype)) +# define ssl_close_construct_packet(s, pkt, htype) \ + s->method->ssl3_enc->close_construct_packet((s), (pkt), (htype)) +# define ssl_do_write(s) s->method->ssl3_enc->do_write(s) + +/* Values for enc_flags */ + +/* Uses explicit IV for CBC mode */ +# define SSL_ENC_FLAG_EXPLICIT_IV 0x1 +/* Uses signature algorithms extension */ +# define SSL_ENC_FLAG_SIGALGS 0x2 +/* Uses SHA256 default PRF */ +# define SSL_ENC_FLAG_SHA256_PRF 0x4 +/* Is DTLS */ +# define SSL_ENC_FLAG_DTLS 0x8 +/* + * Allow TLS 1.2 ciphersuites: applies to DTLS 1.2 as well as TLS 1.2: may + * apply to others in future. + */ +# define SSL_ENC_FLAG_TLS1_2_CIPHERS 0x10 + +# ifndef OPENSSL_NO_COMP +/* Used for holding the relevant compression methods loaded into SSL_CTX */ +typedef struct ssl3_comp_st { + int comp_id; /* The identifier byte for this compression + * type */ + char *name; /* Text name used for the compression type */ + COMP_METHOD *method; /* The method :-) */ +} SSL3_COMP; +# endif + +typedef enum downgrade_en { + DOWNGRADE_NONE, + DOWNGRADE_TO_1_2, + DOWNGRADE_TO_1_1 +} DOWNGRADE; + +/* + * Dummy status type for the status_type extension. Indicates no status type + * set + */ +#define TLSEXT_STATUSTYPE_nothing -1 + +/* Sigalgs values */ +#define TLSEXT_SIGALG_ecdsa_secp256r1_sha256 0x0403 +#define TLSEXT_SIGALG_ecdsa_secp384r1_sha384 0x0503 +#define TLSEXT_SIGALG_ecdsa_secp521r1_sha512 0x0603 +#define TLSEXT_SIGALG_ecdsa_sha224 0x0303 +#define TLSEXT_SIGALG_ecdsa_sha1 0x0203 +#define TLSEXT_SIGALG_rsa_pss_rsae_sha256 0x0804 +#define TLSEXT_SIGALG_rsa_pss_rsae_sha384 0x0805 +#define TLSEXT_SIGALG_rsa_pss_rsae_sha512 0x0806 +#define TLSEXT_SIGALG_rsa_pss_pss_sha256 0x0809 +#define TLSEXT_SIGALG_rsa_pss_pss_sha384 0x080a +#define TLSEXT_SIGALG_rsa_pss_pss_sha512 0x080b +#define TLSEXT_SIGALG_rsa_pkcs1_sha256 0x0401 +#define TLSEXT_SIGALG_rsa_pkcs1_sha384 0x0501 +#define TLSEXT_SIGALG_rsa_pkcs1_sha512 0x0601 +#define TLSEXT_SIGALG_rsa_pkcs1_sha224 0x0301 +#define TLSEXT_SIGALG_rsa_pkcs1_sha1 0x0201 +#define TLSEXT_SIGALG_dsa_sha256 0x0402 +#define TLSEXT_SIGALG_dsa_sha384 0x0502 +#define TLSEXT_SIGALG_dsa_sha512 0x0602 +#define TLSEXT_SIGALG_dsa_sha224 0x0302 +#define TLSEXT_SIGALG_dsa_sha1 0x0202 +#define TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256 0xeeee +#define TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512 0xefef +#define TLSEXT_SIGALG_gostr34102001_gostr3411 0xeded + +#define TLSEXT_SIGALG_ed25519 0x0807 +#define TLSEXT_SIGALG_ed448 0x0808 + +/* Known PSK key exchange modes */ +#define TLSEXT_KEX_MODE_KE 0x00 +#define TLSEXT_KEX_MODE_KE_DHE 0x01 + +/* + * Internal representations of key exchange modes + */ +#define TLSEXT_KEX_MODE_FLAG_NONE 0 +#define TLSEXT_KEX_MODE_FLAG_KE 1 +#define TLSEXT_KEX_MODE_FLAG_KE_DHE 2 + +/* An invalid index into the TLSv1.3 PSK identities */ +#define TLSEXT_PSK_BAD_IDENTITY -1 + +#define SSL_USE_PSS(s) (s->s3->tmp.peer_sigalg != NULL && \ + s->s3->tmp.peer_sigalg->sig == EVP_PKEY_RSA_PSS) + +/* A dummy signature value not valid for TLSv1.2 signature algs */ +#define TLSEXT_signature_rsa_pss 0x0101 + +/* TLSv1.3 downgrade protection sentinel values */ +extern const unsigned char tls11downgrade[8]; +extern const unsigned char tls12downgrade[8]; + +extern SSL3_ENC_METHOD ssl3_undef_enc_method; + +__owur const SSL_METHOD *ssl_bad_method(int ver); +__owur const SSL_METHOD *sslv3_method(void); +__owur const SSL_METHOD *sslv3_server_method(void); +__owur const SSL_METHOD *sslv3_client_method(void); +__owur const SSL_METHOD *tlsv1_method(void); +__owur const SSL_METHOD *tlsv1_server_method(void); +__owur const SSL_METHOD *tlsv1_client_method(void); +__owur const SSL_METHOD *tlsv1_1_method(void); +__owur const SSL_METHOD *tlsv1_1_server_method(void); +__owur const SSL_METHOD *tlsv1_1_client_method(void); +__owur const SSL_METHOD *tlsv1_2_method(void); +__owur const SSL_METHOD *tlsv1_2_server_method(void); +__owur const SSL_METHOD *tlsv1_2_client_method(void); +__owur const SSL_METHOD *tlsv1_3_method(void); +__owur const SSL_METHOD *tlsv1_3_server_method(void); +__owur const SSL_METHOD *tlsv1_3_client_method(void); +__owur const SSL_METHOD *dtlsv1_method(void); +__owur const SSL_METHOD *dtlsv1_server_method(void); +__owur const SSL_METHOD *dtlsv1_client_method(void); +__owur const SSL_METHOD *dtls_bad_ver_client_method(void); +__owur const SSL_METHOD *dtlsv1_2_method(void); +__owur const SSL_METHOD *dtlsv1_2_server_method(void); +__owur const SSL_METHOD *dtlsv1_2_client_method(void); + +extern const SSL3_ENC_METHOD TLSv1_enc_data; +extern const SSL3_ENC_METHOD TLSv1_1_enc_data; +extern const SSL3_ENC_METHOD TLSv1_2_enc_data; +extern const SSL3_ENC_METHOD TLSv1_3_enc_data; +extern const SSL3_ENC_METHOD SSLv3_enc_data; +extern const SSL3_ENC_METHOD DTLSv1_enc_data; +extern const SSL3_ENC_METHOD DTLSv1_2_enc_data; + +/* + * Flags for SSL methods + */ +# define SSL_METHOD_NO_FIPS (1U<<0) +# define SSL_METHOD_NO_SUITEB (1U<<1) + +# define IMPLEMENT_tls_meth_func(version, flags, mask, func_name, s_accept, \ + s_connect, enc_data) \ +const SSL_METHOD *func_name(void) \ + { \ + static const SSL_METHOD func_name##_data= { \ + version, \ + flags, \ + mask, \ + tls1_new, \ + tls1_clear, \ + tls1_free, \ + s_accept, \ + s_connect, \ + ssl3_read, \ + ssl3_peek, \ + ssl3_write, \ + ssl3_shutdown, \ + ssl3_renegotiate, \ + ssl3_renegotiate_check, \ + ssl3_read_bytes, \ + ssl3_write_bytes, \ + ssl3_dispatch_alert, \ + ssl3_ctrl, \ + ssl3_ctx_ctrl, \ + ssl3_get_cipher_by_char, \ + ssl3_put_cipher_by_char, \ + ssl3_pending, \ + ssl3_num_ciphers, \ + ssl3_get_cipher, \ + tls1_default_timeout, \ + &enc_data, \ + ssl_undefined_void_function, \ + ssl3_callback_ctrl, \ + ssl3_ctx_callback_ctrl, \ + }; \ + return &func_name##_data; \ + } + +# define IMPLEMENT_ssl3_meth_func(func_name, s_accept, s_connect) \ +const SSL_METHOD *func_name(void) \ + { \ + static const SSL_METHOD func_name##_data= { \ + SSL3_VERSION, \ + SSL_METHOD_NO_FIPS | SSL_METHOD_NO_SUITEB, \ + SSL_OP_NO_SSLv3, \ + ssl3_new, \ + ssl3_clear, \ + ssl3_free, \ + s_accept, \ + s_connect, \ + ssl3_read, \ + ssl3_peek, \ + ssl3_write, \ + ssl3_shutdown, \ + ssl3_renegotiate, \ + ssl3_renegotiate_check, \ + ssl3_read_bytes, \ + ssl3_write_bytes, \ + ssl3_dispatch_alert, \ + ssl3_ctrl, \ + ssl3_ctx_ctrl, \ + ssl3_get_cipher_by_char, \ + ssl3_put_cipher_by_char, \ + ssl3_pending, \ + ssl3_num_ciphers, \ + ssl3_get_cipher, \ + ssl3_default_timeout, \ + &SSLv3_enc_data, \ + ssl_undefined_void_function, \ + ssl3_callback_ctrl, \ + ssl3_ctx_callback_ctrl, \ + }; \ + return &func_name##_data; \ + } + +# define IMPLEMENT_dtls1_meth_func(version, flags, mask, func_name, s_accept, \ + s_connect, enc_data) \ +const SSL_METHOD *func_name(void) \ + { \ + static const SSL_METHOD func_name##_data= { \ + version, \ + flags, \ + mask, \ + dtls1_new, \ + dtls1_clear, \ + dtls1_free, \ + s_accept, \ + s_connect, \ + ssl3_read, \ + ssl3_peek, \ + ssl3_write, \ + dtls1_shutdown, \ + ssl3_renegotiate, \ + ssl3_renegotiate_check, \ + dtls1_read_bytes, \ + dtls1_write_app_data_bytes, \ + dtls1_dispatch_alert, \ + dtls1_ctrl, \ + ssl3_ctx_ctrl, \ + ssl3_get_cipher_by_char, \ + ssl3_put_cipher_by_char, \ + ssl3_pending, \ + ssl3_num_ciphers, \ + ssl3_get_cipher, \ + dtls1_default_timeout, \ + &enc_data, \ + ssl_undefined_void_function, \ + ssl3_callback_ctrl, \ + ssl3_ctx_callback_ctrl, \ + }; \ + return &func_name##_data; \ + } + +struct openssl_ssl_test_functions { + int (*p_ssl_init_wbio_buffer) (SSL *s); + int (*p_ssl3_setup_buffers) (SSL *s); +}; + +const char *ssl_protocol_to_string(int version); + +/* Returns true if certificate and private key for 'idx' are present */ +static ossl_inline int ssl_has_cert(const SSL *s, int idx) +{ + if (idx < 0 || idx >= SSL_PKEY_NUM) + return 0; + return s->cert->pkeys[idx].x509 != NULL + && s->cert->pkeys[idx].privatekey != NULL; +} + +static ossl_inline void tls1_get_peer_groups(SSL *s, const uint16_t **pgroups, + size_t *pgroupslen) +{ + *pgroups = s->session->ext.supportedgroups; + *pgroupslen = s->session->ext.supportedgroups_len; +} + +# ifndef OPENSSL_UNIT_TEST + +__owur int ssl_read_internal(SSL *s, void *buf, size_t num, size_t *readbytes); +__owur int ssl_write_internal(SSL *s, const void *buf, size_t num, size_t *written); +void ssl_clear_cipher_ctx(SSL *s); +int ssl_clear_bad_session(SSL *s); +__owur CERT *ssl_cert_new(void); +__owur CERT *ssl_cert_dup(CERT *cert); +void ssl_cert_clear_certs(CERT *c); +void ssl_cert_free(CERT *c); +__owur int ssl_generate_session_id(SSL *s, SSL_SESSION *ss); +__owur int ssl_get_new_session(SSL *s, int session); +__owur SSL_SESSION *lookup_sess_in_cache(SSL *s, const unsigned char *sess_id, + size_t sess_id_len); +__owur int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello); +__owur SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket); +__owur int ssl_cipher_id_cmp(const SSL_CIPHER *a, const SSL_CIPHER *b); +DECLARE_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER, ssl_cipher_id); +__owur int ssl_cipher_ptr_id_cmp(const SSL_CIPHER *const *ap, + const SSL_CIPHER *const *bp); +__owur STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, + STACK_OF(SSL_CIPHER) *tls13_ciphersuites, + STACK_OF(SSL_CIPHER) **cipher_list, + STACK_OF(SSL_CIPHER) **cipher_list_by_id, + const char *rule_str, + CERT *c); +__owur int ssl_cache_cipherlist(SSL *s, PACKET *cipher_suites, int sslv2format); +__owur int bytes_to_cipher_list(SSL *s, PACKET *cipher_suites, + STACK_OF(SSL_CIPHER) **skp, + STACK_OF(SSL_CIPHER) **scsvs, int sslv2format, + int fatal); +void ssl_update_cache(SSL *s, int mode); +__owur int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc, + const EVP_MD **md, int *mac_pkey_type, + size_t *mac_secret_size, SSL_COMP **comp, + int use_etm); +__owur int ssl_cipher_get_overhead(const SSL_CIPHER *c, size_t *mac_overhead, + size_t *int_overhead, size_t *blocksize, + size_t *ext_overhead); +__owur int ssl_cert_is_disabled(size_t idx); +__owur const SSL_CIPHER *ssl_get_cipher_by_char(SSL *ssl, + const unsigned char *ptr, + int all); +__owur int ssl_cert_set0_chain(SSL *s, SSL_CTX *ctx, STACK_OF(X509) *chain); +__owur int ssl_cert_set1_chain(SSL *s, SSL_CTX *ctx, STACK_OF(X509) *chain); +__owur int ssl_cert_add0_chain_cert(SSL *s, SSL_CTX *ctx, X509 *x); +__owur int ssl_cert_add1_chain_cert(SSL *s, SSL_CTX *ctx, X509 *x); +__owur int ssl_cert_select_current(CERT *c, X509 *x); +__owur int ssl_cert_set_current(CERT *c, long arg); +void ssl_cert_set_cert_cb(CERT *c, int (*cb) (SSL *ssl, void *arg), void *arg); + +__owur int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk); +__owur int ssl_build_cert_chain(SSL *s, SSL_CTX *ctx, int flags); +__owur int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain, + int ref); + +__owur int ssl_security(const SSL *s, int op, int bits, int nid, void *other); +__owur int ssl_ctx_security(const SSL_CTX *ctx, int op, int bits, int nid, + void *other); + +__owur int ssl_cert_lookup_by_nid(int nid, size_t *pidx); +__owur const SSL_CERT_LOOKUP *ssl_cert_lookup_by_pkey(const EVP_PKEY *pk, + size_t *pidx); +__owur const SSL_CERT_LOOKUP *ssl_cert_lookup_by_idx(size_t idx); + +int ssl_undefined_function(SSL *s); +__owur int ssl_undefined_void_function(void); +__owur int ssl_undefined_const_function(const SSL *s); +__owur int ssl_get_server_cert_serverinfo(SSL *s, + const unsigned char **serverinfo, + size_t *serverinfo_length); +void ssl_set_masks(SSL *s); +__owur STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s); +__owur int ssl_x509err2alert(int type); +void ssl_sort_cipher_list(void); +int ssl_load_ciphers(void); +__owur int ssl_fill_hello_random(SSL *s, int server, unsigned char *field, + size_t len, DOWNGRADE dgrd); +__owur int ssl_generate_master_secret(SSL *s, unsigned char *pms, size_t pmslen, + int free_pms); +__owur EVP_PKEY *ssl_generate_pkey(EVP_PKEY *pm); +__owur int ssl_derive(SSL *s, EVP_PKEY *privkey, EVP_PKEY *pubkey, + int genmaster); +__owur EVP_PKEY *ssl_dh_to_pkey(DH *dh); +__owur unsigned int ssl_get_max_send_fragment(const SSL *ssl); +__owur unsigned int ssl_get_split_send_fragment(const SSL *ssl); + +__owur const SSL_CIPHER *ssl3_get_cipher_by_id(uint32_t id); +__owur const SSL_CIPHER *ssl3_get_cipher_by_std_name(const char *stdname); +__owur const SSL_CIPHER *ssl3_get_cipher_by_char(const unsigned char *p); +__owur int ssl3_put_cipher_by_char(const SSL_CIPHER *c, WPACKET *pkt, + size_t *len); +int ssl3_init_finished_mac(SSL *s); +__owur int ssl3_setup_key_block(SSL *s); +__owur int ssl3_change_cipher_state(SSL *s, int which); +void ssl3_cleanup_key_block(SSL *s); +__owur int ssl3_do_write(SSL *s, int type); +int ssl3_send_alert(SSL *s, int level, int desc); +__owur int ssl3_generate_master_secret(SSL *s, unsigned char *out, + unsigned char *p, size_t len, + size_t *secret_size); +__owur int ssl3_get_req_cert_type(SSL *s, WPACKET *pkt); +__owur int ssl3_num_ciphers(void); +__owur const SSL_CIPHER *ssl3_get_cipher(unsigned int u); +int ssl3_renegotiate(SSL *ssl); +int ssl3_renegotiate_check(SSL *ssl, int initok); +__owur int ssl3_dispatch_alert(SSL *s); +__owur size_t ssl3_final_finish_mac(SSL *s, const char *sender, size_t slen, + unsigned char *p); +__owur int ssl3_finish_mac(SSL *s, const unsigned char *buf, size_t len); +void ssl3_free_digest_list(SSL *s); +__owur unsigned long ssl3_output_cert_chain(SSL *s, WPACKET *pkt, + CERT_PKEY *cpk); +__owur const SSL_CIPHER *ssl3_choose_cipher(SSL *ssl, + STACK_OF(SSL_CIPHER) *clnt, + STACK_OF(SSL_CIPHER) *srvr); +__owur int ssl3_digest_cached_records(SSL *s, int keep); +__owur int ssl3_new(SSL *s); +void ssl3_free(SSL *s); +__owur int ssl3_read(SSL *s, void *buf, size_t len, size_t *readbytes); +__owur int ssl3_peek(SSL *s, void *buf, size_t len, size_t *readbytes); +__owur int ssl3_write(SSL *s, const void *buf, size_t len, size_t *written); +__owur int ssl3_shutdown(SSL *s); +int ssl3_clear(SSL *s); +__owur long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg); +__owur long ssl3_ctx_ctrl(SSL_CTX *s, int cmd, long larg, void *parg); +__owur long ssl3_callback_ctrl(SSL *s, int cmd, void (*fp) (void)); +__owur long ssl3_ctx_callback_ctrl(SSL_CTX *s, int cmd, void (*fp) (void)); + +__owur int ssl3_do_change_cipher_spec(SSL *ssl); +__owur long ssl3_default_timeout(void); + +__owur int ssl3_set_handshake_header(SSL *s, WPACKET *pkt, int htype); +__owur int tls_close_construct_packet(SSL *s, WPACKET *pkt, int htype); +__owur int tls_setup_handshake(SSL *s); +__owur int dtls1_set_handshake_header(SSL *s, WPACKET *pkt, int htype); +__owur int dtls1_close_construct_packet(SSL *s, WPACKET *pkt, int htype); +__owur int ssl3_handshake_write(SSL *s); + +__owur int ssl_allow_compression(SSL *s); + +__owur int ssl_version_supported(const SSL *s, int version, + const SSL_METHOD **meth); + +__owur int ssl_set_client_hello_version(SSL *s); +__owur int ssl_check_version_downgrade(SSL *s); +__owur int ssl_set_version_bound(int method_version, int version, int *bound); +__owur int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello, + DOWNGRADE *dgrd); +__owur int ssl_choose_client_version(SSL *s, int version, + RAW_EXTENSION *extensions); +__owur int ssl_get_min_max_version(const SSL *s, int *min_version, + int *max_version, int *real_max); + +__owur long tls1_default_timeout(void); +__owur int dtls1_do_write(SSL *s, int type); +void dtls1_set_message_header(SSL *s, + unsigned char mt, + size_t len, + size_t frag_off, size_t frag_len); + +int dtls1_write_app_data_bytes(SSL *s, int type, const void *buf_, size_t len, + size_t *written); + +__owur int dtls1_read_failed(SSL *s, int code); +__owur int dtls1_buffer_message(SSL *s, int ccs); +__owur int dtls1_retransmit_message(SSL *s, unsigned short seq, int *found); +__owur int dtls1_get_queue_priority(unsigned short seq, int is_ccs); +int dtls1_retransmit_buffered_messages(SSL *s); +void dtls1_clear_received_buffer(SSL *s); +void dtls1_clear_sent_buffer(SSL *s); +void dtls1_get_message_header(unsigned char *data, + struct hm_header_st *msg_hdr); +__owur long dtls1_default_timeout(void); +__owur struct timeval *dtls1_get_timeout(SSL *s, struct timeval *timeleft); +__owur int dtls1_check_timeout_num(SSL *s); +__owur int dtls1_handle_timeout(SSL *s); +void dtls1_start_timer(SSL *s); +void dtls1_stop_timer(SSL *s); +__owur int dtls1_is_timer_expired(SSL *s); +void dtls1_double_timeout(SSL *s); +__owur int dtls_raw_hello_verify_request(WPACKET *pkt, unsigned char *cookie, + size_t cookie_len); +__owur size_t dtls1_min_mtu(SSL *s); +void dtls1_hm_fragment_free(hm_fragment *frag); +__owur int dtls1_query_mtu(SSL *s); + +__owur int tls1_new(SSL *s); +void tls1_free(SSL *s); +int tls1_clear(SSL *s); + +__owur int dtls1_new(SSL *s); +void dtls1_free(SSL *s); +int dtls1_clear(SSL *s); +long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg); +__owur int dtls1_shutdown(SSL *s); + +__owur int dtls1_dispatch_alert(SSL *s); + +__owur int ssl_init_wbio_buffer(SSL *s); +int ssl_free_wbio_buffer(SSL *s); + +__owur int tls1_change_cipher_state(SSL *s, int which); +__owur int tls1_setup_key_block(SSL *s); +__owur size_t tls1_final_finish_mac(SSL *s, const char *str, size_t slen, + unsigned char *p); +__owur int tls1_generate_master_secret(SSL *s, unsigned char *out, + unsigned char *p, size_t len, + size_t *secret_size); +__owur int tls13_setup_key_block(SSL *s); +__owur size_t tls13_final_finish_mac(SSL *s, const char *str, size_t slen, + unsigned char *p); +__owur int tls13_change_cipher_state(SSL *s, int which); +__owur int tls13_update_key(SSL *s, int send); +__owur int tls13_hkdf_expand(SSL *s, const EVP_MD *md, + const unsigned char *secret, + const unsigned char *label, size_t labellen, + const unsigned char *data, size_t datalen, + unsigned char *out, size_t outlen, int fatal); +__owur int tls13_derive_key(SSL *s, const EVP_MD *md, + const unsigned char *secret, unsigned char *key, + size_t keylen); +__owur int tls13_derive_iv(SSL *s, const EVP_MD *md, + const unsigned char *secret, unsigned char *iv, + size_t ivlen); +__owur int tls13_derive_finishedkey(SSL *s, const EVP_MD *md, + const unsigned char *secret, + unsigned char *fin, size_t finlen); +int tls13_generate_secret(SSL *s, const EVP_MD *md, + const unsigned char *prevsecret, + const unsigned char *insecret, + size_t insecretlen, + unsigned char *outsecret); +__owur int tls13_generate_handshake_secret(SSL *s, + const unsigned char *insecret, + size_t insecretlen); +__owur int tls13_generate_master_secret(SSL *s, unsigned char *out, + unsigned char *prev, size_t prevlen, + size_t *secret_size); +__owur int tls1_export_keying_material(SSL *s, unsigned char *out, size_t olen, + const char *label, size_t llen, + const unsigned char *p, size_t plen, + int use_context); +__owur int tls13_export_keying_material(SSL *s, unsigned char *out, size_t olen, + const char *label, size_t llen, + const unsigned char *context, + size_t contextlen, int use_context); +__owur int tls13_export_keying_material_early(SSL *s, unsigned char *out, + size_t olen, const char *label, + size_t llen, + const unsigned char *context, + size_t contextlen); +__owur int tls1_alert_code(int code); +__owur int tls13_alert_code(int code); +__owur int ssl3_alert_code(int code); + +# ifndef OPENSSL_NO_EC +__owur int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s); +# endif + +SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n); + +# ifndef OPENSSL_NO_EC + +__owur const TLS_GROUP_INFO *tls1_group_id_lookup(uint16_t curve_id); +__owur int tls1_check_group_id(SSL *s, uint16_t group_id, int check_own_curves); +__owur uint16_t tls1_shared_group(SSL *s, int nmatch); +__owur int tls1_set_groups(uint16_t **pext, size_t *pextlen, + int *curves, size_t ncurves); +__owur int tls1_set_groups_list(uint16_t **pext, size_t *pextlen, + const char *str); +void tls1_get_formatlist(SSL *s, const unsigned char **pformats, + size_t *num_formats); +__owur int tls1_check_ec_tmp_key(SSL *s, unsigned long id); +__owur EVP_PKEY *ssl_generate_pkey_group(SSL *s, uint16_t id); +__owur EVP_PKEY *ssl_generate_param_group(uint16_t id); +# endif /* OPENSSL_NO_EC */ + +__owur int tls_curve_allowed(SSL *s, uint16_t curve, int op); +void tls1_get_supported_groups(SSL *s, const uint16_t **pgroups, + size_t *pgroupslen); + +__owur int tls1_set_server_sigalgs(SSL *s); + +__owur SSL_TICKET_STATUS tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello, + SSL_SESSION **ret); +__owur SSL_TICKET_STATUS tls_decrypt_ticket(SSL *s, const unsigned char *etick, + size_t eticklen, + const unsigned char *sess_id, + size_t sesslen, SSL_SESSION **psess); + +__owur int tls_use_ticket(SSL *s); + +void ssl_set_sig_mask(uint32_t *pmask_a, SSL *s, int op); + +__owur int tls1_set_sigalgs_list(CERT *c, const char *str, int client); +__owur int tls1_set_raw_sigalgs(CERT *c, const uint16_t *psigs, size_t salglen, + int client); +__owur int tls1_set_sigalgs(CERT *c, const int *salg, size_t salglen, + int client); +int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain, + int idx); +void tls1_set_cert_validity(SSL *s); + +# ifndef OPENSSL_NO_CT +__owur int ssl_validate_ct(SSL *s); +# endif + +# ifndef OPENSSL_NO_DH +__owur DH *ssl_get_auto_dh(SSL *s); +# endif + +__owur int ssl_security_cert(SSL *s, SSL_CTX *ctx, X509 *x, int vfy, int is_ee); +__owur int ssl_security_cert_chain(SSL *s, STACK_OF(X509) *sk, X509 *ex, + int vfy); + +int tls_choose_sigalg(SSL *s, int fatalerrs); + +__owur EVP_MD_CTX *ssl_replace_hash(EVP_MD_CTX **hash, const EVP_MD *md); +void ssl_clear_hash_ctx(EVP_MD_CTX **hash); +__owur long ssl_get_algorithm2(SSL *s); +__owur int tls12_copy_sigalgs(SSL *s, WPACKET *pkt, + const uint16_t *psig, size_t psiglen); +__owur int tls1_save_u16(PACKET *pkt, uint16_t **pdest, size_t *pdestlen); +__owur int tls1_save_sigalgs(SSL *s, PACKET *pkt, int cert); +__owur int tls1_process_sigalgs(SSL *s); +__owur int tls1_set_peer_legacy_sigalg(SSL *s, const EVP_PKEY *pkey); +__owur int tls1_lookup_md(const SIGALG_LOOKUP *lu, const EVP_MD **pmd); +__owur size_t tls12_get_psigalgs(SSL *s, int sent, const uint16_t **psigs); +# ifndef OPENSSL_NO_EC +__owur int tls_check_sigalg_curve(const SSL *s, int curve); +# endif +__owur int tls12_check_peer_sigalg(SSL *s, uint16_t, EVP_PKEY *pkey); +__owur int ssl_set_client_disabled(SSL *s); +__owur int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op, int echde); + +__owur int ssl_handshake_hash(SSL *s, unsigned char *out, size_t outlen, + size_t *hashlen); +__owur const EVP_MD *ssl_md(int idx); +__owur const EVP_MD *ssl_handshake_md(SSL *s); +__owur const EVP_MD *ssl_prf_md(SSL *s); + +/* + * ssl_log_rsa_client_key_exchange logs |premaster| to the SSL_CTX associated + * with |ssl|, if logging is enabled. It returns one on success and zero on + * failure. The entry is identified by the first 8 bytes of + * |encrypted_premaster|. + */ +__owur int ssl_log_rsa_client_key_exchange(SSL *ssl, + const uint8_t *encrypted_premaster, + size_t encrypted_premaster_len, + const uint8_t *premaster, + size_t premaster_len); + +/* + * ssl_log_secret logs |secret| to the SSL_CTX associated with |ssl|, if + * logging is available. It returns one on success and zero on failure. It tags + * the entry with |label|. + */ +__owur int ssl_log_secret(SSL *ssl, const char *label, + const uint8_t *secret, size_t secret_len); + +#define MASTER_SECRET_LABEL "CLIENT_RANDOM" +#define CLIENT_EARLY_LABEL "CLIENT_EARLY_TRAFFIC_SECRET" +#define CLIENT_HANDSHAKE_LABEL "CLIENT_HANDSHAKE_TRAFFIC_SECRET" +#define SERVER_HANDSHAKE_LABEL "SERVER_HANDSHAKE_TRAFFIC_SECRET" +#define CLIENT_APPLICATION_LABEL "CLIENT_TRAFFIC_SECRET_0" +#define SERVER_APPLICATION_LABEL "SERVER_TRAFFIC_SECRET_0" +#define EARLY_EXPORTER_SECRET_LABEL "EARLY_EXPORTER_SECRET" +#define EXPORTER_SECRET_LABEL "EXPORTER_SECRET" + +/* s3_cbc.c */ +__owur char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx); +__owur int ssl3_cbc_digest_record(const EVP_MD_CTX *ctx, + unsigned char *md_out, + size_t *md_out_size, + const unsigned char header[13], + const unsigned char *data, + size_t data_plus_mac_size, + size_t data_plus_mac_plus_padding_size, + const unsigned char *mac_secret, + size_t mac_secret_length, char is_sslv3); + +__owur int srp_generate_server_master_secret(SSL *s); +__owur int srp_generate_client_master_secret(SSL *s); +__owur int srp_verify_server_param(SSL *s); + +/* statem/statem_srvr.c */ + +__owur int send_certificate_request(SSL *s); + +/* statem/extensions_cust.c */ + +custom_ext_method *custom_ext_find(const custom_ext_methods *exts, + ENDPOINT role, unsigned int ext_type, + size_t *idx); + +void custom_ext_init(custom_ext_methods *meths); + +__owur int custom_ext_parse(SSL *s, unsigned int context, unsigned int ext_type, + const unsigned char *ext_data, size_t ext_size, + X509 *x, size_t chainidx); +__owur int custom_ext_add(SSL *s, int context, WPACKET *pkt, X509 *x, + size_t chainidx, int maxversion); + +__owur int custom_exts_copy(custom_ext_methods *dst, + const custom_ext_methods *src); +__owur int custom_exts_copy_flags(custom_ext_methods *dst, + const custom_ext_methods *src); +void custom_exts_free(custom_ext_methods *exts); + +void ssl_comp_free_compression_methods_int(void); + +/* ssl_mcnf.c */ +void ssl_ctx_system_config(SSL_CTX *ctx); + +# else /* OPENSSL_UNIT_TEST */ + +# define ssl_init_wbio_buffer SSL_test_functions()->p_ssl_init_wbio_buffer +# define ssl3_setup_buffers SSL_test_functions()->p_ssl3_setup_buffers + +# endif +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_mcnf.c b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_mcnf.c new file mode 100644 index 000000000..a0e265771 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_mcnf.c @@ -0,0 +1,99 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "ssl_locl.h" +#include "internal/sslconf.h" + +/* SSL library configuration module. */ + +void SSL_add_ssl_module(void) +{ + /* Do nothing. This will be added automatically by libcrypto */ +} + +static int ssl_do_config(SSL *s, SSL_CTX *ctx, const char *name, int system) +{ + SSL_CONF_CTX *cctx = NULL; + size_t i, idx, cmd_count; + int rv = 0; + unsigned int flags; + const SSL_METHOD *meth; + const SSL_CONF_CMD *cmds; + + if (s == NULL && ctx == NULL) { + SSLerr(SSL_F_SSL_DO_CONFIG, ERR_R_PASSED_NULL_PARAMETER); + goto err; + } + + if (name == NULL && system) + name = "system_default"; + if (!conf_ssl_name_find(name, &idx)) { + if (!system) { + SSLerr(SSL_F_SSL_DO_CONFIG, SSL_R_INVALID_CONFIGURATION_NAME); + ERR_add_error_data(2, "name=", name); + } + goto err; + } + cmds = conf_ssl_get(idx, &name, &cmd_count); + cctx = SSL_CONF_CTX_new(); + if (cctx == NULL) + goto err; + flags = SSL_CONF_FLAG_FILE; + if (!system) + flags |= SSL_CONF_FLAG_CERTIFICATE | SSL_CONF_FLAG_REQUIRE_PRIVATE; + if (s != NULL) { + meth = s->method; + SSL_CONF_CTX_set_ssl(cctx, s); + } else { + meth = ctx->method; + SSL_CONF_CTX_set_ssl_ctx(cctx, ctx); + } + if (meth->ssl_accept != ssl_undefined_function) + flags |= SSL_CONF_FLAG_SERVER; + if (meth->ssl_connect != ssl_undefined_function) + flags |= SSL_CONF_FLAG_CLIENT; + SSL_CONF_CTX_set_flags(cctx, flags); + for (i = 0; i < cmd_count; i++) { + char *cmdstr, *arg; + + conf_ssl_get_cmd(cmds, i, &cmdstr, &arg); + rv = SSL_CONF_cmd(cctx, cmdstr, arg); + if (rv <= 0) { + if (rv == -2) + SSLerr(SSL_F_SSL_DO_CONFIG, SSL_R_UNKNOWN_COMMAND); + else + SSLerr(SSL_F_SSL_DO_CONFIG, SSL_R_BAD_VALUE); + ERR_add_error_data(6, "section=", name, ", cmd=", cmdstr, + ", arg=", arg); + goto err; + } + } + rv = SSL_CONF_CTX_finish(cctx); + err: + SSL_CONF_CTX_free(cctx); + return rv <= 0 ? 0 : 1; +} + +int SSL_config(SSL *s, const char *name) +{ + return ssl_do_config(s, NULL, name, 0); +} + +int SSL_CTX_config(SSL_CTX *ctx, const char *name) +{ + return ssl_do_config(NULL, ctx, name, 0); +} + +void ssl_ctx_system_config(SSL_CTX *ctx) +{ + ssl_do_config(NULL, ctx, NULL, 1); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_rsa.c b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_rsa.c new file mode 100644 index 000000000..172e15f92 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_rsa.c @@ -0,0 +1,1148 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "ssl_locl.h" +#include "packet_locl.h" +#include +#include +#include +#include +#include + +static int ssl_set_cert(CERT *c, X509 *x509); +static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey); + +#define SYNTHV1CONTEXT (SSL_EXT_TLS1_2_AND_BELOW_ONLY \ + | SSL_EXT_CLIENT_HELLO \ + | SSL_EXT_TLS1_2_SERVER_HELLO \ + | SSL_EXT_IGNORE_ON_RESUMPTION) + +int SSL_use_certificate(SSL *ssl, X509 *x) +{ + int rv; + if (x == NULL) { + SSLerr(SSL_F_SSL_USE_CERTIFICATE, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + rv = ssl_security_cert(ssl, NULL, x, 0, 1); + if (rv != 1) { + SSLerr(SSL_F_SSL_USE_CERTIFICATE, rv); + return 0; + } + + return ssl_set_cert(ssl->cert, x); +} + +int SSL_use_certificate_file(SSL *ssl, const char *file, int type) +{ + int j; + BIO *in; + int ret = 0; + X509 *x = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, ERR_R_SYS_LIB); + goto end; + } + if (type == SSL_FILETYPE_ASN1) { + j = ERR_R_ASN1_LIB; + x = d2i_X509_bio(in, NULL); + } else if (type == SSL_FILETYPE_PEM) { + j = ERR_R_PEM_LIB; + x = PEM_read_bio_X509(in, NULL, ssl->default_passwd_callback, + ssl->default_passwd_callback_userdata); + } else { + SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, SSL_R_BAD_SSL_FILETYPE); + goto end; + } + + if (x == NULL) { + SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, j); + goto end; + } + + ret = SSL_use_certificate(ssl, x); + end: + X509_free(x); + BIO_free(in); + return ret; +} + +int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len) +{ + X509 *x; + int ret; + + x = d2i_X509(NULL, &d, (long)len); + if (x == NULL) { + SSLerr(SSL_F_SSL_USE_CERTIFICATE_ASN1, ERR_R_ASN1_LIB); + return 0; + } + + ret = SSL_use_certificate(ssl, x); + X509_free(x); + return ret; +} + +#ifndef OPENSSL_NO_RSA +int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) +{ + EVP_PKEY *pkey; + int ret; + + if (rsa == NULL) { + SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if ((pkey = EVP_PKEY_new()) == NULL) { + SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY, ERR_R_EVP_LIB); + return 0; + } + + RSA_up_ref(rsa); + if (EVP_PKEY_assign_RSA(pkey, rsa) <= 0) { + RSA_free(rsa); + EVP_PKEY_free(pkey); + return 0; + } + + ret = ssl_set_pkey(ssl->cert, pkey); + EVP_PKEY_free(pkey); + return ret; +} +#endif + +static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey) +{ + size_t i; + + if (ssl_cert_lookup_by_pkey(pkey, &i) == NULL) { + SSLerr(SSL_F_SSL_SET_PKEY, SSL_R_UNKNOWN_CERTIFICATE_TYPE); + return 0; + } + + if (c->pkeys[i].x509 != NULL) { + EVP_PKEY *pktmp; + pktmp = X509_get0_pubkey(c->pkeys[i].x509); + if (pktmp == NULL) { + SSLerr(SSL_F_SSL_SET_PKEY, ERR_R_MALLOC_FAILURE); + return 0; + } + /* + * The return code from EVP_PKEY_copy_parameters is deliberately + * ignored. Some EVP_PKEY types cannot do this. + */ + EVP_PKEY_copy_parameters(pktmp, pkey); + ERR_clear_error(); + +#ifndef OPENSSL_NO_RSA + /* + * Don't check the public/private key, this is mostly for smart + * cards. + */ + if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA + && RSA_flags(EVP_PKEY_get0_RSA(pkey)) & RSA_METHOD_FLAG_NO_CHECK) ; + else +#endif + if (!X509_check_private_key(c->pkeys[i].x509, pkey)) { + X509_free(c->pkeys[i].x509); + c->pkeys[i].x509 = NULL; + return 0; + } + } + + EVP_PKEY_free(c->pkeys[i].privatekey); + EVP_PKEY_up_ref(pkey); + c->pkeys[i].privatekey = pkey; + c->key = &c->pkeys[i]; + return 1; +} + +#ifndef OPENSSL_NO_RSA +int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type) +{ + int j, ret = 0; + BIO *in; + RSA *rsa = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE, ERR_R_SYS_LIB); + goto end; + } + if (type == SSL_FILETYPE_ASN1) { + j = ERR_R_ASN1_LIB; + rsa = d2i_RSAPrivateKey_bio(in, NULL); + } else if (type == SSL_FILETYPE_PEM) { + j = ERR_R_PEM_LIB; + rsa = PEM_read_bio_RSAPrivateKey(in, NULL, + ssl->default_passwd_callback, + ssl->default_passwd_callback_userdata); + } else { + SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE, SSL_R_BAD_SSL_FILETYPE); + goto end; + } + if (rsa == NULL) { + SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE, j); + goto end; + } + ret = SSL_use_RSAPrivateKey(ssl, rsa); + RSA_free(rsa); + end: + BIO_free(in); + return ret; +} + +int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const unsigned char *d, long len) +{ + int ret; + const unsigned char *p; + RSA *rsa; + + p = d; + if ((rsa = d2i_RSAPrivateKey(NULL, &p, (long)len)) == NULL) { + SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1, ERR_R_ASN1_LIB); + return 0; + } + + ret = SSL_use_RSAPrivateKey(ssl, rsa); + RSA_free(rsa); + return ret; +} +#endif /* !OPENSSL_NO_RSA */ + +int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) +{ + int ret; + + if (pkey == NULL) { + SSLerr(SSL_F_SSL_USE_PRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + ret = ssl_set_pkey(ssl->cert, pkey); + return ret; +} + +int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type) +{ + int j, ret = 0; + BIO *in; + EVP_PKEY *pkey = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE, ERR_R_SYS_LIB); + goto end; + } + if (type == SSL_FILETYPE_PEM) { + j = ERR_R_PEM_LIB; + pkey = PEM_read_bio_PrivateKey(in, NULL, + ssl->default_passwd_callback, + ssl->default_passwd_callback_userdata); + } else if (type == SSL_FILETYPE_ASN1) { + j = ERR_R_ASN1_LIB; + pkey = d2i_PrivateKey_bio(in, NULL); + } else { + SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE, SSL_R_BAD_SSL_FILETYPE); + goto end; + } + if (pkey == NULL) { + SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE, j); + goto end; + } + ret = SSL_use_PrivateKey(ssl, pkey); + EVP_PKEY_free(pkey); + end: + BIO_free(in); + return ret; +} + +int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const unsigned char *d, + long len) +{ + int ret; + const unsigned char *p; + EVP_PKEY *pkey; + + p = d; + if ((pkey = d2i_PrivateKey(type, NULL, &p, (long)len)) == NULL) { + SSLerr(SSL_F_SSL_USE_PRIVATEKEY_ASN1, ERR_R_ASN1_LIB); + return 0; + } + + ret = SSL_use_PrivateKey(ssl, pkey); + EVP_PKEY_free(pkey); + return ret; +} + +int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) +{ + int rv; + if (x == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + rv = ssl_security_cert(NULL, ctx, x, 0, 1); + if (rv != 1) { + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE, rv); + return 0; + } + return ssl_set_cert(ctx->cert, x); +} + +static int ssl_set_cert(CERT *c, X509 *x) +{ + EVP_PKEY *pkey; + size_t i; + + pkey = X509_get0_pubkey(x); + if (pkey == NULL) { + SSLerr(SSL_F_SSL_SET_CERT, SSL_R_X509_LIB); + return 0; + } + + if (ssl_cert_lookup_by_pkey(pkey, &i) == NULL) { + SSLerr(SSL_F_SSL_SET_CERT, SSL_R_UNKNOWN_CERTIFICATE_TYPE); + return 0; + } +#ifndef OPENSSL_NO_EC + if (i == SSL_PKEY_ECC && !EC_KEY_can_sign(EVP_PKEY_get0_EC_KEY(pkey))) { + SSLerr(SSL_F_SSL_SET_CERT, SSL_R_ECC_CERT_NOT_FOR_SIGNING); + return 0; + } +#endif + if (c->pkeys[i].privatekey != NULL) { + /* + * The return code from EVP_PKEY_copy_parameters is deliberately + * ignored. Some EVP_PKEY types cannot do this. + */ + EVP_PKEY_copy_parameters(pkey, c->pkeys[i].privatekey); + ERR_clear_error(); + +#ifndef OPENSSL_NO_RSA + /* + * Don't check the public/private key, this is mostly for smart + * cards. + */ + if (EVP_PKEY_id(c->pkeys[i].privatekey) == EVP_PKEY_RSA + && RSA_flags(EVP_PKEY_get0_RSA(c->pkeys[i].privatekey)) & + RSA_METHOD_FLAG_NO_CHECK) ; + else +#endif /* OPENSSL_NO_RSA */ + if (!X509_check_private_key(x, c->pkeys[i].privatekey)) { + /* + * don't fail for a cert/key mismatch, just free current private + * key (when switching to a different cert & key, first this + * function should be used, then ssl_set_pkey + */ + EVP_PKEY_free(c->pkeys[i].privatekey); + c->pkeys[i].privatekey = NULL; + /* clear error queue */ + ERR_clear_error(); + } + } + + X509_free(c->pkeys[i].x509); + X509_up_ref(x); + c->pkeys[i].x509 = x; + c->key = &(c->pkeys[i]); + + return 1; +} + +int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type) +{ + int j; + BIO *in; + int ret = 0; + X509 *x = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_SYS_LIB); + goto end; + } + if (type == SSL_FILETYPE_ASN1) { + j = ERR_R_ASN1_LIB; + x = d2i_X509_bio(in, NULL); + } else if (type == SSL_FILETYPE_PEM) { + j = ERR_R_PEM_LIB; + x = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, + ctx->default_passwd_callback_userdata); + } else { + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, SSL_R_BAD_SSL_FILETYPE); + goto end; + } + + if (x == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, j); + goto end; + } + + ret = SSL_CTX_use_certificate(ctx, x); + end: + X509_free(x); + BIO_free(in); + return ret; +} + +int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const unsigned char *d) +{ + X509 *x; + int ret; + + x = d2i_X509(NULL, &d, (long)len); + if (x == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1, ERR_R_ASN1_LIB); + return 0; + } + + ret = SSL_CTX_use_certificate(ctx, x); + X509_free(x); + return ret; +} + +#ifndef OPENSSL_NO_RSA +int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa) +{ + int ret; + EVP_PKEY *pkey; + + if (rsa == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if ((pkey = EVP_PKEY_new()) == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY, ERR_R_EVP_LIB); + return 0; + } + + RSA_up_ref(rsa); + if (EVP_PKEY_assign_RSA(pkey, rsa) <= 0) { + RSA_free(rsa); + EVP_PKEY_free(pkey); + return 0; + } + + ret = ssl_set_pkey(ctx->cert, pkey); + EVP_PKEY_free(pkey); + return ret; +} + +int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type) +{ + int j, ret = 0; + BIO *in; + RSA *rsa = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE, ERR_R_SYS_LIB); + goto end; + } + if (type == SSL_FILETYPE_ASN1) { + j = ERR_R_ASN1_LIB; + rsa = d2i_RSAPrivateKey_bio(in, NULL); + } else if (type == SSL_FILETYPE_PEM) { + j = ERR_R_PEM_LIB; + rsa = PEM_read_bio_RSAPrivateKey(in, NULL, + ctx->default_passwd_callback, + ctx->default_passwd_callback_userdata); + } else { + SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE, SSL_R_BAD_SSL_FILETYPE); + goto end; + } + if (rsa == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE, j); + goto end; + } + ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa); + RSA_free(rsa); + end: + BIO_free(in); + return ret; +} + +int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, + long len) +{ + int ret; + const unsigned char *p; + RSA *rsa; + + p = d; + if ((rsa = d2i_RSAPrivateKey(NULL, &p, (long)len)) == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1, ERR_R_ASN1_LIB); + return 0; + } + + ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa); + RSA_free(rsa); + return ret; +} +#endif /* !OPENSSL_NO_RSA */ + +int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) +{ + if (pkey == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + return ssl_set_pkey(ctx->cert, pkey); +} + +int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type) +{ + int j, ret = 0; + BIO *in; + EVP_PKEY *pkey = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, ERR_R_SYS_LIB); + goto end; + } + if (type == SSL_FILETYPE_PEM) { + j = ERR_R_PEM_LIB; + pkey = PEM_read_bio_PrivateKey(in, NULL, + ctx->default_passwd_callback, + ctx->default_passwd_callback_userdata); + } else if (type == SSL_FILETYPE_ASN1) { + j = ERR_R_ASN1_LIB; + pkey = d2i_PrivateKey_bio(in, NULL); + } else { + SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, SSL_R_BAD_SSL_FILETYPE); + goto end; + } + if (pkey == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, j); + goto end; + } + ret = SSL_CTX_use_PrivateKey(ctx, pkey); + EVP_PKEY_free(pkey); + end: + BIO_free(in); + return ret; +} + +int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, + const unsigned char *d, long len) +{ + int ret; + const unsigned char *p; + EVP_PKEY *pkey; + + p = d; + if ((pkey = d2i_PrivateKey(type, NULL, &p, (long)len)) == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1, ERR_R_ASN1_LIB); + return 0; + } + + ret = SSL_CTX_use_PrivateKey(ctx, pkey); + EVP_PKEY_free(pkey); + return ret; +} + +/* + * Read a file that contains our certificate in "PEM" format, possibly + * followed by a sequence of CA certificates that should be sent to the peer + * in the Certificate message. + */ +static int use_certificate_chain_file(SSL_CTX *ctx, SSL *ssl, const char *file) +{ + BIO *in; + int ret = 0; + X509 *x = NULL; + pem_password_cb *passwd_callback; + void *passwd_callback_userdata; + + ERR_clear_error(); /* clear error stack for + * SSL_CTX_use_certificate() */ + + if (ctx != NULL) { + passwd_callback = ctx->default_passwd_callback; + passwd_callback_userdata = ctx->default_passwd_callback_userdata; + } else { + passwd_callback = ssl->default_passwd_callback; + passwd_callback_userdata = ssl->default_passwd_callback_userdata; + } + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + SSLerr(SSL_F_USE_CERTIFICATE_CHAIN_FILE, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + SSLerr(SSL_F_USE_CERTIFICATE_CHAIN_FILE, ERR_R_SYS_LIB); + goto end; + } + + x = PEM_read_bio_X509_AUX(in, NULL, passwd_callback, + passwd_callback_userdata); + if (x == NULL) { + SSLerr(SSL_F_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB); + goto end; + } + + if (ctx) + ret = SSL_CTX_use_certificate(ctx, x); + else + ret = SSL_use_certificate(ssl, x); + + if (ERR_peek_error() != 0) + ret = 0; /* Key/certificate mismatch doesn't imply + * ret==0 ... */ + if (ret) { + /* + * If we could set up our certificate, now proceed to the CA + * certificates. + */ + X509 *ca; + int r; + unsigned long err; + + if (ctx) + r = SSL_CTX_clear_chain_certs(ctx); + else + r = SSL_clear_chain_certs(ssl); + + if (r == 0) { + ret = 0; + goto end; + } + + while ((ca = PEM_read_bio_X509(in, NULL, passwd_callback, + passwd_callback_userdata)) + != NULL) { + if (ctx) + r = SSL_CTX_add0_chain_cert(ctx, ca); + else + r = SSL_add0_chain_cert(ssl, ca); + /* + * Note that we must not free ca if it was successfully added to + * the chain (while we must free the main certificate, since its + * reference count is increased by SSL_CTX_use_certificate). + */ + if (!r) { + X509_free(ca); + ret = 0; + goto end; + } + } + /* When the while loop ends, it's usually just EOF. */ + err = ERR_peek_last_error(); + if (ERR_GET_LIB(err) == ERR_LIB_PEM + && ERR_GET_REASON(err) == PEM_R_NO_START_LINE) + ERR_clear_error(); + else + ret = 0; /* some real error */ + } + + end: + X509_free(x); + BIO_free(in); + return ret; +} + +int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) +{ + return use_certificate_chain_file(ctx, NULL, file); +} + +int SSL_use_certificate_chain_file(SSL *ssl, const char *file) +{ + return use_certificate_chain_file(NULL, ssl, file); +} + +static int serverinfo_find_extension(const unsigned char *serverinfo, + size_t serverinfo_length, + unsigned int extension_type, + const unsigned char **extension_data, + size_t *extension_length) +{ + PACKET pkt, data; + + *extension_data = NULL; + *extension_length = 0; + if (serverinfo == NULL || serverinfo_length == 0) + return -1; + + if (!PACKET_buf_init(&pkt, serverinfo, serverinfo_length)) + return -1; + + for (;;) { + unsigned int type = 0; + unsigned long context = 0; + + /* end of serverinfo */ + if (PACKET_remaining(&pkt) == 0) + return 0; /* Extension not found */ + + if (!PACKET_get_net_4(&pkt, &context) + || !PACKET_get_net_2(&pkt, &type) + || !PACKET_get_length_prefixed_2(&pkt, &data)) + return -1; + + if (type == extension_type) { + *extension_data = PACKET_data(&data); + *extension_length = PACKET_remaining(&data);; + return 1; /* Success */ + } + } + /* Unreachable */ +} + +static int serverinfoex_srv_parse_cb(SSL *s, unsigned int ext_type, + unsigned int context, + const unsigned char *in, + size_t inlen, X509 *x, size_t chainidx, + int *al, void *arg) +{ + + if (inlen != 0) { + *al = SSL_AD_DECODE_ERROR; + return 0; + } + + return 1; +} + +static int serverinfo_srv_parse_cb(SSL *s, unsigned int ext_type, + const unsigned char *in, + size_t inlen, int *al, void *arg) +{ + return serverinfoex_srv_parse_cb(s, ext_type, 0, in, inlen, NULL, 0, al, + arg); +} + +static int serverinfoex_srv_add_cb(SSL *s, unsigned int ext_type, + unsigned int context, + const unsigned char **out, + size_t *outlen, X509 *x, size_t chainidx, + int *al, void *arg) +{ + const unsigned char *serverinfo = NULL; + size_t serverinfo_length = 0; + + /* We only support extensions for the first Certificate */ + if ((context & SSL_EXT_TLS1_3_CERTIFICATE) != 0 && chainidx > 0) + return 0; + + /* Is there serverinfo data for the chosen server cert? */ + if ((ssl_get_server_cert_serverinfo(s, &serverinfo, + &serverinfo_length)) != 0) { + /* Find the relevant extension from the serverinfo */ + int retval = serverinfo_find_extension(serverinfo, serverinfo_length, + ext_type, out, outlen); + if (retval == -1) { + *al = SSL_AD_INTERNAL_ERROR; + return -1; /* Error */ + } + if (retval == 0) + return 0; /* No extension found, don't send extension */ + return 1; /* Send extension */ + } + return 0; /* No serverinfo data found, don't send + * extension */ +} + +static int serverinfo_srv_add_cb(SSL *s, unsigned int ext_type, + const unsigned char **out, size_t *outlen, + int *al, void *arg) +{ + return serverinfoex_srv_add_cb(s, ext_type, 0, out, outlen, NULL, 0, al, + arg); +} + +/* + * With a NULL context, this function just checks that the serverinfo data + * parses correctly. With a non-NULL context, it registers callbacks for + * the included extensions. + */ +static int serverinfo_process_buffer(unsigned int version, + const unsigned char *serverinfo, + size_t serverinfo_length, SSL_CTX *ctx) +{ + PACKET pkt; + + if (serverinfo == NULL || serverinfo_length == 0) + return 0; + + if (version != SSL_SERVERINFOV1 && version != SSL_SERVERINFOV2) + return 0; + + if (!PACKET_buf_init(&pkt, serverinfo, serverinfo_length)) + return 0; + + while (PACKET_remaining(&pkt)) { + unsigned long context = 0; + unsigned int ext_type = 0; + PACKET data; + + if ((version == SSL_SERVERINFOV2 && !PACKET_get_net_4(&pkt, &context)) + || !PACKET_get_net_2(&pkt, &ext_type) + || !PACKET_get_length_prefixed_2(&pkt, &data)) + return 0; + + if (ctx == NULL) + continue; + + /* + * The old style custom extensions API could be set separately for + * server/client, i.e. you could set one custom extension for a client, + * and *for the same extension in the same SSL_CTX* you could set a + * custom extension for the server as well. It seems quite weird to be + * setting a custom extension for both client and server in a single + * SSL_CTX - but theoretically possible. This isn't possible in the + * new API. Therefore, if we have V1 serverinfo we use the old API. We + * also use the old API even if we have V2 serverinfo but the context + * looks like an old style <= TLSv1.2 extension. + */ + if (version == SSL_SERVERINFOV1 || context == SYNTHV1CONTEXT) { + if (!SSL_CTX_add_server_custom_ext(ctx, ext_type, + serverinfo_srv_add_cb, + NULL, NULL, + serverinfo_srv_parse_cb, + NULL)) + return 0; + } else { + if (!SSL_CTX_add_custom_ext(ctx, ext_type, context, + serverinfoex_srv_add_cb, + NULL, NULL, + serverinfoex_srv_parse_cb, + NULL)) + return 0; + } + } + + return 1; +} + +int SSL_CTX_use_serverinfo_ex(SSL_CTX *ctx, unsigned int version, + const unsigned char *serverinfo, + size_t serverinfo_length) +{ + unsigned char *new_serverinfo; + + if (ctx == NULL || serverinfo == NULL || serverinfo_length == 0) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_EX, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (!serverinfo_process_buffer(version, serverinfo, serverinfo_length, + NULL)) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_EX, SSL_R_INVALID_SERVERINFO_DATA); + return 0; + } + if (ctx->cert->key == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_EX, ERR_R_INTERNAL_ERROR); + return 0; + } + new_serverinfo = OPENSSL_realloc(ctx->cert->key->serverinfo, + serverinfo_length); + if (new_serverinfo == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_EX, ERR_R_MALLOC_FAILURE); + return 0; + } + ctx->cert->key->serverinfo = new_serverinfo; + memcpy(ctx->cert->key->serverinfo, serverinfo, serverinfo_length); + ctx->cert->key->serverinfo_length = serverinfo_length; + + /* + * Now that the serverinfo is validated and stored, go ahead and + * register callbacks. + */ + if (!serverinfo_process_buffer(version, serverinfo, serverinfo_length, + ctx)) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_EX, SSL_R_INVALID_SERVERINFO_DATA); + return 0; + } + return 1; +} + +int SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo, + size_t serverinfo_length) +{ + return SSL_CTX_use_serverinfo_ex(ctx, SSL_SERVERINFOV1, serverinfo, + serverinfo_length); +} + +int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file) +{ + unsigned char *serverinfo = NULL; + unsigned char *tmp; + size_t serverinfo_length = 0; + unsigned char *extension = 0; + long extension_length = 0; + char *name = NULL; + char *header = NULL; + char namePrefix1[] = "SERVERINFO FOR "; + char namePrefix2[] = "SERVERINFOV2 FOR "; + int ret = 0; + BIO *bin = NULL; + size_t num_extensions = 0, contextoff = 0; + + if (ctx == NULL || file == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_PASSED_NULL_PARAMETER); + goto end; + } + + bin = BIO_new(BIO_s_file()); + if (bin == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_BUF_LIB); + goto end; + } + if (BIO_read_filename(bin, file) <= 0) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_SYS_LIB); + goto end; + } + + for (num_extensions = 0;; num_extensions++) { + unsigned int version; + + if (PEM_read_bio(bin, &name, &header, &extension, &extension_length) + == 0) { + /* + * There must be at least one extension in this file + */ + if (num_extensions == 0) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, + SSL_R_NO_PEM_EXTENSIONS); + goto end; + } else /* End of file, we're done */ + break; + } + /* Check that PEM name starts with "BEGIN SERVERINFO FOR " */ + if (strlen(name) < strlen(namePrefix1)) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, SSL_R_PEM_NAME_TOO_SHORT); + goto end; + } + if (strncmp(name, namePrefix1, strlen(namePrefix1)) == 0) { + version = SSL_SERVERINFOV1; + } else { + if (strlen(name) < strlen(namePrefix2)) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, + SSL_R_PEM_NAME_TOO_SHORT); + goto end; + } + if (strncmp(name, namePrefix2, strlen(namePrefix2)) != 0) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, + SSL_R_PEM_NAME_BAD_PREFIX); + goto end; + } + version = SSL_SERVERINFOV2; + } + /* + * Check that the decoded PEM data is plausible (valid length field) + */ + if (version == SSL_SERVERINFOV1) { + /* 4 byte header: 2 bytes type, 2 bytes len */ + if (extension_length < 4 + || (extension[2] << 8) + extension[3] + != extension_length - 4) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, SSL_R_BAD_DATA); + goto end; + } + /* + * File does not have a context value so we must take account of + * this later. + */ + contextoff = 4; + } else { + /* 8 byte header: 4 bytes context, 2 bytes type, 2 bytes len */ + if (extension_length < 8 + || (extension[6] << 8) + extension[7] + != extension_length - 8) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, SSL_R_BAD_DATA); + goto end; + } + } + /* Append the decoded extension to the serverinfo buffer */ + tmp = OPENSSL_realloc(serverinfo, serverinfo_length + extension_length + + contextoff); + if (tmp == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_MALLOC_FAILURE); + goto end; + } + serverinfo = tmp; + if (contextoff > 0) { + unsigned char *sinfo = serverinfo + serverinfo_length; + + /* We know this only uses the last 2 bytes */ + sinfo[0] = 0; + sinfo[1] = 0; + sinfo[2] = (SYNTHV1CONTEXT >> 8) & 0xff; + sinfo[3] = SYNTHV1CONTEXT & 0xff; + } + memcpy(serverinfo + serverinfo_length + contextoff, + extension, extension_length); + serverinfo_length += extension_length + contextoff; + + OPENSSL_free(name); + name = NULL; + OPENSSL_free(header); + header = NULL; + OPENSSL_free(extension); + extension = NULL; + } + + ret = SSL_CTX_use_serverinfo_ex(ctx, SSL_SERVERINFOV2, serverinfo, + serverinfo_length); + end: + /* SSL_CTX_use_serverinfo makes a local copy of the serverinfo. */ + OPENSSL_free(name); + OPENSSL_free(header); + OPENSSL_free(extension); + OPENSSL_free(serverinfo); + BIO_free(bin); + return ret; +} + +static int ssl_set_cert_and_key(SSL *ssl, SSL_CTX *ctx, X509 *x509, EVP_PKEY *privatekey, + STACK_OF(X509) *chain, int override) +{ + int ret = 0; + size_t i; + int j; + int rv; + CERT *c = ssl != NULL ? ssl->cert : ctx->cert; + STACK_OF(X509) *dup_chain = NULL; + EVP_PKEY *pubkey = NULL; + + /* Do all security checks before anything else */ + rv = ssl_security_cert(ssl, ctx, x509, 0, 1); + if (rv != 1) { + SSLerr(SSL_F_SSL_SET_CERT_AND_KEY, rv); + goto out; + } + for (j = 0; j < sk_X509_num(chain); j++) { + rv = ssl_security_cert(ssl, ctx, sk_X509_value(chain, j), 0, 0); + if (rv != 1) { + SSLerr(SSL_F_SSL_SET_CERT_AND_KEY, rv); + goto out; + } + } + + pubkey = X509_get_pubkey(x509); /* bumps reference */ + if (pubkey == NULL) + goto out; + if (privatekey == NULL) { + privatekey = pubkey; + } else { + /* For RSA, which has no parameters, missing returns 0 */ + if (EVP_PKEY_missing_parameters(privatekey)) { + if (EVP_PKEY_missing_parameters(pubkey)) { + /* nobody has parameters? - error */ + SSLerr(SSL_F_SSL_SET_CERT_AND_KEY, SSL_R_MISSING_PARAMETERS); + goto out; + } else { + /* copy to privatekey from pubkey */ + EVP_PKEY_copy_parameters(privatekey, pubkey); + } + } else if (EVP_PKEY_missing_parameters(pubkey)) { + /* copy to pubkey from privatekey */ + EVP_PKEY_copy_parameters(pubkey, privatekey); + } /* else both have parameters */ + + /* Copied from ssl_set_cert/pkey */ +#ifndef OPENSSL_NO_RSA + if ((EVP_PKEY_id(privatekey) == EVP_PKEY_RSA) && + ((RSA_flags(EVP_PKEY_get0_RSA(privatekey)) & RSA_METHOD_FLAG_NO_CHECK))) + /* no-op */ ; + else +#endif + /* check that key <-> cert match */ + if (EVP_PKEY_cmp(pubkey, privatekey) != 1) { + SSLerr(SSL_F_SSL_SET_CERT_AND_KEY, SSL_R_PRIVATE_KEY_MISMATCH); + goto out; + } + } + if (ssl_cert_lookup_by_pkey(pubkey, &i) == NULL) { + SSLerr(SSL_F_SSL_SET_CERT_AND_KEY, SSL_R_UNKNOWN_CERTIFICATE_TYPE); + goto out; + } + + if (!override && (c->pkeys[i].x509 != NULL + || c->pkeys[i].privatekey != NULL + || c->pkeys[i].chain != NULL)) { + /* No override, and something already there */ + SSLerr(SSL_F_SSL_SET_CERT_AND_KEY, SSL_R_NOT_REPLACING_CERTIFICATE); + goto out; + } + + if (chain != NULL) { + dup_chain = X509_chain_up_ref(chain); + if (dup_chain == NULL) { + SSLerr(SSL_F_SSL_SET_CERT_AND_KEY, ERR_R_MALLOC_FAILURE); + goto out; + } + } + + sk_X509_pop_free(c->pkeys[i].chain, X509_free); + c->pkeys[i].chain = dup_chain; + + X509_free(c->pkeys[i].x509); + X509_up_ref(x509); + c->pkeys[i].x509 = x509; + + EVP_PKEY_free(c->pkeys[i].privatekey); + EVP_PKEY_up_ref(privatekey); + c->pkeys[i].privatekey = privatekey; + + c->key = &(c->pkeys[i]); + + ret = 1; + out: + EVP_PKEY_free(pubkey); + return ret; +} + +int SSL_use_cert_and_key(SSL *ssl, X509 *x509, EVP_PKEY *privatekey, + STACK_OF(X509) *chain, int override) +{ + return ssl_set_cert_and_key(ssl, NULL, x509, privatekey, chain, override); +} + +int SSL_CTX_use_cert_and_key(SSL_CTX *ctx, X509 *x509, EVP_PKEY *privatekey, + STACK_OF(X509) *chain, int override) +{ + return ssl_set_cert_and_key(NULL, ctx, x509, privatekey, chain, override); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_sess.c b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_sess.c new file mode 100644 index 000000000..5ad2792a1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_sess.c @@ -0,0 +1,1317 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2005 Nokia. All rights reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "internal/refcount.h" +#include "internal/cryptlib.h" +#include "ssl_locl.h" +#include "statem/statem_locl.h" + +static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s); +static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s); +static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck); + +/* + * SSL_get_session() and SSL_get1_session() are problematic in TLS1.3 because, + * unlike in earlier protocol versions, the session ticket may not have been + * sent yet even though a handshake has finished. The session ticket data could + * come in sometime later...or even change if multiple session ticket messages + * are sent from the server. The preferred way for applications to obtain + * a resumable session is to use SSL_CTX_sess_set_new_cb(). + */ + +SSL_SESSION *SSL_get_session(const SSL *ssl) +/* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */ +{ + return ssl->session; +} + +SSL_SESSION *SSL_get1_session(SSL *ssl) +/* variant of SSL_get_session: caller really gets something */ +{ + SSL_SESSION *sess; + /* + * Need to lock this all up rather than just use CRYPTO_add so that + * somebody doesn't free ssl->session between when we check it's non-null + * and when we up the reference count. + */ + CRYPTO_THREAD_read_lock(ssl->lock); + sess = ssl->session; + if (sess) + SSL_SESSION_up_ref(sess); + CRYPTO_THREAD_unlock(ssl->lock); + return sess; +} + +int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg) +{ + return CRYPTO_set_ex_data(&s->ex_data, idx, arg); +} + +void *SSL_SESSION_get_ex_data(const SSL_SESSION *s, int idx) +{ + return CRYPTO_get_ex_data(&s->ex_data, idx); +} + +SSL_SESSION *SSL_SESSION_new(void) +{ + SSL_SESSION *ss; + + if (!OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL)) + return NULL; + + ss = OPENSSL_zalloc(sizeof(*ss)); + if (ss == NULL) { + SSLerr(SSL_F_SSL_SESSION_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */ + ss->references = 1; + ss->timeout = 60 * 5 + 4; /* 5 minute timeout by default */ + ss->time = (unsigned long)time(NULL); + ss->lock = CRYPTO_THREAD_lock_new(); + if (ss->lock == NULL) { + SSLerr(SSL_F_SSL_SESSION_NEW, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ss); + return NULL; + } + + if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data)) { + CRYPTO_THREAD_lock_free(ss->lock); + OPENSSL_free(ss); + return NULL; + } + return ss; +} + +SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *src) +{ + return ssl_session_dup(src, 1); +} + +/* + * Create a new SSL_SESSION and duplicate the contents of |src| into it. If + * ticket == 0 then no ticket information is duplicated, otherwise it is. + */ +SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket) +{ + SSL_SESSION *dest; + + dest = OPENSSL_malloc(sizeof(*src)); + if (dest == NULL) { + goto err; + } + memcpy(dest, src, sizeof(*dest)); + + /* + * Set the various pointers to NULL so that we can call SSL_SESSION_free in + * the case of an error whilst halfway through constructing dest + */ +#ifndef OPENSSL_NO_PSK + dest->psk_identity_hint = NULL; + dest->psk_identity = NULL; +#endif + dest->ciphers = NULL; + dest->ext.hostname = NULL; +#ifndef OPENSSL_NO_EC + dest->ext.ecpointformats = NULL; + dest->ext.supportedgroups = NULL; +#endif + dest->ext.tick = NULL; + dest->ext.alpn_selected = NULL; +#ifndef OPENSSL_NO_SRP + dest->srp_username = NULL; +#endif + dest->peer_chain = NULL; + dest->peer = NULL; + dest->ticket_appdata = NULL; + memset(&dest->ex_data, 0, sizeof(dest->ex_data)); + + /* We deliberately don't copy the prev and next pointers */ + dest->prev = NULL; + dest->next = NULL; + + dest->references = 1; + + dest->lock = CRYPTO_THREAD_lock_new(); + if (dest->lock == NULL) + goto err; + + if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, dest, &dest->ex_data)) + goto err; + + if (src->peer != NULL) { + if (!X509_up_ref(src->peer)) + goto err; + dest->peer = src->peer; + } + + if (src->peer_chain != NULL) { + dest->peer_chain = X509_chain_up_ref(src->peer_chain); + if (dest->peer_chain == NULL) + goto err; + } +#ifndef OPENSSL_NO_PSK + if (src->psk_identity_hint) { + dest->psk_identity_hint = OPENSSL_strdup(src->psk_identity_hint); + if (dest->psk_identity_hint == NULL) { + goto err; + } + } + if (src->psk_identity) { + dest->psk_identity = OPENSSL_strdup(src->psk_identity); + if (dest->psk_identity == NULL) { + goto err; + } + } +#endif + + if (src->ciphers != NULL) { + dest->ciphers = sk_SSL_CIPHER_dup(src->ciphers); + if (dest->ciphers == NULL) + goto err; + } + + if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, + &dest->ex_data, &src->ex_data)) { + goto err; + } + + if (src->ext.hostname) { + dest->ext.hostname = OPENSSL_strdup(src->ext.hostname); + if (dest->ext.hostname == NULL) { + goto err; + } + } +#ifndef OPENSSL_NO_EC + if (src->ext.ecpointformats) { + dest->ext.ecpointformats = + OPENSSL_memdup(src->ext.ecpointformats, + src->ext.ecpointformats_len); + if (dest->ext.ecpointformats == NULL) + goto err; + } + if (src->ext.supportedgroups) { + dest->ext.supportedgroups = + OPENSSL_memdup(src->ext.supportedgroups, + src->ext.supportedgroups_len + * sizeof(*src->ext.supportedgroups)); + if (dest->ext.supportedgroups == NULL) + goto err; + } +#endif + + if (ticket != 0 && src->ext.tick != NULL) { + dest->ext.tick = + OPENSSL_memdup(src->ext.tick, src->ext.ticklen); + if (dest->ext.tick == NULL) + goto err; + } else { + dest->ext.tick_lifetime_hint = 0; + dest->ext.ticklen = 0; + } + + if (src->ext.alpn_selected != NULL) { + dest->ext.alpn_selected = OPENSSL_memdup(src->ext.alpn_selected, + src->ext.alpn_selected_len); + if (dest->ext.alpn_selected == NULL) + goto err; + } + +#ifndef OPENSSL_NO_SRP + if (src->srp_username) { + dest->srp_username = OPENSSL_strdup(src->srp_username); + if (dest->srp_username == NULL) { + goto err; + } + } +#endif + + if (src->ticket_appdata != NULL) { + dest->ticket_appdata = + OPENSSL_memdup(src->ticket_appdata, src->ticket_appdata_len); + if (dest->ticket_appdata == NULL) + goto err; + } + + return dest; + err: + SSLerr(SSL_F_SSL_SESSION_DUP, ERR_R_MALLOC_FAILURE); + SSL_SESSION_free(dest); + return NULL; +} + +const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len) +{ + if (len) + *len = (unsigned int)s->session_id_length; + return s->session_id; +} +const unsigned char *SSL_SESSION_get0_id_context(const SSL_SESSION *s, + unsigned int *len) +{ + if (len != NULL) + *len = (unsigned int)s->sid_ctx_length; + return s->sid_ctx; +} + +unsigned int SSL_SESSION_get_compress_id(const SSL_SESSION *s) +{ + return s->compress_meth; +} + +/* + * SSLv3/TLSv1 has 32 bytes (256 bits) of session ID space. As such, filling + * the ID with random junk repeatedly until we have no conflict is going to + * complete in one iteration pretty much "most" of the time (btw: + * understatement). So, if it takes us 10 iterations and we still can't avoid + * a conflict - well that's a reasonable point to call it quits. Either the + * RAND code is broken or someone is trying to open roughly very close to + * 2^256 SSL sessions to our server. How you might store that many sessions + * is perhaps a more interesting question ... + */ + +#define MAX_SESS_ID_ATTEMPTS 10 +static int def_generate_session_id(SSL *ssl, unsigned char *id, + unsigned int *id_len) +{ + unsigned int retry = 0; + do + if (RAND_bytes(id, *id_len) <= 0) + return 0; + while (SSL_has_matching_session_id(ssl, id, *id_len) && + (++retry < MAX_SESS_ID_ATTEMPTS)) ; + if (retry < MAX_SESS_ID_ATTEMPTS) + return 1; + /* else - woops a session_id match */ + /* + * XXX We should also check the external cache -- but the probability of + * a collision is negligible, and we could not prevent the concurrent + * creation of sessions with identical IDs since we currently don't have + * means to atomically check whether a session ID already exists and make + * a reservation for it if it does not (this problem applies to the + * internal cache as well). + */ + return 0; +} + +int ssl_generate_session_id(SSL *s, SSL_SESSION *ss) +{ + unsigned int tmp; + GEN_SESSION_CB cb = def_generate_session_id; + + switch (s->version) { + case SSL3_VERSION: + case TLS1_VERSION: + case TLS1_1_VERSION: + case TLS1_2_VERSION: + case TLS1_3_VERSION: + case DTLS1_BAD_VER: + case DTLS1_VERSION: + case DTLS1_2_VERSION: + ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH; + break; + default: + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_SESSION_ID, + SSL_R_UNSUPPORTED_SSL_VERSION); + return 0; + } + + /*- + * If RFC5077 ticket, use empty session ID (as server). + * Note that: + * (a) ssl_get_prev_session() does lookahead into the + * ClientHello extensions to find the session ticket. + * When ssl_get_prev_session() fails, statem_srvr.c calls + * ssl_get_new_session() in tls_process_client_hello(). + * At that point, it has not yet parsed the extensions, + * however, because of the lookahead, it already knows + * whether a ticket is expected or not. + * + * (b) statem_clnt.c calls ssl_get_new_session() before parsing + * ServerHello extensions, and before recording the session + * ID received from the server, so this block is a noop. + */ + if (s->ext.ticket_expected) { + ss->session_id_length = 0; + return 1; + } + + /* Choose which callback will set the session ID */ + CRYPTO_THREAD_read_lock(s->lock); + CRYPTO_THREAD_read_lock(s->session_ctx->lock); + if (s->generate_session_id) + cb = s->generate_session_id; + else if (s->session_ctx->generate_session_id) + cb = s->session_ctx->generate_session_id; + CRYPTO_THREAD_unlock(s->session_ctx->lock); + CRYPTO_THREAD_unlock(s->lock); + /* Choose a session ID */ + memset(ss->session_id, 0, ss->session_id_length); + tmp = (int)ss->session_id_length; + if (!cb(s, ss->session_id, &tmp)) { + /* The callback failed */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_SESSION_ID, + SSL_R_SSL_SESSION_ID_CALLBACK_FAILED); + return 0; + } + /* + * Don't allow the callback to set the session length to zero. nor + * set it higher than it was. + */ + if (tmp == 0 || tmp > ss->session_id_length) { + /* The callback set an illegal length */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_SESSION_ID, + SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH); + return 0; + } + ss->session_id_length = tmp; + /* Finally, check for a conflict */ + if (SSL_has_matching_session_id(s, ss->session_id, + (unsigned int)ss->session_id_length)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_SESSION_ID, + SSL_R_SSL_SESSION_ID_CONFLICT); + return 0; + } + + return 1; +} + +int ssl_get_new_session(SSL *s, int session) +{ + /* This gets used by clients and servers. */ + + SSL_SESSION *ss = NULL; + + if ((ss = SSL_SESSION_new()) == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_NEW_SESSION, + ERR_R_MALLOC_FAILURE); + return 0; + } + + /* If the context has a default timeout, use it */ + if (s->session_ctx->session_timeout == 0) + ss->timeout = SSL_get_default_timeout(s); + else + ss->timeout = s->session_ctx->session_timeout; + + SSL_SESSION_free(s->session); + s->session = NULL; + + if (session) { + if (SSL_IS_TLS13(s)) { + /* + * We generate the session id while constructing the + * NewSessionTicket in TLSv1.3. + */ + ss->session_id_length = 0; + } else if (!ssl_generate_session_id(s, ss)) { + /* SSLfatal() already called */ + SSL_SESSION_free(ss); + return 0; + } + + } else { + ss->session_id_length = 0; + } + + if (s->sid_ctx_length > sizeof(ss->sid_ctx)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_NEW_SESSION, + ERR_R_INTERNAL_ERROR); + SSL_SESSION_free(ss); + return 0; + } + memcpy(ss->sid_ctx, s->sid_ctx, s->sid_ctx_length); + ss->sid_ctx_length = s->sid_ctx_length; + s->session = ss; + ss->ssl_version = s->version; + ss->verify_result = X509_V_OK; + + /* If client supports extended master secret set it in session */ + if (s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) + ss->flags |= SSL_SESS_FLAG_EXTMS; + + return 1; +} + +SSL_SESSION *lookup_sess_in_cache(SSL *s, const unsigned char *sess_id, + size_t sess_id_len) +{ + SSL_SESSION *ret = NULL; + + if ((s->session_ctx->session_cache_mode + & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP) == 0) { + SSL_SESSION data; + + data.ssl_version = s->version; + if (!ossl_assert(sess_id_len <= SSL_MAX_SSL_SESSION_ID_LENGTH)) + return NULL; + + memcpy(data.session_id, sess_id, sess_id_len); + data.session_id_length = sess_id_len; + + CRYPTO_THREAD_read_lock(s->session_ctx->lock); + ret = lh_SSL_SESSION_retrieve(s->session_ctx->sessions, &data); + if (ret != NULL) { + /* don't allow other threads to steal it: */ + SSL_SESSION_up_ref(ret); + } + CRYPTO_THREAD_unlock(s->session_ctx->lock); + if (ret == NULL) + tsan_counter(&s->session_ctx->stats.sess_miss); + } + + if (ret == NULL && s->session_ctx->get_session_cb != NULL) { + int copy = 1; + + ret = s->session_ctx->get_session_cb(s, sess_id, sess_id_len, ©); + + if (ret != NULL) { + tsan_counter(&s->session_ctx->stats.sess_cb_hit); + + /* + * Increment reference count now if the session callback asks us + * to do so (note that if the session structures returned by the + * callback are shared between threads, it must handle the + * reference count itself [i.e. copy == 0], or things won't be + * thread-safe). + */ + if (copy) + SSL_SESSION_up_ref(ret); + + /* + * Add the externally cached session to the internal cache as + * well if and only if we are supposed to. + */ + if ((s->session_ctx->session_cache_mode & + SSL_SESS_CACHE_NO_INTERNAL_STORE) == 0) { + /* + * Either return value of SSL_CTX_add_session should not + * interrupt the session resumption process. The return + * value is intentionally ignored. + */ + (void)SSL_CTX_add_session(s->session_ctx, ret); + } + } + } + + return ret; +} + +/*- + * ssl_get_prev attempts to find an SSL_SESSION to be used to resume this + * connection. It is only called by servers. + * + * hello: The parsed ClientHello data + * + * Returns: + * -1: fatal error + * 0: no session found + * 1: a session may have been found. + * + * Side effects: + * - If a session is found then s->session is pointed at it (after freeing an + * existing session if need be) and s->verify_result is set from the session. + * - Both for new and resumed sessions, s->ext.ticket_expected is set to 1 + * if the server should issue a new session ticket (to 0 otherwise). + */ +int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello) +{ + /* This is used only by servers. */ + + SSL_SESSION *ret = NULL; + int fatal = 0; + int try_session_cache = 0; + SSL_TICKET_STATUS r; + + if (SSL_IS_TLS13(s)) { + /* + * By default we will send a new ticket. This can be overridden in the + * ticket processing. + */ + s->ext.ticket_expected = 1; + if (!tls_parse_extension(s, TLSEXT_IDX_psk_kex_modes, + SSL_EXT_CLIENT_HELLO, hello->pre_proc_exts, + NULL, 0) + || !tls_parse_extension(s, TLSEXT_IDX_psk, SSL_EXT_CLIENT_HELLO, + hello->pre_proc_exts, NULL, 0)) + return -1; + + ret = s->session; + } else { + /* sets s->ext.ticket_expected */ + r = tls_get_ticket_from_client(s, hello, &ret); + switch (r) { + case SSL_TICKET_FATAL_ERR_MALLOC: + case SSL_TICKET_FATAL_ERR_OTHER: + fatal = 1; + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_PREV_SESSION, + ERR_R_INTERNAL_ERROR); + goto err; + case SSL_TICKET_NONE: + case SSL_TICKET_EMPTY: + if (hello->session_id_len > 0) { + try_session_cache = 1; + ret = lookup_sess_in_cache(s, hello->session_id, + hello->session_id_len); + } + break; + case SSL_TICKET_NO_DECRYPT: + case SSL_TICKET_SUCCESS: + case SSL_TICKET_SUCCESS_RENEW: + break; + } + } + + if (ret == NULL) + goto err; + + /* Now ret is non-NULL and we own one of its reference counts. */ + + /* Check TLS version consistency */ + if (ret->ssl_version != s->version) + goto err; + + if (ret->sid_ctx_length != s->sid_ctx_length + || memcmp(ret->sid_ctx, s->sid_ctx, ret->sid_ctx_length)) { + /* + * We have the session requested by the client, but we don't want to + * use it in this context. + */ + goto err; /* treat like cache miss */ + } + + if ((s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0) { + /* + * We can't be sure if this session is being used out of context, + * which is especially important for SSL_VERIFY_PEER. The application + * should have used SSL[_CTX]_set_session_id_context. For this error + * case, we generate an error instead of treating the event like a + * cache miss (otherwise it would be easy for applications to + * effectively disable the session cache by accident without anyone + * noticing). + */ + + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_PREV_SESSION, + SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED); + fatal = 1; + goto err; + } + + if (ret->timeout < (long)(time(NULL) - ret->time)) { /* timeout */ + tsan_counter(&s->session_ctx->stats.sess_timeout); + if (try_session_cache) { + /* session was from the cache, so remove it */ + SSL_CTX_remove_session(s->session_ctx, ret); + } + goto err; + } + + /* Check extended master secret extension consistency */ + if (ret->flags & SSL_SESS_FLAG_EXTMS) { + /* If old session includes extms, but new does not: abort handshake */ + if (!(s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS)) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SSL_GET_PREV_SESSION, + SSL_R_INCONSISTENT_EXTMS); + fatal = 1; + goto err; + } + } else if (s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) { + /* If new session includes extms, but old does not: do not resume */ + goto err; + } + + if (!SSL_IS_TLS13(s)) { + /* We already did this for TLS1.3 */ + SSL_SESSION_free(s->session); + s->session = ret; + } + + tsan_counter(&s->session_ctx->stats.sess_hit); + s->verify_result = s->session->verify_result; + return 1; + + err: + if (ret != NULL) { + SSL_SESSION_free(ret); + /* In TLSv1.3 s->session was already set to ret, so we NULL it out */ + if (SSL_IS_TLS13(s)) + s->session = NULL; + + if (!try_session_cache) { + /* + * The session was from a ticket, so we should issue a ticket for + * the new session + */ + s->ext.ticket_expected = 1; + } + } + if (fatal) + return -1; + + return 0; +} + +int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) +{ + int ret = 0; + SSL_SESSION *s; + + /* + * add just 1 reference count for the SSL_CTX's session cache even though + * it has two ways of access: each session is in a doubly linked list and + * an lhash + */ + SSL_SESSION_up_ref(c); + /* + * if session c is in already in cache, we take back the increment later + */ + + CRYPTO_THREAD_write_lock(ctx->lock); + s = lh_SSL_SESSION_insert(ctx->sessions, c); + + /* + * s != NULL iff we already had a session with the given PID. In this + * case, s == c should hold (then we did not really modify + * ctx->sessions), or we're in trouble. + */ + if (s != NULL && s != c) { + /* We *are* in trouble ... */ + SSL_SESSION_list_remove(ctx, s); + SSL_SESSION_free(s); + /* + * ... so pretend the other session did not exist in cache (we cannot + * handle two SSL_SESSION structures with identical session ID in the + * same cache, which could happen e.g. when two threads concurrently + * obtain the same session from an external cache) + */ + s = NULL; + } else if (s == NULL && + lh_SSL_SESSION_retrieve(ctx->sessions, c) == NULL) { + /* s == NULL can also mean OOM error in lh_SSL_SESSION_insert ... */ + + /* + * ... so take back the extra reference and also don't add + * the session to the SSL_SESSION_list at this time + */ + s = c; + } + + /* Put at the head of the queue unless it is already in the cache */ + if (s == NULL) + SSL_SESSION_list_add(ctx, c); + + if (s != NULL) { + /* + * existing cache entry -- decrement previously incremented reference + * count because it already takes into account the cache + */ + + SSL_SESSION_free(s); /* s == c */ + ret = 0; + } else { + /* + * new cache entry -- remove old ones if cache has become too large + */ + + ret = 1; + + if (SSL_CTX_sess_get_cache_size(ctx) > 0) { + while (SSL_CTX_sess_number(ctx) > SSL_CTX_sess_get_cache_size(ctx)) { + if (!remove_session_lock(ctx, ctx->session_cache_tail, 0)) + break; + else + tsan_counter(&ctx->stats.sess_cache_full); + } + } + } + CRYPTO_THREAD_unlock(ctx->lock); + return ret; +} + +int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c) +{ + return remove_session_lock(ctx, c, 1); +} + +static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck) +{ + SSL_SESSION *r; + int ret = 0; + + if ((c != NULL) && (c->session_id_length != 0)) { + if (lck) + CRYPTO_THREAD_write_lock(ctx->lock); + if ((r = lh_SSL_SESSION_retrieve(ctx->sessions, c)) != NULL) { + ret = 1; + r = lh_SSL_SESSION_delete(ctx->sessions, r); + SSL_SESSION_list_remove(ctx, r); + } + c->not_resumable = 1; + + if (lck) + CRYPTO_THREAD_unlock(ctx->lock); + + if (ctx->remove_session_cb != NULL) + ctx->remove_session_cb(ctx, c); + + if (ret) + SSL_SESSION_free(r); + } else + ret = 0; + return ret; +} + +void SSL_SESSION_free(SSL_SESSION *ss) +{ + int i; + + if (ss == NULL) + return; + CRYPTO_DOWN_REF(&ss->references, &i, ss->lock); + REF_PRINT_COUNT("SSL_SESSION", ss); + if (i > 0) + return; + REF_ASSERT_ISNT(i < 0); + + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); + + OPENSSL_cleanse(ss->master_key, sizeof(ss->master_key)); + OPENSSL_cleanse(ss->session_id, sizeof(ss->session_id)); + X509_free(ss->peer); + sk_X509_pop_free(ss->peer_chain, X509_free); + sk_SSL_CIPHER_free(ss->ciphers); + OPENSSL_free(ss->ext.hostname); + OPENSSL_free(ss->ext.tick); +#ifndef OPENSSL_NO_EC + OPENSSL_free(ss->ext.ecpointformats); + ss->ext.ecpointformats = NULL; + ss->ext.ecpointformats_len = 0; + OPENSSL_free(ss->ext.supportedgroups); + ss->ext.supportedgroups = NULL; + ss->ext.supportedgroups_len = 0; +#endif /* OPENSSL_NO_EC */ +#ifndef OPENSSL_NO_PSK + OPENSSL_free(ss->psk_identity_hint); + OPENSSL_free(ss->psk_identity); +#endif +#ifndef OPENSSL_NO_SRP + OPENSSL_free(ss->srp_username); +#endif + OPENSSL_free(ss->ext.alpn_selected); + OPENSSL_free(ss->ticket_appdata); + CRYPTO_THREAD_lock_free(ss->lock); + OPENSSL_clear_free(ss, sizeof(*ss)); +} + +int SSL_SESSION_up_ref(SSL_SESSION *ss) +{ + int i; + + if (CRYPTO_UP_REF(&ss->references, &i, ss->lock) <= 0) + return 0; + + REF_PRINT_COUNT("SSL_SESSION", ss); + REF_ASSERT_ISNT(i < 2); + return ((i > 1) ? 1 : 0); +} + +int SSL_set_session(SSL *s, SSL_SESSION *session) +{ + ssl_clear_bad_session(s); + if (s->ctx->method != s->method) { + if (!SSL_set_ssl_method(s, s->ctx->method)) + return 0; + } + + if (session != NULL) { + SSL_SESSION_up_ref(session); + s->verify_result = session->verify_result; + } + SSL_SESSION_free(s->session); + s->session = session; + + return 1; +} + +int SSL_SESSION_set1_id(SSL_SESSION *s, const unsigned char *sid, + unsigned int sid_len) +{ + if (sid_len > SSL_MAX_SSL_SESSION_ID_LENGTH) { + SSLerr(SSL_F_SSL_SESSION_SET1_ID, + SSL_R_SSL_SESSION_ID_TOO_LONG); + return 0; + } + s->session_id_length = sid_len; + if (sid != s->session_id) + memcpy(s->session_id, sid, sid_len); + return 1; +} + +long SSL_SESSION_set_timeout(SSL_SESSION *s, long t) +{ + if (s == NULL) + return 0; + s->timeout = t; + return 1; +} + +long SSL_SESSION_get_timeout(const SSL_SESSION *s) +{ + if (s == NULL) + return 0; + return s->timeout; +} + +long SSL_SESSION_get_time(const SSL_SESSION *s) +{ + if (s == NULL) + return 0; + return s->time; +} + +long SSL_SESSION_set_time(SSL_SESSION *s, long t) +{ + if (s == NULL) + return 0; + s->time = t; + return t; +} + +int SSL_SESSION_get_protocol_version(const SSL_SESSION *s) +{ + return s->ssl_version; +} + +int SSL_SESSION_set_protocol_version(SSL_SESSION *s, int version) +{ + s->ssl_version = version; + return 1; +} + +const SSL_CIPHER *SSL_SESSION_get0_cipher(const SSL_SESSION *s) +{ + return s->cipher; +} + +int SSL_SESSION_set_cipher(SSL_SESSION *s, const SSL_CIPHER *cipher) +{ + s->cipher = cipher; + return 1; +} + +const char *SSL_SESSION_get0_hostname(const SSL_SESSION *s) +{ + return s->ext.hostname; +} + +int SSL_SESSION_set1_hostname(SSL_SESSION *s, const char *hostname) +{ + OPENSSL_free(s->ext.hostname); + if (hostname == NULL) { + s->ext.hostname = NULL; + return 1; + } + s->ext.hostname = OPENSSL_strdup(hostname); + + return s->ext.hostname != NULL; +} + +int SSL_SESSION_has_ticket(const SSL_SESSION *s) +{ + return (s->ext.ticklen > 0) ? 1 : 0; +} + +unsigned long SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s) +{ + return s->ext.tick_lifetime_hint; +} + +void SSL_SESSION_get0_ticket(const SSL_SESSION *s, const unsigned char **tick, + size_t *len) +{ + *len = s->ext.ticklen; + if (tick != NULL) + *tick = s->ext.tick; +} + +uint32_t SSL_SESSION_get_max_early_data(const SSL_SESSION *s) +{ + return s->ext.max_early_data; +} + +int SSL_SESSION_set_max_early_data(SSL_SESSION *s, uint32_t max_early_data) +{ + s->ext.max_early_data = max_early_data; + + return 1; +} + +void SSL_SESSION_get0_alpn_selected(const SSL_SESSION *s, + const unsigned char **alpn, + size_t *len) +{ + *alpn = s->ext.alpn_selected; + *len = s->ext.alpn_selected_len; +} + +int SSL_SESSION_set1_alpn_selected(SSL_SESSION *s, const unsigned char *alpn, + size_t len) +{ + OPENSSL_free(s->ext.alpn_selected); + if (alpn == NULL || len == 0) { + s->ext.alpn_selected = NULL; + s->ext.alpn_selected_len = 0; + return 1; + } + s->ext.alpn_selected = OPENSSL_memdup(alpn, len); + if (s->ext.alpn_selected == NULL) { + s->ext.alpn_selected_len = 0; + return 0; + } + s->ext.alpn_selected_len = len; + + return 1; +} + +X509 *SSL_SESSION_get0_peer(SSL_SESSION *s) +{ + return s->peer; +} + +int SSL_SESSION_set1_id_context(SSL_SESSION *s, const unsigned char *sid_ctx, + unsigned int sid_ctx_len) +{ + if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) { + SSLerr(SSL_F_SSL_SESSION_SET1_ID_CONTEXT, + SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG); + return 0; + } + s->sid_ctx_length = sid_ctx_len; + if (sid_ctx != s->sid_ctx) + memcpy(s->sid_ctx, sid_ctx, sid_ctx_len); + + return 1; +} + +int SSL_SESSION_is_resumable(const SSL_SESSION *s) +{ + /* + * In the case of EAP-FAST, we can have a pre-shared "ticket" without a + * session ID. + */ + return !s->not_resumable + && (s->session_id_length > 0 || s->ext.ticklen > 0); +} + +long SSL_CTX_set_timeout(SSL_CTX *s, long t) +{ + long l; + if (s == NULL) + return 0; + l = s->session_timeout; + s->session_timeout = t; + return l; +} + +long SSL_CTX_get_timeout(const SSL_CTX *s) +{ + if (s == NULL) + return 0; + return s->session_timeout; +} + +int SSL_set_session_secret_cb(SSL *s, + tls_session_secret_cb_fn tls_session_secret_cb, + void *arg) +{ + if (s == NULL) + return 0; + s->ext.session_secret_cb = tls_session_secret_cb; + s->ext.session_secret_cb_arg = arg; + return 1; +} + +int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb, + void *arg) +{ + if (s == NULL) + return 0; + s->ext.session_ticket_cb = cb; + s->ext.session_ticket_cb_arg = arg; + return 1; +} + +int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len) +{ + if (s->version >= TLS1_VERSION) { + OPENSSL_free(s->ext.session_ticket); + s->ext.session_ticket = NULL; + s->ext.session_ticket = + OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len); + if (s->ext.session_ticket == NULL) { + SSLerr(SSL_F_SSL_SET_SESSION_TICKET_EXT, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (ext_data != NULL) { + s->ext.session_ticket->length = ext_len; + s->ext.session_ticket->data = s->ext.session_ticket + 1; + memcpy(s->ext.session_ticket->data, ext_data, ext_len); + } else { + s->ext.session_ticket->length = 0; + s->ext.session_ticket->data = NULL; + } + + return 1; + } + + return 0; +} + +typedef struct timeout_param_st { + SSL_CTX *ctx; + long time; + LHASH_OF(SSL_SESSION) *cache; +} TIMEOUT_PARAM; + +static void timeout_cb(SSL_SESSION *s, TIMEOUT_PARAM *p) +{ + if ((p->time == 0) || (p->time > (s->time + s->timeout))) { /* timeout */ + /* + * The reason we don't call SSL_CTX_remove_session() is to save on + * locking overhead + */ + (void)lh_SSL_SESSION_delete(p->cache, s); + SSL_SESSION_list_remove(p->ctx, s); + s->not_resumable = 1; + if (p->ctx->remove_session_cb != NULL) + p->ctx->remove_session_cb(p->ctx, s); + SSL_SESSION_free(s); + } +} + +IMPLEMENT_LHASH_DOALL_ARG(SSL_SESSION, TIMEOUT_PARAM); + +void SSL_CTX_flush_sessions(SSL_CTX *s, long t) +{ + unsigned long i; + TIMEOUT_PARAM tp; + + tp.ctx = s; + tp.cache = s->sessions; + if (tp.cache == NULL) + return; + tp.time = t; + CRYPTO_THREAD_write_lock(s->lock); + i = lh_SSL_SESSION_get_down_load(s->sessions); + lh_SSL_SESSION_set_down_load(s->sessions, 0); + lh_SSL_SESSION_doall_TIMEOUT_PARAM(tp.cache, timeout_cb, &tp); + lh_SSL_SESSION_set_down_load(s->sessions, i); + CRYPTO_THREAD_unlock(s->lock); +} + +int ssl_clear_bad_session(SSL *s) +{ + if ((s->session != NULL) && + !(s->shutdown & SSL_SENT_SHUTDOWN) && + !(SSL_in_init(s) || SSL_in_before(s))) { + SSL_CTX_remove_session(s->session_ctx, s->session); + return 1; + } else + return 0; +} + +/* locked by SSL_CTX in the calling function */ +static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s) +{ + if ((s->next == NULL) || (s->prev == NULL)) + return; + + if (s->next == (SSL_SESSION *)&(ctx->session_cache_tail)) { + /* last element in list */ + if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head)) { + /* only one element in list */ + ctx->session_cache_head = NULL; + ctx->session_cache_tail = NULL; + } else { + ctx->session_cache_tail = s->prev; + s->prev->next = (SSL_SESSION *)&(ctx->session_cache_tail); + } + } else { + if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head)) { + /* first element in list */ + ctx->session_cache_head = s->next; + s->next->prev = (SSL_SESSION *)&(ctx->session_cache_head); + } else { + /* middle of list */ + s->next->prev = s->prev; + s->prev->next = s->next; + } + } + s->prev = s->next = NULL; +} + +static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s) +{ + if ((s->next != NULL) && (s->prev != NULL)) + SSL_SESSION_list_remove(ctx, s); + + if (ctx->session_cache_head == NULL) { + ctx->session_cache_head = s; + ctx->session_cache_tail = s; + s->prev = (SSL_SESSION *)&(ctx->session_cache_head); + s->next = (SSL_SESSION *)&(ctx->session_cache_tail); + } else { + s->next = ctx->session_cache_head; + s->next->prev = s; + s->prev = (SSL_SESSION *)&(ctx->session_cache_head); + ctx->session_cache_head = s; + } +} + +void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx, + int (*cb) (struct ssl_st *ssl, SSL_SESSION *sess)) +{ + ctx->new_session_cb = cb; +} + +int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx)) (SSL *ssl, SSL_SESSION *sess) { + return ctx->new_session_cb; +} + +void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx, + void (*cb) (SSL_CTX *ctx, SSL_SESSION *sess)) +{ + ctx->remove_session_cb = cb; +} + +void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx)) (SSL_CTX *ctx, + SSL_SESSION *sess) { + return ctx->remove_session_cb; +} + +void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx, + SSL_SESSION *(*cb) (struct ssl_st *ssl, + const unsigned char *data, + int len, int *copy)) +{ + ctx->get_session_cb = cb; +} + +SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx)) (SSL *ssl, + const unsigned char + *data, int len, + int *copy) { + return ctx->get_session_cb; +} + +void SSL_CTX_set_info_callback(SSL_CTX *ctx, + void (*cb) (const SSL *ssl, int type, int val)) +{ + ctx->info_callback = cb; +} + +void (*SSL_CTX_get_info_callback(SSL_CTX *ctx)) (const SSL *ssl, int type, + int val) { + return ctx->info_callback; +} + +void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, + int (*cb) (SSL *ssl, X509 **x509, + EVP_PKEY **pkey)) +{ + ctx->client_cert_cb = cb; +} + +int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx)) (SSL *ssl, X509 **x509, + EVP_PKEY **pkey) { + return ctx->client_cert_cb; +} + +#ifndef OPENSSL_NO_ENGINE +int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e) +{ + if (!ENGINE_init(e)) { + SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE, ERR_R_ENGINE_LIB); + return 0; + } + if (!ENGINE_get_ssl_client_cert_function(e)) { + SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE, + SSL_R_NO_CLIENT_CERT_METHOD); + ENGINE_finish(e); + return 0; + } + ctx->client_cert_engine = e; + return 1; +} +#endif + +void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx, + int (*cb) (SSL *ssl, + unsigned char *cookie, + unsigned int *cookie_len)) +{ + ctx->app_gen_cookie_cb = cb; +} + +void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx, + int (*cb) (SSL *ssl, + const unsigned char *cookie, + unsigned int cookie_len)) +{ + ctx->app_verify_cookie_cb = cb; +} + +int SSL_SESSION_set1_ticket_appdata(SSL_SESSION *ss, const void *data, size_t len) +{ + OPENSSL_free(ss->ticket_appdata); + ss->ticket_appdata_len = 0; + if (data == NULL || len == 0) { + ss->ticket_appdata = NULL; + return 1; + } + ss->ticket_appdata = OPENSSL_memdup(data, len); + if (ss->ticket_appdata != NULL) { + ss->ticket_appdata_len = len; + return 1; + } + return 0; +} + +int SSL_SESSION_get0_ticket_appdata(SSL_SESSION *ss, void **data, size_t *len) +{ + *data = ss->ticket_appdata; + *len = ss->ticket_appdata_len; + return 1; +} + +void SSL_CTX_set_stateless_cookie_generate_cb( + SSL_CTX *ctx, + int (*cb) (SSL *ssl, + unsigned char *cookie, + size_t *cookie_len)) +{ + ctx->gen_stateless_cookie_cb = cb; +} + +void SSL_CTX_set_stateless_cookie_verify_cb( + SSL_CTX *ctx, + int (*cb) (SSL *ssl, + const unsigned char *cookie, + size_t cookie_len)) +{ + ctx->verify_stateless_cookie_cb = cb; +} + +IMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION, SSL_SESSION) diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_stat.c b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_stat.c new file mode 100644 index 000000000..179513b1a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_stat.c @@ -0,0 +1,388 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2005 Nokia. All rights reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "ssl_locl.h" + +const char *SSL_state_string_long(const SSL *s) +{ + if (ossl_statem_in_error(s)) + return "error"; + + switch (SSL_get_state(s)) { + case TLS_ST_CR_CERT_STATUS: + return "SSLv3/TLS read certificate status"; + case TLS_ST_CW_NEXT_PROTO: + return "SSLv3/TLS write next proto"; + case TLS_ST_SR_NEXT_PROTO: + return "SSLv3/TLS read next proto"; + case TLS_ST_SW_CERT_STATUS: + return "SSLv3/TLS write certificate status"; + case TLS_ST_BEFORE: + return "before SSL initialization"; + case TLS_ST_OK: + return "SSL negotiation finished successfully"; + case TLS_ST_CW_CLNT_HELLO: + return "SSLv3/TLS write client hello"; + case TLS_ST_CR_SRVR_HELLO: + return "SSLv3/TLS read server hello"; + case TLS_ST_CR_CERT: + return "SSLv3/TLS read server certificate"; + case TLS_ST_CR_KEY_EXCH: + return "SSLv3/TLS read server key exchange"; + case TLS_ST_CR_CERT_REQ: + return "SSLv3/TLS read server certificate request"; + case TLS_ST_CR_SESSION_TICKET: + return "SSLv3/TLS read server session ticket"; + case TLS_ST_CR_SRVR_DONE: + return "SSLv3/TLS read server done"; + case TLS_ST_CW_CERT: + return "SSLv3/TLS write client certificate"; + case TLS_ST_CW_KEY_EXCH: + return "SSLv3/TLS write client key exchange"; + case TLS_ST_CW_CERT_VRFY: + return "SSLv3/TLS write certificate verify"; + case TLS_ST_CW_CHANGE: + case TLS_ST_SW_CHANGE: + return "SSLv3/TLS write change cipher spec"; + case TLS_ST_CW_FINISHED: + case TLS_ST_SW_FINISHED: + return "SSLv3/TLS write finished"; + case TLS_ST_CR_CHANGE: + case TLS_ST_SR_CHANGE: + return "SSLv3/TLS read change cipher spec"; + case TLS_ST_CR_FINISHED: + case TLS_ST_SR_FINISHED: + return "SSLv3/TLS read finished"; + case TLS_ST_SR_CLNT_HELLO: + return "SSLv3/TLS read client hello"; + case TLS_ST_SW_HELLO_REQ: + return "SSLv3/TLS write hello request"; + case TLS_ST_SW_SRVR_HELLO: + return "SSLv3/TLS write server hello"; + case TLS_ST_SW_CERT: + return "SSLv3/TLS write certificate"; + case TLS_ST_SW_KEY_EXCH: + return "SSLv3/TLS write key exchange"; + case TLS_ST_SW_CERT_REQ: + return "SSLv3/TLS write certificate request"; + case TLS_ST_SW_SESSION_TICKET: + return "SSLv3/TLS write session ticket"; + case TLS_ST_SW_SRVR_DONE: + return "SSLv3/TLS write server done"; + case TLS_ST_SR_CERT: + return "SSLv3/TLS read client certificate"; + case TLS_ST_SR_KEY_EXCH: + return "SSLv3/TLS read client key exchange"; + case TLS_ST_SR_CERT_VRFY: + return "SSLv3/TLS read certificate verify"; + case DTLS_ST_CR_HELLO_VERIFY_REQUEST: + return "DTLS1 read hello verify request"; + case DTLS_ST_SW_HELLO_VERIFY_REQUEST: + return "DTLS1 write hello verify request"; + case TLS_ST_SW_ENCRYPTED_EXTENSIONS: + return "TLSv1.3 write encrypted extensions"; + case TLS_ST_CR_ENCRYPTED_EXTENSIONS: + return "TLSv1.3 read encrypted extensions"; + case TLS_ST_CR_CERT_VRFY: + return "TLSv1.3 read server certificate verify"; + case TLS_ST_SW_CERT_VRFY: + return "TLSv1.3 write server certificate verify"; + case TLS_ST_CR_HELLO_REQ: + return "SSLv3/TLS read hello request"; + case TLS_ST_SW_KEY_UPDATE: + return "TLSv1.3 write server key update"; + case TLS_ST_CW_KEY_UPDATE: + return "TLSv1.3 write client key update"; + case TLS_ST_SR_KEY_UPDATE: + return "TLSv1.3 read client key update"; + case TLS_ST_CR_KEY_UPDATE: + return "TLSv1.3 read server key update"; + case TLS_ST_EARLY_DATA: + return "TLSv1.3 early data"; + case TLS_ST_PENDING_EARLY_DATA_END: + return "TLSv1.3 pending early data end"; + case TLS_ST_CW_END_OF_EARLY_DATA: + return "TLSv1.3 write end of early data"; + case TLS_ST_SR_END_OF_EARLY_DATA: + return "TLSv1.3 read end of early data"; + default: + return "unknown state"; + } +} + +const char *SSL_state_string(const SSL *s) +{ + if (ossl_statem_in_error(s)) + return "SSLERR"; + + switch (SSL_get_state(s)) { + case TLS_ST_SR_NEXT_PROTO: + return "TRNP"; + case TLS_ST_SW_SESSION_TICKET: + return "TWST"; + case TLS_ST_SW_CERT_STATUS: + return "TWCS"; + case TLS_ST_CR_CERT_STATUS: + return "TRCS"; + case TLS_ST_CR_SESSION_TICKET: + return "TRST"; + case TLS_ST_CW_NEXT_PROTO: + return "TWNP"; + case TLS_ST_BEFORE: + return "PINIT "; + case TLS_ST_OK: + return "SSLOK "; + case TLS_ST_CW_CLNT_HELLO: + return "TWCH"; + case TLS_ST_CR_SRVR_HELLO: + return "TRSH"; + case TLS_ST_CR_CERT: + return "TRSC"; + case TLS_ST_CR_KEY_EXCH: + return "TRSKE"; + case TLS_ST_CR_CERT_REQ: + return "TRCR"; + case TLS_ST_CR_SRVR_DONE: + return "TRSD"; + case TLS_ST_CW_CERT: + return "TWCC"; + case TLS_ST_CW_KEY_EXCH: + return "TWCKE"; + case TLS_ST_CW_CERT_VRFY: + return "TWCV"; + case TLS_ST_SW_CHANGE: + case TLS_ST_CW_CHANGE: + return "TWCCS"; + case TLS_ST_SW_FINISHED: + case TLS_ST_CW_FINISHED: + return "TWFIN"; + case TLS_ST_SR_CHANGE: + case TLS_ST_CR_CHANGE: + return "TRCCS"; + case TLS_ST_SR_FINISHED: + case TLS_ST_CR_FINISHED: + return "TRFIN"; + case TLS_ST_SW_HELLO_REQ: + return "TWHR"; + case TLS_ST_SR_CLNT_HELLO: + return "TRCH"; + case TLS_ST_SW_SRVR_HELLO: + return "TWSH"; + case TLS_ST_SW_CERT: + return "TWSC"; + case TLS_ST_SW_KEY_EXCH: + return "TWSKE"; + case TLS_ST_SW_CERT_REQ: + return "TWCR"; + case TLS_ST_SW_SRVR_DONE: + return "TWSD"; + case TLS_ST_SR_CERT: + return "TRCC"; + case TLS_ST_SR_KEY_EXCH: + return "TRCKE"; + case TLS_ST_SR_CERT_VRFY: + return "TRCV"; + case DTLS_ST_CR_HELLO_VERIFY_REQUEST: + return "DRCHV"; + case DTLS_ST_SW_HELLO_VERIFY_REQUEST: + return "DWCHV"; + case TLS_ST_SW_ENCRYPTED_EXTENSIONS: + return "TWEE"; + case TLS_ST_CR_ENCRYPTED_EXTENSIONS: + return "TREE"; + case TLS_ST_CR_CERT_VRFY: + return "TRSCV"; + case TLS_ST_SW_CERT_VRFY: + return "TRSCV"; + case TLS_ST_CR_HELLO_REQ: + return "TRHR"; + case TLS_ST_SW_KEY_UPDATE: + return "TWSKU"; + case TLS_ST_CW_KEY_UPDATE: + return "TWCKU"; + case TLS_ST_SR_KEY_UPDATE: + return "TRCKU"; + case TLS_ST_CR_KEY_UPDATE: + return "TRSKU"; + case TLS_ST_EARLY_DATA: + return "TED"; + case TLS_ST_PENDING_EARLY_DATA_END: + return "TPEDE"; + case TLS_ST_CW_END_OF_EARLY_DATA: + return "TWEOED"; + case TLS_ST_SR_END_OF_EARLY_DATA: + return "TWEOED"; + default: + return "UNKWN "; + } +} + +const char *SSL_alert_type_string_long(int value) +{ + switch (value >> 8) { + case SSL3_AL_WARNING: + return "warning"; + case SSL3_AL_FATAL: + return "fatal"; + default: + return "unknown"; + } +} + +const char *SSL_alert_type_string(int value) +{ + switch (value >> 8) { + case SSL3_AL_WARNING: + return "W"; + case SSL3_AL_FATAL: + return "F"; + default: + return "U"; + } +} + +const char *SSL_alert_desc_string(int value) +{ + switch (value & 0xff) { + case SSL3_AD_CLOSE_NOTIFY: + return "CN"; + case SSL3_AD_UNEXPECTED_MESSAGE: + return "UM"; + case SSL3_AD_BAD_RECORD_MAC: + return "BM"; + case SSL3_AD_DECOMPRESSION_FAILURE: + return "DF"; + case SSL3_AD_HANDSHAKE_FAILURE: + return "HF"; + case SSL3_AD_NO_CERTIFICATE: + return "NC"; + case SSL3_AD_BAD_CERTIFICATE: + return "BC"; + case SSL3_AD_UNSUPPORTED_CERTIFICATE: + return "UC"; + case SSL3_AD_CERTIFICATE_REVOKED: + return "CR"; + case SSL3_AD_CERTIFICATE_EXPIRED: + return "CE"; + case SSL3_AD_CERTIFICATE_UNKNOWN: + return "CU"; + case SSL3_AD_ILLEGAL_PARAMETER: + return "IP"; + case TLS1_AD_DECRYPTION_FAILED: + return "DC"; + case TLS1_AD_RECORD_OVERFLOW: + return "RO"; + case TLS1_AD_UNKNOWN_CA: + return "CA"; + case TLS1_AD_ACCESS_DENIED: + return "AD"; + case TLS1_AD_DECODE_ERROR: + return "DE"; + case TLS1_AD_DECRYPT_ERROR: + return "CY"; + case TLS1_AD_EXPORT_RESTRICTION: + return "ER"; + case TLS1_AD_PROTOCOL_VERSION: + return "PV"; + case TLS1_AD_INSUFFICIENT_SECURITY: + return "IS"; + case TLS1_AD_INTERNAL_ERROR: + return "IE"; + case TLS1_AD_USER_CANCELLED: + return "US"; + case TLS1_AD_NO_RENEGOTIATION: + return "NR"; + case TLS1_AD_UNSUPPORTED_EXTENSION: + return "UE"; + case TLS1_AD_CERTIFICATE_UNOBTAINABLE: + return "CO"; + case TLS1_AD_UNRECOGNIZED_NAME: + return "UN"; + case TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE: + return "BR"; + case TLS1_AD_BAD_CERTIFICATE_HASH_VALUE: + return "BH"; + case TLS1_AD_UNKNOWN_PSK_IDENTITY: + return "UP"; + default: + return "UK"; + } +} + +const char *SSL_alert_desc_string_long(int value) +{ + switch (value & 0xff) { + case SSL3_AD_CLOSE_NOTIFY: + return "close notify"; + case SSL3_AD_UNEXPECTED_MESSAGE: + return "unexpected_message"; + case SSL3_AD_BAD_RECORD_MAC: + return "bad record mac"; + case SSL3_AD_DECOMPRESSION_FAILURE: + return "decompression failure"; + case SSL3_AD_HANDSHAKE_FAILURE: + return "handshake failure"; + case SSL3_AD_NO_CERTIFICATE: + return "no certificate"; + case SSL3_AD_BAD_CERTIFICATE: + return "bad certificate"; + case SSL3_AD_UNSUPPORTED_CERTIFICATE: + return "unsupported certificate"; + case SSL3_AD_CERTIFICATE_REVOKED: + return "certificate revoked"; + case SSL3_AD_CERTIFICATE_EXPIRED: + return "certificate expired"; + case SSL3_AD_CERTIFICATE_UNKNOWN: + return "certificate unknown"; + case SSL3_AD_ILLEGAL_PARAMETER: + return "illegal parameter"; + case TLS1_AD_DECRYPTION_FAILED: + return "decryption failed"; + case TLS1_AD_RECORD_OVERFLOW: + return "record overflow"; + case TLS1_AD_UNKNOWN_CA: + return "unknown CA"; + case TLS1_AD_ACCESS_DENIED: + return "access denied"; + case TLS1_AD_DECODE_ERROR: + return "decode error"; + case TLS1_AD_DECRYPT_ERROR: + return "decrypt error"; + case TLS1_AD_EXPORT_RESTRICTION: + return "export restriction"; + case TLS1_AD_PROTOCOL_VERSION: + return "protocol version"; + case TLS1_AD_INSUFFICIENT_SECURITY: + return "insufficient security"; + case TLS1_AD_INTERNAL_ERROR: + return "internal error"; + case TLS1_AD_USER_CANCELLED: + return "user canceled"; + case TLS1_AD_NO_RENEGOTIATION: + return "no renegotiation"; + case TLS1_AD_UNSUPPORTED_EXTENSION: + return "unsupported extension"; + case TLS1_AD_CERTIFICATE_UNOBTAINABLE: + return "certificate unobtainable"; + case TLS1_AD_UNRECOGNIZED_NAME: + return "unrecognized name"; + case TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE: + return "bad certificate status response"; + case TLS1_AD_BAD_CERTIFICATE_HASH_VALUE: + return "bad certificate hash value"; + case TLS1_AD_UNKNOWN_PSK_IDENTITY: + return "unknown PSK identity"; + case TLS1_AD_NO_APPLICATION_PROTOCOL: + return "no application protocol"; + default: + return "unknown"; + } +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_txt.c b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_txt.c new file mode 100644 index 000000000..cf6e4c3c0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_txt.c @@ -0,0 +1,203 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2005 Nokia. All rights reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "ssl_locl.h" + +#ifndef OPENSSL_NO_STDIO +int SSL_SESSION_print_fp(FILE *fp, const SSL_SESSION *x) +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + SSLerr(SSL_F_SSL_SESSION_PRINT_FP, ERR_R_BUF_LIB); + return 0; + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = SSL_SESSION_print(b, x); + BIO_free(b); + return ret; +} +#endif + +int SSL_SESSION_print(BIO *bp, const SSL_SESSION *x) +{ + size_t i; + const char *s; + int istls13; + + if (x == NULL) + goto err; + istls13 = (x->ssl_version == TLS1_3_VERSION); + if (BIO_puts(bp, "SSL-Session:\n") <= 0) + goto err; + s = ssl_protocol_to_string(x->ssl_version); + if (BIO_printf(bp, " Protocol : %s\n", s) <= 0) + goto err; + + if (x->cipher == NULL) { + if (((x->cipher_id) & 0xff000000) == 0x02000000) { + if (BIO_printf(bp, " Cipher : %06lX\n", + x->cipher_id & 0xffffff) <= 0) + goto err; + } else { + if (BIO_printf(bp, " Cipher : %04lX\n", + x->cipher_id & 0xffff) <= 0) + goto err; + } + } else { + if (BIO_printf(bp, " Cipher : %s\n", + ((x->cipher->name == NULL) ? "unknown" + : x->cipher->name)) <= 0) + goto err; + } + if (BIO_puts(bp, " Session-ID: ") <= 0) + goto err; + for (i = 0; i < x->session_id_length; i++) { + if (BIO_printf(bp, "%02X", x->session_id[i]) <= 0) + goto err; + } + if (BIO_puts(bp, "\n Session-ID-ctx: ") <= 0) + goto err; + for (i = 0; i < x->sid_ctx_length; i++) { + if (BIO_printf(bp, "%02X", x->sid_ctx[i]) <= 0) + goto err; + } + if (istls13) { + if (BIO_puts(bp, "\n Resumption PSK: ") <= 0) + goto err; + } else if (BIO_puts(bp, "\n Master-Key: ") <= 0) + goto err; + for (i = 0; i < x->master_key_length; i++) { + if (BIO_printf(bp, "%02X", x->master_key[i]) <= 0) + goto err; + } +#ifndef OPENSSL_NO_PSK + if (BIO_puts(bp, "\n PSK identity: ") <= 0) + goto err; + if (BIO_printf(bp, "%s", x->psk_identity ? x->psk_identity : "None") <= 0) + goto err; + if (BIO_puts(bp, "\n PSK identity hint: ") <= 0) + goto err; + if (BIO_printf + (bp, "%s", x->psk_identity_hint ? x->psk_identity_hint : "None") <= 0) + goto err; +#endif +#ifndef OPENSSL_NO_SRP + if (BIO_puts(bp, "\n SRP username: ") <= 0) + goto err; + if (BIO_printf(bp, "%s", x->srp_username ? x->srp_username : "None") <= 0) + goto err; +#endif + if (x->ext.tick_lifetime_hint) { + if (BIO_printf(bp, + "\n TLS session ticket lifetime hint: %ld (seconds)", + x->ext.tick_lifetime_hint) <= 0) + goto err; + } + if (x->ext.tick) { + if (BIO_puts(bp, "\n TLS session ticket:\n") <= 0) + goto err; + /* TODO(size_t): Convert this call */ + if (BIO_dump_indent + (bp, (const char *)x->ext.tick, (int)x->ext.ticklen, 4) + <= 0) + goto err; + } +#ifndef OPENSSL_NO_COMP + if (x->compress_meth != 0) { + SSL_COMP *comp = NULL; + + if (!ssl_cipher_get_evp(x, NULL, NULL, NULL, NULL, &comp, 0)) + goto err; + if (comp == NULL) { + if (BIO_printf(bp, "\n Compression: %d", x->compress_meth) <= 0) + goto err; + } else { + if (BIO_printf(bp, "\n Compression: %d (%s)", comp->id, + comp->name) <= 0) + goto err; + } + } +#endif + if (x->time != 0L) { + if (BIO_printf(bp, "\n Start Time: %ld", x->time) <= 0) + goto err; + } + if (x->timeout != 0L) { + if (BIO_printf(bp, "\n Timeout : %ld (sec)", x->timeout) <= 0) + goto err; + } + if (BIO_puts(bp, "\n") <= 0) + goto err; + + if (BIO_puts(bp, " Verify return code: ") <= 0) + goto err; + if (BIO_printf(bp, "%ld (%s)\n", x->verify_result, + X509_verify_cert_error_string(x->verify_result)) <= 0) + goto err; + + if (BIO_printf(bp, " Extended master secret: %s\n", + x->flags & SSL_SESS_FLAG_EXTMS ? "yes" : "no") <= 0) + goto err; + + if (istls13) { + if (BIO_printf(bp, " Max Early Data: %u\n", + x->ext.max_early_data) <= 0) + goto err; + } + + return 1; + err: + return 0; +} + +/* + * print session id and master key in NSS keylog format (RSA + * Session-ID: Master-Key:) + */ +int SSL_SESSION_print_keylog(BIO *bp, const SSL_SESSION *x) +{ + size_t i; + + if (x == NULL) + goto err; + if (x->session_id_length == 0 || x->master_key_length == 0) + goto err; + + /* + * the RSA prefix is required by the format's definition although there's + * nothing RSA-specific in the output, therefore, we don't have to check if + * the cipher suite is based on RSA + */ + if (BIO_puts(bp, "RSA ") <= 0) + goto err; + + if (BIO_puts(bp, "Session-ID:") <= 0) + goto err; + for (i = 0; i < x->session_id_length; i++) { + if (BIO_printf(bp, "%02X", x->session_id[i]) <= 0) + goto err; + } + if (BIO_puts(bp, " Master-Key:") <= 0) + goto err; + for (i = 0; i < x->master_key_length; i++) { + if (BIO_printf(bp, "%02X", x->master_key[i]) <= 0) + goto err; + } + if (BIO_puts(bp, "\n") <= 0) + goto err; + + return 1; + err: + return 0; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_utst.c b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_utst.c new file mode 100644 index 000000000..cea1bc270 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/ssl_utst.c @@ -0,0 +1,24 @@ +/* + * Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "ssl_locl.h" + +#ifndef OPENSSL_NO_UNIT_TEST + +static const struct openssl_ssl_test_functions ssl_test_functions = { + ssl_init_wbio_buffer, + ssl3_setup_buffers, +}; + +const struct openssl_ssl_test_functions *SSL_test_functions(void) +{ + return &ssl_test_functions; +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/statem/README b/trunk/3rdparty/openssl-1.1-fit/ssl/statem/README new file mode 100644 index 000000000..145c69db8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/statem/README @@ -0,0 +1,63 @@ +State Machine Design +==================== + +This file provides some guidance on the thinking behind the design of the +state machine code to aid future maintenance. + +The state machine code replaces an older state machine present in OpenSSL +versions 1.0.2 and below. The new state machine has the following objectives: + - Remove duplication of state code between client and server + - Remove duplication of state code between TLS and DTLS + - Simplify transitions and bring the logic together in a single location + so that it is easier to validate + - Remove duplication of code between each of the message handling functions + - Receive a message first and then work out whether that is a valid + transition - not the other way around (the other way causes lots of issues + where we are expecting one type of message next but actually get something + else) + - Separate message flow state from handshake state (in order to better + understand each) + - message flow state = when to flush buffers; handling restarts in the + event of NBIO events; handling the common flow of steps for reading a + message and the common flow of steps for writing a message etc + - handshake state = what handshake message are we working on now + - Control complexity: only the state machine can change state: keep all + the state changes local to the state machine component + +The message flow state machine is divided into a reading sub-state machine and a +writing sub-state machine. See the source comments in statem.c for a more +detailed description of the various states and transitions possible. + +Conceptually the state machine component is designed as follows: + + libssl + | +---------------------------|-----statem.h-------------------------------------- + | + _______V____________________ + | | + | statem.c | + | | + | Core state machine code | + |____________________________| + statem_locl.h ^ ^ + _________| |_______ + | | + _____________|____________ _____________|____________ + | | | | + | statem_clnt.c | | statem_srvr.c | + | | | | + | TLS/DTLS client specific | | TLS/DTLS server specific | + | state machine code | | state machine code | + |__________________________| |__________________________| + | |_______________|__ | + | ________________| | | + | | | | + ____________V_______V________ ________V______V_______________ + | | | | + | statem_both.c | | statem_dtls.c | + | | | | + | Non core functions common | | Non core functions common to | + | to both servers and clients | | both DTLS servers and clients | + |_____________________________| |_______________________________| + diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/statem/extensions.c b/trunk/3rdparty/openssl-1.1-fit/ssl/statem/extensions.c new file mode 100644 index 000000000..c3d3441a1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/statem/extensions.c @@ -0,0 +1,1700 @@ +/* + * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/nelem.h" +#include "internal/cryptlib.h" +#include "../ssl_locl.h" +#include "statem_locl.h" +#include "internal/cryptlib.h" + +static int final_renegotiate(SSL *s, unsigned int context, int sent); +static int init_server_name(SSL *s, unsigned int context); +static int final_server_name(SSL *s, unsigned int context, int sent); +#ifndef OPENSSL_NO_EC +static int final_ec_pt_formats(SSL *s, unsigned int context, int sent); +#endif +static int init_session_ticket(SSL *s, unsigned int context); +#ifndef OPENSSL_NO_OCSP +static int init_status_request(SSL *s, unsigned int context); +#endif +#ifndef OPENSSL_NO_NEXTPROTONEG +static int init_npn(SSL *s, unsigned int context); +#endif +static int init_alpn(SSL *s, unsigned int context); +static int final_alpn(SSL *s, unsigned int context, int sent); +static int init_sig_algs_cert(SSL *s, unsigned int context); +static int init_sig_algs(SSL *s, unsigned int context); +static int init_certificate_authorities(SSL *s, unsigned int context); +static EXT_RETURN tls_construct_certificate_authorities(SSL *s, WPACKET *pkt, + unsigned int context, + X509 *x, + size_t chainidx); +static int tls_parse_certificate_authorities(SSL *s, PACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +#ifndef OPENSSL_NO_SRP +static int init_srp(SSL *s, unsigned int context); +#endif +static int init_etm(SSL *s, unsigned int context); +static int init_ems(SSL *s, unsigned int context); +static int final_ems(SSL *s, unsigned int context, int sent); +static int init_psk_kex_modes(SSL *s, unsigned int context); +#ifndef OPENSSL_NO_EC +static int final_key_share(SSL *s, unsigned int context, int sent); +#endif +#ifndef OPENSSL_NO_SRTP +static int init_srtp(SSL *s, unsigned int context); +#endif +static int final_sig_algs(SSL *s, unsigned int context, int sent); +static int final_early_data(SSL *s, unsigned int context, int sent); +static int final_maxfragmentlen(SSL *s, unsigned int context, int sent); +static int init_post_handshake_auth(SSL *s, unsigned int context); + +/* Structure to define a built-in extension */ +typedef struct extensions_definition_st { + /* The defined type for the extension */ + unsigned int type; + /* + * The context that this extension applies to, e.g. what messages and + * protocol versions + */ + unsigned int context; + /* + * Initialise extension before parsing. Always called for relevant contexts + * even if extension not present + */ + int (*init)(SSL *s, unsigned int context); + /* Parse extension sent from client to server */ + int (*parse_ctos)(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); + /* Parse extension send from server to client */ + int (*parse_stoc)(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); + /* Construct extension sent from server to client */ + EXT_RETURN (*construct_stoc)(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); + /* Construct extension sent from client to server */ + EXT_RETURN (*construct_ctos)(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); + /* + * Finalise extension after parsing. Always called where an extensions was + * initialised even if the extension was not present. |sent| is set to 1 if + * the extension was seen, or 0 otherwise. + */ + int (*final)(SSL *s, unsigned int context, int sent); +} EXTENSION_DEFINITION; + +/* + * Definitions of all built-in extensions. NOTE: Changes in the number or order + * of these extensions should be mirrored with equivalent changes to the + * indexes ( TLSEXT_IDX_* ) defined in ssl_locl.h. + * Each extension has an initialiser, a client and + * server side parser and a finaliser. The initialiser is called (if the + * extension is relevant to the given context) even if we did not see the + * extension in the message that we received. The parser functions are only + * called if we see the extension in the message. The finalisers are always + * called if the initialiser was called. + * There are also server and client side constructor functions which are always + * called during message construction if the extension is relevant for the + * given context. + * The initialisation, parsing, finalisation and construction functions are + * always called in the order defined in this list. Some extensions may depend + * on others having been processed first, so the order of this list is + * significant. + * The extension context is defined by a series of flags which specify which + * messages the extension is relevant to. These flags also specify whether the + * extension is relevant to a particular protocol or protocol version. + * + * TODO(TLS1.3): Make sure we have a test to check the consistency of these + * + * NOTE: WebSphere Application Server 7+ cannot handle empty extensions at + * the end, keep these extensions before signature_algorithm. + */ +#define INVALID_EXTENSION { 0x10000, 0, NULL, NULL, NULL, NULL, NULL, NULL } +static const EXTENSION_DEFINITION ext_defs[] = { + { + TLSEXT_TYPE_renegotiate, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_SSL3_ALLOWED | SSL_EXT_TLS1_2_AND_BELOW_ONLY, + NULL, tls_parse_ctos_renegotiate, tls_parse_stoc_renegotiate, + tls_construct_stoc_renegotiate, tls_construct_ctos_renegotiate, + final_renegotiate + }, + { + TLSEXT_TYPE_server_name, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS, + init_server_name, + tls_parse_ctos_server_name, tls_parse_stoc_server_name, + tls_construct_stoc_server_name, tls_construct_ctos_server_name, + final_server_name + }, + { + TLSEXT_TYPE_max_fragment_length, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS, + NULL, tls_parse_ctos_maxfragmentlen, tls_parse_stoc_maxfragmentlen, + tls_construct_stoc_maxfragmentlen, tls_construct_ctos_maxfragmentlen, + final_maxfragmentlen + }, +#ifndef OPENSSL_NO_SRP + { + TLSEXT_TYPE_srp, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_AND_BELOW_ONLY, + init_srp, tls_parse_ctos_srp, NULL, NULL, tls_construct_ctos_srp, NULL + }, +#else + INVALID_EXTENSION, +#endif +#ifndef OPENSSL_NO_EC + { + TLSEXT_TYPE_ec_point_formats, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_2_AND_BELOW_ONLY, + NULL, tls_parse_ctos_ec_pt_formats, tls_parse_stoc_ec_pt_formats, + tls_construct_stoc_ec_pt_formats, tls_construct_ctos_ec_pt_formats, + final_ec_pt_formats + }, + { + /* + * "supported_groups" is spread across several specifications. + * It was originally specified as "elliptic_curves" in RFC 4492, + * and broadened to include named FFDH groups by RFC 7919. + * Both RFCs 4492 and 7919 do not include a provision for the server + * to indicate to the client the complete list of groups supported + * by the server, with the server instead just indicating the + * selected group for this connection in the ServerKeyExchange + * message. TLS 1.3 adds a scheme for the server to indicate + * to the client its list of supported groups in the + * EncryptedExtensions message, but none of the relevant + * specifications permit sending supported_groups in the ServerHello. + * Nonetheless (possibly due to the close proximity to the + * "ec_point_formats" extension, which is allowed in the ServerHello), + * there are several servers that send this extension in the + * ServerHello anyway. Up to and including the 1.1.0 release, + * we did not check for the presence of nonpermitted extensions, + * so to avoid a regression, we must permit this extension in the + * TLS 1.2 ServerHello as well. + * + * Note that there is no tls_parse_stoc_supported_groups function, + * so we do not perform any additional parsing, validation, or + * processing on the server's group list -- this is just a minimal + * change to preserve compatibility with these misbehaving servers. + */ + TLSEXT_TYPE_supported_groups, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS + | SSL_EXT_TLS1_2_SERVER_HELLO, + NULL, tls_parse_ctos_supported_groups, NULL, + tls_construct_stoc_supported_groups, + tls_construct_ctos_supported_groups, NULL + }, +#else + INVALID_EXTENSION, + INVALID_EXTENSION, +#endif + { + TLSEXT_TYPE_session_ticket, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_2_AND_BELOW_ONLY, + init_session_ticket, tls_parse_ctos_session_ticket, + tls_parse_stoc_session_ticket, tls_construct_stoc_session_ticket, + tls_construct_ctos_session_ticket, NULL + }, +#ifndef OPENSSL_NO_OCSP + { + TLSEXT_TYPE_status_request, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_3_CERTIFICATE | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST, + init_status_request, tls_parse_ctos_status_request, + tls_parse_stoc_status_request, tls_construct_stoc_status_request, + tls_construct_ctos_status_request, NULL + }, +#else + INVALID_EXTENSION, +#endif +#ifndef OPENSSL_NO_NEXTPROTONEG + { + TLSEXT_TYPE_next_proto_neg, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_2_AND_BELOW_ONLY, + init_npn, tls_parse_ctos_npn, tls_parse_stoc_npn, + tls_construct_stoc_next_proto_neg, tls_construct_ctos_npn, NULL + }, +#else + INVALID_EXTENSION, +#endif + { + /* + * Must appear in this list after server_name so that finalisation + * happens after server_name callbacks + */ + TLSEXT_TYPE_application_layer_protocol_negotiation, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS, + init_alpn, tls_parse_ctos_alpn, tls_parse_stoc_alpn, + tls_construct_stoc_alpn, tls_construct_ctos_alpn, final_alpn + }, +#ifndef OPENSSL_NO_SRTP + { + TLSEXT_TYPE_use_srtp, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS | SSL_EXT_DTLS_ONLY, + init_srtp, tls_parse_ctos_use_srtp, tls_parse_stoc_use_srtp, + tls_construct_stoc_use_srtp, tls_construct_ctos_use_srtp, NULL + }, +#else + INVALID_EXTENSION, +#endif + { + TLSEXT_TYPE_encrypt_then_mac, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_2_AND_BELOW_ONLY, + init_etm, tls_parse_ctos_etm, tls_parse_stoc_etm, + tls_construct_stoc_etm, tls_construct_ctos_etm, NULL + }, +#ifndef OPENSSL_NO_CT + { + TLSEXT_TYPE_signed_certificate_timestamp, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_3_CERTIFICATE | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST, + NULL, + /* + * No server side support for this, but can be provided by a custom + * extension. This is an exception to the rule that custom extensions + * cannot override built in ones. + */ + NULL, tls_parse_stoc_sct, NULL, tls_construct_ctos_sct, NULL + }, +#else + INVALID_EXTENSION, +#endif + { + TLSEXT_TYPE_extended_master_secret, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_2_AND_BELOW_ONLY, + init_ems, tls_parse_ctos_ems, tls_parse_stoc_ems, + tls_construct_stoc_ems, tls_construct_ctos_ems, final_ems + }, + { + TLSEXT_TYPE_signature_algorithms_cert, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST, + init_sig_algs_cert, tls_parse_ctos_sig_algs_cert, + tls_parse_ctos_sig_algs_cert, + /* We do not generate signature_algorithms_cert at present. */ + NULL, NULL, NULL + }, + { + TLSEXT_TYPE_post_handshake_auth, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ONLY, + init_post_handshake_auth, + tls_parse_ctos_post_handshake_auth, NULL, + NULL, tls_construct_ctos_post_handshake_auth, + NULL, + }, + { + TLSEXT_TYPE_signature_algorithms, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST, + init_sig_algs, tls_parse_ctos_sig_algs, + tls_parse_ctos_sig_algs, tls_construct_ctos_sig_algs, + tls_construct_ctos_sig_algs, final_sig_algs + }, + { + TLSEXT_TYPE_supported_versions, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_SERVER_HELLO + | SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST | SSL_EXT_TLS_IMPLEMENTATION_ONLY, + NULL, + /* Processed inline as part of version selection */ + NULL, tls_parse_stoc_supported_versions, + tls_construct_stoc_supported_versions, + tls_construct_ctos_supported_versions, NULL + }, + { + TLSEXT_TYPE_psk_kex_modes, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS_IMPLEMENTATION_ONLY + | SSL_EXT_TLS1_3_ONLY, + init_psk_kex_modes, tls_parse_ctos_psk_kex_modes, NULL, NULL, + tls_construct_ctos_psk_kex_modes, NULL + }, +#ifndef OPENSSL_NO_EC + { + /* + * Must be in this list after supported_groups. We need that to have + * been parsed before we do this one. + */ + TLSEXT_TYPE_key_share, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_SERVER_HELLO + | SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST | SSL_EXT_TLS_IMPLEMENTATION_ONLY + | SSL_EXT_TLS1_3_ONLY, + NULL, tls_parse_ctos_key_share, tls_parse_stoc_key_share, + tls_construct_stoc_key_share, tls_construct_ctos_key_share, + final_key_share + }, +#endif + { + /* Must be after key_share */ + TLSEXT_TYPE_cookie, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST + | SSL_EXT_TLS_IMPLEMENTATION_ONLY | SSL_EXT_TLS1_3_ONLY, + NULL, tls_parse_ctos_cookie, tls_parse_stoc_cookie, + tls_construct_stoc_cookie, tls_construct_ctos_cookie, NULL + }, + { + /* + * Special unsolicited ServerHello extension only used when + * SSL_OP_CRYPTOPRO_TLSEXT_BUG is set. We allow it in a ClientHello but + * ignore it. + */ + TLSEXT_TYPE_cryptopro_bug, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_2_AND_BELOW_ONLY, + NULL, NULL, NULL, tls_construct_stoc_cryptopro_bug, NULL, NULL + }, + { + TLSEXT_TYPE_early_data, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS + | SSL_EXT_TLS1_3_NEW_SESSION_TICKET | SSL_EXT_TLS1_3_ONLY, + NULL, tls_parse_ctos_early_data, tls_parse_stoc_early_data, + tls_construct_stoc_early_data, tls_construct_ctos_early_data, + final_early_data + }, + { + TLSEXT_TYPE_certificate_authorities, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST + | SSL_EXT_TLS1_3_ONLY, + init_certificate_authorities, + tls_parse_certificate_authorities, tls_parse_certificate_authorities, + tls_construct_certificate_authorities, + tls_construct_certificate_authorities, NULL, + }, + { + /* Must be immediately before pre_shared_key */ + TLSEXT_TYPE_padding, + SSL_EXT_CLIENT_HELLO, + NULL, + /* We send this, but don't read it */ + NULL, NULL, NULL, tls_construct_ctos_padding, NULL + }, + { + /* Required by the TLSv1.3 spec to always be the last extension */ + TLSEXT_TYPE_psk, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_SERVER_HELLO + | SSL_EXT_TLS_IMPLEMENTATION_ONLY | SSL_EXT_TLS1_3_ONLY, + NULL, tls_parse_ctos_psk, tls_parse_stoc_psk, tls_construct_stoc_psk, + tls_construct_ctos_psk, NULL + } +}; + +/* Check whether an extension's context matches the current context */ +static int validate_context(SSL *s, unsigned int extctx, unsigned int thisctx) +{ + /* Check we're allowed to use this extension in this context */ + if ((thisctx & extctx) == 0) + return 0; + + if (SSL_IS_DTLS(s)) { + if ((extctx & SSL_EXT_TLS_ONLY) != 0) + return 0; + } else if ((extctx & SSL_EXT_DTLS_ONLY) != 0) { + return 0; + } + + return 1; +} + +int tls_validate_all_contexts(SSL *s, unsigned int thisctx, RAW_EXTENSION *exts) +{ + size_t i, num_exts, builtin_num = OSSL_NELEM(ext_defs), offset; + RAW_EXTENSION *thisext; + unsigned int context; + ENDPOINT role = ENDPOINT_BOTH; + + if ((thisctx & SSL_EXT_CLIENT_HELLO) != 0) + role = ENDPOINT_SERVER; + else if ((thisctx & SSL_EXT_TLS1_2_SERVER_HELLO) != 0) + role = ENDPOINT_CLIENT; + + /* Calculate the number of extensions in the extensions list */ + num_exts = builtin_num + s->cert->custext.meths_count; + + for (thisext = exts, i = 0; i < num_exts; i++, thisext++) { + if (!thisext->present) + continue; + + if (i < builtin_num) { + context = ext_defs[i].context; + } else { + custom_ext_method *meth = NULL; + + meth = custom_ext_find(&s->cert->custext, role, thisext->type, + &offset); + if (!ossl_assert(meth != NULL)) + return 0; + context = meth->context; + } + + if (!validate_context(s, context, thisctx)) + return 0; + } + + return 1; +} + +/* + * Verify whether we are allowed to use the extension |type| in the current + * |context|. Returns 1 to indicate the extension is allowed or unknown or 0 to + * indicate the extension is not allowed. If returning 1 then |*found| is set to + * the definition for the extension we found. + */ +static int verify_extension(SSL *s, unsigned int context, unsigned int type, + custom_ext_methods *meths, RAW_EXTENSION *rawexlist, + RAW_EXTENSION **found) +{ + size_t i; + size_t builtin_num = OSSL_NELEM(ext_defs); + const EXTENSION_DEFINITION *thisext; + + for (i = 0, thisext = ext_defs; i < builtin_num; i++, thisext++) { + if (type == thisext->type) { + if (!validate_context(s, thisext->context, context)) + return 0; + + *found = &rawexlist[i]; + return 1; + } + } + + /* Check the custom extensions */ + if (meths != NULL) { + size_t offset = 0; + ENDPOINT role = ENDPOINT_BOTH; + custom_ext_method *meth = NULL; + + if ((context & SSL_EXT_CLIENT_HELLO) != 0) + role = ENDPOINT_SERVER; + else if ((context & SSL_EXT_TLS1_2_SERVER_HELLO) != 0) + role = ENDPOINT_CLIENT; + + meth = custom_ext_find(meths, role, type, &offset); + if (meth != NULL) { + if (!validate_context(s, meth->context, context)) + return 0; + *found = &rawexlist[offset + builtin_num]; + return 1; + } + } + + /* Unknown extension. We allow it */ + *found = NULL; + return 1; +} + +/* + * Check whether the context defined for an extension |extctx| means whether + * the extension is relevant for the current context |thisctx| or not. Returns + * 1 if the extension is relevant for this context, and 0 otherwise + */ +int extension_is_relevant(SSL *s, unsigned int extctx, unsigned int thisctx) +{ + int is_tls13; + + /* + * For HRR we haven't selected the version yet but we know it will be + * TLSv1.3 + */ + if ((thisctx & SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST) != 0) + is_tls13 = 1; + else + is_tls13 = SSL_IS_TLS13(s); + + if ((SSL_IS_DTLS(s) + && (extctx & SSL_EXT_TLS_IMPLEMENTATION_ONLY) != 0) + || (s->version == SSL3_VERSION + && (extctx & SSL_EXT_SSL3_ALLOWED) == 0) + /* + * Note that SSL_IS_TLS13() means "TLS 1.3 has been negotiated", + * which is never true when generating the ClientHello. + * However, version negotiation *has* occurred by the time the + * ClientHello extensions are being parsed. + * Be careful to allow TLS 1.3-only extensions when generating + * the ClientHello. + */ + || (is_tls13 && (extctx & SSL_EXT_TLS1_2_AND_BELOW_ONLY) != 0) + || (!is_tls13 && (extctx & SSL_EXT_TLS1_3_ONLY) != 0 + && (thisctx & SSL_EXT_CLIENT_HELLO) == 0) + || (s->server && !is_tls13 && (extctx & SSL_EXT_TLS1_3_ONLY) != 0) + || (s->hit && (extctx & SSL_EXT_IGNORE_ON_RESUMPTION) != 0)) + return 0; + return 1; +} + +/* + * Gather a list of all the extensions from the data in |packet]. |context| + * tells us which message this extension is for. The raw extension data is + * stored in |*res| on success. We don't actually process the content of the + * extensions yet, except to check their types. This function also runs the + * initialiser functions for all known extensions if |init| is nonzero (whether + * we have collected them or not). If successful the caller is responsible for + * freeing the contents of |*res|. + * + * Per http://tools.ietf.org/html/rfc5246#section-7.4.1.4, there may not be + * more than one extension of the same type in a ClientHello or ServerHello. + * This function returns 1 if all extensions are unique and we have parsed their + * types, and 0 if the extensions contain duplicates, could not be successfully + * found, or an internal error occurred. We only check duplicates for + * extensions that we know about. We ignore others. + */ +int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context, + RAW_EXTENSION **res, size_t *len, int init) +{ + PACKET extensions = *packet; + size_t i = 0; + size_t num_exts; + custom_ext_methods *exts = &s->cert->custext; + RAW_EXTENSION *raw_extensions = NULL; + const EXTENSION_DEFINITION *thisexd; + + *res = NULL; + + /* + * Initialise server side custom extensions. Client side is done during + * construction of extensions for the ClientHello. + */ + if ((context & SSL_EXT_CLIENT_HELLO) != 0) + custom_ext_init(&s->cert->custext); + + num_exts = OSSL_NELEM(ext_defs) + (exts != NULL ? exts->meths_count : 0); + raw_extensions = OPENSSL_zalloc(num_exts * sizeof(*raw_extensions)); + if (raw_extensions == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_COLLECT_EXTENSIONS, + ERR_R_MALLOC_FAILURE); + return 0; + } + + i = 0; + while (PACKET_remaining(&extensions) > 0) { + unsigned int type, idx; + PACKET extension; + RAW_EXTENSION *thisex; + + if (!PACKET_get_net_2(&extensions, &type) || + !PACKET_get_length_prefixed_2(&extensions, &extension)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_COLLECT_EXTENSIONS, + SSL_R_BAD_EXTENSION); + goto err; + } + /* + * Verify this extension is allowed. We only check duplicates for + * extensions that we recognise. We also have a special case for the + * PSK extension, which must be the last one in the ClientHello. + */ + if (!verify_extension(s, context, type, exts, raw_extensions, &thisex) + || (thisex != NULL && thisex->present == 1) + || (type == TLSEXT_TYPE_psk + && (context & SSL_EXT_CLIENT_HELLO) != 0 + && PACKET_remaining(&extensions) != 0)) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_COLLECT_EXTENSIONS, + SSL_R_BAD_EXTENSION); + goto err; + } + idx = thisex - raw_extensions; + /*- + * Check that we requested this extension (if appropriate). Requests can + * be sent in the ClientHello and CertificateRequest. Unsolicited + * extensions can be sent in the NewSessionTicket. We only do this for + * the built-in extensions. Custom extensions have a different but + * similar check elsewhere. + * Special cases: + * - The HRR cookie extension is unsolicited + * - The renegotiate extension is unsolicited (the client signals + * support via an SCSV) + * - The signed_certificate_timestamp extension can be provided by a + * custom extension or by the built-in version. We let the extension + * itself handle unsolicited response checks. + */ + if (idx < OSSL_NELEM(ext_defs) + && (context & (SSL_EXT_CLIENT_HELLO + | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST + | SSL_EXT_TLS1_3_NEW_SESSION_TICKET)) == 0 + && type != TLSEXT_TYPE_cookie + && type != TLSEXT_TYPE_renegotiate + && type != TLSEXT_TYPE_signed_certificate_timestamp + && (s->ext.extflags[idx] & SSL_EXT_FLAG_SENT) == 0 +#ifndef OPENSSL_NO_GOST + && !((context & SSL_EXT_TLS1_2_SERVER_HELLO) != 0 + && type == TLSEXT_TYPE_cryptopro_bug) +#endif + ) { + SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION, + SSL_F_TLS_COLLECT_EXTENSIONS, SSL_R_UNSOLICITED_EXTENSION); + goto err; + } + if (thisex != NULL) { + thisex->data = extension; + thisex->present = 1; + thisex->type = type; + thisex->received_order = i++; + if (s->ext.debug_cb) + s->ext.debug_cb(s, !s->server, thisex->type, + PACKET_data(&thisex->data), + PACKET_remaining(&thisex->data), + s->ext.debug_arg); + } + } + + if (init) { + /* + * Initialise all known extensions relevant to this context, + * whether we have found them or not + */ + for (thisexd = ext_defs, i = 0; i < OSSL_NELEM(ext_defs); + i++, thisexd++) { + if (thisexd->init != NULL && (thisexd->context & context) != 0 + && extension_is_relevant(s, thisexd->context, context) + && !thisexd->init(s, context)) { + /* SSLfatal() already called */ + goto err; + } + } + } + + *res = raw_extensions; + if (len != NULL) + *len = num_exts; + return 1; + + err: + OPENSSL_free(raw_extensions); + return 0; +} + +/* + * Runs the parser for a given extension with index |idx|. |exts| contains the + * list of all parsed extensions previously collected by + * tls_collect_extensions(). The parser is only run if it is applicable for the + * given |context| and the parser has not already been run. If this is for a + * Certificate message, then we also provide the parser with the relevant + * Certificate |x| and its position in the |chainidx| with 0 being the first + * Certificate. Returns 1 on success or 0 on failure. If an extension is not + * present this counted as success. + */ +int tls_parse_extension(SSL *s, TLSEXT_INDEX idx, int context, + RAW_EXTENSION *exts, X509 *x, size_t chainidx) +{ + RAW_EXTENSION *currext = &exts[idx]; + int (*parser)(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) = NULL; + + /* Skip if the extension is not present */ + if (!currext->present) + return 1; + + /* Skip if we've already parsed this extension */ + if (currext->parsed) + return 1; + + currext->parsed = 1; + + if (idx < OSSL_NELEM(ext_defs)) { + /* We are handling a built-in extension */ + const EXTENSION_DEFINITION *extdef = &ext_defs[idx]; + + /* Check if extension is defined for our protocol. If not, skip */ + if (!extension_is_relevant(s, extdef->context, context)) + return 1; + + parser = s->server ? extdef->parse_ctos : extdef->parse_stoc; + + if (parser != NULL) + return parser(s, &currext->data, context, x, chainidx); + + /* + * If the parser is NULL we fall through to the custom extension + * processing + */ + } + + /* Parse custom extensions */ + return custom_ext_parse(s, context, currext->type, + PACKET_data(&currext->data), + PACKET_remaining(&currext->data), + x, chainidx); +} + +/* + * Parse all remaining extensions that have not yet been parsed. Also calls the + * finalisation for all extensions at the end if |fin| is nonzero, whether we + * collected them or not. Returns 1 for success or 0 for failure. If we are + * working on a Certificate message then we also pass the Certificate |x| and + * its position in the |chainidx|, with 0 being the first certificate. + */ +int tls_parse_all_extensions(SSL *s, int context, RAW_EXTENSION *exts, X509 *x, + size_t chainidx, int fin) +{ + size_t i, numexts = OSSL_NELEM(ext_defs); + const EXTENSION_DEFINITION *thisexd; + + /* Calculate the number of extensions in the extensions list */ + numexts += s->cert->custext.meths_count; + + /* Parse each extension in turn */ + for (i = 0; i < numexts; i++) { + if (!tls_parse_extension(s, i, context, exts, x, chainidx)) { + /* SSLfatal() already called */ + return 0; + } + } + + if (fin) { + /* + * Finalise all known extensions relevant to this context, + * whether we have found them or not + */ + for (i = 0, thisexd = ext_defs; i < OSSL_NELEM(ext_defs); + i++, thisexd++) { + if (thisexd->final != NULL && (thisexd->context & context) != 0 + && !thisexd->final(s, context, exts[i].present)) { + /* SSLfatal() already called */ + return 0; + } + } + } + + return 1; +} + +int should_add_extension(SSL *s, unsigned int extctx, unsigned int thisctx, + int max_version) +{ + /* Skip if not relevant for our context */ + if ((extctx & thisctx) == 0) + return 0; + + /* Check if this extension is defined for our protocol. If not, skip */ + if (!extension_is_relevant(s, extctx, thisctx) + || ((extctx & SSL_EXT_TLS1_3_ONLY) != 0 + && (thisctx & SSL_EXT_CLIENT_HELLO) != 0 + && (SSL_IS_DTLS(s) || max_version < TLS1_3_VERSION))) + return 0; + + return 1; +} + +/* + * Construct all the extensions relevant to the current |context| and write + * them to |pkt|. If this is an extension for a Certificate in a Certificate + * message, then |x| will be set to the Certificate we are handling, and + * |chainidx| will indicate the position in the chainidx we are processing (with + * 0 being the first in the chain). Returns 1 on success or 0 on failure. On a + * failure construction stops at the first extension to fail to construct. + */ +int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + size_t i; + int min_version, max_version = 0, reason; + const EXTENSION_DEFINITION *thisexd; + + if (!WPACKET_start_sub_packet_u16(pkt) + /* + * If extensions are of zero length then we don't even add the + * extensions length bytes to a ClientHello/ServerHello + * (for non-TLSv1.3). + */ + || ((context & + (SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO)) != 0 + && !WPACKET_set_flags(pkt, + WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH))) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_EXTENSIONS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + if ((context & SSL_EXT_CLIENT_HELLO) != 0) { + reason = ssl_get_min_max_version(s, &min_version, &max_version, NULL); + if (reason != 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_EXTENSIONS, + reason); + return 0; + } + } + + /* Add custom extensions first */ + if ((context & SSL_EXT_CLIENT_HELLO) != 0) { + /* On the server side with initialise during ClientHello parsing */ + custom_ext_init(&s->cert->custext); + } + if (!custom_ext_add(s, context, pkt, x, chainidx, max_version)) { + /* SSLfatal() already called */ + return 0; + } + + for (i = 0, thisexd = ext_defs; i < OSSL_NELEM(ext_defs); i++, thisexd++) { + EXT_RETURN (*construct)(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); + EXT_RETURN ret; + + /* Skip if not relevant for our context */ + if (!should_add_extension(s, thisexd->context, context, max_version)) + continue; + + construct = s->server ? thisexd->construct_stoc + : thisexd->construct_ctos; + + if (construct == NULL) + continue; + + ret = construct(s, pkt, context, x, chainidx); + if (ret == EXT_RETURN_FAIL) { + /* SSLfatal() already called */ + return 0; + } + if (ret == EXT_RETURN_SENT + && (context & (SSL_EXT_CLIENT_HELLO + | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST + | SSL_EXT_TLS1_3_NEW_SESSION_TICKET)) != 0) + s->ext.extflags[i] |= SSL_EXT_FLAG_SENT; + } + + if (!WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_EXTENSIONS, + ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} + +/* + * Built in extension finalisation and initialisation functions. All initialise + * or finalise the associated extension type for the given |context|. For + * finalisers |sent| is set to 1 if we saw the extension during parsing, and 0 + * otherwise. These functions return 1 on success or 0 on failure. + */ + +static int final_renegotiate(SSL *s, unsigned int context, int sent) +{ + if (!s->server) { + /* + * Check if we can connect to a server that doesn't support safe + * renegotiation + */ + if (!(s->options & SSL_OP_LEGACY_SERVER_CONNECT) + && !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) + && !sent) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_FINAL_RENEGOTIATE, + SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); + return 0; + } + + return 1; + } + + /* Need RI if renegotiating */ + if (s->renegotiate + && !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) + && !sent) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_FINAL_RENEGOTIATE, + SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); + return 0; + } + + + return 1; +} + +static int init_server_name(SSL *s, unsigned int context) +{ + if (s->server) { + s->servername_done = 0; + + OPENSSL_free(s->ext.hostname); + s->ext.hostname = NULL; + } + + return 1; +} + +static int final_server_name(SSL *s, unsigned int context, int sent) +{ + int ret = SSL_TLSEXT_ERR_NOACK; + int altmp = SSL_AD_UNRECOGNIZED_NAME; + int was_ticket = (SSL_get_options(s) & SSL_OP_NO_TICKET) == 0; + + if (!ossl_assert(s->ctx != NULL) || !ossl_assert(s->session_ctx != NULL)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME, + ERR_R_INTERNAL_ERROR); + return 0; + } + + if (s->ctx->ext.servername_cb != NULL) + ret = s->ctx->ext.servername_cb(s, &altmp, + s->ctx->ext.servername_arg); + else if (s->session_ctx->ext.servername_cb != NULL) + ret = s->session_ctx->ext.servername_cb(s, &altmp, + s->session_ctx->ext.servername_arg); + + /* + * For servers, propagate the SNI hostname from the temporary + * storage in the SSL to the persistent SSL_SESSION, now that we + * know we accepted it. + * Clients make this copy when parsing the server's response to + * the extension, which is when they find out that the negotiation + * was successful. + */ + if (s->server) { + /* TODO(OpenSSL1.2) revisit !sent case */ + if (sent && ret == SSL_TLSEXT_ERR_OK && (!s->hit || SSL_IS_TLS13(s))) { + /* Only store the hostname in the session if we accepted it. */ + OPENSSL_free(s->session->ext.hostname); + s->session->ext.hostname = OPENSSL_strdup(s->ext.hostname); + if (s->session->ext.hostname == NULL && s->ext.hostname != NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME, + ERR_R_INTERNAL_ERROR); + } + } + } + + /* + * If we switched contexts (whether here or in the client_hello callback), + * move the sess_accept increment from the session_ctx to the new + * context, to avoid the confusing situation of having sess_accept_good + * exceed sess_accept (zero) for the new context. + */ + if (SSL_IS_FIRST_HANDSHAKE(s) && s->ctx != s->session_ctx) { + tsan_counter(&s->ctx->stats.sess_accept); + tsan_decr(&s->session_ctx->stats.sess_accept); + } + + /* + * If we're expecting to send a ticket, and tickets were previously enabled, + * and now tickets are disabled, then turn off expected ticket. + * Also, if this is not a resumption, create a new session ID + */ + if (ret == SSL_TLSEXT_ERR_OK && s->ext.ticket_expected + && was_ticket && (SSL_get_options(s) & SSL_OP_NO_TICKET) != 0) { + s->ext.ticket_expected = 0; + if (!s->hit) { + SSL_SESSION* ss = SSL_get_session(s); + + if (ss != NULL) { + OPENSSL_free(ss->ext.tick); + ss->ext.tick = NULL; + ss->ext.ticklen = 0; + ss->ext.tick_lifetime_hint = 0; + ss->ext.tick_age_add = 0; + ss->ext.tick_identity = 0; + if (!ssl_generate_session_id(s, ss)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME, + ERR_R_INTERNAL_ERROR); + return 0; + } + } else { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME, + ERR_R_INTERNAL_ERROR); + return 0; + } + } + } + + switch (ret) { + case SSL_TLSEXT_ERR_ALERT_FATAL: + SSLfatal(s, altmp, SSL_F_FINAL_SERVER_NAME, SSL_R_CALLBACK_FAILED); + return 0; + + case SSL_TLSEXT_ERR_ALERT_WARNING: + /* TLSv1.3 doesn't have warning alerts so we suppress this */ + if (!SSL_IS_TLS13(s)) + ssl3_send_alert(s, SSL3_AL_WARNING, altmp); + return 1; + + case SSL_TLSEXT_ERR_NOACK: + s->servername_done = 0; + return 1; + + default: + return 1; + } +} + +#ifndef OPENSSL_NO_EC +static int final_ec_pt_formats(SSL *s, unsigned int context, int sent) +{ + unsigned long alg_k, alg_a; + + if (s->server) + return 1; + + alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + alg_a = s->s3->tmp.new_cipher->algorithm_auth; + + /* + * If we are client and using an elliptic curve cryptography cipher + * suite, then if server returns an EC point formats lists extension it + * must contain uncompressed. + */ + if (s->ext.ecpointformats != NULL + && s->ext.ecpointformats_len > 0 + && s->session->ext.ecpointformats != NULL + && s->session->ext.ecpointformats_len > 0 + && ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA))) { + /* we are using an ECC cipher */ + size_t i; + unsigned char *list = s->session->ext.ecpointformats; + + for (i = 0; i < s->session->ext.ecpointformats_len; i++) { + if (*list++ == TLSEXT_ECPOINTFORMAT_uncompressed) + break; + } + if (i == s->session->ext.ecpointformats_len) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_FINAL_EC_PT_FORMATS, + SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST); + return 0; + } + } + + return 1; +} +#endif + +static int init_session_ticket(SSL *s, unsigned int context) +{ + if (!s->server) + s->ext.ticket_expected = 0; + + return 1; +} + +#ifndef OPENSSL_NO_OCSP +static int init_status_request(SSL *s, unsigned int context) +{ + if (s->server) { + s->ext.status_type = TLSEXT_STATUSTYPE_nothing; + } else { + /* + * Ensure we get sensible values passed to tlsext_status_cb in the event + * that we don't receive a status message + */ + OPENSSL_free(s->ext.ocsp.resp); + s->ext.ocsp.resp = NULL; + s->ext.ocsp.resp_len = 0; + } + + return 1; +} +#endif + +#ifndef OPENSSL_NO_NEXTPROTONEG +static int init_npn(SSL *s, unsigned int context) +{ + s->s3->npn_seen = 0; + + return 1; +} +#endif + +static int init_alpn(SSL *s, unsigned int context) +{ + OPENSSL_free(s->s3->alpn_selected); + s->s3->alpn_selected = NULL; + s->s3->alpn_selected_len = 0; + if (s->server) { + OPENSSL_free(s->s3->alpn_proposed); + s->s3->alpn_proposed = NULL; + s->s3->alpn_proposed_len = 0; + } + return 1; +} + +static int final_alpn(SSL *s, unsigned int context, int sent) +{ + if (!s->server && !sent && s->session->ext.alpn_selected != NULL) + s->ext.early_data_ok = 0; + + if (!s->server || !SSL_IS_TLS13(s)) + return 1; + + /* + * Call alpn_select callback if needed. Has to be done after SNI and + * cipher negotiation (HTTP/2 restricts permitted ciphers). In TLSv1.3 + * we also have to do this before we decide whether to accept early_data. + * In TLSv1.3 we've already negotiated our cipher so we do this call now. + * For < TLSv1.3 we defer it until after cipher negotiation. + * + * On failure SSLfatal() already called. + */ + return tls_handle_alpn(s); +} + +static int init_sig_algs(SSL *s, unsigned int context) +{ + /* Clear any signature algorithms extension received */ + OPENSSL_free(s->s3->tmp.peer_sigalgs); + s->s3->tmp.peer_sigalgs = NULL; + + return 1; +} + +static int init_sig_algs_cert(SSL *s, unsigned int context) +{ + /* Clear any signature algorithms extension received */ + OPENSSL_free(s->s3->tmp.peer_cert_sigalgs); + s->s3->tmp.peer_cert_sigalgs = NULL; + + return 1; +} + +#ifndef OPENSSL_NO_SRP +static int init_srp(SSL *s, unsigned int context) +{ + OPENSSL_free(s->srp_ctx.login); + s->srp_ctx.login = NULL; + + return 1; +} +#endif + +static int init_etm(SSL *s, unsigned int context) +{ + s->ext.use_etm = 0; + + return 1; +} + +static int init_ems(SSL *s, unsigned int context) +{ + if (!s->server) + s->s3->flags &= ~TLS1_FLAGS_RECEIVED_EXTMS; + + return 1; +} + +static int final_ems(SSL *s, unsigned int context, int sent) +{ + if (!s->server && s->hit) { + /* + * Check extended master secret extension is consistent with + * original session. + */ + if (!(s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) != + !(s->session->flags & SSL_SESS_FLAG_EXTMS)) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_FINAL_EMS, + SSL_R_INCONSISTENT_EXTMS); + return 0; + } + } + + return 1; +} + +static int init_certificate_authorities(SSL *s, unsigned int context) +{ + sk_X509_NAME_pop_free(s->s3->tmp.peer_ca_names, X509_NAME_free); + s->s3->tmp.peer_ca_names = NULL; + return 1; +} + +static EXT_RETURN tls_construct_certificate_authorities(SSL *s, WPACKET *pkt, + unsigned int context, + X509 *x, + size_t chainidx) +{ + const STACK_OF(X509_NAME) *ca_sk = get_ca_names(s); + + if (ca_sk == NULL || sk_X509_NAME_num(ca_sk) == 0) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_certificate_authorities) + || !WPACKET_start_sub_packet_u16(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CERTIFICATE_AUTHORITIES, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + if (!construct_ca_names(s, ca_sk, pkt)) { + /* SSLfatal() already called */ + return EXT_RETURN_FAIL; + } + + if (!WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CERTIFICATE_AUTHORITIES, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +static int tls_parse_certificate_authorities(SSL *s, PACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + if (!parse_ca_names(s, pkt)) + return 0; + if (PACKET_remaining(pkt) != 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CERTIFICATE_AUTHORITIES, SSL_R_BAD_EXTENSION); + return 0; + } + return 1; +} + +#ifndef OPENSSL_NO_SRTP +static int init_srtp(SSL *s, unsigned int context) +{ + if (s->server) + s->srtp_profile = NULL; + + return 1; +} +#endif + +static int final_sig_algs(SSL *s, unsigned int context, int sent) +{ + if (!sent && SSL_IS_TLS13(s) && !s->hit) { + SSLfatal(s, TLS13_AD_MISSING_EXTENSION, SSL_F_FINAL_SIG_ALGS, + SSL_R_MISSING_SIGALGS_EXTENSION); + return 0; + } + + return 1; +} + +#ifndef OPENSSL_NO_EC +static int final_key_share(SSL *s, unsigned int context, int sent) +{ + if (!SSL_IS_TLS13(s)) + return 1; + + /* Nothing to do for key_share in an HRR */ + if ((context & SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST) != 0) + return 1; + + /* + * If + * we are a client + * AND + * we have no key_share + * AND + * (we are not resuming + * OR the kex_mode doesn't allow non key_share resumes) + * THEN + * fail; + */ + if (!s->server + && !sent + && (!s->hit + || (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE) == 0)) { + /* Nothing left we can do - just fail */ + SSLfatal(s, SSL_AD_MISSING_EXTENSION, SSL_F_FINAL_KEY_SHARE, + SSL_R_NO_SUITABLE_KEY_SHARE); + return 0; + } + /* + * IF + * we are a server + * THEN + * IF + * we have a suitable key_share + * THEN + * IF + * we are stateless AND we have no cookie + * THEN + * send a HelloRetryRequest + * ELSE + * IF + * we didn't already send a HelloRetryRequest + * AND + * the client sent a key_share extension + * AND + * (we are not resuming + * OR the kex_mode allows key_share resumes) + * AND + * a shared group exists + * THEN + * send a HelloRetryRequest + * ELSE IF + * we are not resuming + * OR + * the kex_mode doesn't allow non key_share resumes + * THEN + * fail + * ELSE IF + * we are stateless AND we have no cookie + * THEN + * send a HelloRetryRequest + */ + if (s->server) { + if (s->s3->peer_tmp != NULL) { + /* We have a suitable key_share */ + if ((s->s3->flags & TLS1_FLAGS_STATELESS) != 0 + && !s->ext.cookieok) { + if (!ossl_assert(s->hello_retry_request == SSL_HRR_NONE)) { + /* + * If we are stateless then we wouldn't know about any + * previously sent HRR - so how can this be anything other + * than 0? + */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_KEY_SHARE, + ERR_R_INTERNAL_ERROR); + return 0; + } + s->hello_retry_request = SSL_HRR_PENDING; + return 1; + } + } else { + /* No suitable key_share */ + if (s->hello_retry_request == SSL_HRR_NONE && sent + && (!s->hit + || (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE_DHE) + != 0)) { + const uint16_t *pgroups, *clntgroups; + size_t num_groups, clnt_num_groups, i; + unsigned int group_id = 0; + + /* Check if a shared group exists */ + + /* Get the clients list of supported groups. */ + tls1_get_peer_groups(s, &clntgroups, &clnt_num_groups); + tls1_get_supported_groups(s, &pgroups, &num_groups); + + /* + * Find the first group we allow that is also in client's list + */ + for (i = 0; i < num_groups; i++) { + group_id = pgroups[i]; + + if (check_in_list(s, group_id, clntgroups, clnt_num_groups, + 1)) + break; + } + + if (i < num_groups) { + /* A shared group exists so send a HelloRetryRequest */ + s->s3->group_id = group_id; + s->hello_retry_request = SSL_HRR_PENDING; + return 1; + } + } + if (!s->hit + || (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE) == 0) { + /* Nothing left we can do - just fail */ + SSLfatal(s, sent ? SSL_AD_HANDSHAKE_FAILURE + : SSL_AD_MISSING_EXTENSION, + SSL_F_FINAL_KEY_SHARE, SSL_R_NO_SUITABLE_KEY_SHARE); + return 0; + } + + if ((s->s3->flags & TLS1_FLAGS_STATELESS) != 0 + && !s->ext.cookieok) { + if (!ossl_assert(s->hello_retry_request == SSL_HRR_NONE)) { + /* + * If we are stateless then we wouldn't know about any + * previously sent HRR - so how can this be anything other + * than 0? + */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_KEY_SHARE, + ERR_R_INTERNAL_ERROR); + return 0; + } + s->hello_retry_request = SSL_HRR_PENDING; + return 1; + } + } + + /* + * We have a key_share so don't send any more HelloRetryRequest + * messages + */ + if (s->hello_retry_request == SSL_HRR_PENDING) + s->hello_retry_request = SSL_HRR_COMPLETE; + } else { + /* + * For a client side resumption with no key_share we need to generate + * the handshake secret (otherwise this is done during key_share + * processing). + */ + if (!sent && !tls13_generate_handshake_secret(s, NULL, 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_KEY_SHARE, + ERR_R_INTERNAL_ERROR); + return 0; + } + } + + return 1; +} +#endif + +static int init_psk_kex_modes(SSL *s, unsigned int context) +{ + s->ext.psk_kex_mode = TLSEXT_KEX_MODE_FLAG_NONE; + return 1; +} + +int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart, + size_t binderoffset, const unsigned char *binderin, + unsigned char *binderout, SSL_SESSION *sess, int sign, + int external) +{ + EVP_PKEY *mackey = NULL; + EVP_MD_CTX *mctx = NULL; + unsigned char hash[EVP_MAX_MD_SIZE], binderkey[EVP_MAX_MD_SIZE]; + unsigned char finishedkey[EVP_MAX_MD_SIZE], tmpbinder[EVP_MAX_MD_SIZE]; + unsigned char *early_secret; + static const unsigned char resumption_label[] = "res binder"; + static const unsigned char external_label[] = "ext binder"; + const unsigned char *label; + size_t bindersize, labelsize, hashsize; + int hashsizei = EVP_MD_size(md); + int ret = -1; + int usepskfored = 0; + + /* Ensure cast to size_t is safe */ + if (!ossl_assert(hashsizei >= 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER, + ERR_R_INTERNAL_ERROR); + goto err; + } + hashsize = (size_t)hashsizei; + + if (external + && s->early_data_state == SSL_EARLY_DATA_CONNECTING + && s->session->ext.max_early_data == 0 + && sess->ext.max_early_data > 0) + usepskfored = 1; + + if (external) { + label = external_label; + labelsize = sizeof(external_label) - 1; + } else { + label = resumption_label; + labelsize = sizeof(resumption_label) - 1; + } + + /* + * Generate the early_secret. On the server side we've selected a PSK to + * resume with (internal or external) so we always do this. On the client + * side we do this for a non-external (i.e. resumption) PSK or external PSK + * that will be used for early_data so that it is in place for sending early + * data. For client side external PSK not being used for early_data we + * generate it but store it away for later use. + */ + if (s->server || !external || usepskfored) + early_secret = (unsigned char *)s->early_secret; + else + early_secret = (unsigned char *)sess->early_secret; + + if (!tls13_generate_secret(s, md, NULL, sess->master_key, + sess->master_key_length, early_secret)) { + /* SSLfatal() already called */ + goto err; + } + + /* + * Create the handshake hash for the binder key...the messages so far are + * empty! + */ + mctx = EVP_MD_CTX_new(); + if (mctx == NULL + || EVP_DigestInit_ex(mctx, md, NULL) <= 0 + || EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* Generate the binder key */ + if (!tls13_hkdf_expand(s, md, early_secret, label, labelsize, hash, + hashsize, binderkey, hashsize, 1)) { + /* SSLfatal() already called */ + goto err; + } + + /* Generate the finished key */ + if (!tls13_derive_finishedkey(s, md, binderkey, finishedkey, hashsize)) { + /* SSLfatal() already called */ + goto err; + } + + if (EVP_DigestInit_ex(mctx, md, NULL) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* + * Get a hash of the ClientHello up to the start of the binders. If we are + * following a HelloRetryRequest then this includes the hash of the first + * ClientHello and the HelloRetryRequest itself. + */ + if (s->hello_retry_request == SSL_HRR_PENDING) { + size_t hdatalen; + long hdatalen_l; + void *hdata; + + hdatalen = hdatalen_l = + BIO_get_mem_data(s->s3->handshake_buffer, &hdata); + if (hdatalen_l <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER, + SSL_R_BAD_HANDSHAKE_LENGTH); + goto err; + } + + /* + * For servers the handshake buffer data will include the second + * ClientHello - which we don't want - so we need to take that bit off. + */ + if (s->server) { + PACKET hashprefix, msg; + + /* Find how many bytes are left after the first two messages */ + if (!PACKET_buf_init(&hashprefix, hdata, hdatalen) + || !PACKET_forward(&hashprefix, 1) + || !PACKET_get_length_prefixed_3(&hashprefix, &msg) + || !PACKET_forward(&hashprefix, 1) + || !PACKET_get_length_prefixed_3(&hashprefix, &msg)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER, + ERR_R_INTERNAL_ERROR); + goto err; + } + hdatalen -= PACKET_remaining(&hashprefix); + } + + if (EVP_DigestUpdate(mctx, hdata, hdatalen) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER, + ERR_R_INTERNAL_ERROR); + goto err; + } + } + + if (EVP_DigestUpdate(mctx, msgstart, binderoffset) <= 0 + || EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER, + ERR_R_INTERNAL_ERROR); + goto err; + } + + mackey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, finishedkey, + hashsize); + if (mackey == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER, + ERR_R_INTERNAL_ERROR); + goto err; + } + + if (!sign) + binderout = tmpbinder; + + bindersize = hashsize; + if (EVP_DigestSignInit(mctx, NULL, md, NULL, mackey) <= 0 + || EVP_DigestSignUpdate(mctx, hash, hashsize) <= 0 + || EVP_DigestSignFinal(mctx, binderout, &bindersize) <= 0 + || bindersize != hashsize) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER, + ERR_R_INTERNAL_ERROR); + goto err; + } + + if (sign) { + ret = 1; + } else { + /* HMAC keys can't do EVP_DigestVerify* - use CRYPTO_memcmp instead */ + ret = (CRYPTO_memcmp(binderin, binderout, hashsize) == 0); + if (!ret) + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PSK_DO_BINDER, + SSL_R_BINDER_DOES_NOT_VERIFY); + } + + err: + OPENSSL_cleanse(binderkey, sizeof(binderkey)); + OPENSSL_cleanse(finishedkey, sizeof(finishedkey)); + EVP_PKEY_free(mackey); + EVP_MD_CTX_free(mctx); + + return ret; +} + +static int final_early_data(SSL *s, unsigned int context, int sent) +{ + if (!sent) + return 1; + + if (!s->server) { + if (context == SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS + && sent + && !s->ext.early_data_ok) { + /* + * If we get here then the server accepted our early_data but we + * later realised that it shouldn't have done (e.g. inconsistent + * ALPN) + */ + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_FINAL_EARLY_DATA, + SSL_R_BAD_EARLY_DATA); + return 0; + } + + return 1; + } + + if (s->max_early_data == 0 + || !s->hit + || s->session->ext.tick_identity != 0 + || s->early_data_state != SSL_EARLY_DATA_ACCEPTING + || !s->ext.early_data_ok + || s->hello_retry_request != SSL_HRR_NONE + || (s->ctx->allow_early_data_cb != NULL + && !s->ctx->allow_early_data_cb(s, + s->ctx->allow_early_data_cb_data))) { + s->ext.early_data = SSL_EARLY_DATA_REJECTED; + } else { + s->ext.early_data = SSL_EARLY_DATA_ACCEPTED; + + if (!tls13_change_cipher_state(s, + SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_SERVER_READ)) { + /* SSLfatal() already called */ + return 0; + } + } + + return 1; +} + +static int final_maxfragmentlen(SSL *s, unsigned int context, int sent) +{ + /* + * Session resumption on server-side with MFL extension active + * BUT MFL extension packet was not resent (i.e. sent == 0) + */ + if (s->server && s->hit && USE_MAX_FRAGMENT_LENGTH_EXT(s->session) + && !sent ) { + SSLfatal(s, SSL_AD_MISSING_EXTENSION, SSL_F_FINAL_MAXFRAGMENTLEN, + SSL_R_BAD_EXTENSION); + return 0; + } + + /* Current SSL buffer is lower than requested MFL */ + if (s->session && USE_MAX_FRAGMENT_LENGTH_EXT(s->session) + && s->max_send_fragment < GET_MAX_FRAGMENT_LENGTH(s->session)) + /* trigger a larger buffer reallocation */ + if (!ssl3_setup_buffers(s)) { + /* SSLfatal() already called */ + return 0; + } + + return 1; +} + +static int init_post_handshake_auth(SSL *s, unsigned int context) +{ + s->post_handshake_auth = SSL_PHA_NONE; + + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/statem/extensions_clnt.c b/trunk/3rdparty/openssl-1.1-fit/ssl/statem/extensions_clnt.c new file mode 100644 index 000000000..ab4dbf671 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/statem/extensions_clnt.c @@ -0,0 +1,1991 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "../ssl_locl.h" +#include "internal/cryptlib.h" +#include "statem_locl.h" + +EXT_RETURN tls_construct_ctos_renegotiate(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + /* Add RI if renegotiating */ + if (!s->renegotiate) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_renegotiate) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_sub_memcpy_u8(pkt, s->s3->previous_client_finished, + s->s3->previous_client_finished_len) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +EXT_RETURN tls_construct_ctos_server_name(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + if (s->ext.hostname == NULL) + return EXT_RETURN_NOT_SENT; + + /* Add TLS extension servername to the Client Hello message */ + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_server_name) + /* Sub-packet for server_name extension */ + || !WPACKET_start_sub_packet_u16(pkt) + /* Sub-packet for servername list (always 1 hostname)*/ + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_put_bytes_u8(pkt, TLSEXT_NAMETYPE_host_name) + || !WPACKET_sub_memcpy_u16(pkt, s->ext.hostname, + strlen(s->ext.hostname)) + || !WPACKET_close(pkt) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SERVER_NAME, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +/* Push a Max Fragment Len extension into ClientHello */ +EXT_RETURN tls_construct_ctos_maxfragmentlen(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + if (s->ext.max_fragment_len_mode == TLSEXT_max_fragment_length_DISABLED) + return EXT_RETURN_NOT_SENT; + + /* Add Max Fragment Length extension if client enabled it. */ + /*- + * 4 bytes for this extension type and extension length + * 1 byte for the Max Fragment Length code value. + */ + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_max_fragment_length) + /* Sub-packet for Max Fragment Length extension (1 byte) */ + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_put_bytes_u8(pkt, s->ext.max_fragment_len_mode) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_MAXFRAGMENTLEN, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +#ifndef OPENSSL_NO_SRP +EXT_RETURN tls_construct_ctos_srp(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + /* Add SRP username if there is one */ + if (s->srp_ctx.login == NULL) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_srp) + /* Sub-packet for SRP extension */ + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_start_sub_packet_u8(pkt) + /* login must not be zero...internal error if so */ + || !WPACKET_set_flags(pkt, WPACKET_FLAGS_NON_ZERO_LENGTH) + || !WPACKET_memcpy(pkt, s->srp_ctx.login, + strlen(s->srp_ctx.login)) + || !WPACKET_close(pkt) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SRP, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} +#endif + +#ifndef OPENSSL_NO_EC +static int use_ecc(SSL *s) +{ + int i, end, ret = 0; + unsigned long alg_k, alg_a; + STACK_OF(SSL_CIPHER) *cipher_stack = NULL; + + /* See if we support any ECC ciphersuites */ + if (s->version == SSL3_VERSION) + return 0; + + cipher_stack = SSL_get1_supported_ciphers(s); + end = sk_SSL_CIPHER_num(cipher_stack); + for (i = 0; i < end; i++) { + const SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i); + + alg_k = c->algorithm_mkey; + alg_a = c->algorithm_auth; + if ((alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) + || (alg_a & SSL_aECDSA) + || c->min_tls >= TLS1_3_VERSION) { + ret = 1; + break; + } + } + + sk_SSL_CIPHER_free(cipher_stack); + return ret; +} + +EXT_RETURN tls_construct_ctos_ec_pt_formats(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + const unsigned char *pformats; + size_t num_formats; + + if (!use_ecc(s)) + return EXT_RETURN_NOT_SENT; + + /* Add TLS extension ECPointFormats to the ClientHello message */ + tls1_get_formatlist(s, &pformats, &num_formats); + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_ec_point_formats) + /* Sub-packet for formats extension */ + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_sub_memcpy_u8(pkt, pformats, num_formats) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +EXT_RETURN tls_construct_ctos_supported_groups(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + const uint16_t *pgroups = NULL; + size_t num_groups = 0, i; + + if (!use_ecc(s)) + return EXT_RETURN_NOT_SENT; + + /* + * Add TLS extension supported_groups to the ClientHello message + */ + /* TODO(TLS1.3): Add support for DHE groups */ + tls1_get_supported_groups(s, &pgroups, &num_groups); + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_groups) + /* Sub-packet for supported_groups extension */ + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_start_sub_packet_u16(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + /* Copy curve ID if supported */ + for (i = 0; i < num_groups; i++) { + uint16_t ctmp = pgroups[i]; + + if (tls_curve_allowed(s, ctmp, SSL_SECOP_CURVE_SUPPORTED)) { + if (!WPACKET_put_bytes_u16(pkt, ctmp)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + } + } + if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} +#endif + +EXT_RETURN tls_construct_ctos_session_ticket(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + size_t ticklen; + + if (!tls_use_ticket(s)) + return EXT_RETURN_NOT_SENT; + + if (!s->new_session && s->session != NULL + && s->session->ext.tick != NULL + && s->session->ssl_version != TLS1_3_VERSION) { + ticklen = s->session->ext.ticklen; + } else if (s->session && s->ext.session_ticket != NULL + && s->ext.session_ticket->data != NULL) { + ticklen = s->ext.session_ticket->length; + s->session->ext.tick = OPENSSL_malloc(ticklen); + if (s->session->ext.tick == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_SESSION_TICKET, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + memcpy(s->session->ext.tick, + s->ext.session_ticket->data, ticklen); + s->session->ext.ticklen = ticklen; + } else { + ticklen = 0; + } + + if (ticklen == 0 && s->ext.session_ticket != NULL && + s->ext.session_ticket->data == NULL) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_session_ticket) + || !WPACKET_sub_memcpy_u16(pkt, s->session->ext.tick, ticklen)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_SESSION_TICKET, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +EXT_RETURN tls_construct_ctos_sig_algs(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + size_t salglen; + const uint16_t *salg; + + if (!SSL_CLIENT_USE_SIGALGS(s)) + return EXT_RETURN_NOT_SENT; + + salglen = tls12_get_psigalgs(s, 1, &salg); + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_signature_algorithms) + /* Sub-packet for sig-algs extension */ + || !WPACKET_start_sub_packet_u16(pkt) + /* Sub-packet for the actual list */ + || !WPACKET_start_sub_packet_u16(pkt) + || !tls12_copy_sigalgs(s, pkt, salg, salglen) + || !WPACKET_close(pkt) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SIG_ALGS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +#ifndef OPENSSL_NO_OCSP +EXT_RETURN tls_construct_ctos_status_request(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + int i; + + /* This extension isn't defined for client Certificates */ + if (x != NULL) + return EXT_RETURN_NOT_SENT; + + if (s->ext.status_type != TLSEXT_STATUSTYPE_ocsp) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_status_request) + /* Sub-packet for status request extension */ + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_put_bytes_u8(pkt, TLSEXT_STATUSTYPE_ocsp) + /* Sub-packet for the ids */ + || !WPACKET_start_sub_packet_u16(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + for (i = 0; i < sk_OCSP_RESPID_num(s->ext.ocsp.ids); i++) { + unsigned char *idbytes; + OCSP_RESPID *id = sk_OCSP_RESPID_value(s->ext.ocsp.ids, i); + int idlen = i2d_OCSP_RESPID(id, NULL); + + if (idlen <= 0 + /* Sub-packet for an individual id */ + || !WPACKET_sub_allocate_bytes_u16(pkt, idlen, &idbytes) + || i2d_OCSP_RESPID(id, &idbytes) != idlen) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + } + if (!WPACKET_close(pkt) + || !WPACKET_start_sub_packet_u16(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + if (s->ext.ocsp.exts) { + unsigned char *extbytes; + int extlen = i2d_X509_EXTENSIONS(s->ext.ocsp.exts, NULL); + + if (extlen < 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + if (!WPACKET_allocate_bytes(pkt, extlen, &extbytes) + || i2d_X509_EXTENSIONS(s->ext.ocsp.exts, &extbytes) + != extlen) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + } + if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} +#endif + +#ifndef OPENSSL_NO_NEXTPROTONEG +EXT_RETURN tls_construct_ctos_npn(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (s->ctx->ext.npn_select_cb == NULL || !SSL_IS_FIRST_HANDSHAKE(s)) + return EXT_RETURN_NOT_SENT; + + /* + * The client advertises an empty extension to indicate its support + * for Next Protocol Negotiation + */ + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_next_proto_neg) + || !WPACKET_put_bytes_u16(pkt, 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_NPN, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} +#endif + +EXT_RETURN tls_construct_ctos_alpn(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + s->s3->alpn_sent = 0; + + if (s->ext.alpn == NULL || !SSL_IS_FIRST_HANDSHAKE(s)) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, + TLSEXT_TYPE_application_layer_protocol_negotiation) + /* Sub-packet ALPN extension */ + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_sub_memcpy_u16(pkt, s->ext.alpn, s->ext.alpn_len) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_ALPN, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + s->s3->alpn_sent = 1; + + return EXT_RETURN_SENT; +} + + +#ifndef OPENSSL_NO_SRTP +EXT_RETURN tls_construct_ctos_use_srtp(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + STACK_OF(SRTP_PROTECTION_PROFILE) *clnt = SSL_get_srtp_profiles(s); + int i, end; + + if (clnt == NULL) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_use_srtp) + /* Sub-packet for SRTP extension */ + || !WPACKET_start_sub_packet_u16(pkt) + /* Sub-packet for the protection profile list */ + || !WPACKET_start_sub_packet_u16(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + end = sk_SRTP_PROTECTION_PROFILE_num(clnt); + for (i = 0; i < end; i++) { + const SRTP_PROTECTION_PROFILE *prof = + sk_SRTP_PROTECTION_PROFILE_value(clnt, i); + + if (prof == NULL || !WPACKET_put_bytes_u16(pkt, prof->id)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + } + if (!WPACKET_close(pkt) + /* Add an empty use_mki value */ + || !WPACKET_put_bytes_u8(pkt, 0) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} +#endif + +EXT_RETURN tls_construct_ctos_etm(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (s->options & SSL_OP_NO_ENCRYPT_THEN_MAC) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_encrypt_then_mac) + || !WPACKET_put_bytes_u16(pkt, 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_ETM, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +#ifndef OPENSSL_NO_CT +EXT_RETURN tls_construct_ctos_sct(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (s->ct_validation_callback == NULL) + return EXT_RETURN_NOT_SENT; + + /* Not defined for client Certificates */ + if (x != NULL) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_signed_certificate_timestamp) + || !WPACKET_put_bytes_u16(pkt, 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SCT, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} +#endif + +EXT_RETURN tls_construct_ctos_ems(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret) + || !WPACKET_put_bytes_u16(pkt, 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EMS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +EXT_RETURN tls_construct_ctos_supported_versions(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + int currv, min_version, max_version, reason; + + reason = ssl_get_min_max_version(s, &min_version, &max_version, NULL); + if (reason != 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, reason); + return EXT_RETURN_FAIL; + } + + /* + * Don't include this if we can't negotiate TLSv1.3. We can do a straight + * comparison here because we will never be called in DTLS. + */ + if (max_version < TLS1_3_VERSION) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_versions) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_start_sub_packet_u8(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + for (currv = max_version; currv >= min_version; currv--) { + if (!WPACKET_put_bytes_u16(pkt, currv)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + } + if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +/* + * Construct a psk_kex_modes extension. + */ +EXT_RETURN tls_construct_ctos_psk_kex_modes(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ +#ifndef OPENSSL_NO_TLS1_3 + int nodhe = s->options & SSL_OP_ALLOW_NO_DHE_KEX; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk_kex_modes) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_start_sub_packet_u8(pkt) + || !WPACKET_put_bytes_u8(pkt, TLSEXT_KEX_MODE_KE_DHE) + || (nodhe && !WPACKET_put_bytes_u8(pkt, TLSEXT_KEX_MODE_KE)) + || !WPACKET_close(pkt) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + s->ext.psk_kex_mode = TLSEXT_KEX_MODE_FLAG_KE_DHE; + if (nodhe) + s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE; +#endif + + return EXT_RETURN_SENT; +} + +#ifndef OPENSSL_NO_TLS1_3 +static int add_key_share(SSL *s, WPACKET *pkt, unsigned int curve_id) +{ + unsigned char *encoded_point = NULL; + EVP_PKEY *key_share_key = NULL; + size_t encodedlen; + + if (s->s3->tmp.pkey != NULL) { + if (!ossl_assert(s->hello_retry_request == SSL_HRR_PENDING)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_ADD_KEY_SHARE, + ERR_R_INTERNAL_ERROR); + return 0; + } + /* + * Could happen if we got an HRR that wasn't requesting a new key_share + */ + key_share_key = s->s3->tmp.pkey; + } else { + key_share_key = ssl_generate_pkey_group(s, curve_id); + if (key_share_key == NULL) { + /* SSLfatal() already called */ + return 0; + } + } + + /* Encode the public key. */ + encodedlen = EVP_PKEY_get1_tls_encodedpoint(key_share_key, + &encoded_point); + if (encodedlen == 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_ADD_KEY_SHARE, ERR_R_EC_LIB); + goto err; + } + + /* Create KeyShareEntry */ + if (!WPACKET_put_bytes_u16(pkt, curve_id) + || !WPACKET_sub_memcpy_u16(pkt, encoded_point, encodedlen)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_ADD_KEY_SHARE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* + * TODO(TLS1.3): When changing to send more than one key_share we're + * going to need to be able to save more than one EVP_PKEY. For now + * we reuse the existing tmp.pkey + */ + s->s3->tmp.pkey = key_share_key; + s->s3->group_id = curve_id; + OPENSSL_free(encoded_point); + + return 1; + err: + if (s->s3->tmp.pkey == NULL) + EVP_PKEY_free(key_share_key); + OPENSSL_free(encoded_point); + return 0; +} +#endif + +EXT_RETURN tls_construct_ctos_key_share(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ +#ifndef OPENSSL_NO_TLS1_3 + size_t i, num_groups = 0; + const uint16_t *pgroups = NULL; + uint16_t curve_id = 0; + + /* key_share extension */ + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share) + /* Extension data sub-packet */ + || !WPACKET_start_sub_packet_u16(pkt) + /* KeyShare list sub-packet */ + || !WPACKET_start_sub_packet_u16(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + tls1_get_supported_groups(s, &pgroups, &num_groups); + + /* + * TODO(TLS1.3): Make the number of key_shares sent configurable. For + * now, just send one + */ + if (s->s3->group_id != 0) { + curve_id = s->s3->group_id; + } else { + for (i = 0; i < num_groups; i++) { + + if (!tls_curve_allowed(s, pgroups[i], SSL_SECOP_CURVE_SUPPORTED)) + continue; + + curve_id = pgroups[i]; + break; + } + } + + if (curve_id == 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE, + SSL_R_NO_SUITABLE_KEY_SHARE); + return EXT_RETURN_FAIL; + } + + if (!add_key_share(s, pkt, curve_id)) { + /* SSLfatal() already called */ + return EXT_RETURN_FAIL; + } + + if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + return EXT_RETURN_SENT; +#else + return EXT_RETURN_NOT_SENT; +#endif +} + +EXT_RETURN tls_construct_ctos_cookie(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + EXT_RETURN ret = EXT_RETURN_FAIL; + + /* Should only be set if we've had an HRR */ + if (s->ext.tls13_cookie_len == 0) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_cookie) + /* Extension data sub-packet */ + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_sub_memcpy_u16(pkt, s->ext.tls13_cookie, + s->ext.tls13_cookie_len) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_COOKIE, + ERR_R_INTERNAL_ERROR); + goto end; + } + + ret = EXT_RETURN_SENT; + end: + OPENSSL_free(s->ext.tls13_cookie); + s->ext.tls13_cookie = NULL; + s->ext.tls13_cookie_len = 0; + + return ret; +} + +EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ +#ifndef OPENSSL_NO_PSK + char identity[PSK_MAX_IDENTITY_LEN + 1]; +#endif /* OPENSSL_NO_PSK */ + const unsigned char *id = NULL; + size_t idlen = 0; + SSL_SESSION *psksess = NULL; + SSL_SESSION *edsess = NULL; + const EVP_MD *handmd = NULL; + + if (s->hello_retry_request == SSL_HRR_PENDING) + handmd = ssl_handshake_md(s); + + if (s->psk_use_session_cb != NULL + && (!s->psk_use_session_cb(s, handmd, &id, &idlen, &psksess) + || (psksess != NULL + && psksess->ssl_version != TLS1_3_VERSION))) { + SSL_SESSION_free(psksess); + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, + SSL_R_BAD_PSK); + return EXT_RETURN_FAIL; + } + +#ifndef OPENSSL_NO_PSK + if (psksess == NULL && s->psk_client_callback != NULL) { + unsigned char psk[PSK_MAX_PSK_LEN]; + size_t psklen = 0; + + memset(identity, 0, sizeof(identity)); + psklen = s->psk_client_callback(s, NULL, identity, sizeof(identity) - 1, + psk, sizeof(psk)); + + if (psklen > PSK_MAX_PSK_LEN) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } else if (psklen > 0) { + const unsigned char tls13_aes128gcmsha256_id[] = { 0x13, 0x01 }; + const SSL_CIPHER *cipher; + + idlen = strlen(identity); + if (idlen > PSK_MAX_IDENTITY_LEN) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + id = (unsigned char *)identity; + + /* + * We found a PSK using an old style callback. We don't know + * the digest so we default to SHA256 as per the TLSv1.3 spec + */ + cipher = SSL_CIPHER_find(s, tls13_aes128gcmsha256_id); + if (cipher == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + psksess = SSL_SESSION_new(); + if (psksess == NULL + || !SSL_SESSION_set1_master_key(psksess, psk, psklen) + || !SSL_SESSION_set_cipher(psksess, cipher) + || !SSL_SESSION_set_protocol_version(psksess, TLS1_3_VERSION)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, + ERR_R_INTERNAL_ERROR); + OPENSSL_cleanse(psk, psklen); + return EXT_RETURN_FAIL; + } + OPENSSL_cleanse(psk, psklen); + } + } +#endif /* OPENSSL_NO_PSK */ + + SSL_SESSION_free(s->psksession); + s->psksession = psksess; + if (psksess != NULL) { + OPENSSL_free(s->psksession_id); + s->psksession_id = OPENSSL_memdup(id, idlen); + if (s->psksession_id == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + s->psksession_id_len = idlen; + } + + if (s->early_data_state != SSL_EARLY_DATA_CONNECTING + || (s->session->ext.max_early_data == 0 + && (psksess == NULL || psksess->ext.max_early_data == 0))) { + s->max_early_data = 0; + return EXT_RETURN_NOT_SENT; + } + edsess = s->session->ext.max_early_data != 0 ? s->session : psksess; + s->max_early_data = edsess->ext.max_early_data; + + if (edsess->ext.hostname != NULL) { + if (s->ext.hostname == NULL + || (s->ext.hostname != NULL + && strcmp(s->ext.hostname, edsess->ext.hostname) != 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, + SSL_R_INCONSISTENT_EARLY_DATA_SNI); + return EXT_RETURN_FAIL; + } + } + + if ((s->ext.alpn == NULL && edsess->ext.alpn_selected != NULL)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, + SSL_R_INCONSISTENT_EARLY_DATA_ALPN); + return EXT_RETURN_FAIL; + } + + /* + * Verify that we are offering an ALPN protocol consistent with the early + * data. + */ + if (edsess->ext.alpn_selected != NULL) { + PACKET prots, alpnpkt; + int found = 0; + + if (!PACKET_buf_init(&prots, s->ext.alpn, s->ext.alpn_len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + while (PACKET_get_length_prefixed_1(&prots, &alpnpkt)) { + if (PACKET_equal(&alpnpkt, edsess->ext.alpn_selected, + edsess->ext.alpn_selected_len)) { + found = 1; + break; + } + } + if (!found) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, + SSL_R_INCONSISTENT_EARLY_DATA_ALPN); + return EXT_RETURN_FAIL; + } + } + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + /* + * We set this to rejected here. Later, if the server acknowledges the + * extension, we set it to accepted. + */ + s->ext.early_data = SSL_EARLY_DATA_REJECTED; + s->ext.early_data_ok = 1; + + return EXT_RETURN_SENT; +} + +#define F5_WORKAROUND_MIN_MSG_LEN 0xff +#define F5_WORKAROUND_MAX_MSG_LEN 0x200 + +/* + * PSK pre binder overhead = + * 2 bytes for TLSEXT_TYPE_psk + * 2 bytes for extension length + * 2 bytes for identities list length + * 2 bytes for identity length + * 4 bytes for obfuscated_ticket_age + * 2 bytes for binder list length + * 1 byte for binder length + * The above excludes the number of bytes for the identity itself and the + * subsequent binder bytes + */ +#define PSK_PRE_BINDER_OVERHEAD (2 + 2 + 2 + 2 + 4 + 2 + 1) + +EXT_RETURN tls_construct_ctos_padding(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + unsigned char *padbytes; + size_t hlen; + + if ((s->options & SSL_OP_TLSEXT_PADDING) == 0) + return EXT_RETURN_NOT_SENT; + + /* + * Add padding to workaround bugs in F5 terminators. See RFC7685. + * This code calculates the length of all extensions added so far but + * excludes the PSK extension (because that MUST be written last). Therefore + * this extension MUST always appear second to last. + */ + if (!WPACKET_get_total_written(pkt, &hlen)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PADDING, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + /* + * If we're going to send a PSK then that will be written out after this + * extension, so we need to calculate how long it is going to be. + */ + if (s->session->ssl_version == TLS1_3_VERSION + && s->session->ext.ticklen != 0 + && s->session->cipher != NULL) { + const EVP_MD *md = ssl_md(s->session->cipher->algorithm2); + + if (md != NULL) { + /* + * Add the fixed PSK overhead, the identity length and the binder + * length. + */ + hlen += PSK_PRE_BINDER_OVERHEAD + s->session->ext.ticklen + + EVP_MD_size(md); + } + } + + if (hlen > F5_WORKAROUND_MIN_MSG_LEN && hlen < F5_WORKAROUND_MAX_MSG_LEN) { + /* Calculate the amount of padding we need to add */ + hlen = F5_WORKAROUND_MAX_MSG_LEN - hlen; + + /* + * Take off the size of extension header itself (2 bytes for type and + * 2 bytes for length bytes), but ensure that the extension is at least + * 1 byte long so as not to have an empty extension last (WebSphere 7.x, + * 8.x are intolerant of that condition) + */ + if (hlen > 4) + hlen -= 4; + else + hlen = 1; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_padding) + || !WPACKET_sub_allocate_bytes_u16(pkt, hlen, &padbytes)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PADDING, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + memset(padbytes, 0, hlen); + } + + return EXT_RETURN_SENT; +} + +/* + * Construct the pre_shared_key extension + */ +EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ +#ifndef OPENSSL_NO_TLS1_3 + uint32_t now, agesec, agems = 0; + size_t reshashsize = 0, pskhashsize = 0, binderoffset, msglen; + unsigned char *resbinder = NULL, *pskbinder = NULL, *msgstart = NULL; + const EVP_MD *handmd = NULL, *mdres = NULL, *mdpsk = NULL; + int dores = 0; + + s->session->ext.tick_identity = TLSEXT_PSK_BAD_IDENTITY; + + /* + * Note: At this stage of the code we only support adding a single + * resumption PSK. If we add support for multiple PSKs then the length + * calculations in the padding extension will need to be adjusted. + */ + + /* + * If this is an incompatible or new session then we have nothing to resume + * so don't add this extension. + */ + if (s->session->ssl_version != TLS1_3_VERSION + || (s->session->ext.ticklen == 0 && s->psksession == NULL)) + return EXT_RETURN_NOT_SENT; + + if (s->hello_retry_request == SSL_HRR_PENDING) + handmd = ssl_handshake_md(s); + + if (s->session->ext.ticklen != 0) { + /* Get the digest associated with the ciphersuite in the session */ + if (s->session->cipher == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + mdres = ssl_md(s->session->cipher->algorithm2); + if (mdres == NULL) { + /* + * Don't recognize this cipher so we can't use the session. + * Ignore it + */ + goto dopsksess; + } + + if (s->hello_retry_request == SSL_HRR_PENDING && mdres != handmd) { + /* + * Selected ciphersuite hash does not match the hash for the session + * so we can't use it. + */ + goto dopsksess; + } + + /* + * Technically the C standard just says time() returns a time_t and says + * nothing about the encoding of that type. In practice most + * implementations follow POSIX which holds it as an integral type in + * seconds since epoch. We've already made the assumption that we can do + * this in multiple places in the code, so portability shouldn't be an + * issue. + */ + now = (uint32_t)time(NULL); + agesec = now - (uint32_t)s->session->time; + /* + * We calculate the age in seconds but the server may work in ms. Due to + * rounding errors we could overestimate the age by up to 1s. It is + * better to underestimate it. Otherwise, if the RTT is very short, when + * the server calculates the age reported by the client it could be + * bigger than the age calculated on the server - which should never + * happen. + */ + if (agesec > 0) + agesec--; + + if (s->session->ext.tick_lifetime_hint < agesec) { + /* Ticket is too old. Ignore it. */ + goto dopsksess; + } + + /* + * Calculate age in ms. We're just doing it to nearest second. Should be + * good enough. + */ + agems = agesec * (uint32_t)1000; + + if (agesec != 0 && agems / (uint32_t)1000 != agesec) { + /* + * Overflow. Shouldn't happen unless this is a *really* old session. + * If so we just ignore it. + */ + goto dopsksess; + } + + /* + * Obfuscate the age. Overflow here is fine, this addition is supposed + * to be mod 2^32. + */ + agems += s->session->ext.tick_age_add; + + reshashsize = EVP_MD_size(mdres); + dores = 1; + } + + dopsksess: + if (!dores && s->psksession == NULL) + return EXT_RETURN_NOT_SENT; + + if (s->psksession != NULL) { + mdpsk = ssl_md(s->psksession->cipher->algorithm2); + if (mdpsk == NULL) { + /* + * Don't recognize this cipher so we can't use the session. + * If this happens it's an application bug. + */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK, + SSL_R_BAD_PSK); + return EXT_RETURN_FAIL; + } + + if (s->hello_retry_request == SSL_HRR_PENDING && mdpsk != handmd) { + /* + * Selected ciphersuite hash does not match the hash for the PSK + * session. This is an application bug. + */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK, + SSL_R_BAD_PSK); + return EXT_RETURN_FAIL; + } + + pskhashsize = EVP_MD_size(mdpsk); + } + + /* Create the extension, but skip over the binder for now */ + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_start_sub_packet_u16(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + if (dores) { + if (!WPACKET_sub_memcpy_u16(pkt, s->session->ext.tick, + s->session->ext.ticklen) + || !WPACKET_put_bytes_u32(pkt, agems)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + } + + if (s->psksession != NULL) { + if (!WPACKET_sub_memcpy_u16(pkt, s->psksession_id, + s->psksession_id_len) + || !WPACKET_put_bytes_u32(pkt, 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + } + + if (!WPACKET_close(pkt) + || !WPACKET_get_total_written(pkt, &binderoffset) + || !WPACKET_start_sub_packet_u16(pkt) + || (dores + && !WPACKET_sub_allocate_bytes_u8(pkt, reshashsize, &resbinder)) + || (s->psksession != NULL + && !WPACKET_sub_allocate_bytes_u8(pkt, pskhashsize, &pskbinder)) + || !WPACKET_close(pkt) + || !WPACKET_close(pkt) + || !WPACKET_get_total_written(pkt, &msglen) + /* + * We need to fill in all the sub-packet lengths now so we can + * calculate the HMAC of the message up to the binders + */ + || !WPACKET_fill_lengths(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + msgstart = WPACKET_get_curr(pkt) - msglen; + + if (dores + && tls_psk_do_binder(s, mdres, msgstart, binderoffset, NULL, + resbinder, s->session, 1, 0) != 1) { + /* SSLfatal() already called */ + return EXT_RETURN_FAIL; + } + + if (s->psksession != NULL + && tls_psk_do_binder(s, mdpsk, msgstart, binderoffset, NULL, + pskbinder, s->psksession, 1, 1) != 1) { + /* SSLfatal() already called */ + return EXT_RETURN_FAIL; + } + + if (dores) + s->session->ext.tick_identity = 0; + if (s->psksession != NULL) + s->psksession->ext.tick_identity = (dores ? 1 : 0); + + return EXT_RETURN_SENT; +#else + return EXT_RETURN_NOT_SENT; +#endif +} + +EXT_RETURN tls_construct_ctos_post_handshake_auth(SSL *s, WPACKET *pkt, + unsigned int context, + X509 *x, size_t chainidx) +{ +#ifndef OPENSSL_NO_TLS1_3 + if (!s->pha_enabled) + return EXT_RETURN_NOT_SENT; + + /* construct extension - 0 length, no contents */ + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_post_handshake_auth) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_POST_HANDSHAKE_AUTH, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + s->post_handshake_auth = SSL_PHA_EXT_SENT; + + return EXT_RETURN_SENT; +#else + return EXT_RETURN_NOT_SENT; +#endif +} + + +/* + * Parse the server's renegotiation binding and abort if it's not right + */ +int tls_parse_stoc_renegotiate(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + size_t expected_len = s->s3->previous_client_finished_len + + s->s3->previous_server_finished_len; + size_t ilen; + const unsigned char *data; + + /* Check for logic errors */ + if (!ossl_assert(expected_len == 0 + || s->s3->previous_client_finished_len != 0) + || !ossl_assert(expected_len == 0 + || s->s3->previous_server_finished_len != 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_RENEGOTIATE, + ERR_R_INTERNAL_ERROR); + return 0; + } + + /* Parse the length byte */ + if (!PACKET_get_1_len(pkt, &ilen)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_RENEGOTIATE, + SSL_R_RENEGOTIATION_ENCODING_ERR); + return 0; + } + + /* Consistency check */ + if (PACKET_remaining(pkt) != ilen) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_RENEGOTIATE, + SSL_R_RENEGOTIATION_ENCODING_ERR); + return 0; + } + + /* Check that the extension matches */ + if (ilen != expected_len) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_RENEGOTIATE, + SSL_R_RENEGOTIATION_MISMATCH); + return 0; + } + + if (!PACKET_get_bytes(pkt, &data, s->s3->previous_client_finished_len) + || memcmp(data, s->s3->previous_client_finished, + s->s3->previous_client_finished_len) != 0) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_RENEGOTIATE, + SSL_R_RENEGOTIATION_MISMATCH); + return 0; + } + + if (!PACKET_get_bytes(pkt, &data, s->s3->previous_server_finished_len) + || memcmp(data, s->s3->previous_server_finished, + s->s3->previous_server_finished_len) != 0) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_RENEGOTIATE, + SSL_R_RENEGOTIATION_MISMATCH); + return 0; + } + s->s3->send_connection_binding = 1; + + return 1; +} + +/* Parse the server's max fragment len extension packet */ +int tls_parse_stoc_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + unsigned int value; + + if (PACKET_remaining(pkt) != 1 || !PACKET_get_1(pkt, &value)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN, + SSL_R_BAD_EXTENSION); + return 0; + } + + /* |value| should contains a valid max-fragment-length code. */ + if (!IS_MAX_FRAGMENT_LENGTH_EXT_VALID(value)) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN, + SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH); + return 0; + } + + /* Must be the same value as client-configured one who was sent to server */ + /*- + * RFC 6066: if a client receives a maximum fragment length negotiation + * response that differs from the length it requested, ... + * It must abort with SSL_AD_ILLEGAL_PARAMETER alert + */ + if (value != s->ext.max_fragment_len_mode) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN, + SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH); + return 0; + } + + /* + * Maximum Fragment Length Negotiation succeeded. + * The negotiated Maximum Fragment Length is binding now. + */ + s->session->ext.max_fragment_len_mode = value; + + return 1; +} + +int tls_parse_stoc_server_name(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (s->ext.hostname == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME, + ERR_R_INTERNAL_ERROR); + return 0; + } + + if (PACKET_remaining(pkt) > 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME, + SSL_R_BAD_EXTENSION); + return 0; + } + + if (!s->hit) { + if (s->session->ext.hostname != NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME, + ERR_R_INTERNAL_ERROR); + return 0; + } + s->session->ext.hostname = OPENSSL_strdup(s->ext.hostname); + if (s->session->ext.hostname == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME, + ERR_R_INTERNAL_ERROR); + return 0; + } + } + + return 1; +} + +#ifndef OPENSSL_NO_EC +int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + size_t ecpointformats_len; + PACKET ecptformatlist; + + if (!PACKET_as_length_prefixed_1(pkt, &ecptformatlist)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS, + SSL_R_BAD_EXTENSION); + return 0; + } + if (!s->hit) { + ecpointformats_len = PACKET_remaining(&ecptformatlist); + if (ecpointformats_len == 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS, SSL_R_BAD_LENGTH); + return 0; + } + + s->session->ext.ecpointformats_len = 0; + OPENSSL_free(s->session->ext.ecpointformats); + s->session->ext.ecpointformats = OPENSSL_malloc(ecpointformats_len); + if (s->session->ext.ecpointformats == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR); + return 0; + } + + s->session->ext.ecpointformats_len = ecpointformats_len; + + if (!PACKET_copy_bytes(&ecptformatlist, + s->session->ext.ecpointformats, + ecpointformats_len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR); + return 0; + } + } + + return 1; +} +#endif + +int tls_parse_stoc_session_ticket(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (s->ext.session_ticket_cb != NULL && + !s->ext.session_ticket_cb(s, PACKET_data(pkt), + PACKET_remaining(pkt), + s->ext.session_ticket_cb_arg)) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_PARSE_STOC_SESSION_TICKET, SSL_R_BAD_EXTENSION); + return 0; + } + + if (!tls_use_ticket(s)) { + SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION, + SSL_F_TLS_PARSE_STOC_SESSION_TICKET, SSL_R_BAD_EXTENSION); + return 0; + } + if (PACKET_remaining(pkt) > 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_STOC_SESSION_TICKET, SSL_R_BAD_EXTENSION); + return 0; + } + + s->ext.ticket_expected = 1; + + return 1; +} + +#ifndef OPENSSL_NO_OCSP +int tls_parse_stoc_status_request(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (context == SSL_EXT_TLS1_3_CERTIFICATE_REQUEST) { + /* We ignore this if the server sends a CertificateRequest */ + /* TODO(TLS1.3): Add support for this */ + return 1; + } + + /* + * MUST only be sent if we've requested a status + * request message. In TLS <= 1.2 it must also be empty. + */ + if (s->ext.status_type != TLSEXT_STATUSTYPE_ocsp) { + SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION, + SSL_F_TLS_PARSE_STOC_STATUS_REQUEST, SSL_R_BAD_EXTENSION); + return 0; + } + if (!SSL_IS_TLS13(s) && PACKET_remaining(pkt) > 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_STOC_STATUS_REQUEST, SSL_R_BAD_EXTENSION); + return 0; + } + + if (SSL_IS_TLS13(s)) { + /* We only know how to handle this if it's for the first Certificate in + * the chain. We ignore any other responses. + */ + if (chainidx != 0) + return 1; + + /* SSLfatal() already called */ + return tls_process_cert_status_body(s, pkt); + } + + /* Set flag to expect CertificateStatus message */ + s->ext.status_expected = 1; + + return 1; +} +#endif + + +#ifndef OPENSSL_NO_CT +int tls_parse_stoc_sct(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ + if (context == SSL_EXT_TLS1_3_CERTIFICATE_REQUEST) { + /* We ignore this if the server sends it in a CertificateRequest */ + /* TODO(TLS1.3): Add support for this */ + return 1; + } + + /* + * Only take it if we asked for it - i.e if there is no CT validation + * callback set, then a custom extension MAY be processing it, so we + * need to let control continue to flow to that. + */ + if (s->ct_validation_callback != NULL) { + size_t size = PACKET_remaining(pkt); + + /* Simply copy it off for later processing */ + OPENSSL_free(s->ext.scts); + s->ext.scts = NULL; + + s->ext.scts_len = (uint16_t)size; + if (size > 0) { + s->ext.scts = OPENSSL_malloc(size); + if (s->ext.scts == NULL + || !PACKET_copy_bytes(pkt, s->ext.scts, size)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SCT, + ERR_R_INTERNAL_ERROR); + return 0; + } + } + } else { + ENDPOINT role = (context & SSL_EXT_TLS1_2_SERVER_HELLO) != 0 + ? ENDPOINT_CLIENT : ENDPOINT_BOTH; + + /* + * If we didn't ask for it then there must be a custom extension, + * otherwise this is unsolicited. + */ + if (custom_ext_find(&s->cert->custext, role, + TLSEXT_TYPE_signed_certificate_timestamp, + NULL) == NULL) { + SSLfatal(s, TLS1_AD_UNSUPPORTED_EXTENSION, SSL_F_TLS_PARSE_STOC_SCT, + SSL_R_BAD_EXTENSION); + return 0; + } + + if (!custom_ext_parse(s, context, + TLSEXT_TYPE_signed_certificate_timestamp, + PACKET_data(pkt), PACKET_remaining(pkt), + x, chainidx)) { + /* SSLfatal already called */ + return 0; + } + } + + return 1; +} +#endif + + +#ifndef OPENSSL_NO_NEXTPROTONEG +/* + * ssl_next_proto_validate validates a Next Protocol Negotiation block. No + * elements of zero length are allowed and the set of elements must exactly + * fill the length of the block. Returns 1 on success or 0 on failure. + */ +static int ssl_next_proto_validate(SSL *s, PACKET *pkt) +{ + PACKET tmp_protocol; + + while (PACKET_remaining(pkt)) { + if (!PACKET_get_length_prefixed_1(pkt, &tmp_protocol) + || PACKET_remaining(&tmp_protocol) == 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL_NEXT_PROTO_VALIDATE, + SSL_R_BAD_EXTENSION); + return 0; + } + } + + return 1; +} + +int tls_parse_stoc_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ + unsigned char *selected; + unsigned char selected_len; + PACKET tmppkt; + + /* Check if we are in a renegotiation. If so ignore this extension */ + if (!SSL_IS_FIRST_HANDSHAKE(s)) + return 1; + + /* We must have requested it. */ + if (s->ctx->ext.npn_select_cb == NULL) { + SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION, SSL_F_TLS_PARSE_STOC_NPN, + SSL_R_BAD_EXTENSION); + return 0; + } + + /* The data must be valid */ + tmppkt = *pkt; + if (!ssl_next_proto_validate(s, &tmppkt)) { + /* SSLfatal() already called */ + return 0; + } + if (s->ctx->ext.npn_select_cb(s, &selected, &selected_len, + PACKET_data(pkt), + PACKET_remaining(pkt), + s->ctx->ext.npn_select_cb_arg) != + SSL_TLSEXT_ERR_OK) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PARSE_STOC_NPN, + SSL_R_BAD_EXTENSION); + return 0; + } + + /* + * Could be non-NULL if server has sent multiple NPN extensions in + * a single Serverhello + */ + OPENSSL_free(s->ext.npn); + s->ext.npn = OPENSSL_malloc(selected_len); + if (s->ext.npn == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_NPN, + ERR_R_INTERNAL_ERROR); + return 0; + } + + memcpy(s->ext.npn, selected, selected_len); + s->ext.npn_len = selected_len; + s->s3->npn_seen = 1; + + return 1; +} +#endif + +int tls_parse_stoc_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ + size_t len; + + /* We must have requested it. */ + if (!s->s3->alpn_sent) { + SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION, SSL_F_TLS_PARSE_STOC_ALPN, + SSL_R_BAD_EXTENSION); + return 0; + } + /*- + * The extension data consists of: + * uint16 list_length + * uint8 proto_length; + * uint8 proto[proto_length]; + */ + if (!PACKET_get_net_2_len(pkt, &len) + || PACKET_remaining(pkt) != len || !PACKET_get_1_len(pkt, &len) + || PACKET_remaining(pkt) != len) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_ALPN, + SSL_R_BAD_EXTENSION); + return 0; + } + OPENSSL_free(s->s3->alpn_selected); + s->s3->alpn_selected = OPENSSL_malloc(len); + if (s->s3->alpn_selected == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_ALPN, + ERR_R_INTERNAL_ERROR); + return 0; + } + if (!PACKET_copy_bytes(pkt, s->s3->alpn_selected, len)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_ALPN, + SSL_R_BAD_EXTENSION); + return 0; + } + s->s3->alpn_selected_len = len; + + if (s->session->ext.alpn_selected == NULL + || s->session->ext.alpn_selected_len != len + || memcmp(s->session->ext.alpn_selected, s->s3->alpn_selected, len) + != 0) { + /* ALPN not consistent with the old session so cannot use early_data */ + s->ext.early_data_ok = 0; + } + if (!s->hit) { + /* + * This is a new session and so alpn_selected should have been + * initialised to NULL. We should update it with the selected ALPN. + */ + if (!ossl_assert(s->session->ext.alpn_selected == NULL)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_ALPN, + ERR_R_INTERNAL_ERROR); + return 0; + } + s->session->ext.alpn_selected = + OPENSSL_memdup(s->s3->alpn_selected, s->s3->alpn_selected_len); + if (s->session->ext.alpn_selected == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_ALPN, + ERR_R_INTERNAL_ERROR); + return 0; + } + s->session->ext.alpn_selected_len = s->s3->alpn_selected_len; + } + + return 1; +} + +#ifndef OPENSSL_NO_SRTP +int tls_parse_stoc_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ + unsigned int id, ct, mki; + int i; + STACK_OF(SRTP_PROTECTION_PROFILE) *clnt; + SRTP_PROTECTION_PROFILE *prof; + + if (!PACKET_get_net_2(pkt, &ct) || ct != 2 + || !PACKET_get_net_2(pkt, &id) + || !PACKET_get_1(pkt, &mki) + || PACKET_remaining(pkt) != 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_USE_SRTP, + SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); + return 0; + } + + if (mki != 0) { + /* Must be no MKI, since we never offer one */ + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_USE_SRTP, + SSL_R_BAD_SRTP_MKI_VALUE); + return 0; + } + + /* Throw an error if the server gave us an unsolicited extension */ + clnt = SSL_get_srtp_profiles(s); + if (clnt == NULL) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_USE_SRTP, + SSL_R_NO_SRTP_PROFILES); + return 0; + } + + /* + * Check to see if the server gave us something we support (and + * presumably offered) + */ + for (i = 0; i < sk_SRTP_PROTECTION_PROFILE_num(clnt); i++) { + prof = sk_SRTP_PROTECTION_PROFILE_value(clnt, i); + + if (prof->id == id) { + s->srtp_profile = prof; + return 1; + } + } + + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_USE_SRTP, + SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); + return 0; +} +#endif + +int tls_parse_stoc_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ + /* Ignore if inappropriate ciphersuite */ + if (!(s->options & SSL_OP_NO_ENCRYPT_THEN_MAC) + && s->s3->tmp.new_cipher->algorithm_mac != SSL_AEAD + && s->s3->tmp.new_cipher->algorithm_enc != SSL_RC4) + s->ext.use_etm = 1; + + return 1; +} + +int tls_parse_stoc_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ + s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS; + if (!s->hit) + s->session->flags |= SSL_SESS_FLAG_EXTMS; + + return 1; +} + +int tls_parse_stoc_supported_versions(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + unsigned int version; + + if (!PACKET_get_net_2(pkt, &version) + || PACKET_remaining(pkt) != 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + /* + * The only protocol version we support which is valid in this extension in + * a ServerHello is TLSv1.3 therefore we shouldn't be getting anything else. + */ + if (version != TLS1_3_VERSION) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS, + SSL_R_BAD_PROTOCOL_VERSION_NUMBER); + return 0; + } + + /* We ignore this extension for HRRs except to sanity check it */ + if (context == SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST) + return 1; + + /* We just set it here. We validate it in ssl_choose_client_version */ + s->version = version; + + return 1; +} + +int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ +#ifndef OPENSSL_NO_TLS1_3 + unsigned int group_id; + PACKET encoded_pt; + EVP_PKEY *ckey = s->s3->tmp.pkey, *skey = NULL; + + /* Sanity check */ + if (ckey == NULL || s->s3->peer_tmp != NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE, + ERR_R_INTERNAL_ERROR); + return 0; + } + + if (!PACKET_get_net_2(pkt, &group_id)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + if ((context & SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST) != 0) { + const uint16_t *pgroups = NULL; + size_t i, num_groups; + + if (PACKET_remaining(pkt) != 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + /* + * It is an error if the HelloRetryRequest wants a key_share that we + * already sent in the first ClientHello + */ + if (group_id == s->s3->group_id) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_KEY_SHARE); + return 0; + } + + /* Validate the selected group is one we support */ + tls1_get_supported_groups(s, &pgroups, &num_groups); + for (i = 0; i < num_groups; i++) { + if (group_id == pgroups[i]) + break; + } + if (i >= num_groups + || !tls_curve_allowed(s, group_id, SSL_SECOP_CURVE_SUPPORTED)) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_KEY_SHARE); + return 0; + } + + s->s3->group_id = group_id; + EVP_PKEY_free(s->s3->tmp.pkey); + s->s3->tmp.pkey = NULL; + return 1; + } + + if (group_id != s->s3->group_id) { + /* + * This isn't for the group that we sent in the original + * key_share! + */ + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_KEY_SHARE, + SSL_R_BAD_KEY_SHARE); + return 0; + } + + if (!PACKET_as_length_prefixed_2(pkt, &encoded_pt) + || PACKET_remaining(&encoded_pt) == 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + skey = ssl_generate_pkey(ckey); + if (skey == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE, + ERR_R_MALLOC_FAILURE); + return 0; + } + if (!EVP_PKEY_set1_tls_encodedpoint(skey, PACKET_data(&encoded_pt), + PACKET_remaining(&encoded_pt))) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_KEY_SHARE, + SSL_R_BAD_ECPOINT); + EVP_PKEY_free(skey); + return 0; + } + + if (ssl_derive(s, ckey, skey, 1) == 0) { + /* SSLfatal() already called */ + EVP_PKEY_free(skey); + return 0; + } + s->s3->peer_tmp = skey; +#endif + + return 1; +} + +int tls_parse_stoc_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ + PACKET cookie; + + if (!PACKET_as_length_prefixed_2(pkt, &cookie) + || !PACKET_memdup(&cookie, &s->ext.tls13_cookie, + &s->ext.tls13_cookie_len)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_COOKIE, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + return 1; +} + +int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (context == SSL_EXT_TLS1_3_NEW_SESSION_TICKET) { + unsigned long max_early_data; + + if (!PACKET_get_net_4(pkt, &max_early_data) + || PACKET_remaining(pkt) != 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_EARLY_DATA, + SSL_R_INVALID_MAX_EARLY_DATA); + return 0; + } + + s->session->ext.max_early_data = max_early_data; + + return 1; + } + + if (PACKET_remaining(pkt) != 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_EARLY_DATA, + SSL_R_BAD_EXTENSION); + return 0; + } + + if (!s->ext.early_data_ok + || !s->hit + || s->session->ext.tick_identity != 0) { + /* + * If we get here then we didn't send early data, or we didn't resume + * using the first identity, or the SNI/ALPN is not consistent so the + * server should not be accepting it. + */ + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_EARLY_DATA, + SSL_R_BAD_EXTENSION); + return 0; + } + + s->ext.early_data = SSL_EARLY_DATA_ACCEPTED; + + return 1; +} + +int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ +#ifndef OPENSSL_NO_TLS1_3 + unsigned int identity; + + if (!PACKET_get_net_2(pkt, &identity) || PACKET_remaining(pkt) != 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_PSK, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + if (s->session->ext.tick_identity == (int)identity) { + s->hit = 1; + SSL_SESSION_free(s->psksession); + s->psksession = NULL; + return 1; + } + + if (s->psksession == NULL + || s->psksession->ext.tick_identity != (int)identity) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_PSK, + SSL_R_BAD_PSK_IDENTITY); + return 0; + } + + /* + * If we used the external PSK for sending early_data then s->early_secret + * is already set up, so don't overwrite it. Otherwise we copy the + * early_secret across that we generated earlier. + */ + if ((s->early_data_state != SSL_EARLY_DATA_WRITE_RETRY + && s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING) + || s->session->ext.max_early_data > 0 + || s->psksession->ext.max_early_data == 0) + memcpy(s->early_secret, s->psksession->early_secret, EVP_MAX_MD_SIZE); + + SSL_SESSION_free(s->session); + s->session = s->psksession; + s->psksession = NULL; + s->hit = 1; +#endif + + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/statem/extensions_cust.c b/trunk/3rdparty/openssl-1.1-fit/ssl/statem/extensions_cust.c new file mode 100644 index 000000000..a4cdc81d6 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/statem/extensions_cust.c @@ -0,0 +1,533 @@ +/* + * Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Custom extension utility functions */ + +#include +#include "../ssl_locl.h" +#include "internal/cryptlib.h" +#include "statem_locl.h" + +typedef struct { + void *add_arg; + custom_ext_add_cb add_cb; + custom_ext_free_cb free_cb; +} custom_ext_add_cb_wrap; + +typedef struct { + void *parse_arg; + custom_ext_parse_cb parse_cb; +} custom_ext_parse_cb_wrap; + +/* + * Provide thin wrapper callbacks which convert new style arguments to old style + */ +static int custom_ext_add_old_cb_wrap(SSL *s, unsigned int ext_type, + unsigned int context, + const unsigned char **out, + size_t *outlen, X509 *x, size_t chainidx, + int *al, void *add_arg) +{ + custom_ext_add_cb_wrap *add_cb_wrap = (custom_ext_add_cb_wrap *)add_arg; + + if (add_cb_wrap->add_cb == NULL) + return 1; + + return add_cb_wrap->add_cb(s, ext_type, out, outlen, al, + add_cb_wrap->add_arg); +} + +static void custom_ext_free_old_cb_wrap(SSL *s, unsigned int ext_type, + unsigned int context, + const unsigned char *out, void *add_arg) +{ + custom_ext_add_cb_wrap *add_cb_wrap = (custom_ext_add_cb_wrap *)add_arg; + + if (add_cb_wrap->free_cb == NULL) + return; + + add_cb_wrap->free_cb(s, ext_type, out, add_cb_wrap->add_arg); +} + +static int custom_ext_parse_old_cb_wrap(SSL *s, unsigned int ext_type, + unsigned int context, + const unsigned char *in, + size_t inlen, X509 *x, size_t chainidx, + int *al, void *parse_arg) +{ + custom_ext_parse_cb_wrap *parse_cb_wrap = + (custom_ext_parse_cb_wrap *)parse_arg; + + if (parse_cb_wrap->parse_cb == NULL) + return 1; + + return parse_cb_wrap->parse_cb(s, ext_type, in, inlen, al, + parse_cb_wrap->parse_arg); +} + +/* + * Find a custom extension from the list. The |role| param is there to + * support the legacy API where custom extensions for client and server could + * be set independently on the same SSL_CTX. It is set to ENDPOINT_SERVER if we + * are trying to find a method relevant to the server, ENDPOINT_CLIENT for the + * client, or ENDPOINT_BOTH for either + */ +custom_ext_method *custom_ext_find(const custom_ext_methods *exts, + ENDPOINT role, unsigned int ext_type, + size_t *idx) +{ + size_t i; + custom_ext_method *meth = exts->meths; + + for (i = 0; i < exts->meths_count; i++, meth++) { + if (ext_type == meth->ext_type + && (role == ENDPOINT_BOTH || role == meth->role + || meth->role == ENDPOINT_BOTH)) { + if (idx != NULL) + *idx = i; + return meth; + } + } + return NULL; +} + +/* + * Initialise custom extensions flags to indicate neither sent nor received. + */ +void custom_ext_init(custom_ext_methods *exts) +{ + size_t i; + custom_ext_method *meth = exts->meths; + + for (i = 0; i < exts->meths_count; i++, meth++) + meth->ext_flags = 0; +} + +/* Pass received custom extension data to the application for parsing. */ +int custom_ext_parse(SSL *s, unsigned int context, unsigned int ext_type, + const unsigned char *ext_data, size_t ext_size, X509 *x, + size_t chainidx) +{ + int al; + custom_ext_methods *exts = &s->cert->custext; + custom_ext_method *meth; + ENDPOINT role = ENDPOINT_BOTH; + + if ((context & (SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO)) != 0) + role = s->server ? ENDPOINT_SERVER : ENDPOINT_CLIENT; + + meth = custom_ext_find(exts, role, ext_type, NULL); + /* If not found return success */ + if (!meth) + return 1; + + /* Check if extension is defined for our protocol. If not, skip */ + if (!extension_is_relevant(s, meth->context, context)) + return 1; + + if ((context & (SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_3_SERVER_HELLO + | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS)) != 0) { + /* + * If it's ServerHello or EncryptedExtensions we can't have any + * extensions not sent in ClientHello. + */ + if ((meth->ext_flags & SSL_EXT_FLAG_SENT) == 0) { + SSLfatal(s, TLS1_AD_UNSUPPORTED_EXTENSION, SSL_F_CUSTOM_EXT_PARSE, + SSL_R_BAD_EXTENSION); + return 0; + } + } + + /* + * Extensions received in the ClientHello are marked with the + * SSL_EXT_FLAG_RECEIVED. This is so we know to add the equivalent + * extensions in the ServerHello/EncryptedExtensions message + */ + if ((context & SSL_EXT_CLIENT_HELLO) != 0) + meth->ext_flags |= SSL_EXT_FLAG_RECEIVED; + + /* If no parse function set return success */ + if (!meth->parse_cb) + return 1; + + if (meth->parse_cb(s, ext_type, context, ext_data, ext_size, x, chainidx, + &al, meth->parse_arg) <= 0) { + SSLfatal(s, al, SSL_F_CUSTOM_EXT_PARSE, SSL_R_BAD_EXTENSION); + return 0; + } + + return 1; +} + +/* + * Request custom extension data from the application and add to the return + * buffer. + */ +int custom_ext_add(SSL *s, int context, WPACKET *pkt, X509 *x, size_t chainidx, + int maxversion) +{ + custom_ext_methods *exts = &s->cert->custext; + custom_ext_method *meth; + size_t i; + int al; + + for (i = 0; i < exts->meths_count; i++) { + const unsigned char *out = NULL; + size_t outlen = 0; + + meth = exts->meths + i; + + if (!should_add_extension(s, meth->context, context, maxversion)) + continue; + + if ((context & (SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_3_SERVER_HELLO + | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS + | SSL_EXT_TLS1_3_CERTIFICATE + | SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST)) != 0) { + /* Only send extensions present in ClientHello. */ + if (!(meth->ext_flags & SSL_EXT_FLAG_RECEIVED)) + continue; + } + /* + * We skip it if the callback is absent - except for a ClientHello where + * we add an empty extension. + */ + if ((context & SSL_EXT_CLIENT_HELLO) == 0 && meth->add_cb == NULL) + continue; + + if (meth->add_cb != NULL) { + int cb_retval = meth->add_cb(s, meth->ext_type, context, &out, + &outlen, x, chainidx, &al, + meth->add_arg); + + if (cb_retval < 0) { + SSLfatal(s, al, SSL_F_CUSTOM_EXT_ADD, SSL_R_CALLBACK_FAILED); + return 0; /* error */ + } + if (cb_retval == 0) + continue; /* skip this extension */ + } + + if (!WPACKET_put_bytes_u16(pkt, meth->ext_type) + || !WPACKET_start_sub_packet_u16(pkt) + || (outlen > 0 && !WPACKET_memcpy(pkt, out, outlen)) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CUSTOM_EXT_ADD, + ERR_R_INTERNAL_ERROR); + return 0; + } + if ((context & SSL_EXT_CLIENT_HELLO) != 0) { + /* + * We can't send duplicates: code logic should prevent this. + */ + if (!ossl_assert((meth->ext_flags & SSL_EXT_FLAG_SENT) == 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CUSTOM_EXT_ADD, + ERR_R_INTERNAL_ERROR); + return 0; + } + /* + * Indicate extension has been sent: this is both a sanity check to + * ensure we don't send duplicate extensions and indicates that it + * is not an error if the extension is present in ServerHello. + */ + meth->ext_flags |= SSL_EXT_FLAG_SENT; + } + if (meth->free_cb != NULL) + meth->free_cb(s, meth->ext_type, context, out, meth->add_arg); + } + return 1; +} + +/* Copy the flags from src to dst for any extensions that exist in both */ +int custom_exts_copy_flags(custom_ext_methods *dst, + const custom_ext_methods *src) +{ + size_t i; + custom_ext_method *methsrc = src->meths; + + for (i = 0; i < src->meths_count; i++, methsrc++) { + custom_ext_method *methdst = custom_ext_find(dst, methsrc->role, + methsrc->ext_type, NULL); + + if (methdst == NULL) + continue; + + methdst->ext_flags = methsrc->ext_flags; + } + + return 1; +} + +/* Copy table of custom extensions */ +int custom_exts_copy(custom_ext_methods *dst, const custom_ext_methods *src) +{ + size_t i; + int err = 0; + + if (src->meths_count > 0) { + dst->meths = + OPENSSL_memdup(src->meths, + sizeof(*src->meths) * src->meths_count); + if (dst->meths == NULL) + return 0; + dst->meths_count = src->meths_count; + + for (i = 0; i < src->meths_count; i++) { + custom_ext_method *methsrc = src->meths + i; + custom_ext_method *methdst = dst->meths + i; + + if (methsrc->add_cb != custom_ext_add_old_cb_wrap) + continue; + + /* + * We have found an old style API wrapper. We need to copy the + * arguments too. + */ + + if (err) { + methdst->add_arg = NULL; + methdst->parse_arg = NULL; + continue; + } + + methdst->add_arg = OPENSSL_memdup(methsrc->add_arg, + sizeof(custom_ext_add_cb_wrap)); + methdst->parse_arg = OPENSSL_memdup(methsrc->parse_arg, + sizeof(custom_ext_parse_cb_wrap)); + + if (methdst->add_arg == NULL || methdst->parse_arg == NULL) + err = 1; + } + } + + if (err) { + custom_exts_free(dst); + return 0; + } + + return 1; +} + +void custom_exts_free(custom_ext_methods *exts) +{ + size_t i; + custom_ext_method *meth; + + for (i = 0, meth = exts->meths; i < exts->meths_count; i++, meth++) { + if (meth->add_cb != custom_ext_add_old_cb_wrap) + continue; + + /* Old style API wrapper. Need to free the arguments too */ + OPENSSL_free(meth->add_arg); + OPENSSL_free(meth->parse_arg); + } + OPENSSL_free(exts->meths); +} + +/* Return true if a client custom extension exists, false otherwise */ +int SSL_CTX_has_client_custom_ext(const SSL_CTX *ctx, unsigned int ext_type) +{ + return custom_ext_find(&ctx->cert->custext, ENDPOINT_CLIENT, ext_type, + NULL) != NULL; +} + +static int add_custom_ext_intern(SSL_CTX *ctx, ENDPOINT role, + unsigned int ext_type, + unsigned int context, + SSL_custom_ext_add_cb_ex add_cb, + SSL_custom_ext_free_cb_ex free_cb, + void *add_arg, + SSL_custom_ext_parse_cb_ex parse_cb, + void *parse_arg) +{ + custom_ext_methods *exts = &ctx->cert->custext; + custom_ext_method *meth, *tmp; + + /* + * Check application error: if add_cb is not set free_cb will never be + * called. + */ + if (add_cb == NULL && free_cb != NULL) + return 0; + +#ifndef OPENSSL_NO_CT + /* + * We don't want applications registering callbacks for SCT extensions + * whilst simultaneously using the built-in SCT validation features, as + * these two things may not play well together. + */ + if (ext_type == TLSEXT_TYPE_signed_certificate_timestamp + && (context & SSL_EXT_CLIENT_HELLO) != 0 + && SSL_CTX_ct_is_enabled(ctx)) + return 0; +#endif + + /* + * Don't add if extension supported internally, but make exception + * for extension types that previously were not supported, but now are. + */ + if (SSL_extension_supported(ext_type) + && ext_type != TLSEXT_TYPE_signed_certificate_timestamp) + return 0; + + /* Extension type must fit in 16 bits */ + if (ext_type > 0xffff) + return 0; + /* Search for duplicate */ + if (custom_ext_find(exts, role, ext_type, NULL)) + return 0; + tmp = OPENSSL_realloc(exts->meths, + (exts->meths_count + 1) * sizeof(custom_ext_method)); + if (tmp == NULL) + return 0; + + exts->meths = tmp; + meth = exts->meths + exts->meths_count; + memset(meth, 0, sizeof(*meth)); + meth->role = role; + meth->context = context; + meth->parse_cb = parse_cb; + meth->add_cb = add_cb; + meth->free_cb = free_cb; + meth->ext_type = ext_type; + meth->add_arg = add_arg; + meth->parse_arg = parse_arg; + exts->meths_count++; + return 1; +} + +static int add_old_custom_ext(SSL_CTX *ctx, ENDPOINT role, + unsigned int ext_type, + unsigned int context, + custom_ext_add_cb add_cb, + custom_ext_free_cb free_cb, + void *add_arg, + custom_ext_parse_cb parse_cb, void *parse_arg) +{ + custom_ext_add_cb_wrap *add_cb_wrap + = OPENSSL_malloc(sizeof(*add_cb_wrap)); + custom_ext_parse_cb_wrap *parse_cb_wrap + = OPENSSL_malloc(sizeof(*parse_cb_wrap)); + int ret; + + if (add_cb_wrap == NULL || parse_cb_wrap == NULL) { + OPENSSL_free(add_cb_wrap); + OPENSSL_free(parse_cb_wrap); + return 0; + } + + add_cb_wrap->add_arg = add_arg; + add_cb_wrap->add_cb = add_cb; + add_cb_wrap->free_cb = free_cb; + parse_cb_wrap->parse_arg = parse_arg; + parse_cb_wrap->parse_cb = parse_cb; + + ret = add_custom_ext_intern(ctx, role, ext_type, + context, + custom_ext_add_old_cb_wrap, + custom_ext_free_old_cb_wrap, + add_cb_wrap, + custom_ext_parse_old_cb_wrap, + parse_cb_wrap); + + if (!ret) { + OPENSSL_free(add_cb_wrap); + OPENSSL_free(parse_cb_wrap); + } + + return ret; +} + +/* Application level functions to add the old custom extension callbacks */ +int SSL_CTX_add_client_custom_ext(SSL_CTX *ctx, unsigned int ext_type, + custom_ext_add_cb add_cb, + custom_ext_free_cb free_cb, + void *add_arg, + custom_ext_parse_cb parse_cb, void *parse_arg) +{ + return add_old_custom_ext(ctx, ENDPOINT_CLIENT, ext_type, + SSL_EXT_TLS1_2_AND_BELOW_ONLY + | SSL_EXT_CLIENT_HELLO + | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_IGNORE_ON_RESUMPTION, + add_cb, free_cb, add_arg, parse_cb, parse_arg); +} + +int SSL_CTX_add_server_custom_ext(SSL_CTX *ctx, unsigned int ext_type, + custom_ext_add_cb add_cb, + custom_ext_free_cb free_cb, + void *add_arg, + custom_ext_parse_cb parse_cb, void *parse_arg) +{ + return add_old_custom_ext(ctx, ENDPOINT_SERVER, ext_type, + SSL_EXT_TLS1_2_AND_BELOW_ONLY + | SSL_EXT_CLIENT_HELLO + | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_IGNORE_ON_RESUMPTION, + add_cb, free_cb, add_arg, parse_cb, parse_arg); +} + +int SSL_CTX_add_custom_ext(SSL_CTX *ctx, unsigned int ext_type, + unsigned int context, + SSL_custom_ext_add_cb_ex add_cb, + SSL_custom_ext_free_cb_ex free_cb, + void *add_arg, + SSL_custom_ext_parse_cb_ex parse_cb, void *parse_arg) +{ + return add_custom_ext_intern(ctx, ENDPOINT_BOTH, ext_type, context, add_cb, + free_cb, add_arg, parse_cb, parse_arg); +} + +int SSL_extension_supported(unsigned int ext_type) +{ + switch (ext_type) { + /* Internally supported extensions. */ + case TLSEXT_TYPE_application_layer_protocol_negotiation: +#ifndef OPENSSL_NO_EC + case TLSEXT_TYPE_ec_point_formats: + case TLSEXT_TYPE_supported_groups: + case TLSEXT_TYPE_key_share: +#endif +#ifndef OPENSSL_NO_NEXTPROTONEG + case TLSEXT_TYPE_next_proto_neg: +#endif + case TLSEXT_TYPE_padding: + case TLSEXT_TYPE_renegotiate: + case TLSEXT_TYPE_max_fragment_length: + case TLSEXT_TYPE_server_name: + case TLSEXT_TYPE_session_ticket: + case TLSEXT_TYPE_signature_algorithms: +#ifndef OPENSSL_NO_SRP + case TLSEXT_TYPE_srp: +#endif +#ifndef OPENSSL_NO_OCSP + case TLSEXT_TYPE_status_request: +#endif +#ifndef OPENSSL_NO_CT + case TLSEXT_TYPE_signed_certificate_timestamp: +#endif +#ifndef OPENSSL_NO_SRTP + case TLSEXT_TYPE_use_srtp: +#endif + case TLSEXT_TYPE_encrypt_then_mac: + case TLSEXT_TYPE_supported_versions: + case TLSEXT_TYPE_extended_master_secret: + case TLSEXT_TYPE_psk_kex_modes: + case TLSEXT_TYPE_cookie: + case TLSEXT_TYPE_early_data: + case TLSEXT_TYPE_certificate_authorities: + case TLSEXT_TYPE_psk: + case TLSEXT_TYPE_post_handshake_auth: + return 1; + default: + return 0; + } +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/statem/extensions_srvr.c b/trunk/3rdparty/openssl-1.1-fit/ssl/statem/extensions_srvr.c new file mode 100644 index 000000000..0f2b22392 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/statem/extensions_srvr.c @@ -0,0 +1,1959 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "../ssl_locl.h" +#include "statem_locl.h" +#include "internal/cryptlib.h" + +#define COOKIE_STATE_FORMAT_VERSION 0 + +/* + * 2 bytes for packet length, 2 bytes for format version, 2 bytes for + * protocol version, 2 bytes for group id, 2 bytes for cipher id, 1 byte for + * key_share present flag, 4 bytes for timestamp, 2 bytes for the hashlen, + * EVP_MAX_MD_SIZE for transcript hash, 1 byte for app cookie length, app cookie + * length bytes, SHA256_DIGEST_LENGTH bytes for the HMAC of the whole thing. + */ +#define MAX_COOKIE_SIZE (2 + 2 + 2 + 2 + 2 + 1 + 4 + 2 + EVP_MAX_MD_SIZE + 1 \ + + SSL_COOKIE_LENGTH + SHA256_DIGEST_LENGTH) + +/* + * Message header + 2 bytes for protocol version + number of random bytes + + * + 1 byte for legacy session id length + number of bytes in legacy session id + * + 2 bytes for ciphersuite + 1 byte for legacy compression + * + 2 bytes for extension block length + 6 bytes for key_share extension + * + 4 bytes for cookie extension header + the number of bytes in the cookie + */ +#define MAX_HRR_SIZE (SSL3_HM_HEADER_LENGTH + 2 + SSL3_RANDOM_SIZE + 1 \ + + SSL_MAX_SSL_SESSION_ID_LENGTH + 2 + 1 + 2 + 6 + 4 \ + + MAX_COOKIE_SIZE) + +/* + * Parse the client's renegotiation binding and abort if it's not right + */ +int tls_parse_ctos_renegotiate(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + unsigned int ilen; + const unsigned char *data; + + /* Parse the length byte */ + if (!PACKET_get_1(pkt, &ilen) + || !PACKET_get_bytes(pkt, &data, ilen)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE, + SSL_R_RENEGOTIATION_ENCODING_ERR); + return 0; + } + + /* Check that the extension matches */ + if (ilen != s->s3->previous_client_finished_len) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE, + SSL_R_RENEGOTIATION_MISMATCH); + return 0; + } + + if (memcmp(data, s->s3->previous_client_finished, + s->s3->previous_client_finished_len)) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE, + SSL_R_RENEGOTIATION_MISMATCH); + return 0; + } + + s->s3->send_connection_binding = 1; + + return 1; +} + +/*- + * The servername extension is treated as follows: + * + * - Only the hostname type is supported with a maximum length of 255. + * - The servername is rejected if too long or if it contains zeros, + * in which case an fatal alert is generated. + * - The servername field is maintained together with the session cache. + * - When a session is resumed, the servername call back invoked in order + * to allow the application to position itself to the right context. + * - The servername is acknowledged if it is new for a session or when + * it is identical to a previously used for the same session. + * Applications can control the behaviour. They can at any time + * set a 'desirable' servername for a new SSL object. This can be the + * case for example with HTTPS when a Host: header field is received and + * a renegotiation is requested. In this case, a possible servername + * presented in the new client hello is only acknowledged if it matches + * the value of the Host: field. + * - Applications must use SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION + * if they provide for changing an explicit servername context for the + * session, i.e. when the session has been established with a servername + * extension. + * - On session reconnect, the servername extension may be absent. + */ +int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + unsigned int servname_type; + PACKET sni, hostname; + + if (!PACKET_as_length_prefixed_2(pkt, &sni) + /* ServerNameList must be at least 1 byte long. */ + || PACKET_remaining(&sni) == 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_SERVER_NAME, + SSL_R_BAD_EXTENSION); + return 0; + } + + /* + * Although the intent was for server_name to be extensible, RFC 4366 + * was not clear about it; and so OpenSSL among other implementations, + * always and only allows a 'host_name' name types. + * RFC 6066 corrected the mistake but adding new name types + * is nevertheless no longer feasible, so act as if no other + * SNI types can exist, to simplify parsing. + * + * Also note that the RFC permits only one SNI value per type, + * i.e., we can only have a single hostname. + */ + if (!PACKET_get_1(&sni, &servname_type) + || servname_type != TLSEXT_NAMETYPE_host_name + || !PACKET_as_length_prefixed_2(&sni, &hostname)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_SERVER_NAME, + SSL_R_BAD_EXTENSION); + return 0; + } + + if (!s->hit || SSL_IS_TLS13(s)) { + if (PACKET_remaining(&hostname) > TLSEXT_MAXLEN_host_name) { + SSLfatal(s, SSL_AD_UNRECOGNIZED_NAME, + SSL_F_TLS_PARSE_CTOS_SERVER_NAME, + SSL_R_BAD_EXTENSION); + return 0; + } + + if (PACKET_contains_zero_byte(&hostname)) { + SSLfatal(s, SSL_AD_UNRECOGNIZED_NAME, + SSL_F_TLS_PARSE_CTOS_SERVER_NAME, + SSL_R_BAD_EXTENSION); + return 0; + } + + /* + * Store the requested SNI in the SSL as temporary storage. + * If we accept it, it will get stored in the SSL_SESSION as well. + */ + OPENSSL_free(s->ext.hostname); + s->ext.hostname = NULL; + if (!PACKET_strndup(&hostname, &s->ext.hostname)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_SERVER_NAME, + ERR_R_INTERNAL_ERROR); + return 0; + } + + s->servername_done = 1; + } + if (s->hit) { + /* + * TODO(openssl-team): if the SNI doesn't match, we MUST + * fall back to a full handshake. + */ + s->servername_done = (s->session->ext.hostname != NULL) + && PACKET_equal(&hostname, s->session->ext.hostname, + strlen(s->session->ext.hostname)); + + if (!s->servername_done && s->session->ext.hostname != NULL) + s->ext.early_data_ok = 0; + } + + return 1; +} + +int tls_parse_ctos_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + unsigned int value; + + if (PACKET_remaining(pkt) != 1 || !PACKET_get_1(pkt, &value)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN, + SSL_R_BAD_EXTENSION); + return 0; + } + + /* Received |value| should be a valid max-fragment-length code. */ + if (!IS_MAX_FRAGMENT_LENGTH_EXT_VALID(value)) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN, + SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH); + return 0; + } + + /* + * RFC 6066: The negotiated length applies for the duration of the session + * including session resumptions. + * We should receive the same code as in resumed session ! + */ + if (s->hit && s->session->ext.max_fragment_len_mode != value) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN, + SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH); + return 0; + } + + /* + * Store it in session, so it'll become binding for us + * and we'll include it in a next Server Hello. + */ + s->session->ext.max_fragment_len_mode = value; + return 1; +} + +#ifndef OPENSSL_NO_SRP +int tls_parse_ctos_srp(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ + PACKET srp_I; + + if (!PACKET_as_length_prefixed_1(pkt, &srp_I) + || PACKET_contains_zero_byte(&srp_I)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_SRP, + SSL_R_BAD_EXTENSION); + return 0; + } + + /* + * TODO(openssl-team): currently, we re-authenticate the user + * upon resumption. Instead, we MUST ignore the login. + */ + if (!PACKET_strndup(&srp_I, &s->srp_ctx.login)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_SRP, + ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} +#endif + +#ifndef OPENSSL_NO_EC +int tls_parse_ctos_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + PACKET ec_point_format_list; + + if (!PACKET_as_length_prefixed_1(pkt, &ec_point_format_list) + || PACKET_remaining(&ec_point_format_list) == 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS, + SSL_R_BAD_EXTENSION); + return 0; + } + + if (!s->hit) { + if (!PACKET_memdup(&ec_point_format_list, + &s->session->ext.ecpointformats, + &s->session->ext.ecpointformats_len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR); + return 0; + } + } + + return 1; +} +#endif /* OPENSSL_NO_EC */ + +int tls_parse_ctos_session_ticket(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (s->ext.session_ticket_cb && + !s->ext.session_ticket_cb(s, PACKET_data(pkt), + PACKET_remaining(pkt), + s->ext.session_ticket_cb_arg)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PARSE_CTOS_SESSION_TICKET, ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} + +int tls_parse_ctos_sig_algs_cert(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + PACKET supported_sig_algs; + + if (!PACKET_as_length_prefixed_2(pkt, &supported_sig_algs) + || PACKET_remaining(&supported_sig_algs) == 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_SIG_ALGS_CERT, SSL_R_BAD_EXTENSION); + return 0; + } + + if (!s->hit && !tls1_save_sigalgs(s, &supported_sig_algs, 1)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_SIG_ALGS_CERT, SSL_R_BAD_EXTENSION); + return 0; + } + + return 1; +} + +int tls_parse_ctos_sig_algs(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ + PACKET supported_sig_algs; + + if (!PACKET_as_length_prefixed_2(pkt, &supported_sig_algs) + || PACKET_remaining(&supported_sig_algs) == 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_SIG_ALGS, SSL_R_BAD_EXTENSION); + return 0; + } + + if (!s->hit && !tls1_save_sigalgs(s, &supported_sig_algs, 0)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_SIG_ALGS, SSL_R_BAD_EXTENSION); + return 0; + } + + return 1; +} + +#ifndef OPENSSL_NO_OCSP +int tls_parse_ctos_status_request(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + PACKET responder_id_list, exts; + + /* We ignore this in a resumption handshake */ + if (s->hit) + return 1; + + /* Not defined if we get one of these in a client Certificate */ + if (x != NULL) + return 1; + + if (!PACKET_get_1(pkt, (unsigned int *)&s->ext.status_type)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION); + return 0; + } + + if (s->ext.status_type != TLSEXT_STATUSTYPE_ocsp) { + /* + * We don't know what to do with any other type so ignore it. + */ + s->ext.status_type = TLSEXT_STATUSTYPE_nothing; + return 1; + } + + if (!PACKET_get_length_prefixed_2 (pkt, &responder_id_list)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION); + return 0; + } + + /* + * We remove any OCSP_RESPIDs from a previous handshake + * to prevent unbounded memory growth - CVE-2016-6304 + */ + sk_OCSP_RESPID_pop_free(s->ext.ocsp.ids, OCSP_RESPID_free); + if (PACKET_remaining(&responder_id_list) > 0) { + s->ext.ocsp.ids = sk_OCSP_RESPID_new_null(); + if (s->ext.ocsp.ids == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, ERR_R_MALLOC_FAILURE); + return 0; + } + } else { + s->ext.ocsp.ids = NULL; + } + + while (PACKET_remaining(&responder_id_list) > 0) { + OCSP_RESPID *id; + PACKET responder_id; + const unsigned char *id_data; + + if (!PACKET_get_length_prefixed_2(&responder_id_list, &responder_id) + || PACKET_remaining(&responder_id) == 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION); + return 0; + } + + id_data = PACKET_data(&responder_id); + /* TODO(size_t): Convert d2i_* to size_t */ + id = d2i_OCSP_RESPID(NULL, &id_data, + (int)PACKET_remaining(&responder_id)); + if (id == NULL) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION); + return 0; + } + + if (id_data != PACKET_end(&responder_id)) { + OCSP_RESPID_free(id); + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION); + + return 0; + } + + if (!sk_OCSP_RESPID_push(s->ext.ocsp.ids, id)) { + OCSP_RESPID_free(id); + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR); + + return 0; + } + } + + /* Read in request_extensions */ + if (!PACKET_as_length_prefixed_2(pkt, &exts)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION); + return 0; + } + + if (PACKET_remaining(&exts) > 0) { + const unsigned char *ext_data = PACKET_data(&exts); + + sk_X509_EXTENSION_pop_free(s->ext.ocsp.exts, + X509_EXTENSION_free); + s->ext.ocsp.exts = + d2i_X509_EXTENSIONS(NULL, &ext_data, (int)PACKET_remaining(&exts)); + if (s->ext.ocsp.exts == NULL || ext_data != PACKET_end(&exts)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION); + return 0; + } + } + + return 1; +} +#endif + +#ifndef OPENSSL_NO_NEXTPROTONEG +int tls_parse_ctos_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ + /* + * We shouldn't accept this extension on a + * renegotiation. + */ + if (SSL_IS_FIRST_HANDSHAKE(s)) + s->s3->npn_seen = 1; + + return 1; +} +#endif + +/* + * Save the ALPN extension in a ClientHello.|pkt| holds the contents of the ALPN + * extension, not including type and length. Returns: 1 on success, 0 on error. + */ +int tls_parse_ctos_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ + PACKET protocol_list, save_protocol_list, protocol; + + if (!SSL_IS_FIRST_HANDSHAKE(s)) + return 1; + + if (!PACKET_as_length_prefixed_2(pkt, &protocol_list) + || PACKET_remaining(&protocol_list) < 2) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_ALPN, + SSL_R_BAD_EXTENSION); + return 0; + } + + save_protocol_list = protocol_list; + do { + /* Protocol names can't be empty. */ + if (!PACKET_get_length_prefixed_1(&protocol_list, &protocol) + || PACKET_remaining(&protocol) == 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_ALPN, + SSL_R_BAD_EXTENSION); + return 0; + } + } while (PACKET_remaining(&protocol_list) != 0); + + OPENSSL_free(s->s3->alpn_proposed); + s->s3->alpn_proposed = NULL; + s->s3->alpn_proposed_len = 0; + if (!PACKET_memdup(&save_protocol_list, + &s->s3->alpn_proposed, &s->s3->alpn_proposed_len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_ALPN, + ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} + +#ifndef OPENSSL_NO_SRTP +int tls_parse_ctos_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ + STACK_OF(SRTP_PROTECTION_PROFILE) *srvr; + unsigned int ct, mki_len, id; + int i, srtp_pref; + PACKET subpkt; + + /* Ignore this if we have no SRTP profiles */ + if (SSL_get_srtp_profiles(s) == NULL) + return 1; + + /* Pull off the length of the cipher suite list and check it is even */ + if (!PACKET_get_net_2(pkt, &ct) || (ct & 1) != 0 + || !PACKET_get_sub_packet(pkt, &subpkt, ct)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP, + SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); + return 0; + } + + srvr = SSL_get_srtp_profiles(s); + s->srtp_profile = NULL; + /* Search all profiles for a match initially */ + srtp_pref = sk_SRTP_PROTECTION_PROFILE_num(srvr); + + while (PACKET_remaining(&subpkt)) { + if (!PACKET_get_net_2(&subpkt, &id)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP, + SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); + return 0; + } + + /* + * Only look for match in profiles of higher preference than + * current match. + * If no profiles have been have been configured then this + * does nothing. + */ + for (i = 0; i < srtp_pref; i++) { + SRTP_PROTECTION_PROFILE *sprof = + sk_SRTP_PROTECTION_PROFILE_value(srvr, i); + + if (sprof->id == id) { + s->srtp_profile = sprof; + srtp_pref = i; + break; + } + } + } + + /* Now extract the MKI value as a sanity check, but discard it for now */ + if (!PACKET_get_1(pkt, &mki_len)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP, + SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); + return 0; + } + + if (!PACKET_forward(pkt, mki_len) + || PACKET_remaining(pkt)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP, + SSL_R_BAD_SRTP_MKI_VALUE); + return 0; + } + + return 1; +} +#endif + +int tls_parse_ctos_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ + if (!(s->options & SSL_OP_NO_ENCRYPT_THEN_MAC)) + s->ext.use_etm = 1; + + return 1; +} + +/* + * Process a psk_kex_modes extension received in the ClientHello. |pkt| contains + * the raw PACKET data for the extension. Returns 1 on success or 0 on failure. + */ +int tls_parse_ctos_psk_kex_modes(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ +#ifndef OPENSSL_NO_TLS1_3 + PACKET psk_kex_modes; + unsigned int mode; + + if (!PACKET_as_length_prefixed_1(pkt, &psk_kex_modes) + || PACKET_remaining(&psk_kex_modes) == 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES, + SSL_R_BAD_EXTENSION); + return 0; + } + + while (PACKET_get_1(&psk_kex_modes, &mode)) { + if (mode == TLSEXT_KEX_MODE_KE_DHE) + s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE_DHE; + else if (mode == TLSEXT_KEX_MODE_KE + && (s->options & SSL_OP_ALLOW_NO_DHE_KEX) != 0) + s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE; + } +#endif + + return 1; +} + +/* + * Process a key_share extension received in the ClientHello. |pkt| contains + * the raw PACKET data for the extension. Returns 1 on success or 0 on failure. + */ +int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ +#ifndef OPENSSL_NO_TLS1_3 + unsigned int group_id; + PACKET key_share_list, encoded_pt; + const uint16_t *clntgroups, *srvrgroups; + size_t clnt_num_groups, srvr_num_groups; + int found = 0; + + if (s->hit && (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE_DHE) == 0) + return 1; + + /* Sanity check */ + if (s->s3->peer_tmp != NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE, + ERR_R_INTERNAL_ERROR); + return 0; + } + + if (!PACKET_as_length_prefixed_2(pkt, &key_share_list)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + /* Get our list of supported groups */ + tls1_get_supported_groups(s, &srvrgroups, &srvr_num_groups); + /* Get the clients list of supported groups. */ + tls1_get_peer_groups(s, &clntgroups, &clnt_num_groups); + if (clnt_num_groups == 0) { + /* + * This can only happen if the supported_groups extension was not sent, + * because we verify that the length is non-zero when we process that + * extension. + */ + SSLfatal(s, SSL_AD_MISSING_EXTENSION, SSL_F_TLS_PARSE_CTOS_KEY_SHARE, + SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION); + return 0; + } + + if (s->s3->group_id != 0 && PACKET_remaining(&key_share_list) == 0) { + /* + * If we set a group_id already, then we must have sent an HRR + * requesting a new key_share. If we haven't got one then that is an + * error + */ + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_KEY_SHARE, + SSL_R_BAD_KEY_SHARE); + return 0; + } + + while (PACKET_remaining(&key_share_list) > 0) { + if (!PACKET_get_net_2(&key_share_list, &group_id) + || !PACKET_get_length_prefixed_2(&key_share_list, &encoded_pt) + || PACKET_remaining(&encoded_pt) == 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + /* + * If we already found a suitable key_share we loop through the + * rest to verify the structure, but don't process them. + */ + if (found) + continue; + + /* + * If we sent an HRR then the key_share sent back MUST be for the group + * we requested, and must be the only key_share sent. + */ + if (s->s3->group_id != 0 + && (group_id != s->s3->group_id + || PACKET_remaining(&key_share_list) != 0)) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_KEY_SHARE); + return 0; + } + + /* Check if this share is in supported_groups sent from client */ + if (!check_in_list(s, group_id, clntgroups, clnt_num_groups, 0)) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_KEY_SHARE); + return 0; + } + + /* Check if this share is for a group we can use */ + if (!check_in_list(s, group_id, srvrgroups, srvr_num_groups, 1)) { + /* Share not suitable */ + continue; + } + + if ((s->s3->peer_tmp = ssl_generate_param_group(group_id)) == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE, + SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS); + return 0; + } + + s->s3->group_id = group_id; + + if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp, + PACKET_data(&encoded_pt), + PACKET_remaining(&encoded_pt))) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_ECPOINT); + return 0; + } + + found = 1; + } +#endif + + return 1; +} + +int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ +#ifndef OPENSSL_NO_TLS1_3 + unsigned int format, version, key_share, group_id; + EVP_MD_CTX *hctx; + EVP_PKEY *pkey; + PACKET cookie, raw, chhash, appcookie; + WPACKET hrrpkt; + const unsigned char *data, *mdin, *ciphdata; + unsigned char hmac[SHA256_DIGEST_LENGTH]; + unsigned char hrr[MAX_HRR_SIZE]; + size_t rawlen, hmaclen, hrrlen, ciphlen; + unsigned long tm, now; + + /* Ignore any cookie if we're not set up to verify it */ + if (s->ctx->verify_stateless_cookie_cb == NULL + || (s->s3->flags & TLS1_FLAGS_STATELESS) == 0) + return 1; + + if (!PACKET_as_length_prefixed_2(pkt, &cookie)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + raw = cookie; + data = PACKET_data(&raw); + rawlen = PACKET_remaining(&raw); + if (rawlen < SHA256_DIGEST_LENGTH + || !PACKET_forward(&raw, rawlen - SHA256_DIGEST_LENGTH)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE, + SSL_R_LENGTH_MISMATCH); + return 0; + } + mdin = PACKET_data(&raw); + + /* Verify the HMAC of the cookie */ + hctx = EVP_MD_CTX_create(); + pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, + s->session_ctx->ext.cookie_hmac_key, + sizeof(s->session_ctx->ext + .cookie_hmac_key)); + if (hctx == NULL || pkey == NULL) { + EVP_MD_CTX_free(hctx); + EVP_PKEY_free(pkey); + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE, + ERR_R_MALLOC_FAILURE); + return 0; + } + + hmaclen = SHA256_DIGEST_LENGTH; + if (EVP_DigestSignInit(hctx, NULL, EVP_sha256(), NULL, pkey) <= 0 + || EVP_DigestSign(hctx, hmac, &hmaclen, data, + rawlen - SHA256_DIGEST_LENGTH) <= 0 + || hmaclen != SHA256_DIGEST_LENGTH) { + EVP_MD_CTX_free(hctx); + EVP_PKEY_free(pkey); + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE, + ERR_R_INTERNAL_ERROR); + return 0; + } + + EVP_MD_CTX_free(hctx); + EVP_PKEY_free(pkey); + + if (CRYPTO_memcmp(hmac, mdin, SHA256_DIGEST_LENGTH) != 0) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE, + SSL_R_COOKIE_MISMATCH); + return 0; + } + + if (!PACKET_get_net_2(&cookie, &format)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE, + SSL_R_LENGTH_MISMATCH); + return 0; + } + /* Check the cookie format is something we recognise. Ignore it if not */ + if (format != COOKIE_STATE_FORMAT_VERSION) + return 1; + + /* + * The rest of these checks really shouldn't fail since we have verified the + * HMAC above. + */ + + /* Check the version number is sane */ + if (!PACKET_get_net_2(&cookie, &version)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE, + SSL_R_LENGTH_MISMATCH); + return 0; + } + if (version != TLS1_3_VERSION) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE, + SSL_R_BAD_PROTOCOL_VERSION_NUMBER); + return 0; + } + + if (!PACKET_get_net_2(&cookie, &group_id)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + ciphdata = PACKET_data(&cookie); + if (!PACKET_forward(&cookie, 2)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE, + SSL_R_LENGTH_MISMATCH); + return 0; + } + if (group_id != s->s3->group_id + || s->s3->tmp.new_cipher + != ssl_get_cipher_by_char(s, ciphdata, 0)) { + /* + * We chose a different cipher or group id this time around to what is + * in the cookie. Something must have changed. + */ + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE, + SSL_R_BAD_CIPHER); + return 0; + } + + if (!PACKET_get_1(&cookie, &key_share) + || !PACKET_get_net_4(&cookie, &tm) + || !PACKET_get_length_prefixed_2(&cookie, &chhash) + || !PACKET_get_length_prefixed_1(&cookie, &appcookie) + || PACKET_remaining(&cookie) != SHA256_DIGEST_LENGTH) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + /* We tolerate a cookie age of up to 10 minutes (= 60 * 10 seconds) */ + now = (unsigned long)time(NULL); + if (tm > now || (now - tm) > 600) { + /* Cookie is stale. Ignore it */ + return 1; + } + + /* Verify the app cookie */ + if (s->ctx->verify_stateless_cookie_cb(s, PACKET_data(&appcookie), + PACKET_remaining(&appcookie)) == 0) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE, + SSL_R_COOKIE_MISMATCH); + return 0; + } + + /* + * Reconstruct the HRR that we would have sent in response to the original + * ClientHello so we can add it to the transcript hash. + * Note: This won't work with custom HRR extensions + */ + if (!WPACKET_init_static_len(&hrrpkt, hrr, sizeof(hrr), 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE, + ERR_R_INTERNAL_ERROR); + return 0; + } + if (!WPACKET_put_bytes_u8(&hrrpkt, SSL3_MT_SERVER_HELLO) + || !WPACKET_start_sub_packet_u24(&hrrpkt) + || !WPACKET_put_bytes_u16(&hrrpkt, TLS1_2_VERSION) + || !WPACKET_memcpy(&hrrpkt, hrrrandom, SSL3_RANDOM_SIZE) + || !WPACKET_sub_memcpy_u8(&hrrpkt, s->tmp_session_id, + s->tmp_session_id_len) + || !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, &hrrpkt, + &ciphlen) + || !WPACKET_put_bytes_u8(&hrrpkt, 0) + || !WPACKET_start_sub_packet_u16(&hrrpkt)) { + WPACKET_cleanup(&hrrpkt); + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE, + ERR_R_INTERNAL_ERROR); + return 0; + } + if (!WPACKET_put_bytes_u16(&hrrpkt, TLSEXT_TYPE_supported_versions) + || !WPACKET_start_sub_packet_u16(&hrrpkt) + || !WPACKET_put_bytes_u16(&hrrpkt, s->version) + || !WPACKET_close(&hrrpkt)) { + WPACKET_cleanup(&hrrpkt); + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE, + ERR_R_INTERNAL_ERROR); + return 0; + } + if (key_share) { + if (!WPACKET_put_bytes_u16(&hrrpkt, TLSEXT_TYPE_key_share) + || !WPACKET_start_sub_packet_u16(&hrrpkt) + || !WPACKET_put_bytes_u16(&hrrpkt, s->s3->group_id) + || !WPACKET_close(&hrrpkt)) { + WPACKET_cleanup(&hrrpkt); + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE, + ERR_R_INTERNAL_ERROR); + return 0; + } + } + if (!WPACKET_put_bytes_u16(&hrrpkt, TLSEXT_TYPE_cookie) + || !WPACKET_start_sub_packet_u16(&hrrpkt) + || !WPACKET_sub_memcpy_u16(&hrrpkt, data, rawlen) + || !WPACKET_close(&hrrpkt) /* cookie extension */ + || !WPACKET_close(&hrrpkt) /* extension block */ + || !WPACKET_close(&hrrpkt) /* message */ + || !WPACKET_get_total_written(&hrrpkt, &hrrlen) + || !WPACKET_finish(&hrrpkt)) { + WPACKET_cleanup(&hrrpkt); + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE, + ERR_R_INTERNAL_ERROR); + return 0; + } + + /* Reconstruct the transcript hash */ + if (!create_synthetic_message_hash(s, PACKET_data(&chhash), + PACKET_remaining(&chhash), hrr, + hrrlen)) { + /* SSLfatal() already called */ + return 0; + } + + /* Act as if this ClientHello came after a HelloRetryRequest */ + s->hello_retry_request = 1; + + s->ext.cookieok = 1; +#endif + + return 1; +} + +#ifndef OPENSSL_NO_EC +int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + PACKET supported_groups_list; + + /* Each group is 2 bytes and we must have at least 1. */ + if (!PACKET_as_length_prefixed_2(pkt, &supported_groups_list) + || PACKET_remaining(&supported_groups_list) == 0 + || (PACKET_remaining(&supported_groups_list) % 2) != 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS, SSL_R_BAD_EXTENSION); + return 0; + } + + if (!s->hit || SSL_IS_TLS13(s)) { + OPENSSL_free(s->session->ext.supportedgroups); + s->session->ext.supportedgroups = NULL; + s->session->ext.supportedgroups_len = 0; + if (!tls1_save_u16(&supported_groups_list, + &s->session->ext.supportedgroups, + &s->session->ext.supportedgroups_len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS, + ERR_R_INTERNAL_ERROR); + return 0; + } + } + + return 1; +} +#endif + +int tls_parse_ctos_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ + /* The extension must always be empty */ + if (PACKET_remaining(pkt) != 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_EMS, SSL_R_BAD_EXTENSION); + return 0; + } + + s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS; + + return 1; +} + + +int tls_parse_ctos_early_data(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (PACKET_remaining(pkt) != 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_EARLY_DATA, SSL_R_BAD_EXTENSION); + return 0; + } + + if (s->hello_retry_request != SSL_HRR_NONE) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PARSE_CTOS_EARLY_DATA, SSL_R_BAD_EXTENSION); + return 0; + } + + return 1; +} + +static SSL_TICKET_STATUS tls_get_stateful_ticket(SSL *s, PACKET *tick, + SSL_SESSION **sess) +{ + SSL_SESSION *tmpsess = NULL; + + s->ext.ticket_expected = 1; + + switch (PACKET_remaining(tick)) { + case 0: + return SSL_TICKET_EMPTY; + + case SSL_MAX_SSL_SESSION_ID_LENGTH: + break; + + default: + return SSL_TICKET_NO_DECRYPT; + } + + tmpsess = lookup_sess_in_cache(s, PACKET_data(tick), + SSL_MAX_SSL_SESSION_ID_LENGTH); + + if (tmpsess == NULL) + return SSL_TICKET_NO_DECRYPT; + + *sess = tmpsess; + return SSL_TICKET_SUCCESS; +} + +int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx) +{ + PACKET identities, binders, binder; + size_t binderoffset, hashsize; + SSL_SESSION *sess = NULL; + unsigned int id, i, ext = 0; + const EVP_MD *md = NULL; + + /* + * If we have no PSK kex mode that we recognise then we can't resume so + * ignore this extension + */ + if ((s->ext.psk_kex_mode + & (TLSEXT_KEX_MODE_FLAG_KE | TLSEXT_KEX_MODE_FLAG_KE_DHE)) == 0) + return 1; + + if (!PACKET_get_length_prefixed_2(pkt, &identities)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_PSK, SSL_R_BAD_EXTENSION); + return 0; + } + + s->ext.ticket_expected = 0; + for (id = 0; PACKET_remaining(&identities) != 0; id++) { + PACKET identity; + unsigned long ticket_agel; + size_t idlen; + + if (!PACKET_get_length_prefixed_2(&identities, &identity) + || !PACKET_get_net_4(&identities, &ticket_agel)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PARSE_CTOS_PSK, SSL_R_BAD_EXTENSION); + return 0; + } + + idlen = PACKET_remaining(&identity); + if (s->psk_find_session_cb != NULL + && !s->psk_find_session_cb(s, PACKET_data(&identity), idlen, + &sess)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PARSE_CTOS_PSK, SSL_R_BAD_EXTENSION); + return 0; + } + +#ifndef OPENSSL_NO_PSK + if(sess == NULL + && s->psk_server_callback != NULL + && idlen <= PSK_MAX_IDENTITY_LEN) { + char *pskid = NULL; + unsigned char pskdata[PSK_MAX_PSK_LEN]; + unsigned int pskdatalen; + + if (!PACKET_strndup(&identity, &pskid)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK, + ERR_R_INTERNAL_ERROR); + return 0; + } + pskdatalen = s->psk_server_callback(s, pskid, pskdata, + sizeof(pskdata)); + OPENSSL_free(pskid); + if (pskdatalen > PSK_MAX_PSK_LEN) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK, + ERR_R_INTERNAL_ERROR); + return 0; + } else if (pskdatalen > 0) { + const SSL_CIPHER *cipher; + const unsigned char tls13_aes128gcmsha256_id[] = { 0x13, 0x01 }; + + /* + * We found a PSK using an old style callback. We don't know + * the digest so we default to SHA256 as per the TLSv1.3 spec + */ + cipher = SSL_CIPHER_find(s, tls13_aes128gcmsha256_id); + if (cipher == NULL) { + OPENSSL_cleanse(pskdata, pskdatalen); + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK, + ERR_R_INTERNAL_ERROR); + return 0; + } + + sess = SSL_SESSION_new(); + if (sess == NULL + || !SSL_SESSION_set1_master_key(sess, pskdata, + pskdatalen) + || !SSL_SESSION_set_cipher(sess, cipher) + || !SSL_SESSION_set_protocol_version(sess, + TLS1_3_VERSION)) { + OPENSSL_cleanse(pskdata, pskdatalen); + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK, + ERR_R_INTERNAL_ERROR); + goto err; + } + OPENSSL_cleanse(pskdata, pskdatalen); + } + } +#endif /* OPENSSL_NO_PSK */ + + if (sess != NULL) { + /* We found a PSK */ + SSL_SESSION *sesstmp = ssl_session_dup(sess, 0); + + if (sesstmp == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PARSE_CTOS_PSK, ERR_R_INTERNAL_ERROR); + return 0; + } + SSL_SESSION_free(sess); + sess = sesstmp; + + /* + * We've just been told to use this session for this context so + * make sure the sid_ctx matches up. + */ + memcpy(sess->sid_ctx, s->sid_ctx, s->sid_ctx_length); + sess->sid_ctx_length = s->sid_ctx_length; + ext = 1; + if (id == 0) + s->ext.early_data_ok = 1; + s->ext.ticket_expected = 1; + } else { + uint32_t ticket_age = 0, now, agesec, agems; + int ret; + + /* + * If we are using anti-replay protection then we behave as if + * SSL_OP_NO_TICKET is set - we are caching tickets anyway so there + * is no point in using full stateless tickets. + */ + if ((s->options & SSL_OP_NO_TICKET) != 0 + || (s->max_early_data > 0 + && (s->options & SSL_OP_NO_ANTI_REPLAY) == 0)) + ret = tls_get_stateful_ticket(s, &identity, &sess); + else + ret = tls_decrypt_ticket(s, PACKET_data(&identity), + PACKET_remaining(&identity), NULL, 0, + &sess); + + if (ret == SSL_TICKET_EMPTY) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK, + SSL_R_BAD_EXTENSION); + return 0; + } + + if (ret == SSL_TICKET_FATAL_ERR_MALLOC + || ret == SSL_TICKET_FATAL_ERR_OTHER) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PARSE_CTOS_PSK, ERR_R_INTERNAL_ERROR); + return 0; + } + if (ret == SSL_TICKET_NONE || ret == SSL_TICKET_NO_DECRYPT) + continue; + + /* Check for replay */ + if (s->max_early_data > 0 + && (s->options & SSL_OP_NO_ANTI_REPLAY) == 0 + && !SSL_CTX_remove_session(s->session_ctx, sess)) { + SSL_SESSION_free(sess); + sess = NULL; + continue; + } + + ticket_age = (uint32_t)ticket_agel; + now = (uint32_t)time(NULL); + agesec = now - (uint32_t)sess->time; + agems = agesec * (uint32_t)1000; + ticket_age -= sess->ext.tick_age_add; + + /* + * For simplicity we do our age calculations in seconds. If the + * client does it in ms then it could appear that their ticket age + * is longer than ours (our ticket age calculation should always be + * slightly longer than the client's due to the network latency). + * Therefore we add 1000ms to our age calculation to adjust for + * rounding errors. + */ + if (id == 0 + && sess->timeout >= (long)agesec + && agems / (uint32_t)1000 == agesec + && ticket_age <= agems + 1000 + && ticket_age + TICKET_AGE_ALLOWANCE >= agems + 1000) { + /* + * Ticket age is within tolerance and not expired. We allow it + * for early data + */ + s->ext.early_data_ok = 1; + } + } + + md = ssl_md(sess->cipher->algorithm2); + if (md != ssl_md(s->s3->tmp.new_cipher->algorithm2)) { + /* The ciphersuite is not compatible with this session. */ + SSL_SESSION_free(sess); + sess = NULL; + s->ext.early_data_ok = 0; + s->ext.ticket_expected = 0; + continue; + } + break; + } + + if (sess == NULL) + return 1; + + binderoffset = PACKET_data(pkt) - (const unsigned char *)s->init_buf->data; + hashsize = EVP_MD_size(md); + + if (!PACKET_get_length_prefixed_2(pkt, &binders)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK, + SSL_R_BAD_EXTENSION); + goto err; + } + + for (i = 0; i <= id; i++) { + if (!PACKET_get_length_prefixed_1(&binders, &binder)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK, + SSL_R_BAD_EXTENSION); + goto err; + } + } + + if (PACKET_remaining(&binder) != hashsize) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK, + SSL_R_BAD_EXTENSION); + goto err; + } + if (tls_psk_do_binder(s, md, (const unsigned char *)s->init_buf->data, + binderoffset, PACKET_data(&binder), NULL, sess, 0, + ext) != 1) { + /* SSLfatal() already called */ + goto err; + } + + sess->ext.tick_identity = id; + + SSL_SESSION_free(s->session); + s->session = sess; + return 1; +err: + SSL_SESSION_free(sess); + return 0; +} + +int tls_parse_ctos_post_handshake_auth(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (PACKET_remaining(pkt) != 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_POST_HANDSHAKE_AUTH, + SSL_R_POST_HANDSHAKE_AUTH_ENCODING_ERR); + return 0; + } + + s->post_handshake_auth = SSL_PHA_EXT_RECEIVED; + + return 1; +} + +/* + * Add the server's renegotiation binding + */ +EXT_RETURN tls_construct_stoc_renegotiate(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + if (!s->s3->send_connection_binding) + return EXT_RETURN_NOT_SENT; + + /* Still add this even if SSL_OP_NO_RENEGOTIATION is set */ + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_renegotiate) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_start_sub_packet_u8(pkt) + || !WPACKET_memcpy(pkt, s->s3->previous_client_finished, + s->s3->previous_client_finished_len) + || !WPACKET_memcpy(pkt, s->s3->previous_server_finished, + s->s3->previous_server_finished_len) + || !WPACKET_close(pkt) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +EXT_RETURN tls_construct_stoc_server_name(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + if (s->hit || s->servername_done != 1 + || s->ext.hostname == NULL) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_server_name) + || !WPACKET_put_bytes_u16(pkt, 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_SERVER_NAME, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +/* Add/include the server's max fragment len extension into ServerHello */ +EXT_RETURN tls_construct_stoc_maxfragmentlen(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + if (!USE_MAX_FRAGMENT_LENGTH_EXT(s->session)) + return EXT_RETURN_NOT_SENT; + + /*- + * 4 bytes for this extension type and extension length + * 1 byte for the Max Fragment Length code value. + */ + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_max_fragment_length) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_put_bytes_u8(pkt, s->session->ext.max_fragment_len_mode) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_MAXFRAGMENTLEN, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +#ifndef OPENSSL_NO_EC +EXT_RETURN tls_construct_stoc_ec_pt_formats(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth; + int using_ecc = ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA)) + && (s->session->ext.ecpointformats != NULL); + const unsigned char *plist; + size_t plistlen; + + if (!using_ecc) + return EXT_RETURN_NOT_SENT; + + tls1_get_formatlist(s, &plist, &plistlen); + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_ec_point_formats) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_sub_memcpy_u8(pkt, plist, plistlen) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} +#endif + +#ifndef OPENSSL_NO_EC +EXT_RETURN tls_construct_stoc_supported_groups(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + const uint16_t *groups; + size_t numgroups, i, first = 1; + + /* s->s3->group_id is non zero if we accepted a key_share */ + if (s->s3->group_id == 0) + return EXT_RETURN_NOT_SENT; + + /* Get our list of supported groups */ + tls1_get_supported_groups(s, &groups, &numgroups); + if (numgroups == 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + /* Copy group ID if supported */ + for (i = 0; i < numgroups; i++) { + uint16_t group = groups[i]; + + if (tls_curve_allowed(s, group, SSL_SECOP_CURVE_SUPPORTED)) { + if (first) { + /* + * Check if the client is already using our preferred group. If + * so we don't need to add this extension + */ + if (s->s3->group_id == group) + return EXT_RETURN_NOT_SENT; + + /* Add extension header */ + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_groups) + /* Sub-packet for supported_groups extension */ + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_start_sub_packet_u16(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + first = 0; + } + if (!WPACKET_put_bytes_u16(pkt, group)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + } + } + + if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} +#endif + +EXT_RETURN tls_construct_stoc_session_ticket(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + if (!s->ext.ticket_expected || !tls_use_ticket(s)) { + s->ext.ticket_expected = 0; + return EXT_RETURN_NOT_SENT; + } + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_session_ticket) + || !WPACKET_put_bytes_u16(pkt, 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_SESSION_TICKET, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +#ifndef OPENSSL_NO_OCSP +EXT_RETURN tls_construct_stoc_status_request(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + if (!s->ext.status_expected) + return EXT_RETURN_NOT_SENT; + + if (SSL_IS_TLS13(s) && chainidx != 0) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_status_request) + || !WPACKET_start_sub_packet_u16(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + /* + * In TLSv1.3 we include the certificate status itself. In <= TLSv1.2 we + * send back an empty extension, with the certificate status appearing as a + * separate message + */ + if (SSL_IS_TLS13(s) && !tls_construct_cert_status_body(s, pkt)) { + /* SSLfatal() already called */ + return EXT_RETURN_FAIL; + } + if (!WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} +#endif + +#ifndef OPENSSL_NO_NEXTPROTONEG +EXT_RETURN tls_construct_stoc_next_proto_neg(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + const unsigned char *npa; + unsigned int npalen; + int ret; + int npn_seen = s->s3->npn_seen; + + s->s3->npn_seen = 0; + if (!npn_seen || s->ctx->ext.npn_advertised_cb == NULL) + return EXT_RETURN_NOT_SENT; + + ret = s->ctx->ext.npn_advertised_cb(s, &npa, &npalen, + s->ctx->ext.npn_advertised_cb_arg); + if (ret == SSL_TLSEXT_ERR_OK) { + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_next_proto_neg) + || !WPACKET_sub_memcpy_u16(pkt, npa, npalen)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_NEXT_PROTO_NEG, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + s->s3->npn_seen = 1; + } + + return EXT_RETURN_SENT; +} +#endif + +EXT_RETURN tls_construct_stoc_alpn(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (s->s3->alpn_selected == NULL) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, + TLSEXT_TYPE_application_layer_protocol_negotiation) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_sub_memcpy_u8(pkt, s->s3->alpn_selected, + s->s3->alpn_selected_len) + || !WPACKET_close(pkt) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_ALPN, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +#ifndef OPENSSL_NO_SRTP +EXT_RETURN tls_construct_stoc_use_srtp(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + if (s->srtp_profile == NULL) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_use_srtp) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_put_bytes_u16(pkt, 2) + || !WPACKET_put_bytes_u16(pkt, s->srtp_profile->id) + || !WPACKET_put_bytes_u8(pkt, 0) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_USE_SRTP, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} +#endif + +EXT_RETURN tls_construct_stoc_etm(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (!s->ext.use_etm) + return EXT_RETURN_NOT_SENT; + + /* + * Don't use encrypt_then_mac if AEAD or RC4 might want to disable + * for other cases too. + */ + if (s->s3->tmp.new_cipher->algorithm_mac == SSL_AEAD + || s->s3->tmp.new_cipher->algorithm_enc == SSL_RC4 + || s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT + || s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT12) { + s->ext.use_etm = 0; + return EXT_RETURN_NOT_SENT; + } + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_encrypt_then_mac) + || !WPACKET_put_bytes_u16(pkt, 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_ETM, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +EXT_RETURN tls_construct_stoc_ems(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if ((s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) == 0) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret) + || !WPACKET_put_bytes_u16(pkt, 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_EMS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +EXT_RETURN tls_construct_stoc_supported_versions(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + if (!ossl_assert(SSL_IS_TLS13(s))) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_versions) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_put_bytes_u16(pkt, s->version) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ +#ifndef OPENSSL_NO_TLS1_3 + unsigned char *encodedPoint; + size_t encoded_pt_len = 0; + EVP_PKEY *ckey = s->s3->peer_tmp, *skey = NULL; + + if (s->hello_retry_request == SSL_HRR_PENDING) { + if (ckey != NULL) { + /* Original key_share was acceptable so don't ask for another one */ + return EXT_RETURN_NOT_SENT; + } + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_put_bytes_u16(pkt, s->s3->group_id) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; + } + + if (ckey == NULL) { + /* No key_share received from client - must be resuming */ + if (!s->hit || !tls13_generate_handshake_secret(s, NULL, 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + return EXT_RETURN_NOT_SENT; + } + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_put_bytes_u16(pkt, s->s3->group_id)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + skey = ssl_generate_pkey(ckey); + if (skey == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, + ERR_R_MALLOC_FAILURE); + return EXT_RETURN_FAIL; + } + + /* Generate encoding of server key */ + encoded_pt_len = EVP_PKEY_get1_tls_encodedpoint(skey, &encodedPoint); + if (encoded_pt_len == 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, + ERR_R_EC_LIB); + EVP_PKEY_free(skey); + return EXT_RETURN_FAIL; + } + + if (!WPACKET_sub_memcpy_u16(pkt, encodedPoint, encoded_pt_len) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, + ERR_R_INTERNAL_ERROR); + EVP_PKEY_free(skey); + OPENSSL_free(encodedPoint); + return EXT_RETURN_FAIL; + } + OPENSSL_free(encodedPoint); + + /* This causes the crypto state to be updated based on the derived keys */ + s->s3->tmp.pkey = skey; + if (ssl_derive(s, skey, ckey, 1) == 0) { + /* SSLfatal() already called */ + return EXT_RETURN_FAIL; + } + return EXT_RETURN_SENT; +#else + return EXT_RETURN_FAIL; +#endif +} + +EXT_RETURN tls_construct_stoc_cookie(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ +#ifndef OPENSSL_NO_TLS1_3 + unsigned char *hashval1, *hashval2, *appcookie1, *appcookie2, *cookie; + unsigned char *hmac, *hmac2; + size_t startlen, ciphlen, totcookielen, hashlen, hmaclen, appcookielen; + EVP_MD_CTX *hctx; + EVP_PKEY *pkey; + int ret = EXT_RETURN_FAIL; + + if ((s->s3->flags & TLS1_FLAGS_STATELESS) == 0) + return EXT_RETURN_NOT_SENT; + + if (s->ctx->gen_stateless_cookie_cb == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE, + SSL_R_NO_COOKIE_CALLBACK_SET); + return EXT_RETURN_FAIL; + } + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_cookie) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_get_total_written(pkt, &startlen) + || !WPACKET_reserve_bytes(pkt, MAX_COOKIE_SIZE, &cookie) + || !WPACKET_put_bytes_u16(pkt, COOKIE_STATE_FORMAT_VERSION) + || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION) + || !WPACKET_put_bytes_u16(pkt, s->s3->group_id) + || !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, pkt, + &ciphlen) + /* Is there a key_share extension present in this HRR? */ + || !WPACKET_put_bytes_u8(pkt, s->s3->peer_tmp == NULL) + || !WPACKET_put_bytes_u32(pkt, (unsigned int)time(NULL)) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_reserve_bytes(pkt, EVP_MAX_MD_SIZE, &hashval1)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + /* + * Get the hash of the initial ClientHello. ssl_handshake_hash() operates + * on raw buffers, so we first reserve sufficient bytes (above) and then + * subsequently allocate them (below) + */ + if (!ssl3_digest_cached_records(s, 0) + || !ssl_handshake_hash(s, hashval1, EVP_MAX_MD_SIZE, &hashlen)) { + /* SSLfatal() already called */ + return EXT_RETURN_FAIL; + } + + if (!WPACKET_allocate_bytes(pkt, hashlen, &hashval2) + || !ossl_assert(hashval1 == hashval2) + || !WPACKET_close(pkt) + || !WPACKET_start_sub_packet_u8(pkt) + || !WPACKET_reserve_bytes(pkt, SSL_COOKIE_LENGTH, &appcookie1)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + /* Generate the application cookie */ + if (s->ctx->gen_stateless_cookie_cb(s, appcookie1, &appcookielen) == 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE, + SSL_R_COOKIE_GEN_CALLBACK_FAILURE); + return EXT_RETURN_FAIL; + } + + if (!WPACKET_allocate_bytes(pkt, appcookielen, &appcookie2) + || !ossl_assert(appcookie1 == appcookie2) + || !WPACKET_close(pkt) + || !WPACKET_get_total_written(pkt, &totcookielen) + || !WPACKET_reserve_bytes(pkt, SHA256_DIGEST_LENGTH, &hmac)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + hmaclen = SHA256_DIGEST_LENGTH; + + totcookielen -= startlen; + if (!ossl_assert(totcookielen <= MAX_COOKIE_SIZE - SHA256_DIGEST_LENGTH)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + /* HMAC the cookie */ + hctx = EVP_MD_CTX_create(); + pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, + s->session_ctx->ext.cookie_hmac_key, + sizeof(s->session_ctx->ext + .cookie_hmac_key)); + if (hctx == NULL || pkey == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE, + ERR_R_MALLOC_FAILURE); + goto err; + } + + if (EVP_DigestSignInit(hctx, NULL, EVP_sha256(), NULL, pkey) <= 0 + || EVP_DigestSign(hctx, hmac, &hmaclen, cookie, + totcookielen) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + if (!ossl_assert(totcookielen + hmaclen <= MAX_COOKIE_SIZE)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + if (!WPACKET_allocate_bytes(pkt, hmaclen, &hmac2) + || !ossl_assert(hmac == hmac2) + || !ossl_assert(cookie == hmac - totcookielen) + || !WPACKET_close(pkt) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + ret = EXT_RETURN_SENT; + + err: + EVP_MD_CTX_free(hctx); + EVP_PKEY_free(pkey); + return ret; +#else + return EXT_RETURN_FAIL; +#endif +} + +EXT_RETURN tls_construct_stoc_cryptopro_bug(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + const unsigned char cryptopro_ext[36] = { + 0xfd, 0xe8, /* 65000 */ + 0x00, 0x20, /* 32 bytes length */ + 0x30, 0x1e, 0x30, 0x08, 0x06, 0x06, 0x2a, 0x85, + 0x03, 0x02, 0x02, 0x09, 0x30, 0x08, 0x06, 0x06, + 0x2a, 0x85, 0x03, 0x02, 0x02, 0x16, 0x30, 0x08, + 0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x17 + }; + + if (((s->s3->tmp.new_cipher->id & 0xFFFF) != 0x80 + && (s->s3->tmp.new_cipher->id & 0xFFFF) != 0x81) + || (SSL_get_options(s) & SSL_OP_CRYPTOPRO_TLSEXT_BUG) == 0) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_memcpy(pkt, cryptopro_ext, sizeof(cryptopro_ext))) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_CRYPTOPRO_BUG, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +EXT_RETURN tls_construct_stoc_early_data(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx) +{ + if (context == SSL_EXT_TLS1_3_NEW_SESSION_TICKET) { + if (s->max_early_data == 0) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_put_bytes_u32(pkt, s->max_early_data) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; + } + + if (s->ext.early_data != SSL_EARLY_DATA_ACCEPTED) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} + +EXT_RETURN tls_construct_stoc_psk(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) +{ + if (!s->hit) + return EXT_RETURN_NOT_SENT; + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_put_bytes_u16(pkt, s->session->ext.tick_identity) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_STOC_PSK, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + return EXT_RETURN_SENT; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem.c b/trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem.c new file mode 100644 index 000000000..e3c5ec003 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem.c @@ -0,0 +1,972 @@ +/* + * Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include +#include "../ssl_locl.h" +#include "statem_locl.h" +#include + +/* + * This file implements the SSL/TLS/DTLS state machines. + * + * There are two primary state machines: + * + * 1) Message flow state machine + * 2) Handshake state machine + * + * The Message flow state machine controls the reading and sending of messages + * including handling of non-blocking IO events, flushing of the underlying + * write BIO, handling unexpected messages, etc. It is itself broken into two + * separate sub-state machines which control reading and writing respectively. + * + * The Handshake state machine keeps track of the current SSL/TLS handshake + * state. Transitions of the handshake state are the result of events that + * occur within the Message flow state machine. + * + * Overall it looks like this: + * + * --------------------------------------------- ------------------- + * | | | | + * | Message flow state machine | | | + * | | | | + * | -------------------- -------------------- | Transition | Handshake state | + * | | MSG_FLOW_READING | | MSG_FLOW_WRITING | | Event | machine | + * | | sub-state | | sub-state | |----------->| | + * | | machine for | | machine for | | | | + * | | reading messages | | writing messages | | | | + * | -------------------- -------------------- | | | + * | | | | + * --------------------------------------------- ------------------- + * + */ + +/* Sub state machine return values */ +typedef enum { + /* Something bad happened or NBIO */ + SUB_STATE_ERROR, + /* Sub state finished go to the next sub state */ + SUB_STATE_FINISHED, + /* Sub state finished and handshake was completed */ + SUB_STATE_END_HANDSHAKE +} SUB_STATE_RETURN; + +static int state_machine(SSL *s, int server); +static void init_read_state_machine(SSL *s); +static SUB_STATE_RETURN read_state_machine(SSL *s); +static void init_write_state_machine(SSL *s); +static SUB_STATE_RETURN write_state_machine(SSL *s); + +OSSL_HANDSHAKE_STATE SSL_get_state(const SSL *ssl) +{ + return ssl->statem.hand_state; +} + +int SSL_in_init(const SSL *s) +{ + return s->statem.in_init; +} + +int SSL_is_init_finished(const SSL *s) +{ + return !(s->statem.in_init) && (s->statem.hand_state == TLS_ST_OK); +} + +int SSL_in_before(const SSL *s) +{ + /* + * Historically being "in before" meant before anything had happened. In the + * current code though we remain in the "before" state for a while after we + * have started the handshake process (e.g. as a server waiting for the + * first message to arrive). There "in before" is taken to mean "in before" + * and not started any handshake process yet. + */ + return (s->statem.hand_state == TLS_ST_BEFORE) + && (s->statem.state == MSG_FLOW_UNINITED); +} + +/* + * Clear the state machine state and reset back to MSG_FLOW_UNINITED + */ +void ossl_statem_clear(SSL *s) +{ + s->statem.state = MSG_FLOW_UNINITED; + s->statem.hand_state = TLS_ST_BEFORE; + s->statem.in_init = 1; + s->statem.no_cert_verify = 0; +} + +/* + * Set the state machine up ready for a renegotiation handshake + */ +void ossl_statem_set_renegotiate(SSL *s) +{ + s->statem.in_init = 1; + s->statem.request_state = TLS_ST_SW_HELLO_REQ; +} + +/* + * Put the state machine into an error state and send an alert if appropriate. + * This is a permanent error for the current connection. + */ +void ossl_statem_fatal(SSL *s, int al, int func, int reason, const char *file, + int line) +{ + ERR_put_error(ERR_LIB_SSL, func, reason, file, line); + /* We shouldn't call SSLfatal() twice. Once is enough */ + if (s->statem.in_init && s->statem.state == MSG_FLOW_ERROR) + return; + s->statem.in_init = 1; + s->statem.state = MSG_FLOW_ERROR; + if (al != SSL_AD_NO_ALERT + && s->statem.enc_write_state != ENC_WRITE_STATE_INVALID) + ssl3_send_alert(s, SSL3_AL_FATAL, al); +} + +/* + * This macro should only be called if we are already expecting to be in + * a fatal error state. We verify that we are, and set it if not (this would + * indicate a bug). + */ +#define check_fatal(s, f) \ + do { \ + if (!ossl_assert((s)->statem.in_init \ + && (s)->statem.state == MSG_FLOW_ERROR)) \ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, (f), \ + SSL_R_MISSING_FATAL); \ + } while (0) + +/* + * Discover whether the current connection is in the error state. + * + * Valid return values are: + * 1: Yes + * 0: No + */ +int ossl_statem_in_error(const SSL *s) +{ + if (s->statem.state == MSG_FLOW_ERROR) + return 1; + + return 0; +} + +void ossl_statem_set_in_init(SSL *s, int init) +{ + s->statem.in_init = init; +} + +int ossl_statem_get_in_handshake(SSL *s) +{ + return s->statem.in_handshake; +} + +void ossl_statem_set_in_handshake(SSL *s, int inhand) +{ + if (inhand) + s->statem.in_handshake++; + else + s->statem.in_handshake--; +} + +/* Are we in a sensible state to skip over unreadable early data? */ +int ossl_statem_skip_early_data(SSL *s) +{ + if (s->ext.early_data != SSL_EARLY_DATA_REJECTED) + return 0; + + if (!s->server + || s->statem.hand_state != TLS_ST_EARLY_DATA + || s->hello_retry_request == SSL_HRR_COMPLETE) + return 0; + + return 1; +} + +/* + * Called when we are in SSL_read*(), SSL_write*(), or SSL_accept() + * /SSL_connect()/SSL_do_handshake(). Used to test whether we are in an early + * data state and whether we should attempt to move the handshake on if so. + * |sending| is 1 if we are attempting to send data (SSL_write*()), 0 if we are + * attempting to read data (SSL_read*()), or -1 if we are in SSL_do_handshake() + * or similar. + */ +void ossl_statem_check_finish_init(SSL *s, int sending) +{ + if (sending == -1) { + if (s->statem.hand_state == TLS_ST_PENDING_EARLY_DATA_END + || s->statem.hand_state == TLS_ST_EARLY_DATA) { + ossl_statem_set_in_init(s, 1); + if (s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) { + /* + * SSL_connect() or SSL_do_handshake() has been called directly. + * We don't allow any more writing of early data. + */ + s->early_data_state = SSL_EARLY_DATA_FINISHED_WRITING; + } + } + } else if (!s->server) { + if ((sending && (s->statem.hand_state == TLS_ST_PENDING_EARLY_DATA_END + || s->statem.hand_state == TLS_ST_EARLY_DATA) + && s->early_data_state != SSL_EARLY_DATA_WRITING) + || (!sending && s->statem.hand_state == TLS_ST_EARLY_DATA)) { + ossl_statem_set_in_init(s, 1); + /* + * SSL_write() has been called directly. We don't allow any more + * writing of early data. + */ + if (sending && s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) + s->early_data_state = SSL_EARLY_DATA_FINISHED_WRITING; + } + } else { + if (s->early_data_state == SSL_EARLY_DATA_FINISHED_READING + && s->statem.hand_state == TLS_ST_EARLY_DATA) + ossl_statem_set_in_init(s, 1); + } +} + +void ossl_statem_set_hello_verify_done(SSL *s) +{ + s->statem.state = MSG_FLOW_UNINITED; + s->statem.in_init = 1; + /* + * This will get reset (briefly) back to TLS_ST_BEFORE when we enter + * state_machine() because |state| is MSG_FLOW_UNINITED, but until then any + * calls to SSL_in_before() will return false. Also calls to + * SSL_state_string() and SSL_state_string_long() will return something + * sensible. + */ + s->statem.hand_state = TLS_ST_SR_CLNT_HELLO; +} + +int ossl_statem_connect(SSL *s) +{ + return state_machine(s, 0); +} + +int ossl_statem_accept(SSL *s) +{ + return state_machine(s, 1); +} + +typedef void (*info_cb) (const SSL *, int, int); + +static info_cb get_callback(SSL *s) +{ + if (s->info_callback != NULL) + return s->info_callback; + else if (s->ctx->info_callback != NULL) + return s->ctx->info_callback; + + return NULL; +} + +/* + * The main message flow state machine. We start in the MSG_FLOW_UNINITED or + * MSG_FLOW_FINISHED state and finish in MSG_FLOW_FINISHED. Valid states and + * transitions are as follows: + * + * MSG_FLOW_UNINITED MSG_FLOW_FINISHED + * | | + * +-----------------------+ + * v + * MSG_FLOW_WRITING <---> MSG_FLOW_READING + * | + * V + * MSG_FLOW_FINISHED + * | + * V + * [SUCCESS] + * + * We may exit at any point due to an error or NBIO event. If an NBIO event + * occurs then we restart at the point we left off when we are recalled. + * MSG_FLOW_WRITING and MSG_FLOW_READING have sub-state machines associated with them. + * + * In addition to the above there is also the MSG_FLOW_ERROR state. We can move + * into that state at any point in the event that an irrecoverable error occurs. + * + * Valid return values are: + * 1: Success + * <=0: NBIO or error + */ +static int state_machine(SSL *s, int server) +{ + BUF_MEM *buf = NULL; + void (*cb) (const SSL *ssl, int type, int val) = NULL; + OSSL_STATEM *st = &s->statem; + int ret = -1; + int ssret; + + if (st->state == MSG_FLOW_ERROR) { + /* Shouldn't have been called if we're already in the error state */ + return -1; + } + + ERR_clear_error(); + clear_sys_error(); + + cb = get_callback(s); + + st->in_handshake++; + if (!SSL_in_init(s) || SSL_in_before(s)) { + /* + * If we are stateless then we already called SSL_clear() - don't do + * it again and clear the STATELESS flag itself. + */ + if ((s->s3->flags & TLS1_FLAGS_STATELESS) == 0 && !SSL_clear(s)) + return -1; + } +#ifndef OPENSSL_NO_SCTP + if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s))) { + /* + * Notify SCTP BIO socket to enter handshake mode and prevent stream + * identifier other than 0. + */ + BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE, + st->in_handshake, NULL); + } +#endif + + /* Initialise state machine */ + if (st->state == MSG_FLOW_UNINITED + || st->state == MSG_FLOW_FINISHED) { + if (st->state == MSG_FLOW_UNINITED) { + st->hand_state = TLS_ST_BEFORE; + st->request_state = TLS_ST_BEFORE; + } + + s->server = server; + if (cb != NULL) { + if (SSL_IS_FIRST_HANDSHAKE(s) || !SSL_IS_TLS13(s)) + cb(s, SSL_CB_HANDSHAKE_START, 1); + } + + /* + * Fatal errors in this block don't send an alert because we have + * failed to even initialise properly. Sending an alert is probably + * doomed to failure. + */ + + if (SSL_IS_DTLS(s)) { + if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00) && + (server || (s->version & 0xff00) != (DTLS1_BAD_VER & 0xff00))) { + SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE, + ERR_R_INTERNAL_ERROR); + goto end; + } + } else { + if ((s->version >> 8) != SSL3_VERSION_MAJOR) { + SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE, + ERR_R_INTERNAL_ERROR); + goto end; + } + } + + if (!ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) { + SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE, + ERR_R_INTERNAL_ERROR); + goto end; + } + + if (s->init_buf == NULL) { + if ((buf = BUF_MEM_new()) == NULL) { + SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE, + ERR_R_INTERNAL_ERROR); + goto end; + } + if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) { + SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE, + ERR_R_INTERNAL_ERROR); + goto end; + } + s->init_buf = buf; + buf = NULL; + } + + if (!ssl3_setup_buffers(s)) { + SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE, + ERR_R_INTERNAL_ERROR); + goto end; + } + s->init_num = 0; + + /* + * Should have been reset by tls_process_finished, too. + */ + s->s3->change_cipher_spec = 0; + + /* + * Ok, we now need to push on a buffering BIO ...but not with + * SCTP + */ +#ifndef OPENSSL_NO_SCTP + if (!SSL_IS_DTLS(s) || !BIO_dgram_is_sctp(SSL_get_wbio(s))) +#endif + if (!ssl_init_wbio_buffer(s)) { + SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE, + ERR_R_INTERNAL_ERROR); + goto end; + } + + if ((SSL_in_before(s)) + || s->renegotiate) { + if (!tls_setup_handshake(s)) { + /* SSLfatal() already called */ + goto end; + } + + if (SSL_IS_FIRST_HANDSHAKE(s)) + st->read_state_first_init = 1; + } + + st->state = MSG_FLOW_WRITING; + init_write_state_machine(s); + } + + while (st->state != MSG_FLOW_FINISHED) { + if (st->state == MSG_FLOW_READING) { + ssret = read_state_machine(s); + if (ssret == SUB_STATE_FINISHED) { + st->state = MSG_FLOW_WRITING; + init_write_state_machine(s); + } else { + /* NBIO or error */ + goto end; + } + } else if (st->state == MSG_FLOW_WRITING) { + ssret = write_state_machine(s); + if (ssret == SUB_STATE_FINISHED) { + st->state = MSG_FLOW_READING; + init_read_state_machine(s); + } else if (ssret == SUB_STATE_END_HANDSHAKE) { + st->state = MSG_FLOW_FINISHED; + } else { + /* NBIO or error */ + goto end; + } + } else { + /* Error */ + check_fatal(s, SSL_F_STATE_MACHINE); + SSLerr(SSL_F_STATE_MACHINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + goto end; + } + } + + ret = 1; + + end: + st->in_handshake--; + +#ifndef OPENSSL_NO_SCTP + if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s))) { + /* + * Notify SCTP BIO socket to leave handshake mode and allow stream + * identifier other than 0. + */ + BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE, + st->in_handshake, NULL); + } +#endif + + BUF_MEM_free(buf); + if (cb != NULL) { + if (server) + cb(s, SSL_CB_ACCEPT_EXIT, ret); + else + cb(s, SSL_CB_CONNECT_EXIT, ret); + } + return ret; +} + +/* + * Initialise the MSG_FLOW_READING sub-state machine + */ +static void init_read_state_machine(SSL *s) +{ + OSSL_STATEM *st = &s->statem; + + st->read_state = READ_STATE_HEADER; +} + +static int grow_init_buf(SSL *s, size_t size) { + + size_t msg_offset = (char *)s->init_msg - s->init_buf->data; + + if (!BUF_MEM_grow_clean(s->init_buf, (int)size)) + return 0; + + if (size < msg_offset) + return 0; + + s->init_msg = s->init_buf->data + msg_offset; + + return 1; +} + +/* + * This function implements the sub-state machine when the message flow is in + * MSG_FLOW_READING. The valid sub-states and transitions are: + * + * READ_STATE_HEADER <--+<-------------+ + * | | | + * v | | + * READ_STATE_BODY -----+-->READ_STATE_POST_PROCESS + * | | + * +----------------------------+ + * v + * [SUB_STATE_FINISHED] + * + * READ_STATE_HEADER has the responsibility for reading in the message header + * and transitioning the state of the handshake state machine. + * + * READ_STATE_BODY reads in the rest of the message and then subsequently + * processes it. + * + * READ_STATE_POST_PROCESS is an optional step that may occur if some post + * processing activity performed on the message may block. + * + * Any of the above states could result in an NBIO event occurring in which case + * control returns to the calling application. When this function is recalled we + * will resume in the same state where we left off. + */ +static SUB_STATE_RETURN read_state_machine(SSL *s) +{ + OSSL_STATEM *st = &s->statem; + int ret, mt; + size_t len = 0; + int (*transition) (SSL *s, int mt); + PACKET pkt; + MSG_PROCESS_RETURN(*process_message) (SSL *s, PACKET *pkt); + WORK_STATE(*post_process_message) (SSL *s, WORK_STATE wst); + size_t (*max_message_size) (SSL *s); + void (*cb) (const SSL *ssl, int type, int val) = NULL; + + cb = get_callback(s); + + if (s->server) { + transition = ossl_statem_server_read_transition; + process_message = ossl_statem_server_process_message; + max_message_size = ossl_statem_server_max_message_size; + post_process_message = ossl_statem_server_post_process_message; + } else { + transition = ossl_statem_client_read_transition; + process_message = ossl_statem_client_process_message; + max_message_size = ossl_statem_client_max_message_size; + post_process_message = ossl_statem_client_post_process_message; + } + + if (st->read_state_first_init) { + s->first_packet = 1; + st->read_state_first_init = 0; + } + + while (1) { + switch (st->read_state) { + case READ_STATE_HEADER: + /* Get the state the peer wants to move to */ + if (SSL_IS_DTLS(s)) { + /* + * In DTLS we get the whole message in one go - header and body + */ + ret = dtls_get_message(s, &mt, &len); + } else { + ret = tls_get_message_header(s, &mt); + } + + if (ret == 0) { + /* Could be non-blocking IO */ + return SUB_STATE_ERROR; + } + + if (cb != NULL) { + /* Notify callback of an impending state change */ + if (s->server) + cb(s, SSL_CB_ACCEPT_LOOP, 1); + else + cb(s, SSL_CB_CONNECT_LOOP, 1); + } + /* + * Validate that we are allowed to move to the new state and move + * to that state if so + */ + if (!transition(s, mt)) + return SUB_STATE_ERROR; + + if (s->s3->tmp.message_size > max_message_size(s)) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_READ_STATE_MACHINE, + SSL_R_EXCESSIVE_MESSAGE_SIZE); + return SUB_STATE_ERROR; + } + + /* dtls_get_message already did this */ + if (!SSL_IS_DTLS(s) + && s->s3->tmp.message_size > 0 + && !grow_init_buf(s, s->s3->tmp.message_size + + SSL3_HM_HEADER_LENGTH)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE, + ERR_R_BUF_LIB); + return SUB_STATE_ERROR; + } + + st->read_state = READ_STATE_BODY; + /* Fall through */ + + case READ_STATE_BODY: + if (!SSL_IS_DTLS(s)) { + /* We already got this above for DTLS */ + ret = tls_get_message_body(s, &len); + if (ret == 0) { + /* Could be non-blocking IO */ + return SUB_STATE_ERROR; + } + } + + s->first_packet = 0; + if (!PACKET_buf_init(&pkt, s->init_msg, len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE, + ERR_R_INTERNAL_ERROR); + return SUB_STATE_ERROR; + } + ret = process_message(s, &pkt); + + /* Discard the packet data */ + s->init_num = 0; + + switch (ret) { + case MSG_PROCESS_ERROR: + check_fatal(s, SSL_F_READ_STATE_MACHINE); + return SUB_STATE_ERROR; + + case MSG_PROCESS_FINISHED_READING: + if (SSL_IS_DTLS(s)) { + dtls1_stop_timer(s); + } + return SUB_STATE_FINISHED; + + case MSG_PROCESS_CONTINUE_PROCESSING: + st->read_state = READ_STATE_POST_PROCESS; + st->read_state_work = WORK_MORE_A; + break; + + default: + st->read_state = READ_STATE_HEADER; + break; + } + break; + + case READ_STATE_POST_PROCESS: + st->read_state_work = post_process_message(s, st->read_state_work); + switch (st->read_state_work) { + case WORK_ERROR: + check_fatal(s, SSL_F_READ_STATE_MACHINE); + /* Fall through */ + case WORK_MORE_A: + case WORK_MORE_B: + case WORK_MORE_C: + return SUB_STATE_ERROR; + + case WORK_FINISHED_CONTINUE: + st->read_state = READ_STATE_HEADER; + break; + + case WORK_FINISHED_STOP: + if (SSL_IS_DTLS(s)) { + dtls1_stop_timer(s); + } + return SUB_STATE_FINISHED; + } + break; + + default: + /* Shouldn't happen */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE, + ERR_R_INTERNAL_ERROR); + return SUB_STATE_ERROR; + } + } +} + +/* + * Send a previously constructed message to the peer. + */ +static int statem_do_write(SSL *s) +{ + OSSL_STATEM *st = &s->statem; + + if (st->hand_state == TLS_ST_CW_CHANGE + || st->hand_state == TLS_ST_SW_CHANGE) { + if (SSL_IS_DTLS(s)) + return dtls1_do_write(s, SSL3_RT_CHANGE_CIPHER_SPEC); + else + return ssl3_do_write(s, SSL3_RT_CHANGE_CIPHER_SPEC); + } else { + return ssl_do_write(s); + } +} + +/* + * Initialise the MSG_FLOW_WRITING sub-state machine + */ +static void init_write_state_machine(SSL *s) +{ + OSSL_STATEM *st = &s->statem; + + st->write_state = WRITE_STATE_TRANSITION; +} + +/* + * This function implements the sub-state machine when the message flow is in + * MSG_FLOW_WRITING. The valid sub-states and transitions are: + * + * +-> WRITE_STATE_TRANSITION ------> [SUB_STATE_FINISHED] + * | | + * | v + * | WRITE_STATE_PRE_WORK -----> [SUB_STATE_END_HANDSHAKE] + * | | + * | v + * | WRITE_STATE_SEND + * | | + * | v + * | WRITE_STATE_POST_WORK + * | | + * +-------------+ + * + * WRITE_STATE_TRANSITION transitions the state of the handshake state machine + + * WRITE_STATE_PRE_WORK performs any work necessary to prepare the later + * sending of the message. This could result in an NBIO event occurring in + * which case control returns to the calling application. When this function + * is recalled we will resume in the same state where we left off. + * + * WRITE_STATE_SEND sends the message and performs any work to be done after + * sending. + * + * WRITE_STATE_POST_WORK performs any work necessary after the sending of the + * message has been completed. As for WRITE_STATE_PRE_WORK this could also + * result in an NBIO event. + */ +static SUB_STATE_RETURN write_state_machine(SSL *s) +{ + OSSL_STATEM *st = &s->statem; + int ret; + WRITE_TRAN(*transition) (SSL *s); + WORK_STATE(*pre_work) (SSL *s, WORK_STATE wst); + WORK_STATE(*post_work) (SSL *s, WORK_STATE wst); + int (*get_construct_message_f) (SSL *s, WPACKET *pkt, + int (**confunc) (SSL *s, WPACKET *pkt), + int *mt); + void (*cb) (const SSL *ssl, int type, int val) = NULL; + int (*confunc) (SSL *s, WPACKET *pkt); + int mt; + WPACKET pkt; + + cb = get_callback(s); + + if (s->server) { + transition = ossl_statem_server_write_transition; + pre_work = ossl_statem_server_pre_work; + post_work = ossl_statem_server_post_work; + get_construct_message_f = ossl_statem_server_construct_message; + } else { + transition = ossl_statem_client_write_transition; + pre_work = ossl_statem_client_pre_work; + post_work = ossl_statem_client_post_work; + get_construct_message_f = ossl_statem_client_construct_message; + } + + while (1) { + switch (st->write_state) { + case WRITE_STATE_TRANSITION: + if (cb != NULL) { + /* Notify callback of an impending state change */ + if (s->server) + cb(s, SSL_CB_ACCEPT_LOOP, 1); + else + cb(s, SSL_CB_CONNECT_LOOP, 1); + } + switch (transition(s)) { + case WRITE_TRAN_CONTINUE: + st->write_state = WRITE_STATE_PRE_WORK; + st->write_state_work = WORK_MORE_A; + break; + + case WRITE_TRAN_FINISHED: + return SUB_STATE_FINISHED; + break; + + case WRITE_TRAN_ERROR: + check_fatal(s, SSL_F_WRITE_STATE_MACHINE); + return SUB_STATE_ERROR; + } + break; + + case WRITE_STATE_PRE_WORK: + switch (st->write_state_work = pre_work(s, st->write_state_work)) { + case WORK_ERROR: + check_fatal(s, SSL_F_WRITE_STATE_MACHINE); + /* Fall through */ + case WORK_MORE_A: + case WORK_MORE_B: + case WORK_MORE_C: + return SUB_STATE_ERROR; + + case WORK_FINISHED_CONTINUE: + st->write_state = WRITE_STATE_SEND; + break; + + case WORK_FINISHED_STOP: + return SUB_STATE_END_HANDSHAKE; + } + if (!get_construct_message_f(s, &pkt, &confunc, &mt)) { + /* SSLfatal() already called */ + return SUB_STATE_ERROR; + } + if (mt == SSL3_MT_DUMMY) { + /* Skip construction and sending. This isn't a "real" state */ + st->write_state = WRITE_STATE_POST_WORK; + st->write_state_work = WORK_MORE_A; + break; + } + if (!WPACKET_init(&pkt, s->init_buf) + || !ssl_set_handshake_header(s, &pkt, mt)) { + WPACKET_cleanup(&pkt); + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE, + ERR_R_INTERNAL_ERROR); + return SUB_STATE_ERROR; + } + if (confunc != NULL && !confunc(s, &pkt)) { + WPACKET_cleanup(&pkt); + check_fatal(s, SSL_F_WRITE_STATE_MACHINE); + return SUB_STATE_ERROR; + } + if (!ssl_close_construct_packet(s, &pkt, mt) + || !WPACKET_finish(&pkt)) { + WPACKET_cleanup(&pkt); + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE, + ERR_R_INTERNAL_ERROR); + return SUB_STATE_ERROR; + } + + /* Fall through */ + + case WRITE_STATE_SEND: + if (SSL_IS_DTLS(s) && st->use_timer) { + dtls1_start_timer(s); + } + ret = statem_do_write(s); + if (ret <= 0) { + return SUB_STATE_ERROR; + } + st->write_state = WRITE_STATE_POST_WORK; + st->write_state_work = WORK_MORE_A; + /* Fall through */ + + case WRITE_STATE_POST_WORK: + switch (st->write_state_work = post_work(s, st->write_state_work)) { + case WORK_ERROR: + check_fatal(s, SSL_F_WRITE_STATE_MACHINE); + /* Fall through */ + case WORK_MORE_A: + case WORK_MORE_B: + case WORK_MORE_C: + return SUB_STATE_ERROR; + + case WORK_FINISHED_CONTINUE: + st->write_state = WRITE_STATE_TRANSITION; + break; + + case WORK_FINISHED_STOP: + return SUB_STATE_END_HANDSHAKE; + } + break; + + default: + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE, + ERR_R_INTERNAL_ERROR); + return SUB_STATE_ERROR; + } + } +} + +/* + * Flush the write BIO + */ +int statem_flush(SSL *s) +{ + s->rwstate = SSL_WRITING; + if (BIO_flush(s->wbio) <= 0) { + return 0; + } + s->rwstate = SSL_NOTHING; + + return 1; +} + +/* + * Called by the record layer to determine whether application data is + * allowed to be received in the current handshake state or not. + * + * Return values are: + * 1: Yes (application data allowed) + * 0: No (application data not allowed) + */ +int ossl_statem_app_data_allowed(SSL *s) +{ + OSSL_STATEM *st = &s->statem; + + if (st->state == MSG_FLOW_UNINITED) + return 0; + + if (!s->s3->in_read_app_data || (s->s3->total_renegotiations == 0)) + return 0; + + if (s->server) { + /* + * If we're a server and we haven't got as far as writing our + * ServerHello yet then we allow app data + */ + if (st->hand_state == TLS_ST_BEFORE + || st->hand_state == TLS_ST_SR_CLNT_HELLO) + return 1; + } else { + /* + * If we're a client and we haven't read the ServerHello yet then we + * allow app data + */ + if (st->hand_state == TLS_ST_CW_CLNT_HELLO) + return 1; + } + + return 0; +} + +/* + * This function returns 1 if TLS exporter is ready to export keying + * material, or 0 if otherwise. + */ +int ossl_statem_export_allowed(SSL *s) +{ + return s->s3->previous_server_finished_len != 0 + && s->statem.hand_state != TLS_ST_SW_FINISHED; +} + +/* + * Return 1 if early TLS exporter is ready to export keying material, + * or 0 if otherwise. + */ +int ossl_statem_export_early_allowed(SSL *s) +{ + /* + * The early exporter secret is only present on the server if we + * have accepted early_data. It is present on the client as long + * as we have sent early_data. + */ + return s->ext.early_data == SSL_EARLY_DATA_ACCEPTED + || (!s->server && s->ext.early_data != SSL_EARLY_DATA_NOT_SENT); +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem.h b/trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem.h new file mode 100644 index 000000000..144d930fc --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem.h @@ -0,0 +1,157 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/***************************************************************************** + * * + * These enums should be considered PRIVATE to the state machine. No * + * non-state machine code should need to use these * + * * + *****************************************************************************/ +/* + * Valid return codes used for functions performing work prior to or after + * sending or receiving a message + */ +typedef enum { + /* Something went wrong */ + WORK_ERROR, + /* We're done working and there shouldn't be anything else to do after */ + WORK_FINISHED_STOP, + /* We're done working move onto the next thing */ + WORK_FINISHED_CONTINUE, + /* We're working on phase A */ + WORK_MORE_A, + /* We're working on phase B */ + WORK_MORE_B, + /* We're working on phase C */ + WORK_MORE_C +} WORK_STATE; + +/* Write transition return codes */ +typedef enum { + /* Something went wrong */ + WRITE_TRAN_ERROR, + /* A transition was successfully completed and we should continue */ + WRITE_TRAN_CONTINUE, + /* There is no more write work to be done */ + WRITE_TRAN_FINISHED +} WRITE_TRAN; + +/* Message flow states */ +typedef enum { + /* No handshake in progress */ + MSG_FLOW_UNINITED, + /* A permanent error with this connection */ + MSG_FLOW_ERROR, + /* We are reading messages */ + MSG_FLOW_READING, + /* We are writing messages */ + MSG_FLOW_WRITING, + /* Handshake has finished */ + MSG_FLOW_FINISHED +} MSG_FLOW_STATE; + +/* Read states */ +typedef enum { + READ_STATE_HEADER, + READ_STATE_BODY, + READ_STATE_POST_PROCESS +} READ_STATE; + +/* Write states */ +typedef enum { + WRITE_STATE_TRANSITION, + WRITE_STATE_PRE_WORK, + WRITE_STATE_SEND, + WRITE_STATE_POST_WORK +} WRITE_STATE; + +typedef enum { + /* The enc_write_ctx can be used normally */ + ENC_WRITE_STATE_VALID, + /* The enc_write_ctx cannot be used */ + ENC_WRITE_STATE_INVALID, + /* Write alerts in plaintext, but otherwise use the enc_write_ctx */ + ENC_WRITE_STATE_WRITE_PLAIN_ALERTS +} ENC_WRITE_STATES; + +typedef enum { + /* The enc_read_ctx can be used normally */ + ENC_READ_STATE_VALID, + /* We may receive encrypted or plaintext alerts */ + ENC_READ_STATE_ALLOW_PLAIN_ALERTS +} ENC_READ_STATES; + +/***************************************************************************** + * * + * This structure should be considered "opaque" to anything outside of the * + * state machine. No non-state machine code should be accessing the members * + * of this structure. * + * * + *****************************************************************************/ + +struct ossl_statem_st { + MSG_FLOW_STATE state; + WRITE_STATE write_state; + WORK_STATE write_state_work; + READ_STATE read_state; + WORK_STATE read_state_work; + OSSL_HANDSHAKE_STATE hand_state; + /* The handshake state requested by an API call (e.g. HelloRequest) */ + OSSL_HANDSHAKE_STATE request_state; + int in_init; + int read_state_first_init; + /* true when we are actually in SSL_accept() or SSL_connect() */ + int in_handshake; + /* + * True when are processing a "real" handshake that needs cleaning up (not + * just a HelloRequest or similar). + */ + int cleanuphand; + /* Should we skip the CertificateVerify message? */ + unsigned int no_cert_verify; + int use_timer; + ENC_WRITE_STATES enc_write_state; + ENC_READ_STATES enc_read_state; +}; +typedef struct ossl_statem_st OSSL_STATEM; + +/***************************************************************************** + * * + * The following macros/functions represent the libssl internal API to the * + * state machine. Any libssl code may call these functions/macros * + * * + *****************************************************************************/ + +__owur int ossl_statem_accept(SSL *s); +__owur int ossl_statem_connect(SSL *s); +void ossl_statem_clear(SSL *s); +void ossl_statem_set_renegotiate(SSL *s); +void ossl_statem_fatal(SSL *s, int al, int func, int reason, const char *file, + int line); +# define SSL_AD_NO_ALERT -1 +# ifndef OPENSSL_NO_ERR +# define SSLfatal(s, al, f, r) ossl_statem_fatal((s), (al), (f), (r), \ + OPENSSL_FILE, OPENSSL_LINE) +# else +# define SSLfatal(s, al, f, r) ossl_statem_fatal((s), (al), (f), (r), NULL, 0) +# endif + +int ossl_statem_in_error(const SSL *s); +void ossl_statem_set_in_init(SSL *s, int init); +int ossl_statem_get_in_handshake(SSL *s); +void ossl_statem_set_in_handshake(SSL *s, int inhand); +__owur int ossl_statem_skip_early_data(SSL *s); +void ossl_statem_check_finish_init(SSL *s, int send); +void ossl_statem_set_hello_verify_done(SSL *s); +__owur int ossl_statem_app_data_allowed(SSL *s); +__owur int ossl_statem_export_allowed(SSL *s); +__owur int ossl_statem_export_early_allowed(SSL *s); + +/* Flush the write BIO */ +int statem_flush(SSL *s); diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_clnt.c b/trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_clnt.c new file mode 100644 index 000000000..e56d24dff --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_clnt.c @@ -0,0 +1,3851 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * Copyright 2005 Nokia. All rights reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "../ssl_locl.h" +#include "statem_locl.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static MSG_PROCESS_RETURN tls_process_as_hello_retry_request(SSL *s, PACKET *pkt); +static MSG_PROCESS_RETURN tls_process_encrypted_extensions(SSL *s, PACKET *pkt); + +static ossl_inline int cert_req_allowed(SSL *s); +static int key_exchange_expected(SSL *s); +static int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, + WPACKET *pkt); + +/* + * Is a CertificateRequest message allowed at the moment or not? + * + * Return values are: + * 1: Yes + * 0: No + */ +static ossl_inline int cert_req_allowed(SSL *s) +{ + /* TLS does not like anon-DH with client cert */ + if ((s->version > SSL3_VERSION + && (s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)) + || (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aSRP | SSL_aPSK))) + return 0; + + return 1; +} + +/* + * Should we expect the ServerKeyExchange message or not? + * + * Return values are: + * 1: Yes + * 0: No + */ +static int key_exchange_expected(SSL *s) +{ + long alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + + /* + * Can't skip server key exchange if this is an ephemeral + * ciphersuite or for SRP + */ + if (alg_k & (SSL_kDHE | SSL_kECDHE | SSL_kDHEPSK | SSL_kECDHEPSK + | SSL_kSRP)) { + return 1; + } + + return 0; +} + +/* + * ossl_statem_client_read_transition() encapsulates the logic for the allowed + * handshake state transitions when a TLS1.3 client is reading messages from the + * server. The message type that the server has sent is provided in |mt|. The + * current state is in |s->statem.hand_state|. + * + * Return values are 1 for success (transition allowed) and 0 on error + * (transition not allowed) + */ +static int ossl_statem_client13_read_transition(SSL *s, int mt) +{ + OSSL_STATEM *st = &s->statem; + + /* + * Note: There is no case for TLS_ST_CW_CLNT_HELLO, because we haven't + * yet negotiated TLSv1.3 at that point so that is handled by + * ossl_statem_client_read_transition() + */ + + switch (st->hand_state) { + default: + break; + + case TLS_ST_CW_CLNT_HELLO: + /* + * This must a ClientHello following a HelloRetryRequest, so the only + * thing we can get now is a ServerHello. + */ + if (mt == SSL3_MT_SERVER_HELLO) { + st->hand_state = TLS_ST_CR_SRVR_HELLO; + return 1; + } + break; + + case TLS_ST_CR_SRVR_HELLO: + if (mt == SSL3_MT_ENCRYPTED_EXTENSIONS) { + st->hand_state = TLS_ST_CR_ENCRYPTED_EXTENSIONS; + return 1; + } + break; + + case TLS_ST_CR_ENCRYPTED_EXTENSIONS: + if (s->hit) { + if (mt == SSL3_MT_FINISHED) { + st->hand_state = TLS_ST_CR_FINISHED; + return 1; + } + } else { + if (mt == SSL3_MT_CERTIFICATE_REQUEST) { + st->hand_state = TLS_ST_CR_CERT_REQ; + return 1; + } + if (mt == SSL3_MT_CERTIFICATE) { + st->hand_state = TLS_ST_CR_CERT; + return 1; + } + } + break; + + case TLS_ST_CR_CERT_REQ: + if (mt == SSL3_MT_CERTIFICATE) { + st->hand_state = TLS_ST_CR_CERT; + return 1; + } + break; + + case TLS_ST_CR_CERT: + if (mt == SSL3_MT_CERTIFICATE_VERIFY) { + st->hand_state = TLS_ST_CR_CERT_VRFY; + return 1; + } + break; + + case TLS_ST_CR_CERT_VRFY: + if (mt == SSL3_MT_FINISHED) { + st->hand_state = TLS_ST_CR_FINISHED; + return 1; + } + break; + + case TLS_ST_OK: + if (mt == SSL3_MT_NEWSESSION_TICKET) { + st->hand_state = TLS_ST_CR_SESSION_TICKET; + return 1; + } + if (mt == SSL3_MT_KEY_UPDATE) { + st->hand_state = TLS_ST_CR_KEY_UPDATE; + return 1; + } + if (mt == SSL3_MT_CERTIFICATE_REQUEST) { +#if DTLS_MAX_VERSION != DTLS1_2_VERSION +# error TODO(DTLS1.3): Restore digest for PHA before adding message. +#endif + if (!SSL_IS_DTLS(s) && s->post_handshake_auth == SSL_PHA_EXT_SENT) { + s->post_handshake_auth = SSL_PHA_REQUESTED; + /* + * In TLS, this is called before the message is added to the + * digest. In DTLS, this is expected to be called after adding + * to the digest. Either move the digest restore, or add the + * message here after the swap, or do it after the clientFinished? + */ + if (!tls13_restore_handshake_digest_for_pha(s)) { + /* SSLfatal() already called */ + return 0; + } + st->hand_state = TLS_ST_CR_CERT_REQ; + return 1; + } + } + break; + } + + /* No valid transition found */ + return 0; +} + +/* + * ossl_statem_client_read_transition() encapsulates the logic for the allowed + * handshake state transitions when the client is reading messages from the + * server. The message type that the server has sent is provided in |mt|. The + * current state is in |s->statem.hand_state|. + * + * Return values are 1 for success (transition allowed) and 0 on error + * (transition not allowed) + */ +int ossl_statem_client_read_transition(SSL *s, int mt) +{ + OSSL_STATEM *st = &s->statem; + int ske_expected; + + /* + * Note that after writing the first ClientHello we don't know what version + * we are going to negotiate yet, so we don't take this branch until later. + */ + if (SSL_IS_TLS13(s)) { + if (!ossl_statem_client13_read_transition(s, mt)) + goto err; + return 1; + } + + switch (st->hand_state) { + default: + break; + + case TLS_ST_CW_CLNT_HELLO: + if (mt == SSL3_MT_SERVER_HELLO) { + st->hand_state = TLS_ST_CR_SRVR_HELLO; + return 1; + } + + if (SSL_IS_DTLS(s)) { + if (mt == DTLS1_MT_HELLO_VERIFY_REQUEST) { + st->hand_state = DTLS_ST_CR_HELLO_VERIFY_REQUEST; + return 1; + } + } + break; + + case TLS_ST_EARLY_DATA: + /* + * We've not actually selected TLSv1.3 yet, but we have sent early + * data. The only thing allowed now is a ServerHello or a + * HelloRetryRequest. + */ + if (mt == SSL3_MT_SERVER_HELLO) { + st->hand_state = TLS_ST_CR_SRVR_HELLO; + return 1; + } + break; + + case TLS_ST_CR_SRVR_HELLO: + if (s->hit) { + if (s->ext.ticket_expected) { + if (mt == SSL3_MT_NEWSESSION_TICKET) { + st->hand_state = TLS_ST_CR_SESSION_TICKET; + return 1; + } + } else if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) { + st->hand_state = TLS_ST_CR_CHANGE; + return 1; + } + } else { + if (SSL_IS_DTLS(s) && mt == DTLS1_MT_HELLO_VERIFY_REQUEST) { + st->hand_state = DTLS_ST_CR_HELLO_VERIFY_REQUEST; + return 1; + } else if (s->version >= TLS1_VERSION + && s->ext.session_secret_cb != NULL + && s->session->ext.tick != NULL + && mt == SSL3_MT_CHANGE_CIPHER_SPEC) { + /* + * Normally, we can tell if the server is resuming the session + * from the session ID. EAP-FAST (RFC 4851), however, relies on + * the next server message after the ServerHello to determine if + * the server is resuming. + */ + s->hit = 1; + st->hand_state = TLS_ST_CR_CHANGE; + return 1; + } else if (!(s->s3->tmp.new_cipher->algorithm_auth + & (SSL_aNULL | SSL_aSRP | SSL_aPSK))) { + if (mt == SSL3_MT_CERTIFICATE) { + st->hand_state = TLS_ST_CR_CERT; + return 1; + } + } else { + ske_expected = key_exchange_expected(s); + /* SKE is optional for some PSK ciphersuites */ + if (ske_expected + || ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK) + && mt == SSL3_MT_SERVER_KEY_EXCHANGE)) { + if (mt == SSL3_MT_SERVER_KEY_EXCHANGE) { + st->hand_state = TLS_ST_CR_KEY_EXCH; + return 1; + } + } else if (mt == SSL3_MT_CERTIFICATE_REQUEST + && cert_req_allowed(s)) { + st->hand_state = TLS_ST_CR_CERT_REQ; + return 1; + } else if (mt == SSL3_MT_SERVER_DONE) { + st->hand_state = TLS_ST_CR_SRVR_DONE; + return 1; + } + } + } + break; + + case TLS_ST_CR_CERT: + /* + * The CertificateStatus message is optional even if + * |ext.status_expected| is set + */ + if (s->ext.status_expected && mt == SSL3_MT_CERTIFICATE_STATUS) { + st->hand_state = TLS_ST_CR_CERT_STATUS; + return 1; + } + /* Fall through */ + + case TLS_ST_CR_CERT_STATUS: + ske_expected = key_exchange_expected(s); + /* SKE is optional for some PSK ciphersuites */ + if (ske_expected || ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK) + && mt == SSL3_MT_SERVER_KEY_EXCHANGE)) { + if (mt == SSL3_MT_SERVER_KEY_EXCHANGE) { + st->hand_state = TLS_ST_CR_KEY_EXCH; + return 1; + } + goto err; + } + /* Fall through */ + + case TLS_ST_CR_KEY_EXCH: + if (mt == SSL3_MT_CERTIFICATE_REQUEST) { + if (cert_req_allowed(s)) { + st->hand_state = TLS_ST_CR_CERT_REQ; + return 1; + } + goto err; + } + /* Fall through */ + + case TLS_ST_CR_CERT_REQ: + if (mt == SSL3_MT_SERVER_DONE) { + st->hand_state = TLS_ST_CR_SRVR_DONE; + return 1; + } + break; + + case TLS_ST_CW_FINISHED: + if (s->ext.ticket_expected) { + if (mt == SSL3_MT_NEWSESSION_TICKET) { + st->hand_state = TLS_ST_CR_SESSION_TICKET; + return 1; + } + } else if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) { + st->hand_state = TLS_ST_CR_CHANGE; + return 1; + } + break; + + case TLS_ST_CR_SESSION_TICKET: + if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) { + st->hand_state = TLS_ST_CR_CHANGE; + return 1; + } + break; + + case TLS_ST_CR_CHANGE: + if (mt == SSL3_MT_FINISHED) { + st->hand_state = TLS_ST_CR_FINISHED; + return 1; + } + break; + + case TLS_ST_OK: + if (mt == SSL3_MT_HELLO_REQUEST) { + st->hand_state = TLS_ST_CR_HELLO_REQ; + return 1; + } + break; + } + + err: + /* No valid transition found */ + if (SSL_IS_DTLS(s) && mt == SSL3_MT_CHANGE_CIPHER_SPEC) { + BIO *rbio; + + /* + * CCS messages don't have a message sequence number so this is probably + * because of an out-of-order CCS. We'll just drop it. + */ + s->init_num = 0; + s->rwstate = SSL_READING; + rbio = SSL_get_rbio(s); + BIO_clear_retry_flags(rbio); + BIO_set_retry_read(rbio); + return 0; + } + SSLfatal(s, SSL3_AD_UNEXPECTED_MESSAGE, + SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION, + SSL_R_UNEXPECTED_MESSAGE); + return 0; +} + +/* + * ossl_statem_client13_write_transition() works out what handshake state to + * move to next when the TLSv1.3 client is writing messages to be sent to the + * server. + */ +static WRITE_TRAN ossl_statem_client13_write_transition(SSL *s) +{ + OSSL_STATEM *st = &s->statem; + + /* + * Note: There are no cases for TLS_ST_BEFORE because we haven't negotiated + * TLSv1.3 yet at that point. They are handled by + * ossl_statem_client_write_transition(). + */ + switch (st->hand_state) { + default: + /* Shouldn't happen */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_OSSL_STATEM_CLIENT13_WRITE_TRANSITION, + ERR_R_INTERNAL_ERROR); + return WRITE_TRAN_ERROR; + + case TLS_ST_CR_CERT_REQ: + if (s->post_handshake_auth == SSL_PHA_REQUESTED) { + st->hand_state = TLS_ST_CW_CERT; + return WRITE_TRAN_CONTINUE; + } + /* + * We should only get here if we received a CertificateRequest after + * we already sent close_notify + */ + if (!ossl_assert((s->shutdown & SSL_SENT_SHUTDOWN) != 0)) { + /* Shouldn't happen - same as default case */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_OSSL_STATEM_CLIENT13_WRITE_TRANSITION, + ERR_R_INTERNAL_ERROR); + return WRITE_TRAN_ERROR; + } + st->hand_state = TLS_ST_OK; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_CR_FINISHED: + if (s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY + || s->early_data_state == SSL_EARLY_DATA_FINISHED_WRITING) + st->hand_state = TLS_ST_PENDING_EARLY_DATA_END; + else if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0 + && s->hello_retry_request == SSL_HRR_NONE) + st->hand_state = TLS_ST_CW_CHANGE; + else + st->hand_state = (s->s3->tmp.cert_req != 0) ? TLS_ST_CW_CERT + : TLS_ST_CW_FINISHED; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_PENDING_EARLY_DATA_END: + if (s->ext.early_data == SSL_EARLY_DATA_ACCEPTED) { + st->hand_state = TLS_ST_CW_END_OF_EARLY_DATA; + return WRITE_TRAN_CONTINUE; + } + /* Fall through */ + + case TLS_ST_CW_END_OF_EARLY_DATA: + case TLS_ST_CW_CHANGE: + st->hand_state = (s->s3->tmp.cert_req != 0) ? TLS_ST_CW_CERT + : TLS_ST_CW_FINISHED; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_CW_CERT: + /* If a non-empty Certificate we also send CertificateVerify */ + st->hand_state = (s->s3->tmp.cert_req == 1) ? TLS_ST_CW_CERT_VRFY + : TLS_ST_CW_FINISHED; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_CW_CERT_VRFY: + st->hand_state = TLS_ST_CW_FINISHED; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_CR_KEY_UPDATE: + if (s->key_update != SSL_KEY_UPDATE_NONE) { + st->hand_state = TLS_ST_CW_KEY_UPDATE; + return WRITE_TRAN_CONTINUE; + } + /* Fall through */ + + case TLS_ST_CW_KEY_UPDATE: + case TLS_ST_CR_SESSION_TICKET: + case TLS_ST_CW_FINISHED: + st->hand_state = TLS_ST_OK; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_OK: + if (s->key_update != SSL_KEY_UPDATE_NONE) { + st->hand_state = TLS_ST_CW_KEY_UPDATE; + return WRITE_TRAN_CONTINUE; + } + + /* Try to read from the server instead */ + return WRITE_TRAN_FINISHED; + } +} + +/* + * ossl_statem_client_write_transition() works out what handshake state to + * move to next when the client is writing messages to be sent to the server. + */ +WRITE_TRAN ossl_statem_client_write_transition(SSL *s) +{ + OSSL_STATEM *st = &s->statem; + + /* + * Note that immediately before/after a ClientHello we don't know what + * version we are going to negotiate yet, so we don't take this branch until + * later + */ + if (SSL_IS_TLS13(s)) + return ossl_statem_client13_write_transition(s); + + switch (st->hand_state) { + default: + /* Shouldn't happen */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_OSSL_STATEM_CLIENT_WRITE_TRANSITION, + ERR_R_INTERNAL_ERROR); + return WRITE_TRAN_ERROR; + + case TLS_ST_OK: + if (!s->renegotiate) { + /* + * We haven't requested a renegotiation ourselves so we must have + * received a message from the server. Better read it. + */ + return WRITE_TRAN_FINISHED; + } + /* Renegotiation */ + /* fall thru */ + case TLS_ST_BEFORE: + st->hand_state = TLS_ST_CW_CLNT_HELLO; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_CW_CLNT_HELLO: + if (s->early_data_state == SSL_EARLY_DATA_CONNECTING) { + /* + * We are assuming this is a TLSv1.3 connection, although we haven't + * actually selected a version yet. + */ + if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0) + st->hand_state = TLS_ST_CW_CHANGE; + else + st->hand_state = TLS_ST_EARLY_DATA; + return WRITE_TRAN_CONTINUE; + } + /* + * No transition at the end of writing because we don't know what + * we will be sent + */ + return WRITE_TRAN_FINISHED; + + case TLS_ST_CR_SRVR_HELLO: + /* + * We only get here in TLSv1.3. We just received an HRR, so issue a + * CCS unless middlebox compat mode is off, or we already issued one + * because we did early data. + */ + if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0 + && s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING) + st->hand_state = TLS_ST_CW_CHANGE; + else + st->hand_state = TLS_ST_CW_CLNT_HELLO; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_EARLY_DATA: + return WRITE_TRAN_FINISHED; + + case DTLS_ST_CR_HELLO_VERIFY_REQUEST: + st->hand_state = TLS_ST_CW_CLNT_HELLO; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_CR_SRVR_DONE: + if (s->s3->tmp.cert_req) + st->hand_state = TLS_ST_CW_CERT; + else + st->hand_state = TLS_ST_CW_KEY_EXCH; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_CW_CERT: + st->hand_state = TLS_ST_CW_KEY_EXCH; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_CW_KEY_EXCH: + /* + * For TLS, cert_req is set to 2, so a cert chain of nothing is + * sent, but no verify packet is sent + */ + /* + * XXX: For now, we do not support client authentication in ECDH + * cipher suites with ECDH (rather than ECDSA) certificates. We + * need to skip the certificate verify message when client's + * ECDH public key is sent inside the client certificate. + */ + if (s->s3->tmp.cert_req == 1) { + st->hand_state = TLS_ST_CW_CERT_VRFY; + } else { + st->hand_state = TLS_ST_CW_CHANGE; + } + if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY) { + st->hand_state = TLS_ST_CW_CHANGE; + } + return WRITE_TRAN_CONTINUE; + + case TLS_ST_CW_CERT_VRFY: + st->hand_state = TLS_ST_CW_CHANGE; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_CW_CHANGE: + if (s->hello_retry_request == SSL_HRR_PENDING) { + st->hand_state = TLS_ST_CW_CLNT_HELLO; + } else if (s->early_data_state == SSL_EARLY_DATA_CONNECTING) { + st->hand_state = TLS_ST_EARLY_DATA; + } else { +#if defined(OPENSSL_NO_NEXTPROTONEG) + st->hand_state = TLS_ST_CW_FINISHED; +#else + if (!SSL_IS_DTLS(s) && s->s3->npn_seen) + st->hand_state = TLS_ST_CW_NEXT_PROTO; + else + st->hand_state = TLS_ST_CW_FINISHED; +#endif + } + return WRITE_TRAN_CONTINUE; + +#if !defined(OPENSSL_NO_NEXTPROTONEG) + case TLS_ST_CW_NEXT_PROTO: + st->hand_state = TLS_ST_CW_FINISHED; + return WRITE_TRAN_CONTINUE; +#endif + + case TLS_ST_CW_FINISHED: + if (s->hit) { + st->hand_state = TLS_ST_OK; + return WRITE_TRAN_CONTINUE; + } else { + return WRITE_TRAN_FINISHED; + } + + case TLS_ST_CR_FINISHED: + if (s->hit) { + st->hand_state = TLS_ST_CW_CHANGE; + return WRITE_TRAN_CONTINUE; + } else { + st->hand_state = TLS_ST_OK; + return WRITE_TRAN_CONTINUE; + } + + case TLS_ST_CR_HELLO_REQ: + /* + * If we can renegotiate now then do so, otherwise wait for a more + * convenient time. + */ + if (ssl3_renegotiate_check(s, 1)) { + if (!tls_setup_handshake(s)) { + /* SSLfatal() already called */ + return WRITE_TRAN_ERROR; + } + st->hand_state = TLS_ST_CW_CLNT_HELLO; + return WRITE_TRAN_CONTINUE; + } + st->hand_state = TLS_ST_OK; + return WRITE_TRAN_CONTINUE; + } +} + +/* + * Perform any pre work that needs to be done prior to sending a message from + * the client to the server. + */ +WORK_STATE ossl_statem_client_pre_work(SSL *s, WORK_STATE wst) +{ + OSSL_STATEM *st = &s->statem; + + switch (st->hand_state) { + default: + /* No pre work to be done */ + break; + + case TLS_ST_CW_CLNT_HELLO: + s->shutdown = 0; + if (SSL_IS_DTLS(s)) { + /* every DTLS ClientHello resets Finished MAC */ + if (!ssl3_init_finished_mac(s)) { + /* SSLfatal() already called */ + return WORK_ERROR; + } + } + break; + + case TLS_ST_CW_CHANGE: + if (SSL_IS_DTLS(s)) { + if (s->hit) { + /* + * We're into the last flight so we don't retransmit these + * messages unless we need to. + */ + st->use_timer = 0; + } +#ifndef OPENSSL_NO_SCTP + if (BIO_dgram_is_sctp(SSL_get_wbio(s))) { + /* Calls SSLfatal() as required */ + return dtls_wait_for_dry(s); + } +#endif + } + break; + + case TLS_ST_PENDING_EARLY_DATA_END: + /* + * If we've been called by SSL_do_handshake()/SSL_write(), or we did not + * attempt to write early data before calling SSL_read() then we press + * on with the handshake. Otherwise we pause here. + */ + if (s->early_data_state == SSL_EARLY_DATA_FINISHED_WRITING + || s->early_data_state == SSL_EARLY_DATA_NONE) + return WORK_FINISHED_CONTINUE; + /* Fall through */ + + case TLS_ST_EARLY_DATA: + return tls_finish_handshake(s, wst, 0, 1); + + case TLS_ST_OK: + /* Calls SSLfatal() as required */ + return tls_finish_handshake(s, wst, 1, 1); + } + + return WORK_FINISHED_CONTINUE; +} + +/* + * Perform any work that needs to be done after sending a message from the + * client to the server. + */ +WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst) +{ + OSSL_STATEM *st = &s->statem; + + s->init_num = 0; + + switch (st->hand_state) { + default: + /* No post work to be done */ + break; + + case TLS_ST_CW_CLNT_HELLO: + if (s->early_data_state == SSL_EARLY_DATA_CONNECTING + && s->max_early_data > 0) { + /* + * We haven't selected TLSv1.3 yet so we don't call the change + * cipher state function associated with the SSL_METHOD. Instead + * we call tls13_change_cipher_state() directly. + */ + if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) == 0) { + if (!tls13_change_cipher_state(s, + SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_CLIENT_WRITE)) { + /* SSLfatal() already called */ + return WORK_ERROR; + } + } + /* else we're in compat mode so we delay flushing until after CCS */ + } else if (!statem_flush(s)) { + return WORK_MORE_A; + } + + if (SSL_IS_DTLS(s)) { + /* Treat the next message as the first packet */ + s->first_packet = 1; + } + break; + + case TLS_ST_CW_END_OF_EARLY_DATA: + /* + * We set the enc_write_ctx back to NULL because we may end up writing + * in cleartext again if we get a HelloRetryRequest from the server. + */ + EVP_CIPHER_CTX_free(s->enc_write_ctx); + s->enc_write_ctx = NULL; + break; + + case TLS_ST_CW_KEY_EXCH: + if (tls_client_key_exchange_post_work(s) == 0) { + /* SSLfatal() already called */ + return WORK_ERROR; + } + break; + + case TLS_ST_CW_CHANGE: + if (SSL_IS_TLS13(s) || s->hello_retry_request == SSL_HRR_PENDING) + break; + if (s->early_data_state == SSL_EARLY_DATA_CONNECTING + && s->max_early_data > 0) { + /* + * We haven't selected TLSv1.3 yet so we don't call the change + * cipher state function associated with the SSL_METHOD. Instead + * we call tls13_change_cipher_state() directly. + */ + if (!tls13_change_cipher_state(s, + SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_CLIENT_WRITE)) + return WORK_ERROR; + break; + } + s->session->cipher = s->s3->tmp.new_cipher; +#ifdef OPENSSL_NO_COMP + s->session->compress_meth = 0; +#else + if (s->s3->tmp.new_compression == NULL) + s->session->compress_meth = 0; + else + s->session->compress_meth = s->s3->tmp.new_compression->id; +#endif + if (!s->method->ssl3_enc->setup_key_block(s)) { + /* SSLfatal() already called */ + return WORK_ERROR; + } + + if (!s->method->ssl3_enc->change_cipher_state(s, + SSL3_CHANGE_CIPHER_CLIENT_WRITE)) { + /* SSLfatal() already called */ + return WORK_ERROR; + } + + if (SSL_IS_DTLS(s)) { +#ifndef OPENSSL_NO_SCTP + if (s->hit) { + /* + * Change to new shared key of SCTP-Auth, will be ignored if + * no SCTP used. + */ + BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, + 0, NULL); + } +#endif + + dtls1_reset_seq_numbers(s, SSL3_CC_WRITE); + } + break; + + case TLS_ST_CW_FINISHED: +#ifndef OPENSSL_NO_SCTP + if (wst == WORK_MORE_A && SSL_IS_DTLS(s) && s->hit == 0) { + /* + * Change to new shared key of SCTP-Auth, will be ignored if + * no SCTP used. + */ + BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, + 0, NULL); + } +#endif + if (statem_flush(s) != 1) + return WORK_MORE_B; + + if (SSL_IS_TLS13(s)) { + if (!tls13_save_handshake_digest_for_pha(s)) { + /* SSLfatal() already called */ + return WORK_ERROR; + } + if (s->post_handshake_auth != SSL_PHA_REQUESTED) { + if (!s->method->ssl3_enc->change_cipher_state(s, + SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_CLIENT_WRITE)) { + /* SSLfatal() already called */ + return WORK_ERROR; + } + } + } + break; + + case TLS_ST_CW_KEY_UPDATE: + if (statem_flush(s) != 1) + return WORK_MORE_A; + if (!tls13_update_key(s, 1)) { + /* SSLfatal() already called */ + return WORK_ERROR; + } + break; + } + + return WORK_FINISHED_CONTINUE; +} + +/* + * Get the message construction function and message type for sending from the + * client + * + * Valid return values are: + * 1: Success + * 0: Error + */ +int ossl_statem_client_construct_message(SSL *s, WPACKET *pkt, + confunc_f *confunc, int *mt) +{ + OSSL_STATEM *st = &s->statem; + + switch (st->hand_state) { + default: + /* Shouldn't happen */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_OSSL_STATEM_CLIENT_CONSTRUCT_MESSAGE, + SSL_R_BAD_HANDSHAKE_STATE); + return 0; + + case TLS_ST_CW_CHANGE: + if (SSL_IS_DTLS(s)) + *confunc = dtls_construct_change_cipher_spec; + else + *confunc = tls_construct_change_cipher_spec; + *mt = SSL3_MT_CHANGE_CIPHER_SPEC; + break; + + case TLS_ST_CW_CLNT_HELLO: + *confunc = tls_construct_client_hello; + *mt = SSL3_MT_CLIENT_HELLO; + break; + + case TLS_ST_CW_END_OF_EARLY_DATA: + *confunc = tls_construct_end_of_early_data; + *mt = SSL3_MT_END_OF_EARLY_DATA; + break; + + case TLS_ST_PENDING_EARLY_DATA_END: + *confunc = NULL; + *mt = SSL3_MT_DUMMY; + break; + + case TLS_ST_CW_CERT: + *confunc = tls_construct_client_certificate; + *mt = SSL3_MT_CERTIFICATE; + break; + + case TLS_ST_CW_KEY_EXCH: + *confunc = tls_construct_client_key_exchange; + *mt = SSL3_MT_CLIENT_KEY_EXCHANGE; + break; + + case TLS_ST_CW_CERT_VRFY: + *confunc = tls_construct_cert_verify; + *mt = SSL3_MT_CERTIFICATE_VERIFY; + break; + +#if !defined(OPENSSL_NO_NEXTPROTONEG) + case TLS_ST_CW_NEXT_PROTO: + *confunc = tls_construct_next_proto; + *mt = SSL3_MT_NEXT_PROTO; + break; +#endif + case TLS_ST_CW_FINISHED: + *confunc = tls_construct_finished; + *mt = SSL3_MT_FINISHED; + break; + + case TLS_ST_CW_KEY_UPDATE: + *confunc = tls_construct_key_update; + *mt = SSL3_MT_KEY_UPDATE; + break; + } + + return 1; +} + +/* + * Returns the maximum allowed length for the current message that we are + * reading. Excludes the message header. + */ +size_t ossl_statem_client_max_message_size(SSL *s) +{ + OSSL_STATEM *st = &s->statem; + + switch (st->hand_state) { + default: + /* Shouldn't happen */ + return 0; + + case TLS_ST_CR_SRVR_HELLO: + return SERVER_HELLO_MAX_LENGTH; + + case DTLS_ST_CR_HELLO_VERIFY_REQUEST: + return HELLO_VERIFY_REQUEST_MAX_LENGTH; + + case TLS_ST_CR_CERT: + return s->max_cert_list; + + case TLS_ST_CR_CERT_VRFY: + return SSL3_RT_MAX_PLAIN_LENGTH; + + case TLS_ST_CR_CERT_STATUS: + return SSL3_RT_MAX_PLAIN_LENGTH; + + case TLS_ST_CR_KEY_EXCH: + return SERVER_KEY_EXCH_MAX_LENGTH; + + case TLS_ST_CR_CERT_REQ: + /* + * Set to s->max_cert_list for compatibility with previous releases. In + * practice these messages can get quite long if servers are configured + * to provide a long list of acceptable CAs + */ + return s->max_cert_list; + + case TLS_ST_CR_SRVR_DONE: + return SERVER_HELLO_DONE_MAX_LENGTH; + + case TLS_ST_CR_CHANGE: + if (s->version == DTLS1_BAD_VER) + return 3; + return CCS_MAX_LENGTH; + + case TLS_ST_CR_SESSION_TICKET: + return SSL3_RT_MAX_PLAIN_LENGTH; + + case TLS_ST_CR_FINISHED: + return FINISHED_MAX_LENGTH; + + case TLS_ST_CR_ENCRYPTED_EXTENSIONS: + return ENCRYPTED_EXTENSIONS_MAX_LENGTH; + + case TLS_ST_CR_KEY_UPDATE: + return KEY_UPDATE_MAX_LENGTH; + } +} + +/* + * Process a message that the client has been received from the server. + */ +MSG_PROCESS_RETURN ossl_statem_client_process_message(SSL *s, PACKET *pkt) +{ + OSSL_STATEM *st = &s->statem; + + switch (st->hand_state) { + default: + /* Shouldn't happen */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_OSSL_STATEM_CLIENT_PROCESS_MESSAGE, + ERR_R_INTERNAL_ERROR); + return MSG_PROCESS_ERROR; + + case TLS_ST_CR_SRVR_HELLO: + return tls_process_server_hello(s, pkt); + + case DTLS_ST_CR_HELLO_VERIFY_REQUEST: + return dtls_process_hello_verify(s, pkt); + + case TLS_ST_CR_CERT: + return tls_process_server_certificate(s, pkt); + + case TLS_ST_CR_CERT_VRFY: + return tls_process_cert_verify(s, pkt); + + case TLS_ST_CR_CERT_STATUS: + return tls_process_cert_status(s, pkt); + + case TLS_ST_CR_KEY_EXCH: + return tls_process_key_exchange(s, pkt); + + case TLS_ST_CR_CERT_REQ: + return tls_process_certificate_request(s, pkt); + + case TLS_ST_CR_SRVR_DONE: + return tls_process_server_done(s, pkt); + + case TLS_ST_CR_CHANGE: + return tls_process_change_cipher_spec(s, pkt); + + case TLS_ST_CR_SESSION_TICKET: + return tls_process_new_session_ticket(s, pkt); + + case TLS_ST_CR_FINISHED: + return tls_process_finished(s, pkt); + + case TLS_ST_CR_HELLO_REQ: + return tls_process_hello_req(s, pkt); + + case TLS_ST_CR_ENCRYPTED_EXTENSIONS: + return tls_process_encrypted_extensions(s, pkt); + + case TLS_ST_CR_KEY_UPDATE: + return tls_process_key_update(s, pkt); + } +} + +/* + * Perform any further processing required following the receipt of a message + * from the server + */ +WORK_STATE ossl_statem_client_post_process_message(SSL *s, WORK_STATE wst) +{ + OSSL_STATEM *st = &s->statem; + + switch (st->hand_state) { + default: + /* Shouldn't happen */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_OSSL_STATEM_CLIENT_POST_PROCESS_MESSAGE, + ERR_R_INTERNAL_ERROR); + return WORK_ERROR; + + case TLS_ST_CR_CERT_VRFY: + case TLS_ST_CR_CERT_REQ: + return tls_prepare_client_certificate(s, wst); + } +} + +int tls_construct_client_hello(SSL *s, WPACKET *pkt) +{ + unsigned char *p; + size_t sess_id_len; + int i, protverr; +#ifndef OPENSSL_NO_COMP + SSL_COMP *comp; +#endif + SSL_SESSION *sess = s->session; + unsigned char *session_id; + + /* Work out what SSL/TLS/DTLS version to use */ + protverr = ssl_set_client_hello_version(s); + if (protverr != 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, + protverr); + return 0; + } + + if (sess == NULL + || !ssl_version_supported(s, sess->ssl_version, NULL) + || !SSL_SESSION_is_resumable(sess)) { + if (s->hello_retry_request == SSL_HRR_NONE + && !ssl_get_new_session(s, 0)) { + /* SSLfatal() already called */ + return 0; + } + } + /* else use the pre-loaded session */ + + p = s->s3->client_random; + + /* + * for DTLS if client_random is initialized, reuse it, we are + * required to use same upon reply to HelloVerify + */ + if (SSL_IS_DTLS(s)) { + size_t idx; + i = 1; + for (idx = 0; idx < sizeof(s->s3->client_random); idx++) { + if (p[idx]) { + i = 0; + break; + } + } + } else { + i = (s->hello_retry_request == SSL_HRR_NONE); + } + + if (i && ssl_fill_hello_random(s, 0, p, sizeof(s->s3->client_random), + DOWNGRADE_NONE) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, + ERR_R_INTERNAL_ERROR); + return 0; + } + + /*- + * version indicates the negotiated version: for example from + * an SSLv2/v3 compatible client hello). The client_version + * field is the maximum version we permit and it is also + * used in RSA encrypted premaster secrets. Some servers can + * choke if we initially report a higher version then + * renegotiate to a lower one in the premaster secret. This + * didn't happen with TLS 1.0 as most servers supported it + * but it can with TLS 1.1 or later if the server only supports + * 1.0. + * + * Possible scenario with previous logic: + * 1. Client hello indicates TLS 1.2 + * 2. Server hello says TLS 1.0 + * 3. RSA encrypted premaster secret uses 1.2. + * 4. Handshake proceeds using TLS 1.0. + * 5. Server sends hello request to renegotiate. + * 6. Client hello indicates TLS v1.0 as we now + * know that is maximum server supports. + * 7. Server chokes on RSA encrypted premaster secret + * containing version 1.0. + * + * For interoperability it should be OK to always use the + * maximum version we support in client hello and then rely + * on the checking of version to ensure the servers isn't + * being inconsistent: for example initially negotiating with + * TLS 1.0 and renegotiating with TLS 1.2. We do this by using + * client_version in client hello and not resetting it to + * the negotiated version. + * + * For TLS 1.3 we always set the ClientHello version to 1.2 and rely on the + * supported_versions extension for the real supported versions. + */ + if (!WPACKET_put_bytes_u16(pkt, s->client_version) + || !WPACKET_memcpy(pkt, s->s3->client_random, SSL3_RANDOM_SIZE)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, + ERR_R_INTERNAL_ERROR); + return 0; + } + + /* Session ID */ + session_id = s->session->session_id; + if (s->new_session || s->session->ssl_version == TLS1_3_VERSION) { + if (s->version == TLS1_3_VERSION + && (s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0) { + sess_id_len = sizeof(s->tmp_session_id); + s->tmp_session_id_len = sess_id_len; + session_id = s->tmp_session_id; + if (s->hello_retry_request == SSL_HRR_NONE + && RAND_bytes(s->tmp_session_id, sess_id_len) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, + ERR_R_INTERNAL_ERROR); + return 0; + } + } else { + sess_id_len = 0; + } + } else { + assert(s->session->session_id_length <= sizeof(s->session->session_id)); + sess_id_len = s->session->session_id_length; + if (s->version == TLS1_3_VERSION) { + s->tmp_session_id_len = sess_id_len; + memcpy(s->tmp_session_id, s->session->session_id, sess_id_len); + } + } + if (!WPACKET_start_sub_packet_u8(pkt) + || (sess_id_len != 0 && !WPACKET_memcpy(pkt, session_id, + sess_id_len)) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, + ERR_R_INTERNAL_ERROR); + return 0; + } + + /* cookie stuff for DTLS */ + if (SSL_IS_DTLS(s)) { + if (s->d1->cookie_len > sizeof(s->d1->cookie) + || !WPACKET_sub_memcpy_u8(pkt, s->d1->cookie, + s->d1->cookie_len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, + ERR_R_INTERNAL_ERROR); + return 0; + } + } + + /* Ciphers supported */ + if (!WPACKET_start_sub_packet_u16(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, + ERR_R_INTERNAL_ERROR); + return 0; + } + + if (!ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), pkt)) { + /* SSLfatal() already called */ + return 0; + } + if (!WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, + ERR_R_INTERNAL_ERROR); + return 0; + } + + /* COMPRESSION */ + if (!WPACKET_start_sub_packet_u8(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, + ERR_R_INTERNAL_ERROR); + return 0; + } +#ifndef OPENSSL_NO_COMP + if (ssl_allow_compression(s) + && s->ctx->comp_methods + && (SSL_IS_DTLS(s) || s->s3->tmp.max_ver < TLS1_3_VERSION)) { + int compnum = sk_SSL_COMP_num(s->ctx->comp_methods); + for (i = 0; i < compnum; i++) { + comp = sk_SSL_COMP_value(s->ctx->comp_methods, i); + if (!WPACKET_put_bytes_u8(pkt, comp->id)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, + ERR_R_INTERNAL_ERROR); + return 0; + } + } + } +#endif + /* Add the NULL method */ + if (!WPACKET_put_bytes_u8(pkt, 0) || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, + ERR_R_INTERNAL_ERROR); + return 0; + } + + /* TLS extensions */ + if (!tls_construct_extensions(s, pkt, SSL_EXT_CLIENT_HELLO, NULL, 0)) { + /* SSLfatal() already called */ + return 0; + } + + return 1; +} + +MSG_PROCESS_RETURN dtls_process_hello_verify(SSL *s, PACKET *pkt) +{ + size_t cookie_len; + PACKET cookiepkt; + + if (!PACKET_forward(pkt, 2) + || !PACKET_get_length_prefixed_1(pkt, &cookiepkt)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_DTLS_PROCESS_HELLO_VERIFY, + SSL_R_LENGTH_MISMATCH); + return MSG_PROCESS_ERROR; + } + + cookie_len = PACKET_remaining(&cookiepkt); + if (cookie_len > sizeof(s->d1->cookie)) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_DTLS_PROCESS_HELLO_VERIFY, + SSL_R_LENGTH_TOO_LONG); + return MSG_PROCESS_ERROR; + } + + if (!PACKET_copy_bytes(&cookiepkt, s->d1->cookie, cookie_len)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_DTLS_PROCESS_HELLO_VERIFY, + SSL_R_LENGTH_MISMATCH); + return MSG_PROCESS_ERROR; + } + s->d1->cookie_len = cookie_len; + + return MSG_PROCESS_FINISHED_READING; +} + +static int set_client_ciphersuite(SSL *s, const unsigned char *cipherchars) +{ + STACK_OF(SSL_CIPHER) *sk; + const SSL_CIPHER *c; + int i; + + c = ssl_get_cipher_by_char(s, cipherchars, 0); + if (c == NULL) { + /* unknown cipher */ + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE, + SSL_R_UNKNOWN_CIPHER_RETURNED); + return 0; + } + /* + * If it is a disabled cipher we either didn't send it in client hello, + * or it's not allowed for the selected protocol. So we return an error. + */ + if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_CHECK, 1)) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE, + SSL_R_WRONG_CIPHER_RETURNED); + return 0; + } + + sk = ssl_get_ciphers_by_id(s); + i = sk_SSL_CIPHER_find(sk, c); + if (i < 0) { + /* we did not say we would use this cipher */ + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE, + SSL_R_WRONG_CIPHER_RETURNED); + return 0; + } + + if (SSL_IS_TLS13(s) && s->s3->tmp.new_cipher != NULL + && s->s3->tmp.new_cipher->id != c->id) { + /* ServerHello selected a different ciphersuite to that in the HRR */ + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE, + SSL_R_WRONG_CIPHER_RETURNED); + return 0; + } + + /* + * Depending on the session caching (internal/external), the cipher + * and/or cipher_id values may not be set. Make sure that cipher_id is + * set and use it for comparison. + */ + if (s->session->cipher != NULL) + s->session->cipher_id = s->session->cipher->id; + if (s->hit && (s->session->cipher_id != c->id)) { + if (SSL_IS_TLS13(s)) { + /* + * In TLSv1.3 it is valid for the server to select a different + * ciphersuite as long as the hash is the same. + */ + if (ssl_md(c->algorithm2) + != ssl_md(s->session->cipher->algorithm2)) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_SET_CLIENT_CIPHERSUITE, + SSL_R_CIPHERSUITE_DIGEST_HAS_CHANGED); + return 0; + } + } else { + /* + * Prior to TLSv1.3 resuming a session always meant using the same + * ciphersuite. + */ + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE, + SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED); + return 0; + } + } + s->s3->tmp.new_cipher = c; + + return 1; +} + +MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt) +{ + PACKET session_id, extpkt; + size_t session_id_len; + const unsigned char *cipherchars; + int hrr = 0; + unsigned int compression; + unsigned int sversion; + unsigned int context; + RAW_EXTENSION *extensions = NULL; +#ifndef OPENSSL_NO_COMP + SSL_COMP *comp; +#endif + + if (!PACKET_get_net_2(pkt, &sversion)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + /* load the server random */ + if (s->version == TLS1_3_VERSION + && sversion == TLS1_2_VERSION + && PACKET_remaining(pkt) >= SSL3_RANDOM_SIZE + && memcmp(hrrrandom, PACKET_data(pkt), SSL3_RANDOM_SIZE) == 0) { + s->hello_retry_request = SSL_HRR_PENDING; + hrr = 1; + if (!PACKET_forward(pkt, SSL3_RANDOM_SIZE)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO, + SSL_R_LENGTH_MISMATCH); + goto err; + } + } else { + if (!PACKET_copy_bytes(pkt, s->s3->server_random, SSL3_RANDOM_SIZE)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO, + SSL_R_LENGTH_MISMATCH); + goto err; + } + } + + /* Get the session-id. */ + if (!PACKET_get_length_prefixed_1(pkt, &session_id)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO, + SSL_R_LENGTH_MISMATCH); + goto err; + } + session_id_len = PACKET_remaining(&session_id); + if (session_id_len > sizeof(s->session->session_id) + || session_id_len > SSL3_SESSION_ID_SIZE) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO, + SSL_R_SSL3_SESSION_ID_TOO_LONG); + goto err; + } + + if (!PACKET_get_bytes(pkt, &cipherchars, TLS_CIPHER_LEN)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + if (!PACKET_get_1(pkt, &compression)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + /* TLS extensions */ + if (PACKET_remaining(pkt) == 0 && !hrr) { + PACKET_null_init(&extpkt); + } else if (!PACKET_as_length_prefixed_2(pkt, &extpkt) + || PACKET_remaining(pkt) != 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO, + SSL_R_BAD_LENGTH); + goto err; + } + + if (!hrr) { + if (!tls_collect_extensions(s, &extpkt, + SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_3_SERVER_HELLO, + &extensions, NULL, 1)) { + /* SSLfatal() already called */ + goto err; + } + + if (!ssl_choose_client_version(s, sversion, extensions)) { + /* SSLfatal() already called */ + goto err; + } + } + + if (SSL_IS_TLS13(s) || hrr) { + if (compression != 0) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PROCESS_SERVER_HELLO, + SSL_R_INVALID_COMPRESSION_ALGORITHM); + goto err; + } + + if (session_id_len != s->tmp_session_id_len + || memcmp(PACKET_data(&session_id), s->tmp_session_id, + session_id_len) != 0) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_INVALID_SESSION_ID); + goto err; + } + } + + if (hrr) { + if (!set_client_ciphersuite(s, cipherchars)) { + /* SSLfatal() already called */ + goto err; + } + + return tls_process_as_hello_retry_request(s, &extpkt); + } + + /* + * Now we have chosen the version we need to check again that the extensions + * are appropriate for this version. + */ + context = SSL_IS_TLS13(s) ? SSL_EXT_TLS1_3_SERVER_HELLO + : SSL_EXT_TLS1_2_SERVER_HELLO; + if (!tls_validate_all_contexts(s, context, extensions)) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO, + SSL_R_BAD_EXTENSION); + goto err; + } + + s->hit = 0; + + if (SSL_IS_TLS13(s)) { + /* + * In TLSv1.3 a ServerHello message signals a key change so the end of + * the message must be on a record boundary. + */ + if (RECORD_LAYER_processed_read_pending(&s->rlayer)) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, + SSL_F_TLS_PROCESS_SERVER_HELLO, + SSL_R_NOT_ON_RECORD_BOUNDARY); + goto err; + } + + /* This will set s->hit if we are resuming */ + if (!tls_parse_extension(s, TLSEXT_IDX_psk, + SSL_EXT_TLS1_3_SERVER_HELLO, + extensions, NULL, 0)) { + /* SSLfatal() already called */ + goto err; + } + } else { + /* + * Check if we can resume the session based on external pre-shared + * secret. EAP-FAST (RFC 4851) supports two types of session resumption. + * Resumption based on server-side state works with session IDs. + * Resumption based on pre-shared Protected Access Credentials (PACs) + * works by overriding the SessionTicket extension at the application + * layer, and does not send a session ID. (We do not know whether + * EAP-FAST servers would honour the session ID.) Therefore, the session + * ID alone is not a reliable indicator of session resumption, so we + * first check if we can resume, and later peek at the next handshake + * message to see if the server wants to resume. + */ + if (s->version >= TLS1_VERSION + && s->ext.session_secret_cb != NULL && s->session->ext.tick) { + const SSL_CIPHER *pref_cipher = NULL; + /* + * s->session->master_key_length is a size_t, but this is an int for + * backwards compat reasons + */ + int master_key_length; + master_key_length = sizeof(s->session->master_key); + if (s->ext.session_secret_cb(s, s->session->master_key, + &master_key_length, + NULL, &pref_cipher, + s->ext.session_secret_cb_arg) + && master_key_length > 0) { + s->session->master_key_length = master_key_length; + s->session->cipher = pref_cipher ? + pref_cipher : ssl_get_cipher_by_char(s, cipherchars, 0); + } else { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_SERVER_HELLO, ERR_R_INTERNAL_ERROR); + goto err; + } + } + + if (session_id_len != 0 + && session_id_len == s->session->session_id_length + && memcmp(PACKET_data(&session_id), s->session->session_id, + session_id_len) == 0) + s->hit = 1; + } + + if (s->hit) { + if (s->sid_ctx_length != s->session->sid_ctx_length + || memcmp(s->session->sid_ctx, s->sid_ctx, s->sid_ctx_length)) { + /* actually a client application bug */ + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PROCESS_SERVER_HELLO, + SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT); + goto err; + } + } else { + /* + * If we were trying for session-id reuse but the server + * didn't resume, make a new SSL_SESSION. + * In the case of EAP-FAST and PAC, we do not send a session ID, + * so the PAC-based session secret is always preserved. It'll be + * overwritten if the server refuses resumption. + */ + if (s->session->session_id_length > 0 + || (SSL_IS_TLS13(s) + && s->session->ext.tick_identity + != TLSEXT_PSK_BAD_IDENTITY)) { + tsan_counter(&s->session_ctx->stats.sess_miss); + if (!ssl_get_new_session(s, 0)) { + /* SSLfatal() already called */ + goto err; + } + } + + s->session->ssl_version = s->version; + /* + * In TLSv1.2 and below we save the session id we were sent so we can + * resume it later. In TLSv1.3 the session id we were sent is just an + * echo of what we originally sent in the ClientHello and should not be + * used for resumption. + */ + if (!SSL_IS_TLS13(s)) { + s->session->session_id_length = session_id_len; + /* session_id_len could be 0 */ + if (session_id_len > 0) + memcpy(s->session->session_id, PACKET_data(&session_id), + session_id_len); + } + } + + /* Session version and negotiated protocol version should match */ + if (s->version != s->session->ssl_version) { + SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_TLS_PROCESS_SERVER_HELLO, + SSL_R_SSL_SESSION_VERSION_MISMATCH); + goto err; + } + /* + * Now that we know the version, update the check to see if it's an allowed + * version. + */ + s->s3->tmp.min_ver = s->version; + s->s3->tmp.max_ver = s->version; + + if (!set_client_ciphersuite(s, cipherchars)) { + /* SSLfatal() already called */ + goto err; + } + +#ifdef OPENSSL_NO_COMP + if (compression != 0) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO, + SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM); + goto err; + } + /* + * If compression is disabled we'd better not try to resume a session + * using compression. + */ + if (s->session->compress_meth != 0) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PROCESS_SERVER_HELLO, + SSL_R_INCONSISTENT_COMPRESSION); + goto err; + } +#else + if (s->hit && compression != s->session->compress_meth) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO, + SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED); + goto err; + } + if (compression == 0) + comp = NULL; + else if (!ssl_allow_compression(s)) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO, + SSL_R_COMPRESSION_DISABLED); + goto err; + } else { + comp = ssl3_comp_find(s->ctx->comp_methods, compression); + } + + if (compression != 0 && comp == NULL) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO, + SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM); + goto err; + } else { + s->s3->tmp.new_compression = comp; + } +#endif + + if (!tls_parse_all_extensions(s, context, extensions, NULL, 0, 1)) { + /* SSLfatal() already called */ + goto err; + } + +#ifndef OPENSSL_NO_SCTP + if (SSL_IS_DTLS(s) && s->hit) { + unsigned char sctpauthkey[64]; + char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)]; + size_t labellen; + + /* + * Add new shared key for SCTP-Auth, will be ignored if + * no SCTP used. + */ + memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL, + sizeof(DTLS1_SCTP_AUTH_LABEL)); + + /* Don't include the terminating zero. */ + labellen = sizeof(labelbuffer) - 1; + if (s->mode & SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG) + labellen += 1; + + if (SSL_export_keying_material(s, sctpauthkey, + sizeof(sctpauthkey), + labelbuffer, + labellen, NULL, 0, 0) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO, + ERR_R_INTERNAL_ERROR); + goto err; + } + + BIO_ctrl(SSL_get_wbio(s), + BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY, + sizeof(sctpauthkey), sctpauthkey); + } +#endif + + /* + * In TLSv1.3 we have some post-processing to change cipher state, otherwise + * we're done with this message + */ + if (SSL_IS_TLS13(s) + && (!s->method->ssl3_enc->setup_key_block(s) + || !s->method->ssl3_enc->change_cipher_state(s, + SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_READ))) { + /* SSLfatal() already called */ + goto err; + } + + OPENSSL_free(extensions); + return MSG_PROCESS_CONTINUE_READING; + err: + OPENSSL_free(extensions); + return MSG_PROCESS_ERROR; +} + +static MSG_PROCESS_RETURN tls_process_as_hello_retry_request(SSL *s, + PACKET *extpkt) +{ + RAW_EXTENSION *extensions = NULL; + + /* + * If we were sending early_data then the enc_write_ctx is now invalid and + * should not be used. + */ + EVP_CIPHER_CTX_free(s->enc_write_ctx); + s->enc_write_ctx = NULL; + + if (!tls_collect_extensions(s, extpkt, SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST, + &extensions, NULL, 1) + || !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST, + extensions, NULL, 0, 1)) { + /* SSLfatal() already called */ + goto err; + } + + OPENSSL_free(extensions); + extensions = NULL; + + if (s->ext.tls13_cookie_len == 0 +#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH) + && s->s3->tmp.pkey != NULL +#endif + ) { + /* + * We didn't receive a cookie or a new key_share so the next + * ClientHello will not change + */ + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PROCESS_AS_HELLO_RETRY_REQUEST, + SSL_R_NO_CHANGE_FOLLOWING_HRR); + goto err; + } + + /* + * Re-initialise the Transcript Hash. We're going to prepopulate it with + * a synthetic message_hash in place of ClientHello1. + */ + if (!create_synthetic_message_hash(s, NULL, 0, NULL, 0)) { + /* SSLfatal() already called */ + goto err; + } + + /* + * Add this message to the Transcript Hash. Normally this is done + * automatically prior to the message processing stage. However due to the + * need to create the synthetic message hash, we defer that step until now + * for HRR messages. + */ + if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, + s->init_num + SSL3_HM_HEADER_LENGTH)) { + /* SSLfatal() already called */ + goto err; + } + + return MSG_PROCESS_FINISHED_READING; + err: + OPENSSL_free(extensions); + return MSG_PROCESS_ERROR; +} + +MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt) +{ + int i; + MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR; + unsigned long cert_list_len, cert_len; + X509 *x = NULL; + const unsigned char *certstart, *certbytes; + STACK_OF(X509) *sk = NULL; + EVP_PKEY *pkey = NULL; + size_t chainidx, certidx; + unsigned int context = 0; + const SSL_CERT_LOOKUP *clu; + + if ((sk = sk_X509_new_null()) == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, + ERR_R_MALLOC_FAILURE); + goto err; + } + + if ((SSL_IS_TLS13(s) && !PACKET_get_1(pkt, &context)) + || context != 0 + || !PACKET_get_net_3(pkt, &cert_list_len) + || PACKET_remaining(pkt) != cert_list_len + || PACKET_remaining(pkt) == 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, + SSL_R_LENGTH_MISMATCH); + goto err; + } + for (chainidx = 0; PACKET_remaining(pkt); chainidx++) { + if (!PACKET_get_net_3(pkt, &cert_len) + || !PACKET_get_bytes(pkt, &certbytes, cert_len)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, + SSL_R_CERT_LENGTH_MISMATCH); + goto err; + } + + certstart = certbytes; + x = d2i_X509(NULL, (const unsigned char **)&certbytes, cert_len); + if (x == NULL) { + SSLfatal(s, SSL_AD_BAD_CERTIFICATE, + SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, ERR_R_ASN1_LIB); + goto err; + } + if (certbytes != (certstart + cert_len)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, + SSL_R_CERT_LENGTH_MISMATCH); + goto err; + } + + if (SSL_IS_TLS13(s)) { + RAW_EXTENSION *rawexts = NULL; + PACKET extensions; + + if (!PACKET_get_length_prefixed_2(pkt, &extensions)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, + SSL_R_BAD_LENGTH); + goto err; + } + if (!tls_collect_extensions(s, &extensions, + SSL_EXT_TLS1_3_CERTIFICATE, &rawexts, + NULL, chainidx == 0) + || !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_CERTIFICATE, + rawexts, x, chainidx, + PACKET_remaining(pkt) == 0)) { + OPENSSL_free(rawexts); + /* SSLfatal already called */ + goto err; + } + OPENSSL_free(rawexts); + } + + if (!sk_X509_push(sk, x)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, + ERR_R_MALLOC_FAILURE); + goto err; + } + x = NULL; + } + + i = ssl_verify_cert_chain(s, sk); + /* + * The documented interface is that SSL_VERIFY_PEER should be set in order + * for client side verification of the server certificate to take place. + * However, historically the code has only checked that *any* flag is set + * to cause server verification to take place. Use of the other flags makes + * no sense in client mode. An attempt to clean up the semantics was + * reverted because at least one application *only* set + * SSL_VERIFY_FAIL_IF_NO_PEER_CERT. Prior to the clean up this still caused + * server verification to take place, after the clean up it silently did + * nothing. SSL_CTX_set_verify()/SSL_set_verify() cannot validate the flags + * sent to them because they are void functions. Therefore, we now use the + * (less clean) historic behaviour of performing validation if any flag is + * set. The *documented* interface remains the same. + */ + if (s->verify_mode != SSL_VERIFY_NONE && i <= 0) { + SSLfatal(s, ssl_x509err2alert(s->verify_result), + SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, + SSL_R_CERTIFICATE_VERIFY_FAILED); + goto err; + } + ERR_clear_error(); /* but we keep s->verify_result */ + if (i > 1) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, i); + goto err; + } + + s->session->peer_chain = sk; + /* + * Inconsistency alert: cert_chain does include the peer's certificate, + * which we don't include in statem_srvr.c + */ + x = sk_X509_value(sk, 0); + sk = NULL; + + pkey = X509_get0_pubkey(x); + + if (pkey == NULL || EVP_PKEY_missing_parameters(pkey)) { + x = NULL; + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, + SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS); + goto err; + } + + if ((clu = ssl_cert_lookup_by_pkey(pkey, &certidx)) == NULL) { + x = NULL; + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, + SSL_R_UNKNOWN_CERTIFICATE_TYPE); + goto err; + } + /* + * Check certificate type is consistent with ciphersuite. For TLS 1.3 + * skip check since TLS 1.3 ciphersuites can be used with any certificate + * type. + */ + if (!SSL_IS_TLS13(s)) { + if ((clu->amask & s->s3->tmp.new_cipher->algorithm_auth) == 0) { + x = NULL; + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, + SSL_R_WRONG_CERTIFICATE_TYPE); + goto err; + } + } + s->session->peer_type = certidx; + + X509_free(s->session->peer); + X509_up_ref(x); + s->session->peer = x; + s->session->verify_result = s->verify_result; + x = NULL; + + /* Save the current hash state for when we receive the CertificateVerify */ + if (SSL_IS_TLS13(s) + && !ssl_handshake_hash(s, s->cert_verify_hash, + sizeof(s->cert_verify_hash), + &s->cert_verify_hash_len)) { + /* SSLfatal() already called */; + goto err; + } + + ret = MSG_PROCESS_CONTINUE_READING; + + err: + X509_free(x); + sk_X509_pop_free(sk, X509_free); + return ret; +} + +static int tls_process_ske_psk_preamble(SSL *s, PACKET *pkt) +{ +#ifndef OPENSSL_NO_PSK + PACKET psk_identity_hint; + + /* PSK ciphersuites are preceded by an identity hint */ + + if (!PACKET_get_length_prefixed_2(pkt, &psk_identity_hint)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + /* + * Store PSK identity hint for later use, hint is used in + * tls_construct_client_key_exchange. Assume that the maximum length of + * a PSK identity hint can be as long as the maximum length of a PSK + * identity. + */ + if (PACKET_remaining(&psk_identity_hint) > PSK_MAX_IDENTITY_LEN) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE, + SSL_R_DATA_LENGTH_TOO_LONG); + return 0; + } + + if (PACKET_remaining(&psk_identity_hint) == 0) { + OPENSSL_free(s->session->psk_identity_hint); + s->session->psk_identity_hint = NULL; + } else if (!PACKET_strndup(&psk_identity_hint, + &s->session->psk_identity_hint)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE, + ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +#else + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE, + ERR_R_INTERNAL_ERROR); + return 0; +#endif +} + +static int tls_process_ske_srp(SSL *s, PACKET *pkt, EVP_PKEY **pkey) +{ +#ifndef OPENSSL_NO_SRP + PACKET prime, generator, salt, server_pub; + + if (!PACKET_get_length_prefixed_2(pkt, &prime) + || !PACKET_get_length_prefixed_2(pkt, &generator) + || !PACKET_get_length_prefixed_1(pkt, &salt) + || !PACKET_get_length_prefixed_2(pkt, &server_pub)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_SRP, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + /* TODO(size_t): Convert BN_bin2bn() calls */ + if ((s->srp_ctx.N = + BN_bin2bn(PACKET_data(&prime), + (int)PACKET_remaining(&prime), NULL)) == NULL + || (s->srp_ctx.g = + BN_bin2bn(PACKET_data(&generator), + (int)PACKET_remaining(&generator), NULL)) == NULL + || (s->srp_ctx.s = + BN_bin2bn(PACKET_data(&salt), + (int)PACKET_remaining(&salt), NULL)) == NULL + || (s->srp_ctx.B = + BN_bin2bn(PACKET_data(&server_pub), + (int)PACKET_remaining(&server_pub), NULL)) == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_SRP, + ERR_R_BN_LIB); + return 0; + } + + if (!srp_verify_server_param(s)) { + /* SSLfatal() already called */ + return 0; + } + + /* We must check if there is a certificate */ + if (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aRSA | SSL_aDSS)) + *pkey = X509_get0_pubkey(s->session->peer); + + return 1; +#else + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_SRP, + ERR_R_INTERNAL_ERROR); + return 0; +#endif +} + +static int tls_process_ske_dhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey) +{ +#ifndef OPENSSL_NO_DH + PACKET prime, generator, pub_key; + EVP_PKEY *peer_tmp = NULL; + + DH *dh = NULL; + BIGNUM *p = NULL, *g = NULL, *bnpub_key = NULL; + + int check_bits = 0; + + if (!PACKET_get_length_prefixed_2(pkt, &prime) + || !PACKET_get_length_prefixed_2(pkt, &generator) + || !PACKET_get_length_prefixed_2(pkt, &pub_key)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_DHE, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + peer_tmp = EVP_PKEY_new(); + dh = DH_new(); + + if (peer_tmp == NULL || dh == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE, + ERR_R_MALLOC_FAILURE); + goto err; + } + + /* TODO(size_t): Convert these calls */ + p = BN_bin2bn(PACKET_data(&prime), (int)PACKET_remaining(&prime), NULL); + g = BN_bin2bn(PACKET_data(&generator), (int)PACKET_remaining(&generator), + NULL); + bnpub_key = BN_bin2bn(PACKET_data(&pub_key), + (int)PACKET_remaining(&pub_key), NULL); + if (p == NULL || g == NULL || bnpub_key == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE, + ERR_R_BN_LIB); + goto err; + } + + /* test non-zero pubkey */ + if (BN_is_zero(bnpub_key)) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_DHE, + SSL_R_BAD_DH_VALUE); + goto err; + } + + if (!DH_set0_pqg(dh, p, NULL, g)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE, + ERR_R_BN_LIB); + goto err; + } + p = g = NULL; + + if (DH_check_params(dh, &check_bits) == 0 || check_bits != 0) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_DHE, + SSL_R_BAD_DH_VALUE); + goto err; + } + + if (!DH_set0_key(dh, bnpub_key, NULL)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE, + ERR_R_BN_LIB); + goto err; + } + bnpub_key = NULL; + + if (!ssl_security(s, SSL_SECOP_TMP_DH, DH_security_bits(dh), 0, dh)) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PROCESS_SKE_DHE, + SSL_R_DH_KEY_TOO_SMALL); + goto err; + } + + if (EVP_PKEY_assign_DH(peer_tmp, dh) == 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE, + ERR_R_EVP_LIB); + goto err; + } + + s->s3->peer_tmp = peer_tmp; + + /* + * FIXME: This makes assumptions about which ciphersuites come with + * public keys. We should have a less ad-hoc way of doing this + */ + if (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aRSA | SSL_aDSS)) + *pkey = X509_get0_pubkey(s->session->peer); + /* else anonymous DH, so no certificate or pkey. */ + + return 1; + + err: + BN_free(p); + BN_free(g); + BN_free(bnpub_key); + DH_free(dh); + EVP_PKEY_free(peer_tmp); + + return 0; +#else + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE, + ERR_R_INTERNAL_ERROR); + return 0; +#endif +} + +static int tls_process_ske_ecdhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey) +{ +#ifndef OPENSSL_NO_EC + PACKET encoded_pt; + unsigned int curve_type, curve_id; + + /* + * Extract elliptic curve parameters and the server's ephemeral ECDH + * public key. We only support named (not generic) curves and + * ECParameters in this case is just three bytes. + */ + if (!PACKET_get_1(pkt, &curve_type) || !PACKET_get_net_2(pkt, &curve_id)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE, + SSL_R_LENGTH_TOO_SHORT); + return 0; + } + /* + * Check curve is named curve type and one of our preferences, if not + * server has sent an invalid curve. + */ + if (curve_type != NAMED_CURVE_TYPE + || !tls1_check_group_id(s, curve_id, 1)) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_ECDHE, + SSL_R_WRONG_CURVE); + return 0; + } + + if ((s->s3->peer_tmp = ssl_generate_param_group(curve_id)) == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE, + SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS); + return 0; + } + + if (!PACKET_get_length_prefixed_1(pkt, &encoded_pt)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp, + PACKET_data(&encoded_pt), + PACKET_remaining(&encoded_pt))) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_ECDHE, + SSL_R_BAD_ECPOINT); + return 0; + } + + /* + * The ECC/TLS specification does not mention the use of DSA to sign + * ECParameters in the server key exchange message. We do support RSA + * and ECDSA. + */ + if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aECDSA) + *pkey = X509_get0_pubkey(s->session->peer); + else if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aRSA) + *pkey = X509_get0_pubkey(s->session->peer); + /* else anonymous ECDH, so no certificate or pkey. */ + + return 1; +#else + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE, + ERR_R_INTERNAL_ERROR); + return 0; +#endif +} + +MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt) +{ + long alg_k; + EVP_PKEY *pkey = NULL; + EVP_MD_CTX *md_ctx = NULL; + EVP_PKEY_CTX *pctx = NULL; + PACKET save_param_start, signature; + + alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + + save_param_start = *pkt; + +#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH) + EVP_PKEY_free(s->s3->peer_tmp); + s->s3->peer_tmp = NULL; +#endif + + if (alg_k & SSL_PSK) { + if (!tls_process_ske_psk_preamble(s, pkt)) { + /* SSLfatal() already called */ + goto err; + } + } + + /* Nothing else to do for plain PSK or RSAPSK */ + if (alg_k & (SSL_kPSK | SSL_kRSAPSK)) { + } else if (alg_k & SSL_kSRP) { + if (!tls_process_ske_srp(s, pkt, &pkey)) { + /* SSLfatal() already called */ + goto err; + } + } else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) { + if (!tls_process_ske_dhe(s, pkt, &pkey)) { + /* SSLfatal() already called */ + goto err; + } + } else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) { + if (!tls_process_ske_ecdhe(s, pkt, &pkey)) { + /* SSLfatal() already called */ + goto err; + } + } else if (alg_k) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_KEY_EXCHANGE, + SSL_R_UNEXPECTED_MESSAGE); + goto err; + } + + /* if it was signed, check the signature */ + if (pkey != NULL) { + PACKET params; + int maxsig; + const EVP_MD *md = NULL; + unsigned char *tbs; + size_t tbslen; + int rv; + + /* + * |pkt| now points to the beginning of the signature, so the difference + * equals the length of the parameters. + */ + if (!PACKET_get_sub_packet(&save_param_start, ¶ms, + PACKET_remaining(&save_param_start) - + PACKET_remaining(pkt))) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + if (SSL_USE_SIGALGS(s)) { + unsigned int sigalg; + + if (!PACKET_get_net_2(pkt, &sigalg)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE, + SSL_R_LENGTH_TOO_SHORT); + goto err; + } + if (tls12_check_peer_sigalg(s, sigalg, pkey) <=0) { + /* SSLfatal() already called */ + goto err; + } + } else if (!tls1_set_peer_legacy_sigalg(s, pkey)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + if (!tls1_lookup_md(s->s3->tmp.peer_sigalg, &md)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto err; + } +#ifdef SSL_DEBUG + if (SSL_USE_SIGALGS(s)) + fprintf(stderr, "USING TLSv1.2 HASH %s\n", + md == NULL ? "n/a" : EVP_MD_name(md)); +#endif + + if (!PACKET_get_length_prefixed_2(pkt, &signature) + || PACKET_remaining(pkt) != 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE, + SSL_R_LENGTH_MISMATCH); + goto err; + } + maxsig = EVP_PKEY_size(pkey); + if (maxsig < 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* + * Check signature length + */ + if (PACKET_remaining(&signature) > (size_t)maxsig) { + /* wrong packet length */ + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE, + SSL_R_WRONG_SIGNATURE_LENGTH); + goto err; + } + + md_ctx = EVP_MD_CTX_new(); + if (md_ctx == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE, + ERR_R_MALLOC_FAILURE); + goto err; + } + + if (EVP_DigestVerifyInit(md_ctx, &pctx, md, NULL, pkey) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE, + ERR_R_EVP_LIB); + goto err; + } + if (SSL_USE_PSS(s)) { + if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0 + || EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, + RSA_PSS_SALTLEN_DIGEST) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB); + goto err; + } + } + tbslen = construct_key_exchange_tbs(s, &tbs, PACKET_data(¶ms), + PACKET_remaining(¶ms)); + if (tbslen == 0) { + /* SSLfatal() already called */ + goto err; + } + + rv = EVP_DigestVerify(md_ctx, PACKET_data(&signature), + PACKET_remaining(&signature), tbs, tbslen); + OPENSSL_free(tbs); + if (rv <= 0) { + SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE, + SSL_R_BAD_SIGNATURE); + goto err; + } + EVP_MD_CTX_free(md_ctx); + md_ctx = NULL; + } else { + /* aNULL, aSRP or PSK do not need public keys */ + if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP)) + && !(alg_k & SSL_PSK)) { + /* Might be wrong key type, check it */ + if (ssl3_check_cert_and_algorithm(s)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE, + SSL_R_BAD_DATA); + } + /* else this shouldn't happen, SSLfatal() already called */ + goto err; + } + /* still data left over */ + if (PACKET_remaining(pkt) != 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE, + SSL_R_EXTRA_DATA_IN_MESSAGE); + goto err; + } + } + + return MSG_PROCESS_CONTINUE_READING; + err: + EVP_MD_CTX_free(md_ctx); + return MSG_PROCESS_ERROR; +} + +MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt) +{ + size_t i; + + /* Clear certificate validity flags */ + for (i = 0; i < SSL_PKEY_NUM; i++) + s->s3->tmp.valid_flags[i] = 0; + + if (SSL_IS_TLS13(s)) { + PACKET reqctx, extensions; + RAW_EXTENSION *rawexts = NULL; + + if ((s->shutdown & SSL_SENT_SHUTDOWN) != 0) { + /* + * We already sent close_notify. This can only happen in TLSv1.3 + * post-handshake messages. We can't reasonably respond to this, so + * we just ignore it + */ + return MSG_PROCESS_FINISHED_READING; + } + + /* Free and zero certificate types: it is not present in TLS 1.3 */ + OPENSSL_free(s->s3->tmp.ctype); + s->s3->tmp.ctype = NULL; + s->s3->tmp.ctype_len = 0; + OPENSSL_free(s->pha_context); + s->pha_context = NULL; + + if (!PACKET_get_length_prefixed_1(pkt, &reqctx) || + !PACKET_memdup(&reqctx, &s->pha_context, &s->pha_context_len)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, + SSL_R_LENGTH_MISMATCH); + return MSG_PROCESS_ERROR; + } + + if (!PACKET_get_length_prefixed_2(pkt, &extensions)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, + SSL_R_BAD_LENGTH); + return MSG_PROCESS_ERROR; + } + if (!tls_collect_extensions(s, &extensions, + SSL_EXT_TLS1_3_CERTIFICATE_REQUEST, + &rawexts, NULL, 1) + || !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_CERTIFICATE_REQUEST, + rawexts, NULL, 0, 1)) { + /* SSLfatal() already called */ + OPENSSL_free(rawexts); + return MSG_PROCESS_ERROR; + } + OPENSSL_free(rawexts); + if (!tls1_process_sigalgs(s)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, + SSL_R_BAD_LENGTH); + return MSG_PROCESS_ERROR; + } + } else { + PACKET ctypes; + + /* get the certificate types */ + if (!PACKET_get_length_prefixed_1(pkt, &ctypes)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, + SSL_R_LENGTH_MISMATCH); + return MSG_PROCESS_ERROR; + } + + if (!PACKET_memdup(&ctypes, &s->s3->tmp.ctype, &s->s3->tmp.ctype_len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, + ERR_R_INTERNAL_ERROR); + return MSG_PROCESS_ERROR; + } + + if (SSL_USE_SIGALGS(s)) { + PACKET sigalgs; + + if (!PACKET_get_length_prefixed_2(pkt, &sigalgs)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, + SSL_R_LENGTH_MISMATCH); + return MSG_PROCESS_ERROR; + } + + /* + * Despite this being for certificates, preserve compatibility + * with pre-TLS 1.3 and use the regular sigalgs field. + */ + if (!tls1_save_sigalgs(s, &sigalgs, 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, + SSL_R_SIGNATURE_ALGORITHMS_ERROR); + return MSG_PROCESS_ERROR; + } + if (!tls1_process_sigalgs(s)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, + ERR_R_MALLOC_FAILURE); + return MSG_PROCESS_ERROR; + } + } + + /* get the CA RDNs */ + if (!parse_ca_names(s, pkt)) { + /* SSLfatal() already called */ + return MSG_PROCESS_ERROR; + } + } + + if (PACKET_remaining(pkt) != 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, + SSL_R_LENGTH_MISMATCH); + return MSG_PROCESS_ERROR; + } + + /* we should setup a certificate to return.... */ + s->s3->tmp.cert_req = 1; + + /* + * In TLSv1.3 we don't prepare the client certificate yet. We wait until + * after the CertificateVerify message has been received. This is because + * in TLSv1.3 the CertificateRequest arrives before the Certificate message + * but in TLSv1.2 it is the other way around. We want to make sure that + * SSL_get_peer_certificate() returns something sensible in + * client_cert_cb. + */ + if (SSL_IS_TLS13(s) && s->post_handshake_auth != SSL_PHA_REQUESTED) + return MSG_PROCESS_CONTINUE_READING; + + return MSG_PROCESS_CONTINUE_PROCESSING; +} + +MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt) +{ + unsigned int ticklen; + unsigned long ticket_lifetime_hint, age_add = 0; + unsigned int sess_len; + RAW_EXTENSION *exts = NULL; + PACKET nonce; + + PACKET_null_init(&nonce); + + if (!PACKET_get_net_4(pkt, &ticket_lifetime_hint) + || (SSL_IS_TLS13(s) + && (!PACKET_get_net_4(pkt, &age_add) + || !PACKET_get_length_prefixed_1(pkt, &nonce))) + || !PACKET_get_net_2(pkt, &ticklen) + || (SSL_IS_TLS13(s) ? (ticklen == 0 || PACKET_remaining(pkt) < ticklen) + : PACKET_remaining(pkt) != ticklen)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + /* + * Server is allowed to change its mind (in <=TLSv1.2) and send an empty + * ticket. We already checked this TLSv1.3 case above, so it should never + * be 0 here in that instance + */ + if (ticklen == 0) + return MSG_PROCESS_CONTINUE_READING; + + /* + * Sessions must be immutable once they go into the session cache. Otherwise + * we can get multi-thread problems. Therefore we don't "update" sessions, + * we replace them with a duplicate. In TLSv1.3 we need to do this every + * time a NewSessionTicket arrives because those messages arrive + * post-handshake and the session may have already gone into the session + * cache. + */ + if (SSL_IS_TLS13(s) || s->session->session_id_length > 0) { + SSL_SESSION *new_sess; + + /* + * We reused an existing session, so we need to replace it with a new + * one + */ + if ((new_sess = ssl_session_dup(s->session, 0)) == 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, + ERR_R_MALLOC_FAILURE); + goto err; + } + + if ((s->session_ctx->session_cache_mode & SSL_SESS_CACHE_CLIENT) != 0 + && !SSL_IS_TLS13(s)) { + /* + * In TLSv1.2 and below the arrival of a new tickets signals that + * any old ticket we were using is now out of date, so we remove the + * old session from the cache. We carry on if this fails + */ + SSL_CTX_remove_session(s->session_ctx, s->session); + } + + SSL_SESSION_free(s->session); + s->session = new_sess; + } + + /* + * Technically the cast to long here is not guaranteed by the C standard - + * but we use it elsewhere, so this should be ok. + */ + s->session->time = (long)time(NULL); + + OPENSSL_free(s->session->ext.tick); + s->session->ext.tick = NULL; + s->session->ext.ticklen = 0; + + s->session->ext.tick = OPENSSL_malloc(ticklen); + if (s->session->ext.tick == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, + ERR_R_MALLOC_FAILURE); + goto err; + } + if (!PACKET_copy_bytes(pkt, s->session->ext.tick, ticklen)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + s->session->ext.tick_lifetime_hint = ticket_lifetime_hint; + s->session->ext.tick_age_add = age_add; + s->session->ext.ticklen = ticklen; + + if (SSL_IS_TLS13(s)) { + PACKET extpkt; + + if (!PACKET_as_length_prefixed_2(pkt, &extpkt) + || PACKET_remaining(pkt) != 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + if (!tls_collect_extensions(s, &extpkt, + SSL_EXT_TLS1_3_NEW_SESSION_TICKET, &exts, + NULL, 1) + || !tls_parse_all_extensions(s, + SSL_EXT_TLS1_3_NEW_SESSION_TICKET, + exts, NULL, 0, 1)) { + /* SSLfatal() already called */ + goto err; + } + } + + /* + * There are two ways to detect a resumed ticket session. One is to set + * an appropriate session ID and then the server must return a match in + * ServerHello. This allows the normal client session ID matching to work + * and we know much earlier that the ticket has been accepted. The + * other way is to set zero length session ID when the ticket is + * presented and rely on the handshake to determine session resumption. + * We choose the former approach because this fits in with assumptions + * elsewhere in OpenSSL. The session ID is set to the SHA256 (or SHA1 is + * SHA256 is disabled) hash of the ticket. + */ + /* + * TODO(size_t): we use sess_len here because EVP_Digest expects an int + * but s->session->session_id_length is a size_t + */ + if (!EVP_Digest(s->session->ext.tick, ticklen, + s->session->session_id, &sess_len, + EVP_sha256(), NULL)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, + ERR_R_EVP_LIB); + goto err; + } + s->session->session_id_length = sess_len; + s->session->not_resumable = 0; + + /* This is a standalone message in TLSv1.3, so there is no more to read */ + if (SSL_IS_TLS13(s)) { + const EVP_MD *md = ssl_handshake_md(s); + int hashleni = EVP_MD_size(md); + size_t hashlen; + static const unsigned char nonce_label[] = "resumption"; + + /* Ensure cast to size_t is safe */ + if (!ossl_assert(hashleni >= 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, + ERR_R_INTERNAL_ERROR); + goto err; + } + hashlen = (size_t)hashleni; + + if (!tls13_hkdf_expand(s, md, s->resumption_master_secret, + nonce_label, + sizeof(nonce_label) - 1, + PACKET_data(&nonce), + PACKET_remaining(&nonce), + s->session->master_key, + hashlen, 1)) { + /* SSLfatal() already called */ + goto err; + } + s->session->master_key_length = hashlen; + + OPENSSL_free(exts); + ssl_update_cache(s, SSL_SESS_CACHE_CLIENT); + return MSG_PROCESS_FINISHED_READING; + } + + return MSG_PROCESS_CONTINUE_READING; + err: + OPENSSL_free(exts); + return MSG_PROCESS_ERROR; +} + +/* + * In TLSv1.3 this is called from the extensions code, otherwise it is used to + * parse a separate message. Returns 1 on success or 0 on failure + */ +int tls_process_cert_status_body(SSL *s, PACKET *pkt) +{ + size_t resplen; + unsigned int type; + + if (!PACKET_get_1(pkt, &type) + || type != TLSEXT_STATUSTYPE_ocsp) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY, + SSL_R_UNSUPPORTED_STATUS_TYPE); + return 0; + } + if (!PACKET_get_net_3_len(pkt, &resplen) + || PACKET_remaining(pkt) != resplen) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY, + SSL_R_LENGTH_MISMATCH); + return 0; + } + s->ext.ocsp.resp = OPENSSL_malloc(resplen); + if (s->ext.ocsp.resp == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY, + ERR_R_MALLOC_FAILURE); + return 0; + } + if (!PACKET_copy_bytes(pkt, s->ext.ocsp.resp, resplen)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY, + SSL_R_LENGTH_MISMATCH); + return 0; + } + s->ext.ocsp.resp_len = resplen; + + return 1; +} + + +MSG_PROCESS_RETURN tls_process_cert_status(SSL *s, PACKET *pkt) +{ + if (!tls_process_cert_status_body(s, pkt)) { + /* SSLfatal() already called */ + return MSG_PROCESS_ERROR; + } + + return MSG_PROCESS_CONTINUE_READING; +} + +/* + * Perform miscellaneous checks and processing after we have received the + * server's initial flight. In TLS1.3 this is after the Server Finished message. + * In <=TLS1.2 this is after the ServerDone message. Returns 1 on success or 0 + * on failure. + */ +int tls_process_initial_server_flight(SSL *s) +{ + /* + * at this point we check that we have the required stuff from + * the server + */ + if (!ssl3_check_cert_and_algorithm(s)) { + /* SSLfatal() already called */ + return 0; + } + + /* + * Call the ocsp status callback if needed. The |ext.ocsp.resp| and + * |ext.ocsp.resp_len| values will be set if we actually received a status + * message, or NULL and -1 otherwise + */ + if (s->ext.status_type != TLSEXT_STATUSTYPE_nothing + && s->ctx->ext.status_cb != NULL) { + int ret = s->ctx->ext.status_cb(s, s->ctx->ext.status_arg); + + if (ret == 0) { + SSLfatal(s, SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE, + SSL_F_TLS_PROCESS_INITIAL_SERVER_FLIGHT, + SSL_R_INVALID_STATUS_RESPONSE); + return 0; + } + if (ret < 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_INITIAL_SERVER_FLIGHT, + ERR_R_MALLOC_FAILURE); + return 0; + } + } +#ifndef OPENSSL_NO_CT + if (s->ct_validation_callback != NULL) { + /* Note we validate the SCTs whether or not we abort on error */ + if (!ssl_validate_ct(s) && (s->verify_mode & SSL_VERIFY_PEER)) { + /* SSLfatal() already called */ + return 0; + } + } +#endif + + return 1; +} + +MSG_PROCESS_RETURN tls_process_server_done(SSL *s, PACKET *pkt) +{ + if (PACKET_remaining(pkt) > 0) { + /* should contain no data */ + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_DONE, + SSL_R_LENGTH_MISMATCH); + return MSG_PROCESS_ERROR; + } +#ifndef OPENSSL_NO_SRP + if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) { + if (SRP_Calc_A_param(s) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_DONE, + SSL_R_SRP_A_CALC); + return MSG_PROCESS_ERROR; + } + } +#endif + + if (!tls_process_initial_server_flight(s)) { + /* SSLfatal() already called */ + return MSG_PROCESS_ERROR; + } + + return MSG_PROCESS_FINISHED_READING; +} + +static int tls_construct_cke_psk_preamble(SSL *s, WPACKET *pkt) +{ +#ifndef OPENSSL_NO_PSK + int ret = 0; + /* + * The callback needs PSK_MAX_IDENTITY_LEN + 1 bytes to return a + * \0-terminated identity. The last byte is for us for simulating + * strnlen. + */ + char identity[PSK_MAX_IDENTITY_LEN + 1]; + size_t identitylen = 0; + unsigned char psk[PSK_MAX_PSK_LEN]; + unsigned char *tmppsk = NULL; + char *tmpidentity = NULL; + size_t psklen = 0; + + if (s->psk_client_callback == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, + SSL_R_PSK_NO_CLIENT_CB); + goto err; + } + + memset(identity, 0, sizeof(identity)); + + psklen = s->psk_client_callback(s, s->session->psk_identity_hint, + identity, sizeof(identity) - 1, + psk, sizeof(psk)); + + if (psklen > PSK_MAX_PSK_LEN) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR); + goto err; + } else if (psklen == 0) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, + SSL_R_PSK_IDENTITY_NOT_FOUND); + goto err; + } + + identitylen = strlen(identity); + if (identitylen > PSK_MAX_IDENTITY_LEN) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + tmppsk = OPENSSL_memdup(psk, psklen); + tmpidentity = OPENSSL_strdup(identity); + if (tmppsk == NULL || tmpidentity == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, + ERR_R_MALLOC_FAILURE); + goto err; + } + + OPENSSL_free(s->s3->tmp.psk); + s->s3->tmp.psk = tmppsk; + s->s3->tmp.psklen = psklen; + tmppsk = NULL; + OPENSSL_free(s->session->psk_identity); + s->session->psk_identity = tmpidentity; + tmpidentity = NULL; + + if (!WPACKET_sub_memcpy_u16(pkt, identity, identitylen)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + ret = 1; + + err: + OPENSSL_cleanse(psk, psklen); + OPENSSL_cleanse(identity, sizeof(identity)); + OPENSSL_clear_free(tmppsk, psklen); + OPENSSL_clear_free(tmpidentity, identitylen); + + return ret; +#else + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, + ERR_R_INTERNAL_ERROR); + return 0; +#endif +} + +static int tls_construct_cke_rsa(SSL *s, WPACKET *pkt) +{ +#ifndef OPENSSL_NO_RSA + unsigned char *encdata = NULL; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *pctx = NULL; + size_t enclen; + unsigned char *pms = NULL; + size_t pmslen = 0; + + if (s->session->peer == NULL) { + /* + * We should always have a server certificate with SSL_kRSA. + */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA, + ERR_R_INTERNAL_ERROR); + return 0; + } + + pkey = X509_get0_pubkey(s->session->peer); + if (EVP_PKEY_get0_RSA(pkey) == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA, + ERR_R_INTERNAL_ERROR); + return 0; + } + + pmslen = SSL_MAX_MASTER_KEY_LENGTH; + pms = OPENSSL_malloc(pmslen); + if (pms == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA, + ERR_R_MALLOC_FAILURE); + return 0; + } + + pms[0] = s->client_version >> 8; + pms[1] = s->client_version & 0xff; + /* TODO(size_t): Convert this function */ + if (RAND_bytes(pms + 2, (int)(pmslen - 2)) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA, + ERR_R_MALLOC_FAILURE); + goto err; + } + + /* Fix buf for TLS and beyond */ + if (s->version > SSL3_VERSION && !WPACKET_start_sub_packet_u16(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA, + ERR_R_INTERNAL_ERROR); + goto err; + } + pctx = EVP_PKEY_CTX_new(pkey, NULL); + if (pctx == NULL || EVP_PKEY_encrypt_init(pctx) <= 0 + || EVP_PKEY_encrypt(pctx, NULL, &enclen, pms, pmslen) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA, + ERR_R_EVP_LIB); + goto err; + } + if (!WPACKET_allocate_bytes(pkt, enclen, &encdata) + || EVP_PKEY_encrypt(pctx, encdata, &enclen, pms, pmslen) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA, + SSL_R_BAD_RSA_ENCRYPT); + goto err; + } + EVP_PKEY_CTX_free(pctx); + pctx = NULL; + + /* Fix buf for TLS and beyond */ + if (s->version > SSL3_VERSION && !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* Log the premaster secret, if logging is enabled. */ + if (!ssl_log_rsa_client_key_exchange(s, encdata, enclen, pms, pmslen)) { + /* SSLfatal() already called */ + goto err; + } + + s->s3->tmp.pms = pms; + s->s3->tmp.pmslen = pmslen; + + return 1; + err: + OPENSSL_clear_free(pms, pmslen); + EVP_PKEY_CTX_free(pctx); + + return 0; +#else + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA, + ERR_R_INTERNAL_ERROR); + return 0; +#endif +} + +static int tls_construct_cke_dhe(SSL *s, WPACKET *pkt) +{ +#ifndef OPENSSL_NO_DH + DH *dh_clnt = NULL; + const BIGNUM *pub_key; + EVP_PKEY *ckey = NULL, *skey = NULL; + unsigned char *keybytes = NULL; + + skey = s->s3->peer_tmp; + if (skey == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + ckey = ssl_generate_pkey(skey); + if (ckey == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + dh_clnt = EVP_PKEY_get0_DH(ckey); + + if (dh_clnt == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + if (ssl_derive(s, ckey, skey, 0) == 0) { + /* SSLfatal() already called */ + goto err; + } + + /* send off the data */ + DH_get0_key(dh_clnt, &pub_key, NULL); + if (!WPACKET_sub_allocate_bytes_u16(pkt, BN_num_bytes(pub_key), + &keybytes)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + BN_bn2bin(pub_key, keybytes); + EVP_PKEY_free(ckey); + + return 1; + err: + EVP_PKEY_free(ckey); + return 0; +#else + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE, + ERR_R_INTERNAL_ERROR); + return 0; +#endif +} + +static int tls_construct_cke_ecdhe(SSL *s, WPACKET *pkt) +{ +#ifndef OPENSSL_NO_EC + unsigned char *encodedPoint = NULL; + size_t encoded_pt_len = 0; + EVP_PKEY *ckey = NULL, *skey = NULL; + int ret = 0; + + skey = s->s3->peer_tmp; + if (skey == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE, + ERR_R_INTERNAL_ERROR); + return 0; + } + + ckey = ssl_generate_pkey(skey); + if (ckey == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE, + ERR_R_MALLOC_FAILURE); + goto err; + } + + if (ssl_derive(s, ckey, skey, 0) == 0) { + /* SSLfatal() already called */ + goto err; + } + + /* Generate encoding of client key */ + encoded_pt_len = EVP_PKEY_get1_tls_encodedpoint(ckey, &encodedPoint); + + if (encoded_pt_len == 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE, + ERR_R_EC_LIB); + goto err; + } + + if (!WPACKET_sub_memcpy_u8(pkt, encodedPoint, encoded_pt_len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + ret = 1; + err: + OPENSSL_free(encodedPoint); + EVP_PKEY_free(ckey); + return ret; +#else + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE, + ERR_R_INTERNAL_ERROR); + return 0; +#endif +} + +static int tls_construct_cke_gost(SSL *s, WPACKET *pkt) +{ +#ifndef OPENSSL_NO_GOST + /* GOST key exchange message creation */ + EVP_PKEY_CTX *pkey_ctx = NULL; + X509 *peer_cert; + size_t msglen; + unsigned int md_len; + unsigned char shared_ukm[32], tmp[256]; + EVP_MD_CTX *ukm_hash = NULL; + int dgst_nid = NID_id_GostR3411_94; + unsigned char *pms = NULL; + size_t pmslen = 0; + + if ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aGOST12) != 0) + dgst_nid = NID_id_GostR3411_2012_256; + + /* + * Get server certificate PKEY and create ctx from it + */ + peer_cert = s->session->peer; + if (!peer_cert) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_CONSTRUCT_CKE_GOST, + SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER); + return 0; + } + + pkey_ctx = EVP_PKEY_CTX_new(X509_get0_pubkey(peer_cert), NULL); + if (pkey_ctx == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST, + ERR_R_MALLOC_FAILURE); + return 0; + } + /* + * If we have send a certificate, and certificate key + * parameters match those of server certificate, use + * certificate key for key exchange + */ + + /* Otherwise, generate ephemeral key pair */ + pmslen = 32; + pms = OPENSSL_malloc(pmslen); + if (pms == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST, + ERR_R_MALLOC_FAILURE); + goto err; + } + + if (EVP_PKEY_encrypt_init(pkey_ctx) <= 0 + /* Generate session key + * TODO(size_t): Convert this function + */ + || RAND_bytes(pms, (int)pmslen) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST, + ERR_R_INTERNAL_ERROR); + goto err; + }; + /* + * Compute shared IV and store it in algorithm-specific context + * data + */ + ukm_hash = EVP_MD_CTX_new(); + if (ukm_hash == NULL + || EVP_DigestInit(ukm_hash, EVP_get_digestbynid(dgst_nid)) <= 0 + || EVP_DigestUpdate(ukm_hash, s->s3->client_random, + SSL3_RANDOM_SIZE) <= 0 + || EVP_DigestUpdate(ukm_hash, s->s3->server_random, + SSL3_RANDOM_SIZE) <= 0 + || EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST, + ERR_R_INTERNAL_ERROR); + goto err; + } + EVP_MD_CTX_free(ukm_hash); + ukm_hash = NULL; + if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT, + EVP_PKEY_CTRL_SET_IV, 8, shared_ukm) < 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST, + SSL_R_LIBRARY_BUG); + goto err; + } + /* Make GOST keytransport blob message */ + /* + * Encapsulate it into sequence + */ + msglen = 255; + if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, pms, pmslen) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST, + SSL_R_LIBRARY_BUG); + goto err; + } + + if (!WPACKET_put_bytes_u8(pkt, V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED) + || (msglen >= 0x80 && !WPACKET_put_bytes_u8(pkt, 0x81)) + || !WPACKET_sub_memcpy_u8(pkt, tmp, msglen)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST, + ERR_R_INTERNAL_ERROR); + goto err; + } + + EVP_PKEY_CTX_free(pkey_ctx); + s->s3->tmp.pms = pms; + s->s3->tmp.pmslen = pmslen; + + return 1; + err: + EVP_PKEY_CTX_free(pkey_ctx); + OPENSSL_clear_free(pms, pmslen); + EVP_MD_CTX_free(ukm_hash); + return 0; +#else + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST, + ERR_R_INTERNAL_ERROR); + return 0; +#endif +} + +static int tls_construct_cke_srp(SSL *s, WPACKET *pkt) +{ +#ifndef OPENSSL_NO_SRP + unsigned char *abytes = NULL; + + if (s->srp_ctx.A == NULL + || !WPACKET_sub_allocate_bytes_u16(pkt, BN_num_bytes(s->srp_ctx.A), + &abytes)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_SRP, + ERR_R_INTERNAL_ERROR); + return 0; + } + BN_bn2bin(s->srp_ctx.A, abytes); + + OPENSSL_free(s->session->srp_username); + s->session->srp_username = OPENSSL_strdup(s->srp_ctx.login); + if (s->session->srp_username == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_SRP, + ERR_R_MALLOC_FAILURE); + return 0; + } + + return 1; +#else + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_SRP, + ERR_R_INTERNAL_ERROR); + return 0; +#endif +} + +int tls_construct_client_key_exchange(SSL *s, WPACKET *pkt) +{ + unsigned long alg_k; + + alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + + /* + * All of the construct functions below call SSLfatal() if necessary so + * no need to do so here. + */ + if ((alg_k & SSL_PSK) + && !tls_construct_cke_psk_preamble(s, pkt)) + goto err; + + if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) { + if (!tls_construct_cke_rsa(s, pkt)) + goto err; + } else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) { + if (!tls_construct_cke_dhe(s, pkt)) + goto err; + } else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) { + if (!tls_construct_cke_ecdhe(s, pkt)) + goto err; + } else if (alg_k & SSL_kGOST) { + if (!tls_construct_cke_gost(s, pkt)) + goto err; + } else if (alg_k & SSL_kSRP) { + if (!tls_construct_cke_srp(s, pkt)) + goto err; + } else if (!(alg_k & SSL_kPSK)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); + goto err; + } + + return 1; + err: + OPENSSL_clear_free(s->s3->tmp.pms, s->s3->tmp.pmslen); + s->s3->tmp.pms = NULL; +#ifndef OPENSSL_NO_PSK + OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen); + s->s3->tmp.psk = NULL; +#endif + return 0; +} + +int tls_client_key_exchange_post_work(SSL *s) +{ + unsigned char *pms = NULL; + size_t pmslen = 0; + + pms = s->s3->tmp.pms; + pmslen = s->s3->tmp.pmslen; + +#ifndef OPENSSL_NO_SRP + /* Check for SRP */ + if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) { + if (!srp_generate_client_master_secret(s)) { + /* SSLfatal() already called */ + goto err; + } + return 1; + } +#endif + + if (pms == NULL && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!ssl_generate_master_secret(s, pms, pmslen, 1)) { + /* SSLfatal() already called */ + /* ssl_generate_master_secret frees the pms even on error */ + pms = NULL; + pmslen = 0; + goto err; + } + pms = NULL; + pmslen = 0; + +#ifndef OPENSSL_NO_SCTP + if (SSL_IS_DTLS(s)) { + unsigned char sctpauthkey[64]; + char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)]; + size_t labellen; + + /* + * Add new shared key for SCTP-Auth, will be ignored if no SCTP + * used. + */ + memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL, + sizeof(DTLS1_SCTP_AUTH_LABEL)); + + /* Don't include the terminating zero. */ + labellen = sizeof(labelbuffer) - 1; + if (s->mode & SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG) + labellen += 1; + + if (SSL_export_keying_material(s, sctpauthkey, + sizeof(sctpauthkey), labelbuffer, + labellen, NULL, 0, 0) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK, + ERR_R_INTERNAL_ERROR); + goto err; + } + + BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY, + sizeof(sctpauthkey), sctpauthkey); + } +#endif + + return 1; + err: + OPENSSL_clear_free(pms, pmslen); + s->s3->tmp.pms = NULL; + return 0; +} + +/* + * Check a certificate can be used for client authentication. Currently check + * cert exists, if we have a suitable digest for TLS 1.2 if static DH client + * certificates can be used and optionally checks suitability for Suite B. + */ +static int ssl3_check_client_certificate(SSL *s) +{ + /* If no suitable signature algorithm can't use certificate */ + if (!tls_choose_sigalg(s, 0) || s->s3->tmp.sigalg == NULL) + return 0; + /* + * If strict mode check suitability of chain before using it. This also + * adjusts suite B digest if necessary. + */ + if (s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT && + !tls1_check_chain(s, NULL, NULL, NULL, -2)) + return 0; + return 1; +} + +WORK_STATE tls_prepare_client_certificate(SSL *s, WORK_STATE wst) +{ + X509 *x509 = NULL; + EVP_PKEY *pkey = NULL; + int i; + + if (wst == WORK_MORE_A) { + /* Let cert callback update client certificates if required */ + if (s->cert->cert_cb) { + i = s->cert->cert_cb(s, s->cert->cert_cb_arg); + if (i < 0) { + s->rwstate = SSL_X509_LOOKUP; + return WORK_MORE_A; + } + if (i == 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE, + SSL_R_CALLBACK_FAILED); + return WORK_ERROR; + } + s->rwstate = SSL_NOTHING; + } + if (ssl3_check_client_certificate(s)) { + if (s->post_handshake_auth == SSL_PHA_REQUESTED) { + return WORK_FINISHED_STOP; + } + return WORK_FINISHED_CONTINUE; + } + + /* Fall through to WORK_MORE_B */ + wst = WORK_MORE_B; + } + + /* We need to get a client cert */ + if (wst == WORK_MORE_B) { + /* + * If we get an error, we need to ssl->rwstate=SSL_X509_LOOKUP; + * return(-1); We then get retied later + */ + i = ssl_do_client_cert_cb(s, &x509, &pkey); + if (i < 0) { + s->rwstate = SSL_X509_LOOKUP; + return WORK_MORE_B; + } + s->rwstate = SSL_NOTHING; + if ((i == 1) && (pkey != NULL) && (x509 != NULL)) { + if (!SSL_use_certificate(s, x509) || !SSL_use_PrivateKey(s, pkey)) + i = 0; + } else if (i == 1) { + i = 0; + SSLerr(SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE, + SSL_R_BAD_DATA_RETURNED_BY_CALLBACK); + } + + X509_free(x509); + EVP_PKEY_free(pkey); + if (i && !ssl3_check_client_certificate(s)) + i = 0; + if (i == 0) { + if (s->version == SSL3_VERSION) { + s->s3->tmp.cert_req = 0; + ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_CERTIFICATE); + return WORK_FINISHED_CONTINUE; + } else { + s->s3->tmp.cert_req = 2; + if (!ssl3_digest_cached_records(s, 0)) { + /* SSLfatal() already called */ + return WORK_ERROR; + } + } + } + + if (s->post_handshake_auth == SSL_PHA_REQUESTED) + return WORK_FINISHED_STOP; + return WORK_FINISHED_CONTINUE; + } + + /* Shouldn't ever get here */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE, + ERR_R_INTERNAL_ERROR); + return WORK_ERROR; +} + +int tls_construct_client_certificate(SSL *s, WPACKET *pkt) +{ + if (SSL_IS_TLS13(s)) { + if (s->pha_context == NULL) { + /* no context available, add 0-length context */ + if (!WPACKET_put_bytes_u8(pkt, 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR); + return 0; + } + } else if (!WPACKET_sub_memcpy_u8(pkt, s->pha_context, s->pha_context_len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR); + return 0; + } + } + if (!ssl3_output_cert_chain(s, pkt, + (s->s3->tmp.cert_req == 2) ? NULL + : s->cert->key)) { + /* SSLfatal() already called */ + return 0; + } + + if (SSL_IS_TLS13(s) + && SSL_IS_FIRST_HANDSHAKE(s) + && (!s->method->ssl3_enc->change_cipher_state(s, + SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_WRITE))) { + /* + * This is a fatal error, which leaves enc_write_ctx in an inconsistent + * state and thus ssl3_send_alert may crash. + */ + SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE, + SSL_R_CANNOT_CHANGE_CIPHER); + return 0; + } + + return 1; +} + +int ssl3_check_cert_and_algorithm(SSL *s) +{ + const SSL_CERT_LOOKUP *clu; + size_t idx; + long alg_k, alg_a; + + alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + alg_a = s->s3->tmp.new_cipher->algorithm_auth; + + /* we don't have a certificate */ + if (!(alg_a & SSL_aCERT)) + return 1; + + /* This is the passed certificate */ + clu = ssl_cert_lookup_by_pkey(X509_get0_pubkey(s->session->peer), &idx); + + /* Check certificate is recognised and suitable for cipher */ + if (clu == NULL || (alg_a & clu->amask) == 0) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, + SSL_R_MISSING_SIGNING_CERT); + return 0; + } + +#ifndef OPENSSL_NO_EC + if (clu->amask & SSL_aECDSA) { + if (ssl_check_srvr_ecc_cert_and_alg(s->session->peer, s)) + return 1; + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_BAD_ECC_CERT); + return 0; + } +#endif +#ifndef OPENSSL_NO_RSA + if (alg_k & (SSL_kRSA | SSL_kRSAPSK) && idx != SSL_PKEY_RSA) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, + SSL_R_MISSING_RSA_ENCRYPTING_CERT); + return 0; + } +#endif +#ifndef OPENSSL_NO_DH + if ((alg_k & SSL_kDHE) && (s->s3->peer_tmp == NULL)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, + ERR_R_INTERNAL_ERROR); + return 0; + } +#endif + + return 1; +} + +#ifndef OPENSSL_NO_NEXTPROTONEG +int tls_construct_next_proto(SSL *s, WPACKET *pkt) +{ + size_t len, padding_len; + unsigned char *padding = NULL; + + len = s->ext.npn_len; + padding_len = 32 - ((len + 2) % 32); + + if (!WPACKET_sub_memcpy_u8(pkt, s->ext.npn, len) + || !WPACKET_sub_allocate_bytes_u8(pkt, padding_len, &padding)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_NEXT_PROTO, + ERR_R_INTERNAL_ERROR); + return 0; + } + + memset(padding, 0, padding_len); + + return 1; +} +#endif + +MSG_PROCESS_RETURN tls_process_hello_req(SSL *s, PACKET *pkt) +{ + if (PACKET_remaining(pkt) > 0) { + /* should contain no data */ + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_HELLO_REQ, + SSL_R_LENGTH_MISMATCH); + return MSG_PROCESS_ERROR; + } + + if ((s->options & SSL_OP_NO_RENEGOTIATION)) { + ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION); + return MSG_PROCESS_FINISHED_READING; + } + + /* + * This is a historical discrepancy (not in the RFC) maintained for + * compatibility reasons. If a TLS client receives a HelloRequest it will + * attempt an abbreviated handshake. However if a DTLS client receives a + * HelloRequest it will do a full handshake. Either behaviour is reasonable + * but doing one for TLS and another for DTLS is odd. + */ + if (SSL_IS_DTLS(s)) + SSL_renegotiate(s); + else + SSL_renegotiate_abbreviated(s); + + return MSG_PROCESS_FINISHED_READING; +} + +static MSG_PROCESS_RETURN tls_process_encrypted_extensions(SSL *s, PACKET *pkt) +{ + PACKET extensions; + RAW_EXTENSION *rawexts = NULL; + + if (!PACKET_as_length_prefixed_2(pkt, &extensions) + || PACKET_remaining(pkt) != 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_ENCRYPTED_EXTENSIONS, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + if (!tls_collect_extensions(s, &extensions, + SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS, &rawexts, + NULL, 1) + || !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS, + rawexts, NULL, 0, 1)) { + /* SSLfatal() already called */ + goto err; + } + + OPENSSL_free(rawexts); + return MSG_PROCESS_CONTINUE_READING; + + err: + OPENSSL_free(rawexts); + return MSG_PROCESS_ERROR; +} + +int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey) +{ + int i = 0; +#ifndef OPENSSL_NO_ENGINE + if (s->ctx->client_cert_engine) { + i = ENGINE_load_ssl_client_cert(s->ctx->client_cert_engine, s, + SSL_get_client_CA_list(s), + px509, ppkey, NULL, NULL, NULL); + if (i != 0) + return i; + } +#endif + if (s->ctx->client_cert_cb) + i = s->ctx->client_cert_cb(s, px509, ppkey); + return i; +} + +int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, WPACKET *pkt) +{ + int i; + size_t totlen = 0, len, maxlen, maxverok = 0; + int empty_reneg_info_scsv = !s->renegotiate; + + /* Set disabled masks for this session */ + if (!ssl_set_client_disabled(s)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES, + SSL_R_NO_PROTOCOLS_AVAILABLE); + return 0; + } + + if (sk == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES, + ERR_R_INTERNAL_ERROR); + return 0; + } + +#ifdef OPENSSL_MAX_TLS1_2_CIPHER_LENGTH +# if OPENSSL_MAX_TLS1_2_CIPHER_LENGTH < 6 +# error Max cipher length too short +# endif + /* + * Some servers hang if client hello > 256 bytes as hack workaround + * chop number of supported ciphers to keep it well below this if we + * use TLS v1.2 + */ + if (TLS1_get_version(s) >= TLS1_2_VERSION) + maxlen = OPENSSL_MAX_TLS1_2_CIPHER_LENGTH & ~1; + else +#endif + /* Maximum length that can be stored in 2 bytes. Length must be even */ + maxlen = 0xfffe; + + if (empty_reneg_info_scsv) + maxlen -= 2; + if (s->mode & SSL_MODE_SEND_FALLBACK_SCSV) + maxlen -= 2; + + for (i = 0; i < sk_SSL_CIPHER_num(sk) && totlen < maxlen; i++) { + const SSL_CIPHER *c; + + c = sk_SSL_CIPHER_value(sk, i); + /* Skip disabled ciphers */ + if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED, 0)) + continue; + + if (!s->method->put_cipher_by_char(c, pkt, &len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES, + ERR_R_INTERNAL_ERROR); + return 0; + } + + /* Sanity check that the maximum version we offer has ciphers enabled */ + if (!maxverok) { + if (SSL_IS_DTLS(s)) { + if (DTLS_VERSION_GE(c->max_dtls, s->s3->tmp.max_ver) + && DTLS_VERSION_LE(c->min_dtls, s->s3->tmp.max_ver)) + maxverok = 1; + } else { + if (c->max_tls >= s->s3->tmp.max_ver + && c->min_tls <= s->s3->tmp.max_ver) + maxverok = 1; + } + } + + totlen += len; + } + + if (totlen == 0 || !maxverok) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES, + SSL_R_NO_CIPHERS_AVAILABLE); + + if (!maxverok) + ERR_add_error_data(1, "No ciphers enabled for max supported " + "SSL/TLS version"); + + return 0; + } + + if (totlen != 0) { + if (empty_reneg_info_scsv) { + static SSL_CIPHER scsv = { + 0, NULL, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + if (!s->method->put_cipher_by_char(&scsv, pkt, &len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_SSL_CIPHER_LIST_TO_BYTES, ERR_R_INTERNAL_ERROR); + return 0; + } + } + if (s->mode & SSL_MODE_SEND_FALLBACK_SCSV) { + static SSL_CIPHER scsv = { + 0, NULL, NULL, SSL3_CK_FALLBACK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + if (!s->method->put_cipher_by_char(&scsv, pkt, &len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_SSL_CIPHER_LIST_TO_BYTES, ERR_R_INTERNAL_ERROR); + return 0; + } + } + } + + return 1; +} + +int tls_construct_end_of_early_data(SSL *s, WPACKET *pkt) +{ + if (s->early_data_state != SSL_EARLY_DATA_WRITE_RETRY + && s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_END_OF_EARLY_DATA, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + s->early_data_state = SSL_EARLY_DATA_FINISHED_WRITING; + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_dtls.c b/trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_dtls.c new file mode 100644 index 000000000..b016fa7cf --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_dtls.c @@ -0,0 +1,1281 @@ +/* + * Copyright 2005-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "../ssl_locl.h" +#include "statem_locl.h" +#include "internal/cryptlib.h" +#include +#include +#include +#include + +#define RSMBLY_BITMASK_SIZE(msg_len) (((msg_len) + 7) / 8) + +#define RSMBLY_BITMASK_MARK(bitmask, start, end) { \ + if ((end) - (start) <= 8) { \ + long ii; \ + for (ii = (start); ii < (end); ii++) bitmask[((ii) >> 3)] |= (1 << ((ii) & 7)); \ + } else { \ + long ii; \ + bitmask[((start) >> 3)] |= bitmask_start_values[((start) & 7)]; \ + for (ii = (((start) >> 3) + 1); ii < ((((end) - 1)) >> 3); ii++) bitmask[ii] = 0xff; \ + bitmask[(((end) - 1) >> 3)] |= bitmask_end_values[((end) & 7)]; \ + } } + +#define RSMBLY_BITMASK_IS_COMPLETE(bitmask, msg_len, is_complete) { \ + long ii; \ + is_complete = 1; \ + if (bitmask[(((msg_len) - 1) >> 3)] != bitmask_end_values[((msg_len) & 7)]) is_complete = 0; \ + if (is_complete) for (ii = (((msg_len) - 1) >> 3) - 1; ii >= 0 ; ii--) \ + if (bitmask[ii] != 0xff) { is_complete = 0; break; } } + +static unsigned char bitmask_start_values[] = + { 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80 }; +static unsigned char bitmask_end_values[] = + { 0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f }; + +static void dtls1_fix_message_header(SSL *s, size_t frag_off, + size_t frag_len); +static unsigned char *dtls1_write_message_header(SSL *s, unsigned char *p); +static void dtls1_set_message_header_int(SSL *s, unsigned char mt, + size_t len, + unsigned short seq_num, + size_t frag_off, + size_t frag_len); +static int dtls_get_reassembled_message(SSL *s, int *errtype, size_t *len); + +static hm_fragment *dtls1_hm_fragment_new(size_t frag_len, int reassembly) +{ + hm_fragment *frag = NULL; + unsigned char *buf = NULL; + unsigned char *bitmask = NULL; + + if ((frag = OPENSSL_malloc(sizeof(*frag))) == NULL) { + SSLerr(SSL_F_DTLS1_HM_FRAGMENT_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (frag_len) { + if ((buf = OPENSSL_malloc(frag_len)) == NULL) { + SSLerr(SSL_F_DTLS1_HM_FRAGMENT_NEW, ERR_R_MALLOC_FAILURE); + OPENSSL_free(frag); + return NULL; + } + } + + /* zero length fragment gets zero frag->fragment */ + frag->fragment = buf; + + /* Initialize reassembly bitmask if necessary */ + if (reassembly) { + bitmask = OPENSSL_zalloc(RSMBLY_BITMASK_SIZE(frag_len)); + if (bitmask == NULL) { + SSLerr(SSL_F_DTLS1_HM_FRAGMENT_NEW, ERR_R_MALLOC_FAILURE); + OPENSSL_free(buf); + OPENSSL_free(frag); + return NULL; + } + } + + frag->reassembly = bitmask; + + return frag; +} + +void dtls1_hm_fragment_free(hm_fragment *frag) +{ + if (!frag) + return; + if (frag->msg_header.is_ccs) { + EVP_CIPHER_CTX_free(frag->msg_header. + saved_retransmit_state.enc_write_ctx); + EVP_MD_CTX_free(frag->msg_header.saved_retransmit_state.write_hash); + } + OPENSSL_free(frag->fragment); + OPENSSL_free(frag->reassembly); + OPENSSL_free(frag); +} + +/* + * send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or + * SSL3_RT_CHANGE_CIPHER_SPEC) + */ +int dtls1_do_write(SSL *s, int type) +{ + int ret; + size_t written; + size_t curr_mtu; + int retry = 1; + size_t len, frag_off, mac_size, blocksize, used_len; + + if (!dtls1_query_mtu(s)) + return -1; + + if (s->d1->mtu < dtls1_min_mtu(s)) + /* should have something reasonable now */ + return -1; + + if (s->init_off == 0 && type == SSL3_RT_HANDSHAKE) { + if (!ossl_assert(s->init_num == + s->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH)) + return -1; + } + + if (s->write_hash) { + if (s->enc_write_ctx + && (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_write_ctx)) & + EVP_CIPH_FLAG_AEAD_CIPHER) != 0) + mac_size = 0; + else + mac_size = EVP_MD_CTX_size(s->write_hash); + } else + mac_size = 0; + + if (s->enc_write_ctx && + (EVP_CIPHER_CTX_mode(s->enc_write_ctx) == EVP_CIPH_CBC_MODE)) + blocksize = 2 * EVP_CIPHER_CTX_block_size(s->enc_write_ctx); + else + blocksize = 0; + + frag_off = 0; + s->rwstate = SSL_NOTHING; + + /* s->init_num shouldn't ever be < 0...but just in case */ + while (s->init_num > 0) { + if (type == SSL3_RT_HANDSHAKE && s->init_off != 0) { + /* We must be writing a fragment other than the first one */ + + if (frag_off > 0) { + /* This is the first attempt at writing out this fragment */ + + if (s->init_off <= DTLS1_HM_HEADER_LENGTH) { + /* + * Each fragment that was already sent must at least have + * contained the message header plus one other byte. + * Therefore |init_off| must have progressed by at least + * |DTLS1_HM_HEADER_LENGTH + 1| bytes. If not something went + * wrong. + */ + return -1; + } + + /* + * Adjust |init_off| and |init_num| to allow room for a new + * message header for this fragment. + */ + s->init_off -= DTLS1_HM_HEADER_LENGTH; + s->init_num += DTLS1_HM_HEADER_LENGTH; + } else { + /* + * We must have been called again after a retry so use the + * fragment offset from our last attempt. We do not need + * to adjust |init_off| and |init_num| as above, because + * that should already have been done before the retry. + */ + frag_off = s->d1->w_msg_hdr.frag_off; + } + } + + used_len = BIO_wpending(s->wbio) + DTLS1_RT_HEADER_LENGTH + + mac_size + blocksize; + if (s->d1->mtu > used_len) + curr_mtu = s->d1->mtu - used_len; + else + curr_mtu = 0; + + if (curr_mtu <= DTLS1_HM_HEADER_LENGTH) { + /* + * grr.. we could get an error if MTU picked was wrong + */ + ret = BIO_flush(s->wbio); + if (ret <= 0) { + s->rwstate = SSL_WRITING; + return ret; + } + used_len = DTLS1_RT_HEADER_LENGTH + mac_size + blocksize; + if (s->d1->mtu > used_len + DTLS1_HM_HEADER_LENGTH) { + curr_mtu = s->d1->mtu - used_len; + } else { + /* Shouldn't happen */ + return -1; + } + } + + /* + * We just checked that s->init_num > 0 so this cast should be safe + */ + if (((unsigned int)s->init_num) > curr_mtu) + len = curr_mtu; + else + len = s->init_num; + + if (len > s->max_send_fragment) + len = s->max_send_fragment; + + /* + * XDTLS: this function is too long. split out the CCS part + */ + if (type == SSL3_RT_HANDSHAKE) { + if (len < DTLS1_HM_HEADER_LENGTH) { + /* + * len is so small that we really can't do anything sensible + * so fail + */ + return -1; + } + dtls1_fix_message_header(s, frag_off, len - DTLS1_HM_HEADER_LENGTH); + + dtls1_write_message_header(s, + (unsigned char *)&s->init_buf-> + data[s->init_off]); + } + + ret = dtls1_write_bytes(s, type, &s->init_buf->data[s->init_off], len, + &written); + if (ret < 0) { + /* + * might need to update MTU here, but we don't know which + * previous packet caused the failure -- so can't really + * retransmit anything. continue as if everything is fine and + * wait for an alert to handle the retransmit + */ + if (retry && BIO_ctrl(SSL_get_wbio(s), + BIO_CTRL_DGRAM_MTU_EXCEEDED, 0, NULL) > 0) { + if (!(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) { + if (!dtls1_query_mtu(s)) + return -1; + /* Have one more go */ + retry = 0; + } else + return -1; + } else { + return -1; + } + } else { + + /* + * bad if this assert fails, only part of the handshake message + * got sent. but why would this happen? + */ + if (!ossl_assert(len == written)) + return -1; + + if (type == SSL3_RT_HANDSHAKE && !s->d1->retransmitting) { + /* + * should not be done for 'Hello Request's, but in that case + * we'll ignore the result anyway + */ + unsigned char *p = + (unsigned char *)&s->init_buf->data[s->init_off]; + const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr; + size_t xlen; + + if (frag_off == 0 && s->version != DTLS1_BAD_VER) { + /* + * reconstruct message header is if it is being sent in + * single fragment + */ + *p++ = msg_hdr->type; + l2n3(msg_hdr->msg_len, p); + s2n(msg_hdr->seq, p); + l2n3(0, p); + l2n3(msg_hdr->msg_len, p); + p -= DTLS1_HM_HEADER_LENGTH; + xlen = written; + } else { + p += DTLS1_HM_HEADER_LENGTH; + xlen = written - DTLS1_HM_HEADER_LENGTH; + } + + if (!ssl3_finish_mac(s, p, xlen)) + return -1; + } + + if (written == s->init_num) { + if (s->msg_callback) + s->msg_callback(1, s->version, type, s->init_buf->data, + (size_t)(s->init_off + s->init_num), s, + s->msg_callback_arg); + + s->init_off = 0; /* done writing this message */ + s->init_num = 0; + + return 1; + } + s->init_off += written; + s->init_num -= written; + written -= DTLS1_HM_HEADER_LENGTH; + frag_off += written; + + /* + * We save the fragment offset for the next fragment so we have it + * available in case of an IO retry. We don't know the length of the + * next fragment yet so just set that to 0 for now. It will be + * updated again later. + */ + dtls1_fix_message_header(s, frag_off, 0); + } + } + return 0; +} + +int dtls_get_message(SSL *s, int *mt, size_t *len) +{ + struct hm_header_st *msg_hdr; + unsigned char *p; + size_t msg_len; + size_t tmplen; + int errtype; + + msg_hdr = &s->d1->r_msg_hdr; + memset(msg_hdr, 0, sizeof(*msg_hdr)); + + again: + if (!dtls_get_reassembled_message(s, &errtype, &tmplen)) { + if (errtype == DTLS1_HM_BAD_FRAGMENT + || errtype == DTLS1_HM_FRAGMENT_RETRY) { + /* bad fragment received */ + goto again; + } + return 0; + } + + *mt = s->s3->tmp.message_type; + + p = (unsigned char *)s->init_buf->data; + *len = s->init_num; + + if (*mt == SSL3_MT_CHANGE_CIPHER_SPEC) { + if (s->msg_callback) { + s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, + p, 1, s, s->msg_callback_arg); + } + /* + * This isn't a real handshake message so skip the processing below. + */ + return 1; + } + + msg_len = msg_hdr->msg_len; + + /* reconstruct message header */ + *(p++) = msg_hdr->type; + l2n3(msg_len, p); + s2n(msg_hdr->seq, p); + l2n3(0, p); + l2n3(msg_len, p); + if (s->version != DTLS1_BAD_VER) { + p -= DTLS1_HM_HEADER_LENGTH; + msg_len += DTLS1_HM_HEADER_LENGTH; + } + + /* + * If receiving Finished, record MAC of prior handshake messages for + * Finished verification. + */ + if (*mt == SSL3_MT_FINISHED && !ssl3_take_mac(s)) { + /* SSLfatal() already called */ + return 0; + } + + if (!ssl3_finish_mac(s, p, msg_len)) + return 0; + if (s->msg_callback) + s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, + p, msg_len, s, s->msg_callback_arg); + + memset(msg_hdr, 0, sizeof(*msg_hdr)); + + s->d1->handshake_read_seq++; + + s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH; + + return 1; +} + +/* + * dtls1_max_handshake_message_len returns the maximum number of bytes + * permitted in a DTLS handshake message for |s|. The minimum is 16KB, but + * may be greater if the maximum certificate list size requires it. + */ +static size_t dtls1_max_handshake_message_len(const SSL *s) +{ + size_t max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH; + if (max_len < s->max_cert_list) + return s->max_cert_list; + return max_len; +} + +static int dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr) +{ + size_t frag_off, frag_len, msg_len; + + msg_len = msg_hdr->msg_len; + frag_off = msg_hdr->frag_off; + frag_len = msg_hdr->frag_len; + + /* sanity checking */ + if ((frag_off + frag_len) > msg_len + || msg_len > dtls1_max_handshake_message_len(s)) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_DTLS1_PREPROCESS_FRAGMENT, + SSL_R_EXCESSIVE_MESSAGE_SIZE); + return 0; + } + + if (s->d1->r_msg_hdr.frag_off == 0) { /* first fragment */ + /* + * msg_len is limited to 2^24, but is effectively checked against + * dtls_max_handshake_message_len(s) above + */ + if (!BUF_MEM_grow_clean(s->init_buf, msg_len + DTLS1_HM_HEADER_LENGTH)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_PREPROCESS_FRAGMENT, + ERR_R_BUF_LIB); + return 0; + } + + s->s3->tmp.message_size = msg_len; + s->d1->r_msg_hdr.msg_len = msg_len; + s->s3->tmp.message_type = msg_hdr->type; + s->d1->r_msg_hdr.type = msg_hdr->type; + s->d1->r_msg_hdr.seq = msg_hdr->seq; + } else if (msg_len != s->d1->r_msg_hdr.msg_len) { + /* + * They must be playing with us! BTW, failure to enforce upper limit + * would open possibility for buffer overrun. + */ + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_DTLS1_PREPROCESS_FRAGMENT, + SSL_R_EXCESSIVE_MESSAGE_SIZE); + return 0; + } + + return 1; +} + +/* + * Returns 1 if there is a buffered fragment available, 0 if not, or -1 on a + * fatal error. + */ +static int dtls1_retrieve_buffered_fragment(SSL *s, size_t *len) +{ + /*- + * (0) check whether the desired fragment is available + * if so: + * (1) copy over the fragment to s->init_buf->data[] + * (2) update s->init_num + */ + pitem *item; + hm_fragment *frag; + int ret; + + do { + item = pqueue_peek(s->d1->buffered_messages); + if (item == NULL) + return 0; + + frag = (hm_fragment *)item->data; + + if (frag->msg_header.seq < s->d1->handshake_read_seq) { + /* This is a stale message that has been buffered so clear it */ + pqueue_pop(s->d1->buffered_messages); + dtls1_hm_fragment_free(frag); + pitem_free(item); + item = NULL; + frag = NULL; + } + } while (item == NULL); + + /* Don't return if reassembly still in progress */ + if (frag->reassembly != NULL) + return 0; + + if (s->d1->handshake_read_seq == frag->msg_header.seq) { + size_t frag_len = frag->msg_header.frag_len; + pqueue_pop(s->d1->buffered_messages); + + /* Calls SSLfatal() as required */ + ret = dtls1_preprocess_fragment(s, &frag->msg_header); + + if (ret && frag->msg_header.frag_len > 0) { + unsigned char *p = + (unsigned char *)s->init_buf->data + DTLS1_HM_HEADER_LENGTH; + memcpy(&p[frag->msg_header.frag_off], frag->fragment, + frag->msg_header.frag_len); + } + + dtls1_hm_fragment_free(frag); + pitem_free(item); + + if (ret) { + *len = frag_len; + return 1; + } + + /* Fatal error */ + s->init_num = 0; + return -1; + } else { + return 0; + } +} + +static int +dtls1_reassemble_fragment(SSL *s, const struct hm_header_st *msg_hdr) +{ + hm_fragment *frag = NULL; + pitem *item = NULL; + int i = -1, is_complete; + unsigned char seq64be[8]; + size_t frag_len = msg_hdr->frag_len; + size_t readbytes; + + if ((msg_hdr->frag_off + frag_len) > msg_hdr->msg_len || + msg_hdr->msg_len > dtls1_max_handshake_message_len(s)) + goto err; + + if (frag_len == 0) { + return DTLS1_HM_FRAGMENT_RETRY; + } + + /* Try to find item in queue */ + memset(seq64be, 0, sizeof(seq64be)); + seq64be[6] = (unsigned char)(msg_hdr->seq >> 8); + seq64be[7] = (unsigned char)msg_hdr->seq; + item = pqueue_find(s->d1->buffered_messages, seq64be); + + if (item == NULL) { + frag = dtls1_hm_fragment_new(msg_hdr->msg_len, 1); + if (frag == NULL) + goto err; + memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr)); + frag->msg_header.frag_len = frag->msg_header.msg_len; + frag->msg_header.frag_off = 0; + } else { + frag = (hm_fragment *)item->data; + if (frag->msg_header.msg_len != msg_hdr->msg_len) { + item = NULL; + frag = NULL; + goto err; + } + } + + /* + * If message is already reassembled, this must be a retransmit and can + * be dropped. In this case item != NULL and so frag does not need to be + * freed. + */ + if (frag->reassembly == NULL) { + unsigned char devnull[256]; + + while (frag_len) { + i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL, + devnull, + frag_len > + sizeof(devnull) ? sizeof(devnull) : + frag_len, 0, &readbytes); + if (i <= 0) + goto err; + frag_len -= readbytes; + } + return DTLS1_HM_FRAGMENT_RETRY; + } + + /* read the body of the fragment (header has already been read */ + i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL, + frag->fragment + msg_hdr->frag_off, + frag_len, 0, &readbytes); + if (i <= 0 || readbytes != frag_len) + i = -1; + if (i <= 0) + goto err; + + RSMBLY_BITMASK_MARK(frag->reassembly, (long)msg_hdr->frag_off, + (long)(msg_hdr->frag_off + frag_len)); + + if (!ossl_assert(msg_hdr->msg_len > 0)) + goto err; + RSMBLY_BITMASK_IS_COMPLETE(frag->reassembly, (long)msg_hdr->msg_len, + is_complete); + + if (is_complete) { + OPENSSL_free(frag->reassembly); + frag->reassembly = NULL; + } + + if (item == NULL) { + item = pitem_new(seq64be, frag); + if (item == NULL) { + i = -1; + goto err; + } + + item = pqueue_insert(s->d1->buffered_messages, item); + /* + * pqueue_insert fails iff a duplicate item is inserted. However, + * |item| cannot be a duplicate. If it were, |pqueue_find|, above, + * would have returned it and control would never have reached this + * branch. + */ + if (!ossl_assert(item != NULL)) + goto err; + } + + return DTLS1_HM_FRAGMENT_RETRY; + + err: + if (item == NULL) + dtls1_hm_fragment_free(frag); + return -1; +} + +static int +dtls1_process_out_of_seq_message(SSL *s, const struct hm_header_st *msg_hdr) +{ + int i = -1; + hm_fragment *frag = NULL; + pitem *item = NULL; + unsigned char seq64be[8]; + size_t frag_len = msg_hdr->frag_len; + size_t readbytes; + + if ((msg_hdr->frag_off + frag_len) > msg_hdr->msg_len) + goto err; + + /* Try to find item in queue, to prevent duplicate entries */ + memset(seq64be, 0, sizeof(seq64be)); + seq64be[6] = (unsigned char)(msg_hdr->seq >> 8); + seq64be[7] = (unsigned char)msg_hdr->seq; + item = pqueue_find(s->d1->buffered_messages, seq64be); + + /* + * If we already have an entry and this one is a fragment, don't discard + * it and rather try to reassemble it. + */ + if (item != NULL && frag_len != msg_hdr->msg_len) + item = NULL; + + /* + * Discard the message if sequence number was already there, is too far + * in the future, already in the queue or if we received a FINISHED + * before the SERVER_HELLO, which then must be a stale retransmit. + */ + if (msg_hdr->seq <= s->d1->handshake_read_seq || + msg_hdr->seq > s->d1->handshake_read_seq + 10 || item != NULL || + (s->d1->handshake_read_seq == 0 && msg_hdr->type == SSL3_MT_FINISHED)) { + unsigned char devnull[256]; + + while (frag_len) { + i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL, + devnull, + frag_len > + sizeof(devnull) ? sizeof(devnull) : + frag_len, 0, &readbytes); + if (i <= 0) + goto err; + frag_len -= readbytes; + } + } else { + if (frag_len != msg_hdr->msg_len) { + return dtls1_reassemble_fragment(s, msg_hdr); + } + + if (frag_len > dtls1_max_handshake_message_len(s)) + goto err; + + frag = dtls1_hm_fragment_new(frag_len, 0); + if (frag == NULL) + goto err; + + memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr)); + + if (frag_len) { + /* + * read the body of the fragment (header has already been read + */ + i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL, + frag->fragment, frag_len, 0, + &readbytes); + if (i<=0 || readbytes != frag_len) + i = -1; + if (i <= 0) + goto err; + } + + item = pitem_new(seq64be, frag); + if (item == NULL) + goto err; + + item = pqueue_insert(s->d1->buffered_messages, item); + /* + * pqueue_insert fails iff a duplicate item is inserted. However, + * |item| cannot be a duplicate. If it were, |pqueue_find|, above, + * would have returned it. Then, either |frag_len| != + * |msg_hdr->msg_len| in which case |item| is set to NULL and it will + * have been processed with |dtls1_reassemble_fragment|, above, or + * the record will have been discarded. + */ + if (!ossl_assert(item != NULL)) + goto err; + } + + return DTLS1_HM_FRAGMENT_RETRY; + + err: + if (item == NULL) + dtls1_hm_fragment_free(frag); + return 0; +} + +static int dtls_get_reassembled_message(SSL *s, int *errtype, size_t *len) +{ + unsigned char wire[DTLS1_HM_HEADER_LENGTH]; + size_t mlen, frag_off, frag_len; + int i, ret, recvd_type; + struct hm_header_st msg_hdr; + size_t readbytes; + + *errtype = 0; + + redo: + /* see if we have the required fragment already */ + ret = dtls1_retrieve_buffered_fragment(s, &frag_len); + if (ret < 0) { + /* SSLfatal() already called */ + return 0; + } + if (ret > 0) { + s->init_num = frag_len; + *len = frag_len; + return 1; + } + + /* read handshake message header */ + i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, &recvd_type, wire, + DTLS1_HM_HEADER_LENGTH, 0, &readbytes); + if (i <= 0) { /* nbio, or an error */ + s->rwstate = SSL_READING; + *len = 0; + return 0; + } + if (recvd_type == SSL3_RT_CHANGE_CIPHER_SPEC) { + if (wire[0] != SSL3_MT_CCS) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, + SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, + SSL_R_BAD_CHANGE_CIPHER_SPEC); + goto f_err; + } + + memcpy(s->init_buf->data, wire, readbytes); + s->init_num = readbytes - 1; + s->init_msg = s->init_buf->data + 1; + s->s3->tmp.message_type = SSL3_MT_CHANGE_CIPHER_SPEC; + s->s3->tmp.message_size = readbytes - 1; + *len = readbytes - 1; + return 1; + } + + /* Handshake fails if message header is incomplete */ + if (readbytes != DTLS1_HM_HEADER_LENGTH) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, + SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE); + goto f_err; + } + + /* parse the message fragment header */ + dtls1_get_message_header(wire, &msg_hdr); + + mlen = msg_hdr.msg_len; + frag_off = msg_hdr.frag_off; + frag_len = msg_hdr.frag_len; + + /* + * We must have at least frag_len bytes left in the record to be read. + * Fragments must not span records. + */ + if (frag_len > RECORD_LAYER_get_rrec_length(&s->rlayer)) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_BAD_LENGTH); + goto f_err; + } + + /* + * if this is a future (or stale) message it gets buffered + * (or dropped)--no further processing at this time + * While listening, we accept seq 1 (ClientHello with cookie) + * although we're still expecting seq 0 (ClientHello) + */ + if (msg_hdr.seq != s->d1->handshake_read_seq) { + *errtype = dtls1_process_out_of_seq_message(s, &msg_hdr); + return 0; + } + + if (frag_len && frag_len < mlen) { + *errtype = dtls1_reassemble_fragment(s, &msg_hdr); + return 0; + } + + if (!s->server + && s->d1->r_msg_hdr.frag_off == 0 + && s->statem.hand_state != TLS_ST_OK + && wire[0] == SSL3_MT_HELLO_REQUEST) { + /* + * The server may always send 'Hello Request' messages -- we are + * doing a handshake anyway now, so ignore them if their format is + * correct. Does not count for 'Finished' MAC. + */ + if (wire[1] == 0 && wire[2] == 0 && wire[3] == 0) { + if (s->msg_callback) + s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, + wire, DTLS1_HM_HEADER_LENGTH, s, + s->msg_callback_arg); + + s->init_num = 0; + goto redo; + } else { /* Incorrectly formatted Hello request */ + + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, + SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, + SSL_R_UNEXPECTED_MESSAGE); + goto f_err; + } + } + + if (!dtls1_preprocess_fragment(s, &msg_hdr)) { + /* SSLfatal() already called */ + goto f_err; + } + + if (frag_len > 0) { + unsigned char *p = + (unsigned char *)s->init_buf->data + DTLS1_HM_HEADER_LENGTH; + + i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL, + &p[frag_off], frag_len, 0, &readbytes); + + /* + * This shouldn't ever fail due to NBIO because we already checked + * that we have enough data in the record + */ + if (i <= 0) { + s->rwstate = SSL_READING; + *len = 0; + return 0; + } + } else { + readbytes = 0; + } + + /* + * XDTLS: an incorrectly formatted fragment should cause the handshake + * to fail + */ + if (readbytes != frag_len) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_BAD_LENGTH); + goto f_err; + } + + /* + * Note that s->init_num is *not* used as current offset in + * s->init_buf->data, but as a counter summing up fragments' lengths: as + * soon as they sum up to handshake packet length, we assume we have got + * all the fragments. + */ + *len = s->init_num = frag_len; + return 1; + + f_err: + s->init_num = 0; + *len = 0; + return 0; +} + +/*- + * for these 2 messages, we need to + * ssl->enc_read_ctx re-init + * ssl->rlayer.read_sequence zero + * ssl->s3->read_mac_secret re-init + * ssl->session->read_sym_enc assign + * ssl->session->read_compression assign + * ssl->session->read_hash assign + */ +int dtls_construct_change_cipher_spec(SSL *s, WPACKET *pkt) +{ + if (s->version == DTLS1_BAD_VER) { + s->d1->next_handshake_write_seq++; + + if (!WPACKET_put_bytes_u16(pkt, s->d1->handshake_write_seq)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC, + ERR_R_INTERNAL_ERROR); + return 0; + } + } + + return 1; +} + +#ifndef OPENSSL_NO_SCTP +/* + * Wait for a dry event. Should only be called at a point in the handshake + * where we are not expecting any data from the peer except an alert. + */ +WORK_STATE dtls_wait_for_dry(SSL *s) +{ + int ret, errtype; + size_t len; + + /* read app data until dry event */ + ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s)); + if (ret < 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS_WAIT_FOR_DRY, + ERR_R_INTERNAL_ERROR); + return WORK_ERROR; + } + + if (ret == 0) { + /* + * We're not expecting any more messages from the peer at this point - + * but we could get an alert. If an alert is waiting then we will never + * return successfully. Therefore we attempt to read a message. This + * should never succeed but will process any waiting alerts. + */ + if (dtls_get_reassembled_message(s, &errtype, &len)) { + /* The call succeeded! This should never happen */ + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS_WAIT_FOR_DRY, + SSL_R_UNEXPECTED_MESSAGE); + return WORK_ERROR; + } + + s->s3->in_read_app_data = 2; + s->rwstate = SSL_READING; + BIO_clear_retry_flags(SSL_get_rbio(s)); + BIO_set_retry_read(SSL_get_rbio(s)); + return WORK_MORE_A; + } + return WORK_FINISHED_CONTINUE; +} +#endif + +int dtls1_read_failed(SSL *s, int code) +{ + if (code > 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_DTLS1_READ_FAILED, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (!dtls1_is_timer_expired(s) || ossl_statem_in_error(s)) { + /* + * not a timeout, none of our business, let higher layers handle + * this. in fact it's probably an error + */ + return code; + } + /* done, no need to send a retransmit */ + if (!SSL_in_init(s)) + { + BIO_set_flags(SSL_get_rbio(s), BIO_FLAGS_READ); + return code; + } + + return dtls1_handle_timeout(s); +} + +int dtls1_get_queue_priority(unsigned short seq, int is_ccs) +{ + /* + * The index of the retransmission queue actually is the message sequence + * number, since the queue only contains messages of a single handshake. + * However, the ChangeCipherSpec has no message sequence number and so + * using only the sequence will result in the CCS and Finished having the + * same index. To prevent this, the sequence number is multiplied by 2. + * In case of a CCS 1 is subtracted. This does not only differ CSS and + * Finished, it also maintains the order of the index (important for + * priority queues) and fits in the unsigned short variable. + */ + return seq * 2 - is_ccs; +} + +int dtls1_retransmit_buffered_messages(SSL *s) +{ + pqueue *sent = s->d1->sent_messages; + piterator iter; + pitem *item; + hm_fragment *frag; + int found = 0; + + iter = pqueue_iterator(sent); + + for (item = pqueue_next(&iter); item != NULL; item = pqueue_next(&iter)) { + frag = (hm_fragment *)item->data; + if (dtls1_retransmit_message(s, (unsigned short) + dtls1_get_queue_priority + (frag->msg_header.seq, + frag->msg_header.is_ccs), &found) <= 0) + return -1; + } + + return 1; +} + +int dtls1_buffer_message(SSL *s, int is_ccs) +{ + pitem *item; + hm_fragment *frag; + unsigned char seq64be[8]; + + /* + * this function is called immediately after a message has been + * serialized + */ + if (!ossl_assert(s->init_off == 0)) + return 0; + + frag = dtls1_hm_fragment_new(s->init_num, 0); + if (frag == NULL) + return 0; + + memcpy(frag->fragment, s->init_buf->data, s->init_num); + + if (is_ccs) { + /* For DTLS1_BAD_VER the header length is non-standard */ + if (!ossl_assert(s->d1->w_msg_hdr.msg_len + + ((s->version == + DTLS1_BAD_VER) ? 3 : DTLS1_CCS_HEADER_LENGTH) + == (unsigned int)s->init_num)) + return 0; + } else { + if (!ossl_assert(s->d1->w_msg_hdr.msg_len + + DTLS1_HM_HEADER_LENGTH == (unsigned int)s->init_num)) + return 0; + } + + frag->msg_header.msg_len = s->d1->w_msg_hdr.msg_len; + frag->msg_header.seq = s->d1->w_msg_hdr.seq; + frag->msg_header.type = s->d1->w_msg_hdr.type; + frag->msg_header.frag_off = 0; + frag->msg_header.frag_len = s->d1->w_msg_hdr.msg_len; + frag->msg_header.is_ccs = is_ccs; + + /* save current state */ + frag->msg_header.saved_retransmit_state.enc_write_ctx = s->enc_write_ctx; + frag->msg_header.saved_retransmit_state.write_hash = s->write_hash; + frag->msg_header.saved_retransmit_state.compress = s->compress; + frag->msg_header.saved_retransmit_state.session = s->session; + frag->msg_header.saved_retransmit_state.epoch = + DTLS_RECORD_LAYER_get_w_epoch(&s->rlayer); + + memset(seq64be, 0, sizeof(seq64be)); + seq64be[6] = + (unsigned + char)(dtls1_get_queue_priority(frag->msg_header.seq, + frag->msg_header.is_ccs) >> 8); + seq64be[7] = + (unsigned + char)(dtls1_get_queue_priority(frag->msg_header.seq, + frag->msg_header.is_ccs)); + + item = pitem_new(seq64be, frag); + if (item == NULL) { + dtls1_hm_fragment_free(frag); + return 0; + } + + pqueue_insert(s->d1->sent_messages, item); + return 1; +} + +int dtls1_retransmit_message(SSL *s, unsigned short seq, int *found) +{ + int ret; + /* XDTLS: for now assuming that read/writes are blocking */ + pitem *item; + hm_fragment *frag; + unsigned long header_length; + unsigned char seq64be[8]; + struct dtls1_retransmit_state saved_state; + + /* XDTLS: the requested message ought to be found, otherwise error */ + memset(seq64be, 0, sizeof(seq64be)); + seq64be[6] = (unsigned char)(seq >> 8); + seq64be[7] = (unsigned char)seq; + + item = pqueue_find(s->d1->sent_messages, seq64be); + if (item == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_RETRANSMIT_MESSAGE, + ERR_R_INTERNAL_ERROR); + *found = 0; + return 0; + } + + *found = 1; + frag = (hm_fragment *)item->data; + + if (frag->msg_header.is_ccs) + header_length = DTLS1_CCS_HEADER_LENGTH; + else + header_length = DTLS1_HM_HEADER_LENGTH; + + memcpy(s->init_buf->data, frag->fragment, + frag->msg_header.msg_len + header_length); + s->init_num = frag->msg_header.msg_len + header_length; + + dtls1_set_message_header_int(s, frag->msg_header.type, + frag->msg_header.msg_len, + frag->msg_header.seq, 0, + frag->msg_header.frag_len); + + /* save current state */ + saved_state.enc_write_ctx = s->enc_write_ctx; + saved_state.write_hash = s->write_hash; + saved_state.compress = s->compress; + saved_state.session = s->session; + saved_state.epoch = DTLS_RECORD_LAYER_get_w_epoch(&s->rlayer); + + s->d1->retransmitting = 1; + + /* restore state in which the message was originally sent */ + s->enc_write_ctx = frag->msg_header.saved_retransmit_state.enc_write_ctx; + s->write_hash = frag->msg_header.saved_retransmit_state.write_hash; + s->compress = frag->msg_header.saved_retransmit_state.compress; + s->session = frag->msg_header.saved_retransmit_state.session; + DTLS_RECORD_LAYER_set_saved_w_epoch(&s->rlayer, + frag->msg_header. + saved_retransmit_state.epoch); + + ret = dtls1_do_write(s, frag->msg_header.is_ccs ? + SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE); + + /* restore current state */ + s->enc_write_ctx = saved_state.enc_write_ctx; + s->write_hash = saved_state.write_hash; + s->compress = saved_state.compress; + s->session = saved_state.session; + DTLS_RECORD_LAYER_set_saved_w_epoch(&s->rlayer, saved_state.epoch); + + s->d1->retransmitting = 0; + + (void)BIO_flush(s->wbio); + return ret; +} + +void dtls1_set_message_header(SSL *s, + unsigned char mt, size_t len, + size_t frag_off, size_t frag_len) +{ + if (frag_off == 0) { + s->d1->handshake_write_seq = s->d1->next_handshake_write_seq; + s->d1->next_handshake_write_seq++; + } + + dtls1_set_message_header_int(s, mt, len, s->d1->handshake_write_seq, + frag_off, frag_len); +} + +/* don't actually do the writing, wait till the MTU has been retrieved */ +static void +dtls1_set_message_header_int(SSL *s, unsigned char mt, + size_t len, unsigned short seq_num, + size_t frag_off, size_t frag_len) +{ + struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr; + + msg_hdr->type = mt; + msg_hdr->msg_len = len; + msg_hdr->seq = seq_num; + msg_hdr->frag_off = frag_off; + msg_hdr->frag_len = frag_len; +} + +static void +dtls1_fix_message_header(SSL *s, size_t frag_off, size_t frag_len) +{ + struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr; + + msg_hdr->frag_off = frag_off; + msg_hdr->frag_len = frag_len; +} + +static unsigned char *dtls1_write_message_header(SSL *s, unsigned char *p) +{ + struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr; + + *p++ = msg_hdr->type; + l2n3(msg_hdr->msg_len, p); + + s2n(msg_hdr->seq, p); + l2n3(msg_hdr->frag_off, p); + l2n3(msg_hdr->frag_len, p); + + return p; +} + +void dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr) +{ + memset(msg_hdr, 0, sizeof(*msg_hdr)); + msg_hdr->type = *(data++); + n2l3(data, msg_hdr->msg_len); + + n2s(data, msg_hdr->seq); + n2l3(data, msg_hdr->frag_off); + n2l3(data, msg_hdr->frag_len); +} + +int dtls1_set_handshake_header(SSL *s, WPACKET *pkt, int htype) +{ + unsigned char *header; + + if (htype == SSL3_MT_CHANGE_CIPHER_SPEC) { + s->d1->handshake_write_seq = s->d1->next_handshake_write_seq; + dtls1_set_message_header_int(s, SSL3_MT_CCS, 0, + s->d1->handshake_write_seq, 0, 0); + if (!WPACKET_put_bytes_u8(pkt, SSL3_MT_CCS)) + return 0; + } else { + dtls1_set_message_header(s, htype, 0, 0, 0); + /* + * We allocate space at the start for the message header. This gets + * filled in later + */ + if (!WPACKET_allocate_bytes(pkt, DTLS1_HM_HEADER_LENGTH, &header) + || !WPACKET_start_sub_packet(pkt)) + return 0; + } + + return 1; +} + +int dtls1_close_construct_packet(SSL *s, WPACKET *pkt, int htype) +{ + size_t msglen; + + if ((htype != SSL3_MT_CHANGE_CIPHER_SPEC && !WPACKET_close(pkt)) + || !WPACKET_get_length(pkt, &msglen) + || msglen > INT_MAX) + return 0; + + if (htype != SSL3_MT_CHANGE_CIPHER_SPEC) { + s->d1->w_msg_hdr.msg_len = msglen - DTLS1_HM_HEADER_LENGTH; + s->d1->w_msg_hdr.frag_len = msglen - DTLS1_HM_HEADER_LENGTH; + } + s->init_num = (int)msglen; + s->init_off = 0; + + if (htype != DTLS1_MT_HELLO_VERIFY_REQUEST) { + /* Buffer the message to handle re-xmits */ + if (!dtls1_buffer_message(s, htype == SSL3_MT_CHANGE_CIPHER_SPEC + ? 1 : 0)) + return 0; + } + + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_lib.c b/trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_lib.c new file mode 100644 index 000000000..c0482b0a9 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_lib.c @@ -0,0 +1,2403 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "../ssl_locl.h" +#include "statem_locl.h" +#include "internal/cryptlib.h" +#include +#include +#include +#include + +/* + * Map error codes to TLS/SSL alart types. + */ +typedef struct x509err2alert_st { + int x509err; + int alert; +} X509ERR2ALERT; + +/* Fixed value used in the ServerHello random field to identify an HRR */ +const unsigned char hrrrandom[] = { + 0xcf, 0x21, 0xad, 0x74, 0xe5, 0x9a, 0x61, 0x11, 0xbe, 0x1d, 0x8c, 0x02, + 0x1e, 0x65, 0xb8, 0x91, 0xc2, 0xa2, 0x11, 0x16, 0x7a, 0xbb, 0x8c, 0x5e, + 0x07, 0x9e, 0x09, 0xe2, 0xc8, 0xa8, 0x33, 0x9c +}; + +/* + * send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or + * SSL3_RT_CHANGE_CIPHER_SPEC) + */ +int ssl3_do_write(SSL *s, int type) +{ + int ret; + size_t written = 0; + + ret = ssl3_write_bytes(s, type, &s->init_buf->data[s->init_off], + s->init_num, &written); + if (ret < 0) + return -1; + if (type == SSL3_RT_HANDSHAKE) + /* + * should not be done for 'Hello Request's, but in that case we'll + * ignore the result anyway + * TLS1.3 KeyUpdate and NewSessionTicket do not need to be added + */ + if (!SSL_IS_TLS13(s) || (s->statem.hand_state != TLS_ST_SW_SESSION_TICKET + && s->statem.hand_state != TLS_ST_CW_KEY_UPDATE + && s->statem.hand_state != TLS_ST_SW_KEY_UPDATE)) + if (!ssl3_finish_mac(s, + (unsigned char *)&s->init_buf->data[s->init_off], + written)) + return -1; + if (written == s->init_num) { + if (s->msg_callback) + s->msg_callback(1, s->version, type, s->init_buf->data, + (size_t)(s->init_off + s->init_num), s, + s->msg_callback_arg); + return 1; + } + s->init_off += written; + s->init_num -= written; + return 0; +} + +int tls_close_construct_packet(SSL *s, WPACKET *pkt, int htype) +{ + size_t msglen; + + if ((htype != SSL3_MT_CHANGE_CIPHER_SPEC && !WPACKET_close(pkt)) + || !WPACKET_get_length(pkt, &msglen) + || msglen > INT_MAX) + return 0; + s->init_num = (int)msglen; + s->init_off = 0; + + return 1; +} + +int tls_setup_handshake(SSL *s) +{ + if (!ssl3_init_finished_mac(s)) { + /* SSLfatal() already called */ + return 0; + } + + /* Reset any extension flags */ + memset(s->ext.extflags, 0, sizeof(s->ext.extflags)); + + if (s->server) { + STACK_OF(SSL_CIPHER) *ciphers = SSL_get_ciphers(s); + int i, ver_min, ver_max, ok = 0; + + /* + * Sanity check that the maximum version we accept has ciphers + * enabled. For clients we do this check during construction of the + * ClientHello. + */ + if (ssl_get_min_max_version(s, &ver_min, &ver_max, NULL) != 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_SETUP_HANDSHAKE, + ERR_R_INTERNAL_ERROR); + return 0; + } + for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { + const SSL_CIPHER *c = sk_SSL_CIPHER_value(ciphers, i); + + if (SSL_IS_DTLS(s)) { + if (DTLS_VERSION_GE(ver_max, c->min_dtls) && + DTLS_VERSION_LE(ver_max, c->max_dtls)) + ok = 1; + } else if (ver_max >= c->min_tls && ver_max <= c->max_tls) { + ok = 1; + } + if (ok) + break; + } + if (!ok) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_SETUP_HANDSHAKE, + SSL_R_NO_CIPHERS_AVAILABLE); + ERR_add_error_data(1, "No ciphers enabled for max supported " + "SSL/TLS version"); + return 0; + } + if (SSL_IS_FIRST_HANDSHAKE(s)) { + /* N.B. s->session_ctx == s->ctx here */ + tsan_counter(&s->session_ctx->stats.sess_accept); + } else { + /* N.B. s->ctx may not equal s->session_ctx */ + tsan_counter(&s->ctx->stats.sess_accept_renegotiate); + + s->s3->tmp.cert_request = 0; + } + } else { + if (SSL_IS_FIRST_HANDSHAKE(s)) + tsan_counter(&s->session_ctx->stats.sess_connect); + else + tsan_counter(&s->session_ctx->stats.sess_connect_renegotiate); + + /* mark client_random uninitialized */ + memset(s->s3->client_random, 0, sizeof(s->s3->client_random)); + s->hit = 0; + + s->s3->tmp.cert_req = 0; + + if (SSL_IS_DTLS(s)) + s->statem.use_timer = 1; + } + + return 1; +} + +/* + * Size of the to-be-signed TLS13 data, without the hash size itself: + * 64 bytes of value 32, 33 context bytes, 1 byte separator + */ +#define TLS13_TBS_START_SIZE 64 +#define TLS13_TBS_PREAMBLE_SIZE (TLS13_TBS_START_SIZE + 33 + 1) + +static int get_cert_verify_tbs_data(SSL *s, unsigned char *tls13tbs, + void **hdata, size_t *hdatalen) +{ + static const char *servercontext = "TLS 1.3, server CertificateVerify"; + static const char *clientcontext = "TLS 1.3, client CertificateVerify"; + + if (SSL_IS_TLS13(s)) { + size_t hashlen; + + /* Set the first 64 bytes of to-be-signed data to octet 32 */ + memset(tls13tbs, 32, TLS13_TBS_START_SIZE); + /* This copies the 33 bytes of context plus the 0 separator byte */ + if (s->statem.hand_state == TLS_ST_CR_CERT_VRFY + || s->statem.hand_state == TLS_ST_SW_CERT_VRFY) + strcpy((char *)tls13tbs + TLS13_TBS_START_SIZE, servercontext); + else + strcpy((char *)tls13tbs + TLS13_TBS_START_SIZE, clientcontext); + + /* + * If we're currently reading then we need to use the saved handshake + * hash value. We can't use the current handshake hash state because + * that includes the CertVerify itself. + */ + if (s->statem.hand_state == TLS_ST_CR_CERT_VRFY + || s->statem.hand_state == TLS_ST_SR_CERT_VRFY) { + memcpy(tls13tbs + TLS13_TBS_PREAMBLE_SIZE, s->cert_verify_hash, + s->cert_verify_hash_len); + hashlen = s->cert_verify_hash_len; + } else if (!ssl_handshake_hash(s, tls13tbs + TLS13_TBS_PREAMBLE_SIZE, + EVP_MAX_MD_SIZE, &hashlen)) { + /* SSLfatal() already called */ + return 0; + } + + *hdata = tls13tbs; + *hdatalen = TLS13_TBS_PREAMBLE_SIZE + hashlen; + } else { + size_t retlen; + long retlen_l; + + retlen = retlen_l = BIO_get_mem_data(s->s3->handshake_buffer, hdata); + if (retlen_l <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_GET_CERT_VERIFY_TBS_DATA, + ERR_R_INTERNAL_ERROR); + return 0; + } + *hdatalen = retlen; + } + + return 1; +} + +int tls_construct_cert_verify(SSL *s, WPACKET *pkt) +{ + EVP_PKEY *pkey = NULL; + const EVP_MD *md = NULL; + EVP_MD_CTX *mctx = NULL; + EVP_PKEY_CTX *pctx = NULL; + size_t hdatalen = 0, siglen = 0; + void *hdata; + unsigned char *sig = NULL; + unsigned char tls13tbs[TLS13_TBS_PREAMBLE_SIZE + EVP_MAX_MD_SIZE]; + const SIGALG_LOOKUP *lu = s->s3->tmp.sigalg; + + if (lu == NULL || s->s3->tmp.cert == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY, + ERR_R_INTERNAL_ERROR); + goto err; + } + pkey = s->s3->tmp.cert->privatekey; + + if (pkey == NULL || !tls1_lookup_md(lu, &md)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY, + ERR_R_INTERNAL_ERROR); + goto err; + } + + mctx = EVP_MD_CTX_new(); + if (mctx == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY, + ERR_R_MALLOC_FAILURE); + goto err; + } + + /* Get the data to be signed */ + if (!get_cert_verify_tbs_data(s, tls13tbs, &hdata, &hdatalen)) { + /* SSLfatal() already called */ + goto err; + } + + if (SSL_USE_SIGALGS(s) && !WPACKET_put_bytes_u16(pkt, lu->sigalg)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY, + ERR_R_INTERNAL_ERROR); + goto err; + } + siglen = EVP_PKEY_size(pkey); + sig = OPENSSL_malloc(siglen); + if (sig == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY, + ERR_R_MALLOC_FAILURE); + goto err; + } + + if (EVP_DigestSignInit(mctx, &pctx, md, NULL, pkey) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY, + ERR_R_EVP_LIB); + goto err; + } + + if (lu->sig == EVP_PKEY_RSA_PSS) { + if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0 + || EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, + RSA_PSS_SALTLEN_DIGEST) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY, + ERR_R_EVP_LIB); + goto err; + } + } + if (s->version == SSL3_VERSION) { + if (EVP_DigestSignUpdate(mctx, hdata, hdatalen) <= 0 + || !EVP_MD_CTX_ctrl(mctx, EVP_CTRL_SSL3_MASTER_SECRET, + (int)s->session->master_key_length, + s->session->master_key) + || EVP_DigestSignFinal(mctx, sig, &siglen) <= 0) { + + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY, + ERR_R_EVP_LIB); + goto err; + } + } else if (EVP_DigestSign(mctx, sig, &siglen, hdata, hdatalen) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY, + ERR_R_EVP_LIB); + goto err; + } + +#ifndef OPENSSL_NO_GOST + { + int pktype = lu->sig; + + if (pktype == NID_id_GostR3410_2001 + || pktype == NID_id_GostR3410_2012_256 + || pktype == NID_id_GostR3410_2012_512) + BUF_reverse(sig, NULL, siglen); + } +#endif + + if (!WPACKET_sub_memcpy_u16(pkt, sig, siglen)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* Digest cached records and discard handshake buffer */ + if (!ssl3_digest_cached_records(s, 0)) { + /* SSLfatal() already called */ + goto err; + } + + OPENSSL_free(sig); + EVP_MD_CTX_free(mctx); + return 1; + err: + OPENSSL_free(sig); + EVP_MD_CTX_free(mctx); + return 0; +} + +MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt) +{ + EVP_PKEY *pkey = NULL; + const unsigned char *data; +#ifndef OPENSSL_NO_GOST + unsigned char *gost_data = NULL; +#endif + MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR; + int j; + unsigned int len; + X509 *peer; + const EVP_MD *md = NULL; + size_t hdatalen = 0; + void *hdata; + unsigned char tls13tbs[TLS13_TBS_PREAMBLE_SIZE + EVP_MAX_MD_SIZE]; + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); + EVP_PKEY_CTX *pctx = NULL; + + if (mctx == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY, + ERR_R_MALLOC_FAILURE); + goto err; + } + + peer = s->session->peer; + pkey = X509_get0_pubkey(peer); + if (pkey == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY, + ERR_R_INTERNAL_ERROR); + goto err; + } + + if (ssl_cert_lookup_by_pkey(pkey, NULL) == NULL) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_CERT_VERIFY, + SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE); + goto err; + } + + if (SSL_USE_SIGALGS(s)) { + unsigned int sigalg; + + if (!PACKET_get_net_2(pkt, &sigalg)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY, + SSL_R_BAD_PACKET); + goto err; + } + if (tls12_check_peer_sigalg(s, sigalg, pkey) <= 0) { + /* SSLfatal() already called */ + goto err; + } + } else if (!tls1_set_peer_legacy_sigalg(s, pkey)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY, + ERR_R_INTERNAL_ERROR); + goto err; + } + + if (!tls1_lookup_md(s->s3->tmp.peer_sigalg, &md)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY, + ERR_R_INTERNAL_ERROR); + goto err; + } + +#ifdef SSL_DEBUG + if (SSL_USE_SIGALGS(s)) + fprintf(stderr, "USING TLSv1.2 HASH %s\n", + md == NULL ? "n/a" : EVP_MD_name(md)); +#endif + + /* Check for broken implementations of GOST ciphersuites */ + /* + * If key is GOST and len is exactly 64 or 128, it is signature without + * length field (CryptoPro implementations at least till TLS 1.2) + */ +#ifndef OPENSSL_NO_GOST + if (!SSL_USE_SIGALGS(s) + && ((PACKET_remaining(pkt) == 64 + && (EVP_PKEY_id(pkey) == NID_id_GostR3410_2001 + || EVP_PKEY_id(pkey) == NID_id_GostR3410_2012_256)) + || (PACKET_remaining(pkt) == 128 + && EVP_PKEY_id(pkey) == NID_id_GostR3410_2012_512))) { + len = PACKET_remaining(pkt); + } else +#endif + if (!PACKET_get_net_2(pkt, &len)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + j = EVP_PKEY_size(pkey); + if (((int)len > j) || ((int)PACKET_remaining(pkt) > j) + || (PACKET_remaining(pkt) == 0)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY, + SSL_R_WRONG_SIGNATURE_SIZE); + goto err; + } + if (!PACKET_get_bytes(pkt, &data, len)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + if (!get_cert_verify_tbs_data(s, tls13tbs, &hdata, &hdatalen)) { + /* SSLfatal() already called */ + goto err; + } + +#ifdef SSL_DEBUG + fprintf(stderr, "Using client verify alg %s\n", + md == NULL ? "n/a" : EVP_MD_name(md)); +#endif + if (EVP_DigestVerifyInit(mctx, &pctx, md, NULL, pkey) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY, + ERR_R_EVP_LIB); + goto err; + } +#ifndef OPENSSL_NO_GOST + { + int pktype = EVP_PKEY_id(pkey); + if (pktype == NID_id_GostR3410_2001 + || pktype == NID_id_GostR3410_2012_256 + || pktype == NID_id_GostR3410_2012_512) { + if ((gost_data = OPENSSL_malloc(len)) == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_MALLOC_FAILURE); + goto err; + } + BUF_reverse(gost_data, data, len); + data = gost_data; + } + } +#endif + + if (SSL_USE_PSS(s)) { + if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0 + || EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, + RSA_PSS_SALTLEN_DIGEST) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY, + ERR_R_EVP_LIB); + goto err; + } + } + if (s->version == SSL3_VERSION) { + if (EVP_DigestVerifyUpdate(mctx, hdata, hdatalen) <= 0 + || !EVP_MD_CTX_ctrl(mctx, EVP_CTRL_SSL3_MASTER_SECRET, + (int)s->session->master_key_length, + s->session->master_key)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY, + ERR_R_EVP_LIB); + goto err; + } + if (EVP_DigestVerifyFinal(mctx, data, len) <= 0) { + SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY, + SSL_R_BAD_SIGNATURE); + goto err; + } + } else { + j = EVP_DigestVerify(mctx, data, len, hdata, hdatalen); + if (j <= 0) { + SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY, + SSL_R_BAD_SIGNATURE); + goto err; + } + } + + /* + * In TLSv1.3 on the client side we make sure we prepare the client + * certificate after the CertVerify instead of when we get the + * CertificateRequest. This is because in TLSv1.3 the CertificateRequest + * comes *before* the Certificate message. In TLSv1.2 it comes after. We + * want to make sure that SSL_get_peer_certificate() will return the actual + * server certificate from the client_cert_cb callback. + */ + if (!s->server && SSL_IS_TLS13(s) && s->s3->tmp.cert_req == 1) + ret = MSG_PROCESS_CONTINUE_PROCESSING; + else + ret = MSG_PROCESS_CONTINUE_READING; + err: + BIO_free(s->s3->handshake_buffer); + s->s3->handshake_buffer = NULL; + EVP_MD_CTX_free(mctx); +#ifndef OPENSSL_NO_GOST + OPENSSL_free(gost_data); +#endif + return ret; +} + +int tls_construct_finished(SSL *s, WPACKET *pkt) +{ + size_t finish_md_len; + const char *sender; + size_t slen; + + /* This is a real handshake so make sure we clean it up at the end */ + if (!s->server && s->post_handshake_auth != SSL_PHA_REQUESTED) + s->statem.cleanuphand = 1; + + /* + * We only change the keys if we didn't already do this when we sent the + * client certificate + */ + if (SSL_IS_TLS13(s) + && !s->server + && s->s3->tmp.cert_req == 0 + && (!s->method->ssl3_enc->change_cipher_state(s, + SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_WRITE))) {; + /* SSLfatal() already called */ + return 0; + } + + if (s->server) { + sender = s->method->ssl3_enc->server_finished_label; + slen = s->method->ssl3_enc->server_finished_label_len; + } else { + sender = s->method->ssl3_enc->client_finished_label; + slen = s->method->ssl3_enc->client_finished_label_len; + } + + finish_md_len = s->method->ssl3_enc->final_finish_mac(s, + sender, slen, + s->s3->tmp.finish_md); + if (finish_md_len == 0) { + /* SSLfatal() already called */ + return 0; + } + + s->s3->tmp.finish_md_len = finish_md_len; + + if (!WPACKET_memcpy(pkt, s->s3->tmp.finish_md, finish_md_len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_FINISHED, + ERR_R_INTERNAL_ERROR); + return 0; + } + + /* + * Log the master secret, if logging is enabled. We don't log it for + * TLSv1.3: there's a different key schedule for that. + */ + if (!SSL_IS_TLS13(s) && !ssl_log_secret(s, MASTER_SECRET_LABEL, + s->session->master_key, + s->session->master_key_length)) { + /* SSLfatal() already called */ + return 0; + } + + /* + * Copy the finished so we can use it for renegotiation checks + */ + if (!ossl_assert(finish_md_len <= EVP_MAX_MD_SIZE)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_FINISHED, + ERR_R_INTERNAL_ERROR); + return 0; + } + if (!s->server) { + memcpy(s->s3->previous_client_finished, s->s3->tmp.finish_md, + finish_md_len); + s->s3->previous_client_finished_len = finish_md_len; + } else { + memcpy(s->s3->previous_server_finished, s->s3->tmp.finish_md, + finish_md_len); + s->s3->previous_server_finished_len = finish_md_len; + } + + return 1; +} + +int tls_construct_key_update(SSL *s, WPACKET *pkt) +{ + if (!WPACKET_put_bytes_u8(pkt, s->key_update)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_KEY_UPDATE, + ERR_R_INTERNAL_ERROR); + return 0; + } + + s->key_update = SSL_KEY_UPDATE_NONE; + return 1; +} + +MSG_PROCESS_RETURN tls_process_key_update(SSL *s, PACKET *pkt) +{ + unsigned int updatetype; + + /* + * A KeyUpdate message signals a key change so the end of the message must + * be on a record boundary. + */ + if (RECORD_LAYER_processed_read_pending(&s->rlayer)) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_KEY_UPDATE, + SSL_R_NOT_ON_RECORD_BOUNDARY); + return MSG_PROCESS_ERROR; + } + + if (!PACKET_get_1(pkt, &updatetype) + || PACKET_remaining(pkt) != 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_UPDATE, + SSL_R_BAD_KEY_UPDATE); + return MSG_PROCESS_ERROR; + } + + /* + * There are only two defined key update types. Fail if we get a value we + * didn't recognise. + */ + if (updatetype != SSL_KEY_UPDATE_NOT_REQUESTED + && updatetype != SSL_KEY_UPDATE_REQUESTED) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_KEY_UPDATE, + SSL_R_BAD_KEY_UPDATE); + return MSG_PROCESS_ERROR; + } + + /* + * If we get a request for us to update our sending keys too then, we need + * to additionally send a KeyUpdate message. However that message should + * not also request an update (otherwise we get into an infinite loop). We + * ignore a request for us to update our sending keys too if we already + * sent close_notify. + */ + if (updatetype == SSL_KEY_UPDATE_REQUESTED + && (s->shutdown & SSL_SENT_SHUTDOWN) == 0) + s->key_update = SSL_KEY_UPDATE_NOT_REQUESTED; + + if (!tls13_update_key(s, 0)) { + /* SSLfatal() already called */ + return MSG_PROCESS_ERROR; + } + + return MSG_PROCESS_FINISHED_READING; +} + +/* + * ssl3_take_mac calculates the Finished MAC for the handshakes messages seen + * to far. + */ +int ssl3_take_mac(SSL *s) +{ + const char *sender; + size_t slen; + + if (!s->server) { + sender = s->method->ssl3_enc->server_finished_label; + slen = s->method->ssl3_enc->server_finished_label_len; + } else { + sender = s->method->ssl3_enc->client_finished_label; + slen = s->method->ssl3_enc->client_finished_label_len; + } + + s->s3->tmp.peer_finish_md_len = + s->method->ssl3_enc->final_finish_mac(s, sender, slen, + s->s3->tmp.peer_finish_md); + + if (s->s3->tmp.peer_finish_md_len == 0) { + /* SSLfatal() already called */ + return 0; + } + + return 1; +} + +MSG_PROCESS_RETURN tls_process_change_cipher_spec(SSL *s, PACKET *pkt) +{ + size_t remain; + + remain = PACKET_remaining(pkt); + /* + * 'Change Cipher Spec' is just a single byte, which should already have + * been consumed by ssl_get_message() so there should be no bytes left, + * unless we're using DTLS1_BAD_VER, which has an extra 2 bytes + */ + if (SSL_IS_DTLS(s)) { + if ((s->version == DTLS1_BAD_VER + && remain != DTLS1_CCS_HEADER_LENGTH + 1) + || (s->version != DTLS1_BAD_VER + && remain != DTLS1_CCS_HEADER_LENGTH - 1)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, + SSL_R_BAD_CHANGE_CIPHER_SPEC); + return MSG_PROCESS_ERROR; + } + } else { + if (remain != 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, + SSL_R_BAD_CHANGE_CIPHER_SPEC); + return MSG_PROCESS_ERROR; + } + } + + /* Check we have a cipher to change to */ + if (s->s3->tmp.new_cipher == NULL) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, + SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, SSL_R_CCS_RECEIVED_EARLY); + return MSG_PROCESS_ERROR; + } + + s->s3->change_cipher_spec = 1; + if (!ssl3_do_change_cipher_spec(s)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, + ERR_R_INTERNAL_ERROR); + return MSG_PROCESS_ERROR; + } + + if (SSL_IS_DTLS(s)) { + dtls1_reset_seq_numbers(s, SSL3_CC_READ); + + if (s->version == DTLS1_BAD_VER) + s->d1->handshake_read_seq++; + +#ifndef OPENSSL_NO_SCTP + /* + * Remember that a CCS has been received, so that an old key of + * SCTP-Auth can be deleted when a CCS is sent. Will be ignored if no + * SCTP is used + */ + BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD, 1, NULL); +#endif + } + + return MSG_PROCESS_CONTINUE_READING; +} + +MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt) +{ + size_t md_len; + + + /* This is a real handshake so make sure we clean it up at the end */ + if (s->server) { + /* + * To get this far we must have read encrypted data from the client. We + * no longer tolerate unencrypted alerts. This value is ignored if less + * than TLSv1.3 + */ + s->statem.enc_read_state = ENC_READ_STATE_VALID; + if (s->post_handshake_auth != SSL_PHA_REQUESTED) + s->statem.cleanuphand = 1; + if (SSL_IS_TLS13(s) && !tls13_save_handshake_digest_for_pha(s)) { + /* SSLfatal() already called */ + return MSG_PROCESS_ERROR; + } + } + + /* + * In TLSv1.3 a Finished message signals a key change so the end of the + * message must be on a record boundary. + */ + if (SSL_IS_TLS13(s) && RECORD_LAYER_processed_read_pending(&s->rlayer)) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_FINISHED, + SSL_R_NOT_ON_RECORD_BOUNDARY); + return MSG_PROCESS_ERROR; + } + + /* If this occurs, we have missed a message */ + if (!SSL_IS_TLS13(s) && !s->s3->change_cipher_spec) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_FINISHED, + SSL_R_GOT_A_FIN_BEFORE_A_CCS); + return MSG_PROCESS_ERROR; + } + s->s3->change_cipher_spec = 0; + + md_len = s->s3->tmp.peer_finish_md_len; + + if (md_len != PACKET_remaining(pkt)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_FINISHED, + SSL_R_BAD_DIGEST_LENGTH); + return MSG_PROCESS_ERROR; + } + + if (CRYPTO_memcmp(PACKET_data(pkt), s->s3->tmp.peer_finish_md, + md_len) != 0) { + SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_FINISHED, + SSL_R_DIGEST_CHECK_FAILED); + return MSG_PROCESS_ERROR; + } + + /* + * Copy the finished so we can use it for renegotiation checks + */ + if (!ossl_assert(md_len <= EVP_MAX_MD_SIZE)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_FINISHED, + ERR_R_INTERNAL_ERROR); + return MSG_PROCESS_ERROR; + } + if (s->server) { + memcpy(s->s3->previous_client_finished, s->s3->tmp.peer_finish_md, + md_len); + s->s3->previous_client_finished_len = md_len; + } else { + memcpy(s->s3->previous_server_finished, s->s3->tmp.peer_finish_md, + md_len); + s->s3->previous_server_finished_len = md_len; + } + + /* + * In TLS1.3 we also have to change cipher state and do any final processing + * of the initial server flight (if we are a client) + */ + if (SSL_IS_TLS13(s)) { + if (s->server) { + if (s->post_handshake_auth != SSL_PHA_REQUESTED && + !s->method->ssl3_enc->change_cipher_state(s, + SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_SERVER_READ)) { + /* SSLfatal() already called */ + return MSG_PROCESS_ERROR; + } + } else { + if (!s->method->ssl3_enc->generate_master_secret(s, + s->master_secret, s->handshake_secret, 0, + &s->session->master_key_length)) { + /* SSLfatal() already called */ + return MSG_PROCESS_ERROR; + } + if (!s->method->ssl3_enc->change_cipher_state(s, + SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_CLIENT_READ)) { + /* SSLfatal() already called */ + return MSG_PROCESS_ERROR; + } + if (!tls_process_initial_server_flight(s)) { + /* SSLfatal() already called */ + return MSG_PROCESS_ERROR; + } + } + } + + return MSG_PROCESS_FINISHED_READING; +} + +int tls_construct_change_cipher_spec(SSL *s, WPACKET *pkt) +{ + if (!WPACKET_put_bytes_u8(pkt, SSL3_MT_CCS)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} + +/* Add a certificate to the WPACKET */ +static int ssl_add_cert_to_wpacket(SSL *s, WPACKET *pkt, X509 *x, int chain) +{ + int len; + unsigned char *outbytes; + + len = i2d_X509(x, NULL); + if (len < 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_TO_WPACKET, + ERR_R_BUF_LIB); + return 0; + } + if (!WPACKET_sub_allocate_bytes_u24(pkt, len, &outbytes) + || i2d_X509(x, &outbytes) != len) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_TO_WPACKET, + ERR_R_INTERNAL_ERROR); + return 0; + } + + if (SSL_IS_TLS13(s) + && !tls_construct_extensions(s, pkt, SSL_EXT_TLS1_3_CERTIFICATE, x, + chain)) { + /* SSLfatal() already called */ + return 0; + } + + return 1; +} + +/* Add certificate chain to provided WPACKET */ +static int ssl_add_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk) +{ + int i, chain_count; + X509 *x; + STACK_OF(X509) *extra_certs; + STACK_OF(X509) *chain = NULL; + X509_STORE *chain_store; + + if (cpk == NULL || cpk->x509 == NULL) + return 1; + + x = cpk->x509; + + /* + * If we have a certificate specific chain use it, else use parent ctx. + */ + if (cpk->chain != NULL) + extra_certs = cpk->chain; + else + extra_certs = s->ctx->extra_certs; + + if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || extra_certs) + chain_store = NULL; + else if (s->cert->chain_store) + chain_store = s->cert->chain_store; + else + chain_store = s->ctx->cert_store; + + if (chain_store != NULL) { + X509_STORE_CTX *xs_ctx = X509_STORE_CTX_new(); + + if (xs_ctx == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN, + ERR_R_MALLOC_FAILURE); + return 0; + } + if (!X509_STORE_CTX_init(xs_ctx, chain_store, x, NULL)) { + X509_STORE_CTX_free(xs_ctx); + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN, + ERR_R_X509_LIB); + return 0; + } + /* + * It is valid for the chain not to be complete (because normally we + * don't include the root cert in the chain). Therefore we deliberately + * ignore the error return from this call. We're not actually verifying + * the cert - we're just building as much of the chain as we can + */ + (void)X509_verify_cert(xs_ctx); + /* Don't leave errors in the queue */ + ERR_clear_error(); + chain = X509_STORE_CTX_get0_chain(xs_ctx); + i = ssl_security_cert_chain(s, chain, NULL, 0); + if (i != 1) { +#if 0 + /* Dummy error calls so mkerr generates them */ + SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_EE_KEY_TOO_SMALL); + SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_CA_KEY_TOO_SMALL); + SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_CA_MD_TOO_WEAK); +#endif + X509_STORE_CTX_free(xs_ctx); + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN, i); + return 0; + } + chain_count = sk_X509_num(chain); + for (i = 0; i < chain_count; i++) { + x = sk_X509_value(chain, i); + + if (!ssl_add_cert_to_wpacket(s, pkt, x, i)) { + /* SSLfatal() already called */ + X509_STORE_CTX_free(xs_ctx); + return 0; + } + } + X509_STORE_CTX_free(xs_ctx); + } else { + i = ssl_security_cert_chain(s, extra_certs, x, 0); + if (i != 1) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN, i); + return 0; + } + if (!ssl_add_cert_to_wpacket(s, pkt, x, 0)) { + /* SSLfatal() already called */ + return 0; + } + for (i = 0; i < sk_X509_num(extra_certs); i++) { + x = sk_X509_value(extra_certs, i); + if (!ssl_add_cert_to_wpacket(s, pkt, x, i + 1)) { + /* SSLfatal() already called */ + return 0; + } + } + } + return 1; +} + +unsigned long ssl3_output_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk) +{ + if (!WPACKET_start_sub_packet_u24(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_OUTPUT_CERT_CHAIN, + ERR_R_INTERNAL_ERROR); + return 0; + } + + if (!ssl_add_cert_chain(s, pkt, cpk)) + return 0; + + if (!WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_OUTPUT_CERT_CHAIN, + ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} + +/* + * Tidy up after the end of a handshake. In the case of SCTP this may result + * in NBIO events. If |clearbufs| is set then init_buf and the wbio buffer is + * freed up as well. + */ +WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs, int stop) +{ + void (*cb) (const SSL *ssl, int type, int val) = NULL; + int cleanuphand = s->statem.cleanuphand; + + if (clearbufs) { + if (!SSL_IS_DTLS(s)) { + /* + * We don't do this in DTLS because we may still need the init_buf + * in case there are any unexpected retransmits + */ + BUF_MEM_free(s->init_buf); + s->init_buf = NULL; + } + if (!ssl_free_wbio_buffer(s)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_FINISH_HANDSHAKE, + ERR_R_INTERNAL_ERROR); + return WORK_ERROR; + } + s->init_num = 0; + } + + if (SSL_IS_TLS13(s) && !s->server + && s->post_handshake_auth == SSL_PHA_REQUESTED) + s->post_handshake_auth = SSL_PHA_EXT_SENT; + + /* + * Only set if there was a Finished message and this isn't after a TLSv1.3 + * post handshake exchange + */ + if (cleanuphand) { + /* skipped if we just sent a HelloRequest */ + s->renegotiate = 0; + s->new_session = 0; + s->statem.cleanuphand = 0; + s->ext.ticket_expected = 0; + + ssl3_cleanup_key_block(s); + + if (s->server) { + /* + * In TLSv1.3 we update the cache as part of constructing the + * NewSessionTicket + */ + if (!SSL_IS_TLS13(s)) + ssl_update_cache(s, SSL_SESS_CACHE_SERVER); + + /* N.B. s->ctx may not equal s->session_ctx */ + tsan_counter(&s->ctx->stats.sess_accept_good); + s->handshake_func = ossl_statem_accept; + } else { + if (SSL_IS_TLS13(s)) { + /* + * We encourage applications to only use TLSv1.3 tickets once, + * so we remove this one from the cache. + */ + if ((s->session_ctx->session_cache_mode + & SSL_SESS_CACHE_CLIENT) != 0) + SSL_CTX_remove_session(s->session_ctx, s->session); + } else { + /* + * In TLSv1.3 we update the cache as part of processing the + * NewSessionTicket + */ + ssl_update_cache(s, SSL_SESS_CACHE_CLIENT); + } + if (s->hit) + tsan_counter(&s->session_ctx->stats.sess_hit); + + s->handshake_func = ossl_statem_connect; + tsan_counter(&s->session_ctx->stats.sess_connect_good); + } + + if (SSL_IS_DTLS(s)) { + /* done with handshaking */ + s->d1->handshake_read_seq = 0; + s->d1->handshake_write_seq = 0; + s->d1->next_handshake_write_seq = 0; + dtls1_clear_received_buffer(s); + } + } + + if (s->info_callback != NULL) + cb = s->info_callback; + else if (s->ctx->info_callback != NULL) + cb = s->ctx->info_callback; + + /* The callback may expect us to not be in init at handshake done */ + ossl_statem_set_in_init(s, 0); + + if (cb != NULL) { + if (cleanuphand + || !SSL_IS_TLS13(s) + || SSL_IS_FIRST_HANDSHAKE(s)) + cb(s, SSL_CB_HANDSHAKE_DONE, 1); + } + + if (!stop) { + /* If we've got more work to do we go back into init */ + ossl_statem_set_in_init(s, 1); + return WORK_FINISHED_CONTINUE; + } + + return WORK_FINISHED_STOP; +} + +int tls_get_message_header(SSL *s, int *mt) +{ + /* s->init_num < SSL3_HM_HEADER_LENGTH */ + int skip_message, i, recvd_type; + unsigned char *p; + size_t l, readbytes; + + p = (unsigned char *)s->init_buf->data; + + do { + while (s->init_num < SSL3_HM_HEADER_LENGTH) { + i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, &recvd_type, + &p[s->init_num], + SSL3_HM_HEADER_LENGTH - s->init_num, + 0, &readbytes); + if (i <= 0) { + s->rwstate = SSL_READING; + return 0; + } + if (recvd_type == SSL3_RT_CHANGE_CIPHER_SPEC) { + /* + * A ChangeCipherSpec must be a single byte and may not occur + * in the middle of a handshake message. + */ + if (s->init_num != 0 || readbytes != 1 || p[0] != SSL3_MT_CCS) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, + SSL_F_TLS_GET_MESSAGE_HEADER, + SSL_R_BAD_CHANGE_CIPHER_SPEC); + return 0; + } + if (s->statem.hand_state == TLS_ST_BEFORE + && (s->s3->flags & TLS1_FLAGS_STATELESS) != 0) { + /* + * We are stateless and we received a CCS. Probably this is + * from a client between the first and second ClientHellos. + * We should ignore this, but return an error because we do + * not return success until we see the second ClientHello + * with a valid cookie. + */ + return 0; + } + s->s3->tmp.message_type = *mt = SSL3_MT_CHANGE_CIPHER_SPEC; + s->init_num = readbytes - 1; + s->init_msg = s->init_buf->data; + s->s3->tmp.message_size = readbytes; + return 1; + } else if (recvd_type != SSL3_RT_HANDSHAKE) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, + SSL_F_TLS_GET_MESSAGE_HEADER, + SSL_R_CCS_RECEIVED_EARLY); + return 0; + } + s->init_num += readbytes; + } + + skip_message = 0; + if (!s->server) + if (s->statem.hand_state != TLS_ST_OK + && p[0] == SSL3_MT_HELLO_REQUEST) + /* + * The server may always send 'Hello Request' messages -- + * we are doing a handshake anyway now, so ignore them if + * their format is correct. Does not count for 'Finished' + * MAC. + */ + if (p[1] == 0 && p[2] == 0 && p[3] == 0) { + s->init_num = 0; + skip_message = 1; + + if (s->msg_callback) + s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, + p, SSL3_HM_HEADER_LENGTH, s, + s->msg_callback_arg); + } + } while (skip_message); + /* s->init_num == SSL3_HM_HEADER_LENGTH */ + + *mt = *p; + s->s3->tmp.message_type = *(p++); + + if (RECORD_LAYER_is_sslv2_record(&s->rlayer)) { + /* + * Only happens with SSLv3+ in an SSLv2 backward compatible + * ClientHello + * + * Total message size is the remaining record bytes to read + * plus the SSL3_HM_HEADER_LENGTH bytes that we already read + */ + l = RECORD_LAYER_get_rrec_length(&s->rlayer) + + SSL3_HM_HEADER_LENGTH; + s->s3->tmp.message_size = l; + + s->init_msg = s->init_buf->data; + s->init_num = SSL3_HM_HEADER_LENGTH; + } else { + n2l3(p, l); + /* BUF_MEM_grow takes an 'int' parameter */ + if (l > (INT_MAX - SSL3_HM_HEADER_LENGTH)) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_GET_MESSAGE_HEADER, + SSL_R_EXCESSIVE_MESSAGE_SIZE); + return 0; + } + s->s3->tmp.message_size = l; + + s->init_msg = s->init_buf->data + SSL3_HM_HEADER_LENGTH; + s->init_num = 0; + } + + return 1; +} + +int tls_get_message_body(SSL *s, size_t *len) +{ + size_t n, readbytes; + unsigned char *p; + int i; + + if (s->s3->tmp.message_type == SSL3_MT_CHANGE_CIPHER_SPEC) { + /* We've already read everything in */ + *len = (unsigned long)s->init_num; + return 1; + } + + p = s->init_msg; + n = s->s3->tmp.message_size - s->init_num; + while (n > 0) { + i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL, + &p[s->init_num], n, 0, &readbytes); + if (i <= 0) { + s->rwstate = SSL_READING; + *len = 0; + return 0; + } + s->init_num += readbytes; + n -= readbytes; + } + + /* + * If receiving Finished, record MAC of prior handshake messages for + * Finished verification. + */ + if (*(s->init_buf->data) == SSL3_MT_FINISHED && !ssl3_take_mac(s)) { + /* SSLfatal() already called */ + *len = 0; + return 0; + } + + /* Feed this message into MAC computation. */ + if (RECORD_LAYER_is_sslv2_record(&s->rlayer)) { + if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, + s->init_num)) { + /* SSLfatal() already called */ + *len = 0; + return 0; + } + if (s->msg_callback) + s->msg_callback(0, SSL2_VERSION, 0, s->init_buf->data, + (size_t)s->init_num, s, s->msg_callback_arg); + } else { + /* + * We defer feeding in the HRR until later. We'll do it as part of + * processing the message + * The TLsv1.3 handshake transcript stops at the ClientFinished + * message. + */ +#define SERVER_HELLO_RANDOM_OFFSET (SSL3_HM_HEADER_LENGTH + 2) + /* KeyUpdate and NewSessionTicket do not need to be added */ + if (!SSL_IS_TLS13(s) || (s->s3->tmp.message_type != SSL3_MT_NEWSESSION_TICKET + && s->s3->tmp.message_type != SSL3_MT_KEY_UPDATE)) { + if (s->s3->tmp.message_type != SSL3_MT_SERVER_HELLO + || s->init_num < SERVER_HELLO_RANDOM_OFFSET + SSL3_RANDOM_SIZE + || memcmp(hrrrandom, + s->init_buf->data + SERVER_HELLO_RANDOM_OFFSET, + SSL3_RANDOM_SIZE) != 0) { + if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, + s->init_num + SSL3_HM_HEADER_LENGTH)) { + /* SSLfatal() already called */ + *len = 0; + return 0; + } + } + } + if (s->msg_callback) + s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data, + (size_t)s->init_num + SSL3_HM_HEADER_LENGTH, s, + s->msg_callback_arg); + } + + *len = s->init_num; + return 1; +} + +static const X509ERR2ALERT x509table[] = { + {X509_V_ERR_APPLICATION_VERIFICATION, SSL_AD_HANDSHAKE_FAILURE}, + {X509_V_ERR_CA_KEY_TOO_SMALL, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_CA_MD_TOO_WEAK, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_CERT_CHAIN_TOO_LONG, SSL_AD_UNKNOWN_CA}, + {X509_V_ERR_CERT_HAS_EXPIRED, SSL_AD_CERTIFICATE_EXPIRED}, + {X509_V_ERR_CERT_NOT_YET_VALID, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_CERT_REJECTED, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_CERT_REVOKED, SSL_AD_CERTIFICATE_REVOKED}, + {X509_V_ERR_CERT_SIGNATURE_FAILURE, SSL_AD_DECRYPT_ERROR}, + {X509_V_ERR_CERT_UNTRUSTED, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_CRL_HAS_EXPIRED, SSL_AD_CERTIFICATE_EXPIRED}, + {X509_V_ERR_CRL_NOT_YET_VALID, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_CRL_SIGNATURE_FAILURE, SSL_AD_DECRYPT_ERROR}, + {X509_V_ERR_DANE_NO_MATCH, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT, SSL_AD_UNKNOWN_CA}, + {X509_V_ERR_EE_KEY_TOO_SMALL, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_EMAIL_MISMATCH, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_HOSTNAME_MISMATCH, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_INVALID_CA, SSL_AD_UNKNOWN_CA}, + {X509_V_ERR_INVALID_CALL, SSL_AD_INTERNAL_ERROR}, + {X509_V_ERR_INVALID_PURPOSE, SSL_AD_UNSUPPORTED_CERTIFICATE}, + {X509_V_ERR_IP_ADDRESS_MISMATCH, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_OUT_OF_MEM, SSL_AD_INTERNAL_ERROR}, + {X509_V_ERR_PATH_LENGTH_EXCEEDED, SSL_AD_UNKNOWN_CA}, + {X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN, SSL_AD_UNKNOWN_CA}, + {X509_V_ERR_STORE_LOOKUP, SSL_AD_INTERNAL_ERROR}, + {X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_UNABLE_TO_GET_CRL, SSL_AD_UNKNOWN_CA}, + {X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER, SSL_AD_UNKNOWN_CA}, + {X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT, SSL_AD_UNKNOWN_CA}, + {X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, SSL_AD_UNKNOWN_CA}, + {X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE, SSL_AD_UNKNOWN_CA}, + {X509_V_ERR_UNSPECIFIED, SSL_AD_INTERNAL_ERROR}, + + /* Last entry; return this if we don't find the value above. */ + {X509_V_OK, SSL_AD_CERTIFICATE_UNKNOWN} +}; + +int ssl_x509err2alert(int x509err) +{ + const X509ERR2ALERT *tp; + + for (tp = x509table; tp->x509err != X509_V_OK; ++tp) + if (tp->x509err == x509err) + break; + return tp->alert; +} + +int ssl_allow_compression(SSL *s) +{ + if (s->options & SSL_OP_NO_COMPRESSION) + return 0; + return ssl_security(s, SSL_SECOP_COMPRESSION, 0, 0, NULL); +} + +static int version_cmp(const SSL *s, int a, int b) +{ + int dtls = SSL_IS_DTLS(s); + + if (a == b) + return 0; + if (!dtls) + return a < b ? -1 : 1; + return DTLS_VERSION_LT(a, b) ? -1 : 1; +} + +typedef struct { + int version; + const SSL_METHOD *(*cmeth) (void); + const SSL_METHOD *(*smeth) (void); +} version_info; + +#if TLS_MAX_VERSION != TLS1_3_VERSION +# error Code needs update for TLS_method() support beyond TLS1_3_VERSION. +#endif + +/* Must be in order high to low */ +static const version_info tls_version_table[] = { +#ifndef OPENSSL_NO_TLS1_3 + {TLS1_3_VERSION, tlsv1_3_client_method, tlsv1_3_server_method}, +#else + {TLS1_3_VERSION, NULL, NULL}, +#endif +#ifndef OPENSSL_NO_TLS1_2 + {TLS1_2_VERSION, tlsv1_2_client_method, tlsv1_2_server_method}, +#else + {TLS1_2_VERSION, NULL, NULL}, +#endif +#ifndef OPENSSL_NO_TLS1_1 + {TLS1_1_VERSION, tlsv1_1_client_method, tlsv1_1_server_method}, +#else + {TLS1_1_VERSION, NULL, NULL}, +#endif +#ifndef OPENSSL_NO_TLS1 + {TLS1_VERSION, tlsv1_client_method, tlsv1_server_method}, +#else + {TLS1_VERSION, NULL, NULL}, +#endif +#ifndef OPENSSL_NO_SSL3 + {SSL3_VERSION, sslv3_client_method, sslv3_server_method}, +#else + {SSL3_VERSION, NULL, NULL}, +#endif + {0, NULL, NULL}, +}; + +#if DTLS_MAX_VERSION != DTLS1_2_VERSION +# error Code needs update for DTLS_method() support beyond DTLS1_2_VERSION. +#endif + +/* Must be in order high to low */ +static const version_info dtls_version_table[] = { +#ifndef OPENSSL_NO_DTLS1_2 + {DTLS1_2_VERSION, dtlsv1_2_client_method, dtlsv1_2_server_method}, +#else + {DTLS1_2_VERSION, NULL, NULL}, +#endif +#ifndef OPENSSL_NO_DTLS1 + {DTLS1_VERSION, dtlsv1_client_method, dtlsv1_server_method}, + {DTLS1_BAD_VER, dtls_bad_ver_client_method, NULL}, +#else + {DTLS1_VERSION, NULL, NULL}, + {DTLS1_BAD_VER, NULL, NULL}, +#endif + {0, NULL, NULL}, +}; + +/* + * ssl_method_error - Check whether an SSL_METHOD is enabled. + * + * @s: The SSL handle for the candidate method + * @method: the intended method. + * + * Returns 0 on success, or an SSL error reason on failure. + */ +static int ssl_method_error(const SSL *s, const SSL_METHOD *method) +{ + int version = method->version; + + if ((s->min_proto_version != 0 && + version_cmp(s, version, s->min_proto_version) < 0) || + ssl_security(s, SSL_SECOP_VERSION, 0, version, NULL) == 0) + return SSL_R_VERSION_TOO_LOW; + + if (s->max_proto_version != 0 && + version_cmp(s, version, s->max_proto_version) > 0) + return SSL_R_VERSION_TOO_HIGH; + + if ((s->options & method->mask) != 0) + return SSL_R_UNSUPPORTED_PROTOCOL; + if ((method->flags & SSL_METHOD_NO_SUITEB) != 0 && tls1_suiteb(s)) + return SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE; + + return 0; +} + +/* + * Only called by servers. Returns 1 if the server has a TLSv1.3 capable + * certificate type, or has PSK or a certificate callback configured. Otherwise + * returns 0. + */ +static int is_tls13_capable(const SSL *s) +{ + int i; +#ifndef OPENSSL_NO_EC + int curve; + EC_KEY *eckey; +#endif + +#ifndef OPENSSL_NO_PSK + if (s->psk_server_callback != NULL) + return 1; +#endif + + if (s->psk_find_session_cb != NULL || s->cert->cert_cb != NULL) + return 1; + + for (i = 0; i < SSL_PKEY_NUM; i++) { + /* Skip over certs disallowed for TLSv1.3 */ + switch (i) { + case SSL_PKEY_DSA_SIGN: + case SSL_PKEY_GOST01: + case SSL_PKEY_GOST12_256: + case SSL_PKEY_GOST12_512: + continue; + default: + break; + } + if (!ssl_has_cert(s, i)) + continue; +#ifndef OPENSSL_NO_EC + if (i != SSL_PKEY_ECC) + return 1; + /* + * Prior to TLSv1.3 sig algs allowed any curve to be used. TLSv1.3 is + * more restrictive so check that our sig algs are consistent with this + * EC cert. See section 4.2.3 of RFC8446. + */ + eckey = EVP_PKEY_get0_EC_KEY(s->cert->pkeys[SSL_PKEY_ECC].privatekey); + if (eckey == NULL) + continue; + curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey)); + if (tls_check_sigalg_curve(s, curve)) + return 1; +#else + return 1; +#endif + } + + return 0; +} + +/* + * ssl_version_supported - Check that the specified `version` is supported by + * `SSL *` instance + * + * @s: The SSL handle for the candidate method + * @version: Protocol version to test against + * + * Returns 1 when supported, otherwise 0 + */ +int ssl_version_supported(const SSL *s, int version, const SSL_METHOD **meth) +{ + const version_info *vent; + const version_info *table; + + switch (s->method->version) { + default: + /* Version should match method version for non-ANY method */ + return version_cmp(s, version, s->version) == 0; + case TLS_ANY_VERSION: + table = tls_version_table; + break; + case DTLS_ANY_VERSION: + table = dtls_version_table; + break; + } + + for (vent = table; + vent->version != 0 && version_cmp(s, version, vent->version) <= 0; + ++vent) { + if (vent->cmeth != NULL + && version_cmp(s, version, vent->version) == 0 + && ssl_method_error(s, vent->cmeth()) == 0 + && (!s->server + || version != TLS1_3_VERSION + || is_tls13_capable(s))) { + if (meth != NULL) + *meth = vent->cmeth(); + return 1; + } + } + return 0; +} + +/* + * ssl_check_version_downgrade - In response to RFC7507 SCSV version + * fallback indication from a client check whether we're using the highest + * supported protocol version. + * + * @s server SSL handle. + * + * Returns 1 when using the highest enabled version, 0 otherwise. + */ +int ssl_check_version_downgrade(SSL *s) +{ + const version_info *vent; + const version_info *table; + + /* + * Check that the current protocol is the highest enabled version + * (according to s->ctx->method, as version negotiation may have changed + * s->method). + */ + if (s->version == s->ctx->method->version) + return 1; + + /* + * Apparently we're using a version-flexible SSL_METHOD (not at its + * highest protocol version). + */ + if (s->ctx->method->version == TLS_method()->version) + table = tls_version_table; + else if (s->ctx->method->version == DTLS_method()->version) + table = dtls_version_table; + else { + /* Unexpected state; fail closed. */ + return 0; + } + + for (vent = table; vent->version != 0; ++vent) { + if (vent->smeth != NULL && ssl_method_error(s, vent->smeth()) == 0) + return s->version == vent->version; + } + return 0; +} + +/* + * ssl_set_version_bound - set an upper or lower bound on the supported (D)TLS + * protocols, provided the initial (D)TLS method is version-flexible. This + * function sanity-checks the proposed value and makes sure the method is + * version-flexible, then sets the limit if all is well. + * + * @method_version: The version of the current SSL_METHOD. + * @version: the intended limit. + * @bound: pointer to limit to be updated. + * + * Returns 1 on success, 0 on failure. + */ +int ssl_set_version_bound(int method_version, int version, int *bound) +{ + if (version == 0) { + *bound = version; + return 1; + } + + /*- + * Restrict TLS methods to TLS protocol versions. + * Restrict DTLS methods to DTLS protocol versions. + * Note, DTLS version numbers are decreasing, use comparison macros. + * + * Note that for both lower-bounds we use explicit versions, not + * (D)TLS_MIN_VERSION. This is because we don't want to break user + * configurations. If the MIN (supported) version ever rises, the user's + * "floor" remains valid even if no longer available. We don't expect the + * MAX ceiling to ever get lower, so making that variable makes sense. + */ + switch (method_version) { + default: + /* + * XXX For fixed version methods, should we always fail and not set any + * bounds, always succeed and not set any bounds, or set the bounds and + * arrange to fail later if they are not met? At present fixed-version + * methods are not subject to controls that disable individual protocol + * versions. + */ + return 0; + + case TLS_ANY_VERSION: + if (version < SSL3_VERSION || version > TLS_MAX_VERSION) + return 0; + break; + + case DTLS_ANY_VERSION: + if (DTLS_VERSION_GT(version, DTLS_MAX_VERSION) || + DTLS_VERSION_LT(version, DTLS1_BAD_VER)) + return 0; + break; + } + + *bound = version; + return 1; +} + +static void check_for_downgrade(SSL *s, int vers, DOWNGRADE *dgrd) +{ + if (vers == TLS1_2_VERSION + && ssl_version_supported(s, TLS1_3_VERSION, NULL)) { + *dgrd = DOWNGRADE_TO_1_2; + } else if (!SSL_IS_DTLS(s) + && vers < TLS1_2_VERSION + /* + * We need to ensure that a server that disables TLSv1.2 + * (creating a hole between TLSv1.3 and TLSv1.1) can still + * complete handshakes with clients that support TLSv1.2 and + * below. Therefore we do not enable the sentinel if TLSv1.3 is + * enabled and TLSv1.2 is not. + */ + && ssl_version_supported(s, TLS1_2_VERSION, NULL)) { + *dgrd = DOWNGRADE_TO_1_1; + } else { + *dgrd = DOWNGRADE_NONE; + } +} + +/* + * ssl_choose_server_version - Choose server (D)TLS version. Called when the + * client HELLO is received to select the final server protocol version and + * the version specific method. + * + * @s: server SSL handle. + * + * Returns 0 on success or an SSL error reason number on failure. + */ +int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello, DOWNGRADE *dgrd) +{ + /*- + * With version-flexible methods we have an initial state with: + * + * s->method->version == (D)TLS_ANY_VERSION, + * s->version == (D)TLS_MAX_VERSION. + * + * So we detect version-flexible methods via the method version, not the + * handle version. + */ + int server_version = s->method->version; + int client_version = hello->legacy_version; + const version_info *vent; + const version_info *table; + int disabled = 0; + RAW_EXTENSION *suppversions; + + s->client_version = client_version; + + switch (server_version) { + default: + if (!SSL_IS_TLS13(s)) { + if (version_cmp(s, client_version, s->version) < 0) + return SSL_R_WRONG_SSL_VERSION; + *dgrd = DOWNGRADE_NONE; + /* + * If this SSL handle is not from a version flexible method we don't + * (and never did) check min/max FIPS or Suite B constraints. Hope + * that's OK. It is up to the caller to not choose fixed protocol + * versions they don't want. If not, then easy to fix, just return + * ssl_method_error(s, s->method) + */ + return 0; + } + /* + * Fall through if we are TLSv1.3 already (this means we must be after + * a HelloRetryRequest + */ + /* fall thru */ + case TLS_ANY_VERSION: + table = tls_version_table; + break; + case DTLS_ANY_VERSION: + table = dtls_version_table; + break; + } + + suppversions = &hello->pre_proc_exts[TLSEXT_IDX_supported_versions]; + + /* If we did an HRR then supported versions is mandatory */ + if (!suppversions->present && s->hello_retry_request != SSL_HRR_NONE) + return SSL_R_UNSUPPORTED_PROTOCOL; + + if (suppversions->present && !SSL_IS_DTLS(s)) { + unsigned int candidate_vers = 0; + unsigned int best_vers = 0; + const SSL_METHOD *best_method = NULL; + PACKET versionslist; + + suppversions->parsed = 1; + + if (!PACKET_as_length_prefixed_1(&suppversions->data, &versionslist)) { + /* Trailing or invalid data? */ + return SSL_R_LENGTH_MISMATCH; + } + + /* + * The TLSv1.3 spec says the client MUST set this to TLS1_2_VERSION. + * The spec only requires servers to check that it isn't SSLv3: + * "Any endpoint receiving a Hello message with + * ClientHello.legacy_version or ServerHello.legacy_version set to + * 0x0300 MUST abort the handshake with a "protocol_version" alert." + * We are slightly stricter and require that it isn't SSLv3 or lower. + * We tolerate TLSv1 and TLSv1.1. + */ + if (client_version <= SSL3_VERSION) + return SSL_R_BAD_LEGACY_VERSION; + + while (PACKET_get_net_2(&versionslist, &candidate_vers)) { + if (version_cmp(s, candidate_vers, best_vers) <= 0) + continue; + if (ssl_version_supported(s, candidate_vers, &best_method)) + best_vers = candidate_vers; + } + if (PACKET_remaining(&versionslist) != 0) { + /* Trailing data? */ + return SSL_R_LENGTH_MISMATCH; + } + + if (best_vers > 0) { + if (s->hello_retry_request != SSL_HRR_NONE) { + /* + * This is after a HelloRetryRequest so we better check that we + * negotiated TLSv1.3 + */ + if (best_vers != TLS1_3_VERSION) + return SSL_R_UNSUPPORTED_PROTOCOL; + return 0; + } + check_for_downgrade(s, best_vers, dgrd); + s->version = best_vers; + s->method = best_method; + return 0; + } + return SSL_R_UNSUPPORTED_PROTOCOL; + } + + /* + * If the supported versions extension isn't present, then the highest + * version we can negotiate is TLSv1.2 + */ + if (version_cmp(s, client_version, TLS1_3_VERSION) >= 0) + client_version = TLS1_2_VERSION; + + /* + * No supported versions extension, so we just use the version supplied in + * the ClientHello. + */ + for (vent = table; vent->version != 0; ++vent) { + const SSL_METHOD *method; + + if (vent->smeth == NULL || + version_cmp(s, client_version, vent->version) < 0) + continue; + method = vent->smeth(); + if (ssl_method_error(s, method) == 0) { + check_for_downgrade(s, vent->version, dgrd); + s->version = vent->version; + s->method = method; + return 0; + } + disabled = 1; + } + return disabled ? SSL_R_UNSUPPORTED_PROTOCOL : SSL_R_VERSION_TOO_LOW; +} + +/* + * ssl_choose_client_version - Choose client (D)TLS version. Called when the + * server HELLO is received to select the final client protocol version and + * the version specific method. + * + * @s: client SSL handle. + * @version: The proposed version from the server's HELLO. + * @extensions: The extensions received + * + * Returns 1 on success or 0 on error. + */ +int ssl_choose_client_version(SSL *s, int version, RAW_EXTENSION *extensions) +{ + const version_info *vent; + const version_info *table; + int ret, ver_min, ver_max, real_max, origv; + + origv = s->version; + s->version = version; + + /* This will overwrite s->version if the extension is present */ + if (!tls_parse_extension(s, TLSEXT_IDX_supported_versions, + SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_3_SERVER_HELLO, extensions, + NULL, 0)) { + s->version = origv; + return 0; + } + + if (s->hello_retry_request != SSL_HRR_NONE + && s->version != TLS1_3_VERSION) { + s->version = origv; + SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_SSL_CHOOSE_CLIENT_VERSION, + SSL_R_WRONG_SSL_VERSION); + return 0; + } + + switch (s->method->version) { + default: + if (s->version != s->method->version) { + s->version = origv; + SSLfatal(s, SSL_AD_PROTOCOL_VERSION, + SSL_F_SSL_CHOOSE_CLIENT_VERSION, + SSL_R_WRONG_SSL_VERSION); + return 0; + } + /* + * If this SSL handle is not from a version flexible method we don't + * (and never did) check min/max, FIPS or Suite B constraints. Hope + * that's OK. It is up to the caller to not choose fixed protocol + * versions they don't want. If not, then easy to fix, just return + * ssl_method_error(s, s->method) + */ + return 1; + case TLS_ANY_VERSION: + table = tls_version_table; + break; + case DTLS_ANY_VERSION: + table = dtls_version_table; + break; + } + + ret = ssl_get_min_max_version(s, &ver_min, &ver_max, &real_max); + if (ret != 0) { + s->version = origv; + SSLfatal(s, SSL_AD_PROTOCOL_VERSION, + SSL_F_SSL_CHOOSE_CLIENT_VERSION, ret); + return 0; + } + if (SSL_IS_DTLS(s) ? DTLS_VERSION_LT(s->version, ver_min) + : s->version < ver_min) { + s->version = origv; + SSLfatal(s, SSL_AD_PROTOCOL_VERSION, + SSL_F_SSL_CHOOSE_CLIENT_VERSION, SSL_R_UNSUPPORTED_PROTOCOL); + return 0; + } else if (SSL_IS_DTLS(s) ? DTLS_VERSION_GT(s->version, ver_max) + : s->version > ver_max) { + s->version = origv; + SSLfatal(s, SSL_AD_PROTOCOL_VERSION, + SSL_F_SSL_CHOOSE_CLIENT_VERSION, SSL_R_UNSUPPORTED_PROTOCOL); + return 0; + } + + if ((s->mode & SSL_MODE_SEND_FALLBACK_SCSV) == 0) + real_max = ver_max; + + /* Check for downgrades */ + if (s->version == TLS1_2_VERSION && real_max > s->version) { + if (memcmp(tls12downgrade, + s->s3->server_random + SSL3_RANDOM_SIZE + - sizeof(tls12downgrade), + sizeof(tls12downgrade)) == 0) { + s->version = origv; + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_SSL_CHOOSE_CLIENT_VERSION, + SSL_R_INAPPROPRIATE_FALLBACK); + return 0; + } + } else if (!SSL_IS_DTLS(s) + && s->version < TLS1_2_VERSION + && real_max > s->version) { + if (memcmp(tls11downgrade, + s->s3->server_random + SSL3_RANDOM_SIZE + - sizeof(tls11downgrade), + sizeof(tls11downgrade)) == 0) { + s->version = origv; + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_SSL_CHOOSE_CLIENT_VERSION, + SSL_R_INAPPROPRIATE_FALLBACK); + return 0; + } + } + + for (vent = table; vent->version != 0; ++vent) { + if (vent->cmeth == NULL || s->version != vent->version) + continue; + + s->method = vent->cmeth(); + return 1; + } + + s->version = origv; + SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_SSL_CHOOSE_CLIENT_VERSION, + SSL_R_UNSUPPORTED_PROTOCOL); + return 0; +} + +/* + * ssl_get_min_max_version - get minimum and maximum protocol version + * @s: The SSL connection + * @min_version: The minimum supported version + * @max_version: The maximum supported version + * @real_max: The highest version below the lowest compile time version hole + * where that hole lies above at least one run-time enabled + * protocol. + * + * Work out what version we should be using for the initial ClientHello if the + * version is initially (D)TLS_ANY_VERSION. We apply any explicit SSL_OP_NO_xxx + * options, the MinProtocol and MaxProtocol configuration commands, any Suite B + * constraints and any floor imposed by the security level here, + * so we don't advertise the wrong protocol version to only reject the outcome later. + * + * Computing the right floor matters. If, e.g., TLS 1.0 and 1.2 are enabled, + * TLS 1.1 is disabled, but the security level, Suite-B and/or MinProtocol + * only allow TLS 1.2, we want to advertise TLS1.2, *not* TLS1. + * + * Returns 0 on success or an SSL error reason number on failure. On failure + * min_version and max_version will also be set to 0. + */ +int ssl_get_min_max_version(const SSL *s, int *min_version, int *max_version, + int *real_max) +{ + int version, tmp_real_max; + int hole; + const SSL_METHOD *single = NULL; + const SSL_METHOD *method; + const version_info *table; + const version_info *vent; + + switch (s->method->version) { + default: + /* + * If this SSL handle is not from a version flexible method we don't + * (and never did) check min/max FIPS or Suite B constraints. Hope + * that's OK. It is up to the caller to not choose fixed protocol + * versions they don't want. If not, then easy to fix, just return + * ssl_method_error(s, s->method) + */ + *min_version = *max_version = s->version; + /* + * Providing a real_max only makes sense where we're using a version + * flexible method. + */ + if (!ossl_assert(real_max == NULL)) + return ERR_R_INTERNAL_ERROR; + return 0; + case TLS_ANY_VERSION: + table = tls_version_table; + break; + case DTLS_ANY_VERSION: + table = dtls_version_table; + break; + } + + /* + * SSL_OP_NO_X disables all protocols above X *if* there are some protocols + * below X enabled. This is required in order to maintain the "version + * capability" vector contiguous. Any versions with a NULL client method + * (protocol version client is disabled at compile-time) is also a "hole". + * + * Our initial state is hole == 1, version == 0. That is, versions above + * the first version in the method table are disabled (a "hole" above + * the valid protocol entries) and we don't have a selected version yet. + * + * Whenever "hole == 1", and we hit an enabled method, its version becomes + * the selected version, and the method becomes a candidate "single" + * method. We're no longer in a hole, so "hole" becomes 0. + * + * If "hole == 0" and we hit an enabled method, then "single" is cleared, + * as we support a contiguous range of at least two methods. If we hit + * a disabled method, then hole becomes true again, but nothing else + * changes yet, because all the remaining methods may be disabled too. + * If we again hit an enabled method after the new hole, it becomes + * selected, as we start from scratch. + */ + *min_version = version = 0; + hole = 1; + if (real_max != NULL) + *real_max = 0; + tmp_real_max = 0; + for (vent = table; vent->version != 0; ++vent) { + /* + * A table entry with a NULL client method is still a hole in the + * "version capability" vector. + */ + if (vent->cmeth == NULL) { + hole = 1; + tmp_real_max = 0; + continue; + } + method = vent->cmeth(); + + if (hole == 1 && tmp_real_max == 0) + tmp_real_max = vent->version; + + if (ssl_method_error(s, method) != 0) { + hole = 1; + } else if (!hole) { + single = NULL; + *min_version = method->version; + } else { + if (real_max != NULL && tmp_real_max != 0) + *real_max = tmp_real_max; + version = (single = method)->version; + *min_version = version; + hole = 0; + } + } + + *max_version = version; + + /* Fail if everything is disabled */ + if (version == 0) + return SSL_R_NO_PROTOCOLS_AVAILABLE; + + return 0; +} + +/* + * ssl_set_client_hello_version - Work out what version we should be using for + * the initial ClientHello.legacy_version field. + * + * @s: client SSL handle. + * + * Returns 0 on success or an SSL error reason number on failure. + */ +int ssl_set_client_hello_version(SSL *s) +{ + int ver_min, ver_max, ret; + + /* + * In a renegotiation we always send the same client_version that we sent + * last time, regardless of which version we eventually negotiated. + */ + if (!SSL_IS_FIRST_HANDSHAKE(s)) + return 0; + + ret = ssl_get_min_max_version(s, &ver_min, &ver_max, NULL); + + if (ret != 0) + return ret; + + s->version = ver_max; + + /* TLS1.3 always uses TLS1.2 in the legacy_version field */ + if (!SSL_IS_DTLS(s) && ver_max > TLS1_2_VERSION) + ver_max = TLS1_2_VERSION; + + s->client_version = ver_max; + return 0; +} + +/* + * Checks a list of |groups| to determine if the |group_id| is in it. If it is + * and |checkallow| is 1 then additionally check if the group is allowed to be + * used. Returns 1 if the group is in the list (and allowed if |checkallow| is + * 1) or 0 otherwise. + */ +#ifndef OPENSSL_NO_EC +int check_in_list(SSL *s, uint16_t group_id, const uint16_t *groups, + size_t num_groups, int checkallow) +{ + size_t i; + + if (groups == NULL || num_groups == 0) + return 0; + + for (i = 0; i < num_groups; i++) { + uint16_t group = groups[i]; + + if (group_id == group + && (!checkallow + || tls_curve_allowed(s, group, SSL_SECOP_CURVE_CHECK))) { + return 1; + } + } + + return 0; +} +#endif + +/* Replace ClientHello1 in the transcript hash with a synthetic message */ +int create_synthetic_message_hash(SSL *s, const unsigned char *hashval, + size_t hashlen, const unsigned char *hrr, + size_t hrrlen) +{ + unsigned char hashvaltmp[EVP_MAX_MD_SIZE]; + unsigned char msghdr[SSL3_HM_HEADER_LENGTH]; + + memset(msghdr, 0, sizeof(msghdr)); + + if (hashval == NULL) { + hashval = hashvaltmp; + hashlen = 0; + /* Get the hash of the initial ClientHello */ + if (!ssl3_digest_cached_records(s, 0) + || !ssl_handshake_hash(s, hashvaltmp, sizeof(hashvaltmp), + &hashlen)) { + /* SSLfatal() already called */ + return 0; + } + } + + /* Reinitialise the transcript hash */ + if (!ssl3_init_finished_mac(s)) { + /* SSLfatal() already called */ + return 0; + } + + /* Inject the synthetic message_hash message */ + msghdr[0] = SSL3_MT_MESSAGE_HASH; + msghdr[SSL3_HM_HEADER_LENGTH - 1] = (unsigned char)hashlen; + if (!ssl3_finish_mac(s, msghdr, SSL3_HM_HEADER_LENGTH) + || !ssl3_finish_mac(s, hashval, hashlen)) { + /* SSLfatal() already called */ + return 0; + } + + /* + * Now re-inject the HRR and current message if appropriate (we just deleted + * it when we reinitialised the transcript hash above). Only necessary after + * receiving a ClientHello2 with a cookie. + */ + if (hrr != NULL + && (!ssl3_finish_mac(s, hrr, hrrlen) + || !ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, + s->s3->tmp.message_size + + SSL3_HM_HEADER_LENGTH))) { + /* SSLfatal() already called */ + return 0; + } + + return 1; +} + +static int ca_dn_cmp(const X509_NAME *const *a, const X509_NAME *const *b) +{ + return X509_NAME_cmp(*a, *b); +} + +int parse_ca_names(SSL *s, PACKET *pkt) +{ + STACK_OF(X509_NAME) *ca_sk = sk_X509_NAME_new(ca_dn_cmp); + X509_NAME *xn = NULL; + PACKET cadns; + + if (ca_sk == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_PARSE_CA_NAMES, + ERR_R_MALLOC_FAILURE); + goto err; + } + /* get the CA RDNs */ + if (!PACKET_get_length_prefixed_2(pkt, &cadns)) { + SSLfatal(s, SSL_AD_DECODE_ERROR,SSL_F_PARSE_CA_NAMES, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + while (PACKET_remaining(&cadns)) { + const unsigned char *namestart, *namebytes; + unsigned int name_len; + + if (!PACKET_get_net_2(&cadns, &name_len) + || !PACKET_get_bytes(&cadns, &namebytes, name_len)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_PARSE_CA_NAMES, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + namestart = namebytes; + if ((xn = d2i_X509_NAME(NULL, &namebytes, name_len)) == NULL) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_PARSE_CA_NAMES, + ERR_R_ASN1_LIB); + goto err; + } + if (namebytes != (namestart + name_len)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_PARSE_CA_NAMES, + SSL_R_CA_DN_LENGTH_MISMATCH); + goto err; + } + + if (!sk_X509_NAME_push(ca_sk, xn)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_PARSE_CA_NAMES, + ERR_R_MALLOC_FAILURE); + goto err; + } + xn = NULL; + } + + sk_X509_NAME_pop_free(s->s3->tmp.peer_ca_names, X509_NAME_free); + s->s3->tmp.peer_ca_names = ca_sk; + + return 1; + + err: + sk_X509_NAME_pop_free(ca_sk, X509_NAME_free); + X509_NAME_free(xn); + return 0; +} + +const STACK_OF(X509_NAME) *get_ca_names(SSL *s) +{ + const STACK_OF(X509_NAME) *ca_sk = NULL;; + + if (s->server) { + ca_sk = SSL_get_client_CA_list(s); + if (ca_sk != NULL && sk_X509_NAME_num(ca_sk) == 0) + ca_sk = NULL; + } + + if (ca_sk == NULL) + ca_sk = SSL_get0_CA_list(s); + + return ca_sk; +} + +int construct_ca_names(SSL *s, const STACK_OF(X509_NAME) *ca_sk, WPACKET *pkt) +{ + /* Start sub-packet for client CA list */ + if (!WPACKET_start_sub_packet_u16(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_CA_NAMES, + ERR_R_INTERNAL_ERROR); + return 0; + } + + if (ca_sk != NULL) { + int i; + + for (i = 0; i < sk_X509_NAME_num(ca_sk); i++) { + unsigned char *namebytes; + X509_NAME *name = sk_X509_NAME_value(ca_sk, i); + int namelen; + + if (name == NULL + || (namelen = i2d_X509_NAME(name, NULL)) < 0 + || !WPACKET_sub_allocate_bytes_u16(pkt, namelen, + &namebytes) + || i2d_X509_NAME(name, &namebytes) != namelen) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_CA_NAMES, + ERR_R_INTERNAL_ERROR); + return 0; + } + } + } + + if (!WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_CA_NAMES, + ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} + +/* Create a buffer containing data to be signed for server key exchange */ +size_t construct_key_exchange_tbs(SSL *s, unsigned char **ptbs, + const void *param, size_t paramlen) +{ + size_t tbslen = 2 * SSL3_RANDOM_SIZE + paramlen; + unsigned char *tbs = OPENSSL_malloc(tbslen); + + if (tbs == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_KEY_EXCHANGE_TBS, + ERR_R_MALLOC_FAILURE); + return 0; + } + memcpy(tbs, s->s3->client_random, SSL3_RANDOM_SIZE); + memcpy(tbs + SSL3_RANDOM_SIZE, s->s3->server_random, SSL3_RANDOM_SIZE); + + memcpy(tbs + SSL3_RANDOM_SIZE * 2, param, paramlen); + + *ptbs = tbs; + return tbslen; +} + +/* + * Saves the current handshake digest for Post-Handshake Auth, + * Done after ClientFinished is processed, done exactly once + */ +int tls13_save_handshake_digest_for_pha(SSL *s) +{ + if (s->pha_dgst == NULL) { + if (!ssl3_digest_cached_records(s, 1)) + /* SSLfatal() already called */ + return 0; + + s->pha_dgst = EVP_MD_CTX_new(); + if (s->pha_dgst == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS13_SAVE_HANDSHAKE_DIGEST_FOR_PHA, + ERR_R_INTERNAL_ERROR); + return 0; + } + if (!EVP_MD_CTX_copy_ex(s->pha_dgst, + s->s3->handshake_dgst)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS13_SAVE_HANDSHAKE_DIGEST_FOR_PHA, + ERR_R_INTERNAL_ERROR); + return 0; + } + } + return 1; +} + +/* + * Restores the Post-Handshake Auth handshake digest + * Done just before sending/processing the Cert Request + */ +int tls13_restore_handshake_digest_for_pha(SSL *s) +{ + if (s->pha_dgst == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS13_RESTORE_HANDSHAKE_DIGEST_FOR_PHA, + ERR_R_INTERNAL_ERROR); + return 0; + } + if (!EVP_MD_CTX_copy_ex(s->s3->handshake_dgst, + s->pha_dgst)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS13_RESTORE_HANDSHAKE_DIGEST_FOR_PHA, + ERR_R_INTERNAL_ERROR); + return 0; + } + return 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_locl.h b/trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_locl.h new file mode 100644 index 000000000..e27c0c13a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_locl.h @@ -0,0 +1,420 @@ +/* + * Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/***************************************************************************** + * * + * The following definitions are PRIVATE to the state machine. They should * + * NOT be used outside of the state machine. * + * * + *****************************************************************************/ + +/* Max message length definitions */ + +/* The spec allows for a longer length than this, but we limit it */ +#define HELLO_VERIFY_REQUEST_MAX_LENGTH 258 +#define END_OF_EARLY_DATA_MAX_LENGTH 0 +#define SERVER_HELLO_MAX_LENGTH 20000 +#define HELLO_RETRY_REQUEST_MAX_LENGTH 20000 +#define ENCRYPTED_EXTENSIONS_MAX_LENGTH 20000 +#define SERVER_KEY_EXCH_MAX_LENGTH 102400 +#define SERVER_HELLO_DONE_MAX_LENGTH 0 +#define KEY_UPDATE_MAX_LENGTH 1 +#define CCS_MAX_LENGTH 1 +/* Max should actually be 36 but we are generous */ +#define FINISHED_MAX_LENGTH 64 + +/* Dummy message type */ +#define SSL3_MT_DUMMY -1 + +extern const unsigned char hrrrandom[]; + +/* Message processing return codes */ +typedef enum { + /* Something bad happened */ + MSG_PROCESS_ERROR, + /* We've finished reading - swap to writing */ + MSG_PROCESS_FINISHED_READING, + /* + * We've completed the main processing of this message but there is some + * post processing to be done. + */ + MSG_PROCESS_CONTINUE_PROCESSING, + /* We've finished this message - read the next message */ + MSG_PROCESS_CONTINUE_READING +} MSG_PROCESS_RETURN; + +typedef int (*confunc_f) (SSL *s, WPACKET *pkt); + +int ssl3_take_mac(SSL *s); +int check_in_list(SSL *s, uint16_t group_id, const uint16_t *groups, + size_t num_groups, int checkallow); +int create_synthetic_message_hash(SSL *s, const unsigned char *hashval, + size_t hashlen, const unsigned char *hrr, + size_t hrrlen); +int parse_ca_names(SSL *s, PACKET *pkt); +const STACK_OF(X509_NAME) *get_ca_names(SSL *s); +int construct_ca_names(SSL *s, const STACK_OF(X509_NAME) *ca_sk, WPACKET *pkt); +size_t construct_key_exchange_tbs(SSL *s, unsigned char **ptbs, + const void *param, size_t paramlen); + +/* + * TLS/DTLS client state machine functions + */ +int ossl_statem_client_read_transition(SSL *s, int mt); +WRITE_TRAN ossl_statem_client_write_transition(SSL *s); +WORK_STATE ossl_statem_client_pre_work(SSL *s, WORK_STATE wst); +WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst); +int ossl_statem_client_construct_message(SSL *s, WPACKET *pkt, + confunc_f *confunc, int *mt); +size_t ossl_statem_client_max_message_size(SSL *s); +MSG_PROCESS_RETURN ossl_statem_client_process_message(SSL *s, PACKET *pkt); +WORK_STATE ossl_statem_client_post_process_message(SSL *s, WORK_STATE wst); + +/* + * TLS/DTLS server state machine functions + */ +int ossl_statem_server_read_transition(SSL *s, int mt); +WRITE_TRAN ossl_statem_server_write_transition(SSL *s); +WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst); +WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst); +int ossl_statem_server_construct_message(SSL *s, WPACKET *pkt, + confunc_f *confunc,int *mt); +size_t ossl_statem_server_max_message_size(SSL *s); +MSG_PROCESS_RETURN ossl_statem_server_process_message(SSL *s, PACKET *pkt); +WORK_STATE ossl_statem_server_post_process_message(SSL *s, WORK_STATE wst); + +/* Functions for getting new message data */ +__owur int tls_get_message_header(SSL *s, int *mt); +__owur int tls_get_message_body(SSL *s, size_t *len); +__owur int dtls_get_message(SSL *s, int *mt, size_t *len); + +/* Message construction and processing functions */ +__owur int tls_process_initial_server_flight(SSL *s); +__owur MSG_PROCESS_RETURN tls_process_change_cipher_spec(SSL *s, PACKET *pkt); +__owur MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt); +__owur int tls_construct_change_cipher_spec(SSL *s, WPACKET *pkt); +__owur int dtls_construct_change_cipher_spec(SSL *s, WPACKET *pkt); + +__owur int tls_construct_finished(SSL *s, WPACKET *pkt); +__owur int tls_construct_key_update(SSL *s, WPACKET *pkt); +__owur MSG_PROCESS_RETURN tls_process_key_update(SSL *s, PACKET *pkt); +__owur WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs, + int stop); +__owur WORK_STATE dtls_wait_for_dry(SSL *s); + +/* some client-only functions */ +__owur int tls_construct_client_hello(SSL *s, WPACKET *pkt); +__owur MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt); +__owur MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt); +__owur MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt); +__owur int tls_process_cert_status_body(SSL *s, PACKET *pkt); +__owur MSG_PROCESS_RETURN tls_process_cert_status(SSL *s, PACKET *pkt); +__owur MSG_PROCESS_RETURN tls_process_server_done(SSL *s, PACKET *pkt); +__owur int tls_construct_cert_verify(SSL *s, WPACKET *pkt); +__owur WORK_STATE tls_prepare_client_certificate(SSL *s, WORK_STATE wst); +__owur int tls_construct_client_certificate(SSL *s, WPACKET *pkt); +__owur int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey); +__owur int tls_construct_client_key_exchange(SSL *s, WPACKET *pkt); +__owur int tls_client_key_exchange_post_work(SSL *s); +__owur int tls_construct_cert_status_body(SSL *s, WPACKET *pkt); +__owur int tls_construct_cert_status(SSL *s, WPACKET *pkt); +__owur MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt); +__owur MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt); +__owur int ssl3_check_cert_and_algorithm(SSL *s); +#ifndef OPENSSL_NO_NEXTPROTONEG +__owur int tls_construct_next_proto(SSL *s, WPACKET *pkt); +#endif +__owur MSG_PROCESS_RETURN tls_process_hello_req(SSL *s, PACKET *pkt); +__owur MSG_PROCESS_RETURN dtls_process_hello_verify(SSL *s, PACKET *pkt); +__owur int tls_construct_end_of_early_data(SSL *s, WPACKET *pkt); + +/* some server-only functions */ +__owur MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt); +__owur WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst); +__owur int tls_construct_server_hello(SSL *s, WPACKET *pkt); +__owur int dtls_construct_hello_verify_request(SSL *s, WPACKET *pkt); +__owur int tls_construct_server_certificate(SSL *s, WPACKET *pkt); +__owur int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt); +__owur int tls_construct_certificate_request(SSL *s, WPACKET *pkt); +__owur int tls_construct_server_done(SSL *s, WPACKET *pkt); +__owur MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt); +__owur MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt); +__owur WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst); +__owur MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt); +#ifndef OPENSSL_NO_NEXTPROTONEG +__owur MSG_PROCESS_RETURN tls_process_next_proto(SSL *s, PACKET *pkt); +#endif +__owur int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt); +MSG_PROCESS_RETURN tls_process_end_of_early_data(SSL *s, PACKET *pkt); + + +/* Extension processing */ + +typedef enum ext_return_en { + EXT_RETURN_FAIL, + EXT_RETURN_SENT, + EXT_RETURN_NOT_SENT +} EXT_RETURN; + +__owur int tls_validate_all_contexts(SSL *s, unsigned int thisctx, + RAW_EXTENSION *exts); +__owur int extension_is_relevant(SSL *s, unsigned int extctx, + unsigned int thisctx); +__owur int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context, + RAW_EXTENSION **res, size_t *len, int init); +__owur int tls_parse_extension(SSL *s, TLSEXT_INDEX idx, int context, + RAW_EXTENSION *exts, X509 *x, size_t chainidx); +__owur int tls_parse_all_extensions(SSL *s, int context, RAW_EXTENSION *exts, + X509 *x, size_t chainidx, int fin); +__owur int should_add_extension(SSL *s, unsigned int extctx, + unsigned int thisctx, int max_version); +__owur int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); + +__owur int tls_psk_do_binder(SSL *s, const EVP_MD *md, + const unsigned char *msgstart, + size_t binderoffset, const unsigned char *binderin, + unsigned char *binderout, + SSL_SESSION *sess, int sign, int external); + +/* Server Extension processing */ +int tls_parse_ctos_renegotiate(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +int tls_parse_ctos_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#ifndef OPENSSL_NO_SRP +int tls_parse_ctos_srp(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +#endif +int tls_parse_ctos_early_data(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#ifndef OPENSSL_NO_EC +int tls_parse_ctos_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidxl); +#endif +int tls_parse_ctos_session_ticket(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +int tls_parse_ctos_sig_algs_cert(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +int tls_parse_ctos_sig_algs(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +#ifndef OPENSSL_NO_OCSP +int tls_parse_ctos_status_request(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#endif +#ifndef OPENSSL_NO_NEXTPROTONEG +int tls_parse_ctos_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +#endif +int tls_parse_ctos_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +#ifndef OPENSSL_NO_SRTP +int tls_parse_ctos_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +#endif +int tls_parse_ctos_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +int tls_parse_ctos_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +int tls_parse_ctos_psk_kex_modes(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +int tls_parse_ctos_post_handshake_auth(SSL *, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); + +EXT_RETURN tls_construct_stoc_renegotiate(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +EXT_RETURN tls_construct_stoc_server_name(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +EXT_RETURN tls_construct_stoc_early_data(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +EXT_RETURN tls_construct_stoc_maxfragmentlen(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +#ifndef OPENSSL_NO_EC +EXT_RETURN tls_construct_stoc_ec_pt_formats(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +#endif +EXT_RETURN tls_construct_stoc_supported_groups(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +EXT_RETURN tls_construct_stoc_session_ticket(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +#ifndef OPENSSL_NO_OCSP +EXT_RETURN tls_construct_stoc_status_request(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +#endif +#ifndef OPENSSL_NO_NEXTPROTONEG +EXT_RETURN tls_construct_stoc_next_proto_neg(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +#endif +EXT_RETURN tls_construct_stoc_alpn(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#ifndef OPENSSL_NO_SRTP +EXT_RETURN tls_construct_stoc_use_srtp(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#endif +EXT_RETURN tls_construct_stoc_etm(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +EXT_RETURN tls_construct_stoc_ems(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +EXT_RETURN tls_construct_stoc_supported_versions(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +EXT_RETURN tls_construct_stoc_cookie(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +/* + * Not in public headers as this is not an official extension. Only used when + * SSL_OP_CRYPTOPRO_TLSEXT_BUG is set. + */ +#define TLSEXT_TYPE_cryptopro_bug 0xfde8 +EXT_RETURN tls_construct_stoc_cryptopro_bug(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +EXT_RETURN tls_construct_stoc_psk(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); + +/* Client Extension processing */ +EXT_RETURN tls_construct_ctos_renegotiate(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +EXT_RETURN tls_construct_ctos_server_name(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +EXT_RETURN tls_construct_ctos_maxfragmentlen(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#ifndef OPENSSL_NO_SRP +EXT_RETURN tls_construct_ctos_srp(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +#endif +#ifndef OPENSSL_NO_EC +EXT_RETURN tls_construct_ctos_ec_pt_formats(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +EXT_RETURN tls_construct_ctos_supported_groups(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +#endif +EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +EXT_RETURN tls_construct_ctos_session_ticket(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +EXT_RETURN tls_construct_ctos_sig_algs(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +#ifndef OPENSSL_NO_OCSP +EXT_RETURN tls_construct_ctos_status_request(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +#endif +#ifndef OPENSSL_NO_NEXTPROTONEG +EXT_RETURN tls_construct_ctos_npn(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#endif +EXT_RETURN tls_construct_ctos_alpn(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#ifndef OPENSSL_NO_SRTP +EXT_RETURN tls_construct_ctos_use_srtp(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#endif +EXT_RETURN tls_construct_ctos_etm(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#ifndef OPENSSL_NO_CT +EXT_RETURN tls_construct_ctos_sct(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#endif +EXT_RETURN tls_construct_ctos_ems(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +EXT_RETURN tls_construct_ctos_supported_versions(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +EXT_RETURN tls_construct_ctos_key_share(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +EXT_RETURN tls_construct_ctos_psk_kex_modes(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +EXT_RETURN tls_construct_ctos_cookie(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +EXT_RETURN tls_construct_ctos_padding(SSL *s, WPACKET *pkt, + unsigned int context, X509 *x, + size_t chainidx); +EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +EXT_RETURN tls_construct_ctos_post_handshake_auth(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); + +int tls_parse_stoc_renegotiate(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +int tls_parse_stoc_server_name(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +int tls_parse_stoc_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#ifndef OPENSSL_NO_EC +int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#endif +int tls_parse_stoc_session_ticket(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#ifndef OPENSSL_NO_OCSP +int tls_parse_stoc_status_request(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +#endif +#ifndef OPENSSL_NO_CT +int tls_parse_stoc_sct(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +#endif +#ifndef OPENSSL_NO_NEXTPROTONEG +int tls_parse_stoc_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +#endif +int tls_parse_stoc_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +#ifndef OPENSSL_NO_SRTP +int tls_parse_stoc_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +#endif +int tls_parse_stoc_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +int tls_parse_stoc_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +int tls_parse_stoc_supported_versions(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx); +int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +int tls_parse_stoc_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); +int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + size_t chainidx); + +int tls_handle_alpn(SSL *s); + +int tls13_save_handshake_digest_for_pha(SSL *s); +int tls13_restore_handshake_digest_for_pha(SSL *s); diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_srvr.c b/trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_srvr.c new file mode 100644 index 000000000..6b8aae62c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/statem/statem_srvr.c @@ -0,0 +1,4272 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * Copyright 2005 Nokia. All rights reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "../ssl_locl.h" +#include "statem_locl.h" +#include "internal/constant_time_locl.h" +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TICKET_NONCE_SIZE 8 + +static int tls_construct_encrypted_extensions(SSL *s, WPACKET *pkt); + +/* + * ossl_statem_server13_read_transition() encapsulates the logic for the allowed + * handshake state transitions when a TLSv1.3 server is reading messages from + * the client. The message type that the client has sent is provided in |mt|. + * The current state is in |s->statem.hand_state|. + * + * Return values are 1 for success (transition allowed) and 0 on error + * (transition not allowed) + */ +static int ossl_statem_server13_read_transition(SSL *s, int mt) +{ + OSSL_STATEM *st = &s->statem; + + /* + * Note: There is no case for TLS_ST_BEFORE because at that stage we have + * not negotiated TLSv1.3 yet, so that case is handled by + * ossl_statem_server_read_transition() + */ + switch (st->hand_state) { + default: + break; + + case TLS_ST_EARLY_DATA: + if (s->hello_retry_request == SSL_HRR_PENDING) { + if (mt == SSL3_MT_CLIENT_HELLO) { + st->hand_state = TLS_ST_SR_CLNT_HELLO; + return 1; + } + break; + } else if (s->ext.early_data == SSL_EARLY_DATA_ACCEPTED) { + if (mt == SSL3_MT_END_OF_EARLY_DATA) { + st->hand_state = TLS_ST_SR_END_OF_EARLY_DATA; + return 1; + } + break; + } + /* Fall through */ + + case TLS_ST_SR_END_OF_EARLY_DATA: + case TLS_ST_SW_FINISHED: + if (s->s3->tmp.cert_request) { + if (mt == SSL3_MT_CERTIFICATE) { + st->hand_state = TLS_ST_SR_CERT; + return 1; + } + } else { + if (mt == SSL3_MT_FINISHED) { + st->hand_state = TLS_ST_SR_FINISHED; + return 1; + } + } + break; + + case TLS_ST_SR_CERT: + if (s->session->peer == NULL) { + if (mt == SSL3_MT_FINISHED) { + st->hand_state = TLS_ST_SR_FINISHED; + return 1; + } + } else { + if (mt == SSL3_MT_CERTIFICATE_VERIFY) { + st->hand_state = TLS_ST_SR_CERT_VRFY; + return 1; + } + } + break; + + case TLS_ST_SR_CERT_VRFY: + if (mt == SSL3_MT_FINISHED) { + st->hand_state = TLS_ST_SR_FINISHED; + return 1; + } + break; + + case TLS_ST_OK: + /* + * Its never ok to start processing handshake messages in the middle of + * early data (i.e. before we've received the end of early data alert) + */ + if (s->early_data_state == SSL_EARLY_DATA_READING) + break; + + if (mt == SSL3_MT_CERTIFICATE + && s->post_handshake_auth == SSL_PHA_REQUESTED) { + st->hand_state = TLS_ST_SR_CERT; + return 1; + } + + if (mt == SSL3_MT_KEY_UPDATE) { + st->hand_state = TLS_ST_SR_KEY_UPDATE; + return 1; + } + break; + } + + /* No valid transition found */ + return 0; +} + +/* + * ossl_statem_server_read_transition() encapsulates the logic for the allowed + * handshake state transitions when the server is reading messages from the + * client. The message type that the client has sent is provided in |mt|. The + * current state is in |s->statem.hand_state|. + * + * Return values are 1 for success (transition allowed) and 0 on error + * (transition not allowed) + */ +int ossl_statem_server_read_transition(SSL *s, int mt) +{ + OSSL_STATEM *st = &s->statem; + + if (SSL_IS_TLS13(s)) { + if (!ossl_statem_server13_read_transition(s, mt)) + goto err; + return 1; + } + + switch (st->hand_state) { + default: + break; + + case TLS_ST_BEFORE: + case TLS_ST_OK: + case DTLS_ST_SW_HELLO_VERIFY_REQUEST: + if (mt == SSL3_MT_CLIENT_HELLO) { + st->hand_state = TLS_ST_SR_CLNT_HELLO; + return 1; + } + break; + + case TLS_ST_SW_SRVR_DONE: + /* + * If we get a CKE message after a ServerDone then either + * 1) We didn't request a Certificate + * OR + * 2) If we did request one then + * a) We allow no Certificate to be returned + * AND + * b) We are running SSL3 (in TLS1.0+ the client must return a 0 + * list if we requested a certificate) + */ + if (mt == SSL3_MT_CLIENT_KEY_EXCHANGE) { + if (s->s3->tmp.cert_request) { + if (s->version == SSL3_VERSION) { + if ((s->verify_mode & SSL_VERIFY_PEER) + && (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) { + /* + * This isn't an unexpected message as such - we're just + * not going to accept it because we require a client + * cert. + */ + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION, + SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); + return 0; + } + st->hand_state = TLS_ST_SR_KEY_EXCH; + return 1; + } + } else { + st->hand_state = TLS_ST_SR_KEY_EXCH; + return 1; + } + } else if (s->s3->tmp.cert_request) { + if (mt == SSL3_MT_CERTIFICATE) { + st->hand_state = TLS_ST_SR_CERT; + return 1; + } + } + break; + + case TLS_ST_SR_CERT: + if (mt == SSL3_MT_CLIENT_KEY_EXCHANGE) { + st->hand_state = TLS_ST_SR_KEY_EXCH; + return 1; + } + break; + + case TLS_ST_SR_KEY_EXCH: + /* + * We should only process a CertificateVerify message if we have + * received a Certificate from the client. If so then |s->session->peer| + * will be non NULL. In some instances a CertificateVerify message is + * not required even if the peer has sent a Certificate (e.g. such as in + * the case of static DH). In that case |st->no_cert_verify| should be + * set. + */ + if (s->session->peer == NULL || st->no_cert_verify) { + if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) { + /* + * For the ECDH ciphersuites when the client sends its ECDH + * pub key in a certificate, the CertificateVerify message is + * not sent. Also for GOST ciphersuites when the client uses + * its key from the certificate for key exchange. + */ + st->hand_state = TLS_ST_SR_CHANGE; + return 1; + } + } else { + if (mt == SSL3_MT_CERTIFICATE_VERIFY) { + st->hand_state = TLS_ST_SR_CERT_VRFY; + return 1; + } + } + break; + + case TLS_ST_SR_CERT_VRFY: + if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) { + st->hand_state = TLS_ST_SR_CHANGE; + return 1; + } + break; + + case TLS_ST_SR_CHANGE: +#ifndef OPENSSL_NO_NEXTPROTONEG + if (s->s3->npn_seen) { + if (mt == SSL3_MT_NEXT_PROTO) { + st->hand_state = TLS_ST_SR_NEXT_PROTO; + return 1; + } + } else { +#endif + if (mt == SSL3_MT_FINISHED) { + st->hand_state = TLS_ST_SR_FINISHED; + return 1; + } +#ifndef OPENSSL_NO_NEXTPROTONEG + } +#endif + break; + +#ifndef OPENSSL_NO_NEXTPROTONEG + case TLS_ST_SR_NEXT_PROTO: + if (mt == SSL3_MT_FINISHED) { + st->hand_state = TLS_ST_SR_FINISHED; + return 1; + } + break; +#endif + + case TLS_ST_SW_FINISHED: + if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) { + st->hand_state = TLS_ST_SR_CHANGE; + return 1; + } + break; + } + + err: + /* No valid transition found */ + if (SSL_IS_DTLS(s) && mt == SSL3_MT_CHANGE_CIPHER_SPEC) { + BIO *rbio; + + /* + * CCS messages don't have a message sequence number so this is probably + * because of an out-of-order CCS. We'll just drop it. + */ + s->init_num = 0; + s->rwstate = SSL_READING; + rbio = SSL_get_rbio(s); + BIO_clear_retry_flags(rbio); + BIO_set_retry_read(rbio); + return 0; + } + SSLfatal(s, SSL3_AD_UNEXPECTED_MESSAGE, + SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION, + SSL_R_UNEXPECTED_MESSAGE); + return 0; +} + +/* + * Should we send a ServerKeyExchange message? + * + * Valid return values are: + * 1: Yes + * 0: No + */ +static int send_server_key_exchange(SSL *s) +{ + unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + + /* + * only send a ServerKeyExchange if DH or fortezza but we have a + * sign only certificate PSK: may send PSK identity hints For + * ECC ciphersuites, we send a serverKeyExchange message only if + * the cipher suite is either ECDH-anon or ECDHE. In other cases, + * the server certificate contains the server's public key for + * key exchange. + */ + if (alg_k & (SSL_kDHE | SSL_kECDHE) + /* + * PSK: send ServerKeyExchange if PSK identity hint if + * provided + */ +#ifndef OPENSSL_NO_PSK + /* Only send SKE if we have identity hint for plain PSK */ + || ((alg_k & (SSL_kPSK | SSL_kRSAPSK)) + && s->cert->psk_identity_hint) + /* For other PSK always send SKE */ + || (alg_k & (SSL_PSK & (SSL_kDHEPSK | SSL_kECDHEPSK))) +#endif +#ifndef OPENSSL_NO_SRP + /* SRP: send ServerKeyExchange */ + || (alg_k & SSL_kSRP) +#endif + ) { + return 1; + } + + return 0; +} + +/* + * Should we send a CertificateRequest message? + * + * Valid return values are: + * 1: Yes + * 0: No + */ +int send_certificate_request(SSL *s) +{ + if ( + /* don't request cert unless asked for it: */ + s->verify_mode & SSL_VERIFY_PEER + /* + * don't request if post-handshake-only unless doing + * post-handshake in TLSv1.3: + */ + && (!SSL_IS_TLS13(s) || !(s->verify_mode & SSL_VERIFY_POST_HANDSHAKE) + || s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) + /* + * if SSL_VERIFY_CLIENT_ONCE is set, don't request cert + * a second time: + */ + && (s->certreqs_sent < 1 || + !(s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) + /* + * never request cert in anonymous ciphersuites (see + * section "Certificate request" in SSL 3 drafts and in + * RFC 2246): + */ + && (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) + /* + * ... except when the application insists on + * verification (against the specs, but statem_clnt.c accepts + * this for SSL 3) + */ + || (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) + /* don't request certificate for SRP auth */ + && !(s->s3->tmp.new_cipher->algorithm_auth & SSL_aSRP) + /* + * With normal PSK Certificates and Certificate Requests + * are omitted + */ + && !(s->s3->tmp.new_cipher->algorithm_auth & SSL_aPSK)) { + return 1; + } + + return 0; +} + +/* + * ossl_statem_server13_write_transition() works out what handshake state to + * move to next when a TLSv1.3 server is writing messages to be sent to the + * client. + */ +static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s) +{ + OSSL_STATEM *st = &s->statem; + + /* + * No case for TLS_ST_BEFORE, because at that stage we have not negotiated + * TLSv1.3 yet, so that is handled by ossl_statem_server_write_transition() + */ + + switch (st->hand_state) { + default: + /* Shouldn't happen */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_OSSL_STATEM_SERVER13_WRITE_TRANSITION, + ERR_R_INTERNAL_ERROR); + return WRITE_TRAN_ERROR; + + case TLS_ST_OK: + if (s->key_update != SSL_KEY_UPDATE_NONE) { + st->hand_state = TLS_ST_SW_KEY_UPDATE; + return WRITE_TRAN_CONTINUE; + } + if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) { + st->hand_state = TLS_ST_SW_CERT_REQ; + return WRITE_TRAN_CONTINUE; + } + /* Try to read from the client instead */ + return WRITE_TRAN_FINISHED; + + case TLS_ST_SR_CLNT_HELLO: + st->hand_state = TLS_ST_SW_SRVR_HELLO; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_SW_SRVR_HELLO: + if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0 + && s->hello_retry_request != SSL_HRR_COMPLETE) + st->hand_state = TLS_ST_SW_CHANGE; + else if (s->hello_retry_request == SSL_HRR_PENDING) + st->hand_state = TLS_ST_EARLY_DATA; + else + st->hand_state = TLS_ST_SW_ENCRYPTED_EXTENSIONS; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_SW_CHANGE: + if (s->hello_retry_request == SSL_HRR_PENDING) + st->hand_state = TLS_ST_EARLY_DATA; + else + st->hand_state = TLS_ST_SW_ENCRYPTED_EXTENSIONS; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_SW_ENCRYPTED_EXTENSIONS: + if (s->hit) + st->hand_state = TLS_ST_SW_FINISHED; + else if (send_certificate_request(s)) + st->hand_state = TLS_ST_SW_CERT_REQ; + else + st->hand_state = TLS_ST_SW_CERT; + + return WRITE_TRAN_CONTINUE; + + case TLS_ST_SW_CERT_REQ: + if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) { + s->post_handshake_auth = SSL_PHA_REQUESTED; + st->hand_state = TLS_ST_OK; + } else { + st->hand_state = TLS_ST_SW_CERT; + } + return WRITE_TRAN_CONTINUE; + + case TLS_ST_SW_CERT: + st->hand_state = TLS_ST_SW_CERT_VRFY; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_SW_CERT_VRFY: + st->hand_state = TLS_ST_SW_FINISHED; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_SW_FINISHED: + st->hand_state = TLS_ST_EARLY_DATA; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_EARLY_DATA: + return WRITE_TRAN_FINISHED; + + case TLS_ST_SR_FINISHED: + /* + * Technically we have finished the handshake at this point, but we're + * going to remain "in_init" for now and write out any session tickets + * immediately. + */ + if (s->post_handshake_auth == SSL_PHA_REQUESTED) { + s->post_handshake_auth = SSL_PHA_EXT_RECEIVED; + } else if (!s->ext.ticket_expected) { + /* + * If we're not going to renew the ticket then we just finish the + * handshake at this point. + */ + st->hand_state = TLS_ST_OK; + return WRITE_TRAN_CONTINUE; + } + if (s->num_tickets > s->sent_tickets) + st->hand_state = TLS_ST_SW_SESSION_TICKET; + else + st->hand_state = TLS_ST_OK; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_SR_KEY_UPDATE: + if (s->key_update != SSL_KEY_UPDATE_NONE) { + st->hand_state = TLS_ST_SW_KEY_UPDATE; + return WRITE_TRAN_CONTINUE; + } + /* Fall through */ + + case TLS_ST_SW_KEY_UPDATE: + st->hand_state = TLS_ST_OK; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_SW_SESSION_TICKET: + /* In a resumption we only ever send a maximum of one new ticket. + * Following an initial handshake we send the number of tickets we have + * been configured for. + */ + if (s->hit || s->num_tickets <= s->sent_tickets) { + /* We've written enough tickets out. */ + st->hand_state = TLS_ST_OK; + } + return WRITE_TRAN_CONTINUE; + } +} + +/* + * ossl_statem_server_write_transition() works out what handshake state to move + * to next when the server is writing messages to be sent to the client. + */ +WRITE_TRAN ossl_statem_server_write_transition(SSL *s) +{ + OSSL_STATEM *st = &s->statem; + + /* + * Note that before the ClientHello we don't know what version we are going + * to negotiate yet, so we don't take this branch until later + */ + + if (SSL_IS_TLS13(s)) + return ossl_statem_server13_write_transition(s); + + switch (st->hand_state) { + default: + /* Shouldn't happen */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_OSSL_STATEM_SERVER_WRITE_TRANSITION, + ERR_R_INTERNAL_ERROR); + return WRITE_TRAN_ERROR; + + case TLS_ST_OK: + if (st->request_state == TLS_ST_SW_HELLO_REQ) { + /* We must be trying to renegotiate */ + st->hand_state = TLS_ST_SW_HELLO_REQ; + st->request_state = TLS_ST_BEFORE; + return WRITE_TRAN_CONTINUE; + } + /* Must be an incoming ClientHello */ + if (!tls_setup_handshake(s)) { + /* SSLfatal() already called */ + return WRITE_TRAN_ERROR; + } + /* Fall through */ + + case TLS_ST_BEFORE: + /* Just go straight to trying to read from the client */ + return WRITE_TRAN_FINISHED; + + case TLS_ST_SW_HELLO_REQ: + st->hand_state = TLS_ST_OK; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_SR_CLNT_HELLO: + if (SSL_IS_DTLS(s) && !s->d1->cookie_verified + && (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)) { + st->hand_state = DTLS_ST_SW_HELLO_VERIFY_REQUEST; + } else if (s->renegotiate == 0 && !SSL_IS_FIRST_HANDSHAKE(s)) { + /* We must have rejected the renegotiation */ + st->hand_state = TLS_ST_OK; + return WRITE_TRAN_CONTINUE; + } else { + st->hand_state = TLS_ST_SW_SRVR_HELLO; + } + return WRITE_TRAN_CONTINUE; + + case DTLS_ST_SW_HELLO_VERIFY_REQUEST: + return WRITE_TRAN_FINISHED; + + case TLS_ST_SW_SRVR_HELLO: + if (s->hit) { + if (s->ext.ticket_expected) + st->hand_state = TLS_ST_SW_SESSION_TICKET; + else + st->hand_state = TLS_ST_SW_CHANGE; + } else { + /* Check if it is anon DH or anon ECDH, */ + /* normal PSK or SRP */ + if (!(s->s3->tmp.new_cipher->algorithm_auth & + (SSL_aNULL | SSL_aSRP | SSL_aPSK))) { + st->hand_state = TLS_ST_SW_CERT; + } else if (send_server_key_exchange(s)) { + st->hand_state = TLS_ST_SW_KEY_EXCH; + } else if (send_certificate_request(s)) { + st->hand_state = TLS_ST_SW_CERT_REQ; + } else { + st->hand_state = TLS_ST_SW_SRVR_DONE; + } + } + return WRITE_TRAN_CONTINUE; + + case TLS_ST_SW_CERT: + if (s->ext.status_expected) { + st->hand_state = TLS_ST_SW_CERT_STATUS; + return WRITE_TRAN_CONTINUE; + } + /* Fall through */ + + case TLS_ST_SW_CERT_STATUS: + if (send_server_key_exchange(s)) { + st->hand_state = TLS_ST_SW_KEY_EXCH; + return WRITE_TRAN_CONTINUE; + } + /* Fall through */ + + case TLS_ST_SW_KEY_EXCH: + if (send_certificate_request(s)) { + st->hand_state = TLS_ST_SW_CERT_REQ; + return WRITE_TRAN_CONTINUE; + } + /* Fall through */ + + case TLS_ST_SW_CERT_REQ: + st->hand_state = TLS_ST_SW_SRVR_DONE; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_SW_SRVR_DONE: + return WRITE_TRAN_FINISHED; + + case TLS_ST_SR_FINISHED: + if (s->hit) { + st->hand_state = TLS_ST_OK; + return WRITE_TRAN_CONTINUE; + } else if (s->ext.ticket_expected) { + st->hand_state = TLS_ST_SW_SESSION_TICKET; + } else { + st->hand_state = TLS_ST_SW_CHANGE; + } + return WRITE_TRAN_CONTINUE; + + case TLS_ST_SW_SESSION_TICKET: + st->hand_state = TLS_ST_SW_CHANGE; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_SW_CHANGE: + st->hand_state = TLS_ST_SW_FINISHED; + return WRITE_TRAN_CONTINUE; + + case TLS_ST_SW_FINISHED: + if (s->hit) { + return WRITE_TRAN_FINISHED; + } + st->hand_state = TLS_ST_OK; + return WRITE_TRAN_CONTINUE; + } +} + +/* + * Perform any pre work that needs to be done prior to sending a message from + * the server to the client. + */ +WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst) +{ + OSSL_STATEM *st = &s->statem; + + switch (st->hand_state) { + default: + /* No pre work to be done */ + break; + + case TLS_ST_SW_HELLO_REQ: + s->shutdown = 0; + if (SSL_IS_DTLS(s)) + dtls1_clear_sent_buffer(s); + break; + + case DTLS_ST_SW_HELLO_VERIFY_REQUEST: + s->shutdown = 0; + if (SSL_IS_DTLS(s)) { + dtls1_clear_sent_buffer(s); + /* We don't buffer this message so don't use the timer */ + st->use_timer = 0; + } + break; + + case TLS_ST_SW_SRVR_HELLO: + if (SSL_IS_DTLS(s)) { + /* + * Messages we write from now on should be buffered and + * retransmitted if necessary, so we need to use the timer now + */ + st->use_timer = 1; + } + break; + + case TLS_ST_SW_SRVR_DONE: +#ifndef OPENSSL_NO_SCTP + if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s))) { + /* Calls SSLfatal() as required */ + return dtls_wait_for_dry(s); + } +#endif + return WORK_FINISHED_CONTINUE; + + case TLS_ST_SW_SESSION_TICKET: + if (SSL_IS_TLS13(s) && s->sent_tickets == 0) { + /* + * Actually this is the end of the handshake, but we're going + * straight into writing the session ticket out. So we finish off + * the handshake, but keep the various buffers active. + * + * Calls SSLfatal as required. + */ + return tls_finish_handshake(s, wst, 0, 0); + } if (SSL_IS_DTLS(s)) { + /* + * We're into the last flight. We don't retransmit the last flight + * unless we need to, so we don't use the timer + */ + st->use_timer = 0; + } + break; + + case TLS_ST_SW_CHANGE: + if (SSL_IS_TLS13(s)) + break; + s->session->cipher = s->s3->tmp.new_cipher; + if (!s->method->ssl3_enc->setup_key_block(s)) { + /* SSLfatal() already called */ + return WORK_ERROR; + } + if (SSL_IS_DTLS(s)) { + /* + * We're into the last flight. We don't retransmit the last flight + * unless we need to, so we don't use the timer. This might have + * already been set to 0 if we sent a NewSessionTicket message, + * but we'll set it again here in case we didn't. + */ + st->use_timer = 0; + } + return WORK_FINISHED_CONTINUE; + + case TLS_ST_EARLY_DATA: + if (s->early_data_state != SSL_EARLY_DATA_ACCEPTING + && (s->s3->flags & TLS1_FLAGS_STATELESS) == 0) + return WORK_FINISHED_CONTINUE; + /* Fall through */ + + case TLS_ST_OK: + /* Calls SSLfatal() as required */ + return tls_finish_handshake(s, wst, 1, 1); + } + + return WORK_FINISHED_CONTINUE; +} + +static ossl_inline int conn_is_closed(void) +{ + switch (get_last_sys_error()) { +#if defined(EPIPE) + case EPIPE: + return 1; +#endif +#if defined(ECONNRESET) + case ECONNRESET: + return 1; +#endif + default: + return 0; + } +} + +/* + * Perform any work that needs to be done after sending a message from the + * server to the client. + */ +WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst) +{ + OSSL_STATEM *st = &s->statem; + + s->init_num = 0; + + switch (st->hand_state) { + default: + /* No post work to be done */ + break; + + case TLS_ST_SW_HELLO_REQ: + if (statem_flush(s) != 1) + return WORK_MORE_A; + if (!ssl3_init_finished_mac(s)) { + /* SSLfatal() already called */ + return WORK_ERROR; + } + break; + + case DTLS_ST_SW_HELLO_VERIFY_REQUEST: + if (statem_flush(s) != 1) + return WORK_MORE_A; + /* HelloVerifyRequest resets Finished MAC */ + if (s->version != DTLS1_BAD_VER && !ssl3_init_finished_mac(s)) { + /* SSLfatal() already called */ + return WORK_ERROR; + } + /* + * The next message should be another ClientHello which we need to + * treat like it was the first packet + */ + s->first_packet = 1; + break; + + case TLS_ST_SW_SRVR_HELLO: + if (SSL_IS_TLS13(s) && s->hello_retry_request == SSL_HRR_PENDING) { + if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) == 0 + && statem_flush(s) != 1) + return WORK_MORE_A; + break; + } +#ifndef OPENSSL_NO_SCTP + if (SSL_IS_DTLS(s) && s->hit) { + unsigned char sctpauthkey[64]; + char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)]; + size_t labellen; + + /* + * Add new shared key for SCTP-Auth, will be ignored if no + * SCTP used. + */ + memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL, + sizeof(DTLS1_SCTP_AUTH_LABEL)); + + /* Don't include the terminating zero. */ + labellen = sizeof(labelbuffer) - 1; + if (s->mode & SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG) + labellen += 1; + + if (SSL_export_keying_material(s, sctpauthkey, + sizeof(sctpauthkey), labelbuffer, + labellen, NULL, 0, + 0) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_OSSL_STATEM_SERVER_POST_WORK, + ERR_R_INTERNAL_ERROR); + return WORK_ERROR; + } + + BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY, + sizeof(sctpauthkey), sctpauthkey); + } +#endif + if (!SSL_IS_TLS13(s) + || ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0 + && s->hello_retry_request != SSL_HRR_COMPLETE)) + break; + /* Fall through */ + + case TLS_ST_SW_CHANGE: + if (s->hello_retry_request == SSL_HRR_PENDING) { + if (!statem_flush(s)) + return WORK_MORE_A; + break; + } + + if (SSL_IS_TLS13(s)) { + if (!s->method->ssl3_enc->setup_key_block(s) + || !s->method->ssl3_enc->change_cipher_state(s, + SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_SERVER_WRITE)) { + /* SSLfatal() already called */ + return WORK_ERROR; + } + + if (s->ext.early_data != SSL_EARLY_DATA_ACCEPTED + && !s->method->ssl3_enc->change_cipher_state(s, + SSL3_CC_HANDSHAKE |SSL3_CHANGE_CIPHER_SERVER_READ)) { + /* SSLfatal() already called */ + return WORK_ERROR; + } + /* + * We don't yet know whether the next record we are going to receive + * is an unencrypted alert, an encrypted alert, or an encrypted + * handshake message. We temporarily tolerate unencrypted alerts. + */ + s->statem.enc_read_state = ENC_READ_STATE_ALLOW_PLAIN_ALERTS; + break; + } + +#ifndef OPENSSL_NO_SCTP + if (SSL_IS_DTLS(s) && !s->hit) { + /* + * Change to new shared key of SCTP-Auth, will be ignored if + * no SCTP used. + */ + BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, + 0, NULL); + } +#endif + if (!s->method->ssl3_enc->change_cipher_state(s, + SSL3_CHANGE_CIPHER_SERVER_WRITE)) + { + /* SSLfatal() already called */ + return WORK_ERROR; + } + + if (SSL_IS_DTLS(s)) + dtls1_reset_seq_numbers(s, SSL3_CC_WRITE); + break; + + case TLS_ST_SW_SRVR_DONE: + if (statem_flush(s) != 1) + return WORK_MORE_A; + break; + + case TLS_ST_SW_FINISHED: + if (statem_flush(s) != 1) + return WORK_MORE_A; +#ifndef OPENSSL_NO_SCTP + if (SSL_IS_DTLS(s) && s->hit) { + /* + * Change to new shared key of SCTP-Auth, will be ignored if + * no SCTP used. + */ + BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, + 0, NULL); + } +#endif + if (SSL_IS_TLS13(s)) { + if (!s->method->ssl3_enc->generate_master_secret(s, + s->master_secret, s->handshake_secret, 0, + &s->session->master_key_length) + || !s->method->ssl3_enc->change_cipher_state(s, + SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_SERVER_WRITE)) + /* SSLfatal() already called */ + return WORK_ERROR; + } + break; + + case TLS_ST_SW_CERT_REQ: + if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) { + if (statem_flush(s) != 1) + return WORK_MORE_A; + } + break; + + case TLS_ST_SW_KEY_UPDATE: + if (statem_flush(s) != 1) + return WORK_MORE_A; + if (!tls13_update_key(s, 1)) { + /* SSLfatal() already called */ + return WORK_ERROR; + } + break; + + case TLS_ST_SW_SESSION_TICKET: + clear_sys_error(); + if (SSL_IS_TLS13(s) && statem_flush(s) != 1) { + if (SSL_get_error(s, 0) == SSL_ERROR_SYSCALL + && conn_is_closed()) { + /* + * We ignore connection closed errors in TLSv1.3 when sending a + * NewSessionTicket and behave as if we were successful. This is + * so that we are still able to read data sent to us by a client + * that closes soon after the end of the handshake without + * waiting to read our post-handshake NewSessionTickets. + */ + s->rwstate = SSL_NOTHING; + break; + } + + return WORK_MORE_A; + } + break; + } + + return WORK_FINISHED_CONTINUE; +} + +/* + * Get the message construction function and message type for sending from the + * server + * + * Valid return values are: + * 1: Success + * 0: Error + */ +int ossl_statem_server_construct_message(SSL *s, WPACKET *pkt, + confunc_f *confunc, int *mt) +{ + OSSL_STATEM *st = &s->statem; + + switch (st->hand_state) { + default: + /* Shouldn't happen */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE, + SSL_R_BAD_HANDSHAKE_STATE); + return 0; + + case TLS_ST_SW_CHANGE: + if (SSL_IS_DTLS(s)) + *confunc = dtls_construct_change_cipher_spec; + else + *confunc = tls_construct_change_cipher_spec; + *mt = SSL3_MT_CHANGE_CIPHER_SPEC; + break; + + case DTLS_ST_SW_HELLO_VERIFY_REQUEST: + *confunc = dtls_construct_hello_verify_request; + *mt = DTLS1_MT_HELLO_VERIFY_REQUEST; + break; + + case TLS_ST_SW_HELLO_REQ: + /* No construction function needed */ + *confunc = NULL; + *mt = SSL3_MT_HELLO_REQUEST; + break; + + case TLS_ST_SW_SRVR_HELLO: + *confunc = tls_construct_server_hello; + *mt = SSL3_MT_SERVER_HELLO; + break; + + case TLS_ST_SW_CERT: + *confunc = tls_construct_server_certificate; + *mt = SSL3_MT_CERTIFICATE; + break; + + case TLS_ST_SW_CERT_VRFY: + *confunc = tls_construct_cert_verify; + *mt = SSL3_MT_CERTIFICATE_VERIFY; + break; + + + case TLS_ST_SW_KEY_EXCH: + *confunc = tls_construct_server_key_exchange; + *mt = SSL3_MT_SERVER_KEY_EXCHANGE; + break; + + case TLS_ST_SW_CERT_REQ: + *confunc = tls_construct_certificate_request; + *mt = SSL3_MT_CERTIFICATE_REQUEST; + break; + + case TLS_ST_SW_SRVR_DONE: + *confunc = tls_construct_server_done; + *mt = SSL3_MT_SERVER_DONE; + break; + + case TLS_ST_SW_SESSION_TICKET: + *confunc = tls_construct_new_session_ticket; + *mt = SSL3_MT_NEWSESSION_TICKET; + break; + + case TLS_ST_SW_CERT_STATUS: + *confunc = tls_construct_cert_status; + *mt = SSL3_MT_CERTIFICATE_STATUS; + break; + + case TLS_ST_SW_FINISHED: + *confunc = tls_construct_finished; + *mt = SSL3_MT_FINISHED; + break; + + case TLS_ST_EARLY_DATA: + *confunc = NULL; + *mt = SSL3_MT_DUMMY; + break; + + case TLS_ST_SW_ENCRYPTED_EXTENSIONS: + *confunc = tls_construct_encrypted_extensions; + *mt = SSL3_MT_ENCRYPTED_EXTENSIONS; + break; + + case TLS_ST_SW_KEY_UPDATE: + *confunc = tls_construct_key_update; + *mt = SSL3_MT_KEY_UPDATE; + break; + } + + return 1; +} + +/* + * Maximum size (excluding the Handshake header) of a ClientHello message, + * calculated as follows: + * + * 2 + # client_version + * 32 + # only valid length for random + * 1 + # length of session_id + * 32 + # maximum size for session_id + * 2 + # length of cipher suites + * 2^16-2 + # maximum length of cipher suites array + * 1 + # length of compression_methods + * 2^8-1 + # maximum length of compression methods + * 2 + # length of extensions + * 2^16-1 # maximum length of extensions + */ +#define CLIENT_HELLO_MAX_LENGTH 131396 + +#define CLIENT_KEY_EXCH_MAX_LENGTH 2048 +#define NEXT_PROTO_MAX_LENGTH 514 + +/* + * Returns the maximum allowed length for the current message that we are + * reading. Excludes the message header. + */ +size_t ossl_statem_server_max_message_size(SSL *s) +{ + OSSL_STATEM *st = &s->statem; + + switch (st->hand_state) { + default: + /* Shouldn't happen */ + return 0; + + case TLS_ST_SR_CLNT_HELLO: + return CLIENT_HELLO_MAX_LENGTH; + + case TLS_ST_SR_END_OF_EARLY_DATA: + return END_OF_EARLY_DATA_MAX_LENGTH; + + case TLS_ST_SR_CERT: + return s->max_cert_list; + + case TLS_ST_SR_KEY_EXCH: + return CLIENT_KEY_EXCH_MAX_LENGTH; + + case TLS_ST_SR_CERT_VRFY: + return SSL3_RT_MAX_PLAIN_LENGTH; + +#ifndef OPENSSL_NO_NEXTPROTONEG + case TLS_ST_SR_NEXT_PROTO: + return NEXT_PROTO_MAX_LENGTH; +#endif + + case TLS_ST_SR_CHANGE: + return CCS_MAX_LENGTH; + + case TLS_ST_SR_FINISHED: + return FINISHED_MAX_LENGTH; + + case TLS_ST_SR_KEY_UPDATE: + return KEY_UPDATE_MAX_LENGTH; + } +} + +/* + * Process a message that the server has received from the client. + */ +MSG_PROCESS_RETURN ossl_statem_server_process_message(SSL *s, PACKET *pkt) +{ + OSSL_STATEM *st = &s->statem; + + switch (st->hand_state) { + default: + /* Shouldn't happen */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE, + ERR_R_INTERNAL_ERROR); + return MSG_PROCESS_ERROR; + + case TLS_ST_SR_CLNT_HELLO: + return tls_process_client_hello(s, pkt); + + case TLS_ST_SR_END_OF_EARLY_DATA: + return tls_process_end_of_early_data(s, pkt); + + case TLS_ST_SR_CERT: + return tls_process_client_certificate(s, pkt); + + case TLS_ST_SR_KEY_EXCH: + return tls_process_client_key_exchange(s, pkt); + + case TLS_ST_SR_CERT_VRFY: + return tls_process_cert_verify(s, pkt); + +#ifndef OPENSSL_NO_NEXTPROTONEG + case TLS_ST_SR_NEXT_PROTO: + return tls_process_next_proto(s, pkt); +#endif + + case TLS_ST_SR_CHANGE: + return tls_process_change_cipher_spec(s, pkt); + + case TLS_ST_SR_FINISHED: + return tls_process_finished(s, pkt); + + case TLS_ST_SR_KEY_UPDATE: + return tls_process_key_update(s, pkt); + + } +} + +/* + * Perform any further processing required following the receipt of a message + * from the client + */ +WORK_STATE ossl_statem_server_post_process_message(SSL *s, WORK_STATE wst) +{ + OSSL_STATEM *st = &s->statem; + + switch (st->hand_state) { + default: + /* Shouldn't happen */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_OSSL_STATEM_SERVER_POST_PROCESS_MESSAGE, + ERR_R_INTERNAL_ERROR); + return WORK_ERROR; + + case TLS_ST_SR_CLNT_HELLO: + return tls_post_process_client_hello(s, wst); + + case TLS_ST_SR_KEY_EXCH: + return tls_post_process_client_key_exchange(s, wst); + } +} + +#ifndef OPENSSL_NO_SRP +/* Returns 1 on success, 0 for retryable error, -1 for fatal error */ +static int ssl_check_srp_ext_ClientHello(SSL *s) +{ + int ret; + int al = SSL_AD_UNRECOGNIZED_NAME; + + if ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) && + (s->srp_ctx.TLS_ext_srp_username_callback != NULL)) { + if (s->srp_ctx.login == NULL) { + /* + * RFC 5054 says SHOULD reject, we do so if There is no srp + * login name + */ + SSLfatal(s, SSL_AD_UNKNOWN_PSK_IDENTITY, + SSL_F_SSL_CHECK_SRP_EXT_CLIENTHELLO, + SSL_R_PSK_IDENTITY_NOT_FOUND); + return -1; + } else { + ret = SSL_srp_server_param_with_username(s, &al); + if (ret < 0) + return 0; + if (ret == SSL3_AL_FATAL) { + SSLfatal(s, al, SSL_F_SSL_CHECK_SRP_EXT_CLIENTHELLO, + al == SSL_AD_UNKNOWN_PSK_IDENTITY + ? SSL_R_PSK_IDENTITY_NOT_FOUND + : SSL_R_CLIENTHELLO_TLSEXT); + return -1; + } + } + } + return 1; +} +#endif + +int dtls_raw_hello_verify_request(WPACKET *pkt, unsigned char *cookie, + size_t cookie_len) +{ + /* Always use DTLS 1.0 version: see RFC 6347 */ + if (!WPACKET_put_bytes_u16(pkt, DTLS1_VERSION) + || !WPACKET_sub_memcpy_u8(pkt, cookie, cookie_len)) + return 0; + + return 1; +} + +int dtls_construct_hello_verify_request(SSL *s, WPACKET *pkt) +{ + unsigned int cookie_leni; + if (s->ctx->app_gen_cookie_cb == NULL || + s->ctx->app_gen_cookie_cb(s, s->d1->cookie, + &cookie_leni) == 0 || + cookie_leni > 255) { + SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST, + SSL_R_COOKIE_GEN_CALLBACK_FAILURE); + return 0; + } + s->d1->cookie_len = cookie_leni; + + if (!dtls_raw_hello_verify_request(pkt, s->d1->cookie, + s->d1->cookie_len)) { + SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST, + ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} + +#ifndef OPENSSL_NO_EC +/*- + * ssl_check_for_safari attempts to fingerprint Safari using OS X + * SecureTransport using the TLS extension block in |hello|. + * Safari, since 10.6, sends exactly these extensions, in this order: + * SNI, + * elliptic_curves + * ec_point_formats + * signature_algorithms (for TLSv1.2 only) + * + * We wish to fingerprint Safari because they broke ECDHE-ECDSA support in 10.8, + * but they advertise support. So enabling ECDHE-ECDSA ciphers breaks them. + * Sadly we cannot differentiate 10.6, 10.7 and 10.8.4 (which work), from + * 10.8..10.8.3 (which don't work). + */ +static void ssl_check_for_safari(SSL *s, const CLIENTHELLO_MSG *hello) +{ + static const unsigned char kSafariExtensionsBlock[] = { + 0x00, 0x0a, /* elliptic_curves extension */ + 0x00, 0x08, /* 8 bytes */ + 0x00, 0x06, /* 6 bytes of curve ids */ + 0x00, 0x17, /* P-256 */ + 0x00, 0x18, /* P-384 */ + 0x00, 0x19, /* P-521 */ + + 0x00, 0x0b, /* ec_point_formats */ + 0x00, 0x02, /* 2 bytes */ + 0x01, /* 1 point format */ + 0x00, /* uncompressed */ + /* The following is only present in TLS 1.2 */ + 0x00, 0x0d, /* signature_algorithms */ + 0x00, 0x0c, /* 12 bytes */ + 0x00, 0x0a, /* 10 bytes */ + 0x05, 0x01, /* SHA-384/RSA */ + 0x04, 0x01, /* SHA-256/RSA */ + 0x02, 0x01, /* SHA-1/RSA */ + 0x04, 0x03, /* SHA-256/ECDSA */ + 0x02, 0x03, /* SHA-1/ECDSA */ + }; + /* Length of the common prefix (first two extensions). */ + static const size_t kSafariCommonExtensionsLength = 18; + unsigned int type; + PACKET sni, tmppkt; + size_t ext_len; + + tmppkt = hello->extensions; + + if (!PACKET_forward(&tmppkt, 2) + || !PACKET_get_net_2(&tmppkt, &type) + || !PACKET_get_length_prefixed_2(&tmppkt, &sni)) { + return; + } + + if (type != TLSEXT_TYPE_server_name) + return; + + ext_len = TLS1_get_client_version(s) >= TLS1_2_VERSION ? + sizeof(kSafariExtensionsBlock) : kSafariCommonExtensionsLength; + + s->s3->is_probably_safari = PACKET_equal(&tmppkt, kSafariExtensionsBlock, + ext_len); +} +#endif /* !OPENSSL_NO_EC */ + +MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt) +{ + /* |cookie| will only be initialized for DTLS. */ + PACKET session_id, compression, extensions, cookie; + static const unsigned char null_compression = 0; + CLIENTHELLO_MSG *clienthello = NULL; + + /* Check if this is actually an unexpected renegotiation ClientHello */ + if (s->renegotiate == 0 && !SSL_IS_FIRST_HANDSHAKE(s)) { + if (!ossl_assert(!SSL_IS_TLS13(s))) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO, + ERR_R_INTERNAL_ERROR); + goto err; + } + if ((s->options & SSL_OP_NO_RENEGOTIATION) != 0 + || (!s->s3->send_connection_binding + && (s->options + & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) == 0)) { + ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION); + return MSG_PROCESS_FINISHED_READING; + } + s->renegotiate = 1; + s->new_session = 1; + } + + clienthello = OPENSSL_zalloc(sizeof(*clienthello)); + if (clienthello == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* + * First, parse the raw ClientHello data into the CLIENTHELLO_MSG structure. + */ + clienthello->isv2 = RECORD_LAYER_is_sslv2_record(&s->rlayer); + PACKET_null_init(&cookie); + + if (clienthello->isv2) { + unsigned int mt; + + if (!SSL_IS_FIRST_HANDSHAKE(s) + || s->hello_retry_request != SSL_HRR_NONE) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, + SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_UNEXPECTED_MESSAGE); + goto err; + } + + /*- + * An SSLv3/TLSv1 backwards-compatible CLIENT-HELLO in an SSLv2 + * header is sent directly on the wire, not wrapped as a TLS + * record. Our record layer just processes the message length and passes + * the rest right through. Its format is: + * Byte Content + * 0-1 msg_length - decoded by the record layer + * 2 msg_type - s->init_msg points here + * 3-4 version + * 5-6 cipher_spec_length + * 7-8 session_id_length + * 9-10 challenge_length + * ... ... + */ + + if (!PACKET_get_1(pkt, &mt) + || mt != SSL2_MT_CLIENT_HELLO) { + /* + * Should never happen. We should have tested this in the record + * layer in order to have determined that this is a SSLv2 record + * in the first place + */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO, + ERR_R_INTERNAL_ERROR); + goto err; + } + } + + if (!PACKET_get_net_2(pkt, &clienthello->legacy_version)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO, + SSL_R_LENGTH_TOO_SHORT); + goto err; + } + + /* Parse the message and load client random. */ + if (clienthello->isv2) { + /* + * Handle an SSLv2 backwards compatible ClientHello + * Note, this is only for SSLv3+ using the backward compatible format. + * Real SSLv2 is not supported, and is rejected below. + */ + unsigned int ciphersuite_len, session_id_len, challenge_len; + PACKET challenge; + + if (!PACKET_get_net_2(pkt, &ciphersuite_len) + || !PACKET_get_net_2(pkt, &session_id_len) + || !PACKET_get_net_2(pkt, &challenge_len)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO, + SSL_R_RECORD_LENGTH_MISMATCH); + goto err; + } + + if (session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH); + goto err; + } + + if (!PACKET_get_sub_packet(pkt, &clienthello->ciphersuites, + ciphersuite_len) + || !PACKET_copy_bytes(pkt, clienthello->session_id, session_id_len) + || !PACKET_get_sub_packet(pkt, &challenge, challenge_len) + /* No extensions. */ + || PACKET_remaining(pkt) != 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO, + SSL_R_RECORD_LENGTH_MISMATCH); + goto err; + } + clienthello->session_id_len = session_id_len; + + /* Load the client random and compression list. We use SSL3_RANDOM_SIZE + * here rather than sizeof(clienthello->random) because that is the limit + * for SSLv3 and it is fixed. It won't change even if + * sizeof(clienthello->random) does. + */ + challenge_len = challenge_len > SSL3_RANDOM_SIZE + ? SSL3_RANDOM_SIZE : challenge_len; + memset(clienthello->random, 0, SSL3_RANDOM_SIZE); + if (!PACKET_copy_bytes(&challenge, + clienthello->random + SSL3_RANDOM_SIZE - + challenge_len, challenge_len) + /* Advertise only null compression. */ + || !PACKET_buf_init(&compression, &null_compression, 1)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO, + ERR_R_INTERNAL_ERROR); + goto err; + } + + PACKET_null_init(&clienthello->extensions); + } else { + /* Regular ClientHello. */ + if (!PACKET_copy_bytes(pkt, clienthello->random, SSL3_RANDOM_SIZE) + || !PACKET_get_length_prefixed_1(pkt, &session_id) + || !PACKET_copy_all(&session_id, clienthello->session_id, + SSL_MAX_SSL_SESSION_ID_LENGTH, + &clienthello->session_id_len)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + if (SSL_IS_DTLS(s)) { + if (!PACKET_get_length_prefixed_1(pkt, &cookie)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO, + SSL_R_LENGTH_MISMATCH); + goto err; + } + if (!PACKET_copy_all(&cookie, clienthello->dtls_cookie, + DTLS1_COOKIE_LENGTH, + &clienthello->dtls_cookie_len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); + goto err; + } + /* + * If we require cookies and this ClientHello doesn't contain one, + * just return since we do not want to allocate any memory yet. + * So check cookie length... + */ + if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) { + if (clienthello->dtls_cookie_len == 0) { + OPENSSL_free(clienthello); + return MSG_PROCESS_FINISHED_READING; + } + } + } + + if (!PACKET_get_length_prefixed_2(pkt, &clienthello->ciphersuites)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + if (!PACKET_get_length_prefixed_1(pkt, &compression)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + /* Could be empty. */ + if (PACKET_remaining(pkt) == 0) { + PACKET_null_init(&clienthello->extensions); + } else { + if (!PACKET_get_length_prefixed_2(pkt, &clienthello->extensions) + || PACKET_remaining(pkt) != 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO, + SSL_R_LENGTH_MISMATCH); + goto err; + } + } + } + + if (!PACKET_copy_all(&compression, clienthello->compressions, + MAX_COMPRESSIONS_SIZE, + &clienthello->compressions_len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* Preserve the raw extensions PACKET for later use */ + extensions = clienthello->extensions; + if (!tls_collect_extensions(s, &extensions, SSL_EXT_CLIENT_HELLO, + &clienthello->pre_proc_exts, + &clienthello->pre_proc_exts_len, 1)) { + /* SSLfatal already been called */ + goto err; + } + s->clienthello = clienthello; + + return MSG_PROCESS_CONTINUE_PROCESSING; + + err: + if (clienthello != NULL) + OPENSSL_free(clienthello->pre_proc_exts); + OPENSSL_free(clienthello); + + return MSG_PROCESS_ERROR; +} + +static int tls_early_post_process_client_hello(SSL *s) +{ + unsigned int j; + int i, al = SSL_AD_INTERNAL_ERROR; + int protverr; + size_t loop; + unsigned long id; +#ifndef OPENSSL_NO_COMP + SSL_COMP *comp = NULL; +#endif + const SSL_CIPHER *c; + STACK_OF(SSL_CIPHER) *ciphers = NULL; + STACK_OF(SSL_CIPHER) *scsvs = NULL; + CLIENTHELLO_MSG *clienthello = s->clienthello; + DOWNGRADE dgrd = DOWNGRADE_NONE; + + /* Finished parsing the ClientHello, now we can start processing it */ + /* Give the ClientHello callback a crack at things */ + if (s->ctx->client_hello_cb != NULL) { + /* A failure in the ClientHello callback terminates the connection. */ + switch (s->ctx->client_hello_cb(s, &al, s->ctx->client_hello_cb_arg)) { + case SSL_CLIENT_HELLO_SUCCESS: + break; + case SSL_CLIENT_HELLO_RETRY: + s->rwstate = SSL_CLIENT_HELLO_CB; + return -1; + case SSL_CLIENT_HELLO_ERROR: + default: + SSLfatal(s, al, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + SSL_R_CALLBACK_FAILED); + goto err; + } + } + + /* Set up the client_random */ + memcpy(s->s3->client_random, clienthello->random, SSL3_RANDOM_SIZE); + + /* Choose the version */ + + if (clienthello->isv2) { + if (clienthello->legacy_version == SSL2_VERSION + || (clienthello->legacy_version & 0xff00) + != (SSL3_VERSION_MAJOR << 8)) { + /* + * This is real SSLv2 or something completely unknown. We don't + * support it. + */ + SSLfatal(s, SSL_AD_PROTOCOL_VERSION, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + SSL_R_UNKNOWN_PROTOCOL); + goto err; + } + /* SSLv3/TLS */ + s->client_version = clienthello->legacy_version; + } + /* + * Do SSL/TLS version negotiation if applicable. For DTLS we just check + * versions are potentially compatible. Version negotiation comes later. + */ + if (!SSL_IS_DTLS(s)) { + protverr = ssl_choose_server_version(s, clienthello, &dgrd); + } else if (s->method->version != DTLS_ANY_VERSION && + DTLS_VERSION_LT((int)clienthello->legacy_version, s->version)) { + protverr = SSL_R_VERSION_TOO_LOW; + } else { + protverr = 0; + } + + if (protverr) { + if (SSL_IS_FIRST_HANDSHAKE(s)) { + /* like ssl3_get_record, send alert using remote version number */ + s->version = s->client_version = clienthello->legacy_version; + } + SSLfatal(s, SSL_AD_PROTOCOL_VERSION, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, protverr); + goto err; + } + + /* TLSv1.3 specifies that a ClientHello must end on a record boundary */ + if (SSL_IS_TLS13(s) && RECORD_LAYER_processed_read_pending(&s->rlayer)) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + SSL_R_NOT_ON_RECORD_BOUNDARY); + goto err; + } + + if (SSL_IS_DTLS(s)) { + /* Empty cookie was already handled above by returning early. */ + if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) { + if (s->ctx->app_verify_cookie_cb != NULL) { + if (s->ctx->app_verify_cookie_cb(s, clienthello->dtls_cookie, + clienthello->dtls_cookie_len) == 0) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + SSL_R_COOKIE_MISMATCH); + goto err; + /* else cookie verification succeeded */ + } + /* default verification */ + } else if (s->d1->cookie_len != clienthello->dtls_cookie_len + || memcmp(clienthello->dtls_cookie, s->d1->cookie, + s->d1->cookie_len) != 0) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + SSL_R_COOKIE_MISMATCH); + goto err; + } + s->d1->cookie_verified = 1; + } + if (s->method->version == DTLS_ANY_VERSION) { + protverr = ssl_choose_server_version(s, clienthello, &dgrd); + if (protverr != 0) { + s->version = s->client_version; + SSLfatal(s, SSL_AD_PROTOCOL_VERSION, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, protverr); + goto err; + } + } + } + + s->hit = 0; + + if (!ssl_cache_cipherlist(s, &clienthello->ciphersuites, + clienthello->isv2) || + !bytes_to_cipher_list(s, &clienthello->ciphersuites, &ciphers, &scsvs, + clienthello->isv2, 1)) { + /* SSLfatal() already called */ + goto err; + } + + s->s3->send_connection_binding = 0; + /* Check what signalling cipher-suite values were received. */ + if (scsvs != NULL) { + for(i = 0; i < sk_SSL_CIPHER_num(scsvs); i++) { + c = sk_SSL_CIPHER_value(scsvs, i); + if (SSL_CIPHER_get_id(c) == SSL3_CK_SCSV) { + if (s->renegotiate) { + /* SCSV is fatal if renegotiating */ + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING); + goto err; + } + s->s3->send_connection_binding = 1; + } else if (SSL_CIPHER_get_id(c) == SSL3_CK_FALLBACK_SCSV && + !ssl_check_version_downgrade(s)) { + /* + * This SCSV indicates that the client previously tried + * a higher version. We should fail if the current version + * is an unexpected downgrade, as that indicates that the first + * connection may have been tampered with in order to trigger + * an insecure downgrade. + */ + SSLfatal(s, SSL_AD_INAPPROPRIATE_FALLBACK, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + SSL_R_INAPPROPRIATE_FALLBACK); + goto err; + } + } + } + + /* For TLSv1.3 we must select the ciphersuite *before* session resumption */ + if (SSL_IS_TLS13(s)) { + const SSL_CIPHER *cipher = + ssl3_choose_cipher(s, ciphers, SSL_get_ciphers(s)); + + if (cipher == NULL) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + SSL_R_NO_SHARED_CIPHER); + goto err; + } + if (s->hello_retry_request == SSL_HRR_PENDING + && (s->s3->tmp.new_cipher == NULL + || s->s3->tmp.new_cipher->id != cipher->id)) { + /* + * A previous HRR picked a different ciphersuite to the one we + * just selected. Something must have changed. + */ + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + SSL_R_BAD_CIPHER); + goto err; + } + s->s3->tmp.new_cipher = cipher; + } + + /* We need to do this before getting the session */ + if (!tls_parse_extension(s, TLSEXT_IDX_extended_master_secret, + SSL_EXT_CLIENT_HELLO, + clienthello->pre_proc_exts, NULL, 0)) { + /* SSLfatal() already called */ + goto err; + } + + /* + * We don't allow resumption in a backwards compatible ClientHello. + * TODO(openssl-team): in TLS1.1+, session_id MUST be empty. + * + * Versions before 0.9.7 always allow clients to resume sessions in + * renegotiation. 0.9.7 and later allow this by default, but optionally + * ignore resumption requests with flag + * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION (it's a new flag rather + * than a change to default behavior so that applications relying on + * this for security won't even compile against older library versions). + * 1.0.1 and later also have a function SSL_renegotiate_abbreviated() to + * request renegotiation but not a new session (s->new_session remains + * unset): for servers, this essentially just means that the + * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION setting will be + * ignored. + */ + if (clienthello->isv2 || + (s->new_session && + (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION))) { + if (!ssl_get_new_session(s, 1)) { + /* SSLfatal() already called */ + goto err; + } + } else { + i = ssl_get_prev_session(s, clienthello); + if (i == 1) { + /* previous session */ + s->hit = 1; + } else if (i == -1) { + /* SSLfatal() already called */ + goto err; + } else { + /* i == 0 */ + if (!ssl_get_new_session(s, 1)) { + /* SSLfatal() already called */ + goto err; + } + } + } + + if (SSL_IS_TLS13(s)) { + memcpy(s->tmp_session_id, s->clienthello->session_id, + s->clienthello->session_id_len); + s->tmp_session_id_len = s->clienthello->session_id_len; + } + + /* + * If it is a hit, check that the cipher is in the list. In TLSv1.3 we check + * ciphersuite compatibility with the session as part of resumption. + */ + if (!SSL_IS_TLS13(s) && s->hit) { + j = 0; + id = s->session->cipher->id; + +#ifdef CIPHER_DEBUG + fprintf(stderr, "client sent %d ciphers\n", sk_SSL_CIPHER_num(ciphers)); +#endif + for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { + c = sk_SSL_CIPHER_value(ciphers, i); +#ifdef CIPHER_DEBUG + fprintf(stderr, "client [%2d of %2d]:%s\n", + i, sk_SSL_CIPHER_num(ciphers), SSL_CIPHER_get_name(c)); +#endif + if (c->id == id) { + j = 1; + break; + } + } + if (j == 0) { + /* + * we need to have the cipher in the cipher list if we are asked + * to reuse it + */ + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + SSL_R_REQUIRED_CIPHER_MISSING); + goto err; + } + } + + for (loop = 0; loop < clienthello->compressions_len; loop++) { + if (clienthello->compressions[loop] == 0) + break; + } + + if (loop >= clienthello->compressions_len) { + /* no compress */ + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + SSL_R_NO_COMPRESSION_SPECIFIED); + goto err; + } + +#ifndef OPENSSL_NO_EC + if (s->options & SSL_OP_SAFARI_ECDHE_ECDSA_BUG) + ssl_check_for_safari(s, clienthello); +#endif /* !OPENSSL_NO_EC */ + + /* TLS extensions */ + if (!tls_parse_all_extensions(s, SSL_EXT_CLIENT_HELLO, + clienthello->pre_proc_exts, NULL, 0, 1)) { + /* SSLfatal() already called */ + goto err; + } + + /* + * Check if we want to use external pre-shared secret for this handshake + * for not reused session only. We need to generate server_random before + * calling tls_session_secret_cb in order to allow SessionTicket + * processing to use it in key derivation. + */ + { + unsigned char *pos; + pos = s->s3->server_random; + if (ssl_fill_hello_random(s, 1, pos, SSL3_RANDOM_SIZE, dgrd) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + ERR_R_INTERNAL_ERROR); + goto err; + } + } + + if (!s->hit + && s->version >= TLS1_VERSION + && !SSL_IS_TLS13(s) + && !SSL_IS_DTLS(s) + && s->ext.session_secret_cb) { + const SSL_CIPHER *pref_cipher = NULL; + /* + * s->session->master_key_length is a size_t, but this is an int for + * backwards compat reasons + */ + int master_key_length; + + master_key_length = sizeof(s->session->master_key); + if (s->ext.session_secret_cb(s, s->session->master_key, + &master_key_length, ciphers, + &pref_cipher, + s->ext.session_secret_cb_arg) + && master_key_length > 0) { + s->session->master_key_length = master_key_length; + s->hit = 1; + s->session->ciphers = ciphers; + s->session->verify_result = X509_V_OK; + + ciphers = NULL; + + /* check if some cipher was preferred by call back */ + if (pref_cipher == NULL) + pref_cipher = ssl3_choose_cipher(s, s->session->ciphers, + SSL_get_ciphers(s)); + if (pref_cipher == NULL) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + SSL_R_NO_SHARED_CIPHER); + goto err; + } + + s->session->cipher = pref_cipher; + sk_SSL_CIPHER_free(s->cipher_list); + s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers); + sk_SSL_CIPHER_free(s->cipher_list_by_id); + s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); + } + } + + /* + * Worst case, we will use the NULL compression, but if we have other + * options, we will now look for them. We have complen-1 compression + * algorithms from the client, starting at q. + */ + s->s3->tmp.new_compression = NULL; + if (SSL_IS_TLS13(s)) { + /* + * We already checked above that the NULL compression method appears in + * the list. Now we check there aren't any others (which is illegal in + * a TLSv1.3 ClientHello. + */ + if (clienthello->compressions_len != 1) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + SSL_R_INVALID_COMPRESSION_ALGORITHM); + goto err; + } + } +#ifndef OPENSSL_NO_COMP + /* This only happens if we have a cache hit */ + else if (s->session->compress_meth != 0) { + int m, comp_id = s->session->compress_meth; + unsigned int k; + /* Perform sanity checks on resumed compression algorithm */ + /* Can't disable compression */ + if (!ssl_allow_compression(s)) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + SSL_R_INCONSISTENT_COMPRESSION); + goto err; + } + /* Look for resumed compression method */ + for (m = 0; m < sk_SSL_COMP_num(s->ctx->comp_methods); m++) { + comp = sk_SSL_COMP_value(s->ctx->comp_methods, m); + if (comp_id == comp->id) { + s->s3->tmp.new_compression = comp; + break; + } + } + if (s->s3->tmp.new_compression == NULL) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + SSL_R_INVALID_COMPRESSION_ALGORITHM); + goto err; + } + /* Look for resumed method in compression list */ + for (k = 0; k < clienthello->compressions_len; k++) { + if (clienthello->compressions[k] == comp_id) + break; + } + if (k >= clienthello->compressions_len) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + SSL_R_REQUIRED_COMPRESSION_ALGORITHM_MISSING); + goto err; + } + } else if (s->hit) { + comp = NULL; + } else if (ssl_allow_compression(s) && s->ctx->comp_methods) { + /* See if we have a match */ + int m, nn, v, done = 0; + unsigned int o; + + nn = sk_SSL_COMP_num(s->ctx->comp_methods); + for (m = 0; m < nn; m++) { + comp = sk_SSL_COMP_value(s->ctx->comp_methods, m); + v = comp->id; + for (o = 0; o < clienthello->compressions_len; o++) { + if (v == clienthello->compressions[o]) { + done = 1; + break; + } + } + if (done) + break; + } + if (done) + s->s3->tmp.new_compression = comp; + else + comp = NULL; + } +#else + /* + * If compression is disabled we'd better not try to resume a session + * using compression. + */ + if (s->session->compress_meth != 0) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + SSL_R_INCONSISTENT_COMPRESSION); + goto err; + } +#endif + + /* + * Given s->session->ciphers and SSL_get_ciphers, we must pick a cipher + */ + + if (!s->hit || SSL_IS_TLS13(s)) { + sk_SSL_CIPHER_free(s->session->ciphers); + s->session->ciphers = ciphers; + if (ciphers == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, + ERR_R_INTERNAL_ERROR); + goto err; + } + ciphers = NULL; + } + + if (!s->hit) { +#ifdef OPENSSL_NO_COMP + s->session->compress_meth = 0; +#else + s->session->compress_meth = (comp == NULL) ? 0 : comp->id; +#endif + } + + sk_SSL_CIPHER_free(ciphers); + sk_SSL_CIPHER_free(scsvs); + OPENSSL_free(clienthello->pre_proc_exts); + OPENSSL_free(s->clienthello); + s->clienthello = NULL; + return 1; + err: + sk_SSL_CIPHER_free(ciphers); + sk_SSL_CIPHER_free(scsvs); + OPENSSL_free(clienthello->pre_proc_exts); + OPENSSL_free(s->clienthello); + s->clienthello = NULL; + + return 0; +} + +/* + * Call the status request callback if needed. Upon success, returns 1. + * Upon failure, returns 0. + */ +static int tls_handle_status_request(SSL *s) +{ + s->ext.status_expected = 0; + + /* + * If status request then ask callback what to do. Note: this must be + * called after servername callbacks in case the certificate has changed, + * and must be called after the cipher has been chosen because this may + * influence which certificate is sent + */ + if (s->ext.status_type != TLSEXT_STATUSTYPE_nothing && s->ctx != NULL + && s->ctx->ext.status_cb != NULL) { + int ret; + + /* If no certificate can't return certificate status */ + if (s->s3->tmp.cert != NULL) { + /* + * Set current certificate to one we will use so SSL_get_certificate + * et al can pick it up. + */ + s->cert->key = s->s3->tmp.cert; + ret = s->ctx->ext.status_cb(s, s->ctx->ext.status_arg); + switch (ret) { + /* We don't want to send a status request response */ + case SSL_TLSEXT_ERR_NOACK: + s->ext.status_expected = 0; + break; + /* status request response should be sent */ + case SSL_TLSEXT_ERR_OK: + if (s->ext.ocsp.resp) + s->ext.status_expected = 1; + break; + /* something bad happened */ + case SSL_TLSEXT_ERR_ALERT_FATAL: + default: + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_HANDLE_STATUS_REQUEST, + SSL_R_CLIENTHELLO_TLSEXT); + return 0; + } + } + } + + return 1; +} + +/* + * Call the alpn_select callback if needed. Upon success, returns 1. + * Upon failure, returns 0. + */ +int tls_handle_alpn(SSL *s) +{ + const unsigned char *selected = NULL; + unsigned char selected_len = 0; + + if (s->ctx->ext.alpn_select_cb != NULL && s->s3->alpn_proposed != NULL) { + int r = s->ctx->ext.alpn_select_cb(s, &selected, &selected_len, + s->s3->alpn_proposed, + (unsigned int)s->s3->alpn_proposed_len, + s->ctx->ext.alpn_select_cb_arg); + + if (r == SSL_TLSEXT_ERR_OK) { + OPENSSL_free(s->s3->alpn_selected); + s->s3->alpn_selected = OPENSSL_memdup(selected, selected_len); + if (s->s3->alpn_selected == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_HANDLE_ALPN, + ERR_R_INTERNAL_ERROR); + return 0; + } + s->s3->alpn_selected_len = selected_len; +#ifndef OPENSSL_NO_NEXTPROTONEG + /* ALPN takes precedence over NPN. */ + s->s3->npn_seen = 0; +#endif + + /* Check ALPN is consistent with session */ + if (s->session->ext.alpn_selected == NULL + || selected_len != s->session->ext.alpn_selected_len + || memcmp(selected, s->session->ext.alpn_selected, + selected_len) != 0) { + /* Not consistent so can't be used for early_data */ + s->ext.early_data_ok = 0; + + if (!s->hit) { + /* + * This is a new session and so alpn_selected should have + * been initialised to NULL. We should update it with the + * selected ALPN. + */ + if (!ossl_assert(s->session->ext.alpn_selected == NULL)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_HANDLE_ALPN, + ERR_R_INTERNAL_ERROR); + return 0; + } + s->session->ext.alpn_selected = OPENSSL_memdup(selected, + selected_len); + if (s->session->ext.alpn_selected == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_HANDLE_ALPN, + ERR_R_INTERNAL_ERROR); + return 0; + } + s->session->ext.alpn_selected_len = selected_len; + } + } + + return 1; + } else if (r != SSL_TLSEXT_ERR_NOACK) { + SSLfatal(s, SSL_AD_NO_APPLICATION_PROTOCOL, SSL_F_TLS_HANDLE_ALPN, + SSL_R_NO_APPLICATION_PROTOCOL); + return 0; + } + /* + * If r == SSL_TLSEXT_ERR_NOACK then behave as if no callback was + * present. + */ + } + + /* Check ALPN is consistent with session */ + if (s->session->ext.alpn_selected != NULL) { + /* Not consistent so can't be used for early_data */ + s->ext.early_data_ok = 0; + } + + return 1; +} + +WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst) +{ + const SSL_CIPHER *cipher; + + if (wst == WORK_MORE_A) { + int rv = tls_early_post_process_client_hello(s); + if (rv == 0) { + /* SSLfatal() was already called */ + goto err; + } + if (rv < 0) + return WORK_MORE_A; + wst = WORK_MORE_B; + } + if (wst == WORK_MORE_B) { + if (!s->hit || SSL_IS_TLS13(s)) { + /* Let cert callback update server certificates if required */ + if (!s->hit) { + if (s->cert->cert_cb != NULL) { + int rv = s->cert->cert_cb(s, s->cert->cert_cb_arg); + if (rv == 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_POST_PROCESS_CLIENT_HELLO, + SSL_R_CERT_CB_ERROR); + goto err; + } + if (rv < 0) { + s->rwstate = SSL_X509_LOOKUP; + return WORK_MORE_B; + } + s->rwstate = SSL_NOTHING; + } + if (!tls1_set_server_sigalgs(s)) { + /* SSLfatal already called */ + goto err; + } + } + + /* In TLSv1.3 we selected the ciphersuite before resumption */ + if (!SSL_IS_TLS13(s)) { + cipher = + ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s)); + + if (cipher == NULL) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_POST_PROCESS_CLIENT_HELLO, + SSL_R_NO_SHARED_CIPHER); + goto err; + } + s->s3->tmp.new_cipher = cipher; + } + if (!s->hit) { + if (!tls_choose_sigalg(s, 1)) { + /* SSLfatal already called */ + goto err; + } + /* check whether we should disable session resumption */ + if (s->not_resumable_session_cb != NULL) + s->session->not_resumable = + s->not_resumable_session_cb(s, + ((s->s3->tmp.new_cipher->algorithm_mkey + & (SSL_kDHE | SSL_kECDHE)) != 0)); + if (s->session->not_resumable) + /* do not send a session ticket */ + s->ext.ticket_expected = 0; + } + } else { + /* Session-id reuse */ + s->s3->tmp.new_cipher = s->session->cipher; + } + + /*- + * we now have the following setup. + * client_random + * cipher_list - our preferred list of ciphers + * ciphers - the clients preferred list of ciphers + * compression - basically ignored right now + * ssl version is set - sslv3 + * s->session - The ssl session has been setup. + * s->hit - session reuse flag + * s->s3->tmp.new_cipher- the new cipher to use. + */ + + /* + * Call status_request callback if needed. Has to be done after the + * certificate callbacks etc above. + */ + if (!tls_handle_status_request(s)) { + /* SSLfatal() already called */ + goto err; + } + /* + * Call alpn_select callback if needed. Has to be done after SNI and + * cipher negotiation (HTTP/2 restricts permitted ciphers). In TLSv1.3 + * we already did this because cipher negotiation happens earlier, and + * we must handle ALPN before we decide whether to accept early_data. + */ + if (!SSL_IS_TLS13(s) && !tls_handle_alpn(s)) { + /* SSLfatal() already called */ + goto err; + } + + wst = WORK_MORE_C; + } +#ifndef OPENSSL_NO_SRP + if (wst == WORK_MORE_C) { + int ret; + if ((ret = ssl_check_srp_ext_ClientHello(s)) == 0) { + /* + * callback indicates further work to be done + */ + s->rwstate = SSL_X509_LOOKUP; + return WORK_MORE_C; + } + if (ret < 0) { + /* SSLfatal() already called */ + goto err; + } + } +#endif + + return WORK_FINISHED_STOP; + err: + return WORK_ERROR; +} + +int tls_construct_server_hello(SSL *s, WPACKET *pkt) +{ + int compm; + size_t sl, len; + int version; + unsigned char *session_id; + int usetls13 = SSL_IS_TLS13(s) || s->hello_retry_request == SSL_HRR_PENDING; + + version = usetls13 ? TLS1_2_VERSION : s->version; + if (!WPACKET_put_bytes_u16(pkt, version) + /* + * Random stuff. Filling of the server_random takes place in + * tls_process_client_hello() + */ + || !WPACKET_memcpy(pkt, + s->hello_retry_request == SSL_HRR_PENDING + ? hrrrandom : s->s3->server_random, + SSL3_RANDOM_SIZE)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_SERVER_HELLO, + ERR_R_INTERNAL_ERROR); + return 0; + } + + /*- + * There are several cases for the session ID to send + * back in the server hello: + * - For session reuse from the session cache, + * we send back the old session ID. + * - If stateless session reuse (using a session ticket) + * is successful, we send back the client's "session ID" + * (which doesn't actually identify the session). + * - If it is a new session, we send back the new + * session ID. + * - However, if we want the new session to be single-use, + * we send back a 0-length session ID. + * - In TLSv1.3 we echo back the session id sent to us by the client + * regardless + * s->hit is non-zero in either case of session reuse, + * so the following won't overwrite an ID that we're supposed + * to send back. + */ + if (s->session->not_resumable || + (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER) + && !s->hit)) + s->session->session_id_length = 0; + + if (usetls13) { + sl = s->tmp_session_id_len; + session_id = s->tmp_session_id; + } else { + sl = s->session->session_id_length; + session_id = s->session->session_id; + } + + if (sl > sizeof(s->session->session_id)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_SERVER_HELLO, + ERR_R_INTERNAL_ERROR); + return 0; + } + + /* set up the compression method */ +#ifdef OPENSSL_NO_COMP + compm = 0; +#else + if (usetls13 || s->s3->tmp.new_compression == NULL) + compm = 0; + else + compm = s->s3->tmp.new_compression->id; +#endif + + if (!WPACKET_sub_memcpy_u8(pkt, session_id, sl) + || !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, pkt, &len) + || !WPACKET_put_bytes_u8(pkt, compm)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_SERVER_HELLO, + ERR_R_INTERNAL_ERROR); + return 0; + } + + if (!tls_construct_extensions(s, pkt, + s->hello_retry_request == SSL_HRR_PENDING + ? SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST + : (SSL_IS_TLS13(s) + ? SSL_EXT_TLS1_3_SERVER_HELLO + : SSL_EXT_TLS1_2_SERVER_HELLO), + NULL, 0)) { + /* SSLfatal() already called */ + return 0; + } + + if (s->hello_retry_request == SSL_HRR_PENDING) { + /* Ditch the session. We'll create a new one next time around */ + SSL_SESSION_free(s->session); + s->session = NULL; + s->hit = 0; + + /* + * Re-initialise the Transcript Hash. We're going to prepopulate it with + * a synthetic message_hash in place of ClientHello1. + */ + if (!create_synthetic_message_hash(s, NULL, 0, NULL, 0)) { + /* SSLfatal() already called */ + return 0; + } + } else if (!(s->verify_mode & SSL_VERIFY_PEER) + && !ssl3_digest_cached_records(s, 0)) { + /* SSLfatal() already called */; + return 0; + } + + return 1; +} + +int tls_construct_server_done(SSL *s, WPACKET *pkt) +{ + if (!s->s3->tmp.cert_request) { + if (!ssl3_digest_cached_records(s, 0)) { + /* SSLfatal() already called */ + return 0; + } + } + return 1; +} + +int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt) +{ +#ifndef OPENSSL_NO_DH + EVP_PKEY *pkdh = NULL; +#endif +#ifndef OPENSSL_NO_EC + unsigned char *encodedPoint = NULL; + size_t encodedlen = 0; + int curve_id = 0; +#endif + const SIGALG_LOOKUP *lu = s->s3->tmp.sigalg; + int i; + unsigned long type; + const BIGNUM *r[4]; + EVP_MD_CTX *md_ctx = EVP_MD_CTX_new(); + EVP_PKEY_CTX *pctx = NULL; + size_t paramlen, paramoffset; + + if (!WPACKET_get_total_written(pkt, ¶moffset)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); + goto err; + } + + if (md_ctx == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); + goto err; + } + + type = s->s3->tmp.new_cipher->algorithm_mkey; + + r[0] = r[1] = r[2] = r[3] = NULL; +#ifndef OPENSSL_NO_PSK + /* Plain PSK or RSAPSK nothing to do */ + if (type & (SSL_kPSK | SSL_kRSAPSK)) { + } else +#endif /* !OPENSSL_NO_PSK */ +#ifndef OPENSSL_NO_DH + if (type & (SSL_kDHE | SSL_kDHEPSK)) { + CERT *cert = s->cert; + + EVP_PKEY *pkdhp = NULL; + DH *dh; + + if (s->cert->dh_tmp_auto) { + DH *dhp = ssl_get_auto_dh(s); + pkdh = EVP_PKEY_new(); + if (pkdh == NULL || dhp == NULL) { + DH_free(dhp); + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto err; + } + EVP_PKEY_assign_DH(pkdh, dhp); + pkdhp = pkdh; + } else { + pkdhp = cert->dh_tmp; + } + if ((pkdhp == NULL) && (s->cert->dh_tmp_cb != NULL)) { + DH *dhp = s->cert->dh_tmp_cb(s, 0, 1024); + pkdh = ssl_dh_to_pkey(dhp); + if (pkdh == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto err; + } + pkdhp = pkdh; + } + if (pkdhp == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, + SSL_R_MISSING_TMP_DH_KEY); + goto err; + } + if (!ssl_security(s, SSL_SECOP_TMP_DH, + EVP_PKEY_security_bits(pkdhp), 0, pkdhp)) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, + SSL_R_DH_KEY_TOO_SMALL); + goto err; + } + if (s->s3->tmp.pkey != NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + s->s3->tmp.pkey = ssl_generate_pkey(pkdhp); + if (s->s3->tmp.pkey == NULL) { + /* SSLfatal() already called */ + goto err; + } + + dh = EVP_PKEY_get0_DH(s->s3->tmp.pkey); + if (dh == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + EVP_PKEY_free(pkdh); + pkdh = NULL; + + DH_get0_pqg(dh, &r[0], NULL, &r[1]); + DH_get0_key(dh, &r[2], NULL); + } else +#endif +#ifndef OPENSSL_NO_EC + if (type & (SSL_kECDHE | SSL_kECDHEPSK)) { + + if (s->s3->tmp.pkey != NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* Get NID of appropriate shared curve */ + curve_id = tls1_shared_group(s, -2); + if (curve_id == 0) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, + SSL_R_UNSUPPORTED_ELLIPTIC_CURVE); + goto err; + } + s->s3->tmp.pkey = ssl_generate_pkey_group(s, curve_id); + /* Generate a new key for this curve */ + if (s->s3->tmp.pkey == NULL) { + /* SSLfatal() already called */ + goto err; + } + + /* Encode the public key. */ + encodedlen = EVP_PKEY_get1_tls_encodedpoint(s->s3->tmp.pkey, + &encodedPoint); + if (encodedlen == 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_EC_LIB); + goto err; + } + + /* + * We'll generate the serverKeyExchange message explicitly so we + * can set these to NULLs + */ + r[0] = NULL; + r[1] = NULL; + r[2] = NULL; + r[3] = NULL; + } else +#endif /* !OPENSSL_NO_EC */ +#ifndef OPENSSL_NO_SRP + if (type & SSL_kSRP) { + if ((s->srp_ctx.N == NULL) || + (s->srp_ctx.g == NULL) || + (s->srp_ctx.s == NULL) || (s->srp_ctx.B == NULL)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, + SSL_R_MISSING_SRP_PARAM); + goto err; + } + r[0] = s->srp_ctx.N; + r[1] = s->srp_ctx.g; + r[2] = s->srp_ctx.s; + r[3] = s->srp_ctx.B; + } else +#endif + { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, + SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE); + goto err; + } + + if (((s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP)) != 0) + || ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK)) != 0) { + lu = NULL; + } else if (lu == NULL) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); + goto err; + } + +#ifndef OPENSSL_NO_PSK + if (type & SSL_PSK) { + size_t len = (s->cert->psk_identity_hint == NULL) + ? 0 : strlen(s->cert->psk_identity_hint); + + /* + * It should not happen that len > PSK_MAX_IDENTITY_LEN - we already + * checked this when we set the identity hint - but just in case + */ + if (len > PSK_MAX_IDENTITY_LEN + || !WPACKET_sub_memcpy_u16(pkt, s->cert->psk_identity_hint, + len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto err; + } + } +#endif + + for (i = 0; i < 4 && r[i] != NULL; i++) { + unsigned char *binval; + int res; + +#ifndef OPENSSL_NO_SRP + if ((i == 2) && (type & SSL_kSRP)) { + res = WPACKET_start_sub_packet_u8(pkt); + } else +#endif + res = WPACKET_start_sub_packet_u16(pkt); + + if (!res) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto err; + } + +#ifndef OPENSSL_NO_DH + /*- + * for interoperability with some versions of the Microsoft TLS + * stack, we need to zero pad the DHE pub key to the same length + * as the prime + */ + if ((i == 2) && (type & (SSL_kDHE | SSL_kDHEPSK))) { + size_t len = BN_num_bytes(r[0]) - BN_num_bytes(r[2]); + + if (len > 0) { + if (!WPACKET_allocate_bytes(pkt, len, &binval)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto err; + } + memset(binval, 0, len); + } + } +#endif + if (!WPACKET_allocate_bytes(pkt, BN_num_bytes(r[i]), &binval) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + BN_bn2bin(r[i], binval); + } + +#ifndef OPENSSL_NO_EC + if (type & (SSL_kECDHE | SSL_kECDHEPSK)) { + /* + * We only support named (not generic) curves. In this situation, the + * ServerKeyExchange message has: [1 byte CurveType], [2 byte CurveName] + * [1 byte length of encoded point], followed by the actual encoded + * point itself + */ + if (!WPACKET_put_bytes_u8(pkt, NAMED_CURVE_TYPE) + || !WPACKET_put_bytes_u8(pkt, 0) + || !WPACKET_put_bytes_u8(pkt, curve_id) + || !WPACKET_sub_memcpy_u8(pkt, encodedPoint, encodedlen)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto err; + } + OPENSSL_free(encodedPoint); + encodedPoint = NULL; + } +#endif + + /* not anonymous */ + if (lu != NULL) { + EVP_PKEY *pkey = s->s3->tmp.cert->privatekey; + const EVP_MD *md; + unsigned char *sigbytes1, *sigbytes2, *tbs; + size_t siglen, tbslen; + int rv; + + if (pkey == NULL || !tls1_lookup_md(lu, &md)) { + /* Should never happen */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto err; + } + /* Get length of the parameters we have written above */ + if (!WPACKET_get_length(pkt, ¶mlen)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto err; + } + /* send signature algorithm */ + if (SSL_USE_SIGALGS(s) && !WPACKET_put_bytes_u16(pkt, lu->sigalg)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto err; + } + /* + * Create the signature. We don't know the actual length of the sig + * until after we've created it, so we reserve enough bytes for it + * up front, and then properly allocate them in the WPACKET + * afterwards. + */ + siglen = EVP_PKEY_size(pkey); + if (!WPACKET_sub_reserve_bytes_u16(pkt, siglen, &sigbytes1) + || EVP_DigestSignInit(md_ctx, &pctx, md, NULL, pkey) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto err; + } + if (lu->sig == EVP_PKEY_RSA_PSS) { + if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0 + || EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, RSA_PSS_SALTLEN_DIGEST) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, + ERR_R_EVP_LIB); + goto err; + } + } + tbslen = construct_key_exchange_tbs(s, &tbs, + s->init_buf->data + paramoffset, + paramlen); + if (tbslen == 0) { + /* SSLfatal() already called */ + goto err; + } + rv = EVP_DigestSign(md_ctx, sigbytes1, &siglen, tbs, tbslen); + OPENSSL_free(tbs); + if (rv <= 0 || !WPACKET_sub_allocate_bytes_u16(pkt, siglen, &sigbytes2) + || sigbytes1 != sigbytes2) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto err; + } + } + + EVP_MD_CTX_free(md_ctx); + return 1; + err: +#ifndef OPENSSL_NO_DH + EVP_PKEY_free(pkdh); +#endif +#ifndef OPENSSL_NO_EC + OPENSSL_free(encodedPoint); +#endif + EVP_MD_CTX_free(md_ctx); + return 0; +} + +int tls_construct_certificate_request(SSL *s, WPACKET *pkt) +{ + if (SSL_IS_TLS13(s)) { + /* Send random context when doing post-handshake auth */ + if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) { + OPENSSL_free(s->pha_context); + s->pha_context_len = 32; + if ((s->pha_context = OPENSSL_malloc(s->pha_context_len)) == NULL + || RAND_bytes(s->pha_context, s->pha_context_len) <= 0 + || !WPACKET_sub_memcpy_u8(pkt, s->pha_context, s->pha_context_len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, + ERR_R_INTERNAL_ERROR); + return 0; + } + /* reset the handshake hash back to just after the ClientFinished */ + if (!tls13_restore_handshake_digest_for_pha(s)) { + /* SSLfatal() already called */ + return 0; + } + } else { + if (!WPACKET_put_bytes_u8(pkt, 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, + ERR_R_INTERNAL_ERROR); + return 0; + } + } + + if (!tls_construct_extensions(s, pkt, + SSL_EXT_TLS1_3_CERTIFICATE_REQUEST, NULL, + 0)) { + /* SSLfatal() already called */ + return 0; + } + goto done; + } + + /* get the list of acceptable cert types */ + if (!WPACKET_start_sub_packet_u8(pkt) + || !ssl3_get_req_cert_type(s, pkt) || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (SSL_USE_SIGALGS(s)) { + const uint16_t *psigs; + size_t nl = tls12_get_psigalgs(s, 1, &psigs); + + if (!WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_set_flags(pkt, WPACKET_FLAGS_NON_ZERO_LENGTH) + || !tls12_copy_sigalgs(s, pkt, psigs, nl) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, + ERR_R_INTERNAL_ERROR); + return 0; + } + } + + if (!construct_ca_names(s, get_ca_names(s), pkt)) { + /* SSLfatal() already called */ + return 0; + } + + done: + s->certreqs_sent++; + s->s3->tmp.cert_request = 1; + return 1; +} + +static int tls_process_cke_psk_preamble(SSL *s, PACKET *pkt) +{ +#ifndef OPENSSL_NO_PSK + unsigned char psk[PSK_MAX_PSK_LEN]; + size_t psklen; + PACKET psk_identity; + + if (!PACKET_get_length_prefixed_2(pkt, &psk_identity)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, + SSL_R_LENGTH_MISMATCH); + return 0; + } + if (PACKET_remaining(&psk_identity) > PSK_MAX_IDENTITY_LEN) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, + SSL_R_DATA_LENGTH_TOO_LONG); + return 0; + } + if (s->psk_server_callback == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, + SSL_R_PSK_NO_SERVER_CB); + return 0; + } + + if (!PACKET_strndup(&psk_identity, &s->session->psk_identity)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, + ERR_R_INTERNAL_ERROR); + return 0; + } + + psklen = s->psk_server_callback(s, s->session->psk_identity, + psk, sizeof(psk)); + + if (psklen > PSK_MAX_PSK_LEN) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, + ERR_R_INTERNAL_ERROR); + return 0; + } else if (psklen == 0) { + /* + * PSK related to the given identity not found + */ + SSLfatal(s, SSL_AD_UNKNOWN_PSK_IDENTITY, + SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, + SSL_R_PSK_IDENTITY_NOT_FOUND); + return 0; + } + + OPENSSL_free(s->s3->tmp.psk); + s->s3->tmp.psk = OPENSSL_memdup(psk, psklen); + OPENSSL_cleanse(psk, psklen); + + if (s->s3->tmp.psk == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, ERR_R_MALLOC_FAILURE); + return 0; + } + + s->s3->tmp.psklen = psklen; + + return 1; +#else + /* Should never happen */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, + ERR_R_INTERNAL_ERROR); + return 0; +#endif +} + +static int tls_process_cke_rsa(SSL *s, PACKET *pkt) +{ +#ifndef OPENSSL_NO_RSA + unsigned char rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH]; + int decrypt_len; + unsigned char decrypt_good, version_good; + size_t j, padding_len; + PACKET enc_premaster; + RSA *rsa = NULL; + unsigned char *rsa_decrypt = NULL; + int ret = 0; + + rsa = EVP_PKEY_get0_RSA(s->cert->pkeys[SSL_PKEY_RSA].privatekey); + if (rsa == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA, + SSL_R_MISSING_RSA_CERTIFICATE); + return 0; + } + + /* SSLv3 and pre-standard DTLS omit the length bytes. */ + if (s->version == SSL3_VERSION || s->version == DTLS1_BAD_VER) { + enc_premaster = *pkt; + } else { + if (!PACKET_get_length_prefixed_2(pkt, &enc_premaster) + || PACKET_remaining(pkt) != 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_RSA, + SSL_R_LENGTH_MISMATCH); + return 0; + } + } + + /* + * We want to be sure that the plaintext buffer size makes it safe to + * iterate over the entire size of a premaster secret + * (SSL_MAX_MASTER_KEY_LENGTH). Reject overly short RSA keys because + * their ciphertext cannot accommodate a premaster secret anyway. + */ + if (RSA_size(rsa) < SSL_MAX_MASTER_KEY_LENGTH) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA, + RSA_R_KEY_SIZE_TOO_SMALL); + return 0; + } + + rsa_decrypt = OPENSSL_malloc(RSA_size(rsa)); + if (rsa_decrypt == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA, + ERR_R_MALLOC_FAILURE); + return 0; + } + + /* + * We must not leak whether a decryption failure occurs because of + * Bleichenbacher's attack on PKCS #1 v1.5 RSA padding (see RFC 2246, + * section 7.4.7.1). The code follows that advice of the TLS RFC and + * generates a random premaster secret for the case that the decrypt + * fails. See https://tools.ietf.org/html/rfc5246#section-7.4.7.1 + */ + + if (RAND_priv_bytes(rand_premaster_secret, + sizeof(rand_premaster_secret)) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* + * Decrypt with no padding. PKCS#1 padding will be removed as part of + * the timing-sensitive code below. + */ + /* TODO(size_t): Convert this function */ + decrypt_len = (int)RSA_private_decrypt((int)PACKET_remaining(&enc_premaster), + PACKET_data(&enc_premaster), + rsa_decrypt, rsa, RSA_NO_PADDING); + if (decrypt_len < 0) { + SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CKE_RSA, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* Check the padding. See RFC 3447, section 7.2.2. */ + + /* + * The smallest padded premaster is 11 bytes of overhead. Small keys + * are publicly invalid, so this may return immediately. This ensures + * PS is at least 8 bytes. + */ + if (decrypt_len < 11 + SSL_MAX_MASTER_KEY_LENGTH) { + SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CKE_RSA, + SSL_R_DECRYPTION_FAILED); + goto err; + } + + padding_len = decrypt_len - SSL_MAX_MASTER_KEY_LENGTH; + decrypt_good = constant_time_eq_int_8(rsa_decrypt[0], 0) & + constant_time_eq_int_8(rsa_decrypt[1], 2); + for (j = 2; j < padding_len - 1; j++) { + decrypt_good &= ~constant_time_is_zero_8(rsa_decrypt[j]); + } + decrypt_good &= constant_time_is_zero_8(rsa_decrypt[padding_len - 1]); + + /* + * If the version in the decrypted pre-master secret is correct then + * version_good will be 0xff, otherwise it'll be zero. The + * Klima-Pokorny-Rosa extension of Bleichenbacher's attack + * (http://eprint.iacr.org/2003/052/) exploits the version number + * check as a "bad version oracle". Thus version checks are done in + * constant time and are treated like any other decryption error. + */ + version_good = + constant_time_eq_8(rsa_decrypt[padding_len], + (unsigned)(s->client_version >> 8)); + version_good &= + constant_time_eq_8(rsa_decrypt[padding_len + 1], + (unsigned)(s->client_version & 0xff)); + + /* + * The premaster secret must contain the same version number as the + * ClientHello to detect version rollback attacks (strangely, the + * protocol does not offer such protection for DH ciphersuites). + * However, buggy clients exist that send the negotiated protocol + * version instead if the server does not support the requested + * protocol version. If SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such + * clients. + */ + if (s->options & SSL_OP_TLS_ROLLBACK_BUG) { + unsigned char workaround_good; + workaround_good = constant_time_eq_8(rsa_decrypt[padding_len], + (unsigned)(s->version >> 8)); + workaround_good &= + constant_time_eq_8(rsa_decrypt[padding_len + 1], + (unsigned)(s->version & 0xff)); + version_good |= workaround_good; + } + + /* + * Both decryption and version must be good for decrypt_good to + * remain non-zero (0xff). + */ + decrypt_good &= version_good; + + /* + * Now copy rand_premaster_secret over from p using + * decrypt_good_mask. If decryption failed, then p does not + * contain valid plaintext, however, a check above guarantees + * it is still sufficiently large to read from. + */ + for (j = 0; j < sizeof(rand_premaster_secret); j++) { + rsa_decrypt[padding_len + j] = + constant_time_select_8(decrypt_good, + rsa_decrypt[padding_len + j], + rand_premaster_secret[j]); + } + + if (!ssl_generate_master_secret(s, rsa_decrypt + padding_len, + sizeof(rand_premaster_secret), 0)) { + /* SSLfatal() already called */ + goto err; + } + + ret = 1; + err: + OPENSSL_free(rsa_decrypt); + return ret; +#else + /* Should never happen */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA, + ERR_R_INTERNAL_ERROR); + return 0; +#endif +} + +static int tls_process_cke_dhe(SSL *s, PACKET *pkt) +{ +#ifndef OPENSSL_NO_DH + EVP_PKEY *skey = NULL; + DH *cdh; + unsigned int i; + BIGNUM *pub_key; + const unsigned char *data; + EVP_PKEY *ckey = NULL; + int ret = 0; + + if (!PACKET_get_net_2(pkt, &i) || PACKET_remaining(pkt) != i) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_DHE, + SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG); + goto err; + } + skey = s->s3->tmp.pkey; + if (skey == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE, + SSL_R_MISSING_TMP_DH_KEY); + goto err; + } + + if (PACKET_remaining(pkt) == 0L) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_DHE, + SSL_R_MISSING_TMP_DH_KEY); + goto err; + } + if (!PACKET_get_bytes(pkt, &data, i)) { + /* We already checked we have enough data */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE, + ERR_R_INTERNAL_ERROR); + goto err; + } + ckey = EVP_PKEY_new(); + if (ckey == NULL || EVP_PKEY_copy_parameters(ckey, skey) == 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE, + SSL_R_BN_LIB); + goto err; + } + + cdh = EVP_PKEY_get0_DH(ckey); + pub_key = BN_bin2bn(data, i, NULL); + if (pub_key == NULL || cdh == NULL || !DH_set0_key(cdh, pub_key, NULL)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE, + ERR_R_INTERNAL_ERROR); + BN_free(pub_key); + goto err; + } + + if (ssl_derive(s, skey, ckey, 1) == 0) { + /* SSLfatal() already called */ + goto err; + } + + ret = 1; + EVP_PKEY_free(s->s3->tmp.pkey); + s->s3->tmp.pkey = NULL; + err: + EVP_PKEY_free(ckey); + return ret; +#else + /* Should never happen */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE, + ERR_R_INTERNAL_ERROR); + return 0; +#endif +} + +static int tls_process_cke_ecdhe(SSL *s, PACKET *pkt) +{ +#ifndef OPENSSL_NO_EC + EVP_PKEY *skey = s->s3->tmp.pkey; + EVP_PKEY *ckey = NULL; + int ret = 0; + + if (PACKET_remaining(pkt) == 0L) { + /* We don't support ECDH client auth */ + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PROCESS_CKE_ECDHE, + SSL_R_MISSING_TMP_ECDH_KEY); + goto err; + } else { + unsigned int i; + const unsigned char *data; + + /* + * Get client's public key from encoded point in the + * ClientKeyExchange message. + */ + + /* Get encoded point length */ + if (!PACKET_get_1(pkt, &i) || !PACKET_get_bytes(pkt, &data, i) + || PACKET_remaining(pkt) != 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE, + SSL_R_LENGTH_MISMATCH); + goto err; + } + if (skey == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE, + SSL_R_MISSING_TMP_ECDH_KEY); + goto err; + } + + ckey = EVP_PKEY_new(); + if (ckey == NULL || EVP_PKEY_copy_parameters(ckey, skey) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE, + ERR_R_EVP_LIB); + goto err; + } + if (EVP_PKEY_set1_tls_encodedpoint(ckey, data, i) == 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE, + ERR_R_EC_LIB); + goto err; + } + } + + if (ssl_derive(s, skey, ckey, 1) == 0) { + /* SSLfatal() already called */ + goto err; + } + + ret = 1; + EVP_PKEY_free(s->s3->tmp.pkey); + s->s3->tmp.pkey = NULL; + err: + EVP_PKEY_free(ckey); + + return ret; +#else + /* Should never happen */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE, + ERR_R_INTERNAL_ERROR); + return 0; +#endif +} + +static int tls_process_cke_srp(SSL *s, PACKET *pkt) +{ +#ifndef OPENSSL_NO_SRP + unsigned int i; + const unsigned char *data; + + if (!PACKET_get_net_2(pkt, &i) + || !PACKET_get_bytes(pkt, &data, i)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_SRP, + SSL_R_BAD_SRP_A_LENGTH); + return 0; + } + if ((s->srp_ctx.A = BN_bin2bn(data, i, NULL)) == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_SRP, + ERR_R_BN_LIB); + return 0; + } + if (BN_ucmp(s->srp_ctx.A, s->srp_ctx.N) >= 0 || BN_is_zero(s->srp_ctx.A)) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_CKE_SRP, + SSL_R_BAD_SRP_PARAMETERS); + return 0; + } + OPENSSL_free(s->session->srp_username); + s->session->srp_username = OPENSSL_strdup(s->srp_ctx.login); + if (s->session->srp_username == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_SRP, + ERR_R_MALLOC_FAILURE); + return 0; + } + + if (!srp_generate_server_master_secret(s)) { + /* SSLfatal() already called */ + return 0; + } + + return 1; +#else + /* Should never happen */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_SRP, + ERR_R_INTERNAL_ERROR); + return 0; +#endif +} + +static int tls_process_cke_gost(SSL *s, PACKET *pkt) +{ +#ifndef OPENSSL_NO_GOST + EVP_PKEY_CTX *pkey_ctx; + EVP_PKEY *client_pub_pkey = NULL, *pk = NULL; + unsigned char premaster_secret[32]; + const unsigned char *start; + size_t outlen = 32, inlen; + unsigned long alg_a; + unsigned int asn1id, asn1len; + int ret = 0; + PACKET encdata; + + /* Get our certificate private key */ + alg_a = s->s3->tmp.new_cipher->algorithm_auth; + if (alg_a & SSL_aGOST12) { + /* + * New GOST ciphersuites have SSL_aGOST01 bit too + */ + pk = s->cert->pkeys[SSL_PKEY_GOST12_512].privatekey; + if (pk == NULL) { + pk = s->cert->pkeys[SSL_PKEY_GOST12_256].privatekey; + } + if (pk == NULL) { + pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey; + } + } else if (alg_a & SSL_aGOST01) { + pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey; + } + + pkey_ctx = EVP_PKEY_CTX_new(pk, NULL); + if (pkey_ctx == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, + ERR_R_MALLOC_FAILURE); + return 0; + } + if (EVP_PKEY_decrypt_init(pkey_ctx) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, + ERR_R_INTERNAL_ERROR); + return 0; + } + /* + * If client certificate is present and is of the same type, maybe + * use it for key exchange. Don't mind errors from + * EVP_PKEY_derive_set_peer, because it is completely valid to use a + * client certificate for authorization only. + */ + client_pub_pkey = X509_get0_pubkey(s->session->peer); + if (client_pub_pkey) { + if (EVP_PKEY_derive_set_peer(pkey_ctx, client_pub_pkey) <= 0) + ERR_clear_error(); + } + /* Decrypt session key */ + if (!PACKET_get_1(pkt, &asn1id) + || asn1id != (V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED) + || !PACKET_peek_1(pkt, &asn1len)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, + SSL_R_DECRYPTION_FAILED); + goto err; + } + if (asn1len == 0x81) { + /* + * Long form length. Should only be one byte of length. Anything else + * isn't supported. + * We did a successful peek before so this shouldn't fail + */ + if (!PACKET_forward(pkt, 1)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, + SSL_R_DECRYPTION_FAILED); + goto err; + } + } else if (asn1len >= 0x80) { + /* + * Indefinite length, or more than one long form length bytes. We don't + * support it + */ + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, + SSL_R_DECRYPTION_FAILED); + goto err; + } /* else short form length */ + + if (!PACKET_as_length_prefixed_1(pkt, &encdata)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, + SSL_R_DECRYPTION_FAILED); + goto err; + } + inlen = PACKET_remaining(&encdata); + start = PACKET_data(&encdata); + + if (EVP_PKEY_decrypt(pkey_ctx, premaster_secret, &outlen, start, + inlen) <= 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, + SSL_R_DECRYPTION_FAILED); + goto err; + } + /* Generate master secret */ + if (!ssl_generate_master_secret(s, premaster_secret, + sizeof(premaster_secret), 0)) { + /* SSLfatal() already called */ + goto err; + } + /* Check if pubkey from client certificate was used */ + if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, + NULL) > 0) + s->statem.no_cert_verify = 1; + + ret = 1; + err: + EVP_PKEY_CTX_free(pkey_ctx); + return ret; +#else + /* Should never happen */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, + ERR_R_INTERNAL_ERROR); + return 0; +#endif +} + +MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt) +{ + unsigned long alg_k; + + alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + + /* For PSK parse and retrieve identity, obtain PSK key */ + if ((alg_k & SSL_PSK) && !tls_process_cke_psk_preamble(s, pkt)) { + /* SSLfatal() already called */ + goto err; + } + + if (alg_k & SSL_kPSK) { + /* Identity extracted earlier: should be nothing left */ + if (PACKET_remaining(pkt) != 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, + SSL_R_LENGTH_MISMATCH); + goto err; + } + /* PSK handled by ssl_generate_master_secret */ + if (!ssl_generate_master_secret(s, NULL, 0, 0)) { + /* SSLfatal() already called */ + goto err; + } + } else if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) { + if (!tls_process_cke_rsa(s, pkt)) { + /* SSLfatal() already called */ + goto err; + } + } else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) { + if (!tls_process_cke_dhe(s, pkt)) { + /* SSLfatal() already called */ + goto err; + } + } else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) { + if (!tls_process_cke_ecdhe(s, pkt)) { + /* SSLfatal() already called */ + goto err; + } + } else if (alg_k & SSL_kSRP) { + if (!tls_process_cke_srp(s, pkt)) { + /* SSLfatal() already called */ + goto err; + } + } else if (alg_k & SSL_kGOST) { + if (!tls_process_cke_gost(s, pkt)) { + /* SSLfatal() already called */ + goto err; + } + } else { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, + SSL_R_UNKNOWN_CIPHER_TYPE); + goto err; + } + + return MSG_PROCESS_CONTINUE_PROCESSING; + err: +#ifndef OPENSSL_NO_PSK + OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen); + s->s3->tmp.psk = NULL; +#endif + return MSG_PROCESS_ERROR; +} + +WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst) +{ +#ifndef OPENSSL_NO_SCTP + if (wst == WORK_MORE_A) { + if (SSL_IS_DTLS(s)) { + unsigned char sctpauthkey[64]; + char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)]; + size_t labellen; + /* + * Add new shared key for SCTP-Auth, will be ignored if no SCTP + * used. + */ + memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL, + sizeof(DTLS1_SCTP_AUTH_LABEL)); + + /* Don't include the terminating zero. */ + labellen = sizeof(labelbuffer) - 1; + if (s->mode & SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG) + labellen += 1; + + if (SSL_export_keying_material(s, sctpauthkey, + sizeof(sctpauthkey), labelbuffer, + labellen, NULL, 0, + 0) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + return WORK_ERROR; + } + + BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY, + sizeof(sctpauthkey), sctpauthkey); + } + } +#endif + + if (s->statem.no_cert_verify || !s->session->peer) { + /* + * No certificate verify or no peer certificate so we no longer need + * the handshake_buffer + */ + if (!ssl3_digest_cached_records(s, 0)) { + /* SSLfatal() already called */ + return WORK_ERROR; + } + return WORK_FINISHED_CONTINUE; + } else { + if (!s->s3->handshake_buffer) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + return WORK_ERROR; + } + /* + * For sigalgs freeze the handshake buffer. If we support + * extms we've done this already so this is a no-op + */ + if (!ssl3_digest_cached_records(s, 1)) { + /* SSLfatal() already called */ + return WORK_ERROR; + } + } + + return WORK_FINISHED_CONTINUE; +} + +MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt) +{ + int i; + MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR; + X509 *x = NULL; + unsigned long l; + const unsigned char *certstart, *certbytes; + STACK_OF(X509) *sk = NULL; + PACKET spkt, context; + size_t chainidx; + SSL_SESSION *new_sess = NULL; + + /* + * To get this far we must have read encrypted data from the client. We no + * longer tolerate unencrypted alerts. This value is ignored if less than + * TLSv1.3 + */ + s->statem.enc_read_state = ENC_READ_STATE_VALID; + + if ((sk = sk_X509_new_null()) == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, + ERR_R_MALLOC_FAILURE); + goto err; + } + + if (SSL_IS_TLS13(s) && (!PACKET_get_length_prefixed_1(pkt, &context) + || (s->pha_context == NULL && PACKET_remaining(&context) != 0) + || (s->pha_context != NULL && + !PACKET_equal(&context, s->pha_context, s->pha_context_len)))) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, + SSL_R_INVALID_CONTEXT); + goto err; + } + + if (!PACKET_get_length_prefixed_3(pkt, &spkt) + || PACKET_remaining(pkt) != 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, + SSL_R_LENGTH_MISMATCH); + goto err; + } + + for (chainidx = 0; PACKET_remaining(&spkt) > 0; chainidx++) { + if (!PACKET_get_net_3(&spkt, &l) + || !PACKET_get_bytes(&spkt, &certbytes, l)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, + SSL_R_CERT_LENGTH_MISMATCH); + goto err; + } + + certstart = certbytes; + x = d2i_X509(NULL, (const unsigned char **)&certbytes, l); + if (x == NULL) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, ERR_R_ASN1_LIB); + goto err; + } + if (certbytes != (certstart + l)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, + SSL_R_CERT_LENGTH_MISMATCH); + goto err; + } + + if (SSL_IS_TLS13(s)) { + RAW_EXTENSION *rawexts = NULL; + PACKET extensions; + + if (!PACKET_get_length_prefixed_2(&spkt, &extensions)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, + SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, + SSL_R_BAD_LENGTH); + goto err; + } + if (!tls_collect_extensions(s, &extensions, + SSL_EXT_TLS1_3_CERTIFICATE, &rawexts, + NULL, chainidx == 0) + || !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_CERTIFICATE, + rawexts, x, chainidx, + PACKET_remaining(&spkt) == 0)) { + OPENSSL_free(rawexts); + goto err; + } + OPENSSL_free(rawexts); + } + + if (!sk_X509_push(sk, x)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, + ERR_R_MALLOC_FAILURE); + goto err; + } + x = NULL; + } + + if (sk_X509_num(sk) <= 0) { + /* TLS does not mind 0 certs returned */ + if (s->version == SSL3_VERSION) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, + SSL_R_NO_CERTIFICATES_RETURNED); + goto err; + } + /* Fail for TLS only if we required a certificate */ + else if ((s->verify_mode & SSL_VERIFY_PEER) && + (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) { + SSLfatal(s, SSL_AD_CERTIFICATE_REQUIRED, + SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, + SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); + goto err; + } + /* No client certificate so digest cached records */ + if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s, 0)) { + /* SSLfatal() already called */ + goto err; + } + } else { + EVP_PKEY *pkey; + i = ssl_verify_cert_chain(s, sk); + if (i <= 0) { + SSLfatal(s, ssl_x509err2alert(s->verify_result), + SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, + SSL_R_CERTIFICATE_VERIFY_FAILED); + goto err; + } + if (i > 1) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, i); + goto err; + } + pkey = X509_get0_pubkey(sk_X509_value(sk, 0)); + if (pkey == NULL) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, + SSL_R_UNKNOWN_CERTIFICATE_TYPE); + goto err; + } + } + + /* + * Sessions must be immutable once they go into the session cache. Otherwise + * we can get multi-thread problems. Therefore we don't "update" sessions, + * we replace them with a duplicate. Here, we need to do this every time + * a new certificate is received via post-handshake authentication, as the + * session may have already gone into the session cache. + */ + + if (s->post_handshake_auth == SSL_PHA_REQUESTED) { + if ((new_sess = ssl_session_dup(s->session, 0)) == 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, + ERR_R_MALLOC_FAILURE); + goto err; + } + + SSL_SESSION_free(s->session); + s->session = new_sess; + } + + X509_free(s->session->peer); + s->session->peer = sk_X509_shift(sk); + s->session->verify_result = s->verify_result; + + sk_X509_pop_free(s->session->peer_chain, X509_free); + s->session->peer_chain = sk; + + /* + * Freeze the handshake buffer. For cert_verify_hash, + sizeof(s->cert_verify_hash), + &s->cert_verify_hash_len)) { + /* SSLfatal() already called */ + goto err; + } + + /* Resend session tickets */ + s->sent_tickets = 0; + } + + ret = MSG_PROCESS_CONTINUE_READING; + + err: + X509_free(x); + sk_X509_pop_free(sk, X509_free); + return ret; +} + +int tls_construct_server_certificate(SSL *s, WPACKET *pkt) +{ + CERT_PKEY *cpk = s->s3->tmp.cert; + + if (cpk == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR); + return 0; + } + + /* + * In TLSv1.3 the certificate chain is always preceded by a 0 length context + * for the server Certificate message + */ + if (SSL_IS_TLS13(s) && !WPACKET_put_bytes_u8(pkt, 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR); + return 0; + } + if (!ssl3_output_cert_chain(s, pkt, cpk)) { + /* SSLfatal() already called */ + return 0; + } + + return 1; +} + +static int create_ticket_prequel(SSL *s, WPACKET *pkt, uint32_t age_add, + unsigned char *tick_nonce) +{ + /* + * Ticket lifetime hint: For TLSv1.2 this is advisory only and we leave this + * unspecified for resumed session (for simplicity). + * In TLSv1.3 we reset the "time" field above, and always specify the + * timeout. + */ + if (!WPACKET_put_bytes_u32(pkt, + (s->hit && !SSL_IS_TLS13(s)) + ? 0 : s->session->timeout)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CREATE_TICKET_PREQUEL, + ERR_R_INTERNAL_ERROR); + return 0; + } + + if (SSL_IS_TLS13(s)) { + if (!WPACKET_put_bytes_u32(pkt, age_add) + || !WPACKET_sub_memcpy_u8(pkt, tick_nonce, TICKET_NONCE_SIZE)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CREATE_TICKET_PREQUEL, + ERR_R_INTERNAL_ERROR); + return 0; + } + } + + /* Start the sub-packet for the actual ticket data */ + if (!WPACKET_start_sub_packet_u16(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CREATE_TICKET_PREQUEL, + ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} + +static int construct_stateless_ticket(SSL *s, WPACKET *pkt, uint32_t age_add, + unsigned char *tick_nonce) +{ + unsigned char *senc = NULL; + EVP_CIPHER_CTX *ctx = NULL; + HMAC_CTX *hctx = NULL; + unsigned char *p, *encdata1, *encdata2, *macdata1, *macdata2; + const unsigned char *const_p; + int len, slen_full, slen, lenfinal; + SSL_SESSION *sess; + unsigned int hlen; + SSL_CTX *tctx = s->session_ctx; + unsigned char iv[EVP_MAX_IV_LENGTH]; + unsigned char key_name[TLSEXT_KEYNAME_LENGTH]; + int iv_len, ok = 0; + size_t macoffset, macendoffset; + + /* get session encoding length */ + slen_full = i2d_SSL_SESSION(s->session, NULL); + /* + * Some length values are 16 bits, so forget it if session is too + * long + */ + if (slen_full == 0 || slen_full > 0xFF00) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET, + ERR_R_INTERNAL_ERROR); + goto err; + } + senc = OPENSSL_malloc(slen_full); + if (senc == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_CONSTRUCT_STATELESS_TICKET, ERR_R_MALLOC_FAILURE); + goto err; + } + + ctx = EVP_CIPHER_CTX_new(); + hctx = HMAC_CTX_new(); + if (ctx == NULL || hctx == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET, + ERR_R_MALLOC_FAILURE); + goto err; + } + + p = senc; + if (!i2d_SSL_SESSION(s->session, &p)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* + * create a fresh copy (not shared with other threads) to clean up + */ + const_p = senc; + sess = d2i_SSL_SESSION(NULL, &const_p, slen_full); + if (sess == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET, + ERR_R_INTERNAL_ERROR); + goto err; + } + + slen = i2d_SSL_SESSION(sess, NULL); + if (slen == 0 || slen > slen_full) { + /* shouldn't ever happen */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET, + ERR_R_INTERNAL_ERROR); + SSL_SESSION_free(sess); + goto err; + } + p = senc; + if (!i2d_SSL_SESSION(sess, &p)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET, + ERR_R_INTERNAL_ERROR); + SSL_SESSION_free(sess); + goto err; + } + SSL_SESSION_free(sess); + + /* + * Initialize HMAC and cipher contexts. If callback present it does + * all the work otherwise use generated values from parent ctx. + */ + if (tctx->ext.ticket_key_cb) { + /* if 0 is returned, write an empty ticket */ + int ret = tctx->ext.ticket_key_cb(s, key_name, iv, ctx, + hctx, 1); + + if (ret == 0) { + + /* Put timeout and length */ + if (!WPACKET_put_bytes_u32(pkt, 0) + || !WPACKET_put_bytes_u16(pkt, 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_CONSTRUCT_STATELESS_TICKET, + ERR_R_INTERNAL_ERROR); + goto err; + } + OPENSSL_free(senc); + EVP_CIPHER_CTX_free(ctx); + HMAC_CTX_free(hctx); + return 1; + } + if (ret < 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET, + SSL_R_CALLBACK_FAILED); + goto err; + } + iv_len = EVP_CIPHER_CTX_iv_length(ctx); + } else { + const EVP_CIPHER *cipher = EVP_aes_256_cbc(); + + iv_len = EVP_CIPHER_iv_length(cipher); + if (RAND_bytes(iv, iv_len) <= 0 + || !EVP_EncryptInit_ex(ctx, cipher, NULL, + tctx->ext.secure->tick_aes_key, iv) + || !HMAC_Init_ex(hctx, tctx->ext.secure->tick_hmac_key, + sizeof(tctx->ext.secure->tick_hmac_key), + EVP_sha256(), NULL)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET, + ERR_R_INTERNAL_ERROR); + goto err; + } + memcpy(key_name, tctx->ext.tick_key_name, + sizeof(tctx->ext.tick_key_name)); + } + + if (!create_ticket_prequel(s, pkt, age_add, tick_nonce)) { + /* SSLfatal() already called */ + goto err; + } + + if (!WPACKET_get_total_written(pkt, &macoffset) + /* Output key name */ + || !WPACKET_memcpy(pkt, key_name, sizeof(key_name)) + /* output IV */ + || !WPACKET_memcpy(pkt, iv, iv_len) + || !WPACKET_reserve_bytes(pkt, slen + EVP_MAX_BLOCK_LENGTH, + &encdata1) + /* Encrypt session data */ + || !EVP_EncryptUpdate(ctx, encdata1, &len, senc, slen) + || !WPACKET_allocate_bytes(pkt, len, &encdata2) + || encdata1 != encdata2 + || !EVP_EncryptFinal(ctx, encdata1 + len, &lenfinal) + || !WPACKET_allocate_bytes(pkt, lenfinal, &encdata2) + || encdata1 + len != encdata2 + || len + lenfinal > slen + EVP_MAX_BLOCK_LENGTH + || !WPACKET_get_total_written(pkt, &macendoffset) + || !HMAC_Update(hctx, + (unsigned char *)s->init_buf->data + macoffset, + macendoffset - macoffset) + || !WPACKET_reserve_bytes(pkt, EVP_MAX_MD_SIZE, &macdata1) + || !HMAC_Final(hctx, macdata1, &hlen) + || hlen > EVP_MAX_MD_SIZE + || !WPACKET_allocate_bytes(pkt, hlen, &macdata2) + || macdata1 != macdata2) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_CONSTRUCT_STATELESS_TICKET, ERR_R_INTERNAL_ERROR); + goto err; + } + + /* Close the sub-packet created by create_ticket_prequel() */ + if (!WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET, + ERR_R_INTERNAL_ERROR); + goto err; + } + + ok = 1; + err: + OPENSSL_free(senc); + EVP_CIPHER_CTX_free(ctx); + HMAC_CTX_free(hctx); + return ok; +} + +static int construct_stateful_ticket(SSL *s, WPACKET *pkt, uint32_t age_add, + unsigned char *tick_nonce) +{ + if (!create_ticket_prequel(s, pkt, age_add, tick_nonce)) { + /* SSLfatal() already called */ + return 0; + } + + if (!WPACKET_memcpy(pkt, s->session->session_id, + s->session->session_id_length) + || !WPACKET_close(pkt)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATEFUL_TICKET, + ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} + +int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt) +{ + SSL_CTX *tctx = s->session_ctx; + unsigned char tick_nonce[TICKET_NONCE_SIZE]; + union { + unsigned char age_add_c[sizeof(uint32_t)]; + uint32_t age_add; + } age_add_u; + + age_add_u.age_add = 0; + + if (SSL_IS_TLS13(s)) { + size_t i, hashlen; + uint64_t nonce; + static const unsigned char nonce_label[] = "resumption"; + const EVP_MD *md = ssl_handshake_md(s); + int hashleni = EVP_MD_size(md); + + /* Ensure cast to size_t is safe */ + if (!ossl_assert(hashleni >= 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, + ERR_R_INTERNAL_ERROR); + goto err; + } + hashlen = (size_t)hashleni; + + /* + * If we already sent one NewSessionTicket, or we resumed then + * s->session may already be in a cache and so we must not modify it. + * Instead we need to take a copy of it and modify that. + */ + if (s->sent_tickets != 0 || s->hit) { + SSL_SESSION *new_sess = ssl_session_dup(s->session, 0); + + if (new_sess == NULL) { + /* SSLfatal already called */ + goto err; + } + + SSL_SESSION_free(s->session); + s->session = new_sess; + } + + if (!ssl_generate_session_id(s, s->session)) { + /* SSLfatal() already called */ + goto err; + } + if (RAND_bytes(age_add_u.age_add_c, sizeof(age_add_u)) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, + ERR_R_INTERNAL_ERROR); + goto err; + } + s->session->ext.tick_age_add = age_add_u.age_add; + + nonce = s->next_ticket_nonce; + for (i = TICKET_NONCE_SIZE; i > 0; i--) { + tick_nonce[i - 1] = (unsigned char)(nonce & 0xff); + nonce >>= 8; + } + + if (!tls13_hkdf_expand(s, md, s->resumption_master_secret, + nonce_label, + sizeof(nonce_label) - 1, + tick_nonce, + TICKET_NONCE_SIZE, + s->session->master_key, + hashlen, 1)) { + /* SSLfatal() already called */ + goto err; + } + s->session->master_key_length = hashlen; + + s->session->time = (long)time(NULL); + if (s->s3->alpn_selected != NULL) { + OPENSSL_free(s->session->ext.alpn_selected); + s->session->ext.alpn_selected = + OPENSSL_memdup(s->s3->alpn_selected, s->s3->alpn_selected_len); + if (s->session->ext.alpn_selected == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, + ERR_R_MALLOC_FAILURE); + goto err; + } + s->session->ext.alpn_selected_len = s->s3->alpn_selected_len; + } + s->session->ext.max_early_data = s->max_early_data; + } + + if (tctx->generate_ticket_cb != NULL && + tctx->generate_ticket_cb(s, tctx->ticket_cb_data) == 0) + goto err; + + /* + * If we are using anti-replay protection then we behave as if + * SSL_OP_NO_TICKET is set - we are caching tickets anyway so there + * is no point in using full stateless tickets. + */ + if (SSL_IS_TLS13(s) + && ((s->options & SSL_OP_NO_TICKET) != 0 + || (s->max_early_data > 0 + && (s->options & SSL_OP_NO_ANTI_REPLAY) == 0))) { + if (!construct_stateful_ticket(s, pkt, age_add_u.age_add, tick_nonce)) { + /* SSLfatal() already called */ + goto err; + } + } else if (!construct_stateless_ticket(s, pkt, age_add_u.age_add, + tick_nonce)) { + /* SSLfatal() already called */ + goto err; + } + + if (SSL_IS_TLS13(s)) { + if (!tls_construct_extensions(s, pkt, + SSL_EXT_TLS1_3_NEW_SESSION_TICKET, + NULL, 0)) { + /* SSLfatal() already called */ + goto err; + } + /* + * Increment both |sent_tickets| and |next_ticket_nonce|. |sent_tickets| + * gets reset to 0 if we send more tickets following a post-handshake + * auth, but |next_ticket_nonce| does not. + */ + s->sent_tickets++; + s->next_ticket_nonce++; + ssl_update_cache(s, SSL_SESS_CACHE_SERVER); + } + + return 1; + err: + return 0; +} + +/* + * In TLSv1.3 this is called from the extensions code, otherwise it is used to + * create a separate message. Returns 1 on success or 0 on failure. + */ +int tls_construct_cert_status_body(SSL *s, WPACKET *pkt) +{ + if (!WPACKET_put_bytes_u8(pkt, s->ext.status_type) + || !WPACKET_sub_memcpy_u24(pkt, s->ext.ocsp.resp, + s->ext.ocsp.resp_len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_STATUS_BODY, + ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} + +int tls_construct_cert_status(SSL *s, WPACKET *pkt) +{ + if (!tls_construct_cert_status_body(s, pkt)) { + /* SSLfatal() already called */ + return 0; + } + + return 1; +} + +#ifndef OPENSSL_NO_NEXTPROTONEG +/* + * tls_process_next_proto reads a Next Protocol Negotiation handshake message. + * It sets the next_proto member in s if found + */ +MSG_PROCESS_RETURN tls_process_next_proto(SSL *s, PACKET *pkt) +{ + PACKET next_proto, padding; + size_t next_proto_len; + + /*- + * The payload looks like: + * uint8 proto_len; + * uint8 proto[proto_len]; + * uint8 padding_len; + * uint8 padding[padding_len]; + */ + if (!PACKET_get_length_prefixed_1(pkt, &next_proto) + || !PACKET_get_length_prefixed_1(pkt, &padding) + || PACKET_remaining(pkt) > 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_NEXT_PROTO, + SSL_R_LENGTH_MISMATCH); + return MSG_PROCESS_ERROR; + } + + if (!PACKET_memdup(&next_proto, &s->ext.npn, &next_proto_len)) { + s->ext.npn_len = 0; + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_NEXT_PROTO, + ERR_R_INTERNAL_ERROR); + return MSG_PROCESS_ERROR; + } + + s->ext.npn_len = (unsigned char)next_proto_len; + + return MSG_PROCESS_CONTINUE_READING; +} +#endif + +static int tls_construct_encrypted_extensions(SSL *s, WPACKET *pkt) +{ + if (!tls_construct_extensions(s, pkt, SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS, + NULL, 0)) { + /* SSLfatal() already called */ + return 0; + } + + return 1; +} + +MSG_PROCESS_RETURN tls_process_end_of_early_data(SSL *s, PACKET *pkt) +{ + if (PACKET_remaining(pkt) != 0) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_END_OF_EARLY_DATA, + SSL_R_LENGTH_MISMATCH); + return MSG_PROCESS_ERROR; + } + + if (s->early_data_state != SSL_EARLY_DATA_READING + && s->early_data_state != SSL_EARLY_DATA_READ_RETRY) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_END_OF_EARLY_DATA, + ERR_R_INTERNAL_ERROR); + return MSG_PROCESS_ERROR; + } + + /* + * EndOfEarlyData signals a key change so the end of the message must be on + * a record boundary. + */ + if (RECORD_LAYER_processed_read_pending(&s->rlayer)) { + SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, + SSL_F_TLS_PROCESS_END_OF_EARLY_DATA, + SSL_R_NOT_ON_RECORD_BOUNDARY); + return MSG_PROCESS_ERROR; + } + + s->early_data_state = SSL_EARLY_DATA_FINISHED_READING; + if (!s->method->ssl3_enc->change_cipher_state(s, + SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_SERVER_READ)) { + /* SSLfatal() already called */ + return MSG_PROCESS_ERROR; + } + + return MSG_PROCESS_CONTINUE_READING; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/t1_enc.c b/trunk/3rdparty/openssl-1.1-fit/ssl/t1_enc.c new file mode 100644 index 000000000..57fb17a66 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/t1_enc.c @@ -0,0 +1,678 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2005 Nokia. All rights reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "ssl_locl.h" +#include +#include +#include +#include + +/* seed1 through seed5 are concatenated */ +static int tls1_PRF(SSL *s, + const void *seed1, size_t seed1_len, + const void *seed2, size_t seed2_len, + const void *seed3, size_t seed3_len, + const void *seed4, size_t seed4_len, + const void *seed5, size_t seed5_len, + const unsigned char *sec, size_t slen, + unsigned char *out, size_t olen, int fatal) +{ + const EVP_MD *md = ssl_prf_md(s); + EVP_PKEY_CTX *pctx = NULL; + int ret = 0; + + if (md == NULL) { + /* Should never happen */ + if (fatal) + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_PRF, + ERR_R_INTERNAL_ERROR); + else + SSLerr(SSL_F_TLS1_PRF, ERR_R_INTERNAL_ERROR); + return 0; + } + pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_TLS1_PRF, NULL); + if (pctx == NULL || EVP_PKEY_derive_init(pctx) <= 0 + || EVP_PKEY_CTX_set_tls1_prf_md(pctx, md) <= 0 + || EVP_PKEY_CTX_set1_tls1_prf_secret(pctx, sec, (int)slen) <= 0 + || EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed1, (int)seed1_len) <= 0 + || EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed2, (int)seed2_len) <= 0 + || EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed3, (int)seed3_len) <= 0 + || EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed4, (int)seed4_len) <= 0 + || EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed5, (int)seed5_len) <= 0 + || EVP_PKEY_derive(pctx, out, &olen) <= 0) { + if (fatal) + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_PRF, + ERR_R_INTERNAL_ERROR); + else + SSLerr(SSL_F_TLS1_PRF, ERR_R_INTERNAL_ERROR); + goto err; + } + + ret = 1; + + err: + EVP_PKEY_CTX_free(pctx); + return ret; +} + +static int tls1_generate_key_block(SSL *s, unsigned char *km, size_t num) +{ + int ret; + + /* Calls SSLfatal() as required */ + ret = tls1_PRF(s, + TLS_MD_KEY_EXPANSION_CONST, + TLS_MD_KEY_EXPANSION_CONST_SIZE, s->s3->server_random, + SSL3_RANDOM_SIZE, s->s3->client_random, SSL3_RANDOM_SIZE, + NULL, 0, NULL, 0, s->session->master_key, + s->session->master_key_length, km, num, 1); + + return ret; +} + +int tls1_change_cipher_state(SSL *s, int which) +{ + unsigned char *p, *mac_secret; + unsigned char *ms, *key, *iv; + EVP_CIPHER_CTX *dd; + const EVP_CIPHER *c; +#ifndef OPENSSL_NO_COMP + const SSL_COMP *comp; +#endif + const EVP_MD *m; + int mac_type; + size_t *mac_secret_size; + EVP_MD_CTX *mac_ctx; + EVP_PKEY *mac_key; + size_t n, i, j, k, cl; + int reuse_dd = 0; + + c = s->s3->tmp.new_sym_enc; + m = s->s3->tmp.new_hash; + mac_type = s->s3->tmp.new_mac_pkey_type; +#ifndef OPENSSL_NO_COMP + comp = s->s3->tmp.new_compression; +#endif + + if (which & SSL3_CC_READ) { + if (s->ext.use_etm) + s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC_READ; + else + s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC_READ; + + if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC) + s->mac_flags |= SSL_MAC_FLAG_READ_MAC_STREAM; + else + s->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_STREAM; + + if (s->enc_read_ctx != NULL) { + reuse_dd = 1; + } else if ((s->enc_read_ctx = EVP_CIPHER_CTX_new()) == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE, + ERR_R_MALLOC_FAILURE); + goto err; + } else { + /* + * make sure it's initialised in case we exit later with an error + */ + EVP_CIPHER_CTX_reset(s->enc_read_ctx); + } + dd = s->enc_read_ctx; + mac_ctx = ssl_replace_hash(&s->read_hash, NULL); + if (mac_ctx == NULL) + goto err; +#ifndef OPENSSL_NO_COMP + COMP_CTX_free(s->expand); + s->expand = NULL; + if (comp != NULL) { + s->expand = COMP_CTX_new(comp->method); + if (s->expand == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS1_CHANGE_CIPHER_STATE, + SSL_R_COMPRESSION_LIBRARY_ERROR); + goto err; + } + } +#endif + /* + * this is done by dtls1_reset_seq_numbers for DTLS + */ + if (!SSL_IS_DTLS(s)) + RECORD_LAYER_reset_read_sequence(&s->rlayer); + mac_secret = &(s->s3->read_mac_secret[0]); + mac_secret_size = &(s->s3->read_mac_secret_size); + } else { + s->statem.enc_write_state = ENC_WRITE_STATE_INVALID; + if (s->ext.use_etm) + s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC_WRITE; + else + s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC_WRITE; + + if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC) + s->mac_flags |= SSL_MAC_FLAG_WRITE_MAC_STREAM; + else + s->mac_flags &= ~SSL_MAC_FLAG_WRITE_MAC_STREAM; + if (s->enc_write_ctx != NULL && !SSL_IS_DTLS(s)) { + reuse_dd = 1; + } else if ((s->enc_write_ctx = EVP_CIPHER_CTX_new()) == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE, + ERR_R_MALLOC_FAILURE); + goto err; + } + dd = s->enc_write_ctx; + if (SSL_IS_DTLS(s)) { + mac_ctx = EVP_MD_CTX_new(); + if (mac_ctx == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS1_CHANGE_CIPHER_STATE, + ERR_R_MALLOC_FAILURE); + goto err; + } + s->write_hash = mac_ctx; + } else { + mac_ctx = ssl_replace_hash(&s->write_hash, NULL); + if (mac_ctx == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS1_CHANGE_CIPHER_STATE, + ERR_R_MALLOC_FAILURE); + goto err; + } + } +#ifndef OPENSSL_NO_COMP + COMP_CTX_free(s->compress); + s->compress = NULL; + if (comp != NULL) { + s->compress = COMP_CTX_new(comp->method); + if (s->compress == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS1_CHANGE_CIPHER_STATE, + SSL_R_COMPRESSION_LIBRARY_ERROR); + goto err; + } + } +#endif + /* + * this is done by dtls1_reset_seq_numbers for DTLS + */ + if (!SSL_IS_DTLS(s)) + RECORD_LAYER_reset_write_sequence(&s->rlayer); + mac_secret = &(s->s3->write_mac_secret[0]); + mac_secret_size = &(s->s3->write_mac_secret_size); + } + + if (reuse_dd) + EVP_CIPHER_CTX_reset(dd); + + p = s->s3->tmp.key_block; + i = *mac_secret_size = s->s3->tmp.new_mac_secret_size; + + /* TODO(size_t): convert me */ + cl = EVP_CIPHER_key_length(c); + j = cl; + /* Was j=(exp)?5:EVP_CIPHER_key_length(c); */ + /* If GCM/CCM mode only part of IV comes from PRF */ + if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE) + k = EVP_GCM_TLS_FIXED_IV_LEN; + else if (EVP_CIPHER_mode(c) == EVP_CIPH_CCM_MODE) + k = EVP_CCM_TLS_FIXED_IV_LEN; + else + k = EVP_CIPHER_iv_length(c); + if ((which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) || + (which == SSL3_CHANGE_CIPHER_SERVER_READ)) { + ms = &(p[0]); + n = i + i; + key = &(p[n]); + n += j + j; + iv = &(p[n]); + n += k + k; + } else { + n = i; + ms = &(p[n]); + n += i + j; + key = &(p[n]); + n += j + k; + iv = &(p[n]); + n += k; + } + + if (n > s->s3->tmp.key_block_length) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE, + ERR_R_INTERNAL_ERROR); + goto err; + } + + memcpy(mac_secret, ms, i); + + if (!(EVP_CIPHER_flags(c) & EVP_CIPH_FLAG_AEAD_CIPHER)) { + /* TODO(size_t): Convert this function */ + mac_key = EVP_PKEY_new_mac_key(mac_type, NULL, mac_secret, + (int)*mac_secret_size); + if (mac_key == NULL + || EVP_DigestSignInit(mac_ctx, NULL, m, NULL, mac_key) <= 0) { + EVP_PKEY_free(mac_key); + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE, + ERR_R_INTERNAL_ERROR); + goto err; + } + EVP_PKEY_free(mac_key); + } +#ifdef SSL_DEBUG + printf("which = %04X\nmac key=", which); + { + size_t z; + for (z = 0; z < i; z++) + printf("%02X%c", ms[z], ((z + 1) % 16) ? ' ' : '\n'); + } +#endif + + if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE) { + if (!EVP_CipherInit_ex(dd, c, NULL, key, NULL, (which & SSL3_CC_WRITE)) + || !EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_GCM_SET_IV_FIXED, (int)k, + iv)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE, + ERR_R_INTERNAL_ERROR); + goto err; + } + } else if (EVP_CIPHER_mode(c) == EVP_CIPH_CCM_MODE) { + int taglen; + if (s->s3->tmp. + new_cipher->algorithm_enc & (SSL_AES128CCM8 | SSL_AES256CCM8)) + taglen = EVP_CCM8_TLS_TAG_LEN; + else + taglen = EVP_CCM_TLS_TAG_LEN; + if (!EVP_CipherInit_ex(dd, c, NULL, NULL, NULL, (which & SSL3_CC_WRITE)) + || !EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_AEAD_SET_IVLEN, 12, NULL) + || !EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_AEAD_SET_TAG, taglen, NULL) + || !EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_CCM_SET_IV_FIXED, (int)k, iv) + || !EVP_CipherInit_ex(dd, NULL, NULL, key, NULL, -1)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE, + ERR_R_INTERNAL_ERROR); + goto err; + } + } else { + if (!EVP_CipherInit_ex(dd, c, NULL, key, iv, (which & SSL3_CC_WRITE))) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE, + ERR_R_INTERNAL_ERROR); + goto err; + } + } + /* Needed for "composite" AEADs, such as RC4-HMAC-MD5 */ + if ((EVP_CIPHER_flags(c) & EVP_CIPH_FLAG_AEAD_CIPHER) && *mac_secret_size + && !EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_AEAD_SET_MAC_KEY, + (int)*mac_secret_size, mac_secret)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE, + ERR_R_INTERNAL_ERROR); + goto err; + } + s->statem.enc_write_state = ENC_WRITE_STATE_VALID; + +#ifdef SSL_DEBUG + printf("which = %04X\nkey=", which); + { + int z; + for (z = 0; z < EVP_CIPHER_key_length(c); z++) + printf("%02X%c", key[z], ((z + 1) % 16) ? ' ' : '\n'); + } + printf("\niv="); + { + size_t z; + for (z = 0; z < k; z++) + printf("%02X%c", iv[z], ((z + 1) % 16) ? ' ' : '\n'); + } + printf("\n"); +#endif + + return 1; + err: + return 0; +} + +int tls1_setup_key_block(SSL *s) +{ + unsigned char *p; + const EVP_CIPHER *c; + const EVP_MD *hash; + SSL_COMP *comp; + int mac_type = NID_undef; + size_t num, mac_secret_size = 0; + int ret = 0; + + if (s->s3->tmp.key_block_length != 0) + return 1; + + if (!ssl_cipher_get_evp(s->session, &c, &hash, &mac_type, &mac_secret_size, + &comp, s->ext.use_etm)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_SETUP_KEY_BLOCK, + SSL_R_CIPHER_OR_HASH_UNAVAILABLE); + return 0; + } + + s->s3->tmp.new_sym_enc = c; + s->s3->tmp.new_hash = hash; + s->s3->tmp.new_mac_pkey_type = mac_type; + s->s3->tmp.new_mac_secret_size = mac_secret_size; + num = EVP_CIPHER_key_length(c) + mac_secret_size + EVP_CIPHER_iv_length(c); + num *= 2; + + ssl3_cleanup_key_block(s); + + if ((p = OPENSSL_malloc(num)) == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_SETUP_KEY_BLOCK, + ERR_R_MALLOC_FAILURE); + goto err; + } + + s->s3->tmp.key_block_length = num; + s->s3->tmp.key_block = p; + +#ifdef SSL_DEBUG + printf("client random\n"); + { + int z; + for (z = 0; z < SSL3_RANDOM_SIZE; z++) + printf("%02X%c", s->s3->client_random[z], + ((z + 1) % 16) ? ' ' : '\n'); + } + printf("server random\n"); + { + int z; + for (z = 0; z < SSL3_RANDOM_SIZE; z++) + printf("%02X%c", s->s3->server_random[z], + ((z + 1) % 16) ? ' ' : '\n'); + } + printf("master key\n"); + { + size_t z; + for (z = 0; z < s->session->master_key_length; z++) + printf("%02X%c", s->session->master_key[z], + ((z + 1) % 16) ? ' ' : '\n'); + } +#endif + if (!tls1_generate_key_block(s, p, num)) { + /* SSLfatal() already called */ + goto err; + } +#ifdef SSL_DEBUG + printf("\nkey block\n"); + { + size_t z; + for (z = 0; z < num; z++) + printf("%02X%c", p[z], ((z + 1) % 16) ? ' ' : '\n'); + } +#endif + + if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) + && s->method->version <= TLS1_VERSION) { + /* + * enable vulnerability countermeasure for CBC ciphers with known-IV + * problem (http://www.openssl.org/~bodo/tls-cbc.txt) + */ + s->s3->need_empty_fragments = 1; + + if (s->session->cipher != NULL) { + if (s->session->cipher->algorithm_enc == SSL_eNULL) + s->s3->need_empty_fragments = 0; + +#ifndef OPENSSL_NO_RC4 + if (s->session->cipher->algorithm_enc == SSL_RC4) + s->s3->need_empty_fragments = 0; +#endif + } + } + + ret = 1; + err: + return ret; +} + +size_t tls1_final_finish_mac(SSL *s, const char *str, size_t slen, + unsigned char *out) +{ + size_t hashlen; + unsigned char hash[EVP_MAX_MD_SIZE]; + + if (!ssl3_digest_cached_records(s, 0)) { + /* SSLfatal() already called */ + return 0; + } + + if (!ssl_handshake_hash(s, hash, sizeof(hash), &hashlen)) { + /* SSLfatal() already called */ + return 0; + } + + if (!tls1_PRF(s, str, slen, hash, hashlen, NULL, 0, NULL, 0, NULL, 0, + s->session->master_key, s->session->master_key_length, + out, TLS1_FINISH_MAC_LENGTH, 1)) { + /* SSLfatal() already called */ + return 0; + } + OPENSSL_cleanse(hash, hashlen); + return TLS1_FINISH_MAC_LENGTH; +} + +int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, + size_t len, size_t *secret_size) +{ + if (s->session->flags & SSL_SESS_FLAG_EXTMS) { + unsigned char hash[EVP_MAX_MD_SIZE * 2]; + size_t hashlen; + /* + * Digest cached records keeping record buffer (if present): this wont + * affect client auth because we're freezing the buffer at the same + * point (after client key exchange and before certificate verify) + */ + if (!ssl3_digest_cached_records(s, 1) + || !ssl_handshake_hash(s, hash, sizeof(hash), &hashlen)) { + /* SSLfatal() already called */ + return 0; + } +#ifdef SSL_DEBUG + fprintf(stderr, "Handshake hashes:\n"); + BIO_dump_fp(stderr, (char *)hash, hashlen); +#endif + if (!tls1_PRF(s, + TLS_MD_EXTENDED_MASTER_SECRET_CONST, + TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE, + hash, hashlen, + NULL, 0, + NULL, 0, + NULL, 0, p, len, out, + SSL3_MASTER_SECRET_SIZE, 1)) { + /* SSLfatal() already called */ + return 0; + } + OPENSSL_cleanse(hash, hashlen); + } else { + if (!tls1_PRF(s, + TLS_MD_MASTER_SECRET_CONST, + TLS_MD_MASTER_SECRET_CONST_SIZE, + s->s3->client_random, SSL3_RANDOM_SIZE, + NULL, 0, + s->s3->server_random, SSL3_RANDOM_SIZE, + NULL, 0, p, len, out, + SSL3_MASTER_SECRET_SIZE, 1)) { + /* SSLfatal() already called */ + return 0; + } + } +#ifdef SSL_DEBUG + fprintf(stderr, "Premaster Secret:\n"); + BIO_dump_fp(stderr, (char *)p, len); + fprintf(stderr, "Client Random:\n"); + BIO_dump_fp(stderr, (char *)s->s3->client_random, SSL3_RANDOM_SIZE); + fprintf(stderr, "Server Random:\n"); + BIO_dump_fp(stderr, (char *)s->s3->server_random, SSL3_RANDOM_SIZE); + fprintf(stderr, "Master Secret:\n"); + BIO_dump_fp(stderr, (char *)s->session->master_key, + SSL3_MASTER_SECRET_SIZE); +#endif + + *secret_size = SSL3_MASTER_SECRET_SIZE; + return 1; +} + +int tls1_export_keying_material(SSL *s, unsigned char *out, size_t olen, + const char *label, size_t llen, + const unsigned char *context, + size_t contextlen, int use_context) +{ + unsigned char *val = NULL; + size_t vallen = 0, currentvalpos; + int rv; + + /* + * construct PRF arguments we construct the PRF argument ourself rather + * than passing separate values into the TLS PRF to ensure that the + * concatenation of values does not create a prohibited label. + */ + vallen = llen + SSL3_RANDOM_SIZE * 2; + if (use_context) { + vallen += 2 + contextlen; + } + + val = OPENSSL_malloc(vallen); + if (val == NULL) + goto err2; + currentvalpos = 0; + memcpy(val + currentvalpos, (unsigned char *)label, llen); + currentvalpos += llen; + memcpy(val + currentvalpos, s->s3->client_random, SSL3_RANDOM_SIZE); + currentvalpos += SSL3_RANDOM_SIZE; + memcpy(val + currentvalpos, s->s3->server_random, SSL3_RANDOM_SIZE); + currentvalpos += SSL3_RANDOM_SIZE; + + if (use_context) { + val[currentvalpos] = (contextlen >> 8) & 0xff; + currentvalpos++; + val[currentvalpos] = contextlen & 0xff; + currentvalpos++; + if ((contextlen > 0) || (context != NULL)) { + memcpy(val + currentvalpos, context, contextlen); + } + } + + /* + * disallow prohibited labels note that SSL3_RANDOM_SIZE > max(prohibited + * label len) = 15, so size of val > max(prohibited label len) = 15 and + * the comparisons won't have buffer overflow + */ + if (memcmp(val, TLS_MD_CLIENT_FINISH_CONST, + TLS_MD_CLIENT_FINISH_CONST_SIZE) == 0) + goto err1; + if (memcmp(val, TLS_MD_SERVER_FINISH_CONST, + TLS_MD_SERVER_FINISH_CONST_SIZE) == 0) + goto err1; + if (memcmp(val, TLS_MD_MASTER_SECRET_CONST, + TLS_MD_MASTER_SECRET_CONST_SIZE) == 0) + goto err1; + if (memcmp(val, TLS_MD_EXTENDED_MASTER_SECRET_CONST, + TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE) == 0) + goto err1; + if (memcmp(val, TLS_MD_KEY_EXPANSION_CONST, + TLS_MD_KEY_EXPANSION_CONST_SIZE) == 0) + goto err1; + + rv = tls1_PRF(s, + val, vallen, + NULL, 0, + NULL, 0, + NULL, 0, + NULL, 0, + s->session->master_key, s->session->master_key_length, + out, olen, 0); + + goto ret; + err1: + SSLerr(SSL_F_TLS1_EXPORT_KEYING_MATERIAL, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL); + rv = 0; + goto ret; + err2: + SSLerr(SSL_F_TLS1_EXPORT_KEYING_MATERIAL, ERR_R_MALLOC_FAILURE); + rv = 0; + ret: + OPENSSL_clear_free(val, vallen); + return rv; +} + +int tls1_alert_code(int code) +{ + switch (code) { + case SSL_AD_CLOSE_NOTIFY: + return SSL3_AD_CLOSE_NOTIFY; + case SSL_AD_UNEXPECTED_MESSAGE: + return SSL3_AD_UNEXPECTED_MESSAGE; + case SSL_AD_BAD_RECORD_MAC: + return SSL3_AD_BAD_RECORD_MAC; + case SSL_AD_DECRYPTION_FAILED: + return TLS1_AD_DECRYPTION_FAILED; + case SSL_AD_RECORD_OVERFLOW: + return TLS1_AD_RECORD_OVERFLOW; + case SSL_AD_DECOMPRESSION_FAILURE: + return SSL3_AD_DECOMPRESSION_FAILURE; + case SSL_AD_HANDSHAKE_FAILURE: + return SSL3_AD_HANDSHAKE_FAILURE; + case SSL_AD_NO_CERTIFICATE: + return -1; + case SSL_AD_BAD_CERTIFICATE: + return SSL3_AD_BAD_CERTIFICATE; + case SSL_AD_UNSUPPORTED_CERTIFICATE: + return SSL3_AD_UNSUPPORTED_CERTIFICATE; + case SSL_AD_CERTIFICATE_REVOKED: + return SSL3_AD_CERTIFICATE_REVOKED; + case SSL_AD_CERTIFICATE_EXPIRED: + return SSL3_AD_CERTIFICATE_EXPIRED; + case SSL_AD_CERTIFICATE_UNKNOWN: + return SSL3_AD_CERTIFICATE_UNKNOWN; + case SSL_AD_ILLEGAL_PARAMETER: + return SSL3_AD_ILLEGAL_PARAMETER; + case SSL_AD_UNKNOWN_CA: + return TLS1_AD_UNKNOWN_CA; + case SSL_AD_ACCESS_DENIED: + return TLS1_AD_ACCESS_DENIED; + case SSL_AD_DECODE_ERROR: + return TLS1_AD_DECODE_ERROR; + case SSL_AD_DECRYPT_ERROR: + return TLS1_AD_DECRYPT_ERROR; + case SSL_AD_EXPORT_RESTRICTION: + return TLS1_AD_EXPORT_RESTRICTION; + case SSL_AD_PROTOCOL_VERSION: + return TLS1_AD_PROTOCOL_VERSION; + case SSL_AD_INSUFFICIENT_SECURITY: + return TLS1_AD_INSUFFICIENT_SECURITY; + case SSL_AD_INTERNAL_ERROR: + return TLS1_AD_INTERNAL_ERROR; + case SSL_AD_USER_CANCELLED: + return TLS1_AD_USER_CANCELLED; + case SSL_AD_NO_RENEGOTIATION: + return TLS1_AD_NO_RENEGOTIATION; + case SSL_AD_UNSUPPORTED_EXTENSION: + return TLS1_AD_UNSUPPORTED_EXTENSION; + case SSL_AD_CERTIFICATE_UNOBTAINABLE: + return TLS1_AD_CERTIFICATE_UNOBTAINABLE; + case SSL_AD_UNRECOGNIZED_NAME: + return TLS1_AD_UNRECOGNIZED_NAME; + case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE: + return TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE; + case SSL_AD_BAD_CERTIFICATE_HASH_VALUE: + return TLS1_AD_BAD_CERTIFICATE_HASH_VALUE; + case SSL_AD_UNKNOWN_PSK_IDENTITY: + return TLS1_AD_UNKNOWN_PSK_IDENTITY; + case SSL_AD_INAPPROPRIATE_FALLBACK: + return TLS1_AD_INAPPROPRIATE_FALLBACK; + case SSL_AD_NO_APPLICATION_PROTOCOL: + return TLS1_AD_NO_APPLICATION_PROTOCOL; + case SSL_AD_CERTIFICATE_REQUIRED: + return SSL_AD_HANDSHAKE_FAILURE; + default: + return -1; + } +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/t1_lib.c b/trunk/3rdparty/openssl-1.1-fit/ssl/t1_lib.c new file mode 100644 index 000000000..68cb237ea --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/t1_lib.c @@ -0,0 +1,2792 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "internal/nelem.h" +#include "ssl_locl.h" +#include + +SSL3_ENC_METHOD const TLSv1_enc_data = { + tls1_enc, + tls1_mac, + tls1_setup_key_block, + tls1_generate_master_secret, + tls1_change_cipher_state, + tls1_final_finish_mac, + TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE, + TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE, + tls1_alert_code, + tls1_export_keying_material, + 0, + ssl3_set_handshake_header, + tls_close_construct_packet, + ssl3_handshake_write +}; + +SSL3_ENC_METHOD const TLSv1_1_enc_data = { + tls1_enc, + tls1_mac, + tls1_setup_key_block, + tls1_generate_master_secret, + tls1_change_cipher_state, + tls1_final_finish_mac, + TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE, + TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE, + tls1_alert_code, + tls1_export_keying_material, + SSL_ENC_FLAG_EXPLICIT_IV, + ssl3_set_handshake_header, + tls_close_construct_packet, + ssl3_handshake_write +}; + +SSL3_ENC_METHOD const TLSv1_2_enc_data = { + tls1_enc, + tls1_mac, + tls1_setup_key_block, + tls1_generate_master_secret, + tls1_change_cipher_state, + tls1_final_finish_mac, + TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE, + TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE, + tls1_alert_code, + tls1_export_keying_material, + SSL_ENC_FLAG_EXPLICIT_IV | SSL_ENC_FLAG_SIGALGS | SSL_ENC_FLAG_SHA256_PRF + | SSL_ENC_FLAG_TLS1_2_CIPHERS, + ssl3_set_handshake_header, + tls_close_construct_packet, + ssl3_handshake_write +}; + +SSL3_ENC_METHOD const TLSv1_3_enc_data = { + tls13_enc, + tls1_mac, + tls13_setup_key_block, + tls13_generate_master_secret, + tls13_change_cipher_state, + tls13_final_finish_mac, + TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE, + TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE, + tls13_alert_code, + tls13_export_keying_material, + SSL_ENC_FLAG_SIGALGS | SSL_ENC_FLAG_SHA256_PRF, + ssl3_set_handshake_header, + tls_close_construct_packet, + ssl3_handshake_write +}; + +long tls1_default_timeout(void) +{ + /* + * 2 hours, the 24 hours mentioned in the TLSv1 spec is way too long for + * http, the cache would over fill + */ + return (60 * 60 * 2); +} + +int tls1_new(SSL *s) +{ + if (!ssl3_new(s)) + return 0; + if (!s->method->ssl_clear(s)) + return 0; + + return 1; +} + +void tls1_free(SSL *s) +{ + OPENSSL_free(s->ext.session_ticket); + ssl3_free(s); +} + +int tls1_clear(SSL *s) +{ + if (!ssl3_clear(s)) + return 0; + + if (s->method->version == TLS_ANY_VERSION) + s->version = TLS_MAX_VERSION; + else + s->version = s->method->version; + + return 1; +} + +#ifndef OPENSSL_NO_EC + +/* + * Table of curve information. + * Do not delete entries or reorder this array! It is used as a lookup + * table: the index of each entry is one less than the TLS curve id. + */ +static const TLS_GROUP_INFO nid_list[] = { + {NID_sect163k1, 80, TLS_CURVE_CHAR2}, /* sect163k1 (1) */ + {NID_sect163r1, 80, TLS_CURVE_CHAR2}, /* sect163r1 (2) */ + {NID_sect163r2, 80, TLS_CURVE_CHAR2}, /* sect163r2 (3) */ + {NID_sect193r1, 80, TLS_CURVE_CHAR2}, /* sect193r1 (4) */ + {NID_sect193r2, 80, TLS_CURVE_CHAR2}, /* sect193r2 (5) */ + {NID_sect233k1, 112, TLS_CURVE_CHAR2}, /* sect233k1 (6) */ + {NID_sect233r1, 112, TLS_CURVE_CHAR2}, /* sect233r1 (7) */ + {NID_sect239k1, 112, TLS_CURVE_CHAR2}, /* sect239k1 (8) */ + {NID_sect283k1, 128, TLS_CURVE_CHAR2}, /* sect283k1 (9) */ + {NID_sect283r1, 128, TLS_CURVE_CHAR2}, /* sect283r1 (10) */ + {NID_sect409k1, 192, TLS_CURVE_CHAR2}, /* sect409k1 (11) */ + {NID_sect409r1, 192, TLS_CURVE_CHAR2}, /* sect409r1 (12) */ + {NID_sect571k1, 256, TLS_CURVE_CHAR2}, /* sect571k1 (13) */ + {NID_sect571r1, 256, TLS_CURVE_CHAR2}, /* sect571r1 (14) */ + {NID_secp160k1, 80, TLS_CURVE_PRIME}, /* secp160k1 (15) */ + {NID_secp160r1, 80, TLS_CURVE_PRIME}, /* secp160r1 (16) */ + {NID_secp160r2, 80, TLS_CURVE_PRIME}, /* secp160r2 (17) */ + {NID_secp192k1, 80, TLS_CURVE_PRIME}, /* secp192k1 (18) */ + {NID_X9_62_prime192v1, 80, TLS_CURVE_PRIME}, /* secp192r1 (19) */ + {NID_secp224k1, 112, TLS_CURVE_PRIME}, /* secp224k1 (20) */ + {NID_secp224r1, 112, TLS_CURVE_PRIME}, /* secp224r1 (21) */ + {NID_secp256k1, 128, TLS_CURVE_PRIME}, /* secp256k1 (22) */ + {NID_X9_62_prime256v1, 128, TLS_CURVE_PRIME}, /* secp256r1 (23) */ + {NID_secp384r1, 192, TLS_CURVE_PRIME}, /* secp384r1 (24) */ + {NID_secp521r1, 256, TLS_CURVE_PRIME}, /* secp521r1 (25) */ + {NID_brainpoolP256r1, 128, TLS_CURVE_PRIME}, /* brainpoolP256r1 (26) */ + {NID_brainpoolP384r1, 192, TLS_CURVE_PRIME}, /* brainpoolP384r1 (27) */ + {NID_brainpoolP512r1, 256, TLS_CURVE_PRIME}, /* brainpool512r1 (28) */ + {EVP_PKEY_X25519, 128, TLS_CURVE_CUSTOM}, /* X25519 (29) */ + {EVP_PKEY_X448, 224, TLS_CURVE_CUSTOM}, /* X448 (30) */ +}; + +static const unsigned char ecformats_default[] = { + TLSEXT_ECPOINTFORMAT_uncompressed, + TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime, + TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2 +}; + +/* The default curves */ +static const uint16_t eccurves_default[] = { + 29, /* X25519 (29) */ + 23, /* secp256r1 (23) */ + 30, /* X448 (30) */ + 25, /* secp521r1 (25) */ + 24, /* secp384r1 (24) */ +}; + +static const uint16_t suiteb_curves[] = { + TLSEXT_curve_P_256, + TLSEXT_curve_P_384 +}; + +const TLS_GROUP_INFO *tls1_group_id_lookup(uint16_t group_id) +{ + /* ECC curves from RFC 4492 and RFC 7027 */ + if (group_id < 1 || group_id > OSSL_NELEM(nid_list)) + return NULL; + return &nid_list[group_id - 1]; +} + +static uint16_t tls1_nid2group_id(int nid) +{ + size_t i; + for (i = 0; i < OSSL_NELEM(nid_list); i++) { + if (nid_list[i].nid == nid) + return (uint16_t)(i + 1); + } + return 0; +} + +/* + * Set *pgroups to the supported groups list and *pgroupslen to + * the number of groups supported. + */ +void tls1_get_supported_groups(SSL *s, const uint16_t **pgroups, + size_t *pgroupslen) +{ + + /* For Suite B mode only include P-256, P-384 */ + switch (tls1_suiteb(s)) { + case SSL_CERT_FLAG_SUITEB_128_LOS: + *pgroups = suiteb_curves; + *pgroupslen = OSSL_NELEM(suiteb_curves); + break; + + case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY: + *pgroups = suiteb_curves; + *pgroupslen = 1; + break; + + case SSL_CERT_FLAG_SUITEB_192_LOS: + *pgroups = suiteb_curves + 1; + *pgroupslen = 1; + break; + + default: + if (s->ext.supportedgroups == NULL) { + *pgroups = eccurves_default; + *pgroupslen = OSSL_NELEM(eccurves_default); + } else { + *pgroups = s->ext.supportedgroups; + *pgroupslen = s->ext.supportedgroups_len; + } + break; + } +} + +/* See if curve is allowed by security callback */ +int tls_curve_allowed(SSL *s, uint16_t curve, int op) +{ + const TLS_GROUP_INFO *cinfo = tls1_group_id_lookup(curve); + unsigned char ctmp[2]; + + if (cinfo == NULL) + return 0; +# ifdef OPENSSL_NO_EC2M + if (cinfo->flags & TLS_CURVE_CHAR2) + return 0; +# endif + ctmp[0] = curve >> 8; + ctmp[1] = curve & 0xff; + return ssl_security(s, op, cinfo->secbits, cinfo->nid, (void *)ctmp); +} + +/* Return 1 if "id" is in "list" */ +static int tls1_in_list(uint16_t id, const uint16_t *list, size_t listlen) +{ + size_t i; + for (i = 0; i < listlen; i++) + if (list[i] == id) + return 1; + return 0; +} + +/*- + * For nmatch >= 0, return the id of the |nmatch|th shared group or 0 + * if there is no match. + * For nmatch == -1, return number of matches + * For nmatch == -2, return the id of the group to use for + * a tmp key, or 0 if there is no match. + */ +uint16_t tls1_shared_group(SSL *s, int nmatch) +{ + const uint16_t *pref, *supp; + size_t num_pref, num_supp, i; + int k; + + /* Can't do anything on client side */ + if (s->server == 0) + return 0; + if (nmatch == -2) { + if (tls1_suiteb(s)) { + /* + * For Suite B ciphersuite determines curve: we already know + * these are acceptable due to previous checks. + */ + unsigned long cid = s->s3->tmp.new_cipher->id; + + if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) + return TLSEXT_curve_P_256; + if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) + return TLSEXT_curve_P_384; + /* Should never happen */ + return 0; + } + /* If not Suite B just return first preference shared curve */ + nmatch = 0; + } + /* + * If server preference set, our groups are the preference order + * otherwise peer decides. + */ + if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) { + tls1_get_supported_groups(s, &pref, &num_pref); + tls1_get_peer_groups(s, &supp, &num_supp); + } else { + tls1_get_peer_groups(s, &pref, &num_pref); + tls1_get_supported_groups(s, &supp, &num_supp); + } + + for (k = 0, i = 0; i < num_pref; i++) { + uint16_t id = pref[i]; + + if (!tls1_in_list(id, supp, num_supp) + || !tls_curve_allowed(s, id, SSL_SECOP_CURVE_SHARED)) + continue; + if (nmatch == k) + return id; + k++; + } + if (nmatch == -1) + return k; + /* Out of range (nmatch > k). */ + return 0; +} + +int tls1_set_groups(uint16_t **pext, size_t *pextlen, + int *groups, size_t ngroups) +{ + uint16_t *glist; + size_t i; + /* + * Bitmap of groups included to detect duplicates: only works while group + * ids < 32 + */ + unsigned long dup_list = 0; + + if (ngroups == 0) { + SSLerr(SSL_F_TLS1_SET_GROUPS, SSL_R_BAD_LENGTH); + return 0; + } + if ((glist = OPENSSL_malloc(ngroups * sizeof(*glist))) == NULL) { + SSLerr(SSL_F_TLS1_SET_GROUPS, ERR_R_MALLOC_FAILURE); + return 0; + } + for (i = 0; i < ngroups; i++) { + unsigned long idmask; + uint16_t id; + /* TODO(TLS1.3): Convert for DH groups */ + id = tls1_nid2group_id(groups[i]); + idmask = 1L << id; + if (!id || (dup_list & idmask)) { + OPENSSL_free(glist); + return 0; + } + dup_list |= idmask; + glist[i] = id; + } + OPENSSL_free(*pext); + *pext = glist; + *pextlen = ngroups; + return 1; +} + +# define MAX_CURVELIST OSSL_NELEM(nid_list) + +typedef struct { + size_t nidcnt; + int nid_arr[MAX_CURVELIST]; +} nid_cb_st; + +static int nid_cb(const char *elem, int len, void *arg) +{ + nid_cb_st *narg = arg; + size_t i; + int nid; + char etmp[20]; + if (elem == NULL) + return 0; + if (narg->nidcnt == MAX_CURVELIST) + return 0; + if (len > (int)(sizeof(etmp) - 1)) + return 0; + memcpy(etmp, elem, len); + etmp[len] = 0; + nid = EC_curve_nist2nid(etmp); + if (nid == NID_undef) + nid = OBJ_sn2nid(etmp); + if (nid == NID_undef) + nid = OBJ_ln2nid(etmp); + if (nid == NID_undef) + return 0; + for (i = 0; i < narg->nidcnt; i++) + if (narg->nid_arr[i] == nid) + return 0; + narg->nid_arr[narg->nidcnt++] = nid; + return 1; +} + +/* Set groups based on a colon separate list */ +int tls1_set_groups_list(uint16_t **pext, size_t *pextlen, const char *str) +{ + nid_cb_st ncb; + ncb.nidcnt = 0; + if (!CONF_parse_list(str, ':', 1, nid_cb, &ncb)) + return 0; + if (pext == NULL) + return 1; + return tls1_set_groups(pext, pextlen, ncb.nid_arr, ncb.nidcnt); +} +/* Return group id of a key */ +static uint16_t tls1_get_group_id(EVP_PKEY *pkey) +{ + EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey); + const EC_GROUP *grp; + + if (ec == NULL) + return 0; + grp = EC_KEY_get0_group(ec); + return tls1_nid2group_id(EC_GROUP_get_curve_name(grp)); +} + +/* Check a key is compatible with compression extension */ +static int tls1_check_pkey_comp(SSL *s, EVP_PKEY *pkey) +{ + const EC_KEY *ec; + const EC_GROUP *grp; + unsigned char comp_id; + size_t i; + + /* If not an EC key nothing to check */ + if (EVP_PKEY_id(pkey) != EVP_PKEY_EC) + return 1; + ec = EVP_PKEY_get0_EC_KEY(pkey); + grp = EC_KEY_get0_group(ec); + + /* Get required compression id */ + if (EC_KEY_get_conv_form(ec) == POINT_CONVERSION_UNCOMPRESSED) { + comp_id = TLSEXT_ECPOINTFORMAT_uncompressed; + } else if (SSL_IS_TLS13(s)) { + /* + * ec_point_formats extension is not used in TLSv1.3 so we ignore + * this check. + */ + return 1; + } else { + int field_type = EC_METHOD_get_field_type(EC_GROUP_method_of(grp)); + + if (field_type == NID_X9_62_prime_field) + comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime; + else if (field_type == NID_X9_62_characteristic_two_field) + comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2; + else + return 0; + } + /* + * If point formats extension present check it, otherwise everything is + * supported (see RFC4492). + */ + if (s->session->ext.ecpointformats == NULL) + return 1; + + for (i = 0; i < s->session->ext.ecpointformats_len; i++) { + if (s->session->ext.ecpointformats[i] == comp_id) + return 1; + } + return 0; +} + +/* Check a group id matches preferences */ +int tls1_check_group_id(SSL *s, uint16_t group_id, int check_own_groups) + { + const uint16_t *groups; + size_t groups_len; + + if (group_id == 0) + return 0; + + /* Check for Suite B compliance */ + if (tls1_suiteb(s) && s->s3->tmp.new_cipher != NULL) { + unsigned long cid = s->s3->tmp.new_cipher->id; + + if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) { + if (group_id != TLSEXT_curve_P_256) + return 0; + } else if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) { + if (group_id != TLSEXT_curve_P_384) + return 0; + } else { + /* Should never happen */ + return 0; + } + } + + if (check_own_groups) { + /* Check group is one of our preferences */ + tls1_get_supported_groups(s, &groups, &groups_len); + if (!tls1_in_list(group_id, groups, groups_len)) + return 0; + } + + if (!tls_curve_allowed(s, group_id, SSL_SECOP_CURVE_CHECK)) + return 0; + + /* For clients, nothing more to check */ + if (!s->server) + return 1; + + /* Check group is one of peers preferences */ + tls1_get_peer_groups(s, &groups, &groups_len); + + /* + * RFC 4492 does not require the supported elliptic curves extension + * so if it is not sent we can just choose any curve. + * It is invalid to send an empty list in the supported groups + * extension, so groups_len == 0 always means no extension. + */ + if (groups_len == 0) + return 1; + return tls1_in_list(group_id, groups, groups_len); +} + +void tls1_get_formatlist(SSL *s, const unsigned char **pformats, + size_t *num_formats) +{ + /* + * If we have a custom point format list use it otherwise use default + */ + if (s->ext.ecpointformats) { + *pformats = s->ext.ecpointformats; + *num_formats = s->ext.ecpointformats_len; + } else { + *pformats = ecformats_default; + /* For Suite B we don't support char2 fields */ + if (tls1_suiteb(s)) + *num_formats = sizeof(ecformats_default) - 1; + else + *num_formats = sizeof(ecformats_default); + } +} + +/* + * Check cert parameters compatible with extensions: currently just checks EC + * certificates have compatible curves and compression. + */ +static int tls1_check_cert_param(SSL *s, X509 *x, int check_ee_md) +{ + uint16_t group_id; + EVP_PKEY *pkey; + pkey = X509_get0_pubkey(x); + if (pkey == NULL) + return 0; + /* If not EC nothing to do */ + if (EVP_PKEY_id(pkey) != EVP_PKEY_EC) + return 1; + /* Check compression */ + if (!tls1_check_pkey_comp(s, pkey)) + return 0; + group_id = tls1_get_group_id(pkey); + /* + * For a server we allow the certificate to not be in our list of supported + * groups. + */ + if (!tls1_check_group_id(s, group_id, !s->server)) + return 0; + /* + * Special case for suite B. We *MUST* sign using SHA256+P-256 or + * SHA384+P-384. + */ + if (check_ee_md && tls1_suiteb(s)) { + int check_md; + size_t i; + CERT *c = s->cert; + + /* Check to see we have necessary signing algorithm */ + if (group_id == TLSEXT_curve_P_256) + check_md = NID_ecdsa_with_SHA256; + else if (group_id == TLSEXT_curve_P_384) + check_md = NID_ecdsa_with_SHA384; + else + return 0; /* Should never happen */ + for (i = 0; i < c->shared_sigalgslen; i++) { + if (check_md == c->shared_sigalgs[i]->sigandhash) + return 1;; + } + return 0; + } + return 1; +} + +/* + * tls1_check_ec_tmp_key - Check EC temporary key compatibility + * @s: SSL connection + * @cid: Cipher ID we're considering using + * + * Checks that the kECDHE cipher suite we're considering using + * is compatible with the client extensions. + * + * Returns 0 when the cipher can't be used or 1 when it can. + */ +int tls1_check_ec_tmp_key(SSL *s, unsigned long cid) +{ + /* If not Suite B just need a shared group */ + if (!tls1_suiteb(s)) + return tls1_shared_group(s, 0) != 0; + /* + * If Suite B, AES128 MUST use P-256 and AES256 MUST use P-384, no other + * curves permitted. + */ + if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) + return tls1_check_group_id(s, TLSEXT_curve_P_256, 1); + if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) + return tls1_check_group_id(s, TLSEXT_curve_P_384, 1); + + return 0; +} + +#else + +static int tls1_check_cert_param(SSL *s, X509 *x, int set_ee_md) +{ + return 1; +} + +#endif /* OPENSSL_NO_EC */ + +/* Default sigalg schemes */ +static const uint16_t tls12_sigalgs[] = { +#ifndef OPENSSL_NO_EC + TLSEXT_SIGALG_ecdsa_secp256r1_sha256, + TLSEXT_SIGALG_ecdsa_secp384r1_sha384, + TLSEXT_SIGALG_ecdsa_secp521r1_sha512, + TLSEXT_SIGALG_ed25519, + TLSEXT_SIGALG_ed448, +#endif + + TLSEXT_SIGALG_rsa_pss_pss_sha256, + TLSEXT_SIGALG_rsa_pss_pss_sha384, + TLSEXT_SIGALG_rsa_pss_pss_sha512, + TLSEXT_SIGALG_rsa_pss_rsae_sha256, + TLSEXT_SIGALG_rsa_pss_rsae_sha384, + TLSEXT_SIGALG_rsa_pss_rsae_sha512, + + TLSEXT_SIGALG_rsa_pkcs1_sha256, + TLSEXT_SIGALG_rsa_pkcs1_sha384, + TLSEXT_SIGALG_rsa_pkcs1_sha512, + +#ifndef OPENSSL_NO_EC + TLSEXT_SIGALG_ecdsa_sha224, + TLSEXT_SIGALG_ecdsa_sha1, +#endif + TLSEXT_SIGALG_rsa_pkcs1_sha224, + TLSEXT_SIGALG_rsa_pkcs1_sha1, +#ifndef OPENSSL_NO_DSA + TLSEXT_SIGALG_dsa_sha224, + TLSEXT_SIGALG_dsa_sha1, + + TLSEXT_SIGALG_dsa_sha256, + TLSEXT_SIGALG_dsa_sha384, + TLSEXT_SIGALG_dsa_sha512, +#endif +#ifndef OPENSSL_NO_GOST + TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256, + TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512, + TLSEXT_SIGALG_gostr34102001_gostr3411, +#endif +}; + +#ifndef OPENSSL_NO_EC +static const uint16_t suiteb_sigalgs[] = { + TLSEXT_SIGALG_ecdsa_secp256r1_sha256, + TLSEXT_SIGALG_ecdsa_secp384r1_sha384 +}; +#endif + +static const SIGALG_LOOKUP sigalg_lookup_tbl[] = { +#ifndef OPENSSL_NO_EC + {"ecdsa_secp256r1_sha256", TLSEXT_SIGALG_ecdsa_secp256r1_sha256, + NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_EC, SSL_PKEY_ECC, + NID_ecdsa_with_SHA256, NID_X9_62_prime256v1}, + {"ecdsa_secp384r1_sha384", TLSEXT_SIGALG_ecdsa_secp384r1_sha384, + NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_EC, SSL_PKEY_ECC, + NID_ecdsa_with_SHA384, NID_secp384r1}, + {"ecdsa_secp521r1_sha512", TLSEXT_SIGALG_ecdsa_secp521r1_sha512, + NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_EC, SSL_PKEY_ECC, + NID_ecdsa_with_SHA512, NID_secp521r1}, + {"ed25519", TLSEXT_SIGALG_ed25519, + NID_undef, -1, EVP_PKEY_ED25519, SSL_PKEY_ED25519, + NID_undef, NID_undef}, + {"ed448", TLSEXT_SIGALG_ed448, + NID_undef, -1, EVP_PKEY_ED448, SSL_PKEY_ED448, + NID_undef, NID_undef}, + {NULL, TLSEXT_SIGALG_ecdsa_sha224, + NID_sha224, SSL_MD_SHA224_IDX, EVP_PKEY_EC, SSL_PKEY_ECC, + NID_ecdsa_with_SHA224, NID_undef}, + {NULL, TLSEXT_SIGALG_ecdsa_sha1, + NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_EC, SSL_PKEY_ECC, + NID_ecdsa_with_SHA1, NID_undef}, +#endif + {"rsa_pss_rsae_sha256", TLSEXT_SIGALG_rsa_pss_rsae_sha256, + NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA, + NID_undef, NID_undef}, + {"rsa_pss_rsae_sha384", TLSEXT_SIGALG_rsa_pss_rsae_sha384, + NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA, + NID_undef, NID_undef}, + {"rsa_pss_rsae_sha512", TLSEXT_SIGALG_rsa_pss_rsae_sha512, + NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA, + NID_undef, NID_undef}, + {"rsa_pss_pss_sha256", TLSEXT_SIGALG_rsa_pss_pss_sha256, + NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA_PSS_SIGN, + NID_undef, NID_undef}, + {"rsa_pss_pss_sha384", TLSEXT_SIGALG_rsa_pss_pss_sha384, + NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA_PSS_SIGN, + NID_undef, NID_undef}, + {"rsa_pss_pss_sha512", TLSEXT_SIGALG_rsa_pss_pss_sha512, + NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA_PSS_SIGN, + NID_undef, NID_undef}, + {"rsa_pkcs1_sha256", TLSEXT_SIGALG_rsa_pkcs1_sha256, + NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA, + NID_sha256WithRSAEncryption, NID_undef}, + {"rsa_pkcs1_sha384", TLSEXT_SIGALG_rsa_pkcs1_sha384, + NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA, + NID_sha384WithRSAEncryption, NID_undef}, + {"rsa_pkcs1_sha512", TLSEXT_SIGALG_rsa_pkcs1_sha512, + NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA, + NID_sha512WithRSAEncryption, NID_undef}, + {"rsa_pkcs1_sha224", TLSEXT_SIGALG_rsa_pkcs1_sha224, + NID_sha224, SSL_MD_SHA224_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA, + NID_sha224WithRSAEncryption, NID_undef}, + {"rsa_pkcs1_sha1", TLSEXT_SIGALG_rsa_pkcs1_sha1, + NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA, + NID_sha1WithRSAEncryption, NID_undef}, +#ifndef OPENSSL_NO_DSA + {NULL, TLSEXT_SIGALG_dsa_sha256, + NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN, + NID_dsa_with_SHA256, NID_undef}, + {NULL, TLSEXT_SIGALG_dsa_sha384, + NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN, + NID_undef, NID_undef}, + {NULL, TLSEXT_SIGALG_dsa_sha512, + NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN, + NID_undef, NID_undef}, + {NULL, TLSEXT_SIGALG_dsa_sha224, + NID_sha224, SSL_MD_SHA224_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN, + NID_undef, NID_undef}, + {NULL, TLSEXT_SIGALG_dsa_sha1, + NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN, + NID_dsaWithSHA1, NID_undef}, +#endif +#ifndef OPENSSL_NO_GOST + {NULL, TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256, + NID_id_GostR3411_2012_256, SSL_MD_GOST12_256_IDX, + NID_id_GostR3410_2012_256, SSL_PKEY_GOST12_256, + NID_undef, NID_undef}, + {NULL, TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512, + NID_id_GostR3411_2012_512, SSL_MD_GOST12_512_IDX, + NID_id_GostR3410_2012_512, SSL_PKEY_GOST12_512, + NID_undef, NID_undef}, + {NULL, TLSEXT_SIGALG_gostr34102001_gostr3411, + NID_id_GostR3411_94, SSL_MD_GOST94_IDX, + NID_id_GostR3410_2001, SSL_PKEY_GOST01, + NID_undef, NID_undef} +#endif +}; +/* Legacy sigalgs for TLS < 1.2 RSA TLS signatures */ +static const SIGALG_LOOKUP legacy_rsa_sigalg = { + "rsa_pkcs1_md5_sha1", 0, + NID_md5_sha1, SSL_MD_MD5_SHA1_IDX, + EVP_PKEY_RSA, SSL_PKEY_RSA, + NID_undef, NID_undef +}; + +/* + * Default signature algorithm values used if signature algorithms not present. + * From RFC5246. Note: order must match certificate index order. + */ +static const uint16_t tls_default_sigalg[] = { + TLSEXT_SIGALG_rsa_pkcs1_sha1, /* SSL_PKEY_RSA */ + 0, /* SSL_PKEY_RSA_PSS_SIGN */ + TLSEXT_SIGALG_dsa_sha1, /* SSL_PKEY_DSA_SIGN */ + TLSEXT_SIGALG_ecdsa_sha1, /* SSL_PKEY_ECC */ + TLSEXT_SIGALG_gostr34102001_gostr3411, /* SSL_PKEY_GOST01 */ + TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256, /* SSL_PKEY_GOST12_256 */ + TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512, /* SSL_PKEY_GOST12_512 */ + 0, /* SSL_PKEY_ED25519 */ + 0, /* SSL_PKEY_ED448 */ +}; + +/* Lookup TLS signature algorithm */ +static const SIGALG_LOOKUP *tls1_lookup_sigalg(uint16_t sigalg) +{ + size_t i; + const SIGALG_LOOKUP *s; + + for (i = 0, s = sigalg_lookup_tbl; i < OSSL_NELEM(sigalg_lookup_tbl); + i++, s++) { + if (s->sigalg == sigalg) + return s; + } + return NULL; +} +/* Lookup hash: return 0 if invalid or not enabled */ +int tls1_lookup_md(const SIGALG_LOOKUP *lu, const EVP_MD **pmd) +{ + const EVP_MD *md; + if (lu == NULL) + return 0; + /* lu->hash == NID_undef means no associated digest */ + if (lu->hash == NID_undef) { + md = NULL; + } else { + md = ssl_md(lu->hash_idx); + if (md == NULL) + return 0; + } + if (pmd) + *pmd = md; + return 1; +} + +/* + * Check if key is large enough to generate RSA-PSS signature. + * + * The key must greater than or equal to 2 * hash length + 2. + * SHA512 has a hash length of 64 bytes, which is incompatible + * with a 128 byte (1024 bit) key. + */ +#define RSA_PSS_MINIMUM_KEY_SIZE(md) (2 * EVP_MD_size(md) + 2) +static int rsa_pss_check_min_key_size(const RSA *rsa, const SIGALG_LOOKUP *lu) +{ + const EVP_MD *md; + + if (rsa == NULL) + return 0; + if (!tls1_lookup_md(lu, &md) || md == NULL) + return 0; + if (RSA_size(rsa) < RSA_PSS_MINIMUM_KEY_SIZE(md)) + return 0; + return 1; +} + +/* + * Return a signature algorithm for TLS < 1.2 where the signature type + * is fixed by the certificate type. + */ +static const SIGALG_LOOKUP *tls1_get_legacy_sigalg(const SSL *s, int idx) +{ + if (idx == -1) { + if (s->server) { + size_t i; + + /* Work out index corresponding to ciphersuite */ + for (i = 0; i < SSL_PKEY_NUM; i++) { + const SSL_CERT_LOOKUP *clu = ssl_cert_lookup_by_idx(i); + + if (clu->amask & s->s3->tmp.new_cipher->algorithm_auth) { + idx = i; + break; + } + } + + /* + * Some GOST ciphersuites allow more than one signature algorithms + * */ + if (idx == SSL_PKEY_GOST01 && s->s3->tmp.new_cipher->algorithm_auth != SSL_aGOST01) { + int real_idx; + + for (real_idx = SSL_PKEY_GOST12_512; real_idx >= SSL_PKEY_GOST01; + real_idx--) { + if (s->cert->pkeys[real_idx].privatekey != NULL) { + idx = real_idx; + break; + } + } + } + } else { + idx = s->cert->key - s->cert->pkeys; + } + } + if (idx < 0 || idx >= (int)OSSL_NELEM(tls_default_sigalg)) + return NULL; + if (SSL_USE_SIGALGS(s) || idx != SSL_PKEY_RSA) { + const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(tls_default_sigalg[idx]); + + if (!tls1_lookup_md(lu, NULL)) + return NULL; + return lu; + } + return &legacy_rsa_sigalg; +} +/* Set peer sigalg based key type */ +int tls1_set_peer_legacy_sigalg(SSL *s, const EVP_PKEY *pkey) +{ + size_t idx; + const SIGALG_LOOKUP *lu; + + if (ssl_cert_lookup_by_pkey(pkey, &idx) == NULL) + return 0; + lu = tls1_get_legacy_sigalg(s, idx); + if (lu == NULL) + return 0; + s->s3->tmp.peer_sigalg = lu; + return 1; +} + +size_t tls12_get_psigalgs(SSL *s, int sent, const uint16_t **psigs) +{ + /* + * If Suite B mode use Suite B sigalgs only, ignore any other + * preferences. + */ +#ifndef OPENSSL_NO_EC + switch (tls1_suiteb(s)) { + case SSL_CERT_FLAG_SUITEB_128_LOS: + *psigs = suiteb_sigalgs; + return OSSL_NELEM(suiteb_sigalgs); + + case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY: + *psigs = suiteb_sigalgs; + return 1; + + case SSL_CERT_FLAG_SUITEB_192_LOS: + *psigs = suiteb_sigalgs + 1; + return 1; + } +#endif + /* + * We use client_sigalgs (if not NULL) if we're a server + * and sending a certificate request or if we're a client and + * determining which shared algorithm to use. + */ + if ((s->server == sent) && s->cert->client_sigalgs != NULL) { + *psigs = s->cert->client_sigalgs; + return s->cert->client_sigalgslen; + } else if (s->cert->conf_sigalgs) { + *psigs = s->cert->conf_sigalgs; + return s->cert->conf_sigalgslen; + } else { + *psigs = tls12_sigalgs; + return OSSL_NELEM(tls12_sigalgs); + } +} + +#ifndef OPENSSL_NO_EC +/* + * Called by servers only. Checks that we have a sig alg that supports the + * specified EC curve. + */ +int tls_check_sigalg_curve(const SSL *s, int curve) +{ + const uint16_t *sigs; + size_t siglen, i; + + if (s->cert->conf_sigalgs) { + sigs = s->cert->conf_sigalgs; + siglen = s->cert->conf_sigalgslen; + } else { + sigs = tls12_sigalgs; + siglen = OSSL_NELEM(tls12_sigalgs); + } + + for (i = 0; i < siglen; i++) { + const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(sigs[i]); + + if (lu == NULL) + continue; + if (lu->sig == EVP_PKEY_EC + && lu->curve != NID_undef + && curve == lu->curve) + return 1; + } + + return 0; +} +#endif + +/* + * Check signature algorithm is consistent with sent supported signature + * algorithms and if so set relevant digest and signature scheme in + * s. + */ +int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey) +{ + const uint16_t *sent_sigs; + const EVP_MD *md = NULL; + char sigalgstr[2]; + size_t sent_sigslen, i, cidx; + int pkeyid = EVP_PKEY_id(pkey); + const SIGALG_LOOKUP *lu; + + /* Should never happen */ + if (pkeyid == -1) + return -1; + if (SSL_IS_TLS13(s)) { + /* Disallow DSA for TLS 1.3 */ + if (pkeyid == EVP_PKEY_DSA) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS12_CHECK_PEER_SIGALG, + SSL_R_WRONG_SIGNATURE_TYPE); + return 0; + } + /* Only allow PSS for TLS 1.3 */ + if (pkeyid == EVP_PKEY_RSA) + pkeyid = EVP_PKEY_RSA_PSS; + } + lu = tls1_lookup_sigalg(sig); + /* + * Check sigalgs is known. Disallow SHA1/SHA224 with TLS 1.3. Check key type + * is consistent with signature: RSA keys can be used for RSA-PSS + */ + if (lu == NULL + || (SSL_IS_TLS13(s) && (lu->hash == NID_sha1 || lu->hash == NID_sha224)) + || (pkeyid != lu->sig + && (lu->sig != EVP_PKEY_RSA_PSS || pkeyid != EVP_PKEY_RSA))) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS12_CHECK_PEER_SIGALG, + SSL_R_WRONG_SIGNATURE_TYPE); + return 0; + } + /* Check the sigalg is consistent with the key OID */ + if (!ssl_cert_lookup_by_nid(EVP_PKEY_id(pkey), &cidx) + || lu->sig_idx != (int)cidx) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS12_CHECK_PEER_SIGALG, + SSL_R_WRONG_SIGNATURE_TYPE); + return 0; + } + +#ifndef OPENSSL_NO_EC + if (pkeyid == EVP_PKEY_EC) { + + /* Check point compression is permitted */ + if (!tls1_check_pkey_comp(s, pkey)) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS12_CHECK_PEER_SIGALG, + SSL_R_ILLEGAL_POINT_COMPRESSION); + return 0; + } + + /* For TLS 1.3 or Suite B check curve matches signature algorithm */ + if (SSL_IS_TLS13(s) || tls1_suiteb(s)) { + EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey); + int curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); + + if (lu->curve != NID_undef && curve != lu->curve) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_CURVE); + return 0; + } + } + if (!SSL_IS_TLS13(s)) { + /* Check curve matches extensions */ + if (!tls1_check_group_id(s, tls1_get_group_id(pkey), 1)) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_CURVE); + return 0; + } + if (tls1_suiteb(s)) { + /* Check sigalg matches a permissible Suite B value */ + if (sig != TLSEXT_SIGALG_ecdsa_secp256r1_sha256 + && sig != TLSEXT_SIGALG_ecdsa_secp384r1_sha384) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS12_CHECK_PEER_SIGALG, + SSL_R_WRONG_SIGNATURE_TYPE); + return 0; + } + } + } + } else if (tls1_suiteb(s)) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS12_CHECK_PEER_SIGALG, + SSL_R_WRONG_SIGNATURE_TYPE); + return 0; + } +#endif + + /* Check signature matches a type we sent */ + sent_sigslen = tls12_get_psigalgs(s, 1, &sent_sigs); + for (i = 0; i < sent_sigslen; i++, sent_sigs++) { + if (sig == *sent_sigs) + break; + } + /* Allow fallback to SHA1 if not strict mode */ + if (i == sent_sigslen && (lu->hash != NID_sha1 + || s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS12_CHECK_PEER_SIGALG, + SSL_R_WRONG_SIGNATURE_TYPE); + return 0; + } + if (!tls1_lookup_md(lu, &md)) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS12_CHECK_PEER_SIGALG, + SSL_R_UNKNOWN_DIGEST); + return 0; + } + if (md != NULL) { + /* + * Make sure security callback allows algorithm. For historical + * reasons we have to pass the sigalg as a two byte char array. + */ + sigalgstr[0] = (sig >> 8) & 0xff; + sigalgstr[1] = sig & 0xff; + if (!ssl_security(s, SSL_SECOP_SIGALG_CHECK, + EVP_MD_size(md) * 4, EVP_MD_type(md), + (void *)sigalgstr)) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS12_CHECK_PEER_SIGALG, + SSL_R_WRONG_SIGNATURE_TYPE); + return 0; + } + } + /* Store the sigalg the peer uses */ + s->s3->tmp.peer_sigalg = lu; + return 1; +} + +int SSL_get_peer_signature_type_nid(const SSL *s, int *pnid) +{ + if (s->s3->tmp.peer_sigalg == NULL) + return 0; + *pnid = s->s3->tmp.peer_sigalg->sig; + return 1; +} + +int SSL_get_signature_type_nid(const SSL *s, int *pnid) +{ + if (s->s3->tmp.sigalg == NULL) + return 0; + *pnid = s->s3->tmp.sigalg->sig; + return 1; +} + +/* + * Set a mask of disabled algorithms: an algorithm is disabled if it isn't + * supported, doesn't appear in supported signature algorithms, isn't supported + * by the enabled protocol versions or by the security level. + * + * This function should only be used for checking which ciphers are supported + * by the client. + * + * Call ssl_cipher_disabled() to check that it's enabled or not. + */ +int ssl_set_client_disabled(SSL *s) +{ + s->s3->tmp.mask_a = 0; + s->s3->tmp.mask_k = 0; + ssl_set_sig_mask(&s->s3->tmp.mask_a, s, SSL_SECOP_SIGALG_MASK); + if (ssl_get_min_max_version(s, &s->s3->tmp.min_ver, + &s->s3->tmp.max_ver, NULL) != 0) + return 0; +#ifndef OPENSSL_NO_PSK + /* with PSK there must be client callback set */ + if (!s->psk_client_callback) { + s->s3->tmp.mask_a |= SSL_aPSK; + s->s3->tmp.mask_k |= SSL_PSK; + } +#endif /* OPENSSL_NO_PSK */ +#ifndef OPENSSL_NO_SRP + if (!(s->srp_ctx.srp_Mask & SSL_kSRP)) { + s->s3->tmp.mask_a |= SSL_aSRP; + s->s3->tmp.mask_k |= SSL_kSRP; + } +#endif + return 1; +} + +/* + * ssl_cipher_disabled - check that a cipher is disabled or not + * @s: SSL connection that you want to use the cipher on + * @c: cipher to check + * @op: Security check that you want to do + * @ecdhe: If set to 1 then TLSv1 ECDHE ciphers are also allowed in SSLv3 + * + * Returns 1 when it's disabled, 0 when enabled. + */ +int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op, int ecdhe) +{ + if (c->algorithm_mkey & s->s3->tmp.mask_k + || c->algorithm_auth & s->s3->tmp.mask_a) + return 1; + if (s->s3->tmp.max_ver == 0) + return 1; + if (!SSL_IS_DTLS(s)) { + int min_tls = c->min_tls; + + /* + * For historical reasons we will allow ECHDE to be selected by a server + * in SSLv3 if we are a client + */ + if (min_tls == TLS1_VERSION && ecdhe + && (c->algorithm_mkey & (SSL_kECDHE | SSL_kECDHEPSK)) != 0) + min_tls = SSL3_VERSION; + + if ((min_tls > s->s3->tmp.max_ver) || (c->max_tls < s->s3->tmp.min_ver)) + return 1; + } + if (SSL_IS_DTLS(s) && (DTLS_VERSION_GT(c->min_dtls, s->s3->tmp.max_ver) + || DTLS_VERSION_LT(c->max_dtls, s->s3->tmp.min_ver))) + return 1; + + return !ssl_security(s, op, c->strength_bits, 0, (void *)c); +} + +int tls_use_ticket(SSL *s) +{ + if ((s->options & SSL_OP_NO_TICKET)) + return 0; + return ssl_security(s, SSL_SECOP_TICKET, 0, 0, NULL); +} + +int tls1_set_server_sigalgs(SSL *s) +{ + size_t i; + + /* Clear any shared signature algorithms */ + OPENSSL_free(s->cert->shared_sigalgs); + s->cert->shared_sigalgs = NULL; + s->cert->shared_sigalgslen = 0; + /* Clear certificate validity flags */ + for (i = 0; i < SSL_PKEY_NUM; i++) + s->s3->tmp.valid_flags[i] = 0; + /* + * If peer sent no signature algorithms check to see if we support + * the default algorithm for each certificate type + */ + if (s->s3->tmp.peer_cert_sigalgs == NULL + && s->s3->tmp.peer_sigalgs == NULL) { + const uint16_t *sent_sigs; + size_t sent_sigslen = tls12_get_psigalgs(s, 1, &sent_sigs); + + for (i = 0; i < SSL_PKEY_NUM; i++) { + const SIGALG_LOOKUP *lu = tls1_get_legacy_sigalg(s, i); + size_t j; + + if (lu == NULL) + continue; + /* Check default matches a type we sent */ + for (j = 0; j < sent_sigslen; j++) { + if (lu->sigalg == sent_sigs[j]) { + s->s3->tmp.valid_flags[i] = CERT_PKEY_SIGN; + break; + } + } + } + return 1; + } + + if (!tls1_process_sigalgs(s)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS1_SET_SERVER_SIGALGS, ERR_R_INTERNAL_ERROR); + return 0; + } + if (s->cert->shared_sigalgs != NULL) + return 1; + + /* Fatal error if no shared signature algorithms */ + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS1_SET_SERVER_SIGALGS, + SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS); + return 0; +} + +/*- + * Gets the ticket information supplied by the client if any. + * + * hello: The parsed ClientHello data + * ret: (output) on return, if a ticket was decrypted, then this is set to + * point to the resulting session. + */ +SSL_TICKET_STATUS tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello, + SSL_SESSION **ret) +{ + size_t size; + RAW_EXTENSION *ticketext; + + *ret = NULL; + s->ext.ticket_expected = 0; + + /* + * If tickets disabled or not supported by the protocol version + * (e.g. TLSv1.3) behave as if no ticket present to permit stateful + * resumption. + */ + if (s->version <= SSL3_VERSION || !tls_use_ticket(s)) + return SSL_TICKET_NONE; + + ticketext = &hello->pre_proc_exts[TLSEXT_IDX_session_ticket]; + if (!ticketext->present) + return SSL_TICKET_NONE; + + size = PACKET_remaining(&ticketext->data); + + return tls_decrypt_ticket(s, PACKET_data(&ticketext->data), size, + hello->session_id, hello->session_id_len, ret); +} + +/*- + * tls_decrypt_ticket attempts to decrypt a session ticket. + * + * If s->tls_session_secret_cb is set and we're not doing TLSv1.3 then we are + * expecting a pre-shared key ciphersuite, in which case we have no use for + * session tickets and one will never be decrypted, nor will + * s->ext.ticket_expected be set to 1. + * + * Side effects: + * Sets s->ext.ticket_expected to 1 if the server will have to issue + * a new session ticket to the client because the client indicated support + * (and s->tls_session_secret_cb is NULL) but the client either doesn't have + * a session ticket or we couldn't use the one it gave us, or if + * s->ctx->ext.ticket_key_cb asked to renew the client's ticket. + * Otherwise, s->ext.ticket_expected is set to 0. + * + * etick: points to the body of the session ticket extension. + * eticklen: the length of the session tickets extension. + * sess_id: points at the session ID. + * sesslen: the length of the session ID. + * psess: (output) on return, if a ticket was decrypted, then this is set to + * point to the resulting session. + */ +SSL_TICKET_STATUS tls_decrypt_ticket(SSL *s, const unsigned char *etick, + size_t eticklen, const unsigned char *sess_id, + size_t sesslen, SSL_SESSION **psess) +{ + SSL_SESSION *sess = NULL; + unsigned char *sdec; + const unsigned char *p; + int slen, renew_ticket = 0, declen; + SSL_TICKET_STATUS ret = SSL_TICKET_FATAL_ERR_OTHER; + size_t mlen; + unsigned char tick_hmac[EVP_MAX_MD_SIZE]; + HMAC_CTX *hctx = NULL; + EVP_CIPHER_CTX *ctx = NULL; + SSL_CTX *tctx = s->session_ctx; + + if (eticklen == 0) { + /* + * The client will accept a ticket but doesn't currently have + * one (TLSv1.2 and below), or treated as a fatal error in TLSv1.3 + */ + ret = SSL_TICKET_EMPTY; + goto end; + } + if (!SSL_IS_TLS13(s) && s->ext.session_secret_cb) { + /* + * Indicate that the ticket couldn't be decrypted rather than + * generating the session from ticket now, trigger + * abbreviated handshake based on external mechanism to + * calculate the master secret later. + */ + ret = SSL_TICKET_NO_DECRYPT; + goto end; + } + + /* Need at least keyname + iv */ + if (eticklen < TLSEXT_KEYNAME_LENGTH + EVP_MAX_IV_LENGTH) { + ret = SSL_TICKET_NO_DECRYPT; + goto end; + } + + /* Initialize session ticket encryption and HMAC contexts */ + hctx = HMAC_CTX_new(); + if (hctx == NULL) { + ret = SSL_TICKET_FATAL_ERR_MALLOC; + goto end; + } + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) { + ret = SSL_TICKET_FATAL_ERR_MALLOC; + goto end; + } + if (tctx->ext.ticket_key_cb) { + unsigned char *nctick = (unsigned char *)etick; + int rv = tctx->ext.ticket_key_cb(s, nctick, + nctick + TLSEXT_KEYNAME_LENGTH, + ctx, hctx, 0); + if (rv < 0) { + ret = SSL_TICKET_FATAL_ERR_OTHER; + goto end; + } + if (rv == 0) { + ret = SSL_TICKET_NO_DECRYPT; + goto end; + } + if (rv == 2) + renew_ticket = 1; + } else { + /* Check key name matches */ + if (memcmp(etick, tctx->ext.tick_key_name, + TLSEXT_KEYNAME_LENGTH) != 0) { + ret = SSL_TICKET_NO_DECRYPT; + goto end; + } + if (HMAC_Init_ex(hctx, tctx->ext.secure->tick_hmac_key, + sizeof(tctx->ext.secure->tick_hmac_key), + EVP_sha256(), NULL) <= 0 + || EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, + tctx->ext.secure->tick_aes_key, + etick + TLSEXT_KEYNAME_LENGTH) <= 0) { + ret = SSL_TICKET_FATAL_ERR_OTHER; + goto end; + } + if (SSL_IS_TLS13(s)) + renew_ticket = 1; + } + /* + * Attempt to process session ticket, first conduct sanity and integrity + * checks on ticket. + */ + mlen = HMAC_size(hctx); + if (mlen == 0) { + ret = SSL_TICKET_FATAL_ERR_OTHER; + goto end; + } + + /* Sanity check ticket length: must exceed keyname + IV + HMAC */ + if (eticklen <= + TLSEXT_KEYNAME_LENGTH + EVP_CIPHER_CTX_iv_length(ctx) + mlen) { + ret = SSL_TICKET_NO_DECRYPT; + goto end; + } + eticklen -= mlen; + /* Check HMAC of encrypted ticket */ + if (HMAC_Update(hctx, etick, eticklen) <= 0 + || HMAC_Final(hctx, tick_hmac, NULL) <= 0) { + ret = SSL_TICKET_FATAL_ERR_OTHER; + goto end; + } + + if (CRYPTO_memcmp(tick_hmac, etick + eticklen, mlen)) { + ret = SSL_TICKET_NO_DECRYPT; + goto end; + } + /* Attempt to decrypt session data */ + /* Move p after IV to start of encrypted ticket, update length */ + p = etick + TLSEXT_KEYNAME_LENGTH + EVP_CIPHER_CTX_iv_length(ctx); + eticklen -= TLSEXT_KEYNAME_LENGTH + EVP_CIPHER_CTX_iv_length(ctx); + sdec = OPENSSL_malloc(eticklen); + if (sdec == NULL || EVP_DecryptUpdate(ctx, sdec, &slen, p, + (int)eticklen) <= 0) { + OPENSSL_free(sdec); + ret = SSL_TICKET_FATAL_ERR_OTHER; + goto end; + } + if (EVP_DecryptFinal(ctx, sdec + slen, &declen) <= 0) { + OPENSSL_free(sdec); + ret = SSL_TICKET_NO_DECRYPT; + goto end; + } + slen += declen; + p = sdec; + + sess = d2i_SSL_SESSION(NULL, &p, slen); + slen -= p - sdec; + OPENSSL_free(sdec); + if (sess) { + /* Some additional consistency checks */ + if (slen != 0) { + SSL_SESSION_free(sess); + sess = NULL; + ret = SSL_TICKET_NO_DECRYPT; + goto end; + } + /* + * The session ID, if non-empty, is used by some clients to detect + * that the ticket has been accepted. So we copy it to the session + * structure. If it is empty set length to zero as required by + * standard. + */ + if (sesslen) { + memcpy(sess->session_id, sess_id, sesslen); + sess->session_id_length = sesslen; + } + if (renew_ticket) + ret = SSL_TICKET_SUCCESS_RENEW; + else + ret = SSL_TICKET_SUCCESS; + goto end; + } + ERR_clear_error(); + /* + * For session parse failure, indicate that we need to send a new ticket. + */ + ret = SSL_TICKET_NO_DECRYPT; + + end: + EVP_CIPHER_CTX_free(ctx); + HMAC_CTX_free(hctx); + + /* + * If set, the decrypt_ticket_cb() is called unless a fatal error was + * detected above. The callback is responsible for checking |ret| before it + * performs any action + */ + if (s->session_ctx->decrypt_ticket_cb != NULL + && (ret == SSL_TICKET_EMPTY + || ret == SSL_TICKET_NO_DECRYPT + || ret == SSL_TICKET_SUCCESS + || ret == SSL_TICKET_SUCCESS_RENEW)) { + size_t keyname_len = eticklen; + int retcb; + + if (keyname_len > TLSEXT_KEYNAME_LENGTH) + keyname_len = TLSEXT_KEYNAME_LENGTH; + retcb = s->session_ctx->decrypt_ticket_cb(s, sess, etick, keyname_len, + ret, + s->session_ctx->ticket_cb_data); + switch (retcb) { + case SSL_TICKET_RETURN_ABORT: + ret = SSL_TICKET_FATAL_ERR_OTHER; + break; + + case SSL_TICKET_RETURN_IGNORE: + ret = SSL_TICKET_NONE; + SSL_SESSION_free(sess); + sess = NULL; + break; + + case SSL_TICKET_RETURN_IGNORE_RENEW: + if (ret != SSL_TICKET_EMPTY && ret != SSL_TICKET_NO_DECRYPT) + ret = SSL_TICKET_NO_DECRYPT; + /* else the value of |ret| will already do the right thing */ + SSL_SESSION_free(sess); + sess = NULL; + break; + + case SSL_TICKET_RETURN_USE: + case SSL_TICKET_RETURN_USE_RENEW: + if (ret != SSL_TICKET_SUCCESS + && ret != SSL_TICKET_SUCCESS_RENEW) + ret = SSL_TICKET_FATAL_ERR_OTHER; + else if (retcb == SSL_TICKET_RETURN_USE) + ret = SSL_TICKET_SUCCESS; + else + ret = SSL_TICKET_SUCCESS_RENEW; + break; + + default: + ret = SSL_TICKET_FATAL_ERR_OTHER; + } + } + + if (s->ext.session_secret_cb == NULL || SSL_IS_TLS13(s)) { + switch (ret) { + case SSL_TICKET_NO_DECRYPT: + case SSL_TICKET_SUCCESS_RENEW: + case SSL_TICKET_EMPTY: + s->ext.ticket_expected = 1; + } + } + + *psess = sess; + + return ret; +} + +/* Check to see if a signature algorithm is allowed */ +static int tls12_sigalg_allowed(SSL *s, int op, const SIGALG_LOOKUP *lu) +{ + unsigned char sigalgstr[2]; + int secbits; + + /* See if sigalgs is recognised and if hash is enabled */ + if (!tls1_lookup_md(lu, NULL)) + return 0; + /* DSA is not allowed in TLS 1.3 */ + if (SSL_IS_TLS13(s) && lu->sig == EVP_PKEY_DSA) + return 0; + /* TODO(OpenSSL1.2) fully axe DSA/etc. in ClientHello per TLS 1.3 spec */ + if (!s->server && !SSL_IS_DTLS(s) && s->s3->tmp.min_ver >= TLS1_3_VERSION + && (lu->sig == EVP_PKEY_DSA || lu->hash_idx == SSL_MD_SHA1_IDX + || lu->hash_idx == SSL_MD_MD5_IDX + || lu->hash_idx == SSL_MD_SHA224_IDX)) + return 0; + + /* See if public key algorithm allowed */ + if (ssl_cert_is_disabled(lu->sig_idx)) + return 0; + + if (lu->sig == NID_id_GostR3410_2012_256 + || lu->sig == NID_id_GostR3410_2012_512 + || lu->sig == NID_id_GostR3410_2001) { + /* We never allow GOST sig algs on the server with TLSv1.3 */ + if (s->server && SSL_IS_TLS13(s)) + return 0; + if (!s->server + && s->method->version == TLS_ANY_VERSION + && s->s3->tmp.max_ver >= TLS1_3_VERSION) { + int i, num; + STACK_OF(SSL_CIPHER) *sk; + + /* + * We're a client that could negotiate TLSv1.3. We only allow GOST + * sig algs if we could negotiate TLSv1.2 or below and we have GOST + * ciphersuites enabled. + */ + + if (s->s3->tmp.min_ver >= TLS1_3_VERSION) + return 0; + + sk = SSL_get_ciphers(s); + num = sk != NULL ? sk_SSL_CIPHER_num(sk) : 0; + for (i = 0; i < num; i++) { + const SSL_CIPHER *c; + + c = sk_SSL_CIPHER_value(sk, i); + /* Skip disabled ciphers */ + if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED, 0)) + continue; + + if ((c->algorithm_mkey & SSL_kGOST) != 0) + break; + } + if (i == num) + return 0; + } + } + + if (lu->hash == NID_undef) + return 1; + /* Security bits: half digest bits */ + secbits = EVP_MD_size(ssl_md(lu->hash_idx)) * 4; + /* Finally see if security callback allows it */ + sigalgstr[0] = (lu->sigalg >> 8) & 0xff; + sigalgstr[1] = lu->sigalg & 0xff; + return ssl_security(s, op, secbits, lu->hash, (void *)sigalgstr); +} + +/* + * Get a mask of disabled public key algorithms based on supported signature + * algorithms. For example if no signature algorithm supports RSA then RSA is + * disabled. + */ + +void ssl_set_sig_mask(uint32_t *pmask_a, SSL *s, int op) +{ + const uint16_t *sigalgs; + size_t i, sigalgslen; + uint32_t disabled_mask = SSL_aRSA | SSL_aDSS | SSL_aECDSA; + /* + * Go through all signature algorithms seeing if we support any + * in disabled_mask. + */ + sigalgslen = tls12_get_psigalgs(s, 1, &sigalgs); + for (i = 0; i < sigalgslen; i++, sigalgs++) { + const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(*sigalgs); + const SSL_CERT_LOOKUP *clu; + + if (lu == NULL) + continue; + + clu = ssl_cert_lookup_by_idx(lu->sig_idx); + if (clu == NULL) + continue; + + /* If algorithm is disabled see if we can enable it */ + if ((clu->amask & disabled_mask) != 0 + && tls12_sigalg_allowed(s, op, lu)) + disabled_mask &= ~clu->amask; + } + *pmask_a |= disabled_mask; +} + +int tls12_copy_sigalgs(SSL *s, WPACKET *pkt, + const uint16_t *psig, size_t psiglen) +{ + size_t i; + int rv = 0; + + for (i = 0; i < psiglen; i++, psig++) { + const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(*psig); + + if (!tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, lu)) + continue; + if (!WPACKET_put_bytes_u16(pkt, *psig)) + return 0; + /* + * If TLS 1.3 must have at least one valid TLS 1.3 message + * signing algorithm: i.e. neither RSA nor SHA1/SHA224 + */ + if (rv == 0 && (!SSL_IS_TLS13(s) + || (lu->sig != EVP_PKEY_RSA + && lu->hash != NID_sha1 + && lu->hash != NID_sha224))) + rv = 1; + } + if (rv == 0) + SSLerr(SSL_F_TLS12_COPY_SIGALGS, SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM); + return rv; +} + +/* Given preference and allowed sigalgs set shared sigalgs */ +static size_t tls12_shared_sigalgs(SSL *s, const SIGALG_LOOKUP **shsig, + const uint16_t *pref, size_t preflen, + const uint16_t *allow, size_t allowlen) +{ + const uint16_t *ptmp, *atmp; + size_t i, j, nmatch = 0; + for (i = 0, ptmp = pref; i < preflen; i++, ptmp++) { + const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(*ptmp); + + /* Skip disabled hashes or signature algorithms */ + if (!tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SHARED, lu)) + continue; + for (j = 0, atmp = allow; j < allowlen; j++, atmp++) { + if (*ptmp == *atmp) { + nmatch++; + if (shsig) + *shsig++ = lu; + break; + } + } + } + return nmatch; +} + +/* Set shared signature algorithms for SSL structures */ +static int tls1_set_shared_sigalgs(SSL *s) +{ + const uint16_t *pref, *allow, *conf; + size_t preflen, allowlen, conflen; + size_t nmatch; + const SIGALG_LOOKUP **salgs = NULL; + CERT *c = s->cert; + unsigned int is_suiteb = tls1_suiteb(s); + + OPENSSL_free(c->shared_sigalgs); + c->shared_sigalgs = NULL; + c->shared_sigalgslen = 0; + /* If client use client signature algorithms if not NULL */ + if (!s->server && c->client_sigalgs && !is_suiteb) { + conf = c->client_sigalgs; + conflen = c->client_sigalgslen; + } else if (c->conf_sigalgs && !is_suiteb) { + conf = c->conf_sigalgs; + conflen = c->conf_sigalgslen; + } else + conflen = tls12_get_psigalgs(s, 0, &conf); + if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE || is_suiteb) { + pref = conf; + preflen = conflen; + allow = s->s3->tmp.peer_sigalgs; + allowlen = s->s3->tmp.peer_sigalgslen; + } else { + allow = conf; + allowlen = conflen; + pref = s->s3->tmp.peer_sigalgs; + preflen = s->s3->tmp.peer_sigalgslen; + } + nmatch = tls12_shared_sigalgs(s, NULL, pref, preflen, allow, allowlen); + if (nmatch) { + if ((salgs = OPENSSL_malloc(nmatch * sizeof(*salgs))) == NULL) { + SSLerr(SSL_F_TLS1_SET_SHARED_SIGALGS, ERR_R_MALLOC_FAILURE); + return 0; + } + nmatch = tls12_shared_sigalgs(s, salgs, pref, preflen, allow, allowlen); + } else { + salgs = NULL; + } + c->shared_sigalgs = salgs; + c->shared_sigalgslen = nmatch; + return 1; +} + +int tls1_save_u16(PACKET *pkt, uint16_t **pdest, size_t *pdestlen) +{ + unsigned int stmp; + size_t size, i; + uint16_t *buf; + + size = PACKET_remaining(pkt); + + /* Invalid data length */ + if (size == 0 || (size & 1) != 0) + return 0; + + size >>= 1; + + if ((buf = OPENSSL_malloc(size * sizeof(*buf))) == NULL) { + SSLerr(SSL_F_TLS1_SAVE_U16, ERR_R_MALLOC_FAILURE); + return 0; + } + for (i = 0; i < size && PACKET_get_net_2(pkt, &stmp); i++) + buf[i] = stmp; + + if (i != size) { + OPENSSL_free(buf); + return 0; + } + + OPENSSL_free(*pdest); + *pdest = buf; + *pdestlen = size; + + return 1; +} + +int tls1_save_sigalgs(SSL *s, PACKET *pkt, int cert) +{ + /* Extension ignored for inappropriate versions */ + if (!SSL_USE_SIGALGS(s)) + return 1; + /* Should never happen */ + if (s->cert == NULL) + return 0; + + if (cert) + return tls1_save_u16(pkt, &s->s3->tmp.peer_cert_sigalgs, + &s->s3->tmp.peer_cert_sigalgslen); + else + return tls1_save_u16(pkt, &s->s3->tmp.peer_sigalgs, + &s->s3->tmp.peer_sigalgslen); + +} + +/* Set preferred digest for each key type */ + +int tls1_process_sigalgs(SSL *s) +{ + size_t i; + uint32_t *pvalid = s->s3->tmp.valid_flags; + CERT *c = s->cert; + + if (!tls1_set_shared_sigalgs(s)) + return 0; + + for (i = 0; i < SSL_PKEY_NUM; i++) + pvalid[i] = 0; + + for (i = 0; i < c->shared_sigalgslen; i++) { + const SIGALG_LOOKUP *sigptr = c->shared_sigalgs[i]; + int idx = sigptr->sig_idx; + + /* Ignore PKCS1 based sig algs in TLSv1.3 */ + if (SSL_IS_TLS13(s) && sigptr->sig == EVP_PKEY_RSA) + continue; + /* If not disabled indicate we can explicitly sign */ + if (pvalid[idx] == 0 && !ssl_cert_is_disabled(idx)) + pvalid[idx] = CERT_PKEY_EXPLICIT_SIGN | CERT_PKEY_SIGN; + } + return 1; +} + +int SSL_get_sigalgs(SSL *s, int idx, + int *psign, int *phash, int *psignhash, + unsigned char *rsig, unsigned char *rhash) +{ + uint16_t *psig = s->s3->tmp.peer_sigalgs; + size_t numsigalgs = s->s3->tmp.peer_sigalgslen; + if (psig == NULL || numsigalgs > INT_MAX) + return 0; + if (idx >= 0) { + const SIGALG_LOOKUP *lu; + + if (idx >= (int)numsigalgs) + return 0; + psig += idx; + if (rhash != NULL) + *rhash = (unsigned char)((*psig >> 8) & 0xff); + if (rsig != NULL) + *rsig = (unsigned char)(*psig & 0xff); + lu = tls1_lookup_sigalg(*psig); + if (psign != NULL) + *psign = lu != NULL ? lu->sig : NID_undef; + if (phash != NULL) + *phash = lu != NULL ? lu->hash : NID_undef; + if (psignhash != NULL) + *psignhash = lu != NULL ? lu->sigandhash : NID_undef; + } + return (int)numsigalgs; +} + +int SSL_get_shared_sigalgs(SSL *s, int idx, + int *psign, int *phash, int *psignhash, + unsigned char *rsig, unsigned char *rhash) +{ + const SIGALG_LOOKUP *shsigalgs; + if (s->cert->shared_sigalgs == NULL + || idx < 0 + || idx >= (int)s->cert->shared_sigalgslen + || s->cert->shared_sigalgslen > INT_MAX) + return 0; + shsigalgs = s->cert->shared_sigalgs[idx]; + if (phash != NULL) + *phash = shsigalgs->hash; + if (psign != NULL) + *psign = shsigalgs->sig; + if (psignhash != NULL) + *psignhash = shsigalgs->sigandhash; + if (rsig != NULL) + *rsig = (unsigned char)(shsigalgs->sigalg & 0xff); + if (rhash != NULL) + *rhash = (unsigned char)((shsigalgs->sigalg >> 8) & 0xff); + return (int)s->cert->shared_sigalgslen; +} + +/* Maximum possible number of unique entries in sigalgs array */ +#define TLS_MAX_SIGALGCNT (OSSL_NELEM(sigalg_lookup_tbl) * 2) + +typedef struct { + size_t sigalgcnt; + /* TLSEXT_SIGALG_XXX values */ + uint16_t sigalgs[TLS_MAX_SIGALGCNT]; +} sig_cb_st; + +static void get_sigorhash(int *psig, int *phash, const char *str) +{ + if (strcmp(str, "RSA") == 0) { + *psig = EVP_PKEY_RSA; + } else if (strcmp(str, "RSA-PSS") == 0 || strcmp(str, "PSS") == 0) { + *psig = EVP_PKEY_RSA_PSS; + } else if (strcmp(str, "DSA") == 0) { + *psig = EVP_PKEY_DSA; + } else if (strcmp(str, "ECDSA") == 0) { + *psig = EVP_PKEY_EC; + } else { + *phash = OBJ_sn2nid(str); + if (*phash == NID_undef) + *phash = OBJ_ln2nid(str); + } +} +/* Maximum length of a signature algorithm string component */ +#define TLS_MAX_SIGSTRING_LEN 40 + +static int sig_cb(const char *elem, int len, void *arg) +{ + sig_cb_st *sarg = arg; + size_t i; + const SIGALG_LOOKUP *s; + char etmp[TLS_MAX_SIGSTRING_LEN], *p; + int sig_alg = NID_undef, hash_alg = NID_undef; + if (elem == NULL) + return 0; + if (sarg->sigalgcnt == TLS_MAX_SIGALGCNT) + return 0; + if (len > (int)(sizeof(etmp) - 1)) + return 0; + memcpy(etmp, elem, len); + etmp[len] = 0; + p = strchr(etmp, '+'); + /* + * We only allow SignatureSchemes listed in the sigalg_lookup_tbl; + * if there's no '+' in the provided name, look for the new-style combined + * name. If not, match both sig+hash to find the needed SIGALG_LOOKUP. + * Just sig+hash is not unique since TLS 1.3 adds rsa_pss_pss_* and + * rsa_pss_rsae_* that differ only by public key OID; in such cases + * we will pick the _rsae_ variant, by virtue of them appearing earlier + * in the table. + */ + if (p == NULL) { + for (i = 0, s = sigalg_lookup_tbl; i < OSSL_NELEM(sigalg_lookup_tbl); + i++, s++) { + if (s->name != NULL && strcmp(etmp, s->name) == 0) { + sarg->sigalgs[sarg->sigalgcnt++] = s->sigalg; + break; + } + } + if (i == OSSL_NELEM(sigalg_lookup_tbl)) + return 0; + } else { + *p = 0; + p++; + if (*p == 0) + return 0; + get_sigorhash(&sig_alg, &hash_alg, etmp); + get_sigorhash(&sig_alg, &hash_alg, p); + if (sig_alg == NID_undef || hash_alg == NID_undef) + return 0; + for (i = 0, s = sigalg_lookup_tbl; i < OSSL_NELEM(sigalg_lookup_tbl); + i++, s++) { + if (s->hash == hash_alg && s->sig == sig_alg) { + sarg->sigalgs[sarg->sigalgcnt++] = s->sigalg; + break; + } + } + if (i == OSSL_NELEM(sigalg_lookup_tbl)) + return 0; + } + + /* Reject duplicates */ + for (i = 0; i < sarg->sigalgcnt - 1; i++) { + if (sarg->sigalgs[i] == sarg->sigalgs[sarg->sigalgcnt - 1]) { + sarg->sigalgcnt--; + return 0; + } + } + return 1; +} + +/* + * Set supported signature algorithms based on a colon separated list of the + * form sig+hash e.g. RSA+SHA512:DSA+SHA512 + */ +int tls1_set_sigalgs_list(CERT *c, const char *str, int client) +{ + sig_cb_st sig; + sig.sigalgcnt = 0; + if (!CONF_parse_list(str, ':', 1, sig_cb, &sig)) + return 0; + if (c == NULL) + return 1; + return tls1_set_raw_sigalgs(c, sig.sigalgs, sig.sigalgcnt, client); +} + +int tls1_set_raw_sigalgs(CERT *c, const uint16_t *psigs, size_t salglen, + int client) +{ + uint16_t *sigalgs; + + if ((sigalgs = OPENSSL_malloc(salglen * sizeof(*sigalgs))) == NULL) { + SSLerr(SSL_F_TLS1_SET_RAW_SIGALGS, ERR_R_MALLOC_FAILURE); + return 0; + } + memcpy(sigalgs, psigs, salglen * sizeof(*sigalgs)); + + if (client) { + OPENSSL_free(c->client_sigalgs); + c->client_sigalgs = sigalgs; + c->client_sigalgslen = salglen; + } else { + OPENSSL_free(c->conf_sigalgs); + c->conf_sigalgs = sigalgs; + c->conf_sigalgslen = salglen; + } + + return 1; +} + +int tls1_set_sigalgs(CERT *c, const int *psig_nids, size_t salglen, int client) +{ + uint16_t *sigalgs, *sptr; + size_t i; + + if (salglen & 1) + return 0; + if ((sigalgs = OPENSSL_malloc((salglen / 2) * sizeof(*sigalgs))) == NULL) { + SSLerr(SSL_F_TLS1_SET_SIGALGS, ERR_R_MALLOC_FAILURE); + return 0; + } + for (i = 0, sptr = sigalgs; i < salglen; i += 2) { + size_t j; + const SIGALG_LOOKUP *curr; + int md_id = *psig_nids++; + int sig_id = *psig_nids++; + + for (j = 0, curr = sigalg_lookup_tbl; j < OSSL_NELEM(sigalg_lookup_tbl); + j++, curr++) { + if (curr->hash == md_id && curr->sig == sig_id) { + *sptr++ = curr->sigalg; + break; + } + } + + if (j == OSSL_NELEM(sigalg_lookup_tbl)) + goto err; + } + + if (client) { + OPENSSL_free(c->client_sigalgs); + c->client_sigalgs = sigalgs; + c->client_sigalgslen = salglen / 2; + } else { + OPENSSL_free(c->conf_sigalgs); + c->conf_sigalgs = sigalgs; + c->conf_sigalgslen = salglen / 2; + } + + return 1; + + err: + OPENSSL_free(sigalgs); + return 0; +} + +static int tls1_check_sig_alg(CERT *c, X509 *x, int default_nid) +{ + int sig_nid; + size_t i; + if (default_nid == -1) + return 1; + sig_nid = X509_get_signature_nid(x); + if (default_nid) + return sig_nid == default_nid ? 1 : 0; + for (i = 0; i < c->shared_sigalgslen; i++) + if (sig_nid == c->shared_sigalgs[i]->sigandhash) + return 1; + return 0; +} + +/* Check to see if a certificate issuer name matches list of CA names */ +static int ssl_check_ca_name(STACK_OF(X509_NAME) *names, X509 *x) +{ + X509_NAME *nm; + int i; + nm = X509_get_issuer_name(x); + for (i = 0; i < sk_X509_NAME_num(names); i++) { + if (!X509_NAME_cmp(nm, sk_X509_NAME_value(names, i))) + return 1; + } + return 0; +} + +/* + * Check certificate chain is consistent with TLS extensions and is usable by + * server. This servers two purposes: it allows users to check chains before + * passing them to the server and it allows the server to check chains before + * attempting to use them. + */ + +/* Flags which need to be set for a certificate when strict mode not set */ + +#define CERT_PKEY_VALID_FLAGS \ + (CERT_PKEY_EE_SIGNATURE|CERT_PKEY_EE_PARAM) +/* Strict mode flags */ +#define CERT_PKEY_STRICT_FLAGS \ + (CERT_PKEY_VALID_FLAGS|CERT_PKEY_CA_SIGNATURE|CERT_PKEY_CA_PARAM \ + | CERT_PKEY_ISSUER_NAME|CERT_PKEY_CERT_TYPE) + +int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain, + int idx) +{ + int i; + int rv = 0; + int check_flags = 0, strict_mode; + CERT_PKEY *cpk = NULL; + CERT *c = s->cert; + uint32_t *pvalid; + unsigned int suiteb_flags = tls1_suiteb(s); + /* idx == -1 means checking server chains */ + if (idx != -1) { + /* idx == -2 means checking client certificate chains */ + if (idx == -2) { + cpk = c->key; + idx = (int)(cpk - c->pkeys); + } else + cpk = c->pkeys + idx; + pvalid = s->s3->tmp.valid_flags + idx; + x = cpk->x509; + pk = cpk->privatekey; + chain = cpk->chain; + strict_mode = c->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT; + /* If no cert or key, forget it */ + if (!x || !pk) + goto end; + } else { + size_t certidx; + + if (!x || !pk) + return 0; + + if (ssl_cert_lookup_by_pkey(pk, &certidx) == NULL) + return 0; + idx = certidx; + pvalid = s->s3->tmp.valid_flags + idx; + + if (c->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT) + check_flags = CERT_PKEY_STRICT_FLAGS; + else + check_flags = CERT_PKEY_VALID_FLAGS; + strict_mode = 1; + } + + if (suiteb_flags) { + int ok; + if (check_flags) + check_flags |= CERT_PKEY_SUITEB; + ok = X509_chain_check_suiteb(NULL, x, chain, suiteb_flags); + if (ok == X509_V_OK) + rv |= CERT_PKEY_SUITEB; + else if (!check_flags) + goto end; + } + + /* + * Check all signature algorithms are consistent with signature + * algorithms extension if TLS 1.2 or later and strict mode. + */ + if (TLS1_get_version(s) >= TLS1_2_VERSION && strict_mode) { + int default_nid; + int rsign = 0; + if (s->s3->tmp.peer_cert_sigalgs != NULL + || s->s3->tmp.peer_sigalgs != NULL) { + default_nid = 0; + /* If no sigalgs extension use defaults from RFC5246 */ + } else { + switch (idx) { + case SSL_PKEY_RSA: + rsign = EVP_PKEY_RSA; + default_nid = NID_sha1WithRSAEncryption; + break; + + case SSL_PKEY_DSA_SIGN: + rsign = EVP_PKEY_DSA; + default_nid = NID_dsaWithSHA1; + break; + + case SSL_PKEY_ECC: + rsign = EVP_PKEY_EC; + default_nid = NID_ecdsa_with_SHA1; + break; + + case SSL_PKEY_GOST01: + rsign = NID_id_GostR3410_2001; + default_nid = NID_id_GostR3411_94_with_GostR3410_2001; + break; + + case SSL_PKEY_GOST12_256: + rsign = NID_id_GostR3410_2012_256; + default_nid = NID_id_tc26_signwithdigest_gost3410_2012_256; + break; + + case SSL_PKEY_GOST12_512: + rsign = NID_id_GostR3410_2012_512; + default_nid = NID_id_tc26_signwithdigest_gost3410_2012_512; + break; + + default: + default_nid = -1; + break; + } + } + /* + * If peer sent no signature algorithms extension and we have set + * preferred signature algorithms check we support sha1. + */ + if (default_nid > 0 && c->conf_sigalgs) { + size_t j; + const uint16_t *p = c->conf_sigalgs; + for (j = 0; j < c->conf_sigalgslen; j++, p++) { + const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(*p); + + if (lu != NULL && lu->hash == NID_sha1 && lu->sig == rsign) + break; + } + if (j == c->conf_sigalgslen) { + if (check_flags) + goto skip_sigs; + else + goto end; + } + } + /* Check signature algorithm of each cert in chain */ + if (!tls1_check_sig_alg(c, x, default_nid)) { + if (!check_flags) + goto end; + } else + rv |= CERT_PKEY_EE_SIGNATURE; + rv |= CERT_PKEY_CA_SIGNATURE; + for (i = 0; i < sk_X509_num(chain); i++) { + if (!tls1_check_sig_alg(c, sk_X509_value(chain, i), default_nid)) { + if (check_flags) { + rv &= ~CERT_PKEY_CA_SIGNATURE; + break; + } else + goto end; + } + } + } + /* Else not TLS 1.2, so mark EE and CA signing algorithms OK */ + else if (check_flags) + rv |= CERT_PKEY_EE_SIGNATURE | CERT_PKEY_CA_SIGNATURE; + skip_sigs: + /* Check cert parameters are consistent */ + if (tls1_check_cert_param(s, x, 1)) + rv |= CERT_PKEY_EE_PARAM; + else if (!check_flags) + goto end; + if (!s->server) + rv |= CERT_PKEY_CA_PARAM; + /* In strict mode check rest of chain too */ + else if (strict_mode) { + rv |= CERT_PKEY_CA_PARAM; + for (i = 0; i < sk_X509_num(chain); i++) { + X509 *ca = sk_X509_value(chain, i); + if (!tls1_check_cert_param(s, ca, 0)) { + if (check_flags) { + rv &= ~CERT_PKEY_CA_PARAM; + break; + } else + goto end; + } + } + } + if (!s->server && strict_mode) { + STACK_OF(X509_NAME) *ca_dn; + int check_type = 0; + switch (EVP_PKEY_id(pk)) { + case EVP_PKEY_RSA: + check_type = TLS_CT_RSA_SIGN; + break; + case EVP_PKEY_DSA: + check_type = TLS_CT_DSS_SIGN; + break; + case EVP_PKEY_EC: + check_type = TLS_CT_ECDSA_SIGN; + break; + } + if (check_type) { + const uint8_t *ctypes = s->s3->tmp.ctype; + size_t j; + + for (j = 0; j < s->s3->tmp.ctype_len; j++, ctypes++) { + if (*ctypes == check_type) { + rv |= CERT_PKEY_CERT_TYPE; + break; + } + } + if (!(rv & CERT_PKEY_CERT_TYPE) && !check_flags) + goto end; + } else { + rv |= CERT_PKEY_CERT_TYPE; + } + + ca_dn = s->s3->tmp.peer_ca_names; + + if (!sk_X509_NAME_num(ca_dn)) + rv |= CERT_PKEY_ISSUER_NAME; + + if (!(rv & CERT_PKEY_ISSUER_NAME)) { + if (ssl_check_ca_name(ca_dn, x)) + rv |= CERT_PKEY_ISSUER_NAME; + } + if (!(rv & CERT_PKEY_ISSUER_NAME)) { + for (i = 0; i < sk_X509_num(chain); i++) { + X509 *xtmp = sk_X509_value(chain, i); + if (ssl_check_ca_name(ca_dn, xtmp)) { + rv |= CERT_PKEY_ISSUER_NAME; + break; + } + } + } + if (!check_flags && !(rv & CERT_PKEY_ISSUER_NAME)) + goto end; + } else + rv |= CERT_PKEY_ISSUER_NAME | CERT_PKEY_CERT_TYPE; + + if (!check_flags || (rv & check_flags) == check_flags) + rv |= CERT_PKEY_VALID; + + end: + + if (TLS1_get_version(s) >= TLS1_2_VERSION) + rv |= *pvalid & (CERT_PKEY_EXPLICIT_SIGN | CERT_PKEY_SIGN); + else + rv |= CERT_PKEY_SIGN | CERT_PKEY_EXPLICIT_SIGN; + + /* + * When checking a CERT_PKEY structure all flags are irrelevant if the + * chain is invalid. + */ + if (!check_flags) { + if (rv & CERT_PKEY_VALID) { + *pvalid = rv; + } else { + /* Preserve sign and explicit sign flag, clear rest */ + *pvalid &= CERT_PKEY_EXPLICIT_SIGN | CERT_PKEY_SIGN; + return 0; + } + } + return rv; +} + +/* Set validity of certificates in an SSL structure */ +void tls1_set_cert_validity(SSL *s) +{ + tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_RSA); + tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_RSA_PSS_SIGN); + tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_DSA_SIGN); + tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_ECC); + tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_GOST01); + tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_GOST12_256); + tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_GOST12_512); + tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_ED25519); + tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_ED448); +} + +/* User level utility function to check a chain is suitable */ +int SSL_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain) +{ + return tls1_check_chain(s, x, pk, chain, -1); +} + +#ifndef OPENSSL_NO_DH +DH *ssl_get_auto_dh(SSL *s) +{ + int dh_secbits = 80; + if (s->cert->dh_tmp_auto == 2) + return DH_get_1024_160(); + if (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aPSK)) { + if (s->s3->tmp.new_cipher->strength_bits == 256) + dh_secbits = 128; + else + dh_secbits = 80; + } else { + if (s->s3->tmp.cert == NULL) + return NULL; + dh_secbits = EVP_PKEY_security_bits(s->s3->tmp.cert->privatekey); + } + + if (dh_secbits >= 128) { + DH *dhp = DH_new(); + BIGNUM *p, *g; + if (dhp == NULL) + return NULL; + g = BN_new(); + if (g == NULL || !BN_set_word(g, 2)) { + DH_free(dhp); + BN_free(g); + return NULL; + } + if (dh_secbits >= 192) + p = BN_get_rfc3526_prime_8192(NULL); + else + p = BN_get_rfc3526_prime_3072(NULL); + if (p == NULL || !DH_set0_pqg(dhp, p, NULL, g)) { + DH_free(dhp); + BN_free(p); + BN_free(g); + return NULL; + } + return dhp; + } + if (dh_secbits >= 112) + return DH_get_2048_224(); + return DH_get_1024_160(); +} +#endif + +static int ssl_security_cert_key(SSL *s, SSL_CTX *ctx, X509 *x, int op) +{ + int secbits = -1; + EVP_PKEY *pkey = X509_get0_pubkey(x); + if (pkey) { + /* + * If no parameters this will return -1 and fail using the default + * security callback for any non-zero security level. This will + * reject keys which omit parameters but this only affects DSA and + * omission of parameters is never (?) done in practice. + */ + secbits = EVP_PKEY_security_bits(pkey); + } + if (s) + return ssl_security(s, op, secbits, 0, x); + else + return ssl_ctx_security(ctx, op, secbits, 0, x); +} + +static int ssl_security_cert_sig(SSL *s, SSL_CTX *ctx, X509 *x, int op) +{ + /* Lookup signature algorithm digest */ + int secbits, nid, pknid; + /* Don't check signature if self signed */ + if ((X509_get_extension_flags(x) & EXFLAG_SS) != 0) + return 1; + if (!X509_get_signature_info(x, &nid, &pknid, &secbits, NULL)) + secbits = -1; + /* If digest NID not defined use signature NID */ + if (nid == NID_undef) + nid = pknid; + if (s) + return ssl_security(s, op, secbits, nid, x); + else + return ssl_ctx_security(ctx, op, secbits, nid, x); +} + +int ssl_security_cert(SSL *s, SSL_CTX *ctx, X509 *x, int vfy, int is_ee) +{ + if (vfy) + vfy = SSL_SECOP_PEER; + if (is_ee) { + if (!ssl_security_cert_key(s, ctx, x, SSL_SECOP_EE_KEY | vfy)) + return SSL_R_EE_KEY_TOO_SMALL; + } else { + if (!ssl_security_cert_key(s, ctx, x, SSL_SECOP_CA_KEY | vfy)) + return SSL_R_CA_KEY_TOO_SMALL; + } + if (!ssl_security_cert_sig(s, ctx, x, SSL_SECOP_CA_MD | vfy)) + return SSL_R_CA_MD_TOO_WEAK; + return 1; +} + +/* + * Check security of a chain, if |sk| includes the end entity certificate then + * |x| is NULL. If |vfy| is 1 then we are verifying a peer chain and not sending + * one to the peer. Return values: 1 if ok otherwise error code to use + */ + +int ssl_security_cert_chain(SSL *s, STACK_OF(X509) *sk, X509 *x, int vfy) +{ + int rv, start_idx, i; + if (x == NULL) { + x = sk_X509_value(sk, 0); + start_idx = 1; + } else + start_idx = 0; + + rv = ssl_security_cert(s, NULL, x, vfy, 1); + if (rv != 1) + return rv; + + for (i = start_idx; i < sk_X509_num(sk); i++) { + x = sk_X509_value(sk, i); + rv = ssl_security_cert(s, NULL, x, vfy, 0); + if (rv != 1) + return rv; + } + return 1; +} + +/* + * For TLS 1.2 servers check if we have a certificate which can be used + * with the signature algorithm "lu" and return index of certificate. + */ + +static int tls12_get_cert_sigalg_idx(const SSL *s, const SIGALG_LOOKUP *lu) +{ + int sig_idx = lu->sig_idx; + const SSL_CERT_LOOKUP *clu = ssl_cert_lookup_by_idx(sig_idx); + + /* If not recognised or not supported by cipher mask it is not suitable */ + if (clu == NULL + || (clu->amask & s->s3->tmp.new_cipher->algorithm_auth) == 0 + || (clu->nid == EVP_PKEY_RSA_PSS + && (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kRSA) != 0)) + return -1; + + return s->s3->tmp.valid_flags[sig_idx] & CERT_PKEY_VALID ? sig_idx : -1; +} + +/* + * Returns true if |s| has a usable certificate configured for use + * with signature scheme |sig|. + * "Usable" includes a check for presence as well as applying + * the signature_algorithm_cert restrictions sent by the peer (if any). + * Returns false if no usable certificate is found. + */ +static int has_usable_cert(SSL *s, const SIGALG_LOOKUP *sig, int idx) +{ + const SIGALG_LOOKUP *lu; + int mdnid, pknid, default_mdnid; + int mandatory_md = 0; + size_t i; + + /* TLS 1.2 callers can override lu->sig_idx, but not TLS 1.3 callers. */ + if (idx == -1) + idx = sig->sig_idx; + if (!ssl_has_cert(s, idx)) + return 0; + /* If the EVP_PKEY reports a mandatory digest, allow nothing else. */ + ERR_set_mark(); + switch (EVP_PKEY_get_default_digest_nid(s->cert->pkeys[idx].privatekey, + &default_mdnid)) { + case 2: + mandatory_md = 1; + break; + case 1: + break; + default: /* If it didn't report a mandatory NID, for whatever reasons, + * just clear the error and allow all hashes to be used. */ + ERR_pop_to_mark(); + } + if (s->s3->tmp.peer_cert_sigalgs != NULL) { + for (i = 0; i < s->s3->tmp.peer_cert_sigalgslen; i++) { + lu = tls1_lookup_sigalg(s->s3->tmp.peer_cert_sigalgs[i]); + if (lu == NULL + || !X509_get_signature_info(s->cert->pkeys[idx].x509, &mdnid, + &pknid, NULL, NULL) + || (mandatory_md && mdnid != default_mdnid)) + continue; + /* + * TODO this does not differentiate between the + * rsa_pss_pss_* and rsa_pss_rsae_* schemes since we do not + * have a chain here that lets us look at the key OID in the + * signing certificate. + */ + if (mdnid == lu->hash && pknid == lu->sig) + return 1; + } + return 0; + } + return !mandatory_md || sig->hash == default_mdnid; +} + +/* + * Choose an appropriate signature algorithm based on available certificates + * Sets chosen certificate and signature algorithm. + * + * For servers if we fail to find a required certificate it is a fatal error, + * an appropriate error code is set and a TLS alert is sent. + * + * For clients fatalerrs is set to 0. If a certificate is not suitable it is not + * a fatal error: we will either try another certificate or not present one + * to the server. In this case no error is set. + */ +int tls_choose_sigalg(SSL *s, int fatalerrs) +{ + const SIGALG_LOOKUP *lu = NULL; + int sig_idx = -1; + + s->s3->tmp.cert = NULL; + s->s3->tmp.sigalg = NULL; + + if (SSL_IS_TLS13(s)) { + size_t i; +#ifndef OPENSSL_NO_EC + int curve = -1; +#endif + + /* Look for a certificate matching shared sigalgs */ + for (i = 0; i < s->cert->shared_sigalgslen; i++) { + lu = s->cert->shared_sigalgs[i]; + sig_idx = -1; + + /* Skip SHA1, SHA224, DSA and RSA if not PSS */ + if (lu->hash == NID_sha1 + || lu->hash == NID_sha224 + || lu->sig == EVP_PKEY_DSA + || lu->sig == EVP_PKEY_RSA) + continue; + /* Check that we have a cert, and signature_algorithms_cert */ + if (!tls1_lookup_md(lu, NULL) || !has_usable_cert(s, lu, -1)) + continue; + if (lu->sig == EVP_PKEY_EC) { +#ifndef OPENSSL_NO_EC + if (curve == -1) { + EC_KEY *ec = EVP_PKEY_get0_EC_KEY(s->cert->pkeys[SSL_PKEY_ECC].privatekey); + + curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); + } + if (lu->curve != NID_undef && curve != lu->curve) + continue; +#else + continue; +#endif + } else if (lu->sig == EVP_PKEY_RSA_PSS) { + /* validate that key is large enough for the signature algorithm */ + EVP_PKEY *pkey; + + pkey = s->cert->pkeys[lu->sig_idx].privatekey; + if (!rsa_pss_check_min_key_size(EVP_PKEY_get0(pkey), lu)) + continue; + } + break; + } + if (i == s->cert->shared_sigalgslen) { + if (!fatalerrs) + return 1; + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_CHOOSE_SIGALG, + SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM); + return 0; + } + } else { + /* If ciphersuite doesn't require a cert nothing to do */ + if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aCERT)) + return 1; + if (!s->server && !ssl_has_cert(s, s->cert->key - s->cert->pkeys)) + return 1; + + if (SSL_USE_SIGALGS(s)) { + size_t i; + if (s->s3->tmp.peer_sigalgs != NULL) { +#ifndef OPENSSL_NO_EC + int curve; + + /* For Suite B need to match signature algorithm to curve */ + if (tls1_suiteb(s)) { + EC_KEY *ec = EVP_PKEY_get0_EC_KEY(s->cert->pkeys[SSL_PKEY_ECC].privatekey); + curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); + } else { + curve = -1; + } +#endif + + /* + * Find highest preference signature algorithm matching + * cert type + */ + for (i = 0; i < s->cert->shared_sigalgslen; i++) { + lu = s->cert->shared_sigalgs[i]; + + if (s->server) { + if ((sig_idx = tls12_get_cert_sigalg_idx(s, lu)) == -1) + continue; + } else { + int cc_idx = s->cert->key - s->cert->pkeys; + + sig_idx = lu->sig_idx; + if (cc_idx != sig_idx) + continue; + } + /* Check that we have a cert, and sig_algs_cert */ + if (!has_usable_cert(s, lu, sig_idx)) + continue; + if (lu->sig == EVP_PKEY_RSA_PSS) { + /* validate that key is large enough for the signature algorithm */ + EVP_PKEY *pkey = s->cert->pkeys[sig_idx].privatekey; + + if (!rsa_pss_check_min_key_size(EVP_PKEY_get0(pkey), lu)) + continue; + } +#ifndef OPENSSL_NO_EC + if (curve == -1 || lu->curve == curve) +#endif + break; + } + if (i == s->cert->shared_sigalgslen) { + if (!fatalerrs) + return 1; + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_CHOOSE_SIGALG, + SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM); + return 0; + } + } else { + /* + * If we have no sigalg use defaults + */ + const uint16_t *sent_sigs; + size_t sent_sigslen; + + if ((lu = tls1_get_legacy_sigalg(s, -1)) == NULL) { + if (!fatalerrs) + return 1; + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CHOOSE_SIGALG, + ERR_R_INTERNAL_ERROR); + return 0; + } + + /* Check signature matches a type we sent */ + sent_sigslen = tls12_get_psigalgs(s, 1, &sent_sigs); + for (i = 0; i < sent_sigslen; i++, sent_sigs++) { + if (lu->sigalg == *sent_sigs + && has_usable_cert(s, lu, lu->sig_idx)) + break; + } + if (i == sent_sigslen) { + if (!fatalerrs) + return 1; + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_TLS_CHOOSE_SIGALG, + SSL_R_WRONG_SIGNATURE_TYPE); + return 0; + } + } + } else { + if ((lu = tls1_get_legacy_sigalg(s, -1)) == NULL) { + if (!fatalerrs) + return 1; + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CHOOSE_SIGALG, + ERR_R_INTERNAL_ERROR); + return 0; + } + } + } + if (sig_idx == -1) + sig_idx = lu->sig_idx; + s->s3->tmp.cert = &s->cert->pkeys[sig_idx]; + s->cert->key = s->s3->tmp.cert; + s->s3->tmp.sigalg = lu; + return 1; +} + +int SSL_CTX_set_tlsext_max_fragment_length(SSL_CTX *ctx, uint8_t mode) +{ + if (mode != TLSEXT_max_fragment_length_DISABLED + && !IS_MAX_FRAGMENT_LENGTH_EXT_VALID(mode)) { + SSLerr(SSL_F_SSL_CTX_SET_TLSEXT_MAX_FRAGMENT_LENGTH, + SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH); + return 0; + } + + ctx->ext.max_fragment_len_mode = mode; + return 1; +} + +int SSL_set_tlsext_max_fragment_length(SSL *ssl, uint8_t mode) +{ + if (mode != TLSEXT_max_fragment_length_DISABLED + && !IS_MAX_FRAGMENT_LENGTH_EXT_VALID(mode)) { + SSLerr(SSL_F_SSL_SET_TLSEXT_MAX_FRAGMENT_LENGTH, + SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH); + return 0; + } + + ssl->ext.max_fragment_len_mode = mode; + return 1; +} + +uint8_t SSL_SESSION_get_max_fragment_length(const SSL_SESSION *session) +{ + return session->ext.max_fragment_len_mode; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/t1_trce.c b/trunk/3rdparty/openssl-1.1-fit/ssl/t1_trce.c new file mode 100644 index 000000000..be3039af3 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/t1_trce.c @@ -0,0 +1,1566 @@ +/* + * Copyright 2012-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "ssl_locl.h" + +#ifndef OPENSSL_NO_SSL_TRACE + +/* Packet trace support for OpenSSL */ + +typedef struct { + int num; + const char *name; +} ssl_trace_tbl; + +# define ssl_trace_str(val, tbl) \ + do_ssl_trace_str(val, tbl, OSSL_NELEM(tbl)) + +# define ssl_trace_list(bio, indent, msg, msglen, value, table) \ + do_ssl_trace_list(bio, indent, msg, msglen, value, \ + table, OSSL_NELEM(table)) + +static const char *do_ssl_trace_str(int val, const ssl_trace_tbl *tbl, + size_t ntbl) +{ + size_t i; + + for (i = 0; i < ntbl; i++, tbl++) { + if (tbl->num == val) + return tbl->name; + } + return "UNKNOWN"; +} + +static int do_ssl_trace_list(BIO *bio, int indent, + const unsigned char *msg, size_t msglen, + size_t vlen, const ssl_trace_tbl *tbl, size_t ntbl) +{ + int val; + + if (msglen % vlen) + return 0; + while (msglen) { + val = msg[0]; + if (vlen == 2) + val = (val << 8) | msg[1]; + BIO_indent(bio, indent, 80); + BIO_printf(bio, "%s (%d)\n", do_ssl_trace_str(val, tbl, ntbl), val); + msg += vlen; + msglen -= vlen; + } + return 1; +} + +/* Version number */ + +static const ssl_trace_tbl ssl_version_tbl[] = { + {SSL3_VERSION, "SSL 3.0"}, + {TLS1_VERSION, "TLS 1.0"}, + {TLS1_1_VERSION, "TLS 1.1"}, + {TLS1_2_VERSION, "TLS 1.2"}, + {TLS1_3_VERSION, "TLS 1.3"}, + {DTLS1_VERSION, "DTLS 1.0"}, + {DTLS1_2_VERSION, "DTLS 1.2"}, + {DTLS1_BAD_VER, "DTLS 1.0 (bad)"} +}; + +static const ssl_trace_tbl ssl_content_tbl[] = { + {SSL3_RT_CHANGE_CIPHER_SPEC, "ChangeCipherSpec"}, + {SSL3_RT_ALERT, "Alert"}, + {SSL3_RT_HANDSHAKE, "Handshake"}, + {SSL3_RT_APPLICATION_DATA, "ApplicationData"}, +}; + +/* Handshake types, sorted by ascending id */ +static const ssl_trace_tbl ssl_handshake_tbl[] = { + {SSL3_MT_HELLO_REQUEST, "HelloRequest"}, + {SSL3_MT_CLIENT_HELLO, "ClientHello"}, + {SSL3_MT_SERVER_HELLO, "ServerHello"}, + {DTLS1_MT_HELLO_VERIFY_REQUEST, "HelloVerifyRequest"}, + {SSL3_MT_NEWSESSION_TICKET, "NewSessionTicket"}, + {SSL3_MT_END_OF_EARLY_DATA, "EndOfEarlyData"}, + {SSL3_MT_ENCRYPTED_EXTENSIONS, "EncryptedExtensions"}, + {SSL3_MT_CERTIFICATE, "Certificate"}, + {SSL3_MT_SERVER_KEY_EXCHANGE, "ServerKeyExchange"}, + {SSL3_MT_CERTIFICATE_REQUEST, "CertificateRequest"}, + {SSL3_MT_SERVER_DONE, "ServerHelloDone"}, + {SSL3_MT_CERTIFICATE_VERIFY, "CertificateVerify"}, + {SSL3_MT_CLIENT_KEY_EXCHANGE, "ClientKeyExchange"}, + {SSL3_MT_FINISHED, "Finished"}, + {SSL3_MT_CERTIFICATE_URL, "CertificateUrl"}, + {SSL3_MT_CERTIFICATE_STATUS, "CertificateStatus"}, + {SSL3_MT_SUPPLEMENTAL_DATA, "SupplementalData"}, + {SSL3_MT_KEY_UPDATE, "KeyUpdate"}, +# ifndef OPENSSL_NO_NEXTPROTONEG + {SSL3_MT_NEXT_PROTO, "NextProto"}, +# endif + {SSL3_MT_MESSAGE_HASH, "MessageHash"} +}; + +/* Cipher suites */ +static const ssl_trace_tbl ssl_ciphers_tbl[] = { + {0x0000, "TLS_NULL_WITH_NULL_NULL"}, + {0x0001, "TLS_RSA_WITH_NULL_MD5"}, + {0x0002, "TLS_RSA_WITH_NULL_SHA"}, + {0x0003, "TLS_RSA_EXPORT_WITH_RC4_40_MD5"}, + {0x0004, "TLS_RSA_WITH_RC4_128_MD5"}, + {0x0005, "TLS_RSA_WITH_RC4_128_SHA"}, + {0x0006, "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5"}, + {0x0007, "TLS_RSA_WITH_IDEA_CBC_SHA"}, + {0x0008, "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA"}, + {0x0009, "TLS_RSA_WITH_DES_CBC_SHA"}, + {0x000A, "TLS_RSA_WITH_3DES_EDE_CBC_SHA"}, + {0x000B, "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"}, + {0x000C, "TLS_DH_DSS_WITH_DES_CBC_SHA"}, + {0x000D, "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA"}, + {0x000E, "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"}, + {0x000F, "TLS_DH_RSA_WITH_DES_CBC_SHA"}, + {0x0010, "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA"}, + {0x0011, "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"}, + {0x0012, "TLS_DHE_DSS_WITH_DES_CBC_SHA"}, + {0x0013, "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA"}, + {0x0014, "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"}, + {0x0015, "TLS_DHE_RSA_WITH_DES_CBC_SHA"}, + {0x0016, "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"}, + {0x0017, "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5"}, + {0x0018, "TLS_DH_anon_WITH_RC4_128_MD5"}, + {0x0019, "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA"}, + {0x001A, "TLS_DH_anon_WITH_DES_CBC_SHA"}, + {0x001B, "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"}, + {0x001D, "SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA"}, + {0x001E, "SSL_FORTEZZA_KEA_WITH_RC4_128_SHA"}, + {0x001F, "TLS_KRB5_WITH_3DES_EDE_CBC_SHA"}, + {0x0020, "TLS_KRB5_WITH_RC4_128_SHA"}, + {0x0021, "TLS_KRB5_WITH_IDEA_CBC_SHA"}, + {0x0022, "TLS_KRB5_WITH_DES_CBC_MD5"}, + {0x0023, "TLS_KRB5_WITH_3DES_EDE_CBC_MD5"}, + {0x0024, "TLS_KRB5_WITH_RC4_128_MD5"}, + {0x0025, "TLS_KRB5_WITH_IDEA_CBC_MD5"}, + {0x0026, "TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA"}, + {0x0027, "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA"}, + {0x0028, "TLS_KRB5_EXPORT_WITH_RC4_40_SHA"}, + {0x0029, "TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5"}, + {0x002A, "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5"}, + {0x002B, "TLS_KRB5_EXPORT_WITH_RC4_40_MD5"}, + {0x002C, "TLS_PSK_WITH_NULL_SHA"}, + {0x002D, "TLS_DHE_PSK_WITH_NULL_SHA"}, + {0x002E, "TLS_RSA_PSK_WITH_NULL_SHA"}, + {0x002F, "TLS_RSA_WITH_AES_128_CBC_SHA"}, + {0x0030, "TLS_DH_DSS_WITH_AES_128_CBC_SHA"}, + {0x0031, "TLS_DH_RSA_WITH_AES_128_CBC_SHA"}, + {0x0032, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"}, + {0x0033, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"}, + {0x0034, "TLS_DH_anon_WITH_AES_128_CBC_SHA"}, + {0x0035, "TLS_RSA_WITH_AES_256_CBC_SHA"}, + {0x0036, "TLS_DH_DSS_WITH_AES_256_CBC_SHA"}, + {0x0037, "TLS_DH_RSA_WITH_AES_256_CBC_SHA"}, + {0x0038, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"}, + {0x0039, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"}, + {0x003A, "TLS_DH_anon_WITH_AES_256_CBC_SHA"}, + {0x003B, "TLS_RSA_WITH_NULL_SHA256"}, + {0x003C, "TLS_RSA_WITH_AES_128_CBC_SHA256"}, + {0x003D, "TLS_RSA_WITH_AES_256_CBC_SHA256"}, + {0x003E, "TLS_DH_DSS_WITH_AES_128_CBC_SHA256"}, + {0x003F, "TLS_DH_RSA_WITH_AES_128_CBC_SHA256"}, + {0x0040, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"}, + {0x0041, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA"}, + {0x0042, "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA"}, + {0x0043, "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA"}, + {0x0044, "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA"}, + {0x0045, "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA"}, + {0x0046, "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA"}, + {0x0067, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"}, + {0x0068, "TLS_DH_DSS_WITH_AES_256_CBC_SHA256"}, + {0x0069, "TLS_DH_RSA_WITH_AES_256_CBC_SHA256"}, + {0x006A, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"}, + {0x006B, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"}, + {0x006C, "TLS_DH_anon_WITH_AES_128_CBC_SHA256"}, + {0x006D, "TLS_DH_anon_WITH_AES_256_CBC_SHA256"}, + {0x0081, "TLS_GOSTR341001_WITH_28147_CNT_IMIT"}, + {0x0083, "TLS_GOSTR341001_WITH_NULL_GOSTR3411"}, + {0x0084, "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA"}, + {0x0085, "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA"}, + {0x0086, "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA"}, + {0x0087, "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA"}, + {0x0088, "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA"}, + {0x0089, "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA"}, + {0x008A, "TLS_PSK_WITH_RC4_128_SHA"}, + {0x008B, "TLS_PSK_WITH_3DES_EDE_CBC_SHA"}, + {0x008C, "TLS_PSK_WITH_AES_128_CBC_SHA"}, + {0x008D, "TLS_PSK_WITH_AES_256_CBC_SHA"}, + {0x008E, "TLS_DHE_PSK_WITH_RC4_128_SHA"}, + {0x008F, "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA"}, + {0x0090, "TLS_DHE_PSK_WITH_AES_128_CBC_SHA"}, + {0x0091, "TLS_DHE_PSK_WITH_AES_256_CBC_SHA"}, + {0x0092, "TLS_RSA_PSK_WITH_RC4_128_SHA"}, + {0x0093, "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA"}, + {0x0094, "TLS_RSA_PSK_WITH_AES_128_CBC_SHA"}, + {0x0095, "TLS_RSA_PSK_WITH_AES_256_CBC_SHA"}, + {0x0096, "TLS_RSA_WITH_SEED_CBC_SHA"}, + {0x0097, "TLS_DH_DSS_WITH_SEED_CBC_SHA"}, + {0x0098, "TLS_DH_RSA_WITH_SEED_CBC_SHA"}, + {0x0099, "TLS_DHE_DSS_WITH_SEED_CBC_SHA"}, + {0x009A, "TLS_DHE_RSA_WITH_SEED_CBC_SHA"}, + {0x009B, "TLS_DH_anon_WITH_SEED_CBC_SHA"}, + {0x009C, "TLS_RSA_WITH_AES_128_GCM_SHA256"}, + {0x009D, "TLS_RSA_WITH_AES_256_GCM_SHA384"}, + {0x009E, "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"}, + {0x009F, "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"}, + {0x00A0, "TLS_DH_RSA_WITH_AES_128_GCM_SHA256"}, + {0x00A1, "TLS_DH_RSA_WITH_AES_256_GCM_SHA384"}, + {0x00A2, "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256"}, + {0x00A3, "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"}, + {0x00A4, "TLS_DH_DSS_WITH_AES_128_GCM_SHA256"}, + {0x00A5, "TLS_DH_DSS_WITH_AES_256_GCM_SHA384"}, + {0x00A6, "TLS_DH_anon_WITH_AES_128_GCM_SHA256"}, + {0x00A7, "TLS_DH_anon_WITH_AES_256_GCM_SHA384"}, + {0x00A8, "TLS_PSK_WITH_AES_128_GCM_SHA256"}, + {0x00A9, "TLS_PSK_WITH_AES_256_GCM_SHA384"}, + {0x00AA, "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256"}, + {0x00AB, "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384"}, + {0x00AC, "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256"}, + {0x00AD, "TLS_RSA_PSK_WITH_AES_256_GCM_SHA384"}, + {0x00AE, "TLS_PSK_WITH_AES_128_CBC_SHA256"}, + {0x00AF, "TLS_PSK_WITH_AES_256_CBC_SHA384"}, + {0x00B0, "TLS_PSK_WITH_NULL_SHA256"}, + {0x00B1, "TLS_PSK_WITH_NULL_SHA384"}, + {0x00B2, "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256"}, + {0x00B3, "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384"}, + {0x00B4, "TLS_DHE_PSK_WITH_NULL_SHA256"}, + {0x00B5, "TLS_DHE_PSK_WITH_NULL_SHA384"}, + {0x00B6, "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256"}, + {0x00B7, "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384"}, + {0x00B8, "TLS_RSA_PSK_WITH_NULL_SHA256"}, + {0x00B9, "TLS_RSA_PSK_WITH_NULL_SHA384"}, + {0x00BA, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256"}, + {0x00BB, "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256"}, + {0x00BC, "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256"}, + {0x00BD, "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256"}, + {0x00BE, "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256"}, + {0x00BF, "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256"}, + {0x00C0, "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256"}, + {0x00C1, "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256"}, + {0x00C2, "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256"}, + {0x00C3, "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256"}, + {0x00C4, "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256"}, + {0x00C5, "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256"}, + {0x00FF, "TLS_EMPTY_RENEGOTIATION_INFO_SCSV"}, + {0x5600, "TLS_FALLBACK_SCSV"}, + {0xC001, "TLS_ECDH_ECDSA_WITH_NULL_SHA"}, + {0xC002, "TLS_ECDH_ECDSA_WITH_RC4_128_SHA"}, + {0xC003, "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"}, + {0xC004, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"}, + {0xC005, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"}, + {0xC006, "TLS_ECDHE_ECDSA_WITH_NULL_SHA"}, + {0xC007, "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"}, + {0xC008, "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"}, + {0xC009, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"}, + {0xC00A, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"}, + {0xC00B, "TLS_ECDH_RSA_WITH_NULL_SHA"}, + {0xC00C, "TLS_ECDH_RSA_WITH_RC4_128_SHA"}, + {0xC00D, "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"}, + {0xC00E, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA"}, + {0xC00F, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA"}, + {0xC010, "TLS_ECDHE_RSA_WITH_NULL_SHA"}, + {0xC011, "TLS_ECDHE_RSA_WITH_RC4_128_SHA"}, + {0xC012, "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"}, + {0xC013, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"}, + {0xC014, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"}, + {0xC015, "TLS_ECDH_anon_WITH_NULL_SHA"}, + {0xC016, "TLS_ECDH_anon_WITH_RC4_128_SHA"}, + {0xC017, "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA"}, + {0xC018, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA"}, + {0xC019, "TLS_ECDH_anon_WITH_AES_256_CBC_SHA"}, + {0xC01A, "TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA"}, + {0xC01B, "TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA"}, + {0xC01C, "TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA"}, + {0xC01D, "TLS_SRP_SHA_WITH_AES_128_CBC_SHA"}, + {0xC01E, "TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA"}, + {0xC01F, "TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA"}, + {0xC020, "TLS_SRP_SHA_WITH_AES_256_CBC_SHA"}, + {0xC021, "TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA"}, + {0xC022, "TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA"}, + {0xC023, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"}, + {0xC024, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"}, + {0xC025, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256"}, + {0xC026, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384"}, + {0xC027, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"}, + {0xC028, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"}, + {0xC029, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256"}, + {0xC02A, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384"}, + {0xC02B, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"}, + {0xC02C, "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"}, + {0xC02D, "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256"}, + {0xC02E, "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384"}, + {0xC02F, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"}, + {0xC030, "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"}, + {0xC031, "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256"}, + {0xC032, "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384"}, + {0xC033, "TLS_ECDHE_PSK_WITH_RC4_128_SHA"}, + {0xC034, "TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA"}, + {0xC035, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA"}, + {0xC036, "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA"}, + {0xC037, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256"}, + {0xC038, "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384"}, + {0xC039, "TLS_ECDHE_PSK_WITH_NULL_SHA"}, + {0xC03A, "TLS_ECDHE_PSK_WITH_NULL_SHA256"}, + {0xC03B, "TLS_ECDHE_PSK_WITH_NULL_SHA384"}, + {0xC03C, "TLS_RSA_WITH_ARIA_128_CBC_SHA256"}, + {0xC03D, "TLS_RSA_WITH_ARIA_256_CBC_SHA384"}, + {0xC03E, "TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256"}, + {0xC03F, "TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384"}, + {0xC040, "TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256"}, + {0xC041, "TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384"}, + {0xC042, "TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256"}, + {0xC043, "TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384"}, + {0xC044, "TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256"}, + {0xC045, "TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384"}, + {0xC046, "TLS_DH_anon_WITH_ARIA_128_CBC_SHA256"}, + {0xC047, "TLS_DH_anon_WITH_ARIA_256_CBC_SHA384"}, + {0xC048, "TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256"}, + {0xC049, "TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384"}, + {0xC04A, "TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256"}, + {0xC04B, "TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384"}, + {0xC04C, "TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256"}, + {0xC04D, "TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384"}, + {0xC04E, "TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256"}, + {0xC04F, "TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384"}, + {0xC050, "TLS_RSA_WITH_ARIA_128_GCM_SHA256"}, + {0xC051, "TLS_RSA_WITH_ARIA_256_GCM_SHA384"}, + {0xC052, "TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256"}, + {0xC053, "TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384"}, + {0xC054, "TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256"}, + {0xC055, "TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384"}, + {0xC056, "TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256"}, + {0xC057, "TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384"}, + {0xC058, "TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256"}, + {0xC059, "TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384"}, + {0xC05A, "TLS_DH_anon_WITH_ARIA_128_GCM_SHA256"}, + {0xC05B, "TLS_DH_anon_WITH_ARIA_256_GCM_SHA384"}, + {0xC05C, "TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256"}, + {0xC05D, "TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384"}, + {0xC05E, "TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256"}, + {0xC05F, "TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384"}, + {0xC060, "TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256"}, + {0xC061, "TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384"}, + {0xC062, "TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256"}, + {0xC063, "TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384"}, + {0xC064, "TLS_PSK_WITH_ARIA_128_CBC_SHA256"}, + {0xC065, "TLS_PSK_WITH_ARIA_256_CBC_SHA384"}, + {0xC066, "TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256"}, + {0xC067, "TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384"}, + {0xC068, "TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256"}, + {0xC069, "TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384"}, + {0xC06A, "TLS_PSK_WITH_ARIA_128_GCM_SHA256"}, + {0xC06B, "TLS_PSK_WITH_ARIA_256_GCM_SHA384"}, + {0xC06C, "TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256"}, + {0xC06D, "TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384"}, + {0xC06E, "TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256"}, + {0xC06F, "TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384"}, + {0xC070, "TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256"}, + {0xC071, "TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384"}, + {0xC072, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256"}, + {0xC073, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384"}, + {0xC074, "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256"}, + {0xC075, "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384"}, + {0xC076, "TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256"}, + {0xC077, "TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384"}, + {0xC078, "TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256"}, + {0xC079, "TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384"}, + {0xC07A, "TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256"}, + {0xC07B, "TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384"}, + {0xC07C, "TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256"}, + {0xC07D, "TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384"}, + {0xC07E, "TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256"}, + {0xC07F, "TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384"}, + {0xC080, "TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256"}, + {0xC081, "TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384"}, + {0xC082, "TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256"}, + {0xC083, "TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384"}, + {0xC084, "TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256"}, + {0xC085, "TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384"}, + {0xC086, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256"}, + {0xC087, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384"}, + {0xC088, "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256"}, + {0xC089, "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384"}, + {0xC08A, "TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256"}, + {0xC08B, "TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384"}, + {0xC08C, "TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256"}, + {0xC08D, "TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384"}, + {0xC08E, "TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256"}, + {0xC08F, "TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384"}, + {0xC090, "TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256"}, + {0xC091, "TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384"}, + {0xC092, "TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256"}, + {0xC093, "TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384"}, + {0xC094, "TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256"}, + {0xC095, "TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384"}, + {0xC096, "TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256"}, + {0xC097, "TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384"}, + {0xC098, "TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256"}, + {0xC099, "TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384"}, + {0xC09A, "TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256"}, + {0xC09B, "TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384"}, + {0xC09C, "TLS_RSA_WITH_AES_128_CCM"}, + {0xC09D, "TLS_RSA_WITH_AES_256_CCM"}, + {0xC09E, "TLS_DHE_RSA_WITH_AES_128_CCM"}, + {0xC09F, "TLS_DHE_RSA_WITH_AES_256_CCM"}, + {0xC0A0, "TLS_RSA_WITH_AES_128_CCM_8"}, + {0xC0A1, "TLS_RSA_WITH_AES_256_CCM_8"}, + {0xC0A2, "TLS_DHE_RSA_WITH_AES_128_CCM_8"}, + {0xC0A3, "TLS_DHE_RSA_WITH_AES_256_CCM_8"}, + {0xC0A4, "TLS_PSK_WITH_AES_128_CCM"}, + {0xC0A5, "TLS_PSK_WITH_AES_256_CCM"}, + {0xC0A6, "TLS_DHE_PSK_WITH_AES_128_CCM"}, + {0xC0A7, "TLS_DHE_PSK_WITH_AES_256_CCM"}, + {0xC0A8, "TLS_PSK_WITH_AES_128_CCM_8"}, + {0xC0A9, "TLS_PSK_WITH_AES_256_CCM_8"}, + {0xC0AA, "TLS_PSK_DHE_WITH_AES_128_CCM_8"}, + {0xC0AB, "TLS_PSK_DHE_WITH_AES_256_CCM_8"}, + {0xC0AC, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM"}, + {0xC0AD, "TLS_ECDHE_ECDSA_WITH_AES_256_CCM"}, + {0xC0AE, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8"}, + {0xC0AF, "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8"}, + {0xCCA8, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"}, + {0xCCA9, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"}, + {0xCCAA, "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256"}, + {0xCCAB, "TLS_PSK_WITH_CHACHA20_POLY1305_SHA256"}, + {0xCCAC, "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256"}, + {0xCCAD, "TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256"}, + {0xCCAE, "TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256"}, + {0x1301, "TLS_AES_128_GCM_SHA256"}, + {0x1302, "TLS_AES_256_GCM_SHA384"}, + {0x1303, "TLS_CHACHA20_POLY1305_SHA256"}, + {0x1304, "TLS_AES_128_CCM_SHA256"}, + {0x1305, "TLS_AES_128_CCM_8_SHA256"}, + {0xFEFE, "SSL_RSA_FIPS_WITH_DES_CBC_SHA"}, + {0xFEFF, "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA"}, + {0xFF85, "GOST2012-GOST8912-GOST8912"}, + {0xFF87, "GOST2012-NULL-GOST12"}, +}; + +/* Compression methods */ +static const ssl_trace_tbl ssl_comp_tbl[] = { + {0x0000, "No Compression"}, + {0x0001, "Zlib Compression"} +}; + +/* Extensions sorted by ascending id */ +static const ssl_trace_tbl ssl_exts_tbl[] = { + {TLSEXT_TYPE_server_name, "server_name"}, + {TLSEXT_TYPE_max_fragment_length, "max_fragment_length"}, + {TLSEXT_TYPE_client_certificate_url, "client_certificate_url"}, + {TLSEXT_TYPE_trusted_ca_keys, "trusted_ca_keys"}, + {TLSEXT_TYPE_truncated_hmac, "truncated_hmac"}, + {TLSEXT_TYPE_status_request, "status_request"}, + {TLSEXT_TYPE_user_mapping, "user_mapping"}, + {TLSEXT_TYPE_client_authz, "client_authz"}, + {TLSEXT_TYPE_server_authz, "server_authz"}, + {TLSEXT_TYPE_cert_type, "cert_type"}, + {TLSEXT_TYPE_supported_groups, "supported_groups"}, + {TLSEXT_TYPE_ec_point_formats, "ec_point_formats"}, + {TLSEXT_TYPE_srp, "srp"}, + {TLSEXT_TYPE_signature_algorithms, "signature_algorithms"}, + {TLSEXT_TYPE_use_srtp, "use_srtp"}, + {TLSEXT_TYPE_heartbeat, "tls_heartbeat"}, + {TLSEXT_TYPE_application_layer_protocol_negotiation, + "application_layer_protocol_negotiation"}, + {TLSEXT_TYPE_signed_certificate_timestamp, "signed_certificate_timestamps"}, + {TLSEXT_TYPE_padding, "padding"}, + {TLSEXT_TYPE_encrypt_then_mac, "encrypt_then_mac"}, + {TLSEXT_TYPE_extended_master_secret, "extended_master_secret"}, + {TLSEXT_TYPE_session_ticket, "session_ticket"}, + {TLSEXT_TYPE_psk, "psk"}, + {TLSEXT_TYPE_early_data, "early_data"}, + {TLSEXT_TYPE_supported_versions, "supported_versions"}, + {TLSEXT_TYPE_cookie, "cookie_ext"}, + {TLSEXT_TYPE_psk_kex_modes, "psk_key_exchange_modes"}, + {TLSEXT_TYPE_certificate_authorities, "certificate_authorities"}, + {TLSEXT_TYPE_post_handshake_auth, "post_handshake_auth"}, + {TLSEXT_TYPE_signature_algorithms_cert, "signature_algorithms_cert"}, + {TLSEXT_TYPE_key_share, "key_share"}, + {TLSEXT_TYPE_renegotiate, "renegotiate"}, +# ifndef OPENSSL_NO_NEXTPROTONEG + {TLSEXT_TYPE_next_proto_neg, "next_proto_neg"}, +# endif +}; + +static const ssl_trace_tbl ssl_groups_tbl[] = { + {1, "sect163k1 (K-163)"}, + {2, "sect163r1"}, + {3, "sect163r2 (B-163)"}, + {4, "sect193r1"}, + {5, "sect193r2"}, + {6, "sect233k1 (K-233)"}, + {7, "sect233r1 (B-233)"}, + {8, "sect239k1"}, + {9, "sect283k1 (K-283)"}, + {10, "sect283r1 (B-283)"}, + {11, "sect409k1 (K-409)"}, + {12, "sect409r1 (B-409)"}, + {13, "sect571k1 (K-571)"}, + {14, "sect571r1 (B-571)"}, + {15, "secp160k1"}, + {16, "secp160r1"}, + {17, "secp160r2"}, + {18, "secp192k1"}, + {19, "secp192r1 (P-192)"}, + {20, "secp224k1"}, + {21, "secp224r1 (P-224)"}, + {22, "secp256k1"}, + {23, "secp256r1 (P-256)"}, + {24, "secp384r1 (P-384)"}, + {25, "secp521r1 (P-521)"}, + {26, "brainpoolP256r1"}, + {27, "brainpoolP384r1"}, + {28, "brainpoolP512r1"}, + {29, "ecdh_x25519"}, + {30, "ecdh_x448"}, + {256, "ffdhe2048"}, + {257, "ffdhe3072"}, + {258, "ffdhe4096"}, + {259, "ffdhe6144"}, + {260, "ffdhe8192"}, + {0xFF01, "arbitrary_explicit_prime_curves"}, + {0xFF02, "arbitrary_explicit_char2_curves"} +}; + +static const ssl_trace_tbl ssl_point_tbl[] = { + {0, "uncompressed"}, + {1, "ansiX962_compressed_prime"}, + {2, "ansiX962_compressed_char2"} +}; + +static const ssl_trace_tbl ssl_mfl_tbl[] = { + {0, "disabled"}, + {1, "max_fragment_length := 2^9 (512 bytes)"}, + {2, "max_fragment_length := 2^10 (1024 bytes)"}, + {3, "max_fragment_length := 2^11 (2048 bytes)"}, + {4, "max_fragment_length := 2^12 (4096 bytes)"} +}; + +static const ssl_trace_tbl ssl_sigalg_tbl[] = { + {TLSEXT_SIGALG_ecdsa_secp256r1_sha256, "ecdsa_secp256r1_sha256"}, + {TLSEXT_SIGALG_ecdsa_secp384r1_sha384, "ecdsa_secp384r1_sha384"}, + {TLSEXT_SIGALG_ecdsa_secp521r1_sha512, "ecdsa_secp521r1_sha512"}, + {TLSEXT_SIGALG_ecdsa_sha224, "ecdsa_sha224"}, + {TLSEXT_SIGALG_ed25519, "ed25519"}, + {TLSEXT_SIGALG_ed448, "ed448"}, + {TLSEXT_SIGALG_ecdsa_sha1, "ecdsa_sha1"}, + {TLSEXT_SIGALG_rsa_pss_rsae_sha256, "rsa_pss_rsae_sha256"}, + {TLSEXT_SIGALG_rsa_pss_rsae_sha384, "rsa_pss_rsae_sha384"}, + {TLSEXT_SIGALG_rsa_pss_rsae_sha512, "rsa_pss_rsae_sha512"}, + {TLSEXT_SIGALG_rsa_pss_pss_sha256, "rsa_pss_pss_sha256"}, + {TLSEXT_SIGALG_rsa_pss_pss_sha384, "rsa_pss_pss_sha384"}, + {TLSEXT_SIGALG_rsa_pss_pss_sha512, "rsa_pss_pss_sha512"}, + {TLSEXT_SIGALG_rsa_pkcs1_sha256, "rsa_pkcs1_sha256"}, + {TLSEXT_SIGALG_rsa_pkcs1_sha384, "rsa_pkcs1_sha384"}, + {TLSEXT_SIGALG_rsa_pkcs1_sha512, "rsa_pkcs1_sha512"}, + {TLSEXT_SIGALG_rsa_pkcs1_sha224, "rsa_pkcs1_sha224"}, + {TLSEXT_SIGALG_rsa_pkcs1_sha1, "rsa_pkcs1_sha1"}, + {TLSEXT_SIGALG_dsa_sha256, "dsa_sha256"}, + {TLSEXT_SIGALG_dsa_sha384, "dsa_sha384"}, + {TLSEXT_SIGALG_dsa_sha512, "dsa_sha512"}, + {TLSEXT_SIGALG_dsa_sha224, "dsa_sha224"}, + {TLSEXT_SIGALG_dsa_sha1, "dsa_sha1"}, + {TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256, "gost2012_256"}, + {TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512, "gost2012_512"}, + {TLSEXT_SIGALG_gostr34102001_gostr3411, "gost2001_gost94"}, +}; + +static const ssl_trace_tbl ssl_ctype_tbl[] = { + {1, "rsa_sign"}, + {2, "dss_sign"}, + {3, "rsa_fixed_dh"}, + {4, "dss_fixed_dh"}, + {5, "rsa_ephemeral_dh"}, + {6, "dss_ephemeral_dh"}, + {20, "fortezza_dms"}, + {64, "ecdsa_sign"}, + {65, "rsa_fixed_ecdh"}, + {66, "ecdsa_fixed_ecdh"} +}; + +static const ssl_trace_tbl ssl_psk_kex_modes_tbl[] = { + {TLSEXT_KEX_MODE_KE, "psk_ke"}, + {TLSEXT_KEX_MODE_KE_DHE, "psk_dhe_ke"} +}; + +static const ssl_trace_tbl ssl_key_update_tbl[] = { + {SSL_KEY_UPDATE_NOT_REQUESTED, "update_not_requested"}, + {SSL_KEY_UPDATE_REQUESTED, "update_requested"} +}; + +static void ssl_print_hex(BIO *bio, int indent, const char *name, + const unsigned char *msg, size_t msglen) +{ + size_t i; + + BIO_indent(bio, indent, 80); + BIO_printf(bio, "%s (len=%d): ", name, (int)msglen); + for (i = 0; i < msglen; i++) + BIO_printf(bio, "%02X", msg[i]); + BIO_puts(bio, "\n"); +} + +static int ssl_print_hexbuf(BIO *bio, int indent, const char *name, size_t nlen, + const unsigned char **pmsg, size_t *pmsglen) +{ + size_t blen; + const unsigned char *p = *pmsg; + + if (*pmsglen < nlen) + return 0; + blen = p[0]; + if (nlen > 1) + blen = (blen << 8) | p[1]; + if (*pmsglen < nlen + blen) + return 0; + p += nlen; + ssl_print_hex(bio, indent, name, p, blen); + *pmsg += blen + nlen; + *pmsglen -= blen + nlen; + return 1; +} + +static int ssl_print_version(BIO *bio, int indent, const char *name, + const unsigned char **pmsg, size_t *pmsglen, + unsigned int *version) +{ + int vers; + + if (*pmsglen < 2) + return 0; + vers = ((*pmsg)[0] << 8) | (*pmsg)[1]; + if (version != NULL) + *version = vers; + BIO_indent(bio, indent, 80); + BIO_printf(bio, "%s=0x%x (%s)\n", + name, vers, ssl_trace_str(vers, ssl_version_tbl)); + *pmsg += 2; + *pmsglen -= 2; + return 1; +} + +static int ssl_print_random(BIO *bio, int indent, + const unsigned char **pmsg, size_t *pmsglen) +{ + unsigned int tm; + const unsigned char *p = *pmsg; + + if (*pmsglen < 32) + return 0; + tm = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; + p += 4; + BIO_indent(bio, indent, 80); + BIO_puts(bio, "Random:\n"); + BIO_indent(bio, indent + 2, 80); + BIO_printf(bio, "gmt_unix_time=0x%08X\n", tm); + ssl_print_hex(bio, indent + 2, "random_bytes", p, 28); + *pmsg += 32; + *pmsglen -= 32; + return 1; +} + +static int ssl_print_signature(BIO *bio, int indent, const SSL *ssl, + const unsigned char **pmsg, size_t *pmsglen) +{ + if (*pmsglen < 2) + return 0; + if (SSL_USE_SIGALGS(ssl)) { + const unsigned char *p = *pmsg; + unsigned int sigalg = (p[0] << 8) | p[1]; + + BIO_indent(bio, indent, 80); + BIO_printf(bio, "Signature Algorithm: %s (0x%04x)\n", + ssl_trace_str(sigalg, ssl_sigalg_tbl), sigalg); + *pmsg += 2; + *pmsglen -= 2; + } + return ssl_print_hexbuf(bio, indent, "Signature", 2, pmsg, pmsglen); +} + +static int ssl_print_extension(BIO *bio, int indent, int server, + unsigned char mt, int extype, + const unsigned char *ext, size_t extlen) +{ + size_t xlen, share_len; + unsigned int sigalg; + uint32_t max_early_data; + + BIO_indent(bio, indent, 80); + BIO_printf(bio, "extension_type=%s(%d), length=%d\n", + ssl_trace_str(extype, ssl_exts_tbl), extype, (int)extlen); + switch (extype) { + case TLSEXT_TYPE_max_fragment_length: + if (extlen < 1) + return 0; + xlen = extlen; + return ssl_trace_list(bio, indent + 2, ext, xlen, 1, ssl_mfl_tbl); + + case TLSEXT_TYPE_ec_point_formats: + if (extlen < 1) + return 0; + xlen = ext[0]; + if (extlen != xlen + 1) + return 0; + return ssl_trace_list(bio, indent + 2, ext + 1, xlen, 1, ssl_point_tbl); + + case TLSEXT_TYPE_supported_groups: + if (extlen < 2) + return 0; + xlen = (ext[0] << 8) | ext[1]; + if (extlen != xlen + 2) + return 0; + return ssl_trace_list(bio, indent + 2, ext + 2, xlen, 2, ssl_groups_tbl); + case TLSEXT_TYPE_application_layer_protocol_negotiation: + if (extlen < 2) + return 0; + xlen = (ext[0] << 8) | ext[1]; + if (extlen != xlen + 2) + return 0; + ext += 2; + while (xlen > 0) { + size_t plen = *ext++; + + if (plen + 1 > xlen) + return 0; + BIO_indent(bio, indent + 2, 80); + BIO_write(bio, ext, plen); + BIO_puts(bio, "\n"); + ext += plen; + xlen -= plen + 1; + } + return 1; + + case TLSEXT_TYPE_signature_algorithms: + + if (extlen < 2) + return 0; + xlen = (ext[0] << 8) | ext[1]; + if (extlen != xlen + 2) + return 0; + if (xlen & 1) + return 0; + ext += 2; + while (xlen > 0) { + BIO_indent(bio, indent + 2, 80); + sigalg = (ext[0] << 8) | ext[1]; + BIO_printf(bio, "%s (0x%04x)\n", + ssl_trace_str(sigalg, ssl_sigalg_tbl), sigalg); + xlen -= 2; + ext += 2; + } + break; + + case TLSEXT_TYPE_renegotiate: + if (extlen < 1) + return 0; + xlen = ext[0]; + if (xlen + 1 != extlen) + return 0; + ext++; + if (xlen) { + if (server) { + if (xlen & 1) + return 0; + xlen >>= 1; + } + ssl_print_hex(bio, indent + 4, "client_verify_data", ext, xlen); + if (server) { + ext += xlen; + ssl_print_hex(bio, indent + 4, "server_verify_data", ext, xlen); + } + } else { + BIO_indent(bio, indent + 4, 80); + BIO_puts(bio, "\n"); + } + break; + + case TLSEXT_TYPE_heartbeat: + return 0; + + case TLSEXT_TYPE_session_ticket: + if (extlen != 0) + ssl_print_hex(bio, indent + 4, "ticket", ext, extlen); + break; + + case TLSEXT_TYPE_key_share: + if (server && extlen == 2) { + int group_id; + + /* We assume this is an HRR, otherwise this is an invalid key_share */ + group_id = (ext[0] << 8) | ext[1]; + BIO_indent(bio, indent + 4, 80); + BIO_printf(bio, "NamedGroup: %s (%d)\n", + ssl_trace_str(group_id, ssl_groups_tbl), group_id); + break; + } + if (extlen < 2) + return 0; + if (server) { + xlen = extlen; + } else { + xlen = (ext[0] << 8) | ext[1]; + if (extlen != xlen + 2) + return 0; + ext += 2; + } + for (; xlen > 0; ext += share_len, xlen -= share_len) { + int group_id; + + if (xlen < 4) + return 0; + group_id = (ext[0] << 8) | ext[1]; + share_len = (ext[2] << 8) | ext[3]; + ext += 4; + xlen -= 4; + if (xlen < share_len) + return 0; + BIO_indent(bio, indent + 4, 80); + BIO_printf(bio, "NamedGroup: %s (%d)\n", + ssl_trace_str(group_id, ssl_groups_tbl), group_id); + ssl_print_hex(bio, indent + 4, "key_exchange: ", ext, share_len); + } + break; + + case TLSEXT_TYPE_supported_versions: + if (server) { + int version; + + if (extlen != 2) + return 0; + version = (ext[0] << 8) | ext[1]; + BIO_indent(bio, indent + 4, 80); + BIO_printf(bio, "%s (%d)\n", + ssl_trace_str(version, ssl_version_tbl), version); + break; + } + if (extlen < 1) + return 0; + xlen = ext[0]; + if (extlen != xlen + 1) + return 0; + return ssl_trace_list(bio, indent + 2, ext + 1, xlen, 2, + ssl_version_tbl); + + case TLSEXT_TYPE_psk_kex_modes: + if (extlen < 1) + return 0; + xlen = ext[0]; + if (extlen != xlen + 1) + return 0; + return ssl_trace_list(bio, indent + 2, ext + 1, xlen, 1, + ssl_psk_kex_modes_tbl); + + case TLSEXT_TYPE_early_data: + if (mt != SSL3_MT_NEWSESSION_TICKET) + break; + if (extlen != 4) + return 0; + max_early_data = (ext[0] << 24) | (ext[1] << 16) | (ext[2] << 8) + | ext[3]; + BIO_indent(bio, indent + 2, 80); + BIO_printf(bio, "max_early_data=%u\n", max_early_data); + break; + + default: + BIO_dump_indent(bio, (const char *)ext, extlen, indent + 2); + } + return 1; +} + +static int ssl_print_extensions(BIO *bio, int indent, int server, + unsigned char mt, const unsigned char **msgin, + size_t *msginlen) +{ + size_t extslen, msglen = *msginlen; + const unsigned char *msg = *msgin; + + BIO_indent(bio, indent, 80); + if (msglen == 0) { + BIO_puts(bio, "No extensions\n"); + return 1; + } + if (msglen < 2) + return 0; + extslen = (msg[0] << 8) | msg[1]; + msglen -= 2; + msg += 2; + if (extslen == 0) { + BIO_puts(bio, "No extensions\n"); + *msgin = msg; + *msginlen = msglen; + return 1; + } + if (extslen > msglen) + return 0; + BIO_printf(bio, "extensions, length = %d\n", (int)extslen); + msglen -= extslen; + while (extslen > 0) { + int extype; + size_t extlen; + if (extslen < 4) + return 0; + extype = (msg[0] << 8) | msg[1]; + extlen = (msg[2] << 8) | msg[3]; + if (extslen < extlen + 4) { + BIO_printf(bio, "extensions, extype = %d, extlen = %d\n", extype, + (int)extlen); + BIO_dump_indent(bio, (const char *)msg, extslen, indent + 2); + return 0; + } + msg += 4; + if (!ssl_print_extension(bio, indent + 2, server, mt, extype, msg, + extlen)) + return 0; + msg += extlen; + extslen -= extlen + 4; + } + + *msgin = msg; + *msginlen = msglen; + return 1; +} + +static int ssl_print_client_hello(BIO *bio, const SSL *ssl, int indent, + const unsigned char *msg, size_t msglen) +{ + size_t len; + unsigned int cs; + + if (!ssl_print_version(bio, indent, "client_version", &msg, &msglen, NULL)) + return 0; + if (!ssl_print_random(bio, indent, &msg, &msglen)) + return 0; + if (!ssl_print_hexbuf(bio, indent, "session_id", 1, &msg, &msglen)) + return 0; + if (SSL_IS_DTLS(ssl)) { + if (!ssl_print_hexbuf(bio, indent, "cookie", 1, &msg, &msglen)) + return 0; + } + if (msglen < 2) + return 0; + len = (msg[0] << 8) | msg[1]; + msg += 2; + msglen -= 2; + BIO_indent(bio, indent, 80); + BIO_printf(bio, "cipher_suites (len=%d)\n", (int)len); + if (msglen < len || len & 1) + return 0; + while (len > 0) { + cs = (msg[0] << 8) | msg[1]; + BIO_indent(bio, indent + 2, 80); + BIO_printf(bio, "{0x%02X, 0x%02X} %s\n", + msg[0], msg[1], ssl_trace_str(cs, ssl_ciphers_tbl)); + msg += 2; + msglen -= 2; + len -= 2; + } + if (msglen < 1) + return 0; + len = msg[0]; + msg++; + msglen--; + if (msglen < len) + return 0; + BIO_indent(bio, indent, 80); + BIO_printf(bio, "compression_methods (len=%d)\n", (int)len); + while (len > 0) { + BIO_indent(bio, indent + 2, 80); + BIO_printf(bio, "%s (0x%02X)\n", + ssl_trace_str(msg[0], ssl_comp_tbl), msg[0]); + msg++; + msglen--; + len--; + } + if (!ssl_print_extensions(bio, indent, 0, SSL3_MT_CLIENT_HELLO, &msg, + &msglen)) + return 0; + return 1; +} + +static int dtls_print_hello_vfyrequest(BIO *bio, int indent, + const unsigned char *msg, size_t msglen) +{ + if (!ssl_print_version(bio, indent, "server_version", &msg, &msglen, NULL)) + return 0; + if (!ssl_print_hexbuf(bio, indent, "cookie", 1, &msg, &msglen)) + return 0; + return 1; +} + +static int ssl_print_server_hello(BIO *bio, int indent, + const unsigned char *msg, size_t msglen) +{ + unsigned int cs; + unsigned int vers; + + if (!ssl_print_version(bio, indent, "server_version", &msg, &msglen, &vers)) + return 0; + if (!ssl_print_random(bio, indent, &msg, &msglen)) + return 0; + if (vers != TLS1_3_VERSION + && !ssl_print_hexbuf(bio, indent, "session_id", 1, &msg, &msglen)) + return 0; + if (msglen < 2) + return 0; + cs = (msg[0] << 8) | msg[1]; + BIO_indent(bio, indent, 80); + BIO_printf(bio, "cipher_suite {0x%02X, 0x%02X} %s\n", + msg[0], msg[1], ssl_trace_str(cs, ssl_ciphers_tbl)); + msg += 2; + msglen -= 2; + if (vers != TLS1_3_VERSION) { + if (msglen < 1) + return 0; + BIO_indent(bio, indent, 80); + BIO_printf(bio, "compression_method: %s (0x%02X)\n", + ssl_trace_str(msg[0], ssl_comp_tbl), msg[0]); + msg++; + msglen--; + } + if (!ssl_print_extensions(bio, indent, 1, SSL3_MT_SERVER_HELLO, &msg, + &msglen)) + return 0; + return 1; +} + +static int ssl_get_keyex(const char **pname, const SSL *ssl) +{ + unsigned long alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey; + + if (alg_k & SSL_kRSA) { + *pname = "rsa"; + return SSL_kRSA; + } + if (alg_k & SSL_kDHE) { + *pname = "DHE"; + return SSL_kDHE; + } + if (alg_k & SSL_kECDHE) { + *pname = "ECDHE"; + return SSL_kECDHE; + } + if (alg_k & SSL_kPSK) { + *pname = "PSK"; + return SSL_kPSK; + } + if (alg_k & SSL_kRSAPSK) { + *pname = "RSAPSK"; + return SSL_kRSAPSK; + } + if (alg_k & SSL_kDHEPSK) { + *pname = "DHEPSK"; + return SSL_kDHEPSK; + } + if (alg_k & SSL_kECDHEPSK) { + *pname = "ECDHEPSK"; + return SSL_kECDHEPSK; + } + if (alg_k & SSL_kSRP) { + *pname = "SRP"; + return SSL_kSRP; + } + if (alg_k & SSL_kGOST) { + *pname = "GOST"; + return SSL_kGOST; + } + *pname = "UNKNOWN"; + return 0; +} + +static int ssl_print_client_keyex(BIO *bio, int indent, const SSL *ssl, + const unsigned char *msg, size_t msglen) +{ + const char *algname; + int id = ssl_get_keyex(&algname, ssl); + + BIO_indent(bio, indent, 80); + BIO_printf(bio, "KeyExchangeAlgorithm=%s\n", algname); + if (id & SSL_PSK) { + if (!ssl_print_hexbuf(bio, indent + 2, + "psk_identity", 2, &msg, &msglen)) + return 0; + } + switch (id) { + + case SSL_kRSA: + case SSL_kRSAPSK: + if (TLS1_get_version(ssl) == SSL3_VERSION) { + ssl_print_hex(bio, indent + 2, + "EncryptedPreMasterSecret", msg, msglen); + } else { + if (!ssl_print_hexbuf(bio, indent + 2, + "EncryptedPreMasterSecret", 2, &msg, &msglen)) + return 0; + } + break; + + case SSL_kDHE: + case SSL_kDHEPSK: + if (!ssl_print_hexbuf(bio, indent + 2, "dh_Yc", 2, &msg, &msglen)) + return 0; + break; + + case SSL_kECDHE: + case SSL_kECDHEPSK: + if (!ssl_print_hexbuf(bio, indent + 2, "ecdh_Yc", 1, &msg, &msglen)) + return 0; + break; + + } + + return !msglen; +} + +static int ssl_print_server_keyex(BIO *bio, int indent, const SSL *ssl, + const unsigned char *msg, size_t msglen) +{ + const char *algname; + int id = ssl_get_keyex(&algname, ssl); + + BIO_indent(bio, indent, 80); + BIO_printf(bio, "KeyExchangeAlgorithm=%s\n", algname); + if (id & SSL_PSK) { + if (!ssl_print_hexbuf(bio, indent + 2, + "psk_identity_hint", 2, &msg, &msglen)) + return 0; + } + switch (id) { + case SSL_kRSA: + + if (!ssl_print_hexbuf(bio, indent + 2, "rsa_modulus", 2, &msg, &msglen)) + return 0; + if (!ssl_print_hexbuf(bio, indent + 2, "rsa_exponent", 2, + &msg, &msglen)) + return 0; + break; + + case SSL_kDHE: + case SSL_kDHEPSK: + if (!ssl_print_hexbuf(bio, indent + 2, "dh_p", 2, &msg, &msglen)) + return 0; + if (!ssl_print_hexbuf(bio, indent + 2, "dh_g", 2, &msg, &msglen)) + return 0; + if (!ssl_print_hexbuf(bio, indent + 2, "dh_Ys", 2, &msg, &msglen)) + return 0; + break; + +# ifndef OPENSSL_NO_EC + case SSL_kECDHE: + case SSL_kECDHEPSK: + if (msglen < 1) + return 0; + BIO_indent(bio, indent + 2, 80); + if (msg[0] == EXPLICIT_PRIME_CURVE_TYPE) + BIO_puts(bio, "explicit_prime\n"); + else if (msg[0] == EXPLICIT_CHAR2_CURVE_TYPE) + BIO_puts(bio, "explicit_char2\n"); + else if (msg[0] == NAMED_CURVE_TYPE) { + int curve; + if (msglen < 3) + return 0; + curve = (msg[1] << 8) | msg[2]; + BIO_printf(bio, "named_curve: %s (%d)\n", + ssl_trace_str(curve, ssl_groups_tbl), curve); + msg += 3; + msglen -= 3; + if (!ssl_print_hexbuf(bio, indent + 2, "point", 1, &msg, &msglen)) + return 0; + } else { + BIO_printf(bio, "UNKNOWN CURVE PARAMETER TYPE %d\n", msg[0]); + return 0; + } + break; +# endif + + case SSL_kPSK: + case SSL_kRSAPSK: + break; + } + if (!(id & SSL_PSK)) + ssl_print_signature(bio, indent, ssl, &msg, &msglen); + return !msglen; +} + +static int ssl_print_certificate(BIO *bio, int indent, + const unsigned char **pmsg, size_t *pmsglen) +{ + size_t msglen = *pmsglen; + size_t clen; + X509 *x; + const unsigned char *p = *pmsg, *q; + + if (msglen < 3) + return 0; + clen = (p[0] << 16) | (p[1] << 8) | p[2]; + if (msglen < clen + 3) + return 0; + q = p + 3; + BIO_indent(bio, indent, 80); + BIO_printf(bio, "ASN.1Cert, length=%d", (int)clen); + x = d2i_X509(NULL, &q, clen); + if (!x) + BIO_puts(bio, "\n"); + else { + BIO_puts(bio, "\n------details-----\n"); + X509_print_ex(bio, x, XN_FLAG_ONELINE, 0); + PEM_write_bio_X509(bio, x); + /* Print certificate stuff */ + BIO_puts(bio, "------------------\n"); + X509_free(x); + } + if (q != p + 3 + clen) { + BIO_puts(bio, "\n"); + } + *pmsg += clen + 3; + *pmsglen -= clen + 3; + return 1; +} + +static int ssl_print_certificates(BIO *bio, const SSL *ssl, int server, + int indent, const unsigned char *msg, + size_t msglen) +{ + size_t clen; + + if (SSL_IS_TLS13(ssl) + && !ssl_print_hexbuf(bio, indent, "context", 1, &msg, &msglen)) + return 0; + + if (msglen < 3) + return 0; + clen = (msg[0] << 16) | (msg[1] << 8) | msg[2]; + if (msglen != clen + 3) + return 0; + msg += 3; + BIO_indent(bio, indent, 80); + BIO_printf(bio, "certificate_list, length=%d\n", (int)clen); + while (clen > 0) { + if (!ssl_print_certificate(bio, indent + 2, &msg, &clen)) + return 0; + if (!ssl_print_extensions(bio, indent + 2, server, SSL3_MT_CERTIFICATE, + &msg, &clen)) + return 0; + + } + return 1; +} + +static int ssl_print_cert_request(BIO *bio, int indent, const SSL *ssl, + const unsigned char *msg, size_t msglen) +{ + size_t xlen; + unsigned int sigalg; + + if (SSL_IS_TLS13(ssl)) { + if (!ssl_print_hexbuf(bio, indent, "request_context", 1, &msg, &msglen)) + return 0; + if (!ssl_print_extensions(bio, indent, 1, + SSL3_MT_CERTIFICATE_REQUEST, &msg, &msglen)) + return 0; + return 1; + } else { + if (msglen < 1) + return 0; + xlen = msg[0]; + if (msglen < xlen + 1) + return 0; + msg++; + BIO_indent(bio, indent, 80); + BIO_printf(bio, "certificate_types (len=%d)\n", (int)xlen); + if (!ssl_trace_list(bio, indent + 2, msg, xlen, 1, ssl_ctype_tbl)) + return 0; + msg += xlen; + msglen -= xlen + 1; + } + if (SSL_USE_SIGALGS(ssl)) { + if (msglen < 2) + return 0; + xlen = (msg[0] << 8) | msg[1]; + if (msglen < xlen + 2 || (xlen & 1)) + return 0; + msg += 2; + msglen -= xlen + 2; + BIO_indent(bio, indent, 80); + BIO_printf(bio, "signature_algorithms (len=%d)\n", (int)xlen); + while (xlen > 0) { + BIO_indent(bio, indent + 2, 80); + sigalg = (msg[0] << 8) | msg[1]; + BIO_printf(bio, "%s (0x%04x)\n", + ssl_trace_str(sigalg, ssl_sigalg_tbl), sigalg); + xlen -= 2; + msg += 2; + } + msg += xlen; + } + + if (msglen < 2) + return 0; + xlen = (msg[0] << 8) | msg[1]; + BIO_indent(bio, indent, 80); + if (msglen < xlen + 2) + return 0; + msg += 2; + msglen -= 2 + xlen; + BIO_printf(bio, "certificate_authorities (len=%d)\n", (int)xlen); + while (xlen > 0) { + size_t dlen; + X509_NAME *nm; + const unsigned char *p; + if (xlen < 2) + return 0; + dlen = (msg[0] << 8) | msg[1]; + if (xlen < dlen + 2) + return 0; + msg += 2; + BIO_indent(bio, indent + 2, 80); + BIO_printf(bio, "DistinguishedName (len=%d): ", (int)dlen); + p = msg; + nm = d2i_X509_NAME(NULL, &p, dlen); + if (!nm) { + BIO_puts(bio, "\n"); + } else { + X509_NAME_print_ex(bio, nm, 0, XN_FLAG_ONELINE); + BIO_puts(bio, "\n"); + X509_NAME_free(nm); + } + xlen -= dlen + 2; + msg += dlen; + } + if (SSL_IS_TLS13(ssl)) { + if (!ssl_print_hexbuf(bio, indent, "request_extensions", 2, + &msg, &msglen)) + return 0; + } + return msglen == 0; +} + +static int ssl_print_ticket(BIO *bio, int indent, const SSL *ssl, + const unsigned char *msg, size_t msglen) +{ + unsigned int tick_life; + + if (msglen == 0) { + BIO_indent(bio, indent + 2, 80); + BIO_puts(bio, "No Ticket\n"); + return 1; + } + if (msglen < 4) + return 0; + tick_life = (msg[0] << 24) | (msg[1] << 16) | (msg[2] << 8) | msg[3]; + msglen -= 4; + msg += 4; + BIO_indent(bio, indent + 2, 80); + BIO_printf(bio, "ticket_lifetime_hint=%u\n", tick_life); + if (SSL_IS_TLS13(ssl)) { + unsigned int ticket_age_add; + + if (msglen < 4) + return 0; + ticket_age_add = + (msg[0] << 24) | (msg[1] << 16) | (msg[2] << 8) | msg[3]; + msglen -= 4; + msg += 4; + BIO_indent(bio, indent + 2, 80); + BIO_printf(bio, "ticket_age_add=%u\n", ticket_age_add); + if (!ssl_print_hexbuf(bio, indent + 2, "ticket_nonce", 1, &msg, + &msglen)) + return 0; + } + if (!ssl_print_hexbuf(bio, indent + 2, "ticket", 2, &msg, &msglen)) + return 0; + if (SSL_IS_TLS13(ssl) + && !ssl_print_extensions(bio, indent + 2, 0, + SSL3_MT_NEWSESSION_TICKET, &msg, &msglen)) + return 0; + if (msglen) + return 0; + return 1; +} + +static int ssl_print_handshake(BIO *bio, const SSL *ssl, int server, + const unsigned char *msg, size_t msglen, + int indent) +{ + size_t hlen; + unsigned char htype; + + if (msglen < 4) + return 0; + htype = msg[0]; + hlen = (msg[1] << 16) | (msg[2] << 8) | msg[3]; + BIO_indent(bio, indent, 80); + BIO_printf(bio, "%s, Length=%d\n", + ssl_trace_str(htype, ssl_handshake_tbl), (int)hlen); + msg += 4; + msglen -= 4; + if (SSL_IS_DTLS(ssl)) { + if (msglen < 8) + return 0; + BIO_indent(bio, indent, 80); + BIO_printf(bio, "message_seq=%d, fragment_offset=%d, " + "fragment_length=%d\n", + (msg[0] << 8) | msg[1], + (msg[2] << 16) | (msg[3] << 8) | msg[4], + (msg[5] << 16) | (msg[6] << 8) | msg[7]); + msg += 8; + msglen -= 8; + } + if (msglen < hlen) + return 0; + switch (htype) { + case SSL3_MT_CLIENT_HELLO: + if (!ssl_print_client_hello(bio, ssl, indent + 2, msg, msglen)) + return 0; + break; + + case DTLS1_MT_HELLO_VERIFY_REQUEST: + if (!dtls_print_hello_vfyrequest(bio, indent + 2, msg, msglen)) + return 0; + break; + + case SSL3_MT_SERVER_HELLO: + if (!ssl_print_server_hello(bio, indent + 2, msg, msglen)) + return 0; + break; + + case SSL3_MT_SERVER_KEY_EXCHANGE: + if (!ssl_print_server_keyex(bio, indent + 2, ssl, msg, msglen)) + return 0; + break; + + case SSL3_MT_CLIENT_KEY_EXCHANGE: + if (!ssl_print_client_keyex(bio, indent + 2, ssl, msg, msglen)) + return 0; + break; + + case SSL3_MT_CERTIFICATE: + if (!ssl_print_certificates(bio, ssl, server, indent + 2, msg, msglen)) + return 0; + break; + + case SSL3_MT_CERTIFICATE_VERIFY: + if (!ssl_print_signature(bio, indent + 2, ssl, &msg, &msglen)) + return 0; + break; + + case SSL3_MT_CERTIFICATE_REQUEST: + if (!ssl_print_cert_request(bio, indent + 2, ssl, msg, msglen)) + return 0; + break; + + case SSL3_MT_FINISHED: + ssl_print_hex(bio, indent + 2, "verify_data", msg, msglen); + break; + + case SSL3_MT_SERVER_DONE: + if (msglen != 0) + ssl_print_hex(bio, indent + 2, "unexpected value", msg, msglen); + break; + + case SSL3_MT_NEWSESSION_TICKET: + if (!ssl_print_ticket(bio, indent + 2, ssl, msg, msglen)) + return 0; + break; + + case SSL3_MT_ENCRYPTED_EXTENSIONS: + if (!ssl_print_extensions(bio, indent + 2, 1, + SSL3_MT_ENCRYPTED_EXTENSIONS, &msg, &msglen)) + return 0; + break; + + case SSL3_MT_KEY_UPDATE: + if (msglen != 1) { + ssl_print_hex(bio, indent + 2, "unexpected value", msg, msglen); + return 0; + } + if (!ssl_trace_list(bio, indent + 2, msg, msglen, 1, + ssl_key_update_tbl)) + return 0; + break; + + default: + BIO_indent(bio, indent + 2, 80); + BIO_puts(bio, "Unsupported, hex dump follows:\n"); + BIO_dump_indent(bio, (const char *)msg, msglen, indent + 4); + } + return 1; +} + +void SSL_trace(int write_p, int version, int content_type, + const void *buf, size_t msglen, SSL *ssl, void *arg) +{ + const unsigned char *msg = buf; + BIO *bio = arg; + + switch (content_type) { + case SSL3_RT_HEADER: + { + int hvers; + + /* avoid overlapping with length at the end of buffer */ + if (msglen < (size_t)(SSL_IS_DTLS(ssl) ? + DTLS1_RT_HEADER_LENGTH : SSL3_RT_HEADER_LENGTH)) { + BIO_puts(bio, write_p ? "Sent" : "Received"); + ssl_print_hex(bio, 0, " too short message", msg, msglen); + break; + } + hvers = msg[1] << 8 | msg[2]; + BIO_puts(bio, write_p ? "Sent" : "Received"); + BIO_printf(bio, " Record\nHeader:\n Version = %s (0x%x)\n", + ssl_trace_str(hvers, ssl_version_tbl), hvers); + if (SSL_IS_DTLS(ssl)) { + BIO_printf(bio, + " epoch=%d, sequence_number=%04x%04x%04x\n", + (msg[3] << 8 | msg[4]), + (msg[5] << 8 | msg[6]), + (msg[7] << 8 | msg[8]), (msg[9] << 8 | msg[10])); + } + + BIO_printf(bio, " Content Type = %s (%d)\n Length = %d", + ssl_trace_str(msg[0], ssl_content_tbl), msg[0], + msg[msglen - 2] << 8 | msg[msglen - 1]); + } + break; + + case SSL3_RT_INNER_CONTENT_TYPE: + BIO_printf(bio, " Inner Content Type = %s (%d)", + ssl_trace_str(msg[0], ssl_content_tbl), msg[0]); + break; + + case SSL3_RT_HANDSHAKE: + if (!ssl_print_handshake(bio, ssl, ssl->server ? write_p : !write_p, + msg, msglen, 4)) + BIO_printf(bio, "Message length parse error!\n"); + break; + + case SSL3_RT_CHANGE_CIPHER_SPEC: + if (msglen == 1 && msg[0] == 1) + BIO_puts(bio, " change_cipher_spec (1)\n"); + else + ssl_print_hex(bio, 4, "unknown value", msg, msglen); + break; + + case SSL3_RT_ALERT: + if (msglen != 2) + BIO_puts(bio, " Illegal Alert Length\n"); + else { + BIO_printf(bio, " Level=%s(%d), description=%s(%d)\n", + SSL_alert_type_string_long(msg[0] << 8), + msg[0], SSL_alert_desc_string_long(msg[1]), msg[1]); + } + + } + + BIO_puts(bio, "\n"); +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/tls13_enc.c b/trunk/3rdparty/openssl-1.1-fit/ssl/tls13_enc.c new file mode 100644 index 000000000..1f956e61e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/tls13_enc.c @@ -0,0 +1,833 @@ +/* + * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "ssl_locl.h" +#include "internal/cryptlib.h" +#include +#include + +#define TLS13_MAX_LABEL_LEN 249 + +/* Always filled with zeros */ +static const unsigned char default_zeros[EVP_MAX_MD_SIZE]; + +/* + * Given a |secret|; a |label| of length |labellen|; and |data| of length + * |datalen| (e.g. typically a hash of the handshake messages), derive a new + * secret |outlen| bytes long and store it in the location pointed to be |out|. + * The |data| value may be zero length. Any errors will be treated as fatal if + * |fatal| is set. Returns 1 on success 0 on failure. + */ +int tls13_hkdf_expand(SSL *s, const EVP_MD *md, const unsigned char *secret, + const unsigned char *label, size_t labellen, + const unsigned char *data, size_t datalen, + unsigned char *out, size_t outlen, int fatal) +{ + static const unsigned char label_prefix[] = "tls13 "; + EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL); + int ret; + size_t hkdflabellen; + size_t hashlen; + /* + * 2 bytes for length of derived secret + 1 byte for length of combined + * prefix and label + bytes for the label itself + 1 byte length of hash + * + bytes for the hash itself + */ + unsigned char hkdflabel[sizeof(uint16_t) + sizeof(uint8_t) + + + (sizeof(label_prefix) - 1) + TLS13_MAX_LABEL_LEN + + 1 + EVP_MAX_MD_SIZE]; + WPACKET pkt; + + if (pctx == NULL) + return 0; + + if (labellen > TLS13_MAX_LABEL_LEN) { + if (fatal) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_HKDF_EXPAND, + ERR_R_INTERNAL_ERROR); + } else { + /* + * Probably we have been called from SSL_export_keying_material(), + * or SSL_export_keying_material_early(). + */ + SSLerr(SSL_F_TLS13_HKDF_EXPAND, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL); + } + EVP_PKEY_CTX_free(pctx); + return 0; + } + + hashlen = EVP_MD_size(md); + + if (!WPACKET_init_static_len(&pkt, hkdflabel, sizeof(hkdflabel), 0) + || !WPACKET_put_bytes_u16(&pkt, outlen) + || !WPACKET_start_sub_packet_u8(&pkt) + || !WPACKET_memcpy(&pkt, label_prefix, sizeof(label_prefix) - 1) + || !WPACKET_memcpy(&pkt, label, labellen) + || !WPACKET_close(&pkt) + || !WPACKET_sub_memcpy_u8(&pkt, data, (data == NULL) ? 0 : datalen) + || !WPACKET_get_total_written(&pkt, &hkdflabellen) + || !WPACKET_finish(&pkt)) { + EVP_PKEY_CTX_free(pctx); + WPACKET_cleanup(&pkt); + if (fatal) + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_HKDF_EXPAND, + ERR_R_INTERNAL_ERROR); + else + SSLerr(SSL_F_TLS13_HKDF_EXPAND, ERR_R_INTERNAL_ERROR); + return 0; + } + + ret = EVP_PKEY_derive_init(pctx) <= 0 + || EVP_PKEY_CTX_hkdf_mode(pctx, EVP_PKEY_HKDEF_MODE_EXPAND_ONLY) + <= 0 + || EVP_PKEY_CTX_set_hkdf_md(pctx, md) <= 0 + || EVP_PKEY_CTX_set1_hkdf_key(pctx, secret, hashlen) <= 0 + || EVP_PKEY_CTX_add1_hkdf_info(pctx, hkdflabel, hkdflabellen) <= 0 + || EVP_PKEY_derive(pctx, out, &outlen) <= 0; + + EVP_PKEY_CTX_free(pctx); + + if (ret != 0) { + if (fatal) + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_HKDF_EXPAND, + ERR_R_INTERNAL_ERROR); + else + SSLerr(SSL_F_TLS13_HKDF_EXPAND, ERR_R_INTERNAL_ERROR); + } + + return ret == 0; +} + +/* + * Given a |secret| generate a |key| of length |keylen| bytes. Returns 1 on + * success 0 on failure. + */ +int tls13_derive_key(SSL *s, const EVP_MD *md, const unsigned char *secret, + unsigned char *key, size_t keylen) +{ + static const unsigned char keylabel[] = "key"; + + return tls13_hkdf_expand(s, md, secret, keylabel, sizeof(keylabel) - 1, + NULL, 0, key, keylen, 1); +} + +/* + * Given a |secret| generate an |iv| of length |ivlen| bytes. Returns 1 on + * success 0 on failure. + */ +int tls13_derive_iv(SSL *s, const EVP_MD *md, const unsigned char *secret, + unsigned char *iv, size_t ivlen) +{ + static const unsigned char ivlabel[] = "iv"; + + return tls13_hkdf_expand(s, md, secret, ivlabel, sizeof(ivlabel) - 1, + NULL, 0, iv, ivlen, 1); +} + +int tls13_derive_finishedkey(SSL *s, const EVP_MD *md, + const unsigned char *secret, + unsigned char *fin, size_t finlen) +{ + static const unsigned char finishedlabel[] = "finished"; + + return tls13_hkdf_expand(s, md, secret, finishedlabel, + sizeof(finishedlabel) - 1, NULL, 0, fin, finlen, 1); +} + +/* + * Given the previous secret |prevsecret| and a new input secret |insecret| of + * length |insecretlen|, generate a new secret and store it in the location + * pointed to by |outsecret|. Returns 1 on success 0 on failure. + */ +int tls13_generate_secret(SSL *s, const EVP_MD *md, + const unsigned char *prevsecret, + const unsigned char *insecret, + size_t insecretlen, + unsigned char *outsecret) +{ + size_t mdlen, prevsecretlen; + int mdleni; + int ret; + EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL); + static const char derived_secret_label[] = "derived"; + unsigned char preextractsec[EVP_MAX_MD_SIZE]; + + if (pctx == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_GENERATE_SECRET, + ERR_R_INTERNAL_ERROR); + return 0; + } + + mdleni = EVP_MD_size(md); + /* Ensure cast to size_t is safe */ + if (!ossl_assert(mdleni >= 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_GENERATE_SECRET, + ERR_R_INTERNAL_ERROR); + return 0; + } + mdlen = (size_t)mdleni; + + if (insecret == NULL) { + insecret = default_zeros; + insecretlen = mdlen; + } + if (prevsecret == NULL) { + prevsecret = default_zeros; + prevsecretlen = 0; + } else { + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); + unsigned char hash[EVP_MAX_MD_SIZE]; + + /* The pre-extract derive step uses a hash of no messages */ + if (mctx == NULL + || EVP_DigestInit_ex(mctx, md, NULL) <= 0 + || EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_GENERATE_SECRET, + ERR_R_INTERNAL_ERROR); + EVP_MD_CTX_free(mctx); + EVP_PKEY_CTX_free(pctx); + return 0; + } + EVP_MD_CTX_free(mctx); + + /* Generate the pre-extract secret */ + if (!tls13_hkdf_expand(s, md, prevsecret, + (unsigned char *)derived_secret_label, + sizeof(derived_secret_label) - 1, hash, mdlen, + preextractsec, mdlen, 1)) { + /* SSLfatal() already called */ + EVP_PKEY_CTX_free(pctx); + return 0; + } + + prevsecret = preextractsec; + prevsecretlen = mdlen; + } + + ret = EVP_PKEY_derive_init(pctx) <= 0 + || EVP_PKEY_CTX_hkdf_mode(pctx, EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY) + <= 0 + || EVP_PKEY_CTX_set_hkdf_md(pctx, md) <= 0 + || EVP_PKEY_CTX_set1_hkdf_key(pctx, insecret, insecretlen) <= 0 + || EVP_PKEY_CTX_set1_hkdf_salt(pctx, prevsecret, prevsecretlen) + <= 0 + || EVP_PKEY_derive(pctx, outsecret, &mdlen) + <= 0; + + if (ret != 0) + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_GENERATE_SECRET, + ERR_R_INTERNAL_ERROR); + + EVP_PKEY_CTX_free(pctx); + if (prevsecret == preextractsec) + OPENSSL_cleanse(preextractsec, mdlen); + return ret == 0; +} + +/* + * Given an input secret |insecret| of length |insecretlen| generate the + * handshake secret. This requires the early secret to already have been + * generated. Returns 1 on success 0 on failure. + */ +int tls13_generate_handshake_secret(SSL *s, const unsigned char *insecret, + size_t insecretlen) +{ + /* Calls SSLfatal() if required */ + return tls13_generate_secret(s, ssl_handshake_md(s), s->early_secret, + insecret, insecretlen, + (unsigned char *)&s->handshake_secret); +} + +/* + * Given the handshake secret |prev| of length |prevlen| generate the master + * secret and store its length in |*secret_size|. Returns 1 on success 0 on + * failure. + */ +int tls13_generate_master_secret(SSL *s, unsigned char *out, + unsigned char *prev, size_t prevlen, + size_t *secret_size) +{ + const EVP_MD *md = ssl_handshake_md(s); + + *secret_size = EVP_MD_size(md); + /* Calls SSLfatal() if required */ + return tls13_generate_secret(s, md, prev, NULL, 0, out); +} + +/* + * Generates the mac for the Finished message. Returns the length of the MAC or + * 0 on error. + */ +size_t tls13_final_finish_mac(SSL *s, const char *str, size_t slen, + unsigned char *out) +{ + const EVP_MD *md = ssl_handshake_md(s); + unsigned char hash[EVP_MAX_MD_SIZE]; + size_t hashlen, ret = 0; + EVP_PKEY *key = NULL; + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + + if (!ssl_handshake_hash(s, hash, sizeof(hash), &hashlen)) { + /* SSLfatal() already called */ + goto err; + } + + if (str == s->method->ssl3_enc->server_finished_label) { + key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, + s->server_finished_secret, hashlen); + } else if (SSL_IS_FIRST_HANDSHAKE(s)) { + key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, + s->client_finished_secret, hashlen); + } else { + unsigned char finsecret[EVP_MAX_MD_SIZE]; + + if (!tls13_derive_finishedkey(s, ssl_handshake_md(s), + s->client_app_traffic_secret, + finsecret, hashlen)) + goto err; + + key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, finsecret, + hashlen); + OPENSSL_cleanse(finsecret, sizeof(finsecret)); + } + + if (key == NULL + || ctx == NULL + || EVP_DigestSignInit(ctx, NULL, md, NULL, key) <= 0 + || EVP_DigestSignUpdate(ctx, hash, hashlen) <= 0 + || EVP_DigestSignFinal(ctx, out, &hashlen) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_FINAL_FINISH_MAC, + ERR_R_INTERNAL_ERROR); + goto err; + } + + ret = hashlen; + err: + EVP_PKEY_free(key); + EVP_MD_CTX_free(ctx); + return ret; +} + +/* + * There isn't really a key block in TLSv1.3, but we still need this function + * for initialising the cipher and hash. Returns 1 on success or 0 on failure. + */ +int tls13_setup_key_block(SSL *s) +{ + const EVP_CIPHER *c; + const EVP_MD *hash; + + s->session->cipher = s->s3->tmp.new_cipher; + if (!ssl_cipher_get_evp(s->session, &c, &hash, NULL, NULL, NULL, 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_SETUP_KEY_BLOCK, + SSL_R_CIPHER_OR_HASH_UNAVAILABLE); + return 0; + } + + s->s3->tmp.new_sym_enc = c; + s->s3->tmp.new_hash = hash; + + return 1; +} + +static int derive_secret_key_and_iv(SSL *s, int sending, const EVP_MD *md, + const EVP_CIPHER *ciph, + const unsigned char *insecret, + const unsigned char *hash, + const unsigned char *label, + size_t labellen, unsigned char *secret, + unsigned char *iv, EVP_CIPHER_CTX *ciph_ctx) +{ + unsigned char key[EVP_MAX_KEY_LENGTH]; + size_t ivlen, keylen, taglen; + int hashleni = EVP_MD_size(md); + size_t hashlen; + + /* Ensure cast to size_t is safe */ + if (!ossl_assert(hashleni >= 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DERIVE_SECRET_KEY_AND_IV, + ERR_R_EVP_LIB); + goto err; + } + hashlen = (size_t)hashleni; + + if (!tls13_hkdf_expand(s, md, insecret, label, labellen, hash, hashlen, + secret, hashlen, 1)) { + /* SSLfatal() already called */ + goto err; + } + + /* TODO(size_t): convert me */ + keylen = EVP_CIPHER_key_length(ciph); + if (EVP_CIPHER_mode(ciph) == EVP_CIPH_CCM_MODE) { + uint32_t algenc; + + ivlen = EVP_CCM_TLS_IV_LEN; + if (s->s3->tmp.new_cipher == NULL) { + /* We've not selected a cipher yet - we must be doing early data */ + algenc = s->session->cipher->algorithm_enc; + } else { + algenc = s->s3->tmp.new_cipher->algorithm_enc; + } + if (algenc & (SSL_AES128CCM8 | SSL_AES256CCM8)) + taglen = EVP_CCM8_TLS_TAG_LEN; + else + taglen = EVP_CCM_TLS_TAG_LEN; + } else { + ivlen = EVP_CIPHER_iv_length(ciph); + taglen = 0; + } + + if (!tls13_derive_key(s, md, secret, key, keylen) + || !tls13_derive_iv(s, md, secret, iv, ivlen)) { + /* SSLfatal() already called */ + goto err; + } + + if (EVP_CipherInit_ex(ciph_ctx, ciph, NULL, NULL, NULL, sending) <= 0 + || !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_IVLEN, ivlen, NULL) + || (taglen != 0 && !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_TAG, + taglen, NULL)) + || EVP_CipherInit_ex(ciph_ctx, NULL, NULL, key, NULL, -1) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DERIVE_SECRET_KEY_AND_IV, + ERR_R_EVP_LIB); + goto err; + } + + return 1; + err: + OPENSSL_cleanse(key, sizeof(key)); + return 0; +} + +int tls13_change_cipher_state(SSL *s, int which) +{ + static const unsigned char client_early_traffic[] = "c e traffic"; + static const unsigned char client_handshake_traffic[] = "c hs traffic"; + static const unsigned char client_application_traffic[] = "c ap traffic"; + static const unsigned char server_handshake_traffic[] = "s hs traffic"; + static const unsigned char server_application_traffic[] = "s ap traffic"; + static const unsigned char exporter_master_secret[] = "exp master"; + static const unsigned char resumption_master_secret[] = "res master"; + static const unsigned char early_exporter_master_secret[] = "e exp master"; + unsigned char *iv; + unsigned char secret[EVP_MAX_MD_SIZE]; + unsigned char hashval[EVP_MAX_MD_SIZE]; + unsigned char *hash = hashval; + unsigned char *insecret; + unsigned char *finsecret = NULL; + const char *log_label = NULL; + EVP_CIPHER_CTX *ciph_ctx; + size_t finsecretlen = 0; + const unsigned char *label; + size_t labellen, hashlen = 0; + int ret = 0; + const EVP_MD *md = NULL; + const EVP_CIPHER *cipher = NULL; + + if (which & SSL3_CC_READ) { + if (s->enc_read_ctx != NULL) { + EVP_CIPHER_CTX_reset(s->enc_read_ctx); + } else { + s->enc_read_ctx = EVP_CIPHER_CTX_new(); + if (s->enc_read_ctx == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE); + goto err; + } + } + ciph_ctx = s->enc_read_ctx; + iv = s->read_iv; + + RECORD_LAYER_reset_read_sequence(&s->rlayer); + } else { + s->statem.enc_write_state = ENC_WRITE_STATE_INVALID; + if (s->enc_write_ctx != NULL) { + EVP_CIPHER_CTX_reset(s->enc_write_ctx); + } else { + s->enc_write_ctx = EVP_CIPHER_CTX_new(); + if (s->enc_write_ctx == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE); + goto err; + } + } + ciph_ctx = s->enc_write_ctx; + iv = s->write_iv; + + RECORD_LAYER_reset_write_sequence(&s->rlayer); + } + + if (((which & SSL3_CC_CLIENT) && (which & SSL3_CC_WRITE)) + || ((which & SSL3_CC_SERVER) && (which & SSL3_CC_READ))) { + if (which & SSL3_CC_EARLY) { + EVP_MD_CTX *mdctx = NULL; + long handlen; + void *hdata; + unsigned int hashlenui; + const SSL_CIPHER *sslcipher = SSL_SESSION_get0_cipher(s->session); + + insecret = s->early_secret; + label = client_early_traffic; + labellen = sizeof(client_early_traffic) - 1; + log_label = CLIENT_EARLY_LABEL; + + handlen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata); + if (handlen <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS13_CHANGE_CIPHER_STATE, + SSL_R_BAD_HANDSHAKE_LENGTH); + goto err; + } + + if (s->early_data_state == SSL_EARLY_DATA_CONNECTING + && s->max_early_data > 0 + && s->session->ext.max_early_data == 0) { + /* + * If we are attempting to send early data, and we've decided to + * actually do it but max_early_data in s->session is 0 then we + * must be using an external PSK. + */ + if (!ossl_assert(s->psksession != NULL + && s->max_early_data == + s->psksession->ext.max_early_data)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS13_CHANGE_CIPHER_STATE, + ERR_R_INTERNAL_ERROR); + goto err; + } + sslcipher = SSL_SESSION_get0_cipher(s->psksession); + } + if (sslcipher == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS13_CHANGE_CIPHER_STATE, SSL_R_BAD_PSK); + goto err; + } + + /* + * We need to calculate the handshake digest using the digest from + * the session. We haven't yet selected our ciphersuite so we can't + * use ssl_handshake_md(). + */ + mdctx = EVP_MD_CTX_new(); + if (mdctx == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE); + goto err; + } + cipher = EVP_get_cipherbynid(SSL_CIPHER_get_cipher_nid(sslcipher)); + md = ssl_md(sslcipher->algorithm2); + if (md == NULL || !EVP_DigestInit_ex(mdctx, md, NULL) + || !EVP_DigestUpdate(mdctx, hdata, handlen) + || !EVP_DigestFinal_ex(mdctx, hashval, &hashlenui)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR); + EVP_MD_CTX_free(mdctx); + goto err; + } + hashlen = hashlenui; + EVP_MD_CTX_free(mdctx); + + if (!tls13_hkdf_expand(s, md, insecret, + early_exporter_master_secret, + sizeof(early_exporter_master_secret) - 1, + hashval, hashlen, + s->early_exporter_master_secret, hashlen, + 1)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR); + goto err; + } + + if (!ssl_log_secret(s, EARLY_EXPORTER_SECRET_LABEL, + s->early_exporter_master_secret, hashlen)) { + /* SSLfatal() already called */ + goto err; + } + } else if (which & SSL3_CC_HANDSHAKE) { + insecret = s->handshake_secret; + finsecret = s->client_finished_secret; + finsecretlen = EVP_MD_size(ssl_handshake_md(s)); + label = client_handshake_traffic; + labellen = sizeof(client_handshake_traffic) - 1; + log_label = CLIENT_HANDSHAKE_LABEL; + /* + * The handshake hash used for the server read/client write handshake + * traffic secret is the same as the hash for the server + * write/client read handshake traffic secret. However, if we + * processed early data then we delay changing the server + * read/client write cipher state until later, and the handshake + * hashes have moved on. Therefore we use the value saved earlier + * when we did the server write/client read change cipher state. + */ + hash = s->handshake_traffic_hash; + } else { + insecret = s->master_secret; + label = client_application_traffic; + labellen = sizeof(client_application_traffic) - 1; + log_label = CLIENT_APPLICATION_LABEL; + /* + * For this we only use the handshake hashes up until the server + * Finished hash. We do not include the client's Finished, which is + * what ssl_handshake_hash() would give us. Instead we use the + * previously saved value. + */ + hash = s->server_finished_hash; + } + } else { + /* Early data never applies to client-read/server-write */ + if (which & SSL3_CC_HANDSHAKE) { + insecret = s->handshake_secret; + finsecret = s->server_finished_secret; + finsecretlen = EVP_MD_size(ssl_handshake_md(s)); + label = server_handshake_traffic; + labellen = sizeof(server_handshake_traffic) - 1; + log_label = SERVER_HANDSHAKE_LABEL; + } else { + insecret = s->master_secret; + label = server_application_traffic; + labellen = sizeof(server_application_traffic) - 1; + log_label = SERVER_APPLICATION_LABEL; + } + } + + if (!(which & SSL3_CC_EARLY)) { + md = ssl_handshake_md(s); + cipher = s->s3->tmp.new_sym_enc; + if (!ssl3_digest_cached_records(s, 1) + || !ssl_handshake_hash(s, hashval, sizeof(hashval), &hashlen)) { + /* SSLfatal() already called */; + goto err; + } + } + + /* + * Save the hash of handshakes up to now for use when we calculate the + * client application traffic secret + */ + if (label == server_application_traffic) + memcpy(s->server_finished_hash, hashval, hashlen); + + if (label == server_handshake_traffic) + memcpy(s->handshake_traffic_hash, hashval, hashlen); + + if (label == client_application_traffic) { + /* + * We also create the resumption master secret, but this time use the + * hash for the whole handshake including the Client Finished + */ + if (!tls13_hkdf_expand(s, ssl_handshake_md(s), insecret, + resumption_master_secret, + sizeof(resumption_master_secret) - 1, + hashval, hashlen, s->resumption_master_secret, + hashlen, 1)) { + /* SSLfatal() already called */ + goto err; + } + } + + if (!derive_secret_key_and_iv(s, which & SSL3_CC_WRITE, md, cipher, + insecret, hash, label, labellen, secret, iv, + ciph_ctx)) { + /* SSLfatal() already called */ + goto err; + } + + if (label == server_application_traffic) { + memcpy(s->server_app_traffic_secret, secret, hashlen); + /* Now we create the exporter master secret */ + if (!tls13_hkdf_expand(s, ssl_handshake_md(s), insecret, + exporter_master_secret, + sizeof(exporter_master_secret) - 1, + hash, hashlen, s->exporter_master_secret, + hashlen, 1)) { + /* SSLfatal() already called */ + goto err; + } + + if (!ssl_log_secret(s, EXPORTER_SECRET_LABEL, s->exporter_master_secret, + hashlen)) { + /* SSLfatal() already called */ + goto err; + } + } else if (label == client_application_traffic) + memcpy(s->client_app_traffic_secret, secret, hashlen); + + if (!ssl_log_secret(s, log_label, secret, hashlen)) { + /* SSLfatal() already called */ + goto err; + } + + if (finsecret != NULL + && !tls13_derive_finishedkey(s, ssl_handshake_md(s), secret, + finsecret, finsecretlen)) { + /* SSLfatal() already called */ + goto err; + } + + if (!s->server && label == client_early_traffic) + s->statem.enc_write_state = ENC_WRITE_STATE_WRITE_PLAIN_ALERTS; + else + s->statem.enc_write_state = ENC_WRITE_STATE_VALID; + ret = 1; + err: + OPENSSL_cleanse(secret, sizeof(secret)); + return ret; +} + +int tls13_update_key(SSL *s, int sending) +{ + static const unsigned char application_traffic[] = "traffic upd"; + const EVP_MD *md = ssl_handshake_md(s); + size_t hashlen = EVP_MD_size(md); + unsigned char *insecret, *iv; + unsigned char secret[EVP_MAX_MD_SIZE]; + EVP_CIPHER_CTX *ciph_ctx; + int ret = 0; + + if (s->server == sending) + insecret = s->server_app_traffic_secret; + else + insecret = s->client_app_traffic_secret; + + if (sending) { + s->statem.enc_write_state = ENC_WRITE_STATE_INVALID; + iv = s->write_iv; + ciph_ctx = s->enc_write_ctx; + RECORD_LAYER_reset_write_sequence(&s->rlayer); + } else { + iv = s->read_iv; + ciph_ctx = s->enc_read_ctx; + RECORD_LAYER_reset_read_sequence(&s->rlayer); + } + + if (!derive_secret_key_and_iv(s, sending, ssl_handshake_md(s), + s->s3->tmp.new_sym_enc, insecret, NULL, + application_traffic, + sizeof(application_traffic) - 1, secret, iv, + ciph_ctx)) { + /* SSLfatal() already called */ + goto err; + } + + memcpy(insecret, secret, hashlen); + + s->statem.enc_write_state = ENC_WRITE_STATE_VALID; + ret = 1; + err: + OPENSSL_cleanse(secret, sizeof(secret)); + return ret; +} + +int tls13_alert_code(int code) +{ + /* There are 2 additional alerts in TLSv1.3 compared to TLSv1.2 */ + if (code == SSL_AD_MISSING_EXTENSION || code == SSL_AD_CERTIFICATE_REQUIRED) + return code; + + return tls1_alert_code(code); +} + +int tls13_export_keying_material(SSL *s, unsigned char *out, size_t olen, + const char *label, size_t llen, + const unsigned char *context, + size_t contextlen, int use_context) +{ + unsigned char exportsecret[EVP_MAX_MD_SIZE]; + static const unsigned char exporterlabel[] = "exporter"; + unsigned char hash[EVP_MAX_MD_SIZE], data[EVP_MAX_MD_SIZE]; + const EVP_MD *md = ssl_handshake_md(s); + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + unsigned int hashsize, datalen; + int ret = 0; + + if (ctx == NULL || !ossl_statem_export_allowed(s)) + goto err; + + if (!use_context) + contextlen = 0; + + if (EVP_DigestInit_ex(ctx, md, NULL) <= 0 + || EVP_DigestUpdate(ctx, context, contextlen) <= 0 + || EVP_DigestFinal_ex(ctx, hash, &hashsize) <= 0 + || EVP_DigestInit_ex(ctx, md, NULL) <= 0 + || EVP_DigestFinal_ex(ctx, data, &datalen) <= 0 + || !tls13_hkdf_expand(s, md, s->exporter_master_secret, + (const unsigned char *)label, llen, + data, datalen, exportsecret, hashsize, 0) + || !tls13_hkdf_expand(s, md, exportsecret, exporterlabel, + sizeof(exporterlabel) - 1, hash, hashsize, + out, olen, 0)) + goto err; + + ret = 1; + err: + EVP_MD_CTX_free(ctx); + return ret; +} + +int tls13_export_keying_material_early(SSL *s, unsigned char *out, size_t olen, + const char *label, size_t llen, + const unsigned char *context, + size_t contextlen) +{ + static const unsigned char exporterlabel[] = "exporter"; + unsigned char exportsecret[EVP_MAX_MD_SIZE]; + unsigned char hash[EVP_MAX_MD_SIZE], data[EVP_MAX_MD_SIZE]; + const EVP_MD *md; + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + unsigned int hashsize, datalen; + int ret = 0; + const SSL_CIPHER *sslcipher; + + if (ctx == NULL || !ossl_statem_export_early_allowed(s)) + goto err; + + if (!s->server && s->max_early_data > 0 + && s->session->ext.max_early_data == 0) + sslcipher = SSL_SESSION_get0_cipher(s->psksession); + else + sslcipher = SSL_SESSION_get0_cipher(s->session); + + md = ssl_md(sslcipher->algorithm2); + + /* + * Calculate the hash value and store it in |data|. The reason why + * the empty string is used is that the definition of TLS-Exporter + * is like so: + * + * TLS-Exporter(label, context_value, key_length) = + * HKDF-Expand-Label(Derive-Secret(Secret, label, ""), + * "exporter", Hash(context_value), key_length) + * + * Derive-Secret(Secret, Label, Messages) = + * HKDF-Expand-Label(Secret, Label, + * Transcript-Hash(Messages), Hash.length) + * + * Here Transcript-Hash is the cipher suite hash algorithm. + */ + if (EVP_DigestInit_ex(ctx, md, NULL) <= 0 + || EVP_DigestUpdate(ctx, context, contextlen) <= 0 + || EVP_DigestFinal_ex(ctx, hash, &hashsize) <= 0 + || EVP_DigestInit_ex(ctx, md, NULL) <= 0 + || EVP_DigestFinal_ex(ctx, data, &datalen) <= 0 + || !tls13_hkdf_expand(s, md, s->early_exporter_master_secret, + (const unsigned char *)label, llen, + data, datalen, exportsecret, hashsize, 0) + || !tls13_hkdf_expand(s, md, exportsecret, exporterlabel, + sizeof(exporterlabel) - 1, hash, hashsize, + out, olen, 0)) + goto err; + + ret = 1; + err: + EVP_MD_CTX_free(ctx); + return ret; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/ssl/tls_srp.c b/trunk/3rdparty/openssl-1.1-fit/ssl/tls_srp.c new file mode 100644 index 000000000..f94e46b4e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/ssl/tls_srp.c @@ -0,0 +1,456 @@ +/* + * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2004, EdelKey Project. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + * + * Originally written by Christophe Renou and Peter Sylvester, + * for the EdelKey project. + */ + +#include +#include +#include +#include "ssl_locl.h" + +#ifndef OPENSSL_NO_SRP +# include + +int SSL_CTX_SRP_CTX_free(struct ssl_ctx_st *ctx) +{ + if (ctx == NULL) + return 0; + OPENSSL_free(ctx->srp_ctx.login); + OPENSSL_free(ctx->srp_ctx.info); + BN_free(ctx->srp_ctx.N); + BN_free(ctx->srp_ctx.g); + BN_free(ctx->srp_ctx.s); + BN_free(ctx->srp_ctx.B); + BN_free(ctx->srp_ctx.A); + BN_free(ctx->srp_ctx.a); + BN_free(ctx->srp_ctx.b); + BN_free(ctx->srp_ctx.v); + memset(&ctx->srp_ctx, 0, sizeof(ctx->srp_ctx)); + ctx->srp_ctx.strength = SRP_MINIMAL_N; + return 1; +} + +int SSL_SRP_CTX_free(struct ssl_st *s) +{ + if (s == NULL) + return 0; + OPENSSL_free(s->srp_ctx.login); + OPENSSL_free(s->srp_ctx.info); + BN_free(s->srp_ctx.N); + BN_free(s->srp_ctx.g); + BN_free(s->srp_ctx.s); + BN_free(s->srp_ctx.B); + BN_free(s->srp_ctx.A); + BN_free(s->srp_ctx.a); + BN_free(s->srp_ctx.b); + BN_free(s->srp_ctx.v); + memset(&s->srp_ctx, 0, sizeof(s->srp_ctx)); + s->srp_ctx.strength = SRP_MINIMAL_N; + return 1; +} + +int SSL_SRP_CTX_init(struct ssl_st *s) +{ + SSL_CTX *ctx; + + if ((s == NULL) || ((ctx = s->ctx) == NULL)) + return 0; + + memset(&s->srp_ctx, 0, sizeof(s->srp_ctx)); + + s->srp_ctx.SRP_cb_arg = ctx->srp_ctx.SRP_cb_arg; + /* set client Hello login callback */ + s->srp_ctx.TLS_ext_srp_username_callback = + ctx->srp_ctx.TLS_ext_srp_username_callback; + /* set SRP N/g param callback for verification */ + s->srp_ctx.SRP_verify_param_callback = + ctx->srp_ctx.SRP_verify_param_callback; + /* set SRP client passwd callback */ + s->srp_ctx.SRP_give_srp_client_pwd_callback = + ctx->srp_ctx.SRP_give_srp_client_pwd_callback; + + s->srp_ctx.strength = ctx->srp_ctx.strength; + + if (((ctx->srp_ctx.N != NULL) && + ((s->srp_ctx.N = BN_dup(ctx->srp_ctx.N)) == NULL)) || + ((ctx->srp_ctx.g != NULL) && + ((s->srp_ctx.g = BN_dup(ctx->srp_ctx.g)) == NULL)) || + ((ctx->srp_ctx.s != NULL) && + ((s->srp_ctx.s = BN_dup(ctx->srp_ctx.s)) == NULL)) || + ((ctx->srp_ctx.B != NULL) && + ((s->srp_ctx.B = BN_dup(ctx->srp_ctx.B)) == NULL)) || + ((ctx->srp_ctx.A != NULL) && + ((s->srp_ctx.A = BN_dup(ctx->srp_ctx.A)) == NULL)) || + ((ctx->srp_ctx.a != NULL) && + ((s->srp_ctx.a = BN_dup(ctx->srp_ctx.a)) == NULL)) || + ((ctx->srp_ctx.v != NULL) && + ((s->srp_ctx.v = BN_dup(ctx->srp_ctx.v)) == NULL)) || + ((ctx->srp_ctx.b != NULL) && + ((s->srp_ctx.b = BN_dup(ctx->srp_ctx.b)) == NULL))) { + SSLerr(SSL_F_SSL_SRP_CTX_INIT, ERR_R_BN_LIB); + goto err; + } + if ((ctx->srp_ctx.login != NULL) && + ((s->srp_ctx.login = OPENSSL_strdup(ctx->srp_ctx.login)) == NULL)) { + SSLerr(SSL_F_SSL_SRP_CTX_INIT, ERR_R_INTERNAL_ERROR); + goto err; + } + if ((ctx->srp_ctx.info != NULL) && + ((s->srp_ctx.info = BUF_strdup(ctx->srp_ctx.info)) == NULL)) { + SSLerr(SSL_F_SSL_SRP_CTX_INIT, ERR_R_INTERNAL_ERROR); + goto err; + } + s->srp_ctx.srp_Mask = ctx->srp_ctx.srp_Mask; + + return 1; + err: + OPENSSL_free(s->srp_ctx.login); + OPENSSL_free(s->srp_ctx.info); + BN_free(s->srp_ctx.N); + BN_free(s->srp_ctx.g); + BN_free(s->srp_ctx.s); + BN_free(s->srp_ctx.B); + BN_free(s->srp_ctx.A); + BN_free(s->srp_ctx.a); + BN_free(s->srp_ctx.b); + BN_free(s->srp_ctx.v); + memset(&s->srp_ctx, 0, sizeof(s->srp_ctx)); + return 0; +} + +int SSL_CTX_SRP_CTX_init(struct ssl_ctx_st *ctx) +{ + if (ctx == NULL) + return 0; + + memset(&ctx->srp_ctx, 0, sizeof(ctx->srp_ctx)); + ctx->srp_ctx.strength = SRP_MINIMAL_N; + + return 1; +} + +/* server side */ +int SSL_srp_server_param_with_username(SSL *s, int *ad) +{ + unsigned char b[SSL_MAX_MASTER_KEY_LENGTH]; + int al; + + *ad = SSL_AD_UNKNOWN_PSK_IDENTITY; + if ((s->srp_ctx.TLS_ext_srp_username_callback != NULL) && + ((al = + s->srp_ctx.TLS_ext_srp_username_callback(s, ad, + s->srp_ctx.SRP_cb_arg)) != + SSL_ERROR_NONE)) + return al; + + *ad = SSL_AD_INTERNAL_ERROR; + if ((s->srp_ctx.N == NULL) || + (s->srp_ctx.g == NULL) || + (s->srp_ctx.s == NULL) || (s->srp_ctx.v == NULL)) + return SSL3_AL_FATAL; + + if (RAND_priv_bytes(b, sizeof(b)) <= 0) + return SSL3_AL_FATAL; + s->srp_ctx.b = BN_bin2bn(b, sizeof(b), NULL); + OPENSSL_cleanse(b, sizeof(b)); + + /* Calculate: B = (kv + g^b) % N */ + + return ((s->srp_ctx.B = + SRP_Calc_B(s->srp_ctx.b, s->srp_ctx.N, s->srp_ctx.g, + s->srp_ctx.v)) != + NULL) ? SSL_ERROR_NONE : SSL3_AL_FATAL; +} + +/* + * If the server just has the raw password, make up a verifier entry on the + * fly + */ +int SSL_set_srp_server_param_pw(SSL *s, const char *user, const char *pass, + const char *grp) +{ + SRP_gN *GN = SRP_get_default_gN(grp); + if (GN == NULL) + return -1; + s->srp_ctx.N = BN_dup(GN->N); + s->srp_ctx.g = BN_dup(GN->g); + BN_clear_free(s->srp_ctx.v); + s->srp_ctx.v = NULL; + BN_clear_free(s->srp_ctx.s); + s->srp_ctx.s = NULL; + if (!SRP_create_verifier_BN + (user, pass, &s->srp_ctx.s, &s->srp_ctx.v, GN->N, GN->g)) + return -1; + + return 1; +} + +int SSL_set_srp_server_param(SSL *s, const BIGNUM *N, const BIGNUM *g, + BIGNUM *sa, BIGNUM *v, char *info) +{ + if (N != NULL) { + if (s->srp_ctx.N != NULL) { + if (!BN_copy(s->srp_ctx.N, N)) { + BN_free(s->srp_ctx.N); + s->srp_ctx.N = NULL; + } + } else + s->srp_ctx.N = BN_dup(N); + } + if (g != NULL) { + if (s->srp_ctx.g != NULL) { + if (!BN_copy(s->srp_ctx.g, g)) { + BN_free(s->srp_ctx.g); + s->srp_ctx.g = NULL; + } + } else + s->srp_ctx.g = BN_dup(g); + } + if (sa != NULL) { + if (s->srp_ctx.s != NULL) { + if (!BN_copy(s->srp_ctx.s, sa)) { + BN_free(s->srp_ctx.s); + s->srp_ctx.s = NULL; + } + } else + s->srp_ctx.s = BN_dup(sa); + } + if (v != NULL) { + if (s->srp_ctx.v != NULL) { + if (!BN_copy(s->srp_ctx.v, v)) { + BN_free(s->srp_ctx.v); + s->srp_ctx.v = NULL; + } + } else + s->srp_ctx.v = BN_dup(v); + } + if (info != NULL) { + if (s->srp_ctx.info) + OPENSSL_free(s->srp_ctx.info); + if ((s->srp_ctx.info = BUF_strdup(info)) == NULL) + return -1; + } + + if (!(s->srp_ctx.N) || + !(s->srp_ctx.g) || !(s->srp_ctx.s) || !(s->srp_ctx.v)) + return -1; + + return 1; +} + +int srp_generate_server_master_secret(SSL *s) +{ + BIGNUM *K = NULL, *u = NULL; + int ret = -1, tmp_len = 0; + unsigned char *tmp = NULL; + + if (!SRP_Verify_A_mod_N(s->srp_ctx.A, s->srp_ctx.N)) + goto err; + if ((u = SRP_Calc_u(s->srp_ctx.A, s->srp_ctx.B, s->srp_ctx.N)) == NULL) + goto err; + if ((K = SRP_Calc_server_key(s->srp_ctx.A, s->srp_ctx.v, u, s->srp_ctx.b, + s->srp_ctx.N)) == NULL) + goto err; + + tmp_len = BN_num_bytes(K); + if ((tmp = OPENSSL_malloc(tmp_len)) == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_SRP_GENERATE_SERVER_MASTER_SECRET, ERR_R_MALLOC_FAILURE); + goto err; + } + BN_bn2bin(K, tmp); + /* Calls SSLfatal() as required */ + ret = ssl_generate_master_secret(s, tmp, tmp_len, 1); + err: + BN_clear_free(K); + BN_clear_free(u); + return ret; +} + +/* client side */ +int srp_generate_client_master_secret(SSL *s) +{ + BIGNUM *x = NULL, *u = NULL, *K = NULL; + int ret = -1, tmp_len = 0; + char *passwd = NULL; + unsigned char *tmp = NULL; + + /* + * Checks if b % n == 0 + */ + if (SRP_Verify_B_mod_N(s->srp_ctx.B, s->srp_ctx.N) == 0 + || (u = SRP_Calc_u(s->srp_ctx.A, s->srp_ctx.B, s->srp_ctx.N)) + == NULL + || s->srp_ctx.SRP_give_srp_client_pwd_callback == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET, ERR_R_INTERNAL_ERROR); + goto err; + } + if ((passwd = s->srp_ctx.SRP_give_srp_client_pwd_callback(s, + s->srp_ctx.SRP_cb_arg)) + == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET, + SSL_R_CALLBACK_FAILED); + goto err; + } + if ((x = SRP_Calc_x(s->srp_ctx.s, s->srp_ctx.login, passwd)) == NULL + || (K = SRP_Calc_client_key(s->srp_ctx.N, s->srp_ctx.B, + s->srp_ctx.g, x, + s->srp_ctx.a, u)) == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET, ERR_R_INTERNAL_ERROR); + goto err; + } + + tmp_len = BN_num_bytes(K); + if ((tmp = OPENSSL_malloc(tmp_len)) == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET, ERR_R_MALLOC_FAILURE); + goto err; + } + BN_bn2bin(K, tmp); + /* Calls SSLfatal() as required */ + ret = ssl_generate_master_secret(s, tmp, tmp_len, 1); + err: + BN_clear_free(K); + BN_clear_free(x); + if (passwd != NULL) + OPENSSL_clear_free(passwd, strlen(passwd)); + BN_clear_free(u); + return ret; +} + +int srp_verify_server_param(SSL *s) +{ + SRP_CTX *srp = &s->srp_ctx; + /* + * Sanity check parameters: we can quickly check B % N == 0 by checking B + * != 0 since B < N + */ + if (BN_ucmp(srp->g, srp->N) >= 0 || BN_ucmp(srp->B, srp->N) >= 0 + || BN_is_zero(srp->B)) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SRP_VERIFY_SERVER_PARAM, + SSL_R_BAD_DATA); + return 0; + } + + if (BN_num_bits(srp->N) < srp->strength) { + SSLfatal(s, SSL_AD_INSUFFICIENT_SECURITY, SSL_F_SRP_VERIFY_SERVER_PARAM, + SSL_R_INSUFFICIENT_SECURITY); + return 0; + } + + if (srp->SRP_verify_param_callback) { + if (srp->SRP_verify_param_callback(s, srp->SRP_cb_arg) <= 0) { + SSLfatal(s, SSL_AD_INSUFFICIENT_SECURITY, + SSL_F_SRP_VERIFY_SERVER_PARAM, + SSL_R_CALLBACK_FAILED); + return 0; + } + } else if (!SRP_check_known_gN_param(srp->g, srp->N)) { + SSLfatal(s, SSL_AD_INSUFFICIENT_SECURITY, SSL_F_SRP_VERIFY_SERVER_PARAM, + SSL_R_INSUFFICIENT_SECURITY); + return 0; + } + + return 1; +} + +int SRP_Calc_A_param(SSL *s) +{ + unsigned char rnd[SSL_MAX_MASTER_KEY_LENGTH]; + + if (RAND_priv_bytes(rnd, sizeof(rnd)) <= 0) + return 0; + s->srp_ctx.a = BN_bin2bn(rnd, sizeof(rnd), s->srp_ctx.a); + OPENSSL_cleanse(rnd, sizeof(rnd)); + + if (!(s->srp_ctx.A = SRP_Calc_A(s->srp_ctx.a, s->srp_ctx.N, s->srp_ctx.g))) + return 0; + + return 1; +} + +BIGNUM *SSL_get_srp_g(SSL *s) +{ + if (s->srp_ctx.g != NULL) + return s->srp_ctx.g; + return s->ctx->srp_ctx.g; +} + +BIGNUM *SSL_get_srp_N(SSL *s) +{ + if (s->srp_ctx.N != NULL) + return s->srp_ctx.N; + return s->ctx->srp_ctx.N; +} + +char *SSL_get_srp_username(SSL *s) +{ + if (s->srp_ctx.login != NULL) + return s->srp_ctx.login; + return s->ctx->srp_ctx.login; +} + +char *SSL_get_srp_userinfo(SSL *s) +{ + if (s->srp_ctx.info != NULL) + return s->srp_ctx.info; + return s->ctx->srp_ctx.info; +} + +# define tls1_ctx_ctrl ssl3_ctx_ctrl +# define tls1_ctx_callback_ctrl ssl3_ctx_callback_ctrl + +int SSL_CTX_set_srp_username(SSL_CTX *ctx, char *name) +{ + return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_USERNAME, 0, name); +} + +int SSL_CTX_set_srp_password(SSL_CTX *ctx, char *password) +{ + return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_PASSWORD, 0, password); +} + +int SSL_CTX_set_srp_strength(SSL_CTX *ctx, int strength) +{ + return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_STRENGTH, strength, + NULL); +} + +int SSL_CTX_set_srp_verify_param_callback(SSL_CTX *ctx, + int (*cb) (SSL *, void *)) +{ + return tls1_ctx_callback_ctrl(ctx, SSL_CTRL_SET_SRP_VERIFY_PARAM_CB, + (void (*)(void))cb); +} + +int SSL_CTX_set_srp_cb_arg(SSL_CTX *ctx, void *arg) +{ + return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_SRP_ARG, 0, arg); +} + +int SSL_CTX_set_srp_username_callback(SSL_CTX *ctx, + int (*cb) (SSL *, int *, void *)) +{ + return tls1_ctx_callback_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB, + (void (*)(void))cb); +} + +int SSL_CTX_set_srp_client_pwd_callback(SSL_CTX *ctx, + char *(*cb) (SSL *, void *)) +{ + return tls1_ctx_callback_ctrl(ctx, SSL_CTRL_SET_SRP_GIVE_CLIENT_PWD_CB, + (void (*)(void))cb); +} + +#endif diff --git a/trunk/3rdparty/openssl-1.1-fit/tools/build.info b/trunk/3rdparty/openssl-1.1-fit/tools/build.info new file mode 100644 index 000000000..059e58234 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/tools/build.info @@ -0,0 +1,7 @@ +{- our $c_rehash_name = + $config{target} =~ /^(VC|vms)-/ ? "c_rehash.pl" : "c_rehash"; + "" -} +IF[{- !$disabled{apps} -}] + SCRIPTS={- $c_rehash_name -} + SOURCE[{- $c_rehash_name -}]=c_rehash.in +ENDIF diff --git a/trunk/3rdparty/openssl-1.1-fit/tools/c_rehash.in b/trunk/3rdparty/openssl-1.1-fit/tools/c_rehash.in new file mode 100644 index 000000000..421fd8920 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/tools/c_rehash.in @@ -0,0 +1,231 @@ +#!{- $config{HASHBANGPERL} -} + +# {- join("\n# ", @autowarntext) -} +# Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# Perl c_rehash script, scan all files in a directory +# and add symbolic links to their hash values. + +my $dir = {- quotify1($config{openssldir}) -}; +my $prefix = {- quotify1($config{prefix}) -}; + +my $errorcount = 0; +my $openssl = $ENV{OPENSSL} || "openssl"; +my $pwd; +my $x509hash = "-subject_hash"; +my $crlhash = "-hash"; +my $verbose = 0; +my $symlink_exists=eval {symlink("",""); 1}; +my $removelinks = 1; + +## Parse flags. +while ( $ARGV[0] =~ /^-/ ) { + my $flag = shift @ARGV; + last if ( $flag eq '--'); + if ( $flag eq '-old') { + $x509hash = "-subject_hash_old"; + $crlhash = "-hash_old"; + } elsif ( $flag eq '-h' || $flag eq '-help' ) { + help(); + } elsif ( $flag eq '-n' ) { + $removelinks = 0; + } elsif ( $flag eq '-v' ) { + $verbose++; + } + else { + print STDERR "Usage error; try -h.\n"; + exit 1; + } +} + +sub help { + print "Usage: c_rehash [-old] [-h] [-help] [-v] [dirs...]\n"; + print " -old use old-style digest\n"; + print " -h or -help print this help text\n"; + print " -v print files removed and linked\n"; + exit 0; +} + +eval "require Cwd"; +if (defined(&Cwd::getcwd)) { + $pwd=Cwd::getcwd(); +} else { + $pwd=`pwd`; + chomp($pwd); +} + +# DOS/Win32 or Unix delimiter? Prefix our installdir, then search. +my $path_delim = ($pwd =~ /^[a-z]\:/i) ? ';' : ':'; +$ENV{PATH} = "$prefix/bin" . ($ENV{PATH} ? $path_delim . $ENV{PATH} : ""); + +if (! -x $openssl) { + my $found = 0; + foreach (split /$path_delim/, $ENV{PATH}) { + if (-x "$_/$openssl") { + $found = 1; + $openssl = "$_/$openssl"; + last; + } + } + if ($found == 0) { + print STDERR "c_rehash: rehashing skipped ('openssl' program not available)\n"; + exit 0; + } +} + +if (@ARGV) { + @dirlist = @ARGV; +} elsif ($ENV{SSL_CERT_DIR}) { + @dirlist = split /$path_delim/, $ENV{SSL_CERT_DIR}; +} else { + $dirlist[0] = "$dir/certs"; +} + +if (-d $dirlist[0]) { + chdir $dirlist[0]; + $openssl="$pwd/$openssl" if (!-x $openssl); + chdir $pwd; +} + +foreach (@dirlist) { + if (-d $_ ) { + if ( -w $_) { + hash_dir($_); + } else { + print "Skipping $_, can't write\n"; + $errorcount++; + } + } +} +exit($errorcount); + +sub hash_dir { + my %hashlist; + print "Doing $_[0]\n"; + chdir $_[0]; + opendir(DIR, "."); + my @flist = sort readdir(DIR); + closedir DIR; + if ( $removelinks ) { + # Delete any existing symbolic links + foreach (grep {/^[\da-f]+\.r{0,1}\d+$/} @flist) { + if (-l $_) { + print "unlink $_" if $verbose; + unlink $_ || warn "Can't unlink $_, $!\n"; + } + } + } + FILE: foreach $fname (grep {/\.(pem)|(crt)|(cer)|(crl)$/} @flist) { + # Check to see if certificates and/or CRLs present. + my ($cert, $crl) = check_file($fname); + if (!$cert && !$crl) { + print STDERR "WARNING: $fname does not contain a certificate or CRL: skipping\n"; + next; + } + link_hash_cert($fname) if ($cert); + link_hash_crl($fname) if ($crl); + } +} + +sub check_file { + my ($is_cert, $is_crl) = (0,0); + my $fname = $_[0]; + open IN, $fname; + while() { + if (/^-----BEGIN (.*)-----/) { + my $hdr = $1; + if ($hdr =~ /^(X509 |TRUSTED |)CERTIFICATE$/) { + $is_cert = 1; + last if ($is_crl); + } elsif ($hdr eq "X509 CRL") { + $is_crl = 1; + last if ($is_cert); + } + } + } + close IN; + return ($is_cert, $is_crl); +} + + +# Link a certificate to its subject name hash value, each hash is of +# the form . where n is an integer. If the hash value already exists +# then we need to up the value of n, unless its a duplicate in which +# case we skip the link. We check for duplicates by comparing the +# certificate fingerprints + +sub link_hash_cert { + my $fname = $_[0]; + $fname =~ s/'/'\\''/g; + my ($hash, $fprint) = `"$openssl" x509 $x509hash -fingerprint -noout -in "$fname"`; + chomp $hash; + chomp $fprint; + $fprint =~ s/^.*=//; + $fprint =~ tr/://d; + my $suffix = 0; + # Search for an unused hash filename + while(exists $hashlist{"$hash.$suffix"}) { + # Hash matches: if fingerprint matches its a duplicate cert + if ($hashlist{"$hash.$suffix"} eq $fprint) { + print STDERR "WARNING: Skipping duplicate certificate $fname\n"; + return; + } + $suffix++; + } + $hash .= ".$suffix"; + if ($symlink_exists) { + print "link $fname -> $hash\n" if $verbose; + symlink $fname, $hash || warn "Can't symlink, $!"; + } else { + print "copy $fname -> $hash\n" if $verbose; + if (open($in, "<", $fname)) { + if (open($out,">", $hash)) { + print $out $_ while (<$in>); + close $out; + } else { + warn "can't open $hash for write, $!"; + } + close $in; + } else { + warn "can't open $fname for read, $!"; + } + } + $hashlist{$hash} = $fprint; +} + +# Same as above except for a CRL. CRL links are of the form .r + +sub link_hash_crl { + my $fname = $_[0]; + $fname =~ s/'/'\\''/g; + my ($hash, $fprint) = `"$openssl" crl $crlhash -fingerprint -noout -in '$fname'`; + chomp $hash; + chomp $fprint; + $fprint =~ s/^.*=//; + $fprint =~ tr/://d; + my $suffix = 0; + # Search for an unused hash filename + while(exists $hashlist{"$hash.r$suffix"}) { + # Hash matches: if fingerprint matches its a duplicate cert + if ($hashlist{"$hash.r$suffix"} eq $fprint) { + print STDERR "WARNING: Skipping duplicate CRL $fname\n"; + return; + } + $suffix++; + } + $hash .= ".r$suffix"; + if ($symlink_exists) { + print "link $fname -> $hash\n" if $verbose; + symlink $fname, $hash || warn "Can't symlink, $!"; + } else { + print "cp $fname -> $hash\n" if $verbose; + system ("cp", $fname, $hash); + warn "Can't copy, $!" if ($? >> 8) != 0; + } + $hashlist{$hash} = $fprint; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/util/add-depends.pl b/trunk/3rdparty/openssl-1.1-fit/util/add-depends.pl new file mode 100644 index 000000000..55d56b761 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/add-depends.pl @@ -0,0 +1,288 @@ +#! /usr/bin/env perl +# Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use strict; +use warnings; + +use lib '.'; +use configdata; + +use File::Spec::Functions qw(:DEFAULT rel2abs); +use File::Compare qw(compare_text); +use feature 'state'; + +# When using stat() on Windows, we can get it to perform better by avoid some +# data. This doesn't affect the mtime field, so we're not losing anything... +${^WIN32_SLOPPY_STAT} = 1; + +my $debug = $ENV{ADD_DEPENDS_DEBUG}; +my $buildfile = $config{build_file}; +my $build_mtime = (stat($buildfile))[9]; +my $rebuild = 0; +my $depext = $target{dep_extension} || ".d"; +my @depfiles = + sort + grep { + # This grep has side effects. Not only does if check the existence + # of the dependency file given in $_, but it also checks if it's + # newer than the build file, and if it is, sets $rebuild. + my @st = stat($_); + $rebuild = 1 if @st && $st[9] > $build_mtime; + scalar @st > 0; # Determines the grep result + } + map { (my $x = $_) =~ s|\.o$|$depext|; $x; } + ( ( grep { $unified_info{sources}->{$_}->[0] =~ /\.cc?$/ } + keys %{$unified_info{sources}} ), + ( grep { $unified_info{shared_sources}->{$_}->[0] =~ /\.cc?$/ } + keys %{$unified_info{shared_sources}} ) ); + +exit 0 unless $rebuild; + +# Ok, primary checks are done, time to do some real work + +my $producer = shift @ARGV; +die "Producer not given\n" unless $producer; + +my $srcdir = $config{sourcedir}; +my $blddir = $config{builddir}; +my $abs_srcdir = rel2abs($srcdir); +my $abs_blddir = rel2abs($blddir); + +# Convenient cache of absolute to relative map. We start with filling it +# with mappings for the known generated header files. They are relative to +# the current working directory, so that's an easy task. +# NOTE: there's more than C header files that are generated. They will also +# generate entries in this map. We could of course deal with C header files +# only, but in case we decide to handle more than just C files in the future, +# we already have the mechanism in place here. +# NOTE2: we lower case the index to make it searchable without regard for +# character case. That could seem dangerous, but as long as we don't have +# files we depend on in the same directory that only differ by character case, +# we're fine. +my %depconv_cache = + map { catfile($abs_blddir, $_) => $_ } + keys %{$unified_info{generate}}; + +my %procedures = ( + 'gcc' => undef, # gcc style dependency files needs no mods + 'makedepend' => + sub { + # makedepend, in its infinite wisdom, wants to have the object file + # in the same directory as the source file. This doesn't work too + # well with out-of-source-tree builds, so we must resort to tricks + # to get things right. Fortunately, the .d files are always placed + # parallel with the object files, so all we need to do is construct + # the object file name from the dep file name. + (my $objfile = shift) =~ s|\.d$|.o|i; + my $line = shift; + + # Discard comments + return undef if $line =~ /^(#.*|\s*)$/; + + # Remove the original object file + $line =~ s|^.*\.o: | |; + # Also, remove any dependency that starts with a /, because those + # are typically system headers + $line =~ s/\s+\/(\\.|\S)*//g; + # Finally, discard all empty lines + return undef if $line =~ /^\s*$/; + + # All we got now is a dependency, just shave off surrounding spaces + $line =~ s/^\s+//; + $line =~ s/\s+$//; + return ($objfile, $line); + }, + 'VMS C' => + sub { + state $abs_srcdir_shaved = undef; + state $srcdir_shaved = undef; + + unless (defined $abs_srcdir_shaved) { + ($abs_srcdir_shaved = $abs_srcdir) =~ s|[>\]]$||; + ($srcdir_shaved = $srcdir) =~ s|[>\]]$||; + } + + # current versions of DEC / Compaq / HP / VSI C strips away all + # directory information from the object file, so we must insert it + # back. To make life simpler, we simply replace it with the + # corresponding .D file that's had its extension changed. Since + # .D files are always written parallel to the object files, we + # thereby get the directory information for free. + (my $objfile = shift) =~ s|\.D$|.OBJ|i; + my $line = shift; + + # Shave off the target. + # + # The pattern for target and dependencies will always take this + # form: + # + # target SPACE : SPACE deps + # + # This is so a volume delimiter (a : without any spaces around it) + # won't get mixed up with the target / deps delimiter. We use this + # to easily identify what needs to be removed. + m|\s:\s|; $line = $'; + + # We know that VMS has system header files in text libraries, + # extension .TLB. We also know that our header files aren't stored + # in text libraries. Finally, we know that VMS C produces exactly + # one dependency per line, so we simply discard any line ending with + # .TLB. + return undef if /\.TLB\s*$/; + + # All we got now is a dependency, just shave off surrounding spaces + $line =~ s/^\s+//; + $line =~ s/\s+$//; + + # VMS C gives us absolute paths, always. Let's see if we can + # make them relative instead. + $line = canonpath($line); + + unless (defined $depconv_cache{$line}) { + my $dep = $line; + # Since we have already pre-populated the cache with + # mappings for generated headers, we only need to deal + # with the source tree. + if ($dep =~ s|^\Q$abs_srcdir_shaved\E([\.>\]])?|$srcdir_shaved$1|i) { + $depconv_cache{$line} = $dep; + } + } + return ($objfile, $depconv_cache{$line}) + if defined $depconv_cache{$line}; + print STDERR "DEBUG[VMS C]: ignoring $objfile <- $line\n" + if $debug; + + return undef; + }, + 'VC' => + sub { + # For the moment, we only support Visual C on native Windows, or + # compatible compilers. With those, the flags /Zs /showIncludes + # give us the necessary output to be able to create dependencies + # that nmake (or any 'make' implementation) should be able to read, + # with a bit of help. The output we're interested in looks like + # this (it always starts the same) + # + # Note: including file: {whatever header file} + # + # Since there's no object file name at all in that information, + # we must construct it ourselves. + + (my $objfile = shift) =~ s|\.d$|.obj|i; + my $line = shift; + + # There are also other lines mixed in, for example compiler + # warnings, so we simply discard anything that doesn't start with + # the Note: + + if (/^Note: including file: */) { + (my $tail = $') =~ s/\s*\R$//; + + # VC gives us absolute paths for all include files, so to + # remove system header dependencies, we need to check that + # they don't match $abs_srcdir or $abs_blddir. + $tail = canonpath($tail); + + unless (defined $depconv_cache{$tail}) { + my $dep = $tail; + # Since we have already pre-populated the cache with + # mappings for generated headers, we only need to deal + # with the source tree. + if ($dep =~ s|^\Q$abs_srcdir\E\\|\$(SRCDIR)\\|i) { + $depconv_cache{$tail} = $dep; + } + } + return ($objfile, '"'.$depconv_cache{$tail}.'"') + if defined $depconv_cache{$tail}; + print STDERR "DEBUG[VC]: ignoring $objfile <- $tail\n" + if $debug; + } + + return undef; + }, +); +my %continuations = ( + 'gcc' => undef, + 'makedepend' => "\\", + 'VMS C' => "-", + 'VC' => "\\", +); + +die "Producer unrecognised: $producer\n" + unless exists $procedures{$producer} && exists $continuations{$producer}; + +my $procedure = $procedures{$producer}; +my $continuation = $continuations{$producer}; + +my $buildfile_new = "$buildfile-$$"; + +my %collect = (); +if (defined $procedure) { + foreach my $depfile (@depfiles) { + open IDEP,$depfile or die "Trying to read $depfile: $!\n"; + while () { + s|\R$||; # The better chomp + my ($target, $deps) = $procedure->($depfile, $_); + $collect{$target}->{$deps} = 1 if defined $target; + } + close IDEP; + } +} + +open IBF, $buildfile or die "Trying to read $buildfile: $!\n"; +open OBF, '>', $buildfile_new or die "Trying to write $buildfile_new: $!\n"; +while () { + last if /^# DO NOT DELETE THIS LINE/; + print OBF or die "$!\n"; +} +close IBF; + +print OBF "# DO NOT DELETE THIS LINE -- make depend depends on it.\n"; + +if (defined $procedure) { + foreach my $target (sort keys %collect) { + my $prefix = $target . ' :'; + my @deps = sort keys %{$collect{$target}}; + + while (@deps) { + my $buf = $prefix; + $prefix = ''; + + while (@deps && ($buf eq '' + || length($buf) + length($deps[0]) <= 77)) { + $buf .= ' ' . shift @deps; + } + $buf .= ' '.$continuation if @deps; + + print OBF $buf,"\n" or die "Trying to print: $!\n" + } + } +} else { + foreach my $depfile (@depfiles) { + open IDEP,$depfile or die "Trying to read $depfile: $!\n"; + while () { + print OBF or die "Trying to print: $!\n"; + } + close IDEP; + } +} + +close OBF; + +if (compare_text($buildfile_new, $buildfile) != 0) { + rename $buildfile_new, $buildfile + or die "Trying to rename $buildfile_new -> $buildfile: $!\n"; +} + +END { + # On VMS, we want to remove all generations of this file, in case there + # are more than one, so we loop. + if (defined $buildfile_new) { + while (unlink $buildfile_new) {} + } +} diff --git a/trunk/3rdparty/openssl-1.1-fit/util/build.info b/trunk/3rdparty/openssl-1.1-fit/util/build.info new file mode 100644 index 000000000..609be5166 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/build.info @@ -0,0 +1,8 @@ +IF[{- $target{build_scheme}->[1] eq "VMS" -}] + SCRIPTS_NO_INST=local_shlib.com unlocal_shlib.com + SOURCE[local_shlib.com]=local_shlib.com.in + SOURCE[unlocal_shlib.com]=unlocal_shlib.com.in +ELSIF[{- $target{build_scheme}->[1] eq "unix" -}] + SCRIPTS_NO_INST=shlib_wrap.sh + SOURCE[shlib_wrap.sh]=shlib_wrap.sh.in +ENDIF diff --git a/trunk/3rdparty/openssl-1.1-fit/util/check-malloc-errs b/trunk/3rdparty/openssl-1.1-fit/util/check-malloc-errs new file mode 100755 index 000000000..1e632407c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/check-malloc-errs @@ -0,0 +1,16 @@ +#! /bin/sh +# Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +( + pcregrep -rnM 'OPENSSL_.?alloc.*\n.*if.*NULL.*\n.*return' crypto ssl + pcregrep -rnM 'if.*OPENSSL_.?alloc.*NULL.*\n.*.*return' crypto ssl +) | tee /tmp/out$$ +X=0 +test -s /tmp/out$$ && X=1 +rm /tmp/out$$ +exit $X diff --git a/trunk/3rdparty/openssl-1.1-fit/util/ck_errf.pl b/trunk/3rdparty/openssl-1.1-fit/util/ck_errf.pl new file mode 100755 index 000000000..539736db0 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/ck_errf.pl @@ -0,0 +1,152 @@ +#! /usr/bin/env perl +# Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# This is just a quick script to scan for cases where the 'error' +# function name in a XXXerr() macro is wrong. +# +# Run in the top level by going +# perl util/ck_errf.pl */*.c */*/*.c +# + +use strict; +use warnings; + +my $config; +my $err_strict = 0; +my $debug = 0; +my $internal = 0; + +sub help +{ + print STDERR <<"EOF"; +mkerr.pl [options] [files...] + +Options: + + -conf FILE Use the named config file FILE instead of the default. + + -debug Verbose output debugging on stderr. + + -internal Generate code that is to be built as part of OpenSSL itself. + Also scans internal list of files. + + -strict If any error was found, fail with exit code 1, otherwise 0. + + -help Show this help text. + + ... Additional arguments are added to the file list to scan, + if '-internal' was NOT specified on the command line. + +EOF +} + +while ( @ARGV ) { + my $arg = $ARGV[0]; + last unless $arg =~ /-.*/; + $arg = $1 if $arg =~ /-(-.*)/; + if ( $arg eq "-conf" ) { + $config = $ARGV[1]; + shift @ARGV; + } elsif ( $arg eq "-debug" ) { + $debug = 1; + } elsif ( $arg eq "-internal" ) { + $internal = 1; + } elsif ( $arg eq "-strict" ) { + $err_strict = 1; + } elsif ( $arg =~ /-*h(elp)?/ ) { + &help(); + exit; + } elsif ( $arg =~ /-.*/ ) { + die "Unknown option $arg; use -h for help.\n"; + } + shift @ARGV; +} + +my @source; +if ( $internal ) { + die "Extra parameters given.\n" if @ARGV; + $config = "crypto/err/openssl.ec" unless defined $config; + @source = ( glob('crypto/*.c'), glob('crypto/*/*.c'), + glob('ssl/*.c'), glob('ssl/*/*.c') ); +} else { + die "Configuration file not given.\nSee '$0 -help' for information\n" + unless defined $config; + @source = @ARGV; +} + +# To detect if there is any error generation for a libcrypto/libssl libs +# we don't know, we need to find out what libs we do know. That list is +# readily available in crypto/err/openssl.ec, in form of lines starting +# with "L ". Note that we always rely on the modules SYS and ERR to be +# generally available. +my %libs = ( SYS => 1, ERR => 1 ); +open my $cfh, $config or die "Trying to read $config: $!\n"; +while (<$cfh>) { + s|\R$||; # Better chomp + next unless m|^L ([0-9A-Z_]+)\s|; + next if $1 eq "NONE"; + $libs{$1} = 1; +} + +my $bad = 0; +foreach my $file (@source) { + open( IN, "<$file" ) || die "Can't open $file, $!"; + my $func = ""; + while () { + if ( !/;$/ && /^\**([a-zA-Z_].*[\s*])?([A-Za-z_0-9]+)\(.*([),]|$)/ ) { + /^([^()]*(\([^()]*\)[^()]*)*)\(/; + $1 =~ /([A-Za-z_0-9]*)$/; + $func = $1; + $func =~ tr/A-Z/a-z/; + } + if ( /([A-Z0-9_]+[A-Z0-9])err\(([^,]+)/ && !/ckerr_ignore/ ) { + my $errlib = $1; + my $n = $2; + + unless ( $libs{$errlib} ) { + print "$file:$.:$errlib not listed in $config\n"; + $libs{$errlib} = 1; # To not display it again + $bad = 1; + } + + if ( $func eq "" ) { + print "$file:$.:???:$n\n"; + $bad = 1; + next; + } + + if ( $n !~ /^(.+)_F_(.+)$/ ) { + #print "check -$file:$.:$func:$n\n"; + next; + } + my $lib = $1; + $n = $2; + + if ( $lib ne $errlib ) { + print "$file:$.:$func:$n [${errlib}err]\n"; + $bad = 1; + next; + } + + $n =~ tr/A-Z/a-z/; + if ( $n ne $func && $errlib ne "SYS" ) { + print "$file:$.:$func:$n\n"; + $bad = 1; + next; + } + + # print "$func:$1\n"; + } + } + close(IN); +} + +if ( $bad && $err_strict ) { + print STDERR "FATAL: error discrepancy\n"; + exit 1; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/util/copy.pl b/trunk/3rdparty/openssl-1.1-fit/util/copy.pl new file mode 100644 index 000000000..58ecc82c4 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/copy.pl @@ -0,0 +1,84 @@ +#! /usr/bin/env perl +# Copyright 2005-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +use Fcntl; + + +# copy.pl + +# Perl script 'copy' comment. On Windows the built in "copy" command also +# copies timestamps: this messes up Makefile dependencies. + +my $stripcr = 0; + +my $arg; +my @excludes = (); + +foreach $arg (@ARGV) { + if ($arg eq "-stripcr") + { + $stripcr = 1; + next; + } + if ($arg =~ /^-exclude_re=(.*)$/) + { + push @excludes, $1; + next; + } + $arg =~ s|\\|/|g; # compensate for bug/feature in cygwin glob... + $arg = qq("$arg") if ($arg =~ /\s/); # compensate for bug in 5.10... + foreach my $f (glob $arg) + { + push @filelist, $f unless grep { $f =~ /$_/ } @excludes; + } +} + +$fnum = @filelist; + +if ($fnum <= 1) + { + die "Need at least two filenames"; + } + +$dest = pop @filelist; + +if ($fnum > 2 && ! -d $dest) + { + die "Destination must be a directory"; + } + +foreach (@filelist) + { + if (-d $dest) + { + $dfile = $_; + $dfile =~ s|^.*[/\\]([^/\\]*)$|$1|; + $dfile = "$dest/$dfile"; + } + else + { + $dfile = $dest; + } + sysopen(IN, $_, O_RDONLY|O_BINARY) || die "Can't Open $_"; + sysopen(OUT, $dfile, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY) + || die "Can't Open $dfile"; + while (sysread IN, $buf, 10240) + { + if ($stripcr) + { + $buf =~ tr/\015//d; + } + syswrite(OUT, $buf, length($buf)); + } + close(IN); + close(OUT); + print "Copying: $_ to $dfile\n"; + } + + diff --git a/trunk/3rdparty/openssl-1.1-fit/util/dofile.pl b/trunk/3rdparty/openssl-1.1-fit/util/dofile.pl new file mode 100644 index 000000000..c3bc9ba9d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/dofile.pl @@ -0,0 +1,210 @@ +#! /usr/bin/env perl +# Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# Reads one or more template files and runs it through Text::Template +# +# It is assumed that this scripts is called with -Mconfigdata, a module +# that holds configuration data in %config + +use strict; +use warnings; + +use FindBin; +use Getopt::Std; + +# We actually expect to get the following hash tables from configdata: +# +# %config +# %target +# %withargs +# %unified_info +# +# We just do a minimal test to see that we got what we expected. +# $config{target} must exist as an absolute minimum. +die "You must run this script with -Mconfigdata\n" if !exists($config{target}); + +# Make a subclass of Text::Template to override append_text_to_result, +# as recommended here: +# +# http://search.cpan.org/~mjd/Text-Template-1.46/lib/Text/Template.pm#Automatic_postprocessing_of_template_hunks + +package OpenSSL::Template; + +# Because we know that Text::Template isn't a core Perl module, we use +# a fallback in case it's not installed on the system +use File::Basename; +use File::Spec::Functions; +use lib "$FindBin::Bin/perl"; +use with_fallback "Text::Template 1.46"; + +#use parent qw/Text::Template/; +use vars qw/@ISA/; +push @ISA, qw/Text::Template/; + +# Override constructor +sub new { + my ($class) = shift; + + # Call the constructor of the parent class, Person. + my $self = $class->SUPER::new( @_ ); + # Add few more attributes + $self->{_output_off} = 0; # Default to output hunks + bless $self, $class; + return $self; +} + +sub append_text_to_output { + my $self = shift; + + if ($self->{_output_off} == 0) { + $self->SUPER::append_text_to_output(@_); + } + + return; +} + +sub output_reset_on { + my $self = shift; + $self->{_output_off} = 0; +} + +sub output_on { + my $self = shift; + if (--$self->{_output_off} < 0) { + $self->{_output_off} = 0; + } +} + +sub output_off { + my $self = shift; + $self->{_output_off}++; +} + +# Come back to main + +package main; + +# Helper functions for the templates ################################# + +# It might be practical to quotify some strings and have them protected +# from possible harm. These functions primarily quote things that might +# be interpreted wrongly by a perl eval. + +# quotify1 STRING +# This adds quotes (") around the given string, and escapes any $, @, \, +# " and ' by prepending a \ to them. +sub quotify1 { + my $s = shift @_; + $s =~ s/([\$\@\\"'])/\\$1/g; + '"'.$s.'"'; +} + +# quotify_l LIST +# For each defined element in LIST (i.e. elements that aren't undef), have +# it quotified with 'quotify1' +sub quotify_l { + map { + if (!defined($_)) { + (); + } else { + quotify1($_); + } + } @_; +} + +# Error reporter ##################################################### + +# The error reporter uses %lines to figure out exactly which file the +# error happened and at what line. Not that the line number may be +# the start of a perl snippet rather than the exact line where it +# happened. Nothing we can do about that here. + +my %lines = (); +sub broken { + my %args = @_; + my $filename = ""; + my $deducelines = 0; + foreach (sort keys %lines) { + $filename = $lines{$_}; + last if ($_ > $args{lineno}); + $deducelines += $_; + } + print STDERR $args{error}," in $filename, fragment starting at line ",$args{lineno}-$deducelines; + undef; +} + +# Check options ###################################################### + +my %opts = (); + +# -o ORIGINATOR +# declares ORIGINATOR as the originating script. +getopt('o', \%opts); + +my @autowarntext = ("WARNING: do not edit!", + "Generated" + . (defined($opts{o}) ? " by ".$opts{o} : "") + . (scalar(@ARGV) > 0 ? " from ".join(", ",@ARGV) : "")); + +# Template reading ################################################### + +# Read in all the templates into $text, while keeping track of each +# file and its size in lines, to try to help report errors with the +# correct file name and line number. + +my $prev_linecount = 0; +my $text = + @ARGV + ? join("", map { my $x = Text::Template::_load_text($_); + if (!defined($x)) { + die $Text::Template::ERROR, "\n"; + } + $x = "{- output_reset_on() -}" . $x; + my $linecount = $x =~ tr/\n//; + $prev_linecount = ($linecount += $prev_linecount); + $lines{$linecount} = $_; + $x } @ARGV) + : join("", ); + +# Engage! ############################################################ + +# Load the full template (combination of files) into Text::Template +# and fill it up with our data. Output goes directly to STDOUT + +my $template = + OpenSSL::Template->new(TYPE => 'STRING', + SOURCE => $text, + PREPEND => qq{use lib "$FindBin::Bin/perl";}); + +sub output_reset_on { + $template->output_reset_on(); + ""; +} +sub output_on { + $template->output_on(); + ""; +} +sub output_off { + $template->output_off(); + ""; +} + +$template->fill_in(OUTPUT => \*STDOUT, + HASH => { config => \%config, + target => \%target, + disabled => \%disabled, + withargs => \%withargs, + unified_info => \%unified_info, + autowarntext => \@autowarntext, + quotify1 => \"ify1, + quotify_l => \"ify_l, + output_reset_on => \&output_reset_on, + output_on => \&output_on, + output_off => \&output_off }, + DELIMITERS => [ "{-", "-}" ], + BROKEN => \&broken); diff --git a/trunk/3rdparty/openssl-1.1-fit/util/echo.pl b/trunk/3rdparty/openssl-1.1-fit/util/echo.pl new file mode 100644 index 000000000..d90e52129 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/echo.pl @@ -0,0 +1,12 @@ +#! /usr/bin/perl + +use strict; +use warnings; +use Getopt::Std; + +our $opt_n = 0; + +getopts('n') or die "Invalid option: $!\n"; + +print join(' ', @ARGV); +print "\n" unless $opt_n; diff --git a/trunk/3rdparty/openssl-1.1-fit/util/find-doc-nits b/trunk/3rdparty/openssl-1.1-fit/util/find-doc-nits new file mode 100755 index 000000000..860bb9958 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/find-doc-nits @@ -0,0 +1,545 @@ +#! /usr/bin/env perl +# Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +require 5.10.0; +use warnings; +use strict; +use Pod::Checker; +use File::Find; +use File::Basename; +use File::Spec::Functions; +use Getopt::Std; +use lib catdir(dirname($0), "perl"); +use OpenSSL::Util::Pod; + +# Options. +our($opt_d); +our($opt_h); +our($opt_l); +our($opt_n); +our($opt_p); +our($opt_u); +our($opt_c); + +sub help() +{ + print < [ 'NAME', 'DESCRIPTION', 'COPYRIGHT' ], + 1 => [ 'SYNOPSIS', 'OPTIONS' ], + 3 => [ 'SYNOPSIS', 'RETURN VALUES' ], + 5 => [ ], + 7 => [ ] ); + +# Cross-check functions in the NAME and SYNOPSIS section. +sub name_synopsis() +{ + my $id = shift; + my $filename = shift; + my $contents = shift; + + # Get NAME section and all words in it. + return unless $contents =~ /=head1 NAME(.*)=head1 SYNOPSIS/ms; + my $tmp = $1; + $tmp =~ tr/\n/ /; + print "$id trailing comma before - in NAME\n" if $tmp =~ /, *-/; + $tmp =~ s/ -.*//g; + $tmp =~ s/ */ /g; + print "$id missing comma in NAME\n" if $tmp =~ /[^,] /; + $tmp =~ s/,//g; + + my $dirname = dirname($filename); + my $simplename = basename($filename); + $simplename =~ s/.pod$//; + my $foundfilename = 0; + my %foundfilenames = (); + my %names; + foreach my $n ( split ' ', $tmp ) { + $names{$n} = 1; + $foundfilename++ if $n eq $simplename; + $foundfilenames{$n} = 1 + if -f "$dirname/$n.pod" && $n ne $simplename; + } + print "$id the following exist as other .pod files:\n", + join(" ", sort keys %foundfilenames), "\n" + if %foundfilenames; + print "$id $simplename (filename) missing from NAME section\n" + unless $foundfilename; + foreach my $n ( keys %names ) { + print "$id $n is not public\n" + if $opt_p and !defined $public{$n}; + } + + # Find all functions in SYNOPSIS + return unless $contents =~ /=head1 SYNOPSIS(.*)=head1 DESCRIPTION/ms; + my $syn = $1; + foreach my $line ( split /\n+/, $syn ) { + my $sym; + $line =~ s/STACK_OF\([^)]+\)/int/g; + $line =~ s/__declspec\([^)]+\)//; + if ( $line =~ /env (\S*)=/ ) { + # environment variable env NAME=... + $sym = $1; + } elsif ( $line =~ /typedef.*\(\*(\S+)\)\(.*/ ) { + # a callback function pointer: typedef ... (*NAME)(... + $sym = $1; + } elsif ( $line =~ /typedef.* (\S+)\(.*/ ) { + # a callback function signature: typedef ... NAME(... + $sym = $1; + } elsif ( $line =~ /typedef.* (\S+);/ ) { + # a simple typedef: typedef ... NAME; + $sym = $1; + } elsif ( $line =~ /enum (\S*) \{/ ) { + # an enumeration: enum ... { + $sym = $1; + } elsif ( $line =~ /#define ([A-Za-z0-9_]+)/ ) { + $sym = $1; + } elsif ( $line =~ /([A-Za-z0-9_]+)\(/ ) { + $sym = $1; + } + else { + next; + } + print "$id $sym missing from NAME section\n" + unless defined $names{$sym}; + $names{$sym} = 2; + + # Do some sanity checks on the prototype. + print "$id prototype missing spaces around commas: $line\n" + if ( $line =~ /[a-z0-9],[^ ]/ ); + } + + foreach my $n ( keys %names ) { + next if $names{$n} == 2; + print "$id $n missing from SYNOPSIS\n"; + } +} + +sub check() +{ + my $filename = shift; + my $dirname = basename(dirname($filename)); + + my $contents = ''; + { + local $/ = undef; + open POD, $filename or die "Couldn't open $filename, $!"; + $contents = ; + close POD; + } + + my $id = "${filename}:1:"; + + &name_synopsis($id, $filename, $contents) + unless $contents =~ /=for comment generic/ + or $filename =~ m@man[157]/@; + + print "$id doesn't start with =pod\n" + if $contents !~ /^=pod/; + print "$id doesn't end with =cut\n" + if $contents !~ /=cut\n$/; + print "$id more than one cut line.\n" + if $contents =~ /=cut.*=cut/ms; + print "$id missing copyright\n" + if $contents !~ /Copyright .* The OpenSSL Project Authors/; + print "$id copyright not last\n" + if $contents =~ /head1 COPYRIGHT.*=head/ms; + print "$id head2 in All uppercase\n" + if $contents =~ /head2\s+[A-Z ]+\n/; + print "$id extra space after head\n" + if $contents =~ /=head\d\s\s+/; + print "$id period in NAME section\n" + if $contents =~ /=head1 NAME.*\.\n.*=head1 SYNOPSIS/ms; + print "$id POD markup in NAME section\n" + if $contents =~ /=head1 NAME.*[<>].*=head1 SYNOPSIS/ms; + print "$id Duplicate $1 in L<>\n" + if $contents =~ /L<([^>]*)\|([^>]*)>/ && $1 eq $2; + print "$id Bad =over $1\n" + if $contents =~ /=over([^ ][^24])/; + print "$id Possible version style issue\n" + if $contents =~ /OpenSSL version [019]/; + + if ( $contents !~ /=for comment multiple includes/ ) { + # Look for multiple consecutive openssl #include lines + # (non-consecutive lines are okay; see man3/MD5.pod). + if ( $contents =~ /=head1 SYNOPSIS(.*)=head1 DESCRIPTION/ms ) { + my $count = 0; + foreach my $line ( split /\n+/, $1 ) { + if ( $line =~ m@include ', $temp + or die "Can't open $temp, $!"; + podchecker($filename, $OUT); + close $OUT; + open $OUT, '<', $temp + or die "Can't read $temp, $!"; + while ( <$OUT> ) { + next if /\(section\) in.*deprecated/; + print; + } + close $OUT; + unlink $temp || warn "Can't remove $temp, $!"; + + # Find what section this page is in; assume 3. + my $section = 3; + $section = $1 if $dirname =~ /man([1-9])/; + + foreach ((@{$mandatory_sections{'*'}}, @{$mandatory_sections{$section}})) { + # Skip "return values" if not -s + print "$id: missing $_ head1 section\n" + if $contents !~ /^=head1\s+${_}\s*$/m; + } +} + +my %dups; + +sub parsenum() +{ + my $file = shift; + my @apis; + + open my $IN, '<', $file + or die "Can't open $file, $!, stopped"; + + while ( <$IN> ) { + next if /^#/; + next if /\bNOEXIST\b/; + next if /\bEXPORT_VAR_AS_FUNC\b/; + my @fields = split(); + die "Malformed line $_" + if scalar @fields != 2 && scalar @fields != 4; + push @apis, $fields[0]; + } + + close $IN; + + print "# Found ", scalar(@apis), " in $file\n" unless $opt_p; + return sort @apis; +} + +sub getdocced() +{ + my $dir = shift; + my %return; + + foreach my $pod ( glob("$dir/*.pod") ) { + my %podinfo = extract_pod_info($pod); + foreach my $n ( @{$podinfo{names}} ) { + $return{$n} = $pod; + print "# Duplicate $n in $pod and $dups{$n}\n" + if defined $dups{$n} && $dups{$n} ne $pod; + $dups{$n} = $pod; + } + } + + return %return; +} + +my %docced; + +sub checkmacros() +{ + my $count = 0; + + print "# Checking macros (approximate)\n"; + foreach my $f ( glob('include/openssl/*.h') ) { + # Skip some internals we don't want to document yet. + next if $f eq 'include/openssl/asn1.h'; + next if $f eq 'include/openssl/asn1t.h'; + next if $f eq 'include/openssl/err.h'; + open(IN, $f) || die "Can't open $f, $!"; + while ( ) { + next unless /^#\s*define\s*(\S+)\(/; + my $macro = $1; + next if $docced{$macro}; + next if $macro =~ /i2d_/ + || $macro =~ /d2i_/ + || $macro =~ /DEPRECATEDIN/ + || $macro =~ /IMPLEMENT_/ + || $macro =~ /DECLARE_/; + print "$f:$macro\n" if $opt_d; + $count++; + } + close(IN); + } + print "# Found $count macros missing (not all should be documented)\n" +} + +sub printem() +{ + my $libname = shift; + my $numfile = shift; + my $count = 0; + + foreach my $func ( &parsenum($numfile) ) { + next if $docced{$func}; + + # Skip ASN1 utilities + next if $func =~ /^ASN1_/; + + print "$libname:$func\n" if $opt_d; + $count++; + } + print "# Found $count missing from $numfile\n\n"; +} + + +# Collection of links in each POD file. +# filename => [ "foo(1)", "bar(3)", ... ] +my %link_collection = (); +# Collection of names in each POD file. +# "name(s)" => filename +my %name_collection = (); + +sub collectnames { + my $filename = shift; + $filename =~ m|man(\d)/|; + my $section = $1; + my $simplename = basename($filename, ".pod"); + my $id = "${filename}:1:"; + + my $contents = ''; + { + local $/ = undef; + open POD, $filename or die "Couldn't open $filename, $!"; + $contents = ; + close POD; + } + + $contents =~ /=head1 NAME([^=]*)=head1 /ms; + my $tmp = $1; + unless (defined $tmp) { + print "$id weird name section\n"; + return; + } + $tmp =~ tr/\n/ /; + $tmp =~ s/-.*//g; + + my @names = map { s/\s+//g; $_ } split(/,/, $tmp); + unless (grep { $simplename eq $_ } @names) { + print "$id missing $simplename\n"; + push @names, $simplename; + } + foreach my $name (@names) { + next if $name eq ""; + my $name_sec = "$name($section)"; + if (! exists $name_collection{$name_sec}) { + $name_collection{$name_sec} = $filename; + } else { #elsif ($filename ne $name_collection{$name_sec}) { + print "$id $name_sec also in $name_collection{$name_sec}\n"; + } + } + + my @foreign_names = + map { map { s/\s+//g; $_ } split(/,/, $_) } + $contents =~ /=for\s+comment\s+foreign\s+manuals:\s*(.*)\n\n/; + foreach (@foreign_names) { + $name_collection{$_} = undef; # It still exists! + } + + my @links = $contents =~ /L< + # if the link is of the form L, + # then remove 'something'. Note that 'something' + # may contain POD codes as well... + (?:(?:[^\|]|<[^>]*>)*\|)? + # we're only interested in references that have + # a one digit section number + ([^\/>\(]+\(\d\)) + /gx; + $link_collection{$filename} = [ @links ]; +} + +sub checklinks { + foreach my $filename (sort keys %link_collection) { + foreach my $link (@{$link_collection{$filename}}) { + print "${filename}:1: reference to non-existing $link\n" + unless exists $name_collection{$link}; + } + } +} + +sub publicize() { + foreach my $name ( &parsenum('util/libcrypto.num') ) { + $public{$name} = 1; + } + foreach my $name ( &parsenum('util/libssl.num') ) { + $public{$name} = 1; + } + foreach my $name ( &parsenum('util/private.num') ) { + $public{$name} = 1; + } +} + +my %skips = ( + 'aes128' => 1, + 'aes192' => 1, + 'aes256' => 1, + 'aria128' => 1, + 'aria192' => 1, + 'aria256' => 1, + 'camellia128' => 1, + 'camellia192' => 1, + 'camellia256' => 1, + 'des' => 1, + 'des3' => 1, + 'idea' => 1, + '[cipher]' => 1, + '[digest]' => 1, +); + +sub checkflags() { + my $cmd = shift; + my %cmdopts; + my %docopts; + my $ok = 1; + + # Get the list of options in the command. + open CFH, "./apps/openssl list --options $cmd|" + || die "Can list options for $cmd, $!"; + while ( ) { + chop; + s/ .$//; + $cmdopts{$_} = 1; + } + close CFH; + + # Get the list of flags from the synopsis + open CFH, " ) { + chop; + last if /DESCRIPTION/; + next unless /\[B<-([^ >]+)/; + $docopts{$1} = 1; + } + close CFH; + + # See what's in the command not the manpage. + my @undocced = (); + foreach my $k ( keys %cmdopts ) { + push @undocced, $k unless $docopts{$k}; + } + if ( scalar @undocced > 0 ) { + $ok = 0; + foreach ( @undocced ) { + print "doc/man1/$cmd.pod: Missing -$_\n"; + } + } + + # See what's in the command not the manpage. + my @unimpl = (); + foreach my $k ( keys %docopts ) { + push @unimpl, $k unless $cmdopts{$k}; + } + if ( scalar @unimpl > 0 ) { + $ok = 0; + foreach ( @unimpl ) { + next if defined $skips{$_}; + print "doc/man1/$cmd.pod: Not implemented -$_\n"; + } + } + + return $ok; +} + +getopts('cdlnphu'); + +&help() if $opt_h; +$opt_n = 1 if $opt_p; +$opt_u = 1 if $opt_d; + +die "Need one of -[cdlnpu] flags.\n" + unless $opt_c or $opt_l or $opt_n or $opt_u; + +if ( $opt_c ) { + my $ok = 1; + my @commands = (); + + # Get list of commands. + open FH, "./apps/openssl list -1 -commands|" + || die "Can't list commands, $!"; + while ( ) { + chop; + push @commands, $_; + } + close FH; + + # See if each has a manpage. + foreach ( @commands ) { + next if $_ eq 'help' || $_ eq 'exit'; + if ( ! -f "doc/man1/$_.pod" ) { + print "doc/man1/$_.pod does not exist\n"; + $ok = 0; + } else { + $ok = 0 if not &checkflags($_); + } + } + + # See what help is missing. + open FH, "./apps/openssl list --missing-help |" + || die "Can't list missing help, $!"; + while ( ) { + chop; + my ($cmd, $flag) = split; + print "$cmd has no help for -$flag\n"; + $ok = 0; + } + close FH; + + exit 1 if not $ok; +} + +if ( $opt_l ) { + foreach (@ARGV ? @ARGV : glob('doc/*/*.pod')) { + collectnames($_); + } + checklinks(); +} + +if ( $opt_n ) { + &publicize() if $opt_p; + foreach (@ARGV ? @ARGV : glob('doc/*/*.pod')) { + &check($_); + } +} + +if ( $opt_u ) { + my %temp = &getdocced('doc/man3'); + foreach ( keys %temp ) { + $docced{$_} = $temp{$_}; + } + &printem('crypto', 'util/libcrypto.num'); + &printem('ssl', 'util/libssl.num'); + &checkmacros(); +} + +exit; diff --git a/trunk/3rdparty/openssl-1.1-fit/util/find-unused-errs b/trunk/3rdparty/openssl-1.1-fit/util/find-unused-errs new file mode 100755 index 000000000..cd1026d59 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/find-unused-errs @@ -0,0 +1,54 @@ +#! /bin/bash +# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# Find unused error function-names and reason-codes, and edit them +# out of the source. Doesn't handle line-wrapping, might have to do +# some manual cleanups to fix compile errors. + +export X1=/tmp/f.1.$$ +export X2=/tmp/f.2.$$ + +case "$1" in + -f) + PAT='_F_' + echo Functions only + ;; + -[er]) + PAT='_R_' + echo Reason codes only + ;; + "") + PAT='_[FR]_' + echo Function and reasons + ;; + *) + echo "Usage error; one of -[efr] required." + exit 1; + ;; +esac + +cd include/openssl || exit 1 +grep "$PAT" * | grep -v ERR_FATAL_ERROR | awk '{print $3;}' | sort -u >$X1 +cd ../.. + +for F in `cat $X1` ; do + git grep -l --full-name -F $F >$X2 + NUM=`wc -l <$X2` + test $NUM -gt 2 && continue + if grep -q $F crypto/err/openssl.ec ; then + echo Possibly unused $F found in openssl.ec + continue + fi + echo $F + for FILE in `cat $X2` ; do + grep -v -w $F <$FILE >$FILE.new + mv $FILE.new $FILE + done +done + +rm $X1 $X2 diff --git a/trunk/3rdparty/openssl-1.1-fit/util/indent.pro b/trunk/3rdparty/openssl-1.1-fit/util/indent.pro new file mode 100644 index 000000000..3d3f747bf --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/indent.pro @@ -0,0 +1,643 @@ +-bap +-bbo +-br +-brs +-c33 +-cd33 +-ce +-ci4 +-cli0 +-cp33 +-d0 +-di1 +-hnl +-i4 +-il1 +-ip0 +-l80 +-lp +-nbad +-nbc +-ncdb +-ncs +-nfc1 +-nfca +-npcs +-nprs +-npsl +-nsc +-ppi1 +-saf +-sai +-saw +-sob +-ss +-ts0 +-T ACCESS_DESCRIPTION +-T ADDED_OBJ +-T AES_KEY +-T APP_INFO +-T ARGS +-T ASIdOrRange +-T ASIdOrRanges +-T ASIdentifierChoice +-T ASIdentifiers +-T ASN1_ADB +-T ASN1_ADB_TABLE +-T ASN1_AUX +-T ASN1_BIT_STRING +-T ASN1_BMPSTRING +-T ASN1_BOOLEAN +-T ASN1_ENCODING +-T ASN1_ENUMERATED +-T ASN1_EXTERN_FUNCS +-T ASN1_GENERALIZEDTIME +-T ASN1_GENERALSTRING +-T ASN1_IA5STRING +-T ASN1_INTEGER +-T ASN1_ITEM +-T ASN1_ITEM_EXP +-T ASN1_NULL +-T ASN1_OBJECT +-T ASN1_OCTET_STRING +-T ASN1_PCTX +-T ASN1_PRIMITIVE_FUNCS +-T ASN1_PRINTABLESTRING +-T ASN1_PRINT_ARG +-T ASN1_SCTX +-T ASN1_STREAM_ARG +-T ASN1_STRING +-T ASN1_STRING_TABLE +-T ASN1_T61STRING +-T ASN1_TEMPLATE +-T ASN1_TIME +-T ASN1_TLC +-T ASN1_TYPE +-T ASN1_UNIVERSALSTRING +-T ASN1_UTCTIME +-T ASN1_UTF8STRING +-T ASN1_VALUE +-T ASN1_VISIBLESTRING +-T AUTHORITY_INFO_ACCESS +-T AUTHORITY_KEYID +-T BASIC_CONSTRAINTS +-T BF_KEY +-T BF_LONG +-T BIGNUM +-T BIO +-T BIO_ACCEPT +-T BIO_ADDR +-T BIO_ASN1_BUF_CTX +-T BIO_ASN1_EX_FUNCS +-T BIO_B64_CTX +-T BIO_CONNECT +-T BIO_ENC_CTX +-T BIO_F_BUFFER_CTX +-T BIO_LINEBUFFER_CTX +-T BIO_METHOD +-T BIO_OK_CTX +-T BIO_SSL +-T BIT_STRING_BITNAME +-T BN_BLINDING +-T BN_CTX +-T BN_GENCB +-T BN_MONT_CTX +-T BN_POOL +-T BN_POOL_ITEM +-T BN_RECP_CTX +-T BN_STACK +-T BN_ULONG +-T BUF_MEM +-T BY_DIR +-T BY_DIR_ENTRY +-T BY_DIR_HASH +-T Bytef +-T CAMELLIA_KEY +-T CAST_KEY +-T CAST_LONG +-T CA_DB +-T CCM128_CONTEXT +-T CERT +-T CERTIFICATEPOLICIES +-T CERT_PKEY +-T CIPHER_ORDER +-T CMAC_CTX +-T CMS_AuthenticatedData +-T CMS_CertificateChoices +-T CMS_CompressedData +-T CMS_ContentInfo +-T CMS_DigestedData +-T CMS_EncapsulatedContentInfo +-T CMS_EncryptedContentInfo +-T CMS_EncryptedData +-T CMS_EnvelopedData +-T CMS_IssuerAndSerialNumber +-T CMS_KEKIdentifier +-T CMS_KEKRecipientInfo +-T CMS_KeyAgreeRecipientIdentifier +-T CMS_KeyAgreeRecipientInfo +-T CMS_KeyTransRecipientInfo +-T CMS_OriginatorIdentifierOrKey +-T CMS_OriginatorInfo +-T CMS_OriginatorPublicKey +-T CMS_OtherCertificateFormat +-T CMS_OtherKeyAttribute +-T CMS_OtherRecipientInfo +-T CMS_OtherRevocationInfoFormat +-T CMS_PasswordRecipientInfo +-T CMS_Receipt +-T CMS_ReceiptRequest +-T CMS_ReceiptsFrom +-T CMS_RecipientEncryptedKey +-T CMS_RecipientIdentifier +-T CMS_RecipientInfo +-T CMS_RecipientKeyIdentifier +-T CMS_RevocationInfoChoice +-T CMS_SignedData +-T CMS_SignerIdentifier +-T CMS_SignerInfo +-T COMP_CTX +-T COMP_METHOD +-T CONF +-T CONF_IMODULE +-T CONF_METHOD +-T CONF_MODULE +-T CONF_VALUE +-T CRYPTO_EX_DATA +-T CRYPTO_EX_dup +-T CRYPTO_EX_free +-T CRYPTO_EX_new +-T CRYPTO_THREADID +-T DB_ATTR +-T DES_LONG +-T DES_cblock +-T DES_key_schedule +-T DH +-T DH_METHOD +-T DH_PKEY_CTX +-T DIST_POINT +-T DIST_POINT_NAME +-T DSA +-T DSA_METHOD +-T DSA_SIG +-T DSO +-T DSO_FUNC_TYPE +-T DSO_MERGER_FUNC +-T DSO_METHOD +-T DSO_NAME_CONVERTER_FUNC +-T DSO_VMS_INTERNAL +-T DTLS1_BITMAP +-T DTLS1_RECORD_DATA +-T DTLS1_STATE +-T Dl_info +-T ECDH_METHOD +-T ECDSA_METHOD +-T ECDSA_SIG +-T ECPARAMETERS +-T ECPKPARAMETERS +-T EC_GROUP +-T EC_KEY +-T EC_METHOD +-T EC_POINT +-T EC_PRE_COMP +-T EC_PRIVATEKEY +-T EC_builtin_curve +-T EDIPARTYNAME +-T ENGINE +-T ENGINE_CIPHERS_PTR +-T ENGINE_CLEANUP_CB +-T ENGINE_CLEANUP_ITEM +-T ENGINE_CMD_DEFN +-T ENGINE_CTRL_FUNC_PTR +-T ENGINE_DIGESTS_PTR +-T ENGINE_GEN_FUNC_PTR +-T ENGINE_GEN_INT_FUNC_PTR +-T ENGINE_LOAD_KEY_PTR +-T ENGINE_PILE +-T ENGINE_PILE_DOALL +-T ENGINE_PKEY_ASN1_METHS_PTR +-T ENGINE_PKEY_METHS_PTR +-T ENGINE_SSL_CLIENT_CERT_PTR +-T ENGINE_TABLE +-T ENUMERATED_NAMES +-T ERR_STATE +-T ERR_STRING_DATA +-T ESS_CERT_ID +-T ESS_CERT_ID_V2 +-T ESS_ISSUER_SERIAL +-T ESS_SIGNING_CERT +-T ESS_SIGNING_CERT_V2 +-T EVP_AES_HMAC_SHA1 +-T EVP_AES_HMAC_SHA256 +-T EVP_CIPHER +-T EVP_CIPHER_CTX +-T EVP_CIPHER_INFO +-T EVP_ENCODE_CTX +-T EVP_MD +-T EVP_MD_CTX +-T EVP_PBE_CTL +-T EVP_PBE_KEYGEN +-T EVP_PKEY +-T EVP_PKEY_ASN1_METHOD +-T EVP_PKEY_CTX +-T EVP_PKEY_METHOD +-T EVP_PKEY_gen_cb +-T FILE +-T GCM128_CONTEXT +-T GENERAL_NAME +-T GENERAL_NAMES +-T GENERAL_SUBTREE +-T GEN_SESSION_CB +-T HASH_CTX +-T HEAPENTRY32 +-T HEAPLIST32 +-T HMAC_CTX +-T IDEA_KEY_SCHEDULE +-T IPAddrBlocks +-T IPAddressFamily +-T IPAddressOrRange +-T IPAddressOrRanges +-T ISSUING_DIST_POINT +-T KEY_TABLE_TYPE +-T LHASH +-T LHASH_DOALL_ARG_FN_TYPE +-T LHASH_NODE +-T LPHEAPENTRY32 +-T LPHEAPLIST32 +-T LPMODULEENTRY32 +-T LPMODULEENTRY32W +-T LPPROCESSENTRY32 +-T LPPROCESSENTRY32W +-T LPTHREADENTRY32 +-T LP_DIR_CTX +-T MD2_CTX +-T MD4_CTX +-T MD5_CTX +-T MDC2_CTX +-T MEM +-T MEM_LEAK +-T MIME_HEADER +-T MIME_PARAM +-T MODULEENTRY32 +-T MODULEENTRY32W +-T NAME_CONSTRAINTS +-T NAME_FUNCS +-T NBIO_TEST +-T NDEF_SUPPORT +-T NETSCAPE_CERT_SEQUENCE +-T NETSCAPE_ENCRYPTED_PKEY +-T NETSCAPE_PKEY +-T NETSCAPE_SPKAC +-T NETSCAPE_SPKI +-T NOTICEREF +-T OBJ_NAME +-T OCB128_CONTEXT +-T OCB_BLOCK +-T OCSP_BASICRESP +-T OCSP_CERTID +-T OCSP_CERTSTATUS +-T OCSP_CRLID +-T OCSP_ONEREQ +-T OCSP_REQINFO +-T OCSP_REQUEST +-T OCSP_REQ_CTX +-T OCSP_RESPBYTES +-T OCSP_RESPDATA +-T OCSP_RESPID +-T OCSP_RESPONSE +-T OCSP_REVOKEDINFO +-T OCSP_SERVICELOC +-T OCSP_SIGNATURE +-T OCSP_SINGLERESP +-T OCSP_TBLSTR +-T OPENSSL_BLOCK +-T OPENSSL_CSTRING +-T OPENSSL_DIR_CTX +-T OPENSSL_PSTRING +-T OPENSSL_STRING +-T OSSL_ASYNC_FD +-T OTHERNAME +-T P256_POINT +-T P256_POINT_AFFINE +-T PBE2PARAM +-T PBEPARAM +-T PBKDF2PARAM +-T PHEAPENTRY32 +-T PHEAPLIST32 +-T PKCS12 +-T PKCS12_BAGS +-T PKCS12_SAFEBAG +-T PKCS7 +-T PKCS7_DIGEST +-T PKCS7_ENCRYPT +-T PKCS7_ENC_CONTENT +-T PKCS7_ENVELOPE +-T PKCS7_ISSUER_AND_SERIAL +-T PKCS7_RECIP_INFO +-T PKCS7_SIGNED +-T PKCS7_SIGNER_INFO +-T PKCS7_SIGN_ENVELOPE +-T PKCS8_PRIV_KEY_INFO +-T PKEY_USAGE_PERIOD +-T PMODULEENTRY32 +-T PMODULEENTRY32W +-T POLICYINFO +-T POLICYQUALINFO +-T POLICY_CONSTRAINTS +-T POLICY_MAPPING +-T POLICY_MAPPINGS +-T PPROCESSENTRY32 +-T PPROCESSENTRY32W +-T PRECOMP256_ROW +-T PROCESSENTRY32 +-T PROCESSENTRY32W +-T PROXY_CERT_INFO_EXTENSION +-T PROXY_POLICY +-T PTHREADENTRY32 +-T PW_CB_DATA +-T RAND_METHOD +-T RC2_KEY +-T RC4_KEY +-T RC5_32_KEY +-T RIPEMD160_CTX +-T RSA +-T RSA_METHOD +-T RSA_OAEP_PARAMS +-T RSA_PKEY_CTX +-T RSA_PSS_PARAMS +-T SCT +-T SEED_KEY_SCHEDULE +-T SHA256_CTX +-T SHA512_CTX +-T SHA_CTX +-T SRP_ARG +-T SRP_CLIENT_ARG +-T SRP_CTX +-T SRP_SERVER_ARG +-T SRP_VBASE +-T SRP_gN_cache +-T SRP_user_pwd +-T SRTP_PROTECTION_PROFILE +-T SSL +-T SSL3_BUFFER +-T SSL3_COMP +-T SSL3_ENC_METHOD +-T SSL3_RECORD +-T SSL3_STATE +-T SSL_CIPHER +-T SSL_COMP +-T SSL_CONF_CTX +-T SSL_CTX +-T SSL_DANE +-T SSL_EXCERT +-T SSL_METHOD +-T SSL_SESSION +-T SSL_SESSION_ASN1 +-T STACK_OF +-T SXNET +-T SXNETID +-T TCHAR +-T TEST_INFO +-T THREADENTRY32 +-T TIMEOUT_PARAM +-T TLS_SESSION_TICKET_EXT +-T TLS_SIGALGS +-T TS_ACCURACY +-T TS_MSG_IMPRINT +-T TS_REQ +-T TS_RESP +-T TS_RESP_CTX +-T TS_STATUS_INFO +-T TS_TST_INFO +-T TS_VERIFY_CTX +-T TXT_DB +-T UI +-T UINT64 +-T UI_METHOD +-T UI_STRING +-T USERNOTICE +-T WCHAR +-T WHIRLPOOL_CTX +-T WINAPI +-T X509 +-T X509V3_CONF_METHOD +-T X509V3_CTX +-T X509V3_EXT_D2I +-T X509V3_EXT_FREE +-T X509V3_EXT_I2D +-T X509V3_EXT_I2R +-T X509V3_EXT_I2S +-T X509V3_EXT_METHOD +-T X509V3_EXT_NEW +-T X509V3_EXT_R2I +-T X509V3_EXT_S2I +-T X509V3_EXT_V2I +-T X509_ALGOR +-T X509_ATTRIBUTE +-T X509_CERT_AUX +-T X509_CINF +-T X509_CRL +-T X509_CRL_INFO +-T X509_CRL_METHOD +-T X509_EXTENSION +-T X509_INFO +-T X509_LOOKUP +-T X509_LOOKUP_METHOD +-T X509_NAME +-T X509_NAME_ENTRY +-T X509_OBJECT +-T X509_PKEY +-T X509_POLICY_CACHE +-T X509_POLICY_DATA +-T X509_POLICY_LEVEL +-T X509_POLICY_NODE +-T X509_POLICY_TREE +-T X509_PUBKEY +-T X509_PURPOSE +-T X509_REQ +-T X509_REQ_INFO +-T X509_REVOKED +-T X509_SIG +-T X509_STORE +-T X509_STORE_CTX +-T X509_TRUST +-T X509_VAL +-T X509_VERIFY_PARAM +-T X9_62_CHARACTERISTIC_TWO +-T X9_62_CURVE +-T X9_62_FIELDID +-T X9_62_PENTANOMIAL +-T XTS128_CONTEXT +-T _LHASH +-T _STACK +-T __int64 +-T asn1_ps_func +-T bio_dgram_data +-T bio_info_cb +-T BIO_info_cb +-T BIO_callback_fn +-T char_io +-T conf_finish_func +-T conf_init_func +-T const_DES_cblock +-T d2i_of_void +-T des_cblock +-T dynamic_data_ctx +-T dynamic_fns +-T engine_table_doall_cb +-T i2d_of_void +-T int_dhx942_dh +-T nid_triple +-T pem_password_cb +-T pitem +-T piterator +-T pqueue_s +-T session_op +-T size_t +-T tag_exp_arg +-T testdata +-T time_t +-T time_t +-T u32 +-T u64 +-T u8 +-T v3_ext_ctx +-T v3_ext_method +-T STACK_OF_ACCESS_DESCRIPTION_ +-T STACK_OF_ASIdOrRange_ +-T STACK_OF_ASN1_ADB_TABLE_ +-T STACK_OF_ASN1_INTEGER_ +-T STACK_OF_ASN1_OBJECT_ +-T STACK_OF_ASN1_STRING_TABLE_ +-T STACK_OF_ASN1_TYPE_ +-T STACK_OF_ASN1_UTF8STRING_ +-T STACK_OF_ASN1_VALUE_ +-T STACK_OF_BIO_ +-T STACK_OF_BY_DIR_ENTRY_ +-T STACK_OF_BY_DIR_HASH_ +-T STACK_OF_CMS_CertificateChoices_ +-T STACK_OF_CMS_RecipientEncryptedKey_ +-T STACK_OF_CMS_RecipientInfo_ +-T STACK_OF_CMS_RevocationInfoChoice_ +-T STACK_OF_CMS_SignerInfo_ +-T STACK_OF_CONF_IMODULE_ +-T STACK_OF_CONF_MODULE_ +-T STACK_OF_CONF_VALUE_ +-T STACK_OF_CRYPTO_dynlock_ +-T STACK_OF_DIST_POINT_ +-T STACK_OF_ENGINE_ +-T STACK_OF_ENGINE_CLEANUP_ITEM_ +-T STACK_OF_ESS_CERT_ID_ +-T STACK_OF_ESS_CERT_ID_V2_ +-T STACK_OF_EVP_PBE_CTL_ +-T STACK_OF_EVP_PKEY_ASN1_METHOD_ +-T STACK_OF_EVP_PKEY_METHOD_ +-T STACK_OF_GENERAL_NAMES_ +-T STACK_OF_GENERAL_NAME_ +-T STACK_OF_GENERAL_SUBTREE_ +-T STACK_OF_IPAddressFamily_ +-T STACK_OF_IPAddressOrRange_ +-T STACK_OF_MIME_HEADER_ +-T STACK_OF_MIME_PARAM_ +-T STACK_OF_NAME_FUNCS_ +-T STACK_OF_OCSP_CERTID_ +-T STACK_OF_OCSP_ONEREQ_ +-T STACK_OF_OCSP_RESPID_ +-T STACK_OF_OCSP_SINGLERESP_ +-T STACK_OF_OPENSSL_BLOCK_ +-T STACK_OF_OPENSSL_PSTRING_ +-T STACK_OF_OPENSSL_STRING_ +-T STACK_OF_PKCS12_SAFEBAG_ +-T STACK_OF_PKCS7_ +-T STACK_OF_PKCS7_RECIP_INFO_ +-T STACK_OF_PKCS7_SIGNER_INFO_ +-T STACK_OF_POLICYINFO_ +-T STACK_OF_POLICYQUALINFO_ +-T STACK_OF_POLICY_MAPPING_ +-T STACK_OF_Request_ +-T STACK_OF_SCT_ +-T STACK_OF_SRP_gN_ +-T STACK_OF_SRP_gN_cache_ +-T STACK_OF_SRP_user_pwd_ +-T STACK_OF_SRTP_PROTECTION_PROFILE_ +-T STACK_OF_SSL_CIPHER_ +-T STACK_OF_SSL_COMP_ +-T STACK_OF_STRING_ +-T STACK_OF_SXNETID_ +-T STACK_OF_SingleResponse_ +-T STACK_OF_UI_STRING_ +-T STACK_OF_X509V3_EXT_METHOD_ +-T STACK_OF_X509_ +-T STACK_OF_X509_ALGOR_ +-T STACK_OF_X509_ATTRIBUTE_ +-T STACK_OF_X509_CRL_ +-T STACK_OF_X509_EXTENSION_ +-T STACK_OF_X509_INFO_ +-T STACK_OF_X509_LOOKUP_ +-T STACK_OF_X509_NAME_ +-T STACK_OF_X509_NAME_ENTRY_ +-T STACK_OF_X509_OBJECT_ +-T STACK_OF_X509_POLICY_DATA_ +-T STACK_OF_X509_POLICY_NODE_ +-T STACK_OF_X509_PURPOSE_ +-T STACK_OF_X509_REVOKED_ +-T STACK_OF_X509_TRUST_ +-T STACK_OF_X509_VERIFY_PARAM_ +-T STACK_OF_nid_triple_ +-T STACK_OF_void_ +-T LHASH_OF_ADDED_OBJ_ +-T LHASH_OF_APP_INFO_ +-T LHASH_OF_CONF_VALUE_ +-T LHASH_OF_ENGINE_PILE_ +-T LHASH_OF_ERR_STATE_ +-T LHASH_OF_ERR_STRING_DATA_ +-T LHASH_OF_FUNCTION_ +-T LHASH_OF_MEM_ +-T LHASH_OF_OBJ_NAME_ +-T LHASH_OF_OPENSSL_STRING_ +-T LHASH_OF_SSL_SESSION_ +-T LHASH_OF_STRING_ +-T clock_t +-T custom_ext_methods +-T hm_fragment +-T record_pqueue +-T ssl_ctx_st +-T ssl_flag_tbl +-T ssl_st +-T ssl_trace_tbl +-T _stdcall +-T OPTIONS +-T OPT_PAIR +-T uint64_t +-T int64_t +-T uint32_t +-T int32_t +-T uint16_t +-T int16_t +-T uint8_t +-T int8_t +-T STRINT_PAIR +-T felem +-T felem_bytearray +-T SH_LIST +-T PACKET +-T RECORD_LAYER +-T ASYNC_CTX +-T ASYNC_JOB +-T intmax_t +-T uintmax_t +-T pqueue +-T danetls_record +-T CTLOG_STORE +-T OPENSSL_INIT_SETTINGS +-T OSSL_HANDSHAKE_STATE +-T OSSL_STATEM +-T ossl_intmax_t +-T ossl_intmax_t +-T ossl_uintmax_t +-T ossl_uintmax_t +-T CT_POLICY_EVAL_CTX +-T RAND_DRBG +-T RAND_DRBG_CTR +-T RAND_POOL +-T RAND_METHOD diff --git a/trunk/3rdparty/openssl-1.1-fit/util/libcrypto.num b/trunk/3rdparty/openssl-1.1-fit/util/libcrypto.num new file mode 100644 index 000000000..32c64cb2c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/libcrypto.num @@ -0,0 +1,4581 @@ +d2i_EC_PUBKEY 1 1_1_0 EXIST::FUNCTION:EC +b2i_PVK_bio 2 1_1_0 EXIST::FUNCTION:DSA,RC4 +PEM_read_bio_NETSCAPE_CERT_SEQUENCE 3 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_get0_chain 4 1_1_0 EXIST::FUNCTION: +COMP_expand_block 5 1_1_0 EXIST::FUNCTION:COMP +X509V3_get_string 6 1_1_0 EXIST::FUNCTION: +TS_MSG_IMPRINT_free 7 1_1_0 EXIST::FUNCTION:TS +DES_xcbc_encrypt 8 1_1_0 EXIST::FUNCTION:DES +TS_RESP_CTX_new 9 1_1_0 EXIST::FUNCTION:TS +PKCS5_PBE_add 10 1_1_0 EXIST::FUNCTION: +i2d_DSAparams 11 1_1_0 EXIST::FUNCTION:DSA +X509_NAME_get0_der 12 1_1_0 EXIST::FUNCTION: +i2d_ESS_ISSUER_SERIAL 13 1_1_0 EXIST::FUNCTION:TS +X509at_get_attr_by_NID 14 1_1_0 EXIST::FUNCTION: +X509_PUBKEY_set0_param 15 1_1_0 EXIST::FUNCTION: +PKCS12_it 16 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +PKCS12_it 16 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +i2d_ASN1_OCTET_STRING 17 1_1_0 EXIST::FUNCTION: +EC_KEY_set_private_key 18 1_1_0 EXIST::FUNCTION:EC +SRP_VBASE_get_by_user 19 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0,SRP +Camellia_cfb128_encrypt 21 1_1_0 EXIST::FUNCTION:CAMELLIA +DES_ncbc_encrypt 22 1_1_0 EXIST::FUNCTION:DES +TS_REQ_get_ext_count 23 1_1_0 EXIST::FUNCTION:TS +EVP_aes_128_ocb 24 1_1_0 EXIST::FUNCTION:OCB +ASN1_item_d2i_fp 25 1_1_0 EXIST::FUNCTION:STDIO +BN_lshift 26 1_1_0 EXIST::FUNCTION: +X509_NAME_add_entry_by_NID 27 1_1_0 EXIST::FUNCTION: +X509V3_add_value_bool 28 1_1_0 EXIST::FUNCTION: +GENERAL_NAME_get0_otherName 29 1_1_0 EXIST::FUNCTION: +ASN1_INTEGER_get_uint64 30 1_1_0 EXIST::FUNCTION: +EVP_DigestInit_ex 31 1_1_0 EXIST::FUNCTION: +CTLOG_new 32 1_1_0 EXIST::FUNCTION:CT +UI_get_result_minsize 33 1_1_0 EXIST::FUNCTION: +EVP_PBE_alg_add_type 34 1_1_0 EXIST::FUNCTION: +EVP_cast5_ofb 35 1_1_0 EXIST::FUNCTION:CAST +d2i_PUBKEY_fp 36 1_1_0 EXIST::FUNCTION:STDIO +PKCS7_set_cipher 37 1_1_0 EXIST::FUNCTION: +BF_decrypt 38 1_1_0 EXIST::FUNCTION:BF +PEM_read_bio_PUBKEY 39 1_1_0 EXIST::FUNCTION: +X509_NAME_delete_entry 40 1_1_0 EXIST::FUNCTION: +EVP_PKEY_meth_set_verify_recover 41 1_1_0 EXIST::FUNCTION: +UI_set_method 42 1_1_0 EXIST::FUNCTION: +PKCS7_ISSUER_AND_SERIAL_it 43 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +PKCS7_ISSUER_AND_SERIAL_it 43 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +EC_GROUP_method_of 44 1_1_0 EXIST::FUNCTION:EC +RSA_blinding_on 45 1_1_0 EXIST::FUNCTION:RSA +X509_get0_signature 47 1_1_0 EXIST::FUNCTION: +X509_REVOKED_get0_extensions 48 1_1_0 EXIST::FUNCTION: +NETSCAPE_SPKI_verify 49 1_1_0 EXIST::FUNCTION: +i2d_OCSP_RESPONSE 50 1_1_0 EXIST::FUNCTION:OCSP +ERR_peek_error 51 1_1_0 EXIST::FUNCTION: +X509v3_asid_validate_resource_set 52 1_1_0 EXIST::FUNCTION:RFC3779 +PEM_write_bio_Parameters 53 1_1_0 EXIST::FUNCTION: +CMS_SignerInfo_verify 54 1_1_0 EXIST::FUNCTION:CMS +X509v3_asid_is_canonical 55 1_1_0 EXIST::FUNCTION:RFC3779 +ASN1_ENUMERATED_get 56 1_1_0 EXIST::FUNCTION: +EVP_MD_do_all_sorted 57 1_1_0 EXIST::FUNCTION: +OCSP_crl_reason_str 58 1_1_0 EXIST::FUNCTION:OCSP +ENGINE_ctrl_cmd_string 59 1_1_0 EXIST::FUNCTION:ENGINE +ENGINE_finish 60 1_1_0 EXIST::FUNCTION:ENGINE +SRP_Calc_client_key 61 1_1_0 EXIST::FUNCTION:SRP +X509_PUBKEY_free 62 1_1_0 EXIST::FUNCTION: +BIO_free_all 63 1_1_0 EXIST::FUNCTION: +EVP_idea_ofb 64 1_1_0 EXIST::FUNCTION:IDEA +DSO_bind_func 65 1_1_0 EXIST::FUNCTION: +EVP_PKEY_meth_get_copy 66 1_1_0 EXIST::FUNCTION: +RSA_up_ref 67 1_1_0 EXIST::FUNCTION:RSA +EVP_PKEY_meth_set_ctrl 68 1_1_0 EXIST::FUNCTION: +OCSP_basic_sign 69 1_1_0 EXIST::FUNCTION:OCSP +BN_GENCB_set 70 1_1_0 EXIST::FUNCTION: +BN_generate_prime 71 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_0_9_8 +d2i_DSAPrivateKey_fp 72 1_1_0 EXIST::FUNCTION:DSA,STDIO +BIO_nread0 73 1_1_0 EXIST::FUNCTION: +NETSCAPE_SPKI_print 74 1_1_0 EXIST::FUNCTION: +X509_set_pubkey 75 1_1_0 EXIST::FUNCTION: +ASN1_item_print 76 1_1_0 EXIST::FUNCTION: +CONF_set_nconf 77 1_1_0 EXIST::FUNCTION: +RAND_set_rand_method 78 1_1_0 EXIST::FUNCTION: +BN_GF2m_mod_mul 79 1_1_0 EXIST::FUNCTION:EC2M +UI_add_input_boolean 80 1_1_0 EXIST::FUNCTION: +ASN1_TIME_adj 81 1_1_0 EXIST::FUNCTION: +EVP_PKEY_asn1_get0_info 82 1_1_0 EXIST::FUNCTION: +BN_add_word 83 1_1_0 EXIST::FUNCTION: +EVP_des_ede 84 1_1_0 EXIST::FUNCTION:DES +EVP_PKEY_add1_attr_by_OBJ 85 1_1_0 EXIST::FUNCTION: +ASYNC_WAIT_CTX_get_all_fds 86 1_1_0 EXIST::FUNCTION: +EVP_CIPHER_meth_set_do_cipher 87 1_1_0 EXIST::FUNCTION: +EVP_set_pw_prompt 88 1_1_0 EXIST::FUNCTION: +d2i_OCSP_RESPBYTES 89 1_1_0 EXIST::FUNCTION:OCSP +TS_REQ_get_ext_by_NID 90 1_1_0 EXIST::FUNCTION:TS +ASN1_item_ndef_i2d 91 1_1_0 EXIST::FUNCTION: +OCSP_archive_cutoff_new 92 1_1_0 EXIST::FUNCTION:OCSP +DSA_size 93 1_1_0 EXIST::FUNCTION:DSA +IPAddressRange_free 94 1_1_0 EXIST::FUNCTION:RFC3779 +CMS_ContentInfo_free 95 1_1_0 EXIST::FUNCTION:CMS +BIO_accept 96 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0,SOCK +X509_VERIFY_PARAM_set1_policies 97 1_1_0 EXIST::FUNCTION: +SCT_set0_extensions 98 1_1_0 EXIST::FUNCTION:CT +PKCS5_pbe2_set_scrypt 99 1_1_0 EXIST::FUNCTION:SCRYPT +X509_find_by_subject 100 1_1_0 EXIST::FUNCTION: +DSAparams_print 101 1_1_0 EXIST::FUNCTION:DSA +BF_set_key 102 1_1_0 EXIST::FUNCTION:BF +d2i_DHparams 103 1_1_0 EXIST::FUNCTION:DH +i2d_PKCS7_ENC_CONTENT 104 1_1_0 EXIST::FUNCTION: +DH_generate_key 105 1_1_0 EXIST::FUNCTION:DH +ENGINE_add_conf_module 106 1_1_0 EXIST::FUNCTION:ENGINE +BIO_new_socket 107 1_1_0 EXIST::FUNCTION:SOCK +ASN1_OBJECT_free 108 1_1_0 EXIST::FUNCTION: +X509_REQ_get_extensions 109 1_1_0 EXIST::FUNCTION: +X509_get_version 110 1_1_0 EXIST::FUNCTION: +OCSP_CERTID_dup 111 1_1_0 EXIST::FUNCTION:OCSP +RSA_PSS_PARAMS_free 112 1_1_0 EXIST::FUNCTION:RSA +i2d_TS_MSG_IMPRINT 113 1_1_0 EXIST::FUNCTION:TS +EC_POINT_mul 114 1_1_0 EXIST::FUNCTION:EC +WHIRLPOOL_Final 115 1_1_0 EXIST::FUNCTION:WHIRLPOOL +CMS_get1_ReceiptRequest 116 1_1_0 EXIST::FUNCTION:CMS +BIO_sock_non_fatal_error 117 1_1_0 EXIST::FUNCTION:SOCK +HMAC_Update 118 1_1_0 EXIST::FUNCTION: +i2d_PKCS12 119 1_1_0 EXIST::FUNCTION: +EVP_BytesToKey 120 1_1_0 EXIST::FUNCTION: +ENGINE_set_default_pkey_asn1_meths 121 1_1_0 EXIST::FUNCTION:ENGINE +OCSP_BASICRESP_add1_ext_i2d 122 1_1_0 EXIST::FUNCTION:OCSP +EVP_camellia_128_ctr 123 1_1_0 EXIST::FUNCTION:CAMELLIA +EVP_CIPHER_impl_ctx_size 124 1_1_0 EXIST::FUNCTION: +X509_CRL_get_nextUpdate 125 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0 +PKCS12_free 126 1_1_0 EXIST::FUNCTION: +CMS_signed_get_attr 127 1_1_0 EXIST::FUNCTION:CMS +ENGINE_set_destroy_function 128 1_1_0 EXIST::FUNCTION:ENGINE +ASN1_STRING_TABLE_add 129 1_1_0 EXIST::FUNCTION: +d2i_ASIdentifiers 130 1_1_0 EXIST::FUNCTION:RFC3779 +i2d_PKCS12_bio 131 1_1_0 EXIST::FUNCTION: +X509_to_X509_REQ 132 1_1_0 EXIST::FUNCTION: +OCSP_basic_add1_nonce 133 1_1_0 EXIST::FUNCTION:OCSP +d2i_OCSP_BASICRESP 134 1_1_0 EXIST::FUNCTION:OCSP +X509v3_add_ext 135 1_1_0 EXIST::FUNCTION: +X509v3_addr_subset 136 1_1_0 EXIST::FUNCTION:RFC3779 +CRYPTO_strndup 137 1_1_0 EXIST::FUNCTION: +OCSP_REQ_CTX_free 138 1_1_0 EXIST::FUNCTION:OCSP +X509_STORE_new 140 1_1_0 EXIST::FUNCTION: +ASN1_TYPE_free 141 1_1_0 EXIST::FUNCTION: +PKCS12_BAGS_new 142 1_1_0 EXIST::FUNCTION: +CMAC_CTX_new 143 1_1_0 EXIST::FUNCTION:CMAC +ASIdentifierChoice_new 144 1_1_0 EXIST::FUNCTION:RFC3779 +EVP_PKEY_asn1_set_public 145 1_1_0 EXIST::FUNCTION: +IDEA_set_decrypt_key 146 1_1_0 EXIST::FUNCTION:IDEA +X509_STORE_CTX_set_flags 147 1_1_0 EXIST::FUNCTION: +BIO_ADDR_rawmake 148 1_1_0 EXIST::FUNCTION:SOCK +EVP_PKEY_asn1_set_ctrl 149 1_1_0 EXIST::FUNCTION: +EC_POINTs_mul 150 1_1_0 EXIST::FUNCTION:EC +ASN1_get_object 151 1_1_0 EXIST::FUNCTION: +i2d_IPAddressFamily 152 1_1_0 EXIST::FUNCTION:RFC3779 +ENGINE_get_ctrl_function 153 1_1_0 EXIST::FUNCTION:ENGINE +X509_REVOKED_get_ext_count 154 1_1_0 EXIST::FUNCTION: +BN_is_prime_fasttest_ex 155 1_1_0 EXIST::FUNCTION: +ERR_load_PKCS12_strings 156 1_1_0 EXIST::FUNCTION: +EVP_sha384 157 1_1_0 EXIST::FUNCTION: +i2d_DHparams 158 1_1_0 EXIST::FUNCTION:DH +TS_VERIFY_CTX_set_store 159 1_1_0 EXIST::FUNCTION:TS +PKCS12_verify_mac 160 1_1_0 EXIST::FUNCTION: +X509v3_addr_canonize 161 1_1_0 EXIST::FUNCTION:RFC3779 +ASN1_item_ex_i2d 162 1_1_0 EXIST::FUNCTION: +ENGINE_set_digests 163 1_1_0 EXIST::FUNCTION:ENGINE +PEM_ASN1_read_bio 164 1_1_0 EXIST::FUNCTION: +CT_POLICY_EVAL_CTX_free 165 1_1_0 EXIST::FUNCTION:CT +CMS_RecipientInfo_kari_get0_ctx 166 1_1_0 EXIST::FUNCTION:CMS +PKCS7_set_attributes 167 1_1_0 EXIST::FUNCTION: +d2i_POLICYQUALINFO 168 1_1_0 EXIST::FUNCTION: +EVP_MD_type 170 1_1_0 EXIST::FUNCTION: +EVP_PKCS82PKEY 171 1_1_0 EXIST::FUNCTION: +BN_generate_prime_ex 172 1_1_0 EXIST::FUNCTION: +EVP_EncryptInit 173 1_1_0 EXIST::FUNCTION: +RAND_OpenSSL 174 1_1_0 EXIST::FUNCTION: +BN_uadd 175 1_1_0 EXIST::FUNCTION: +EVP_PKEY_derive_init 176 1_1_0 EXIST::FUNCTION: +PEM_write_bio_ASN1_stream 177 1_1_0 EXIST::FUNCTION: +EVP_PKEY_delete_attr 178 1_1_0 EXIST::FUNCTION: +EVP_CIPHER_CTX_key_length 179 1_1_0 EXIST::FUNCTION: +BIO_clear_flags 180 1_1_0 EXIST::FUNCTION: +i2d_DISPLAYTEXT 181 1_1_0 EXIST::FUNCTION: +OCSP_response_status 182 1_1_0 EXIST::FUNCTION:OCSP +i2d_ASN1_PRINTABLESTRING 183 1_1_0 EXIST::FUNCTION: +X509_VERIFY_PARAM_set_hostflags 184 1_1_0 EXIST::FUNCTION: +SCT_get0_log_id 185 1_1_0 EXIST::FUNCTION:CT +ASN1_IA5STRING_it 186 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ASN1_IA5STRING_it 186 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +PEM_write_bio_ECPrivateKey 187 1_1_0 EXIST::FUNCTION:EC +BN_consttime_swap 188 1_1_0 EXIST::FUNCTION: +BIO_f_buffer 189 1_1_0 EXIST::FUNCTION: +CMS_SignerInfo_get0_signer_id 190 1_1_0 EXIST::FUNCTION:CMS +TS_TST_INFO_new 191 1_1_0 EXIST::FUNCTION:TS +X509_REQ_check_private_key 192 1_1_0 EXIST::FUNCTION: +EVP_DigestInit 193 1_1_0 EXIST::FUNCTION: +EVP_PKEY_meth_find 194 1_1_0 EXIST::FUNCTION: +X509_VERIFY_PARAM_get_count 195 1_1_0 EXIST::FUNCTION: +ASN1_BIT_STRING_get_bit 196 1_1_0 EXIST::FUNCTION: +EVP_PKEY_cmp 197 1_1_0 EXIST::FUNCTION: +d2i_X509_ALGORS 198 1_1_0 EXIST::FUNCTION: +EVP_PKEY2PKCS8 199 1_1_0 EXIST::FUNCTION: +BN_nist_mod_256 200 1_1_0 EXIST::FUNCTION: +OCSP_request_add0_id 201 1_1_0 EXIST::FUNCTION:OCSP +EVP_seed_cfb128 202 1_1_0 EXIST::FUNCTION:SEED +BASIC_CONSTRAINTS_free 203 1_1_0 EXIST::FUNCTION: +EVP_CIPHER_flags 204 1_1_0 EXIST::FUNCTION: +PEM_write_bio_ECPKParameters 205 1_1_0 EXIST::FUNCTION:EC +SCT_set_version 206 1_1_0 EXIST::FUNCTION:CT +CMS_add1_ReceiptRequest 207 1_1_0 EXIST::FUNCTION:CMS +d2i_CRL_DIST_POINTS 208 1_1_0 EXIST::FUNCTION: +X509_CRL_INFO_free 209 1_1_0 EXIST::FUNCTION: +ERR_load_UI_strings 210 1_1_0 EXIST::FUNCTION: +ERR_load_strings 211 1_1_0 EXIST::FUNCTION: +RSA_X931_hash_id 212 1_1_0 EXIST::FUNCTION:RSA +EC_KEY_set_method 213 1_1_0 EXIST::FUNCTION:EC +PEM_write_PKCS8_PRIV_KEY_INFO 214 1_1_0 EXIST::FUNCTION:STDIO +X509at_get0_data_by_OBJ 215 1_1_0 EXIST::FUNCTION: +b2i_PublicKey_bio 216 1_1_0 EXIST::FUNCTION:DSA +s2i_ASN1_OCTET_STRING 217 1_1_0 EXIST::FUNCTION: +POLICYINFO_it 218 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +POLICYINFO_it 218 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +OBJ_create 219 1_1_0 EXIST::FUNCTION: +d2i_NOTICEREF 220 1_1_0 EXIST::FUNCTION: +BN_get_rfc2409_prime_768 221 1_1_0 EXIST::FUNCTION: +PEM_read_bio_PKCS8 222 1_1_0 EXIST::FUNCTION: +X509_ATTRIBUTE_new 223 1_1_0 EXIST::FUNCTION: +ASN1_STRING_TABLE_cleanup 224 1_1_0 EXIST::FUNCTION: +ASN1_put_eoc 225 1_1_0 EXIST::FUNCTION: +EVP_MD_meth_set_input_blocksize 226 1_1_0 EXIST::FUNCTION: +PKCS12_SAFEBAG_get0_attrs 227 1_1_0 EXIST::FUNCTION: +PKCS8_get_attr 228 1_1_0 EXIST::FUNCTION: +DSAparams_print_fp 229 1_1_0 EXIST::FUNCTION:DSA,STDIO +EC_POINT_set_Jprojective_coordinates_GFp 230 1_1_0 EXIST::FUNCTION:EC +DIST_POINT_NAME_new 231 1_1_0 EXIST::FUNCTION: +X509_LOOKUP_file 232 1_1_0 EXIST::FUNCTION: +EVP_PKEY_meth_set_decrypt 233 1_1_0 EXIST::FUNCTION: +EVP_rc2_ecb 234 1_1_0 EXIST::FUNCTION:RC2 +i2b_PublicKey_bio 235 1_1_0 EXIST::FUNCTION:DSA +d2i_ASN1_SET_ANY 236 1_1_0 EXIST::FUNCTION: +ASN1_item_i2d 238 1_1_0 EXIST::FUNCTION: +OCSP_copy_nonce 239 1_1_0 EXIST::FUNCTION:OCSP +OBJ_txt2nid 240 1_1_0 EXIST::FUNCTION: +SEED_set_key 241 1_1_0 EXIST::FUNCTION:SEED +EC_KEY_clear_flags 242 1_1_0 EXIST::FUNCTION:EC +CMS_RecipientInfo_ktri_get0_algs 243 1_1_0 EXIST::FUNCTION:CMS +i2d_EC_PUBKEY 244 1_1_0 EXIST::FUNCTION:EC +MDC2 245 1_1_0 EXIST::FUNCTION:MDC2 +BN_clear_free 246 1_1_0 EXIST::FUNCTION: +ENGINE_get_pkey_asn1_meths 247 1_1_0 EXIST::FUNCTION:ENGINE +DSO_merge 248 1_1_0 EXIST::FUNCTION: +RSA_get_ex_data 249 1_1_0 EXIST::FUNCTION:RSA +EVP_PKEY_meth_get_decrypt 250 1_1_0 EXIST::FUNCTION: +DES_cfb_encrypt 251 1_1_0 EXIST::FUNCTION:DES +CMS_SignerInfo_set1_signer_cert 252 1_1_0 EXIST::FUNCTION:CMS +X509_CRL_http_nbio 253 1_1_0 EXIST::FUNCTION:OCSP +ENGINE_register_all_ciphers 254 1_1_0 EXIST::FUNCTION:ENGINE +SXNET_new 255 1_1_0 EXIST::FUNCTION: +EVP_camellia_256_ctr 256 1_1_0 EXIST::FUNCTION:CAMELLIA +d2i_PKCS8_PRIV_KEY_INFO 257 1_1_0 EXIST::FUNCTION: +EVP_md2 259 1_1_0 EXIST::FUNCTION:MD2 +RC2_ecb_encrypt 260 1_1_0 EXIST::FUNCTION:RC2 +ENGINE_register_DH 261 1_1_0 EXIST::FUNCTION:ENGINE +ASN1_NULL_free 262 1_1_0 EXIST::FUNCTION: +EC_KEY_copy 263 1_1_0 EXIST::FUNCTION:EC +EVP_des_ede3 264 1_1_0 EXIST::FUNCTION:DES +PKCS7_add1_attrib_digest 265 1_1_0 EXIST::FUNCTION: +EC_POINT_get_affine_coordinates_GFp 266 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_2_0,EC +EVP_seed_ecb 267 1_1_0 EXIST::FUNCTION:SEED +BIO_dgram_sctp_wait_for_dry 268 1_1_0 EXIST::FUNCTION:DGRAM,SCTP +ASN1_OCTET_STRING_NDEF_it 269 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ASN1_OCTET_STRING_NDEF_it 269 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +EVP_PKEY_asn1_get_count 270 1_1_0 EXIST::FUNCTION: +WHIRLPOOL_Init 271 1_1_0 EXIST::FUNCTION:WHIRLPOOL +EVP_OpenInit 272 1_1_0 EXIST::FUNCTION:RSA +OCSP_response_get1_basic 273 1_1_0 EXIST::FUNCTION:OCSP +CRYPTO_gcm128_tag 274 1_1_0 EXIST::FUNCTION: +OCSP_parse_url 275 1_1_0 EXIST::FUNCTION:OCSP +UI_get0_test_string 276 1_1_0 EXIST::FUNCTION: +CRYPTO_secure_free 277 1_1_0 EXIST::FUNCTION: +DSA_print_fp 278 1_1_0 EXIST::FUNCTION:DSA,STDIO +X509_get_ext_d2i 279 1_1_0 EXIST::FUNCTION: +d2i_PKCS7_ENC_CONTENT 280 1_1_0 EXIST::FUNCTION: +BUF_MEM_grow 281 1_1_0 EXIST::FUNCTION: +TS_REQ_free 282 1_1_0 EXIST::FUNCTION:TS +PEM_read_DHparams 283 1_1_0 EXIST::FUNCTION:DH,STDIO +RSA_private_decrypt 284 1_1_0 EXIST::FUNCTION:RSA +X509V3_EXT_get_nid 285 1_1_0 EXIST::FUNCTION: +BIO_s_log 286 1_1_0 EXIST::FUNCTION: +EC_POINT_set_to_infinity 287 1_1_0 EXIST::FUNCTION:EC +EVP_des_ede_ofb 288 1_1_0 EXIST::FUNCTION:DES +ECDH_KDF_X9_62 289 1_1_0 EXIST::FUNCTION:EC +ASN1_UNIVERSALSTRING_to_string 290 1_1_0 EXIST::FUNCTION: +CRYPTO_gcm128_setiv 291 1_1_0 EXIST::FUNCTION: +ASN1_PCTX_set_oid_flags 292 1_1_0 EXIST::FUNCTION: +d2i_ASN1_INTEGER 293 1_1_0 EXIST::FUNCTION: +i2d_PKCS7_ENCRYPT 294 1_1_0 EXIST::FUNCTION: +CT_POLICY_EVAL_CTX_set1_issuer 295 1_1_0 EXIST::FUNCTION:CT +X509_NAME_ENTRY_set 296 1_1_0 EXIST::FUNCTION: +PKCS8_set0_pbe 297 1_1_0 EXIST::FUNCTION: +PEM_write_bio_DSA_PUBKEY 298 1_1_0 EXIST::FUNCTION:DSA +PEM_X509_INFO_read_bio 299 1_1_0 EXIST::FUNCTION: +EC_GROUP_get0_order 300 1_1_0 EXIST::FUNCTION:EC +OCSP_BASICRESP_delete_ext 301 1_1_0 EXIST::FUNCTION:OCSP +PKCS12_get_attr_gen 302 1_1_0 EXIST::FUNCTION: +PKCS12_SAFEBAG_get0_safes 303 1_1_0 EXIST::FUNCTION: +EVP_PKEY_derive 304 1_1_0 EXIST::FUNCTION: +OCSP_BASICRESP_get_ext_by_NID 305 1_1_0 EXIST::FUNCTION:OCSP +OBJ_dup 306 1_1_0 EXIST::FUNCTION: +CMS_signed_get_attr_count 307 1_1_0 EXIST::FUNCTION:CMS +EC_get_builtin_curves 308 1_1_0 EXIST::FUNCTION:EC +i2d_ASN1_IA5STRING 309 1_1_0 EXIST::FUNCTION: +OCSP_check_nonce 310 1_1_0 EXIST::FUNCTION:OCSP +X509_STORE_CTX_init 311 1_1_0 EXIST::FUNCTION: +OCSP_RESPONSE_free 312 1_1_0 EXIST::FUNCTION:OCSP +ENGINE_set_DH 313 1_1_0 EXIST::FUNCTION:ENGINE +EVP_CIPHER_CTX_set_flags 314 1_1_0 EXIST::FUNCTION: +err_free_strings_int 315 1_1_0 EXIST::FUNCTION: +PEM_write_bio_PKCS7_stream 316 1_1_0 EXIST::FUNCTION: +d2i_X509_CERT_AUX 317 1_1_0 EXIST::FUNCTION: +UI_process 318 1_1_0 EXIST::FUNCTION: +X509_get_subject_name 319 1_1_0 EXIST::FUNCTION: +DH_get_1024_160 320 1_1_0 EXIST::FUNCTION:DH +i2d_ASN1_UNIVERSALSTRING 321 1_1_0 EXIST::FUNCTION: +d2i_OCSP_RESPID 322 1_1_0 EXIST::FUNCTION:OCSP +BIO_s_accept 323 1_1_0 EXIST::FUNCTION:SOCK +EVP_whirlpool 324 1_1_0 EXIST::FUNCTION:WHIRLPOOL +OCSP_ONEREQ_get1_ext_d2i 325 1_1_0 EXIST::FUNCTION:OCSP +d2i_ESS_SIGNING_CERT 326 1_1_0 EXIST::FUNCTION:TS +EC_KEY_set_default_method 327 1_1_0 EXIST::FUNCTION:EC +X509_OBJECT_up_ref_count 328 1_1_0 EXIST::FUNCTION: +RAND_load_file 329 1_1_0 EXIST::FUNCTION: +BIO_ctrl_reset_read_request 330 1_1_0 EXIST::FUNCTION: +CRYPTO_ccm128_tag 331 1_1_0 EXIST::FUNCTION: +BIO_new_dgram_sctp 332 1_1_0 EXIST::FUNCTION:DGRAM,SCTP +d2i_RSAPrivateKey_fp 333 1_1_0 EXIST::FUNCTION:RSA,STDIO +s2i_ASN1_IA5STRING 334 1_1_0 EXIST::FUNCTION: +UI_get_ex_data 335 1_1_0 EXIST::FUNCTION: +EVP_EncryptUpdate 336 1_1_0 EXIST::FUNCTION: +SRP_create_verifier 337 1_1_0 EXIST::FUNCTION:SRP +TS_TST_INFO_print_bio 338 1_1_0 EXIST::FUNCTION:TS +X509_NAME_get_index_by_OBJ 339 1_1_0 EXIST::FUNCTION: +BIO_get_host_ip 340 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0,SOCK +PKCS7_add_certificate 341 1_1_0 EXIST::FUNCTION: +TS_REQ_get_ext 342 1_1_0 EXIST::FUNCTION:TS +X509_NAME_cmp 343 1_1_0 EXIST::FUNCTION: +DIST_POINT_it 344 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +DIST_POINT_it 344 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +PEM_read_X509_CRL 345 1_1_0 EXIST::FUNCTION:STDIO +OPENSSL_sk_sort 346 1_1_0 EXIST::FUNCTION: +CTLOG_STORE_load_file 347 1_1_0 EXIST::FUNCTION:CT +ASN1_SEQUENCE_it 348 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ASN1_SEQUENCE_it 348 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +TS_RESP_CTX_get_tst_info 349 1_1_0 EXIST::FUNCTION:TS +RC4 350 1_1_0 EXIST::FUNCTION:RC4 +PKCS7_stream 352 1_1_0 EXIST::FUNCTION: +i2t_ASN1_OBJECT 353 1_1_0 EXIST::FUNCTION: +EC_GROUP_get0_generator 354 1_1_0 EXIST::FUNCTION:EC +RSA_padding_add_PKCS1_PSS_mgf1 355 1_1_0 EXIST::FUNCTION:RSA +EVP_MD_meth_set_init 356 1_1_0 EXIST::FUNCTION: +X509_get_issuer_name 357 1_1_0 EXIST::FUNCTION: +EVP_SignFinal 358 1_1_0 EXIST::FUNCTION: +PKCS12_mac_present 359 1_1_0 EXIST::FUNCTION: +d2i_PUBKEY_bio 360 1_1_0 EXIST::FUNCTION: +BN_asc2bn 361 1_1_0 EXIST::FUNCTION: +EVP_desx_cbc 362 1_1_0 EXIST::FUNCTION:DES +SXNETID_it 363 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +SXNETID_it 363 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +CRYPTO_gcm128_encrypt 364 1_1_0 EXIST::FUNCTION: +EVP_PKEY_CTX_ctrl_str 365 1_1_0 EXIST::FUNCTION: +CMS_signed_add1_attr_by_txt 366 1_1_0 EXIST::FUNCTION:CMS +i2d_NETSCAPE_SPKAC 367 1_1_0 EXIST::FUNCTION: +X509V3_add_value_bool_nf 368 1_1_0 EXIST::FUNCTION: +ASN1_item_verify 369 1_1_0 EXIST::FUNCTION: +SEED_ecb_encrypt 370 1_1_0 EXIST::FUNCTION:SEED +X509_PUBKEY_get0_param 371 1_1_0 EXIST::FUNCTION: +ASN1_i2d_fp 372 1_1_0 EXIST::FUNCTION:STDIO +BIO_new_mem_buf 373 1_1_0 EXIST::FUNCTION: +UI_get_input_flags 374 1_1_0 EXIST::FUNCTION: +X509V3_EXT_REQ_add_nconf 375 1_1_0 EXIST::FUNCTION: +X509v3_asid_subset 376 1_1_0 EXIST::FUNCTION:RFC3779 +RSA_check_key_ex 377 1_1_0 EXIST::FUNCTION:RSA +d2i_TS_MSG_IMPRINT_bio 378 1_1_0 EXIST::FUNCTION:TS +i2d_ASN1_TYPE 379 1_1_0 EXIST::FUNCTION: +EVP_aes_256_wrap_pad 380 1_1_0 EXIST::FUNCTION: +CMS_RecipientInfo_kekri_id_cmp 381 1_1_0 EXIST::FUNCTION:CMS +X509_VERIFY_PARAM_get0_peername 382 1_1_0 EXIST::FUNCTION: +ASN1_PCTX_get_oid_flags 383 1_1_0 EXIST::FUNCTION: +CONF_free 384 1_1_0 EXIST::FUNCTION: +DSO_get_filename 385 1_1_0 EXIST::FUNCTION: +i2d_ASN1_SEQUENCE_ANY 387 1_1_0 EXIST::FUNCTION: +OPENSSL_strlcpy 388 1_1_0 EXIST::FUNCTION: +BIO_get_port 389 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0,SOCK +DISPLAYTEXT_free 390 1_1_0 EXIST::FUNCTION: +BN_div 391 1_1_0 EXIST::FUNCTION: +RIPEMD160_Update 392 1_1_0 EXIST::FUNCTION:RMD160 +PEM_write_bio_CMS 393 1_1_0 EXIST::FUNCTION:CMS +ASN1_OBJECT_new 394 1_1_0 EXIST::FUNCTION: +EVP_des_ede3_cfb8 395 1_1_0 EXIST::FUNCTION:DES +BIO_dump_indent_fp 396 1_1_0 EXIST::FUNCTION:STDIO +X509_NAME_ENTRY_get_data 397 1_1_0 EXIST::FUNCTION: +BIO_socket 398 1_1_0 EXIST::FUNCTION:SOCK +EVP_PKEY_meth_get_derive 399 1_1_0 EXIST::FUNCTION: +ASN1_STRING_clear_free 400 1_1_0 EXIST::FUNCTION: +d2i_OCSP_REVOKEDINFO 401 1_1_0 EXIST::FUNCTION:OCSP +ASN1_STRING_print_ex_fp 402 1_1_0 EXIST::FUNCTION:STDIO +PKCS7_SIGNED_new 403 1_1_0 EXIST::FUNCTION: +CMS_get0_eContentType 404 1_1_0 EXIST::FUNCTION:CMS +HMAC_Final 405 1_1_0 EXIST::FUNCTION: +X509_CRL_delete_ext 406 1_1_0 EXIST::FUNCTION: +TS_TST_INFO_get_ordering 407 1_1_0 EXIST::FUNCTION:TS +X509_get_extended_key_usage 408 1_1_0 EXIST::FUNCTION: +ERR_print_errors 409 1_1_0 EXIST::FUNCTION: +X509_REVOKED_set_revocationDate 410 1_1_0 EXIST::FUNCTION: +EVP_CipherFinal_ex 411 1_1_0 EXIST::FUNCTION: +d2i_DSA_PUBKEY 412 1_1_0 EXIST::FUNCTION:DSA +BN_CTX_get 413 1_1_0 EXIST::FUNCTION: +BN_to_montgomery 414 1_1_0 EXIST::FUNCTION: +X509_OBJECT_get0_X509_CRL 415 1_1_0 EXIST::FUNCTION: +EVP_camellia_128_cfb8 416 1_1_0 EXIST::FUNCTION:CAMELLIA +EC_KEY_METHOD_free 417 1_1_0 EXIST::FUNCTION:EC +TS_TST_INFO_set_policy_id 418 1_1_0 EXIST::FUNCTION:TS +d2i_EXTENDED_KEY_USAGE 419 1_1_0 EXIST::FUNCTION: +ASYNC_unblock_pause 420 1_1_0 EXIST::FUNCTION: +i2d_X509_VAL 421 1_1_0 EXIST::FUNCTION: +ASN1_SCTX_get_flags 422 1_1_0 EXIST::FUNCTION: +RIPEMD160 423 1_1_0 EXIST::FUNCTION:RMD160 +CRYPTO_ocb128_setiv 424 1_1_0 EXIST::FUNCTION:OCB +X509_CRL_digest 425 1_1_0 EXIST::FUNCTION: +EVP_aes_128_cbc_hmac_sha1 426 1_1_0 EXIST::FUNCTION: +ERR_load_CMS_strings 427 1_1_0 EXIST::FUNCTION:CMS +EVP_MD_CTX_md 428 1_1_0 EXIST::FUNCTION: +X509_REVOKED_get_ext 429 1_1_0 EXIST::FUNCTION: +d2i_RSA_PSS_PARAMS 430 1_1_0 EXIST::FUNCTION:RSA +USERNOTICE_free 431 1_1_0 EXIST::FUNCTION: +MD4_Transform 432 1_1_0 EXIST::FUNCTION:MD4 +EVP_CIPHER_block_size 433 1_1_0 EXIST::FUNCTION: +CERTIFICATEPOLICIES_new 434 1_1_0 EXIST::FUNCTION: +BIO_dump_fp 435 1_1_0 EXIST::FUNCTION:STDIO +BIO_set_flags 436 1_1_0 EXIST::FUNCTION: +BN_is_one 437 1_1_0 EXIST::FUNCTION: +TS_CONF_set_def_policy 438 1_1_0 EXIST::FUNCTION:TS +DSA_free 439 1_1_0 EXIST::FUNCTION:DSA +BN_GENCB_new 440 1_1_0 EXIST::FUNCTION: +X509_VAL_new 441 1_1_0 EXIST::FUNCTION: +NCONF_load 442 1_1_0 EXIST::FUNCTION: +ASN1_put_object 443 1_1_0 EXIST::FUNCTION: +d2i_OCSP_RESPONSE 444 1_1_0 EXIST::FUNCTION:OCSP +d2i_PublicKey 445 1_1_0 EXIST::FUNCTION: +ENGINE_set_ex_data 446 1_1_0 EXIST::FUNCTION:ENGINE +X509_get_default_private_dir 447 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_set0_dane 448 1_1_0 EXIST::FUNCTION: +EVP_des_ecb 449 1_1_0 EXIST::FUNCTION:DES +OCSP_resp_get0 450 1_1_0 EXIST::FUNCTION:OCSP +RSA_X931_generate_key_ex 452 1_1_0 EXIST::FUNCTION:RSA +X509_get_serialNumber 453 1_1_0 EXIST::FUNCTION: +BIO_sock_should_retry 454 1_1_0 EXIST::FUNCTION:SOCK +ENGINE_get_digests 455 1_1_0 EXIST::FUNCTION:ENGINE +TS_MSG_IMPRINT_get_algo 456 1_1_0 EXIST::FUNCTION:TS +DH_new_method 457 1_1_0 EXIST::FUNCTION:DH +BF_ecb_encrypt 458 1_1_0 EXIST::FUNCTION:BF +PEM_write_bio_DHparams 459 1_1_0 EXIST::FUNCTION:DH +EVP_DigestFinal 460 1_1_0 EXIST::FUNCTION: +CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE 461 1_1_0 EXIST::FUNCTION:CT +X509v3_asid_add_id_or_range 462 1_1_0 EXIST::FUNCTION:RFC3779 +X509_NAME_ENTRY_create_by_NID 463 1_1_0 EXIST::FUNCTION: +EC_KEY_METHOD_get_init 464 1_1_0 EXIST::FUNCTION:EC +ASN1_INTEGER_to_BN 465 1_1_0 EXIST::FUNCTION: +OPENSSL_memcmp 466 1_1_0 EXIST::FUNCTION: +BUF_MEM_new 467 1_1_0 EXIST::FUNCTION: +DSO_set_filename 468 1_1_0 EXIST::FUNCTION: +DH_new 469 1_1_0 EXIST::FUNCTION:DH +OCSP_RESPID_free 470 1_1_0 EXIST::FUNCTION:OCSP +PKCS5_pbe2_set 471 1_1_0 EXIST::FUNCTION: +SCT_set_signature_nid 473 1_1_0 EXIST::FUNCTION:CT +i2d_RSA_PUBKEY_fp 474 1_1_0 EXIST::FUNCTION:RSA,STDIO +PKCS12_BAGS_it 475 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +PKCS12_BAGS_it 475 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +X509_pubkey_digest 476 1_1_0 EXIST::FUNCTION: +ENGINE_register_all_RSA 477 1_1_0 EXIST::FUNCTION:ENGINE +CRYPTO_THREAD_set_local 478 1_1_0 EXIST::FUNCTION: +X509_get_default_cert_dir_env 479 1_1_0 EXIST::FUNCTION: +X509_CRL_sort 480 1_1_0 EXIST::FUNCTION: +i2d_RSA_PUBKEY_bio 481 1_1_0 EXIST::FUNCTION:RSA +ASN1_T61STRING_free 482 1_1_0 EXIST::FUNCTION: +PEM_write_CMS 483 1_1_0 EXIST::FUNCTION:CMS,STDIO +OPENSSL_sk_find 484 1_1_0 EXIST::FUNCTION: +ENGINE_get_ciphers 485 1_1_0 EXIST::FUNCTION:ENGINE +EVP_rc2_ofb 486 1_1_0 EXIST::FUNCTION:RC2 +EVP_PKEY_set1_RSA 487 1_1_0 EXIST::FUNCTION:RSA +CMS_SignerInfo_get0_md_ctx 488 1_1_0 EXIST::FUNCTION:CMS +X509_STORE_set_trust 489 1_1_0 EXIST::FUNCTION: +d2i_POLICYINFO 490 1_1_0 EXIST::FUNCTION: +DES_cbc_encrypt 491 1_1_0 EXIST::FUNCTION:DES +BN_GF2m_mod_sqr_arr 492 1_1_0 EXIST::FUNCTION:EC2M +ASN1_PRINTABLESTRING_it 493 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ASN1_PRINTABLESTRING_it 493 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +BIO_f_cipher 494 1_1_0 EXIST::FUNCTION: +UI_destroy_method 495 1_1_0 EXIST::FUNCTION: +BN_get_rfc3526_prime_3072 496 1_1_0 EXIST::FUNCTION: +X509_INFO_new 497 1_1_0 EXIST::FUNCTION: +OCSP_RESPDATA_it 498 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:OCSP +OCSP_RESPDATA_it 498 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:OCSP +X509_CRL_print 499 1_1_0 EXIST::FUNCTION: +WHIRLPOOL_Update 500 1_1_0 EXIST::FUNCTION:WHIRLPOOL +DSA_get_ex_data 501 1_1_0 EXIST::FUNCTION:DSA +BN_copy 502 1_1_0 EXIST::FUNCTION: +FIPS_mode_set 503 1_1_0 EXIST::FUNCTION: +X509_VERIFY_PARAM_add0_policy 504 1_1_0 EXIST::FUNCTION: +PKCS7_cert_from_signer_info 505 1_1_0 EXIST::FUNCTION: +X509_TRUST_get_trust 506 1_1_0 EXIST::FUNCTION: +DES_string_to_key 507 1_1_0 EXIST::FUNCTION:DES +ERR_error_string 508 1_1_0 EXIST::FUNCTION: +BIO_new_connect 509 1_1_0 EXIST::FUNCTION:SOCK +DSA_new_method 511 1_1_0 EXIST::FUNCTION:DSA +OCSP_CERTID_new 512 1_1_0 EXIST::FUNCTION:OCSP +X509_CRL_get_signature_nid 513 1_1_0 EXIST::FUNCTION: +X509_policy_level_node_count 514 1_1_0 EXIST::FUNCTION: +d2i_OCSP_CERTSTATUS 515 1_1_0 EXIST::FUNCTION:OCSP +X509V3_add1_i2d 516 1_1_0 EXIST::FUNCTION: +TS_TST_INFO_set_serial 517 1_1_0 EXIST::FUNCTION:TS +OCSP_RESPBYTES_new 518 1_1_0 EXIST::FUNCTION:OCSP +OCSP_SINGLERESP_delete_ext 519 1_1_0 EXIST::FUNCTION:OCSP +EVP_MD_CTX_test_flags 521 1_1_0 EXIST::FUNCTION: +X509v3_addr_validate_path 522 1_1_0 EXIST::FUNCTION:RFC3779 +BIO_new_fp 523 1_1_0 EXIST::FUNCTION:STDIO +EC_GROUP_set_generator 524 1_1_0 EXIST::FUNCTION:EC +CRYPTO_memdup 525 1_1_0 EXIST::FUNCTION: +DH_generate_parameters 526 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_0_9_8,DH +BN_set_negative 527 1_1_0 EXIST::FUNCTION: +i2d_TS_RESP_bio 528 1_1_0 EXIST::FUNCTION:TS +ASYNC_WAIT_CTX_set_wait_fd 529 1_1_0 EXIST::FUNCTION: +ERR_func_error_string 530 1_1_0 EXIST::FUNCTION: +ASN1_STRING_data 531 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0 +X509_CRL_add1_ext_i2d 532 1_1_0 EXIST::FUNCTION: +i2d_TS_TST_INFO 533 1_1_0 EXIST::FUNCTION:TS +OBJ_sigid_free 534 1_1_0 EXIST::FUNCTION: +TS_STATUS_INFO_get0_status 535 1_1_0 EXIST::FUNCTION:TS +EC_KEY_get_flags 536 1_1_0 EXIST::FUNCTION:EC +ASN1_TYPE_cmp 537 1_1_0 EXIST::FUNCTION: +i2d_RSAPublicKey 538 1_1_0 EXIST::FUNCTION:RSA +EC_GROUP_get_trinomial_basis 539 1_1_0 EXIST::FUNCTION:EC,EC2M +BIO_ADDRINFO_protocol 540 1_1_0 EXIST::FUNCTION:SOCK +i2d_PBKDF2PARAM 541 1_1_0 EXIST::FUNCTION: +ENGINE_unregister_RAND 542 1_1_0 EXIST::FUNCTION:ENGINE +PEM_write_bio_RSAPrivateKey 543 1_1_0 EXIST::FUNCTION:RSA +CONF_get_number 544 1_1_0 EXIST::FUNCTION: +X509_EXTENSION_get_object 545 1_1_0 EXIST::FUNCTION: +X509_EXTENSIONS_it 546 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +X509_EXTENSIONS_it 546 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +EC_POINT_set_compressed_coordinates_GF2m 547 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_2_0,EC,EC2M +RSA_sign_ASN1_OCTET_STRING 548 1_1_0 EXIST::FUNCTION:RSA +d2i_X509_CRL_fp 549 1_1_0 EXIST::FUNCTION:STDIO +i2d_RSA_PUBKEY 550 1_1_0 EXIST::FUNCTION:RSA +EVP_aes_128_ccm 551 1_1_0 EXIST::FUNCTION: +ECParameters_print 552 1_1_0 EXIST::FUNCTION:EC +OCSP_SINGLERESP_get1_ext_d2i 553 1_1_0 EXIST::FUNCTION:OCSP +RAND_status 554 1_1_0 EXIST::FUNCTION: +EVP_ripemd160 555 1_1_0 EXIST::FUNCTION:RMD160 +EVP_MD_meth_set_final 556 1_1_0 EXIST::FUNCTION: +ENGINE_get_cmd_defns 557 1_1_0 EXIST::FUNCTION:ENGINE +d2i_PKEY_USAGE_PERIOD 558 1_1_0 EXIST::FUNCTION: +RSAPublicKey_dup 559 1_1_0 EXIST::FUNCTION:RSA +RAND_write_file 560 1_1_0 EXIST::FUNCTION: +BN_GF2m_mod 561 1_1_0 EXIST::FUNCTION:EC2M +EC_GROUP_get_pentanomial_basis 562 1_1_0 EXIST::FUNCTION:EC,EC2M +X509_CINF_free 563 1_1_0 EXIST::FUNCTION: +X509_EXTENSION_free 564 1_1_0 EXIST::FUNCTION: +EVP_DigestSignInit 565 1_1_0 EXIST::FUNCTION: +CT_POLICY_EVAL_CTX_get0_issuer 566 1_1_0 EXIST::FUNCTION:CT +TLS_FEATURE_new 567 1_1_0 EXIST::FUNCTION: +RSA_get_default_method 568 1_1_0 EXIST::FUNCTION:RSA +CRYPTO_cts128_encrypt_block 569 1_1_0 EXIST::FUNCTION: +ASN1_digest 570 1_1_0 EXIST::FUNCTION: +ERR_load_X509V3_strings 571 1_1_0 EXIST::FUNCTION: +EVP_PKEY_meth_get_cleanup 572 1_1_0 EXIST::FUNCTION: +d2i_X509 574 1_1_0 EXIST::FUNCTION: +a2i_ASN1_STRING 575 1_1_0 EXIST::FUNCTION: +EC_GROUP_get_mont_data 576 1_1_0 EXIST::FUNCTION:EC +CMAC_CTX_copy 577 1_1_0 EXIST::FUNCTION:CMAC +EVP_camellia_128_cfb128 579 1_1_0 EXIST::FUNCTION:CAMELLIA +DH_compute_key_padded 580 1_1_0 EXIST::FUNCTION:DH +ERR_load_CONF_strings 581 1_1_0 EXIST::FUNCTION: +ESS_ISSUER_SERIAL_dup 582 1_1_0 EXIST::FUNCTION:TS +BN_GF2m_mod_exp_arr 583 1_1_0 EXIST::FUNCTION:EC2M +ASN1_UTF8STRING_free 584 1_1_0 EXIST::FUNCTION: +BN_X931_generate_prime_ex 585 1_1_0 EXIST::FUNCTION: +ENGINE_get_RAND 586 1_1_0 EXIST::FUNCTION:ENGINE +EVP_DecryptInit 587 1_1_0 EXIST::FUNCTION: +BN_bin2bn 588 1_1_0 EXIST::FUNCTION: +X509_subject_name_hash 589 1_1_0 EXIST::FUNCTION: +EVP_CIPHER_meth_set_flags 590 1_1_0 EXIST::FUNCTION: +TS_CONF_set_clock_precision_digits 591 1_1_0 EXIST::FUNCTION:TS +ASN1_TYPE_set 592 1_1_0 EXIST::FUNCTION: +i2d_PKCS8_PRIV_KEY_INFO 593 1_1_0 EXIST::FUNCTION: +i2d_PKCS7_bio 594 1_1_0 EXIST::FUNCTION: +EVP_MD_meth_get_copy 595 1_1_0 EXIST::FUNCTION: +RAND_query_egd_bytes 596 1_1_0 EXIST::FUNCTION:EGD +i2d_ASN1_PRINTABLE 597 1_1_0 EXIST::FUNCTION: +ENGINE_cmd_is_executable 598 1_1_0 EXIST::FUNCTION:ENGINE +BIO_puts 599 1_1_0 EXIST::FUNCTION: +RSAPublicKey_it 601 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:RSA +RSAPublicKey_it 601 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:RSA +ISSUING_DIST_POINT_new 602 1_1_0 EXIST::FUNCTION: +X509_VAL_it 603 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +X509_VAL_it 603 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +EVP_DigestVerifyInit 604 1_1_0 EXIST::FUNCTION: +i2d_IPAddressChoice 605 1_1_0 EXIST::FUNCTION:RFC3779 +EVP_md5 606 1_1_0 EXIST::FUNCTION:MD5 +ASRange_new 607 1_1_0 EXIST::FUNCTION:RFC3779 +BN_GF2m_mod_mul_arr 608 1_1_0 EXIST::FUNCTION:EC2M +d2i_RSA_OAEP_PARAMS 609 1_1_0 EXIST::FUNCTION:RSA +BIO_s_bio 610 1_1_0 EXIST::FUNCTION: +OBJ_NAME_add 611 1_1_0 EXIST::FUNCTION: +BIO_fd_non_fatal_error 612 1_1_0 EXIST::FUNCTION: +EVP_PKEY_set_type 613 1_1_0 EXIST::FUNCTION: +ENGINE_get_next 614 1_1_0 EXIST::FUNCTION:ENGINE +BN_is_negative 615 1_1_0 EXIST::FUNCTION: +EVP_PKEY_get_attr_count 616 1_1_0 EXIST::FUNCTION: +X509_REVOKED_get_ext_by_critical 617 1_1_0 EXIST::FUNCTION: +X509at_get_attr 618 1_1_0 EXIST::FUNCTION: +X509_PUBKEY_it 619 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +X509_PUBKEY_it 619 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +DES_ede3_ofb64_encrypt 620 1_1_0 EXIST::FUNCTION:DES +EC_KEY_METHOD_get_compute_key 621 1_1_0 EXIST::FUNCTION:EC +RC2_cfb64_encrypt 622 1_1_0 EXIST::FUNCTION:RC2 +EVP_EncryptFinal_ex 623 1_1_0 EXIST::FUNCTION: +ERR_load_RSA_strings 624 1_1_0 EXIST::FUNCTION: +CRYPTO_secure_malloc_done 625 1_1_0 EXIST::FUNCTION: +RSA_OAEP_PARAMS_new 626 1_1_0 EXIST::FUNCTION:RSA +X509_NAME_free 627 1_1_0 EXIST::FUNCTION: +PKCS12_set_mac 628 1_1_0 EXIST::FUNCTION: +UI_get0_result_string 629 1_1_0 EXIST::FUNCTION: +TS_RESP_CTX_add_policy 630 1_1_0 EXIST::FUNCTION:TS +X509_REQ_dup 631 1_1_0 EXIST::FUNCTION: +d2i_DSA_PUBKEY_fp 633 1_1_0 EXIST::FUNCTION:DSA,STDIO +OCSP_REQ_CTX_nbio_d2i 634 1_1_0 EXIST::FUNCTION:OCSP +d2i_X509_REQ_fp 635 1_1_0 EXIST::FUNCTION:STDIO +DH_OpenSSL 636 1_1_0 EXIST::FUNCTION:DH +BN_get_rfc3526_prime_8192 637 1_1_0 EXIST::FUNCTION: +X509_REVOKED_it 638 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +X509_REVOKED_it 638 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +CRYPTO_THREAD_write_lock 639 1_1_0 EXIST::FUNCTION: +X509V3_NAME_from_section 640 1_1_0 EXIST::FUNCTION: +EC_POINT_set_compressed_coordinates_GFp 641 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_2_0,EC +OCSP_SINGLERESP_get0_id 642 1_1_0 EXIST::FUNCTION:OCSP +UI_add_info_string 643 1_1_0 EXIST::FUNCTION: +OBJ_NAME_remove 644 1_1_0 EXIST::FUNCTION: +UI_get_method 645 1_1_0 EXIST::FUNCTION: +CONF_modules_unload 646 1_1_0 EXIST::FUNCTION: +CRYPTO_ccm128_encrypt_ccm64 647 1_1_0 EXIST::FUNCTION: +CRYPTO_secure_malloc_init 648 1_1_0 EXIST::FUNCTION: +DSAparams_dup 649 1_1_0 EXIST::FUNCTION:DSA +PKCS8_PRIV_KEY_INFO_new 650 1_1_0 EXIST::FUNCTION: +TS_RESP_verify_token 652 1_1_0 EXIST::FUNCTION:TS +PEM_read_bio_CMS 653 1_1_0 EXIST::FUNCTION:CMS +PEM_get_EVP_CIPHER_INFO 654 1_1_0 EXIST::FUNCTION: +X509V3_EXT_print 655 1_1_0 EXIST::FUNCTION: +i2d_OCSP_SINGLERESP 656 1_1_0 EXIST::FUNCTION:OCSP +ESS_CERT_ID_free 657 1_1_0 EXIST::FUNCTION:TS +PEM_SignInit 658 1_1_0 EXIST::FUNCTION: +EVP_CIPHER_CTX_set_key_length 659 1_1_0 EXIST::FUNCTION: +X509_delete_ext 660 1_1_0 EXIST::FUNCTION: +OCSP_resp_get0_produced_at 661 1_1_0 EXIST::FUNCTION:OCSP +IDEA_encrypt 662 1_1_0 EXIST::FUNCTION:IDEA +CRYPTO_nistcts128_encrypt_block 663 1_1_0 EXIST::FUNCTION: +EVP_MD_do_all 664 1_1_0 EXIST::FUNCTION: +EC_KEY_oct2priv 665 1_1_0 EXIST::FUNCTION:EC +CONF_parse_list 666 1_1_0 EXIST::FUNCTION: +ENGINE_set_table_flags 667 1_1_0 EXIST::FUNCTION:ENGINE +EVP_MD_meth_get_ctrl 668 1_1_0 EXIST::FUNCTION: +ASN1_TYPE_get_int_octetstring 669 1_1_0 EXIST::FUNCTION: +PKCS5_pbe_set0_algor 670 1_1_0 EXIST::FUNCTION: +ENGINE_get_table_flags 671 1_1_0 EXIST::FUNCTION:ENGINE +PKCS12_MAC_DATA_new 672 1_1_0 EXIST::FUNCTION: +X509_chain_up_ref 673 1_1_0 EXIST::FUNCTION: +OCSP_REQINFO_it 674 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:OCSP +OCSP_REQINFO_it 674 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:OCSP +PKCS12_add_localkeyid 675 1_1_0 EXIST::FUNCTION: +PKCS12_SAFEBAG_get0_type 676 1_1_0 EXIST::FUNCTION: +X509_TRUST_set_default 677 1_1_0 EXIST::FUNCTION: +TXT_DB_read 678 1_1_0 EXIST::FUNCTION: +BN_sub 679 1_1_0 EXIST::FUNCTION: +ASRange_free 680 1_1_0 EXIST::FUNCTION:RFC3779 +EVP_aes_192_cfb8 681 1_1_0 EXIST::FUNCTION: +DSO_global_lookup 682 1_1_0 EXIST::FUNCTION: +PKCS7_SIGNER_INFO_it 683 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +PKCS7_SIGNER_INFO_it 683 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +CRYPTO_ocb128_copy_ctx 684 1_1_0 EXIST::FUNCTION:OCB +TS_REQ_get_ext_d2i 685 1_1_0 EXIST::FUNCTION:TS +AES_ige_encrypt 686 1_1_0 EXIST::FUNCTION: +d2i_SXNET 687 1_1_0 EXIST::FUNCTION: +CTLOG_get0_log_id 688 1_1_0 EXIST::FUNCTION:CT +CMS_RecipientInfo_ktri_get0_signer_id 689 1_1_0 EXIST::FUNCTION:CMS +OCSP_REQUEST_add1_ext_i2d 690 1_1_0 EXIST::FUNCTION:OCSP +EVP_PBE_CipherInit 691 1_1_0 EXIST::FUNCTION: +DSA_dup_DH 692 1_1_0 EXIST::FUNCTION:DH,DSA +CONF_imodule_get_value 693 1_1_0 EXIST::FUNCTION: +OCSP_id_issuer_cmp 694 1_1_0 EXIST::FUNCTION:OCSP +ASN1_INTEGER_free 695 1_1_0 EXIST::FUNCTION: +BN_get0_nist_prime_224 696 1_1_0 EXIST::FUNCTION: +OPENSSL_isservice 697 1_1_0 EXIST::FUNCTION: +DH_compute_key 698 1_1_0 EXIST::FUNCTION:DH +TS_RESP_CTX_set_signer_key 699 1_1_0 EXIST::FUNCTION:TS +i2d_DSAPrivateKey_bio 700 1_1_0 EXIST::FUNCTION:DSA +ASN1_item_d2i 702 1_1_0 EXIST::FUNCTION: +BIO_int_ctrl 703 1_1_0 EXIST::FUNCTION: +CMS_ReceiptRequest_it 704 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:CMS +CMS_ReceiptRequest_it 704 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:CMS +X509_ATTRIBUTE_get0_type 705 1_1_0 EXIST::FUNCTION: +EVP_MD_meth_set_copy 706 1_1_0 EXIST::FUNCTION: +d2i_ASN1_ENUMERATED 707 1_1_0 EXIST::FUNCTION: +d2i_ASIdOrRange 708 1_1_0 EXIST::FUNCTION:RFC3779 +i2s_ASN1_OCTET_STRING 709 1_1_0 EXIST::FUNCTION: +X509_add1_reject_object 710 1_1_0 EXIST::FUNCTION: +ERR_set_mark 711 1_1_0 EXIST::FUNCTION: +d2i_ASN1_VISIBLESTRING 712 1_1_0 EXIST::FUNCTION: +X509_NAME_ENTRY_dup 714 1_1_0 EXIST::FUNCTION: +X509_certificate_type 715 1_1_0 EXIST::FUNCTION: +PKCS7_add_signature 716 1_1_0 EXIST::FUNCTION: +OBJ_ln2nid 717 1_1_0 EXIST::FUNCTION: +CRYPTO_128_unwrap 718 1_1_0 EXIST::FUNCTION: +BIO_new_PKCS7 719 1_1_0 EXIST::FUNCTION: +UI_get0_user_data 720 1_1_0 EXIST::FUNCTION: +TS_RESP_get_token 721 1_1_0 EXIST::FUNCTION:TS +OCSP_RESPID_new 722 1_1_0 EXIST::FUNCTION:OCSP +ASN1_SET_ANY_it 723 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ASN1_SET_ANY_it 723 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +d2i_TS_RESP_bio 724 1_1_0 EXIST::FUNCTION:TS +PEM_write_X509_REQ 725 1_1_0 EXIST::FUNCTION:STDIO +BIO_snprintf 726 1_1_0 EXIST::FUNCTION: +EC_POINT_hex2point 727 1_1_0 EXIST::FUNCTION:EC +X509v3_get_ext_by_critical 728 1_1_0 EXIST::FUNCTION: +ENGINE_get_default_RSA 729 1_1_0 EXIST::FUNCTION:ENGINE +DSA_sign_setup 730 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_2_0,DSA +OPENSSL_sk_new_null 731 1_1_0 EXIST::FUNCTION: +PEM_read_PKCS8 732 1_1_0 EXIST::FUNCTION:STDIO +BN_mod_sqr 733 1_1_0 EXIST::FUNCTION: +CAST_ofb64_encrypt 734 1_1_0 EXIST::FUNCTION:CAST +TXT_DB_write 735 1_1_0 EXIST::FUNCTION: +OCSP_REQUEST_get1_ext_d2i 736 1_1_0 EXIST::FUNCTION:OCSP +CMS_unsigned_add1_attr_by_NID 737 1_1_0 EXIST::FUNCTION:CMS +BN_mod_exp_mont 738 1_1_0 EXIST::FUNCTION: +d2i_DHxparams 739 1_1_0 EXIST::FUNCTION:DH +DH_size 740 1_1_0 EXIST::FUNCTION:DH +CONF_imodule_get_name 741 1_1_0 EXIST::FUNCTION: +ENGINE_get_pkey_meth_engine 742 1_1_0 EXIST::FUNCTION:ENGINE +OCSP_BASICRESP_free 743 1_1_0 EXIST::FUNCTION:OCSP +BN_set_params 744 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_0_9_8 +BN_add 745 1_1_0 EXIST::FUNCTION: +OPENSSL_sk_free 746 1_1_0 EXIST::FUNCTION: +TS_TST_INFO_get_ext_d2i 747 1_1_0 EXIST::FUNCTION:TS +RSA_check_key 748 1_1_0 EXIST::FUNCTION:RSA +TS_MSG_IMPRINT_set_algo 749 1_1_0 EXIST::FUNCTION:TS +BN_nist_mod_521 750 1_1_0 EXIST::FUNCTION: +CRYPTO_THREAD_get_local 751 1_1_0 EXIST::FUNCTION: +PKCS7_to_TS_TST_INFO 752 1_1_0 EXIST::FUNCTION:TS +X509_STORE_CTX_new 753 1_1_0 EXIST::FUNCTION: +CTLOG_STORE_new 754 1_1_0 EXIST::FUNCTION:CT +EVP_CIPHER_meth_set_cleanup 755 1_1_0 EXIST::FUNCTION: +d2i_PKCS12_SAFEBAG 756 1_1_0 EXIST::FUNCTION: +EVP_MD_pkey_type 757 1_1_0 EXIST::FUNCTION: +X509_policy_node_get0_qualifiers 758 1_1_0 EXIST::FUNCTION: +OCSP_cert_status_str 759 1_1_0 EXIST::FUNCTION:OCSP +EVP_MD_meth_get_flags 760 1_1_0 EXIST::FUNCTION: +ASN1_ENUMERATED_set 761 1_1_0 EXIST::FUNCTION: +UI_UTIL_read_pw 762 1_1_0 EXIST::FUNCTION: +PKCS7_ENC_CONTENT_free 763 1_1_0 EXIST::FUNCTION: +CMS_RecipientInfo_type 764 1_1_0 EXIST::FUNCTION:CMS +OCSP_BASICRESP_get_ext 765 1_1_0 EXIST::FUNCTION:OCSP +BN_lebin2bn 766 1_1_0 EXIST::FUNCTION: +AES_decrypt 767 1_1_0 EXIST::FUNCTION: +BIO_fd_should_retry 768 1_1_0 EXIST::FUNCTION: +ASN1_STRING_new 769 1_1_0 EXIST::FUNCTION: +ENGINE_init 770 1_1_0 EXIST::FUNCTION:ENGINE +TS_RESP_CTX_add_flags 771 1_1_0 EXIST::FUNCTION:TS +BIO_gethostbyname 772 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0,SOCK +X509V3_EXT_add 773 1_1_0 EXIST::FUNCTION: +UI_add_verify_string 774 1_1_0 EXIST::FUNCTION: +EVP_rc5_32_12_16_cfb64 775 1_1_0 EXIST::FUNCTION:RC5 +PKCS7_dataVerify 776 1_1_0 EXIST::FUNCTION: +PKCS7_SIGNER_INFO_free 777 1_1_0 EXIST::FUNCTION: +PKCS7_add_attrib_smimecap 778 1_1_0 EXIST::FUNCTION: +ERR_peek_last_error_line_data 779 1_1_0 EXIST::FUNCTION: +EVP_PKEY_meth_set_sign 780 1_1_0 EXIST::FUNCTION: +ASN1_i2d_bio 781 1_1_0 EXIST::FUNCTION: +DSA_verify 782 1_1_0 EXIST::FUNCTION:DSA +i2a_ASN1_OBJECT 783 1_1_0 EXIST::FUNCTION: +i2d_PKEY_USAGE_PERIOD 784 1_1_0 EXIST::FUNCTION: +DSA_new 785 1_1_0 EXIST::FUNCTION:DSA +PEM_read_bio_X509_CRL 786 1_1_0 EXIST::FUNCTION: +PKCS7_dataDecode 787 1_1_0 EXIST::FUNCTION: +DSA_up_ref 788 1_1_0 EXIST::FUNCTION:DSA +EVP_DecryptInit_ex 789 1_1_0 EXIST::FUNCTION: +CONF_get1_default_config_file 790 1_1_0 EXIST::FUNCTION: +CRYPTO_ocb128_encrypt 791 1_1_0 EXIST::FUNCTION:OCB +EXTENDED_KEY_USAGE_new 792 1_1_0 EXIST::FUNCTION: +EVP_EncryptFinal 793 1_1_0 EXIST::FUNCTION: +PEM_write_ECPrivateKey 794 1_1_0 EXIST::FUNCTION:EC,STDIO +EVP_CIPHER_meth_set_get_asn1_params 796 1_1_0 EXIST::FUNCTION: +PKCS7_dataInit 797 1_1_0 EXIST::FUNCTION: +EVP_PKEY_CTX_set_app_data 798 1_1_0 EXIST::FUNCTION: +a2i_GENERAL_NAME 799 1_1_0 EXIST::FUNCTION: +SXNETID_new 800 1_1_0 EXIST::FUNCTION: +RC4_options 801 1_1_0 EXIST::FUNCTION:RC4 +BIO_f_null 802 1_1_0 EXIST::FUNCTION: +EC_GROUP_set_curve_name 803 1_1_0 EXIST::FUNCTION:EC +d2i_PBE2PARAM 804 1_1_0 EXIST::FUNCTION: +EVP_PKEY_security_bits 805 1_1_0 EXIST::FUNCTION: +PKCS12_unpack_p7encdata 806 1_1_0 EXIST::FUNCTION: +X509V3_EXT_i2d 807 1_1_0 EXIST::FUNCTION: +X509V3_get_value_bool 808 1_1_0 EXIST::FUNCTION: +X509_verify_cert_error_string 809 1_1_0 EXIST::FUNCTION: +d2i_X509_PUBKEY 810 1_1_0 EXIST::FUNCTION: +i2a_ASN1_ENUMERATED 811 1_1_0 EXIST::FUNCTION: +PKCS7_ISSUER_AND_SERIAL_new 812 1_1_0 EXIST::FUNCTION: +d2i_USERNOTICE 813 1_1_0 EXIST::FUNCTION: +X509_cmp 814 1_1_0 EXIST::FUNCTION: +EVP_PKEY_set1_EC_KEY 815 1_1_0 EXIST::FUNCTION:EC +ECPKParameters_print_fp 816 1_1_0 EXIST::FUNCTION:EC,STDIO +GENERAL_SUBTREE_free 817 1_1_0 EXIST::FUNCTION: +RSA_blinding_off 818 1_1_0 EXIST::FUNCTION:RSA +i2d_OCSP_REVOKEDINFO 819 1_1_0 EXIST::FUNCTION:OCSP +X509V3_add_standard_extensions 820 1_1_0 EXIST::FUNCTION: +PEM_write_bio_RSA_PUBKEY 821 1_1_0 EXIST::FUNCTION:RSA +i2d_ASN1_UTF8STRING 822 1_1_0 EXIST::FUNCTION: +TS_REQ_delete_ext 823 1_1_0 EXIST::FUNCTION:TS +PKCS7_DIGEST_free 824 1_1_0 EXIST::FUNCTION: +OBJ_nid2ln 825 1_1_0 EXIST::FUNCTION: +COMP_CTX_new 826 1_1_0 EXIST::FUNCTION:COMP +BIO_ADDR_family 827 1_1_0 EXIST::FUNCTION:SOCK +OCSP_RESPONSE_it 828 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:OCSP +OCSP_RESPONSE_it 828 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:OCSP +BIO_ADDRINFO_socktype 829 1_1_0 EXIST::FUNCTION:SOCK +d2i_X509_REQ_bio 830 1_1_0 EXIST::FUNCTION: +EVP_PBE_cleanup 831 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_get0_current_crl 832 1_1_0 EXIST::FUNCTION: +CMS_get0_SignerInfos 833 1_1_0 EXIST::FUNCTION:CMS +EVP_PKEY_paramgen 834 1_1_0 EXIST::FUNCTION: +PEM_write_PKCS8PrivateKey_nid 835 1_1_0 EXIST::FUNCTION:STDIO +PKCS7_ATTR_VERIFY_it 836 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +PKCS7_ATTR_VERIFY_it 836 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +OCSP_response_status_str 837 1_1_0 EXIST::FUNCTION:OCSP +CRYPTO_gcm128_new 838 1_1_0 EXIST::FUNCTION: +SMIME_read_PKCS7 839 1_1_0 EXIST::FUNCTION: +EC_GROUP_copy 840 1_1_0 EXIST::FUNCTION:EC +ENGINE_set_ciphers 841 1_1_0 EXIST::FUNCTION:ENGINE +OPENSSL_LH_doall_arg 842 1_1_0 EXIST::FUNCTION: +OCSP_REQUEST_get_ext_by_NID 843 1_1_0 EXIST::FUNCTION:OCSP +X509_REQ_get_attr_by_NID 844 1_1_0 EXIST::FUNCTION: +PBE2PARAM_new 845 1_1_0 EXIST::FUNCTION: +DES_ecb_encrypt 846 1_1_0 EXIST::FUNCTION:DES +EVP_camellia_256_ecb 847 1_1_0 EXIST::FUNCTION:CAMELLIA +PEM_read_RSA_PUBKEY 848 1_1_0 EXIST::FUNCTION:RSA,STDIO +d2i_NETSCAPE_SPKAC 849 1_1_0 EXIST::FUNCTION: +ASN1_TIME_check 851 1_1_0 EXIST::FUNCTION: +PKCS7_DIGEST_new 852 1_1_0 EXIST::FUNCTION: +i2d_TS_TST_INFO_fp 853 1_1_0 EXIST::FUNCTION:STDIO,TS +d2i_PKCS8_fp 854 1_1_0 EXIST::FUNCTION:STDIO +EVP_PKEY_keygen 855 1_1_0 EXIST::FUNCTION: +X509_CRL_dup 856 1_1_0 EXIST::FUNCTION: +EVP_PKEY_CTX_get_cb 857 1_1_0 EXIST::FUNCTION: +X509_STORE_free 858 1_1_0 EXIST::FUNCTION: +ECDSA_sign_ex 859 1_1_0 EXIST::FUNCTION:EC +TXT_DB_insert 860 1_1_0 EXIST::FUNCTION: +EC_POINTs_make_affine 861 1_1_0 EXIST::FUNCTION:EC +RSA_padding_add_PKCS1_PSS 862 1_1_0 EXIST::FUNCTION:RSA +BF_options 863 1_1_0 EXIST::FUNCTION:BF +OCSP_BASICRESP_it 864 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:OCSP +OCSP_BASICRESP_it 864 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:OCSP +X509_VERIFY_PARAM_get0_name 865 1_1_0 EXIST::FUNCTION: +TS_RESP_CTX_set_signer_digest 866 1_1_0 EXIST::FUNCTION:TS +X509_VERIFY_PARAM_set1_email 867 1_1_0 EXIST::FUNCTION: +BIO_sock_error 868 1_1_0 EXIST::FUNCTION:SOCK +RSA_set_default_method 869 1_1_0 EXIST::FUNCTION:RSA +BN_GF2m_mod_sqrt_arr 870 1_1_0 EXIST::FUNCTION:EC2M +X509_get0_extensions 871 1_1_0 EXIST::FUNCTION: +TS_STATUS_INFO_set_status 872 1_1_0 EXIST::FUNCTION:TS +RSA_verify 873 1_1_0 EXIST::FUNCTION:RSA +ASN1_FBOOLEAN_it 874 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ASN1_FBOOLEAN_it 874 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +d2i_ASN1_TIME 875 1_1_0 EXIST::FUNCTION: +EVP_PKEY_meth_get_signctx 876 1_1_0 EXIST::FUNCTION: +EC_KEY_METHOD_set_compute_key 877 1_1_0 EXIST::FUNCTION:EC +X509_REQ_INFO_free 878 1_1_0 EXIST::FUNCTION: +CMS_ReceiptRequest_create0 879 1_1_0 EXIST::FUNCTION:CMS +EVP_MD_meth_set_cleanup 880 1_1_0 EXIST::FUNCTION: +EVP_aes_128_xts 881 1_1_0 EXIST::FUNCTION: +TS_RESP_verify_signature 883 1_1_0 EXIST::FUNCTION:TS +ENGINE_set_pkey_meths 884 1_1_0 EXIST::FUNCTION:ENGINE +CMS_EncryptedData_decrypt 885 1_1_0 EXIST::FUNCTION:CMS +CONF_module_add 886 1_1_0 EXIST::FUNCTION: +ASN1_UTCTIME_print 887 1_1_0 EXIST::FUNCTION: +X509_REQ_verify 888 1_1_0 EXIST::FUNCTION: +X509_VERIFY_PARAM_set_purpose 889 1_1_0 EXIST::FUNCTION: +i2d_TS_MSG_IMPRINT_bio 890 1_1_0 EXIST::FUNCTION:TS +X509_EXTENSION_set_object 891 1_1_0 EXIST::FUNCTION: +EVP_CIPHER_CTX_get_app_data 892 1_1_0 EXIST::FUNCTION: +CRL_DIST_POINTS_it 893 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +CRL_DIST_POINTS_it 893 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +DIRECTORYSTRING_new 894 1_1_0 EXIST::FUNCTION: +ERR_load_ASYNC_strings 895 1_1_0 EXIST::FUNCTION: +EVP_bf_cfb64 896 1_1_0 EXIST::FUNCTION:BF +PKCS7_sign_add_signer 897 1_1_0 EXIST::FUNCTION: +X509_print_ex 898 1_1_0 EXIST::FUNCTION: +PKCS7_add_recipient 899 1_1_0 EXIST::FUNCTION: +OCSP_SINGLERESP_add_ext 900 1_1_0 EXIST::FUNCTION:OCSP +d2i_X509_SIG 901 1_1_0 EXIST::FUNCTION: +X509_NAME_set 902 1_1_0 EXIST::FUNCTION: +OPENSSL_sk_pop 903 1_1_0 EXIST::FUNCTION: +ENGINE_register_ciphers 904 1_1_0 EXIST::FUNCTION:ENGINE +PKCS5_pbe2_set_iv 905 1_1_0 EXIST::FUNCTION: +ASN1_add_stable_module 906 1_1_0 EXIST::FUNCTION: +EVP_camellia_128_cbc 907 1_1_0 EXIST::FUNCTION:CAMELLIA +COMP_zlib 908 1_1_0 EXIST::FUNCTION:COMP +EVP_read_pw_string 909 1_1_0 EXIST::FUNCTION: +i2d_ASN1_NULL 910 1_1_0 EXIST::FUNCTION: +DES_encrypt1 911 1_1_0 EXIST::FUNCTION:DES +BN_mod_lshift1_quick 912 1_1_0 EXIST::FUNCTION: +BN_get_rfc3526_prime_6144 913 1_1_0 EXIST::FUNCTION: +OBJ_obj2txt 914 1_1_0 EXIST::FUNCTION: +UI_set_result 915 1_1_0 EXIST::FUNCTION: +EVP_EncodeUpdate 916 1_1_0 EXIST::FUNCTION: +PEM_write_bio_X509_CRL 917 1_1_0 EXIST::FUNCTION: +BN_cmp 918 1_1_0 EXIST::FUNCTION: +CT_POLICY_EVAL_CTX_get0_log_store 919 1_1_0 EXIST::FUNCTION:CT +CONF_set_default_method 920 1_1_0 EXIST::FUNCTION: +ASN1_PCTX_get_nm_flags 921 1_1_0 EXIST::FUNCTION: +X509_add1_ext_i2d 922 1_1_0 EXIST::FUNCTION: +i2d_PKCS7_RECIP_INFO 924 1_1_0 EXIST::FUNCTION: +PKCS1_MGF1 925 1_1_0 EXIST::FUNCTION:RSA +BIO_vsnprintf 926 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_get0_current_issuer 927 1_1_0 EXIST::FUNCTION: +CRYPTO_secure_malloc_initialized 928 1_1_0 EXIST::FUNCTION: +o2i_SCT_LIST 929 1_1_0 EXIST::FUNCTION:CT +ASN1_PCTX_get_cert_flags 930 1_1_0 EXIST::FUNCTION: +X509at_add1_attr_by_NID 931 1_1_0 EXIST::FUNCTION: +DHparams_dup 932 1_1_0 EXIST::FUNCTION:DH +X509_get_ext 933 1_1_0 EXIST::FUNCTION: +X509_issuer_and_serial_hash 934 1_1_0 EXIST::FUNCTION: +ASN1_BMPSTRING_it 935 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ASN1_BMPSTRING_it 935 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +PEM_read_EC_PUBKEY 936 1_1_0 EXIST::FUNCTION:EC,STDIO +d2i_ASN1_IA5STRING 937 1_1_0 EXIST::FUNCTION: +TS_TST_INFO_ext_free 938 1_1_0 EXIST::FUNCTION:TS +i2d_X509_CRL_fp 939 1_1_0 EXIST::FUNCTION:STDIO +PKCS7_get0_signers 940 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_set_ex_data 941 1_1_0 EXIST::FUNCTION: +TS_VERIFY_CTS_set_certs 942 1_1_0 EXIST::FUNCTION:TS +BN_MONT_CTX_copy 943 1_1_0 EXIST::FUNCTION: +OPENSSL_INIT_new 945 1_1_0 EXIST::FUNCTION: +TS_ACCURACY_dup 946 1_1_0 EXIST::FUNCTION:TS +i2d_ECPrivateKey 947 1_1_0 EXIST::FUNCTION:EC +X509_NAME_ENTRY_create_by_OBJ 948 1_1_0 EXIST::FUNCTION: +TS_VERIFY_CTX_cleanup 949 1_1_0 EXIST::FUNCTION:TS +ASN1_INTEGER_get 950 1_1_0 EXIST::FUNCTION: +ASN1_PRINTABLE_it 951 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ASN1_PRINTABLE_it 951 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +EVP_VerifyFinal 952 1_1_0 EXIST::FUNCTION: +TS_ASN1_INTEGER_print_bio 953 1_1_0 EXIST::FUNCTION:TS +X509_NAME_ENTRY_set_object 954 1_1_0 EXIST::FUNCTION: +BIO_s_socket 955 1_1_0 EXIST::FUNCTION:SOCK +EVP_rc5_32_12_16_ecb 956 1_1_0 EXIST::FUNCTION:RC5 +i2d_PKCS8_bio 957 1_1_0 EXIST::FUNCTION: +v2i_ASN1_BIT_STRING 958 1_1_0 EXIST::FUNCTION: +PKEY_USAGE_PERIOD_new 959 1_1_0 EXIST::FUNCTION: +OBJ_NAME_init 960 1_1_0 EXIST::FUNCTION: +EVP_PKEY_meth_set_keygen 961 1_1_0 EXIST::FUNCTION: +RSA_PSS_PARAMS_new 962 1_1_0 EXIST::FUNCTION:RSA +RSA_sign 963 1_1_0 EXIST::FUNCTION:RSA +EVP_DigestVerifyFinal 964 1_1_0 EXIST::FUNCTION: +d2i_RSA_PUBKEY_bio 965 1_1_0 EXIST::FUNCTION:RSA +TS_RESP_dup 966 1_1_0 EXIST::FUNCTION:TS +ERR_set_error_data 967 1_1_0 EXIST::FUNCTION: +BN_RECP_CTX_new 968 1_1_0 EXIST::FUNCTION: +DES_options 969 1_1_0 EXIST::FUNCTION:DES +IPAddressChoice_it 970 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:RFC3779 +IPAddressChoice_it 970 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:RFC3779 +ASN1_UNIVERSALSTRING_it 971 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ASN1_UNIVERSALSTRING_it 971 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +d2i_DSAPublicKey 972 1_1_0 EXIST::FUNCTION:DSA +ENGINE_get_name 973 1_1_0 EXIST::FUNCTION:ENGINE +CRYPTO_THREAD_read_lock 974 1_1_0 EXIST::FUNCTION: +ASIdentifierChoice_free 975 1_1_0 EXIST::FUNCTION:RFC3779 +BIO_dgram_sctp_msg_waiting 976 1_1_0 EXIST::FUNCTION:DGRAM,SCTP +BN_is_bit_set 978 1_1_0 EXIST::FUNCTION: +AES_ofb128_encrypt 979 1_1_0 EXIST::FUNCTION: +X509_STORE_add_lookup 980 1_1_0 EXIST::FUNCTION: +ASN1_GENERALSTRING_new 981 1_1_0 EXIST::FUNCTION: +IDEA_options 982 1_1_0 EXIST::FUNCTION:IDEA +d2i_X509_REQ 983 1_1_0 EXIST::FUNCTION: +i2d_TS_STATUS_INFO 984 1_1_0 EXIST::FUNCTION:TS +X509_PURPOSE_get_by_id 985 1_1_0 EXIST::FUNCTION: +X509_get1_ocsp 986 1_1_0 EXIST::FUNCTION: +ISSUING_DIST_POINT_free 987 1_1_0 EXIST::FUNCTION: +ASN1_UTCTIME_free 988 1_1_0 EXIST::FUNCTION: +ERR_load_TS_strings 989 1_1_0 EXIST::FUNCTION:TS +BN_nist_mod_func 990 1_1_0 EXIST::FUNCTION: +OCSP_ONEREQ_new 991 1_1_0 EXIST::FUNCTION:OCSP +DSA_SIG_new 992 1_1_0 EXIST::FUNCTION:DSA +DH_get_default_method 993 1_1_0 EXIST::FUNCTION:DH +PEM_proc_type 994 1_1_0 EXIST::FUNCTION: +BIO_printf 995 1_1_0 EXIST::FUNCTION: +a2i_IPADDRESS 996 1_1_0 EXIST::FUNCTION: +ERR_peek_error_line_data 997 1_1_0 EXIST::FUNCTION: +ERR_unload_strings 998 1_1_0 EXIST::FUNCTION: +SEED_cfb128_encrypt 999 1_1_0 EXIST::FUNCTION:SEED +ASN1_BIT_STRING_it 1000 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ASN1_BIT_STRING_it 1000 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +PKCS12_decrypt_skey 1001 1_1_0 EXIST::FUNCTION: +ENGINE_register_EC 1002 1_1_0 EXIST::FUNCTION:ENGINE +OCSP_RESPONSE_new 1003 1_1_0 EXIST::FUNCTION:OCSP +CRYPTO_cbc128_encrypt 1004 1_1_0 EXIST::FUNCTION: +i2d_RSAPublicKey_bio 1005 1_1_0 EXIST::FUNCTION:RSA +X509_chain_check_suiteb 1006 1_1_0 EXIST::FUNCTION: +i2d_OCSP_REQUEST 1007 1_1_0 EXIST::FUNCTION:OCSP +BN_X931_generate_Xpq 1008 1_1_0 EXIST::FUNCTION: +ASN1_item_digest 1009 1_1_0 EXIST::FUNCTION: +X509_VERIFY_PARAM_set_trust 1010 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_get_error 1011 1_1_0 EXIST::FUNCTION: +EVP_PKEY_meth_set_encrypt 1012 1_1_0 EXIST::FUNCTION: +ASN1_UTCTIME_it 1013 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ASN1_UTCTIME_it 1013 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +i2d_DSA_PUBKEY_fp 1014 1_1_0 EXIST::FUNCTION:DSA,STDIO +X509at_get_attr_by_OBJ 1015 1_1_0 EXIST::FUNCTION: +EVP_MD_CTX_copy_ex 1016 1_1_0 EXIST::FUNCTION: +UI_dup_error_string 1017 1_1_0 EXIST::FUNCTION: +OPENSSL_LH_num_items 1018 1_1_0 EXIST::FUNCTION: +ASN1_INTEGER_cmp 1020 1_1_0 EXIST::FUNCTION: +X509_NAME_entry_count 1021 1_1_0 EXIST::FUNCTION: +UI_method_set_closer 1022 1_1_0 EXIST::FUNCTION: +OPENSSL_LH_get_down_load 1023 1_1_0 EXIST::FUNCTION: +EVP_md4 1024 1_1_0 EXIST::FUNCTION:MD4 +X509_set_subject_name 1025 1_1_0 EXIST::FUNCTION: +i2d_PKCS8PrivateKey_nid_bio 1026 1_1_0 EXIST::FUNCTION: +ERR_put_error 1027 1_1_0 EXIST::FUNCTION: +ERR_add_error_data 1028 1_1_0 EXIST::FUNCTION: +X509_ALGORS_it 1029 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +X509_ALGORS_it 1029 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +MD5_Update 1030 1_1_0 EXIST::FUNCTION:MD5 +X509_policy_check 1031 1_1_0 EXIST::FUNCTION: +X509_CRL_METHOD_new 1032 1_1_0 EXIST::FUNCTION: +ASN1_ANY_it 1033 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ASN1_ANY_it 1033 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +d2i_DSA_SIG 1034 1_1_0 EXIST::FUNCTION:DSA +DH_free 1035 1_1_0 EXIST::FUNCTION:DH +ENGINE_register_all_DSA 1036 1_1_0 EXIST::FUNCTION:ENGINE +TS_REQ_set_msg_imprint 1037 1_1_0 EXIST::FUNCTION:TS +BN_mod_sub_quick 1038 1_1_0 EXIST::FUNCTION: +SMIME_write_CMS 1039 1_1_0 EXIST::FUNCTION:CMS +i2d_DSAPublicKey 1040 1_1_0 EXIST::FUNCTION:DSA +SMIME_text 1042 1_1_0 EXIST::FUNCTION: +PKCS7_add_recipient_info 1043 1_1_0 EXIST::FUNCTION: +BN_get_word 1044 1_1_0 EXIST::FUNCTION: +EVP_CipherFinal 1045 1_1_0 EXIST::FUNCTION: +i2d_X509_bio 1046 1_1_0 EXIST::FUNCTION: +X509_EXTENSION_new 1047 1_1_0 EXIST::FUNCTION: +X509_getm_notAfter 1048 1_1_0 EXIST::FUNCTION: +X509_ALGOR_dup 1049 1_1_0 EXIST::FUNCTION: +d2i_X509_REQ_INFO 1050 1_1_0 EXIST::FUNCTION: +d2i_EC_PUBKEY_bio 1051 1_1_0 EXIST::FUNCTION:EC +X509_STORE_CTX_set_error 1052 1_1_0 EXIST::FUNCTION: +EC_KEY_METHOD_set_keygen 1053 1_1_0 EXIST::FUNCTION:EC +CRYPTO_free 1054 1_1_0 EXIST::FUNCTION: +BN_GF2m_mod_exp 1055 1_1_0 EXIST::FUNCTION:EC2M +OPENSSL_buf2hexstr 1056 1_1_0 EXIST::FUNCTION: +DES_encrypt2 1057 1_1_0 EXIST::FUNCTION:DES +DH_up_ref 1058 1_1_0 EXIST::FUNCTION:DH +RC2_ofb64_encrypt 1059 1_1_0 EXIST::FUNCTION:RC2 +PKCS12_pbe_crypt 1060 1_1_0 EXIST::FUNCTION: +ASIdentifiers_free 1061 1_1_0 EXIST::FUNCTION:RFC3779 +X509_VERIFY_PARAM_get0 1062 1_1_0 EXIST::FUNCTION: +EVP_MD_meth_get_input_blocksize 1063 1_1_0 EXIST::FUNCTION: +TS_ACCURACY_get_micros 1064 1_1_0 EXIST::FUNCTION:TS +PKCS12_SAFEBAG_create_cert 1065 1_1_0 EXIST::FUNCTION: +CRYPTO_mem_debug_malloc 1066 1_1_0 EXIST::FUNCTION:CRYPTO_MDEBUG +RAND_seed 1067 1_1_0 EXIST::FUNCTION: +NETSCAPE_SPKAC_free 1068 1_1_0 EXIST::FUNCTION: +X509_CRL_diff 1069 1_1_0 EXIST::FUNCTION: +X509_VERIFY_PARAM_set_flags 1070 1_1_0 EXIST::FUNCTION: +X509_EXTENSION_set_data 1071 1_1_0 EXIST::FUNCTION: +ENGINE_get_EC 1072 1_1_0 EXIST::FUNCTION:ENGINE +ASN1_STRING_copy 1073 1_1_0 EXIST::FUNCTION: +EVP_PKEY_encrypt_old 1074 1_1_0 EXIST::FUNCTION: +OPENSSL_LH_free 1075 1_1_0 EXIST::FUNCTION: +DES_is_weak_key 1076 1_1_0 EXIST::FUNCTION:DES +EVP_PKEY_verify 1077 1_1_0 EXIST::FUNCTION: +ERR_load_BIO_strings 1078 1_1_0 EXIST::FUNCTION: +BIO_nread 1079 1_1_0 EXIST::FUNCTION: +PEM_read_bio_RSAPrivateKey 1080 1_1_0 EXIST::FUNCTION:RSA +OBJ_nid2obj 1081 1_1_0 EXIST::FUNCTION: +CRYPTO_ofb128_encrypt 1082 1_1_0 EXIST::FUNCTION: +ENGINE_set_init_function 1083 1_1_0 EXIST::FUNCTION:ENGINE +NCONF_default 1084 1_1_0 EXIST::FUNCTION: +ENGINE_remove 1085 1_1_0 EXIST::FUNCTION:ENGINE +ASYNC_get_current_job 1086 1_1_0 EXIST::FUNCTION: +OBJ_nid2sn 1087 1_1_0 EXIST::FUNCTION: +X509_gmtime_adj 1088 1_1_0 EXIST::FUNCTION: +X509_add_ext 1089 1_1_0 EXIST::FUNCTION: +ENGINE_set_DSA 1090 1_1_0 EXIST::FUNCTION:ENGINE +EC_KEY_METHOD_set_sign 1091 1_1_0 EXIST::FUNCTION:EC +d2i_TS_MSG_IMPRINT 1092 1_1_0 EXIST::FUNCTION:TS +X509_print_ex_fp 1093 1_1_0 EXIST::FUNCTION:STDIO +ERR_load_PEM_strings 1094 1_1_0 EXIST::FUNCTION: +ENGINE_unregister_pkey_asn1_meths 1095 1_1_0 EXIST::FUNCTION:ENGINE +IPAddressFamily_free 1096 1_1_0 EXIST::FUNCTION:RFC3779 +UI_method_get_prompt_constructor 1097 1_1_0 EXIST::FUNCTION: +ASN1_NULL_it 1098 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ASN1_NULL_it 1098 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +X509_REQ_get_pubkey 1099 1_1_0 EXIST::FUNCTION: +X509_CRL_set1_nextUpdate 1100 1_1_0 EXIST::FUNCTION: +EVP_des_ede3_cfb64 1101 1_1_0 EXIST::FUNCTION:DES +BN_to_ASN1_INTEGER 1102 1_1_0 EXIST::FUNCTION: +EXTENDED_KEY_USAGE_free 1103 1_1_0 EXIST::FUNCTION: +PEM_read_bio_EC_PUBKEY 1104 1_1_0 EXIST::FUNCTION:EC +BN_MONT_CTX_set 1105 1_1_0 EXIST::FUNCTION: +TS_CONF_set_serial 1106 1_1_0 EXIST::FUNCTION:TS +X509_NAME_ENTRY_new 1107 1_1_0 EXIST::FUNCTION: +RSA_security_bits 1108 1_1_0 EXIST::FUNCTION:RSA +X509v3_addr_add_prefix 1109 1_1_0 EXIST::FUNCTION:RFC3779 +X509_REQ_print_fp 1110 1_1_0 EXIST::FUNCTION:STDIO +ASN1_item_ex_new 1111 1_1_0 EXIST::FUNCTION: +BIO_s_datagram 1112 1_1_0 EXIST::FUNCTION:DGRAM +PEM_write_bio_PKCS8 1113 1_1_0 EXIST::FUNCTION: +ASN1_str2mask 1114 1_1_0 EXIST::FUNCTION: +ASN1_TYPE_get 1115 1_1_0 EXIST::FUNCTION: +i2d_X509_EXTENSIONS 1116 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_get0_store 1117 1_1_0 EXIST::FUNCTION: +PKCS12_pack_p7data 1118 1_1_0 EXIST::FUNCTION: +RSA_print_fp 1119 1_1_0 EXIST::FUNCTION:RSA,STDIO +OPENSSL_INIT_set_config_appname 1120 1_1_0 EXIST::FUNCTION:STDIO +EC_KEY_print_fp 1121 1_1_0 EXIST::FUNCTION:EC,STDIO +BIO_dup_chain 1122 1_1_0 EXIST::FUNCTION: +PKCS8_PRIV_KEY_INFO_it 1123 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +PKCS8_PRIV_KEY_INFO_it 1123 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +RSA_OAEP_PARAMS_free 1124 1_1_0 EXIST::FUNCTION:RSA +ASN1_item_new 1125 1_1_0 EXIST::FUNCTION: +CRYPTO_cts128_encrypt 1126 1_1_0 EXIST::FUNCTION: +RC2_encrypt 1127 1_1_0 EXIST::FUNCTION:RC2 +PEM_write 1128 1_1_0 EXIST::FUNCTION:STDIO +EVP_CIPHER_meth_get_get_asn1_params 1129 1_1_0 EXIST::FUNCTION: +i2d_OCSP_RESPBYTES 1130 1_1_0 EXIST::FUNCTION:OCSP +d2i_ASN1_UTF8STRING 1131 1_1_0 EXIST::FUNCTION: +EXTENDED_KEY_USAGE_it 1132 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +EXTENDED_KEY_USAGE_it 1132 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +EVP_CipherInit 1133 1_1_0 EXIST::FUNCTION: +PKCS12_add_safe 1134 1_1_0 EXIST::FUNCTION: +ENGINE_get_digest 1135 1_1_0 EXIST::FUNCTION:ENGINE +EC_GROUP_have_precompute_mult 1136 1_1_0 EXIST::FUNCTION:EC +OPENSSL_gmtime 1137 1_1_0 EXIST::FUNCTION: +X509_set_issuer_name 1138 1_1_0 EXIST::FUNCTION: +RSA_new 1139 1_1_0 EXIST::FUNCTION:RSA +ASN1_STRING_set_by_NID 1140 1_1_0 EXIST::FUNCTION: +PEM_write_bio_PKCS7 1141 1_1_0 EXIST::FUNCTION: +MDC2_Final 1142 1_1_0 EXIST::FUNCTION:MDC2 +SMIME_crlf_copy 1143 1_1_0 EXIST::FUNCTION: +OCSP_REQUEST_get_ext_count 1144 1_1_0 EXIST::FUNCTION:OCSP +OCSP_REQ_CTX_new 1145 1_1_0 EXIST::FUNCTION:OCSP +X509_load_cert_crl_file 1146 1_1_0 EXIST::FUNCTION: +EVP_PKEY_new_mac_key 1147 1_1_0 EXIST::FUNCTION: +DIST_POINT_new 1148 1_1_0 EXIST::FUNCTION: +BN_is_prime_fasttest 1149 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_0_9_8 +EC_POINT_dup 1150 1_1_0 EXIST::FUNCTION:EC +PKCS5_v2_scrypt_keyivgen 1151 1_1_0 EXIST::FUNCTION:SCRYPT +X509_STORE_CTX_set0_param 1152 1_1_0 EXIST::FUNCTION: +DES_check_key_parity 1153 1_1_0 EXIST::FUNCTION:DES +EVP_aes_256_ocb 1154 1_1_0 EXIST::FUNCTION:OCB +X509_VAL_free 1155 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_get1_certs 1156 1_1_0 EXIST::FUNCTION: +PEM_write_RSA_PUBKEY 1157 1_1_0 EXIST::FUNCTION:RSA,STDIO +PKCS12_SAFEBAG_get0_p8inf 1158 1_1_0 EXIST::FUNCTION: +X509_CRL_set_issuer_name 1159 1_1_0 EXIST::FUNCTION: +CMS_EncryptedData_encrypt 1160 1_1_0 EXIST::FUNCTION:CMS +ASN1_tag2str 1161 1_1_0 EXIST::FUNCTION: +BN_zero_ex 1162 1_1_0 EXIST::FUNCTION: +X509_NAME_dup 1163 1_1_0 EXIST::FUNCTION: +SCT_LIST_print 1164 1_1_0 EXIST::FUNCTION:CT +NOTICEREF_it 1165 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +NOTICEREF_it 1165 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +CMS_add0_crl 1166 1_1_0 EXIST::FUNCTION:CMS +d2i_DSAparams 1167 1_1_0 EXIST::FUNCTION:DSA +EVP_CIPHER_CTX_set_app_data 1168 1_1_0 EXIST::FUNCTION: +EVP_CIPHER_param_to_asn1 1169 1_1_0 EXIST::FUNCTION: +TS_CONF_set_certs 1170 1_1_0 EXIST::FUNCTION:TS +BN_security_bits 1171 1_1_0 EXIST::FUNCTION: +X509_PURPOSE_get0_name 1172 1_1_0 EXIST::FUNCTION: +TS_TST_INFO_get_serial 1173 1_1_0 EXIST::FUNCTION:TS +ASN1_PCTX_get_str_flags 1174 1_1_0 EXIST::FUNCTION: +SHA256 1175 1_1_0 EXIST::FUNCTION: +X509_LOOKUP_hash_dir 1176 1_1_0 EXIST::FUNCTION: +ASN1_BIT_STRING_check 1177 1_1_0 EXIST::FUNCTION: +ENGINE_set_default_RAND 1178 1_1_0 EXIST::FUNCTION:ENGINE +BIO_connect 1179 1_1_0 EXIST::FUNCTION:SOCK +TS_TST_INFO_add_ext 1180 1_1_0 EXIST::FUNCTION:TS +EVP_aes_192_ccm 1181 1_1_0 EXIST::FUNCTION: +X509V3_add_value 1182 1_1_0 EXIST::FUNCTION: +EVP_PKEY_CTX_set0_keygen_info 1183 1_1_0 EXIST::FUNCTION: +ENGINE_unregister_digests 1184 1_1_0 EXIST::FUNCTION:ENGINE +IPAddressOrRange_new 1185 1_1_0 EXIST::FUNCTION:RFC3779 +EVP_aes_256_ofb 1186 1_1_0 EXIST::FUNCTION: +CRYPTO_mem_debug_push 1187 1_1_0 EXIST::FUNCTION:CRYPTO_MDEBUG +X509_PKEY_new 1188 1_1_0 EXIST::FUNCTION: +X509_get_key_usage 1189 1_1_0 EXIST::FUNCTION: +X509_ATTRIBUTE_create_by_txt 1190 1_1_0 EXIST::FUNCTION: +PEM_SignFinal 1191 1_1_0 EXIST::FUNCTION: +PEM_bytes_read_bio 1192 1_1_0 EXIST::FUNCTION: +X509_signature_dump 1193 1_1_0 EXIST::FUNCTION: +TS_RESP_CTX_set_def_policy 1194 1_1_0 EXIST::FUNCTION:TS +RAND_pseudo_bytes 1195 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0 +DES_ofb_encrypt 1196 1_1_0 EXIST::FUNCTION:DES +EVP_add_digest 1197 1_1_0 EXIST::FUNCTION: +ASN1_item_sign_ctx 1198 1_1_0 EXIST::FUNCTION: +BIO_dump_indent_cb 1199 1_1_0 EXIST::FUNCTION: +X509_VERIFY_PARAM_set_depth 1200 1_1_0 EXIST::FUNCTION: +DES_ecb3_encrypt 1201 1_1_0 EXIST::FUNCTION:DES +OBJ_obj2nid 1202 1_1_0 EXIST::FUNCTION: +PKCS12_SAFEBAG_free 1203 1_1_0 EXIST::FUNCTION: +EVP_cast5_cfb64 1204 1_1_0 EXIST::FUNCTION:CAST +OPENSSL_uni2asc 1205 1_1_0 EXIST::FUNCTION: +SCT_validation_status_string 1206 1_1_0 EXIST::FUNCTION:CT +PKCS7_add_attribute 1207 1_1_0 EXIST::FUNCTION: +ENGINE_register_DSA 1208 1_1_0 EXIST::FUNCTION:ENGINE +OPENSSL_LH_node_stats 1209 1_1_0 EXIST::FUNCTION:STDIO +X509_policy_tree_free 1210 1_1_0 EXIST::FUNCTION: +EC_GFp_simple_method 1211 1_1_0 EXIST::FUNCTION:EC +X509_it 1212 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +X509_it 1212 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +d2i_PROXY_POLICY 1213 1_1_0 EXIST::FUNCTION: +MDC2_Update 1214 1_1_0 EXIST::FUNCTION:MDC2 +EC_KEY_new_by_curve_name 1215 1_1_0 EXIST::FUNCTION:EC +X509_CRL_free 1216 1_1_0 EXIST::FUNCTION: +i2d_PKCS7_SIGN_ENVELOPE 1217 1_1_0 EXIST::FUNCTION: +OCSP_CERTSTATUS_it 1218 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:OCSP +OCSP_CERTSTATUS_it 1218 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:OCSP +BIO_f_reliable 1219 1_1_0 EXIST::FUNCTION: +OCSP_resp_count 1220 1_1_0 EXIST::FUNCTION:OCSP +i2d_X509_AUX 1221 1_1_0 EXIST::FUNCTION: +RSA_verify_PKCS1_PSS_mgf1 1222 1_1_0 EXIST::FUNCTION:RSA +X509_time_adj 1223 1_1_0 EXIST::FUNCTION: +EVP_PKEY_asn1_find_str 1224 1_1_0 EXIST::FUNCTION: +X509_VERIFY_PARAM_get_flags 1225 1_1_0 EXIST::FUNCTION: +OPENSSL_DIR_end 1226 1_1_0 EXIST::FUNCTION: +EC_GROUP_new 1227 1_1_0 EXIST::FUNCTION:EC +CMS_SignerInfo_get0_pkey_ctx 1228 1_1_0 EXIST::FUNCTION:CMS +d2i_ASN1_PRINTABLESTRING 1229 1_1_0 EXIST::FUNCTION: +CMS_RecipientInfo_ktri_cert_cmp 1230 1_1_0 EXIST::FUNCTION:CMS +CMS_decrypt_set1_pkey 1231 1_1_0 EXIST::FUNCTION:CMS +PKCS7_RECIP_INFO_set 1232 1_1_0 EXIST::FUNCTION: +EC_POINT_is_on_curve 1233 1_1_0 EXIST::FUNCTION:EC +PKCS12_add_cert 1234 1_1_0 EXIST::FUNCTION: +X509_NAME_hash_old 1235 1_1_0 EXIST::FUNCTION: +PBKDF2PARAM_free 1236 1_1_0 EXIST::FUNCTION: +i2d_CMS_ContentInfo 1237 1_1_0 EXIST::FUNCTION:CMS +EVP_CIPHER_meth_set_ctrl 1238 1_1_0 EXIST::FUNCTION: +RSA_public_decrypt 1239 1_1_0 EXIST::FUNCTION:RSA +ENGINE_get_id 1240 1_1_0 EXIST::FUNCTION:ENGINE +PKCS12_item_decrypt_d2i 1241 1_1_0 EXIST::FUNCTION: +PEM_read_bio_DSAparams 1242 1_1_0 EXIST::FUNCTION:DSA +X509_CRL_cmp 1243 1_1_0 EXIST::FUNCTION: +DSO_METHOD_openssl 1244 1_1_0 EXIST::FUNCTION: +d2i_PrivateKey_fp 1245 1_1_0 EXIST::FUNCTION:STDIO +i2d_NETSCAPE_CERT_SEQUENCE 1246 1_1_0 EXIST::FUNCTION: +EC_POINT_oct2point 1248 1_1_0 EXIST::FUNCTION:EC +EVP_CIPHER_CTX_buf_noconst 1249 1_1_0 EXIST::FUNCTION: +OPENSSL_DIR_read 1250 1_1_0 EXIST::FUNCTION: +CMS_add_smimecap 1251 1_1_0 EXIST::FUNCTION:CMS +X509_check_email 1252 1_1_0 EXIST::FUNCTION: +CRYPTO_cts128_decrypt_block 1253 1_1_0 EXIST::FUNCTION: +UI_method_get_opener 1254 1_1_0 EXIST::FUNCTION: +EVP_aes_192_gcm 1255 1_1_0 EXIST::FUNCTION: +TS_CONF_set_tsa_name 1256 1_1_0 EXIST::FUNCTION:TS +X509_email_free 1257 1_1_0 EXIST::FUNCTION: +BIO_get_callback 1258 1_1_0 EXIST::FUNCTION: +OPENSSL_sk_shift 1259 1_1_0 EXIST::FUNCTION: +i2d_X509_REVOKED 1260 1_1_0 EXIST::FUNCTION: +CMS_sign 1261 1_1_0 EXIST::FUNCTION:CMS +X509_STORE_add_cert 1262 1_1_0 EXIST::FUNCTION: +EC_GROUP_precompute_mult 1263 1_1_0 EXIST::FUNCTION:EC +d2i_DISPLAYTEXT 1265 1_1_0 EXIST::FUNCTION: +HMAC_CTX_copy 1266 1_1_0 EXIST::FUNCTION: +CRYPTO_gcm128_init 1267 1_1_0 EXIST::FUNCTION: +i2d_X509_CINF 1268 1_1_0 EXIST::FUNCTION: +X509_REVOKED_delete_ext 1269 1_1_0 EXIST::FUNCTION: +RC5_32_cfb64_encrypt 1270 1_1_0 EXIST::FUNCTION:RC5 +TS_REQ_set_cert_req 1271 1_1_0 EXIST::FUNCTION:TS +TXT_DB_get_by_index 1272 1_1_0 EXIST::FUNCTION: +X509_check_ca 1273 1_1_0 EXIST::FUNCTION: +DH_get_2048_224 1274 1_1_0 EXIST::FUNCTION:DH +X509_http_nbio 1275 1_1_0 EXIST::FUNCTION:OCSP +i2d_AUTHORITY_INFO_ACCESS 1276 1_1_0 EXIST::FUNCTION: +EVP_get_cipherbyname 1277 1_1_0 EXIST::FUNCTION: +CONF_dump_fp 1278 1_1_0 EXIST::FUNCTION:STDIO +d2i_DIST_POINT_NAME 1279 1_1_0 EXIST::FUNCTION: +ASN1_INTEGER_set_int64 1280 1_1_0 EXIST::FUNCTION: +ASN1_TIME_free 1281 1_1_0 EXIST::FUNCTION: +i2o_SCT_LIST 1282 1_1_0 EXIST::FUNCTION:CT +AES_encrypt 1283 1_1_0 EXIST::FUNCTION: +MD5_Init 1284 1_1_0 EXIST::FUNCTION:MD5 +UI_add_error_string 1285 1_1_0 EXIST::FUNCTION: +X509_TRUST_cleanup 1286 1_1_0 EXIST::FUNCTION: +PEM_read_X509 1287 1_1_0 EXIST::FUNCTION:STDIO +EC_KEY_new_method 1288 1_1_0 EXIST::FUNCTION:EC +i2d_RSAPublicKey_fp 1289 1_1_0 EXIST::FUNCTION:RSA,STDIO +CRYPTO_ctr128_encrypt_ctr32 1290 1_1_0 EXIST::FUNCTION: +X509_VERIFY_PARAM_move_peername 1291 1_1_0 EXIST::FUNCTION: +OCSP_SINGLERESP_it 1292 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:OCSP +OCSP_SINGLERESP_it 1292 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:OCSP +BN_num_bits 1293 1_1_0 EXIST::FUNCTION: +X509_CRL_METHOD_free 1294 1_1_0 EXIST::FUNCTION: +PEM_read_NETSCAPE_CERT_SEQUENCE 1295 1_1_0 EXIST::FUNCTION:STDIO +OPENSSL_load_builtin_modules 1296 1_1_0 EXIST::FUNCTION: +X509_set_version 1297 1_1_0 EXIST::FUNCTION: +i2d_EC_PUBKEY_bio 1298 1_1_0 EXIST::FUNCTION:EC +X509_REQ_get_attr_count 1299 1_1_0 EXIST::FUNCTION: +CMS_set1_signers_certs 1300 1_1_0 EXIST::FUNCTION:CMS +TS_ACCURACY_free 1301 1_1_0 EXIST::FUNCTION:TS +PEM_write_DSA_PUBKEY 1302 1_1_0 EXIST::FUNCTION:DSA,STDIO +BN_rshift1 1303 1_1_0 EXIST::FUNCTION: +i2d_PKCS7_ENVELOPE 1304 1_1_0 EXIST::FUNCTION: +PBKDF2PARAM_it 1305 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +PBKDF2PARAM_it 1305 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +UI_get_result_maxsize 1306 1_1_0 EXIST::FUNCTION: +PBEPARAM_it 1307 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +PBEPARAM_it 1307 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +TS_ACCURACY_set_seconds 1308 1_1_0 EXIST::FUNCTION:TS +UI_get0_action_string 1309 1_1_0 EXIST::FUNCTION: +RC2_decrypt 1310 1_1_0 EXIST::FUNCTION:RC2 +OPENSSL_atexit 1311 1_1_0 EXIST::FUNCTION: +CMS_add_standard_smimecap 1312 1_1_0 EXIST::FUNCTION:CMS +PKCS7_add_attrib_content_type 1313 1_1_0 EXIST::FUNCTION: +BN_BLINDING_set_flags 1314 1_1_0 EXIST::FUNCTION: +ERR_peek_last_error 1315 1_1_0 EXIST::FUNCTION: +ENGINE_set_cmd_defns 1316 1_1_0 EXIST::FUNCTION:ENGINE +d2i_ASN1_NULL 1317 1_1_0 EXIST::FUNCTION: +RAND_event 1318 1_1_0 EXIST:_WIN32:FUNCTION:DEPRECATEDIN_1_1_0 +i2d_PKCS12_fp 1319 1_1_0 EXIST::FUNCTION:STDIO +EVP_PKEY_meth_get_init 1320 1_1_0 EXIST::FUNCTION: +X509_check_trust 1321 1_1_0 EXIST::FUNCTION: +b2i_PrivateKey 1322 1_1_0 EXIST::FUNCTION:DSA +HMAC_Init_ex 1323 1_1_0 EXIST::FUNCTION: +SMIME_read_CMS 1324 1_1_0 EXIST::FUNCTION:CMS +X509_subject_name_cmp 1325 1_1_0 EXIST::FUNCTION: +CRYPTO_ocb128_finish 1326 1_1_0 EXIST::FUNCTION:OCB +EVP_CIPHER_do_all 1327 1_1_0 EXIST::FUNCTION: +POLICY_MAPPINGS_it 1328 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +POLICY_MAPPINGS_it 1328 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +SCT_set0_log_id 1329 1_1_0 EXIST::FUNCTION:CT +CRYPTO_cfb128_encrypt 1330 1_1_0 EXIST::FUNCTION: +RSA_padding_add_PKCS1_type_2 1331 1_1_0 EXIST::FUNCTION:RSA +TS_CONF_set_signer_cert 1332 1_1_0 EXIST::FUNCTION:TS +i2d_ASN1_OBJECT 1333 1_1_0 EXIST::FUNCTION: +d2i_PKCS8_PRIV_KEY_INFO_bio 1334 1_1_0 EXIST::FUNCTION: +X509V3_add_value_int 1335 1_1_0 EXIST::FUNCTION: +TS_REQ_set_nonce 1336 1_1_0 EXIST::FUNCTION:TS +Camellia_ctr128_encrypt 1337 1_1_0 EXIST::FUNCTION:CAMELLIA +X509_LOOKUP_new 1338 1_1_0 EXIST::FUNCTION: +AUTHORITY_INFO_ACCESS_new 1339 1_1_0 EXIST::FUNCTION: +CRYPTO_mem_leaks_fp 1340 1_1_0 EXIST::FUNCTION:CRYPTO_MDEBUG,STDIO +DES_set_key_unchecked 1341 1_1_0 EXIST::FUNCTION:DES +BN_free 1342 1_1_0 EXIST::FUNCTION: +EVP_aes_128_cfb1 1343 1_1_0 EXIST::FUNCTION: +EC_KEY_get0_group 1344 1_1_0 EXIST::FUNCTION:EC +PEM_write_bio_CMS_stream 1345 1_1_0 EXIST::FUNCTION:CMS +BIO_f_linebuffer 1346 1_1_0 EXIST::FUNCTION: +ASN1_item_d2i_bio 1347 1_1_0 EXIST::FUNCTION: +ENGINE_get_flags 1348 1_1_0 EXIST::FUNCTION:ENGINE +OCSP_resp_find 1349 1_1_0 EXIST::FUNCTION:OCSP +OPENSSL_LH_node_usage_stats_bio 1350 1_1_0 EXIST::FUNCTION: +EVP_PKEY_encrypt 1351 1_1_0 EXIST::FUNCTION: +CRYPTO_cfb128_8_encrypt 1352 1_1_0 EXIST::FUNCTION: +SXNET_get_id_INTEGER 1353 1_1_0 EXIST::FUNCTION: +CRYPTO_clear_free 1354 1_1_0 EXIST::FUNCTION: +i2v_GENERAL_NAME 1355 1_1_0 EXIST::FUNCTION: +PKCS7_ENC_CONTENT_new 1356 1_1_0 EXIST::FUNCTION: +CRYPTO_realloc 1357 1_1_0 EXIST::FUNCTION: +BIO_ctrl_pending 1358 1_1_0 EXIST::FUNCTION: +EVP_MD_meth_new 1360 1_1_0 EXIST::FUNCTION: +X509_sign_ctx 1361 1_1_0 EXIST::FUNCTION: +BN_is_odd 1362 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_get_current_cert 1363 1_1_0 EXIST::FUNCTION: +ASN1_ENUMERATED_get_int64 1364 1_1_0 EXIST::FUNCTION: +ASN1_SCTX_get_app_data 1365 1_1_0 EXIST::FUNCTION: +X509_get_default_cert_file_env 1366 1_1_0 EXIST::FUNCTION: +X509v3_addr_validate_resource_set 1367 1_1_0 EXIST::FUNCTION:RFC3779 +d2i_X509_VAL 1368 1_1_0 EXIST::FUNCTION: +CRYPTO_gcm128_decrypt_ctr32 1370 1_1_0 EXIST::FUNCTION: +DHparams_print 1371 1_1_0 EXIST::FUNCTION:DH +OPENSSL_sk_unshift 1372 1_1_0 EXIST::FUNCTION: +BN_GENCB_set_old 1373 1_1_0 EXIST::FUNCTION: +PEM_write_bio_X509 1374 1_1_0 EXIST::FUNCTION: +EVP_PKEY_asn1_free 1375 1_1_0 EXIST::FUNCTION: +ENGINE_unregister_DH 1376 1_1_0 EXIST::FUNCTION:ENGINE +PROXY_CERT_INFO_EXTENSION_it 1377 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +PROXY_CERT_INFO_EXTENSION_it 1377 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +CT_POLICY_EVAL_CTX_set1_cert 1378 1_1_0 EXIST::FUNCTION:CT +X509_NAME_hash 1379 1_1_0 EXIST::FUNCTION: +SCT_set_timestamp 1380 1_1_0 EXIST::FUNCTION:CT +UI_new 1381 1_1_0 EXIST::FUNCTION: +TS_REQ_get_msg_imprint 1382 1_1_0 EXIST::FUNCTION:TS +i2d_PKCS12_BAGS 1383 1_1_0 EXIST::FUNCTION: +CERTIFICATEPOLICIES_free 1385 1_1_0 EXIST::FUNCTION: +X509V3_get_section 1386 1_1_0 EXIST::FUNCTION: +BIO_parse_hostserv 1387 1_1_0 EXIST::FUNCTION:SOCK +EVP_PKEY_meth_set_cleanup 1388 1_1_0 EXIST::FUNCTION: +PROXY_CERT_INFO_EXTENSION_free 1389 1_1_0 EXIST::FUNCTION: +X509_dup 1390 1_1_0 EXIST::FUNCTION: +EDIPARTYNAME_free 1391 1_1_0 EXIST::FUNCTION: +X509_CRL_add0_revoked 1393 1_1_0 EXIST::FUNCTION: +GENERAL_NAME_set0_value 1394 1_1_0 EXIST::FUNCTION: +X509_ATTRIBUTE_dup 1395 1_1_0 EXIST::FUNCTION: +EC_GROUP_check_discriminant 1396 1_1_0 EXIST::FUNCTION:EC +PKCS12_MAC_DATA_free 1397 1_1_0 EXIST::FUNCTION: +PEM_read_bio_PrivateKey 1398 1_1_0 EXIST::FUNCTION: +d2i_PKCS7_ENCRYPT 1399 1_1_0 EXIST::FUNCTION: +EVP_PKEY_CTX_ctrl 1400 1_1_0 EXIST::FUNCTION: +X509_REQ_set_pubkey 1401 1_1_0 EXIST::FUNCTION: +UI_create_method 1402 1_1_0 EXIST::FUNCTION: +X509_REQ_add_extensions_nid 1403 1_1_0 EXIST::FUNCTION: +PEM_X509_INFO_write_bio 1404 1_1_0 EXIST::FUNCTION: +BIO_dump_cb 1405 1_1_0 EXIST::FUNCTION: +v2i_GENERAL_NAMES 1406 1_1_0 EXIST::FUNCTION: +EVP_des_ede3_ofb 1407 1_1_0 EXIST::FUNCTION:DES +EVP_MD_meth_get_cleanup 1408 1_1_0 EXIST::FUNCTION: +SRP_Calc_server_key 1409 1_1_0 EXIST::FUNCTION:SRP +BN_mod_exp_simple 1410 1_1_0 EXIST::FUNCTION: +BIO_set_ex_data 1411 1_1_0 EXIST::FUNCTION: +SHA512 1412 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_get_explicit_policy 1413 1_1_0 EXIST::FUNCTION: +EVP_DecodeBlock 1414 1_1_0 EXIST::FUNCTION: +OCSP_REQ_CTX_http 1415 1_1_0 EXIST::FUNCTION:OCSP +EVP_MD_CTX_reset 1416 1_1_0 EXIST::FUNCTION: +X509_NAME_new 1417 1_1_0 EXIST::FUNCTION: +ASN1_item_pack 1418 1_1_0 EXIST::FUNCTION: +ASN1_BIT_STRING_set_asc 1419 1_1_0 EXIST::FUNCTION: +d2i_GENERAL_NAME 1420 1_1_0 EXIST::FUNCTION: +i2d_ESS_CERT_ID 1421 1_1_0 EXIST::FUNCTION:TS +X509_TRUST_get_by_id 1422 1_1_0 EXIST::FUNCTION: +d2i_RSA_PUBKEY_fp 1423 1_1_0 EXIST::FUNCTION:RSA,STDIO +EVP_PBE_get 1424 1_1_0 EXIST::FUNCTION: +CRYPTO_nistcts128_encrypt 1425 1_1_0 EXIST::FUNCTION: +CONF_modules_finish 1426 1_1_0 EXIST::FUNCTION: +BN_value_one 1427 1_1_0 EXIST::FUNCTION: +RSA_padding_add_SSLv23 1428 1_1_0 EXIST::FUNCTION:RSA +OCSP_RESPBYTES_it 1429 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:OCSP +OCSP_RESPBYTES_it 1429 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:OCSP +EVP_aes_192_wrap 1430 1_1_0 EXIST::FUNCTION: +OCSP_CERTID_it 1431 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:OCSP +OCSP_CERTID_it 1431 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:OCSP +ENGINE_get_RSA 1432 1_1_0 EXIST::FUNCTION:ENGINE +RAND_get_rand_method 1433 1_1_0 EXIST::FUNCTION: +ERR_load_DSA_strings 1434 1_1_0 EXIST::FUNCTION:DSA +ASN1_check_infinite_end 1435 1_1_0 EXIST::FUNCTION: +i2d_PKCS7_DIGEST 1436 1_1_0 EXIST::FUNCTION: +ERR_lib_error_string 1437 1_1_0 EXIST::FUNCTION: +X509_ATTRIBUTE_set1_object 1438 1_1_0 EXIST::FUNCTION: +i2d_ECPrivateKey_bio 1439 1_1_0 EXIST::FUNCTION:EC +BN_GENCB_free 1440 1_1_0 EXIST::FUNCTION: +HMAC_size 1441 1_1_0 EXIST::FUNCTION: +EVP_PKEY_get0_DH 1442 1_1_0 EXIST::FUNCTION:DH +d2i_OCSP_CRLID 1443 1_1_0 EXIST::FUNCTION:OCSP +EVP_CIPHER_CTX_set_padding 1444 1_1_0 EXIST::FUNCTION: +CTLOG_new_from_base64 1445 1_1_0 EXIST::FUNCTION:CT +AES_bi_ige_encrypt 1446 1_1_0 EXIST::FUNCTION: +ERR_pop_to_mark 1447 1_1_0 EXIST::FUNCTION: +CRL_DIST_POINTS_new 1449 1_1_0 EXIST::FUNCTION: +EVP_PKEY_get0_asn1 1450 1_1_0 EXIST::FUNCTION: +EVP_camellia_192_ctr 1451 1_1_0 EXIST::FUNCTION:CAMELLIA +EVP_PKEY_free 1452 1_1_0 EXIST::FUNCTION: +X509_ATTRIBUTE_count 1453 1_1_0 EXIST::FUNCTION: +BIO_new_dgram 1454 1_1_0 EXIST::FUNCTION:DGRAM +CMS_RecipientInfo_kari_get0_reks 1455 1_1_0 EXIST::FUNCTION:CMS +BASIC_CONSTRAINTS_new 1456 1_1_0 EXIST::FUNCTION: +PEM_read_bio_X509_REQ 1457 1_1_0 EXIST::FUNCTION: +BIO_sock_init 1458 1_1_0 EXIST::FUNCTION:SOCK +BN_nist_mod_192 1459 1_1_0 EXIST::FUNCTION: +i2d_PKCS7_ISSUER_AND_SERIAL 1460 1_1_0 EXIST::FUNCTION: +X509V3_EXT_nconf 1461 1_1_0 EXIST::FUNCTION: +X509v3_addr_inherits 1462 1_1_0 EXIST::FUNCTION:RFC3779 +NETSCAPE_SPKI_sign 1463 1_1_0 EXIST::FUNCTION: +BN_BLINDING_update 1464 1_1_0 EXIST::FUNCTION: +BN_gcd 1465 1_1_0 EXIST::FUNCTION: +CMS_dataInit 1466 1_1_0 EXIST::FUNCTION:CMS +TS_CONF_get_tsa_section 1467 1_1_0 EXIST::FUNCTION:TS +i2d_PKCS7_SIGNER_INFO 1468 1_1_0 EXIST::FUNCTION: +EVP_get_pw_prompt 1469 1_1_0 EXIST::FUNCTION: +BN_bn2bin 1470 1_1_0 EXIST::FUNCTION: +d2i_ASN1_BIT_STRING 1471 1_1_0 EXIST::FUNCTION: +OCSP_CERTSTATUS_new 1472 1_1_0 EXIST::FUNCTION:OCSP +ENGINE_register_RAND 1473 1_1_0 EXIST::FUNCTION:ENGINE +X509V3_section_free 1474 1_1_0 EXIST::FUNCTION: +CRYPTO_mem_debug_free 1475 1_1_0 EXIST::FUNCTION:CRYPTO_MDEBUG +d2i_OCSP_REQUEST 1476 1_1_0 EXIST::FUNCTION:OCSP +ENGINE_get_cipher_engine 1477 1_1_0 EXIST::FUNCTION:ENGINE +SHA384_Final 1478 1_1_0 EXIST::FUNCTION: +TS_RESP_CTX_set_certs 1479 1_1_0 EXIST::FUNCTION:TS +BN_MONT_CTX_free 1480 1_1_0 EXIST::FUNCTION: +BN_GF2m_mod_solve_quad_arr 1481 1_1_0 EXIST::FUNCTION:EC2M +UI_add_input_string 1482 1_1_0 EXIST::FUNCTION: +TS_TST_INFO_get_version 1483 1_1_0 EXIST::FUNCTION:TS +BIO_accept_ex 1484 1_1_0 EXIST::FUNCTION:SOCK +CRYPTO_get_mem_functions 1485 1_1_0 EXIST::FUNCTION: +PEM_read_bio 1486 1_1_0 EXIST::FUNCTION: +OCSP_BASICRESP_get_ext_by_critical 1487 1_1_0 EXIST::FUNCTION:OCSP +SXNET_it 1488 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +SXNET_it 1488 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +BIO_indent 1489 1_1_0 EXIST::FUNCTION: +i2d_X509_fp 1490 1_1_0 EXIST::FUNCTION:STDIO +d2i_ASN1_TYPE 1491 1_1_0 EXIST::FUNCTION: +CTLOG_STORE_free 1492 1_1_0 EXIST::FUNCTION:CT +ENGINE_get_pkey_meths 1493 1_1_0 EXIST::FUNCTION:ENGINE +i2d_TS_REQ_bio 1494 1_1_0 EXIST::FUNCTION:TS +EVP_PKEY_CTX_get_operation 1495 1_1_0 EXIST::FUNCTION: +EVP_MD_meth_set_ctrl 1496 1_1_0 EXIST::FUNCTION: +X509_EXTENSION_set_critical 1497 1_1_0 EXIST::FUNCTION: +BIO_ADDR_clear 1498 1_1_0 EXIST::FUNCTION:SOCK +ENGINE_get_DSA 1499 1_1_0 EXIST::FUNCTION:ENGINE +ASYNC_get_wait_ctx 1500 1_1_0 EXIST::FUNCTION: +ENGINE_set_load_privkey_function 1501 1_1_0 EXIST::FUNCTION:ENGINE +CRYPTO_ccm128_setiv 1502 1_1_0 EXIST::FUNCTION: +PKCS7_dataFinal 1503 1_1_0 EXIST::FUNCTION: +SHA1_Final 1504 1_1_0 EXIST::FUNCTION: +i2a_ASN1_STRING 1505 1_1_0 EXIST::FUNCTION: +EVP_CIPHER_CTX_rand_key 1506 1_1_0 EXIST::FUNCTION: +AES_set_encrypt_key 1507 1_1_0 EXIST::FUNCTION: +ASN1_UTCTIME_new 1508 1_1_0 EXIST::FUNCTION: +AES_cbc_encrypt 1509 1_1_0 EXIST::FUNCTION: +OCSP_RESPDATA_free 1510 1_1_0 EXIST::FUNCTION:OCSP +EVP_PKEY_asn1_find 1511 1_1_0 EXIST::FUNCTION: +d2i_ASN1_GENERALIZEDTIME 1512 1_1_0 EXIST::FUNCTION: +OPENSSL_cleanup 1513 1_1_0 EXIST::FUNCTION: +X509_ATTRIBUTE_create 1514 1_1_0 EXIST::FUNCTION: +SCT_get_source 1515 1_1_0 EXIST::FUNCTION:CT +EVP_PKEY_verify_init 1516 1_1_0 EXIST::FUNCTION: +ASN1_TIME_set_string 1517 1_1_0 EXIST::FUNCTION: +BIO_free 1518 1_1_0 EXIST::FUNCTION: +i2d_X509_ALGOR 1519 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_set0_crls 1520 1_1_0 EXIST::FUNCTION: +ASYNC_pause_job 1521 1_1_0 EXIST::FUNCTION: +OCSP_BASICRESP_new 1522 1_1_0 EXIST::FUNCTION:OCSP +EVP_camellia_256_ofb 1523 1_1_0 EXIST::FUNCTION:CAMELLIA +PKCS12_item_i2d_encrypt 1524 1_1_0 EXIST::FUNCTION: +EVP_PKEY_meth_set_copy 1525 1_1_0 EXIST::FUNCTION: +EC_POINT_clear_free 1526 1_1_0 EXIST::FUNCTION:EC +i2s_ASN1_ENUMERATED_TABLE 1527 1_1_0 EXIST::FUNCTION: +PKCS7_verify 1528 1_1_0 EXIST::FUNCTION: +X509_VERIFY_PARAM_add0_table 1529 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_set_cert 1530 1_1_0 EXIST::FUNCTION: +ASN1_GENERALSTRING_free 1531 1_1_0 EXIST::FUNCTION: +BN_MONT_CTX_set_locked 1532 1_1_0 EXIST::FUNCTION: +EVP_CIPHER_CTX_set_num 1533 1_1_0 EXIST::FUNCTION: +CONF_load 1534 1_1_0 EXIST::FUNCTION: +EC_KEY_METHOD_get_keygen 1535 1_1_0 EXIST::FUNCTION:EC +EVP_PKEY_add1_attr_by_txt 1536 1_1_0 EXIST::FUNCTION: +ASN1_INTEGER_set_uint64 1537 1_1_0 EXIST::FUNCTION: +EVP_PKEY_get_attr_by_OBJ 1538 1_1_0 EXIST::FUNCTION: +ASN1_add_oid_module 1539 1_1_0 EXIST::FUNCTION: +BN_div_recp 1540 1_1_0 EXIST::FUNCTION: +SRP_Verify_B_mod_N 1541 1_1_0 EXIST::FUNCTION:SRP +SXNET_free 1542 1_1_0 EXIST::FUNCTION: +CMS_get0_content 1543 1_1_0 EXIST::FUNCTION:CMS +BN_is_word 1544 1_1_0 EXIST::FUNCTION: +EVP_CIPHER_key_length 1545 1_1_0 EXIST::FUNCTION: +EVP_CIPHER_asn1_to_param 1546 1_1_0 EXIST::FUNCTION: +OCSP_request_onereq_get0 1547 1_1_0 EXIST::FUNCTION:OCSP +ERR_load_PKCS7_strings 1548 1_1_0 EXIST::FUNCTION: +X509_PUBKEY_get 1549 1_1_0 EXIST::FUNCTION: +EC_KEY_free 1550 1_1_0 EXIST::FUNCTION:EC +BIO_read 1551 1_1_0 EXIST::FUNCTION: +EVP_PKEY_get_attr_by_NID 1552 1_1_0 EXIST::FUNCTION: +BIO_get_accept_socket 1553 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0,SOCK +CMS_SignerInfo_sign 1554 1_1_0 EXIST::FUNCTION:CMS +ASN1_item_i2d_bio 1555 1_1_0 EXIST::FUNCTION: +EVP_CIPHER_CTX_block_size 1556 1_1_0 EXIST::FUNCTION: +DIRECTORYSTRING_free 1557 1_1_0 EXIST::FUNCTION: +TS_CONF_set_default_engine 1558 1_1_0 EXIST::FUNCTION:ENGINE,TS +BN_set_bit 1559 1_1_0 EXIST::FUNCTION: +EVP_MD_meth_set_app_datasize 1560 1_1_0 EXIST::FUNCTION: +DSO_free 1561 1_1_0 EXIST::FUNCTION: +TS_TST_INFO_get_tsa 1562 1_1_0 EXIST::FUNCTION:TS +EC_GROUP_check 1563 1_1_0 EXIST::FUNCTION:EC +OPENSSL_sk_delete 1564 1_1_0 EXIST::FUNCTION: +TS_RESP_CTX_set_extension_cb 1565 1_1_0 EXIST::FUNCTION:TS +EVP_CIPHER_CTX_nid 1566 1_1_0 EXIST::FUNCTION: +TS_RESP_CTX_add_md 1567 1_1_0 EXIST::FUNCTION:TS +DES_set_key 1568 1_1_0 EXIST::FUNCTION:DES +X509V3_extensions_print 1569 1_1_0 EXIST::FUNCTION: +PEM_do_header 1570 1_1_0 EXIST::FUNCTION: +i2d_re_X509_CRL_tbs 1571 1_1_0 EXIST::FUNCTION: +BIO_method_name 1572 1_1_0 EXIST::FUNCTION: +i2d_OCSP_CRLID 1573 1_1_0 EXIST::FUNCTION:OCSP +OCSP_request_set1_name 1574 1_1_0 EXIST::FUNCTION:OCSP +d2i_X509_NAME_ENTRY 1575 1_1_0 EXIST::FUNCTION: +X509_trusted 1576 1_1_0 EXIST::FUNCTION: +X509_TRUST_get_flags 1577 1_1_0 EXIST::FUNCTION: +PKCS7_set_content 1578 1_1_0 EXIST::FUNCTION: +PEM_write_X509_REQ_NEW 1579 1_1_0 EXIST::FUNCTION:STDIO +CONF_imodule_set_usr_data 1580 1_1_0 EXIST::FUNCTION: +d2i_TS_RESP_fp 1581 1_1_0 EXIST::FUNCTION:STDIO,TS +X509_policy_tree_get0_user_policies 1582 1_1_0 EXIST::FUNCTION: +DSA_do_sign 1584 1_1_0 EXIST::FUNCTION:DSA +EVP_CIPHER_CTX_reset 1585 1_1_0 EXIST::FUNCTION: +OCSP_REVOKEDINFO_new 1586 1_1_0 EXIST::FUNCTION:OCSP +SRP_Verify_A_mod_N 1587 1_1_0 EXIST::FUNCTION:SRP +SRP_VBASE_free 1588 1_1_0 EXIST::FUNCTION:SRP +PKCS7_add0_attrib_signing_time 1589 1_1_0 EXIST::FUNCTION: +X509_STORE_set_flags 1590 1_1_0 EXIST::FUNCTION: +UI_get0_output_string 1591 1_1_0 EXIST::FUNCTION: +ERR_get_error_line_data 1592 1_1_0 EXIST::FUNCTION: +CTLOG_get0_name 1593 1_1_0 EXIST::FUNCTION:CT +ASN1_TBOOLEAN_it 1594 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ASN1_TBOOLEAN_it 1594 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +RC2_set_key 1595 1_1_0 EXIST::FUNCTION:RC2 +X509_REVOKED_get_ext_by_NID 1596 1_1_0 EXIST::FUNCTION: +RSA_padding_add_none 1597 1_1_0 EXIST::FUNCTION:RSA +EVP_rc5_32_12_16_cbc 1599 1_1_0 EXIST::FUNCTION:RC5 +PEM_dek_info 1600 1_1_0 EXIST::FUNCTION: +ASN1_SCTX_get_template 1601 1_1_0 EXIST::FUNCTION: +EVP_PKEY_asn1_get0 1602 1_1_0 EXIST::FUNCTION: +X509_verify 1603 1_1_0 EXIST::FUNCTION: +TS_RESP_CTX_get_request 1604 1_1_0 EXIST::FUNCTION:TS +EVP_cast5_cbc 1605 1_1_0 EXIST::FUNCTION:CAST +PEM_read_bio_X509_AUX 1606 1_1_0 EXIST::FUNCTION: +TS_ext_print_bio 1607 1_1_0 EXIST::FUNCTION:TS +SCT_set1_log_id 1608 1_1_0 EXIST::FUNCTION:CT +X509_get0_pubkey_bitstr 1609 1_1_0 EXIST::FUNCTION: +ENGINE_register_all_RAND 1610 1_1_0 EXIST::FUNCTION:ENGINE +EVP_MD_meth_get_result_size 1612 1_1_0 EXIST::FUNCTION: +BIO_ADDRINFO_address 1613 1_1_0 EXIST::FUNCTION:SOCK +ASN1_STRING_print_ex 1614 1_1_0 EXIST::FUNCTION: +i2d_CMS_ReceiptRequest 1615 1_1_0 EXIST::FUNCTION:CMS +d2i_TS_REQ_fp 1616 1_1_0 EXIST::FUNCTION:STDIO,TS +OCSP_REQ_CTX_i2d 1617 1_1_0 EXIST::FUNCTION:OCSP +EVP_PKEY_get_default_digest_nid 1618 1_1_0 EXIST::FUNCTION: +ASIdOrRange_new 1619 1_1_0 EXIST::FUNCTION:RFC3779 +ASN1_SCTX_new 1620 1_1_0 EXIST::FUNCTION: +X509V3_EXT_get 1621 1_1_0 EXIST::FUNCTION: +OCSP_id_cmp 1622 1_1_0 EXIST::FUNCTION:OCSP +NCONF_dump_bio 1623 1_1_0 EXIST::FUNCTION: +X509_NAME_get_entry 1624 1_1_0 EXIST::FUNCTION: +EVP_PKEY_get1_DH 1625 1_1_0 EXIST::FUNCTION:DH +CRYPTO_gcm128_aad 1626 1_1_0 EXIST::FUNCTION: +EVP_des_cfb8 1627 1_1_0 EXIST::FUNCTION:DES +BN_BLINDING_convert 1628 1_1_0 EXIST::FUNCTION: +CRYPTO_ocb128_cleanup 1629 1_1_0 EXIST::FUNCTION:OCB +EVP_des_ede_cbc 1630 1_1_0 EXIST::FUNCTION:DES +i2d_ASN1_TIME 1631 1_1_0 EXIST::FUNCTION: +ENGINE_register_all_pkey_asn1_meths 1632 1_1_0 EXIST::FUNCTION:ENGINE +OCSP_set_max_response_length 1633 1_1_0 EXIST::FUNCTION:OCSP +d2i_ISSUING_DIST_POINT 1634 1_1_0 EXIST::FUNCTION: +CMS_RecipientInfo_set0_key 1635 1_1_0 EXIST::FUNCTION:CMS +NCONF_new 1636 1_1_0 EXIST::FUNCTION: +OCSP_SINGLERESP_free 1637 1_1_0 EXIST::FUNCTION:OCSP +PKCS7_ENCRYPT_free 1638 1_1_0 EXIST::FUNCTION: +i2d_DIST_POINT 1639 1_1_0 EXIST::FUNCTION: +EVP_PKEY_paramgen_init 1640 1_1_0 EXIST::FUNCTION: +TS_MSG_IMPRINT_dup 1641 1_1_0 EXIST::FUNCTION:TS +CMS_ContentInfo_it 1642 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:CMS +CMS_ContentInfo_it 1642 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:CMS +OCSP_resp_get0_signature 1643 1_1_0 EXIST::FUNCTION:OCSP +X509_STORE_CTX_get1_issuer 1644 1_1_0 EXIST::FUNCTION: +EVP_Digest 1645 1_1_0 EXIST::FUNCTION: +CRYPTO_set_ex_data 1646 1_1_0 EXIST::FUNCTION: +BN_bn2hex 1647 1_1_0 EXIST::FUNCTION: +BN_lshift1 1648 1_1_0 EXIST::FUNCTION: +i2d_EDIPARTYNAME 1649 1_1_0 EXIST::FUNCTION: +X509_policy_tree_get0_policies 1650 1_1_0 EXIST::FUNCTION: +X509at_add1_attr 1651 1_1_0 EXIST::FUNCTION: +X509_get_ex_data 1653 1_1_0 EXIST::FUNCTION: +RSA_set_method 1654 1_1_0 EXIST::FUNCTION:RSA +X509_REVOKED_dup 1655 1_1_0 EXIST::FUNCTION: +ASN1_TIME_new 1656 1_1_0 EXIST::FUNCTION: +PEM_write_NETSCAPE_CERT_SEQUENCE 1657 1_1_0 EXIST::FUNCTION:STDIO +PEM_read_X509_REQ 1658 1_1_0 EXIST::FUNCTION:STDIO +EC_GROUP_free 1659 1_1_0 EXIST::FUNCTION:EC +X509_CRL_get_meth_data 1660 1_1_0 EXIST::FUNCTION: +X509V3_add_value_uchar 1661 1_1_0 EXIST::FUNCTION: +BIO_asn1_get_suffix 1662 1_1_0 EXIST::FUNCTION: +X509_VERIFY_PARAM_clear_flags 1663 1_1_0 EXIST::FUNCTION: +X509_NAME_add_entry_by_txt 1664 1_1_0 EXIST::FUNCTION: +DES_ede3_cfb_encrypt 1665 1_1_0 EXIST::FUNCTION:DES +i2d_CMS_bio_stream 1667 1_1_0 EXIST::FUNCTION:CMS +DES_quad_cksum 1668 1_1_0 EXIST::FUNCTION:DES +X509_ATTRIBUTE_create_by_NID 1669 1_1_0 EXIST::FUNCTION: +TS_VERIFY_CTX_free 1670 1_1_0 EXIST::FUNCTION:TS +EC_KEY_up_ref 1671 1_1_0 EXIST::FUNCTION:EC +EC_GROUP_get_basis_type 1672 1_1_0 EXIST::FUNCTION:EC +OCSP_crlID_new 1673 1_1_0 EXIST:!VMS:FUNCTION:OCSP +OCSP_crlID2_new 1673 1_1_0 EXIST:VMS:FUNCTION:OCSP +PEM_write_PKCS7 1674 1_1_0 EXIST::FUNCTION:STDIO +PKCS7_add_signer 1675 1_1_0 EXIST::FUNCTION: +X509_SIG_it 1676 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +X509_SIG_it 1676 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +ASYNC_start_job 1677 1_1_0 EXIST::FUNCTION: +TS_TST_INFO_dup 1678 1_1_0 EXIST::FUNCTION:TS +EVP_aes_192_ctr 1679 1_1_0 EXIST::FUNCTION: +PKCS12_pack_authsafes 1680 1_1_0 EXIST::FUNCTION: +PKCS7_get_attribute 1681 1_1_0 EXIST::FUNCTION: +OPENSSL_config 1682 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0 +s2i_ASN1_INTEGER 1683 1_1_0 EXIST::FUNCTION: +CMS_signed_add1_attr_by_OBJ 1684 1_1_0 EXIST::FUNCTION:CMS +CRYPTO_128_wrap_pad 1685 1_1_0 EXIST::FUNCTION: +CMS_EncryptedData_set1_key 1686 1_1_0 EXIST::FUNCTION:CMS +OBJ_find_sigid_by_algs 1687 1_1_0 EXIST::FUNCTION: +ASN1_generate_nconf 1688 1_1_0 EXIST::FUNCTION: +CMS_add0_recipient_password 1689 1_1_0 EXIST::FUNCTION:CMS +UI_get_string_type 1690 1_1_0 EXIST::FUNCTION: +PEM_read_bio_ECPrivateKey 1691 1_1_0 EXIST::FUNCTION:EC +EVP_PKEY_get_attr 1692 1_1_0 EXIST::FUNCTION: +PEM_read_bio_ECPKParameters 1693 1_1_0 EXIST::FUNCTION:EC +d2i_PKCS12_MAC_DATA 1694 1_1_0 EXIST::FUNCTION: +ENGINE_ctrl_cmd 1695 1_1_0 EXIST::FUNCTION:ENGINE +PKCS12_SAFEBAG_get_bag_nid 1696 1_1_0 EXIST::FUNCTION: +TS_CONF_set_digests 1697 1_1_0 EXIST::FUNCTION:TS +PKCS7_SIGNED_it 1698 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +PKCS7_SIGNED_it 1698 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +b2i_PublicKey 1699 1_1_0 EXIST::FUNCTION:DSA +X509_PURPOSE_cleanup 1700 1_1_0 EXIST::FUNCTION: +ESS_SIGNING_CERT_dup 1701 1_1_0 EXIST::FUNCTION:TS +ENGINE_set_default_DSA 1702 1_1_0 EXIST::FUNCTION:ENGINE +X509_REVOKED_new 1703 1_1_0 EXIST::FUNCTION: +NCONF_WIN32 1704 1_1_0 EXIST::FUNCTION: +RSA_padding_check_PKCS1_OAEP_mgf1 1705 1_1_0 EXIST::FUNCTION:RSA +X509_policy_tree_get0_level 1706 1_1_0 EXIST::FUNCTION: +ASN1_parse_dump 1708 1_1_0 EXIST::FUNCTION: +BIO_vfree 1709 1_1_0 EXIST::FUNCTION: +CRYPTO_cbc128_decrypt 1710 1_1_0 EXIST::FUNCTION: +UI_dup_verify_string 1711 1_1_0 EXIST::FUNCTION: +d2i_PKCS7_bio 1712 1_1_0 EXIST::FUNCTION: +ENGINE_set_default_digests 1713 1_1_0 EXIST::FUNCTION:ENGINE +i2d_PublicKey 1714 1_1_0 EXIST::FUNCTION: +RC5_32_set_key 1715 1_1_0 EXIST::FUNCTION:RC5 +AES_unwrap_key 1716 1_1_0 EXIST::FUNCTION: +EVP_Cipher 1717 1_1_0 EXIST::FUNCTION: +AES_set_decrypt_key 1718 1_1_0 EXIST::FUNCTION: +BF_ofb64_encrypt 1719 1_1_0 EXIST::FUNCTION:BF +d2i_TS_TST_INFO_fp 1720 1_1_0 EXIST::FUNCTION:STDIO,TS +X509_find_by_issuer_and_serial 1721 1_1_0 EXIST::FUNCTION: +EVP_PKEY_type 1722 1_1_0 EXIST::FUNCTION: +ENGINE_ctrl 1723 1_1_0 EXIST::FUNCTION:ENGINE +EVP_cast5_ecb 1724 1_1_0 EXIST::FUNCTION:CAST +BIO_nwrite0 1725 1_1_0 EXIST::FUNCTION: +CAST_encrypt 1726 1_1_0 EXIST::FUNCTION:CAST +a2d_ASN1_OBJECT 1727 1_1_0 EXIST::FUNCTION: +OCSP_ONEREQ_delete_ext 1728 1_1_0 EXIST::FUNCTION:OCSP +UI_method_get_reader 1729 1_1_0 EXIST::FUNCTION: +CMS_unsigned_get_attr 1730 1_1_0 EXIST::FUNCTION:CMS +EVP_aes_256_cbc 1731 1_1_0 EXIST::FUNCTION: +X509_check_ip_asc 1732 1_1_0 EXIST::FUNCTION: +PEM_write_bio_X509_AUX 1733 1_1_0 EXIST::FUNCTION: +RC2_cbc_encrypt 1734 1_1_0 EXIST::FUNCTION:RC2 +TS_MSG_IMPRINT_new 1735 1_1_0 EXIST::FUNCTION:TS +EVP_ENCODE_CTX_new 1736 1_1_0 EXIST::FUNCTION: +BIO_f_base64 1737 1_1_0 EXIST::FUNCTION: +CMS_verify 1738 1_1_0 EXIST::FUNCTION:CMS +i2d_PrivateKey 1739 1_1_0 EXIST::FUNCTION: +i2d_OCSP_ONEREQ 1740 1_1_0 EXIST::FUNCTION:OCSP +OPENSSL_issetugid 1741 1_1_0 EXIST::FUNCTION: +d2i_ASN1_OBJECT 1742 1_1_0 EXIST::FUNCTION: +EVP_MD_meth_set_flags 1743 1_1_0 EXIST::FUNCTION: +EVP_idea_cbc 1744 1_1_0 EXIST::FUNCTION:IDEA +EC_POINT_cmp 1745 1_1_0 EXIST::FUNCTION:EC +ASN1_buf_print 1746 1_1_0 EXIST::FUNCTION: +EVP_PKEY_CTX_hex2ctrl 1747 1_1_0 EXIST::FUNCTION: +PEM_write_bio_PKCS8PrivateKey 1748 1_1_0 EXIST::FUNCTION: +CMAC_Update 1749 1_1_0 EXIST::FUNCTION:CMAC +d2i_ASN1_UTCTIME 1750 1_1_0 EXIST::FUNCTION: +OPENSSL_sk_insert 1751 1_1_0 EXIST::FUNCTION: +DSO_up_ref 1752 1_1_0 EXIST::FUNCTION: +EVP_rc2_cbc 1753 1_1_0 EXIST::FUNCTION:RC2 +i2d_NETSCAPE_SPKI 1754 1_1_0 EXIST::FUNCTION: +ASYNC_init_thread 1755 1_1_0 EXIST::FUNCTION: +OCSP_BASICRESP_get_ext_by_OBJ 1756 1_1_0 EXIST::FUNCTION:OCSP +X509_reject_clear 1757 1_1_0 EXIST::FUNCTION: +DH_security_bits 1758 1_1_0 EXIST::FUNCTION:DH +LONG_it 1759 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:DEPRECATEDIN_1_2_0 +LONG_it 1759 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:DEPRECATEDIN_1_2_0 +ASN1_dup 1760 1_1_0 EXIST::FUNCTION: +TS_RESP_new 1761 1_1_0 EXIST::FUNCTION:TS +i2d_PKCS8PrivateKeyInfo_fp 1762 1_1_0 EXIST::FUNCTION:STDIO +X509_alias_get0 1763 1_1_0 EXIST::FUNCTION: +X509_ATTRIBUTE_free 1764 1_1_0 EXIST::FUNCTION: +d2i_X509_bio 1765 1_1_0 EXIST::FUNCTION: +TS_TST_INFO_get_exts 1766 1_1_0 EXIST::FUNCTION:TS +EVP_aes_256_ecb 1767 1_1_0 EXIST::FUNCTION: +ASN1_BIT_STRING_name_print 1768 1_1_0 EXIST::FUNCTION: +d2i_X509_EXTENSIONS 1769 1_1_0 EXIST::FUNCTION: +ASN1_OCTET_STRING_free 1770 1_1_0 EXIST::FUNCTION: +PKCS7_RECIP_INFO_free 1771 1_1_0 EXIST::FUNCTION: +ASN1_tag2bit 1772 1_1_0 EXIST::FUNCTION: +TS_REQ_add_ext 1773 1_1_0 EXIST::FUNCTION:TS +X509_digest 1776 1_1_0 EXIST::FUNCTION: +CRYPTO_THREAD_cleanup_local 1777 1_1_0 EXIST::FUNCTION: +NETSCAPE_CERT_SEQUENCE_it 1778 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +NETSCAPE_CERT_SEQUENCE_it 1778 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +EVP_aes_128_wrap 1779 1_1_0 EXIST::FUNCTION: +X509V3_conf_free 1780 1_1_0 EXIST::FUNCTION: +TS_TST_INFO_get_ext_by_NID 1781 1_1_0 EXIST::FUNCTION:TS +EVP_aes_256_cfb1 1782 1_1_0 EXIST::FUNCTION: +X509_issuer_name_cmp 1783 1_1_0 EXIST::FUNCTION: +CMS_RecipientEncryptedKey_get0_id 1784 1_1_0 EXIST::FUNCTION:CMS +EVP_PKEY_meth_get_verify_recover 1785 1_1_0 EXIST::FUNCTION: +NAME_CONSTRAINTS_check 1786 1_1_0 EXIST::FUNCTION: +X509_CERT_AUX_it 1787 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +X509_CERT_AUX_it 1787 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +X509_get_X509_PUBKEY 1789 1_1_0 EXIST::FUNCTION: +TXT_DB_create_index 1790 1_1_0 EXIST::FUNCTION: +RAND_set_rand_engine 1791 1_1_0 EXIST::FUNCTION:ENGINE +X509_set_serialNumber 1792 1_1_0 EXIST::FUNCTION: +BN_mod_exp_mont_consttime 1793 1_1_0 EXIST::FUNCTION: +X509V3_parse_list 1794 1_1_0 EXIST::FUNCTION: +ACCESS_DESCRIPTION_new 1795 1_1_0 EXIST::FUNCTION: +EVP_CIPHER_CTX_clear_flags 1796 1_1_0 EXIST::FUNCTION: +ECDSA_size 1797 1_1_0 EXIST::FUNCTION:EC +X509_ALGOR_get0 1798 1_1_0 EXIST::FUNCTION: +d2i_ACCESS_DESCRIPTION 1799 1_1_0 EXIST::FUNCTION: +OCSP_SINGLERESP_get_ext_by_NID 1800 1_1_0 EXIST::FUNCTION:OCSP +a2i_IPADDRESS_NC 1801 1_1_0 EXIST::FUNCTION: +CTLOG_STORE_load_default_file 1802 1_1_0 EXIST::FUNCTION:CT +PKCS12_SAFEBAG_create_pkcs8_encrypt 1803 1_1_0 EXIST::FUNCTION: +RAND_screen 1804 1_1_0 EXIST:_WIN32:FUNCTION:DEPRECATEDIN_1_1_0 +CONF_get_string 1805 1_1_0 EXIST::FUNCTION: +X509_cmp_current_time 1806 1_1_0 EXIST::FUNCTION: +i2d_DSAPrivateKey 1807 1_1_0 EXIST::FUNCTION:DSA +ASN1_BIT_STRING_new 1808 1_1_0 EXIST::FUNCTION: +BIO_new_file 1809 1_1_0 EXIST::FUNCTION: +PKCS7_SIGNER_INFO_get0_algs 1810 1_1_0 EXIST::FUNCTION: +TS_RESP_set_status_info 1811 1_1_0 EXIST::FUNCTION:TS +OPENSSL_LH_delete 1812 1_1_0 EXIST::FUNCTION: +TS_STATUS_INFO_dup 1813 1_1_0 EXIST::FUNCTION:TS +X509v3_addr_get_range 1814 1_1_0 EXIST::FUNCTION:RFC3779 +X509_EXTENSION_get_data 1815 1_1_0 EXIST::FUNCTION: +RC5_32_encrypt 1816 1_1_0 EXIST::FUNCTION:RC5 +DIST_POINT_set_dpname 1817 1_1_0 EXIST::FUNCTION: +BIO_sock_info 1818 1_1_0 EXIST::FUNCTION:SOCK +OPENSSL_hexstr2buf 1819 1_1_0 EXIST::FUNCTION: +EVP_add_cipher 1820 1_1_0 EXIST::FUNCTION: +X509V3_EXT_add_list 1821 1_1_0 EXIST::FUNCTION: +CMS_compress 1822 1_1_0 EXIST::FUNCTION:CMS +X509_get_ext_by_critical 1823 1_1_0 EXIST::FUNCTION: +ASYNC_WAIT_CTX_clear_fd 1824 1_1_0 EXIST::FUNCTION: +ZLONG_it 1825 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:DEPRECATEDIN_1_2_0 +ZLONG_it 1825 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:DEPRECATEDIN_1_2_0 +OPENSSL_sk_find_ex 1826 1_1_0 EXIST::FUNCTION: +ASN1_ENUMERATED_to_BN 1827 1_1_0 EXIST::FUNCTION: +X509_CRL_get_ext_d2i 1828 1_1_0 EXIST::FUNCTION: +i2d_AUTHORITY_KEYID 1829 1_1_0 EXIST::FUNCTION: +TS_TST_INFO_get_time 1830 1_1_0 EXIST::FUNCTION:TS +ASN1_VISIBLESTRING_it 1831 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ASN1_VISIBLESTRING_it 1831 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +X509V3_EXT_REQ_add_conf 1832 1_1_0 EXIST::FUNCTION: +ASN1_STRING_to_UTF8 1833 1_1_0 EXIST::FUNCTION: +EVP_MD_meth_set_update 1835 1_1_0 EXIST::FUNCTION: +EVP_camellia_192_cbc 1836 1_1_0 EXIST::FUNCTION:CAMELLIA +OPENSSL_LH_stats_bio 1837 1_1_0 EXIST::FUNCTION: +PKCS7_set_signed_attributes 1838 1_1_0 EXIST::FUNCTION: +EC_KEY_priv2buf 1839 1_1_0 EXIST::FUNCTION:EC +BN_BLINDING_free 1840 1_1_0 EXIST::FUNCTION: +IPAddressChoice_new 1841 1_1_0 EXIST::FUNCTION:RFC3779 +X509_CRL_get_ext_count 1842 1_1_0 EXIST::FUNCTION: +PKCS12_add_key 1843 1_1_0 EXIST::FUNCTION: +EVP_camellia_128_cfb1 1844 1_1_0 EXIST::FUNCTION:CAMELLIA +BIO_find_type 1845 1_1_0 EXIST::FUNCTION: +ISSUING_DIST_POINT_it 1846 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ISSUING_DIST_POINT_it 1846 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +BIO_ctrl_wpending 1847 1_1_0 EXIST::FUNCTION: +X509_ALGOR_cmp 1848 1_1_0 EXIST::FUNCTION: +i2d_ASN1_bio_stream 1849 1_1_0 EXIST::FUNCTION: +CRYPTO_THREAD_init_local 1850 1_1_0 EXIST::FUNCTION: +TS_RESP_CTX_set_serial_cb 1851 1_1_0 EXIST::FUNCTION:TS +POLICY_MAPPING_it 1852 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +POLICY_MAPPING_it 1852 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +ERR_load_KDF_strings 1853 1_1_0 EXIST::FUNCTION: +UI_method_set_reader 1854 1_1_0 EXIST::FUNCTION: +BIO_next 1855 1_1_0 EXIST::FUNCTION: +ASN1_STRING_set_default_mask_asc 1856 1_1_0 EXIST::FUNCTION: +X509_CRL_new 1857 1_1_0 EXIST::FUNCTION: +i2b_PrivateKey_bio 1858 1_1_0 EXIST::FUNCTION:DSA +ASN1_STRING_length_set 1859 1_1_0 EXIST::FUNCTION: +PEM_write_PKCS8 1860 1_1_0 EXIST::FUNCTION:STDIO +PKCS7_digest_from_attributes 1861 1_1_0 EXIST::FUNCTION: +EC_GROUP_set_curve_GFp 1862 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_2_0,EC +X509_PURPOSE_get0 1863 1_1_0 EXIST::FUNCTION: +EVP_PKEY_set1_DSA 1864 1_1_0 EXIST::FUNCTION:DSA +X509_NAME_it 1865 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +X509_NAME_it 1865 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +OBJ_add_object 1866 1_1_0 EXIST::FUNCTION: +DSA_generate_key 1867 1_1_0 EXIST::FUNCTION:DSA +EVP_DigestUpdate 1868 1_1_0 EXIST::FUNCTION: +X509_get_ext_by_OBJ 1869 1_1_0 EXIST::FUNCTION: +PBEPARAM_new 1870 1_1_0 EXIST::FUNCTION: +EVP_aes_128_cbc 1871 1_1_0 EXIST::FUNCTION: +CRYPTO_dup_ex_data 1872 1_1_0 EXIST::FUNCTION: +OCSP_single_get0_status 1873 1_1_0 EXIST::FUNCTION:OCSP +d2i_AUTHORITY_INFO_ACCESS 1874 1_1_0 EXIST::FUNCTION: +PEM_read_RSAPrivateKey 1875 1_1_0 EXIST::FUNCTION:RSA,STDIO +BIO_closesocket 1876 1_1_0 EXIST::FUNCTION:SOCK +RSA_verify_ASN1_OCTET_STRING 1877 1_1_0 EXIST::FUNCTION:RSA +SCT_set_log_entry_type 1878 1_1_0 EXIST::FUNCTION:CT +BN_new 1879 1_1_0 EXIST::FUNCTION: +X509_OBJECT_retrieve_by_subject 1880 1_1_0 EXIST::FUNCTION: +MD5_Final 1881 1_1_0 EXIST::FUNCTION:MD5 +X509_STORE_set_verify_cb 1882 1_1_0 EXIST::FUNCTION: +OCSP_REQUEST_print 1883 1_1_0 EXIST::FUNCTION:OCSP +CMS_add1_crl 1884 1_1_0 EXIST::FUNCTION:CMS +d2i_EDIPARTYNAME 1885 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_set0_trusted_stack 1886 1_1_0 EXIST::FUNCTION: +BIO_ADDR_service_string 1887 1_1_0 EXIST::FUNCTION:SOCK +ASN1_BOOLEAN_it 1888 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ASN1_BOOLEAN_it 1888 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +TS_RESP_CTX_set_time_cb 1889 1_1_0 EXIST::FUNCTION:TS +IDEA_cbc_encrypt 1890 1_1_0 EXIST::FUNCTION:IDEA +BN_CTX_secure_new 1891 1_1_0 EXIST::FUNCTION: +OCSP_ONEREQ_add_ext 1892 1_1_0 EXIST::FUNCTION:OCSP +CMS_uncompress 1893 1_1_0 EXIST::FUNCTION:CMS +CRYPTO_mem_debug_pop 1895 1_1_0 EXIST::FUNCTION:CRYPTO_MDEBUG +EVP_aes_192_cfb128 1896 1_1_0 EXIST::FUNCTION: +OCSP_REQ_CTX_nbio 1897 1_1_0 EXIST::FUNCTION:OCSP +EVP_CIPHER_CTX_copy 1898 1_1_0 EXIST::FUNCTION: +CRYPTO_secure_allocated 1899 1_1_0 EXIST::FUNCTION: +UI_UTIL_read_pw_string 1900 1_1_0 EXIST::FUNCTION: +NOTICEREF_free 1901 1_1_0 EXIST::FUNCTION: +AES_cfb1_encrypt 1902 1_1_0 EXIST::FUNCTION: +X509v3_get_ext 1903 1_1_0 EXIST::FUNCTION: +CRYPTO_gcm128_encrypt_ctr32 1905 1_1_0 EXIST::FUNCTION: +SCT_set1_signature 1906 1_1_0 EXIST::FUNCTION:CT +CONF_imodule_get_module 1907 1_1_0 EXIST::FUNCTION: +NAME_CONSTRAINTS_new 1908 1_1_0 EXIST::FUNCTION: +BN_usub 1909 1_1_0 EXIST::FUNCTION: +SRP_Calc_B 1910 1_1_0 EXIST::FUNCTION:SRP +CMS_decrypt_set1_key 1911 1_1_0 EXIST::FUNCTION:CMS +EC_GROUP_get_degree 1912 1_1_0 EXIST::FUNCTION:EC +X509_ALGOR_set0 1913 1_1_0 EXIST::FUNCTION: +OPENSSL_LH_set_down_load 1914 1_1_0 EXIST::FUNCTION: +X509v3_asid_inherits 1915 1_1_0 EXIST::FUNCTION:RFC3779 +EVP_MD_meth_get_app_datasize 1916 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_get_num_untrusted 1917 1_1_0 EXIST::FUNCTION: +RAND_poll 1918 1_1_0 EXIST::FUNCTION: +EVP_PKEY_print_public 1919 1_1_0 EXIST::FUNCTION: +CMS_SignedData_init 1920 1_1_0 EXIST::FUNCTION:CMS +X509_REQ_free 1921 1_1_0 EXIST::FUNCTION: +ASN1_INTEGER_set 1922 1_1_0 EXIST::FUNCTION: +EVP_DecodeFinal 1923 1_1_0 EXIST::FUNCTION: +MD5_Transform 1925 1_1_0 EXIST::FUNCTION:MD5 +SRP_create_verifier_BN 1926 1_1_0 EXIST::FUNCTION:SRP +ENGINE_register_all_EC 1927 1_1_0 EXIST::FUNCTION:ENGINE +EVP_camellia_128_ofb 1928 1_1_0 EXIST::FUNCTION:CAMELLIA +PEM_write_X509_AUX 1929 1_1_0 EXIST::FUNCTION:STDIO +X509_LOOKUP_by_subject 1930 1_1_0 EXIST::FUNCTION: +X509_REQ_add_extensions 1931 1_1_0 EXIST::FUNCTION: +Camellia_cbc_encrypt 1932 1_1_0 EXIST::FUNCTION:CAMELLIA +EC_KEY_METHOD_new 1933 1_1_0 EXIST::FUNCTION:EC +RSA_flags 1934 1_1_0 EXIST::FUNCTION:RSA +X509_NAME_add_entry 1935 1_1_0 EXIST::FUNCTION: +EVP_CIPHER_get_asn1_iv 1936 1_1_0 EXIST::FUNCTION: +i2d_RSAPrivateKey_bio 1937 1_1_0 EXIST::FUNCTION:RSA +PKCS5_PBE_keyivgen 1938 1_1_0 EXIST::FUNCTION: +i2d_OCSP_SERVICELOC 1939 1_1_0 EXIST::FUNCTION:OCSP +EC_POINT_copy 1940 1_1_0 EXIST::FUNCTION:EC +X509V3_EXT_CRL_add_nconf 1941 1_1_0 EXIST::FUNCTION: +SHA256_Init 1942 1_1_0 EXIST::FUNCTION: +X509_NAME_ENTRY_get_object 1943 1_1_0 EXIST::FUNCTION: +ASN1_ENUMERATED_free 1944 1_1_0 EXIST::FUNCTION: +X509_CRL_set_meth_data 1945 1_1_0 EXIST::FUNCTION: +EVP_aes_192_cfb1 1946 1_1_0 EXIST::FUNCTION: +EVP_MD_CTX_set_flags 1947 1_1_0 EXIST::FUNCTION: +EVP_seed_cbc 1948 1_1_0 EXIST::FUNCTION:SEED +d2i_PKCS12 1949 1_1_0 EXIST::FUNCTION: +X509_policy_node_get0_policy 1950 1_1_0 EXIST::FUNCTION: +PKCS12_unpack_p7data 1951 1_1_0 EXIST::FUNCTION: +ECDSA_sign 1952 1_1_0 EXIST::FUNCTION:EC +d2i_PKCS12_fp 1953 1_1_0 EXIST::FUNCTION:STDIO +CMS_unsigned_get_attr_by_NID 1954 1_1_0 EXIST::FUNCTION:CMS +UI_add_user_data 1955 1_1_0 EXIST::FUNCTION: +BN_bntest_rand 1956 1_1_0 EXIST::FUNCTION: +X509_get_pubkey 1957 1_1_0 EXIST::FUNCTION: +i2d_X509_NAME 1958 1_1_0 EXIST::FUNCTION: +EVP_PKEY_add1_attr 1959 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_purpose_inherit 1960 1_1_0 EXIST::FUNCTION: +EVP_PKEY_meth_get_keygen 1961 1_1_0 EXIST::FUNCTION: +ENGINE_get_pkey_asn1_meth 1962 1_1_0 EXIST::FUNCTION:ENGINE +SHA256_Update 1963 1_1_0 EXIST::FUNCTION: +d2i_PKCS7_ISSUER_AND_SERIAL 1964 1_1_0 EXIST::FUNCTION: +PKCS12_unpack_authsafes 1965 1_1_0 EXIST::FUNCTION: +X509_CRL_it 1966 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +X509_CRL_it 1966 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +d2i_X509_ALGOR 1967 1_1_0 EXIST::FUNCTION: +PKCS12_PBE_keyivgen 1968 1_1_0 EXIST::FUNCTION: +BIO_test_flags 1969 1_1_0 EXIST::FUNCTION: +EC_POINT_get_affine_coordinates_GF2m 1970 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_2_0,EC,EC2M +EVP_ENCODE_CTX_num 1971 1_1_0 EXIST::FUNCTION: +Camellia_cfb1_encrypt 1972 1_1_0 EXIST::FUNCTION:CAMELLIA +NCONF_load_fp 1973 1_1_0 EXIST::FUNCTION:STDIO +i2d_OCSP_REQINFO 1974 1_1_0 EXIST::FUNCTION:OCSP +EVP_PKEY_sign 1975 1_1_0 EXIST::FUNCTION: +TS_REQ_get_ext_by_critical 1976 1_1_0 EXIST::FUNCTION:TS +EC_KEY_key2buf 1977 1_1_0 EXIST::FUNCTION:EC +X509_EXTENSION_it 1978 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +X509_EXTENSION_it 1978 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +i2d_PKCS8_fp 1979 1_1_0 EXIST::FUNCTION:STDIO +UTF8_getc 1980 1_1_0 EXIST::FUNCTION: +ASN1_IA5STRING_free 1981 1_1_0 EXIST::FUNCTION: +EC_KEY_METHOD_get_verify 1982 1_1_0 EXIST::FUNCTION:EC +OBJ_NAME_do_all 1983 1_1_0 EXIST::FUNCTION: +d2i_TS_MSG_IMPRINT_fp 1984 1_1_0 EXIST::FUNCTION:STDIO,TS +X509_CRL_verify 1985 1_1_0 EXIST::FUNCTION: +X509_get0_uids 1986 1_1_0 EXIST::FUNCTION: +EVP_PKEY_get0_DSA 1987 1_1_0 EXIST::FUNCTION:DSA +d2i_CMS_ContentInfo 1988 1_1_0 EXIST::FUNCTION:CMS +EVP_CIPHER_meth_get_do_cipher 1989 1_1_0 EXIST::FUNCTION: +i2d_DSA_PUBKEY 1990 1_1_0 EXIST::FUNCTION:DSA +GENERAL_NAME_it 1991 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +GENERAL_NAME_it 1991 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +EVP_des_ede_ecb 1992 1_1_0 EXIST::FUNCTION:DES +i2d_CRL_DIST_POINTS 1993 1_1_0 EXIST::FUNCTION: +PEM_write_bio_X509_REQ_NEW 1994 1_1_0 EXIST::FUNCTION: +RC5_32_ofb64_encrypt 1995 1_1_0 EXIST::FUNCTION:RC5 +i2d_PKCS7 1996 1_1_0 EXIST::FUNCTION: +BN_mod_lshift_quick 1997 1_1_0 EXIST::FUNCTION: +DIST_POINT_NAME_it 1998 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +DIST_POINT_NAME_it 1998 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +PEM_read_PrivateKey 1999 1_1_0 EXIST::FUNCTION:STDIO +X509V3_get_d2i 2000 1_1_0 EXIST::FUNCTION: +PKCS7_SIGNER_INFO_sign 2001 1_1_0 EXIST::FUNCTION: +TS_TST_INFO_free 2002 1_1_0 EXIST::FUNCTION:TS +DSA_security_bits 2003 1_1_0 EXIST::FUNCTION:DSA +X509v3_addr_is_canonical 2004 1_1_0 EXIST::FUNCTION:RFC3779 +BN_mod_mul_reciprocal 2005 1_1_0 EXIST::FUNCTION: +TS_REQ_get_version 2006 1_1_0 EXIST::FUNCTION:TS +BN_exp 2007 1_1_0 EXIST::FUNCTION: +i2d_SXNET 2008 1_1_0 EXIST::FUNCTION: +OBJ_bsearch_ 2009 1_1_0 EXIST::FUNCTION: +OPENSSL_LH_new 2010 1_1_0 EXIST::FUNCTION: +ENGINE_register_all_pkey_meths 2011 1_1_0 EXIST::FUNCTION:ENGINE +ENGINE_get_init_function 2012 1_1_0 EXIST::FUNCTION:ENGINE +EC_POINT_point2hex 2013 1_1_0 EXIST::FUNCTION:EC +ENGINE_get_default_DSA 2014 1_1_0 EXIST::FUNCTION:ENGINE +ENGINE_register_all_complete 2015 1_1_0 EXIST::FUNCTION:ENGINE +SRP_get_default_gN 2016 1_1_0 EXIST::FUNCTION:SRP +UI_dup_input_boolean 2017 1_1_0 EXIST::FUNCTION: +PKCS7_dup 2018 1_1_0 EXIST::FUNCTION: +i2d_TS_REQ_fp 2019 1_1_0 EXIST::FUNCTION:STDIO,TS +i2d_OTHERNAME 2020 1_1_0 EXIST::FUNCTION: +EC_KEY_get0_private_key 2021 1_1_0 EXIST::FUNCTION:EC +SCT_get0_extensions 2022 1_1_0 EXIST::FUNCTION:CT +OPENSSL_LH_node_stats_bio 2023 1_1_0 EXIST::FUNCTION: +i2d_DIRECTORYSTRING 2024 1_1_0 EXIST::FUNCTION: +BN_X931_derive_prime_ex 2025 1_1_0 EXIST::FUNCTION: +ENGINE_get_pkey_asn1_meth_str 2026 1_1_0 EXIST::FUNCTION:ENGINE +PKCS7_signatureVerify 2027 1_1_0 EXIST::FUNCTION: +CRYPTO_ocb128_new 2028 1_1_0 EXIST::FUNCTION:OCB +EC_curve_nist2nid 2029 1_1_0 EXIST::FUNCTION:EC +UI_get0_result 2030 1_1_0 EXIST::FUNCTION: +OCSP_request_add1_nonce 2031 1_1_0 EXIST::FUNCTION:OCSP +UI_construct_prompt 2032 1_1_0 EXIST::FUNCTION: +ENGINE_unregister_RSA 2033 1_1_0 EXIST::FUNCTION:ENGINE +EC_GROUP_order_bits 2034 1_1_0 EXIST::FUNCTION:EC +d2i_CMS_bio 2035 1_1_0 EXIST::FUNCTION:CMS +OPENSSL_sk_num 2036 1_1_0 EXIST::FUNCTION: +_shadow_DES_check_key 2037 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:DES +_shadow_DES_check_key 2037 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:DES +CMS_RecipientInfo_set0_pkey 2038 1_1_0 EXIST::FUNCTION:CMS +X509_STORE_CTX_set_default 2039 1_1_0 EXIST::FUNCTION: +AES_wrap_key 2040 1_1_0 EXIST::FUNCTION: +EVP_md_null 2041 1_1_0 EXIST::FUNCTION: +i2d_SCT_LIST 2042 1_1_0 EXIST::FUNCTION:CT +PKCS7_get_issuer_and_serial 2043 1_1_0 EXIST::FUNCTION: +PKCS7_SIGN_ENVELOPE_it 2044 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +PKCS7_SIGN_ENVELOPE_it 2044 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +ASN1_d2i_fp 2045 1_1_0 EXIST::FUNCTION:STDIO +EVP_DecryptFinal 2046 1_1_0 EXIST::FUNCTION: +ASN1_ENUMERATED_it 2047 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ASN1_ENUMERATED_it 2047 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +o2i_ECPublicKey 2048 1_1_0 EXIST::FUNCTION:EC +ERR_load_BUF_strings 2049 1_1_0 EXIST::FUNCTION: +PEM_read_bio_RSA_PUBKEY 2050 1_1_0 EXIST::FUNCTION:RSA +OCSP_SINGLERESP_new 2051 1_1_0 EXIST::FUNCTION:OCSP +ASN1_SCTX_free 2052 1_1_0 EXIST::FUNCTION: +i2d_ECPrivateKey_fp 2053 1_1_0 EXIST::FUNCTION:EC,STDIO +EVP_CIPHER_CTX_original_iv 2054 1_1_0 EXIST::FUNCTION: +PKCS7_SIGNED_free 2055 1_1_0 EXIST::FUNCTION: +X509_TRUST_get0_name 2056 1_1_0 EXIST::FUNCTION: +ENGINE_get_load_pubkey_function 2057 1_1_0 EXIST::FUNCTION:ENGINE +UI_get_default_method 2058 1_1_0 EXIST::FUNCTION: +PKCS12_add_CSPName_asc 2059 1_1_0 EXIST::FUNCTION: +PEM_write_PUBKEY 2060 1_1_0 EXIST::FUNCTION:STDIO +UI_method_set_prompt_constructor 2061 1_1_0 EXIST::FUNCTION: +OBJ_length 2062 1_1_0 EXIST::FUNCTION: +BN_GENCB_get_arg 2063 1_1_0 EXIST::FUNCTION: +EVP_MD_CTX_clear_flags 2064 1_1_0 EXIST::FUNCTION: +EVP_PKEY_meth_get_verifyctx 2065 1_1_0 EXIST::FUNCTION: +CT_POLICY_EVAL_CTX_get0_cert 2066 1_1_0 EXIST::FUNCTION:CT +PEM_write_DHparams 2067 1_1_0 EXIST::FUNCTION:DH,STDIO +DH_set_ex_data 2068 1_1_0 EXIST::FUNCTION:DH +OCSP_SIGNATURE_free 2069 1_1_0 EXIST::FUNCTION:OCSP +CRYPTO_128_unwrap_pad 2070 1_1_0 EXIST::FUNCTION: +BIO_new_CMS 2071 1_1_0 EXIST::FUNCTION:CMS +i2d_ASN1_ENUMERATED 2072 1_1_0 EXIST::FUNCTION: +PEM_read_DSAparams 2073 1_1_0 EXIST::FUNCTION:DSA,STDIO +TS_TST_INFO_set_ordering 2074 1_1_0 EXIST::FUNCTION:TS +MDC2_Init 2075 1_1_0 EXIST::FUNCTION:MDC2 +i2o_SCT 2076 1_1_0 EXIST::FUNCTION:CT +d2i_TS_STATUS_INFO 2077 1_1_0 EXIST::FUNCTION:TS +ERR_error_string_n 2078 1_1_0 EXIST::FUNCTION: +HMAC 2079 1_1_0 EXIST::FUNCTION: +BN_mul 2080 1_1_0 EXIST::FUNCTION: +BN_get0_nist_prime_384 2081 1_1_0 EXIST::FUNCTION: +X509_VERIFY_PARAM_set1_ip_asc 2082 1_1_0 EXIST::FUNCTION: +CONF_modules_load 2083 1_1_0 EXIST::FUNCTION: +d2i_RSAPublicKey 2084 1_1_0 EXIST::FUNCTION:RSA +i2d_ASN1_GENERALSTRING 2085 1_1_0 EXIST::FUNCTION: +POLICYQUALINFO_new 2086 1_1_0 EXIST::FUNCTION: +PKCS7_RECIP_INFO_get0_alg 2087 1_1_0 EXIST::FUNCTION: +EVP_PKEY_base_id 2088 1_1_0 EXIST::FUNCTION: +UI_method_set_opener 2089 1_1_0 EXIST::FUNCTION: +X509v3_get_ext_by_NID 2090 1_1_0 EXIST::FUNCTION: +TS_CONF_set_policies 2091 1_1_0 EXIST::FUNCTION:TS +CMS_SignerInfo_cert_cmp 2092 1_1_0 EXIST::FUNCTION:CMS +PEM_read 2093 1_1_0 EXIST::FUNCTION:STDIO +X509_STORE_set_depth 2094 1_1_0 EXIST::FUNCTION: +EC_KEY_METHOD_get_sign 2095 1_1_0 EXIST::FUNCTION:EC +EVP_CIPHER_CTX_iv 2096 1_1_0 EXIST::FUNCTION: +i2d_ESS_SIGNING_CERT 2097 1_1_0 EXIST::FUNCTION:TS +TS_RESP_set_tst_info 2098 1_1_0 EXIST::FUNCTION:TS +EVP_PKEY_CTX_set_data 2099 1_1_0 EXIST::FUNCTION: +CMS_EnvelopedData_create 2100 1_1_0 EXIST::FUNCTION:CMS +SCT_new 2101 1_1_0 EXIST::FUNCTION:CT +X509_REQ_add1_attr 2102 1_1_0 EXIST::FUNCTION: +X509_get_ext_count 2103 1_1_0 EXIST::FUNCTION: +CRYPTO_cts128_decrypt 2104 1_1_0 EXIST::FUNCTION: +ASYNC_WAIT_CTX_get_fd 2105 1_1_0 EXIST::FUNCTION: +i2d_TS_REQ 2106 1_1_0 EXIST::FUNCTION:TS +OCSP_ONEREQ_add1_ext_i2d 2107 1_1_0 EXIST::FUNCTION:OCSP +ENGINE_register_pkey_meths 2108 1_1_0 EXIST::FUNCTION:ENGINE +ENGINE_load_public_key 2109 1_1_0 EXIST::FUNCTION:ENGINE +ASIdOrRange_it 2110 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:RFC3779 +ASIdOrRange_it 2110 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:RFC3779 +DHparams_print_fp 2111 1_1_0 EXIST::FUNCTION:DH,STDIO +ERR_load_CRYPTO_strings 2112 1_1_0 EXIST:!VMS:FUNCTION: +ERR_load_CRYPTOlib_strings 2112 1_1_0 EXIST:VMS:FUNCTION: +X509_REQ_set_version 2113 1_1_0 EXIST::FUNCTION: +d2i_ASN1_GENERALSTRING 2114 1_1_0 EXIST::FUNCTION: +i2d_ASIdentifiers 2115 1_1_0 EXIST::FUNCTION:RFC3779 +X509V3_EXT_cleanup 2116 1_1_0 EXIST::FUNCTION: +CAST_ecb_encrypt 2117 1_1_0 EXIST::FUNCTION:CAST +BIO_s_file 2118 1_1_0 EXIST::FUNCTION: +RSA_X931_derive_ex 2119 1_1_0 EXIST::FUNCTION:RSA +EVP_PKEY_decrypt_init 2120 1_1_0 EXIST::FUNCTION: +ENGINE_get_destroy_function 2121 1_1_0 EXIST::FUNCTION:ENGINE +SHA224_Init 2122 1_1_0 EXIST::FUNCTION: +X509V3_EXT_add_conf 2123 1_1_0 EXIST::FUNCTION: +ASN1_object_size 2124 1_1_0 EXIST::FUNCTION: +X509_REVOKED_free 2125 1_1_0 EXIST::FUNCTION: +BN_mod_exp_recp 2126 1_1_0 EXIST::FUNCTION: +EVP_mdc2 2127 1_1_0 EXIST::FUNCTION:MDC2 +EVP_des_cfb64 2128 1_1_0 EXIST::FUNCTION:DES +PKCS7_sign 2129 1_1_0 EXIST::FUNCTION: +OCSP_SINGLERESP_get_ext_by_critical 2130 1_1_0 EXIST::FUNCTION:OCSP +EDIPARTYNAME_it 2131 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +EDIPARTYNAME_it 2131 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +ERR_print_errors_fp 2132 1_1_0 EXIST::FUNCTION:STDIO +BN_GF2m_mod_div_arr 2133 1_1_0 EXIST::FUNCTION:EC2M +PKCS12_SAFEBAG_get0_attr 2134 1_1_0 EXIST::FUNCTION: +BIO_s_mem 2135 1_1_0 EXIST::FUNCTION: +OCSP_RESPDATA_new 2136 1_1_0 EXIST::FUNCTION:OCSP +ASN1_item_i2d_fp 2137 1_1_0 EXIST::FUNCTION:STDIO +BN_GF2m_mod_sqr 2138 1_1_0 EXIST::FUNCTION:EC2M +ASN1_PRINTABLE_new 2139 1_1_0 EXIST::FUNCTION: +OBJ_NAME_new_index 2140 1_1_0 EXIST::FUNCTION: +EVP_PKEY_asn1_add_alias 2141 1_1_0 EXIST::FUNCTION: +EVP_PKEY_get1_DSA 2142 1_1_0 EXIST::FUNCTION:DSA +SEED_cbc_encrypt 2143 1_1_0 EXIST::FUNCTION:SEED +EVP_rc2_40_cbc 2144 1_1_0 EXIST::FUNCTION:RC2 +ECDSA_SIG_new 2145 1_1_0 EXIST::FUNCTION:EC +i2d_PKCS8PrivateKey_nid_fp 2146 1_1_0 EXIST::FUNCTION:STDIO +X509_NAME_ENTRY_it 2147 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +X509_NAME_ENTRY_it 2147 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +CRYPTO_THREAD_compare_id 2148 1_1_0 EXIST::FUNCTION: +d2i_IPAddressChoice 2149 1_1_0 EXIST::FUNCTION:RFC3779 +IPAddressFamily_it 2150 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:RFC3779 +IPAddressFamily_it 2150 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:RFC3779 +ERR_load_OCSP_strings 2151 1_1_0 EXIST::FUNCTION:OCSP +BIO_push 2152 1_1_0 EXIST::FUNCTION: +ASN1_BMPSTRING_new 2153 1_1_0 EXIST::FUNCTION: +COMP_get_type 2154 1_1_0 EXIST::FUNCTION:COMP +d2i_ASIdentifierChoice 2155 1_1_0 EXIST::FUNCTION:RFC3779 +i2d_ASN1_T61STRING 2156 1_1_0 EXIST::FUNCTION: +X509_add1_trust_object 2157 1_1_0 EXIST::FUNCTION: +PEM_write_X509 2158 1_1_0 EXIST::FUNCTION:STDIO +BN_CTX_free 2159 1_1_0 EXIST::FUNCTION: +EC_GROUP_get_curve_GF2m 2160 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_2_0,EC,EC2M +EVP_MD_flags 2161 1_1_0 EXIST::FUNCTION: +OPENSSL_sk_set 2162 1_1_0 EXIST::FUNCTION: +OCSP_request_sign 2163 1_1_0 EXIST::FUNCTION:OCSP +BN_GF2m_mod_solve_quad 2164 1_1_0 EXIST::FUNCTION:EC2M +EC_POINT_method_of 2165 1_1_0 EXIST::FUNCTION:EC +PKCS7_ENCRYPT_it 2166 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +PKCS7_ENCRYPT_it 2166 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +AUTHORITY_INFO_ACCESS_it 2167 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +AUTHORITY_INFO_ACCESS_it 2167 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +X509_EXTENSION_create_by_NID 2168 1_1_0 EXIST::FUNCTION: +i2d_RSAPrivateKey 2169 1_1_0 EXIST::FUNCTION:RSA +d2i_CERTIFICATEPOLICIES 2170 1_1_0 EXIST::FUNCTION: +CMAC_CTX_get0_cipher_ctx 2171 1_1_0 EXIST::FUNCTION:CMAC +X509_STORE_load_locations 2172 1_1_0 EXIST::FUNCTION: +OBJ_find_sigid_algs 2173 1_1_0 EXIST::FUNCTION: +TS_RESP_CTX_set_accuracy 2174 1_1_0 EXIST::FUNCTION:TS +NETSCAPE_SPKI_get_pubkey 2175 1_1_0 EXIST::FUNCTION: +ECDSA_do_sign_ex 2176 1_1_0 EXIST::FUNCTION:EC +OCSP_ONEREQ_get_ext 2177 1_1_0 EXIST::FUNCTION:OCSP +BN_get_rfc3526_prime_4096 2179 1_1_0 EXIST::FUNCTION: +d2i_PKCS7_fp 2180 1_1_0 EXIST::FUNCTION:STDIO +PEM_write_bio_NETSCAPE_CERT_SEQUENCE 2181 1_1_0 EXIST::FUNCTION: +PKCS12_AUTHSAFES_it 2182 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +PKCS12_AUTHSAFES_it 2182 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +EVP_MD_CTX_free 2183 1_1_0 EXIST::FUNCTION: +CMS_RecipientInfo_kari_orig_id_cmp 2184 1_1_0 EXIST::FUNCTION:CMS +NETSCAPE_SPKI_b64_encode 2185 1_1_0 EXIST::FUNCTION: +d2i_PrivateKey 2186 1_1_0 EXIST::FUNCTION: +EVP_MD_CTX_new 2187 1_1_0 EXIST::FUNCTION: +X509_get0_tbs_sigalg 2189 1_1_0 EXIST::FUNCTION: +ASN1_GENERALIZEDTIME_new 2190 1_1_0 EXIST::FUNCTION: +d2i_ECDSA_SIG 2191 1_1_0 EXIST::FUNCTION:EC +d2i_OTHERNAME 2192 1_1_0 EXIST::FUNCTION: +i2d_TS_RESP_fp 2193 1_1_0 EXIST::FUNCTION:STDIO,TS +OCSP_BASICRESP_get_ext_count 2194 1_1_0 EXIST::FUNCTION:OCSP +ASN1_T61STRING_new 2195 1_1_0 EXIST::FUNCTION: +BN_kronecker 2196 1_1_0 EXIST::FUNCTION: +i2d_ACCESS_DESCRIPTION 2197 1_1_0 EXIST::FUNCTION: +EVP_camellia_192_cfb8 2198 1_1_0 EXIST::FUNCTION:CAMELLIA +X509_STORE_CTX_set_depth 2199 1_1_0 EXIST::FUNCTION: +X509v3_delete_ext 2200 1_1_0 EXIST::FUNCTION: +ASN1_STRING_set0 2201 1_1_0 EXIST::FUNCTION: +BN_GF2m_add 2202 1_1_0 EXIST::FUNCTION:EC2M +CMAC_resume 2203 1_1_0 EXIST::FUNCTION:CMAC +TS_ACCURACY_set_millis 2204 1_1_0 EXIST::FUNCTION:TS +X509V3_EXT_conf 2205 1_1_0 EXIST::FUNCTION: +i2d_DHxparams 2206 1_1_0 EXIST::FUNCTION:DH +EVP_CIPHER_CTX_free 2207 1_1_0 EXIST::FUNCTION: +WHIRLPOOL_BitUpdate 2208 1_1_0 EXIST::FUNCTION:WHIRLPOOL +EVP_idea_ecb 2209 1_1_0 EXIST::FUNCTION:IDEA +i2d_TS_ACCURACY 2210 1_1_0 EXIST::FUNCTION:TS +ASN1_VISIBLESTRING_free 2211 1_1_0 EXIST::FUNCTION: +NCONF_load_bio 2212 1_1_0 EXIST::FUNCTION: +DSA_get_default_method 2213 1_1_0 EXIST::FUNCTION:DSA +OPENSSL_LH_retrieve 2214 1_1_0 EXIST::FUNCTION: +CRYPTO_ccm128_decrypt_ccm64 2215 1_1_0 EXIST::FUNCTION: +TS_RESP_CTX_set_clock_precision_digits 2216 1_1_0 EXIST::FUNCTION:TS +SCT_LIST_validate 2217 1_1_0 EXIST::FUNCTION:CT +X509_PURPOSE_get_id 2218 1_1_0 EXIST::FUNCTION: +EC_KEY_get_ex_data 2219 1_1_0 EXIST::FUNCTION:EC +EVP_MD_size 2220 1_1_0 EXIST::FUNCTION: +CRYPTO_malloc 2221 1_1_0 EXIST::FUNCTION: +ERR_load_ASN1_strings 2222 1_1_0 EXIST::FUNCTION: +X509_REQ_get_extension_nids 2223 1_1_0 EXIST::FUNCTION: +TS_REQ_get_ext_by_OBJ 2224 1_1_0 EXIST::FUNCTION:TS +i2d_X509 2225 1_1_0 EXIST::FUNCTION: +PEM_read_X509_AUX 2226 1_1_0 EXIST::FUNCTION:STDIO +TS_VERIFY_CTX_set_flags 2227 1_1_0 EXIST::FUNCTION:TS +IPAddressRange_new 2228 1_1_0 EXIST::FUNCTION:RFC3779 +TS_REQ_get_exts 2229 1_1_0 EXIST::FUNCTION:TS +POLICY_CONSTRAINTS_new 2230 1_1_0 EXIST::FUNCTION: +OTHERNAME_new 2231 1_1_0 EXIST::FUNCTION: +BN_rshift 2232 1_1_0 EXIST::FUNCTION: +i2d_GENERAL_NAMES 2233 1_1_0 EXIST::FUNCTION: +EC_METHOD_get_field_type 2234 1_1_0 EXIST::FUNCTION:EC +ENGINE_set_name 2235 1_1_0 EXIST::FUNCTION:ENGINE +TS_TST_INFO_get_policy_id 2236 1_1_0 EXIST::FUNCTION:TS +PKCS7_SIGNER_INFO_set 2237 1_1_0 EXIST::FUNCTION: +PEM_write_bio_PKCS8_PRIV_KEY_INFO 2238 1_1_0 EXIST::FUNCTION: +EC_GROUP_set_curve_GF2m 2239 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_2_0,EC,EC2M +ENGINE_load_builtin_engines 2240 1_1_0 EXIST::FUNCTION:ENGINE +SRP_VBASE_init 2241 1_1_0 EXIST::FUNCTION:SRP +SHA224_Final 2242 1_1_0 EXIST::FUNCTION: +OCSP_CERTSTATUS_free 2243 1_1_0 EXIST::FUNCTION:OCSP +d2i_TS_TST_INFO 2244 1_1_0 EXIST::FUNCTION:TS +IPAddressOrRange_it 2245 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:RFC3779 +IPAddressOrRange_it 2245 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:RFC3779 +ENGINE_get_cipher 2246 1_1_0 EXIST::FUNCTION:ENGINE +TS_TST_INFO_delete_ext 2247 1_1_0 EXIST::FUNCTION:TS +TS_OBJ_print_bio 2248 1_1_0 EXIST::FUNCTION:TS +X509_time_adj_ex 2249 1_1_0 EXIST::FUNCTION: +OCSP_request_add1_cert 2250 1_1_0 EXIST::FUNCTION:OCSP +ERR_load_X509_strings 2251 1_1_0 EXIST::FUNCTION: +SHA1_Transform 2252 1_1_0 EXIST::FUNCTION: +CMS_signed_get_attr_by_NID 2253 1_1_0 EXIST::FUNCTION:CMS +X509_STORE_CTX_get_by_subject 2254 1_1_0 EXIST::FUNCTION: +ASN1_OCTET_STRING_it 2255 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ASN1_OCTET_STRING_it 2255 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +OPENSSL_sk_set_cmp_func 2256 1_1_0 EXIST::FUNCTION: +X509_VERIFY_PARAM_table_cleanup 2257 1_1_0 EXIST::FUNCTION: +i2d_re_X509_REQ_tbs 2258 1_1_0 EXIST::FUNCTION: +CONF_load_bio 2259 1_1_0 EXIST::FUNCTION: +X509_ATTRIBUTE_get0_object 2260 1_1_0 EXIST::FUNCTION: +EVP_PKEY_missing_parameters 2261 1_1_0 EXIST::FUNCTION: +X509_REQ_INFO_new 2262 1_1_0 EXIST::FUNCTION: +EVP_rc2_cfb64 2263 1_1_0 EXIST::FUNCTION:RC2 +PKCS7_get_smimecap 2264 1_1_0 EXIST::FUNCTION: +ERR_get_state 2265 1_1_0 EXIST::FUNCTION: +d2i_DSAPrivateKey_bio 2266 1_1_0 EXIST::FUNCTION:DSA +X509_PURPOSE_get_trust 2267 1_1_0 EXIST::FUNCTION: +EC_GROUP_get_point_conversion_form 2268 1_1_0 EXIST::FUNCTION:EC +ASN1_OBJECT_it 2269 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ASN1_OBJECT_it 2269 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +BN_mod_add_quick 2270 1_1_0 EXIST::FUNCTION: +NCONF_free 2271 1_1_0 EXIST::FUNCTION: +NETSCAPE_SPKI_b64_decode 2272 1_1_0 EXIST::FUNCTION: +BIO_f_md 2273 1_1_0 EXIST::FUNCTION: +EVP_MD_CTX_pkey_ctx 2274 1_1_0 EXIST::FUNCTION: +ENGINE_set_default_EC 2275 1_1_0 EXIST::FUNCTION:ENGINE +CMS_ReceiptRequest_free 2276 1_1_0 EXIST::FUNCTION:CMS +TS_STATUS_INFO_get0_text 2277 1_1_0 EXIST::FUNCTION:TS +CRYPTO_get_ex_new_index 2278 1_1_0 EXIST::FUNCTION: +ASN1_PCTX_set_flags 2279 1_1_0 EXIST::FUNCTION: +PEM_write_X509_CRL 2280 1_1_0 EXIST::FUNCTION:STDIO +BF_cbc_encrypt 2281 1_1_0 EXIST::FUNCTION:BF +BN_num_bits_word 2282 1_1_0 EXIST::FUNCTION: +EVP_DecodeInit 2283 1_1_0 EXIST::FUNCTION: +BN_ucmp 2284 1_1_0 EXIST::FUNCTION: +SXNET_get_id_asc 2285 1_1_0 EXIST::FUNCTION: +SCT_set1_extensions 2286 1_1_0 EXIST::FUNCTION:CT +PKCS12_SAFEBAG_new 2287 1_1_0 EXIST::FUNCTION: +TS_TST_INFO_set_nonce 2288 1_1_0 EXIST::FUNCTION:TS +PEM_read_ECPrivateKey 2289 1_1_0 EXIST::FUNCTION:EC,STDIO +RSA_free 2290 1_1_0 EXIST::FUNCTION:RSA +X509_CRL_INFO_new 2291 1_1_0 EXIST::FUNCTION: +AES_cfb8_encrypt 2292 1_1_0 EXIST::FUNCTION: +d2i_ASN1_SEQUENCE_ANY 2293 1_1_0 EXIST::FUNCTION: +PKCS12_create 2294 1_1_0 EXIST::FUNCTION: +X509at_get_attr_count 2295 1_1_0 EXIST::FUNCTION: +PKCS12_init 2296 1_1_0 EXIST::FUNCTION: +CRYPTO_free_ex_data 2297 1_1_0 EXIST::FUNCTION: +EVP_aes_128_cfb8 2298 1_1_0 EXIST::FUNCTION: +ESS_ISSUER_SERIAL_free 2299 1_1_0 EXIST::FUNCTION:TS +BN_mod_exp_mont_word 2300 1_1_0 EXIST::FUNCTION: +X509V3_EXT_nconf_nid 2301 1_1_0 EXIST::FUNCTION: +UTF8_putc 2302 1_1_0 EXIST::FUNCTION: +RSA_private_encrypt 2303 1_1_0 EXIST::FUNCTION:RSA +X509_LOOKUP_shutdown 2304 1_1_0 EXIST::FUNCTION: +TS_TST_INFO_set_accuracy 2305 1_1_0 EXIST::FUNCTION:TS +OCSP_basic_verify 2306 1_1_0 EXIST::FUNCTION:OCSP +X509at_add1_attr_by_OBJ 2307 1_1_0 EXIST::FUNCTION: +EVP_PKEY_asn1_add0 2308 1_1_0 EXIST::FUNCTION: +PKCS12_SAFEBAG_get1_crl 2309 1_1_0 EXIST::FUNCTION: +ASN1_STRING_get_default_mask 2310 1_1_0 EXIST::FUNCTION: +X509_alias_set1 2311 1_1_0 EXIST::FUNCTION: +ASN1_item_unpack 2312 1_1_0 EXIST::FUNCTION: +HMAC_CTX_free 2313 1_1_0 EXIST::FUNCTION: +EC_POINT_new 2314 1_1_0 EXIST::FUNCTION:EC +PKCS7_ISSUER_AND_SERIAL_digest 2315 1_1_0 EXIST::FUNCTION: +EVP_des_ofb 2316 1_1_0 EXIST::FUNCTION:DES +DSA_set_method 2317 1_1_0 EXIST::FUNCTION:DSA +EVP_PKEY_get1_RSA 2318 1_1_0 EXIST::FUNCTION:RSA +EC_KEY_OpenSSL 2319 1_1_0 EXIST::FUNCTION:EC +EVP_camellia_192_ofb 2320 1_1_0 EXIST::FUNCTION:CAMELLIA +ASN1_STRING_length 2321 1_1_0 EXIST::FUNCTION: +PKCS7_set_digest 2322 1_1_0 EXIST::FUNCTION: +PEM_write_bio_PUBKEY 2323 1_1_0 EXIST::FUNCTION: +PEM_read_PKCS7 2324 1_1_0 EXIST::FUNCTION:STDIO +DH_get_2048_256 2325 1_1_0 EXIST::FUNCTION:DH +X509at_delete_attr 2326 1_1_0 EXIST::FUNCTION: +PEM_write_bio 2327 1_1_0 EXIST::FUNCTION: +CMS_signed_get_attr_by_OBJ 2329 1_1_0 EXIST::FUNCTION:CMS +X509_REVOKED_add_ext 2330 1_1_0 EXIST::FUNCTION: +EVP_CipherUpdate 2331 1_1_0 EXIST::FUNCTION: +Camellia_cfb8_encrypt 2332 1_1_0 EXIST::FUNCTION:CAMELLIA +EVP_aes_256_xts 2333 1_1_0 EXIST::FUNCTION: +EVP_DigestSignFinal 2334 1_1_0 EXIST::FUNCTION: +ASN1_STRING_cmp 2335 1_1_0 EXIST::FUNCTION: +EVP_chacha20_poly1305 2336 1_1_0 EXIST::FUNCTION:CHACHA,POLY1305 +OPENSSL_sk_zero 2337 1_1_0 EXIST::FUNCTION: +ASN1_PRINTABLE_type 2338 1_1_0 EXIST::FUNCTION: +TS_CONF_set_ess_cert_id_chain 2339 1_1_0 EXIST::FUNCTION:TS +PEM_read_DSAPrivateKey 2340 1_1_0 EXIST::FUNCTION:DSA,STDIO +DH_generate_parameters_ex 2341 1_1_0 EXIST::FUNCTION:DH +UI_dup_input_string 2342 1_1_0 EXIST::FUNCTION: +X509_keyid_set1 2343 1_1_0 EXIST::FUNCTION: +X509_VERIFY_PARAM_set1 2344 1_1_0 EXIST::FUNCTION: +EC_GROUP_get_asn1_flag 2345 1_1_0 EXIST::FUNCTION:EC +CMS_decrypt_set1_password 2346 1_1_0 EXIST::FUNCTION:CMS +BIO_copy_next_retry 2347 1_1_0 EXIST::FUNCTION: +X509_POLICY_NODE_print 2348 1_1_0 EXIST::FUNCTION: +ASN1_TIME_diff 2349 1_1_0 EXIST::FUNCTION: +BIO_s_fd 2350 1_1_0 EXIST::FUNCTION: +i2d_CMS_bio 2351 1_1_0 EXIST::FUNCTION:CMS +CRYPTO_gcm128_decrypt 2352 1_1_0 EXIST::FUNCTION: +EVP_aes_256_ctr 2353 1_1_0 EXIST::FUNCTION: +EVP_PKEY_bits 2354 1_1_0 EXIST::FUNCTION: +BN_BLINDING_new 2355 1_1_0 EXIST::FUNCTION: +ASN1_GENERALIZEDTIME_check 2356 1_1_0 EXIST::FUNCTION: +BN_clear_bit 2357 1_1_0 EXIST::FUNCTION: +BN_bn2lebinpad 2358 1_1_0 EXIST::FUNCTION: +EVP_PKEY_up_ref 2359 1_1_0 EXIST::FUNCTION: +X509_getm_notBefore 2360 1_1_0 EXIST::FUNCTION: +BN_nist_mod_224 2361 1_1_0 EXIST::FUNCTION: +DES_decrypt3 2362 1_1_0 EXIST::FUNCTION:DES +OTHERNAME_it 2363 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +OTHERNAME_it 2363 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +X509at_add1_attr_by_txt 2364 1_1_0 EXIST::FUNCTION: +PKCS7_SIGN_ENVELOPE_free 2365 1_1_0 EXIST::FUNCTION: +BIO_dgram_is_sctp 2366 1_1_0 EXIST::FUNCTION:DGRAM,SCTP +DH_check 2367 1_1_0 EXIST::FUNCTION:DH +Camellia_set_key 2368 1_1_0 EXIST::FUNCTION:CAMELLIA +X509_LOOKUP_by_issuer_serial 2369 1_1_0 EXIST::FUNCTION: +ASN1_BMPSTRING_free 2370 1_1_0 EXIST::FUNCTION: +BIO_new_accept 2371 1_1_0 EXIST::FUNCTION:SOCK +GENERAL_NAME_new 2372 1_1_0 EXIST::FUNCTION: +DES_encrypt3 2373 1_1_0 EXIST::FUNCTION:DES +PKCS7_get_signer_info 2374 1_1_0 EXIST::FUNCTION: +ASN1_OCTET_STRING_set 2375 1_1_0 EXIST::FUNCTION: +BN_mask_bits 2376 1_1_0 EXIST::FUNCTION: +ASN1_UTF8STRING_it 2377 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ASN1_UTF8STRING_it 2377 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +ASN1_SCTX_set_app_data 2378 1_1_0 EXIST::FUNCTION: +CMS_add0_cert 2379 1_1_0 EXIST::FUNCTION:CMS +i2d_GENERAL_NAME 2380 1_1_0 EXIST::FUNCTION: +BIO_ADDR_new 2381 1_1_0 EXIST::FUNCTION:SOCK +ENGINE_get_pkey_asn1_meth_engine 2382 1_1_0 EXIST::FUNCTION:ENGINE +d2i_ASN1_BMPSTRING 2383 1_1_0 EXIST::FUNCTION: +PKCS12_SAFEBAG_create0_p8inf 2384 1_1_0 EXIST::FUNCTION: +OBJ_cmp 2385 1_1_0 EXIST::FUNCTION: +MD2 2386 1_1_0 EXIST::FUNCTION:MD2 +X509_PUBKEY_new 2387 1_1_0 EXIST::FUNCTION: +BN_CTX_end 2388 1_1_0 EXIST::FUNCTION: +BIO_get_retry_BIO 2389 1_1_0 EXIST::FUNCTION: +X509_REQ_add1_attr_by_OBJ 2390 1_1_0 EXIST::FUNCTION: +ASN1_item_ex_free 2391 1_1_0 EXIST::FUNCTION: +X509_SIG_new 2392 1_1_0 EXIST::FUNCTION: +BN_sqr 2393 1_1_0 EXIST::FUNCTION: +TS_TST_INFO_set_time 2394 1_1_0 EXIST::FUNCTION:TS +OPENSSL_die 2395 1_1_0 EXIST::FUNCTION: +X509_LOOKUP_by_alias 2396 1_1_0 EXIST::FUNCTION: +EC_KEY_set_conv_form 2397 1_1_0 EXIST::FUNCTION:EC +X509_TRUST_get_count 2399 1_1_0 EXIST::FUNCTION: +IPAddressOrRange_free 2400 1_1_0 EXIST::FUNCTION:RFC3779 +RSA_padding_add_PKCS1_OAEP 2401 1_1_0 EXIST::FUNCTION:RSA +EC_KEY_set_ex_data 2402 1_1_0 EXIST::FUNCTION:EC +SRP_VBASE_new 2403 1_1_0 EXIST::FUNCTION:SRP +i2d_ECDSA_SIG 2404 1_1_0 EXIST::FUNCTION:EC +BIO_dump_indent 2405 1_1_0 EXIST::FUNCTION: +ENGINE_set_pkey_asn1_meths 2406 1_1_0 EXIST::FUNCTION:ENGINE +OPENSSL_gmtime_diff 2407 1_1_0 EXIST::FUNCTION: +TS_CONF_set_crypto_device 2408 1_1_0 EXIST::FUNCTION:ENGINE,TS +COMP_CTX_get_method 2409 1_1_0 EXIST::FUNCTION:COMP +EC_GROUP_get_cofactor 2410 1_1_0 EXIST::FUNCTION:EC +EVP_rc5_32_12_16_ofb 2411 1_1_0 EXIST::FUNCTION:RC5 +EVP_MD_CTX_md_data 2412 1_1_0 EXIST::FUNCTION: +ASN1_PCTX_set_nm_flags 2413 1_1_0 EXIST::FUNCTION: +BIO_ctrl 2414 1_1_0 EXIST::FUNCTION: +X509_CRL_set_default_method 2415 1_1_0 EXIST::FUNCTION: +d2i_RSAPublicKey_fp 2417 1_1_0 EXIST::FUNCTION:RSA,STDIO +UI_method_get_flusher 2418 1_1_0 EXIST::FUNCTION: +EC_POINT_dbl 2419 1_1_0 EXIST::FUNCTION:EC +i2d_X509_CRL_INFO 2420 1_1_0 EXIST::FUNCTION: +i2d_OCSP_CERTSTATUS 2421 1_1_0 EXIST::FUNCTION:OCSP +X509_REVOKED_get0_revocationDate 2422 1_1_0 EXIST::FUNCTION: +PKCS7_add_crl 2423 1_1_0 EXIST::FUNCTION: +ECDSA_do_sign 2424 1_1_0 EXIST::FUNCTION:EC +ASN1_GENERALIZEDTIME_it 2425 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ASN1_GENERALIZEDTIME_it 2425 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +PKCS8_pkey_get0 2426 1_1_0 EXIST::FUNCTION: +OCSP_sendreq_new 2427 1_1_0 EXIST::FUNCTION:OCSP +EVP_aes_256_cfb128 2428 1_1_0 EXIST::FUNCTION: +RSA_set_ex_data 2429 1_1_0 EXIST::FUNCTION:RSA +BN_GENCB_call 2430 1_1_0 EXIST::FUNCTION: +X509V3_EXT_add_nconf_sk 2431 1_1_0 EXIST::FUNCTION: +i2d_TS_MSG_IMPRINT_fp 2432 1_1_0 EXIST::FUNCTION:STDIO,TS +PKCS12_new 2433 1_1_0 EXIST::FUNCTION: +X509_REVOKED_set_serialNumber 2434 1_1_0 EXIST::FUNCTION: +EVP_get_digestbyname 2435 1_1_0 EXIST::FUNCTION: +X509_CRL_get_lastUpdate 2436 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0 +OBJ_create_objects 2437 1_1_0 EXIST::FUNCTION: +EVP_enc_null 2438 1_1_0 EXIST::FUNCTION: +OCSP_ONEREQ_get_ext_by_critical 2439 1_1_0 EXIST::FUNCTION:OCSP +OCSP_request_onereq_count 2440 1_1_0 EXIST::FUNCTION:OCSP +BN_hex2bn 2441 1_1_0 EXIST::FUNCTION: +EVP_CIPHER_meth_set_impl_ctx_size 2442 1_1_0 EXIST::FUNCTION: +ASIdentifiers_new 2443 1_1_0 EXIST::FUNCTION:RFC3779 +CONF_imodule_get_flags 2444 1_1_0 EXIST::FUNCTION: +PKCS12_SAFEBAG_it 2445 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +PKCS12_SAFEBAG_it 2445 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +EVP_CIPHER_meth_set_set_asn1_params 2446 1_1_0 EXIST::FUNCTION: +EC_KEY_get_enc_flags 2447 1_1_0 EXIST::FUNCTION:EC +X509_OBJECT_idx_by_subject 2448 1_1_0 EXIST::FUNCTION: +EVP_PKEY_meth_copy 2449 1_1_0 EXIST::FUNCTION: +NETSCAPE_CERT_SEQUENCE_new 2450 1_1_0 EXIST::FUNCTION: +CRYPTO_ocb128_decrypt 2451 1_1_0 EXIST::FUNCTION:OCB +ASYNC_WAIT_CTX_free 2452 1_1_0 EXIST::FUNCTION: +d2i_PKCS7_DIGEST 2453 1_1_0 EXIST::FUNCTION: +d2i_TS_TST_INFO_bio 2454 1_1_0 EXIST::FUNCTION:TS +BIGNUM_it 2455 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +BIGNUM_it 2455 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +BN_BLINDING_get_flags 2456 1_1_0 EXIST::FUNCTION: +X509_EXTENSION_get_critical 2457 1_1_0 EXIST::FUNCTION: +DSA_set_default_method 2458 1_1_0 EXIST::FUNCTION:DSA +PEM_write_bio_DHxparams 2459 1_1_0 EXIST::FUNCTION:DH +DSA_set_ex_data 2460 1_1_0 EXIST::FUNCTION:DSA +BIO_s_datagram_sctp 2461 1_1_0 EXIST::FUNCTION:DGRAM,SCTP +SXNET_add_id_asc 2462 1_1_0 EXIST::FUNCTION: +X509_print_fp 2463 1_1_0 EXIST::FUNCTION:STDIO +TS_REQ_set_version 2464 1_1_0 EXIST::FUNCTION:TS +OCSP_REQINFO_new 2465 1_1_0 EXIST::FUNCTION:OCSP +Camellia_decrypt 2466 1_1_0 EXIST::FUNCTION:CAMELLIA +X509_signature_print 2467 1_1_0 EXIST::FUNCTION: +EVP_camellia_128_ecb 2468 1_1_0 EXIST::FUNCTION:CAMELLIA +MD2_Final 2469 1_1_0 EXIST::FUNCTION:MD2 +OCSP_REQ_CTX_add1_header 2470 1_1_0 EXIST::FUNCTION:OCSP +NETSCAPE_SPKAC_it 2471 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +NETSCAPE_SPKAC_it 2471 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +ASIdOrRange_free 2472 1_1_0 EXIST::FUNCTION:RFC3779 +EC_POINT_get_Jprojective_coordinates_GFp 2473 1_1_0 EXIST::FUNCTION:EC +EVP_aes_128_cbc_hmac_sha256 2474 1_1_0 EXIST::FUNCTION: +i2d_PKCS7_SIGNED 2475 1_1_0 EXIST::FUNCTION: +TS_VERIFY_CTX_set_data 2476 1_1_0 EXIST::FUNCTION:TS +BN_pseudo_rand_range 2477 1_1_0 EXIST::FUNCTION: +X509V3_EXT_add_nconf 2478 1_1_0 EXIST::FUNCTION: +EVP_CIPHER_CTX_ctrl 2479 1_1_0 EXIST::FUNCTION: +ASN1_T61STRING_it 2480 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ASN1_T61STRING_it 2480 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +ENGINE_get_prev 2481 1_1_0 EXIST::FUNCTION:ENGINE +OCSP_accept_responses_new 2482 1_1_0 EXIST::FUNCTION:OCSP +ERR_load_EC_strings 2483 1_1_0 EXIST::FUNCTION:EC +X509V3_string_free 2484 1_1_0 EXIST::FUNCTION: +EVP_PKEY_meth_set_paramgen 2485 1_1_0 EXIST::FUNCTION: +ENGINE_set_load_ssl_client_cert_function 2486 1_1_0 EXIST::FUNCTION:ENGINE +EVP_ENCODE_CTX_free 2487 1_1_0 EXIST::FUNCTION: +i2d_ASN1_BIT_STRING 2488 1_1_0 EXIST::FUNCTION: +EVP_PKEY_meth_set_verifyctx 2489 1_1_0 EXIST::FUNCTION: +X509_TRUST_add 2490 1_1_0 EXIST::FUNCTION: +BUF_MEM_free 2491 1_1_0 EXIST::FUNCTION: +TS_TST_INFO_get_accuracy 2492 1_1_0 EXIST::FUNCTION:TS +TS_REQ_dup 2493 1_1_0 EXIST::FUNCTION:TS +ASN1_STRING_type_new 2494 1_1_0 EXIST::FUNCTION: +TS_STATUS_INFO_free 2495 1_1_0 EXIST::FUNCTION:TS +BN_mod_mul 2496 1_1_0 EXIST::FUNCTION: +CMS_add0_recipient_key 2497 1_1_0 EXIST::FUNCTION:CMS +BIO_f_zlib 2498 1_1_0 EXIST:ZLIB:FUNCTION:COMP +AES_cfb128_encrypt 2499 1_1_0 EXIST::FUNCTION: +ENGINE_set_EC 2500 1_1_0 EXIST::FUNCTION:ENGINE +d2i_ECPKParameters 2501 1_1_0 EXIST::FUNCTION:EC +IDEA_ofb64_encrypt 2502 1_1_0 EXIST::FUNCTION:IDEA +CAST_decrypt 2503 1_1_0 EXIST::FUNCTION:CAST +TS_STATUS_INFO_get0_failure_info 2504 1_1_0 EXIST::FUNCTION:TS +ENGINE_unregister_pkey_meths 2506 1_1_0 EXIST::FUNCTION:ENGINE +DISPLAYTEXT_new 2507 1_1_0 EXIST::FUNCTION: +CMS_final 2508 1_1_0 EXIST::FUNCTION:CMS +BIO_nwrite 2509 1_1_0 EXIST::FUNCTION: +GENERAL_NAME_free 2510 1_1_0 EXIST::FUNCTION: +PKCS12_pack_p7encdata 2511 1_1_0 EXIST::FUNCTION: +BN_generate_dsa_nonce 2512 1_1_0 EXIST::FUNCTION: +X509_verify_cert 2513 1_1_0 EXIST::FUNCTION: +X509_policy_level_get0_node 2514 1_1_0 EXIST::FUNCTION: +X509_REQ_get_attr 2515 1_1_0 EXIST::FUNCTION: +SHA1 2516 1_1_0 EXIST::FUNCTION: +X509_print 2517 1_1_0 EXIST::FUNCTION: +d2i_AutoPrivateKey 2518 1_1_0 EXIST::FUNCTION: +X509_REQ_new 2519 1_1_0 EXIST::FUNCTION: +PKCS12_add_safes 2520 1_1_0 EXIST::FUNCTION: +PKCS12_parse 2521 1_1_0 EXIST::FUNCTION: +BN_GF2m_mod_div 2522 1_1_0 EXIST::FUNCTION:EC2M +i2d_USERNOTICE 2523 1_1_0 EXIST::FUNCTION: +d2i_NETSCAPE_SPKI 2524 1_1_0 EXIST::FUNCTION: +CRYPTO_mem_leaks 2525 1_1_0 EXIST::FUNCTION:CRYPTO_MDEBUG +BN_get_rfc3526_prime_1536 2526 1_1_0 EXIST::FUNCTION: +DSA_sign 2527 1_1_0 EXIST::FUNCTION:DSA +RAND_egd 2528 1_1_0 EXIST::FUNCTION:EGD +ASN1_d2i_bio 2529 1_1_0 EXIST::FUNCTION: +X509_REQ_digest 2531 1_1_0 EXIST::FUNCTION: +X509_set1_notAfter 2532 1_1_0 EXIST::FUNCTION: +EVP_CIPHER_type 2533 1_1_0 EXIST::FUNCTION: +ASN1_TYPE_set_octetstring 2534 1_1_0 EXIST::FUNCTION: +EVP_PKEY_asn1_set_free 2535 1_1_0 EXIST::FUNCTION: +CMS_signed_get0_data_by_OBJ 2536 1_1_0 EXIST::FUNCTION:CMS +X509_PURPOSE_add 2537 1_1_0 EXIST::FUNCTION: +PKCS7_ENVELOPE_free 2538 1_1_0 EXIST::FUNCTION: +PKCS12_key_gen_uni 2539 1_1_0 EXIST::FUNCTION: +WHIRLPOOL 2540 1_1_0 EXIST::FUNCTION:WHIRLPOOL +UI_set_default_method 2542 1_1_0 EXIST::FUNCTION: +EC_POINT_is_at_infinity 2543 1_1_0 EXIST::FUNCTION:EC +i2d_NOTICEREF 2544 1_1_0 EXIST::FUNCTION: +EC_KEY_new 2545 1_1_0 EXIST::FUNCTION:EC +EVP_chacha20 2546 1_1_0 EXIST::FUNCTION:CHACHA +BN_bn2dec 2547 1_1_0 EXIST::FUNCTION: +X509_REQ_print_ex 2548 1_1_0 EXIST::FUNCTION: +PEM_read_CMS 2549 1_1_0 EXIST::FUNCTION:CMS,STDIO +d2i_NETSCAPE_CERT_SEQUENCE 2550 1_1_0 EXIST::FUNCTION: +X509_CRL_set_version 2551 1_1_0 EXIST::FUNCTION: +ASN1_PCTX_set_cert_flags 2552 1_1_0 EXIST::FUNCTION: +PKCS8_PRIV_KEY_INFO_free 2553 1_1_0 EXIST::FUNCTION: +SHA224_Update 2554 1_1_0 EXIST::FUNCTION: +EC_GROUP_new_by_curve_name 2555 1_1_0 EXIST::FUNCTION:EC +X509_STORE_set_purpose 2556 1_1_0 EXIST::FUNCTION: +X509_CRL_get0_signature 2557 1_1_0 EXIST::FUNCTION: +EVP_PKEY_CTX_get_keygen_info 2558 1_1_0 EXIST::FUNCTION: +d2i_ASN1_UINTEGER 2559 1_1_0 EXIST::FUNCTION: +i2s_ASN1_INTEGER 2560 1_1_0 EXIST::FUNCTION: +d2i_EC_PUBKEY_fp 2561 1_1_0 EXIST::FUNCTION:EC,STDIO +i2d_OCSP_SIGNATURE 2562 1_1_0 EXIST::FUNCTION:OCSP +i2d_X509_EXTENSION 2563 1_1_0 EXIST::FUNCTION: +PEM_read_bio_X509 2564 1_1_0 EXIST::FUNCTION: +DES_key_sched 2565 1_1_0 EXIST::FUNCTION:DES +GENERAL_NAME_dup 2566 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_get1_crls 2567 1_1_0 EXIST::FUNCTION: +EVP_PKEY_meth_set_verify 2568 1_1_0 EXIST::FUNCTION: +EVP_sha256 2569 1_1_0 EXIST::FUNCTION: +CMS_unsigned_delete_attr 2570 1_1_0 EXIST::FUNCTION:CMS +EVP_md5_sha1 2571 1_1_0 EXIST::FUNCTION:MD5 +EVP_PKEY_sign_init 2572 1_1_0 EXIST::FUNCTION: +OPENSSL_LH_insert 2573 1_1_0 EXIST::FUNCTION: +EVP_CIPHER_meth_get_cleanup 2574 1_1_0 EXIST::FUNCTION: +ASN1_item_ex_d2i 2575 1_1_0 EXIST::FUNCTION: +EVP_MD_meth_free 2576 1_1_0 EXIST::FUNCTION: +EVP_PKEY_meth_new 2577 1_1_0 EXIST::FUNCTION: +RSA_padding_check_PKCS1_OAEP 2578 1_1_0 EXIST::FUNCTION:RSA +OCSP_SERVICELOC_it 2579 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:OCSP +OCSP_SERVICELOC_it 2579 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:OCSP +PKCS12_SAFEBAG_get_nid 2580 1_1_0 EXIST::FUNCTION: +EVP_MD_CTX_set_update_fn 2581 1_1_0 EXIST::FUNCTION: +BIO_f_asn1 2582 1_1_0 EXIST::FUNCTION: +BIO_dump 2583 1_1_0 EXIST::FUNCTION: +ENGINE_load_ssl_client_cert 2584 1_1_0 EXIST::FUNCTION:ENGINE +X509_STORE_CTX_set_verify_cb 2585 1_1_0 EXIST::FUNCTION: +CRYPTO_clear_realloc 2586 1_1_0 EXIST::FUNCTION: +OPENSSL_strnlen 2587 1_1_0 EXIST::FUNCTION: +IDEA_ecb_encrypt 2588 1_1_0 EXIST::FUNCTION:IDEA +ASN1_STRING_set_default_mask 2589 1_1_0 EXIST::FUNCTION: +TS_VERIFY_CTX_add_flags 2590 1_1_0 EXIST::FUNCTION:TS +FIPS_mode 2591 1_1_0 EXIST::FUNCTION: +d2i_ASN1_UNIVERSALSTRING 2592 1_1_0 EXIST::FUNCTION: +NAME_CONSTRAINTS_free 2593 1_1_0 EXIST::FUNCTION: +EC_GROUP_get_order 2594 1_1_0 EXIST::FUNCTION:EC +X509_REVOKED_add1_ext_i2d 2595 1_1_0 EXIST::FUNCTION: +X509_VERIFY_PARAM_add1_host 2596 1_1_0 EXIST::FUNCTION: +i2d_PUBKEY_bio 2597 1_1_0 EXIST::FUNCTION: +MD4_Update 2598 1_1_0 EXIST::FUNCTION:MD4 +X509_STORE_CTX_set_time 2599 1_1_0 EXIST::FUNCTION: +ENGINE_set_default_DH 2600 1_1_0 EXIST::FUNCTION:ENGINE +X509_ocspid_print 2601 1_1_0 EXIST::FUNCTION: +DH_set_method 2602 1_1_0 EXIST::FUNCTION:DH +EVP_rc2_64_cbc 2603 1_1_0 EXIST::FUNCTION:RC2 +CRYPTO_THREAD_get_current_id 2604 1_1_0 EXIST::FUNCTION: +EVP_PKEY_CTX_set_cb 2605 1_1_0 EXIST::FUNCTION: +PROXY_POLICY_it 2606 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +PROXY_POLICY_it 2606 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +ENGINE_register_complete 2607 1_1_0 EXIST::FUNCTION:ENGINE +EVP_DecodeUpdate 2609 1_1_0 EXIST::FUNCTION: +ENGINE_get_default_RAND 2610 1_1_0 EXIST::FUNCTION:ENGINE +ERR_peek_last_error_line 2611 1_1_0 EXIST::FUNCTION: +ENGINE_get_ssl_client_cert_function 2612 1_1_0 EXIST::FUNCTION:ENGINE +OPENSSL_LH_node_usage_stats 2613 1_1_0 EXIST::FUNCTION:STDIO +DIRECTORYSTRING_it 2614 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +DIRECTORYSTRING_it 2614 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +BIO_write 2615 1_1_0 EXIST::FUNCTION: +OCSP_ONEREQ_get_ext_by_OBJ 2616 1_1_0 EXIST::FUNCTION:OCSP +SEED_encrypt 2617 1_1_0 EXIST::FUNCTION:SEED +IPAddressRange_it 2618 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:RFC3779 +IPAddressRange_it 2618 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:RFC3779 +PEM_read_bio_DSAPrivateKey 2619 1_1_0 EXIST::FUNCTION:DSA +CMS_get0_type 2620 1_1_0 EXIST::FUNCTION:CMS +ASN1_PCTX_free 2621 1_1_0 EXIST::FUNCTION: +ESS_SIGNING_CERT_new 2622 1_1_0 EXIST::FUNCTION:TS +X509V3_EXT_conf_nid 2623 1_1_0 EXIST::FUNCTION: +EC_KEY_check_key 2624 1_1_0 EXIST::FUNCTION:EC +PKCS5_PBKDF2_HMAC 2625 1_1_0 EXIST::FUNCTION: +CONF_get_section 2626 1_1_0 EXIST::FUNCTION: +CMS_RecipientInfo_kari_decrypt 2627 1_1_0 EXIST::FUNCTION:CMS +OBJ_add_sigid 2628 1_1_0 EXIST::FUNCTION: +d2i_SXNETID 2629 1_1_0 EXIST::FUNCTION: +CMS_get1_certs 2630 1_1_0 EXIST::FUNCTION:CMS +X509_CRL_check_suiteb 2631 1_1_0 EXIST::FUNCTION: +PKCS7_ENVELOPE_it 2632 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +PKCS7_ENVELOPE_it 2632 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +ASIdentifierChoice_it 2633 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:RFC3779 +ASIdentifierChoice_it 2633 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:RFC3779 +CMS_RecipientEncryptedKey_cert_cmp 2634 1_1_0 EXIST::FUNCTION:CMS +EVP_PKEY_CTX_get_app_data 2635 1_1_0 EXIST::FUNCTION: +EC_GROUP_clear_free 2636 1_1_0 EXIST::FUNCTION:EC +BN_get_rfc2409_prime_1024 2637 1_1_0 EXIST::FUNCTION: +CRYPTO_set_mem_functions 2638 1_1_0 EXIST::FUNCTION: +i2d_ASN1_VISIBLESTRING 2639 1_1_0 EXIST::FUNCTION: +d2i_PBKDF2PARAM 2640 1_1_0 EXIST::FUNCTION: +ERR_load_COMP_strings 2641 1_1_0 EXIST::FUNCTION:COMP +EVP_PKEY_meth_add0 2642 1_1_0 EXIST::FUNCTION: +EVP_rc4_40 2643 1_1_0 EXIST::FUNCTION:RC4 +RSA_bits 2645 1_1_0 EXIST::FUNCTION:RSA +ASN1_item_dup 2646 1_1_0 EXIST::FUNCTION: +GENERAL_NAMES_it 2647 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +GENERAL_NAMES_it 2647 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +X509_issuer_name_hash 2648 1_1_0 EXIST::FUNCTION: +TS_TST_INFO_get_nonce 2649 1_1_0 EXIST::FUNCTION:TS +MD4_Init 2650 1_1_0 EXIST::FUNCTION:MD4 +X509_EXTENSION_create_by_OBJ 2651 1_1_0 EXIST::FUNCTION: +EVP_aes_256_cbc_hmac_sha1 2652 1_1_0 EXIST::FUNCTION: +SCT_validate 2653 1_1_0 EXIST::FUNCTION:CT +EC_GROUP_dup 2654 1_1_0 EXIST::FUNCTION:EC +EVP_sha1 2655 1_1_0 EXIST::FUNCTION: +OPENSSL_sk_new 2656 1_1_0 EXIST::FUNCTION: +BN_dup 2657 1_1_0 EXIST::FUNCTION: +TS_MSG_IMPRINT_print_bio 2658 1_1_0 EXIST::FUNCTION:TS +CONF_module_set_usr_data 2659 1_1_0 EXIST::FUNCTION: +EC_KEY_generate_key 2660 1_1_0 EXIST::FUNCTION:EC +BIO_ctrl_get_write_guarantee 2661 1_1_0 EXIST::FUNCTION: +EVP_PKEY_assign 2662 1_1_0 EXIST::FUNCTION: +EVP_aes_128_ofb 2663 1_1_0 EXIST::FUNCTION: +CMS_data 2664 1_1_0 EXIST::FUNCTION:CMS +X509_load_cert_file 2665 1_1_0 EXIST::FUNCTION: +EC_GFp_nistp521_method 2667 1_1_0 EXIST::FUNCTION:EC,EC_NISTP_64_GCC_128 +ECDSA_SIG_free 2668 1_1_0 EXIST::FUNCTION:EC +d2i_PKCS12_BAGS 2669 1_1_0 EXIST::FUNCTION: +RSA_public_encrypt 2670 1_1_0 EXIST::FUNCTION:RSA +X509_CRL_get0_extensions 2671 1_1_0 EXIST::FUNCTION: +CMS_digest_verify 2672 1_1_0 EXIST::FUNCTION:CMS +ASN1_GENERALIZEDTIME_set 2673 1_1_0 EXIST::FUNCTION: +TS_VERIFY_CTX_set_imprint 2674 1_1_0 EXIST::FUNCTION:TS +BN_RECP_CTX_set 2675 1_1_0 EXIST::FUNCTION: +CRYPTO_secure_zalloc 2676 1_1_0 EXIST::FUNCTION: +i2d_EXTENDED_KEY_USAGE 2677 1_1_0 EXIST::FUNCTION: +PEM_write_bio_DSAparams 2678 1_1_0 EXIST::FUNCTION:DSA +X509_cmp_time 2679 1_1_0 EXIST::FUNCTION: +d2i_CMS_ReceiptRequest 2680 1_1_0 EXIST::FUNCTION:CMS +X509_CRL_INFO_it 2681 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +X509_CRL_INFO_it 2681 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +BUF_reverse 2682 1_1_0 EXIST::FUNCTION: +d2i_OCSP_SIGNATURE 2683 1_1_0 EXIST::FUNCTION:OCSP +X509_REQ_delete_attr 2684 1_1_0 EXIST::FUNCTION: +TS_RESP_CTX_set_signer_cert 2685 1_1_0 EXIST::FUNCTION:TS +X509V3_EXT_d2i 2686 1_1_0 EXIST::FUNCTION: +ASN1_GENERALSTRING_it 2687 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ASN1_GENERALSTRING_it 2687 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +POLICYQUALINFO_free 2688 1_1_0 EXIST::FUNCTION: +EC_KEY_set_group 2689 1_1_0 EXIST::FUNCTION:EC +OCSP_check_validity 2690 1_1_0 EXIST::FUNCTION:OCSP +PEM_write_ECPKParameters 2691 1_1_0 EXIST::FUNCTION:EC,STDIO +X509_VERIFY_PARAM_lookup 2692 1_1_0 EXIST::FUNCTION: +X509_LOOKUP_by_fingerprint 2693 1_1_0 EXIST::FUNCTION: +EVP_CIPHER_meth_free 2694 1_1_0 EXIST::FUNCTION: +PKCS7_RECIP_INFO_new 2695 1_1_0 EXIST::FUNCTION: +d2i_ECPrivateKey_fp 2696 1_1_0 EXIST::FUNCTION:EC,STDIO +TS_CONF_set_ordering 2697 1_1_0 EXIST::FUNCTION:TS +X509_CRL_get_ext 2698 1_1_0 EXIST::FUNCTION: +X509_CRL_get_ext_by_OBJ 2699 1_1_0 EXIST::FUNCTION: +OCSP_basic_add1_cert 2700 1_1_0 EXIST::FUNCTION:OCSP +ASN1_PRINTABLESTRING_new 2701 1_1_0 EXIST::FUNCTION: +i2d_PBEPARAM 2702 1_1_0 EXIST::FUNCTION: +NETSCAPE_SPKI_new 2703 1_1_0 EXIST::FUNCTION: +AES_options 2704 1_1_0 EXIST::FUNCTION: +POLICYINFO_free 2705 1_1_0 EXIST::FUNCTION: +PEM_read_bio_Parameters 2706 1_1_0 EXIST::FUNCTION: +BN_abs_is_word 2707 1_1_0 EXIST::FUNCTION: +BIO_set_callback_arg 2708 1_1_0 EXIST::FUNCTION: +CONF_modules_load_file 2709 1_1_0 EXIST::FUNCTION: +X509_trust_clear 2710 1_1_0 EXIST::FUNCTION: +EVP_CIPHER_CTX_test_flags 2711 1_1_0 EXIST::FUNCTION: +PKCS12_BAGS_free 2712 1_1_0 EXIST::FUNCTION: +PEM_X509_INFO_read 2713 1_1_0 EXIST::FUNCTION:STDIO +d2i_DSAPrivateKey 2714 1_1_0 EXIST::FUNCTION:DSA +i2d_PKCS8_PRIV_KEY_INFO_fp 2715 1_1_0 EXIST::FUNCTION:STDIO +TS_RESP_print_bio 2716 1_1_0 EXIST::FUNCTION:TS +X509_STORE_set_default_paths 2717 1_1_0 EXIST::FUNCTION: +d2i_TS_REQ 2718 1_1_0 EXIST::FUNCTION:TS +i2d_TS_TST_INFO_bio 2719 1_1_0 EXIST::FUNCTION:TS +CMS_sign_receipt 2720 1_1_0 EXIST::FUNCTION:CMS +ENGINE_set_RAND 2721 1_1_0 EXIST::FUNCTION:ENGINE +X509_REVOKED_get_ext_by_OBJ 2722 1_1_0 EXIST::FUNCTION: +SEED_decrypt 2723 1_1_0 EXIST::FUNCTION:SEED +PEM_write_PKCS8PrivateKey 2724 1_1_0 EXIST::FUNCTION:STDIO +ENGINE_new 2725 1_1_0 EXIST::FUNCTION:ENGINE +X509_check_issued 2726 1_1_0 EXIST::FUNCTION: +EVP_CIPHER_CTX_iv_length 2727 1_1_0 EXIST::FUNCTION: +DES_string_to_2keys 2728 1_1_0 EXIST::FUNCTION:DES +EVP_PKEY_copy_parameters 2729 1_1_0 EXIST::FUNCTION: +CMS_ContentInfo_print_ctx 2730 1_1_0 EXIST::FUNCTION:CMS +d2i_PKCS7_SIGNED 2731 1_1_0 EXIST::FUNCTION: +GENERAL_NAMES_free 2732 1_1_0 EXIST::FUNCTION: +SCT_get_timestamp 2733 1_1_0 EXIST::FUNCTION:CT +OCSP_SIGNATURE_it 2734 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:OCSP +OCSP_SIGNATURE_it 2734 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:OCSP +CMS_verify_receipt 2735 1_1_0 EXIST::FUNCTION:CMS +CRYPTO_THREAD_lock_new 2736 1_1_0 EXIST::FUNCTION: +BIO_get_ex_data 2737 1_1_0 EXIST::FUNCTION: +CMS_digest_create 2738 1_1_0 EXIST::FUNCTION:CMS +EC_KEY_METHOD_set_verify 2739 1_1_0 EXIST::FUNCTION:EC +PEM_read_RSAPublicKey 2740 1_1_0 EXIST::FUNCTION:RSA,STDIO +ENGINE_pkey_asn1_find_str 2741 1_1_0 EXIST::FUNCTION:ENGINE +ENGINE_get_load_privkey_function 2742 1_1_0 EXIST::FUNCTION:ENGINE +d2i_IPAddressRange 2743 1_1_0 EXIST::FUNCTION:RFC3779 +ERR_remove_state 2744 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_0_0 +X509_CRL_print_fp 2745 1_1_0 EXIST::FUNCTION:STDIO +TS_CONF_load_key 2746 1_1_0 EXIST::FUNCTION:TS +d2i_OCSP_REQINFO 2747 1_1_0 EXIST::FUNCTION:OCSP +d2i_X509_CINF 2748 1_1_0 EXIST::FUNCTION: +OCSP_REQUEST_get_ext_by_critical 2749 1_1_0 EXIST::FUNCTION:OCSP +X509_REQ_to_X509 2750 1_1_0 EXIST::FUNCTION: +EVP_aes_192_wrap_pad 2751 1_1_0 EXIST::FUNCTION: +PKCS7_SIGN_ENVELOPE_new 2752 1_1_0 EXIST::FUNCTION: +TS_REQ_get_policy_id 2753 1_1_0 EXIST::FUNCTION:TS +RC5_32_cbc_encrypt 2754 1_1_0 EXIST::FUNCTION:RC5 +BN_is_zero 2755 1_1_0 EXIST::FUNCTION: +CT_POLICY_EVAL_CTX_new 2756 1_1_0 EXIST::FUNCTION:CT +NETSCAPE_SPKI_it 2757 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +NETSCAPE_SPKI_it 2757 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +CRYPTO_THREAD_unlock 2758 1_1_0 EXIST::FUNCTION: +UI_method_set_writer 2759 1_1_0 EXIST::FUNCTION: +UI_dup_info_string 2760 1_1_0 EXIST::FUNCTION: +OPENSSL_init 2761 1_1_0 EXIST::FUNCTION: +TS_RESP_get_tst_info 2762 1_1_0 EXIST::FUNCTION:TS +X509_VERIFY_PARAM_get_depth 2763 1_1_0 EXIST::FUNCTION: +EVP_SealFinal 2764 1_1_0 EXIST::FUNCTION:RSA +BIO_set 2765 1_1_0 NOEXIST::FUNCTION: +CONF_imodule_set_flags 2766 1_1_0 EXIST::FUNCTION: +i2d_ASN1_SET_ANY 2767 1_1_0 EXIST::FUNCTION: +EVP_PKEY_decrypt 2768 1_1_0 EXIST::FUNCTION: +OCSP_RESPID_it 2769 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:OCSP +OCSP_RESPID_it 2769 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:OCSP +EVP_des_ede3_cbc 2770 1_1_0 EXIST::FUNCTION:DES +X509_up_ref 2771 1_1_0 EXIST::FUNCTION: +OBJ_NAME_do_all_sorted 2772 1_1_0 EXIST::FUNCTION: +ENGINE_unregister_DSA 2773 1_1_0 EXIST::FUNCTION:ENGINE +ASN1_bn_print 2774 1_1_0 EXIST::FUNCTION: +CMS_is_detached 2775 1_1_0 EXIST::FUNCTION:CMS +X509_REQ_INFO_it 2776 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +X509_REQ_INFO_it 2776 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +RSAPrivateKey_it 2777 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:RSA +RSAPrivateKey_it 2777 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:RSA +X509_NAME_ENTRY_free 2778 1_1_0 EXIST::FUNCTION: +BIO_new_fd 2779 1_1_0 EXIST::FUNCTION: +OPENSSL_sk_value 2781 1_1_0 EXIST::FUNCTION: +NCONF_get_section 2782 1_1_0 EXIST::FUNCTION: +PKCS12_MAC_DATA_it 2783 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +PKCS12_MAC_DATA_it 2783 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +X509_REQ_add1_attr_by_NID 2784 1_1_0 EXIST::FUNCTION: +ASN1_sign 2785 1_1_0 EXIST::FUNCTION: +CMS_RecipientInfo_encrypt 2786 1_1_0 EXIST::FUNCTION:CMS +X509_get_pubkey_parameters 2787 1_1_0 EXIST::FUNCTION: +PKCS12_setup_mac 2788 1_1_0 EXIST::FUNCTION: +PEM_read_bio_PKCS7 2789 1_1_0 EXIST::FUNCTION: +SHA512_Final 2790 1_1_0 EXIST::FUNCTION: +X509_VERIFY_PARAM_set1_host 2791 1_1_0 EXIST::FUNCTION: +OCSP_resp_find_status 2792 1_1_0 EXIST::FUNCTION:OCSP +d2i_ASN1_T61STRING 2793 1_1_0 EXIST::FUNCTION: +DES_pcbc_encrypt 2794 1_1_0 EXIST::FUNCTION:DES +EVP_PKEY_print_params 2795 1_1_0 EXIST::FUNCTION: +BN_get0_nist_prime_192 2796 1_1_0 EXIST::FUNCTION: +EVP_SealInit 2798 1_1_0 EXIST::FUNCTION:RSA +X509_REQ_get0_signature 2799 1_1_0 EXIST::FUNCTION: +PKEY_USAGE_PERIOD_free 2800 1_1_0 EXIST::FUNCTION: +EC_GROUP_set_point_conversion_form 2801 1_1_0 EXIST::FUNCTION:EC +CMS_dataFinal 2802 1_1_0 EXIST::FUNCTION:CMS +ASN1_TIME_it 2803 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ASN1_TIME_it 2803 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +ENGINE_get_static_state 2804 1_1_0 EXIST::FUNCTION:ENGINE +EC_KEY_set_asn1_flag 2805 1_1_0 EXIST::FUNCTION:EC +EC_GFp_mont_method 2806 1_1_0 EXIST::FUNCTION:EC +OPENSSL_asc2uni 2807 1_1_0 EXIST::FUNCTION: +TS_REQ_new 2808 1_1_0 EXIST::FUNCTION:TS +ENGINE_register_all_DH 2809 1_1_0 EXIST::FUNCTION:ENGINE +ERR_clear_error 2810 1_1_0 EXIST::FUNCTION: +EC_KEY_dup 2811 1_1_0 EXIST::FUNCTION:EC +X509_LOOKUP_init 2812 1_1_0 EXIST::FUNCTION: +i2b_PVK_bio 2813 1_1_0 EXIST::FUNCTION:DSA,RC4 +OCSP_ONEREQ_free 2814 1_1_0 EXIST::FUNCTION:OCSP +X509V3_EXT_print_fp 2815 1_1_0 EXIST::FUNCTION:STDIO +OBJ_bsearch_ex_ 2816 1_1_0 EXIST::FUNCTION: +DES_ofb64_encrypt 2817 1_1_0 EXIST::FUNCTION:DES +i2d_IPAddressOrRange 2818 1_1_0 EXIST::FUNCTION:RFC3779 +CRYPTO_secure_used 2819 1_1_0 EXIST::FUNCTION: +d2i_X509_CRL_INFO 2820 1_1_0 EXIST::FUNCTION: +X509_CRL_get_issuer 2821 1_1_0 EXIST::FUNCTION: +d2i_SCT_LIST 2822 1_1_0 EXIST::FUNCTION:CT +EC_GFp_nist_method 2823 1_1_0 EXIST::FUNCTION:EC +SCT_free 2824 1_1_0 EXIST::FUNCTION:CT +TS_TST_INFO_get_msg_imprint 2825 1_1_0 EXIST::FUNCTION:TS +X509v3_addr_add_range 2826 1_1_0 EXIST::FUNCTION:RFC3779 +PKCS12_get_friendlyname 2827 1_1_0 EXIST::FUNCTION: +X509_CRL_add_ext 2829 1_1_0 EXIST::FUNCTION: +X509_REQ_get_signature_nid 2830 1_1_0 EXIST::FUNCTION: +TS_TST_INFO_get_ext 2831 1_1_0 EXIST::FUNCTION:TS +i2d_OCSP_RESPID 2832 1_1_0 EXIST::FUNCTION:OCSP +EVP_camellia_256_cfb8 2833 1_1_0 EXIST::FUNCTION:CAMELLIA +EC_KEY_get0_public_key 2834 1_1_0 EXIST::FUNCTION:EC +SRP_Calc_x 2835 1_1_0 EXIST::FUNCTION:SRP +a2i_ASN1_ENUMERATED 2836 1_1_0 EXIST::FUNCTION: +CONF_module_get_usr_data 2837 1_1_0 EXIST::FUNCTION: +i2d_X509_NAME_ENTRY 2838 1_1_0 EXIST::FUNCTION: +SCT_LIST_free 2839 1_1_0 EXIST::FUNCTION:CT +PROXY_POLICY_new 2840 1_1_0 EXIST::FUNCTION: +X509_ALGOR_set_md 2841 1_1_0 EXIST::FUNCTION: +PKCS7_print_ctx 2842 1_1_0 EXIST::FUNCTION: +ASN1_UTF8STRING_new 2843 1_1_0 EXIST::FUNCTION: +EVP_des_cbc 2844 1_1_0 EXIST::FUNCTION:DES +i2v_ASN1_BIT_STRING 2845 1_1_0 EXIST::FUNCTION: +ASN1_TYPE_set1 2846 1_1_0 EXIST::FUNCTION: +d2i_X509_CRL_bio 2847 1_1_0 EXIST::FUNCTION: +PKCS12_SAFEBAG_get1_cert 2848 1_1_0 EXIST::FUNCTION: +ASN1_UNIVERSALSTRING_free 2849 1_1_0 EXIST::FUNCTION: +EC_KEY_precompute_mult 2850 1_1_0 EXIST::FUNCTION:EC +CRYPTO_mem_debug_realloc 2851 1_1_0 EXIST::FUNCTION:CRYPTO_MDEBUG +PKCS7_new 2852 1_1_0 EXIST::FUNCTION: +BASIC_CONSTRAINTS_it 2853 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +BASIC_CONSTRAINTS_it 2853 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +ASN1_generate_v3 2854 1_1_0 EXIST::FUNCTION: +PEM_write_bio_PrivateKey 2855 1_1_0 EXIST::FUNCTION: +ASN1_UTCTIME_check 2856 1_1_0 EXIST::FUNCTION: +ACCESS_DESCRIPTION_it 2857 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ACCESS_DESCRIPTION_it 2857 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +TS_MSG_IMPRINT_get_msg 2859 1_1_0 EXIST::FUNCTION:TS +PKCS8_add_keyusage 2860 1_1_0 EXIST::FUNCTION: +X509_EXTENSION_dup 2861 1_1_0 EXIST::FUNCTION: +EVP_PKEY_asn1_new 2862 1_1_0 EXIST::FUNCTION: +BIO_socket_nbio 2863 1_1_0 EXIST::FUNCTION:SOCK +EVP_CIPHER_set_asn1_iv 2864 1_1_0 EXIST::FUNCTION: +EC_GFp_nistp224_method 2865 1_1_0 EXIST::FUNCTION:EC,EC_NISTP_64_GCC_128 +BN_swap 2866 1_1_0 EXIST::FUNCTION: +d2i_ECParameters 2867 1_1_0 EXIST::FUNCTION:EC +X509_NAME_add_entry_by_OBJ 2868 1_1_0 EXIST::FUNCTION: +TS_TST_INFO_get_ext_count 2869 1_1_0 EXIST::FUNCTION:TS +i2d_OCSP_CERTID 2870 1_1_0 EXIST::FUNCTION:OCSP +BN_CTX_start 2871 1_1_0 EXIST::FUNCTION: +BN_print 2872 1_1_0 EXIST::FUNCTION: +EC_KEY_set_flags 2873 1_1_0 EXIST::FUNCTION:EC +EVP_PKEY_get0 2874 1_1_0 EXIST::FUNCTION: +ENGINE_set_default 2875 1_1_0 EXIST::FUNCTION:ENGINE +NCONF_get_number_e 2876 1_1_0 EXIST::FUNCTION: +OPENSSL_cleanse 2877 1_1_0 EXIST::FUNCTION: +SCT_set0_signature 2878 1_1_0 EXIST::FUNCTION:CT +X509_CRL_sign 2879 1_1_0 EXIST::FUNCTION: +X509_CINF_it 2880 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +X509_CINF_it 2880 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +TS_CONF_set_accuracy 2881 1_1_0 EXIST::FUNCTION:TS +DES_crypt 2882 1_1_0 EXIST::FUNCTION:DES +BN_BLINDING_create_param 2883 1_1_0 EXIST::FUNCTION: +OCSP_SERVICELOC_free 2884 1_1_0 EXIST::FUNCTION:OCSP +DIST_POINT_NAME_free 2885 1_1_0 EXIST::FUNCTION: +BIO_listen 2886 1_1_0 EXIST::FUNCTION:SOCK +BIO_ADDR_path_string 2887 1_1_0 EXIST::FUNCTION:SOCK +POLICY_CONSTRAINTS_it 2888 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +POLICY_CONSTRAINTS_it 2888 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +NCONF_free_data 2889 1_1_0 EXIST::FUNCTION: +BIO_asn1_set_prefix 2890 1_1_0 EXIST::FUNCTION: +PEM_SignUpdate 2891 1_1_0 EXIST::FUNCTION: +PEM_write_bio_EC_PUBKEY 2892 1_1_0 EXIST::FUNCTION:EC +CMS_add_simple_smimecap 2893 1_1_0 EXIST::FUNCTION:CMS +IPAddressChoice_free 2894 1_1_0 EXIST::FUNCTION:RFC3779 +d2i_X509_AUX 2895 1_1_0 EXIST::FUNCTION: +X509_get_default_cert_area 2896 1_1_0 EXIST::FUNCTION: +ERR_load_DSO_strings 2897 1_1_0 EXIST::FUNCTION: +ASIdentifiers_it 2898 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:RFC3779 +ASIdentifiers_it 2898 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:RFC3779 +BN_mod_lshift 2899 1_1_0 EXIST::FUNCTION: +ENGINE_get_last 2900 1_1_0 EXIST::FUNCTION:ENGINE +EVP_PKEY_encrypt_init 2901 1_1_0 EXIST::FUNCTION: +i2d_RSAPrivateKey_fp 2902 1_1_0 EXIST::FUNCTION:RSA,STDIO +X509_REQ_print 2903 1_1_0 EXIST::FUNCTION: +RSA_size 2904 1_1_0 EXIST::FUNCTION:RSA +EVP_CIPHER_CTX_iv_noconst 2905 1_1_0 EXIST::FUNCTION: +DH_set_default_method 2906 1_1_0 EXIST::FUNCTION:DH +X509_ALGOR_new 2907 1_1_0 EXIST::FUNCTION: +EVP_aes_192_ofb 2908 1_1_0 EXIST::FUNCTION: +EVP_des_ede3_cfb1 2909 1_1_0 EXIST::FUNCTION:DES +TS_REQ_to_TS_VERIFY_CTX 2910 1_1_0 EXIST::FUNCTION:TS +d2i_PBEPARAM 2911 1_1_0 EXIST::FUNCTION: +BN_get0_nist_prime_521 2912 1_1_0 EXIST::FUNCTION: +OCSP_ONEREQ_get_ext_by_NID 2913 1_1_0 EXIST::FUNCTION:OCSP +X509_PUBKEY_get0 2914 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_get0_parent_ctx 2915 1_1_0 EXIST::FUNCTION: +EC_GROUP_set_seed 2916 1_1_0 EXIST::FUNCTION:EC +X509_STORE_CTX_free 2917 1_1_0 EXIST::FUNCTION: +AUTHORITY_KEYID_it 2918 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +AUTHORITY_KEYID_it 2918 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +X509V3_get_value_int 2919 1_1_0 EXIST::FUNCTION: +ASN1_UTCTIME_set_string 2920 1_1_0 EXIST::FUNCTION: +RC5_32_decrypt 2921 1_1_0 EXIST::FUNCTION:RC5 +i2d_X509_REQ_INFO 2922 1_1_0 EXIST::FUNCTION: +EVP_des_cfb1 2923 1_1_0 EXIST::FUNCTION:DES +OBJ_NAME_cleanup 2924 1_1_0 EXIST::FUNCTION: +OCSP_BASICRESP_get1_ext_d2i 2925 1_1_0 EXIST::FUNCTION:OCSP +DES_cfb64_encrypt 2926 1_1_0 EXIST::FUNCTION:DES +CAST_cfb64_encrypt 2927 1_1_0 EXIST::FUNCTION:CAST +EVP_PKEY_asn1_set_param 2928 1_1_0 EXIST::FUNCTION: +BN_RECP_CTX_free 2929 1_1_0 EXIST::FUNCTION: +BN_with_flags 2930 1_1_0 EXIST::FUNCTION: +DSO_ctrl 2931 1_1_0 EXIST::FUNCTION: +EVP_MD_meth_get_final 2932 1_1_0 EXIST::FUNCTION: +ASN1_TYPE_get_octetstring 2933 1_1_0 EXIST::FUNCTION: +ENGINE_by_id 2934 1_1_0 EXIST::FUNCTION:ENGINE +d2i_PKCS7_SIGNER_INFO 2935 1_1_0 EXIST::FUNCTION: +EVP_aes_192_cbc 2936 1_1_0 EXIST::FUNCTION: +PKCS8_pkey_set0 2937 1_1_0 EXIST::FUNCTION: +X509_get1_email 2938 1_1_0 EXIST::FUNCTION: +EC_POINT_point2oct 2939 1_1_0 EXIST::FUNCTION:EC +EC_GROUP_get_curve_GFp 2940 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_2_0,EC +ASYNC_block_pause 2941 1_1_0 EXIST::FUNCTION: +OCSP_SINGLERESP_get_ext 2942 1_1_0 EXIST::FUNCTION:OCSP +CRYPTO_strdup 2943 1_1_0 EXIST::FUNCTION: +i2d_X509_CRL_bio 2945 1_1_0 EXIST::FUNCTION: +EVP_PKEY_asn1_set_item 2946 1_1_0 EXIST::FUNCTION: +CRYPTO_ccm128_encrypt 2947 1_1_0 EXIST::FUNCTION: +X509v3_addr_get_afi 2948 1_1_0 EXIST::FUNCTION:RFC3779 +X509_STORE_CTX_get0_param 2949 1_1_0 EXIST::FUNCTION: +EVP_add_alg_module 2950 1_1_0 EXIST::FUNCTION: +X509_check_purpose 2951 1_1_0 EXIST::FUNCTION: +OCSP_REQUEST_delete_ext 2952 1_1_0 EXIST::FUNCTION:OCSP +X509_PURPOSE_get_count 2953 1_1_0 EXIST::FUNCTION: +d2i_PKCS12_bio 2954 1_1_0 EXIST::FUNCTION: +ASN1_item_free 2955 1_1_0 EXIST::FUNCTION: +PKCS7_content_new 2956 1_1_0 EXIST::FUNCTION: +X509_keyid_get0 2957 1_1_0 EXIST::FUNCTION: +COMP_get_name 2958 1_1_0 EXIST::FUNCTION:COMP +EC_GROUP_new_curve_GF2m 2959 1_1_0 EXIST::FUNCTION:EC,EC2M +X509_SIG_free 2960 1_1_0 EXIST::FUNCTION: +PEM_ASN1_write 2961 1_1_0 EXIST::FUNCTION:STDIO +ENGINE_get_digest_engine 2962 1_1_0 EXIST::FUNCTION:ENGINE +BN_CTX_new 2963 1_1_0 EXIST::FUNCTION: +EC_curve_nid2nist 2964 1_1_0 EXIST::FUNCTION:EC +ENGINE_get_finish_function 2965 1_1_0 EXIST::FUNCTION:ENGINE +EC_POINT_add 2966 1_1_0 EXIST::FUNCTION:EC +EC_KEY_oct2key 2967 1_1_0 EXIST::FUNCTION:EC +SHA384_Init 2968 1_1_0 EXIST::FUNCTION: +ASN1_UNIVERSALSTRING_new 2969 1_1_0 EXIST::FUNCTION: +EVP_PKEY_print_private 2970 1_1_0 EXIST::FUNCTION: +ASN1_INTEGER_new 2971 1_1_0 EXIST::FUNCTION: +NAME_CONSTRAINTS_it 2972 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +NAME_CONSTRAINTS_it 2972 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +TS_REQ_get_cert_req 2973 1_1_0 EXIST::FUNCTION:TS +BIO_pop 2974 1_1_0 EXIST::FUNCTION: +SHA256_Final 2975 1_1_0 EXIST::FUNCTION: +EVP_PKEY_set1_DH 2976 1_1_0 EXIST::FUNCTION:DH +DH_get_ex_data 2977 1_1_0 EXIST::FUNCTION:DH +CRYPTO_secure_malloc 2978 1_1_0 EXIST::FUNCTION: +TS_RESP_get_status_info 2979 1_1_0 EXIST::FUNCTION:TS +HMAC_CTX_new 2980 1_1_0 EXIST::FUNCTION: +ENGINE_get_default_DH 2981 1_1_0 EXIST::FUNCTION:ENGINE +ECDSA_do_verify 2982 1_1_0 EXIST::FUNCTION:EC +DSO_flags 2983 1_1_0 EXIST::FUNCTION: +RAND_add 2984 1_1_0 EXIST::FUNCTION: +EVP_CIPHER_do_all_sorted 2985 1_1_0 EXIST::FUNCTION: +PKCS7_encrypt 2986 1_1_0 EXIST::FUNCTION: +i2d_DSA_SIG 2987 1_1_0 EXIST::FUNCTION:DSA +CMS_set_detached 2988 1_1_0 EXIST::FUNCTION:CMS +X509_REQ_get_attr_by_OBJ 2989 1_1_0 EXIST::FUNCTION: +i2d_ASRange 2990 1_1_0 EXIST::FUNCTION:RFC3779 +EC_GROUP_set_asn1_flag 2991 1_1_0 EXIST::FUNCTION:EC +EVP_PKEY_new 2992 1_1_0 EXIST::FUNCTION: +i2d_POLICYINFO 2993 1_1_0 EXIST::FUNCTION: +BN_get_flags 2994 1_1_0 EXIST::FUNCTION: +SHA384 2995 1_1_0 EXIST::FUNCTION: +NCONF_get_string 2996 1_1_0 EXIST::FUNCTION: +d2i_PROXY_CERT_INFO_EXTENSION 2997 1_1_0 EXIST::FUNCTION: +EC_POINT_point2buf 2998 1_1_0 EXIST::FUNCTION:EC +RSA_padding_add_PKCS1_OAEP_mgf1 2999 1_1_0 EXIST::FUNCTION:RSA +COMP_CTX_get_type 3000 1_1_0 EXIST::FUNCTION:COMP +TS_RESP_CTX_set_status_info 3001 1_1_0 EXIST::FUNCTION:TS +BIO_f_nbio_test 3002 1_1_0 EXIST::FUNCTION: +SEED_ofb128_encrypt 3003 1_1_0 EXIST::FUNCTION:SEED +d2i_RSAPrivateKey_bio 3004 1_1_0 EXIST::FUNCTION:RSA +DH_KDF_X9_42 3005 1_1_0 EXIST::FUNCTION:CMS,DH +EVP_PKEY_meth_set_signctx 3006 1_1_0 EXIST::FUNCTION: +X509_CRL_get_version 3007 1_1_0 EXIST::FUNCTION: +EVP_PKEY_meth_get0_info 3008 1_1_0 EXIST::FUNCTION: +PEM_read_bio_RSAPublicKey 3009 1_1_0 EXIST::FUNCTION:RSA +EVP_PKEY_asn1_set_private 3010 1_1_0 EXIST::FUNCTION: +EVP_PKEY_get0_RSA 3011 1_1_0 EXIST::FUNCTION:RSA +DES_ede3_cfb64_encrypt 3012 1_1_0 EXIST::FUNCTION:DES +POLICY_MAPPING_free 3014 1_1_0 EXIST::FUNCTION: +EVP_aes_128_gcm 3015 1_1_0 EXIST::FUNCTION: +BIO_dgram_non_fatal_error 3016 1_1_0 EXIST::FUNCTION:DGRAM +OCSP_request_is_signed 3017 1_1_0 EXIST::FUNCTION:OCSP +i2d_BASIC_CONSTRAINTS 3018 1_1_0 EXIST::FUNCTION: +EC_KEY_get_method 3019 1_1_0 EXIST::FUNCTION:EC +EC_POINT_bn2point 3021 1_1_0 EXIST::FUNCTION:EC +PBE2PARAM_it 3022 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +PBE2PARAM_it 3022 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +BN_rand 3023 1_1_0 EXIST::FUNCTION: +ASN1_TYPE_unpack_sequence 3024 1_1_0 EXIST::FUNCTION: +X509_CRL_sign_ctx 3025 1_1_0 EXIST::FUNCTION: +X509_STORE_add_crl 3026 1_1_0 EXIST::FUNCTION: +PEM_write_RSAPrivateKey 3027 1_1_0 EXIST::FUNCTION:RSA,STDIO +RC4_set_key 3028 1_1_0 EXIST::FUNCTION:RC4 +EVP_CIPHER_CTX_cipher 3029 1_1_0 EXIST::FUNCTION: +PEM_write_bio_PKCS8PrivateKey_nid 3030 1_1_0 EXIST::FUNCTION: +BN_MONT_CTX_new 3031 1_1_0 EXIST::FUNCTION: +CRYPTO_free_ex_index 3032 1_1_0 EXIST::FUNCTION: +ASYNC_WAIT_CTX_new 3033 1_1_0 EXIST::FUNCTION: +PKCS7_it 3034 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +PKCS7_it 3034 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +CMS_unsigned_get_attr_by_OBJ 3035 1_1_0 EXIST::FUNCTION:CMS +BN_clear 3036 1_1_0 EXIST::FUNCTION: +BIO_socket_ioctl 3037 1_1_0 EXIST::FUNCTION:SOCK +GENERAL_NAME_cmp 3038 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_set_purpose 3039 1_1_0 EXIST::FUNCTION: +X509_REVOKED_get_ext_d2i 3040 1_1_0 EXIST::FUNCTION: +X509V3_set_conf_lhash 3041 1_1_0 EXIST::FUNCTION: +PKCS7_ENC_CONTENT_it 3042 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +PKCS7_ENC_CONTENT_it 3042 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +PKCS12_item_pack_safebag 3043 1_1_0 EXIST::FUNCTION: +i2d_OCSP_RESPDATA 3044 1_1_0 EXIST::FUNCTION:OCSP +i2d_X509_PUBKEY 3045 1_1_0 EXIST::FUNCTION: +EVP_DecryptUpdate 3046 1_1_0 EXIST::FUNCTION: +CAST_cbc_encrypt 3047 1_1_0 EXIST::FUNCTION:CAST +BN_BLINDING_invert 3048 1_1_0 EXIST::FUNCTION: +SHA512_Update 3049 1_1_0 EXIST::FUNCTION: +ESS_ISSUER_SERIAL_new 3050 1_1_0 EXIST::FUNCTION:TS +PKCS12_SAFEBAG_get0_pkcs8 3051 1_1_0 EXIST::FUNCTION: +X509_get_ext_by_NID 3052 1_1_0 EXIST::FUNCTION: +d2i_IPAddressFamily 3053 1_1_0 EXIST::FUNCTION:RFC3779 +X509_check_private_key 3054 1_1_0 EXIST::FUNCTION: +GENERAL_NAME_get0_value 3055 1_1_0 EXIST::FUNCTION: +X509_check_akid 3056 1_1_0 EXIST::FUNCTION: +PKCS12_key_gen_asc 3057 1_1_0 EXIST::FUNCTION: +EVP_bf_ofb 3058 1_1_0 EXIST::FUNCTION:BF +AUTHORITY_KEYID_free 3059 1_1_0 EXIST::FUNCTION: +EVP_seed_ofb 3060 1_1_0 EXIST::FUNCTION:SEED +OBJ_NAME_get 3061 1_1_0 EXIST::FUNCTION: +ASN1_UTCTIME_set 3062 1_1_0 EXIST::FUNCTION: +X509_NAME_ENTRY_set_data 3063 1_1_0 EXIST::FUNCTION: +ASN1_PCTX_set_str_flags 3064 1_1_0 EXIST::FUNCTION: +i2a_ASN1_INTEGER 3065 1_1_0 EXIST::FUNCTION: +d2i_TS_RESP 3066 1_1_0 EXIST::FUNCTION:TS +EVP_des_ede_cfb64 3067 1_1_0 EXIST::FUNCTION:DES +d2i_RSAPrivateKey 3068 1_1_0 EXIST::FUNCTION:RSA +ERR_load_BN_strings 3069 1_1_0 EXIST::FUNCTION: +BF_encrypt 3070 1_1_0 EXIST::FUNCTION:BF +MD5 3071 1_1_0 EXIST::FUNCTION:MD5 +BN_GF2m_arr2poly 3072 1_1_0 EXIST::FUNCTION:EC2M +EVP_PKEY_meth_get_ctrl 3073 1_1_0 EXIST::FUNCTION: +i2d_X509_REQ_bio 3074 1_1_0 EXIST::FUNCTION: +X509_VERIFY_PARAM_set1_name 3075 1_1_0 EXIST::FUNCTION: +d2i_RSAPublicKey_bio 3076 1_1_0 EXIST::FUNCTION:RSA +X509_REQ_get_X509_PUBKEY 3077 1_1_0 EXIST::FUNCTION: +ENGINE_load_private_key 3078 1_1_0 EXIST::FUNCTION:ENGINE +GENERAL_NAMES_new 3079 1_1_0 EXIST::FUNCTION: +i2d_POLICYQUALINFO 3080 1_1_0 EXIST::FUNCTION: +EC_GF2m_simple_method 3081 1_1_0 EXIST::FUNCTION:EC,EC2M +RSA_get_method 3082 1_1_0 EXIST::FUNCTION:RSA +d2i_ASRange 3083 1_1_0 EXIST::FUNCTION:RFC3779 +CMS_ContentInfo_new 3084 1_1_0 EXIST::FUNCTION:CMS +OPENSSL_init_crypto 3085 1_1_0 EXIST::FUNCTION: +X509_TRUST_set 3086 1_1_0 EXIST::FUNCTION: +EVP_camellia_192_ecb 3087 1_1_0 EXIST::FUNCTION:CAMELLIA +d2i_X509_REVOKED 3088 1_1_0 EXIST::FUNCTION: +d2i_IPAddressOrRange 3089 1_1_0 EXIST::FUNCTION:RFC3779 +TS_TST_INFO_set_version 3090 1_1_0 EXIST::FUNCTION:TS +PKCS12_get0_mac 3091 1_1_0 EXIST::FUNCTION: +EVP_EncodeInit 3092 1_1_0 EXIST::FUNCTION: +X509_get0_trust_objects 3093 1_1_0 EXIST::FUNCTION: +d2i_ECPrivateKey_bio 3094 1_1_0 EXIST::FUNCTION:EC +BIO_s_secmem 3095 1_1_0 EXIST::FUNCTION: +ENGINE_get_default_EC 3096 1_1_0 EXIST::FUNCTION:ENGINE +TS_RESP_create_response 3097 1_1_0 EXIST::FUNCTION:TS +BIO_ADDR_rawaddress 3098 1_1_0 EXIST::FUNCTION:SOCK +PKCS7_ENCRYPT_new 3099 1_1_0 EXIST::FUNCTION: +i2d_PKCS8PrivateKey_fp 3100 1_1_0 EXIST::FUNCTION:STDIO +SRP_user_pwd_free 3101 1_1_0 EXIST::FUNCTION:SRP +Camellia_encrypt 3102 1_1_0 EXIST::FUNCTION:CAMELLIA +BIO_ADDR_hostname_string 3103 1_1_0 EXIST::FUNCTION:SOCK +USERNOTICE_new 3104 1_1_0 EXIST::FUNCTION: +POLICY_MAPPING_new 3105 1_1_0 EXIST::FUNCTION: +CRYPTO_gcm128_release 3106 1_1_0 EXIST::FUNCTION: +BIO_new 3107 1_1_0 EXIST::FUNCTION: +d2i_GENERAL_NAMES 3108 1_1_0 EXIST::FUNCTION: +PKCS7_SIGNER_INFO_new 3109 1_1_0 EXIST::FUNCTION: +PEM_read_DSA_PUBKEY 3110 1_1_0 EXIST::FUNCTION:DSA,STDIO +X509_get0_subject_key_id 3111 1_1_0 EXIST::FUNCTION: +i2s_ASN1_ENUMERATED 3112 1_1_0 EXIST::FUNCTION: +X509v3_get_ext_by_OBJ 3113 1_1_0 EXIST::FUNCTION: +OCSP_REQUEST_free 3114 1_1_0 EXIST::FUNCTION:OCSP +CRYPTO_ocb128_aad 3115 1_1_0 EXIST::FUNCTION:OCB +OPENSSL_sk_deep_copy 3116 1_1_0 EXIST::FUNCTION: +i2d_RSA_PSS_PARAMS 3117 1_1_0 EXIST::FUNCTION:RSA +EVP_aes_128_wrap_pad 3118 1_1_0 EXIST::FUNCTION: +ASN1_BIT_STRING_set 3119 1_1_0 EXIST::FUNCTION: +PKCS5_PBKDF2_HMAC_SHA1 3120 1_1_0 EXIST::FUNCTION: +RSA_padding_check_PKCS1_type_2 3121 1_1_0 EXIST::FUNCTION:RSA +EVP_des_ede3_ecb 3122 1_1_0 EXIST::FUNCTION:DES +CBIGNUM_it 3123 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +CBIGNUM_it 3123 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +BIO_new_NDEF 3124 1_1_0 EXIST::FUNCTION: +EVP_aes_256_wrap 3125 1_1_0 EXIST::FUNCTION: +ASN1_STRING_print 3126 1_1_0 EXIST::FUNCTION: +CRYPTO_THREAD_lock_free 3127 1_1_0 EXIST::FUNCTION: +TS_ACCURACY_get_seconds 3128 1_1_0 EXIST::FUNCTION:TS +BN_options 3129 1_1_0 EXIST::FUNCTION: +BIO_debug_callback 3130 1_1_0 EXIST::FUNCTION: +EVP_MD_meth_get_update 3131 1_1_0 EXIST::FUNCTION: +GENERAL_NAME_set0_othername 3132 1_1_0 EXIST::FUNCTION: +ASN1_BIT_STRING_set_bit 3133 1_1_0 EXIST::FUNCTION: +EVP_aes_256_ccm 3134 1_1_0 EXIST::FUNCTION: +EVP_PKEY_CTX_get0_pkey 3135 1_1_0 EXIST::FUNCTION: +CONF_load_fp 3136 1_1_0 EXIST::FUNCTION:STDIO +BN_to_ASN1_ENUMERATED 3137 1_1_0 EXIST::FUNCTION: +i2d_ISSUING_DIST_POINT 3138 1_1_0 EXIST::FUNCTION: +TXT_DB_free 3139 1_1_0 EXIST::FUNCTION: +ASN1_STRING_set 3140 1_1_0 EXIST::FUNCTION: +d2i_ESS_CERT_ID 3141 1_1_0 EXIST::FUNCTION:TS +EVP_PKEY_meth_set_derive 3142 1_1_0 EXIST::FUNCTION: +OPENSSL_LH_stats 3143 1_1_0 EXIST::FUNCTION:STDIO +NCONF_dump_fp 3144 1_1_0 EXIST::FUNCTION:STDIO +TS_STATUS_INFO_print_bio 3145 1_1_0 EXIST::FUNCTION:TS +OPENSSL_sk_dup 3146 1_1_0 EXIST::FUNCTION: +BF_cfb64_encrypt 3147 1_1_0 EXIST::FUNCTION:BF +ASN1_GENERALIZEDTIME_adj 3148 1_1_0 EXIST::FUNCTION: +ECDSA_verify 3149 1_1_0 EXIST::FUNCTION:EC +EVP_camellia_256_cfb128 3150 1_1_0 EXIST::FUNCTION:CAMELLIA +CMAC_Init 3151 1_1_0 EXIST::FUNCTION:CMAC +OCSP_basic_add1_status 3152 1_1_0 EXIST::FUNCTION:OCSP +X509_CRL_get0_by_cert 3153 1_1_0 EXIST::FUNCTION: +TS_TST_INFO_set_tsa 3154 1_1_0 EXIST::FUNCTION:TS +i2d_ASN1_GENERALIZEDTIME 3155 1_1_0 EXIST::FUNCTION: +EVP_PKEY_derive_set_peer 3156 1_1_0 EXIST::FUNCTION: +X509V3_EXT_CRL_add_conf 3157 1_1_0 EXIST::FUNCTION: +CRYPTO_ccm128_init 3158 1_1_0 EXIST::FUNCTION: +X509_VERIFY_PARAM_set_time 3159 1_1_0 EXIST::FUNCTION: +BN_reciprocal 3160 1_1_0 EXIST::FUNCTION: +d2i_PKCS7_SIGN_ENVELOPE 3161 1_1_0 EXIST::FUNCTION: +X509_NAME_digest 3162 1_1_0 EXIST::FUNCTION: +d2i_OCSP_SERVICELOC 3163 1_1_0 EXIST::FUNCTION:OCSP +GENERAL_NAME_print 3164 1_1_0 EXIST::FUNCTION: +CMS_ReceiptRequest_get0_values 3165 1_1_0 EXIST::FUNCTION:CMS +a2i_ASN1_INTEGER 3166 1_1_0 EXIST::FUNCTION: +OCSP_sendreq_bio 3167 1_1_0 EXIST::FUNCTION:OCSP +PKCS12_SAFEBAG_create_crl 3168 1_1_0 EXIST::FUNCTION: +d2i_X509_NAME 3169 1_1_0 EXIST::FUNCTION: +IDEA_cfb64_encrypt 3170 1_1_0 EXIST::FUNCTION:IDEA +BN_mod_sub 3171 1_1_0 EXIST::FUNCTION: +ASN1_NULL_new 3172 1_1_0 EXIST::FUNCTION: +HMAC_Init 3173 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0 +EVP_MD_CTX_update_fn 3174 1_1_0 EXIST::FUNCTION: +EVP_aes_128_ecb 3175 1_1_0 EXIST::FUNCTION: +i2d_PKCS7_bio_stream 3176 1_1_0 EXIST::FUNCTION: +i2a_ACCESS_DESCRIPTION 3178 1_1_0 EXIST::FUNCTION: +EC_KEY_set_enc_flags 3179 1_1_0 EXIST::FUNCTION:EC +i2d_PUBKEY_fp 3180 1_1_0 EXIST::FUNCTION:STDIO +b2i_PrivateKey_bio 3181 1_1_0 EXIST::FUNCTION:DSA +OCSP_REQUEST_add_ext 3182 1_1_0 EXIST::FUNCTION:OCSP +SXNET_add_id_INTEGER 3183 1_1_0 EXIST::FUNCTION: +CTLOG_get0_public_key 3184 1_1_0 EXIST::FUNCTION:CT +OCSP_REQUEST_get_ext_by_OBJ 3185 1_1_0 EXIST::FUNCTION:OCSP +X509_NAME_oneline 3186 1_1_0 EXIST::FUNCTION: +X509V3_set_nconf 3187 1_1_0 EXIST::FUNCTION: +RSAPrivateKey_dup 3188 1_1_0 EXIST::FUNCTION:RSA +BN_mod_add 3189 1_1_0 EXIST::FUNCTION: +EC_POINT_set_affine_coordinates_GFp 3190 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_2_0,EC +X509_get_default_cert_file 3191 1_1_0 EXIST::FUNCTION: +UI_method_set_flusher 3192 1_1_0 EXIST::FUNCTION: +RSA_new_method 3193 1_1_0 EXIST::FUNCTION:RSA +OCSP_request_verify 3194 1_1_0 EXIST::FUNCTION:OCSP +CRYPTO_THREAD_run_once 3195 1_1_0 EXIST::FUNCTION: +TS_REQ_print_bio 3196 1_1_0 EXIST::FUNCTION:TS +SCT_get_version 3197 1_1_0 EXIST::FUNCTION:CT +IDEA_set_encrypt_key 3198 1_1_0 EXIST::FUNCTION:IDEA +ENGINE_get_DH 3199 1_1_0 EXIST::FUNCTION:ENGINE +i2d_ASIdentifierChoice 3200 1_1_0 EXIST::FUNCTION:RFC3779 +SRP_Calc_A 3201 1_1_0 EXIST::FUNCTION:SRP +OCSP_BASICRESP_add_ext 3202 1_1_0 EXIST::FUNCTION:OCSP +EVP_idea_cfb64 3203 1_1_0 EXIST::FUNCTION:IDEA +PKCS12_newpass 3204 1_1_0 EXIST::FUNCTION: +EVP_aes_256_cbc_hmac_sha256 3205 1_1_0 EXIST::FUNCTION: +TS_ACCURACY_get_millis 3206 1_1_0 EXIST::FUNCTION:TS +X509_CRL_get_REVOKED 3207 1_1_0 EXIST::FUNCTION: +X509_issuer_name_hash_old 3208 1_1_0 EXIST::FUNCTION:MD5 +i2d_PKCS12_SAFEBAG 3209 1_1_0 EXIST::FUNCTION: +BN_rand_range 3210 1_1_0 EXIST::FUNCTION: +SMIME_write_ASN1 3211 1_1_0 EXIST::FUNCTION: +EVP_CIPHER_CTX_new 3212 1_1_0 EXIST::FUNCTION: +MD4_Final 3213 1_1_0 EXIST::FUNCTION:MD4 +EVP_PKEY_id 3214 1_1_0 EXIST::FUNCTION: +CMS_RecipientInfo_get0_pkey_ctx 3215 1_1_0 EXIST::FUNCTION:CMS +OCSP_REQINFO_free 3216 1_1_0 EXIST::FUNCTION:OCSP +AUTHORITY_KEYID_new 3217 1_1_0 EXIST::FUNCTION: +i2d_DIST_POINT_NAME 3218 1_1_0 EXIST::FUNCTION: +OpenSSL_version_num 3219 1_1_0 EXIST::FUNCTION: +OCSP_CERTID_free 3220 1_1_0 EXIST::FUNCTION:OCSP +BIO_hex_string 3221 1_1_0 EXIST::FUNCTION: +X509_REQ_sign_ctx 3222 1_1_0 EXIST::FUNCTION: +CRYPTO_ocb128_init 3223 1_1_0 EXIST::FUNCTION:OCB +EVP_PKEY_get1_EC_KEY 3224 1_1_0 EXIST::FUNCTION:EC +ASN1_PRINTABLESTRING_free 3225 1_1_0 EXIST::FUNCTION: +BIO_get_retry_reason 3226 1_1_0 EXIST::FUNCTION: +X509_NAME_print 3227 1_1_0 EXIST::FUNCTION: +ACCESS_DESCRIPTION_free 3228 1_1_0 EXIST::FUNCTION: +BN_nist_mod_384 3229 1_1_0 EXIST::FUNCTION: +i2d_EC_PUBKEY_fp 3230 1_1_0 EXIST::FUNCTION:EC,STDIO +ENGINE_set_default_pkey_meths 3231 1_1_0 EXIST::FUNCTION:ENGINE +DH_bits 3232 1_1_0 EXIST::FUNCTION:DH +i2d_X509_ALGORS 3233 1_1_0 EXIST::FUNCTION: +EVP_camellia_192_cfb1 3234 1_1_0 EXIST::FUNCTION:CAMELLIA +TS_RESP_CTX_add_failure_info 3235 1_1_0 EXIST::FUNCTION:TS +EVP_PBE_alg_add 3236 1_1_0 EXIST::FUNCTION: +ESS_CERT_ID_dup 3237 1_1_0 EXIST::FUNCTION:TS +CMS_SignerInfo_get0_signature 3238 1_1_0 EXIST::FUNCTION:CMS +EVP_PKEY_verify_recover 3239 1_1_0 EXIST::FUNCTION: +i2d_PUBKEY 3240 1_1_0 EXIST::FUNCTION: +ERR_load_EVP_strings 3241 1_1_0 EXIST::FUNCTION: +X509_ATTRIBUTE_set1_data 3242 1_1_0 EXIST::FUNCTION: +d2i_X509_fp 3243 1_1_0 EXIST::FUNCTION:STDIO +MD2_Init 3244 1_1_0 EXIST::FUNCTION:MD2 +ERR_get_error_line 3245 1_1_0 EXIST::FUNCTION: +X509_CRL_get_ext_by_NID 3246 1_1_0 EXIST::FUNCTION: +OPENSSL_INIT_free 3247 1_1_0 EXIST::FUNCTION: +PBE2PARAM_free 3248 1_1_0 EXIST::FUNCTION: +EVP_aes_192_ecb 3249 1_1_0 EXIST::FUNCTION: +ASN1_OCTET_STRING_new 3250 1_1_0 EXIST::FUNCTION: +CMS_set1_eContentType 3251 1_1_0 EXIST::FUNCTION:CMS +EVP_des_ede3_wrap 3252 1_1_0 EXIST::FUNCTION:DES +GENERAL_SUBTREE_it 3253 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +GENERAL_SUBTREE_it 3253 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +EVP_read_pw_string_min 3254 1_1_0 EXIST::FUNCTION: +X509_set1_notBefore 3255 1_1_0 EXIST::FUNCTION: +MD4 3256 1_1_0 EXIST::FUNCTION:MD4 +EVP_PKEY_CTX_dup 3257 1_1_0 EXIST::FUNCTION: +ENGINE_setup_bsd_cryptodev 3258 1_1_0 EXIST:__FreeBSD__:FUNCTION:DEPRECATEDIN_1_1_0,ENGINE +PEM_read_bio_DHparams 3259 1_1_0 EXIST::FUNCTION:DH +CMS_SharedInfo_encode 3260 1_1_0 EXIST::FUNCTION:CMS +ASN1_OBJECT_create 3261 1_1_0 EXIST::FUNCTION: +i2d_ECParameters 3262 1_1_0 EXIST::FUNCTION:EC +BN_GF2m_mod_arr 3263 1_1_0 EXIST::FUNCTION:EC2M +ENGINE_set_finish_function 3264 1_1_0 EXIST::FUNCTION:ENGINE +d2i_ASN1_OCTET_STRING 3265 1_1_0 EXIST::FUNCTION: +ENGINE_set_load_pubkey_function 3266 1_1_0 EXIST::FUNCTION:ENGINE +BIO_vprintf 3267 1_1_0 EXIST::FUNCTION: +CMS_RecipientInfo_decrypt 3268 1_1_0 EXIST::FUNCTION:CMS +RSA_generate_key 3269 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_0_9_8,RSA +PKCS7_set0_type_other 3270 1_1_0 EXIST::FUNCTION: +OCSP_REQUEST_new 3271 1_1_0 EXIST::FUNCTION:OCSP +BIO_lookup 3272 1_1_0 EXIST::FUNCTION:SOCK +EC_GROUP_get0_cofactor 3273 1_1_0 EXIST::FUNCTION:EC +SCT_print 3275 1_1_0 EXIST::FUNCTION:CT +X509_PUBKEY_set 3276 1_1_0 EXIST::FUNCTION: +POLICY_CONSTRAINTS_free 3277 1_1_0 EXIST::FUNCTION: +EVP_aes_256_cfb8 3278 1_1_0 EXIST::FUNCTION: +d2i_DSA_PUBKEY_bio 3279 1_1_0 EXIST::FUNCTION:DSA +X509_NAME_get_text_by_OBJ 3280 1_1_0 EXIST::FUNCTION: +RSA_padding_check_none 3281 1_1_0 EXIST::FUNCTION:RSA +CRYPTO_set_mem_debug 3282 1_1_0 EXIST::FUNCTION: +TS_VERIFY_CTX_init 3283 1_1_0 EXIST::FUNCTION:TS +OCSP_cert_id_new 3284 1_1_0 EXIST::FUNCTION:OCSP +GENERAL_SUBTREE_new 3285 1_1_0 EXIST::FUNCTION: +OPENSSL_sk_push 3286 1_1_0 EXIST::FUNCTION: +X509_LOOKUP_ctrl 3287 1_1_0 EXIST::FUNCTION: +SRP_check_known_gN_param 3288 1_1_0 EXIST::FUNCTION:SRP +d2i_DIST_POINT 3289 1_1_0 EXIST::FUNCTION: +EVP_PKEY_CTX_free 3290 1_1_0 EXIST::FUNCTION: +PBEPARAM_free 3291 1_1_0 EXIST::FUNCTION: +NETSCAPE_SPKI_set_pubkey 3292 1_1_0 EXIST::FUNCTION: +EVP_sha512 3293 1_1_0 EXIST::FUNCTION: +X509_CRL_match 3294 1_1_0 EXIST::FUNCTION: +i2s_ASN1_IA5STRING 3295 1_1_0 EXIST::FUNCTION: +EC_KEY_get_default_method 3296 1_1_0 EXIST::FUNCTION:EC +PKCS8_decrypt 3297 1_1_0 EXIST::FUNCTION: +EVP_PKEY_CTX_get_data 3298 1_1_0 EXIST::FUNCTION: +POLICYQUALINFO_it 3299 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +POLICYQUALINFO_it 3299 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +PKCS7_ISSUER_AND_SERIAL_free 3300 1_1_0 EXIST::FUNCTION: +DSA_SIG_free 3301 1_1_0 EXIST::FUNCTION:DSA +BIO_asn1_set_suffix 3302 1_1_0 EXIST::FUNCTION: +EVP_PKEY_set_type_str 3303 1_1_0 EXIST::FUNCTION: +i2d_X509_SIG 3304 1_1_0 EXIST::FUNCTION: +OPENSSL_LH_strhash 3305 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_set_trust 3306 1_1_0 EXIST::FUNCTION: +TS_ACCURACY_set_micros 3307 1_1_0 EXIST::FUNCTION:TS +EVP_DigestFinal_ex 3308 1_1_0 EXIST::FUNCTION: +X509_get0_pubkey 3309 1_1_0 EXIST::FUNCTION: +X509_check_ip 3310 1_1_0 EXIST::FUNCTION: +PKCS7_get_signed_attribute 3311 1_1_0 EXIST::FUNCTION: +ASN1_GENERALIZEDTIME_free 3312 1_1_0 EXIST::FUNCTION: +COMP_compress_block 3313 1_1_0 EXIST::FUNCTION:COMP +ASN1_STRING_dup 3314 1_1_0 EXIST::FUNCTION: +X509_LOOKUP_free 3315 1_1_0 EXIST::FUNCTION: +EC_GROUP_cmp 3316 1_1_0 EXIST::FUNCTION:EC +TS_TST_INFO_get_ext_by_critical 3317 1_1_0 EXIST::FUNCTION:TS +ECParameters_print_fp 3318 1_1_0 EXIST::FUNCTION:EC,STDIO +X509_REQ_sign 3319 1_1_0 EXIST::FUNCTION: +CRYPTO_xts128_encrypt 3320 1_1_0 EXIST::FUNCTION: +PEM_def_callback 3321 1_1_0 EXIST::FUNCTION: +PKCS12_add_friendlyname_uni 3322 1_1_0 EXIST::FUNCTION: +X509_policy_tree_level_count 3323 1_1_0 EXIST::FUNCTION: +OBJ_sn2nid 3324 1_1_0 EXIST::FUNCTION: +CTLOG_free 3325 1_1_0 EXIST::FUNCTION:CT +EVP_CIPHER_meth_dup 3326 1_1_0 EXIST::FUNCTION: +CMS_get1_crls 3327 1_1_0 EXIST::FUNCTION:CMS +X509_aux_print 3328 1_1_0 EXIST::FUNCTION: +OPENSSL_thread_stop 3330 1_1_0 EXIST::FUNCTION: +X509_policy_node_get0_parent 3331 1_1_0 EXIST::FUNCTION: +X509_PKEY_free 3332 1_1_0 EXIST::FUNCTION: +OCSP_CRLID_new 3333 1_1_0 EXIST::FUNCTION:OCSP +CONF_dump_bio 3334 1_1_0 EXIST::FUNCTION: +d2i_PKCS8PrivateKey_fp 3335 1_1_0 EXIST::FUNCTION:STDIO +RSA_setup_blinding 3336 1_1_0 EXIST::FUNCTION:RSA +ERR_peek_error_line 3337 1_1_0 EXIST::FUNCTION: +d2i_PKCS7 3338 1_1_0 EXIST::FUNCTION: +ERR_reason_error_string 3339 1_1_0 EXIST::FUNCTION: +ERR_remove_thread_state 3340 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0 +PEM_write_PrivateKey 3341 1_1_0 EXIST::FUNCTION:STDIO +EVP_PKEY_CTX_str2ctrl 3342 1_1_0 EXIST::FUNCTION: +CMS_SignerInfo_verify_content 3343 1_1_0 EXIST::FUNCTION:CMS +ASN1_INTEGER_get_int64 3344 1_1_0 EXIST::FUNCTION: +ASN1_item_sign 3345 1_1_0 EXIST::FUNCTION: +OCSP_SERVICELOC_new 3346 1_1_0 EXIST::FUNCTION:OCSP +ASN1_VISIBLESTRING_new 3347 1_1_0 EXIST::FUNCTION: +BN_set_flags 3348 1_1_0 EXIST::FUNCTION: +d2i_PrivateKey_bio 3349 1_1_0 EXIST::FUNCTION: +ASN1_SEQUENCE_ANY_it 3350 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ASN1_SEQUENCE_ANY_it 3350 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +ASN1_UTCTIME_adj 3351 1_1_0 EXIST::FUNCTION: +BN_mod_sqrt 3352 1_1_0 EXIST::FUNCTION: +OPENSSL_sk_is_sorted 3353 1_1_0 EXIST::FUNCTION: +OCSP_SIGNATURE_new 3354 1_1_0 EXIST::FUNCTION:OCSP +EVP_PKEY_meth_get_paramgen 3355 1_1_0 EXIST::FUNCTION: +X509_ATTRIBUTE_create_by_OBJ 3356 1_1_0 EXIST::FUNCTION: +RSA_generate_key_ex 3357 1_1_0 EXIST::FUNCTION:RSA +CMS_SignerInfo_get0_algs 3358 1_1_0 EXIST::FUNCTION:CMS +DIST_POINT_free 3359 1_1_0 EXIST::FUNCTION: +ESS_SIGNING_CERT_free 3360 1_1_0 EXIST::FUNCTION:TS +SCT_new_from_base64 3361 1_1_0 EXIST::FUNCTION:CT +OpenSSL_version 3362 1_1_0 EXIST::FUNCTION: +OCSP_SINGLERESP_get_ext_by_OBJ 3363 1_1_0 EXIST::FUNCTION:OCSP +ECDSA_SIG_get0 3364 1_1_0 EXIST::FUNCTION:EC +BN_set_word 3365 1_1_0 EXIST::FUNCTION: +ENGINE_set_flags 3366 1_1_0 EXIST::FUNCTION:ENGINE +DSA_OpenSSL 3367 1_1_0 EXIST::FUNCTION:DSA +CMS_RecipientInfo_kari_get0_alg 3368 1_1_0 EXIST::FUNCTION:CMS +PKCS7_ENVELOPE_new 3369 1_1_0 EXIST::FUNCTION: +EDIPARTYNAME_new 3370 1_1_0 EXIST::FUNCTION: +CMS_add1_cert 3371 1_1_0 EXIST::FUNCTION:CMS +DSO_convert_filename 3372 1_1_0 EXIST::FUNCTION: +RSA_padding_check_SSLv23 3373 1_1_0 EXIST::FUNCTION:RSA +CRYPTO_gcm128_finish 3374 1_1_0 EXIST::FUNCTION: +PKCS12_SAFEBAGS_it 3375 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +PKCS12_SAFEBAGS_it 3375 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +PKCS12_PBE_add 3376 1_1_0 EXIST::FUNCTION: +EC_KEY_set_public_key_affine_coordinates 3377 1_1_0 EXIST::FUNCTION:EC +EVP_EncryptInit_ex 3378 1_1_0 EXIST::FUNCTION: +ENGINE_add 3379 1_1_0 EXIST::FUNCTION:ENGINE +OPENSSL_LH_error 3380 1_1_0 EXIST::FUNCTION: +PKCS7_DIGEST_it 3381 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +PKCS7_DIGEST_it 3381 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +X509_CINF_new 3382 1_1_0 EXIST::FUNCTION: +EVP_PKEY_keygen_init 3383 1_1_0 EXIST::FUNCTION: +EVP_aes_192_ocb 3384 1_1_0 EXIST::FUNCTION:OCB +EVP_camellia_256_cfb1 3385 1_1_0 EXIST::FUNCTION:CAMELLIA +CRYPTO_secure_actual_size 3387 1_1_0 EXIST::FUNCTION: +COMP_CTX_free 3388 1_1_0 EXIST::FUNCTION:COMP +i2d_PBE2PARAM 3389 1_1_0 EXIST::FUNCTION: +EC_POINT_make_affine 3390 1_1_0 EXIST::FUNCTION:EC +DSA_generate_parameters 3391 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_0_9_8,DSA +ASN1_BIT_STRING_num_asc 3392 1_1_0 EXIST::FUNCTION: +X509_INFO_free 3394 1_1_0 EXIST::FUNCTION: +d2i_PKCS8_PRIV_KEY_INFO_fp 3395 1_1_0 EXIST::FUNCTION:STDIO +X509_OBJECT_retrieve_match 3396 1_1_0 EXIST::FUNCTION: +EVP_aes_128_ctr 3397 1_1_0 EXIST::FUNCTION: +EVP_PBE_find 3398 1_1_0 EXIST::FUNCTION: +SHA512_Transform 3399 1_1_0 EXIST::FUNCTION: +ERR_add_error_vdata 3400 1_1_0 EXIST::FUNCTION: +OCSP_REQUEST_get_ext 3401 1_1_0 EXIST::FUNCTION:OCSP +NETSCAPE_SPKAC_new 3402 1_1_0 EXIST::FUNCTION: +EVP_PKEY_meth_get_verify 3403 1_1_0 EXIST::FUNCTION: +CRYPTO_128_wrap 3404 1_1_0 EXIST::FUNCTION: +X509_STORE_set_lookup_crls 3405 1_1_0 EXIST::FUNCTION: +EVP_CIPHER_meth_get_ctrl 3406 1_1_0 EXIST::FUNCTION: +OCSP_REQ_CTX_set1_req 3407 1_1_0 EXIST::FUNCTION:OCSP +CONF_imodule_get_usr_data 3408 1_1_0 EXIST::FUNCTION: +CRYPTO_new_ex_data 3409 1_1_0 EXIST::FUNCTION: +PEM_read_PKCS8_PRIV_KEY_INFO 3410 1_1_0 EXIST::FUNCTION:STDIO +TS_VERIFY_CTX_new 3411 1_1_0 EXIST::FUNCTION:TS +BUF_MEM_new_ex 3412 1_1_0 EXIST::FUNCTION: +RSA_padding_add_X931 3413 1_1_0 EXIST::FUNCTION:RSA +BN_get0_nist_prime_256 3414 1_1_0 EXIST::FUNCTION: +CRYPTO_memcmp 3415 1_1_0 EXIST::FUNCTION: +DH_check_pub_key 3416 1_1_0 EXIST::FUNCTION:DH +ASN1_mbstring_copy 3417 1_1_0 EXIST::FUNCTION: +PKCS7_set_type 3418 1_1_0 EXIST::FUNCTION: +BIO_gets 3419 1_1_0 EXIST::FUNCTION: +RSA_padding_check_PKCS1_type_1 3420 1_1_0 EXIST::FUNCTION:RSA +UI_ctrl 3421 1_1_0 EXIST::FUNCTION: +i2d_X509_REQ_fp 3422 1_1_0 EXIST::FUNCTION:STDIO +BN_BLINDING_convert_ex 3423 1_1_0 EXIST::FUNCTION: +ASN1_GENERALIZEDTIME_print 3424 1_1_0 EXIST::FUNCTION: +BIO_s_null 3425 1_1_0 EXIST::FUNCTION: +PEM_ASN1_read 3426 1_1_0 EXIST::FUNCTION:STDIO +SCT_get_log_entry_type 3427 1_1_0 EXIST::FUNCTION:CT +EVP_CIPHER_meth_get_init 3428 1_1_0 EXIST::FUNCTION: +X509_ALGOR_free 3429 1_1_0 EXIST::FUNCTION: +OCSP_SINGLERESP_get_ext_count 3430 1_1_0 EXIST::FUNCTION:OCSP +EC_POINT_free 3431 1_1_0 EXIST::FUNCTION:EC +EVP_OpenFinal 3432 1_1_0 EXIST::FUNCTION:RSA +RAND_egd_bytes 3433 1_1_0 EXIST::FUNCTION:EGD +UI_method_get_writer 3434 1_1_0 EXIST::FUNCTION: +BN_secure_new 3435 1_1_0 EXIST::FUNCTION: +SHA1_Update 3437 1_1_0 EXIST::FUNCTION: +BIO_s_connect 3438 1_1_0 EXIST::FUNCTION:SOCK +EVP_MD_meth_get_init 3439 1_1_0 EXIST::FUNCTION: +ASN1_BIT_STRING_free 3440 1_1_0 EXIST::FUNCTION: +i2d_PROXY_CERT_INFO_EXTENSION 3441 1_1_0 EXIST::FUNCTION: +ASN1_IA5STRING_new 3442 1_1_0 EXIST::FUNCTION: +X509_CRL_up_ref 3443 1_1_0 EXIST::FUNCTION: +EVP_EncodeFinal 3444 1_1_0 EXIST::FUNCTION: +X509_set_ex_data 3445 1_1_0 EXIST::FUNCTION: +ERR_get_next_error_library 3446 1_1_0 EXIST::FUNCTION: +OCSP_RESPONSE_print 3447 1_1_0 EXIST::FUNCTION:OCSP +BN_get_rfc3526_prime_2048 3448 1_1_0 EXIST::FUNCTION: +BIO_new_bio_pair 3449 1_1_0 EXIST::FUNCTION: +EC_GFp_nistp256_method 3450 1_1_0 EXIST::FUNCTION:EC,EC_NISTP_64_GCC_128 +BIO_method_type 3451 1_1_0 EXIST::FUNCTION: +ECPKParameters_print 3452 1_1_0 EXIST::FUNCTION:EC +EVP_rc4 3453 1_1_0 EXIST::FUNCTION:RC4 +CMS_data_create 3454 1_1_0 EXIST::FUNCTION:CMS +EC_POINT_point2bn 3455 1_1_0 EXIST::FUNCTION:EC +CMS_unsigned_get0_data_by_OBJ 3456 1_1_0 EXIST::FUNCTION:CMS +ASN1_OCTET_STRING_cmp 3457 1_1_0 EXIST::FUNCTION: +X509_NAME_print_ex 3458 1_1_0 EXIST::FUNCTION: +ASN1_parse 3459 1_1_0 EXIST::FUNCTION: +EC_KEY_priv2oct 3460 1_1_0 EXIST::FUNCTION:EC +PKCS7_simple_smimecap 3461 1_1_0 EXIST::FUNCTION: +ASN1_TYPE_set_int_octetstring 3462 1_1_0 EXIST::FUNCTION: +BIO_number_written 3463 1_1_0 EXIST::FUNCTION: +TS_TST_INFO_set_msg_imprint 3464 1_1_0 EXIST::FUNCTION:TS +CRYPTO_get_ex_data 3465 1_1_0 EXIST::FUNCTION: +X509_PURPOSE_get0_sname 3466 1_1_0 EXIST::FUNCTION: +RSA_verify_PKCS1_PSS 3467 1_1_0 EXIST::FUNCTION:RSA +HMAC_CTX_reset 3468 1_1_0 EXIST::FUNCTION: +EVP_PKEY_meth_set_init 3469 1_1_0 EXIST::FUNCTION: +X509_REQ_extension_nid 3470 1_1_0 EXIST::FUNCTION: +ENGINE_up_ref 3471 1_1_0 EXIST::FUNCTION:ENGINE +BN_BLINDING_invert_ex 3472 1_1_0 EXIST::FUNCTION: +RIPEMD160_Init 3473 1_1_0 EXIST::FUNCTION:RMD160 +ASYNC_WAIT_CTX_get_changed_fds 3474 1_1_0 EXIST::FUNCTION: +EVP_PKEY_save_parameters 3475 1_1_0 EXIST::FUNCTION: +SCT_set_source 3476 1_1_0 EXIST::FUNCTION:CT +DES_set_odd_parity 3477 1_1_0 EXIST::FUNCTION:DES +CMAC_CTX_free 3478 1_1_0 EXIST::FUNCTION:CMAC +d2i_ESS_ISSUER_SERIAL 3479 1_1_0 EXIST::FUNCTION:TS +HMAC_CTX_set_flags 3480 1_1_0 EXIST::FUNCTION: +d2i_PKCS8_bio 3481 1_1_0 EXIST::FUNCTION: +OCSP_ONEREQ_get_ext_count 3482 1_1_0 EXIST::FUNCTION:OCSP +PEM_read_bio_PKCS8_PRIV_KEY_INFO 3483 1_1_0 EXIST::FUNCTION: +i2d_OCSP_BASICRESP 3484 1_1_0 EXIST::FUNCTION:OCSP +CMAC_Final 3485 1_1_0 EXIST::FUNCTION:CMAC +X509V3_EXT_add_alias 3486 1_1_0 EXIST::FUNCTION: +BN_get_params 3487 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_0_9_8 +PKCS5_pbkdf2_set 3488 1_1_0 EXIST::FUNCTION: +d2i_PKCS8PrivateKey_bio 3489 1_1_0 EXIST::FUNCTION: +ASN1_ENUMERATED_new 3490 1_1_0 EXIST::FUNCTION: +ENGINE_register_digests 3491 1_1_0 EXIST::FUNCTION:ENGINE +X509_NAME_get_text_by_NID 3492 1_1_0 EXIST::FUNCTION: +SMIME_read_ASN1 3493 1_1_0 EXIST::FUNCTION: +X509_REQ_set_subject_name 3494 1_1_0 EXIST::FUNCTION: +BN_sub_word 3495 1_1_0 EXIST::FUNCTION: +DSO_load 3496 1_1_0 EXIST::FUNCTION: +BN_mod_exp 3497 1_1_0 EXIST::FUNCTION: +X509_get_signature_type 3498 1_1_0 EXIST::FUNCTION: +BIO_ptr_ctrl 3499 1_1_0 EXIST::FUNCTION: +EVP_rc4_hmac_md5 3500 1_1_0 EXIST::FUNCTION:MD5,RC4 +OPENSSL_strlcat 3501 1_1_0 EXIST::FUNCTION: +X509_VERIFY_PARAM_new 3502 1_1_0 EXIST::FUNCTION: +BIO_ADDR_rawport 3503 1_1_0 EXIST::FUNCTION:SOCK +BUF_MEM_grow_clean 3504 1_1_0 EXIST::FUNCTION: +X509_NAME_print_ex_fp 3505 1_1_0 EXIST::FUNCTION:STDIO +X509_check_host 3506 1_1_0 EXIST::FUNCTION: +PEM_read_ECPKParameters 3507 1_1_0 EXIST::FUNCTION:EC,STDIO +X509_ATTRIBUTE_get0_data 3508 1_1_0 EXIST::FUNCTION: +CMS_add1_signer 3509 1_1_0 EXIST::FUNCTION:CMS +BN_pseudo_rand 3510 1_1_0 EXIST::FUNCTION: +d2i_DIRECTORYSTRING 3511 1_1_0 EXIST::FUNCTION: +d2i_ASN1_PRINTABLE 3512 1_1_0 EXIST::FUNCTION: +EVP_PKEY_add1_attr_by_NID 3513 1_1_0 EXIST::FUNCTION: +i2d_PKCS8_PRIV_KEY_INFO_bio 3514 1_1_0 EXIST::FUNCTION: +X509_NAME_get_index_by_NID 3515 1_1_0 EXIST::FUNCTION: +ENGINE_get_first 3516 1_1_0 EXIST::FUNCTION:ENGINE +CERTIFICATEPOLICIES_it 3517 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +CERTIFICATEPOLICIES_it 3517 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +EVP_MD_CTX_ctrl 3518 1_1_0 EXIST::FUNCTION: +PKCS7_final 3519 1_1_0 EXIST::FUNCTION: +EVP_PKEY_size 3520 1_1_0 EXIST::FUNCTION: +EVP_DecryptFinal_ex 3521 1_1_0 EXIST::FUNCTION: +SCT_get_signature_nid 3522 1_1_0 EXIST::FUNCTION:CT +PROXY_CERT_INFO_EXTENSION_new 3523 1_1_0 EXIST::FUNCTION: +EVP_bf_cbc 3524 1_1_0 EXIST::FUNCTION:BF +DSA_do_verify 3525 1_1_0 EXIST::FUNCTION:DSA +EC_GROUP_get_seed_len 3526 1_1_0 EXIST::FUNCTION:EC +EC_POINT_set_affine_coordinates_GF2m 3527 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_2_0,EC,EC2M +TS_REQ_set_policy_id 3528 1_1_0 EXIST::FUNCTION:TS +BIO_callback_ctrl 3529 1_1_0 EXIST::FUNCTION: +v2i_GENERAL_NAME 3530 1_1_0 EXIST::FUNCTION: +ERR_print_errors_cb 3531 1_1_0 EXIST::FUNCTION: +ENGINE_set_default_string 3532 1_1_0 EXIST::FUNCTION:ENGINE +BIO_number_read 3533 1_1_0 EXIST::FUNCTION: +CRYPTO_zalloc 3534 1_1_0 EXIST::FUNCTION: +EVP_PKEY_cmp_parameters 3535 1_1_0 EXIST::FUNCTION: +EVP_PKEY_CTX_new_id 3537 1_1_0 EXIST::FUNCTION: +TLS_FEATURE_free 3538 1_1_0 EXIST::FUNCTION: +d2i_BASIC_CONSTRAINTS 3539 1_1_0 EXIST::FUNCTION: +X509_CERT_AUX_new 3540 1_1_0 EXIST::FUNCTION: +ENGINE_register_pkey_asn1_meths 3541 1_1_0 EXIST::FUNCTION:ENGINE +CRYPTO_ocb128_tag 3542 1_1_0 EXIST::FUNCTION:OCB +ERR_load_OBJ_strings 3544 1_1_0 EXIST::FUNCTION: +BIO_ctrl_get_read_request 3545 1_1_0 EXIST::FUNCTION: +BN_from_montgomery 3546 1_1_0 EXIST::FUNCTION: +DSO_new 3547 1_1_0 EXIST::FUNCTION: +AES_ecb_encrypt 3548 1_1_0 EXIST::FUNCTION: +BN_dec2bn 3549 1_1_0 EXIST::FUNCTION: +CMS_decrypt 3550 1_1_0 EXIST::FUNCTION:CMS +BN_mpi2bn 3551 1_1_0 EXIST::FUNCTION: +EVP_aes_128_cfb128 3552 1_1_0 EXIST::FUNCTION: +RC5_32_ecb_encrypt 3554 1_1_0 EXIST::FUNCTION:RC5 +EVP_CIPHER_meth_new 3555 1_1_0 EXIST::FUNCTION: +i2d_RSA_OAEP_PARAMS 3556 1_1_0 EXIST::FUNCTION:RSA +SXNET_get_id_ulong 3557 1_1_0 EXIST::FUNCTION: +BIO_get_callback_arg 3558 1_1_0 EXIST::FUNCTION: +ENGINE_register_RSA 3559 1_1_0 EXIST::FUNCTION:ENGINE +i2v_GENERAL_NAMES 3560 1_1_0 EXIST::FUNCTION: +PKCS7_decrypt 3562 1_1_0 EXIST::FUNCTION: +X509_STORE_set1_param 3563 1_1_0 EXIST::FUNCTION: +RAND_file_name 3564 1_1_0 EXIST::FUNCTION: +EVP_CipherInit_ex 3566 1_1_0 EXIST::FUNCTION: +BIO_dgram_sctp_notification_cb 3567 1_1_0 EXIST::FUNCTION:DGRAM,SCTP +ERR_load_RAND_strings 3568 1_1_0 EXIST::FUNCTION: +X509_ATTRIBUTE_it 3569 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +X509_ATTRIBUTE_it 3569 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +X509_ALGOR_it 3570 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +X509_ALGOR_it 3570 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +OCSP_CRLID_free 3571 1_1_0 EXIST::FUNCTION:OCSP +CRYPTO_ccm128_aad 3572 1_1_0 EXIST::FUNCTION: +IPAddressFamily_new 3573 1_1_0 EXIST::FUNCTION:RFC3779 +d2i_TS_ACCURACY 3574 1_1_0 EXIST::FUNCTION:TS +X509_load_crl_file 3575 1_1_0 EXIST::FUNCTION: +SXNET_add_id_ulong 3576 1_1_0 EXIST::FUNCTION: +EVP_camellia_256_cbc 3577 1_1_0 EXIST::FUNCTION:CAMELLIA +i2d_PROXY_POLICY 3578 1_1_0 EXIST::FUNCTION: +X509_subject_name_hash_old 3579 1_1_0 EXIST::FUNCTION:MD5 +PEM_read_bio_DSA_PUBKEY 3580 1_1_0 EXIST::FUNCTION:DSA +OCSP_cert_to_id 3581 1_1_0 EXIST::FUNCTION:OCSP +PEM_write_DSAparams 3582 1_1_0 EXIST::FUNCTION:DSA,STDIO +ASN1_TIME_to_generalizedtime 3583 1_1_0 EXIST::FUNCTION: +X509_CRL_get_ext_by_critical 3584 1_1_0 EXIST::FUNCTION: +ASN1_STRING_type 3585 1_1_0 EXIST::FUNCTION: +X509_REQ_add1_attr_by_txt 3586 1_1_0 EXIST::FUNCTION: +PEM_write_RSAPublicKey 3587 1_1_0 EXIST::FUNCTION:RSA,STDIO +EVP_MD_meth_dup 3588 1_1_0 EXIST::FUNCTION: +ENGINE_unregister_ciphers 3589 1_1_0 EXIST::FUNCTION:ENGINE +X509_issuer_and_serial_cmp 3590 1_1_0 EXIST::FUNCTION: +OCSP_response_create 3591 1_1_0 EXIST::FUNCTION:OCSP +SHA224 3592 1_1_0 EXIST::FUNCTION: +MD2_options 3593 1_1_0 EXIST::FUNCTION:MD2 +X509_REQ_it 3595 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +X509_REQ_it 3595 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +RAND_bytes 3596 1_1_0 EXIST::FUNCTION: +PKCS7_free 3597 1_1_0 EXIST::FUNCTION: +X509_NAME_ENTRY_create_by_txt 3598 1_1_0 EXIST::FUNCTION: +DES_cbc_cksum 3599 1_1_0 EXIST::FUNCTION:DES +UI_free 3600 1_1_0 EXIST::FUNCTION: +BN_is_prime 3601 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_0_9_8 +CMS_get0_signers 3602 1_1_0 EXIST::FUNCTION:CMS +i2d_PrivateKey_fp 3603 1_1_0 EXIST::FUNCTION:STDIO +OTHERNAME_cmp 3604 1_1_0 EXIST::FUNCTION: +SMIME_write_PKCS7 3605 1_1_0 EXIST::FUNCTION: +EC_KEY_set_public_key 3606 1_1_0 EXIST::FUNCTION:EC +d2i_X509_EXTENSION 3607 1_1_0 EXIST::FUNCTION: +CMS_add1_recipient_cert 3608 1_1_0 EXIST::FUNCTION:CMS +CMS_RecipientInfo_kekri_get0_id 3609 1_1_0 EXIST::FUNCTION:CMS +BN_mod_word 3610 1_1_0 EXIST::FUNCTION: +ASN1_PCTX_new 3611 1_1_0 EXIST::FUNCTION: +BN_is_prime_ex 3612 1_1_0 EXIST::FUNCTION: +PKCS5_v2_PBE_keyivgen 3613 1_1_0 EXIST::FUNCTION: +CRYPTO_ctr128_encrypt 3614 1_1_0 EXIST::FUNCTION: +CMS_unsigned_add1_attr_by_OBJ 3615 1_1_0 EXIST::FUNCTION:CMS +PEM_write_EC_PUBKEY 3616 1_1_0 EXIST::FUNCTION:EC,STDIO +X509v3_asid_add_inherit 3617 1_1_0 EXIST::FUNCTION:RFC3779 +ERR_get_error 3618 1_1_0 EXIST::FUNCTION: +TS_CONF_set_signer_digest 3619 1_1_0 EXIST::FUNCTION:TS +OBJ_new_nid 3620 1_1_0 EXIST::FUNCTION: +CMS_ReceiptRequest_new 3621 1_1_0 EXIST::FUNCTION:CMS +SRP_VBASE_get1_by_user 3622 1_1_0 EXIST::FUNCTION:SRP +UI_method_get_closer 3623 1_1_0 EXIST::FUNCTION: +ENGINE_get_ex_data 3624 1_1_0 EXIST::FUNCTION:ENGINE +BN_print_fp 3625 1_1_0 EXIST::FUNCTION:STDIO +MD2_Update 3626 1_1_0 EXIST::FUNCTION:MD2 +ENGINE_free 3628 1_1_0 EXIST::FUNCTION:ENGINE +d2i_X509_ATTRIBUTE 3629 1_1_0 EXIST::FUNCTION: +TS_RESP_free 3630 1_1_0 EXIST::FUNCTION:TS +PKCS5_pbe_set 3631 1_1_0 EXIST::FUNCTION: +TS_RESP_CTX_free 3632 1_1_0 EXIST::FUNCTION:TS +d2i_PUBKEY 3633 1_1_0 EXIST::FUNCTION: +ASYNC_cleanup_thread 3634 1_1_0 EXIST::FUNCTION: +SHA384_Update 3635 1_1_0 EXIST::FUNCTION: +CRYPTO_cfb128_1_encrypt 3636 1_1_0 EXIST::FUNCTION: +BIO_set_cipher 3637 1_1_0 EXIST::FUNCTION: +PEM_read_PUBKEY 3638 1_1_0 EXIST::FUNCTION:STDIO +RSA_PKCS1_OpenSSL 3639 1_1_0 EXIST::FUNCTION:RSA +AUTHORITY_INFO_ACCESS_free 3640 1_1_0 EXIST::FUNCTION: +SCT_get0_signature 3641 1_1_0 EXIST::FUNCTION:CT +DISPLAYTEXT_it 3643 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +DISPLAYTEXT_it 3643 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +OPENSSL_gmtime_adj 3644 1_1_0 EXIST::FUNCTION: +ASN1_INTEGER_dup 3645 1_1_0 EXIST::FUNCTION: +DSA_print 3646 1_1_0 EXIST::FUNCTION:DSA +X509_REQ_set_extension_nids 3647 1_1_0 EXIST::FUNCTION: +X509_free 3648 1_1_0 EXIST::FUNCTION: +ERR_load_ERR_strings 3649 1_1_0 EXIST::FUNCTION: +ASN1_const_check_infinite_end 3650 1_1_0 EXIST::FUNCTION: +RSA_null_method 3651 1_1_0 EXIST::FUNCTION:RSA +TS_REQ_ext_free 3652 1_1_0 EXIST::FUNCTION:TS +EVP_PKEY_meth_get_encrypt 3653 1_1_0 EXIST::FUNCTION: +Camellia_ecb_encrypt 3654 1_1_0 EXIST::FUNCTION:CAMELLIA +ENGINE_set_default_RSA 3655 1_1_0 EXIST::FUNCTION:ENGINE +EVP_EncodeBlock 3656 1_1_0 EXIST::FUNCTION: +SXNETID_free 3657 1_1_0 EXIST::FUNCTION: +SHA1_Init 3658 1_1_0 EXIST::FUNCTION: +CRYPTO_atomic_add 3659 1_1_0 EXIST::FUNCTION: +TS_CONF_load_certs 3660 1_1_0 EXIST::FUNCTION:TS +PEM_write_bio_DSAPrivateKey 3661 1_1_0 EXIST::FUNCTION:DSA +CMS_encrypt 3662 1_1_0 EXIST::FUNCTION:CMS +CRYPTO_nistcts128_decrypt 3663 1_1_0 EXIST::FUNCTION: +ERR_load_DH_strings 3664 1_1_0 EXIST::FUNCTION:DH +EVP_MD_block_size 3665 1_1_0 EXIST::FUNCTION: +TS_X509_ALGOR_print_bio 3666 1_1_0 EXIST::FUNCTION:TS +d2i_PKCS7_ENVELOPE 3667 1_1_0 EXIST::FUNCTION: +ESS_CERT_ID_new 3669 1_1_0 EXIST::FUNCTION:TS +EC_POINT_invert 3670 1_1_0 EXIST::FUNCTION:EC +CAST_set_key 3671 1_1_0 EXIST::FUNCTION:CAST +ENGINE_get_pkey_meth 3672 1_1_0 EXIST::FUNCTION:ENGINE +BIO_ADDRINFO_free 3673 1_1_0 EXIST::FUNCTION:SOCK +DES_ede3_cbc_encrypt 3674 1_1_0 EXIST::FUNCTION:DES +X509v3_asid_canonize 3675 1_1_0 EXIST::FUNCTION:RFC3779 +i2d_ASIdOrRange 3676 1_1_0 EXIST::FUNCTION:RFC3779 +OCSP_url_svcloc_new 3677 1_1_0 EXIST::FUNCTION:OCSP +CRYPTO_mem_ctrl 3678 1_1_0 EXIST::FUNCTION: +ASN1_verify 3679 1_1_0 EXIST::FUNCTION: +DSA_generate_parameters_ex 3680 1_1_0 EXIST::FUNCTION:DSA +X509_sign 3681 1_1_0 EXIST::FUNCTION: +SHA256_Transform 3682 1_1_0 EXIST::FUNCTION: +BIO_ADDR_free 3683 1_1_0 EXIST::FUNCTION:SOCK +ASN1_STRING_free 3684 1_1_0 EXIST::FUNCTION: +X509_VERIFY_PARAM_inherit 3685 1_1_0 EXIST::FUNCTION: +EC_GROUP_get_curve_name 3686 1_1_0 EXIST::FUNCTION:EC +RSA_print 3687 1_1_0 EXIST::FUNCTION:RSA +i2d_ASN1_BMPSTRING 3688 1_1_0 EXIST::FUNCTION: +EVP_PKEY_decrypt_old 3689 1_1_0 EXIST::FUNCTION: +ASN1_UTCTIME_cmp_time_t 3690 1_1_0 EXIST::FUNCTION: +X509_VERIFY_PARAM_set1_ip 3691 1_1_0 EXIST::FUNCTION: +OTHERNAME_free 3692 1_1_0 EXIST::FUNCTION: +OCSP_REVOKEDINFO_free 3693 1_1_0 EXIST::FUNCTION:OCSP +EVP_CIPHER_CTX_encrypting 3694 1_1_0 EXIST::FUNCTION: +EC_KEY_can_sign 3695 1_1_0 EXIST::FUNCTION:EC +PEM_write_bio_RSAPublicKey 3696 1_1_0 EXIST::FUNCTION:RSA +X509_CRL_set1_lastUpdate 3697 1_1_0 EXIST::FUNCTION: +OCSP_sendreq_nbio 3698 1_1_0 EXIST::FUNCTION:OCSP +PKCS8_encrypt 3699 1_1_0 EXIST::FUNCTION: +i2d_PKCS7_fp 3700 1_1_0 EXIST::FUNCTION:STDIO +i2d_X509_REQ 3701 1_1_0 EXIST::FUNCTION: +OCSP_CRLID_it 3702 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:OCSP +OCSP_CRLID_it 3702 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:OCSP +PEM_ASN1_write_bio 3703 1_1_0 EXIST::FUNCTION: +X509_get0_reject_objects 3704 1_1_0 EXIST::FUNCTION: +BIO_set_tcp_ndelay 3705 1_1_0 EXIST::FUNCTION:SOCK +CMS_add0_CertificateChoices 3706 1_1_0 EXIST::FUNCTION:CMS +POLICYINFO_new 3707 1_1_0 EXIST::FUNCTION: +X509_CRL_get0_by_serial 3708 1_1_0 EXIST::FUNCTION: +PKCS12_add_friendlyname_asc 3709 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_get1_chain 3710 1_1_0 EXIST::FUNCTION: +ASN1_mbstring_ncopy 3711 1_1_0 EXIST::FUNCTION: +PKCS7_RECIP_INFO_it 3712 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +PKCS7_RECIP_INFO_it 3712 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +ENGINE_register_all_digests 3713 1_1_0 EXIST::FUNCTION:ENGINE +X509_REQ_get_version 3714 1_1_0 EXIST::FUNCTION: +i2d_ASN1_UTCTIME 3715 1_1_0 EXIST::FUNCTION: +TS_STATUS_INFO_new 3716 1_1_0 EXIST::FUNCTION:TS +UI_set_ex_data 3717 1_1_0 EXIST::FUNCTION: +ASN1_TIME_set 3718 1_1_0 EXIST::FUNCTION: +TS_RESP_verify_response 3719 1_1_0 EXIST::FUNCTION:TS +X509_REVOKED_get0_serialNumber 3720 1_1_0 EXIST::FUNCTION: +X509_VERIFY_PARAM_free 3721 1_1_0 EXIST::FUNCTION: +ASN1_TYPE_new 3722 1_1_0 EXIST::FUNCTION: +CMAC_CTX_cleanup 3723 1_1_0 EXIST::FUNCTION:CMAC +i2d_PKCS7_NDEF 3724 1_1_0 EXIST::FUNCTION: +OPENSSL_sk_pop_free 3725 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_get0_policy_tree 3726 1_1_0 EXIST::FUNCTION: +DES_set_key_checked 3727 1_1_0 EXIST::FUNCTION:DES +EVP_PKEY_meth_free 3728 1_1_0 EXIST::FUNCTION: +EVP_sha224 3729 1_1_0 EXIST::FUNCTION: +ENGINE_set_id 3730 1_1_0 EXIST::FUNCTION:ENGINE +d2i_ECPrivateKey 3731 1_1_0 EXIST::FUNCTION:EC +CMS_signed_add1_attr_by_NID 3732 1_1_0 EXIST::FUNCTION:CMS +i2d_DSAPrivateKey_fp 3733 1_1_0 EXIST::FUNCTION:DSA,STDIO +EVP_CIPHER_meth_get_set_asn1_params 3734 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_get_ex_data 3735 1_1_0 EXIST::FUNCTION: +CMS_RecipientInfo_kari_set0_pkey 3736 1_1_0 EXIST::FUNCTION:CMS +X509v3_addr_add_inherit 3737 1_1_0 EXIST::FUNCTION:RFC3779 +SRP_Calc_u 3738 1_1_0 EXIST::FUNCTION:SRP +i2d_PKCS8PrivateKey_bio 3739 1_1_0 EXIST::FUNCTION: +X509_get_extension_flags 3740 1_1_0 EXIST::FUNCTION: +X509V3_EXT_val_prn 3741 1_1_0 EXIST::FUNCTION: +SCT_get_validation_status 3742 1_1_0 EXIST::FUNCTION:CT +NETSCAPE_CERT_SEQUENCE_free 3743 1_1_0 EXIST::FUNCTION: +EVP_PBE_scrypt 3744 1_1_0 EXIST::FUNCTION:SCRYPT +d2i_TS_REQ_bio 3745 1_1_0 EXIST::FUNCTION:TS +ENGINE_set_default_ciphers 3746 1_1_0 EXIST::FUNCTION:ENGINE +X509_get_signature_nid 3747 1_1_0 EXIST::FUNCTION: +DES_fcrypt 3748 1_1_0 EXIST::FUNCTION:DES +PEM_write_bio_X509_REQ 3749 1_1_0 EXIST::FUNCTION: +EVP_PKEY_meth_get_sign 3750 1_1_0 EXIST::FUNCTION: +TS_REQ_get_nonce 3751 1_1_0 EXIST::FUNCTION:TS +ENGINE_unregister_EC 3752 1_1_0 EXIST::FUNCTION:ENGINE +X509v3_get_ext_count 3753 1_1_0 EXIST::FUNCTION: +UI_OpenSSL 3754 1_1_0 EXIST::FUNCTION:UI_CONSOLE +CRYPTO_ccm128_decrypt 3755 1_1_0 EXIST::FUNCTION: +d2i_OCSP_RESPDATA 3756 1_1_0 EXIST::FUNCTION:OCSP +BIO_set_callback 3757 1_1_0 EXIST::FUNCTION: +BN_GF2m_poly2arr 3758 1_1_0 EXIST::FUNCTION:EC2M +CMS_unsigned_get_attr_count 3759 1_1_0 EXIST::FUNCTION:CMS +EVP_aes_256_gcm 3760 1_1_0 EXIST::FUNCTION: +RSA_padding_check_X931 3761 1_1_0 EXIST::FUNCTION:RSA +ECDH_compute_key 3762 1_1_0 EXIST::FUNCTION:EC +ASN1_TIME_print 3763 1_1_0 EXIST::FUNCTION: +EVP_PKEY_CTX_get0_peerkey 3764 1_1_0 EXIST::FUNCTION: +BN_mod_lshift1 3765 1_1_0 EXIST::FUNCTION: +BIO_ADDRINFO_family 3766 1_1_0 EXIST::FUNCTION:SOCK +PEM_write_DHxparams 3767 1_1_0 EXIST::FUNCTION:DH,STDIO +BN_mod_exp2_mont 3768 1_1_0 EXIST::FUNCTION: +ASN1_PRINTABLE_free 3769 1_1_0 EXIST::FUNCTION: +PKCS7_ATTR_SIGN_it 3771 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +PKCS7_ATTR_SIGN_it 3771 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +EVP_MD_CTX_copy 3772 1_1_0 EXIST::FUNCTION: +ENGINE_set_ctrl_function 3773 1_1_0 EXIST::FUNCTION:ENGINE +OCSP_id_get0_info 3774 1_1_0 EXIST::FUNCTION:OCSP +BIO_ADDRINFO_next 3775 1_1_0 EXIST::FUNCTION:SOCK +OCSP_RESPBYTES_free 3776 1_1_0 EXIST::FUNCTION:OCSP +EC_KEY_METHOD_set_init 3777 1_1_0 EXIST::FUNCTION:EC +EVP_PKEY_asn1_copy 3778 1_1_0 EXIST::FUNCTION: +RSA_PSS_PARAMS_it 3779 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:RSA +RSA_PSS_PARAMS_it 3779 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:RSA +X509_STORE_CTX_get_error_depth 3780 1_1_0 EXIST::FUNCTION: +ASN1_GENERALIZEDTIME_set_string 3781 1_1_0 EXIST::FUNCTION: +EC_GROUP_new_curve_GFp 3782 1_1_0 EXIST::FUNCTION:EC +UI_new_method 3783 1_1_0 EXIST::FUNCTION: +Camellia_ofb128_encrypt 3784 1_1_0 EXIST::FUNCTION:CAMELLIA +X509_new 3785 1_1_0 EXIST::FUNCTION: +EC_KEY_get_conv_form 3786 1_1_0 EXIST::FUNCTION:EC +CTLOG_STORE_get0_log_by_id 3787 1_1_0 EXIST::FUNCTION:CT +CMS_signed_add1_attr 3788 1_1_0 EXIST::FUNCTION:CMS +EVP_CIPHER_meth_set_iv_length 3789 1_1_0 EXIST::FUNCTION: +X509v3_asid_validate_path 3790 1_1_0 EXIST::FUNCTION:RFC3779 +CMS_RecipientInfo_set0_password 3791 1_1_0 EXIST::FUNCTION:CMS +TS_CONF_load_cert 3792 1_1_0 EXIST::FUNCTION:TS +i2d_ECPKParameters 3793 1_1_0 EXIST::FUNCTION:EC +X509_TRUST_get0 3794 1_1_0 EXIST::FUNCTION: +CMS_get0_RecipientInfos 3795 1_1_0 EXIST::FUNCTION:CMS +EVP_PKEY_CTX_new 3796 1_1_0 EXIST::FUNCTION: +i2d_DSA_PUBKEY_bio 3797 1_1_0 EXIST::FUNCTION:DSA +X509_REQ_get_subject_name 3798 1_1_0 EXIST::FUNCTION: +BN_div_word 3799 1_1_0 EXIST::FUNCTION: +TS_CONF_set_signer_key 3800 1_1_0 EXIST::FUNCTION:TS +BN_GF2m_mod_sqrt 3801 1_1_0 EXIST::FUNCTION:EC2M +EVP_CIPHER_nid 3802 1_1_0 EXIST::FUNCTION: +OBJ_txt2obj 3803 1_1_0 EXIST::FUNCTION: +CMS_RecipientInfo_kari_get0_orig_id 3804 1_1_0 EXIST::FUNCTION:CMS +EVP_bf_ecb 3805 1_1_0 EXIST::FUNCTION:BF +v2i_GENERAL_NAME_ex 3806 1_1_0 EXIST::FUNCTION: +CMS_signed_delete_attr 3807 1_1_0 EXIST::FUNCTION:CMS +ASN1_TYPE_pack_sequence 3808 1_1_0 EXIST::FUNCTION: +USERNOTICE_it 3809 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +USERNOTICE_it 3809 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +PKEY_USAGE_PERIOD_it 3810 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +PKEY_USAGE_PERIOD_it 3810 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +BN_mul_word 3811 1_1_0 EXIST::FUNCTION: +i2d_IPAddressRange 3813 1_1_0 EXIST::FUNCTION:RFC3779 +CMS_unsigned_add1_attr_by_txt 3814 1_1_0 EXIST::FUNCTION:CMS +d2i_RSA_PUBKEY 3815 1_1_0 EXIST::FUNCTION:RSA +PKCS12_gen_mac 3816 1_1_0 EXIST::FUNCTION: +ERR_load_ENGINE_strings 3817 1_1_0 EXIST::FUNCTION:ENGINE +ERR_load_CT_strings 3818 1_1_0 EXIST::FUNCTION:CT +OCSP_ONEREQ_it 3819 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:OCSP +OCSP_ONEREQ_it 3819 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:OCSP +X509_PURPOSE_get_by_sname 3820 1_1_0 EXIST::FUNCTION: +X509_PURPOSE_set 3821 1_1_0 EXIST::FUNCTION: +BN_mod_inverse 3822 1_1_0 EXIST::FUNCTION: +ASN1_STRING_TABLE_get 3823 1_1_0 EXIST::FUNCTION: +BN_bn2binpad 3824 1_1_0 EXIST::FUNCTION: +X509_supported_extension 3825 1_1_0 EXIST::FUNCTION: +ECDSA_sign_setup 3826 1_1_0 EXIST::FUNCTION:EC +EVP_camellia_192_cfb128 3827 1_1_0 EXIST::FUNCTION:CAMELLIA +d2i_AUTHORITY_KEYID 3828 1_1_0 EXIST::FUNCTION: +RIPEMD160_Transform 3829 1_1_0 EXIST::FUNCTION:RMD160 +DES_random_key 3830 1_1_0 EXIST::FUNCTION:DES +i2d_PKCS12_MAC_DATA 3831 1_1_0 EXIST::FUNCTION: +EVP_PKEY_get0_EC_KEY 3832 1_1_0 EXIST::FUNCTION:EC +ASN1_SCTX_get_item 3833 1_1_0 EXIST::FUNCTION: +NOTICEREF_new 3834 1_1_0 EXIST::FUNCTION: +BN_GF2m_mod_inv 3835 1_1_0 EXIST::FUNCTION:EC2M +X509_CERT_AUX_free 3836 1_1_0 EXIST::FUNCTION: +BN_GF2m_mod_inv_arr 3837 1_1_0 EXIST::FUNCTION:EC2M +X509_REQ_get1_email 3838 1_1_0 EXIST::FUNCTION: +EC_KEY_print 3839 1_1_0 EXIST::FUNCTION:EC +i2d_ASN1_INTEGER 3840 1_1_0 EXIST::FUNCTION: +OCSP_SINGLERESP_add1_ext_i2d 3841 1_1_0 EXIST::FUNCTION:OCSP +PKCS7_add_signed_attribute 3842 1_1_0 EXIST::FUNCTION: +i2d_PrivateKey_bio 3843 1_1_0 EXIST::FUNCTION: +RSA_padding_add_PKCS1_type_1 3844 1_1_0 EXIST::FUNCTION:RSA +i2d_re_X509_tbs 3845 1_1_0 EXIST::FUNCTION: +EVP_CIPHER_iv_length 3846 1_1_0 EXIST::FUNCTION: +OCSP_REQ_CTX_get0_mem_bio 3847 1_1_0 EXIST::FUNCTION:OCSP +i2d_PKCS8PrivateKeyInfo_bio 3848 1_1_0 EXIST::FUNCTION: +d2i_OCSP_CERTID 3849 1_1_0 EXIST::FUNCTION:OCSP +EVP_CIPHER_meth_set_init 3850 1_1_0 EXIST::FUNCTION: +RIPEMD160_Final 3851 1_1_0 EXIST::FUNCTION:RMD160 +NETSCAPE_SPKI_free 3852 1_1_0 EXIST::FUNCTION: +BIO_asn1_get_prefix 3853 1_1_0 EXIST::FUNCTION: +d2i_OCSP_ONEREQ 3854 1_1_0 EXIST::FUNCTION:OCSP +EVP_PKEY_asn1_set_security_bits 3855 1_1_0 EXIST::FUNCTION: +i2d_CERTIFICATEPOLICIES 3856 1_1_0 EXIST::FUNCTION: +i2d_X509_CERT_AUX 3857 1_1_0 EXIST::FUNCTION: +i2o_ECPublicKey 3858 1_1_0 EXIST::FUNCTION:EC +PKCS12_SAFEBAG_create0_pkcs8 3859 1_1_0 EXIST::FUNCTION: +OBJ_get0_data 3860 1_1_0 EXIST::FUNCTION: +EC_GROUP_get0_seed 3861 1_1_0 EXIST::FUNCTION:EC +OCSP_REQUEST_it 3862 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:OCSP +OCSP_REQUEST_it 3862 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:OCSP +ASRange_it 3863 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:RFC3779 +ASRange_it 3863 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:RFC3779 +i2d_TS_RESP 3864 1_1_0 EXIST::FUNCTION:TS +TS_TST_INFO_get_ext_by_OBJ 3865 1_1_0 EXIST::FUNCTION:TS +d2i_PKCS7_RECIP_INFO 3866 1_1_0 EXIST::FUNCTION: +d2i_X509_CRL 3867 1_1_0 EXIST::FUNCTION: +ASN1_OCTET_STRING_dup 3868 1_1_0 EXIST::FUNCTION: +CRYPTO_nistcts128_decrypt_block 3869 1_1_0 EXIST::FUNCTION: +CMS_stream 3870 1_1_0 EXIST::FUNCTION:CMS +RSA_OAEP_PARAMS_it 3871 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:RSA +RSA_OAEP_PARAMS_it 3871 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:RSA +BN_bn2mpi 3872 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_cleanup 3873 1_1_0 EXIST::FUNCTION: +OCSP_onereq_get0_id 3874 1_1_0 EXIST::FUNCTION:OCSP +X509_get_default_cert_dir 3875 1_1_0 EXIST::FUNCTION: +PROXY_POLICY_free 3877 1_1_0 EXIST::FUNCTION: +PEM_write_DSAPrivateKey 3878 1_1_0 EXIST::FUNCTION:DSA,STDIO +OPENSSL_sk_delete_ptr 3879 1_1_0 EXIST::FUNCTION: +CMS_add0_RevocationInfoChoice 3880 1_1_0 EXIST::FUNCTION:CMS +ASN1_PCTX_get_flags 3881 1_1_0 EXIST::FUNCTION: +EVP_MD_meth_set_result_size 3882 1_1_0 EXIST::FUNCTION: +i2d_X509_CRL 3883 1_1_0 EXIST::FUNCTION: +ASN1_INTEGER_it 3885 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ASN1_INTEGER_it 3885 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +TS_ACCURACY_new 3886 1_1_0 EXIST::FUNCTION:TS +i2d_SXNETID 3887 1_1_0 EXIST::FUNCTION: +BN_mod_mul_montgomery 3888 1_1_0 EXIST::FUNCTION: +BN_nnmod 3889 1_1_0 EXIST::FUNCTION: +TS_RESP_CTX_set_status_info_cond 3890 1_1_0 EXIST::FUNCTION:TS +PBKDF2PARAM_new 3891 1_1_0 EXIST::FUNCTION: +ENGINE_set_RSA 3892 1_1_0 EXIST::FUNCTION:ENGINE +i2d_X509_ATTRIBUTE 3893 1_1_0 EXIST::FUNCTION: +PKCS7_ctrl 3894 1_1_0 EXIST::FUNCTION: +OCSP_REVOKEDINFO_it 3895 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:OCSP +OCSP_REVOKEDINFO_it 3895 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:OCSP +X509V3_set_ctx 3896 1_1_0 EXIST::FUNCTION: +ASN1_ENUMERATED_set_int64 3897 1_1_0 EXIST::FUNCTION: +o2i_SCT 3898 1_1_0 EXIST::FUNCTION:CT +CRL_DIST_POINTS_free 3899 1_1_0 EXIST::FUNCTION: +d2i_OCSP_SINGLERESP 3900 1_1_0 EXIST::FUNCTION:OCSP +EVP_CIPHER_CTX_num 3901 1_1_0 EXIST::FUNCTION: +EVP_PKEY_verify_recover_init 3902 1_1_0 EXIST::FUNCTION: +SHA512_Init 3903 1_1_0 EXIST::FUNCTION: +TS_MSG_IMPRINT_set_msg 3904 1_1_0 EXIST::FUNCTION:TS +CMS_unsigned_add1_attr 3905 1_1_0 EXIST::FUNCTION:CMS +OPENSSL_LH_doall 3906 1_1_0 EXIST::FUNCTION: +PKCS8_pkey_get0_attrs 3907 1_1_0 EXIST::FUNCTION: +PKCS8_pkey_add1_attr_by_NID 3908 1_1_0 EXIST::FUNCTION: +ASYNC_is_capable 3909 1_1_0 EXIST::FUNCTION: +EVP_CIPHER_CTX_set_cipher_data 3910 1_1_0 EXIST::FUNCTION: +EVP_CIPHER_CTX_get_cipher_data 3911 1_1_0 EXIST::FUNCTION: +BIO_up_ref 3912 1_1_0 EXIST::FUNCTION: +X509_STORE_up_ref 3913 1_1_0 EXIST::FUNCTION: +DSA_SIG_get0 3914 1_1_0 EXIST::FUNCTION:DSA +BN_BLINDING_is_current_thread 3915 1_1_0 EXIST::FUNCTION: +BN_BLINDING_set_current_thread 3916 1_1_0 EXIST::FUNCTION: +BN_BLINDING_lock 3917 1_1_0 EXIST::FUNCTION: +BN_BLINDING_unlock 3918 1_1_0 EXIST::FUNCTION: +EC_GROUP_new_from_ecpkparameters 3919 1_1_0 EXIST::FUNCTION:EC +EC_GROUP_get_ecpkparameters 3920 1_1_0 EXIST::FUNCTION:EC +EC_GROUP_new_from_ecparameters 3921 1_1_0 EXIST::FUNCTION:EC +ECPARAMETERS_it 3922 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:EC +ECPARAMETERS_it 3922 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:EC +ECPKPARAMETERS_it 3923 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:EC +ECPKPARAMETERS_it 3923 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:EC +EC_GROUP_get_ecparameters 3924 1_1_0 EXIST::FUNCTION:EC +DHparams_it 3925 1_1_0 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:DH +DHparams_it 3925 1_1_0 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:DH +EVP_blake2s256 3926 1_1_0 EXIST::FUNCTION:BLAKE2 +EVP_blake2b512 3927 1_1_0 EXIST::FUNCTION:BLAKE2 +X509_SIG_get0 3928 1_1_0 EXIST::FUNCTION: +BIO_meth_new 3929 1_1_0 EXIST::FUNCTION: +BIO_meth_get_puts 3930 1_1_0 EXIST::FUNCTION: +BIO_meth_get_ctrl 3931 1_1_0 EXIST::FUNCTION: +BIO_meth_get_gets 3932 1_1_0 EXIST::FUNCTION: +BIO_get_data 3933 1_1_0 EXIST::FUNCTION: +BIO_set_init 3934 1_1_0 EXIST::FUNCTION: +BIO_meth_set_puts 3935 1_1_0 EXIST::FUNCTION: +BIO_get_shutdown 3936 1_1_0 EXIST::FUNCTION: +BIO_get_init 3937 1_1_0 EXIST::FUNCTION: +BIO_meth_set_ctrl 3938 1_1_0 EXIST::FUNCTION: +BIO_meth_set_read 3939 1_1_0 EXIST::FUNCTION: +BIO_set_shutdown 3940 1_1_0 EXIST::FUNCTION: +BIO_meth_set_create 3941 1_1_0 EXIST::FUNCTION: +BIO_meth_get_write 3942 1_1_0 EXIST::FUNCTION: +BIO_meth_set_callback_ctrl 3943 1_1_0 EXIST::FUNCTION: +BIO_meth_get_create 3944 1_1_0 EXIST::FUNCTION: +BIO_set_next 3945 1_1_0 EXIST::FUNCTION: +BIO_set_data 3946 1_1_0 EXIST::FUNCTION: +BIO_meth_set_write 3947 1_1_0 EXIST::FUNCTION: +BIO_meth_set_destroy 3948 1_1_0 EXIST::FUNCTION: +BIO_meth_set_gets 3949 1_1_0 EXIST::FUNCTION: +BIO_meth_get_callback_ctrl 3950 1_1_0 EXIST::FUNCTION: +BIO_meth_get_destroy 3951 1_1_0 EXIST::FUNCTION: +BIO_meth_get_read 3952 1_1_0 EXIST::FUNCTION: +BIO_set_retry_reason 3953 1_1_0 EXIST::FUNCTION: +BIO_meth_free 3954 1_1_0 EXIST::FUNCTION: +DSA_meth_set_bn_mod_exp 3955 1_1_0 EXIST::FUNCTION:DSA +DSA_meth_set_init 3956 1_1_0 EXIST::FUNCTION:DSA +DSA_meth_free 3957 1_1_0 EXIST::FUNCTION:DSA +DSA_meth_set_mod_exp 3958 1_1_0 EXIST::FUNCTION:DSA +DSA_meth_set_sign 3959 1_1_0 EXIST::FUNCTION:DSA +DSA_meth_get_finish 3960 1_1_0 EXIST::FUNCTION:DSA +DSA_set_flags 3961 1_1_0 EXIST::FUNCTION:DSA +DSA_get0_pqg 3962 1_1_0 EXIST::FUNCTION:DSA +DSA_meth_get0_app_data 3963 1_1_0 EXIST::FUNCTION:DSA +DSA_meth_get_keygen 3964 1_1_0 EXIST::FUNCTION:DSA +DSA_clear_flags 3965 1_1_0 EXIST::FUNCTION:DSA +DSA_meth_get0_name 3966 1_1_0 EXIST::FUNCTION:DSA +DSA_meth_get_paramgen 3967 1_1_0 EXIST::FUNCTION:DSA +DSA_meth_get_sign 3968 1_1_0 EXIST::FUNCTION:DSA +DSA_meth_set_paramgen 3969 1_1_0 EXIST::FUNCTION:DSA +DSA_test_flags 3970 1_1_0 EXIST::FUNCTION:DSA +DSA_meth_set0_app_data 3971 1_1_0 EXIST::FUNCTION:DSA +DSA_meth_set1_name 3972 1_1_0 EXIST::FUNCTION:DSA +DSA_get0_key 3973 1_1_0 EXIST::FUNCTION:DSA +DSA_meth_get_mod_exp 3974 1_1_0 EXIST::FUNCTION:DSA +DSA_set0_pqg 3975 1_1_0 EXIST::FUNCTION:DSA +DSA_meth_get_flags 3976 1_1_0 EXIST::FUNCTION:DSA +DSA_meth_get_verify 3977 1_1_0 EXIST::FUNCTION:DSA +DSA_meth_set_verify 3978 1_1_0 EXIST::FUNCTION:DSA +DSA_meth_set_finish 3979 1_1_0 EXIST::FUNCTION:DSA +DSA_meth_set_keygen 3980 1_1_0 EXIST::FUNCTION:DSA +DSA_meth_dup 3981 1_1_0 EXIST::FUNCTION:DSA +DSA_set0_key 3982 1_1_0 EXIST::FUNCTION:DSA +DSA_meth_get_init 3983 1_1_0 EXIST::FUNCTION:DSA +DSA_meth_set_sign_setup 3984 1_1_0 EXIST::FUNCTION:DSA +DSA_meth_get_bn_mod_exp 3985 1_1_0 EXIST::FUNCTION:DSA +DSA_get_method 3986 1_1_0 EXIST::FUNCTION:DSA +DSA_meth_new 3987 1_1_0 EXIST::FUNCTION:DSA +DSA_meth_set_flags 3988 1_1_0 EXIST::FUNCTION:DSA +DSA_meth_get_sign_setup 3989 1_1_0 EXIST::FUNCTION:DSA +DSA_get0_engine 3990 1_1_0 EXIST::FUNCTION:DSA +X509_VERIFY_PARAM_set_auth_level 3991 1_1_0 EXIST::FUNCTION: +X509_VERIFY_PARAM_get_auth_level 3992 1_1_0 EXIST::FUNCTION: +X509_REQ_get0_pubkey 3993 1_1_0 EXIST::FUNCTION: +RSA_set0_key 3994 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_get_flags 3995 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_set_finish 3996 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_get_priv_dec 3997 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_get_sign 3998 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_get_bn_mod_exp 3999 1_1_0 EXIST::FUNCTION:RSA +RSA_test_flags 4000 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_new 4001 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_get0_app_data 4002 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_dup 4003 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_set1_name 4004 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_set0_app_data 4005 1_1_0 EXIST::FUNCTION:RSA +RSA_set_flags 4006 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_set_sign 4007 1_1_0 EXIST::FUNCTION:RSA +RSA_clear_flags 4008 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_get_keygen 4009 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_set_keygen 4010 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_set_pub_dec 4011 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_get_finish 4012 1_1_0 EXIST::FUNCTION:RSA +RSA_get0_key 4013 1_1_0 EXIST::FUNCTION:RSA +RSA_get0_engine 4014 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_set_priv_enc 4015 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_set_verify 4016 1_1_0 EXIST::FUNCTION:RSA +RSA_get0_factors 4017 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_get0_name 4018 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_get_mod_exp 4019 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_set_flags 4020 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_get_pub_dec 4021 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_set_bn_mod_exp 4022 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_get_init 4023 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_free 4024 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_get_pub_enc 4025 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_set_mod_exp 4026 1_1_0 EXIST::FUNCTION:RSA +RSA_set0_factors 4027 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_set_pub_enc 4028 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_set_priv_dec 4029 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_get_verify 4030 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_set_init 4031 1_1_0 EXIST::FUNCTION:RSA +RSA_meth_get_priv_enc 4032 1_1_0 EXIST::FUNCTION:RSA +RSA_set0_crt_params 4037 1_1_0 EXIST::FUNCTION:RSA +RSA_get0_crt_params 4038 1_1_0 EXIST::FUNCTION:RSA +DH_set0_pqg 4039 1_1_0 EXIST::FUNCTION:DH +DH_clear_flags 4041 1_1_0 EXIST::FUNCTION:DH +DH_get0_key 4042 1_1_0 EXIST::FUNCTION:DH +DH_get0_engine 4043 1_1_0 EXIST::FUNCTION:DH +DH_set0_key 4044 1_1_0 EXIST::FUNCTION:DH +DH_set_length 4045 1_1_0 EXIST::FUNCTION:DH +DH_test_flags 4046 1_1_0 EXIST::FUNCTION:DH +DH_get_length 4047 1_1_0 EXIST::FUNCTION:DH +DH_get0_pqg 4048 1_1_0 EXIST::FUNCTION:DH +DH_meth_get_compute_key 4049 1_1_0 EXIST::FUNCTION:DH +DH_meth_set1_name 4050 1_1_0 EXIST::FUNCTION:DH +DH_meth_set_init 4051 1_1_0 EXIST::FUNCTION:DH +DH_meth_get_finish 4052 1_1_0 EXIST::FUNCTION:DH +DH_meth_get0_name 4053 1_1_0 EXIST::FUNCTION:DH +DH_meth_set_generate_params 4054 1_1_0 EXIST::FUNCTION:DH +DH_meth_set_compute_key 4055 1_1_0 EXIST::FUNCTION:DH +DH_meth_set_flags 4056 1_1_0 EXIST::FUNCTION:DH +DH_meth_get_generate_params 4057 1_1_0 EXIST::FUNCTION:DH +DH_meth_get_flags 4058 1_1_0 EXIST::FUNCTION:DH +DH_meth_set_finish 4059 1_1_0 EXIST::FUNCTION:DH +DH_meth_get0_app_data 4060 1_1_0 EXIST::FUNCTION:DH +DH_meth_set0_app_data 4061 1_1_0 EXIST::FUNCTION:DH +DH_meth_get_init 4062 1_1_0 EXIST::FUNCTION:DH +DH_meth_get_bn_mod_exp 4063 1_1_0 EXIST::FUNCTION:DH +DH_meth_new 4064 1_1_0 EXIST::FUNCTION:DH +DH_meth_dup 4065 1_1_0 EXIST::FUNCTION:DH +DH_meth_set_bn_mod_exp 4066 1_1_0 EXIST::FUNCTION:DH +DH_meth_set_generate_key 4067 1_1_0 EXIST::FUNCTION:DH +DH_meth_free 4068 1_1_0 EXIST::FUNCTION:DH +DH_meth_get_generate_key 4069 1_1_0 EXIST::FUNCTION:DH +DH_set_flags 4070 1_1_0 EXIST::FUNCTION:DH +X509_STORE_CTX_get_obj_by_subject 4071 1_1_0 EXIST::FUNCTION: +X509_OBJECT_free 4072 1_1_0 EXIST::FUNCTION: +X509_OBJECT_get0_X509 4073 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_get0_untrusted 4074 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_set_error_depth 4075 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_get0_cert 4076 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_set_verify 4077 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_set_current_cert 4078 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_get_verify 4079 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_get_verify_cb 4080 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_set0_verified_chain 4081 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_set0_untrusted 4082 1_1_0 EXIST::FUNCTION: +OPENSSL_hexchar2int 4083 1_1_0 EXIST::FUNCTION: +X509_STORE_set_ex_data 4084 1_1_0 EXIST::FUNCTION: +X509_STORE_get_ex_data 4085 1_1_0 EXIST::FUNCTION: +X509_STORE_get0_objects 4086 1_1_0 EXIST::FUNCTION: +X509_OBJECT_get_type 4087 1_1_0 EXIST::FUNCTION: +X509_STORE_set_verify 4088 1_1_0 EXIST::FUNCTION: +X509_OBJECT_new 4089 1_1_0 EXIST::FUNCTION: +X509_STORE_get0_param 4090 1_1_0 EXIST::FUNCTION: +PEM_write_bio_PrivateKey_traditional 4091 1_1_0 EXIST::FUNCTION: +X509_get_pathlen 4092 1_1_0 EXIST::FUNCTION: +ECDSA_SIG_set0 4093 1_1_0 EXIST::FUNCTION:EC +DSA_SIG_set0 4094 1_1_0 EXIST::FUNCTION:DSA +EVP_PKEY_get0_hmac 4095 1_1_0 EXIST::FUNCTION: +HMAC_CTX_get_md 4096 1_1_0 EXIST::FUNCTION: +NAME_CONSTRAINTS_check_CN 4097 1_1_0 EXIST::FUNCTION: +OCSP_resp_get0_id 4098 1_1_0 EXIST::FUNCTION:OCSP +OCSP_resp_get0_certs 4099 1_1_0 EXIST::FUNCTION:OCSP +X509_set_proxy_flag 4100 1_1_0 EXIST::FUNCTION: +EVP_ENCODE_CTX_copy 4101 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_get_check_issued 4102 1_1_0 EXIST::FUNCTION: +X509_STORE_set_lookup_certs 4103 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_get_check_crl 4104 1_1_0 EXIST::FUNCTION: +X509_STORE_get_cleanup 4105 1_1_0 EXIST::FUNCTION: +X509_STORE_get_lookup_crls 4106 1_1_0 EXIST::FUNCTION: +X509_STORE_get_cert_crl 4107 1_1_0 EXIST::FUNCTION: +X509_STORE_get_lookup_certs 4108 1_1_0 EXIST::FUNCTION: +X509_STORE_get_check_revocation 4109 1_1_0 EXIST::FUNCTION: +X509_STORE_set_get_crl 4110 1_1_0 EXIST::FUNCTION: +X509_STORE_set_check_issued 4111 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_get_check_policy 4112 1_1_0 EXIST::FUNCTION: +X509_STORE_get_check_crl 4113 1_1_0 EXIST::FUNCTION: +X509_STORE_set_check_crl 4114 1_1_0 EXIST::FUNCTION: +X509_STORE_get_check_issued 4115 1_1_0 EXIST::FUNCTION: +X509_STORE_get_get_issuer 4116 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_get_get_crl 4117 1_1_0 EXIST::FUNCTION: +X509_STORE_set_get_issuer 4118 1_1_0 EXIST::FUNCTION: +X509_STORE_set_cleanup 4119 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_get_cleanup 4120 1_1_0 EXIST::FUNCTION: +X509_STORE_get_get_crl 4121 1_1_0 EXIST::FUNCTION: +X509_STORE_set_check_revocation 4122 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_get_cert_crl 4123 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_get_lookup_certs 4124 1_1_0 EXIST::FUNCTION: +X509_STORE_set_check_policy 4125 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_get_get_issuer 4126 1_1_0 EXIST::FUNCTION: +X509_STORE_get_check_policy 4127 1_1_0 EXIST::FUNCTION: +X509_STORE_set_cert_crl 4128 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_get_check_revocation 4129 1_1_0 EXIST::FUNCTION: +X509_STORE_get_verify_cb 4130 1_1_0 EXIST::FUNCTION: +X509_STORE_CTX_get_lookup_crls 4131 1_1_0 EXIST::FUNCTION: +X509_STORE_get_verify 4132 1_1_0 EXIST::FUNCTION: +X509_STORE_unlock 4133 1_1_0 EXIST::FUNCTION: +X509_STORE_lock 4134 1_1_0 EXIST::FUNCTION: +X509_set_proxy_pathlen 4135 1_1_0 EXIST::FUNCTION: +X509_get_proxy_pathlen 4136 1_1_0 EXIST::FUNCTION: +DSA_bits 4137 1_1_0 EXIST::FUNCTION:DSA +EVP_PKEY_set1_tls_encodedpoint 4138 1_1_0 EXIST::FUNCTION: +EVP_PKEY_get1_tls_encodedpoint 4139 1_1_0 EXIST::FUNCTION: +ASN1_STRING_get0_data 4140 1_1_0 EXIST::FUNCTION: +X509_SIG_getm 4141 1_1_0 EXIST::FUNCTION: +X509_get0_serialNumber 4142 1_1_0 EXIST::FUNCTION: +PKCS12_get_attr 4143 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0 +X509_CRL_get0_lastUpdate 4144 1_1_0 EXIST::FUNCTION: +X509_get0_notBefore 4145 1_1_0 EXIST::FUNCTION: +X509_get0_notAfter 4146 1_1_0 EXIST::FUNCTION: +X509_CRL_get0_nextUpdate 4147 1_1_0 EXIST::FUNCTION: +BIO_get_new_index 4148 1_1_0 EXIST::FUNCTION: +OPENSSL_utf82uni 4149 1_1_0 EXIST::FUNCTION: +PKCS12_add_friendlyname_utf8 4150 1_1_0 EXIST::FUNCTION: +OPENSSL_uni2utf8 4151 1_1_0 EXIST::FUNCTION: +PKCS12_key_gen_utf8 4152 1_1_0 EXIST::FUNCTION: +ECPKPARAMETERS_free 4153 1_1_0 EXIST::FUNCTION:EC +ECPARAMETERS_free 4154 1_1_0 EXIST::FUNCTION:EC +ECPKPARAMETERS_new 4155 1_1_0 EXIST::FUNCTION:EC +ECPARAMETERS_new 4156 1_1_0 EXIST::FUNCTION:EC +OCSP_RESPID_set_by_name 4157 1_1_0a EXIST::FUNCTION:OCSP +OCSP_RESPID_set_by_key 4158 1_1_0a EXIST::FUNCTION:OCSP +OCSP_RESPID_match 4159 1_1_0a EXIST::FUNCTION:OCSP +ASN1_ITEM_lookup 4160 1_1_1 EXIST::FUNCTION: +ASN1_ITEM_get 4161 1_1_1 EXIST::FUNCTION: +BIO_read_ex 4162 1_1_1 EXIST::FUNCTION: +BIO_set_callback_ex 4163 1_1_1 EXIST::FUNCTION: +BIO_get_callback_ex 4164 1_1_1 EXIST::FUNCTION: +BIO_meth_set_read_ex 4165 1_1_1 EXIST::FUNCTION: +BIO_meth_get_read_ex 4166 1_1_1 EXIST::FUNCTION: +BIO_write_ex 4167 1_1_1 EXIST::FUNCTION: +BIO_meth_get_write_ex 4168 1_1_1 EXIST::FUNCTION: +BIO_meth_set_write_ex 4169 1_1_1 EXIST::FUNCTION: +DSO_pathbyaddr 4170 1_1_0c EXIST::FUNCTION: +DSO_dsobyaddr 4171 1_1_0c EXIST::FUNCTION: +CT_POLICY_EVAL_CTX_get_time 4172 1_1_0d EXIST::FUNCTION:CT +CT_POLICY_EVAL_CTX_set_time 4173 1_1_0d EXIST::FUNCTION:CT +X509_VERIFY_PARAM_set_inh_flags 4174 1_1_0d EXIST::FUNCTION: +X509_VERIFY_PARAM_get_inh_flags 4175 1_1_0d EXIST::FUNCTION: +EVP_PKEY_CTX_md 4176 1_1_1 EXIST::FUNCTION: +RSA_pkey_ctx_ctrl 4177 1_1_1 EXIST::FUNCTION:RSA +UI_method_set_ex_data 4178 1_1_1 EXIST::FUNCTION: +UI_method_get_ex_data 4179 1_1_1 EXIST::FUNCTION: +UI_UTIL_wrap_read_pem_callback 4180 1_1_1 EXIST::FUNCTION: +X509_VERIFY_PARAM_get_time 4181 1_1_0d EXIST::FUNCTION: +EVP_PKEY_get0_poly1305 4182 1_1_1 EXIST::FUNCTION:POLY1305 +DH_check_params 4183 1_1_0d EXIST::FUNCTION:DH +EVP_PKEY_get0_siphash 4184 1_1_1 EXIST::FUNCTION:SIPHASH +EVP_aria_256_ofb 4185 1_1_1 EXIST::FUNCTION:ARIA +EVP_aria_256_cfb128 4186 1_1_1 EXIST::FUNCTION:ARIA +EVP_aria_128_cfb1 4187 1_1_1 EXIST::FUNCTION:ARIA +EVP_aria_128_ecb 4188 1_1_1 EXIST::FUNCTION:ARIA +EVP_aria_128_cfb128 4189 1_1_1 EXIST::FUNCTION:ARIA +EVP_aria_192_ecb 4190 1_1_1 EXIST::FUNCTION:ARIA +EVP_aria_128_cbc 4191 1_1_1 EXIST::FUNCTION:ARIA +EVP_aria_192_ofb 4192 1_1_1 EXIST::FUNCTION:ARIA +EVP_aria_192_cbc 4193 1_1_1 EXIST::FUNCTION:ARIA +EVP_aria_192_cfb1 4194 1_1_1 EXIST::FUNCTION:ARIA +EVP_aria_128_cfb8 4195 1_1_1 EXIST::FUNCTION:ARIA +EVP_aria_256_cfb1 4196 1_1_1 EXIST::FUNCTION:ARIA +EVP_aria_192_cfb8 4197 1_1_1 EXIST::FUNCTION:ARIA +EVP_aria_256_cfb8 4198 1_1_1 EXIST::FUNCTION:ARIA +EVP_aria_256_cbc 4199 1_1_1 EXIST::FUNCTION:ARIA +EVP_aria_128_ofb 4200 1_1_1 EXIST::FUNCTION:ARIA +EVP_aria_192_cfb128 4201 1_1_1 EXIST::FUNCTION:ARIA +EVP_aria_256_ecb 4202 1_1_1 EXIST::FUNCTION:ARIA +EVP_aria_256_ctr 4203 1_1_1 EXIST::FUNCTION:ARIA +EVP_aria_128_ctr 4204 1_1_1 EXIST::FUNCTION:ARIA +EVP_aria_192_ctr 4205 1_1_1 EXIST::FUNCTION:ARIA +UI_null 4206 1_1_1 EXIST::FUNCTION: +EC_KEY_get0_engine 4207 1_1_1 EXIST::FUNCTION:EC +INT32_it 4208 1_1_0f EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +INT32_it 4208 1_1_0f EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +UINT64_it 4209 1_1_0f EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +UINT64_it 4209 1_1_0f EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +ZINT32_it 4210 1_1_0f EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ZINT32_it 4210 1_1_0f EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +ZUINT64_it 4211 1_1_0f EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ZUINT64_it 4211 1_1_0f EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +INT64_it 4212 1_1_0f EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +INT64_it 4212 1_1_0f EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +ZUINT32_it 4213 1_1_0f EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ZUINT32_it 4213 1_1_0f EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +UINT32_it 4214 1_1_0f EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +UINT32_it 4214 1_1_0f EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +ZINT64_it 4215 1_1_0f EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ZINT64_it 4215 1_1_0f EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +CRYPTO_mem_leaks_cb 4216 1_1_1 EXIST::FUNCTION:CRYPTO_MDEBUG +BIO_lookup_ex 4217 1_1_1 EXIST::FUNCTION:SOCK +X509_CRL_print_ex 4218 1_1_1 EXIST::FUNCTION: +X509_SIG_INFO_get 4219 1_1_1 EXIST::FUNCTION: +X509_get_signature_info 4220 1_1_1 EXIST::FUNCTION: +X509_SIG_INFO_set 4221 1_1_1 EXIST::FUNCTION: +ESS_CERT_ID_V2_free 4222 1_1_1 EXIST::FUNCTION:TS +ESS_SIGNING_CERT_V2_new 4223 1_1_1 EXIST::FUNCTION:TS +d2i_ESS_SIGNING_CERT_V2 4224 1_1_1 EXIST::FUNCTION:TS +i2d_ESS_CERT_ID_V2 4225 1_1_1 EXIST::FUNCTION:TS +ESS_CERT_ID_V2_dup 4226 1_1_1 EXIST::FUNCTION:TS +TS_RESP_CTX_set_ess_cert_id_digest 4227 1_1_1 EXIST::FUNCTION:TS +d2i_ESS_CERT_ID_V2 4228 1_1_1 EXIST::FUNCTION:TS +i2d_ESS_SIGNING_CERT_V2 4229 1_1_1 EXIST::FUNCTION:TS +TS_CONF_set_ess_cert_id_digest 4230 1_1_1 EXIST::FUNCTION:TS +ESS_SIGNING_CERT_V2_free 4231 1_1_1 EXIST::FUNCTION:TS +ESS_SIGNING_CERT_V2_dup 4232 1_1_1 EXIST::FUNCTION:TS +ESS_CERT_ID_V2_new 4233 1_1_1 EXIST::FUNCTION:TS +PEM_read_bio_ex 4234 1_1_1 EXIST::FUNCTION: +PEM_bytes_read_bio_secmem 4235 1_1_1 EXIST::FUNCTION: +EVP_DigestSign 4236 1_1_1 EXIST::FUNCTION: +EVP_DigestVerify 4237 1_1_1 EXIST::FUNCTION: +UI_method_get_data_duplicator 4238 1_1_1 EXIST::FUNCTION: +UI_method_set_data_duplicator 4239 1_1_1 EXIST::FUNCTION: +UI_dup_user_data 4240 1_1_1 EXIST::FUNCTION: +UI_method_get_data_destructor 4241 1_1_1 EXIST::FUNCTION: +ERR_load_strings_const 4242 1_1_1 EXIST::FUNCTION: +ASN1_TIME_to_tm 4243 1_1_1 EXIST::FUNCTION: +ASN1_TIME_set_string_X509 4244 1_1_1 EXIST::FUNCTION: +OCSP_resp_get1_id 4245 1_1_1 EXIST::FUNCTION:OCSP +OSSL_STORE_register_loader 4246 1_1_1 EXIST::FUNCTION: +OSSL_STORE_LOADER_set_error 4247 1_1_1 EXIST::FUNCTION: +OSSL_STORE_INFO_get0_PKEY 4248 1_1_1 EXIST::FUNCTION: +OSSL_STORE_INFO_get_type 4249 1_1_1 EXIST::FUNCTION: +ERR_load_OSSL_STORE_strings 4250 1_1_1 EXIST::FUNCTION: +OSSL_STORE_LOADER_free 4251 1_1_1 EXIST::FUNCTION: +OSSL_STORE_INFO_get1_PKEY 4252 1_1_1 EXIST::FUNCTION: +OSSL_STORE_INFO_free 4253 1_1_1 EXIST::FUNCTION: +OSSL_STORE_open_file 4254 1_1_1 NOEXIST::FUNCTION: +OSSL_STORE_LOADER_set_eof 4255 1_1_1 EXIST::FUNCTION: +OSSL_STORE_LOADER_new 4256 1_1_1 EXIST::FUNCTION: +OSSL_STORE_INFO_get0_CERT 4257 1_1_1 EXIST::FUNCTION: +OSSL_STORE_LOADER_set_close 4258 1_1_1 EXIST::FUNCTION: +OSSL_STORE_INFO_new_PARAMS 4259 1_1_1 EXIST::FUNCTION: +OSSL_STORE_INFO_new_PKEY 4260 1_1_1 EXIST::FUNCTION: +OSSL_STORE_INFO_get1_PARAMS 4261 1_1_1 EXIST::FUNCTION: +OSSL_STORE_INFO_get1_CRL 4262 1_1_1 EXIST::FUNCTION: +OSSL_STORE_error 4263 1_1_1 EXIST::FUNCTION: +OSSL_STORE_INFO_get1_CERT 4264 1_1_1 EXIST::FUNCTION: +OSSL_STORE_INFO_get0_PARAMS 4265 1_1_1 EXIST::FUNCTION: +OSSL_STORE_INFO_type_string 4266 1_1_1 EXIST::FUNCTION: +OSSL_STORE_INFO_get1_NAME 4267 1_1_1 EXIST::FUNCTION: +OSSL_STORE_LOADER_set_load 4268 1_1_1 EXIST::FUNCTION: +OSSL_STORE_LOADER_get0_scheme 4269 1_1_1 EXIST::FUNCTION: +OSSL_STORE_open 4270 1_1_1 EXIST::FUNCTION: +OSSL_STORE_close 4271 1_1_1 EXIST::FUNCTION: +OSSL_STORE_INFO_new_CERT 4272 1_1_1 EXIST::FUNCTION: +OSSL_STORE_INFO_get0_CRL 4273 1_1_1 EXIST::FUNCTION: +OSSL_STORE_load 4274 1_1_1 EXIST::FUNCTION: +OSSL_STORE_INFO_get0_NAME 4275 1_1_1 EXIST::FUNCTION: +OSSL_STORE_unregister_loader 4276 1_1_1 EXIST::FUNCTION: +OSSL_STORE_INFO_new_CRL 4277 1_1_1 EXIST::FUNCTION: +OSSL_STORE_INFO_new_NAME 4278 1_1_1 EXIST::FUNCTION: +OSSL_STORE_eof 4279 1_1_1 EXIST::FUNCTION: +OSSL_STORE_LOADER_set_open 4280 1_1_1 EXIST::FUNCTION: +OSSL_STORE_LOADER_set_ctrl 4281 1_1_1 EXIST::FUNCTION: +OSSL_STORE_ctrl 4282 1_1_1 EXIST::FUNCTION: +OSSL_STORE_INFO_get0_NAME_description 4283 1_1_1 EXIST::FUNCTION: +OSSL_STORE_INFO_set0_NAME_description 4284 1_1_1 EXIST::FUNCTION: +OSSL_STORE_INFO_get1_NAME_description 4285 1_1_1 EXIST::FUNCTION: +OSSL_STORE_do_all_loaders 4286 1_1_1 EXIST::FUNCTION: +OSSL_STORE_LOADER_get0_engine 4287 1_1_1 EXIST::FUNCTION: +OPENSSL_fork_prepare 4288 1_1_1 EXIST:UNIX:FUNCTION: +OPENSSL_fork_parent 4289 1_1_1 EXIST:UNIX:FUNCTION: +OPENSSL_fork_child 4290 1_1_1 EXIST:UNIX:FUNCTION: +RAND_DRBG_instantiate 4292 1_1_1 EXIST::FUNCTION: +RAND_DRBG_uninstantiate 4293 1_1_1 EXIST::FUNCTION: +RAND_DRBG_set 4295 1_1_1 EXIST::FUNCTION: +RAND_DRBG_set_callbacks 4296 1_1_1 EXIST::FUNCTION: +RAND_DRBG_new 4297 1_1_1 EXIST::FUNCTION: +RAND_DRBG_set_reseed_interval 4298 1_1_1 EXIST::FUNCTION: +RAND_DRBG_free 4299 1_1_1 EXIST::FUNCTION: +RAND_DRBG_generate 4300 1_1_1 EXIST::FUNCTION: +RAND_DRBG_reseed 4301 1_1_1 EXIST::FUNCTION: +RAND_DRBG_set_ex_data 4302 1_1_1 EXIST::FUNCTION: +RAND_DRBG_get_ex_data 4303 1_1_1 EXIST::FUNCTION: +EVP_sha3_224 4304 1_1_1 EXIST::FUNCTION: +EVP_sha3_256 4305 1_1_1 EXIST::FUNCTION: +EVP_sha3_384 4306 1_1_1 EXIST::FUNCTION: +EVP_sha3_512 4307 1_1_1 EXIST::FUNCTION: +EVP_shake128 4308 1_1_1 EXIST::FUNCTION: +EVP_shake256 4309 1_1_1 EXIST::FUNCTION: +SCRYPT_PARAMS_new 4310 1_1_1 EXIST::FUNCTION:SCRYPT +SCRYPT_PARAMS_free 4311 1_1_1 EXIST::FUNCTION:SCRYPT +i2d_SCRYPT_PARAMS 4312 1_1_1 EXIST::FUNCTION:SCRYPT +d2i_SCRYPT_PARAMS 4313 1_1_1 EXIST::FUNCTION:SCRYPT +SCRYPT_PARAMS_it 4314 1_1_1 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:SCRYPT +SCRYPT_PARAMS_it 4314 1_1_1 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:SCRYPT +CRYPTO_secure_clear_free 4315 1_1_0g EXIST::FUNCTION: +EVP_PKEY_meth_get0 4316 1_1_1 EXIST::FUNCTION: +EVP_PKEY_meth_get_count 4317 1_1_1 EXIST::FUNCTION: +RAND_DRBG_get0_public 4319 1_1_1 EXIST::FUNCTION: +RAND_priv_bytes 4320 1_1_1 EXIST::FUNCTION: +BN_priv_rand 4321 1_1_1 EXIST::FUNCTION: +BN_priv_rand_range 4322 1_1_1 EXIST::FUNCTION: +ASN1_TIME_normalize 4323 1_1_1 EXIST::FUNCTION: +ASN1_TIME_cmp_time_t 4324 1_1_1 EXIST::FUNCTION: +ASN1_TIME_compare 4325 1_1_1 EXIST::FUNCTION: +EVP_PKEY_CTX_ctrl_uint64 4326 1_1_1 EXIST::FUNCTION: +EVP_DigestFinalXOF 4327 1_1_1 EXIST::FUNCTION: +ERR_clear_last_mark 4328 1_1_1 EXIST::FUNCTION: +RAND_DRBG_get0_private 4329 1_1_1 EXIST::FUNCTION: +EVP_aria_192_ccm 4330 1_1_1 EXIST::FUNCTION:ARIA +EVP_aria_256_gcm 4331 1_1_1 EXIST::FUNCTION:ARIA +EVP_aria_256_ccm 4332 1_1_1 EXIST::FUNCTION:ARIA +EVP_aria_128_gcm 4333 1_1_1 EXIST::FUNCTION:ARIA +EVP_aria_128_ccm 4334 1_1_1 EXIST::FUNCTION:ARIA +EVP_aria_192_gcm 4335 1_1_1 EXIST::FUNCTION:ARIA +UI_get_result_length 4337 1_1_1 EXIST::FUNCTION: +UI_set_result_ex 4338 1_1_1 EXIST::FUNCTION: +UI_get_result_string_length 4339 1_1_1 EXIST::FUNCTION: +EVP_PKEY_check 4340 1_1_1 EXIST::FUNCTION: +EVP_PKEY_meth_set_check 4341 1_1_1 EXIST::FUNCTION: +EVP_PKEY_meth_get_check 4342 1_1_1 EXIST::FUNCTION: +EVP_PKEY_meth_remove 4343 1_1_1 EXIST::FUNCTION: +OPENSSL_sk_reserve 4344 1_1_1 EXIST::FUNCTION: +EVP_PKEY_set1_engine 4347 1_1_0g EXIST::FUNCTION:ENGINE +DH_new_by_nid 4348 1_1_1 EXIST::FUNCTION:DH +DH_get_nid 4349 1_1_1 EXIST::FUNCTION:DH +CRYPTO_get_alloc_counts 4350 1_1_1 EXIST::FUNCTION:CRYPTO_MDEBUG +OPENSSL_sk_new_reserve 4351 1_1_1 EXIST::FUNCTION: +EVP_PKEY_asn1_set_check 4352 1_1_1 EXIST::FUNCTION: +EVP_PKEY_asn1_set_siginf 4353 1_1_1 EXIST::FUNCTION: +EVP_sm4_ctr 4354 1_1_1 EXIST::FUNCTION:SM4 +EVP_sm4_cbc 4355 1_1_1 EXIST::FUNCTION:SM4 +EVP_sm4_ofb 4356 1_1_1 EXIST::FUNCTION:SM4 +EVP_sm4_ecb 4357 1_1_1 EXIST::FUNCTION:SM4 +EVP_sm4_cfb128 4358 1_1_1 EXIST::FUNCTION:SM4 +EVP_sm3 4359 1_1_1 EXIST::FUNCTION:SM3 +RSA_get0_multi_prime_factors 4360 1_1_1 EXIST::FUNCTION:RSA +EVP_PKEY_public_check 4361 1_1_1 EXIST::FUNCTION: +EVP_PKEY_param_check 4362 1_1_1 EXIST::FUNCTION: +EVP_PKEY_meth_set_public_check 4363 1_1_1 EXIST::FUNCTION: +EVP_PKEY_meth_set_param_check 4364 1_1_1 EXIST::FUNCTION: +EVP_PKEY_meth_get_public_check 4365 1_1_1 EXIST::FUNCTION: +EVP_PKEY_meth_get_param_check 4366 1_1_1 EXIST::FUNCTION: +EVP_PKEY_asn1_set_public_check 4367 1_1_1 EXIST::FUNCTION: +EVP_PKEY_asn1_set_param_check 4368 1_1_1 EXIST::FUNCTION: +DH_check_ex 4369 1_1_1 EXIST::FUNCTION:DH +DH_check_pub_key_ex 4370 1_1_1 EXIST::FUNCTION:DH +DH_check_params_ex 4371 1_1_1 EXIST::FUNCTION:DH +RSA_generate_multi_prime_key 4372 1_1_1 EXIST::FUNCTION:RSA +RSA_get_multi_prime_extra_count 4373 1_1_1 EXIST::FUNCTION:RSA +OCSP_resp_get0_signer 4374 1_1_0h EXIST::FUNCTION:OCSP +RSA_get0_multi_prime_crt_params 4375 1_1_1 EXIST::FUNCTION:RSA +RSA_set0_multi_prime_params 4376 1_1_1 EXIST::FUNCTION:RSA +RSA_get_version 4377 1_1_1 EXIST::FUNCTION:RSA +RSA_meth_get_multi_prime_keygen 4378 1_1_1 EXIST::FUNCTION:RSA +RSA_meth_set_multi_prime_keygen 4379 1_1_1 EXIST::FUNCTION:RSA +RAND_DRBG_get0_master 4380 1_1_1 EXIST::FUNCTION: +RAND_DRBG_set_reseed_time_interval 4381 1_1_1 EXIST::FUNCTION: +PROFESSION_INFO_get0_addProfessionInfo 4382 1_1_1 EXIST::FUNCTION: +ADMISSION_SYNTAX_free 4383 1_1_1 EXIST::FUNCTION: +d2i_ADMISSION_SYNTAX 4384 1_1_1 EXIST::FUNCTION: +NAMING_AUTHORITY_set0_authorityId 4385 1_1_1 EXIST::FUNCTION: +NAMING_AUTHORITY_set0_authorityURL 4386 1_1_1 EXIST::FUNCTION: +d2i_PROFESSION_INFO 4387 1_1_1 EXIST::FUNCTION: +NAMING_AUTHORITY_it 4388 1_1_1 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +NAMING_AUTHORITY_it 4388 1_1_1 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +ADMISSION_SYNTAX_get0_contentsOfAdmissions 4389 1_1_1 EXIST::FUNCTION: +PROFESSION_INFO_set0_professionItems 4390 1_1_1 EXIST::FUNCTION: +NAMING_AUTHORITY_new 4391 1_1_1 EXIST::FUNCTION: +NAMING_AUTHORITY_get0_authorityURL 4392 1_1_1 EXIST::FUNCTION: +ADMISSION_SYNTAX_get0_admissionAuthority 4393 1_1_1 EXIST::FUNCTION: +PROFESSION_INFO_new 4394 1_1_1 EXIST::FUNCTION: +ADMISSIONS_new 4395 1_1_1 EXIST::FUNCTION: +ADMISSION_SYNTAX_set0_admissionAuthority 4396 1_1_1 EXIST::FUNCTION: +PROFESSION_INFO_get0_professionOIDs 4397 1_1_1 EXIST::FUNCTION: +PROFESSION_INFO_it 4398 1_1_1 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +PROFESSION_INFO_it 4398 1_1_1 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +i2d_PROFESSION_INFO 4399 1_1_1 EXIST::FUNCTION: +ADMISSIONS_set0_professionInfos 4400 1_1_1 EXIST::FUNCTION: +PROFESSION_INFO_get0_namingAuthority 4401 1_1_1 EXIST::FUNCTION: +PROFESSION_INFO_free 4402 1_1_1 EXIST::FUNCTION: +PROFESSION_INFO_set0_addProfessionInfo 4403 1_1_1 EXIST::FUNCTION: +PROFESSION_INFO_set0_registrationNumber 4404 1_1_1 EXIST::FUNCTION: +ADMISSION_SYNTAX_set0_contentsOfAdmissions 4405 1_1_1 EXIST::FUNCTION: +NAMING_AUTHORITY_get0_authorityId 4406 1_1_1 EXIST::FUNCTION: +ADMISSION_SYNTAX_it 4407 1_1_1 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ADMISSION_SYNTAX_it 4407 1_1_1 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +i2d_ADMISSION_SYNTAX 4408 1_1_1 EXIST::FUNCTION: +NAMING_AUTHORITY_get0_authorityText 4409 1_1_1 EXIST::FUNCTION: +PROFESSION_INFO_set0_namingAuthority 4410 1_1_1 EXIST::FUNCTION: +i2d_NAMING_AUTHORITY 4411 1_1_1 EXIST::FUNCTION: +NAMING_AUTHORITY_free 4412 1_1_1 EXIST::FUNCTION: +ADMISSIONS_set0_admissionAuthority 4413 1_1_1 EXIST::FUNCTION: +ADMISSIONS_free 4414 1_1_1 EXIST::FUNCTION: +PROFESSION_INFO_get0_registrationNumber 4415 1_1_1 EXIST::FUNCTION: +d2i_ADMISSIONS 4416 1_1_1 EXIST::FUNCTION: +i2d_ADMISSIONS 4417 1_1_1 EXIST::FUNCTION: +PROFESSION_INFO_get0_professionItems 4418 1_1_1 EXIST::FUNCTION: +ADMISSIONS_get0_admissionAuthority 4419 1_1_1 EXIST::FUNCTION: +PROFESSION_INFO_set0_professionOIDs 4420 1_1_1 EXIST::FUNCTION: +d2i_NAMING_AUTHORITY 4421 1_1_1 EXIST::FUNCTION: +ADMISSIONS_it 4422 1_1_1 EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE: +ADMISSIONS_it 4422 1_1_1 EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION: +ADMISSIONS_get0_namingAuthority 4423 1_1_1 EXIST::FUNCTION: +NAMING_AUTHORITY_set0_authorityText 4424 1_1_1 EXIST::FUNCTION: +ADMISSIONS_set0_namingAuthority 4425 1_1_1 EXIST::FUNCTION: +ADMISSIONS_get0_professionInfos 4426 1_1_1 EXIST::FUNCTION: +ADMISSION_SYNTAX_new 4427 1_1_1 EXIST::FUNCTION: +EVP_sha512_256 4428 1_1_1 EXIST::FUNCTION: +EVP_sha512_224 4429 1_1_1 EXIST::FUNCTION: +OCSP_basic_sign_ctx 4430 1_1_1 EXIST::FUNCTION:OCSP +RAND_DRBG_bytes 4431 1_1_1 EXIST::FUNCTION: +RAND_DRBG_secure_new 4432 1_1_1 EXIST::FUNCTION: +OSSL_STORE_vctrl 4433 1_1_1 EXIST::FUNCTION: +OSSL_STORE_SEARCH_by_alias 4434 1_1_1 EXIST::FUNCTION: +BIO_bind 4435 1_1_1 EXIST::FUNCTION:SOCK +OSSL_STORE_LOADER_set_expect 4436 1_1_1 EXIST::FUNCTION: +OSSL_STORE_expect 4437 1_1_1 EXIST::FUNCTION: +OSSL_STORE_SEARCH_by_key_fingerprint 4438 1_1_1 EXIST::FUNCTION: +OSSL_STORE_SEARCH_get0_serial 4439 1_1_1 EXIST::FUNCTION: +OSSL_STORE_SEARCH_by_name 4440 1_1_1 EXIST::FUNCTION: +OSSL_STORE_supports_search 4441 1_1_1 EXIST::FUNCTION: +OSSL_STORE_find 4442 1_1_1 EXIST::FUNCTION: +OSSL_STORE_SEARCH_get_type 4443 1_1_1 EXIST::FUNCTION: +OSSL_STORE_SEARCH_get0_bytes 4444 1_1_1 EXIST::FUNCTION: +OSSL_STORE_SEARCH_get0_string 4445 1_1_1 EXIST::FUNCTION: +OSSL_STORE_SEARCH_by_issuer_serial 4446 1_1_1 EXIST::FUNCTION: +OSSL_STORE_SEARCH_get0_name 4447 1_1_1 EXIST::FUNCTION: +X509_get0_authority_key_id 4448 1_1_0h EXIST::FUNCTION: +OSSL_STORE_LOADER_set_find 4449 1_1_1 EXIST::FUNCTION: +OSSL_STORE_SEARCH_free 4450 1_1_1 EXIST::FUNCTION: +OSSL_STORE_SEARCH_get0_digest 4451 1_1_1 EXIST::FUNCTION: +RAND_DRBG_set_reseed_defaults 4452 1_1_1 EXIST::FUNCTION: +EVP_PKEY_new_raw_private_key 4453 1_1_1 EXIST::FUNCTION: +EVP_PKEY_new_raw_public_key 4454 1_1_1 EXIST::FUNCTION: +EVP_PKEY_new_CMAC_key 4455 1_1_1 EXIST::FUNCTION: +EVP_PKEY_asn1_set_set_priv_key 4456 1_1_1 EXIST::FUNCTION: +EVP_PKEY_asn1_set_set_pub_key 4457 1_1_1 EXIST::FUNCTION: +RAND_DRBG_set_defaults 4458 1_1_1 EXIST::FUNCTION: +conf_ssl_name_find 4469 1_1_0i EXIST::FUNCTION: +conf_ssl_get_cmd 4470 1_1_0i EXIST::FUNCTION: +conf_ssl_get 4471 1_1_0i EXIST::FUNCTION: +X509_VERIFY_PARAM_get_hostflags 4472 1_1_0i EXIST::FUNCTION: +DH_get0_p 4473 1_1_1 EXIST::FUNCTION:DH +DH_get0_q 4474 1_1_1 EXIST::FUNCTION:DH +DH_get0_g 4475 1_1_1 EXIST::FUNCTION:DH +DH_get0_priv_key 4476 1_1_1 EXIST::FUNCTION:DH +DH_get0_pub_key 4477 1_1_1 EXIST::FUNCTION:DH +DSA_get0_priv_key 4478 1_1_1 EXIST::FUNCTION:DSA +DSA_get0_pub_key 4479 1_1_1 EXIST::FUNCTION:DSA +DSA_get0_q 4480 1_1_1 EXIST::FUNCTION:DSA +DSA_get0_p 4481 1_1_1 EXIST::FUNCTION:DSA +DSA_get0_g 4482 1_1_1 EXIST::FUNCTION:DSA +RSA_get0_dmp1 4483 1_1_1 EXIST::FUNCTION:RSA +RSA_get0_d 4484 1_1_1 EXIST::FUNCTION:RSA +RSA_get0_n 4485 1_1_1 EXIST::FUNCTION:RSA +RSA_get0_dmq1 4486 1_1_1 EXIST::FUNCTION:RSA +RSA_get0_e 4487 1_1_1 EXIST::FUNCTION:RSA +RSA_get0_q 4488 1_1_1 EXIST::FUNCTION:RSA +RSA_get0_p 4489 1_1_1 EXIST::FUNCTION:RSA +RSA_get0_iqmp 4490 1_1_1 EXIST::FUNCTION:RSA +ECDSA_SIG_get0_r 4491 1_1_1 EXIST::FUNCTION:EC +ECDSA_SIG_get0_s 4492 1_1_1 EXIST::FUNCTION:EC +X509_LOOKUP_meth_get_get_by_fingerprint 4493 1_1_0i EXIST::FUNCTION: +X509_LOOKUP_meth_new 4494 1_1_0i EXIST::FUNCTION: +X509_LOOKUP_meth_get_init 4495 1_1_0i EXIST::FUNCTION: +X509_LOOKUP_meth_get_get_by_alias 4496 1_1_0i EXIST::FUNCTION: +X509_LOOKUP_meth_set_new_item 4497 1_1_0i EXIST::FUNCTION: +X509_LOOKUP_meth_set_shutdown 4498 1_1_0i EXIST::FUNCTION: +X509_LOOKUP_meth_get_new_item 4499 1_1_0i EXIST::FUNCTION: +X509_LOOKUP_meth_set_ctrl 4500 1_1_0i EXIST::FUNCTION: +X509_LOOKUP_meth_set_get_by_issuer_serial 4501 1_1_0i EXIST::FUNCTION: +X509_LOOKUP_get_store 4502 1_1_0i EXIST::FUNCTION: +X509_LOOKUP_meth_get_ctrl 4503 1_1_0i EXIST::FUNCTION: +X509_LOOKUP_meth_set_get_by_alias 4504 1_1_0i EXIST::FUNCTION: +X509_LOOKUP_meth_get_get_by_subject 4505 1_1_0i EXIST::FUNCTION: +X509_LOOKUP_meth_get_free 4506 1_1_0i EXIST::FUNCTION: +X509_LOOKUP_meth_set_get_by_subject 4507 1_1_0i EXIST::FUNCTION: +X509_LOOKUP_meth_set_free 4508 1_1_0i EXIST::FUNCTION: +X509_LOOKUP_meth_get_shutdown 4509 1_1_0i EXIST::FUNCTION: +X509_LOOKUP_set_method_data 4510 1_1_0i EXIST::FUNCTION: +X509_LOOKUP_get_method_data 4511 1_1_0i EXIST::FUNCTION: +X509_LOOKUP_meth_set_get_by_fingerprint 4512 1_1_0i EXIST::FUNCTION: +X509_LOOKUP_meth_free 4513 1_1_0i EXIST::FUNCTION: +X509_OBJECT_set1_X509 4514 1_1_0i EXIST::FUNCTION: +X509_LOOKUP_meth_get_get_by_issuer_serial 4515 1_1_0i EXIST::FUNCTION: +X509_LOOKUP_meth_set_init 4516 1_1_0i EXIST::FUNCTION: +X509_OBJECT_set1_X509_CRL 4517 1_1_0i EXIST::FUNCTION: +EVP_PKEY_get_raw_public_key 4518 1_1_1 EXIST::FUNCTION: +EVP_PKEY_get_raw_private_key 4519 1_1_1 EXIST::FUNCTION: +EVP_PKEY_asn1_set_get_priv_key 4520 1_1_1 EXIST::FUNCTION: +EVP_PKEY_asn1_set_get_pub_key 4521 1_1_1 EXIST::FUNCTION: +EVP_PKEY_set_alias_type 4522 1_1_1 EXIST::FUNCTION: +RAND_keep_random_devices_open 4523 1_1_1 EXIST::FUNCTION: +EC_POINT_set_compressed_coordinates 4524 1_1_1 EXIST::FUNCTION:EC +EC_POINT_set_affine_coordinates 4525 1_1_1 EXIST::FUNCTION:EC +EC_POINT_get_affine_coordinates 4526 1_1_1 EXIST::FUNCTION:EC +EC_GROUP_set_curve 4527 1_1_1 EXIST::FUNCTION:EC +EC_GROUP_get_curve 4528 1_1_1 EXIST::FUNCTION:EC +OCSP_resp_get0_tbs_sigalg 4529 1_1_0j EXIST::FUNCTION:OCSP +OCSP_resp_get0_respdata 4530 1_1_0j EXIST::FUNCTION:OCSP +EVP_MD_CTX_set_pkey_ctx 4531 1_1_1 EXIST::FUNCTION: +EVP_PKEY_meth_set_digest_custom 4532 1_1_1 EXIST::FUNCTION: +EVP_PKEY_meth_get_digest_custom 4533 1_1_1 EXIST::FUNCTION: +OPENSSL_INIT_set_config_filename 4534 1_1_1b EXIST::FUNCTION:STDIO +OPENSSL_INIT_set_config_file_flags 4535 1_1_1b EXIST::FUNCTION:STDIO diff --git a/trunk/3rdparty/openssl-1.1-fit/util/libssl.num b/trunk/3rdparty/openssl-1.1-fit/util/libssl.num new file mode 100644 index 000000000..297522c36 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/libssl.num @@ -0,0 +1,500 @@ +SSL_get_selected_srtp_profile 1 1_1_0 EXIST::FUNCTION:SRTP +SSL_set_read_ahead 2 1_1_0 EXIST::FUNCTION: +SSL_set_accept_state 3 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_cipher_list 4 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_srp_client_pwd_callback 5 1_1_0 EXIST::FUNCTION:SRP +SSL_copy_session_id 6 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_srp_password 7 1_1_0 EXIST::FUNCTION:SRP +SSL_shutdown 8 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_msg_callback 9 1_1_0 EXIST::FUNCTION: +SSL_SESSION_get0_ticket 11 1_1_0 EXIST::FUNCTION: +SSL_get1_supported_ciphers 12 1_1_0 EXIST::FUNCTION: +SSL_state_string_long 13 1_1_0 EXIST::FUNCTION: +SSL_CTX_get0_certificate 14 1_1_0 EXIST::FUNCTION: +SSL_SESSION_set_ex_data 15 1_1_0 EXIST::FUNCTION: +SSL_get_verify_depth 16 1_1_0 EXIST::FUNCTION: +SSL_get0_dane 17 1_1_0 EXIST::FUNCTION: +SSL_CTX_sess_get_get_cb 18 1_1_0 EXIST::FUNCTION: +SSL_CTX_get_default_passwd_cb_userdata 19 1_1_0 EXIST::FUNCTION: +SSL_set_tmp_dh_callback 20 1_1_0 EXIST::FUNCTION:DH +SSL_CTX_get_verify_depth 21 1_1_0 EXIST::FUNCTION: +SSL_CTX_use_RSAPrivateKey_file 22 1_1_0 EXIST::FUNCTION:RSA +SSL_use_PrivateKey_file 23 1_1_0 EXIST::FUNCTION: +SSL_set_generate_session_id 24 1_1_0 EXIST::FUNCTION: +SSL_get_ex_data_X509_STORE_CTX_idx 25 1_1_0 EXIST::FUNCTION: +SSL_get_quiet_shutdown 26 1_1_0 EXIST::FUNCTION: +SSL_dane_enable 27 1_1_0 EXIST::FUNCTION: +SSL_COMP_add_compression_method 28 1_1_0 EXIST::FUNCTION: +SSL_CTX_use_RSAPrivateKey 29 1_1_0 EXIST::FUNCTION:RSA +SSL_CTX_sess_get_new_cb 30 1_1_0 EXIST::FUNCTION: +d2i_SSL_SESSION 31 1_1_0 EXIST::FUNCTION: +SSL_use_PrivateKey_ASN1 32 1_1_0 EXIST::FUNCTION: +PEM_write_SSL_SESSION 33 1_1_0 EXIST::FUNCTION:STDIO +SSL_CTX_set_session_id_context 34 1_1_0 EXIST::FUNCTION: +SSL_CIPHER_get_cipher_nid 35 1_1_0 EXIST::FUNCTION: +SSL_get_srp_g 36 1_1_0 EXIST::FUNCTION:SRP +SSL_want 37 1_1_0 EXIST::FUNCTION: +SSL_get_cipher_list 38 1_1_0 EXIST::FUNCTION: +SSL_get_verify_result 39 1_1_0 EXIST::FUNCTION: +SSL_renegotiate 40 1_1_0 EXIST::FUNCTION: +SSL_get_privatekey 41 1_1_0 EXIST::FUNCTION: +SSL_peek 42 1_1_0 EXIST::FUNCTION: +SRP_Calc_A_param 43 1_1_0 EXIST::FUNCTION:SRP +SSL_SESSION_get_ticket_lifetime_hint 44 1_1_0 EXIST::FUNCTION: +SSL_SRP_CTX_free 45 1_1_0 EXIST::FUNCTION:SRP +SSL_CTX_set_client_CA_list 46 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_next_proto_select_cb 47 1_1_0 EXIST::FUNCTION:NEXTPROTONEG +BIO_ssl_copy_session_id 48 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_security_callback 49 1_1_0 EXIST::FUNCTION: +SSL_CONF_cmd_value_type 50 1_1_0 EXIST::FUNCTION: +SSL_CTX_remove_session 51 1_1_0 EXIST::FUNCTION: +SSL_SESSION_new 52 1_1_0 EXIST::FUNCTION: +TLSv1_2_server_method 53 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0,TLS1_2_METHOD +BIO_new_buffer_ssl_connect 54 1_1_0 EXIST::FUNCTION: +SSL_CTX_set0_security_ex_data 55 1_1_0 EXIST::FUNCTION: +SSL_alert_desc_string 56 1_1_0 EXIST::FUNCTION: +SSL_get0_dane_authority 57 1_1_0 EXIST::FUNCTION: +SSL_set_purpose 58 1_1_0 EXIST::FUNCTION: +SSL_CTX_use_PrivateKey_file 59 1_1_0 EXIST::FUNCTION: +SSL_get_rfd 60 1_1_0 EXIST::FUNCTION: +DTLSv1_listen 61 1_1_0 EXIST::FUNCTION:SOCK +SSL_set_ssl_method 62 1_1_0 EXIST::FUNCTION: +SSL_get0_security_ex_data 63 1_1_0 EXIST::FUNCTION: +SSLv3_client_method 64 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0,SSL3_METHOD +SSL_set_security_level 65 1_1_0 EXIST::FUNCTION: +DTLSv1_2_method 66 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0,DTLS1_2_METHOD +SSL_get_fd 67 1_1_0 EXIST::FUNCTION: +SSL_get1_session 68 1_1_0 EXIST::FUNCTION: +SSL_use_RSAPrivateKey 69 1_1_0 EXIST::FUNCTION:RSA +SSL_CTX_set_srp_cb_arg 70 1_1_0 EXIST::FUNCTION:SRP +SSL_CTX_add_session 71 1_1_0 EXIST::FUNCTION: +SSL_get_srp_N 72 1_1_0 EXIST::FUNCTION:SRP +SSL_has_matching_session_id 73 1_1_0 EXIST::FUNCTION: +PEM_read_SSL_SESSION 74 1_1_0 EXIST::FUNCTION:STDIO +SSL_get_shared_ciphers 75 1_1_0 EXIST::FUNCTION: +SSL_add1_host 76 1_1_0 EXIST::FUNCTION: +SSL_CONF_cmd_argv 77 1_1_0 EXIST::FUNCTION: +SSL_version 78 1_1_0 EXIST::FUNCTION: +SSL_SESSION_print 79 1_1_0 EXIST::FUNCTION: +SSL_get_client_ciphers 80 1_1_0 EXIST::FUNCTION: +SSL_get_srtp_profiles 81 1_1_0 EXIST::FUNCTION:SRTP +SSL_use_certificate_ASN1 82 1_1_0 EXIST::FUNCTION: +SSL_get_peer_certificate 83 1_1_0 EXIST::FUNCTION: +DTLSv1_2_server_method 84 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0,DTLS1_2_METHOD +SSL_set_cert_cb 85 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_cookie_verify_cb 86 1_1_0 EXIST::FUNCTION: +SSL_get_shared_sigalgs 87 1_1_0 EXIST::FUNCTION: +SSL_config 88 1_1_0 EXIST::FUNCTION: +TLSv1_1_client_method 89 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0,TLS1_1_METHOD +SSL_CIPHER_standard_name 90 1_1_0 EXIST::FUNCTION: +SSL_CTX_get_verify_mode 91 1_1_0 EXIST::FUNCTION: +SSL_get_all_async_fds 92 1_1_0 EXIST::FUNCTION: +SSL_CTX_check_private_key 93 1_1_0 EXIST::FUNCTION: +SSL_set_wfd 94 1_1_0 EXIST::FUNCTION:SOCK +SSL_get_client_CA_list 95 1_1_0 EXIST::FUNCTION: +SSL_CONF_CTX_set_flags 96 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_srp_username_callback 97 1_1_0 EXIST::FUNCTION:SRP +SSL_connect 98 1_1_0 EXIST::FUNCTION: +SSL_get_psk_identity 99 1_1_0 EXIST::FUNCTION:PSK +SSL_CTX_use_certificate_file 100 1_1_0 EXIST::FUNCTION: +SSL_set_session_ticket_ext 101 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_psk_server_callback 102 1_1_0 EXIST::FUNCTION:PSK +SSL_get_sigalgs 103 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_next_protos_advertised_cb 104 1_1_0 EXIST::FUNCTION:NEXTPROTONEG +SSL_CTX_set_trust 105 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_verify 106 1_1_0 EXIST::FUNCTION: +SSL_set_rfd 107 1_1_0 EXIST::FUNCTION:SOCK +SSL_SESSION_set_timeout 108 1_1_0 EXIST::FUNCTION: +SSL_set_psk_client_callback 109 1_1_0 EXIST::FUNCTION:PSK +SSL_get_client_random 110 1_1_0 EXIST::FUNCTION: +TLS_method 111 1_1_0 EXIST::FUNCTION: +SSL_CONF_CTX_clear_flags 112 1_1_0 EXIST::FUNCTION: +TLSv1_client_method 113 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0,TLS1_METHOD +SSL_CIPHER_get_bits 114 1_1_0 EXIST::FUNCTION: +SSL_test_functions 115 1_1_0 EXIST::FUNCTION:UNIT_TEST +SSL_get_SSL_CTX 116 1_1_0 EXIST::FUNCTION: +SSL_get_session 117 1_1_0 EXIST::FUNCTION: +SSL_CTX_callback_ctrl 118 1_1_0 EXIST::FUNCTION: +SSL_get_finished 119 1_1_0 EXIST::FUNCTION: +SSL_add_dir_cert_subjects_to_stack 120 1_1_0 EXIST::FUNCTION: +SSL_get_state 121 1_1_0 EXIST::FUNCTION: +SSL_CONF_CTX_finish 122 1_1_0 EXIST::FUNCTION: +SSL_CTX_add_server_custom_ext 123 1_1_0 EXIST::FUNCTION: +SSL_SESSION_get_ex_data 124 1_1_0 EXIST::FUNCTION: +SSL_get_srp_username 125 1_1_0 EXIST::FUNCTION:SRP +SSL_CTX_set_purpose 126 1_1_0 EXIST::FUNCTION: +SSL_clear 127 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_cert_store 128 1_1_0 EXIST::FUNCTION: +TLSv1_2_method 129 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0,TLS1_2_METHOD +SSL_session_reused 130 1_1_0 EXIST::FUNCTION: +SSL_free 131 1_1_0 EXIST::FUNCTION: +BIO_ssl_shutdown 132 1_1_0 EXIST::FUNCTION: +SSL_CTX_get_client_CA_list 133 1_1_0 EXIST::FUNCTION: +SSL_CTX_sessions 134 1_1_0 EXIST::FUNCTION: +SSL_get_options 135 1_1_0 EXIST::FUNCTION: +SSL_set_verify_depth 136 1_1_0 EXIST::FUNCTION: +SSL_get_error 137 1_1_0 EXIST::FUNCTION: +SSL_get_servername 138 1_1_0 EXIST::FUNCTION: +SSL_get_version 139 1_1_0 EXIST::FUNCTION: +SSL_state_string 140 1_1_0 EXIST::FUNCTION: +SSL_SESSION_get_timeout 141 1_1_0 EXIST::FUNCTION: +SSL_CTX_sess_get_remove_cb 142 1_1_0 EXIST::FUNCTION: +SSL_get_current_cipher 143 1_1_0 EXIST::FUNCTION: +SSL_up_ref 144 1_1_0 EXIST::FUNCTION: +SSL_export_keying_material 145 1_1_0 EXIST::FUNCTION: +SSL_callback_ctrl 146 1_1_0 EXIST::FUNCTION: +SSL_set_security_callback 147 1_1_0 EXIST::FUNCTION: +SSL_SRP_CTX_init 148 1_1_0 EXIST::FUNCTION:SRP +ERR_load_SSL_strings 149 1_1_0 EXIST::FUNCTION: +SSL_CTX_SRP_CTX_init 150 1_1_0 EXIST::FUNCTION:SRP +SSL_SESSION_set_time 151 1_1_0 EXIST::FUNCTION: +i2d_SSL_SESSION 152 1_1_0 EXIST::FUNCTION: +SSL_SESSION_get_master_key 153 1_1_0 EXIST::FUNCTION: +SSL_COMP_get_compression_methods 154 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_alpn_select_cb 155 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_tmp_dh_callback 156 1_1_0 EXIST::FUNCTION:DH +SSL_CTX_get_default_passwd_cb 157 1_1_0 EXIST::FUNCTION: +TLSv1_server_method 158 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0,TLS1_METHOD +DTLS_server_method 159 1_1_0 EXIST::FUNCTION: +SSL_set0_rbio 160 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_options 161 1_1_0 EXIST::FUNCTION: +SSL_set_msg_callback 162 1_1_0 EXIST::FUNCTION: +SSL_CONF_CTX_free 163 1_1_0 EXIST::FUNCTION: +SSL_CTX_get_ssl_method 164 1_1_0 EXIST::FUNCTION: +SSL_get_server_random 165 1_1_0 EXIST::FUNCTION: +SSL_set_shutdown 166 1_1_0 EXIST::FUNCTION: +SSL_CTX_add_client_CA 167 1_1_0 EXIST::FUNCTION: +TLSv1_1_server_method 168 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0,TLS1_1_METHOD +PEM_write_bio_SSL_SESSION 169 1_1_0 EXIST::FUNCTION: +SSL_write 170 1_1_0 EXIST::FUNCTION: +SSL_set1_host 171 1_1_0 EXIST::FUNCTION: +SSL_use_RSAPrivateKey_file 172 1_1_0 EXIST::FUNCTION:RSA +SSL_CTX_get_info_callback 173 1_1_0 EXIST::FUNCTION: +SSL_get0_peername 174 1_1_0 EXIST::FUNCTION: +SSL_set_srp_server_param 175 1_1_0 EXIST::FUNCTION:SRP +TLS_server_method 176 1_1_0 EXIST::FUNCTION: +SSL_get_psk_identity_hint 177 1_1_0 EXIST::FUNCTION:PSK +SSL_set_session 178 1_1_0 EXIST::FUNCTION: +SSL_get0_param 179 1_1_0 EXIST::FUNCTION: +SSL_set_default_passwd_cb 180 1_1_0 EXIST::FUNCTION: +SSL_get_read_ahead 181 1_1_0 EXIST::FUNCTION: +SSL_dup_CA_list 182 1_1_0 EXIST::FUNCTION: +SSL_get_verify_callback 183 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_default_passwd_cb 184 1_1_0 EXIST::FUNCTION: +SSL_get_servername_type 185 1_1_0 EXIST::FUNCTION: +TLSv1_2_client_method 186 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0,TLS1_2_METHOD +SSL_add_client_CA 187 1_1_0 EXIST::FUNCTION: +SSL_CTX_get0_security_ex_data 188 1_1_0 EXIST::FUNCTION: +SSL_get_ex_data 189 1_1_0 EXIST::FUNCTION: +SSL_CTX_flush_sessions 190 1_1_0 EXIST::FUNCTION: +SSL_use_PrivateKey 191 1_1_0 EXIST::FUNCTION: +DTLSv1_client_method 192 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0,DTLS1_METHOD +SSL_CTX_dane_mtype_set 193 1_1_0 EXIST::FUNCTION: +SSL_get_wfd 194 1_1_0 EXIST::FUNCTION: +SSL_get_ssl_method 195 1_1_0 EXIST::FUNCTION: +SSL_set_verify_result 196 1_1_0 EXIST::FUNCTION: +SSL_use_RSAPrivateKey_ASN1 197 1_1_0 EXIST::FUNCTION:RSA +SSL_CIPHER_get_name 198 1_1_0 EXIST::FUNCTION: +OPENSSL_init_ssl 199 1_1_0 EXIST::FUNCTION: +SSL_dup 200 1_1_0 EXIST::FUNCTION: +SSL_CTX_use_serverinfo 201 1_1_0 EXIST::FUNCTION: +SSL_CTX_use_serverinfo_file 202 1_1_0 EXIST::FUNCTION: +SSL_set_options 203 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_default_verify_dir 204 1_1_0 EXIST::FUNCTION: +SSL_do_handshake 205 1_1_0 EXIST::FUNCTION: +SSL_CTX_get_ex_data 206 1_1_0 EXIST::FUNCTION: +SSL_is_init_finished 207 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_default_verify_file 208 1_1_0 EXIST::FUNCTION: +SSLv3_method 209 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0,SSL3_METHOD +SSL_CTX_set_cookie_generate_cb 210 1_1_0 EXIST::FUNCTION: +SSL_certs_clear 211 1_1_0 EXIST::FUNCTION: +SSL_set_connect_state 212 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_ex_data 213 1_1_0 EXIST::FUNCTION: +SSL_rstate_string 214 1_1_0 EXIST::FUNCTION: +SSL_SESSION_get0_peer 215 1_1_0 EXIST::FUNCTION: +SSL_SESSION_get_compress_id 216 1_1_0 EXIST::FUNCTION: +SSL_get_peer_cert_chain 217 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_cert_cb 218 1_1_0 EXIST::FUNCTION: +PEM_read_bio_SSL_SESSION 219 1_1_0 EXIST::FUNCTION: +SSL_set_info_callback 220 1_1_0 EXIST::FUNCTION: +SSL_CTX_sess_set_new_cb 221 1_1_0 EXIST::FUNCTION: +SSL_CTX_get_security_level 222 1_1_0 EXIST::FUNCTION: +SSL_CTX_ctrl 223 1_1_0 EXIST::FUNCTION: +SSL_set_alpn_protos 224 1_1_0 EXIST::FUNCTION: +SSL_set_ex_data 225 1_1_0 EXIST::FUNCTION: +SSL_rstate_string_long 226 1_1_0 EXIST::FUNCTION: +SSL_ctrl 227 1_1_0 EXIST::FUNCTION: +SSL_get_current_compression 228 1_1_0 EXIST::FUNCTION: +SSL_SESSION_has_ticket 229 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_cert_verify_callback 230 1_1_0 EXIST::FUNCTION: +SSL_set_session_secret_cb 231 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_client_cert_engine 232 1_1_0 EXIST::FUNCTION:ENGINE +SSL_CTX_get0_param 233 1_1_0 EXIST::FUNCTION: +SSL_CTX_set1_param 234 1_1_0 EXIST::FUNCTION: +SSL_get_certificate 235 1_1_0 EXIST::FUNCTION: +DTLSv1_server_method 236 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0,DTLS1_METHOD +SSL_set_fd 237 1_1_0 EXIST::FUNCTION:SOCK +SSL_use_certificate 238 1_1_0 EXIST::FUNCTION: +DTLSv1_method 239 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0,DTLS1_METHOD +SSL_set0_wbio 240 1_1_0 EXIST::FUNCTION: +SSL_read 241 1_1_0 EXIST::FUNCTION: +SSL_CTX_get_options 242 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_ssl_version 243 1_1_0 EXIST::FUNCTION: +SSL_set_SSL_CTX 244 1_1_0 EXIST::FUNCTION: +SSL_renegotiate_abbreviated 245 1_1_0 EXIST::FUNCTION: +SSL_get_verify_mode 246 1_1_0 EXIST::FUNCTION: +SSL_CIPHER_get_id 247 1_1_0 EXIST::FUNCTION: +SSL_SESSION_print_keylog 248 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_psk_client_callback 249 1_1_0 EXIST::FUNCTION:PSK +SSL_SESSION_get_time 250 1_1_0 EXIST::FUNCTION: +SSL_set_debug 251 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0 +SSL_get_security_level 252 1_1_0 EXIST::FUNCTION: +SSL_CIPHER_description 253 1_1_0 EXIST::FUNCTION: +SSL_set_default_passwd_cb_userdata 254 1_1_0 EXIST::FUNCTION: +SSL_get_srp_userinfo 255 1_1_0 EXIST::FUNCTION:SRP +SSL_extension_supported 256 1_1_0 EXIST::FUNCTION: +SSL_dane_tlsa_add 257 1_1_0 EXIST::FUNCTION: +SSL_srp_server_param_with_username 258 1_1_0 EXIST::FUNCTION:SRP +SSL_CIPHER_get_version 259 1_1_0 EXIST::FUNCTION: +SSL_get0_verified_chain 260 1_1_0 EXIST::FUNCTION: +SSL_CIPHER_find 261 1_1_0 EXIST::FUNCTION: +SSL_get_rbio 262 1_1_0 EXIST::FUNCTION: +SSL_CONF_CTX_set_ssl 263 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_verify_depth 264 1_1_0 EXIST::FUNCTION: +SSL_get_ciphers 265 1_1_0 EXIST::FUNCTION: +SSL_CTX_config 266 1_1_0 EXIST::FUNCTION: +SSL_CONF_CTX_set_ssl_ctx 267 1_1_0 EXIST::FUNCTION: +SSL_CONF_cmd 268 1_1_0 EXIST::FUNCTION: +SSL_add_ssl_module 269 1_1_0 EXIST::FUNCTION: +SSL_CTX_get_verify_callback 270 1_1_0 EXIST::FUNCTION: +SSL_set1_param 271 1_1_0 EXIST::FUNCTION: +SSL_use_certificate_file 272 1_1_0 EXIST::FUNCTION: +SSL_get_changed_async_fds 273 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_client_cert_cb 274 1_1_0 EXIST::FUNCTION: +DTLS_client_method 275 1_1_0 EXIST::FUNCTION: +SSL_set_trust 276 1_1_0 EXIST::FUNCTION: +SSL_CTX_get_security_callback 277 1_1_0 EXIST::FUNCTION: +SSL_CTX_clear_options 278 1_1_0 EXIST::FUNCTION: +SSL_check_chain 279 1_1_0 EXIST::FUNCTION: +SSL_CTX_sess_set_remove_cb 280 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_info_callback 281 1_1_0 EXIST::FUNCTION: +SSL_pending 282 1_1_0 EXIST::FUNCTION: +SSL_set_bio 283 1_1_0 EXIST::FUNCTION: +BIO_new_ssl_connect 284 1_1_0 EXIST::FUNCTION: +SSL_waiting_for_async 285 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_srp_strength 286 1_1_0 EXIST::FUNCTION:SRP +SSL_CTX_get_quiet_shutdown 287 1_1_0 EXIST::FUNCTION: +SSL_CTX_use_certificate_chain_file 288 1_1_0 EXIST::FUNCTION: +SSL_CTX_dane_enable 289 1_1_0 EXIST::FUNCTION: +SSL_CONF_CTX_new 290 1_1_0 EXIST::FUNCTION: +SSL_get0_alpn_selected 291 1_1_0 EXIST::FUNCTION: +SSL_get0_next_proto_negotiated 292 1_1_0 EXIST::FUNCTION:NEXTPROTONEG +SSL_set0_security_ex_data 293 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_tlsext_use_srtp 294 1_1_0 EXIST::FUNCTION:SRTP +SSL_COMP_set0_compression_methods 295 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_not_resumable_session_callback 296 1_1_0 EXIST::FUNCTION: +SSL_accept 297 1_1_0 EXIST::FUNCTION: +SSL_use_psk_identity_hint 298 1_1_0 EXIST::FUNCTION:PSK +SSL_trace 299 1_1_0 EXIST::FUNCTION:SSL_TRACE +DTLS_method 300 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_srp_verify_param_callback 301 1_1_0 EXIST::FUNCTION:SRP +SSL_CTX_set_timeout 302 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_security_level 303 1_1_0 EXIST::FUNCTION: +TLS_client_method 304 1_1_0 EXIST::FUNCTION: +SSL_set_quiet_shutdown 305 1_1_0 EXIST::FUNCTION: +SSL_CTX_up_ref 306 1_1_0 EXIST::FUNCTION: +SSL_check_private_key 307 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_quiet_shutdown 308 1_1_0 EXIST::FUNCTION: +SSL_select_next_proto 309 1_1_0 EXIST::FUNCTION: +SSL_load_client_CA_file 310 1_1_0 EXIST::FUNCTION: +SSL_set_srp_server_param_pw 311 1_1_0 EXIST::FUNCTION:SRP +SSL_renegotiate_pending 312 1_1_0 EXIST::FUNCTION: +SSL_CTX_new 313 1_1_0 EXIST::FUNCTION: +SSL_set_session_ticket_ext_cb 314 1_1_0 EXIST::FUNCTION: +SSL_CTX_get_timeout 315 1_1_0 EXIST::FUNCTION: +SSL_use_certificate_chain_file 316 1_1_0 EXIST::FUNCTION: +SSL_set_not_resumable_session_callback 317 1_1_0 EXIST::FUNCTION: +SSL_CTX_SRP_CTX_free 318 1_1_0 EXIST::FUNCTION:SRP +SSL_get_current_expansion 319 1_1_0 EXIST::FUNCTION: +SSL_clear_options 320 1_1_0 EXIST::FUNCTION: +SSL_CTX_use_PrivateKey 321 1_1_0 EXIST::FUNCTION: +SSL_get_info_callback 322 1_1_0 EXIST::FUNCTION: +SSL_CTX_use_psk_identity_hint 323 1_1_0 EXIST::FUNCTION:PSK +SSL_CTX_use_RSAPrivateKey_ASN1 324 1_1_0 EXIST::FUNCTION:RSA +SSL_CTX_use_PrivateKey_ASN1 325 1_1_0 EXIST::FUNCTION: +SSL_CTX_get0_privatekey 326 1_1_0 EXIST::FUNCTION: +BIO_f_ssl 327 1_1_0 EXIST::FUNCTION: +SSLv3_server_method 328 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0,SSL3_METHOD +SSL_SESSION_free 329 1_1_0 EXIST::FUNCTION: +SSL_get_shutdown 330 1_1_0 EXIST::FUNCTION: +SSL_get_peer_finished 331 1_1_0 EXIST::FUNCTION: +SSL_set_tlsext_use_srtp 332 1_1_0 EXIST::FUNCTION:SRTP +TLSv1_method 333 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0,TLS1_METHOD +SSL_set_psk_server_callback 334 1_1_0 EXIST::FUNCTION:PSK +SSL_CTX_set_alpn_protos 335 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_default_verify_paths 336 1_1_0 EXIST::FUNCTION: +SSL_CTX_sess_set_get_cb 337 1_1_0 EXIST::FUNCTION: +SSL_add_file_cert_subjects_to_stack 338 1_1_0 EXIST::FUNCTION: +SSL_get_default_passwd_cb_userdata 339 1_1_0 EXIST::FUNCTION: +SSL_get_security_callback 340 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_srp_username 341 1_1_0 EXIST::FUNCTION:SRP +SSL_COMP_get_name 342 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_default_passwd_cb_userdata 343 1_1_0 EXIST::FUNCTION: +SSL_set_verify 344 1_1_0 EXIST::FUNCTION: +SSL_in_before 345 1_1_0 EXIST::FUNCTION: +SSL_CIPHER_get_digest_nid 346 1_1_0 EXIST::FUNCTION: +SSL_CTX_add_client_custom_ext 347 1_1_0 EXIST::FUNCTION: +SSL_CTX_use_certificate 348 1_1_0 EXIST::FUNCTION: +SSL_set_cipher_list 349 1_1_0 EXIST::FUNCTION: +SSL_get_wbio 350 1_1_0 EXIST::FUNCTION: +SSL_set_hostflags 351 1_1_0 EXIST::FUNCTION: +SSL_alert_desc_string_long 352 1_1_0 EXIST::FUNCTION: +SSL_get_default_timeout 353 1_1_0 EXIST::FUNCTION: +SSL_set_session_id_context 354 1_1_0 EXIST::FUNCTION: +SSL_new 355 1_1_0 EXIST::FUNCTION: +TLSv1_1_method 356 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0,TLS1_1_METHOD +SSL_CTX_get_cert_store 357 1_1_0 EXIST::FUNCTION: +SSL_CTX_load_verify_locations 358 1_1_0 EXIST::FUNCTION: +SSL_SESSION_print_fp 359 1_1_0 EXIST::FUNCTION:STDIO +SSL_get0_dane_tlsa 360 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_generate_session_id 361 1_1_0 EXIST::FUNCTION: +SSL_alert_type_string_long 362 1_1_0 EXIST::FUNCTION: +SSL_CONF_CTX_set1_prefix 363 1_1_0 EXIST::FUNCTION: +SSL_in_init 364 1_1_0 EXIST::FUNCTION: +BIO_new_ssl 365 1_1_0 EXIST::FUNCTION: +SSL_CTX_get_client_cert_cb 366 1_1_0 EXIST::FUNCTION: +SSL_CTX_use_certificate_ASN1 367 1_1_0 EXIST::FUNCTION: +SSL_set_client_CA_list 368 1_1_0 EXIST::FUNCTION: +SSL_CTX_free 369 1_1_0 EXIST::FUNCTION: +SSL_get_default_passwd_cb 370 1_1_0 EXIST::FUNCTION: +SSL_SESSION_get_id 371 1_1_0 EXIST::FUNCTION: +SSL_SESSION_set1_id_context 372 1_1_0 EXIST::FUNCTION: +SSL_is_server 373 1_1_0 EXIST::FUNCTION: +SSL_alert_type_string 374 1_1_0 EXIST::FUNCTION: +DTLSv1_2_client_method 375 1_1_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0,DTLS1_2_METHOD +SSL_CTX_set_ctlog_list_file 376 1_1_0 EXIST::FUNCTION:CT +SSL_set_ct_validation_callback 377 1_1_0 EXIST::FUNCTION:CT +SSL_CTX_set_default_ctlog_list_file 378 1_1_0 EXIST::FUNCTION:CT +SSL_CTX_has_client_custom_ext 379 1_1_0 EXIST::FUNCTION: +SSL_ct_is_enabled 380 1_1_0 EXIST::FUNCTION:CT +SSL_get0_peer_scts 381 1_1_0 EXIST::FUNCTION:CT +SSL_CTX_set_ct_validation_callback 382 1_1_0 EXIST::FUNCTION:CT +SSL_CTX_ct_is_enabled 383 1_1_0 EXIST::FUNCTION:CT +SSL_set_default_read_buffer_len 384 1_1_0 EXIST::FUNCTION: +SSL_CTX_set_default_read_buffer_len 385 1_1_0 EXIST::FUNCTION: +SSL_has_pending 386 1_1_0 EXIST::FUNCTION: +SSL_CIPHER_get_auth_nid 387 1_1_0 EXIST::FUNCTION: +SSL_CIPHER_get_kx_nid 388 1_1_0 EXIST::FUNCTION: +SSL_CIPHER_is_aead 389 1_1_0 EXIST::FUNCTION: +SSL_SESSION_up_ref 390 1_1_0 EXIST::FUNCTION: +SSL_CTX_set0_ctlog_store 391 1_1_0 EXIST::FUNCTION:CT +SSL_CTX_get0_ctlog_store 392 1_1_0 EXIST::FUNCTION:CT +SSL_enable_ct 393 1_1_0 EXIST::FUNCTION:CT +SSL_CTX_enable_ct 394 1_1_0 EXIST::FUNCTION:CT +SSL_CTX_get_ciphers 395 1_1_0 EXIST::FUNCTION: +SSL_SESSION_get0_hostname 396 1_1_0 EXIST::FUNCTION: +SSL_client_version 397 1_1_0 EXIST::FUNCTION: +SSL_SESSION_get_protocol_version 398 1_1_0 EXIST::FUNCTION: +SSL_is_dtls 399 1_1_0 EXIST::FUNCTION: +SSL_CTX_dane_set_flags 400 1_1_0 EXIST::FUNCTION: +SSL_dane_set_flags 401 1_1_0 EXIST::FUNCTION: +SSL_CTX_dane_clear_flags 402 1_1_0 EXIST::FUNCTION: +SSL_dane_clear_flags 403 1_1_0 EXIST::FUNCTION: +SSL_SESSION_get0_cipher 404 1_1_0 EXIST::FUNCTION: +SSL_SESSION_get0_id_context 405 1_1_0 EXIST::FUNCTION: +SSL_SESSION_set1_id 406 1_1_0 EXIST::FUNCTION: +SSL_CTX_set1_cert_store 407 1_1_1 EXIST::FUNCTION: +DTLS_get_data_mtu 408 1_1_1 EXIST::FUNCTION: +SSL_read_ex 409 1_1_1 EXIST::FUNCTION: +SSL_peek_ex 410 1_1_1 EXIST::FUNCTION: +SSL_write_ex 411 1_1_1 EXIST::FUNCTION: +SSL_COMP_get_id 412 1_1_0d EXIST::FUNCTION: +SSL_COMP_get0_name 413 1_1_0d EXIST::FUNCTION: +SSL_CTX_set_keylog_callback 414 1_1_1 EXIST::FUNCTION: +SSL_CTX_get_keylog_callback 415 1_1_1 EXIST::FUNCTION: +SSL_get_peer_signature_type_nid 416 1_1_1 EXIST::FUNCTION: +SSL_key_update 417 1_1_1 EXIST::FUNCTION: +SSL_get_key_update_type 418 1_1_1 EXIST::FUNCTION: +SSL_bytes_to_cipher_list 419 1_1_1 EXIST::FUNCTION: +SSL_client_hello_get0_compression_methods 420 1_1_1 EXIST::FUNCTION: +SSL_client_hello_get0_ciphers 421 1_1_1 EXIST::FUNCTION: +SSL_client_hello_get0_ext 422 1_1_1 EXIST::FUNCTION: +SSL_client_hello_get0_session_id 423 1_1_1 EXIST::FUNCTION: +SSL_client_hello_get0_random 424 1_1_1 EXIST::FUNCTION: +SSL_CTX_set_client_hello_cb 425 1_1_1 EXIST::FUNCTION: +SSL_client_hello_get0_legacy_version 426 1_1_1 EXIST::FUNCTION: +SSL_client_hello_isv2 427 1_1_1 EXIST::FUNCTION: +SSL_set_max_early_data 428 1_1_1 EXIST::FUNCTION: +SSL_CTX_set_max_early_data 429 1_1_1 EXIST::FUNCTION: +SSL_get_max_early_data 430 1_1_1 EXIST::FUNCTION: +SSL_CTX_get_max_early_data 431 1_1_1 EXIST::FUNCTION: +SSL_write_early_data 432 1_1_1 EXIST::FUNCTION: +SSL_read_early_data 433 1_1_1 EXIST::FUNCTION: +SSL_get_early_data_status 434 1_1_1 EXIST::FUNCTION: +SSL_SESSION_get_max_early_data 435 1_1_1 EXIST::FUNCTION: +SSL_add1_to_CA_list 436 1_1_1 EXIST::FUNCTION: +SSL_set0_CA_list 437 1_1_1 EXIST::FUNCTION: +SSL_CTX_set0_CA_list 438 1_1_1 EXIST::FUNCTION: +SSL_get0_CA_list 439 1_1_1 EXIST::FUNCTION: +SSL_get0_peer_CA_list 440 1_1_1 EXIST::FUNCTION: +SSL_CTX_add1_to_CA_list 441 1_1_1 EXIST::FUNCTION: +SSL_CTX_get0_CA_list 442 1_1_1 EXIST::FUNCTION: +SSL_CTX_add_custom_ext 443 1_1_1 EXIST::FUNCTION: +SSL_SESSION_is_resumable 444 1_1_1 EXIST::FUNCTION: +SSL_CTX_set_record_padding_callback 445 1_1_1 EXIST::FUNCTION: +SSL_set_record_padding_callback 446 1_1_1 EXIST::FUNCTION: +SSL_CTX_set_block_padding 447 1_1_1 EXIST::FUNCTION: +SSL_CTX_get_record_padding_callback_arg 448 1_1_1 EXIST::FUNCTION: +SSL_get_record_padding_callback_arg 449 1_1_1 EXIST::FUNCTION: +SSL_set_block_padding 450 1_1_1 EXIST::FUNCTION: +SSL_set_record_padding_callback_arg 451 1_1_1 EXIST::FUNCTION: +SSL_CTX_set_record_padding_callback_arg 452 1_1_1 EXIST::FUNCTION: +SSL_CTX_use_serverinfo_ex 453 1_1_1 EXIST::FUNCTION: +SSL_client_hello_get1_extensions_present 454 1_1_1 EXIST::FUNCTION: +SSL_set_psk_find_session_callback 455 1_1_1 EXIST::FUNCTION: +SSL_set_psk_use_session_callback 456 1_1_1 EXIST::FUNCTION: +SSL_CTX_set_psk_use_session_callback 457 1_1_1 EXIST::FUNCTION: +SSL_CTX_set_psk_find_session_callback 458 1_1_1 EXIST::FUNCTION: +SSL_CIPHER_get_handshake_digest 459 1_1_1 EXIST::FUNCTION: +SSL_SESSION_set1_master_key 460 1_1_1 EXIST::FUNCTION: +SSL_SESSION_set_cipher 461 1_1_1 EXIST::FUNCTION: +SSL_SESSION_set_protocol_version 462 1_1_1 EXIST::FUNCTION: +OPENSSL_cipher_name 463 1_1_1 EXIST::FUNCTION: +SSL_alloc_buffers 464 1_1_1 EXIST::FUNCTION: +SSL_free_buffers 465 1_1_1 EXIST::FUNCTION: +SSL_SESSION_dup 466 1_1_1 EXIST::FUNCTION: +SSL_get_pending_cipher 467 1_1_1 EXIST::FUNCTION: +SSL_CIPHER_get_protocol_id 468 1_1_1 EXIST::FUNCTION: +SSL_SESSION_set_max_early_data 469 1_1_1 EXIST::FUNCTION: +SSL_SESSION_set1_alpn_selected 470 1_1_1 EXIST::FUNCTION: +SSL_SESSION_set1_hostname 471 1_1_1 EXIST::FUNCTION: +SSL_SESSION_get0_alpn_selected 472 1_1_1 EXIST::FUNCTION: +DTLS_set_timer_cb 473 1_1_1 EXIST::FUNCTION: +SSL_CTX_set_tlsext_max_fragment_length 474 1_1_1 EXIST::FUNCTION: +SSL_set_tlsext_max_fragment_length 475 1_1_1 EXIST::FUNCTION: +SSL_SESSION_get_max_fragment_length 476 1_1_1 EXIST::FUNCTION: +SSL_stateless 477 1_1_1 EXIST::FUNCTION: +SSL_verify_client_post_handshake 478 1_1_1 EXIST::FUNCTION: +SSL_set_post_handshake_auth 479 1_1_1 EXIST::FUNCTION: +SSL_export_keying_material_early 480 1_1_1 EXIST::FUNCTION: +SSL_CTX_use_cert_and_key 481 1_1_1 EXIST::FUNCTION: +SSL_use_cert_and_key 482 1_1_1 EXIST::FUNCTION: +SSL_SESSION_get0_ticket_appdata 483 1_1_1 EXIST::FUNCTION: +SSL_SESSION_set1_ticket_appdata 484 1_1_1 EXIST::FUNCTION: +SSL_CTX_set_session_ticket_cb 485 1_1_1 EXIST::FUNCTION: +SSL_CTX_set_stateless_cookie_generate_cb 486 1_1_1 EXIST::FUNCTION: +SSL_CTX_set_stateless_cookie_verify_cb 487 1_1_1 EXIST::FUNCTION: +SSL_CTX_set_ciphersuites 488 1_1_1 EXIST::FUNCTION: +SSL_set_ciphersuites 489 1_1_1 EXIST::FUNCTION: +SSL_set_num_tickets 490 1_1_1 EXIST::FUNCTION: +SSL_CTX_get_num_tickets 491 1_1_1 EXIST::FUNCTION: +SSL_get_num_tickets 492 1_1_1 EXIST::FUNCTION: +SSL_CTX_set_num_tickets 493 1_1_1 EXIST::FUNCTION: +SSL_CTX_set_allow_early_data_cb 494 1_1_1 EXIST::FUNCTION: +SSL_set_allow_early_data_cb 495 1_1_1 EXIST::FUNCTION: +SSL_set_recv_max_early_data 496 1_1_1 EXIST::FUNCTION: +SSL_get_recv_max_early_data 497 1_1_1 EXIST::FUNCTION: +SSL_CTX_get_recv_max_early_data 498 1_1_1 EXIST::FUNCTION: +SSL_CTX_set_recv_max_early_data 499 1_1_1 EXIST::FUNCTION: +SSL_CTX_set_post_handshake_auth 500 1_1_1 EXIST::FUNCTION: +SSL_get_signature_type_nid 501 1_1_1a EXIST::FUNCTION: diff --git a/trunk/3rdparty/openssl-1.1-fit/util/local_shlib.com.in b/trunk/3rdparty/openssl-1.1-fit/util/local_shlib.com.in new file mode 100644 index 000000000..a38187253 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/local_shlib.com.in @@ -0,0 +1,30 @@ +${- + use File::Spec::Functions qw(rel2abs); + + my $bldtop = rel2abs($config{builddir}); + our %names = ( map { $_ => $bldtop.$_.".EXE" } + map { $unified_info{sharednames}->{$_} || () } + @{$unified_info{libraries}} ); + "" -} +$ ! Create a local environment with the shared library logical names +$ ! properly set. Undo this with unlocal_shlib.com +$ +$ OPENSSL_NAMES := OPENSSL_NAMES_'F$GETJPI("","PID")' +$ CREATE/NAME_TABLE/PARENT_TABLE=LNM$PROCESS_DIRECTORY 'OPENSSL_NAMES' +$ DEFINE/TABLE='OPENSSL_NAMES' OSSL_FLAG YES +$ +$ NAMES := {- join(",", keys %names); -} +{- + join("\n", map { "\$ __$_ = \"".$names{$_}."\"" } keys %names); +-} +$ I = 0 +$ LOOP: +$ E = F$ELEMENT(I,",",NAMES) +$ I = I + 1 +$ IF E .EQS. "," THEN GOTO ENDLOOP +$ EV = __'E' +$ OLDV = F$TRNLNM(E,"LNM$PROCESS") +$ IF OLDV .NES. "" THEN DEFINE/TABLE='OPENSSL_NAMES' 'E' 'OLDV' +$ DEFINE 'E' 'EV' +$ GOTO LOOP +$ ENDLOOP: diff --git a/trunk/3rdparty/openssl-1.1-fit/util/mkbuildinf.pl b/trunk/3rdparty/openssl-1.1-fit/util/mkbuildinf.pl new file mode 100755 index 000000000..c9324a9de --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/mkbuildinf.pl @@ -0,0 +1,56 @@ +#! /usr/bin/env perl +# Copyright 2014-2017 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use strict; +use warnings; + +my ($cflags, $platform) = @ARGV; +$cflags = "compiler: $cflags"; + +my $date = gmtime($ENV{'SOURCE_DATE_EPOCH'} || time()) . " UTC"; + +print <<"END_OUTPUT"; +/* + * WARNING: do not edit! + * Generated by util/mkbuildinf.pl + * + * Copyright 2014-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#define PLATFORM "platform: $platform" +#define DATE "built on: $date" + +/* + * Generate compiler_flags as an array of individual characters. This is a + * workaround for the situation where CFLAGS gets too long for a C90 string + * literal + */ +static const char compiler_flags[] = { +END_OUTPUT + +my $ctr = 0; +foreach my $c (split //, $cflags) { + $c =~ s|([\\'])|\\$1|; + # Max 16 characters per line + if (($ctr++ % 16) == 0) { + if ($ctr != 1) { + print "\n"; + } + print " "; + } + print "'$c',"; +} +print <<"END_OUTPUT"; +'\\0' +}; +END_OUTPUT diff --git a/trunk/3rdparty/openssl-1.1-fit/util/mkdef.pl b/trunk/3rdparty/openssl-1.1-fit/util/mkdef.pl new file mode 100755 index 000000000..bcbb47583 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/mkdef.pl @@ -0,0 +1,1633 @@ +#! /usr/bin/env perl +# Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# generate a .def file +# +# It does this by parsing the header files and looking for the +# prototyped functions: it then prunes the output. +# +# Intermediary files are created, call libcrypto.num and libssl.num, +# The format of these files is: +# +# routine-name nnnn vers info +# +# The "nnnn" and "vers" fields are the numeric id and version for the symbol +# respectively. The "info" part is actually a colon-separated string of fields +# with the following meaning: +# +# existence:platform:kind:algorithms +# +# - "existence" can be "EXIST" or "NOEXIST" depending on if the symbol is +# found somewhere in the source, +# - "platforms" is empty if it exists on all platforms, otherwise it contains +# comma-separated list of the platform, just as they are if the symbol exists +# for those platforms, or prepended with a "!" if not. This helps resolve +# symbol name variants for platforms where the names are too long for the +# compiler or linker, or if the systems is case insensitive and there is a +# clash, or the symbol is implemented differently (see +# EXPORT_VAR_AS_FUNCTION). This script assumes renaming of symbols is found +# in the file crypto/symhacks.h. +# The semantics for the platforms is that every item is checked against the +# environment. For the negative items ("!FOO"), if any of them is false +# (i.e. "FOO" is true) in the environment, the corresponding symbol can't be +# used. For the positive items, if all of them are false in the environment, +# the corresponding symbol can't be used. Any combination of positive and +# negative items are possible, and of course leave room for some redundancy. +# - "kind" is "FUNCTION" or "VARIABLE". The meaning of that is obvious. +# - "algorithms" is a comma-separated list of algorithm names. This helps +# exclude symbols that are part of an algorithm that some user wants to +# exclude. +# + +use lib "."; +use configdata; +use File::Spec::Functions; +use File::Basename; +use FindBin; +use lib "$FindBin::Bin/perl"; +use OpenSSL::Glob; + +# When building a "variant" shared library, with a custom SONAME, also customize +# all the symbol versions. This produces a shared object that can coexist +# without conflict in the same address space as a default build, or an object +# with a different variant tag. +# +# For example, with a target definition that includes: +# +# shlib_variant => "-opt", +# +# we build the following objects: +# +# $ perl -le ' +# for (@ARGV) { +# if ($l = readlink) { +# printf "%s -> %s\n", $_, $l +# } else { +# print +# } +# }' *.so* +# libcrypto-opt.so.1.1 +# libcrypto.so -> libcrypto-opt.so.1.1 +# libssl-opt.so.1.1 +# libssl.so -> libssl-opt.so.1.1 +# +# whose SONAMEs and dependencies are: +# +# $ for l in *.so; do +# echo $l +# readelf -d $l | egrep 'SONAME|NEEDED.*(ssl|crypto)' +# done +# libcrypto.so +# 0x000000000000000e (SONAME) Library soname: [libcrypto-opt.so.1.1] +# libssl.so +# 0x0000000000000001 (NEEDED) Shared library: [libcrypto-opt.so.1.1] +# 0x000000000000000e (SONAME) Library soname: [libssl-opt.so.1.1] +# +# We case-fold the variant tag to upper case and replace all non-alnum +# characters with "_". This yields the following symbol versions: +# +# $ nm libcrypto.so | grep -w A +# 0000000000000000 A OPENSSL_OPT_1_1_0 +# 0000000000000000 A OPENSSL_OPT_1_1_0a +# 0000000000000000 A OPENSSL_OPT_1_1_0c +# 0000000000000000 A OPENSSL_OPT_1_1_0d +# 0000000000000000 A OPENSSL_OPT_1_1_0f +# 0000000000000000 A OPENSSL_OPT_1_1_0g +# $ nm libssl.so | grep -w A +# 0000000000000000 A OPENSSL_OPT_1_1_0 +# 0000000000000000 A OPENSSL_OPT_1_1_0d +# +(my $SO_VARIANT = qq{\U$target{"shlib_variant"}}) =~ s/\W/_/g; + +my $debug=0; +my $trace=0; +my $verbose=0; + +my $crypto_num= catfile($config{sourcedir},"util","libcrypto.num"); +my $ssl_num= catfile($config{sourcedir},"util","libssl.num"); +my $libname; + +my $do_update = 0; +my $do_rewrite = 1; +my $do_crypto = 0; +my $do_ssl = 0; +my $do_ctest = 0; +my $do_ctestall = 0; +my $do_checkexist = 0; + +my $VMS=0; +my $W32=0; +my $NT=0; +my $UNIX=0; +my $linux=0; +my $aix=0; +# Set this to make typesafe STACK definitions appear in DEF +my $safe_stack_def = 0; + +my @known_platforms = ( "__FreeBSD__", "PERL5", + "EXPORT_VAR_AS_FUNCTION", "ZLIB", "_WIN32" + ); +my @known_ossl_platforms = ( "UNIX", "VMS", "WIN32", "WINNT", "OS2" ); +my @known_algorithms = ( # These are algorithms we know are guarded in relevant + # header files, but aren't actually disablable. + # Without these, this script will warn a lot. + "RSA", "MD5", + # @disablables comes from configdata.pm + map { (my $x = uc $_) =~ s|-|_|g; $x; } @disablables, + # Deprecated functions. Not really algorithmss, but + # treated as such here for the sake of simplicity + "DEPRECATEDIN_0_9_8", + "DEPRECATEDIN_1_0_0", + "DEPRECATEDIN_1_1_0", + "DEPRECATEDIN_1_2_0", + ); + +# %disabled comes from configdata.pm +my %disabled_algorithms = + map { (my $x = uc $_) =~ s|-|_|g; $x => 1; } keys %disabled; + +my $apiv = sprintf "%x%02x%02x", split(/\./, $config{api}); +foreach (@known_algorithms) { + if (/^DEPRECATEDIN_(\d+)_(\d+)_(\d+)$/) { + my $depv = sprintf "%x%02x%02x", $1, $2, $3; + $disabled_algorithms{$_} = 1 if $apiv ge $depv; + } +} + +my $zlib; + +foreach (@ARGV, split(/ /, $config{options})) + { + $debug=1 if $_ eq "debug"; + $trace=1 if $_ eq "trace"; + $verbose=1 if $_ eq "verbose"; + $W32=1 if $_ eq "32"; + die "win16 not supported" if $_ eq "16"; + if($_ eq "NT") { + $W32 = 1; + $NT = 1; + } elsif ($_ eq "linux") { + $linux=1; + $UNIX=1; + } elsif ($_ eq "aix") { + $aix=1; + $UNIX=1; + } elsif ($_ eq "VMS") { + $VMS=1; + } + if ($_ eq "zlib" || $_ eq "enable-zlib" || $_ eq "zlib-dynamic" + || $_ eq "enable-zlib-dynamic") { + $zlib = 1; + } + + $do_crypto=1 if $_ eq "libcrypto" || $_ eq "crypto"; + $do_ssl=1 if $_ eq "libssl" || $_ eq "ssl"; + + $do_update=1 if $_ eq "update"; + $do_rewrite=1 if $_ eq "rewrite"; + $do_ctest=1 if $_ eq "ctest"; + $do_ctestall=1 if $_ eq "ctestall"; + $do_checkexist=1 if $_ eq "exist"; + } +$libname = $unified_info{sharednames}->{libcrypto} if $do_crypto; +$libname = $unified_info{sharednames}->{libssl} if $do_ssl; + +if (!$libname) { + if ($do_ssl) { + $libname="LIBSSL"; + } + if ($do_crypto) { + $libname="LIBCRYPTO"; + } +} + +# If no platform is given, assume WIN32 +if ($W32 + $VMS + $linux + $aix == 0) { + $W32 = 1; +} +die "Please, only one platform at a time" + if ($W32 + $VMS + $linux + $aix > 1); + +if (!$do_ssl && !$do_crypto) + { + print STDERR "usage: $0 ( ssl | crypto ) [ 16 | 32 | NT | OS2 | linux | VMS ]\n"; + exit(1); + } + +%ssl_list=&load_numbers($ssl_num); +$max_ssl = $max_num; +%crypto_list=&load_numbers($crypto_num); +$max_crypto = $max_num; + +my $ssl="include/openssl/ssl.h"; +$ssl.=" include/openssl/sslerr.h"; +$ssl.=" include/openssl/tls1.h"; +$ssl.=" include/openssl/srtp.h"; + +# When scanning include/openssl, skip all SSL files and some internal ones. +my %skipthese; +foreach my $f ( split(/\s+/, $ssl) ) { + $skipthese{$f} = 1; +} +$skipthese{'include/openssl/conf_api.h'} = 1; +$skipthese{'include/openssl/ebcdic.h'} = 1; +$skipthese{'include/openssl/opensslconf.h'} = 1; + +# We use headers found in include/openssl and include/internal only. +# The latter is needed so libssl.so/.dll/.exe can link properly. +my $crypto ="include/internal/dso.h"; +$crypto.=" include/internal/o_dir.h"; +$crypto.=" include/internal/o_str.h"; +$crypto.=" include/internal/err.h"; +$crypto.=" include/internal/sslconf.h"; +foreach my $f ( glob(catfile($config{sourcedir},'include/openssl/*.h')) ) { + my $fn = "include/openssl/" . basename($f); + $crypto .= " $fn" if !defined $skipthese{$fn}; +} + +my $symhacks="include/openssl/symhacks.h"; + +my @ssl_symbols = &do_defs("LIBSSL", $ssl, $symhacks); +my @crypto_symbols = &do_defs("LIBCRYPTO", $crypto, $symhacks); + +if ($do_update) { + +if ($do_ssl == 1) { + + &maybe_add_info("LIBSSL",*ssl_list,@ssl_symbols); + if ($do_rewrite == 1) { + open(OUT, ">$ssl_num"); + &rewrite_numbers(*OUT,"LIBSSL",*ssl_list,@ssl_symbols); + } else { + open(OUT, ">>$ssl_num"); + } + &update_numbers(*OUT,"LIBSSL",*ssl_list,$max_ssl,@ssl_symbols); + close OUT; +} + +if($do_crypto == 1) { + + &maybe_add_info("LIBCRYPTO",*crypto_list,@crypto_symbols); + if ($do_rewrite == 1) { + open(OUT, ">$crypto_num"); + &rewrite_numbers(*OUT,"LIBCRYPTO",*crypto_list,@crypto_symbols); + } else { + open(OUT, ">>$crypto_num"); + } + &update_numbers(*OUT,"LIBCRYPTO",*crypto_list,$max_crypto,@crypto_symbols); + close OUT; +} + +} elsif ($do_checkexist) { + &check_existing(*ssl_list, @ssl_symbols) + if $do_ssl == 1; + &check_existing(*crypto_list, @crypto_symbols) + if $do_crypto == 1; +} elsif ($do_ctest || $do_ctestall) { + + print <<"EOF"; + +/* Test file to check all DEF file symbols are present by trying + * to link to all of them. This is *not* intended to be run! + */ + +int main() +{ +EOF + &print_test_file(*STDOUT,"LIBSSL",*ssl_list,$do_ctestall,@ssl_symbols) + if $do_ssl == 1; + + &print_test_file(*STDOUT,"LIBCRYPTO",*crypto_list,$do_ctestall,@crypto_symbols) + if $do_crypto == 1; + + print "}\n"; + +} else { + + &print_def_file(*STDOUT,$libname,*ssl_list,@ssl_symbols) + if $do_ssl == 1; + + &print_def_file(*STDOUT,$libname,*crypto_list,@crypto_symbols) + if $do_crypto == 1; + +} + + +sub do_defs +{ + my($name,$files,$symhacksfile)=@_; + my $file; + my @ret; + my %syms; + my %platform; # For anything undefined, we assume "" + my %kind; # For anything undefined, we assume "FUNCTION" + my %algorithm; # For anything undefined, we assume "" + my %variant; + my %variant_cnt; # To be able to allocate "name{n}" if "name" + # is the same name as the original. + my $cpp; + my %unknown_algorithms = (); + my $parens = 0; + + foreach $file (split(/\s+/,$symhacksfile." ".$files)) + { + my $fn = catfile($config{sourcedir},$file); + print STDERR "DEBUG: starting on $fn:\n" if $debug; + print STDERR "TRACE: start reading $fn\n" if $trace; + open(IN,"<$fn") || die "Can't open $fn, $!,"; + my $line = "", my $def= ""; + my %tag = ( + (map { $_ => 0 } @known_platforms), + (map { "OPENSSL_SYS_".$_ => 0 } @known_ossl_platforms), + (map { "OPENSSL_NO_".$_ => 0 } @known_algorithms), + (map { "OPENSSL_USE_".$_ => 0 } @known_algorithms), + (grep /^DEPRECATED_/, @known_algorithms), + NOPROTO => 0, + PERL5 => 0, + _WINDLL => 0, + CONST_STRICT => 0, + TRUE => 1, + ); + my $symhacking = $file eq $symhacksfile; + my @current_platforms = (); + my @current_algorithms = (); + + # params: symbol, alias, platforms, kind + # The reason to put this subroutine in a variable is that + # it will otherwise create it's own, unshared, version of + # %tag and %variant... + my $make_variant = sub + { + my ($s, $a, $p, $k) = @_; + my ($a1, $a2); + + print STDERR "DEBUG: make_variant: Entered with ",$s,", ",$a,", ",(defined($p)?$p:""),", ",(defined($k)?$k:""),"\n" if $debug; + if (defined($p)) + { + $a1 = join(",",$p, + grep(!/^$/, + map { $tag{$_} == 1 ? $_ : "" } + @known_platforms)); + } + else + { + $a1 = join(",", + grep(!/^$/, + map { $tag{$_} == 1 ? $_ : "" } + @known_platforms)); + } + $a2 = join(",", + grep(!/^$/, + map { $tag{"OPENSSL_SYS_".$_} == 1 ? $_ : "" } + @known_ossl_platforms)); + print STDERR "DEBUG: make_variant: a1 = $a1; a2 = $a2\n" if $debug; + if ($a1 eq "") { $a1 = $a2; } + elsif ($a1 ne "" && $a2 ne "") { $a1 .= ",".$a2; } + if ($a eq $s) + { + if (!defined($variant_cnt{$s})) + { + $variant_cnt{$s} = 0; + } + $variant_cnt{$s}++; + $a .= "{$variant_cnt{$s}}"; + } + my $toadd = $a.":".$a1.(defined($k)?":".$k:""); + my $togrep = $s.'(\{[0-9]+\})?:'.$a1.(defined($k)?":".$k:""); + if (!grep(/^$togrep$/, + split(/;/, defined($variant{$s})?$variant{$s}:""))) { + if (defined($variant{$s})) { $variant{$s} .= ";"; } + $variant{$s} .= $toadd; + } + print STDERR "DEBUG: make_variant: Exit with variant of ",$s," = ",$variant{$s},"\n" if $debug; + }; + + print STDERR "DEBUG: parsing ----------\n" if $debug; + while() { + s|\R$||; # Better chomp + if($parens > 0) { + #Inside a DEPRECATEDIN + $stored_multiline .= $_; + print STDERR "DEBUG: Continuing multiline DEPRECATEDIN: $stored_multiline\n" if $debug; + $parens = count_parens($stored_multiline); + if ($parens == 0) { + $def .= do_deprecated($stored_multiline, + \@current_platforms, + \@current_algorithms); + } + next; + } + if (/\/\* Error codes for the \w+ functions\. \*\//) + { + undef @tag; + last; + } + if ($line ne '') { + $_ = $line . $_; + $line = ''; + } + + if (/\\$/) { + $line = $`; # keep what was before the backslash + next; + } + + if(/\/\*/) { + if (not /\*\//) { # multi-line comment... + $line = $_; # ... just accumulate + next; + } else { + s/\/\*.*?\*\///gs;# wipe it + } + } + + if ($cpp) { + $cpp++ if /^#\s*if/; + $cpp-- if /^#\s*endif/; + next; + } + if (/^#.*ifdef.*cplusplus/) { + $cpp = 1; + next; + } + + s/{[^{}]*}//gs; # ignore {} blocks + print STDERR "DEBUG: \$def=\"$def\"\n" if $debug && $def ne ""; + print STDERR "DEBUG: \$_=\"$_\"\n" if $debug; + if (/^\#\s*if\s+OPENSSL_API_COMPAT\s*(\S)\s*(0x[0-9a-fA-F]{8})L\s*$/) { + my $op = $1; + my $v = hex($2); + if ($op ne '<' && $op ne '>=') { + die "$file unacceptable operator $op: $_\n"; + } + my ($one, $major, $minor) = + ( ($v >> 28) & 0xf, + ($v >> 20) & 0xff, + ($v >> 12) & 0xff ); + my $t = "DEPRECATEDIN_${one}_${major}_${minor}"; + push(@tag,"-"); + push(@tag,$t); + $tag{$t}=($op eq '<' ? 1 : -1); + print STDERR "DEBUG: $file: found tag $t = $tag{$t}\n" if $debug; + } elsif (/^\#\s*ifndef\s+(.*)/) { + push(@tag,"-"); + push(@tag,$1); + $tag{$1}=-1; + print STDERR "DEBUG: $file: found tag $1 = -1\n" if $debug; + } elsif (/^\#\s*if\s+!defined\s*\(([^\)]+)\)/) { + push(@tag,"-"); + if (/^\#\s*if\s+(!defined\s*\(([^\)]+)\)(\s+\&\&\s+!defined\s*\(([^\)]+)\))*)$/) { + my $tmp_1 = $1; + my $tmp_; + foreach $tmp_ (split '\&\&',$tmp_1) { + $tmp_ =~ /!defined\s*\(([^\)]+)\)/; + print STDERR "DEBUG: $file: found tag $1 = -1\n" if $debug; + push(@tag,$1); + $tag{$1}=-1; + } + } else { + print STDERR "Warning: $file: taking only '!defined($1)' of complicated expression: $_" if $verbose; # because it is O... + print STDERR "DEBUG: $file: found tag $1 = -1\n" if $debug; + push(@tag,$1); + $tag{$1}=-1; + } + } elsif (/^\#\s*ifdef\s+(\S*)/) { + push(@tag,"-"); + push(@tag,$1); + $tag{$1}=1; + print STDERR "DEBUG: $file: found tag $1 = 1\n" if $debug; + } elsif (/^\#\s*if\s+defined\s*\(([^\)]+)\)/) { + push(@tag,"-"); + if (/^\#\s*if\s+(defined\s*\(([^\)]+)\)(\s+\|\|\s+defined\s*\(([^\)]+)\))*)$/) { + my $tmp_1 = $1; + my $tmp_; + foreach $tmp_ (split '\|\|',$tmp_1) { + $tmp_ =~ /defined\s*\(([^\)]+)\)/; + print STDERR "DEBUG: $file: found tag $1 = 1\n" if $debug; + push(@tag,$1); + $tag{$1}=1; + } + } else { + print STDERR "Warning: $file: taking only 'defined($1)' of complicated expression: $_\n" if $verbose; # because it is O... + print STDERR "DEBUG: $file: found tag $1 = 1\n" if $debug; + push(@tag,$1); + $tag{$1}=1; + } + } elsif (/^\#\s*error\s+(\w+) is disabled\./) { + my $tag_i = $#tag; + while($tag[$tag_i] ne "-") { + if ($tag[$tag_i] eq "OPENSSL_NO_".$1) { + $tag{$tag[$tag_i]}=2; + print STDERR "DEBUG: $file: changed tag $1 = 2\n" if $debug; + } + $tag_i--; + } + } elsif (/^\#\s*endif/) { + my $tag_i = $#tag; + while($tag_i > 0 && $tag[$tag_i] ne "-") { + my $t=$tag[$tag_i]; + print STDERR "DEBUG: \$t=\"$t\"\n" if $debug; + if ($tag{$t}==2) { + $tag{$t}=-1; + } else { + $tag{$t}=0; + } + print STDERR "DEBUG: $file: changed tag ",$t," = ",$tag{$t},"\n" if $debug; + pop(@tag); + if ($t =~ /^OPENSSL_NO_([A-Z0-9_]+)$/) { + $t=$1; + } elsif($t =~ /^OPENSSL_USE_([A-Z0-9_]+)$/) { + $t=$1; + } else { + $t=""; + } + if ($t ne "" + && !grep(/^$t$/, @known_algorithms)) { + $unknown_algorithms{$t} = 1; + #print STDERR "DEBUG: Added as unknown algorithm: $t\n" if $debug; + } + $tag_i--; + } + pop(@tag); + } elsif (/^\#\s*else/) { + my $tag_i = $#tag; + die "$file unmatched else\n" if $tag_i < 0; + while($tag[$tag_i] ne "-") { + my $t=$tag[$tag_i]; + $tag{$t}= -$tag{$t}; + print STDERR "DEBUG: $file: changed tag ",$t," = ",$tag{$t},"\n" if $debug; + $tag_i--; + } + } elsif (/^\#\s*if\s+1/) { + push(@tag,"-"); + # Dummy tag + push(@tag,"TRUE"); + $tag{"TRUE"}=1; + print STDERR "DEBUG: $file: found 1\n" if $debug; + } elsif (/^\#\s*if\s+0/) { + push(@tag,"-"); + # Dummy tag + push(@tag,"TRUE"); + $tag{"TRUE"}=-1; + print STDERR "DEBUG: $file: found 0\n" if $debug; + } elsif (/^\#\s*if\s+/) { + #Some other unrecognized "if" style + push(@tag,"-"); + print STDERR "Warning: $file: ignoring unrecognized expression: $_\n" if $verbose; # because it is O... + } elsif (/^\#\s*define\s+(\w+)\s+(\w+)/ + && $symhacking && $tag{'TRUE'} != -1) { + # This is for aliasing. When we find an alias, + # we have to invert + &$make_variant($1,$2); + print STDERR "DEBUG: $file: defined $1 = $2\n" if $debug; + } + if (/^\#/) { + @current_platforms = + grep(!/^$/, + map { $tag{$_} == 1 ? $_ : + $tag{$_} == -1 ? "!".$_ : "" } + @known_platforms); + push @current_platforms + , grep(!/^$/, + map { $tag{"OPENSSL_SYS_".$_} == 1 ? $_ : + $tag{"OPENSSL_SYS_".$_} == -1 ? "!".$_ : "" } + @known_ossl_platforms); + @current_algorithms = (); + @current_algorithms = + grep(!/^$/, + map { $tag{"OPENSSL_NO_".$_} == -1 ? $_ : "" } + @known_algorithms); + push @current_algorithms + , grep(!/^$/, + map { $tag{"OPENSSL_USE_".$_} == 1 ? $_ : "" } + @known_algorithms); + push @current_algorithms, + grep { /^DEPRECATEDIN_/ && $tag{$_} == 1 } + @known_algorithms; + $def .= + "#INFO:" + .join(',',@current_platforms).":" + .join(',',@current_algorithms).";"; + next; + } + if ($tag{'TRUE'} != -1) { + if (/^\s*DEFINE_STACK_OF\s*\(\s*(\w*)\s*\)/ + || /^\s*DEFINE_STACK_OF_CONST\s*\(\s*(\w*)\s*\)/) { + next; + } elsif (/^\s*DECLARE_ASN1_ENCODE_FUNCTIONS\s*\(\s*(\w*)\s*,\s*(\w*)\s*,\s*(\w*)\s*\)/) { + $def .= "int d2i_$3(void);"; + $def .= "int i2d_$3(void);"; + # Variant for platforms that do not + # have to access global variables + # in shared libraries through functions + $def .= + "#INFO:" + .join(',',"!EXPORT_VAR_AS_FUNCTION",@current_platforms).":" + .join(',',@current_algorithms).";"; + $def .= "OPENSSL_EXTERN int $2_it;"; + $def .= + "#INFO:" + .join(',',@current_platforms).":" + .join(',',@current_algorithms).";"; + # Variant for platforms that have to + # access global variables in shared + # libraries through functions + &$make_variant("$2_it","$2_it", + "EXPORT_VAR_AS_FUNCTION", + "FUNCTION"); + next; + } elsif (/^\s*DECLARE_ASN1_FUNCTIONS_fname\s*\(\s*(\w*)\s*,\s*(\w*)\s*,\s*(\w*)\s*\)/) { + $def .= "int d2i_$3(void);"; + $def .= "int i2d_$3(void);"; + $def .= "int $3_free(void);"; + $def .= "int $3_new(void);"; + # Variant for platforms that do not + # have to access global variables + # in shared libraries through functions + $def .= + "#INFO:" + .join(',',"!EXPORT_VAR_AS_FUNCTION",@current_platforms).":" + .join(',',@current_algorithms).";"; + $def .= "OPENSSL_EXTERN int $2_it;"; + $def .= + "#INFO:" + .join(',',@current_platforms).":" + .join(',',@current_algorithms).";"; + # Variant for platforms that have to + # access global variables in shared + # libraries through functions + &$make_variant("$2_it","$2_it", + "EXPORT_VAR_AS_FUNCTION", + "FUNCTION"); + next; + } elsif (/^\s*DECLARE_ASN1_FUNCTIONS\s*\(\s*(\w*)\s*\)/ || + /^\s*DECLARE_ASN1_FUNCTIONS_const\s*\(\s*(\w*)\s*\)/) { + $def .= "int d2i_$1(void);"; + $def .= "int i2d_$1(void);"; + $def .= "int $1_free(void);"; + $def .= "int $1_new(void);"; + # Variant for platforms that do not + # have to access global variables + # in shared libraries through functions + $def .= + "#INFO:" + .join(',',"!EXPORT_VAR_AS_FUNCTION",@current_platforms).":" + .join(',',@current_algorithms).";"; + $def .= "OPENSSL_EXTERN int $1_it;"; + $def .= + "#INFO:" + .join(',',@current_platforms).":" + .join(',',@current_algorithms).";"; + # Variant for platforms that have to + # access global variables in shared + # libraries through functions + &$make_variant("$1_it","$1_it", + "EXPORT_VAR_AS_FUNCTION", + "FUNCTION"); + next; + } elsif (/^\s*DECLARE_ASN1_ENCODE_FUNCTIONS_const\s*\(\s*(\w*)\s*,\s*(\w*)\s*\)/) { + $def .= "int d2i_$2(void);"; + $def .= "int i2d_$2(void);"; + # Variant for platforms that do not + # have to access global variables + # in shared libraries through functions + $def .= + "#INFO:" + .join(',',"!EXPORT_VAR_AS_FUNCTION",@current_platforms).":" + .join(',',@current_algorithms).";"; + $def .= "OPENSSL_EXTERN int $2_it;"; + $def .= + "#INFO:" + .join(',',@current_platforms).":" + .join(',',@current_algorithms).";"; + # Variant for platforms that have to + # access global variables in shared + # libraries through functions + &$make_variant("$2_it","$2_it", + "EXPORT_VAR_AS_FUNCTION", + "FUNCTION"); + next; + } elsif (/^\s*DECLARE_ASN1_ALLOC_FUNCTIONS\s*\(\s*(\w*)\s*\)/) { + $def .= "int $1_free(void);"; + $def .= "int $1_new(void);"; + next; + } elsif (/^\s*DECLARE_ASN1_FUNCTIONS_name\s*\(\s*(\w*)\s*,\s*(\w*)\s*\)/) { + $def .= "int d2i_$2(void);"; + $def .= "int i2d_$2(void);"; + $def .= "int $2_free(void);"; + $def .= "int $2_new(void);"; + # Variant for platforms that do not + # have to access global variables + # in shared libraries through functions + $def .= + "#INFO:" + .join(',',"!EXPORT_VAR_AS_FUNCTION",@current_platforms).":" + .join(',',@current_algorithms).";"; + $def .= "OPENSSL_EXTERN int $2_it;"; + $def .= + "#INFO:" + .join(',',@current_platforms).":" + .join(',',@current_algorithms).";"; + # Variant for platforms that have to + # access global variables in shared + # libraries through functions + &$make_variant("$2_it","$2_it", + "EXPORT_VAR_AS_FUNCTION", + "FUNCTION"); + next; + } elsif (/^\s*DECLARE_ASN1_ITEM\s*\(\s*(\w*)\s*\)/) { + # Variant for platforms that do not + # have to access global variables + # in shared libraries through functions + $def .= + "#INFO:" + .join(',',"!EXPORT_VAR_AS_FUNCTION",@current_platforms).":" + .join(',',@current_algorithms).";"; + $def .= "OPENSSL_EXTERN int $1_it;"; + $def .= + "#INFO:" + .join(',',@current_platforms).":" + .join(',',@current_algorithms).";"; + # Variant for platforms that have to + # access global variables in shared + # libraries through functions + &$make_variant("$1_it","$1_it", + "EXPORT_VAR_AS_FUNCTION", + "FUNCTION"); + next; + } elsif (/^\s*DECLARE_ASN1_NDEF_FUNCTION\s*\(\s*(\w*)\s*\)/) { + $def .= "int i2d_$1_NDEF(void);"; + } elsif (/^\s*DECLARE_ASN1_SET_OF\s*\(\s*(\w*)\s*\)/) { + next; + } elsif (/^\s*DECLARE_ASN1_PRINT_FUNCTION\s*\(\s*(\w*)\s*\)/) { + $def .= "int $1_print_ctx(void);"; + next; + } elsif (/^\s*DECLARE_ASN1_PRINT_FUNCTION_name\s*\(\s*(\w*)\s*,\s*(\w*)\s*\)/) { + $def .= "int $2_print_ctx(void);"; + next; + } elsif (/^\s*DECLARE_PKCS12_STACK_OF\s*\(\s*(\w*)\s*\)/) { + next; + } elsif (/^DECLARE_PEM_rw\s*\(\s*(\w*)\s*,/ || + /^DECLARE_PEM_rw_cb\s*\(\s*(\w*)\s*,/ || + /^DECLARE_PEM_rw_const\s*\(\s*(\w*)\s*,/ ) { + $def .= + "#INFO:" + .join(',',@current_platforms).":" + .join(',',"STDIO",@current_algorithms).";"; + $def .= "int PEM_read_$1(void);"; + $def .= "int PEM_write_$1(void);"; + $def .= + "#INFO:" + .join(',',@current_platforms).":" + .join(',',@current_algorithms).";"; + # Things that are everywhere + $def .= "int PEM_read_bio_$1(void);"; + $def .= "int PEM_write_bio_$1(void);"; + next; + } elsif (/^DECLARE_PEM_write\s*\(\s*(\w*)\s*,/ || + /^DECLARE_PEM_write_const\s*\(\s*(\w*)\s*,/ || + /^DECLARE_PEM_write_cb\s*\(\s*(\w*)\s*,/ ) { + $def .= + "#INFO:" + .join(',',@current_platforms).":" + .join(',',"STDIO",@current_algorithms).";"; + $def .= "int PEM_write_$1(void);"; + $def .= + "#INFO:" + .join(',',@current_platforms).":" + .join(',',@current_algorithms).";"; + # Things that are everywhere + $def .= "int PEM_write_bio_$1(void);"; + next; + } elsif (/^DECLARE_PEM_read\s*\(\s*(\w*)\s*,/ || + /^DECLARE_PEM_read_cb\s*\(\s*(\w*)\s*,/ ) { + $def .= + "#INFO:" + .join(',',@current_platforms).":" + .join(',',"STDIO",@current_algorithms).";"; + $def .= "int PEM_read_$1(void);"; + $def .= + "#INFO:" + .join(',',@current_platforms).":" + .join(',',"STDIO",@current_algorithms).";"; + # Things that are everywhere + $def .= "int PEM_read_bio_$1(void);"; + next; + } elsif (/^OPENSSL_DECLARE_GLOBAL\s*\(\s*(\w*)\s*,\s*(\w*)\s*\)/) { + # Variant for platforms that do not + # have to access global variables + # in shared libraries through functions + $def .= + "#INFO:" + .join(',',"!EXPORT_VAR_AS_FUNCTION",@current_platforms).":" + .join(',',@current_algorithms).";"; + $def .= "OPENSSL_EXTERN int _shadow_$2;"; + $def .= + "#INFO:" + .join(',',@current_platforms).":" + .join(',',@current_algorithms).";"; + # Variant for platforms that have to + # access global variables in shared + # libraries through functions + &$make_variant("_shadow_$2","_shadow_$2", + "EXPORT_VAR_AS_FUNCTION", + "FUNCTION"); + } elsif (/^\s*DEPRECATEDIN/) { + $parens = count_parens($_); + if ($parens == 0) { + $def .= do_deprecated($_, + \@current_platforms, + \@current_algorithms); + } else { + $stored_multiline = $_; + print STDERR "DEBUG: Found multiline DEPRECATEDIN starting with: $stored_multiline\n" if $debug; + next; + } + } elsif ($tag{'CONST_STRICT'} != 1) { + if (/\{|\/\*|\([^\)]*$/) { + $line = $_; + } else { + $def .= $_; + } + } + } + } + close(IN); + die "$file: Unmatched tags\n" if $#tag >= 0; + + my $algs; + my $plays; + + print STDERR "DEBUG: postprocessing ----------\n" if $debug; + foreach (split /;/, $def) { + my $s; my $k = "FUNCTION"; my $p; my $a; + s/^[\n\s]*//g; + s/[\n\s]*$//g; + next if(/\#undef/); + next if(/typedef\W/); + next if(/\#define/); + + print STDERR "TRACE: processing $_\n" if $trace && !/^\#INFO:/; + # Reduce argument lists to empty () + # fold round brackets recursively: (t(*v)(t),t) -> (t{}{},t) -> {} + my $nsubst = 1; # prevent infinite loop, e.g., on int fn() + while($nsubst && /\(.*\)/s) { + $nsubst = s/\([^\(\)]+\)/\{\}/gs; + $nsubst+= s/\(\s*\*\s*(\w+)\s*\{\}\s*\)/$1/gs; #(*f{}) -> f + } + # pretend as we didn't use curly braces: {} -> () + s/\{\}/\(\)/gs; + + s/STACK_OF\(\)/void/gs; + s/LHASH_OF\(\)/void/gs; + + print STDERR "DEBUG: \$_ = \"$_\"\n" if $debug; + if (/^\#INFO:([^:]*):(.*)$/) { + $plats = $1; + $algs = $2; + print STDERR "DEBUG: found info on platforms ($plats) and algorithms ($algs)\n" if $debug; + next; + } elsif (/^\s*OPENSSL_EXTERN\s.*?(\w+(\{[0-9]+\})?)(\[[0-9]*\])*\s*$/) { + $s = $1; + $k = "VARIABLE"; + print STDERR "DEBUG: found external variable $s\n" if $debug; + } elsif (/TYPEDEF_\w+_OF/s) { + next; + } elsif (/(\w+)\s*\(\).*/s) { # first token prior [first] () is + $s = $1; # a function name! + print STDERR "DEBUG: found function $s\n" if $debug; + } elsif (/\(/ and not (/=/)) { + print STDERR "File $file: cannot parse: $_;\n"; + next; + } else { + next; + } + + $syms{$s} = 1; + $kind{$s} = $k; + + $p = $plats; + $a = $algs; + + $platform{$s} = + &reduce_platforms((defined($platform{$s})?$platform{$s}.',':"").$p); + $algorithm{$s} .= ','.$a; + + if (defined($variant{$s})) { + foreach $v (split /;/,$variant{$s}) { + (my $r, my $p, my $k) = split(/:/,$v); + my $ip = join ',',map({ /^!(.*)$/ ? $1 : "!".$_ } split /,/, $p); + $syms{$r} = 1; + if (!defined($k)) { $k = $kind{$s}; } + $kind{$r} = $k."(".$s.")"; + $algorithm{$r} = $algorithm{$s}; + $platform{$r} = &reduce_platforms($platform{$s}.",".$p.",".$p); + $platform{$s} = &reduce_platforms($platform{$s}.','.$ip.','.$ip); + print STDERR "DEBUG: \$variant{\"$s\"} = ",$v,"; \$r = $r; \$p = ",$platform{$r},"; \$a = ",$algorithm{$r},"; \$kind = ",$kind{$r},"\n" if $debug; + } + } + print STDERR "DEBUG: \$s = $s; \$p = ",$platform{$s},"; \$a = ",$algorithm{$s},"; \$kind = ",$kind{$s},"\n" if $debug; + } + } + + # Info we know about + + push @ret, map { $_."\\".&info_string($_,"EXIST", + $platform{$_}, + $kind{$_}, + $algorithm{$_}) } keys %syms; + + if (keys %unknown_algorithms) { + print STDERR "WARNING: mkdef.pl doesn't know the following algorithms:\n"; + print STDERR "\t",join("\n\t",keys %unknown_algorithms),"\n"; + } + return(@ret); +} + +# Param: string of comma-separated platform-specs. +sub reduce_platforms +{ + my ($platforms) = @_; + my $pl = defined($platforms) ? $platforms : ""; + my %p = map { $_ => 0 } split /,/, $pl; + my $ret; + + print STDERR "DEBUG: Entered reduce_platforms with \"$platforms\"\n" + if $debug; + # We do this, because if there's code like the following, it really + # means the function exists in all cases and should therefore be + # everywhere. By increasing and decreasing, we may attain 0: + # + # ifndef WIN16 + # int foo(); + # else + # int _fat foo(); + # endif + foreach $platform (split /,/, $pl) { + if ($platform =~ /^!(.*)$/) { + $p{$1}--; + } else { + $p{$platform}++; + } + } + foreach $platform (keys %p) { + if ($p{$platform} == 0) { delete $p{$platform}; } + } + + delete $p{""}; + + $ret = join(',',sort(map { $p{$_} < 0 ? "!".$_ : $_ } keys %p)); + print STDERR "DEBUG: Exiting reduce_platforms with \"$ret\"\n" + if $debug; + return $ret; +} + +sub info_string +{ + (my $symbol, my $exist, my $platforms, my $kind, my $algorithms) = @_; + + my %a = defined($algorithms) ? + map { $_ => 1 } split /,/, $algorithms : (); + my $k = defined($kind) ? $kind : "FUNCTION"; + my $ret; + my $p = &reduce_platforms($platforms); + + delete $a{""}; + + $ret = $exist; + $ret .= ":".$p; + $ret .= ":".$k; + $ret .= ":".join(',',sort keys %a); + return $ret; +} + +sub maybe_add_info +{ + (my $name, *nums, my @symbols) = @_; + my $sym; + my $new_info = 0; + my %syms=(); + + foreach $sym (@symbols) { + (my $s, my $i) = split /\\/, $sym; + if (defined($nums{$s})) { + $i =~ s/^(.*?:.*?:\w+)(\(\w+\))?/$1/; + (my $n, my $vers, my $dummy) = split /\\/, $nums{$s}; + if (!defined($dummy) || $i ne $dummy) { + $nums{$s} = $n."\\".$vers."\\".$i; + $new_info++; + print STDERR "DEBUG: maybe_add_info for $s: \"$dummy\" => \"$i\"\n" if $debug; + } + } + $syms{$s} = 1; + } + + my @s=sort { &parse_number($nums{$a},"n") <=> &parse_number($nums{$b},"n") } keys %nums; + foreach $sym (@s) { + (my $n, my $vers, my $i) = split /\\/, $nums{$sym}; + if (!defined($syms{$sym}) && $i !~ /^NOEXIST:/) { + $new_info++; + print STDERR "DEBUG: maybe_add_info for $sym: -> undefined\n" if $debug; + } + } + if ($new_info) { + print STDERR "$name: $new_info old symbols have updated info\n"; + if (!$do_rewrite) { + print STDERR "You should do a rewrite to fix this.\n"; + } + } else { + } +} + +# Param: string of comma-separated keywords, each possibly prefixed with a "!" +sub is_valid +{ + my ($keywords_txt,$platforms) = @_; + my (@keywords) = split /,/,$keywords_txt; + my ($falsesum, $truesum) = (0, 1); + + # Param: one keyword + sub recognise + { + my ($keyword,$platforms) = @_; + + if ($platforms) { + # platforms + if ($keyword eq "UNIX" && $UNIX) { return 1; } + if ($keyword eq "VMS" && $VMS) { return 1; } + if ($keyword eq "WIN32" && $W32) { return 1; } + if ($keyword eq "_WIN32" && $W32) { return 1; } + if ($keyword eq "WINNT" && $NT) { return 1; } + # Special platforms: + # EXPORT_VAR_AS_FUNCTION means that global variables + # will be represented as functions. + if ($keyword eq "EXPORT_VAR_AS_FUNCTION" && $W32) { + return 1; + } + if ($keyword eq "ZLIB" && $zlib) { return 1; } + return 0; + } else { + # algorithms + if ($disabled_algorithms{$keyword}) { return 0;} + + # Nothing recognise as true + return 1; + } + } + + foreach $k (@keywords) { + if ($k =~ /^!(.*)$/) { + $falsesum += &recognise($1,$platforms); + } else { + $truesum *= &recognise($k,$platforms); + } + } + print STDERR "DEBUG: [",$#keywords,",",$#keywords < 0,"] is_valid($keywords_txt) => (\!$falsesum) && $truesum = ",(!$falsesum) && $truesum,"\n" if $debug; + return (!$falsesum) && $truesum; +} + +sub print_test_file +{ + (*OUT,my $name,*nums,my $testall,my @symbols)=@_; + my $n = 1; my @e; my @r; + my $sym; my $prev = ""; my $prefSSLeay; + + (@e)=grep(/^SSLeay(\{[0-9]+\})?\\.*?:.*?:.*/,@symbols); + (@r)=grep(/^\w+(\{[0-9]+\})?\\.*?:.*?:.*/ && !/^SSLeay(\{[0-9]+\})?\\.*?:.*?:.*/,@symbols); + @symbols=((sort @e),(sort @r)); + + foreach $sym (@symbols) { + (my $s, my $i) = $sym =~ /^(.*?)\\(.*)$/; + my $v = 0; + $v = 1 if $i=~ /^.*?:.*?:VARIABLE/; + my $p = ($i =~ /^[^:]*:([^:]*):/,$1); + my $a = ($i =~ /^[^:]*:[^:]*:[^:]*:([^:]*)/,$1); + if (!defined($nums{$s})) { + print STDERR "Warning: $s does not have a number assigned\n" + if(!$do_update); + } elsif (is_valid($p,1) && is_valid($a,0)) { + my $s2 = ($s =~ /^(.*?)(\{[0-9]+\})?$/, $1); + if ($prev eq $s2) { + print OUT "\t/* The following has already appeared previously */\n"; + print STDERR "Warning: Symbol '",$s2,"' redefined. old=",($nums{$prev} =~ /^(.*?)\\/,$1),", new=",($nums{$s2} =~ /^(.*?)\\/,$1),"\n"; + } + $prev = $s2; # To warn about duplicates... + + (my $nn, my $vers, my $ni) = split /\\/, $nums{$s2}; + if ($v) { + print OUT "\textern int $s2; /* type unknown */ /* $nn $ni */\n"; + } else { + print OUT "\textern int $s2(); /* type unknown */ /* $nn $ni */\n"; + } + } + } +} + +sub get_version +{ + return $config{version}; +} + +sub print_def_file +{ + (*OUT,my $name,*nums,my @symbols)=@_; + my $n = 1; my @e; my @r; my @v; my $prev=""; + my $liboptions=""; + my $libname = $name; + my $http_vendor = 'www.openssl.org/'; + my $version = get_version(); + my $what = "OpenSSL: implementation of Secure Socket Layer"; + my $description = "$what $version, $name - http://$http_vendor"; + my $prevsymversion = "", $prevprevsymversion = ""; + # For VMS + my $prevnum = 0; + my $symvtextcount = 0; + + if ($W32) + { + print OUT <<"EOF"; +; +; Definition file for the DLL version of the $name library from OpenSSL +; + +LIBRARY $libname $liboptions + +EOF + + print "EXPORTS\n"; + } + elsif ($VMS) + { + print OUT <<"EOF"; +IDENTIFICATION=$version +CASE_SENSITIVE=YES +SYMBOL_VECTOR=(- +EOF + $symvtextcount = 16; # length of "SYMBOL_VECTOR=(-" + } + + (@r)=grep(/^\w+(\{[0-9]+\})?\\.*?:.*?:FUNCTION/,@symbols); + (@v)=grep(/^\w+(\{[0-9]+\})?\\.*?:.*?:VARIABLE/,@symbols); + if ($VMS) { + # VMS needs to have the symbols on slot number order + @symbols=(map { $_->[1] } + sort { $a->[0] <=> $b->[0] } + map { (my $s, my $i) = $_ =~ /^(.*?)\\(.*)$/; + die "Error: $s doesn't have a number assigned\n" + if !defined($nums{$s}); + (my $n, my @rest) = split /\\/, $nums{$s}; + [ $n, $_ ] } (@e, @r, @v)); + } else { + @symbols=((sort @e),(sort @r), (sort @v)); + } + + my ($baseversion, $currversion) = get_openssl_version(); + my $thisversion; + do { + if (!defined($thisversion)) { + $thisversion = $baseversion; + } else { + $thisversion = get_next_version($thisversion); + } + foreach $sym (@symbols) { + (my $s, my $i) = $sym =~ /^(.*?)\\(.*)$/; + my $v = 0; + $v = 1 if $i =~ /^.*?:.*?:VARIABLE/; + if (!defined($nums{$s})) { + die "Error: $s does not have a number assigned\n" + if(!$do_update); + } else { + (my $n, my $symversion, my $dummy) = split /\\/, $nums{$s}; + my %pf = (); + my $p = ($i =~ /^[^:]*:([^:]*):/,$1); + my $a = ($i =~ /^[^:]*:[^:]*:[^:]*:([^:]*)/,$1); + if (is_valid($p,1) && is_valid($a,0)) { + my $s2 = ($s =~ /^(.*?)(\{[0-9]+\})?$/, $1); + if ($prev eq $s2) { + print STDERR "Warning: Symbol '",$s2, + "' redefined. old=",($nums{$prev} =~ /^(.*?)\\/,$1), + ", new=",($nums{$s2} =~ /^(.*?)\\/,$1),"\n"; + } + $prev = $s2; # To warn about duplicates... + if($linux) { + next if $symversion ne $thisversion; + if ($symversion ne $prevsymversion) { + if ($prevsymversion ne "") { + if ($prevprevsymversion ne "") { + print OUT "} OPENSSL${SO_VARIANT}_" + ."$prevprevsymversion;\n\n"; + } else { + print OUT "};\n\n"; + } + } + print OUT "OPENSSL${SO_VARIANT}_$symversion {\n global:\n"; + $prevprevsymversion = $prevsymversion; + $prevsymversion = $symversion; + } + print OUT " $s2;\n"; + } elsif ($aix) { + print OUT "$s2\n"; + } elsif ($VMS) { + while(++$prevnum < $n) { + my $symline=" ,SPARE -\n ,SPARE -\n"; + if ($symvtextcount + length($symline) - 2 > 1024) { + print OUT ")\nSYMBOL_VECTOR=(-\n"; + $symvtextcount = 16; # length of "SYMBOL_VECTOR=(-" + } + if ($symvtextcount == 16) { + # Take away first comma + $symline =~ s/,//; + } + print OUT $symline; + $symvtextcount += length($symline) - 2; + } + (my $s_uc = $s) =~ tr/a-z/A-Z/; + my $symtype= + $v ? "DATA" : "PROCEDURE"; + my $symline= + ($s_uc ne $s + ? " ,$s_uc/$s=$symtype -\n ,$s=$symtype -\n" + : " ,$s=$symtype -\n ,SPARE -\n"); + if ($symvtextcount + length($symline) - 2 > 1024) { + print OUT ")\nSYMBOL_VECTOR=(-\n"; + $symvtextcount = 16; # length of "SYMBOL_VECTOR=(-" + } + if ($symvtextcount == 16) { + # Take away first comma + $symline =~ s/,//; + } + print OUT $symline; + $symvtextcount += length($symline) - 2; + } elsif($v) { + printf OUT " %s%-39s DATA\n", + ($W32)?"":"_",$s2; + } else { + printf OUT " %s%s\n", + ($W32)?"":"_",$s2; + } + } + } + } + } while ($linux && $thisversion ne $currversion); + if ($linux) { + if ($prevprevsymversion ne "") { + print OUT " local: *;\n} OPENSSL${SO_VARIANT}_$prevprevsymversion;\n\n"; + } else { + print OUT " local: *;\n};\n\n"; + } + } elsif ($VMS) { + print OUT ")\n"; + (my $libvmaj, my $libvmin, my $libvedit) = + $currversion =~ /^(\d+)_(\d+)_(\d+)[a-z]{0,2}$/; + # The reason to multiply the edit number with 100 is to make space + # for the possibility that we want to encode the patch letters + print OUT "GSMATCH=LEQUAL,",($libvmaj * 100 + $libvmin),",",($libvedit * 100),"\n"; + } + printf OUT "\n"; +} + +sub load_numbers +{ + my($name)=@_; + my(@a,%ret); + my $prevversion; + + $max_num = 0; + $num_noinfo = 0; + $prev = ""; + $prev_cnt = 0; + + my ($baseversion, $currversion) = get_openssl_version(); + + open(IN,"<$name") || die "unable to open $name:$!\n"; + while () { + s|\R$||; # Better chomp + s/#.*$//; + next if /^\s*$/; + @a=split; + if (defined $ret{$a[0]}) { + # This is actually perfectly OK + #print STDERR "Warning: Symbol '",$a[0],"' redefined. old=",$ret{$a[0]},", new=",$a[1],"\n"; + } + if ($max_num > $a[1]) { + print STDERR "Warning: Number decreased from ",$max_num," to ",$a[1],"\n"; + } + elsif ($max_num == $a[1]) { + # This is actually perfectly OK + #print STDERR "Warning: Symbol ",$a[0]," has same number as previous ",$prev,": ",$a[1],"\n"; + if ($a[0] eq $prev) { + $prev_cnt++; + $a[0] .= "{$prev_cnt}"; + } + } + else { + $prev_cnt = 0; + } + if ($#a < 2) { + # Existence will be proven later, in do_defs + $ret{$a[0]}=$a[1]; + $num_noinfo++; + } else { + #Sanity check the version number + if (defined $prevversion) { + check_version_lte($prevversion, $a[2]); + } + check_version_lte($a[2], $currversion); + $prevversion = $a[2]; + $ret{$a[0]}=$a[1]."\\".$a[2]."\\".$a[3]; # \\ is a special marker + } + $max_num = $a[1] if $a[1] > $max_num; + $prev=$a[0]; + } + if ($num_noinfo) { + print STDERR "Warning: $num_noinfo symbols were without info." if $verbose || !$do_rewrite; + if ($do_rewrite) { + printf STDERR " The rewrite will fix this.\n" if $verbose; + } else { + printf STDERR " You should do a rewrite to fix this.\n"; + } + } + close(IN); + return(%ret); +} + +sub parse_number +{ + (my $str, my $what) = @_; + (my $n, my $v, my $i) = split(/\\/,$str); + if ($what eq "n") { + return $n; + } else { + return $i; + } +} + +sub rewrite_numbers +{ + (*OUT,$name,*nums,@symbols)=@_; + my $thing; + + my @r = grep(/^\w+(\{[0-9]+\})?\\.*?:.*?:\w+\(\w+\)/,@symbols); + my $r; my %r; my %rsyms; + foreach $r (@r) { + (my $s, my $i) = split /\\/, $r; + my $a = $1 if $i =~ /^.*?:.*?:\w+\((\w+)\)/; + $i =~ s/^(.*?:.*?:\w+)\(\w+\)/$1/; + $r{$a} = $s."\\".$i; + $rsyms{$s} = 1; + } + + my %syms = (); + foreach $_ (@symbols) { + (my $n, my $i) = split /\\/; + $syms{$n} = 1; + } + + my @s=sort { + &parse_number($nums{$a},"n") <=> &parse_number($nums{$b},"n") + || $a cmp $b + } keys %nums; + foreach $sym (@s) { + (my $n, my $vers, my $i) = split /\\/, $nums{$sym}; + next if defined($i) && $i =~ /^.*?:.*?:\w+\(\w+\)/; + next if defined($rsyms{$sym}); + print STDERR "DEBUG: rewrite_numbers for sym = ",$sym,": i = ",$i,", n = ",$n,", rsym{sym} = ",$rsyms{$sym},"syms{sym} = ",$syms{$sym},"\n" if $debug; + $i="NOEXIST::FUNCTION:" + if !defined($i) || $i eq "" || !defined($syms{$sym}); + my $s2 = $sym; + $s2 =~ s/\{[0-9]+\}$//; + printf OUT "%s%-39s %d\t%s\t%s\n","",$s2,$n,$vers,$i; + if (exists $r{$sym}) { + (my $s, $i) = split /\\/,$r{$sym}; + my $s2 = $s; + $s2 =~ s/\{[0-9]+\}$//; + printf OUT "%s%-39s %d\t%s\t%s\n","",$s2,$n,$vers,$i; + } + } +} + +sub update_numbers +{ + (*OUT,$name,*nums,my $start_num, my @symbols)=@_; + my $new_syms = 0; + my $basevers; + my $vers; + + ($basevers, $vers) = get_openssl_version(); + + my @r = grep(/^\w+(\{[0-9]+\})?\\.*?:.*?:\w+\(\w+\)/,@symbols); + my $r; my %r; my %rsyms; + foreach $r (@r) { + (my $s, my $i) = split /\\/, $r; + my $a = $1 if $i =~ /^.*?:.*?:\w+\((\w+)\)/; + $i =~ s/^(.*?:.*?:\w+)\(\w+\)/$1/; + $r{$a} = $s."\\".$i; + $rsyms{$s} = 1; + } + + foreach $sym (@symbols) { + (my $s, my $i) = $sym =~ /^(.*?)\\(.*)$/; + next if $i =~ /^.*?:.*?:\w+\(\w+\)/; + next if defined($rsyms{$sym}); + die "ERROR: Symbol $sym had no info attached to it." + if $i eq ""; + if (!exists $nums{$s}) { + $new_syms++; + my $s2 = $s; + $s2 =~ s/\{[0-9]+\}$//; + printf OUT "%s%-39s %d\t%s\t%s\n","",$s2, ++$start_num,$vers,$i; + if (exists $r{$s}) { + ($s, $i) = split /\\/,$r{$s}; + $s =~ s/\{[0-9]+\}$//; + printf OUT "%s%-39s %d\t%s\t%s\n","",$s, $start_num,$vers,$i; + } + } + } + if($new_syms) { + print STDERR "$name: Added $new_syms new symbols\n"; + } else { + print STDERR "$name: No new symbols added\n"; + } +} + +sub check_existing +{ + (*nums, my @symbols)=@_; + my %existing; my @remaining; + @remaining=(); + foreach $sym (@symbols) { + (my $s, my $i) = $sym =~ /^(.*?)\\(.*)$/; + $existing{$s}=1; + } + foreach $sym (keys %nums) { + if (!exists $existing{$sym}) { + push @remaining, $sym; + } + } + if(@remaining) { + print STDERR "The following symbols do not seem to exist:\n"; + foreach $sym (@remaining) { + print STDERR "\t",$sym,"\n"; + } + } +} + +sub count_parens +{ + my $line = shift(@_); + + my $open = $line =~ tr/\(//; + my $close = $line =~ tr/\)//; + + return $open - $close; +} + +#Parse opensslv.h to get the current version number. Also work out the base +#version, i.e. the lowest version number that is binary compatible with this +#version +sub get_openssl_version() +{ + my $fn = catfile($config{sourcedir},"include","openssl","opensslv.h"); + open (IN, "$fn") || die "Can't open opensslv.h"; + + while() { + if (/OPENSSL_VERSION_TEXT\s+"OpenSSL (\d\.\d\.)(\d[a-z]*)(-| )/) { + my $suffix = $2; + (my $baseversion = $1) =~ s/\./_/g; + close IN; + return ($baseversion."0", $baseversion.$suffix); + } + } + die "Can't find OpenSSL version number\n"; +} + +#Given an OpenSSL version number, calculate the next version number. If the +#version number gets to a.b.czz then we go to a.b.(c+1) +sub get_next_version() +{ + my $thisversion = shift; + + my ($base, $letter) = $thisversion =~ /^(\d_\d_\d)([a-z]{0,2})$/; + + if ($letter eq "zz") { + my $lastnum = substr($base, -1); + return substr($base, 0, length($base)-1).(++$lastnum); + } + return $base.get_next_letter($letter); +} + +#Given the letters off the end of an OpenSSL version string, calculate what +#the letters for the next release would be. +sub get_next_letter() +{ + my $thisletter = shift; + my $baseletter = ""; + my $endletter; + + if ($thisletter eq "") { + return "a"; + } + if ((length $thisletter) > 1) { + ($baseletter, $endletter) = $thisletter =~ /([a-z]+)([a-z])/; + } else { + $endletter = $thisletter; + } + + if ($endletter eq "z") { + return $thisletter."a"; + } else { + return $baseletter.(++$endletter); + } +} + +#Check if a version is less than or equal to the current version. Its a fatal +#error if not. They must also only differ in letters, or the last number (i.e. +#the first two numbers must be the same) +sub check_version_lte() +{ + my ($testversion, $currversion) = @_; + my $lentv; + my $lencv; + my $cvbase; + + my ($cvnums) = $currversion =~ /^(\d_\d_\d)[a-z]*$/; + my ($tvnums) = $testversion =~ /^(\d_\d_\d)[a-z]*$/; + + #Die if we can't parse the version numbers or they don't look sane + die "Invalid version number: $testversion and $currversion\n" + if (!defined($cvnums) || !defined($tvnums) + || length($cvnums) != 5 + || length($tvnums) != 5); + + #If the base versions (without letters) don't match check they only differ + #in the last number + if ($cvnums ne $tvnums) { + die "Invalid version number: $testversion " + ."for current version $currversion\n" + if (substr($cvnums, 0, 4) ne substr($tvnums, 0, 4)); + return; + } + #If we get here then the base version (i.e. the numbers) are the same - they + #only differ in the letters + + $lentv = length $testversion; + $lencv = length $currversion; + + #If the testversion has more letters than the current version then it must + #be later (or malformed) + if ($lentv > $lencv) { + die "Invalid version number: $testversion " + ."is greater than $currversion\n"; + } + + #Get the last letter from the current version + my ($cvletter) = $currversion =~ /([a-z])$/; + if (defined $cvletter) { + ($cvbase) = $currversion =~ /(\d_\d_\d[a-z]*)$cvletter$/; + } else { + $cvbase = $currversion; + } + die "Unable to parse version number $currversion" if (!defined $cvbase); + my $tvbase; + my ($tvletter) = $testversion =~ /([a-z])$/; + if (defined $tvletter) { + ($tvbase) = $testversion =~ /(\d_\d_\d[a-z]*)$tvletter$/; + } else { + $tvbase = $testversion; + } + die "Unable to parse version number $testversion" if (!defined $tvbase); + + if ($lencv > $lentv) { + #If current version has more letters than testversion then testversion + #minus the final letter must be a substring of the current version + die "Invalid version number $testversion " + ."is greater than $currversion or is invalid\n" + if (index($cvbase, $tvbase) != 0); + } else { + #If both versions have the same number of letters then they must be + #equal up to the last letter, and the last letter in testversion must + #be less than or equal to the last letter in current version. + die "Invalid version number $testversion " + ."is greater than $currversion\n" + if (($cvbase ne $tvbase) && ($tvletter gt $cvletter)); + } +} + +sub do_deprecated() +{ + my ($decl, $plats, $algs) = @_; + $decl =~ /^\s*(DEPRECATEDIN_\d+_\d+_\d+)\s*\((.*)\)\s*$/ + or die "Bad DEPRECATEDIN: $decl\n"; + my $info1 .= "#INFO:"; + $info1 .= join(',', @{$plats}) . ":"; + my $info2 = $info1; + $info1 .= join(',',@{$algs}, $1) . ";"; + $info2 .= join(',',@{$algs}) . ";"; + return $info1 . $2 . ";" . $info2; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/util/mkdir-p.pl b/trunk/3rdparty/openssl-1.1-fit/util/mkdir-p.pl new file mode 100755 index 000000000..328060243 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/mkdir-p.pl @@ -0,0 +1,44 @@ +#! /usr/bin/env perl +# Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# On some systems, the -p option to mkdir (= also create any missing parent +# directories) is not available. + +my $arg; + +foreach $arg (@ARGV) { + $arg =~ tr|\\|/|; + &do_mkdir_p($arg); +} + + +sub do_mkdir_p { + local($dir) = @_; + + $dir =~ s|/*\Z(?!\n)||s; + + if (-d $dir) { + return; + } + + if ($dir =~ m|[^/]/|s) { + local($parent) = $dir; + $parent =~ s|[^/]*\Z(?!\n)||s; + + do_mkdir_p($parent); + } + + unless (mkdir($dir, 0777)) { + if (-d $dir) { + # We raced against another instance doing the same thing. + return; + } + die "Cannot create directory $dir: $!\n"; + } + print "created directory `$dir'\n"; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/util/mkerr.pl b/trunk/3rdparty/openssl-1.1-fit/util/mkerr.pl new file mode 100755 index 000000000..0ea02961a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/mkerr.pl @@ -0,0 +1,753 @@ +#! /usr/bin/env perl +# Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use strict; +use warnings; + +use lib "."; +use configdata; + +my $config = "crypto/err/openssl.ec"; +my $debug = 0; +my $internal = 0; +my $nowrite = 0; +my $rebuild = 0; +my $reindex = 0; +my $static = 0; +my $unref = 0; +my %modules = (); + +my $errors = 0; +my @t = localtime(); +my $YEAR = $t[5] + 1900; + +sub phase +{ + my $text = uc(shift); + print STDERR "\n---\n$text\n" if $debug; +} + +sub help +{ + print STDERR <<"EOF"; +mkerr.pl [options] [files...] + +Options: + + -conf FILE Use the named config file FILE instead of the default. + + -debug Verbose output debugging on stderr. + + -internal Generate code that is to be built as part of OpenSSL itself. + Also scans internal list of files. + + -module M Only useful with -internal! + Only write files for library module M. Whether files are + actually written or not depends on other options, such as + -rebuild. + Note: this option is cumulative. If not given at all, all + internal modules will be considered. + + -nowrite Do not write the header/source files, even if changed. + + -rebuild Rebuild all header and C source files, even if there + were no changes. + + -reindex Ignore previously assigned values (except for R records in + the config file) and renumber everything starting at 100. + + -static Make the load/unload functions static. + + -unref List all unreferenced function and reason codes on stderr; + implies -nowrite. + + -help Show this help text. + + ... Additional arguments are added to the file list to scan, + if '-internal' was NOT specified on the command line. + +EOF +} + +while ( @ARGV ) { + my $arg = $ARGV[0]; + last unless $arg =~ /-.*/; + $arg = $1 if $arg =~ /-(-.*)/; + if ( $arg eq "-conf" ) { + $config = $ARGV[1]; + shift @ARGV; + } elsif ( $arg eq "-debug" ) { + $debug = 1; + $unref = 1; + } elsif ( $arg eq "-internal" ) { + $internal = 1; + } elsif ( $arg eq "-nowrite" ) { + $nowrite = 1; + } elsif ( $arg eq "-rebuild" ) { + $rebuild = 1; + } elsif ( $arg eq "-reindex" ) { + $reindex = 1; + } elsif ( $arg eq "-static" ) { + $static = 1; + } elsif ( $arg eq "-unref" ) { + $unref = 1; + $nowrite = 1; + } elsif ( $arg eq "-module" ) { + shift @ARGV; + $modules{uc $ARGV[0]} = 1; + } elsif ( $arg =~ /-*h(elp)?/ ) { + &help(); + exit; + } elsif ( $arg =~ /-.*/ ) { + die "Unknown option $arg; use -h for help.\n"; + } + shift @ARGV; +} + +my @source; +if ( $internal ) { + die "Cannot mix -internal and -static\n" if $static; + die "Extra parameters given.\n" if @ARGV; + @source = ( glob('crypto/*.c'), glob('crypto/*/*.c'), + glob('ssl/*.c'), glob('ssl/*/*.c') ); +} else { + die "-module isn't useful without -internal\n" if scalar keys %modules > 0; + @source = @ARGV; +} + +# Data parsed out of the config and state files. +my %hinc; # lib -> header +my %libinc; # header -> lib +my %cskip; # error_file -> lib +my %errorfile; # lib -> error file name +my %fmax; # lib -> max assigned function code +my %rmax; # lib -> max assigned reason code +my %fassigned; # lib -> colon-separated list of assigned function codes +my %rassigned; # lib -> colon-separated list of assigned reason codes +my %fnew; # lib -> count of new function codes +my %rnew; # lib -> count of new reason codes +my %rextra; # "extra" reason code -> lib +my %rcodes; # reason-name -> value +my %ftrans; # old name -> #define-friendly name (all caps) +my %fcodes; # function-name -> value +my $statefile; # state file with assigned reason and function codes +my %strings; # define -> text + +# Read and parse the config file +open(IN, "$config") || die "Can't open config file $config, $!,"; +while ( ) { + next if /^#/ || /^$/; + if ( /^L\s+(\S+)\s+(\S+)\s+(\S+)/ ) { + my $lib = $1; + my $hdr = $2; + my $err = $3; + $hinc{$lib} = $hdr; + $libinc{$hdr} = $lib; + $cskip{$err} = $lib; + next if $err eq 'NONE'; + $errorfile{$lib} = $err; + $fmax{$lib} = 100; + $rmax{$lib} = 100; + $fassigned{$lib} = ":"; + $rassigned{$lib} = ":"; + $fnew{$lib} = 0; + $rnew{$lib} = 0; + } elsif ( /^R\s+(\S+)\s+(\S+)/ ) { + $rextra{$1} = $2; + $rcodes{$1} = $2; + } elsif ( /^S\s+(\S+)/ ) { + $statefile = $1; + } else { + die "Illegal config line $_\n"; + } +} +close IN; + +if ( ! $statefile ) { + $statefile = $config; + $statefile =~ s/.ec/.txt/; +} + +# The statefile has all the previous assignments. +&phase("Reading state"); +my $skippedstate = 0; +if ( ! $reindex && $statefile ) { + open(STATE, "<$statefile") || die "Can't open $statefile, $!"; + + # Scan function and reason codes and store them: keep a note of the + # maximum code used. + while ( ) { + next if /^#/ || /^$/; + my $name; + my $code; + if ( /^(.+):(\d+):\\$/ ) { + $name = $1; + $code = $2; + my $next = ; + $next =~ s/^\s*(.*)\s*$/$1/; + die "Duplicate define $name" if exists $strings{$name}; + $strings{$name} = $next; + } elsif ( /^(\S+):(\d+):(.*)$/ ) { + $name = $1; + $code = $2; + die "Duplicate define $name" if exists $strings{$name}; + $strings{$name} = $3; + } else { + die "Bad line in $statefile:\n$_\n"; + } + my $lib = $name; + $lib =~ s/^((?:OSSL_|OPENSSL_)?[^_]{2,}).*$/$1/; + $lib = "SSL" if $lib =~ /TLS/; + if ( !defined $errorfile{$lib} ) { + print "Skipping $_"; + $skippedstate++; + next; + } + if ( $name =~ /^(?:OSSL_|OPENSSL_)?[A-Z0-9]{2,}_R_/ ) { + die "$lib reason code $code collision at $name\n" + if $rassigned{$lib} =~ /:$code:/; + $rassigned{$lib} .= "$code:"; + if ( !exists $rextra{$name} ) { + $rmax{$lib} = $code if $code > $rmax{$lib}; + } + $rcodes{$name} = $code; + } elsif ( $name =~ /^(?:OSSL_|OPENSSL_)?[A-Z0-9]{2,}_F_/ ) { + die "$lib function code $code collision at $name\n" + if $fassigned{$lib} =~ /:$code:/; + $fassigned{$lib} .= "$code:"; + $fmax{$lib} = $code if $code > $fmax{$lib}; + $fcodes{$name} = $code; + } else { + die "Bad line in $statefile:\n$_\n"; + } + } + close(STATE); + + if ( $debug ) { + foreach my $lib ( sort keys %rmax ) { + print STDERR "Reason codes for ${lib}:\n"; + if ( $rassigned{$lib} =~ m/^:(.*):$/ ) { + my @rassigned = sort { $a <=> $b } split( ":", $1 ); + print STDERR " ", join(' ', @rassigned), "\n"; + } else { + print STDERR " --none--\n"; + } + } + print STDERR "\n"; + foreach my $lib ( sort keys %fmax ) { + print STDERR "Function codes for ${lib}:\n"; + if ( $fassigned{$lib} =~ m/^:(.*):$/ ) { + my @fassigned = sort { $a <=> $b } split( ":", $1 ); + print STDERR " ", join(' ', @fassigned), "\n"; + } else { + print STDERR " --none--\n"; + } + } + } +} + +# Scan each header file and make a list of error codes +# and function names +&phase("Scanning headers"); +while ( ( my $hdr, my $lib ) = each %libinc ) { + next if $hdr eq "NONE"; + print STDERR " ." if $debug; + my $line = ""; + my $def = ""; + my $linenr = 0; + my $cpp = 0; + + open(IN, "<$hdr") || die "Can't open $hdr, $!,"; + while ( ) { + $linenr++; + + if ( $line ne '' ) { + $_ = $line . $_; + $line = ''; + } + + if ( /\\$/ ) { + $line = $_; + next; + } + + if ( /\/\*/ ) { + if ( not /\*\// ) { # multiline comment... + $line = $_; # ... just accumulate + next; + } else { + s/\/\*.*?\*\///gs; # wipe it + } + } + + if ( $cpp ) { + $cpp++ if /^#\s*if/; + $cpp-- if /^#\s*endif/; + next; + } + $cpp = 1 if /^#.*ifdef.*cplusplus/; # skip "C" declaration + + next if /^\#/; # skip preprocessor directives + + s/{[^{}]*}//gs; # ignore {} blocks + + if ( /\{|\/\*/ ) { # Add a so editor works... + $line = $_; + } else { + $def .= $_; + } + } + + # Delete any DECLARE_ macros + my $defnr = 0; + $def =~ s/DECLARE_\w+\([\w,\s]+\)//gs; + foreach ( split /;/, $def ) { + $defnr++; + # The goal is to collect function names from function declarations. + + s/^[\n\s]*//g; + s/[\n\s]*$//g; + + # Skip over recognized non-function declarations + next if /typedef\W/ or /DECLARE_STACK_OF/ or /TYPEDEF_.*_OF/; + + # Remove STACK_OF(foo) + s/STACK_OF\(\w+\)/void/; + + # Reduce argument lists to empty () + # fold round brackets recursively: (t(*v)(t),t) -> (t{}{},t) -> {} + while ( /\(.*\)/s ) { + s/\([^\(\)]+\)/\{\}/gs; + s/\(\s*\*\s*(\w+)\s*\{\}\s*\)/$1/gs; #(*f{}) -> f + } + + # pretend as we didn't use curly braces: {} -> () + s/\{\}/\(\)/gs; + + # Last token just before the first () is a function name. + if ( /(\w+)\s*\(\).*/s ) { + my $name = $1; + $name =~ tr/[a-z]/[A-Z]/; + $ftrans{$name} = $1; + } elsif ( /[\(\)]/ and not(/=/) ) { + print STDERR "Header $hdr: cannot parse: $_;\n"; + } + } + + next if $reindex; + + if ( $lib eq "SSL" && $rmax{$lib} >= 1000 ) { + print STDERR "SSL error codes 1000+ are reserved for alerts.\n"; + print STDERR "Any new alerts must be added to $config.\n"; + $errors++; + } + close IN; +} +print STDERR "\n" if $debug; + +# Scan each C source file and look for function and reason codes +# This is done by looking for strings that "look like" function or +# reason codes: basically anything consisting of all upper case and +# numerics which has _F_ or _R_ in it and which has the name of an +# error library at the start. This seems to work fine except for the +# oddly named structure BIO_F_CTX which needs to be ignored. +# If a code doesn't exist in list compiled from headers then mark it +# with the value "X" as a place holder to give it a value later. +# Store all function and reason codes found in %usedfuncs and %usedreasons +# so all those unreferenced can be printed out. +&phase("Scanning source"); +my %usedfuncs; +my %usedreasons; +foreach my $file ( @source ) { + # Don't parse the error source file. + next if exists $cskip{$file}; + open( IN, "<$file" ) || die "Can't open $file, $!,"; + my $func; + my $linenr = 0; + print STDERR "$file:\n" if $debug; + while ( ) { + + # skip obsoleted source files entirely! + last if /^#error\s+obsolete/; + $linenr++; + if ( !/;$/ && /^\**([a-zA-Z_].*[\s*])?([A-Za-z_0-9]+)\(.*([),]|$)/ ) { + /^([^()]*(\([^()]*\)[^()]*)*)\(/; + $1 =~ /([A-Za-z_0-9]*)$/; + $func = $1; + } + + if ( /(((?:OSSL_|OPENSSL_)?[A-Z0-9]{2,})_F_([A-Z0-9_]+))/ ) { + next unless exists $errorfile{$2}; + next if $1 eq "BIO_F_BUFFER_CTX"; + $usedfuncs{$1} = 1; + if ( !exists $fcodes{$1} ) { + print STDERR " New function $1\n" if $debug; + $fcodes{$1} = "X"; + $fnew{$2}++; + } + $ftrans{$3} = $func unless exists $ftrans{$3}; + if ( uc($func) ne $3 ) { + print STDERR "ERROR: mismatch $file:$linenr $func:$3\n"; + $errors++; + } + print STDERR " Function $1 = $fcodes{$1}\n" + if $debug; + } + if ( /(((?:OSSL_|OPENSSL_)?[A-Z0-9]{2,})_R_[A-Z0-9_]+)/ ) { + next unless exists $errorfile{$2}; + $usedreasons{$1} = 1; + if ( !exists $rcodes{$1} ) { + print STDERR " New reason $1\n" if $debug; + $rcodes{$1} = "X"; + $rnew{$2}++; + } + print STDERR " Reason $1 = $rcodes{$1}\n" if $debug; + } + } + close IN; +} +print STDERR "\n" if $debug; + +# Now process each library in turn. +&phase("Writing files"); +my $newstate = 0; +foreach my $lib ( keys %errorfile ) { + if ( ! $fnew{$lib} && ! $rnew{$lib} ) { + next unless $rebuild; + } + next if scalar keys %modules > 0 && !$modules{$lib}; + next if $nowrite; + print STDERR "$lib: $fnew{$lib} new functions\n" if $fnew{$lib}; + print STDERR "$lib: $rnew{$lib} new reasons\n" if $rnew{$lib}; + $newstate = 1; + + # If we get here then we have some new error codes so we + # need to rebuild the header file and C file. + + # Make a sorted list of error and reason codes for later use. + my @function = sort grep( /^${lib}_/, keys %fcodes ); + my @reasons = sort grep( /^${lib}_/, keys %rcodes ); + + # indent level for innermost preprocessor lines + my $indent = " "; + + # Rewrite the header file + + my $hfile = $hinc{$lib}; + $hfile =~ s/.h$/err.h/ if $internal; + open( OUT, ">$hfile" ) || die "Can't write to $hfile, $!,"; + print OUT <<"EOF"; +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-$YEAR The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the \"License\"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_${lib}ERR_H +# define HEADER_${lib}ERR_H + +EOF + if ( $internal ) { + # Declare the load function because the generate C file + # includes "fooerr.h" not "foo.h" + if ($lib ne "SSL" && $lib ne "ASYNC" + && grep { $lib eq uc $_ } @disablables) { + print OUT <<"EOF"; +# include + +# ifndef OPENSSL_NO_${lib} + +EOF + $indent = " "; + } + print OUT <<"EOF"; +#${indent}ifdef __cplusplus +extern \"C\" +#${indent}endif +int ERR_load_${lib}_strings(void); +EOF + } else { + print OUT <<"EOF"; +# define ${lib}err(f, r) ERR_${lib}_error((f), (r), OPENSSL_FILE, OPENSSL_LINE) + +EOF + if ( ! $static ) { + print OUT <<"EOF"; + +# ifdef __cplusplus +extern \"C\" { +# endif +int ERR_load_${lib}_strings(void); +void ERR_unload_${lib}_strings(void); +void ERR_${lib}_error(int function, int reason, char *file, int line); +# ifdef __cplusplus +} +# endif +EOF + } + } + + print OUT "\n/*\n * $lib function codes.\n */\n"; + foreach my $i ( @function ) { + my $z = 48 - length($i); + $z = 0 if $z < 0; + if ( $fcodes{$i} eq "X" ) { + $fassigned{$lib} =~ m/^:([^:]*):/; + my $findcode = $1; + $findcode = $fmax{$lib} if !defined $findcode; + while ( $fassigned{$lib} =~ m/:$findcode:/ ) { + $findcode++; + } + $fcodes{$i} = $findcode; + $fassigned{$lib} .= "$findcode:"; + print STDERR "New Function code $i\n" if $debug; + } + printf OUT "#${indent}define $i%s $fcodes{$i}\n", " " x $z; + } + + print OUT "\n/*\n * $lib reason codes.\n */\n"; + foreach my $i ( @reasons ) { + my $z = 48 - length($i); + $z = 0 if $z < 0; + if ( $rcodes{$i} eq "X" ) { + $rassigned{$lib} =~ m/^:([^:]*):/; + my $findcode = $1; + $findcode = $rmax{$lib} if !defined $findcode; + while ( $rassigned{$lib} =~ m/:$findcode:/ ) { + $findcode++; + } + $rcodes{$i} = $findcode; + $rassigned{$lib} .= "$findcode:"; + print STDERR "New Reason code $i\n" if $debug; + } + printf OUT "#${indent}define $i%s $rcodes{$i}\n", " " x $z; + } + print OUT "\n"; + + while (length($indent) > 0) { + $indent = substr $indent, 0, -1; + print OUT "#${indent}endif\n"; + } + + # Rewrite the C source file containing the error details. + + # First, read any existing reason string definitions: + my $cfile = $errorfile{$lib}; + my $pack_lib = $internal ? "ERR_LIB_${lib}" : "0"; + my $hincf = $hfile; + $hincf =~ s|.*include/||; + if ( $hincf =~ m|^openssl/| ) { + $hincf = "<${hincf}>"; + } else { + $hincf = "\"${hincf}\""; + } + + open( OUT, ">$cfile" ) + || die "Can't open $cfile for writing, $!, stopped"; + + my $const = $internal ? 'const ' : ''; + + print OUT <<"EOF"; +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-$YEAR The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include $hincf + +#ifndef OPENSSL_NO_ERR + +static ${const}ERR_STRING_DATA ${lib}_str_functs[] = { +EOF + + # Add each function code: if a function name is found then use it. + foreach my $i ( @function ) { + my $fn; + if ( exists $strings{$i} and $strings{$i} ne '' ) { + $fn = $strings{$i}; + $fn = "" if $fn eq '*'; + } else { + $i =~ /^${lib}_F_(\S+)$/; + $fn = $1; + $fn = $ftrans{$fn} if exists $ftrans{$fn}; + $strings{$i} = $fn; + } + my $short = " {ERR_PACK($pack_lib, $i, 0), \"$fn\"},"; + if ( length($short) <= 80 ) { + print OUT "$short\n"; + } else { + print OUT " {ERR_PACK($pack_lib, $i, 0),\n \"$fn\"},\n"; + } + } + print OUT <<"EOF"; + {0, NULL} +}; + +static ${const}ERR_STRING_DATA ${lib}_str_reasons[] = { +EOF + + # Add each reason code. + foreach my $i ( @reasons ) { + my $rn; + if ( exists $strings{$i} ) { + $rn = $strings{$i}; + $rn = "" if $rn eq '*'; + } else { + $i =~ /^${lib}_R_(\S+)$/; + $rn = $1; + $rn =~ tr/_[A-Z]/ [a-z]/; + $strings{$i} = $rn; + } + my $short = " {ERR_PACK($pack_lib, 0, $i), \"$rn\"},"; + if ( length($short) <= 80 ) { + print OUT "$short\n"; + } else { + print OUT " {ERR_PACK($pack_lib, 0, $i),\n \"$rn\"},\n"; + } + } + print OUT <<"EOF"; + {0, NULL} +}; + +#endif +EOF + if ( $internal ) { + print OUT <<"EOF"; + +int ERR_load_${lib}_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(${lib}_str_functs[0].error) == NULL) { + ERR_load_strings_const(${lib}_str_functs); + ERR_load_strings_const(${lib}_str_reasons); + } +#endif + return 1; +} +EOF + } else { + my $st = $static ? "static " : ""; + print OUT <<"EOF"; + +static int lib_code = 0; +static int error_loaded = 0; + +${st}int ERR_load_${lib}_strings(void) +{ + if (lib_code == 0) + lib_code = ERR_get_next_error_library(); + + if (!error_loaded) { +#ifndef OPENSSL_NO_ERR + ERR_load_strings(lib_code, ${lib}_str_functs); + ERR_load_strings(lib_code, ${lib}_str_reasons); +#endif + error_loaded = 1; + } + return 1; +} + +${st}void ERR_unload_${lib}_strings(void) +{ + if (error_loaded) { +#ifndef OPENSSL_NO_ERR + ERR_unload_strings(lib_code, ${lib}_str_functs); + ERR_unload_strings(lib_code, ${lib}_str_reasons); +#endif + error_loaded = 0; + } +} + +${st}void ERR_${lib}_error(int function, int reason, char *file, int line) +{ + if (lib_code == 0) + lib_code = ERR_get_next_error_library(); + ERR_PUT_error(lib_code, function, reason, file, line); +} +EOF + + } + + close OUT; +} + +&phase("Ending"); +# Make a list of unreferenced function and reason codes +if ( $unref ) { + my @funref; + foreach ( keys %fcodes ) { + push( @funref, $_ ) unless exists $usedfuncs{$_}; + } + my @runref; + foreach ( keys %rcodes ) { + push( @runref, $_ ) unless exists $usedreasons{$_}; + } + if ( @funref ) { + print STDERR "The following function codes were not referenced:\n"; + foreach ( sort @funref ) { + print STDERR " $_\n"; + } + } + if ( @runref ) { + print STDERR "The following reason codes were not referenced:\n"; + foreach ( sort @runref ) { + print STDERR " $_\n"; + } + } +} + +die "Found $errors errors, quitting" if $errors; + +# Update the state file +if ( $newstate ) { + open(OUT, ">$statefile.new") + || die "Can't write $statefile.new, $!"; + print OUT <<"EOF"; +# Copyright 1999-$YEAR The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html +EOF + print OUT "\n# Function codes\n"; + foreach my $i ( sort keys %fcodes ) { + my $short = "$i:$fcodes{$i}:"; + my $t = exists $strings{$i} ? $strings{$i} : ""; + $t = "\\\n\t" . $t if length($short) + length($t) > 80; + print OUT "$short$t\n"; + } + print OUT "\n#Reason codes\n"; + foreach my $i ( sort keys %rcodes ) { + my $short = "$i:$rcodes{$i}:"; + my $t = exists $strings{$i} ? "$strings{$i}" : ""; + $t = "\\\n\t" . $t if length($short) + length($t) > 80; + print OUT "$short$t\n" if !exists $rextra{$i}; + } + close(OUT); + if ( $skippedstate ) { + print "Skipped state, leaving update in $statefile.new"; + } else { + rename "$statefile", "$statefile.old" + || die "Can't backup $statefile to $statefile.old, $!"; + rename "$statefile.new", "$statefile" + || die "Can't rename $statefile to $statefile.new, $!"; + } +} + +exit; diff --git a/trunk/3rdparty/openssl-1.1-fit/util/mkrc.pl b/trunk/3rdparty/openssl-1.1-fit/util/mkrc.pl new file mode 100755 index 000000000..6762bc4a5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/mkrc.pl @@ -0,0 +1,93 @@ +#! /usr/bin/env perl +# Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use strict; +use warnings; +use lib "."; +use configdata; +use File::Spec::Functions; + +my $versionfile = catfile( $config{sourcedir}, "include/openssl/opensslv.h" ); + +my ( $ver, $v1, $v2, $v3, $v4, $beta, $version ); + +open FD, $versionfile or die "Couldn't open include/openssl/opensslv.h: $!\n"; +while () { + if (/OPENSSL_VERSION_NUMBER\s+(0x[0-9a-f]+)/i) { + $ver = hex($1); + $v1 = ( $ver >> 28 ); + $v2 = ( $ver >> 20 ) & 0xff; + $v3 = ( $ver >> 12 ) & 0xff; + $v4 = ( $ver >> 4 ) & 0xff; + $beta = $ver & 0xf; + $version = "$v1.$v2.$v3"; + if ( $beta == 0xf ) { + $version .= chr( ord('a') + $v4 - 1 ) if ($v4); + } elsif ( $beta == 0 ) { + $version .= "-dev"; + } else { + $version .= "-beta$beta"; + } + last; + } +} +close(FD); + +my $filename = $ARGV[0]; +my $description = "OpenSSL library"; +my $vft = "VFT_DLL"; +if ( $filename =~ /openssl/i ) { + $description = "OpenSSL application"; + $vft = "VFT_APP"; +} + +my $YEAR = [localtime()]->[5] + 1900; +print <<___; +#include + +LANGUAGE 0x09,0x01 + +1 VERSIONINFO + FILEVERSION $v1,$v2,$v3,$v4 + PRODUCTVERSION $v1,$v2,$v3,$v4 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x01L +#else + FILEFLAGS 0x00L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE $vft + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + // Required: + VALUE "CompanyName", "The OpenSSL Project, https://www.openssl.org/\\0" + VALUE "FileDescription", "$description\\0" + VALUE "FileVersion", "$version\\0" + VALUE "InternalName", "$filename\\0" + VALUE "OriginalFilename", "$filename\\0" + VALUE "ProductName", "The OpenSSL Toolkit\\0" + VALUE "ProductVersion", "$version\\0" + // Optional: + //VALUE "Comments", "\\0" + VALUE "LegalCopyright", "Copyright 1998-$YEAR The OpenSSL Authors. All rights reserved.\\0" + //VALUE "LegalTrademarks", "\\0" + //VALUE "PrivateBuild", "\\0" + //VALUE "SpecialBuild", "\\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 0x4b0 + END +END +___ diff --git a/trunk/3rdparty/openssl-1.1-fit/util/openssl-format-source b/trunk/3rdparty/openssl-1.1-fit/util/openssl-format-source new file mode 100755 index 000000000..e39964420 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/openssl-format-source @@ -0,0 +1,175 @@ +#!/bin/sh +# +# Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# +# openssl-format-source +# - format source tree according to OpenSSL coding style using indent +# +# usage: +# openssl-format-source [-v] [-n] [file|directory] ... +# +# note: the indent options assume GNU indent v2.2.10 which was released +# Feb-2009 so if you have an older indent the options may not +# match what is expected +# +# any marked block comment blocks have to be moved to align manually after +# the reformatting has been completed as marking a block causes indent to +# not move it at all ... +# + +PATH=/usr/local/bin:/bin:/usr/bin:$PATH +export PATH +HERE="`dirname $0`" + +set -e + +INDENT=indent +uname -s | grep BSD > /dev/null && type gindent > /dev/null 2>&1 && INDENT=gindent + +if [ $# -eq 0 ]; then + echo "usage: $0 [-v] [-n] [-c] [sourcefile|sourcedir] ..." >&2 + exit 1 +fi + +VERBOSE=false +DONT=false +STOPARGS=false +COMMENTS=false +CHANGED=false +DEBUG="" + +# for this exercise, we want to force the openssl style, so we roll +# our own indent profile, which is at a well known location +INDENT_PROFILE="$HERE/indent.pro" +export INDENT_PROFILE +if [ ! -f "$INDENT_PROFILE" ]; then + echo "$0: unable to locate the openssl indent.pro file" >&2 + exit 1 +fi + +# Extra arguments; for adding the comment-formatting +INDENT_ARGS="" +for i +do + if [ "$STOPARGS" != "true" ]; then + case $i in + --) STOPARGS="true"; continue;; + -n) DONT="true"; continue;; + -v) VERBOSE="true"; + echo "INDENT_PROFILE=$INDENT_PROFILE"; + continue;; + -c) COMMENTS="true"; + INDENT_ARGS="-fc1 -fca -cdb -sc"; + continue;; + -nc) COMMENTS="true"; + continue;; + -d) DEBUG='eval tee "$j.pre" |' + continue;; + esac + fi + + if [ -d "$i" ]; then + LIST=`find "$i" -name '*.[ch]' -print` + else + if [ ! -f "$i" ]; then + echo "$0: source file not found: $i" >&2 + exit 1 + fi + LIST="$i" + fi + + for j in $LIST + do + # ignore symlinks - we only ever process the base file - so if we + # expand a directory tree we need to ignore any located symlinks + if [ -d "$i" ]; then + if [ -h "$j" ]; then + continue; + fi + fi + + if [ "$DONT" = "false" ]; then + tmp=$(mktemp /tmp/indent.XXXXXX) + trap 'rm -f "$tmp"' HUP INT TERM EXIT + + case `basename $j` in + # the list of files that indent is unable to handle correctly + # that we simply leave alone for manual formatting now + obj_dat.h|aes_core.c|aes_x86core.c|ecp_nistz256.c) + echo "skipping $j" + ;; + *) + if [ "$COMMENTS" = "true" ]; then + # we have to mark single line comments as /*- ...*/ to stop indent + # messing with them, run expand then indent as usual but with the + # the process-comments options and then undo that marking, and then + # finally re-run indent without process-comments so the marked-to- + # be-ignored comments we did automatically end up getting moved + # into the right position within the code as indent leaves marked + # comments entirely untouched - we appear to have no way to avoid + # the double processing and get the desired output + cat "$j" | \ + expand | \ + perl -0 -np \ + -e 's/(\n#[ \t]*ifdef[ \t]+__cplusplus\n[^\n]*\n#[ \t]*endif\n)/\n\/**INDENT-OFF**\/$1\/**INDENT-ON**\/\n/g;' \ + -e 's/(\n\/\*\!)/\n\/**/g;' \ + -e 's/(STACK_OF|LHASH_OF)\(([^ \t,\)]+)\)( |\n)/$1_$2_$3/g;' \ + | \ + perl -np \ + -e 's/^([ \t]*)\/\*([ \t]+.*)\*\/[ \t]*$/my ($x1,$x2) = ($1, $2); if (length("$x1$x2")<75 && $x2 !~ m#^\s*\*INDENT-(ON|OFF)\*\s*$#) {$c="-"}else{$c=""}; "$x1\/*$c$x2*\/"/e;' \ + -e 's/^\/\* ((Copyright|=|----).*)$/\/*-$1/;' \ + -e 's/^((DECLARE|IMPLEMENT)_.*)$/\/**INDENT-OFF**\/\n$1\n\/**INDENT-ON**\//;' \ + -e 's/^([ \t]*(make_dh|make_dh_bn|make_rfc5114_td)\(.*\)[ \t,]*)$/\/**INDENT-OFF**\/\n$1\n\/**INDENT-ON**\//;' \ + -e 's/^(ASN1_ADB_TEMPLATE\(.*)$/\/**INDENT-OFF**\/\n$1\n\/**INDENT-ON**\//;' \ + -e 's/^((ASN1|ADB)_.*_(end|END)\(.*[\){=,;]+[ \t]*)$/$1\n\/**INDENT-ON**\//;' \ + -e '/ASN1_(ITEM_ref|ITEM_ptr|ITEM_rptr|PCTX)/ || s/^((ASN1|ADB)_[^\*]*[){=,]+[ \t]*)$/\/**INDENT-OFF**\/\n$1/;' \ + -e 's/^(} (ASN1|ADB)_[^\*]*[\){=,;]+)$/$1\n\/**INDENT-ON**\//;' \ + | \ + $DEBUG $INDENT $INDENT_ARGS | \ + perl -np \ + -e 's/^([ \t]*)\/\*-(.*)\*\/[ \t]*$/$1\/*$2*\//;' \ + -e 's/^\/\*-((Copyright|=|----).*)$/\/* $1/;' \ + | $INDENT | \ + perl -0 -np \ + -e 's/\/\*\*INDENT-(ON|OFF)\*\*\/\n//g;' \ + | perl -np \ + -e 's/(STACK_OF|LHASH_OF)_([^ \t,]+)_( |\/)/$1($2)$3/g;' \ + -e 's/(STACK_OF|LHASH_OF)_([^ \t,]+)_$/$1($2)/g;' \ + | perl "$HERE"/su-filter.pl \ + > "$tmp" + else + expand "$j" | $INDENT $INDENT_ARGS > "$tmp" + fi; + if cmp -s "$tmp" "$j"; then + if [ "$VERBOSE" = "true" ]; then + echo "$j unchanged" + fi + rm "$tmp" + else + if [ "$VERBOSE" = "true" ]; then + echo "$j changed" + fi + CHANGED=true + mv "$tmp" "$j" + fi + ;; + esac + fi + done +done + + +if [ "$VERBOSE" = "true" ]; then + echo + if [ "$CHANGED" = "true" ]; then + echo "SOURCE WAS MODIFIED" + else + echo "SOURCE WAS NOT MODIFIED" + fi +fi diff --git a/trunk/3rdparty/openssl-1.1-fit/util/openssl-update-copyright b/trunk/3rdparty/openssl-1.1-fit/util/openssl-update-copyright new file mode 100755 index 000000000..c432f8462 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/openssl-update-copyright @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +# +# Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +myname="$(basename $0)" + +this_year="$(date '+%Y')" +some_year="[12][0-9][0-9][0-9]" +year_range="(${some_year})(-${some_year})?" + +copyright_owner="The OpenSSL Project" +copyright="Copyright .*${year_range} .*${copyright_owner}" + +# sed_script: +# for all lines that contain ${copyright} : { +# replace years yyyy-zzzz (or year yyyy) by yyyy-${this_year} +# replace repeated years yyyy-yyyy by yyyy +# } +sed_script="/${copyright}/{ s/${year_range}/\1-${this_year}/ ; s/(${some_year})-\1/\1/ }" + +function usage() { + cat >&2 <& 2 + usage + exit 1 + ;; + *) + if [ -f "$arg" ]; then + sed -E -i "${sed_script}" "$arg" + elif [ -d "$arg" ]; then + find "$arg" -name '.[a-z]*' -prune -o -type f -exec sed -E -i "${sed_script}" {} + + else + echo "$arg: no such file or directory" >&2 + fi + ;; + esac +done diff --git a/trunk/3rdparty/openssl-1.1-fit/util/opensslwrap.sh b/trunk/3rdparty/openssl-1.1-fit/util/opensslwrap.sh new file mode 100755 index 000000000..b27cbb897 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/opensslwrap.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +HERE="`echo $0 | sed -e 's|[^/]*$||'`" +OPENSSL="${HERE}../apps/openssl" + +if [ -d "${HERE}../engines" -a "x$OPENSSL_ENGINES" = "x" ]; then + OPENSSL_ENGINES="${HERE}../engines"; export OPENSSL_ENGINES +fi + +if [ -x "${OPENSSL}.exe" ]; then + # The original reason for this script existence is to work around + # certain caveats in run-time linker behaviour. On Windows platforms + # adjusting $PATH used to be sufficient, but with introduction of + # SafeDllSearchMode in XP/2003 the only way to get it right in + # *all* possible situations is to copy newly built .DLLs to apps/ + # and test/, which is now done elsewhere... The $PATH is adjusted + # for backward compatibility (and nostagical reasons:-). + if [ "$OSTYPE" != msdosdjgpp ]; then + PATH="${HERE}..:$PATH"; export PATH + fi + exec "${OPENSSL}.exe" "$@" +elif [ -x "${OPENSSL}" -a -x "${HERE}shlib_wrap.sh" ]; then + exec "${HERE}shlib_wrap.sh" "${OPENSSL}" "$@" +else + exec "${OPENSSL}" "$@" # hope for the best... +fi diff --git a/trunk/3rdparty/openssl-1.1-fit/util/perl/OpenSSL/Glob.pm b/trunk/3rdparty/openssl-1.1-fit/util/perl/OpenSSL/Glob.pm new file mode 100644 index 000000000..ec87da4ae --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/perl/OpenSSL/Glob.pm @@ -0,0 +1,21 @@ +package OpenSSL::Glob; + +use strict; +use warnings; + +use File::Glob; + +use Exporter; +use vars qw($VERSION @ISA @EXPORT); + +$VERSION = '0.1'; +@ISA = qw(Exporter); +@EXPORT = qw(glob); + +sub glob { + goto &File::Glob::bsd_glob if $^O ne "VMS"; + goto &CORE::glob; +} + +1; +__END__ diff --git a/trunk/3rdparty/openssl-1.1-fit/util/perl/OpenSSL/Test.pm b/trunk/3rdparty/openssl-1.1-fit/util/perl/OpenSSL/Test.pm new file mode 100644 index 000000000..9564b2604 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/perl/OpenSSL/Test.pm @@ -0,0 +1,1216 @@ +# Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +package OpenSSL::Test; + +use strict; +use warnings; + +use Test::More 0.96; + +use Exporter; +use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); +$VERSION = "0.8"; +@ISA = qw(Exporter); +@EXPORT = (@Test::More::EXPORT, qw(setup run indir cmd app fuzz test + perlapp perltest subtest)); +@EXPORT_OK = (@Test::More::EXPORT_OK, qw(bldtop_dir bldtop_file + srctop_dir srctop_file + data_file data_dir + pipe with cmdstr quotify + openssl_versions)); + +=head1 NAME + +OpenSSL::Test - a private extension of Test::More + +=head1 SYNOPSIS + + use OpenSSL::Test; + + setup("my_test_name"); + + ok(run(app(["openssl", "version"])), "check for openssl presence"); + + indir "subdir" => sub { + ok(run(test(["sometest", "arg1"], stdout => "foo.txt")), + "run sometest with output to foo.txt"); + }; + +=head1 DESCRIPTION + +This module is a private extension of L for testing OpenSSL. +In addition to the Test::More functions, it also provides functions that +easily find the diverse programs within a OpenSSL build tree, as well as +some other useful functions. + +This module I on the environment variables C<$TOP> or C<$SRCTOP> +and C<$BLDTOP>. Without one of the combinations it refuses to work. +See L below. + +With each test recipe, a parallel data directory with (almost) the same name +as the recipe is possible in the source directory tree. For example, for a +recipe C<$SRCTOP/test/recipes/99-foo.t>, there could be a directory +C<$SRCTOP/test/recipes/99-foo_data/>. + +=cut + +use File::Copy; +use File::Spec::Functions qw/file_name_is_absolute curdir canonpath splitdir + catdir catfile splitpath catpath devnull abs2rel + rel2abs/; +use File::Path 2.00 qw/rmtree mkpath/; +use File::Basename; + +my $level = 0; + +# The name of the test. This is set by setup() and is used in the other +# functions to verify that setup() has been used. +my $test_name = undef; + +# Directories we want to keep track of TOP, APPS, TEST and RESULTS are the +# ones we're interested in, corresponding to the environment variables TOP +# (mandatory), BIN_D, TEST_D, UTIL_D and RESULT_D. +my %directories = (); + +# The environment variables that gave us the contents in %directories. These +# get modified whenever we change directories, so that subprocesses can use +# the values of those environment variables as well +my @direnv = (); + +# A bool saying if we shall stop all testing if the current recipe has failing +# tests or not. This is set by setup() if the environment variable STOPTEST +# is defined with a non-empty value. +my $end_with_bailout = 0; + +# A set of hooks that is affected by with() and may be used in diverse places. +# All hooks are expected to be CODE references. +my %hooks = ( + + # exit_checker is used by run() directly after completion of a command. + # it receives the exit code from that command and is expected to return + # 1 (for success) or 0 (for failure). This is the status value that run() + # will give back (through the |statusvar| reference and as returned value + # when capture => 1 doesn't apply). + exit_checker => sub { return shift == 0 ? 1 : 0 }, + + ); + +# Debug flag, to be set manually when needed +my $debug = 0; + +=head2 Main functions + +The following functions are exported by default when using C. + +=cut + +=over 4 + +=item B + +C is used for initial setup, and it is mandatory that it's used. +If it's not used in a OpenSSL test recipe, the rest of the recipe will +most likely refuse to run. + +C checks for environment variables (see L below), +checks that C<$TOP/Configure> or C<$SRCTOP/Configure> exists, C +into the results directory (defined by the C<$RESULT_D> environment +variable if defined, otherwise C<$BLDTOP/test> or C<$TOP/test>, whichever +is defined). + +=back + +=cut + +sub setup { + my $old_test_name = $test_name; + $test_name = shift; + + BAIL_OUT("setup() must receive a name") unless $test_name; + warn "setup() detected test name change. Innocuous, so we continue...\n" + if $old_test_name && $old_test_name ne $test_name; + + return if $old_test_name; + + BAIL_OUT("setup() needs \$TOP or \$SRCTOP and \$BLDTOP to be defined") + unless $ENV{TOP} || ($ENV{SRCTOP} && $ENV{BLDTOP}); + BAIL_OUT("setup() found both \$TOP and \$SRCTOP or \$BLDTOP...") + if $ENV{TOP} && ($ENV{SRCTOP} || $ENV{BLDTOP}); + + __env(); + + BAIL_OUT("setup() expects the file Configure in the source top directory") + unless -f srctop_file("Configure"); + + __cwd($directories{RESULTS}); +} + +=over 4 + +=item B sub BLOCK, OPTS> + +C is used to run a part of the recipe in a different directory than +the one C moved into, usually a subdirectory, given by SUBDIR. +The part of the recipe that's run there is given by the codeblock BLOCK. + +C takes some additional options OPTS that affect the subdirectory: + +=over 4 + +=item B 0|1> + +When set to 1 (or any value that perl preceives as true), the subdirectory +will be created if it doesn't already exist. This happens before BLOCK +is executed. + +=item B 0|1> + +When set to 1 (or any value that perl preceives as true), the subdirectory +will be cleaned out and removed. This happens both before and after BLOCK +is executed. + +=back + +An example: + + indir "foo" => sub { + ok(run(app(["openssl", "version"]), stdout => "foo.txt")); + if (ok(open(RESULT, "foo.txt"), "reading foo.txt")) { + my $line = ; + close RESULT; + is($line, qr/^OpenSSL 1\./, + "check that we're using OpenSSL 1.x.x"); + } + }, create => 1, cleanup => 1; + +=back + +=cut + +sub indir { + my $subdir = shift; + my $codeblock = shift; + my %opts = @_; + + my $reverse = __cwd($subdir,%opts); + BAIL_OUT("FAILURE: indir, \"$subdir\" wasn't possible to move into") + unless $reverse; + + $codeblock->(); + + __cwd($reverse); + + if ($opts{cleanup}) { + rmtree($subdir, { safe => 0 }); + } +} + +=over 4 + +=item B + +This functions build up a platform dependent command based on the +input. It takes a reference to a list that is the executable or +script and its arguments, and some additional options (described +further on). Where necessary, the command will be wrapped in a +suitable environment to make sure the correct shared libraries are +used (currently only on Unix). + +It returns a CODEREF to be used by C, C or C. + +The options that C can take are in the form of hash values: + +=over 4 + +=item B PATH> + +=item B PATH> + +=item B PATH> + +In all three cases, the corresponding standard input, output or error is +redirected from (for stdin) or to (for the others) a file given by the +string PATH, I, if the value is C, C or similar. + +=back + +=item B + +=item B + +Both of these are specific applications of C, with just a couple +of small difference: + +C expects to find the given command (the first item in the given list +reference) as an executable in C<$BIN_D> (if defined, otherwise C<$TOP/apps> +or C<$BLDTOP/apps>). + +C expects to find the given command (the first item in the given list +reference) as an executable in C<$TEST_D> (if defined, otherwise C<$TOP/test> +or C<$BLDTOP/test>). + +Also, for both C and C, the command may be prefixed with +the content of the environment variable C<$EXE_SHELL>, which is useful +in case OpenSSL has been cross compiled. + +=item B + +=item B + +These are also specific applications of C, where the interpreter +is predefined to be C, and they expect the script to be +interpreted to reside in the same location as C and C. + +C and C will also take the following option: + +=over 4 + +=item B ARRAYref> + +The array reference is a set of arguments for the interpreter rather +than the script. Take care so that none of them can be seen as a +script! Flags and their eventual arguments only! + +=back + +An example: + + ok(run(perlapp(["foo.pl", "arg1"], + interpreter_args => [ "-I", srctop_dir("test") ]))); + +=back + +=begin comment + +One might wonder over the complexity of C, C, C, ... +with all the lazy evaluations and all that. The reason for this is that +we want to make sure the directory in which those programs are found are +correct at the time these commands are used. Consider the following code +snippet: + + my $cmd = app(["openssl", ...]); + + indir "foo", sub { + ok(run($cmd), "Testing foo") + }; + +If there wasn't this lazy evaluation, the directory where C is +found would be incorrect at the time C is called, because it was +calculated before we moved into the directory "foo". + +=end comment + +=cut + +sub cmd { + my $cmd = shift; + my %opts = @_; + return sub { + my $num = shift; + # Make a copy to not destroy the caller's array + my @cmdargs = ( @$cmd ); + my @prog = __wrap_cmd(shift @cmdargs, $opts{exe_shell} // ()); + + return __decorate_cmd($num, [ @prog, quotify(@cmdargs) ], + %opts); + } +} + +sub app { + my $cmd = shift; + my %opts = @_; + return sub { + my @cmdargs = ( @{$cmd} ); + my @prog = __fixup_prg(__apps_file(shift @cmdargs, __exeext())); + return cmd([ @prog, @cmdargs ], + exe_shell => $ENV{EXE_SHELL}, %opts) -> (shift); + } +} + +sub fuzz { + my $cmd = shift; + my %opts = @_; + return sub { + my @cmdargs = ( @{$cmd} ); + my @prog = __fixup_prg(__fuzz_file(shift @cmdargs, __exeext())); + return cmd([ @prog, @cmdargs ], + exe_shell => $ENV{EXE_SHELL}, %opts) -> (shift); + } +} + +sub test { + my $cmd = shift; + my %opts = @_; + return sub { + my @cmdargs = ( @{$cmd} ); + my @prog = __fixup_prg(__test_file(shift @cmdargs, __exeext())); + return cmd([ @prog, @cmdargs ], + exe_shell => $ENV{EXE_SHELL}, %opts) -> (shift); + } +} + +sub perlapp { + my $cmd = shift; + my %opts = @_; + return sub { + my @interpreter_args = defined $opts{interpreter_args} ? + @{$opts{interpreter_args}} : (); + my @interpreter = __fixup_prg($^X); + my @cmdargs = ( @{$cmd} ); + my @prog = __apps_file(shift @cmdargs, undef); + return cmd([ @interpreter, @interpreter_args, + @prog, @cmdargs ], %opts) -> (shift); + } +} + +sub perltest { + my $cmd = shift; + my %opts = @_; + return sub { + my @interpreter_args = defined $opts{interpreter_args} ? + @{$opts{interpreter_args}} : (); + my @interpreter = __fixup_prg($^X); + my @cmdargs = ( @{$cmd} ); + my @prog = __test_file(shift @cmdargs, undef); + return cmd([ @interpreter, @interpreter_args, + @prog, @cmdargs ], %opts) -> (shift); + } +} + +=over 4 + +=item B + +CODEREF is expected to be the value return by C or any of its +derivatives, anything else will most likely cause an error unless you +know what you're doing. + +C executes the command returned by CODEREF and return either the +resulting output (if the option C is set true) or a boolean +indicating if the command succeeded or not. + +The options that C can take are in the form of hash values: + +=over 4 + +=item B 0|1> + +If true, the command will be executed with a perl backtick, and C will +return the resulting output as an array of lines. If false or not given, +the command will be executed with C, and C will return 1 if +the command was successful or 0 if it wasn't. + +=item B EXPR> + +If specified, EXPR will be used as a string to prefix the output from the +command. This is useful if the output contains lines starting with C +or C that can disturb Test::Harness. + +=item B VARREF> + +If used, B must be a reference to a scalar variable. It will be +assigned a boolean indicating if the command succeeded or not. This is +particularly useful together with B. + +=back + +For further discussion on what is considered a successful command or not, see +the function C further down. + +=back + +=cut + +sub run { + my ($cmd, $display_cmd) = shift->(0); + my %opts = @_; + + return () if !$cmd; + + my $prefix = ""; + if ( $^O eq "VMS" ) { # VMS + $prefix = "pipe "; + } + + my @r = (); + my $r = 0; + my $e = 0; + + die "OpenSSL::Test::run(): statusvar value not a scalar reference" + if $opts{statusvar} && ref($opts{statusvar}) ne "SCALAR"; + + # In non-verbose, we want to shut up the command interpreter, in case + # it has something to complain about. On VMS, it might complain both + # on stdout and stderr + my $save_STDOUT; + my $save_STDERR; + if ($ENV{HARNESS_ACTIVE} && !$ENV{HARNESS_VERBOSE}) { + open $save_STDOUT, '>&', \*STDOUT or die "Can't dup STDOUT: $!"; + open $save_STDERR, '>&', \*STDERR or die "Can't dup STDERR: $!"; + open STDOUT, ">", devnull(); + open STDERR, ">", devnull(); + } + + $ENV{HARNESS_OSSL_LEVEL} = $level + 1; + + # The dance we do with $? is the same dance the Unix shells appear to + # do. For example, a program that gets aborted (and therefore signals + # SIGABRT = 6) will appear to exit with the code 134. We mimic this + # to make it easier to compare with a manual run of the command. + if ($opts{capture} || defined($opts{prefix})) { + my $pipe; + local $_; + + open($pipe, '-|', "$prefix$cmd") or die "Can't start command: $!"; + while(<$pipe>) { + my $l = ($opts{prefix} // "") . $_; + if ($opts{capture}) { + push @r, $l; + } else { + print STDOUT $l; + } + } + close $pipe; + } else { + $ENV{HARNESS_OSSL_PREFIX} = "# "; + system("$prefix$cmd"); + delete $ENV{HARNESS_OSSL_PREFIX}; + } + $e = ($? & 0x7f) ? ($? & 0x7f)|0x80 : ($? >> 8); + $r = $hooks{exit_checker}->($e); + if ($opts{statusvar}) { + ${$opts{statusvar}} = $r; + } + + if ($ENV{HARNESS_ACTIVE} && !$ENV{HARNESS_VERBOSE}) { + close STDOUT; + close STDERR; + open STDOUT, '>&', $save_STDOUT or die "Can't restore STDOUT: $!"; + open STDERR, '>&', $save_STDERR or die "Can't restore STDERR: $!"; + } + + print STDERR "$prefix$display_cmd => $e\n" + if !$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE}; + + # At this point, $? stops being interesting, and unfortunately, + # there are Test::More versions that get picky if we leave it + # non-zero. + $? = 0; + + if ($opts{capture}) { + return @r; + } else { + return $r; + } +} + +END { + my $tb = Test::More->builder; + my $failure = scalar(grep { $_ == 0; } $tb->summary); + if ($failure && $end_with_bailout) { + BAIL_OUT("Stoptest!"); + } +} + +=head2 Utility functions + +The following functions are exported on request when using C. + + # To only get the bldtop_file and srctop_file functions. + use OpenSSL::Test qw/bldtop_file srctop_file/; + + # To only get the bldtop_file function in addition to the default ones. + use OpenSSL::Test qw/:DEFAULT bldtop_file/; + +=cut + +# Utility functions, exported on request + +=over 4 + +=item B + +LIST is a list of directories that make up a path from the top of the OpenSSL +build directory (as indicated by the environment variable C<$TOP> or +C<$BLDTOP>). +C returns the resulting directory as a string, adapted to the local +operating system. + +=back + +=cut + +sub bldtop_dir { + return __bldtop_dir(@_); # This caters for operating systems that have + # a very distinct syntax for directories. +} + +=over 4 + +=item B + +LIST is a list of directories that make up a path from the top of the OpenSSL +build directory (as indicated by the environment variable C<$TOP> or +C<$BLDTOP>) and FILENAME is the name of a file located in that directory path. +C returns the resulting file path as a string, adapted to the local +operating system. + +=back + +=cut + +sub bldtop_file { + return __bldtop_file(@_); +} + +=over 4 + +=item B + +LIST is a list of directories that make up a path from the top of the OpenSSL +source directory (as indicated by the environment variable C<$TOP> or +C<$SRCTOP>). +C returns the resulting directory as a string, adapted to the local +operating system. + +=back + +=cut + +sub srctop_dir { + return __srctop_dir(@_); # This caters for operating systems that have + # a very distinct syntax for directories. +} + +=over 4 + +=item B + +LIST is a list of directories that make up a path from the top of the OpenSSL +source directory (as indicated by the environment variable C<$TOP> or +C<$SRCTOP>) and FILENAME is the name of a file located in that directory path. +C returns the resulting file path as a string, adapted to the local +operating system. + +=back + +=cut + +sub srctop_file { + return __srctop_file(@_); +} + +=over 4 + +=item B + +LIST is a list of directories that make up a path from the data directory +associated with the test (see L above). +C returns the resulting directory as a string, adapted to the local +operating system. + +=back + +=cut + +sub data_dir { + return __data_dir(@_); +} + +=over 4 + +=item B + +LIST is a list of directories that make up a path from the data directory +associated with the test (see L above) and FILENAME is the name +of a file located in that directory path. C returns the resulting +file path as a string, adapted to the local operating system. + +=back + +=cut + +sub data_file { + return __data_file(@_); +} + +=over 4 + +=item B + +LIST is a list of CODEREFs returned by C or C, from which C +creates a new command composed of all the given commands put together in a +pipe. C returns a new CODEREF in the same manner as C or C, +to be passed to C for execution. + +=back + +=cut + +sub pipe { + my @cmds = @_; + return + sub { + my @cs = (); + my @dcs = (); + my @els = (); + my $counter = 0; + foreach (@cmds) { + my ($c, $dc, @el) = $_->(++$counter); + + return () if !$c; + + push @cs, $c; + push @dcs, $dc; + push @els, @el; + } + return ( + join(" | ", @cs), + join(" | ", @dcs), + @els + ); + }; +} + +=over 4 + +=item B + +C will temporarily install hooks given by the HASHREF and then execute +the given CODEREF. Hooks are usually expected to have a coderef as value. + +The currently available hoosk are: + +=over 4 + +=item B CODEREF> + +This hook is executed after C has performed its given command. The +CODEREF receives the exit code as only argument and is expected to return +1 (if the exit code indicated success) or 0 (if the exit code indicated +failure). + +=back + +=back + +=cut + +sub with { + my $opts = shift; + my %opts = %{$opts}; + my $codeblock = shift; + + my %saved_hooks = (); + + foreach (keys %opts) { + $saved_hooks{$_} = $hooks{$_} if exists($hooks{$_}); + $hooks{$_} = $opts{$_}; + } + + $codeblock->(); + + foreach (keys %saved_hooks) { + $hooks{$_} = $saved_hooks{$_}; + } +} + +=over 4 + +=item B + +C takes a CODEREF from C or C and simply returns the +command as a string. + +C takes some additional options OPTS that affect the string returned: + +=over 4 + +=item B 0|1> + +When set to 0, the returned string will be with all decorations, such as a +possible redirect of stderr to the null device. This is suitable if the +string is to be used directly in a recipe. + +When set to 1, the returned string will be without extra decorations. This +is suitable for display if that is desired (doesn't confuse people with all +internal stuff), or if it's used to pass a command down to a subprocess. + +Default: 0 + +=back + +=back + +=cut + +sub cmdstr { + my ($cmd, $display_cmd) = shift->(0); + my %opts = @_; + + if ($opts{display}) { + return $display_cmd; + } else { + return $cmd; + } +} + +=over 4 + +=item B + +LIST is a list of strings that are going to be used as arguments for a +command, and makes sure to inject quotes and escapes as necessary depending +on the content of each string. + +This can also be used to put quotes around the executable of a command. +I + +=back + +=cut + +sub quotify { + # Unix setup (default if nothing else is mentioned) + my $arg_formatter = + sub { $_ = shift; + ($_ eq '' || /\s|[\{\}\\\$\[\]\*\?\|\&:;<>]/) ? "'$_'" : $_ }; + + if ( $^O eq "VMS") { # VMS setup + $arg_formatter = sub { + $_ = shift; + if ($_ eq '' || /\s|["[:upper:]]/) { + s/"/""/g; + '"'.$_.'"'; + } else { + $_; + } + }; + } elsif ( $^O eq "MSWin32") { # MSWin setup + $arg_formatter = sub { + $_ = shift; + if ($_ eq '' || /\s|["\|\&\*\;<>]/) { + s/(["\\])/\\$1/g; + '"'.$_.'"'; + } else { + $_; + } + }; + } + + return map { $arg_formatter->($_) } @_; +} + +=over 4 + +=item B + +Returns a list of two numbers, the first representing the build version, +the second representing the library version. See opensslv.h for more +information on those numbers. + +=back + +=cut + +my @versions = (); +sub openssl_versions { + unless (@versions) { + my %lines = + map { s/\R$//; + /^(.*): (0x[[:xdigit:]]{8})$/; + die "Weird line: $_" unless defined $1; + $1 => hex($2) } + run(test(['versions']), capture => 1); + @versions = ( $lines{'Build version'}, $lines{'Library version'} ); + } + return @versions; +} + +###################################################################### +# private functions. These are never exported. + +=head1 ENVIRONMENT + +OpenSSL::Test depends on some environment variables. + +=over 4 + +=item B + +This environment variable is mandatory. C will check that it's +defined and that it's a directory that contains the file C. +If this isn't so, C will C. + +=item B + +If defined, its value should be the directory where the openssl application +is located. Defaults to C<$TOP/apps> (adapted to the operating system). + +=item B + +If defined, its value should be the directory where the test applications +are located. Defaults to C<$TOP/test> (adapted to the operating system). + +=item B + +If defined, it puts testing in a different mode, where a recipe with +failures will result in a C at the end of its run. + +=back + +=cut + +sub __env { + (my $recipe_datadir = basename($0)) =~ s/\.t$/_data/i; + + $directories{SRCTOP} = $ENV{SRCTOP} || $ENV{TOP}; + $directories{BLDTOP} = $ENV{BLDTOP} || $ENV{TOP}; + $directories{BLDAPPS} = $ENV{BIN_D} || __bldtop_dir("apps"); + $directories{SRCAPPS} = __srctop_dir("apps"); + $directories{BLDFUZZ} = __bldtop_dir("fuzz"); + $directories{SRCFUZZ} = __srctop_dir("fuzz"); + $directories{BLDTEST} = $ENV{TEST_D} || __bldtop_dir("test"); + $directories{SRCTEST} = __srctop_dir("test"); + $directories{SRCDATA} = __srctop_dir("test", "recipes", + $recipe_datadir); + $directories{RESULTS} = $ENV{RESULT_D} || $directories{BLDTEST}; + + push @direnv, "TOP" if $ENV{TOP}; + push @direnv, "SRCTOP" if $ENV{SRCTOP}; + push @direnv, "BLDTOP" if $ENV{BLDTOP}; + push @direnv, "BIN_D" if $ENV{BIN_D}; + push @direnv, "TEST_D" if $ENV{TEST_D}; + push @direnv, "RESULT_D" if $ENV{RESULT_D}; + + $end_with_bailout = $ENV{STOPTEST} ? 1 : 0; +}; + +# __srctop_file and __srctop_dir are helpers to build file and directory +# names on top of the source directory. They depend on $SRCTOP, and +# therefore on the proper use of setup() and when needed, indir(). +# __bldtop_file and __bldtop_dir do the same thing but relative to $BLDTOP. +# __srctop_file and __bldtop_file take the same kind of argument as +# File::Spec::Functions::catfile. +# Similarly, __srctop_dir and __bldtop_dir take the same kind of argument +# as File::Spec::Functions::catdir +sub __srctop_file { + BAIL_OUT("Must run setup() first") if (! $test_name); + + my $f = pop; + return catfile($directories{SRCTOP},@_,$f); +} + +sub __srctop_dir { + BAIL_OUT("Must run setup() first") if (! $test_name); + + return catdir($directories{SRCTOP},@_); +} + +sub __bldtop_file { + BAIL_OUT("Must run setup() first") if (! $test_name); + + my $f = pop; + return catfile($directories{BLDTOP},@_,$f); +} + +sub __bldtop_dir { + BAIL_OUT("Must run setup() first") if (! $test_name); + + return catdir($directories{BLDTOP},@_); +} + +# __exeext is a function that returns the platform dependent file extension +# for executable binaries, or the value of the environment variable $EXE_EXT +# if that one is defined. +sub __exeext { + my $ext = ""; + if ($^O eq "VMS" ) { # VMS + $ext = ".exe"; + } elsif ($^O eq "MSWin32") { # Windows + $ext = ".exe"; + } + return $ENV{"EXE_EXT"} || $ext; +} + +# __test_file, __apps_file and __fuzz_file return the full path to a file +# relative to the test/, apps/ or fuzz/ directory in the build tree or the +# source tree, depending on where the file is found. Note that when looking +# in the build tree, the file name with an added extension is looked for, if +# an extension is given. The intent is to look for executable binaries (in +# the build tree) or possibly scripts (in the source tree). +# These functions all take the same arguments as File::Spec::Functions::catfile, +# *plus* a mandatory extension argument. This extension argument can be undef, +# and is ignored in such a case. +sub __test_file { + BAIL_OUT("Must run setup() first") if (! $test_name); + + my $e = pop || ""; + my $f = pop; + my $out = catfile($directories{BLDTEST},@_,$f . $e); + $out = catfile($directories{SRCTEST},@_,$f) unless -f $out; + return $out; +} + +sub __apps_file { + BAIL_OUT("Must run setup() first") if (! $test_name); + + my $e = pop || ""; + my $f = pop; + my $out = catfile($directories{BLDAPPS},@_,$f . $e); + $out = catfile($directories{SRCAPPS},@_,$f) unless -f $out; + return $out; +} + +sub __fuzz_file { + BAIL_OUT("Must run setup() first") if (! $test_name); + + my $e = pop || ""; + my $f = pop; + my $out = catfile($directories{BLDFUZZ},@_,$f . $e); + $out = catfile($directories{SRCFUZZ},@_,$f) unless -f $out; + return $out; +} + +sub __data_file { + BAIL_OUT("Must run setup() first") if (! $test_name); + + my $f = pop; + return catfile($directories{SRCDATA},@_,$f); +} + +sub __data_dir { + BAIL_OUT("Must run setup() first") if (! $test_name); + + return catdir($directories{SRCDATA},@_); +} + +sub __results_file { + BAIL_OUT("Must run setup() first") if (! $test_name); + + my $f = pop; + return catfile($directories{RESULTS},@_,$f); +} + +# __cwd DIR +# __cwd DIR, OPTS +# +# __cwd changes directory to DIR (string) and changes all the relative +# entries in %directories accordingly. OPTS is an optional series of +# hash style arguments to alter __cwd's behavior: +# +# create = 0|1 The directory we move to is created if 1, not if 0. +# cleanup = 0|1 The directory we move from is removed if 1, not if 0. + +sub __cwd { + my $dir = catdir(shift); + my %opts = @_; + my $abscurdir = rel2abs(curdir()); + my $absdir = rel2abs($dir); + my $reverse = abs2rel($abscurdir, $absdir); + + # PARANOIA: if we're not moving anywhere, we do nothing more + if ($abscurdir eq $absdir) { + return $reverse; + } + + # Do not support a move to a different volume for now. Maybe later. + BAIL_OUT("FAILURE: \"$dir\" moves to a different volume, not supported") + if $reverse eq $abscurdir; + + # If someone happened to give a directory that leads back to the current, + # it's extremely silly to do anything more, so just simulate that we did + # move. + # In this case, we won't even clean it out, for safety's sake. + return "." if $reverse eq ""; + + $dir = canonpath($dir); + if ($opts{create}) { + mkpath($dir); + } + + # We are recalculating the directories we keep track of, but need to save + # away the result for after having moved into the new directory. + my %tmp_directories = (); + my %tmp_ENV = (); + + # For each of these directory variables, figure out where they are relative + # to the directory we want to move to if they aren't absolute (if they are, + # they don't change!) + my @dirtags = sort keys %directories; + foreach (@dirtags) { + if (!file_name_is_absolute($directories{$_})) { + my $newpath = abs2rel(rel2abs($directories{$_}), rel2abs($dir)); + $tmp_directories{$_} = $newpath; + } + } + + # Treat each environment variable that was used to get us the values in + # %directories the same was as the paths in %directories, so any sub + # process can use their values properly as well + foreach (@direnv) { + if (!file_name_is_absolute($ENV{$_})) { + my $newpath = abs2rel(rel2abs($ENV{$_}), rel2abs($dir)); + $tmp_ENV{$_} = $newpath; + } + } + + # Should we just bail out here as well? I'm unsure. + return undef unless chdir($dir); + + if ($opts{cleanup}) { + rmtree(".", { safe => 0, keep_root => 1 }); + } + + # We put back new values carefully. Doing the obvious + # %directories = ( %tmp_directories ) + # will clear out any value that happens to be an absolute path + foreach (keys %tmp_directories) { + $directories{$_} = $tmp_directories{$_}; + } + foreach (keys %tmp_ENV) { + $ENV{$_} = $tmp_ENV{$_}; + } + + if ($debug) { + print STDERR "DEBUG: __cwd(), directories and files:\n"; + print STDERR " \$directories{BLDTEST} = \"$directories{BLDTEST}\"\n"; + print STDERR " \$directories{SRCTEST} = \"$directories{SRCTEST}\"\n"; + print STDERR " \$directories{SRCDATA} = \"$directories{SRCDATA}\"\n"; + print STDERR " \$directories{RESULTS} = \"$directories{RESULTS}\"\n"; + print STDERR " \$directories{BLDAPPS} = \"$directories{BLDAPPS}\"\n"; + print STDERR " \$directories{SRCAPPS} = \"$directories{SRCAPPS}\"\n"; + print STDERR " \$directories{SRCTOP} = \"$directories{SRCTOP}\"\n"; + print STDERR " \$directories{BLDTOP} = \"$directories{BLDTOP}\"\n"; + print STDERR "\n"; + print STDERR " current directory is \"",curdir(),"\"\n"; + print STDERR " the way back is \"$reverse\"\n"; + } + + return $reverse; +} + +# __wrap_cmd CMD +# __wrap_cmd CMD, EXE_SHELL +# +# __wrap_cmd "wraps" CMD (string) with a beginning command that makes sure +# the command gets executed with an appropriate environment. If EXE_SHELL +# is given, it is used as the beginning command. +# +# __wrap_cmd returns a list that should be used to build up a larger list +# of command tokens, or be joined together like this: +# +# join(" ", __wrap_cmd($cmd)) +sub __wrap_cmd { + my $cmd = shift; + my $exe_shell = shift; + + my @prefix = ( __bldtop_file("util", "shlib_wrap.sh") ); + + if(defined($exe_shell)) { + @prefix = ( $exe_shell ); + } elsif ($^O eq "VMS" || $^O eq "MSWin32") { + # VMS and Windows don't use any wrapper script for the moment + @prefix = (); + } + + return (@prefix, $cmd); +} + +# __fixup_prg PROG +# +# __fixup_prg does whatever fixup is needed to execute an executable binary +# given by PROG (string). +# +# __fixup_prg returns a string with the possibly prefixed program path spec. +sub __fixup_prg { + my $prog = shift; + + my $prefix = ""; + + if ($^O eq "VMS" ) { + $prefix = ($prog =~ /^(?:[\$a-z0-9_]+:)?[<\[]/i ? "mcr " : "mcr []"); + } + + if (defined($prog)) { + # Make sure to quotify the program file on platforms that may + # have spaces or similar in their path name. + # To our knowledge, VMS is the exception where quotifying should + # never happen. + ($prog) = quotify($prog) unless $^O eq "VMS"; + return $prefix.$prog; + } + + print STDERR "$prog not found\n"; + return undef; +} + +# __decorate_cmd NUM, CMDARRAYREF +# +# __decorate_cmd takes a command number NUM and a command token array +# CMDARRAYREF, builds up a command string from them and decorates it +# with necessary redirections. +# __decorate_cmd returns a list of two strings, one with the command +# string to actually be used, the other to be displayed for the user. +# The reason these strings might differ is that we redirect stderr to +# the null device unless we're verbose and unless the user has +# explicitly specified a stderr redirection. +sub __decorate_cmd { + BAIL_OUT("Must run setup() first") if (! $test_name); + + my $num = shift; + my $cmd = shift; + my %opts = @_; + + my $cmdstr = join(" ", @$cmd); + my $null = devnull(); + my $fileornull = sub { $_[0] ? $_[0] : $null; }; + my $stdin = ""; + my $stdout = ""; + my $stderr = ""; + my $saved_stderr = undef; + $stdin = " < ".$fileornull->($opts{stdin}) if exists($opts{stdin}); + $stdout= " > ".$fileornull->($opts{stdout}) if exists($opts{stdout}); + $stderr=" 2> ".$fileornull->($opts{stderr}) if exists($opts{stderr}); + + my $display_cmd = "$cmdstr$stdin$stdout$stderr"; + + $stderr=" 2> ".$null + unless $stderr || !$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE}; + + $cmdstr .= "$stdin$stdout$stderr"; + + if ($debug) { + print STDERR "DEBUG[__decorate_cmd]: \$cmdstr = \"$cmdstr\"\n"; + print STDERR "DEBUG[__decorate_cmd]: \$display_cmd = \"$display_cmd\"\n"; + } + + return ($cmdstr, $display_cmd); +} + +=head1 SEE ALSO + +L, L + +=head1 AUTHORS + +Richard Levitte Elevitte@openssl.orgE with assistance and +inspiration from Andy Polyakov Eappro@openssl.org. + +=cut + +no warnings 'redefine'; +sub subtest { + $level++; + + Test::More::subtest @_; + + $level--; +}; + +1; diff --git a/trunk/3rdparty/openssl-1.1-fit/util/perl/OpenSSL/Test/Simple.pm b/trunk/3rdparty/openssl-1.1-fit/util/perl/OpenSSL/Test/Simple.pm new file mode 100644 index 000000000..c5a84d5ca --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/perl/OpenSSL/Test/Simple.pm @@ -0,0 +1,91 @@ +# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +package OpenSSL::Test::Simple; + +use strict; +use warnings; + +use Exporter; +use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); +$VERSION = "0.2"; +@ISA = qw(Exporter); +@EXPORT = qw(simple_test); + +=head1 NAME + +OpenSSL::Test::Simple - a few very simple test functions + +=head1 SYNOPSIS + + use OpenSSL::Test::Simple; + + simple_test("my_test_name", "destest", "des"); + +=head1 DESCRIPTION + +Sometimes, the functions in L are quite tedious for some +repetitive tasks. This module provides functions to make life easier. +You could call them hacks if you wish. + +=cut + +use OpenSSL::Test; +use OpenSSL::Test::Utils; + +=over 4 + +=item B + +Runs a test named NAME, running the program PROGRAM with no arguments, +to test the algorithm ALGORITHM. + +A complete recipe looks like this: + + use OpenSSL::Test::Simple; + + simple_test("test_bf", "bftest", "bf"); + +=back + +=cut + +# args: +# name (used with setup()) +# algorithm (used to check if it's at all supported) +# name of binary (the program that does the actual test) +sub simple_test { + my ($name, $prgr, @algos) = @_; + + setup($name); + + if (scalar(disabled(@algos))) { + if (scalar(@algos) == 1) { + plan skip_all => $algos[0]." is not supported by this OpenSSL build"; + } else { + my $last = pop @algos; + plan skip_all => join(", ", @algos)." and $last are not supported by this OpenSSL build"; + } + } + + plan tests => 1; + + ok(run(test([$prgr])), "running $prgr"); +} + +=head1 SEE ALSO + +L + +=head1 AUTHORS + +Richard Levitte Elevitte@openssl.orgE with inspiration +from Rich Salz Ersalz@openssl.orgE. + +=cut + +1; diff --git a/trunk/3rdparty/openssl-1.1-fit/util/perl/OpenSSL/Test/Utils.pm b/trunk/3rdparty/openssl-1.1-fit/util/perl/OpenSSL/Test/Utils.pm new file mode 100644 index 000000000..7b0a70563 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/perl/OpenSSL/Test/Utils.pm @@ -0,0 +1,240 @@ +# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +package OpenSSL::Test::Utils; + +use strict; +use warnings; + +use Exporter; +use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); +$VERSION = "0.1"; +@ISA = qw(Exporter); +@EXPORT = qw(alldisabled anydisabled disabled config available_protocols + have_IPv4 have_IPv6); + +=head1 NAME + +OpenSSL::Test::Utils - test utility functions + +=head1 SYNOPSIS + + use OpenSSL::Test::Utils; + + my @tls = available_protocols("tls"); + my @dtls = available_protocols("dtls"); + alldisabled("dh", "dsa"); + anydisabled("dh", "dsa"); + + config("fips"); + + have_IPv4(); + have_IPv6(); + +=head1 DESCRIPTION + +This module provides utility functions for the testing framework. + +=cut + +use OpenSSL::Test qw/:DEFAULT bldtop_file/; + +=over 4 + +=item B + +Returns a list of strings for all the available SSL/TLS versions if +STRING is "tls", or for all the available DTLS versions if STRING is +"dtls". Otherwise, it returns the empty list. The strings in the +returned list can be used with B and B. + +=item B +=item B + +In an array context returns an array with each element set to 1 if the +corresponding feature is disabled and 0 otherwise. + +In a scalar context, alldisabled returns 1 if all of the features in +ARRAY are disabled, while anydisabled returns 1 if any of them are +disabled. + +=item B + +Returns an item from the %config hash in \$TOP/configdata.pm. + +=item B +=item B + +Return true if IPv4 / IPv6 is possible to use on the current system. + +=back + +=cut + +our %available_protocols; +our %disabled; +our %config; +my $configdata_loaded = 0; + +sub load_configdata { + # We eval it so it doesn't run at compile time of this file. + # The latter would have bldtop_file() complain that setup() hasn't + # been run yet. + my $configdata = bldtop_file("configdata.pm"); + eval { require $configdata; + %available_protocols = %configdata::available_protocols; + %disabled = %configdata::disabled; + %config = %configdata::config; + }; + $configdata_loaded = 1; +} + +# args +# list of 1s and 0s, coming from check_disabled() +sub anyof { + my $x = 0; + foreach (@_) { $x += $_ } + return $x > 0; +} + +# args +# list of 1s and 0s, coming from check_disabled() +sub allof { + my $x = 1; + foreach (@_) { $x *= $_ } + return $x > 0; +} + +# args +# list of strings, all of them should be names of features +# that can be disabled. +# returns a list of 1s (if the corresponding feature is disabled) +# and 0s (if it isn't) +sub check_disabled { + return map { exists $disabled{lc $_} ? 1 : 0 } @_; +} + +# Exported functions ################################################# + +# args: +# list of features to check +sub anydisabled { + load_configdata() unless $configdata_loaded; + my @ret = check_disabled(@_); + return @ret if wantarray; + return anyof(@ret); +} + +# args: +# list of features to check +sub alldisabled { + load_configdata() unless $configdata_loaded; + my @ret = check_disabled(@_); + return @ret if wantarray; + return allof(@ret); +} + +# !!! Kept for backward compatibility +# args: +# single string +sub disabled { + anydisabled(@_); +} + +sub available_protocols { + load_configdata() unless $configdata_loaded; + my $protocol_class = shift; + if (exists $available_protocols{lc $protocol_class}) { + return @{$available_protocols{lc $protocol_class}} + } + return (); +} + +sub config { + load_configdata() unless $configdata_loaded; + return $config{$_[0]}; +} + +# IPv4 / IPv6 checker +my $have_IPv4 = -1; +my $have_IPv6 = -1; +my $IP_factory; +sub check_IP { + my $listenaddress = shift; + + eval { + require IO::Socket::IP; + my $s = IO::Socket::IP->new( + LocalAddr => $listenaddress, + LocalPort => 0, + Listen=>1, + ); + $s or die "\n"; + $s->close(); + }; + if ($@ eq "") { + return 1; + } + + eval { + require IO::Socket::INET6; + my $s = IO::Socket::INET6->new( + LocalAddr => $listenaddress, + LocalPort => 0, + Listen=>1, + ); + $s or die "\n"; + $s->close(); + }; + if ($@ eq "") { + return 1; + } + + eval { + require IO::Socket::INET; + my $s = IO::Socket::INET->new( + LocalAddr => $listenaddress, + LocalPort => 0, + Listen=>1, + ); + $s or die "\n"; + $s->close(); + }; + if ($@ eq "") { + return 1; + } + + return 0; +} + +sub have_IPv4 { + if ($have_IPv4 < 0) { + $have_IPv4 = check_IP("127.0.0.1"); + } + return $have_IPv4; +} + +sub have_IPv6 { + if ($have_IPv6 < 0) { + $have_IPv6 = check_IP("::1"); + } + return $have_IPv6; +} + + +=head1 SEE ALSO + +L + +=head1 AUTHORS + +Stephen Henson Esteve@openssl.orgE and +Richard Levitte Elevitte@openssl.orgE + +=cut + +1; diff --git a/trunk/3rdparty/openssl-1.1-fit/util/perl/OpenSSL/Util/Pod.pm b/trunk/3rdparty/openssl-1.1-fit/util/perl/OpenSSL/Util/Pod.pm new file mode 100644 index 000000000..9f76fbf1a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/perl/OpenSSL/Util/Pod.pm @@ -0,0 +1,149 @@ +# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +package OpenSSL::Util::Pod; + +use strict; +use warnings; + +use Exporter; +use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); +$VERSION = "0.1"; +@ISA = qw(Exporter); +@EXPORT = qw(extract_pod_info); +@EXPORT_OK = qw(); + +=head1 NAME + +OpenSSL::Util::Pod - utilities to manipulate .pod files + +=head1 SYNOPSIS + + use OpenSSL::Util::Pod; + + my %podinfo = extract_pod_info("foo.pod"); + + # or if the file is already opened... Note that this consumes the + # remainder of the file. + + my %podinfo = extract_pod_info(\*STDIN); + +=head1 DESCRIPTION + +=over + +=item B + +=item B + +=item B + +=item B + +Extracts information from a .pod file, given a STRING (file name) or a +GLOB (a file handle). The result is given back as a hash table. + +The additional hash is for extra parameters: + +=over + +=item B
N> + +The value MUST be a number, and will be the man section number +to be used with the given .pod file. + +=item B 0|1> + +If set to 1, extra debug text will be printed on STDERR + +=back + +=back + +=head1 RETURN VALUES + +=over + +=item B returns a hash table with the following +items: + +=over + +=item B
N> + +The man section number this .pod file belongs to. Often the same as +was given as input. + +=item B [ "name", ... ]> + +All the names extracted from the NAME section. + +=back + +=back + +=cut + +sub extract_pod_info { + my $input = shift; + my $defaults_ref = shift || {}; + my %defaults = ( debug => 0, section => 0, %$defaults_ref ); + my $fh = undef; + my $filename = undef; + + # If not a file handle, then it's assume to be a file path (a string) + unless (ref $input eq "GLOB") { + $filename = $input; + open $fh, $input or die "Trying to read $filename: $!\n"; + print STDERR "DEBUG: Reading $input\n" if $defaults{debug}; + $input = $fh; + } + + my %podinfo = ( section => $defaults{section}); + while(<$input>) { + s|\R$||; + # Stop reading when we have reached past the NAME section. + last if (m|^=head1| + && defined $podinfo{lastsect} + && $podinfo{lastsect} eq "NAME"); + + # Collect the section name + if (m|^=head1\s*(.*)|) { + $podinfo{lastsect} = $1; + $podinfo{lastsect} =~ s/\s+$//; + print STDERR "DEBUG: Found new pod section $1\n" + if $defaults{debug}; + print STDERR "DEBUG: Clearing pod section text\n" + if $defaults{debug}; + $podinfo{lastsecttext} = ""; + } + + next if (m|^=| || m|^\s*$|); + + # Collect the section text + print STDERR "DEBUG: accumulating pod section text \"$_\"\n" + if $defaults{debug}; + $podinfo{lastsecttext} .= " " if $podinfo{lastsecttext}; + $podinfo{lastsecttext} .= $_; + } + + + if (defined $fh) { + close $fh; + print STDERR "DEBUG: Done reading $filename\n" if $defaults{debug}; + } + + $podinfo{lastsecttext} =~ s| - .*$||; + + my @names = + map { s|\s+||g; $_ } + split(m|,|, $podinfo{lastsecttext}); + + return ( section => $podinfo{section}, names => [ @names ] ); +} + +1; diff --git a/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/Alert.pm b/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/Alert.pm new file mode 100644 index 000000000..e27497dbd --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/Alert.pm @@ -0,0 +1,51 @@ +# Copyright 2018-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use strict; + +package TLSProxy::Alert; + +sub new +{ + my $class = shift; + my ($server, + $encrypted, + $level, + $description) = @_; + + my $self = { + server => $server, + encrypted => $encrypted, + level => $level, + description => $description + }; + + return bless $self, $class; +} + +#Read only accessors +sub server +{ + my $self = shift; + return $self->{server}; +} +sub encrypted +{ + my $self = shift; + return $self->{encrypted}; +} +sub level +{ + my $self = shift; + return $self->{level}; +} +sub description +{ + my $self = shift; + return $self->{description}; +} +1; diff --git a/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/Certificate.pm b/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/Certificate.pm new file mode 100644 index 000000000..73737137b --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/Certificate.pm @@ -0,0 +1,214 @@ +# Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use strict; + +package TLSProxy::Certificate; + +use vars '@ISA'; +push @ISA, 'TLSProxy::Message'; + +sub new +{ + my $class = shift; + my ($server, + $data, + $records, + $startoffset, + $message_frag_lens) = @_; + + my $self = $class->SUPER::new( + $server, + TLSProxy::Message::MT_CERTIFICATE, + $data, + $records, + $startoffset, + $message_frag_lens); + + $self->{first_certificate} = ""; + $self->{extension_data} = ""; + $self->{remaining_certdata} = ""; + + return $self; +} + +sub parse +{ + my $self = shift; + + if (TLSProxy::Proxy->is_tls13()) { + my $context_len = unpack('C', $self->data); + my $context = substr($self->data, 1, $context_len); + + my $remdata = substr($self->data, 1 + $context_len); + + my ($hicertlistlen, $certlistlen) = unpack('Cn', $remdata); + $certlistlen += ($hicertlistlen << 16); + + $remdata = substr($remdata, 3); + + die "Invalid Certificate List length" + if length($remdata) != $certlistlen; + + my ($hicertlen, $certlen) = unpack('Cn', $remdata); + $certlen += ($hicertlen << 16); + + die "Certificate too long" if ($certlen + 3) > $certlistlen; + + $remdata = substr($remdata, 3); + + my $certdata = substr($remdata, 0, $certlen); + + $remdata = substr($remdata, $certlen); + + my $extensions_len = unpack('n', $remdata); + $remdata = substr($remdata, 2); + + die "Extensions too long" + if ($certlen + 3 + $extensions_len + 2) > $certlistlen; + + my $extension_data = ""; + if ($extensions_len != 0) { + $extension_data = substr($remdata, 0, $extensions_len); + + if (length($extension_data) != $extensions_len) { + die "Invalid extension length\n"; + } + } + my %extensions = (); + while (length($extension_data) >= 4) { + my ($type, $size) = unpack("nn", $extension_data); + my $extdata = substr($extension_data, 4, $size); + $extension_data = substr($extension_data, 4 + $size); + $extensions{$type} = $extdata; + } + $remdata = substr($remdata, $extensions_len); + + $self->context($context); + $self->first_certificate($certdata); + $self->extension_data(\%extensions); + $self->remaining_certdata($remdata); + + print " Context:".$context."\n"; + print " Certificate List Len:".$certlistlen."\n"; + print " Certificate Len:".$certlen."\n"; + print " Extensions Len:".$extensions_len."\n"; + } else { + my ($hicertlistlen, $certlistlen) = unpack('Cn', $self->data); + $certlistlen += ($hicertlistlen << 16); + + my $remdata = substr($self->data, 3); + + die "Invalid Certificate List length" + if length($remdata) != $certlistlen; + + my ($hicertlen, $certlen) = unpack('Cn', $remdata); + $certlen += ($hicertlen << 16); + + die "Certificate too long" if ($certlen + 3) > $certlistlen; + + $remdata = substr($remdata, 3); + + my $certdata = substr($remdata, 0, $certlen); + + $remdata = substr($remdata, $certlen); + + $self->first_certificate($certdata); + $self->remaining_certdata($remdata); + + print " Certificate List Len:".$certlistlen."\n"; + print " Certificate Len:".$certlen."\n"; + } +} + +#Reconstruct the on-the-wire message data following changes +sub set_message_contents +{ + my $self = shift; + my $data; + my $extensions = ""; + + if (TLSProxy::Proxy->is_tls13()) { + foreach my $key (keys %{$self->extension_data}) { + my $extdata = ${$self->extension_data}{$key}; + $extensions .= pack("n", $key); + $extensions .= pack("n", length($extdata)); + $extensions .= $extdata; + } + $data = pack('C', length($self->context())); + $data .= $self->context; + my $certlen = length($self->first_certificate); + my $certlistlen = $certlen + length($extensions) + + length($self->remaining_certdata); + my $hi = $certlistlen >> 16; + $certlistlen = $certlistlen & 0xffff; + $data .= pack('Cn', $hi, $certlistlen); + $hi = $certlen >> 16; + $certlen = $certlen & 0xffff; + $data .= pack('Cn', $hi, $certlen); + $data .= pack('n', length($extensions)); + $data .= $extensions; + $data .= $self->remaining_certdata(); + $self->data($data); + } else { + my $certlen = length($self->first_certificate); + my $certlistlen = $certlen + length($self->remaining_certdata); + my $hi = $certlistlen >> 16; + $certlistlen = $certlistlen & 0xffff; + $data .= pack('Cn', $hi, $certlistlen); + $hi = $certlen >> 16; + $certlen = $certlen & 0xffff; + $data .= pack('Cn', $hi, $certlen); + $data .= $self->remaining_certdata(); + $self->data($data); + } +} + +#Read/write accessors +sub context +{ + my $self = shift; + if (@_) { + $self->{context} = shift; + } + return $self->{context}; +} +sub first_certificate +{ + my $self = shift; + if (@_) { + $self->{first_certificate} = shift; + } + return $self->{first_certificate}; +} +sub remaining_certdata +{ + my $self = shift; + if (@_) { + $self->{remaining_certdata} = shift; + } + return $self->{remaining_certdata}; +} +sub extension_data +{ + my $self = shift; + if (@_) { + $self->{extension_data} = shift; + } + return $self->{extension_data}; +} +sub set_extension +{ + my ($self, $ext_type, $ext_data) = @_; + $self->{extension_data}{$ext_type} = $ext_data; +} +sub delete_extension +{ + my ($self, $ext_type) = @_; + delete $self->{extension_data}{$ext_type}; +} +1; diff --git a/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/CertificateVerify.pm b/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/CertificateVerify.pm new file mode 100644 index 000000000..8bf969fba --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/CertificateVerify.pm @@ -0,0 +1,96 @@ +# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use strict; + +package TLSProxy::CertificateVerify; + +use vars '@ISA'; +push @ISA, 'TLSProxy::Message'; + +sub new +{ + my $class = shift; + my ($server, + $data, + $records, + $startoffset, + $message_frag_lens) = @_; + + my $self = $class->SUPER::new( + $server, + TLSProxy::Message::MT_CERTIFICATE_VERIFY, + $data, + $records, + $startoffset, + $message_frag_lens); + + $self->{sigalg} = -1; + $self->{signature} = ""; + + return $self; +} + +sub parse +{ + my $self = shift; + + my $sigalg = -1; + my $remdata = $self->data; + my $record = ${$self->records}[0]; + + if (TLSProxy::Proxy->is_tls13() + || $record->version() == TLSProxy::Record::VERS_TLS_1_2) { + $sigalg = unpack('n', $remdata); + $remdata = substr($remdata, 2); + } + + my $siglen = unpack('n', substr($remdata, 0, 2)); + my $sig = substr($remdata, 2); + + die "Invalid CertificateVerify signature length" if length($sig) != $siglen; + + print " SigAlg:".$sigalg."\n"; + print " Signature Len:".$siglen."\n"; + + $self->sigalg($sigalg); + $self->signature($sig); +} + +#Reconstruct the on-the-wire message data following changes +sub set_message_contents +{ + my $self = shift; + my $data = ""; + my $sig = $self->signature(); + my $olddata = $self->data(); + + $data .= pack("n", $self->sigalg()) if ($self->sigalg() != -1); + $data .= pack("n", length($sig)); + $data .= $sig; + + $self->data($data); +} + +#Read/write accessors +sub sigalg +{ + my $self = shift; + if (@_) { + $self->{sigalg} = shift; + } + return $self->{sigalg}; +} +sub signature +{ + my $self = shift; + if (@_) { + $self->{signature} = shift; + } + return $self->{signature}; +} +1; diff --git a/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/ClientHello.pm b/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/ClientHello.pm new file mode 100644 index 000000000..76dce740a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/ClientHello.pm @@ -0,0 +1,258 @@ +# Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use strict; + +package TLSProxy::ClientHello; + +use vars '@ISA'; +push @ISA, 'TLSProxy::Message'; + +sub new +{ + my $class = shift; + my ($server, + $data, + $records, + $startoffset, + $message_frag_lens) = @_; + + my $self = $class->SUPER::new( + $server, + 1, + $data, + $records, + $startoffset, + $message_frag_lens); + + $self->{client_version} = 0; + $self->{random} = []; + $self->{session_id_len} = 0; + $self->{session} = ""; + $self->{ciphersuite_len} = 0; + $self->{ciphersuites} = []; + $self->{comp_meth_len} = 0; + $self->{comp_meths} = []; + $self->{extensions_len} = 0; + $self->{extension_data} = ""; + + return $self; +} + +sub parse +{ + my $self = shift; + my $ptr = 2; + my ($client_version) = unpack('n', $self->data); + my $random = substr($self->data, $ptr, 32); + $ptr += 32; + my $session_id_len = unpack('C', substr($self->data, $ptr)); + $ptr++; + my $session = substr($self->data, $ptr, $session_id_len); + $ptr += $session_id_len; + my $ciphersuite_len = unpack('n', substr($self->data, $ptr)); + $ptr += 2; + my @ciphersuites = unpack('n*', substr($self->data, $ptr, + $ciphersuite_len)); + $ptr += $ciphersuite_len; + my $comp_meth_len = unpack('C', substr($self->data, $ptr)); + $ptr++; + my @comp_meths = unpack('C*', substr($self->data, $ptr, $comp_meth_len)); + $ptr += $comp_meth_len; + my $extensions_len = unpack('n', substr($self->data, $ptr)); + $ptr += 2; + #For now we just deal with this as a block of data. In the future we will + #want to parse this + my $extension_data = substr($self->data, $ptr); + + if (length($extension_data) != $extensions_len) { + die "Invalid extension length\n"; + } + my %extensions = (); + while (length($extension_data) >= 4) { + my ($type, $size) = unpack("nn", $extension_data); + my $extdata = substr($extension_data, 4, $size); + $extension_data = substr($extension_data, 4 + $size); + $extensions{$type} = $extdata; + } + + $self->client_version($client_version); + $self->random($random); + $self->session_id_len($session_id_len); + $self->session($session); + $self->ciphersuite_len($ciphersuite_len); + $self->ciphersuites(\@ciphersuites); + $self->comp_meth_len($comp_meth_len); + $self->comp_meths(\@comp_meths); + $self->extensions_len($extensions_len); + $self->extension_data(\%extensions); + + $self->process_extensions(); + + print " Client Version:".$client_version."\n"; + print " Session ID Len:".$session_id_len."\n"; + print " Ciphersuite len:".$ciphersuite_len."\n"; + print " Compression Method Len:".$comp_meth_len."\n"; + print " Extensions Len:".$extensions_len."\n"; +} + +#Perform any actions necessary based on the extensions we've seen +sub process_extensions +{ + my $self = shift; + my %extensions = %{$self->extension_data}; + + #Clear any state from a previous run + TLSProxy::Record->etm(0); + + if (exists $extensions{TLSProxy::Message::EXT_ENCRYPT_THEN_MAC}) { + TLSProxy::Record->etm(1); + } +} + +sub extension_contents +{ + my $self = shift; + my $key = shift; + my $extension = ""; + + my $extdata = ${$self->extension_data}{$key}; + $extension .= pack("n", $key); + $extension .= pack("n", length($extdata)); + $extension .= $extdata; + return $extension; +} + +#Reconstruct the on-the-wire message data following changes +sub set_message_contents +{ + my $self = shift; + my $data; + my $extensions = ""; + + $data = pack('n', $self->client_version); + $data .= $self->random; + $data .= pack('C', $self->session_id_len); + $data .= $self->session; + $data .= pack('n', $self->ciphersuite_len); + $data .= pack("n*", @{$self->ciphersuites}); + $data .= pack('C', $self->comp_meth_len); + $data .= pack("C*", @{$self->comp_meths}); + + foreach my $key (keys %{$self->extension_data}) { + next if ($key == TLSProxy::Message::EXT_PSK); + $extensions .= $self->extension_contents($key); + #Add extension twice if we are duplicating that extension + $extensions .= $self->extension_contents($key) if ($key == $self->dupext); + } + #PSK extension always goes last... + if (defined ${$self->extension_data}{TLSProxy::Message::EXT_PSK}) { + $extensions .= $self->extension_contents(TLSProxy::Message::EXT_PSK); + } + #unless we have EXT_FORCE_LAST + if (defined ${$self->extension_data}{TLSProxy::Message::EXT_FORCE_LAST}) { + $extensions .= $self->extension_contents(TLSProxy::Message::EXT_FORCE_LAST); + } + + $data .= pack('n', length($extensions)); + $data .= $extensions; + + $self->data($data); +} + +#Read/write accessors +sub client_version +{ + my $self = shift; + if (@_) { + $self->{client_version} = shift; + } + return $self->{client_version}; +} +sub random +{ + my $self = shift; + if (@_) { + $self->{random} = shift; + } + return $self->{random}; +} +sub session_id_len +{ + my $self = shift; + if (@_) { + $self->{session_id_len} = shift; + } + return $self->{session_id_len}; +} +sub session +{ + my $self = shift; + if (@_) { + $self->{session} = shift; + } + return $self->{session}; +} +sub ciphersuite_len +{ + my $self = shift; + if (@_) { + $self->{ciphersuite_len} = shift; + } + return $self->{ciphersuite_len}; +} +sub ciphersuites +{ + my $self = shift; + if (@_) { + $self->{ciphersuites} = shift; + } + return $self->{ciphersuites}; +} +sub comp_meth_len +{ + my $self = shift; + if (@_) { + $self->{comp_meth_len} = shift; + } + return $self->{comp_meth_len}; +} +sub comp_meths +{ + my $self = shift; + if (@_) { + $self->{comp_meths} = shift; + } + return $self->{comp_meths}; +} +sub extensions_len +{ + my $self = shift; + if (@_) { + $self->{extensions_len} = shift; + } + return $self->{extensions_len}; +} +sub extension_data +{ + my $self = shift; + if (@_) { + $self->{extension_data} = shift; + } + return $self->{extension_data}; +} +sub set_extension +{ + my ($self, $ext_type, $ext_data) = @_; + $self->{extension_data}{$ext_type} = $ext_data; +} +sub delete_extension +{ + my ($self, $ext_type) = @_; + delete $self->{extension_data}{$ext_type}; +} +1; diff --git a/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/EncryptedExtensions.pm b/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/EncryptedExtensions.pm new file mode 100644 index 000000000..262b720cf --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/EncryptedExtensions.pm @@ -0,0 +1,110 @@ +# Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use strict; + +package TLSProxy::EncryptedExtensions; + +use vars '@ISA'; +push @ISA, 'TLSProxy::Message'; + +sub new +{ + my $class = shift; + my ($server, + $data, + $records, + $startoffset, + $message_frag_lens) = @_; + + my $self = $class->SUPER::new( + $server, + TLSProxy::Message::MT_ENCRYPTED_EXTENSIONS, + $data, + $records, + $startoffset, + $message_frag_lens); + + $self->{extension_data} = ""; + + return $self; +} + +sub parse +{ + my $self = shift; + + my $extensions_len = unpack('n', $self->data); + if (!defined $extensions_len) { + $extensions_len = 0; + } + + my $extension_data; + if ($extensions_len != 0) { + $extension_data = substr($self->data, 2); + + if (length($extension_data) != $extensions_len) { + die "Invalid extension length\n"; + } + } else { + if (length($self->data) != 2) { + die "Invalid extension length\n"; + } + $extension_data = ""; + } + my %extensions = (); + while (length($extension_data) >= 4) { + my ($type, $size) = unpack("nn", $extension_data); + my $extdata = substr($extension_data, 4, $size); + $extension_data = substr($extension_data, 4 + $size); + $extensions{$type} = $extdata; + } + + $self->extension_data(\%extensions); + + print " Extensions Len:".$extensions_len."\n"; +} + +#Reconstruct the on-the-wire message data following changes +sub set_message_contents +{ + my $self = shift; + my $data; + my $extensions = ""; + + foreach my $key (keys %{$self->extension_data}) { + my $extdata = ${$self->extension_data}{$key}; + $extensions .= pack("n", $key); + $extensions .= pack("n", length($extdata)); + $extensions .= $extdata; + } + + $data = pack('n', length($extensions)); + $data .= $extensions; + $self->data($data); +} + +#Read/write accessors +sub extension_data +{ + my $self = shift; + if (@_) { + $self->{extension_data} = shift; + } + return $self->{extension_data}; +} +sub set_extension +{ + my ($self, $ext_type, $ext_data) = @_; + $self->{extension_data}{$ext_type} = $ext_data; +} +sub delete_extension +{ + my ($self, $ext_type) = @_; + delete $self->{extension_data}{$ext_type}; +} +1; diff --git a/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/Message.pm b/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/Message.pm new file mode 100644 index 000000000..5682ae3e1 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/Message.pm @@ -0,0 +1,592 @@ +# Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use strict; + +package TLSProxy::Message; + +use TLSProxy::Alert; + +use constant TLS_MESSAGE_HEADER_LENGTH => 4; + +#Message types +use constant { + MT_HELLO_REQUEST => 0, + MT_CLIENT_HELLO => 1, + MT_SERVER_HELLO => 2, + MT_NEW_SESSION_TICKET => 4, + MT_ENCRYPTED_EXTENSIONS => 8, + MT_CERTIFICATE => 11, + MT_SERVER_KEY_EXCHANGE => 12, + MT_CERTIFICATE_REQUEST => 13, + MT_SERVER_HELLO_DONE => 14, + MT_CERTIFICATE_VERIFY => 15, + MT_CLIENT_KEY_EXCHANGE => 16, + MT_FINISHED => 20, + MT_CERTIFICATE_STATUS => 22, + MT_NEXT_PROTO => 67 +}; + +#Alert levels +use constant { + AL_LEVEL_WARN => 1, + AL_LEVEL_FATAL => 2 +}; + +#Alert descriptions +use constant { + AL_DESC_CLOSE_NOTIFY => 0, + AL_DESC_UNEXPECTED_MESSAGE => 10, + AL_DESC_ILLEGAL_PARAMETER => 47, + AL_DESC_NO_RENEGOTIATION => 100 +}; + +my %message_type = ( + MT_HELLO_REQUEST, "HelloRequest", + MT_CLIENT_HELLO, "ClientHello", + MT_SERVER_HELLO, "ServerHello", + MT_NEW_SESSION_TICKET, "NewSessionTicket", + MT_ENCRYPTED_EXTENSIONS, "EncryptedExtensions", + MT_CERTIFICATE, "Certificate", + MT_SERVER_KEY_EXCHANGE, "ServerKeyExchange", + MT_CERTIFICATE_REQUEST, "CertificateRequest", + MT_SERVER_HELLO_DONE, "ServerHelloDone", + MT_CERTIFICATE_VERIFY, "CertificateVerify", + MT_CLIENT_KEY_EXCHANGE, "ClientKeyExchange", + MT_FINISHED, "Finished", + MT_CERTIFICATE_STATUS, "CertificateStatus", + MT_NEXT_PROTO, "NextProto" +); + +use constant { + EXT_SERVER_NAME => 0, + EXT_MAX_FRAGMENT_LENGTH => 1, + EXT_STATUS_REQUEST => 5, + EXT_SUPPORTED_GROUPS => 10, + EXT_EC_POINT_FORMATS => 11, + EXT_SRP => 12, + EXT_SIG_ALGS => 13, + EXT_USE_SRTP => 14, + EXT_ALPN => 16, + EXT_SCT => 18, + EXT_PADDING => 21, + EXT_ENCRYPT_THEN_MAC => 22, + EXT_EXTENDED_MASTER_SECRET => 23, + EXT_SESSION_TICKET => 35, + EXT_KEY_SHARE => 51, + EXT_PSK => 41, + EXT_SUPPORTED_VERSIONS => 43, + EXT_COOKIE => 44, + EXT_PSK_KEX_MODES => 45, + EXT_POST_HANDSHAKE_AUTH => 49, + EXT_SIG_ALGS_CERT => 50, + EXT_RENEGOTIATE => 65281, + EXT_NPN => 13172, + EXT_CRYPTOPRO_BUG_EXTENSION => 0xfde8, + EXT_UNKNOWN => 0xfffe, + #Unknown extension that should appear last + EXT_FORCE_LAST => 0xffff +}; + +# SignatureScheme of TLS 1.3 from: +# https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-signaturescheme +# We have to manually grab the SHA224 equivalents from the old registry +use constant { + SIG_ALG_RSA_PKCS1_SHA256 => 0x0401, + SIG_ALG_RSA_PKCS1_SHA384 => 0x0501, + SIG_ALG_RSA_PKCS1_SHA512 => 0x0601, + SIG_ALG_ECDSA_SECP256R1_SHA256 => 0x0403, + SIG_ALG_ECDSA_SECP384R1_SHA384 => 0x0503, + SIG_ALG_ECDSA_SECP521R1_SHA512 => 0x0603, + SIG_ALG_RSA_PSS_RSAE_SHA256 => 0x0804, + SIG_ALG_RSA_PSS_RSAE_SHA384 => 0x0805, + SIG_ALG_RSA_PSS_RSAE_SHA512 => 0x0806, + SIG_ALG_ED25519 => 0x0807, + SIG_ALG_ED448 => 0x0808, + SIG_ALG_RSA_PSS_PSS_SHA256 => 0x0809, + SIG_ALG_RSA_PSS_PSS_SHA384 => 0x080a, + SIG_ALG_RSA_PSS_PSS_SHA512 => 0x080b, + SIG_ALG_RSA_PKCS1_SHA1 => 0x0201, + SIG_ALG_ECDSA_SHA1 => 0x0203, + SIG_ALG_DSA_SHA1 => 0x0202, + SIG_ALG_DSA_SHA256 => 0x0402, + SIG_ALG_DSA_SHA384 => 0x0502, + SIG_ALG_DSA_SHA512 => 0x0602, + OSSL_SIG_ALG_RSA_PKCS1_SHA224 => 0x0301, + OSSL_SIG_ALG_DSA_SHA224 => 0x0302, + OSSL_SIG_ALG_ECDSA_SHA224 => 0x0303 +}; + +use constant { + CIPHER_RSA_WITH_AES_128_CBC_SHA => 0x002f, + CIPHER_DHE_RSA_AES_128_SHA => 0x0033, + CIPHER_ADH_AES_128_SHA => 0x0034, + CIPHER_TLS13_AES_128_GCM_SHA256 => 0x1301, + CIPHER_TLS13_AES_256_GCM_SHA384 => 0x1302 +}; + +my $payload = ""; +my $messlen = -1; +my $mt; +my $startoffset = -1; +my $server = 0; +my $success = 0; +my $end = 0; +my @message_rec_list = (); +my @message_frag_lens = (); +my $ciphersuite = 0; +my $successondata = 0; +my $alert; + +sub clear +{ + $payload = ""; + $messlen = -1; + $startoffset = -1; + $server = 0; + $success = 0; + $end = 0; + $successondata = 0; + @message_rec_list = (); + @message_frag_lens = (); + $alert = undef; +} + +#Class method to extract messages from a record +sub get_messages +{ + my $class = shift; + my $serverin = shift; + my $record = shift; + my @messages = (); + my $message; + + @message_frag_lens = (); + + if ($serverin != $server && length($payload) != 0) { + die "Changed peer, but we still have fragment data\n"; + } + $server = $serverin; + + if ($record->content_type == TLSProxy::Record::RT_CCS) { + if ($payload ne "") { + #We can't handle this yet + die "CCS received before message data complete\n"; + } + if (!TLSProxy::Proxy->is_tls13()) { + if ($server) { + TLSProxy::Record->server_encrypting(1); + } else { + TLSProxy::Record->client_encrypting(1); + } + } + } elsif ($record->content_type == TLSProxy::Record::RT_HANDSHAKE) { + if ($record->len == 0 || $record->len_real == 0) { + print " Message truncated\n"; + } else { + my $recoffset = 0; + + if (length $payload > 0) { + #We are continuing processing a message started in a previous + #record. Add this record to the list associated with this + #message + push @message_rec_list, $record; + + if ($messlen <= length($payload)) { + #Shouldn't happen + die "Internal error: invalid messlen: ".$messlen + ." payload length:".length($payload)."\n"; + } + if (length($payload) + $record->decrypt_len >= $messlen) { + #We can complete the message with this record + $recoffset = $messlen - length($payload); + $payload .= substr($record->decrypt_data, 0, $recoffset); + push @message_frag_lens, $recoffset; + $message = create_message($server, $mt, $payload, + $startoffset); + push @messages, $message; + + $payload = ""; + } else { + #This is just part of the total message + $payload .= $record->decrypt_data; + $recoffset = $record->decrypt_len; + push @message_frag_lens, $record->decrypt_len; + } + print " Partial message data read: ".$recoffset." bytes\n"; + } + + while ($record->decrypt_len > $recoffset) { + #We are at the start of a new message + if ($record->decrypt_len - $recoffset < 4) { + #Whilst technically probably valid we can't cope with this + die "End of record in the middle of a message header\n"; + } + @message_rec_list = ($record); + my $lenhi; + my $lenlo; + ($mt, $lenhi, $lenlo) = unpack('CnC', + substr($record->decrypt_data, + $recoffset)); + $messlen = ($lenhi << 8) | $lenlo; + print " Message type: $message_type{$mt}\n"; + print " Message Length: $messlen\n"; + $startoffset = $recoffset; + $recoffset += 4; + $payload = ""; + + if ($recoffset <= $record->decrypt_len) { + #Some payload data is present in this record + if ($record->decrypt_len - $recoffset >= $messlen) { + #We can complete the message with this record + $payload .= substr($record->decrypt_data, $recoffset, + $messlen); + $recoffset += $messlen; + push @message_frag_lens, $messlen; + $message = create_message($server, $mt, $payload, + $startoffset); + push @messages, $message; + + $payload = ""; + } else { + #This is just part of the total message + $payload .= substr($record->decrypt_data, $recoffset, + $record->decrypt_len - $recoffset); + $recoffset = $record->decrypt_len; + push @message_frag_lens, $recoffset; + } + } + } + } + } elsif ($record->content_type == TLSProxy::Record::RT_APPLICATION_DATA) { + print " [ENCRYPTED APPLICATION DATA]\n"; + print " [".$record->decrypt_data."]\n"; + + if ($successondata) { + $success = 1; + $end = 1; + } + } elsif ($record->content_type == TLSProxy::Record::RT_ALERT) { + my ($alertlev, $alertdesc) = unpack('CC', $record->decrypt_data); + print " [$alertlev, $alertdesc]\n"; + #A CloseNotify from the client indicates we have finished successfully + #(we assume) + if (!$end && !$server && $alertlev == AL_LEVEL_WARN + && $alertdesc == AL_DESC_CLOSE_NOTIFY) { + $success = 1; + } + #Fatal or close notify alerts end the test + if ($alertlev == AL_LEVEL_FATAL || $alertdesc == AL_DESC_CLOSE_NOTIFY) { + $end = 1; + } + $alert = TLSProxy::Alert->new( + $server, + $record->encrypted, + $alertlev, + $alertdesc); + } + + return @messages; +} + +#Function to work out which sub-class we need to create and then +#construct it +sub create_message +{ + my ($server, $mt, $data, $startoffset) = @_; + my $message; + + #We only support ClientHello in this version...needs to be extended for + #others + if ($mt == MT_CLIENT_HELLO) { + $message = TLSProxy::ClientHello->new( + $server, + $data, + [@message_rec_list], + $startoffset, + [@message_frag_lens] + ); + $message->parse(); + } elsif ($mt == MT_SERVER_HELLO) { + $message = TLSProxy::ServerHello->new( + $server, + $data, + [@message_rec_list], + $startoffset, + [@message_frag_lens] + ); + $message->parse(); + } elsif ($mt == MT_ENCRYPTED_EXTENSIONS) { + $message = TLSProxy::EncryptedExtensions->new( + $server, + $data, + [@message_rec_list], + $startoffset, + [@message_frag_lens] + ); + $message->parse(); + } elsif ($mt == MT_CERTIFICATE) { + $message = TLSProxy::Certificate->new( + $server, + $data, + [@message_rec_list], + $startoffset, + [@message_frag_lens] + ); + $message->parse(); + } elsif ($mt == MT_CERTIFICATE_VERIFY) { + $message = TLSProxy::CertificateVerify->new( + $server, + $data, + [@message_rec_list], + $startoffset, + [@message_frag_lens] + ); + $message->parse(); + } elsif ($mt == MT_SERVER_KEY_EXCHANGE) { + $message = TLSProxy::ServerKeyExchange->new( + $server, + $data, + [@message_rec_list], + $startoffset, + [@message_frag_lens] + ); + $message->parse(); + } elsif ($mt == MT_NEW_SESSION_TICKET) { + $message = TLSProxy::NewSessionTicket->new( + $server, + $data, + [@message_rec_list], + $startoffset, + [@message_frag_lens] + ); + $message->parse(); + } else { + #Unknown message type + $message = TLSProxy::Message->new( + $server, + $mt, + $data, + [@message_rec_list], + $startoffset, + [@message_frag_lens] + ); + } + + return $message; +} + +sub end +{ + my $class = shift; + return $end; +} +sub success +{ + my $class = shift; + return $success; +} +sub fail +{ + my $class = shift; + return !$success && $end; +} + +sub alert +{ + return $alert; +} + +sub new +{ + my $class = shift; + my ($server, + $mt, + $data, + $records, + $startoffset, + $message_frag_lens) = @_; + + my $self = { + server => $server, + data => $data, + records => $records, + mt => $mt, + startoffset => $startoffset, + message_frag_lens => $message_frag_lens, + dupext => -1 + }; + + return bless $self, $class; +} + +sub ciphersuite +{ + my $class = shift; + if (@_) { + $ciphersuite = shift; + } + return $ciphersuite; +} + +#Update all the underlying records with the modified data from this message +#Note: Only supports re-encrypting for TLSv1.3 +sub repack +{ + my $self = shift; + my $msgdata; + + my $numrecs = $#{$self->records}; + + $self->set_message_contents(); + + my $lenhi; + my $lenlo; + + $lenlo = length($self->data) & 0xff; + $lenhi = length($self->data) >> 8; + $msgdata = pack('CnC', $self->mt, $lenhi, $lenlo).$self->data; + + if ($numrecs == 0) { + #The message is fully contained within one record + my ($rec) = @{$self->records}; + my $recdata = $rec->decrypt_data; + + my $old_length; + + # We use empty message_frag_lens to indicates that pre-repacking, + # the message wasn't present. The first fragment length doesn't include + # the TLS header, so we need to check and compute the right length. + if (@{$self->message_frag_lens}) { + $old_length = ${$self->message_frag_lens}[0] + + TLS_MESSAGE_HEADER_LENGTH; + } else { + $old_length = 0; + } + + my $prefix = substr($recdata, 0, $self->startoffset); + my $suffix = substr($recdata, $self->startoffset + $old_length); + + $rec->decrypt_data($prefix.($msgdata).($suffix)); + # TODO(openssl-team): don't keep explicit lengths. + # (If a length override is ever needed to construct invalid packets, + # use an explicit override field instead.) + $rec->decrypt_len(length($rec->decrypt_data)); + $rec->len($rec->len + length($msgdata) - $old_length); + # Only support re-encryption for TLSv1.3. + if (TLSProxy::Proxy->is_tls13() && $rec->encrypted()) { + #Add content type (1 byte) and 16 tag bytes + $rec->data($rec->decrypt_data + .pack("C", TLSProxy::Record::RT_HANDSHAKE).("\0"x16)); + } else { + $rec->data($rec->decrypt_data); + } + + #Update the fragment len in case we changed it above + ${$self->message_frag_lens}[0] = length($msgdata) + - TLS_MESSAGE_HEADER_LENGTH; + return; + } + + #Note we don't currently support changing a fragmented message length + my $recctr = 0; + my $datadone = 0; + foreach my $rec (@{$self->records}) { + my $recdata = $rec->decrypt_data; + if ($recctr == 0) { + #This is the first record + my $remainlen = length($recdata) - $self->startoffset; + $rec->data(substr($recdata, 0, $self->startoffset) + .substr(($msgdata), 0, $remainlen)); + $datadone += $remainlen; + } elsif ($recctr + 1 == $numrecs) { + #This is the last record + $rec->data(substr($msgdata, $datadone)); + } else { + #This is a middle record + $rec->data(substr($msgdata, $datadone, length($rec->data))); + $datadone += length($rec->data); + } + $recctr++; + } +} + +#To be overridden by sub-classes +sub set_message_contents +{ +} + +#Read only accessors +sub server +{ + my $self = shift; + return $self->{server}; +} + +#Read/write accessors +sub mt +{ + my $self = shift; + if (@_) { + $self->{mt} = shift; + } + return $self->{mt}; +} +sub data +{ + my $self = shift; + if (@_) { + $self->{data} = shift; + } + return $self->{data}; +} +sub records +{ + my $self = shift; + if (@_) { + $self->{records} = shift; + } + return $self->{records}; +} +sub startoffset +{ + my $self = shift; + if (@_) { + $self->{startoffset} = shift; + } + return $self->{startoffset}; +} +sub message_frag_lens +{ + my $self = shift; + if (@_) { + $self->{message_frag_lens} = shift; + } + return $self->{message_frag_lens}; +} +sub encoded_length +{ + my $self = shift; + return TLS_MESSAGE_HEADER_LENGTH + length($self->data); +} +sub dupext +{ + my $self = shift; + if (@_) { + $self->{dupext} = shift; + } + return $self->{dupext}; +} +sub successondata +{ + my $class = shift; + if (@_) { + $successondata = shift; + } + return $successondata; +} +1; diff --git a/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/NewSessionTicket.pm b/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/NewSessionTicket.pm new file mode 100644 index 000000000..e5099851d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/NewSessionTicket.pm @@ -0,0 +1,81 @@ +# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use strict; + +package TLSProxy::NewSessionTicket; + +use vars '@ISA'; +push @ISA, 'TLSProxy::Message'; + +sub new +{ + my $class = shift; + my ($server, + $data, + $records, + $startoffset, + $message_frag_lens) = @_; + + my $self = $class->SUPER::new( + $server, + TLSProxy::Message::MT_NEW_SESSION_TICKET, + $data, + $records, + $startoffset, + $message_frag_lens); + + $self->{ticket_lifetime_hint} = 0; + $self->{ticket} = ""; + + return $self; +} + +sub parse +{ + my $self = shift; + + my $ticket_lifetime_hint = unpack('N', $self->data); + my $ticket_len = unpack('n', $self->data); + my $ticket = substr($self->data, 6, $ticket_len); + + $self->ticket_lifetime_hint($ticket_lifetime_hint); + $self->ticket($ticket); +} + + +#Reconstruct the on-the-wire message data following changes +sub set_message_contents +{ + my $self = shift; + my $data; + + $data = pack('N', $self->ticket_lifetime_hint); + $data .= pack('n', length($self->ticket)); + $data .= $self->ticket; + + $self->data($data); +} + +#Read/write accessors +sub ticket_lifetime_hint +{ + my $self = shift; + if (@_) { + $self->{ticket_lifetime_hint} = shift; + } + return $self->{ticket_lifetime_hint}; +} +sub ticket +{ + my $self = shift; + if (@_) { + $self->{ticket} = shift; + } + return $self->{ticket}; +} +1; diff --git a/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/Proxy.pm b/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/Proxy.pm new file mode 100644 index 000000000..f7bca02e5 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/Proxy.pm @@ -0,0 +1,728 @@ +# Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use strict; +use POSIX ":sys_wait_h"; + +package TLSProxy::Proxy; + +use File::Spec; +use IO::Socket; +use IO::Select; +use TLSProxy::Record; +use TLSProxy::Message; +use TLSProxy::ClientHello; +use TLSProxy::ServerHello; +use TLSProxy::EncryptedExtensions; +use TLSProxy::Certificate; +use TLSProxy::CertificateVerify; +use TLSProxy::ServerKeyExchange; +use TLSProxy::NewSessionTicket; + +my $have_IPv6; +my $IP_factory; + +BEGIN +{ + # IO::Socket::IP is on the core module list, IO::Socket::INET6 isn't. + # However, IO::Socket::INET6 is older and is said to be more widely + # deployed for the moment, and may have less bugs, so we try the latter + # first, then fall back on the core modules. Worst case scenario, we + # fall back to IO::Socket::INET, only supports IPv4. + eval { + require IO::Socket::INET6; + my $s = IO::Socket::INET6->new( + LocalAddr => "::1", + LocalPort => 0, + Listen=>1, + ); + $s or die "\n"; + $s->close(); + }; + if ($@ eq "") { + $IP_factory = sub { IO::Socket::INET6->new(Domain => AF_INET6, @_); }; + $have_IPv6 = 1; + } else { + eval { + require IO::Socket::IP; + my $s = IO::Socket::IP->new( + LocalAddr => "::1", + LocalPort => 0, + Listen=>1, + ); + $s or die "\n"; + $s->close(); + }; + if ($@ eq "") { + $IP_factory = sub { IO::Socket::IP->new(@_); }; + $have_IPv6 = 1; + } else { + $IP_factory = sub { IO::Socket::INET->new(@_); }; + $have_IPv6 = 0; + } + } +} + +my $is_tls13 = 0; +my $ciphersuite = undef; + +sub new +{ + my $class = shift; + my ($filter, + $execute, + $cert, + $debug) = @_; + + my $self = { + #Public read/write + proxy_addr => $have_IPv6 ? "[::1]" : "127.0.0.1", + filter => $filter, + serverflags => "", + clientflags => "", + serverconnects => 1, + reneg => 0, + sessionfile => undef, + + #Public read + proxy_port => 0, + server_port => 0, + serverpid => 0, + clientpid => 0, + execute => $execute, + cert => $cert, + debug => $debug, + cipherc => "", + ciphersuitesc => "", + ciphers => "AES128-SHA", + ciphersuitess => "TLS_AES_128_GCM_SHA256", + flight => -1, + direction => -1, + partial => ["", ""], + record_list => [], + message_list => [], + }; + + # Create the Proxy socket + my $proxaddr = $self->{proxy_addr}; + $proxaddr =~ s/[\[\]]//g; # Remove [ and ] + my @proxyargs = ( + LocalHost => $proxaddr, + LocalPort => 0, + Proto => "tcp", + Listen => SOMAXCONN, + ); + + if (my $sock = $IP_factory->(@proxyargs)) { + $self->{proxy_sock} = $sock; + $self->{proxy_port} = $sock->sockport(); + $self->{proxy_addr} = $sock->sockhost(); + $self->{proxy_addr} =~ s/(.*:.*)/[$1]/; + print "Proxy started on port ", + "$self->{proxy_addr}:$self->{proxy_port}\n"; + # use same address for s_server + $self->{server_addr} = $self->{proxy_addr}; + } else { + warn "Failed creating proxy socket (".$proxaddr.",0): $!\n"; + } + + return bless $self, $class; +} + +sub DESTROY +{ + my $self = shift; + + $self->{proxy_sock}->close() if $self->{proxy_sock}; +} + +sub clearClient +{ + my $self = shift; + + $self->{cipherc} = ""; + $self->{ciphersuitec} = ""; + $self->{flight} = -1; + $self->{direction} = -1; + $self->{partial} = ["", ""]; + $self->{record_list} = []; + $self->{message_list} = []; + $self->{clientflags} = ""; + $self->{sessionfile} = undef; + $self->{clientpid} = 0; + $is_tls13 = 0; + $ciphersuite = undef; + + TLSProxy::Message->clear(); + TLSProxy::Record->clear(); +} + +sub clear +{ + my $self = shift; + + $self->clearClient; + $self->{ciphers} = "AES128-SHA"; + $self->{ciphersuitess} = "TLS_AES_128_GCM_SHA256"; + $self->{serverflags} = ""; + $self->{serverconnects} = 1; + $self->{serverpid} = 0; + $self->{reneg} = 0; +} + +sub restart +{ + my $self = shift; + + $self->clear; + $self->start; +} + +sub clientrestart +{ + my $self = shift; + + $self->clear; + $self->clientstart; +} + +sub connect_to_server +{ + my $self = shift; + my $servaddr = $self->{server_addr}; + + $servaddr =~ s/[\[\]]//g; # Remove [ and ] + + my $sock = $IP_factory->(PeerAddr => $servaddr, + PeerPort => $self->{server_port}, + Proto => 'tcp'); + if (!defined($sock)) { + my $err = $!; + kill(3, $self->{real_serverpid}); + die "unable to connect: $err\n"; + } + + $self->{server_sock} = $sock; +} + +sub start +{ + my ($self) = shift; + my $pid; + + if ($self->{proxy_sock} == 0) { + return 0; + } + + my $execcmd = $self->execute + ." s_server -max_protocol TLSv1.3 -no_comp -rev -engine ossltest" + #In TLSv1.3 we issue two session tickets. The default session id + #callback gets confused because the ossltest engine causes the same + #session id to be created twice due to the changed random number + #generation. Using "-ext_cache" replaces the default callback with a + #different one that doesn't get confused. + ." -ext_cache" + ." -accept $self->{server_addr}:0" + ." -cert ".$self->cert." -cert2 ".$self->cert + ." -naccept ".$self->serverconnects; + if ($self->ciphers ne "") { + $execcmd .= " -cipher ".$self->ciphers; + } + if ($self->ciphersuitess ne "") { + $execcmd .= " -ciphersuites ".$self->ciphersuitess; + } + if ($self->serverflags ne "") { + $execcmd .= " ".$self->serverflags; + } + if ($self->debug) { + print STDERR "Server command: $execcmd\n"; + } + + open(my $savedin, "<&STDIN"); + + # Temporarily replace STDIN so that sink process can inherit it... + $pid = open(STDIN, "$execcmd 2>&1 |") or die "Failed to $execcmd: $!\n"; + $self->{real_serverpid} = $pid; + + # Process the output from s_server until we find the ACCEPT line, which + # tells us what the accepting address and port are. + while (<>) { + print; + s/\R$//; # Better chomp + next unless (/^ACCEPT\s.*:(\d+)$/); + $self->{server_port} = $1; + last; + } + + if ($self->{server_port} == 0) { + # This actually means that s_server exited, because otherwise + # we would still searching for ACCEPT... + waitpid($pid, 0); + die "no ACCEPT detected in '$execcmd' output: $?\n"; + } + + # Just make sure everything else is simply printed [as separate lines]. + # The sub process simply inherits our STD* and will keep consuming + # server's output and printing it as long as there is anything there, + # out of our way. + my $error; + $pid = undef; + if (eval { require Win32::Process; 1; }) { + if (Win32::Process::Create(my $h, $^X, "perl -ne print", 0, 0, ".")) { + $pid = $h->GetProcessID(); + $self->{proc_handle} = $h; # hold handle till next round [or exit] + } else { + $error = Win32::FormatMessage(Win32::GetLastError()); + } + } else { + if (defined($pid = fork)) { + $pid or exec("$^X -ne print") or exit($!); + } else { + $error = $!; + } + } + + # Change back to original stdin + open(STDIN, "<&", $savedin); + close($savedin); + + if (!defined($pid)) { + kill(3, $self->{real_serverpid}); + die "Failed to capture s_server's output: $error\n"; + } + + $self->{serverpid} = $pid; + + print STDERR "Server responds on ", + "$self->{server_addr}:$self->{server_port}\n"; + + # Connect right away... + $self->connect_to_server(); + + return $self->clientstart; +} + +sub clientstart +{ + my ($self) = shift; + + if ($self->execute) { + my $pid; + my $execcmd = $self->execute + ." s_client -max_protocol TLSv1.3 -engine ossltest" + ." -connect $self->{proxy_addr}:$self->{proxy_port}"; + if ($self->cipherc ne "") { + $execcmd .= " -cipher ".$self->cipherc; + } + if ($self->ciphersuitesc ne "") { + $execcmd .= " -ciphersuites ".$self->ciphersuitesc; + } + if ($self->clientflags ne "") { + $execcmd .= " ".$self->clientflags; + } + if ($self->clientflags !~ m/-(no)?servername/) { + $execcmd .= " -servername localhost"; + } + if (defined $self->sessionfile) { + $execcmd .= " -ign_eof"; + } + if ($self->debug) { + print STDERR "Client command: $execcmd\n"; + } + + open(my $savedout, ">&STDOUT"); + # If we open pipe with new descriptor, attempt to close it, + # explicitly or implicitly, would incur waitpid and effectively + # dead-lock... + if (!($pid = open(STDOUT, "| $execcmd"))) { + my $err = $!; + kill(3, $self->{real_serverpid}); + die "Failed to $execcmd: $err\n"; + } + $self->{clientpid} = $pid; + + # queue [magic] input + print $self->reneg ? "R" : "test"; + + # this closes client's stdin without waiting for its pid + open(STDOUT, ">&", $savedout); + close($savedout); + } + + # Wait for incoming connection from client + my $fdset = IO::Select->new($self->{proxy_sock}); + if (!$fdset->can_read(60)) { + kill(3, $self->{real_serverpid}); + die "s_client didn't try to connect\n"; + } + + my $client_sock; + if(!($client_sock = $self->{proxy_sock}->accept())) { + warn "Failed accepting incoming connection: $!\n"; + return 0; + } + + print "Connection opened\n"; + + my $server_sock = $self->{server_sock}; + my $indata; + + #Wait for either the server socket or the client socket to become readable + $fdset = IO::Select->new($server_sock, $client_sock); + my @ready; + my $ctr = 0; + local $SIG{PIPE} = "IGNORE"; + $self->{saw_session_ticket} = undef; + while($fdset->count && $ctr < 10) { + if (defined($self->{sessionfile})) { + # s_client got -ign_eof and won't be exiting voluntarily, so we + # look for data *and* session ticket... + last if TLSProxy::Message->success() + && $self->{saw_session_ticket}; + } + if (!(@ready = $fdset->can_read(1))) { + $ctr++; + next; + } + foreach my $hand (@ready) { + if ($hand == $server_sock) { + if ($server_sock->sysread($indata, 16384)) { + if ($indata = $self->process_packet(1, $indata)) { + $client_sock->syswrite($indata) or goto END; + } + $ctr = 0; + } else { + $fdset->remove($server_sock); + $client_sock->shutdown(SHUT_WR); + } + } elsif ($hand == $client_sock) { + if ($client_sock->sysread($indata, 16384)) { + if ($indata = $self->process_packet(0, $indata)) { + $server_sock->syswrite($indata) or goto END; + } + $ctr = 0; + } else { + $fdset->remove($client_sock); + $server_sock->shutdown(SHUT_WR); + } + } else { + kill(3, $self->{real_serverpid}); + die "Unexpected handle"; + } + } + } + + if ($ctr >= 10) { + kill(3, $self->{real_serverpid}); + die "No progress made"; + } + + END: + print "Connection closed\n"; + if($server_sock) { + $server_sock->close(); + $self->{server_sock} = undef; + } + if($client_sock) { + #Closing this also kills the child process + $client_sock->close(); + } + + my $pid; + if (--$self->{serverconnects} == 0) { + $pid = $self->{serverpid}; + print "Waiting for 'perl -ne print' process to close: $pid...\n"; + $pid = waitpid($pid, 0); + if ($pid > 0) { + die "exit code $? from 'perl -ne print' process\n" if $? != 0; + } elsif ($pid == 0) { + kill(3, $self->{real_serverpid}); + die "lost control over $self->{serverpid}?"; + } + $pid = $self->{real_serverpid}; + print "Waiting for s_server process to close: $pid...\n"; + # it's done already, just collect the exit code [and reap]... + waitpid($pid, 0); + die "exit code $? from s_server process\n" if $? != 0; + } else { + # It's a bit counter-intuitive spot to make next connection to + # the s_server. Rationale is that established connection works + # as syncronization point, in sense that this way we know that + # s_server is actually done with current session... + $self->connect_to_server(); + } + $pid = $self->{clientpid}; + print "Waiting for s_client process to close: $pid...\n"; + waitpid($pid, 0); + + return 1; +} + +sub process_packet +{ + my ($self, $server, $packet) = @_; + my $len_real; + my $decrypt_len; + my $data; + my $recnum; + + if ($server) { + print "Received server packet\n"; + } else { + print "Received client packet\n"; + } + + if ($self->{direction} != $server) { + $self->{flight} = $self->{flight} + 1; + $self->{direction} = $server; + } + + print "Packet length = ".length($packet)."\n"; + print "Processing flight ".$self->flight."\n"; + + #Return contains the list of record found in the packet followed by the + #list of messages in those records and any partial message + my @ret = TLSProxy::Record->get_records($server, $self->flight, + $self->{partial}[$server].$packet); + $self->{partial}[$server] = $ret[2]; + push @{$self->{record_list}}, @{$ret[0]}; + push @{$self->{message_list}}, @{$ret[1]}; + + print "\n"; + + if (scalar(@{$ret[0]}) == 0 or length($ret[2]) != 0) { + return ""; + } + + #Finished parsing. Call user provided filter here + if (defined $self->filter) { + $self->filter->($self); + } + + #Take a note on NewSessionTicket + foreach my $message (reverse @{$self->{message_list}}) { + if ($message->{mt} == TLSProxy::Message::MT_NEW_SESSION_TICKET) { + $self->{saw_session_ticket} = 1; + last; + } + } + + #Reconstruct the packet + $packet = ""; + foreach my $record (@{$self->record_list}) { + $packet .= $record->reconstruct_record($server); + } + + print "Forwarded packet length = ".length($packet)."\n\n"; + + return $packet; +} + +#Read accessors +sub execute +{ + my $self = shift; + return $self->{execute}; +} +sub cert +{ + my $self = shift; + return $self->{cert}; +} +sub debug +{ + my $self = shift; + return $self->{debug}; +} +sub flight +{ + my $self = shift; + return $self->{flight}; +} +sub record_list +{ + my $self = shift; + return $self->{record_list}; +} +sub success +{ + my $self = shift; + return $self->{success}; +} +sub end +{ + my $self = shift; + return $self->{end}; +} +sub supports_IPv6 +{ + my $self = shift; + return $have_IPv6; +} +sub proxy_addr +{ + my $self = shift; + return $self->{proxy_addr}; +} +sub proxy_port +{ + my $self = shift; + return $self->{proxy_port}; +} +sub server_addr +{ + my $self = shift; + return $self->{server_addr}; +} +sub server_port +{ + my $self = shift; + return $self->{server_port}; +} +sub serverpid +{ + my $self = shift; + return $self->{serverpid}; +} +sub clientpid +{ + my $self = shift; + return $self->{clientpid}; +} + +#Read/write accessors +sub filter +{ + my $self = shift; + if (@_) { + $self->{filter} = shift; + } + return $self->{filter}; +} +sub cipherc +{ + my $self = shift; + if (@_) { + $self->{cipherc} = shift; + } + return $self->{cipherc}; +} +sub ciphersuitesc +{ + my $self = shift; + if (@_) { + $self->{ciphersuitesc} = shift; + } + return $self->{ciphersuitesc}; +} +sub ciphers +{ + my $self = shift; + if (@_) { + $self->{ciphers} = shift; + } + return $self->{ciphers}; +} +sub ciphersuitess +{ + my $self = shift; + if (@_) { + $self->{ciphersuitess} = shift; + } + return $self->{ciphersuitess}; +} +sub serverflags +{ + my $self = shift; + if (@_) { + $self->{serverflags} = shift; + } + return $self->{serverflags}; +} +sub clientflags +{ + my $self = shift; + if (@_) { + $self->{clientflags} = shift; + } + return $self->{clientflags}; +} +sub serverconnects +{ + my $self = shift; + if (@_) { + $self->{serverconnects} = shift; + } + return $self->{serverconnects}; +} +# This is a bit ugly because the caller is responsible for keeping the records +# in sync with the updated message list; simply updating the message list isn't +# sufficient to get the proxy to forward the new message. +# But it does the trick for the one test (test_sslsessiontick) that needs it. +sub message_list +{ + my $self = shift; + if (@_) { + $self->{message_list} = shift; + } + return $self->{message_list}; +} + +sub fill_known_data +{ + my $length = shift; + my $ret = ""; + for (my $i = 0; $i < $length; $i++) { + $ret .= chr($i); + } + return $ret; +} + +sub is_tls13 +{ + my $class = shift; + if (@_) { + $is_tls13 = shift; + } + return $is_tls13; +} + +sub reneg +{ + my $self = shift; + if (@_) { + $self->{reneg} = shift; + } + return $self->{reneg}; +} + +#Setting a sessionfile means that the client will not close until the given +#file exists. This is useful in TLSv1.3 where otherwise s_client will close +#immediately at the end of the handshake, but before the session has been +#received from the server. A side effect of this is that s_client never sends +#a close_notify, so instead we consider success to be when it sends application +#data over the connection. +sub sessionfile +{ + my $self = shift; + if (@_) { + $self->{sessionfile} = shift; + TLSProxy::Message->successondata(1); + } + return $self->{sessionfile}; +} + +sub ciphersuite +{ + my $class = shift; + if (@_) { + $ciphersuite = shift; + } + return $ciphersuite; +} + +1; diff --git a/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/Record.pm b/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/Record.pm new file mode 100644 index 000000000..841467b8e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/Record.pm @@ -0,0 +1,401 @@ +# Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use strict; + +use TLSProxy::Proxy; + +package TLSProxy::Record; + +my $server_encrypting = 0; +my $client_encrypting = 0; +my $etm = 0; + +use constant TLS_RECORD_HEADER_LENGTH => 5; + +#Record types +use constant { + RT_APPLICATION_DATA => 23, + RT_HANDSHAKE => 22, + RT_ALERT => 21, + RT_CCS => 20, + RT_UNKNOWN => 100 +}; + +my %record_type = ( + RT_APPLICATION_DATA, "APPLICATION DATA", + RT_HANDSHAKE, "HANDSHAKE", + RT_ALERT, "ALERT", + RT_CCS, "CCS", + RT_UNKNOWN, "UNKNOWN" +); + +use constant { + VERS_TLS_1_4 => 0x0305, + VERS_TLS_1_3 => 0x0304, + VERS_TLS_1_2 => 0x0303, + VERS_TLS_1_1 => 0x0302, + VERS_TLS_1_0 => 0x0301, + VERS_SSL_3_0 => 0x0300, + VERS_SSL_LT_3_0 => 0x02ff +}; + +my %tls_version = ( + VERS_TLS_1_3, "TLS1.3", + VERS_TLS_1_2, "TLS1.2", + VERS_TLS_1_1, "TLS1.1", + VERS_TLS_1_0, "TLS1.0", + VERS_SSL_3_0, "SSL3", + VERS_SSL_LT_3_0, "SSL<3" +); + +#Class method to extract records from a packet of data +sub get_records +{ + my $class = shift; + my $server = shift; + my $flight = shift; + my $packet = shift; + my $partial = ""; + my @record_list = (); + my @message_list = (); + + my $recnum = 1; + while (length ($packet) > 0) { + print " Record $recnum ", $server ? "(server -> client)\n" + : "(client -> server)\n"; + + #Get the record header (unpack can't fail if $packet is too short) + my ($content_type, $version, $len) = unpack('Cnn', $packet); + + if (length($packet) < TLS_RECORD_HEADER_LENGTH + ($len // 0)) { + print "Partial data : ".length($packet)." bytes\n"; + $partial = $packet; + last; + } + + my $data = substr($packet, TLS_RECORD_HEADER_LENGTH, $len); + + print " Content type: ".$record_type{$content_type}."\n"; + print " Version: $tls_version{$version}\n"; + print " Length: $len\n"; + + my $record = TLSProxy::Record->new( + $flight, + $content_type, + $version, + $len, + 0, + $len, # len_real + $len, # decrypt_len + $data, # data + $data # decrypt_data + ); + + if ($content_type != RT_CCS + && (!TLSProxy::Proxy->is_tls13() + || $content_type != RT_ALERT)) { + if (($server && $server_encrypting) + || (!$server && $client_encrypting)) { + if (!TLSProxy::Proxy->is_tls13() && $etm) { + $record->decryptETM(); + } else { + $record->decrypt(); + } + $record->encrypted(1); + + if (TLSProxy::Proxy->is_tls13()) { + print " Inner content type: " + .$record_type{$record->content_type()}."\n"; + } + } + } + + push @record_list, $record; + + #Now figure out what messages are contained within this record + my @messages = TLSProxy::Message->get_messages($server, $record); + push @message_list, @messages; + + $packet = substr($packet, TLS_RECORD_HEADER_LENGTH + $len); + $recnum++; + } + + return (\@record_list, \@message_list, $partial); +} + +sub clear +{ + $server_encrypting = 0; + $client_encrypting = 0; +} + +#Class level accessors +sub server_encrypting +{ + my $class = shift; + if (@_) { + $server_encrypting = shift; + } + return $server_encrypting; +} +sub client_encrypting +{ + my $class = shift; + if (@_) { + $client_encrypting= shift; + } + return $client_encrypting; +} +#Enable/Disable Encrypt-then-MAC +sub etm +{ + my $class = shift; + if (@_) { + $etm = shift; + } + return $etm; +} + +sub new +{ + my $class = shift; + my ($flight, + $content_type, + $version, + $len, + $sslv2, + $len_real, + $decrypt_len, + $data, + $decrypt_data) = @_; + + my $self = { + flight => $flight, + content_type => $content_type, + version => $version, + len => $len, + sslv2 => $sslv2, + len_real => $len_real, + decrypt_len => $decrypt_len, + data => $data, + decrypt_data => $decrypt_data, + orig_decrypt_data => $decrypt_data, + sent => 0, + encrypted => 0, + outer_content_type => RT_APPLICATION_DATA + }; + + return bless $self, $class; +} + +#Decrypt using encrypt-then-MAC +sub decryptETM +{ + my ($self) = shift; + + my $data = $self->data; + + if($self->version >= VERS_TLS_1_1()) { + #TLS1.1+ has an explicit IV. Throw it away + $data = substr($data, 16); + } + + #Throw away the MAC (assumes MAC is 20 bytes for now. FIXME) + $data = substr($data, 0, length($data) - 20); + + #Find out what the padding byte is + my $padval = unpack("C", substr($data, length($data) - 1)); + + #Throw away the padding + $data = substr($data, 0, length($data) - ($padval + 1)); + + $self->decrypt_data($data); + $self->decrypt_len(length($data)); + + return $data; +} + +#Standard decrypt +sub decrypt() +{ + my ($self) = shift; + my $mactaglen = 20; + my $data = $self->data; + + #Throw away any IVs + if (TLSProxy::Proxy->is_tls13()) { + #A TLS1.3 client, when processing the server's initial flight, could + #respond with either an encrypted or an unencrypted alert. + if ($self->content_type() == RT_ALERT) { + #TODO(TLS1.3): Eventually it is sufficient just to check the record + #content type. If an alert is encrypted it will have a record + #content type of application data. However we haven't done the + #record layer changes yet, so it's a bit more complicated. For now + #we will additionally check if the data length is 2 (1 byte for + #alert level, 1 byte for alert description). If it is, then this is + #an unencrypted alert, so don't try to decrypt + return $data if (length($data) == 2); + } + $mactaglen = 16; + } elsif ($self->version >= VERS_TLS_1_1()) { + #16 bytes for a standard IV + $data = substr($data, 16); + + #Find out what the padding byte is + my $padval = unpack("C", substr($data, length($data) - 1)); + + #Throw away the padding + $data = substr($data, 0, length($data) - ($padval + 1)); + } + + #Throw away the MAC or TAG + $data = substr($data, 0, length($data) - $mactaglen); + + if (TLSProxy::Proxy->is_tls13()) { + #Get the content type + my $content_type = unpack("C", substr($data, length($data) - 1)); + $self->content_type($content_type); + $data = substr($data, 0, length($data) - 1); + } + + $self->decrypt_data($data); + $self->decrypt_len(length($data)); + + return $data; +} + +#Reconstruct the on-the-wire record representation +sub reconstruct_record +{ + my $self = shift; + my $server = shift; + my $data; + + #We only replay the records in the same direction + if ($self->{sent} || ($self->flight & 1) != $server) { + return ""; + } + $self->{sent} = 1; + + if ($self->sslv2) { + $data = pack('n', $self->len | 0x8000); + } else { + if (TLSProxy::Proxy->is_tls13() && $self->encrypted) { + $data = pack('Cnn', $self->outer_content_type, $self->version, + $self->len); + } else { + $data = pack('Cnn', $self->content_type, $self->version, + $self->len); + } + + } + $data .= $self->data; + + return $data; +} + +#Read only accessors +sub flight +{ + my $self = shift; + return $self->{flight}; +} +sub sslv2 +{ + my $self = shift; + return $self->{sslv2}; +} +sub len_real +{ + my $self = shift; + return $self->{len_real}; +} +sub orig_decrypt_data +{ + my $self = shift; + return $self->{orig_decrypt_data}; +} + +#Read/write accessors +sub decrypt_len +{ + my $self = shift; + if (@_) { + $self->{decrypt_len} = shift; + } + return $self->{decrypt_len}; +} +sub data +{ + my $self = shift; + if (@_) { + $self->{data} = shift; + } + return $self->{data}; +} +sub decrypt_data +{ + my $self = shift; + if (@_) { + $self->{decrypt_data} = shift; + } + return $self->{decrypt_data}; +} +sub len +{ + my $self = shift; + if (@_) { + $self->{len} = shift; + } + return $self->{len}; +} +sub version +{ + my $self = shift; + if (@_) { + $self->{version} = shift; + } + return $self->{version}; +} +sub content_type +{ + my $self = shift; + if (@_) { + $self->{content_type} = shift; + } + return $self->{content_type}; +} +sub encrypted +{ + my $self = shift; + if (@_) { + $self->{encrypted} = shift; + } + return $self->{encrypted}; +} +sub outer_content_type +{ + my $self = shift; + if (@_) { + $self->{outer_content_type} = shift; + } + return $self->{outer_content_type}; +} +sub is_fatal_alert +{ + my $self = shift; + my $server = shift; + + if (($self->{flight} & 1) == $server + && $self->{content_type} == TLSProxy::Record::RT_ALERT) { + my ($level, $alert) = unpack('CC', $self->decrypt_data); + return $alert if ($level == 2); + } + return 0; +} +1; diff --git a/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/ServerHello.pm b/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/ServerHello.pm new file mode 100644 index 000000000..e9f1eca19 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/ServerHello.pm @@ -0,0 +1,236 @@ +# Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use strict; + +package TLSProxy::ServerHello; + +use vars '@ISA'; +push @ISA, 'TLSProxy::Message'; + +my $hrrrandom = pack("C*", 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, 0xBE, + 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91, 0xC2, 0xA2, + 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E, 0x07, 0x9E, 0x09, + 0xE2, 0xC8, 0xA8, 0x33, 0x9C); + +sub new +{ + my $class = shift; + my ($server, + $data, + $records, + $startoffset, + $message_frag_lens) = @_; + + my $self = $class->SUPER::new( + $server, + TLSProxy::Message::MT_SERVER_HELLO, + $data, + $records, + $startoffset, + $message_frag_lens); + + $self->{server_version} = 0; + $self->{random} = []; + $self->{session_id_len} = 0; + $self->{session} = ""; + $self->{ciphersuite} = 0; + $self->{comp_meth} = 0; + $self->{extension_data} = ""; + + return $self; +} + +sub parse +{ + my $self = shift; + my $ptr = 2; + my ($server_version) = unpack('n', $self->data); + my $neg_version = $server_version; + + my $random = substr($self->data, $ptr, 32); + $ptr += 32; + my $session_id_len = 0; + my $session = ""; + $session_id_len = unpack('C', substr($self->data, $ptr)); + $ptr++; + $session = substr($self->data, $ptr, $session_id_len); + $ptr += $session_id_len; + + my $ciphersuite = unpack('n', substr($self->data, $ptr)); + $ptr += 2; + my $comp_meth = 0; + $comp_meth = unpack('C', substr($self->data, $ptr)); + $ptr++; + + my $extensions_len = unpack('n', substr($self->data, $ptr)); + if (!defined $extensions_len) { + $extensions_len = 0; + } else { + $ptr += 2; + } + #For now we just deal with this as a block of data. In the future we will + #want to parse this + my $extension_data; + if ($extensions_len != 0) { + $extension_data = substr($self->data, $ptr); + + if (length($extension_data) != $extensions_len) { + die "Invalid extension length\n"; + } + } else { + if (length($self->data) != $ptr) { + die "Invalid extension length\n"; + } + $extension_data = ""; + } + my %extensions = (); + while (length($extension_data) >= 4) { + my ($type, $size) = unpack("nn", $extension_data); + my $extdata = substr($extension_data, 4, $size); + $extension_data = substr($extension_data, 4 + $size); + $extensions{$type} = $extdata; + if ($type == TLSProxy::Message::EXT_SUPPORTED_VERSIONS) { + $neg_version = unpack('n', $extdata); + } + } + + if ($random eq $hrrrandom) { + TLSProxy::Proxy->is_tls13(1); + } elsif ($neg_version == TLSProxy::Record::VERS_TLS_1_3) { + TLSProxy::Proxy->is_tls13(1); + + TLSProxy::Record->server_encrypting(1); + TLSProxy::Record->client_encrypting(1); + } + + $self->server_version($server_version); + $self->random($random); + $self->session_id_len($session_id_len); + $self->session($session); + $self->ciphersuite($ciphersuite); + TLSProxy::Proxy->ciphersuite($ciphersuite); + $self->comp_meth($comp_meth); + $self->extension_data(\%extensions); + + $self->process_data(); + + + print " Server Version:".$server_version."\n"; + print " Session ID Len:".$session_id_len."\n"; + print " Ciphersuite:".$ciphersuite."\n"; + print " Compression Method:".$comp_meth."\n"; + print " Extensions Len:".$extensions_len."\n"; +} + +#Perform any actions necessary based on the data we've seen +sub process_data +{ + my $self = shift; + + TLSProxy::Message->ciphersuite($self->ciphersuite); +} + +#Reconstruct the on-the-wire message data following changes +sub set_message_contents +{ + my $self = shift; + my $data; + my $extensions = ""; + + $data = pack('n', $self->server_version); + $data .= $self->random; + $data .= pack('C', $self->session_id_len); + $data .= $self->session; + $data .= pack('n', $self->ciphersuite); + $data .= pack('C', $self->comp_meth); + + foreach my $key (keys %{$self->extension_data}) { + my $extdata = ${$self->extension_data}{$key}; + $extensions .= pack("n", $key); + $extensions .= pack("n", length($extdata)); + $extensions .= $extdata; + if ($key == $self->dupext) { + $extensions .= pack("n", $key); + $extensions .= pack("n", length($extdata)); + $extensions .= $extdata; + } + } + + $data .= pack('n', length($extensions)); + $data .= $extensions; + $self->data($data); +} + +#Read/write accessors +sub server_version +{ + my $self = shift; + if (@_) { + $self->{server_version} = shift; + } + return $self->{server_version}; +} +sub random +{ + my $self = shift; + if (@_) { + $self->{random} = shift; + } + return $self->{random}; +} +sub session_id_len +{ + my $self = shift; + if (@_) { + $self->{session_id_len} = shift; + } + return $self->{session_id_len}; +} +sub session +{ + my $self = shift; + if (@_) { + $self->{session} = shift; + } + return $self->{session}; +} +sub ciphersuite +{ + my $self = shift; + if (@_) { + $self->{ciphersuite} = shift; + } + return $self->{ciphersuite}; +} +sub comp_meth +{ + my $self = shift; + if (@_) { + $self->{comp_meth} = shift; + } + return $self->{comp_meth}; +} +sub extension_data +{ + my $self = shift; + if (@_) { + $self->{extension_data} = shift; + } + return $self->{extension_data}; +} +sub set_extension +{ + my ($self, $ext_type, $ext_data) = @_; + $self->{extension_data}{$ext_type} = $ext_data; +} +sub delete_extension +{ + my ($self, $ext_type) = @_; + delete $self->{extension_data}{$ext_type}; +} +1; diff --git a/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/ServerKeyExchange.pm b/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/ServerKeyExchange.pm new file mode 100644 index 000000000..e0086e2be --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/perl/TLSProxy/ServerKeyExchange.pm @@ -0,0 +1,157 @@ +# Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use strict; + +package TLSProxy::ServerKeyExchange; + +use vars '@ISA'; +push @ISA, 'TLSProxy::Message'; + +sub new +{ + my $class = shift; + my ($server, + $data, + $records, + $startoffset, + $message_frag_lens) = @_; + + my $self = $class->SUPER::new( + $server, + TLSProxy::Message::MT_SERVER_KEY_EXCHANGE, + $data, + $records, + $startoffset, + $message_frag_lens); + + #DHE + $self->{p} = ""; + $self->{g} = ""; + $self->{pub_key} = ""; + $self->{sigalg} = -1; + $self->{sig} = ""; + + return $self; +} + +sub parse +{ + my $self = shift; + my $sigalg = -1; + + #Minimal SKE parsing. Only supports one known DHE ciphersuite at the moment + return if TLSProxy::Proxy->ciphersuite() + != TLSProxy::Message::CIPHER_ADH_AES_128_SHA + && TLSProxy::Proxy->ciphersuite() + != TLSProxy::Message::CIPHER_DHE_RSA_AES_128_SHA; + + my $p_len = unpack('n', $self->data); + my $ptr = 2; + my $p = substr($self->data, $ptr, $p_len); + $ptr += $p_len; + + my $g_len = unpack('n', substr($self->data, $ptr)); + $ptr += 2; + my $g = substr($self->data, $ptr, $g_len); + $ptr += $g_len; + + my $pub_key_len = unpack('n', substr($self->data, $ptr)); + $ptr += 2; + my $pub_key = substr($self->data, $ptr, $pub_key_len); + $ptr += $pub_key_len; + + #We assume its signed + my $record = ${$self->records}[0]; + + if (TLSProxy::Proxy->is_tls13() + || $record->version() == TLSProxy::Record::VERS_TLS_1_2) { + $sigalg = unpack('n', substr($self->data, $ptr)); + $ptr += 2; + } + my $sig = ""; + if (defined $sigalg) { + my $sig_len = unpack('n', substr($self->data, $ptr)); + if (defined $sig_len) { + $ptr += 2; + $sig = substr($self->data, $ptr, $sig_len); + $ptr += $sig_len; + } + } + + $self->p($p); + $self->g($g); + $self->pub_key($pub_key); + $self->sigalg($sigalg) if defined $sigalg; + $self->signature($sig); +} + + +#Reconstruct the on-the-wire message data following changes +sub set_message_contents +{ + my $self = shift; + my $data; + + $data = pack('n', length($self->p)); + $data .= $self->p; + $data .= pack('n', length($self->g)); + $data .= $self->g; + $data .= pack('n', length($self->pub_key)); + $data .= $self->pub_key; + $data .= pack('n', $self->sigalg) if ($self->sigalg != -1); + if (length($self->signature) > 0) { + $data .= pack('n', length($self->signature)); + $data .= $self->signature; + } + + $self->data($data); +} + +#Read/write accessors +#DHE +sub p +{ + my $self = shift; + if (@_) { + $self->{p} = shift; + } + return $self->{p}; +} +sub g +{ + my $self = shift; + if (@_) { + $self->{g} = shift; + } + return $self->{g}; +} +sub pub_key +{ + my $self = shift; + if (@_) { + $self->{pub_key} = shift; + } + return $self->{pub_key}; +} +sub sigalg +{ + my $self = shift; + if (@_) { + $self->{sigalg} = shift; + } + return $self->{sigalg}; +} +sub signature +{ + my $self = shift; + if (@_) { + $self->{sig} = shift; + } + return $self->{sig}; +} +1; diff --git a/trunk/3rdparty/openssl-1.1-fit/util/perl/checkhandshake.pm b/trunk/3rdparty/openssl-1.1-fit/util/perl/checkhandshake.pm new file mode 100644 index 000000000..c53b96d5e --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/perl/checkhandshake.pm @@ -0,0 +1,228 @@ +#! /usr/bin/env perl +# Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +package checkhandshake; + +use OpenSSL::Test qw/:DEFAULT cmdstr srctop_file srctop_dir bldtop_dir/; +use OpenSSL::Test::Utils; +use TLSProxy::Proxy; + +use Exporter; +our @ISA = 'Exporter'; +our @EXPORT = qw(@handmessages @extensions checkhandshake); + +use constant { + DEFAULT_HANDSHAKE => 1, + OCSP_HANDSHAKE => 2, + RESUME_HANDSHAKE => 4, + CLIENT_AUTH_HANDSHAKE => 8, + RENEG_HANDSHAKE => 16, + NPN_HANDSHAKE => 32, + EC_HANDSHAKE => 64, + HRR_HANDSHAKE => 128, + HRR_RESUME_HANDSHAKE => 256, + + ALL_HANDSHAKES => 511 +}; + +use constant { + #DEFAULT also includes SESSION_TICKET_SRV_EXTENSION and SERVER_NAME_CLI + DEFAULT_EXTENSIONS => 0x00000007, + SESSION_TICKET_SRV_EXTENSION => 0x00000002, + SERVER_NAME_CLI_EXTENSION => 0x00000004, + SERVER_NAME_SRV_EXTENSION => 0x00000008, + STATUS_REQUEST_CLI_EXTENSION => 0x00000010, + STATUS_REQUEST_SRV_EXTENSION => 0x00000020, + ALPN_CLI_EXTENSION => 0x00000040, + ALPN_SRV_EXTENSION => 0x00000080, + SCT_CLI_EXTENSION => 0x00000100, + SCT_SRV_EXTENSION => 0x00000200, + RENEGOTIATE_CLI_EXTENSION => 0x00000400, + NPN_CLI_EXTENSION => 0x00000800, + NPN_SRV_EXTENSION => 0x00001000, + SRP_CLI_EXTENSION => 0x00002000, + #Client side for ec point formats is a default extension + EC_POINT_FORMAT_SRV_EXTENSION => 0x00004000, + PSK_CLI_EXTENSION => 0x00008000, + PSK_SRV_EXTENSION => 0x00010000, + KEY_SHARE_SRV_EXTENSION => 0x00020000, + PSK_KEX_MODES_EXTENSION => 0x00040000, + KEY_SHARE_HRR_EXTENSION => 0x00080000, + SUPPORTED_GROUPS_SRV_EXTENSION => 0x00100000, + POST_HANDSHAKE_AUTH_CLI_EXTENSION => 0x00200000 +}; + +our @handmessages = (); +our @extensions = (); + +sub checkhandshake($$$$) +{ + my ($proxy, $handtype, $exttype, $testname) = @_; + + subtest $testname => sub { + my $loop = 0; + my $numtests; + my $extcount; + my $clienthelloseen = 0; + + my $lastmt = 0; + my $numsh = 0; + if (TLSProxy::Proxy::is_tls13()) { + #How many ServerHellos are we expecting? + for ($numtests = 0; $handmessages[$loop][1] != 0; $loop++) { + next if (($handmessages[$loop][1] & $handtype) == 0); + $numsh++ if ($lastmt != TLSProxy::Message::MT_SERVER_HELLO + && $handmessages[$loop][0] == TLSProxy::Message::MT_SERVER_HELLO); + $lastmt = $handmessages[$loop][0]; + } + } + + #First count the number of tests + my $nextmess = 0; + my $message = undef; + my $chnum = 0; + my $shnum = 0; + if (!TLSProxy::Proxy::is_tls13()) { + # In non-TLSv1.3 we always treat reneg CH and SH like the first CH + # and SH + $chnum = 1; + $shnum = 1; + } + #If we're only expecting one ServerHello out of two then we skip the + #first ServerHello in the list completely + $shnum++ if ($numsh == 1 && TLSProxy::Proxy::is_tls13()); + $loop = 0; + for ($numtests = 0; $handmessages[$loop][1] != 0; $loop++) { + next if (($handmessages[$loop][1] & $handtype) == 0); + if (scalar @{$proxy->message_list} > $nextmess) { + $message = ${$proxy->message_list}[$nextmess]; + $nextmess++; + } else { + $message = undef; + } + $numtests++; + + next if (!defined $message); + if (TLSProxy::Proxy::is_tls13()) { + $chnum++ if $message->mt() == TLSProxy::Message::MT_CLIENT_HELLO; + $shnum++ if $message->mt() == TLSProxy::Message::MT_SERVER_HELLO; + } + next if ($message->mt() != TLSProxy::Message::MT_CLIENT_HELLO + && $message->mt() != TLSProxy::Message::MT_SERVER_HELLO + && $message->mt() != + TLSProxy::Message::MT_ENCRYPTED_EXTENSIONS + && $message->mt() != TLSProxy::Message::MT_CERTIFICATE); + + next if $message->mt() == TLSProxy::Message::MT_CERTIFICATE + && !TLSProxy::Proxy::is_tls13(); + + my $extchnum = 1; + my $extshnum = 1; + for (my $extloop = 0; + $extensions[$extloop][2] != 0; + $extloop++) { + $extchnum = 2 if $extensions[$extloop][0] != TLSProxy::Message::MT_CLIENT_HELLO + && TLSProxy::Proxy::is_tls13(); + $extshnum = 2 if $extensions[$extloop][0] != TLSProxy::Message::MT_SERVER_HELLO + && $extchnum == 2; + next if $extensions[$extloop][0] == TLSProxy::Message::MT_CLIENT_HELLO + && $extchnum != $chnum; + next if $extensions[$extloop][0] == TLSProxy::Message::MT_SERVER_HELLO + && $extshnum != $shnum; + next if ($message->mt() != $extensions[$extloop][0]); + $numtests++; + } + $numtests++; + } + + plan tests => $numtests; + + $nextmess = 0; + $message = undef; + if (TLSProxy::Proxy::is_tls13()) { + $chnum = 0; + $shnum = 0; + } else { + # In non-TLSv1.3 we always treat reneg CH and SH like the first CH + # and SH + $chnum = 1; + $shnum = 1; + } + #If we're only expecting one ServerHello out of two then we skip the + #first ServerHello in the list completely + $shnum++ if ($numsh == 1 && TLSProxy::Proxy::is_tls13()); + for ($loop = 0; $handmessages[$loop][1] != 0; $loop++) { + next if (($handmessages[$loop][1] & $handtype) == 0); + if (scalar @{$proxy->message_list} > $nextmess) { + $message = ${$proxy->message_list}[$nextmess]; + $nextmess++; + } else { + $message = undef; + } + if (!defined $message) { + fail("Message type check. Got nothing, expected " + .$handmessages[$loop][0]); + next; + } else { + ok($message->mt == $handmessages[$loop][0], + "Message type check. Got ".$message->mt + .", expected ".$handmessages[$loop][0]); + } + if (TLSProxy::Proxy::is_tls13()) { + $chnum++ if $message->mt() == TLSProxy::Message::MT_CLIENT_HELLO; + $shnum++ if $message->mt() == TLSProxy::Message::MT_SERVER_HELLO; + } + + next if ($message->mt() != TLSProxy::Message::MT_CLIENT_HELLO + && $message->mt() != TLSProxy::Message::MT_SERVER_HELLO + && $message->mt() != + TLSProxy::Message::MT_ENCRYPTED_EXTENSIONS + && $message->mt() != TLSProxy::Message::MT_CERTIFICATE); + + next if $message->mt() == TLSProxy::Message::MT_CERTIFICATE + && !TLSProxy::Proxy::is_tls13(); + + if ($message->mt() == TLSProxy::Message::MT_CLIENT_HELLO) { + #Add renegotiate extension we will expect if renegotiating + $exttype |= RENEGOTIATE_CLI_EXTENSION + if ($clienthelloseen && !TLSProxy::Proxy::is_tls13()); + $clienthelloseen = 1; + } + #Now check that we saw the extensions we expected + my $msgexts = $message->extension_data(); + my $extchnum = 1; + my $extshnum = 1; + for (my $extloop = 0, $extcount = 0; $extensions[$extloop][2] != 0; + $extloop++) { + #In TLSv1.3 we can have two ClientHellos if there has been a + #HelloRetryRequest, and they may have different extensions. Skip + #if these are extensions for a different ClientHello + $extchnum = 2 if $extensions[$extloop][0] != TLSProxy::Message::MT_CLIENT_HELLO + && TLSProxy::Proxy::is_tls13(); + $extshnum = 2 if $extensions[$extloop][0] != TLSProxy::Message::MT_SERVER_HELLO + && $extchnum == 2; + next if $extensions[$extloop][0] == TLSProxy::Message::MT_CLIENT_HELLO + && $extchnum != $chnum; + next if $extensions[$extloop][0] == TLSProxy::Message::MT_SERVER_HELLO + && $extshnum != $shnum; + next if ($message->mt() != $extensions[$extloop][0]); + ok (($extensions[$extloop][2] & $exttype) == 0 + || defined ($msgexts->{$extensions[$extloop][1]}), + "Extension presence check (Message: ".$message->mt() + ." Extension: ".($extensions[$extloop][2] & $exttype).", " + .$extloop.")"); + $extcount++ if (($extensions[$extloop][2] & $exttype) != 0); + } + ok($extcount == keys %$msgexts, "Extensions count mismatch (" + .$extcount.", ".(keys %$msgexts) + .")"); + } + } +} + +1; diff --git a/trunk/3rdparty/openssl-1.1-fit/util/perl/with_fallback.pm b/trunk/3rdparty/openssl-1.1-fit/util/perl/with_fallback.pm new file mode 100644 index 000000000..242365033 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/perl/with_fallback.pm @@ -0,0 +1,27 @@ +# Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +package with_fallback; + +sub import { + shift; + + use File::Basename; + use File::Spec::Functions; + foreach (@_) { + eval "use $_"; + if ($@) { + unshift @INC, catdir(dirname(__FILE__), + "..", "..", "external", "perl"); + my $transfer = "transfer::$_"; + eval "use $transfer"; + shift @INC; + warn $@ if $@; + } + } +} +1; diff --git a/trunk/3rdparty/openssl-1.1-fit/util/private.num b/trunk/3rdparty/openssl-1.1-fit/util/private.num new file mode 100644 index 000000000..a6ef44e4a --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/private.num @@ -0,0 +1,457 @@ +# This isn't a library ".num" file but is a list of documented items +# that don't appear in lib*.num -- because they are define's, in +# assembly language, etc. +# +OPENSSL_ia32cap environment +OPENSSL_MALLOC_FD environment +OPENSSL_MALLOC_FAILURES environment +OPENSSL_instrument_bus assembler +OPENSSL_instrument_bus2 assembler +# +ADMISSION_SYNTAX datatype +ADMISSIONS datatype +ASN1_STRING_TABLE datatype +BIO_ADDR datatype +BIO_ADDRINFO datatype +BIO_callback_fn datatype +BIO_callback_fn_ex datatype +BIO_hostserv_priorities datatype +BIO_lookup_type datatype +CRYPTO_EX_dup datatype +CRYPTO_EX_free datatype +CRYPTO_EX_new datatype +DTLS_timer_cb datatype +EVP_PKEY_gen_cb datatype +EVP_PKEY_METHOD datatype +EVP_PKEY_ASN1_METHOD datatype +GEN_SESSION_CB datatype +OPENSSL_Applink external +NAMING_AUTHORITY datatype +OSSL_STORE_CTX datatype +OSSL_STORE_INFO datatype +OSSL_STORE_LOADER datatype +OSSL_STORE_LOADER_CTX datatype +OSSL_STORE_SEARCH datatype +OSSL_STORE_close_fn datatype +OSSL_STORE_ctrl_fn datatype +OSSL_STORE_expect_fn datatype +OSSL_STORE_find_fn datatype +OSSL_STORE_eof_fn datatype +OSSL_STORE_error_fn datatype +OSSL_STORE_load_fn datatype +OSSL_STORE_open_fn datatype +OSSL_STORE_post_process_info_fn datatype +PROFESSION_INFO datatype +PROFESSION_INFOS datatype +RAND_DRBG_cleanup_entropy_fn datatype +RAND_DRBG_cleanup_nonce_fn datatype +RAND_DRBG_get_entropy_fn datatype +RAND_DRBG_get_nonce_fn datatype +RAND_poll_cb datatype +SSL_CTX_allow_early_data_cb_fn datatype +SSL_CTX_keylog_cb_func datatype +SSL_allow_early_data_cb_fn datatype +SSL_client_hello_cb_fn datatype +SSL_psk_client_cb_func datatype +SSL_psk_find_session_cb_func datatype +SSL_psk_server_cb_func datatype +SSL_psk_use_session_cb_func datatype +SSL_verify_cb datatype +UI datatype +UI_METHOD datatype +UI_STRING datatype +UI_string_types datatype +UI_string_types datatype +X509_STORE_CTX_cert_crl_fn datatype +X509_STORE_CTX_check_crl_fn datatype +X509_STORE_CTX_check_issued_fn datatype +X509_STORE_CTX_check_policy_fn datatype +X509_STORE_CTX_check_revocation_fn datatype +X509_STORE_CTX_cleanup_fn datatype +X509_STORE_CTX_get_crl_fn datatype +X509_STORE_CTX_get_issuer_fn datatype +X509_STORE_CTX_lookup_certs_fn datatype +X509_STORE_CTX_lookup_crls_fn datatype +X509_STORE_CTX_verify_cb datatype +X509_STORE_CTX_verify_fn datatype +X509_STORE_set_verify_cb_func datatype +X509_LOOKUP_get_by_alias_fn datatype +X509_LOOKUP_get_by_subject_fn datatype +X509_LOOKUP_get_by_fingerprint_fn datatype +X509_LOOKUP_ctrl_fn datatype +X509_LOOKUP_get_by_issuer_serial_fn datatype +bio_info_cb datatype +BIO_info_cb datatype +custom_ext_add_cb datatype +custom_ext_free_cb datatype +custom_ext_parse_cb datatype +pem_password_cb datatype +ssl_ct_validation_cb datatype +# +BIO_append_filename define +BIO_destroy_bio_pair define +BIO_do_accept define +BIO_do_connect define +BIO_do_handshake define +BIO_eof define +BIO_flush define +BIO_get_accept_name define +BIO_get_accept_port define +BIO_get_accept_ip_family define +BIO_get_peer_name define +BIO_get_peer_port define +BIO_get_bind_mode define +BIO_get_buffer_num_lines define +BIO_get_cipher_ctx define +BIO_get_cipher_status define +BIO_get_close define +BIO_get_conn_address define +BIO_get_conn_hostname define +BIO_get_conn_port define +BIO_get_conn_ip_family define +BIO_get_fd define +BIO_get_fp define +BIO_get_info_callback define +BIO_get_md define +BIO_get_md_ctx define +BIO_get_mem_data define +BIO_get_mem_ptr define +BIO_get_num_renegotiates define +BIO_get_read_request define +BIO_get_ssl define +BIO_get_write_buf_size define +BIO_get_write_guarantee define +BIO_make_bio_pair define +BIO_pending define +BIO_read_filename define +BIO_reset define +BIO_retry_type define +BIO_rw_filename define +BIO_seek define +BIO_set_accept_bios define +BIO_set_accept_name define +BIO_set_accept_port define +BIO_set_accept_ip_family define +BIO_set_bind_mode define +BIO_set_buffer_read_data define +BIO_set_buffer_size define +BIO_set_close define +BIO_set_conn_address define +BIO_set_conn_hostname define +BIO_set_conn_port define +BIO_set_conn_ip_family define +BIO_set_fd define +BIO_set_fp define +BIO_set_info_callback define +BIO_set_md define +BIO_set_mem_buf define +BIO_set_mem_eof_return define +BIO_set_nbio define +BIO_set_nbio_accept define +BIO_set_read_buffer_size define +BIO_set_ssl define +BIO_set_ssl_mode define +BIO_set_ssl_renegotiate_bytes define +BIO_set_ssl_renegotiate_timeout define +BIO_set_write_buf_size define +BIO_set_write_buffer_size define +BIO_should_io_special define +BIO_should_read define +BIO_should_retry define +BIO_should_write define +BIO_shutdown_wr define +BIO_tell define +BIO_wpending define +BIO_write_filename define +BN_mod define +BN_num_bytes define +BN_one define +BN_zero define deprecated 0.9.8 +CONF_modules_free define deprecated 1.1.0 +DES_ecb2_encrypt define +DES_ede2_cbc_encrypt define +DES_ede2_cfb64_encrypt define +DES_ede2_ofb64_encrypt define +DTLS_get_link_min_mtu define +DTLS_set_link_mtu define +ENGINE_cleanup define deprecated 1.1.0 +ERR_FATAL_ERROR define +ERR_GET_FUNC define +ERR_GET_LIB define +ERR_GET_REASON define +ERR_PACK define +ERR_free_strings define deprecated 1.1.0 +ERR_load_crypto_strings define deprecated 1.1.0 +EVP_DigestSignUpdate define +EVP_DigestVerifyUpdate define +EVP_MD_CTX_block_size define +EVP_MD_CTX_size define +EVP_MD_CTX_type define +EVP_OpenUpdate define +EVP_PKEY_CTX_add1_hkdf_info define +EVP_PKEY_CTX_add1_tls1_prf_seed define +EVP_PKEY_CTX_get0_dh_kdf_oid define +EVP_PKEY_CTX_get0_dh_kdf_ukm define +EVP_PKEY_CTX_get0_ecdh_kdf_ukm define +EVP_PKEY_CTX_get0_rsa_oaep_label define +EVP_PKEY_CTX_get_dh_kdf_md define +EVP_PKEY_CTX_get_dh_kdf_outlen define +EVP_PKEY_CTX_get_dh_kdf_type define +EVP_PKEY_CTX_get_ecdh_cofactor_mode define +EVP_PKEY_CTX_get_ecdh_kdf_md define +EVP_PKEY_CTX_get_ecdh_kdf_outlen define +EVP_PKEY_CTX_get_ecdh_kdf_type define +EVP_PKEY_CTX_get_rsa_mgf1_md define +EVP_PKEY_CTX_get_rsa_oaep_md define +EVP_PKEY_CTX_get_rsa_padding define +EVP_PKEY_CTX_get_rsa_pss_saltlen define +EVP_PKEY_CTX_get_signature_md define +EVP_PKEY_CTX_hkdf_mode define +EVP_PKEY_CTX_set0_dh_kdf_oid define +EVP_PKEY_CTX_set0_dh_kdf_ukm define +EVP_PKEY_CTX_set0_ecdh_kdf_ukm define +EVP_PKEY_CTX_set0_rsa_oaep_label define +EVP_PKEY_CTX_set1_hkdf_key define +EVP_PKEY_CTX_set1_hkdf_salt define +EVP_PKEY_CTX_set1_pbe_pass define +EVP_PKEY_CTX_set1_scrypt_salt define +EVP_PKEY_CTX_set1_tls1_prf_secret define +EVP_PKEY_CTX_set_dh_paramgen_generator define +EVP_PKEY_CTX_set_dh_paramgen_prime_len define +EVP_PKEY_CTX_set_dh_paramgen_subprime_len define +EVP_PKEY_CTX_set_dh_paramgen_type define +EVP_PKEY_CTX_set_dh_kdf_md define +EVP_PKEY_CTX_set_dh_kdf_outlen define +EVP_PKEY_CTX_set_dh_kdf_type define +EVP_PKEY_CTX_set_dh_nid define +EVP_PKEY_CTX_set_dh_pad define +EVP_PKEY_CTX_set_dh_rfc5114 define +EVP_PKEY_CTX_set_dhx_rfc5114 define +EVP_PKEY_CTX_set_dsa_paramgen_bits define +EVP_PKEY_CTX_set_ec_param_enc define +EVP_PKEY_CTX_set_ec_paramgen_curve_nid define +EVP_PKEY_CTX_set_ecdh_cofactor_mode define +EVP_PKEY_CTX_set_ecdh_kdf_md define +EVP_PKEY_CTX_set_ecdh_kdf_outlen define +EVP_PKEY_CTX_set_ecdh_kdf_type define +EVP_PKEY_CTX_set_hkdf_md define +EVP_PKEY_CTX_set_mac_key define +EVP_PKEY_CTX_set_rsa_keygen_bits define +EVP_PKEY_CTX_set_rsa_keygen_pubexp define +EVP_PKEY_CTX_set_rsa_keygen_primes define +EVP_PKEY_CTX_set_rsa_mgf1_md define +EVP_PKEY_CTX_set_rsa_oaep_md define +EVP_PKEY_CTX_set_rsa_padding define +EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md define +EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen define +EVP_PKEY_CTX_set_rsa_pss_keygen_md define +EVP_PKEY_CTX_set_rsa_pss_saltlen define +EVP_PKEY_CTX_set_scrypt_N define +EVP_PKEY_CTX_set_scrypt_r define +EVP_PKEY_CTX_set_scrypt_maxmem_bytes define +EVP_PKEY_CTX_set_scrypt_p define +EVP_PKEY_CTX_set_signature_md define +EVP_PKEY_CTX_set_tls1_prf_md define +EVP_PKEY_assign_DH define +EVP_PKEY_assign_DSA define +EVP_PKEY_assign_EC_KEY define +EVP_PKEY_assign_POLY1305 define +EVP_PKEY_assign_RSA define +EVP_PKEY_assign_SIPHASH define +EVP_SealUpdate define +EVP_SignInit define +EVP_SignInit_ex define +EVP_SignUpdate define +EVP_VerifyInit define +EVP_VerifyInit_ex define +EVP_VerifyUpdate define +EVP_bf_cfb define +EVP_cast5_cfb define +EVP_cleanup define deprecated 1.1.0 +EVP_get_digestbynid define +EVP_get_digestbyobj define +EVP_idea_cfb define +EVP_rc2_cfb define +EVP_rc5_32_12_16_cfb define +EVP_seed_cfb define +EVP_sm4_cfb define +OBJ_cleanup define deprecated 1.1.0 +OPENSSL_VERSION_NUMBER define +OPENSSL_VERSION_TEXT define +OPENSSL_clear_free define +OPENSSL_clear_realloc define +OPENSSL_free define +OPENSSL_malloc define +OPENSSL_malloc_init define +OPENSSL_mem_debug_pop define +OPENSSL_mem_debug_push define +OPENSSL_memdup define +OPENSSL_no_config define deprecated 1.1.0 +OPENSSL_realloc define +OPENSSL_secure_actual_size define +OPENSSL_secure_clear_free define +OPENSSL_secure_free define +OPENSSL_secure_malloc define +OPENSSL_secure_zalloc define +OPENSSL_strdup define +OPENSSL_strndup define +OPENSSL_zalloc define +OpenSSL_add_all_algorithms define deprecated 1.1.0 +OpenSSL_add_all_ciphers define deprecated 1.1.0 +OpenSSL_add_all_digests define deprecated 1.1.0 +OpenSSL_add_ssl_algorithms define +PEM_FLAG_EAY_COMPATIBLE define +PEM_FLAG_ONLY_B64 define +PEM_FLAG_SECURE define +RAND_cleanup define deprecated 1.1.0 +RAND_DRBG_get_ex_new_index define +SSL_COMP_free_compression_methods define deprecated 1.1.0 +SSL_CTX_add0_chain_cert define +SSL_CTX_add1_chain_cert define +SSL_CTX_add_extra_chain_cert define +SSL_CTX_build_cert_chain define +SSL_CTX_clear_chain_certs define +SSL_CTX_clear_extra_chain_certs define +SSL_CTX_clear_mode define +SSL_CTX_decrypt_session_ticket_fn define +SSL_CTX_disable_ct define +SSL_CTX_generate_session_ticket_fn define +SSL_CTX_get0_chain_certs define +SSL_CTX_get_default_read_ahead define +SSL_CTX_get_max_cert_list define +SSL_CTX_get_max_proto_version define +SSL_CTX_get_min_proto_version define +SSL_CTX_get_mode define +SSL_CTX_get_read_ahead define +SSL_CTX_get_session_cache_mode define +SSL_CTX_get_tlsext_status_arg define +SSL_CTX_get_tlsext_status_cb define +SSL_CTX_get_tlsext_status_type define +SSL_CTX_select_current_cert define +SSL_CTX_sess_accept define +SSL_CTX_sess_accept_good define +SSL_CTX_sess_accept_renegotiate define +SSL_CTX_sess_cache_full define +SSL_CTX_sess_cb_hits define +SSL_CTX_sess_connect define +SSL_CTX_sess_connect_good define +SSL_CTX_sess_connect_renegotiate define +SSL_CTX_sess_get_cache_size define +SSL_CTX_sess_hits define +SSL_CTX_sess_misses define +SSL_CTX_sess_number define +SSL_CTX_sess_set_cache_size define +SSL_CTX_sess_timeouts define +SSL_CTX_set0_chain define +SSL_CTX_set0_chain_cert_store define +SSL_CTX_set0_verify_cert_store define +SSL_CTX_set1_chain define +SSL_CTX_set1_chain_cert_store define +SSL_CTX_set1_client_sigalgs define +SSL_CTX_set1_client_sigalgs_list define +SSL_CTX_set1_curves define +SSL_CTX_set1_curves_list define +SSL_CTX_set1_groups define +SSL_CTX_set1_groups_list define +SSL_CTX_set1_sigalgs define +SSL_CTX_set1_sigalgs_list define +SSL_CTX_set1_verify_cert_store define +SSL_CTX_set_current_cert define +SSL_CTX_set_max_cert_list define +SSL_CTX_set_max_pipelines define +SSL_CTX_set_max_proto_version define +SSL_CTX_set_max_send_fragment define +SSL_CTX_set_min_proto_version define +SSL_CTX_set_mode define +SSL_CTX_set_msg_callback_arg define +SSL_CTX_set_read_ahead define +SSL_CTX_set_session_cache_mode define +SSL_CTX_set_split_send_fragment define +SSL_CTX_set_tlsext_servername_arg define +SSL_CTX_set_tlsext_servername_callback define +SSL_CTX_set_tlsext_status_arg define +SSL_CTX_set_tlsext_status_cb define +SSL_CTX_set_tlsext_status_type define +SSL_CTX_set_tlsext_ticket_key_cb define +SSL_CTX_set_tmp_dh define +SSL_add0_chain_cert define +SSL_add1_chain_cert define +SSL_build_cert_chain define +SSL_clear_chain_certs define +SSL_clear_mode define +SSL_disable_ct define +SSL_get0_chain_certs define +SSL_get0_session define +SSL_get1_curves define +SSL_get1_groups define +SSL_get_cipher define +SSL_get_cipher_bits define +SSL_get_cipher_name define +SSL_get_cipher_version define +SSL_get_extms_support define +SSL_get_max_cert_list define +SSL_get_max_proto_version define +SSL_get_min_proto_version define +SSL_get_mode define +SSL_get_peer_signature_nid define +SSL_get_peer_tmp_key define +SSL_get_secure_renegotiation_support define +SSL_get_server_tmp_key define +SSL_get_shared_curve define +SSL_get_shared_group define +SSL_get_signature_nid define +SSL_get_time define +SSL_get_timeout define +SSL_get_tlsext_status_ocsp_resp define +SSL_get_tlsext_status_type define +SSL_get_tmp_key define +SSL_in_accept_init define +SSL_in_connect_init define +SSL_library_init define +SSL_load_error_strings define deprecated 1.1.0 +SSL_select_current_cert define +SSL_set0_chain define +SSL_set0_chain_cert_store define +SSL_set0_verify_cert_store define +SSL_set1_chain define +SSL_set1_chain_cert_store define +SSL_set1_client_sigalgs define +SSL_set1_client_sigalgs_list define +SSL_set1_curves define +SSL_set1_curves_list define +SSL_set1_groups define +SSL_set1_groups_list define +SSL_set1_sigalgs define +SSL_set1_sigalgs_list define +SSL_set1_verify_cert_store define +SSL_set_current_cert define +SSL_set_max_cert_list define +SSL_set_max_pipelines define +SSL_set_max_proto_version define +SSL_set_max_send_fragment define +SSL_set_min_proto_version define +SSL_set_mode define +SSL_set_msg_callback_arg define +SSL_set_mtu define +SSL_set_split_send_fragment define +SSL_set_time define +SSL_set_timeout define +SSL_set_tlsext_host_name define +SSL_set_tlsext_status_ocsp_resp define +SSL_set_tlsext_status_type define +SSL_set_tmp_dh define +SSL_want_async define +SSL_want_async_job define +SSL_want_client_hello_cb define +SSL_want_nothing define +SSL_want_read define +SSL_want_write define +SSL_want_x509_lookup define +SSLv23_client_method define +SSLv23_method define +SSLv23_server_method define +X509_STORE_set_lookup_crls_cb define +X509_STORE_set_verify_func define +EVP_PKEY_CTX_set1_id define +EVP_PKEY_CTX_get1_id define +EVP_PKEY_CTX_get1_id_len define diff --git a/trunk/3rdparty/openssl-1.1-fit/util/process_docs.pl b/trunk/3rdparty/openssl-1.1-fit/util/process_docs.pl new file mode 100755 index 000000000..30b149eb8 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/process_docs.pl @@ -0,0 +1,271 @@ +#! /usr/bin/env perl +# Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use strict; +use warnings; + +use File::Spec::Functions; +use File::Basename; +use File::Copy; +use File::Path; +use FindBin; +use lib "$FindBin::Bin/perl"; +use OpenSSL::Glob; +use Getopt::Long; +use Pod::Usage; + +use lib '.'; +use configdata; + +# We know we are in the 'util' directory and that our perl modules are +# in util/perl +use lib catdir(dirname($0), "perl"); +use OpenSSL::Util::Pod; + +my %options = (); +GetOptions(\%options, + 'sourcedir=s', # Source directory + 'section=i@', # Subdirectories to look through, + # with associated section numbers + 'destdir=s', # Destination directory + #'in=s@', # Explicit files to process (ignores sourcedir) + 'type=s', # The result type, 'man' or 'html' + 'suffix:s', # Suffix to add to the extension. + # Only used with type=man + 'remove', # To remove files rather than writing them + 'dry-run|n', # Only output file names on STDOUT + 'debug|D+', + ); + +unless ($options{section}) { + $options{section} = [ 1, 3, 5, 7 ]; +} +unless ($options{sourcedir}) { + $options{sourcedir} = catdir($config{sourcedir}, "doc"); +} +pod2usage(1) unless ( defined $options{section} + && defined $options{sourcedir} + && defined $options{destdir} + && defined $options{type} + && ($options{type} eq 'man' + || $options{type} eq 'html') ); +pod2usage(1) if ( $options{type} eq 'html' + && defined $options{suffix} ); + +if ($options{debug}) { + print STDERR "DEBUG: options:\n"; + print STDERR "DEBUG: --sourcedir = $options{sourcedir}\n" + if defined $options{sourcedir}; + print STDERR "DEBUG: --destdir = $options{destdir}\n" + if defined $options{destdir}; + print STDERR "DEBUG: --type = $options{type}\n" + if defined $options{type}; + print STDERR "DEBUG: --suffix = $options{suffix}\n" + if defined $options{suffix}; + foreach (sort @{$options{section}}) { + print STDERR "DEBUG: --section = $_\n"; + } + print STDERR "DEBUG: --remove = $options{remove}\n" + if defined $options{remove}; + print STDERR "DEBUG: --debug = $options{debug}\n" + if defined $options{debug}; + print STDERR "DEBUG: --dry-run = $options{\"dry-run\"}\n" + if defined $options{"dry-run"}; +} + +my $symlink_exists = eval { symlink("",""); 1 }; + +foreach my $section (sort @{$options{section}}) { + my $subdir = "man$section"; + my $podsourcedir = catfile($options{sourcedir}, $subdir); + my $podglob = catfile($podsourcedir, "*.pod"); + + foreach my $podfile (glob $podglob) { + my $podname = basename($podfile, ".pod"); + my $podpath = catfile($podfile); + my %podinfo = extract_pod_info($podpath, + { debug => $options{debug}, + section => $section }); + my @podfiles = grep { $_ ne $podname } @{$podinfo{names}}; + + my $updir = updir(); + my $name = uc $podname; + my $suffix = { man => ".$podinfo{section}".($options{suffix} // ""), + html => ".html" } -> {$options{type}}; + my $generate = { man => "pod2man --name=$name --section=$podinfo{section} --center=OpenSSL --release=$config{version} \"$podpath\"", + html => "pod2html \"--podroot=$options{sourcedir}\" --htmldir=$updir --podpath=man1:man3:man5:man7 \"--infile=$podpath\" \"--title=$podname\" --quiet" + } -> {$options{type}}; + my $output_dir = catdir($options{destdir}, "man$podinfo{section}"); + my $output_file = $podname . $suffix; + my $output_path = catfile($output_dir, $output_file); + + if (! $options{remove}) { + my @output; + print STDERR "DEBUG: Processing, using \"$generate\"\n" + if $options{debug}; + unless ($options{"dry-run"}) { + @output = `$generate`; + map { s|href="http://man\.he\.net/(man\d/[^"]+)(?:\.html)?"|href="../$1.html"|g; } @output + if $options{type} eq "html"; + if ($options{type} eq "man") { + # Because some *roff parsers are more strict than others, + # multiple lines in the NAME section must be merged into + # one. + my $in_name = 0; + my $name_line = ""; + my @newoutput = (); + foreach (@output) { + if ($in_name) { + if (/^\.SH "/) { + $in_name = 0; + push @newoutput, $name_line."\n"; + } else { + chomp (my $x = $_); + $name_line .= " " if $name_line; + $name_line .= $x; + next; + } + } + if (/^\.SH +"NAME" *$/) { + $in_name = 1; + } + push @newoutput, $_; + } + @output = @newoutput; + } + } + print STDERR "DEBUG: Done processing\n" if $options{debug}; + + if (! -d $output_dir) { + print STDERR "DEBUG: Creating directory $output_dir\n" if $options{debug}; + unless ($options{"dry-run"}) { + mkpath $output_dir + or die "Trying to create directory $output_dir: $!\n"; + } + } + print STDERR "DEBUG: Writing $output_path\n" if $options{debug}; + unless ($options{"dry-run"}) { + open my $output_fh, '>', $output_path + or die "Trying to write to $output_path: $!\n"; + foreach (@output) { + print $output_fh $_; + } + close $output_fh; + } + print STDERR "DEBUG: Done writing $output_path\n" if $options{debug}; + } else { + print STDERR "DEBUG: Removing $output_path\n" if $options{debug}; + unless ($options{"dry-run"}) { + while (unlink $output_path) {} + } + } + print "$output_path\n"; + + foreach (@podfiles) { + my $link_file = $_ . $suffix; + my $link_path = catfile($output_dir, $link_file); + if (! $options{remove}) { + if ($symlink_exists) { + print STDERR "DEBUG: Linking $link_path -> $output_file\n" + if $options{debug}; + unless ($options{"dry-run"}) { + symlink $output_file, $link_path; + } + } else { + print STDERR "DEBUG: Copying $output_path to link_path\n" + if $options{debug}; + unless ($options{"dry-run"}) { + copy $output_path, $link_path; + } + } + } else { + print STDERR "DEBUG: Removing $link_path\n" if $options{debug}; + unless ($options{"dry-run"}) { + while (unlink $link_path) {} + } + } + print "$link_path -> $output_path\n"; + } + } +} + +__END__ + +=pod + +=head1 NAME + +process_docs.pl - A script to process OpenSSL docs + +=head1 SYNOPSIS + +B +[B<--sourcedir>=I] +B<--destdir>=I +B<--type>=B|B +[B<--suffix>=I] +[B<--remove>] +[B<--dry-run>|B<-n>] +[B<--debug>|B<-D>] + +=head1 DESCRIPTION + +This script looks for .pod files in the subdirectories 'apps', 'crypto' +and 'ssl' under the given source directory. + +The OpenSSL configuration data file F I reside in +the current directory, I perl must have the directory it resides in +in its inclusion array. For the latter variant, a call like this would +work: + + perl -I../foo util/process_docs.pl {options ...} + +=head1 OPTIONS + +=over 4 + +=item B<--sourcedir>=I + +Top directory where the source files are found. + +=item B<--destdir>=I + +Top directory where the resulting files should end up + +=item B<--type>=B|B + +Type of output to produce. Currently supported are man pages and HTML files. + +=item B<--suffix>=I + +A suffix added to the extension. Only valid with B<--type>=B + +=item B<--remove> + +Instead of writing the files, remove them. + +=item B<--dry-run>|B<-n> + +Do not perform any file writing, directory creation or file removal. + +=item B<--debug>|B<-D> + +Print extra debugging output. + +=back + +=head1 COPYRIGHT + +Copyright 2013-2018 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the OpenSSL license (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +https://www.openssl.org/source/license.html + +=cut diff --git a/trunk/3rdparty/openssl-1.1-fit/util/shlib_wrap.sh.in b/trunk/3rdparty/openssl-1.1-fit/util/shlib_wrap.sh.in new file mode 100755 index 000000000..eac70ed97 --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/shlib_wrap.sh.in @@ -0,0 +1,138 @@ +#!/bin/sh +{- + use lib '.'; + use configdata; + + sub shlib { + my $lib = shift; + return "" if $disabled{shared}; + $lib = $unified_info{rename}->{$lib} + if defined $unified_info{rename}->{$lib}; + $lib = $unified_info{sharednames}->{$lib} + . ($target{shlib_variant} || "") + . ($target{shared_extension} || ".so"); + $lib =~ s|\.\$\(SHLIB_VERSION_NUMBER\) + |.$config{shlib_version_number}|x; + return $lib; + } + ""; # Make sure no left over string sneaks its way into the script +-} +# To test this OpenSSL version's applications against another version's +# shared libraries, simply set +# +# OPENSSL_REGRESSION=/path/to/other/OpenSSL/build/tree +if [ -n "$OPENSSL_REGRESSION" ]; then + shlibwrap="$OPENSSL_REGRESSION/util/shlib_wrap.sh" + if [ -x "$shlibwrap" ]; then + # We clear OPENSSL_REGRESSION to avoid a loop, should the shlib_wrap.sh + # we exec also support that mechanism... + OPENSSL_REGRESSION= exec "$shlibwrap" "$@" + else + if [ -f "$shlibwrap" ]; then + echo "Not permitted to run $shlibwrap" >&2 + else + echo "No $shlibwrap, perhaps OPENSSL_REGRESSION isn't properly set?" >&2 + fi + exit 1 + fi +fi + +[ $# -ne 0 ] || set -x # debug mode without arguments:-) + +THERE="`echo $0 | sed -e 's|[^/]*$||' 2>/dev/null`.." +[ -d "${THERE}" ] || exec "$@" # should never happen... + +LIBCRYPTOSO="${THERE}/{- shlib('libcrypto') -}" +LIBSSLSO="${THERE}/{- shlib('libssl') -}" + +SYSNAME=`(uname -s) 2>/dev/null`; +case "$SYSNAME" in +SunOS|IRIX*) + # SunOS and IRIX run-time linkers evaluate alternative + # variables depending on target ABI... + rld_var=LD_LIBRARY_PATH + case "`(/usr/bin/file "$LIBCRYPTOSO") 2>/dev/null`" in + *ELF\ 64*SPARC*|*ELF\ 64*AMD64*) + [ -n "$LD_LIBRARY_PATH_64" ] && rld_var=LD_LIBRARY_PATH_64 + LD_PRELOAD_64="$LIBCRYPTOSO $LIBSSLSO"; export LD_PRELOAD_64 + preload_var=LD_PRELOAD_64 + ;; + *ELF\ 32*SPARC*|*ELF\ 32*80386*) + # We only need to change LD_PRELOAD_32 and LD_LIBRARY_PATH_32 + # on a multi-arch system. Otherwise, trust the fallbacks. + if [ -f /lib/64/ld.so.1 ]; then + [ -n "$LD_LIBRARY_PATH_32" ] && rld_var=LD_LIBRARY_PATH_32 + LD_PRELOAD_32="$LIBCRYPTOSO $LIBSSLSO"; export LD_PRELOAD_32 + preload_var=LD_PRELOAD_32 + fi + ;; + # Why are newly built .so's preloaded anyway? Because run-time + # .so lookup path embedded into application takes precedence + # over LD_LIBRARY_PATH and as result application ends up linking + # to previously installed .so's. On IRIX instead of preloading + # newly built .so's we trick run-time linker to fail to find + # the installed .so by setting _RLD_ROOT variable. + *ELF\ 32*MIPS*) + #_RLD_LIST="$LIBCRYPTOSO:$LIBSSLSO:DEFAULT"; export _RLD_LIST + _RLD_ROOT=/no/such/dir; export _RLD_ROOT + eval $rld_var=\"/usr/lib'${'$rld_var':+:$'$rld_var'}'\" + preload_var=_RLD_LIST + ;; + *ELF\ N32*MIPS*) + [ -n "$LD_LIBRARYN32_PATH" ] && rld_var=LD_LIBRARYN32_PATH + #_RLDN32_LIST="$LIBCRYPTOSO:$LIBSSLSO:DEFAULT"; export _RLDN32_LIST + _RLDN32_ROOT=/no/such/dir; export _RLDN32_ROOT + eval $rld_var=\"/usr/lib32'${'$rld_var':+:$'$rld_var'}'\" + preload_var=_RLDN32_LIST + ;; + *ELF\ 64*MIPS*) + [ -n "$LD_LIBRARY64_PATH" ] && rld_var=LD_LIBRARY64_PATH + #_RLD64_LIST="$LIBCRYPTOSO:$LIBSSLSO:DEFAULT"; export _RLD64_LIST + _RLD64_ROOT=/no/such/dir; export _RLD64_ROOT + eval $rld_var=\"/usr/lib64'${'$rld_var':+:$'$rld_var'}'\" + preload_var=_RLD64_LIST + ;; + esac + eval $rld_var=\"${THERE}'${'$rld_var':+:$'$rld_var'}'\"; export $rld_var + unset rld_var + ;; +*) LD_LIBRARY_PATH="${THERE}:$LD_LIBRARY_PATH" # Linux, ELF HP-UX + DYLD_LIBRARY_PATH="${THERE}:$DYLD_LIBRARY_PATH" # MacOS X + SHLIB_PATH="${THERE}:$SHLIB_PATH" # legacy HP-UX + LIBPATH="${THERE}:$LIBPATH" # AIX, OS/2 + export LD_LIBRARY_PATH DYLD_LIBRARY_PATH SHLIB_PATH LIBPATH + # Even though $PATH is adjusted [for Windows sake], it doesn't + # necessarily does the trick. Trouble is that with introduction + # of SafeDllSearchMode in XP/2003 it's more appropriate to copy + # .DLLs in vicinity of executable, which is done elsewhere... + if [ "$OSTYPE" != msdosdjgpp ]; then + PATH="${THERE}:$PATH"; export PATH + fi + ;; +esac + +{- output_off() unless grep (/-rpath\b/, @{$config{LDFLAGS}}); ""; -} +if [ -f "$LIBCRYPTOSO" -a -z "$preload_var" ]; then + # Following three lines are major excuse for isolating them into + # this wrapper script. Original reason for setting LD_PRELOAD + # was to make it possible to pass 'make test' when user linked + # with -rpath pointing to previous version installation. Wrapping + # it into a script makes it possible to do so on multi-ABI + # platforms. + case "$SYSNAME" in + *BSD) LD_PRELOAD="$LIBCRYPTOSO:$LIBSSLSO" ;; # *BSD + *) LD_PRELOAD="$LIBCRYPTOSO $LIBSSLSO" ;; # SunOS, Linux, ELF HP-UX + esac + _RLD_LIST="$LIBCRYPTOSO:$LIBSSLSO:DEFAULT" # Tru64, o32 IRIX + DYLD_INSERT_LIBRARIES="$LIBCRYPTOSO:$LIBSSLSO" # MacOS X + export LD_PRELOAD _RLD_LIST DYLD_INSERT_LIBRARIES +fi +{- output_on() unless grep (/-rpath\b/, @{$config{LDFLAGS}}); ""; -} + +cmd="$1"; [ -x "$cmd" ] || cmd="$cmd${EXE_EXT}" +shift +if [ $# -eq 0 ]; then + exec "$cmd" # old sh, such as Tru64 4.x, fails to expand empty "$@" +else + exec "$cmd" "$@" +fi diff --git a/trunk/3rdparty/openssl-1.1-fit/util/su-filter.pl b/trunk/3rdparty/openssl-1.1-fit/util/su-filter.pl new file mode 100644 index 000000000..389c7c35c --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/su-filter.pl @@ -0,0 +1,264 @@ +#! /usr/bin/env perl +# Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use strict; + +my $in_su = 0; +my $indent = 0; +my $out; +my $braces = 0; +my $arrcnt; +my $data; +my $tststr; +my $incomm = 0; + +while(<>) { + $tststr = $_; + $incomm++ while $tststr =~ /\/\*/g; + $incomm-- while $tststr =~ /\*\//g; + + if($in_su == 1) { + if(/}(.*);/) { + $out .= $_; + do_output($out); + $in_su = 0; + } elsif(/^ *\} [^\s]+(\[\d*\])* = \{/) { + $tststr = $1; + $arrcnt = 0; + $arrcnt++ while $tststr =~ /\[/g; + $in_su++; + $braces = 1; + /^(.* = \{)(.*)$/; + $data = $2; + $out .= $1."\n"; + } else { + $out .= $_; + } + } elsif($in_su == 2) { + $data .= $_; + if(/};$/) { + #$data = "\n$data"; + $data =~ s/\n */\n/g; + $data =~ s/};\n?//s; + my @strucdata = structureData($data); + $out .= displayData($indent, 0, \@strucdata); + $out .= "\n$indent};\n"; + do_output($out); + $in_su = 0; + } + } elsif($incomm <= 0 && /( *)(static )?(const )?(union|struct) ([a-zA-Z_\$][\$0-9a-zA-Z_]+ )?\{/) { + $in_su = 1; + $indent = $1; + $out = $_; + next; + } else { + do_output($_); + } +} + + +sub structureData { + my $data = $_[0]; + my @datalist = split(/(\{|\}|,|"|#|\n|\/\*|\*\/|\(|\))/, $data); + my $item; + my $dataitem = ""; + my @struclist = (); + my $substruc; + my $inquote = 0; + my $inbrace = 0; + my $preproc = 0; + my $comment = 0; + my $inparen = 0; + + + foreach $item (@datalist) { + if($comment) { + if($item eq "*/") { + $comment = 0; + $dataitem .= "*/"; + push @struclist, $dataitem; + $dataitem = ""; + next; + } + $dataitem .= $item; + next; + } + if($inquote) { + $dataitem .= $item; + if($item eq "\"") { + $inquote--; + } + next; + } + if($preproc) { + if($item eq "\n") { + $preproc = 0; + push @struclist, $dataitem; + $dataitem = ""; + next; + } + $dataitem .= $item; + next; + } + if($inbrace) { + if($item eq "}") { + $inbrace --; + + if(!$inbrace) { + $substruc = structureData($dataitem); + $dataitem = $substruc; + next; + } + } elsif($item eq "{") { + $inbrace++; + } elsif ($item eq "\"") { + $inquote++; + } + $dataitem .= $item; + next; + } + if($inparen) { + if($item eq ")") { + $inparen--; + } + $dataitem .= $item; + next; + } + if($item eq "\n") { + next; + } + if($item eq "#") { + $preproc = 1; + push @struclist, $dataitem; + $dataitem = "#"; + next; + } + if($item eq "/*") { + $comment = 1; + push @struclist, $dataitem; + $dataitem= "/*"; + next; + } + if($item eq "\"") { + $dataitem .= $item; + $inquote++; + next; + } + if($item eq "{") { + $inbrace++; + next; + } + if($item eq ",") { + push @struclist, $dataitem; + $dataitem = ""; + next; + } + if($item eq "(") { + $dataitem .= $item; + $inparen++; + next; + } + if($item =~ /^\s*$/) { + next; + } + if(ref $dataitem eq 'ARRAY') { + push @struclist, $dataitem; + $dataitem = ""; + } + $dataitem .= $item; + } + push @struclist, $dataitem; + return \@struclist; +} + +sub displayData { + my $indent = shift; + my $depth = shift; + my $data = shift; + my $item; + my $out = ""; + my $currline = ""; + my $first = 1; + my $prevpreproc = 0; + my $prevcomment = 0; + + foreach $item (@{$data}) { + if($item =~ /^\/\*/) { + #Comment + $item =~ s/\n/\n$indent/g; + if($out =~ /\n\s*$/s) { + $out .= $item."\n".$indent; + } else { + $out .= "\n".$indent.$item."\n".$indent; + } + $currline = $indent; + $prevcomment = 1; + next; + } + $item =~ s/^\s+//; + if($item =~ /^#/) { + #Pre-processor directive + if($out =~ /\n\s*$/s) { + $out =~ s/\n\s*$/\n/; + $out .= $item."\n".$indent; + } else { + $out .= "\n".$item."\n".$indent; + } + $currline = $indent; + $prevpreproc = 1; + next; + } + if($first) { + $first = 0; + if($depth != 0) { + $out .= $indent; + $currline = $indent; + } + } else { + if(!$prevpreproc && !$prevcomment) { + $out .= ", "; + $currline .= ", "; + if($depth == 1) { + $out .= "\n"; + $currline = ""; + } + if($depth == 1) { + $out .= $indent; + $currline .= $indent; + } + } + + } + $prevpreproc = 0; + $prevcomment = 0; + + if (ref $item eq 'ARRAY') { + if($depth == 0) { + $out .= displayData("$indent ", $depth+1, $item); + } else { + $out .= "{\n".displayData("$indent ", $depth+1, $item)."\n".$indent."}"; + $currline = $indent."}"; + } + } else { + if(length $currline.$item > 79) { + $currline = $indent; + $out .= "\n$indent"; + } + $out .= $item; + $currline .= $item; + } + } + return $out; +} + +sub do_output { + my $out = shift; + # Strip any trailing whitespace + $out =~ s/\s+\n/\n/g; + print $out; +} diff --git a/trunk/3rdparty/openssl-1.1-fit/util/unlocal_shlib.com.in b/trunk/3rdparty/openssl-1.1-fit/util/unlocal_shlib.com.in new file mode 100644 index 000000000..dd4fd2a9d --- /dev/null +++ b/trunk/3rdparty/openssl-1.1-fit/util/unlocal_shlib.com.in @@ -0,0 +1,26 @@ +${- + use File::Spec::Functions qw(rel2abs); + + my $bldtop = rel2abs($config{builddir}); + our %names = ( map { $_ => $bldtop.$_.".EXE" } + map { $unified_info{sharednames}->{$_} || () } + @{$unified_info{libraries}} ); + "" -} +$ ! Remove the local environment created by local_shlib.com +$ +$ OPENSSL_NAMES := OPENSSL_NAMES_'F$GETJPI("","PID")' +$ IF F$TRNLNM("OSSL_FLAG",OPENSSL_NAMES) .EQS. "" THEN EXIT 0 +$ +$ NAMES := {- join(",", keys %names); -} +$ I = 0 +$ LOOP: +$ E = F$ELEMENT(I,",",NAMES) +$ I = I + 1 +$ IF E .EQS. "," THEN GOTO ENDLOOP +$ OLDV = F$TRNLNM(E,OPENSSL_NAMES) +$ DEASSIGN 'E' +$ IF OLDV .NES. "" THEN DEFINE 'E' 'OLDV' +$ GOTO LOOP +$ ENDLOOP: +$ +$ DEASSIGN 'OPENSSL_NAMES' /TABLE=LNM$PROCESS_DIRECTORY diff --git a/trunk/3rdparty/openssl-1.1.0e.zip b/trunk/3rdparty/openssl-1.1.0e.zip deleted file mode 100644 index 1361d91cc7f4514558433a39155a5e97ae48644a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6623784 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

T;s2-MK})o9U0?Howu0+|c|R<^ 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

PpI-ZY`E6NtoVm+$WTVZW`x07pu6 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%0A6=9-d1A+Q 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

T-Vl%G5d2xg$#!u8#}^z;+B) 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

`0g<0fuqS9}v6u&@e^yw`@ zyk}Wn)4Nnca+K{z->f%|X%x*9m&$deT$Q!Biv=4uh#Z7+K?FK79@Wa}eFV>szZuQt zs_m~0lQyE*LOrBN?3}c~o1~k7qAB}%gx@o+Q4Mt;8+ahKPEv(zL-$^lInq3G(Ip8I zuP{;6*eCw`dJM;}Wa}gzxlt0;{%)6#)}wO

O5x$N&)m|1hVySY50EcEeXJg7uc) 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

OIH~jN!7gyJq-;*}L^H#4)anamVUk|$E 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%0A0tYe*Y8J9ws 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⪚rjoLEONM;>98044Xnt<%|B@2qOv*d#`?y^RU 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 y`b#l)uyDje23ZYjb%6iXc99qnn>l5%5Y&p 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

|$B%ORMX!ffbYJHdI^j9%zg3oMsX50} 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

*((t%3_ELJ7NN$7PVa5p)_mB8wKZg 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 %HEheXve73T!|HiW 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

{I3B0 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

` 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 r44+nNrM`#*SFvhI<$-Z5F)McQsTgqlk$c2p7yX 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®Rolx78Q_ofywc?VOIN>&W7PsV;^@Wy~UXP4IQ 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 z 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%0Dl(D#a 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�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 z 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%0A6kxJR@ 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 }if_L|DJXMPfg4sPtLb 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

?m$SSr!poEUV`+$DL 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

fR%bFuS1y?t--#4+FBX?ob4%%tvT08x7<`arw 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

*8}L#z5*V@rbJrmA~&(wcCGvuS`Nr2U6#iU6r? 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 z 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

IBc$W}-yznLNGO2efI1c#@n`(bBw|31V) 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≷1Plm-Q54>Flu5%))1orsP<~usB;c`f=tr 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 W!!@>l?L3(oCBo=e&YH1>UoO9;Fc3&Z@<#Zbe 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%0A=xXBFEx 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 LGS6KrR>5wR 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Πq^J1-s0O-`x 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 z eT)x6C6P1DNK4oJfe-!66Oa=ay?ylL)P6vQX2#LEjjS}x3W9HOsNPk$p|yAS*V zh}sRc6nHN93quCLg-_5K(4!oBsRc5_)aVav#_rkP52c z#K%AH3@2)*jg|XqwM`RgsicBR#p6cxf7G@O-|CwtS2CLuROLol;Fqje*_k=;9~zQn ztAB2Oc=}ugXoNSBi}p_oQxekCE!E;5yUReQhu&U=N|y)o?Vv~Bf|O7f{hY~YL7&J2 z{u1vXz``sbPPO&|MuF%582K`no&0q+=~@kKJQ~X-IL9ovGR{D)JOcEGo-K+MbAH{H z>MYvsQjfy+V@x8)`lc%V>39z6Nne)4)^mFwRgO1_^&}qy`d%sB!<4!&otx45Lap$r z{&jqJ(S%dOW2#S@E*ZFCVIq$iNclPkH!DF*6M~RNGqiD(S=Kf`&yrT&Nc2SRNG7i2 zi&$D&Iii3U%kPE43@`bCUuN=)`H`l@950X#v1;th#`+rv@SAsbi}%|Y&wEB_p`Jr! z_!LR#eM#*gx&fR`H$%ai&|zdi%?Np5zx9PH;j~g+F8N%07_z+j7h8Qu+qq z&V4o!B-D5@a`16PF7@Zo7?!pb;)=>%KHXRrEbH(Q6Z3YDHisT(E#OUu6s zoN9f&KK$_t^O7Z-^PwAiF?{!deZ{W^Z2r!~%x*{?67t}U_Cv0_eB%B^JLlZ@h z$Jd7X@GT@t&e6{)o_q>nd{Q6_o8$MtG0sd?B?-Eq52~VnAWkYKgU-_#rx_CT5|yj- zpj0f*^ab63#gaE&UUHeh^eN5!S_*00jIdVqtpJ>cEvfg~A z%Q`wH!o2b@E4rpDT2^L!lqDcLygc#bU(AC)EJnk6i`Ebbv`8C#sm^qXE_f$xjP~#X z9c>cW&KrIS<`(4Y^Au$B}o2fS`QV0r7+4n66 zQ}rC;a(ff01if9q?-V&-3!SGARZ*!afP+yKrz(DF0GmSIi_~I~D5B@Gc8Oi&rWO{J z*@}WJ*u2Yv2A|+4yu>Vl+>ozI{|u_rI4On>}1ODxPboyCdMJz6z(~A zOO`eVxyz=8LS{yq(}u=@lu4{CF@tvKs!nVyiQbK#@Z5yKZvHyVq`3&QP7Az;ox-9$ zVUBEfwFU!@2R+DYD<+pWV0$Z-1cq5wV}9Q|LP7Fv z%7R&h_Dr_K$etYH8YE@OKlVt$sYTeTq)cn4UTwk(5!ErWZFR7!zN2m=fFPDzZUW53 z&J4-7*^F6^@vL>w3Y09C@vb4en#Q&g(~&SL5pzerPbJokg1;XaXPO^7MbroCrJrCY-4N0MJMN>+R(K%Ewu$`MaGw zy!=h$J(L)a5{VGsi?Kl%mGIiA<3v}%5!PXe4s8ZNDxg53cR+S#U!-&u_c1tR#t@ESd>D2^+=bon2^&1}@%toPao&kW_taWdh7`zEqJ+di zvnLu1GITFm?*O-4e<}cI)k1>F2>r*%nikF^5rV@eN7&{bjU8~V=%j=%n|M3}uPK|2 zjZG5()L>l+=v*tMU3wYaI!T&4X`bs1-z&V~wy<@)Z4T_sYTV6c-HM-!i5GcWR$d3o@RaGq^`dvvc2#4}uX(1c5XN7TkzGdPAy%-WY7~r|RiK zV?hT4|Pusj3tjw}#c z*TD0@cRzZ3SW;~N2tC&o^PabDektQIZ%ie~aRYEjW|C=SWhm_1;1ljL6Sg3`o(j&x z83M#)(9S(&sD@DTGuU*L5A%)#pRFxGl&W5TL6BX`Em9`XPKUwpb%2pGL7i@?f4GJ0 z?!@)#6D|C$BJ?VPxxR4pEVI}q_AKi4fGC5Mz%d{4W|$-oc8nX%6o9R@EX__6XcbBQ z=PL1`k|L6{5d?v=fXB_SB0JfQJ#v!pW;k#TkEoiWMh<8JVvPQ<7ZZ=}Fa$q_x#=7J z-@ayn3FidveV%kg$-&~2?*a9nmxACv0cwAOO<-c_aF{o@bY>zvS&GXPOYhmzx*a2k z&%teJ3UtSH=(RND-jO&ceq*SHe!$VNJok2LD(*foV98bM(Y(=hGW1Up0bci!KeC{4 zN_u_#rc*rBSO+E}_Bf+hn!VeI>5|A`4TXr2So}h9;*EbnL>kEn{(eK_dRpQ?PEDc- zI_&jLwmnppSujJJF$GU4Lzz*cr6t7{H>7s%f)P)&3@a3v9>ja=b*1Jo8 zlNuNo^2*xzeO_2_DY2U@rMU8TuO=-2QaT_SA@Gc}C;=t~GpPm(2R^JRuInc?O!`clO1O(Zk{>E9HO#%CJWZU*(o>|CjwZqlRO@flC;M zpcf7c;l&G$J5EyFQz}s3Up|=YbHC47PqLK4O9grKIBeZg5Tv8Ap|BK^{G}I(;OlDG zYlK>_Poj*twqQqz#OZcH0acu<;OL|fZNFq5eCs1l3?4ruHiPG3?`=2KdMKR7|3>AX z3z-wl{|lgXiwwWwfFfQgm}0n};&At%Qx8;OQeSaMTv5gl2T5B+Cwc**MGkFB4o!P1 zp_d6qk=5mM4J)-!bW~7IlNv*XtUoPM64K>cSJHr^MR&6T(KiLM%;k5HR~Wj^=)l#> z0e4w2t2U8V0uXJqPXyNzH3n&g$P4)&#=a>=l&EWVY}>Z2Gq!EpI%C_mZ5wB7+qP}% zpFg?D&39k!m+VTfbhuR1o1o8VPRpZ7tai@(cyudQ*b`A|AdKe^njVtyd5=qK>6rPWya)agBxXpI7S4}O*=y^KTbH>naYkzk|-gy zD@!A>*?iH)oQvyOZTCi%D}GqA>nUXk1kdEP|9;K#e5SLb9NjbRxm&Ji4fFBnyeAhS zHpr}dUQ_eem#KH_m*0C!CMZT(poP}OZ%#ICb}tvdc{<2*2kK4%OrVr!sy@u<91|V| ztquBY2W`Na@4tsCcpL`NRQ*S|RcBD?4h=h3h+|3*1oGEVG5K`{@$;`On4haLL{E!1 zz!XigCA2=_Qc}sGh=9QjA}dUN3yAvnnowS2tk>{>Ro03>teSQPU9`78(A;8GF06$j zWagRkqF~ZM`#N6&&Ss@#+KF+2d(qgFhKJ2=Y$&KWb1{CI?x#Hnp~wzM5rE*$85%-P z7>gMOfuWl%_S*@d2JxTs$BDAwVO}G}0ENRh^0&Z3Zr^ur8si1Z6;a$5U=o>6ac!Fl z4(b(tpr~zL!?^X9a4+;$x|UN|AA?MzcoVAdL;1$aZr?y?_K&h1rT7g_#&xU_=--b} zv;$^I7k4(LTgJJ3Cx@V7RjL`yLU9Wgrt4Lff6!B>CMGJ^hj#W`bu9vd4@A2n{;F3r zjAy-X>bBiOI_ep7ungijIBJkg3{wOfvZ6Gx;>cL-m72|T*A4%Xve~Q)nZg3J;`%H(8!*x^(lwWRuz0u=I%qGVFizaj z?WXMQrKU`+KM!78?P*`6bNXDgYEmFAHr$%5msyIq`)6i3>=V7z2)+=c&?8>%gJchn zUxF=Ccw}=w24`p|{#p1PN&n^qyGt6(=pqvf!v$#o+AHPf6C32AASm<$2U(g)n&n|% zp)Ke^6ZYaln2sXx{?Z^HM}$1azy_hbI#+PKbY2VYyODDg%a@ze?X56Tb*r&~skvAf zP_6yit}!{%m68&n&s&m@kRRX@IFp$3w=C~-ca*LIq(O(Dkt`9=1fjw!q{K=zoZ>kS zy!aML2Lt5+Mb~N4tadxA{AlK~LHq6Fvq8G2-=9$%1KW{_mwv+jJo|gik>JVYHq>xY z_PFaFIO&H8#0U(Rui$Taz;k+u5vPsfgxG>P9LS@#bSn`j?ToBB&oD2~jBugok`i96 zF{`lN^ig<3(r;Vqo)+X(uqEn(H(E(GL^fVs!in47N|riY;2<9-lcmMt)A;(i!p+Z~ zsyg%$8Plc|#!4jyB4&|NC1-vXalkAfcyIQ#4I|Ugi)NS>D>bL{N`+d?@~B+Xy+k#q zGTEqsHv-^S7xbnFtb>p7aqD-6%eJXPouY|ZfvQ!_VHv#QAqN)Pr0l*^`On$71InWM z36BR028^kry$kOxj0x5@>Ec;-sH-M{(9+W6TK80q)C6NkGe3bB&;~hLY}ht__=5=c zK$0#_I6Nl?l$G@;G#bw84Cqj9l1ND~7d&2&3(*6`ZQR5}Er76*s)(L;m!bIdL8sE{ z`s(IJO$m(w=o?%dJT9DaI3P=jWM$r<1xB1ak2Zp+EVx7%XkLx_1|K6^v!b785i}gA zzhN3v2BA8$S;nb#JwI%HE6l@JidLh@yrKY-G%h|-uSJ_9l3YbNh>8msYsnZ-^R>Dh zUUO%!mF2roEN6Mys^|Ox&h`0imI>~$&Bj@J!=4K}`(tkVo2Qk!dCIx1&cMW`-bhn} zC^~D-qZT-gAo_#DFHF$0QJ|;m=e_d}Q;5(;ee1h_eFj16jdu=Gl$~wl-IR?6 zTWw077KO#@0I{C?)BCGQk1v;fb&7@7-mY_bQFNF7Z%ilXH-MS96#*4n-Hl+kyG)lC zQ-8RKHeIu1#!>z$wPfwL?C%`r~K8(--U}kdYV!eoi9}3RBl7pg!#AjvYyHS3Gs#jBqm5 zI90p04nK-N1^l2ER=SE5+_&5`Fatxg3=am>_$|y-a0wXe3Z!;sZH?yUQcy_vl#A8a z+1YGoNTJZ*y}~`suu53OM|qZySe0eTrXO-hgRx(qpYfeAr#l_V_l zv+-WGW;1d}j_jU3WVx`+nQl3lDM#AWJvxy7DzkVnHWf2jL{BY6WwoTOtd+{;es@?M%B(C_-iQVu0%Fi~ z$@sqKvZdS_g)$0eIV+0qhxt@ea?S6_W4+&ugOp@qVv>B{oQ+(JvRNGM zOR7a;N`*+r%+F7FKNnmF6}5saY{nc|<+jnKwN}^Q=n+IRwUZee$3_T`rg0W`KNF=x z@ASeeAK7auID|w|Y-KK=n@8ZwwLLkMGTVFHjW~=krBqS3ZiUtGuF0!%UFgh&szrI0 zIG3O0=a}(0vS}(0c#>}S(Z1u2=(6BuOImcHR-Jjng(tB;{PQ<61A9fTx1dd{11&TA zJ$l>RB7;moLZO?0h9b!6U11(}%$-&$z8d2#qP)nnzE=a?KF~{rOKw>a6I{c-del@h z5?$EJ29}| z3(%OxEhRNTyz7Zh+VpPeipq;=NImP4gC481zLQzH>f%A@A48`V17D-tGgbSG+bbe8 zwY05hYp+mOCXbqJ|4ymvZqR3WsJ{2q{?dgkAsU4Z#e9=dGC@6FZ;A!iao5$;Te?~< zQYY9Rq{*5URoPsbwfs)39+;|9wK8X*;Hof%G<_?26k+J-s_*-P->diJzL^SzYIOS@ zWse_>b6S$$Kzh#+kEVqwTb*YP2vdy;>lULcc#kfDWZ>rJ9!}MvjR+x2C@cO2*83>@#bNaxIyBZCvsR^)hX4pguqRcYS;%<}nt|lIK zEX|+kN2nQNq{3&wdTcr#-o+Zll|eV{oe30+6?9vIpT5^PD1Vn-O}mZW!l`;t@@BHg zR0r4o+~qX+PLieExGgH9(oqwziC` zZ_XRtL=Mr)wB$!F(b}-hqgC5lG%aMWu9}&h^_wdR%J2=F+*{Wj?H^sdaKE(Ax6Po! zsld07T@{(x{Y}oqeK^c9&GselxSAw#x^f8h5?h4&b31f&9jo(9aKX(f#7VYP~6x8#y!zKB0TcPZ#;1+mhe`p8<*4INh}{L6^I1M(hM#jqYJgqPq|#y&(eP$TXgGdaCBivh)jucQJjhV)dF*fS>}={E11Q zCW_13;5B+*B3~k;@~j2$M@G}~O3nAhdb*uDQhc4#(6MuvO)%wFgJ(b31U;D|zCf_m z6ya+&`?BiTSo3P89E5j_u}rWb{*I}>1Z2lK|9mb-9_z=2>Z@$u5w}FO^uFy?^3>FH zAM>&0F?#AdEj_4^4$nG;k-*E0;1|f6Bc_%da}}RBPXge***FnVuI_Gi11V5QT0$19X+ zP`pK(D!gAjMdF_yTQ-QJh-cpZ)rn~p#A(wal?>suH-!840wjH_9iq2O@%&svZv9a^ z!dIXe$2|NnN8^Zl^j)xf@xe4Bn#)(4Jh2@p;~6|NxRVjm z1PmU|bhv-9REvVq;CQ@w`LwfH_jvV=4!@PN+slm`XNV;8eKhYWWMW}M^u`v=uD?|k zlmdSH#MAB`#_6j^XfgRbnS1fQ()n>+|JU%d_KDh^L^{hAZbRTtcG%J?)8eVyx|LY+ z@h+PvZzL@R2S^vE{qEA?`>_z!t$xpLJ<@d6eVucOWknKQ6mQD%9!29CDiS>2OtZm_a)By0>SrLS@U_w;D0L;lu+qS$}vv8>krRRHu{Y2*&L*XdNU$Oe5A#c}(Wm z?Jw0OtnN=*Ac`Lo!{zBbpWY(xgj0S@Ba-d6J%w^l8-2_sK4m>yRE!QOFQGzgo?%fV}HPXG3l;ccyi&@N#L4T z95)g+qn34UNs#A9{9HQ6W)Q++s|uPr#*IRpy7_cbXB(i3uK8h80=TQ7Rky7I5i~l* zbR-ifI$F>ZE8_8%lu0k^xjQrMK=WJLl{HM4tQlP(TaL7TRmvdo2$x zySy#vCub@Tzl1T}z6UGLrX_S6zY}>GE<*n9btJh5BRaKT2{+>wX0Fz#5`UVLLZ$TB zO2{6tm9dx{)G~8Ln9&|*k`QLjM5SDmxJyap)5iP|J~x#x+yA$=wt>-PVMrUChKGOC z&pld$o%n||ddpy^{Gy>M>7a_5bRv&gC#Py0zFM}4s`cM4nw2q{x+}(8tZ>mr0_odr&cO{&dXkPNHjufIjYn*ok0gMTq!2T%KE3H zx5QyFaNV7Qg<6d?9|04}_Ncjk?M;(g135`%{w5b11r-)gc8*q=@A%^oi1L}Hf5c9F zm&6no&M6)19@=x!!JAx5(KVuCeYNs3uNt=$yyYBHafDjb?rXqio7kI=l#Z)&2>yUI z3SXn4Z2d}hGpA%l#A-2N3VyI@IjT{W)bI&lZSWi-a9G6MX{7?dDf?Pt^1dZiUc(Wcnf$;nuV z>mimX&YB--4>xOe>6B4>Xb+RY4~3n|O-T$A;%t9^jt44aQ@J{&h|*kFZ&^5al$v_2 zs|uz7O6<`OjMj>=+s%2D&X*k%LieLdSka?7WN7(90Ti5bcSH^WkP)2FWZ%37sH zoL+38#hYhv5y8DpW!~%0AU+T8=hsAE@dVg*Ce2CiTJMVhPLe=ro}oIY=boP!B$e=ipeT zXbt4VPT#ZTN{-Bn_=9MW5Lt?L;CYiwY*k)9>9(7gcA3QJ%$YJiR_!D|gz7Z%>-KFK z)^EaeqCju4^ivltLib|mK!gl5WUTpXR;xg?aUl=N0z}YoMS#C3ATS^NsMT1`QJ%U_ z&ahOQc9Oz6EgE6=$)9-P_WQoE!jcz@R}GSY2{+P@m6;cq7?CEcG09`rgg?q?)79*! zI?mK;;P1%q2d?UM`pjf@wEfP<($XZ#X<7* zLzjA*C@@qgdZhC5`R3H9XsA(LP zGbI=nU~!^@%+rElvUq>I?KY2mXz$6O=(=86@D_6(XBTjzGjzQ&z$uvWQY5O^7$!)7 zHMkFV&po5mmTmXG3p3ZEKrP6mmo|iN8?vxO=_kq!UVn?>-vSZ9l#~;)PkQ7C+~=)( zKh;hNIE}M7Lciv7MbbrZ=eU>tf&2HG929^3V+llr;|+0`#>vP-f4IEF0e5U}JK_@i zOypHY5H#}L%Y5RL$E^NLcf>({a0pIf)qgNrZt-7#3r6B_?r{#3lEY{*Cuq7_O-38+ zM&iS-h!fi|;V*7np*Nyk;dVmet6((>01y)(!loRToh$LO?((Od-N0n{qpT6W6j4;s zsN~~msX9-mQo@as-i9CM5l57oEE*0S2sNw4>usqjM34)of}(bB}Xn>Pkw0Hr`LU zIvX8mAK6;c^-zc2NvpDMU{zJ-%K@WF251ImCm%D&XcL?h8G7ApUx=R!O?S-z#-Cz) z9=FcD-hFtxcg<^@O@%+5!U7$^$b@*y^x3Z7uE6LefirewsZVaKFdf?9+}@h~>#@yk zxpc5gdAcLvUP~ZG01^k~Ud>xTR~Qf08m%`M%CN<-mbjgV38i5ypo zfXT-P6?TO=d7!c=O2zz<(<4Oz$tx&^xCun&(_b8c20K99=*!dxJBX2wWH2bD=~9U< z!UnC~j^E}nBRPw*P@8q8qYyri?-QcnrNO))db)i>ZvOlj`lIS48^ewg3nPUnZCWKT zgzf7l2JPWYno=N50xD5~Rmanwfkzp^MgedB%oiXqkTdOZ6o`?DDca8#DJ|pM$Na8G zdpKoVt3Dh*g|I+}um#4mbI-5Xgo1N#Z84;}14pJ`K&<+=UVEFiUMr-5ZzsFHzh7oM zY;DtgFLw=zYj<4szTilEurqs+jP_W>>P%QG%PvxX)s^gic@DHWUd_cqCpQuaTu#a( zWEu)w3ic8}brbVA03Sxqh(W&HeI0OKqWHxy6bOmf7X{iE4cHF`aGXN?4yFMp8;8QN z)cq}1>n}`#dJH#d)hG!7B;c|h&!gX-t^Kg-j`Zy{f`50E< z%i&~5dptmX#Qq-Ol{RnXzsBDej|5@}jATtIu**u2-&d3TEan%$FzPdyNiSv$a0~W> zbrs)^xLy}(;ZGdS1=fWa3JaME4jVrn3Ft|(D*|*R@KJm(xEd$#-iPHbMs{G|e^kbb z3L<1MSu~JQHBhz5fDr-D4r#n6V_v2q4*VBQaun5T=N|(X&Rl;D;))eGLf1BLFDz$t zNPG(o+m_nCic3Td9T-RgaBw`hT0A&KJoZFf5E4SnKO#6y_An@l%U#}|HIMIun>^Rd zV-q+wMxdh*ShzYTGsR*jasWh8ZjGbYlYul-rIx4`hh|1!$d+fPZlZ}onP`c{UgTBe zKDkdfY%j)3%=15+js2lRvi6D(5Ut5rBkQVO`V57up%q(i=9~`U8bG=9p`+|(V}jb$ z1Gd$A&KIf8J?~2bTX}#+_M#--iB%dVhG!!AF&c~sj zELO7=*8Xgydgl&mV_1XN+R?-PQ-hP!+yK1V4M)LEj^*qacO%_f18c2uO{v+z5$Bx0 zQQCvf@}cEl-Gk-zP7PFWa1pzsh88~iFCPN7i8V~WR8)2wQ>vO#S(KNixeJrQnIAKL zxMg0Hb&FWq+2tw@BrHY?;wD6Xy9{h>n^i*vMDMf#z>|69OMd}%6SLyui^lbi_2gmh z2>9(-yhc>B~a73(-HN^7BFztS3zKcSi+L3J*zZVH)HNrb3}O)e>agQ!n8lRRNh z(?yw>Js#uaKy@Z^snvd5ruA~+&FdW>7k4!ud8Z6m?`+VO?ZsAXArth^lL+6;6jH#6 z7_@iYl}(Q;T}$Z3myOyD-kDqn@Ilc9=1jZLfqSbRj;jvpUC_tP%j2`3@GA1W2H+vG z_e3{q$z6k?ygW-=If51vj-=YSzC6vmAAo#>ViR2w%q^;NDQT+ob`!CrEmHr9I@1|k z!oB{H&wJS&Q}j4wNw$-Y5V2veaEDf!lew|m&Qle=@4 zgf$#lML23&LWUIOa|KMrZZVRSN(>Y4n@bS%?n&M#a;Qcy+tCyTNlN~}KI*J|RT&VK zB{ySX@d?KJ+|xk4Ux1PHcxZN|14A1Uy>41w!`w`R*0maj9^=*TA_4-=8D%mB(Vq7x~UOgr{m4!-px97*Y@Rj(LT7ESgG~dwmL^iQt-&L zn9=Rw`s3qT!e{KU;5VO>!{hnaYaQ7l5Rt&VcnFn_l=Mh|BNVzd@O=&!_;U;@5Z&e# z7PL23R`?V=|KS+9dIei&#-nuN?xyhVei*YSJFWuk_iJC&r(mAQWqq4_dhlRQl}P!$ zNzD-ioYzCF`H3X*z=^g6^1d2H^1}U0y$FB$NXE2-Z}_)##Tbwg*s>omwo10d$`U?; znA@zLNi=;ytj|S(GQQrS(=7Yl_IpX*3O63K#pFKC&VW!QC+*4B)|Mu2_kSz~LU2tx zP3TTM_L~J!2R=sOIDcvHLf#r`yy;)@So`ELl0%VWFhf8fFol{b-SW&xCEOPrekE5O ztahYVL7)A}hgL9aaD~-qZE%&rGoRPPRQ(N_NjUbk>b0Y&#iJq(Nob4F4jNQ%F(@=h z7M@NAQ-$5o9f7ffZ|bkZe&)J24gZ54Ks?R3E2TXNMzkn`%Cr6pU;|7TCxxY^ zCtJ0V#~McG(1M$TfQc(GdT@W|0z?Uwwu!44-2f1kDSQV>oH&7LZ%2YiV-thQ6-W5g z>$TbYaiaNQ?jyBP|Bqm=tpn4<{h02oth;QLC*mU*it;8HKSjJgck`+a0VFBNcbfGD z22Zyw9Y}fPtSw6goxdk_jwi2`;$PoI*aY%&VUw$vJ$yC0tW-%Bi<)qWB!!Ulw;usu zdh&FZIs&;;e^7ViPaHr@w@Gr!o47u4VaIVH8bLc$i&*O>{BWtD)pe^{V)SBoh_`Pp z>fqZE(}c5H3}6cbcTovB9&|weQ>y(x@ZBJkD@DlR)~pI7gpetpXLZADWKS@P5u0__ z0fn%u|1fUxo$_b+G(*0hmwaDjb$P$qUe1RW)MoVXa^Jh;vI&7@t+D4Wif&RZn8!m1 zS+lA%d)np!6zAcHZ5-y2(awBe(tPH!`xA|ZpUI}3di2{B)dr+kk*KB#!*A2n*S_w| z@5VB7XN8E#hDsnNjA2@Z6HHiSNG;?tG^Sb-nr0Hke_EfDidynlbi2IY5~8U2dzwS% zJOwT1l7hT2>FlB5z*>jj(`6Sdj7xb^!oWLSdK4U9&-xpEjVDF3{ zO24JKt6!0+e7u0_6E+PaYy_;4-q_Pmpy9#QHvm(c2W(&!zotLYr2nyx(0h2_9GK5X zKIT(8Z5zi0Sh8Ts8jTiYm-Pq8jUhL(E!3ll;LH$~#@xo19KrTfCL}Z?*dUqh2h#50 z1;w@&nIT?7ON{8pG5PcOKuVA}im9?aUp{`WVPZ594=?2sP`d{-NnJpZKqY!Sa)m(t zF!2ImFBg4Ta%n_Wl6Ss9u+Sv)4<*-B5p{-s;gWte$?s+g0}?+IDX1?*sqr4)R^S{F z5Sr_f+lM4%NTxV2n}PppEL{6gq~f92#gC{6GMyw36jAyCzQOLz%-VC5@OYv3e(6;7 z>|tvCGyQzKudv0T#~ox;uLo#p3$I>6|)9R>fEI z51h!YIm*bso90GaMl5kXrQW2@>j~KSA@VvJ9dA$L5WyR;tqvK3G&B#W&uQ7bF$72t z0xemf^!1%wb755r=&`BDLY+;0O&4=INuqKCjL;NvB{Ei3!weF)@UW+4$V#m8AUoG7 z3~bw;4-YsHCQJo}*^g)! zAICLoY2VmHKsH31#}STo7}vC||0w@#&6`2)Y2~`XHvdiY1+}PvU7l|O&^e;Q9&=E{ zsX{m6(0E413ndi!H4FXhxkL9U_uIH!b{XH(pRg@j#-UBmp+yI4Ft1Mmgbr_qwa!rv1#U&aY7PMbpC}ZvdB1RWmn7(=KY)_?YpPu2Yb^>XlI_AiX$~9fd|~chljoqnvE9jeP=u} z&+KsmQA8jk*cU1_h+Ffp4rZ@bjeaNQUGPvw-4w7&7eH4)4WnM10C;WI(* ztqMg7J#el(no)Gb&KG#5pmy;K&tEu(uHPO%N&6OaMgwvhwlNI4$b>AdL401E1H-%d z>PF;ZvIsn;nCsopGE@H1fK#F$(i|~mx}g~8k)}%&F!dH3L9EiG_cpb#@F65#A1Nps z9jIR~{G$tyncs?1R1Gi8aXLRe6h;xY9ZxW8RXGjHq7K3Y4dwF(4F`w7@Lo{~-;_Hh zk-`50h|$kqesuoO5X^}#TaTCUtd{>2OmPQqQ` z6bywY|0MG>uzZHZu#XjH3T?iMMzx;X<6RL17{?%w{nuqIe}#(4(0M_c%OPDD#}Gg< zev)Pkk2)HsKWU1ehMqr30KiZ_af%~@d@naxdOb;?KuB~P zV6w4597uebDKOlTtz(z^69U`JOW|0Wfpr%NU|G!y=q8YePDnk#^jGBM=imca1O_dG zNn-hiK{R{ynR=2wXHYyx$>;^)Wp2k{@^HO9B5T%Z=JdBm4%QNL@%jnQ00fv5%pt0O zBq$aXADb7>Yx7vWa)(?PmResOZ~zKJwYLr^1eKx6&mb5YAD*{6E=E4p2VzLv+U$%7Nh8Zl2@-_y$CP*4J#7$DT*uT8dG!53$ii=RAp<%nEYiNF zq;rtLgf0^kY!kA;2ZF)?F*CJJ+d?>n%A=x5upjz%rtuBP^nhW0J@mCg=h>h=C}bt% z>A))NvhzirBKr=3DdlKo{3_rJFxpRCAj8?#+E3m=Bw5?}9(BBti;W)e*Zm(l6$wG` z9^XI_MmrFXm!S>>CFPs#Ijl<-kn!4u#V*R#@-iYGy_G<1#D-jUjdT&!+%G}`DfP6r zXBKbQ^ag>4f5?z`#-To6Suw&bf5VSw(4NMq1p?_WIA6??t&m&0RkR-B>j!=P1_{q& z+tzs}&mUa)STIk8@n^Wok3zGVJb#h7Z3C%1K9K&*WE#+UEmKYeG=5!cVZ)V*kSHHd zD4_@u`yRqla{A%IK3&8y&Y>;)x>QkWXwiXu`P7mZCH8mtG7PuSEBdg~IM(-mwiVLU zVlCR}Wou2g-({0PR&Cm(KkQx zixlxyXYc@|BA~|95MH@3WGr$mE7;cs9}XYueE&%ZIKhyCpiAhnxW7S>W(!7S-ap{) zI8YAUb6!4FEWc1Cvsa1!5)eu;W~I5yc&UaD?cg*Dn24)F#1?Xx!&argJjAHBbldAV zT>`?hUL0pKle>^8ZuYXEU&oHJAT3JEc2;)3cTRHKKVK$Ex)K<8KMV+L>Jh zc^K}^(cg}#j$D5-K*cDrMG=)I^zx>!asNIACYuGugu=aFq z8;$Z+2ndfi&(_kcGh7MG>)C3BrM*~K@BY*vN=|(pA4IF!`AKEhzOPiG{7gLV?58d< zQPWC=j@C{&nAymM51Xf*3|u|dmpovs(gP})sRo8ZHuQ4a>_wd(ftIfQ_m%(~l#?*Y zf3y+*Nxs325=F>g46*@fq34bVhj<9{myGGZOIaVx<9sY=E6YJ$wRm(#N`}J%kjn zD8VnRuYt}Ow%|j+)VLL}Xin)`foFMzp$8o=Icn9qtDZQ@rrEq#c{0NYw#H&3EkY}k z#xl5Q{{&0bxGriD+qojxIVYzNn8*4}?(<^%;(4@kYTF|^L^3a8S!(L8$f=@|Z#XB| zUT-=|)~;D3$c*Z^OHK0w$ycs-)+-8d7^m}mXhBTT|5j-sfeXC_QH_tSYh}~x;n7Kq zWCkU10-l#N0BzZgSaL2Xn?7{}7rO6Gqq}2Rb})&`6Hsw{dr^7KnvbA~G9ymNMc( zcv6)e>SwW3On<~@RUrA6Y(yQLYqqz4RQ*192#uw1fQF1E>QQAiliSMy$NL)cn6is^ z{CbJAUm}&{;mkfix=V@KAQhsw3Mw47Xwml@zx~NqT9BV%Xtvh&E7NcTa> z8W%@zGYhENayJ#P*Ao@-ZC`P`HyO0bTdzW{-X_y@O3&){j`eYt z(5xHvm=eLAl}Qy{3ut8+MdtUNyFFap`Gj8?Oywu7)3^q6p9@Zgl-+$_X>-Qc(=T-w z;JAR|G=ky^dZ9aKPPe(P&N(-x8rxS=%ns1kxrS|g1v~#3;vUF;%`Z6>j%~R-L1wwO z>~7~NQbH2941dvR{xbHjbb4h*E><@?O85K3m>WlxW05`jm@}0DYYU3*) zwOWI0+h!nX$7XU&BX0DpU32Cr+3RtgWc-dBa^yg_c5CK%Uq%P|y1DJJqc>&iTCYeW zt|bEU!Yc(nu{-MMVwKVO54M>*NTxvU%=iYW?SrEn5tHU21=%M#j?{=*+0^w99yM+GsB13l$H2Hs=r(o; z&h|Lhz_@DYH+BdOSl9iK#jX6BQT|~p240!(i8-3gt4No-6A%lR`rUPFQ==B_0`hG< z3q|&jT0&=~SFAZ=_Mn>re{{p0bI_}7a3mVIp=7sbGp~Rl7u3XOxIxw{@AiS<9o7aB zj_Z;rNR5gd=5f!_(IM?3`6rxXRnt|29_cf#{EHO<$(}o_Y6)xRWJ+#9c$2NE0*Vun zyE>h0j~JNnv>G@5buFIrl$+PuamnLyfn_F@je3FB^&HG&)s1iin`R#N%jy>NkjACw z$URG&ixut4JkrKChBgm$+G&)1T;|!v*G%v?bS&y1Wg&6aND#T%bNEK<8s^_!uZqtb zHS?}=Zs7{NroiamIRasVU2_Ug!Hs*sh z93PK)7JUR{(x>RsQ#bhzw2iPX1}u4aW#zhMr4B2%t`;E;!&wOE{pTGlO&MM)=l&QK z3jCF7M$=*apu8Pu3tN^d!vXEptKlNGx|lMdnur))``$Am3j5W&$x#eI1Us^Jmq!~e z;5h<$4v3wgv`UlKX^5#uH{fk@abEK;ua3_aUmKGqw$!+y2~#0r6}qaVqFy_wpZpA0 zZzPn_j09}Q^=B{#b3QK_p^Kq-;G%oi7!Y;($@!tin013+f_wgSaq=V?HAT9f z@+x(@ObUWcCJo^_n}%SMO+%3RhA|`{8)gv{Bh^TAyRaba^v!wpl8<*@s=X!|0ItXa z_2E{bA?9}JFDm~J{r;L{i(qU7ePz|^VsfARStGKTLiwftaJW05jz9};HEC)D)O z_D{>syi$|j25vt692Eb(Q$?v4lEQM2I?^L*xZ8}t>j-I~nI<>vqBms00AYAPA`HYpd-(CF<>jP+WDjXATW}Y1YeloC4-uF=pek|zUGC(<~{HTe6bH6_@)DonDzmN zapA1O!+u;mgLZ5I;)})UsEXEPGj}ATg$jl~*g#P#j(sY6{S(CwbDNAcmD*K0iBp#N zJAzSSd%m_E!bUfC=(UIP>F;>UDoR)UlyeFnp}MAdCK*SBIj@uTr1nBf(ihwSO+N>t&2!u4Q%48;U+l0%#2 zicyPEMVP1RX&at`IJ6MD(xrvMFkmQ@__~_Ut(`vnq#^_Pz(BN^Iao57(M> zmpSnZ5jq`5u?L)D;z$gxXog#M0(TP;b6)h~W7vt90D|SdbIfqb5on8`M0TZr;1vY2 z9&)Wx>d;`TA>XVLhoS5t;=aYcGaWN>W}2q*jKzdYJuqi!_zI=%Ut7>c=qKgaOAa_1 zS=KwQ6C=Nl6ScW=haH%(gFk?CHnnAb>-o?*jn0w~MkA#$b{6}r?62HpXpv>ph$Y~O z>zj*%R^zuo^ih|+%jE;k8mFN#)%4B#2pgqF!qr3 zQ~WEsj<6^EOpMS@)AO7fKk%@$#fkFcf<7;>YZd^dU=tJ zaN}7;L^+x3%#y<4EIG-QIsidsf8&CD+;vPOKlME3*ZQ* zLX|39o;M8=9gD^zi{bz;NC1qqVEfk^0#L;2=ZM}9t^O5}MB0ty4*&@K@mI8Y{!!85 zksD-y$v&&)$i@I5%qS|cT?~)Tjt{{4Ls{YE6(%Hpd*LnvKPsa^G=e`f6SM!1^hhXO z25s%v<|YyrENq4Vp+z*VcNgAJ>-@T%ViLf}D9kAJZkq$vzQXTgHJ*N8u}m&Ox(>jf zWUPdUyWWJ9p_(yXvM2G}If%+nhKT%1Gt4CH{Ysn?YEBt)B?&zDjlLc(!WA3l^$yI~9NW;h2xm4)_4AbF4^qA>`=AiJ| zmEg>Q=#V?LzBy}zsS!$ORM}O-bM>DR()A_2#`4ZWG3&w1GB<6N37vrS9m80)F;jAi z7m|a5dSV;t{F))xo+DxPh{RoPiw&GebQHgPmAw^azFG5&s=COS3m ziR4Bd{;cqmrZEPU{;la=_^4=HzzffaX7khA&C`3%o3G;3fjWgBN$&UsE$#G9z;xaN z%rmtmr`HYGFM)=cKhZx*U2ue@)qygZv=!riM>5wao`*i-F=yufppb7eg24Q-XlmzG4D&e3_-HN$@B;wXP6I(%98Ne5Vz6roabx@&McQFG!8iKZyM9Z z?WYGsJ!d;k?6xaC{Yc=&#m3&$Mx|EWb*@9CoSB8L`gdaTZ6|>BE_Ec2##@wJDU;BG zPRSV%PDXKDM(o+A9B9!ZeV)qP+!~AjWjr${Jx9T%U(ku7`bb34F4x_nIg67)V8)JH1C*0@V*8)UQ}u%csL@sp($mMc!s{ybkmt$mxqZ? zac~fsuDP&@7ae1N`;8qJf(G)P{uD`?a-zROTonML799ii-xB|{rUsM-XE^I!xHLjE zKh+MC__H;LNBP~^pEKgYsw`P}Vn{?7#cwrJN+cTeU0Me5XRk%ufmJ^fJ3Dk?`jjDy zZw847?~9L{>WZ_ao>)E}pU=nFv)k)XIk8+kc$e6hmulay_2Ie}(bkg{zAYD*Z*9e! zPTSTOml<0=r#~HbwISJCmATtDTBXa|vMXz6myfq|PcF}TTEjgz{P`cGT$FZN9XA94 zvaandXiMH{PA(k|tUT*T~|txwRpf4Q8NY5nYy+M3o^ckZ1q zS2wun>cV)bo!)V&9k(_4=W4fIquXb3LszTtiDJr^DBip*9AOr`=aV7oweEpJ<8w;a4R-Ci_tBn=I#Rmfx z9^PQqdnn#9jW;oBrl?tb>9C^!oTHFX6Z<|N#r~TaV~h7pA;gfE%N6Xd1I?XikWjW% zY(;~j4q?b}2h%OD7J9#(!j|FF&7A$P3(y}AY$v3b4&pKesC>*3%*a{)@7(feA3&rE znmTukLD%SCl`@X@lap#Ze}aIY2+))~Z(1 zw^d6~;K~#7FAYx?u5K>O-FPsfUmHBya9lDWUon~_svJqtKGX~2=X_7?e1%5oqP6?d zwFN^)P|d<<1A^Gax4P39Cf%Q{&1$>wzJbF(;kT|9<>bu#l^QlY^;oo3g=Cv8(?hCl z+XqRTwmO2^-*q4K*6&ZmZzFR@8yg!FKAgl`&h`S}2n$IgXjPsR`NyYU@A0;Ke)ay+ zLljHz$(n57MwwOe4AxQlc7#G#SPfY+1&y=~o3zH*4V^Lt|HIff1!vNA;f8N)+qP}n zwr$(CZA@%uVmq1GHYU~tC*S2cH|M|UTJ?18Rl9a|Rd=s?@Icq}@n0D%SNw&pwU6Ee zr{x;s0niCupyS7~mEJV|in06Cw)SJoy@3w#d!5`a2BPrZs-%NP3{vfEKR9%3a_SL84&4%LXq%CxJd|z(MvMoZ4L%nWA16CWq zj4uDZb!WoVlJS6zH zyDF6qeDG9FmAZ!7?AhtfeB}n4-m)l-vaKPV9x_LTY6-nxt0bEkG37ltscuk*RN7r7OZV-p^(f%e2;u+PGW1sdXDTFF9BKl}qz%>pLV; zKiStgFt{}&FN>UF7TR8`S41FASG%HG#Iia4CP{;&|d( ze9zT*A1+L&cp5-5d?<%!QJ-{mn>}+^6&EVsl&$euk*g8+p8M_`<57}0W8E_-{`@=g zmBIJr*V315Hm9F!KDT2#t;Zl|R_$B8d}F1On^k`Hb5$!x45VR}1>Uyh8|va7T3dnD z;amOe@~(TtUC4OEwWEGc&W{6H;C5@x=Tn)hTWQuf#|p~-Q8{j|%Z}8^i}_rtexp^T z6DeOz%IZyFYH6ga)yvXMElK+-LMSdu(cGGkUwky@*}c7>?fqluto+XDAzhBI|FNd8 znJi;N2xagg{4hs2b26xEZ%5rS==JqoE+Jc@O!>&@tHI*&U0>U8$Lh|%8pp5y75q-A zlGSIRQMs`ZN2P^k4WwsP%}%6wHZaQ4q2py=>yusAB?GJYh^Kg3r&mr{3F6LY%l0Uq zX&<*iEhf|2kM($Sj5l+V4ybBGe=jO~Ix1L%x|(igokPI*?b-hjd)^|d18)F)gT11B z+m+VJsU1^m4C=wpxApcY`R~cbP0vgWs{k~dSgo79xEPJ01o|r`SI2X`+|jOR6{%T% z^Ko3yZnm7^=JC$?8oC5ijY)8*bx^C-cmPE`%|$G3S*askzN)qKYvo{2@X(IRz%|0< z>@)s-L~&qKS?es`I?|!qP>zm$*e1oh&w%@&=6Vql#Jbds1^P@}Jlx~@TaonG8}5T~ zp|g8;2Qy}CnataSa$70EG#rN- zH_z2lr{0PB>iZM>w2be;>ijk2PxsSRr?&9ZiT{lJ7mWLTfCbuZglgF(5+L=mqpc>U zQ(w^4cegdiW|4g{c^9?!<MAOb53hrLS$D-8z- z2he0J;j@Sfuq4^%?$$44OLENK%9O@Au+htw#wAeFOP6Atq*vXGT$7tTx}cnoK22lS zM!6owm)qrT_Ez>$S0-UctS!%_=pD+ows~B`n>_aZ+`hMnTM_MY0##jaVb-=&5gG2s zwSVxpjO$2ZU?7{8e%W9RkBu1({8sQZU=#PrvhPIrw<;y8Sg zd6NT~K5rONibe>>bK|K&=r`3jJ$LbgFwk$SvPQD7{Qcx{!+jj)??%RkeGp#u!CEK< zdwr~Jg2=O0!7n3ta32%tY~$+4h<&gMpEuCZ1)#rmX+7aUc>f1p7Wy6?xMYA7SqZjx zTa{r~u0!xv+7LbAY7G}|X_7Q+{z_+2;~+Kpmv>{cH*TVgQk&tKS$D z6)TGlc|MJC2$eIq6mgPZJ*vE|1g#J`mbg8x6Gk>DcBm67RLBIpo&qCB@XoM%@OUez zsq;{%a`v8NlEhZ#{JbG_RvuU^&-@e$Hn$We5lTXZqggD;$W{!fG-wDFeB@l`pQz1Y z@@XaRp!YT$B-{xnzXP%)*33+k#r`WCyNhAI~uNnFa9 zYk$htT!%^zi{p&m1oiU3K(z6#sxwHLaHfW%%%r!#!;CIn2HotC;|gp zNJ65TDU*OTqDYXXZRZyJi?<$daj8J&*@?_kVNOJW*FaDrNQEH7)s=312Fq~Wi1RN+ z|FG9$sPv=HBWCetb;MS25kC(mdcvx?>CGJ*kq{$CNN%d_=@I;iVyycB;~I?uF>I!c zwlc*I4*$tAHntWOnl>h0l2qLQN~9D}ig3;>!=7~m+4Y!La6*>E3L|1(mlq{QA_9Vv zx&nhs*(5>}6|HD=6gv}^t@KTH>hBDxB(jSD=w|)|)+$2YkW!2B;V4p(GZ_AnQN*r63h8uN2N$Hk#)MDc#gW*AA%(}Q)HGCa zin2{pV9es;XLB;6|PGSc0 zWPSDx0y1=W@|ynG*`WF^7xvS)_}UkF;y}lHaF8fIy;o4@XZtcYvrwzz zykZ^k>Ile4wooA-R}0@tA9U+?#EKWUgvPO)r;DXOQaQ zG(r*;@)+Ks=LzC{yS2>9L3FB`Oj{fn+jWzrq<#%)Qby%gODUz4b}dJ> zaB3wfhFG_17Y|)tylQHxv^MZG$Qp-6Ayj^n(z*BBXY*+QpZCsUwzW=3Q;p?Dmt>or zQjn*dD2(w`+cs+gJUl%;eJ(WmJS)wwsyXi}gAUlGfW1j8_P2|H_!QG%~5W zaic7~q}AmM>5md_3WKPb^16J?Heb2>i|hy?-xAQ{inH2kTbOEk>>S!^7%zI898;af z3z7whN`yp8mg%s9ujlufYK#a0{3lE%{ z^?Z^PrY2iy(vO1-yu_DG?I~exJ-eM7`N~Yt!^m&Q==ffqBY(#|mb%}ruZsz%Nwf2- zO@K-5VqGB-B{N2i2HK9+Mw{pa)P7&)F1Mh42p>eo;k_j&;Ebc##+`CrhnZZvL#B z?wg)0G|nQKau;`p_uGBj@~T$*h>7MKYNhFL9W6wXRnAR=jLU+06E3i&aE+jt z)I^Yb=Wfd_)ih`?#j1^?f5Lz7+Frt8E^u0-X9B84tHY^*r!8%gCcM&469_8_1l3jL zR7eps+b&dq0fc;p=;D8qsAPfDCSB1hNvmimtFq*P6o8~uy~+&{v}c5j!LfxfCoLn5 z>ql8qlrGO{#S(0TxFtvouSYsr7aJGWJ=4n{h_KY`gZm8IK&&~?uy>sUds?@S$*~;3 z4BxA`yRkRH_#!B2k#7m8f%b9E`3!6Zt@Wpx&Gpmzp?Ynio11`KMAw5)#TJR-H8q9L zf>;`b$VaXgyk!4!{n-2)M7abmiZ#>TKi^p@+ilLYT?@pMr_z3jtw5-p?%!>Ov^yx6 zkM&i)d`=9QFi%8#GZ`gFs4#cx2KmL@9f8jCM|<;WfLSzSR}<%-;=yDA_wFJ)=7PQs z$x~)O4Ok4PxvC331e@_&5~Wj7_mBg-lT0RQd_Rohf2aJ$Q}F-yblp+VXTW^E0)2&$ zu;U9l9TRa2GAJfrzD-z%4}4`P&L3MdvG{ivmu~OS#FPL1A93&tg~Z6Z_WVeyMBC-M zJ?|#cy744$j#%3mYU4R)mYk$%iX$Phg)IalBB4_;a=n(Qs$ZhTuWMspsBnK$XYg$w z3+Plci)f2%;f@*IoCllo#D4SXlP@+E$;fAASb5c8oYbhoBE2&Ps%@l$SQ#PHN5p(X|+}!wUDmPsF zZdbrVT>eLu#G|V9nj7xP=6EQsg1^2jMa1(_C7+kMLT@9*-1S8J^HCVzo4vbCYKdy3 z@uHN>wbay}K*aZroj%}83Fb7ZsdSzE=)BtD%U$~X{Fv<3*ALuEX${3l0of;cBV{^Y z(kFQ{g~g{Smo7h-Up#-php}PJqWRx+Kuy?A|B{2@1&422CjZ+L=IAL>e8JlGuh$I< zM?QZr8b~6-9w6?DpO>HX%mGa}6k9eSH)l+JFE<}w>pPNcVGnVHoS1!HzVMvi*W;tB z>GJ)Svi1_`EdcLuFHkmm0sn^j9_g$@r%2{zckI_c*lpw5ra1MMIc~LoAH)2kulZ{} zA4H^wzg+3ir`c2)6{z~%Z0-~${CW)Y)2nNDL}YocI@Z^G{u<6kEXMoJ<@Ee(A&-tZ z-!_e+ZDz~`VG-dm?d+RZV?}G8TPuOaZmU^&vfTNRBG&}j9V5T=S!0N1$H@X$70uO{ z`2jlgLHF97^=FGv>4;3V3P&wjxIkZI6?~xm)k{~njI`F4 zel)NQiV1<%Pc&;}L)Abfqf`&ARZ<6nK{6>mMN{29f=1S1ol~`p+JVSxnu^TfT}tR4WX?nz*kh?o zLs?t^-7eW0!Wek0RH|2r=^n!2TOGzR#lu%p-ftWun08cm;Fa;DG}Ov6!z)=oTymx3 z$f%B-3k^0kwN-8X!vcK2wp?kR_Br!BstUv+xrFFlT$sTs99Fi$m*Wsz2@ z>wIg`$?rp|v)t`_$YOudy{G6zwzruh*Sk33cIO8;S{~wxV)W~c>_Xl1Z7#pJ4}LYY ztbdN6rgL4onnKTKc=K)=(E6}&FU&FtM8BvQQMg-Yzlp!34`401h7Ts&gm>|X$hk#2 za4t7mCsCX=_tEr52weT$1dHv%iVF$p)_b!cyb_St#ZxQKS^oD4AN4{WhqQMIRZaFP zKln48u=t&{^v&aZ7X0 ze7+;>yw1bW@W0dx=U@}~fn^-ywLHDQtJ>>#`+TpRTL^O3bTu;?Bs}zYvI7th#5NWR zjud@#ZxNe9JsK(h7Il0PSo>kz?qgCW0^2QCCHORi{Nv(Y&L9rdk*A_NJ@#^?o@(pu zYGrO!*wW14ZDY`@@`!X9ElKHfRT%{Ob5>yziZV|27jt=7I~O?3rfSMV6{8}*+wJp8}jwFB}r zsOT%Gp$`yl_$xHar*gSRn0eh8At(~FQ&k(h8+m*c{N7u<9j+sj4yZN;wE*M&yXJ>k z?fw-cj`=Kp` ze~K3Bx3em`Wdq^w<-O|CF~EU#^ppm!HWxaJyD2zOsCT>MbMrjfr#xet z2jKc@JfNQ@76m$4l!(3&?96831r$H_C$3S!zJ6uGP2R-c!q$_guH)_F(4w~n(~HC* zUuxzbiiJ1Tkod;9mBwC~-c)gpyn#3fq$c6*^U$K3F@(DGG`g#;T6I;6F8AxHt?c6* z31j@i6Fm2PY1S7(o>?DJ0CVUi#K2TS=i~J8is*kf9#iUK8cglQ&^he#NOBiiSCPGIw-hNX65d{HBxk9_3u>oQzj`0k)vrD7`DI;53TjtsnPZ^j+)hm{+!# zvmacXH3e#_ET@4G9@%^?*OUrQbo`SQ%;K#-w~2E?>#WQR@qzFeV17O#g*enPokhXi zq7|H{j|pxM_VD%xFVhM>RtsBHD%IRSIJ;9qW#A7htQhvMAO~8;6efj`tpqP&ugK|q z$ewW&;>6oiv2b$%xeB0Vsgp)rea0=|P=QI&Bj%Its3NX--E)=#87wd@dR4_hnlJ@k z8Qu&Q>mxuJJ;EYo{Cy}3hF(UXoKb#wR4Nzv3&OM&AywG4qtOPX!U9ef!(gVD(Uo!# zKihAlQesCx0I~hBnquad2|ff7nks;qbvm#gnC+ggA?cJWJVz!RUCe(n1a;7uGyo7k zb-#pBITkj}$f1itJiEmi^Eo_oAH;QA38_brtaTKWBX!&*sF*}bA4;}AD7g?>hI3YZ7X}1_`rIfg(1|`G0{)!nLH)QD2XG!-LK+rP7KLQNtw`{imjF5%n)T5hc#1z z$s4YP0jQiS#0J@wDYfw=F)qH&jI)$}iggM9rY(0GTV>Dt7Y?b_ZBH2YC%A>+K zvlw>}5{a};Hl<}kA2;4Fiv^bg>l9R3nl6P2SJWj!QM@x({7o5JHGVHSNg5xt{)C)e z8pTj#{CnIr52rb`d{0Fn&JU9Jq!dTJQzR9((3_Gx6Kg(> z4CtkC_BihxxCdy4RQwKNK0*{timW)UK5Px>ie?9wsVuf25Sl$05ll($5ON2?Ec+mx z=h>vH^gu}9h^5OYv7-;R^CQZyB4B1>6r=PXHy)}$^m5Ca2&@i@2;5YxX`^&C`4B{# zIAAbROnc}XfZ-$f7&p3j8Dqs6XEFYUJW&bLmejZb2CsVQE9E&2{H zVGfFVYuY45WgJ)+ueEy`kpON~^<&2sLg@XO|f!*G~!vx7cHUGk2 ze4Q@@r>=X=N9!4b{!JuEFxbQU#G|+mElw~j<$nyC!x$O{9kQ9=;0ybnaXEG^mJAgX zTyia!oFudedqyuW&eU5Ict9kXQ*{uy?q-FE46u0UW^SK&vtrlf;Gd^#&Rmui_UU!G z_q0rA9y(9G8@^tYIKkG|?(>8HZF?-6IKLO(&S69p?HlOytlQa6N$9>z>0gZay2*wx zc+TWHWOzJutQ-V+3S*6T#lF7z*uXKZ zK#qL~L>Kd4!sj%<6)=w9AVh(7K!Ae#XK_t8@sJKGrO9FP)ztfieME=B2GI~}2(=HT zbc#_0H>je-wqI#@8h-qe+?z$AtbsK3+2u_H$b9V(9HQYx2 z^||;{5F*HD&{j43#aI9gGoIGrteA<-9b1qdxa};jbY&0D-e_b32@e)f#5QJvr>Ufn z5RNf$q}G~sKTvR=-r%La>5xH8Wqd3BaTj$ADzR$8c>zrvt?!D!9naV2hpD&h>9UhVu9WS?BroAReCKt$zS8gw6f+XVmidV%K~F zh2|~5*fXys3A|^!g^Hc44Xm#O!~JfJ(NUG@tC;vDNqNJ*j|98E16hqs^k9WvF6B%4yqq0WMFy^oRQGsb80RB*W$G!8>?%$|i6(uhP>GU13AOJeSeIW6zG-Gr_sff^e}nhUPT8F-N5 zQUTR#BBZ~XGWPOPfOl2h!kVQ})a02sTOQ)bk3%ZR&lZf8m^W>n@_6(79DzW<4dqHG z7m;V`{hQ9R&CGzCqIscVmZ#ST^t&+Ipgd$fHZJaVYYk`YbTr1)6aOPU7kd|wGQs+$ ze|XGOQh-VddxXNIh{wjMX*>zd2Rq8hY2`Sr2&)X137|%jRWcT2k&ZK*j6Jks%pcGM zD5c6C4!o{qlBtPobT)p8h@DFb>N#wZJyPP5FF36IiX3s-gYa=V@sY?UNu6o5#|c3? zDriE&nS*`Jb!H11$Ztzn&y)i_5|B1F7hEk+Ft^Q)BhfK9`3 z*#JlPE}mm17;y&g-)_AoI)c7AI@{w)AT8Z;n^Nu@a)ZEk1S5Sd4T^Nb^I)`rFr~fMRER zrQj0r;{&i`6*&q~9wKdICwJzsvbS;Ja3F|e1A9UweC$y1q5*v&wuJ#El|r1zz?wW& zG3r>7Uc{Uc(RLf~5G+Z|@j~AH^vq#yupwBJJ#ojp5~(;W=ic}@6u<=Kocnr$K|lH> z0a$sZQ>71b57K$$kF5JGs7dCNC>DS+3O~auV(zY8JL`2yHiUFyaoUGiKMnSR7prMy zxkNeY-@853KXWNu^AP86mdrBdA&`DF(7`-4r3iUzq1H8aH8!iwJlnrs$ot<7!CGDn zK1@Z|NTD65hyCK|1biQTBrdi=6k4i1m1AYKxCv&J_n#o2%t90$F?#Qw1F4kGO>n&c z;%susNCc`g$zO5#k#G^^OlKxz9ZE$Kfl5F|0y{Q7@=~2>2qd??XF*9Z8ud{gk-ufv z?*em_Fk=IJKI=tLh7myH-MGZA1;1RaZsDELRPZA5*R=XN5dp$(afhT)Ww4$RSM0E~ z&?IuFvT)f4g^0EoQ&4f7JZGf8-=7-T5| zn6(Fq1#qw~cqo|+g_=*!Df(yBNIpklEZH2lAK}KL7^r4N5~7a<6!lERho8wQe*`}0 zJ9t3^h9H*2QHIJRjkC%kWc{tr5hQqa@6i!ffl@i6EQ|&xnQ4xTTV5HMBT8suKrKyZ;og;=pjQ zScq{ryi>yq)@4QU^(Foe=7rMws*&H_of*hsP^}ihg={uEyG*_jt3~6FlhKtq0p=lm zWOa=w&LCYt^qSM8BC!Oa45NlKF={R9?36Ks;#i2DABGDC{K4z(p-aa2tqA zoaxt8u*neYf>@*X%>10m>!4d@d&4dQMkSQ*CZpgDStHGLR5u1i`qrcIo3bWJg5w3%cij&@xW(0()GQXBJx!CE@gQi_Wz z4FI4t)sNr>%veBQ^<8YZOFZ4YP{@`6SOpS87o7 zL!tT`9z%1~LY?=TDLo(!i%Yy*ohiGX1YFJpccywU%SXl(2p}Jspv)=y0o1bNhW(TH z7}AaY0f=yWJhILZdvLaOu*vD5s7xR%0G8O?Nbo6h_Ehh<5LImMY1a@W2w}tgy?A-U z6_z#5EP{f}uFhZyxiIu6`y5U5f$72k`d>&QAVJhhzC_o?xueahkS=vu+>XhSh9ze$ldXrVB}J4w?8?ZZz}O34ZJW1vqg8H z5S@OGbB6uoh3jsoERMrBJ-avTy;uIlR zoD`xx^(=@SGUSH7{Z!H+MT@z2$1)kS|E>a}p)C>=Ii+c!5;3i19T7ndMFJSNn*t8UKn0?l65I ztD!>4ewU{hMpi(9r!IoBFxvW>3okC8p|%~Haao(0lzBrlxa>{J)gku)Dwl*4Llp(( zN4il$nir1ZK}o?E$tuJy>6`Sbp_rCJm7)R&->!cQj#xQ#*gmM}3}n#p z!jV1_3_`wMtnKt0^bQGn;x~^4isoT{sgrES>(LtN;2ETKAf%hmV>|Ka$F1S@b&6eW z($zNUtFJTckr|E*Hpp3Ky4zB2(V)6Fdn178X71*|ADD#Ga!QKj=%lX7OODytcdlHY zoS4geluMp_L@sYN`6arISo@(FK@sR;U} z$n}Ken6?j=vLvdN{t!{>UNsGIY3vr|tOdMYN7Hxo7j7OuPV%i(Y&TjD55;eGbqE!% zuU!EjRZJxN|DqUH*19(YqBr9P`A{w4q+Jr$w`DpLzaxmvsXoIeAIelQ`sBJR4(Fk11^9Civl-KZrrd7@H>gx|8Uaq z^se#Mxx5xmelXzLF64e8SK`DTD&^}@atBfBhnn+~ORFa5JSWJ{4HmC%brV zI~3571XJr!Ul*i-h+s$u<#NHnl6gQ<(=H2!*FW25cO~%eE#cpb0QR*3NVA`H3rR^H z<|Y%*HhxGQ)^)S5i?mGn?lzIbWh?gN(SCD53$rto39G@P``=r+(^hZ-9Xi|!?^>kX z`~gNboTF~N4Wgd(#xj3JXyH%Fj&}?OkJETu$`5tia;C|k1h}R?kK0F+{H@>vH&t4DCC|h-(k)DkKMCvJ8+|Cy&&CPB zc3{Wu>-BC9D$otuw;{KcM0tKQ2Tk>U*gFO#+}I8kP#$r60H-AWw^)!+vJL0g=@;7Z zK$$ga3yrpn&G2%=x4ygmih#P;hw$aF8Zq}b!1v3!eSM7u=Vf}-ulcUu_9`ciV0u)f z`L3dMbE|_7ZkAp46>>y^l;8LjC?qK0c4(Io?)5AR!T1h2)K+lJW@c2zm>mS>YfJ(9 zd$U;IFf^liB!YxrSLrhlB_M#26CZrVKIOgqI@6s&fwWuhAaj@lZxBUAD>;+VEk~R~ zVK|v@F$5L?1xF>5;=pya-LL|VJ(SH-D0m%zm>EhKm`vzY8QD}gSXMF-3aY6X%w*>} z|CKQPgY+(pIhD-r?R;E;13fPF$Wk$7jod@N6Blldbhy-BC|(>R%w|oDOW1hsD4!&y zy?Lhf&X=KO0V_tQZws1EK69E@K}tWeCdqeiW%b z#xsZTkj`e&0c4;QTq}-5p2089?aOjFcTWZaZuqk`>px&dH8LL3c~OOK`meN4v`D`F3~+@vmEv zth`?!%h>iBdl+T$anC))b5pUjwVS4|RVrp~*cZe4Wz!)czHk(KuXZD6bTb^YcJ;BL zwl{gGy#noNgOaP3hyu8F)y6^*pKB-TGbGliVx z-wD%Mcg^n+En2s@BfVy5JrivmOD=5_t>vmQU<@LLP0=*lsDt9i0DYG*0oq4{FGv>m z5Cf6^ioS#J5~fkEKolx>7bHRrHeH~-zvMPj@P)-GU8z+K55$#Zl2OF1*+MdIv(&Ei z^;%4}BHO(GOkb>S>##D5uv&jyR$NTOtB4=jm>4h}u6s$ft4L2PpEeS~*(%qvS_X+w z_w;r)szScdQ?;nS+CzP?2U_%Pc1TJ?i4ybU=a$C(35C?`3x;{TpDv)EwbN2V5G11jt0{`U}SeMpWTBrFUXc%z$FQdG zx}L0IMj$kg^@dxqs^F`<2jWiQGAXW^ME<|+3In)YadU!yf^CVRNy|Xyx3iFcFzK0{phAo$l3_=3? z8Yq57hDp_Aq~q{L>C}wyXEzqEk;D6YL;(kYA7W)j<YxNkSXxuhZ(_py>BSUmdV>4_rfo&cwd=V&P<1wLqjLg!E;FbKDo}b@gB-kmvv4Ny z-QTDS;`>leb{eqVIH}-&hANuc>x-Tw^(bLR&W<@8vCdNO!mN1|DOSv~@uydH*~R?^ z+H$6tA4mH6;;I`xym3`6|Gctm|KJ~4#Y=C_E$XH{i{zhFwnTVoYn1VU*n#9-^A1o3 zb)C?PP3lQGE9?=)^Sm0%atnvzIXibIhz*xU2gwgkg#-;%{MF`(VXLgf z!IFpr)cKOfB&mhJ*OB^tAlT>hoGaNQw~P@rGDFbxnkt|0Crc*bGVGtvR96HE=I|ScB*_EQjFkvTfd#a ztzHb-Yr1K$7cQ$2$JJ+8XhK^b)w3-|mV@!c>}IneXpBRUR+q(_GmOph}4Oo z`|k#OEK_5>*g>cIe5+nW%pyz;p(xL-lxPY5ahFJUs(7ytU2&Q)N_3xsa zq%-zZ6C`WwXFD!TB(1$k?{YH;%tY;YG@bcVy@W9+aHAq9-L0r1@>mnYx0OM?m~xVp zx_S$~RHAsut_{w;p+3M#F2pHXNpNEuX0hY@@VnRZ?PGsu5tKIykwaw%wXWROu_h4@ zvNi^JXD&oD=l+o1*C^FmMW9t{*QLaBW)PaaVLa+O@#1!X!k+(8*%FNy2fs1Vs_ZUim?g2OgkgiY(TRd+nl())v0;g04e zz9#|fjN5k+@WfYXYx?B~PPqCgKH|Z++$DeKV;=#M zuMxD}S>kR&1pwZs4XrS|R!b9DhOp6ZGR**3HWM^+tZOAZ3~ks|P_<=Fs4O_!UX)KT zaOVe-bqg6U0*+zp*og75w;cQY*+BnAgwSrYNjb0v&XPcB(0|9`okt%7I!_MwfjkDW zYZ&pfr&|nN=*A!Fx}hVaUK?;njh3d++1kaw9(n^M8cI8_Iuz#3pM8QXHjcg1ll20s z^j2L$@U_|-K#uG&coMMR@Dg(gyM8h5c`2*5UqXKjh0r?Nthm}KF)uR zi_TQ|*4R+3uB{MQN*UwPb!JdWu$w&w6Q<%c2|t>ioZr%RsjLEW>7q_66WnP&&V(U4 z3!D)e&t&&{l<~{Y(VP|#zCsHN^yj{dGYlznPlQzyh80b)5Jxdr2Gn6@5UhMJ-+_x# z7$%n<+jfmi9dZ$G`b9n?)CRrWAJ@HmuhVwwe3ZXSm)8`K2Mw&@R=N1|$kVaBx^qPRB6b-@`k>^3Be#O{Im~JjMKOuh3Hwcd!nN$hf3m*p#W!8D z>@_?nn{07Hapa|dafs2tzy|xiJy_pGNae2rmk{T*2l1LL<<0zejE&bEJfn{FIs-U$yW8Vi zs8LW-6?k@;?(i$5$0x=OlJ7WnoB27w^Of>cW>Mc%n;!sFwdc(;!tJXTbiw6sd^PHc z{K@W1&{yx2qWC$g;AE?J$t&fFt3Wtd-C}ad`&mbCXHr)`$!P1~y);-t)KTAe)=foSMss=3sGE=J63%cR(ceb9B{uakQ2p0LZa)iN?KEBEl|K@pz^tx1-2`-IRHujm z)88uz)P^d!0z31k`dAkgw8)P4wJ#O7=GeJGV=72>T!^Wo&^a4-K5c58KtlAZ<(l@w zj0skAZFa9oTpvBF)z(y+_+g`T_1u-7imgf4dd0eO0lJb3AETw4lnvi!b-1`3_J{OI zhmYGWYJViG)?L1(yW!4IZJmL%(R8B$t$g{*MeC)bia~$#n(nWRmaypJldJ++x$Zhf zoZU-PT_VjQ^bTM3b!}#(F*>jdPo zqB{Mv)3cxydw|KbOzP9_xy352DS(jo)Y9BcI8^;0n z(MCiv@@p(-*zm8Hy$t#hntQ{UtopZk+k#gH?C6Zcw1X_Iwfr4*z+~*-1noRHd|hgW z@gt1mIC6wX+ZCH#+O$dfQTH3)MPRkh6ZoAw%lk`QwTxNq-Av6$2%zXG)Dct&>k-si za$|LUp%hmOEti^15H>uKXm_UC;P%0pCStxF)+8#-IXY|8s?m=+Z8Vqz)tL$%-i1hxNE*}F;!mS5JZMAbU}s9#~WAXPzUY;n>&5;>}#qkL}Y zq;Yzwv>q(C$od|@rzaDzZghpTk7+-V3D0e`w>-n3$q?&Y&L>Y0(bLOzD_M^4F>b7jN=3iqlaav12pQf^7|wbUn@SmfPa$YJ_8S zq9fh(pt0=^!Vr{->S6d&gxfOm28U(15?*)yu3XOy!ZiQUCp_Al=ZKpCHh5ihU{vLQ zE$VbJEWd(sF6({uVdT~C3C*yV!ej`ZZhLM0 z$w~Ynh@urA`y{iR4i4(37dKQJbRmIgcX*W?sq1LjsF&plY4Z*#@>tbB^0E63-K6#E z{rbDo^XKJa{xbElp|!XpThE!SLNlZdhGGpxrYNh7Y>_uB^_)w=*KKf}N{O3`j80|4 zdrDt_eua8CjKo2OY%e)hqYT-xfE0!4(POlPh;D}S)hs#CQp{7txZ~a&D>(zF|463h{CniPz9AUcdwbN4)k4qEQp8&`nVMS)|sct zuzr!~v0)8yHch>Hi}$!Pxmt=FZiYZh+X?%TF)+qP}nwr$_OZQHhO+qS!> z-}0?yX7fiyRMn;`vnnJ1bIvz(Y08Orn2LhrIAfB$<2J(_awBFuV4wmsQqQ?_0Yva# zO1^w4$VX`oh5nfqe<6fZZd_9IgnqL+VPLD`GHz?(L+Ftg=^S-#oX@FIDs?MYmIQv( z5tag6;MS^TOM+)b6PxgLJf!%cQyTty`&yH2ncHP_qohpw*^COQ_`BjzW*fHUIHnh?W zg{^|lMa*g2H&3C_;{Ju&pjz(5vlx{P+LQfmqDbS;rt{Tv&dH9;=0J_7%SFHQonF0p z4UJi2rqAAZO{ROom%jTuk1IC-PH(uRg1TbsqgPXgNH>WwL7rN2u~hnIV&SlTtD>b| zP;TP1A!}gSL5U}2*5A+V&a~C>I2%#+oCz$Zrsfz>Sz&gMbx|Mhy*6@59Rj>^Aq2=@ zIdVbSO5iM#ALBCY%fhQ61V8S-?}T|{0h8092_F^(M0DL2#^HK!wCc<6o8aq(?IOv_?8QzKv?IhrXJx1*RzYd1IzvWl6Pua{*4y1)AFlt2vV|j_x@boyHM$?-8Vux$xLFo z@Acw}nDo{pQSl+#lqsEA51i;n>O;CSp+ zF@6dszIm+%of z`cM2G#*gc@XH^X#h@Le-z;KGU_LZB-b9j;EnFp$kKgwdkIb@e~I?&3F=M~BhbD!SV z^AI@oDFaAvS2*5?-;#ltH>EC)3$au(Q5+?3Y`Y4e*bxR8?c(}bkr0M#+A#eg#}R%g zcM0}T{7G^Un(PE1TzLk`98AfPeQ4#KW47ROb8oU{V-Q-Ky=JV!=v$()a)II=q(*Up zNx6Io^}+(9%BmnM0M$O)J>vv0`aNS>g!ZVE9!k4^lBme8U}~r7YX1Ye-^rWq)wIPM zdpP#?X8x?joAM}cXI%q9DYhztgYT>p6W4c12vODr-o_>e&7jq3)F@TX+~#heDl#^U zovYtZV{JwE^VtBW;<3;Cqx1?`eK%|Jhfs~PVr`}g>JfhmUgvgxuZ2U2ARm_ciTSSM zK522coI7yGNl6G#HP-e?yXJuL+wyx!i-L{R*YHbYb-7?>%lqTTNm`S`g{if7A41i| zpMAe75AE6ykA`Cg>MZbkL1?=z*&pAiws+jSl3kjW%k!^i7PbUb_wHpL4a0H6jOeiAE87(R~ZzZNdnrbe6mXXO_fk!U(T)Hh8el?qa99Q zzwIeLj zJ$*dN@2abIwaeRf?mrUGSlc^~z5^f7h@bC)t+Bh`KkIhxd1o3gPSaxP@=}a9XU6gA`rEq;) zpf&Fv9`xR0U@%Lm(OrlQ`@x)JK+i5ri=BN6gSJ>(Lu?-<)ANLhRnMmr-POmC!u2bd zp5)us?ws15scD{1ve1TT$0SvtXJ#$grR^OXSpT*3z@b_C`VF206{OzX1)8~ml$fCp z?eHT;_ss3ke6V~UTYXOPk$#6>-0)F;A14iMXn#rYp=nUN1`ud&!X6zw zvkabCh0mNL;AN*#vM$yiUhrjr>`Yhlq!~Z`4(0_>)vyI>ZYN>Bl|{GI%7M!^h>1WY zW1SRu6pp35>Dt%eM7zVi&2k?`71^Cja_)-#N6Q%!if89HB2miBr937@WAC>H(NyIE zr>8{Xd{=aeF85@*L5fMR2J>G%jif?r~=G$4=Ox9 z#VxGzC(|V+@n1FLoRGL`^fIWS`r3;eolr}Y<*k6Wn)^HidvOm7T;2T~VXyMDKH|C- z`x-iyDA(IcIZsi=iT7tob~gI(@sGSSG%GP`}rXbuOP}G9;9*TMXXIM zQR_dyr1f8_EX`6zx43h9qAtohVRKUFw$S1tS^?M^gjZU2cC3yoKlO~dskB`6<0q$U z-@yc#JjILLoekKZd7c6RENiKE$(PPvNl~Lj&b}~-^-=%TIb(Bd{9R42f4#z33TcRbg~*hvdNHK6Uh3OLE@1hl08>xl9*w zK0|2CLfD!&8G*b3W$1GRxIm7Jjd`PE;xS9xNDJ3Qu}rJ=un_&;Er{&vow`MTDCxWv zYKF|$QS@BvVYhv-_ROs+2z31%xuh(%(0I<6`|*d;ivGfDdt*wz`B1e)f8&tq?K!9> z)o9Lb(-F<(ju&}WyDPw$Mk%fLZpzc;j_D00c0~=G$|WT*aP=ujnsF>aDn_{FTOZPe zU{cX8QEA#@`qgob47v5+y5%mqe1}i#J-eokhf31vtl89aeJ!gZYgwdZDyWy99~k*?eEhLfs>N)IU5b>-y_hBH3SPM_+KBMl$D!z>*Dq0@jeJ5}H_GZnyXM@r? zaG_^MaDU}HklX~vNX^9{1rU?`m+YgG}zRD--n*Z>S1DK@UZGMn^{xp@s6cAItd51SosE)6%@ z$XpDgX|P;zwcrn*r4mfwmM&g644QM7C@&B}kd6{aySnSEi6xA{PcRuCtT>t0=)A*0 zqgAQ}NWZ`Ra@RAT9D7@5AUpAMnvBrqoefb_hE~x$*yOidPhDRV6=_CmxO0iu;MJH6 z%RPE?X26qXooN}03b1Tv8`p)l2_HJ9sC-;=X2o9w_rf8zX24=8 z;B~DXD+~x;kZmgD!MYtqbI!W)55yNJ^RAl{54anB%W|v#6GxU^2IC1*GN1o zcoKQwsL5wd5FtoDa!Go)I=?6SQOEDeG65RcgC@dQW}o{1nCG|ka8>3L3hwRKf|=#i zg53!AI)~VYQ3*C4$xpT+p*&FLr?0k<`=TKX7u|yr){P_Y?t`6Zo$1=6hupl} zCjD+OQObr6ed?{FJ~1%{K(I3+=vEloDW-@N)bN^r|C3Gbxdk?^lX_7-1#>6n6VkAx zeofut0_$dx9X52U)6E2Rw)-U{w`aVh*1iL0sqR{)P#c(-echij|rl&YvItc}sOU`~tbZ?zv` z&jA%Gw!`qFKzpGzes5RIUOm;7VQT6)=MSqWYMyyw89vBEKM+U*^_VqG21jixvngc$SZq8EGmg=rebGJg|O!(C5qoAIKa2sp+V=ve^jl z%e&Gez|f`iBHK{B9Gt>hXBlI}p9(GP16#}>(s2AIkfJ<6q20J)w{sWE-KCzGqn{TF z6yq%x!F|q==vGKPJw9}3yD#HlY<)lM>P_^H^6t?1*l#kdQK)P|i*5>x+y3pBuop7$ zX14x0RI)dRpHXW&P&aVZ-1iHT7x-&X;NWOe10j2WU8N*=u@J&h)(URu8Ke`WH#|nS zndZsokVjS~>P3+;$tzV4U5#Rgm>sy4lx(%kq$&#!prZPrTi4u2N!d6vEHp!N1OfEL+aDL9rgsw%u z9t0XVTrdF8b_sArCUYVuEE2kaBo2^#T7BYsqvHLN=VnId;O{smP+7mmXXE1Kpc~Is z<|j;BByBp2S4xjjKcvYd?$f~*(>yEqNdSQ~O)~+s(5mK|X!A0{Fxti}F;@S&;YR$r zBCdrj0`_fF2tAPUr`5bv`3 zK?zA7f%$m2cYM1iB%D3?_|io2;EZ%Ywg#n&;Xi=hs+cymZQ<(bYsdR98TY;WvUtG^ z7dE4>9f^4>J2aZo(7;aiDZNjbOlC2m{2s7lsDEv-vfT|ik|gN6ap!?UI3R#9-^fp5 zQQ%1yEowb-Gju!O++FSNUM`*Lo$?JrZ=>nhvwP)myM{d8eX$v8$mc}^ zQt}yPL_hLZo6_nSQ38xscwHR6;+`FKjEc|HTGG;Lsq2IO&e6ox92VM9dfPj%?oVe| znd-u10(ZUcCAl4}MXeFNVMKcUaX=Ab9{iE_CXNd|H&?^aa6TM7Hy05j~^y^+iH zc}qHYJgg6gb~70sF4d}Cn{guR^|ita^itB`KuGi8cCbGFvwSxeknY}(!QxrB8pJ>9 zApeM_$M3>shORW?wL7_9dq2_Sm9I5_9`*o{H32-I_$J>U(;Z1JzPzUDCiVUH{YT)u zEy|8jl~M0v>OmFHnHqN7K?#tzTb&H3GqqaM-%u}>r)#D<*@H&PJ-8s!q>gSRG54!f zBY2Ua>AY35$-1iEQYqw01#RQN6tQG8_c^;ps^%^eb{EfaT;0`B206CKG+#mcZp#M# zL$X&@qLDYRLO~~F^dv5oS4H!+{4Di=Rnx*~p8juUV(3X2Ta5s7E(& ze`4LFGMt}+Cj%*!A9niZ8&2y)XC^+8SoMX{Z%N%#b-YS2C-;>8bfkjCp=A$Liq`a? z8_$i+wHxo1r{im!B>O#5}b8Wh6G6dh4g}$WM8{Azg+}C{=HTqI6E7 z`^%o58lG~#^yD@TSD=r z2VJqWKPSwPv&4MoUA858+itw%%gvn5lAX5$Ma#L2yC7qy8VC*scD&i&o*#R)Z*>1{ zXu?P8HnGA60C-jb0HFK78k(H!4IGVJIsTU%rC+k5(*|q9f5?i12_Ne$M8LaU5u6U! z9tW%$t2|^p7Q%pbZQc@#Ga_X6>(k8K@<6G#dc>a9jvVRQ!{7c@lJi@t$nGsI%eB0F_TKTl8NJGIbys5BCSR9L7|kJ7P? zF+Jk2B=2=oEIo?%?{0a;Ii-unrBIVpa4Sg4e&H-kBChuK6}qiWT%?C9h9bxNfrla@ zszpEyOVl(HiKdaIPGxAQ5>A9sZ-i1Jw5V^1s!TK;sfrWvgk&Phkm}U>Z~H*ReN42A z^>BK8KHm>>52nBDJt+jV5|bwB0+kfBS|15v&<#_SCUU>kouB)oiBst z2E7l)T$KlF_TZ-^zdgM0w;dBr6-u%>P>#_9==QS zb>$)D$qAn%!J0wFZ$kdQxsIS0xv@H-@g+kAYAWHQ40b6aM`lvKA`P%qzR01BOul8l z2Ewx8wsK$WA1y#Y4zU`z)(eAtfMur~pEK-BFdxbqh)><~N$I)FvhgKFW&a9lLy_r0 zMimkWiPWKNc4w`T3-gqulEZ>2JYkC0M#+X(o&b-ITw~heG`$pqCs>R0px^@RGi!rmjEp6 zv_R+QMlK@7N6Z8C_NNnUp=4-Sznp?XOyka2`4q8BvVnQT!<*#HgXJLvMc zyc&qY-_n=r4N@haAS@iuE{`sUkJ-yA{uM%=P<@WV2-n0Lh+@OrdOl|(6$H#`KtS{Y z%&sY|UCQ_aA1Q?-|1YXV_&!({P+#BMAJC~@`-p?{903BETxXJ2a+EOow<~s>0W{)r z&hn37Z(1Kp5<8ebfh!MSM^qfVmC;1@B&>s z3Med^MaY~I_z(2)lJf|-hdDZVk-3vraLD zt&Vf6t@O5GFiYdRcQ9`9Y%kk@Sq805{+5;MA`LpfzvXWlUVQJ&g(5@oE+i!oNf9Z` z=hUvlmYk|sxF5HGxXF?_G(6c%Fqn>B4}o`5JtIch2kfI1?=UhYcKTs3O~|85YtdQxF7 zIldkgchTq6D({0XuLj1&E4#g3_d9Uo#7ueMGaIEU>f*Su0yQq&-KAh`Y+l#b(dznp zUGBOkJ2p^1*ArF7rwl^em(Kl(J$)cFEzC;5V-~>)QDKLseK%fPvTm zgA)r~Dtha+d%cS4leb3xQD$-G*?>^`OucCzwM@Lmtr&v{P(RC!!&H6GF!tSsNL<|f znfB}$96a?#-KG7D0n;cc*JPc#K8G}X>XYQYR!p zBroIFD+(U$_RQ_va@@?_+*};p?c7ov-JXMGb639t9v020QL1V5%h@+ z9-*(5F=i76HH=-Hbw5|aQ?`q7kgf3E)L8@X{ZZ-rfU%g^`n*81vo{Tnrj*#y zJYbVEH4ToabJcXbbq>KAr%=61sPP5N*fM5f6%+BpI?UL0BEi5M!@!^*YJp|<-&eyG zI?v%UJ@)Ru|MtXHPi_Nv?-i9 zOcINemDTqJz-E07U%sA`TRwotJ1e=y$i3B%e*v?p2G804i+n0j!)89LZWqnvIU6cq zFErlwoU923`4E-l6(2K18C4e}a8ge8L{REWpci>$#*K!;gB1-;8y@>zi?*cCl`{Va z?>suBz{sr33i}};I6f47{b@LsirrnG*?16v9;-j!((IAz@bmOVjQ4YOV*}?Kl3Wi6 zEdr~kA4nDY_#Iu#>T=Se=-r2%JQcWW7RIOC&*I2WCpJ$NxVY(0uO!WGIwrUkn-+@i ztRp?m_qpka+hijbk@vQhUnzEj?RKr zBbQ4dw3!YYzkCiLIJmkQelOrQrardV<#l)%k*ry;RhzAwF!XaMFozz@dEwdlk!D=Y zK}X-Un6w*ok{86>h|9GFA=W0*A3OC9F6`6Rj5SUN3p*zrn#QrSg{tNFKhjw@b3FbW zt2lN7f0jF%!D2YPUm7Wpc}6xEEhaCL1Dj_*7Ylgc*CS#?+0$b5(_+jW7sLCZ0@3*B zYw%hohPLPK`WD#8$qVe6qgdIViCwl|I-_3AjQiep zyp5a4aNA|@i(TO+pMstD{Y__@Zu95$8$X>D%T~j{d!Na27}a;@Xqfo3+&1sWQ}8_U zvG13_3F7I{_G69(9#@>4YmJ@ON^{9X4BE^ku)G#tpNrrO*voZ-0w;F1(LAP?wB;@d zfLdN)$qqPtrp)Jph0qx5LESt*P*X}_q!x;LQR|ds&M;Kexx^W0m{Mm6)^pYImUVyjQiiW_Lf+dA6~qAE%p zwQZNwoN~tgpqsZ;h)`3S{GnwQ@48+*hRV9fL}yzGqk?EzW%sf71laxqcGAwi8O>lNi{Tv<1UxC;I*WDV%IginlgHXWQyup6 zhx7XWB?Y0@1)}=kc>7xliY+w1VQ*M|S7h>6?3h(H%yrqXgU+^(?Atyp89bkEX79`# zukWr_vUD#NhP@1;2p?3k1#l(9uP^G)`ctOw)7%3*f6;@sJ9D!P&g4|xK0)&hH~7`$_B`SC zaBK*@lC#`Z;S7D<-&MG>o7wXh1I5$%>q?E5=xNc3HQ}RWv!XiFTg!_5Cv|()({bP! zi+LcV1ajQewR!?5!$VoA0WM|7s3Vr*lkvh2G&jrEh=#utxyps^HB#%gcw!l>VXfG7 zsp9sM@f^!b0{p20Wv<;h$X|=vAKER9mbLsmalO=_$*y(#VzlE+>6EXhtHpO#7E0G- z#I6m&Du^xzq*|Nik0u_b?$1fu=|$`YUZ&Pe-SKNyQQW-f^;zbg-Tw0~<=*yhu6vcC zNb`7z`Z)3{AJ$CsU(iB{N+idBV%*?`aanS~U>i!dTXaW?%8tue%_{>hcUqQX_UyDN z-}-*FEY*u1O(t9D8mi(KyuRf%e6L|F?=|bdGnn0&UuArg9~WVJt?lZi0$loAbcCP0 zIj)ThRn@*2jMI_coPST?;6dd2dkG&m&6;o62?kC^Q31}46lF0y@)z$_kSIprxxI@aD`Sex9u+CllP`3* zRSD8^pVtw8Be(_4D~yFftry5W0Mrnoo~r3lyWp%zdFYlg6fK?fEd2@wVZVgm zFLdUWl0_q88tSM%<2lyR&n5QOs++SpxDWGJ)`q@DO9<_oz9L1k*EGA4gSH(0(Ky>+ z`5WTE@T5WQxZ)V~kd=lzUjmV~!L;=yePmDkMW*X35C#pz>`A}n7Q0E@i~yn+;`_*T z&Nw}d#DsuRFa5gjkN4ERkijmuUQwUMw-0=G?urWOPl!Hir8fyuF8|s`0NHVC)N4kb z6Bq5`HclKDH##k4N9bp`ixi{?DL6O<)%K8>pCTvor&d|F;zOu5%L)gNh57W)kWQK} z$p*_IUl1pe_;&<75<*WA0~Q_HFDs4f$@>r#yyEv$@vA0F!QDL^XxQ&m3)$_gLYhgr z^OVy{jbECNxC(!vTyiYI)5-IckIr$nmBc$J$qomvp8zTykx3j?@CGLE=aYvM zP#3G&1G{B6)IAlcJdhJY`#Yb)d(gab1dEXxf$m7RDNInSLo$iTa8n0)3Yi_;QJ$np z)8)^jfN#X+*dYx(&`oDd&f^ArrZ4R-+;;Q)3a+RQDaRooCMPA1(79>=`FZMyT;77| zbY)xD$PCI${V3$Wurj#xR~BFh%v{Ln0=H5-(tdief98`1UQ zFNt0HW4<>zx(==wj62E@H598nCkE~ycX2Ut^CjHB^Z}4t1-4?AtsowWzse|~I>#fA z{)sMuw97Wg06jXG?eXGWz5rg7cm3ymv{E)P?Cgp$PR?hiHbBx_|tw z?Py3VaXEu>FioWx$*xvh`MEU_lP56bl=E#u1hTz%7)pRFh+zMeN?^iCVM>iKSICv) zr*lTlnCo4>0IWE8FJ1?N*zdmvms%BmBg}R9Skr*)#Wwvze6E9Y($^W46aJZF1#Lzs z7c%(s59iV;@Gt{N8kHd9iAl1#I?n`FD#68ZFUWlbhY=Lp0)1XnZF3N|M?`ZIYs*s@ zx+`kNk>P}e0A4!;A9Mgdu=&22XczlA$GshZUpbv1-CsW`tyc8hl;_3ieceA~h7@HCqI3CDK{i4UlkO{Mc&&|Q+_Imz)o0}Wk zdk8}3vfJVLc{@G571m3g7NkHUyP>8B{_dCx@fd$h6Dxj~Y_S0L?XBV~ncK+%QuTV@ z{~DXC2tos{=Lr#vTGaPm_5N{XAB`Gf(W5P`aXtKr;%F~!PFQVtL#?KBP87H$0?k!|zZNUpm##;dF(g%?E}e|>X=i8b6W(I$1ymRzO)vGS$#x@EeE^(M zA%cqlmp$N?84rf`dKp-;t7x1AZg`4v4~C!yJWW5h&NYcTA@S2g4clScn2U)91Ujb;-H;jqaQh<2sv&=oD2Ic3t0!x>D$;XBag?eKFh5fwt1&SPMd%W zVkV6GXyKQ}uW`KilrG(56MT~w>3C#{wGxB4x)1@qgmT4Wj`vH)(C-BC1xU*XbFqVc z^^dUL>cJEUw!=Q2JTkI<$Bm7=-9HbnmkVoih-=A~REK8$!Nm>Es@|Xn6sh)3O06_Y z`L_WX;(us!B1VByVDR>l*%f=c)dD{#TmQwP+RH0^ob!O7w$;G>A@s?mKG`LRRs{zy zpu}tS2RG*hbwb_Y$7-Wl46w)%#Db+oxqvy}qOrBdtJ(G`)T(NWQ@i1vuUg(5sc^$P zQ?^m-!TTi;B>j`C!|!p=6HpDxn8g zY}D3aAr80`0HCSkWW-OA5}Hc@xt6l}t+7R8r=#iA{Od8H#P%5C2XhI4Yk`gUI1;%H)NpG(h z1!*1cMuJcU+I%j|*=HxYL&IuzT~wW=s#@Oxs0+5rTB`tsSpVAudbbx^1{#-36rVq7!dcT+JctzNjY z1M{?~LbY>opqCv zYn^?^IMp1jT78@UF88QLySk_l;^R3q`AY(5C*cm7I zt4>k4L8Q-^a_78=W1sqM>rba{&T>t?Rg|8!5jWtn^d)dtak(rn9$Leg6Lc|8i?9fg z#$zu{-alv12&#MQ7UTIVV~+-=d*kt|e6VMd*Ay@~;#YCtFr-gSU@;``$^b8=t+Gq(hqT|IFB zBO!9Lm!KWKjy4ZkMifxJLrgGKIg-1x0O_L*dV_#{oE|r(99a|90P0V`qev*3Jw>z~ zh%7|P37iC-SaG*>hmO-_jVF~@DKwW4p@ zTWSS<)jX99fEveSg-)lA`8xz9lGyF<#2MG9G7;36XS!|g$r;z-q~gUf&SKTH0L5N1 z3nW@%?JL!^aK&83V@Y>JTXhxCVQ1U%ud!cXmps0yUN|82dQd?rMbZ>l2aQTT(O*#1c<%kMl zTB4!Zl|;YAY>y1nQnF5@x%^sQ67Vw>6Vr=h^I`+g7_hRVb)WktY04&N*~6u=PBN0L zQ}Y7U1Cg4WIs+AFg{0>K(yN!u#vQA9-yVsNFVZV`+=8z@zx*$wy^YA{9c9_h>r0t+ zJ+~LVrSFXxD-hksYecHSZlqOZETqr=zw*pj{kCivC=os~!+ecpDguNyJJ{>9*UQJT zAUYX?s@F~)_pn@d_Jcqtc%KMlOw&*uH&-zq8_p?_$xOa2&U6l5Enaxtz<}lq8DBOW z;~$t>@&(FANO$qU=&DWYoQI+DQ7ji&) z{L=W@N7OR4Z%LKw%L&w}1c*ENICLdJRhiK(H{sB3p=mJBc z%5fY`Dq<}zSZ3=ZA3%$7)zY;mE9dw3VGK<&*Xl76-aFdGtl%!1 zi(g9Wy0Z9)TJdr9yy)oDF@vXy9s0_K)#CL-H+rWFHNbyWCrwKIQEtraD<+gkvw?MK z(bTufjj|3&r0odWB?>L<_2sjNj0Rr$0eGhK%qhvozPFudClU)ys5DHNnLk=|9b|Yg zKHIYPx{LWT?y#3H_P!qM!J}Ub3i|s3T;gZHE5;|U4i5gCM`YM((;z63p|Do$UzP7k zc~76U%9|Gh-3YkR=4`##V8xa33TEbDM%%rYv6T@~BVg<%Y4pc-@rUPKMCH<^rAOQJ zVa?*VX~GT~(jNhm64Bzaaew2g3Ha+?%jOh6P-Thmseb+|C%TGN7*|;7U#kj8?QU_j zYGP86EedG0Sbx=PFplaaE+$>H%7xj~^XbCK`PJpbxIRFM&~bF5L%Qk%7JqU@p$|QX z#&va7X4rQvarZ$win}?jw0ElSWeY6~@!`4%xPUA)3sJOh0fR&ZnZmvezsDd++eEZi zKon0yKI$^)fh5e7anLS1RsP)a4fx+Z&1PFm_XaEg03PN4M@ZvuOVh&1=znQxHfsK; zZM3HTaD1YAN^^o2lZxNJ6rH64ebvXIp`F4oDZ!1_OW%_cYitD6I~{*rdDR$?INEdO zJZwKd>PxlnJhrL5a3*$tV6Ew(yxB75UYDQoWK?+9-{EkiPvJe>U6m4N&%1{yp~Xif z5Ry5u@bK}Gmb_i!Nv0b6Da4w3FyMbAL2?L%248I{o|H<95qzzK=U|U-Sc;D;!Ph*n;FRdsu@i5_1 zZb8hEGmATN$MoeeBz@*#t>V%FU(C?4q!%*8Q=(o2+9;l$t@@Ao&(_pD=%kl6yD_tu z{0pU*Z^7cjbl=nn_ozzVXsLIk&R zo*W7XkAX;9(5M3cc@m)T4N4$y1i!Zn1a_9?VA%9KL4`?2oWBc88G@_)w`j)M2I@f= zGziHRbdt34L3Jt<2f*v21FIyU#9$nO_Mo+}>`mcq{?Q8gK?>B0PkhkyZ7dS%_(~vV zOd0-q%Iz9`AcD;D<`32mT;%~ZF$0|>#c@q$%&c{!13NVo#qxn+HJ&t2f*eYrbtUcj;e-sJf=uJHN& zOw2ujI*Y7&IyL|7oxTrzukFN5|BbSY{KAWatC^AY5<=7ecwBhnLQzOQGu`^G)q7%h z>vzu0Hk=`rxi}76Q3-QOj@9 z`CY1CApo|hzolGj5>*DGKm@3>!U?KV@(*RD0h_U!;SC*jx8ir2=KLL?!R4qvX}x={ zPl9bpKdBwPOTVV3lsra2;vlx>Oki{c!hoo4$P*GT6gi4H_~w$g&)=7U_->HZ=ZZAqBXI=j0{bb z-W9W=!sX*hZehBe}y1%D|`Il-+3J{8hAmc*Uf@3 z!qqP621?A1{+icdbFlmGs-Pymalf800yY9J{k@KGu%RejM829*GhaYvE0YHm1b8+WyeUNef`?GGeJec6ZUKYLEST_ny~rNw*xPz_t^kdaDZT8 zNY#hpA%u0rL|z3J;8unsHEGl1E>T@YCG4pI`!>C>0k^^?uxAOSSl($@D|M1FuuJpl zMHOoC7Sw8BTG^1<1=9xjLBOp0;;)BqyPy5y$7Tx7*KXv4?Ny4nuwwK_EACNGn)#xPMQBYs(M$smvB){MXMKm^Q2DgTAXm~J@VMDs8 z1TA9ecS;eOGKl%`x>5rPqCZgiCxrh&KkR8^#A);8mkvD${V|TPRBt`0AC*IaqdX$v zPBc%KGf9_3Z+g{8b&q7DCXh?c3pH0C9w3ec&h`~nN~whbZG(i~$2VBkPE?-f4~8hA z6B^dZ_BVD&WS|i@6_^ZKwNg(;CljEaJ6AWEM5dS)3ApLrqz5KHPzw>a8k!ftS&jiiPB*5iLm`x8PNUBs z2<~P3tc0W+nA>I#`|cNO3?RKK2Up)%s6|rSD-{XAfuKSLo{ZB=x7G&o872nl;*8}> zg5t;g^B8SgJZ7W|Y;{Ts6}cr=N|>b*GL3Ez(6vEC7TC>C1*vqQXd=}3#X>jI~|WuF-%4>G{EmZ)j%My)>k9xEKZuUqm3 z9|>}Rp#_l;mo8u36H90q%H$38Cq?gNCy^gfEY%GpLl-Mtp&v5CojzEJ}&>0X-378MB!tj)Ra<`e1$_@Nha6CLrLhmukm}2x{VgNKhBuGIo6f zp~DEK;_p+AI@cBp^e2g{hX&}xzoWFz%NdM0;cyucfA%gRLP<~^YUmT7c`!l|6@QH| zLL?#t@g*`AYRlnypSRW3J32}ur~lJJ@>W8HY|E((B8wv|mn&;fZ%Wtj zg?Nj581}P3kUR`Uk+V40@VzU1RFX?04re~PBc46um~^k~o4^nG)nro*GiHF0RdnRPWsHmW3EaBgaN zS4CPat+bcAsw!4^YYzQJF65ZZm4~PvRZQrZ#WX-=sSKa5FKN_PQkpCkwj;Qx;#C~3 zf)NRFevPn^@ie5l88uJ1X7Y4log9p@DCTgro_YDWS}yAJ z@L-+K7;crf_~#vMu4!Du+3`>vZ@f~K1m}Gc$~koSFm~vanufh}3Gc#XvX4dB4Ezb$V#`MIJ+L{NtFyC4^NT5`c7{V$vriQZ#-)R!A z^e0po)z9fdvo+kBS^=7&?OW3vPWES4f#ztGHmIyV!2y4|=h0qgV?k8VH1KqGMcsIR z4EH6xqkp?|uGoBm`*|EJWJAW3kRTTEzE}B$0Y8b_ge3GVtcz`H)L|HDZ&n;lyVMzr zc2!JT@%L>VlQmY*+dU>qz>Ugxh4^Pd9pqNDuF$``RXLw@sp!mD6g-UF)-~os!lFi%k(BC$efCmIH%6W z3l)ArBXpZ&J=OKW)mS}Aum+Ie7T7o@#6w3CmNt8c)ei6YecI8NdbZ67g7iLk!Lp`6 zaq=Z3=GEcqQKv3T6Ixy1Dm5GDJe8hZsy7Nt7cHJU%3T5#FE&e9&7M0p)Gvwj@&G(I zqgUj^U5$o^v~J~%4=yK!m@l@3G<9pP75OD#@47Ldg0{3?;bX6^l8gis8r=a7Ou)uX zAGZ99a23w3wgnlx^A%-l;Y>hJ)(uCLcN!e-V|Y~ITEnllg<{C8mJJh`KxO=wXhG)|>N{`CSo zgzs4^q%RZ*%b3Co`w5ymvGs0}EkFB`QGJ9>SKzh0j2f2DRJG`SolcrLxmydFg*hC% z-|98P$_O=RcUz`z%l}xJKJ9wlAI%!GsFO%hF?cb1l`OfQ3m5%Z%!{~Oev(Nn^({dp zI;!+Ws*mmCTwYUhf%&qPwMdprA(`s@WmbCat87b&+0*8UHZbIbb~|DZr}KP*wSY7F zD5qNJ1L!%Ibfw?bbvfd~xUFti#D#fPo4NzRWxgEvspf_l2oQ-pfvw3>#;%SJRYO&+ zL<=kl{vXE9A-b2SS^Kg1k9}g>wr$(ClM~yv%@d#4w(aD^wsZ4-v-?f%yH>9n?A?>@ zLGS8%>iHG6{Uq0E7vFGA)gz}5!ZkN-`dND?Sh-sCF(M?{2Jwb=@ zuVujMtf%@L)KhsOw~JOfo6A=UUzxA+93CfaI1U#Nm8W$j#C(^dRyey0;cV9cm(j^K z7j0|Rw!0kcS`3$Kx5sIEwQYCwnb6IpJ{@c4#AMIYeg5B0s1WFub_Uaxw;eyfhW+}N zvc`(aG^g{If-kCBO(gjN=+o=CVFW%hW}i;Bnw3&l11-o>R|~DM*>#2$gg5ch^HHQu z#v1n0$K|H&%w_HcFZK-EBtpS2+Pgov8S3UoevhL*-u9kx{vpe}An2zM?C`#>0sS4QAN5({lbEi&n>a^;T`1W?<>xAt6XY$ zdj$TidAr(y_JAFd?vj^Owl5;z5MG!OCZCC$OY|MPTialJVqPxfzef&g*6o7<(zvbJ zXDb!A2UQbYF=adLe#{qd=TE@SE!`@B&$?zFsI6LN?#OqTHRnHs*^_5K1#ar!v@X8O z=tWKDQ@5SI;jm+fp^q$LOL>{#S(!6thM}TQlON(s1l26WcRt~6IyDOwh#{O%z1jj@ z<#Z}(99woNnFFl2U3m6m!1uM}U+y)txMz1q2TLxkk9g2cT03jA*f(+c6MVL12-q#t zE_zvd`g<0KH?G6?>o1vQa|d5-L-O_(JdP-gVcVUYy5E`Ra0+N~*7}JSba9Kf`SgrU z0|lC@%Q^8}fhMk=CaPtuz{DcNEraENey?V|TX?TDMU#g}x~^r{bi1yfBT0JKMOzUv zxNWU4Nfu9a3;W!H0gj7tiST) zD<7D0pR4kEvnknqD4Nh3>!B>b=<2k(z5@>%Ptj&)`&G+E!$rR%r=W-XEL-=pY4}ln zYoS$y`YZ~2;E5NWWC4TqAua5cV+4EYf@czA$l`pdMETR8ZBU;I&lhhc>_Y3g8O9`X z@2RfaY1237>c_3a8s0*uk>bL+ zy=xc8`~wKLPpzmHHWO!J*3(@cL=bgV^+{x3wya26O4?K#VQtuKwJ9@f4Pdix?ob6J zT{@87EyFX;<&31JHE6jvP*Jv?Y_*`OrF4H+9a(uVhy~u5zfr5vk#M+zv_J>26<_LR zVN{$+uH?$Kx7vC*Vv~U2y3MCaf4@&nc6)TP5f+b!NvT?enwz^5%pe@BJr;9vNqaBp znAwpPH8cf*#H}ABThcp}3 z&LH9Az)J2Is3x+TNI(C6)qNFKJ3;@X{lZ1))GLv!qM48zC!6gVuiGC_tUxzoVImBY z%*#%(sDI^!PRCp!ZUm6RIg1g6e40&*CC|=egaaTrVHJgDJ!!kB+ekAU5`&hUPJcgW z{DTp$(=%d`ZTm>CsbFMp#=om6$j+SKGw1S=7Ee3BiHTM4!Y}|)XB35{pV!->U^g#L z;ZHUnGgLhG?LYZ%z@)e&k>ylde(9hp zI!Fl*vV;ktFk!EJG5^CG!Rj)0B2jW+%>;m`Y`pgOu{<__eqvJ^zGt3GW2a%IgyK>}RJpCe+Q6<1H2WHx7OUFd;LE%p9if0s*UX{_;CF(G>gh;)|8#)qrfVJAHD z7iUCQ(n&}7N$ZuZ`k(y!+3-7DYp|$72t|E)9wxvwEJyeCWx5-o=rNp3<$+G98MJ4J z26a%)a%pD^3?TBr1KV0@CaMcI`jYu!Nt_F`VkI_#cW?Kvl*k+>1ctK?iQ_fQ=%b}J z#o`4^z>L7Ij{_p5H{IhEDG3v_%*3LlH>2Vc%D@W8>+%6@gHy0r?EpZ9>CSSXiB$uvb{wv2ntM} zEuiHiV>yQHH;qnpem8TeF?$u|5l*E)(9r$O7_#YUn7=yW~43j|CbXw;ZX zG}_*{T~tQF;EyI)2)IImagRWQZwrDTc;;o1D-;!yZCtkpoN&OXLwN0l(n=D{4WT!K&Czhr3fFmgMv=f>JUx7(+P@ajD1Ds9AQgweYnK0MJVN>BPBT-gh-p{_i%-8}?N zTUlPL{;&k}{k~8Jdxd(B>_844tB!(1;E<5NPwW)>z)KDxa^;_&h1C&I#N>-UPITE| z^7Emvk*G50hZi1nI25IhV+xyIo0l(qV&=^YQ#o?y_mLH6Eb#eH{?PRLUuNUIlKR{p zWE}EKuKXj=sy^g5UeorXUf%O7e??^d?%w0Cdqu?jMij=*IoC;Ivr-n?GHn>PjIc=N42JnS(plz+C0?hg-V;btj3^g-BX9V-8GtkLfpu7&_~%O>JL!TYQAj> zgFawr)N@=wIkN+kZN<1a${rZeO&eFBz+lTGbrV*o$htE0yJK$pcPa4V{Om$$=)&fX zrYXp&Sp%ZE&h6iEqX?w$VtW+`;vOA%;|AlwtpnX+ep^`cGppGvCThsXwkN=L`4-po zsPk~RNo_N|*A3^zZ=tKAWlZjyhSZOH`qFFZ}>Z7O5p+5K> zDeJ@Sr_6(aBbC|MS;oOsL}G8p1dR3^hEbU7FD+XzK)H#eB+HtXDCVNZ|B0F7yXsWb z2!SA_@;Q8rsn0KkJvKxkmD~F#y1mFta13RjFbUJx%};JOgENM&~JDvg)UvL`daB zRreG^UdI6bQKCZUo4Ff()4?@4X3E@$RgQsSh_Kog)HMI*x`|hIHbAkPR}>}?xofSW zLK6IdwO0w>=?1Ia7yjU3QRpMGJ&$FS zi-&63SY7GPifhD~wRgCTb>^Jsle!~*`(c+fDT}HV(|P@ON*Vi5oMmL;>&YEc^pnLa z%q$AfZe?@w59%D-9#b>MD=VaHATaX8#-?d0|M)|UlMEZKwn)&}0gpX;XE`0g(Bh@= zZOqxF-<=~Ppd#Eqi|l*rT)fj*Ioj&*84 z%h+6mJwwcZ2Ji?YK{G5!7NawBlMBe~8}2mnz!zl40|sax^tS9tU&fSHSQ>DIG*J>a zFi-=C-7ydbK^$Px+68rS@*bV+WMfSpY2b`wbE3zbj2mN(TmYHDno2myhIRANeH;D& zL<7z2fy?~(N>gOli83-oCCtr0&mQFLN9LQ*O*jXv6Ot#a6FwxY8_G^%8ja+5gI(z;i6YQB+T6xM_Ga3q4#mWj5p;=^wswc$q8R!QKn5ksO;iQ%^7f1rgQ z%61k1N~1&uQP9n3Kd%8KyPl#Tbfd{7+u6X4%B$ECM(Fjuc_MX={8DCxUxk9wutC10 zHvJJOK{6U=_i%NK34URaw>pvSt7xkiSXa(hL7YLi3_Q>bh{-^V8kC5hB$(K!yYa(s zv73QvK;RP8|4kvawnvp!aVh})*ZvPH32GAQ0kAPftV)f3-j9LA#IJ?=j)R+3h1JvkaQ$sU_gg^`%Ay_3@lDW+zxdaG;&|Gq8} z0D(Zf=?2N^{9T)a-%@aEe{wc8|ND(g-nXliwGD39SVh6@hG@2ad0bf;1L_7l5)LQH z_BdjcU)gKv%lScWxt60AFUdL9+@mwbHIOELOjH>)UbCdF_H zyxyA?x3$#=^i#%zd5xEU;MC~qV`?bwmBgh73Eu>5-qt$E#XRL-vK zdQ~rf#FC!^*U4epfjVT5fBf}d_K!w12Y9zhsHUE_Ma2H$fo0#oj9Uc6L~HG3)jw#=8*$6Y#u= zU%&t5dyBk7I9l>|^1Zy8Shz}Utk(`Ji^edo>q3{r^sksDt4XJ1i&V96}28# z7B;K4HOLGnYu7A)tV^JoAP zIxrr*Q~+^lm%(al)l4d^f9Fe(i}%gO6rHg4GyO$5MscbjQ<^o-D%OOBaebuV z=(_h*DaHJ-f8+uJlq(xa&`y)#fFx9zaTp3HA`%uk)H`{y?cq3`rjJP1bwYCBpP?iQ($7~ptiSXz46Ua|7D)3x$}nBQtWThzs7HL6di=*PkG zBRTH!AKefT1p8TDvEeINa27DkC^s=K{RUyAaqatIT~DkrPGJQlK#2ttiXK;k>^h~p z7%nF(xu%}rqPlG;q;O1OOpNGg(?yF%kAB;|{9xNaHWND)qpZlAgZMsLVQ~AWT&DeJx5f>%As0o4>iM{6>}9KPz9Z$1j2SuCJGdwrn5&dDp2i4ncjb zv=H-mhdNFDwP}yoZL5u=-SX^=zw?|gdFJ9h9BrlmLkl%h4My{u!YW;TYTVwv@_`V= zn9`JIgwAF0*;K5pPKzqKH{1o4ZzSP40s+}k8N`qcEm;X8U^rt)#b8hB{D8rTgm{|;$Ffx89#mc~^wt*@oos=e3REM%y+NxOgk*k%F z9?Jb{s{L6YcIx1rlsiwLcUwSh;tk3=uj8H>Qus7mB^LyAcm)?fa9mD_?le0&glw8m zYdgQ~9a z`du?|5~&U=1n;%gB1oPEoOmqyV0g^He$Dn0EV}ncj-OYie2{G_7Ov^c6;G}Rh5}2xoBqTZ(29w$8uYh1E z3*l=SJM@@*L!qBBJ3Qw|^?}FSDnbG}GvqYcz!^<&J%BAi8{4}d%%w{LYJVvNj5;4j zMP6e1cBr_WCK%eNV~vg%RhtJwZ2p3{8f;ep*5=aJG#?-`YzcLPe3<&K$sU)Dagf!F z7a$(f?L_hCMDvj}%I$pHhoKCHmkNp5liCdQj*GBs?m$B~xDTNBWW8kdL6Y-11)gih zP`BEpkTxQ$GB%B2GbQ{5=XpW~D{{11M&U6<0olH&LvW&K?VB&Z@z0-x_A#Csl#M(a zgxX<|;yv7@IgUg9J)G%!#~y-UF$lv~38r*uK2E|2P2c(2P@1vk_HXi3<_$jgbwl?9 z8dvz%60Gcgm8IHdG}YFyUcikbWV*Z`>4Q}KWrBL34Pqz2#CtR4*Tw){pbzQU&#K_h zYFrz@#CkLZNt?Jfcoo}$ba2^&ny@8Q8@ir#T`Ih$51p`OL<_o}bTPD0;@Ih624*8| z*5bON@PP9`K z6eu$mXga|lC5H>mPbW;mPQ)*_n2ZU^h+cT`C>}7Oco~et{gI%#xqltF-1bJSVCX?B zxj*Jl>km^&{-n8n@UqB+o9@}`VdUj4L$*Omn$y+=O&8GY!I%2MJpc2N_=exAnh@!g zpsQ7z5Rl`{n$E=h|CY#Im@`0Da1ZR#9%(v3Ush9yw|@7~GYYH@QvbLXqW*?l=j4Rm zWqcTG4)tpdkVbe$i4wa zP);Yj_hCM_S6!A*xoeMW=l-&vO5@5G+v5~nQTe8=;cz*~&gd2Gyze~c?QG3L9u(yy zf6@(!chJ1^M#i}*JiVh5T-Kdn?8$QXzp(4mqXtuw^-~VN_}G=;`a6e7RAy_py&h~L zC(<6PMFDYmM)RO1RiOcKdIrL&?!Pu$20c>+-2_?Q8ea{zGS@e0fAr@peh(6~wJCMI zj;6FYLF`SM)qYD>1WYi%Vvs1Io8}+XeOQUB^Vf4l?H^n%9j$C>U9FM){t!s|Iq%P} z{d(HJZVDY;xAyqv4B&Tl@z4-xWsx=h zfd|GT@jgC9aul2zJ$UdA-FkmWOmx)(EBZ4#)#gH0GZDRdk~5rAOmTX;D4m%P+C#05 z!cdTFdVf?JWV*J{NTh+9G9|iKTH_1@AIV!FS5^=Zoe*!r>(}CbGjkBM*33f-4h37( ziIkv^t_X7x=m}mI6G=2dU~8wRtBXY`^J~VK7!4yU(Y!G;ijiu#UJAwCFN`1Qo*o$u zTt1!OG>9a-p@=2d>v~@LX?21r;VM@?#^7+s7~zLgi@+^!Ee8Re5uG9kj9X?1jS}aS z6Ejc!dn{zSe?H2*FMY@ootPe)5l`>K$HnPoV0YvIOLtlbfy6Lbhv8;^DI9jXboXw2 z3;E<7Uxt$&T!UCZY;;d7yD{6@=?F&uOG&gaG| zfvIl*paex6pKMGpSbR)FAbJc0*SC{~jFg{@ngCIc&76Raua#sRKC;XGK+ukMkJg6g zJrD=ub~;2lB1794jSGX}+__`B;M+(4%f5|ab!Vc}pC|m_Au?tnB1RAlM+9Ose$7dy0)ui>9s9y{!s?rlg)UZc^-wk{|;`AMH1c+e+-Bu!m z@-V}Ctal0Kwjz3eZ3V`K+K(_fCLHuw(Zh4$+1hQNE2WXhWN9}rI zCACaYh<6tLO;-<91a1qgSIJx#SjjzE&#k>YUl)X}cGhfUv^a?&zgY{K;qyVjuHgg3 z$>`!}-qi0M^pMW_{C$C=wI8(fFU)T=F`t-D(0zy1151o8z8JTYcH>>M^{e3z z5w$}?e+8~#HV3WxL0G$z?xkLMHEfhlvzeNYO{eA%Z&BJ*^k0q2jn|jpYX2vQk2_Y6 z*I4PjU5xF0&9KxUcwoZa8~r0R%o;b)$CEeQPpI{5KRVaSw=Sr?P3_<=)?U|Ek6NbX zpr`nt5;#nJNC{1KKnE&CwBfZcbm9PL#{X@t_A@e z+0+qY!i=2V2BKBplgOmZ@hqe=u{eWKZ8CxqEr@DD)LGHeyVk{$=}C4WZBQs8)p=0k z<*&^6d=1@)AIKLto`qS0zsE@LH&Qs3bx%%szXb=Mva5}{L;D*fqnADJ$! zvFMY~ z(rKdnhP9~TPQPh}qFZ0s0o4J5^I)MT8Ag2t&m}jLhip3iBs)A->>n@_-FPFyuHvQO zll18XWl^-kOD`+C@pCtjGsCQ0-rr#EhB-0r+@h%6~S82`IdsSd-;q!+v#Qp0#uPdX9d;2kdsH%apHPe&<(Uy zNn%Jbpg;NPt^M_st%^pK3NX7J%D#V9(B39k`d0{YSs#E$u0xSL?b9RUqmFJD`W&tg zlX>AD{9Cj{-We9|Pe2LKUtl2J)Q3g0-~7K*n3h$DQ7j$KWvPTCjjO1k@he~&MovZB z;$s*UBtJa*N2i^)=4x8(&d6+_Z*u~`WVOTAK>evm+72J;2N$*U}9tscWPBf8k!b;7J4EZK>X9)V#hwiI=x-Vk^C z=e&uS)Q#r6E7>lcxn0d&UAh^rQ^s>`shY-xHo&EHh=1FzHSaTBr_6R#L|p-`UdO4| zkcJMzDasY?W(6u>slDgx0cdV%v5Ff_780U3YU-&V4pAKe(ld{O*%;kJ820hZ54oWr zzj9!N@mrVYl{H+mJ35o6H1~T+ZyQOKO~kT^wuje<)ru*(pMxv0X9kF-@TW?M8rl3= zr;`Jl$Xf*~&`?(Ys4NvvH$(oth_oj73%m3Jq&_L?54zzo-UOu|&}Z;m((!>04u$3b zfn*n5$op>_ReRx&6G*U)D z3IX$u#79M24MTd#)d;pMHl)*nI+#HT&Y=`GSb2P9`||J!{tkSt6-|r8P8zI;FvB4P zUZ8GzFOH1N!|?Fl^R+Y^Ws;(!rv2brBryt63KSg>HRr1aML%{r#itfv9%QGj|M3~j zpVJem_i{QQCkz5hUw@GFIgls!Ff8{NnY~S_e$bs6FdnG*@OIYo|G99M-!b*@06;)p zbU;9~|4rh}%E;uv@n4kNYqTugH`tc{!xdCf)#ffG1=>8YlG_~Alv^Mpm*dW{l>k$He|1~c;cZu6V;HJf50Pdk18CpJt~!|&XfVy z113q&OqiA;GwYQx3Rt2gY-^b6pEco1*UuDs!~ijMI6S& zS7DnR&7niNSq$=V$tAguPdA^8M-(^fYp zpu5aKs-3Pc6JSCDuscMnEMAP=+#lh8{9Rhusk<~ps;#mx_B|f;>-gc7@iC}EzT9oz zdiD3~{sX4&95jM#AwFz9ohGd+G|-gL@sd!3mF{?mj*t=aD%t9&bDM!H8SY?-L40oA zo;_83@13=qc0pBjbzjw*w}S=g`Qy0Babw+x^oIMc=4BzPz)`-VB{qAsYV(lO8GNdrPDtqV$?$2_=z=PQhrehE%F;;6Uz=b=t4VJQa$&l-I}g(2*!k}V@3fC znZ>L))cRme7`6RZw80HO$@_fem6qie#W$>F4V>bu5!;Fas`O~O^lUTB2i$J2M@688 zu(4)^T!A-@cKPq_%pJ81e;}yQvmdaGoU!ka?jVDmG`rVwoU#})&1gomeZf{RzYvq+mj}pFKpJ$IY$>c|G zWedk|=ss`d^Iy4uG`AEFTGD4#oxiF&J=Z6#b}kYRzzyI)_L>6psxK=RxOfF|yAf&R z{Cu8{9|tzZV;3`)bY<_m!HjBZw58rjkUia5-QMmk-{*c0?|mL#!NZbj)5C`rtzpCL zvoeP^EMGv@1cb|BUcf|l^N$S8Bo+inSNH=aOdo(ZTxvwL;(P5Mbe%J)wzPxzYLS38JA^Ah{w9+?U;W3pw`Tf$FDCc!1Md<=p`&k(X!sC7=hJ4q{ z8L0w2;dUPFs?`rpcSd{~-_1W8A}K=piEtx6k#XQePZ4z~W_nnhUpN+@``|kJ*4X@G z5G#-4pltdjgZa1JKRv9rB*}6xzPFMtY+15J)d}x|Yi0wm6|MtihVx{O1DI`U4|N6Y z&+P=UuHjz8=A)CTs=VJmAPG8~fhoVjIE}BO1y%N=OPJ+yZcCVRuV?Uc2q-ge?G2pW z1fF_`0wUun0Gt`V@0YKyuLk+1)~v%fn*{)M5GuB7YSzIaE}7Prt%*ZJylO7 z6Sd=vq8$Xua}bJesd8INsVg_|MyzG7{6h>~v@CXRz=e^Sc>Sg&yj#g zg1XBXKjvIDg#IG4uI$6~k8bju#kNg#65Tc`_F`e&ed>N? z*RTsoQ7C*p>%t)ep0IG7#uPhIPX6?YbQ|Pw)o~=qpFt(OEj_N%CXJ+j)=+N6KY6zr zg|BDUXSdg6746vmB&wa;IG$5{m~Gl`Ctqn)Z3~`L)^lyhS#fWwM6g{!efIv|Fh+0} z*-1&`V%jm6(rB+WL|0?#VehsK<_G+wl0#E`LZu3dn6u{Gt$E zjk6+{CC6K0XD4k z*qC!r3Q8E*J7fwI9ug>;Z~!3>oA~#O!Qg%t4#U8=*$ILE32qcu;m#inQV^8&-JwV; zASQ}MUD7ljWD|6QuAod`qea3I`Ma=9xZPa`#Jy7M^#O)K*fDUm4`^C!r^~+&ews~n zu2p$U^}9o*qDD>XPv0-d*#|iU$7K9?=MjrkRAXTg9Mg?rc9AQ(#7`nmLsj-URq7x5g8$wSLhUcak6A_er_73d<^wO=K-+b@XAwS(_on|g~ zDo*`}og5 z0+QI2q5*GpM`5-b{#RpMZ)=0&xBkP+zCgn!Ac)PgKk06yYjI~kkE=<0KbNnjem^IF z@>taOvyzwjd^CSTTGIEcol&iMoGu1-&&zT=lTK&(sfYT7uW>b$uU3??GZ;?ZB;X(H zJ?ay|=A`Gi3zjM31l+NiV=!6Bc7-ostHur0ta&N0Xx1Df zy2BrL$c@W;hbM>siU1ks6Xq=5Jy1`)v$vRV?Qk;c&f)yC&3Wfd9{aH!Ak2HZeHuQC z^!rKTKLP3|xE=lt&Lg7R*xXi2D`#QFM;LjDqhKUL^T>eSFffbg$J`K>JsImDpC zmFuLJk}8 z5)^`$G291;6?)r?o$uxX{uAg3O83;yqPSaJJ&s>I>(3zBQC4TA7<3g@;zWCAGlFVo z`yXzM0C!AQUE%X~=fmN+^%w`G$HgSkdxFi%eDCo9022SrByqZ7)p;SJFxdBE8Y-uk z0`m=KCgCIM>wrUkx3Q^F_wxzvNxbWj#oZ1oT;74RxzCqfMNhsWfDiwaoz~Ev1GA4a zSuDELF*(?QkP?rx4imus(3!5FUK&83m{4TdM(;2#N)?jUnq8WyHoPg%aZd~wfNm{bOM5y2Z_59XGn=uHM; z+KnfB&@etp)y=^c^~MO~(d$Y_Dd$UzAl*uk@Uc5pgn<(a1rwswLw%UpM?_aZDe;%$ zF3iq)(L4~v)eH3JVX!*+_A!F?@!U$l(31@Vi||Tm90K+`IumfjYab%yOW*=YOxe%{ zNOqZJTaT3jvwV72OA5mGDgGt54x8i3z$ha-Q7Xg5{%s`13{XZsBW2CI_?6o#XS1G_($J}elHl^OttgY!$L4)qmZLwsRzFkPw;F49L36nL(# zNe={HT4|4YPmv5I39%N|kjyT7kk9?+{Xp=U6`Tv-HLy6KSo)$fOmesrVrMsykrNY9 zln2C*2L~Lm*vbe?i5{ZR2ckN*m6#@%F&Tl~1sky6RQo~0f*@9o6wwXK=0cy{Lbasr zvPAYNlFjrBynxN~-|*6H4I@GWgAz&P36%1YmTo8higgs=-9hw0x8G0o(rEvE_)b_% zUpo1M!IZg&L^SRxSoHbN1)Av)A7gB2oR4B&PJlwboiW zNQb?WE=Qzaf0>Ml=mp_9jam(}$ofc;9Lz_QSRqD6iJ9@ihwbZRfdj>0!CC)R$Rwf6 z4$bjz79o@CiRgqBV1*SKz3u}=d<1D1FT@XJiOupmoCi4sIhjgQIC$zQ?AMQIqqGY2*f%B{ zjRmhuS!}`rCGjIrNq`|>5UTPOa@cr5OKYT)1W1sCcAGdcJr02BBnfSgfw90E?J zn%u3F1O|X|HdV%ZIikR-4<<@aLJg)%+dV-rN(3r+%%U*Lbq@FBBK-zI7m$*OyX)N- zO`qpLr+nyAs1#v+jfcS(uy@h~v7aA>4?a%d0N~#X0Tn6G#y-Whi(`dU=r`pOVkd)* z2+Rr28p>l5MGAk?VCBPPLKU~lg8;VqFu0@=m%Lhi z+Y@);GqB8acO3Xa9?KrIoNNm|;%B-mY_@O)ZQ)H`8M^)$$;+`!u6{WoMsP#fxM*%( z?%E=nbH7+6ZWmfX%6e0*3(6ZO4^1MdJux%{#SDj`BXdiv3il%1VZqXFyE@c{+2iRj zA8E0i=W8H#ah03mTGdwuDe~H!86-Nkh!!G%JjRy=ag?%ZW}og#BdT+G7_nI@76;+; zE}rCvIQkETBd|R%6a;|}F?C+q!09#f;PQPK26x-YG*E9 z;d1mdMk{nq-M&t{=_c1qo1yuv->K!j!-;RS%R4mD>j+vTn@O zl^j*HS2>y5d^#^KoPaUAIYmDf8~P3Tzs27Yx}XCW3Lqern*X}pla+(*|ImInwa?XX zMjF0&y&_v^OrXWwk@~?#n2^G3jh*3cO_8;|Sr&v)W@w#(DP!-|j=`ssa{g4B7tal` z@ex{Ix@sUuENm?;sp|WxZY{L=$+IL<*udHTA?&h79-XD!#0dM%0DoEKNTcQL-KEvB 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 z zFzs2gnwnta%ih$E2?dwu?P}%rbYo=98Plxn==9{W6uvWF>TPKm*~yN>f)ieW?9%Jz z4N>*mpWArDWFAj>Xi2RpC+_^})8Db*vO zx|S`8unhK3mGjY)>o!VCm@DJP`b@SfLP9;j2U*D(peO{7pRFDF_w5{>pCzq6r!(+< zr9{Dp>vB~c7NWH<^Da`$CjSjS#4-|!xiU?LXe))yGw@HILQsRBGcQXN z=@PfOzo)7j)qL2$G+cxTVoz%Jdc)c#zDrS;$^ll#D8o_rfJ@7FP-2P(0=Ld{sK)&I zUD4MJP5%OyZ7#ItoapNp1o1ikhBJi(xK^oI@E~S0pldq*Q}u?`==OS01{xm}3O1wT33t{OCMQ%%URo+3*O0%2`N=<5 z5Xs8}86W@wBdCu6l!%blIVY+BLE4M`P(s5z_BRABb8vC4Hs-TWkT7!46WhysNWaSP zz%@`6H;k|QA$^Xl>(0Z}apW_9p0S2EVU?r^>==s&4rgzbb6iuIW_4a?^NR z$-~(xfE)m7YWH~6!p6onPi2*-0feG^tJ@=c;nAHV#3M{6A1W)p<#|O2A!7G#Z=TEl zAw95@hTIx7P7Jllt@*l179Mk9%Q|e+6)Nrk^M0#&<&Qg~S~ zSsy*1_NX~Z_$)-tKDraedhDNWf`F=CJm5Ho2dcbmh zP(x;Le*R@s=56(Gf7KRxYA5DhwXV(c5g^j^Uyi1FRE6zVif11%JTkbaMR<^**KXoM zTxyB7(N;6pd|cy3a1|U&=+d)V!w1>6vU>zzFooWYkF9wE_wn4SZiHiq4{l_fUBt-H z-A14)lUUNL0Au3+^U8@{7CzJ`dK5K=keqYc$<~sMNj+f&>vgwU_F_+?Q}c4|z4{SO z*|S~vDQqKOy5ds@SJg*S?lRQ59>|EmoBM7+vp6K#7>b-L8mGnAY8CO;+!bU}=%bYy zHIFr2K>*ahkevUXZmkHea%p zT3-p(UZdMI#9NAhG9h*|dCb+BukN@;)0Ur}7F_-DjrdA66%T$mE*6*pIE6^le901n zp)-K)>v?HiZT*VB%BO1U`q;_> zPLdTO8c83)-`+HUa)x<#?X0mpqAr0%A5jn5Afuh;nwhV$(#*eL0{qI=7X>VHp2XQi zoIp4`r-vh_ zCIQ7*NL7inWRVU+*!+-m2fx!YsKrQ^a(yCHm)9)&;)*PJUw_pKyl~FLXPUwLa3)y< z-l{X$1w?au@gyyo=`ihscMq2+O_TI=)xs-DV5} zY%m8$FT#v|5e3A+2$-o0S}b@_ecKnJ=d=#mfM-U6!|&CwwAUqvweJr7?tUf)!mGgT zUuh$Yu)32yaOofD0(8M@{hMf zDW@O)_drZs837PP=%)Y@!1-Oej4c{Zlia;j`U;@?Xn%wk%ZqPdks1mlvzqJb|CBUo z$4nT9V(u*I|)4UGuB*xRK+9R`pD|B z&bidjg49tz>qn}Kh|EmhWuklJ3-!_UFvolQzP@%4h2DP4g*WVe84f)S2@peeA>=P9*nG3onZ~L$5_1&$d4p-m!DzIqF*Q0tE8VVd}tgC&m2wbuZ3&DaX?_S62O_Q1DEBsCeB44OCIYE&Gv4HTDcsSzl}1S_*c^tG2NksAS~ z%h0GCJ<5})s;;5NUHT7%RsrRYRb;A5+65s>Ykr*dCQ+m&n127bBQ;D5+V(=kn8mz-dSCAfk-kxLBj`WXg19H5IN)oSrr#93%=O%MTb0#bBQescF$2*bbpl9ti_y8Cw|5E4L? z>5M?0A>e5QjF3en(-5akU_FHGRDk6k%#|t+=7tlw6Rd>l9Cc)95y@xyGEOz$y$su< zeowlGU+0k^-OCq|!oCJCPlt5xeb~DDWLT!Q(=%~|(nq%F`#SX&=w_&$Wazth^$&<< ziR8{x^c}k5bXqmYwmrP9Ry@Wp;2c|6IJ`q84fwLOVD&@iu%`)m2Bd0`buKNd?H%OU zI!bc#_c^k-;2m-cQXzi#xX5$*_FQd0m#B83Q?Xe@SQ}{Ew-8f@DtAHxF-PluCCjSsw?XWbX;5~T~Th4Gk%2vE| z(8GKXOAy>0k3sNPg+@#rH9_&+Tc%v`604t@0$4AfdL3^~CGd?H2!SbC@!hd!u4K4% zTCi+9TnG)#vy!9=JDuO+aqNNsa?c=1q#K#I!ybXFIELpjq~KC;sAX!I1CZDQqD;`O zO4TzA&)}ro)H4h$j=}eD71QU;ivzIzCvxdMK2Zc6OI61IXk9(}#}tov7-H~=+ox?f zoI=6To`EV-Qn9m;C?UtGmp%?vGI_e+=ooqG)0FBiI*HvJ4pZ6YK;m%*w-N|kB^W!h zK^Q}C6ZGym(L~2KCpJi;djPi+AVFa611kk0NoQpeCj@in#G92Lk{%3`M!HKXXcvSd ziNMP(oH1Krl$XT z_8%A@goV>3xKw;&ks|si_SvdC5S|i58^U#2k(v%q+FQ*Csal=Aa|&n5_~rF`D>1rB z#2qy#B|Zk!jSk@9w%fFKWu!D;mBUfvPMr)%5}=&Z+JlfjM!aFaNnGLQ?%;pJ1Wy$ z#i@kFaNlX?0%(#|4^5$btUj^U*mfp4!za2gE7v?TCFar@X3+SMuhg47@DHfv4QOuJ zhgHt38qUt`vENopKDDXDYx~N`W?cmvJ2b(|s=>3;+K&c}r0uK89=4&j4UPY3$_1$W zvQp`GewuTIP%0xS1s;1KvGq#@PHvo84~qRPyUsCfmEcNYI~K3vGW?(Gqr8b&r?r@0 zl3mzWi>kTCpn#9CWF;zjg(WbJ@l*d%{bYa>kGln=0>5gk1t`+*NqOy;i+o|oO&P5k zOA3nh5aaq6BM3_hEY%&ZN*{Gg%f{u)W|4_pU!y^fb-7T%AQ(TfN85vCNJUSlBRb70I0pmugv&pqOMv zGGn8HEMq0s;>D{NN|z5hx$+-$_0OM#sNC`4%%`Sxa($C$`2qdT+)ym1%i@sFLktiztcft9 z=cEOBbK|_2*A|#yfRGeBzh^~M9 zmDTq9>+j$(GcLK6xlT4EfUZ;k%9r~>pl`byM}(3mwwpR$otTa!z_K3&Qrw({u_Qpx{@5O_yIxWl?mFG0BJKkg5L$F> zu^lNvnA@~uqVwkkPn;a&Yzb)zM#ig}*AmW9eLQ0S>srT-Zh3qx?ht;~%604c>3dLl&#Yyto-=#E zhk5CSbtJ~}UsI*wl&eFLk#bI-pA4LcvJp@3FBZaA5|(qoE2cuzNN-Qt>}rh$1%NIp zVO;3;|DwQ4QxhZ8r8kGYGeny;Y>=*Q80aSXrpV!8IiBMv&5F0Bu00`wENfIwUHt`U z%|>CQ|J7gF5|vmlIo4Q4V&ooz9U8Z8td+ob*?O^)K~_%zJud^wH%rf;VxwNisoWoe z5<+91R{>uZC|xxd$Nl!x;^%goIrdS!U~%Kqt@DmtxbH7-l3LL)zKKps5@=#s&Tk4v z&SI6npaLc}*ccj&;bc&IpgT7>DM(mtNs*}iG+EHe{^o5n^G_hXB1L62v3~wJA!fv%vR(6x^PTcv(zgWzZVi;~UbXAypH79(XRsj?rj^&0}@kkFnq{ zq*~GLO+AcdqvU6|Urb@wXhK`J-~X)Xihl{WvT2{wcUz1yR4FA5_v5s8vM?Yu&eX!@ z;5vvO!4bLFE^SR2q(Mh#s>vwbnpKgdPRK?RfJ3^xrsj>vj4b>E<24^O7hu>;awm}W% z32KP_OQlHJbQ=ysE14oiSKO9`d_Vl_$tve)AVMa|B7h+SEt}VYmU#L7>&2G%fC=!~ zC#GD?lpE6Ck{-U@mrf8aPLqRqg3!UslfYdlC}h9WnqlSY_=PQ;RsyyY2_;)JsW#yI zqOZiNu8cQ8NuJDxy6uq}@$T_@x?2^x(6an`@8;~6{6)#Hsy-_F9V0hV%wO)L(pXuN z!a!@VC9JE4(yYJ+Vt%WI_A;a|PU-qCI-Tuxt1+r%cdxLU1TLVzP-@v%18j#=WTr5z zLh8J7W^r9@S{?cq1IKO;SFdoRe8`bB?eY&ql(HniOrkmV0UVS+~aaT#cxs zy<$0}pFfmP-y@)8~u)naWenWLmkS<BmWq|~na z=k8zu-md5C^>O?AFn7lr_QtPXkGFGsM%LHY7wUQ7;sdZR6(0Bf_8tGf=VunUW6KyA z0067v001=qOXiu8g_Xv@(Z-ee{{hnsa#?6?3@_&%=`qyd8iErtCv*yI2_hvtrcle} zQ~LC}h|NR%`AZ{`pg~L8^TlH(ni-Q1ng23{Jn3#a-970TI!s*8A-6BHk!y3mh8f|G zvxs%*fuS?}eMUkWTK&QblkGaT7o6yZn2U>ZnfT)H`j?AxExR<4UY5BY8{|+8M0~V{ zd+!d@tw|G@{^|oRmvoc#A$`IqK{X!4F}$(1AxEaNg+=fi;>38Ic8pqjjC;?YEc+Gm z?$aOHckh;h^gEh;j~U9F)rp^PHGxQoK z_!&7_y5Grn*eJQx3GFa+)Fx>oY)acXMDNGl@AZ1=Iy1;yS5O;HN!!m=l3(Zq8PCZP z@_btP3b-q^H@utZ$Q zIW&4q?dC-S$_R2)NY;o|DrAHwdK+-2??R_=fz%a&Ggm$a&h3PNtit_eh0QEQblX43 z(Ak`2j0{F5gb7GUFB;m=sTKzdByJRTh9VY?MUDYM@)%V;Hsee&|wp7%&Kf7tDlIKil8V|NJ-$hZGKYqK9uC z6=EPQ4rJvg9h?GqskoZZF&lCeGtWdp@i7)g175ndihf0G^$*$--+<3Nd5 zst;TEI$X(D!1W_AKK?GMjv!RtED$d25=vIrkt?S`-Cl@kVuTRPqO-5}6H-xFS)o^P z@lh1XVdTX-ELh=O?(2sUv0CNY{Dooo1IX`BTOls})Yd01|MZ>`Hdugw5@YK{`{C7g zM~gTS0tg5^mWLYYLFr)@sqwf55Zqw_y4h<0ZcZl58cSn;TAtT{w={PO3hiM~SZ*L| zKjtb-ml!cP6IvSs7pf&+Z8$biSuQQH)POu`{Ive5gdpepl{;X}?F5=Vmk_x>CM96Z z!KHXRyYSuSHiD#?fPJ}PLe8#s(tI)z0~gBSx}Y1Qe3^-9o+4K-op^Jz z({8S8IU&P9`at}H+&;B z2KKE9cW7^L?n%wa0e)ClM!gUao9I@>h`ImY^;#5A&rDu2ReKyi_M+?zpbt_|^0E<$ zB3AR8au%eAl1pT238#^ir45Wig6Vv@Y?cE!N9}K_u}spUv11shKAziR`E=0-S-8TLU=p*ZbU}rG zQ%cVbsjj~1s+uD;2HJZ(NWgcSp?N!L24{*!;{SL*p3&9%Y3a>GGbr5oNje$f;C>WJ z1Dgvd_v*>~FkF3uYL2ECG5Vq@oCY2x$VAi_D+d&5LQSIwK%4O&gFu6lesZ7=%#hPm zd!Ac#6j1L;qw1U$cRxucQAcSMSQ>}2Sxn~>PR`HLann~a#Uy?HGe%0i&vk5)I>qm` z3I^X2NBOrPjN%kmIt}tA1~N4jui;7~WJ(V>{oQD=b6*D_)pN^6$+{a$(&j&vT-}`EE;s-$hNvgeUGPv z%CCr0vscHCc3EIn{iLNexwEBZ3JjyfZtWVtk(ohdzHn4}cv z-?dN{h58M&Kkjwx0g|z?*DdTebd|itkQJ=M%9(PSwTVl#L>^c?RQ^>p5c*e0EtM1sdCrg_d@LH@i9U)7{pxLW>5mP(pvBMa7nH}tj2AQc=X^E?M z3krDQY&!4DEvRqh%p^-gyR=xYxTAGMdTOJ2nK}jZmgqbeFEy6^1sAT_+s(M}nBRJ@ zTUjqq5RUT}T%u!Pjj{v8D4!4v_0x2B^wF5pWwPPiq##;qUNDfE%jVd)nqv_{P3C<^ zj>Ag}xp-C>pu=+v9%46ytbMkQSfA|IdtGt6COl`IPkW!uXQ&8TS!z3g!4aKij#X=R zLQ1atgjdd>9NP!V4p0z6C%{7&L@;TV8{W~3Mk9?bVEESNFVb

^Ds~8|IjO&M~HY5iFTJL-!t~ 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

j-B5?3SSm){n1 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%0ALIGTSE$(V4tu;fTq$Bu;DqB|=HZB+6C{M} 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⪻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%0ABLojlHfrmQ7Pmx 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